From 6a136863d2cb3c65508e7044822237dcdfdcb037 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 21 Sep 2022 11:27:10 +0000 Subject: [PATCH 0001/1483] setup_rts: fix the loading of projects installed in the toolchain prefix Trying to resolve the project file name with GPR2.Project.Create is wrong as this only looks up directories listed in the GPR_PROJECT_PATH environment variable: loading projects is also supposed to use the target information to look up projects in the toolchain installation prefix. As a consequence, "gnatcov instrument" fails to load the setup configuration when it is supposed to load gnatcov_rts.gpr as installed by "gnatcov setup" (no --prefix): GPR2 then tries to load gnatcov_rts.gpr in the current directory, which fails. Directly create a GPR2.Path_Name object instead with no resolution, and let project loading do the resolution. Note that our testing infrastructure does not allow us to install projects in the toolchain prefix, so it is unfortunately not possible to add an automatic regression test for this. TN: V921-005 Change-Id: I1e720177fded95c004fcbaff9bcc5fae23ea8a14 --- tools/gnatcov/setup_rts.adb | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 49d53c72d..b03ad8a4b 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -816,9 +816,25 @@ package body Setup_RTS is Result : Setup_Config := Default_Setup_Config; Setup_Config_File : Virtual_File; + Prj_Ext : constant String := ".gpr"; + Prj_Filename : constant String := + (if not Has_Suffix (Runtime_Project, Prj_Ext) + and then Exists (Runtime_Project & Prj_Ext) + then Runtime_Project & Prj_Ext + else Runtime_Project); + -- Name of the runtime project file to load it with GPR2. + -- + -- TODO??? (V921-006) While the call to Prj.Load below is responsible + -- for resolving GPR file base names to full names, it is not able to + -- append the ".gpr" extension when missing, whereas command-line tools + -- are supposed to accept this case. Add ".gpr" ourselves when needed + -- for now, and remove this special case when GPR2 is able to do it + Prj : GPR2.Project.Tree.Object; Project_File : Virtual_File; + -- Name of the runtime project file after it has been loaded + -- (i.e. resolved file name). begin -- Load the runtime project file, only to locate the prefix where it has -- been installed: do not print any error message, and if the project @@ -826,9 +842,9 @@ package body Setup_RTS is begin Prj.Load - (Filename => GPR2.Project.Create - (GPR2.Filename_Type (Runtime_Project), - GPR2.Project.Default_Search_Paths (True)), + (Filename => GPR2.Path_Name.Create_File + (GPR2.Filename_Type (Prj_Filename), + GPR2.Path_Name.No_Resolution), Context => GPR2.Context.Empty, Config => Create_Config (Target, RTS, Config_File, Runtime_Project)); From 278c41f480f1d08a951c3d8b878c66bbf4eb03ec Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Sep 2022 08:53:02 +0000 Subject: [PATCH 0002/1483] clang-extensions.adb: minor reordering Try to keep the order of subprograms consistent between the package spec and its body. Change-Id: I67e30f01fa0a4b023e0bcae816a3bffd47868f6a TN: V916-015 --- tools/gnatcov/clang-extensions.adb | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index 9e5b96687..0e7b7d9fd 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -96,6 +96,26 @@ package body Clang.Extensions is return Is_Macro_Location_C (Loc) /= 0; end Is_Macro_Location; + ---------------------------- + -- Is_Macro_Arg_Expansion -- + ---------------------------- + + function Is_Macro_Arg_Expansion + (Loc : Source_Location_T; + Start_Loc : access Source_Location_T := null; + TU : Translation_Unit_T) return Boolean + is + function Is_Macro_Arg_Expansion + (Loc : Source_Location_T; + Start_Loc : access Source_Location_T; + TU : Translation_Unit_T) return unsigned + with + Import, Convention => C, + External_Name => "clang_isMacroArgExpansion"; + begin + return Is_Macro_Arg_Expansion (Loc, Start_Loc, TU) /= 0; + end Is_Macro_Arg_Expansion; + ---------------------------------------------- -- Get_Immediate_Macro_Name_For_Diagnostics -- ---------------------------------------------- @@ -120,24 +140,4 @@ package body Clang.Extensions is return Macro_Name; end Get_Immediate_Macro_Name_For_Diagnostics; - ---------------------------- - -- Is_Macro_Arg_Expansion -- - ---------------------------- - - function Is_Macro_Arg_Expansion - (Loc : Source_Location_T; - Start_Loc : access Source_Location_T := null; - TU : Translation_Unit_T) return Boolean - is - function Is_Macro_Arg_Expansion - (Loc : Source_Location_T; - Start_Loc : access Source_Location_T; - TU : Translation_Unit_T) return unsigned - with - Import, Convention => C, - External_Name => "clang_isMacroArgExpansion"; - begin - return Is_Macro_Arg_Expansion (Loc, Start_Loc, TU) /= 0; - end Is_Macro_Arg_Expansion; - end Clang.Extensions; From c0f56d1a2e4341d1c03fdee2f2c019625b2b44ee Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Sep 2022 10:21:37 +0000 Subject: [PATCH 0003/1483] Introduce wrapper to avoid access types in instrument-c.adb Using 'Access or 'Address should be avoided when used to implement OUT parameters. Create subprograms that wrap thin C bindings to avoid this, and refactor instrument-c.adb accordingly. Change-Id: I40ca1268e18e7099bce6604ff94128a559582fec TN: V916-015 --- tools/gnatcov/clang-extensions.adb | 69 ++++++++++++++- tools/gnatcov/clang-extensions.ads | 17 +++- tools/gnatcov/instrument-c.adb | 120 ++++++--------------------- tools/gnatcov/instrument-c_utils.adb | 27 +----- 4 files changed, 113 insertions(+), 120 deletions(-) diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index 0e7b7d9fd..ad3c3c2f2 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -22,8 +22,23 @@ with Clang.CX_String; use Clang.CX_String; +with Files_Table; use Files_Table; + package body Clang.Extensions is + function To_Sloc (Line, Column : unsigned) return Local_Source_Location is + ((Natural (Line), Natural (Column))); + -- Convert a Clang local source location to gnatcov's own format + + function To_Sloc + (File : File_T; Line, Column : unsigned) return Source_Location + is + ((Source_File => Get_Index_From_Generic_Name + (Name => Get_File_Name (File), + Kind => Source_File), + L => To_Sloc (Line, Column))); + -- Convert a Clang source location to gnatcov's own format + -------------------- -- Get_Opcode_Str -- -------------------- @@ -82,6 +97,50 @@ package body Clang.Extensions is CX_Rewriter_Insert_Text_After_Token_C (Rew, Loc, Insert & ASCII.NUL); end CX_Rewriter_Insert_Text_After_Token; + ----------------------- + -- Spelling_Location -- + ----------------------- + + function Spelling_Location (Loc : Source_Location_T) return Source_Location + is + File : File_T; + Line, Column, Offset : aliased unsigned; + begin + Get_Spelling_Location + (Loc, File'Address, Line'Access, Column'Access, Offset'Access); + + return To_Sloc (File, Line, Column); + end Spelling_Location; + + ------------------- + -- File_Location -- + ------------------- + + function File_Location + (Loc : Source_Location_T) return Local_Source_Location + is + File : File_T; + Line, Column, Offset : aliased unsigned; + begin + Get_File_Location + (Loc, File'Address, Line'Access, Column'Access, Offset'Access); + return To_Sloc (Line, Column); + end File_Location; + + ----------------------- + -- Presumed_Location -- + ----------------------- + + function Presumed_Location + (Loc : Source_Location_T) return Local_Source_Location + is + Filename : aliased String_T; + Line, Column : aliased unsigned; + begin + Get_Presumed_Location (Loc, Filename'Access, Line'Access, Column'Access); + return To_Sloc (Line, Column); + end Presumed_Location; + ----------------------- -- Is_Macro_Location -- ----------------------- @@ -102,7 +161,7 @@ package body Clang.Extensions is function Is_Macro_Arg_Expansion (Loc : Source_Location_T; - Start_Loc : access Source_Location_T := null; + Start_Loc : out Source_Location_T; TU : Translation_Unit_T) return Boolean is function Is_Macro_Arg_Expansion @@ -112,8 +171,14 @@ package body Clang.Extensions is with Import, Convention => C, External_Name => "clang_isMacroArgExpansion"; + + C_Start_Loc : aliased Source_Location_T; begin - return Is_Macro_Arg_Expansion (Loc, Start_Loc, TU) /= 0; + return Result : constant Boolean := + Is_Macro_Arg_Expansion (Loc, C_Start_Loc'Access, TU) /= 0 + do + Start_Loc := C_Start_Loc; + end return; end Is_Macro_Arg_Expansion; ---------------------------------------------- diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index 671c7eeda..d5868cca5 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -25,6 +25,8 @@ with Interfaces.C; use Interfaces.C; with Clang.Index; use Clang.Index; with Clang.Rewrite; use Clang.Rewrite; +with Slocs; use Slocs; + package Clang.Extensions is function Get_Body (C : Cursor_T) return Cursor_T @@ -114,13 +116,26 @@ package Clang.Extensions is -- The functions below are simply bindings around clang functions, which -- are exhaustively documented in the clang sources. + function Spelling_Location (Loc : Source_Location_T) return Source_Location + with Inline; + -- Thick binding for Clang.Index.Get_Spelling_Location + + function File_Location + (Loc : Source_Location_T) return Local_Source_Location + with Inline; + -- Thick binding for Clang.Index.Get_File_Location + + function Presumed_Location + (Loc : Source_Location_T) return Local_Source_Location; + -- Thick binding for Clang.Index.Get Presumed_Location + function Is_Macro_Location (Loc : Source_Location_T) return Boolean with Inline; -- See isMacroID in clang/Basic/SourceLocation.h. function Is_Macro_Arg_Expansion (Loc : Source_Location_T; - Start_Loc : access Source_Location_T := null; + Start_Loc : out Source_Location_T; TU : Translation_Unit_T) return Boolean with Inline; -- See isMacroArgExpansion in clang/Basic/SourceManager.h. diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 77b778bc9..2e5a0740b 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -565,12 +565,8 @@ package body Instrument.C is Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name) is - Loc : Source_Location_T := - Get_Range_Start (Get_Cursor_Extent (N)); - - Line, Column, Offset : aliased unsigned; - File : File_T; - Info : PP_Info; + Loc : Source_Location_T := Get_Range_Start (Get_Cursor_Extent (N)); + Info : PP_Info; begin Append_SCO (C1, C2, From, To, Last, Pragma_Aspect_Name); @@ -591,14 +587,10 @@ package body Instrument.C is Expansion_Stack : Expansion_Lists.List; Definition_Info : Expansion_Info; - Macro_Expansion_Name : US.Unbounded_String; - Immediate_Expansion_Loc_C : Source_Location_T; - Immediate_Expansion_Loc : Source_Location; - - Macro_Arg_Expanded_Loc_C : aliased Source_Location_T; - Macro_Arg_Expanded_Loc : Source_Location; + Macro_Expansion_Name : US.Unbounded_String; + Immediate_Expansion_Loc : Source_Location_T; + Macro_Arg_Expanded_Loc : Source_Location_T; begin - -- Note: macro arguments are completely macro-expanded before they -- are substituted in a macro body, unless they are stringified or -- pasted with other tokens. @@ -662,53 +654,26 @@ package body Instrument.C is -- So we have to get the macro argument expansion location, and -- get its spelling location. - if Is_Macro_Arg_Expansion - (Loc, Macro_Arg_Expanded_Loc_C'Access, UIC.TU) + if Is_Macro_Arg_Expansion (Loc, Macro_Arg_Expanded_Loc, UIC.TU) then - Get_Spelling_Location - (Macro_Arg_Expanded_Loc_C, - File'Address, - Line'Access, - Column'Access, - Offset'Access); - Macro_Arg_Expanded_Loc := - (Source_File => - Get_Index_From_Generic_Name - (Name => Get_File_Name (File), - Kind => Source_File), - L => (Natural (Line), Natural (Column))); - Macro_Expansion_Name := +Get_Immediate_Macro_Name_For_Diagnostics - (Macro_Arg_Expanded_Loc_C, UIC.TU); + (Macro_Arg_Expanded_Loc, UIC.TU); Definition_Info := (Macro_Name => Macro_Expansion_Name, - Sloc => Macro_Arg_Expanded_Loc); + Sloc => Spelling_Location (Macro_Arg_Expanded_Loc)); else - Get_Spelling_Location - (Loc, - File'Address, - Line'Access, - Column'Access, - Offset'Access); - - Immediate_Expansion_Loc := - (Source_File => - Get_Index_From_Generic_Name - (Name => Get_File_Name (File), - Kind => Source_File), - L => (Natural (Line), Natural (Column))); Macro_Expansion_Name := +Get_Immediate_Macro_Name_For_Diagnostics (Loc, UIC.TU); Definition_Info := (Macro_Name => Macro_Expansion_Name, - Sloc => Immediate_Expansion_Loc); + Sloc => Spelling_Location (Loc)); end if; while Is_Macro_Location (Loc) loop - Immediate_Expansion_Loc_C := Loc; + Immediate_Expansion_Loc := Loc; -- Find the location of the immediately expanded macro. Getting -- the immediate expansion location yields a location in the @@ -747,9 +712,7 @@ package body Instrument.C is -- as implemented in clang. while Is_Macro_Arg_Expansion - (Immediate_Expansion_Loc_C, - Macro_Arg_Expanded_Loc_C'Access, - UIC.TU) + (Immediate_Expansion_Loc, Macro_Arg_Expanded_Loc, UIC.TU) loop -- TODO??? Document why it is needed to loop while we are -- in a macro argument expansion (did not manage to make an @@ -758,31 +721,17 @@ package body Instrument.C is -- Get_Immediate_Macro_Name_For_Diagnostics implemented in -- clang. - Immediate_Expansion_Loc_C := + Immediate_Expansion_Loc := Get_Immediate_Expansion_Loc - (Immediate_Expansion_Loc_C, UIC.TU); + (Immediate_Expansion_Loc, UIC.TU); end loop; - -- Immediate_Expansion_Loc is the location of the token in - -- the immediate expanded macro definition. To get to the - -- expansion point, go up one level. - - Immediate_Expansion_Loc_C := - Get_Immediate_Expansion_Loc - (Immediate_Expansion_Loc_C, UIC.TU); - Get_Spelling_Location - (Immediate_Expansion_Loc_C, - File'Address, - Line'Access, - Column'Access, - Offset'Access); + -- Immediate_Expansion_Loc is the location of the token in the + -- immediate expanded macro definition. To get to the expansion + -- point, go up one level. Immediate_Expansion_Loc := - (Source_File => - Get_Index_From_Generic_Name - (Name => Get_File_Name (File), - Kind => Source_File), - L => (Natural (Line), Natural (Column))); + Get_Immediate_Expansion_Loc (Immediate_Expansion_Loc, UIC.TU); Macro_Expansion_Name := +Get_Immediate_Macro_Name_For_Diagnostics (Loc, UIC.TU); @@ -797,7 +746,8 @@ package body Instrument.C is if Length (Macro_Expansion_Name) /= 0 then Expansion_Stack.Append ((Macro_Name => Macro_Expansion_Name, - Sloc => Immediate_Expansion_Loc)); + Sloc => Spelling_Location + (Immediate_Expansion_Loc))); end if; end loop; @@ -844,9 +794,6 @@ package body Instrument.C is End_Loc : constant Source_Location_T := Get_Range_End (Cursor_Source_Range_C); - Line, Column, Offset : aliased unsigned; - File : File_T; - Cursor_Source_Range : Slocs.Local_Source_Location_Range; procedure Update (LL_SCO : Nat; Info : in out PP_Info); @@ -864,28 +811,13 @@ package body Instrument.C is end Update; begin - -- Get start of the range - - Get_File_Location - (Start_Loc, - File'Address, - Line'Access, - Column'Access, - Offset'Access); - Cursor_Source_Range.First_Sloc := - (Line => Natural (Line), Column => Natural (Column)); - - -- Get end of the range. Note: end column is exclusive - - Get_File_Location - (End_Loc, - File'Address, - Line'Access, - Column'Access, - Offset'Access); - - Cursor_Source_Range.Last_Sloc := - (Line => Natural (Line), Column => Natural (Column) - 1); + -- Get start and end of the range. Note: End_Loc is exclusive, + -- whereas we need Cursor_Source_Range.Last_Sloc to be inclusive. + + Cursor_Source_Range.First_Sloc := File_Location (Start_Loc); + Cursor_Source_Range.Last_Sloc := File_Location (End_Loc); + Cursor_Source_Range.Last_Sloc.Column := + Cursor_Source_Range.Last_Sloc.Column - 1; UIC.LL_PP_Info_Map.Update_Element (UIC.LL_PP_Info_Map.Find (SCOs.SCO_Table.Last), Update'Access); diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index f3b8ff62f..62206bfcc 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -34,13 +34,8 @@ package body Instrument.C_Utils is ---------- function Sloc (Loc : Source_Location_T) return Local_Source_Location is - Line, Column : aliased Interfaces.C.unsigned; begin - Get_Presumed_Location (Location => Loc, - Filename => null, - Line => Line'Access, - Column => Column'Access); - return (Natural (Line), Natural (Column)); + return Presumed_Location (Loc); end Sloc; ---------------- @@ -48,15 +43,8 @@ package body Instrument.C_Utils is ---------------- function Start_Sloc (N : Cursor_T) return Local_Source_Location is - Line, Column : aliased Interfaces.C.unsigned; - Loc : constant Source_Location_T := - Get_Range_Start (Get_Cursor_Extent (N)); begin - Get_Presumed_Location (Location => Loc, - Filename => null, - Line => Line'Access, - Column => Column'Access); - return (Natural (Line), Natural (Column)); + return Presumed_Location (Get_Range_Start (Get_Cursor_Extent (N))); end Start_Sloc; -------------- @@ -64,19 +52,12 @@ package body Instrument.C_Utils is -------------- function End_Sloc (N : Cursor_T) return Local_Source_Location is - Line, Column : aliased Interfaces.C.unsigned; - Loc : Source_Location_T := - Get_Range_End (Get_Cursor_Extent (N)); + Loc : Source_Location_T := Get_Range_End (Get_Cursor_Extent (N)); begin if Is_Macro_Location (Loc) then Loc := Get_Expansion_End (Get_Cursor_TU (N), Loc); end if; - Get_Presumed_Location - (Location => Loc, - Filename => null, - Line => Line'Access, - Column => Column'Access); - return (Natural (Line), Natural (Column)); + return Presumed_Location (Loc); end End_Sloc; ---------- From dbe951620e17f7408d10fbf2450ba76ea5a28e78 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Sep 2022 11:16:33 +0000 Subject: [PATCH 0004/1483] pre-commit: fix formatting for casts The GNU predefined style is buggy for C-style casts (see https://github.com/llvm/llvm-project/issues/20356). Adjust the corresponding parameter. Also run the pre-commit hook on C/C++ sources. Change-Id: I3615475ab16ae04afb1efc377420456166bd2090 TN: V916-015 --- .pre-commit-config.yaml | 2 +- tools/gnatcov/bfd_helpers.c | 62 +++++++---- tools/gnatcov/clang-wrapper.cc | 116 ++++++++++---------- tools/gnatcov/libopcodes_bind/dis_stream.c | 16 +-- tools/gnatcov/libopcodes_bind/dis_stream.h | 5 +- tools/gnatcov/libopcodes_bind/dis_wrapper.c | 38 +++---- tools/gnatcov/zlib_helpers.c | 10 +- 7 files changed, 130 insertions(+), 119 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 84f22d470..8cd76df07 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,4 +5,4 @@ repos: - id: clang-format types: [file] files: \.(cc|c|h)$ - args: ["--style=gnu"] + args: ["--style={BasedOnStyle: gnu, SpaceAfterCStyleCast: true}"] diff --git a/tools/gnatcov/bfd_helpers.c b/tools/gnatcov/bfd_helpers.c index 5828f9203..62a4cf440 100644 --- a/tools/gnatcov/bfd_helpers.c +++ b/tools/gnatcov/bfd_helpers.c @@ -23,10 +23,21 @@ #include #include -#define CHECK(expr, call) do { if (!(expr)) { (*warn_cb)(call " failed", bfd_errmsg(bfd_get_error())); return; } } while (0) +#define CHECK(expr, call) \ + do \ + { \ + if (!(expr)) \ + { \ + (*warn_cb) (call " failed", bfd_errmsg (bfd_get_error ())); \ + return; \ + } \ + } \ + while (0) void -_gnatcov_for_each_synthetic_symbol(char *fn, void (*cb)(const char *, long unsigned int), void (*warn_cb)(const char *, const char *)) +_gnatcov_for_each_synthetic_symbol ( + char *fn, void (*cb) (const char *, long unsigned int), + void (*warn_cb) (const char *, const char *)) { bfd *abfd; asymbol **dyn_syms = NULL, *synthsyms = NULL; @@ -36,49 +47,54 @@ _gnatcov_for_each_synthetic_symbol(char *fn, void (*cb)(const char *, long unsig int j; symbol_info si; - abfd = bfd_openr(fn, "default"); - CHECK(abfd != NULL, "bfd_openr"); + abfd = bfd_openr (fn, "default"); + CHECK (abfd != NULL, "bfd_openr"); - bfd_check_format(abfd, bfd_object); + bfd_check_format (abfd, bfd_object); - storage = bfd_get_dynamic_symtab_upper_bound(abfd); - CHECK(storage >= 0, "bfd_get_dynamic_symtab_upper_bound"); + storage = bfd_get_dynamic_symtab_upper_bound (abfd); + CHECK (storage >= 0, "bfd_get_dynamic_symtab_upper_bound"); if (storage == 0) /* No dynamic symbols, nothing to do. */ return; - dyn_syms = (asymbol **) bfd_alloc(abfd, storage); - CHECK(dyn_syms != NULL, "bfd_alloc"); + dyn_syms = (asymbol **) bfd_alloc (abfd, storage); + CHECK (dyn_syms != NULL, "bfd_alloc"); - dyn_count = bfd_canonicalize_dynamic_symtab(abfd, dyn_syms); + dyn_count = bfd_canonicalize_dynamic_symtab (abfd, dyn_syms); if (dyn_count <= 0) /* No dynamic symbols, nothing to do. */ return; - synth_count = bfd_get_synthetic_symtab - (abfd, /*static_count*/ 0, /*static_syms*/ NULL, - dyn_count, dyn_syms, &synthsyms); + synth_count = bfd_get_synthetic_symtab (abfd, /*static_count*/ 0, + /*static_syms*/ NULL, dyn_count, + dyn_syms, &synthsyms); /* Note: synth_count is either -1 or >0, never 0. There is no way distinguish an error condition from the mere absence of synthetic symbols. */ - for (j = 0; j < synth_count; j++) { - bfd_symbol_info(&synthsyms[j], &si); - (*cb) (si.name, si.value); - } + for (j = 0; j < synth_count; j++) + { + bfd_symbol_info (&synthsyms[j], &si); + (*cb) (si.name, si.value); + } - bfd_close(abfd); + bfd_close (abfd); } #ifdef BFD_HELPERS_TEST -void print_cb(const char *name, unsigned long int val) { - printf("%016lx %s\n", val, name); +void +print_cb (const char *name, unsigned long int val) +{ + printf ("%016lx %s\n", val, name); } -int main(int argc, char **argv) { - bfd_init(); - _gnatcov_for_each_synthetic_symbol(argv[1], print_cb); +int +main (int argc, char **argv) +{ + bfd_init (); + _gnatcov_for_each_synthetic_symbol (argv[1], print_cb); } #endif diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index db6ce156b..52d66ced9 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -110,9 +110,10 @@ clang_getBody (CXCursor C) switch (D->getKind ()) { case Decl::FunctionTemplate: - return MakeCXCursorWithNull ( - cast (D)->getTemplatedDecl ()->getBody (), - C); + return MakeCXCursorWithNull (cast (D) + ->getTemplatedDecl () + ->getBody (), + C); case Decl::Function: case Decl::CXXMethod: case Decl::CXXConstructor: @@ -133,29 +134,29 @@ clang_getBody (CXCursor C) if (const Stmt *S = cxcursor::getCursorStmt (C)) switch (S->getStmtClass ()) { - case Stmt::WhileStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), C); - case Stmt::ForStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), C); - case Stmt::CXXForRangeStmtClass: - return MakeCXCursorWithNull - (cast (S)->getBody (), C); - case Stmt::DoStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), C); - case Stmt::SwitchStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), C); - default: - return clang_getNullCursor (); + case Stmt::WhileStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), C); + case Stmt::ForStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), C); + case Stmt::CXXForRangeStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), + C); + case Stmt::DoStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), C); + case Stmt::SwitchStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), C); + default: + return clang_getNullCursor (); } } else if (clang_isExpression (C.kind)) if (const Expr *E = cxcursor::getCursorExpr (C)) switch (E->getStmtClass ()) { - case Expr::LambdaExprClass: - return MakeCXCursorWithNull (cast (E)->getBody (), C); - default: - return clang_getNullCursor (); + case Expr::LambdaExprClass: + return MakeCXCursorWithNull (cast (E)->getBody (), C); + default: + return clang_getNullCursor (); } return clang_getNullCursor (); } @@ -184,8 +185,7 @@ clang_getForRangeExpr (CXCursor C) const Stmt *stmt; const CXXForRangeStmt *for_stmt; - if (clang_isStatement (C.kind) - && (stmt = cxcursor::getCursorStmt (C)) + if (clang_isStatement (C.kind) && (stmt = cxcursor::getCursorStmt (C)) && stmt->getStmtClass () == Stmt::CXXForRangeStmtClass) { for_stmt = cast (stmt); @@ -216,8 +216,7 @@ clang_getCondVar (CXCursor C) const WhileStmt *while_stmt; const VarDecl *decl; - if (clang_isStatement (C.kind) - && (stmt = cxcursor::getCursorStmt (C)) + if (clang_isStatement (C.kind) && (stmt = cxcursor::getCursorStmt (C)) && stmt->getStmtClass () == Stmt::WhileStmtClass) { while_stmt = cast (stmt); @@ -233,8 +232,7 @@ clang_getVarInitExpr (CXCursor C) const Decl *decl; const VarDecl *var_decl; - if (clang_isDeclaration (C.kind) - && (decl = cxcursor::getCursorDecl (C)) + if (clang_isDeclaration (C.kind) && (decl = cxcursor::getCursorDecl (C)) && decl->getKind () == Decl::Kind::Var) { var_decl = cast (decl); @@ -401,24 +399,23 @@ clang_unwrap (CXCursor C) if (const Stmt *S = cxcursor::getCursorStmt (C)) switch (S->getStmtClass ()) { - case Stmt::ParenExprClass: - return clang_unwrap - (MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); - case Expr::ConstantExprClass: - case Expr::ExprWithCleanupsClass: - return clang_unwrap - (MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); - case Expr::ImplicitCastExprClass: - case Expr::CStyleCastExprClass: - case Expr::CXXFunctionalCastExprClass: - case Expr::CXXStaticCastExprClass: - case Expr::CXXDynamicCastExprClass: - case Expr::CXXReinterpretCastExprClass: - case Expr::CXXConstCastExprClass: - case Expr::CXXAddrspaceCastExprClass: - return clang_unwrap - (MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); - + case Stmt::ParenExprClass: + return clang_unwrap ( + MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); + case Expr::ConstantExprClass: + case Expr::ExprWithCleanupsClass: + return clang_unwrap ( + MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); + case Expr::ImplicitCastExprClass: + case Expr::CStyleCastExprClass: + case Expr::CXXFunctionalCastExprClass: + case Expr::CXXStaticCastExprClass: + case Expr::CXXDynamicCastExprClass: + case Expr::CXXReinterpretCastExprClass: + case Expr::CXXConstCastExprClass: + case Expr::CXXAddrspaceCastExprClass: + return clang_unwrap ( + MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); } return C; } @@ -480,13 +477,14 @@ clang_CXRewriter_insertTextAfterToken (CXRewriter Rew, CXSourceLocation Loc, extern "C" unsigned clang_isMacroLocation (CXSourceLocation Loc) { - const clang::SourceLocation SLoc = - clang::cxloc::translateSourceLocation (Loc); + const clang::SourceLocation SLoc + = clang::cxloc::translateSourceLocation (Loc); return SLoc.isMacroID () ? 1 : 0; } extern "C" unsigned -clang_isMacroArgExpansion (CXSourceLocation Loc, CXSourceLocation *StartLoc, CXTranslationUnit TU) +clang_isMacroArgExpansion (CXSourceLocation Loc, CXSourceLocation *StartLoc, + CXTranslationUnit TU) { const SourceManager &SM = cxtu::getASTUnit (TU)->getSourceManager (); const SourceLocation SLoc = translateSourceLocation (Loc); @@ -509,8 +507,8 @@ clang_getImmediateMacroCallerLoc (CXSourceLocation Loc, CXTranslationUnit TU) ASTContext &astContext = astUnit->getASTContext (); SourceLocation SLoc = translateSourceLocation (Loc); if (SLoc.isMacroID ()) - return cxloc::translateSourceLocation - (astContext, SM.getImmediateMacroCallerLoc (SLoc)); + return cxloc::translateSourceLocation ( + astContext, SM.getImmediateMacroCallerLoc (SLoc)); return Loc; } @@ -521,20 +519,20 @@ clang_getImmediateExpansionLoc (CXSourceLocation Loc, CXTranslationUnit TU) ASTUnit *astUnit = cxtu::getASTUnit (TU); ASTContext &astContext = astUnit->getASTContext (); SourceLocation SLoc = translateSourceLocation (Loc); - return cxloc::translateSourceLocation - (astContext, SM.getImmediateExpansionRange (SLoc).getBegin ()); + return cxloc::translateSourceLocation ( + astContext, SM.getImmediateExpansionRange (SLoc).getBegin ()); } extern "C" CXString -clang_getImmediateMacroNameForDiagnostics (CXSourceLocation Loc, CXTranslationUnit TU) +clang_getImmediateMacroNameForDiagnostics (CXSourceLocation Loc, + CXTranslationUnit TU) { SourceLocation SLoc = translateSourceLocation (Loc); SourceManager &SM = cxtu::getASTUnit (TU)->getSourceManager (); ASTUnit *astUnit = cxtu::getASTUnit (TU); ASTContext &astContext = astUnit->getASTContext (); - return createDup - (Lexer::getImmediateMacroNameForDiagnostics - (SLoc, SM, astContext.getLangOpts ())); + return createDup (Lexer::getImmediateMacroNameForDiagnostics ( + SLoc, SM, astContext.getLangOpts ())); } extern "C" CXSourceLocation @@ -544,8 +542,8 @@ clang_getExpansionEnd (CXTranslationUnit TU, CXSourceLocation Loc) SourceManager &SM = cxtu::getASTUnit (TU)->getSourceManager (); ASTUnit *astUnit = cxtu::getASTUnit (TU); ASTContext &astContext = astUnit->getASTContext (); - return cxloc::translateSourceLocation - (astContext, SM.getExpansionRange (SLoc).getEnd ()); + return cxloc::translateSourceLocation ( + astContext, SM.getExpansionRange (SLoc).getEnd ()); } extern "C" CXTranslationUnit @@ -557,6 +555,6 @@ clang_getCursorTU (CXCursor C) extern "C" void clang_printLocation (CXTranslationUnit TU, CXSourceLocation Loc) { - const SourceManager &SM = cxtu::getASTUnit(TU)->getSourceManager(); - clang::cxloc::translateSourceLocation (Loc).dump(SM); + const SourceManager &SM = cxtu::getASTUnit (TU)->getSourceManager (); + clang::cxloc::translateSourceLocation (Loc).dump (SM); } diff --git a/tools/gnatcov/libopcodes_bind/dis_stream.c b/tools/gnatcov/libopcodes_bind/dis_stream.c index f94d2cbad..ddf6c2790 100644 --- a/tools/gnatcov/libopcodes_bind/dis_stream.c +++ b/tools/gnatcov/libopcodes_bind/dis_stream.c @@ -17,17 +17,17 @@ * * ****************************************************************************/ -#include #include +#include #include #include "dis_stream.h" struct disassembler_stream { - char *buff; - unsigned int size; - unsigned int idx; + char *buff; + unsigned int size; + unsigned int idx; }; /* Printf-like function to add content to the DS stream according to FORMAT. @@ -53,7 +53,7 @@ stream_printf (disassembler_stream *ds, const char *format, ...) int res; va_start (ap, format); - res = common_printf(ds, format, ap); + res = common_printf (ds, format, ap); va_end (ap); return res; @@ -63,14 +63,14 @@ stream_printf (disassembler_stream *ds, const char *format, ...) desired. */ int stream_styled_printf (disassembler_stream *ds, - enum disassembler_style style ATTRIBUTE_UNUSED, - const char *format, ...) + enum disassembler_style style ATTRIBUTE_UNUSED, + const char *format, ...) { va_list ap; int res; va_start (ap, format); - res = common_printf(ds, format, ap); + res = common_printf (ds, format, ap); va_end (ap); return res; diff --git a/tools/gnatcov/libopcodes_bind/dis_stream.h b/tools/gnatcov/libopcodes_bind/dis_stream.h index 696216d67..1a6deb3cd 100644 --- a/tools/gnatcov/libopcodes_bind/dis_stream.h +++ b/tools/gnatcov/libopcodes_bind/dis_stream.h @@ -17,7 +17,6 @@ * * ****************************************************************************/ - #ifndef DIS_STREAM_H_ #define DIS_STREAM_H_ @@ -38,8 +37,8 @@ extern void delete_stream (disassembler_stream *const ds); extern int stream_printf (disassembler_stream *ptr, const char *format, ...); extern int stream_styled_printf (disassembler_stream *ptr, - enum disassembler_style style, - const char *format, ...); + enum disassembler_style style, + const char *format, ...); extern void clear_stream (disassembler_stream *const ds); diff --git a/tools/gnatcov/libopcodes_bind/dis_wrapper.c b/tools/gnatcov/libopcodes_bind/dis_wrapper.c index bbe1783f1..85e920110 100644 --- a/tools/gnatcov/libopcodes_bind/dis_wrapper.c +++ b/tools/gnatcov/libopcodes_bind/dis_wrapper.c @@ -17,32 +17,32 @@ * * ****************************************************************************/ -#include #include #include +#include #include -#include "dis_wrapper.h" #include "dis_stream.h" +#include "dis_wrapper.h" /* Define the number of values in enum bfd_endian. */ #define N_BFD_ENDIAN_VALUES 3 struct disassemble_handle { - disassembler_ftype disass_func[N_BFD_ENDIAN_VALUES]; - disassemble_info dinfo; - /* Libopcode sets dinfo.disassembler_options to NULL after parsing once. - This is erroneous when we want e.g. to switch between ARM and Thumb - multiple times. So we need to keep our disassembler options. */ - char *disassembler_options; + disassembler_ftype disass_func[N_BFD_ENDIAN_VALUES]; + disassemble_info dinfo; + /* Libopcode sets dinfo.disassembler_options to NULL after parsing once. + This is erroneous when we want e.g. to switch between ARM and Thumb + multiple times. So we need to keep our disassembler options. */ + char *disassembler_options; }; /* Type stored in dhandle->dinfo->application_data. */ typedef struct symbolizer_data { - print_symbol_cb addr_cb; /* Function that performs the symbol lookup. */ - void *symbolizer; /* Object containing the symbol informations. */ + print_symbol_cb addr_cb; /* Function that performs the symbol lookup. */ + void *symbolizer; /* Object containing the symbol informations. */ } symbolizer_data; char *const dis_thumb_option = "force-thumb"; @@ -54,11 +54,11 @@ char *const dis_ppc_32_option = "32"; char *const dis_ppc_64_option = "64"; #if TARGET_BITS == 32 -# define TARGET_ADDR_FMT "0x%lx" +#define TARGET_ADDR_FMT "0x%lx" #elif TARGET_BITS == 64 -# define TARGET_ADDR_FMT "0x%lx" +#define TARGET_ADDR_FMT "0x%lx" #else /* TARGET_BITS != 32 and TARGET_BITS != 64 */ -# error "Target arch is neither 32 or 64bits, not supported." +#error "Target arch is neither 32 or 64bits, not supported." #endif /* This is a callback for disassemble_info->print_address_func. */ @@ -76,7 +76,7 @@ _print_address_cb (bfd_vma addr, disassemble_info *dinfo) /* Then, print the symbolized address, if possible. First dump it to BUFF, then if symbolization worked, move it to the output stream. */ buff_cur - = sym_data->addr_cb (addr, sym_data->symbolizer, buff, buff_size - 1); + = sym_data->addr_cb (addr, sym_data->symbolizer, buff, buff_size - 1); buff[buff_cur++] = '\0'; stream_printf (dinfo->stream, "%s", buff); } @@ -100,7 +100,7 @@ _create_base_disassembler (enum bfd_architecture arch, const char *options) } init_disassemble_info (&(dh->dinfo), ds, (fprintf_ftype) stream_printf, - (fprintf_styled_ftype) stream_styled_printf); + (fprintf_styled_ftype) stream_styled_printf); dh->dinfo.arch = arch; if (options) { @@ -133,8 +133,8 @@ _create_base_disassembler (enum bfd_architecture arch, const char *options) static disassemble_handle * _create_arm_arch_disassembler (unsigned char for_thumb) { - return _create_base_disassembler - (bfd_arch_arm, (for_thumb) ? dis_thumb_option : dis_arm_option); + return _create_base_disassembler ( + bfd_arch_arm, (for_thumb) ? dis_thumb_option : dis_arm_option); } /* Set necessary information for symbol resolution for the disassembler @@ -143,7 +143,7 @@ void set_disassembler_symbolizer (disassemble_handle *const dh, void *const symbolizer, print_symbol_cb addr_cb) { - symbolizer_data* sym_data = dh->dinfo.application_data; + symbolizer_data *sym_data = dh->dinfo.application_data; sym_data->addr_cb = addr_cb; dh->dinfo.print_address_func = _print_address_cb; @@ -269,7 +269,7 @@ disassemble_to_text (disassemble_handle *const dh, bfd_vma pc, instruction. */ dh->dinfo.disassembler_options = dh->disassembler_options; - size = dh->disass_func[endian] (pc, &(dh->dinfo)); + size = dh->disass_func[endian](pc, &(dh->dinfo)); clear_stream (dh->dinfo.stream); diff --git a/tools/gnatcov/zlib_helpers.c b/tools/gnatcov/zlib_helpers.c index 85f380e43..b9dc0a62d 100644 --- a/tools/gnatcov/zlib_helpers.c +++ b/tools/gnatcov/zlib_helpers.c @@ -26,8 +26,8 @@ OUT_BUFFER (a byte buffer of size OUT_SIZE) using zlib. Return whether decompression was successful. */ int -gnatcov_zlib_uncompress (char *in_buffer, uint64_t in_size, - char *out_buffer, uint64_t out_size) +gnatcov_zlib_uncompress (char *in_buffer, uint64_t in_size, char *out_buffer, + uint64_t out_size) { z_stream strm; @@ -39,8 +39,6 @@ gnatcov_zlib_uncompress (char *in_buffer, uint64_t in_size, /* Uncompress and then check that uncompressed data consumed exactly OUT_SIZE bytes. */ - return (inflateInit (&strm) == Z_OK - && inflate (&strm, Z_FINISH) == Z_OK - && inflateEnd (&strm) == Z_OK - && strm.avail_out == 0); + return (inflateInit (&strm) == Z_OK && inflate (&strm, Z_FINISH) == Z_OK + && inflateEnd (&strm) == Z_OK && strm.avail_out == 0); } From a0b05e86f6d6d22b10c5fe468edd3231d3cb86b9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Sep 2022 11:50:13 +0000 Subject: [PATCH 0005/1483] clang-wrapper.cc: remove a seemingly redundant check Change-Id: I45a0d8eb12c75272600f0293470f0057016b8613 TN: V916-015 --- tools/gnatcov/clang-wrapper.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 52d66ced9..914e61b19 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -369,8 +369,6 @@ extern "C" CXSourceLocation clang_getOperatorLoc (CXCursor C) { ASTUnit *CXXUnit = cxtu::getASTUnit (getCursorTU (C)); - if (!CXXUnit) - return clang_getNullLocation (); SourceLocation sloc; if (clang_isExpression (C.kind)) if (const Stmt *S = cxcursor::getCursorStmt (C)) From 2568411c23c59783a8ef80b7512df983736c8a7d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Sep 2022 11:51:04 +0000 Subject: [PATCH 0006/1483] clang-wrapper.cc: add more "section separators" Change-Id: I8f2509d92320b2161c35f1f3fe572080e9bf36af TN: V916-015 --- tools/gnatcov/clang-wrapper.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 914e61b19..a53208ce1 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -472,6 +472,8 @@ clang_CXRewriter_insertTextAfterToken (CXRewriter Rew, CXSourceLocation Loc, R.InsertTextAfterToken (clang::cxloc::translateSourceLocation (Loc), Insert); } +/* Wrappers around source location analysis functions. */ + extern "C" unsigned clang_isMacroLocation (CXSourceLocation Loc) { @@ -550,6 +552,8 @@ clang_getCursorTU (CXCursor C) return cxcursor::getCursorTU (C); } +/* Debug helpers. */ + extern "C" void clang_printLocation (CXTranslationUnit TU, CXSourceLocation Loc) { From 4849c7fdb24103ad177bbba44a8a1439e70e0f3c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Sep 2022 11:51:42 +0000 Subject: [PATCH 0007/1483] clang-wrapper.cc: introduce helpers to reduce code duplication Change-Id: I1544bc18922dddf91879d59c991ff9d36d16935a TN: V916-015 --- tools/gnatcov/clang-wrapper.cc | 76 +++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 29 deletions(-) diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index a53208ce1..08dd2a584 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -46,6 +46,39 @@ using namespace clang::cxloc; using namespace clang::cxstring; using namespace clang::cxtu; +/* Return the AST context corresponding to the given translation unit TU. */ + +static ASTContext & +getContext (CXTranslationUnit TU) +{ + return cxtu::getASTUnit (TU)->getASTContext (); +} + +/* Likewise, but starting from a cursor. */ + +static ASTContext & +getContext (CXCursor C) +{ + return getContext (getCursorTU (C)); +} + +/* Return the SourceManager corresponding to the given translation unit TU. */ + +static const SourceManager & +getSourceManager (CXTranslationUnit TU) +{ + return cxtu::getASTUnit (TU)->getSourceManager (); +} + +/* Translate a source location to a cursor source location in the given + translation unit TU. */ + +static CXSourceLocation +translateSLoc (CXTranslationUnit TU, SourceLocation Loc) +{ + return cxloc::translateSourceLocation (getContext (TU), Loc); +} + /* Convert a clang Stmt type to a libclang CXCursor structure. The CXCursor C is simply used to get a relevant declaration and translation unit to tie the returned cursor to. */ @@ -368,7 +401,7 @@ clang_getOpcodeStr (CXCursor C) extern "C" CXSourceLocation clang_getOperatorLoc (CXCursor C) { - ASTUnit *CXXUnit = cxtu::getASTUnit (getCursorTU (C)); + CXTranslationUnit TU = getCursorTU (C); SourceLocation sloc; if (clang_isExpression (C.kind)) if (const Stmt *S = cxcursor::getCursorStmt (C)) @@ -383,7 +416,7 @@ clang_getOperatorLoc (CXCursor C) default: return clang_getNullLocation (); } - return cxloc::translateSourceLocation (CXXUnit->getASTContext (), sloc); + return translateSLoc (TU, sloc); } /* If the given expression is a wrapping expression (i.e. a parenthesized @@ -438,11 +471,9 @@ extern "C" CXCursor clang_getParent (CXCursor C) { assert (clang_isStatement (C.kind) || clang_isExpression (C.kind)); - ASTUnit *astUnit = cxtu::getASTUnit (getCursorTU (C)); - ASTContext &astContext = astUnit->getASTContext (); if (const Stmt *S = cxcursor::getCursorStmt (C)) { - const auto Parents = astContext.getParents (*S); + const auto Parents = getContext (C).getParents (*S); if (Parents.empty ()) return clang_getNullCursor (); const auto &SParent = Parents[0]; @@ -486,14 +517,12 @@ extern "C" unsigned clang_isMacroArgExpansion (CXSourceLocation Loc, CXSourceLocation *StartLoc, CXTranslationUnit TU) { - const SourceManager &SM = cxtu::getASTUnit (TU)->getSourceManager (); + const SourceManager &SM = getSourceManager (TU); const SourceLocation SLoc = translateSourceLocation (Loc); - ASTUnit *astUnit = cxtu::getASTUnit (TU); - ASTContext &astContext = astUnit->getASTContext (); SourceLocation Result; if (SM.isMacroArgExpansion (SLoc, &Result)) { - *StartLoc = cxloc::translateSourceLocation (astContext, Result); + *StartLoc = translateSLoc (TU, Result); return 1; } return 0; @@ -502,25 +531,19 @@ clang_isMacroArgExpansion (CXSourceLocation Loc, CXSourceLocation *StartLoc, extern "C" CXSourceLocation clang_getImmediateMacroCallerLoc (CXSourceLocation Loc, CXTranslationUnit TU) { - SourceManager &SM = cxtu::getASTUnit (TU)->getSourceManager (); - ASTUnit *astUnit = cxtu::getASTUnit (TU); - ASTContext &astContext = astUnit->getASTContext (); + const SourceManager &SM = getSourceManager (TU); SourceLocation SLoc = translateSourceLocation (Loc); if (SLoc.isMacroID ()) - return cxloc::translateSourceLocation ( - astContext, SM.getImmediateMacroCallerLoc (SLoc)); + return translateSLoc (TU, SM.getImmediateMacroCallerLoc (SLoc)); return Loc; } extern "C" CXSourceLocation clang_getImmediateExpansionLoc (CXSourceLocation Loc, CXTranslationUnit TU) { - SourceManager &SM = cxtu::getASTUnit (TU)->getSourceManager (); - ASTUnit *astUnit = cxtu::getASTUnit (TU); - ASTContext &astContext = astUnit->getASTContext (); + const SourceManager &SM = getSourceManager (TU); SourceLocation SLoc = translateSourceLocation (Loc); - return cxloc::translateSourceLocation ( - astContext, SM.getImmediateExpansionRange (SLoc).getBegin ()); + return translateSLoc (TU, SM.getImmediateExpansionRange (SLoc).getBegin ()); } extern "C" CXString @@ -528,22 +551,17 @@ clang_getImmediateMacroNameForDiagnostics (CXSourceLocation Loc, CXTranslationUnit TU) { SourceLocation SLoc = translateSourceLocation (Loc); - SourceManager &SM = cxtu::getASTUnit (TU)->getSourceManager (); - ASTUnit *astUnit = cxtu::getASTUnit (TU); - ASTContext &astContext = astUnit->getASTContext (); + const SourceManager &SM = getSourceManager (TU); return createDup (Lexer::getImmediateMacroNameForDiagnostics ( - SLoc, SM, astContext.getLangOpts ())); + SLoc, SM, getContext (TU).getLangOpts ())); } extern "C" CXSourceLocation clang_getExpansionEnd (CXTranslationUnit TU, CXSourceLocation Loc) { SourceLocation SLoc = translateSourceLocation (Loc); - SourceManager &SM = cxtu::getASTUnit (TU)->getSourceManager (); - ASTUnit *astUnit = cxtu::getASTUnit (TU); - ASTContext &astContext = astUnit->getASTContext (); - return cxloc::translateSourceLocation ( - astContext, SM.getExpansionRange (SLoc).getEnd ()); + const SourceManager &SM = getSourceManager (TU); + return translateSLoc (TU, SM.getExpansionRange (SLoc).getEnd ()); } extern "C" CXTranslationUnit @@ -557,6 +575,6 @@ clang_getCursorTU (CXCursor C) extern "C" void clang_printLocation (CXTranslationUnit TU, CXSourceLocation Loc) { - const SourceManager &SM = cxtu::getASTUnit (TU)->getSourceManager (); + const SourceManager &SM = getSourceManager (TU); clang::cxloc::translateSourceLocation (Loc).dump (SM); } From 6c1940b6553d67e9bee379a83622f4941533b0a3 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Sep 2022 11:55:20 +0000 Subject: [PATCH 0008/1483] clang-wrapper.cc: remove redundant namespace prefixes Change-Id: If59825d1be8df53cc644814a658b1c658622549d TN: V916-015 --- tools/gnatcov/clang-wrapper.cc | 62 ++++++++++++++++------------------ 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 08dd2a584..b37f3c374 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -51,7 +51,7 @@ using namespace clang::cxtu; static ASTContext & getContext (CXTranslationUnit TU) { - return cxtu::getASTUnit (TU)->getASTContext (); + return getASTUnit (TU)->getASTContext (); } /* Likewise, but starting from a cursor. */ @@ -67,7 +67,7 @@ getContext (CXCursor C) static const SourceManager & getSourceManager (CXTranslationUnit TU) { - return cxtu::getASTUnit (TU)->getSourceManager (); + return getASTUnit (TU)->getSourceManager (); } /* Translate a source location to a cursor source location in the given @@ -76,7 +76,7 @@ getSourceManager (CXTranslationUnit TU) static CXSourceLocation translateSLoc (CXTranslationUnit TU, SourceLocation Loc) { - return cxloc::translateSourceLocation (getContext (TU), Loc); + return translateSourceLocation (getContext (TU), Loc); } /* Convert a clang Stmt type to a libclang CXCursor structure. The CXCursor C @@ -112,7 +112,7 @@ extern "C" CXCursor clang_getCond (CXCursor C) { if (clang_isStatement (C.kind) || clang_isExpression (C.kind)) - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) { case Stmt::IfStmtClass: @@ -139,7 +139,7 @@ clang_getBody (CXCursor C) { if (clang_isDeclaration (C.kind)) { - if (const Decl *D = cxcursor::getCursorDecl (C)) + if (const Decl *D = getCursorDecl (C)) switch (D->getKind ()) { case Decl::FunctionTemplate: @@ -164,7 +164,7 @@ clang_getBody (CXCursor C) } else if (clang_isStatement (C.kind)) { - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) { case Stmt::WhileStmtClass: @@ -183,7 +183,7 @@ clang_getBody (CXCursor C) } } else if (clang_isExpression (C.kind)) - if (const Expr *E = cxcursor::getCursorExpr (C)) + if (const Expr *E = getCursorExpr (C)) switch (E->getStmtClass ()) { case Expr::LambdaExprClass: @@ -198,7 +198,7 @@ extern "C" CXCursor clang_getForInit (CXCursor C) { if (clang_isStatement (C.kind)) - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) { case Stmt::ForStmtClass: @@ -231,7 +231,7 @@ extern "C" CXCursor clang_getForInc (CXCursor C) { if (clang_isStatement (C.kind)) - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) { case Stmt::ForStmtClass: @@ -249,7 +249,7 @@ clang_getCondVar (CXCursor C) const WhileStmt *while_stmt; const VarDecl *decl; - if (clang_isStatement (C.kind) && (stmt = cxcursor::getCursorStmt (C)) + if (clang_isStatement (C.kind) && (stmt = getCursorStmt (C)) && stmt->getStmtClass () == Stmt::WhileStmtClass) { while_stmt = cast (stmt); @@ -265,7 +265,7 @@ clang_getVarInitExpr (CXCursor C) const Decl *decl; const VarDecl *var_decl; - if (clang_isDeclaration (C.kind) && (decl = cxcursor::getCursorDecl (C)) + if (clang_isDeclaration (C.kind) && (decl = getCursorDecl (C)) && decl->getKind () == Decl::Kind::Var) { var_decl = cast (decl); @@ -278,7 +278,7 @@ extern "C" CXCursor clang_getThen (CXCursor C) { if (clang_isStatement (C.kind)) - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) { case Stmt::IfStmtClass: @@ -293,7 +293,7 @@ extern "C" CXCursor clang_getElse (CXCursor C) { if (clang_isStatement (C.kind)) - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) { case Stmt::IfStmtClass: @@ -308,7 +308,7 @@ extern "C" CXCursor clang_getSubExpr (CXCursor C) { if (clang_isExpression (C.kind)) - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) { case Stmt::UnaryOperatorClass: @@ -324,7 +324,7 @@ extern "C" CXCursor clang_getSubStmt (CXCursor C) { if (clang_isStatement (C.kind)) - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) { case Stmt::CaseStmtClass: @@ -342,7 +342,7 @@ extern "C" CXCursor clang_getRHS (CXCursor C) { if (clang_isExpression (C.kind)) - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) { case Stmt::BinaryOperatorClass: @@ -360,7 +360,7 @@ extern "C" CXCursor clang_getLHS (CXCursor C) { if (clang_isExpression (C.kind)) - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) { case Stmt::BinaryOperatorClass: @@ -381,7 +381,7 @@ extern "C" CXString clang_getOpcodeStr (CXCursor C) { if (clang_isExpression (C.kind)) - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) { case Stmt::BinaryOperatorClass: @@ -404,7 +404,7 @@ clang_getOperatorLoc (CXCursor C) CXTranslationUnit TU = getCursorTU (C); SourceLocation sloc; if (clang_isExpression (C.kind)) - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) { case Stmt::BinaryOperatorClass: @@ -427,7 +427,7 @@ extern "C" CXCursor clang_unwrap (CXCursor C) { if (clang_isExpression (C.kind)) - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) { case Stmt::ParenExprClass: @@ -458,9 +458,8 @@ extern "C" unsigned clang_visit (CXCursor parent, CXCursorVisitor visitor, CXClientData client_data) { - cxcursor::CursorVisitor CursorVis (getCursorTU (parent), visitor, - client_data, - /*VisitPreprocessorLast=*/false); + CursorVisitor CursorVis (getCursorTU (parent), visitor, client_data, + /*VisitPreprocessorLast=*/false); return CursorVis.Visit (parent); } @@ -471,7 +470,7 @@ extern "C" CXCursor clang_getParent (CXCursor C) { assert (clang_isStatement (C.kind) || clang_isExpression (C.kind)); - if (const Stmt *S = cxcursor::getCursorStmt (C)) + if (const Stmt *S = getCursorStmt (C)) { const auto Parents = getContext (C).getParents (*S); if (Parents.empty ()) @@ -490,8 +489,8 @@ clang_CXRewriter_insertTextAfter (CXRewriter Rew, CXSourceLocation Loc, const char *Insert) { assert (Rew); - clang::Rewriter &R = *reinterpret_cast (Rew); - R.InsertTextAfter (clang::cxloc::translateSourceLocation (Loc), Insert); + Rewriter &R = *reinterpret_cast (Rew); + R.InsertTextAfter (translateSourceLocation (Loc), Insert); } extern "C" void @@ -499,8 +498,8 @@ clang_CXRewriter_insertTextAfterToken (CXRewriter Rew, CXSourceLocation Loc, const char *Insert) { assert (Rew); - clang::Rewriter &R = *reinterpret_cast (Rew); - R.InsertTextAfterToken (clang::cxloc::translateSourceLocation (Loc), Insert); + Rewriter &R = *reinterpret_cast (Rew); + R.InsertTextAfterToken (translateSourceLocation (Loc), Insert); } /* Wrappers around source location analysis functions. */ @@ -508,8 +507,7 @@ clang_CXRewriter_insertTextAfterToken (CXRewriter Rew, CXSourceLocation Loc, extern "C" unsigned clang_isMacroLocation (CXSourceLocation Loc) { - const clang::SourceLocation SLoc - = clang::cxloc::translateSourceLocation (Loc); + const SourceLocation SLoc = translateSourceLocation (Loc); return SLoc.isMacroID () ? 1 : 0; } @@ -567,7 +565,7 @@ clang_getExpansionEnd (CXTranslationUnit TU, CXSourceLocation Loc) extern "C" CXTranslationUnit clang_getCursorTU (CXCursor C) { - return cxcursor::getCursorTU (C); + return getCursorTU (C); } /* Debug helpers. */ @@ -576,5 +574,5 @@ extern "C" void clang_printLocation (CXTranslationUnit TU, CXSourceLocation Loc) { const SourceManager &SM = getSourceManager (TU); - clang::cxloc::translateSourceLocation (Loc).dump (SM); + translateSourceLocation (Loc).dump (SM); } From 39b32802a1d83b0f0c1465f0032d368248a06a29 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Sep 2022 12:55:00 +0000 Subject: [PATCH 0009/1483] Instrument.C_Utils: reformattings and refactorings Fix and harmonize the coding style, add missing comments and get rid of the pragma Warnings. TN: V916-015 Change-Id: I0c3a38ed411206951daa45ccd57c58879168ac8d --- tools/gnatcov/instrument-c_utils.adb | 113 +++++++++++++++++++-------- tools/gnatcov/instrument-c_utils.ads | 19 +++-- 2 files changed, 92 insertions(+), 40 deletions(-) diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index 62206bfcc..1a63f6af1 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -78,21 +78,24 @@ package body Instrument.C_Utils is return Cursor_Is_Null (N); end Is_Null; - pragma Warnings (Off); - -------------------- -- Visit_Children -- -------------------- procedure Visit_Children - (Parent : Cursor_T; - Visitor : Cursor_Visitor_Function) is - + (Parent : Cursor_T; Visitor : Cursor_Visitor_Function) + is function Visitor_Wrapper (Node : Cursor_T; Parent : Cursor_T; Client_Data : Client_Data_T) return Child_Visit_Result_T with Convention => C; + -- Callback for Clang.Index.Visit_Children. Just a wrapper around + -- Visitor. + + --------------------- + -- Visitor_Wrapper -- + --------------------- function Visitor_Wrapper (Node : Cursor_T; @@ -104,11 +107,15 @@ package body Instrument.C_Utils is return Visitor (Node); end Visitor_Wrapper; - Data : Client_Data_T; - Result : unsigned; + Dummy : constant unsigned := Visit_Children + (Parent, + Visitor_Wrapper'Unrestricted_Access, + Client_Data_T (System.Null_Address)); + + -- Start of processing for Visit_Children + begin - Result := - Visit_Children (Parent, Visitor_Wrapper'Unrestricted_Access, Data); + null; end Visit_Children; ----------- @@ -116,12 +123,17 @@ package body Instrument.C_Utils is ----------- procedure Visit (Parent : Cursor_T; Visitor : Cursor_Visitor_Function) is - function Visitor_Wrapper (Node : Cursor_T; Parent : Cursor_T; Client_Data : Client_Data_T) return Child_Visit_Result_T with Convention => C; + -- Callback for Clang.Index.Visit_Children. Just a wrapper around + -- Visitor. + + --------------------- + -- Visitor_Wrapper -- + --------------------- function Visitor_Wrapper (Node : Cursor_T; @@ -133,34 +145,41 @@ package body Instrument.C_Utils is return Visitor (Node); end Visitor_Wrapper; - Data : Client_Data_T; - Result : unsigned; + Dummy : constant unsigned := Visit + (Parent, + Visitor_Wrapper'Unrestricted_Access, + Client_Data_T (System.Null_Address)); + + -- Start of processing for Visit + begin - Result := Visit (Parent, Visitor_Wrapper'Unrestricted_Access, Data); + null; end Visit; - pragma Warnings (On); ------------------ -- Get_Children -- ------------------ function Get_Children (N : Cursor_T) return Cursor_Vectors.Vector is - Res : Vector; - -- Append the children to the result vector and continue the traversal - -- until all children have been appended. - function Append_Child (Cursor : Cursor_T) return Child_Visit_Result_T with Convention => C; + -- Callback for Visit_Children. Append Cursor to Res and continue the + -- traversal. - function Append_Child (Cursor : Cursor_T) return Child_Visit_Result_T - is + ------------------ + -- Append_Child -- + ------------------ + + function Append_Child (Cursor : Cursor_T) return Child_Visit_Result_T is begin Res.Append (Cursor); return Child_Visit_Continue; end Append_Child; + -- Start of processing for Get_Children + begin Visit_Children (N, Get_Children.Append_Child'Unrestricted_Access); return Res; @@ -190,6 +209,9 @@ package body Instrument.C_Utils is end if; return Child_Visit_Recurse; end Process; + + -- Start of processing for Get_Lambda_Exprs + begin Visit_Children (N, Process'Unrestricted_Access); return Res; @@ -223,6 +245,10 @@ package body Instrument.C_Utils is end; end Is_Unit_Of_Interest; + --------------- + -- To_Vector -- + --------------- + function To_Vector (N : Cursor_T) return Cursor_Vectors.Vector is Res : Cursor_Vectors.Vector; begin @@ -235,28 +261,36 @@ package body Instrument.C_Utils is -------------- function Get_Main (TU : Translation_Unit_T) return Cursor_T is - - Main_Decl_Cursor : Cursor_T := Get_Null_Cursor; + Result : Cursor_T := Get_Null_Cursor; function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T with Convention => C; + -- Callback for Visit_Children. Set Result and break the iteration if + -- Cursor is the "main" function definition, continue the iteration to + -- find the main otherwise. - function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T - is + ---------------- + -- Visit_Decl -- + ---------------- + + function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T is begin if Kind (Cursor) = Cursor_Translation_Unit then return Child_Visit_Recurse; end if; if Cursor_Get_Mangling (Cursor) = "main" then - Main_Decl_Cursor := Cursor; + Result := Cursor; return Child_Visit_Break; end if; return Child_Visit_Continue; end Visit_Decl; + + -- Start of processing for Get_Main + begin Visit_Children (Parent => Get_Translation_Unit_Cursor (TU), Visitor => Visit_Decl'Unrestricted_Access); - return Main_Decl_Cursor; + return Result; end Get_Main; -- Rewriting utilities @@ -268,20 +302,23 @@ package body Instrument.C_Utils is procedure Add_Statement_In_Main (TU : Translation_Unit_T; Rew : Rewriter_T; - Statement : String) is - + Statement : String) + is function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T with Convention => C; -- Traverse the tree until the main function is found, and insert a -- statement. - function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T - is + ---------------- + -- Visit_Decl -- + ---------------- + + function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T is begin if Kind (Cursor) = Cursor_Translation_Unit then return Child_Visit_Recurse; - end if; - if Cursor_Get_Mangling (Cursor) = "main" then + + elsif Cursor_Get_Mangling (Cursor) = "main" then declare Fun_Children : constant Vector := Get_Children (Cursor); Body_Cursor : constant Cursor_T := @@ -303,9 +340,14 @@ package body Instrument.C_Utils is Insert => Statement); end; return Child_Visit_Break; + + else + return Child_Visit_Continue; end if; - return Child_Visit_Continue; end Visit_Decl; + + -- Start of processing for Add_Statement_In_Main + begin Visit_Children (Parent => Get_Translation_Unit_Cursor (TU), Visitor => Visit_Decl'Unrestricted_Access); @@ -443,6 +485,8 @@ package body Instrument.C_Utils is procedure Print_Tokens (TU : Translation_Unit_T; N : Cursor_T) is procedure Put_Token (Tok : Token_T); + -- Callback for Iterate_Tokens. Put the spelling of Tok on the standard + -- output. --------------- -- Put_Token -- @@ -452,6 +496,9 @@ package body Instrument.C_Utils is begin Put (Get_Token_Spelling (TU, Tok)); end Put_Token; + + -- Start of processing for Print_Tokens + begin Iterate_Tokens (TU, N, Put_Token'Access); New_Line; diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 494c08d4f..eb979cfb9 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -33,9 +33,9 @@ package Instrument.C_Utils is type Cursor_Visitor_Function is access function (Node : Cursor_T) return Child_Visit_Result_T with Convention => C; - ------------------------- - -- Location utilities -- - ------------------------- + ------------------------ + -- Location utilities -- + ------------------------ function Sloc (Loc : Source_Location_T) return Local_Source_Location; -- Convert a Source_Location_T to a Source_Location @@ -53,8 +53,7 @@ package Instrument.C_Utils is -- Return True if the node N is a null cursor, false otherwise procedure Visit_Children - (Parent : Cursor_T; - Visitor : Cursor_Visitor_Function); + (Parent : Cursor_T; Visitor : Cursor_Visitor_Function); -- Wrapper for the Visit_Children clang procedure procedure Visit (Parent : Cursor_T; Visitor : Cursor_Visitor_Function); @@ -90,8 +89,12 @@ package Instrument.C_Utils is -- Turn the node N into a single element node vector function Get_Main (TU : Translation_Unit_T) return Cursor_T; + -- Return the cursor corresponding to the definition of the "main" + -- function, or the null cursor if there is no main function. - -- Rewriting utilities + ------------------------- + -- Rewriting utilities -- + ------------------------- procedure Add_Statement_In_Main (TU : Translation_Unit_T; @@ -151,7 +154,9 @@ package Instrument.C_Utils is Process : not null access procedure (Tok : Token_T)); -- Call Process on all of the tokens within the source range of N - -- Debugging + --------------- + -- Debugging -- + --------------- procedure Print_Tokens (TU : Translation_Unit_T; N : Cursor_T); -- Print the tokens associated to the given node From 89329ff002e5e4b782641c2363ab6fe34d1a4d33 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Sep 2022 13:18:30 +0000 Subject: [PATCH 0010/1483] Instrument.C_Utils: use anonymous functions as callbacks Expose anonymous functions with Ada convention as callbacks for the Visit and Visit_Children procedures. This also avoids the use of 'Unrestricted_Access. TN: V916-015 Change-Id: If8abd7d5cc8e23b74d230d5992e6fd525fccc8ef --- tools/gnatcov/instrument-c.adb | 23 ++---- tools/gnatcov/instrument-c_utils.adb | 118 +++++++++++---------------- tools/gnatcov/instrument-c_utils.ads | 9 +- 3 files changed, 64 insertions(+), 86 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 2e5a0740b..73b63f204 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -1327,8 +1327,7 @@ package body Instrument.C is -- output for the complex decision. It process the suboperands of the -- decision looking for nested decisions. - function Process_Node (N : Cursor_T) return Child_Visit_Result_T - with Convention => C; + function Process_Node (N : Cursor_T) return Child_Visit_Result_T; -- Processes one node in the traversal, looking for logical operators, -- and if one is found, outputs the appropriate table entries. @@ -1581,7 +1580,7 @@ package body Instrument.C is return; end if; Hash_Entries.Init; - Visit (N, Process_Node'Unrestricted_Access); + Visit (N, Process_Node'Access); Hash_Entries.Free; end Process_Decisions; @@ -1609,8 +1608,7 @@ package body Instrument.C is function Has_Decision (T : Cursor_T) return Boolean is - function Visitor (N : Cursor_T) return Child_Visit_Result_T - with Convention => C; + function Visitor (N : Cursor_T) return Child_Visit_Result_T; -- If N's kind indicates the presence of a decision, return -- Child_Visit_Break, otherwise return Child_Visit_Recurse. -- @@ -1645,7 +1643,7 @@ package body Instrument.C is -- Start of processing for Has_Decision begin - Visit (T, Visitor'Unrestricted_Access); + Visit (T, Visitor'Access); return Has_Decision; end Has_Decision; @@ -3318,8 +3316,7 @@ package body Instrument.C is when Main_End | Ravenscar_Task_Termination => declare function Process - (Cursor : Cursor_T) return Child_Visit_Result_T - with Convention => C; + (Cursor : Cursor_T) return Child_Visit_Result_T; -- Callback for Visit_Children. Insert calls to dump buffers -- before the function return. @@ -3398,9 +3395,8 @@ package body Instrument.C is end Process; begin - Visit_Children - (Parent => Get_Main (Rew.TU), - Visitor => Process'Unrestricted_Access); + Visit_Children (Parent => Get_Main (Rew.TU), + Visitor => Process'Access); end; when At_Exit => @@ -3578,8 +3574,7 @@ package body Instrument.C is is Location : Source_Location_T := Get_Null_Location; - function Visit_Decl - (Cursor : Cursor_T) return Child_Visit_Result_T with Convention => C; + function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T; -- Callback for Visit_Children ---------------- @@ -3608,7 +3603,7 @@ package body Instrument.C is begin Visit_Children (Parent => Get_Translation_Unit_Cursor (TU), - Visitor => Visit_Decl'Unrestricted_Access); + Visitor => Visit_Decl'Access); return Location; end Find_First_Insert_Location; diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index 1a63f6af1..00e9115d9 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -29,6 +29,19 @@ package body Instrument.C_Utils is use Cursor_Vectors; + function Visitor_Wrapper + (Node : Cursor_T; + Parent : Cursor_T; + Client_Data : Client_Data_T) return Child_Visit_Result_T + with Convention => C; + -- Helper for Visit_Children and Visit procedures. + -- + -- Interpret Client_Data as the Visitor anonymous function for these + -- procedures and call it on Node. + -- + -- Note: this has convention C in order to be a callback for the + -- Clang.Index.Visit_Children and Clang.Index.Visit functions. + ---------- -- Sloc -- ---------- @@ -78,42 +91,34 @@ package body Instrument.C_Utils is return Cursor_Is_Null (N); end Is_Null; + --------------------- + -- Visitor_Wrapper -- + --------------------- + + function Visitor_Wrapper + (Node : Cursor_T; + Parent : Cursor_T; + Client_Data : Client_Data_T) return Child_Visit_Result_T + is + pragma Unreferenced (Parent); + Callback : access function + (Node : Cursor_T) return Child_Visit_Result_T + with Import, Address => System.Address (Client_Data); + begin + return Callback.all (Node); + end Visitor_Wrapper; + -------------------- -- Visit_Children -- -------------------- procedure Visit_Children - (Parent : Cursor_T; Visitor : Cursor_Visitor_Function) + (Parent : Cursor_T; + Visitor : not null access function + (Node : Cursor_T) return Child_Visit_Result_T) is - function Visitor_Wrapper - (Node : Cursor_T; - Parent : Cursor_T; - Client_Data : Client_Data_T) return Child_Visit_Result_T - with Convention => C; - -- Callback for Clang.Index.Visit_Children. Just a wrapper around - -- Visitor. - - --------------------- - -- Visitor_Wrapper -- - --------------------- - - function Visitor_Wrapper - (Node : Cursor_T; - Parent : Cursor_T; - Client_Data : Client_Data_T) return Child_Visit_Result_T - is - pragma Unreferenced (Parent, Client_Data); - begin - return Visitor (Node); - end Visitor_Wrapper; - Dummy : constant unsigned := Visit_Children - (Parent, - Visitor_Wrapper'Unrestricted_Access, - Client_Data_T (System.Null_Address)); - - -- Start of processing for Visit_Children - + (Parent, Visitor_Wrapper'Access, Client_Data_T (Visitor'Address)); begin null; end Visit_Children; @@ -122,36 +127,13 @@ package body Instrument.C_Utils is -- Visit -- ----------- - procedure Visit (Parent : Cursor_T; Visitor : Cursor_Visitor_Function) is - function Visitor_Wrapper - (Node : Cursor_T; - Parent : Cursor_T; - Client_Data : Client_Data_T) return Child_Visit_Result_T - with Convention => C; - -- Callback for Clang.Index.Visit_Children. Just a wrapper around - -- Visitor. - - --------------------- - -- Visitor_Wrapper -- - --------------------- - - function Visitor_Wrapper - (Node : Cursor_T; - Parent : Cursor_T; - Client_Data : Client_Data_T) return Child_Visit_Result_T - is - pragma Unreferenced (Parent, Client_Data); - begin - return Visitor (Node); - end Visitor_Wrapper; - + procedure Visit + (Parent : Cursor_T; + Visitor : not null access function + (Node : Cursor_T) return Child_Visit_Result_T) + is Dummy : constant unsigned := Visit - (Parent, - Visitor_Wrapper'Unrestricted_Access, - Client_Data_T (System.Null_Address)); - - -- Start of processing for Visit - + (Parent, Visitor_Wrapper'Access, Client_Data_T (Visitor'Address)); begin null; end Visit; @@ -163,8 +145,7 @@ package body Instrument.C_Utils is function Get_Children (N : Cursor_T) return Cursor_Vectors.Vector is Res : Vector; - function Append_Child (Cursor : Cursor_T) return Child_Visit_Result_T - with Convention => C; + function Append_Child (Cursor : Cursor_T) return Child_Visit_Result_T; -- Callback for Visit_Children. Append Cursor to Res and continue the -- traversal. @@ -181,7 +162,7 @@ package body Instrument.C_Utils is -- Start of processing for Get_Children begin - Visit_Children (N, Get_Children.Append_Child'Unrestricted_Access); + Visit_Children (N, Get_Children.Append_Child'Access); return Res; end Get_Children; @@ -192,8 +173,7 @@ package body Instrument.C_Utils is function Get_Lambda_Exprs (N : Cursor_T) return Cursor_Vectors.Vector is Res : Vector; - function Process (Cursor : Cursor_T) return Child_Visit_Result_T - with Convention => C; + function Process (Cursor : Cursor_T) return Child_Visit_Result_T; -- Helper for Visit_Children. Add every lambda expr under Cursor to Res, -- _but_ the lambda expressions nested in other lambda expressions. @@ -213,7 +193,7 @@ package body Instrument.C_Utils is -- Start of processing for Get_Lambda_Exprs begin - Visit_Children (N, Process'Unrestricted_Access); + Visit_Children (N, Process'Access); return Res; end Get_Lambda_Exprs; @@ -263,8 +243,7 @@ package body Instrument.C_Utils is function Get_Main (TU : Translation_Unit_T) return Cursor_T is Result : Cursor_T := Get_Null_Cursor; - function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T - with Convention => C; + function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T; -- Callback for Visit_Children. Set Result and break the iteration if -- Cursor is the "main" function definition, continue the iteration to -- find the main otherwise. @@ -289,7 +268,7 @@ package body Instrument.C_Utils is begin Visit_Children (Parent => Get_Translation_Unit_Cursor (TU), - Visitor => Visit_Decl'Unrestricted_Access); + Visitor => Visit_Decl'Access); return Result; end Get_Main; @@ -304,8 +283,7 @@ package body Instrument.C_Utils is Rew : Rewriter_T; Statement : String) is - function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T - with Convention => C; + function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T; -- Traverse the tree until the main function is found, and insert a -- statement. @@ -350,7 +328,7 @@ package body Instrument.C_Utils is begin Visit_Children (Parent => Get_Translation_Unit_Cursor (TU), - Visitor => Visit_Decl'Unrestricted_Access); + Visitor => Visit_Decl'Access); end Add_Statement_In_Main; -------------------------------- diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index eb979cfb9..2bdca03f0 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -53,10 +53,15 @@ package Instrument.C_Utils is -- Return True if the node N is a null cursor, false otherwise procedure Visit_Children - (Parent : Cursor_T; Visitor : Cursor_Visitor_Function); + (Parent : Cursor_T; + Visitor : not null access function + (Node : Cursor_T) return Child_Visit_Result_T); -- Wrapper for the Visit_Children clang procedure - procedure Visit (Parent : Cursor_T; Visitor : Cursor_Visitor_Function); + procedure Visit + (Parent : Cursor_T; + Visitor : not null access function + (Node : Cursor_T) return Child_Visit_Result_T); -- Wrapper for the Visit clang procedure function Get_Children (N : Cursor_T) return Cursor_Vectors.Vector; From 0c9cb7ae85fd92c2c184170166846ed3cddd2019 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 27 Sep 2022 17:57:06 +0200 Subject: [PATCH 0011/1483] Fix build with C_SUPPORT=False Adapt the stub after Instrument.C specification changes. Change-Id: I548d8f04093b8bb77c705f25d939e5fd86952972 TN: V927-039 --- tools/gnatcov/instrument-c__stub.adb | 65 ++++++++++++---------------- tools/gnatcov/instrument-c__stub.ads | 61 +++++++++++++++++--------- 2 files changed, 68 insertions(+), 58 deletions(-) diff --git a/tools/gnatcov/instrument-c__stub.adb b/tools/gnatcov/instrument-c__stub.adb index 9aedfb7c9..6b340c13b 100644 --- a/tools/gnatcov/instrument-c__stub.adb +++ b/tools/gnatcov/instrument-c__stub.adb @@ -21,61 +21,52 @@ package body Instrument.C is Error_Msg : constant String := "GNATcoverage not built with C support."; - --------------------------- - -- Add_Auto_Dump_Buffers -- - --------------------------- + ---------------------- + -- Skip_Source_File -- + ---------------------- - procedure Add_Auto_Dump_Buffers - (IC : Inst_Context; - Info : in out Project_Info; - Main : Compilation_Unit_Name; - Rew : C_Source_Rewriter) is - begin - raise Program_Error with Error_Msg; - end Add_Auto_Dump_Buffers; + function Skip_Source_File + (Self : C_Family_Instrumenter_Type; + Source_File : GNATCOLL.Projects.File_Info) return Boolean + is (raise Program_Error with Error_Msg); - ----------- - -- Apply -- - ----------- + --------------------- + -- Instrument_Unit -- + --------------------- - procedure Apply (Self : in out C_Source_Rewriter) is + procedure Instrument_Unit + (Self : C_Family_Instrumenter_Type; + CU_Name : Compilation_Unit_Name; + IC : in out Inst_Context; + Unit_Info : in out Instrumented_Unit_Info) is begin raise Program_Error with Error_Msg; - end Apply; + end Instrument_Unit; - --------------------- - -- Start_Rewriting -- - --------------------- + ------------------------------- + -- Auto_Dump_Buffers_In_Main -- + ------------------------------- - procedure Start_Rewriting - (Self : out C_Source_Rewriter; - Info : in out Project_Info; - Input_Filename : String) is + procedure Auto_Dump_Buffers_In_Main + (Self : C_Family_Instrumenter_Type; + IC : in out Inst_Context; + Main : Compilation_Unit_Name; + Filename : String; + Info : in out Project_Info) is begin raise Program_Error with Error_Msg; - end Start_Rewriting; + end Auto_Dump_Buffers_In_Main; ---------------------------- -- Emit_Buffers_List_Unit -- ---------------------------- procedure Emit_Buffers_List_Unit - (IC : in out Inst_Context; + (Self : C_Family_Instrumenter_Type; + IC : in out Inst_Context; Root_Project_Info : in out Project_Info) is begin raise Program_Error with Error_Msg; end Emit_Buffers_List_Unit; - --------------------- - -- Instrument_Unit -- - --------------------- - - procedure Instrument_Unit - (CU_Name : Compilation_Unit_Name; - IC : in out Inst_Context; - Unit_Info : in out Instrumented_Unit_Info) is - begin - raise Program_Error with Error_Msg; - end Instrument_Unit; - end Instrument.C; diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index ca5282f1e..eab924d79 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -24,38 +24,57 @@ -- units, using the procedures defined here, which will result in a crash (all -- the procedures are empty stubs raising an error). +with GNATCOLL.Projects; use GNATCOLL.Projects; + with Instrument.Base_Types; use Instrument.Base_Types; with Instrument.Common; use Instrument.Common; +with Switches; use Switches; private package Instrument.C is - type C_Source_Decision is null record; - type C_Source_Condition is null record; + type C_Family_Instrumenter_Type is + abstract new Language_Instrumenter with null record; + -- Common instrumentation primitives for C/C++ - type C_Unit_Inst_Context is null record; + overriding function Skip_Source_File + (Self : C_Family_Instrumenter_Type; + Source_File : GNATCOLL.Projects.File_Info) return Boolean; - type C_Source_Rewriter is tagged limited null record; + overriding procedure Instrument_Unit + (Self : C_Family_Instrumenter_Type; + CU_Name : Compilation_Unit_Name; + IC : in out Inst_Context; + Unit_Info : in out Instrumented_Unit_Info); - procedure Add_Auto_Dump_Buffers - (IC : Inst_Context; - Info : in out Project_Info; - Main : Compilation_Unit_Name; - Rew : C_Source_Rewriter); + overriding procedure Auto_Dump_Buffers_In_Main + (Self : C_Family_Instrumenter_Type; + IC : in out Inst_Context; + Main : Compilation_Unit_Name; + Filename : String; + Info : in out Project_Info); - procedure Apply (Self : in out C_Source_Rewriter); + overriding procedure Emit_Buffers_List_Unit + (Self : C_Family_Instrumenter_Type; + IC : in out Inst_Context; + Root_Project_Info : in out Project_Info); - procedure Start_Rewriting - (Self : out C_Source_Rewriter; - Info : in out Project_Info; - Input_Filename : String); + type C_Instrumenter_Type is + new C_Family_Instrumenter_Type with null record; + -- Instrumentation primitives for C - procedure Emit_Buffers_List_Unit - (IC : in out Inst_Context; - Root_Project_Info : in out Project_Info); + overriding function Language + (Self : C_Instrumenter_Type) return Src_Supported_Language + is (C_Language); - procedure Instrument_Unit - (CU_Name : Compilation_Unit_Name; - IC : in out Inst_Context; - Unit_Info : in out Instrumented_Unit_Info); + type CPP_Instrumenter_Type is + new C_Family_Instrumenter_Type with null record; + -- Instrumentation primitives for C++ + + overriding function Language + (Self : CPP_Instrumenter_Type) return Src_Supported_Language + is (CPP_Language); + + C_Instrumenter : aliased constant C_Instrumenter_Type := (null record); + CPP_Instrumenter : aliased constant CPP_Instrumenter_Type := (null record); end Instrument.C; From 3980e843b506f47bab765011cac9f2b200aaf115 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 28 Sep 2022 13:54:17 +0000 Subject: [PATCH 0012/1483] gpr_stubs/libclang.gpr: fix a gprbuild warning about missing Ada sources TN: V927-039 Change-Id: I06bd29a5e0083c149df11e8f1e667086193140da --- tools/gnatcov/gpr_stubs/libclang.gpr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/gpr_stubs/libclang.gpr b/tools/gnatcov/gpr_stubs/libclang.gpr index c960014af..3f2f11c9e 100644 --- a/tools/gnatcov/gpr_stubs/libclang.gpr +++ b/tools/gnatcov/gpr_stubs/libclang.gpr @@ -1,3 +1,3 @@ project Libclang is - for Source_Dirs use ("."); + for Languages use (); end Libclang; From 3bb3bc79e4e5f7bc958f350cd45172aee80ad12b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 28 Sep 2022 13:55:57 +0000 Subject: [PATCH 0013/1483] gnatcov.gpr: minor refactorings Fix casing coding style issues and use "CPP" to designate C++, like in the rest of the codebase. TN: V927-039 Change-Id: I36a21873862a79de6241ffc9c0843d70664f9e51 --- tools/gnatcov/gnatcov.gpr | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index e552c03ce..6a54b2336 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -50,47 +50,47 @@ project Gnatcov is package Compiler is - ada_common_switches := + Ada_Common_Switches := ("-gnat12", "-gnatwa", "-gnatyg"); - c_common_switches := + C_Common_Switches := ("-DTARGET_BITS=" & Bits, "-Wall", "-Wextra", "-std=c99", "-I" & Binutils_Build_Dir & "/bfd", "-I" & Binutils_Src_Dir & "/include", "-I" & Binutils_Src_Dir & "/bfd"); - mode_switches := (); - ada_mode_switches := (); - c_mode_switches := (); - cxx_mode_switches := (); + Mode_Switches := (); + Ada_Mode_Switches := (); + C_Mode_Switches := (); + CPP_Mode_Switches := (); case Build_Mode is when "dev" => - mode_switches := ("-O0", "-g"); - ada_mode_switches := ("-gnata"); - c_mode_switches := ("-Werror"); - cxx_mode_switches := ("-Werror"); + Mode_Switches := ("-O0", "-g"); + Ada_Mode_Switches := ("-gnata"); + C_Mode_Switches := ("-Werror"); + CPP_Mode_Switches := ("-Werror"); when "prod" => - mode_switches := ("-O2"); - c_mode_switches := ("-DNDEBUG"); - cxx_mode_switches := ("-DNDEBUG"); + Mode_Switches := ("-O2"); + C_Mode_Switches := ("-DNDEBUG"); + CPP_Mode_Switches := ("-DNDEBUG"); when "boot" => - mode_switches := + Mode_Switches := ("-O1", "-fdump-scos", "-fpreserve-control-flow", "-g"); - c_mode_switches := ("-DNDEBUG"); - cxx_mode_switches := ("-DNDEBUG"); + C_Mode_Switches := ("-DNDEBUG"); + CPP_Mode_Switches := ("-DNDEBUG"); end case; for Default_Switches ("ada") - use ada_common_switches & mode_switches & ada_mode_switches; + use Ada_Common_Switches & Mode_Switches & Ada_Mode_Switches; for Default_Switches ("C") - use c_common_switches & mode_switches & c_mode_switches; + use C_Common_Switches & Mode_Switches & C_Mode_Switches; for Default_Switches ("C++") - use mode_switches & cxx_mode_switches; + use Mode_Switches & CPP_Mode_Switches; for Local_Configuration_Pragmas use "gnat.adc"; From 46d12ea22064d9ba4bf0079447f3c8b9eb66ea5c Mon Sep 17 00:00:00 2001 From: Leo Creuse Date: Mon, 12 Sep 2022 18:03:17 +0200 Subject: [PATCH 0014/1483] Document exemptions as comment markers for C Change-Id: Ibdfafa9d0e60ec6a62e0a44ac83b8cbeb5c21338 TN: V802-023 --- doc/gnatcov/exemptions.rst | 48 ++++++++++++++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/doc/gnatcov/exemptions.rst b/doc/gnatcov/exemptions.rst index ee871b93c..c3c59d8a9 100644 --- a/doc/gnatcov/exemptions.rst +++ b/doc/gnatcov/exemptions.rst @@ -13,9 +13,10 @@ Defining :term:`Exemption Regions ` ===================================================== :dfn:`Exemption regions` are lexical sections of sources in which coverage -violations are expected and can be justified. For Ada with the |gnat| -compilers, regions are defined by the insertion of dedicated pragmas in the -sources: +violations are expected and can be justified. + +For Ada with the |gnat| compilers, regions are defined by the insertion of +dedicated pragmas in the sources: - ``pragma Annotate (Xcov, Exempt_On, "justification text");`` starts a region, providing some justification text that will be recalled in coverage @@ -42,13 +43,52 @@ We expect never to reach here with ``T`` False, so we declare an exemption region to state that coverage violations across this region are expected and not a testing campaign deficiency. +For C code, exemptions are only supported with +:term:`source traces` and are defined using comment markers to +delimit the exempted regions: + +- Any comment containing the string ``GNATCOV_EXEMPT_ON`` followed by a string + in double quotes starts a region, the string within the double quotes being + used as justification text that will be recalled in coverage reports. + +- Any comment containing the string ``GNATCOV_EXEMPT_OFF`` closes the current + exemption region. + +The following assert function illustrates the definition of an exemption +block: + +.. code-block:: C + + void + assert (bool x){ + // GNATCOV_EXEMPT_ON "assert condition is never false" + if (!x) + abort(); + // GNATCOV_EXEMPT_OFF + } + +As in the first example, we never expect to reach this function with x false, +so an exemption region is declared to state that all coverage violations +within the region are expected. + +An exemption comment marker may not intersect any coverage obligation, +such as a statement or a decision, as in the following example attempting +to exempt a decision only partially: + +.. code-block:: C + + if(a && /*GNATCOV_EXEMPT_ON "justification"*/ b /*GNATCOV_EXEMPT_OFF*/){ + ... + } + +Such markers are ignored by |gcvins|, after emitting a warning. Reporting about coverage exemptions =================================== Exempted regions are reported as blocks in both the annotated source and the synthetic text reports, for both source and object coverage metrics. In -annotated source reports, a ``#`` or ``*`` caracter annotates all the exempted +annotated source reports, a ``#`` or ``*`` character annotates all the exempted lines, depending on whether 0 or at least 1 violation was exempted over the whole section, respectively. For our ``Eassert`` example above, a typical :cmd-option:`=xcov` output for :cmd-option:`stmt+decision` coverage for would From 4dc2a56dc4abd92f3c77b74046acd825c4f365ca Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 27 Jun 2022 16:08:42 +0200 Subject: [PATCH 0015/1483] annotations-dhtml.adb: always fill a non-empty project name The Project_Name function can return an empty string if the given source could not be attached to any project of the tree. As we always want to fill the "project" field (otherwise, the report will be buggy), let's fallback to a default of "Other sources" in that case. This case can happen when "gnatcov coverage" loads a copy of the project that was passed to "gnatcov instrument": as absolute names for source files in the original project are recorded in SID files, "gnatcov coverage" fails to relate these sources to the copied project, as its own sources have different absolute names. Change-Id: I18eb0a2cf9e1af1b9e7e5869208eceac6cf09734 TN: V627-017 --- tools/gnatcov/annotations-dynamic_html.adb | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index f52c48030..6ae54def2 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -430,11 +430,20 @@ package body Annotations.Dynamic_Html is Source.Set_Field ("liStats", Line_Stats); Source.Set_Field ("enAllStats", To_JSON (Info.Ob_Stats)); - if Switches.Root_Project /= null then - Source.Set_Field ("project", Project_Name (Info.Full_Name.all)); - else - Source.Set_Field ("project", "Other Sources"); - end if; + declare + P_Name : constant String := + (if Switches.Root_Project /= null + then Project_Name (Info.Full_Name.all) + else ""); + -- Note that P_Name can be "" here either because we don't have a + -- root project at all or because we were unable to find the project + -- to which the source pertains. + + begin + Source.Set_Field + ("project", + (if P_Name /= "" then P_Name else "Other Sources")); + end; Pp.Current_Source := Source; end Pretty_Print_Start_File; From a053d26a69d40c5163124c0470e88e58dff39a54 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 22 Sep 2022 15:19:47 +0000 Subject: [PATCH 0016/1483] Instrument: allow explicit list of mains on the command-line While so far "gnatcov instrument" rejected all positional arguments, it now takes, like gprbuild, a list of source files. When this list is not empty, these source files are considered as mains regardless of the "for Main" clauses in GPR files. Change-Id: Id65ef64095e11199cc1752b1417fbf7af0fa4566 TN: V911-003 --- tools/gnatcov/gnatcov_bits_specific.adb | 13 +++--- tools/gnatcov/instrument-ada_unit.adb | 1 - tools/gnatcov/instrument-base_types.adb | 1 - tools/gnatcov/instrument-c.ads | 1 - tools/gnatcov/instrument-common.ads | 1 - tools/gnatcov/instrument-input_traces.adb | 1 - tools/gnatcov/instrument.adb | 52 ++++++++++++++++++++--- tools/gnatcov/instrument.ads | 9 +++- tools/gnatcov/instrument__stub.adb | 3 +- tools/gnatcov/switches.adb | 18 +++++++- tools/gnatcov/switches.ads | 3 ++ 11 files changed, 79 insertions(+), 24 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index f53df8bd3..5c64750da 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -997,12 +997,6 @@ procedure GNATcov_Bits_Specific is & " (--level=" & Source_Level_Options ("|") & ")"); end if; - if Args.Remaining_Args.Length > 0 then - Fatal_Error - ("Invalid extra argument: " - & (+Args.Remaining_Args.First_Element)); - end if; - if Args.String_Args (Opt_Path_Count_Limit).Present then declare Limit : Positive; @@ -1278,6 +1272,10 @@ begin -- Matcher for the source files to ignore Language_Version : Any_Language_Version; + + Mains : String_Vectors.Vector renames Args.Remaining_Args; + -- Treat remaining command line arguments as a list of source + -- files to be processed as mains. begin Create_Matcher (Ignored_Source_Files, Matcher, Has_Matcher); @@ -1329,7 +1327,8 @@ begin (Dump_Config => Dump_Config, Language_Version => Language_Version, Ignored_Source_Files => - (if Has_Matcher then Matcher'Access else null)); + (if Has_Matcher then Matcher'Access else null), + Mains => Mains); end; when Cmd_Scan_Objects => diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index d0686ccd8..31080b8fc 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -45,7 +45,6 @@ with Outputs; use Outputs; with SCOs; with Slocs; with Snames; use Snames; -with Strings; use Strings; with Table; with Text_Files; use Text_Files; diff --git a/tools/gnatcov/instrument-base_types.adb b/tools/gnatcov/instrument-base_types.adb index c8b64b9f8..bf513eae8 100644 --- a/tools/gnatcov/instrument-base_types.adb +++ b/tools/gnatcov/instrument-base_types.adb @@ -22,7 +22,6 @@ with Interfaces; use Interfaces; with GNATCOLL.VFS; with Hex_Images; use Hex_Images; -with Strings; use Strings; package body Instrument.Base_Types is diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 25bf041a5..a9d7e3cf8 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -35,7 +35,6 @@ with Instrument.Base_Types; use Instrument.Base_Types; with Instrument.Common; use Instrument.Common; with SC_Obligations; use SC_Obligations; with Slocs; use Slocs; -with Strings; use Strings; with Switches; use Switches; package Instrument.C is diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 8391052c5..9a2ffb62a 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -71,7 +71,6 @@ with Instrument.Base_Types; use Instrument.Base_Types; with Namet; use Namet; with SC_Obligations; use SC_Obligations; with Slocs; use Slocs; -with Strings; use Strings; with Switches; use Switches; with Text_Files; with Types; use Types; diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index bfad8c1de..b9e2215cc 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -34,7 +34,6 @@ with GNATCOLL.Projects; use GNATCOLL.Projects; with Traces_Source; use Traces_Source; with Hex_Images; -with Strings; use Strings; with Outputs; package body Instrument.Input_Traces is diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 78b02d924..a1e268155 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -51,7 +51,6 @@ with Outputs; with Paths; use Paths; with Project; with SC_Obligations; -with Strings; use Strings; with Switches; use Switches; package body Instrument is @@ -304,7 +303,8 @@ package body Instrument is procedure Instrument_Units_Of_Interest (Dump_Config : Any_Dump_Config; Language_Version : Any_Language_Version; - Ignored_Source_Files : access GNAT.Regexp.Regexp) + Ignored_Source_Files : access GNAT.Regexp.Regexp; + Mains : String_Vectors.Vector) is use Libadalang.Analysis; @@ -472,12 +472,50 @@ package body Instrument is -- for coverage analysis. if Dump_Config.Trigger /= Manual then - for Lang in Src_Supported_Language loop - for Main of Project.Enumerate_Mains (Lang) loop - Register_Main_To_Instrument - (IC, Mains_To_Instrument (Lang), Main.File, Main.Project); + + -- If no source file was specified on the command line to be a main, + -- use the list of mains specified in project files. + + if Mains.Is_Empty then + for Lang in Src_Supported_Language loop + for Main of Project.Enumerate_Mains (Lang) loop + Register_Main_To_Instrument + (IC, Mains_To_Instrument (Lang), Main.File, Main.Project); + end loop; end loop; - end loop; + + -- Otherwise, make sure we can find the source file of each main in + -- the project tree and that we can instrument them (supported + -- language). + + else + for Filename of Mains loop + declare + use GNATCOLL.VFS; + + F : constant String := +Filename; + Info : constant File_Info := + Project.Project.Root_Project.Create_From_Project (+F); + File : constant Virtual_File := Info.File; + Project : constant Project_Type := Info.Project; + Lang : Any_Language; + begin + if File = No_File or else Project = No_Project then + Outputs.Fatal_Error ("No such source file: " & F); + end if; + + Lang := To_Language_Or_All (Info.Language); + if Lang not in Src_Supported_Language then + Outputs.Fatal_Error + ("Cannot instrument main source file (unsupported" + & " language): " & F); + end if; + + Register_Main_To_Instrument + (IC, Mains_To_Instrument (Lang), File, Project); + end; + end loop; + end if; end if; -- Know that we know all the sources we need to instrument, prepare diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 923293937..51049d2d1 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -22,6 +22,8 @@ with Ada.Strings.Unbounded; with GNAT.Regexp; +with Strings; use Strings; + package Instrument is package US renames Ada.Strings.Unbounded; @@ -83,7 +85,8 @@ package Instrument is procedure Instrument_Units_Of_Interest (Dump_Config : Any_Dump_Config; Language_Version : Any_Language_Version; - Ignored_Source_Files : access GNAT.Regexp.Regexp); + Ignored_Source_Files : access GNAT.Regexp.Regexp; + Mains : String_Vectors.Vector); -- Generate instrumented sources for the source files of all units of -- interest. Also save mappings between coverage buffers and SCOs for each -- library units to SID files (one per library unit). @@ -99,5 +102,7 @@ package Instrument is -- -- If Ignored_Source_File is non-null, ignore files whose names match the -- accessed pattern. - + -- + -- Mains is the list of source files that were listed on the command line: + -- if non-empty, they replace the mains specified in project files. end Instrument; diff --git a/tools/gnatcov/instrument__stub.adb b/tools/gnatcov/instrument__stub.adb index 698711e28..e56a101ef 100644 --- a/tools/gnatcov/instrument__stub.adb +++ b/tools/gnatcov/instrument__stub.adb @@ -53,7 +53,8 @@ package body Instrument is procedure Instrument_Units_Of_Interest (Dump_Config : Any_Dump_Config; Language_Version : Any_Language_Version; - Ignored_Source_Files : access GNAT.Regexp.Regexp) is + Ignored_Source_Files : access GNAT.Regexp.Regexp; + Mains : String_Vectors.Vector) is begin raise Program_Error with Msg; end Instrument_Units_Of_Interest; diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index d1702c1bd..7d4dd64d6 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -193,6 +193,20 @@ package body Switches is ----------------- function To_Language (Name : String) return Some_Language is + Result : constant Any_Language := To_Language_Or_All (Name); + begin + if Result = All_Languages then + Fatal_Error ("Unsupported language: " & Name); + else + return Result; + end if; + end To_Language; + + ------------------------ + -- To_Language_Or_All -- + ------------------------ + + function To_Language_Or_All (Name : String) return Any_Language is Lower_Name : constant String := To_Lower (Name); begin if Lower_Name = "ada" then @@ -202,9 +216,9 @@ package body Switches is elsif Lower_Name = "c++" then return CPP_Language; else - Fatal_Error ("Unsupported language: " & Name); + return All_Languages; end if; - end To_Language; + end To_Language_Or_All; ----------- -- Image -- diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index aad4ea843..cb3de1994 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -141,6 +141,9 @@ package Switches is -- Convert a human-readable language name to the corresponding enumeration -- value. Abort with a fatal error if Name is invalid. + function To_Language_Or_All (Name : String) return Any_Language; + -- Like To_Language, but return All_Languages if Name is invalid + function Image (Language : Some_Language) return String; -- Return a human-readable name for the given language From 416dd297f82a678d64d9abc67f6988c0eeccacea Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 3 Oct 2022 16:54:44 +0200 Subject: [PATCH 0017/1483] paths.adb: minor reformattings no-tn-check Change-Id: I6d965cd569272d3359793237b06a66db918ec493 --- tools/gnatcov/paths.adb | 42 +++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index a435d9ba5..c9c17e5bb 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -63,12 +63,12 @@ package body Paths is -- Canonicalize_Filename -- --------------------------- - function Canonicalize_Filename (Filename : String) return String - is + function Canonicalize_Filename (Filename : String) return String is + -- Start with a very basic normalization step as for globbing -- patterns. If we have a Windows path but are not on a Windows -- host, stop there as there's not much more we can reasonably - -- do. Otherwise, leave it to the GNAT runtime: + -- do. Otherwise, leave it to the GNAT runtime. Likely_Windows : constant Boolean := Likely_Windows_Path (Filename); @@ -76,7 +76,6 @@ package body Paths is (if Likely_Windows then Normalize_Windows_Pattern (Filename) else Filename); - begin if Likely_Windows and then not On_Windows then return Name; @@ -185,22 +184,34 @@ package body Paths is function Is_Absolute_Unix_Path (Path : String) return Boolean; function Is_Absolute_Windows_Path (Path : String) return Boolean; + -- Predicates to determine if Path looks like a Unix/Windows absolute + -- filename. + + --------------------------- + -- Is_Absolute_Unix_Path -- + --------------------------- function Is_Absolute_Unix_Path (Path : String) return Boolean is begin return Path'Length >= 1 and then Path (Path'First) = '/'; end Is_Absolute_Unix_Path; + ------------------------------ + -- Is_Absolute_Windows_Path -- + ------------------------------ + function Is_Absolute_Windows_Path (Path : String) return Boolean is begin - return (Path'Length >= 3 - and then Starts_With_Drive_Pattern (Path) - and then Path (Path'First + 2) in '\' | '/'); + return Path'Length >= 3 + and then Starts_With_Drive_Pattern (Path) + and then Path (Path'First + 2) in '\' | '/'; end Is_Absolute_Windows_Path; + -- Start of processing for Is_Absolute_Path + begin - return (Is_Absolute_Unix_Path (Path) - or else Is_Absolute_Windows_Path (Path)); + return Is_Absolute_Unix_Path (Path) + or else Is_Absolute_Windows_Path (Path); end Is_Absolute_Path; ------------------------- @@ -234,7 +245,7 @@ package body Paths is use Ada.Characters.Handling; Res : Unbounded_String; - Newchar : Character; + Newchar : Character; New_Is_Sep : Boolean; -- The new character we take from Pattern, and whether it -- is a dir separator. @@ -242,11 +253,8 @@ package body Paths is Last_Was_Sep : Boolean := False; -- Whether the last character we added to our result was a dir -- separator. - begin - for I in Pattern'Range loop - Newchar := (if Pattern (I) = '/' then '\' else Pattern (I)); New_Is_Sep := Newchar = '\'; @@ -254,12 +262,10 @@ package body Paths is Append (Res, To_Lower (Newchar)); Last_Was_Sep := New_Is_Sep; end if; - end loop; return To_String (Res); end; - end Normalize_Windows_Pattern; ------------------------------- @@ -268,9 +274,9 @@ package body Paths is function Starts_With_Drive_Pattern (Path : String) return Boolean is begin - return (Path'Length >= 2 - and then Path (Path'First) in 'A' .. 'Z' | 'a' .. 'z' - and then Path (Path'First + 1) = ':'); + return Path'Length >= 2 + and then Path (Path'First) in 'A' .. 'Z' | 'a' .. 'z' + and then Path (Path'First + 1) = ':'; end Starts_With_Drive_Pattern; end Paths; From c579bfa4d42c7ee1bcf97e656c788a7c9fe849b3 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 4 Oct 2022 11:36:27 +0200 Subject: [PATCH 0018/1483] files_table.adb: minor typo fix no-tn-check Change-Id: I66796a61506182311eda36928773a2b4fbd467be --- tools/gnatcov/files_table.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 33494b7d8..c267dd85a 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -2060,7 +2060,7 @@ package body Files_Table is FE := (Kind => Source_File, others => <>); if not Checkpoints.Version_Less (CLS, Than => 5) then - -- Dumping ingored source files is only supported from + -- Dumping ignored source files is only supported from -- Checkpoint version 5. FE.Ignore_Status := Any_Ignore_Status'Input (S); From 1a4e6d947a5c3d2b55d0b9bbd6adbcddb45ebfb6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 4 Oct 2022 15:07:22 +0000 Subject: [PATCH 0019/1483] SC_Obligations: fix loading of non-instrumented SCOs from checkpoints Move the code that loads the list of non-instrumented SCOs for a CU_Info before CU_Info.First_SCO and CU_Info.Last_SCO are relocated, as these are used as bound guards for the non-instrumented SCO that was just loaded from the checkpoint (and which thus was not relocated). For instance, suppose that we load the following CU_Info from a checkpoint: .First_SCO = 10 .Last_SCO = 20 and that after relocation, we have: .First_SCO = 110 .Last_SCO = 120 (because there are already 100 SCOs in gnatcov's internal tables) Then trying to load the non-instrumented SCO #15 will be discarded, as 15 is in range before relocation (10 .. 20), but is not in range anymore after relocation (110 .. 120). TN: VA04-023 Change-Id: I32c5958103bd6bc2bd26235e46b6e624073695db --- tools/gnatcov/sc_obligations.adb | 41 +++++++++++++++----------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 3d962445e..ca0967354 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -1156,6 +1156,25 @@ package body SC_Obligations is end; end loop; + -- If we have information about non instrumented units, import them as + -- is. Only import SCOs that belong to this CU, as others SCOs might + -- belong to a CU already present in the current execution, and which + -- would not be simply imported as is. + + if not Version_Less (S, Than => 9) then + for SCO of CP_Vectors.Non_Instr_SCOs loop + if SCO in CP_CU.First_SCO .. CP_CU.Last_SCO then + Non_Instr_SCOs.Insert (Remap_SCO_Id (Relocs, SCO)); + end if; + end loop; + + for SCO of CP_Vectors.Non_Instr_MCDC_SCOs loop + if SCO in CP_CU.First_SCO .. CP_CU.Last_SCO then + Non_Instr_MCDC_SCOs.Insert (Remap_SCO_Id (Relocs, SCO)); + end if; + end loop; + end if; + -- Perform final fixups and insert CU CP_CU.Last_Instance := @@ -1181,28 +1200,6 @@ package body SC_Obligations is if CLS.Purpose = Instrumentation then Coverage.Source.Initialize_SCI_For_Instrumented_CU (New_CU_Id); end if; - - if Version_Less (S, Than => 9) then - return; - end if; - - -- If we have information about non instrumented units, import them as - -- is. Only import SCOs that belong to this CU, as others SCOs might - -- belong to a CU already present in the current execution, and which - -- would not be simply imported as is. - - for SCO of CP_Vectors.Non_Instr_SCOs loop - if SCO in CP_CU.First_SCO .. CP_CU.Last_SCO then - Non_Instr_SCOs.Insert (Remap_SCO_Id (Relocs, SCO)); - end if; - end loop; - - for SCO of CP_Vectors.Non_Instr_MCDC_SCOs loop - if SCO in CP_CU.First_SCO .. CP_CU.Last_SCO then - Non_Instr_MCDC_SCOs.Insert (Remap_SCO_Id (Relocs, SCO)); - end if; - end loop; - end Checkpoint_Load_New_Unit; -------------------------- From 47e8f5a6304155a94910b16f921777b031350e1b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 4 Oct 2022 11:47:19 +0000 Subject: [PATCH 0020/1483] Instrument: handle MCDC "path overflow" for C/C++ In Ada, instrumentation is now able to skip instrumenting an MC/DC decision if it is too complex (number of paths too high) and properly report this to users. Similar support is missing in the C/C++ instrumenter. This commit adds it back, extracting common code from the Ada and C/C++ instrumenter to the Instrumenter.Common unit, and finally updates the warning message wrt recent developments (undetermined coverage status). TN: VA04-026 Change-Id: I016ce53a827dd96c4779cfc587f60f3e9a603a21 Depends-On: Id47c316aacbc8c067ff75a2a703cf07bef5c450d --- tools/gnatcov/instrument-ada_unit.adb | 98 ++++++++++----------------- tools/gnatcov/instrument-c.adb | 67 ++++++++---------- tools/gnatcov/instrument-common.adb | 81 ++++++++++++++++++++++ tools/gnatcov/instrument-common.ads | 47 +++++++++++-- 4 files changed, 188 insertions(+), 105 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 31080b8fc..b0912283d 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1276,58 +1276,24 @@ package body Instrument.Ada_Unit is SD : Source_Decision; Path_Count : Natural) is - LL_SCO_Id : Nat renames SD.LL_SCO; - N : Expr renames SD.Decision; + N : Expr renames SD.Decision; - Bits : Decision_Bit_Ids; RH_P : constant Node_Rewriting_Handle := Create_Node (IC.Rewriting_Context, Libadalang.Common.Ada_Identifier); RH_N : constant Node_Rewriting_Handle := Handle (N); - begin - Bits.LL_D_SCO := LL_SCO_Id; - - -- Allocate outcome bits - - Bits.Outcome_Bits := - (False => IC.Unit_Bits.Last_Outcome_Bit + 1, - True => IC.Unit_Bits.Last_Outcome_Bit + 2); - IC.Unit_Bits.Last_Outcome_Bit := - IC.Unit_Bits.Last_Outcome_Bit + 2; - - -- Allocate path bits for MC/DC if MC/DC is required and we were - -- able to generate a local state variable. If Path_Count is 0, this - -- means the BDD has more paths than the allowed limit, so do not - -- allocate any bit in the MC/DC buffers. The SCOs for the conditions - -- have already been emitted so this will generate MC/DC violations for - -- all of them. - - if MCDC_Coverage_Enabled - and then Length (SD.State) > 0 - and then Path_Count > 0 - then - Bits.Path_Bits_Base := IC.Unit_Bits.Last_Path_Bit + 1; - IC.Unit_Bits.Last_Path_Bit := - IC.Unit_Bits.Last_Path_Bit + Bit_Id (Path_Count); - else - Bits.Path_Bits_Base := No_Bit_Id; - end if; - if Path_Count = 0 then - Report (Node => N, - Msg => "Number of distinct paths in the decision exceeds" - & " the limit (" - & Img (SC_Obligations.Get_Path_Count_Limit) - & "). MC/DC coverage for this decision will not be" - & " assessed and will result in MC/DC violations." - & " Use option --path-count-limit to adjust the" - & " limit if the default value is too low.", - Kind => Warning); - end if; - - IC.Unit_Bits.Decision_Bits.Append (Bits); + -- Allocate bits for this decision in coverage buffers + Bits : constant Decision_Bit_Ids := + Allocate_Decision_Bits + (IC.Unit_Bits, + (IC.SFI, +Sloc (SD.Decision)), + SD.LL_SCO, + SD.State, + Path_Count); + begin -- Detach original decision from tree so that it can be reattached -- inside the witness call. @@ -2943,6 +2909,7 @@ package body Instrument.Ada_Unit is Insert_Pos : Natural; Insert_Info : Insertion_Info_Access := UIC.Current_Insertion_Info; + Bit : Any_Bit_Id; begin -- Create an artificial internal error, if requested @@ -2958,14 +2925,9 @@ package body Instrument.Ada_Unit is return; end if; - -- Allocate a bit in the statement coverage buffer, and record - -- its id in the bitmap. + -- Allocate a bit in the statement coverage buffer - UIC.Unit_Bits.Last_Statement_Bit := - UIC.Unit_Bits.Last_Statement_Bit + 1; - UIC.Unit_Bits.Statement_Bits.Append - (Statement_Bit_Ids' - (LL_SCO_Id, Executed => UIC.Unit_Bits.Last_Statement_Bit)); + Bit := Allocate_Statement_Bit (UIC.Unit_Bits, LL_SCO_Id); case Insert_Info.Method is @@ -2981,7 +2943,7 @@ package body Instrument.Ada_Unit is Children => (1 => Make_Statement_Witness (UIC, - Bit => UIC.Unit_Bits.Last_Statement_Bit, + Bit => Bit, Flavor => Function_Call, In_Generic => SCE.In_Generic), @@ -3119,7 +3081,7 @@ package body Instrument.Ada_Unit is Child => Make_Statement_Witness (UIC, - Bit => UIC.Unit_Bits.Last_Statement_Bit, + Bit => Bit, Flavor => (case Insert_Info.Method is when Statement => Procedure_Call, @@ -3160,7 +3122,7 @@ package body Instrument.Ada_Unit is begin Insert_Info.Witness_Actual := Make_Statement_Witness (UIC, - Bit => UIC.Unit_Bits.Last_Statement_Bit, + Bit => Bit, Flavor => Function_Call, In_Generic => SCE.In_Generic); @@ -6713,18 +6675,26 @@ package body Instrument.Ada_Unit is -- static decision, as this would make the instrumented -- expression non-static. Mark the enclosing decision as not -- instrumented for MCDC instead. + -- + -- As we go through each condition, mark their enclosing + -- decision as not instrumented if their number of paths + -- exceeds our limit. for SC of UIC.Source_Conditions loop - if Path_Count - (Enclosing_Decision (SCO_Map (SC.LL_SCO))) /= 0 - and then not SC.Decision_Static - then - Insert_Condition_Witness - (UIC, SC, Offset_For_True (SCO_Map (SC.LL_SCO))); - else - Set_Decision_SCO_Non_Instr_For_MCDC - (Enclosing_Decision (SCO_Map (SC.LL_SCO))); - end if; + declare + Condition : constant SCO_Id := SCO_Map (SC.LL_SCO); + Decision : constant SCO_Id := + Enclosing_Decision (Condition); + begin + if Path_Count (Decision) /= 0 + and then not SC.Decision_Static + then + Insert_Condition_Witness + (UIC, SC, Offset_For_True (Condition)); + else + Set_Decision_SCO_Non_Instr_For_MCDC (Decision); + end if; + end; end loop; end if; end if; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 73b63f204..c28fb13f8 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -246,7 +246,7 @@ package body Instrument.C is procedure Insert_Decision_Witness (UIC : in out C_Unit_Inst_Context; SD : C_Source_Decision; - Path_Count : Positive); + Path_Count : Natural); -- For use when decision coverage or MC/DC is requested. Insert witness -- function call for the identified decision. @@ -935,15 +935,11 @@ package body Instrument.C is procedure Insert_Statement_Witness (UIC : in out C_Unit_Inst_Context; SS : C_Source_Statement) is - -- Allocate a bit in the statement coverage buffer, and record - -- its id in the bitmap. + -- Allocate a bit in the statement coverage buffer - Bit : constant Bit_Id := UIC.Unit_Bits.Last_Statement_Bit + 1; + Bit : constant Bit_Id := + Allocate_Statement_Bit (UIC.Unit_Bits, SS.LL_SCO); begin - UIC.Unit_Bits.Last_Statement_Bit := Bit; - UIC.Unit_Bits.Statement_Bits.Append - (Statement_Bit_Ids'(SS.LL_SCO, Executed => Bit)); - -- Insert the call to the witness function: as a foregoing statement if -- SS.Statement is a statement, or as a previous expression (using the -- comma operator) if SS.Statement is an expression. @@ -1012,37 +1008,20 @@ package body Instrument.C is procedure Insert_Decision_Witness (UIC : in out C_Unit_Inst_Context; SD : C_Source_Decision; - Path_Count : Positive) + Path_Count : Natural) is - LL_SCO_Id : Nat renames SD.LL_SCO; - N : Cursor_T renames SD.Decision; + N : Cursor_T renames SD.Decision; - Bits : Decision_Bit_Ids; + -- Allocate bits for this decision in coverage buffers + Bits : constant Decision_Bit_Ids := + Allocate_Decision_Bits + (UIC.Unit_Bits, + (UIC.SFI, Start_Sloc (N)), + SD.LL_SCO, + SD.State, + Path_Count); begin - Bits.LL_D_SCO := LL_SCO_Id; - - -- Allocate outcome bits - - Bits.Outcome_Bits := - (False => UIC.Unit_Bits.Last_Outcome_Bit + 1, - True => UIC.Unit_Bits.Last_Outcome_Bit + 2); - UIC.Unit_Bits.Last_Outcome_Bit := - UIC.Unit_Bits.Last_Outcome_Bit + 2; - - -- Allocate path bits for MC/DC if MC/DC is required and we were - -- able to generate a local state variable. - - if MCDC_Coverage_Enabled and then US.Length (SD.State) > 0 then - Bits.Path_Bits_Base := UIC.Unit_Bits.Last_Path_Bit + 1; - UIC.Unit_Bits.Last_Path_Bit := - UIC.Unit_Bits.Last_Path_Bit + Bit_Id (Path_Count); - else - Bits.Path_Bits_Base := No_Bit_Id; - end if; - - UIC.Unit_Bits.Decision_Bits.Append (Bits); - -- Now attach witness call at the place of the original decision declare @@ -2875,10 +2854,24 @@ package body Instrument.C is -- As high-level SCO tables have been populated, we have built -- BDDs for each decisions, and we can now set the correct -- MC/DC path offset for each condition. + -- + -- As we go through each condition, mark their enclosing + -- decision as not instrumented if their number of paths + -- exceeds our limit. for SC of UIC.Source_Conditions loop - Insert_Condition_Witness - (UIC, SC, Offset_For_True (SCO_Map (SC.LL_SCO))); + declare + Condition : constant SCO_Id := SCO_Map (SC.LL_SCO); + Decision : constant SCO_Id := + Enclosing_Decision (Condition); + begin + if Path_Count (Decision) = 0 then + Set_Decision_SCO_Non_Instr_For_MCDC (Decision); + else + Insert_Condition_Witness + (UIC, SC, Offset_For_True (Condition)); + end if; + end; end loop; end if; end if; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index f8f3b7229..1baa2dc33 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -32,6 +32,8 @@ with Langkit_Support.Text; with Libadalang.Common; with Libadalang.Sources; +with Coverage; +with Diagnostics; with Hex_Images; with Outputs; use Outputs; with Paths; use Paths; @@ -82,6 +84,10 @@ package body Instrument.Common is -- IC.Get_From_File_Count to 0, as the new context has not been used to -- instrument any source file yet. + function Next_Bit (Last_Bit : in out Any_Bit_Id) return Any_Bit_Id; + -- Convenience function to allocate a new coverage buffer bit: increment + -- Last_Bit and return the new Last_Bit. + ------------------- -- Buffer_Symbol -- ------------------- @@ -712,6 +718,81 @@ package body Instrument.Common is (Missing_Src_Reporter'(others => <>)); end Create_Missing_File_Reporter; + -------------- + -- Next_Bit -- + -------------- + + function Next_Bit (Last_Bit : in out Any_Bit_Id) return Any_Bit_Id is + begin + Last_Bit := Last_Bit + 1; + return Last_Bit; + end Next_Bit; + + ---------------------------- + -- Allocate_Statement_Bit -- + ---------------------------- + + function Allocate_Statement_Bit + (Unit_Bits : in out Allocated_Bits; LL_S_SCO : Nat) return Any_Bit_Id + is + Bit : constant Any_Bit_Id := Next_Bit (Unit_Bits.Last_Statement_Bit); + begin + Unit_Bits.Statement_Bits.Append (Statement_Bit_Ids'(LL_S_SCO, Bit)); + return Bit; + end Allocate_Statement_Bit; + + ---------------------------- + -- Allocate_Decision_Bits -- + ---------------------------- + + function Allocate_Decision_Bits + (Unit_Bits : in out Allocated_Bits; + Decision_Sloc : Source_Location; + LL_D_SCO : Nat; + State_Variable : Unbounded_String; + Path_Count : Natural) return Decision_Bit_Ids is + begin + return Result : Decision_Bit_Ids do + Result.LL_D_SCO := LL_D_SCO; + + -- Allocate one bit per outcome + + for Outcome in Boolean loop + Result.Outcome_Bits (Outcome) := + Next_Bit (Unit_Bits.Last_Outcome_Bit); + end loop; + + -- If appropriate, allocate path bits for MC/DC: one bit per path in + -- the decision. + + if Coverage.MCDC_Coverage_Enabled + and then Length (State_Variable) > 0 + and then Path_Count > 0 + then + Result.Path_Bits_Base := Unit_Bits.Last_Path_Bit + 1; + Unit_Bits.Last_Path_Bit := + Unit_Bits.Last_Path_Bit + Bit_Id (Path_Count); + else + Result.Path_Bits_Base := No_Bit_Id; + end if; + + -- Warn if the number of paths exceeded the limit + + if Path_Count = 0 then + Diagnostics.Report + (Decision_Sloc, + "Number of distinct paths in the decision exceeds the limit" + & " (" & Img (SC_Obligations.Get_Path_Count_Limit) & ")." + & " MC/DC coverage for this decision will be left undetermined" + & " in coverage reports. Use option --path-count-limit to" + & " adjust the limit if the default value is too low.", + Diagnostics.Warning); + end if; + + Unit_Bits.Decision_Bits.Append (Result); + end return; + end Allocate_Decision_Bits; + ------------------------ -- Import_Annotations -- ------------------------ diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 9a2ffb62a..70e0e1608 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -405,7 +405,10 @@ package Instrument.Common is type Statement_Bit_Ids is record LL_S_SCO : Nat; + -- Low-level SCO for this statement + Executed : Bit_Id; + -- Corresponding bit in the "statement" coverage buffer end record; package LL_Statement_SCO_Bit_Allocs is @@ -418,16 +421,23 @@ package Instrument.Common is No_Outcome_Bit_Ids : constant Outcome_Bit_Ids := (others => No_Bit_Id); type Decision_Bit_Ids is record - LL_D_SCO : Nat; + LL_D_SCO : Nat; + -- Low-level SCO for this decision + + Outcome_Bits : Outcome_Bit_Ids := No_Outcome_Bit_Ids; + -- Bits in the "decision" coverage buffer, corresponding to the False + -- and True outcomes. - Outcome_Bits : Outcome_Bit_Ids := No_Outcome_Bit_Ids; Path_Bits_Base : Any_Bit_Id := No_Bit_Id; + -- First bit in the "mcdc" coverage buffer, corresponding to the first + -- path in the BDD. The other paths for the BDD are associated to the + -- bits that follow it. end record; package LL_Decision_SCO_Bit_Allocs is new Ada.Containers.Vectors (Nat, Decision_Bit_Ids); - type LL_Unit_Bit_Allocs is record + type Allocated_Bits is record Statement_Bits : LL_Statement_SCO_Bit_Allocs.Vector; Last_Statement_Bit : Any_Bit_Id := No_Bit_Id; @@ -435,6 +445,35 @@ package Instrument.Common is Last_Outcome_Bit : Any_Bit_Id := No_Bit_Id; Last_Path_Bit : Any_Bit_Id := No_Bit_Id; end record; + -- Vectors of coverage buffer allocated bits for the low-level SCOs of a + -- given source file. + + function Allocate_Statement_Bit + (Unit_Bits : in out Allocated_Bits; LL_S_SCO : Nat) return Any_Bit_Id; + -- Allocate a bit for a statement in the coverage buffers referenced by + -- Unit_Bits and return its index. + -- + -- LL_S_SCO must be the low-level SCO for that statement. + + function Allocate_Decision_Bits + (Unit_Bits : in out Allocated_Bits; + Decision_Sloc : Source_Location; + LL_D_SCO : Nat; + State_Variable : Unbounded_String; + Path_Count : Natural) return Decision_Bit_Ids; + -- Allocate bits for a decision ("decision" bits, and optionally "path" + -- bits) in the coverage buffers referenced by Unit_Bits. + -- + -- LL_D_SCO must be the low-level SCO for that decision and Decision_Sloc + -- must be its location (used for diagnostics). + -- + -- State_Variable is the local state variable: if it is empty, it means + -- that we were not able to generate one, and thus that we are unable to + -- compute MC/DC on this decision: no path bits are allocated in this case. + -- + -- Path_Count is the number of paths in this decision. If the number of + -- paths exceeds the limit, must be 0: this function emits a warning in + -- this case. ----------------------------- -- Instrumentation context -- @@ -480,7 +519,7 @@ package Instrument.Common is -- Name of the compilation unit that holds coverage buffers for the -- unit currently being instrumented (see Common.Buffer_Unit). - Unit_Bits : LL_Unit_Bit_Allocs; + Unit_Bits : Allocated_Bits; -- Record of allocation of coverage buffer bits for low-level SCOs Annotations : Annotation_Vectors.Vector; From 821df560299f0daf6c486d1662d3eef626a270d4 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 5 Oct 2022 19:21:35 +0000 Subject: [PATCH 0021/1483] Arrange to reset chapter numbers in pdf doc "parts" Adjust the sphinx latex_preamble so the doc for each tool starts with chapter 1 instead of having chapter numbers always increasing across the whole gnatdas doc. Part of VA05-064 Change-Id: I3b65eaa651381145bd5d4a3a51d0bb92e03bec15 --- doc/latex_preamble.inc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/latex_preamble.inc b/doc/latex_preamble.inc index 9d2f7249e..bbf4720f1 100644 --- a/doc/latex_preamble.inc +++ b/doc/latex_preamble.inc @@ -3,6 +3,12 @@ \let\oldpart\part \renewcommand{\part}[1]{\oldpart{#1}\gdef\parttitle{#1}} +% Arrange to reset chapter numbering at the start of each "part" +\makeatletter +\@addtoreset{chapter}{part} +\makeatother + +% Setup page headers and footers \makeatletter \fancypagestyle{normal}{ \fancyhf{} From 2156f00b37ffaaba4900b126d41b258d1cbbe844 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 29 Sep 2022 11:35:10 +0000 Subject: [PATCH 0022/1483] instrument-ada_unit.adb: minor reformatting TN: V728-002 Change-Id: Ib6a9a3b173fb1fdd8a9be801fa4de531ee89589d --- tools/gnatcov/instrument-ada_unit.adb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index b0912283d..35bafbb19 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6840,17 +6840,20 @@ package body Instrument.Ada_Unit is declare Pkg_Name : constant String := To_Ada (CU_Name.Unit); + -- Package name for the buffer unit Fingerprint : Unbounded_String; + -- Fingerprint for the instrumented unit Unit_Name : constant String := Ada.Characters.Handling.To_Lower (To_Ada (UIC.Instrumented_Unit.Unit)); + -- Lower-case name for the instrumented unit Unit_Part : constant String := - (case UIC.Instrumented_Unit.Part is - when GPR.Unit_Spec => "Unit_Spec", - when GPR.Unit_Body => "Unit_Body", - when GPR.Unit_Separate => "Unit_Separate"); + (case UIC.Instrumented_Unit.Part is + when GPR.Unit_Spec => "Unit_Spec", + when GPR.Unit_Body => "Unit_Body", + when GPR.Unit_Separate => "Unit_Separate"); -- Do not use 'Image so that we use the original casing for the -- enumerators, and thus avoid compilation warnings/errors. From e7be56884266de9bbb38c9f98e0e0fb2561e2a3a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 29 Sep 2022 11:35:29 +0000 Subject: [PATCH 0023/1483] Instrument: remove useless USE clause in Ada buffer units TN: V728-002 Change-Id: I044e977616f2d8c9eace7d76fbd66d854cb86813 --- tools/gnatcov/instrument-ada_unit.adb | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 35bafbb19..e26bab9e8 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6886,7 +6886,6 @@ package body Instrument.Ada_Unit is File.New_Line; File.Put_Line (" pragma Preelaborate;"); File.New_Line; - File.Put_Line ("use type Interfaces.C.int;"); File.Put_Line (" Statement_Buffer : Coverage_Buffer_Type" & " (0 .. " & Statement_Last_Bit & ") :=" & " (others => False);"); From 177d2238f4005c5f66d64fa9b23bd3e88a36dedf Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 29 Sep 2022 12:33:44 +0000 Subject: [PATCH 0024/1483] pre-commit: refine for the GNU coding style TN: V916-015 Change-Id: I68f0a5f31fc0d56b2552ef5ab85587296b61c2bb --- .pre-commit-config.yaml | 11 +- tools/gnatcov/bfd_helpers.c | 16 +- tools/gnatcov/clang-wrapper.cc | 339 +++++++++--------- tools/gnatcov/libopcodes_bind/dis_stream.c | 4 +- tools/gnatcov/libopcodes_bind/dis_stream.h | 6 +- tools/gnatcov/libopcodes_bind/dis_wrapper.c | 14 +- tools/gnatcov/libopcodes_bind/dis_wrapper.h | 12 +- tools/gnatcov/rts/gnatcov_rts_c-base_io.h | 10 +- tools/gnatcov/rts/gnatcov_rts_c-buffers.c | 22 +- tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 232 ++++++------ .../gnatcov/rts/gnatcov_rts_c-os_interface.h | 24 +- .../rts/gnatcov_rts_c-traces-output-base64.c | 2 +- .../rts/gnatcov_rts_c-traces-output-base64.h | 17 +- .../rts/gnatcov_rts_c-traces-output-files.c | 45 ++- .../rts/gnatcov_rts_c-traces-output-files.h | 71 ++-- .../gnatcov/rts/gnatcov_rts_c-traces-output.c | 30 +- .../gnatcov/rts/gnatcov_rts_c-traces-output.h | 34 +- tools/gnatcov/rts/gnatcov_rts_c-traces.h | 163 ++++----- tools/gnatcov/rts/gnatcov_rts_c_strings.h | 16 +- tools/gnatcov/zlib_helpers.c | 4 +- 20 files changed, 542 insertions(+), 530 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8cd76df07..959f2a690 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -5,4 +5,13 @@ repos: - id: clang-format types: [file] files: \.(cc|c|h)$ - args: ["--style={BasedOnStyle: gnu, SpaceAfterCStyleCast: true}"] + args: ["--style={ + BasedOnStyle: gnu, + ContinuationIndentWidth: 2, + + # Unfortunately, a bug in clang-format makes this ineffective + IndentExternBlock: NoIndent, + + SpaceAfterCStyleCast: true, + UseTab: ForContinuationAndIndentation + }"] diff --git a/tools/gnatcov/bfd_helpers.c b/tools/gnatcov/bfd_helpers.c index 62a4cf440..0f5bfa617 100644 --- a/tools/gnatcov/bfd_helpers.c +++ b/tools/gnatcov/bfd_helpers.c @@ -27,17 +27,17 @@ do \ { \ if (!(expr)) \ - { \ - (*warn_cb) (call " failed", bfd_errmsg (bfd_get_error ())); \ - return; \ - } \ + { \ + (*warn_cb) (call " failed", bfd_errmsg (bfd_get_error ())); \ + return; \ + } \ } \ while (0) void _gnatcov_for_each_synthetic_symbol ( - char *fn, void (*cb) (const char *, long unsigned int), - void (*warn_cb) (const char *, const char *)) + char *fn, void (*cb) (const char *, long unsigned int), + void (*warn_cb) (const char *, const char *)) { bfd *abfd; asymbol **dyn_syms = NULL, *synthsyms = NULL; @@ -68,8 +68,8 @@ _gnatcov_for_each_synthetic_symbol ( return; synth_count = bfd_get_synthetic_symtab (abfd, /*static_count*/ 0, - /*static_syms*/ NULL, dyn_count, - dyn_syms, &synthsyms); + /*static_syms*/ NULL, dyn_count, + dyn_syms, &synthsyms); /* Note: synth_count is either -1 or >0, never 0. There is no way distinguish an error condition from the mere absence of synthetic diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index b37f3c374..19e89e705 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -114,23 +114,23 @@ clang_getCond (CXCursor C) if (clang_isStatement (C.kind) || clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::IfStmtClass: - return MakeCXCursorWithNull (cast (S)->getCond (), C); - case Stmt::WhileStmtClass: - return MakeCXCursorWithNull (cast (S)->getCond (), C); - case Stmt::ForStmtClass: - return MakeCXCursorWithNull (cast (S)->getCond (), C); - case Stmt::SwitchStmtClass: - return MakeCXCursorWithNull (cast (S)->getCond (), C); - case Stmt::DoStmtClass: - return MakeCXCursorWithNull (cast (S)->getCond (), C); - case Stmt::ConditionalOperatorClass: - return MakeCXCursorWithNull ( - cast (S)->getCond (), C); - default: - return clang_getNullCursor (); - } + { + case Stmt::IfStmtClass: + return MakeCXCursorWithNull (cast (S)->getCond (), C); + case Stmt::WhileStmtClass: + return MakeCXCursorWithNull (cast (S)->getCond (), C); + case Stmt::ForStmtClass: + return MakeCXCursorWithNull (cast (S)->getCond (), C); + case Stmt::SwitchStmtClass: + return MakeCXCursorWithNull (cast (S)->getCond (), C); + case Stmt::DoStmtClass: + return MakeCXCursorWithNull (cast (S)->getCond (), C); + case Stmt::ConditionalOperatorClass: + return MakeCXCursorWithNull ( + cast (S)->getCond (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -140,57 +140,56 @@ clang_getBody (CXCursor C) if (clang_isDeclaration (C.kind)) { if (const Decl *D = getCursorDecl (C)) - switch (D->getKind ()) - { - case Decl::FunctionTemplate: - return MakeCXCursorWithNull (cast (D) - ->getTemplatedDecl () - ->getBody (), - C); - case Decl::Function: - case Decl::CXXMethod: - case Decl::CXXConstructor: - case Decl::CXXDestructor: - case Decl::CXXConversion: - { - const FunctionDecl *FD = cast (D); - if (FD->doesThisDeclarationHaveABody ()) - return MakeCXCursorWithNull (FD->getBody (), C); - break; - } - default: - return MakeCXCursorWithNull (D->getBody (), C); - } + switch (D->getKind ()) + { + case Decl::FunctionTemplate: + return MakeCXCursorWithNull ( + cast (D)->getTemplatedDecl ()->getBody (), + C); + case Decl::Function: + case Decl::CXXMethod: + case Decl::CXXConstructor: + case Decl::CXXDestructor: + case Decl::CXXConversion: + { + const FunctionDecl *FD = cast (D); + if (FD->doesThisDeclarationHaveABody ()) + return MakeCXCursorWithNull (FD->getBody (), C); + break; + } + default: + return MakeCXCursorWithNull (D->getBody (), C); + } } else if (clang_isStatement (C.kind)) { if (const Stmt *S = getCursorStmt (C)) - switch (S->getStmtClass ()) - { - case Stmt::WhileStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), C); - case Stmt::ForStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), C); - case Stmt::CXXForRangeStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), - C); - case Stmt::DoStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), C); - case Stmt::SwitchStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), C); - default: - return clang_getNullCursor (); - } + switch (S->getStmtClass ()) + { + case Stmt::WhileStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), C); + case Stmt::ForStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), C); + case Stmt::CXXForRangeStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), + C); + case Stmt::DoStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), C); + case Stmt::SwitchStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), C); + default: + return clang_getNullCursor (); + } } else if (clang_isExpression (C.kind)) if (const Expr *E = getCursorExpr (C)) switch (E->getStmtClass ()) - { - case Expr::LambdaExprClass: - return MakeCXCursorWithNull (cast (E)->getBody (), C); - default: - return clang_getNullCursor (); - } + { + case Expr::LambdaExprClass: + return MakeCXCursorWithNull (cast (E)->getBody (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -200,15 +199,15 @@ clang_getForInit (CXCursor C) if (clang_isStatement (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::ForStmtClass: - return MakeCXCursorWithNull (cast (S)->getInit (), C); - case Stmt::CXXForRangeStmtClass: - return MakeCXCursorWithNull (cast (S)->getInit (), - C); - default: - return clang_getNullCursor (); - } + { + case Stmt::ForStmtClass: + return MakeCXCursorWithNull (cast (S)->getInit (), C); + case Stmt::CXXForRangeStmtClass: + return MakeCXCursorWithNull (cast (S)->getInit (), + C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -233,12 +232,12 @@ clang_getForInc (CXCursor C) if (clang_isStatement (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::ForStmtClass: - return MakeCXCursorWithNull (cast (S)->getInc (), C); - default: - return clang_getNullCursor (); - } + { + case Stmt::ForStmtClass: + return MakeCXCursorWithNull (cast (S)->getInc (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -254,7 +253,7 @@ clang_getCondVar (CXCursor C) { while_stmt = cast (stmt); if (decl = while_stmt->getConditionVariable ()) - return MakeCXCursorWithNull (decl, C); + return MakeCXCursorWithNull (decl, C); } return clang_getNullCursor (); } @@ -280,12 +279,12 @@ clang_getThen (CXCursor C) if (clang_isStatement (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::IfStmtClass: - return MakeCXCursorWithNull (cast (S)->getThen (), C); - default: - return clang_getNullCursor (); - } + { + case Stmt::IfStmtClass: + return MakeCXCursorWithNull (cast (S)->getThen (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -295,12 +294,12 @@ clang_getElse (CXCursor C) if (clang_isStatement (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::IfStmtClass: - return MakeCXCursorWithNull (cast (S)->getElse (), C); - default: - return clang_getNullCursor (); - } + { + case Stmt::IfStmtClass: + return MakeCXCursorWithNull (cast (S)->getElse (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -310,13 +309,13 @@ clang_getSubExpr (CXCursor C) if (clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::UnaryOperatorClass: - return MakeCXCursorWithNull (cast (S)->getSubExpr (), - C); - default: - return clang_getNullCursor (); - } + { + case Stmt::UnaryOperatorClass: + return MakeCXCursorWithNull (cast (S)->getSubExpr (), + C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -326,15 +325,15 @@ clang_getSubStmt (CXCursor C) if (clang_isStatement (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::CaseStmtClass: - return MakeCXCursorWithNull (cast (S)->getSubStmt (), C); - case Stmt::DefaultStmtClass: - return MakeCXCursorWithNull (cast (S)->getSubStmt (), - C); - default: - return clang_getNullCursor (); - } + { + case Stmt::CaseStmtClass: + return MakeCXCursorWithNull (cast (S)->getSubStmt (), C); + case Stmt::DefaultStmtClass: + return MakeCXCursorWithNull (cast (S)->getSubStmt (), + C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -344,15 +343,15 @@ clang_getRHS (CXCursor C) if (clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::BinaryOperatorClass: - return MakeCXCursorWithNull (cast (S)->getRHS (), C); - case Stmt::ConditionalOperatorClass: - return MakeCXCursorWithNull ( - cast (S)->getRHS (), C); - default: - return clang_getNullCursor (); - } + { + case Stmt::BinaryOperatorClass: + return MakeCXCursorWithNull (cast (S)->getRHS (), C); + case Stmt::ConditionalOperatorClass: + return MakeCXCursorWithNull ( + cast (S)->getRHS (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -362,15 +361,15 @@ clang_getLHS (CXCursor C) if (clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::BinaryOperatorClass: - return MakeCXCursorWithNull (cast (S)->getLHS (), C); - case Stmt::ConditionalOperatorClass: - return MakeCXCursorWithNull ( - cast (S)->getRHS (), C); - default: - return clang_getNullCursor (); - } + { + case Stmt::BinaryOperatorClass: + return MakeCXCursorWithNull (cast (S)->getLHS (), C); + case Stmt::ConditionalOperatorClass: + return MakeCXCursorWithNull ( + cast (S)->getRHS (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -383,16 +382,16 @@ clang_getOpcodeStr (CXCursor C) if (clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::BinaryOperatorClass: - return createRef (BinaryOperator::getOpcodeStr ( - cast (S)->getOpcode ())); - case Stmt::UnaryOperatorClass: - return createRef (UnaryOperator::getOpcodeStr ( - cast (S)->getOpcode ())); - default: - return createEmpty (); - } + { + case Stmt::BinaryOperatorClass: + return createRef (BinaryOperator::getOpcodeStr ( + cast (S)->getOpcode ())); + case Stmt::UnaryOperatorClass: + return createRef (UnaryOperator::getOpcodeStr ( + cast (S)->getOpcode ())); + default: + return createEmpty (); + } return createEmpty (); } @@ -406,16 +405,16 @@ clang_getOperatorLoc (CXCursor C) if (clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::BinaryOperatorClass: - sloc = cast (S)->getOperatorLoc (); - break; - case Stmt::UnaryOperatorClass: - sloc = cast (S)->getOperatorLoc (); - break; - default: - return clang_getNullLocation (); - } + { + case Stmt::BinaryOperatorClass: + sloc = cast (S)->getOperatorLoc (); + break; + case Stmt::UnaryOperatorClass: + sloc = cast (S)->getOperatorLoc (); + break; + default: + return clang_getNullLocation (); + } return translateSLoc (TU, sloc); } @@ -429,25 +428,25 @@ clang_unwrap (CXCursor C) if (clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::ParenExprClass: - return clang_unwrap ( - MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); - case Expr::ConstantExprClass: - case Expr::ExprWithCleanupsClass: - return clang_unwrap ( - MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); - case Expr::ImplicitCastExprClass: - case Expr::CStyleCastExprClass: - case Expr::CXXFunctionalCastExprClass: - case Expr::CXXStaticCastExprClass: - case Expr::CXXDynamicCastExprClass: - case Expr::CXXReinterpretCastExprClass: - case Expr::CXXConstCastExprClass: - case Expr::CXXAddrspaceCastExprClass: - return clang_unwrap ( - MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); - } + { + case Stmt::ParenExprClass: + return clang_unwrap ( + MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); + case Expr::ConstantExprClass: + case Expr::ExprWithCleanupsClass: + return clang_unwrap ( + MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); + case Expr::ImplicitCastExprClass: + case Expr::CStyleCastExprClass: + case Expr::CXXFunctionalCastExprClass: + case Expr::CXXStaticCastExprClass: + case Expr::CXXDynamicCastExprClass: + case Expr::CXXReinterpretCastExprClass: + case Expr::CXXConstCastExprClass: + case Expr::CXXAddrspaceCastExprClass: + return clang_unwrap ( + MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); + } return C; } @@ -456,10 +455,10 @@ clang_unwrap (CXCursor C) extern "C" unsigned clang_visit (CXCursor parent, CXCursorVisitor visitor, - CXClientData client_data) + CXClientData client_data) { CursorVisitor CursorVis (getCursorTU (parent), visitor, client_data, - /*VisitPreprocessorLast=*/false); + /*VisitPreprocessorLast=*/false); return CursorVis.Visit (parent); } @@ -474,10 +473,10 @@ clang_getParent (CXCursor C) { const auto Parents = getContext (C).getParents (*S); if (Parents.empty ()) - return clang_getNullCursor (); + return clang_getNullCursor (); const auto &SParent = Parents[0]; if (const auto *Res = SParent.get ()) - return MakeCXCursorWithNull (Res, C); + return MakeCXCursorWithNull (Res, C); } return clang_getNullCursor (); } @@ -486,7 +485,7 @@ clang_getParent (CXCursor C) extern "C" void clang_CXRewriter_insertTextAfter (CXRewriter Rew, CXSourceLocation Loc, - const char *Insert) + const char *Insert) { assert (Rew); Rewriter &R = *reinterpret_cast (Rew); @@ -495,7 +494,7 @@ clang_CXRewriter_insertTextAfter (CXRewriter Rew, CXSourceLocation Loc, extern "C" void clang_CXRewriter_insertTextAfterToken (CXRewriter Rew, CXSourceLocation Loc, - const char *Insert) + const char *Insert) { assert (Rew); Rewriter &R = *reinterpret_cast (Rew); @@ -513,7 +512,7 @@ clang_isMacroLocation (CXSourceLocation Loc) extern "C" unsigned clang_isMacroArgExpansion (CXSourceLocation Loc, CXSourceLocation *StartLoc, - CXTranslationUnit TU) + CXTranslationUnit TU) { const SourceManager &SM = getSourceManager (TU); const SourceLocation SLoc = translateSourceLocation (Loc); @@ -546,12 +545,12 @@ clang_getImmediateExpansionLoc (CXSourceLocation Loc, CXTranslationUnit TU) extern "C" CXString clang_getImmediateMacroNameForDiagnostics (CXSourceLocation Loc, - CXTranslationUnit TU) + CXTranslationUnit TU) { SourceLocation SLoc = translateSourceLocation (Loc); const SourceManager &SM = getSourceManager (TU); return createDup (Lexer::getImmediateMacroNameForDiagnostics ( - SLoc, SM, getContext (TU).getLangOpts ())); + SLoc, SM, getContext (TU).getLangOpts ())); } extern "C" CXSourceLocation diff --git a/tools/gnatcov/libopcodes_bind/dis_stream.c b/tools/gnatcov/libopcodes_bind/dis_stream.c index ddf6c2790..b97b34284 100644 --- a/tools/gnatcov/libopcodes_bind/dis_stream.c +++ b/tools/gnatcov/libopcodes_bind/dis_stream.c @@ -63,8 +63,8 @@ stream_printf (disassembler_stream *ds, const char *format, ...) desired. */ int stream_styled_printf (disassembler_stream *ds, - enum disassembler_style style ATTRIBUTE_UNUSED, - const char *format, ...) + enum disassembler_style style ATTRIBUTE_UNUSED, + const char *format, ...) { va_list ap; int res; diff --git a/tools/gnatcov/libopcodes_bind/dis_stream.h b/tools/gnatcov/libopcodes_bind/dis_stream.h index 1a6deb3cd..a2e50cf0f 100644 --- a/tools/gnatcov/libopcodes_bind/dis_stream.h +++ b/tools/gnatcov/libopcodes_bind/dis_stream.h @@ -37,14 +37,14 @@ extern void delete_stream (disassembler_stream *const ds); extern int stream_printf (disassembler_stream *ptr, const char *format, ...); extern int stream_styled_printf (disassembler_stream *ptr, - enum disassembler_style style, - const char *format, ...); + enum disassembler_style style, + const char *format, ...); extern void clear_stream (disassembler_stream *const ds); extern unsigned char stream_is_empty (disassembler_stream *const ds); extern void set_stream_buffer (disassembler_stream *const ds, char *const buff, - int size); + int size); #endif /* !DIS_STREAM_H_ */ diff --git a/tools/gnatcov/libopcodes_bind/dis_wrapper.c b/tools/gnatcov/libopcodes_bind/dis_wrapper.c index 85e920110..b6c442fbd 100644 --- a/tools/gnatcov/libopcodes_bind/dis_wrapper.c +++ b/tools/gnatcov/libopcodes_bind/dis_wrapper.c @@ -76,7 +76,7 @@ _print_address_cb (bfd_vma addr, disassemble_info *dinfo) /* Then, print the symbolized address, if possible. First dump it to BUFF, then if symbolization worked, move it to the output stream. */ buff_cur - = sym_data->addr_cb (addr, sym_data->symbolizer, buff, buff_size - 1); + = sym_data->addr_cb (addr, sym_data->symbolizer, buff, buff_size - 1); buff[buff_cur++] = '\0'; stream_printf (dinfo->stream, "%s", buff); } @@ -100,7 +100,7 @@ _create_base_disassembler (enum bfd_architecture arch, const char *options) } init_disassemble_info (&(dh->dinfo), ds, (fprintf_ftype) stream_printf, - (fprintf_styled_ftype) stream_styled_printf); + (fprintf_styled_ftype) stream_styled_printf); dh->dinfo.arch = arch; if (options) { @@ -134,14 +134,14 @@ static disassemble_handle * _create_arm_arch_disassembler (unsigned char for_thumb) { return _create_base_disassembler ( - bfd_arch_arm, (for_thumb) ? dis_thumb_option : dis_arm_option); + bfd_arch_arm, (for_thumb) ? dis_thumb_option : dis_arm_option); } /* Set necessary information for symbol resolution for the disassembler represented by DH. */ void set_disassembler_symbolizer (disassemble_handle *const dh, - void *const symbolizer, print_symbol_cb addr_cb) + void *const symbolizer, print_symbol_cb addr_cb) { symbolizer_data *sym_data = dh->dinfo.application_data; @@ -247,9 +247,9 @@ delete_disassembler (disassemble_handle *const dh) Returns the size of the disassembled instruction. */ int disassemble_to_text (disassemble_handle *const dh, bfd_vma pc, - char *const dest, unsigned int dest_size, - bfd_byte *const insn_buffer, unsigned int ib_size, - enum bfd_endian endian) + char *const dest, unsigned int dest_size, + bfd_byte *const insn_buffer, unsigned int ib_size, + enum bfd_endian endian) { int size; diff --git a/tools/gnatcov/libopcodes_bind/dis_wrapper.h b/tools/gnatcov/libopcodes_bind/dis_wrapper.h index 101ce776c..115b652d6 100644 --- a/tools/gnatcov/libopcodes_bind/dis_wrapper.h +++ b/tools/gnatcov/libopcodes_bind/dis_wrapper.h @@ -32,7 +32,7 @@ typedef struct disassemble_handle disassemble_handle; /* Functions of this type can write at most BUFF_SIZE bytes. */ typedef int (*print_symbol_cb) (bfd_vma addr, void *symbolizer, - char *const buff, int buff_size); + char *const buff, int buff_size); extern disassemble_handle *create_arm_disassembler (void); @@ -47,12 +47,12 @@ extern disassemble_handle *create_aarch64_disassembler (void); extern void delete_disassembler (disassemble_handle *const dh); extern int disassemble_to_text (disassemble_handle *const dh, bfd_vma pc, - char *const dest, unsigned int dest_size, - bfd_byte *const insn_buffer, - unsigned int ib_size, enum bfd_endian endian); + char *const dest, unsigned int dest_size, + bfd_byte *const insn_buffer, + unsigned int ib_size, enum bfd_endian endian); extern void set_disassembler_symbolizer (disassemble_handle *const dh, - void *const symbolizer, - print_symbol_cb addr_cb); + void *const symbolizer, + print_symbol_cb addr_cb); #endif /* !DIS_WRAPPER_H_ */ diff --git a/tools/gnatcov/rts/gnatcov_rts_c-base_io.h b/tools/gnatcov/rts/gnatcov_rts_c-base_io.h index 30837fa79..26efd7d7d 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-base_io.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-base_io.h @@ -17,7 +17,6 @@ * * ****************************************************************************/ - /* This header provides the smallest subset of functions needed to output bytes. These functions are used in gnatcov_rts_c-traces-output-base64.c to dump base64 traces to "the output": stdout when linking with a C runtime @@ -31,12 +30,13 @@ #include "gnatcov_rts_c_strings.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/* See gnatcov_rts-base_io.ads. */ -extern int gnatcov_rts_puts (gnatcov_rts_string str); -extern int gnatcov_rts_putchar (int c); + /* See gnatcov_rts-base_io.ads. */ + extern int gnatcov_rts_puts (gnatcov_rts_string str); + extern int gnatcov_rts_putchar (int c); #ifdef __cplusplus } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c index 11081ba19..7a78eb5c1 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c @@ -30,8 +30,8 @@ gnatcov_rts_witness (uint8_t *buffer, gnatcov_rts_bit_id bit) gnatcov_rts_bool gnatcov_rts_witness_decision (uint8_t *buffer, gnatcov_rts_bit_id false_bit, - gnatcov_rts_bit_id true_bit, - gnatcov_rts_bool value) + gnatcov_rts_bit_id true_bit, + gnatcov_rts_bool value) { gnatcov_rts_witness (buffer, value ? true_bit : false_bit); return value; @@ -39,23 +39,23 @@ gnatcov_rts_witness_decision (uint8_t *buffer, gnatcov_rts_bit_id false_bit, gnatcov_rts_bool gnatcov_rts_witness_decision_mcdc (uint8_t *decision_buffer, - gnatcov_rts_bit_id false_bit, - gnatcov_rts_bit_id true_bit, - uint8_t *mcdc_buffer, - gnatcov_rts_bit_id mcdc_base, - gnatcov_rts_bit_id *mcdc_path_address, - gnatcov_rts_bool value) + gnatcov_rts_bit_id false_bit, + gnatcov_rts_bit_id true_bit, + uint8_t *mcdc_buffer, + gnatcov_rts_bit_id mcdc_base, + gnatcov_rts_bit_id *mcdc_path_address, + gnatcov_rts_bool value) { gnatcov_rts_bit_id mcdc_path_index = *mcdc_path_address; gnatcov_rts_witness (mcdc_buffer, mcdc_base + mcdc_path_index); return gnatcov_rts_witness_decision (decision_buffer, false_bit, true_bit, - value); + value); } gnatcov_rts_bool gnatcov_rts_witness_condition (gnatcov_rts_bit_id *mcdc_path_address, - gnatcov_rts_bit_id offset_for_true, - gnatcov_rts_bool first, gnatcov_rts_bool value) + gnatcov_rts_bit_id offset_for_true, + gnatcov_rts_bool first, gnatcov_rts_bool value) { gnatcov_rts_bit_id *mcdc_path_index = (gnatcov_rts_bit_id *) mcdc_path_address; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index 81d3b03c0..c0fcfea91 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -25,138 +25,138 @@ #include "gnatcov_rts_c_strings.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/* Coverage buffers are big arrays of booleans. How to interpret them depends - on the type of coverage obligation. + /* Coverage buffers are big arrays of booleans. How to interpret them depends + on the type of coverage obligation. - For statement coverage, each statement is assigned such a boolean, which - indicates whether it was executed. + For statement coverage, each statement is assigned such a boolean, which + indicates whether it was executed. - For decision coverage, each decision is assigned two booleans: one which - indicates whether the decision reached the False outcome and another for - the True outcome. + For decision coverage, each decision is assigned two booleans: one which + indicates whether the decision reached the False outcome and another for + the True outcome. - For MC/DC coverage, there is a boolean for each decision valuation path in - the binary decision diagram. */ + For MC/DC coverage, there is a boolean for each decision valuation path in + the binary decision diagram. */ -/* Representation of the boolean type */ -typedef unsigned gnatcov_rts_bool; + /* Representation of the boolean type. */ + typedef unsigned gnatcov_rts_bool; -/* Unique identifier for a boolean in a coverage buffer */ -typedef int gnatcov_rts_bit_id; + /* Unique identifier for a boolean in a coverage buffer. */ + typedef int gnatcov_rts_bit_id; #define FINGERPRINT_SIZE 20 -enum gnatcov_rts_unit_part -{ - /* `NOT_APPLICABLE_PART` is a default value used for compilation units in - languages that are not unit-based. */ - NOT_APPLICABLE_PART = 0, - UNIT_BODY = 1, - UNIT_SPEC = 2, - UNIT_SEPARATE = 3 -}; - -enum gnatcov_rts_language_kind -{ - UNIT_BASED_LANGUAGE = 0, - FILE_BASED_LANGUAGE = 1 -}; - -typedef struct gnatcov_rts_unit_coverage_buffers -{ - /* Hash of SCO info for this unit, as gnatcov computes it (see - SC_Obligations). Used as a fast way to check that coverage obligations - and coverage data are consistent. Specific hash values are computed during - instrumentation. */ - uint8_t fingerprint[FINGERPRINT_SIZE]; - - /* Language kind for this unit. */ - enum gnatcov_rts_language_kind language_kind; - - /* Unit kind and name for the instrumented unit. The unit_name field - accounts both for unit-based languages (such as Ada) and file-based - languages such as C. - - The unit_part field is only there for unit-based languages and is set - to NOT_APPLICABLE_PART for file-based languages. - - More specifically, for unit-based languages, unit_name is the fully - qualified name of the compilation unit (or subunit) in lower case. - For instance: "foo", "ada.text_io" or "foo.bar.my_subunit". - - For file-based languages, unit_name is the simple filename, e.g. - "foo.c". */ - enum gnatcov_rts_unit_part unit_part; - gnatcov_rts_string unit_name; - - /* Project name for this compilation unit. This is only initialized for - file-based languages (otherwise, it is an empty string). */ - gnatcov_rts_string project_name; - - /* Addresses of coverage buffers for statement obligations, decision - obligations and MC/DC obligations. The address refer to - Coverage_Buffer_Type arrays whose bounds go from 0 to - unit_coverage_buffers.*_last_bit. */ - uint8_t *statement, *decision, *mcdc; - - /* Index for the last bits in coverage buffers for statements, decisions and - MC/DC. */ - gnatcov_rts_bit_id statement_last_bit, decision_last_bit, mcdc_last_bit; -} gnatcov_rts_unit_coverage_buffers; - -/* Array of unit coverage buffers. */ -typedef struct gnatcov_rts_unit_coverage_buffers_array -{ - unsigned length; - gnatcov_rts_unit_coverage_buffers **buffers; -} gnatcov_rts_unit_coverage_buffers_array; - -/***********************/ -/* Witness subprograms */ -/***********************/ - -/* The following subprograms are called by generated code to record - the execution of constructs. */ - -/* Statements */ - -/* Set the boolean corresponding to BIT to true in BUFFER in various - context. */ -extern gnatcov_rts_bool gnatcov_rts_witness (uint8_t *buffer, - gnatcov_rts_bit_id bit); - -/* Decisions */ - -/* If VALUE is false, set the boolean corresponding to FALSE_BIT to true in - BUFFER. Set the one corresponding to TRUE_BIT otherwise. */ -extern gnatcov_rts_bool -gnatcov_rts_witness_decision (uint8_t *buffer, gnatcov_rts_bit_id false_bit, - gnatcov_rts_bit_id true_bit, - gnatcov_rts_bool value); - -/* Same as above, and also set the bit determined by MCDC_BASE and the - gnatcov_rts_bit_id value at MCDC_PATH_ADDRESS in the buffer at - MCDC_BUFFER_ADDRESS. Note that MCDC_PATH may not be passed by value, - because it is not known until the side effect of the actual for the VALUE - formal have been evaluated. */ -extern gnatcov_rts_bool gnatcov_rts_witness_decision_mcdc ( + enum gnatcov_rts_unit_part + { + /* `NOT_APPLICABLE_PART` is a default value used for compilation units in + languages that are not unit-based. */ + NOT_APPLICABLE_PART = 0, + UNIT_BODY = 1, + UNIT_SPEC = 2, + UNIT_SEPARATE = 3 + }; + + enum gnatcov_rts_language_kind + { + UNIT_BASED_LANGUAGE = 0, + FILE_BASED_LANGUAGE = 1 + }; + + typedef struct gnatcov_rts_unit_coverage_buffers + { + /* Hash of SCO info for this unit, as gnatcov computes it (see + SC_Obligations). Used as a fast way to check that coverage obligations + and coverage data are consistent. Specific hash values are computed + during instrumentation. */ + uint8_t fingerprint[FINGERPRINT_SIZE]; + + /* Language kind for this unit. */ + enum gnatcov_rts_language_kind language_kind; + + /* Unit kind and name for the instrumented unit. The unit_name field + accounts both for unit-based languages (such as Ada) and file-based + languages such as C. + + The unit_part field is only there for unit-based languages and is set + to NOT_APPLICABLE_PART for file-based languages. + + More specifically, for unit-based languages, unit_name is the fully + qualified name of the compilation unit (or subunit) in lower case. + For instance: "foo", "ada.text_io" or "foo.bar.my_subunit". + + For file-based languages, unit_name is the simple filename, e.g. + "foo.c". */ + enum gnatcov_rts_unit_part unit_part; + gnatcov_rts_string unit_name; + + /* Project name for this compilation unit. This is only initialized for + file-based languages (otherwise, it is an empty string). */ + gnatcov_rts_string project_name; + + /* Addresses of coverage buffers for statement obligations, decision + obligations and MC/DC obligations. The address refer to + Coverage_Buffer_Type arrays whose bounds go from 0 to + unit_coverage_buffers.*_last_bit. */ + uint8_t *statement, *decision, *mcdc; + + /* Index for the last bits in coverage buffers for statements, decisions + and MC/DC. */ + gnatcov_rts_bit_id statement_last_bit, decision_last_bit, mcdc_last_bit; + } gnatcov_rts_unit_coverage_buffers; + + /* Array of unit coverage buffers. */ + typedef struct gnatcov_rts_unit_coverage_buffers_array + { + unsigned length; + gnatcov_rts_unit_coverage_buffers **buffers; + } gnatcov_rts_unit_coverage_buffers_array; + + /***********************/ + /* Witness subprograms */ + /***********************/ + + /* The following subprograms are called by generated code to record + the execution of constructs. */ + + /* Statements */ + + /* Set the boolean corresponding to BIT to true in BUFFER in various + context. */ + extern gnatcov_rts_bool gnatcov_rts_witness (uint8_t *buffer, + gnatcov_rts_bit_id bit); + + /* Decisions */ + + /* If VALUE is false, set the boolean corresponding to FALSE_BIT to true in + BUFFER. Set the one corresponding to TRUE_BIT otherwise. */ + extern gnatcov_rts_bool + gnatcov_rts_witness_decision (uint8_t *buffer, gnatcov_rts_bit_id false_bit, + gnatcov_rts_bit_id true_bit, + gnatcov_rts_bool value); + + /* Same as above, and also set the bit determined by MCDC_BASE and the + gnatcov_rts_bit_id value at MCDC_PATH_ADDRESS in the buffer at + MCDC_BUFFER_ADDRESS. Note that MCDC_PATH may not be passed by value, + because it is not known until the side effect of the actual for the VALUE + formal have been evaluated. */ + extern gnatcov_rts_bool gnatcov_rts_witness_decision_mcdc ( uint8_t *decision_buffer, gnatcov_rts_bit_id false_bit, gnatcov_rts_bit_id true_bit, uint8_t *mcdc_buffer, gnatcov_rts_bit_id mcdc_base, gnatcov_rts_bit_id *mcdc_path_address, gnatcov_rts_bool value); -/* Conditions */ + /* Conditions */ -/* MCDC_PATH_ADDRESS is the address of a local variable storing the mcdc_state. - If FIRST is true, first reset it to 0. If VALUE is true, add - OFFSET_FOR_TRUE. */ -extern gnatcov_rts_bool -gnatcov_rts_witness_condition (gnatcov_rts_bit_id *mcdc_path_address, - gnatcov_rts_bit_id offset_for_true, - gnatcov_rts_bool first, gnatcov_rts_bool value); + /* MCDC_PATH_ADDRESS is the address of a local variable storing the + mcdc_state. If FIRST is true, first reset it to 0. If VALUE is true, add + OFFSET_FOR_TRUE. */ + extern gnatcov_rts_bool gnatcov_rts_witness_condition ( + gnatcov_rts_bit_id *mcdc_path_address, gnatcov_rts_bit_id offset_for_true, + gnatcov_rts_bool first, gnatcov_rts_bool value); #ifdef __cplusplus } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h index 4554f3241..4a9ab24d5 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h @@ -20,21 +20,21 @@ #include #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif + /* The C "time" function can return integers of + different size depending on the platform. + Here, we ensure that the returned result will be an + expected long long (a 64 bit integer). It will thus + be compatible with 32 bit as well as 64 bit architectures. + It also ensures compatibility with Ada Long_Long_Integer + standard type. */ + extern uint64_t gnatcov_rts_time_to_uint64 (void); -/* The C "time" function can return integers of - different size depending on the platform. - Here, we ensure that the returned result will be an - expected long long (a 64 bit integer). It will thus - be compatible with 32 bit as well as 64 bit architectures. - It also ensures compatibility with Ada Long_Long_Integer - standard type. */ -extern uint64_t gnatcov_rts_time_to_uint64 (void); - -/* Return the current process ID as an unsigned 64-bit integer. */ -extern uint64_t gnatcov_rts_getpid (void); + /* Return the current process ID as an unsigned 64-bit integer. */ + extern uint64_t gnatcov_rts_getpid (void); #ifdef __cplusplus } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c index 80b358129..d6d390e72 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c @@ -119,7 +119,7 @@ write_bytes (void *output, const void *bytes, unsigned count) buffer->bytes[buffer->next] = bytes_array[i]; buffer->next = buffer->next + 1; if (buffer->next == 3) - flush (buffer); + flush (buffer); } return 0; } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h index 587ebfdb7..baa688d3a 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h @@ -22,16 +22,17 @@ #include #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/* Write a Base64-encoded trace file to the standard output. See the - documentation of the gnatcov_rts_generic_write_trace_file function in - gnatcov_rts_c-output.h for more information. */ -extern void gnatcov_rts_write_trace_file_base64 ( - const gnatcov_rts_unit_coverage_buffers_array *buffers, - gnatcov_rts_string program_name, uint64_t exec_date, - gnatcov_rts_string user_data); + /* Write a Base64-encoded trace file to the standard output. See the + documentation of the gnatcov_rts_generic_write_trace_file function in + gnatcov_rts_c-output.h for more information. */ + extern void gnatcov_rts_write_trace_file_base64 ( + const gnatcov_rts_unit_coverage_buffers_array *buffers, + gnatcov_rts_string program_name, uint64_t exec_date, + gnatcov_rts_string user_data); #ifdef __cplusplus } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c index 21042d88e..5a91c9979 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c @@ -129,25 +129,25 @@ gnatcov_rts_default_trace_filename (const char *env_var, const char *prefix, else { /* The caller is supposed to free the returned string, so create a - copy. */ + copy. */ env_trace_filename = concat (env_trace_filename, NULL); /* If the filename ends with a directory separator, consider that it - refers to a directory: in that case return a filename inside it. */ + refers to a directory: in that case return a filename inside it. */ size_t length = strlen (env_trace_filename); if (length > 0 - && (env_trace_filename[length - 1] == '/' - || env_trace_filename[length - 1] == '\\')) - { - char *basename - = gnatcov_rts_default_trace_basename (prefix, tag, simple); - char *res = concat (env_trace_filename, basename, NULL); - free (env_trace_filename); - free (basename); - return res; - } + && (env_trace_filename[length - 1] == '/' + || env_trace_filename[length - 1] == '\\')) + { + char *basename + = gnatcov_rts_default_trace_basename (prefix, tag, simple); + char *res = concat (env_trace_filename, basename, NULL); + free (env_trace_filename); + free (basename); + return res; + } else - return env_trace_filename; + return env_trace_filename; } } @@ -163,7 +163,7 @@ gnatcov_rts_write_trace_file ( return 1; gnatcov_rts_generic_write_trace_file (file, buffers, program_name, exec_date, - user_data, write_bytes); + user_data, write_bytes); fclose (file); return 0; } @@ -171,14 +171,13 @@ gnatcov_rts_write_trace_file ( /* See gnatcov_rts_c-traces-output-files.h. */ void gnatcov_rts_write_trace_file_wrapper ( - const gnatcov_rts_unit_coverage_buffers_array *buffers, - const char *filename, gnatcov_rts_string program_name, - uint64_t exec_date, gnatcov_rts_string user_data) + const gnatcov_rts_unit_coverage_buffers_array *buffers, const char *filename, + gnatcov_rts_string program_name, uint64_t exec_date, + gnatcov_rts_string user_data) { - if (gnatcov_rts_write_trace_file - (buffers, filename, program_name, exec_date, user_data) != 0) - fprintf - (stderr, - "Error occurred while creating the trace file %s: %s\n", - filename, strerror (errno)); + if (gnatcov_rts_write_trace_file (buffers, filename, program_name, exec_date, + user_data) + != 0) + fprintf (stderr, "Error occurred while creating the trace file %s: %s\n", + filename, strerror (errno)); } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h index 667938ea6..be3223808 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h @@ -22,7 +22,8 @@ #include #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif /* Default name of the environment variable which controls the default @@ -30,52 +31,50 @@ extern "C" { function below. */ #define GNATCOV_RTS_DEFAULT_TRACE_FILENAME_ENV_VAR "GNATCOV_TRACE_FILE" -/* Return the default name of the trace file to write. The returned name must - be manually freed. + /* Return the default name of the trace file to write. The returned name + must be manually freed. - If the ENV_VAR environment variable is not defined or empty, return: + If the ENV_VAR environment variable is not defined or empty, return: - * "PREFIX.srctrace" if SIMPLE is True. + * "PREFIX.srctrace" if SIMPLE is True. - * "PREFIX-TAG-PID-CLOCK.srctrace" if SIMPLE is False (PID is the current - process ID and CLOCK is the execution timestamp). The "-TAG" part is - omitted if TAG is the empty string. + * "PREFIX-TAG-PID-CLOCK.srctrace" if SIMPLE is False (PID is the current + process ID and CLOCK is the execution timestamp). The "-TAG" part is + omitted if TAG is the empty string. - If the ENV_VAR environment variable is defined and not empty, then: + If the ENV_VAR environment variable is defined and not empty, then: - * if it ends with "/" or "\", consider it contains the name of a directory: - use the algorithm described above to compute the basename and return the - filename in that directory; + * if it ends with "/" or "\", consider it contains the name of a + directory: use the algorithm described above to compute the basename and + return the filename in that directory; - * otherwise, just return the content of that environment variable. */ -extern char *gnatcov_rts_default_trace_filename (const char *env_var, - const char *prefix, - const char *tag, - unsigned simple); + * otherwise, just return the content of that environment variable. */ + extern char *gnatcov_rts_default_trace_filename (const char *env_var, + const char *prefix, + const char *tag, + unsigned simple); -/* Write a trace file in FILENAME to contain the data in BUFFERS. + /* Write a trace file in FILENAME to contain the data in BUFFERS. - PROGRAM_NAME, EXEC_DATE, and USER_DATA are used to fill the - corresponding metadata in the written trace file. + PROGRAM_NAME, EXEC_DATE, and USER_DATA are used to fill the + corresponding metadata in the written trace file. - EXEC_DATE is given to produce the timestamp. Use the current - time by default. + EXEC_DATE is given to produce the timestamp. Use the current + time by default. - Return 0 if the trace creation was successful, 1 otherwise. In case of - error, ERRNO is left to the number for the cause of error. */ -extern int -gnatcov_rts_write_trace_file ( - const gnatcov_rts_unit_coverage_buffers_array *buffers, const char *filename, - gnatcov_rts_string program_name, uint64_t exec_date, - gnatcov_rts_string user_data); + Return 0 if the trace creation was successful, 1 otherwise. In case of + error, ERRNO is left to the number for the cause of error. */ + extern int gnatcov_rts_write_trace_file ( + const gnatcov_rts_unit_coverage_buffers_array *buffers, + const char *filename, gnatcov_rts_string program_name, uint64_t exec_date, + gnatcov_rts_string user_data); -/* Call gnatcov_rts_write_trace_file and print an error message on the standard - error if the trace could not be created. */ -extern void -gnatcov_rts_write_trace_file_wrapper ( - const gnatcov_rts_unit_coverage_buffers_array *buffers, const char *filename, - gnatcov_rts_string program_name, uint64_t exec_date, - gnatcov_rts_string user_data); + /* Call gnatcov_rts_write_trace_file and print an error message on the + standard error if the trace could not be created. */ + extern void gnatcov_rts_write_trace_file_wrapper ( + const gnatcov_rts_unit_coverage_buffers_array *buffers, + const char *filename, gnatcov_rts_string program_name, uint64_t exec_date, + gnatcov_rts_string user_data); #ifdef __cplusplus } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index b3ea17049..9ccd71859 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -33,7 +33,7 @@ typedef struct info_entry_d /* Write `count` padding bytes. */ static void write_padding (gnatcov_rts_write_bytes_callback write_bytes, void *output, - unsigned count) + unsigned count) { unsigned pad_count = (alignment - count) % alignment; if (pad_count != alignment) @@ -62,7 +62,7 @@ write_header (gnatcov_rts_write_bytes_callback write_bytes, void *output) /* Write an information entry (e.g. the program_name, the exec date etc.). */ static void write_info (gnatcov_rts_write_bytes_callback write_bytes, void *output, - uint32_t kind, info_entry *data) + uint32_t kind, info_entry *data) { struct trace_info_header header; header.kind = kind; @@ -91,7 +91,7 @@ flush (gnatcov_rts_write_bytes_callback write_bytes, void *output, /* Write a coverage bit buffer. */ static void write_buffer (gnatcov_rts_write_bytes_callback write_bytes, void *output, - uint8_t *buffer, unsigned buffer_length) + uint8_t *buffer, unsigned buffer_length) { uint8_t current_byte = 0; uint8_t bit_mask = 1; @@ -101,11 +101,11 @@ write_buffer (gnatcov_rts_write_bytes_callback write_bytes, void *output, for (i = 0; i < buffer_length; i++) { if (buffer[i]) - current_byte = current_byte | bit_mask; + current_byte = current_byte | bit_mask; if (bit_mask == 1 << 7) - flush (write_bytes, output, &bit_mask, ¤t_byte, &bytes_count); + flush (write_bytes, output, &bit_mask, ¤t_byte, &bytes_count); else - bit_mask <<= 1; + bit_mask <<= 1; } flush (write_bytes, output, &bit_mask, ¤t_byte, &bytes_count); @@ -115,7 +115,7 @@ write_buffer (gnatcov_rts_write_bytes_callback write_bytes, void *output, /* Write a coverage buffer (unit information + coverage bit buffers). */ static void write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, - const gnatcov_rts_unit_coverage_buffers *buffers) + const gnatcov_rts_unit_coverage_buffers *buffers) { struct trace_entry_header header; header.unit_name_length = (uint32_t) buffers->unit_name.length; @@ -132,21 +132,21 @@ write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, write_bytes (output, (char *) &header, sizeof (header)); write_bytes (output, buffers->unit_name.str, buffers->unit_name.length); write_padding (write_bytes, output, buffers->unit_name.length); - write_bytes - (output, buffers->project_name.str, buffers->project_name.length); + write_bytes (output, buffers->project_name.str, + buffers->project_name.length); write_padding (write_bytes, output, buffers->project_name.length); write_buffer (write_bytes, output, buffers->statement, - buffers->statement_last_bit + 1); + buffers->statement_last_bit + 1); write_buffer (write_bytes, output, buffers->decision, - buffers->decision_last_bit + 1); + buffers->decision_last_bit + 1); write_buffer (write_bytes, output, buffers->mcdc, - buffers->mcdc_last_bit + 1); + buffers->mcdc_last_bit + 1); } /* Write a uint64_t timestamp (by splitting it in uint8_t chunks). */ void write_date (gnatcov_rts_write_bytes_callback write_bytes, void *output, - uint64_t timestamp) + uint64_t timestamp) { uint8_t formatted_date[8]; info_entry entry; @@ -185,10 +185,10 @@ gnatcov_rts_generic_write_trace_file ( write_header (write_bytes, output); write_info (write_bytes, output, GNATCOV_RTS_INFO_PROGRAM_NAME, - &program_name_entry); + &program_name_entry); write_date (write_bytes, output, exec_date); write_info (write_bytes, output, GNATCOV_RTS_INFO_USER_DATA, - &user_data_entry); + &user_data_entry); write_info (write_bytes, output, GNATCOV_RTS_INFO_END, &end_entry); for (i = 0; i < buffers->length; i++) diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h index eda9ae23e..c130e7f0e 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h @@ -21,25 +21,27 @@ #include "gnatcov_rts_c_strings.h" #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -/* Callback for trace writing routines. Write the N bytes starting at SOURCE to - the OUTPUT stream (OUTPUT is just forwarded from - gnatcov_rts_generic_write_trace_file). Return 0 if the write was - successful and return any non-zero value in case of error. */ -typedef int (*gnatcov_rts_write_bytes_callback) - (void *output, const void *source, unsigned n); + /* Callback for trace writing routines. Write the N bytes starting at SOURCE + to the OUTPUT stream (OUTPUT is just forwarded from + gnatcov_rts_generic_write_trace_file). Return 0 if the write was + successful and return any non-zero value in case of error. */ + typedef int (*gnatcov_rts_write_bytes_callback) (void *output, + const void *source, + unsigned n); -/* Write a trace file to contain the given coverage BUFFERS to the OUTPUT - stream using the WRITE_BYTES callback. PROGRAM_NAME, EXEC_DATE and - USER_DATA are included as metadata in the trace file. Return 0 if the write - was successful, and return any non-zero value in case of error. */ -extern int gnatcov_rts_generic_write_trace_file ( - void *output, const gnatcov_rts_unit_coverage_buffers_array *buffers, - gnatcov_rts_string program_name, uint64_t exec_date, - gnatcov_rts_string user_data, - gnatcov_rts_write_bytes_callback write_bytes); + /* Write a trace file to contain the given coverage BUFFERS to the OUTPUT + stream using the WRITE_BYTES callback. PROGRAM_NAME, EXEC_DATE and + USER_DATA are included as metadata in the trace file. Return 0 if the + write was successful, and return any non-zero value in case of error. */ + extern int gnatcov_rts_generic_write_trace_file ( + void *output, const gnatcov_rts_unit_coverage_buffers_array *buffers, + gnatcov_rts_string program_name, uint64_t exec_date, + gnatcov_rts_string user_data, + gnatcov_rts_write_bytes_callback write_bytes); #ifdef __cplusplus } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces.h b/tools/gnatcov/rts/gnatcov_rts_c-traces.h index f38a1d653..7342e1eba 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces.h @@ -23,7 +23,8 @@ #include #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif /* Expected value of the `trace_file_header.format_version` field. @@ -44,104 +45,104 @@ extern "C" { significant bit maps to bit 8 * Y + 7. */ #define GNATCOV_RTS_LSB_FIRST_BYTES 0 -enum -{ - GNATCOV_RTS_LITTLE_ENDIAN, - GNATCOV_RTS_BIG_ENDIAN -}; + enum + { + GNATCOV_RTS_LITTLE_ENDIAN, + GNATCOV_RTS_BIG_ENDIAN + }; -/* Return the native endianity, 0 for little-endian, 1 for big-endian. */ -extern unsigned gnatcov_rts_native_endianity (void); + /* Return the native endianity, 0 for little-endian, 1 for big-endian. */ + extern unsigned gnatcov_rts_native_endianity (void); -struct trace_file_header -{ - char magic[32]; + struct trace_file_header + { + char magic[32]; - uint32_t format_version; - uint8_t alignment; - uint8_t endianity; + uint32_t format_version; + uint8_t alignment; + uint8_t endianity; - /* Padding used only to make the size of the trace file header a - multiple of 8 bytes. Must be zero. */ - uint16_t padding; -}; + /* Padding used only to make the size of the trace file header a + multiple of 8 bytes. Must be zero. */ + uint16_t padding; + }; -/*********************/ -/* Trace information */ -/*********************/ + /*********************/ + /* Trace information */ + /*********************/ -enum -{ + enum + { - /* Special trace info entry: indicates the end of a sequence of entries. No - data is associated to this trace info entry. */ - GNATCOV_RTS_INFO_END = 0, + /* Special trace info entry: indicates the end of a sequence of entries. No + data is associated to this trace info entry. */ + GNATCOV_RTS_INFO_END = 0, - /* Name of the program that produced this trace. */ - GNATCOV_RTS_INFO_PROGRAM_NAME = 1, + /* Name of the program that produced this trace. */ + GNATCOV_RTS_INFO_PROGRAM_NAME = 1, - /* Date for the program execution that produced this trace. */ - GNATCOV_RTS_INFO_EXEC_DATE = 2, + /* Date for the program execution that produced this trace. */ + GNATCOV_RTS_INFO_EXEC_DATE = 2, - /* Arbitrary storage for user data. This is exposed to users as the trace - "tag". */ - GNATCOV_RTS_INFO_USER_DATA = 3 -}; + /* Arbitrary storage for user data. This is exposed to users as the trace + "tag". */ + GNATCOV_RTS_INFO_USER_DATA = 3 + }; -struct trace_info_header -{ - uint32_t kind; - uint32_t length; -}; + struct trace_info_header + { + uint32_t kind; + uint32_t length; + }; -/* Trace entry header + /* Trace entry header -Each trace entry starts with the following header. Then goes: + Each trace entry starts with the following header. Then goes: - * The name of the unit describes. It is NUL-padded according to the - trace file alignment. + * The name of the unit describes. It is NUL-padded according to the + trace file alignment. - * The statement coverage buffer. It is also NUL-padded. + * The statement coverage buffer. It is also NUL-padded. - * The decision coverage buffer. It is also NUL-padded. + * The decision coverage buffer. It is also NUL-padded. - * The MC/DC coverage buffer. It is also NUL-padded. */ + * The MC/DC coverage buffer. It is also NUL-padded. */ -struct trace_entry_header -{ - /* Length of the unit name / filename for the unit this trace entry - describes. */ - uint32_t unit_name_length; - - /* For file-based languages, length of the project name this file belongs to. - For unit-based languages, the unit name is unique so this piece of - information is not needed (and thus will be 0). */ - uint32_t project_name_length; - - /* Number of bits in the statement, decision and MC/DC coverage buffers. */ - uint32_t statement_bit_count; - uint32_t decision_bit_count; - uint32_t mcdc_bit_count; - - /* Language kind for this unit */ - uint8_t language_kind; - - /* Part of the unit this trace entry describes. `not_applicable_part` for - file-based languages. */ - uint8_t unit_part; - - /* Encoding used to represent statement and decision coverage buffers. */ - uint8_t bit_buffer_encoding; - - /* Hash of SCO info for this unit. Used as a fast way to check that coverage - obligations and coverage data are consistent. Specific hash values are - computed during instrumentation. */ - uint8_t fingerprint[20]; - - /* Padding used only to make the size of this trace entry header a multiple - of 8 bytes. Must be zero. */ - uint8_t padding[5]; -}; + struct trace_entry_header + { + /* Length of the unit name / filename for the unit this trace entry + describes. */ + uint32_t unit_name_length; + + /* For file-based languages, length of the project name this file belongs + to. For unit-based languages, the unit name is unique so this piece of + information is not needed (and thus will be 0). */ + uint32_t project_name_length; + + /* Number of bits in the statement, decision and MC/DC coverage buffers. */ + uint32_t statement_bit_count; + uint32_t decision_bit_count; + uint32_t mcdc_bit_count; + + /* Language kind for this unit */ + uint8_t language_kind; + + /* Part of the unit this trace entry describes. `not_applicable_part` for + file-based languages. */ + uint8_t unit_part; + + /* Encoding used to represent statement and decision coverage buffers. */ + uint8_t bit_buffer_encoding; + + /* Hash of SCO info for this unit. Used as a fast way to check that + coverage obligations and coverage data are consistent. Specific hash + values are computed during instrumentation. */ + uint8_t fingerprint[20]; + + /* Padding used only to make the size of this trace entry header a multiple + of 8 bytes. Must be zero. */ + uint8_t padding[5]; + }; #ifdef __cplusplus } diff --git a/tools/gnatcov/rts/gnatcov_rts_c_strings.h b/tools/gnatcov/rts/gnatcov_rts_c_strings.h index 22b2ce0d2..246a8ba26 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c_strings.h +++ b/tools/gnatcov/rts/gnatcov_rts_c_strings.h @@ -23,18 +23,20 @@ #include #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -typedef struct gnatcov_rts_string -{ - const char *str; - size_t length; -} gnatcov_rts_string; + typedef struct gnatcov_rts_string + { + const char *str; + size_t length; + } gnatcov_rts_string; /* Converts a string litteral to the corresponding gnatcov_rts_string struct value. */ -#define STR(x) (struct gnatcov_rts_string) { x, sizeof (x) - 1 } +#define STR(x) \ + (struct gnatcov_rts_string) { x, sizeof (x) - 1 } #ifdef __cplusplus } diff --git a/tools/gnatcov/zlib_helpers.c b/tools/gnatcov/zlib_helpers.c index b9dc0a62d..aa1905859 100644 --- a/tools/gnatcov/zlib_helpers.c +++ b/tools/gnatcov/zlib_helpers.c @@ -27,7 +27,7 @@ decompression was successful. */ int gnatcov_zlib_uncompress (char *in_buffer, uint64_t in_size, char *out_buffer, - uint64_t out_size) + uint64_t out_size) { z_stream strm; @@ -40,5 +40,5 @@ gnatcov_zlib_uncompress (char *in_buffer, uint64_t in_size, char *out_buffer, /* Uncompress and then check that uncompressed data consumed exactly OUT_SIZE bytes. */ return (inflateInit (&strm) == Z_OK && inflate (&strm, Z_FINISH) == Z_OK - && inflateEnd (&strm) == Z_OK && strm.avail_out == 0); + && inflateEnd (&strm) == Z_OK && strm.avail_out == 0); } From 8971db714d7fe5f1b6b3a100f80728260ccbeca3 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 29 Sep 2022 12:02:17 +0000 Subject: [PATCH 0025/1483] gnatcov_rts: remove typedefs for struct definitions Current definitions for struct types both define a struct name and a typedef name, and references to these struct types are inconsistent ("struct S" or just "S"), making it harder to keep names consistent across renamings. "struct S" seems the most common reference, so harmonize the codebase and get rid of the struct typedefs. Change-Id: Id62d2c75e19196b821a1c3b3b51479b888494945 TN: V728-002 --- tools/gnatcov/instrument-c.adb | 9 ++++---- tools/gnatcov/rts/gnatcov_rts_c-base_io.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-base_io.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 14 +++++------ .../rts/gnatcov_rts_c-traces-output-base64.c | 10 ++++---- .../rts/gnatcov_rts_c-traces-output-base64.h | 6 ++--- .../rts/gnatcov_rts_c-traces-output-files.c | 12 +++++----- .../rts/gnatcov_rts_c-traces-output-files.h | 12 +++++----- .../gnatcov/rts/gnatcov_rts_c-traces-output.c | 23 ++++++++++--------- .../gnatcov/rts/gnatcov_rts_c-traces-output.h | 7 +++--- tools/gnatcov/rts/gnatcov_rts_c_strings.h | 4 ++-- 11 files changed, 52 insertions(+), 49 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index c28fb13f8..4003f3ff1 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3634,7 +3634,7 @@ package body Instrument.C is declare Buffer_Array_Decl : constant String := - "gnatcov_rts_unit_coverage_buffers_array " + "struct gnatcov_rts_unit_coverage_buffers_array " & Unit_Buffers_Array_Name (IC); Buffer_Unit_Length : constant String := Count_Type'Image (Instr_Units.Length); @@ -3651,7 +3651,7 @@ package body Instrument.C is Put_Extern_Decl (File_Body, Self, - "gnatcov_rts_unit_coverage_buffers", + "struct gnatcov_rts_unit_coverage_buffers", Unit_Buffers_Name (Instr_Unit)); end loop; @@ -3662,7 +3662,8 @@ package body Instrument.C is File_Body.Put_Line (Self.Extern_Prefix & Buffer_Array_Decl & ";"); File_Body.Put_Line (Buffer_Array_Decl & " = {"); File_Body.Put_Line (" " & Buffer_Unit_Length & ","); - File_Body.Put_Line (" (gnatcov_rts_unit_coverage_buffers *[]) {"); + File_Body.Put_Line (" (struct gnatcov_rts_unit_coverage_buffers *[])" + & " {"); for Cur in Instr_Units.Iterate loop declare use CU_Name_Vectors; @@ -3684,7 +3685,7 @@ package body Instrument.C is Put_Extern_Decl (File_Header, Self, - "gnatcov_rts_unit_coverage_buffers_array", + "struct gnatcov_rts_unit_coverage_buffers_array", Unit_Buffers_Array_Name (IC)); end Emit_Buffers_List_Unit; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-base_io.c b/tools/gnatcov/rts/gnatcov_rts_c-base_io.c index 968ff64b0..22c5bad77 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-base_io.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-base_io.c @@ -25,7 +25,7 @@ functions to print to the standard output. */ int -gnatcov_rts_puts (gnatcov_rts_string str) +gnatcov_rts_puts (struct gnatcov_rts_string str) { fwrite (str.str, 1, str.length, stdout); fwrite ("\n", 1, 1, stdout); diff --git a/tools/gnatcov/rts/gnatcov_rts_c-base_io.h b/tools/gnatcov/rts/gnatcov_rts_c-base_io.h index 26efd7d7d..62ec455b2 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-base_io.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-base_io.h @@ -35,7 +35,7 @@ extern "C" #endif /* See gnatcov_rts-base_io.ads. */ - extern int gnatcov_rts_puts (gnatcov_rts_string str); + extern int gnatcov_rts_puts (struct gnatcov_rts_string str); extern int gnatcov_rts_putchar (int c); #ifdef __cplusplus diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index c0fcfea91..329ceec65 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -66,7 +66,7 @@ extern "C" FILE_BASED_LANGUAGE = 1 }; - typedef struct gnatcov_rts_unit_coverage_buffers + struct gnatcov_rts_unit_coverage_buffers { /* Hash of SCO info for this unit, as gnatcov computes it (see SC_Obligations). Used as a fast way to check that coverage obligations @@ -91,11 +91,11 @@ extern "C" For file-based languages, unit_name is the simple filename, e.g. "foo.c". */ enum gnatcov_rts_unit_part unit_part; - gnatcov_rts_string unit_name; + struct gnatcov_rts_string unit_name; /* Project name for this compilation unit. This is only initialized for file-based languages (otherwise, it is an empty string). */ - gnatcov_rts_string project_name; + struct gnatcov_rts_string project_name; /* Addresses of coverage buffers for statement obligations, decision obligations and MC/DC obligations. The address refer to @@ -106,14 +106,14 @@ extern "C" /* Index for the last bits in coverage buffers for statements, decisions and MC/DC. */ gnatcov_rts_bit_id statement_last_bit, decision_last_bit, mcdc_last_bit; - } gnatcov_rts_unit_coverage_buffers; + }; /* Array of unit coverage buffers. */ - typedef struct gnatcov_rts_unit_coverage_buffers_array + struct gnatcov_rts_unit_coverage_buffers_array { unsigned length; - gnatcov_rts_unit_coverage_buffers **buffers; - } gnatcov_rts_unit_coverage_buffers_array; + struct gnatcov_rts_unit_coverage_buffers **buffers; + }; /***********************/ /* Witness subprograms */ diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c index d6d390e72..4dd4dd55a 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c @@ -126,16 +126,16 @@ write_bytes (void *output, const void *bytes, unsigned count) void gnatcov_rts_write_trace_file_base64 ( - const gnatcov_rts_unit_coverage_buffers_array *buffers, - gnatcov_rts_string program_name, uint64_t exec_date, - gnatcov_rts_string user_data) + const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + struct gnatcov_rts_string program_name, uint64_t exec_date, + struct gnatcov_rts_string user_data) { gnatcov_rts_base64_buffer buffer; buffer.next = 0; buffer.columns = 0; - gnatcov_rts_string begin_string + struct gnatcov_rts_string begin_string = STR ("== GNATcoverage source trace file =="); - gnatcov_rts_string end_string = STR ("== End =="); + struct gnatcov_rts_string end_string = STR ("== End =="); gnatcov_rts_putchar ('\n'); gnatcov_rts_puts (begin_string); gnatcov_rts_generic_write_trace_file (&buffer, buffers, program_name, diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h index baa688d3a..c6c6ba1b5 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h @@ -30,9 +30,9 @@ extern "C" documentation of the gnatcov_rts_generic_write_trace_file function in gnatcov_rts_c-output.h for more information. */ extern void gnatcov_rts_write_trace_file_base64 ( - const gnatcov_rts_unit_coverage_buffers_array *buffers, - gnatcov_rts_string program_name, uint64_t exec_date, - gnatcov_rts_string user_data); + const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + struct gnatcov_rts_string program_name, uint64_t exec_date, + struct gnatcov_rts_string user_data); #ifdef __cplusplus } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c index 5a91c9979..65f93865b 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c @@ -154,9 +154,9 @@ gnatcov_rts_default_trace_filename (const char *env_var, const char *prefix, /* See gnatcov_rts_c-traces-output-files.h. */ int gnatcov_rts_write_trace_file ( - const gnatcov_rts_unit_coverage_buffers_array *buffers, const char *filename, - gnatcov_rts_string program_name, uint64_t exec_date, - gnatcov_rts_string user_data) + const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + const char *filename, struct gnatcov_rts_string program_name, + uint64_t exec_date, struct gnatcov_rts_string user_data) { FILE *file = fopen (filename, "wb+"); if (!file) @@ -171,9 +171,9 @@ gnatcov_rts_write_trace_file ( /* See gnatcov_rts_c-traces-output-files.h. */ void gnatcov_rts_write_trace_file_wrapper ( - const gnatcov_rts_unit_coverage_buffers_array *buffers, const char *filename, - gnatcov_rts_string program_name, uint64_t exec_date, - gnatcov_rts_string user_data) + const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + const char *filename, struct gnatcov_rts_string program_name, + uint64_t exec_date, struct gnatcov_rts_string user_data) { if (gnatcov_rts_write_trace_file (buffers, filename, program_name, exec_date, user_data) diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h index be3223808..0d86db783 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h @@ -65,16 +65,16 @@ extern "C" Return 0 if the trace creation was successful, 1 otherwise. In case of error, ERRNO is left to the number for the cause of error. */ extern int gnatcov_rts_write_trace_file ( - const gnatcov_rts_unit_coverage_buffers_array *buffers, - const char *filename, gnatcov_rts_string program_name, uint64_t exec_date, - gnatcov_rts_string user_data); + const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + const char *filename, struct gnatcov_rts_string program_name, + uint64_t exec_date, struct gnatcov_rts_string user_data); /* Call gnatcov_rts_write_trace_file and print an error message on the standard error if the trace could not be created. */ extern void gnatcov_rts_write_trace_file_wrapper ( - const gnatcov_rts_unit_coverage_buffers_array *buffers, - const char *filename, gnatcov_rts_string program_name, uint64_t exec_date, - gnatcov_rts_string user_data); + const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + const char *filename, struct gnatcov_rts_string program_name, + uint64_t exec_date, struct gnatcov_rts_string user_data); #ifdef __cplusplus } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index 9ccd71859..422517e16 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -24,11 +24,11 @@ const unsigned alignment = sizeof (void *); -typedef struct info_entry_d +struct info_entry { const void *data; uint32_t length; -} info_entry; +}; /* Write `count` padding bytes. */ static void @@ -62,7 +62,7 @@ write_header (gnatcov_rts_write_bytes_callback write_bytes, void *output) /* Write an information entry (e.g. the program_name, the exec date etc.). */ static void write_info (gnatcov_rts_write_bytes_callback write_bytes, void *output, - uint32_t kind, info_entry *data) + uint32_t kind, struct info_entry *data) { struct trace_info_header header; header.kind = kind; @@ -115,7 +115,7 @@ write_buffer (gnatcov_rts_write_bytes_callback write_bytes, void *output, /* Write a coverage buffer (unit information + coverage bit buffers). */ static void write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, - const gnatcov_rts_unit_coverage_buffers *buffers) + const struct gnatcov_rts_unit_coverage_buffers *buffers) { struct trace_entry_header header; header.unit_name_length = (uint32_t) buffers->unit_name.length; @@ -149,7 +149,7 @@ write_date (gnatcov_rts_write_bytes_callback write_bytes, void *output, uint64_t timestamp) { uint8_t formatted_date[8]; - info_entry entry; + struct info_entry entry; int i; for (i = 0; i < 8; i++) @@ -166,21 +166,22 @@ write_date (gnatcov_rts_write_bytes_callback write_bytes, void *output, /* See gnatcov_rts_c-traces-output.h. */ int gnatcov_rts_generic_write_trace_file ( - void *output, const gnatcov_rts_unit_coverage_buffers_array *buffers, - gnatcov_rts_string program_name, uint64_t exec_date, - gnatcov_rts_string user_data, gnatcov_rts_write_bytes_callback write_bytes) + void *output, const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + struct gnatcov_rts_string program_name, uint64_t exec_date, + struct gnatcov_rts_string user_data, + gnatcov_rts_write_bytes_callback write_bytes) { unsigned i; - info_entry program_name_entry; + struct info_entry program_name_entry; program_name_entry.length = program_name.length; program_name_entry.data = program_name.str; - info_entry user_data_entry; + struct info_entry user_data_entry; user_data_entry.length = user_data.length; user_data_entry.data = user_data.str; - info_entry end_entry; + struct info_entry end_entry; end_entry.length = 0; write_header (write_bytes, output); diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h index c130e7f0e..fef2b66d5 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h @@ -38,9 +38,10 @@ extern "C" USER_DATA are included as metadata in the trace file. Return 0 if the write was successful, and return any non-zero value in case of error. */ extern int gnatcov_rts_generic_write_trace_file ( - void *output, const gnatcov_rts_unit_coverage_buffers_array *buffers, - gnatcov_rts_string program_name, uint64_t exec_date, - gnatcov_rts_string user_data, + void *output, + const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + struct gnatcov_rts_string program_name, uint64_t exec_date, + struct gnatcov_rts_string user_data, gnatcov_rts_write_bytes_callback write_bytes); #ifdef __cplusplus diff --git a/tools/gnatcov/rts/gnatcov_rts_c_strings.h b/tools/gnatcov/rts/gnatcov_rts_c_strings.h index 246a8ba26..0e9d6b8cc 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c_strings.h +++ b/tools/gnatcov/rts/gnatcov_rts_c_strings.h @@ -27,11 +27,11 @@ extern "C" { #endif - typedef struct gnatcov_rts_string + struct gnatcov_rts_string { const char *str; size_t length; - } gnatcov_rts_string; + }; /* Converts a string litteral to the corresponding gnatcov_rts_string struct value. */ From 2a77f3c35997bfffd14977189bd2fda960ccad26 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 30 Sep 2022 08:38:36 +0000 Subject: [PATCH 0026/1483] Instrument: make coverage buffers and their arrays constant All these datastructures are supposed to be preelaborate (in Ada parlance), so they can be constant. TN: V728-002 Change-Id: Ie3a1fd620250529a3531442b9d0d1fb704576bb4 --- tools/gnatcov/instrument-ada_unit.adb | 13 ++++++------- tools/gnatcov/instrument-c.adb | 12 ++++++------ tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads | 2 +- tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 2 +- 4 files changed, 14 insertions(+), 15 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index e26bab9e8..94dc5e59f 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6921,7 +6921,7 @@ package body Instrument.Ada_Unit is File.Put_Line (" Project_Name : constant String := """";"); File.New_Line; - File.Put_Line (" Buffers : aliased" + File.Put_Line (" Buffers : aliased constant" & " GNATcov_RTS_Unit_Coverage_Buffers :="); File.Put_Line (" (Fingerprint => " & To_String (Fingerprint) & ","); @@ -7371,7 +7371,7 @@ package body Instrument.Ada_Unit is begin File.Put_Line (" " & Buffer_Name - & " : aliased GNATcov_RTS_Unit_Coverage_Buffers;"); + & " : aliased constant GNATcov_RTS_Unit_Coverage_Buffers;"); File.Put_Line (" pragma Import (C, " & Buffer_Name & ",""" & Buffer_Name & """);"); end; @@ -7379,20 +7379,19 @@ package body Instrument.Ada_Unit is -- Create the list of coverage buffers - File.Put_Line (" List : GNATcov_RTS.Buffers.Lists" + File.Put_Line (" List : constant GNATcov_RTS.Buffers.Lists" & ".Unit_Coverage_Buffers_Array := ("); for Cur in Instr_Units.Iterate loop declare use CU_Name_Vectors; Index : constant Positive := To_Index (Cur); + Index_Img : constant String := Img (To_Index (Cur)); Buffer_Name : constant String := Unit_Buffers_Name (Element (Cur)); - begin - File.Put ((1 .. 6 => ' ')); - File.Put (Strings.Img (To_Index (Cur)) - & " => " & Buffer_Name & "'Unrestricted_Access"); + File.Put + (" " & Index_Img & " => " & Buffer_Name & "'Access"); if Index = Instr_Units.Last_Index then File.Put_Line (");"); else diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 4003f3ff1..ca882d1c2 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3097,7 +3097,7 @@ package body Instrument.C is Put_Format_Def (File, Instrumenter, - "struct gnatcov_rts_unit_coverage_buffers", + "const struct gnatcov_rts_unit_coverage_buffers", Unit_Buffers_Name (UIC.Instrumented_Unit), Init_Expr => "{" @@ -3634,7 +3634,7 @@ package body Instrument.C is declare Buffer_Array_Decl : constant String := - "struct gnatcov_rts_unit_coverage_buffers_array " + "const struct gnatcov_rts_unit_coverage_buffers_array " & Unit_Buffers_Array_Name (IC); Buffer_Unit_Length : constant String := Count_Type'Image (Instr_Units.Length); @@ -3651,7 +3651,7 @@ package body Instrument.C is Put_Extern_Decl (File_Body, Self, - "struct gnatcov_rts_unit_coverage_buffers", + "const struct gnatcov_rts_unit_coverage_buffers", Unit_Buffers_Name (Instr_Unit)); end loop; @@ -3662,8 +3662,8 @@ package body Instrument.C is File_Body.Put_Line (Self.Extern_Prefix & Buffer_Array_Decl & ";"); File_Body.Put_Line (Buffer_Array_Decl & " = {"); File_Body.Put_Line (" " & Buffer_Unit_Length & ","); - File_Body.Put_Line (" (struct gnatcov_rts_unit_coverage_buffers *[])" - & " {"); + File_Body.Put_Line + (" (const struct gnatcov_rts_unit_coverage_buffers *[]) {"); for Cur in Instr_Units.Iterate loop declare use CU_Name_Vectors; @@ -3685,7 +3685,7 @@ package body Instrument.C is Put_Extern_Decl (File_Header, Self, - "struct gnatcov_rts_unit_coverage_buffers_array", + "const struct gnatcov_rts_unit_coverage_buffers_array", Unit_Buffers_Array_Name (IC)); end Emit_Buffers_List_Unit; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads index 23de29cd6..c9d073b46 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads @@ -35,7 +35,7 @@ package GNATcov_RTS.Buffers.Lists is pragma Convention (C, GNATcov_RTS_Unit_Coverage_Buffers_Array); type Unit_Coverage_Buffers_Access is - access all GNATcov_RTS_Unit_Coverage_Buffers; + access constant GNATcov_RTS_Unit_Coverage_Buffers; type Unit_Coverage_Buffers_Array is array (Positive range <>) of Unit_Coverage_Buffers_Access; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index 329ceec65..9633e59bd 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -112,7 +112,7 @@ extern "C" struct gnatcov_rts_unit_coverage_buffers_array { unsigned length; - struct gnatcov_rts_unit_coverage_buffers **buffers; + const struct gnatcov_rts_unit_coverage_buffers **buffers; }; /***********************/ From fbe44562e0bd3df6b68da70ba75474c8e7726abf Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 30 Sep 2022 09:00:29 +0000 Subject: [PATCH 0027/1483] Instrument: make coverage buffers for C/C++ units static Coverage buffers themselves (i.e. not coverage buffer *pointers*) are not used outside of the buffer units for C. Make them "static" to clearly show the intent and to reduce the number of exported symbols. TN: V728-002 Change-Id: Ifa685e0e518a006c3ffb317078ca381eb4cfbd8a --- tools/gnatcov/instrument-c.adb | 39 ++++++++++++++++------------------ 1 file changed, 18 insertions(+), 21 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index ca882d1c2..d34af64ad 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3052,13 +3052,14 @@ package body Instrument.C is File.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); File.New_Line; - Put_Format_Def - (File, - Instrumenter, - "unsigned char", - Statement_Buffer_Repr, - Array_Size => - Img (Any_Bit_Id'Max (1, UIC.Unit_Bits.Last_Statement_Bit + 1))); + + -- Define the individual buffers (statement, decision and MC/DC, + -- which are static) as well as pointers to them (exported). + + File.Put_Line + ("static unsigned char " & Statement_Buffer_Repr & "[" + & Img (Any_Bit_Id'Max (1, UIC.Unit_Bits.Last_Statement_Bit + 1)) + & "];"); Put_Format_Def (File, Instrumenter, @@ -3066,13 +3067,10 @@ package body Instrument.C is Statement_Buffer, Init_Expr => "&" & Statement_Buffer_Repr & "[0]"); - Put_Format_Def - (File, - Instrumenter, - "unsigned char", - Decision_Buffer_Repr, - Array_Size => - Img (Any_Bit_Id'Max (1, UIC.Unit_Bits.Last_Outcome_Bit + 1))); + File.Put_Line + ("static unsigned char " & Decision_Buffer_Repr & "[" + & Img (Any_Bit_Id'Max (1, UIC.Unit_Bits.Last_Outcome_Bit + 1)) + & "];"); Put_Format_Def (File, Instrumenter, @@ -3080,13 +3078,10 @@ package body Instrument.C is Decision_Buffer, Init_Expr => "&" & Decision_Buffer_Repr & "[0]"); - Put_Format_Def - (File, - Instrumenter, - "unsigned char", - MCDC_Buffer_Repr, - Array_Size => - Img (Any_Bit_Id'Max (1, UIC.Unit_Bits.Last_Path_Bit + 1))); + File.Put_Line + ("static unsigned char " & MCDC_Buffer_Repr & "[" + & Img (Any_Bit_Id'Max (1, UIC.Unit_Bits.Last_Path_Bit + 1)) + & "];"); Put_Format_Def (File, Instrumenter, @@ -3094,6 +3089,8 @@ package body Instrument.C is MCDC_Buffer, Init_Expr => "&" & MCDC_Buffer_Repr & "[0]"); + -- Create the gnatcov_rts_coverage_buffers struct + Put_Format_Def (File, Instrumenter, From f06d3731a7d9ad8eb343d0d7141c7f977b9bfd31 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 30 Sep 2022 09:17:12 +0000 Subject: [PATCH 0028/1483] GNATcov_RTS: rename *unit_coverage_buffers* to *coverage_buffers* Coverage buffers always relate to a single unit, so the extra word in the already long name is redundant. TN: V728-002 Change-Id: I40a0aa5784ced9f8fbcfd84b690ad670dae71d55 --- tools/gnatcov/instrument-ada_unit.adb | 6 +++--- tools/gnatcov/instrument-c.adb | 12 ++++++------ tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads | 12 ++++++------ tools/gnatcov/rts/gnatcov_rts-buffers.ads | 4 ++-- .../rts/gnatcov_rts-traces-output-base64.adb | 7 +++---- .../rts/gnatcov_rts-traces-output-base64.ads | 4 ++-- .../gnatcov/rts/gnatcov_rts-traces-output-files.adb | 9 ++++----- .../gnatcov/rts/gnatcov_rts-traces-output-files.ads | 4 ++-- tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 13 ++++++------- .../rts/gnatcov_rts_c-traces-output-base64.c | 2 +- .../rts/gnatcov_rts_c-traces-output-base64.h | 2 +- .../gnatcov/rts/gnatcov_rts_c-traces-output-files.c | 4 ++-- .../gnatcov/rts/gnatcov_rts_c-traces-output-files.h | 4 ++-- tools/gnatcov/rts/gnatcov_rts_c-traces-output.c | 4 ++-- tools/gnatcov/rts/gnatcov_rts_c-traces-output.h | 3 +-- 15 files changed, 43 insertions(+), 47 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 94dc5e59f..486a75da0 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6922,7 +6922,7 @@ package body Instrument.Ada_Unit is File.New_Line; File.Put_Line (" Buffers : aliased constant" - & " GNATcov_RTS_Unit_Coverage_Buffers :="); + & " GNATcov_RTS_Coverage_Buffers :="); File.Put_Line (" (Fingerprint => " & To_String (Fingerprint) & ","); @@ -7371,7 +7371,7 @@ package body Instrument.Ada_Unit is begin File.Put_Line (" " & Buffer_Name - & " : aliased constant GNATcov_RTS_Unit_Coverage_Buffers;"); + & " : aliased constant GNATcov_RTS_Coverage_Buffers;"); File.Put_Line (" pragma Import (C, " & Buffer_Name & ",""" & Buffer_Name & """);"); end; @@ -7380,7 +7380,7 @@ package body Instrument.Ada_Unit is -- Create the list of coverage buffers File.Put_Line (" List : constant GNATcov_RTS.Buffers.Lists" - & ".Unit_Coverage_Buffers_Array := ("); + & ".Coverage_Buffers_Array := ("); for Cur in Instr_Units.Iterate loop declare use CU_Name_Vectors; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index d34af64ad..3f13899af 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -296,7 +296,7 @@ package body Instrument.C is function Unit_Buffers_Array_Name (IC : Inst_Context) return String is ("gnatcov_rts_buffers_array_" & (+IC.Project_Name)); -- Name of the symbol that references the - -- gnatcov_rts_unit_coverage_buffers_array struct (defined for the whole + -- gnatcov_rts_coverage_buffers_array struct (defined for the whole -- project). This struct is an array containing the coverage buffers of all -- of the instrumented units. -- @@ -3094,7 +3094,7 @@ package body Instrument.C is Put_Format_Def (File, Instrumenter, - "const struct gnatcov_rts_unit_coverage_buffers", + "const struct gnatcov_rts_coverage_buffers", Unit_Buffers_Name (UIC.Instrumented_Unit), Init_Expr => "{" @@ -3631,7 +3631,7 @@ package body Instrument.C is declare Buffer_Array_Decl : constant String := - "const struct gnatcov_rts_unit_coverage_buffers_array " + "const struct gnatcov_rts_coverage_buffers_array " & Unit_Buffers_Array_Name (IC); Buffer_Unit_Length : constant String := Count_Type'Image (Instr_Units.Length); @@ -3648,7 +3648,7 @@ package body Instrument.C is Put_Extern_Decl (File_Body, Self, - "const struct gnatcov_rts_unit_coverage_buffers", + "const struct gnatcov_rts_coverage_buffers", Unit_Buffers_Name (Instr_Unit)); end loop; @@ -3660,7 +3660,7 @@ package body Instrument.C is File_Body.Put_Line (Buffer_Array_Decl & " = {"); File_Body.Put_Line (" " & Buffer_Unit_Length & ","); File_Body.Put_Line - (" (const struct gnatcov_rts_unit_coverage_buffers *[]) {"); + (" (const struct gnatcov_rts_coverage_buffers *[]) {"); for Cur in Instr_Units.Iterate loop declare use CU_Name_Vectors; @@ -3682,7 +3682,7 @@ package body Instrument.C is Put_Extern_Decl (File_Header, Self, - "const struct gnatcov_rts_unit_coverage_buffers_array", + "const struct gnatcov_rts_coverage_buffers_array", Unit_Buffers_Array_Name (IC)); end Emit_Buffers_List_Unit; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads index c9d073b46..16f8fd8e9 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads @@ -28,16 +28,16 @@ package GNATcov_RTS.Buffers.Lists is pragma Preelaborate; - type GNATcov_RTS_Unit_Coverage_Buffers_Array is record + type GNATcov_RTS_Coverage_Buffers_Array is record Length : aliased unsigned; Buffers : System.Address; end record; - pragma Convention (C, GNATcov_RTS_Unit_Coverage_Buffers_Array); + pragma Convention (C, GNATcov_RTS_Coverage_Buffers_Array); - type Unit_Coverage_Buffers_Access is - access constant GNATcov_RTS_Unit_Coverage_Buffers; + type Coverage_Buffers_Access is + access constant GNATcov_RTS_Coverage_Buffers; - type Unit_Coverage_Buffers_Array is - array (Positive range <>) of Unit_Coverage_Buffers_Access; + type Coverage_Buffers_Array is + array (Positive range <>) of Coverage_Buffers_Access; end GNATcov_RTS.Buffers.Lists; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index 6663ba04a..3d00fbc33 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -66,7 +66,7 @@ package GNATcov_RTS.Buffers is -- Hash type to perform consistency checks over Source Coverage -- Obligations. 20-byte to hold a SHA-1. - type GNATcov_RTS_Unit_Coverage_Buffers is record + type GNATcov_RTS_Coverage_Buffers is record Fingerprint : SCOs_Hash; Language : Any_Language_Kind; Unit_Part : Any_Unit_Part; @@ -76,7 +76,7 @@ package GNATcov_RTS.Buffers is Statement_Last_Bit, Decision_Last_Bit, MCDC_Last_Bit : Any_Bit_Id; end record; - pragma Convention (C, GNATcov_RTS_Unit_Coverage_Buffers); + pragma Convention (C, GNATcov_RTS_Coverage_Buffers); ------------------------- -- Witness subprograms -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb index 92b9671d2..b2150e98c 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb @@ -30,7 +30,7 @@ with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; package body GNATcov_RTS.Traces.Output.Base64 is procedure Write_Trace_File_C - (Buffers : GNATcov_RTS_Unit_Coverage_Buffers_Array; + (Buffers : GNATcov_RTS_Coverage_Buffers_Array; Program_Name : GNATcov_RTS_String; Exec_Date : Unsigned_64; User_Data : GNATcov_RTS_String); @@ -42,15 +42,14 @@ package body GNATcov_RTS.Traces.Output.Base64 is ---------------------- procedure Write_Trace_File - (Buffers : Unit_Coverage_Buffers_Array; + (Buffers : Coverage_Buffers_Array; Program_Name : String; Exec_Date : Unsigned_64; User_Data : String := "") is begin Write_Trace_File_C - (GNATcov_RTS_Unit_Coverage_Buffers_Array' - (Length => Buffers'Length, Buffers => Buffers'Address), + ((Buffers'Length, Buffers'Address), (Program_Name'Address, Program_Name'Length), Exec_Date, (User_Data'Address, User_Data'Length)); diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads index 12e4e20b8..a8bcc082d 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads @@ -31,13 +31,13 @@ with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; package GNATcov_RTS.Traces.Output.Base64 is procedure Write_Trace_File - (Buffers : Unit_Coverage_Buffers_Array; + (Buffers : Coverage_Buffers_Array; Program_Name : String; Exec_Date : Unsigned_64; User_Data : String := ""); procedure Write_Trace_File_Wrapper - (Buffers : Unit_Coverage_Buffers_Array; + (Buffers : Coverage_Buffers_Array; Program_Name : String; Exec_Date : Unsigned_64; User_Data : String := "") renames Write_Trace_File; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb index ef6af3d6f..8e25975c8 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb @@ -36,7 +36,7 @@ with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; package body GNATcov_RTS.Traces.Output.Files is function Write_Trace_File_C - (Buffers : GNATcov_RTS_Unit_Coverage_Buffers_Array; + (Buffers : GNATcov_RTS_Coverage_Buffers_Array; Filename : chars_ptr; Program_Name : GNATcov_RTS_String; Exec_Date : Unsigned_64; @@ -95,7 +95,7 @@ package body GNATcov_RTS.Traces.Output.Files is ---------------------- procedure Write_Trace_File - (Buffers : Unit_Coverage_Buffers_Array; + (Buffers : Coverage_Buffers_Array; Filename : String := Default_Trace_Filename; Program_Name : String := Ada.Command_Line.Command_Name; Exec_Date : Time := Clock; @@ -104,8 +104,7 @@ package body GNATcov_RTS.Traces.Output.Files is Filename_C : chars_ptr := New_String (Filename); begin if Write_Trace_File_C - (GNATcov_RTS_Unit_Coverage_Buffers_Array' - (Length => Buffers'Length, Buffers => Buffers'Address), + ((Buffers'Length, Buffers'Address), Filename_C, (Program_Name'Address, Program_Name'Length), Interfaces.Unsigned_64 (Exec_Date), @@ -122,7 +121,7 @@ package body GNATcov_RTS.Traces.Output.Files is ------------------------------ procedure Write_Trace_File_Wrapper - (Buffers : Unit_Coverage_Buffers_Array; + (Buffers : Coverage_Buffers_Array; Filename : String := Default_Trace_Filename; Program_Name : String := Ada.Command_Line.Command_Name; Exec_Date : Time := Clock; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads index 80d486867..42c4150de 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads @@ -57,7 +57,7 @@ package GNATcov_RTS.Traces.Output.Files is -- Exception we raise in case of errors during the trace file creation procedure Write_Trace_File - (Buffers : Unit_Coverage_Buffers_Array; + (Buffers : Coverage_Buffers_Array; Filename : String := Default_Trace_Filename; Program_Name : String := Ada.Command_Line.Command_Name; Exec_Date : Time := Clock; @@ -66,7 +66,7 @@ package GNATcov_RTS.Traces.Output.Files is -- If unsuccessful, raise IO_Error and leave the error code in errno. procedure Write_Trace_File_Wrapper - (Buffers : Unit_Coverage_Buffers_Array; + (Buffers : Coverage_Buffers_Array; Filename : String := Default_Trace_Filename; Program_Name : String := Ada.Command_Line.Command_Name; Exec_Date : Time := Clock; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index 9633e59bd..220d59310 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -66,7 +66,7 @@ extern "C" FILE_BASED_LANGUAGE = 1 }; - struct gnatcov_rts_unit_coverage_buffers + struct gnatcov_rts_coverage_buffers { /* Hash of SCO info for this unit, as gnatcov computes it (see SC_Obligations). Used as a fast way to check that coverage obligations @@ -97,10 +97,9 @@ extern "C" file-based languages (otherwise, it is an empty string). */ struct gnatcov_rts_string project_name; - /* Addresses of coverage buffers for statement obligations, decision - obligations and MC/DC obligations. The address refer to - Coverage_Buffer_Type arrays whose bounds go from 0 to - unit_coverage_buffers.*_last_bit. */ + /* Pointers to coverage buffers for statement obligations, decision + obligations and MC/DC obligations. The size of each array is in the + corresponding *_last_bit field. */ uint8_t *statement, *decision, *mcdc; /* Index for the last bits in coverage buffers for statements, decisions @@ -109,10 +108,10 @@ extern "C" }; /* Array of unit coverage buffers. */ - struct gnatcov_rts_unit_coverage_buffers_array + struct gnatcov_rts_coverage_buffers_array { unsigned length; - const struct gnatcov_rts_unit_coverage_buffers **buffers; + const struct gnatcov_rts_coverage_buffers **buffers; }; /***********************/ diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c index 4dd4dd55a..2ee732fd8 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c @@ -126,7 +126,7 @@ write_bytes (void *output, const void *bytes, unsigned count) void gnatcov_rts_write_trace_file_base64 ( - const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + const struct gnatcov_rts_coverage_buffers_array *buffers, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data) { diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h index c6c6ba1b5..a731749be 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h @@ -30,7 +30,7 @@ extern "C" documentation of the gnatcov_rts_generic_write_trace_file function in gnatcov_rts_c-output.h for more information. */ extern void gnatcov_rts_write_trace_file_base64 ( - const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + const struct gnatcov_rts_coverage_buffers_array *buffers, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data); diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c index 65f93865b..50edf3bab 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c @@ -154,7 +154,7 @@ gnatcov_rts_default_trace_filename (const char *env_var, const char *prefix, /* See gnatcov_rts_c-traces-output-files.h. */ int gnatcov_rts_write_trace_file ( - const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + const struct gnatcov_rts_coverage_buffers_array *buffers, const char *filename, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data) { @@ -171,7 +171,7 @@ gnatcov_rts_write_trace_file ( /* See gnatcov_rts_c-traces-output-files.h. */ void gnatcov_rts_write_trace_file_wrapper ( - const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + const struct gnatcov_rts_coverage_buffers_array *buffers, const char *filename, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data) { diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h index 0d86db783..db1535b01 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h @@ -65,14 +65,14 @@ extern "C" Return 0 if the trace creation was successful, 1 otherwise. In case of error, ERRNO is left to the number for the cause of error. */ extern int gnatcov_rts_write_trace_file ( - const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + const struct gnatcov_rts_coverage_buffers_array *buffers, const char *filename, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data); /* Call gnatcov_rts_write_trace_file and print an error message on the standard error if the trace could not be created. */ extern void gnatcov_rts_write_trace_file_wrapper ( - const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + const struct gnatcov_rts_coverage_buffers_array *buffers, const char *filename, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data); diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index 422517e16..1a9265044 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -115,7 +115,7 @@ write_buffer (gnatcov_rts_write_bytes_callback write_bytes, void *output, /* Write a coverage buffer (unit information + coverage bit buffers). */ static void write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, - const struct gnatcov_rts_unit_coverage_buffers *buffers) + const struct gnatcov_rts_coverage_buffers *buffers) { struct trace_entry_header header; header.unit_name_length = (uint32_t) buffers->unit_name.length; @@ -166,7 +166,7 @@ write_date (gnatcov_rts_write_bytes_callback write_bytes, void *output, /* See gnatcov_rts_c-traces-output.h. */ int gnatcov_rts_generic_write_trace_file ( - void *output, const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + void *output, const struct gnatcov_rts_coverage_buffers_array *buffers, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data, gnatcov_rts_write_bytes_callback write_bytes) diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h index fef2b66d5..f23156b16 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h @@ -38,8 +38,7 @@ extern "C" USER_DATA are included as metadata in the trace file. Return 0 if the write was successful, and return any non-zero value in case of error. */ extern int gnatcov_rts_generic_write_trace_file ( - void *output, - const struct gnatcov_rts_unit_coverage_buffers_array *buffers, + void *output, const struct gnatcov_rts_coverage_buffers_array *buffers, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data, gnatcov_rts_write_bytes_callback write_bytes); From b56202484843427379523eb9da98393f73c27620 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 3 Oct 2022 09:17:05 +0000 Subject: [PATCH 0029/1483] Instrument: make Ada buffers list units preelaborate These units are supposed to contain constant and static (in the C sense) data: they should be preelaborate to make sure this is the case. TN: V728-002 Change-Id: I3db1e49ebe25dd9c6893da916725039d955a0a08 --- tools/gnatcov/instrument-ada_unit.adb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 486a75da0..fa195e984 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -7362,6 +7362,8 @@ package body Instrument.Ada_Unit is File.New_Line; File.Put_Line ("package " & Unit_Name & " is"); File.New_Line; + File.Put_Line (" pragma Preelaborate;"); + File.New_Line; -- Import all the coverage buffers From ddf3f8f963232699920a423313c9045a4633f9d0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 3 Oct 2022 14:10:22 +0000 Subject: [PATCH 0030/1483] dump-src-trace: add a missing space in the output no-tn-check Change-Id: I3734a2880456313121c0368268d57270b16dabac --- tools/gnatcov/instrument-input_traces.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index b9e2215cc..be6b56c6c 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -857,7 +857,7 @@ package body Instrument.Input_Traces is Put ("Unit " & To_Ada (CU_Name.Unit) & " (" & CU_Name.Part'Image & ", hash="); when GNATcov_RTS.Buffers.File_Based_Language => - Put ("Unit" & (+CU_Name.Filename) & " (hash="); + Put ("Unit " & (+CU_Name.Filename) & " (hash="); end case; for B of Fingerprint loop From 5f6381c48fb773a3e7494b710637dd3135f0fcd2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 4 Oct 2022 11:38:13 +0000 Subject: [PATCH 0031/1483] dump-src-trace: fix the dump of coverage buffers The logic to dump coverage buffers for the dump-src-trace command is wrong, as it unconditionally displays "" for buffers, even the non-empty ones: Statement buffer: [0-2] 0 2 Decision buffer: [0-1] MCDC buffer: [0-2] This patch fixes this logic so that the above becomes: Statement buffer: [0-2] 0 2 Decision buffer: [0-1] MCDC buffer: [0-2] no-tn-check Change-Id: I12f15b82f3765fb730d46572b806b7d5c99e86b9 --- tools/gnatcov/instrument-input_traces.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index be6b56c6c..d39ce9c5b 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -890,7 +890,7 @@ package body Instrument.Input_Traces is Put ("]"); for Bit_Id in Buffer'Range loop if Buffer (Bit_Id) then - Is_Empty := True; + Is_Empty := False; Put (Bit_Id'Image); end if; end loop; From 379550581ce9be69fa3f7e5d300b8e1f24d11af0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 5 Oct 2022 09:52:33 +0000 Subject: [PATCH 0032/1483] Instrument.C: rework "sources of interest" filtering This is preparatory work to support the coverage of C headers: no change of behavior expected for now. This commit extends code that determines if a Clang cursor belongs to a source file for which we want to compute code coverage (ad hoc notion of "source of interest", previously called "unit of interest", but C headers are not units of interest on their own for gnatcov). Instead of only computing if it is a source of interest, it now also registers it in the gnatcov's file table and computes its related project file. Both bits of information will be necessary when creating dedicated coverage buffers for C headers. TN: V728-002 Change-Id: I25b65c4a4a1887036b52babc7fa1598742091f69 --- tools/gnatcov/instrument-c.adb | 61 +++++++++++++++++++++++++--- tools/gnatcov/instrument-c.ads | 37 +++++++++++++++++ tools/gnatcov/instrument-c_utils.adb | 29 ------------- tools/gnatcov/instrument-c_utils.ads | 11 ----- 4 files changed, 92 insertions(+), 46 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 3f13899af..268740fde 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -18,12 +18,10 @@ with Ada.Characters.Handling; with Ada.Containers; use Ada.Containers; -with Ada.Containers.Hashed_Maps; with Ada.Directories; use Ada.Directories; -with Ada.Strings; -with Ada.Strings.Unbounded.Hash; with Ada.Text_IO; use Ada.Text_IO; +with Clang.CX_String; use Clang.CX_String; with Clang.Extensions; use Clang.Extensions; with GNAT.OS_Lib; use GNAT.OS_Lib; @@ -40,7 +38,6 @@ with Command_Line; with ALI_Files; use ALI_Files; with Coverage; use Coverage; with Coverage_Options; -with Files_Table; use Files_Table; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Hex_Images; use Hex_Images; with Instrument.C_Utils; use Instrument.C_Utils; @@ -2008,7 +2005,7 @@ package body Instrument.C is -- For now, instrument only cursors that come from the file being -- instrumented, and do not instrument included code. - if Is_Null (N) or else not Is_Unit_Of_Interest (N, +UIC.File) then + if Is_Null (N) or else not Is_Source_Of_Interest (UIC, N) then return; end if; @@ -2157,7 +2154,7 @@ package body Instrument.C is -- interest. begin - if Is_Unit_Of_Interest (N, +UIC.File) then + if Is_Source_Of_Interest (UIC, N) then case Kind (N) is @@ -4023,4 +4020,56 @@ package body Instrument.C is +Info.Output_Dir).all; end Import_Options; + --------------------------- + -- Is_Source_Of_Interest -- + --------------------------- + + function Is_Source_Of_Interest + (UIC : in out C_Unit_Inst_Context; N : Cursor_T) return Boolean + is + -- Determine the file from which N originates + + C_File : aliased String_T; + Line : aliased unsigned; + Column : aliased unsigned; + Loc : constant Source_Location_T := Get_Cursor_Location (N); + File : Unbounded_String; + begin + Get_Presumed_Location (Location => Loc, + Filename => C_File'Access, + Line => Line'Access, + Column => Column'Access); + File := +Get_C_String (C_File); + + -- Look for a corresponding entry in UIC.Sources_Of_Interest, create one + -- if it is missing. + + declare + use Source_Of_Interest_Maps; + + Cur : constant Cursor := UIC.Sources_Of_Interest.Find (File); + SOI : Source_Of_Interest; + begin + if Has_Element (Cur) then + return UIC.Sources_Of_Interest.Reference (Cur).Of_Interest; + end if; + + if File = UIC.File then + SOI := + (Of_Interest => True, + SFI => Get_Index_From_Generic_Name + (+File, Source_File), + CU_Name => + CU_Name_For_File + (Filename => +Simple_Name (+File), + Project_Name => UIC.Instrumented_Unit.Project_Name)); + else + SOI := (Of_Interest => False); + end if; + UIC.Sources_Of_Interest.Insert (File, SOI); + + return SOI.Of_Interest; + end; + end Is_Source_Of_Interest; + end Instrument.C; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index a9d7e3cf8..eb42972bc 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -18,10 +18,12 @@ -- Instrumentation of a C source file +with Ada.Containers.Hashed_Maps; with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; with Ada.Finalization; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Strings.Unbounded.Hash; with GNATCOLL.Projects; @@ -31,6 +33,7 @@ with Types; use Types; with Clang.Index; use Clang.Index; with Clang.Rewrite; use Clang.Rewrite; +with Files_Table; use Files_Table; with Instrument.Base_Types; use Instrument.Base_Types; with Instrument.Common; use Instrument.Common; with SC_Obligations; use SC_Obligations; @@ -279,6 +282,26 @@ package Instrument.C is -- Shortcut to call Import_From_Project, and Import_From_Agrs on the -- --c-opts/--c++-opts option. + type Source_Of_Interest (Of_Interest : Boolean := False) is record + case Of_Interest is + when False => + null; + when True => + SFI : Valid_Source_File_Index; + CU_Name : Compilation_Unit_Name; + end case; + end record; + -- Descriptor for a source file: Of_Interest determines if we should + -- compute its code coverage. If we are, SFI is the corresponding index in + -- gnatcov's file table and Project_Name is the name of the project that + -- owns this source file. + + package Source_Of_Interest_Maps is new Ada.Containers.Hashed_Maps + (Key_Type => Unbounded_String, + Element_Type => Source_Of_Interest, + Hash => Hash, + Equivalent_Keys => "="); + type C_Unit_Inst_Context is new Instrument.Common.Unit_Inst_Context with record TU : Translation_Unit_T; @@ -308,11 +331,25 @@ package Instrument.C is LL_PP_Info_Map : LL_SCO_PP_Info_Maps.Map; -- Preprocessing information for low level SCOs + Sources_Of_Interest : Source_Of_Interest_Maps.Map; + -- Records for each source file processed during the instrumentation + -- whether it is a source of interest, and some properties if it is. end record; type C_Source_Rewriter is tagged limited private; -- Helper object to instrument a source file + function Is_Source_Of_Interest + (UIC : in out C_Unit_Inst_Context; N : Cursor_T) return Boolean; + -- Track the source file from which N originates in + -- UIC.Sources_Of_Interest. Return whether this source file is a source of + -- interest. + -- + -- TODO??? For now, only the source file from which instrumentation started + -- (the "body" C/C++ file, i.e. UIC.File) is considered as a source of + -- interest, i.e. code inserted by #include is not instrumented and + -- excluded from coverage analysis. + private type Pass_Kind is abstract tagged null record; diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index 00e9115d9..d92422b95 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -22,7 +22,6 @@ with System; use System; with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Conversion; -with Clang.CX_String; use Clang.CX_String; with Clang.Extensions; use Clang.Extensions; package body Instrument.C_Utils is @@ -197,34 +196,6 @@ package body Instrument.C_Utils is return Res; end Get_Lambda_Exprs; - ------------------------- - -- Is_Unit_Of_Interest -- - ------------------------- - - function Is_Unit_Of_Interest - (N : Cursor_T; - Filename : String) return Boolean - is - File : aliased String_T; - Line : aliased unsigned; - Column : aliased unsigned; - Loc : constant Source_Location_T := Get_Cursor_Location (N); - begin - Get_Presumed_Location (Location => Loc, - Filename => File'Access, - Line => Line'Access, - Column => Column'Access); - declare - Cursor_Filename : constant String := Get_C_String (File); - begin - -- For now, just retrieve SCO for the file being instrumented. - -- TODO: determine what should be done for included code (inlines - -- function, expanded macro coming from another file etc.) - - return Cursor_Filename = Filename; - end; - end Is_Unit_Of_Interest; - --------------- -- To_Vector -- --------------- diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 2bdca03f0..248d74d2d 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -79,17 +79,6 @@ package Instrument.C_Utils is -- Return the lambda expressions in a node and its descendents if any, -- except the lambda expressions nested in other lambda expressions. - function Is_Unit_Of_Interest - (N : Cursor_T; - Filename : String) return Boolean; - -- True if the node N corresponds to code originating from a unit of - -- interest. This is used to avoid instrumenting included code (that comes - -- from preprocessing). - -- - -- TODO: For now, we make an even stronger assumption, and only return True - -- for code that originates from the file being processed (e.g. included - -- code won't be considered). - function To_Vector (N : Cursor_T) return Cursor_Vectors.Vector; -- Turn the node N into a single element node vector From 64e7bd169d7a156ce93de3df64e3bf1540e04601 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 7 Oct 2022 09:39:43 +0000 Subject: [PATCH 0033/1483] Instrument.C: add "overriding" to Pass_Kind overriding primitives This is good practice in general, and will make the compiler complain if for some reason the procedure is no longer considered as a primitive (for instance, accidental subprogram spec desync with the Pass_Kind primitive). Change-Id: I91d7d56de97ebaddbaa6296a3bcc2e08500d3db9 TN: V728-002 --- tools/gnatcov/instrument-c.adb | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 268740fde..e42104a52 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -156,7 +156,7 @@ package body Instrument.C is type Record_PP_Info_Pass_Kind is new Pass_Kind with null record; - procedure Append_SCO + overriding procedure Append_SCO (Pass : Record_PP_Info_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; N : Cursor_T; @@ -170,7 +170,7 @@ package body Instrument.C is type Instrument_Pass_Kind is new Pass_Kind with null record; - procedure Append_SCO + overriding procedure Append_SCO (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; N : Cursor_T; @@ -181,7 +181,7 @@ package body Instrument.C is -- Append a SCO to SCOs.SCO_Table, and complete the preprocessing info with -- the preprocessed source range. - procedure Instrument_Statement + overriding procedure Instrument_Statement (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; @@ -189,7 +189,7 @@ package body Instrument.C is Instr_Scheme : Instr_Scheme_Type); -- Add an entry to UIC.Source_Statements - procedure Instrument_Decision + overriding procedure Instrument_Decision (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; @@ -197,7 +197,7 @@ package body Instrument.C is State : US.Unbounded_String); -- Add an entry to UIC.Source_Decisions - procedure Instrument_Condition + overriding procedure Instrument_Condition (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; @@ -206,13 +206,13 @@ package body Instrument.C is First : Boolean); -- Add an entry to UIC.Source_Conditions - procedure Curlify + overriding procedure Curlify (Pass : Instrument_Pass_Kind; N : Cursor_T; Rew : Rewriter_T); -- Wrapper around Instrument.C.Utils.Curlify - procedure Insert_MCDC_State + overriding procedure Insert_MCDC_State (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; Name : String; @@ -553,7 +553,7 @@ package body Instrument.C is -- Append_SCO -- ---------------- - procedure Append_SCO + overriding procedure Append_SCO (Pass : Record_PP_Info_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; N : Cursor_T; @@ -764,7 +764,7 @@ package body Instrument.C is -- Append_SCO -- ---------------- - procedure Append_SCO + overriding procedure Append_SCO (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; N : Cursor_T; @@ -826,7 +826,7 @@ package body Instrument.C is -- Curlify -- ------------- - procedure Curlify + overriding procedure Curlify (Pass : Instrument_Pass_Kind; N : Cursor_T; Rew : Rewriter_T) is begin Curlify (N, Rew); @@ -836,7 +836,7 @@ package body Instrument.C is -- Insert_MCDC_State -- ----------------------- - procedure Insert_MCDC_State + overriding procedure Insert_MCDC_State (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; Name : String; @@ -849,7 +849,7 @@ package body Instrument.C is -- Instrument_Statement -- -------------------------- - procedure Instrument_Statement + overriding procedure Instrument_Statement (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; @@ -867,7 +867,7 @@ package body Instrument.C is -- Instrument_Decision -- ------------------------- - procedure Instrument_Decision + overriding procedure Instrument_Decision (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; @@ -885,7 +885,7 @@ package body Instrument.C is -- Instrument_Condition -- -------------------------- - procedure Instrument_Condition + overriding procedure Instrument_Condition (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; From 42865f04f60f954abd552b8a335b41624b9f0241 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 7 Oct 2022 09:43:25 +0000 Subject: [PATCH 0034/1483] instrument-c.adb: minor reformatting TN: V728-002 Change-Id: Idc5b33858843d036808a78ae7b0cff9231243f83 --- tools/gnatcov/instrument-c.adb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index e42104a52..e9f5956df 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -760,10 +760,6 @@ package body Instrument.C is UIC.LL_PP_Info_Map.Insert (SCOs.SCO_Table.Last, Info); end Append_SCO; - ---------------- - -- Append_SCO -- - ---------------- - overriding procedure Append_SCO (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; From 9af3edaf03de8303c6c91ee486a38185160f910a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 29 Sep 2022 13:06:32 +0000 Subject: [PATCH 0035/1483] GNATcov_RTS: allow multiple sets of coverage buffers in a buffer unit This commit changes the data structures in GNATcov_RTS used to represent lists of coverage buffers so that the instrumenter can easily create multiple sets of coverage buffers (i.e. multiple gnatcov_rts_coverage_buffers structs/records) for a single source file. This is preparatory work for the coverage of C headers, which will be instrumented once per inclusion in a C "body" source file: when processing C bodies, the instrumenter needs to create one set of buffers for the C body itself, but also one per included C header that has coverage obligations. Change-Id: I8b3ef44fe5520256398fa09835a5a4287d389012 TN: V728-002 --- tools/gnatcov/instrument-ada_unit.adb | 26 +++- tools/gnatcov/instrument-c.adb | 112 ++++++++++-------- tools/gnatcov/instrument-common.ads | 8 +- .../gnatcov/rts/gnatcov_rts-buffers-lists.ads | 30 ++++- .../rts/gnatcov_rts-traces-output-base64.adb | 19 ++- .../rts/gnatcov_rts-traces-output-base64.ads | 16 +-- .../rts/gnatcov_rts-traces-output-files.adb | 35 +++--- .../rts/gnatcov_rts-traces-output-files.ads | 22 ++-- tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 13 +- .../rts/gnatcov_rts_c-traces-output-base64.c | 4 +- .../rts/gnatcov_rts_c-traces-output-base64.h | 2 +- .../rts/gnatcov_rts_c-traces-output-files.c | 12 +- .../rts/gnatcov_rts_c-traces-output-files.h | 6 +- .../gnatcov/rts/gnatcov_rts_c-traces-output.c | 14 ++- .../gnatcov/rts/gnatcov_rts_c-traces-output.h | 7 +- 15 files changed, 199 insertions(+), 127 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index fa195e984..c3a47004f 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6837,6 +6837,8 @@ package body Instrument.Ada_Unit is To_Filename (Info.Project, CU_Name, Switches.Ada_Language)); Put_Warnings_And_Style_Checks_Pragmas (File); File.Put_Line ("with Interfaces.C; use Interfaces.C;"); + File.Put_Line + ("with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists;"); declare Pkg_Name : constant String := To_Ada (CU_Name.Unit); @@ -6886,6 +6888,10 @@ package body Instrument.Ada_Unit is File.New_Line; File.Put_Line (" pragma Preelaborate;"); File.New_Line; + + -- Create declarations for individual buffers (statement, decision + -- and MC/DC) as well as their exported addresses. + File.Put_Line (" Statement_Buffer : Coverage_Buffer_Type" & " (0 .. " & Statement_Last_Bit & ") :=" & " (others => False);"); @@ -6916,6 +6922,8 @@ package body Instrument.Ada_Unit is & """);"); File.New_Line; + -- Create the GNATcov_RTS_Coverage_Buffers record + File.Put_Line (" Unit_Name : constant String := """ & Unit_Name & """;"); File.Put_Line (" Project_Name : constant String := """";"); @@ -6943,9 +6951,21 @@ package body Instrument.Ada_Unit is File.Put_Line (" Decision_Last_Bit => " & Decision_Last_Bit & ","); File.Put_Line (" MCDC_Last_Bit => " & MCDC_Last_Bit & ");"); - File.Put_Line (" pragma Export (C, Buffers, """ + File.New_Line; + + -- Create the buffers group + + File.Put_Line + (" Buffers_Group : aliased constant Coverage_Buffers_Group :=" + & " (1 => Buffers'Access);"); + File.Put_Line + (" C_Buffers_Group : aliased constant" + & " GNATcov_RTS_Coverage_Buffers_Group :=" + & " (1, Buffers_Group'Address);"); + File.Put_Line (" pragma Export (C, C_Buffers_Group, """ & Unit_Buffers_Name (UIC.Instrumented_Unit) & """);"); File.New_Line; + File.Put_Line ("end " & Pkg_Name & ";"); end; end Emit_Buffer_Unit; @@ -7373,7 +7393,7 @@ package body Instrument.Ada_Unit is begin File.Put_Line (" " & Buffer_Name - & " : aliased constant GNATcov_RTS_Coverage_Buffers;"); + & " : aliased constant GNATcov_RTS_Coverage_Buffers_Group;"); File.Put_Line (" pragma Import (C, " & Buffer_Name & ",""" & Buffer_Name & """);"); end; @@ -7382,7 +7402,7 @@ package body Instrument.Ada_Unit is -- Create the list of coverage buffers File.Put_Line (" List : constant GNATcov_RTS.Buffers.Lists" - & ".Coverage_Buffers_Array := ("); + & ".Coverage_Buffers_Group_Array := ("); for Cur in Instr_Units.Iterate loop declare use CU_Name_Vectors; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index e9f5956df..1d19d8ee6 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3006,6 +3006,13 @@ package body Instrument.C is "__" & Decision_Buffer_Symbol (UIC.Instrumented_Unit); MCDC_Buffer_Repr : constant String := "__" & MCDC_Buffer_Symbol (UIC.Instrumented_Unit); + + Buffers_Record : constant String := "__xcov_buffers"; + -- Name of the gnatcov_rts_coverage_buffers struct for this unit + + Buffers_Group_Array : constant String := "__xcov_buffers_group"; + -- Name of the array of gnatcov_rts_coverage_buffers struct for this + -- unit. begin Create_File (Info, File, +CU_Name.Filename); @@ -3084,52 +3091,62 @@ package body Instrument.C is -- Create the gnatcov_rts_coverage_buffers struct + File.Put_Line + ("static const struct gnatcov_rts_coverage_buffers " + & Buffers_Record & " = {" + & ASCII.LF + & " .fingerprint = " & To_String (Fingerprint) & "," + & ASCII.LF + & " .language_kind = FILE_BASED_LANGUAGE," + & ASCII.LF + & " .unit_part = NOT_APPLICABLE_PART," + & ASCII.LF + + -- Old toolchains (for instance GNAT Pro 7.1.2) consider that + -- "STR()" is not a static expression, and thus + -- refuse using STR to initialize a global data structure. To + -- workaround this, emit a gnatcov_rtr_string literal ourselves. + + & " .unit_name = " & Format_Str_Constant (Unit_Name) & "," + & ASCII.LF + & " .project_name = " & Format_Str_Constant (Project_Name) & "," + & ASCII.LF + + -- We do not use the created pointer (Statement_Buffer) to + -- initialize the buffer fields, as this is rejected by old + -- versions of the compiler (up to the 20 version): the + -- initializer element is considered not constant. To work around + -- it, we simply use the original expression instead of using a + -- wrapper pointer. + + & " .statement = &" & Statement_Buffer_Repr & "[0]," + & ASCII.LF + & " .decision = &" & Decision_Buffer_Repr & "[0]," + & ASCII.LF + & " .mcdc = &" & MCDC_Buffer_Repr & "[0]," + & ASCII.LF + + & " .statement_last_bit = " & Statement_Last_Bit & "," + & ASCII.LF + & " .decision_last_bit = " & Decision_Last_Bit & "," + & ASCII.LF + & " .mcdc_last_bit = " & MCDC_Last_Bit + & ASCII.LF + & "};"); + + -- Create the buffers group: first the array of buffers (static), + -- then the gnatcov_rts_coverage_buffers_group struct (extern). + + File.Put_Line ("static const struct gnatcov_rts_coverage_buffers *" + & Buffers_Group_Array & "[] = {"); + File.Put_Line (" &" & Buffers_Record); + File.Put_Line ("};"); Put_Format_Def (File, Instrumenter, - "const struct gnatcov_rts_coverage_buffers", + "const struct gnatcov_rts_coverage_buffers_group", Unit_Buffers_Name (UIC.Instrumented_Unit), - Init_Expr => - "{" - & ASCII.LF - & " .fingerprint = " & To_String (Fingerprint) & "," - & ASCII.LF - & " .language_kind = FILE_BASED_LANGUAGE," - & ASCII.LF - & " .unit_part = NOT_APPLICABLE_PART," - & ASCII.LF - - -- Old toolchains (for instance GNAT Pro 7.1.2) consider that - -- "STR()" is not a static expression, and thus - -- refuse using STR to initialize a global data structure. To - -- workaround this, emit a gnatcov_rtr_string literal ourselves. - - & " .unit_name = " & Format_Str_Constant (Unit_Name) & "," - & ASCII.LF - & " .project_name = " & Format_Str_Constant (Project_Name) & "," - & ASCII.LF - - -- We do not use the created pointer (Statement_Buffer) to - -- initialize the buffer fields, as this is rejected by old - -- versions of the compiler (up to the 20 version): the - -- initializer element is considered not constant. To work - -- around it, we simply use the original expression instead of - -- using a wrapper pointer. - - & " .statement = &" & Statement_Buffer_Repr & "[0]," - & ASCII.LF - & " .decision = &" & Decision_Buffer_Repr & "[0]," - & ASCII.LF - & " .mcdc = &" & MCDC_Buffer_Repr & "[0]," - & ASCII.LF - - & " .statement_last_bit = " & Statement_Last_Bit & "," - & ASCII.LF - & " .decision_last_bit = " & Decision_Last_Bit & "," - & ASCII.LF - & " .mcdc_last_bit = " & MCDC_Last_Bit - & ASCII.LF - & "}"); + Init_Expr => "{1, " & Buffers_Group_Array & "}"); end; end Emit_Buffer_Unit; @@ -3624,7 +3641,7 @@ package body Instrument.C is declare Buffer_Array_Decl : constant String := - "const struct gnatcov_rts_coverage_buffers_array " + "const struct gnatcov_rts_coverage_buffers_group_array " & Unit_Buffers_Array_Name (IC); Buffer_Unit_Length : constant String := Count_Type'Image (Instr_Units.Length); @@ -3635,13 +3652,14 @@ package body Instrument.C is File_Body.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); - -- First create extern declarations for each individual unit buffer + -- First create extern declarations for the buffers group of each + -- unit. for Instr_Unit of Instr_Units loop Put_Extern_Decl (File_Body, Self, - "const struct gnatcov_rts_coverage_buffers", + "const struct gnatcov_rts_coverage_buffers_group", Unit_Buffers_Name (Instr_Unit)); end loop; @@ -3653,7 +3671,7 @@ package body Instrument.C is File_Body.Put_Line (Buffer_Array_Decl & " = {"); File_Body.Put_Line (" " & Buffer_Unit_Length & ","); File_Body.Put_Line - (" (const struct gnatcov_rts_coverage_buffers *[]) {"); + (" (const struct gnatcov_rts_coverage_buffers_group *[]) {"); for Cur in Instr_Units.Iterate loop declare use CU_Name_Vectors; @@ -3675,7 +3693,7 @@ package body Instrument.C is Put_Extern_Decl (File_Header, Self, - "const struct gnatcov_rts_coverage_buffers_array", + "const struct gnatcov_rts_coverage_buffers_group_array", Unit_Buffers_Array_Name (IC)); end Emit_Buffers_List_Unit; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 70e0e1608..f794c07e8 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -137,12 +137,12 @@ package Instrument.Common is function Buffer_Unit (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name; -- Given a unit to instrument, return the name of the unit that holds - -- its coverage buffers (Coverage_Buffer_Type and Unit_Coverage_Buffers - -- records). + -- its coverage buffers (Coverage_Buffer_Type and + -- GNATcov_RTS_Coverage_Buffers records). function Unit_Buffers_Name (Unit : Compilation_Unit_Name) return String; - -- Name of the symbol that references the gnatcov_rts_unit_coverage_buffers - -- struct for this unit. + -- Name of the symbol that references the + -- gnatcov_rts_coverage_buffers_group struct for this unit. function Project_Output_Dir (Project : Project_Type) return String; -- Return the directory in which we must create instrumented sources for diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads index 16f8fd8e9..7fc1a14d8 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads @@ -28,16 +28,34 @@ package GNATcov_RTS.Buffers.Lists is pragma Preelaborate; - type GNATcov_RTS_Coverage_Buffers_Array is record + type Coverage_Buffers_Access is + access constant GNATcov_RTS_Coverage_Buffers; + pragma Convention (C, Coverage_Buffers_Access); + + type Coverage_Buffers_Group is + array (Positive range <>) of Coverage_Buffers_Access; + pragma Convention (C, Coverage_Buffers_Group); + + type GNATcov_RTS_Coverage_Buffers_Group is record Length : aliased unsigned; Buffers : System.Address; + -- Address of a Coverage_Buffers_Group array of Length items end record; - pragma Convention (C, GNATcov_RTS_Coverage_Buffers_Array); + pragma Convention (C, GNATcov_RTS_Coverage_Buffers_Group); - type Coverage_Buffers_Access is - access constant GNATcov_RTS_Coverage_Buffers; + type Coverage_Buffers_Group_Access is + access constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Convention (C, Coverage_Buffers_Group_Access); - type Coverage_Buffers_Array is - array (Positive range <>) of Coverage_Buffers_Access; + type Coverage_Buffers_Group_Array is + array (Positive range <>) of Coverage_Buffers_Group_Access; + pragma Convention (C, Coverage_Buffers_Group_Array); + + type GNATcov_RTS_Coverage_Buffers_Group_Array is record + Length : aliased unsigned; + Groups : System.Address; + -- Address of a Coverage_Buffers_Group_Array array of Length items + end record; + pragma Convention (C, GNATcov_RTS_Coverage_Buffers_Group_Array); end GNATcov_RTS.Buffers.Lists; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb index b2150e98c..9a52382c4 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb @@ -30,10 +30,10 @@ with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; package body GNATcov_RTS.Traces.Output.Base64 is procedure Write_Trace_File_C - (Buffers : GNATcov_RTS_Coverage_Buffers_Array; - Program_Name : GNATcov_RTS_String; - Exec_Date : Unsigned_64; - User_Data : GNATcov_RTS_String); + (Buffers_Groups : GNATcov_RTS_Coverage_Buffers_Group_Array; + Program_Name : GNATcov_RTS_String; + Exec_Date : Unsigned_64; + User_Data : GNATcov_RTS_String); pragma Import (C, Write_Trace_File_C, "gnatcov_rts_write_trace_file_base64"); @@ -42,14 +42,13 @@ package body GNATcov_RTS.Traces.Output.Base64 is ---------------------- procedure Write_Trace_File - (Buffers : Coverage_Buffers_Array; - Program_Name : String; - Exec_Date : Unsigned_64; - User_Data : String := "") - is + (Buffers_Groups : Coverage_Buffers_Group_Array; + Program_Name : String; + Exec_Date : Unsigned_64; + User_Data : String := "") is begin Write_Trace_File_C - ((Buffers'Length, Buffers'Address), + ((Buffers_Groups'Length, Buffers_Groups'Address), (Program_Name'Address, Program_Name'Length), Exec_Date, (User_Data'Address, User_Data'Length)); diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads index a8bcc082d..7efb3c7a5 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads @@ -31,16 +31,16 @@ with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; package GNATcov_RTS.Traces.Output.Base64 is procedure Write_Trace_File - (Buffers : Coverage_Buffers_Array; - Program_Name : String; - Exec_Date : Unsigned_64; - User_Data : String := ""); + (Buffers_Groups : Coverage_Buffers_Group_Array; + Program_Name : String; + Exec_Date : Unsigned_64; + User_Data : String := ""); procedure Write_Trace_File_Wrapper - (Buffers : Coverage_Buffers_Array; - Program_Name : String; - Exec_Date : Unsigned_64; - User_Data : String := "") renames Write_Trace_File; + (Buffers_Groups : Coverage_Buffers_Group_Array; + Program_Name : String; + Exec_Date : Unsigned_64; + User_Data : String := "") renames Write_Trace_File; -- Renaming to mirror the API in GNATcov_RTS.Traces.Output.Files. This -- avoids special cases in the generation of automatic buffer dumps: except -- for the package that is WITHed, generated code is the same for diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb index 8e25975c8..cedbc2d03 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb @@ -36,11 +36,11 @@ with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; package body GNATcov_RTS.Traces.Output.Files is function Write_Trace_File_C - (Buffers : GNATcov_RTS_Coverage_Buffers_Array; - Filename : chars_ptr; - Program_Name : GNATcov_RTS_String; - Exec_Date : Unsigned_64; - User_Data : GNATcov_RTS_String) return int; + (Buffers_Groups : GNATcov_RTS_Coverage_Buffers_Group_Array; + Filename : chars_ptr; + Program_Name : GNATcov_RTS_String; + Exec_Date : Unsigned_64; + User_Data : GNATcov_RTS_String) return int; pragma Import (C, Write_Trace_File_C, External_Name => "gnatcov_rts_write_trace_file"); @@ -95,16 +95,16 @@ package body GNATcov_RTS.Traces.Output.Files is ---------------------- procedure Write_Trace_File - (Buffers : Coverage_Buffers_Array; - Filename : String := Default_Trace_Filename; - Program_Name : String := Ada.Command_Line.Command_Name; - Exec_Date : Time := Clock; - User_Data : String := "") + (Buffers_Groups : Coverage_Buffers_Group_Array; + Filename : String := Default_Trace_Filename; + Program_Name : String := Ada.Command_Line.Command_Name; + Exec_Date : Time := Clock; + User_Data : String := "") is Filename_C : chars_ptr := New_String (Filename); begin if Write_Trace_File_C - ((Buffers'Length, Buffers'Address), + ((Buffers_Groups'Length, Buffers_Groups'Address), Filename_C, (Program_Name'Address, Program_Name'Length), Interfaces.Unsigned_64 (Exec_Date), @@ -121,11 +121,11 @@ package body GNATcov_RTS.Traces.Output.Files is ------------------------------ procedure Write_Trace_File_Wrapper - (Buffers : Coverage_Buffers_Array; - Filename : String := Default_Trace_Filename; - Program_Name : String := Ada.Command_Line.Command_Name; - Exec_Date : Time := Clock; - User_Data : String := "") + (Buffers_Groups : Coverage_Buffers_Group_Array; + Filename : String := Default_Trace_Filename; + Program_Name : String := Ada.Command_Line.Command_Name; + Exec_Date : Time := Clock; + User_Data : String := "") is function C_Strerror (Errnum : C.int) return C.Strings.chars_ptr; @@ -135,7 +135,8 @@ package body GNATcov_RTS.Traces.Output.Files is -- errno. begin - Write_Trace_File (Buffers, Filename, Program_Name, Exec_Date, User_Data); + Write_Trace_File + (Buffers_Groups, Filename, Program_Name, Exec_Date, User_Data); exception when IO_Error => declare diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads index 42c4150de..1b272a8f0 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads @@ -57,20 +57,20 @@ package GNATcov_RTS.Traces.Output.Files is -- Exception we raise in case of errors during the trace file creation procedure Write_Trace_File - (Buffers : Coverage_Buffers_Array; - Filename : String := Default_Trace_Filename; - Program_Name : String := Ada.Command_Line.Command_Name; - Exec_Date : Time := Clock; - User_Data : String := ""); - -- Write a trace file in Filename to contain the data in Buffers. + (Buffers_Groups : Coverage_Buffers_Group_Array; + Filename : String := Default_Trace_Filename; + Program_Name : String := Ada.Command_Line.Command_Name; + Exec_Date : Time := Clock; + User_Data : String := ""); + -- Write a trace file in Filename to contain the data in Buffers_Groups. -- If unsuccessful, raise IO_Error and leave the error code in errno. procedure Write_Trace_File_Wrapper - (Buffers : Coverage_Buffers_Array; - Filename : String := Default_Trace_Filename; - Program_Name : String := Ada.Command_Line.Command_Name; - Exec_Date : Time := Clock; - User_Data : String := ""); + (Buffers_Groups : Coverage_Buffers_Group_Array; + Filename : String := Default_Trace_Filename; + Program_Name : String := Ada.Command_Line.Command_Name; + Exec_Date : Time := Clock; + User_Data : String := ""); -- Wrapper around Write_Trace_File that writes an error message to the -- standard error if the trace file could not be written. diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index 220d59310..14ee79c33 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -107,13 +107,22 @@ extern "C" gnatcov_rts_bit_id statement_last_bit, decision_last_bit, mcdc_last_bit; }; - /* Array of unit coverage buffers. */ - struct gnatcov_rts_coverage_buffers_array + /* Group of coverage buffers. For a given source file, instrumentation may + create more than one set of coverage buffers: these are grouped in a + coverage buffers group. */ + struct gnatcov_rts_coverage_buffers_group { unsigned length; const struct gnatcov_rts_coverage_buffers **buffers; }; + /* Array of coverage buffers groups. */ + struct gnatcov_rts_coverage_buffers_group_array + { + unsigned length; + const struct gnatcov_rts_coverage_buffers_group **groups; + }; + /***********************/ /* Witness subprograms */ /***********************/ diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c index 2ee732fd8..f11d33875 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c @@ -126,7 +126,7 @@ write_bytes (void *output, const void *bytes, unsigned count) void gnatcov_rts_write_trace_file_base64 ( - const struct gnatcov_rts_coverage_buffers_array *buffers, + const struct gnatcov_rts_coverage_buffers_group_array *buffers_groups, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data) { @@ -138,7 +138,7 @@ gnatcov_rts_write_trace_file_base64 ( struct gnatcov_rts_string end_string = STR ("== End =="); gnatcov_rts_putchar ('\n'); gnatcov_rts_puts (begin_string); - gnatcov_rts_generic_write_trace_file (&buffer, buffers, program_name, + gnatcov_rts_generic_write_trace_file (&buffer, buffers_groups, program_name, exec_date, user_data, write_bytes); flush (&buffer); if (buffer.columns != 0) diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h index a731749be..dfba2512e 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h @@ -30,7 +30,7 @@ extern "C" documentation of the gnatcov_rts_generic_write_trace_file function in gnatcov_rts_c-output.h for more information. */ extern void gnatcov_rts_write_trace_file_base64 ( - const struct gnatcov_rts_coverage_buffers_array *buffers, + const struct gnatcov_rts_coverage_buffers_group_array *buffers_groups, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data); diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c index 50edf3bab..840183079 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c @@ -154,7 +154,7 @@ gnatcov_rts_default_trace_filename (const char *env_var, const char *prefix, /* See gnatcov_rts_c-traces-output-files.h. */ int gnatcov_rts_write_trace_file ( - const struct gnatcov_rts_coverage_buffers_array *buffers, + const struct gnatcov_rts_coverage_buffers_group_array *buffers_groups, const char *filename, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data) { @@ -162,8 +162,8 @@ gnatcov_rts_write_trace_file ( if (!file) return 1; - gnatcov_rts_generic_write_trace_file (file, buffers, program_name, exec_date, - user_data, write_bytes); + gnatcov_rts_generic_write_trace_file (file, buffers_groups, program_name, + exec_date, user_data, write_bytes); fclose (file); return 0; } @@ -171,12 +171,12 @@ gnatcov_rts_write_trace_file ( /* See gnatcov_rts_c-traces-output-files.h. */ void gnatcov_rts_write_trace_file_wrapper ( - const struct gnatcov_rts_coverage_buffers_array *buffers, + const struct gnatcov_rts_coverage_buffers_group_array *buffers_groups, const char *filename, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data) { - if (gnatcov_rts_write_trace_file (buffers, filename, program_name, exec_date, - user_data) + if (gnatcov_rts_write_trace_file (buffers_groups, filename, program_name, + exec_date, user_data) != 0) fprintf (stderr, "Error occurred while creating the trace file %s: %s\n", filename, strerror (errno)); diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h index db1535b01..16efcc789 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h @@ -54,7 +54,7 @@ extern "C" const char *tag, unsigned simple); - /* Write a trace file in FILENAME to contain the data in BUFFERS. + /* Write a trace file in FILENAME to contain the data in BUFFERS_GROUPS. PROGRAM_NAME, EXEC_DATE, and USER_DATA are used to fill the corresponding metadata in the written trace file. @@ -65,14 +65,14 @@ extern "C" Return 0 if the trace creation was successful, 1 otherwise. In case of error, ERRNO is left to the number for the cause of error. */ extern int gnatcov_rts_write_trace_file ( - const struct gnatcov_rts_coverage_buffers_array *buffers, + const struct gnatcov_rts_coverage_buffers_group_array *buffers_groups, const char *filename, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data); /* Call gnatcov_rts_write_trace_file and print an error message on the standard error if the trace could not be created. */ extern void gnatcov_rts_write_trace_file_wrapper ( - const struct gnatcov_rts_coverage_buffers_array *buffers, + const struct gnatcov_rts_coverage_buffers_group_array *buffers_groups, const char *filename, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data); diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index 1a9265044..537a30bbb 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -166,12 +166,14 @@ write_date (gnatcov_rts_write_bytes_callback write_bytes, void *output, /* See gnatcov_rts_c-traces-output.h. */ int gnatcov_rts_generic_write_trace_file ( - void *output, const struct gnatcov_rts_coverage_buffers_array *buffers, + void *output, + const struct gnatcov_rts_coverage_buffers_group_array *buffers_groups, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data, gnatcov_rts_write_bytes_callback write_bytes) { - unsigned i; + const struct gnatcov_rts_coverage_buffers_group *group; + unsigned i_group, i_buffer; struct info_entry program_name_entry; program_name_entry.length = program_name.length; @@ -192,8 +194,12 @@ gnatcov_rts_generic_write_trace_file ( &user_data_entry); write_info (write_bytes, output, GNATCOV_RTS_INFO_END, &end_entry); - for (i = 0; i < buffers->length; i++) - write_entry (write_bytes, output, buffers->buffers[i]); + for (i_group = 0; i_group < buffers_groups->length; ++i_group) + { + group = buffers_groups->groups[i_group]; + for (i_buffer = 0; i_buffer < group->length; ++i_buffer) + write_entry (write_bytes, output, group->buffers[i_buffer]); + } return 0; } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h index f23156b16..939ec31c8 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h @@ -33,12 +33,13 @@ extern "C" const void *source, unsigned n); - /* Write a trace file to contain the given coverage BUFFERS to the OUTPUT - stream using the WRITE_BYTES callback. PROGRAM_NAME, EXEC_DATE and + /* Write a trace file to contain the given coverage BUFFERS_GROUPS to the + OUTPUT stream using the WRITE_BYTES callback. PROGRAM_NAME, EXEC_DATE and USER_DATA are included as metadata in the trace file. Return 0 if the write was successful, and return any non-zero value in case of error. */ extern int gnatcov_rts_generic_write_trace_file ( - void *output, const struct gnatcov_rts_coverage_buffers_array *buffers, + void *output, + const struct gnatcov_rts_coverage_buffers_group_array *buffers_groups, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data, gnatcov_rts_write_bytes_callback write_bytes); From 6e08db314e48e92cfb32a8a8cf56168dfbec2894 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 10 Oct 2022 11:49:12 +0000 Subject: [PATCH 0036/1483] gnatcov_rts_c-traces-output-base64.h: fix obsolete file reference no-tn-check Change-Id: Ib3598f4fb1dda62bacfdc5b5b6a789ca4f35495e --- tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h index dfba2512e..59792be54 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h @@ -28,7 +28,7 @@ extern "C" /* Write a Base64-encoded trace file to the standard output. See the documentation of the gnatcov_rts_generic_write_trace_file function in - gnatcov_rts_c-output.h for more information. */ + gnatcov_rts_c-traces-output.h for more information. */ extern void gnatcov_rts_write_trace_file_base64 ( const struct gnatcov_rts_coverage_buffers_group_array *buffers_groups, struct gnatcov_rts_string program_name, uint64_t exec_date, From 0ce0ace432cafe89456068c0a37f8cf46ff71e8e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 13 Sep 2022 15:33:34 +0000 Subject: [PATCH 0037/1483] Instrument: allow one set of coverage buffers per source file Now that GNATcov_RTS supports it, extend the instrumentation infrastructure to allow it: stop assuming that there is only one set of coverage buffers in common code, and extend data structures in the C/C++ instrumenter to be ready for creating buffers for C headers. This is still preparatory work: just refactoring, no behavior change expected. Change-Id: I247fae8d3803412fc5941a6993de9709063d74fa TN: V728-002 --- tools/gnatcov/instrument-ada_unit.adb | 1 + tools/gnatcov/instrument-ada_unit.ads | 3 + tools/gnatcov/instrument-c.adb | 772 +++++++++++++++++--------- tools/gnatcov/instrument-c.ads | 42 +- tools/gnatcov/instrument-common.adb | 12 + tools/gnatcov/instrument-common.ads | 20 +- tools/gnatcov/sc_obligations.ads | 2 + 7 files changed, 595 insertions(+), 257 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index c3a47004f..7ca52118d 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6587,6 +6587,7 @@ package body Instrument.Ada_Unit is (Filename, Kind => Files_Table.Source_File, Indexed_Simple_Name => True); + UIC.Unit_Bits.SFI := UIC.SFI; -- Then run SCOs generation. This inserts calls to witness -- procedures/functions in the same pass. diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 7a7e8ccb2..aa4e67269 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -236,6 +236,9 @@ private Source_Conditions : Source_Condition_Vectors.Vector; -- Decisions and (for MC/DC) conditions to be instrumented + Unit_Bits : Instrument.Common.Allocated_Bits; + -- Allocated bits in coverage buffers for low-level SCOs + Entities : Instrumentation_Entities; -- Bank of nodes to use during instrumentation diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 1d19d8ee6..c24ea5298 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -83,6 +83,10 @@ package body Instrument.C is -- is always a SCO associated with a pragma exempt, which would result in -- all the annotations being filtered out. + function Last_File return Valid_Source_File_Index + is (SCOs.SCO_Unit_Table.Table (SCOs.SCO_Unit_Table.Last).File_Index); + -- Return the source file for the last low-level SCO that was created + ------------------------------ -- Preprocessing utilities -- ------------------------------ @@ -226,26 +230,43 @@ package body Instrument.C is -- Generation of witness fragments -- ------------------------------------- + function Buffers_Subscript (Buffers_Index : Positive) return String + is ("[" & Img (Buffers_Index - 1) & "]"); + -- Return a C array subscript to refer to the coverage buffers + -- corresponding to Buffers_Index. + -- + -- Note that while Buffers_Index is 1-based, C arrays are 0-based, hence + -- the index "off-by-1" conversion. + function Make_Expr_Witness - (UIC : C_Unit_Inst_Context; Bit : Bit_Id) return String; + (UIC : C_Unit_Inst_Context; + Buffer_Index : Positive; + Bit : Bit_Id) return String; -- Create a procedure call expression on to witness execution of the low - -- level SCO with the given bit id. + -- level SCO with the given Bit id in the statement buffer at Buffer_Index. function Make_Statement_Witness - (UIC : C_Unit_Inst_Context; Bit : Bit_Id) return String; + (UIC : C_Unit_Inst_Context; + Buffer_Index : Positive; + Bit : Bit_Id) return String; -- Create a procedure call statement to witness execution of the low level - -- SCO with the given bit id. + -- SCO with the given Bit id in the statement buffer at Buffer_Index. procedure Insert_Statement_Witness - (UIC : in out C_Unit_Inst_Context; SS : C_Source_Statement); - -- Insert witness function call for the identified statement + (UIC : in out C_Unit_Inst_Context; + Buffers_Index : Positive; + SS : C_Source_Statement); + -- Insert witness function call for the identified statement. Buffers_Index + -- designates the relevant set of coverage buffers. procedure Insert_Decision_Witness - (UIC : in out C_Unit_Inst_Context; - SD : C_Source_Decision; - Path_Count : Natural); + (UIC : in out C_Unit_Inst_Context; + Buffers_Index : Positive; + SD : C_Source_Decision; + Path_Count : Natural); -- For use when decision coverage or MC/DC is requested. Insert witness - -- function call for the identified decision. + -- function call for the identified decision. Buffers_Index designates the + -- relevant set of coverage buffers. procedure Insert_Condition_Witness (UIC : in out C_Unit_Inst_Context; @@ -359,6 +380,20 @@ package body Instrument.C is function Format_Str_Constant (Value : String) return String; -- Return a gnatcov_rts_string literal corresponding to Value + function Format_Array_Init_Expr + (Exprs : String_Vectors.Vector; + Multiline : Boolean := False) return String; + -- Helper to format the initialization expression for an array. + -- + -- Exprs is the list of expressions for all items in the array. + -- + -- If Multiline is False, the returned expression fits on a single line. + -- Otherwise, put one array item per line. + + function Format_Fingerprint + (Fingerprint : SC_Obligations.SCOs_Hash) return String; + -- Helper to format a uint8_t[] literal for a SCOs fingerprint + function Format_Def (Instrumenter : C_Family_Instrumenter_Type'Class; C_Type : String; @@ -404,6 +439,7 @@ package body Instrument.C is (Instrumenter : C_Family_Instrumenter_Type'Class; C_Type : String; Name : String; + Array_Size : String := ""; Func_Args : String := "") return String; -- Helper for format an "extern" declaration. Arguments are the same as -- Format_Def. @@ -414,6 +450,7 @@ package body Instrument.C is Instrumenter : C_Family_Instrumenter_Type'Class; C_Type : String; Name : String; + Array_Size : String := ""; Func_Args : String := ""); -- Like Format_Extern_Decl, but write the definition at Location in the -- unit rewritten by Rewriter. @@ -828,6 +865,24 @@ package body Instrument.C is Curlify (N, Rew); end Curlify; + -------------------------------- + -- Find_Instrumented_Entities -- + -------------------------------- + + function Find_Instrumented_Entities + (UIC : in out C_Unit_Inst_Context'Class; + SFI : Valid_Source_File_Index) + return C_Instrumented_Entities_Maps.Reference_Type + is + use C_Instrumented_Entities_Maps; + Cur : Cursor; + Dummy : Boolean; + begin + UIC.Instrumented_Entities.Insert + (SFI, (others => <>), Cur, Dummy); + return UIC.Instrumented_Entities.Reference (Cur); + end Find_Instrumented_Entities; + ----------------------- -- Insert_MCDC_State -- ----------------------- @@ -852,7 +907,7 @@ package body Instrument.C is Insertion_N : Cursor_T; Instr_Scheme : Instr_Scheme_Type) is begin - UIC.Source_Statements.Append + UIC.Find_Instrumented_Entities (Last_File).Statements.Append (C_Source_Statement' (LL_SCO => SCOs.SCO_Table.Last, Instr_Scheme => Instr_Scheme, @@ -870,7 +925,7 @@ package body Instrument.C is Decision : Cursor_T; State : US.Unbounded_String) is begin - UIC.Source_Decisions.Append + UIC.Find_Instrumented_Entities (Last_File).Decisions.Append (C_Source_Decision' (LL_SCO => LL_SCO, Decision => Decision, @@ -889,7 +944,7 @@ package body Instrument.C is State : US.Unbounded_String; First : Boolean) is begin - UIC.Source_Conditions.Append + UIC.Find_Instrumented_Entities (Last_File).Conditions.Append (C_Source_Condition' (LL_SCO => SCOs.SCO_Table.Last, Condition => Condition, @@ -902,13 +957,14 @@ package body Instrument.C is ----------------------- function Make_Expr_Witness - (UIC : C_Unit_Inst_Context; Bit : Bit_Id) return String - is - Bit_Img : constant String := Img (Bit); + (UIC : C_Unit_Inst_Context; + Buffer_Index : Positive; + Bit : Bit_Id) return String is begin - return "gnatcov_rts_witness (" - & Statement_Buffer_Symbol (UIC.Instrumented_Unit) & "," & Bit_Img - & ")"; + return + "gnatcov_rts_witness (" + & Statement_Buffer_Symbol (UIC.Instrumented_Unit) + & Buffers_Subscript (Buffer_Index) & ", " & Img (Bit) & ")"; end Make_Expr_Witness; ---------------------------- @@ -916,9 +972,11 @@ package body Instrument.C is ---------------------------- function Make_Statement_Witness - (UIC : C_Unit_Inst_Context; Bit : Bit_Id) return String is + (UIC : C_Unit_Inst_Context; + Buffer_Index : Positive; + Bit : Bit_Id) return String is begin - return Make_Expr_Witness (UIC, Bit) & ";"; + return Make_Expr_Witness (UIC, Buffer_Index, Bit) & ";"; end Make_Statement_Witness; ------------------------------ @@ -926,12 +984,16 @@ package body Instrument.C is ------------------------------ procedure Insert_Statement_Witness - (UIC : in out C_Unit_Inst_Context; SS : C_Source_Statement) + (UIC : in out C_Unit_Inst_Context; + Buffers_Index : Positive; + SS : C_Source_Statement) is + Unit_Bits : Allocated_Bits renames UIC.Allocated_Bits (Buffers_Index); + -- Allocate a bit in the statement coverage buffer Bit : constant Bit_Id := - Allocate_Statement_Bit (UIC.Unit_Bits, SS.LL_SCO); + Allocate_Statement_Bit (Unit_Bits, SS.LL_SCO); begin -- Insert the call to the witness function: as a foregoing statement if -- SS.Statement is a statement, or as a previous expression (using the @@ -941,13 +1003,14 @@ package body Instrument.C is when Instr_Stmt => Insert_Text_After_Start_Of (N => SS.Statement, - Text => Make_Statement_Witness (UIC, Bit), + Text => Make_Statement_Witness (UIC, Buffers_Index, Bit), Rew => UIC.Rewriter); when Instr_Expr => Insert_Text_After_Start_Of (N => SS.Statement, - Text => "(" & Make_Expr_Witness (UIC, Bit) & ", ", + Text => + "(" & Make_Expr_Witness (UIC, Buffers_Index, Bit) & ", ", Rew => UIC.Rewriter); Insert_Text_Before_End_Of (N => SS.Statement, @@ -999,18 +1062,21 @@ package body Instrument.C is ----------------------------- procedure Insert_Decision_Witness - (UIC : in out C_Unit_Inst_Context; - SD : C_Source_Decision; - Path_Count : Natural) + (UIC : in out C_Unit_Inst_Context; + Buffers_Index : Positive; + SD : C_Source_Decision; + Path_Count : Natural) is + Unit_Bits : Allocated_Bits renames UIC.Allocated_Bits (Buffers_Index); + N : Cursor_T renames SD.Decision; -- Allocate bits for this decision in coverage buffers Bits : constant Decision_Bit_Ids := Allocate_Decision_Bits - (UIC.Unit_Bits, - (UIC.SFI, Start_Sloc (N)), + (Unit_Bits, + (Unit_Bits.SFI, Start_Sloc (N)), SD.LL_SCO, SD.State, Path_Count); @@ -1027,7 +1093,8 @@ package body Instrument.C is Insert_Text_After_Start_Of (N => N, Text => Function_Name & "(" - & Decision_Buffer_Symbol (UIC.Instrumented_Unit) & ", " + & Decision_Buffer_Symbol (UIC.Instrumented_Unit) + & Buffers_Subscript (Buffers_Index) & ", " & Img (Bits.Outcome_Bits (False)) & ", " & Img (Bits.Outcome_Bits (True)), Rew => UIC.Rewriter); @@ -1035,7 +1102,8 @@ package body Instrument.C is if Is_MCDC then Insert_Text_After_Start_Of (N => N, - Text => ", " & MCDC_Buffer_Symbol (UIC.Instrumented_Unit) & ", " + Text => ", " & MCDC_Buffer_Symbol (UIC.Instrumented_Unit) + & Buffers_Subscript (Buffers_Index) & ", " & Img (Bits.Path_Bits_Base) & ", " & US.To_String (SD.State), Rew => UIC.Rewriter); @@ -2639,9 +2707,10 @@ package body Instrument.C is -- Where to insert extern declarations procedure Put_Extern_Decl - (C_Type : String; - Name : String; - Func_Args : String := ""); + (C_Type : String; + Name : String; + Array_Size : String := ""; + Func_Args : String := ""); -- Local shortcut to avoid passing UIC.TU/UIC.Rewriter explicitly --------------------- @@ -2649,9 +2718,10 @@ package body Instrument.C is --------------------- procedure Put_Extern_Decl - (C_Type : String; - Name : String; - Func_Args : String := "") is + (C_Type : String; + Name : String; + Array_Size : String := ""; + Func_Args : String := "") is begin Put_Extern_Decl (UIC.Rewriter, @@ -2659,9 +2729,14 @@ package body Instrument.C is Instrumenter, C_Type, Name, + Array_Size, Func_Args); end Put_Extern_Decl; + Unit_Index : SCOs.SCO_Unit_Index; + -- Index in low-level tables of the only SCO Unit we create for this + -- source file. + -- Start of processing for Instrument_Source_File begin @@ -2678,6 +2753,23 @@ package body Instrument.C is CU_Name_For_File (+Buffer_Filename, CU_Name.Project_Name); UIC.File := +Orig_Filename; + -- Create the only SCO Unit we will need to instrument this source file. + -- Also make sure we will create at least the set of coverage buffers + -- for the main source file. + + declare + Dummy : C_Instrumented_Entities renames + UIC.Find_Instrumented_Entities (UIC.SFI); + begin + SCOs.SCO_Unit_Table.Append + ((File_Name => new String'(Orig_Filename), + File_Index => UIC.SFI, + Dep_Num => 1, + From => SCOs.SCO_Table.First, + To => SCOs.SCO_Table.Last)); + Unit_Index := SCOs.SCO_Unit_Table.Last; + end; + -- Import analysis options for the file to preprocess, then run the -- preprocessor. @@ -2768,12 +2860,16 @@ package body Instrument.C is UIC => UIC, L => Get_Children (Get_Translation_Unit_Cursor (UIC.TU))); - SCOs.SCO_Unit_Table.Append - ((File_Name => new String'(Orig_Filename), - File_Index => UIC.SFI, - Dep_Num => 1, - From => SCOs.SCO_Table.First, - To => SCOs.SCO_Table.Last)); + -- At this point, all coverage obligations where created in the + -- low-level tables, so we can adjust the upper bound in the SCO Unit + -- table. + -- + -- TODO??? This works because for now we handle only one SCO unit, but + -- handling more units (for instance C headers) will require a redesign + -- for this part, for instance making Append_SCO automatically increment + -- that upper bound for the last SCO unit. + + SCOs.SCO_Unit_Table.Table (Unit_Index).To := SCOs.SCO_Table.Last; -- Check whether there is a mismatch between Last_SCO and -- SCOs.SCO_Table.Last. If there is, warn the user and discard the @@ -2790,19 +2886,27 @@ package body Instrument.C is UIC.LL_PP_Info_Map.Clear; end if; + -- Now that the set of coverage obligations and the set of source files + -- are known, allocate the required set of coverage buffers (one per + -- source file) and assign the corresponding buffers indexes. + + for Cur in UIC.Instrumented_Entities.Iterate loop + UIC.Instrumented_Entities.Reference (Cur).Buffers_Index := + Create_Unit_Bits + (UIC.Allocated_Bits, C_Instrumented_Entities_Maps.Key (Cur)); + end loop; + -- Convert low level SCOs from the instrumenter to high level SCOs. -- This creates BDDs for every decision. declare - SCO_Map : aliased LL_HL_SCO_Map := + SCO_Map : aliased LL_HL_SCO_Map := (SCOs.SCO_Table.First .. SCOs.SCO_Table.Last => No_SCO_Id); - Bit_Maps : CU_Bit_Maps; - Created_Units : Created_Unit_Maps.Map; begin Process_Low_Level_SCOs (Provider => SC_Obligations.Instrumenter, Origin => UIC.SFI, - Created_Units => Created_Units, + Created_Units => UIC.CUs, SCO_Map => SCO_Map'Access, Count_Paths => True); @@ -2823,94 +2927,116 @@ package body Instrument.C is -- In the instrumentation case, the origin of SCO information is -- the original source file. - UIC.CU := Created_Units.Element (UIC.SFI); + UIC.CU := UIC.CUs.Element (UIC.SFI); -- Import annotations in our internal tables UIC.Import_Annotations; Filter_Annotations; - for SS of UIC.Source_Statements loop - Insert_Statement_Witness (UIC, SS); - end loop; + for Cur in UIC.Instrumented_Entities.Iterate loop + declare + SFI : constant Valid_Source_File_Index := + C_Instrumented_Entities_Maps.Key (Cur); + Ent : C_Instrumented_Entities renames + UIC.Instrumented_Entities.Reference (Cur); + + Unit_Bits : Allocated_Bits renames + UIC.Allocated_Bits.Reference (Ent.Buffers_Index); + Bit_Maps : CU_Bit_Maps; + begin + -- Allocate bits in covearge buffers and insert the + -- corresponding witness calls. - if Coverage.Enabled (Coverage_Options.Decision) - or else MCDC_Coverage_Enabled - then - for SD of UIC.Source_Decisions loop - Insert_Decision_Witness - (UIC, SD, Path_Count (SCO_Map (SD.LL_SCO))); - end loop; + for SS of Ent.Statements loop + Insert_Statement_Witness (UIC, Ent.Buffers_Index, SS); + end loop; - if MCDC_Coverage_Enabled then + if Coverage.Enabled (Coverage_Options.Decision) + or else MCDC_Coverage_Enabled + then + for SD of Ent.Decisions loop + Insert_Decision_Witness + (UIC, + Ent.Buffers_Index, + SD, + Path_Count (SCO_Map (SD.LL_SCO))); + end loop; + + if MCDC_Coverage_Enabled then + + -- As high-level SCO tables have been populated, we have + -- built BDDs for each decisions, and we can now set the + -- correct MC/DC path offset for each condition. + + for SC of Ent.Conditions loop + declare + Condition : constant SCO_Id := SCO_Map (SC.LL_SCO); + Decision : constant SCO_Id := + Enclosing_Decision (Condition); + begin + if Path_Count (Decision) = 0 then + Set_Decision_SCO_Non_Instr_For_MCDC (Decision); + else + Insert_Condition_Witness + (UIC, SC, Offset_For_True (Condition)); + end if; + end; + end loop; + end if; + end if; - -- As high-level SCO tables have been populated, we have built - -- BDDs for each decisions, and we can now set the correct - -- MC/DC path offset for each condition. - -- - -- As we go through each condition, mark their enclosing - -- decision as not instrumented if their number of paths - -- exceeds our limit. + -- Create mappings from alloacted bits to the corresponding SCO + -- discharging information (Bit_Maps). + + Bit_Maps := + (Statement_Bits => new Statement_Bit_Map' + (Bit_Id'First .. Unit_Bits.Last_Statement_Bit => + No_SCO_Id), + Decision_Bits => new Decision_Bit_Map' + (Bit_Id'First .. Unit_Bits.Last_Outcome_Bit => + (No_SCO_Id, False)), + MCDC_Bits => new MCDC_Bit_Map' + (Bit_Id'First .. Unit_Bits.Last_Path_Bit => + (No_SCO_Id, 0))); + + for S_Bit_Alloc of Unit_Bits.Statement_Bits loop + Bit_Maps.Statement_Bits (S_Bit_Alloc.Executed) := + SCO_Map (S_Bit_Alloc.LL_S_SCO); + end loop; - for SC of UIC.Source_Conditions loop + for D_Bit_Alloc of Unit_Bits.Decision_Bits loop declare - Condition : constant SCO_Id := SCO_Map (SC.LL_SCO); - Decision : constant SCO_Id := - Enclosing_Decision (Condition); + D_SCO : constant SCO_Id := SCO_Map (D_Bit_Alloc.LL_D_SCO); begin - if Path_Count (Decision) = 0 then - Set_Decision_SCO_Non_Instr_For_MCDC (Decision); - else - Insert_Condition_Witness - (UIC, SC, Offset_For_True (Condition)); + for Outcome in Boolean loop + Bit_Maps.Decision_Bits + (D_Bit_Alloc.Outcome_Bits (Outcome)) := + (D_SCO, Outcome); + end loop; + + if MCDC_Coverage_Enabled + and then D_Bit_Alloc.Path_Bits_Base /= No_Bit_Id + then + declare + Path_Count : constant Natural := + SC_Obligations.Path_Count (D_SCO); + begin + for J in 1 .. Any_Bit_Id (Path_Count) loop + Bit_Maps.MCDC_Bits + (D_Bit_Alloc.Path_Bits_Base + J - 1) := + (D_SCO, Natural (J - 1)); + end loop; + end; end if; end; end loop; - end if; - end if; - Bit_Maps := - (Statement_Bits => new Statement_Bit_Map' - (Bit_Id'First .. UIC.Unit_Bits.Last_Statement_Bit => No_SCO_Id), - Decision_Bits => new Decision_Bit_Map' - (Bit_Id'First .. UIC.Unit_Bits.Last_Outcome_Bit => - (No_SCO_Id, False)), - MCDC_Bits => - new MCDC_Bit_Map'(Bit_Id'First .. UIC.Unit_Bits.Last_Path_Bit => - (No_SCO_Id, 0))); - - for S_Bit_Alloc of UIC.Unit_Bits.Statement_Bits loop - Bit_Maps.Statement_Bits (S_Bit_Alloc.Executed) := - SCO_Map (S_Bit_Alloc.LL_S_SCO); - end loop; + -- Associate these bit maps to the corresponding CU - for D_Bit_Alloc of UIC.Unit_Bits.Decision_Bits loop - declare - D_SCO : constant SCO_Id := SCO_Map (D_Bit_Alloc.LL_D_SCO); - begin - for Outcome in Boolean loop - Bit_Maps.Decision_Bits - (D_Bit_Alloc.Outcome_Bits (Outcome)) := (D_SCO, Outcome); - end loop; - - if MCDC_Coverage_Enabled - and then D_Bit_Alloc.Path_Bits_Base /= No_Bit_Id - then - declare - Path_Count : constant Natural := - SC_Obligations.Path_Count (D_SCO); - begin - for J in 1 .. Any_Bit_Id (Path_Count) loop - Bit_Maps.MCDC_Bits - (D_Bit_Alloc.Path_Bits_Base + J - 1) := - (D_SCO, Natural (J - 1)); - end loop; - end; - end if; + Set_Bit_Maps (UIC.CUs.Element (SFI), Bit_Maps); end; end loop; - - Set_Bit_Maps (UIC.CU, Bit_Maps); end; -- We import the extern declaration of symbols instead of including the @@ -2927,15 +3053,23 @@ package body Instrument.C is -- libraries, which we don't want. To be safe, we will declare -- GNATcov_RTS functions and symbols as extern. - Put_Extern_Decl - ("unsigned char *", - Statement_Buffer_Symbol (UIC.Instrumented_Unit)); - Put_Extern_Decl - ("unsigned char *", - Decision_Buffer_Symbol (UIC.Instrumented_Unit)); - Put_Extern_Decl - ("unsigned char *", - MCDC_Buffer_Symbol (UIC.Instrumented_Unit)); + declare + Buffers_Count : constant String := + Img (Natural (UIC.Allocated_Bits.Length)); + begin + Put_Extern_Decl + ("unsigned char *", + Statement_Buffer_Symbol (UIC.Instrumented_Unit), + Array_Size => Buffers_Count); + Put_Extern_Decl + ("unsigned char *", + Decision_Buffer_Symbol (UIC.Instrumented_Unit), + Array_Size => Buffers_Count); + Put_Extern_Decl + ("unsigned char *", + MCDC_Buffer_Symbol (UIC.Instrumented_Unit), + Array_Size => Buffers_Count); + end; Put_Extern_Decl ("unsigned", "gnatcov_rts_witness", @@ -2978,6 +3112,55 @@ package body Instrument.C is Rewriter.Apply; end Instrument_Source_File; + ---------------------------- + -- Format_Array_Init_Expr -- + ---------------------------- + + function Format_Array_Init_Expr + (Exprs : String_Vectors.Vector; + Multiline : Boolean := False) return String + is + Result : Unbounded_String; + begin + Append (Result, "{"); + if Multiline then + Append (Result, ASCII.LF); + end if; + for I in Exprs.First_Index .. Exprs.Last_Index loop + if I > Exprs.First_Index then + if Multiline then + Append (Result, "," & ASCII.LF); + else + Append (Result, ", "); + end if; + end if; + if Multiline then + Append (Result, " "); + end if; + Append (Result, To_String (Exprs.Element (I))); + end loop; + if Multiline then + Append (Result, ASCII.LF); + end if; + Append (Result, "}"); + return To_String (Result); + end Format_Array_Init_Expr; + + ------------------------ + -- Format_Fingerprint -- + ------------------------ + + function Format_Fingerprint + (Fingerprint : SC_Obligations.SCOs_Hash) return String is + Items : String_Vectors.Vector; + begin + for Byte of Fingerprint loop + Items.Append (+Img (Integer (Byte))); + end loop; + + return Format_Array_Init_Expr (Items); + end Format_Fingerprint; + ---------------------- -- Emit_Buffer_Unit -- ---------------------- @@ -2990,163 +3173,251 @@ package body Instrument.C is CU_Name : Compilation_Unit_Name renames UIC.Buffer_Unit; File : Text_Files.File_Type; - -- As a reminder, the representation of a static-array variable differs - -- from a pointer-to-array variable. + Buffers_Count : constant Natural := Natural (UIC.Allocated_Bits.Length); + -- Number of items in the buffer group to create - Statement_Buffer : constant String := + -- Symbol names for the arrays of buffer bits (one for statements, one + -- for decisions, one for MC/DC paths). They are exported, so they need + -- to be unique program-wide. + + Statement_Buffers : constant String := Statement_Buffer_Symbol (UIC.Instrumented_Unit); - Decision_Buffer : constant String := + Decision_Buffers : constant String := Decision_Buffer_Symbol (UIC.Instrumented_Unit); - MCDC_Buffer : constant String := + MCDC_Buffers : constant String := MCDC_Buffer_Symbol (UIC.Instrumented_Unit); - Statement_Buffer_Repr : constant String := - "__" & Statement_Buffer_Symbol (UIC.Instrumented_Unit); - Decision_Buffer_Repr : constant String := - "__" & Decision_Buffer_Symbol (UIC.Instrumented_Unit); - MCDC_Buffer_Repr : constant String := - "__" & MCDC_Buffer_Symbol (UIC.Instrumented_Unit); - - Buffers_Record : constant String := "__xcov_buffers"; - -- Name of the gnatcov_rts_coverage_buffers struct for this unit - - Buffers_Group_Array : constant String := "__xcov_buffers_group"; + Buffers_Array : constant String := "__xcov_buffers_group"; -- Name of the array of gnatcov_rts_coverage_buffers struct for this -- unit. + + Statement_Init : String_Vectors.Vector; + Decision_Init : String_Vectors.Vector; + MCDC_Init : String_Vectors.Vector; + -- Initialization expressions for the pointer arrays: each element in a + -- vector is an array item initializer. + + Group_Init : String_Vectors.Vector; + -- Likewise, but for the coverage buffers group + + Buffers_CUs : CU_Id_Vectors.Vector := + CU_Id_Vectors.To_Vector (No_CU_Id, UIC.Allocated_Bits.Length); + Buffers_CU_Names : CU_Name_Vectors.Vector := + CU_Name_Vectors.To_Vector + ((Language_Kind => File_Based_Language, others => <>), + UIC.Allocated_Bits.Length); + -- For each set of buffers in UIC.Allocated_Bits, corresponding CU_Id + -- and CU_Name for the instrumented source file. + + I : Positive := 1; begin - Create_File (Info, File, +CU_Name.Filename); + -- Compute Buffers_Filenames and Buffers_Projects - declare - Fingerprint : Unbounded_String; + for Cur in UIC.Sources_Of_Interest.Iterate loop + declare + use Created_Unit_Maps; - Unit_Name : constant String := +UIC.Instrumented_Unit.Filename; - Project_Name : constant String := +UIC.Instrumented_Unit.Project_Name; + SOI : Source_Of_Interest renames + UIC.Sources_Of_Interest.Constant_Reference (Cur); + Cur : Cursor; + Index : Natural; + begin + if SOI.Of_Interest then + Cur := UIC.CUs.Find (SOI.SFI); + if Has_Element (Cur) then + Index := + UIC.Instrumented_Entities.Constant_Reference + (SOI.SFI).Buffers_Index; + Buffers_CUs (Index) := Element (Cur); + Buffers_CU_Names (Index) := SOI.CU_Name; + end if; + end if; + end; + end loop; - -- Do not use 'Image so that we use the original casing for the - -- enumerators, and thus avoid compilation warnings/errors. + -- Each source file in UIC.Instrumented_Entities is supposed to have a + -- corresponding "Of_Interest => True" entry in UIC.Sources_Of_Interest. - Statement_Last_Bit : constant String := Img - (UIC.Unit_Bits.Last_Statement_Bit); - Decision_Last_Bit : constant String := Img - (UIC.Unit_Bits.Last_Outcome_Bit); - MCDC_Last_Bit : constant String := Img - (UIC.Unit_Bits.Last_Path_Bit); - begin - -- Turn the fingerprint value into the corresponding C literal (array - -- of uint8_t). + pragma Assert (for all CU of Buffers_CUs => CU /= No_CU_Id); + -- Start to emit the buffer unit + + Create_File (Info, File, +CU_Name.Filename); + + File.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); + File.New_Line; + + -- Define coverage buffers for each source file: + -- + -- * First, create individual buffers for each kind (statement, decision + -- and MC/DC). These are static, so no need to create symbol names + -- that are unique program-wide. + -- + -- * Then, create pointers to these individual buffers. Put all pointers + -- to each kind of buffers in an exported array. Since both pointers + -- and the exported array are exported (used in buffer list units and + -- instrumented units), we need to create symbol names that are unique + -- program-wide. + + -- Create the static buffers as well as the + -- gnatcov_rts_coverage_buffers struct for each source file. + + for Cur in UIC.Instrumented_Entities.Iterate loop declare - First : Boolean := True; + SFI : constant Valid_Source_File_Index := + C_Instrumented_Entities_Maps.Key (Cur); + Buffers_Index : constant Positive := + UIC.Instrumented_Entities.Constant_Reference (SFI).Buffers_Index; + Unit_Bits : Allocated_Bits renames + UIC.Allocated_Bits.Constant_Reference (Buffers_Index); + + CU : constant CU_Id := Buffers_CUs (Buffers_Index); + CU_Name : Compilation_Unit_Name renames + Buffers_CU_Names.Constant_Reference (Buffers_Index); + + -- Symbol name for each kind of static buffer + + Suffix : constant String := "_" & Img (I); + + Statement_Buffer_Repr : constant String := "__stmt_bits" & Suffix; + Decision_Buffer_Repr : constant String := "__dc_bits" & Suffix; + MCDC_Buffer_Repr : constant String := "__mcdc_bits" & Suffix; + + Buffers_Struct : constant String := "__xcov_buffers" & Suffix; + -- Name of the gnatcov_rts_coverage_buffers struct for this + -- source file. + begin - Append (Fingerprint, "{"); - for Byte of SC_Obligations.Fingerprint (UIC.CU) loop - if First then - First := False; - else - Append (Fingerprint, ", "); - end if; - Append (Fingerprint, Strings.Img (Integer (Byte))); - end loop; - Append (Fingerprint, "}"); - end; + File.Put_Line ("/* Buffers for " & Get_Full_Name (SFI) & " */"); + + -- Static buffers + + File.Put_Line + ("static unsigned char " & Statement_Buffer_Repr & "[" + & Img (Any_Bit_Id'Max (1, Unit_Bits.Last_Statement_Bit + 1)) + & "];"); + Statement_Init.Append (+("&" & Statement_Buffer_Repr & "[0]")); + + File.Put_Line + ("static unsigned char " & Decision_Buffer_Repr & "[" + & Img (Any_Bit_Id'Max (1, Unit_Bits.Last_Outcome_Bit + 1)) + & "];"); + Decision_Init.Append (+("&" & Decision_Buffer_Repr & "[0]")); + + File.Put_Line + ("static unsigned char " & MCDC_Buffer_Repr & "[" + & Img (Any_Bit_Id'Max (1, Unit_Bits.Last_Path_Bit + 1)) + & "];"); + MCDC_Init.Append (+("&" & MCDC_Buffer_Repr & "[0]")); + + -- gnatcov_rts_coverage_buffers struct + + File.Put_Line + ("static const struct gnatcov_rts_coverage_buffers " + & Buffers_Struct & " = {" + & ASCII.LF + & " .fingerprint = " + & Format_Fingerprint (SC_Obligations.Fingerprint (CU)) & "," + & ASCII.LF + & " .language_kind = FILE_BASED_LANGUAGE," + & ASCII.LF + & " .unit_part = NOT_APPLICABLE_PART," + & ASCII.LF + + -- Old toolchains (for instance GNAT Pro 7.1.2) consider that + -- "STR()" is not a static expression, and thus + -- refuse using STR to initialize a global data structure. To + -- workaround this, emit a gnatcov_rtr_string literal + -- ourselves. + + & " .unit_name = " & Format_Str_Constant (+CU_Name.Filename) + & "," + & ASCII.LF + & " .project_name = " + & Format_Str_Constant (+CU_Name.Project_Name) & "," + & ASCII.LF + + -- We do not use the created pointer (Statement_Buffer) to + -- initialize the buffer fields, as this is rejected by old + -- versions of the compiler (up to the 20 version): the + -- initializer element is considered not constant. To work + -- around it, we simply use the original expression instead of + -- using a wrapper pointer. + + & " .statement = &" & Statement_Buffer_Repr & "[0]," + & ASCII.LF + & " .decision = &" & Decision_Buffer_Repr & "[0]," + & ASCII.LF + & " .mcdc = &" & MCDC_Buffer_Repr & "[0]," + & ASCII.LF + + & " .statement_last_bit = " + & Img (Unit_Bits.Last_Statement_Bit) & "," + & ASCII.LF + & " .decision_last_bit = " & Img (Unit_Bits.Last_Outcome_Bit) + & "," + & ASCII.LF + & " .mcdc_last_bit = " & Img (Unit_Bits.Last_Path_Bit) + & ASCII.LF + & "};"); + Group_Init.Append (+("&" & Buffers_Struct)); + + File.New_Line; + + -- Track which CU_Id maps to which instrumented unit + + Instrumented_Unit_CUs.Insert (CU_Name, CU); - File.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); - File.New_Line; + I := I + 1; + end; + end loop; - -- Define the individual buffers (statement, decision and MC/DC, - -- which are static) as well as pointers to them (exported). + declare + Buffers_Count_Img : constant String := Img (Buffers_Count); + begin + -- Then define pointers to these individual buffers. Put all pointers + -- to statement buffers in an exported array (same for decision and + -- for MC/DC). - File.Put_Line - ("static unsigned char " & Statement_Buffer_Repr & "[" - & Img (Any_Bit_Id'Max (1, UIC.Unit_Bits.Last_Statement_Bit + 1)) - & "];"); Put_Format_Def (File, Instrumenter, "unsigned char *const", - Statement_Buffer, - Init_Expr => "&" & Statement_Buffer_Repr & "[0]"); - - File.Put_Line - ("static unsigned char " & Decision_Buffer_Repr & "[" - & Img (Any_Bit_Id'Max (1, UIC.Unit_Bits.Last_Outcome_Bit + 1)) - & "];"); + Statement_Buffers, + Array_Size => Buffers_Count_Img, + Init_Expr => Format_Array_Init_Expr + (Statement_Init, Multiline => True)); Put_Format_Def (File, Instrumenter, "unsigned char *const", - Decision_Buffer, - Init_Expr => "&" & Decision_Buffer_Repr & "[0]"); - - File.Put_Line - ("static unsigned char " & MCDC_Buffer_Repr & "[" - & Img (Any_Bit_Id'Max (1, UIC.Unit_Bits.Last_Path_Bit + 1)) - & "];"); + Decision_Buffers, + Array_Size => Buffers_Count_Img, + Init_Expr => Format_Array_Init_Expr + (Decision_Init, Multiline => True)); Put_Format_Def (File, Instrumenter, "unsigned char *const", - MCDC_Buffer, - Init_Expr => "&" & MCDC_Buffer_Repr & "[0]"); - - -- Create the gnatcov_rts_coverage_buffers struct - - File.Put_Line - ("static const struct gnatcov_rts_coverage_buffers " - & Buffers_Record & " = {" - & ASCII.LF - & " .fingerprint = " & To_String (Fingerprint) & "," - & ASCII.LF - & " .language_kind = FILE_BASED_LANGUAGE," - & ASCII.LF - & " .unit_part = NOT_APPLICABLE_PART," - & ASCII.LF - - -- Old toolchains (for instance GNAT Pro 7.1.2) consider that - -- "STR()" is not a static expression, and thus - -- refuse using STR to initialize a global data structure. To - -- workaround this, emit a gnatcov_rtr_string literal ourselves. - - & " .unit_name = " & Format_Str_Constant (Unit_Name) & "," - & ASCII.LF - & " .project_name = " & Format_Str_Constant (Project_Name) & "," - & ASCII.LF - - -- We do not use the created pointer (Statement_Buffer) to - -- initialize the buffer fields, as this is rejected by old - -- versions of the compiler (up to the 20 version): the - -- initializer element is considered not constant. To work around - -- it, we simply use the original expression instead of using a - -- wrapper pointer. - - & " .statement = &" & Statement_Buffer_Repr & "[0]," - & ASCII.LF - & " .decision = &" & Decision_Buffer_Repr & "[0]," - & ASCII.LF - & " .mcdc = &" & MCDC_Buffer_Repr & "[0]," - & ASCII.LF - - & " .statement_last_bit = " & Statement_Last_Bit & "," - & ASCII.LF - & " .decision_last_bit = " & Decision_Last_Bit & "," - & ASCII.LF - & " .mcdc_last_bit = " & MCDC_Last_Bit - & ASCII.LF - & "};"); + MCDC_Buffers, + Array_Size => Buffers_Count_Img, + Init_Expr => Format_Array_Init_Expr + (MCDC_Init, Multiline => True)); -- Create the buffers group: first the array of buffers (static), -- then the gnatcov_rts_coverage_buffers_group struct (extern). - File.Put_Line ("static const struct gnatcov_rts_coverage_buffers *" - & Buffers_Group_Array & "[] = {"); - File.Put_Line (" &" & Buffers_Record); - File.Put_Line ("};"); + File.Put_Line + ("static const struct gnatcov_rts_coverage_buffers *" + & Buffers_Array & "[" & Buffers_Count_Img & "] = " + & Format_Array_Init_Expr (Group_Init, Multiline => True) & ";"); Put_Format_Def (File, Instrumenter, "const struct gnatcov_rts_coverage_buffers_group", Unit_Buffers_Name (UIC.Instrumented_Unit), - Init_Expr => "{1, " & Buffers_Group_Array & "}"); + Init_Expr => + "{" & Img (Buffers_Count) & ", &" & Buffers_Array & "[0]}"); end; end Emit_Buffer_Unit; @@ -3520,6 +3791,7 @@ package body Instrument.C is (Instrumenter : C_Family_Instrumenter_Type'Class; C_Type : String; Name : String; + Array_Size : String := ""; Func_Args : String := "") return String is begin return @@ -3527,8 +3799,9 @@ package body Instrument.C is (Instrumenter, C_Type, Name, - Func_Args => Func_Args, - External => True); + Array_Size => Array_Size, + Func_Args => Func_Args, + External => True); end Format_Extern_Decl; --------------------- @@ -3541,12 +3814,13 @@ package body Instrument.C is Instrumenter : C_Family_Instrumenter_Type'Class; C_Type : String; Name : String; + Array_Size : String := ""; Func_Args : String := "") is begin CX_Rewriter_Insert_Text_After (Rewriter, Location, - Format_Extern_Decl (Instrumenter, C_Type, Name, Func_Args) + Format_Extern_Decl (Instrumenter, C_Type, Name, Array_Size, Func_Args) & ASCII.LF); end Put_Extern_Decl; @@ -3724,10 +3998,6 @@ package body Instrument.C is -- be compatible with a C-only compiler. Emit_Buffer_Unit (Prj_Info, UIC, Self); - - -- Track which CU_Id maps to which instrumented unit - - Instrumented_Unit_CUs.Insert (CU_Name, UIC.CU); end Instrument_Unit; ---------------------- diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index eb42972bc..95e896769 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -166,6 +166,26 @@ package Instrument.C is package Source_Condition_Vectors is new Ada.Containers.Vectors (Natural, C_Source_Condition); + type C_Instrumented_Entities is record + Buffers_Index : Natural := 0; + -- 1-based index of the set of coverage buffers for this source file. We + -- allow 0 while it is uninitialized. Once all instrumented entities are + -- known, we allocate coverage buffers (UIC.Allocated_Bits) and + -- initialize Buffers_Index at the same time. + + Statements : Source_Statement_Vectors.Vector; + Decisions : Source_Decision_Vectors.Vector; + Conditions : Source_Condition_Vectors.Vector; + -- Statements, decisions and conditions (for MC/DC) to be instrumented + end record; + -- Coverage buffer information for a given source file + + package C_Instrumented_Entities_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Valid_Source_File_Index, + Element_Type => C_Instrumented_Entities); + -- Mapping from source files to all the entities to be instrumented in that + -- source file. + type Pass_Kind is abstract tagged private; type Pass_Kind_Acc is access all Pass_Kind'Class; -- As we want to keep some information about coverage obligations inside @@ -311,9 +331,7 @@ package Instrument.C is File : Ada.Strings.Unbounded.Unbounded_String; -- Original filename - Source_Statements : Source_Statement_Vectors.Vector; - Source_Decisions : Source_Decision_Vectors.Vector; - Source_Conditions : Source_Condition_Vectors.Vector; + Instrumented_Entities : C_Instrumented_Entities_Maps.Map; -- Statements, decisions and (for MC/DC) conditions to be -- instrumented. @@ -334,6 +352,16 @@ package Instrument.C is Sources_Of_Interest : Source_Of_Interest_Maps.Map; -- Records for each source file processed during the instrumentation -- whether it is a source of interest, and some properties if it is. + + Allocated_Bits : Allocated_Bits_Vectors.Vector; + -- Allocated bits in coverage buffers for low-level SCOs. We allocate + -- one set of coverage buffers per source file, i.e. one per entry in + -- Instrumented_Entities. + + CUs : Created_Unit_Maps.Map; + -- Compilation units created while instrumenting this source file. + -- Initialized when calling Process_Low_Level_SCOs in + -- Instrument_Source_File. end record; type C_Source_Rewriter is tagged limited private; @@ -352,6 +380,14 @@ package Instrument.C is private + function Find_Instrumented_Entities + (UIC : in out C_Unit_Inst_Context'Class; + SFI : Valid_Source_File_Index) + return C_Instrumented_Entities_Maps.Reference_Type; + -- Return a reference to the UIC.Instrumented_Entities entry + -- corresponding to the source file that SFI designates. If there is no + -- such entry yet, create it. + type Pass_Kind is abstract tagged null record; procedure Append_SCO diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 1baa2dc33..e2da01b27 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -793,6 +793,18 @@ package body Instrument.Common is end return; end Allocate_Decision_Bits; + ---------------------- + -- Create_Unit_Bits -- + ---------------------- + + function Create_Unit_Bits + (Allocated_Bits : in out Allocated_Bits_Vectors.Vector; + SFI : Valid_Source_File_Index) return Positive is + begin + Allocated_Bits.Append (Common.Allocated_Bits'(SFI => SFI, others => <>)); + return Allocated_Bits.Last_Index; + end Create_Unit_Bits; + ------------------------ -- Import_Annotations -- ------------------------ diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index f794c07e8..ff84ef811 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -65,6 +65,7 @@ with Libadalang.Analysis; use Libadalang.Analysis; with Libadalang.Rewriting; use Libadalang.Rewriting; with ALI_Files; use ALI_Files; +with Files_Table; use Files_Table; with GNATcov_RTS; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Instrument.Base_Types; use Instrument.Base_Types; @@ -438,6 +439,9 @@ package Instrument.Common is new Ada.Containers.Vectors (Nat, Decision_Bit_Ids); type Allocated_Bits is record + SFI : Valid_Source_File_Index; + -- Source file index for the SCOs associated to these coverage buffers + Statement_Bits : LL_Statement_SCO_Bit_Allocs.Vector; Last_Statement_Bit : Any_Bit_Id := No_Bit_Id; @@ -475,6 +479,19 @@ package Instrument.Common is -- paths exceeds the limit, must be 0: this function emits a warning in -- this case. + package Allocated_Bits_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, Element_Type => Allocated_Bits); + -- Allocated bits in coverage buffers for low-level SCOs (one per source + -- file). Because of #include directives in C/C++, a single compilation + -- unit may yield multiple sets of coverage buffers: one for the compiled + -- source file, one for each included source. + + function Create_Unit_Bits + (Allocated_Bits : in out Allocated_Bits_Vectors.Vector; + SFI : Valid_Source_File_Index) return Positive; + -- Allocate a new set of coverage buffers for the given source file. Return + -- the index for the newly created set of buffers. + ----------------------------- -- Instrumentation context -- ----------------------------- @@ -519,9 +536,6 @@ package Instrument.Common is -- Name of the compilation unit that holds coverage buffers for the -- unit currently being instrumented (see Common.Buffer_Unit). - Unit_Bits : Allocated_Bits; - -- Record of allocation of coverage buffer bits for low-level SCOs - Annotations : Annotation_Vectors.Vector; -- Annotations created during the instrumentation process, to insert in -- ALI_Files.ALI_Annotations afterwards, when the compilation unit diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index d0723212e..352b9f9ef 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -92,6 +92,8 @@ package SC_Obligations is No_CU_Id : constant CU_Id := 0; subtype Valid_CU_Id is CU_Id range No_CU_Id + 1 .. CU_Id'Last; + package CU_Id_Vectors is new Ada.Containers.Vectors (Positive, CU_Id); + function Provider (CU : CU_Id) return SCO_Provider; -- Return the SCO provider corresponding to the given compilation unit From d5bc5137b3e5b1c21e78efc1f3def8528912b14f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 7 Oct 2022 08:44:07 +0000 Subject: [PATCH 0038/1483] Instrument: allow annotations to refer to various source files So far, the processing for annotations (pragma Annotate (Xcov) in Ada, or comments in C/C++ to create exemptions) assumed that only the main instrumented source file could have annotations. Upcoming work to support coverage in C headers (included sources) will need to support annotations in other files. Since C headers are still ignored for instrumentation, there is no change of behavior, this is just preparatory work. TN: V728-002 Change-Id: Id2603e5a0938381f4dc1bc0f5a5c31fd1207d26a --- tools/gnatcov/instrument-ada_unit.adb | 5 +++-- tools/gnatcov/instrument-c.adb | 10 ++++++---- tools/gnatcov/instrument-common.adb | 16 ++++++---------- tools/gnatcov/instrument-common.ads | 9 +++++---- 4 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 7ca52118d..193692527 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -4551,7 +4551,8 @@ package body Instrument.Ada_Unit is end if; UIC.Annotations.Append - (Annotation_Couple'(+Sloc (N), Ann)); + (Annotation_Couple' + ((UIC.SFI, +Sloc (N)), Ann)); exception when Constraint_Error => @@ -6630,7 +6631,7 @@ package body Instrument.Ada_Unit is -- Import annotations in our internal tables - UIC.Import_Annotations; + UIC.Import_Annotations (Created_Units); -- Import non-instrumented SCOs in the internal tables diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index c24ea5298..d8571dd27 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2815,14 +2815,16 @@ package body Instrument.C is new String' (Comment (Match_Res (1).First .. Match_Res (1).Last)); UIC.Annotations.Append - ((Sloc (Get_Token_Location (UIC.TU, Token)), Ann)); + (((UIC.SFI, Sloc (Get_Token_Location (UIC.TU, Token))), + Ann)); end if; Match (End_Matcher, Comment, Match_Res); if Match_Res (0) /= No_Match then Ann.Kind := Exempt_Off; UIC.Annotations.Append - ((Sloc - (Get_Range_End (Get_Token_Extent (UIC.TU, Token))), + (((UIC.SFI, + Sloc + (Get_Range_End (Get_Token_Extent (UIC.TU, Token)))), Ann)); end if; end; @@ -2931,7 +2933,7 @@ package body Instrument.C is -- Import annotations in our internal tables - UIC.Import_Annotations; + UIC.Import_Annotations (UIC.CUs); Filter_Annotations; for Cur in UIC.Instrumented_Entities.Iterate loop diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index e2da01b27..4db27b982 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -809,18 +809,14 @@ package body Instrument.Common is -- Import_Annotations -- ------------------------ - procedure Import_Annotations (UIC : in out Unit_Inst_Context) is + procedure Import_Annotations + (UIC : in out Unit_Inst_Context; Created_Units : Created_Unit_Maps.Map) is begin for Couple of UIC.Annotations loop - declare - Sloc : constant Source_Location := - (Source_File => UIC.SFI, - L => Couple.Sloc); - begin - Couple.Annotation.CU := UIC.CU; - ALI_Annotations.Insert - (Key => Sloc, New_Item => Couple.Annotation); - end; + Couple.Annotation.CU := + Created_Units.Element (Couple.Sloc.Source_File); + ALI_Annotations.Insert + (Key => Couple.Sloc, New_Item => Couple.Annotation); end loop; end Import_Annotations; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index ff84ef811..cd707d30f 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -504,7 +504,7 @@ package Instrument.Common is -- MC/DC instrumentation depends on BDD information. type Annotation_Couple is record - Sloc : Local_Source_Location; + Sloc : Source_Location; Annotation : ALI_Annotation; end record; -- When instrumenting sources, annotations are registred in two steps: @@ -549,10 +549,11 @@ package Instrument.Common is end record; - procedure Import_Annotations (UIC : in out Unit_Inst_Context) with - Pre => UIC.CU /= No_CU_Id; + procedure Import_Annotations + (UIC : in out Unit_Inst_Context; Created_Units : Created_Unit_Maps.Map); -- Import ALI annotations for this unit in the global annotations table. - -- This should be called once the unit was insturmented and given a CU id. + -- This should be called once the unit was instrumented and its low level + -- SCOS have been transformed into high-level ones. function Img (Bit : Any_Bit_Id) return String is (Strings.Img (Integer (Bit))); From 59680524d14ae97026e1dce970668d4c9e47e122 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 7 Oct 2022 08:59:55 +0000 Subject: [PATCH 0039/1483] Instrument: make the context CU component specific to Ada This component assumes the the instrumenter deals with exactly one source file at a time. While this is true for Ada, this will no longer be the case for C/C++ once we start computing code coverage for C headers. Move the CU component from common code to Ada-specific code to reflect that. TN: V728-002 Change-Id: I5b3d4bff50bac15a856e1fa8ed1291d089dbd813 Depends-On: I90ce80bb9d5fb138228a8a3dcc500fc7428d184c --- tools/gnatcov/instrument-ada_unit.ads | 3 +++ tools/gnatcov/instrument-c.adb | 5 ----- tools/gnatcov/instrument-common.ads | 3 --- 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index aa4e67269..f4819f49d 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -229,6 +229,9 @@ private type Ada_Unit_Inst_Context is new Instrument.Common.Unit_Inst_Context with record + CU : CU_Id := No_CU_Id; + -- SCO identifier of the compilation unit being instrumented + Root_Unit : Compilation_Unit; -- Node of compilation unit diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index d8571dd27..dbce28cdf 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2926,11 +2926,6 @@ package body Instrument.C is end; end loop; - -- In the instrumentation case, the origin of SCO information is - -- the original source file. - - UIC.CU := UIC.CUs.Element (UIC.SFI); - -- Import annotations in our internal tables UIC.Import_Annotations (UIC.CUs); diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index cd707d30f..6f3eb9dcb 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -529,9 +529,6 @@ package Instrument.Common is SFI : Source_File_Index := No_Source_File; -- Source file index of the compilation unit being instrumented - CU : CU_Id := No_CU_Id; - -- SCO identifier of the compilation unit being instrumented - Buffer_Unit : Compilation_Unit_Name; -- Name of the compilation unit that holds coverage buffers for the -- unit currently being instrumented (see Common.Buffer_Unit). From 7880c3c9b341d3fe8fbba07990b71eba67c220fa Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 16 Sep 2022 15:24:17 +0200 Subject: [PATCH 0040/1483] Instrument.C: fix dump-trigger when main is in linkage specifier If the main was in a linkage specifier section, it was not detected and so gnatcov instrument did not insert any code to dump buffers. Fix the detection of the main in that case. TN: V916-012 Depends-On: Ib1d58309772a03453e317d42ce06d76b60df5e5b Change-Id: I3335a8333ebdc34bf1e420b63fe981c6109d546f --- tools/gnatcov/instrument-c.adb | 31 ++++++++++++-- tools/gnatcov/instrument-c_utils.adb | 60 +--------------------------- tools/gnatcov/instrument-c_utils.ads | 7 ---- 3 files changed, 29 insertions(+), 69 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index dbce28cdf..20c95ea24 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3559,11 +3559,19 @@ package body Instrument.C is Insert_Extern_Location : constant Source_Location_T := Find_First_Insert_Location (Rew.TU); -- Where to insert extern declarations + + Main_Cursor : constant Cursor_T := Get_Main (Rew.TU); + -- Cursor of the main declaration begin if Instr_Units.Is_Empty then return; end if; + if Main_Cursor = Get_Null_Cursor then + Outputs.Fatal_Error ("Could not find main function in " + & (+Main.Filename)); + end if; + Emit_Dump_Helper_Unit (IC, Info, Main, Helper_Filename, Instrumenter); Put_Extern_Decl @@ -3663,7 +3671,7 @@ package body Instrument.C is end Process; begin - Visit_Children (Parent => Get_Main (Rew.TU), + Visit_Children (Parent => Main_Cursor, Visitor => Process'Access); end; @@ -3676,9 +3684,24 @@ package body Instrument.C is "atexit", Func_Args => "void (*function) (void)"); - Add_Statement_In_Main - (Rew.TU, Rew.Rewriter, - "atexit (" & Dump_Procedure_Symbol (Main) & ");"); + declare + Body_Cursor : constant Cursor_T := Get_Body (Main_Cursor); + + -- The body of a function is a compound statement, so insert + -- the call to atexit before its first statement. + + Body_Stmts : constant Cursor_Vectors.Vector := + Get_Children (Body_Cursor); + First_Stmt : constant Cursor_T := Body_Stmts.First_Element; + + Location : constant Source_Location_T := + Get_Cursor_Location (First_Stmt); + begin + CX_Rewriter_Insert_Text_Before + (Rew => Rew.Rewriter, + Loc => Location, + Insert => "atexit (" & Dump_Procedure_Symbol (Main) & ");"); + end; when others => null; diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index d92422b95..4a9074c40 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -225,7 +225,8 @@ package body Instrument.C_Utils is function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T is begin - if Kind (Cursor) = Cursor_Translation_Unit then + if Kind (Cursor) in Cursor_Translation_Unit | Cursor_Linkage_Spec + then return Child_Visit_Recurse; end if; if Cursor_Get_Mangling (Cursor) = "main" then @@ -245,63 +246,6 @@ package body Instrument.C_Utils is -- Rewriting utilities - --------------------------- - -- Add_Statement_In_Main -- - --------------------------- - - procedure Add_Statement_In_Main - (TU : Translation_Unit_T; - Rew : Rewriter_T; - Statement : String) - is - function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T; - -- Traverse the tree until the main function is found, and insert a - -- statement. - - ---------------- - -- Visit_Decl -- - ---------------- - - function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T is - begin - if Kind (Cursor) = Cursor_Translation_Unit then - return Child_Visit_Recurse; - - elsif Cursor_Get_Mangling (Cursor) = "main" then - declare - Fun_Children : constant Vector := Get_Children (Cursor); - Body_Cursor : constant Cursor_T := - Fun_Children (Last_Index (Fun_Children)); - - -- Body of a function is a compound statement, so rewrite - -- before its first children node will do. - - Body_Stmts : constant Vector := Get_Children (Body_Cursor); - First_Stmt : constant Cursor_T := - Body_Stmts (First_Index (Body_Stmts)); - - Location : constant Source_Location_T := - Get_Cursor_Location (First_Stmt); - begin - CX_Rewriter_Insert_Text_Before - (Rew => Rew, - Loc => Location, - Insert => Statement); - end; - return Child_Visit_Break; - - else - return Child_Visit_Continue; - end if; - end Visit_Decl; - - -- Start of processing for Add_Statement_In_Main - - begin - Visit_Children (Parent => Get_Translation_Unit_Cursor (TU), - Visitor => Visit_Decl'Access); - end Add_Statement_In_Main; - -------------------------------- -- Insert_Text_After_Start_Of -- -------------------------------- diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 248d74d2d..d312e85b6 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -90,13 +90,6 @@ package Instrument.C_Utils is -- Rewriting utilities -- ------------------------- - procedure Add_Statement_In_Main - (TU : Translation_Unit_T; - Rew : Rewriter_T; - Statement : String); - -- Add a statement at the beginning of the main, and before any previously - -- inserted string at the same location. - procedure Insert_Text_After_Start_Of (N : Cursor_T; Text : String; From 702ff45d0f6060c48b0d2ea89208890bf48afe5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 5 Oct 2022 10:58:46 +0200 Subject: [PATCH 0041/1483] Instrument: fix handling of mains given on the cmdline for units of interest Mains specified only on the command line that were already units of interest were instrumented as any other source file. Now they are marked as mains and can be instrumented as such. Also, when adding a unit of interest, always mark it as not being a main. The decision according to the gpr file and the command line is made later so no such computation needs to be done here. TN: V911-003 Change-Id: Ica7c973433257fc4c62b83887efcb36cb6d29040 --- tools/gnatcov/instrument-common.adb | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 4db27b982..4695ba295 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -573,10 +573,20 @@ package body Instrument.Common is begin -- If this main is already a unit of interest, no need to register it: -- we will instrument it as part of our regular instrumentation process. + -- However, mains can be passed via the command line or in the GPR file + -- and we don't know which main to use when first registering units of + -- interest. Since every unit of interest is marked as not begin a main, + -- this information must be updated here by setting Is_Main accordingly. - if Context.Instrumented_Units.Contains (CU_Name) then - return; - end if; + declare + C : constant Instrumented_Unit_Maps.Cursor := + Context.Instrumented_Units.Find (CU_Name); + begin + if Instrumented_Unit_Maps.Has_Element (C) then + Instrumented_Unit_Maps.Element (C).Is_Main := True; + return; + end if; + end; declare Prj_Info : constant Project_Info_Access := @@ -615,14 +625,17 @@ package body Instrument.Common is return; end if; + -- Because different main files than those given in the GPR file can + -- be passed via command line, set Is_Main to false for every + -- file and decide which to use as mains accordingly later. + declare Unit_Info : constant Instrumented_Unit_Info_Access := new Instrumented_Unit_Info' (Filename => To_Unbounded_String (+Source_File.File.Full_Name), Prj_Info => Get_Or_Create_Project_Info (Context, Project), - Is_Main => GNATCOLL.Projects.Is_Main_File - (Project, Source_File.File.Base_Name), + Is_Main => False, Language => To_Language (Source_File.Language)); begin Context.Instrumented_Units.Insert (CU_Name, Unit_Info); From da91241e24990708523a880863abc42eca473911 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 30 Sep 2022 10:00:36 +0000 Subject: [PATCH 0042/1483] Project.Iterate_Projects: remove the Extended formal (unused) Change-Id: Ie214dff196561a96f55f55e27324b390bb20c19b TN: V930-029 --- tools/gnatcov/project.adb | 14 +++++--------- tools/gnatcov/project.ads | 7 +------ 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 4f794ff91..5c1e3de9c 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -311,8 +311,7 @@ package body Project is procedure Iterate_Projects (Root_Project : Project_Type; Process : access procedure (Prj : Project_Type); - Recursive : Boolean; - Extended : Boolean := False) + Recursive : Boolean) is Iter : Project_Iterator := Start (Root_Project => Root_Project, @@ -320,19 +319,16 @@ package body Project is Include_Extended => False); Visited_Projects : Project_Sets.Set; Project : Project_Type; - begin loop Project := Current (Iter); exit when Project = No_Project; - -- Unless specifically asked to go through extended projects, go to - -- the ultimate extending project, which might override the Coverage - -- package. + -- Go to the ultimate extending project: this is the "reference" + -- project for chains of project extension (we care about the + -- Coverage package of extending projects, their object dirs, etc.). - if not Extended then - Project := Extending_Project (Project, Recurse => True); - end if; + Project := Extending_Project (Project, Recurse => True); declare Name : constant String := Project.Name; diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 1c2ccb85a..a7e692ab7 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -228,14 +228,9 @@ package Project is procedure Iterate_Projects (Root_Project : GNATCOLL.Projects.Project_Type; Process : access procedure (Prj : GNATCOLL.Projects.Project_Type); - Recursive : Boolean; - Extended : Boolean := False) + Recursive : Boolean) with Pre => Is_Project_Loaded; -- Call Process on Root_Project if Recursive is False, or on the whole -- project tree otherwise. - -- - -- Visit extended projects only if Extended is True. This is useful only in - -- very specific cases, such as when needing to process all object - -- direcotries in the project tree. end Project; From bc93ce4e03994a3f935f18c91c5679ee9198ebf4 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 22 Sep 2022 14:45:51 +0200 Subject: [PATCH 0043/1483] Do not warn on missing object / library directory When loading the project file, we should avoid warning on missing object directory as it won't impact gnatcov usability. TN: V922-008 Change-Id: I2b2cf35e0903271af29e7f3e1ade6a0d83a49a6f --- tools/gnatcov/project.adb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 5c1e3de9c..13c026ada 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -1284,10 +1284,11 @@ package body Project is Prj_Tree := new Project_Tree; begin Prj_Tree.Load - (Root_Project_Path => Create (+Prj_Name), - Env => Env, - Packages_To_Check => Coverage_Package_List'Access, - Errors => Outputs.Warning_Or_Error'Access); + (Root_Project_Path => Create (+Prj_Name), + Env => Env, + Packages_To_Check => Coverage_Package_List'Access, + Errors => Outputs.Warning_Or_Error'Access, + Report_Missing_Dirs => False); exception when Invalid_Project => Free (Prj_Tree); From 7bfc255b0de54913811b60448863cdd617c652fd Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 19 Aug 2022 11:10:03 +0200 Subject: [PATCH 0044/1483] C instrumentation: make warning more precise When there is a mismatching between the preprocessing phase, and the instrumentation phase, we output a warning and discard the preprocessing information. Make this warning more precise. Change-Id: Ic8aee1665df206cf1c3baf0af914adc1a66c012d TN: V816-018 --- tools/gnatcov/instrument-c.adb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 20c95ea24..09d5a9627 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2883,8 +2883,10 @@ package body Instrument.C is if Record_PP_Info_Last_SCO /= SCOs.SCO_Table.Last then Outputs.Warn (Orig_Filename & ": preprocessed file coverage obligations" - & " inconsistent with obligations from the original file." - & " Discarding preprocessing information."); + & " inconsistent with original file obligations (expecting" + & Nat'Image (Record_PP_Info_Last_SCO) & " coverage obligations," + & " but got" & Nat'Image (SCOs.SCO_Table.Last) + & ". Discarding preprocessing information."); UIC.LL_PP_Info_Map.Clear; end if; From 975777a3f50a883918b5fe8f54898354f5084a67 Mon Sep 17 00:00:00 2001 From: Leo Creuse Date: Thu, 8 Sep 2022 16:09:01 +0200 Subject: [PATCH 0045/1483] Document new Undetermined Coverage state Change-Id: I77c81890a3637a3f39b9d4a6a711e6fb287482e9 TN: V419-003 --- doc/gnatcov/cov_source.rst | 25 ++++++++++++++++++++++--- doc/gnatcov/exemptions.rst | 13 +++++++++++++ doc/gnatcov/src_traces.rst | 8 +++++--- 3 files changed, 40 insertions(+), 6 deletions(-) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index d9861b79c..28bdf284b 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -258,8 +258,12 @@ in a single character, which may be one of the following: ``.`` | No coverage obligation is attached to the line ``-`` | Coverage obligations attached to the line, none satisfied ``!`` | Coverage obligations attached to the line, some satisfied + ``?`` | Coverage obligations attached to the line, undetermined coverage state (*) ``+`` | Coverage obligations attached to the line, all satisfied +(*) The Undetermined Coverage state (``?``) is only shown on the line in the +absence of other known violations for that same line. + Here is, to illustrate, the full statement coverage report produced for our example unit when the ``Between`` function was called so that the ``if`` control evaluated True only. The function is actually part of an Ada package, @@ -356,9 +360,13 @@ assessed criteria. The report features explicit start/end of report notifications and at least three sections in between: Assessment Context, Coverage Violations, and -Analysis Summary. A few variations are introduced when :term:`exemption -regions ` are in scope. See the :ref:`exemptions` section -for more details on their use and effect on the output reports. +Analysis Summary. Should |gcv| be unable to determine the coverage state of +some coverage obligations, those will be reported in a dedicated Undetermined +Coverage Items section, with a description of why the tool was unable to +determine the coverage state for each obligation. A few variations are +introduced when :term:`exemption regions ` are in scope. +See the :ref:`exemptions` section for more details on their use and effect on +the output reports. If :cmd-option:`--dump-units-to -` is also on the command line, a *UNITS OF INTEREST* section is produced, which contains the list of units considered @@ -551,8 +559,12 @@ indications: ``-`` | At least one statement on the line, none covered ``!`` | More than one statement on the line, some covered + ``?`` | At least one statement on this line, some with undetermined coverage state (*) ``+`` | At least one statement on the line, all covered +(*) The Undetermined Coverage state (``?``) is only shown on the line in the +absence of other known violations for that same line. + When a single statement spans multiple lines, the coverage annotation is present on all the lines, as the two ``+`` signs for the single assignment in the following excerpt:: @@ -807,8 +819,11 @@ following table summarizes the meaning of the possible annotations: ``-`` | At least one statement on the line, none executed. ``!`` | Unless multiple statements are involved, decision partially covered on the line. + ``?`` | At least one statement or decision on the line with undetermined coverage state. (*) ``+`` | All the statements and decisions on the line are covered. +(*) The Undetermined Coverage state (``?``) is only shown on the line in the +absence of other known violations for that same line. When a trailing `+` is added to the format passed to :cmd-option:`--annotate` (:cmd-option:`=xcov+` or :cmd-option:`=html+`), a precise description of the @@ -1020,8 +1035,12 @@ condition specific cases marked with a ``!`` as well: ``-`` | At least one statement associated with this line, none executed. ``!`` | For a single statement line, decision partially covered or condition not covered on the line. + ``?`` | At least one statment or decision on the line with undetermined coverage state. (*) ``+`` | All the statements, decisions and conditions on the line are covered. +(*) The Undetermined Coverage state (``?``) is only shown on the line in the +absence of other known violations for that same line. + The :cmd-option:`=report` outputs feature an extra MCDC section in the Coverage Violations segment, which holds: diff --git a/doc/gnatcov/exemptions.rst b/doc/gnatcov/exemptions.rst index c3c59d8a9..aa3545564 100644 --- a/doc/gnatcov/exemptions.rst +++ b/doc/gnatcov/exemptions.rst @@ -169,6 +169,19 @@ In synthetic reports, the count of exempted violations is 0, like:: 1 exempted region. +Undetermined Coverage state and Exemptions +------------------------------------------ + +For each exemption region in which there are obligations with undetermined +coverage state, the synthetic text report will indicate the count of +undetermined coverage obligations in the region, in addition to the number +of violations. + +In the annotated sources, exemption regions with *only* undetermined coverage +items are annotated with ``@`` signs instead of ``*``. If there are both +undetermined coverage obligations as well as violations in the exemption +region, the corresponding lines is still annotated with ``#``. + .. _ocov_exemptions: Object coverage exemptions diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 91cfa0e16..ed872aefa 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -356,10 +356,12 @@ section :ref:`spark_instr`. Unsupported source constructs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -There are a few language constructs that |gcvins| doesn't handle properly. +There are a few language constructs that |gcvins| doesn't support. The tool emits a warning when it encounters such cases and the corresponding -code is not instrumented. Source coverage obligations are still emitted, so -the unsupported constructs will appear as ``not covered`` in the report. +code is not instrumented. Source coverage obligations are still emitted, and +the unsupported constructs will be reported in a separate +``Undetermined_Coverage`` category, to differentiate them from actual coverage +violations. The list of unsupported constructs is as follows: From 8ed756b8c532422ce000ecbc881810affac15302 Mon Sep 17 00:00:00 2001 From: Leo Creuse Date: Thu, 8 Sep 2022 17:55:51 +0200 Subject: [PATCH 0046/1483] Document limitation for decisions with overly large BDDs Change-Id: Ie4f5afcd2377e1e0d7de159a80add738ade10313 TN: U728-010 --- doc/gnatcov/src_traces.rst | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index ed872aefa..6fe1a6ddf 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -348,7 +348,7 @@ providing the variable name to use. |gcvins| limitations -------------------- -There are situations and code patterns not handeled correctly by |gcvins|. +There are situations and code patterns not handled correctly by |gcvins|. Below are listed the limitations associated with general Ada sources. Coverage of SPARK sources require additional considerations, detailed in section :ref:`spark_instr`. @@ -372,11 +372,19 @@ The list of unsupported constructs is as follows: tagged type. The simplest way to work around the limitation concerning expression functions -is to turn them into regular funtions, by giving them a proper body, -containing a single return statment with the original expression. +is to turn them into regular functions, by giving them a proper body, +containing a single return statement with the original expression. Otherwise it is possible to exempt those constructs (see :ref:`exemptions`) and/or perform a manual coverage analysis for these special cases. +Additionally, the MC/DC instrumentation of decisions with many conditions +may require more memory than available (during instrumentation and/or at +run-time) to enumerate the possible paths through the decision. To avoid this, +|gcv| will not instrument such decisions for MC/DC, emitting a warning in the +process, and the MC/DC coverage for each decision will be reported as +``Undetermined_Coverage`` state. Should the default limit not be satisfactory, +it can be tuned with the option :cmd-option:`--path-count-limit`. + Global source traces limitations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -391,7 +399,7 @@ Toolchain-specific limitations With GNAT versions from 7.1 to 7.3, compiling with optimization will result in coverage violations on all statement obligations associated with expression -functions. Explicitely disabling optimization (with ``-O0`` for instance) will +functions. Explicitly disabling optimization (with ``-O0`` for instance) will resolve this issue. .. _instr-build: From b89ec33e1a70c5caf1eed807fa612fa087dbf17a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 15 Mar 2022 17:54:32 +0100 Subject: [PATCH 0047/1483] Enhance qualif testsuite for complex if expression As noticed in the qgen codebase, when we have an if expression inside a decision and if the operands of that if expression are complex boolean operands, gnatcov failed to find edges for all of the conditions. This is because the if expression itself (as an operand of the top-level decision), and the operands of the if expression are conditions, but they share the same control flow branches. For example, if we take a look at this example: (if A then B and then C else D and then E) or else B If we focus on the valuation of the C condition Condition Val Res | Condition Val Res --------------------------------------------------- (if_expr) | (if_expr) C ------> True | C -------> B True | False Here, we see that the if expression "condition", and the C "condition" share the same branch. To work around this, the compiler now introduces a temporary holding the value of the if expression. Change-Id: If37d8261c99a1ce57c61dbe62e5decb28d2b9bb6 TN: U709-021 --- testsuite/.gitignore | 1 + .../IfExpr/ComplexInDecision/src/pkg.ads | 18 ++++++++++++++++ .../IfExpr/ComplexInDecision/src/test_1.adb | 19 +++++++++++++++++ .../IfExpr/ComplexInDecision/src/test_2.adb | 19 +++++++++++++++++ .../IfExpr/ComplexInDecision/src/test_3.adb | 20 ++++++++++++++++++ .../IfExpr/ComplexInDecision/src/test_4.adb | 16 ++++++++++++++ .../ComplexInDecision/src/test_full.adb | 21 +++++++++++++++++++ .../1_Core/IfExpr/ComplexInDecision/tc.rst | 3 +++ .../1_Core/IfExpr/ComplexInDecision/test.py | 6 ++++++ 9 files changed, 123 insertions(+) create mode 100644 testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/pkg.ads create mode 100644 testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_1.adb create mode 100644 testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_2.adb create mode 100644 testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_3.adb create mode 100644 testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_4.adb create mode 100644 testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_full.adb create mode 100644 testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/tc.rst create mode 100644 testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.py diff --git a/testsuite/.gitignore b/testsuite/.gitignore index f6174cf15..8a9351363 100644 --- a/testsuite/.gitignore +++ b/testsuite/.gitignore @@ -5,3 +5,4 @@ st_* tmp_* wd_* test.py.* +.~undo-tree~ \ No newline at end of file diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/pkg.ads b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/pkg.ads new file mode 100644 index 000000000..3a40c6608 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/pkg.ads @@ -0,0 +1,18 @@ +pragma Ada_2012; + +package Pkg is + + function P + (A : Boolean; + B : Boolean; + C : Boolean; + D : Boolean; + E : Boolean; + F : Boolean) return Boolean + is + ((if A -- # eval-if-expr + then B and then C -- # decision-1-if-expr + else D and then E) -- # decision-2-if-expr + or else F); -- # last-cond + +end Pkg; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_1.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_1.adb new file mode 100644 index 000000000..ed3769ceb --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_1.adb @@ -0,0 +1,19 @@ +with Pkg; use Pkg; +with Support; use Support; + +procedure Test_1 is +begin + Assert (P (True, True, True, True, True, True)); +end Test_1; + +--# pkg.ads +-- +-- /decision-1-if-expr/ l! ## eF- +-- /decision-2-if-expr/ l! ## e- +-- /last-cond/ l! ## 0 +-- +--%opts: --trace-mode=bin +-- /eval-if-expr/ l! ## eF-, d! +-- +--%opts: --trace-mode=src +-- /eval-if-expr/ l! ## eF-, dF- \ No newline at end of file diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_2.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_2.adb new file mode 100644 index 000000000..335c33c6c --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_2.adb @@ -0,0 +1,19 @@ +with Pkg; use Pkg; +with Support; use Support; + +procedure Test_2 is +begin + Assert (P (True, False, True, True, True, True)); +end Test_2; + +--# pkg.ads +-- +-- /decision-1-if-expr/ l! ## eT- +-- /decision-2-if-expr/ l! ## e- +-- /last-cond/ l! ## 0 +-- +--%opts: --trace-mode=bin +-- /eval-if-expr/ l! ## eF-, d! +-- +--%opts: --trace-mode=src +-- /eval-if-expr/ l! ## eF-, dF- \ No newline at end of file diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_3.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_3.adb new file mode 100644 index 000000000..e1fda93eb --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_3.adb @@ -0,0 +1,20 @@ +with Pkg; use Pkg; +with Support; use Support; + +procedure Test_3 is +begin + Assert (P (True, True, True, True, True, True)); + Assert (P (True, True, False, True, True, True)); +end Test_3; + +--# pkg.ads +-- +-- /decision-1-if-expr/ l! ## c! +-- /decision-2-if-expr/ l! ## e- +-- /last-cond/ l! ## 0 +-- +--%opts: --trace-mode=bin +-- /eval-if-expr/ l! ## eF-, d! +-- +--%opts: --trace-mode=src +-- /eval-if-expr/ l! ## eF-, dF- \ No newline at end of file diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_4.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_4.adb new file mode 100644 index 000000000..65d69959a --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_4.adb @@ -0,0 +1,16 @@ +with Pkg; use Pkg; +with Support; use Support; + +procedure Test_4 is +begin + Assert (P (False, True, True, True, False, True)); + Assert (P (True, True, True, True, True, False)); + Assert (not P (False, True, True, False, True, False)); +end Test_4; + +--# pkg.ads +-- +-- /eval-if-expr/ l+ ## 0 +-- /decision-1-if-expr/ l! ## eF- +-- /decision-2-if-expr/ l! ## eT- +-- /last-cond/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_full.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_full.adb new file mode 100644 index 000000000..5a746f94b --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_full.adb @@ -0,0 +1,21 @@ +with Pkg; use Pkg; +with Support; use Support; + +procedure Test_Full is +begin + Assert (P (True, True, True, True, True, True)); + Assert (P (True, False, True, True, True, True)); + Assert (P (True, True, False, True, True, True)); + Assert (P (False, True, True, True, True, True)); + Assert (P (False, True, True, False, True, True)); + Assert (P (False, True, True, True, False, True)); + + Assert (not P (False, True, True, True, False, False)); +end Test_Full; + +--# pkg.ads +-- +-- /eval-if-expr/ l+ ## 0 +-- /decision-1-if-expr/ l+ ## 0 +-- /decision-2-if-expr/ l+ ## 0 +-- /last-cond/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/tc.rst b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/tc.rst new file mode 100644 index 000000000..dea592510 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/tc.rst @@ -0,0 +1,3 @@ +**MCDC on an if expression in a decision, with decisions as sub expressions** + +LRMREF: 4.5.7 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.py b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.py new file mode 100644 index 000000000..6987337a8 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.mcdc).run() +thistest.result() From 18ea391af173fd014dfbeb011e3b64b6c54f1ce8 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 19 Oct 2022 12:11:02 +0000 Subject: [PATCH 0048/1483] doinstall: replace mentions of GNATcoverage with GNAT DAS TN: VA11-012 Change-Id: Ibe54d64f1d143b9c5ea46023496bc58806f2682a --- tools/gnatcov/doinstall.tmplt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/doinstall.tmplt b/tools/gnatcov/doinstall.tmplt index 8377699ae..eceefddb3 100755 --- a/tools/gnatcov/doinstall.tmplt +++ b/tools/gnatcov/doinstall.tmplt @@ -1,6 +1,6 @@ #! /bin/sh # -# GNATcoverage binary distribution installation script +# GNAT DAS binary distribution installation script # Copyright (c) 2011-2020, Free Software Foundation # @@ -55,7 +55,7 @@ check_env () { ################################### set_qualifier () { - qualifier="GNATcoverage" + qualifier="GNAT DAS" long_qualifier="$qualifier" } @@ -76,9 +76,9 @@ EOF fi } -##################################### -# Install GNATcoverage into $prefix # -##################################### +################################# +# Install GNAT DAS into $prefix # +################################# standard_installation () { @@ -159,11 +159,11 @@ if [ $# -eq 1 ]; then cat << EOF Usage: $0 [install_dir] - When no argument is specified, runs the GNATcoverage installer + When no argument is specified, runs the $qualifier installer interactively, otherwise installs automatically under install_dir. EOF else - echo " installing GNATcoverage under $1" + echo " installing $qualifier under $1" prefix="$1" standard_installation fi From ea628238f25af20487a5570307675bac5adfe8ea Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 14 Oct 2022 14:55:28 +0000 Subject: [PATCH 0049/1483] Setup_RTS: fix how gnatcov_rts.gpr is loaded Refactor config handling: when --config is not provided, use Load_Autoconf, which is the right way to let GPR2 automatically create the configuration. This fixes the loading of projects when only an old (pre-23 release) native 32-bit toolchain is present. TN: VA11-007 Change-Id: Ic9791ec5b4fef3657fab7ed465b7efa6a1dab274 --- tools/gnatcov/setup_rts.adb | 154 +++++++++++++++--------------------- 1 file changed, 65 insertions(+), 89 deletions(-) diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index b03ad8a4b..247a607f8 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -28,7 +28,7 @@ with GNAT.Regexp; with GNATCOLL.JSON; use GNATCOLL.JSON; with GNATCOLL.VFS; use GNATCOLL.VFS; with GPR2.Context; -with GPR2.KB; +with GPR2.Containers; with GPR2.Log; with GPR2.Path_Name; with GPR2.Project.Attribute; @@ -64,20 +64,18 @@ package body Setup_RTS is Ravenscar_RTS_Regexp : constant GNAT.Regexp.Regexp := GNAT.Regexp.Compile (".*(ravenscar|light-tasking|embedded).*"); - function Create_Config - (Target : String; + procedure Load_Project + (Project : in out GPR2.Project.Tree.Object; + Project_File : String; + Target : String; RTS : String; Config_File : String; - Project_File : String) return GPR2.Project.Configuration.Object; - -- Create a GPR2 configuration for C, and for Ada if it is enabled, both - -- for the given target/RTS. If Target is empty, use the knowledge base's - -- default target. - -- - -- If Config_File is not an empty string, disregard Target/RTS and load the - -- configuration from that file instead. + Context : GPR2.Context.Object := GPR2.Context.Empty); + -- Load Project_File for the given Target/RTS/Config_File/Context. -- - -- In case of error, GPR2 uses Project_File as context for the error - -- messages. + -- This does not raise an exception in case of project loading failure: + -- callers are supposed to check Project.Log_Messages to handle possible + -- errors. function Setup_Project (Temp_Dir : Temporary_Directory; @@ -172,61 +170,74 @@ package body Setup_RTS is -- project to install. Use a filename that will match the Install'Artifacts -- attribute in the runtime project file. - ------------------- - -- Create_Config -- - ------------------- + ------------------ + -- Load_Project -- + ------------------ - function Create_Config - (Target : String; + procedure Load_Project + (Project : in out GPR2.Project.Tree.Object; + Project_File : String; + Target : String; RTS : String; Config_File : String; - Project_File : String) return GPR2.Project.Configuration.Object is + Context : GPR2.Context.Object := GPR2.Context.Empty) + is + PF : constant GPR2.Path_Name.Object := + GPR2.Path_Name.Create_File + (GPR2.Filename_Type (Project_File), GPR2.Path_Name.No_Resolution); begin + -- According to the documentation, an error message is recorded in + -- Project when Load and Load_Autoconf raise GPR2.Project_Error + -- exceptions, so we can just ignore this exception and let callers deal + -- with errors recorded in Project.Log_Messages. + -- If a configuration project file is provided, just load it to create -- the configuration. if Config_File /= "" then declare - F : constant GPR2.Path_Name.Object := + F : constant GPR2.Path_Name.Object := GPR2.Path_Name.Create_File (GPR2.Filename_Type (Config_File)); + Config : constant GPR2.Project.Configuration.Object := + GPR2.Project.Configuration.Load (F); begin - return GPR2.Project.Configuration.Load (F); + Project.Load + (Filename => PF, + Context => Context, + Config => Config); + exception + when GPR2.Project_Error => + null; end; - end if; - - -- Otherwise, use the GPR knowledge base to create a configuration for C - -- (needed for the core coverage runtime) and for the Ada language, if - -- enabled. - - declare - Actual_Target : constant GPR2.Name_Type := - (if Target = "" - then GPR2.KB.Default_Target - else GPR2.Name_Type (Target)); - KB : GPR2.KB.Object := GPR2.KB.Create_Default (GPR2.KB.Default_Flags); + -- Otherwise, use the "auto configuration" mode that will use the + -- optional target and RTS information. Always require C (needed for the + -- core coverage runtime) and require the Ada language only if enabled. - Descs : GPR2.Project.Configuration.Description_Set (1 .. 2); - Last : Positive := 1; - begin - Descs (1) := GPR2.Project.Configuration.Create - (Language => GPR2.C_Language, - Runtime => GPR2.Optional_Name_Type (RTS)); - if Src_Enabled_Languages (Ada_Language) then - Descs (2) := GPR2.Project.Configuration.Create - (Language => GPR2.Ada_Language, - Runtime => GPR2.Optional_Name_Type (RTS)); - Last := Last + 1; - end if; + else + declare + RTS_Map : GPR2.Containers.Lang_Value_Map; + Actual_Target : constant GPR2.Optional_Name_Type := + GPR2.Optional_Name_Type (Target); + begin + RTS_Map.Include (GPR2.C_Language, RTS); + if Src_Enabled_Languages (Ada_Language) then + RTS_Map.Include (GPR2.Ada_Language, RTS); + end if; - return GPR2.Project.Configuration.Create - (Settings => Descs (1 .. Last), - Target => Actual_Target, - Project => GPR2.Path_Name.Create_File - (GPR2.Filename_Type (Project_File)), - Base => KB); - end; - end Create_Config; + begin + Project.Load_Autoconf + (Filename => PF, + Context => Context, + Target => Actual_Target, + Language_Runtimes => RTS_Map); + exception + when GPR2.Project_Error => + null; + end; + end; + end if; + end Load_Project; ----------- -- Image -- @@ -411,24 +422,7 @@ package body Setup_RTS is -- Now load the project - begin - Prj.Load - (Filename => GPR2.Project.Create - (GPR2.Filename_Type (Project_File), - GPR2.Project.Default_Search_Paths (True)), - Context => Ctx, - Config => Create_Config - (Target, RTS, Config_File, Project_File)); - exception - when GPR2.Project_Error => - - -- According to the documentation for this exception, an error - -- message is recorded in Prj when it is raised, so we can just - -- ignore the exception and let the processing below take care of - -- the error. - - null; - end; + Load_Project (Prj, Project_File, Target, RTS, Config_File, Ctx); -- Print all messages in verbose mode, and all but the Information ones -- otherwise. Abort on error, or if we failed to get a runtime project @@ -840,25 +834,7 @@ package body Setup_RTS is -- been installed: do not print any error message, and if the project -- fails to load, just return the default setup config. - begin - Prj.Load - (Filename => GPR2.Path_Name.Create_File - (GPR2.Filename_Type (Prj_Filename), - GPR2.Path_Name.No_Resolution), - Context => GPR2.Context.Empty, - Config => Create_Config - (Target, RTS, Config_File, Runtime_Project)); - exception - when GPR2.Project_Error => - - -- According to the documentation for this exception, an error - -- message is recorded in Prj when it is raised, so we can just - -- ignore the exception and let the processing below take care of - -- the error. - - null; - end; - + Load_Project (Prj, Prj_Filename, Target, RTS, Config_File); if Prj.Log_Messages.Has_Error then if Verbose then Put_Line From e8bb7364839404bad831eefdde6b9ff31ad572ed Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 20 Oct 2022 14:28:16 +0000 Subject: [PATCH 0050/1483] SC_Obligations: avoid non-trivial copies for container elements Change-Id: I11c34debebc3e2e7d87ab4f3d4127c9c1a209e4c TN: VA20-036 --- tools/gnatcov/sc_obligations.adb | 38 ++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index ca0967354..f552ab752 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -1643,7 +1643,7 @@ package body SC_Obligations is if CU = No_CU_Id then return No_SCO_Id; else - return CU_Vector.Element (CU).First_SCO; + return CU_Vector.Constant_Reference (CU).First_SCO; end if; end First_SCO; @@ -1656,7 +1656,7 @@ package body SC_Obligations is if CU = No_CU_Id then return No_SCO_Id; else - return CU_Vector.Element (CU).Last_SCO; + return CU_Vector.Constant_Reference (CU).Last_SCO; end if; end Last_SCO; @@ -1678,7 +1678,7 @@ package body SC_Obligations is for J in First .. Last loop declare - BDDN : BDD_Node renames BDD_Vector.Element (J); + BDDN : BDD_Node renames BDD_Vector.Constant_Reference (J); begin if BDDN.Kind = Condition then Current_Condition_Index := Current_Condition_Index + 1; @@ -1969,7 +1969,7 @@ package body SC_Obligations is if BDDN.Parent = No_BDD_Node_Id then Prev_SCO := No_SCO_Id; else - Prev_SCO := BDD_Vector.Element (BDDN.Parent).C_SCO; + Prev_SCO := BDD_Vector.Constant_Reference (BDDN.Parent).C_SCO; Prev_Value := BDDN.Parent_Value; end if; end Get_Origin; @@ -2003,7 +2003,7 @@ package body SC_Obligations is .. TP.Current_Routine.Insns.Last + TP.Current_Routine.Offset); if CU /= No_CU_Id then - CUI := CU_Vector.Element (CU); + CUI := CU_Vector.Constant_Reference (CU); Has_Instances := CUI.First_Instance <= CUI.Last_Instance; else Has_Instances := False; @@ -2030,7 +2030,8 @@ package body SC_Obligations is (Global_Instance_Index <= CUI.Last_Instance); pragma Assert - (Inst_Vector.Element (Global_Instance_Index).Comp_Unit + (Inst_Vector.Constant_Reference + (Global_Instance_Index).Comp_Unit = TP.Current_Subp.Subprogram_CU); Tslocs (Last).Tag := Valid_SC_Tag (Global_Instance_Index); @@ -2279,7 +2280,6 @@ package body SC_Obligations is function Comp_Unit (SCO : SCO_Id) return CU_Id is LB, UB, Middle : Valid_CU_Id; - CU : CU_Info; begin -- Assume that compilation units in CU_Vector are ordered by SCO range -- to look up efficiently (by dichotomy) the compilation unit for the @@ -2289,14 +2289,17 @@ package body SC_Obligations is UB := CU_Vector.Last_Index; while LB <= UB loop Middle := LB + (UB - LB) / 2; - CU := CU_Vector.Element (Middle); - if SCO in CU.First_SCO .. CU.Last_SCO then - return Middle; - elsif SCO < CU.First_SCO then - UB := Middle - 1; - else - LB := Middle + 1; - end if; + declare + CU : CU_Info renames CU_Vector.Constant_Reference (Middle); + begin + if SCO in CU.First_SCO .. CU.Last_SCO then + return Middle; + elsif SCO < CU.First_SCO then + UB := Middle - 1; + else + LB := Middle + 1; + end if; + end; end loop; return No_CU_Id; end Comp_Unit; @@ -2336,7 +2339,7 @@ package body SC_Obligations is function Instance_Loc (Inst_Index : Inst_Id) return String is - II : Inst_Info renames Inst_Vector.Element (Inst_Index); + II : Inst_Info renames Inst_Vector.Constant_Reference (Inst_Index); begin return Image (II.Sloc) @@ -3880,7 +3883,8 @@ package body SC_Obligations is loop declare BDDN : constant BDD_Node := - BDD_Vector.Element (Next_BDD_Node (Cond_SCO, Cond_Value)); + BDD_Vector.Constant_Reference + (Next_BDD_Node (Cond_SCO, Cond_Value)); begin case BDDN.Kind is when Outcome => From d97b7e20df9cffd6dfdd673e0c2dc3926574e3ee Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 21 Oct 2022 14:31:41 +0200 Subject: [PATCH 0051/1483] Kill test featuring an expression function with GNAT 7.1.2 Their support is weak in GNAT 7.1.2 and we already had problems with expression function optimizations with this toolchain in the past. Change-Id: I1ef11f9cee68df0b9a38ae154588726b1d3eba5d TN: U709-021 --- .../Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.opt diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.opt new file mode 100644 index 000000000..bb690ece6 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/test.opt @@ -0,0 +1 @@ +7.1.2 DEAD support for expression functions weak in 7.1.2 From 346f7568431d722beed1d743dcad375ceedd3b46 Mon Sep 17 00:00:00 2001 From: Leo Creuse Date: Thu, 20 Oct 2022 15:53:28 +0200 Subject: [PATCH 0052/1483] Add configuration pragma loading in the instr. context creation Being able to check for configuration pragmas will be useful for V905-005 as well as U621-005. No behavior change expected. Change-Id: I8ffcd2cd697c2fa8cc12cfacf148d752a32bd266 --- tools/gnatcov/instrument-common.adb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 4695ba295..301cfe796 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -30,6 +30,7 @@ with GNAT.OS_Lib; with Langkit_Support.Symbols; with Langkit_Support.Text; with Libadalang.Common; +with Libadalang.Config_Pragmas; with Libadalang.Sources; with Coverage; @@ -381,6 +382,13 @@ package body Instrument.Common is (Unit_Provider => IC.Provider, Event_Handler => IC.Event_Handler); IC.Get_From_File_Count := 0; + + -- Load configuration pragmas + -- TODO??? Remove the type convertion when the LAL API change for + -- VA07-037 makes it into stable-libadalang. + + Libadalang.Config_Pragmas.Import_From_Project + (IC.Context, GNATCOLL.Projects.Project_Tree (Project.Project.all)); end Create_LAL_Context; -------------------- From 88d4539dbe09d55850baaca634c151be8dce467d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 30 Sep 2022 15:21:20 +0000 Subject: [PATCH 0053/1483] Instrument: rework the logistics around instrumented source files The current handling of instrumented source files has two related defficiencies in the presence of project extension: * some instrumented sources are created under the object directory of extended projects whereas they should always go to the ultimate extending project; * existing instrumented source files in the object directory of extended projects are not cleaned up, which may interfere with the build of instrumented extending projects. This commit fixes both issues: object directories cleanup code is reworked so that it handles multiple projects using the same object directory (now iterating on all projects, extended ones included), and instrumented sources are now created in under the correct project's object directory. TN: V930-029 Change-Id: I705e9f4ffb74887ea5884a5740c225f6f6fae03c --- tools/gnatcov/instrument-clean_objdirs.adb | 100 +++++++++------------ tools/gnatcov/instrument-common.adb | 15 +++- tools/gnatcov/instrument-common.ads | 4 +- tools/gnatcov/project.adb | 21 +++-- tools/gnatcov/project.ads | 11 ++- 5 files changed, 80 insertions(+), 71 deletions(-) diff --git a/tools/gnatcov/instrument-clean_objdirs.adb b/tools/gnatcov/instrument-clean_objdirs.adb index d141fe967..1d7c0e307 100644 --- a/tools/gnatcov/instrument-clean_objdirs.adb +++ b/tools/gnatcov/instrument-clean_objdirs.adb @@ -27,73 +27,47 @@ with Project; procedure Instrument.Clean_Objdirs (IC : Inst_Context) is use Project_Info_Maps; + All_Instr_Files : File_Sets.Set; + -- Set of full names for all files that were written to output directories + -- for all instrumented projects. + procedure Clean_Subdir (Project : Project_Type); -- Callback for Project.Iterate_Projects. If Project is not externally -- built, remove all files from the "$project_name-gnatcov-instr" folder in -- Project's object directory that we did not just instrument. - procedure Remove_Files - (Output_Dir : String; Preserved_Files : File_Sets.Set); - -- Remove all files in Output_Dir which are not present in - -- Preserved_Files. - ------------------ -- Clean_Subdir -- ------------------ procedure Clean_Subdir (Project : Project_Type) is - begin - -- Leave externally built projects out of the picture - - if Project.Externally_Built then - return; - end if; + Output_Dir : constant String := Project_Output_Dir (Project); - -- Plan to clean this project's output directory + -- Removing items in a directory and iterate on these items at the same + -- time is not supported: first collect all files to remove (iteration) + -- and then remove them. - declare - Output_Dir : constant String := Project_Output_Dir (Project); - - -- Lookup instrumentation information about this project - - Name : constant Unbounded_String := - To_Unbounded_String (Project.Name); - Cur : constant Cursor := IC.Project_Info_Map.Find (Name); - begin - if Has_Element (Cur) then - - -- We just instrumented sources for this project: preserve the - -- generated source files (i.e. remove only obsolete instrumented - -- sources). - - Remove_Files (Output_Dir, Element (Cur).Instr_Files); - else - Remove_Files (Output_Dir, File_Sets.Empty_Set); - end if; - end; - end Clean_Subdir; + To_Delete : File_Sets.Set; + Search : Search_Type; + Dir_Entry : Directory_Entry_Type; + begin + if + -- Leave externally built projects out of the picture - ------------------ - -- Remove_Files -- - ------------------ + Project.Externally_Built - procedure Remove_Files - (Output_Dir : String; Preserved_Files : File_Sets.Set) - is - To_Delete : File_Sets.Set; - Search : Search_Type; - Dir_Entry : Directory_Entry_Type; - begin - -- Some projects don't have an object directory: ignore them as there - -- is nothing to do. + -- Some projects don't have an object directory: ignore them as there + -- is nothing to do. - if Output_Dir'Length = 0 + or else Output_Dir'Length = 0 or else not Exists (Output_Dir) or else Kind (Output_Dir) /= Directory then return; end if; + -- Collect the files to delete + Start_Search (Search, Directory => Output_Dir, @@ -102,27 +76,41 @@ procedure Instrument.Clean_Objdirs (IC : Inst_Context) is while More_Entries (Search) loop Get_Next_Entry (Search, Dir_Entry); declare - Name : constant String := Simple_Name (Dir_Entry); - UB_Name : constant Unbounded_String := - To_Unbounded_String (Name); + Name : constant String := Simple_Name (Dir_Entry); + Full_Name : constant Unbounded_String := + To_Unbounded_String (Output_Dir / Name); begin - if not Preserved_Files.Contains (UB_Name) then - To_Delete.Insert (UB_Name); + if not All_Instr_Files.Contains (Full_Name) then + To_Delete.Insert (Full_Name); end if; end; end loop; End_Search (Search); + -- Do the deletion + for Name of To_Delete loop - Delete_File (Output_Dir / To_String (Name)); + Delete_File (To_String (Name)); end loop; - end Remove_Files; + end Clean_Subdir; -- Start of processing for Instrument.Clean_Objdirs begin + -- First initialize All_Instr_Files + + for Cur in IC.Project_Info_Map.Iterate loop + All_Instr_Files.Union (Element (Cur).Instr_Files); + end loop; + + -- Then go through all projects to clear up their object directories, + -- ignoring files in All_Instr_Files. Also go through extended projects, as + -- their object directories can interfere with the build of the extending + -- project. + Project.Iterate_Projects - (Root_Project => Project.Project.Root_Project, - Process => Clean_Subdir'Access, - Recursive => True); + (Root_Project => Project.Project.Root_Project, + Process => Clean_Subdir'Access, + Recursive => True, + Include_Extended => True); end Instrument.Clean_Objdirs; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 301cfe796..1a5e97f5f 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -210,7 +210,7 @@ package body Instrument.Common is Self.Unit := Unit; Self.Handle := Start_Rewriting (IC.Context); - Info.Instr_Files.Insert (To_Unbounded_String (Base_Filename)); + Info.Instr_Files.Insert (To_Unbounded_String (Output_Filename)); end Start_Rewriting; -------------------- @@ -530,10 +530,19 @@ package body Instrument.Common is -- register it and return it. declare + Storage_Project : constant Project_Type := + Project.Extending_Project (Recurse => True); + -- Actual project that will host instrumented sources: even when + -- we instrument an extended project, the resulting instrumented + -- sources must go to the ultimate extending project's object + -- directory. This is similar to the object directory that hosts + -- object files when GPRbuild processes a project that is + -- extended. + Result : constant Project_Info_Access := new Project_Info' (Project => Project, Externally_Built => Project.Externally_Built, - Output_Dir => +Project_Output_Dir (Project), + Output_Dir => +Project_Output_Dir (Storage_Project), Instr_Files => <>); begin Context.Project_Info_Map.Insert (Project_Name, Result); @@ -663,7 +672,7 @@ package body Instrument.Common is Output_Filename : constant String := To_String (Info.Output_Dir) / Base_Filename; begin - Info.Instr_Files.Insert (To_Unbounded_String (Base_Filename)); + Info.Instr_Files.Insert (To_Unbounded_String (Output_Filename)); return Output_Filename; end Register_New_File; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 6f3eb9dcb..7969d4079 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -169,7 +169,9 @@ package Instrument.Common is -- for this project must land in it. Instr_Files : aliased File_Sets.Set; - -- Set of files that were written to Output_Dir + -- Set of full names for files that were written to Output_Dir for this + -- project. Note that in the case of project extension, more than one + -- project may use the same output directory. end record; type Project_Info_Access is access all Project_Info; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 13c026ada..2f7e717d3 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -309,14 +309,16 @@ package body Project is ---------------------- procedure Iterate_Projects - (Root_Project : Project_Type; - Process : access procedure (Prj : Project_Type); - Recursive : Boolean) + (Root_Project : GNATCOLL.Projects.Project_Type; + Process : access procedure + (Prj : GNATCOLL.Projects.Project_Type); + Recursive : Boolean; + Include_Extended : Boolean := False) is Iter : Project_Iterator := Start (Root_Project => Root_Project, Recursive => Recursive, - Include_Extended => False); + Include_Extended => Include_Extended); Visited_Projects : Project_Sets.Set; Project : Project_Type; begin @@ -324,11 +326,14 @@ package body Project is Project := Current (Iter); exit when Project = No_Project; - -- Go to the ultimate extending project: this is the "reference" - -- project for chains of project extension (we care about the - -- Coverage package of extending projects, their object dirs, etc.). + -- If requested, go to the ultimate extending project: this is the + -- "reference" project for chains of project extension (we care about + -- the Coverage package of extending projects, their object dirs, + -- etc.). - Project := Extending_Project (Project, Recurse => True); + if not Include_Extended then + Project := Extending_Project (Project, Recurse => True); + end if; declare Name : constant String := Project.Name; diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index a7e692ab7..3460742b7 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -226,11 +226,16 @@ package Project is with Pre => Is_Project_Loaded; procedure Iterate_Projects - (Root_Project : GNATCOLL.Projects.Project_Type; - Process : access procedure (Prj : GNATCOLL.Projects.Project_Type); - Recursive : Boolean) + (Root_Project : GNATCOLL.Projects.Project_Type; + Process : access procedure + (Prj : GNATCOLL.Projects.Project_Type); + Recursive : Boolean; + Include_Extended : Boolean := False) with Pre => Is_Project_Loaded; -- Call Process on Root_Project if Recursive is False, or on the whole -- project tree otherwise. + -- + -- Unless Include_Extended is True, only process ultimate extending + -- projects. end Project; From b6ef9a83210185737b2396e3a5dc38854fd64b41 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 21 Oct 2022 10:36:21 +0200 Subject: [PATCH 0054/1483] Instrumentation: remove dominance SCOs We do not need the dominance information when doing source traces coverage analysis as instrumented code can't be optimized away. As this is adding maintenance burden, and as it is also partially implemented, remove the dominance computation both from the Ada and C/C++ instrumentation. TN: VA21-006 Change-Id: Iadc7fb798220c6eeb336ef37c5cc24947c97e749 --- tools/gnatcov/instrument-ada_unit.adb | 335 +++++--------------------- tools/gnatcov/instrument-c.adb | 136 ++--------- 2 files changed, 80 insertions(+), 391 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 193692527..bf4a640bb 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -2356,42 +2356,17 @@ package body Instrument.Ada_Unit is -- Traverse_Declarations_Or_Statements -- ----------------------------------------- - type Dominant_Info is record - K : Character; - -- F/T/S/E for a valid dominance marker, or ' ' for no dominant - - N : Ada_Node; - -- Node providing the Sloc(s) for the dominance marker - end record; - No_Dominant : constant Dominant_Info := (' ', No_Ada_Node); - procedure Traverse_Declarations_Or_Statements (IC : in out Inst_Context; UIC : in out Ada_Unit_Inst_Context; L : Ada_List'Class; Preelab : Boolean := False; - D : Dominant_Info := No_Dominant; - P : Ada_Node := No_Ada_Node; - Is_Select_Stmt_Alternative : Boolean := False); - -- 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. Preelab - -- is True if L is a list of preelaborable declarations (which do not - -- allow elaboration code, so do not require any SCOs, and wouldn't allow - -- insertion of witnesses). - - function Traverse_Declarations_Or_Statements - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; - L : Ada_List'Class; - Preelab : Boolean := False; - D : Dominant_Info := No_Dominant; P : Ada_Node := No_Ada_Node; Is_Select_Stmt_Alternative : Boolean := False; Priv_Part : Private_Part := No_Private_Part) - return Dominant_Info with Post => UIC.Current_Insertion_Info = UIC'Old.Current_Insertion_Info; - -- 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. + -- Process L, a list of statements or declarations. If P is present, it is + -- processed as though it had been prepended to L. -- -- Preelab is True if L is a list of preelaborable declarations (which do -- not allow elaboration code, so do not require any SCOs, and wouldn't @@ -2404,16 +2379,11 @@ package body Instrument.Ada_Unit is -- If L is the list of declarations for a public part, Priv_Part is the -- corresponding private part (if any). -- - -- Returns dominant information corresponding to the last node with SCO in - -- L. - -- -- The postcondition ensures that the Current_Insertion_Info has been -- correctly reset to its value upon entry. -- The following Traverse_* routines perform appropriate calls to -- Traverse_Declarations_Or_Statements to traverse specific node kinds. - -- Parameter D, when present, indicates the dominant of the first - -- declaration or statement within N. procedure Traverse_Context_Clause (UIC : in out Ada_Unit_Inst_Context; @@ -2433,8 +2403,7 @@ package body Instrument.Ada_Unit is procedure Traverse_Handled_Statement_Sequence (IC : in out Inst_Context; UIC : in out Ada_Unit_Inst_Context; - N : Handled_Stmts; - D : Dominant_Info := No_Dominant); + N : Handled_Stmts); procedure Traverse_Package_Body (IC : in out Inst_Context; @@ -2446,14 +2415,12 @@ package body Instrument.Ada_Unit is (IC : in out Inst_Context; UIC : in out Ada_Unit_Inst_Context; N : Base_Package_Decl; - Preelab : Boolean; - D : Dominant_Info := No_Dominant); + Preelab : Boolean); procedure Traverse_Subprogram_Or_Task_Body (IC : in out Inst_Context; UIC : in out Ada_Unit_Inst_Context; - N : Ada_Node; - D : Dominant_Info := No_Dominant); + N : Ada_Node); procedure Traverse_Sync_Definition (IC : in out Inst_Context; @@ -2621,33 +2588,10 @@ package body Instrument.Ada_Unit is UIC : in out Ada_Unit_Inst_Context; L : Ada_List'Class; Preelab : Boolean := False; - D : Dominant_Info := No_Dominant; - P : Ada_Node := No_Ada_Node; - Is_Select_Stmt_Alternative : Boolean := False) - is - Discard_Dom : Dominant_Info; - pragma Warnings (Off, Discard_Dom); - begin - Discard_Dom := Traverse_Declarations_Or_Statements - (IC, UIC, L, Preelab, D, P, Is_Select_Stmt_Alternative); - end Traverse_Declarations_Or_Statements; - - function Traverse_Declarations_Or_Statements - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; - L : Ada_List'Class; - Preelab : Boolean := False; - D : Dominant_Info := No_Dominant; P : Ada_Node := No_Ada_Node; Is_Select_Stmt_Alternative : Boolean := False; Priv_Part : Private_Part := No_Private_Part) - return Dominant_Info is - Current_Dominant : Dominant_Info := D; - -- Dominance information for the current basic block - - Current_Test : Ada_Node; - -- Conditional node (IF statement or ELSIF part) being processed SC_First : constant Nat := SC.Last + 1; SD_First : constant Nat := SD.Last + 1; @@ -3147,30 +3091,6 @@ package body Instrument.Ada_Unit is -- Output statement entries from saved entries in SC table for J in SC_First .. SC_Last loop - -- If there is a pending dominant for this statement sequence, - -- emit a SCO for it. - - if J = SC_First and then Current_Dominant /= No_Dominant then - declare - SR : constant Source_Location_Range := - Current_Dominant.N.Sloc_Range; - From : constant Source_Location := Start_Sloc (SR); - To : Source_Location := Inclusive_End_Sloc (SR); - - begin - if Current_Dominant.K /= 'E' then - To := No_Source_Location; - end if; - - Append_SCO - (C1 => '>', - C2 => Current_Dominant.K, - From => +From, - To => +To, - Last => False); - end; - end if; - declare SCE : SC_Entry renames SC.Table (J); Dummy_Ctx : constant Context_Handle := @@ -3228,13 +3148,6 @@ package body Instrument.Ada_Unit is end; end loop; - -- Last statement of basic block, if present, becomes new current - -- dominant. - - if SC_Last >= SC_First then - Current_Dominant := ('S', SC.Table (SC_Last).N); - end if; - -- Clear out used section of SC table SC.Set_Last (SC_First - 1); @@ -3389,11 +3302,7 @@ package body Instrument.Ada_Unit is F_Stmts => Stmts_RH, F_End_Name => Proc_Name)); - -- We are exiting the newly created regular function, so reset - -- dominant information. - Set_Statement_Entry; - Current_Dominant := No_Dominant; UIC.Current_Insertion_Info := Saved_Insertion_Info; UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; @@ -3440,9 +3349,6 @@ package body Instrument.Ada_Unit is -- Local contexts for statement and MC/DC instrumentation -- ------------------------------------------------------------ - Saved_Dominant : constant Dominant_Info := Current_Dominant; - -- Save last statement in current sequence as dominant - New_Insertion_Info : aliased Insertion_Info; -- Witness insertion info for statements (for both null procedures -- and expression functions). @@ -3643,10 +3549,8 @@ package body Instrument.Ada_Unit is UIC.MCDC_State_Inserter := EF_Inserter'Unchecked_Access; -- Output statement SCO for degenerate subprogram body (null - -- statement or freestanding expression) outside of the dominance - -- chain. + -- statement or freestanding expression). - Current_Dominant := No_Dominant; if Is_Expr_Function then declare N_Expr : constant Expr := N.As_Expr_Function.F_Expr; @@ -3677,12 +3581,6 @@ package body Instrument.Ada_Unit is end if; Set_Statement_Entry; - -- Restore current dominant information designating last statement - -- in previous sequence (i.e. make the dominance chain skip over - -- the degenerate body). - - Current_Dominant := Saved_Dominant; - -- Restore saved insertion context UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; @@ -4017,7 +3915,7 @@ package body Instrument.Ada_Unit is when Ada_Package_Decl => Set_Statement_Entry; Traverse_Package_Declaration - (IC, UIC, N.As_Base_Package_Decl, Preelab, Current_Dominant); + (IC, UIC, N.As_Base_Package_Decl, Preelab); -- Generic package declaration @@ -4083,23 +3981,15 @@ package body Instrument.Ada_Unit is declare Cond : constant Expr := As_Entry_Body (N).F_Barrier; - Inner_Dominant : Dominant_Info := No_Dominant; - begin Set_Statement_Entry; if Switches.Analyze_Entry_Barriers and then not Cond.Is_Null 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. - - Inner_Dominant := ('T', N); end if; - Traverse_Subprogram_Or_Task_Body - (IC, UIC, N, Inner_Dominant); + Traverse_Subprogram_Or_Task_Body (IC, UIC, N); end; -- Protected body @@ -4121,15 +4011,6 @@ package body Instrument.Ada_Unit is begin Process_Decisions_Defer (Cond, 'E'); Set_Statement_Entry; - - -- If condition is present, then following statement is - -- only executed if the condition evaluates to False. - - if not Cond.Is_Null then - Current_Dominant := ('F', N); - else - Current_Dominant := No_Dominant; - end if; end; -- Label, which breaks the current statement sequence, but the @@ -4138,7 +4019,6 @@ package body Instrument.Ada_Unit is when Ada_Label => Set_Statement_Entry; - Current_Dominant := No_Dominant; -- Block statement, which breaks the current statement sequence @@ -4146,13 +4026,8 @@ package body Instrument.Ada_Unit is Set_Statement_Entry; if N.Kind = Ada_Decl_Block then - -- The first statement in the handled sequence of statements - -- is dominated by the elaboration of the last declaration. - - Current_Dominant := Traverse_Declarations_Or_Statements - (IC, UIC, - L => As_Decl_Block (N).F_Decls.F_Decls, - D => Current_Dominant); + Traverse_Declarations_Or_Statements + (IC, UIC, L => As_Decl_Block (N).F_Decls.F_Decls); end if; Traverse_Handled_Statement_Sequence @@ -4160,14 +4035,12 @@ package body Instrument.Ada_Unit is N => (case N.Kind is when Ada_Decl_Block => As_Decl_Block (N).F_Stmts, when Ada_Begin_Block => As_Begin_Block (N).F_Stmts, - when others => raise Program_Error), - D => Current_Dominant); + when others => raise Program_Error)); -- If statement, which breaks the current statement sequence, -- but we include the condition in the current sequence. when Ada_If_Stmt => - Current_Test := N; Extend_Statement_Sequence (UIC, N, 'I'); declare @@ -4181,65 +4054,40 @@ package body Instrument.Ada_Unit is Traverse_Declarations_Or_Statements (IC, UIC, - L => If_N.F_Then_Stmts.As_Ada_Node_List, - D => ('T', N)); + L => If_N.F_Then_Stmts.As_Ada_Node_List); -- Loop through ELSIF parts if present - declare - Saved_Dominant : constant Dominant_Info := - Current_Dominant; - - begin - for J in 1 .. If_N.F_Alternatives.Children_Count loop - declare - Elif : constant Elsif_Stmt_Part := - Alt.Child (J).As_Elsif_Stmt_Part; - begin - - -- An Elsif is executed only if the previous test - -- got a FALSE outcome. - - Current_Dominant := ('F', Current_Test); - - -- Now update current test information - - Current_Test := Ada_Node (Elif); - - -- We generate a statement sequence for the - -- construct "ELSIF condition", so that we have - -- a statement for the resulting decisions. - - Extend_Statement_Sequence - (UIC, - Ada_Node (Elif), 'I', - Insertion_N => Handle (Elif.F_Cond_Expr), - Instrument_Location => Inside_Expr); - Process_Decisions_Defer (Elif.F_Cond_Expr, 'I'); - Set_Statement_Entry; - - -- An ELSIF part is never guaranteed to have - -- been executed, following statements are only - -- dominated by the initial IF statement. + for J in 1 .. If_N.F_Alternatives.Children_Count loop + declare + Elif : constant Elsif_Stmt_Part := + Alt.Child (J).As_Elsif_Stmt_Part; + begin + -- We generate a statement sequence for the construct + -- "ELSIF condition", so that we have a statement for + -- the resulting decisions. - Current_Dominant := Saved_Dominant; + Extend_Statement_Sequence + (UIC, + Ada_Node (Elif), 'I', + Insertion_N => Handle (Elif.F_Cond_Expr), + Instrument_Location => Inside_Expr); + Process_Decisions_Defer (Elif.F_Cond_Expr, 'I'); + Set_Statement_Entry; - -- Traverse the statements in the ELSIF + -- Traverse the statements in the ELSIF - Traverse_Declarations_Or_Statements - (IC, UIC, - L => Elif.F_Stmts.As_Ada_Node_List, - D => ('T', Ada_Node (Elif))); - end; - end loop; - end; + Traverse_Declarations_Or_Statements + (IC, UIC, + L => Elif.F_Stmts.As_Ada_Node_List); + end; + end loop; -- Finally traverse the ELSE statements if present Traverse_Declarations_Or_Statements (IC, UIC, - L => If_N.F_Else_Stmts.As_Ada_Node_List, - D => ('F', Current_Test)); + L => If_N.F_Else_Stmts.As_Ada_Node_List); end; -- CASE statement, which breaks the current statement sequence, @@ -4255,8 +4103,7 @@ package body Instrument.Ada_Unit is Process_Decisions_Defer (Case_N.F_Expr, 'X'); Set_Statement_Entry; - -- Process case branches, all of which are dominated by the - -- CASE statement. + -- Process case branches for J in 1 .. Alt_L.Children_Count loop declare @@ -4265,8 +4112,7 @@ package body Instrument.Ada_Unit is begin Traverse_Declarations_Or_Statements (IC, UIC, - L => Alt.F_Stmts.As_Ada_Node_List, - D => Current_Dominant); + L => Alt.F_Stmts.As_Ada_Node_List); end; end loop; end; @@ -4278,13 +4124,11 @@ package body Instrument.Ada_Unit is Set_Statement_Entry; if N.Kind = Ada_Accept_Stmt_With_Stmts then - -- Process sequence of statements, dominant is the ACCEPT - -- statement. + -- Process sequence of statements Traverse_Handled_Statement_Sequence (IC, UIC, - N => N.As_Accept_Stmt_With_Stmts.F_Stmts, - D => Current_Dominant); + N => N.As_Accept_Stmt_With_Stmts.F_Stmts); end if; -- SELECT statement @@ -4297,7 +4141,6 @@ package body Instrument.Ada_Unit is declare Sel_N : constant Select_Stmt := As_Select_Stmt (N); - S_Dom : Dominant_Info; begin for J in 1 .. Sel_N.F_Guards.Children_Count loop declare @@ -4305,24 +4148,19 @@ package body Instrument.Ada_Unit is Sel_N.F_Guards.Child (J).As_Select_When_Part; Guard : Expr; begin - S_Dom := Current_Dominant; Guard := Alt.F_Cond_Expr; if not Guard.Is_Null then Process_Decisions (UIC, Guard, 'G'); - Current_Dominant := ('T', Ada_Node (Guard)); end if; - -- Travrse the select_alternative, + -- Traverse the select_alternative, -- entry_call_alternative, or triggering_alternative. Traverse_Declarations_Or_Statements (IC, UIC, L => Alt.F_Stmts.As_Ada_Node_List, - D => Current_Dominant, Is_Select_Stmt_Alternative => True); - - Current_Dominant := S_Dom; end; end loop; @@ -4331,12 +4169,10 @@ package body Instrument.Ada_Unit is Traverse_Declarations_Or_Statements (IC, UIC, - L => Sel_N.F_Else_Stmts.As_Ada_Node_List, - D => Current_Dominant); + L => Sel_N.F_Else_Stmts.As_Ada_Node_List); Traverse_Declarations_Or_Statements (IC, UIC, - L => Sel_N.F_Abort_Stmts.As_Ada_Node_List, - D => Current_Dominant); + L => Sel_N.F_Abort_Stmts.As_Ada_Node_List); end; -- There is no SCO for a TERMINATE alternative in instrumentation @@ -4356,7 +4192,6 @@ package body Instrument.Ada_Unit is => Extend_Statement_Sequence (UIC, N, ' '); Set_Statement_Entry; - Current_Dominant := No_Dominant; -- Simple return statement. which is an exit point, but we -- have to process the return expression for decisions. @@ -4366,7 +4201,6 @@ package body Instrument.Ada_Unit is Process_Decisions_Defer (N.As_Return_Stmt.F_Return_Expr, 'X'); Set_Statement_Entry; - Current_Dominant := No_Dominant; -- Extended return statement @@ -4381,10 +4215,8 @@ package body Instrument.Ada_Unit is Traverse_Handled_Statement_Sequence (IC, UIC, - N => ER_N.F_Stmts, - D => Current_Dominant); + N => ER_N.F_Stmts); end; - Current_Dominant := No_Dominant; -- Loop ends the current statement sequence, but we include -- the iteration scheme if present in the current sequence. @@ -4393,10 +4225,8 @@ package body Instrument.Ada_Unit is when Ada_Base_Loop_Stmt => declare - Loop_S : constant Base_Loop_Stmt := - N.As_Base_Loop_Stmt; - ISC : constant Loop_Spec := Loop_S.F_Spec; - Inner_Dominant : Dominant_Info := No_Dominant; + Loop_S : constant Base_Loop_Stmt := N.As_Base_Loop_Stmt; + ISC : constant Loop_Spec := Loop_S.F_Spec; begin if not ISC.Is_Null then @@ -4412,12 +4242,6 @@ package body Instrument.Ada_Unit is Process_Decisions_Defer (ISC.As_While_Loop_Spec.F_Expr, 'W'); - -- Set more specific dominant for inner statements - -- (the control sloc for the decision is that of - -- the WHILE token). - - Inner_Dominant := ('T', Ada_Node (ISC)); - -- FOR loop else @@ -4438,14 +4262,9 @@ package body Instrument.Ada_Unit is Set_Statement_Entry; - if Inner_Dominant = No_Dominant then - Inner_Dominant := Current_Dominant; - end if; - Traverse_Declarations_Or_Statements (IC, UIC, - L => Loop_S.F_Stmts.As_Ada_Node_List, - D => Inner_Dominant); + L => Loop_S.F_Stmts.As_Ada_Node_List); end; -- Pragma @@ -4783,7 +4602,6 @@ package body Instrument.Ada_Unit is -- Pop insertion info UIC.Current_Insertion_Info := Saved_Insertion_Info; - return Current_Dominant; end Traverse_Declarations_Or_Statements; ----------------------------- @@ -4896,8 +4714,7 @@ package body Instrument.Ada_Unit is procedure Traverse_Handled_Statement_Sequence (IC : in out Inst_Context; UIC : in out Ada_Unit_Inst_Context; - N : Handled_Stmts; - D : Dominant_Info := No_Dominant) + N : Handled_Stmts) is begin if N.Is_Null then @@ -4905,7 +4722,7 @@ package body Instrument.Ada_Unit is end if; Traverse_Declarations_Or_Statements - (IC, UIC, L => N.F_Stmts.As_Ada_Node_List, D => D); + (IC, UIC, L => N.F_Stmts.As_Ada_Node_List); for J in 1 .. N.F_Exceptions.Children_Count loop declare @@ -4916,8 +4733,7 @@ package body Instrument.Ada_Unit is if Handler.Kind = Ada_Exception_Handler then Traverse_Declarations_Or_Statements (IC, UIC, - L => Handler.As_Exception_Handler.F_Stmts.As_Ada_Node_List, - D => ('E', Handler)); + L => Handler.As_Exception_Handler.F_Stmts.As_Ada_Node_List); end if; end; end loop; @@ -4945,14 +4761,9 @@ package body Instrument.Ada_Unit is Sloc => Sloc (N)); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; - -- The first statement in the handled sequence of statements is - -- dominated by the elaboration of the last declaration. - - Traverse_Handled_Statement_Sequence - (IC, UIC, - N => N.F_Stmts, - D => Traverse_Declarations_Or_Statements - (IC, UIC, N.F_Decls.F_Decls, Preelab)); + Traverse_Declarations_Or_Statements + (IC, UIC, N.F_Decls.F_Decls, Preelab); + Traverse_Handled_Statement_Sequence (IC, UIC, N => N.F_Stmts); UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; Exit_Scope (UIC); @@ -4967,11 +4778,8 @@ package body Instrument.Ada_Unit is (IC : in out Inst_Context; UIC : in out Ada_Unit_Inst_Context; N : Base_Package_Decl; - Preelab : Boolean; - D : Dominant_Info := No_Dominant) + Preelab : Boolean) is - Private_Part_Dominant : Dominant_Info; - Saved_MCDC_State_Inserter : constant Any_MCDC_State_Inserter := UIC.MCDC_State_Inserter; Local_Inserter : aliased Default_MCDC_State_Inserter := @@ -4984,20 +4792,15 @@ package body Instrument.Ada_Unit is Sloc => Sloc (N)); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; - Private_Part_Dominant := - Traverse_Declarations_Or_Statements - (IC, UIC, N.F_Public_Part.F_Decls, Preelab, D, - Priv_Part => N.F_Private_Part); + Traverse_Declarations_Or_Statements + (IC, UIC, N.F_Public_Part.F_Decls, Preelab, + Priv_Part => N.F_Private_Part); if not N.F_Private_Part.Is_Null then - - -- First private declaration is dominated by last visible declaration - Traverse_Declarations_Or_Statements (IC, UIC, L => N.F_Private_Part.F_Decls, - Preelab => Preelab, - D => Private_Part_Dominant); + Preelab => Preelab); end if; UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; Exit_Scope (UIC); @@ -5013,10 +4816,6 @@ package body Instrument.Ada_Unit is UIC : in out Ada_Unit_Inst_Context; N : Ada_Node) is - Dom_Info : Dominant_Info := ('S', N); - -- The first declaration is dominated by the protected or task [type] - -- declaration. - Vis_Decl : Public_Part := No_Public_Part; Priv_Decl : Private_Part := No_Private_Part; -- Visible and private declarations of the protected or task definition @@ -5071,17 +4870,13 @@ package body Instrument.Ada_Unit is -- declarations. Querying F_Decls is invalid in this case. if not Vis_Decl.Is_Null then - Dom_Info := Traverse_Declarations_Or_Statements - (IC, UIC, L => Vis_Decl.F_Decls, D => Dom_Info, - Priv_Part => Priv_Decl); + Traverse_Declarations_Or_Statements + (IC, UIC, L => Vis_Decl.F_Decls, Priv_Part => Priv_Decl); end if; if not Priv_Decl.Is_Null then - -- If visible declarations are present, the first private declaration - -- is dominated by the last visible declaration. - Traverse_Declarations_Or_Statements - (IC, UIC, L => Priv_Decl.F_Decls, D => Dom_Info); + (IC, UIC, L => Priv_Decl.F_Decls); end if; end Traverse_Sync_Definition; @@ -5092,12 +4887,10 @@ package body Instrument.Ada_Unit is procedure Traverse_Subprogram_Or_Task_Body (IC : in out Inst_Context; UIC : in out Ada_Unit_Inst_Context; - N : Ada_Node; - D : Dominant_Info := No_Dominant) + N : Ada_Node) is Decls : Declarative_Part; HSS : Handled_Stmts; - Dom_Info : Dominant_Info := D; Saved_MCDC_State_Inserter : constant Any_MCDC_State_Inserter := UIC.MCDC_State_Inserter; @@ -5145,13 +4938,9 @@ package body Instrument.Ada_Unit is Local_Inserter.Local_Decls := Handle (Decls.F_Decls); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; - -- If declarations are present, the first statement is dominated by the - -- last declaration. - - Dom_Info := Traverse_Declarations_Or_Statements - (IC, UIC, L => Decls.F_Decls, D => Dom_Info); + Traverse_Declarations_Or_Statements (IC, UIC, L => Decls.F_Decls); - Traverse_Handled_Statement_Sequence (IC, UIC, N => HSS, D => Dom_Info); + Traverse_Handled_Statement_Sequence (IC, UIC, N => HSS); Exit_Scope (UIC); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 09d5a9627..4507a8821 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -605,9 +605,9 @@ package body Instrument.C is Append_SCO (C1, C2, From, To, Last, Pragma_Aspect_Name); -- We add preprocessing information only for actual SCOs. Return there - -- if this is an operator SCO or a dominance SCO. + -- if this is an operator SCO. - if C1 in '>' | '!' | '&' | '|' then + if C1 in '!' | '&' | '|' then return; end if; @@ -1208,29 +1208,11 @@ package body Instrument.C is -- Traverse_Statements -- ------------------------- - type Dominant_Info is record - K : Character; - -- F/T/S/E for a valid dominance marker, or ' ' for no dominant - - N : Cursor_T; - -- Node providing the Sloc(s) for the dominance marker - end record; - No_Dominant : constant Dominant_Info := (' ', Get_Null_Cursor); - procedure Traverse_Statements (IC : in out Inst_Context; UIC : in out C_Unit_Inst_Context; - L : Cursor_Vectors.Vector; - D : Dominant_Info := No_Dominant); - -- Process L, a list of statements or declarations dominated by D - - function Traverse_Statements - (IC : in out Inst_Context; - UIC : in out C_Unit_Inst_Context; - L : Cursor_Vectors.Vector; - D : Dominant_Info := No_Dominant) return Dominant_Info; - -- Process L, a list of statements or declarations dominated by D. Returns - -- dominant information corresponding to the last node with SCO in L. + L : Cursor_Vectors.Vector); + -- Process L, a list of statements or declarations procedure Traverse_Declarations (IC : in out Inst_Context; @@ -1732,23 +1714,8 @@ package body Instrument.C is procedure Traverse_Statements (IC : in out Inst_Context; UIC : in out C_Unit_Inst_Context; - L : Cursor_Vectors.Vector; - D : Dominant_Info := No_Dominant) - is - Discard_Dom : constant Dominant_Info := - Traverse_Statements (IC, UIC, L, D); - begin - null; - end Traverse_Statements; - - function Traverse_Statements - (IC : in out Inst_Context; - UIC : in out C_Unit_Inst_Context; - L : Cursor_Vectors.Vector; - D : Dominant_Info := No_Dominant) return Dominant_Info + L : Cursor_Vectors.Vector) is - Current_Dominant : Dominant_Info := D; - SC_First : constant Nat := SC.Last + 1; SD_First : constant Nat := SD.Last + 1; @@ -1786,16 +1753,12 @@ package body Instrument.C is when Cursor_Label_Ref => Set_Statement_Entry; - Current_Dominant := No_Dominant; -- Compound statement, which breaks the current statement sequence when Cursor_Compound_Stmt => Set_Statement_Entry; - Traverse_Statements - (IC, UIC, - L => Get_Children (N), - D => Current_Dominant); + Traverse_Statements (IC, UIC, L => Get_Children (N)); -- If statement, which breaks the current statement sequence, but -- we include the condition in the current sequence. @@ -1816,8 +1779,7 @@ package body Instrument.C is Rew => UIC.Rewriter); Traverse_Statements (IC, UIC, - L => To_Vector (Then_Part), - D => ('S', N)); + L => To_Vector (Then_Part)); -- Traverse the ELSE statements if present @@ -1826,8 +1788,7 @@ package body Instrument.C is Rew => UIC.Rewriter); Traverse_Statements (IC, UIC, - L => To_Vector (Else_Part), - D => ('S', N)); + L => To_Vector (Else_Part)); end if; end; @@ -1843,13 +1804,9 @@ package body Instrument.C is Process_Decisions_Defer (Switch_Cond, 'X'); Set_Statement_Entry; - -- Process case branches, all of which are dominated by the - -- Switch statement. + -- Process case branches - Traverse_Statements - (IC, UIC, - L => To_Vector (Alt), - D => Current_Dominant); + Traverse_Statements (IC, UIC, L => To_Vector (Alt)); end; -- Case alternative @@ -1858,10 +1815,7 @@ package body Instrument.C is declare Case_Body : constant Cursor_T := Get_Sub_Stmt (N); begin - Traverse_Statements - (IC, UIC, - L => To_Vector (Case_Body), - D => Current_Dominant); + Traverse_Statements (IC, UIC, L => To_Vector (Case_Body)); end; -- Loop ends the current statement sequence, but we include @@ -1871,10 +1825,9 @@ package body Instrument.C is when Cursor_While_Stmt => declare - While_Body : constant Cursor_T := Get_Body (N); - Cond_Var : constant Cursor_T := Get_Cond_Var (N); - Cond : constant Cursor_T := Get_Cond (N); - Inner_Dominant : constant Dominant_Info := ('S', N); + While_Body : constant Cursor_T := Get_Body (N); + Cond_Var : constant Cursor_T := Get_Cond_Var (N); + Cond : constant Cursor_T := Get_Cond (N); begin UIC.Pass.Curlify (N => While_Body, @@ -1892,8 +1845,7 @@ package body Instrument.C is Process_Decisions_Defer (Cond, 'W'); Set_Statement_Entry; - Traverse_Statements - (IC, UIC, To_Vector (While_Body), Inner_Dominant); + Traverse_Statements (IC, UIC, To_Vector (While_Body)); end; -- Do while statement. Ends the current statement sequence. @@ -1907,14 +1859,12 @@ package body Instrument.C is UIC.Pass.Curlify (N => Do_Body, Rew => UIC.Rewriter); - Traverse_Statements - (IC, UIC, To_Vector (Do_Body), No_Dominant); + Traverse_Statements (IC, UIC, To_Vector (Do_Body)); Extend_Statement_Sequence (Do_While, 'W', Instr_Scheme => Instr_Expr); Process_Decisions_Defer (Do_While, 'W'); Set_Statement_Entry; - Current_Dominant := ('S', Do_While); end; @@ -1939,29 +1889,13 @@ package body Instrument.C is Set_Statement_Entry; - -- The first statement that is nested in the FOR loop runs - -- iff the guard expression evaluates to True. Set the - -- dominant accordingly. - - Current_Dominant := ('T', For_Cond); - UIC.Pass.Curlify (N => For_Body, Rew => UIC.Rewriter); - Current_Dominant := - Traverse_Statements - (IC, UIC, - To_Vector (For_Body), - Current_Dominant); + Traverse_Statements (IC, UIC, To_Vector (For_Body)); Extend_Statement_Sequence (For_Inc, ' ', Instr_Scheme => Instr_Expr); Set_Statement_Entry; - - -- Evaluation of the guard expression necessarily precedes - -- evaluation of the first statement that follows the - -- FOR loop. - - Current_Dominant := ('S', For_Cond); end; when Cursor_CXX_For_Range_Stmt => @@ -1989,10 +1923,7 @@ package body Instrument.C is -- Generate obligations for body statements UIC.Pass.Curlify (N => For_Body, Rew => UIC.Rewriter); - Traverse_Statements - (IC, UIC, - To_Vector (For_Body), - Current_Dominant); + Traverse_Statements (IC, UIC, To_Vector (For_Body)); end; -- Unconditional goto, which is included in the current statement @@ -2001,11 +1932,9 @@ package body Instrument.C is when Cursor_Goto_Stmt | Cursor_Indirect_Goto_Stmt => Extend_Statement_Sequence (N, ' '); Set_Statement_Entry; - Current_Dominant := No_Dominant; when Cursor_Label_Stmt => Set_Statement_Entry; - Current_Dominant := No_Dominant; Traverse_Statements (IC, UIC, Get_Children (N)); when Cursor_Stmt_Expr => @@ -2112,27 +2041,6 @@ package body Instrument.C is SD_Last : constant Types.Int := SD.Last; begin for J in SC_First .. SC_Last loop - -- If there is a pending dominant for this statement sequence, - -- emit a SCO for it. - - if J = SC_First and then Current_Dominant /= No_Dominant then - declare - From : constant Local_Source_Location := - Start_Sloc (Current_Dominant.N); - To : constant Local_Source_Location := - End_Sloc (Current_Dominant.N); - - begin - UIC.Pass.Append_SCO - (UIC => UIC, - N => Current_Dominant.N, - C1 => '>', - C2 => Current_Dominant.K, - From => From, - To => To, - Last => False); - end; - end if; declare SCE : SC_Entry renames SC.Table (J); begin @@ -2153,13 +2061,6 @@ package body Instrument.C is end; end loop; - -- Last statement of basic block, if present, becomes new current - -- dominant. - - if SC_Last >= SC_First then - Current_Dominant := ('S', SC.Table (SC_Last).N); - end if; - -- Clear out used section of SC table SC.Set_Last (SC_First - 1); @@ -2196,7 +2097,6 @@ package body Instrument.C is if Emit_SCOs then Set_Statement_Entry; end if; - return Current_Dominant; end Traverse_Statements; --------------------------- From 7d1ed7b81d6d0483833bab619e2893ea9eb4e288 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 13 Oct 2022 14:45:37 +0200 Subject: [PATCH 0055/1483] xcov_instrument: register_failure should imply !warnings_as_errors A gnatcov instrument failure will always come with a warning: if we expect a failure, do not make the test fail for a warning, even if warnings_as_errors is True (which is the case by default). Change-Id: Ide0a55c28d5bf084f92211392e44c01dba011538 TN: V922-008 --- testsuite/SCOV/instr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index d6c4d78e8..ef5d2f0cf 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -110,7 +110,7 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", auto_languages=auto_languages, ) - if warnings_as_errors: + if register_failure and warnings_as_errors: output = contents_of(out) thistest.fail_if( From 3b0b55952d9d34e35f78cb56925078a48693696a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 22 Sep 2022 14:50:24 +0200 Subject: [PATCH 0056/1483] Fix tests that actually expect a warning Some test expect warnings; set instrument_warnings_as_errors to False for them. Also fix the formatting of the modified tests. Change-Id: Ic64ae3c2bee703095a8e5e2f0a404c10e0e45b06 TN: V922-008 --- .../UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py | 4 +++- .../UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py | 4 +++- .../UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py | 4 +++- .../Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py | 2 +- .../UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py | 4 +++- 5 files changed, 13 insertions(+), 5 deletions(-) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py index 1ecc98509..7a39230ff 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py @@ -18,7 +18,9 @@ extra=gprcov_for(units_in=['no_such_unit', 'main']))), covlevel='stmt', mains=['main'], - extra_coverage_args=['-axcov']) + instrument_warnings_as_errors=False, + extra_coverage_args=['-axcov'], +) log_file = ('coverage.log' if thistest.options.trace_mode == 'bin' else diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py index c4f1eecc6..c234c62f2 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py @@ -16,7 +16,9 @@ units=['no_such_unit', 'main', 'helper.say_hello']), covlevel='stmt', mains=['main'], - extra_coverage_args=['-axcov']) + instrument_warnings_as_errors=False, + extra_coverage_args=['-axcov'], +) log_file = ('coverage.log' if thistest.options.trace_mode == 'bin' else diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py index f468949a8..7d6132bfa 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py @@ -79,7 +79,9 @@ def run_test(label, slug, main, helper, recursive, projects=[], units=[], covlevel='stmt', mains=['main'], gpr_obj_dir='obj-main', - extra_coverage_args=['-axcov']) + instrument_warnings_as_errors=False, + extra_coverage_args=['-axcov'], + ) log_file = ('coverage.log' if thistest.options.trace_mode == 'bin' else diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py index 7b0dfc039..f7d4f869d 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py @@ -21,7 +21,7 @@ def try_one_gpr(gpr, no_such): mains=['p'], extra_coverage_args=['-axcov'], out=dump, - register_failure=False + register_failure=False, ) dump = contents_of(dump) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py index 30e41e757..02b1bc45f 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py @@ -29,7 +29,9 @@ covlevel='stmt', mains=['main'], gpr_obj_dir='obj-main', - extra_coverage_args=['-axcov']) + instrument_warnings_as_errors=False, + extra_coverage_args=['-axcov'], +) log_file = ('coverage.log' if thistest.options.trace_mode == 'bin' else From b34f77e5670fc430ce0a126dcf83335e611d2e49 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 23 Sep 2022 10:36:17 +0200 Subject: [PATCH 0057/1483] SUITE/tutils.py: pass user-defined gargs to gprinstall Change-Id: Ifaeb4d6ad479cdd0867f27b8a296c7dc3d9d0c1c TN: V922-008 --- testsuite/SUITE/tutils.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index ee52d89e0..b19a99300 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -246,22 +246,23 @@ def gprbuild(project, return p -def gprinstall(project, prefix=None): +def gprinstall(project, gargs=None): """ Run "gprinstall" on the provided project file. - :param None|str prefix: If a string is passed, add `--prefix=PREFIX` to the - gprinstall command-line. + :param None|list[str] gargs: list of command line switches to pass to + gprinstall """ ofile = 'gprinstall.out' args = ['gprinstall', '-P', project, '-p'] - if prefix: - args.append('--prefix={}'.format(prefix)) # Add mandatory options, such as target and RTS info args.extend(thistest.gprconfoptions) args.extend(thistest.gprvaroptions) + # Add user-provided arguments + args.extend(to_list(gargs)) + p = run_and_log(args, output=ofile, timeout=thistest.options.timeout) thistest.stop_if(p.status != 0, FatalError('gprinstall exit in error', ofile)) From a634c06c13eae1e847e1852b7b442a2688045ffc Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 16 Sep 2022 11:30:33 +0200 Subject: [PATCH 0058/1483] testsuite: detect more error/warnings from "gnatcov instrument" Consider error messages (starting with !!!), and other messages starting with "warning:" as warning messages. Note that not all error messages lead to a fatal error, so some warnings/errors are currently ignored even when register_failure=True. As we still want to detect such messages (as they are a sign of something not correct in the gnatcov execution), signal them when warnings_as_errors=True is passed to xcov_instrument. TN: V922-008 Depends-On: I3c7ac2bc9fc634b4769854dce1de23e1fffc5b8d Change-Id: I9e86e1c91017e2ba98bd28325b4ef70389c9826c --- testsuite/SCOV/instr.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index ef5d2f0cf..1579670f7 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -114,8 +114,8 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", output = contents_of(out) thistest.fail_if( - "***" in output, - f"Warnings detected in the output of 'gnatcov instrument':" + "***" in output or "!!!" in output or "warning:" in output, + f"Warnings/errors detected in the output of 'gnatcov instrument':" f"\n{indent(output)}" ) From ccfc353a28dd2d8a95ba70e663bb0540ecc6b078 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 9 Nov 2022 16:05:21 +0000 Subject: [PATCH 0059/1483] instrument-common.adb: remove special processing for dominance markers Now that instrumenters no longer emit dominance markers, it no longer makes sense to have special processing for them in instrumentation code. TN: VA21-006 Change-Id: I5cc2cacd93d6d3131c6c328e451a84dfb5fcd700 --- tools/gnatcov/instrument-common.adb | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 1a5e97f5f..04009001e 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -936,25 +936,6 @@ package body Instrument.Common is Parent : Scope_Entity_Acc renames UIC.Current_Scope_Entity.Parent; Scope : Scope_Entity_Acc renames UIC.Current_Scope_Entity; begin - -- Note that scope entities may reference any kind of low-level SCOs, - -- including dominance markers. As those markers are removed after - -- calling Process_Low_Level_SCOs, they are remapped to No_SCO_Id. Fix - -- up the span so that only valid high-level SCOs are referenced there. - -- Note that a dominance marker is necessarily emitted with a statement - -- SCO, so we have no risk of having only a dominance marker in the - -- scope entity. As such dominance markers are emitted before statement - -- SCOs, this also means that Scope_Entity.To can't possibly reference a - -- dominance marker SCO. - -- - -- TODO???: clarify whether we need dominance SCOs or not in the - -- instrumentation scheme, as this is not clear we do. - - while Nat (Scope.From) < SCOs.SCO_Table.Last - and then SCOs.SCO_Table.Table (Nat (Scope.From)).C1 = '>' - loop - Scope.From := Scope.From + 1; - end loop; - -- Update the last SCO for this scope entity Scope.To := SCO_Id (SCOs.SCO_Table.Last); From 3e87859df6a7333d81dbb137a056f450e2e9196c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 8 Sep 2022 16:05:25 +0200 Subject: [PATCH 0060/1483] Instrumentation: allow the extension of the SCO_Unit_Table Preparatory work for coverage analysis of C headers. When traversing a body file, some SCOs may be attached to e.g. an included file. In this case, we want to attach the SCOs to the included file rather than the body file. Add support for it in Instrument.Common.Append_SCO. This also enables the removal of the code that was filling the SCO_Unit_Table both in Instrument.{C,Ada_Unit}. Change-Id: I28f7a0a1507a0ba658317b133822fb065a063ce7 TN: V728-002 --- tools/gnatcov/instrument-ada_unit.adb | 18 ++++++++----- tools/gnatcov/instrument-c.adb | 22 +++------------- tools/gnatcov/instrument-common.adb | 37 ++++++++++++++++++++++++++- tools/gnatcov/instrument-common.ads | 8 +++++- 4 files changed, 58 insertions(+), 27 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index bf4a640bb..c64190b70 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3109,6 +3109,7 @@ package body Instrument.Ada_Unit is C2 => SCE.Typ, From => +SCE.From, To => +SCE.To, + SFI => UIC.SFI, Last => (J = SC_Last), Pragma_Aspect_Name => Pragma_Aspect_Name); @@ -5103,6 +5104,7 @@ package body Instrument.Ada_Unit is C2 => C2, From => +Sloc (Op_N), To => Slocs.No_Local_Location, + SFI => UIC.SFI, Last => False); Hash_Entries.Append ((Sloc (N), SCOs.SCO_Table.Last)); @@ -5159,6 +5161,7 @@ package body Instrument.Ada_Unit is C2 => C2, From => +Start_Sloc (N_SR), To => +Inclusive_End_Sloc (N_SR), + SFI => UIC.SFI, Last => False); Hash_Entries.Append ((Start_Sloc (N_SR), SCOs.SCO_Table.Last)); end Output_Element; @@ -5238,6 +5241,7 @@ package body Instrument.Ada_Unit is C2 => ' ', From => +Loc, To => Slocs.No_Local_Location, + SFI => UIC.SFI, Last => False, Pragma_Aspect_Name => Nam); @@ -6383,6 +6387,13 @@ package body Instrument.Ada_Unit is -- procedures/functions in the same pass. SCOs.Initialize; + + -- Append an entry in the SCO_Unit_Table for this unit to preserve + -- invariants in our data structures and subsequently avoiding to have + -- UIC.CU set to No_CU_Id. + + Append_Unit (UIC.SFI); + Traverse_Declarations_Or_Statements (IC => IC, UIC => UIC, @@ -6390,13 +6401,6 @@ package body Instrument.Ada_Unit is Preelab => Preelab, P => Rewriter.Rewritten_Unit.Root); - SCOs.SCO_Unit_Table.Append - ((File_Name => new String'(Filename), - File_Index => UIC.SFI, - Dep_Num => 1, - From => SCOs.SCO_Table.First, - To => SCOs.SCO_Table.Last)); - -- Convert low level SCOs from the instrumenter to high level SCOs. -- This creates BDDs for every decision. diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 4507a8821..a056fd84c 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -602,7 +602,8 @@ package body Instrument.C is Loc : Source_Location_T := Get_Range_Start (Get_Cursor_Extent (N)); Info : PP_Info; begin - Append_SCO (C1, C2, From, To, Last, Pragma_Aspect_Name); + Append_SCO + (C1, C2, From, To, UIC.SFI, Last, Pragma_Aspect_Name); -- We add preprocessing information only for actual SCOs. Return there -- if this is an operator SCO. @@ -807,7 +808,8 @@ package body Instrument.C is Pragma_Aspect_Name : Name_Id := Namet.No_Name) is begin - Append_SCO (C1, C2, From, To, Last, Pragma_Aspect_Name); + Append_SCO + (C1, C2, From, To, UIC.SFI, Last, Pragma_Aspect_Name); -- If this SCO is in a macro expansion, let's add source location -- information: we want to be able to know the actual source location @@ -2633,10 +2635,6 @@ package body Instrument.C is Func_Args); end Put_Extern_Decl; - Unit_Index : SCOs.SCO_Unit_Index; - -- Index in low-level tables of the only SCO Unit we create for this - -- source file. - -- Start of processing for Instrument_Source_File begin @@ -2667,7 +2665,6 @@ package body Instrument.C is Dep_Num => 1, From => SCOs.SCO_Table.First, To => SCOs.SCO_Table.Last)); - Unit_Index := SCOs.SCO_Unit_Table.Last; end; -- Import analysis options for the file to preprocess, then run the @@ -2762,17 +2759,6 @@ package body Instrument.C is UIC => UIC, L => Get_Children (Get_Translation_Unit_Cursor (UIC.TU))); - -- At this point, all coverage obligations where created in the - -- low-level tables, so we can adjust the upper bound in the SCO Unit - -- table. - -- - -- TODO??? This works because for now we handle only one SCO unit, but - -- handling more units (for instance C headers) will require a redesign - -- for this part, for instance making Append_SCO automatically increment - -- that upper bound for the last SCO unit. - - SCOs.SCO_Unit_Table.Table (Unit_Index).To := SCOs.SCO_Table.Last; - -- Check whether there is a mismatch between Last_SCO and -- SCOs.SCO_Table.Last. If there is, warn the user and discard the -- preprocessed info: the SCO mapping will be wrong. diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 04009001e..8b6503f9b 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -850,6 +850,20 @@ package body Instrument.Common is end loop; end Import_Annotations; + ----------------- + -- Append_Unit -- + ----------------- + + procedure Append_Unit (SFI : Source_File_Index) is + begin + SCOs.SCO_Unit_Table.Append + ((File_Name => new String'(Get_Full_Name (SFI)), + File_Index => SFI, + Dep_Num => 1, + From => SCOs.SCO_Table.Last + 1, + To => SCOs.SCO_Table.Last)); + end Append_Unit; + ---------------- -- Append_SCO -- ---------------- @@ -857,10 +871,26 @@ package body Instrument.Common is procedure Append_SCO (C1, C2 : Character; From, To : Local_Source_Location; + SFI : Source_File_Index; Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name) is - begin + use type SCOs.SCO_Unit_Index; + begin + -- If needed, append a new entry to the SCO_Unit_Table (if we + -- are entering a new file when instrumenting a compilation unit, + -- which can happen with #included files for instance). + + if SCOs.SCO_Unit_Table.Last = 0 + or else + SCOs.SCO_Unit_Table.Table (SCOs.SCO_Unit_Table.Last).File_Index /= + SFI + then + Append_Unit (SFI); + end if; + + -- Append a new SCO to the low level SCO table + SCOs.SCO_Table.Append ((From => (Logical_Line_Number (From.Line), Column_Number (From.Column)), @@ -871,6 +901,11 @@ package body Instrument.Common is Last => Last, Pragma_Sloc => Types.No_Location, Pragma_Aspect_Name => Pragma_Aspect_Name)); + + -- Then, extend the SCO_Unit_Table with the newly created SCO + + SCOs.SCO_Unit_Table.Table (SCOs.SCO_Unit_Table.Last).To := + SCOs.SCO_Table.Last; end Append_SCO; ------------------------------ diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 7969d4079..8d63791e3 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -567,12 +567,18 @@ package Instrument.Common is -- verify that they are built with the version of GNATcov_RTS the -- instrumenter expects. + procedure Append_Unit (SFI : Source_File_Index); + -- Append a new entry to the SCO_Unit_Table, with an empty SCO range + procedure Append_SCO (C1, C2 : Character; From, To : Local_Source_Location; + SFI : Source_File_Index; Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name); - -- Append a new entry to the low-level SCO table + -- Append a new entry to the low-level SCO table. If SFI designates a new + -- source file, also append a new entry to the SCO_Unit_Table, otherwise + -- complete its last entry. package CU_Name_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, From 1edd271db2d6b46961642b945df35460c2c20623 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 8 Sep 2022 17:28:47 +0200 Subject: [PATCH 0061/1483] C instrumentation: coverage analysis on header files Header files may contain code that is of interest for coverage analysis. To simplify the C instrumentation process, gnatcov used to ignore included code. This commit adds the support to instrument included code that is of interest (i.e. that comes from a header file of interest). TN: V728-002 Change-Id: I80e14e318d64694aaa4f0b620af7e0e16033bdcf --- tools/gnatcov/instrument-c.adb | 85 ++++++++++++---------------- tools/gnatcov/instrument-c.ads | 10 +--- tools/gnatcov/instrument-c_utils.adb | 33 ++++++++--- tools/gnatcov/instrument-c_utils.ads | 6 +- 4 files changed, 67 insertions(+), 67 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index a056fd84c..9da869faa 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -43,6 +43,7 @@ with Hex_Images; use Hex_Images; with Instrument.C_Utils; use Instrument.C_Utils; with Outputs; use Outputs; with Paths; use Paths; +with Project; with SCOs; with Subprocesses; use Subprocesses; with System; use System; @@ -165,7 +166,7 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context'Class; N : Cursor_T; C1, C2 : Character; - From, To : Local_Source_Location; + From, To : Source_Location; Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name); -- Append a SCO to SCOs.SCO_Table. Also partially fill the preprocessing @@ -179,7 +180,7 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context'Class; N : Cursor_T; C1, C2 : Character; - From, To : Local_Source_Location; + From, To : Source_Location; Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name); -- Append a SCO to SCOs.SCO_Table, and complete the preprocessing info with @@ -595,7 +596,7 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context'Class; N : Cursor_T; C1, C2 : Character; - From, To : Local_Source_Location; + From, To : Source_Location; Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name) is @@ -603,7 +604,7 @@ package body Instrument.C is Info : PP_Info; begin Append_SCO - (C1, C2, From, To, UIC.SFI, Last, Pragma_Aspect_Name); + (C1, C2, From.L, To.L, From.Source_File, Last, Pragma_Aspect_Name); -- We add preprocessing information only for actual SCOs. Return there -- if this is an operator SCO. @@ -612,7 +613,10 @@ package body Instrument.C is return; end if; - Info.Actual_Source_Range := (From, To); + -- TODO??? the actual source range should be a Source_Location, and not + -- a Local_Source_Location as it can refer to #included files. + + Info.Actual_Source_Range := (From.L, To.L); -- Check if this is comes from a macro expansion, in which case we need -- to record some information, for reporting purposes. @@ -803,13 +807,13 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context'Class; N : Cursor_T; C1, C2 : Character; - From, To : Local_Source_Location; + From, To : Source_Location; Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name) is begin Append_SCO - (C1, C2, From, To, UIC.SFI, Last, Pragma_Aspect_Name); + (C1, C2, From.L, To.L, From.Source_File, Last, Pragma_Aspect_Name); -- If this SCO is in a macro expansion, let's add source location -- information: we want to be able to know the actual source location @@ -1078,7 +1082,7 @@ package body Instrument.C is Bits : constant Decision_Bit_Ids := Allocate_Decision_Bits (Unit_Bits, - (Unit_Bits.SFI, Start_Sloc (N)), + Start_Sloc (N), SD.LL_SCO, SD.State, Path_Count); @@ -1152,8 +1156,8 @@ package body Instrument.C is -- If not null, node where the witness call should be inserted. -- Otherwise, the insertion node will be N. - From : Local_Source_Location; - To : Local_Source_Location; + From : Source_Location; + To : Source_Location; Typ : Character; Instr_Scheme : Instr_Scheme_Type := Instr_Stmt; @@ -1278,7 +1282,7 @@ package body Instrument.C is -- Likewise for the putative SCO_Raw_Hash_Table entries: see below type Hash_Entry is record - Sloc : Local_Source_Location; + Sloc : Source_Location; SCO_Index : Nat; end record; -- We must register all conditions/pragmas in SCO_Raw_Hash_Table. @@ -1404,7 +1408,7 @@ package body Instrument.C is C1 => C1, C2 => C2, From => Sloc (Get_Operator_Loc (N)), - To => No_Local_Location, + To => Slocs.No_Location, Last => False); Hash_Entries.Append ((Sloc => Start_Sloc (N), @@ -1984,8 +1988,8 @@ package body Instrument.C is is Insert_Cursor : aliased Cursor_T := N; - F : constant Local_Source_Location := Start_Sloc (N); - T : Local_Source_Location := End_Sloc (N); + F : constant Source_Location := Start_Sloc (N); + T : Source_Location := End_Sloc (N); -- Source location bounds used to produce a SCO statement. By -- default, this should cover the same source location range as N, -- however for nodes that can contain other statements, we select an @@ -1996,10 +2000,8 @@ package body Instrument.C is -- In the case of simple statements, set to null cursor and unused. -- Otherwise, use F and this node's end sloc for the emitted -- statement source location range. - begin - -- For now, instrument only cursors that come from the file being - -- instrumented, and do not instrument included code. + begin if Is_Null (N) or else not Is_Source_Of_Interest (UIC, N) then return; end if; @@ -2121,7 +2123,6 @@ package body Instrument.C is begin if Is_Source_Of_Interest (UIC, N) then - case Kind (N) is -- Traverse the statements of function bodies @@ -2146,8 +2147,8 @@ package body Instrument.C is end if; end; - -- Traverse the declarations of a namespace / linkage - -- specifier etc. + -- Traverse the declarations of a namespace / linkage + -- specifier etc. when Cursor_Namespace | Cursor_Linkage_Spec @@ -2649,23 +2650,6 @@ package body Instrument.C is UIC.Instrumented_Unit := CU_Name; UIC.Buffer_Unit := CU_Name_For_File (+Buffer_Filename, CU_Name.Project_Name); - UIC.File := +Orig_Filename; - - -- Create the only SCO Unit we will need to instrument this source file. - -- Also make sure we will create at least the set of coverage buffers - -- for the main source file. - - declare - Dummy : C_Instrumented_Entities renames - UIC.Find_Instrumented_Entities (UIC.SFI); - begin - SCOs.SCO_Unit_Table.Append - ((File_Name => new String'(Orig_Filename), - File_Index => UIC.SFI, - Dep_Num => 1, - From => SCOs.SCO_Table.First, - To => SCOs.SCO_Table.Last)); - end; -- Import analysis options for the file to preprocess, then run the -- preprocessor. @@ -2712,16 +2696,14 @@ package body Instrument.C is new String' (Comment (Match_Res (1).First .. Match_Res (1).Last)); UIC.Annotations.Append - (((UIC.SFI, Sloc (Get_Token_Location (UIC.TU, Token))), - Ann)); + ((Sloc (Get_Token_Location (UIC.TU, Token)), Ann)); end if; Match (End_Matcher, Comment, Match_Res); if Match_Res (0) /= No_Match then Ann.Kind := Exempt_Off; UIC.Annotations.Append - (((UIC.SFI, - Sloc - (Get_Range_End (Get_Token_Extent (UIC.TU, Token)))), + ((Sloc + (Get_Range_End (Get_Token_Extent (UIC.TU, Token))), Ann)); end if; end; @@ -2734,12 +2716,12 @@ package body Instrument.C is Search_Exempt_In_Token'Access); end Search_Exemptions; - -- Flush the SCO_Table. We want the SCOs to be located at their - -- presumed (i.e. accounting for line directives) preprocessed source - -- range, to have unique locations for each. + -- Save the last SCO of the first pass (for a consistency check with + -- the second pass later), and reset the SCO tables for the + -- instrumentation pass. Record_PP_Info_Last_SCO := SCOs.SCO_Table.Last; - SCOs.SCO_Table.Init; + SCOs.Initialize; -- Then, instrument @@ -4231,22 +4213,29 @@ package body Instrument.C is Filename => C_File'Access, Line => Line'Access, Column => Column'Access); - File := +Get_C_String (C_File); + File := +Ada.Directories.Full_Name (Get_C_String (C_File)); -- Look for a corresponding entry in UIC.Sources_Of_Interest, create one -- if it is missing. declare + use GNATCOLL.Projects; + use GNATCOLL.VFS; use Source_Of_Interest_Maps; Cur : constant Cursor := UIC.Sources_Of_Interest.Find (File); SOI : Source_Of_Interest; + FI : GNATCOLL.Projects.File_Info; begin if Has_Element (Cur) then return UIC.Sources_Of_Interest.Reference (Cur).Of_Interest; end if; - if File = UIC.File then + -- Consider that File is of interest iff it belongs to a loaded + -- project. + + FI := Project.Project.Info (Create (+To_String (File))); + if FI.Project /= No_Project then SOI := (Of_Interest => True, SFI => Get_Index_From_Generic_Name diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 95e896769..8b266dc8f 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -328,9 +328,6 @@ package Instrument.C is CIdx : Index_T; Rewriter : Rewriter_T; - File : Ada.Strings.Unbounded.Unbounded_String; - -- Original filename - Instrumented_Entities : C_Instrumented_Entities_Maps.Map; -- Statements, decisions and (for MC/DC) conditions to be -- instrumented. @@ -372,11 +369,6 @@ package Instrument.C is -- Track the source file from which N originates in -- UIC.Sources_Of_Interest. Return whether this source file is a source of -- interest. - -- - -- TODO??? For now, only the source file from which instrumentation started - -- (the "body" C/C++ file, i.e. UIC.File) is considered as a source of - -- interest, i.e. code inserted by #include is not instrumented and - -- excluded from coverage analysis. private @@ -395,7 +387,7 @@ private UIC : in out C_Unit_Inst_Context'Class; N : Cursor_T; C1, C2 : Character; - From, To : Local_Source_Location; + From, To : Source_Location; Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name) is null; diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index 4a9074c40..799a3de7f 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -19,11 +19,15 @@ with Interfaces.C; use Interfaces.C; with System; use System; -with Ada.Text_IO; use Ada.Text_IO; +with Ada.Directories; use Ada.Directories; +with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Conversion; +with Clang.CX_String; use Clang.CX_String; with Clang.Extensions; use Clang.Extensions; +with Files_Table; use Files_Table; + package body Instrument.C_Utils is use Cursor_Vectors; @@ -45,31 +49,46 @@ package body Instrument.C_Utils is -- Sloc -- ---------- - function Sloc (Loc : Source_Location_T) return Local_Source_Location is + function Sloc (Loc : Source_Location_T) return Source_Location is + Line, Column : aliased Interfaces.C.unsigned; + File : aliased String_T; begin - return Presumed_Location (Loc); + if Loc = Get_Null_Location then + return No_Location; + end if; + Get_Presumed_Location (Location => Loc, + Filename => File'Access, + Line => Line'Access, + Column => Column'Access); + return + (Source_File => + Get_Index_From_Generic_Name + (Full_Name (Get_C_String (File)), Kind => Source_File), + L => + (Line => Natural (Line), + Column => Natural (Column))); end Sloc; ---------------- -- Start_Sloc -- ---------------- - function Start_Sloc (N : Cursor_T) return Local_Source_Location is + function Start_Sloc (N : Cursor_T) return Source_Location is begin - return Presumed_Location (Get_Range_Start (Get_Cursor_Extent (N))); + return Sloc (Get_Range_Start (Get_Cursor_Extent (N))); end Start_Sloc; -------------- -- End_Sloc -- -------------- - function End_Sloc (N : Cursor_T) return Local_Source_Location is + function End_Sloc (N : Cursor_T) return Source_Location is Loc : Source_Location_T := Get_Range_End (Get_Cursor_Extent (N)); begin if Is_Macro_Location (Loc) then Loc := Get_Expansion_End (Get_Cursor_TU (N), Loc); end if; - return Presumed_Location (Loc); + return Sloc (Loc); end End_Sloc; ---------- diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index d312e85b6..33a3ef2a1 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -37,13 +37,13 @@ package Instrument.C_Utils is -- Location utilities -- ------------------------ - function Sloc (Loc : Source_Location_T) return Local_Source_Location; + function Sloc (Loc : Source_Location_T) return Source_Location; -- Convert a Source_Location_T to a Source_Location - function Start_Sloc (N : Cursor_T) return Local_Source_Location; + function Start_Sloc (N : Cursor_T) return Source_Location; -- Return the starting location of a node - function End_Sloc (N : Cursor_T) return Local_Source_Location; + function End_Sloc (N : Cursor_T) return Source_Location; -- Return the end location of a node function Kind (N : Cursor_T) return Cursor_Kind_T; From de346d143453aabd6050bd016b965fd5d284c5e0 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 4 Jul 2022 15:16:51 +0200 Subject: [PATCH 0062/1483] source-rebase: always rebase even when the source already exists gnatcov used not to rebase if the original source existed. Fix that behavior and always rebase, if we have an existing source after applying the rebasing. Change-Id: I8e07ddfea54fe7770431f64c3eb2f1e926c657c4 TN: V627-017 --- doc/gnatcov/cov_source.rst | 29 +++++++++++---------- tools/gnatcov/files_table.adb | 47 ++++++++++++----------------------- 2 files changed, 30 insertions(+), 46 deletions(-) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index 28bdf284b..225120974 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -147,8 +147,8 @@ The available options are as follows: analysis from that initial state. :cmd-option:`--source-rebase`, |rarg|: - Specify alternate absolute path prefixes to locate missing source files - when producing annotated source outputs. See :ref:`rebase_opts` + Specify alternate absolute path prefixes to locate source files when + producing annotated source outputs. See :ref:`rebase_opts` :cmd-option:`--source-search`, |rarg|: Specify a directory in which missing source files will be searched when @@ -1510,7 +1510,7 @@ options to help in those situations: * The option :cmd-option:`--source-rebase=\=\` This option allows the specification of alternate path prefixes for source - files that were not found in there build_1234/instrumentation location. + files. If the location of a source file, when built on a first machine, was ``/work/build_1234/src/main.adb`` but on the machine where the report is to @@ -1538,18 +1538,17 @@ options to help in those situations: This option allows the specification of directories in which to search for missing source files. - If the location of a source file, when built on a first machine, was - ``/work/build_1234/src/main.adb`` but its location on the machine where the - report is generated is ``/some/path/project/src/main.adb`` then passing - :cmd-option:`--source-search=/some/path/project/src` will enable |gcv| to - find the missing source file. This option also accepts response files. - - This option can appear multiple times on the command line, and when trying to - locate a missing source file, |gcv| will first try the - :cmd-option:`--source-rebase` prefix pairs, if any, and if the source file - was not found, it will then look for the file in all the directories passed - with :cmd-option:`--source-search` in the order in which they appear on the - command line. + If the location of a source file, when built on a first machine, + was ``/work/build_1234/src/main.adb`` but its location on the machine where + the report is generated is ``/some/path/project/src/main.adb`` then passing + :option:`--source-search=/some/path/project/src` will enable |gcv| to find + the missing source file. This option also accepts response files. + + This option can appear multiple times on the command line. Note that |gcv| + will first try the :option:`--source-rebase` prefix pairs, if any, and if + the source file was not found, it will then look for the file in all the + directories passed with :option:`--source-search` in the order in which they + appear on the command line. These two options perform very similar functions and can sometimes be used interchangeably, however the second option is less selective and can lead to diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index c267dd85a..3819a971b 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -170,11 +170,9 @@ package body Files_Table is -- Whether we should even try to rebase files using Renaming_Map or not function Locate_Source (File : Virtual_File) return Virtual_File; - -- Try to find the actual location on disk of File. This returns File if it - -- exists in the filesystem. Otherwise, it tries to locate it transforming - -- File according to the source rebase/search parameters - -- (see --source-rebase and --source-search command line arguments). - -- Return No_File if we could not locate the file. + -- Apply the --source-rebase and --source-search options over the given + -- File (see the documentation of these options). If no file was found + -- using these options, return the original file. function Name_For_Rebase (File : Virtual_File) return String; -- Helper for Locate_Source. Return the file name to use in source rebasing @@ -779,16 +777,6 @@ package body Files_Table is Full_Path := Element (Rebase_Cur); elsif Insert then Full_Path := Locate_Source (Original_Full_Path); - if Full_Path = No_File then - - -- If the file was not found, reset it to his original full - -- path. Still make the association in Renaming_Map to avoid - -- subsequent calls to Locate_Source. We don't need to update - -- the Has_Source field of the corresponding File_Info, this - -- will be done when trying to open the source file. - - Full_Path := Original_Full_Path; - end if; Renaming_Map.Insert (Original_Full_Path, Full_Path); end if; end if; @@ -1576,6 +1564,11 @@ package body Files_Table is Try_Open (File, Name.all, Success); + -- TODO???: the FI.Full_Name can only be null in binary traces, when + -- loading SCOs from a library file while there is no debug info for the + -- corresponding SCOs. Remove the code below and check that FI.Full_Name + -- is not null if / when binary traces are deprecated. + if FI.Full_Name = null then if Success then @@ -1600,8 +1593,8 @@ package body Files_Table is end if; end if; - -- If we could not find the source file in his original path or using - -- the project information, try to use the rebase and souce search + -- If we could not find the source file at its original path or using + -- the project information, try to use the rebase and source search -- mechanism on the simple name. if not Success then @@ -1609,11 +1602,9 @@ package body Files_Table is Candidate_File : Virtual_File := Create (+FI.Simple_Name.all); begin Candidate_File := Locate_Source (Candidate_File); - if Candidate_File /= No_File then - Try_Open (File, +Candidate_File.Full_Name, Success); - if Success then - FI.Full_Name := new String'(+Candidate_File.Full_Name); - end if; + Try_Open (File, +Candidate_File.Full_Name, Success); + if Success then + FI.Full_Name := new String'(+Candidate_File.Full_Name); end if; end; end if; @@ -1634,13 +1625,7 @@ package body Files_Table is function Locate_Source (File : Virtual_File) return Virtual_File is Candidate : Virtual_File; begin - -- If the file exists at his original full path then great! - - if File.Is_Regular_File then - return File; - end if; - - -- Try to rebase + -- Try to rebase (--source-rebase) declare use GNAT.Regpat; @@ -1664,7 +1649,7 @@ package body Files_Table is end loop; end; - -- Try source path + -- Try source search (--source-search) declare E : Source_Search_Entry_Acc := First_Source_Search_Entry; @@ -1678,7 +1663,7 @@ package body Files_Table is end loop; end; - return No_File; + return File; end Locate_Source; From 28150cb7c81ee154ab7d87c86a8f85deaf4c8222 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 16 Sep 2022 14:44:19 +0200 Subject: [PATCH 0063/1483] Instrument.C: do not insert an atexit declaration if not needed With --dump-trigger=atexit, gnatcov instrument inserts a all to atexit and generates an extern declaration for it, in case it was not included. As observed, the inserted extern declaration can conflict with the atexit declaration coming from the inclusion of stdlib.h, for instance, as the signature may differ. To prevent that from happening, we will only emit a declaration of atexit if it is not already declared in the translation unit. Change-Id: Ie6ce9e5115d196e009ee47bbd954889c4d12f43a TN: V914-021 --- tools/gnatcov/instrument-c.adb | 21 ++++++++++----- tools/gnatcov/instrument-c_utils.adb | 38 ++++++++++++++++++++++++++++ tools/gnatcov/instrument-c_utils.ads | 4 +++ 3 files changed, 56 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 9da869faa..68c354605 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3546,13 +3546,20 @@ package body Instrument.C is end; when At_Exit => - Put_Extern_Decl - (Rew.Rewriter, - Insert_Extern_Location, - Instrumenter, - "int", - "atexit", - Func_Args => "void (*function) (void)"); + + -- To avoid getting conflicting atexit declarations (if the user + -- includes stdlib.h), we only emit a declaration of atexit if + -- is not already declared in the translation unit. + + if not Is_Atexit_Declared (Rew.TU) then + Put_Extern_Decl + (Rew.Rewriter, + Insert_Extern_Location, + Instrumenter, + "int", + "atexit", + Func_Args => "void (*function) (void)"); + end if; declare Body_Cursor : constant Cursor_T := Get_Body (Main_Cursor); diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index 799a3de7f..1aafc1c7e 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -263,6 +263,44 @@ package body Instrument.C_Utils is return Result; end Get_Main; + ------------------------ + -- Is_Atexit_Declared -- + ------------------------ + + function Is_Atexit_Declared (TU : Translation_Unit_T) return Boolean is + Has_Atexit_Declaration : Boolean := False; + + function Is_Atexit (Cursor : Cursor_T) return Child_Visit_Result_T; + -- Set Has_Atexit_Declaration to True if Cursor is the declaration of + -- the atexit function. Otherwise, recurse into the node if it is a + -- list of C declarations, or continue the traversal of the current + -- declaration list. + + --------------- + -- Is_Atexit -- + --------------- + + function Is_Atexit (Cursor : Cursor_T) return Child_Visit_Result_T is + begin + if Kind (Cursor) in Cursor_Translation_Unit | Cursor_Linkage_Spec + then + return Child_Visit_Recurse; + elsif Cursor_Get_Mangling (Cursor) = "atexit" then + Has_Atexit_Declaration := True; + return Child_Visit_Break; + else + return Child_Visit_Continue; + end if; + end Is_Atexit; + + -- Start of processing for Is_Atexit_Declared + + begin + Visit_Children (Parent => Get_Translation_Unit_Cursor (TU), + Visitor => Is_Atexit'Access); + return Has_Atexit_Declaration; + end Is_Atexit_Declared; + -- Rewriting utilities -------------------------------- diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 33a3ef2a1..336655c0f 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -86,6 +86,10 @@ package Instrument.C_Utils is -- Return the cursor corresponding to the definition of the "main" -- function, or the null cursor if there is no main function. + function Is_Atexit_Declared (TU : Translation_Unit_T) return Boolean; + -- Return True if there is a declaration of atexit in the given translation + -- unit. + ------------------------- -- Rewriting utilities -- ------------------------- From 324f0cef912cd3c8eedb3f24f1de602170ad23c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Mon, 7 Nov 2022 15:39:33 +0100 Subject: [PATCH 0064/1483] Instrumentation.C: pass included project source dirs as -I args Before, only the source directories of the project being compiled were passed as arguments to the -I options. This poses a problem for sources including headers from a project dependency (with "proj.gpr") as the source directories of the included projects are not registered to be searched during preprocessing, leading to the source files not being found. Now all source directories including those of included projects are given to -I. TN: VB03-024 Change-Id: I6f2bd6e597c6f96a09026bc939c37692fd6adece --- tools/gnatcov/instrument-c.adb | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 68c354605..c5e62a4c4 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -49,6 +49,7 @@ with Subprocesses; use Subprocesses; with System; use System; with Table; with Text_Files; use Text_Files; +with Project; use Project; package body Instrument.C is @@ -3978,14 +3979,37 @@ package body Instrument.C is Info : Project_Info; Filename : String) is + procedure Register_Source_Dirs (P : GNATCOLL.Projects.Project_Type); + -- Add the source directories of P's project file to the search paths + -- to be passed as -I arguments later. The order in which the paths are + -- added to the search paths vector is the same order in which GNATCOLL + -- retrieves the files in the project tree. gprbuild also depends on + -- GNATCOLL which ensures we have the same behavior here. + + -------------------------- + -- Register_Source_Dirs -- + -------------------------- + + procedure Register_Source_Dirs (P : GNATCOLL.Projects.Project_Type) is + begin + for Dir of P.Source_Dirs loop + Self.PP_Search_Path.Append + (+GNATCOLL.VFS."+" (GNATCOLL.VFS.Dir_Name (Dir))); + end loop; + end Register_Source_Dirs; + Switches : GNAT.Strings.String_List_Access; + begin + -- Pass the source directories of the project file as -I options - for Dir of Info.Project.Source_Dirs loop - Self.PP_Search_Path.Append - (+GNATCOLL.VFS."+" (GNATCOLL.VFS.Dir_Name (Dir))); - end loop; + Register_Source_Dirs (Info.Project); + + -- Pass the source directories of included projects as -I options + + Project.Iterate_Projects + (Info.Project, Register_Source_Dirs'Access, True); -- Now get actual compiler switches from the project file for Filename. -- First try to get the switches specifically for Filename, then if From 82e930536fb1d83de8e3015666ef47240e5937ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Fri, 18 Nov 2022 11:19:06 +0100 Subject: [PATCH 0065/1483] Instrument.C: remove redundant with clause TN: VB03-024 Change-Id: If967a8bb18abfbfac7ec3ddf9d05221ab96d818d --- tools/gnatcov/instrument-c.adb | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index c5e62a4c4..e94243a1d 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -49,7 +49,6 @@ with Subprocesses; use Subprocesses; with System; use System; with Table; with Text_Files; use Text_Files; -with Project; use Project; package body Instrument.C is From 55c48456a504da928c8705a03aa2545768290a5c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Nov 2022 12:50:08 +0000 Subject: [PATCH 0066/1483] instrument-input_traces.ads: minor reformatting Change-Id: I68fdc502b717d014c38f10d0a470554d733bd6a6 --- tools/gnatcov/instrument-input_traces.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-input_traces.ads b/tools/gnatcov/instrument-input_traces.ads index d337ec374..18b680131 100644 --- a/tools/gnatcov/instrument-input_traces.ads +++ b/tools/gnatcov/instrument-input_traces.ads @@ -19,10 +19,10 @@ -- Source trace files decoding with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -with Traces_Source; with Instrument.Base_Types; use Instrument.Base_Types; with SC_Obligations; with Traces_Files; +with Traces_Source; package Instrument.Input_Traces is From 0c3c61dc9fedfa870ff7b8a696dedd6c924a2f46 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Nov 2022 13:16:20 +0000 Subject: [PATCH 0067/1483] instrument-ada_unit.adb: minor refactoring Change-Id: Iede2c5fa0c0131f3eb8aef65840ec6eaf6aaf1bc --- tools/gnatcov/instrument-ada_unit.adb | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index c64190b70..a77c1e34a 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -98,6 +98,11 @@ package body Instrument.Ada_Unit is -- primitive. The additional URH argument is the Ada source rewriter that -- is ready to use for the source file to instrument. + procedure Import_Non_Instrumented_LL_SCOs + (UIC : Ada_Unit_Inst_Context; SCO_Map : LL_HL_SCO_Map); + -- Import the low level SCO in UIC marked as non-instrumented in the high + -- level non-instrumented SCO_Id sets. + ----------------------- -- To_Qualified_Name -- ----------------------- @@ -163,20 +168,12 @@ package body Instrument.Ada_Unit is return Result; end To_Qualified_Name; - procedure Import_Non_Instrumented_LL_SCOs - (UIC : Ada_Unit_Inst_Context; - SCO_Map : LL_HL_SCO_Map); - -- Import the low level SCO ids marked as non-instrumetned in the - -- high level non-instrumented SCO_id sets. - ------------------------------------- -- Import_Non_Instrumented_LL_SCOs -- ------------------------------------- procedure Import_Non_Instrumented_LL_SCOs - (UIC : Ada_Unit_Inst_Context; - SCO_Map : LL_HL_SCO_Map) - is + (UIC : Ada_Unit_Inst_Context; SCO_Map : LL_HL_SCO_Map) is begin for LL_SCO of UIC.Non_Instr_LL_SCOs loop declare @@ -6459,8 +6456,8 @@ package body Instrument.Ada_Unit is if MCDC_Coverage_Enabled then -- As high-level SCO tables have been populated, we have built - -- BDDs for each decisions, and we can now set the correct - -- MC/DC path offset for each condition. + -- BDDs for each decision, and we can now set the correct MC/DC + -- path offset for each condition. -- -- We do not include a witness call for conditions which appear -- in a decision with a path count exceeding the limit to avoid From 0851a2c369f34f85acbc28c62d9baafb9659fa8b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Nov 2022 14:06:26 +0000 Subject: [PATCH 0068/1483] Rename SCOs_Hash to Fingerprint_Type While gnatcov currently computes fingerprints for SCO tables only, upcoming changes for this ticket will use this type to store hashes of buffer bit maps, so make the name more generic. TN: VB21-022 Change-Id: I6aa9fe0cbc7757dee21fafedfdcd52a1ba53aa3b --- tools/gnatcov/coverage-source.adb | 2 +- tools/gnatcov/coverage-source.ads | 2 +- tools/gnatcov/instrument-c.adb | 5 +++-- tools/gnatcov/instrument-input_traces.adb | 9 +++++---- tools/gnatcov/instrument-input_traces.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-buffers.ads | 5 +++-- tools/gnatcov/sc_obligations.adb | 14 +++++++------- tools/gnatcov/sc_obligations.ads | 4 ++-- tools/gnatcov/traces_source.ads | 2 +- 9 files changed, 24 insertions(+), 21 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 0a3ec2a92..773331ce9 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -1702,7 +1702,7 @@ package body Coverage.Source is procedure Compute_Source_Coverage (Filename : String; - Fingerprint : SC_Obligations.SCOs_Hash; + Fingerprint : SC_Obligations.Fingerprint_Type; CU_Name : Compilation_Unit_Name; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 2cb418906..5234bbef8 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -50,7 +50,7 @@ package Coverage.Source is procedure Compute_Source_Coverage (Filename : String; - Fingerprint : SC_Obligations.SCOs_Hash; + Fingerprint : SC_Obligations.Fingerprint_Type; CU_Name : Compilation_Unit_Name; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index e94243a1d..8674ef137 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -392,7 +392,7 @@ package body Instrument.C is -- Otherwise, put one array item per line. function Format_Fingerprint - (Fingerprint : SC_Obligations.SCOs_Hash) return String; + (Fingerprint : SC_Obligations.Fingerprint_Type) return String; -- Helper to format a uint8_t[] literal for a SCOs fingerprint function Format_Def @@ -3018,7 +3018,8 @@ package body Instrument.C is ------------------------ function Format_Fingerprint - (Fingerprint : SC_Obligations.SCOs_Hash) return String is + (Fingerprint : SC_Obligations.Fingerprint_Type) return String + is Items : String_Vectors.Vector; begin for Byte of Fingerprint loop diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index d39ce9c5b..32ebf745c 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -696,8 +696,9 @@ package body Instrument.Input_Traces is with Import, Address => Trace_Entry.Project_Name; function Convert is new Ada.Unchecked_Conversion - (GNATcov_RTS.Buffers.SCOs_Hash, SC_Obligations.SCOs_Hash); - Fingerprint : constant SC_Obligations.SCOs_Hash := + (GNATcov_RTS.Buffers.Fingerprint_Type, + SC_Obligations.Fingerprint_Type); + Fingerprint : constant SC_Obligations.Fingerprint_Type := Convert (Entry_Header.Fingerprint); Statement_Buffer_Size : constant Natural := @@ -799,7 +800,7 @@ package body Instrument.Input_Traces is Data : String); procedure On_Trace_Entry (Filename : String; - Fingerprint : SC_Obligations.SCOs_Hash; + Fingerprint : SC_Obligations.Fingerprint_Type; CU_Name : Compilation_Unit_Name; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; @@ -838,7 +839,7 @@ package body Instrument.Input_Traces is procedure On_Trace_Entry (Filename : String; - Fingerprint : SC_Obligations.SCOs_Hash; + Fingerprint : SC_Obligations.Fingerprint_Type; CU_Name : Compilation_Unit_Name; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/instrument-input_traces.ads b/tools/gnatcov/instrument-input_traces.ads index 18b680131..cf048f4a4 100644 --- a/tools/gnatcov/instrument-input_traces.ads +++ b/tools/gnatcov/instrument-input_traces.ads @@ -35,7 +35,7 @@ package Instrument.Input_Traces is Data : String) is <>; with procedure On_Trace_Entry (Filename : String; - Fingerprint : SC_Obligations.SCOs_Hash; + Fingerprint : SC_Obligations.Fingerprint_Type; CU_Name : Compilation_Unit_Name; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index 3d00fbc33..bb6b56135 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -62,12 +62,13 @@ package GNATcov_RTS.Buffers is type Any_Language_Kind is (Unit_Based_Language, File_Based_Language); pragma Convention (C, Any_Language_Kind); - type SCOs_Hash is new System.Storage_Elements.Storage_Array (1 .. 20); + type Fingerprint_Type is + new System.Storage_Elements.Storage_Array (1 .. 20); -- Hash type to perform consistency checks over Source Coverage -- Obligations. 20-byte to hold a SHA-1. type GNATcov_RTS_Coverage_Buffers is record - Fingerprint : SCOs_Hash; + Fingerprint : Fingerprint_Type; Language : Any_Language_Kind; Unit_Part : Any_Unit_Part; Unit_Name : GNATcov_RTS_String; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index f552ab752..9cc09148c 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -96,7 +96,7 @@ package body SC_Obligations is Has_Code : Boolean := False; -- Set True when object code for some source file in this unit is seen - Fingerprint : SCOs_Hash; + Fingerprint : Fingerprint_Type; -- Hash of SCO info in ALI, for incremental coverage consistency check PP_Info_Map : SCO_PP_Info_Maps.Map; @@ -268,7 +268,7 @@ package body SC_Obligations is function Allocate_CU (Provider : SCO_Provider; Origin, Main_Source : Source_File_Index; - Fingerprint : SCOs_Hash; + Fingerprint : Fingerprint_Type; Created_Units : in out Created_Unit_Maps.Map) return CU_Id; -- If there is already a compilation unit for the given Main_Source that is -- not in Created_Units, emit a warning to say the we ignore duplicate SCOs @@ -1370,7 +1370,7 @@ package body SC_Obligations is Inst_Id'Read (S, V.Last_Instance); SFI_Vector'Read (S, V.Deps); Boolean'Read (S, V.Has_Code); - SCOs_Hash'Read (S, V.Fingerprint); + Fingerprint_Type'Read (S, V.Fingerprint); -- Checkpoint version 8 preprocessing information @@ -1439,7 +1439,7 @@ package body SC_Obligations is Inst_Id'Write (S, V.Last_Instance); SFI_Vector'Write (S, V.Deps); Boolean'Write (S, V.Has_Code); - SCOs_Hash'Write (S, V.Fingerprint); + Fingerprint_Type'Write (S, V.Fingerprint); SCO_PP_Info_Maps.Map'Write (S, V.PP_Info_Map); @@ -2578,7 +2578,7 @@ package body SC_Obligations is -- Fingerprint -- ----------------- - function Fingerprint (CU : CU_Id) return SCOs_Hash is + function Fingerprint (CU : CU_Id) return Fingerprint_Type is begin return CU_Vector.Reference (CU).Fingerprint; end Fingerprint; @@ -2891,7 +2891,7 @@ package body SC_Obligations is function Allocate_CU (Provider : SCO_Provider; Origin, Main_Source : Source_File_Index; - Fingerprint : SCOs_Hash; + Fingerprint : Fingerprint_Type; Created_Units : in out Created_Unit_Maps.Map) return CU_Id is use Created_Unit_Maps; @@ -3332,7 +3332,7 @@ package body SC_Obligations is First_SCO : constant SCO_Id := SCO_Vector.Last_Index + 1; First_Instance : constant Inst_Id := Inst_Vector.Last_Index + 1; - Fingerprint : constant SCOs_Hash := SCOs_Hash + Fingerprint : constant Fingerprint_Type := Fingerprint_Type (GNAT.SHA1.Binary_Message_Digest' (GNAT.SHA1.Digest (Info.Fingerprint_Context))); diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 352b9f9ef..ca9acd43f 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -97,9 +97,9 @@ package SC_Obligations is function Provider (CU : CU_Id) return SCO_Provider; -- Return the SCO provider corresponding to the given compilation unit - type SCOs_Hash is new GNAT.SHA1.Binary_Message_Digest; + type Fingerprint_Type is new GNAT.SHA1.Binary_Message_Digest; - function Fingerprint (CU : CU_Id) return SCOs_Hash; + function Fingerprint (CU : CU_Id) return Fingerprint_Type; -- Hash of SCO info in ALI, for incremental coverage consistency check function Comp_Unit (Src_File : Source_File_Index) return CU_Id; diff --git a/tools/gnatcov/traces_source.ads b/tools/gnatcov/traces_source.ads index 1227a60b7..208a26bb3 100644 --- a/tools/gnatcov/traces_source.ads +++ b/tools/gnatcov/traces_source.ads @@ -244,7 +244,7 @@ package Traces_Source is Bit_Buffer_Encoding : Any_Bit_Buffer_Encoding; -- Encoding used to represent statement and decision coverage buffers - Fingerprint : Buffers.SCOs_Hash; + Fingerprint : Buffers.Fingerprint_Type; -- Hash of SCO info for this unit. Useds a fast way to check that -- coverage obligations and coverage data are consistent. Specific hash -- values are computed during instrumentation. From 07bb56913f9d54258ef1fe7a0005c293f07d84d0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Nov 2022 14:46:24 +0000 Subject: [PATCH 0069/1483] rts: minor refactorings Change-Id: I22cbf1577675d63b5fc8324112db635c4ab1f8a6 --- tools/gnatcov/rts/gnatcov_rts_c-traces-output.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces.h | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index 537a30bbb..c692ad556 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -127,7 +127,7 @@ write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, header.unit_part = (uint8_t) buffers->unit_part; header.bit_buffer_encoding = GNATCOV_RTS_LSB_FIRST_BYTES; memset (header.padding, 0, 5); - memcpy (&(header.fingerprint), buffers->fingerprint, FINGERPRINT_SIZE); + memcpy (&header.fingerprint, buffers->fingerprint, FINGERPRINT_SIZE); write_bytes (output, (char *) &header, sizeof (header)); write_bytes (output, buffers->unit_name.str, buffers->unit_name.length); diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces.h b/tools/gnatcov/rts/gnatcov_rts_c-traces.h index 7342e1eba..bab0b7ec5 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces.h @@ -97,16 +97,16 @@ extern "C" /* Trace entry header - Each trace entry starts with the following header. Then goes: + Each trace entry starts with the following header. Then goes: - * The name of the unit describes. It is NUL-padded according to the - trace file alignment. + * The name of the unit describes. It is NUL-padded according to the trace + file alignment. - * The statement coverage buffer. It is also NUL-padded. + * The statement coverage buffer. It is also NUL-padded. - * The decision coverage buffer. It is also NUL-padded. + * The decision coverage buffer. It is also NUL-padded. - * The MC/DC coverage buffer. It is also NUL-padded. */ + * The MC/DC coverage buffer. It is also NUL-padded. */ struct trace_entry_header { From 4af84a4fe6f9b04ed7bfaa10c9daae8810a0760b Mon Sep 17 00:00:00 2001 From: Leo Creuse Date: Mon, 10 Oct 2022 17:12:18 +0200 Subject: [PATCH 0070/1483] Add new Ada main autodump instrumentation schemes The current autodump instrumentation scheme introduces a nested scope in the main, containing the original main's declarations and statements, which is incompatible with the presence of subprogram stubs in the main. This change modifies the autodump instrumentation shceme as follows: - For atexit and ravenscar-task-termination, the procedure registering the buffer dump callback is now transformed into a function, which is used to initialize a dummy variable declaration inserted as first declaration in the main. This removes the need for a nested scope for those two dump methods. - For main-end, there are now two instrumentation schemes depending on the capabilities of the runtime. If finalization is available in the configured runtime, the buffer dump procedure is called by the finalization of a controlled object declared first in the main's declarative part. If the runtime doesn't provide support for finalization, then calls to the Dump_Buffer procedure are inserted at each exit point of the main (last statement of the top-level handeled statements, last statement of each exception handler branch and before each return statement). In the case where finalization is not supported by the runtime, but tasks are, there is no main-end dump method that works with all constructs and still permits coverage of code in tasks depending on the main. In such circumstances, the selected dump trigger is changed to ravenscar-task-termination. The feature availability checks for the runtime are implemented by checking the presence of the required units for each dump trigger in the runtime sources. We additionnaly check that there aren't any configuration pragmas restricting the use of finalization when instrumenting the main. Change-Id: Id1f8737b737a26b1cef5e825eb3f94914afdb96a TN: V905-005 --- tools/gnatcov/instrument-ada_unit.adb | 743 +++++++++++++++++++------- tools/gnatcov/instrument-common.adb | 3 + tools/gnatcov/instrument-common.ads | 11 +- tools/gnatcov/project.adb | 48 ++ tools/gnatcov/project.ads | 9 + 5 files changed, 604 insertions(+), 210 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index a77c1e34a..f80721843 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -42,6 +42,7 @@ with Files_Table; use Files_Table; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Namet; use Namet; with Outputs; use Outputs; +with Project; with SCOs; with Slocs; with Snames; use Snames; @@ -239,6 +240,9 @@ package body Instrument.Ada_Unit is -- Return a symbol from Symbols corresponding to the name of the given -- P pragma. + function Canonically_Equal (Left, Right : Text_Type) return Boolean; + -- Returns whether Left and Right are equal after canonicalization + function Aspect_Assoc_Name (A : Aspect_Assoc) return Identifier; function Aspect_Assoc_Name (A : Aspect_Assoc) return Symbol_Type; function Aspect_Assoc_Name (A : Aspect_Assoc) return Name_Id; @@ -281,13 +285,6 @@ package body Instrument.Ada_Unit is -- Wrapper around E.P_Expression_Type, logging a warning and returning -- Standard.Boolean if unable to determine the type. - function Referenced_Defining_Name - (Main_Name : Ada_Qualified_Name; - N : LAL.Name) return Defining_Name; - -- Wrapper around Name.P_Referenced_Defining_Name, logging a warning and - -- returning No_Defining_Name if unable to determine the referenced - -- defining name. - function Is_Static_Expr (E : Expr) return Boolean; -- Wrapper around E.P_Is_Static_Expr, logging a warning and returning -- False if unable to determine whether the expression is static. @@ -943,6 +940,62 @@ package body Instrument.Ada_Unit is -- generated is a primitive of a tagged type, and if that tagged type is -- the return type of the expression function. + function Has_Matching_Pragma_For_Unit + (IC : Inst_Context; + Unit : Compilation_Unit; + Filter : access function (Node : Pragma_Node) return Boolean) + return Boolean; + -- Return whether Filter return True on at least one configuration pragma + -- that applies to Unit or system.ads. + + Unusable_System_Reported : Boolean := False; + -- Global variable set to True once gnatcov emits a warning about a failure + -- to get the analysis unit for System. Used to avoid emitting duplicate + -- messages. + + function Pragma_Restricts_Finalization + (Prag_Node : Pragma_Node) return Boolean; + -- Return True if Prag_Node imposes a restrictions on use of finalization + + function Finalization_Restricted_In_Unit + (IC : Inst_Context; Unit : Compilation_Unit) return Boolean; + -- Return True if Finalization is not available in this runtime, or if + -- some control pragma restricts the usage of finalization in either Unit + -- or the whole project. + + function Pragma_Prevents_Task_Termination + (Prag_Node : Pragma_Node) return Boolean; + -- Return True if Node prevents the use of tasks and/or + -- Ada.Task_Termination and/or Ada.Task_Identification. + + function Task_Termination_Restricted + (IC : Inst_Context; Unit : Compilation_Unit) return Boolean; + -- Return True if tasking is not available in this runtime, or if some + -- configuration pragma prevents the use of tasks and/or + -- Ada.Task_Termination and/or Ada.Task_Identification in either the whole + -- project or in Unit. + + function Return_From_Subp_Body + (Ret_Node : Return_Stmt; Subp : Subp_Body) return Boolean; + -- Return whether Ret_Node is returning from Subp + + procedure Insert_Simple_Dump_Proc_Calls + (RH : Rewriting_Handle; + Helper_Unit : Ada_Qualified_Name; + Subp_Body : LAL.Subp_Body); + -- Insert calls, in Subp_Body, to the .Dump_Buffers procedure + -- as the last statment of the top level handeled statments of the main, as + -- the last statement of each exception handler branch, and right before + -- each return statment returning from the main procedure. + + procedure Insert_Controlled_Dump_Object_Decl + (RH : Rewriting_Handle; + Helper_Unit : Ada_Qualified_Name; + Subp_Body : LAL.Subp_Body); + -- Insert, in Subp_Body, the declaration of a controlled object of type + -- .Dump_Controlled_Type to dump the coverage buffers during + -- finalization of said object. + -------------------------------- -- Instrumentation extensions -- -------------------------------- @@ -1001,14 +1054,22 @@ package body Instrument.Ada_Unit is -- Emit the unit to contain addresses for the coverage buffers procedure Emit_Dump_Helper_Unit - (IC : Inst_Context; - Info : in out Project_Info; - Main : Compilation_Unit_Name; - Helper_Unit : out Ada_Qualified_Name); + (IC : Inst_Context; + Info : in out Project_Info; + Main : Compilation_Unit_Name; + Helper_Unit : out Ada_Qualified_Name; + Override_Dump_Trigger : Any_Dump_Trigger := Manual; + Has_Controlled : Boolean := False); -- Emit the unit to contain helpers to implement the automatic dump of -- coverage buffers for the given Main unit. Info must be the project that -- owns this main. Upon return, the name of this helper unit is stored in -- Helper_Unit. + -- + -- If Override_Dump_Trigger is anything other than Manual, it will be used + -- as a dump trigger instead of the one defined in IC.Dump_Config. + -- + -- If Has_Controlled is True, generate a controlled type for which the + -- Finalize procedure calls the buffer dump procedure. ---------------- -- Convert_To -- @@ -2349,6 +2410,74 @@ package body Instrument.Ada_Unit is return False; end Return_Type_Is_Controlling; + --------------------------- + -- Return_From_Subp_Body -- + --------------------------- + + function Return_From_Subp_Body + (Ret_Node : Return_Stmt; Subp : Subp_Body) return Boolean + is + function Subp_Body_Is_Parent_Decl (Node : Ada_Node'Class) return Boolean; + -- Return True if Subp is the first body in the chain of parent + -- declarations of Node. + + ------------------------------ + -- Subp_Body_Is_Parent_Decl -- + ------------------------------ + + function Subp_Body_Is_Parent_Decl (Node : Ada_Node'Class) return Boolean + is + Parent_Basic_Decl : constant Basic_Decl := Node.P_Parent_Basic_Decl; + -- Parent Basic_Decl of Ret_Node + begin + if Parent_Basic_Decl.Is_Null then + return False; + end if; + case Parent_Basic_Decl.Kind is + when Ada_Subp_Body_Range => + return Parent_Basic_Decl.As_Subp_Body = Subp; + + when Ada_Accept_Stmt + | Ada_Accept_Stmt_With_Stmts + | Ada_Entry_Body => + + -- A return statment may only appear within a callable + -- construct (RM 6.5 (4/2)), which are either subprogram + -- bodies, entry bodies or accept statements (RM 6.2)). As + -- Subp is a Subp_Body if we encounter an accept statement + -- or an entry body on the way we can't be returning from + -- Subp. + + return False; + when others => + return Subp_Body_Is_Parent_Decl (Parent_Basic_Decl); + end case; + end Subp_Body_Is_Parent_Decl; + + -- Start of processing for Return_From_Body + + begin + return Subp_Body_Is_Parent_Decl (Ret_Node); + exception + when Exc : Property_Error => + Report + (Node => Ret_Node, + Msg => "Unable to determine to which body this return statment" + & "applies: " & Ada.Exceptions.Exception_Information (Exc), + Kind => Low_Warning); + + -- Inserting an extranous Dump_Buffer call isn't really a problem + -- as, at best the trace dump generated too early will be overwritten + -- by the trace dump happening at the main end, and at worst, + -- multiple trace files will coexist, and passing both to gnatcov + -- will result in the same coverage results as ony passing the trace + -- file that was created when dumping the buffers at the actual end + -- of the main. We can thus conservatively return True if some + -- property call fails. + + return True; + end Return_From_Subp_Body; + ----------------------------------------- -- Traverse_Declarations_Or_Statements -- ----------------------------------------- @@ -5725,6 +5854,21 @@ package body Instrument.Ada_Unit is end Safe_Is_Ghost; + ----------------------- + -- Canonically_Equal -- + ----------------------- + + function Canonically_Equal (Left, Right : Text_Type) return Boolean is + Canonical_Left : constant Symbolization_Result := Canonicalize (Left); + Canonical_Right : constant Symbolization_Result := Canonicalize (Right); + begin + -- If canonicalization failed for one of the two text types, assume they + -- are different. + + return Canonical_Left.Success + and then Canonical_Left = Canonical_Right; + end Canonically_Equal; + ----------------------- -- Aspect_Assoc_Name -- ----------------------- @@ -5838,44 +5982,6 @@ package body Instrument.Ada_Unit is end if; end Expression_Type; - ------------------------------ - -- Referenced_Defining_Name -- - ------------------------------ - - function Referenced_Defining_Name - (Main_Name : Ada_Qualified_Name; - N : LAL.Name) return Defining_Name - is - DF : Defining_Name; - begin - begin - DF := N.P_Referenced_Defining_Name; - - if DF.Is_Null then - Report - (N, - "Failed to determine referenced defining name while " - & "processing the main " & To_Ada (Main_Name) & " (got null " - & "defining name)", - Warning); - end if; - - exception - when Exc : Property_Error => - Report - (N, - "Failed to determine referenced defining name while " - & "processing the main " & To_Ada (Main_Name) & ": " - & Ada.Exceptions.Exception_Information (Exc), - Warning); - end; - if not DF.Is_Null then - return DF; - else - return No_Defining_Name; - end if; - end Referenced_Defining_Name; - -------------------- -- Is_Static_Expr -- -------------------- @@ -6044,6 +6150,280 @@ package body Instrument.Ada_Unit is end; end Initialize_Rewriting; + ---------------------------- + -- Insert_Dump_Proc_Calls -- + ---------------------------- + + procedure Insert_Simple_Dump_Proc_Calls + (RH : Rewriting_Handle; + Helper_Unit : Ada_Qualified_Name; + Subp_Body : LAL.Subp_Body) + is + -- Simply add a call to the buffer dump procedure at the end of + -- the top level statement list, as well as at the end of the + -- statement list of each top level exception handler, and + -- right before each return statment that applies to the main. + + Dump_Procedure : Ada_Qualified_Name; + -- Name of the procedure to dump coverage buffers + + Call_Stmt : Node_Rewriting_Handle; + -- Call invoking the dump procedure + + function Process_Returns + (Node : Ada_Node'Class) return Visit_Status; + -- Helper for LAL's Traverse procedure. If node is a return + -- statement that returns from the main, insert a call to the + -- dump buffer procedure right before. + + --------------------- + -- Process_Returns -- + --------------------- + + function Process_Returns (Node : Ada_Node'Class) return Visit_Status is + begin + if Node.Kind in Ada_Return_Stmt + and then Return_From_Subp_Body + (Node.As_Return_Stmt, Subp_Body) + then + -- Child_Index is 0 based whereas Insert_Child is 1 based + + Insert_Child + (Handle (Node.Parent), + Node.Child_Index + 1, + Clone (Call_Stmt)); + return Over; + else + return Into; + end if; + end Process_Returns; + + Handled_Stmt_List : constant Node_Rewriting_Handle := + Handle (Subp_Body.F_Stmts.F_Stmts); + + -- Start of processing for Insert_Simple_Dump_Proc_Calls + + begin + Dump_Procedure := Helper_Unit; + Dump_Procedure.Append (Dump_Procedure_Name); + Call_Stmt := Create_Regular_Node + (RH, Ada_Call_Stmt, (1 => To_Nodes (RH, Dump_Procedure))); + + -- Add a Dump_Buffer call at the end of the main's handeled statements + + Append_Child (Handled_Stmt_List, Call_Stmt); + + -- Add a Dump_Buffer call before any return statement that returns from + -- the main. + + Traverse (Subp_Body, Process_Returns'Access); + + if Is_Null (Subp_Body.F_Stmts.F_Exceptions) then + return; + end if; + + -- Add a Dump_Buffer call as the last statement of each exception + -- handler branch. + + for Node of Subp_Body.F_Stmts.F_Exceptions loop + if Node.Kind in Ada_Exception_Handler_Range then + declare + Exn_Handler : constant Exception_Handler := + Node.As_Exception_Handler; + Exn_Stmt_List : constant Node_Rewriting_Handle := + Handle (Exn_Handler.F_Stmts); + begin + Append_Child (Exn_Stmt_List, Clone (Call_Stmt)); + end; + end if; + end loop; + end Insert_Simple_Dump_Proc_Calls; + + -------------------------------------- + -- Insert_Controlled_Dump_Proc_Call -- + -------------------------------------- + + procedure Insert_Controlled_Dump_Object_Decl + (RH : Rewriting_Handle; + Helper_Unit : Ada_Qualified_Name; + Subp_Body : LAL.Subp_Body) + is + -- Declare an object of the type .Dump_Controlled_Type + -- which will call the procedure Dump_Buffers when finalized. + + Controlled_Type_Name : Ada_Qualified_Name := Helper_Unit; + Dump_Object_Decl : Node_Rewriting_Handle; + Decl_List : constant Node_Rewriting_Handle := + Handle (Subp_Body.F_Decls.F_Decls); + begin + Controlled_Type_Name.Append + (To_Unbounded_String ("Dump_Controlled_Type")); + Dump_Object_Decl := Create_From_Template + (RH, + "GNATcov_Dump_Object : {};", + (1 => To_Nodes (RH, Controlled_Type_Name)), + Object_Decl_Rule); + + -- Insert the declaration as the first declaration in the + -- list to ensure it is finalized last. + + Insert_Child (Decl_List, 1, Dump_Object_Decl); + end Insert_Controlled_Dump_Object_Decl; + + ---------------------------------- + -- Has_Matching_Pragma_For_Unit -- + ---------------------------------- + + function Has_Matching_Pragma_For_Unit + (IC : Inst_Context; + Unit : Compilation_Unit; + Filter : access function (Node : Pragma_Node) return Boolean) + return Boolean + is + System_Unit : constant Analysis_Unit := + IC.Context.Get_From_Provider ("System", Unit_Specification); + Unit_Pragmas : constant Pragma_Node_Array := + Unit.P_All_Config_Pragmas + & (if System_Unit.Has_Diagnostics + then Pragma_Node_Array'(1 .. 0 => No_Pragma_Node) + else System_Unit.Root.As_Compilation_Unit.P_All_Config_Pragmas); + -- Configuration pragmas that apply to Unit. Also append the list of + -- configuration pragmas defined in System as they often define the set + -- of restrictions associated with the runtime. + + begin + if not Unusable_System_Reported and then System_Unit.Has_Diagnostics + then + Diagnostics.Report + (Msg => "Could not parse the System unit for the runtime," + & " instrumentation of mains may be incorrect:", + Kind => Low_Warning); + for Diag of System_Unit.Diagnostics loop + Diagnostics.Report + (Msg => System_Unit.Format_GNU_Diagnostic (Diag), + Kind => Low_Warning); + end loop; + Unusable_System_Reported := True; + end if; + for Prag_Node of Unit_Pragmas loop + if Filter.all (Prag_Node) then + return True; + end if; + end loop; + return False; + + end Has_Matching_Pragma_For_Unit; + + ----------------------------------- + -- Pragma_Restricts_Finalization -- + ----------------------------------- + + function Pragma_Restricts_Finalization + (Prag_Node : Pragma_Node) return Boolean + is + begin + -- We are looking for pragmas of the form: + -- pragma Restrictions (No_Finalization); + -- or + -- pragma Restriction (No_Dependence => Ada.Finalization); + + if Canonically_Equal (Prag_Node.F_Id.Text, "Restrictions") then + for Assoc of Prag_Node.F_Args loop + declare + Prag_Assoc : constant Pragma_Argument_Assoc := + Assoc.As_Pragma_Argument_Assoc; + begin + if not Prag_Assoc.F_Name.Is_Null + and then + (Canonically_Equal + (Prag_Assoc.F_Name.Text, "No_Finalization") + or else + (Canonically_Equal + (Prag_Assoc.F_Name.Text, "No_Dependence") + and then Canonically_Equal (Prag_Assoc.F_Expr.Text, + "Ada.Finalization"))) + then + return True; + end if; + end; + end loop; + end if; + return False; + end Pragma_Restricts_Finalization; + + ------------------------------------- + -- Finalization_Restricted_In_Unit -- + ------------------------------------- + + function Finalization_Restricted_In_Unit + (IC : Inst_Context; Unit : Compilation_Unit) return Boolean + is + begin + if not Project.Runtime_Supports_Finalization then + return True; + end if; + return Has_Matching_Pragma_For_Unit + (IC, Unit, Pragma_Restricts_Finalization'Access); + end Finalization_Restricted_In_Unit; + + -------------------------------------- + -- Pragma_Prevents_Task_Termination -- + -------------------------------------- + + function Pragma_Prevents_Task_Termination + (Prag_Node : Pragma_Node) return Boolean + is + begin + -- We are looking for pragmas of the form: + -- pragma Restrictions (No_Tasking); + -- or + -- pragma Restriction (No_Dependence => Ada.Task_Termination); + -- or + -- pragma Restriction (No_Depenence => Ada.Task_Identification); + + if Canonically_Equal (Prag_Node.F_Id.Text, "Restrictions") then + for Assoc of Prag_Node.F_Args loop + declare + Prag_Assoc : constant Pragma_Argument_Assoc := + Assoc.As_Pragma_Argument_Assoc; + begin + if not Prag_Assoc.F_Name.Is_Null + and then + (Canonically_Equal + (Prag_Assoc.F_Name.Text, "No_Finalization") + or else + (Canonically_Equal + (Prag_Assoc.F_Name.Text, "No_Dependence") + and then + (Canonically_Equal (Prag_Assoc.F_Expr.Text, + "Ada.Task_Termination") + or else + Canonically_Equal (Prag_Assoc.F_Expr.Text, + "Ada.Task_Identification")))) + then + return True; + end if; + end; + end loop; + end if; + return False; + end Pragma_Prevents_Task_Termination; + + --------------------------------- + -- Task_Termination_Restricted -- + --------------------------------- + + function Task_Termination_Restricted + (IC : Inst_Context; Unit : Compilation_Unit) return Boolean + is + begin + if not Project.Runtime_Supports_Task_Termination then + return False; + end if; + return Has_Matching_Pragma_For_Unit + (IC, Unit, Pragma_Prevents_Task_Termination'Access); + end Task_Termination_Restricted; + ------------------------------- -- Auto_Dump_Buffers_In_Main -- ------------------------------- @@ -6054,8 +6434,6 @@ package body Instrument.Ada_Unit is Main : Compilation_Unit_Name; URH : Unit_Rewriting_Handle) is - No_Node : Node_Rewriting_Handle renames No_Node_Rewriting_Handle; - U : constant Analysis_Unit := Unit (URH); RH : constant Rewriting_Handle := Handle (U.Context); Tmp : LAL.Ada_Node := U.Root; @@ -6063,12 +6441,11 @@ package body Instrument.Ada_Unit is CU : LAL.Compilation_Unit; Subp_Body : LAL.Subp_Body; - Old_Stmts, New_Stmts : Node_Rewriting_Handle; + Controlled_Types_Available : Boolean; - New_Stmt_List : constant Node_Rewriting_Handle := - Create_Node (RH, Ada_Stmt_List); - -- List of statements to contain 1) the original handled statements - -- (Old_Stmts) and 2) the call to the Write_Trace_File procedure. + Actual_Dump_Trigger : Auto_Dump_Trigger; + -- Resolved dump trigger after eventual override depending on the + -- features available on the runtime. Instr_Units : constant CU_Name_Vectors.Vector := Instr_Units_For_Closure (IC, Main); @@ -6104,9 +6481,25 @@ package body Instrument.Ada_Unit is Subp_Body := Tmp.As_Subp_Body; end if; + Controlled_Types_Available := + not Finalization_Restricted_In_Unit (IC, CU); + + Actual_Dump_Trigger := + (if IC.Dump_Config.Trigger = Main_End + and then not Controlled_Types_Available + and then not Task_Termination_Restricted (IC, CU) + then Ravenscar_Task_Termination + else IC.Dump_Config.Trigger); + -- Emit the helper unit and add a WITH clause for it - Emit_Dump_Helper_Unit (IC, Info, Main, Helper_Unit); + Emit_Dump_Helper_Unit + (IC, + Info, + Main, + Helper_Unit, + Override_Dump_Trigger => Actual_Dump_Trigger, + Has_Controlled => Controlled_Types_Available); declare Prelude : constant Node_Rewriting_Handle := Handle (CU.F_Prelude); @@ -6138,152 +6531,61 @@ package body Instrument.Ada_Unit is Append_Child (Prelude, Runtime_Version_Check_Node); end; - -- Wrap the previous subprogram body content (declarations, handled - -- statements) in a declare block. This is a simple handled statements - -- block if there is no declaration. - - declare - New_Excs : constant Node_Rewriting_Handle := - Create_Node (RH, Ada_Ada_Node_List); - - Nested_Block : Node_Rewriting_Handle; - Nested_Decls : Node_Rewriting_Handle; - - Main_Name : constant LAL.Defining_Name := - Subp_Body.F_Subp_Spec.F_Subp_Name; - Block_Name : constant Node_Rewriting_Handle := - Create_Identifier (RH, "GNATcov_Original_Main"); - - function Replace_FQNs - (Node : LAL.Ada_Node'Class) return Visit_Status; - -- Callback for Libadalang's Traverse. If Node is a dotted name whose - -- prefix refers to Main, rewrite the prefix to refer to the named - -- block we create here. - - ----------------- - -- Replace_FQN -- - ----------------- - - function Replace_FQNs - (Node : LAL.Ada_Node'Class) return Visit_Status - is - Name : Dotted_Name; - begin - if Node.Kind /= Ada_Dotted_Name then - return Into; - end if; - Name := Node.As_Dotted_Name; - if Referenced_Defining_Name (Main.Unit, Name.F_Prefix) = Main_Name - then - declare - Old_Prefix : constant Node_Rewriting_Handle := - Handle (Name.F_Prefix); - New_Node : constant Node_Rewriting_Handle := - Create_Regular_Node - (RH, - Ada_Dotted_Name, - (No_Node_Rewriting_Handle, - Clone (Block_Name))); - begin - Replace (Old_Prefix, New_Node); - Set_Child (Handle => New_Node, - Index => 1, - Child => Old_Prefix); - return Over; - end; - end if; - return Into; - end Replace_FQNs; - - begin - -- Extract the original statements (Old_Stmts) and replace it in the - -- subprogram body with the new statements. - - Old_Stmts := Handle (Subp_Body.F_Stmts); - New_Stmts := Create_Regular_Node - (RH, Ada_Handled_Stmts, (New_Stmt_List, New_Excs)); - Replace (Old_Stmts, New_Stmts); - - -- If the original subprogram has declarations or exception handlers, - -- wrap the original statements in a named block to hold them. - - if Subp_Body.F_Decls.F_Decls.Children_Count = 0 - and then Subp_Body.F_Stmts.F_Exceptions.Children_Count = 0 - then - Nested_Block := Old_Stmts; - else - Nested_Decls := Handle (Subp_Body.F_Decls); - Replace - (Nested_Decls, - Create_Regular_Node - (RH, Ada_Declarative_Part, - (1 => Create_Node (RH, Ada_Ada_Node_List)))); - - Nested_Block := Create_Named_Stmt - (RH, - F_Decl => Create_Named_Stmt_Decl - (RH, Create_Defining_Name (RH, Clone (Block_Name)), No_Node), - F_Stmt => Create_Decl_Block - (RH, - F_Decls => Nested_Decls, - F_Stmts => Old_Stmts, - F_End_Name => Clone (Block_Name))); - - -- Change the Qualified names in the Main's declarations and - -- statements to be compatible ith the new nested block. - Subp_Body.F_Stmts.Traverse (Replace_FQNs'Access); - Subp_Body.F_Decls.Traverse (Replace_FQNs'Access); - - end if; - Append_Child (New_Stmt_List, Nested_Block); - end; - -- Depending on the chosen coverage buffers dump trigger, insert the -- appropriate code. - case Auto_Dump_Trigger (IC.Dump_Config.Trigger) is + case Actual_Dump_Trigger is when At_Exit | Ravenscar_Task_Termination => - -- Build the call to the registration procedure and insert it in - -- New_Stmt_List, right before the old list of statements. + -- Build the call to the registration function and insert it in + -- the main's declarative part, right before the first declaration. declare - Register_Procedure : Ada_Qualified_Name; - -- Name of the procedure to register the coverage buffers dump + Register_Function : Ada_Qualified_Name; + -- Name of the function to register the coverage buffers dump -- routine. - Call_Stmt : Node_Rewriting_Handle; - + Call_Expr : Node_Rewriting_Handle; + Call_Decl : Node_Rewriting_Handle; + Decl_List : constant Node_Rewriting_Handle := + Handle (Subp_Body.F_Decls.F_Decls); begin - Register_Procedure := Helper_Unit; - Register_Procedure.Append (Register_Dump_Procedure_Name); + Register_Function := Helper_Unit; + Register_Function.Append (Register_Dump_Function_Name); + Call_Expr := To_Nodes (RH, Register_Function); - Call_Stmt := Create_Regular_Node - (RH, Ada_Call_Stmt, (1 => To_Nodes (RH, Register_Procedure))); - Insert_Child (New_Stmt_List, 1, Call_Stmt); + Call_Decl := Create_From_Template + (RH, + "Autodump_Dummy : {} := {};", + (1 => To_Nodes (RH, Witness_Dummy_Type_Name), 2 => Call_Expr), + Object_Decl_Rule); + Insert_Child (Decl_List, 1, Call_Decl); end; when Main_End => - -- Build the call to the dump procedure and append it to - -- New_Stmt_List, right after the old list of statements. - - declare - Dump_Procedure : Ada_Qualified_Name; - -- Name of the procedure to dump coverage buffers - - Call_Stmt : Node_Rewriting_Handle; - - begin - Dump_Procedure := Helper_Unit; - Dump_Procedure.Append (Dump_Procedure_Name); - - Call_Stmt := Create_Regular_Node - (RH, Ada_Call_Stmt, (1 => To_Nodes (RH, Dump_Procedure))); - Append_Child (New_Stmt_List, Call_Stmt); - end; + -- For Main_End we have three instrumentation schemes depending on + -- the availability of tasks and controlled types: + -- + -- - If controlled types are available use a controlled object to + -- dump the buffers as part of its finalization. + -- + -- - If controlled types are unavailable but task types are, then + -- use the Ravenscar_Task_Termination dump trigger as we otherwise + -- have no instrumentation method that works with all code + -- constructs. In that case, Actuall_Dump_Trigger is set to + -- Ravenscar_Task_Termination and we should not reach this part of + -- the code. + -- + -- - If we do not have finalization or tasks then simply insert calls + -- right before all the exit points of the main. + if not Finalization_Restricted_In_Unit (IC, CU) then + Insert_Controlled_Dump_Object_Decl (RH, Helper_Unit, Subp_Body); + else + Insert_Simple_Dump_Proc_Calls (RH, Helper_Unit, Subp_Body); + end if; end case; end Auto_Dump_Buffers_In_Main; @@ -6870,10 +7172,12 @@ package body Instrument.Ada_Unit is --------------------------- procedure Emit_Dump_Helper_Unit - (IC : Inst_Context; - Info : in out Project_Info; - Main : Compilation_Unit_Name; - Helper_Unit : out Ada_Qualified_Name) + (IC : Inst_Context; + Info : in out Project_Info; + Main : Compilation_Unit_Name; + Helper_Unit : out Ada_Qualified_Name; + Override_Dump_Trigger : Any_Dump_Trigger := Manual; + Has_Controlled : Boolean := False) is File : Text_Files.File_Type; @@ -6893,9 +7197,11 @@ package body Instrument.Ada_Unit is -- Qualified names for the unit that contains the buffer output -- procedure, and for the procedure itself. - Dump_Trigger : constant Auto_Dump_Trigger := IC.Dump_Config.Trigger; - -- Shortcut to avoid repeatedly restricting the dump trigger to the - -- Auto_Dump_Trigger subtype. + Dump_Trigger : constant Auto_Dump_Trigger := + (if Override_Dump_Trigger = Manual + then IC.Dump_Config.Trigger + else Override_Dump_Trigger); + -- Resolved dump trigger -- Start of processing for Emit_Dump_Helper_Unit @@ -6941,20 +7247,33 @@ package body Instrument.Ada_Unit is Switches.Ada_Language)); Put_Warnings_And_Style_Checks_Pragmas (File); + Put_With (Sys_Buffers); + if Dump_Trigger = Main_End and then Has_Controlled then + File.Put_Line ("with Ada.Finalization;"); + end if; File.Put_Line ("package " & Helper_Unit_Name & " is"); File.New_Line; File.Put_Line (" procedure " & Dump_Procedure & ";"); File.Put_Line (" pragma Convention (C, " & Dump_Procedure & ");"); + File.New_Line; case Dump_Trigger is when At_Exit | Ravenscar_Task_Termination => File.Put_Line - ("procedure " - & To_String (Register_Dump_Procedure_Name) & ";"); + ("function " + & To_String (Register_Dump_Function_Name) & " return " + & To_Ada (Witness_Dummy_Type_Name) & ";"); File.New_Line; when Main_End => - null; + if Has_Controlled then + File.Put_Line (" type Dump_Controlled_Type is new" + & " Ada.Finalization.Controlled with"); + File.Put_Line (" null record;"); + File.Put_Line (" overriding procedure Finalize (Self : in" + & " out Dump_Controlled_Type);"); + File.New_Line; + end if; end case; File.Put_Line ("end " & Helper_Unit_Name & ";"); @@ -7053,16 +7372,17 @@ package body Instrument.Ada_Unit is File.Put_Line (" end " & Dump_Procedure & ";"); File.New_Line; - -- Emit trigger-specific procedures + -- Emit trigger-specific subprograms case Dump_Trigger is when At_Exit => - -- Emit a procedure to schedule a trace dump with atexit + -- Emit a function to schedule a trace dump with atexit File.Put_Line - ("procedure " - & To_String (Register_Dump_Procedure_Name) & " is"); + ("function " + & To_String (Register_Dump_Function_Name) & " return " + & To_Ada (Witness_Dummy_Type_Name) & " is"); File.Put_Line (" type Callback is access procedure;"); File.Put_Line (" pragma Convention (C, Callback);"); File.New_Line; @@ -7072,9 +7392,9 @@ package body Instrument.Ada_Unit is File.Put_Line (" Dummy : constant Interfaces.C.int :="); File.Put_Line (" atexit (" & Dump_Procedure & "'Access);"); File.Put_Line ("begin"); - File.Put_Line (" null;"); + File.Put_Line (" return (Data => False);"); File.Put_Line - ("end " & To_String (Register_Dump_Procedure_Name) & ";"); + ("end " & To_String (Register_Dump_Function_Name) & ";"); File.New_Line; when Ravenscar_Task_Termination => @@ -7096,22 +7416,31 @@ package body Instrument.Ada_Unit is File.Put_Line (" end Wrapper;"); File.New_Line; - -- Emit a procedure to schedule a trace dump with + -- Emit a function to schedule a trace dump with -- Ada.Task_Termination. File.Put_Line - ("procedure " - & To_String (Register_Dump_Procedure_Name) & " is"); + ("function " + & To_String (Register_Dump_Function_Name) & " return " + & To_Ada (Witness_Dummy_Type_Name)); File.Put_Line ("begin"); File.Put_Line (" Ada.Task_Termination" & ".Set_Dependents_Fallback_Handler" & " (Wrapper.Do_Dump'Access);"); + File.Put_Line (" return (Data => False);"); File.Put_Line - ("end " & To_String (Register_Dump_Procedure_Name) & ";"); + ("end " & To_String (Register_Dump_Function_Name) & ";"); File.New_Line; when Main_End => - null; + if Has_Controlled then + File.Put_Line (" overriding procedure Finalize (Self : in" + & " out Dump_Controlled_Type) is"); + File.Put_Line (" begin"); + File.Put_Line (" Dump_Buffers;"); + File.Put_Line (" end Finalize;"); + File.New_Line; + end if; end case; File.Put_Line ("end " & Helper_Unit_Name & ";"); diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 8b6503f9b..132c417c3 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -1006,4 +1006,7 @@ begin Decision_Buffer_Name.Append (To_Unbounded_String ("Decision_Buffer")); MCDC_Buffer_Name.Append (To_Unbounded_String ("MCDC_Buffer")); + Witness_Dummy_Type_Name := Sys_Buffers; + Witness_Dummy_Type_Name.Append (To_Unbounded_String ("Witness_Dummy_Type")); + end Instrument.Common; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 8d63791e3..8d5b3ba13 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -103,15 +103,20 @@ package Instrument.Common is -- Qualified name (relative to the unit buffer package) of the buffer to -- contain coverage data corresponding to decision BDD paths. + Witness_Dummy_Type_Name : Ada_Qualified_Name; + -- Qualified name for the type returned by the Witness function used for + -- declaration instrumentation. + Dump_Procedure_Name : constant Ada_Identifier := To_Unbounded_String ("Dump_Buffers"); -- Name of the procedure (in main dump helper packages) that dumps all -- coverage buffers to the source trace file. - Register_Dump_Procedure_Name : constant Ada_Identifier := + Register_Dump_Function_Name : constant Ada_Identifier := To_Unbounded_String ("Register_Dump_Buffers"); - -- Name of the procedure (in main dump helper packages) that registers the - -- coverage buffers dump through atexit(3). + -- Name of the function (in main dump helper packages) that registers the + -- coverage buffers dump through atexit(3) or through a task termination + -- handler. function Dump_Procedure_Symbol (Main : Compilation_Unit_Name) return String diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 2f7e717d3..a1e6a2b3c 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -226,6 +226,10 @@ package body Project is -- Note that this also returns source files for mains that are not units of -- interest. + function Runtime_Has_File (Filename : Filesystem_String) return Boolean; + -- Return whether Filename can be found among the sources of the + -- configured Ada runtime. + --------- -- "+" -- --------- @@ -656,6 +660,50 @@ package body Project is end; end Find_Source_File; + ---------------------- + -- Runtime_Has_File -- + ---------------------- + function Runtime_Has_File (Filename : Filesystem_String) return Boolean is + Result_File : Virtual_File; + -- Virtual_File for Ada.Finalization. Only search predefined sources. + Ambiguous : Boolean; + -- Required in the call for GNATCOLL.Projects.Create + begin + GNATCOLL.Projects.Create + (Self => Prj_Tree.all, + Name => Filename, + Use_Object_Path => False, + Ambiguous => Ambiguous, + File => Result_File, + Predefined_Only => True); + + -- We don't expect there to be multiple homonyms for the runtime files + + pragma Assert (not Ambiguous); + return Result_File /= No_File; + end Runtime_Has_File; + + ------------------------------ + -- Runtime_Has_Finalization -- + ------------------------------ + + function Runtime_Supports_Finalization return Boolean is + (Runtime_Has_File ("a-finali.ads")); + + --------------------------------------- + -- Runtime_Supports_Task_Termination -- + --------------------------------------- + + function Runtime_Supports_Task_Termination return Boolean is + begin + -- We need both Ada.Task_Identification (a-taside.ads) and + -- Ada.Task_Termination (a-taster.ads) to be able to use task + -- termination. + + return Runtime_Has_File ("a-taster.ads") + and then Runtime_Has_File ("a-taside.ads"); + end Runtime_Supports_Task_Termination; + ---------------- -- Initialize -- ---------------- diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 3460742b7..5b3b31c03 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -188,6 +188,15 @@ package Project is -- -- If no project is loaded, just return null. + function Runtime_Supports_Finalization return Boolean with + Pre => Is_Project_Loaded; + -- Return whether the configured runtime includes the Ada.Finalization unit + + function Runtime_Supports_Task_Termination return Boolean with + Pre => Is_Project_Loaded; + -- Return whether the configured runtime has necessary units to implement + -- the ravenscar-task-termination dump trigger. + function Switches (Op : String) return String_List_Access with Pre => Is_Project_Loaded; -- Return a list of gnatcov switches defined by the root project. Caller From 8104361b1be0e6839f4bc977ac495beb0ec67f23 Mon Sep 17 00:00:00 2001 From: Leo Creuse Date: Fri, 21 Oct 2022 14:59:00 +0200 Subject: [PATCH 0071/1483] SCOV/instr.py: Add new function returning the available dump triggers This makes writing tests meant to exercise the various main autodump instrumentation schemes easier. Change-Id: I0140b7abd11ae192b740a56b53c0edd94c9a5bdd TN: V905-005 --- testsuite/SCOV/instr.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 1579670f7..079207907 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -248,3 +248,15 @@ def filename(prefix, ext): with open(main_file, 'w') as f: f.write('\n'.join(lines)) + + +def available_ada_dump_triggers(): + """ + Return the list of dump triggers available for the current Ada runtime. + """ + if RUNTIME_INFO.has_full_runtime: + return ["main-end", "atexit"] + elif RUNTIME_INFO.has_ravenscar_runtime: + return ["main-end", "ravenscar-task-termination"] + else: + return ["main-end"] From 6069229208ab421ad9cba5ea1327fe8bb44d55a0 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 18 Nov 2022 23:58:10 +0100 Subject: [PATCH 0072/1483] Force compilation with g++ for C++ files As compilation with clang++ errors out, force the use of g++ as C++ compiler driver. TN: V816-018 Change-Id: Idbd971f996773b02fc0a3d0d59e11810bf714d13 --- tools/gnatcov/gnatcov.gpr | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 6a54b2336..4dba03a7a 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -94,6 +94,10 @@ project Gnatcov is for Local_Configuration_Pragmas use "gnat.adc"; + -- As we don't want to compile with clang++ (compilation of + -- clang-wrapper.cc errors out), force the use of g++. + + for Driver ("C++") use "g++"; end Compiler; package Linker is From c4970e21eec1f3b83b2f2d228e6ae03bc8286228 Mon Sep 17 00:00:00 2001 From: Leo Creuse Date: Wed, 23 Nov 2022 10:30:50 +0100 Subject: [PATCH 0073/1483] Main auto dump: Fix various errors Fix missing "is" in generated buffer dump procedure as well as a some wrong logic regarding the overriding of the dump trigger depending on the capabilities of the runtime. TN: V905-005 --- tools/gnatcov/instrument-ada_unit.adb | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index f80721843..cf4146c88 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6359,11 +6359,9 @@ package body Instrument.Ada_Unit is (IC : Inst_Context; Unit : Compilation_Unit) return Boolean is begin - if not Project.Runtime_Supports_Finalization then - return True; - end if; - return Has_Matching_Pragma_For_Unit - (IC, Unit, Pragma_Restricts_Finalization'Access); + return not Project.Runtime_Supports_Finalization + or else Has_Matching_Pragma_For_Unit + (IC, Unit, Pragma_Restricts_Finalization'Access); end Finalization_Restricted_In_Unit; -------------------------------------- @@ -6391,6 +6389,8 @@ package body Instrument.Ada_Unit is and then (Canonically_Equal (Prag_Assoc.F_Name.Text, "No_Finalization") + or else Canonically_Equal + (Prag_Assoc.F_Name.Text, "No_Tasking") or else (Canonically_Equal (Prag_Assoc.F_Name.Text, "No_Dependence") @@ -6417,11 +6417,9 @@ package body Instrument.Ada_Unit is (IC : Inst_Context; Unit : Compilation_Unit) return Boolean is begin - if not Project.Runtime_Supports_Task_Termination then - return False; - end if; - return Has_Matching_Pragma_For_Unit - (IC, Unit, Pragma_Prevents_Task_Termination'Access); + return not Project.Runtime_Supports_Task_Termination + or else Has_Matching_Pragma_For_Unit + (IC, Unit, Pragma_Prevents_Task_Termination'Access); end Task_Termination_Restricted; ------------------------------- @@ -7422,7 +7420,7 @@ package body Instrument.Ada_Unit is File.Put_Line ("function " & To_String (Register_Dump_Function_Name) & " return " - & To_Ada (Witness_Dummy_Type_Name)); + & To_Ada (Witness_Dummy_Type_Name) & " is"); File.Put_Line ("begin"); File.Put_Line (" Ada.Task_Termination" & ".Set_Dependents_Fallback_Handler" From 56e01140bfb73d6db6200007411eef872ca9c5a6 Mon Sep 17 00:00:00 2001 From: Leo Creuse Date: Mon, 24 Oct 2022 15:15:30 +0200 Subject: [PATCH 0074/1483] Use config pragmas when processing non short-circuit operators With this change, the configuration pragma Short_Circuit_And_Or is taken into account to determine if gnatcov should consider non short circuit boolean operators as short circuiting ones. The switch already in place to enable this behavior remains in place as it would allow a user to get MC/DC coverage on non-short circuit conditions without modifying the semantics of the code. TN: U621-005 --- tools/gnatcov/instrument-ada_unit.adb | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index cf4146c88..ceb009c8e 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6630,6 +6630,10 @@ package body Instrument.Ada_Unit is -- any witness calls for elaboration of declarations: they would be -- pointless (there is no elaboration code anyway) and, in any case, -- illegal. + + Has_Pragma_SCAO : Boolean; + -- Whether there is a pragma Short_Circuit_And_Or that applies to this + -- unit. begin Rewriter.Start_Rewriting (IC, Prj_Info, Filename); @@ -6660,10 +6664,22 @@ package body Instrument.Ada_Unit is Initialize_Rewriting (UIC, CU_Name, IC.Context); - -- ??? Modify this when libadalang can provide the information about - -- global/local configuration pragmas for Short_Circuit_And_Or. + begin + Has_Pragma_SCAO := UIC.Root_Unit.P_Config_Pragmas + (To_Unbounded_Text ("Short_Circuit_And_Or"))'Length /= 0; + exception + when Exc : Property_Error => + Report + (UIC, + UIC.Root_Unit, + "Could not determine pragmas of the compilation unit: " + & Ada.Exceptions.Exception_Information (Exc), + Kind => Low_Warning); + Has_Pragma_SCAO := False; + end; - UIC.Short_Circuit_And_Or := Switches.Short_Circuit_And_Or; + UIC.Short_Circuit_And_Or := + Switches.Short_Circuit_And_Or or else Has_Pragma_SCAO; -- Create an artificial internal error, if requested From bcffa68c153f8d32cfa0b4317e591f1df18d9230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 22 Nov 2022 11:10:51 +0100 Subject: [PATCH 0075/1483] Add default values for options --level and --annotate This change adds default values for options --level and --annotate to respectively stmt and report. Additionnaly, when the coverage level is not specified on the command line or the project file, a warning will be emitted to let the user know that the default "stmt" value was used. TN: VB18-035 --- tools/gnatcov/gnatcov_bits_specific.adb | 32 +++++++++++++++++-------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 5c64750da..19cb52241 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -804,16 +804,16 @@ procedure GNATcov_Bits_Specific is | Cmd_Dump_Trace_Asm | Cmd_Dump_Src_Trace => - -- For "coverage", require an annotation format unless we must - -- save a checkpoint. In this case, we'll just skip report - -- production. + -- For "coverage", if the annotation format is not specified on + -- the command line, default to report, unless we must save a + -- checkpoint. if Args.Command = Cmd_Coverage - and then - (Args.String_List_Args (Opt_Annotation_Format).Is_Empty - and Save_Checkpoint = null) + and then Args.String_List_Args (Opt_Annotation_Format).Is_Empty + and then Save_Checkpoint = null then - Report_Missing_Argument ("an annotation format"); + Annotation (Annotate_Report) := True; + Annotation (Annotate_Unknown) := False; end if; -- If --no-cov-report is on the command line, check that @@ -990,11 +990,17 @@ procedure GNATcov_Bits_Specific is -- either an object level specified, or possibly no --level at -- all. - if not Source_Coverage_Enabled then + if Object_Coverage_Enabled then Fatal_Error ("Instrumentation requires a source coverage level" & ASCII.LF & " (--level=" & Source_Level_Options ("|") & ")"); + elsif not Source_Coverage_Enabled then + Warn + ("Coverage level not specified on the command" + & " line or in the project file (--level=" + & Source_Level_Options ("|") & "), defaulting to ""stmt""."); + Set_Coverage_Levels ("stmt"); end if; if Args.String_Args (Opt_Path_Count_Limit).Present then @@ -1616,11 +1622,16 @@ begin when Cmd_Coverage => - -- Make sure we have a coverage level + -- Warn when the user hasn't explicitly set a coverage level and + -- default to stmt. if not (Source_Coverage_Enabled or else Object_Coverage_Enabled) then - Report_Missing_Argument ("a coverage level"); + Warn ("Coverage level not specified on the command line or in the" + & " project file (--level=" & Source_Level_Options ("|") + & "|" & Object_Level_Options ("|") & "), defaulting to" + & " ""stmt""."); + Set_Coverage_Levels ("stmt"); end if; -- Reject the use of several features that are not supported with @@ -2347,6 +2358,7 @@ begin if Annotation (Annotate_Unknown) then pragma Assert (Save_Checkpoint /= null); end if; + else pragma Assert (Save_Checkpoint /= null); end if; From 88f984a5dff28d9883e60aa66033ae3e2faffffe Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 3 Nov 2022 12:53:55 +0100 Subject: [PATCH 0076/1483] clang-wrapper.cc: Fix clang_getLHS for the conditional operator TN: VB03-009 --- tools/gnatcov/clang-wrapper.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 19e89e705..6895d4033 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -366,7 +366,7 @@ clang_getLHS (CXCursor C) return MakeCXCursorWithNull (cast (S)->getLHS (), C); case Stmt::ConditionalOperatorClass: return MakeCXCursorWithNull ( - cast (S)->getRHS (), C); + cast (S)->getLHS (), C); default: return clang_getNullCursor (); } From 466478980693f48251a4de00e0a59dc5880da053 Mon Sep 17 00:00:00 2001 From: Nicolas Setton Date: Wed, 23 Nov 2022 15:44:51 +0000 Subject: [PATCH 0077/1483] Initial version of a CI for gnatcoverage --- .gitlab-ci.yml | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 000000000..9a25287dd --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,89 @@ +# This bit is used to make sure we don't run too many pipelines: +# run on a triggered pipeline, on a merge request, or on a push to a branch, +# but do not run in reaction to a push to a branch if there is also +# a merge request for it. +workflow: + rules: + - if: '$CI_PIPELINE_SOURCE == "pipeline"' + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' + - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS' + when: never + - if: '$CI_COMMIT_BRANCH' + +variables: +# These are not needed at the moment, but will be useful when we migrate +# to a multi-stage pipeline. +# PACKAGE_BASENAME: gnatcoverage.tar.gz +# PACKAGE: $CI_PROJECT_DIR/$PACKAGE_BASENAME +# PACKAGE_REPOSITORY_PROJECT: eng/cov/ci-packages +# CI_FRAGMENTS: ci-fragments +# CI_FRAGMENTS_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/it/$CI_FRAGMENTS + GNATCOVERAGE_EXTRA_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/cov/gnatcoverage-extra + +stages: + - build_and_test + + +build_and_test: + services: + - image:sandbox + - cpu:8 + - mem:16 + stage: build_and_test + rules: + # Triggers on a push or pipeline + - if: ($CI_PIPELINE_SOURCE == "pipeline" || $CI_PIPELINE_SOURCE == "push") + script: + - . ~/.aws_container_credentials + - export PATH=/it/e3/bin:$PATH + + # Get the gnatcoverage-extra repository. If we're testing a 'sync/' branch, + # expect the same for that repo. + - cd /tmp + - EXTRA_BRANCH=master + - if [[ $CI_COMMIT_BRANCH =~ ^sync/ ]]; then + EXTRA_BRANCH=$CI_COMMIT_BRANCH; + elif [[ $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ ^sync/ ]]; then + EXTRA_BRANCH=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME; + fi + - git clone $GNATCOVERAGE_EXTRA_GIT -b $EXTRA_BRANCH + + # Setup the anod sandbox repositories + + - cd /it/wave + - anod vcs --add-repo gnatcoverage $CI_PROJECT_DIR + - anod vcs --add-repo gnatcoverage-extra /tmp/gnatcoverage-extra + + # Build using anod + - anod build --minimal gnatcov --qualifier=no-c + + # Test using anod + - anod test gnatcov --qualifier=-O0 + - e3-testsuite-report + --failure-exit-code 1 + --xunit-output /tmp/xunit_output.xml + --xunit-name O0 + x86_64-linux/gnatcov-O0-test/results/new/ + + - anod test gnatcov --qualifier=src-traces + - e3-testsuite-report + --failure-exit-code 1 + --xunit-output /tmp/xunit_output.xml + --xunit-name src-traces + x86_64-linux/gnatcov-src-traces-test/results/new/ + + - anod test gnatcov --qualifier=spark-tests,src-traces + - e3-testsuite-report + --failure-exit-code 1 + --xunit-output /tmp/xunit_output.xml + --xunit-name spark + x86_64-linux/gnatcov-spark-tests-src-traces-test/results/new/ + + - cp /tmp/xunit_output.xml $CI_PROJECT_DIR + + artifacts: + when: always + paths: + - xunit_output.xml + reports: + junit: xunit_output.xml From cd3489e0013333eb2ba2e5ef4a3abc62e6956c26 Mon Sep 17 00:00:00 2001 From: Nicolas Setton Date: Wed, 23 Nov 2022 17:17:53 +0000 Subject: [PATCH 0078/1483] Split the xunit output in separate files In an attempt to convey all results from 3 testsuites to GitLab. Adjust workflow and rules to prevent multiple pipeline runs. --- .gitlab-ci.yml | 29 +++++++++++++---------------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9a25287dd..9d49c03dd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,14 +1,11 @@ # This bit is used to make sure we don't run too many pipelines: -# run on a triggered pipeline, on a merge request, or on a push to a branch, -# but do not run in reaction to a push to a branch if there is also -# a merge request for it. +# don't run the branch CI when a merge request is already open for the +# branch. workflow: rules: - - if: '$CI_PIPELINE_SOURCE == "pipeline"' - - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - - if: '$CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS' + - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push" when: never - - if: '$CI_COMMIT_BRANCH' + - when: always variables: # These are not needed at the moment, but will be useful when we migrate @@ -30,10 +27,8 @@ build_and_test: - cpu:8 - mem:16 stage: build_and_test - rules: - # Triggers on a push or pipeline - - if: ($CI_PIPELINE_SOURCE == "pipeline" || $CI_PIPELINE_SOURCE == "push") script: + - env - . ~/.aws_container_credentials - export PATH=/it/e3/bin:$PATH @@ -61,29 +56,31 @@ build_and_test: - anod test gnatcov --qualifier=-O0 - e3-testsuite-report --failure-exit-code 1 - --xunit-output /tmp/xunit_output.xml + --xunit-output /tmp/xunit_output_O0.xml --xunit-name O0 x86_64-linux/gnatcov-O0-test/results/new/ - anod test gnatcov --qualifier=src-traces - e3-testsuite-report --failure-exit-code 1 - --xunit-output /tmp/xunit_output.xml + --xunit-output /tmp/xunit_output_src-traces.xml --xunit-name src-traces x86_64-linux/gnatcov-src-traces-test/results/new/ - anod test gnatcov --qualifier=spark-tests,src-traces - e3-testsuite-report --failure-exit-code 1 - --xunit-output /tmp/xunit_output.xml + --xunit-output /tmp/xunit_output_spark.xml --xunit-name spark x86_64-linux/gnatcov-spark-tests-src-traces-test/results/new/ - - cp /tmp/xunit_output.xml $CI_PROJECT_DIR + - cp /tmp/xunit_output*.xml $CI_PROJECT_DIR artifacts: when: always paths: - - xunit_output.xml + - xunit_output_O0.xml + - xunit_output_src-traces.xml + - xunit_output_spark.xml reports: - junit: xunit_output.xml + junit: "xunit_output*.xml" From 55fd9264b5558cc1a1d0e61de31a43d2036d13d4 Mon Sep 17 00:00:00 2001 From: Nicolas Setton Date: Thu, 24 Nov 2022 11:59:19 +0000 Subject: [PATCH 0079/1483] Parallelize the tests --- .gitlab-ci.yml | 132 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 105 insertions(+), 27 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9d49c03dd..d8e4c4378 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,30 +8,75 @@ workflow: - when: always variables: -# These are not needed at the moment, but will be useful when we migrate -# to a multi-stage pipeline. -# PACKAGE_BASENAME: gnatcoverage.tar.gz -# PACKAGE: $CI_PROJECT_DIR/$PACKAGE_BASENAME -# PACKAGE_REPOSITORY_PROJECT: eng/cov/ci-packages -# CI_FRAGMENTS: ci-fragments -# CI_FRAGMENTS_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/it/$CI_FRAGMENTS - GNATCOVERAGE_EXTRA_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/cov/gnatcoverage-extra + PACKAGE_BASE_NAME: gnatcoverage.tar.gz + PACKAGE_ABSOLUTE_NAME: $CI_PROJECT_DIR/$PACKAGE_BASE_NAME + + # These are not needed at the moment, but will be useful when we migrate + # to a multi-stage pipeline. + # PACKAGE_REPOSITORY_PROJECT: eng/cov/ci-packages + # CI_FRAGMENTS: ci-fragments + # CI_FRAGMENTS_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/it/$CI_FRAGMENTS + GNATCOVERAGE_EXTRA_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/cov/gnatcoverage-extra stages: - - build_and_test + - build + - test + +build: + services: + - image:sandbox + - cpu:8 + - mem:16 + stage: build + script: + - . ~/.aws_container_credentials + - export PATH=/it/e3/bin:$PATH + + # Setup the repository + - cd /it/wave + - anod vcs --add-repo gnatcoverage $CI_PROJECT_DIR + + # Build using anod + - anod build --minimal gnatcov + - anod build --minimal gnatcov-internal + + # Create the package + - tar czf $PACKAGE_ABSOLUTE_NAME -C / + it/wave/x86_64-linux/gnatcov-build/install/ + it/wave/x86_64-linux/gnatcov-internal/install/ + - cd $CI_PROJECT_DIR + - ls -l $PACKAGE_BASE_NAME -build_and_test: + artifacts: + paths: + - $PACKAGE_BASE_NAME + +build_community: services: - image:sandbox - cpu:8 - mem:16 - stage: build_and_test + stage: test script: - - env - . ~/.aws_container_credentials - export PATH=/it/e3/bin:$PATH + # Setup the repository + - cd /it/wave + - anod vcs --add-repo gnatcoverage $CI_PROJECT_DIR + + # Build using anod + - anod build --minimal gnatcov --qualifier=no-c + +.common_test_bits: &retrieve_gnatcoverage_extras_and_setup_anod_repo + - . ~/.aws_container_credentials + - export PATH=/it/e3/bin:$PATH + + # Unpack the artifact then delete it + - tar zxf $PACKAGE_ABSOLUTE_NAME -C / + - rm -f $PACKAGE_ABSOLUTE_NAME + # Get the gnatcoverage-extra repository. If we're testing a 'sync/' branch, # expect the same for that repo. - cd /tmp @@ -44,43 +89,76 @@ build_and_test: - git clone $GNATCOVERAGE_EXTRA_GIT -b $EXTRA_BRANCH # Setup the anod sandbox repositories - - cd /it/wave - anod vcs --add-repo gnatcoverage $CI_PROJECT_DIR - anod vcs --add-repo gnatcoverage-extra /tmp/gnatcoverage-extra - # Build using anod - - anod build --minimal gnatcov --qualifier=no-c + # Setup fingerprints so anod doesn't do unnecessary rebuilds + - mkdir -p fingerprints + - touch fingerprints/x86_64-linux.gnatcov-internal.install.json.assume-unchanged + - touch fingerprints/x86_64-linux.gnatcov-build.install.json.assume-unchanged + +.common_artifacts_bits: &artifacts + artifacts: + paths: + - xunit_output.xml + reports: + junit: xunit_output.xml + +test_O0: + services: + - image:sandbox + - cpu:8 + - mem:16 + stage: test + script: + - *retrieve_gnatcoverage_extras_and_setup_anod_repo # Test using anod - anod test gnatcov --qualifier=-O0 - e3-testsuite-report --failure-exit-code 1 - --xunit-output /tmp/xunit_output_O0.xml + --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name O0 x86_64-linux/gnatcov-O0-test/results/new/ + <<: *artifacts + +test_src_traces: + services: + - image:sandbox + - cpu:8 + - mem:16 + stage: test + script: + - *retrieve_gnatcoverage_extras_and_setup_anod_repo + + # Test using anod - anod test gnatcov --qualifier=src-traces - e3-testsuite-report --failure-exit-code 1 - --xunit-output /tmp/xunit_output_src-traces.xml + --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name src-traces x86_64-linux/gnatcov-src-traces-test/results/new/ + <<: *artifacts + +test_spark: + services: + - image:sandbox + - cpu:8 + - mem:16 + stage: test + script: + - *retrieve_gnatcoverage_extras_and_setup_anod_repo + + # Test using anod - anod test gnatcov --qualifier=spark-tests,src-traces - e3-testsuite-report --failure-exit-code 1 - --xunit-output /tmp/xunit_output_spark.xml + --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name spark x86_64-linux/gnatcov-spark-tests-src-traces-test/results/new/ - - cp /tmp/xunit_output*.xml $CI_PROJECT_DIR + <<: *artifacts - artifacts: - when: always - paths: - - xunit_output_O0.xml - - xunit_output_src-traces.xml - - xunit_output_spark.xml - reports: - junit: "xunit_output*.xml" From 509e2d45be11360a51a3ae16a02fb8f6a6b6afb9 Mon Sep 17 00:00:00 2001 From: Nicolas Setton Date: Thu, 24 Nov 2022 14:53:39 +0000 Subject: [PATCH 0080/1483] Remove the -O0 testsuite and replace with a cross testing Remove the build of gnatcov-internal, no longer needed. --- .gitlab-ci.yml | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d8e4c4378..6f635beda 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -38,12 +38,10 @@ build: # Build using anod - anod build --minimal gnatcov - - anod build --minimal gnatcov-internal # Create the package - tar czf $PACKAGE_ABSOLUTE_NAME -C / it/wave/x86_64-linux/gnatcov-build/install/ - it/wave/x86_64-linux/gnatcov-internal/install/ - cd $CI_PROJECT_DIR - ls -l $PACKAGE_BASE_NAME @@ -95,7 +93,6 @@ build_community: # Setup fingerprints so anod doesn't do unnecessary rebuilds - mkdir -p fingerprints - - touch fingerprints/x86_64-linux.gnatcov-internal.install.json.assume-unchanged - touch fingerprints/x86_64-linux.gnatcov-build.install.json.assume-unchanged .common_artifacts_bits: &artifacts @@ -105,7 +102,7 @@ build_community: reports: junit: xunit_output.xml -test_O0: +test_bin_traces: services: - image:sandbox - cpu:8 @@ -115,12 +112,12 @@ test_O0: - *retrieve_gnatcoverage_extras_and_setup_anod_repo # Test using anod - - anod test gnatcov --qualifier=-O0 + - anod test gnatcov --target=leon3-elf --qualifier="RTS=embedded-leon3,-O0" - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml - --xunit-name O0 - x86_64-linux/gnatcov-O0-test/results/new/ + --xunit-name bin-traces + leon3-elf-linux64/gnatcov-O0-embedded-leon3-test/results/new/ <<: *artifacts From 28427fab039300ac1a60675c804cfe286806bb08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Fri, 21 Oct 2022 10:45:10 +0200 Subject: [PATCH 0081/1483] Instrument.C: add scoped metrics for C/C++ Record scope information when instrumenting C/C++ programs during the second traversal (not the pre-processing traversal). The supported scopes are functions, classes, methods, constructors, destructors, namespaces, and templated functions and classes. Lambdas and language linkage specifications are not registered as scopes. TN: V923-016 --- tools/gnatcov/clang-extensions.adb | 18 ++++ tools/gnatcov/clang-extensions.ads | 2 + tools/gnatcov/clang-wrapper.cc | 63 +++++++++++ tools/gnatcov/instrument-ada_unit.adb | 25 +---- tools/gnatcov/instrument-c.adb | 144 ++++++++++++++++++++------ tools/gnatcov/instrument-c.ads | 7 ++ tools/gnatcov/instrument-common.adb | 16 +++ tools/gnatcov/instrument-common.ads | 6 ++ 8 files changed, 225 insertions(+), 56 deletions(-) diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index ad3c3c2f2..fadececfd 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -39,6 +39,24 @@ package body Clang.Extensions is L => To_Sloc (Line, Column))); -- Convert a Clang source location to gnatcov's own format + ----------------------- + -- Get_Decl_Name_Str -- + ----------------------- + + function Get_Decl_Name_Str (C : Cursor_T) return String is + + function Get_Decl_Name_Str_C (C : Cursor_T) return String_T + with + Import, Convention => C, + External_Name => "clang_getDeclName"; + + DeclName_Str_C : constant String_T := Get_Decl_Name_Str_C (C); + DeclName : constant String := Get_C_String (DeclName_Str_C); + begin + Dispose_String (DeclName_Str_C); + return DeclName; + end Get_Decl_Name_Str; + -------------------- -- Get_Opcode_Str -- -------------------- diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index d5868cca5..e5ce0186e 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -73,6 +73,8 @@ package Clang.Extensions is function Get_Opcode_Str (C : Cursor_T) return String with Inline; + function Get_Decl_Name_Str (C : Cursor_T) return String with Inline; + function Unwrap (C : Cursor_T) return Cursor_T with Import, Convention => C, External_Name => "clang_unwrap"; diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 6895d4033..44c768117 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -373,6 +373,69 @@ clang_getLHS (CXCursor C) return clang_getNullCursor (); } +/* Return the name of the declared object. */ + +extern "C" const CXString +clang_getDeclName (CXCursor C) +{ + if (clang_isDeclaration (C.kind)) + { + auto getFunctionDeclName = [] (const FunctionDecl *FD) { + const DeclarationName FunctionName = FD->getNameInfo ().getName (); + return createDup (FunctionName.getAsString ().c_str ()); + }; + + const Decl *D = getCursorDecl (C); + + switch (D->getKind ()) + { + case Decl::Function: + case Decl::CXXMethod: + case Decl::CXXConstructor: + case Decl::CXXDestructor: + { + const clang::FunctionDecl *FD = cast (D); + return getFunctionDeclName (FD); + } + case Decl::FunctionTemplate: + { + const clang::FunctionDecl *FD + = (cast (D))->getTemplatedDecl (); + return getFunctionDeclName (FD); + } + + case Decl::Namespace: + { + const NamespaceDecl *ND + = (cast (D))->getCanonicalDecl (); + + if (ND->isAnonymousNamespace ()) + return createDup ("Anonymous namespace"); + + return createDup (ND->getName ()); + } + case Decl::ClassTemplate: + + { + const clang::ClassTemplateDecl *CD + = (cast (D))->getCanonicalDecl (); + return createDup (CD->getName ()); + } + case Decl::CXXRecord: + { + const clang::CXXRecordDecl *RD + = (cast (D))->getCanonicalDecl (); + return createDup (RD->getName ()); + } + + default: + return createEmpty (); + } + } + + return createEmpty (); +} + /* Return the string representative of the operator for a binary or unary operator node. */ diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index ceb009c8e..745d21f81 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6858,30 +6858,11 @@ package body Instrument.Ada_Unit is -- See the comment for Scope_Entity.From/To. if UIC.Current_Scope_Entity /= null then - declare - use Scope_Entities_Vectors; - - procedure Remap_SCOs (Scope_Entity : Scope_Entity_Acc); - - ---------------- - -- Remap_SCOs -- - ---------------- - - procedure Remap_SCOs (Scope_Entity : Scope_Entity_Acc) is - begin - Scope_Entity.From := SCO_Map (Nat (Scope_Entity.From)); - Scope_Entity.To := SCO_Map (Nat (Scope_Entity.To)); - for Child of Scope_Entity.Children loop - Remap_SCOs (Child); - end loop; - end Remap_SCOs; - begin - -- Iterate through the package level body entities + -- Iterate through the package level body entities - Remap_SCOs (UIC.Current_Scope_Entity); - Set_Scope_Entity (UIC.CU, UIC.Current_Scope_Entity); - end; + Remap_Scope_Entity (UIC.Current_Scope_Entity, SCO_Map); + Set_Scope_Entity (UIC.CU, UIC.Current_Scope_Entity); end if; end; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 8674ef137..14b3f3f6d 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -175,6 +175,17 @@ package body Instrument.C is type Instrument_Pass_Kind is new Pass_Kind with null record; + overriding procedure Enter_Scope + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class; + N : Cursor_T); + -- Open a scope for N + + overriding procedure Exit_Scope + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class); + -- Close the current scope + overriding procedure Append_SCO (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; @@ -587,6 +598,33 @@ package body Instrument.C is end case; end Source_Suffix; + ----------------- + -- Enter_Scope -- + ----------------- + + overriding procedure Enter_Scope + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class; + N : Cursor_T) is + begin + Enter_Scope (UIC => UIC, + Scope_Name => +Get_Decl_Name_Str (N), + Sloc => Start_Sloc (N).L); + end Enter_Scope; + + ---------------- + -- Exit_Scope -- + ---------------- + + overriding procedure Exit_Scope + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class) is + begin + if UIC.Current_Scope_Entity /= null then + Exit_Scope (UIC); + end if; + end Exit_Scope; + ---------------- -- Append_SCO -- ---------------- @@ -1968,7 +2006,8 @@ package body Instrument.C is end if; end case; - -- Traverse lambda expressions, if any + -- Traverse lambda expressions, if any. Do not register them as + -- scopes. Traverse_Declarations (IC => IC, @@ -2120,47 +2159,59 @@ package body Instrument.C is -- Only traverse the function declarations that belong to a unit of -- interest. + if Is_Source_Of_Interest (UIC, N) then - begin - if Is_Source_Of_Interest (UIC, N) then - case Kind (N) is + case Kind (N) is - -- Traverse the statements of function bodies + -- Traverse the statements of function bodies - when Cursor_Function_Decl - | Cursor_Function_Template - | Cursor_CXX_Method - | Cursor_Constructor - | Cursor_Destructor - | Cursor_Lambda_Expr => - declare - -- Get_Body returns a Compound_Stmt, convert it to a - -- list of statements using the Get_Children utility. + when Cursor_Function_Decl + | Cursor_Function_Template + | Cursor_CXX_Method + | Cursor_Constructor + | Cursor_Destructor + | Cursor_Lambda_Expr => - Fun_Body : constant Cursor_Vectors.Vector := - Get_Children (Get_Body (N)); - begin - if Fun_Body.Length > 0 then - UIC.MCDC_State_Declaration_Node := - Fun_Body.First_Element; - Traverse_Statements (IC, UIC, Fun_Body); - end if; - end; + UIC.Pass.Enter_Scope (UIC, N); + + declare + -- Get_Body returns a Compound_Stmt, convert it to + -- a list of statements using the Get_Children + -- utility. + + Fun_Body : constant Cursor_Vectors.Vector := + Get_Children (Get_Body (N)); + begin + if Fun_Body.Length > 0 then + UIC.MCDC_State_Declaration_Node := + Fun_Body.First_Element; + Traverse_Statements (IC, UIC, Fun_Body); + end if; + end; + + UIC.Pass.Exit_Scope (UIC); -- Traverse the declarations of a namespace / linkage - -- specifier etc. + -- specification etc. - when Cursor_Namespace - | Cursor_Linkage_Spec - | Cursor_Class_Template - | Cursor_Class_Decl => - Traverse_Declarations (IC, UIC, Get_Children (N)); + when Cursor_Namespace + | Cursor_Class_Template + | Cursor_Class_Decl => - when others => - null; - end case; - end if; - end; + UIC.Pass.Enter_Scope (UIC, N); + + Traverse_Declarations (IC, UIC, Get_Children (N)); + + UIC.Pass.Exit_Scope (UIC); + + when Cursor_Linkage_Spec => + Traverse_Declarations (IC, UIC, Get_Children (N)); + + when others => + null; + end case; + + end if; end loop; -- Restore previous MCDC_State insertion node: we can have lambda @@ -2640,6 +2691,7 @@ package body Instrument.C is begin SCOs.Initialize; + UIC.SFI := Get_Index_From_Generic_Name (Orig_Filename, Kind => Files_Table.Source_File, @@ -2736,6 +2788,11 @@ package body Instrument.C is UIC.Rewriter := Rewriter.Rewriter; Insert_Extern_Location := Find_First_Insert_Location (UIC.TU); + -- Enter the scope corresponding to the file in which all other scopes + -- will be declared. + + Enter_Scope (UIC, CU_Name.Filename, (Line => 0, Column => 0)); + Traverse_Declarations (IC => IC, UIC => UIC, @@ -2758,6 +2815,10 @@ package body Instrument.C is UIC.LL_PP_Info_Map.Clear; end if; + -- Exit the scope of the file + + Exit_Scope (UIC); + -- Now that the set of coverage obligations and the set of source files -- are known, allocate the required set of coverage buffers (one per -- source file) and assign the corresponding buffers indexes. @@ -2902,6 +2963,21 @@ package body Instrument.C is -- Associate these bit maps to the corresponding CU Set_Bit_Maps (UIC.CUs.Element (SFI), Bit_Maps); + + if UIC.Current_Scope_Entity /= null then + + -- Iterate through the package level body entities + + Remap_Scope_Entity (UIC.Current_Scope_Entity, SCO_Map); + + declare + CU : constant Created_Unit_Maps.Cursor := + UIC.CUs.Find (UIC.SFI); + begin + Set_Scope_Entity (Created_Unit_Maps.Element (CU), + UIC.Current_Scope_Entity); + end; + end if; end; end loop; end; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 8b266dc8f..c2e47a890 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -391,6 +391,13 @@ private Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name) is null; + procedure Enter_Scope (Pass : Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class; + N : Cursor_T) is null; + + procedure Exit_Scope (Pass : Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class) is null; + procedure Instrument_Statement (Pass : Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 132c417c3..10ff48f43 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -908,6 +908,22 @@ package body Instrument.Common is SCOs.SCO_Table.Last; end Append_SCO; + ------------------------ + -- Remap_Scope_Entity -- + ------------------------ + + procedure Remap_Scope_Entity + (Scope_Entity : Scope_Entity_Acc; + SCO_Map : LL_HL_SCO_Map) + is + begin + Scope_Entity.From := SCO_Map (Nat (Scope_Entity.From)); + Scope_Entity.To := SCO_Map (Nat (Scope_Entity.To)); + for Child of Scope_Entity.Children loop + Remap_Scope_Entity (Child, SCO_Map); + end loop; + end Remap_Scope_Entity; + ------------------------------ -- Buffer_Units_For_Closure -- ------------------------------ diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 8d5b3ba13..a0398e1f8 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -585,6 +585,12 @@ package Instrument.Common is -- source file, also append a new entry to the SCO_Unit_Table, otherwise -- complete its last entry. + procedure Remap_Scope_Entity + (Scope_Entity : Scope_Entity_Acc; + SCO_Map : LL_HL_SCO_Map); + -- Convert low level SCOs in Scope_Entity to high-level SCOs using the + -- mapping in SCO_Map. + package CU_Name_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Compilation_Unit_Name); From 87c6454cfd95fcdfa8166bef37ac7da34deffe4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 22 Nov 2022 17:11:26 +0100 Subject: [PATCH 0082/1483] Instrument.C: support SCOs in header file for C/C++ scoped metrics The registering of the scopes is done during the instrumentation pass after the preprocessing pass. Since the location of a scope is local to a file, the location of SCOs defined in an included header was undestood as being in the file being instrumented, which is incorrect. This commit changes the storing of scopes for C/C++ by introducing a mapping from the files to the scopes defined in them. TN: V923-016 --- tools/gnatcov/instrument-ada_unit.adb | 63 ++++++++- tools/gnatcov/instrument-ada_unit.ads | 6 + tools/gnatcov/instrument-c.adb | 179 ++++++++++++++++++++++---- tools/gnatcov/instrument-c.ads | 17 +++ tools/gnatcov/instrument-common.adb | 60 +-------- tools/gnatcov/instrument-common.ads | 23 ---- 6 files changed, 234 insertions(+), 114 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 745d21f81..d2690a9f8 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1004,8 +1004,17 @@ package body Instrument.Ada_Unit is (UIC : in out Ada_Unit_Inst_Context; Scope_Name : Text_Type; Sloc : Source_Location); - -- Wrapper around Instrument.Common.Enter_Scope. See the documentation for - -- this function. + -- Enter a scope. This must be completed with a call to the function + -- Exit_Scope, defined below. Scope_Name is the name of the scope, which + -- is defined at location Sloc. Assume that the scope first SCO is the next + -- generated SCO (SCOs.SCO_Table.Last + 1). Update UIC.Current_Scope_Entity + -- to the created entity. + + procedure Exit_Scope (UIC : in out Ada_Unit_Inst_Context) + with Pre => UIC.Current_Scope_Entity /= null; + -- Exit the current scope, updating UIC.Current_Scope_Entity to + -- UIC.Current_Scope_Entity.Parent, if any. Assume that the last generated + -- SCO (SCOs.SCO_Table.Last) is the last SCO for the current scope. ---------------------------- -- Source level rewriting -- @@ -6105,14 +6114,54 @@ package body Instrument.Ada_Unit is procedure Enter_Scope (UIC : in out Ada_Unit_Inst_Context; Scope_Name : Text_Type; - Sloc : Source_Location) is + Sloc : Source_Location) + is + New_Scope_Ent : constant Scope_Entity_Acc := new Scope_Entity' + (From => SCO_Id (SCOs.SCO_Table.Last + 1), + To => No_SCO_Id, + Name => +Langkit_Support.Text.To_UTF8 (Scope_Name), + Sloc => (Line => Natural (Sloc.Line), + Column => Natural (Sloc.Column)), + Children => Scope_Entities_Vectors.Empty_Vector, + Parent => UIC.Current_Scope_Entity); begin - Enter_Scope - (UIC, - +Langkit_Support.Text.To_UTF8 (Scope_Name), - (Line => Natural (Sloc.Line), Column => Natural (Sloc.Column))); + if UIC.Current_Scope_Entity /= null then + UIC.Current_Scope_Entity.Children.Append (New_Scope_Ent); + end if; + UIC.Current_Scope_Entity := New_Scope_Ent; end Enter_Scope; + ---------------- + -- Exit_Scope -- + ---------------- + + procedure Exit_Scope (UIC : in out Ada_Unit_Inst_Context) + is + Parent : Scope_Entity_Acc renames UIC.Current_Scope_Entity.Parent; + Scope : Scope_Entity_Acc renames UIC.Current_Scope_Entity; + begin + -- Update the last SCO for this scope entity + + Scope.To := SCO_Id (SCOs.SCO_Table.Last); + + -- If the scope has no SCO (it could be possible for a package spec with + -- only subprogram declarations for instance), discard it. + + if Scope.To < Scope.From then + if Parent /= null then + Parent.Children.Delete_Last; + end if; + Free (Scope); + end if; + + -- If this is not the top-level scope (we want to keep its reference + -- after having traversed the AST), go up the scope tree. + + if Parent /= null then + Scope := Parent; + end if; + end Exit_Scope; + -------------------------- -- Initialize_Rewriting -- -------------------------- diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index f4819f49d..8046564a5 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -288,6 +288,12 @@ private Non_Instr_LL_SCOs : Non_Instrumented_SCO_Sets.Set; -- Set of low level SCO ids that were not instrumented + + Current_Scope_Entity : Scope_Entity_Acc := null; + -- Information about the name, sloc, SCO range and children scopes of + -- the current scope entity. This is modified when entering a scope + -- (updated to the current scope), and when leaving it (updated to + -- the current scope parent, if any). end record; function Insert_MCDC_State diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 14b3f3f6d..783820d75 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -179,12 +179,28 @@ package body Instrument.C is (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; N : Cursor_T); - -- Open a scope for N + -- Open a scope for N under the scope of the file in which the + -- corresponding code was written. This must be completed with a call to + -- the function Exit_Scope, defined below. Assume that the scope first SCO + -- is the next generated SCO (SCOs.SCO_Table.Last + 1). Update + -- UIC.Scopes to the created entity and UIC.Current_File_Scope to the + -- corresponding file. overriding procedure Exit_Scope (Pass : Instrument_Pass_Kind; - UIC : in out C_Unit_Inst_Context'Class); - -- Close the current scope + UIC : in out C_Unit_Inst_Context'Class) + with Pre => UIC.Scopes.Contains (UIC.Current_File_Scope); + -- Close the current scope, removing the current scope of the current file + -- from UIC.Scopes if it does not contain SCOs. Assume that the last + -- generated SCO (SCOs.SCO_Table.Last) is the last SCO for the current + -- scope. + + procedure Remap_Scopes + (Scopes : Scopes_In_Files_Map.Map; + SCO_Map : LL_HL_SCO_Map); + -- Convert low level SCOs in each scope for each file to high-level SCOs + -- using the mapping in SCO_Map. Set the file's SCO range to cover all of + -- its scopes' SCO ranges. overriding procedure Append_SCO (Pass : Instrument_Pass_Kind; @@ -605,11 +621,73 @@ package body Instrument.C is overriding procedure Enter_Scope (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; - N : Cursor_T) is + N : Cursor_T) + is + procedure Enter_File_Scope + (UIC : in out C_Unit_Inst_Context'Class; + SFI : Source_File_Index) + with Post => UIC.Scopes.Contains (SFI); + -- Create a global scope for the file index SFI in which all scopes + -- opened in the file will be stored. + + ---------------------- + -- Enter_File_Scope -- + ---------------------- + + procedure Enter_File_Scope + (UIC : in out C_Unit_Inst_Context'Class; + SFI : Source_File_Index) is + begin + if not UIC.Scopes.Contains (SFI) then + declare + New_Scope_Ent : constant Scope_Entity_Acc := new Scope_Entity' + (From => SCO_Id (SCOs.SCO_Table.Last + 1), + To => No_SCO_Id, + Name => +Get_Unique_Name (SFI), + Sloc => (Line => 0, Column => 0), + Children => Scope_Entities_Vectors.Empty_Vector, + Parent => null); + begin + UIC.Scopes.Insert (SFI, New_Scope_Ent); + end; + end if; + + UIC.Current_File_Scope := SFI; + end Enter_File_Scope; + + Sloc : constant Source_Location := Start_Sloc (N); + File : constant Source_File_Index := Sloc.Source_File; begin - Enter_Scope (UIC => UIC, - Scope_Name => +Get_Decl_Name_Str (N), - Sloc => Start_Sloc (N).L); + -- For C and C++ programs that can include header files we need to be + -- able to know which file a scope was opened in. For this we use a map + -- from Source_File_Index to Scope_Entity_Acc. The scope associated to a + -- file is the last scope that was opened in it but not yet exited. + -- This mechanism works in the same way as that for Ada with the + -- possibility to have one current scope per file rather than just one + -- only for the file being instrumented. + + Enter_File_Scope (UIC, File); + + declare + C : constant Scopes_In_Files_Map.Cursor := + UIC.Scopes.Find (File); + Current_Scope : constant Scope_Entity_Acc := + Scopes_In_Files_Map.Element (C); + New_Scope_Ent : constant Scope_Entity_Acc := new Scope_Entity' + (From => SCO_Id (SCOs.SCO_Table.Last + 1), + To => No_SCO_Id, + Name => +Get_Decl_Name_Str (N), + Sloc => Sloc.L, + Children => Scope_Entities_Vectors.Empty_Vector, + Parent => Current_Scope); + begin + -- Add New_Scope_Ent to the children of the last open scope in the + -- file. + Current_Scope.Children.Append (New_Scope_Ent); + + -- Set New_Scope_Ent as the current open scope for the file. + UIC.Scopes.Replace_Element (C, New_Scope_Ent); + end; end Enter_Scope; ---------------- @@ -618,13 +696,68 @@ package body Instrument.C is overriding procedure Exit_Scope (Pass : Instrument_Pass_Kind; - UIC : in out C_Unit_Inst_Context'Class) is + UIC : in out C_Unit_Inst_Context'Class) + is + C : Scopes_In_Files_Map.Cursor := + UIC.Scopes.Find (UIC.Current_File_Scope); + Scope : Scope_Entity_Acc := Scopes_In_Files_Map.Element (C); begin - if UIC.Current_Scope_Entity /= null then - Exit_Scope (UIC); + -- If the scope associated to the current file is that of the file (no + -- parent), no scope is currently open in it. Then the scope that needs + -- closing is the current one of the file being instrumented. + + if Scope.Parent = null then + UIC.Current_File_Scope := UIC.SFI; + C := UIC.Scopes.Find (UIC.SFI); + Scope := Scopes_In_Files_Map.Element (C); end if; + + declare + Parent : constant Scope_Entity_Acc := Scope.Parent; + begin + -- Update the last SCO for this scope entity + + Scope.To := SCO_Id (SCOs.SCO_Table.Last); + + -- If the scope has no SCO, discard it + + if Scope.To < Scope.From then + if Parent /= null then + Parent.Children.Delete_Last; + end if; + Free (Scope); + end if; + + -- If this is not a top-level file scope (we want to keep its + -- reference after having traversed the AST), go up the scope tree + -- of the current file. + + if Parent /= null then + UIC.Scopes.Replace_Element (C, Parent); + end if; + end; end Exit_Scope; + ------------------ + -- Remap_Scopes -- + ------------------ + + procedure Remap_Scopes + (Scopes : Scopes_In_Files_Map.Map; + SCO_Map : LL_HL_SCO_Map) is + begin + for S of Scopes loop + if not S.Children.Is_Empty then + for Child of S.Children loop + Remap_Scope_Entity (Child, SCO_Map); + end loop; + + S.From := S.Children.First_Element.From; + S.To := S.Children.Last_Element.To; + end if; + end loop; + end Remap_Scopes; + ---------------- -- Append_SCO -- ---------------- @@ -2788,11 +2921,6 @@ package body Instrument.C is UIC.Rewriter := Rewriter.Rewriter; Insert_Extern_Location := Find_First_Insert_Location (UIC.TU); - -- Enter the scope corresponding to the file in which all other scopes - -- will be declared. - - Enter_Scope (UIC, CU_Name.Filename, (Line => 0, Column => 0)); - Traverse_Declarations (IC => IC, UIC => UIC, @@ -2815,10 +2943,6 @@ package body Instrument.C is UIC.LL_PP_Info_Map.Clear; end if; - -- Exit the scope of the file - - Exit_Scope (UIC); - -- Now that the set of coverage obligations and the set of source files -- are known, allocate the required set of coverage buffers (one per -- source file) and assign the corresponding buffers indexes. @@ -2964,20 +3088,21 @@ package body Instrument.C is Set_Bit_Maps (UIC.CUs.Element (SFI), Bit_Maps); - if UIC.Current_Scope_Entity /= null then - - -- Iterate through the package level body entities + -- Iterate through the package level body entities - Remap_Scope_Entity (UIC.Current_Scope_Entity, SCO_Map); + Remap_Scopes (UIC.Scopes, SCO_Map); + for C in UIC.Scopes.Iterate loop declare CU : constant Created_Unit_Maps.Cursor := - UIC.CUs.Find (UIC.SFI); + UIC.CUs.Find (Scopes_In_Files_Map.Key (C)); begin - Set_Scope_Entity (Created_Unit_Maps.Element (CU), - UIC.Current_Scope_Entity); + if Created_Unit_Maps.Has_Element (CU) then + Set_Scope_Entity (Created_Unit_Maps.Element (CU), + Scopes_In_Files_Map.Element (C)); + end if; end; - end if; + end loop; end; end loop; end; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index c2e47a890..bf9e2df09 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -322,6 +322,13 @@ package Instrument.C is Hash => Hash, Equivalent_Keys => "="); + package Scopes_In_Files_Map is new Ada.Containers.Ordered_Maps + (Key_Type => Source_File_Index, + Element_Type => Scope_Entity_Acc); + -- Mapping from a source file to the tree of scopes opened within it. The + -- root of each tree is the scope corresponding to the file itself in which + -- all its scopes are stored. + type C_Unit_Inst_Context is new Instrument.Common.Unit_Inst_Context with record TU : Translation_Unit_T; @@ -359,6 +366,16 @@ package Instrument.C is -- Compilation units created while instrumenting this source file. -- Initialized when calling Process_Low_Level_SCOs in -- Instrument_Source_File. + + Scopes : Scopes_In_Files_Map.Map := Scopes_In_Files_Map.Empty_Map; + -- Mapping between a file's SFI and the scopes containing SCOs + -- defined within that file. The SCOs located in imported files + -- are traversed during the instrumentation of the importing file + -- after preprocessing. This is needed in order to keep track of + -- which scope was originally opened in which file. + + Current_File_Scope : Source_File_Index; + -- Source file in wich the last scope encountered was opened. end record; type C_Source_Rewriter is tagged limited private; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 10ff48f43..7aed8f91f 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -914,11 +914,11 @@ package body Instrument.Common is procedure Remap_Scope_Entity (Scope_Entity : Scope_Entity_Acc; - SCO_Map : LL_HL_SCO_Map) - is + SCO_Map : LL_HL_SCO_Map) is begin Scope_Entity.From := SCO_Map (Nat (Scope_Entity.From)); - Scope_Entity.To := SCO_Map (Nat (Scope_Entity.To)); + Scope_Entity.To := SCO_Map (Nat (Scope_Entity.To)); + for Child of Scope_Entity.Children loop Remap_Scope_Entity (Child, SCO_Map); end loop; @@ -955,60 +955,6 @@ package body Instrument.Common is return Result; end Instr_Units_For_Closure; - ----------------- - -- Enter_Scope -- - ----------------- - - procedure Enter_Scope - (UIC : in out Unit_Inst_Context; - Scope_Name : Unbounded_String; - Sloc : Slocs.Local_Source_Location) - is - New_Scope_Ent : constant Scope_Entity_Acc := new Scope_Entity' - (From => SCO_Id (SCOs.SCO_Table.Last + 1), - To => No_SCO_Id, - Name => Scope_Name, - Sloc => Sloc, - Children => Scope_Entities_Vectors.Empty_Vector, - Parent => UIC.Current_Scope_Entity); - begin - if UIC.Current_Scope_Entity /= null then - UIC.Current_Scope_Entity.Children.Append (New_Scope_Ent); - end if; - UIC.Current_Scope_Entity := New_Scope_Ent; - end Enter_Scope; - - ---------------- - -- Exit_Scope -- - ---------------- - - procedure Exit_Scope (UIC : in out Unit_Inst_Context) - is - Parent : Scope_Entity_Acc renames UIC.Current_Scope_Entity.Parent; - Scope : Scope_Entity_Acc renames UIC.Current_Scope_Entity; - begin - -- Update the last SCO for this scope entity - - Scope.To := SCO_Id (SCOs.SCO_Table.Last); - - -- If the scope has no SCO (it could be possible for a package spec with - -- only subprogram declarations for instance), discard it. - - if Scope.To < Scope.From then - if Parent /= null then - Parent.Children.Delete_Last; - end if; - Free (Scope); - end if; - - -- If this is not the top-level scope (we want to keep its reference - -- after having traversed the AST), go up the scope tree. - - if Parent /= null then - Scope := Parent; - end if; - end Exit_Scope; - begin Sys_Prefix.Append (To_Unbounded_String ("GNATcov_RTS")); diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index a0398e1f8..d59162d95 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -544,13 +544,6 @@ package Instrument.Common is -- Annotations created during the instrumentation process, to insert in -- ALI_Files.ALI_Annotations afterwards, when the compilation unit -- (SC_Obligations.CU_Info) for this annotation is ready. - - Current_Scope_Entity : Scope_Entity_Acc := null; - -- Information about the name, sloc, SCO range and children scopes of - -- the current scope entity. This is modified when entering a scope - -- (updated to the current scope), and when leaving it (updated to the - -- current scope parent, if any). - end record; procedure Import_Annotations @@ -605,22 +598,6 @@ package Instrument.Common is Main : Compilation_Unit_Name) return CU_Name_Vectors.Vector; -- Return the list of instrumented units in Main's closure - procedure Enter_Scope - (UIC : in out Unit_Inst_Context; - Scope_Name : Unbounded_String; - Sloc : Local_Source_Location); - -- Enter a scope. This must be completed with a call to the function - -- Exit_Scope, defined below. Scope_Name is the name of the scope, which - -- is defined at location Sloc. Assume that the scope first SCO is the next - -- generated SCO (SCOs.SCO_Table.Last + 1). Update UIC.Current_Scope_Entity - -- to the created entity. - - procedure Exit_Scope (UIC : in out Unit_Inst_Context) - with Pre => UIC.Current_Scope_Entity /= null; - -- Exit the current scioe, updating UIC.Current_Scope_Entity to - -- UIC.Current_Scope_Entity.Parent, if any. Assume that the last generated - -- SCO (SCOs.SCO_Table.Last) is the last SCO for the current scope. - type Language_Instrumenter is abstract tagged null record; -- Set of operations to allow the instrumentation of sources files for a -- given language. From 1802bd2f89eb5c46aa66f0d9bb458fb2982f81eb Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 28 Nov 2022 19:05:43 +0100 Subject: [PATCH 0083/1483] Instrument.C: fix crash with empty source of interest gnatcov used to crash when instrumenting an empty source of interest, as it could not find a source location to insert extern declarations. Rework this part and simplify it. TN: VB03-009 --- tools/gnatcov/instrument-c.adb | 55 +++++----------------------------- 1 file changed, 7 insertions(+), 48 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 783820d75..8abb5b267 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -491,10 +491,6 @@ package body Instrument.C is Func_Args : String := ""); -- Like Format_Extern_Decl, but write the definition to File - function Find_First_Insert_Location - (TU : Translation_Unit_T) return Source_Location_T; - -- Find the first rewritable (raw) location of the file - ------------------------ -- To_Chars_Ptr_Array -- ------------------------ @@ -2919,7 +2915,10 @@ package body Instrument.C is Preprocessed => True); UIC.TU := Rewriter.TU; UIC.Rewriter := Rewriter.Rewriter; - Insert_Extern_Location := Find_First_Insert_Location (UIC.TU); + Insert_Extern_Location := + Get_Range_Start + (Get_Cursor_Extent + (Get_Translation_Unit_Cursor (UIC.TU))); Traverse_Declarations (IC => IC, @@ -3629,7 +3628,9 @@ package body Instrument.C is -- Name of file to contain helpers implementing the buffers dump Insert_Extern_Location : constant Source_Location_T := - Find_First_Insert_Location (Rew.TU); + Get_Range_Start + (Get_Cursor_Extent + (Get_Translation_Unit_Cursor (Rew.TU))); -- Where to insert extern declarations Main_Cursor : constant Cursor_T := Get_Main (Rew.TU); @@ -3938,48 +3939,6 @@ package body Instrument.C is (Format_Extern_Decl (Instrumenter, C_Type, Name, Func_Args)); end Put_Extern_Decl; - -------------------------------- - -- Find_First_Insert_Location -- - -------------------------------- - - function Find_First_Insert_Location - (TU : Translation_Unit_T) return Source_Location_T - is - Location : Source_Location_T := Get_Null_Location; - - function Visit_Decl (Cursor : Cursor_T) return Child_Visit_Result_T; - -- Callback for Visit_Children - - ---------------- - -- Visit_Decl -- - ---------------- - - function Visit_Decl - (Cursor : Cursor_T) return Child_Visit_Result_T is - begin - if Kind (Cursor) = Cursor_Translation_Unit then - return Child_Visit_Recurse; - end if; - declare - Cursor_Location : constant Source_Location_T := - Get_Range_Start (Get_Cursor_Extent (Cursor)); - begin - if not Is_Macro_Location (Location) then - Location := Cursor_Location; - return Child_Visit_Break; - end if; - end; - return Child_Visit_Continue; - end Visit_Decl; - - -- Start of processing for Find_First_Insert_Location - - begin - Visit_Children (Parent => Get_Translation_Unit_Cursor (TU), - Visitor => Visit_Decl'Access); - return Location; - end Find_First_Insert_Location; - ---------------------------- -- Emit_Buffers_List_Unit -- ---------------------------- From d9ea41b338337e955c4ae4ababbb201d579b8bb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 18 Nov 2022 13:12:23 +0100 Subject: [PATCH 0084/1483] Clean previous xcov report before emitting a new one With this change, gnatcov now removes all xcov file in the output dir as well as in /xcov prior to emitting a new report. TN: VB07-015 --- tools/gnatcov/annotations-xcov.adb | 3 +- tools/gnatcov/annotations.adb | 30 ++++++++---- tools/gnatcov/annotations.ads | 18 ++++++-- tools/gnatcov/instrument-clean_objdirs.adb | 47 ++++--------------- tools/gnatcov/outputs.adb | 54 +++++++++++++++++++++- tools/gnatcov/outputs.ads | 9 ++++ 6 files changed, 110 insertions(+), 51 deletions(-) diff --git a/tools/gnatcov/annotations-xcov.adb b/tools/gnatcov/annotations-xcov.adb index a0378baf7..92700a6c1 100644 --- a/tools/gnatcov/annotations-xcov.adb +++ b/tools/gnatcov/annotations-xcov.adb @@ -88,7 +88,8 @@ package body Annotations.Xcov is Annotations.Generate_Report (Pp, Show_Details, - Subdir => (if Pp.Show_Details then "xcov+" else "xcov")); + Subdir => (if Pp.Show_Details then "xcov+" else "xcov"), + Clean_Pattern => "*.xcov"); end Generate_Report; --------------------------- diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 23a4684ef..15255e829 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -384,9 +384,10 @@ package body Annotations is --------------------- procedure Generate_Report - (Pp : in out Pretty_Printer'Class; - Show_Details : Boolean; - Subdir : String := "") + (Pp : in out Pretty_Printer'Class; + Show_Details : Boolean; + Subdir : String := ""; + Clean_Pattern : String := No_Cleaning) is use Coverage; @@ -500,12 +501,25 @@ package body Annotations is begin - -- Switch the output dir to produce the report content in the requested - -- subdir, if needed. + if Clean_Pattern /= No_Cleaning then + Clean_Dir (Get_Output_Dir, Clean_Pattern); + end if; - if Subdir'Length > 0 and then Multiple_Reports then - Set_Output_Dir (Previous_Output_Dir & GNAT.OS_Lib.Directory_Separator - & Subdir); + -- Clean the output subdir in all cases, and then switch to that subdir + -- to generate the report, if needed. + + if Subdir'Length > 0 then + declare + Output_Subdir : constant String := + Previous_Output_Dir & GNAT.OS_Lib.Directory_Separator & Subdir; + begin + if Clean_Pattern /= No_Cleaning then + Clean_Dir (Output_Subdir, Clean_Pattern); + end if; + if Multiple_Reports then + Set_Output_Dir (Output_Subdir); + end if; + end; end if; Pp.Show_Details := Show_Details; diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 96ca28938..afa5ee718 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -197,15 +197,25 @@ private Scope_Ent : Scope_Entity) is null; -- Let Pp print the given body entity + No_Cleaning : constant String := "DO NOT CLEAN"; + -- Constant used to indicate that we should not attempt to clean the output + -- dir prior to emitting the report. This is used instead of the empty + -- string as the empty string pattern can be used as a cleaning pattern + -- that will match every file in the report directory. We should probably + -- never need to clean a report dir with the above string as a pattern. + procedure Generate_Report - (Pp : in out Pretty_Printer'Class; - Show_Details : Boolean; - Subdir : String := ""); + (Pp : in out Pretty_Printer'Class; + Show_Details : Boolean; + Subdir : String := ""; + Clean_Pattern : String := No_Cleaning); -- Let Pp generate the annotated sources. If Show_Details is False, only -- a line state will be displayed. If Show_Details is True, a justification -- is associated to this line state. If Subdir is not empty, this will be -- subdirectory in which the report will be created if multiple reports are - -- requested. + -- requested. If Clean_Pattern is not No_Cleaning, all the files matching + -- Clean_Pattern in Output_Dir as well as in Output_Dir/Subdir will be + -- removed. function Aggregated_State (Info : Line_Info; diff --git a/tools/gnatcov/instrument-clean_objdirs.adb b/tools/gnatcov/instrument-clean_objdirs.adb index 1d7c0e307..ab8f19209 100644 --- a/tools/gnatcov/instrument-clean_objdirs.adb +++ b/tools/gnatcov/instrument-clean_objdirs.adb @@ -17,17 +17,17 @@ ------------------------------------------------------------------------------ with Ada.Directories; use Ada.Directories; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with GNATCOLL.Projects; use GNATCOLL.Projects; -with Paths; use Paths; +with Outputs; use Outputs; +with Strings; use Strings; with Project; procedure Instrument.Clean_Objdirs (IC : Inst_Context) is use Project_Info_Maps; - All_Instr_Files : File_Sets.Set; + All_Instr_Files : String_Sets.Set; -- Set of full names for all files that were written to output directories -- for all instrumented projects. @@ -42,14 +42,6 @@ procedure Instrument.Clean_Objdirs (IC : Inst_Context) is procedure Clean_Subdir (Project : Project_Type) is Output_Dir : constant String := Project_Output_Dir (Project); - - -- Removing items in a directory and iterate on these items at the same - -- time is not supported: first collect all files to remove (iteration) - -- and then remove them. - - To_Delete : File_Sets.Set; - Search : Search_Type; - Dir_Entry : Directory_Entry_Type; begin if -- Leave externally built projects out of the picture @@ -66,32 +58,11 @@ procedure Instrument.Clean_Objdirs (IC : Inst_Context) is return; end if; - -- Collect the files to delete - - Start_Search - (Search, - Directory => Output_Dir, - Pattern => "", - Filter => (Ordinary_File => True, others => False)); - while More_Entries (Search) loop - Get_Next_Entry (Search, Dir_Entry); - declare - Name : constant String := Simple_Name (Dir_Entry); - Full_Name : constant Unbounded_String := - To_Unbounded_String (Output_Dir / Name); - begin - if not All_Instr_Files.Contains (Full_Name) then - To_Delete.Insert (Full_Name); - end if; - end; - end loop; - End_Search (Search); - - -- Do the deletion + Clean_Dir + (Dir => Output_Dir, + Pattern => "", + Ignored_Files => All_Instr_Files); - for Name of To_Delete loop - Delete_File (To_String (Name)); - end loop; end Clean_Subdir; -- Start of processing for Instrument.Clean_Objdirs @@ -100,7 +71,9 @@ begin -- First initialize All_Instr_Files for Cur in IC.Project_Info_Map.Iterate loop - All_Instr_Files.Union (Element (Cur).Instr_Files); + for Filename of Element (Cur).Instr_Files loop + All_Instr_Files.Include (Filename); + end loop; end loop; -- Then go through all projects to clear up their object directories, diff --git a/tools/gnatcov/outputs.adb b/tools/gnatcov/outputs.adb index b912321cd..db6e2c7b6 100644 --- a/tools/gnatcov/outputs.adb +++ b/tools/gnatcov/outputs.adb @@ -28,7 +28,6 @@ with GNAT.OS_Lib; use GNAT.OS_Lib; with Command_Line; with Support_Files; -with Strings; use Strings; with Switches; with Version; @@ -99,6 +98,59 @@ package body Outputs is raise; end Create_Output_File; + --------------- + -- Clean_Dir -- + --------------- + + procedure Clean_Dir + (Dir : String; + Pattern : String; + Ignored_Files : String_Sets.Set := String_Sets.Empty_Set) + is + use Ada.Directories; + + -- Removing items in a directory and iterate on these items at the same + -- time is not supported: first collect all files to remove (iteration) + -- and then remove them. + + To_Delete : String_Vectors.Vector; + Search : Search_Type; + Dir_Entry : Directory_Entry_Type; + begin + -- Nothing to do if Dir does not exist or is not a directory + + if not Ada.Directories.Exists (Dir) or else Kind (Dir) /= Directory then + return; + end if; + + -- Collect the files to delete + + Start_Search + (Search, + Directory => Dir, + Pattern => Pattern, + Filter => (Ordinary_File => True, others => False)); + while More_Entries (Search) loop + Get_Next_Entry (Search, Dir_Entry); + declare + Name : constant String := Simple_Name (Dir_Entry); + Full_Name : constant Unbounded_String := + To_Unbounded_String (Dir / Name); + begin + if not Ignored_Files.Contains (Full_Name) then + To_Delete.Append (Full_Name); + end if; + end; + end loop; + End_Search (Search); + + -- Do the deletion + + for Name of To_Delete loop + Delete_File (To_String (Name)); + end loop; + end Clean_Dir; + ----------- -- Error -- ----------- diff --git a/tools/gnatcov/outputs.ads b/tools/gnatcov/outputs.ads index 7b944230f..967c3073f 100644 --- a/tools/gnatcov/outputs.ads +++ b/tools/gnatcov/outputs.ads @@ -25,6 +25,7 @@ with Ada.Text_IO; use Ada.Text_IO; with Types; use Types; with Files_Table; use Files_Table; +with Strings; use Strings; with Temp_Dirs; use Temp_Dirs; with Paths; use Paths; @@ -157,6 +158,14 @@ package Outputs is (SFI : Source_File_Index) return String is (PP_Temp_Dir.Directory_Name / (Get_Unique_Name (SFI) & ".pp")); + procedure Clean_Dir + (Dir : String; + Pattern : String; + Ignored_Files : String_Sets.Set := String_Sets.Empty_Set); + -- Remove all the files in Dir for which the base name matches Pattern, but + -- whose the full name is not contained in Ignored_Files. An empty string + -- for Pattern will match every file. + private type Context_Handle is From d33288380418b2432eadbc1d5d912c9c16f791e4 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 29 Nov 2022 15:12:56 +0100 Subject: [PATCH 0085/1483] Instrument.C: fix main-end dump-trigger Add a call to dump buffers at the end of the main if the last statement is not a return statement. gnatcov used to not dump buffers in that case, which meant that no trace was produced by the instrumented main execution. TN: VB28-007 --- tools/gnatcov/instrument-c.adb | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 8abb5b267..f7497373c 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3746,6 +3746,48 @@ package body Instrument.C is begin Visit_Children (Parent => Main_Cursor, Visitor => Process'Access); + + -- If the last statement of the function is not a return + -- statement add a call to dump_buffers at the end of the main + -- function. + + declare + use Cursor_Vectors; + Main_Body : constant Cursor_T := Get_Body (Main_Cursor); + Main_Stmts : constant Vector := Get_Children (Main_Body); + Last_Stmt : constant Cursor := Main_Stmts.Last; + Insert_Sloc : Source_Location_T; + Insert : Boolean := False; + begin + -- If the main is empty, insert right at the start of the + -- function. + + if Length (Main_Stmts) = 0 then + Insert_Sloc := + Get_Range_Start (Get_Cursor_Extent (Main_Body)); + Insert := True; + + -- Otherwise, insert after the last statement + + elsif Kind (Element (Last_Stmt)) /= Cursor_Return_Stmt then + Insert_Sloc := + Get_Range_End (Get_Cursor_Extent (Element (Last_Stmt))); + Insert := True; + end if; + + if Insert then + + -- Insert a terminating semicolon in case we end up + -- inserting between the last statement expression and + -- its terminating semicolon. + + CX_Rewriter_Insert_Text_After_Token + (Rew.Rewriter, + Insert_Sloc, + ";" & Dump_Procedure_Symbol (Main) & "();"); + end if; + end; + end; when At_Exit => From 2dd0c4ade06cca0bb28d2212eef6806d112664fd Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 28 Nov 2022 15:50:16 +0100 Subject: [PATCH 0086/1483] Fix wrong comment box TN: VB03-009 --- tools/gnatcov/instrument-c.adb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index f7497373c..947694178 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2690,9 +2690,9 @@ package body Instrument.C is end if; end Finalize; - --------------- - -- Emit_SCOs -- - --------------- + -------------------- + -- Record_PP_Info -- + -------------------- procedure Record_PP_Info (Unit_Info : Instrumented_Unit_Info; From 82578e4925482a57fd5265cbc4a6e2d76be154d1 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 7 Nov 2022 15:54:01 +0100 Subject: [PATCH 0087/1483] C instrumentation: change curlify implementation When instrumenting statement expressions that are inside a control flow statement, we may need to insert braces to preserve the semantics of the program when inserting witness code. We were not doing it in a robust enough way: as the end sloc of a statement expression in clang refers to the end of the expression, and not to the terminating semicolon, we were inserting after the next token of the statement expression to work around it. The instrumentation of the following code excerpt: if (a) return 0 // dumb-token ; else ... yielded: if (a) {witness; return 0 // dumb-token }; else ... which is wrong (and not compilable code). TN: VB03-009 --- tools/gnatcov/clang-extensions.ads | 10 + tools/gnatcov/clang-wrapper.cc | 31 +++ tools/gnatcov/instrument-c.adb | 347 +++++++++++++++++++-------- tools/gnatcov/instrument-c.ads | 13 +- tools/gnatcov/instrument-c_utils.adb | 34 +-- tools/gnatcov/instrument-c_utils.ads | 11 +- 6 files changed, 307 insertions(+), 139 deletions(-) diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index e5ce0186e..c56cfd42d 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -56,6 +56,16 @@ package Clang.Extensions is function Get_Else (C : Cursor_T) return Cursor_T with Import, Convention => C, External_Name => "clang_getElse"; + function Get_Else_Loc (C : Cursor_T) return Source_Location_T + with Import, Convention => C, External_Name => "clang_getElseLoc"; + -- If this cursor is an if statement with an else part, return the + -- else location.Otherwise, return a null location. + + function Get_While_Loc (C : Cursor_T) return Source_Location_T + with Import, Convention => C, External_Name => "clang_getWhileLoc"; + -- If this cursor is a do / while statement, return the while location. + -- Otherwise return a null location. + function Get_Sub_Expr (C : Cursor_T) return Cursor_T with Import, Convention => C, External_Name => "clang_getSubExpr"; diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 44c768117..cb82c22dd 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -303,6 +303,37 @@ clang_getElse (CXCursor C) return clang_getNullCursor (); } +extern "C" CXSourceLocation +clang_getElseLoc (CXCursor C) +{ + if (clang_isStatement (C.kind)) + if (const Stmt *S = getCursorStmt (C)) + switch (S->getStmtClass ()) + { + case Stmt::IfStmtClass: + return translateSLoc (getCursorTU (C), cast (S)->getElseLoc ()); + default: + return clang_getNullLocation (); + } + return clang_getNullLocation (); +} + +extern "C" CXSourceLocation +clang_getWhileLoc (CXCursor C) +{ + if (clang_isStatement (C.kind)) + if (const Stmt *S = getCursorStmt (C)) + switch (S->getStmtClass ()) + { + case Stmt::DoStmtClass: + return translateSLoc (getCursorTU (C), cast (S)->getWhileLoc ()); + default: + return clang_getNullLocation (); + } + return clang_getNullLocation (); +} + + extern "C" CXCursor clang_getSubExpr (CXCursor C) { diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 947694178..563f1243a 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -238,12 +238,6 @@ package body Instrument.C is First : Boolean); -- Add an entry to UIC.Source_Conditions - overriding procedure Curlify - (Pass : Instrument_Pass_Kind; - N : Cursor_T; - Rew : Rewriter_T); - -- Wrapper around Instrument.C.Utils.Curlify - overriding procedure Insert_MCDC_State (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; @@ -251,6 +245,18 @@ package body Instrument.C is MCDC_State : out US.Unbounded_String); -- Wrapper around Insert_MCDC_State overload + overriding procedure Insert_Text_Before + (Pass : Instrument_Pass_Kind; + Rew : Rewriter_T; + Loc : Source_Location_T; + Text : String); + + overriding procedure Insert_Text_After + (Pass : Instrument_Pass_Kind; + Rew : Rewriter_T; + Loc : Source_Location_T; + Text : String); + Record_PP_Info_Pass : aliased Record_PP_Info_Pass_Kind; Instrument_Pass : aliased Instrument_Pass_Kind; @@ -1028,16 +1034,6 @@ package body Instrument.C is end if; end Append_SCO; - ------------- - -- Curlify -- - ------------- - - overriding procedure Curlify - (Pass : Instrument_Pass_Kind; N : Cursor_T; Rew : Rewriter_T) is - begin - Curlify (N, Rew); - end Curlify; - -------------------------------- -- Find_Instrumented_Entities -- -------------------------------- @@ -1069,6 +1065,32 @@ package body Instrument.C is MCDC_State := +Insert_MCDC_State (UIC, Name); end Insert_MCDC_State; + ------------------------ + -- Insert_Text_Before -- + ------------------------ + + procedure Insert_Text_Before + (Pass : Instrument_Pass_Kind; + Rew : Rewriter_T; + Loc : Source_Location_T; + Text : String) is + begin + CX_Rewriter_Insert_Text_Before (Rew, Loc, Text); + end Insert_Text_Before; + + ----------------------- + -- Insert_Text_After -- + ----------------------- + + procedure Insert_Text_After + (Pass : Instrument_Pass_Kind; + Rew : Rewriter_T; + Loc : Source_Location_T; + Text : String) is + begin + CX_Rewriter_Insert_Text_After (Rew, Loc, Text); + end Insert_Text_After; + -------------------------- -- Instrument_Statement -- -------------------------- @@ -1382,10 +1404,13 @@ package body Instrument.C is ------------------------- procedure Traverse_Statements - (IC : in out Inst_Context; - UIC : in out C_Unit_Inst_Context; - L : Cursor_Vectors.Vector); - -- Process L, a list of statements or declarations + (IC : in out Inst_Context; + UIC : in out C_Unit_Inst_Context; + L : Cursor_Vectors.Vector; + Trailing_Braces : out Unbounded_String); + -- Process L, a list of statements or declarations. Set Trailing_Braces + -- to the list of braces that should be inserted after this statements' + -- list. procedure Traverse_Declarations (IC : in out Inst_Context; @@ -1885,15 +1910,18 @@ package body Instrument.C is ------------------------- procedure Traverse_Statements - (IC : in out Inst_Context; - UIC : in out C_Unit_Inst_Context; - L : Cursor_Vectors.Vector) + (IC : in out Inst_Context; + UIC : in out C_Unit_Inst_Context; + L : Cursor_Vectors.Vector; + Trailing_Braces : out Unbounded_String) is SC_First : constant Nat := SC.Last + 1; SD_First : constant Nat := SD.Last + 1; - procedure Traverse_One (N : Cursor_T); - -- Traverse a statement + procedure Traverse_One + (N : Cursor_T; Trailing_Braces : out Unbounded_String); + -- Traverse a statement. Set Trailing_Braces to the list of braces that + -- should be inserted after this statement. procedure Extend_Statement_Sequence (N : Cursor_T; @@ -1907,13 +1935,45 @@ package body Instrument.C is -- current CS sequence. Then output entries for all decisions nested in -- these statements, which have been deferred so far. + function Curlify (N : Cursor_T) return Boolean; + -- Rewrite control flow statements (if else, for, while etc.) with + -- braces when needed (i.e. when they do not already have them). Note + -- that the insertion of the last closing brace is deferred to the + -- traversal of the following statement, and thus, Curlify returns + -- True if the insertion of a closing brace is required. + -- + -- We can't insert this closing brace with N source location information + -- only, as the ending location of a statement expression is the end + -- location of the expression, and not the location of the semicolon + -- terminating the statement. To solve this, we choose to insert the + -- closing brace _before_ the next statement (or _before the closing + -- brace of the function body, if this is the last statement of the + -- function) rather than _after_ the statement semicolon, which can't + -- be done easily. + ------------------ -- Traverse_One -- ------------------ - procedure Traverse_One (N : Cursor_T) is + procedure Traverse_One + (N : Cursor_T; Trailing_Braces : out Unbounded_String) is use Cursor_Vectors; + TB : Unbounded_String; + -- Local to pass on to Traverse_Statements invocations. Trailing + -- braces that can be inserted while instrumenting the current node + -- (e.g. for the then part of an if-else statement, the closing + -- brace will be inserted before the else location) will be inserted. + -- For the other cases, the insertion of the closing braces will + -- be delayed to the instrumentation of the next statement (see + -- Traverse_Statements body) or, if this is the last statement, after + -- being done with the instrumentation of the function (see the body + -- of Traverse_Declarations). + begin + if Curlify (N) then + Append (Trailing_Braces, '}'); + end if; + -- Initialize or extend current statement sequence. Note that for -- special cases such as IF and SWITCH statements we will modify -- the range to exclude internal statements that should not be @@ -1931,7 +1991,7 @@ package body Instrument.C is when Cursor_Compound_Stmt => Set_Statement_Entry; - Traverse_Statements (IC, UIC, L => Get_Children (N)); + Traverse_Statements (IC, UIC, Get_Children (N), TB); -- If statement, which breaks the current statement sequence, but -- we include the condition in the current sequence. @@ -1945,23 +2005,21 @@ package body Instrument.C is begin Process_Decisions_Defer (Get_Cond (N), 'I'); Set_Statement_Entry; - - -- Now we traverse the statements in the THEN part - - UIC.Pass.Curlify (N => Then_Part, - Rew => UIC.Rewriter); Traverse_Statements - (IC, UIC, - L => To_Vector (Then_Part)); + (IC, UIC, To_Vector (Then_Part), TB); -- Traverse the ELSE statements if present if not Is_Null (Else_Part) then - UIC.Pass.Curlify (N => Else_Part, - Rew => UIC.Rewriter); + + -- Insert the trailing braces resulting from the + -- traversal of the then part before the else. + + UIC.Pass.Insert_Text_Before + (UIC.Rewriter, Get_Else_Loc (N), +TB); + TB := +""; Traverse_Statements - (IC, UIC, - L => To_Vector (Else_Part)); + (IC, UIC, To_Vector (Else_Part), TB); end if; end; @@ -1979,7 +2037,7 @@ package body Instrument.C is -- Process case branches - Traverse_Statements (IC, UIC, L => To_Vector (Alt)); + Traverse_Statements (IC, UIC, To_Vector (Alt), TB); end; -- Case alternative @@ -1988,7 +2046,8 @@ package body Instrument.C is declare Case_Body : constant Cursor_T := Get_Sub_Stmt (N); begin - Traverse_Statements (IC, UIC, L => To_Vector (Case_Body)); + Traverse_Statements + (IC, UIC, To_Vector (Case_Body), TB); end; -- Loop ends the current statement sequence, but we include @@ -2003,9 +2062,6 @@ package body Instrument.C is Cond : constant Cursor_T := Get_Cond (N); begin - UIC.Pass.Curlify (N => While_Body, - Rew => UIC.Rewriter); - -- If the loop condition is a declaration, instrument its -- initialization expression. @@ -2018,7 +2074,8 @@ package body Instrument.C is Process_Decisions_Defer (Cond, 'W'); Set_Statement_Entry; - Traverse_Statements (IC, UIC, To_Vector (While_Body)); + Traverse_Statements + (IC, UIC, To_Vector (While_Body), TB); end; -- Do while statement. Ends the current statement sequence. @@ -2029,19 +2086,26 @@ package body Instrument.C is Do_While : constant Cursor_T := Get_Cond (N); begin - UIC.Pass.Curlify (N => Do_Body, - Rew => UIC.Rewriter); + Traverse_Statements + (IC, UIC, To_Vector (Do_Body), TB); + + -- Insert the trailing braces resulting from the body + -- traversal before the while. + + UIC.Pass.Insert_Text_After + (UIC.Rewriter, Get_While_Loc (N), +TB); + TB := +""; + + -- Process the while decision - Traverse_Statements (IC, UIC, To_Vector (Do_Body)); Extend_Statement_Sequence (Do_While, 'W', Instr_Scheme => Instr_Expr); - Process_Decisions_Defer (Do_While, 'W'); Set_Statement_Entry; end; - -- For statement. Ends the current statement sequence. + -- For statement. Ends the current statement sequence when Cursor_For_Stmt => declare @@ -2062,8 +2126,8 @@ package body Instrument.C is Set_Statement_Entry; - UIC.Pass.Curlify (N => For_Body, Rew => UIC.Rewriter); - Traverse_Statements (IC, UIC, To_Vector (For_Body)); + Traverse_Statements + (IC, UIC, To_Vector (For_Body), TB); Extend_Statement_Sequence (For_Inc, ' ', Instr_Scheme => Instr_Expr); @@ -2095,8 +2159,8 @@ package body Instrument.C is -- Generate obligations for body statements - UIC.Pass.Curlify (N => For_Body, Rew => UIC.Rewriter); - Traverse_Statements (IC, UIC, To_Vector (For_Body)); + Traverse_Statements + (IC, UIC, To_Vector (For_Body), TB); end; -- Unconditional goto, which is included in the current statement @@ -2108,10 +2172,10 @@ package body Instrument.C is when Cursor_Label_Stmt => Set_Statement_Entry; - Traverse_Statements (IC, UIC, Get_Children (N)); + Traverse_Statements (IC, UIC, Get_Children (N), TB); when Cursor_Stmt_Expr => - Traverse_Statements (IC, UIC, Get_Children (N)); + Traverse_Statements (IC, UIC, Get_Children (N), TB); -- Null statement, we won't monitor their execution @@ -2135,6 +2199,8 @@ package body Instrument.C is end if; end case; + Append (Trailing_Braces, TB); + -- Traverse lambda expressions, if any. Do not register them as -- scopes. @@ -2254,6 +2320,77 @@ package body Instrument.C is end Set_Statement_Entry; + ------------- + -- Curlify -- + ------------- + + function Curlify (N : Cursor_T) return Boolean + is + Rew : Rewriter_T renames UIC.Rewriter; + begin + case Kind (N) is + when Cursor_If_Stmt => + declare + Then_Part : constant Cursor_T := Get_Then (N); + Else_Part : constant Cursor_T := Get_Else (N); + begin + if Kind (Then_Part) /= Cursor_Compound_Stmt then + UIC.Pass.Insert_Text_Before + (Rew, Start_Sloc (Then_Part), "{"); + if not Is_Null (Else_Part) then + -- Close the brace introduced to wrap the then part + -- if possible. + + UIC.Pass.Insert_Text_Before + (Rew, Get_Else_Loc (N), "}"); + else + -- Otherwise, we need to insert a trailing brace + + return True; + end if; + end if; + + -- Then, deal with the else if it is not a compound stmt + + if not Is_Null (Else_Part) + and then Kind (Else_Part) /= Cursor_Compound_Stmt + then + UIC.Pass.Insert_Text_Before + (Rew, Start_Sloc (Else_Part), "{"); + return True; + end if; + return False; + end; + + when Cursor_Do_Stmt => + declare + Do_Body : constant Cursor_T := Get_Body (N); + begin + if Kind (Do_Body) /= Cursor_Compound_Stmt then + UIC.Pass.Insert_Text_Before + (Rew, Start_Sloc (Do_Body), "{"); + UIC.Pass.Insert_Text_Before + (Rew, Get_While_Loc (N), "}"); + end if; + return False; + end; + when Cursor_While_Stmt + | Cursor_For_Stmt + | Cursor_CXX_For_Range_Stmt => + declare + B : constant Cursor_T := Get_Body (N); + begin + if Kind (B) /= Cursor_Compound_Stmt then + UIC.Pass.Insert_Text_Before (Rew, Start_Sloc (B), "{"); + return True; + end if; + return False; + end; + when others => + return False; + end case; + end Curlify; + use Cursor_Vectors; Emit_SCOs : Boolean := False; @@ -2262,7 +2399,12 @@ package body Instrument.C is begin for N of L loop - Traverse_One (N); + if Length (Trailing_Braces) /= 0 then + UIC.Pass.Insert_Text_Before + (UIC.Rewriter, Start_Sloc (N), +Trailing_Braces); + Trailing_Braces := +""; + end if; + Traverse_One (N, Trailing_Braces); Emit_SCOs := True; end loop; @@ -2308,20 +2450,27 @@ package body Instrument.C is -- a list of statements using the Get_Children -- utility. - Fun_Body : constant Cursor_Vectors.Vector := - Get_Children (Get_Body (N)); + Fun_Body : constant Cursor_T := Get_Body (N); + Stmts : constant Cursor_Vectors.Vector := + Get_Children (Fun_Body); + + TB : Unbounded_String; + -- Trailing braces that should be inserted at the end + -- of the function body. begin - if Fun_Body.Length > 0 then + if Stmts.Length > 0 then UIC.MCDC_State_Declaration_Node := - Fun_Body.First_Element; - Traverse_Statements (IC, UIC, Fun_Body); + Stmts.First_Element; + Traverse_Statements (IC, UIC, Stmts, TB); + UIC.Pass.Insert_Text_Before + (UIC.Rewriter, End_Sloc (Fun_Body), +TB); end if; end; UIC.Pass.Exit_Scope (UIC); - -- Traverse the declarations of a namespace / linkage - -- specification etc. + -- Traverse the declarations of a namespace / linkage + -- specification etc. when Cursor_Namespace | Cursor_Class_Template @@ -3664,6 +3813,8 @@ package body Instrument.C is case IC.Dump_Config.Trigger is when Main_End | Ravenscar_Task_Termination => declare + use Cursor_Vectors; + function Process (Cursor : Cursor_T) return Child_Visit_Result_T; -- Callback for Visit_Children. Insert calls to dump buffers @@ -3683,36 +3834,11 @@ package body Instrument.C is Return_Expr : constant Cursor_T := Get_Children (Cursor).First_Element; begin - -- Introduce a variable to hold the return result, - -- and replace "return ;" with - -- "{ - -- int ; - -- return =, (), ; - -- }". - -- - -- Note that we have to be careful to put braces - -- around the return statement, as the control flow - -- structures may not have been curlified yet, - -- e.g. if the main is not a unit of interest. This - -- means that: + -- Replace "return ;" with + -- "return =, (), ;" -- - -- if () - -- return ; - -- - -- should produce - -- - -- if () - -- { - -- int ; - -- return =, (), ; - -- } - -- - -- Notice how this would be wrong without the braces. - - Insert_Text_After_Start_Of - (N => Cursor, - Text => "{int gnatcov_rts_return;", - Rew => Rew.Rewriter); + -- Note that a variable declaration is + -- introduced at the beginning of the main. Insert_Text_Before_Start_Of (N => Return_Expr, @@ -3726,11 +3852,6 @@ package body Instrument.C is & "(), gnatcov_rts_return", Rew => Rew.Rewriter); - CX_Rewriter_Insert_Text_After_Token - (Rew.Rewriter, - Get_Range_End (Get_Cursor_Extent (Cursor)), - "}"); - return Child_Visit_Continue; end; else @@ -3744,21 +3865,36 @@ package body Instrument.C is end Process; begin - Visit_Children (Parent => Main_Cursor, - Visitor => Process'Access); - - -- If the last statement of the function is not a return - -- statement add a call to dump_buffers at the end of the main - -- function. declare - use Cursor_Vectors; Main_Body : constant Cursor_T := Get_Body (Main_Cursor); Main_Stmts : constant Vector := Get_Children (Main_Body); Last_Stmt : constant Cursor := Main_Stmts.Last; Insert_Sloc : Source_Location_T; - Insert : Boolean := False; + Insert : Boolean := False; begin + -- Introduce a variable to hold the return value. Declare + -- it at the start of the main to avoid complications with + -- curly braces and control flow constructs. + + if Length (Main_Stmts) /= 0 then + declare + Main_First_Stmt : constant Cursor_T := + Main_Stmts.First_Element; + begin + Insert_Text_Before_Start_Of + (N => Main_First_Stmt, + Text => "int gnatcov_rts_return;", + Rew => Rew.Rewriter); + end; + end if; + + Visit (Main_Body, Process'Access); + + -- If the last statement of the function is not a return + -- statement add a call to dump_buffers at the end of the + -- main function. + -- -- If the main is empty, insert right at the start of the -- function. @@ -3787,7 +3923,6 @@ package body Instrument.C is ";" & Dump_Procedure_Symbol (Main) & "();"); end if; end; - end; when At_Exit => diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index bf9e2df09..746c0b621 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -443,8 +443,17 @@ private Name : String; MCDC_State : out US.Unbounded_String) is null; - procedure Curlify - (Pass : Pass_Kind; N : Cursor_T; Rew : Rewriter_T) is null; + procedure Insert_Text_Before + (Pass : Pass_Kind; + Rew : Rewriter_T; + Loc : Source_Location_T; + Text : String) is null; + + procedure Insert_Text_After + (Pass : Pass_Kind; + Rew : Rewriter_T; + Loc : Source_Location_T; + Text : String) is null; type C_Source_Rewriter is limited new Ada.Finalization.Limited_Controlled with record diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index 1aafc1c7e..adab44e6b 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -73,17 +73,27 @@ package body Instrument.C_Utils is -- Start_Sloc -- ---------------- + function Start_Sloc (N : Cursor_T) return Source_Location_T is + begin + return Get_Range_Start (Get_Cursor_Extent (N)); + end Start_Sloc; + function Start_Sloc (N : Cursor_T) return Source_Location is begin - return Sloc (Get_Range_Start (Get_Cursor_Extent (N))); + return Sloc (Start_Sloc (N)); end Start_Sloc; -------------- -- End_Sloc -- -------------- + function End_Sloc (N : Cursor_T) return Source_Location_T is + begin + return Get_Range_End (Get_Cursor_Extent (N)); + end End_Sloc; + function End_Sloc (N : Cursor_T) return Source_Location is - Loc : Source_Location_T := Get_Range_End (Get_Cursor_Extent (N)); + Loc : Source_Location_T := End_Sloc (N); begin if Is_Macro_Location (Loc) then Loc := Get_Expansion_End (Get_Cursor_TU (N), Loc); @@ -375,26 +385,6 @@ package body Instrument.C_Utils is Insert => Text); end Insert_Text_Before_End_Of; - ------------- - -- Curlify -- - ------------- - - procedure Curlify (N : Cursor_T; Rew : Rewriter_T) is - begin - case Kind (N) is - when Cursor_Compound_Stmt => - null; - when others => - declare - Location_After : constant Source_Location_T := - Get_Range_End (Get_Cursor_Extent (N)); - begin - Insert_Text_After_Start_Of (N, "{", Rew); - CX_Rewriter_Insert_Text_After_Token (Rew, Location_After, "}"); - end; - end case; - end Curlify; - -------------------- -- Iterate_Tokens -- -------------------- diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 336655c0f..85141afb4 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -40,9 +40,11 @@ package Instrument.C_Utils is function Sloc (Loc : Source_Location_T) return Source_Location; -- Convert a Source_Location_T to a Source_Location + function Start_Sloc (N : Cursor_T) return Source_Location_T; function Start_Sloc (N : Cursor_T) return Source_Location; -- Return the starting location of a node + function End_Sloc (N : Cursor_T) return Source_Location_T; function End_Sloc (N : Cursor_T) return Source_Location; -- Return the end location of a node @@ -130,15 +132,6 @@ package Instrument.C_Utils is -- If this procedure is called multiple times with the same N as parameter, -- the string will be inserted _before_ any previously inserted string. - procedure Curlify (N : Cursor_T; Rew : Rewriter_T) - with Pre => not Is_Null (N); - -- If the node N is not a compound statement, rewrite it by surrounding it - -- with curly braces. Otherwise, do nothing. - -- - -- If other text was previously inserted at the same location (N start loc, - -- and N end loc), then the curly brace will be appended after that text, - -- so make sure to call Curlify before further rewriting. - procedure Iterate_Tokens (TU : Translation_Unit_T; N : Cursor_T; From 5de4d631d0eaab993e44e17b29aa4e79f746c090 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 8 Nov 2022 10:34:17 +0100 Subject: [PATCH 0088/1483] C instrumentation: accept response file for --c[++]-opts switch TN: VB03-009 --- tools/gnatcov/gnatcov_bits_specific.adb | 3 +++ tools/gnatcov/instrument-c.adb | 13 +++++++------ tools/gnatcov/switches.ads | 3 +++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 19cb52241..6fa57af67 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1020,6 +1020,9 @@ procedure GNATcov_Bits_Specific is end; end if; + Copy_Arg_List (Opt_C_Opts, C_Opts); + Copy_Arg_List (Opt_CPP_Opts, CPP_Opts); + when others => null; end case; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 563f1243a..159b4bf9c 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -34,12 +34,12 @@ with Interfaces; use Interfaces; with Interfaces.C; use Interfaces.C; with Interfaces.C.Strings; use Interfaces.C.Strings; -with Command_Line; with ALI_Files; use ALI_Files; with Coverage; use Coverage; with Coverage_Options; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Hex_Images; use Hex_Images; +with Inputs; use Inputs; with Instrument.C_Utils; use Instrument.C_Utils; with Outputs; use Outputs; with Paths; use Paths; @@ -4541,13 +4541,14 @@ package body Instrument.C is Info : Project_Info; Filename : String) is - Opt : constant Command_Line.String_List_Options := - (case Language is - when C_Language => Command_Line.Opt_C_Opts, - when CPP_Language => Command_Line.Opt_CPP_Opts); + Cmdline_Opts : constant String_Vectors.Vector := + To_String_Vector + (case Language is + when C_Language => C_Opts, + when CPP_Language => CPP_Opts); begin Import_From_Project (Self, Language, Info, Filename); - for Args of Switches.Args.String_List_Args (Opt) loop + for Args of Cmdline_Opts loop Import_From_Args (Self, Split_Args (Args)); end loop; diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index cb3de1994..51e5b80cd 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -129,6 +129,9 @@ package Switches is Units_Inputs : Inputs.Inputs_Type; -- List of names for requested units of interest + C_Opts : Inputs.Inputs_Type; + CPP_Opts : Inputs.Inputs_Type; + type Any_Language is (All_Languages, Ada_Language, C_Language, CPP_Language); -- A language that is supported for source coverage All_Languages is a From 0fee28e079a4a9c2ca261496926100bd11950de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 1 Dec 2022 15:32:05 +0100 Subject: [PATCH 0089/1483] Doc: Update documentation after changes in the GS integration This change reflects the changes that were made in GNATstudio in the handling of coverage preferences for gnatcov. TN: VB18-035 --- doc/gnatcov/gps.rst | 13 ++++++++----- doc/gnatcov/gps_screenshots/3-cov-level.png | Bin 74553 -> 53352 bytes 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/gnatcov/gps.rst b/doc/gnatcov/gps.rst index d180e1d8b..a949403aa 100644 --- a/doc/gnatcov/gps.rst +++ b/doc/gnatcov/gps.rst @@ -8,16 +8,19 @@ coverage without leaving your favorite editor. Basic usage =========== -As a first step, indicate which coverage criterion GNATcoverage should use. -The default is stmt. +As a first step, indicate which coverage criterion GNATcoverage should use +through the :ref:`project file`. If no coverage level is set +in the project file, gnatcov will default to ``stmt``, and emit a warning +indicating that the coverage level is not set. For this, go to the project properties (:menuselection:`Edit --> Project Properties...`). .. image:: gps_screenshots/3-cov-level.png -In the GNATcov entry, you can change the coverage level passed to |gcv| commands -in the corresponding *Coverage level* combo boxes. Change both to -``stmt+decision``. +In the :menuselection:`Build --> Switches --> GNATcoverage` entry, you can +change the coverage level passed to |gcv| commands in the corresponding +*Coverage level* combo +box. Change it to ``stmt+decision``. This is all for the setup part. Then you just need to click on the *Run GNATcoverage* toolbar button as shown in the following screenshot. diff --git a/doc/gnatcov/gps_screenshots/3-cov-level.png b/doc/gnatcov/gps_screenshots/3-cov-level.png index 5e2bb3a6456609685eb155cc0f5109b8da935118..256fe5d9784631d76eabfd0462927747a4bd391d 100644 GIT binary patch literal 53352 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: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 `gUPvaueg#Pq*akL0C3d`S! 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 Date: Thu, 1 Dec 2022 15:50:29 +0100 Subject: [PATCH 0090/1483] gnatcov/gen_prj_trees.py: Delete .dot after image generation This prevents untracked files from lingering after generating the documentation. no-tn-check --- doc/gnatcov/gen_prjtrees.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/gnatcov/gen_prjtrees.py b/doc/gnatcov/gen_prjtrees.py index 52b037d40..3ccadcc36 100644 --- a/doc/gnatcov/gen_prjtrees.py +++ b/doc/gnatcov/gen_prjtrees.py @@ -1,5 +1,6 @@ import re import subprocess +import os def render(tree): @@ -29,5 +30,6 @@ def gen_tree(tmpl, outfile, selected): for k in trees: gen_tree(tmpl, open(k + ".dot", "w"), trees[k]) render(k) + os.remove (f"{k}.dot") render('prjtree') From ba6d0e480ebf95270c3369f50043dd16ae668fe2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Nov 2022 15:46:39 +0000 Subject: [PATCH 0091/1483] Introduce fingerprints for buffer bit maps in SIDs and source traces This new fingerprint allows "gnatcov coverage" to detect and reject a source trace entry that reference bit maps which do not correlate with the bit maps that gnatcov read from SID files. This can arise when instrumenting and running a program a first time to create both SID files and source traces, and then re-instrumenting that program, either with a different version of gnatcov (which can allocate different buffer bits for the same SCOs) or with different parameters (for instance a different coverage level, which creates different buffer bits). Having a fingerprint to check SID/source trace files consistency allows gnatcov to reject the inconsistency with a helpful warning (pointing at the source of the inconsistency), rather than crashing as it does currently. Note that it is not possible to use the existing CU fingerprint, computed from low level SCOs, since we need it to be computed when creating the CU itself (the fingerprint is used to check whether another CU exists for the same unit). Bit maps are computed at a later stage (only once the high level SCOs have been created), so bit maps cannot contribute to the CU fingerprint computation. TN: VB21-022 Change-Id: I2254511415e0961ddcd4e8d6ed9e57facc962daf Depends-On: I307f4283ef5e0684b8c1d6962a2960368ebe4b9d --- testsuite/SUITE/srctracelib.py | 24 ++-- tools/gnatcov/checkpoints.ads | 3 +- tools/gnatcov/coverage-source.adb | 18 +-- tools/gnatcov/coverage-source.ads | 13 +- tools/gnatcov/instrument-ada_unit.adb | 15 ++- tools/gnatcov/instrument-c.adb | 24 ++-- tools/gnatcov/instrument-common.adb | 24 ++++ tools/gnatcov/instrument-common.ads | 10 ++ tools/gnatcov/instrument-input_traces.adb | 47 +++++--- tools/gnatcov/instrument-input_traces.ads | 13 +- tools/gnatcov/rts/gnatcov_rts-buffers.ads | 1 + tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 6 + .../gnatcov/rts/gnatcov_rts_c-traces-output.c | 4 +- tools/gnatcov/rts/gnatcov_rts_c-traces.h | 13 +- tools/gnatcov/sc_obligations.adb | 111 +++++++++++++++--- tools/gnatcov/sc_obligations.ads | 4 + tools/gnatcov/traces_source.ads | 34 ++++-- 17 files changed, 263 insertions(+), 101 deletions(-) diff --git a/testsuite/SUITE/srctracelib.py b/testsuite/SUITE/srctracelib.py index 7f3d227e8..a43943212 100755 --- a/testsuite/SUITE/srctracelib.py +++ b/testsuite/SUITE/srctracelib.py @@ -40,7 +40,8 @@ ('unit_part', 'B'), ('bit_buffer_encoding', 'B'), ('fingerprint', '20B'), - ('padding', '5B'), + ('bit_maps_fingerprint', '20B'), + ('padding', 'B'), ) @@ -95,7 +96,7 @@ class SrcTraceFile(object): MAGIC = b'GNATcov source trace file' + b'\x00' * 7 - FORMAT_VERSION = 1 + FORMAT_VERSION = 2 ENDIANITY_NAMES = { 0: 'little-endian', @@ -190,9 +191,11 @@ def format_buffer(b): print(' Endianity: {}'.format(self.endianity)) print('') for e in self.entries: - print(' Unit {} ({}, fingerprint={})'.format( + print(' Unit {} ({}, SCOS hash={}, bit maps hash={})'.format( e.unit_name, e.unit_part, - ''.join('{:02x}'.format(b) for b in e.fingerprint))) + ''.join('{:02x}'.format(b) for b in e.fingerprint), + ''.join('{:02x}'.format(b) for b in e.bit_maps_fingerprint) + )) print(' Project: {}'.format(e.project_name)) print(' Stmt buffer: {}'.format(format_buffer(e.stmt_buffer))) print(' Dc buffer: {}'.format(format_buffer(e.dc_buffer))) @@ -274,12 +277,14 @@ class TraceEntry(object): value: key for key, value in BIT_BUFFER_ENCODING_NAMES.items()} def __init__(self, language, unit_part, unit_name, project_name, - fingerprint, stmt_buffer, dc_buffer, mcdc_buffer): + fingerprint, bit_maps_fingerprint, stmt_buffer, dc_buffer, + mcdc_buffer): self.language = language self.unit_part = unit_part self.unit_name = unit_name self.project_name = project_name self.fingerprint = fingerprint + self.bit_maps_fingerprint = bit_maps_fingerprint self.stmt_buffer = stmt_buffer self.dc_buffer = dc_buffer self.mcdc_buffer = mcdc_buffer @@ -298,7 +303,7 @@ def read(cls, fp, trace_file, big_endian): language = cls.LANGUAGE_NAMES[header['language']] - if header['padding'] != (0, ) * 5: + if header['padding'] != 0: raise ValueError('Invalid padding: {}' .format(header['padding'])) @@ -328,8 +333,8 @@ def read(cls, fp, trace_file, big_endian): header['mcdc_bit_count']) return cls(language, unit_part, unit_name, project_name, - header['fingerprint'], stmt_buffer, dc_buffer, - mcdc_buffer) + header['fingerprint'], header['bit_maps_fingerprint'], + stmt_buffer, dc_buffer, mcdc_buffer) def write(self, fp, big_endian, alignment): """Write this trace info entry to the `fp` file.""" @@ -344,7 +349,8 @@ def write(self, fp, big_endian, alignment): 'bit_buffer_encoding': self.BIT_BUFFER_ENCODING_CODES['lsb_first_bytes'], 'fingerprint': self.fingerprint, - 'padding': (0, ) * 5, + 'bit_maps_fingerprint': self.bit_maps_fingerprint, + 'padding': 0, }, big_endian=big_endian) write_aligned(fp, self.unit_name, alignment) diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index af4b5e497..8de4d9de5 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -32,7 +32,7 @@ with SC_Obligations; use SC_Obligations; package Checkpoints is - subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 10; + subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 11; -- For compatibility with previous Gnatcov versions, the checkpoint -- file format is versioned. -- @@ -47,6 +47,7 @@ package Checkpoints is -- 8 -- Add macro expansion information -- 9 -- Add the support for scoped metrics -- 10 -- Add non instrumented SCOs sets + -- 11 -- fingerprints for buffer bit maps -- -- Note that we always use the last version when creating a checkpoint. diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 773331ce9..978fd216f 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -1701,12 +1701,13 @@ package body Coverage.Source is end Compute_Source_Coverage; procedure Compute_Source_Coverage - (Filename : String; - Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; - Stmt_Buffer : Coverage_Buffer; - Decision_Buffer : Coverage_Buffer; - MCDC_Buffer : Coverage_Buffer) + (Filename : String; + Fingerprint : SC_Obligations.Fingerprint_Type; + CU_Name : Compilation_Unit_Name; + Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; + Stmt_Buffer : Coverage_Buffer; + Decision_Buffer : Coverage_Buffer; + MCDC_Buffer : Coverage_Buffer) is CU : CU_Id; BM : CU_Bit_Maps; @@ -1781,7 +1782,10 @@ package body Coverage.Source is -- Sanity check that Fingerprint is consistent with what the -- instrumenter recorded in the CU info. - if Fingerprint /= SC_Obligations.Fingerprint (CU) then + if Fingerprint /= SC_Obligations.Fingerprint (CU) + or else + Bit_Maps_Fingerprint /= SC_Obligations.Bit_Maps_Fingerprint (CU) + then Warn ("traces for " & Unit_Image & " (from " & Filename & ") are" & " inconsistent with the corresponding Source Instrumentation" & " Data"); diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 5234bbef8..7ea312310 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -49,12 +49,13 @@ package Coverage.Source is -- determine the coverage state of each SCO. procedure Compute_Source_Coverage - (Filename : String; - Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; - Stmt_Buffer : Coverage_Buffer; - Decision_Buffer : Coverage_Buffer; - MCDC_Buffer : Coverage_Buffer); + (Filename : String; + Fingerprint : SC_Obligations.Fingerprint_Type; + CU_Name : Compilation_Unit_Name; + Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; + Stmt_Buffer : Coverage_Buffer; + Decision_Buffer : Coverage_Buffer; + MCDC_Buffer : Coverage_Buffer); -- Analyze source instrumentation traces to determine the coverage state -- of each SCO. Generic actual for -- Instrument.Input_Traces.Generic_Read_Source_Trace_File. diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index d2690a9f8..17bbaf62e 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -63,6 +63,11 @@ package body Instrument.Ada_Unit is -- and thus to check that it works as expected. This is the role of the -- following helpers. + function Format_Fingerprint + (Fingerprint : SC_Obligations.Fingerprint_Type) return String + is (Instrument.Common.Format_Fingerprint (Fingerprint, "(", ")")); + -- Helper to format a String literal for a fingerprint + ------------------------------- -- Create_Context_Instrument -- ------------------------------- @@ -7069,8 +7074,9 @@ package body Instrument.Ada_Unit is File.Put_Line (" Buffers : aliased constant" & " GNATcov_RTS_Coverage_Buffers :="); - File.Put_Line (" (Fingerprint => " - & To_String (Fingerprint) & ","); + File.Put_Line + (" (Fingerprint => " + & Format_Fingerprint (SC_Obligations.Fingerprint (UIC.CU)) & ","); File.Put_Line (" Language => Unit_Based_Language,"); File.Put_Line (" Unit_Part => " & Unit_Part & ","); @@ -7080,6 +7086,11 @@ package body Instrument.Ada_Unit is File.Put_Line (" Project_Name =>" & " (Project_Name'Address, Project_Name'Length),"); + File.Put_Line + (" Bit_Maps_Fingerprint => " + & Format_Fingerprint (SC_Obligations.Bit_Maps_Fingerprint (UIC.CU)) + & ","); + File.Put_Line (" Statement => Statement_Buffer'Address,"); File.Put_Line (" Decision => Decision_Buffer'Address,"); File.Put_Line (" MCDC => MCDC_Buffer'Address,"); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 159b4bf9c..65011aba2 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -425,7 +425,8 @@ package body Instrument.C is -- Otherwise, put one array item per line. function Format_Fingerprint - (Fingerprint : SC_Obligations.Fingerprint_Type) return String; + (Fingerprint : SC_Obligations.Fingerprint_Type) return String + is (Instrument.Common.Format_Fingerprint (Fingerprint, "{", "}")); -- Helper to format a uint8_t[] literal for a SCOs fingerprint function Format_Def @@ -3362,22 +3363,6 @@ package body Instrument.C is return To_String (Result); end Format_Array_Init_Expr; - ------------------------ - -- Format_Fingerprint -- - ------------------------ - - function Format_Fingerprint - (Fingerprint : SC_Obligations.Fingerprint_Type) return String - is - Items : String_Vectors.Vector; - begin - for Byte of Fingerprint loop - Items.Append (+Img (Integer (Byte))); - end loop; - - return Format_Array_Init_Expr (Items); - end Format_Fingerprint; - ---------------------- -- Emit_Buffer_Unit -- ---------------------- @@ -3554,6 +3539,11 @@ package body Instrument.C is & Format_Str_Constant (+CU_Name.Project_Name) & "," & ASCII.LF + & " .bit_maps_fingerprint = " + & Format_Fingerprint (SC_Obligations.Bit_Maps_Fingerprint (CU)) + & "," + & ASCII.LF + -- We do not use the created pointer (Statement_Buffer) to -- initialize the buffer fields, as this is rejected by old -- versions of the compiler (up to the 20 version): the diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 7aed8f91f..0ec387cb7 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -178,6 +178,30 @@ package body Instrument.Common is end if; end Project_Output_Dir; + ------------------------ + -- Format_Fingerprint -- + ------------------------ + + function Format_Fingerprint + (Fingerprint : SC_Obligations.Fingerprint_Type; + Opening, Closing : String) return String + is + Result : Unbounded_String; + First : Boolean := True; + begin + Append (Result, Opening); + for Byte of Fingerprint loop + if First then + First := False; + else + Append (Result, ", "); + end if; + Append (Result, Strings.Img (Integer (Byte))); + end loop; + Append (Result, Closing); + return To_String (Result); + end Format_Fingerprint; + --------------------- -- Start_Rewriting -- --------------------- diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index d59162d95..8c413e618 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -155,6 +155,16 @@ package Instrument.Common is -- Project. This retuns an empty strings for projects that do not have an -- object directory. + function Format_Fingerprint + (Fingerprint : SC_Obligations.Fingerprint_Type; + Opening, Closing : String) return String; + -- Somewhat language agnostic formatter for fingerprint values in generated + -- code. + -- + -- Opening and Closing are strings used at the beginning and the end of the + -- returned literal expression (aggregate in Ada, compound expression in + -- C/C++). + package File_Sets is new Ada.Containers.Hashed_Sets (Element_Type => Ada.Strings.Unbounded.Unbounded_String, "=" => Ada.Strings.Unbounded."=", diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 32ebf745c..c750a7ad1 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -527,7 +527,7 @@ package body Instrument.Input_Traces is Create_Error (Result, "invalid bit buffer encoding"); return False; - elsif Raw_Header.Padding /= (1 .. 5 => ASCII.NUL) then + elsif Raw_Header.Padding /= (1 => ASCII.NUL) then Create_Error (Result, "invalid entry header padding"); return False; end if; @@ -698,8 +698,10 @@ package body Instrument.Input_Traces is function Convert is new Ada.Unchecked_Conversion (GNATcov_RTS.Buffers.Fingerprint_Type, SC_Obligations.Fingerprint_Type); - Fingerprint : constant SC_Obligations.Fingerprint_Type := + Fingerprint : constant SC_Obligations.Fingerprint_Type := Convert (Entry_Header.Fingerprint); + Bit_Maps_Fingerprint : constant SC_Obligations.Fingerprint_Type := + Convert (Entry_Header.Bit_Maps_Fingerprint); Statement_Buffer_Size : constant Natural := Buffer_Size (Entry_Header.Bit_Buffer_Encoding, @@ -771,8 +773,10 @@ package body Instrument.Input_Traces is end case; On_Trace_Entry - (Filename, Fingerprint, + (Filename, + Fingerprint, CU_Name, + Bit_Maps_Fingerprint, Statement_Buffer (0 .. Last_Bit (Entry_Header.Statement_Bit_Count)), Decision_Buffer @@ -799,12 +803,13 @@ package body Instrument.Input_Traces is (Kind : Traces_Source.Supported_Info_Kind; Data : String); procedure On_Trace_Entry - (Filename : String; - Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; - Stmt_Buffer : Coverage_Buffer; - Decision_Buffer : Coverage_Buffer; - MCDC_Buffer : Coverage_Buffer); + (Filename : String; + Fingerprint : SC_Obligations.Fingerprint_Type; + CU_Name : Compilation_Unit_Name; + Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; + Stmt_Buffer : Coverage_Buffer; + Decision_Buffer : Coverage_Buffer; + MCDC_Buffer : Coverage_Buffer); -- Callbacks for Read_Source_Trace_File Last_Is_Info : Boolean := False; @@ -838,12 +843,13 @@ package body Instrument.Input_Traces is -------------------- procedure On_Trace_Entry - (Filename : String; - Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; - Stmt_Buffer : Coverage_Buffer; - Decision_Buffer : Coverage_Buffer; - MCDC_Buffer : Coverage_Buffer) + (Filename : String; + Fingerprint : SC_Obligations.Fingerprint_Type; + CU_Name : Compilation_Unit_Name; + Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; + Stmt_Buffer : Coverage_Buffer; + Decision_Buffer : Coverage_Buffer; + MCDC_Buffer : Coverage_Buffer) is pragma Unreferenced (Filename); use Ada.Text_IO; @@ -856,14 +862,21 @@ package body Instrument.Input_Traces is case CU_Name.Language_Kind is when GNATcov_RTS.Buffers.Unit_Based_Language => Put ("Unit " & To_Ada (CU_Name.Unit) & " (" & CU_Name.Part'Image - & ", hash="); + & ", "); when GNATcov_RTS.Buffers.File_Based_Language => - Put ("Unit " & (+CU_Name.Filename) & " (hash="); + Put ("Unit " & (+CU_Name.Filename) & " ("); end case; + Put ("SCOs hash="); for B of Fingerprint loop Put (Hex_Images.Hex_Image (Interfaces.Unsigned_8 (B))); end loop; + + Put (", bit maps hash="); + for B of Bit_Maps_Fingerprint loop + Put (Hex_Images.Hex_Image (Interfaces.Unsigned_8 (B))); + end loop; + Put_Line (")"); Dump_Buffer ("Statement", Stmt_Buffer); Dump_Buffer ("Decision", Decision_Buffer); diff --git a/tools/gnatcov/instrument-input_traces.ads b/tools/gnatcov/instrument-input_traces.ads index cf048f4a4..f1fe7c1b7 100644 --- a/tools/gnatcov/instrument-input_traces.ads +++ b/tools/gnatcov/instrument-input_traces.ads @@ -34,12 +34,13 @@ package Instrument.Input_Traces is (Kind : Traces_Source.Supported_Info_Kind; Data : String) is <>; with procedure On_Trace_Entry - (Filename : String; - Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; - Stmt_Buffer : Coverage_Buffer; - Decision_Buffer : Coverage_Buffer; - MCDC_Buffer : Coverage_Buffer) is <>; + (Filename : String; + Fingerprint : SC_Obligations.Fingerprint_Type; + CU_Name : Compilation_Unit_Name; + Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; + Stmt_Buffer : Coverage_Buffer; + Decision_Buffer : Coverage_Buffer; + MCDC_Buffer : Coverage_Buffer) is <>; procedure Generic_Read_Source_Trace_File (Filename : String; Result : out Traces_Files.Read_Result); diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index bb6b56135..a1fda80fb 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -73,6 +73,7 @@ package GNATcov_RTS.Buffers is Unit_Part : Any_Unit_Part; Unit_Name : GNATcov_RTS_String; Project_Name : GNATcov_RTS_String; + Bit_Maps_Fingerprint : Fingerprint_Type; Statement, Decision, MCDC : System.Address; Statement_Last_Bit, Decision_Last_Bit, MCDC_Last_Bit : Any_Bit_Id; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index 14ee79c33..ad584520f 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -97,6 +97,12 @@ extern "C" file-based languages (otherwise, it is an empty string). */ struct gnatcov_rts_string project_name; + /* Hash of buffer bit mappings for this unit, as gnatcov computes it (see + SC_Obligations). Used as a fast way to check that gnatcov will be able + to interpret buffer bits from a source traces using buffer bit mappings + from SID files. */ + uint8_t bit_maps_fingerprint[FINGERPRINT_SIZE]; + /* Pointers to coverage buffers for statement obligations, decision obligations and MC/DC obligations. The size of each array is in the corresponding *_last_bit field. */ diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index c692ad556..7d7b322ba 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -126,8 +126,10 @@ write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, header.language_kind = (uint8_t) buffers->language_kind; header.unit_part = (uint8_t) buffers->unit_part; header.bit_buffer_encoding = GNATCOV_RTS_LSB_FIRST_BYTES; - memset (header.padding, 0, 5); + memset (header.padding, 0, 1); memcpy (&header.fingerprint, buffers->fingerprint, FINGERPRINT_SIZE); + memcpy (&header.bit_maps_fingerprint, buffers->bit_maps_fingerprint, + FINGERPRINT_SIZE); write_bytes (output, (char *) &header, sizeof (header)); write_bytes (output, buffers->unit_name.str, buffers->unit_name.length); diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces.h b/tools/gnatcov/rts/gnatcov_rts_c-traces.h index bab0b7ec5..386066ab1 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces.h @@ -30,8 +30,9 @@ extern "C" /* Expected value of the `trace_file_header.format_version` field. 0 -- initial version - 1 -- extend trace entry model to account for C files */ -#define GNATCOV_RTS_CURRENT_VERSION 1 + 1 -- extend trace entry model to account for C files + 2 -- introduce fingerprints for bit maps */ +#define GNATCOV_RTS_CURRENT_VERSION 2 /* LSB_First_Bytes: bit buffers are encoded as sequences of bytes. @@ -139,9 +140,15 @@ extern "C" values are computed during instrumentation. */ uint8_t fingerprint[20]; + /* Hash of buffer bit mappings for this unit, as gnatcov computes it (see + SC_Obligations). Used as a fast way to check that gnatcov will be able + to interpret buffer bits from a source traces using buffer bit mappings + from SID files. */ + uint8_t bit_maps_fingerprint[20]; + /* Padding used only to make the size of this trace entry header a multiple of 8 bytes. Must be zero. */ - uint8_t padding[5]; + uint8_t padding[1]; }; #ifdef __cplusplus diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 9cc09148c..6ede290cd 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -112,6 +112,9 @@ package body SC_Obligations is when Instrumenter => Bit_Maps : CU_Bit_Maps; -- Mapping of bits in coverage buffers to SCOs + + Bit_Maps_Fingerprint : Fingerprint_Type; + -- Hash of Bit_Maps, for consistency checks with source traces end case; end record; @@ -1285,13 +1288,31 @@ package body SC_Obligations is & Provider_Image (CP_CU.Provider) & " and from " & Provider_Image (CU_Record.Provider)); - -- Ignore also when the fingerprint does not match - - elsif CP_CU.Fingerprint /= CU_Record.Fingerprint then + -- Ignore also when the fingerprints do not match. + -- + -- Note that only recent enough SID files contain buffer bit maps + -- and their fingerprints. Bit_Maps_Fingerprint is left to + -- No_Fingerprint for checkpoints. Skip the consistency check for + -- these cases, and if the loaded CU has these fingerprints, + -- record them for later consistency checks. + + elsif CP_CU.Fingerprint /= CU_Record.Fingerprint + or else + (CP_CU.Provider = Instrumenter + and then CP_CU.Bit_Maps_Fingerprint /= No_Fingerprint + and then CU_Record.Bit_Maps_Fingerprint /= No_Fingerprint + and then CP_CU.Bit_Maps_Fingerprint + /= CU_Record.Bit_Maps_Fingerprint) + then Warn ("unexpected fingerprint, cannot merge coverage" & " information for " & CU_Image); else + if CU_Record.Provider = Instrumenter + and then CU_Record.Bit_Maps_Fingerprint = No_Fingerprint + then + CU_Record.Bit_Maps_Fingerprint := CP_CU.Bit_Maps_Fingerprint; + end if; Checkpoint_Load_Merge_Unit (CLS, CP_CU => CP_CU, @@ -1378,23 +1399,37 @@ package body SC_Obligations is SCO_PP_Info_Maps.Map'Read (S, V.PP_Info_Map); end if; - -- Checkpoint version 2 data (instrumentation support) + case V.Provider is + when Compiler => + null; + when Instrumenter => + + -- Checkpoint version 2 data (instrumentation support) - if not Version_Less (S, Than => 2) then - case V.Provider is - when Compiler => - null; - when Instrumenter => - if Purpose_Of (S) = Instrumentation then - V.Bit_Maps.Statement_Bits := - new Statement_Bit_Map'(Statement_Bit_Map'Input (S)); - V.Bit_Maps.Decision_Bits := - new Decision_Bit_Map'(Decision_Bit_Map'Input (S)); - V.Bit_Maps.MCDC_Bits := - new MCDC_Bit_Map'(MCDC_Bit_Map'Input (S)); + -- By default, use "no fingerprint" for buffer bit maps + -- fingerprints: either the SID file we load is too old to have + -- such fingerprints, either we are loading a checkpoint, and by + -- design checkpoints contains neither bit maps nor their + -- fingerprints (all source traces are processed before loading + -- checkpoints, and bit maps are needed only to interpret source + -- traces). + + V.Bit_Maps_Fingerprint := No_Fingerprint; + + if not Version_Less (S, Than => 2) + and then Purpose_Of (S) = Instrumentation + then + V.Bit_Maps.Statement_Bits := + new Statement_Bit_Map'(Statement_Bit_Map'Input (S)); + V.Bit_Maps.Decision_Bits := + new Decision_Bit_Map'(Decision_Bit_Map'Input (S)); + V.Bit_Maps.MCDC_Bits := + new MCDC_Bit_Map'(MCDC_Bit_Map'Input (S)); + if not Version_Less (S, Than => 11) then + Fingerprint_Type'Read (S, V.Bit_Maps_Fingerprint); end if; - end case; - end if; + end if; + end case; -- Checkpoint version 8 data (scoped metrics support) @@ -1454,6 +1489,7 @@ package body SC_Obligations is (S, V.Bit_Maps.Decision_Bits.all); MCDC_Bit_Map'Output (S, V.Bit_Maps.MCDC_Bits.all); + Fingerprint_Type'Write (S, V.Bit_Maps_Fingerprint); end if; end case; @@ -2583,6 +2619,15 @@ package body SC_Obligations is return CU_Vector.Reference (CU).Fingerprint; end Fingerprint; + -------------------------- + -- Bit_Maps_Fingerprint -- + -------------------------- + + function Bit_Maps_Fingerprint (CU : CU_Id) return Fingerprint_Type is + begin + return CU_Vector.Reference (CU).Bit_Maps_Fingerprint; + end Bit_Maps_Fingerprint; + --------------- -- Load_SCOs -- --------------- @@ -4126,8 +4171,36 @@ package body SC_Obligations is ------------------ procedure Set_Bit_Maps (CU : CU_Id; Bit_Maps : CU_Bit_Maps) is + use GNAT.SHA1; + + Info : CU_Info renames CU_Vector.Reference (CU); + Ctx : GNAT.SHA1.Context; + LF : constant String := (1 => ASCII.LF); begin - CU_Vector.Reference (CU).Bit_Maps := Bit_Maps; + Info.Bit_Maps := Bit_Maps; + + -- Compute the fingerprint for these bit maps + + Update (Ctx, "stmt:"); + for Id of Bit_Maps.Statement_Bits.all loop + Update (Ctx, Id'Image); + end loop; + Update (Ctx, LF); + + Update (Ctx, "dc:"); + for D of Bit_Maps.Decision_Bits.all loop + Update (Ctx, D.D_SCO'Image & ":" & D.Outcome'Image); + end loop; + Update (Ctx, LF); + + Update (Ctx, "mcdc:"); + for M of Bit_Maps.MCDC_Bits.all loop + Update (Ctx, M.D_SCO'Image & ":" & M.Path_Index'Image); + end loop; + Update (Ctx, LF); + + Info.Bit_Maps_Fingerprint := Fingerprint_Type + (GNAT.SHA1.Binary_Message_Digest'(GNAT.SHA1.Digest (Ctx))); end Set_Bit_Maps; ---------------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index ca9acd43f..9bd3ccd80 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -98,10 +98,14 @@ package SC_Obligations is -- Return the SCO provider corresponding to the given compilation unit type Fingerprint_Type is new GNAT.SHA1.Binary_Message_Digest; + No_Fingerprint : constant Fingerprint_Type := (others => 0); function Fingerprint (CU : CU_Id) return Fingerprint_Type; -- Hash of SCO info in ALI, for incremental coverage consistency check + function Bit_Maps_Fingerprint (CU : CU_Id) return Fingerprint_Type; + -- Hash of buffer bit mappings in CU + function Comp_Unit (Src_File : Source_File_Index) return CU_Id; -- Return the identifier for the compilation unit containing the given -- source, or No_CU_Id if no such LI file has been loaded. diff --git a/tools/gnatcov/traces_source.ads b/tools/gnatcov/traces_source.ads index 208a26bb3..230867cd4 100644 --- a/tools/gnatcov/traces_source.ads +++ b/tools/gnatcov/traces_source.ads @@ -50,11 +50,12 @@ package Traces_Source is -- trace entries start and end on byte/half word/word/long word boundaries. type Trace_File_Format_Version is new Unsigned_32; - Current_Version : Trace_File_Format_Version := 1; + Current_Version : Trace_File_Format_Version := 2; -- Expected value of the Trace_File_Header.Format_Version field. -- -- 0 -- initial version -- 1 -- extend trace entry model to account for C files + -- 2 -- introduce fingerprints for bit maps type Any_Alignment is new Unsigned_8; subtype Supported_Alignment is Any_Alignment; @@ -249,24 +250,31 @@ package Traces_Source is -- coverage obligations and coverage data are consistent. Specific hash -- values are computed during instrumentation. - Padding : String (1 .. 5); + Bit_Maps_Fingerprint : Buffers.Fingerprint_Type; + -- Hash of buffer bit mappings for this unit, as gnatcov computes it + -- (see SC_Obligations). Used as a fast way to check that gnatcov will + -- be able to interpret buffer bits from a source traces using buffer + -- bit mappings from SID files. + + Padding : String (1 .. 1); -- Padding used only to make the size of this trace entry header a -- multiple of 8 bytes. Must be zero. end record; for Trace_Entry_Header use record - Unit_Name_Length at 0 range 0 .. 31; - Project_Name_Length at 4 range 0 .. 31; - Statement_Bit_Count at 8 range 0 .. 31; - Decision_Bit_Count at 12 range 0 .. 31; - MCDC_Bit_Count at 16 range 0 .. 31; - Language_Kind at 20 range 0 .. 7; - Unit_Part at 21 range 0 .. 7; - Bit_Buffer_Encoding at 22 range 0 .. 7; - Fingerprint at 23 range 0 .. 20 * 8 - 1; - Padding at 43 range 0 .. 5 * 8 - 1; + Unit_Name_Length at 0 range 0 .. 31; + Project_Name_Length at 4 range 0 .. 31; + Statement_Bit_Count at 8 range 0 .. 31; + Decision_Bit_Count at 12 range 0 .. 31; + MCDC_Bit_Count at 16 range 0 .. 31; + Language_Kind at 20 range 0 .. 7; + Unit_Part at 21 range 0 .. 7; + Bit_Buffer_Encoding at 22 range 0 .. 7; + Fingerprint at 23 range 0 .. 20 * 8 - 1; + Bit_Maps_Fingerprint at 43 range 0 .. 20 * 8 - 1; + Padding at 63 range 0 .. 7; end record; - for Trace_Entry_Header'Size use 48 * 8; + for Trace_Entry_Header'Size use 64 * 8; end Traces_Source; From 42a4553866e9a5da14783a2feb7a9e5a1812e5a1 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 5 Dec 2022 11:42:48 +0100 Subject: [PATCH 0092/1483] Instrument.C: avoid code duplication TN: VB28-007 --- tools/gnatcov/instrument-c.adb | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 65011aba2..6c844b246 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -774,7 +774,7 @@ package body Instrument.C is Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name) is - Loc : Source_Location_T := Get_Range_Start (Get_Cursor_Extent (N)); + Loc : Source_Location_T := Start_Sloc (N); Info : PP_Info; begin Append_SCO @@ -997,12 +997,8 @@ package body Instrument.C is if UIC.LL_PP_Info_Map.Contains (SCOs.SCO_Table.Last) then declare - Cursor_Source_Range_C : constant Source_Range_T := - Get_Cursor_Extent (N); - Start_Loc : constant Source_Location_T := - Get_Range_Start (Cursor_Source_Range_C); - End_Loc : constant Source_Location_T := - Get_Range_End (Cursor_Source_Range_C); + Start_Loc : constant Source_Location_T := Start_Sloc (N); + End_Loc : constant Source_Location_T := End_Sloc (N); Cursor_Source_Range : Slocs.Local_Source_Location_Range; @@ -3066,9 +3062,7 @@ package body Instrument.C is UIC.TU := Rewriter.TU; UIC.Rewriter := Rewriter.Rewriter; Insert_Extern_Location := - Get_Range_Start - (Get_Cursor_Extent - (Get_Translation_Unit_Cursor (UIC.TU))); + Start_Sloc (Get_Translation_Unit_Cursor (UIC.TU)); Traverse_Declarations (IC => IC, @@ -3767,9 +3761,7 @@ package body Instrument.C is -- Name of file to contain helpers implementing the buffers dump Insert_Extern_Location : constant Source_Location_T := - Get_Range_Start - (Get_Cursor_Extent - (Get_Translation_Unit_Cursor (Rew.TU))); + Start_Sloc (Get_Translation_Unit_Cursor (Rew.TU)); -- Where to insert extern declarations Main_Cursor : constant Cursor_T := Get_Main (Rew.TU); @@ -3889,15 +3881,13 @@ package body Instrument.C is -- function. if Length (Main_Stmts) = 0 then - Insert_Sloc := - Get_Range_Start (Get_Cursor_Extent (Main_Body)); + Insert_Sloc := Start_Sloc (Main_Body); Insert := True; -- Otherwise, insert after the last statement elsif Kind (Element (Last_Stmt)) /= Cursor_Return_Stmt then - Insert_Sloc := - Get_Range_End (Get_Cursor_Extent (Element (Last_Stmt))); + Insert_Sloc := End_Sloc (Element (Last_Stmt)); Insert := True; end if; From 64ae0d45de1c4513af48bb52af1a200d5c863d94 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 5 Dec 2022 13:01:44 +0100 Subject: [PATCH 0093/1483] Instrument.C: fix text insertion at the end of a function gnatcov may need to insert text right before the end of the function. The implementation was not robust enough as shown by a recent regression. Add a new API CX_Rewriter_Insert_Text_Before_Token to be able to insert text right before the function closing brace, and use it instead of trying to insert after the last statement, or after the function closing brace (when adding new closing braces). TN: VB28-007 --- tools/gnatcov/clang-extensions.adb | 20 +++++++++ tools/gnatcov/clang-extensions.ads | 12 +++++- tools/gnatcov/clang-wrapper.cc | 15 +++++++ tools/gnatcov/instrument-c.adb | 67 +++++++++++++++--------------- tools/gnatcov/instrument-c.ads | 6 +++ 5 files changed, 84 insertions(+), 36 deletions(-) diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index fadececfd..c3b4aa01e 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -115,6 +115,26 @@ package body Clang.Extensions is CX_Rewriter_Insert_Text_After_Token_C (Rew, Loc, Insert & ASCII.NUL); end CX_Rewriter_Insert_Text_After_Token; + ------------------------------------------ + -- CX_Rewriter_Insert_Text_Before_Token -- + ------------------------------------------ + + procedure CX_Rewriter_Insert_Text_Before_Token + (Rew : Rewriter_T; + Loc : Source_Location_T; + Insert : String) + is + procedure CX_Rewriter_Insert_Text_Before_Token_C + (Rew : Rewriter_T; + Loc : Source_Location_T; + Insert : String) + with + Import, Convention => C, + External_Name => "clang_CXRewriter_insertTextBeforeToken"; + begin + CX_Rewriter_Insert_Text_Before_Token_C (Rew, Loc, Insert & ASCII.NUL); + end CX_Rewriter_Insert_Text_Before_Token; + ----------------------- -- Spelling_Location -- ----------------------- diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index c56cfd42d..6362c1c77 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -108,13 +108,21 @@ package Clang.Extensions is -- previously inserted string (at the same location). procedure CX_Rewriter_Insert_Text_After_Token - (Rew : Rewriter_T; - Loc : Source_Location_T; + (Rew : Rewriter_T; + Loc : Source_Location_T; Insert : String) with Inline; -- Insert the text Insert after the token at the given location, and after -- any previously inserted string (at the same location). + procedure CX_Rewriter_Insert_Text_Before_Token + (Rew : Rewriter_T; + Loc : Source_Location_T; + Insert : String) + with Inline; + -- Insert the text Insert before the token at the given location, and after + -- any previously inserted string (at the same location). + function Get_Cursor_TU (C : Cursor_T) return Translation_Unit_T with Import, Convention => C, diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index cb82c22dd..f969308c1 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -595,6 +595,21 @@ clang_CXRewriter_insertTextAfterToken (CXRewriter Rew, CXSourceLocation Loc, R.InsertTextAfterToken (translateSourceLocation (Loc), Insert); } +extern "C" void +clang_CXRewriter_insertTextBeforeToken (CXRewriter Rew, CXSourceLocation Loc, + const char *Insert) +{ + assert (Rew); + Rewriter &R = *reinterpret_cast (Rew); + const SourceManager &SM = R.getSourceMgr (); + + // Get the previous location, and insert after it + + SourceLocation SLoc = translateSourceLocation (Loc); + SourceLocation Prv = SLoc.getLocWithOffset (-1); + R.InsertTextAfter (Prv, Insert); +} + /* Wrappers around source location analysis functions. */ extern "C" unsigned diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 6c844b246..52fc70419 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -245,6 +245,12 @@ package body Instrument.C is MCDC_State : out US.Unbounded_String); -- Wrapper around Insert_MCDC_State overload + overriding procedure Insert_Text_Before_Token + (Pass : Instrument_Pass_Kind; + Rew : Rewriter_T; + Loc : Source_Location_T; + Text : String); + overriding procedure Insert_Text_Before (Pass : Instrument_Pass_Kind; Rew : Rewriter_T; @@ -1062,11 +1068,24 @@ package body Instrument.C is MCDC_State := +Insert_MCDC_State (UIC, Name); end Insert_MCDC_State; + ------------------------------ + -- Insert_Text_Before_Token -- + ------------------------------ + + overriding procedure Insert_Text_Before_Token + (Pass : Instrument_Pass_Kind; + Rew : Rewriter_T; + Loc : Source_Location_T; + Text : String) is + begin + CX_Rewriter_Insert_Text_Before_Token (Rew, Loc, Text); + end Insert_Text_Before_Token; + ------------------------ -- Insert_Text_Before -- ------------------------ - procedure Insert_Text_Before + overriding procedure Insert_Text_Before (Pass : Instrument_Pass_Kind; Rew : Rewriter_T; Loc : Source_Location_T; @@ -1079,7 +1098,7 @@ package body Instrument.C is -- Insert_Text_After -- ----------------------- - procedure Insert_Text_After + overriding procedure Insert_Text_After (Pass : Instrument_Pass_Kind; Rew : Rewriter_T; Loc : Source_Location_T; @@ -2459,7 +2478,7 @@ package body Instrument.C is UIC.MCDC_State_Declaration_Node := Stmts.First_Element; Traverse_Statements (IC, UIC, Stmts, TB); - UIC.Pass.Insert_Text_Before + UIC.Pass.Insert_Text_Before_Token (UIC.Rewriter, End_Sloc (Fun_Body), +TB); end if; end; @@ -3849,11 +3868,8 @@ package body Instrument.C is begin declare - Main_Body : constant Cursor_T := Get_Body (Main_Cursor); - Main_Stmts : constant Vector := Get_Children (Main_Body); - Last_Stmt : constant Cursor := Main_Stmts.Last; - Insert_Sloc : Source_Location_T; - Insert : Boolean := False; + Main_Body : constant Cursor_T := Get_Body (Main_Cursor); + Main_Stmts : constant Vector := Get_Children (Main_Body); begin -- Introduce a variable to hold the return value. Declare -- it at the start of the main to avoid complications with @@ -3873,34 +3889,17 @@ package body Instrument.C is Visit (Main_Body, Process'Access); - -- If the last statement of the function is not a return - -- statement add a call to dump_buffers at the end of the - -- main function. - -- - -- If the main is empty, insert right at the start of the - -- function. - - if Length (Main_Stmts) = 0 then - Insert_Sloc := Start_Sloc (Main_Body); - Insert := True; + -- If the main function does not end with a return, add + -- a call to dump_buffers at the end of the function. - -- Otherwise, insert after the last statement - - elsif Kind (Element (Last_Stmt)) /= Cursor_Return_Stmt then - Insert_Sloc := End_Sloc (Element (Last_Stmt)); - Insert := True; - end if; - - if Insert then - - -- Insert a terminating semicolon in case we end up - -- inserting between the last statement expression and - -- its terminating semicolon. - - CX_Rewriter_Insert_Text_After_Token + if Length (Main_Stmts) = 0 + or else + Kind (Main_Stmts.Last_Element) /= Cursor_Return_Stmt + then + CX_Rewriter_Insert_Text_Before_Token (Rew.Rewriter, - Insert_Sloc, - ";" & Dump_Procedure_Symbol (Main) & "();"); + End_Sloc (Main_Body), + Dump_Procedure_Symbol (Main) & "();"); end if; end; end; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 746c0b621..512992047 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -443,6 +443,12 @@ private Name : String; MCDC_State : out US.Unbounded_String) is null; + procedure Insert_Text_Before_Token + (Pass : Pass_Kind; + Rew : Rewriter_T; + Loc : Source_Location_T; + Text : String) is null; + procedure Insert_Text_Before (Pass : Pass_Kind; Rew : Rewriter_T; From 5fbd3bc53095605150ef64ad63be18a510b37077 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 7 Dec 2022 10:32:36 +0000 Subject: [PATCH 0094/1483] sc_obligations.ads: minor reformatting --- tools/gnatcov/sc_obligations.ads | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 9bd3ccd80..be3a8f541 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -646,7 +646,7 @@ package SC_Obligations is -- Refers to the source location of a SCO in the unpreprocessed view -- of the source file. - PP_Source_Range : Slocs.Local_Source_Location_Range; + PP_Source_Range : Slocs.Local_Source_Location_Range; -- Refer to a source location from the preprocessed version of the -- source file, without accounting for preprocessor-inserted line -- directives. @@ -659,10 +659,9 @@ package SC_Obligations is Definition_Loc : Expansion_Info; -- Location in the definition of the ultimate macro expansion - when others => + when others => null; end case; - end record; -- Preprocessing information for SCOs. Hold basic information to enhance -- the report output with more precise messages. From c253638575137a4f602bd3db86c2affdc8d8f47d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 8 Nov 2022 10:04:26 +0100 Subject: [PATCH 0095/1483] Instrument.C: pass the language to the preprocessing / parsing cmd The body suffix extension can be redefined through gpr Naming's package, which means that a C / C++ source file can have an arbitrary extension. Pass explicitly the language to let the compiler know the language for the source file. TN: VB03-009 --- tools/gnatcov/instrument-c.adb | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 52fc70419..c030e4dcf 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -151,7 +151,8 @@ package body Instrument.C is -- preprocess the file, assuming that it accepts the -E flag, to preprocess -- a file. - function Common_Parse_TU_Args return String_Vectors.Vector; + function Common_Parse_TU_Args + (Lang : Some_Language) return String_Vectors.Vector; -- Return the list of arguments that should always be passed to -- Parse_Translation_Unit. @@ -2742,8 +2743,11 @@ package body Instrument.C is -- Common_Parse_TU_Args -- -------------------------- - function Common_Parse_TU_Args return String_Vectors.Vector is + function Common_Parse_TU_Args + (Lang : Some_Language) return String_Vectors.Vector + is Command_Line_Args : String_Vectors.Vector; + use Ada.Characters.Handling; use String_Vectors; begin -- We will get errors when parsing a gcc-preprocessed file with clang: @@ -2753,6 +2757,13 @@ package body Instrument.C is Append (Command_Line_Args, +"-ferror-limit=0"); + -- Pass explicitly the language through the command-line, as we can + -- redefine file suffixes with gprbuild, and .c can be a C++ + -- file. + + Append (Command_Line_Args, +"-x"); + Append (Command_Line_Args, +To_Lower (Image (Lang))); + return Command_Line_Args; end Common_Parse_TU_Args; @@ -2783,7 +2794,8 @@ package body Instrument.C is (Exclude_Declarations_From_PCH => 0, Display_Diagnostics => 0); Add_Options (Args, Options); - String_Vectors.Append (Args, Common_Parse_TU_Args); + String_Vectors.Append + (Args, Common_Parse_TU_Args (Instrumenter.Language)); declare C_Args : chars_ptr_array := To_Chars_Ptr_Array (Args); begin @@ -2877,7 +2889,7 @@ package body Instrument.C is -- the user's preprocessor. Add_Options (Args, UIC.Options); - String_Vectors.Append (Args, Common_Parse_TU_Args); + String_Vectors.Append (Args, Common_Parse_TU_Args (Unit_Info.Language)); -- TODO??? We should also inhibit the use of clang predefined macros, -- with the -undef option, but doing this yields parsing errors, and a From fd5ce3c7c1846777beed0c632d892d238ab4d7c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 16 Dec 2022 10:58:57 +0100 Subject: [PATCH 0096/1483] Rename C qualification test to shorten test names The mains in the test Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile had relatively long names, which were duplicated when testing, as each test takes place in a subdirectory named after the main, resulting in paths over 260 characters in length and thus being unusable on Windows. This change shortens the names of the test mains by using initials for each of the words that constituted the filename. Fixes eng/cov/gnatcoverage#8 --- .../02_DoWhile/src/{test_dowhile_false.c => test_dw_f.c} | 0 .../src/{test_dowhile_false_gotoin.c => test_dw_f_gi.c} | 0 .../src/{test_dowhile_false_gotoinout.c => test_dw_f_gio.c} | 0 .../src/{test_dowhile_false_gotoout.c => test_dw_f_go.c} | 0 .../02_DoWhile/src/{test_dowhile_no.c => test_dw_no.c} | 0 .../02_DoWhile/src/{test_dowhile_true.c => test_dw_t.c} | 0 .../02_DoWhile/src/{test_dowhile_true_gotoin.c => test_dw_t_gi.c} | 0 .../src/{test_dowhile_true_gotoinout.c => test_dw_t_gio.c} | 0 .../src/{test_dowhile_true_gotoout.c => test_dw_t_go.c} | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/{test_dowhile_false.c => test_dw_f.c} (100%) rename testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/{test_dowhile_false_gotoin.c => test_dw_f_gi.c} (100%) rename testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/{test_dowhile_false_gotoinout.c => test_dw_f_gio.c} (100%) rename testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/{test_dowhile_false_gotoout.c => test_dw_f_go.c} (100%) rename testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/{test_dowhile_no.c => test_dw_no.c} (100%) rename testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/{test_dowhile_true.c => test_dw_t.c} (100%) rename testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/{test_dowhile_true_gotoin.c => test_dw_t_gi.c} (100%) rename testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/{test_dowhile_true_gotoinout.c => test_dw_t_gio.c} (100%) rename testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/{test_dowhile_true_gotoout.c => test_dw_t_go.c} (100%) diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false_gotoin.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f_gi.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false_gotoin.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f_gi.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false_gotoinout.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f_gio.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false_gotoinout.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f_gio.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false_gotoout.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f_go.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_false_gotoout.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_f_go.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_no.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_no.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_no.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_no.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true_gotoin.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t_gi.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true_gotoin.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t_gi.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true_gotoinout.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t_gio.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true_gotoinout.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t_gio.c diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true_gotoout.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t_go.c similarity index 100% rename from testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dowhile_true_gotoout.c rename to testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/test_dw_t_go.c From bad9c5c6fa07db8b6f0f2ff692310cb362a570e2 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Tue, 6 Dec 2022 02:52:52 -0800 Subject: [PATCH 0097/1483] Fix incorrect uses of :option: in cov_source.rst For our purposes, mere typesetting control at this stage, :cmd-option: should be used instead of :option:. Part of V805-004 --- doc/gnatcov/cov_source.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index 225120974..87914867e 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -1541,14 +1541,14 @@ options to help in those situations: If the location of a source file, when built on a first machine, was ``/work/build_1234/src/main.adb`` but its location on the machine where the report is generated is ``/some/path/project/src/main.adb`` then passing - :option:`--source-search=/some/path/project/src` will enable |gcv| to find - the missing source file. This option also accepts response files. + :cmd-option:`--source-search=/some/path/project/src` will enable |gcv| to + find the missing source file. This option also accepts response files. This option can appear multiple times on the command line. Note that |gcv| - will first try the :option:`--source-rebase` prefix pairs, if any, and if - the source file was not found, it will then look for the file in all the - directories passed with :option:`--source-search` in the order in which they - appear on the command line. + will first try the :cmd-option:`--source-rebase` prefix pairs, if any, and + if the source file was not found, it will then look for the file in all + the directories passed with :cmd-option:`--source-search` in the order in + which they appear on the command line. These two options perform very similar functions and can sometimes be used interchangeably, however the second option is less selective and can lead to From 18b2c313abd54c0bae427a89389ab82305043784 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 23 Nov 2022 04:56:53 -0800 Subject: [PATCH 0098/1483] Split bin trace support out of the main gnatcov user manual Setup a new "part" (gnatcov_bin_part.rst) to hold a gnatcov doc appendix dedicated to bin traces. Add a bin_intro.rst file to hold the corresponding introduction chapter. Add the new part to the top level index/toc (index.rst). Rework the original getting_started chapter to focus on source traces. The rewritten getting_started uses a fig_flow_srctraces dot to illustrate. The former fig_flow0 figure comparing the flows is renamed as fig_flow_compare, adjusted and now used in the intro section of the bintrace appendix. Simplify text in the "integration" to get rid of references to intro sections which are now incorrect. Part of V805-004 --- doc/Makefile | 2 +- ...bin_traces_convert.rst => bin_convert.rst} | 2 + doc/gnatcov/bin_intro.rst | 154 +++++++ doc/gnatcov/fig_flow0.pdf | Bin 14262 -> 0 bytes doc/gnatcov/fig_flow0.png | Bin 72417 -> 0 bytes .../{fig_flow0.dot => fig_flow_compare.dot} | 18 +- doc/gnatcov/fig_flow_compare.pdf | Bin 0 -> 14375 bytes doc/gnatcov/fig_flow_compare.png | Bin 0 -> 71500 bytes doc/gnatcov/fig_flow_srctraces.dot | 61 +++ doc/gnatcov/fig_flow_srctraces.pdf | Bin 0 -> 12407 bytes doc/gnatcov/fig_flow_srctraces.png | Bin 0 -> 43383 bytes doc/gnatcov/getting_started.rst | 392 +++++++----------- doc/gnatcov/gnatcov_bin_part.rst | 12 + doc/gnatcov/gnatcov_part.rst | 5 - doc/index.rst | 1 + doc/integration/integration_part.rst | 9 +- 16 files changed, 398 insertions(+), 258 deletions(-) rename doc/gnatcov/{bin_traces_convert.rst => bin_convert.rst} (95%) create mode 100644 doc/gnatcov/bin_intro.rst delete mode 100644 doc/gnatcov/fig_flow0.pdf delete mode 100644 doc/gnatcov/fig_flow0.png rename doc/gnatcov/{fig_flow0.dot => fig_flow_compare.dot} (81%) create mode 100644 doc/gnatcov/fig_flow_compare.pdf create mode 100644 doc/gnatcov/fig_flow_compare.png create mode 100644 doc/gnatcov/fig_flow_srctraces.dot create mode 100644 doc/gnatcov/fig_flow_srctraces.pdf create mode 100644 doc/gnatcov/fig_flow_srctraces.png create mode 100644 doc/gnatcov/gnatcov_bin_part.rst diff --git a/doc/Makefile b/doc/Makefile index 8cf357103..12fac6bd9 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -74,7 +74,7 @@ install.html: prepare-installdir.html gnatcov/fig_%.png: gnatcov/fig_%.dot gnatcov/fig_%.pdf: gnatcov/fig_%.dot -FIGURES=fig_consolidation fig_multipath-bdd fig_flow0 +FIGURES=fig_consolidation fig_multipath-bdd fig_flow_compare fig_flow_srctraces prepare-images:: $(foreach fig, $(FIGURES), gnatcov/$(fig).pdf) prepare-images:: $(foreach fig, $(FIGURES), gnatcov/$(fig).png) diff --git a/doc/gnatcov/bin_traces_convert.rst b/doc/gnatcov/bin_convert.rst similarity index 95% rename from doc/gnatcov/bin_traces_convert.rst rename to doc/gnatcov/bin_convert.rst index c63a56f1a..6817a6367 100644 --- a/doc/gnatcov/bin_traces_convert.rst +++ b/doc/gnatcov/bin_convert.rst @@ -1,3 +1,5 @@ +.. _bin_convert: + ##################################### Importing binary traces with |gcvcnv| ##################################### diff --git a/doc/gnatcov/bin_intro.rst b/doc/gnatcov/bin_intro.rst new file mode 100644 index 000000000..1bc0dd6cd --- /dev/null +++ b/doc/gnatcov/bin_intro.rst @@ -0,0 +1,154 @@ +************ +Introduction +************ + +Definition and main characteristics +----------------------------------- + +Unlike *source traces* produced by the execution of instrumented +programs in their regular environment, :dfn:`binary traces` are +coverage trace files produced by the execution of uninstrumented +programs under the control of an instrumented execution environment. +*"Binary"* in this designation refers to the nature of the collected +data, which consists in low level information about executed blocks of +machine instructions. + +From binary traces, |gcp| is able to compute both *source coverage* +metrics as with source traces, and :dfn:`object coverage` metrics +assessing the coverage of machine level instructions. |gcp| supports +two criteria of the latter kind: + +- :dfn:`Instruction Coverage`, where we evaluate for each machine instruction + whether it has been executed at least once or not; and + +- :dfn:`Branch Coverage`, where we also evaluate for each conditional + branch instruction whether it was only taken, or went fallthrough or both. + +Source coverage metrics are only available for a subset of the target +configurations supported with source traces, though, and new tool +functionalities are most often implemented for source traces only. + +The matrix below summarizes the main characteristics of the two +trace production modes: + + +.. list-table:: + :widths: 20 20 20 + :header-rows: 1 + :stub-columns: 1 + + * - + - **With Source Traces** + - **With Binary Traces** + * - *Tracing mechanism* + - Program instrumentation + - Execution environment + * - ~ + - ~ + - ~ + * - *Native applications* + - Yes (including shared-libraries) + - No + * - *Cross configurations with RTOS* + - Yes + - No + * - *Bareboard configurations* + - Yes + - Specific CPUs only, through GNATemulator or + hardware probes + * - ~ + - ~ + - ~ + * - *Object coverage analysis* + - No + - Yes + * - *New features* + - Often not + - Yes (source level metrics for C++, scoped metrics in dhtml) + + +Workflow overview +----------------- + +A high level view comparing the processes involved in the use of +binary or source traces is provided on :numref:`fig-flow_compare`. The +use of coverage *traces* in both modes allows lots of similarities +between workflows, in particular in the steps processing traces after +they have been produced. + +We don't support mixing the two kinds of traces together, though, and have +depicted a separate analysis/consolidation step to emphasize this: + +.. _fig-flow_compare: +.. figure:: fig_flow_compare.* + :align: center + + Workflows using source or binary coverage traces + +For binary traces, |gcv| relies on an instrumented execution +environment to produce the traces instead of having to instrument the +program itself with extra code and data structures. |gem| provides +such an environment for bareboard configurations, as well as hardware +probes assisted with means to convert their output to the format |gcv| +expects. + +Programs are built from their original sources, only requiring the use of +:cmd-option:`-g -fpreserve-control-flow -fdump-scos` compilation options to +generate coverage obligation lists and let us associate execution traces to +these obligations afterwards. + + + +A simple example +---------------- + +For the original "Getting Started" use case, we first use the GNAT Pro +toolset for ``powerpc-elf`` to build, using :command:`gprbuild` as +follows:: + + gprbuild --target=powerpc-elf --RTS=light-mpc8641 -Ptests.gpr \ + -cargs -g -fpreserve-control-flow -fdump-scos + +We pass the project file with ``-P``, the required compilation flags +with ``-cargs`` and request the use of a ``light`` runtime library tailored +for the ``mpc8641`` board. + +The build command produces a ``test_inc`` executable in the object +subdirectory. To automate the execution of this program within |gem| +to produce a trace, we provide the |gcvrun| command. For the use case +at hand, we would simply do:: + + gnatcov run --target=powerpc-elf obj-tests/test_inc + + +This produces a ``test_inc.trace`` binary trace file in the current +directory. By default, such a trace is amenable to statement and decision +coverage at most. If MCDC analysis is needed, ``--level=stmt+mcdc`` must be +passed to |gcvrun| as well and we recommend also providing source coverage +obligations in this case. + +Going Further +============= + +As the source and binary trace based workflows share commonalities, +a lot of information from the main documentation also applies to the +use binary traces, such as + +- The use of project files, to specify command switches or designate + units of interest, + +- Using coverage checkpoints or traces for consolidation, + +- Defining exemptions regions with pragmas for Ada. The support + for other languages is not available for binary traces. + +Then this appendix holds separate chapters dedicated to binary trace +specific considerations: + +- :ref:`bin_traces` + +- :ref:`ocov` + +- :ref:`osmetrics` + +- :ref:`bin_convert` diff --git a/doc/gnatcov/fig_flow0.pdf b/doc/gnatcov/fig_flow0.pdf deleted file mode 100644 index 0f5fc3f356c9dc72659ff9e344affd6446561efa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 14262 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 diff --git a/doc/gnatcov/fig_flow0.png b/doc/gnatcov/fig_flow0.png deleted file mode 100644 index d560ed3b7a4f1b1bc9f8d3ae77b928078629390b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72417 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⁣Ub+A2^ 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 E4>xy+?EnA( diff --git a/doc/gnatcov/fig_flow0.dot b/doc/gnatcov/fig_flow_compare.dot similarity index 81% rename from doc/gnatcov/fig_flow0.dot rename to doc/gnatcov/fig_flow_compare.dot index fdc744c37..698438dda 100644 --- a/doc/gnatcov/fig_flow0.dot +++ b/doc/gnatcov/fig_flow_compare.dot @@ -15,12 +15,12 @@ digraph { node [shape = box]; node [color = green]; - instrument [label = "Instrument\nOriginal Sources"]; - build_instr [label = "Build from\nInstrumented Sources"]; - regular_execution [label = "Regular Execution\n(Instrumented Executable)"]; + instrument [label = "Instrument Original Sources\n(gnatcov instrument)"]; + build_instr [label = "Build from Instrumented Sources\n(gprbuild --src-subdirs ...)"]; + regular_execution [label = "Regular Execution\n(instrumented executable)"]; node [color = blue]; - srct_coverage [label = "Analyze/Consolidate"]; + srct_coverage [label = "Analyze/Consolidate\n(gnatcov coverage)"]; /* products or inputs */ node [shape = ellipse, color = green]; @@ -40,11 +40,11 @@ digraph { /* processes */ node [shape = box]; node [color = red]; - build_orig [label = "Build from\nOriginal Sources"]; - instr_execution [label = "Instrumented Execution\n(Regular Executable)"]; + build_orig [label = "Build from Original Sources\n(gprbuild -cargs ...)"]; + instr_execution [label = "Instrumented Execution\n(gnatcov run)"]; node [color = blue]; - bint_coverage [label = "Analyze/Consolidate"]; + bint_coverage [label = "Analyze/Consolidate\n(gnatcov coverage)"]; /* products or inputs */ node [shape = ellipse, color = red]; @@ -101,6 +101,10 @@ digraph { build_orig [rank=2]; build_orig -> instr_execution; + pad1 [style=invis]; + build_orig:e -> pad1 [style=invis]; + pad1 -> instr_execution:e [style=invis]; + {rank = same; bt1; btdots; bt2; } diff --git a/doc/gnatcov/fig_flow_compare.pdf b/doc/gnatcov/fig_flow_compare.pdf new file mode 100644 index 0000000000000000000000000000000000000000..2e188dfb719c786dd63cbc35f62ec20b37901dde GIT binary patch literal 14375 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

%! zI5>DO?&)c7e|4=pmrcq84Ke!b_Ag)F6lajA{gSjfeE4N=v7_f7SI-4QVoxU^e|uBs zW_8*0Iq+S`4=B)0A3jKWEu_W7>;Wu4NEQ-popST0hL_iBZTOyp3^y|}EH7QUWMabB zBj3aqIh%Cr=FRNvY|iF8ag#&0Ut0ZOdmITGh_nkhG_!-%fxx3{ zYim3Au&*aYHVjqpgo~S*xa)zT2-sKy5^V$FgSDxfw*XB2r}Lmg=V4%E6n^6d87Zku z;O4q(0V`(|2qgvAlZ?85>BA9?Ia{7#>PmCDbn6_?Ce^PbsDKDVl7eTK~VG-Sf4g9xSx}A zWUwc??D61oZu-(5x#=bO!~vs7EjhWMj0_&<-ejEWulkJa0zujTOj#k~b5fOe_hiV?$_sSK2qNT6|Bc_>b+u1U zC*lYe7-WC@_6?N^SV&bxWm%Vnz(Ko&2akB#_L0Nvhf85OPC+V$v;5A9_UseDc@$vBj94p9=bhNY` zg+DX1vQXK;I|`mSQCLtQEGoJT-u2VpGp|cprV2fyOy@tD z)Q;IXi>C%Dv)H~@MUZ|))WY&XkmpWon^u3EH#oyLE@c<~}C62HUop2)P|WQF06UxR2~ zEL5dZDYl|OxY8UH=_o4}AGlfpyAwelOxCS{=?O&u;@1}RYQ&CJX!ezogaS67$T z3e|zjNvZz@wldl*Ul`K&bJey{qv0Agy)a-&wKY9rSv- zS>lF*_X-Oa%>p+*fBot;*Czp5&qAf=%^OivLNl{LP|kgQ#sJQ((q;V)q=Vl|ZGMc& zR#=?8?#u7@h-Y|fESnpOJSPEJm0ooEFNEvc;B=r8vKn5|i9lS!^z zxbj2d+TFW%B_$A0&4(VG*m*YJKac*^9#f`85dps48m@rEp-bt6&0)a ztLETOU&}pSnCRpwWN$4DDQ5kiAFS@~>>QCEH5C;S`u@>sz&cdH=XCz?P_FXL0pi;D zK05mQeYr}W$5f>-v*CpcD3_Jn=mX(>A7RZ-)48o%5;iE_I zfj8Z}#Xu3ZXl>)|T^d_fm;A=`Zm^%Ci-!lhte+Q($Jw)8V7Qd?B4Y2|dxKh#p&CP% zcpzeZ@5bVbv80!Hu℘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ⅆL%9^y)}C7m^_qtAwZA?>ryW-S&NOV^&+nJ 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 literal 0 HcmV?d00001 diff --git a/doc/gnatcov/fig_flow_srctraces.dot b/doc/gnatcov/fig_flow_srctraces.dot new file mode 100644 index 000000000..d4c9e9b8e --- /dev/null +++ b/doc/gnatcov/fig_flow_srctraces.dot @@ -0,0 +1,61 @@ +digraph { + node [fontsize = 9] + + edge [fontsize = 9, arrowsize=0.7] + + setup [shape=box, label="gnatcov setup"] + + /*------------------- + Using Source traces + -------------------*/ + subgraph "cluster_src_traces" { + label = "Instrument / Build / Execute / Analyze"; + fontsize = 10; + labeljust = l; + + /* processes */ + node [shape = box]; + + node [color = green]; + instrument [label = "Instrument Original Sources\n(gnatcov instrument -P)"]; + build_instr [label = "Build from Instrumented Sources\n(gprbuild -P... --src-subdirs ...)"]; + regular_execution [label = "Regular Execution\n(instrumented executable)"]; + + node [color = blue]; + srct_coverage [label = "Analyze/Consolidate\n(gnatcov coverage -P...)"]; + + /* products or inputs */ + node [shape = ellipse, color = green]; + st1 [label = "strace1"]; + stdots [label = "..."]; + st2 [label = "strace2"]; + + node [shape = ellipse, color = blue]; + srct_report [label = "Report"]; + srct_checkpoint [label = "Checkpoint"]; + + src [shape = ellipse, label = "Original Sources"]; + + /* Links */ + src -> instrument; + instrument -> build_instr; + build_instr -> regular_execution; + + {rank = same; + st1; stdots; st2; + } + + regular_execution -> st1 [style = dotted]; + regular_execution -> stdots [style = dotted]; + regular_execution -> st2 [style = dotted]; + + st1 -> srct_coverage; + stdots -> srct_coverage; + st2 -> srct_coverage; + + srct_coverage -> srct_report [style = dotted]; + srct_coverage -> srct_checkpoint [style = dotted]; + srct_checkpoint -> srct_coverage; + + } +} diff --git a/doc/gnatcov/fig_flow_srctraces.pdf b/doc/gnatcov/fig_flow_srctraces.pdf new file mode 100644 index 0000000000000000000000000000000000000000..0d6a5b808d8a075671b4cc17fdc7e6737ab3635b GIT binary patch literal 12407 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 below, in ``test_inc.adb``, which exercises the ``Increment`` operation only: @@ -184,13 +144,9 @@ driver ` below, in ``test_inc.adb``, which exercises the end; -We will illustrate two basic use cases, one using binary traces produced by -GNATemulator for a cross target, and one using source traces for a native -environment. -Assuming we start from a temporary working directory, with the *ops* sources -in an ``opslib`` subdirectory and the *test* sources in a ``tests`` -subdirectory, we will rely for both cases on a couple of project files in the -common working directory: +Assuming a working directory, with the *ops* sources in an ``opslib`` +subdirectory and the *test* sources in a ``tests`` subdirectory, we +will use a couple of project files in the common working directory: .. code-block:: ada @@ -213,122 +169,72 @@ common working directory: end Tests; -If you wish to experiment with both trace modes, you should start from -separate working directories (one for each mode) to prevent possible -intereferences of artifacts from one mode on the other. - +Setup, Instrument, Build, Execute, Analyze +------------------------------------------ -Example production of a binary trace for a bareboard environment ----------------------------------------------------------------- +We first set up the instrumentation context, providing a local +*prefix* location where the runtime and default parameters for future +commands are going to be installed:: -For binary traces, |gcv| relies on an instrumented execution environment to -produce the traces instead of having to instrument the program itself with -extra code and data structures. For cross configurations, |gem| provides such -an environment. Hardware probes may also be used, provided trace data is -converted to the format |gcv| expects. + gnatcov setup --prefix=/path/to/gnatcov-rts -Programs are built from their original sources, only requiring the use of -:cmd-option:`-g -fpreserve-control-flow -fdump-scos` compilation options to -generate coverage obligation lists and let us associate execution traces to -these obligations afterwards. +The simplest means to let further commands know about the *prefix* +location consists in adding ``/share/gpr`` to the +``GPR_PROJECT_PATH`` variable. In a Unix like environment, this would +be achieved with:: -For our example use case here, we first use the GNAT Pro toolset for -``powerpc-elf`` to build, using :command:`gprbuild` as follows:: + export GPR_PROJECT_PATH=$GPR_PROJECT_PATH:/path/to/gnatcov-rts/share/gpr - gprbuild --target=powerpc-elf --RTS=light-mpc8641 -Ptests.gpr \ - -cargs -g -fpreserve-control-flow -fdump-scos - -We pass the project file with ``-P``, the required compilation flags -with ``-cargs`` and request the use of a ``light`` runtime library tailored -for the ``mpc8641`` board. - -The build command produces a ``test_inc`` executable in the object -subdirectory. To automate the execution of this program within |gem| -to produce a trace, we provide the |gcvrun| command. For the use case -at hand, we would simply do:: - - gnatcov run --target=powerpc-elf obj-tests/test_inc - - -... which would produce a ``test_inc.trace`` binary trace file in the current -directory. By default, such a trace is amenable to statement and decision -coverage at most. If MCDC analysis is needed, ``--level=stmt+mcdc`` must be -passed to |gcvrun| as well and we recommand also providing source coverage -obligations in this case. - -Example production of a source trace for a native environment -------------------------------------------------------------- - -The production of source traces is performed by an instrumented version of the -program running in its regular execution environment. The coverage data is -collected and output by the program itself. The output step is performed by a -specific instrumentation of the program main unit, according to a user -selectable policy. - -The whole scheme requires the use of GPR project files. The code inserted by -the instrumentation process relies on common types and subprograms provided by -a :dfn:`coverage runtime` library, distributed in source form with |gcp|. The -first thing to do for a given project is then to setup this coverage runtime -so it becomes available to the instrumented sources afterwards. This step is -documented in the :ref:`instr-rts` section of this manual. +The instrumentation step that follows assumes that the original program +is well formed. A simple way to verify this is to build the non instrumented +version first. For our example, this would be:: + gprbuild -f -p -Ptests.gpr + Instrumenting a test main program together with its "code" dependency is then -achieved by a |gcvins| command. For our example use case, this would be:: +achieved by a |gcvins| command:: - gnatcov instrument -Ptests.gpr --level=stmt \ - --dump-trigger=atexit --dump-channel=bin-file + gnatcov instrument -Ptests.gpr --level=stmt -The ``--dump-channel=bin-file`` switch requests outputing coverage data -directly to a trace file and ``--dump-trigger=atexit`` instructs to perform -this operation as part of an execution termination handler, the simplest -option in native environments. ``--level=stmt`` states that we will want to -perform statement coverage analysis afterwards and ``-Ptests.gpr`` specifies -the root project for coverage obligations and the main unit(s) to instrument. +And building the instrumented program goes like:: -After setting ``GPR_PROJECT_PATH`` to designate the directory where the -coverage runtime has been installed, building the instrumented program then -goes like:: - - gprbuild -f -p -Ptests.gpr \ + gprbuild -f -p -Ptests.gpr \ --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts +This is the same command as for the regular build, with a couple +of additional switches to: + + * Instruct the builder to search for the instrumented versions of the + sources (``--src-subdirs``), -The ``--src-subdirs`` and ``--implicit-with`` options respectively instruct -the builder to use the alternative sources produced by the instrumenter and to -automatically provide visiblity over the coverage runtime. This allows -building the instrumented version of the program without requiring any change -to the GPR project files. + * Provide visibility to the builder over the coverage runtime + referenced by the instrumented sources (``--implicit-with``). -Then simply executing the test program in its native environment, as in:: +Executing the test program in its native environment, as in:: obj-tests/test_inc -produces a ``test_inc-.srctrace`` source trace file in the +then produces a ``test_inc-.srctrace`` source trace file in the current directory. The ``-`` suffix is intended to prevent clashes in case of concurrent executions of the program in the same directory. It can be controlled in a variety of ways from the instrumentation command line, documented in the :ref:`instr-tracename` section of this manual. +Analysis of the coverage achieved by previous executions is done with +|gcvcov| commands. For our example use case, this could for example +be:: -Example production of a coverage report ---------------------------------------- - -Analysis of the coverage achieved by previous executions is done with |gcvcov| -commands. For our example use case, this could for example be:: - - gnatcov coverage --level=stmt --annotate=xcov -Ptests.gpr + gnatcov coverage --level=stmt --annotate=xcov test_inc*.srctrace -Ptests.gpr -... where ```` would be either the source or the binary trace produced -by the commands introduced in the previous example sections. Here, we request: +Here, we request: - A source *statement coverage* assessment with :cmd-option:`--level=stmt`, - An annotated source report in text format with :cmd-option:`--annotate=xcov`, -- For the complete set of units involved in the executable, per - :cmd-option:`-Ptests.gpr` and no specification otherwise in the project - files. +- For the complete set of units involved in the executable with + :cmd-option:`-Ptests.gpr`. This produces annotated sources in the project's object directory, with ``ops.adb.xcov`` quoted below: @@ -354,20 +260,25 @@ all the statements except the one dealing with a ``Decrement`` operation, indeed never exercised by our driver. The command actually also produces reports for ``ops.ads`` and -``test_inc.adb``, even though the latter is not really relevant. Focus on -specific units can be achieved by providing a more precise set of units of -interest at this stage. For source traces, this could also be incorporated as -part of the instrumentation step, as there is no point in instrumenting the -test units for their own coverage achievements. +``test_inc.adb``, even though the latter is not really relevant. Focus +on specific units can be achieved by providing a more precise set of +units of interest at this step, for example passing ``-Pcode.gpr`` +instead of ``-Ptests.gpr``, adding ``--projects=code.gpr`` to the +latter, or setting dedicated attributes in the project files +themselves. See the :ref:`sunits` chapter for details on this aspect +of the procedure. + +Also note that units of interest can be stated as part of the +instrumentation step, which allows limiting the set of sources that +are instrumented to keep track of coverage, hence minimizes the +associated performance impact. Going Further ============= Each of the steps involved in the process overview presented previously -is described in detail in a specific chapter of this manual, the most -important ones referenced hereafter: - -- :ref:`bin_traces` +is described in detail in a specific chapter of this manual. The most +important ones are: - :ref:`src_traces` @@ -375,14 +286,15 @@ important ones referenced hereafter: - :ref:`scov` -- :ref:`ocov` - - :ref:`consolidation` :ref:`exemptions` is also worth noting here, a mechanism allowing users to define code regions for which coverage violations are expected and legitimate (Ada only at this stage). +The known limitations of the tool are outlined in section +:ref:`instr-limitations`. + Conventions used in the rest of this manual =========================================== diff --git a/doc/gnatcov/gnatcov_bin_part.rst b/doc/gnatcov/gnatcov_bin_part.rst new file mode 100644 index 000000000..c40832649 --- /dev/null +++ b/doc/gnatcov/gnatcov_bin_part.rst @@ -0,0 +1,12 @@ +########################################### +GNATcoverage Appendix - Using Binary Traces +########################################### + +.. toctree:: + :maxdepth: 3 + + bin_intro + bin_traces + cov_object + cov_metrics + bin_convert diff --git a/doc/gnatcov/gnatcov_part.rst b/doc/gnatcov/gnatcov_part.rst index 841d4f80f..98b5ab2d0 100644 --- a/doc/gnatcov/gnatcov_part.rst +++ b/doc/gnatcov/gnatcov_part.rst @@ -7,15 +7,10 @@ GNATcoverage User's Guide getting_started units_of_interest - bin_traces src_traces cov_source - cov_object - cov_metrics consolidation exemptions gpr - bin_traces_convert gps - appendix glossary diff --git a/doc/index.rst b/doc/index.rst index ad35eb865..30fdea3bf 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -9,3 +9,4 @@ gnatcov/gnatcov_part gnattest/gnattest_part integration/integration_part + gnatcov/gnatcov_bin_part diff --git a/doc/integration/integration_part.rst b/doc/integration/integration_part.rst index 64be188a6..723d99ce0 100644 --- a/doc/integration/integration_part.rst +++ b/doc/integration/integration_part.rst @@ -49,11 +49,10 @@ If all the switches that need to be passed to |gcp| are correctly defined in will build and run all the harness projects and then generate a coverage report for all the units under test. -By default, the trace kind (binary or source, see :ref:`selecting_trace_kind`) -used to produce the coverage report will be chosen based on the target of the -root project. Coverage data for a native project will be obtained using -:ref:`source traces `, and coverage for projects targeting a cross -environment will be assessed using :ref:`binary traces `. +By default, coverage data for a native project is obtained using +:ref:`source traces ` and coverage for projects targeting +a cross environment is assessed using :ref:`binary traces +`. For cases where the default behavior isn't appropriate for the project under test, the rules for producing a coverage report from both kind of traces are From 6a18cacc994c59f556dd865c8e8ba29993e5e4fe Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 14 Dec 2022 00:44:53 -0800 Subject: [PATCH 0099/1483] Remove note advertising exemptions as Ada only Exemptions are now also supported for C :) Part of V805-004 (focus the main gnatcov doc on instrumentation) --- doc/gnatcov/getting_started.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gnatcov/getting_started.rst b/doc/gnatcov/getting_started.rst index 97deb1164..3d8538f6c 100644 --- a/doc/gnatcov/getting_started.rst +++ b/doc/gnatcov/getting_started.rst @@ -290,7 +290,7 @@ important ones are: :ref:`exemptions` is also worth noting here, a mechanism allowing users to define code regions for which coverage violations are -expected and legitimate (Ada only at this stage). +expected and legitimate. The known limitations of the tool are outlined in section :ref:`instr-limitations`. From 60dc0a84f39488bd1244281bb3b423794ad8379a Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Sun, 11 Dec 2022 06:57:39 -0800 Subject: [PATCH 0100/1483] Adjust Specify Units of Interest doc to instrumentation split Focus the main doc chapter on the source instrumentation workflow. Clarify what can be used when (GPR switches vs --sid, gnatcov instrument vs gnatcov coverage). Put GPR facilities first, showing the simplest possible use upfront. Augment the introduction chapter on binary traces with a how-to specify units of interest in this mode. Part of V805-004 --- doc/gnatcov/bin_intro.rst | 39 ++++++++- doc/gnatcov/getting_started.rst | 51 ++++++----- doc/gnatcov/units_of_interest.rst | 141 ++++++++++++++---------------- 3 files changed, 128 insertions(+), 103 deletions(-) diff --git a/doc/gnatcov/bin_intro.rst b/doc/gnatcov/bin_intro.rst index 1bc0dd6cd..4cf7849e3 100644 --- a/doc/gnatcov/bin_intro.rst +++ b/doc/gnatcov/bin_intro.rst @@ -127,6 +127,41 @@ coverage at most. If MCDC analysis is needed, ``--level=stmt+mcdc`` must be passed to |gcvrun| as well and we recommend also providing source coverage obligations in this case. +Producing report is then achieved as for sources traces, using the +binary trace files as inputs to the |gcvcov| commands. + +Units of interest can be conveyed with either the GPR oriented +facilities as with source traces, or with :cmd-option:`--scos` +switches to provide lists of files holding coverage obligations in a +similar fashion as :cmd-option:`--sid` switches for ``.sid`` files out +of source instrumentation. + +The files to list with :cmd-option:`--scos` are the *Library +Information* files produced by the compiler along with object files, +which are ``.ali`` files for Ada and ``.gli`` files for C. + +The GNAT toolchain provides a helpful device in this process for Ada +units: the :cmd-option:`-A` command line argument to +:command:`gnatbind` which produces a list of all the ``.ali`` files +involved in an executable construction. By default, the list goes to +standard output. It may be directed to a file on request with +:cmd-option:`-A=`, and users may of course filter this +list as they see fit depending on their analysis purposes. + +Below is a complete example sequence of commands to illustrate, using +the standard Unix ``grep`` tool to filter out test harness units:: + + # Build executable and produce the corresponding list of ALI files. Pass + # -A to gnatbind through gprbuild -bargs then filter out the test units: + gprbuild -p --target=powerpc-elf --RTS=light-mpc8641 -Ptests.gpr + -cargs -fdump-scos -g -fpreserve-control-flow -bargs -A=all.alis + + # Run and analyse all units except the test harness, filtering out + # the correspond ALI files from the list: + grep -v 'test_[^/]*.ali' all.alis > nontest.alis + gnatcov run --level=stmt+mcdc --scos=@nontest.alis + gnatcov coverage --level=stmt+mcdc --annotate=xcov --scos=@nontest.alis + Going Further ============= @@ -134,8 +169,8 @@ As the source and binary trace based workflows share commonalities, a lot of information from the main documentation also applies to the use binary traces, such as -- The use of project files, to specify command switches or designate - units of interest, +- The use of project files to specify command switches or designate + units of interest at analysis time, - Using coverage checkpoints or traces for consolidation, diff --git a/doc/gnatcov/getting_started.rst b/doc/gnatcov/getting_started.rst index 3d8538f6c..c43f0beb3 100644 --- a/doc/gnatcov/getting_started.rst +++ b/doc/gnatcov/getting_started.rst @@ -172,34 +172,40 @@ will use a couple of project files in the common working directory: Setup, Instrument, Build, Execute, Analyze ------------------------------------------ -We first set up the instrumentation context, providing a local +The instrumentation step that follows assumes that the original program +is well formed. A simple way to verify this is to build the non instrumented +version first. For our example, this would be:: + + gprbuild -f -p -Ptests.gpr + +We then first set up the instrumentation context, providing a local *prefix* location where the runtime and default parameters for future commands are going to be installed:: gnatcov setup --prefix=/path/to/gnatcov-rts -The simplest means to let further commands know about the *prefix* -location consists in adding ``/share/gpr`` to the -``GPR_PROJECT_PATH`` variable. In a Unix like environment, this would -be achieved with:: +Letting further commands know about the *prefix* location is achieved +by adding ``/share/gpr`` to the ``GPR_PROJECT_PATH`` +variable. In a Unix like environment, this would be:: export GPR_PROJECT_PATH=$GPR_PROJECT_PATH:/path/to/gnatcov-rts/share/gpr -The instrumentation step that follows assumes that the original program -is well formed. A simple way to verify this is to build the non instrumented -version first. For our example, this would be:: +This will both let the ``gprbuild`` command below locate the +``gnatcov_rts.gpr`` project file, and the |gcvins| command find +default parameter values. - gprbuild -f -p -Ptests.gpr - -Instrumenting a test main program together with its "code" dependency is then -achieved by a |gcvins| command:: +Instrumentation is performed by a simple |gcvins| command:: gnatcov instrument -Ptests.gpr --level=stmt -And building the instrumented program goes like:: +The use of ``tests.gpr``, not ``code.gpr``, at this step is important +as it lets the instrumenter know about the main subprogram, which +needs to be processed specially to dump coverage data. + +Building the instrumented program then goes like:: gprbuild -f -p -Ptests.gpr \ - --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts + --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts.gpr This is the same command as for the regular build, with a couple of additional switches to: @@ -222,8 +228,7 @@ instrumentation command line, documented in the :ref:`instr-tracename` section of this manual. Analysis of the coverage achieved by previous executions is done with -|gcvcov| commands. For our example use case, this could for example -be:: +|gcvcov| commands. For our example use case, this could for instance be:: gnatcov coverage --level=stmt --annotate=xcov test_inc*.srctrace -Ptests.gpr @@ -262,16 +267,10 @@ indeed never exercised by our driver. The command actually also produces reports for ``ops.ads`` and ``test_inc.adb``, even though the latter is not really relevant. Focus on specific units can be achieved by providing a more precise set of -units of interest at this step, for example passing ``-Pcode.gpr`` -instead of ``-Ptests.gpr``, adding ``--projects=code.gpr`` to the -latter, or setting dedicated attributes in the project files -themselves. See the :ref:`sunits` chapter for details on this aspect -of the procedure. - -Also note that units of interest can be stated as part of the -instrumentation step, which allows limiting the set of sources that -are instrumented to keep track of coverage, hence minimizes the -associated performance impact. +units of interest at this step, for example by adding +``--projects=code.gpr`` to the command line, or setting dedicated attributes +in the project files themselves. See the :ref:`sunits` chapter for +details on this aspect of the procedure. Going Further ============= diff --git a/doc/gnatcov/units_of_interest.rst b/doc/gnatcov/units_of_interest.rst index 748a59f55..b46112e49 100644 --- a/doc/gnatcov/units_of_interest.rst +++ b/doc/gnatcov/units_of_interest.rst @@ -3,71 +3,31 @@ Specifying *Units Of Interest* ============================== -This chapter describes the means available to convey the set of units on which +This chapter describes the means to convey the set of units on which coverage should be assessed, which we commonly refer to as the :dfn:`units of -interest`, and which are relevant to |gcvins|, |gcvrun| and |gcvcov|. - -There are two main families of such means: users would either provide the set -of files which hold the coverage obligations for the units of interest, or -rely on project files facilities to designate the set of units. At analysis -time, the actual list of unit names for which a report or checkpoint is -produced as well as the list of individually ignored source files for each unit -can be displayed with the :cmd-option:`--dump-units-to` option of the -|gcvcov| command. - -.. _passing_scos: - -Providing coverage obligation files (:cmd-option:`--scos|--sid`) ----------------------------------------------------------------- - -With the :cmd-option:`--scos` or :cmd-option:`--sid` command line arguments, -users convey the set of units of interest by directly providing the set of -files which contain the coverage obligations for those units. - -The :cmd-option:`--scos` switch is for binary trace based analysis and the -files to provide are the *Library Information* files produced by the compiler -(``.ali`` files for Ada, ``.gli`` files for C). The :cmd-option:`--sid` switch -is for source trace based analysis and the files to provide are the ``.sid`` -*Source Instrumentation Data* files produced by ``gnatcov instrument``. In all -cases, the files are located at the same place as where the object file for a -unit is produced. - -The following paragraphs provide details and examples on the use of -:cmd-option:`--scos` with ``.gli`` or ``.ali`` files. The same principles apply -to :cmd-option:`--sid` with ``.sid`` files. - -Each occurrence of :cmd-option:`--scos` on the command line expects a single -argument which specifies a set of units of interest. Multiple occurrences are -allowed and the sets accumulate. The argument might be either the name of a -single Library Information file for a unit, or a :term:`@listfile arguments -<@listfile argument>` expected to contain a list of such file names. - -For example, focusing on Ada units ``u1``, ``u2`` and ``u3`` can be achieved -with either ``--scos=u1.ali --scos=u2.ali --scos=u3.ali``, with ``--scos=u3.ali ---scos=@lst12`` where ``lst12`` is a text file containing the first two ALI -file names, or with other combinations alike. - -The GNAT toolchain provides a useful device for list computations: the -:cmd-option:`-A` command line argument to :command:`gnatbind` which produces a -list of all the ``.ali`` files involved in an executable construction. By -default, the list goes to standard output. It may be directed to a file on -request with :cmd-option:`-A=`, and users may of course filter -this list as they see fit depending on their analysis purposes. - -Below is an example sequence of commands to illustrate, using the standard Unix -``grep`` tool to filter out test harness units, assuming a basic naming -convention:: - - # Build executable and produce the corresponding list of ALI files. Pass - # -A to gnatbind through gprbuild -bargs then filter out the test units: - gprbuild -p --target=powerpc-elf --RTS=zfp-prep -Pmy.gpr - test_divmod0.adb -fdump-scos -g -fpreserve-control-flow -bargs -A=all.alis - - # Run and analyse all units except the test harness, filtering out - # the correspond ALI files from the list: - grep -v 'test_[^/]*.ali' all.alis > divmod0.alis - gnatcov run --level=stmt+mcdc --scos=@divmod0.alis - gnatcov coverage --level=stmt+mcdc --annotate=xcov --scos=@divmod0.alis +interest`. + +The first opportunity to do so is at |gcvins| time, with GPR project file +oriented command line switches possibly associated with coverage specific +attributes within project files. This step controls which units are +instrumented to track coverage to begin with. It also needs visibility +over the main subprogram(s) as they require special processing to trigger +the calls dumping coverage data when a program terminates. + +The use of such GPR based mechanisms is also allowed at |gcvcov| time to +further refine the focus of reports or coverage checkpoints. Another mechanism +is available at this point, with lower level command line switches letting +users provide lists of files holding SCO definitions for the units of +interest, where one such file is produced per unit by the |gcvins| command. +When both obligation files and project file options are on the command line, +the former prevail and the project files are only used for switches or the +determination of the target and runtime configuration. + +Regardless of how units of interest were requested, the actual list of units +for which a report is produced can be displayed with the +:cmd-option:`--dump-units-to` option of the |gcvcov| command. This also +displays the list of individually ignored source files for each unit, +controlled by the :cmd-option:`--ignore-source-files` switch. .. _passing_gpr: @@ -75,15 +35,23 @@ convention:: Using project files (:cmd-option:`-P`, :cmd-option:`--projects`, :cmd-option:`--units`) --------------------------------------------------------------------------------------- -As an alternative to providing the complete list of coverage obligation files -with :cmd-option:`--scos` or :cmd-option:`--sid`, you can use project files to -specify units of interest. When both obligation files and project file options -are on the command line, the former prevail and the project files are only used -for switches or the determination of the target and runtime configuration. +The simplest possible form of units of interest specification with GPR +facilities is a lone:: + + -P.gpr + +provided to both |gcvins| and |gcvcov|. In the absence of coverage related +attributes within the project file(s), this requests considering *of interest* +all the units of ** and its project dependency closure. + +For |gcvins|, the source files containing main subprograms need to be +encompassed by ``myproject.gpr`` and specified either by a ``Main`` +project file attribute or provided on the command line, as for ``gprbuild`` +commands. -The units of interest designation with project files incurs two levels of -selection: first, specify the set of :dfn:`projects of interest` where the -units of interest reside, then specify units of interest therein. +Finer grain control is possible with additional switches and attributes, +letting users first specify the set of :dfn:`projects of interest` where the +units of interest reside, then may filter the *units* of interest therein. Conveying *projects* of interest ******************************** @@ -465,10 +433,33 @@ Typically, from a sample ``foo.c`` source like: { ... } -``gcc -c foo.c -fdump-scos ...`` would produce a ``foo.o`` object file, a -``foo.c.gli`` companion Library Information file, and excluding it from the -analysis scope can be achieved with:: +excluding ``foo.c`` from the analysis scope can be achieved with:: package Coverage is for Excluded_Units use ("foo.c"); /* source file name here */ end Coverage; + +.. _passing_scos: + +Providing coverage obligation files (:cmd-option:`--sid`) +--------------------------------------------------------- + +With the :cmd-option:`--sid` command line option, users can convey the set of +units of interest by directly providing the set of files which contain the +coverage obligations for those units. + +One such file is produced for each unit instrumented by the |gcvins| command, +next to the object file for a unit, with a `.sid` extension which stands for +*Source Instrumentation Data*. + +Each occurrence of :cmd-option:`--sid` on the command line expects a +single argument which specifies a set of units of interest. Multiple +occurrences are allowed and the sets accumulate. The argument might be +either the name of a single `.sid` file for a unit, or a +:term:`@listfile arguments <@listfile argument>` expected to contain a +list of such file names. + +For example, focusing on Ada units ``u1``, ``u2`` and ``u3`` can be achieved +with either ``--sid=u1.sid --sid=u2.sid --sid=u3.sid``, with ``--sid=u3.sid +--sid=@lst12`` where ``lst12`` is a text file containing the first two SID +file names, or with other combinations alike. From 6e7d9dd328e47f82fca1aa7d807328c8e5d651ff Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Sun, 11 Dec 2022 07:17:15 -0800 Subject: [PATCH 0101/1483] Rework explicit refs to bin trace workflow in main doc Since the main doc is now "source instrumentation" only, rework bits referring to, for example, "gnatcov run" explictly. Part of V805-004 --- doc/gnatcov/cons_checkpoints.rst | 8 ++++---- doc/gnatcov/cons_traces.rst | 4 ++-- doc/gnatcov/cov_source.rst | 13 ++++--------- 3 files changed, 10 insertions(+), 15 deletions(-) diff --git a/doc/gnatcov/cons_checkpoints.rst b/doc/gnatcov/cons_checkpoints.rst index cd77856c0..77486529c 100644 --- a/doc/gnatcov/cons_checkpoints.rst +++ b/doc/gnatcov/cons_checkpoints.rst @@ -39,8 +39,8 @@ latter case, if the contribution comes from an intermediate checkpoint, the command which produced the checkpoint is displayed. For example, a sequence of commands such as:: - gnatcov run obj/pgm1 -o trace1 - gnatcov run obj/pgm2 -o trace2 + obj/pgm1 # producing trace1 + obj/pgm2 # producing trace2 gnatcov coverage --level=<> trace1 --save-checkpoint=t1.ckpt gnatcov coverage --level=<> trace2 --checkpoint=t1.ckpt --annotate=report @@ -51,13 +51,13 @@ Would produce a report with this kind of information in the header:: Trace files: trace2 - kind : binary + kind : source program : obj/pgm2 date : 2020-09-22 16:32:52 tag : trace1 - kind : binary + kind : source program : obj/pgm1 date : 2020-09-22 16:32:47 tag : diff --git a/doc/gnatcov/cons_traces.rst b/doc/gnatcov/cons_traces.rst index 7be5fdba3..77a25e5bd 100644 --- a/doc/gnatcov/cons_traces.rst +++ b/doc/gnatcov/cons_traces.rst @@ -119,8 +119,8 @@ the symmetric results:: 12 .: end if; 13 .: end Stat; -Then a report obtained by combining traces, binary or source, will show -achievement of complete statement coverage like so:: +Then a report obtained by combining traces will show achievement of +complete statement coverage like so:: 6 .: procedure Stat (Safe : Boolean) is 7 .: begin diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index 87914867e..6911d6f0a 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -1280,16 +1280,11 @@ single case where X1 < V < X2: Assert (Between (X1 => 2, X2 => 5, V => 3)); -- X1 < V < X2 end Test_X1VX2; -Performing MCDC analysis with binary traces requires telling the execution step -about it, by providing both the :cmd-option:`--level` and a list of units for -which analysis is to be performed to |gcvrun|:: +After instrumentation for MCDC and execution, we can then request, +say, an :cmd-option:`=xcov+` report to get a first set of results in +the ``ranges.adb.xcov`` annotated source:: - gnatcov run --level=stmt+mcdc -Pmytest.gpr test_x1vx2 - -We can then request, say, an :cmd-option:`=xcov+` report to get a first set of -results in the ``ranges.adb.xcov`` annotated source:: - - gnatcov coverage --level=stmt+mcdc -Pmytest.gpr --annotate=xcov+ test_x1vx2.trace + gnatcov coverage --level=stmt+mcdc -Pmytest.gpr --annotate=xcov+ test_x1vx2.srctrace ... 8 .: function Between (X1, X2, V : Integer) return Boolean is From 9b0c7206bb1b22400c8a9c7a14a57e087c0dd70f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 19 Dec 2022 16:04:15 +0100 Subject: [PATCH 0102/1483] Project.adb: parse the Switches attributes from the origin project When the Origin_Project attribute is set in the root project, loading of the Switches attributes will be done from that project instead of from the root project. This will allow a more seamless integration between gnatcov and gnattest. TN: VC19-001 Closes eng/cov/gnatcoverage#2 --- tools/gnatcov/project.adb | 80 +++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index a1e6a2b3c..7c1caa196 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -181,6 +181,10 @@ package body Project is -- Initialize project environment. Formals have the same semantics as in -- Load_Root_Project. + function Lookup_Project (Prj_Name : String) return Project_Type; + -- Look for the project in Prj_Tree whose name matches Prj_Name and return + -- it. Emit a fatal error if there is no such project. + procedure Build_Prj_Map with Pre => Is_Project_Loaded; -- Add entries in Prj_Map for all relevant projects @@ -808,51 +812,47 @@ package body Project is end if; end Initialize; + -------------------- + -- Lookup_Project -- + -------------------- + + function Lookup_Project (Prj_Name : String) return Project_Type is + Prj_Name_FS : constant GNATCOLL.VFS.Filesystem_String := + +Simple_Name (Prj_Name); + Last : Integer; + begin + -- Strip optional Project_File_Extension + + if Prj_Name_FS'Length >= Project_File_Extension'Length + and then + Prj_Name_FS (Prj_Name_FS'Last - Project_File_Extension'Length + 1 + .. Prj_Name_FS'Last) = Project_File_Extension + then + Last := Prj_Name_FS'Last - Project_File_Extension'Length; + else + Last := Prj_Name_FS'Last; + end if; + + -- Look up project from project tree + + return Result : constant Project_Type := Prj_Tree.Project_From_Name + (+Prj_Name_FS (Prj_Name_FS'First .. Last)) + do + if Result = No_Project then + Fatal_Error ("project " & Prj_Name & " not found"); + end if; + end return; + end Lookup_Project; + ------------------- -- Build_Prj_Map -- ------------------- procedure Build_Prj_Map is - function Lookup_Project (Prj_Name : String) return Project_Type; - -- Look for the project in Prj_Tree whose name matches Prj_Name and - -- return it. Emit a fatal error if there is no such project. - procedure Process_Project (Project : Project_Type); -- Callback for Iterate_Projects: add an entry in Prj_Map for Project - -------------------- - -- Lookup_Project -- - -------------------- - - function Lookup_Project (Prj_Name : String) return Project_Type is - Prj_Name_FS : constant GNATCOLL.VFS.Filesystem_String := - +Simple_Name (Prj_Name); - Last : Integer; - begin - -- Strip optional Project_File_Extension - - if Prj_Name_FS'Length >= Project_File_Extension'Length - and then - Prj_Name_FS (Prj_Name_FS'Last - Project_File_Extension'Length + 1 - .. Prj_Name_FS'Last) = Project_File_Extension - then - Last := Prj_Name_FS'Last - Project_File_Extension'Length; - else - Last := Prj_Name_FS'Last; - end if; - - -- Look up project from project tree - - return Result : constant Project_Type := Prj_Tree.Project_From_Name - (+Prj_Name_FS (Prj_Name_FS'First .. Last)) - do - if Result = No_Project then - Fatal_Error ("project " & Prj_Name & " not found"); - end if; - end return; - end Lookup_Project; - --------------------- -- Process_Project -- --------------------- @@ -1513,9 +1513,15 @@ package body Project is -------------- function Switches (Op : String) return String_List_Access is + Origin_Prj : constant String := + Prj_Tree.Root_Project.Attribute_Value (Origin_Project_Attribute); + Actual_Prj : constant Project_Type := + (if Origin_Prj = "" + then Prj_Tree.Root_Project + else Lookup_Project (Origin_Prj)); begin return Attribute_Value - (Prj_Tree.Root_Project, +Switches, Index => Op); + (Actual_Prj, +Switches, Index => Op); end Switches; ----------------- From 117741fe137587adf399db13cfef02c983655cbd Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 9 Nov 2022 12:48:22 +0100 Subject: [PATCH 0103/1483] C instr: remove spurious line markers in preprocessed code The following preprocessed code excerpt: ``` # 1 main.c int a; # 1 main.c 3 int ab; ``` will produce SCOs with conflicting source locations, as we use the presumed location, which accounts for line markers. To avoid this problem, we will postprocess the code to remove spurious line markers, so it will look like this: ``` # 1 main.c int a;int ab; ``` TN: VA21-009 --- tools/gnatcov/annotations.adb | 22 ++++- tools/gnatcov/instrument-c.adb | 137 ++++++++++++++++++++++++--- tools/gnatcov/instrument-c.ads | 23 +++++ tools/gnatcov/instrument-c__stub.ads | 6 +- 4 files changed, 167 insertions(+), 21 deletions(-) diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 15255e829..66714b06b 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -32,6 +32,7 @@ with Coverage.Object; with Coverage.Source; use Coverage.Source; with Coverage.Tags; with Instrument.Base_Types; +with Instrument.C; with Outputs; use Outputs; with Subprocesses; with Switches; use Switches; @@ -704,9 +705,11 @@ package body Annotations is declare SFI : constant Source_File_Index := Sloc_Start.Source_File; - Info : constant PP_Info := Get_PP_Info (SCO); - Preprocessed_Filename : constant String := Get_PP_Filename (SFI); - Preprocessed_SFI : Source_File_Index := + Info : constant PP_Info := Get_PP_Info (SCO); + Preprocessed_Filename : constant String := + Get_PP_Filename (SFI) & ".prepro"; + Postprocessed_Filename : constant String := Get_PP_Filename (SFI); + Preprocessed_SFI : Source_File_Index := Get_Index_From_Generic_Name (Preprocessed_Filename, Source_File, Insert => False); @@ -723,13 +726,22 @@ package body Annotations is Run_Command (PP_Cmds.Element (SFI), "Preprocessing", Preprocessed_Filename, - Err_To_Out => False, + Err_To_Out => False, Ignore_Error => True); if Preprocessed then + -- As a reminder, we compute source locations from + -- preprocessed sources with redundant line markers + -- removed. This means that the preprocessed code + -- locations refer to the latter version, which we + -- need to recompute there to have the right version + -- of the source. + + Instrument.C.Postprocess_Source + (Preprocessed_Filename, Postprocessed_Filename); Preprocessed_SFI := Get_Index_From_Generic_Name - (Preprocessed_Filename, + (Postprocessed_Filename, Source_File, Insert_After_Freeze => True); else diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index c030e4dcf..4c8f849db 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2606,6 +2606,100 @@ package body Instrument.C is return Macro_Vector_Cst_Access (Result); end Builtin_Macros; + ------------------------ + -- Postprocess_Source -- + ------------------------ + + procedure Postprocess_Source + (Preprocessed_Filename : String; + Postprocessed_Filename : String) + is + Preprocessed_File : Ada.Text_IO.File_Type; + Postprocessed_File : Ada.Text_IO.File_Type; + begin + Open (Preprocessed_File, In_File, Preprocessed_Filename); + Create (Postprocessed_File, Out_File, Postprocessed_Filename); + declare + Line_Marker_Pattern : constant GNAT.Regpat.Pattern_Matcher := + Compile + ("\s*#\s*" + -- Start of the line directive + + & "([0-9]+)" + -- Line index + + & "\s+" + & "([^ \s]+)" + -- Filename + + & "(.*)" + -- Trailing flags; + + ); + + Add_New_Line : Boolean := True; + + Line_Marker_Line : Integer; + Line_Marker_File : Unbounded_String; + -- Line and file of the read line if it is a line marker + + Current_File : Unbounded_String; + Current_Line : Integer := 0; + -- Line and file of the currently-active line marker + + Matches : Match_Array (0 .. 3); + begin + while not End_Of_File (Preprocessed_File) loop + declare + Line : constant String := Get_Line (Preprocessed_File); + begin + Match (Line_Marker_Pattern, Line, Matches); + if Matches (0) /= No_Match then + Line_Marker_Line := + Integer'Value + (Line (Matches (1).First .. Matches (1).Last)); + Line_Marker_File := + +Line (Matches (2).First .. Matches (2).Last); + if Line_Marker_Line = Current_Line - 1 + and then Line_Marker_File = Current_File + then + -- We have a spurious line marker. Remove it, and write + -- the next line in continuation of the previous line. + + Add_New_Line := False; + Current_Line := Current_Line - 1; + else + -- Write this line marker, and set the current line and + -- the current file. + + Current_Line := Line_Marker_Line; + Current_File := Line_Marker_File; + + -- Line markers should always be inserted on their own + -- line. + + Add_New_Line := True; + New_Line (Postprocessed_File); + Put (Postprocessed_File, Line); + end if; + else + if Add_New_Line then + New_Line (Postprocessed_File); + end if; + Add_New_Line := True; + Put (Postprocessed_File, Line); + Current_Line := Current_Line + 1; + end if; + end; + end loop; + if Add_New_Line then + New_Line (Postprocessed_File); + end if; + end; + Close (Preprocessed_File); + Close (Postprocessed_File); + end Postprocess_Source; + ----------------------- -- Preprocess_Source -- ----------------------- @@ -2623,15 +2717,22 @@ package body Instrument.C is Success : Boolean; -- Whether this command is successful - PID : constant Unsigned_64 := + PID : constant Unsigned_64 := Unsigned_64 (Pid_To_Integer (Current_Process_Id)); - PP_Output_Filename : constant String := + + Preprocessed_Filename : constant String := + (+Info.Output_Dir) / ("pp-" & Strip_Zero_Padding (Hex_Image (PID))); + -- Preprocessed file. We then postprocess it to remove redundant line + -- markers inserted by the preprocessor. + + Preprocessor_Output_Filename : constant String := (+Info.Output_Dir) / ("pp-output-" & Strip_Zero_Padding (Hex_Image (PID))); - PP_Output_File : Ada.Text_IO.File_Type; - begin - PP_Filename := +Register_New_File (Info, Filename); + Preprocessor_Output_File : Ada.Text_IO.File_Type; + -- File containing the preprocessor output (used to get include search + -- paths). + begin Cmd := (Command => +Compiler_Driver (Info.Project, Instrumenter.Language), others => <>); @@ -2660,7 +2761,7 @@ package body Instrument.C is Append_Arg (Cmd, "-v"); Append_Arg (Cmd, "-o"); - Append_Arg (Cmd, +PP_Filename); + Append_Arg (Cmd, Preprocessed_Filename); -- Run the preprocessing command, keep track of whether it was -- successful for later @@ -2668,7 +2769,7 @@ package body Instrument.C is Success := Run_Command (Command => Cmd, Origin_Command_Name => "Preprocessing", - Output_File => PP_Output_Filename, + Output_File => Preprocessor_Output_Filename, Ignore_Error => True); -- Clear the search path so that we populate it from the include search @@ -2682,7 +2783,7 @@ package body Instrument.C is -- ... -- End of search list - Open (PP_Output_File, In_File, PP_Output_Filename); + Open (Preprocessor_Output_File, In_File, Preprocessor_Output_Filename); declare RE_Begin_Pattern : constant Pattern_Matcher := @@ -2692,9 +2793,9 @@ package body Instrument.C is Compile ("End of search list"); Matches : Match_Array (0 .. 0); begin - while not End_Of_File (PP_Output_File) loop + while not End_Of_File (Preprocessor_Output_File) loop declare - Line : constant String := Get_Line (PP_Output_File); + Line : constant String := Get_Line (Preprocessor_Output_File); begin Match (RE_Begin_Pattern, Line, Matches); if Matches (0) /= No_Match then @@ -2725,18 +2826,24 @@ package body Instrument.C is -- output. if not Begin_Pattern_Matched then - Reset (PP_Output_File); + Reset (Preprocessor_Output_File); end if; - while not End_Of_File (PP_Output_File) loop - Put_Line (Get_Line (PP_Output_File)); + while not End_Of_File (Preprocessor_Output_File) loop + Put_Line (Get_Line (Preprocessor_Output_File)); end loop; - Delete (PP_Output_File); + Delete (Preprocessor_Output_File); Fatal_Error ("Preprocessing failed: aborting"); end if; + Delete (Preprocessor_Output_File); end; - Delete (PP_Output_File); + -- Now, onto the postprocessing. Remove spurious system header line + -- markers. + + PP_Filename := +Register_New_File (Info, Filename); + Postprocess_Source (Preprocessed_Filename, +PP_Filename); + Ada.Directories.Delete_File (Preprocessed_Filename); end Preprocess_Source; -------------------------- diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 512992047..136b8d38b 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -387,6 +387,29 @@ package Instrument.C is -- UIC.Sources_Of_Interest. Return whether this source file is a source of -- interest. + procedure Postprocess_Source + (Preprocessed_Filename : String; + Postprocessed_Filename : String); + -- Postprocess the given Preprocessed_Filename to remove redundant line + -- markers. This is done to keep the following invariant intact: we must + -- be able to use presumed source locations to have unique SCOs source + -- locations. As a reminder, presumed locations are computed through + -- preprocessor-inserted line markers. + -- + -- This means that the following code: + -- # 1 main.c + -- int a; + -- # 1 main.c 3 + -- int ab; + -- + -- will be rewritten to + -- # 1 main.c + -- int a; int ab; + -- + -- Note that this will remove the "system header "flag (the "3" at the + -- end of the line marker). We expect that this won't be a problem in + -- practice. + private function Find_Instrumented_Entities diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index eab924d79..cdff4928e 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -30,7 +30,7 @@ with Instrument.Base_Types; use Instrument.Base_Types; with Instrument.Common; use Instrument.Common; with Switches; use Switches; -private package Instrument.C is +package Instrument.C is type C_Family_Instrumenter_Type is abstract new Language_Instrumenter with null record; @@ -77,4 +77,8 @@ private package Instrument.C is C_Instrumenter : aliased constant C_Instrumenter_Type := (null record); CPP_Instrumenter : aliased constant CPP_Instrumenter_Type := (null record); + procedure Postprocess_Source + (Preprocessed_Filename : String; + Postprocessed_Filename : String) is null; + end Instrument.C; From f2abeb64f3af7fc7a18c8aa7401fd4dd7aa31dad Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 9 Nov 2022 14:47:31 +0100 Subject: [PATCH 0104/1483] sc_obligations.adb: ignore control locations with the instrumenter The control location is computed from the given location for the decision SCO, when appending an entry to the SCO table. With the C instrumenter, such location can conflicts when decisions nest. This problem was observed on the following code excerpt: if ( ? 1 : 0) { ; } In this case, the location of the if decision, and the location of the ternary expression decision are the same (start location of ). As we don't need control locations for the instrumenter (they are only useful for dominance markers, which we suppressed before), we will ignore them when processing SCOs for source traces. TN: VB03-009 --- tools/gnatcov/sc_obligations.adb | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 6ede290cd..6615f72cc 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -326,12 +326,14 @@ package body SC_Obligations is State : in out CU_Load_State; Ignored_Slocs : in out Ignored_Slocs_Sets.Set; SCO_Map : access LL_HL_SCO_Map := null; - Count_Paths : Boolean); + Count_Paths : Boolean; + Provider : SCO_Provider); -- Load the low level SCO at SCO_Index into our Internal table, to be part -- of the CU compilation unit. -- -- Use and update State according to the semantics of its members. See - -- Process_Low_Level_SCOs for the semantics of SCO_Map. + -- Process_Low_Level_SCOs for the semantics of SCO_Map, Count_Paths and + -- Provider. ------------------------------- -- Main SCO descriptor table -- @@ -3043,7 +3045,8 @@ package body SC_Obligations is State : in out CU_Load_State; Ignored_Slocs : in out Ignored_Slocs_Sets.Set; SCO_Map : access LL_HL_SCO_Map := null; - Count_Paths : Boolean) + Count_Paths : Boolean; + Provider : SCO_Provider) is Unit : CU_Info renames CU_Vector.Reference (CU); SCOE : SCOs.SCO_Table_Entry renames SCOs.SCO_Table.Table (SCO_Index); @@ -3265,7 +3268,18 @@ package body SC_Obligations is (Kind => Decision, Origin => CU, Control_Location => - Slocs.To_Sloc (Unit.Main_Source, From_Sloc), + + -- Control locations are only useful for dominance + -- markers, which are only used with binary traces. As + -- it is impractical to get the correct location with + -- the C/C++ instrumenter, and as using incorrect slocs + -- can create conflicts, ignore those in the + -- instrumentation case. + + (if Provider = Compiler + then Slocs.To_Sloc (Unit.Main_Source, From_Sloc) + else No_Location), + D_Kind => To_Decision_Kind (SCOE.C1), Last_Cond_Index => 0, Aspect_Name => @@ -3410,7 +3424,8 @@ package body SC_Obligations is State, Ignored_Slocs_Set, SCO_Map, - Count_Paths); + Count_Paths, + Provider); end loop; end loop; From fa1d6eccecacaaab01d1a73c09d95b1f11237f20 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 22 Dec 2022 15:05:13 +0100 Subject: [PATCH 0105/1483] Instrument.C: do not exit with a failure when there is a parsing error Parsing errors are bound to happen as we preprocess with gcc and parse with clang. Only print a warning when this happens. TN: VB03-009 --- tools/gnatcov/instrument-c.adb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 4c8f849db..0e14310c5 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -1914,7 +1914,8 @@ package body Instrument.C is begin case Severity is when Diagnostic_Error | Diagnostic_Fatal => - Outputs.Error ("Error when parsing the file " & Str); + Outputs.Warning_Or_Error + ("Error when parsing the file " & Str); when others => null; end case; From 15560cec15a3ea45948fd70956d07173750f800e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 4 Jan 2023 15:34:10 +0100 Subject: [PATCH 0106/1483] SC_Obligations: Fix consolidation bug for exemption annotations When loading an exemption annotation from a checkpoint, the CU to which the annotation belongs is not updated according to the mapping of CU between the checkpoint and gnatcov internal tables. This is not a problem during the current execution of gnatcov as the CU of exemption annotations are only used when loading checkpoints, but if the annotation with the wrong CU is then written back to a checkpoint, then this can lead to either annotations wrongly not being loaded, or a constraint error due to attempts to insert an annotation with a key already present in the annotation map. See the corresponding test for a concrete example of the above. This change fixes this bug by inserting the annotations with the CU correctly remapped. Note that this bug was present from the introduction of checkpoints, so it potentially concerns all previous gnatcov versions. TN: VC14-043 --- tools/gnatcov/sc_obligations.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 6615f72cc..c8d5460ba 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -1614,7 +1614,7 @@ package body SC_Obligations is Annotation.CU := Remap_CU_Id (Relocs, Annotation.CU); if Annotation.CU > Last_Existing_CU_Id then Remap_SFI (Relocs, Annotation_Sloc.Source_File); - ALI_Annotations.Insert (Annotation_Sloc, Element (Cur)); + ALI_Annotations.Insert (Annotation_Sloc, Annotation); end if; end if; end; From a4bcf434904c7991b20406a13e54882b729db76f Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Tue, 3 Jan 2023 10:54:08 -0800 Subject: [PATCH 0107/1483] Remove obsolete ref to bin traces in consolidation doc The statement telling that mixing bin and src traces isn't supported is in the "introduction" chapter of the bin traces appendix. There's no need to have it in the main chapter on consolidation, and it actually is confusing there. Part of V805-004 --- doc/gnatcov/cons_traces.rst | 5 ----- 1 file changed, 5 deletions(-) diff --git a/doc/gnatcov/cons_traces.rst b/doc/gnatcov/cons_traces.rst index 77a25e5bd..2a584b5c4 100644 --- a/doc/gnatcov/cons_traces.rst +++ b/doc/gnatcov/cons_traces.rst @@ -13,11 +13,6 @@ The set of traces involved in a computation, with some details about each trace in the *Assessment Context* section of :cmd-option:`=report` outputs, where the command line is quoted. -Trace consolidation works the same for source or binary traces. Mixing -binary and source traces is not supported, however, so all the traces -provided for a consolidation must be of the same kind (all source or -all binary). - The following subsections provide examples of possible use cases of this facility. Single unit tested by different programs From 3cdf33373235ecf273aacde8656312e441c7e573 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 4 Jan 2023 03:09:11 -0800 Subject: [PATCH 0108/1483] Fix sectioning level inaccuracy in bin trace intro chapter "Going Further" is intended at the same level as previous sections in the chapter. Use consistent underlining style. Part of V805-004 --- doc/gnatcov/bin_intro.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gnatcov/bin_intro.rst b/doc/gnatcov/bin_intro.rst index 4cf7849e3..eed05df17 100644 --- a/doc/gnatcov/bin_intro.rst +++ b/doc/gnatcov/bin_intro.rst @@ -163,7 +163,7 @@ the standard Unix ``grep`` tool to filter out test harness units:: gnatcov coverage --level=stmt+mcdc --annotate=xcov --scos=@nontest.alis Going Further -============= +------------- As the source and binary trace based workflows share commonalities, a lot of information from the main documentation also applies to the From 2ae501909e86b5e71e29d75d378386e15d0a24e1 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 4 Jan 2023 03:12:11 -0800 Subject: [PATCH 0109/1483] Move bin-trace section of "consolidation" out to the bin-trace part Part of V805-004 --- doc/gnatcov/cons_traces.rst | 57 ++----------------------------------- doc/gnatcov/run_prereq.rst | 43 +++++++++++++++++++++++++++- 2 files changed, 44 insertions(+), 56 deletions(-) diff --git a/doc/gnatcov/cons_traces.rst b/doc/gnatcov/cons_traces.rst index 2a584b5c4..c11e90be1 100644 --- a/doc/gnatcov/cons_traces.rst +++ b/doc/gnatcov/cons_traces.rst @@ -126,9 +126,8 @@ complete statement coverage like so:: 12 .: end if; 13 .: end Stat; -Assuming you have obtained one trace for the execution of each test, both -traces either source or binary, the command to produce the combined report -would be something like:: +Assuming you have obtained one trace for the execution of each test, +the command to produce the combined report would be something like:: gnatcov coverage --level=stmt --annotate=xcov test_cmd_safe.trace test_cmd_unsafe.trace @@ -378,55 +377,3 @@ visible on lines 7, 14, and 15 of ``main.c``, and attempt to compute an unsupported operation, visible on lines 21 and 22 of ``process.c``. These two scenarios, exercised through ``div.srctrace`` and ``misuse.srctrace`` were indeed not included in the consolidation scope. - -Special care needed with binary traces -====================================== - -Control of inlining in test programs ------------------------------------- - -With binary traces, the program is not itself instrumented to collect coverage -information on its own and the object files used to assess coverage are more -likely (than with source traces) to be used directly in operational -conditions. In such cases, we want to make sure that the binary code from -those object files is indeed exercised during the testing campaign. - -While this would automatically be the case for integration testing campaigns, -campaigns based on the use of explicit testing code, such as unit tests, need -to make sure that calls into the code-under-test by the testing code are not -inlined by the compiler. - -With GCC based toolchains such as GNAT Pro, this can be achieved by adding -:cmd-option:`-fno-inline` to the compilation options of the testing code. - - -Object code overlap in executables ----------------------------------- - -For object or source level criteria, |gcv| computes the coverage achieved for -the full set of routines or source units declared to be of interest amongst -those exposed by the union of the exercised executables, as designated by the -set of consolidated traces; - -For the purpose of computing combined coverage achievements, two symbols are -considered overlapping when all the following conditions are met: - -* Both symbols have identical names at the object level, - -* Both symbols have DWARF debug information attached to them, - -* According to this debug information, both symbols originate from the same - compilation unit, denoted by the full path of the corresponding source file. - -By this construction, a symbol missing debug information is never considered -overlapping with any other symbol. Whatever coverage is achieved on such a -symbol never gets combined with anything else and the only kind of report where -the symbol coverage is exposed is the :cmd-option:`=asm` assembly output for -object level criteria. - -Moreover, for object level coverage criteria, |gcvcov| will issue a -consolidation error when two symbols are found to overlap but have -structurally different machine code, which happens for example when the same -unit is compiled with different different optimization levels for -different executables. - diff --git a/doc/gnatcov/run_prereq.rst b/doc/gnatcov/run_prereq.rst index f82797f22..0ebcf524c 100644 --- a/doc/gnatcov/run_prereq.rst +++ b/doc/gnatcov/run_prereq.rst @@ -3,13 +3,24 @@ Compilation prerequisites ========================= +General rules +------------- + If the traces are intended to be used for :ref:`source coverage analysis `, regardless of the actual criteria to be assessed afterwards, sources must be compiled with :cmd-option:`-g -fpreserve-control-flow -fdump-scos` to control optimizations and allow mapping trace info to source constructs. :cmd-option:`-gno-strict-dwarf` is required in addition for VxWorks targets, together with :cmd-option:`-mlongcall` for PowerPC configurations. -Optimization is supported up to :cmd-option:`-O1`, with inlining allowed. + +Optimization is supported up to :cmd-option:`-O1`, with inlining +allowed. However, if the binary version of the code under test during +the coverage campaign is intended to be used directly in operational +conditions, care is needed to prevent inlining of the code under test +within the testing code at compilation time in unit-testing campaigns. +With GCC based toolchains such as GNAT Pro, this can be achieved by +adding :cmd-option:`-fno-inline` to the compilation options of the +testing code. The :cmd-option:`-fprofile-arcs` or :cmd-option:`--coverage` compilation switches, intended for analysis with the gcov tool, are incompatible with the @@ -26,3 +37,33 @@ process might turn simpler if the same compilation options are used for both kinds of analysis. There is no incompatibility with object coverage analysis incurred by compiling the code compiled with options required for source coverage. + +Consolidation related rules +--------------------------- + +For object or source level criteria, |gcv| computes the coverage achieved for +the full set of routines or source units declared to be of interest amongst +those exposed by the union of the exercised executables, as designated by the +set of consolidated traces; + +For the purpose of computing combined coverage achievements, two symbols are +considered overlapping when all the following conditions are met: + +* Both symbols have identical names at the object level, + +* Both symbols have DWARF debug information attached to them, + +* According to this debug information, both symbols originate from the same + compilation unit, denoted by the full path of the corresponding source file. + +By this construction, a symbol missing debug information is never considered +overlapping with any other symbol. Whatever coverage is achieved on such a +symbol never gets combined with anything else and the only kind of report where +the symbol coverage is exposed is the :cmd-option:`=asm` assembly output for +object level criteria. + +Moreover, for object level coverage criteria, |gcvcov| will issue a +consolidation error when two symbols are found to overlap but have +structurally different machine code, which happens for example when the same +unit is compiled with different different optimization levels for +different executables. From 7fc566e125d6bdfb33418e6758678e5bb18104ff Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 4 Jan 2023 03:49:31 -0800 Subject: [PATCH 0110/1483] Remove a few src/bin traces distinctions Simply refer to "traces" instead of "source or binary traces" in a few places, where the explicit mention of the two isn't of importance and is potentially confusing in a context where binary traces have not been introduced. Simplify the section describing handling of source relocation, removing non fundamental detail on how default locations are picked depending on the trace kind. Part of V805-004 --- doc/gnatcov/cons_checkpoints.rst | 8 ++++--- doc/gnatcov/consolidation.rst | 2 +- doc/gnatcov/cov_source.rst | 37 +++++++++++++++----------------- 3 files changed, 23 insertions(+), 24 deletions(-) diff --git a/doc/gnatcov/cons_checkpoints.rst b/doc/gnatcov/cons_checkpoints.rst index 77486529c..ef356d479 100644 --- a/doc/gnatcov/cons_checkpoints.rst +++ b/doc/gnatcov/cons_checkpoints.rst @@ -91,9 +91,11 @@ discuss compatibility issues regarding consolidation. Efficient storage of test results ================================= -Binary trace files can be large and their processing requires access to the -executable file that was used to produce the trace. Preserving collections of -traces and executables to allow consolidation can be problematic, space-wise. +Trace files can be large and often need to be kept together with the +executable files that were used to produce the traces, for traceability +reasons for example, or for specific processing operations in some +circumstances. Preserving collections of traces and executables to allow +consolidation can be problematic, space-wise. In some situations (depending on the overall size of programs, number of units of interest, assessed coverage criteria, number and structure of decisions, diff --git a/doc/gnatcov/consolidation.rst b/doc/gnatcov/consolidation.rst index ce91d93b0..656ba0c76 100644 --- a/doc/gnatcov/consolidation.rst +++ b/doc/gnatcov/consolidation.rst @@ -22,7 +22,7 @@ tested separately (e.g. the different subprograms of a library unit or different scenarios of a given subprogram). The production of consolidated coverage reports can proceed either directly -from a set of source or binary traces produced by the executions, or from a +from a set of traces produced by the executions, or from a set of pre-computed partial results latched in what we refer to as :term:`coverage checkpoints `, which offer a lot of advanced capabilities. The following sections illustrate various combinations diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index 6911d6f0a..a1beb025b 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -11,9 +11,10 @@ language entities such as high level *statements* or *decisions* (DO178 parlance for boolean expressions), which translate as :term:`Source Coverage Obligations `, or SCOs, in |gcp| terms. -Once you have produced source or binary traces, actual analysis is then -performed with |gcvcov| to generate coverage reports. *Source* coverage is -queried by passing a specific :cmd-option:`--level` argument to |gcvcov|. +Once you have produced coverage traces, actual analysis is performed +with |gcvcov| to generate coverage reports. *Source* coverage is +queried by passing a specific :cmd-option:`--level` argument to +|gcvcov|. The general structure of this command line is always like:: @@ -390,9 +391,9 @@ items: * Coverage level requested to be analyzed -* Details on the input trace files: path to binary program exercised (as - recorded in the trace header), production time stamp and tag string - (:cmd-option:`--tag` command line argument value). +* Details on the input trace files, such as the path to the binary + program exercised (as recorded in the trace header) or the trace + production time stamp. Here is a example excerpt:: @@ -1487,20 +1488,16 @@ Handling source relocation for annotated sources output formats =============================================================== For all annotated sources output formats -(:cmd-option:`--annotate=xcov[+]|html[+]|dhtml)`, |gcv| needs access to the -sources of the :term:`units of interest ` to generate the -output. By default, the sources will be searched in the location where they -were compiled, for binary traces, or where they were instrumented for source -traces. This is generally going to be the case if the whole coverage analysis -process is done on the same machine, but in some cases it may be preferable to -generate the coverage report on a different machine than the one where the -coverage run was done, or the sources may have been moved. - -For instance, a project with a large number of unit tests may be run on -multiple machines in parallel to speed up the test runs, and then a single -report will be generated from all the traces/checkpoints. In such case, |gcv| -will not be able to automatically find the source files. |gcv| offers two -options to help in those situations: +(:cmd-option:`--annotate=xcov[+]|html[+]|dhtml)`, |gcv| needs access +to the sources of the :term:`units of interest ` to +generate the output. The tool searches for sources in some default +locations which are usually correct when the whole coverage analysis +process is done on the same machine. + +When coverage reports are produced on a different machine than the one +where the coverage run was done, or when sources are moved in the +interim, |gcv| will likely not be able to automatically find the +source files. The tool offers two options to help in those situations: * The option :cmd-option:`--source-rebase=\=\` From 03fe495feafa58fca3d78f76eb80ff5e13ccacbb Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 4 Jan 2023 06:33:12 -0800 Subject: [PATCH 0111/1483] Move bin-trace section of "using from gps" out to the bin-trace part ... now into the Using Bin Traces appendix. Part of V805-004 --- doc/gnatcov/bin_gps.rst | 28 ++++++++++++++++++++++++++++ doc/gnatcov/gnatcov_bin_part.rst | 1 + doc/gnatcov/gps.rst | 29 ++--------------------------- 3 files changed, 31 insertions(+), 27 deletions(-) create mode 100644 doc/gnatcov/bin_gps.rst diff --git a/doc/gnatcov/bin_gps.rst b/doc/gnatcov/bin_gps.rst new file mode 100644 index 000000000..af2a579e0 --- /dev/null +++ b/doc/gnatcov/bin_gps.rst @@ -0,0 +1,28 @@ +###################### +Using |gcp| from |gps| +###################### + +Starting from GNATcoverage version 22.0, binary traces (using gnatcov run) are +no longer supported in native profiles. This mode is still supported for cross +configurations, and the IDE integrated use in such cases is similar to the use +for source traces: + +Go to the :menuselection:`Analyze --> Coverage --> GNATcoverage Binary Traces` +menu to perform each step individually, or use the ``Run All Actions`` item to +do everything at once. + +In configurations where binary traces are not supported, the menu entry just +wouldn't show up. + +You can also replace the toolbar button (dedicated to the instrumentation-based +scheme) with an alike button, but for binary traces. Go to GNATstudio +Preferences in :menuselection:`Edit --> Preferences`. + +Then, go to the ``Build Targets`` section, and find the ``Run GNATcoverage`` +workflow: add it to the toolbar as shown below. + +.. image:: gps_screenshots/7-binary-traces.png + +Remove the ``Run GNATcoverage with instrumentation`` entry from the toolbar in +the same fashion. + diff --git a/doc/gnatcov/gnatcov_bin_part.rst b/doc/gnatcov/gnatcov_bin_part.rst index c40832649..b3e27ecce 100644 --- a/doc/gnatcov/gnatcov_bin_part.rst +++ b/doc/gnatcov/gnatcov_bin_part.rst @@ -9,4 +9,5 @@ GNATcoverage Appendix - Using Binary Traces bin_traces cov_object cov_metrics + bin_gps bin_convert diff --git a/doc/gnatcov/gps.rst b/doc/gnatcov/gps.rst index a949403aa..d96b5dcd6 100644 --- a/doc/gnatcov/gps.rst +++ b/doc/gnatcov/gps.rst @@ -5,8 +5,8 @@ Using |gcp| from |gps| GNATcoverage is integrated in |gps| so that it is possible to analyze code coverage without leaving your favorite editor. -Basic usage -=========== +Basic scenario +============== As a first step, indicate which coverage criterion GNATcoverage should use through the :ref:`project file`. If no coverage level is set @@ -58,31 +58,6 @@ file with annotations that represent the coverage state: Note that the Locations view reports all non-covered lines. It makes navigation easy as you only have to click on a diagnostic to go to the corresponding line. -Binary traces usage -=================== - -Starting from GNATcoverage version 22.0, binary traces (using gnatcov run) are -no longer supported in native profiles. This mode is still supported for cross -configurations so the same steps performed above for source traces can be done -for binary traces IF you are in a supported configuration (otherwise, the menu -items won't show up). - -Go to the menu -:menuselection:`Analyze --> Coverage --> GNATcoverage Binary Traces`. -to perform each step individually, or use the ``Run All Actions`` item. - -You can also replace the toolbar button (dedicated to the instrumentation-based -scheme) with an alike button, but for binary traces. Go to GNATstudio -Preferences in :menuselection:`Edit --> Preferences`. - -Then, go to the ``Build Targets`` section, and find the ``Run GNATcoverage`` -workflow: add it to the toolbar as shown below. - -.. image:: gps_screenshots/7-binary-traces.png - -Remove from the toolbar the ``Run GNATcoverage with instrumentation`` in the -same fashion. - GNATtest scenario ================= From bafcdee3005e294d5deabb76cd0d840e50e9e39b Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 11 Jan 2023 12:54:58 +0000 Subject: [PATCH 0112/1483] Clarify Makefile/gnatcov.gpr split of responsibilities The gnatcov.gpr project file is used to build a variety of executables, with some parameters controlling the possible stubbing of some units. The control of what sources get stubbed was split between Makefiles and the project file, with Makefiles adjusting settings based on knowledge of what the project file does e.g. for 32 vs 64bit. As we are going to introduce support for 32 vs 64bit variants of the trace32 adapter, which also rely on gnatcov.gpr, some implicit assumptions in the project file won't hold any more and getting the current split to work for all combinations induces undue conceptual complexity. This change simplifies the overall organization by removing some attempts at figuring default parameter values from the project file, pushing the responsibility to do so entirely in Makefiles instead. To let Makefiles associate meaningful parameter values for the various uses of the project file, the change also removes the computation of a Main attribute from the project itself. Main units are simply stated from build commands when they are needed, together the parameters that make sense for what is being built. Essentially, this defers the responsibilty to state what is needed at the points where the build commands are issued, which is where we know best what we intend to build and where what is needed is simple to state locally. Part of W105-035 --- tools/gnatcov/Makefile | 41 ++++++++++++++++++----------- tools/gnatcov/gnatcov.gpr | 54 +++++++++++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 28 deletions(-) diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index 1282b82fb..a3dca3a95 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -186,6 +186,22 @@ nexus_ADAPTER_INSTALL_VARS=PREFIX=$(PREFIX) default: bin all: bin adapters +# Here we build gnatcov32, gnatcov64 and the "gnatcov" driver that spawns +# one or the other of the first two depending on the operation to perform +# and the kind of binary item at hand, if any. Source instrumentation is +# unconditionally directed to gnatcov64, so this is the only program where +# "instrument" support is needed. + +BIN_COMMON_BUILD_ARGS=\ + -Pgnatcov.gpr -p -j$(PARALLEL_BUILD) \ + -XBUILD_MODE=$(BUILD_MODE) \ + -XBINUTILS_SRC_DIR="$(BINUTILS_SRC_DIR)" \ + -XBINUTILS_BUILD_DIR="$(BINUTILS_BUILD_DIR)" \ + $(EXTRA_ADAFLAGS) \ + -largs $(LD_FLAGS) \ + -cargs:c++ $(CXXFLAGS) \ + -gargs + bin: # Unlike BINUTILS_BUILD_DIR for which we have a default fallback, # BINUTILS_SRC_DIR must be defined explicitely. @@ -196,21 +212,16 @@ bin: exit 1; \ fi -# Use "set -e" not to start the second build if the first one failed. Also -# start with the 64-bit one so that errors in the "gnatcov" main closure show -# up as soon as possible. - set -e && for bits in 64 32; \ - do \ - $(GPRBUILD) -Pgnatcov -p -j$(PARALLEL_BUILD) \ - -XARCH=$$bits \ - -XBUILD_MODE=$(BUILD_MODE) \ - -XBINUTILS_SRC_DIR="$(BINUTILS_SRC_DIR)" \ - -XBINUTILS_BUILD_DIR="$(BINUTILS_BUILD_DIR)" \ - -XC_SUPPORT=$(C_SUPPORT) \ - $(EXTRA_ADAFLAGS) \ - -largs $(LD_FLAGS) \ - -cargs:c++ $(CXXFLAGS); \ - done +# Start with the 64-bit gnatcov, which has the largest closure + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) \ + gnatcov_bits_specific.adb \ + -XARCH=64 -XINSTRUMENT_SUPPORT=True -XC_SUPPORT=$(C_SUPPORT) + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) \ + gnatcov_bits_specific.adb \ + -XARCH=32 -XINSTRUMENT_SUPPORT=False + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) \ + gnatcov.adb \ + -XINSTRUMENT_SUPPORT=False ADAPTER_TARGETS=$(foreach a, $(ADAPTERS_LIST), adapter-$(a)) .PHONY: $(ADAPTERS_TARGETS) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 4dba03a7a..d449f428f 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -4,35 +4,64 @@ with "rts/gnatcov_rts"; project Gnatcov is - type Bits_Type is ("32", "64"); - Bits : Bits_Type := external("ARCH", "32"); + -- This project file participates in the build of a variety of programs + -- that use all or part-of the sources in the project's subdirectory. Such + -- progrms include the "gnatcov" driver, the "gnatcov32/64" tools or the + -- trace adapters. + + -- We provide scenario variables to control some aspects of what the + -- sources include, such as whether the tool is intended to process 32 or + -- 64 binaries or whether it needs to include a fully functional source + -- instrumenter. The control of what parameter makes sense for each actual + -- program is not decided by this project file, and when this project file + -- is used as a root project to build gnatcov* executables, build commands + -- are expected to state the Mains on the on the command line along + -- with the associated parameters. + + -- The size of addresses we expect the tool we build will handle. For + -- gnatcov* programs, this also controls the subdir where the executable + -- is placed. Default to "64" as we build 64bit binaries only. Only those + -- that explicitly request to handle 32bit addresses will end up in the + -- 32bit specific object dir. - Mains := ("gnatcov_bits_specific.adb"); - case Bits is - when "32" => null; - when "64" => Mains := Mains & ("gnatcov.adb"); - end case; + type Bits_Type is ("32", "64"); + Bits : Bits_Type := external("ARCH", "64"); Binutils_Src_Dir := external ("BINUTILS_SRC_DIR"); Binutils_Build_Dir := external ("BINUTILS_BUILD_DIR", Binutils_Src_Dir); -- Build mode. Default to "dev" to make it shorter for developers. -- The other modes are for nightly scripts and are better made explicit - --- anyway: + -- anyway: + type Build_Mode_Type is ("dev", "prod", "boot"); Build_Mode : Build_Mode_Type := external("BUILD_MODE", "dev"); + -- Whether the tool we build needs to include source instrumentation + -- support at all, then for C more specifically: + type Boolean is ("False", "True"); - C_Support : Boolean := external("C_SUPPORT", "True"); + Instrument_Support : Boolean := external("INSTRUMENT_SUPPORT"); + C_Support : Boolean := external("C_SUPPORT", Instrument_Support); package Naming is for Specification ("Arch") use "arch__" & Bits & ".ads"; for Specification ("Qemu_Traces_Entries") use"qemu_traces_entries__" & Bits & ".ads"; - case Bits is - when "32" => for Body ("Instrument") use "instrument__stub.adb"; - when "64" => for Body ("Instrument") use "instrument.adb"; + + -- Tools that don't need instrumentation support might nevertheless + -- rely on sources that drag dependencies on the "instrument" source + -- unit, even though the instrumentation feature is never actually + -- used. Provide a stub body for such tools, which significantly + -- reduces the size of executables: + + case Instrument_Support is + when "False" => + for Body ("Instrument") use "instrument__stub.adb"; + when "True" => + null; end case; + case C_Support is when "False" => for Specification ("Instrument.C") use "instrument-c__stub.ads"; @@ -134,6 +163,5 @@ project Gnatcov is for Object_Dir use "obj" & Bits & "/" & Build_Mode; for Languages use ("Ada", "C", "C++"); - for Main use Mains; end Gnatcov; From fc300804140b00ad85b124737544985382146b14 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 11 Jan 2023 13:26:51 +0000 Subject: [PATCH 0113/1483] Trace32: Also build the adapter for 64 bit tragets The Trace32 adapter was linked against the 32 version of gnatcov, and could thus only process traces from a 32bit target. This change adds a second executable for the adapter, linked against the 64 bit version of gnatcov to allow processing of traces from 64 bit targets. This also changes the adapter invocation to ensure the correct adapter is used depending on the target. Part of W105-035 --- tools/gnatcov/Makefile | 4 +-- tools/gnatcov/arch__32.ads | 2 ++ tools/gnatcov/arch__64.ads | 2 ++ tools/gnatcov/convert.adb | 7 +++- tools/gnatcov/trace_adapters/trace32/Makefile | 33 ++++++++++++------- .../trace_adapters/trace32/trace32.gpr | 9 ++++- 6 files changed, 42 insertions(+), 15 deletions(-) diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index a3dca3a95..d8b0cde2a 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -138,9 +138,9 @@ endif ifeq ($(HOST_OS), linux) ifeq ($(BITS_ARCH), 32) -DEFAULT_ADAPTERS = valgrind trace32 -else DEFAULT_ADAPTERS = valgrind +else +DEFAULT_ADAPTERS = valgrind trace32 endif endif diff --git a/tools/gnatcov/arch__32.ads b/tools/gnatcov/arch__32.ads index d603b9c2a..263d741ac 100644 --- a/tools/gnatcov/arch__32.ads +++ b/tools/gnatcov/arch__32.ads @@ -57,4 +57,6 @@ package Arch is renames Elf32_R_Type; function Elf_R_Info (S, T : Elf_Word) return Elf_Word renames Elf32_R_Info; + + Current_Bits : constant String := "32"; end Arch; diff --git a/tools/gnatcov/arch__64.ads b/tools/gnatcov/arch__64.ads index 40074d5d6..472f7dbdc 100644 --- a/tools/gnatcov/arch__64.ads +++ b/tools/gnatcov/arch__64.ads @@ -57,4 +57,6 @@ package Arch is renames Elf64_R_Type; function Elf_R_Info (S, T : Elf_Word) return Elf_Xword renames Elf64_R_Info; + + Current_Bits : constant String := "64"; end Arch; diff --git a/tools/gnatcov/convert.adb b/tools/gnatcov/convert.adb index 334fca63c..fea3d7003 100644 --- a/tools/gnatcov/convert.adb +++ b/tools/gnatcov/convert.adb @@ -23,6 +23,7 @@ with Ada.Unchecked_Conversion; with Qemu_Traces; with Interfaces; +with Arch; with Traces_Files; use Traces_Files; with GNAT.Strings; @@ -166,7 +167,11 @@ package body Convert is 7 => Trigger_Stop_ID ); when Trace32_Branchflow => - Prg := Locate_Exec_On_Path ("../libexec/gnatcoverage/trace32_drv"); + -- Despite being named Trace32, the adapters also support 64 bit + -- targets, so invoke the correct trace adapter. + + Prg := Locate_Exec_On_Path ("../libexec/gnatcoverage/trace32_drv_" + & Arch.Current_Bits); Opts := new String_List'(1 => new String'("stm32f7"), 2 => Exe_Name, 3 => Trace_Arg, diff --git a/tools/gnatcov/trace_adapters/trace32/Makefile b/tools/gnatcov/trace_adapters/trace32/Makefile index df9f669b2..74ed3d542 100644 --- a/tools/gnatcov/trace_adapters/trace32/Makefile +++ b/tools/gnatcov/trace_adapters/trace32/Makefile @@ -6,12 +6,12 @@ include ../../host.mk .PHONY: force -ARCH=32 - # Files for libexec/gnatcoverage include binary executables # (which need to be built first), and a python script. -EXENAMES=trace32_drv +# Despite being named Trace32, the probes support both 32 and 64 bit targets, +# so we need to build a trace adapter both for 32 bit and 64 bit targets. +EXENAMES=trace32_drv_32 trace32_drv_64 # Directory name in the install tree DIRNAME=gnatcoverage @@ -21,15 +21,25 @@ DOCFORMATS=pdf html # By default, assume that the binutils dependency was built in the source tree. BINUTILS_BUILD_DIR?=$(BINUTILS_SRC_DIR) -all: $(EXENAMES) +all: bin + +# Here we build trace32_drv_32 and trace32_drv_64 executables. State +# we don't need source instrumentation support at all in these programs +# to minimize the executable sizes. -$(EXENAMES): force - $(GPRBUILD) -Ptrace32 -XARCH=$(ARCH) $(EXTRA_ADAFLAGS) $@ \ - -XBINUTILS_SRC_DIR="$(BINUTILS_SRC_DIR)" \ - -XBINUTILS_BUILD_DIR="$(BINUTILS_BUILD_DIR)" \ - -largs $(LD_FLAGS) \ - -cargs:c++ $(CXXFLAGS) \ +BIN_COMMON_BUILD_ARGS=\ + -Ptrace32.gpr \ + -XBINUTILS_SRC_DIR="$(BINUTILS_SRC_DIR)" \ + -XBINUTILS_BUILD_DIR="$(BINUTILS_BUILD_DIR)" \ + -XINSTRUMENT_SUPPORT=False \ + -largs $(LD_FLAGS) \ + -cargs:c++ $(CXXFLAGS) \ + $(EXTRA_ADAFLAGS) \ + -gargs +bin: force + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XARCH=64 + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XARCH=32 ################### # General cleanup # @@ -38,7 +48,8 @@ $(EXENAMES): force .PHONY: clean clean: - $(GPRCLEAN) -Ptrace32 + $(GPRCLEAN) -Ptrace32.gpr -XARCH=64 + $(GPRCLEAN) -Ptrace32.gpr -XARCH=32 ################ # Installation # diff --git a/tools/gnatcov/trace_adapters/trace32/trace32.gpr b/tools/gnatcov/trace_adapters/trace32/trace32.gpr index c2d45eb95..ad2bc8ea7 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace32.gpr +++ b/tools/gnatcov/trace_adapters/trace32/trace32.gpr @@ -2,8 +2,11 @@ with "../../gnatcov"; project Trace32 is + type Bits_Type is ("32", "64"); + Bits : Bits_Type := external("ARCH", "32"); + for Main use ("trace32_drv.adb"); - for Object_Dir use "obj"; + for Object_Dir use "obj" & Bits; for Exec_Dir Use "."; for Create_Missing_Dirs use "True"; @@ -15,4 +18,8 @@ project Trace32 is for Required_Switches use Gnatcov.Linker'Required_Switches; end Linker; + package Builder is + for Executable ("trace32_drv.adb") use "trace32_drv_" & Bits; + end Builder; + end Trace32; From de8f26f51cc1664df4a7318aa6fb8b744cff7a3f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 12 Jan 2023 18:18:10 +0100 Subject: [PATCH 0114/1483] Remove testsuite/tests from .gitignore This is now a directory hosting tests. Ref: eng/cov/gnatcoverage#6 --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 0c701ac4b..c6aed1b83 100644 --- a/.gitignore +++ b/.gitignore @@ -21,7 +21,6 @@ lib /testsuite/out /testsuite/suite.cgpr /testsuite/support -/testsuite/tests /testsuite/tmp gnatcov-loc.xml gnatinspect.db From d08a319d5b46844800b0fe2fda745257f8415b66 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Thu, 19 Jan 2023 10:12:06 +0000 Subject: [PATCH 0115/1483] Remove Ada/stmt/.../Subunits/Packages/src/ops-lsub.adb Separate package body referenced *nowhere* else (no comment, no corresponding spec, no coverage expectation). Spotted in the course of V923-031 --- .../1_Core/10_Structure/Subunits/Packages/src/ops-lsub.adb | 7 ------- 1 file changed, 7 deletions(-) delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/Packages/src/ops-lsub.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/Packages/src/ops-lsub.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/Packages/src/ops-lsub.adb deleted file mode 100644 index 49097ea23..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/Packages/src/ops-lsub.adb +++ /dev/null @@ -1,7 +0,0 @@ -separate (Ops) -package body Lsub is - procedure Op (Opd: in out Opdata) is - begin - Touch (Opd); -- # lsub - end; -end; From db1f1b217277c70d7b3a1838f51e3a128bdd45b6 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 20 Dec 2022 10:23:25 +0100 Subject: [PATCH 0116/1483] Fix builds after libadalang API breaking change TN: VB07-098 --- tools/gnatcov/instrument-ada_unit.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 17bbaf62e..fd257b94f 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -2849,7 +2849,7 @@ package body Instrument.Ada_Unit is To_Node := Stmt.F_Entry_Index_Expr.As_Ada_Node; else - To_Node := Stmt.F_Name.As_Ada_Node; + To_Node := Stmt.F_Body_Decl.F_Name.As_Ada_Node; end if; end; From 6d309b881cffa4f2f3c99b2b21af959e48a37e68 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 6 Jan 2023 14:59:40 +0000 Subject: [PATCH 0117/1483] Update after recent Langkit_Support.Text API changes This package now provides its own version of To_Lower for Wide_Wide_String, which conflicts with the one from Ada.Wide_Wide_Characters.Handling (it is an optimized version of it for strings that are mostly ASCII). Use it instead, and fix the visibility issue. TN: VC16-029 --- tools/gnatcov/instrument-ada_unit.adb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index fd257b94f..c8f983f5a 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -16,12 +16,11 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Characters.Conversions; use Ada.Characters.Conversions; +with Ada.Characters.Conversions; use Ada.Characters.Conversions; with Ada.Characters.Handling; with Ada.Exceptions; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Wide_Wide_Fixed; -with Ada.Wide_Wide_Characters.Handling; use Ada.Wide_Wide_Characters.Handling; with Langkit_Support; with Langkit_Support.Slocs; use Langkit_Support.Slocs; From ea24e3f7c7df516691608b70870f77cd561b5e26 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 19 Dec 2022 17:47:13 +0100 Subject: [PATCH 0118/1483] Handle C compilation units starting with a symbol / upper-case letter The name of the slug for e.g. Pkg.c belonging to project prj was prj_z_z__4bkg_2ec, resulting in a coverage buffer symbol name with two underlines. This is not accepted by the Ada compiler, so it resulted in a compile error as far as projects mixing Ada / C code are concerned. To fix this, we change the slug computation mechanism to avoid generating a slug with consecutive underlines. TN: VB03-009 --- tools/gnatcov/instrument-base_types.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-base_types.adb b/tools/gnatcov/instrument-base_types.adb index bf513eae8..2b383d7b2 100644 --- a/tools/gnatcov/instrument-base_types.adb +++ b/tools/gnatcov/instrument-base_types.adb @@ -149,7 +149,7 @@ package body Instrument.Base_Types is -- Add an unambiguous separator between the project name and -- the rest of the slug. - Append (Result, "_z_z_"); + Append (Result, "_z_z"); -- File names can contain characters that cannot appear in -- identifiers. Furthermore, unlike for the identifier to From d314d0f8c492c4fd8cbddadef8ad3dfe3c08641d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 17 Oct 2022 17:14:23 +0200 Subject: [PATCH 0119/1483] Instrument.C: rework macro data structure We use to opt for a compact representation of macro definitions, e.g. saving macro definitions as "A(x)=int x;" rather than splitting the macro name, arguments and value. Rework the macro data structure to easily know the name of the macro being defined. There is no behavioral change: this is prepartory work to handle source coverage obligations coming from built-in macros. TN: V914-024 --- tools/gnatcov/instrument-c.adb | 181 +++++++++++++++++++++++++-------- tools/gnatcov/instrument-c.ads | 43 +++++--- 2 files changed, 168 insertions(+), 56 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 0e14310c5..ecbfa0556 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -92,31 +92,43 @@ package body Instrument.C is -- Preprocessing utilities -- ------------------------------ + Macro_Cmdline_Regexp : constant Pattern_Matcher := Compile ( + "([a-zA-Z_]\w*)" + -- The name of the macro + + & "(\(.*\))?" + -- The optional list of macro arguments + + & "([^ =]+)?" + -- Then, there can be any character before the assignment: they will be + -- part of the macro value (e.g. A(b)b will yield #define A b 1) + + & "(?:=(.*))?" + -- The macro value itself + ); + Macro_Def_Regexp : constant Pattern_Matcher := Compile ( "#define" & "(?: |\t)+" -- "#define", then a non-empty blank - & "([a-zA-Z0-9_][^ \t]*" - -- The name of the macro, followed by.... + & "([a-zA-Z_]\w*)" + -- The name of the macro - & "(?:\(.*\))?" + & "(\(.*\))?" -- The optional list of macro arguments - & ")" - -- End of "extended" macro name (actual name + arguments) - & "(.*)" -- The macro value itself ); -- Regular expression to analyze definitions for builtin macros (see -- Builtin_Macros) - type Macro_Vector_Access is access Macro_Vectors.Vector; - type Macro_Vector_Cst_Access is access constant Macro_Vectors.Vector; + type Macro_Set_Access is access Macro_Set; + type Macro_Set_Cst_Access is access constant Macro_Set; package Compiler_Macros_Maps is new Ada.Containers.Hashed_Maps (Key_Type => Unbounded_String, - Element_Type => Macro_Vector_Access, + Element_Type => Macro_Set_Access, Equivalent_Keys => "=", Hash => Ada.Strings.Unbounded.Hash); Compiler_Macros : Compiler_Macros_Maps.Map; @@ -127,8 +139,22 @@ package body Instrument.C is -- The three following functions are not used, but could be in the future, -- when we will refine what is done with macros. + procedure Parse_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean); + -- Parse a macro definition. If the parsing failed, set Success to False. + -- Otherwise, set Parsed_Def to the parsed definition and set Success to + -- True. + + procedure Parse_Cmdline_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean); + -- Same as above, but with a command-line macro definition + function Builtin_Macros - (Lang, Compiler, Std, Output_Dir : String) return Macro_Vector_Cst_Access; + (Lang, Compiler, Std, Output_Dir : String) return Macro_Set_Cst_Access; -- Return the list of built-in macros for the given compiler, standard and -- language. Output_Dir is used to store a temporary file. -- @@ -2517,12 +2543,77 @@ package body Instrument.C is UIC.MCDC_State_Declaration_Node := Saved_MCDC_State_Declaration_Node; end Traverse_Declarations; + ---------------------------- + -- Parse_Macro_Definition -- + ---------------------------- + + procedure Parse_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean) + is + Matches : Match_Array (0 .. 3); + begin + Match (Macro_Def_Regexp, Str, Matches); + if Matches (0) = No_Match then + Success := False; + else + Success := True; + Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); + if Matches (2) /= No_Match then + Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); + end if; + Parsed_Def.Value := +Str (Matches (3).First .. Matches (3).Last); + end if; + end Parse_Macro_Definition; + + ------------------------------------ + -- Parse_Cmdline_Macro_Definition -- + ------------------------------------ + + procedure Parse_Cmdline_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean) + is + Matches : Match_Array (0 .. 4); + begin + Match (Macro_Cmdline_Regexp, Str, Matches); + if Matches (0) = No_Match then + Success := False; + else + Success := True; + Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); + if Matches (2) /= No_Match then + Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); + end if; + + -- Command line macros can have part of their value before the + -- assignment, e.g. "-DA(b)b" is equivalent to "#define A(b) b 1". + + if Matches (3) /= No_Match then + Append + (Parsed_Def.Value, + Str (Matches (3).First .. Matches (3).Last) & " "); + end if; + + -- If no value is given, then it is implicitly 1 + + if Matches (4) /= No_Match then + Append + (Parsed_Def.Value, Str (Matches (4).First .. Matches (4).Last)); + else + Append (Parsed_Def.Value, " 1"); + end if; + end if; + end Parse_Cmdline_Macro_Definition; + -------------------- -- Builtin_Macros -- -------------------- function Builtin_Macros - (Lang, Compiler, Std, Output_Dir : String) return Macro_Vector_Cst_Access + (Lang, Compiler, Std, Output_Dir : String) return Macro_Set_Cst_Access is use Ada.Characters.Handling; use Compiler_Macros_Maps; @@ -2531,7 +2622,7 @@ package body Instrument.C is Key : constant Unbounded_String := +Compiler & " -x " & L & " " & Std; Cur : constant Cursor := Compiler_Macros.Find (Key); - Result : Macro_Vector_Access; + Result : Macro_Set_Access; begin -- If we already computed builtin macros for Compiler, return the cached -- result. Compute it now otherwise. @@ -2540,7 +2631,7 @@ package body Instrument.C is Result := Element (Cur); else - Result := new Macro_Vectors.Vector; + Result := new Macro_Set; declare Args : String_Vectors.Vector; Basename : constant String := @@ -2574,24 +2665,21 @@ package body Instrument.C is Open (File, In_File, Filename); while not End_Of_File (File) loop declare - Line : constant String := Get_Line (File); - Matches : Match_Array (0 .. 2); - M : Macro_Definition; + Line : constant String := Get_Line (File); + Macro_Def : Macro_Definition (Define => True); + Success : Boolean; begin - Match (Macro_Def_Regexp, Line, Matches); - if Matches (0) = No_Match then + Parse_Macro_Definition + (Line, + Macro_Def, + Success); + if Success then + Result.Include (Macro_Def); + else Warn ("Cannot parse a built-in macro definition for " - & Compiler & ", ignoring it:" - & ASCII.LF & " " & Line); - else - M.Define := True; - Append - (M.Value, Line (Matches (1).First .. Matches (1).Last)); - Append (M.Value, "="); - Append - (M.Value, Line (Matches (2).First .. Matches (2).Last)); - Result.Append (M); + & Compiler & ", ignoring it:" & ASCII.LF & " " + & Line); end if; end; end loop; @@ -2604,7 +2692,7 @@ package body Instrument.C is end; end if; - return Macro_Vector_Cst_Access (Result); + return Macro_Set_Cst_Access (Result); end Builtin_Macros; ------------------------ @@ -4359,24 +4447,21 @@ package body Instrument.C is Options : Analysis_Options; Pass_Builtins : Boolean := True) is - procedure Add_Macro_Switches (Macros : Macro_Vectors.Vector); + procedure Add_Macro_Switches (Macros : Macro_Set); -- Add the given macro switches to Args ------------------------ -- Add_Macro_Switches -- ------------------------ - procedure Add_Macro_Switches (Macros : Macro_Vectors.Vector) is + procedure Add_Macro_Switches (Macros : Macro_Set) is begin for M of Macros loop - declare - Prefix : constant Unbounded_String := - +(if M.Define - then "-D" - else "-U"); - begin - Args.Append (Prefix & M.Value); - end; + if M.Define then + Args.Append ("-D" & M.Name & M.Args & "=" & M.Value); + else + Args.Append ("-U" & M.Name); + end if; end loop; end Add_Macro_Switches; @@ -4551,10 +4636,24 @@ package body Instrument.C is Self.PP_Search_Path.Append (Value); elsif Read_With_Argument (A, 'D', Value) then - Self.PP_Macros.Append ((Define => True, Value => Value)); + declare + Macro_Def : Macro_Definition (Define => True); + Success : Boolean; + begin + Parse_Cmdline_Macro_Definition + (Str => +Value, + Parsed_Def => Macro_Def, + Success => Success); + if Success then + Self.PP_Macros.Include (Macro_Def); + else + Warn ("Failed to parse command-line macro definition: " + & (+Value)); + end if; + end; elsif Read_With_Argument (A, 'U', Value) then - Self.PP_Macros.Append ((Define => False, Value => Value)); + Self.PP_Macros.Include ((Define => False, Name => Value)); elsif Has_Prefix (A, "-std=") then Self.Std := +A; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 136b8d38b..758dae99f 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -20,6 +20,7 @@ with Ada.Containers.Hashed_Maps; with Ada.Containers.Ordered_Maps; +with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; with Ada.Finalization; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; @@ -239,31 +240,43 @@ package Instrument.C is (Key_Type => Nat, Element_Type => PP_Info); - type Macro_Definition is record - Define : Boolean; - -- Whether this defines a macro or undefines it + type Macro_Definition (Define : Boolean := True) is record + Name : Unbounded_String; + -- Name of the macro - Value : Unbounded_String; - -- If this undefines a macro, this just contains the name of that macro. - -- - -- If this defines a macro, "-D" option value for the definition of this - -- macro. For instance "A(x, y)=B" for "#define A(x, y) B". + case Define is + when True => + Args : Unbounded_String; + -- String representation of the macro arguments, e.g. (x, y) + + Value : Unbounded_String; + -- Value for the macro definition + + when False => + null; + end case; end record; -- Whether a macro should be defined, its name, and when it must be - -- defined, its value. + -- defined, its optional arguments and value. + + function "<" (L, R : Macro_Definition) return Boolean is (L.Name < R.Name); + -- As we store Macro_Definition in sets, we do not want two conflicting + -- definitions of the same macro to coexist. Thus, we compare only the + -- name, meaning that when we insert a new definition, it will replace + -- the previous one. - package Macro_Vectors is - new Ada.Containers.Vectors (Positive, Macro_Definition); + package Macro_Sets is new Ada.Containers.Ordered_Sets (Macro_Definition); + subtype Macro_Set is Macro_Sets.Set; type Analysis_Options is record PP_Search_Path : String_Vectors.Vector; -- List of directories to search when looking for an included file - Builtin_Macros : Macro_Vectors.Vector; - -- List of predefined macros for the project compiler driver + Builtin_Macros : Macro_Set; + -- Set of predefined macros for the project compiler driver - PP_Macros : Macro_Vectors.Vector; - -- List of macros for the preprocessor + PP_Macros : Macro_Set; + -- Set of macros for the preprocessor Std : Unbounded_String; -- -std=X argument to pass to the preprocessor and the parser, or the From 2711b825c355cfbcf25beaac1d37ef51dc92e400 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 15 Sep 2022 16:56:55 +0200 Subject: [PATCH 0120/1483] Instrument.C: support SCOs that come from command line macros MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Spelling locations associated to the expansion of built-in macros or macros defined on the command line do not have a filename. For such locations, Get_Spelling_Location returns a null File_T (pointer), which makes the Spelling_Location function crash. Clang’s SourceManager creates a file table entry called "command line" for such locations, which the Get_Presumed_Location function returns when appropriate. Introduce a new Presumed_Location function overload to wrap Get_Presumed_Location, and use it in combination with Get_Spelling_Loc where locations for macro expansion are processed in the C instrumenter. TN: V914-024 --- tools/gnatcov/clang-extensions.adb | 5 +-- tools/gnatcov/clang-extensions.ads | 14 ++++++++ tools/gnatcov/clang-wrapper.cc | 12 +++++++ tools/gnatcov/instrument-c.adb | 30 ++++++++++++++--- tools/gnatcov/instrument-c_utils.adb | 50 ++++++++++++++++++++++++++++ tools/gnatcov/instrument-c_utils.ads | 18 ++++++++-- tools/gnatcov/slocs.adb | 12 +++++-- tools/gnatcov/slocs.ads | 5 +++ 8 files changed, 134 insertions(+), 12 deletions(-) diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index c3b4aa01e..c010c4b0f 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -26,10 +26,6 @@ with Files_Table; use Files_Table; package body Clang.Extensions is - function To_Sloc (Line, Column : unsigned) return Local_Source_Location is - ((Natural (Line), Natural (Column))); - -- Convert a Clang local source location to gnatcov's own format - function To_Sloc (File : File_T; Line, Column : unsigned) return Source_Location is @@ -176,6 +172,7 @@ package body Clang.Extensions is Line, Column : aliased unsigned; begin Get_Presumed_Location (Loc, Filename'Access, Line'Access, Column'Access); + Dispose_String (Filename); return To_Sloc (Line, Column); end Presumed_Location; diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index 6362c1c77..0dc07d97f 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -190,7 +190,21 @@ package Clang.Extensions is External_Name => "clang_getExpansionEnd"; -- See getExpansionRange in clang/Basic/SourceManager.h. + function Get_Spelling_Loc + (TU : Translation_Unit_T; + Loc : Source_Location_T) return Source_Location_T + with Import, Convention => C, External_Name => "clang_getSpellingLoc"; + -- See getSpellingLoc in clang/Basic/SourceManager.h + procedure Print_Location (TU : Translation_Unit_T; Loc : Source_Location_T) with Import, Convention => C, External_Name => "clang_printLocation"; + ----------- + -- Utils -- + ----------- + + function To_Sloc (Line, Column : unsigned) return Local_Source_Location is + ((Natural (Line), Natural (Column))); + -- Convert a Clang local source location to gnatcov's own format + end Clang.Extensions; diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index f969308c1..c4929e506 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -684,3 +684,15 @@ clang_printLocation (CXTranslationUnit TU, CXSourceLocation Loc) const SourceManager &SM = getSourceManager (TU); translateSourceLocation (Loc).dump (SM); } + +extern "C" CXSourceLocation +clang_getSpellingLoc (CXTranslationUnit TU, CXSourceLocation location) +{ + + SourceLocation Loc = SourceLocation::getFromRawEncoding (location.int_data); + if (!location.ptr_data[0] || Loc.isInvalid ()) + return clang_getNullLocation (); + + const SourceManager &SM = getSourceManager (TU); + return translateSLoc (TU, SM.getSpellingLoc (Loc)); +} diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index ecbfa0556..2b7ca0de5 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -899,6 +899,14 @@ package body Instrument.C is -- ^~~~~~ -- So we have to get the macro argument expansion location, and -- get its spelling location. + -- + -- Another important point is that macro definitions can be + -- given on the command line, which means that source locations + -- that refer to the expansion of such macros will not have an + -- associated file. This information is preserved through + -- preprocessing, and we can actually use the Presumed_Location + -- API to get either a filename, or a or + -- string in these cases. if Is_Macro_Arg_Expansion (Loc, Macro_Arg_Expanded_Loc, UIC.TU) then @@ -908,13 +916,23 @@ package body Instrument.C is Definition_Info := (Macro_Name => Macro_Expansion_Name, - Sloc => Spelling_Location (Macro_Arg_Expanded_Loc)); + Sloc => + Presumed_Spelling_Location + (UIC.TU, + Macro_Arg_Expanded_Loc, + Macro_Expansion_Name, + UIC.Options.Builtin_Macros)); else Macro_Expansion_Name := +Get_Immediate_Macro_Name_For_Diagnostics (Loc, UIC.TU); Definition_Info := (Macro_Name => Macro_Expansion_Name, - Sloc => Spelling_Location (Loc)); + Sloc => + Presumed_Spelling_Location + (UIC.TU, + Loc, + Macro_Expansion_Name, + UIC.Options.Builtin_Macros)); end if; while Is_Macro_Location (Loc) loop @@ -992,8 +1010,12 @@ package body Instrument.C is if Length (Macro_Expansion_Name) /= 0 then Expansion_Stack.Append ((Macro_Name => Macro_Expansion_Name, - Sloc => Spelling_Location - (Immediate_Expansion_Loc))); + Sloc => + Presumed_Spelling_Location + (UIC.TU, + Immediate_Expansion_Loc, + Macro_Expansion_Name, + UIC.Options.Builtin_Macros))); end if; end loop; diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index adab44e6b..b4388bbd9 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -45,6 +45,56 @@ package body Instrument.C_Utils is -- Note: this has convention C in order to be a callback for the -- Clang.Index.Visit_Children and Clang.Index.Visit functions. + -------------------------------- + -- Presumed_Spelling_Location -- + -------------------------------- + + function Presumed_Spelling_Location + (TU : Translation_Unit_T; + Loc : Source_Location_T; + Macro_Name : Unbounded_String; + Builtin_Macros : Macro_Set) return Source_Location + is + C_Filename : aliased String_T; + Line, Column : aliased unsigned; + Filename : Unbounded_String; + Sloc : Local_Source_Location; + begin + Get_Presumed_Location + (Get_Spelling_Loc (TU, Loc), + C_Filename'Access, + Line'Access, + Column'Access); + Filename := +Get_C_String (C_Filename); + + -- If this is a command-line or built-in source location, ignore the + -- line and column indices. + + if Clang_Predefined_File (+Filename) then + + -- As built-in macros are passed through clang's command line, their + -- location refers to the "" rather than "". + -- Fix this for macros that are actually built-in. + + if Builtin_Macros.Contains + (Macro_Definition' + (Define => True, Name => Macro_Name, others => <>)) + then + Filename := +""; + end if; + Sloc := To_Sloc (0, 0); + else + Sloc := To_Sloc (Line, Column); + end if; + + Dispose_String (C_Filename); + return + (Source_File => Get_Index_From_Generic_Name + (Name => +Filename, + Kind => Source_File), + L => Sloc); + end Presumed_Spelling_Location; + ---------- -- Sloc -- ---------- diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 85141afb4..6b3fda8ea 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -16,13 +16,15 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Containers; use Ada.Containers; +with Ada.Containers; use Ada.Containers; with Ada.Containers.Vectors; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Clang.Index; use Clang.Index; with Clang.Rewrite; use Clang.Rewrite; -with Slocs; use Slocs; +with Instrument.C; use Instrument.C; +with Slocs; use Slocs; package Instrument.C_Utils is @@ -40,6 +42,18 @@ package Instrument.C_Utils is function Sloc (Loc : Source_Location_T) return Source_Location; -- Convert a Source_Location_T to a Source_Location + function Presumed_Spelling_Location + (TU : Translation_Unit_T; + Loc : Source_Location_T; + Macro_Name : Unbounded_String; + Builtin_Macros : Macro_Set) return Source_Location; + -- Assuming Loc is a macro expansion location that refers to the expansion + -- of Macro_Name, return its presumed spelling location, i.e. the actual + -- source location of its expansion with command-line / built-in macros + -- accounted for. If Macro_Name refers to a built-in macro (i.e. in + -- the Builtin_Macros set), set the filename for the returned sloc + -- to "". + function Start_Sloc (N : Cursor_T) return Source_Location_T; function Start_Sloc (N : Cursor_T) return Source_Location; -- Return the starting location of a node diff --git a/tools/gnatcov/slocs.adb b/tools/gnatcov/slocs.adb index 9a450c2bc..f8f1d4f52 100644 --- a/tools/gnatcov/slocs.adb +++ b/tools/gnatcov/slocs.adb @@ -108,9 +108,17 @@ package body Slocs is Show_File, Show_Line, Show_Column : Boolean; + File_Name : constant String := + Get_Name (Sloc.Source_File); begin if Sloc.L = No_Local_Location then - return ""; + + -- If this location points to predefined code (such as the command + -- line, for macros defined with the -D switch), let the user know. + + return (if Clang_Predefined_File (File_Name) + then File_Name + else ""); end if; Show_File := Sloc.Source_File /= Ref.Source_File; @@ -120,7 +128,7 @@ package body Slocs is or else Sloc.L.Column /= Ref.L.Column; return - (if Show_File then Get_Name (Sloc.Source_File) & ":" else "") + (if Show_File then File_Name & ":" else "") & (if Show_Line then Img (Sloc.L.Line) & ":" else "") & diff --git a/tools/gnatcov/slocs.ads b/tools/gnatcov/slocs.ads index d573c0f93..03a9ad246 100644 --- a/tools/gnatcov/slocs.ads +++ b/tools/gnatcov/slocs.ads @@ -104,4 +104,9 @@ package Slocs is type Source_Locations is array (Positive range <>) of Source_Location; + function Clang_Predefined_File (Filename : String) return Boolean is + (Filename = "" or else Filename = ""); + -- Return whether this filename represents a command-line / built-in + -- location. + end Slocs; From 4eb45157876058a2477a9fb247e57793c1c4a00d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 14 Sep 2022 15:09:04 +0200 Subject: [PATCH 0121/1483] C instrumentation: fix parsing of preprocessed file When parsing a preprocessed file, we were passing all of the macro definition flags, even if the file already had been preprocessed. This meant that self-referencing macros, that expand to themselves (e.g. -DX=;x), were expanded twice. This could result in spurious coverage expectations (;;x with the above example), as the parsed AST could have more coverage obligations than the compiled code. In practice, this meant warnings at gnatcov instrument time, with mismatching coverage obligations between the preprocessing info recording pass, and the instrumentation pass, and also overlapping SCOs (because we ended up with macro locations in the instrumentation pass, which is not supposed to happen), leading us to discard valid SCOs. TN: V914-021 --- .../instr-cov/cmdline-self-ref-macro/main.c | 5 ++++ .../instr-cov/cmdline-self-ref-macro/test.py | 28 ++++++++++++++++++ tools/gnatcov/instrument-c.adb | 29 ++++++++++++++----- tools/gnatcov/instrument-c.ads | 7 +++-- 4 files changed, 59 insertions(+), 10 deletions(-) create mode 100644 testsuite/tests/instr-cov/cmdline-self-ref-macro/main.c create mode 100644 testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py diff --git a/testsuite/tests/instr-cov/cmdline-self-ref-macro/main.c b/testsuite/tests/instr-cov/cmdline-self-ref-macro/main.c new file mode 100644 index 000000000..398ec675a --- /dev/null +++ b/testsuite/tests/instr-cov/cmdline-self-ref-macro/main.c @@ -0,0 +1,5 @@ +int +main (void) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py b/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py new file mode 100644 index 000000000..0b2b98b7a --- /dev/null +++ b/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py @@ -0,0 +1,28 @@ +""" +Regression test: gnatcov used to produce spurious coverage obligations for code +coming from self-referencing macros defined on the command line, as it was +expanding them another time when parsing the file. This led to warnings at +instrumentation time, and wrong coverage expectations. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.c'])), + covlevel='stmt', + mains=['main'], + extra_instr_args=['--c-opts=-Dreturn=printf ("Before return"); return'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src', +) + +check_xcov_reports('xcov/*.xcov', {'xcov/main.c.xcov': {'+': {4}}}) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 2b7ca0de5..94c959ca9 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3011,9 +3011,13 @@ package body Instrument.C is Create_Index (Exclude_Declarations_From_PCH => 0, Display_Diagnostics => 0); - Add_Options (Args, Options); + -- At this point, whether Preprocessed was passed True or False to + -- Start_Rewriting, the code to parse is always preprocessed. + + Add_Options (Args, Options, Preprocessed => True); String_Vectors.Append (Args, Common_Parse_TU_Args (Instrumenter.Language)); + declare C_Args : chars_ptr_array := To_Chars_Ptr_Array (Args); begin @@ -4467,7 +4471,8 @@ package body Instrument.C is procedure Add_Options (Args : in out String_Vectors.Vector; Options : Analysis_Options; - Pass_Builtins : Boolean := True) is + Pass_Builtins : Boolean := True; + Preprocessed : Boolean := False) is procedure Add_Macro_Switches (Macros : Macro_Set); -- Add the given macro switches to Args @@ -4493,14 +4498,22 @@ package body Instrument.C is Args.Append (Dir); end loop; - -- Add builtin macros before macros from command line switches, as the - -- latter should have precedence over builtins and thus must come last - -- in Args. + -- If the file was already pre-processed, do not pass macro command + -- line switches. Since preprocessed code can contain names of defined + -- macros, passing macro arguments for the parsing step could trigger + -- other expansions, and thus feed the parser with unexpected code. + + if not Preprocessed then + + -- Add builtin macros before macros from command line switches, as + -- the latter should have precedence over builtins and thus must + -- come last in Args. - if Pass_Builtins then - Add_Macro_Switches (Options.Builtin_Macros); + if Pass_Builtins then + Add_Macro_Switches (Options.Builtin_Macros); + end if; + Add_Macro_Switches (Options.PP_Macros); end if; - Add_Macro_Switches (Options.PP_Macros); -- The -std switch also indicates the C/C++ version used, and -- influences both the configuration of the preprocessor, and the diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 758dae99f..dd8c167e7 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -287,9 +287,12 @@ package Instrument.C is procedure Add_Options (Args : in out String_Vectors.Vector; Options : Analysis_Options; - Pass_Builtins : Boolean := True); + Pass_Builtins : Boolean := True; + Preprocessed : Boolean := False); -- Append to Args the command line options corresponding to Options. If - -- Pass_Builtins is True, pass builtin macros in Options to Args. + -- Pass_Builtins is True, pass builtin macros in Options to Args. If + -- Preprocessed is True, consider that we will use these options on a + -- file that was already preprocessed. procedure Import_From_Project (Self : out Analysis_Options; From 3c3eda9692038a83c1340baadb4abe805dfec2d3 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 26 Jan 2023 14:24:32 +0100 Subject: [PATCH 0122/1483] instr-cov/cmdline-self-ref-macro: adapt test for light runtimes TN: V914-024 --- testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py b/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py index 0b2b98b7a..861e77b4c 100644 --- a/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py +++ b/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py @@ -18,7 +18,7 @@ gprsw=GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.c'])), covlevel='stmt', mains=['main'], - extra_instr_args=['--c-opts=-Dreturn=printf ("Before return"); return'], + extra_instr_args=['--c-opts=-Dreturn=int a; return'], extra_coverage_args=['-axcov', '--output-dir=xcov'], trace_mode='src', ) From e1eff57055dcd93b6b2cb4c459ebfbdb0c563d3b Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 26 Jan 2023 15:52:17 +0100 Subject: [PATCH 0123/1483] Add in the file table files containing inlined subprogram calls With binary traces, we may print notice messages referencing the inlined subprogram caller, and thus expect the file containing calls to an inlined subprogram to be in the files table, even if it is not a unit of interest by itself. TN: V914-024 --- tools/gnatcov/traces_elf.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/traces_elf.adb b/tools/gnatcov/traces_elf.adb index c39f02c08..23fd8650c 100644 --- a/tools/gnatcov/traces_elf.adb +++ b/tools/gnatcov/traces_elf.adb @@ -3155,7 +3155,7 @@ package body Traces_Elf is else Get_Index_From_Full_Name (Full_Name => Filenames.Element (Inlined_Subp.File).all, Kind => Stub_File, - Insert => False)); + Insert => True)); Info : Address_Info_Acc := new Address_Info' (Kind => Inlined_Subprogram_Addresses, From b635da9a665716d48a7e902f6c857f3b5f372dc5 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 2 Dec 2022 08:10:57 +0000 Subject: [PATCH 0124/1483] instrument.adb: minor refactorings/reformattings TN: VB02-026 --- tools/gnatcov/instrument.adb | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index a1e268155..fa3667145 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -31,7 +31,7 @@ with GNAT.OS_Lib; with GNATCOLL.Projects; use GNATCOLL.Projects; with GNATCOLL.JSON; use GNATCOLL.JSON; -with GNATCOLL.VFS; +with GNATCOLL.VFS; use GNATCOLL.VFS; with Libadalang.Analysis; with Libadalang.Project_Provider; @@ -108,7 +108,7 @@ package body Instrument is -- Map to associate a list of compilation units to instrument to a library -- unit (indexed by the library unit name). -- - -- For file-based languages, the library unit only have one compilation + -- For file-based languages, the library unit only has one compilation -- unit associated to it (that is the library unit itself, for which the -- name is the actual base filename). @@ -215,7 +215,6 @@ package body Instrument is (Cur : Library_Unit_Maps.Cursor; In_Library_Dir : Boolean) return String is - use GNATCOLL.VFS; use Library_Unit_Maps; LU_Name : constant String := Key (Cur); @@ -365,8 +364,7 @@ package body Instrument is (Project : GPR.Project_Type; Source_File : GPR.File_Info) is procedure Add_Instrumented_Unit - (CU_Name : Compilation_Unit_Name; - Info : GPR.File_Info); + (CU_Name : Compilation_Unit_Name; Info : GPR.File_Info); -- Wrapper for Instrument.Common.Add_Instrumented_Unit --------------------------- @@ -374,10 +372,8 @@ package body Instrument is --------------------------- procedure Add_Instrumented_Unit - (CU_Name : Compilation_Unit_Name; - Info : GPR.File_Info) + (CU_Name : Compilation_Unit_Name; Info : GPR.File_Info) is - use GNATCOLL.VFS; Should_Ignore : constant Boolean := Is_Ignored_Source_File (IC, +Info.File.Base_Name); begin @@ -491,8 +487,6 @@ package body Instrument is else for Filename of Mains loop declare - use GNATCOLL.VFS; - F : constant String := +Filename; Info : constant File_Info := Project.Project.Root_Project.Create_From_Project (+F); @@ -543,7 +537,6 @@ package body Instrument is Filename : constant String := To_String (Unit_Info.Filename); begin - -- Simply add the unit to the file table if it is not -- externally built. @@ -614,8 +607,6 @@ package body Instrument is -- creates automatically, the library directory may not -- exist: create it if needed. - declare - use GNATCOLL.VFS; begin Create (Create (+Lib_SID).Dir_Name).Make_Dir; exception @@ -669,12 +660,8 @@ package body Instrument is -- mains that are units of interest. for Main of Mains_To_Instrument (Language) loop - declare - use type GNATCOLL.VFS.Filesystem_String; - begin - Instrumenters (Language).Auto_Dump_Buffers_In_Main - (IC, Main.CU_Name, +Main.File.Full_Name, Main.Prj_Info.all); - end; + Instrumenters (Language).Auto_Dump_Buffers_In_Main + (IC, Main.CU_Name, +Main.File.Full_Name, Main.Prj_Info.all); end loop; end loop; From c55d47fa081f279da0990cb68bf707f495c59639 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 30 Jan 2023 16:13:35 +0000 Subject: [PATCH 0125/1483] ALI files: consolidate the file kinds of main sources for C Main sources for C are looked up from "D line" entries, which load files as stubs. Make sure we consolidate them to source files when we decide to treat them as source files. This fixes a crash in the homonym-units-of-interest testcase that the eng/cov/gnatcoverage!8 MR creates. TN: V728-002 --- tools/gnatcov/sc_obligations.adb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index c8d5460ba..3067e5c40 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -2668,6 +2668,12 @@ package body SC_Obligations is for Dep of Deps loop if Get_Simple_Name (Dep) = Main_Source_Simple_Name then Main_Source := Dep; + + -- Files designated by D lines are loaded as stub files. Here, + -- we decide to treat one as a source file, so make sure we + -- have registered it as one. + + Consolidate_File_Kind (Main_Source, Source_File); exit; end if; end loop; From 519ad961719ec13e88715af6109de83efe969b19 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 27 Sep 2022 16:18:31 +0200 Subject: [PATCH 0126/1483] Do not go through subprojects sources when computing UoI for a prj When parsing project file coverage attributes (such as Excluded_Units or Units), we go through the whole project arborescence, projet per project. gnatcov also used to re-go through imported projects when exploring one project, which is not right: the Excluded_Units/Units attributes only apply to the project itself. Note that in practice, this only resulted in a missing warning (no unit in project when was excluded in but belonged to an imported project). TN: V728-002 --- .../excluded_unit_imported_prj/prj1/pkg.c | 5 ++ .../tests/excluded_unit_imported_prj/test.c | 8 +++ .../tests/excluded_unit_imported_prj/test.py | 51 +++++++++++++++++++ tools/gnatcov/project.adb | 5 +- 4 files changed, 68 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/excluded_unit_imported_prj/prj1/pkg.c create mode 100644 testsuite/tests/excluded_unit_imported_prj/test.c create mode 100644 testsuite/tests/excluded_unit_imported_prj/test.py diff --git a/testsuite/tests/excluded_unit_imported_prj/prj1/pkg.c b/testsuite/tests/excluded_unit_imported_prj/prj1/pkg.c new file mode 100644 index 000000000..f939f7693 --- /dev/null +++ b/testsuite/tests/excluded_unit_imported_prj/prj1/pkg.c @@ -0,0 +1,5 @@ +int +foo (int a, int b) +{ + return a && b; +} diff --git a/testsuite/tests/excluded_unit_imported_prj/test.c b/testsuite/tests/excluded_unit_imported_prj/test.c new file mode 100644 index 000000000..19740b019 --- /dev/null +++ b/testsuite/tests/excluded_unit_imported_prj/test.c @@ -0,0 +1,8 @@ +extern int foo (int a, int b); + +int +main () +{ + foo (0, 1); + return 0; +} diff --git a/testsuite/tests/excluded_unit_imported_prj/test.py b/testsuite/tests/excluded_unit_imported_prj/test.py new file mode 100644 index 000000000..7e84f330b --- /dev/null +++ b/testsuite/tests/excluded_unit_imported_prj/test.py @@ -0,0 +1,51 @@ +""" +This test checks that units of interest project attributes only apply to the +project in which they are defined, and not to recursive project dependencies. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.gprutils import GPRswitches +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import thistest, gprfor + +Wdir('tmp_') + +prj1 = gprfor(mains=[], prjid='prj1', srcdirs=['../prj1'], objdir='obj-prj1') + +# Check that ignoring pkg.c in the main project yields a warning, as the pkg.c +# unit is in thr prj1 dependency and not in the root project. +extra_p = """ +package Coverage is + for Excluded_Units use ("pkg.c"); +end Coverage; +""" +p = gprfor(mains=['test.c'], deps=['prj1'], srcdirs=['..'], extra=extra_p) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel='stmt+mcdc', + mains=['test'], + extra_coverage_args=['--annotate=xcov'], + instrument_warnings_as_errors=False, +) +warning_file = ('coverage.log' if thistest.options.trace_mode == 'bin' + else 'instrument.log') + +thistest.fail_if_not_equal( + warning_file, + 'warning: no unit pkg.c in project gen' + ' (coverage.excluded_units attribute)\n', + contents_of(warning_file) +) + +# Check that pkg.c is not ignored by checking the report contents +check_xcov_reports( + '*.xcov', + { + 'pkg.c.xcov': {'!': {4}}, + 'test.c.xcov': {'+': {6, 7}} + }, + 'obj' +) + +thistest.result() diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 7c1caa196..468d297b7 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -1033,6 +1033,9 @@ package body Project is end Process_Source_File; begin + -- Do not go through imported projects; the Excluded_Units / + -- Units attributes only apply to the project itself. + Iterate_Source_Files (Project, Process_Source_File'Access, Recursive => False); Inc_Units_Defined := True; @@ -1286,7 +1289,7 @@ package body Project is -- source file name. Iterate_Source_Files - (Prj, Process_Source_File'Access, Recursive => True); + (Prj, Process_Source_File'Access, Recursive => False); Match_Pattern_List (Patterns_List => Unit_Patterns, Strings_List => Units_Present, From 38533ec793eefa714e031e329da48a061e649dd3 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 4 Aug 2022 18:08:39 +0200 Subject: [PATCH 0127/1483] Improve support homonym source files Across different projects, there can be homonym C source files. It is thus not enough to identify a unit only by its unit name / base name. For file- based languages, we also need the project name. Add this bit of information at every place needed. TN: V728-002 --- .../homonym-units-of-interest/prj1/pkg.c | 5 + .../homonym-units-of-interest/prj2/pkg.c | 5 + .../tests/homonym-units-of-interest/test.c | 10 + .../tests/homonym-units-of-interest/test.py | 50 +++ tools/gnatcov/annotations-report.adb | 7 +- tools/gnatcov/checkpoints.ads | 3 +- tools/gnatcov/coverage-source.adb | 57 ++-- tools/gnatcov/coverage-source.ads | 5 +- tools/gnatcov/gnatcov_bits_specific.adb | 20 +- tools/gnatcov/instrument-ada_unit.adb | 2 +- tools/gnatcov/instrument-base_types.ads | 1 + tools/gnatcov/instrument-c.adb | 2 +- tools/gnatcov/instrument-common.adb | 1 - tools/gnatcov/instrument-common.ads | 1 + tools/gnatcov/instrument.adb | 2 +- tools/gnatcov/paths.adb | 13 + tools/gnatcov/paths.ads | 4 + tools/gnatcov/project.adb | 294 +++++++++--------- tools/gnatcov/project.ads | 106 +++++-- 19 files changed, 367 insertions(+), 221 deletions(-) create mode 100644 testsuite/tests/homonym-units-of-interest/prj1/pkg.c create mode 100644 testsuite/tests/homonym-units-of-interest/prj2/pkg.c create mode 100644 testsuite/tests/homonym-units-of-interest/test.c create mode 100644 testsuite/tests/homonym-units-of-interest/test.py diff --git a/testsuite/tests/homonym-units-of-interest/prj1/pkg.c b/testsuite/tests/homonym-units-of-interest/prj1/pkg.c new file mode 100644 index 000000000..f939f7693 --- /dev/null +++ b/testsuite/tests/homonym-units-of-interest/prj1/pkg.c @@ -0,0 +1,5 @@ +int +foo (int a, int b) +{ + return a && b; +} diff --git a/testsuite/tests/homonym-units-of-interest/prj2/pkg.c b/testsuite/tests/homonym-units-of-interest/prj2/pkg.c new file mode 100644 index 000000000..845f66891 --- /dev/null +++ b/testsuite/tests/homonym-units-of-interest/prj2/pkg.c @@ -0,0 +1,5 @@ +int +bar (int a, int b) +{ + return a || b; +} diff --git a/testsuite/tests/homonym-units-of-interest/test.c b/testsuite/tests/homonym-units-of-interest/test.c new file mode 100644 index 000000000..6d783a071 --- /dev/null +++ b/testsuite/tests/homonym-units-of-interest/test.c @@ -0,0 +1,10 @@ +extern int foo (int a, int b); +extern int bar (int a, int b); + +int +main () +{ + foo (0, 1); + bar (0, 1); + return 0; +} diff --git a/testsuite/tests/homonym-units-of-interest/test.py b/testsuite/tests/homonym-units-of-interest/test.py new file mode 100644 index 000000000..b1bbf4816 --- /dev/null +++ b/testsuite/tests/homonym-units-of-interest/test.py @@ -0,0 +1,50 @@ +""" +This test checks that gnatcov can deal with two homonym files belonging to +different projects, with one of the source files being excluded from the +coverage analysis (through project file coverage attributes) while the other +is not. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import thistest, gprfor + +Wdir('tmp_') + +is_bin_traces = thistest.options.trace_mode == 'bin' + +extra_prj1 = """ +package Coverage is + for Excluded_Units use ("pkg.c"); +end Coverage; +""" +prj1 = gprfor(mains=[], prjid='prj1', srcdirs=['../prj1'], objdir='obj-prj1', + extra=extra_prj1) +prj2 = gprfor(mains=[], prjid='prj2', srcdirs=['../prj2'], objdir='obj-prj2') +p = gprfor(mains=['test.c'], deps=['prj1', 'prj2'], srcdirs=['..']) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel='stmt+mcdc', + mains=['test'], + extra_coverage_args=['--annotate=xcov', '--output-dir=xcov'], + instrument_warnings_as_errors=False, +) + +# The filtering of units of interest is done at a later stage for binary +# traces, and files that may be ignored in coverage report can have been +# added to gnatcov file table. This means that the shortest unique suffix, +# computed from gnatcov file table to differentiate homonym source files +# will be different from source traces. +xcov_homonoym_filename = 'prj2-pkg.c.xcov' if is_bin_traces else 'pkg.c.xcov' +check_xcov_reports( + '*.xcov', + { + xcov_homonoym_filename: {'!': {4}}, + 'test.c.xcov': {'+': {7, 8, 9}} + }, + 'xcov' +) + +thistest.result() diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 698c77f72..6445f6ed1 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -29,6 +29,7 @@ with Coverage.Source; use Coverage.Source; with Coverage.Tags; use Coverage.Tags; with Files_Table; with SC_Obligations; +with Project; use Project; with Switches; with Traces_Files; use Traces_Files; @@ -648,7 +649,7 @@ package body Annotations.Report is (FI : Files_Table.File_Info); -- Print the name of the file and its ignore status on the report - procedure Print_Unit_Name (Name : String); + procedure Print_Unit_Name (Name : Unique_Name); -- Print Name on the report ------------------------ @@ -671,9 +672,9 @@ package body Annotations.Report is -- Print_Unit_Name -- --------------------- - procedure Print_Unit_Name (Name : String) is + procedure Print_Unit_Name (Name : Unique_Name) is begin - Put_Line (Output.all, Name); + Put_Line (Output.all, +Name.Unit_Name); end Print_Unit_Name; begin Iterate_On_Unit_List diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 8de4d9de5..3384f0c66 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -32,7 +32,7 @@ with SC_Obligations; use SC_Obligations; package Checkpoints is - subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 11; + subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 12; -- For compatibility with previous Gnatcov versions, the checkpoint -- file format is versioned. -- @@ -48,6 +48,7 @@ package Checkpoints is -- 9 -- Add the support for scoped metrics -- 10 -- Add non instrumented SCOs sets -- 11 -- fingerprints for buffer bit maps + -- 12 -- Extend Unit_List to distinguish homonym source files -- -- Note that we always use the last version when creating a checkpoint. diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 978fd216f..4e2524823 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -40,7 +40,6 @@ with Elf_Disassemblers; use Elf_Disassemblers; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with MC_DC; use MC_DC; with Outputs; use Outputs; -with Project; with Slocs; use Slocs; with Strings; use Strings; with Switches; use Switches; @@ -217,7 +216,7 @@ package body Coverage.Source is package US renames Ada.Strings.Unbounded; - Unit_List : String_Sets.Set; + 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. @@ -279,17 +278,17 @@ package body Coverage.Source is end if; Unit_List_Invalidated := True; - Unit_List := String_Sets.Empty_Set; + Unit_List := Unit_Sets.Empty_Set; end Invalidate_Unit_List; ------------------- -- Add_Unit_Name -- ------------------- - procedure Add_Unit_Name (Name : String) is + procedure Add_Unit_Name (Name : Unique_Name) is begin if not Unit_List_Invalidated then - Unit_List.Include (US.To_Unbounded_String (Name)); + Unit_List.Include (Name); end if; end Add_Unit_Name; @@ -308,8 +307,13 @@ package body Coverage.Source is Pattern => ".", From => Sep, Going => Ada.Strings.Backward); + if Unit_List.Contains - (US.To_Unbounded_String (Qualified_Name (First .. Sep - 1))) + (Unique_Name' + (Language => Unit_Based_Language, + Unit_Name => + US.To_Unbounded_String + (Qualified_Name (First .. Sep - 1)))) then return Qualified_Name (First .. Sep - 1); end if; @@ -335,7 +339,6 @@ package body Coverage.Source is procedure Compute_Unit_Name_For_Ignored_Sources is - use Project; use Types; procedure Callback @@ -407,8 +410,7 @@ package body Coverage.Source is and then FI.Ignore_Status in Always .. Sometimes then pragma Assert - (FI.Unit.Known and then Unit_List.Contains (FI.Unit.Name)); - + (FI.Unit.Known and then Is_Unit_Of_Interest (FI.Full_Name.all)); if not Ignored_SF_Map.Contains (FI.Unit.Name) then Vec := new Ignored_Sources_Vector.Vector; Ignored_SF_Map.Insert (FI.Unit.Name, Vec); @@ -430,15 +432,15 @@ package body Coverage.Source is -------------------------- procedure Iterate_On_Unit_List - (Process_Unit : not null access procedure (Name : String); + (Process_Unit : not null access procedure (Name : Unique_Name); Process_Source_File : not null access procedure (FI : File_Info)) is begin for S of Unit_List loop - Process_Unit.all (US.To_String (S)); + Process_Unit.all (S); - if Ignored_SF_Map.Contains (S) then - for FI of Ignored_SF_Map.Element (S).all loop + if Ignored_SF_Map.Contains (S.Unit_Name) then + for FI of Ignored_SF_Map.Element (S.Unit_Name).all loop Process_Source_File (FI.all); end loop; end if; @@ -461,7 +463,7 @@ package body Coverage.Source is if not Unit_List_Invalidated then Ada.Containers.Count_Type'Output (CSS, Unit_List.Length); for N of Unit_List loop - US.Unbounded_String'Output (CSS, N); + Unique_Name'Output (CSS, N); end loop; end if; end if; @@ -475,7 +477,7 @@ package body Coverage.Source is begin SCI_Vector.Clear; Unit_List_Invalidated := False; - Unit_List := String_Sets.Empty_Set; + Unit_List := Unit_Sets.Empty_Set; end Checkpoint_Clear; --------------------- @@ -585,9 +587,13 @@ package body Coverage.Source is Invalidate_Unit_List (US.To_String (CLS.Filename) & " does not contain the list of units (obsolete format)"); + else declare Invalidated : constant Boolean := Boolean'Input (CLS); + Obsolete : constant Boolean := + Checkpoints.Version_Less (CLS, Than => 12); + Dummy : US.Unbounded_String; begin if Invalidated then Invalidate_Unit_List @@ -595,9 +601,24 @@ package body Coverage.Source is & " does not contain the list of units (produced with" & " --scos or --sid)"); else - for I in 1 .. Ada.Containers.Count_Type'Input (CLS) loop - pragma Unreferenced (I); - Unit_List.Include (US.Unbounded_String'Input (CLS)); + for I in 1 .. Ada.Containers.Count_Type'Input (CLS) loop + + -- From version 3 up to version 11, Unit_List used to + -- be a set of unbounded strings, and did not support + -- homonym source files. If we are in that case, read the + -- old Unit_List from the checkpoint and then discard it. + + if Obsolete then + if I = 1 then + Invalidate_Unit_List + (US.To_String (CLS.Filename) + & " does not contain the list of units (obsolete" + & " format)"); + end if; + US.Unbounded_String'Read (CLS, Dummy); + else + Unit_List.Include (Unique_Name'Input (CLS)); + end if; end loop; end if; end; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 7ea312310..44f4d268e 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -21,6 +21,7 @@ with Files_Table; use Files_Table; with Instrument; use Instrument; with Instrument.Input_Traces; use Instrument.Input_Traces; with Instrument.Base_Types; use Instrument.Base_Types; +with Project; use Project; with Traces; use Traces; with Traces_Names; use Traces_Names; with Traces_Lines; use Traces_Lines; @@ -103,7 +104,7 @@ package Coverage.Source is -- message is used for logging purposes, so that users can find out why we -- cannot dump the list of units of interest. - procedure Add_Unit_Name (Name : String); + procedure Add_Unit_Name (Name : Unique_Name); -- Add Name to the list of names for units of interest. For convenience, do -- nothing if it is invalid. @@ -116,7 +117,7 @@ package Coverage.Source is -- unit names, linking them to the list of ignored source files. procedure Iterate_On_Unit_List - (Process_Unit : not null access procedure (Name : String); + (Process_Unit : not null access procedure (Name : Unique_Name); Process_Source_File : not null access procedure (FI : File_Info)) with Pre => Unit_List_Is_Valid; -- Call Unit_Callback for each unit of interest, passing to it the name of diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 6fa57af67..b580bc2d6 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -281,13 +281,7 @@ procedure GNATcov_Bits_Specific is -- have to be enumerated from a project file. if Inputs.Length (ALIs_Inputs) = 0 and then Is_Project_Loaded then - Enumerate_LIs (Add_LI'Access); - end if; - - -- When appropriate, warn about units of interest with no LI - - if Is_Project_Loaded and then LIs_Enumerated then - Report_Units_Without_LI; + Enumerate_SCOs_Files (Add_LI'Access, Binary_Trace_File); end if; if Source_Coverage_Enabled then @@ -354,7 +348,7 @@ procedure GNATcov_Bits_Specific is -- of interest. This requires a project file. if Is_Project_Loaded and then Inputs.Length (SID_Inputs) = 0 then - Enumerate_SIDs (Add_SID_File'Access); + Enumerate_SCOs_Files (Add_SID_File'Access, Source_Trace_File); end if; -- Now load the SID files, applying the Ignore_Source_Files filter, @@ -1683,14 +1677,14 @@ begin -- Build the list of units of interest from project files option declare - procedure Add_Unit (Name : String; Is_Subunit : Boolean); + procedure Add_Unit (Name : Unique_Name; Is_Subunit : Boolean); -- Add Name to the list of names for units of interest -------------- -- Add_Unit -- -------------- - procedure Add_Unit (Name : String; Is_Subunit : Boolean) is + procedure Add_Unit (Name : Unique_Name; Is_Subunit : Boolean) is pragma Unreferenced (Is_Subunit); begin Add_Unit_Name (Name); @@ -2268,7 +2262,7 @@ begin then Standard_Output else File'Access); - procedure Print_Unit_Name (Name : String); + procedure Print_Unit_Name (Name : Unique_Name); -- Print the name of the file and if it was always or -- sometimes ignored on the report, if it was ignored at -- some point during the coverage analysis. @@ -2289,9 +2283,9 @@ begin end if; end Print_Ignored_File; - procedure Print_Unit_Name (Name : String) is + procedure Print_Unit_Name (Name : Unique_Name) is begin - Put_Line (Output.all, Name); + Put_Line (Output.all, +Name.Unit_Name); end Print_Unit_Name; begin diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index c8f983f5a..330e3175b 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -41,7 +41,7 @@ with Files_Table; use Files_Table; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Namet; use Namet; with Outputs; use Outputs; -with Project; +with Project; use Project; with SCOs; with Slocs; with Snames; use Snames; diff --git a/tools/gnatcov/instrument-base_types.ads b/tools/gnatcov/instrument-base_types.ads index 99dc1c449..99df2fbf4 100644 --- a/tools/gnatcov/instrument-base_types.ads +++ b/tools/gnatcov/instrument-base_types.ads @@ -28,6 +28,7 @@ with GNATCOLL.Projects; use GNATCOLL.Projects; with Types; use Types; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with Project; use Project; with SC_Obligations; use SC_Obligations; with Subprocesses; use Subprocesses; with Switches; use Switches; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 94c959ca9..7054c41e6 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -43,7 +43,7 @@ with Inputs; use Inputs; with Instrument.C_Utils; use Instrument.C_Utils; with Outputs; use Outputs; with Paths; use Paths; -with Project; +with Project; use Project; with SCOs; with Subprocesses; use Subprocesses; with System; use System; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 0ec387cb7..3eede45b6 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -38,7 +38,6 @@ with Diagnostics; with Hex_Images; with Outputs; use Outputs; with Paths; use Paths; -with Project; with SCOs; package body Instrument.Common is diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 8c413e618..6112c6a4c 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -70,6 +70,7 @@ with GNATcov_RTS; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Instrument.Base_Types; use Instrument.Base_Types; with Namet; use Namet; +with Project; use Project; with SC_Obligations; use SC_Obligations; with Slocs; use Slocs; with Switches; use Switches; diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index fa3667145..5837925d8 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -49,7 +49,7 @@ with Instrument.Find_Ada_Units; with JSON; use JSON; with Outputs; with Paths; use Paths; -with Project; +with Project; use Project; with SC_Obligations; with Switches; use Switches; diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index c9c17e5bb..fdaa16aa9 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -59,6 +59,19 @@ package body Paths is return new String'(Build_Filename (Dir, Filename)); end Build_Filename; + -------------------------- + -- Fold_Filename_Casing -- + -------------------------- + + function Fold_Filename_Casing (Filename : String) return String is + begin + if On_Windows then + return Ada.Characters.Handling.To_Lower (Filename); + else + return Filename; + end if; + end Fold_Filename_Casing; + --------------------------- -- Canonicalize_Filename -- --------------------------- diff --git a/tools/gnatcov/paths.ads b/tools/gnatcov/paths.ads index cfccf6de5..684d1d37b 100644 --- a/tools/gnatcov/paths.ads +++ b/tools/gnatcov/paths.ads @@ -39,6 +39,10 @@ package Paths is -- Likewise, without the "dir shouldn't be empty" constraint but -- checking that the path components are valid when not empty. + function Fold_Filename_Casing (Filename : String) return String; + -- If this is a windows host, return the lower-cased filename, otherwise + -- leave it unchanged. + function Canonicalize_Filename (Filename : String) return String; function Canonicalize_Filename (Filename : String) return String_Access; -- Assuming Filename is a full pathname to a file, return a normalized diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 468d297b7..58e9e2b7c 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -19,8 +19,8 @@ with Ada.Containers.Hashed_Maps; with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Containers.Indefinite_Ordered_Sets; +with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; -with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Directories; use Ada.Directories; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Hash; @@ -31,13 +31,12 @@ with GNAT.OS_Lib; with GNAT.Regexp; with GNATCOLL.Traces; -with GNATCOLL.Projects; use GNATCOLL.Projects; with GNATCOLL.Projects.Aux; -with GNATCOLL.VFS; use GNATCOLL.VFS; +with GNATCOLL.VFS; use GNATCOLL.VFS; -with Inputs; use Inputs; -with Outputs; use Outputs; -with Strings; use Strings; +with Instrument.Base_Types; use Instrument.Base_Types; +with Inputs; use Inputs; +with Outputs; use Outputs; package body Project is @@ -150,16 +149,18 @@ package body Project is end record; package Unit_Maps is new Ada.Containers.Indefinite_Ordered_Maps - (Key_Type => String, + (Key_Type => Unique_Name, Element_Type => Unit_Info); procedure Add_Unit - (Units : in out Unit_Maps.Map; - Cur : out Unit_Maps.Cursor; - Original_Name : String; - Language : Some_Language); - -- Add an entry to Units. See Unit_Info's members for the semantics of - -- arguments. + (Units : in out Unit_Maps.Map; + Cur : out Unit_Maps.Cursor; + Original_Name : String; + Info : File_Info; + Language : Some_Language); + -- Add a Unit_Info entry to Units. The key for this new entry (which is a + -- Unique_Name) is computed using the Original_Name, and the + -- Info.Project_Name if the unit is of a file-based language. procedure Warn_Missing_Info (What_Info : String; Unit : in out Unit_Info); -- If we haven't already, warn that we miss information (ALI or SID) about @@ -168,12 +169,6 @@ package body Project is Unit_Map : Unit_Maps.Map; -- Map lower-case unit names to Unit_Info records for all units of interest - Are_LIs_Enumerated : Boolean := False; - -- Return whether Enumerate_LIs was called - - Are_SIDs_Enumerated : Boolean := False; - -- Return whether Enumerate_SIDs was called - procedure Initialize (Target, Runtime, CGPR_File : GNAT.Strings.String_Access) with Pre => (Target = null and then Runtime = null) @@ -234,6 +229,24 @@ package body Project is -- Return whether Filename can be found among the sources of the -- configured Ada runtime. + -------------------- + -- To_Unique_Name -- + -------------------- + + function To_Unique_Name + (Unit_Name : String; + Project : Project_Type; + Language : Some_Language) return Unique_Name + is + U : Unique_Name (Language_Kind (Language)); + begin + U.Unit_Name := +Unit_Name; + if U.Language = File_Based_Language then + U.Project_Name := +Project.Name; + end if; + return U; + end To_Unique_Name; + --------- -- "+" -- --------- @@ -258,33 +271,32 @@ package body Project is -------------- procedure Add_Unit - (Units : in out Unit_Maps.Map; - Cur : out Unit_Maps.Cursor; - Original_Name : String; - Language : Some_Language) + (Units : in out Unit_Maps.Map; + Cur : out Unit_Maps.Cursor; + Original_Name : String; + Info : File_Info; + Language : Some_Language) is Ignored_Inserted : Boolean; - On_Windows : constant Boolean := - GNAT.OS_Lib.Directory_Separator = '\'; - Is_C_Header : constant Boolean := - Strings.Has_Suffix (To_Lower (Original_Name), ".h"); + Is_Header : constant Boolean := + (To_Language (Info.Language) in C_Family_Language + and then Info.Unit_Part = Unit_Spec); Orig_Name : constant Unbounded_String := - To_Unbounded_String ((if On_Windows and then Is_C_Header - then To_Lower (Original_Name) - else Original_Name)); - + +Fold_Filename_Casing (Original_Name); + Unit_Name : constant Unique_Name := + To_Unique_Name (Original_Name, Info.Project, Language); begin - -- Disable warnings for C header units as they do not have a proper + -- Disable warnings for C/C++ header units as they do not have a proper -- library file. Units.Insert - (Key => To_Lower (Original_Name), + (Key => Unit_Name, New_Item => (Original_Name => Orig_Name, Present_In_Projects => False, Is_Subunit => False, Language => Language, - LI_Seen => Is_C_Header, - Warned_About_Missing_Info => Is_C_Header), + LI_Seen => Is_Header, + Warned_About_Missing_Info => Is_Header), Position => Cur, Inserted => Ignored_Inserted); end Add_Unit; @@ -296,12 +308,11 @@ package body Project is procedure Warn_Missing_Info (What_Info : String; Unit : in out Unit_Info) is begin -- The only way to perform code coverage on C++ units is to use - -- instrumentation. If we have not enumerated SID files, this means that - -- we are using binary traces only, and thus C++ units cannot be units - -- of interest, so do not warn about them in this specific case. + -- instrumentation. With binary traces, C++ units cannot be units of + -- interest, so do not warn about them in this specific case. if Unit.Warned_About_Missing_Info - or else (not Are_SIDs_Enumerated + or else (Currently_Accepted_Trace_Kind = Binary_Trace_File and then Unit.Language = CPP_Language) then return; @@ -444,7 +455,7 @@ package body Project is --------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : String; Is_Subunit : Boolean)) + (Callback : access procedure (Name : Unique_Name; Is_Subunit : Boolean)) is use Unit_Maps; begin @@ -457,96 +468,60 @@ package body Project is end loop; end Enumerate_Units_Of_Interest; - ------------------- - -- Enumerate_LIs -- - ------------------- - - procedure Enumerate_LIs (LI_Cb : access procedure (LI_Name : String)) is - Lib_Info : Library_Info_List; - begin - -- Go through all library files in all projects of interest + ------------------------- + -- Is_Unit_Of_Interest -- + ------------------------- - for Prj_Info of Prj_Map loop - Prj_Info.Project.Library_Files - (List => Lib_Info, ALI_Ext => "^.*\.[ag]li$"); - for LI of Lib_Info loop - - -- Enumerate only LI files for Ada and C sources - - if To_Lower (LI.Source.Language) in "ada" | "c" then - - -- If the unit for this library file is in Unit_Map, this is a - -- unit of interest, so use it. - - declare - use Unit_Maps; - - LI_Source_Unit : constant String := LI.Source.Unit_Name; - LI_Source_File : constant String := - +LI.Source.File.Base_Name; - - U : constant String := - (if LI_Source_Unit'Length > 0 - then LI_Source_Unit - else LI_Source_File); - -- For unit-based languages (Ada), retrieve unit name from - -- LI file. For file-based languages (C), fall back to - -- translation unit source file name instead. - - Cur : constant Cursor := Unit_Map.Find (U); - begin - if Has_Element (Cur) then - LI_Cb.all (+LI.Library_File.Full_Name); - Unit_Map.Reference (Cur).LI_Seen := True; - end if; - end; - end if; - end loop; - Lib_Info.Clear; - end loop; - - Are_LIs_Enumerated := True; - end Enumerate_LIs; - - -------------------- - -- LIs_Enumerated -- - -------------------- - - function LIs_Enumerated return Boolean is + function Is_Unit_Of_Interest + (Project : Project_Type; + Unit_Name : String; + Language : Some_Language) return Boolean + is + U : constant Unique_Name := + To_Unique_Name (Unit_Name, Project, Language); begin - return Are_LIs_Enumerated; - end LIs_Enumerated; - - ----------------------------- - -- Report_Units_Without_LI -- - ----------------------------- - - procedure Report_Units_Without_LI is + return Unit_Map.Contains (U); + end Is_Unit_Of_Interest; + + ------------------------- + -- Is_Unit_Of_Interest -- + ------------------------- + + function Is_Unit_Of_Interest (Full_Name : String) return Boolean is + FI : constant File_Info := + Prj_Tree.Info (Create (+Full_Name)); + Unit_Name : constant String := + (case Language_Kind (To_Language (FI.Language)) is + when Unit_Based_Language => FI.Unit_Name, + when File_Based_Language => +FI.File.Base_Name); begin - for UI of Unit_Map loop - if not UI.Is_Subunit and then not UI.LI_Seen then - Warn_Missing_Info ("ALI", UI); - end if; - end loop; - end Report_Units_Without_LI; + return Is_Unit_Of_Interest + (FI.Project, Unit_Name, To_Language (FI.Language)); + end Is_Unit_Of_Interest; - -------------------- - -- Enumerate_SIDs -- - -------------------- + ------------------------- + -- Enumerate_SCO_Files -- + ------------------------- - procedure Enumerate_SIDs (Callback : access procedure (SID_Name : String)) + procedure Enumerate_SCOs_Files + (Callback : access procedure (Lib_Name : String); + Kind : Trace_File_Kind) is - Lib_Info : Library_Info_List; + Ext_Regexp : constant GNATCOLL.VFS.Filesystem_String := + (case Kind is + when Binary_Trace_File => "^.*\.[ag]li$", + when Source_Trace_File => "^.*\.sid$"); + Lib_Info : Library_Info_List; begin - -- Go through all SID files in all projects of interest + -- Go through all SCOs files in all projects of interest for Prj_Info of Prj_Map loop Prj_Info.Project.Library_Files - (List => Lib_Info, ALI_Ext => "^.*\.sid$"); + (List => Lib_Info, ALI_Ext => Ext_Regexp); for LI of Lib_Info loop - -- If the unit for this SID file is in Unit_Map, this is a unit of - -- interest, so use it. + -- If the unit for this SCO file is in Unit_Map, this is a + -- unit of interest, so use it. declare use Unit_Maps; @@ -554,15 +529,20 @@ package body Project is LI_Source_Unit : constant String := LI.Source.Unit_Name; LI_Source_File : constant String := +LI.Source.File.Base_Name; - U : constant String := + U : constant String := (if LI_Source_Unit'Length > 0 then LI_Source_Unit else LI_Source_File); - -- For unit-based languages (Ada), retrieve unit name from SID - -- file. For file-based languages (C), fall back to translation - -- unit source file name instead. - - Cur : constant Cursor := Unit_Map.Find (U); + -- For unit-based languages (Ada), retrieve unit name from + -- SCOs file. For file-based languages (C), fall back to + -- translation unit source file name instead. + + Cur : constant Cursor := + Unit_Map.Find + (To_Unique_Name + (U, + Project_Type (LI.LI_Project.all), + To_Language (LI.Source.Language))); begin if Has_Element (Cur) then Callback.all (+LI.Library_File.Full_Name); @@ -573,25 +553,19 @@ package body Project is Lib_Info.Clear; end loop; - -- Now warn about units of interest that have no SID + -- Now warn about units of interest that have no SCOs file for UI of Unit_Map loop if not UI.Is_Subunit and then not UI.LI_Seen then - Warn_Missing_Info ("SID", UI); + case Kind is + when Binary_Trace_File => + Warn_Missing_Info ("ALI", UI); + when Source_Trace_File => + Warn_Missing_Info ("SID", UI); + end case; end if; end loop; - - Are_SIDs_Enumerated := True; - end Enumerate_SIDs; - - --------------------- - -- SIDs_Enumerated -- - --------------------- - - function SIDs_Enumerated return Boolean is - begin - return Are_SIDs_Enumerated; - end SIDs_Enumerated; + end Enumerate_SCOs_Files; ----------------------- -- Enumerate_Sources -- @@ -619,8 +593,8 @@ package body Project is Language = To_Language (Info.Language)) and then (Include_Subunits - or else - Unit_Map.Contains (To_Lower (Unit_Name))) + or else Is_Unit_Of_Interest + (Info.Project, Unit_Name, To_Language (Info.Language))) then Callback (Info.Project, Info); end if; @@ -1026,6 +1000,7 @@ package body Project is (Inc_Units, Cur, Unit_Name, + Info, To_Language (Info.Language)); Inc_Units.Reference (Cur).Is_Subunit := Info.Unit_Part = Unit_Separate; @@ -1048,7 +1023,7 @@ package body Project is for Cur in Inc_Units.Iterate loop declare use Unit_Maps; - K : constant String := Key (Cur); + K : constant Unique_Name := Key (Cur); begin if not Exc_Units.Contains (K) then declare @@ -1110,7 +1085,7 @@ package body Project is procedure Add_To_Unit_Presents (C : Unit_Maps.Cursor) is begin - Units_Present.Append (+Unit_Maps.Key (C)); + Units_Present.Append (Unit_Maps.Key (C).Unit_Name); end Add_To_Unit_Presents; begin @@ -1221,9 +1196,22 @@ package body Project is Units : out Unit_Maps.Map; Defined : out Boolean) is + package FI_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, Element_Type => File_Info); + + use type FI_Vectors.Vector; + + package Unit_Name_FI_Vector_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Unbounded_String, + Element_Type => FI_Vectors.Vector); + Units_Present : String_Vectors.Vector; -- List of all units in Prj + Unit_Present_To_FI : Unit_Name_FI_Vector_Maps.Map; + -- Map a unit name to a file information vector. A unit name can be + -- be mapped to multiple file info if there are homonym source files. + package Unit_Language_Maps is new Ada.Containers.Hashed_Maps (Key_Type => Unbounded_String, Element_Type => Some_Language, @@ -1264,10 +1252,19 @@ package body Project is ------------------------- procedure Process_Source_File (Info : File_Info; Unit_Name : String) is + + use Unit_Name_FI_Vector_Maps; + Key : constant Unbounded_String := +Unit_Name; + Cur : constant Cursor := Unit_Present_To_FI.Find (Key); begin Units_Present.Append (Key); Unit_Languages.Include (Key, To_Language (Info.Language)); + if Has_Element (Cur) then + Unit_Present_To_FI.Reference (Cur).Append (Info); + else + Unit_Present_To_FI.Insert (Key, FI_Vectors.To_Vector (Info, 1)); + end if; end Process_Source_File; -- Start of processing for Units_From_Project @@ -1301,11 +1298,14 @@ package body Project is end loop; for Unit_Name of Units_Present loop - Add_Unit - (Units, - Ignored_Cur, - +Unit_Name, - Unit_Languages.Element (Unit_Name)); + for Info of Unit_Present_To_FI (Unit_Name) loop + Add_Unit + (Units, + Ignored_Cur, + +Unit_Name, + Info, + Unit_Languages.Element (Unit_Name)); + end loop; end loop; end Units_From_Project; diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 5b3b31c03..c17423f01 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -18,13 +18,22 @@ -- GNAT projects support +with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Containers.Ordered_Sets; +with Ada.Strings.Unbounded; + with GNAT.Strings; use GNAT.Strings; -with GNATCOLL.Projects; +with GNATCOLL.Projects; use GNATCOLL.Projects; with GNATCOLL.VFS; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; + with Inputs; -with Switches; use Switches; +with Paths; use Paths; +with Strings; use Strings; +with Switches; use Switches; +with Traces_Files; use Traces_Files; package Project is @@ -109,42 +118,73 @@ package Project is -- path of its main executable (including its suffix, for instance ".exe"). -- Otherwise, return an empty string. + ------------------------- + -- Unit identification -- + ------------------------- + + type Unique_Name (Language : Any_Language_Kind := Unit_Based_Language) is + record + Unit_Name : Ada.Strings.Unbounded.Unbounded_String; + case Language is + when File_Based_Language => + Project_Name : Ada.Strings.Unbounded.Unbounded_String; + when others => null; + end case; + end record; + -- To uniquely identify a unit, we need its unit name (or base name for a C + -- unit). For file-based languages such as C or C++, we might have homonym + -- base file names in different projects so we keep track of the project + -- name in addition. + + use type Ada.Strings.Unbounded.Unbounded_String; + + function To_Unique_Name + (Unit_Name : String; + Project : Project_Type; + Language : Some_Language) return Unique_Name; + + function Image (U : Unique_Name) return String is + (case U.Language is + when Unit_Based_Language => To_Lower (+U.Unit_Name), + when File_Based_Language => + +U.Project_Name & ":" & Fold_Filename_Casing (+U.Unit_Name)); + + function "<" (L, R : Unique_Name) return Boolean is + (Image (L) < Image (R)); + + function "=" (L, R : Unique_Name) return Boolean is + (Image (L) = Image (R)); + + package Unit_Sets is new Ada.Containers.Ordered_Sets + (Element_Type => Unique_Name); + -------------------------------------- -- Accessors for project properties -- -------------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : String; Is_Subunit : Boolean)); - -- Call Callback once for every unit of interest. Name is the lower-case - -- unit name, and Is_Subunit corresponds to the Unit_Info.Is_Subunit field - -- (see project.adb). - - procedure Enumerate_LIs (LI_Cb : access procedure (LI_Name : String)) - with Pre => Is_Project_Loaded and then not LIs_Enumerated, - Post => LIs_Enumerated; - -- Call LI_Cb once for every library information (ALI/GLI) file from a - -- project mentioned in a previous Add_Project call. - -- - -- Note that this skips LI files that are not for Ada/C sources. This is - -- expected since gnatcov processes LI files only when dealing with binary - -- traces, which support only Ada and C (not C++, for instance). - - function LIs_Enumerated return Boolean with Pre => Is_Project_Loaded; - -- Return whether Enumerate_LIs was called - - procedure Report_Units_Without_LI with Pre => LIs_Enumerated; - -- Output a warning for all units of interest for which we saw no library - -- information file. - - procedure Enumerate_SIDs (Callback : access procedure (SID_Name : String)) - with Pre => Is_Project_Loaded and then not SIDs_Enumerated, - Post => SIDs_Enumerated; - -- Invoke Callback once for every SID file corresponding to a unit of - -- interest. This emits a warning for all units of interest that have no - -- SID file. - - function SIDs_Enumerated return Boolean with Pre => Is_Project_Loaded; - -- Return whether Enumerate_SIDs was called + (Callback : access procedure (Name : Unique_Name; Is_Subunit : Boolean)); + -- Call Callback once for every unit of interest. Name is the unit name, + -- and Is_Subunit corresponds to the Unit_Info.Is_Subunit field (see + -- project.adb). + + function Is_Unit_Of_Interest + (Project : Project_Type; + Unit_Name : String; + Language : Some_Language) return Boolean; + -- Return whether the unit Unit_Name that belongs to the project Project + -- is a unit of interest. + + function Is_Unit_Of_Interest (Full_Name : String) return Boolean; + -- Same as above, but given a full name + + procedure Enumerate_SCOs_Files + (Callback : access procedure (Lib_Name : String); + Kind : Traces_Files.Trace_File_Kind) + with Pre => Is_Project_Loaded; + -- Invoke Callback once for every SCOs file (SID / ALI depending on the + -- trace mode) corresponding to a unit of interest. This emits a warning + -- for all units of interest that have no SCOs file. procedure Enumerate_Sources (Callback : access procedure From bc0023074da0bf081f521ec9e1c567ba40260c7d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 30 Jan 2023 11:18:09 +0100 Subject: [PATCH 0128/1483] Fix instrumentation of homonym sources Previous patches enhanced the support for homonym source files, enabling the user to actually be able to ignore a specific homonym source file in the project tree. There were still some issues at instrumentation time: the instrumentation of the two homonyms was done in the same unit instrumentation process, resulting in one SID being produced for the two homonym files. This patch aims at fixing this, and enhances the homonym sources test accordingly. TN: V728-002 --- .../tests/homonym-units-of-interest/test.py | 93 +++++++++++++------ tools/gnatcov/instrument.adb | 13 ++- 2 files changed, 76 insertions(+), 30 deletions(-) diff --git a/testsuite/tests/homonym-units-of-interest/test.py b/testsuite/tests/homonym-units-of-interest/test.py index b1bbf4816..6931c25bc 100644 --- a/testsuite/tests/homonym-units-of-interest/test.py +++ b/testsuite/tests/homonym-units-of-interest/test.py @@ -5,46 +5,85 @@ is not. """ -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +import os.path + +from e3.fs import sync_tree + +from SCOV.minicheck import build_and_run, check_xcov_reports from SUITE.gprutils import GPRswitches from SUITE.cutils import Wdir -from SUITE.tutils import thistest, gprfor +from SUITE.tutils import thistest, gprfor, xcov -Wdir('tmp_') +wd = Wdir('tmp_') -is_bin_traces = thistest.options.trace_mode == 'bin' +# Run the build and run in a dedicated directory -extra_prj1 = """ -package Coverage is - for Excluded_Units use ("pkg.c"); -end Coverage; -""" -prj1 = gprfor(mains=[], prjid='prj1', srcdirs=['../prj1'], objdir='obj-prj1', - extra=extra_prj1) +prj1 = gprfor(mains=[], prjid='prj1', srcdirs=['../prj1'], objdir='obj-prj1') prj2 = gprfor(mains=[], prjid='prj2', srcdirs=['../prj2'], objdir='obj-prj2') p = gprfor(mains=['test.c'], deps=['prj1', 'prj2'], srcdirs=['..']) -build_run_and_coverage( +xcov_args = build_and_run( gprsw=GPRswitches(root_project=p), covlevel='stmt+mcdc', mains=['test'], extra_coverage_args=['--annotate=xcov', '--output-dir=xcov'], - instrument_warnings_as_errors=False, ) -# The filtering of units of interest is done at a later stage for binary -# traces, and files that may be ignored in coverage report can have been -# added to gnatcov file table. This means that the shortest unique suffix, -# computed from gnatcov file table to differentiate homonym source files -# will be different from source traces. -xcov_homonoym_filename = 'prj2-pkg.c.xcov' if is_bin_traces else 'pkg.c.xcov' -check_xcov_reports( - '*.xcov', - { - xcov_homonoym_filename: {'!': {4}}, - 'test.c.xcov': {'+': {7, 8, 9}} - }, - 'xcov' -) +# Now onto coverage. Try to ignore pkg.c in prj1, and in prj2 in two different +# gnatcov coverage invocations, using the project attributes as this can't be +# specified unambiguously on the command line. +# +# This checks two things: +# +# * a user can ignore a specific source file even if it has an homonym in +# the project tree. Note that the user would probably have the same +# project for instrument / coverage, but for testing purposes, we also +# need to check the second point. +# +# * gnatcov instrument does not generate a single SID file for the two +# homonym source files. + +ignore_pkg = """ +package Coverage is + for Excluded_Units use ("pkg.c"); +end Coverage; +""" + +wd.to_homedir() + + +def check_report(prj_ignore, prj_of_interest): + """ + Check that the report is correct when the homonym source file (pkg.c) is + ignored in prj_ignore and of interest in prj_of_interest. + """ + subdir = f'tmp_cov_ignore_{prj_ignore}' + wd = Wdir(subdir) + sync_tree(os.path.join('..', 'tmp_'), '.') + gprfor(mains=[], prjid=prj_ignore, srcdirs=[f'../{prj_ignore}'], + objdir=f'obj-{prj_ignore}', extra=ignore_pkg) + xcov(xcov_args) + + # The filtering of units of interest is done at a later stage for binary + # traces, and files that may be ignored in the coverage report can have + # been added to gnatcov's file table. This means that the shortest unique + # suffix computed from gnatcov file table to differentiate homonym source + # files will be different from source traces. + xcov_homonoym_filename = ( + f'{prj_of_interest}-pkg.c.xcov' if thistest.options.trace_mode == 'bin' + else 'pkg.c.xcov' + ) + check_xcov_reports( + '*.xcov', + { + xcov_homonoym_filename: {'!': {4}}, + 'test.c.xcov': {'+': {7, 8, 9}} + }, + 'xcov' + ) + wd.to_homedir() + +check_report('prj1', 'prj2') +check_report('prj2', 'prj1') thistest.result() diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 5837925d8..334c280ee 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -106,7 +106,8 @@ package body Instrument is package Library_Unit_Maps is new Ada.Containers.Indefinite_Ordered_Maps (String, Library_Unit_Info_Access); -- Map to associate a list of compilation units to instrument to a library - -- unit (indexed by the library unit name). + -- unit (indexed by the library unit name, i.e. the unit name or the + -- full name depending on the language kind for the library unit). -- -- For file-based languages, the library unit only has one compilation -- unit associated to it (that is the library unit itself, for which the @@ -263,7 +264,7 @@ package body Instrument is & "sid"); end; when File_Based_Language => - SID_Basename := +(LU_Name & ".sid"); + SID_Basename := +(Ada.Directories.Simple_Name (LU_Name & ".sid")); end case; return String'(+Output_Directory.Full_Name) / (+SID_Basename); @@ -405,13 +406,19 @@ package body Instrument is end if; declare + use GNATCOLL.VFS; + CU_Name : constant Compilation_Unit_Name := To_Compilation_Unit_Name (Source_File); Unit_Name : constant String := (case CU_Name.Language_Kind is when Unit_Based_Language => To_Ada (CU_Name.Unit), - when File_Based_Language => +CU_Name.Filename); + + -- For file-based languages, we need to use the full + -- name to account for homonyms. + + when File_Based_Language => +Source_File.File.Full_Name); begin -- Get the vector in which we will record the compilation units From ba7388759a9730511c3784b9b47ba636068797a4 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 27 Jan 2023 17:30:05 +0100 Subject: [PATCH 0129/1483] Instrument.C: fix name used for the top level scope We can't rely on the Get_Unique_Name API as it freezes the files table and forbids insertions of filenames afterwards. Using the simple name here is unambiguous, as scopes are displayed in index-based reports (xml and dhtml), in each file report. The issue was never visible in production, as assertion are deactivated. It was not visible in dev as well as we probably don't have tests running instrumentation over multiple C files. TN: V923-016 --- tools/gnatcov/instrument-c.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 7054c41e6..7d135aed8 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -679,7 +679,7 @@ package body Instrument.C is New_Scope_Ent : constant Scope_Entity_Acc := new Scope_Entity' (From => SCO_Id (SCOs.SCO_Table.Last + 1), To => No_SCO_Id, - Name => +Get_Unique_Name (SFI), + Name => +Get_Simple_Name (SFI), Sloc => (Line => 0, Column => 0), Children => Scope_Entities_Vectors.Empty_Vector, Parent => null); From 4c3b5f2879fc8c74ae3fd85c98bfd71c8ff5d1e7 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 1 Feb 2023 13:35:37 +0000 Subject: [PATCH 0130/1483] Testsuite: build SPARK tests in Ada 2022 mode Some SPARK tests (red black trees, currently XFAILed) use Ada 2022 specific syntax (for instance, brackets aggregates). Use the Ada 2022 mode instead of Ada 2012 for them. TN: V830-008 --- testsuite/testsuite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 391fda3fd..cbc3d477f 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1104,10 +1104,10 @@ def set_up(self): else: setattr(args, attr_cargs_ada, cargs_ada + " -gnat05") - # Most SPARK testcases require Ada 2012 + # Most SPARK testcases require Ada 2022 if getattr(args, "spark_tests"): - setattr(args, attr_cargs_ada, cargs_ada + " -gnat12") + setattr(args, attr_cargs_ada, cargs_ada + " -gnat2022") # Expect an explicit -gnatec if we're running for qualification From bc508fc466405a57a7426c3f585db48c5d06833a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 3 Feb 2023 09:01:09 +0000 Subject: [PATCH 0131/1483] gnatcov_bits_specific.adb: minor reformatting --- tools/gnatcov/gnatcov_bits_specific.adb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index b580bc2d6..5c1a8cb57 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1875,8 +1875,7 @@ begin procedure Process_Source_Trace (Trace_File_Name : String) is procedure On_Trace_Info - (Kind : Traces_Source.Supported_Info_Kind; - Data : String); + (Kind : Traces_Source.Supported_Info_Kind; Data : String); -- Callback for Read_Source_Trace_File procedure Read_Source_Trace_File is new @@ -1887,10 +1886,12 @@ begin Trace_File : Trace_File_Element_Acc; Result : Read_Result; + ------------------- + -- On_Trace_Info -- + ------------------- + procedure On_Trace_Info - (Kind : Traces_Source.Supported_Info_Kind; - Data : String) - is + (Kind : Traces_Source.Supported_Info_Kind; Data : String) is begin Update_From_Source_Trace (Trace_File.all, Kind, Data); end On_Trace_Info; From def37fbac2360b27e5b3da0fe7e2e8baea8a3098 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 2 Feb 2023 14:03:49 +0000 Subject: [PATCH 0132/1483] Minor reformatting/comment update --- tools/gnatcov/gnatcov_bits_specific.adb | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 5c1a8cb57..015db40d3 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -2263,13 +2263,16 @@ begin then Standard_Output else File'Access); + procedure Print_Ignored_File (FI : Files_Table.File_Info); + -- Assuming that FI designates an ignored file, print its + -- filename and its ignored status. + procedure Print_Unit_Name (Name : Unique_Name); - -- Print the name of the file and if it was always or - -- sometimes ignored on the report, if it was ignored at - -- some point during the coverage analysis. + -- Print the name of the file - procedure Print_Ignored_File - (FI : Files_Table.File_Info); + ------------------------ + -- Print_Ignored_File -- + ------------------------ procedure Print_Ignored_File (FI : Files_Table.File_Info) is @@ -2284,6 +2287,10 @@ begin end if; end Print_Ignored_File; + --------------------- + -- Print_Unit_Name -- + --------------------- + procedure Print_Unit_Name (Name : Unique_Name) is begin Put_Line (Output.all, +Name.Unit_Name); From e277645c8fa718d5b3dae8a7e49745e635521439 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 2 Feb 2023 14:07:58 +0000 Subject: [PATCH 0133/1483] instrument.adb: remove useless USE clause TN: V728-002 --- tools/gnatcov/instrument.adb | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 334c280ee..fda088569 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -406,8 +406,6 @@ package body Instrument is end if; declare - use GNATCOLL.VFS; - CU_Name : constant Compilation_Unit_Name := To_Compilation_Unit_Name (Source_File); From 83bfc52d3276231e0092f46a5406de68f54c19b0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 2 Feb 2023 14:10:07 +0000 Subject: [PATCH 0134/1483] project.ads: rename Unique_Name to Project_Unit The Files_Table package defines Get_Unique_Name, with different semantics. Rename project.ads' to avoid confusion. TN: V728-002 --- tools/gnatcov/annotations-report.adb | 12 ++++------ tools/gnatcov/coverage-source.adb | 20 ++++++++-------- tools/gnatcov/coverage-source.ads | 8 +++---- tools/gnatcov/gnatcov_bits_specific.adb | 12 +++++----- tools/gnatcov/project.adb | 32 ++++++++++++------------- tools/gnatcov/project.ads | 16 ++++++------- 6 files changed, 49 insertions(+), 51 deletions(-) diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 6445f6ed1..dd36e7b51 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -645,19 +645,17 @@ package body Annotations.Report is New_Line (Output.all); declare - procedure Print_Ignored_File - (FI : Files_Table.File_Info); + procedure Print_Ignored_File (FI : Files_Table.File_Info); -- Print the name of the file and its ignore status on the report - procedure Print_Unit_Name (Name : Unique_Name); + procedure Print_Unit_Name (Unit : Project_Unit); -- Print Name on the report ------------------------ -- Print_Ignored_File -- ------------------------ - procedure Print_Ignored_File - (FI : Files_Table.File_Info) is + procedure Print_Ignored_File (FI : Files_Table.File_Info) is begin if FI.Ignore_Status = Files_Table.Sometimes then Put_Line (Output.all, @@ -672,9 +670,9 @@ package body Annotations.Report is -- Print_Unit_Name -- --------------------- - procedure Print_Unit_Name (Name : Unique_Name) is + procedure Print_Unit_Name (Unit : Project_Unit) is begin - Put_Line (Output.all, +Name.Unit_Name); + Put_Line (Output.all, +Unit.Unit_Name); end Print_Unit_Name; begin Iterate_On_Unit_List diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 4e2524823..3eee24d33 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -281,16 +281,16 @@ package body Coverage.Source is Unit_List := Unit_Sets.Empty_Set; end Invalidate_Unit_List; - ------------------- - -- Add_Unit_Name -- - ------------------- + -------------- + -- Add_Unit -- + -------------- - procedure Add_Unit_Name (Name : Unique_Name) is + procedure Add_Unit (Unit : Project_Unit) is begin if not Unit_List_Invalidated then - Unit_List.Include (Name); + Unit_List.Include (Unit); end if; - end Add_Unit_Name; + end Add_Unit; --------------------------- -- Unit_Name_For_Subunit -- @@ -309,7 +309,7 @@ package body Coverage.Source is Going => Ada.Strings.Backward); if Unit_List.Contains - (Unique_Name' + (Project_Unit' (Language => Unit_Based_Language, Unit_Name => US.To_Unbounded_String @@ -432,7 +432,7 @@ package body Coverage.Source is -------------------------- procedure Iterate_On_Unit_List - (Process_Unit : not null access procedure (Name : Unique_Name); + (Process_Unit : not null access procedure (Name : Project_Unit); Process_Source_File : not null access procedure (FI : File_Info)) is begin @@ -463,7 +463,7 @@ package body Coverage.Source is if not Unit_List_Invalidated then Ada.Containers.Count_Type'Output (CSS, Unit_List.Length); for N of Unit_List loop - Unique_Name'Output (CSS, N); + Project_Unit'Output (CSS, N); end loop; end if; end if; @@ -617,7 +617,7 @@ package body Coverage.Source is end if; US.Unbounded_String'Read (CLS, Dummy); else - Unit_List.Include (Unique_Name'Input (CLS)); + Unit_List.Include (Project_Unit'Input (CLS)); end if; end loop; end if; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 44f4d268e..2de4ca3dc 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -104,9 +104,9 @@ package Coverage.Source is -- message is used for logging purposes, so that users can find out why we -- cannot dump the list of units of interest. - procedure Add_Unit_Name (Name : Unique_Name); - -- Add Name to the list of names for units of interest. For convenience, do - -- nothing if it is invalid. + procedure Add_Unit (Unit : Project_Unit); + -- Add Unit to the list of units of interest. For convenience, do nothing + -- if it is invalid. procedure Compute_Unit_Name_For_Ignored_Sources; -- Compute the name of the owning unit for each known source file that is @@ -117,7 +117,7 @@ package Coverage.Source is -- unit names, linking them to the list of ignored source files. procedure Iterate_On_Unit_List - (Process_Unit : not null access procedure (Name : Unique_Name); + (Process_Unit : not null access procedure (Name : Project_Unit); Process_Source_File : not null access procedure (FI : File_Info)) with Pre => Unit_List_Is_Valid; -- Call Unit_Callback for each unit of interest, passing to it the name of diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 015db40d3..679acea10 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1677,17 +1677,17 @@ begin -- Build the list of units of interest from project files option declare - procedure Add_Unit (Name : Unique_Name; Is_Subunit : Boolean); + procedure Add_Unit (Unit : Project_Unit; Is_Subunit : Boolean); -- Add Name to the list of names for units of interest -------------- -- Add_Unit -- -------------- - procedure Add_Unit (Name : Unique_Name; Is_Subunit : Boolean) is + procedure Add_Unit (Unit : Project_Unit; Is_Subunit : Boolean) is pragma Unreferenced (Is_Subunit); begin - Add_Unit_Name (Name); + Add_Unit (Unit); end Add_Unit; begin Enumerate_Units_Of_Interest (Add_Unit'Access); @@ -2267,7 +2267,7 @@ begin -- Assuming that FI designates an ignored file, print its -- filename and its ignored status. - procedure Print_Unit_Name (Name : Unique_Name); + procedure Print_Unit_Name (Unit : Project_Unit); -- Print the name of the file ------------------------ @@ -2291,9 +2291,9 @@ begin -- Print_Unit_Name -- --------------------- - procedure Print_Unit_Name (Name : Unique_Name) is + procedure Print_Unit_Name (Unit : Project_Unit) is begin - Put_Line (Output.all, +Name.Unit_Name); + Put_Line (Output.all, +Unit.Unit_Name); end Print_Unit_Name; begin diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 58e9e2b7c..32af1b2b9 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -149,7 +149,7 @@ package body Project is end record; package Unit_Maps is new Ada.Containers.Indefinite_Ordered_Maps - (Key_Type => Unique_Name, + (Key_Type => Project_Unit, Element_Type => Unit_Info); procedure Add_Unit @@ -159,7 +159,7 @@ package body Project is Info : File_Info; Language : Some_Language); -- Add a Unit_Info entry to Units. The key for this new entry (which is a - -- Unique_Name) is computed using the Original_Name, and the + -- Project_Unit) is computed using the Original_Name, and the -- Info.Project_Name if the unit is of a file-based language. procedure Warn_Missing_Info (What_Info : String; Unit : in out Unit_Info); @@ -229,23 +229,23 @@ package body Project is -- Return whether Filename can be found among the sources of the -- configured Ada runtime. - -------------------- - -- To_Unique_Name -- - -------------------- + --------------------- + -- To_Project_Unit -- + --------------------- - function To_Unique_Name + function To_Project_Unit (Unit_Name : String; Project : Project_Type; - Language : Some_Language) return Unique_Name + Language : Some_Language) return Project_Unit is - U : Unique_Name (Language_Kind (Language)); + U : Project_Unit (Language_Kind (Language)); begin U.Unit_Name := +Unit_Name; if U.Language = File_Based_Language then U.Project_Name := +Project.Name; end if; return U; - end To_Unique_Name; + end To_Project_Unit; --------- -- "+" -- @@ -283,8 +283,8 @@ package body Project is and then Info.Unit_Part = Unit_Spec); Orig_Name : constant Unbounded_String := +Fold_Filename_Casing (Original_Name); - Unit_Name : constant Unique_Name := - To_Unique_Name (Original_Name, Info.Project, Language); + Unit_Name : constant Project_Unit := + To_Project_Unit (Original_Name, Info.Project, Language); begin -- Disable warnings for C/C++ header units as they do not have a proper -- library file. @@ -455,7 +455,7 @@ package body Project is --------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Unique_Name; Is_Subunit : Boolean)) + (Callback : access procedure (Name : Project_Unit; Is_Subunit : Boolean)) is use Unit_Maps; begin @@ -477,8 +477,8 @@ package body Project is Unit_Name : String; Language : Some_Language) return Boolean is - U : constant Unique_Name := - To_Unique_Name (Unit_Name, Project, Language); + U : constant Project_Unit := + To_Project_Unit (Unit_Name, Project, Language); begin return Unit_Map.Contains (U); end Is_Unit_Of_Interest; @@ -539,7 +539,7 @@ package body Project is Cur : constant Cursor := Unit_Map.Find - (To_Unique_Name + (To_Project_Unit (U, Project_Type (LI.LI_Project.all), To_Language (LI.Source.Language))); @@ -1023,7 +1023,7 @@ package body Project is for Cur in Inc_Units.Iterate loop declare use Unit_Maps; - K : constant Unique_Name := Key (Cur); + K : constant Project_Unit := Key (Cur); begin if not Exc_Units.Contains (K) then declare diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index c17423f01..c08251897 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -122,7 +122,7 @@ package Project is -- Unit identification -- ------------------------- - type Unique_Name (Language : Any_Language_Kind := Unit_Based_Language) is + type Project_Unit (Language : Any_Language_Kind := Unit_Based_Language) is record Unit_Name : Ada.Strings.Unbounded.Unbounded_String; case Language is @@ -138,32 +138,32 @@ package Project is use type Ada.Strings.Unbounded.Unbounded_String; - function To_Unique_Name + function To_Project_Unit (Unit_Name : String; Project : Project_Type; - Language : Some_Language) return Unique_Name; + Language : Some_Language) return Project_Unit; - function Image (U : Unique_Name) return String is + function Image (U : Project_Unit) return String is (case U.Language is when Unit_Based_Language => To_Lower (+U.Unit_Name), when File_Based_Language => +U.Project_Name & ":" & Fold_Filename_Casing (+U.Unit_Name)); - function "<" (L, R : Unique_Name) return Boolean is + function "<" (L, R : Project_Unit) return Boolean is (Image (L) < Image (R)); - function "=" (L, R : Unique_Name) return Boolean is + function "=" (L, R : Project_Unit) return Boolean is (Image (L) = Image (R)); package Unit_Sets is new Ada.Containers.Ordered_Sets - (Element_Type => Unique_Name); + (Element_Type => Project_Unit); -------------------------------------- -- Accessors for project properties -- -------------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Unique_Name; Is_Subunit : Boolean)); + (Callback : access procedure (Name : Project_Unit; Is_Subunit : Boolean)); -- Call Callback once for every unit of interest. Name is the unit name, -- and Is_Subunit corresponds to the Unit_Info.Is_Subunit field (see -- project.adb). From 50c3b3eafe2c7dc6878edf900eaad134c0056c91 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 3 Feb 2023 15:42:42 +0000 Subject: [PATCH 0135/1483] checkpoints.ads: minor reformatting --- tools/gnatcov/checkpoints.ads | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 3384f0c66..98e925089 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -19,7 +19,7 @@ -- This unit controls the generation and processing of coverage state -- checkpoint files for incremental coverage. -with Ada.Streams; use Ada.Streams; +with Ada.Streams; use Ada.Streams; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Interfaces; @@ -27,7 +27,7 @@ with GNAT.Regexp; with Types; use Types; with Coverage; -with Files_Table; use Files_Table; +with Files_Table; use Files_Table; with SC_Obligations; use SC_Obligations; package Checkpoints is From 0eb11dc5f454744e31745cc1748423f0a1cb8579 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 3 Feb 2023 15:53:38 +0000 Subject: [PATCH 0136/1483] files_table.adb: minor typo fix --- tools/gnatcov/files_table.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 3819a971b..c233e9523 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -1239,7 +1239,7 @@ package body Files_Table is end loop; -- Then, for each set of aliased files, find the shortest unique suffix. - -- Note that the loops below will not get executed ofter (aliases are + -- Note that the loops below will not get executed often (aliases are -- rare), so efficiency should not be an issue. for Alias_Set of Alias_Map loop From 9bbd935d81b435fbf30470c34c7305530fb00f01 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 3 Feb 2023 15:54:15 +0000 Subject: [PATCH 0137/1483] gnatcov_bits_specific.adb: rewrap comment --- tools/gnatcov/gnatcov_bits_specific.adb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 679acea10..cddd2b569 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -2193,10 +2193,9 @@ begin end if; end; - -- Reconstruct unit names for ignored source files. - -- This is done before loading checkpoints, because this will already - -- have been done for the files in the checkpoints when creating - -- them. + -- Reconstruct unit names for ignored source files. This is done + -- before loading checkpoints, because this will already have been + -- done for the files in the checkpoints when creating them. if Project.Is_Project_Loaded and then Coverage.Source.Unit_List_Is_Valid From a28c20b57751de284ff227d1959f38f9bf06177f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 6 Feb 2023 12:12:59 +0000 Subject: [PATCH 0138/1483] Revert "Add in the file table files containing inlined subprogram calls" This reverts commit e1eff57055dcd93b6b2cb4c459ebfbdb0c563d3b, which made gnatcov insert entries in its files table for units that are not of interest, leading gnatcov to consider that such entries conflict with other entries ("same base name" warning). The notice messages meant to be fixed under e1eff57055dcd93b6b2cb4c459ebfbdb0c563d3b can actually afford not having a source file, which was the case before 2711b825c355cfbcf25beaac1d37ef51dc92e400. It is not ideal, but fixing this without violating invariants would imply tricky extensions for the files table: we could go this way one day (for instance if/when simple name indexes can be lifted after binary traces support is dropped), but in the meantime let's work around this. TN: V914-024 --- tools/gnatcov/traces_elf.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/traces_elf.adb b/tools/gnatcov/traces_elf.adb index 23fd8650c..c39f02c08 100644 --- a/tools/gnatcov/traces_elf.adb +++ b/tools/gnatcov/traces_elf.adb @@ -3155,7 +3155,7 @@ package body Traces_Elf is else Get_Index_From_Full_Name (Full_Name => Filenames.Element (Inlined_Subp.File).all, Kind => Stub_File, - Insert => True)); + Insert => False)); Info : Address_Info_Acc := new Address_Info' (Kind => Inlined_Subprogram_Addresses, From ca2eb7e91c046806cbe46dec31eb89201bcc0e61 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 6 Feb 2023 12:19:15 +0000 Subject: [PATCH 0139/1483] Slocs.Abridged_Image: do not compute file name unless required In some cases, this function is supposed not to include the sloc file name in its result. For some of these cases, there can be no file at all, so computing its file name triggers a crash. Do not compute it unless required to avoid such crashes. TN: V914-024 --- tools/gnatcov/slocs.adb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/slocs.adb b/tools/gnatcov/slocs.adb index f8f1d4f52..aa39b0d88 100644 --- a/tools/gnatcov/slocs.adb +++ b/tools/gnatcov/slocs.adb @@ -101,15 +101,12 @@ package body Slocs is Ref : Source_Location; Unique_Name : Boolean := False) return String is - function Get_Name (File : Source_File_Index) return String is + function File_Name return String is (if Unique_Name - then Get_Unique_Name (File) - else Get_Simple_Name (File)); + then Get_Unique_Name (Sloc.Source_File) + else Get_Simple_Name (Sloc.Source_File)); Show_File, Show_Line, Show_Column : Boolean; - - File_Name : constant String := - Get_Name (Sloc.Source_File); begin if Sloc.L = No_Local_Location then From 238acbe132046d93d58f5fefc6a432047323fd33 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 2 Feb 2023 16:35:16 +0000 Subject: [PATCH 0140/1483] Fix doc for Coverage.Source.Iterate_On_Unit_List For eng/cov/gnatcoverage#17 --- tools/gnatcov/coverage-source.ads | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 2de4ca3dc..4a3ef645d 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -120,10 +120,11 @@ package Coverage.Source is (Process_Unit : not null access procedure (Name : Project_Unit); Process_Source_File : not null access procedure (FI : File_Info)) with Pre => Unit_List_Is_Valid; - -- Call Unit_Callback for each unit of interest, passing to it the name of - -- the unit, and call File_Callback for each (sometimes or always) ignored - -- source file in the unit. - -- Unit_Callback is called before iterating on the ignored files for that + -- Call Process_Unit for each unit of interest, passing to it the name of + -- the unit, and call Process_Source_File for each (sometimes or always) + -- ignored source file in the unit. + -- + -- Process_Unit is called before iterating on the ignored files for that -- unit. ----------------- From 7b81a1d299e9eaf5bd69f444ac7b1759791e6313 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 2 Feb 2023 16:48:41 +0000 Subject: [PATCH 0141/1483] Refactor duplicated code For eng/cov/gnatcoverage#17 --- tools/gnatcov/annotations-report.adb | 37 +--------------- tools/gnatcov/coverage-source.adb | 41 +++++++++++++++++- tools/gnatcov/coverage-source.ads | 6 +++ tools/gnatcov/gnatcov_bits_specific.adb | 56 ++++--------------------- 4 files changed, 56 insertions(+), 84 deletions(-) diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index dd36e7b51..dceba81f3 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -27,7 +27,6 @@ with Coverage_Options; use Coverage_Options; with Coverage; use Coverage; with Coverage.Source; use Coverage.Source; with Coverage.Tags; use Coverage.Tags; -with Files_Table; with SC_Obligations; with Project; use Project; with Switches; @@ -643,41 +642,7 @@ package body Annotations.Report is if Pp.Dump_Units then Pp.Chapter ("UNITS OF INTEREST"); New_Line (Output.all); - declare - - procedure Print_Ignored_File (FI : Files_Table.File_Info); - -- Print the name of the file and its ignore status on the report - - procedure Print_Unit_Name (Unit : Project_Unit); - -- Print Name on the report - - ------------------------ - -- Print_Ignored_File -- - ------------------------ - - procedure Print_Ignored_File (FI : Files_Table.File_Info) is - begin - if FI.Ignore_Status = Files_Table.Sometimes then - Put_Line (Output.all, - " " & FI.Unique_Name.all & " sometimes ignored"); - elsif FI.Ignore_Status = Files_Table.Always then - Put_Line (Output.all, - " " & FI.Unique_Name.all & " always ignored"); - end if; - end Print_Ignored_File; - - --------------------- - -- Print_Unit_Name -- - --------------------- - - procedure Print_Unit_Name (Unit : Project_Unit) is - begin - Put_Line (Output.all, +Unit.Unit_Name); - end Print_Unit_Name; - begin - Iterate_On_Unit_List - (Print_Unit_Name'Access, Print_Ignored_File'Access); - end; + Report_Units (Output.all); end if; New_Line (Output.all); diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 3eee24d33..e1a335366 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -24,7 +24,6 @@ with Ada.Streams; use Ada.Streams; with Ada.Strings.Fixed; with Ada.Strings.Unbounded; with Ada.Tags; -with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Deallocation; with Interfaces; @@ -447,6 +446,46 @@ package body Coverage.Source is 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 : Project_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 : Project_Unit) is + begin + Put_Line (File, +Unit.Unit_Name); + 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 -- --------------------- diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 4a3ef645d..9b7bccff6 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -16,6 +16,8 @@ -- of the license. -- ------------------------------------------------------------------------------ +with Ada.Text_IO; use Ada.Text_IO; + with Checkpoints; use Checkpoints; with Files_Table; use Files_Table; with Instrument; use Instrument; @@ -127,6 +129,10 @@ package Coverage.Source is -- Process_Unit is called before iterating on the ignored files for that -- unit. + procedure Report_Units (File : File_Type); + -- Print a report about units of interest as well as ignored source files + -- to File. + ----------------- -- Checkpoints -- ----------------- diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index cddd2b569..352ceca6a 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -2253,55 +2253,17 @@ begin -- file or on the standard output, do it now. if Dump_Units and then not Dump_Units_In_Report then - declare - File : aliased File_Type; - -- Output file for the list of names for units of interest - - Output : constant access File_Type := - (if Dump_Units_Filename = null - then Standard_Output - else File'Access); - - procedure Print_Ignored_File (FI : Files_Table.File_Info); - -- Assuming that FI designates an ignored file, print its - -- filename and its ignored status. - - procedure Print_Unit_Name (Unit : Project_Unit); - -- Print the name of the file - - ------------------------ - -- Print_Ignored_File -- - ------------------------ - - procedure Print_Ignored_File - (FI : Files_Table.File_Info) is - begin - if FI.Ignore_Status = Files_Table.Sometimes then - Put_Line (Output.all, " " & FI.Unique_Name.all - & " sometimes ignored"); - elsif FI.Ignore_Status = Files_Table.Always then - Put_Line (Output.all, " " & FI.Unique_Name.all - & " always ignored"); - - end if; - end Print_Ignored_File; - - --------------------- - -- Print_Unit_Name -- - --------------------- - - procedure Print_Unit_Name (Unit : Project_Unit) is + if Dump_Units_Filename = null then + Report_Units (Standard_Output); + else + declare + File : File_Type; begin - Put_Line (Output.all, +Unit.Unit_Name); - end Print_Unit_Name; - - begin - if Dump_Units_Filename /= null then Create (File, Name => Dump_Units_Filename.all); - end if; - Iterate_On_Unit_List - (Print_Unit_Name'Access, Print_Ignored_File'Access); - end; + Report_Units (File); + Close (File); + end; + end if; end if; -- Generate annotated reports From c5b0f124c64efe49c6e621e14d6a63e514434985 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 3 Feb 2023 08:38:19 +0000 Subject: [PATCH 0142/1483] project.adb: replace Unit_Info.Is_Subunit with Is_Stub While the former was specific to Ada, the latter also covers C/C++ header files. While no external behavior change is expected, this internal refactoring will allow upcoming changes to process "stubs" correctly when dumping the list of units of interest and ignored files. For eng/cov/gnatcoverage#17 --- tools/gnatcov/gnatcov_bits_specific.adb | 6 ++-- tools/gnatcov/project.adb | 43 ++++++++++++++----------- tools/gnatcov/project.ads | 4 +-- 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 352ceca6a..9156d5bb9 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1677,15 +1677,15 @@ begin -- Build the list of units of interest from project files option declare - procedure Add_Unit (Unit : Project_Unit; Is_Subunit : Boolean); + procedure Add_Unit (Unit : Project_Unit; Is_Stub : Boolean); -- Add Name to the list of names for units of interest -------------- -- Add_Unit -- -------------- - procedure Add_Unit (Unit : Project_Unit; Is_Subunit : Boolean) is - pragma Unreferenced (Is_Subunit); + procedure Add_Unit (Unit : Project_Unit; Is_Stub : Boolean) is + pragma Unreferenced (Is_Stub); begin Add_Unit (Unit); end Add_Unit; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 32af1b2b9..7536542f1 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -133,10 +133,13 @@ package body Project is -- Whether we found at least one source file in the projects of interest -- that matches this unit. - Is_Subunit : Boolean; - -- Whether this unit is actually a subunit. We consider that subunits - -- are not units of their own (in particular they don't have their own - -- LI file), but we still allow them to appear in unit lists. + Is_Stub : Boolean; + -- Whether this record describes a source file that is not a bona fide + -- unit of interest: a subunit (Ada) or a header file (C/C++). + -- + -- Such source files are not units of their own (in particular they + -- don't have their own LI file), but we still need them to appear in + -- unit lists, for reporting purposes. Language : Some_Language; -- Language for this unit @@ -277,26 +280,30 @@ package body Project is Info : File_Info; Language : Some_Language) is - Ignored_Inserted : Boolean; - Is_Header : constant Boolean := - (To_Language (Info.Language) in C_Family_Language - and then Info.Unit_Part = Unit_Spec); - Orig_Name : constant Unbounded_String := + Unit_Part : constant Unit_Parts := Info.Unit_Part; + Is_Stub : constant Boolean := + (case Language is + when C_Family_Language => Unit_Part = Unit_Spec, + when Ada_Language => Unit_Part = Unit_Separate); + + Orig_Name : constant Unbounded_String := +Fold_Filename_Casing (Original_Name); - Unit_Name : constant Project_Unit := + Unit_Name : constant Project_Unit := To_Project_Unit (Original_Name, Info.Project, Language); + + Ignored_Inserted : Boolean; begin - -- Disable warnings for C/C++ header units as they do not have a proper + -- Disable warnings for stub units as they do not have a corresponding -- library file. Units.Insert (Key => Unit_Name, New_Item => (Original_Name => Orig_Name, Present_In_Projects => False, - Is_Subunit => False, + Is_Stub => Is_Stub, Language => Language, - LI_Seen => Is_Header, - Warned_About_Missing_Info => Is_Header), + LI_Seen => Is_Stub, + Warned_About_Missing_Info => Is_Stub), Position => Cur, Inserted => Ignored_Inserted); end Add_Unit; @@ -455,7 +462,7 @@ package body Project is --------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Project_Unit; Is_Subunit : Boolean)) + (Callback : access procedure (Name : Project_Unit; Is_Stub : Boolean)) is use Unit_Maps; begin @@ -463,7 +470,7 @@ package body Project is declare Info : Unit_Info renames Reference (Unit_Map, Cur); begin - Callback (Key (Cur), Info.Is_Subunit); + Callback (Key (Cur), Info.Is_Stub); end; end loop; end Enumerate_Units_Of_Interest; @@ -556,7 +563,7 @@ package body Project is -- Now warn about units of interest that have no SCOs file for UI of Unit_Map loop - if not UI.Is_Subunit and then not UI.LI_Seen then + if not UI.LI_Seen then case Kind is when Binary_Trace_File => Warn_Missing_Info ("ALI", UI); @@ -1002,8 +1009,6 @@ package body Project is Unit_Name, Info, To_Language (Info.Language)); - Inc_Units.Reference (Cur).Is_Subunit := - Info.Unit_Part = Unit_Separate; end if; end Process_Source_File; diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index c08251897..acc27145c 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -163,9 +163,9 @@ package Project is -------------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Project_Unit; Is_Subunit : Boolean)); + (Callback : access procedure (Name : Project_Unit; Is_Stub : Boolean)); -- Call Callback once for every unit of interest. Name is the unit name, - -- and Is_Subunit corresponds to the Unit_Info.Is_Subunit field (see + -- and Is_Stub corresponds to the Unit_Info.Is_Stub field (see -- project.adb). function Is_Unit_Of_Interest From 899d316d1d0f04ce0cfc68905452f61ddd296294 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 3 Feb 2023 09:02:26 +0000 Subject: [PATCH 0143/1483] gnatcov_bits_specific.adb: reorder context clauses For eng/cov/gnatcoverage#17 --- tools/gnatcov/gnatcov_bits_specific.adb | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 9156d5bb9..c824ff7ab 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -30,32 +30,32 @@ with GNAT.Strings; use GNAT.Strings; with Snames; with ALI_Files; -with Annotations; use Annotations; with Annotations.Dynamic_Html; with Annotations.Html; +with Annotations.Report; with Annotations.Xcov; with Annotations.Xml; -with Annotations.Report; -with Calendar_Utils; +with Annotations; use Annotations; +with Binary_Files; with CFG_Dump; +with Calendar_Utils; with Check_SCOs; with Checkpoints; with Command_Line; use Command_Line; use Command_Line.Parser; with Command_Line_Support; with Convert; -with Coverage; use Coverage; with Coverage.Source; use Coverage.Source; with Coverage.Tags; use Coverage.Tags; +with Coverage; use Coverage; with Coverage_Options; use Coverage_Options; with Decision_Map; use Decision_Map; with Disassemble_Insn_Properties; -with Binary_Files; with Execs_Dbase; use Execs_Dbase; with Files_Table; use Files_Table; with Inputs; use Inputs; -with Instrument; use Instrument; with Instrument.Input_Traces; +with Instrument; use Instrument; with Object_Locations; with Outputs; use Outputs; with Perf_Counters; @@ -68,13 +68,13 @@ with Strings; use Strings; with Switches; use Switches; with Temp_Dirs; use Temp_Dirs; with Traces; use Traces; +with Traces_Dbase; use Traces_Dbase; +with Traces_Disa; +with Traces_Dump; with Traces_Elf; use Traces_Elf; +with Traces_Files; use Traces_Files; with Traces_Files_Registry; use Traces_Files_Registry; with Traces_Names; use Traces_Names; -with Traces_Dump; -with Traces_Files; use Traces_Files; -with Traces_Dbase; use Traces_Dbase; -with Traces_Disa; with Traces_Source; with Version; From 138ab58b2c3e44de998a79e0cdd2ff4c0a824896 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 3 Feb 2023 11:00:39 +0000 Subject: [PATCH 0144/1483] Fix loading of preprocessing commands for ignored source files The corresponding code path was not exercized, and triggered an precondition failure (Remap_SFI called for an ignored source file). For eng/cov/gnatcoverage#17 --- testsuite/tests/ignored-c-file/foo.c | 5 ++ testsuite/tests/ignored-c-file/test.c | 8 ++++ testsuite/tests/ignored-c-file/test.py | 28 +++++++++++ tools/gnatcov/instrument-checkpoints.adb | 61 +++++++++++++----------- 4 files changed, 73 insertions(+), 29 deletions(-) create mode 100644 testsuite/tests/ignored-c-file/foo.c create mode 100644 testsuite/tests/ignored-c-file/test.c create mode 100644 testsuite/tests/ignored-c-file/test.py diff --git a/testsuite/tests/ignored-c-file/foo.c b/testsuite/tests/ignored-c-file/foo.c new file mode 100644 index 000000000..e78bea7cd --- /dev/null +++ b/testsuite/tests/ignored-c-file/foo.c @@ -0,0 +1,5 @@ +int +foo (int n) +{ + return n; +} diff --git a/testsuite/tests/ignored-c-file/test.c b/testsuite/tests/ignored-c-file/test.c new file mode 100644 index 000000000..0a6cb91c2 --- /dev/null +++ b/testsuite/tests/ignored-c-file/test.c @@ -0,0 +1,8 @@ +extern int foo (int n); + +int +main (void) +{ + foo (1); + return 0; +} diff --git a/testsuite/tests/ignored-c-file/test.py b/testsuite/tests/ignored-c-file/test.py new file mode 100644 index 000000000..4482a7d70 --- /dev/null +++ b/testsuite/tests/ignored-c-file/test.py @@ -0,0 +1,28 @@ +""" +Check that ignoring a C file file works as expected. It used to make "gnatcov +coverage" crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.gprutils import GPRswitches +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["test.c"], srcdirs=[".."])), + covlevel="stmt", + mains=["test"], + extra_coverage_args=["--annotate=xcov", "--ignore-source-files=foo.c"], +) + +check_xcov_reports( + "*.xcov", + { + "test.c.xcov": {"+": {6, 7}} + }, + "obj", +) + +thistest.result() diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index cb0498873..f4984a1b9 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -96,42 +96,45 @@ package body Instrument.Checkpoints is end loop; end; + -- Load the mappings for preprocessing commands + if not Version_Less (CLS, Than => 8) then declare use SFI_To_PP_Cmd_Maps; - CP_PP_Map : Map; + CP_PP_Cmds : Map; + CP_SFI : Source_File_Index; begin - Map'Read (CLS.Stream, CP_PP_Map); - - for Cur in CP_PP_Map.Iterate loop - declare - SFI : constant Source_File_Index := - Remap_SFI (Relocs, Key (Cur)); - Existing_Cur : constant Cursor := - PP_Cmds.Find (SFI); - Ignored : constant Boolean := - SFI_Ignored (Relocs, Key (Cur)); - - Existing_PP_Cmd : constant Command_Type := - (if Existing_Cur = No_Element - then Null_Command - else Element (Existing_Cur)); - New_PP_Cmd : constant Command_Type := - (if Ignored - then Null_Command - else Element (Cur)); - - begin - if not Ignored then - if Existing_PP_Cmd = Null_Command then - PP_Cmds.Insert (SFI, New_PP_Cmd); - - elsif Existing_PP_Cmd /= New_PP_Cmd then + Map'Read (CLS.Stream, CP_PP_Cmds); + + for CP_Cur in CP_PP_Cmds.Iterate loop + + -- If this source file is now ignored, just discard its + -- preprocessing commands. + + CP_SFI := Key (CP_Cur); + if not SFI_Ignored (Relocs, CP_SFI) then + declare + SFI : constant Source_File_Index := + Remap_SFI (Relocs, CP_SFI); + Cur : constant Cursor := PP_Cmds.Find (SFI); + begin + -- If there was no known preprocessing command for SFI so + -- far, just register the loaded one. + + if not Has_Element (Cur) then + PP_Cmds.Insert (SFI, CP_PP_Cmds.Reference (CP_Cur)); + + -- Otherwise, warn if the already known command and the + -- loaded one are different. + + elsif CP_PP_Cmds.Reference (CP_Cur) + /= PP_Cmds.Reference (Cur) + then Warn ("inconsistent information for instrumented file " & Get_Unique_Name (SFI)); end if; - end if; - end; + end; + end if; end loop; end; end if; From 4162040b06359257a555f240d4a33588a14da1c2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 6 Dec 2022 13:24:49 +0000 Subject: [PATCH 0145/1483] ali_files.adb: do not register simple names for ignored C SCOs from .gli Registering a file by simple name can introduce ambiguities, in particular if the source file was already registered with its full name (like C units from modern .gli files), but without registering it in the simple name table: the ignored source file in this case introduces a separate file table entry. This ambiguity generates spurious "same base name" warnings, and sometimes even crashes during the computation of unique names: this computation relies on full names, so homonym file entries with only a simple name makes it crash. This fixes such a crash, visible with the "ignored-c-header" testcase added later in this commit chain. For eng/cov/gnatcoverage#17 --- tools/gnatcov/ali_files.adb | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/ali_files.adb b/tools/gnatcov/ali_files.adb index 649787f5a..9e3a9e511 100644 --- a/tools/gnatcov/ali_files.adb +++ b/tools/gnatcov/ali_files.adb @@ -109,15 +109,28 @@ package body ALI_Files is for J in SCO_Unit_Table.First + 1 .. SCO_Unit_Table.Last loop declare - U : SCO_Unit_Table_Entry renames SCO_Unit_Table.Table (J); - Name : constant String := + U : SCO_Unit_Table_Entry renames SCO_Unit_Table.Table (J); + + SFI : constant Source_File_Index := (if Deps_Present - then Get_Simple_Name (Deps.Element (U.Dep_Num)) - else U.File_Name.all); - SFI : constant Source_File_Index := - Get_Index_From_Generic_Name (Name, Source_File); + then Deps.Element (U.Dep_Num) + else Get_Index_From_Generic_Name + (U.File_Name.all, Source_File)); + -- Source file corresponding to this unit. Use the name from the + -- SCO "C" line if there are no list of dependencies ("D" lines, + -- missing for old GLI files for C). + + Match_Name : constant String := Get_Simple_Name (SFI); + -- Name to use for matching against the pattern of ignored files begin - if GNAT.Regexp.Match (Name, Ignored_Source_Files.all) then + -- In case we got SFI from the Deps vector, make sure it is + -- considered as a source file. + + Consolidate_File_Kind (SFI, Source_File); + + -- Do the ignored file matching itself + + if GNAT.Regexp.Match (Match_Name, Ignored_Source_Files.all) then Consolidate_Ignore_Status (SFI, Always); U.Dep_Num := Missing_Dep_Num; else From d4361db407f7bb7ba7652ec82348dd368f4b23be Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 2 Feb 2023 14:45:48 +0000 Subject: [PATCH 0146/1483] sc_obligations.adb: fix rules to discard CUs from checkpoints CU have two file attributes: Origin (the file from which the SCOs are computed/loaded: LI files for binary traces, and source files themselves for source traces). While so far, a CU loaded from a checkpoint was discarded when Origin was an ignored source file, we used to try to load it anyway even if the Main_Source was ignored, which is invalid and resulted in a crash. This commit fixes this bug: it discards the CU if Origin *or* Main_Source are ignored. For eng/cov/gnatcoverage#17 --- testsuite/tests/ignored-c-header/identity.c | 7 +++ testsuite/tests/ignored-c-header/identity.h | 5 ++ testsuite/tests/ignored-c-header/test.c | 10 ++++ testsuite/tests/ignored-c-header/test.py | 57 +++++++++++++++++++++ testsuite/tests/ignored-c-header/twice.h | 5 ++ tools/gnatcov/checkpoints.adb | 27 ++++++++++ tools/gnatcov/checkpoints.ads | 19 +++++++ tools/gnatcov/files_table.adb | 5 ++ tools/gnatcov/sc_obligations.adb | 47 ++++++++++++----- 9 files changed, 168 insertions(+), 14 deletions(-) create mode 100644 testsuite/tests/ignored-c-header/identity.c create mode 100644 testsuite/tests/ignored-c-header/identity.h create mode 100644 testsuite/tests/ignored-c-header/test.c create mode 100644 testsuite/tests/ignored-c-header/test.py create mode 100644 testsuite/tests/ignored-c-header/twice.h diff --git a/testsuite/tests/ignored-c-header/identity.c b/testsuite/tests/ignored-c-header/identity.c new file mode 100644 index 000000000..171abe411 --- /dev/null +++ b/testsuite/tests/ignored-c-header/identity.c @@ -0,0 +1,7 @@ +#include "identity.h" + +int +identity (int n) +{ + return static_identity (n); +} diff --git a/testsuite/tests/ignored-c-header/identity.h b/testsuite/tests/ignored-c-header/identity.h new file mode 100644 index 000000000..fda54f8d6 --- /dev/null +++ b/testsuite/tests/ignored-c-header/identity.h @@ -0,0 +1,5 @@ +static int +static_identity (int n) +{ + return n; +} diff --git a/testsuite/tests/ignored-c-header/test.c b/testsuite/tests/ignored-c-header/test.c new file mode 100644 index 000000000..b56d92982 --- /dev/null +++ b/testsuite/tests/ignored-c-header/test.c @@ -0,0 +1,10 @@ +#include "twice.h" + +extern int identity (int n); + +int +main () +{ + int n = identity (twice (2)); + return 0; +} diff --git a/testsuite/tests/ignored-c-header/test.py b/testsuite/tests/ignored-c-header/test.py new file mode 100644 index 000000000..229b84d90 --- /dev/null +++ b/testsuite/tests/ignored-c-header/test.py @@ -0,0 +1,57 @@ +""" +Check that ignoring a C header file works as expected. It used to make "gnatcov +coverage" crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.gprutils import GPRswitches +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["test.c"], srcdirs=[".."])), + covlevel="stmt", + mains=["test"], + extra_coverage_args=[ + "--annotate=xcov", + + # Ignore directly "twice.h" + + "--ignore-source-files=twice.h", + + # Ignore indirectly "identity.h", as its CU's origin is "identity.c". + # It is important for test reliability to check this testcase that only + # "identity.c" includes "identity.h". + "--ignore-source-files=identity.c", + ], +) + +expected_coverage = { + "test.c.xcov": {"+": {8, 9}}, + "identity.h.xcov": {"+": {4}}, +} + +# The following is specific to the instrumentation: the CU for "identity.h" +# depends on the "identity.c". As a result, ignoring "identity.c" implicitly +# ignores "identity.h", and gnatcov is supposed to warn for this case. +# +# This also implies that gnatcov will not emit a report for "identity.h". +# +# For binary traces, the CU for "identity.h" does not depend on "identity.c" +# (its Origin is "identity.c.gli", instead), so the above is not true. +if thistest.options.trace_mode == "src": + cov_log = contents_of("coverage.log").strip() + thistest.fail_if_no_match( + "'gnatcov coverage' output", + r"warning: gnatcov limitation: ignoring unit identity\.h from" + r".*[\\/]identity\.c\.sid because identity\.c is ignored$", + cov_log, + ) + + expected_coverage.pop("identity.h.xcov") + +check_xcov_reports("*.xcov", expected_coverage, "obj") + +thistest.result() diff --git a/testsuite/tests/ignored-c-header/twice.h b/testsuite/tests/ignored-c-header/twice.h new file mode 100644 index 000000000..df3a7fe00 --- /dev/null +++ b/testsuite/tests/ignored-c-header/twice.h @@ -0,0 +1,5 @@ +static int +twice (int n) +{ + return 2 * n; +} diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index 26166bb7b..a126c85f0 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -103,6 +103,8 @@ package body Checkpoints is new SFI_Map_Array'(First .. Last => No_Source_File); Relocs.Ignored_SFIs := new SFI_Ignored_Map_Array'(First .. Last => False); + Relocs.SFI_Simple_Filenames := + new SFI_Simple_Name_Map_Array'(First .. Last => <>); end Allocate_SFI_Maps; ------------------------- @@ -167,6 +169,18 @@ package body Checkpoints is new SCO_Ignored_Map_Array'(First .. Last => False); end Allocate_SCO_Id_Map; + --------------------- + -- Get_Simple_Name -- + --------------------- + + function Get_Simple_Name + (Relocs : Checkpoint_Relocations; + CP_SFI : Valid_Source_File_Index) return Unbounded_String + is + begin + return Relocs.SFI_Simple_Filenames.all (CP_SFI); + end Get_Simple_Name; + ---------------- -- Ignore_SFI -- ---------------- @@ -254,6 +268,19 @@ package body Checkpoints is Relocs.SFI_Map (Source_SFI) := Target_SFI; end Set_SFI_Map; + ------------------------- + -- Set_SFI_Simple_Name -- + ------------------------- + + procedure Set_SFI_Simple_Name + (Relocs : in out Checkpoint_Relocations; + SFI : Valid_Source_File_Index; + Simple_Name : Unbounded_String) + is + begin + Relocs.SFI_Simple_Filenames.all (SFI) := Simple_Name; + end Set_SFI_Simple_Name; + ------------------- -- Set_CU_Id_Map -- ------------------- diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 98e925089..e87fbb8cf 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -85,6 +85,12 @@ package Checkpoints is First, Last : SCO_Id); -- Allocate the various tables in the checkpoint relocations. + function Get_Simple_Name + (Relocs : Checkpoint_Relocations; + CP_SFI : Valid_Source_File_Index) return Unbounded_String; + -- Return the simple file name for CP_SFI. Using this function is necessary + -- when CP_SFI is ignored, as it is not possible to call Remap_SFI on it. + procedure Ignore_SFI (Relocs : in out Checkpoint_Relocations; CP_SFI : Source_File_Index); @@ -128,6 +134,12 @@ package Checkpoints is -- Source_SFI must not have been previously marked as ignored with -- Ignore_SFI. + procedure Set_SFI_Simple_Name + (Relocs : in out Checkpoint_Relocations; + SFI : Valid_Source_File_Index; + Simple_Name : Unbounded_String); + -- Assign a simple name to SFI + procedure Set_CU_Id_Map (Relocs : in out Checkpoint_Relocations; Source_CU_Id, Target_CU_Id : Valid_CU_Id) with @@ -308,6 +320,10 @@ private type CU_Id_Ignored_Map_Array is array (CU_Id range <>) of Boolean; type CU_Id_Ignored_Access is access all CU_Id_Ignored_Map_Array; + type SFI_Simple_Name_Map_Array is + array (Source_File_Index range <>) of Unbounded_String; + type SFI_Simple_Name_Map_Access is access all SFI_Simple_Name_Map_Array; + type Checkpoint_Relocations is record SFI_Map : SFI_Map_Acc; CU_Map : CU_Id_Map_Acc; @@ -317,6 +333,9 @@ private -- Maps to replace checkpoint identifiers with local table identifiers -- after merging the checkpoint in local tables. + SFI_Simple_Filenames : SFI_Simple_Name_Map_Access; + -- For each SFI from this checkpoint, corresponding simple name + Ignored_SCOs : SCO_Ignored_Map_Access; -- Map of SCOs that were ignored and thus are not remapped when loading -- the checkpoint. diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index c233e9523..02852a006 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -2038,6 +2038,11 @@ package body Files_Table is Kind : constant File_Kind := File_Kind'Input (S); Indexed_Simple_Name : constant Boolean := Boolean'Input (S); begin + Set_SFI_Simple_Name + (Relocs, + CP_SFI, + Ada.Strings.Unbounded.To_Unbounded_String + (Ada.Directories.Simple_Name (Name))); case Kind is when Stub_File => FE := (Kind => Stub_File, others => <>); diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 3067e5c40..d5b6d24dd 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -1567,8 +1567,40 @@ package body SC_Obligations is CP_CU_Id : constant CU_Id := To_Index (Cur); CP_CU : CU_Info := Element (Cur); New_CU_Id : CU_Id := No_CU_Id; + + -- If the CU Origin or its Main_Source files are ignored, we + -- cannot load this CU. + + Origin_Ignored : constant Boolean := + SFI_Ignored (Relocs, CP_CU.Origin); + Main_Source_Ignored : constant Boolean := + SFI_Ignored (Relocs, CP_CU.Main_Source); begin - if not SFI_Ignored (Relocs, CP_CU.Origin) then + if Origin_Ignored or else Main_Source_Ignored then + if Switches.Verbose then + Put_Line ("Ignoring CU from SID file: Id" & CP_CU_Id'Img); + end if; + + -- If we cannot load this CU *not* because its main source + -- is ignored, but rather because the origin is ignored, + -- warn the user: they probably did not want to ignore this + -- CU, but we have to in order not to break our data + -- structure invariants: Origin cannot be null. + + if not Main_Source_Ignored then + Warn + ("gnatcov limitation: ignoring unit " + & Get_Simple_Name + (Remap_SFI (Relocs, CP_CU.Main_Source)) + & " from " & To_String (CLS.Filename) + & " because " + & To_String (Get_Simple_Name (Relocs, CP_CU.Origin)) + & " is ignored"); + end if; + + Ignore_CU_Id (Relocs, CP_CU_Id); + + else Checkpoint_Load_Unit (CLS, CP_Vectors, @@ -1576,19 +1608,6 @@ package body SC_Obligations is CP_CU_Id => CP_CU_Id, New_CU_Id => New_CU_Id); Set_CU_Id_Map (Relocs, CP_CU_Id, New_CU_Id); - else - if Switches.Verbose then - Put_Line ("Ignoring CU from SID file: Id" & CP_CU_Id'Img); - end if; - - -- Ignoring compilation units from a checkpoint file should - -- only be possible when loading a SID file. In this case, - -- CP_CU.Main_Source and CP_CU.Origin should be the same. - -- Otherwise there is some weird things going on that we'd - -- like to be aware of. - - pragma Assert (SFI_Ignored (Relocs, CP_CU.Main_Source)); - Ignore_CU_Id (Relocs, CP_CU_Id); end if; end; end loop; From 82c9e1d56a89e6a703e378e68bd969219636a36a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 3 Feb 2023 15:46:26 +0000 Subject: [PATCH 0147/1483] Fix --dump-units-to for ignored C/C++ headers This commit enhances the data structure used to track ignored source files (Coverage.Source.Ignored_SF_Map) so that they can represent C/C++ sources in a sound way and fixes its initialization for C/C++ sources: GNATCOLL.Projects.Unit_Name returns an empty string for them, so they were just ignored so far. For consistency, this also enhances Files_Table.File_Info.Unit to contain a Project_Unit value instead of a mere unit name string, to avoid issues with homonym sources in a project. For eng/cov/gnatcoverage#17 --- tools/gnatcov/annotations-report.adb | 1 - tools/gnatcov/checkpoints.ads | 3 +- tools/gnatcov/coverage-source.adb | 46 ++++++++++----- tools/gnatcov/coverage-source.ads | 1 - tools/gnatcov/files_table.adb | 75 ++++++++++--------------- tools/gnatcov/files_table.ads | 72 ++++++++++++++++++------ tools/gnatcov/gnatcov_bits_specific.adb | 10 +++- tools/gnatcov/instrument-base_types.ads | 1 - tools/gnatcov/instrument-common.adb | 1 + tools/gnatcov/instrument-common.ads | 1 - tools/gnatcov/project.adb | 11 +++- tools/gnatcov/project.ads | 49 ++-------------- 12 files changed, 141 insertions(+), 130 deletions(-) diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index dceba81f3..8909cd6a7 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -28,7 +28,6 @@ with Coverage; use Coverage; with Coverage.Source; use Coverage.Source; with Coverage.Tags; use Coverage.Tags; with SC_Obligations; -with Project; use Project; with Switches; with Traces_Files; use Traces_Files; diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index e87fbb8cf..81df6a963 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -32,7 +32,7 @@ with SC_Obligations; use SC_Obligations; package Checkpoints is - subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 12; + subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 13; -- For compatibility with previous Gnatcov versions, the checkpoint -- file format is versioned. -- @@ -49,6 +49,7 @@ package Checkpoints is -- 10 -- Add non instrumented SCOs sets -- 11 -- fingerprints for buffer bit maps -- 12 -- Extend Unit_List to distinguish homonym source files + -- 13 -- Extend Files_Table.File_Info to distinguish homonym source files -- -- Note that we always use the last version when creating a checkpoint. diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index e1a335366..f920e7d12 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -39,6 +39,7 @@ with Elf_Disassemblers; use Elf_Disassemblers; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with MC_DC; use MC_DC; with Outputs; use Outputs; +with Project; use Project; with Slocs; use Slocs; with Strings; use Strings; with Switches; use Switches; @@ -220,9 +221,7 @@ package body Coverage.Source is -- 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 => US.Unbounded_String, - Element_Type => Ignored_Sources_Vector_Access, - "<" => US."<"); + (Key_Type => Project_Unit, Element_Type => Ignored_Sources_Vector_Access); -- Map units of interest to the list of associated ignored source files Ignored_SF_Map : Unit_To_Ignored_Maps.Map; @@ -355,7 +354,6 @@ package body Coverage.Source is File : GNATCOLL.Projects.File_Info) is use GNATCOLL.VFS; - pragma Unreferenced (Project); 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 @@ -364,13 +362,28 @@ package body Coverage.Source is begin if FI /= null and then not FI.Unit.Known then declare - use GNATCOLL.Projects; + use type GNATCOLL.Projects.Unit_Parts; + + Language : constant Some_Language := + To_Language (File.Language); + + -- For Ada, get the unit name for the compilation unit (no + -- subunit names). For file-based languages, + -- GNATCOLL.Projects.Unit_Name returns an empty string: we need + -- to get the file base name instead. + Unit_Name : constant String := - (if File.Unit_Part = Unit_Separate - then Unit_Name_For_Subunit (File.Unit_Name) - else File.Unit_Name); + (case Language is + when Ada_Language => + (if File.Unit_Part = GNATCOLL.Projects.Unit_Separate + then Unit_Name_For_Subunit (File.Unit_Name) + else File.Unit_Name), + when others => Get_Simple_Name (SFI)); + + Unit : constant Project_Unit := + To_Project_Unit (Unit_Name, Project, Language); begin - Consolidate_Source_File_Unit (SFI, Unit_Name); + Consolidate_Source_File_Unit (SFI, Unit); end; end if; end Callback; @@ -381,7 +394,7 @@ package body Coverage.Source is Enumerate_Sources (Callback'Access, Include_Subunits => True, - Language => Ada_Language); + Language => All_Languages); end Compute_Unit_Name_For_Ignored_Sources; ------------------------- @@ -408,8 +421,13 @@ package body Coverage.Source is if FI.Kind = Source_File and then FI.Ignore_Status in Always .. Sometimes then - pragma Assert - (FI.Unit.Known and then Is_Unit_Of_Interest (FI.Full_Name.all)); + -- If FI is a separate (Ada) or a header file (C/C++), it is not a + -- unit of interest itself: only the compilation unit is, so + -- Is_Unit_Of_Interest (FI.Full_Name.all) return False. Still, the + -- unit that owns this file is supposed to be known by now, so it + -- should be valid to access FI.Unit.Name (i.e. FI.Unit.Known + -- should be True). + if not Ignored_SF_Map.Contains (FI.Unit.Name) then Vec := new Ignored_Sources_Vector.Vector; Ignored_SF_Map.Insert (FI.Unit.Name, Vec); @@ -438,8 +456,8 @@ package body Coverage.Source is for S of Unit_List loop Process_Unit.all (S); - if Ignored_SF_Map.Contains (S.Unit_Name) then - for FI of Ignored_SF_Map.Element (S.Unit_Name).all loop + 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; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 9b7bccff6..834e51053 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -23,7 +23,6 @@ with Files_Table; use Files_Table; with Instrument; use Instrument; with Instrument.Input_Traces; use Instrument.Input_Traces; with Instrument.Base_Types; use Instrument.Base_Types; -with Project; use Project; with Traces; use Traces; with Traces_Names; use Traces_Names; with Traces_Lines; use Traces_Lines; diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 02852a006..2c951332d 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -17,8 +17,6 @@ ------------------------------------------------------------------------------ with Ada.Containers.Hashed_Maps; -with Ada.Characters.Handling; -with Ada.Containers.Ordered_Sets; with Ada.Directories; with Ada.Streams; with Ada.Unchecked_Deallocation; @@ -36,7 +34,6 @@ with ALI_Files; use ALI_Files; with Checkpoints; use Checkpoints; with Coverage; use Coverage; with Outputs; -with Paths; use Paths; with Perf_Counters; use Perf_Counters; with Project; with Switches; @@ -219,16 +216,6 @@ package body Files_Table is function Create_Line_Info return Line_Info_Access; -- Return a new Line_Info record - procedure Consolidate_Source_File_Unit - (Index : Valid_Source_File_Index; - New_Unit : Ada.Strings.Unbounded.Unbounded_String) with - Pre => Get_File (Index).Kind = Source_File; - -- Update the unit name info for the source file represented by Index. - -- Does nothing if the new unit name is the empty string. - -- - -- Calling this procedure is valid iff the source file at Index has no - -- owning unit already, or that it is the same as New_Unit. - --------------------- -- Append_To_Array -- --------------------- @@ -446,8 +433,6 @@ package body Files_Table is function End_Lex_Element (Sloc : Source_Location) return Source_Location is - use Ada.Characters.Handling; - type Lex_Type is (String_Literal, Numeric_Literal, Other); Lex : Lex_Type; @@ -636,32 +621,21 @@ package body Files_Table is ---------------------------------- procedure Consolidate_Source_File_Unit - (Index : Valid_Source_File_Index; - New_Unit : Ada.Strings.Unbounded.Unbounded_String) + (Index : Valid_Source_File_Index; New_Unit : Project_Unit) is use Ada.Strings.Unbounded; FI : File_Info renames Files_Table.Element (Index).all; begin - if FI.Kind /= Source_File or else New_Unit = Null_Unbounded_String then - return; - end if; - if not FI.Unit.Known then - FI.Unit := (Known => True, - Name => New_Unit); + pragma Assert (New_Unit.Unit_Name /= Null_Unbounded_String); + if FI.Kind /= Source_File then + null; + elsif not FI.Unit.Known then + FI.Unit := (Known => True, Name => New_Unit); elsif FI.Unit.Known then pragma Assert (FI.Unit.Name = New_Unit); end if; end Consolidate_Source_File_Unit; - procedure Consolidate_Source_File_Unit - (Index : Valid_Source_File_Index; - New_Unit : String) - is - begin - Consolidate_Source_File_Unit - (Index, Ada.Strings.Unbounded.To_Unbounded_String (New_Unit)); - end Consolidate_Source_File_Unit; - --------------------- -- Fill_Line_Cache -- --------------------- @@ -1917,8 +1891,7 @@ package body Files_Table is Any_Ignore_Status'Write (S, FI.Ignore_Status); Boolean'Write (S, FI.Unit.Known); if FI.Unit.Known then - String'Output - (S, Ada.Strings.Unbounded.To_String (FI.Unit.Name)); + Project_Unit'Output (S, FI.Unit.Name); end if; end if; end; @@ -2048,27 +2021,37 @@ package body Files_Table is FE := (Kind => Stub_File, others => <>); when Source_File => FE := (Kind => Source_File, others => <>); - if not Checkpoints.Version_Less (CLS, Than => 5) then - -- Dumping ignored source files is only supported from - -- Checkpoint version 5. + -- Dumping ignored source files requires information that is + -- not available before checkpoint version 13. + FE.Ignore_Status := Unknown; + FE.Unit := (Known => False); + if not Checkpoints.Version_Less (CLS, Than => 5) then FE.Ignore_Status := Any_Ignore_Status'Input (S); declare - use Ada.Strings.Unbounded; Unit_Known : constant Boolean := Boolean'Input (S); begin if Unit_Known then - FE.Unit := - (Known => True, - Name => To_Unbounded_String (String'Input (S))); - else - FE.Unit := (Known => False); + + -- Starting with the version 13 of checkpoints, + -- owning units are represented as Project_Unit + -- values (they were mere strings before). Consider + -- the owning unit unknown if we do not have recent + -- formats. + + if Checkpoints.Version_Less (CLS, Than => 13) then + declare + Dummy : constant String := String'Input (S); + begin + null; + end; + else + FE.Unit := (Known => True, + Name => Project_Unit'Input (S)); + end if; end if; end; - else - FE.Ignore_Status := Unknown; - FE.Unit := (Known => False); end if; when Library_File => FE := (Kind => Library_File, others => <>); diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 9ad16ca1e..49ce8a20d 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -16,23 +16,27 @@ -- of the license. -- ------------------------------------------------------------------------------ +with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; with Ada.Strings.Unbounded; -with Ada.Text_IO; use Ada.Text_IO; +with Ada.Text_IO; use Ada.Text_IO; with GNAT.Strings; use GNAT.Strings; with GNAT.Regexp; limited with Checkpoints; -with Coverage_Options; use Coverage_Options; -with Diagnostics; use Diagnostics; -with SC_Obligations; use SC_Obligations; -with Slocs; use Slocs; -with Traces_Elf; use Traces_Elf; -with Traces_Dbase; use Traces_Dbase; -with Traces_Stats; use Traces_Stats; -with Traces_Lines; use Traces_Lines; -with Types; use Types; +with Coverage_Options; use Coverage_Options; +with Diagnostics; use Diagnostics; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with Paths; use Paths; +with SC_Obligations; use SC_Obligations; +with Slocs; use Slocs; +with Traces_Elf; use Traces_Elf; +with Traces_Dbase; use Traces_Dbase; +with Traces_Stats; use Traces_Stats; +with Traces_Lines; use Traces_Lines; +with Types; use Types; package Files_Table is @@ -297,12 +301,47 @@ package Files_Table is -- option --ignore-source-files. Consolidation rules are described in -- procedure Consolidate_Ignore_Status. + type Project_Unit (Language : Any_Language_Kind := Unit_Based_Language) + is record + Unit_Name : Ada.Strings.Unbounded.Unbounded_String; + + case Language is + when File_Based_Language => + Project_Name : Ada.Strings.Unbounded.Unbounded_String; + when others => + null; + end case; + end record; + -- To uniquely identify a unit in a project tree, we need its unit name (or + -- base name for a C unit). For file-based languages such as C or C++, we + -- might have homonym base file names in different projects so we keep + -- track of the project name in addition. + + use type Ada.Strings.Unbounded.Unbounded_String; + + function Image (U : Project_Unit) return String is + (case U.Language is + when Unit_Based_Language => + To_Lower (Ada.Strings.Unbounded.To_String (U.Unit_Name)), + when File_Based_Language => + Ada.Strings.Unbounded.To_String (U.Project_Name) + & ":" + & Fold_Filename_Casing + (Ada.Strings.Unbounded.To_String (U.Unit_Name))); + + function "<" (L, R : Project_Unit) return Boolean is + (Image (L) < Image (R)); + + function "=" (L, R : Project_Unit) return Boolean is + (Image (L) = Image (R)); + + package Unit_Sets is new Ada.Containers.Ordered_Sets + (Element_Type => Project_Unit); + type Owning_Unit (Known : Boolean := False) is record case Known is - when True => - Name : Ada.Strings.Unbounded.Unbounded_String; - when False => - null; + when True => Name : Project_Unit; + when False => null; end case; end record; -- Whether the unit of a file is known or not. If it is, stores the name of @@ -423,9 +462,8 @@ package Files_Table is (Index : Source_File_Index) return File_Info_Access; procedure Consolidate_Source_File_Unit - (Index : Valid_Source_File_Index; - New_Unit : String) with - Pre => Get_File (Index).Kind = Source_File; + (Index : Valid_Source_File_Index; New_Unit : Project_Unit) + with Pre => Get_File (Index).Kind = Source_File; -- Update the unit name info for the source file represented by Index. -- Does nothing if the new unit name is the empty string. -- diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index c824ff7ab..5718d516f 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -53,6 +53,7 @@ with Decision_Map; use Decision_Map; with Disassemble_Insn_Properties; with Execs_Dbase; use Execs_Dbase; with Files_Table; use Files_Table; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Inputs; use Inputs; with Instrument.Input_Traces; with Instrument; use Instrument; @@ -1678,16 +1679,19 @@ begin declare procedure Add_Unit (Unit : Project_Unit; Is_Stub : Boolean); - -- Add Name to the list of names for units of interest + -- Add Name to the list of names for units of interest. Do nothing + -- if this is a stub for a unit-based language, since such stubs + -- are implicitly part of another unit of interest. -------------- -- Add_Unit -- -------------- procedure Add_Unit (Unit : Project_Unit; Is_Stub : Boolean) is - pragma Unreferenced (Is_Stub); begin - Add_Unit (Unit); + if not Is_Stub or else Unit.Language = File_Based_Language then + Add_Unit (Unit); + end if; end Add_Unit; begin Enumerate_Units_Of_Interest (Add_Unit'Access); diff --git a/tools/gnatcov/instrument-base_types.ads b/tools/gnatcov/instrument-base_types.ads index 99df2fbf4..99dc1c449 100644 --- a/tools/gnatcov/instrument-base_types.ads +++ b/tools/gnatcov/instrument-base_types.ads @@ -28,7 +28,6 @@ with GNATCOLL.Projects; use GNATCOLL.Projects; with Types; use Types; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -with Project; use Project; with SC_Obligations; use SC_Obligations; with Subprocesses; use Subprocesses; with Switches; use Switches; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 3eede45b6..98ef80f93 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -38,6 +38,7 @@ with Diagnostics; with Hex_Images; with Outputs; use Outputs; with Paths; use Paths; +with Project; use Project; with SCOs; package body Instrument.Common is diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 6112c6a4c..8c413e618 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -70,7 +70,6 @@ with GNATcov_RTS; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Instrument.Base_Types; use Instrument.Base_Types; with Namet; use Namet; -with Project; use Project; with SC_Obligations; use SC_Obligations; with Slocs; use Slocs; with Switches; use Switches; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 7536542f1..67d874569 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -34,12 +34,18 @@ with GNATCOLL.Traces; with GNATCOLL.Projects.Aux; with GNATCOLL.VFS; use GNATCOLL.VFS; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Instrument.Base_Types; use Instrument.Base_Types; with Inputs; use Inputs; with Outputs; use Outputs; +with Paths; use Paths; +with Strings; use Strings; package body Project is + subtype Project_Unit is Files_Table.Project_Unit; + use type Project_Unit; + Coverage_Package : aliased String := "coverage"; Coverage_Package_List : aliased String_List := (1 => Coverage_Package'Access); @@ -239,7 +245,7 @@ package body Project is function To_Project_Unit (Unit_Name : String; Project : Project_Type; - Language : Some_Language) return Project_Unit + Language : Some_Language) return Files_Table.Project_Unit is U : Project_Unit (Language_Kind (Language)); begin @@ -462,7 +468,8 @@ package body Project is --------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Project_Unit; Is_Stub : Boolean)) + (Callback : access procedure (Name : Files_Table.Project_Unit; + Is_Stub : Boolean)) is use Unit_Maps; begin diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index acc27145c..5d3f8ab7d 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -19,19 +19,14 @@ -- GNAT projects support with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Containers.Ordered_Sets; -with Ada.Strings.Unbounded; with GNAT.Strings; use GNAT.Strings; with GNATCOLL.Projects; use GNATCOLL.Projects; with GNATCOLL.VFS; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; - with Inputs; -with Paths; use Paths; -with Strings; use Strings; +with Files_Table; with Switches; use Switches; with Traces_Files; use Traces_Files; @@ -118,52 +113,20 @@ package Project is -- path of its main executable (including its suffix, for instance ".exe"). -- Otherwise, return an empty string. - ------------------------- - -- Unit identification -- - ------------------------- - - type Project_Unit (Language : Any_Language_Kind := Unit_Based_Language) is - record - Unit_Name : Ada.Strings.Unbounded.Unbounded_String; - case Language is - when File_Based_Language => - Project_Name : Ada.Strings.Unbounded.Unbounded_String; - when others => null; - end case; - end record; - -- To uniquely identify a unit, we need its unit name (or base name for a C - -- unit). For file-based languages such as C or C++, we might have homonym - -- base file names in different projects so we keep track of the project - -- name in addition. - - use type Ada.Strings.Unbounded.Unbounded_String; - function To_Project_Unit (Unit_Name : String; Project : Project_Type; - Language : Some_Language) return Project_Unit; - - function Image (U : Project_Unit) return String is - (case U.Language is - when Unit_Based_Language => To_Lower (+U.Unit_Name), - when File_Based_Language => - +U.Project_Name & ":" & Fold_Filename_Casing (+U.Unit_Name)); - - function "<" (L, R : Project_Unit) return Boolean is - (Image (L) < Image (R)); - - function "=" (L, R : Project_Unit) return Boolean is - (Image (L) = Image (R)); - - package Unit_Sets is new Ada.Containers.Ordered_Sets - (Element_Type => Project_Unit); + Language : Some_Language) return Files_Table.Project_Unit; + -- Return the Project_Unit value that designates the same unit as + -- Unit_Name/Project/Language. -------------------------------------- -- Accessors for project properties -- -------------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Project_Unit; Is_Stub : Boolean)); + (Callback : access procedure (Name : Files_Table.Project_Unit; + Is_Stub : Boolean)); -- Call Callback once for every unit of interest. Name is the unit name, -- and Is_Stub corresponds to the Unit_Info.Is_Stub field (see -- project.adb). From 4a1bd2bbba0ce88baa2c80a0b6c0845d93f9cde1 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 8 Feb 2023 10:59:15 +0000 Subject: [PATCH 0148/1483] Use "stub" instead of "subunit" where it makes sense For code that treats Ada subunits the same way C/C++ headers are treated, it makes more sense to talk about "stubs". Do the renaming where appropriate. For eng/cov/gnatcoverage#17 --- tools/gnatcov/coverage-source.adb | 4 ++-- tools/gnatcov/project.adb | 40 +++++++++++++++---------------- tools/gnatcov/project.ads | 10 ++++---- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index f920e7d12..58527f599 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -393,8 +393,8 @@ package body Coverage.Source is begin Enumerate_Sources (Callback'Access, - Include_Subunits => True, - Language => All_Languages); + Include_Stubs => True, + Language => All_Languages); end Compute_Unit_Name_For_Ignored_Sources; ------------------------- diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 67d874569..4fb56ae92 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -75,18 +75,19 @@ package body Project is -- Build identifiers for attributes in package Coverage procedure Iterate_Source_Files - (Root_Project : Project_Type; - Process : access procedure + (Root_Project : Project_Type; + Process : access procedure (Info : File_Info; Unit_Name : String); - Recursive : Boolean; - Include_Subunits : Boolean := False); + Recursive : Boolean; + Include_Stubs : Boolean := False); -- Call Process on all source files in Root_Project (recursively -- considering source files of sub-projects if Recursive is true). -- -- This passes the name of the unit as Unit_Name for languages featuring -- this notion (Ada) and the base file name otherwise (i.e. for C sources). - -- If Include_Subunits is false (default), then skip all files that - -- implement subunits. + -- + -- If Include_Stubs is false (the default) then Callback will skip + -- sources files that are subunits (Ada) or headers (C/C++). Env : Project_Environment_Access; -- Environment in which we load the project tree @@ -391,11 +392,11 @@ package body Project is -------------------------- procedure Iterate_Source_Files - (Root_Project : Project_Type; - Process : access procedure + (Root_Project : Project_Type; + Process : access procedure (Info : File_Info; Unit_Name : String); - Recursive : Boolean; - Include_Subunits : Boolean := False) + Recursive : Boolean; + Include_Stubs : Boolean := False) is -- If Root_Project is extending some project P, consider for coverage -- purposes that source files in P also belong to Root_Project. For @@ -432,12 +433,11 @@ package body Project is declare Info : constant File_Info := File_Info (Abstract_Info); begin - -- Register only units in supported languages (Ada, C and - -- C++), and don't consider subunits as independent - -- units. + -- Process only source files in supported languages (Ada, + -- C and C++), and include subunits only if requested. if To_Lower (Info.Language) in "ada" | "c" | "c++" - and then (Include_Subunits + and then (Include_Stubs or else Info.Unit_Part /= Unit_Separate) then Process.all @@ -586,11 +586,11 @@ package body Project is ----------------------- procedure Enumerate_Sources - (Callback : access procedure + (Callback : access procedure (Project : GNATCOLL.Projects.Project_Type; File : GNATCOLL.Projects.File_Info); - Language : Any_Language; - Include_Subunits : Boolean := False) + Language : Any_Language; + Include_Stubs : Boolean := False) is procedure Process_Source_File (Info : File_Info; Unit_Name : String); -- Callback for Iterate_Source_File. If Unit_Name is a unit of interest, @@ -606,7 +606,7 @@ package body Project is or else Language = To_Language (Info.Language)) and then - (Include_Subunits + (Include_Stubs or else Is_Unit_Of_Interest (Info.Project, Unit_Name, To_Language (Info.Language))) then @@ -621,8 +621,8 @@ package body Project is Iterate_Source_Files (Prj_Info.Project, Process_Source_File'Access, - Recursive => False, - Include_Subunits => Include_Subunits); + Recursive => False, + Include_Stubs => Include_Stubs); end loop; end Enumerate_Sources; diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 5d3f8ab7d..608b63f73 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -150,18 +150,18 @@ package Project is -- for all units of interest that have no SCOs file. procedure Enumerate_Sources - (Callback : access procedure + (Callback : access procedure (Project : GNATCOLL.Projects.Project_Type; File : GNATCOLL.Projects.File_Info); - Language : Any_Language; - Include_Subunits : Boolean := False) + Language : Any_Language; + Include_Stubs : Boolean := False) with Pre => Is_Project_Loaded; -- Call Callback once for every source file of the given language -- mentionned in a previous Add_Project call. Override_Units has the same -- semantics as in Enumerate_LIs. -- - -- If Include_Subunits is false (the default) then Callback will skip - -- sources that are subunits. + -- If Include_Stubs is false (the default) then Callback will skip + -- sources files that are subunits (Ada) or headers (C/C++). type Main_Source_File is record File : GNATCOLL.VFS.Virtual_File; From 9e2febabb61713106810d6365720f87f96ed1107 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 31 Jan 2023 12:28:33 +0100 Subject: [PATCH 0149/1483] SC_Obligations: Fix logic error when consolidating non-instr SCOs The code taking care of consolidating non-instrumented SCOs used to try to get the previous element of some Cursor, without checking if the cursor was No_Element, resulting in a constraint error. Fixes eng/cov/gnatcoverage#15 --- testsuite/tests/15-non-instr-cons/pkg.ads | 12 +++++ testsuite/tests/15-non-instr-cons/test.opt | 1 + testsuite/tests/15-non-instr-cons/test.py | 51 ++++++++++++++++++++ testsuite/tests/15-non-instr-cons/test_f.adb | 8 +++ testsuite/tests/15-non-instr-cons/test_t.adb | 8 +++ tools/gnatcov/sc_obligations.adb | 19 +++----- 6 files changed, 88 insertions(+), 11 deletions(-) create mode 100644 testsuite/tests/15-non-instr-cons/pkg.ads create mode 100644 testsuite/tests/15-non-instr-cons/test.opt create mode 100644 testsuite/tests/15-non-instr-cons/test.py create mode 100644 testsuite/tests/15-non-instr-cons/test_f.adb create mode 100644 testsuite/tests/15-non-instr-cons/test_t.adb diff --git a/testsuite/tests/15-non-instr-cons/pkg.ads b/testsuite/tests/15-non-instr-cons/pkg.ads new file mode 100644 index 000000000..378529f9a --- /dev/null +++ b/testsuite/tests/15-non-instr-cons/pkg.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Pkg is + + type T is tagged record + X : Boolean; + end record; + + function Store_AT (L : Boolean; R : Boolean) return T is + (X => L and then R); + +end Pkg; diff --git a/testsuite/tests/15-non-instr-cons/test.opt b/testsuite/tests/15-non-instr-cons/test.opt new file mode 100644 index 000000000..4d7631d98 --- /dev/null +++ b/testsuite/tests/15-non-instr-cons/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Bug reproducer requires expression functions diff --git a/testsuite/tests/15-non-instr-cons/test.py b/testsuite/tests/15-non-instr-cons/test.py new file mode 100644 index 000000000..e61358212 --- /dev/null +++ b/testsuite/tests/15-non-instr-cons/test.py @@ -0,0 +1,51 @@ +""" +Regression test: the relocation logic for non instrumented SCOs when loading +SCOs/checkpoints contained a logic error, resulting in trying to get the +previous element from a No_Element cursor, resulting in a constraint error. +This only happened if the last SCO of a checkpoint was not instrumented, and +that SCO had already been loaded through another checkpoint. + +In this test we use an expression function which is a primitive of a tagged +type, and that type is its return type, to create non-instrumented SCOs. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +gpr = gprfor(mains=["test_f.adb", "test_t.adb"], srcdirs=[".."]) + + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gpr, units=["pkg"]), + extra_coverage_args=[], + covlevel="stmt", + mains=["test_f", "test_t"], + trace_mode="src", + instrument_warnings_as_errors=False, +) + +trace_t = xcov_args.pop() +trace_f = xcov_args.pop() + +# Create a checkpoint from each trace +xcov(xcov_args + ["--save-checkpoint=test_t.ckpt", trace_t]) +xcov(xcov_args + ["--save-checkpoint=test_f.ckpt", trace_f]) + +# Try to consolidate the checkpoint +xcov(xcov_args + ["-Ctest_t.ckpt", "-Ctest_f.ckpt", "-axcov"]) + +check_xcov_reports( + "*.xcov", + expected_cov={ + "pkg.ads.xcov": {"?": {10}, "+": {5,6,7}}, + }, + cwd="obj", +) + +thistest.result() diff --git a/testsuite/tests/15-non-instr-cons/test_f.adb b/testsuite/tests/15-non-instr-cons/test_f.adb new file mode 100644 index 000000000..b2c09002e --- /dev/null +++ b/testsuite/tests/15-non-instr-cons/test_f.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Test_F is +begin + if Pkg.Store_AT (True, False).X /= False then + raise Program_Error; + end if; +end Test_F; diff --git a/testsuite/tests/15-non-instr-cons/test_t.adb b/testsuite/tests/15-non-instr-cons/test_t.adb new file mode 100644 index 000000000..bc00817c4 --- /dev/null +++ b/testsuite/tests/15-non-instr-cons/test_t.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Test_T is +begin + if Pkg.Store_AT (True, True).X /= True then + raise Program_Error; + end if; +end Test_T; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index d5b6d24dd..d2dc7ed1b 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -752,7 +752,6 @@ package body SC_Obligations is use Non_Instrumented_SCO_Sets; CU_CP_Set : Set; CU_Set : Set; - Remapped_SCO : SCO_Id; Cur : Cursor; Prev : Cursor; begin @@ -767,11 +766,10 @@ package body SC_Obligations is -- current CU to compute the intersection. for SCO of CP_Vectors.Non_Instr_SCOs loop - Remapped_SCO := Remap_SCO_Id (Relocs, SCO); - if SCO in CP_CU.First_SCO .. CP_CU.Last_SCO - and then Remapped_SCO /= No_SCO_Id + if SCO /= No_SCO_Id + and then SCO in CP_CU.First_SCO .. CP_CU.Last_SCO then - CU_CP_Set.Insert (Remapped_SCO); + CU_CP_Set.Insert (Remap_SCO_Id (Relocs, SCO)); end if; end loop; @@ -779,12 +777,12 @@ package body SC_Obligations is while Has_Element (Cur) and then Element (Cur) <= Real_CU.Last_SCO loop CU_Set.Insert (Element (Cur)); + Prev := Cur; Next (Cur); -- Remove the element from the main set so we can insert the -- intersection of the CU-specific sets later. - Prev := Previous (Cur); Non_Instr_SCOs.Delete (Prev); end loop; Non_Instr_SCOs.Union (CU_Set.Intersection (CU_CP_Set)); @@ -795,11 +793,10 @@ package body SC_Obligations is CU_CP_Set.Clear; for SCO of CP_Vectors.Non_Instr_MCDC_SCOs loop - Remapped_SCO := Remap_SCO_Id (Relocs, SCO); - if SCO in CP_CU.First_SCO .. CP_CU.Last_SCO - and then Remapped_SCO /= No_SCO_Id + if SCO /= No_SCO_Id + and then SCO in CP_CU.First_SCO .. CP_CU.Last_SCO then - CU_CP_Set.Insert (Remapped_SCO); + CU_CP_Set.Insert (Remap_SCO_Id (Relocs, SCO)); end if; end loop; @@ -807,8 +804,8 @@ package body SC_Obligations is while Has_Element (Cur) and then Element (Cur) <= Real_CU.Last_SCO loop CU_Set.Insert (Element (Cur)); + Prev := Cur; Next (Cur); - Prev := Previous (Cur); Non_Instr_MCDC_SCOs.Delete (Prev); end loop; Non_Instr_MCDC_SCOs.Union (CU_Set.Intersection (CU_CP_Set)); From 80148ee9a3a6b26b7df1349f7745b77afa97187f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 9 Feb 2023 15:52:15 +0100 Subject: [PATCH 0150/1483] files_table.adb: do not call Simple_Name on Clang predefined file names Following recent changes for for eng/cov/gnatcoverage#17, the tests-instr-cov-cmdline-self-ref-macro testcase started failing on Windows: the problem is that we inserted a call to Ada.Directories.Simple_Name on a file name that may be artificial: "" is not real file name, and is used to designate source that appears in the command line (not from a source file). This name is invalid on Windows, and thus Simple_Name raises a Name_Error exception for it on Windows. --- tools/gnatcov/files_table.adb | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 2c951332d..ec1e45c90 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -2010,12 +2010,20 @@ package body Files_Table is Name : constant String := String'Input (S); Kind : constant File_Kind := File_Kind'Input (S); Indexed_Simple_Name : constant Boolean := Boolean'Input (S); + + -- Do not call Ada.Directories.Simple_Name on artificial file + -- names: such names are known to make Simple_Name raise a + -- Name_Error on Windows. + + Simple_Name : constant String := + (if Clang_Predefined_File (Name) + then Name + else Ada.Directories.Simple_Name (Name)); begin Set_SFI_Simple_Name (Relocs, CP_SFI, - Ada.Strings.Unbounded.To_Unbounded_String - (Ada.Directories.Simple_Name (Name))); + Ada.Strings.Unbounded.To_Unbounded_String (Simple_Name)); case Kind is when Stub_File => FE := (Kind => Stub_File, others => <>); From 3b85e91c92d561234391373ff95128e5439ee518 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 6 Dec 2022 18:15:13 +0100 Subject: [PATCH 0151/1483] fix typos Ref: eng/cov/gnatcoverage#18 --- tools/gnatcov/argparse.ads | 2 +- tools/gnatcov/instrument-c.ads | 2 +- tools/gnatcov/instrument-common.ads | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/argparse.ads b/tools/gnatcov/argparse.ads index 832bb2d58..698f2940b 100644 --- a/tools/gnatcov/argparse.ads +++ b/tools/gnatcov/argparse.ads @@ -294,7 +294,7 @@ package Argparse is end record; -- For single string options, we distinguish the case when the options did -- not appear on the command-line and the case when the option specified an - -- empty value. This is specified thanks to the Present distriminant. + -- empty value. This is specified thanks to the Present discriminant. function Value_Or_Null (Opt : String_Option) return Unbounded_String; -- If Opt is present, return its value. Return the empty string otherwise. diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index dd8c167e7..ef5316fcd 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -315,7 +315,7 @@ package Instrument.C is Language : C_Family_Language; Info : Project_Info; Filename : String); - -- Shortcut to call Import_From_Project, and Import_From_Agrs on the + -- Shortcut to call Import_From_Project, and Import_From_Args on the -- --c-opts/--c++-opts option. type Source_Of_Interest (Of_Interest : Boolean := False) is record diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 8c413e618..d5751e713 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -152,7 +152,7 @@ package Instrument.Common is function Project_Output_Dir (Project : Project_Type) return String; -- Return the directory in which we must create instrumented sources for - -- Project. This retuns an empty strings for projects that do not have an + -- Project. This returns an empty string for projects that do not have an -- object directory. function Format_Fingerprint @@ -176,7 +176,7 @@ package Instrument.Common is -- Project that this record describes Externally_Built : Boolean; - -- Whether this project is externaly built. In that case, we assume its + -- Whether this project is externally built. In that case, we assume its -- units of interest have already been instrumented. Output_Dir : Ada.Strings.Unbounded.Unbounded_String; From c927ac8e00731e5f37bba2b7d1c6b280e692066f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 14 Dec 2022 18:23:55 +0100 Subject: [PATCH 0152/1483] Fix formatting Ref: eng/cov/gnatcoverage#18 --- tools/gnatcov/project.adb | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 4fb56ae92..5a6222cae 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -655,6 +655,7 @@ package body Project is ---------------------- -- Runtime_Has_File -- ---------------------- + function Runtime_Has_File (Filename : Filesystem_String) return Boolean is Result_File : Virtual_File; -- Virtual_File for Ada.Finalization. Only search predefined sources. From 34ffc567418374169f560f368bf8aa6c40803df7 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 6 Dec 2022 18:19:45 +0100 Subject: [PATCH 0153/1483] Suprocesses: fix ordering of parameters Put optional argument after required argument. Ref: eng/cov/gnatcoverage#18 --- tools/gnatcov/subprocesses.adb | 8 ++++---- tools/gnatcov/subprocesses.ads | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index bbacb6797..d1a75c580 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -81,8 +81,8 @@ package body Subprocesses is return Run_Command (+Command.Command, Command.Arguments, - Command.Environment, Origin_Command_Name, + Command.Environment, Output_File, Err_To_Out, Out_To_Null, @@ -113,8 +113,8 @@ package body Subprocesses is procedure Run_Command (Command : String; Arguments : String_Vectors.Vector; - Environment : String_Maps.Map := Empty_Environment; Origin_Command_Name : String; + Environment : String_Maps.Map := Empty_Environment; Output_File : String := ""; Err_To_Out : Boolean := True; Out_To_Null : Boolean := False; @@ -123,8 +123,8 @@ package body Subprocesses is Dummy : constant Boolean := Run_Command (Command, Arguments, - Environment, Origin_Command_Name, + Environment, Output_File, Err_To_Out, Out_To_Null, @@ -137,8 +137,8 @@ package body Subprocesses is function Run_Command (Command : String; Arguments : String_Vectors.Vector; - Environment : String_Maps.Map := Empty_Environment; Origin_Command_Name : String; + Environment : String_Maps.Map := Empty_Environment; Output_File : String := ""; Err_To_Out : Boolean := True; Out_To_Null : Boolean := False; diff --git a/tools/gnatcov/subprocesses.ads b/tools/gnatcov/subprocesses.ads index b98824353..080800dba 100644 --- a/tools/gnatcov/subprocesses.ads +++ b/tools/gnatcov/subprocesses.ads @@ -93,8 +93,8 @@ package Subprocesses is function Run_Command (Command : String; Arguments : String_Vectors.Vector; - Environment : String_Maps.Map := Empty_Environment; Origin_Command_Name : String; + Environment : String_Maps.Map := Empty_Environment; Output_File : String := ""; Err_To_Out : Boolean := True; Out_To_Null : Boolean := False; @@ -112,8 +112,8 @@ package Subprocesses is procedure Run_Command (Command : String; Arguments : String_Vectors.Vector; - Environment : String_Maps.Map := Empty_Environment; Origin_Command_Name : String; + Environment : String_Maps.Map := Empty_Environment; Output_File : String := ""; Err_To_Out : Boolean := True; Out_To_Null : Boolean := False; From e255365827e09b8d658b52b526fd897b1db6a177 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 7 Dec 2022 14:53:33 +0100 Subject: [PATCH 0154/1483] Instrumentation: refactor cleaning of gnatcov-instr directory This is preliminary work for the parallelized instrumentation. To avoid leaving stale instrumented files (if a file instrumented in a previous run is not a unit of interest anymore, and thus is not instrumented anymore), we need to clean the -gnatcov-instr directories when running gnatcov instrument. We used to cleaning after having generated the instrumented files: we recorded what files had been generated, and cleaned all of the files that weren't generated by the current run. To simplify the process, and avoid relying on the source instrumentation communicating to the project instrumentation the sources it created, we will clean up beforehand all of the -gnatcov-instr directories in the project tree. Ref: eng/cov/gnatcoverage#18 --- tools/gnatcov/instrument-c.adb | 4 +-- tools/gnatcov/instrument-clean_objdirs.adb | 33 +++++----------------- tools/gnatcov/instrument-clean_objdirs.ads | 7 ++--- tools/gnatcov/instrument-common.adb | 20 ++++++------- tools/gnatcov/instrument-common.ads | 14 +++------ tools/gnatcov/instrument.adb | 11 +++----- 6 files changed, 27 insertions(+), 62 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 7d135aed8..f31054dc0 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2842,8 +2842,9 @@ package body Instrument.C is Preprocessor_Output_File : Ada.Text_IO.File_Type; -- File containing the preprocessor output (used to get include search -- paths). - begin + PP_Filename := +New_File (Info, Filename); + Cmd := (Command => +Compiler_Driver (Info.Project, Instrumenter.Language), others => <>); @@ -2952,7 +2953,6 @@ package body Instrument.C is -- Now, onto the postprocessing. Remove spurious system header line -- markers. - PP_Filename := +Register_New_File (Info, Filename); Postprocess_Source (Preprocessed_Filename, +PP_Filename); Ada.Directories.Delete_File (Preprocessed_Filename); end Preprocess_Source; diff --git a/tools/gnatcov/instrument-clean_objdirs.adb b/tools/gnatcov/instrument-clean_objdirs.adb index ab8f19209..5051ad259 100644 --- a/tools/gnatcov/instrument-clean_objdirs.adb +++ b/tools/gnatcov/instrument-clean_objdirs.adb @@ -20,21 +20,15 @@ with Ada.Directories; use Ada.Directories; with GNATCOLL.Projects; use GNATCOLL.Projects; -with Outputs; use Outputs; -with Strings; use Strings; +with Instrument.Common; use Instrument.Common; with Project; -procedure Instrument.Clean_Objdirs (IC : Inst_Context) is - use Project_Info_Maps; - - All_Instr_Files : String_Sets.Set; - -- Set of full names for all files that were written to output directories - -- for all instrumented projects. +procedure Instrument.Clean_Objdirs is procedure Clean_Subdir (Project : Project_Type); -- Callback for Project.Iterate_Projects. If Project is not externally -- built, remove all files from the "$project_name-gnatcov-instr" folder in - -- Project's object directory that we did not just instrument. + -- Project's object directory. ------------------ -- Clean_Subdir -- @@ -58,28 +52,15 @@ procedure Instrument.Clean_Objdirs (IC : Inst_Context) is return; end if; - Clean_Dir - (Dir => Output_Dir, - Pattern => "", - Ignored_Files => All_Instr_Files); - + Delete_Tree (Directory => Output_Dir); end Clean_Subdir; -- Start of processing for Instrument.Clean_Objdirs begin - -- First initialize All_Instr_Files - - for Cur in IC.Project_Info_Map.Iterate loop - for Filename of Element (Cur).Instr_Files loop - All_Instr_Files.Include (Filename); - end loop; - end loop; - - -- Then go through all projects to clear up their object directories, - -- ignoring files in All_Instr_Files. Also go through extended projects, as - -- their object directories can interfere with the build of the extending - -- project. + -- Go through all projects to clear up their object directories. Also go + -- through extended projects, as their object directories can interfere + -- with the build of the extending project. Project.Iterate_Projects (Root_Project => Project.Project.Root_Project, diff --git a/tools/gnatcov/instrument-clean_objdirs.ads b/tools/gnatcov/instrument-clean_objdirs.ads index 5e44952f9..8fe9a0098 100644 --- a/tools/gnatcov/instrument-clean_objdirs.ads +++ b/tools/gnatcov/instrument-clean_objdirs.ads @@ -16,8 +16,5 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Instrument.Common; use Instrument.Common; - -procedure Instrument.Clean_Objdirs (IC : Inst_Context); --- Remove sources in output directories that were not generated during this --- instrumentation process. +procedure Instrument.Clean_Objdirs; +-- Delete instrumentation output directories diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 98ef80f93..90b462450 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -233,8 +233,6 @@ package body Instrument.Common is Self.Output_Filename := To_Unbounded_String (Output_Filename); Self.Unit := Unit; Self.Handle := Start_Rewriting (IC.Context); - - Info.Instr_Files.Insert (To_Unbounded_String (Output_Filename)); end Start_Rewriting; -------------------- @@ -566,8 +564,7 @@ package body Instrument.Common is Result : constant Project_Info_Access := new Project_Info' (Project => Project, Externally_Built => Project.Externally_Built, - Output_Dir => +Project_Output_Dir (Storage_Project), - Instr_Files => <>); + Output_Dir => +Project_Output_Dir (Storage_Project)); begin Context.Project_Info_Map.Insert (Project_Name, Result); return Result; @@ -684,21 +681,20 @@ package body Instrument.Common is end; end Add_Instrumented_Unit; - ----------------------- - -- Register_New_File -- - ----------------------- + -------------- + -- New_File -- + -------------- - function Register_New_File - (Info : in out Project_Info; Name : String) return String + function New_File + (Info : Project_Info; Name : String) return String is Base_Filename : constant String := Ada.Directories.Simple_Name (Name); Output_Filename : constant String := To_String (Info.Output_Dir) / Base_Filename; begin - Info.Instr_Files.Insert (To_Unbounded_String (Output_Filename)); return Output_Filename; - end Register_New_File; + end New_File; ----------------- -- Create_File -- @@ -709,7 +705,7 @@ package body Instrument.Common is File : in out Text_Files.File_Type; Name : String) is - Filename : constant String := Register_New_File (Info, Name); + Filename : constant String := New_File (Info, Name); begin File.Create (Filename); end Create_File; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index d5751e713..6d5e5fe40 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -182,11 +182,6 @@ package Instrument.Common is Output_Dir : Ada.Strings.Unbounded.Unbounded_String; -- Subdirectory in the project file's object directory. All we generate -- for this project must land in it. - - Instr_Files : aliased File_Sets.Set; - -- Set of full names for files that were written to Output_Dir for this - -- project. Note that in the case of project extension, more than one - -- project may use the same output directory. end record; type Project_Info_Access is access all Project_Info; @@ -348,17 +343,16 @@ package Instrument.Common is Source_File : GNATCOLL.Projects.File_Info); -- Add the given source file to the list of units to instrument - function Register_New_File - (Info : in out Project_Info; Name : String) return String; - -- Helper for Create_File and Start_Rewriting: compute the path to the file - -- to create and register it to Info.Instr_Files. + function New_File + (Info : Project_Info; Name : String) return String; + -- Compute the path to the file to create in Info.Output_Dir procedure Create_File (Info : in out Project_Info; File : in out Text_Files.File_Type; Name : String); -- Shortcut to Text_Files.Create: create a text file with the given name in - -- Info.Output_Dir and register it in Info.Instr_Files. + -- Info.Output_Dir. -- -- Name can be a basename, a relative name or an absolute one: in all -- cases, the basename is taken and the file is created in Info.Output_Dir. diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index fda088569..51094d74d 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -457,6 +457,10 @@ package body Instrument is -- Start of processing for Instrument_Units_Of_Interest begin + -- Delete output directories from previous instrumentations + + Clean_Objdirs; + -- First get the list of all units of interest for Lang in Src_Supported_Language loop @@ -670,13 +674,6 @@ package body Instrument is end loop; end loop; - -- Remove sources in IC.Output_Dir that we did not generate this time. - -- They are probably left overs from previous instrumentations for units - -- that are no longer of interest. It is crucial not to make them part - -- of next builds. - - Clean_Objdirs (IC); - -- Deallocate Ignored_Unit_Infos for IU of Ignored_Units loop From 81c7a30516f1e1ab606af2a33e677d3cff28eecc Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 15 Feb 2023 16:05:14 +0000 Subject: [PATCH 0155/1483] Make glob patterns for filenames case sensitive on non-Windows systems This should have been the case (file names are case insensitive only on Windows systems), but the work for NA07-015 has probably changed this by accident. TN: W208-010 --- testsuite/tests/ignored-casing/main.adb | 6 +++++ testsuite/tests/ignored-casing/pkg.adb | 10 ++++++++ testsuite/tests/ignored-casing/pkg.ads | 3 +++ testsuite/tests/ignored-casing/test.py | 32 +++++++++++++++++++++++++ tools/gnatcov/inputs.adb | 27 ++++++++++++++------- tools/gnatcov/inputs.ads | 19 ++++++++++----- tools/gnatcov/project.adb | 13 ++++++---- 7 files changed, 90 insertions(+), 20 deletions(-) create mode 100644 testsuite/tests/ignored-casing/main.adb create mode 100644 testsuite/tests/ignored-casing/pkg.adb create mode 100644 testsuite/tests/ignored-casing/pkg.ads create mode 100644 testsuite/tests/ignored-casing/test.py diff --git a/testsuite/tests/ignored-casing/main.adb b/testsuite/tests/ignored-casing/main.adb new file mode 100644 index 000000000..10e85a255 --- /dev/null +++ b/testsuite/tests/ignored-casing/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Do_Things; +end Main; diff --git a/testsuite/tests/ignored-casing/pkg.adb b/testsuite/tests/ignored-casing/pkg.adb new file mode 100644 index 000000000..39d405e46 --- /dev/null +++ b/testsuite/tests/ignored-casing/pkg.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Do_Things is + begin + Put_Line ("Hello, world!"); + end Do_Things; + +end Pkg; diff --git a/testsuite/tests/ignored-casing/pkg.ads b/testsuite/tests/ignored-casing/pkg.ads new file mode 100644 index 000000000..d7efa61ac --- /dev/null +++ b/testsuite/tests/ignored-casing/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Do_Things; +end Pkg; diff --git a/testsuite/tests/ignored-casing/test.py b/testsuite/tests/ignored-casing/test.py new file mode 100644 index 000000000..a41fc7829 --- /dev/null +++ b/testsuite/tests/ignored-casing/test.py @@ -0,0 +1,32 @@ +""" +Check that, except on Windows, the casing of glob patterns for +--ignore-source-files is significant. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.control import env +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[ + "--annotate=xcov", + "--ignore-source-files=Pkg.adb", + ], +) + +expected_reports = { + "main.adb.xcov": {"+": {5}}, +} +if env.build.os.name != "windows": + expected_reports["pkg.adb.xcov"] = {"+": {7}} + +check_xcov_reports("*.xcov", expected_reports, "obj") + +thistest.result() diff --git a/tools/gnatcov/inputs.adb b/tools/gnatcov/inputs.adb index b4ca574b9..300aac1cd 100644 --- a/tools/gnatcov/inputs.adb +++ b/tools/gnatcov/inputs.adb @@ -267,9 +267,10 @@ package body Inputs is -------------------- procedure Create_Matcher - (Pattern_List : String_Vectors.Vector; - Matcher : out GNAT.Regexp.Regexp; - Has_Matcher : out Boolean) + (Pattern_List : String_Vectors.Vector; + Matcher : out GNAT.Regexp.Regexp; + Has_Matcher : out Boolean; + Case_Insensitive : Boolean := False) is use Ada.Strings.Unbounded; use String_Vectors; @@ -293,7 +294,11 @@ package body Inputs is ------------- procedure Process (C : Cursor) is - Glob_Pattern : constant String := To_Lower (+Element (C)); + Raw_Pattern : constant String := +String_Vectors.Element (C); + Glob_Pattern : constant String := + (if Case_Insensitive + then To_Lower (Raw_Pattern) + else Raw_Pattern); begin -- Ignore blank lines @@ -320,12 +325,16 @@ package body Inputs is end Create_Matcher; procedure Create_Matcher - (Pattern_List : Inputs.Inputs_Type; - Matcher : out GNAT.Regexp.Regexp; - Has_Matcher : out Boolean) - is + (Pattern_List : Inputs.Inputs_Type; + Matcher : out GNAT.Regexp.Regexp; + Has_Matcher : out Boolean; + Case_Insensitive : Boolean := False) is begin - Create_Matcher (To_String_Vector (Pattern_List), Matcher, Has_Matcher); + Create_Matcher + (To_String_Vector (Pattern_List), + Matcher, + Has_Matcher, + Case_Insensitive); end Create_Matcher; end Inputs; diff --git a/tools/gnatcov/inputs.ads b/tools/gnatcov/inputs.ads index 00cfe7743..b53251ec3 100644 --- a/tools/gnatcov/inputs.ads +++ b/tools/gnatcov/inputs.ads @@ -80,17 +80,24 @@ package Inputs is -- Convert an inputs list into a String_Vectors.Vector procedure Create_Matcher - (Pattern_List : String_Vectors.Vector; - Matcher : out GNAT.Regexp.Regexp; - Has_Matcher : out Boolean); + (Pattern_List : String_Vectors.Vector; + Matcher : out GNAT.Regexp.Regexp; + Has_Matcher : out Boolean; + Case_Insensitive : Boolean := False); -- If Pattern_List is empty, leave Matcher uninitialized and set -- Has_Matcher to False. Otherwise, set it to True and put in Matcher a -- pattern matching each of the globbing patterns in Pattern_List. + -- + -- If Case_Insensitive is True, the returned matcher is made case + -- insensitive. Note that it may be case insensitive even if + -- Case_Insensitive is False (for instance on Windows, where all glob + -- patterns are interpreted as case insensitive). procedure Create_Matcher - (Pattern_List : Inputs.Inputs_Type; - Matcher : out GNAT.Regexp.Regexp; - Has_Matcher : out Boolean); + (Pattern_List : Inputs.Inputs_Type; + Matcher : out GNAT.Regexp.Regexp; + Has_Matcher : out Boolean; + Case_Insensitive : Boolean := False); -- Overload to work on Inputs.Inputs_Type values private diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 5a6222cae..1c4ff0d6d 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -1067,11 +1067,14 @@ package body Project is Iterate (Override_Units, Add_Pattern'Access); - -- Then, create a regexp matching all the patterns specified - - Create_Matcher (Pattern_List => Unit_Patterns, - Matcher => Units_Specified_Matcher, - Has_Matcher => Has_Matcher); + -- Then, create a regexp matching all the patterns specified. + -- Regardless of the current platform, the casing of unit names is not + -- significant: the Foo unit is the same as the foo unit. + + Create_Matcher (Pattern_List => Unit_Patterns, + Matcher => Units_Specified_Matcher, + Has_Matcher => Has_Matcher, + Case_Insensitive => True); -- Now go through all selected projects to find units of interest From ca50911b982e8534dd2a353823cb291fc865b753 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 16 Feb 2023 09:01:03 +0000 Subject: [PATCH 0156/1483] paths.ads: minor reformatting TN: W208-010 --- tools/gnatcov/paths.ads | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/gnatcov/paths.ads b/tools/gnatcov/paths.ads index 684d1d37b..c66f5c407 100644 --- a/tools/gnatcov/paths.ads +++ b/tools/gnatcov/paths.ads @@ -30,14 +30,14 @@ package Paths is function Build_Filename (Dir : String; Filename : String) return String_Access; - -- Create a filename from a directory name and a filename. - -- The directory name is expected to be not empty and the result - -- is _not_ canonicalized (left to the callers to decide). + -- Create a filename from a directory name and a filename. The directory + -- name is expected to be not empty and the result is _not_ canonicalized + -- (left to the callers to decide). function "/" (Dir, Name : String) return String is (Ada.Directories.Compose (Dir, Name)); - -- Likewise, without the "dir shouldn't be empty" constraint but - -- checking that the path components are valid when not empty. + -- Likewise, without the "dir shouldn't be empty" constraint but checking + -- that the path components are valid when not empty. function Fold_Filename_Casing (Filename : String) return String; -- If this is a windows host, return the lower-cased filename, otherwise @@ -46,17 +46,17 @@ package Paths is function Canonicalize_Filename (Filename : String) return String; function Canonicalize_Filename (Filename : String) return String_Access; -- Assuming Filename is a full pathname to a file, return a normalized - -- version of it such that different references to the same file map to - -- the same canonical string as much as possible. + -- version of it such that different references to the same file map to the + -- same canonical string as much as possible. function Glob_To_Regexp (Pattern : String) return String; - -- Convert the provided globbing Pattern to a regular expression. - -- This might be used for file name or unit name patterns. + -- Convert the provided globbing Pattern to a regular expression. This + -- might be used for file name or unit name patterns. function Is_Absolute_Path (Path : String) return Boolean; - -- Return whether Path is an absolute path. Unlike the GNAT runtime - -- version of the service, this one always matches both Windows or Unix - -- file path flavors. + -- Return whether Path is an absolute path. Unlike the GNAT runtime version + -- of the service, this one always matches both Windows or Unix file path + -- flavors. -- TODO??? Handle Unicode file names From a30277687f32c8484cf23a6bee458b1c2aafbc20 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 16 Feb 2023 09:10:42 +0000 Subject: [PATCH 0157/1483] Fix case insentivity of --ignore-source-files for "gnatcov instrument" TN: W208-010 --- testsuite/tests/ignored-casing/test.py | 34 +++++++++++++++++++------- tools/gnatcov/instrument-common.adb | 9 ++++--- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/testsuite/tests/ignored-casing/test.py b/testsuite/tests/ignored-casing/test.py index a41fc7829..45bd72570 100644 --- a/testsuite/tests/ignored-casing/test.py +++ b/testsuite/tests/ignored-casing/test.py @@ -11,22 +11,38 @@ Wdir("tmp_") +ignore_opt = "--ignore-source-files=Pkg.adb" +expected_reports = { + "main.adb.xcov": {"+": {5}}, +} +if env.build.os.name != "windows": + expected_reports["pkg.adb.xcov"] = {"+": {7}} + +gprsw = GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])) + +# First check --ignore-source-files on "gnatcov coverage" build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + gprsw=gprsw, covlevel="stmt", mains=["main"], extra_coverage_args=[ - "--annotate=xcov", - "--ignore-source-files=Pkg.adb", + "--annotate=xcov", "--output-dir=out-cov", ignore_opt ], ) +check_xcov_reports("*.xcov", expected_reports, "out-cov") -expected_reports = { - "main.adb.xcov": {"+": {5}}, -} -if env.build.os.name != "windows": - expected_reports["pkg.adb.xcov"] = {"+": {7}} +# Then check it on "gnatcov instrument". This separate test makes sense as +# --ignore-source-files exercises different code paths depending on the gnatcov +# command. -check_xcov_reports("*.xcov", expected_reports, "obj") +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_instr_args=[ignore_opt], + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], + trace_mode="src" +) +check_xcov_reports("*.xcov", expected_reports, "out-instr") thistest.result() diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 90b462450..62f77b5db 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -520,12 +520,13 @@ package body Instrument.Common is ---------------------------- function Is_Ignored_Source_File - (Context : Inst_Context; Filename : String) return Boolean - is + (Context : Inst_Context; Filename : String) return Boolean is begin return - Context.Ignored_Source_Files_Present - and then GNAT.Regexp.Match (Filename, Context.Ignored_Source_Files); + Context.Ignored_Source_Files_Present + and then GNAT.Regexp.Match + (S => Fold_Filename_Casing (Filename), + R => Context.Ignored_Source_Files); end Is_Ignored_Source_File; -------------------------------- From fd30a5a0c43a82b49889d85477e0f4bb7aaaccae Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 9 Feb 2023 15:35:30 +0000 Subject: [PATCH 0158/1483] SCOV.instr: add missing argument documentations --- testsuite/SCOV/instr.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 079207907..32e93fd22 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -58,6 +58,8 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", option. :param bool warnings_as_errors: Whether to make the test fail if there are warnings in gnatcov's output. + :param bool register_failure: See SUITE.tutils.xcov. + :param bool auto_languages: See SUITE.tutils.xcov. See SUITE.tutils.xcov for the other supported options. """ From bc01dc02b3ada81ee4f29d31777169b59758bcf6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 9 Feb 2023 15:57:20 +0000 Subject: [PATCH 0159/1483] Instrument.C: emit a proper error message in case of missing compiler --- testsuite/SCOV/instr.py | 5 ++ testsuite/tests/instr-cov/no-compiler/main.c | 5 ++ testsuite/tests/instr-cov/no-compiler/test.py | 58 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 10 +++- 4 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/instr-cov/no-compiler/main.c create mode 100644 testsuite/tests/instr-cov/no-compiler/test.py diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 32e93fd22..176e6f44c 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -36,6 +36,7 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", dump_channel="auto", gpr_obj_dir=None, runtime_project=None, out=None, err=None, warnings_as_errors=True, register_failure=True, + auto_config_args=True, auto_target_args=True, auto_languages=True): """ Run "gnatcov instrument" on a project. @@ -59,6 +60,8 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", :param bool warnings_as_errors: Whether to make the test fail if there are warnings in gnatcov's output. :param bool register_failure: See SUITE.tutils.xcov. + :param bool auto_config_args: See SUITE.tutils.xcov. + :param bool auto_target_args: See SUITE.tutils.xcov. :param bool auto_languages: See SUITE.tutils.xcov. See SUITE.tutils.xcov for the other supported options. @@ -109,6 +112,8 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", out=out, err=err, register_failure=register_failure, + auto_config_args=auto_config_args, + auto_target_args=auto_target_args, auto_languages=auto_languages, ) diff --git a/testsuite/tests/instr-cov/no-compiler/main.c b/testsuite/tests/instr-cov/no-compiler/main.c new file mode 100644 index 000000000..398ec675a --- /dev/null +++ b/testsuite/tests/instr-cov/no-compiler/main.c @@ -0,0 +1,5 @@ +int +main (void) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/no-compiler/test.py b/testsuite/tests/instr-cov/no-compiler/test.py new file mode 100644 index 000000000..19d641520 --- /dev/null +++ b/testsuite/tests/instr-cov/no-compiler/test.py @@ -0,0 +1,58 @@ +""" +Check that gnatcov properly reports a missing C/C++ compiler in the +environment. It used to emit a cryptic error message: invalid path "". +""" + +from e3.fs import mkdir +from e3.os.process import DEVNULL, Run, STDOUT + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +# Create a configuration file so that only the Ada compiler is available to +# gnatcov. +config_file = "for_ada.cgpr" +Run( + [ + "gprconfig", + "--batch", + f"--target={env.target.triplet}", + "-o", + config_file, + f"--config=Ada,,{thistest.options.RTS or ''}", + ], + input=DEVNULL, + output="gprconfig.out", + error=STDOUT, +) + +# Avoid noisy "creating output path" messages +mkdir("obj") + +# Now run the instrumenter on a C project with this configuration file and +# check the error message. +output = "instr.log" +p = xcov_instrument( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + extra_args=[f"--config={config_file}"], + out=output, + auto_config_args=False, + auto_target_args=False, + register_failure=False, +) +thistest.fail_if_not_equal("'gnatcov instrument' exit code", 1, p.status) +thistest.fail_if_no_match( + "'gnatcov instrument' output", + ".*gnatcov.*: could not find a compiler for C", + contents_of(output).strip(), +) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index f31054dc0..d9b66afd9 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -564,8 +564,14 @@ package body Instrument.C is (Project : GNATCOLL.Projects.Project_Type; Language : C_Family_Language) return String is begin - return GNATCOLL.Projects.Attribute_Value - (Project, GPR.Compiler_Driver_Attribute, Image (Language)); + return Result : constant String := + GNATCOLL.Projects.Attribute_Value + (Project, GPR.Compiler_Driver_Attribute, Image (Language)) + do + if Result = "" then + Fatal_Error ("could not find a compiler for " & Image (Language)); + end if; + end return; end Compiler_Driver; ------------------------ From 8fc7fbbbed50205fb3d22a2ada66111ccc36fd7d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 20 Feb 2023 13:36:05 +0000 Subject: [PATCH 0160/1483] Instrument: fix a crash when Libadalang cannot find the parent decl This commit fixes a crash in the Ada instrumenter. The crash occurred when instrumenting an incomplete code closure: Libadalang can return a null node when it cannot find the "parent" declaration of the current unit (package Pkg for package Pkg.Child, for instance). In the new testcase, whether or not "gnatcov instrument" should skip the instrumentation of pkg-child.adb (just like gprbuild skips it), we should have defensive code to avoid the crash, and emit a warning instead. TN: W213-002 --- .../tests/instr-cov/orphan-unit/main.adb | 6 ++++ .../tests/instr-cov/orphan-unit/pkg-child.adb | 8 +++++ .../tests/instr-cov/orphan-unit/pkg-child.ads | 3 ++ testsuite/tests/instr-cov/orphan-unit/test.py | 35 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 29 +++++++++++++-- 5 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/instr-cov/orphan-unit/main.adb create mode 100644 testsuite/tests/instr-cov/orphan-unit/pkg-child.adb create mode 100644 testsuite/tests/instr-cov/orphan-unit/pkg-child.ads create mode 100644 testsuite/tests/instr-cov/orphan-unit/test.py diff --git a/testsuite/tests/instr-cov/orphan-unit/main.adb b/testsuite/tests/instr-cov/orphan-unit/main.adb new file mode 100644 index 000000000..6e16d750d --- /dev/null +++ b/testsuite/tests/instr-cov/orphan-unit/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello world"); +end Main; diff --git a/testsuite/tests/instr-cov/orphan-unit/pkg-child.adb b/testsuite/tests/instr-cov/orphan-unit/pkg-child.adb new file mode 100644 index 000000000..8f6b24be8 --- /dev/null +++ b/testsuite/tests/instr-cov/orphan-unit/pkg-child.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg.Child is + procedure Do_Things is + begin + Put_Line ("Doing things"); + end Do_Things; +end Pkg.Child; diff --git a/testsuite/tests/instr-cov/orphan-unit/pkg-child.ads b/testsuite/tests/instr-cov/orphan-unit/pkg-child.ads new file mode 100644 index 000000000..d3df3d14a --- /dev/null +++ b/testsuite/tests/instr-cov/orphan-unit/pkg-child.ads @@ -0,0 +1,3 @@ +package Pkg.Child is + procedure Do_Things; +end Pkg.Child; diff --git a/testsuite/tests/instr-cov/orphan-unit/test.py b/testsuite/tests/instr-cov/orphan-unit/test.py new file mode 100644 index 000000000..3448779b1 --- /dev/null +++ b/testsuite/tests/instr-cov/orphan-unit/test.py @@ -0,0 +1,35 @@ +""" +Check that instrumenting a project that contains an "orphan" unit (i.e. a +source file present in the project but not used in the build and not +compilable) works as expected. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +expected_cov = {"main.adb.xcov": {"+": {5}}} +if thistest.options.trace_mode == "src": + expected_cov["pkg-child.adb.xcov"] = {"-": {6}} + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + instrument_warnings_as_errors=False, + extra_coverage_args=["--annotate=xcov"], +) + +if thistest.options.trace_mode == "src": + thistest.fail_if_not_equal( + '"gnatcov instrument" output', + "warning: Cannot find required source file: pkg.ads", + contents_of("instrument.log").strip(), + ) + +check_xcov_reports("*.xcov", expected_cov, "obj") + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 330e3175b..db702cde8 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -983,6 +983,10 @@ package body Instrument.Ada_Unit is (Ret_Node : Return_Stmt; Subp : Subp_Body) return Boolean; -- Return whether Ret_Node is returning from Subp + function Parent_Decl (Decl : Basic_Decl'Class) return Basic_Decl; + -- Return the parent declaration for Decl, or No_Basic_Decl if Decl has no + -- parent, or if we cannot find it. + procedure Insert_Simple_Dump_Proc_Calls (RH : Rewriting_Handle; Helper_Unit : Ada_Qualified_Name; @@ -2491,6 +2495,23 @@ package body Instrument.Ada_Unit is return True; end Return_From_Subp_Body; + ----------------- + -- Parent_Decl -- + ----------------- + + function Parent_Decl (Decl : Basic_Decl'Class) return Basic_Decl is + begin + return Decl.P_Parent_Basic_Decl; + exception + when Exc : Property_Error => + Report + (Node => Decl, + Msg => "Could not find the parent package: " + & Ada.Exceptions.Exception_Information (Exc), + Kind => Warning); + return No_Basic_Decl; + end Parent_Decl; + ----------------------------------------- -- Traverse_Declarations_Or_Statements -- ----------------------------------------- @@ -3993,13 +4014,17 @@ package body Instrument.Ada_Unit is begin while AUN /= Std loop declare - Root_Decl : constant Basic_Decl := + Root_Decl : constant Basic_Decl := AUN.Root.As_Compilation_Unit .F_Body.As_Library_Item.F_Item; + Parent : constant Basic_Decl := + Parent_Decl (Root_Decl); begin UIC.Withed_Units.Include (Root_Decl.P_Canonical_Fully_Qualified_Name); - AUN := Root_Decl.P_Parent_Basic_Decl.Unit; + + exit when Parent.Is_Null; + AUN := Parent.Unit; end; end loop; end; From b2f2a256a2a414bfd3786b43f6d1932d4f17537a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 16 Feb 2023 10:06:32 +0100 Subject: [PATCH 0161/1483] Add default for Instrument_Support scenario variable --- tools/gnatcov/gnatcov.gpr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index d449f428f..dccb2cec6 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -41,7 +41,7 @@ project Gnatcov is -- support at all, then for C more specifically: type Boolean is ("False", "True"); - Instrument_Support : Boolean := external("INSTRUMENT_SUPPORT"); + Instrument_Support : Boolean := external("INSTRUMENT_SUPPORT", "True"); C_Support : Boolean := external("C_SUPPORT", Instrument_Support); package Naming is From e9d7a2356a0a20baed24bc9f46cfaeda9e4657c0 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Fri, 17 Feb 2023 08:27:21 -0800 Subject: [PATCH 0162/1483] testsuite: evolve warnings_as_errors into tolerate_messages Replace the "warnings_as_errors" bool argument to xcov_instrument by a "tolerate_messages" regular expression for which matching warnings or errors shouldn't result in a test failure. This allows finer grain expression of what tests expect and addresses the slightly misleading aspect of the previous parameter name, which was also preventing failures on _errors_ when set to False. Tests in this repo are adjusted to new API and similar adjustments are to be provided for tests hosted in separate repositories. A secondary motivation for this change is to facilitate supporting tests doing instrumentation before builds without complaining about missing object dirs, in qualification contexts possibly using old versions of gnatcov. This part will come as a separate change. Part of W215-023 (gnatcov 22.2 qualification) --- .../No_Elab_InLib/mylib/obj/.gitignore | 0 .../GPR/Robustness/BadUnitInAttr/test.py | 2 +- .../GPR/Robustness/BadUnitInSwitch/test.py | 2 +- .../GPR/Robustness/NoContribPrj/test.py | 2 +- .../GPR/Robustness/UnitNotInProjects/test.py | 2 +- testsuite/SCOV/instr.py | 31 ++++++++++++++----- testsuite/SCOV/minicheck.py | 9 +++--- testsuite/tests/15-non-instr-cons/test.py | 3 +- .../tests/excluded_unit_imported_prj/test.py | 2 +- testsuite/tests/instr-cov/orphan-unit/test.py | 2 +- 10 files changed, 37 insertions(+), 18 deletions(-) delete mode 100644 testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/obj/.gitignore diff --git a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/obj/.gitignore b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/obj/.gitignore deleted file mode 100644 index e69de29bb..000000000 diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py index 7a39230ff..e8ce851e8 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py @@ -18,7 +18,7 @@ extra=gprcov_for(units_in=['no_such_unit', 'main']))), covlevel='stmt', mains=['main'], - instrument_warnings_as_errors=False, + tolerate_instrument_messages="no unit.*in project", extra_coverage_args=['-axcov'], ) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py index c234c62f2..a1a571dda 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py @@ -16,7 +16,7 @@ units=['no_such_unit', 'main', 'helper.say_hello']), covlevel='stmt', mains=['main'], - instrument_warnings_as_errors=False, + tolerate_instrument_messages="no unit.*in the projects of interest", extra_coverage_args=['-axcov'], ) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py index 7d6132bfa..6130d32d1 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py @@ -79,7 +79,7 @@ def run_test(label, slug, main, helper, recursive, projects=[], units=[], covlevel='stmt', mains=['main'], gpr_obj_dir='obj-main', - instrument_warnings_as_errors=False, + tolerate_instrument_messages="project.*provides no unit", extra_coverage_args=['-axcov'], ) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py index 02b1bc45f..628a47c15 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py @@ -29,7 +29,7 @@ covlevel='stmt', mains=['main'], gpr_obj_dir='obj-main', - instrument_warnings_as_errors=False, + tolerate_instrument_messages="no unit.*in the projects", extra_coverage_args=['-axcov'], ) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 176e6f44c..5f9af2477 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -35,7 +35,7 @@ def default_dump_channel(): def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", dump_channel="auto", gpr_obj_dir=None, runtime_project=None, out=None, err=None, - warnings_as_errors=True, register_failure=True, + tolerate_messages=None, register_failure=True, auto_config_args=True, auto_target_args=True, auto_languages=True): """ @@ -57,8 +57,9 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", :param None|str runtime_project: If None, use the default name for the instrumentation runtime project. Otherwise, use the name given for this option. - :param bool warnings_as_errors: Whether to make the test fail if there are - warnings in gnatcov's output. + :param None|str tolerate_messages: If not None, a re pattern of warning + or error messsages tolerated in the tool output. Messages not matching + this pattern will cause a test failure when register_failure is True. :param bool register_failure: See SUITE.tutils.xcov. :param bool auto_config_args: See SUITE.tutils.xcov. :param bool auto_target_args: See SUITE.tutils.xcov. @@ -117,13 +118,29 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", auto_languages=auto_languages, ) - if register_failure and warnings_as_errors: + if register_failure: output = contents_of(out) + # Check for unexpected messages. Beware that the "warning:" + # indication at least is not necessarily at the beginning of + # a line, as in + # + # app.gpr:4:23: warning: object directory "obj" not found + + messages = re.findall( + pattern="(?:!!!|\*\*\*|warning:).*$", string=output, + flags=re.MULTILINE) + + re_tolerate_messages = tolerate_messages or "__NEVER_IN_A_WARNING___" + unexpected_messages = [ + w for w in messages + if not re.search(pattern=re_tolerate_messages, string=w) + ] thistest.fail_if( - "***" in output or "!!!" in output or "warning:" in output, - f"Warnings/errors detected in the output of 'gnatcov instrument':" - f"\n{indent(output)}" + unexpected_messages, + f"Unexpected messages in the output of 'gnatcov instrument':" + f"\n{indent(output)}" + \ + (f"\n(allowed: {tolerate_messages})" if tolerate_messages else "") ) return result diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 4ca1eb2ec..783fb8b4b 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -36,7 +36,7 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, check_gprbuild_output=False, trace_mode=None, runtime_project=None, gprsw_for_coverage=None, scos_for_run=True, register_failure=True, program_env=None, - instrument_warnings_as_errors=True, exec_args=None, + tolerate_instrument_messages=None, exec_args=None, auto_languages=True): """ Prepare a project to run a coverage analysis on it. @@ -100,8 +100,9 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, exits with a non-zero status code, stop with a FatalError. :param None|dict[str, str] program_env: If not none, environment variables for the program to run. - :param bool instrument_warnings_as_errors: Whether to make the test fail if - there are warnings in the output of "gnatcov instrument". + :param None|str tolerate_instrument_messages: If not None, a re pattern + of error or warning messages tolerated in the "gnatcov instrument" + output. :param None|list[str] exec_args: List of arguments to pass to the executable. This will only work for native configurations. :param bool auto_languages: See SUITE.tutils.xcov. @@ -207,7 +208,7 @@ def gprbuild_wrapper(root_project): runtime_project=runtime_project, out='instrument.log', register_failure=register_failure, - warnings_as_errors=instrument_warnings_as_errors, + tolerate_messages=tolerate_instrument_messages, auto_languages=auto_languages) gprbuild_wrapper(gprsw.root_project) diff --git a/testsuite/tests/15-non-instr-cons/test.py b/testsuite/tests/15-non-instr-cons/test.py index e61358212..0094a59c1 100644 --- a/testsuite/tests/15-non-instr-cons/test.py +++ b/testsuite/tests/15-non-instr-cons/test.py @@ -27,7 +27,8 @@ covlevel="stmt", mains=["test_f", "test_t"], trace_mode="src", - instrument_warnings_as_errors=False, + tolerate_instrument_messages=\ + "gnatcov limitation: cannot instrument an expression function", ) trace_t = xcov_args.pop() diff --git a/testsuite/tests/excluded_unit_imported_prj/test.py b/testsuite/tests/excluded_unit_imported_prj/test.py index 7e84f330b..0991ac8d6 100644 --- a/testsuite/tests/excluded_unit_imported_prj/test.py +++ b/testsuite/tests/excluded_unit_imported_prj/test.py @@ -26,7 +26,7 @@ covlevel='stmt+mcdc', mains=['test'], extra_coverage_args=['--annotate=xcov'], - instrument_warnings_as_errors=False, + tolerate_instrument_messages="no unit .* in project", ) warning_file = ('coverage.log' if thistest.options.trace_mode == 'bin' else 'instrument.log') diff --git a/testsuite/tests/instr-cov/orphan-unit/test.py b/testsuite/tests/instr-cov/orphan-unit/test.py index 3448779b1..430a24fd9 100644 --- a/testsuite/tests/instr-cov/orphan-unit/test.py +++ b/testsuite/tests/instr-cov/orphan-unit/test.py @@ -19,7 +19,7 @@ gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), covlevel="stmt", mains=["main"], - instrument_warnings_as_errors=False, + tolerate_instrument_messages="Cannot find required source file", extra_coverage_args=["--annotate=xcov"], ) From 878baeed08a758f3aac9076103d7605f9c03eab6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 27 Feb 2023 15:26:15 +0000 Subject: [PATCH 0163/1483] Subprocesses: remove the "empty command" special case This special case is not intuitive and not really needed. Remove it, which will allow code simplification in upcoming refactorings. Complement for eng/cov/gnatcoverage!60 --- tools/gnatcov/rundrv.adb | 10 +++++++++- tools/gnatcov/subprocesses.adb | 7 ------- tools/gnatcov/subprocesses.ads | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/rundrv.adb b/tools/gnatcov/rundrv.adb index 391deca8f..b923a1d1f 100644 --- a/tools/gnatcov/rundrv.adb +++ b/tools/gnatcov/rundrv.adb @@ -18,6 +18,7 @@ with Ada.Directories; use Ada.Directories; with Ada.Environment_Variables; +with Ada.Strings.Unbounded; with Ada.Unchecked_Conversion; with Interfaces; @@ -36,6 +37,7 @@ with Traces_Files; use Traces_Files; package body Rundrv is package Env renames Ada.Environment_Variables; + package US renames Ada.Strings.Unbounded; Native_Warning : constant String := "Support for coverage of non-instrumented native programs is deprecated" @@ -165,8 +167,14 @@ package body Rundrv is -- Note that as far as "gnatcov run" is concerned, a non-zero status -- code from this subprocess is not an error for trace production, as it -- may reflect a non-zero status code from the user program. + -- + -- Also note that for the special "prepare*" targets, we do not have any + -- command to run, as we just need to create the trace file header: do + -- not call Run_Command in this case. - Dummy := Run_Command (Run_Cmd, "gnatcov run", Ignore_Error => True); + if US.Length (Run_Cmd.Command) > 0 then + Dummy := Run_Command (Run_Cmd, "gnatcov run", Ignore_Error => True); + end if; end Driver; end Rundrv; diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index d1a75c580..83d24eb64 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -156,13 +156,6 @@ package body Subprocesses is raise Program_Error; end if; - -- Honor a possible empty command text, meaning no actual - -- command to run. - - if Command'Length = 0 then - return True; - end if; - -- Find the actual executable to execute Program := GNAT.OS_Lib.Locate_Exec_On_Path (Command); diff --git a/tools/gnatcov/subprocesses.ads b/tools/gnatcov/subprocesses.ads index 080800dba..a0fd1020e 100644 --- a/tools/gnatcov/subprocesses.ads +++ b/tools/gnatcov/subprocesses.ads @@ -30,7 +30,7 @@ package Subprocesses is type Command_Type is record Command : Ada.Strings.Unbounded.Unbounded_String; - -- Command to run or empty string if there is no command to run + -- Command (executable file) to run Arguments : String_Vectors.Vector; -- Arguments to pass to this command From 14ae89467f31db527be0a495d22609da76dd6134 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 13 Jan 2023 12:25:42 +0100 Subject: [PATCH 0164/1483] Instrument: change implementation of Compilation_Unit_Name comparison It used to rely on the slug comparison, which was very uneffective as it meant calculating the slug, and then do the comparison. --- tools/gnatcov/instrument-base_types.adb | 81 +++++++++++++++++++++++-- tools/gnatcov/instrument-base_types.ads | 2 - 2 files changed, 77 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/instrument-base_types.adb b/tools/gnatcov/instrument-base_types.adb index 2b383d7b2..fee57845c 100644 --- a/tools/gnatcov/instrument-base_types.adb +++ b/tools/gnatcov/instrument-base_types.adb @@ -16,8 +16,12 @@ -- of the license. -- ------------------------------------------------------------------------------ +with Ada.Containers; use Ada.Containers; with Ada.Characters.Handling; use Ada.Characters.Handling; -with Interfaces; use Interfaces; +with Ada.Strings.Unbounded.Equal_Case_Insensitive; +with Ada.Strings.Unbounded.Less_Case_Insensitive; + +with Interfaces; use Interfaces; with GNATCOLL.VFS; @@ -61,16 +65,85 @@ package body Instrument.Base_Types is function "<" (Left, Right : Compilation_Unit_Name) return Boolean is begin - return Instrumented_Unit_Slug (Left) < Instrumented_Unit_Slug (Right); + if Left.Language_Kind = Right.Language_Kind then + case Left.Language_Kind is + when Unit_Based_Language => + if Left.Part = Right.Part then + if Left.Unit.Length = Right.Unit.Length then + for I in 1 .. Integer (Left.Unit.Length) loop + declare + Left_Id : constant Unbounded_String := + Unbounded_String (Left.Unit.Element (I)); + Right_Id : constant Unbounded_String := + Unbounded_String (Right.Unit.Element (I)); + begin + if not Equal_Case_Insensitive (Left_Id, Right_Id) + then + return Less_Case_Insensitive (Left_Id, Right_Id); + end if; + end; + end loop; + + -- If we get there, they are equal + + return False; + else + return Left.Unit.Length < Right.Unit.Length; + end if; + else + return Left.Part < Right.Part; + end if; + when File_Based_Language => + if Equal_Case_Insensitive + (Left.Project_Name, Right.Project_Name) + then + return Left.Filename < Right.Filename; + else + return Less_Case_Insensitive + (Left.Project_Name, Right.Project_Name); + end if; + end case; + else + return Left.Language_Kind < Right.Language_Kind; + end if; end "<"; --------- -- "=" -- --------- - function "=" (Left, Right : Compilation_Unit_Name) return Boolean is + function "=" (Left, Right : Compilation_Unit_Name) return Boolean + is + use Ada_Identifier_Vectors; begin - return Instrumented_Unit_Slug (Left) = Instrumented_Unit_Slug (Right); + if Left.Language_Kind = Right.Language_Kind then + case Left.Language_Kind is + when Unit_Based_Language => + if Left.Part = Right.Part + and then Left.Unit.Length = Right.Unit.Length + then + for I in 1 .. Integer (Left.Unit.Length) loop + if not Equal_Case_Insensitive + (Unbounded_String (Left.Unit.Element (I)), + Unbounded_String (Right.Unit.Element (I))) + then + return False; + end if; + end loop; + + -- If we get there, they are equal + + return True; + end if; + return False; + when File_Based_Language => + return Left.Filename = Right.Filename + and then Equal_Case_Insensitive + (Left.Project_Name, Right.Project_Name); + end case; + else + return False; + end if; end "="; ------------------------- diff --git a/tools/gnatcov/instrument-base_types.ads b/tools/gnatcov/instrument-base_types.ads index 99dc1c449..711ec91c3 100644 --- a/tools/gnatcov/instrument-base_types.ads +++ b/tools/gnatcov/instrument-base_types.ads @@ -87,8 +87,6 @@ package Instrument.Base_Types is function "=" (Left, Right : Compilation_Unit_Name) return Boolean; function "<" (Left, Right : Compilation_Unit_Name) return Boolean; - -- Compare the result of a call to Instrumented_Unit_Slug (which gives - -- unique identifiers for each compilation unit name) for both operands. function Image (CU_Name : Compilation_Unit_Name) return String; -- Return a string representation of CU_Name for use in diagnostics From 63956cfa01f613d3567f2ec4e5cbb827e181393f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Fri, 17 Feb 2023 17:46:04 +0100 Subject: [PATCH 0165/1483] Display exempted violation messages in report format The coverage violations that are within an exempted region are displayed in the corresponding report section when the "--all-messages" is passed. TN: TC31-001 --- testsuite/SCOV/internals/driver.py | 11 +- testsuite/SCOV/internals/rnexpanders.py | 182 +++++++++++++--- testsuite/SCOV/report.py | 3 +- .../TC31-001-show-exempted/src/exemptions.adb | 26 +++ .../TC31-001-show-exempted/src/test_1.adb | 16 ++ .../tests/TC31-001-show-exempted/test.py | 8 + tools/gnatcov/annotations-report.adb | 196 ++++++++++++------ 7 files changed, 343 insertions(+), 99 deletions(-) create mode 100644 testsuite/tests/TC31-001-show-exempted/src/exemptions.adb create mode 100644 testsuite/tests/TC31-001-show-exempted/src/test_1.adb create mode 100644 testsuite/tests/TC31-001-show-exempted/test.py diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index cbe22ae4b..2296a487e 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -882,7 +882,16 @@ def check_expectations(self): # Checking that we do have the expected reports will be performed by # the regular coverage expectation assessments triggered below. - self.ernotes = RnotesExpander("test.rep").ernotes + # Check if the "--all-messages" switch is activated. In the case of + # exempted violations, its use causes the report to show different + # informations than would otherwise be expected and that needs to be + # checked. + + all_messages = "--all-messages" in self.covoptions + + self.ernotes = RnotesExpander( + "test.rep", + all_messages=all_messages).ernotes if self.covctl and self.covctl.xreports is not None: self.check_unexpected_reports() diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index 93b0cff0a..cd95c5e9b 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -128,7 +128,7 @@ def ends_on(self, rline): self.end_hits.append(rline) return p - def check(self): + def check(self, all_messages=False): """ Once we're done reading the entire report, sanity check what we found for this block. Raise a test failure. @@ -205,8 +205,6 @@ def __init__(self, re_notes): self.enotes = [] - # def nkind_for(self, rline) - def try_parse_enote(self, rline): dline = Rdiagline_from(rline) @@ -241,9 +239,16 @@ def __stag_replacement_for(m): enote.kind = self.nkind_for(this_diag) + return self.check_enote(this_diag, enote) + + def report_unexpected_enote(self, rline): + thistest.failed("(%s report section) '%s' does not" + " correspond to any expected violation note" + % (self.name, rline.rstrip('\n'))) + + def check_enote(self, rline, enote): if enote.kind is None: - thistest.failed("(%s =report section) '%s' ?" - % (self.name, rline.rstrip('\n'))) + self.report_unexpected_enote(rline) return None else: return enote @@ -254,7 +259,7 @@ def try_parse(self, rline): self.enotes.append(enote) return enote - def __validate_ecount(self, count): + def validate_ecount(self, count): self.ecount = len(self.enotes) thistest.fail_if( count != self.ecount, @@ -265,7 +270,7 @@ def __validate_ecount(self, count): def ends_on(self, rline): p = Rblock.ends_on(self, rline) if p: - self.__validate_ecount(count=self.value(p.group(1))) + self.validate_ecount(count=self.value(p.group(1))) return p def re_summary(self): @@ -332,11 +337,94 @@ def nkind_for(self, rline): class XREchapter(Nchapter): """Exemptions Regions chapter.""" - def __init__(self, re_start, re_notes): + + def __init__(self, re_start, re_notes, exempted_notes, + all_messages=False): + + self.all_messages = all_messages + + # The list of notes acceptable for an exempted violation + self.exempted_notes = exempted_notes + + self.ecount_violations = 0 + + re_end = (r"(No|\d+) exempted region[s]*, " + r"(No|\d+) exempted violation[s]*\.$") + Nchapter.__init__(self, re_start=re_start, - re_end=r"(No|\d+) exempted region[s]*\.$", + re_end=re_end, re_notes=re_notes) + def __check_summary_count(self, sec, sum_count, sec_count): + thistest.fail_if( + sum_count != sec_count, + "summary count %d != section count %d for %s" % ( + sum_count, sec_count, sec.name)) + thistest.fail_if( + len(sec.start_hits) != 1, + "summary found for section starts != 1 (%s)" % sec.name) + + def check_exempted_summary(self, sec, p): + self.__check_summary_count(sec, + self.value(p.group(1)), + len(self.enotes)) + + if self.all_messages: + self.__check_summary_count(sec, + self.value(p.group(2)), + self.ecount_violations) + + def __validate(self, actual_count, count, element_counted): + thistest.fail_if( + actual_count != count, + "(%s report section) recognized %d notes != summary (%d)" + "for (%s)\n" + % (self.name, actual_count, count, element_counted) + ) + + def ends_on(self, rline): + if not self.all_messages: + return Rblock.ends_on(self, rline) + else: + p = Rblock.ends_on(self, rline) + if p: + # Validate the number of exempted regions + self.__validate(len(self.enotes), + self.value(p.group(1)), + "exempted regions") + + # Validate the total number of exempted violations + self.__validate(self.ecount_violations, + self.value(p.group(2)), + "exempted violations") + return p + + def check_enote(self, rline, enote): + + # Within an exempted region, if the "--all-messages" switch is ised + # we expect the exempted violations to still be displayed. + # Enote.kind being None means that rline could be one of those. + + if enote.kind is None and self.all_messages: + exempted = False + + # Check that rline does indeed correspond to an exempted + # violation. The report does not provide any information regarding + # their type. We can only check their number. + + for key in self.exempted_notes: + if re.match(key, rline): + self.ecount_violations += 1 + exempted = True + break + + if not exempted: + self.report_unexpected_enote(rline) + + return None + else: + return enote + class NCIchapter(Nchapter): """Non-coverable Items chapter.""" @@ -371,15 +459,22 @@ def __init__(self, re_start, skeys): def try_match(self, sec, rline): p = re.match(self.skeys[sec], rline) if p: - sum_count = self.value(p.group(1)) - sec_count = sec.ecount - thistest.fail_if( - sum_count != sec_count, - "summary count %d != section count %d for %s" % ( - sum_count, sec_count, sec.name)) - thistest.fail_if( - len(sec.start_hits) != 1, - "summary found for section starts != 1 (%s)" % sec.name) + # If the check is done on the exempted regions chapter and the + # the "--all-messages" switch is used then the verification has + # to be done on the number of regions and the number of violations + + if sec.name == 'EXEMPTED REGIONS': + sec.check_exempted_summary(sec, p) + else: + sum_count = self.value(p.group(1)) + sec_count = sec.ecount + thistest.fail_if( + sum_count != sec_count, + "summary count %d != section count %d for %s" % ( + sum_count, sec_count, sec.name)) + thistest.fail_if( + len(sec.start_hits) != 1, + "summary found for section starts != 1 (%s)" % sec.name) self.checked[sec] = True def try_parse(self, rline): @@ -388,11 +483,20 @@ def try_parse(self, rline): self.try_match(sec, rline) return None - def check(self): + def check(self, all_messages=False): Rchapter.check(self) for sec in self.skeys: + # If "--all-messages" is used, the report will show the + # "OTHER ERRORS" section. This is expected and nothing is to be + # checked in it. + + other_errors = (all_messages and + len(sec.start_hits) == 1 and + "OTHER ERRORS" in sec.start_hits[0]) + thistest.fail_if( + not other_errors and len(sec.start_hits) > 0 and not self.checked[sec], "summary count check missing for section %s" % sec.name) @@ -418,7 +522,7 @@ def check(self): # unexpected blocks: class Ublock(Rblock): - def check(self): + def check(self, all_messages=False): thistest.fail_if( len(self.start_hits) > 0, "Unexpected headers caught by %s:\n%s" @@ -449,7 +553,7 @@ def __init__(self, re_start): # process a report: class RblockSet: - def __init__(self): + def __init__(self, all_messages=False): # We need a list of all the blocks to drive the report parsing # process, and a list of all the note blocks to setup the analysis @@ -458,6 +562,10 @@ def __init__(self): self.noteblocks = [] self.allblocks = [] + # Is "--all-messages" used + + self.all_messages = all_messages + # Violation sections stmt_notes = { @@ -500,24 +608,31 @@ def __init__(self): ni_notes = { "statement was not instrumented": sUndetCov, "decision was not instrumented" - " for decision coverage" : dUndetCov, + " for decision coverage": dUndetCov, "decision was not instrumented" - " for MC/DC coverage" : eUndetCov + " for MC/DC coverage": eUndetCov } self.noteblocks.append( - UCIchapter(re_start="UNDETERMINED COVERAGE ITEMS", re_notes=ni_notes)) + UCIchapter(re_start="UNDETERMINED COVERAGE ITEMS", + re_notes=ni_notes)) # Exemptions regions xr_notes = { "0 exempted violation": xBlock0, r"[1-9]\d* exempted violation": xBlock1, - r"\d+ exempted violations?; [1-9]\d+ exempted undetermined" + r"\d+ exempted violations?; [1-9]\d+ exempted undetermined " r"coverage items?": xBlock2 } + + lvl_notes = stmt_notes | dc_notes | mcdc_notes + all_notes = nc_notes | ni_notes | lvl_notes self.noteblocks.append( - XREchapter(re_start="EXEMPTED REGIONS", re_notes=xr_notes)) + XREchapter(re_start="EXEMPTED REGIONS", + re_notes=xr_notes, + exempted_notes=all_notes, + all_messages=self.all_messages)) # Other note blocks @@ -551,9 +666,9 @@ def starts_with(self, rline): return rs return None - def check(self): + def check(self, all_messages=False): for rs in self.allblocks: - rs.check() + rs.check(all_messages) class RnotesExpander: @@ -564,13 +679,13 @@ def to_enotes(self, report): # We need to ignore everything not in the report sections # of interest, so until we know we're in ... - self.rset = RblockSet() + self.rset = RblockSet(self.all_messages) self.rs = None self.report = report Tfile(filename=self.report, process=self.process_tline) - self.rset.check() + self.rset.check(self.all_messages) def register(self, enote): source = enote.source @@ -611,10 +726,15 @@ def process_tline(self, tline): return enote - def __init__(self, report): + def __init__(self, report, all_messages=False): # xcov --annotate=report produces a single report featuring a list of # indications for slocs in all the units. self.ernotes = {} + + # True if the "--all-messages" switch is used. Its use changes what + # must be checked in case of exempted violations. + + self.all_messages = all_messages self.to_enotes(report) diff --git a/testsuite/SCOV/report.py b/testsuite/SCOV/report.py index 4926615e4..4e2716c0a 100644 --- a/testsuite/SCOV/report.py +++ b/testsuite/SCOV/report.py @@ -251,7 +251,8 @@ def __setup_expectations(self, ntraces, xcovlevel, xregions): if xregions: xmrHeader = Piece(pattern="EXEMPTED REGIONS", pre=pre) - xmrCount = Piece(pattern="([0-9]+|No) exempted region", + xmrCount = Piece(pattern="([0-9]+|No) exempted region[s]*, " + "([0-9]+|No) exempted violation[s]*", nexpected=-1, pre=xmrHeader) self.__register(rpieces=[xmrHeader, xmrCount]) diff --git a/testsuite/tests/TC31-001-show-exempted/src/exemptions.adb b/testsuite/tests/TC31-001-show-exempted/src/exemptions.adb new file mode 100644 index 000000000..744097572 --- /dev/null +++ b/testsuite/tests/TC31-001-show-exempted/src/exemptions.adb @@ -0,0 +1,26 @@ +procedure Exemptions (X : in out Positive) is +begin + if X = 1 then -- # if_1 + X := X + 1; -- # inc_1 + end if; + + if X = 3 then -- # if_2 + X := X + 1; -- # inc_2 + end if; + + pragma Annotate (Xcov, Exempt_On, "Exempt 1"); -- # exempt1 + if X = 3 then -- # exempt1 + X := X + 1; -- # exempt1 + X := X + 1; -- # exempt1 + end if; -- # exempt1 + pragma Annotate (Xcov, Exempt_Off); -- # exempt1 + + pragma Annotate (Xcov, Exempt_On, "Exempt 2"); -- # exempt2 + if X = 3 then -- # exempt2 + X := X + 1; -- # exempt2 + X := X + 1; -- # exempt2 + X := X + 1; -- # exempt2 + X := X + 1; -- # exempt2 + end if; -- # exempt2 + pragma Annotate (Xcov, Exempt_Off); -- # exempt2 +end Exemptions; diff --git a/testsuite/tests/TC31-001-show-exempted/src/test_1.adb b/testsuite/tests/TC31-001-show-exempted/src/test_1.adb new file mode 100644 index 000000000..9d40e915f --- /dev/null +++ b/testsuite/tests/TC31-001-show-exempted/src/test_1.adb @@ -0,0 +1,16 @@ +with Exemptions; + +procedure Test_1 is + X : Positive := 1; +begin + Exemptions (X); + Exemptions (X); +end Test_1; + +--# exemptions.adb +-- /if_1/ l+ ## 0 +-- /inc_1/ l+ ## 0 +-- /if_2/ l! ## dT- +-- /inc_2/ l- ## s- +-- /exempt1/ l* ## x+ +-- /exempt2/ l* ## x+ diff --git a/testsuite/tests/TC31-001-show-exempted/test.py b/testsuite/tests/TC31-001-show-exempted/test.py new file mode 100644 index 000000000..0d6cd4d49 --- /dev/null +++ b/testsuite/tests/TC31-001-show-exempted/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run(covcontrol=CovControl + (covoptions="--all-messages")) +thistest.result() diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 8909cd6a7..338b8923d 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -18,6 +18,7 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Containers.Vectors; +with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; @@ -96,6 +97,12 @@ package body Annotations.Report is type Messages_Array is array (Report_Section) of Message_Vectors.Vector; + package Messages_Of_Exempted_Region is new + Ada.Containers.Indefinite_Ordered_Maps + (Key_Type => Source_Location, + Element_Type => Message_Vectors.Vector, + "=" => Message_Vectors."="); + package String_Vectors is new Ada.Containers.Vectors (Natural, @@ -113,7 +120,8 @@ package body Annotations.Report is Current_Section : Natural := 0; -- Current section in final report - Exempted_Messages : Message_Vectors.Vector; + Exempted_Messages : Messages_Of_Exempted_Region.Map := + Messages_Of_Exempted_Region.Empty_Map; -- Messages that have been covered by an exemption Exemption : Slocs.Source_Location := Slocs.No_Location; @@ -299,6 +307,7 @@ package body Annotations.Report is Output : constant File_Access := Get_Output; Total_Exempted_Regions : Natural; + Total_Exempted_Violations : Natural := 0; function Has_Exempted_Region return Boolean; -- True iff there's at least one exempted region @@ -311,6 +320,11 @@ package body Annotations.Report is -- given title (section omitted if Title is empty). Item is the noun for -- the summary line counting messages in the section. + procedure Output_Message (C : Message_Vectors.Cursor); + -- Print M in the final report and update item count. The difference + -- with Pretty_Print_Message is that Put_Message does not tries to + -- know if the message should be exempted or not. + procedure Output_Exemption (C : Cursor); -- Show summary information for exemption denoted by C @@ -377,6 +391,55 @@ package body Annotations.Report is -- else Non_Exempted = "". Used to omit the mention "non-exempted" when -- there's no exemption in sight anyway. + -------------------- + -- Output_Message -- + -------------------- + + procedure Output_Message (C : Message_Vectors.Cursor) is + M : Message renames Message_Vectors.Element (C); + Msg : constant String := To_String (M.Msg); + First : Natural := Msg'First; + begin + + -- For info messages (such as the messages displayed with + -- --show-mcdc-vectors), do not display the SCO, as it is only + -- used to attach the message to the right report location. + + if M.Kind /= Info and then M.SCO /= No_SCO_Id then + Put + (Output.all, Image (First_Sloc (M.SCO), Unique_Name => True)); + Put (Output.all, ": "); + if Msg (First) = '^' then + First := First + 1; + else + Put + (Output.all, + To_Lower (SCO_Kind'Image (Kind (M.SCO))) + & (if Switches.Show_MCDC_Vectors + and then Kind (M.SCO) = Condition + then Index (M.SCO)'Image + & " (" & SCO_Image (M.SCO) & ") " + else " ")); + end if; + + else + Put (Output.all, Image (M.Sloc, Unique_Name => True)); + Put (Output.all, ": "); + end if; + + Output_Multiline_Msg + (Output => Output.all, + Text => Msg (First .. Msg'Last)); + + if M.SCO /= No_SCO_Id and then M.Tag /= No_SC_Tag then + Put (Output.all, + " (from " & Tag_Provider.Tag_Name (M.Tag) & ")"); + end if; + + New_Line (Output.all); + Output_Annotations (Output.all, SCO_Annotations (M.SCO)); + end Output_Message; + ---------------------- -- Output_Exemption -- ---------------------- @@ -431,6 +494,26 @@ package body Annotations.Report is Put_Line (Output.all, ", justification:"); Put_Line (Output.all, E.Message.all); + if Switches.All_Messages then + + New_Line (Output.all); + + if Pp.Exempted_Messages.Is_Empty then + Put_Line (Output.all, "No exempted violations."); + else + Put_Line (Output.all, "Exempted violations:"); + + for C in Pp.Exempted_Messages (Sloc).Iterate loop + Output_Message (C); + + if Message_Vectors.Element (C).Kind /= Info then + Total_Exempted_Violations := + Total_Exempted_Violations + 1; + end if; + end loop; + end if; + end if; + Total_Exempted_Regions := Total_Exempted_Regions + 1; end Output_Exemption; @@ -443,11 +526,6 @@ package body Annotations.Report is Title : String; Item : String) is - procedure Output_Message (C : Message_Vectors.Cursor); - -- Print M in the final report and update item count. The difference - -- with Pretty_Print_Message is that Put_Message does not tries to - -- know if the message should be exempted or not. - Item_Count : Natural := 0; -- Count of the number of violation / error messages for the current -- section. @@ -456,62 +534,6 @@ package body Annotations.Report is -- Count of the number of messages (including info messages) for the -- current section. - -------------------- - -- Output_Message -- - -------------------- - - procedure Output_Message (C : Message_Vectors.Cursor) is - M : Message renames Message_Vectors.Element (C); - Msg : constant String := To_String (M.Msg); - First : Natural := Msg'First; - - begin - - -- For info messages (such as the messages displayed with - -- --show-mcdc-vectors), do not display the SCO, as it is only - -- used to attach the message to the right report location. - - if M.Kind /= Info and then M.SCO /= No_SCO_Id then - Put - (Output.all, Image (First_Sloc (M.SCO), Unique_Name => True)); - Put (Output.all, ": "); - if Msg (First) = '^' then - First := First + 1; - else - Put - (Output.all, - To_Lower (SCO_Kind'Image (Kind (M.SCO))) - & (if Switches.Show_MCDC_Vectors - and then Kind (M.SCO) = Condition - then Index (M.SCO)'Image - & " (" & SCO_Image (M.SCO) & ") " - else " ")); - end if; - - else - Put (Output.all, Image (M.Sloc, Unique_Name => True)); - Put (Output.all, ": "); - end if; - - Output_Multiline_Msg - (Output => Output.all, - Text => Msg (First .. Msg'Last)); - - if M.SCO /= No_SCO_Id and then M.Tag /= No_SC_Tag then - Put (Output.all, - " (from " & Tag_Provider.Tag_Name (M.Tag) & ")"); - end if; - - Msg_Count := Msg_Count + 1; - - if M.Kind /= Info then - Item_Count := Item_Count + 1; - end if; - - New_Line (Output.all); - Output_Annotations (Output.all, SCO_Annotations (M.SCO)); - end Output_Message; - -- Start of processing for Messages_For_Section begin @@ -519,7 +541,15 @@ package body Annotations.Report is Pp.Section (Title); end if; - Pp.Nonexempted_Messages (MC).Iterate (Output_Message'Access); + for C in Pp.Nonexempted_Messages (MC).Iterate loop + Output_Message (C); + + Msg_Count := Msg_Count + 1; + + if Message_Vectors.Element (C).Kind /= Info then + Item_Count := Item_Count + 1; + end if; + end loop; if Msg_Count > 0 then New_Line (Output.all); @@ -621,7 +651,10 @@ package body Annotations.Report is New_Line (Output.all); Put_Line (Output.all, - Pluralize (Total_Exempted_Regions, "exempted region") & "."); + Pluralize (Total_Exempted_Regions, "exempted region") + & ", " + & Pluralize (Total_Exempted_Violations, "exempted violation") + & "."); end if; Pp.Chapter ("ANALYSIS SUMMARY"); @@ -635,7 +668,10 @@ package body Annotations.Report is if Has_Exempted_Region then Put_Line (Output.all, - Pluralize (Total_Exempted_Regions, "exempted region") & "."); + Pluralize (Total_Exempted_Regions, "exempted region") + & ", " + & Pluralize (Total_Exempted_Violations, "exempted violation") + & "."); end if; if Pp.Dump_Units then @@ -691,7 +727,35 @@ package body Annotations.Report is if M.Kind in Violation | Undetermined_Cov and then Pp.Exemption /= Slocs.No_Location then - Pp.Exempted_Messages.Append (M); + + declare + use Messages_Of_Exempted_Region; + + procedure Add_Message + (Key : Source_Location; + Element : in out Message_Vectors.Vector); + -- Append a message to the message vector of Key + + procedure Add_Message + (Key : Source_Location; + Element : in out Message_Vectors.Vector) + is + pragma Unreferenced (Key); + begin + Element.Append (M); + end Add_Message; + + C : Cursor := Pp.Exempted_Messages.Find (Pp.Exemption); + Inserted : Boolean; + begin + if not Has_Element (C) then + Pp.Exempted_Messages.Insert + (Pp.Exemption, Message_Vectors.Empty_Vector, C, Inserted); + end if; + + Pp.Exempted_Messages.Update_Element (C, Add_Message'Access); + end; + if M.Kind = Violation then Inc_Violation_Exemption_Count (Pp.Exemption); else From 2114523eea776e37ab9ca616a03ce276663e30b3 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 6 Dec 2022 17:56:13 +0100 Subject: [PATCH 0166/1483] Add an API to unparse options Add an API to get a string representation of all command line arguments in the current gnatcov run that are compatible with a specific gnatcov command. This is preliminary work for the parallelized instrumentation (to pass on the right flags to gnatcov instrument-{source/main} subprocesses). Ref: eng/cov/gnatcoverage#18 --- tools/gnatcov/argparse.adb | 64 ++++++++++++++++++++++++++++++++++++++ tools/gnatcov/argparse.ads | 14 +++++++++ tools/gnatcov/switches.adb | 53 ++++++++++++++++++++++++++++++- tools/gnatcov/switches.ads | 7 +++++ 4 files changed, 137 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/argparse.adb b/tools/gnatcov/argparse.adb index b6d116199..70bed5848 100644 --- a/tools/gnatcov/argparse.adb +++ b/tools/gnatcov/argparse.adb @@ -217,6 +217,70 @@ package body Argparse is else Default); end Value; + -------------- + -- Supports -- + -------------- + + function Supports + (Parser : Parser_Type; + Cmd : Command_Type; + Option : Option_Reference) return Boolean is + begin + case Option.Kind is + when Bool_Opt => + return Parser.Data.Bool_Info (Option.Bool_Option).Commands (Cmd); + when String_Opt => + return Parser.Data.String_Info + (Option.String_Option).Commands (Cmd); + when String_List_Opt => + return Parser.Data.String_List_Info + (Option.String_List_Option).Commands (Cmd); + end case; + end Supports; + + ------------- + -- Unparse -- + ------------- + + function Unparse + (Parser : Parser_Type; + Args : Parsed_Arguments; + Option : Option_Reference) return String_Vectors.Vector + is + Result : String_Vectors.Vector; + + function Name (Opt : Option_Info'Class) return Unbounded_String is + (if Length (Opt.Long_Name) = 0 + then Opt.Short_Name + else Opt.Long_Name); + -- Some options such as -P do not defined a long name. In this case, + -- return the short name. + + begin + case Option.Kind is + when Bool_Opt => + Result.Append + (Name (Parser.Data.Bool_Info (Option.Bool_Option))); + when String_Opt => + Result.Append + (Name (Parser.Data.String_Info (Option.String_Option))); + Result.Append (Args.String_Args (Option.String_Option).Value); + when String_List_Opt => + declare + Opt_Name : constant Unbounded_String := + Name + (Parser.Data.String_List_Info (Option.String_List_Option)); + begin + for Arg of Args.String_List_Args (Option.String_List_Option) + loop + Result.Append (Opt_Name); + Result.Append (Arg); + end loop; + end; + end case; + return Result; + end Unparse; + ---------------- -- Get_Option -- ---------------- diff --git a/tools/gnatcov/argparse.ads b/tools/gnatcov/argparse.ads index 698f2940b..98ca12eac 100644 --- a/tools/gnatcov/argparse.ads +++ b/tools/gnatcov/argparse.ads @@ -383,6 +383,20 @@ package Argparse is Default : String := "") return String; -- If Option is present in Args, return its value. Return Default otherwise + function Supports + (Parser : Parser_Type; + Cmd : Command_Type; + Option : Option_Reference) return Boolean; + -- Return True if Cmd supports Option, False otherwise + + function Unparse + (Parser : Parser_Type; + Args : Parsed_Arguments; + Option : Option_Reference) return String_Vectors.Vector + with Pre => Is_Present (Args, Option); + -- If Option is present in Args, return a string representation of this + -- option that can be passed to a gnatcov invocation. + private type Command_Info is record diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 7d4dd64d6..668ce9554 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -23,7 +23,6 @@ with Ada.Strings.Unbounded; with Outputs; use Outputs; with Project; use Project; -with Strings; use Strings; with Switches; use Switches; package body Switches is @@ -498,4 +497,56 @@ package body Switches is Copy_Arg (Opt_Config, CGPR_File); end Parse_Arguments; + --------------------- + -- Common_Switches -- + --------------------- + + function Common_Switches + (Cmd : Command_Line.Command_Type) return String_Vectors.Vector + is + Has_Config : constant Boolean := + Is_Present (Args, Option_Reference'(String_Opt, Opt_Config)); + -- Whether the --config flag is on the command line. If this is the + -- case, do not pass the --target and --RTS flags (they will be parsed + -- from the config). + + Result : String_Vectors.Vector; + + procedure Process (Option : Option_Reference); + -- Add the command line value of Option to Result if Cmd supports it + + ------------- + -- Process -- + ------------- + + procedure Process (Option : Option_Reference) is + begin + if Is_Present (Args, Option) + and then Supports (Arg_Parser, Cmd, Option) + then + Result.Append_Vector (Unparse (Arg_Parser, Args, Option)); + end if; + end Process; + + begin + -- Unfortunately, we can't avoid the code duplication. Deal with all + -- kind of options: boolean, string and strings list. Do not pass + -- the --target and --RTS flags if there is a --config flag. + + for Opt in Bool_Options loop + Process (Option_Reference'(Bool_Opt, Opt)); + end loop; + + for Opt in String_Options loop + if not Has_Config or else Opt not in Opt_Target | Opt_Runtime then + Process (Option_Reference'(String_Opt, Opt)); + end if; + end loop; + + for Opt in String_List_Options loop + Process (Option_Reference'(String_List_Opt, Opt)); + end loop; + return Result; + end Common_Switches; + end Switches; diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 51e5b80cd..458563518 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -25,6 +25,7 @@ with Command_Line; use Command_Line; with Command_Line_Support; use Command_Line_Support; with Inputs; with Instrument; use Instrument; +with Strings; use Strings; package Switches is @@ -215,4 +216,10 @@ package Switches is Debug_File_Table : Boolean renames Debug_Switches (File_Table); + function Common_Switches + (Cmd : Command_Line.Command_Type) return String_Vectors.Vector; + -- Return the unparsed command line arguments supported by the given + -- Cmd. This is used to propagate a set of switches to a gnatcov + -- subprocess. + end Switches; From e2245a6c1a68145fe8d1d8fd1ebebab89ffd46cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Thu, 2 Mar 2023 11:24:51 +0100 Subject: [PATCH 0167/1483] Disable test with exemptions for 5.04a1 The pragmas marking the exempted regions cannot be compiled with this version of the compiler. TN: TC31-001 --- testsuite/tests/TC31-001-show-exempted/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/TC31-001-show-exempted/test.opt diff --git a/testsuite/tests/TC31-001-show-exempted/test.opt b/testsuite/tests/TC31-001-show-exempted/test.opt new file mode 100644 index 000000000..d53c552fd --- /dev/null +++ b/testsuite/tests/TC31-001-show-exempted/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Cannot compile pragmas marking begin and end of exempted regions From 045e9e60e4ccff9f1fd88670a686402ec254c606 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 27 Feb 2023 13:57:50 +0000 Subject: [PATCH 0168/1483] instrument-checkpoints.adb: remove ambiguous "=" operator references Even though GNAT does not reject it here, comparing Map1.Reference (Cur1) and Map2.Reference (Cur2) when both the Reference_Type and the Element_Type "=" operators are visible is ambiguous and thus illegal. Address this ambiguity. Noticed while reviewing eng/cov/gnatcoverage!60 --- tools/gnatcov/instrument-checkpoints.adb | 25 ++++++++++++------------ tools/gnatcov/instrument-checkpoints.ads | 3 +-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index f4984a1b9..0022f0265 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -16,12 +16,13 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Diagnostics; use Diagnostics; -with Files_Table; use Files_Table; -with Outputs; use Outputs; -with SC_Obligations; use SC_Obligations; -with Subprocesses; use Subprocesses; -with Types; use Types; +with Diagnostics; use Diagnostics; +with Files_Table; use Files_Table; +with Instrument.Base_Types; use Instrument.Base_Types; +with Outputs; use Outputs; +with SC_Obligations; use SC_Obligations; +with Subprocesses; use Subprocesses; +with Types; use Types; package body Instrument.Checkpoints is @@ -100,28 +101,28 @@ package body Instrument.Checkpoints is if not Version_Less (CLS, Than => 8) then declare - use SFI_To_PP_Cmd_Maps; - CP_PP_Cmds : Map; + CP_PP_Cmds : SFI_To_PP_Cmd_Maps.Map; CP_SFI : Source_File_Index; begin - Map'Read (CLS.Stream, CP_PP_Cmds); + SFI_To_PP_Cmd_Maps.Map'Read (CLS.Stream, CP_PP_Cmds); for CP_Cur in CP_PP_Cmds.Iterate loop -- If this source file is now ignored, just discard its -- preprocessing commands. - CP_SFI := Key (CP_Cur); + CP_SFI := SFI_To_PP_Cmd_Maps.Key (CP_Cur); if not SFI_Ignored (Relocs, CP_SFI) then declare SFI : constant Source_File_Index := Remap_SFI (Relocs, CP_SFI); - Cur : constant Cursor := PP_Cmds.Find (SFI); + Cur : constant SFI_To_PP_Cmd_Maps.Cursor := + PP_Cmds.Find (SFI); begin -- If there was no known preprocessing command for SFI so -- far, just register the loaded one. - if not Has_Element (Cur) then + if not SFI_To_PP_Cmd_Maps.Has_Element (Cur) then PP_Cmds.Insert (SFI, CP_PP_Cmds.Reference (CP_Cur)); -- Otherwise, warn if the already known command and the diff --git a/tools/gnatcov/instrument-checkpoints.ads b/tools/gnatcov/instrument-checkpoints.ads index e58dfea9a..71fd2ef23 100644 --- a/tools/gnatcov/instrument-checkpoints.ads +++ b/tools/gnatcov/instrument-checkpoints.ads @@ -16,8 +16,7 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Checkpoints; use Checkpoints; -with Instrument.Base_Types; use Instrument.Base_Types; +with Checkpoints; use Checkpoints; package Instrument.Checkpoints is From 7d26a22e2cc0af53e2cef0e15cd835a9014f922f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 1 Mar 2023 14:18:32 +0100 Subject: [PATCH 0169/1483] Fix partial message in dhtml report As we were flushing current decisions when pretty printing a statement, it meant that the SCOs flushing for the line, done in Pretty_Print_End_Line, missed the decisions SCO. This resulted in incomplete messages, e.g. "outcome TRUE never exercised" instead of ": outcome TRUE never exercised". --- tools/gnatcov/annotations-dynamic_html.adb | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 6ae54def2..11249fb48 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -628,9 +628,6 @@ package body Annotations.Dynamic_Html is is Statement : constant JSON_Value := Create_Object; begin - Clear (Pp.Current_Decisions); - Clear (Pp.Current_Conditions); - Set_SCO_Fields (Statement, SCO, State); Append (Pp.Current_Statements, Statement); From 21a7af51d4761d48def8bd901fadd2288cffdb61 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 20 Feb 2023 11:55:10 +0100 Subject: [PATCH 0170/1483] Implement a custom unit provider This is preliminary work to parallelized instrumentation. To avoid having to reparse a project file every time a unit is instrumented, we implement a custom unit provider that uses the mapping file provided through the -gnatem switch to the compiler. --- .../gnatcov/instrument-ada_unit_provider.adb | 187 ++++++++++++++++++ .../gnatcov/instrument-ada_unit_provider.ads | 91 +++++++++ tools/gnatcov/instrument.adb | 9 +- tools/gnatcov/project.adb | 16 +- tools/gnatcov/project.ads | 4 + 5 files changed, 300 insertions(+), 7 deletions(-) create mode 100644 tools/gnatcov/instrument-ada_unit_provider.adb create mode 100644 tools/gnatcov/instrument-ada_unit_provider.ads diff --git a/tools/gnatcov/instrument-ada_unit_provider.adb b/tools/gnatcov/instrument-ada_unit_provider.adb new file mode 100644 index 000000000..da00309a5 --- /dev/null +++ b/tools/gnatcov/instrument-ada_unit_provider.adb @@ -0,0 +1,187 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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.Characters.Handling; use Ada.Characters.Handling; +with Ada.Text_IO; use Ada.Text_IO; + +with GNATCOLL.Projects.Aux; use GNATCOLL.Projects.Aux; +with GNATCOLL.Projects; use GNATCOLL.Projects; + +with Libadalang.Unit_Files; + +with Outputs; +with Project; use Project; + +package body Instrument.Ada_Unit_Provider is + + --------------------- + -- Create_Provider -- + --------------------- + + function Create_Provider + (Runtime_Directories : String_Vectors.Vector; + Dependencies_Filename : String) return Provider_Type + is + use GNATCOLL.VFS; + + Provider : Provider_Type; + + Dependencies_File : File_Type; + + begin + -- Parse the mapping file and fill Provider.Unit_Map + + Open (Dependencies_File, In_File, Dependencies_Filename); + + -- The mapping file is a succession of triplets as such: + -- {%b,%s} + -- + -- + + begin + while not End_Of_File (Dependencies_File) loop + declare + Unit_Name : constant String := + Get_Line (Dependencies_File); + Dummy_Basename : constant String := + Get_Line (Dependencies_File); + File_Fullname : constant String := + Get_Line (Dependencies_File); + begin + Provider.Unit_Map.Insert (To_Lower (Unit_Name), File_Fullname); + end; + end loop; + exception + when End_Error => + Outputs.Warn ("mapping file """ & Dependencies_Filename + & " "" is truncated"); + end; + Close (Dependencies_File); + + -- Read the runtime files and fill Provider.Runtime_Files + + for Dirname of Runtime_Directories loop + for File of Read_Dir (Create (+(+Dirname))).all loop + Provider.Runtime_Files.Insert (+File.Base_Name, +File.Full_Name); + end loop; + end loop; + + return Provider; + end Create_Provider; + + ---------------------------------- + -- Create_Provider_From_Project -- + ---------------------------------- + + function Create_Provider_From_Project return Unit_Provider_Reference + is + Mapping_File : constant String := + Create_Ada_Mapping_File (Project.Project.Root_Project); + -- The mapping file will be removed by the Finalize procedure in + -- project.adb. + + begin + if Mapping_File = "" then + Outputs.Fatal_Error + ("Error when creating the mapping file for the project " + & Project.Project.Root_Project.Name); + end if; + + return Create_Unit_Provider_Reference + (Create_Provider + (Runtime_Directories => Project.Runtime_Dirs, + Dependencies_Filename => Mapping_File)); + end Create_Provider_From_Project; + + ----------------------- + -- Get_Unit_Filename -- + ----------------------- + + overriding function Get_Unit_Filename + (Provider : Provider_Type; + Name : Text_Type; + Kind : Analysis_Unit_Kind) return String + is + use String_Maps; + + Part : constant String := + (case Kind is + when Libadalang.Common.Unit_Body => "%b", + when Libadalang.Common.Unit_Specification => "%s"); + Unit_Name : constant String := + Libadalang.Unit_Files.Unit_String_Name (Name) & Part; + + Unit_Name_Cur : Cursor := Provider.Unit_Map.Find (Unit_Name); + begin + if Has_Element (Unit_Name_Cur) then + return Element (Unit_Name_Cur); + end if; + + -- The requested unit does not belong to the project tree: look for a + -- source file in the runtime. + + declare + Basename : constant String := + Libadalang.Unit_Files.File_From_Unit (Name, Kind); + begin + Unit_Name_Cur := Provider.Runtime_Files.Find (Basename); + if Has_Element (Unit_Name_Cur) then + return Element (Unit_Name_Cur); + end if; + end; + + -- The unit could not be found. Return an empty string + + return ""; + end Get_Unit_Filename; + + -------------- + -- Get_Unit -- + -------------- + + overriding function Get_Unit + (Provider : Provider_Type; + Context : Analysis_Context'Class; + Name : Text_Type; + Kind : Analysis_Unit_Kind; + Charset : String := ""; + Reparse : Boolean := False) return Analysis_Unit'Class + is + Filename : constant String := Provider.Get_Unit_Filename (Name, Kind); + begin + if Filename /= "" then + return Context.Get_From_File (Filename, Charset, Reparse); + else + declare + Dummy_File : constant String := + Libadalang.Unit_Files.File_From_Unit (Name, Kind); + Kind_Name : constant Text_Type := + (case Kind is + when Unit_Specification => "specification file", + when Unit_Body => "body file"); + Error : constant Text_Type := + "Could not find source file for " & Name & " (" & Kind_Name + & ")"; + begin + return Libadalang.Analysis.Get_With_Error + (Context, Dummy_File, Error, Charset); + end; + end if; + end Get_Unit; + +end Instrument.Ada_Unit_Provider; diff --git a/tools/gnatcov/instrument-ada_unit_provider.ads b/tools/gnatcov/instrument-ada_unit_provider.ads new file mode 100644 index 000000000..14dbfd4db --- /dev/null +++ b/tools/gnatcov/instrument-ada_unit_provider.ads @@ -0,0 +1,91 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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.Indefinite_Hashed_Maps; +with Ada.Strings.Hash; + +with GNATCOLL.VFS; + +with Langkit_Support.Text; use Langkit_Support.Text; + +with Libadalang.Analysis; use Libadalang.Analysis; +with Libadalang.Common; use Libadalang.Common; + +with Instrument.Base_Types; use Instrument.Base_Types; + +-- Custom implementation of a libadalang unit provider, using the mapping +-- file produced from the project file (that is passed to the compiler through +-- the -gnatem switch). + +package Instrument.Ada_Unit_Provider is + + type Provider_Type is new Libadalang.Analysis.Unit_Provider_Interface + with private; + + function Create_Provider + (Runtime_Directories : String_Vectors.Vector; + Dependencies_Filename : String) return Provider_Type; + -- Create a unit provider, from a list of predefined directories passed + -- through Runtime_Directories, and from a mapping file in the same format + -- as the file passed through -gnatem in the compiler invocation. + + function Create_Provider_From_Project return Unit_Provider_Reference; + -- Uses the loaded project (Project.Project) to generate a mapping + -- file and create a unit provider from it. + + overriding function Get_Unit_Filename + (Provider : Provider_Type; + Name : Text_Type; + Kind : Analysis_Unit_Kind) return String; + -- Return the filename corresponding to the given unit name/unit kind. + -- Raise a ``Property_Error`` if the given unit name is not valid. + + overriding function Get_Unit + (Provider : Provider_Type; + Context : Analysis_Context'Class; + Name : Text_Type; + Kind : Analysis_Unit_Kind; + Charset : String := ""; + Reparse : Boolean := False) return Analysis_Unit'Class; + -- Fetch and return the analysis unit referenced by the given unit name. + -- Raise a ``Property_Error`` if the given unit name is not valid. + + overriding procedure Release (Provider : in out Provider_Type) is null; + +private + + use US; + use type GNATCOLL.VFS.Virtual_File; + + package String_Maps is new Ada.Containers.Indefinite_Hashed_Maps + (Key_Type => String, + Element_Type => String, + Hash => Ada.Strings.Hash, + Equivalent_Keys => "="); + + type Provider_Type is new Libadalang.Analysis.Unit_Provider_Interface + with record + Unit_Map : String_Maps.Map; + -- Mapping from unit name to file fullnames + + Runtime_Files : String_Maps.Map; + -- Mapping from a runtime file basename to its fullname + + end record; + +end Instrument.Ada_Unit_Provider; diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 51094d74d..b8b2fa0e4 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -34,13 +34,13 @@ with GNATCOLL.JSON; use GNATCOLL.JSON; with GNATCOLL.VFS; use GNATCOLL.VFS; with Libadalang.Analysis; -with Libadalang.Project_Provider; with Checkpoints; with Coverage; with Files_Table; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Instrument.Ada_Unit; +with Instrument.Ada_Unit_Provider; with Instrument.Base_Types; use Instrument.Base_Types; with Instrument.Clean_Objdirs; with Instrument.C; @@ -307,15 +307,12 @@ package body Instrument is Mains : String_Vectors.Vector) is use Libadalang.Analysis; + use String_Vectors; -- First create the context for Libadalang Provider : constant Unit_Provider_Reference := - Libadalang.Project_Provider.Create_Project_Unit_Provider - (Tree => Project.Project, - Project => Project.Project.Root_Project, - Env => null, - Is_Project_Owner => False); + Instrument.Ada_Unit_Provider.Create_Provider_From_Project; -- Create the event handler, to report when Libadalang cannot read a -- required source file. diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 1c4ff0d6d..29b714787 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -39,7 +39,6 @@ with Instrument.Base_Types; use Instrument.Base_Types; with Inputs; use Inputs; with Outputs; use Outputs; with Paths; use Paths; -with Strings; use Strings; package body Project is @@ -1649,6 +1648,21 @@ package body Project is end loop; end Enumerate_Ignored_Source_Files; + ------------------ + -- Runtime_Dirs -- + ------------------ + + function Runtime_Dirs return String_Vectors.Vector + is + Result : String_Vectors.Vector; + begin + for Dir of Project.Root_Project.Get_Environment.Predefined_Source_Path + loop + Result.Append (+(+Dir.Full_Name)); + end loop; + return Result; + end Runtime_Dirs; + -------------- -- Finalize -- -------------- diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 608b63f73..fb8b60812 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -27,6 +27,7 @@ with GNATCOLL.VFS; with Inputs; with Files_Table; +with Strings; use Strings; with Switches; use Switches; with Traces_Files; use Traces_Files; @@ -230,6 +231,9 @@ package Project is with Pre => Is_Project_Loaded; -- Call Process on each name in the Coverage'Ignored_Source_File attribute + function Runtime_Dirs return String_Vectors.Vector; + -- Return the list of runtime directories for the currently loaded project + ---------------------------------------- -- Raw accessors for the project tree -- ---------------------------------------- From 2a5e3b24bd7f79be08dfb0cb7f8f91f747fcd860 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 2 Mar 2023 14:48:56 +0100 Subject: [PATCH 0171/1483] GNATcov_RTS.Base_IO: minor reformattings TN: W301-030 --- tools/gnatcov/rts/gnatcov_rts-base_io.adb | 5 +++-- tools/gnatcov/rts/gnatcov_rts-base_io.ads | 1 + 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts-base_io.adb b/tools/gnatcov/rts/gnatcov_rts-base_io.adb index e86198585..d42be21fa 100644 --- a/tools/gnatcov/rts/gnatcov_rts-base_io.adb +++ b/tools/gnatcov/rts/gnatcov_rts-base_io.adb @@ -26,7 +26,7 @@ with GNAT.IO; -package body GNATcov_RTS.Base_Io is +package body GNATcov_RTS.Base_IO is --------- -- Put -- @@ -47,4 +47,5 @@ package body GNATcov_RTS.Base_Io is begin GNAT.IO.Put_Line (Str); end Put_Line; -end GNATcov_RTS.Base_Io; + +end GNATcov_RTS.Base_IO; diff --git a/tools/gnatcov/rts/gnatcov_rts-base_io.ads b/tools/gnatcov/rts/gnatcov_rts-base_io.ads index 9931f39e8..c2ef6e8fa 100644 --- a/tools/gnatcov/rts/gnatcov_rts-base_io.ads +++ b/tools/gnatcov/rts/gnatcov_rts-base_io.ads @@ -35,4 +35,5 @@ package GNATcov_RTS.Base_IO is procedure Put_Line (S : GNATcov_RTS_String); pragma Export (C, Entity => Put_Line, External_Name => "gnatcov_rts_puts"); + end GNATcov_RTS.Base_IO; From 53f79585b46a31eb93104c045258135ff9e65697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Thu, 2 Mar 2023 16:21:05 +0100 Subject: [PATCH 0172/1483] Document the display of exempted violations This TN introduced the possibility of showing exempted violation in a report through the "--all-messages" switch. This change documents this feature. TN: TC31-001 --- doc/gnatcov/exemptions.rst | 34 ++++++++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/doc/gnatcov/exemptions.rst b/doc/gnatcov/exemptions.rst index aa3545564..f0cd6c7ef 100644 --- a/doc/gnatcov/exemptions.rst +++ b/doc/gnatcov/exemptions.rst @@ -32,7 +32,7 @@ To illustrate, let us consider a common assertion control procedure in Ada: procedure Eassert (T : Boolean) is begin - pragma Annotate (Xcov, Exempt_On, "assert condition is never False"); + pragma Annotate (Xcov, Exempt_On, "assert condition never to be False"); if not T then raise Program_Error; end if; @@ -61,7 +61,7 @@ block: void assert (bool x){ - // GNATCOV_EXEMPT_ON "assert condition is never false" + // GNATCOV_EXEMPT_ON "assert condition never to be False" if (!x) abort(); // GNATCOV_EXEMPT_OFF @@ -113,7 +113,7 @@ region as a whole, and the indications for all the regions are grouped in a separate *Exempted Regions* report section, only present if there are exemption regions in the analysis scope. This section lists the exempted regions, displaying for each the source location span, the number of actually -exempted violations in the region, and the exemption justification text. It +exempted violations in the region and the exemption justification text. It also includes a total count of the number of exempted regions at the end. The corresponding :cmd-option:`=report` excerpt below illustrates this for the @@ -125,7 +125,7 @@ The corresponding :cmd-option:`=report` excerpt below illustrates this for the ========================= eassert.adb:8:4-12:4: 2 exempted violations, justification: - assert condition never to be False + "assert condition never to be False" 1 exempted region. @@ -137,6 +137,32 @@ The corresponding :cmd-option:`=report` excerpt below illustrates this for the No non-exempted DECISION violation. 1 exempted region. +It is possible to display the exempted violations to let the user check that +they match the expected ones. This can be done by using the +:cmd-option:`--all-messages` switch. That way, the report will show the +previously mentionned information along with the observed violations under +their corresponding exempted block, and the total number of exempted violations +found across all exempted regions. + +The :cmd-option:`=report` excerpt below produced while +:cmd-option:`--all-messages` is used illustrates this for the ``Eassert`` +example:: + + ... + ========================= + == 3. EXEMPTED REGIONS == + ========================= + + eassert.adb:8:4-12:4: 2 exempted violations, justification: + "assert condition never to be False" + + Exempted violations: + eassert.adb:8:4: decision outcome TRUE never exercised + eassert.adb:9:8: statement not executed + + 1 exempted region, 2 exempted violations. + ... + The *Coverage Violations* section is renamed to convey that it contains "NON-EXEMPTED" violations only, and the *Analysis Summary* counters are adjusted in a similar manner. The number of exempted regions is added to From 212cb3838258cd5a0a79dfaee640f1e80b8376b6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 3 Mar 2023 14:35:40 +0000 Subject: [PATCH 0173/1483] Remove redundant parentheses Recent GNAT wavefronts warn about these parentheses, so remove them. TN: W203-029 --- tools/gnatcov/cfg_dump.adb | 6 +++--- tools/gnatcov/instrument-ada_unit.adb | 2 +- tools/gnatcov/slocs.adb | 2 +- tools/gnatcov/traces_elf.adb | 18 +++++++++--------- tools/gnatcov/traces_stats.adb | 4 ++-- 5 files changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/gnatcov/cfg_dump.adb b/tools/gnatcov/cfg_dump.adb index f1ba3cdd3..3aa9be786 100644 --- a/tools/gnatcov/cfg_dump.adb +++ b/tools/gnatcov/cfg_dump.adb @@ -1250,7 +1250,7 @@ package body CFG_Dump is Result : Unbounded_String; begin while Sloc /= No_Element - and then (PC in Element (Sloc).First .. Element (Sloc).Last) + and then PC in Element (Sloc).First .. Element (Sloc).Last loop Append (Result, @@ -1455,8 +1455,8 @@ package body CFG_Dump is exit; elsif Successors (BB.all).Length = 1 - and then (Successors (BB.all).First_Element.Kind in - Fallthrough | Branch) + and then Successors (BB.all).First_Element.Kind + in Fallthrough | Branch then declare Successor : Successor_Record renames diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index db702cde8..29b815efd 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -2337,7 +2337,7 @@ package body Instrument.Ada_Unit is (Common_Nodes : Degenerate_Subp_Common_Nodes) return Boolean is begin return Common_Nodes.Ctrl_Type /= No_Base_Type_Decl - and then (not Common_Nodes.N_Spec.P_Return_Type.Is_Null) + and then not Common_Nodes.N_Spec.P_Return_Type.Is_Null and then Common_Nodes.N_Spec.P_Return_Type = Common_Nodes.Ctrl_Type; exception diff --git a/tools/gnatcov/slocs.adb b/tools/gnatcov/slocs.adb index aa39b0d88..5167e2bc5 100644 --- a/tools/gnatcov/slocs.adb +++ b/tools/gnatcov/slocs.adb @@ -80,7 +80,7 @@ package body Slocs is function "<" (L, R : Source_Location_Range) return Boolean is (L.Source_File < R.Source_File or else - (L.Source_File = R.Source_File and then (L.L < R.L))); + (L.Source_File = R.Source_File and then L.L < R.L)); ---------- -- "<=" -- diff --git a/tools/gnatcov/traces_elf.adb b/tools/gnatcov/traces_elf.adb index c39f02c08..b7b454e53 100644 --- a/tools/gnatcov/traces_elf.adb +++ b/tools/gnatcov/traces_elf.adb @@ -3249,7 +3249,7 @@ package body Traces_Elf is if (Shdr.Sh_Flags and (SHF_ALLOC or SHF_EXECINSTR)) = (SHF_ALLOC or SHF_EXECINSTR) - and then (Shdr.Sh_Type = SHT_PROGBITS) + and then Shdr.Sh_Type = SHT_PROGBITS and then Shdr.Sh_Size > 0 then if Do_Reloc then @@ -4097,8 +4097,8 @@ package body Traces_Elf is if not Inserted and then - (Mapping_Symbol_Sets.Element (Position).Insn_Set - /= Symbol.Insn_Set) + Mapping_Symbol_Sets.Element (Position).Insn_Set + /= Symbol.Insn_Set then raise Program_Error with ("Inconsistent mapping symbols at " @@ -4673,8 +4673,8 @@ package body Traces_Elf is and then Item.Last = Existing_Item.Last and then Item.Subprogram_Name /= null and then Existing_Item.Subprogram_Name /= null - and then (Item.Subprogram_Name.all - = Existing_Item.Subprogram_Name.all) + and then Item.Subprogram_Name.all + = Existing_Item.Subprogram_Name.all then Free (Item); Item := Existing_Item; @@ -5053,9 +5053,9 @@ package body Traces_Elf is if Symbol /= null then if Addr = Symbol.First - and then - (Subprg = null or else (Subprg.Subprogram_Name.all - /= Symbol.Symbol_Name.all)) + and then (Subprg = null + or else Subprg.Subprogram_Name.all + /= Symbol.Symbol_Name.all) then Put ('<'); Put (Symbol.Symbol_Name.all); @@ -5217,7 +5217,7 @@ package body Traces_Elf is if (Shdr.Sh_Flags and (SHF_ALLOC or SHF_EXECINSTR)) = (SHF_ALLOC or SHF_EXECINSTR) - and then (Shdr.Sh_Type = SHT_PROGBITS) + and then Shdr.Sh_Type = SHT_PROGBITS and then Shdr.Sh_Size > 0 then Shdr_Sets (Idx) := new Address_Info_Sets.Set; diff --git a/tools/gnatcov/traces_stats.adb b/tools/gnatcov/traces_stats.adb index f51ce13df..a6bacaa17 100644 --- a/tools/gnatcov/traces_stats.adb +++ b/tools/gnatcov/traces_stats.adb @@ -111,11 +111,11 @@ package body Traces_Stats is -- 1 line not covered out of 201+ lines will still result in 1% of non -- covered lines. - if Percentage = 100 and then (Part /= Total) then + if Percentage = 100 and then Part /= Total then Percentage := 99; end if; - if Percentage = 0 and then (Part /= 0) then + if Percentage = 0 and then Part /= 0 then Percentage := 1; end if; From 9dac0f8955bdfc9ad09829a914f72d05e4ca5134 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 3 Mar 2023 14:36:21 +0000 Subject: [PATCH 0174/1483] instrument-ada_unit.adb: add missing comment box --- tools/gnatcov/instrument-ada_unit.adb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 29b815efd..287be2a95 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -2333,6 +2333,10 @@ package body Instrument.Ada_Unit is return True; end Augmented_Expr_Function_Needs_Decl; + ---------------------------------------- + -- Augmented_EF_Needs_Wrapper_Package -- + ---------------------------------------- + function Augmented_EF_Needs_Wrapper_Package (Common_Nodes : Degenerate_Subp_Common_Nodes) return Boolean is begin From 5ec63bad1d62afb91d53461f9d21274c3721e525 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 13 Dec 2022 13:10:10 +0100 Subject: [PATCH 0175/1483] Subprocesses: introduce new API to run command asynchronously This is preliminary work for the parallelized instrumentation. This commit introduces support to run asynchronously commands, and wait for their termination. Each command output is redirected to a file and printed as a whole after the command executed. --- tools/gnatcov/subprocesses.adb | 251 +++++++++++++++++++++++++++++++-- tools/gnatcov/subprocesses.ads | 81 ++++++++++- tools/gnatcov/temp_dirs.adb | 2 +- 3 files changed, 317 insertions(+), 17 deletions(-) diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 83d24eb64..33c2b5901 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -16,20 +16,45 @@ -- of the license. -- ------------------------------------------------------------------------------ +with Ada.Strings; with Ada.Text_IO; use Ada.Text_IO; with GNAT.OS_Lib; with GNAT.Strings; use GNAT.Strings; -with GNATCOLL.OS.FS; use GNATCOLL.OS.FS; -with GNATCOLL.OS.Process; use GNATCOLL.OS.Process; +with GNATCOLL.Mmap; use GNATCOLL.Mmap; +with GNATCOLL.OS.FS; use GNATCOLL.OS.FS; with GNATCOLL.OS.Process_Types; with Outputs; use Outputs; +with Paths; use Paths; with Switches; use Switches; package body Subprocesses is + function Run_Command + (Command : String; + Arguments : String_Vectors.Vector; + Origin_Command_Name : String; + Environment : String_Maps.Map := Empty_Environment; + Output_File : String := ""; + Err_To_Out : Boolean := True; + Out_To_Null : Boolean := False; + In_To_Null : Boolean := False; + Ignore_Error : Boolean := False) return Process_Handle; + -- Overload to run asynchronously a command + + function Wait_And_Finalize (Self : in out Process_Pool) return Positive; + -- Wait for a process to terminate and handle its output. Return the id in + -- Self for the process that terminated. + + procedure Check_Status + (Success : Boolean; + Ignore_Error : Boolean; + Command : String; + Origin_Command_Name : String); + -- If Ignore_Error is False and Success is False, raise a Fatal_Error + --------- -- "=" -- --------- @@ -64,6 +89,28 @@ package body Subprocesses is Cmd.Arguments.Append_Vector (Args); end Append_Args; + ------------------ + -- Check_Status -- + ------------------ + + procedure Check_Status + (Success : Boolean; + Ignore_Error : Boolean; + Command : String; + Origin_Command_Name : String) is + begin + if not Ignore_Error and then not Success then + Fatal_Error (Origin_Command_Name & " failed: aborting"); + + elsif Verbose then + if Success then + Put_Line (Command & " finished"); + else + Error (Origin_Command_Name & " failed"); + end if; + end if; + end Check_Status; + ----------------- -- Run_Command -- ----------------- @@ -144,13 +191,39 @@ package body Subprocesses is Out_To_Null : Boolean := False; In_To_Null : Boolean := False; Ignore_Error : Boolean := False) return Boolean + is + Handle : constant Process_Handle := Run_Command + (Command, + Arguments, + Origin_Command_Name, + Environment, + Output_File, + Err_To_Out, + Out_To_Null, + In_To_Null, + Ignore_Error); + Success : constant Boolean := Wait (Handle) = 0; + begin + Check_Status (Success, Ignore_Error, Command, Origin_Command_Name); + return Success; + end Run_Command; + + function Run_Command + (Command : String; + Arguments : String_Vectors.Vector; + Origin_Command_Name : String; + Environment : String_Maps.Map := Empty_Environment; + Output_File : String := ""; + Err_To_Out : Boolean := True; + Out_To_Null : Boolean := False; + In_To_Null : Boolean := False; + Ignore_Error : Boolean := False) return Process_Handle is package Process_Types renames GNATCOLL.OS.Process_Types; Program : String_Access; Env : Process_Types.Environ; Args : Process_Types.Arguments; - Success : Boolean; begin if Out_To_Null and then Output_File /= "" then raise Program_Error; @@ -162,7 +235,7 @@ package body Subprocesses is if Program = null then Error (Origin_Command_Name & ": cannot find " & Command & " on your path"); - return False; + return Invalid_Handle; end if; -- Instantiate environment variables @@ -209,7 +282,7 @@ package body Subprocesses is Stdin : constant File_Descriptor := (if In_To_Null then Null_FD else Standin); Stdout, Stderr : File_Descriptor; - Status : Integer; + Handle : Process_Handle; Redirect_Stdout : constant Boolean := Output_File /= ""; begin @@ -227,32 +300,180 @@ package body Subprocesses is end if; Stderr := (if Err_To_Out then Stdout else Standerr); - Status := Run + Handle := Start (Args => Args, Env => Env, Stdin => Stdin, Stdout => Stdout, Stderr => Stderr); - Success := Status = 0; Process_Types.Deallocate (Args); Process_Types.Deallocate (Env); if Redirect_Stdout then Close (Stdout); end if; + return Handle; end; + end Run_Command; - if not Ignore_Error and then not Success then - Fatal_Error (Origin_Command_Name & " failed: aborting"); + ----------------------- + -- Wait_And_Finalize -- + ----------------------- - elsif Verbose then - if Success then - Put_Line (Command & " finished"); - else - Error (Origin_Command_Name & " failed"); + function Wait_And_Finalize (Self : in out Process_Pool) return Positive + is + Terminated_Process : Process_Handle := Invalid_Handle; + Id : Positive; + -- Terminated process + + Success : Boolean; + -- Status of the process that terminated + + begin + while Terminated_Process = Invalid_Handle loop + + -- Wait until one process terminates. TODO??? W222-016: replace the + -- magic constant with Duration'Last once GNATCOLL.OS.Processes is + -- fixed. + + Terminated_Process := Wait_For_Processes (Self.Handles, 1000.0); + end loop; + + Self.Nb_Running_Processes := Self.Nb_Running_Processes - 1; + + -- Find the id of the process that terminated + + for I in Self.Handles'Range loop + if Self.Handles (I) = Terminated_Process then + Id := I; end if; + end loop; + + -- Get its termination status + + Success := Wait (Self.Handles (Id)) = 0; + + -- Dump the output of the process that terminated to stdout if it was + -- not redirected to a file. + + if Self.Process_Infos (Id).Output_To_Stdout then + declare + Output_File : Mapped_File; + Region : Mapped_Region; + Str : Str_Access; + Str_Last : Natural := Last (Region); + begin + Output_File := Open_Read (+Self.Process_Infos (Id).Output_File); + Region := Read (Output_File); + Str := Data (Region); + + -- The finalization of Ada.Text_IO always emits a newline after a + -- call to Put. To avoid redundant line breaks in this situation, + -- do not pass that newline to Put and call New_Line instead. + + if Str_Last > 0 and then Str (Str_Last) = ASCII.LF then + Str_Last := Str_Last - 1; + end if; + Put (Str (1 .. Str_Last)); + New_Line; + + Free (Region); + Close (Output_File); + end; end if; - return Success; + + -- If the subprocess terminated with an error, deal with it here + + Check_Status + (Success, + Self.Process_Infos (Id).Ignore_Error, + +Self.Process_Infos (Id).Command, + +Self.Process_Infos (Id).Origin_Command_Name); + return Id; + end Wait_And_Finalize; + + ----------------- + -- Run_Command -- + ----------------- + + procedure Run_Command + (Pool : in out Process_Pool; + Command : String; + Arguments : String_Vectors.Vector; + Origin_Command_Name : String; + Environment : String_Maps.Map := Empty_Environment; + Output_File : String := ""; + Err_To_Out : Boolean := True; + Out_To_Null : Boolean := False; + In_To_Null : Boolean := False; + Ignore_Error : Boolean := False) + is + Id : Positive; + -- Identifier of the process in the process pool (i.e. its index in + -- the Pool.Handles process array). + + begin + -- If the process pool is full, wait for the first completion to occur + -- and create the new process to replace it. Otherwise we just started + -- to fill it: use the next available slot. + + if Pool.Nb_Running_Processes = Pool.Parallelism_Level then + Id := Pool.Wait_And_Finalize; + else + Id := Pool.Nb_Running_Processes + 1; + end if; + + -- Fill the information relative to this command that we will need + -- when it terminates. + + Pool.Process_Infos (Id).Ignore_Error := Ignore_Error; + Pool.Process_Infos (Id).Output_File := +Output_File; + Pool.Process_Infos (Id).Origin_Command_Name := +Origin_Command_Name; + Pool.Process_Infos (Id).Command := +Command; + + Pool.Handles (Id) := Run_Command + (Command, + Arguments, + Origin_Command_Name, + Environment, + + -- Redirect the output to a temporary file to avoid mangling on the + -- standard output. The dump of the output is done in + -- Wait_And_Finalize, through a later call to Run_Command, or + -- through the finalization of the process pool. + + (if Output_File = "" + then Pool.Output_Dir.Directory_Name / "job-" + & Strings.Img (Id) & ".txt" + else Output_File), + Err_To_Out => Output_File = "", + Out_To_Null => Out_To_Null, + In_To_Null => In_To_Null, + Ignore_Error => Ignore_Error); + Pool.Nb_Running_Processes := Pool.Nb_Running_Processes + 1; end Run_Command; + ---------------- + -- Initialize -- + ---------------- + + procedure Initialize (Pool : in out Process_Pool) is + begin + Create_Temporary_Directory (Pool.Output_Dir, "gnatcov_outputs"); + Pool.Nb_Running_Processes := 0; + end Initialize; + + -------------- + -- Finalize -- + -------------- + + overriding procedure Finalize (Self : in out Process_Pool) + is + Dummy : Positive; + begin + while Self.Nb_Running_Processes /= 0 loop + Dummy := Wait_And_Finalize (Self); + end loop; + end Finalize; + end Subprocesses; diff --git a/tools/gnatcov/subprocesses.ads b/tools/gnatcov/subprocesses.ads index a0fd1020e..2bca5f15e 100644 --- a/tools/gnatcov/subprocesses.ads +++ b/tools/gnatcov/subprocesses.ads @@ -22,9 +22,13 @@ -- handle gnatcov's small needs for I/O redirections and can automatically -- abort gnatcov in case of subprocess failure. +with Ada.Finalization; with Ada.Strings.Unbounded; -with Strings; use Strings; +with GNATCOLL.OS.Process; use GNATCOLL.OS.Process; + +with Strings; use Strings; +with Temp_Dirs; use Temp_Dirs; package Subprocesses is @@ -121,4 +125,79 @@ package Subprocesses is -- Overloads to stop with a fatal error if the subprocess exits with a -- non-zero status code. + type Process_Pool (Parallelism_Level : Positive) is tagged limited private; + -- Holder for a pool of processes to run in parallel. + -- + -- Declare one such object with the desired level of parallelism as the + -- discriminant, then use the Run_Command procedure below to start the + -- processes to run in parallel. + -- + -- Run_Command will return immediately and run the process in background + -- if the desired parallelism level is not reached yet, or will wait for + -- a process in the pool to terminate before running the new process. + -- + -- Process_Pool finalization blocks until all processes in the pool have + -- terminated. + + procedure Run_Command + (Pool : in out Process_Pool; + Command : String; + Arguments : String_Vectors.Vector; + Origin_Command_Name : String; + Environment : String_Maps.Map := Empty_Environment; + Output_File : String := ""; + Err_To_Out : Boolean := True; + Out_To_Null : Boolean := False; + In_To_Null : Boolean := False; + Ignore_Error : Boolean := False); + -- Overload to run a command in a pool of processes + +private + + type Process_Info is record + Command, Origin_Command_Name : Ada.Strings.Unbounded.Unbounded_String; + Output_File : Ada.Strings.Unbounded.Unbounded_String; + Ignore_Error : Boolean; + -- Information specific to a subprocess, filled when calling the + -- Run_Command overload running a subprocess in a process pool. See the + -- documentation of Run_Command to have an exhaustive documentation of + -- these members. + + Output_To_Stdout : Boolean; + -- Instructs Wait_And_Finalize that Output_File is temporary, so its + -- content should be read / printed and it should be removed once the + -- process has terminated. + + end record; + -- Holder for the process information + + type Process_Info_Array is array (Positive range <>) of Process_Info; + + type Process_Pool (Parallelism_Level : Positive) is + new Ada.Finalization.Limited_Controlled with + record + Handles : Process_Array (1 .. Parallelism_Level); + -- Processes currently running / waitable + + Process_Infos : Process_Info_Array (1 .. Parallelism_Level); + -- Copy of the information passed to Run_Command that is also needed + -- when the process terminates. + + Nb_Running_Processes : Natural; + -- Number of tasks currently running / waitable + + Output_Dir : Temporary_Directory; + -- Directory in which to create the temporary files that store + -- subprocess outputs. + + end record + with Dynamic_Predicate => + (Nb_Running_Processes in 0 .. Parallelism_Level); + + overriding procedure Initialize (Pool : in out Process_Pool); + -- Initialize the process pool + + overriding procedure Finalize (Self : in out Process_Pool); + -- Wait for all still running subprocesses in Self and handle their outputs + end Subprocesses; diff --git a/tools/gnatcov/temp_dirs.adb b/tools/gnatcov/temp_dirs.adb index d6bad8770..f6700b42d 100644 --- a/tools/gnatcov/temp_dirs.adb +++ b/tools/gnatcov/temp_dirs.adb @@ -49,7 +49,7 @@ package body Temp_Dirs is begin if Verbose then Put_Line - ("Creating temporary build directory: " & Name); + ("Creating temporary directory: " & Name); end if; -- In directory creation fails and we raise an exception, make sure to From df8336466fb163f3a6e8e8baf2f41aec27676435 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 20 Feb 2023 01:57:26 -0800 Subject: [PATCH 0176/1483] testsuite: convey gnatcov info to testsuite internals Introduce a gnatcov_info() functionality similar to what we already have as runtime_info(), or target_info() This is intended to help pick choices (e.g. which gnatcov_rts gpr file to select) depending on whether "gnatcov setup" is available, or allow XFAILing tests for which older versions of gnatcov lack support. Those adjustments will come through separate commits. Part of W215-023 (gnatcov 22.x qualification) --- testsuite/SUITE/control.py | 14 +++++++++++++- testsuite/SUITE/tutils.py | 1 + testsuite/testsuite.py | 12 +++++++++++- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index a9b7f5375..dde4e5a2d 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -9,7 +9,7 @@ from e3.fs import rm from e3.os.process import Run -from SUITE.cutils import no_ext +from SUITE.cutils import no_ext, version env = Env() @@ -347,6 +347,18 @@ def target_info(target=None): return TARGETINFO[re_target] +class GnatcovInfo: + def __init__(self): + self.major = int( + re.search( + pattern="GNATcoverage (\d+)", + string=version("gnatcov") + ).group(1)) + self.has_setup = self.major >= 23 + +def gnatcov_info(): + return GnatcovInfo() + # Allowed pairs for the --gnatcov- family of command line options: ALTRUN_GNATCOV_PAIRS = (('gnatcov', 'run'), ) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index b19a99300..841e74631 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -34,6 +34,7 @@ TARGET_INFO = control.target_info() RUNTIME_INFO = control.runtime_info() +GNATCOV_INFO = control.gnatcov_info() XCOV = xcov_pgm(thistest.options.auto_arch) VALGRIND = 'valgrind' + env.host.os.exeext diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index cbc3d477f..22f6b00ee 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1262,7 +1262,8 @@ def _discriminants(self): self._qualif_level_discriminants() + self._cargs_discriminants() + self._rts_discriminants() + - self._toolchain_discriminants()) + self._toolchain_discriminants() + + self._gnatcov_discriminants()) def _base_discriminants(self): @@ -1390,6 +1391,15 @@ def _toolchain_discriminants(self): return [m.group(1)] if m else [] + def _gnatcov_discriminants(self): + """ + Compute the discriminant that reflects the version of the + particular gnatcov in use. + """ + + return ["gnatcov-{}".format(control.gnatcov_info().major)] + + # -------------------------- # -- Command-line options -- # -------------------------- From 046a3cdc5b3b7451ce1edd0a1f70fd6933de2c4f Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Fri, 17 Feb 2023 07:01:45 -0800 Subject: [PATCH 0177/1483] testsuite: adjustments to support gnatcov without "setup" Pick gnatcov_rts_full.gpr when has_full_runtime. Don't try to figure out the dump_channel actually used from the .json dumped by gnatcov instrument. This is intended for a branch dedicated to a qualification run using a version of gnatcov predating the introduction of gnatcov setup. Part of W215-023 (gnatcov 22.x qualification) --- testsuite/SCOV/minicheck.py | 111 ++++++++++++++++++++++++------------ testsuite/SUITE/control.py | 10 +++- 2 files changed, 82 insertions(+), 39 deletions(-) diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 783fb8b4b..8bf9a5609 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -20,13 +20,12 @@ from SUITE.cutils import contents_of, indent from SUITE.tutils import ( exepath_to, gprbuild, run_cov_program, srctrace_pattern_for, - srctracename_for, thistest, tracename_for, xcov, xrun + srctracename_for, thistest, tracename_for, xcov, xrun, GNATCOV_INFO ) COV_RE = re.compile(r'^ *(\d+) (.):.*$') - def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, gpr_obj_dir=None, gpr_exe_dir=None, ignored_source_files=[], separate_coverage=None, extra_args=[], extra_run_args=None, @@ -212,14 +211,17 @@ def gprbuild_wrapper(root_project): auto_languages=auto_languages) gprbuild_wrapper(gprsw.root_project) - # If an explicit dump channel was requested, check that "gnatcov - # instrument" used it. In case it was implicit, get the one that was - # used. + # Retrieve the dump_channel that "gnatcov instrument" actually used, + # when available. It could be unavailable when either + # + # - the version of gnatcov we run doesn't dump the parameters it + # used (older than the introduction of gnatcov setup, typically + # in qualification contexts), # - # The mode in which we do not register failures is tricky: in this case - # we may not have an actual dump channel because instrumentation did - # not complete. In that case we cannot use source traces, but we must - # build and run programs nonetheless. + # - or we are called in a context causing a failure on purpose + # (register_failure False), at a point before gnatcov has dumped + # the parameters. + params_file_dir = gpr_obj_dir if gprsw.subdirs: params_file_dir = os.path.join(params_file_dir, gprsw.subdirs) @@ -227,23 +229,47 @@ def gprbuild_wrapper(root_project): try: f = open(params_file) except FileNotFoundError: - if register_failure: - raise - else: - actual_dump_channel = None + actual_dump_channel = None else: with f: params = json.load(f) actual_dump_channel = params["dump-channel"] - if dump_channel in (None, "auto"): - dump_channel = actual_dump_channel - elif dump_channel and actual_dump_channel: - thistest.fail_if_not_equal( - "actual dump channel", dump_channel, actual_dump_channel + # Fail if we expected to be able to retrieve the dump channel + # actually used, but don't have it: + thistest.fail_if( + register_failure and GNATCOV_INFO.has_setup + and actual_dump_channel is None, + "Unable to retrieve actual dump_channel from {}".format( + params_file) + ) + + # At this point, dump_channel is either None (request not to pass an + # argument at all), or a meaningful value that was passed to gnatcov + # instrument, possibly inferred from an "auto" selection at our level. + + # If an explicit dump channel was provided to gnatcov instrument and + # we have the actual dump channel used, the two should be consistent: + thistest.fail_if( + dump_channel and actual_dump_channel + and dump_channel != actual_dump_channel, + "requested dump_channel ({}) != actual ({})".format( + dump_channel, actual_dump_channel ) + ) + + # Now execute each main and collect the trace files we can. Tests + # triggering instrumentation failures on purpose are not guaranteed to + # produce a trace. + + # See if we know the dump-channel that was used. Sometimes we don't, + # e.g. from a test failing to instrument or from a test requesting not + # to pass a dump-channel switch (dump_channel None) with a pre-setup + # version of gnatcov that would fallback to a default but not dump the + # parameters it used. + + known_channel = dump_channel or actual_dump_channel - # Then execute each main and collect trace files trace_files = [] for m in mains: # Remove potential existing source trace files: the name is @@ -256,30 +282,39 @@ def gprbuild_wrapper(root_project): register_failure=register_failure, exec_args=exec_args) - # Depending on the dump channel, we also may have to create the - # trace file. If we could not determine the actually used dump - # channel (see above), do not collect the trace file. - if dump_channel is None: - continue - - elif dump_channel == 'bin-file': - trace_file = srctracename_for(m, - register_failure=register_failure) - if trace_file is None: - continue - - elif dump_channel == 'base64-stdout': - # Create a trace name that is compatible with srctracename_for + # See if we have a trace file at hand or if could create one from + # a base64 trace in the output. Operate best effort here, simply + # gathering what we can. + + # The possible combinations of gnatcov versions and project file + # contents associated with dump_channel None on entry together + # with tests checking for some kinds of failures on purpose make + # it very tricky to determine what we actually expect at this + # particular spot. + # + # Encoding that logic here is not worth the effort/complexity; + # simply assume that if we fail to get a trace when our context + # expects one, there will be some kind of test failure afterwards. + + trace_file = None + + if known_channel in [None, "bin-file"]: + trace_file = srctracename_for(m, register_failure=False) + + if (not trace_file + and (known_channel == "base64-stdout" + or "source trace file ==" in contents_of(out_file)) + ): + # Pick a trace name that is compatible with srctracename_for trace_file = srctrace_pattern_for(m).replace("*", "unique") + # Here we're really supposed to have a trace in the output + # so we can be a tad stricter on the conversion outcome. xcov_convert_base64(out_file, trace_file, register_failure=register_failure) - else: - raise ValueError('Invalid dump channel: {}' - .format(dump_channel)) - - trace_files.append(abspath(trace_file)) + if trace_file: + trace_files.append(abspath(trace_file)) xcov_args.extend(cov_or_instr_args) diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index dde4e5a2d..cf57c656f 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -282,7 +282,15 @@ def need_libsupport(self): @property def gnatcov_rts_project(self): """Name of the gnatcov_rts project to use in instrumented projects.""" - return 'gnatcov_rts' + + # gnatcov_rts_full and gnatcov_rts were merged with the introduction + # of gnatcov setup. + + return ( + 'gnatcov_rts_full' if ( + self.has_full_runtime and not gnatcov_info().has_setup) + else 'gnatcov_rts' + ) def runtime_info(runtime=None): From adbd5d0bcef99518540159fba6657e11a6472dfc Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 20 Feb 2023 02:09:31 -0800 Subject: [PATCH 0178/1483] Split Qualif/Ada tests on IF statements in elab body Extract them out within the /stmt/1_Core/052_CompoundStmts/53_If series. xfail the new dedicated tests for gnatcov < 23 in doA qualification mode as mcdc instrumentation for lib level decisions was not supported then. Part of W215-023 (gnatcov 22.x qualification) --- .../53_If/ELSE_Path/src/test_else_path.adb | 7 +------ .../ELSIF_Path/src/test_elsif_path_first.adb | 6 ------ .../ELSIF_Path/src/test_elsif_path_last.adb | 6 ------ .../ELSIF_Path/src/test_elsif_path_middle.adb | 6 ------ .../53_If/Elab_ELSE/src/lib_init.ads | 4 ++++ .../53_If/Elab_ELSE/src/test_init_else.adb | 18 ++++++++++++++++ .../052_CompoundStmts/53_If/Elab_ELSE/tc.rst | 3 +++ .../53_If/Elab_ELSE/test.opt | 1 + .../052_CompoundStmts/53_If/Elab_ELSE/test.py | 5 +++++ .../53_If/Elab_ELSIF/src/lib_init.ads | 4 ++++ .../53_If/Elab_ELSIF/src/test_init_elsif.adb | 18 ++++++++++++++++ .../052_CompoundStmts/53_If/Elab_ELSIF/tc.rst | 3 +++ .../53_If/Elab_ELSIF/test.opt | 1 + .../53_If/Elab_ELSIF/test.py | 5 +++++ .../53_If/Elab_IF/src/lib_init.ads | 4 ++++ .../53_If/Elab_IF/src/test_init_if.adb | 18 ++++++++++++++++ .../052_CompoundStmts/53_If/Elab_IF/tc.rst | 3 +++ .../052_CompoundStmts/53_If/Elab_IF/test.opt | 1 + .../052_CompoundStmts/53_If/Elab_IF/test.py | 5 +++++ .../53_If/IF_Path/src/test_if_path.adb | 6 ------ .../src/test_multiple_paths.adb | 6 ------ .../No_Execution/src/test_no_execution.adb | 4 ---- .../53_If/src/lib_if_statements.adb | 21 +++++++++++++++++++ .../53_If/src/lib_if_statements.ads | 5 +++++ .../53_If/src/more_if_statements.adb | 10 --------- .../53_If/src/more_if_statements.ads | 5 +---- 26 files changed, 121 insertions(+), 54 deletions(-) create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/lib_init.ads create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/test_init_else.adb create mode 100755 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/tc.rst create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/test.opt create mode 100755 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/test.py create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/lib_init.ads create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/test_init_elsif.adb create mode 100755 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/tc.rst create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/test.opt create mode 100755 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/test.py create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/lib_init.ads create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/test_init_if.adb create mode 100755 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/tc.rst create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/test.opt create mode 100755 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/test.py create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSE_Path/src/test_else_path.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSE_Path/src/test_else_path.adb index ecbc45472..68f8cb3af 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSE_Path/src/test_else_path.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSE_Path/src/test_else_path.adb @@ -16,8 +16,6 @@ begin Assert (My_Max_From_Two (1, 3) = 3); - Assert (Global_Var = 11); - Set_Prime_Number (Num => 50, Res => Res); Assert (Res = 0); @@ -57,7 +55,4 @@ end Test_ELSE_Path; -- /max/ l+ ## 0 -- /ifmax/ l- ## s- -- /elsemax/ l+ ## 0 --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- + diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_first.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_first.adb index b583fce2b..9f62cb5ce 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_first.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_first.adb @@ -14,8 +14,6 @@ begin Set_Prime_Number (Res, 2); Assert (Res = 3); - - Assert (Global_Var = 11); end Test_ELSIF_Path_First; --# if_statements.adb @@ -52,10 +50,6 @@ end Test_ELSIF_Path_First; -- /max/ ~l- ## ~s- -- /ifmax/ ~l- ## ~s- -- /elsemax/ ~l- ## ~s- --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- -- We have stricter expectations on uncalled subprograms -- with instrumentation, in particular wrt declarations. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_last.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_last.adb index aeb49b500..2eefb4b90 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_last.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_last.adb @@ -11,8 +11,6 @@ begin Set_Prime_Number (Res, 10); Assert (Res = 29); - - Assert (Global_Var = 11); end Test_ELSIF_Path_Last; --# more_if_statements.adb @@ -40,10 +38,6 @@ end Test_ELSIF_Path_Last; -- /max/ ~l- ## ~s- -- /ifmax/ ~l- ## ~s- -- /elsemax/ ~l- ## ~s- --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- -- %opts: --trace-mode=src -- =/max/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_middle.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_middle.adb index 429dcebc0..45a1c555c 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_middle.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSIF_Path/src/test_elsif_path_middle.adb @@ -11,8 +11,6 @@ begin Set_Prime_Number (Res, 6); Assert (Res = 13); - - Assert (Global_Var = 11); end Test_ELSIF_Path_Middle; --# more_if_statements.adb @@ -40,10 +38,6 @@ end Test_ELSIF_Path_Middle; -- /max/ ~l- ## ~s- -- /ifmax/ ~l- ## ~s- -- /elsemax/ ~l- ## ~s- --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- -- %opts: --trace-mode=src -- =/max/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/lib_init.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/lib_init.ads new file mode 100644 index 000000000..72dcb0e77 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/lib_init.ads @@ -0,0 +1,4 @@ +package Lib_Init is + Init_Ref : Integer := -2; + -- A value to get into the ELSE branch +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/test_init_else.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/test_init_else.adb new file mode 100644 index 000000000..63da57662 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/test_init_else.adb @@ -0,0 +1,18 @@ +with Lib_If_Statements; +with Support; use Support; + +procedure Test_Init_Else is + X : Integer; +begin + X := Lib_If_Statements.Probe (Slot => 1); + Assert (X < 0); +end; + +--# lib_if_statements.adb +-- /test_if/ l+ ## 0 +-- /do_if/ l- ## s- +-- /test_elsif/ l+ ## 0 +-- /do_elsif/ l- ## s- +-- /test_else/ l+ ## 0 +-- /do_else/ l+ ## 0 + diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/tc.rst new file mode 100755 index 000000000..db494f354 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/tc.rst @@ -0,0 +1,3 @@ +**Exercise the ELSE branch of an elaboration IF statement** + +LRMREF: 5.3 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/test.py b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/test.py new file mode 100755 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/lib_init.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/lib_init.ads new file mode 100644 index 000000000..123aa43c1 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/lib_init.ads @@ -0,0 +1,4 @@ +package Lib_Init is + Init_Ref : Integer := 0; + -- A value to get into the ELSIF branch +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/test_init_elsif.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/test_init_elsif.adb new file mode 100644 index 000000000..44bff284a --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/test_init_elsif.adb @@ -0,0 +1,18 @@ +with Lib_If_Statements; +with Support; use Support; + +procedure Test_Init_ElsIf is + X : Integer; +begin + X := Lib_If_Statements.Probe (Slot => 1); + Assert (X = 0); +end; + +--# lib_if_statements.adb +-- /test_if/ l+ ## 0 +-- /do_if/ l- ## s- +-- /test_elsif/ l+ ## 0 +-- /do_elsif/ l+ ## 0 +-- /test_else/ l- ## s- +-- /do_else/ l- ## s- + diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/tc.rst new file mode 100755 index 000000000..482a0b3f4 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/tc.rst @@ -0,0 +1,3 @@ +**Exercise the ELSIF branch of an elaboration IF statement** + +LRMREF: 5.3 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/test.py b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/test.py new file mode 100755 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/lib_init.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/lib_init.ads new file mode 100644 index 000000000..f937b69ec --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/lib_init.ads @@ -0,0 +1,4 @@ +package Lib_Init is + Init_Ref : Integer := 15; + -- A value to get the IF test True +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/test_init_if.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/test_init_if.adb new file mode 100644 index 000000000..a53faeee2 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/test_init_if.adb @@ -0,0 +1,18 @@ +with Lib_If_Statements; +with Support; use Support; + +procedure Test_Init_If is + X : Integer; +begin + X := Lib_If_Statements.Probe (Slot => 1); + Assert (X > 0); +end; + +--# lib_if_statements.adb +-- /test_if/ l+ ## 0 +-- /do_if/ l+ ## 0 +-- /test_elsif/ l- ## s- +-- /do_elsif/ l- ## s- +-- /test_else/ l- ## s- +-- /do_else/ l- ## s- + diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/tc.rst new file mode 100755 index 000000000..201bdbd81 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/tc.rst @@ -0,0 +1,3 @@ +**Exercise the IF branch of an elaboration IF statement** + +LRMREF: 5.3 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/test.py b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/test.py new file mode 100755 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/IF_Path/src/test_if_path.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/IF_Path/src/test_if_path.adb index 5138cba92..e6c936586 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/IF_Path/src/test_if_path.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/IF_Path/src/test_if_path.adb @@ -18,8 +18,6 @@ begin Assert (Res = 2); Assert (My_Max_From_Two (2, 1) = 2); - - Assert (Global_Var = 11); end Test_IF_Path; --# if_statements.adb @@ -56,7 +54,3 @@ end Test_IF_Path; -- /max/ l+ ## 0 -- /ifmax/ l+ ## 0 -- /elsemax/ l- ## s- --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Multiple_Paths/src/test_multiple_paths.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Multiple_Paths/src/test_multiple_paths.adb index bf457373a..f2e9d2005 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Multiple_Paths/src/test_multiple_paths.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Multiple_Paths/src/test_multiple_paths.adb @@ -50,8 +50,6 @@ begin -- Covering all paths in More_IF_Statements.Max_From_Two Assert (My_Max_From_Two (2, 1) = 2); Assert (My_Max_From_Two (1, 2) = 2); - - Assert (Global_Var = 11); end Test_Multiple_Paths; --# if_statements.adb @@ -88,7 +86,3 @@ end Test_Multiple_Paths; -- /max/ l+ ## 0 -- /ifmax/ l+ ## 0 -- /elsemax/ l+ ## 0 --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/No_Execution/src/test_no_execution.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/No_Execution/src/test_no_execution.adb index 1c3a4187c..aac83cb8c 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/No_Execution/src/test_no_execution.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/No_Execution/src/test_no_execution.adb @@ -45,7 +45,3 @@ end Test_No_Execution; -- /max/ l- ## s- -- /ifmax/ l- ## s- -- /elsemax/ l- ## s- --- /elab/ l+ ## 0 --- /gt0elab/ l+ ## 0 --- /notgt0elab/ l- ## s- --- /eq0elabeq0/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.adb new file mode 100644 index 000000000..d187c670b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.adb @@ -0,0 +1,21 @@ +with Lib_Init; +-- A helper to be provided by each test, to influence which +-- part of the IF statement below gets exercised. + +package body Lib_If_Statements is + + Values : array (1 .. 8) of Integer; + + function Probe (Slot : Integer) return Integer is + begin + return Values (Slot); + end; +begin + if Lib_Init.Init_Ref > 0 then -- # test_if + Values := (others => 1); -- # do_if + elsif Lib_Init.Init_Ref = 0 then -- # test_elsif + Values := (others => 0); -- # do_elsif + else + Values := (others => -1); -- # do_else + end if; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.ads new file mode 100644 index 000000000..daa5adf43 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.ads @@ -0,0 +1,5 @@ +-- A package which features an IF statement within its elaboration body + +package Lib_If_Statements is + function Probe (Slot : Integer) return Integer; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.adb index 051d9b347..6a1383e38 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.adb @@ -44,15 +44,5 @@ package body More_IF_Statements is return Result; -- # max end Max_From_Two; -begin - - Global_Var := Identity (1); -- # elab - - if Global_Var > 0 then -- # elab - Global_Var := Global_Var + 10; -- # gt0elab - elsif Global_Var = 0 then -- # notgt0elab - Global_Var := Identity (100); -- # eq0elabeq0 - end if; - end More_IF_Statements; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.ads index 4f1712248..7dea18249 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.ads @@ -1,12 +1,9 @@ -- Contains routines with different forms of IF statements in different kinds --- of program units. The body contains IF statement is an elaboration --- statement sequence +-- of program units. package More_IF_Statements is pragma Elaborate_Body; - Global_Var : Integer; - procedure Set_Prime_Number (Res : out Natural; Num : Natural); From 031e3554d5f7dd2fd7a717b31113ce727f7712d4 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Tue, 28 Feb 2023 09:41:34 -0800 Subject: [PATCH 0179/1483] Split Qualif/Ada tests on WHILE statements in elab body Extract them out within the Ada/stmt/1_Core/052_CompoundStmts/550_Loop/ series. xfail the new dedicated tests for gnatcov < 23 in doA qualification mode as mcdc instrumentation for lib level decisions was not supported then. Part of W215-023 (gnatcov 22.x qualification) --- .../550_Loop/Elab_0/src/lib_init.ads | 4 ++++ .../550_Loop/Elab_0/src/test_init_loop.adb | 20 ++++++++++++++++ .../052_CompoundStmts/550_Loop/Elab_0/tc.rst | 3 +++ .../550_Loop/Elab_0/test.opt | 1 + .../052_CompoundStmts/550_Loop/Elab_0/test.py | 5 ++++ .../550_Loop/Elab_Some/src/lib_init.ads | 4 ++++ .../550_Loop/Elab_Some/src/test_init_loop.adb | 20 ++++++++++++++++ .../550_Loop/Elab_Some/tc.rst | 3 +++ .../550_Loop/Elab_Some/test.opt | 1 + .../550_Loop/Elab_Some/test.py | 5 ++++ .../550_Loop/src/lib_loop_statements.adb | 24 +++++++++++++++++++ .../550_Loop/src/lib_loop_statements.ads | 7 ++++++ .../550_Loop/src/more_loop_statements.adb | 7 ------ 13 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/lib_init.ads create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/test_init_loop.adb create mode 100755 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/tc.rst create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt create mode 100755 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.py create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/lib_init.ads create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/test_init_loop.adb create mode 100755 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/tc.rst create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/test.opt create mode 100755 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/test.py create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/lib_init.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/lib_init.ads new file mode 100644 index 000000000..ddf69d259 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/lib_init.ads @@ -0,0 +1,4 @@ +package Lib_Init is + N1 : Integer := 0; + -- Number of value items to initialize to 1 +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/test_init_loop.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/test_init_loop.adb new file mode 100644 index 000000000..cc40cfedb --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/test_init_loop.adb @@ -0,0 +1,20 @@ +with Lib_Loop_Statements; +with Support; use Support; + +procedure Test_Init_Loop is + X : Integer; +begin + X := Lib_Loop_Statements.N_Ones; + Assert (X = 0); +end; + +--# lib_loop_statements.adb +-- /count/ l+ ## 0 +-- /iter/ l+ ## 0 +-- /test-inc/ l+ ## 0 +-- /inc/ l- ## s- + +-- /elab/ l+ ## 0 +-- /test-init/ l+ ## 0 +-- /init/ l- ## s- + diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/tc.rst new file mode 100755 index 000000000..3a49f8472 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/tc.rst @@ -0,0 +1,3 @@ +**Exercise an elaboration WHILE-loop statement, not entering the loop** + +LRMREF: 5.5 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.py b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.py new file mode 100755 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/lib_init.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/lib_init.ads new file mode 100644 index 000000000..91780dd70 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/lib_init.ads @@ -0,0 +1,4 @@ +package Lib_Init is + N1 : Integer := 2; + -- Number of value items to initialize to 1 +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/test_init_loop.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/test_init_loop.adb new file mode 100644 index 000000000..a475fb26b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/test_init_loop.adb @@ -0,0 +1,20 @@ +with Lib_Loop_Statements; +with Support; use Support; + +procedure Test_Init_Loop is + X : Integer; +begin + X := Lib_Loop_Statements.N_Ones; + Assert (X = 2); +end; + +--# lib_loop_statements.adb +-- /count/ l+ ## 0 +-- /iter/ l+ ## 0 +-- /test-inc/ l+ ## 0 +-- /inc/ l+ ## 0 + +-- /elab/ l+ ## 0 +-- /test-init/ l+ ## 0 +-- /init/ l+ ## 0 + diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/tc.rst new file mode 100755 index 000000000..e04431151 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/tc.rst @@ -0,0 +1,3 @@ +**Exercise an elaboration WHILE-loop statement, entering the loop** + +LRMREF: 5.5 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/test.py b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/test.py new file mode 100755 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb new file mode 100644 index 000000000..577cecdcd --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb @@ -0,0 +1,24 @@ +with Lib_Init; + +package body Lib_Loop_Statements is + + N : Integer; + + function N_Ones return Integer is + begin + N := 0; -- # count + for I in Values'Range loop -- # iter + if Values (I) = 1 then -- # test-inc + N := N + 1; -- # inc + end if; + end loop; + return N; -- # count + end; + +begin + N := 0; -- # elab + while N < Lib_Init.N1 loop -- # test-init + Values (Values'First + N + 1) := 1; -- # init + N := N + 1; -- # init + end loop; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.ads new file mode 100644 index 000000000..862f4d4aa --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.ads @@ -0,0 +1,7 @@ +-- Package featuring a loop controlled by a decision within +-- its body elaboration code. + +package Lib_Loop_Statements is + Values : array (1 .. 8) of Integer := (others => 0); + function N_Ones return Integer; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.adb index 099b291e4..866285416 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.adb @@ -36,13 +36,6 @@ package body More_LOOP_Statements is end Change_Char; begin - Idx := Identity (1); --# elab - - while Idx <= Identity (10) loop --# elab - Global_Sample (Idx) := Level (Identity (Idx)); --# elab - Idx := Idx + 1; --# elab - end loop; - for J in Global_String'Range loop --# elab Global_String (J) := Character'Val (J); --# elab end loop; From 8d783d8ec4d51adde124fe87ee91d894f2040ae1 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Tue, 28 Feb 2023 09:47:45 -0800 Subject: [PATCH 0180/1483] testsuite: tolerate messages from old gnatcov about missing obj dirs Part of W215-023 (gnatcov 22.x qualification) --- testsuite/SCOV/instr.py | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 5f9af2477..f84aace16 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -7,7 +7,7 @@ from SUITE.context import thistest from SUITE.cutils import contents_of, ext, indent -from SUITE.tutils import RUNTIME_INFO, xcov +from SUITE.tutils import RUNTIME_INFO, GNATCOV_INFO, xcov def default_dump_trigger(mains): @@ -118,6 +118,21 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", auto_languages=auto_languages, ) + # When no message is to be tolerated, fallback to an actual regexp + # that will never match: + re_tolerate_messages = tolerate_messages or "__NEVER_IN_A_WARNING___" + + # For qualification purposes, tolerate possible warnings about + # inexistant object dirs from older gnatcov versions, typically + # issued when instrumenting before building. Tests do a best + # effort attempt at creating objects dirs beforehand but doing + # that is cumbersome for some of the more convoluted tests. + if GNATCOV_INFO.major < 23: + re_tolerate_messages = '|'.join( + "(?:{})".format(mre) for mre in [ + "object directory.*not found", re_tolerate_messages] + ) + if register_failure: output = contents_of(out) @@ -131,7 +146,6 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", pattern="(?:!!!|\*\*\*|warning:).*$", string=output, flags=re.MULTILINE) - re_tolerate_messages = tolerate_messages or "__NEVER_IN_A_WARNING___" unexpected_messages = [ w for w in messages if not re.search(pattern=re_tolerate_messages, string=w) From 7dabe78af44c1627b9f0ca0272779e3d06f39dc3 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 1 Mar 2023 08:27:26 -0800 Subject: [PATCH 0181/1483] XFAIL stmt/Exemptions/StmtsInElab for doA instrumentation with gnatcov 22 Exemptions naturally come with conditionals, and conditionals at lib level are not supported by the instrumenter before gnatcov 23. Part of W215-023 (gnatcov 22.x qualification) --- testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/test.opt diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/test.opt b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation From 88769b7ec4cad2e9968f3b0ec803713409a4ddeb Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Thu, 2 Mar 2023 03:38:16 -0800 Subject: [PATCH 0182/1483] Replace Pre by Precondition in test on disabled assert pragma For mcdc, the gnatcov 22 instrumenter mistakenly tries to instrument a disabled library level "Pre" pragma, only to warn that it cannot find a spot to declare the mcdc state. This is not a real problem as the pragma was requested to be disabled anyway, just produces a warning which triggers a test failure. As the use of aspects instead of pragmas is generally encouraged, we expect pragmas not to be used much if at all in the first place. This change simply replaces a lone Pre pragma by a Precondition one, functionally equivalent and better recognized by gnatcov 22. Part of W215-023 (gnatcov 22.x qualification) --- .../Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.ads | 2 +- .../Assertions/Inactive/PrePost/PrePragma_LibSpec/tc.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.ads index 26ff26852..f6252a056 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.ads @@ -7,5 +7,5 @@ package Ops is type T_Operand is new T_Base_Operand with null record; procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand); - pragma Pre (A.Valid and then B.Valid); -- # cond + pragma Precondition (A.Valid and then B.Valid); -- # cond end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/tc.rst b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/tc.rst index d7adc3cac..cb7f81c79 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/tc.rst +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/tc.rst @@ -1,3 +1,3 @@ -**DC on a library level subpgrogram with a disabled Pre pragma** +**DC on a library level subpgrogram with a disabled Precondition pragma** LRMREF: 11.4.2, 6.1.1 From 10783fddddd409e11abc9091641cc7502bae3435 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 20 Feb 2023 11:15:16 +0100 Subject: [PATCH 0183/1483] Add the cobertura report format to the list of gnatcov formats This is the format de facto supported by the Gitlab CI coverage integration in merge requests. Note that we can't express the MC/DC level in this report format: we make the decision to actually express decision coverage in their branch coverage terminology. --- testsuite/tests/cobertura_validation/lib.c | 5 + testsuite/tests/cobertura_validation/pkg.adb | 6 + testsuite/tests/cobertura_validation/pkg.ads | 9 + testsuite/tests/cobertura_validation/test.adb | 18 + testsuite/tests/cobertura_validation/test.py | 36 + tools/gnatcov/Makefile | 1 + tools/gnatcov/annotations-cobertura.adb | 639 ++++++++++++++++++ tools/gnatcov/annotations-cobertura.ads | 59 ++ tools/gnatcov/annotations.adb | 3 + tools/gnatcov/annotations.ads | 3 +- tools/gnatcov/cobertura.dtd | 60 ++ tools/gnatcov/command_line.ads | 14 +- tools/gnatcov/gnatcov_bits_specific.adb | 15 +- 13 files changed, 863 insertions(+), 5 deletions(-) create mode 100644 testsuite/tests/cobertura_validation/lib.c create mode 100644 testsuite/tests/cobertura_validation/pkg.adb create mode 100644 testsuite/tests/cobertura_validation/pkg.ads create mode 100644 testsuite/tests/cobertura_validation/test.adb create mode 100644 testsuite/tests/cobertura_validation/test.py create mode 100644 tools/gnatcov/annotations-cobertura.adb create mode 100644 tools/gnatcov/annotations-cobertura.ads create mode 100644 tools/gnatcov/cobertura.dtd diff --git a/testsuite/tests/cobertura_validation/lib.c b/testsuite/tests/cobertura_validation/lib.c new file mode 100644 index 000000000..c1524eef2 --- /dev/null +++ b/testsuite/tests/cobertura_validation/lib.c @@ -0,0 +1,5 @@ +int +and_then (int a, int b) +{ + return a && b; +} diff --git a/testsuite/tests/cobertura_validation/pkg.adb b/testsuite/tests/cobertura_validation/pkg.adb new file mode 100644 index 000000000..1f3b12e57 --- /dev/null +++ b/testsuite/tests/cobertura_validation/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + function Id (A : Boolean) return Boolean is + begin + return A; + end Id; +end Pkg; diff --git a/testsuite/tests/cobertura_validation/pkg.ads b/testsuite/tests/cobertura_validation/pkg.ads new file mode 100644 index 000000000..4c73d86df --- /dev/null +++ b/testsuite/tests/cobertura_validation/pkg.ads @@ -0,0 +1,9 @@ +with Interfaces.C; use Interfaces.C; + +package Pkg is + function And_Then (A, B : int) return int; + pragma Import + (Convention => C, Entity => And_Then, External_Name => "and_then"); + + function Id (A : Boolean) return Boolean; +end Pkg; diff --git a/testsuite/tests/cobertura_validation/test.adb b/testsuite/tests/cobertura_validation/test.adb new file mode 100644 index 000000000..7d416f467 --- /dev/null +++ b/testsuite/tests/cobertura_validation/test.adb @@ -0,0 +1,18 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Interfaces.C; use Interfaces.C; + +with Pkg; + +procedure Test is + function And_Then (A, B : Boolean) return Boolean; + + function And_Then (A, B : Boolean) return Boolean is + begin + return A and then B; + end And_Then; + +begin + Put_Line (int'Image (Pkg.And_Then (0, 1))); + Put_Line (Boolean'Image (And_Then (Pkg.Id (True), False))); +end Test; diff --git a/testsuite/tests/cobertura_validation/test.py b/testsuite/tests/cobertura_validation/test.py new file mode 100644 index 000000000..f7d3672a6 --- /dev/null +++ b/testsuite/tests/cobertura_validation/test.py @@ -0,0 +1,36 @@ +""" +Check that the cobertura.dtd standard validates the cobertura report that +gnatcov produces. +""" + +import os + +from lxml import etree + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +Wdir("tmp_") + + +def build_run_coverage_and_check(covlevel): + build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], + mains=["test.adb"])), + covlevel=covlevel, + mains=["test"], + extra_coverage_args=["--annotate=cobertura"] + ) + parser = etree.XMLParser(dtd_validation=True) + etree.parse(os.path.join("obj", "cobertura.xml"), parser) + + +build_run_coverage_and_check("stmt+mcdc") + +if thistest.options.trace_mode == "bin": + build_run_coverage_and_check("insn") + build_run_coverage_and_check("branch") + +thistest.result() diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index d8b0cde2a..0fa67a902 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -305,6 +305,7 @@ install-gnatcov_rts: install-lib: $(MKDIR) $(PREFIX)/lib/gnatcoverage $(CP) gnatcov-xml-report.xsd $(PREFIX)/lib/gnatcoverage + $(CP) cobertura.dtd $(PREFIX)/lib/gnatcoverage install-common: install-bin install-examples install-gnatcov_rts install-lib install-without-doc: install-common diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb new file mode 100644 index 000000000..a77a4490f --- /dev/null +++ b/tools/gnatcov/annotations-cobertura.adb @@ -0,0 +1,639 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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.Calendar.Conversions; use Ada.Calendar.Conversions; +with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Containers.Ordered_Maps; +with Ada.Directories; +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Strings.Fixed; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; + +with GNAT.OS_Lib; +with GNAT.Regpat; use GNAT.Regpat; + +with Interfaces.C; use Interfaces.C; + +with Annotations.Xml; use Annotations.Xml; +with Command_Line; use Command_Line; +with Coverage; use Coverage; +with Coverage_Options; use Coverage_Options; +with Coverage.Source; use Coverage.Source; +with Outputs; use Outputs; +with Support_Files; +with Switches; use Switches; +with Version; + +package body Annotations.Cobertura is + + DTD_Basename : constant String := "cobertura.dtd"; + DTD_Filename : constant String := Support_Files.In_Lib_Dir (DTD_Basename); + + type Pattern_Matcher_Acc is access all GNAT.Regpat.Pattern_Matcher; + + type Cobertura_Pretty_Printer is new Pretty_Printer with record + -- Pretty printer type for the Cobertura annotation format + + Report_File : File_Type; + -- Cobertura.xml file + + Indentation : Natural := 0; + + Source_Roots : Pattern_Matcher_Acc; + -- Regexp matching a list of prefixes removed in the filenames output + -- in the report. + -- + -- This implements gitlab support, which requires paths that are + -- relative to the project gitlab repository, and not fullnames. The + -- user is supposed to pass one or several source roots through the + -- --source-roots option. + + end record; + + type Rate_Type is digits 3; + + function Img (R : Rate_Type) return String; + -- Return a string representation of the rate without an exponent suffix + -- and without a leading space. + + -------------------- + -- XML generation -- + -------------------- + + Xml_Header : constant String := ""; + Report_File_Name : constant String := "cobertura.xml"; + + function A (Name : String; Value : String) return String; + -- Return a string representing an xml attribute whose name + -- and value are given in parameter, i.e. Name = "Value". + + procedure T + (Pp : in out Cobertura_Pretty_Printer'Class; + Name : String; + Attributes : String); + -- Print a string representing an empty tag whose name and + -- attributes are given in parameter, i.e. . + + procedure ST + (Pp : in out Cobertura_Pretty_Printer'Class; + Name : String; + Attributes : String); + -- Print a string representing a start tag whose name and attributes + -- are given in parameter, i.e. . + + procedure ST + (Pp : in out Cobertura_Pretty_Printer'Class; + Name : String); + -- Same as ST, with no attributes. + + procedure ET + (Pp : in out Cobertura_Pretty_Printer'Class; + Name : String); + -- Print a string representing an end tag whose name is given + -- in parameter, i.e. . + + ----------------------------------------------------- + -- Cobertura_Pretty_Printer's primitive operations -- + -- (inherited from Pretty_Printer) -- + ----------------------------------------------------- + + procedure Pretty_Print_Start + (Pp : in out Cobertura_Pretty_Printer); + + procedure Pretty_Print_End + (Pp : in out Cobertura_Pretty_Printer); + + procedure Pretty_Print_Start_File + (Pp : in out Cobertura_Pretty_Printer; + File : Source_File_Index; + Skip : out Boolean); + + procedure Pretty_Print_End_File (Pp : in out Cobertura_Pretty_Printer); + + procedure Pretty_Print_Start_Line + (Pp : in out Cobertura_Pretty_Printer; + Line_Num : Natural; + Info : Line_Info_Access; + Line : String); + + ----------------------------- + -- Shortcut for Put_Line's -- + ----------------------------- + + procedure P + (Pp : Cobertura_Pretty_Printer'Class; + S : String); + -- Put_Line S in the destination file + + ----------------------------- + -- Statistics computations -- + ----------------------------- + + procedure Compute_Line_Stats + (Li_Stat : Li_Stat_Array; + Lines_Valid : out Natural; + Lines_Covered : out Natural; + Line_Rate : out Rate_Type); + -- Compute line statistics. This does not account for exempted / non- + -- instrumented / non-coverable lines. + + procedure Compute_Branch_Stats + (Ob_Stats : Ob_Stat_Array; + Branches_Valid : out Natural; + Branches_Covered : out Natural; + Branch_Rate : out Rate_Type); + -- Compute branch statistics. This does not account exempted / non- + -- instrumented / non-coverable obligations. + -- + -- We choose to represent decisions in the branch terminology that + -- cobertura uses: a decision yields two branches. If it is + -- not covered, neither branch is covered; if it is partially + -- covered, one of the branch is; if it is fully covered, the two + -- branches are. + + --------------- + -- Installed -- + --------------- + + function Installed return Boolean is + begin + return Ada.Directories.Exists (DTD_Filename); + end Installed; + + --------- + -- Img -- + --------- + + function Img (R : Rate_Type) return String + is + package Float_IO is new Ada.Text_IO.Float_IO (Rate_Type); + Result : String (1 .. 8); + begin + Float_IO.Put + (To => Result, + Item => R, + Aft => Rate_Type'Digits - 1, + Exp => 0); + return Ada.Strings.Fixed.Trim (Result, Side => Ada.Strings.Both); + end Img; + + ------- + -- A -- + ------- + + function A (Name : String; Value : String) return String is + begin + return " " & Name & "=" & '"' & To_Xml_String (Value) & '"'; + end A; + + -------- + -- ET -- + -------- + + procedure ET + (Pp : in out Cobertura_Pretty_Printer'Class; + Name : String) is + begin + Pp.Indentation := Pp.Indentation - 1; + Pp.P (""); + New_Line (Pp.Report_File); + end ET; + + --------------------- + -- Generate_Report -- + --------------------- + + procedure Generate_Report (Context : Coverage.Context_Access) is + use String_Vectors; + + Pp : Cobertura_Pretty_Printer := + (Need_Sources => True, + Context => Context, + others => <>); + + Source_Roots : String_Vectors.Vector renames + Args.String_List_Args (Opt_Source_Roots); + Source_Roots_Regexp : Unbounded_String; + Flags : constant Regexp_Flags := + (if GNAT.OS_Lib.Directory_Separator = '\' + then Case_Insensitive + else No_Flags); + -- See Pp.Source_Roots for more documentation + + begin + Append (Source_Roots_Regexp, "(?:"); + for Cur in Source_Roots.Iterate loop + Append (Source_Roots_Regexp, Element (Cur)); + if Cur /= Source_Roots.Last then + Append (Source_Roots_Regexp, "|"); + end if; + end loop; + Append (Source_Roots_Regexp, ")"); + + Pp.Source_Roots := + new Pattern_Matcher' + (Compile (+Source_Roots_Regexp, Flags)); + Annotations.Generate_Report (Pp, True, Subdir => "cobertura"); + end Generate_Report; + + ------- + -- P -- + ------- + + procedure P + (Pp : Cobertura_Pretty_Printer'Class; + S : String) + is + Spaces : constant String (1 .. Pp.Indentation) := (others => ' '); + begin + Put_Line (Pp.Report_File, Spaces & S); + end P; + + ---------------------- + -- Pretty_Print_End -- + ---------------------- + + procedure Pretty_Print_End + (Pp : in out Cobertura_Pretty_Printer) + is + begin + Pp.ET ("packages"); + Pp.ET ("coverage"); + Close (Pp.Report_File); + end Pretty_Print_End; + + --------------------------- + -- Pretty_Print_End_File -- + --------------------------- + + procedure Pretty_Print_End_File (Pp : in out Cobertura_Pretty_Printer) is + begin + Pp.ET ("lines"); + Pp.ET ("class"); + Pp.ET ("classes"); + Pp.ET ("package"); + end Pretty_Print_End_File; + + ------------------------ + -- Compute_Line_Stats -- + ------------------------ + + procedure Compute_Line_Stats + (Li_Stat : Li_Stat_Array; + Lines_Valid : out Natural; + Lines_Covered : out Natural; + Line_Rate : out Rate_Type) is + begin + Lines_Valid := + Li_Stat (Covered) + + Li_Stat (Not_Covered) + + Li_Stat (Partially_Covered); + Lines_Covered := Li_Stat (Covered) + Li_Stat (Partially_Covered); + Line_Rate := Rate_Type (Lines_Covered) / Rate_Type (Lines_Valid); + end Compute_Line_Stats; + + -------------------------- + -- Compute_Branch_Stats -- + -------------------------- + + procedure Compute_Branch_Stats + (Ob_Stats : Ob_Stat_Array; + Branches_Valid : out Natural; + Branches_Covered : out Natural; + Branch_Rate : out Rate_Type) + is + begin + Branches_Valid := + Ob_Stats (Decision).Stats (Covered) + + Ob_Stats (Decision).Stats (Not_Covered) + + Ob_Stats (Decision).Stats (Partially_Covered); + Branches_Covered := + 2 * Ob_Stats (Decision).Stats (Covered) + + Ob_Stats (Decision).Stats (Partially_Covered); + if Branches_Valid = 0 then + Branch_Rate := 1.0; + else + Branch_Rate := + Rate_Type (Branches_Covered) / Rate_Type (Branches_Valid); + end if; + end Compute_Branch_Stats; + + ------------------------ + -- Pretty_Print_Start -- + ------------------------ + + procedure Pretty_Print_Start (Pp : in out Cobertura_Pretty_Printer) + is + Success : Boolean; + Timestamp : constant String := + Ada.Strings.Fixed.Trim + (long'Image (To_Unix_Time (Pp.Context.Timestamp)), + Ada.Strings.Left); + begin + -- Copy the DTD Schema to the output directory + + GNAT.OS_Lib.Copy_File + (Name => DTD_Filename, + Pathname => Get_Output_Dir, + Success => Success, + Mode => GNAT.OS_Lib.Overwrite); + if not Success then + Fatal_Error + ("Error while copying " & DTD_Filename + & " to the output directory"); + end if; + + Create_Output_File (Pp.Report_File, Report_File_Name); + + Pp.P (Xml_Header); + Pp.P (""); + + -- Compute statistics + + declare + Lines_Valid, Lines_Covered : Natural; + Line_Rate : Rate_Type; + + Branches_Valid, Branches_Covered : Natural; + Branch_Rate : Rate_Type; + begin + Compute_Line_Stats + (Global_Stats, Lines_Valid, Lines_Covered, Line_Rate); + Compute_Branch_Stats + (Global_Ob_Stats, Branches_Valid, Branches_Covered, Branch_Rate); + + Pp.ST ("coverage", + A ("line-rate", Img (Line_Rate)) + & A ("branch-rate", Img (Branch_Rate)) + & A ("lines-covered", Img (Lines_Covered)) + & A ("lines-valid", Img (Lines_Valid)) + & A ("branches-covered", Img (Branches_Covered)) + & A ("branches-valid", Img (Branches_Valid)) + + -- Cobertura also provides the cyclomatic complexity number. + -- As we don't compute this, print an arbitrary invalid value. + + & A ("complexity", "-1") + & A ("version", Version.Xcov_Version) + & A ("timestamp", Timestamp)); + + Pp.ST ("sources"); + Pp.ET ("sources"); + Pp.ST ("packages"); + end; + end Pretty_Print_Start; + + ----------------------------- + -- Pretty_Print_Start_File -- + ----------------------------- + + procedure Pretty_Print_Start_File + (Pp : in out Cobertura_Pretty_Printer; + File : Source_File_Index; + Skip : out Boolean) + is + Info : constant File_Info_Access := Get_File (File); + + Simple_Source_Filename : constant String := Info.Simple_Name.all; + + Lines_Valid, Lines_Covered : Natural; + Line_Rate : Rate_Type; + + Branches_Valid, Branches_Covered : Natural; + Branch_Rate : Rate_Type; + + Adjusted_Filename : Unbounded_String := +Info.Full_Name.all; + -- This is the full filename with prefix from --source-roots removed + + begin + if not Info.Has_Source then + Skip := True; + return; + end if; + Skip := False; + + -- Compute line and branch statistics + + Compute_Line_Stats + (Info.Li_Stats, Lines_Valid, Lines_Covered, Line_Rate); + Compute_Branch_Stats + (Info.Ob_Stats, + Branches_Valid, + Branches_Covered, + Branch_Rate); + + -- Remove the source root prefix + + declare + Match_Res : GNAT.Regpat.Match_Array (0 .. 0); + begin + GNAT.Regpat.Match + (Pp.Source_Roots.all, +Adjusted_Filename, Match_Res); + if Match_Res (0) /= GNAT.Regpat.No_Match then + Adjusted_Filename := Unbounded_Slice + (Adjusted_Filename, + Match_Res (0).Last + 1, + Positive (Length (Adjusted_Filename))); + end if; + end; + + Pp.ST ("package", + A ("name", Simple_Source_Filename) + & A ("line-rate", Img (Line_Rate)) + & A ("branch-rate", Img (Branch_Rate)) + & A ("complexity", "-1")); + Pp.ST ("classes"); + Pp.ST ("class", + A ("name", Simple_Source_Filename) + & A ("filename", +Adjusted_Filename) + & A ("line-rate", Img (Line_Rate)) + & A ("branch-rate", Img (Branch_Rate)) + & A ("complexity", "-1")); + Pp.ST ("methods"); + Pp.ET ("methods"); + Pp.ST ("lines"); + end Pretty_Print_Start_File; + + ----------------------------- + -- Pretty_Print_Start_Line -- + ----------------------------- + + procedure Pretty_Print_Start_Line + (Pp : in out Cobertura_Pretty_Printer; + Line_Num : Natural; + Info : Line_Info_Access; + Line : String) + is + Coverage_State : constant Any_Line_State := + Aggregated_State (Info.all); + Exempted : constant Boolean := Info.Exemption /= Slocs.No_Location; + begin + if not Exempted and then Coverage_State /= No_Code then + declare + subtype Coverage_Line_State is + Any_Line_State range Not_Covered .. Covered; + package SCOs_State_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => SCO_Id, + Element_Type => Coverage_Line_State); + + Hit : Natural := 0; + -- Whether the line was covered or not. Cobertura enables + -- counting the number of coverage hits; we don't. + + Has_Decision : Boolean := False; + -- Whether there is a decision on the current line + + State_Decisions : SCOs_State_Maps.Map; + -- List of decisions at the current line and their coverage state + + Branches_Covered, Branches_Valid : Natural := 0; + begin + if Coverage_State /= Not_Covered then + Hit := 1; + end if; + + -- Express decision coverage in cobertura notion of condition + -- coverage: in Cobertura terminology, a condition is represented + -- as a two-valuation expression: either 0, 1 or 2 of its + -- valuation are covered. + + -- Start by getting all of the decisions present on this line. + -- Note that there can be no SCOs for the line if using binary + -- traces with the insn coverage level. TODO???: is this really + -- something we want to support? + + if Info.SCOs /= null then + for SCO of Info.SCOs.all loop + if Kind (SCO) /= Removed + and then First_Sloc (SCO).L.Line = Line_Num + and then SCO_Kind (Kind (SCO)) = Decision + and then + (Coverage.Enabled (Decision) + or else Coverage.MCDC_Coverage_Enabled) + then + declare + Line_State : constant Any_Line_State := + Get_Line_State (SCO, Decision); + begin + if Line_State in Coverage_Line_State then + Has_Decision := True; + State_Decisions.Insert (SCO, Line_State); + end if; + end; + end if; + end loop; + end if; + + -- Compute the decision coverage rate if any + + if not State_Decisions.Is_Empty then + for State_Decision of State_Decisions loop + Branches_Valid := Branches_Valid + 2; + if State_Decision = Covered then + Branches_Covered := Branches_Covered + 2; + elsif State_Decision = Partially_Covered then + Branches_Covered := Branches_Covered + 1; + end if; + end loop; + end if; + + -- Emit the xml line node. Here is an example: + -- + -- + + declare + Line_Attributes : Unbounded_String; + begin + Append (Line_Attributes, A ("number", Img (Line_Num))); + Append (Line_Attributes, A ("hits", Img (Hit))); + if Has_Decision then + Append (Line_Attributes, A ("branch", "true")); + Append + (Line_Attributes, + A + ("condition-coverage", + Img (Ratio (Branches_Covered, Branches_Valid)) + & "%" & "(" & Img (Branches_Covered) & "/" + & Img (Branches_Valid) & ")")); + else + Append (Line_Attributes, A ("branch", "false")); + end if; + Pp.ST ("line", +Line_Attributes); + + Pp.ST ("conditions"); + declare + I : Integer := 0; + Coverage_Ratio : Integer; + begin + for State_Decision of State_Decisions loop + Coverage_Ratio := + (case State_Decision is + when Not_Covered => 0, + when Partially_Covered => 50, + when Covered => 100); + Pp.T + ("condition", + A ("number", Img (I)) + & A ("type", "jump") + & A ("coverage", Img (Coverage_Ratio) & "%")); + I := I + 1; + end loop; + end; + Pp.ET ("conditions"); + + Pp.ET ("line"); + end; + end; + end if; + end Pretty_Print_Start_Line; + + ------- + -- T -- + ------- + + procedure T + (Pp : in out Cobertura_Pretty_Printer'Class; + Name : String; + Attributes : String) is + begin + Pp.P ("<" & Name & Attributes & "/>"); + end T; + + -------- + -- ST -- + -------- + + procedure ST + (Pp : in out Cobertura_Pretty_Printer'Class; + Name : String; + Attributes : String) is + begin + Pp.P ("<" & Name & Attributes & ">"); + Pp.Indentation := Pp.Indentation + 1; + end ST; + + procedure ST + (Pp : in out Cobertura_Pretty_Printer'Class; + Name : String) is + begin + Pp.P ("<" & Name & ">"); + Pp.Indentation := Pp.Indentation + 1; + end ST; + +end Annotations.Cobertura; diff --git a/tools/gnatcov/annotations-cobertura.ads b/tools/gnatcov/annotations-cobertura.ads new file mode 100644 index 000000000..a62e2a460 --- /dev/null +++ b/tools/gnatcov/annotations-cobertura.ads @@ -0,0 +1,59 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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 Coverage; + +package Annotations.Cobertura is + + -- Generate a report in the Cobertura report format. This report format + -- is designed for integration with standard continuous integration + -- systems, e.g. gitlab CI, which do not support standard gnatcov report + -- formats. The only specification for this format is a document type + -- definition found there: + -- https://github.com/cobertura/web/blob/master/htdocs/xml/coverage-04.dtd + -- + -- This is a partial report in the sense that gnatcov coverage metrics + -- can't be specified accurately in the Cobertura report format. This + -- format provides + -- + -- * Line coverage metrics: whether a line was covered, and the number + -- of coverage hits. + -- + -- * Condition coverage metrics: whether a line is branching (talking + -- Cobertura terminology, which means whether it has any condition). + -- For each condition, whether its true / false / both valuation(s) + -- were covered. + -- + -- Obviously, neither decision and MC/DC coverage can be expressed using + -- the aforementioned metrics without little tweaks. We actually chose + -- to represent decision coverage in the condition coverage metrics: + -- a decision (gnatcov) is represented as a condition (cobertura). We drop + -- the MC/DC coverage as we can't express it. + -- + -- Note that for now, at least some of the continuous integration systems + -- (this is the case for gitlab at least) do not integrate condition + -- coverage results, which means that users won't have decision coverage + -- results over their code if they use it with gitlab. + + procedure Generate_Report (Context : Coverage.Context_Access); + + function Installed return Boolean; + -- Return whether the DTD is installed, i.e. the required resource files + -- are installed in lib/gnatcoverage/. + +end Annotations.Cobertura; diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 66714b06b..feab9f492 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -878,6 +878,9 @@ package body Annotations is elsif Option = "report" then return Annotate_Report; + elsif Option = "cobertura" then + return Annotate_Cobertura; + else return Annotate_Unknown; end if; diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index afa5ee718..925afff4e 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -45,6 +45,7 @@ package Annotations is Annotate_Xcov_Plus, Annotate_Html_Plus, Annotate_Dynamic_Html, + Annotate_Cobertura, Annotate_Xml, Annotate_Report, Annotate_Unknown); @@ -98,7 +99,7 @@ private function Message_Annotation (M : Message) return String; -- Return a representation of M to be associated with an annotated line - Global_Stats : Li_Stat_Array := (others => 0); + Global_Stats : Li_Stat_Array := (others => 0); Global_Ob_Stats : Ob_Stat_Array; -- Stats associated with the whole set of source files that this package -- considers (i.e. total numbers of lines / obligations, of partially diff --git a/tools/gnatcov/cobertura.dtd b/tools/gnatcov/cobertura.dtd new file mode 100644 index 000000000..e5a21bb15 --- /dev/null +++ b/tools/gnatcov/cobertura.dtd @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index b0ea3ec78..992eabeed 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -144,7 +144,8 @@ package Command_Line is Opt_Restricted_To_Languages, Opt_Annotation_Format, Opt_C_Opts, - Opt_CPP_Opts); + Opt_CPP_Opts, + Opt_Source_Roots); -- Set of string list options we support. More complete descriptions below. package Parser is new Argparse @@ -1098,7 +1099,16 @@ package Command_Line is "List of additional compiler switches to analayze C++ source" & " files.", Commands => (Cmd_Instrument => True, others => False), - Internal => False) + Internal => False), + + Opt_Source_Roots => Create + (Long_Name => "--source-roots", + Pattern => "[PATH|LIST]", + Help => + "Option specific to the Cobertura coverage report: remove the" + & " specified prefixes from the filenames in the report", + Commands => (Cmd_Coverage => True, others => False), + Internal => True) ); procedure Bool_Callback diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 5718d516f..458fd4714 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -30,6 +30,7 @@ with GNAT.Strings; use GNAT.Strings; with Snames; with ALI_Files; +with Annotations.Cobertura; with Annotations.Dynamic_Html; with Annotations.Html; with Annotations.Report; @@ -1667,6 +1668,12 @@ begin ("Dynamic HTML report format support is not installed."); end if; + if Annotation (Annotate_Cobertura) + and then not Annotations.Cobertura.Installed + then + Fatal_Error ("Cobertura report format support is not installed."); + end if; + -- Check that the user specified units of interest. We'll load SCOs -- from ALIs/SIDs only when necessary, i.e. only the first time we -- process a binary trace file. This will avoid conflicts between @@ -2293,8 +2300,7 @@ begin Auto_Delete => not Save_Temps); if Annotation (Annotate_Xml) then - Annotations.Xml.Generate_Report - (Context'Unchecked_Access); + Annotations.Xml.Generate_Report (Context'Unchecked_Access); end if; if Annotation (Annotate_Xcov) @@ -2320,6 +2326,11 @@ begin Report_Title => Args.String_Args (Opt_Report_Title)); end if; + if Annotation (Annotate_Cobertura) then + Annotations.Cobertura.Generate_Report + (Context'Unchecked_Access); + end if; + if Annotation (Annotate_Report) then Annotations.Report.Generate_Report (Context'Unchecked_Access, Output, Dump_Units_In_Report); From 11e95df1011cd697bf1c3e8b2d43714e89cee2af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 9 Mar 2023 14:26:14 +0100 Subject: [PATCH 0184/1483] Testsuite: Adapt GNATCOV_INFO to work with gnatcov dev The development tree version of gnatcov does not have a major listed when running "gnatcov --version" but only "development-tree". Add support for this by implementing a "major_less" method to gnatcov_info, assuming that gnatcov dev has a major greater than anything. Part of W215-023 (gnatcov 22.x qualification) --- testsuite/SCOV/instr.py | 2 +- testsuite/SUITE/control.py | 32 ++++++++++++++++++++++++++++---- testsuite/testsuite.py | 7 ++++++- 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index f84aace16..607b705f5 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -127,7 +127,7 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", # issued when instrumenting before building. Tests do a best # effort attempt at creating objects dirs beforehand but doing # that is cumbersome for some of the more convoluted tests. - if GNATCOV_INFO.major < 23: + if GNATCOV_INFO.major_at_most(22): re_tolerate_messages = '|'.join( "(?:{})".format(mre) for mre in [ "object directory.*not found", re_tolerate_messages] diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index cf57c656f..aeb8b856f 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -357,12 +357,36 @@ def target_info(target=None): class GnatcovInfo: def __init__(self): - self.major = int( - re.search( + p = re.search( pattern="GNATcoverage (\d+)", string=version("gnatcov") - ).group(1)) - self.has_setup = self.major >= 23 + ) + self._major = int(p.group(1)) if p else None + self.has_setup = self.major_at_least(23) + + + def major_at_most(self, val): + """ + Returns whether the major version of gnatcov is less or equal than + val. Consider that development versions of gnatcov have a greater + major version than anything. + """ + return self._major is not None and self._major <= val + + def major_at_least(self, val): + """ + Returns whether the major version of gnatcov is greater or equal than + val. Consider that development versions of gnatcov have a greater + major version than anything. + """ + return self._major is None or self._major >= val + + def major(self): + """ + Major of gnatcov, if defined, or None if gnatcov is a development + version. + """ + return self._major def gnatcov_info(): return GnatcovInfo() diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 22f6b00ee..2674c82e6 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1396,8 +1396,13 @@ def _gnatcov_discriminants(self): Compute the discriminant that reflects the version of the particular gnatcov in use. """ + gnatcov_info = control.gnatcov_info() - return ["gnatcov-{}".format(control.gnatcov_info().major)] + return ( + ["gnatcov-{}".format(gnatcov_info.major())] + if gnatcov_info.major() + else [] + ) # -------------------------- From 4e99288ccf861daae884b431487156f35cbdf54b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 9 Mar 2023 14:30:11 +0100 Subject: [PATCH 0185/1483] Testsuite: Add options to change dump trigger and channel This change adds two options that respectively change the default dump trigger and default dump channel. This is useful to ensure for future qualifications that we are testing gnatcov with the correct set of options. Forcing the dump trigger or dump channel can mess with the logic of some of the internal tests, by moving the buffer dump point (and thus changing what is covered or not) or violating some assumptions concerning the location of traces. Part of W215-023 (gnatcov 22.x qualification) --- testsuite/SCOV/instr.py | 8 ++++++-- testsuite/SCOV/internals/driver.py | 11 +++++++++-- testsuite/SUITE/control.py | 19 ++++++++++++++++++- testsuite/testsuite.py | 10 ++++++++++ 4 files changed, 43 insertions(+), 5 deletions(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 607b705f5..ab0433920 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -12,7 +12,9 @@ def default_dump_trigger(mains): """Return the default dump trigger to use in testcases.""" - if RUNTIME_INFO.has_full_runtime: + if thistest.options.default_dump_trigger: + return thistest.options.default_dump_trigger + elif RUNTIME_INFO.has_full_runtime: return 'atexit' # It does not make sense to have a dump-trigger=ravenscar-task-termination @@ -26,7 +28,9 @@ def default_dump_trigger(mains): def default_dump_channel(): """Return the default dump channel to use in testcases.""" - if RUNTIME_INFO.has_full_runtime: + if thistest.options.default_dump_channel: + return thistest.options.default_dump_channel + elif RUNTIME_INFO.has_full_runtime: return 'bin-file' else: return 'base64-stdout' diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 2296a487e..350507029 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -33,7 +33,7 @@ xcov_instrument) from SUITE.context import thistest -from SUITE.control import language_info +from SUITE.control import language_info, runtime_info from SUITE.cutils import ext, to_list, list_to_file, match, no_ext from SUITE.cutils import contents_of, lines_of from SUITE.gprutils import GPRswitches @@ -1301,6 +1301,7 @@ def mode_build(self): covlevel=self.xcovlevel, extra_args=to_list(self.covctl.covoptions) if self.covctl else [], dump_channel=self.dump_channel, + dump_trigger=self.dump_trigger, gprsw=instrument_gprsw, gpr_obj_dir=self.gpr_obj_dir, out=out) @@ -1309,7 +1310,8 @@ def mode_build(self): # trigger will not work when the test driver ends with an unhandled # exception. To workaround that, force the dump in the last chance # handler. - if default_dump_trigger(self.drivers) == 'main-end': + if (self.dump_trigger == 'main-end' + and not runtime_info().has_exception_propagation): # The only tests with multiple drivers are consolidation ones, # which compute consolidated coverage reports from data obtained # in previously executed tests (trace files or checkpoints). These @@ -1373,3 +1375,8 @@ def mode_tracename_for(self, pgm): def dump_channel(self): """Return the dump channel to use when instrumenting programs.""" return default_dump_channel() + + @property + def dump_trigger(self): + """Return the dump trigger to use when instrumenting programs.""" + return default_dump_trigger(self.drivers) diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index aeb8b856f..a86afbbf9 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -240,6 +240,7 @@ def __init__(self, runtime_name=None): self.has_ravenscar_runtime = False self.has_kernel_runtime = False self.has_light_runtime = False + self.has_exception_propagation = True if not self.runtime_name: self.has_full_runtime = True @@ -247,10 +248,13 @@ def __init__(self, runtime_name=None): self.has_ravenscar_runtime = True elif 'light-tasking' in self.runtime_name: self.has_ravenscar_runtime = True + self.has_exception_propagation = False elif self.runtime_name.startswith('zfp'): self.has_light_runtime = True + self.has_exception_propagation = False elif self.runtime_name.startswith('light-'): self.has_light_runtime = True + self.has_exception_propagation = False elif self.runtime_name == 'kernel': self.has_kernel_runtime = True else: @@ -292,7 +296,6 @@ def gnatcov_rts_project(self): else 'gnatcov_rts' ) - def runtime_info(runtime=None): if runtime is None: runtime = env.main_options.RTS @@ -531,3 +534,17 @@ def add_shared_options_to(parser, toplevel): parser.add_argument( '--rewrite', action='store_true', help='Rewrite test baselines according to current outputs.') + + # --default-dump-trigger + parser.add_argument( + '--default-dump-trigger', dest='default_dump_trigger', + help='Default dump trigger to be passed to "gnatcov instrument,"' + ' unless the test specifically overrides it.' + ) + + # --default-dump-channel + parser.add_argument( + '--default-dump-channel', dest='default_dump_channel', + help='Default dump channel to be passed to "gnatcov instrument,"' + ' unless the test specifically overrides it.' + ) \ No newline at end of file diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 2674c82e6..5fe6d21ef 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -567,6 +567,16 @@ def set_up(self): if mopt.all_warnings: testcase_cmd.append('--all-warnings') + if mopt.default_dump_trigger: + testcase_cmd.append( + f'--default-dump-trigger={mopt.default_dump_trigger}' + ) + + if mopt.default_dump_channel: + testcase_cmd.append( + f'--default-dump-channel={mopt.default_dump_channel}' + ) + # --gnatcov_ family for pgm, cmd in control.ALTRUN_GNATCOV_PAIRS: From 835fcb89909b838bfc77e7227ca50eda2066a40e Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Fri, 10 Mar 2023 02:59:19 -0800 Subject: [PATCH 0186/1483] Robustify Qualif/...550_Loop/src/lib_loop_statements wrt optimization Reorder statements to prevent the occurrence of a no-code line at the end of a loop sequence. The no-code was legit but is annoying to test against. Reordering the statements helps that, doesn't invalidate the test and doesn't hide any defect. Take the opportunity to add a few comments in a common spec, describing the testcase(s) organisation. Part of W215-023 (gnatcov 22.x qualification) --- .../550_Loop/src/lib_loop_statements.adb | 6 +++--- .../550_Loop/src/lib_loop_statements.ads | 8 ++++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb index 577cecdcd..1abb69325 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb @@ -17,8 +17,8 @@ package body Lib_Loop_Statements is begin N := 0; -- # elab - while N < Lib_Init.N1 loop -- # test-init - Values (Values'First + N + 1) := 1; -- # init - N := N + 1; -- # init + while N < Lib_Init.N1 loop -- # test-init + N := N + 1; -- # init + Values (Values'First + N) := 1; -- # init end loop; end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.ads index 862f4d4aa..f7ad17731 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.ads @@ -2,6 +2,14 @@ -- its body elaboration code. package Lib_Loop_Statements is + + -- An array of integers, all zero for starters. A number of these + -- are set to 1 in the package elab body. The number of values so + -- initialized is controlled by a variable in a distinct package spec, + -- provided by each testcase. Values : array (1 .. 8) of Integer := (others => 0); + function N_Ones return Integer; + -- Recompute the number of slots set by looking at the values + end; From c60f43b5c4d74531637c3da93628e39b78fc3d9e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 13 Mar 2023 10:19:42 +0000 Subject: [PATCH 0187/1483] paths.ads: minor reformatting --- tools/gnatcov/paths.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/paths.ads b/tools/gnatcov/paths.ads index c66f5c407..0d1acc5b6 100644 --- a/tools/gnatcov/paths.ads +++ b/tools/gnatcov/paths.ads @@ -40,7 +40,7 @@ package Paths is -- that the path components are valid when not empty. function Fold_Filename_Casing (Filename : String) return String; - -- If this is a windows host, return the lower-cased filename, otherwise + -- If this is a Windows host, return the lower-cased filename, otherwise -- leave it unchanged. function Canonicalize_Filename (Filename : String) return String; From 478db4315101fcd3f522d325eb00b197912d5108 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 13 Mar 2023 10:37:34 +0000 Subject: [PATCH 0188/1483] Fix a crash in the recently introduced unit provider Entries in the ADA_INCLUDE_PATH environment variable make the GPR system list them as "runtime directories". They are included even if there is no such directory, so code that processes them must have defensive code for this case. --- .../instr-cov/missing-runtime-dir/main.adb | 6 +++++ .../instr-cov/missing-runtime-dir/test.py | 27 +++++++++++++++++++ .../gnatcov/instrument-ada_unit_provider.adb | 21 ++++++++++++--- 3 files changed, 50 insertions(+), 4 deletions(-) create mode 100644 testsuite/tests/instr-cov/missing-runtime-dir/main.adb create mode 100644 testsuite/tests/instr-cov/missing-runtime-dir/test.py diff --git a/testsuite/tests/instr-cov/missing-runtime-dir/main.adb b/testsuite/tests/instr-cov/missing-runtime-dir/main.adb new file mode 100644 index 000000000..6e16d750d --- /dev/null +++ b/testsuite/tests/instr-cov/missing-runtime-dir/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello world"); +end Main; diff --git a/testsuite/tests/instr-cov/missing-runtime-dir/test.py b/testsuite/tests/instr-cov/missing-runtime-dir/test.py new file mode 100644 index 000000000..0facbcb14 --- /dev/null +++ b/testsuite/tests/instr-cov/missing-runtime-dir/test.py @@ -0,0 +1,27 @@ +""" +Check that instrumentation an Ada project does not fail when the +ADA_INCLUDE_PATH environment variable (classified as a "runtime directory" by +the GPR system) does not exist. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + + +Wdir("tmp_") + +os.environ["ADA_INCLUDE_PATH"] = os.path.abspath("nosuchdir") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], +) +check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {5}}}, "obj") + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit_provider.adb b/tools/gnatcov/instrument-ada_unit_provider.adb index da00309a5..2585c74b7 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.adb +++ b/tools/gnatcov/instrument-ada_unit_provider.adb @@ -73,12 +73,25 @@ package body Instrument.Ada_Unit_Provider is end; Close (Dependencies_File); - -- Read the runtime files and fill Provider.Runtime_Files + -- Read the runtime files and fill Provider.Runtime_Files. + -- + -- Note that the GPR system does not ensure that all runtime directories + -- actually exist, so do not crash in this case. for Dirname of Runtime_Directories loop - for File of Read_Dir (Create (+(+Dirname))).all loop - Provider.Runtime_Files.Insert (+File.Base_Name, +File.Full_Name); - end loop; + declare + Runtime_Dir : constant Virtual_File := Create (+(+Dirname)); + Files : File_Array_Access; + begin + if Runtime_Dir.Is_Directory then + Files := Runtime_Dir.Read_Dir; + for File of Files.all loop + Provider.Runtime_Files.Insert + (+File.Base_Name, +File.Full_Name); + end loop; + Unchecked_Free (Files); + end if; + end; end loop; return Provider; From 4937b4a3b70d42e043b914358e943d6e74631bda Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 13 Mar 2023 13:40:54 +0000 Subject: [PATCH 0189/1483] annotations-cobertura.adb: minor reformattings --- tools/gnatcov/annotations-cobertura.adb | 73 ++++++++++++------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb index a77a4490f..5ae51d962 100644 --- a/tools/gnatcov/annotations-cobertura.adb +++ b/tools/gnatcov/annotations-cobertura.adb @@ -47,12 +47,11 @@ package body Annotations.Cobertura is type Pattern_Matcher_Acc is access all GNAT.Regpat.Pattern_Matcher; type Cobertura_Pretty_Printer is new Pretty_Printer with record - -- Pretty printer type for the Cobertura annotation format - Report_File : File_Type; - -- Cobertura.xml file + -- "cobertura.xml" file Indentation : Natural := 0; + -- Indentation for the next XML items to write Source_Roots : Pattern_Matcher_Acc; -- Regexp matching a list of prefixes removed in the filenames output @@ -64,6 +63,7 @@ package body Annotations.Cobertura is -- --source-roots option. end record; + -- Pretty printer type for the Cobertura annotation format type Rate_Type is digits 3; @@ -79,53 +79,54 @@ package body Annotations.Cobertura is Report_File_Name : constant String := "cobertura.xml"; function A (Name : String; Value : String) return String; - -- Return a string representing an xml attribute whose name - -- and value are given in parameter, i.e. Name = "Value". + -- Return a string representing an xml attribute whose name and value are + -- given in parameter, i.e. Name = "Value". procedure T (Pp : in out Cobertura_Pretty_Printer'Class; Name : String; Attributes : String); - -- Print a string representing an empty tag whose name and - -- attributes are given in parameter, i.e. . + -- Print a string representing an empty tag whose name and attributes are + -- given in parameter, i.e. . procedure ST (Pp : in out Cobertura_Pretty_Printer'Class; Name : String; Attributes : String); - -- Print a string representing a start tag whose name and attributes - -- are given in parameter, i.e. . + -- Print a string representing a start tag whose name and attributes are + -- given in parameter, i.e. . procedure ST (Pp : in out Cobertura_Pretty_Printer'Class; Name : String); - -- Same as ST, with no attributes. + -- Same as ST, with no attributes procedure ET (Pp : in out Cobertura_Pretty_Printer'Class; Name : String); - -- Print a string representing an end tag whose name is given - -- in parameter, i.e. . + -- Print a string representing an end tag whose name is given in parameter, + -- i.e. . ----------------------------------------------------- -- Cobertura_Pretty_Printer's primitive operations -- -- (inherited from Pretty_Printer) -- ----------------------------------------------------- - procedure Pretty_Print_Start + overriding procedure Pretty_Print_Start (Pp : in out Cobertura_Pretty_Printer); - procedure Pretty_Print_End + overriding procedure Pretty_Print_End (Pp : in out Cobertura_Pretty_Printer); - procedure Pretty_Print_Start_File + overriding procedure Pretty_Print_Start_File (Pp : in out Cobertura_Pretty_Printer; File : Source_File_Index; Skip : out Boolean); - procedure Pretty_Print_End_File (Pp : in out Cobertura_Pretty_Printer); + overriding procedure Pretty_Print_End_File + (Pp : in out Cobertura_Pretty_Printer); - procedure Pretty_Print_Start_Line + overriding procedure Pretty_Print_Start_Line (Pp : in out Cobertura_Pretty_Printer; Line_Num : Natural; Info : Line_Info_Access; @@ -161,10 +162,9 @@ package body Annotations.Cobertura is -- instrumented / non-coverable obligations. -- -- We choose to represent decisions in the branch terminology that - -- cobertura uses: a decision yields two branches. If it is - -- not covered, neither branch is covered; if it is partially - -- covered, one of the branch is; if it is fully covered, the two - -- branches are. + -- cobertura uses: a decision yields two branches. If it is not covered, + -- neither branch is covered; if it is partially covered, one of the branch + -- is; if it is fully covered, the two branches are. --------------- -- Installed -- @@ -179,8 +179,7 @@ package body Annotations.Cobertura is -- Img -- --------- - function Img (R : Rate_Type) return String - is + function Img (R : Rate_Type) return String is package Float_IO is new Ada.Text_IO.Float_IO (Rate_Type); Result : String (1 .. 8); begin @@ -226,10 +225,10 @@ package body Annotations.Cobertura is Context => Context, others => <>); - Source_Roots : String_Vectors.Vector renames + Source_Roots : String_Vectors.Vector renames Args.String_List_Args (Opt_Source_Roots); - Source_Roots_Regexp : Unbounded_String; - Flags : constant Regexp_Flags := + Source_Roots_Regexp : Unbounded_String; + Flags : constant Regexp_Flags := (if GNAT.OS_Lib.Directory_Separator = '\' then Case_Insensitive else No_Flags); @@ -268,8 +267,7 @@ package body Annotations.Cobertura is -- Pretty_Print_End -- ---------------------- - procedure Pretty_Print_End - (Pp : in out Cobertura_Pretty_Printer) + overriding procedure Pretty_Print_End (Pp : in out Cobertura_Pretty_Printer) is begin Pp.ET ("packages"); @@ -281,7 +279,8 @@ package body Annotations.Cobertura is -- Pretty_Print_End_File -- --------------------------- - procedure Pretty_Print_End_File (Pp : in out Cobertura_Pretty_Printer) is + overriding procedure Pretty_Print_End_File + (Pp : in out Cobertura_Pretty_Printer) is begin Pp.ET ("lines"); Pp.ET ("class"); @@ -315,8 +314,7 @@ package body Annotations.Cobertura is (Ob_Stats : Ob_Stat_Array; Branches_Valid : out Natural; Branches_Covered : out Natural; - Branch_Rate : out Rate_Type) - is + Branch_Rate : out Rate_Type) is begin Branches_Valid := Ob_Stats (Decision).Stats (Covered) @@ -337,7 +335,8 @@ package body Annotations.Cobertura is -- Pretty_Print_Start -- ------------------------ - procedure Pretty_Print_Start (Pp : in out Cobertura_Pretty_Printer) + overriding procedure Pretty_Print_Start + (Pp : in out Cobertura_Pretty_Printer) is Success : Boolean; Timestamp : constant String := @@ -402,7 +401,7 @@ package body Annotations.Cobertura is -- Pretty_Print_Start_File -- ----------------------------- - procedure Pretty_Print_Start_File + overriding procedure Pretty_Print_Start_File (Pp : in out Cobertura_Pretty_Printer; File : Source_File_Index; Skip : out Boolean) @@ -473,7 +472,7 @@ package body Annotations.Cobertura is -- Pretty_Print_Start_Line -- ----------------------------- - procedure Pretty_Print_Start_Line + overriding procedure Pretty_Print_Start_Line (Pp : in out Cobertura_Pretty_Printer; Line_Num : Natural; Info : Line_Info_Access; @@ -492,8 +491,8 @@ package body Annotations.Cobertura is Element_Type => Coverage_Line_State); Hit : Natural := 0; - -- Whether the line was covered or not. Cobertura enables - -- counting the number of coverage hits; we don't. + -- Whether the line was covered or not. Cobertura enables counting + -- the number of coverage hits; we don't. Has_Decision : Boolean := False; -- Whether there is a decision on the current line @@ -514,7 +513,7 @@ package body Annotations.Cobertura is -- Start by getting all of the decisions present on this line. -- Note that there can be no SCOs for the line if using binary - -- traces with the insn coverage level. TODO???: is this really + -- traces with the insn coverage level. TODO??? Is this really -- something we want to support? if Info.SCOs /= null then From 7bfb23ba9144bc4403ef5b38fb254cf7bfe232c7 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 13 Mar 2023 13:47:39 +0000 Subject: [PATCH 0190/1483] Rework the --source-root(s) command line option GitLab pipelines test exactly one source repository, so it makes more sense to have only one "source root": rename the --source-roots option to --source-root, and adjust the codebase accordingly. Also turn "/prefix" patterns into "/prefix/" so that "/prefix/basename" always become "basename" (no leading slash). --- testsuite/tests/cobertura_validation/test.py | 44 +++++++-- tools/gnatcov/annotations-cobertura.adb | 99 ++++++++++---------- tools/gnatcov/command_line.ads | 29 +++--- tools/gnatcov/paths.adb | 13 ++- 4 files changed, 109 insertions(+), 76 deletions(-) diff --git a/testsuite/tests/cobertura_validation/test.py b/testsuite/tests/cobertura_validation/test.py index f7d3672a6..6decfa2ec 100644 --- a/testsuite/tests/cobertura_validation/test.py +++ b/testsuite/tests/cobertura_validation/test.py @@ -1,6 +1,5 @@ """ -Check that the cobertura.dtd standard validates the cobertura report that -gnatcov produces. +Check that creating Cobertura coverage reports works as expected. """ import os @@ -12,25 +11,52 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor, thistest -Wdir("tmp_") +tmp = Wdir("tmp_") + +gprsw = gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["test.adb"]) +) + + +def build_run_coverage_and_check(covlevel, source_root=None): + extra_args = ["--annotate=cobertura"] + if source_root is not None: + extra_args += ["--source-root", source_root] -def build_run_coverage_and_check(covlevel): build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], - mains=["test.adb"])), + gprsw=gprsw, covlevel=covlevel, mains=["test"], - extra_coverage_args=["--annotate=cobertura"] + extra_coverage_args=extra_args, ) parser = etree.XMLParser(dtd_validation=True) - etree.parse(os.path.join("obj", "cobertura.xml"), parser) + return etree.parse(os.path.join("obj", "cobertura.xml"), parser) +# For both source and object coverage, check that the output "cobertura.xml" +# file is valid according to the cobertura.dtd standard. build_run_coverage_and_check("stmt+mcdc") - if thistest.options.trace_mode == "bin": build_run_coverage_and_check("insn") build_run_coverage_and_check("branch") + +# Check that the --source-root option works as expected +for prefix in [tmp.homedir, tmp.homedir + "/"]: + thistest.log(f"== Prefix: {prefix} ==") + + report = build_run_coverage_and_check("stmt", source_root=prefix) + filenames = set() + for elt in report.getroot().iter(): + if elt.tag == "class": + filenames.add(elt.get("filename")) + + expected_filenames = {"lib.c", "pkg.adb", "pkg.ads", "test.adb"} + thistest.fail_if_not_equal( + "list of filenames in cobertura.xml", + "\n".join(sorted(expected_filenames)), + "\n".join(sorted(filenames)), + ) + thistest.result() diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb index 5ae51d962..fe1b26615 100644 --- a/tools/gnatcov/annotations-cobertura.adb +++ b/tools/gnatcov/annotations-cobertura.adb @@ -23,6 +23,7 @@ with Ada.Directories; with Ada.Text_IO; use Ada.Text_IO; with Ada.Strings.Fixed; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Unchecked_Deallocation; with GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; @@ -35,6 +36,7 @@ with Coverage; use Coverage; with Coverage_Options; use Coverage_Options; with Coverage.Source; use Coverage.Source; with Outputs; use Outputs; +with Paths; with Support_Files; with Switches; use Switches; with Version; @@ -44,7 +46,9 @@ package body Annotations.Cobertura is DTD_Basename : constant String := "cobertura.dtd"; DTD_Filename : constant String := Support_Files.In_Lib_Dir (DTD_Basename); - type Pattern_Matcher_Acc is access all GNAT.Regpat.Pattern_Matcher; + type Pattern_Matcher_Acc is access all Pattern_Matcher; + procedure Free is new Ada.Unchecked_Deallocation + (Pattern_Matcher, Pattern_Matcher_Acc); type Cobertura_Pretty_Printer is new Pretty_Printer with record Report_File : File_Type; @@ -53,15 +57,13 @@ package body Annotations.Cobertura is Indentation : Natural := 0; -- Indentation for the next XML items to write - Source_Roots : Pattern_Matcher_Acc; - -- Regexp matching a list of prefixes removed in the filenames output - -- in the report. + Source_Prefix_Pattern : Pattern_Matcher_Acc; + -- Regexp matching a source filename prefix to remove in the report. -- - -- This implements gitlab support, which requires paths that are - -- relative to the project gitlab repository, and not fullnames. The - -- user is supposed to pass one or several source roots through the - -- --source-roots option. - + -- This is needed to support coverage reports in GitLab pipelines, which + -- require filenames to be relative to the root of the tested + -- repository. GNATcoverage users are supposed to pass the root of this + -- repository through the --source-root option. end record; -- Pretty printer type for the Cobertura annotation format @@ -218,36 +220,30 @@ package body Annotations.Cobertura is --------------------- procedure Generate_Report (Context : Coverage.Context_Access) is - use String_Vectors; - Pp : Cobertura_Pretty_Printer := - (Need_Sources => True, - Context => Context, - others => <>); - - Source_Roots : String_Vectors.Vector renames - Args.String_List_Args (Opt_Source_Roots); - Source_Roots_Regexp : Unbounded_String; - Flags : constant Regexp_Flags := - (if GNAT.OS_Lib.Directory_Separator = '\' - then Case_Insensitive - else No_Flags); - -- See Pp.Source_Roots for more documentation + (Need_Sources => True, + Context => Context, + Source_Prefix_Pattern => null, + others => <>); + + -- If --source-root was passed, turn it into the corresponding prefix + -- matcher. Append a directory separator so that "/prefix/basename" + -- always becomes "basename" instead of "/basename" regardless of + -- whether the prefix is "/prefix" or "/prefix/". + Opt : Parser.String_Option renames Args.String_Args (Opt_Source_Root); begin - Append (Source_Roots_Regexp, "(?:"); - for Cur in Source_Roots.Iterate loop - Append (Source_Roots_Regexp, Element (Cur)); - if Cur /= Source_Roots.Last then - Append (Source_Roots_Regexp, "|"); - end if; - end loop; - Append (Source_Roots_Regexp, ")"); - - Pp.Source_Roots := - new Pattern_Matcher' - (Compile (+Source_Roots_Regexp, Flags)); + if Opt.Present then + declare + Prefix : constant String := +Opt.Value & "/"; + begin + Pp.Source_Prefix_Pattern := + new Pattern_Matcher'(Compile (Paths.Glob_To_Regexp (Prefix))); + end; + end if; + Annotations.Generate_Report (Pp, True, Subdir => "cobertura"); + Free (Pp.Source_Prefix_Pattern); end Generate_Report; ------- @@ -416,9 +412,11 @@ package body Annotations.Cobertura is Branches_Valid, Branches_Covered : Natural; Branch_Rate : Rate_Type; - Adjusted_Filename : Unbounded_String := +Info.Full_Name.all; - -- This is the full filename with prefix from --source-roots removed - + Filename : String renames Info.Full_Name.all; + Filename_Start : Positive := Filename'First; + -- Filename, plus the lower bound for what is included in the report. + -- Setting that lower bound is used to implement source prefix + -- stripping: see Cobertura_Pretty_Printer. begin if not Info.Has_Source then Skip := True; @@ -438,18 +436,17 @@ package body Annotations.Cobertura is -- Remove the source root prefix - declare - Match_Res : GNAT.Regpat.Match_Array (0 .. 0); - begin - GNAT.Regpat.Match - (Pp.Source_Roots.all, +Adjusted_Filename, Match_Res); - if Match_Res (0) /= GNAT.Regpat.No_Match then - Adjusted_Filename := Unbounded_Slice - (Adjusted_Filename, - Match_Res (0).Last + 1, - Positive (Length (Adjusted_Filename))); - end if; - end; + if Pp.Source_Prefix_Pattern /= null then + declare + Matches : GNAT.Regpat.Match_Array (0 .. 0); + begin + GNAT.Regpat.Match + (Pp.Source_Prefix_Pattern.all, Filename, Matches); + if Matches (0) /= GNAT.Regpat.No_Match then + Filename_Start := Matches (0).Last + 1; + end if; + end; + end if; Pp.ST ("package", A ("name", Simple_Source_Filename) @@ -459,7 +456,7 @@ package body Annotations.Cobertura is Pp.ST ("classes"); Pp.ST ("class", A ("name", Simple_Source_Filename) - & A ("filename", +Adjusted_Filename) + & A ("filename", Filename (Filename_Start .. Filename'Last)) & A ("line-rate", Img (Line_Rate)) & A ("branch-rate", Img (Branch_Rate)) & A ("complexity", "-1")); diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 992eabeed..1ae276a49 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -120,7 +120,8 @@ package Command_Line is Opt_RTS_Profile, Opt_Path_Count_Limit, Opt_Install_Name, - Opt_Runtime_Project); + Opt_Runtime_Project, + Opt_Source_Root); -- Set of string options we support. More complete descriptions below. type String_List_Options is @@ -144,8 +145,7 @@ package Command_Line is Opt_Restricted_To_Languages, Opt_Annotation_Format, Opt_C_Opts, - Opt_CPP_Opts, - Opt_Source_Roots); + Opt_CPP_Opts); -- Set of string list options we support. More complete descriptions below. package Parser is new Argparse @@ -876,7 +876,17 @@ package Command_Line is & " ""gnatcov_rts"".", Commands => (Cmd_Instrument => True, others => False), At_Most_Once => False, - Internal => False) + Internal => False), + + Opt_Source_Root => Create + (Long_Name => "--source-root", + Pattern => "PATH", + Help => + "Option specific to the Cobertura coverage report: remove the" + & " specified prefix from the filenames in the report.", + Commands => (Cmd_Coverage => True, others => False), + At_Most_Once => True, + Internal => True) ); String_List_Infos : constant String_List_Option_Info_Array := @@ -1099,16 +1109,7 @@ package Command_Line is "List of additional compiler switches to analayze C++ source" & " files.", Commands => (Cmd_Instrument => True, others => False), - Internal => False), - - Opt_Source_Roots => Create - (Long_Name => "--source-roots", - Pattern => "[PATH|LIST]", - Help => - "Option specific to the Cobertura coverage report: remove the" - & " specified prefixes from the filenames in the report", - Commands => (Cmd_Coverage => True, others => False), - Internal => True) + Internal => False) ); procedure Bool_Callback diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index fdaa16aa9..722204b7d 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -179,8 +179,17 @@ package body Paths is I := End_Cur; end if; end; - when '\' => - Append (Res, '/'); + + when '/' | '\' => + + -- De-duplicate directory separators so that "a//b" can match + -- "a/b". + + if Length (Res) = 0 or else Element (Res, Length (Res)) /= '/' + then + Append (Res, '/'); + end if; + when others => Append (Res, Quote ("" & Pat (I))); end case; From dd8fa854ffb9e4700be0f16c743aac3febd56896 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 14 Mar 2023 11:49:09 +0100 Subject: [PATCH 0191/1483] XFAIL test pending resolution of W313-031 --- .../Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt index 00dc3ce12..efc590458 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt @@ -1 +1,2 @@ src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation +ARM-ELF,CARGS_O1 XFAIL instruction debug info attached to wrong sloc, see W313-031 From 0a63f7daaf4c594f853b6ae5d4105bb12f980a3f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 3 Mar 2023 18:00:12 +0100 Subject: [PATCH 0192/1483] trace_name: new test Check that gnatcov produces correct source trace names (matching the executable name), even if the unit name and the filename mismatch, or if the executable name is specified in the project file. --- testsuite/tests/trace_name/main.adb | 6 ++++ testsuite/tests/trace_name/test.py | 50 +++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100644 testsuite/tests/trace_name/main.adb create mode 100644 testsuite/tests/trace_name/test.py diff --git a/testsuite/tests/trace_name/main.adb b/testsuite/tests/trace_name/main.adb new file mode 100644 index 000000000..3072b68a4 --- /dev/null +++ b/testsuite/tests/trace_name/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("Hello world!"); +end Foo; diff --git a/testsuite/tests/trace_name/test.py b/testsuite/tests/trace_name/test.py new file mode 100644 index 000000000..58060cd32 --- /dev/null +++ b/testsuite/tests/trace_name/test.py @@ -0,0 +1,50 @@ +""" +Check that the source trace produced by gnatcov matches the executable name, +and not the unit name. The two can be different when the executable name is +specified in the project file, or when the unit name and the filename are +mismatching. Test both cases. +""" + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +import os + + +def check_srctrace_name(gprsw, main): + build_and_run( + gprsw=gprsw, + covlevel="stmt", + mains=[main], + extra_instr_args=["--dump-filename-simple"], + extra_coverage_args=[], + ) + # Check the name of the trace + if thistest.options.trace_mode == "src": + trace_name = f"{main}.srctrace" + else: + trace_name = f"{main}.trace" + thistest.fail_if(not os.path.exists(trace_name)) + + +# Check when the executable name is left unspecified +tmp = Wdir("tmp_no_exec_attr") +gprsw = GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])) +check_srctrace_name(gprsw, "main") + +# Check when the executable name is specified in the project +tmp.to_subdir("tmp_exec_attr") +gprsw = GPRswitches( + root_project=gprfor( + mains=["main.adb"], + srcdirs=[".."], + extra="""package Builder is + for Executable ("main.adb") use "bar"; + end Builder;""", + ) +) +check_srctrace_name(gprsw, "bar") + +thistest.result() From 7c0b76eb5b0cb0350b47284a040210031b03d54e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 14 Mar 2023 14:12:09 +0000 Subject: [PATCH 0193/1483] paths.adb: minor refactoring Hoist code outside of a seemingly useless declare block. --- tools/gnatcov/paths.adb | 55 +++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index 722204b7d..0d48cf564 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -250,44 +250,41 @@ package body Paths is ------------------------------- function Normalize_Windows_Pattern (Pattern : String) return String is - begin - -- Force lower case and Backslashify, paying attention not to - -- add multiple backslashes in a row. + -- Force lower case and Backslashify, paying attention not to add + -- multiple backslashes in a row. + -- -- Folding to all lower case maximizes the mapping unicity from -- different casing on input, notably useful for path components that -- might be coming from the command line, e.g. as a --source-rebase -- argument. + -- + -- At least for dirsep purposes, we craft the new value incrementally. - declare - -- At least for dirsep purposes, we craft the new value - -- incrementally. + use Ada.Strings.Unbounded; + use Ada.Characters.Handling; + Res : Unbounded_String; - use Ada.Strings.Unbounded; - use Ada.Characters.Handling; - Res : Unbounded_String; + Newchar : Character; + New_Is_Sep : Boolean; + -- The new character we take from Pattern, and whether it + -- is a dir separator. - Newchar : Character; - New_Is_Sep : Boolean; - -- The new character we take from Pattern, and whether it - -- is a dir separator. + Last_Was_Sep : Boolean := False; + -- Whether the last character we added to our result was a dir + -- separator. + begin + for I in Pattern'Range loop + Newchar := (if Pattern (I) = '/' then '\' else Pattern (I)); + New_Is_Sep := Newchar = '\'; + + if not New_Is_Sep or else not Last_Was_Sep then + Append (Res, To_Lower (Newchar)); + Last_Was_Sep := New_Is_Sep; + end if; + end loop; - Last_Was_Sep : Boolean := False; - -- Whether the last character we added to our result was a dir - -- separator. - begin - for I in Pattern'Range loop - Newchar := (if Pattern (I) = '/' then '\' else Pattern (I)); - New_Is_Sep := Newchar = '\'; - - if not New_Is_Sep or else not Last_Was_Sep then - Append (Res, To_Lower (Newchar)); - Last_Was_Sep := New_Is_Sep; - end if; - end loop; - - return To_String (Res); - end; + return To_String (Res); end Normalize_Windows_Pattern; ------------------------------- From 28c037db3bb8ca645c2f77c52b15175d64d6d2d5 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 14 Mar 2023 14:13:02 +0000 Subject: [PATCH 0194/1483] annotations-cobertura.adb: fix --source-root on Windows The pattern that Paths.Glob_To_Regexp returns expects matched filenames to use de-duplicated forward slashes as directory separators exclusively and case folding on Windows. Make sure the corresponding filename normalization is done for the implementation of --source-root. --- tools/gnatcov/annotations-cobertura.adb | 36 ++++++++++++++++++------- tools/gnatcov/paths.adb | 19 +++++++++++++ tools/gnatcov/paths.ads | 6 +++++ 3 files changed, 51 insertions(+), 10 deletions(-) diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb index fe1b26615..a5a850084 100644 --- a/tools/gnatcov/annotations-cobertura.adb +++ b/tools/gnatcov/annotations-cobertura.adb @@ -412,11 +412,9 @@ package body Annotations.Cobertura is Branches_Valid, Branches_Covered : Natural; Branch_Rate : Rate_Type; - Filename : String renames Info.Full_Name.all; - Filename_Start : Positive := Filename'First; - -- Filename, plus the lower bound for what is included in the report. - -- Setting that lower bound is used to implement source prefix - -- stripping: see Cobertura_Pretty_Printer. + Filename : Unbounded_String := To_Unbounded_String (Info.Full_Name.all); + -- Filename to mention in the coverage report. Use the full name, unless + -- we can remove the prefix according to the --source-root option. begin if not Info.Has_Source then Skip := True; @@ -434,16 +432,34 @@ package body Annotations.Cobertura is Branches_Covered, Branch_Rate); - -- Remove the source root prefix + -- Remove the source root prefix (if present) from Filename so that, if + -- Filename designates a source file that is inside the directory + -- referenced by --source-root, Filename is set to a pathname relative + -- to the source root. + -- + -- Note that the pattern matcher in Pp.Source_Prefix_Pattern expects + -- "normalized" filename with: + -- + -- 1) casing folded for case insensitive systems, + -- 2) forward slashes instead of backslashes. + -- + -- So normalize first into Normalized_Filename, then turn Filename into + -- a slice of it. if Pp.Source_Prefix_Pattern /= null then declare - Matches : GNAT.Regpat.Match_Array (0 .. 0); + Matches : GNAT.Regpat.Match_Array (0 .. 0); + First, Last : Natural; + Normalized_Filename : constant String := + Paths.Normalize_For_Regexp (To_String (Filename)); begin GNAT.Regpat.Match - (Pp.Source_Prefix_Pattern.all, Filename, Matches); + (Pp.Source_Prefix_Pattern.all, Normalized_Filename, Matches); if Matches (0) /= GNAT.Regpat.No_Match then - Filename_Start := Matches (0).Last + 1; + First := Matches (0).Last + 1; + Last := Normalized_Filename'Last; + Filename := + To_Unbounded_String (Normalized_Filename (First .. Last)); end if; end; end if; @@ -456,7 +472,7 @@ package body Annotations.Cobertura is Pp.ST ("classes"); Pp.ST ("class", A ("name", Simple_Source_Filename) - & A ("filename", Filename (Filename_Start .. Filename'Last)) + & A ("filename", To_String (Filename)) & A ("line-rate", Img (Line_Rate)) & A ("branch-rate", Img (Branch_Rate)) & A ("complexity", "-1")); diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index 0d48cf564..b25ebaee1 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -198,6 +198,25 @@ package body Paths is return To_String (Res); end Glob_To_Regexp; + -------------------------- + -- Normalize_For_Regexp -- + -------------------------- + + function Normalize_For_Regexp (Filename : String) return String is + begin + return Result : String := Canonicalize_Filename (Filename) do + if On_Windows then + for C of Result loop + if C = '\' then + C := '/'; + else + C := Ada.Characters.Handling.To_Lower (C); + end if; + end loop; + end if; + end return; + end Normalize_For_Regexp; + ---------------------- -- Is_Absolute_Path -- ---------------------- diff --git a/tools/gnatcov/paths.ads b/tools/gnatcov/paths.ads index 0d1acc5b6..a7bc5dc55 100644 --- a/tools/gnatcov/paths.ads +++ b/tools/gnatcov/paths.ads @@ -53,6 +53,12 @@ package Paths is -- Convert the provided globbing Pattern to a regular expression. This -- might be used for file name or unit name patterns. + function Normalize_For_Regexp (Filename : String) return String; + -- Assuming Filename is a full pathname to a file, return a normalized + -- version of it that is suitable to match against patterns created with + -- Glob_To_Regexp: de-duplicated directory separators, backslashes + -- converted to forward slashes, case folded for Windows pathnames. + function Is_Absolute_Path (Path : String) return Boolean; -- Return whether Path is an absolute path. Unlike the GNAT runtime version -- of the service, this one always matches both Windows or Unix file path From fe2a676d7d2b2e58d3a8226105a1df15d6783344 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Fri, 13 Jan 2023 07:58:03 -0800 Subject: [PATCH 0195/1483] Qualif test for unit selection attributes in non root project Our qualification tests for the use of project files to select units of interest had essentially - a set of tests showing proper selection of the projects of interest, from command line switches, - a set of tests showing proper selection of units of interest in a project, from attributes in a project file. The use of attributes in project files was in effect only tested within a root project. This change adds a test to check that the attributes also work within a non root project. Part of T317-055 (qualification material for use of project files) --- .../GPR/InnerAttr/src/ops/ops-andthen.adb | 6 ++ .../GPR/InnerAttr/src/ops/ops-andthen.ads | 3 + .../GPR/InnerAttr/src/ops/ops-orelse.adb | 6 ++ .../GPR/InnerAttr/src/ops/ops-orelse.ads | 3 + .../GPR/InnerAttr/src/ops/ops.adb | 13 +++++ .../GPR/InnerAttr/src/ops/ops.ads | 5 ++ .../GPR/InnerAttr/src/test_and_tf.adb | 19 ++++++ .../GPR/InnerAttr/src/test_and_tt.adb | 19 ++++++ .../GPR/InnerAttr/src/test_or_ft.adb | 19 ++++++ .../UnitsOfInterest/GPR/InnerAttr/tc.rst | 21 +++++++ .../UnitsOfInterest/GPR/InnerAttr/test.py | 58 +++++++++++++++++++ 11 files changed, 172 insertions(+) create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.adb create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.ads create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.adb create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.ads create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.adb create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.ads create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tf.adb create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tt.adb create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_or_ft.adb create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/tc.rst create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.adb new file mode 100644 index 000000000..0910aec41 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.adb @@ -0,0 +1,6 @@ +package body Ops.Andthen is + function Eval (A, B : Boolean) return Boolean is + begin + return A and then B; -- # eval + end; +end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.ads b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.ads new file mode 100644 index 000000000..e947bdf97 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-andthen.ads @@ -0,0 +1,3 @@ +package Ops.Andthen is + function Eval (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.adb new file mode 100644 index 000000000..8c4df1b7e --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.adb @@ -0,0 +1,6 @@ +package body Ops.Orelse is + function Eval (A, B : Boolean) return Boolean is + begin + return A or else B; -- # eval + end; +end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.ads b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.ads new file mode 100644 index 000000000..0720cc3c6 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops-orelse.ads @@ -0,0 +1,3 @@ +package Ops.Orelse is + function Eval (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.adb new file mode 100644 index 000000000..51f3391b5 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.adb @@ -0,0 +1,13 @@ +with Ops.Andthen; with Ops.Orelse; + +package body Ops is + + function Eval (Op: Opkind; A, B : Boolean) return Boolean is + begin + case Op is + when Op_Andthen => return Ops.Andthen.Eval (A, B); -- # eval_and + when Op_Orelse => return Ops.Orelse.Eval (A, B); -- # eval_or + end case; + end; + +end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.ads b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.ads new file mode 100644 index 000000000..7d4925214 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/ops/ops.ads @@ -0,0 +1,5 @@ +package Ops is + type Opkind is (Op_Andthen, Op_Orelse); + + function Eval (Op: Opkind; A, B : Boolean) return Boolean; +end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tf.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tf.adb new file mode 100644 index 000000000..03dd99082 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tf.adb @@ -0,0 +1,19 @@ + +with Support, Ops; use Ops, Support; + +procedure Test_And_TF is +begin + Assert (Ops.Eval (Op_Andthen, True, False) = False); +end; + +--# ops/ops.adb +-- /eval_and/ l+ ## 0 +-- /eval_or/ l- ## s- + +--# ops/ops-andthen.adb +-- /eval/ l! ## eT- + +--# ops/ops-orelse.adb +-- /eval/ l- ## s- + + diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tt.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tt.adb new file mode 100644 index 000000000..1a34e4a17 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tt.adb @@ -0,0 +1,19 @@ + +with Support, Ops; use Ops, Support; + +procedure Test_And_TT is +begin + Assert (Ops.Eval (Op_Andthen, True, True) = True); +end; + +--# ops/ops.adb +-- /eval_and/ l+ ## 0 +-- /eval_or/ l- ## s- + +--# ops/ops-andthen.adb +-- /eval/ l! ## eF- + +--# ops/ops-orelse.adb +-- /eval/ l- ## s- + + diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_or_ft.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_or_ft.adb new file mode 100644 index 000000000..59cba22eb --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_or_ft.adb @@ -0,0 +1,19 @@ + +with Support, Ops; use Ops, Support; + +procedure Test_Or_FT is +begin + Assert (Ops.Eval (Op_Orelse, False, True) = True); +end; + +--# ops/ops.adb +-- /eval_and/ l- ## s- +-- /eval_or/ l+ ## 0 + +--# ops/ops-andthen.adb +-- /eval/ l- ## s- + +--# ops/ops-orelse.adb +-- /eval/ l! ## eF- + + diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/tc.rst b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/tc.rst new file mode 100644 index 000000000..8c4defe4d --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/tc.rst @@ -0,0 +1,21 @@ +**Check unit selection attributes in a non-root project** + +From a test dir where we have + + src/ops/ops.ad? + ops-andthen.ad? + ops-orelse.ad? + /test_*.adb + +Verify that the proper set of units is examined for +a variety of subtests for which we + +- Create an ops.gpr project with attributes to include + or exclude some of the units in src/ops, + +- Launch a testcase which will create it's own working dir and + it's own root project there, for which we setup an empty set of + units of interest. + +Check the selection of units in ops.gpr with a lone Units attribute, a +lone Excluded_Units attribute or a mix of the two. diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py new file mode 100644 index 000000000..24738dd58 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py @@ -0,0 +1,58 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest +from SUITE.cutils import Wdir, list_to_file +from SUITE.tutils import gprfor +from SUITE.gprutils import gprcov_for + +wd = Wdir() + + +def check(subdir, opspkg, xreports): + + wd.to_subdir(subdir) + + ops_gpr = gprfor( + mains=[], prjid="ops", srcdirs="../src/ops", extra=opspkg + ) + + TestCase(category=None).run(covcontrol=CovControl( + deps=["../ops.gpr"], units_in=[], xreports = xreports + )) + +# ops.gpr: no attribute + +check( + opspkg="", + xreports=["ops.adb", "ops.ads", "ops-andthen.adb", "ops-orelse.adb"], + subdir="wd_1", +) + +# ops.gpr: for Units use ... + +check( + opspkg=gprcov_for(units_in=["ops.andthen"]), + xreports=["ops-andthen.adb"], + subdir="wd_2", +) + +# ops.gpr: for Excluded_Units use ... + +check( + opspkg=gprcov_for(units_out=["ops.andthen"]), + xreports=["ops.ads", "ops.adb", "ops-orelse.adb"], + subdir="wd_3", +) + +# ops.gpr: for Included_Units use ... for Excluded_Units use ... + +check( + opspkg=gprcov_for( + units_in=["ops", "ops.orelse", "ops.andthen"], + units_out=["ops.orelse"]), + xreports=["ops.ads", "ops.adb", "ops-andthen.adb"], + subdir="wd_3", +) + + +thistest.result() From 1c8a6bdd26b2550f04e5c35a4c6bfd19f98b3c21 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Fri, 13 Jan 2023 09:55:37 -0800 Subject: [PATCH 0196/1483] Test use of glob patterns for unit names in gpr or external files The requirements advertise support for the use of globbing patterns when selecting units of interest. This adds a couple of tests to verify that this indeed works. Part of T317-055 (qualification material for use of project files) --- .../GPR/ByAttr/GlobInList/tc.rst | 1 + .../GPR/ByAttr/GlobInList/test.py | 14 +++++++++++ .../GPR/ByAttr/GlobUnits/tc.rst | 1 + .../GPR/ByAttr/GlobUnits/test.py | 25 +++++++++++++++++++ .../UnitsOfInterest/GPR/InnerAttr/test.py | 2 +- 5 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/tc.rst create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/tc.rst create mode 100644 testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/tc.rst b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/tc.rst new file mode 100644 index 000000000..f794510eb --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/tc.rst @@ -0,0 +1 @@ +**Check use of globbing patterns for unit names in external unit lists** diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py new file mode 100644 index 000000000..b4f7c1a05 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py @@ -0,0 +1,14 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest +from SUITE.cutils import Wdir, list_to_file + +wd = Wdir() + +wd.to_subdir("wd_1") +TestCase(category=None).run(covcontrol=CovControl( + ulist_in="../" + list_to_file(["ops*"]), + units_out=['ops.orelse'], + xreports=["ops.ads", "ops.adb", "ops-andthen.adb"])) + +thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/tc.rst b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/tc.rst new file mode 100644 index 000000000..4ef7e27be --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/tc.rst @@ -0,0 +1 @@ +**Check use of globbing patterns for unit names in Coverage attributes** diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py new file mode 100644 index 000000000..9c2c55968 --- /dev/null +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py @@ -0,0 +1,25 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest +from SUITE.cutils import Wdir + + +wd = Wdir() + +wd.to_subdir('wd_1') +TestCase(category=None).run(covcontrol=CovControl( + units_in=['ops*'], + xreports=['ops.ads', 'ops.adb', 'ops-andthen.adb', 'ops-orelse.adb'])) + +wd.to_subdir('wd_2') +TestCase(category=None).run(covcontrol=CovControl( + units_out=['test*', 'support'], + xreports=['ops.ads', 'ops.adb', 'ops-andthen.adb', 'ops-orelse.adb'])) + +wd.to_subdir('wd_3') +TestCase(category=None).run(covcontrol=CovControl( + units_in=['ops*'], + units_out=['ops.andthen'], + xreports=['ops.ads', 'ops.adb', 'ops-orelse.adb'])) + +thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py index 24738dd58..fa3040cb6 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py @@ -44,7 +44,7 @@ def check(subdir, opspkg, xreports): subdir="wd_3", ) -# ops.gpr: for Included_Units use ... for Excluded_Units use ... +# ops.gpr: for Units use ... for Excluded_Units use ... check( opspkg=gprcov_for( From 94e488f88da202264731248fa511c522bae5dd01 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 14 Mar 2023 14:46:07 +0000 Subject: [PATCH 0197/1483] instrument.adb: always instrument sources in the same order When instrumenting a unit, sort the source files to instrument before iterating on them so that the order for instrumentation is deterministic. This is useful both to avoid spurious variations in tests, and to reduce the chance that we reproduce bugs in one configuration, but not on another. TN: W213-002 --- tools/gnatcov/instrument.adb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index b8b2fa0e4..e674e7936 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -68,6 +68,11 @@ package body Instrument is Ignored : Boolean; end record; + function "<" (Left, Right : CU_Name_With_Ignore) return Boolean + is (if Left.Name = Right.Name + then Left.Ignored < Right.Ignored + else Left.Name < Right.Name); + package CU_Name_Vectors is new Ada.Containers.Vectors (Positive, CU_Name_With_Ignore); @@ -528,13 +533,17 @@ package body Instrument is for Cur in LU_Map.Iterate loop -- Instrument compilation units (only the ones this library unit - -- owns). + -- owns). Sort them first, so that the instrumentation order is + -- deterministic. declare + package Sorting is new CU_Name_Vectors.Generic_Sorting; + LU_Info : constant Library_Unit_Info_Access := Library_Unit_Maps.Element (Cur); All_Externally_Built : Boolean := True; begin + Sorting.Sort (LU_Info.CU_Names); for CU of LU_Info.CU_Names loop if CU.Ignored then declare From 5ee1801772fc052919107e4c312ec8ddc016fa00 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 13 Mar 2023 13:30:22 +0000 Subject: [PATCH 0198/1483] Instrument: mention instrumented file when warning about missing source TN: W213-002 --- .../tests/instr-cov/file-context/main.adb | 9 +++ .../tests/instr-cov/file-context/pkg.ads | 2 + .../tests/instr-cov/file-context/test.py | 68 +++++++++++++++++++ testsuite/tests/instr-cov/orphan-unit/test.py | 7 +- tools/gnatcov/instrument-common.adb | 53 ++++----------- tools/gnatcov/instrument-common.ads | 34 ++++++++-- tools/gnatcov/instrument.adb | 38 ++++++++--- 7 files changed, 157 insertions(+), 54 deletions(-) create mode 100644 testsuite/tests/instr-cov/file-context/main.adb create mode 100644 testsuite/tests/instr-cov/file-context/pkg.ads create mode 100644 testsuite/tests/instr-cov/file-context/test.py diff --git a/testsuite/tests/instr-cov/file-context/main.adb b/testsuite/tests/instr-cov/file-context/main.adb new file mode 100644 index 000000000..48c2672b7 --- /dev/null +++ b/testsuite/tests/instr-cov/file-context/main.adb @@ -0,0 +1,9 @@ +with Pkg; + +with Missing_A; +with Missing_B; + +procedure Main is +begin + Put_Line ("Hello world"); +end Main; diff --git a/testsuite/tests/instr-cov/file-context/pkg.ads b/testsuite/tests/instr-cov/file-context/pkg.ads new file mode 100644 index 000000000..2db1f1de6 --- /dev/null +++ b/testsuite/tests/instr-cov/file-context/pkg.ads @@ -0,0 +1,2 @@ +package Pkg is +end Pkg; diff --git a/testsuite/tests/instr-cov/file-context/test.py b/testsuite/tests/instr-cov/file-context/test.py new file mode 100644 index 000000000..dff6fbf0e --- /dev/null +++ b/testsuite/tests/instr-cov/file-context/test.py @@ -0,0 +1,68 @@ +""" +Check that "gnatcov instrument" mentions the source file it is currently +instrumented when it is supposed to: once per source file that triggers an +error/warning, and once for every file in verbose mode. +""" + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SUITE.cutils import contents_of, lines_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + + +Wdir("tmp_") + +# Create the object direcotry to avoid spurious notices +gprsw = GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])) +mkdir("obj") + + +def do_instr(label, args): + thistest.log(f"== {label} ==") + output_file = f"{label}.txt" + p = xcov_instrument( + gprsw=gprsw, + covlevel="stmt", + extra_args=args, + out=output_file, + register_failure=False, + ) + thistest.fail_if( + p.status != 0, f'{label}: "gnatcov instrument" unexpected failure' + ) + return output_file + +# Check that we print the source file that is currently instrumented when +# warnings/errors occur at most once, and never for other files. +log = do_instr("basic", []) +thistest.fail_if_not_equal( + f'"gnatcov instrument" output', + contents_of(log).strip(), + "\n".join([ + "warning: While instrumenting main.adb...", + "warning: Cannot find required source file: missing_a.ads", + "warning: Cannot find required source file: missing_b.ads", + ]), +) + +# In verbose mode: always print it once. +log = do_instr("verbose", ["-v"]) +actual_lines = [ + line + for line in lines_of(log) + if line.startswith("Instrumenting ") or line.startswith("warning: ") +] +thistest.fail_if_not_equal( + f'"gnatcov instrument" output', + "\n".join(actual_lines), + "\n".join([ + "Instrumenting main.adb", + "warning: Cannot find required source file: missing_a.ads", + "warning: Cannot find required source file: missing_b.ads", + "Instrumenting pkg.ads", + ]), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/orphan-unit/test.py b/testsuite/tests/instr-cov/orphan-unit/test.py index 430a24fd9..60d3db495 100644 --- a/testsuite/tests/instr-cov/orphan-unit/test.py +++ b/testsuite/tests/instr-cov/orphan-unit/test.py @@ -19,14 +19,17 @@ gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), covlevel="stmt", mains=["main"], - tolerate_instrument_messages="Cannot find required source file", + tolerate_instrument_messages=".", extra_coverage_args=["--annotate=xcov"], ) if thistest.options.trace_mode == "src": thistest.fail_if_not_equal( '"gnatcov instrument" output', - "warning: Cannot find required source file: pkg.ads", + ( + "warning: While instrumenting pkg-child.adb...\n" + "warning: Cannot find required source file: pkg.ads" + ), contents_of("instrument.log").strip(), ) diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 62f77b5db..d5589f756 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -28,7 +28,6 @@ with Interfaces; with GNAT.OS_Lib; with Langkit_Support.Symbols; -with Langkit_Support.Text; with Libadalang.Common; with Libadalang.Config_Pragmas; with Libadalang.Sources; @@ -54,28 +53,6 @@ package body Instrument.Common is (Rewriter : Source_Rewriter); -- Remove all Warnings/Style_Checks pragmas in Rewriter's unit - type Missing_Src_Reporter is new Libadalang.Analysis.Event_Handler_Interface - with record - Reported_Files : String_Sets.Set; - -- Set of source file names which were already reported as missing. - -- Libadalang does not guarantee that the Unit_Requested event is - -- triggered only once per source, so de-duplicate events with this set. - end record; - -- Implementation of the Libadalang event handler interface used in - -- Create_Missing_File_Reporter. - - overriding procedure Release (Self : in out Missing_Src_Reporter) is null; - - overriding procedure Unit_Requested_Callback - (Self : in out Missing_Src_Reporter; - Context : Libadalang.Analysis.Analysis_Context'Class; - Name : Langkit_Support.Text.Text_Type; - From : Libadalang.Analysis.Analysis_Unit'Class; - Found : Boolean; - Is_Not_Found_Error : Boolean); - -- If the requested unit is not found and that is an error, warn about it. - -- Make sure we warn only once about a given source file. - procedure Create_LAL_Context (IC : in out Inst_Context); -- Create a new Libadalang analysis context for IC, assigning it to -- IC.Context. @@ -750,24 +727,24 @@ package body Instrument.Common is N : constant Unbounded_String := To_Unbounded_String (Ada.Directories.Simple_Name (Langkit_Support.Text.Image (Name))); begin - if not Self.Reported_Files.Contains (N) then - Self.Reported_Files.Include (N); - Warn ("Cannot find required source file: " & To_String (N)); + if Self.Reported_Files.Contains (N) then + return; end if; - end; - end Unit_Requested_Callback; - ---------------------------------- - -- Create_Missing_File_Reporter -- - ---------------------------------- + -- If we have not done it yet, clarify which file we were + -- instrumenting when we noticed that the source file N was missing. - function Create_Missing_File_Reporter - return Libadalang.Analysis.Event_Handler_Reference - is - begin - return Create_Event_Handler_Reference - (Missing_Src_Reporter'(others => <>)); - end Create_Missing_File_Reporter; + if Length (Self.Instrumented_File) > 0 then + Warn ("While instrumenting " + & To_String (Self.Instrumented_File) + & "..."); + Self.Instrumented_File := Null_Unbounded_String; + end if; + + Self.Reported_Files.Include (N); + Warn ("Cannot find required source file: " & To_String (N)); + end; + end Unit_Requested_Callback; -------------- -- Next_Bit -- diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 6d5e5fe40..7c289d11c 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -61,6 +61,7 @@ with Ada.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; with GNATCOLL.Projects; use GNATCOLL.Projects; with GNATCOLL.VFS; +with Langkit_Support.Text; with Libadalang.Analysis; use Libadalang.Analysis; with Libadalang.Rewriting; use Libadalang.Rewriting; @@ -368,11 +369,34 @@ package Instrument.Common is -- this could mean that instrumentation breaks the build. When written at -- the very beginning of each written source, these pragmas avoid this. - function Create_Missing_File_Reporter - return Libadalang.Analysis.Event_Handler_Reference; - -- Create an event handler to warn about source files that Libadalang needs - -- to perform semantic analysis (so mandated by Ada), but which are not - -- available. + type Missing_Src_Reporter is new Libadalang.Analysis.Event_Handler_Interface + with record + Instrumented_File : Unbounded_String; + -- Base name for the file that is currently instrumented. Reset to the + -- empty string everytime we print the "While instrumenting XXX ..." + -- message, so that we print it at most once per instrumented file. + + Reported_Files : String_Sets.Set; + -- Set of source file names which were already reported as missing. + -- Libadalang does not guarantee that the Unit_Requested event is + -- triggered only once per source, so de-duplicate events with this set. + end record; + -- Implementation of the Libadalang event handler interface used in + -- Create_Missing_File_Reporter. + + type Missing_Src_Reporter_Access is access all Missing_Src_Reporter; + + overriding procedure Release (Self : in out Missing_Src_Reporter) is null; + + overriding procedure Unit_Requested_Callback + (Self : in out Missing_Src_Reporter; + Context : Libadalang.Analysis.Analysis_Context'Class; + Name : Langkit_Support.Text.Text_Type; + From : Libadalang.Analysis.Analysis_Unit'Class; + Found : Boolean; + Is_Not_Found_Error : Boolean); + -- If the requested unit is not found and that is an error, warn about it. + -- Make sure we warn only once about a given source file. ------------------------- -- Source instrumenter -- diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index e674e7936..0acb792f2 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -25,6 +25,7 @@ with Ada.Directories; with Ada.Exceptions; with Ada.Strings.Fixed; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Deallocation; with GNAT.OS_Lib; @@ -319,12 +320,6 @@ package body Instrument is Provider : constant Unit_Provider_Reference := Instrument.Ada_Unit_Provider.Create_Provider_From_Project; - -- Create the event handler, to report when Libadalang cannot read a - -- required source file. - - Event_Handler : constant Event_Handler_Reference := - Create_Missing_File_Reporter; - -- Create a map from library units to lists of compilation units to -- instrument for them. @@ -346,11 +341,15 @@ package body Instrument is IC : Inst_Context := Create_Context (Provider, - Event_Handler, + Create_Event_Handler_Reference (Missing_Src_Reporter'(others => <>)), Dump_Config, Language_Version, Ignored_Source_Files); + Event_Handler : Missing_Src_Reporter renames + Missing_Src_Reporter_Access (IC.Event_Handler.Unchecked_Get).all; + -- Handle to the event handler we use to report missing source files + Root_Project_Info : constant Project_Info_Access := Get_Or_Create_Project_Info (IC, Project.Project.Root_Project); @@ -568,14 +567,35 @@ package body Instrument is declare Unit_Info : Instrumented_Unit_Info renames IC.Instrumented_Units.Element (CU.Name).all; - Filename : constant String := To_String - (Unit_Info.Filename); + Filename : constant String := + To_String (Unit_Info.Filename); + Basename : constant String := + Ada.Directories.Simple_Name (Filename); begin -- Do not process units from externally built projects if not Unit_Info.Prj_Info.Externally_Built then + + -- Keep a note that we are processing at least one + -- source file from a non-externally built project. + All_Externally_Built := False; + -- In verbose mode, always print a notice for the + -- source file that we are about to instrument. In + -- non-verbose mode, just get prepared to print it in + -- case we emit a "source file missing" warning + -- through Libadalang's event handler. + + if Verbose then + Put_Line ("Instrumenting " & Basename); + else + Event_Handler.Instrumented_File := + To_Unbounded_String (Basename); + end if; + + -- Run the instrumentation for this file + Instrumenters (Unit_Info.Language).Instrument_Unit (CU.Name, IC, Unit_Info); From 83792f99a1e203ad58ae37d6c58780f369478f4d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 13 Mar 2023 18:17:49 +0100 Subject: [PATCH 0199/1483] pre-commit hook: add .cpp and .hh file extension --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 959f2a690..af4cb852d 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,7 +4,7 @@ repos: hooks: - id: clang-format types: [file] - files: \.(cc|c|h)$ + files: \.(cc|c|h|cpp|hh)$ args: ["--style={ BasedOnStyle: gnu, ContinuationIndentWidth: 2, From b07012f1009ee1c895192846578304255a394f57 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 9 Mar 2023 17:37:07 +0100 Subject: [PATCH 0200/1483] Fix instrumentation of projects mixing C / C++ The list of coverage buffers is stored in a compilation unit unique to the project, but for each language of the project. In practice, this meant that we had a gnatcov_rts_c-buffers-lists-.c file (for C), and a gnatcov_rts_c-buffers-lists-.cpp file (for C++), both having the same object name which was rejected by the builder. As the list of coverage buffers is the same, there is no need to generate a declaration for each language. We now generate this list for one of the language supported, and then reuse the exported symbol when dumping coverage buffers. --- testsuite/tests/24_mixed_c_c++/pkg.c | 5 ++++ testsuite/tests/24_mixed_c_c++/test.cpp | 8 ++++++ testsuite/tests/24_mixed_c_c++/test.opt | 1 + testsuite/tests/24_mixed_c_c++/test.py | 31 +++++++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 9 +++++++ tools/gnatcov/instrument-c.adb | 30 +++++++++------------- tools/gnatcov/instrument-common.ads | 15 +++++++++++ tools/gnatcov/instrument.adb | 33 ++++++++++++++++--------- 8 files changed, 102 insertions(+), 30 deletions(-) create mode 100644 testsuite/tests/24_mixed_c_c++/pkg.c create mode 100644 testsuite/tests/24_mixed_c_c++/test.cpp create mode 100644 testsuite/tests/24_mixed_c_c++/test.opt create mode 100644 testsuite/tests/24_mixed_c_c++/test.py diff --git a/testsuite/tests/24_mixed_c_c++/pkg.c b/testsuite/tests/24_mixed_c_c++/pkg.c new file mode 100644 index 000000000..5d74411a2 --- /dev/null +++ b/testsuite/tests/24_mixed_c_c++/pkg.c @@ -0,0 +1,5 @@ +int +id (int x) +{ + return x; +} diff --git a/testsuite/tests/24_mixed_c_c++/test.cpp b/testsuite/tests/24_mixed_c_c++/test.cpp new file mode 100644 index 000000000..548d53dba --- /dev/null +++ b/testsuite/tests/24_mixed_c_c++/test.cpp @@ -0,0 +1,8 @@ +extern "C" int id (int x); + +int +main () +{ + int a = id (1); + return 0; +} diff --git a/testsuite/tests/24_mixed_c_c++/test.opt b/testsuite/tests/24_mixed_c_c++/test.opt new file mode 100644 index 000000000..195e6c2d4 --- /dev/null +++ b/testsuite/tests/24_mixed_c_c++/test.opt @@ -0,0 +1 @@ +!C++ DEAD test requires C++ compiler diff --git a/testsuite/tests/24_mixed_c_c++/test.py b/testsuite/tests/24_mixed_c_c++/test.py new file mode 100644 index 000000000..9a4f7c42a --- /dev/null +++ b/testsuite/tests/24_mixed_c_c++/test.py @@ -0,0 +1,31 @@ +""" +Check that the instrumentation of a project mixing C and C++ works. It used to +produce files with the same object name, resulting in an error at build time. +""" + + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], + mains=["test.cpp"])), + covlevel="stmt", + mains=["test"], + extra_coverage_args=["--annotate=xcov"], +) + +check_xcov_reports( + "*.xcov", + { + "test.cpp.xcov": {"+": {6, 7}}, + "pkg.c.xcov": {"+": {4}}, + }, + "obj", +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 287be2a95..271391357 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -18,6 +18,7 @@ with Ada.Characters.Conversions; use Ada.Characters.Conversions; with Ada.Characters.Handling; +with Ada.Containers; use Ada.Containers; with Ada.Exceptions; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Wide_Wide_Fixed; @@ -7625,6 +7626,14 @@ package body Instrument.Ada_Unit is end if; end; end loop; + File.Put_Line (" C_List : constant GNATcov_RTS.Buffers.Lists" + & ".GNATcov_RTS_Coverage_Buffers_Group_Array :="); + File.Put_Line (" (" & Instr_Units.Length'Image + & " , List'Address);"); + + File.Put_Line + (" pragma Export (C, C_List, """ + & Unit_Buffers_Array_Name (+IC.Project_Name) & """);"); File.New_Line; File.Put_Line ("end " & Unit_Name & ";"); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index d9b66afd9..76ed677cb 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -378,17 +378,6 @@ package body Instrument.C is -- Source instrumentation -- ---------------------------- - function Unit_Buffers_Array_Name (IC : Inst_Context) return String is - ("gnatcov_rts_buffers_array_" & (+IC.Project_Name)); - -- Name of the symbol that references the - -- gnatcov_rts_coverage_buffers_array struct (defined for the whole - -- project). This struct is an array containing the coverage buffers of all - -- of the instrumented units. - -- - -- We need this to be unique per root project instrumented, as gnatcov - -- gives the possibility to link two separately-instrumented libraries in - -- the same executable. - function Buffers_List_Filename (IC : Inst_Context) return String is ("gnatcov_rts_c-buffers-lists-" & (+IC.Project_Name)); -- Return the name of the unit containing the array of coverage buffers @@ -3936,10 +3925,14 @@ package body Instrument.C is & "gnatcov_rts_c-traces-output-base64.h"""); end case; File.Put_Line ("#include "); - File.Put_Line - ("#include """ & Buffers_List_Filename (IC) - & Source_Suffix (Instrumenter, GPR.Unit_Spec, Info.Project) - & """"); + + -- Import the coverage buffers + + Put_Extern_Decl + (File, + Instrumenter, + "const struct gnatcov_rts_coverage_buffers_group_array", + Unit_Buffers_Array_Name (+IC.Project_Name)); -- Emit the procedure to write the trace file @@ -3948,7 +3941,8 @@ package body Instrument.C is File.Put_Line ("void " & Dump_Procedure & " (void) {"); File.Put_Line (Indent1 & Output_Proc & " ("); - File.Put_Line (Indent2 & "&" & Unit_Buffers_Array_Name (IC) & ","); + File.Put_Line + (Indent2 & "&" & Unit_Buffers_Array_Name (+IC.Project_Name) & ","); case IC.Dump_Config.Channel is when Binary_File => declare @@ -4370,7 +4364,7 @@ package body Instrument.C is declare Buffer_Array_Decl : constant String := "const struct gnatcov_rts_coverage_buffers_group_array " - & Unit_Buffers_Array_Name (IC); + & Unit_Buffers_Array_Name (+IC.Project_Name); Buffer_Unit_Length : constant String := Count_Type'Image (Instr_Units.Length); begin @@ -4422,7 +4416,7 @@ package body Instrument.C is (File_Header, Self, "const struct gnatcov_rts_coverage_buffers_group_array", - Unit_Buffers_Array_Name (IC)); + Unit_Buffers_Array_Name (+IC.Project_Name)); end Emit_Buffers_List_Unit; --------------------- diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 7c289d11c..6364648fb 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -151,6 +151,16 @@ package Instrument.Common is -- Name of the symbol that references the -- gnatcov_rts_coverage_buffers_group struct for this unit. + function Unit_Buffers_Array_Name (Prj_Name : String) return String is + ("gnatcov_rts_buffers_array_" & Prj_Name); + -- Name of the symbol that designates the + -- gnatcov_rts_coverage_buffers_array struct, which contains an array of + -- coverage buffers for all instrumented units in this project. + -- + -- We need this to be unique per root project instrumented, as gnatcov + -- gives the possibility to link two separately-instrumented libraries in + -- the same executable. + function Project_Output_Dir (Project : Project_Type) return String; -- Return the directory in which we must create instrumented sources for -- Project. This returns an empty string for projects that do not have an @@ -675,6 +685,11 @@ package Instrument.Common is Root_Project_Info : in out Project_Info) is abstract; -- Emit in the root project a unit (in Self's language) to contain the list -- of coverage buffers for all units of interest. + -- + -- The variable holding the list of coverage buffers is exported to a + -- unique C symbol whose name is defined by the Unit_Buffers_Array_Name + -- function. This procedure should thus be called only once, for one of + -- the supported languages of the project. private diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 0acb792f2..4f07a81d5 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -676,24 +676,33 @@ package body Instrument is Outputs.Fatal_Error ("No unit to instrument."); end if; - for Language in Src_Supported_Language loop - - -- Emit units to contain the list of coverage buffers, one per - -- language present in the root project. - -- - -- If the project contains both Ada and C sources, this will create - -- two arrays of coverage buffers. TODO??? we could have one array - -- defined in C and have the Ada unit just import it. + -- Emit the unit to contain the list of coverage buffers, exported to a + -- C symbol, in one of the language supported by the project. + -- + -- Note that this has an implicit hack to it: if Ada is a language of + -- the project, it will pick it over the others (as it is the first + -- enumeration member of the Src_Supported_Language type). This matters + -- as we make the assumption in the Emit_Dump_Helper_Unit implementation + -- in instrument-ada_unit.adb (when instrumenting for an Ada main) that + -- the Ada package for buffers list units always exists: we need to + -- include it in the main closure, as it puts buffer units in scope + -- by importing them (otherwise they aren't as they are used through + -- C symbol importations). - if Project.Project.Root_Project.Has_Language (Image (Language)) then + for Language in Src_Supported_Language loop + if Project.Project.Root_Project.Has_Language (Image (Language)) + then Instrumenters (Language).Emit_Buffers_List_Unit (IC, Root_Project_Info.all); + exit; end if; + end loop; - -- Instrument all the mains that are not unit of interest to add the - -- dump of coverage buffers: Instrument_Unit already took care of - -- mains that are units of interest. + -- Instrument all the mains that are not unit of interest to add the + -- dump of coverage buffers: Instrument_Unit already took care of mains + -- that are units of interest. + for Language in Src_Supported_Language loop for Main of Mains_To_Instrument (Language) loop Instrumenters (Language).Auto_Dump_Buffers_In_Main (IC, Main.CU_Name, +Main.File.Full_Name, Main.Prj_Info.all); From 727c584e69ec77478122acc17691895f20256d6b Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 16 Mar 2023 10:03:53 +0100 Subject: [PATCH 0201/1483] Fix typos --- testsuite/SUITE/tutils.py | 4 ++-- tools/gnatcov/decision_map.adb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 841e74631..a420dabdf 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -17,7 +17,7 @@ from e3.os.process import DEVNULL, Run -# Expose a few other items as a test util-facilities as well +# Expose a few other items as a test util facilities as well from SUITE import control from SUITE.control import (BUILDER, KNOWN_LANGUAGES, env, language_info, @@ -25,7 +25,7 @@ from SUITE.context import ROOT_DIR, thistest -# Then mind our own buisness +# Then mind our own business from SUITE.cutils import FatalError, contents_of, text_to_file, to_list diff --git a/tools/gnatcov/decision_map.adb b/tools/gnatcov/decision_map.adb index b41498d80..04f6eb8a9 100644 --- a/tools/gnatcov/decision_map.adb +++ b/tools/gnatcov/decision_map.adb @@ -2463,7 +2463,7 @@ package body Decision_Map is -- Machine properties for this conditional branch BB_From : Pc_Type; - -- Fisrt PC of the basic block that contain this instruction + -- First PC of the basic block that contains this instruction end record; package Pending_Cond_Branch_Vectors is new Ada.Containers.Vectors From 355f024fa34152285da017f95b420648070d6bde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 28 Feb 2023 16:05:06 +0100 Subject: [PATCH 0202/1483] Qualif: Add first tool qualified interface for src traces This change introduces differentiated versions of the tool qualified interface and operationnal environment chapters to have one variant per trace kind, as well as some utilities in the qualification document building scripts to account for this. Part of W215-023 (gnatcov 22.2 qualification) --- qualification/genbundle.py | 71 +++++++++++- .../{content.rst => content_bin.rst} | 0 .../Qualified_Interface/content_src.rst | 106 ++++++++++++++++++ .../Environment/additional_switches_bin.rst | 0 .../Environment/additional_switches_src.rst | 5 + .../Environment/{content.rst => content.tmpl} | 13 +-- .../Qualif/Environment/env_table_bin.rst | 11 ++ .../Qualif/Environment/env_table_src.rst | 12 ++ testsuite/STR/genrest.py | 74 +++++++++++- 9 files changed, 276 insertions(+), 16 deletions(-) rename qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/{content.rst => content_bin.rst} (100%) create mode 100644 qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst create mode 100644 testsuite/Qualif/Environment/additional_switches_bin.rst create mode 100644 testsuite/Qualif/Environment/additional_switches_src.rst rename testsuite/Qualif/Environment/{content.rst => content.tmpl} (91%) create mode 100644 testsuite/Qualif/Environment/env_table_bin.rst create mode 100644 testsuite/Qualif/Environment/env_table_src.rst diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 68d06fba0..7caac139f 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -363,6 +363,42 @@ def __init__(self, options): self.passno = 0 + + def process_imports(self, dir): + """ + Process the template file in dir, replacing the occurrences of + <%name%> in the text by the contents of name_.rst, + according to the qualification parameters + """ + def replace_one(p): + return contents_of( + os.path.join(dir,p.group(1) + f"_{self.o.trace_mode}.rst") + ) + + + template_content = contents_of(os.path.join (dir,"content.tmpl")) + with open(os.path.join(dir, "content.rst"), "w") as f: + f.write(re.sub( + pattern=r"<%([^%]+)%>", + repl=replace_one, + string=template_content + )) + + # --------------------- + # -- prepare_content -- + # --------------------- + + def prepare_content(self, dirs): + """ + Prepare the content files by choosing the correct content_*.rst file + according to the qualification parameters. + """ + for dir in dirs: + cp( + os.path.join(dir, f"content_{self.o.trace_mode}.rst"), + os.path.join(dir, f"content.rst"), + ) + # -------------------- # -- setup_workdir -- # -------------------- @@ -610,6 +646,8 @@ def sync(tr): print ("ERRRR !! inexistant target dir for %s" % tr) [sync(tr) for tr in find (root=".", pattern="tc.dump")] + env_chapter_dir = os.path.join(self.repodir, "testsuite", "Qualif", "Environment") + self.process_imports(env_chapter_dir) self.__qm_build (part="tor") @@ -849,6 +887,15 @@ def build_str (self): # ----------------- def build_plans (self): + plans_root = os.path.join(self.repodir, "qualification", "qm", "plans") + trace_specific_content = [ + os.path.join( + plans_root, + "Tool_Qualification_Plan", + "Qualified_Interface" + ) + ] + self.prepare_content(trace_specific_content) self.__qm_build (part="plans") # --------------- @@ -981,11 +1028,12 @@ def build_as_needed (self, docformat): # == MAIN SCRIPT BODY == # ======================================================================= -valid_docformats = ('html', 'pdf') -valid_parts = ('tor', 'plans', 'str') -valid_dolevels = ('doA', 'doB', 'doC') -valid_xada = ('95', '2005', '2012') -valid_languages = ["Ada%s" % version for version in valid_xada] +valid_docformats = ('html', 'pdf') +valid_parts = ('tor', 'plans', 'str') +valid_dolevels = ('doA', 'doB', 'doC') +valid_xada = ('95', '2005', '2012') +valid_languages = ["Ada%s" % version for version in valid_xada] +valid_trace_modes = ("src", "bin") def commandline(): """Build and return an OptionParser instance for this script.""" @@ -1100,6 +1148,14 @@ def commandline(): ) ) + op.add_option ( + "--trace-mode", + dest="trace_mode", + default=None, + choices=valid_trace_modes, + help="Trace kind we are qualifying gnatcov for. One of 'src' or 'bin'" + ) + return op def check_valid(options, args): @@ -1112,6 +1168,11 @@ def check_valid(options, args): "Please specify an explicit dolevel (--dolevel)." ) + exit_if ( + not options.trace_mode, + "Please specify an explicit trace-mode (--trace-mode)." + ) + # Generating docs can be pretty long. Better make sure the output format # was intentionally stated: diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_bin.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst rename to qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_bin.rst diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst b/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst new file mode 100644 index 000000000..6ceb67e22 --- /dev/null +++ b/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst @@ -0,0 +1,106 @@ +.. _qualified-interface: + +GNATcoverage Qualified Interface +================================ + +To obtain reports suitable for use as certification evidence, applicants shall +use GNATcoverage as follows: + +* Build and install the coverage runtime in a dedicated + directory. Use the GNAT Pro toolchain identified in the + *Operational Environment* section of the |tor_doc| document for this, + taking care to specify the and if the application is + not a native one. + + This would be achieved with a command such as: + + .. code-block:: text + + gnatcov setup [--target= --RTS=] --prefix= + + + This step needs only to be done once, provided that the *Operational + Environment* described in the |tor_doc| document has not changed as of + the previous coverage runtime setup. + + +* Instrument the application for coverage assessment and test harness main + units for coverage buffer dumping using the ``gnatcov instrument`` command; + Specify the coverage criterion level to be assessed as well as a trace + and as specified in the + *Operational Environment* section of the |tor_doc| document. Also specify the + set of units of interest for which coverage should be assessed trough + the arguments, which should at least include a + indication using the :literal:`-P` switch: + + .. code-block:: text + + gnatcov instrument [--target= --RTS=] --level= --dump-trigger= --dump-channel= -P + + +* Build the application and test executables with the GNAT Pro toolchain + identified in the *Operational Environment* section of the |tor_doc| document, + obeying the coding standard rules, and compilation switches documented there + as well. The gprbuild invocation to build the application shall contain the + ``--src-subdirs=gnatcov-instr`` argument on the command line, as well as a + ``--implicit-with=gnatcov_rts.gpr`` argument to link against the coverage + runtime. The coverage runtime project must be made available to gprbuild by + adding ``/share/gpr`` to the ``GPR_PROJECT_PATH`` environment + variable. + + +* Obtain as many execution trace files () as needed, by + running the test executables. + +* Optionally, produce a single file (format documented in the + GNATcoverage User's Guide), consolidating the coverage outcome for the list of + execution traces, produced in the previous step and stored in the + file, and querying results for the source units designated by + the argument: + + .. code-block:: text + + gnatcov coverage --annotate=report --level= -P @ -o + + +In the sample commands above: + +* designates the path to a directory in which the coverage + runtime will be installed. It shall be accessible for writing and reading by + the tool; +* identifies the trigger to produce execution traces, as + described in the tool User's Manual, and for which the value to be used + is defined in the |tor_doc| document; +* identifies the medium used by the instrumented executable to + output the execution traces, as described in the tool User's Manual and for + which the value to be used is defined in the |tor_doc| document; +* designates the coverage criteria to assess, depending on the software + level; + + * For level C, statement coverage data is obtained with :literal:`--level=stmt`; + + * For level B, statement *and* decision coverage data is obtained with + :literal:`--level=stmt+decision`; + + * For level A, statement *and* decision *and* mcdc coverage data is obtained + with :literal:`--level=stmt+mcdc`. + +* is the output file containing the GNATcoverage report; +* identifies the target platform (as in the GNAT Pro toolchain + prefixes, e.g. arm-elf); +* identifies the Ada runtime library to be used, (either a GNAT Pro + provided runtime, identified by its name, e.g. embedded-stm32f4, or the path + to a custom runtime project); +* is the name of an output file containing an execution trace; +* is the path to the GPR project file defining the main units for + the application testing; +* is a specification of the units for which coverage is to be + assessed (so called *Units Of Interest*), with GPR project file facilities, + as documented in the tool User's Guide and summarized in the |tor_doc| + document; + +* is a text file containing the list of execution traces to + operate on. + +IO redirections, sometimes necessary for proper operation of the programs +within the execution environment, are allowed. diff --git a/testsuite/Qualif/Environment/additional_switches_bin.rst b/testsuite/Qualif/Environment/additional_switches_bin.rst new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/Qualif/Environment/additional_switches_src.rst b/testsuite/Qualif/Environment/additional_switches_src.rst new file mode 100644 index 000000000..92a2e016a --- /dev/null +++ b/testsuite/Qualif/Environment/additional_switches_src.rst @@ -0,0 +1,5 @@ +The indications for the GNATcov dump trigger and GNATcov dump channel switch +values represent the retained values for the corresponding switches, required +as part of the :literal:`gnatcov instrument` command, in accordance to the +restrictions imposed by the GNATPro runtime library profile and execution host +capabilities defined above, as described in the tool's User Manual. \ No newline at end of file diff --git a/testsuite/Qualif/Environment/content.rst b/testsuite/Qualif/Environment/content.tmpl similarity index 91% rename from testsuite/Qualif/Environment/content.rst rename to testsuite/Qualif/Environment/content.tmpl index 6ec9e1c5c..46ef4333d 100644 --- a/testsuite/Qualif/Environment/content.rst +++ b/testsuite/Qualif/Environment/content.tmpl @@ -22,16 +22,7 @@ matching process. .. tabularcolumns:: |p{0.06\textwidth}|p{0.30\textwidth}|p{0.60\textwidth}| -.. csv-table:: - :header: "Item #", "Description", "Expected value" - :widths: 5, 30, 60 - :delim: | - - e1 | Host Operating System name and version | Linux Redhat 7 - e2 | GNATcoverage executable name and version | GNATcoverage 19.3 (20200318) - e3 | GNAT Pro compiler executable name and version | gcc (GCC) 7.3.1 20180924 (for GNAT Pro 19lts 20200331) [i686-pc-linux-gnu] - s1 | GNAT Pro compilation switches | -g -fpreserve-control-flow -fdump-scos -gnat12 - s2 | GNAT Pro Runtime Library Profile | No --RTS switch expected. Programs shall honor the :ref:`language-scope` restrictions, nevertheless. +<%env_table%> For the GNAT Pro compilation switches, additional options which do not influence code generation are allowed. This may, for example, include options @@ -46,6 +37,8 @@ delivered with the GNAT Pro toolchain. Tool Users shall have their toolchain setup to compile programs with a :literal:`--RTS` switch as well, designating a runtime with a ``system.ads`` identical to the qualification one. +<%additional_switches%> + Installation, Documentation and Qualified Interface --------------------------------------------------- diff --git a/testsuite/Qualif/Environment/env_table_bin.rst b/testsuite/Qualif/Environment/env_table_bin.rst new file mode 100644 index 000000000..acf3069dd --- /dev/null +++ b/testsuite/Qualif/Environment/env_table_bin.rst @@ -0,0 +1,11 @@ +.. csv-table:: + :header: "Item #", "Description", "Expected value" + :widths: 5, 30, 60 + :delim: | + + e1 | Host Operating System name and version | Linux Redhat 7 + e2 | GNATcoverage executable name and version | GNATcoverage 19.3 (20200318) + e3 | GNAT Pro compiler executable name and version | gcc (GCC) 7.3.1 20180924 (for GNAT Pro 19lts 20200331) [i686-pc-linux-gnu] + s1 | GNAT Pro compilation switches | -g -fpreserve-control-flow -fdump-scos -gnat12 + s2 | GNAT Pro Runtime Library Profile | No --RTS switch expected. Programs + shall honor the :ref:`language-scope` restrictions, nevertheless. diff --git a/testsuite/Qualif/Environment/env_table_src.rst b/testsuite/Qualif/Environment/env_table_src.rst new file mode 100644 index 000000000..f97d0497f --- /dev/null +++ b/testsuite/Qualif/Environment/env_table_src.rst @@ -0,0 +1,12 @@ +.. csv-table:: + :header: "Item #", "Description", "Expected value" + :widths: 5, 30, 60 + :delim: | + + e1 | Host Operating System name and version | Linux Redhat 7 + e2 | GNATcoverage executable name and version | GNATcoverage 19.3 (20200318) + e3 | GNAT Pro compiler executable name and version | gcc (GCC) 7.3.1 20180924 (for GNAT Pro 19lts 20200331) [i686-pc-linux-gnu] + s1 | GNAT Pro compilation switches | -gnat12 + s2 | GNAT Pro Runtime Library Profile | No --RTS switch expected. Programs shall honor the :ref:`language-scope` restrictions, nevertheless. + s3 | GNATcov dump trigger switch value | :literal:`--dump-triger=atexit` + s4 | GNATcov dump channel switch value | :literal:`--dump-channel=bin-file` diff --git a/testsuite/STR/genrest.py b/testsuite/STR/genrest.py index f8d11e269..e94872fd0 100644 --- a/testsuite/STR/genrest.py +++ b/testsuite/STR/genrest.py @@ -25,6 +25,8 @@ os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(LOCAL_TESTSUITE_DIR) +TEST_LOG = "test.py.log" + from SUITE.qdata import qdaf_in, stdf_in from SUITE.qdata import STATUSDATA_FILE, QLANGUAGES, QROOTDIR from SUITE.qdata import CTXDATA_FILE, Qdata @@ -36,7 +38,7 @@ r0, r0c, xBlock0, sNoCov, sPartCov, dtNoCov, dfNoCov, dPartCov, dNoCov, etNoCov, efNoCov, ePartCov, eNoCov, cPartCov, xBlock1) -from SUITE.cutils import FatalError +from SUITE.cutils import FatalError, lines_of from REST import rest # ============================= @@ -775,6 +777,16 @@ def __init__(self, options): self.languages = set( [cat.lang for cat in lang_categories if cat.qdl]) + self.dump_trigger=None + self.dump_channel=None + + # Gather effectively used dump-trigger and dump channel from the logs + # in source trace mode. + + if self.suitedata["options"]["trace_mode"] == "src": + self.dump_trigger, self.dump_channel = \ + self.gather_trigger_and_channel() + self.gen_envinfo(sepfile="env.rst") # Then compute the tables and summaries of test status counters @@ -790,6 +802,53 @@ def __init__(self, options): # self.gen_index(sepfiles=["env.rst", "tctables.rst", "tssummary.rst"]) + def _check_one_dump_option(self, line, option_name, current_value): + """ + Helper for gather_trigger_and_channel, inspect a line to determine + if it contains a "gnatcov instrument" command line, look for a + "--dump-{option_name}" and check its value against current_value. + In case of inconsistency, or if the option is not found, raises + FatalError + """ + if "gnatcov instrument" in line: + matcher = re.search( + pattern=f"--dump-{option_name}" + r"(?:=| )(\S*) ", + string=line + ) + if matcher is None: + raise FatalError ( + comment=f"Found no dump {option_name} in gnatcov" + f"instrument command line: {line}" + ) + if current_value and matcher.group(1) != current_value: + raise FatalError ( + comment=f"Inconsistent dump {option_name} found:" + f" got {matcher.group(1)}" + f" but expected {current_value}" + ) + return matcher.group(1) + else: + return current_value + + + def gather_trigger_and_channel(self): + """ + Inspect all test.py.log files to determine which dump trigger and + dump channel switches were passed to gnatcov. Raises a FatalError if + one of the "gnatcov instrument" invocation is missing one of the two + arguments, or if we detect inconsistent values across tests. + """ + current_dt = None + current_dc = None + for p in find (self.o.testsuite_dir, TEST_LOG): + for line in lines_of(p): + current_dt = self._check_one_dump_option( + line, "trigger", current_dt) + current_dc = self._check_one_dump_option( + line, "channel", current_dc) + return (current_dt, current_dc) + + def categorize(self, qda): for cat in self.categories: if cat.trymatch(qda): @@ -1182,6 +1241,19 @@ def switches_with_eq_from(switches_string): ("--RTS=%s" % rts)) if rts else rest.emph("no --RTS switch")}) + if self.dump_trigger: + csv_contents.append( + {itemno: "s3", + item: "GNATcov dump trigger option value", + value: literal (f"--dump-trigger={self.dump_trigger}") + }) + if self.dump_channel: + csv_contents.append( + {itemno: "s4", + item: "GNATcov dump channel option value", + value: literal(f"--dump-channel={self.dump_channel}") + }) + CSVtable( title=None, text=None, columns=(itemno, item, value), From e1a28d3d562b555fcfa78a79d43768af99c54d87 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 17 Mar 2023 11:05:46 +0100 Subject: [PATCH 0203/1483] trace_name: fix test --- testsuite/tests/trace_name/test.opt | 1 + testsuite/tests/trace_name/test.py | 6 ++++-- 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/trace_name/test.opt diff --git a/testsuite/tests/trace_name/test.opt b/testsuite/tests/trace_name/test.opt new file mode 100644 index 000000000..b07d3aea8 --- /dev/null +++ b/testsuite/tests/trace_name/test.opt @@ -0,0 +1 @@ +!native,src-traces DEAD Check default trace file name (dump-channel=bin-file) diff --git a/testsuite/tests/trace_name/test.py b/testsuite/tests/trace_name/test.py index 58060cd32..9b3e4c7d8 100644 --- a/testsuite/tests/trace_name/test.py +++ b/testsuite/tests/trace_name/test.py @@ -6,6 +6,7 @@ """ from SCOV.minicheck import build_and_run +from SUITE.control import env from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import thistest, gprfor @@ -22,10 +23,11 @@ def check_srctrace_name(gprsw, main): extra_coverage_args=[], ) # Check the name of the trace + main_ext = ".exe" if env.build.os.name == "windows" else "" if thistest.options.trace_mode == "src": - trace_name = f"{main}.srctrace" + trace_name = f"{main}{main_ext}.srctrace" else: - trace_name = f"{main}.trace" + trace_name = f"{main}{main_ext}.trace" thistest.fail_if(not os.path.exists(trace_name)) From 3b1efb1f59a432d64dafc697f56b7b5b6400780e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 17 Mar 2023 08:43:02 +0000 Subject: [PATCH 0204/1483] trace_adapters: use parallelism for gprbuild-based Makefiles --- tools/gnatcov/trace_adapters/nexus/Makefile | 4 +++- tools/gnatcov/trace_adapters/trace32/Makefile | 3 ++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/trace_adapters/nexus/Makefile b/tools/gnatcov/trace_adapters/nexus/Makefile index a4cd19e03..817f5a55d 100644 --- a/tools/gnatcov/trace_adapters/nexus/Makefile +++ b/tools/gnatcov/trace_adapters/nexus/Makefile @@ -1,5 +1,6 @@ GPRBUILD=gprbuild PREFIX=install +PARALLEL_BUILD=0 include ../../host.mk @@ -25,7 +26,8 @@ DOCFORMATS=pdf html all: $(EXENAMES) $(EXENAMES): force - $(GPRBUILD) -p -Pnexus -XARCH=$(ARCH) $(EXTRA_ADAFLAGS) $@ + $(GPRBUILD) -p -j$(PARALLEL_BUILD) \ + -Pnexus -XARCH=$(ARCH) $(EXTRA_ADAFLAGS) $@ ################### diff --git a/tools/gnatcov/trace_adapters/trace32/Makefile b/tools/gnatcov/trace_adapters/trace32/Makefile index 74ed3d542..991779a62 100644 --- a/tools/gnatcov/trace_adapters/trace32/Makefile +++ b/tools/gnatcov/trace_adapters/trace32/Makefile @@ -1,6 +1,7 @@ GPRBUILD=gprbuild GPRCLEAN=gprclean PREFIX=install +PARALLEL_BUILD=0 include ../../host.mk @@ -28,7 +29,7 @@ all: bin # to minimize the executable sizes. BIN_COMMON_BUILD_ARGS=\ - -Ptrace32.gpr \ + -Ptrace32.gpr -p -j$(PARALLEL_BUILD) \ -XBINUTILS_SRC_DIR="$(BINUTILS_SRC_DIR)" \ -XBINUTILS_BUILD_DIR="$(BINUTILS_BUILD_DIR)" \ -XINSTRUMENT_SUPPORT=False \ From 378d1faba7beb0f947608551e2113f1a867a4249 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 17 Mar 2023 09:10:51 +0000 Subject: [PATCH 0205/1483] trace_adapters/trace32/.gitignore: add object dirs and new executables --- tools/gnatcov/trace_adapters/trace32/.gitignore | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/trace_adapters/trace32/.gitignore b/tools/gnatcov/trace_adapters/trace32/.gitignore index c6d738599..6f71706b1 100644 --- a/tools/gnatcov/trace_adapters/trace32/.gitignore +++ b/tools/gnatcov/trace_adapters/trace32/.gitignore @@ -1,2 +1,6 @@ -trace32_drv -trace32_drv.exe +trace32_drv_32 +trace32_drv_32.exe +trace32_drv_64 +trace32_drv_64.exe +obj32 +obj64 From 956eb416e8d111472d04753cf136ccde1d67447c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 17 Mar 2023 08:47:00 +0000 Subject: [PATCH 0206/1483] gnatcov.gpr: rework settings to configure what to build This commit pushes further the work initiated on W105-035 for build settings in gnatcov.gpr. It creates a new external (PART) and removes others (BITS and INSTRUMENT_SUPPORT) to clearly separate the control of what to build ("gnatcov" driver? gnatcov32? gnatcov64? gnatcov-as-a-lib? choice happens in Makefiles) from source selection (use stub for instrumentation.adb? choice happens in gnatcov.gpr). This change also fixes issues with incremental builds (some units were always rebuilt even without source changes): introducing more object directories allows builds of alternative units to create output in different directories. --- .gitignore | 3 +- tools/gnatcov/Makefile | 15 +- tools/gnatcov/gnatcov.gpr | 165 +++++++++++++----- tools/gnatcov/trace_adapters/nexus/Makefile | 4 +- tools/gnatcov/trace_adapters/trace32/Makefile | 9 +- .../trace_adapters/trace32/trace32.gpr | 7 +- 6 files changed, 135 insertions(+), 68 deletions(-) diff --git a/.gitignore b/.gitignore index c6aed1b83..1ddf255c3 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ lib /tools/gnatcov/obj32/ /tools/gnatcov/obj64/ /tools/gnatcov/obj-gnatcov_rts/ +/tools/gnatcov/objlib64/ /tools/gnatcov/examples/support/lib /tools/gnatcov/examples/support/obj /tools/gnatcov/rts-instr @@ -26,4 +27,4 @@ gnatcov-loc.xml gnatinspect.db README.html TAGS -*.~undo-tree~ \ No newline at end of file +*.~undo-tree~ diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index 0fa67a902..5d0c497eb 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -74,7 +74,7 @@ GPRINSTALL=gprinstall # Binary program name PGMNAME=gnatcov -PGMPATH=obj64/$(BUILD_MODE)/$(PGMNAME) +PGMPATH=obj32/$(BUILD_MODE)/$(PGMNAME) PGM32PATH=obj32/$(BUILD_MODE)/gnatcov32 PGM64PATH=obj64/$(BUILD_MODE)/gnatcov64 @@ -197,6 +197,7 @@ BIN_COMMON_BUILD_ARGS=\ -XBUILD_MODE=$(BUILD_MODE) \ -XBINUTILS_SRC_DIR="$(BINUTILS_SRC_DIR)" \ -XBINUTILS_BUILD_DIR="$(BINUTILS_BUILD_DIR)" \ + -XC_SUPPORT=$(C_SUPPORT) \ $(EXTRA_ADAFLAGS) \ -largs $(LD_FLAGS) \ -cargs:c++ $(CXXFLAGS) \ @@ -213,15 +214,9 @@ bin: fi # Start with the 64-bit gnatcov, which has the largest closure - $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) \ - gnatcov_bits_specific.adb \ - -XARCH=64 -XINSTRUMENT_SUPPORT=True -XC_SUPPORT=$(C_SUPPORT) - $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) \ - gnatcov_bits_specific.adb \ - -XARCH=32 -XINSTRUMENT_SUPPORT=False - $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) \ - gnatcov.adb \ - -XINSTRUMENT_SUPPORT=False + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov32 + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver ADAPTER_TARGETS=$(foreach a, $(ADAPTERS_LIST), adapter-$(a)) .PHONY: $(ADAPTERS_TARGETS) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index dccb2cec6..cd444a77b 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -4,45 +4,93 @@ with "rts/gnatcov_rts"; project Gnatcov is - -- This project file participates in the build of a variety of programs - -- that use all or part-of the sources in the project's subdirectory. Such - -- progrms include the "gnatcov" driver, the "gnatcov32/64" tools or the - -- trace adapters. - - -- We provide scenario variables to control some aspects of what the - -- sources include, such as whether the tool is intended to process 32 or - -- 64 binaries or whether it needs to include a fully functional source - -- instrumenter. The control of what parameter makes sense for each actual - -- program is not decided by this project file, and when this project file - -- is used as a root project to build gnatcov* executables, build commands - -- are expected to state the Mains on the on the command line along - -- with the associated parameters. - - -- The size of addresses we expect the tool we build will handle. For - -- gnatcov* programs, this also controls the subdir where the executable - -- is placed. Default to "64" as we build 64bit binaries only. Only those - -- that explicitly request to handle 32bit addresses will end up in the - -- 32bit specific object dir. + type Boolean is ("False", "True"); - type Bits_Type is ("32", "64"); - Bits : Bits_Type := external("ARCH", "64"); + -- This project file is used: + -- + -- * As the root project when building the "gnatcov" driver program or the + -- gnatcov32/gnatcov64 internal programs. + -- + -- * As a subproject when building the trace adapters implemented on top of + -- some gnatcov units (for instance, trace32). + -- + -- The following externals ("scenario variables") allows to instruct + -- gprbuild which subset of sources to build: which program ("gnatcov" + -- driver, ...) and with what optional feature (C instrumentation support). + -- This project file also use them to derive various build settings: "main" + -- sources, object directory to use, ... + + ------------------------- + -- Mandatory externals -- + ------------------------- + + type Part_Type is ("lib32", "lib64", "driver", "gnatcov32", "gnatcov64"); + Part : Part_Type := external ("PART"); + -- Which program this project should build: + -- + -- * "lib32/lib64": gnatcov.gpr is used as a subproject, the main is a + -- trace adapter for 32-bit binary traces (lib32) or 64-bit ones (lib64). + -- + -- * "driver": the user-facing "gnatcov" program, whose job is to run + -- gnatcov32 or gnatcov64. + -- + -- * "gnatcov32": the homonym program, for everything that needs to deal + -- with binary traces of 32-bit programs. + -- + -- * "gnatcov64": the homonym program, for everything else. Binutils_Src_Dir := external ("BINUTILS_SRC_DIR"); Binutils_Build_Dir := external ("BINUTILS_BUILD_DIR", Binutils_Src_Dir); - - -- Build mode. Default to "dev" to make it shorter for developers. - -- The other modes are for nightly scripts and are better made explicit - -- anyway: + -- Directories that contain the source tree for binutils, and its build + -- tree, if different (in the case of out-of-tree builds). + + ------------------------ + -- Optional externals -- + ------------------------ + + C_Support : Boolean := external ("C_SUPPORT", "True"); + -- Whether to include support source instrumentation for C + -- + -- Enabling this is useful for gnatcov64 only (at it is the only program + -- that is supposed to run the C/C++ instrumenter): it will create link + -- issue in some other configurations (because of the need for Clang link + -- options), and will just create bloat in others (link of Clang code that + -- is dead code in practice): force it to "False" in all but the + -- "gnatcov64" configuration. + + case Part is + when "gnatcov64" => null; + when others => C_Support := "False"; + end case; type Build_Mode_Type is ("dev", "prod", "boot"); - Build_Mode : Build_Mode_Type := external("BUILD_MODE", "dev"); + Build_Mode : Build_Mode_Type := external ("BUILD_MODE", "dev"); + -- Build mode. Default to "dev" to make it shorter for developers. The + -- other modes are for nightly scripts and are better made explicit anyway. + + -------------------------------------- + -- Settings computed from externals -- + -------------------------------------- + + -- The size of addresses we expect the tool we build will handle. Used to + -- select source variants implementing 32-bit or 64-bit types, constants + -- and subprograms. + -- + -- Note that we build the "gnatcov" driver in 32-bit mode as an + -- optimization: unlike "gnatcov64", none of "lib32", "gnatcov32" and + -- "driver" need source instrumentation support, so they all use the same + -- sources, and can thus share the same object directory. - -- Whether the tool we build needs to include source instrumentation - -- support at all, then for C more specifically: + type Bits_Type is ("32", "64"); + Bits : Bits_Type := "32"; + case Part is + when "lib64" | "gnatcov64" => Bits := "64"; + when "driver" | "lib32" | "gnatcov32" => Bits := "32"; + end case; - type Boolean is ("False", "True"); - Instrument_Support : Boolean := external("INSTRUMENT_SUPPORT", "True"); - C_Support : Boolean := external("C_SUPPORT", Instrument_Support); + ------------------------------------------- + -- Selection of alternative source files -- + ------------------------------------------- package Naming is for Specification ("Arch") use "arch__" & Bits & ".ads"; @@ -55,10 +103,10 @@ project Gnatcov is -- used. Provide a stub body for such tools, which significantly -- reduces the size of executables: - case Instrument_Support is - when "False" => + case Part is + when "lib32" | "lib64" | "driver" | "gnatcov32" => for Body ("Instrument") use "instrument__stub.adb"; - when "True" => + when "gnatcov64" => null; end case; @@ -73,10 +121,28 @@ project Gnatcov is for Body_Suffix ("C++") use ".cc"; end Naming; + ---------------------------- + -- Configuration of mains -- + ---------------------------- + + case Part is + when "lib32" | "lib64" => + for Main use (); + when "driver" => + for Main use ("gnatcov.adb"); + when "gnatcov32" | "gnatcov64" => + for Main use ("gnatcov_bits_specific.adb"); + end case; + package Builder is - for Executable ("gnatcov_bits_specific.adb") use "gnatcov" & Bits; + for Executable ("gnatcov_bits_specific.adb") use Part; + for Executable ("gnatcov.adb") use "gnatcov"; end Builder; + ----------------------- + -- Toolchain options -- + ----------------------- + package Compiler is Ada_Common_Switches := @@ -141,10 +207,8 @@ project Gnatcov is package Binder is case Build_Mode is - when "dev" => - for Default_Switches ("Ada") use ("-Es"); - when others => - null; + when "dev" => for Default_Switches ("Ada") use ("-Es"); + when others => null; end case; end Binder; @@ -153,15 +217,28 @@ project Gnatcov is for VCS_Repository_Root use "../.."; end IDE; + ------------------------------------------- + -- Configuration of sources/object files -- + ------------------------------------------- + for Source_Dirs use (".", "libopcodes_bind"); case C_Support is - when "False" => - for Excluded_Source_Files use ("clang-wrapper.cc"); - when others => - null; + when "False" => for Excluded_Source_Files use ("clang-wrapper.cc"); + when "True" => null; + end case; + + Object_Dir := ""; + case Part is + when "driver" | "lib32" | "gnatcov32" => Object_Dir := "obj32"; + when "gnatcov64" => Object_Dir := "obj64"; + + -- gnatcov64 uses the real instrumenter.adb while lib64 uses the stub + -- one, so they cannot use the same object directory. + + when "lib64" => Object_Dir := "objlib64"; end case; + for Object_Dir use Object_Dir & "/" & Build_Mode; - for Object_Dir use "obj" & Bits & "/" & Build_Mode; for Languages use ("Ada", "C", "C++"); end Gnatcov; diff --git a/tools/gnatcov/trace_adapters/nexus/Makefile b/tools/gnatcov/trace_adapters/nexus/Makefile index 817f5a55d..180b7e3fc 100644 --- a/tools/gnatcov/trace_adapters/nexus/Makefile +++ b/tools/gnatcov/trace_adapters/nexus/Makefile @@ -6,8 +6,6 @@ include ../../host.mk .PHONY: force -ARCH=32 - # Files for libexec/gnatcoverage include binary executables # (which need to be built first), and a python script. @@ -27,7 +25,7 @@ all: $(EXENAMES) $(EXENAMES): force $(GPRBUILD) -p -j$(PARALLEL_BUILD) \ - -Pnexus -XARCH=$(ARCH) $(EXTRA_ADAFLAGS) $@ + -Pnexus -XPART=lib32 $(EXTRA_ADAFLAGS) $@ ################### diff --git a/tools/gnatcov/trace_adapters/trace32/Makefile b/tools/gnatcov/trace_adapters/trace32/Makefile index 991779a62..e7da42db3 100644 --- a/tools/gnatcov/trace_adapters/trace32/Makefile +++ b/tools/gnatcov/trace_adapters/trace32/Makefile @@ -32,15 +32,14 @@ BIN_COMMON_BUILD_ARGS=\ -Ptrace32.gpr -p -j$(PARALLEL_BUILD) \ -XBINUTILS_SRC_DIR="$(BINUTILS_SRC_DIR)" \ -XBINUTILS_BUILD_DIR="$(BINUTILS_BUILD_DIR)" \ - -XINSTRUMENT_SUPPORT=False \ -largs $(LD_FLAGS) \ -cargs:c++ $(CXXFLAGS) \ $(EXTRA_ADAFLAGS) \ -gargs bin: force - $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XARCH=64 - $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XARCH=32 + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=lib64 + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=lib32 ################### # General cleanup # @@ -49,8 +48,8 @@ bin: force .PHONY: clean clean: - $(GPRCLEAN) -Ptrace32.gpr -XARCH=64 - $(GPRCLEAN) -Ptrace32.gpr -XARCH=32 + $(GPRCLEAN) -Ptrace32.gpr -XPART=lib64 + $(GPRCLEAN) -Ptrace32.gpr -XPART=lib32 ################ # Installation # diff --git a/tools/gnatcov/trace_adapters/trace32/trace32.gpr b/tools/gnatcov/trace_adapters/trace32/trace32.gpr index ad2bc8ea7..34d184e4f 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace32.gpr +++ b/tools/gnatcov/trace_adapters/trace32/trace32.gpr @@ -2,11 +2,8 @@ with "../../gnatcov"; project Trace32 is - type Bits_Type is ("32", "64"); - Bits : Bits_Type := external("ARCH", "32"); - for Main use ("trace32_drv.adb"); - for Object_Dir use "obj" & Bits; + for Object_Dir use "obj" & Gnatcov.Bits; for Exec_Dir Use "."; for Create_Missing_Dirs use "True"; @@ -19,7 +16,7 @@ project Trace32 is end Linker; package Builder is - for Executable ("trace32_drv.adb") use "trace32_drv_" & Bits; + for Executable ("trace32_drv.adb") use "trace32_drv_" & Gnatcov.Bits; end Builder; end Trace32; From 4413821725ceb577c1e2ce3f29e07c039c45fe99 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 20 Mar 2023 10:21:14 +0100 Subject: [PATCH 0207/1483] Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0: extend XFAIL Extend XFAIL coverage to all configurations where this test actually fails currently. TN: W313-031 --- .../Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt index efc590458..d0da1f5ef 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt @@ -1,2 +1,3 @@ src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation -ARM-ELF,CARGS_O1 XFAIL instruction debug info attached to wrong sloc, see W313-031 +arm-elf,CARGS_O1 XFAIL W313-031: instruction debug info attached to wrong sloc +ppc-elf,CARGS_O1 XFAIL W313-031: instruction debug info attached to wrong sloc From ceeb6485e80df32ff2938fa4abfee6b2870df044 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 20 Mar 2023 10:26:49 +0100 Subject: [PATCH 0208/1483] tests/trace_name: fix formatting and add an error message --- testsuite/tests/trace_name/test.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/trace_name/test.py b/testsuite/tests/trace_name/test.py index 9b3e4c7d8..abdb11de1 100644 --- a/testsuite/tests/trace_name/test.py +++ b/testsuite/tests/trace_name/test.py @@ -23,12 +23,15 @@ def check_srctrace_name(gprsw, main): extra_coverage_args=[], ) # Check the name of the trace - main_ext = ".exe" if env.build.os.name == "windows" else "" + main_ext = ".exe" if env.build.os.name == "windows" else "" if thistest.options.trace_mode == "src": trace_name = f"{main}{main_ext}.srctrace" else: trace_name = f"{main}{main_ext}.trace" - thistest.fail_if(not os.path.exists(trace_name)) + thistest.fail_if( + not os.path.exists(trace_name), + f"Could not find {trace_name}", + ) # Check when the executable name is left unspecified From 1ce480dc89bc9dc1a096864525c2b4bc54b5c2d8 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 20 Mar 2023 10:28:42 +0100 Subject: [PATCH 0209/1483] tests/trace_name: fix trace name computation for cross platforms The ".exe" prefix is expected only for native Windows configurations: programs compiled by cross toolchains hosted on Windows do not have it. --- testsuite/tests/trace_name/test.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/testsuite/tests/trace_name/test.py b/testsuite/tests/trace_name/test.py index abdb11de1..f56e6aacc 100644 --- a/testsuite/tests/trace_name/test.py +++ b/testsuite/tests/trace_name/test.py @@ -23,11 +23,10 @@ def check_srctrace_name(gprsw, main): extra_coverage_args=[], ) # Check the name of the trace - main_ext = ".exe" if env.build.os.name == "windows" else "" - if thistest.options.trace_mode == "src": - trace_name = f"{main}{main_ext}.srctrace" - else: - trace_name = f"{main}{main_ext}.trace" + trace_ext = ( + ".srctrace" if thistest.options.trace_mode == "src" else ".trace" + ) + trace_name = f"{main}{env.target.os.exeext}{trace_ext}" thistest.fail_if( not os.path.exists(trace_name), f"Could not find {trace_name}", From 9cb984f00d0ecabefe27f0ae73797ae645282994 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 20 Feb 2023 16:47:57 +0100 Subject: [PATCH 0210/1483] Instrument: remove occurrences of Inst_Context in unit instr process This is preliminary work for the parallelized instrumentation. We want to isolate the most we can the instrumentation of a single source. The Inst_Context is shared between all of the source instrumentations, and holds global information which holds us against being able to instrument a single compilation unit at a time. This commit removes the uses of the Inst_Context in the unit instrumentation process (in Instrument.Ada_Unit and Instrument.C). In practice, this means no behavior change. Note that this Inst_Context was used in the Ada instrumentation process to actually check that the parent unit of a separate unit is instrumented. As assertions are deactivated in production mode, we make the controversial choice to drop it. Note that we also use this as an opportunity to actually isolate the libadalang dependency to Instrument.Ada_Unit, as the Inst_Context is no longer the one holding the Libadalang.Analysis_Context, but the Ada_Unit_Inst_Context is. --- .../1_Core/Operands/QuantExpr/src/test_c6.adb | 2 +- .../DynObjects/src/test_vectors_0.adb | 2 +- tools/gnatcov/instrument-ada_unit.adb | 1022 ++++++++++++----- tools/gnatcov/instrument-ada_unit.ads | 64 +- tools/gnatcov/instrument-c.adb | 303 ++--- tools/gnatcov/instrument-c.ads | 20 +- tools/gnatcov/instrument-c__stub.adb | 19 +- tools/gnatcov/instrument-c__stub.ads | 21 +- tools/gnatcov/instrument-common.adb | 392 +------ tools/gnatcov/instrument-common.ads | 187 +-- tools/gnatcov/instrument-find_ada_units.adb | 148 --- tools/gnatcov/instrument-find_ada_units.ads | 34 - tools/gnatcov/instrument.adb | 149 +-- tools/gnatcov/instrument.ads | 1 + 14 files changed, 1087 insertions(+), 1277 deletions(-) delete mode 100644 tools/gnatcov/instrument-find_ada_units.adb delete mode 100644 tools/gnatcov/instrument-find_ada_units.ads diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/QuantExpr/src/test_c6.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/QuantExpr/src/test_c6.adb index 717c8bf14..47fef9ead 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/QuantExpr/src/test_c6.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/QuantExpr/src/test_c6.adb @@ -1,6 +1,6 @@ with Test_V0_V0, Test_V0_V1, Test_V0_V2, Test_V1_X, Test_V2_X; -procedure Test_C5 is +procedure Test_C6 is begin Test_V0_V0; Test_V0_V1; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_0.adb index 6a2bd1e58..241f2d72e 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_0.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_0.adb @@ -1,6 +1,6 @@ with Vectors; use Vectors; -procedure Test_Vector_0 is +procedure Test_Vectors_0 is begin null; end; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 271391357..0e4485e2f 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -19,19 +19,24 @@ with Ada.Characters.Conversions; use Ada.Characters.Conversions; with Ada.Characters.Handling; with Ada.Containers; use Ada.Containers; +with Ada.Directories; with Ada.Exceptions; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Wide_Wide_Fixed; +pragma Warnings (Off, "* is an internal GNAT unit"); +with Ada.Strings.Wide_Wide_Unbounded.Aux; +pragma Warnings (On, "* is an internal GNAT unit"); with Langkit_Support; with Langkit_Support.Slocs; use Langkit_Support.Slocs; with Langkit_Support.Symbols; use Langkit_Support.Symbols; with Libadalang.Common; use Libadalang.Common; +with Libadalang.Config_Pragmas; with Libadalang.Expr_Eval; with Libadalang.Introspection; use Libadalang.Introspection; with Libadalang.Sources; use Libadalang.Sources; -with GNATCOLL.Projects; +with GNATCOLL.Utils; with GNATCOLL.VFS; with ALI_Files; use ALI_Files; @@ -42,12 +47,14 @@ with Files_Table; use Files_Table; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Namet; use Namet; with Outputs; use Outputs; -with Project; use Project; +with Paths; use Paths; +with Project; with SCOs; with Slocs; with Snames; use Snames; with Table; with Text_Files; use Text_Files; +with Switches; use Switches; package body Instrument.Ada_Unit is @@ -86,23 +93,9 @@ package body Instrument.Ada_Unit is -- tree. function To_Qualified_Name - (Name : Unbounded_String) return Ada_Qualified_Name; - -- Return the qualified name corresponding to the given name (e.g. - -- foo-bar -> Foo.Bar). - - procedure Auto_Dump_Buffers_In_Main - (IC : Inst_Context; - Info : in out Project_Info; - Main : Compilation_Unit_Name; - URH : Unit_Rewriting_Handle) - with Pre => IC.Dump_Config.Trigger /= Manual; - -- Common code for auto dump insertion in the main procedure, used in the - -- Auto_Dump_Buffers_In_Main primitive for Ada_Instrumenter_Type, and - -- from the Instrument_Source_File procedure. - -- - -- Arguments have the same semantics as in the Auto_Dump_Buffers_In_Main - -- primitive. The additional URH argument is the Ada source rewriter that - -- is ready to use for the source file to instrument. + (Name : Libadalang.Analysis.Unbounded_Text_Type_Array) + return Ada_Qualified_Name; + -- Convert a Libadalang fully qualified name into our format procedure Import_Non_Instrumented_LL_SCOs (UIC : Ada_Unit_Inst_Context; SCO_Map : LL_HL_SCO_Map); @@ -150,28 +143,19 @@ package body Instrument.Ada_Unit is end return; end To_Qualified_Name; - ----------------------- - -- To_Qualified_Name -- - ----------------------- - function To_Qualified_Name - (Name : Unbounded_String) return Ada_Qualified_Name - is - Result : Ada_Qualified_Name; - Start_Index : Positive := 1; + (Name : Libadalang.Analysis.Unbounded_Text_Type_Array) + return Ada_Qualified_Name is begin - for I in 1 .. Length (Name) loop - if Element (Name, I) = '-' then + return Result : Ada_Qualified_Name do + for N of Name loop + + -- ??? Same limitation regarding non-ASCII characters as above + Result.Append - (Instrument.Base_Types.Ada_Identifier - (+Slice (Name, Start_Index, I - 1))); - Start_Index := I + 1; - end if; - end loop; - Result.Append - (Instrument.Base_Types.Ada_Identifier - (+Slice (Name, Start_Index, Length (Name)))); - return Result; + (To_Unbounded_String (Image (To_Wide_Wide_String (N)))); + end loop; + end return; end To_Qualified_Name; ------------------------------------- @@ -946,9 +930,9 @@ package body Instrument.Ada_Unit is -- the return type of the expression function. function Has_Matching_Pragma_For_Unit - (IC : Inst_Context; - Unit : Compilation_Unit; - Filter : access function (Node : Pragma_Node) return Boolean) + (Context : Analysis_Context; + Unit : Compilation_Unit; + Filter : access function (Node : Pragma_Node) return Boolean) return Boolean; -- Return whether Filter return True on at least one configuration pragma -- that applies to Unit or system.ads. @@ -963,7 +947,7 @@ package body Instrument.Ada_Unit is -- Return True if Prag_Node imposes a restrictions on use of finalization function Finalization_Restricted_In_Unit - (IC : Inst_Context; Unit : Compilation_Unit) return Boolean; + (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean; -- Return True if Finalization is not available in this runtime, or if -- some control pragma restricts the usage of finalization in either Unit -- or the whole project. @@ -974,7 +958,7 @@ package body Instrument.Ada_Unit is -- Ada.Task_Termination and/or Ada.Task_Identification. function Task_Termination_Restricted - (IC : Inst_Context; Unit : Compilation_Unit) return Boolean; + (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean; -- Return True if tasking is not available in this runtime, or if some -- configuration pragma prevents the use of tasks and/or -- Ada.Task_Termination and/or Ada.Task_Identification in either the whole @@ -1025,25 +1009,147 @@ package body Instrument.Ada_Unit is -- UIC.Current_Scope_Entity.Parent, if any. Assume that the last generated -- SCO (SCOs.SCO_Table.Last) is the last SCO for the current scope. + ---------------------------- + -- Context miscellaneous -- + ---------------------------- + + Max_Get_From_File_Count : constant := 50; + -- In addition to nodes and text buffers for each loaded unit, Libadalang + -- maintains caches in Analysis_Context objects so that semantic queries + -- are fast. This means that if we keep the same context to process a lot + -- of units, we end up with excessive memory consumption, which can trigger + -- heap exhaustion on big projects. + -- + -- Replacing an analysis context with a new one clears all the caches, but + -- makes semantic queries slower, as the units are re-loaded and caches are + -- re-populated as needed. + -- + -- To compromise between memory consumption and performance, we reset the + -- analysis context each Max_Get_From_File_Count number of calls to + -- Libadalang's Get_From_File function. + + type Missing_Src_Reporter is new Libadalang.Analysis.Event_Handler_Interface + with record + Instrumented_File : Unbounded_String; + -- Base name for the file that is currently instrumented. Reset to the + -- empty string everytime we print the "While instrumenting XXX ..." + -- message, so that we print it at most once per instrumented file. + + Reported_Files : String_Sets.Set; + -- Set of source file names which were already reported as missing. + -- Libadalang does not guarantee that the Unit_Requested event is + -- triggered only once per source, so de-duplicate events with this set. + end record; + -- Implementation of the Libadalang event handler interface used in + -- Create_Missing_File_Reporter. + + type Missing_Src_Reporter_Access is access all Missing_Src_Reporter; + + overriding procedure Release (Self : in out Missing_Src_Reporter) is null; + + overriding procedure Unit_Requested_Callback + (Self : in out Missing_Src_Reporter; + Context : Libadalang.Analysis.Analysis_Context'Class; + Name : Langkit_Support.Text.Text_Type; + From : Libadalang.Analysis.Analysis_Unit'Class; + Found : Boolean; + Is_Not_Found_Error : Boolean); + -- If the requested unit is not found and that is an error, warn about it. + -- Make sure we warn only once about a given source file. + + function Create_Missing_File_Reporter + return Libadalang.Analysis.Event_Handler_Reference; + -- Create an event handler to warn about source files that Libadalang needs + -- to perform semantic analysis (so mandated by Ada), but which are not + -- available. + + procedure Create_LAL_Context (Instrumenter : in out Ada_Instrumenter_Type); + -- Create a new Libadalang analysis context for Instrumenter, assigning it + -- to Instrumenter.Context. + -- + -- This helper takes care of passing the unit provider and the event + -- handler that we need for all such contexts, and resets + -- Instrumenter.Get_From_File_Count to 0, as the new context has not been + -- used to instrument any source file yet. + + function Get_From_File + (Instrumenter : in out Ada_Instrumenter_Type; + Filename : String) return Libadalang.Analysis.Analysis_Unit; + -- Fetch the analysis unit for the given filename + + ------------------------- + -- Source instrumenter -- + ------------------------- + + type Ada_Source_Rewriter is limited new Ada.Finalization.Limited_Controlled + with + record + Input_Filename : Ada.Strings.Unbounded.Unbounded_String; + Output_Filename : Ada.Strings.Unbounded.Unbounded_String; + + Unit : Libadalang.Analysis.Analysis_Unit; + Handle : Libadalang.Rewriting.Rewriting_Handle; + end record; + + overriding procedure Finalize (Self : in out Ada_Source_Rewriter); + + procedure Start_Rewriting + (Self : out Ada_Source_Rewriter'Class; + Instrumenter : in out Ada_Instrumenter_Type; + Info : in out Project_Info; + Input_Filename : String); + -- Start a rewriting session for the given Input_Filename. If the rewriting + -- process is successful, the result will be written to a file in + -- Info.Output_Dir with the basename of Output_Filename. + -- + -- This registers the output file in Info.Instr_Files. + -- + -- If there are parsing errors while reading Input_Filename, this raises a + -- fatal error and prints the corresponding error messages. + + function Rewritten_Unit + (Self : Ada_Source_Rewriter'Class) + return Libadalang.Analysis.Analysis_Unit; + -- Return the analysis unit for the source that Self instruments + + procedure Apply (Self : in out Ada_Source_Rewriter'Class); + -- Write the instrumented source to the filename passed as Output_Filename + -- to Start_Rewriting. If rewriting failed, raise a fatal error and print + -- the corresponding error message. + + procedure Remove_Warnings_And_Style_Checks_Pragmas + (Rewriter : Ada_Source_Rewriter'Class); + -- Remove all Warnings/Style_Checks pragmas in Rewriter's unit + ---------------------------- -- Source level rewriting -- ---------------------------- + procedure Put_Warnings_And_Style_Checks_Pragmas + (File : in out Text_Files.File_Type); + -- Code generation helper: write "pragma Style_Checks (Off); pragma + -- Warnings (Off);" to File. + -- + -- This is useful when writing instrumented sources, as they may introduce + -- warnings and break the original codebase's coding style, and since some + -- projects are built with "warnings-as-errors" (GNAT's -gnatwe option), + -- this could mean that instrumentation breaks the build. When written at + -- the very beginning of each written source, these pragmas avoid this. + procedure Initialize_Rewriting - (IC : out Ada_Unit_Inst_Context; - Instrumented_Unit : Compilation_Unit_Name; - Context : Analysis_Context); + (Instrumenter : Ada_Instrumenter_Type; + UIC : out Ada_Unit_Inst_Context; + Instrumented_Unit : Compilation_Unit_Name); -- Initialize a unit instrumentation context for the given unit to -- instrument. procedure Instrument_Source_File - (CU_Name : Compilation_Unit_Name; - Unit_Info : Instrumented_Unit_Info; - Prj_Info : in out Project_Info; - IC : in out Inst_Context; - UIC : out Ada_Unit_Inst_Context); + (CU_Name : Compilation_Unit_Name; + Unit_Info : Instrumented_Unit_Info; + Prj_Info : in out Project_Info; + Instrumenter : in out Ada_Instrumenter_Type; + UIC : out Ada_Unit_Inst_Context); -- Generate the instrumented source corresponding to CU_Name/Unit_Info. - -- Record instrumentation information in IC. -- -- If the unit to instrument is also a main and the buffers dump trigger -- is not manual, instrumented code will also dump the coverage buffers. @@ -1052,7 +1158,8 @@ package body Instrument.Ada_Unit is -- Unit instrumentation -- -------------------------- - function Buffers_List_Unit (IC : Inst_Context) return Ada_Qualified_Name; + function Buffers_List_Unit + (Project_Name : String) return Ada_Qualified_Name; -- Returns the name of the unit containing the array of coverage buffers. -- It is named after the root project name (e.g. if the root project is -- p.gpr, its name is .). @@ -1072,16 +1179,17 @@ package body Instrument.Ada_Unit is -- Emit the unit to contain addresses for the coverage buffers procedure Emit_Dump_Helper_Unit - (IC : Inst_Context; + (Dump_Config : Any_Dump_Config; Info : in out Project_Info; + Main_Filename : String; Main : Compilation_Unit_Name; Helper_Unit : out Ada_Qualified_Name; Override_Dump_Trigger : Any_Dump_Trigger := Manual; Has_Controlled : Boolean := False); -- Emit the unit to contain helpers to implement the automatic dump of - -- coverage buffers for the given Main unit. Info must be the project that - -- owns this main. Upon return, the name of this helper unit is stored in - -- Helper_Unit. + -- coverage buffers for the given Main unit implemented in Main_Filename. + -- Info must be the project that owns this main. Upon return, the name of + -- this helper unit is stored in Helper_Unit. -- -- If Override_Dump_Trigger is anything other than Manual, it will be used -- as a dump trigger instead of the one defined in IC.Dump_Config. @@ -2522,8 +2630,7 @@ package body Instrument.Ada_Unit is ----------------------------------------- procedure Traverse_Declarations_Or_Statements - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; L : Ada_List'Class; Preelab : Boolean := False; P : Ada_Node := No_Ada_Node; @@ -2560,36 +2667,30 @@ package body Instrument.Ada_Unit is -- and semantic dependencies. procedure Traverse_Generic_Package_Declaration - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; N : Generic_Package_Decl; Preelab : Boolean); procedure Traverse_Handled_Statement_Sequence - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; N : Handled_Stmts); procedure Traverse_Package_Body - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; N : Package_Body; Preelab : Boolean); procedure Traverse_Package_Declaration - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; N : Base_Package_Decl; Preelab : Boolean); procedure Traverse_Subprogram_Or_Task_Body - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; N : Ada_Node); procedure Traverse_Sync_Definition - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; N : Ada_Node); -- Traverse a protected definition or task definition @@ -2749,8 +2850,7 @@ package body Instrument.Ada_Unit is -- in which the decisions occur. procedure Traverse_Declarations_Or_Statements - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; L : Ada_List'Class; Preelab : Boolean := False; P : Ada_Node := No_Ada_Node; @@ -3978,29 +4078,12 @@ package body Instrument.Ada_Unit is CU_Prev_Decl : constant Basic_Decl := CU_Decl.P_Previous_Part_For_Decl; begin - -- If we found a subunit, assert that the corresponding - -- body/parent subunit is also instrumented. - - if Is_Subunit then - declare - Body_Name : constant Ada_Qualified_Name := - Canonicalize - (To_Qualified_Name (CUN_Body.As_Subunit.F_Name)); - begin - pragma Assert - (IC.Instrumented_Units.Contains - (CU_Name_For_Unit (Body_Name, GPR.Unit_Body)) - or else IC.Instrumented_Units.Contains - (CU_Name_For_Unit - (Body_Name, GPR.Unit_Separate))); - end; - -- For a library unit, scan context clause. If this is a -- body, also obtain WITH clauses from the spec. Also -- record implicit WITHs for the unit itself and all of -- its parents. - else + if not Is_Subunit then Traverse_Context_Clause (UIC, CUN.F_Prelude, Process_Pragmas => True); if not CU_Prev_Decl.Is_Null then @@ -4052,7 +4135,7 @@ package body Instrument.Ada_Unit is UIC.In_Generic := True; end if; Traverse_Declarations_Or_Statements - (IC, UIC, + (UIC, P => CU_Decl.As_Ada_Node, L => CUN.F_Pragmas, Preelab => Preelab); @@ -4085,7 +4168,7 @@ package body Instrument.Ada_Unit is when Ada_Package_Decl => Set_Statement_Entry; Traverse_Package_Declaration - (IC, UIC, N.As_Base_Package_Decl, Preelab); + (UIC, N.As_Base_Package_Decl, Preelab); -- Generic package declaration @@ -4093,7 +4176,7 @@ package body Instrument.Ada_Unit is UIC.In_Generic := True; Set_Statement_Entry; Traverse_Generic_Package_Declaration - (IC, UIC, N.As_Generic_Package_Decl, Preelab); + (UIC, N.As_Generic_Package_Decl, Preelab); UIC.In_Generic := Saved_In_Generic; -- Package body @@ -4101,7 +4184,7 @@ package body Instrument.Ada_Unit is when Ada_Package_Body => UIC.In_Generic := Is_Generic (UIC, N.As_Basic_Decl); Set_Statement_Entry; - Traverse_Package_Body (IC, UIC, N.As_Package_Body, Preelab); + Traverse_Package_Body (UIC, N.As_Package_Body, Preelab); UIC.In_Generic := Saved_In_Generic; -- Subprogram declaration or subprogram body stub @@ -4142,7 +4225,7 @@ package body Instrument.Ada_Unit is UIC.In_Generic := True; end if; Set_Statement_Entry; - Traverse_Subprogram_Or_Task_Body (IC, UIC, N); + Traverse_Subprogram_Or_Task_Body (UIC, N); UIC.In_Generic := Saved_In_Generic; -- Entry body @@ -4159,7 +4242,7 @@ package body Instrument.Ada_Unit is Process_Decisions_Defer (Cond, 'G'); end if; - Traverse_Subprogram_Or_Task_Body (IC, UIC, N); + Traverse_Subprogram_Or_Task_Body (UIC, N); end; -- Protected body @@ -4167,7 +4250,7 @@ package body Instrument.Ada_Unit is when Ada_Protected_Body => Set_Statement_Entry; Traverse_Declarations_Or_Statements - (IC, UIC, L => As_Protected_Body (N).F_Decls.F_Decls); + (UIC, L => As_Protected_Body (N).F_Decls.F_Decls); -- Exit statement, which is an exit statement in the SCO sense, -- so it is included in the current statement sequence, but @@ -4197,11 +4280,11 @@ package body Instrument.Ada_Unit is if N.Kind = Ada_Decl_Block then Traverse_Declarations_Or_Statements - (IC, UIC, L => As_Decl_Block (N).F_Decls.F_Decls); + (UIC, L => As_Decl_Block (N).F_Decls.F_Decls); end if; Traverse_Handled_Statement_Sequence - (IC, UIC, + (UIC, N => (case N.Kind is when Ada_Decl_Block => As_Decl_Block (N).F_Stmts, when Ada_Begin_Block => As_Begin_Block (N).F_Stmts, @@ -4223,7 +4306,7 @@ package body Instrument.Ada_Unit is -- Now we traverse the statements in the THEN part Traverse_Declarations_Or_Statements - (IC, UIC, + (UIC, L => If_N.F_Then_Stmts.As_Ada_Node_List); -- Loop through ELSIF parts if present @@ -4248,7 +4331,7 @@ package body Instrument.Ada_Unit is -- Traverse the statements in the ELSIF Traverse_Declarations_Or_Statements - (IC, UIC, + (UIC, L => Elif.F_Stmts.As_Ada_Node_List); end; end loop; @@ -4256,7 +4339,7 @@ package body Instrument.Ada_Unit is -- Finally traverse the ELSE statements if present Traverse_Declarations_Or_Statements - (IC, UIC, + (UIC, L => If_N.F_Else_Stmts.As_Ada_Node_List); end; @@ -4281,7 +4364,7 @@ package body Instrument.Ada_Unit is Alt_L.Child (J).As_Case_Stmt_Alternative; begin Traverse_Declarations_Or_Statements - (IC, UIC, + (UIC, L => Alt.F_Stmts.As_Ada_Node_List); end; end loop; @@ -4297,7 +4380,7 @@ package body Instrument.Ada_Unit is -- Process sequence of statements Traverse_Handled_Statement_Sequence - (IC, UIC, + (UIC, N => N.As_Accept_Stmt_With_Stmts.F_Stmts); end if; @@ -4328,7 +4411,7 @@ package body Instrument.Ada_Unit is -- entry_call_alternative, or triggering_alternative. Traverse_Declarations_Or_Statements - (IC, UIC, + (UIC, L => Alt.F_Stmts.As_Ada_Node_List, Is_Select_Stmt_Alternative => True); end; @@ -4338,10 +4421,10 @@ package body Instrument.Ada_Unit is -- do not require the special processing for alternatives. Traverse_Declarations_Or_Statements - (IC, UIC, + (UIC, L => Sel_N.F_Else_Stmts.As_Ada_Node_List); Traverse_Declarations_Or_Statements - (IC, UIC, + (UIC, L => Sel_N.F_Abort_Stmts.As_Ada_Node_List); end; @@ -4384,7 +4467,7 @@ package body Instrument.Ada_Unit is Set_Statement_Entry; Traverse_Handled_Statement_Sequence - (IC, UIC, + (UIC, N => ER_N.F_Stmts); end; @@ -4433,7 +4516,7 @@ package body Instrument.Ada_Unit is Set_Statement_Entry; Traverse_Declarations_Or_Statements - (IC, UIC, + (UIC, L => Loop_S.F_Stmts.As_Ada_Node_List); end; @@ -4604,7 +4687,7 @@ package body Instrument.Ada_Unit is end; Set_Statement_Entry; - Traverse_Sync_Definition (IC, UIC, N); + Traverse_Sync_Definition (UIC, N); when Ada_Single_Protected_Decl | Ada_Single_Task_Decl @@ -4612,7 +4695,7 @@ package body Instrument.Ada_Unit is Extend_Statement_Sequence (UIC, N, 'o'); Set_Statement_Entry; - Traverse_Sync_Definition (IC, UIC, N); + Traverse_Sync_Definition (UIC, N); when Ada_Named_Stmt => Traverse_One (N.As_Named_Stmt.F_Stmt.As_Ada_Node); @@ -4866,15 +4949,14 @@ package body Instrument.Ada_Unit is ------------------------------------------ procedure Traverse_Generic_Package_Declaration - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; N : Generic_Package_Decl; Preelab : Boolean) is begin Process_Decisions (UIC, N.F_Formal_Part, 'X'); Traverse_Package_Declaration - (IC, UIC, N.F_Package_Decl.As_Base_Package_Decl, Preelab); + (UIC, N.F_Package_Decl.As_Base_Package_Decl, Preelab); end Traverse_Generic_Package_Declaration; ----------------------------------------- @@ -4882,8 +4964,7 @@ package body Instrument.Ada_Unit is ----------------------------------------- procedure Traverse_Handled_Statement_Sequence - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; N : Handled_Stmts) is begin @@ -4892,7 +4973,7 @@ package body Instrument.Ada_Unit is end if; Traverse_Declarations_Or_Statements - (IC, UIC, L => N.F_Stmts.As_Ada_Node_List); + (UIC, L => N.F_Stmts.As_Ada_Node_List); for J in 1 .. N.F_Exceptions.Children_Count loop declare @@ -4902,7 +4983,7 @@ package body Instrument.Ada_Unit is if Handler.Kind = Ada_Exception_Handler then Traverse_Declarations_Or_Statements - (IC, UIC, + (UIC, L => Handler.As_Exception_Handler.F_Stmts.As_Ada_Node_List); end if; end; @@ -4914,8 +4995,7 @@ package body Instrument.Ada_Unit is --------------------------- procedure Traverse_Package_Body - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; N : Package_Body; Preelab : Boolean) is @@ -4932,8 +5012,8 @@ package body Instrument.Ada_Unit is UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; Traverse_Declarations_Or_Statements - (IC, UIC, N.F_Decls.F_Decls, Preelab); - Traverse_Handled_Statement_Sequence (IC, UIC, N => N.F_Stmts); + (UIC, N.F_Decls.F_Decls, Preelab); + Traverse_Handled_Statement_Sequence (UIC, N => N.F_Stmts); UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; Exit_Scope (UIC); @@ -4945,8 +5025,7 @@ package body Instrument.Ada_Unit is ---------------------------------- procedure Traverse_Package_Declaration - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; N : Base_Package_Decl; Preelab : Boolean) is @@ -4963,12 +5042,12 @@ package body Instrument.Ada_Unit is UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; Traverse_Declarations_Or_Statements - (IC, UIC, N.F_Public_Part.F_Decls, Preelab, + (UIC, N.F_Public_Part.F_Decls, Preelab, Priv_Part => N.F_Private_Part); if not N.F_Private_Part.Is_Null then Traverse_Declarations_Or_Statements - (IC, UIC, + (UIC, L => N.F_Private_Part.F_Decls, Preelab => Preelab); end if; @@ -4982,8 +5061,7 @@ package body Instrument.Ada_Unit is ------------------------------ procedure Traverse_Sync_Definition - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; N : Ada_Node) is Vis_Decl : Public_Part := No_Public_Part; @@ -5041,12 +5119,12 @@ package body Instrument.Ada_Unit is if not Vis_Decl.Is_Null then Traverse_Declarations_Or_Statements - (IC, UIC, L => Vis_Decl.F_Decls, Priv_Part => Priv_Decl); + (UIC, L => Vis_Decl.F_Decls, Priv_Part => Priv_Decl); end if; if not Priv_Decl.Is_Null then Traverse_Declarations_Or_Statements - (IC, UIC, L => Priv_Decl.F_Decls); + (UIC, L => Priv_Decl.F_Decls); end if; end Traverse_Sync_Definition; @@ -5055,8 +5133,7 @@ package body Instrument.Ada_Unit is -------------------------------------- procedure Traverse_Subprogram_Or_Task_Body - (IC : in out Inst_Context; - UIC : in out Ada_Unit_Inst_Context; + (UIC : in out Ada_Unit_Inst_Context; N : Ada_Node) is Decls : Declarative_Part; @@ -5108,9 +5185,9 @@ package body Instrument.Ada_Unit is Local_Inserter.Local_Decls := Handle (Decls.F_Decls); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; - Traverse_Declarations_Or_Statements (IC, UIC, L => Decls.F_Decls); + Traverse_Declarations_Or_Statements (UIC, L => Decls.F_Decls); - Traverse_Handled_Statement_Sequence (IC, UIC, N => HSS); + Traverse_Handled_Statement_Sequence (UIC, N => HSS); Exit_Scope (UIC); @@ -6196,38 +6273,223 @@ package body Instrument.Ada_Unit is end if; end Exit_Scope; + --------------------- + -- Start_Rewriting -- + --------------------- + + procedure Start_Rewriting + (Self : out Ada_Source_Rewriter'Class; + Instrumenter : in out Ada_Instrumenter_Type; + Info : in out Project_Info; + Input_Filename : String) + is + Base_Filename : constant String := + Ada.Directories.Simple_Name (Input_Filename); + Output_Filename : constant String := + To_String (Info.Output_Dir) / Base_Filename; + Unit : constant Analysis_Unit := + Get_From_File (Instrumenter, Input_Filename); + begin + if Unit.Has_Diagnostics then + Outputs.Error ("instrumentation failed for " & Input_Filename); + Outputs.Error ("please make sure the original project can be " + & "compiled"); + for D of Unit.Diagnostics loop + Outputs.Error (Unit.Format_GNU_Diagnostic (D)); + end loop; + raise Xcov_Exit_Exc; + end if; + + Self.Input_Filename := To_Unbounded_String (Input_Filename); + Self.Output_Filename := To_Unbounded_String (Output_Filename); + Self.Unit := Unit; + Self.Handle := Start_Rewriting (Instrumenter.Context); + end Start_Rewriting; + + -------------------- + -- Rewritten_Unit -- + -------------------- + + function Rewritten_Unit + (Self : Ada_Source_Rewriter'Class) + return Libadalang.Analysis.Analysis_Unit is + begin + return Self.Unit; + end Rewritten_Unit; + + ----------------------------- + -- Unit_Requested_Callback -- + ----------------------------- + + overriding procedure Unit_Requested_Callback + (Self : in out Missing_Src_Reporter; + Context : Libadalang.Analysis.Analysis_Context'Class; + Name : Langkit_Support.Text.Text_Type; + From : Libadalang.Analysis.Analysis_Unit'Class; + Found : Boolean; + Is_Not_Found_Error : Boolean) + is + begin + -- We need to warn about sources that we could not find *and* whose + -- presence is mandated by Ada. + + if Found or else not Is_Not_Found_Error then + return; + end if; + + -- Warn for a given source file only once, as Libadalang can invoke this + -- callback several times. For clarity, only mention the base name, + -- which should be unique in Ada projects anyway. + + declare + N : constant Unbounded_String := To_Unbounded_String + (Ada.Directories.Simple_Name (Langkit_Support.Text.Image (Name))); + begin + if Self.Reported_Files.Contains (N) then + return; + end if; + + Self.Reported_Files.Include (N); + + -- Warn only if the file does not reside in the GNATcov_RTS + -- hierarchy. + + declare + Source_Name : constant String := To_String (N); + begin + if GNATCOLL.Utils.Starts_With (Source_Name, "gnatcov_rts") then + return; + end if; + end; + + -- If we have not done it yet, clarify which file we were + -- instrumenting when we noticed that the source file N was missing. + + if Length (Self.Instrumented_File) > 0 then + Warn ("While instrumenting " + & To_String (Self.Instrumented_File) + & "..."); + Self.Instrumented_File := Null_Unbounded_String; + end if; + + Warn ("Cannot find required source file: " & To_String (N)); + end; + end Unit_Requested_Callback; + + ---------------------------------- + -- Create_Missing_File_Reporter -- + ---------------------------------- + + function Create_Missing_File_Reporter + return Libadalang.Analysis.Event_Handler_Reference + is + begin + return Create_Event_Handler_Reference + (Missing_Src_Reporter'(others => <>)); + end Create_Missing_File_Reporter; + + ------------------------ + -- Create_LAL_Context -- + ------------------------ + + procedure Create_LAL_Context (Instrumenter : in out Ada_Instrumenter_Type) + is + begin + Instrumenter.Context := Create_Context + (Unit_Provider => Instrumenter.Provider, + Event_Handler => Instrumenter.Event_Handler); + Instrumenter.Get_From_File_Count := 0; + + -- Load configuration pragmas + -- TODO??? Remove the type convertion when the LAL API change for + -- VA07-037 makes it into stable-libadalang. + + Libadalang.Config_Pragmas.Import_From_Project + (Instrumenter.Context, + GNATCOLL.Projects.Project_Tree (Project.Project.all)); + end Create_LAL_Context; + + ----------------------------- + -- Create_Ada_Instrumenter -- + ----------------------------- + + function Create_Ada_Instrumenter + (Provider : Unit_Provider_Reference; + Language_Version : Any_Language_Version) return Ada_Instrumenter_Type + is + Instrumenter : Ada_Instrumenter_Type; + begin + Instrumenter.Provider := Provider; + Instrumenter.Event_Handler := Create_Missing_File_Reporter; + Create_LAL_Context (Instrumenter); + Instrumenter.Language_Version := Language_Version; + return Instrumenter; + end Create_Ada_Instrumenter; + + ------------------- + -- Get_From_File -- + ------------------- + + function Get_From_File + (Instrumenter : in out Ada_Instrumenter_Type; + Filename : String) return Libadalang.Analysis.Analysis_Unit + is + begin + -- If we exceeded the maximum number of calls to Get_From_File, start + -- with a new context. + + if Instrumenter.Get_From_File_Count >= Max_Get_From_File_Count then + Create_LAL_Context (Instrumenter); + end if; + Instrumenter.Get_From_File_Count := + Instrumenter.Get_From_File_Count + 1; + + return Instrumenter.Context.Get_From_File (Filename); + end Get_From_File; + + ------------------------------------------- + -- Put_Warnings_And_Style_Checks_Pragmas -- + ------------------------------------------- + + procedure Put_Warnings_And_Style_Checks_Pragmas + (File : in out Text_Files.File_Type) + is + begin + File.Put_Line ("pragma Style_Checks (Off); pragma Warnings (Off);"); + end Put_Warnings_And_Style_Checks_Pragmas; + -------------------------- -- Initialize_Rewriting -- -------------------------- procedure Initialize_Rewriting - (IC : out Ada_Unit_Inst_Context; - Instrumented_Unit : Compilation_Unit_Name; - Context : Analysis_Context) is + (Instrumenter : Ada_Instrumenter_Type; + UIC : out Ada_Unit_Inst_Context; + Instrumented_Unit : Compilation_Unit_Name) is begin - IC.Instrumented_Unit := Instrumented_Unit; - IC.Buffer_Unit := + UIC.Instrumented_Unit := Instrumented_Unit; + UIC.Buffer_Unit := CU_Name_For_Unit (Buffer_Unit (Instrumented_Unit), GPR.Unit_Spec); - IC.Pure_Buffer_Unit := + UIC.Pure_Buffer_Unit := CU_Name_For_Unit (Pure_Buffer_Unit (Instrumented_Unit), GPR.Unit_Spec); - IC.Rewriting_Context := Handle (Context); + UIC.Rewriting_Context := Handle (Instrumenter.Context); declare - RH : constant Rewriting_Handle := IC.Rewriting_Context; - E : Instrumentation_Entities renames IC.Entities; + RH : constant Rewriting_Handle := UIC.Rewriting_Context; + E : Instrumentation_Entities renames UIC.Entities; begin E.Common_Buffers := To_Nodes (RH, Sys_Buffers); - E.Unit_Buffers := To_Nodes (RH, IC.Pure_Buffer_Unit.Unit); + E.Unit_Buffers := To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit); E.Statement_Buffer := - To_Nodes (RH, IC.Pure_Buffer_Unit.Unit & Statement_Buffer_Name); + To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit & Statement_Buffer_Name); if Coverage.Enabled (Decision) or else MCDC_Coverage_Enabled then E.Decision_Buffer := - To_Nodes (RH, IC.Pure_Buffer_Unit.Unit & Decision_Buffer_Name); + To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit & Decision_Buffer_Name); if MCDC_Coverage_Enabled then E.MCDC_Buffer := - To_Nodes (RH, IC.Pure_Buffer_Unit.Unit & MCDC_Buffer_Name); + To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit & MCDC_Buffer_Name); end if; end if; end; @@ -6358,13 +6620,13 @@ package body Instrument.Ada_Unit is ---------------------------------- function Has_Matching_Pragma_For_Unit - (IC : Inst_Context; - Unit : Compilation_Unit; - Filter : access function (Node : Pragma_Node) return Boolean) + (Context : Analysis_Context; + Unit : Compilation_Unit; + Filter : access function (Node : Pragma_Node) return Boolean) return Boolean is System_Unit : constant Analysis_Unit := - IC.Context.Get_From_Provider ("System", Unit_Specification); + Context.Get_From_Provider ("System", Unit_Specification); Unit_Pragmas : constant Pragma_Node_Array := Unit.P_All_Config_Pragmas & (if System_Unit.Has_Diagnostics @@ -6439,12 +6701,12 @@ package body Instrument.Ada_Unit is ------------------------------------- function Finalization_Restricted_In_Unit - (IC : Inst_Context; Unit : Compilation_Unit) return Boolean + (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean is begin return not Project.Runtime_Supports_Finalization or else Has_Matching_Pragma_For_Unit - (IC, Unit, Pragma_Restricts_Finalization'Access); + (Context, Unit, Pragma_Restricts_Finalization'Access); end Finalization_Restricted_In_Unit; -------------------------------------- @@ -6497,27 +6759,176 @@ package body Instrument.Ada_Unit is --------------------------------- function Task_Termination_Restricted - (IC : Inst_Context; Unit : Compilation_Unit) return Boolean + (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean is begin return not Project.Runtime_Supports_Task_Termination or else Has_Matching_Pragma_For_Unit - (IC, Unit, Pragma_Prevents_Task_Termination'Access); + (Context, Unit, Pragma_Prevents_Task_Termination'Access); end Task_Termination_Restricted; + ----------- + -- Apply -- + ----------- + + procedure Apply (Self : in out Ada_Source_Rewriter'Class) is + begin + -- Automatically insert pragmas to disable style checks and + -- warnings in generated code: it is not our goal to make + -- instrumentation generate warning-free or well-formatted + -- code. + + Remove_Warnings_And_Style_Checks_Pragmas (Self); + + declare + use Ada.Strings.Wide_Wide_Unbounded.Aux; + + Unit : constant Unit_Rewriting_Handle := Handle (Self.Unit); + Source : constant Unbounded_Wide_Wide_String := Unparse (Unit); + + -- To avoid copying the potentially big string for sources on the + -- secondary stack (and reduce the amount of copies anyway), use the + -- internal GNAT API to retreive the internal string access and + -- process it by chunks. + + Source_Access : Big_Wide_Wide_String_Access; + Length : Natural; + + Chunk_Size : constant := 4096; + Position : Natural; + + Filename : constant String := To_String (Self.Output_Filename); + Out_File : Text_Files.File_Type; + begin + Abort_Rewriting (Self.Handle); + Out_File.Create (Filename); + Put_Warnings_And_Style_Checks_Pragmas (Out_File); + + Get_Wide_Wide_String (Source, Source_Access, Length); + Position := Source_Access.all'First; + + while Position <= Length loop + declare + Chunk_First : constant Natural := Position; + Chunk_Last : constant Natural := Natural'Min + (Chunk_First + Chunk_Size - 1, Length); + + Chunk : Wide_Wide_String renames + Source_Access.all (Chunk_First .. Chunk_Last); + Encoded_Chunk : constant String := + Ada.Characters.Conversions.To_String (Chunk); + begin + Out_File.Put (Encoded_Chunk); + Position := Chunk_Last + 1; + end; + end loop; + + Out_File.Close; + if Switches.Pretty_Print then + Text_Files.Run_GNATpp (Out_File); + end if; + end; + + Self.Finalize; + end Apply; + + -------------- + -- Finalize -- + -------------- + + overriding procedure Finalize (Self : in out Ada_Source_Rewriter) is + begin + if Self.Handle /= No_Rewriting_Handle then + Abort_Rewriting (Self.Handle); + end if; + Self.Unit := No_Analysis_Unit; + end Finalize; + + ---------------------------------------------- + -- Remove_Warnings_And_Style_Checks_Pragmas -- + ---------------------------------------------- + + procedure Remove_Warnings_And_Style_Checks_Pragmas + (Rewriter : Ada_Source_Rewriter'Class) + is + + function Should_Remove (Node : Node_Rewriting_Handle) return Boolean; + -- Return whether Node is a pragma Warnings or Style_Checks + + procedure Process (Node : Node_Rewriting_Handle); + -- Remove all pragma Warnings/Style_Checks statements from Node and its + -- children. + + ------------------- + -- Should_Remove -- + ------------------- + + function Should_Remove (Node : Node_Rewriting_Handle) return Boolean is + begin + if Kind (Node) /= Ada_Pragma_Node then + return False; + end if; + + declare + Symbol : constant Symbolization_Result := + Canonicalize (Text (Child (Node, 1))); + begin + return (Symbol.Success + and then Symbol.Symbol in "warnings" | "style_checks"); + end; + end Should_Remove; + + ------------- + -- Process -- + ------------- + + procedure Process (Node : Node_Rewriting_Handle) is + begin + if Node = No_Node_Rewriting_Handle then + return; + end if; + + -- Go through all children in reverse order so that we can remove + -- pragmas in one pass. + + for I in reverse 1 .. Children_Count (Node) loop + declare + Child : constant Node_Rewriting_Handle := + Libadalang.Rewriting.Child (Node, I); + begin + if Child /= No_Node_Rewriting_Handle + and then Should_Remove (Child) + then + Remove_Child (Node, I); + else + Process (Child); + end if; + end; + end loop; + end Process; + + -- Start of processing for Remove_Warnings_And_Style_Checks_Pragmas + + begin + Process (Handle (Rewriter.Unit.Root)); + end Remove_Warnings_And_Style_Checks_Pragmas; + ------------------------------- -- Auto_Dump_Buffers_In_Main -- ------------------------------- - procedure Auto_Dump_Buffers_In_Main - (IC : Inst_Context; - Info : in out Project_Info; - Main : Compilation_Unit_Name; - URH : Unit_Rewriting_Handle) + overriding procedure Auto_Dump_Buffers_In_Main + (Self : in out Ada_Instrumenter_Type; + Filename : String; + Instr_Units : CU_Name_Vectors.Vector; + Dump_Config : Any_Dump_Config; + Info : in out Project_Info) is - U : constant Analysis_Unit := Unit (URH); - RH : constant Rewriting_Handle := Handle (U.Context); - Tmp : LAL.Ada_Node := U.Root; + Rewriter : Ada_Source_Rewriter; + + U : Analysis_Unit; + RH : Rewriting_Handle; + Tmp : LAL.Ada_Node; CU : LAL.Compilation_Unit; Subp_Body : LAL.Subp_Body; @@ -6528,22 +6939,34 @@ package body Instrument.Ada_Unit is -- Resolved dump trigger after eventual override depending on the -- features available on the runtime. - Instr_Units : constant CU_Name_Vectors.Vector := - Instr_Units_For_Closure (IC, Main); - -- List of instrumented units for which we need to dump buffers - Helper_Unit : Ada_Qualified_Name; -- Name of unit to contain helpers implementing the buffers dump + Main : Compilation_Unit_Name (Unit_Based_Language) := + (Language_Kind => Unit_Based_Language, + Part => Unit_Body, + others => <>); + -- Note that we can't get the compilation unit name using the + -- To_Compilation_Unit_Name overload taking a File_Info parameter, + -- as the main we are instrumenting there may be the instrumented + -- version of the original version, in which case it won't belong + -- to the root project as it will be in the -gnatcov-instr + -- directory. + begin if Instr_Units.Is_Empty then return; end if; + Start_Rewriting (Rewriter, Self, Info, Filename); -- Make sure this main source has the expected structure: a -- simple subprogram body in a compilation unit. If not, return without -- doing anything. + U := Unit (Handle (Rewriter.Rewritten_Unit)); + RH := Handle (U.Context); + Tmp := U.Root; + if Tmp.Kind /= Ada_Compilation_Unit then return; else @@ -6563,20 +6986,23 @@ package body Instrument.Ada_Unit is end if; Controlled_Types_Available := - not Finalization_Restricted_In_Unit (IC, CU); + not Finalization_Restricted_In_Unit (U.Context, CU); Actual_Dump_Trigger := - (if IC.Dump_Config.Trigger = Main_End + (if Dump_Config.Trigger = Main_End and then not Controlled_Types_Available - and then not Task_Termination_Restricted (IC, CU) + and then not Task_Termination_Restricted (U.Context, CU) then Ravenscar_Task_Termination - else IC.Dump_Config.Trigger); + else Dump_Config.Trigger); + + Main.Unit := To_Qualified_Name (CU.P_Syntactic_Fully_Qualified_Name); -- Emit the helper unit and add a WITH clause for it Emit_Dump_Helper_Unit - (IC, + (Dump_Config, Info, + Filename, Main, Helper_Unit, Override_Dump_Trigger => Actual_Dump_Trigger, @@ -6662,29 +7088,12 @@ package body Instrument.Ada_Unit is -- - If we do not have finalization or tasks then simply insert calls -- right before all the exit points of the main. - if not Finalization_Restricted_In_Unit (IC, CU) then + if not Finalization_Restricted_In_Unit (U.Context, CU) then Insert_Controlled_Dump_Object_Decl (RH, Helper_Unit, Subp_Body); else Insert_Simple_Dump_Proc_Calls (RH, Helper_Unit, Subp_Body); end if; end case; - end Auto_Dump_Buffers_In_Main; - - overriding procedure Auto_Dump_Buffers_In_Main - (Self : Ada_Instrumenter_Type; - IC : in out Inst_Context; - Main : Compilation_Unit_Name; - Filename : String; - Info : in out Project_Info) - is - Rewriter : Source_Rewriter; - begin - Rewriter.Start_Rewriting (IC, Info, Filename); - Auto_Dump_Buffers_In_Main - (IC => IC, - Info => Info, - Main => Main, - URH => Libadalang.Rewriting.Handle (Rewriter.Rewritten_Unit)); Rewriter.Apply; end Auto_Dump_Buffers_In_Main; @@ -6693,13 +7102,13 @@ package body Instrument.Ada_Unit is ---------------------------- procedure Instrument_Source_File - (CU_Name : Compilation_Unit_Name; - Unit_Info : Instrumented_Unit_Info; - Prj_Info : in out Project_Info; - IC : in out Inst_Context; - UIC : out Ada_Unit_Inst_Context) + (CU_Name : Compilation_Unit_Name; + Unit_Info : Instrumented_Unit_Info; + Prj_Info : in out Project_Info; + Instrumenter : in out Ada_Instrumenter_Type; + UIC : out Ada_Unit_Inst_Context) is - Rewriter : Source_Rewriter; + Rewriter : Ada_Source_Rewriter; Filename : constant String := To_String (Unit_Info.Filename); Dummy_Ctx : constant Context_Handle := Create_Context ("Instrumenting " & Filename); @@ -6718,7 +7127,7 @@ package body Instrument.Ada_Unit is -- Whether there is a pragma Short_Circuit_And_Or that applies to this -- unit. begin - Rewriter.Start_Rewriting (IC, Prj_Info, Filename); + Start_Rewriting (Rewriter, Instrumenter, Prj_Info, Filename); Root_Analysis_Unit := Rewriter.Rewritten_Unit; @@ -6745,7 +7154,7 @@ package body Instrument.Ada_Unit is Preelab := False; end; - Initialize_Rewriting (UIC, CU_Name, IC.Context); + Initialize_Rewriting (Instrumenter, UIC, CU_Name); begin Has_Pragma_SCAO := UIC.Root_Unit.P_Config_Pragmas @@ -6791,8 +7200,7 @@ package body Instrument.Ada_Unit is Append_Unit (UIC.SFI); Traverse_Declarations_Or_Statements - (IC => IC, - UIC => UIC, + (UIC => UIC, L => No_Ada_List, Preelab => Preelab, P => Rewriter.Rewritten_Unit.Root); @@ -6949,16 +7357,6 @@ package body Instrument.Ada_Unit is end if; end; - -- Insert automatic buffer dump calls, if requested - - if IC.Dump_Config.Trigger /= Manual and then Unit_Info.Is_Main then - Auto_Dump_Buffers_In_Main - (IC => IC, - Info => Prj_Info, - Main => UIC.Instrumented_Unit, - URH => Handle (Rewriter.Rewritten_Unit)); - end if; - -- Emit the instrumented source file Rewriter.Apply; @@ -6968,10 +7366,11 @@ package body Instrument.Ada_Unit is -- Buffers_List_Unit -- ----------------------- - function Buffers_List_Unit (IC : Inst_Context) return Ada_Qualified_Name + function Buffers_List_Unit + (Project_Name : String) return Ada_Qualified_Name is Project_Name_Slug : constant String := - Qualified_Name_Slug (To_Qualified_Name (IC.Project_Name)); + Qualified_Name_Slug (To_Qualified_Name (Project_Name)); begin return Ada_Identifier_Vectors."&" (Sys_Buffers_Lists, @@ -7256,13 +7655,17 @@ package body Instrument.Ada_Unit is --------------------------- procedure Emit_Dump_Helper_Unit - (IC : Inst_Context; + (Dump_Config : Any_Dump_Config; Info : in out Project_Info; + Main_Filename : String; Main : Compilation_Unit_Name; Helper_Unit : out Ada_Qualified_Name; Override_Dump_Trigger : Any_Dump_Trigger := Manual; Has_Controlled : Boolean := False) is + Root_Prj_Name : constant String := + Project.Project.Root_Project.Name; + File : Text_Files.File_Type; procedure Put_With (Unit : Ada_Qualified_Name); @@ -7283,7 +7686,7 @@ package body Instrument.Ada_Unit is Dump_Trigger : constant Auto_Dump_Trigger := (if Override_Dump_Trigger = Manual - then IC.Dump_Config.Trigger + then Dump_Config.Trigger else Override_Dump_Trigger); -- Resolved dump trigger @@ -7301,7 +7704,7 @@ package body Instrument.Ada_Unit is declare use type Ada_Qualified_Name; Unit : constant String := - (case IC.Dump_Config.Channel is + (case Dump_Config.Channel is when Binary_File => "Files", when Base64_Standard_Output => "Base64"); begin @@ -7387,7 +7790,8 @@ package body Instrument.Ada_Unit is null; end case; - File.Put_Line ("with " & To_Ada (Buffers_List_Unit (IC)) & ";"); + File.Put_Line + ("with " & To_Ada (Buffers_List_Unit (Root_Prj_Name)) & ";"); File.Put_Line ("package body " & Helper_Unit_Name & " is"); File.New_Line; @@ -7401,8 +7805,9 @@ package body Instrument.Ada_Unit is File.Put_Line (" " & To_Ada (Output_Proc)); File.Put (" ("); - File.Put_Line (To_Ada (Buffers_List_Unit (IC)) & ".List,"); - case IC.Dump_Config.Channel is + File.Put_Line + (To_Ada (Buffers_List_Unit (Root_Prj_Name)) & ".List,"); + case Dump_Config.Channel is when Binary_File => declare use GNATCOLL.VFS; @@ -7412,23 +7817,21 @@ package body Instrument.Ada_Unit is Indent2 : constant String := Indent1 & " "; Env_Var : constant String := - (if Length (IC.Dump_Config.Filename_Env_Var) = 0 + (if Length (Dump_Config.Filename_Env_Var) = 0 then U & ".Default_Trace_Filename_Env_Var" - else """" & To_String (IC.Dump_Config.Filename_Env_Var) + else """" & To_String (Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := - (if Length (IC.Dump_Config.Filename_Prefix) = 0 + (if Length (Dump_Config.Filename_Prefix) = 0 then """" & String'(+Info.Project.Executable_Name - (File => +To_Filename - (Project => Info.Project, - CU_Name => Main, - Language => Switches.Ada_Language), + (File => +Main_Filename, Include_Suffix => True)) & """" - else """" & To_String (IC.Dump_Config.Filename_Prefix) + else """" & To_String (Dump_Config.Filename_Prefix) & """"); - Tag : constant String := """" & To_String (IC.Tag) & """"; + Tag : constant String := + """" & Trace_Filename_Tag & """"; Simple : constant String := - (if IC.Dump_Config.Filename_Simple + (if Dump_Config.Filename_Simple then "True" else "False"); begin @@ -7536,30 +7939,21 @@ package body Instrument.Ada_Unit is -- Emit_Buffers_List_Unit -- ---------------------------- - procedure Emit_Buffers_List_Unit + overriding procedure Emit_Buffers_List_Unit (Self : Ada_Instrumenter_Type; - IC : in out Inst_Context; - Root_Project_Info : in out Project_Info) + Root_Project_Info : in out Project_Info; + Instr_Units : CU_Name_Vectors.Vector) is - CU_Name : constant Compilation_Unit_Name := - CU_Name_For_Unit (Buffers_List_Unit (IC), GNATCOLL.Projects.Unit_Spec); - File : Text_Files.File_Type; - - Instr_Units : CU_Name_Vectors.Vector; + Prj_Name : constant String := Root_Project_Info.Project.Name; + CU_Name : constant Compilation_Unit_Name := + CU_Name_For_Unit + (Buffers_List_Unit (Prj_Name), GNATCOLL.Projects.Unit_Spec); + File : Text_Files.File_Type; begin - for Cur in IC.Instrumented_Units.Iterate loop - declare - Instr_Unit : constant Compilation_Unit_Name := - Instrumented_Unit_Maps.Key (Cur); - begin - Instr_Units.Append (Instr_Unit); - end; - end loop; - - -- Now emit the unit to contain the list of buffers + -- Emit the unit to contain the list of buffers declare - Unit_Name : constant String := To_Ada (CU_Name.Unit); + Unit_Name_Str : constant String := To_Ada (CU_Name.Unit); begin Create_File (Root_Project_Info, @@ -7585,7 +7979,7 @@ package body Instrument.Ada_Unit is end if; end loop; File.New_Line; - File.Put_Line ("package " & Unit_Name & " is"); + File.Put_Line ("package " & Unit_Name_Str & " is"); File.New_Line; File.Put_Line (" pragma Preelaborate;"); File.New_Line; @@ -7633,10 +8027,11 @@ package body Instrument.Ada_Unit is File.Put_Line (" pragma Export (C, C_List, """ - & Unit_Buffers_Array_Name (+IC.Project_Name) & """);"); + & Unit_Buffers_Array_Name (Prj_Name) + & """);"); File.New_Line; - File.Put_Line ("end " & Unit_Name & ";"); + File.Put_Line ("end " & Unit_Name_Str & ";"); end; end Emit_Buffers_List_Unit; @@ -7645,23 +8040,38 @@ package body Instrument.Ada_Unit is --------------------- overriding procedure Instrument_Unit - (Self : Ada_Instrumenter_Type; + (Self : in out Ada_Instrumenter_Type; CU_Name : Compilation_Unit_Name; - IC : in out Inst_Context; Unit_Info : in out Instrumented_Unit_Info) is Prj_Info : Project_Info renames Unit_Info.Prj_Info.all; UIC : Ada_Unit_Inst_Context; + + Event_Handler : Missing_Src_Reporter renames + Missing_Src_Reporter_Access (Self.Event_Handler.Unchecked_Get).all; + -- Handle to the event handler we use to report missing source files + + Filename : constant String := To_String (Unit_Info.Filename); + Basename : constant String := Ada.Directories.Simple_Name (Filename); begin + -- If we are in verbose mode, we already printed the source file that + -- we are about to instrument. Otherwise, just get prepared to print it + -- in case we emit a "source file missing" warning through Libadalang's + -- event handler. + + if not Verbose then + Event_Handler.Instrumented_File := To_Unbounded_String (Basename); + end if; + -- Instrument the source file and create a unit to contain its coverage -- buffers. Instrument_Source_File - (CU_Name => CU_Name, - Unit_Info => Unit_Info, - Prj_Info => Prj_Info, - IC => IC, - UIC => UIC); + (CU_Name => CU_Name, + Unit_Info => Unit_Info, + Prj_Info => Prj_Info, + Instrumenter => Self, + UIC => UIC); Emit_Buffer_Unit (Prj_Info, UIC); Emit_Pure_Buffer_Unit (Prj_Info, UIC); @@ -7670,4 +8080,100 @@ package body Instrument.Ada_Unit is Instrumented_Unit_CUs.Insert (CU_Name, UIC.CU); end Instrument_Unit; + procedure Find_Ada_Units + (Instrumenter : in out Ada_Instrumenter_Type; + CU_Name : Compilation_Unit_Name; + Info : GNATCOLL.Projects.File_Info; + Process_Unit : access procedure + (CU_Name : Compilation_Unit_Name; + Info : GNATCOLL.Projects.File_Info)) + is + use GNATCOLL.VFS; + + function Process_Node (N : LAL.Ada_Node'Class) return Visit_Status; + + ------------------ + -- Process_Node -- + ------------------ + + function Process_Node (N : LAL.Ada_Node'Class) return Visit_Status is + begin + if N.Kind in Ada_Body_Stub then + begin + declare + Stub : constant LAL.Body_Stub := N.As_Body_Stub; + Subunit_FQN : constant LAL.Unbounded_Text_Type_Array := + Stub.P_Syntactic_Fully_Qualified_Name; + Subunit_Name : constant Compilation_Unit_Name := + CU_Name_For_Unit + (Unit => To_Qualified_Name (Subunit_FQN), + Part => GPR.Unit_Separate); + Subunit_Info : GPR.File_Info; + begin + if Subunit_FQN'Length = 0 then + raise Property_Error; + elsif Unit_Info (Subunit_Name, Subunit_Info) then + Find_Ada_Units + (Instrumenter, + Subunit_Name, + Subunit_Info, + Process_Unit); + else + Warn ("cannot instrument " & Image (Subunit_Name) + & ": this unit does not belong to this project"); + end if; + end; + exception + when Property_Error => + -- TODO: location + Warn ("failed to locate the subunit for this stub"); + end; + return Over; + end if; + + return Into; + end Process_Node; + + Input_Filename : constant String := +Info.File.Full_Name; + Unit : constant LAL.Analysis_Unit := + Get_From_File (Instrumenter, Input_Filename); + begin + -- Abort if the input project is not compilable + + if Unit.Has_Diagnostics then + Outputs.Error ("instrumentation failed for " & Input_Filename); + Outputs.Error + ("please make sure the original project can be compiled"); + for D of Unit.Diagnostics loop + Outputs.Error (Unit.Format_GNU_Diagnostic (D)); + end loop; + raise Xcov_Exit_Exc; + end if; + + -- We cannot instrument files that contain only pragmas, but they are + -- still valid sources in the context of the GNAT runtime (for instance + -- g-os_lib.adb), so just ignore them. + + if Unit.Root.Kind = Ada_Pragma_Node_List then + return; + + -- Abort if a source file does not contain exactly one compilation + -- unit. + + elsif Unit.Root.Kind = Ada_Compilation_Unit_List then + Outputs.Error ("instrumentation failed for " & Input_Filename); + Outputs.Error ("source files containing multiple compilation units" + & " are not supported"); + raise Xcov_Exit_Exc; + end if; + + pragma Assert (Unit.Root.Kind = Ada_Compilation_Unit); + declare + CU : constant LAL.Compilation_Unit := Unit.Root.As_Compilation_Unit; + begin + Process_Unit (CU_Name, Info); + CU.Traverse (Process_Node'Access); + end; + end Find_Ada_Units; + end Instrument.Ada_Unit; diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 8046564a5..b10418ae2 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -24,6 +24,8 @@ with Ada.Strings.Unbounded; with Ada.Strings.Wide_Wide_Hash; with Ada.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; +with GNATCOLL.Projects; use GNATCOLL.Projects; + with Langkit_Support.Text; use Langkit_Support.Text; with Libadalang.Analysis; use Libadalang.Analysis; with Libadalang.Rewriting; use Libadalang.Rewriting; @@ -36,33 +38,65 @@ with Types; use Types; package Instrument.Ada_Unit is - type Ada_Instrumenter_Type is new Language_Instrumenter with - null record; + type Ada_Instrumenter_Type is new Language_Instrumenter + with record + Provider : Libadalang.Analysis.Unit_Provider_Reference; + -- Unit provider to create an analysis context (Context member below) + + Event_Handler : Libadalang.Analysis.Event_Handler_Reference; + -- Event handler to warn about missing source files + + Context : Libadalang.Analysis.Analysis_Context; + -- Libadalang context to load all units to rewrite + + Get_From_File_Count : Natural; + -- Count how many times we called Context.Get_From_File. See the + -- Max_Get_From_File_Count constant. + + Language_Version : Any_Language_Version; + -- See the eponym arguments in Instrument.Intrument_Units_Of_Interest + + end record; -- Instrumentation primitives for Ada + function Create_Ada_Instrumenter + (Provider : Unit_Provider_Reference; + Language_Version : Any_Language_Version) return Ada_Instrumenter_Type; + -- Create an Ada instrumenter from the given provider, and the given + -- language version. + overriding function Language (Self : Ada_Instrumenter_Type) return Switches.Src_Supported_Language is (Switches.Ada_Language); overriding procedure Instrument_Unit - (Self : Ada_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - IC : in out Inst_Context; - Unit_Info : in out Instrumented_Unit_Info); + (Self : in out Ada_Instrumenter_Type; + CU_Name : Compilation_Unit_Name; + Unit_Info : in out Instrumented_Unit_Info); overriding procedure Auto_Dump_Buffers_In_Main - (Self : Ada_Instrumenter_Type; - IC : in out Inst_Context; - Main : Compilation_Unit_Name; - Filename : String; - Info : in out Project_Info); + (Self : in out Ada_Instrumenter_Type; + Filename : String; + Instr_Units : CU_Name_Vectors.Vector; + Dump_Config : Any_Dump_Config; + Info : in out Project_Info); overriding procedure Emit_Buffers_List_Unit (Self : Ada_Instrumenter_Type; - IC : in out Inst_Context; - Root_Project_Info : in out Project_Info); - - Instrumenter : aliased constant Ada_Instrumenter_Type := (null record); + Root_Project_Info : in out Project_Info; + Instr_Units : CU_Name_Vectors.Vector); + + procedure Find_Ada_Units + (Instrumenter : in out Ada_Instrumenter_Type; + CU_Name : Compilation_Unit_Name; + Info : GNATCOLL.Projects.File_Info; + Process_Unit : access procedure + (CU_Name : Compilation_Unit_Name; + Info : GNATCOLL.Projects.File_Info)); + -- Consider that Info is a source file to instrument (i.e. a unit of + -- interest, CU_Name being the name of its compilation unit) and call + -- Process_Unit for all compilation units that must be instrumented with + -- it (i.e. related subunits, if present). -- Private declarations relative to the AST traversal private diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 76ed677cb..2f6764a38 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -356,7 +356,6 @@ package body Instrument.C is procedure Record_PP_Info (Unit_Info : Instrumented_Unit_Info; - IC : in out Inst_Context; UIC : in out C_Unit_Inst_Context); -- Emit the low-level SCOs for the given unit. Do not process them: this is -- left to the other (instrumentation) pass. @@ -366,7 +365,6 @@ package body Instrument.C is Unit_Info : Instrumented_Unit_Info; Instrumenter : C_Family_Instrumenter_Type'Class; Prj_Info : in out Project_Info; - IC : in out Inst_Context; UIC : out C_Unit_Inst_Context); -- Generate the instrumented source corresponding to CU_Name/Unit_Info. -- Record instrumentation information in IC. @@ -378,10 +376,6 @@ package body Instrument.C is -- Source instrumentation -- ---------------------------- - function Buffers_List_Filename (IC : Inst_Context) return String is - ("gnatcov_rts_c-buffers-lists-" & (+IC.Project_Name)); - -- Return the name of the unit containing the array of coverage buffers - procedure Emit_Buffer_Unit (Info : in out Project_Info; UIC : C_Unit_Inst_Context'Class; @@ -390,7 +384,7 @@ package body Instrument.C is -- unit, for the given instrumenter. procedure Emit_Dump_Helper_Unit - (IC : Inst_Context; + (Dump_Config : Any_Dump_Config; Info : in out Project_Info; Main : Compilation_Unit_Name; Helper_Unit : out US.Unbounded_String; @@ -419,20 +413,6 @@ package body Instrument.C is procedure Run_Diagnostics (TU : Translation_Unit_T); -- Output clang diagnostics on the given translation unit - procedure Auto_Dump_Buffers_In_Main - (IC : Inst_Context; - Info : in out Project_Info; - Main : Compilation_Unit_Name; - Rew : in out C_Source_Rewriter; - Instrumenter : C_Family_Instrumenter_Type'Class); - -- Common code for auto dump insertion in the "main" function, used in the - -- Auto_Dump_Buffers_In_Main primitive for C_Instrumenter_Type, and from - -- the Instrument_Source_File procedure. - -- - -- Arguments have the same semantics as in the Auto_Dump_Buffers_In_Main - -- primitive. The additional Rew argument is the C source rewriter that is - -- ready to use for the source file to instrument. - function Format_Str_Constant (Value : String) return String; -- Return a gnatcov_rts_string literal corresponding to Value @@ -1464,8 +1444,7 @@ package body Instrument.C is ------------------------- procedure Traverse_Statements - (IC : in out Inst_Context; - UIC : in out C_Unit_Inst_Context; + (UIC : in out C_Unit_Inst_Context; L : Cursor_Vectors.Vector; Trailing_Braces : out Unbounded_String); -- Process L, a list of statements or declarations. Set Trailing_Braces @@ -1473,8 +1452,7 @@ package body Instrument.C is -- list. procedure Traverse_Declarations - (IC : in out Inst_Context; - UIC : in out C_Unit_Inst_Context; + (UIC : in out C_Unit_Inst_Context; L : Cursor_Vectors.Vector); -- Traverse a translation unit (top level declarations) @@ -1971,8 +1949,7 @@ package body Instrument.C is ------------------------- procedure Traverse_Statements - (IC : in out Inst_Context; - UIC : in out C_Unit_Inst_Context; + (UIC : in out C_Unit_Inst_Context; L : Cursor_Vectors.Vector; Trailing_Braces : out Unbounded_String) is @@ -2052,7 +2029,8 @@ package body Instrument.C is when Cursor_Compound_Stmt => Set_Statement_Entry; - Traverse_Statements (IC, UIC, Get_Children (N), TB); + + Traverse_Statements (UIC, Get_Children (N), TB); -- If statement, which breaks the current statement sequence, but -- we include the condition in the current sequence. @@ -2067,7 +2045,7 @@ package body Instrument.C is Process_Decisions_Defer (Get_Cond (N), 'I'); Set_Statement_Entry; Traverse_Statements - (IC, UIC, To_Vector (Then_Part), TB); + (UIC, To_Vector (Then_Part), TB); -- Traverse the ELSE statements if present @@ -2080,7 +2058,7 @@ package body Instrument.C is (UIC.Rewriter, Get_Else_Loc (N), +TB); TB := +""; Traverse_Statements - (IC, UIC, To_Vector (Else_Part), TB); + (UIC, To_Vector (Else_Part), TB); end if; end; @@ -2098,7 +2076,7 @@ package body Instrument.C is -- Process case branches - Traverse_Statements (IC, UIC, To_Vector (Alt), TB); + Traverse_Statements (UIC, To_Vector (Alt), TB); end; -- Case alternative @@ -2107,8 +2085,7 @@ package body Instrument.C is declare Case_Body : constant Cursor_T := Get_Sub_Stmt (N); begin - Traverse_Statements - (IC, UIC, To_Vector (Case_Body), TB); + Traverse_Statements (UIC, To_Vector (Case_Body), TB); end; -- Loop ends the current statement sequence, but we include @@ -2135,8 +2112,7 @@ package body Instrument.C is Process_Decisions_Defer (Cond, 'W'); Set_Statement_Entry; - Traverse_Statements - (IC, UIC, To_Vector (While_Body), TB); + Traverse_Statements (UIC, To_Vector (While_Body), TB); end; -- Do while statement. Ends the current statement sequence. @@ -2147,8 +2123,7 @@ package body Instrument.C is Do_While : constant Cursor_T := Get_Cond (N); begin - Traverse_Statements - (IC, UIC, To_Vector (Do_Body), TB); + Traverse_Statements (UIC, To_Vector (Do_Body), TB); -- Insert the trailing braces resulting from the body -- traversal before the while. @@ -2187,8 +2162,7 @@ package body Instrument.C is Set_Statement_Entry; - Traverse_Statements - (IC, UIC, To_Vector (For_Body), TB); + Traverse_Statements (UIC, To_Vector (For_Body), TB); Extend_Statement_Sequence (For_Inc, ' ', Instr_Scheme => Instr_Expr); @@ -2220,8 +2194,7 @@ package body Instrument.C is -- Generate obligations for body statements - Traverse_Statements - (IC, UIC, To_Vector (For_Body), TB); + Traverse_Statements (UIC, To_Vector (For_Body), TB); end; -- Unconditional goto, which is included in the current statement @@ -2233,10 +2206,10 @@ package body Instrument.C is when Cursor_Label_Stmt => Set_Statement_Entry; - Traverse_Statements (IC, UIC, Get_Children (N), TB); + Traverse_Statements (UIC, Get_Children (N), TB); when Cursor_Stmt_Expr => - Traverse_Statements (IC, UIC, Get_Children (N), TB); + Traverse_Statements (UIC, Get_Children (N), TB); -- Null statement, we won't monitor their execution @@ -2266,8 +2239,7 @@ package body Instrument.C is -- scopes. Traverse_Declarations - (IC => IC, - UIC => UIC, + (UIC => UIC, L => Get_Lambda_Exprs (N)); end Traverse_One; @@ -2479,8 +2451,7 @@ package body Instrument.C is --------------------------- procedure Traverse_Declarations - (IC : in out Inst_Context; - UIC : in out C_Unit_Inst_Context; + (UIC : in out C_Unit_Inst_Context; L : Cursor_Vectors.Vector) is use Cursor_Vectors; @@ -2522,7 +2493,7 @@ package body Instrument.C is if Stmts.Length > 0 then UIC.MCDC_State_Declaration_Node := Stmts.First_Element; - Traverse_Statements (IC, UIC, Stmts, TB); + Traverse_Statements (UIC, Stmts, TB); UIC.Pass.Insert_Text_Before_Token (UIC.Rewriter, End_Sloc (Fun_Body), +TB); end if; @@ -2539,12 +2510,12 @@ package body Instrument.C is UIC.Pass.Enter_Scope (UIC, N); - Traverse_Declarations (IC, UIC, Get_Children (N)); + Traverse_Declarations (UIC, Get_Children (N)); UIC.Pass.Exit_Scope (UIC); when Cursor_Linkage_Spec => - Traverse_Declarations (IC, UIC, Get_Children (N)); + Traverse_Declarations (UIC, Get_Children (N)); when others => null; @@ -2840,6 +2811,16 @@ package body Instrument.C is begin PP_Filename := +New_File (Info, Filename); + -- The file may have been preprocessed already, if we are instrumenting + -- it as a main after having instrumented it as a source. In this case, + -- we should not preprocess it again (as it will fail). HACK: if the + -- original filename is an instrumented file (in which case it is + -- equal to PP_Filename), skip the preprocessing step. + + if +PP_Filename = Filename then + return; + end if; + Cmd := (Command => +Compiler_Driver (Info.Project, Instrumenter.Language), others => <>); @@ -3090,7 +3071,6 @@ package body Instrument.C is procedure Record_PP_Info (Unit_Info : Instrumented_Unit_Info; - IC : in out Inst_Context; UIC : in out C_Unit_Inst_Context) is Orig_Filename : constant String := +Unit_Info.Filename; @@ -3141,8 +3121,7 @@ package body Instrument.C is Free (C_Args); end; Traverse_Declarations - (IC => IC, - UIC => UIC, + (UIC => UIC, L => Get_Children (Get_Translation_Unit_Cursor (UIC.TU))); end Record_PP_Info; @@ -3156,7 +3135,6 @@ package body Instrument.C is Unit_Info : Instrumented_Unit_Info; Instrumenter : C_Family_Instrumenter_Type'Class; Prj_Info : in out Project_Info; - IC : in out Inst_Context; UIC : out C_Unit_Inst_Context) is Orig_Filename : constant String := +Unit_Info.Filename; @@ -3236,7 +3214,7 @@ package body Instrument.C is -- Start by recording preprocessing information - Record_PP_Info (Unit_Info, IC, UIC); + Record_PP_Info (Unit_Info, UIC); -- Then record exemption annotations in the comments. Reuse the TU from -- the preprocessing information recording pass as we want the @@ -3313,8 +3291,7 @@ package body Instrument.C is Start_Sloc (Get_Translation_Unit_Cursor (UIC.TU)); Traverse_Declarations - (IC => IC, - UIC => UIC, + (UIC => UIC, L => Get_Children (Get_Translation_Unit_Cursor (UIC.TU))); -- Check whether there is a mismatch between Last_SCO and @@ -3558,16 +3535,6 @@ package body Instrument.C is & " unsigned first," & " unsigned value"); - -- Insert automatic buffer dump calls, if requested - - if IC.Dump_Config.Trigger /= Manual and then Unit_Info.Is_Main then - Auto_Dump_Buffers_In_Main - (IC => IC, - Info => Prj_Info, - Main => UIC.Instrumented_Unit, - Rew => Rewriter, - Instrumenter => Instrumenter); - end if; Rewriter.Apply; end Instrument_Source_File; @@ -3875,7 +3842,7 @@ package body Instrument.C is --------------------------- procedure Emit_Dump_Helper_Unit - (IC : Inst_Context; + (Dump_Config : Any_Dump_Config; Info : in out Project_Info; Main : Compilation_Unit_Name; Helper_Unit : out US.Unbounded_String; @@ -3884,7 +3851,7 @@ package body Instrument.C is File : Text_Files.File_Type; Output_Proc : constant String := - (case IC.Dump_Config.Channel is + (case Dump_Config.Channel is when Binary_File => "gnatcov_rts_write_trace_file_wrapper", when Base64_Standard_Output => "gnatcov_rts_write_trace_file_base64"); @@ -3915,7 +3882,7 @@ package body Instrument.C is File.Put_Line ("#include ""gnatcov_rts_c_strings.h"""); - case IC.Dump_Config.Channel is + case Dump_Config.Channel is when Binary_File => File.Put_Line ("#include """ & "gnatcov_rts_c-traces-output-files.h"""); @@ -3932,7 +3899,7 @@ package body Instrument.C is (File, Instrumenter, "const struct gnatcov_rts_coverage_buffers_group_array", - Unit_Buffers_Array_Name (+IC.Project_Name)); + Unit_Buffers_Array_Name (Project.Project.Root_Project.Name)); -- Emit the procedure to write the trace file @@ -3942,25 +3909,28 @@ package body Instrument.C is File.Put_Line (Indent1 & Output_Proc & " ("); File.Put_Line - (Indent2 & "&" & Unit_Buffers_Array_Name (+IC.Project_Name) & ","); - case IC.Dump_Config.Channel is + (Indent2 & "&" + & Unit_Buffers_Array_Name (Project.Project.Root_Project.Name) + & ","); + case Dump_Config.Channel is when Binary_File => declare use GNATCOLL.VFS; Env_Var : constant String := - (if US.Length (IC.Dump_Config.Filename_Env_Var) = 0 + (if US.Length (Dump_Config.Filename_Env_Var) = 0 then "GNATCOV_RTS_DEFAULT_TRACE_FILENAME_ENV_VAR" - else """" & (+IC.Dump_Config.Filename_Env_Var) & """"); + else """" & (+Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := - (if US.Length (IC.Dump_Config.Filename_Prefix) = 0 + (if US.Length (Dump_Config.Filename_Prefix) = 0 then """" & String'(+Info.Project.Executable_Name (+(+Main.Filename), Include_Suffix => True)) & """" - else """" & (+IC.Dump_Config.Filename_Prefix) & """"); - Tag : constant String := """" & (+IC.Tag) & """"; + else """" & (+Dump_Config.Filename_Prefix) & """"); + Tag : constant String := + """" & Trace_Filename_Tag & """"; Simple : constant String := - (if IC.Dump_Config.Filename_Simple then "1" else "0"); + (if Dump_Config.Filename_Simple then "1" else "0"); begin File.Put_Line (Indent2 & "gnatcov_rts_default_trace_filename("); @@ -3999,53 +3969,57 @@ package body Instrument.C is -- Auto_Dump_Buffers_In_Main -- ------------------------------- - procedure Auto_Dump_Buffers_In_Main - (IC : Inst_Context; - Info : in out Project_Info; - Main : Compilation_Unit_Name; - Rew : in out C_Source_Rewriter; - Instrumenter : C_Family_Instrumenter_Type'Class) + overriding procedure Auto_Dump_Buffers_In_Main + (Self : in out C_Family_Instrumenter_Type; + Filename : String; + Instr_Units : CU_Name_Vectors.Vector; + Dump_Config : Any_Dump_Config; + Info : in out Project_Info) is - Instr_Units : constant CU_Name_Vectors.Vector := - Instr_Units_For_Closure (IC, Main); - -- List of names for instrumented units Helper_Filename : US.Unbounded_String; -- Name of file to contain helpers implementing the buffers dump - Insert_Extern_Location : constant Source_Location_T := - Start_Sloc (Get_Translation_Unit_Cursor (Rew.TU)); + Rew : C_Source_Rewriter; + Main : constant Compilation_Unit_Name := + (Language_Kind => File_Based_Language, + Filename => +Ada.Directories.Simple_Name (Filename), + Project_Name => +Info.Project.Name); + + Insert_Extern_Location : Source_Location_T; -- Where to insert extern declarations - Main_Cursor : constant Cursor_T := Get_Main (Rew.TU); + Main_Cursor : Cursor_T; -- Cursor of the main declaration begin - if Instr_Units.Is_Empty then - return; - end if; + Rew.Start_Rewriting (Info, Filename, Self); + Insert_Extern_Location := + Start_Sloc (Get_Translation_Unit_Cursor (Rew.TU)); + Main_Cursor := Get_Main (Rew.TU); if Main_Cursor = Get_Null_Cursor then Outputs.Fatal_Error ("Could not find main function in " & (+Main.Filename)); end if; - Emit_Dump_Helper_Unit (IC, Info, Main, Helper_Filename, Instrumenter); + Emit_Dump_Helper_Unit + (Dump_Config, Info, Main, Helper_Filename, Self); Put_Extern_Decl (Rew.Rewriter, Insert_Extern_Location, - Instrumenter, + Self, "void", Dump_Procedure_Symbol (Main), Func_Args => "void"); - if IC.Dump_Config.Trigger = Ravenscar_Task_Termination then + if Dump_Config.Trigger = Ravenscar_Task_Termination then Warn ("--dump-trigger=ravenscar-task-termination is not valid for a C" & " main. Defaulting to --dump-trigger=main-end for this" & " main."); end if; - case IC.Dump_Config.Trigger is + case Dump_Config.Trigger is when Main_End | Ravenscar_Task_Termination => declare use Cursor_Vectors; @@ -4148,7 +4122,7 @@ package body Instrument.C is Put_Extern_Decl (Rew.Rewriter, Insert_Extern_Location, - Instrumenter, + Self, "int", "atexit", Func_Args => "void (*function) (void)"); @@ -4176,19 +4150,6 @@ package body Instrument.C is when others => null; end case; - end Auto_Dump_Buffers_In_Main; - - overriding procedure Auto_Dump_Buffers_In_Main - (Self : C_Family_Instrumenter_Type; - IC : in out Inst_Context; - Main : Compilation_Unit_Name; - Filename : String; - Info : in out Project_Info) - is - Rew : C_Source_Rewriter; - begin - Rew.Start_Rewriting (Info, Filename, Self); - Auto_Dump_Buffers_In_Main (IC, Info, Main, Rew, Self); Rew.Apply; end Auto_Dump_Buffers_In_Main; @@ -4335,88 +4296,58 @@ package body Instrument.C is overriding procedure Emit_Buffers_List_Unit (Self : C_Family_Instrumenter_Type; - IC : in out Inst_Context; - Root_Project_Info : in out Project_Info) + Root_Project_Info : in out Project_Info; + Instr_Units : CU_Name_Vectors.Vector) is - Base_Filename : constant String := Buffers_List_Filename (IC); - CU_Name_Body : constant String := - Base_Filename + Project_Name : String renames Root_Project_Info.Project.Name; + CU_Name_Body : constant String := + "gnatcov_rts_c-buffers-lists-" & Project_Name & Source_Suffix (Self, GPR.Unit_Body, Root_Project_Info.Project); - CU_Name_Header : constant String := - Base_Filename - & Source_Suffix (Self, GPR.Unit_Spec, Root_Project_Info.Project); + File_Body : Text_Files.File_Type; - File_Body : Text_Files.File_Type; - File_Header : Text_Files.File_Type; - - Instr_Units : CU_Name_Vectors.Vector; + Buffer_Array_Decl : constant String := + "const struct gnatcov_rts_coverage_buffers_group_array " + & Unit_Buffers_Array_Name (Project_Name); + Buffer_Unit_Length : constant String := + Count_Type'Image (Instr_Units.Length); begin + -- Emit the body to contain the list of buffers - for Cur in IC.Instrumented_Units.Iterate loop - declare - Instr_Unit : constant Compilation_Unit_Name := - Instrumented_Unit_Maps.Key (Cur); - begin - Instr_Units.Append (Instr_Unit); - end; - end loop; - - declare - Buffer_Array_Decl : constant String := - "const struct gnatcov_rts_coverage_buffers_group_array " - & Unit_Buffers_Array_Name (+IC.Project_Name); - Buffer_Unit_Length : constant String := - Count_Type'Image (Instr_Units.Length); - begin - -- Emit the body to contain the list of buffers + Create_File (Root_Project_Info, File_Body, CU_Name_Body); - Create_File (Root_Project_Info, File_Body, CU_Name_Body); + File_Body.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); - File_Body.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); + -- First create extern declarations for the buffers group of each unit - -- First create extern declarations for the buffers group of each - -- unit. - - for Instr_Unit of Instr_Units loop - Put_Extern_Decl - (File_Body, - Self, - "const struct gnatcov_rts_coverage_buffers_group", - Unit_Buffers_Name (Instr_Unit)); - end loop; - - -- Then create an extern declaration for the buffer array (necessary - -- in C++ to set the C linkage), and finally the definition for that - -- array. - - File_Body.Put_Line (Self.Extern_Prefix & Buffer_Array_Decl & ";"); - File_Body.Put_Line (Buffer_Array_Decl & " = {"); - File_Body.Put_Line (" " & Buffer_Unit_Length & ","); - File_Body.Put_Line - (" (const struct gnatcov_rts_coverage_buffers_group *[]) {"); - for Cur in Instr_Units.Iterate loop - declare - use CU_Name_Vectors; - begin - File_Body.Put (" &" & Unit_Buffers_Name (Element (Cur))); - if To_Index (Cur) = Instr_Units.Last_Index then - File_Body.Put_Line ("}};"); - else - File_Body.Put_Line (","); - end if; - end; - end loop; - end; - - -- Emit the extern declaration of the buffers array in the header file + for Instr_Unit of Instr_Units loop + Put_Extern_Decl + (File_Body, + Self, + "const struct gnatcov_rts_coverage_buffers_group", + Unit_Buffers_Name (Instr_Unit)); + end loop; - Create_File (Root_Project_Info, File_Header, CU_Name_Header); + -- Then create an extern declaration for the buffer array (necessary + -- in C++ to set the C linkage), and finally the definition for that + -- array. - Put_Extern_Decl - (File_Header, - Self, - "const struct gnatcov_rts_coverage_buffers_group_array", - Unit_Buffers_Array_Name (+IC.Project_Name)); + File_Body.Put_Line (Self.Extern_Prefix & Buffer_Array_Decl & ";"); + File_Body.Put_Line (Buffer_Array_Decl & " = {"); + File_Body.Put_Line (" " & Buffer_Unit_Length & ","); + File_Body.Put_Line + (" (const struct gnatcov_rts_coverage_buffers_group *[]) {"); + for Cur in Instr_Units.Iterate loop + declare + use CU_Name_Vectors; + begin + File_Body.Put (" &" & Unit_Buffers_Name (Element (Cur))); + if To_Index (Cur) = Instr_Units.Last_Index then + File_Body.Put_Line ("}};"); + else + File_Body.Put_Line (","); + end if; + end; + end loop; end Emit_Buffers_List_Unit; --------------------- @@ -4424,9 +4355,8 @@ package body Instrument.C is --------------------- overriding procedure Instrument_Unit - (Self : C_Family_Instrumenter_Type; + (Self : in out C_Family_Instrumenter_Type; CU_Name : Compilation_Unit_Name; - IC : in out Inst_Context; Unit_Info : in out Instrumented_Unit_Info) is Prj_Info : Project_Info renames Unit_Info.Prj_Info.all; @@ -4437,7 +4367,6 @@ package body Instrument.C is Unit_Info => Unit_Info, Instrumenter => Self, Prj_Info => Prj_Info, - IC => IC, UIC => UIC); -- Generate a buffer compilation unit defining coverage buffers that diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index ef5316fcd..6d0c0c596 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -52,22 +52,21 @@ package Instrument.C is Source_File : GNATCOLL.Projects.File_Info) return Boolean; overriding procedure Instrument_Unit - (Self : C_Family_Instrumenter_Type; + (Self : in out C_Family_Instrumenter_Type; CU_Name : Compilation_Unit_Name; - IC : in out Inst_Context; Unit_Info : in out Instrumented_Unit_Info); overriding procedure Auto_Dump_Buffers_In_Main - (Self : C_Family_Instrumenter_Type; - IC : in out Inst_Context; - Main : Compilation_Unit_Name; - Filename : String; - Info : in out Project_Info); + (Self : in out C_Family_Instrumenter_Type; + Filename : String; + Instr_Units : CU_Name_Vectors.Vector; + Dump_Config : Any_Dump_Config; + Info : in out Project_Info); overriding procedure Emit_Buffers_List_Unit (Self : C_Family_Instrumenter_Type; - IC : in out Inst_Context; - Root_Project_Info : in out Project_Info); + Root_Project_Info : in out Project_Info; + Instr_Units : CU_Name_Vectors.Vector); function Extern_Prefix (Self : C_Family_Instrumenter_Type) return String @@ -94,9 +93,6 @@ package Instrument.C is (Self : CPP_Instrumenter_Type) return String is ("extern ""C"" "); - C_Instrumenter : aliased constant C_Instrumenter_Type := (null record); - CPP_Instrumenter : aliased constant CPP_Instrumenter_Type := (null record); - type Instr_Scheme_Type is (Instr_Stmt, Instr_Expr); -- Depending on the statement construct, we can instrument it either with -- another statement right before (Instr_Stmt), which is the case for most diff --git a/tools/gnatcov/instrument-c__stub.adb b/tools/gnatcov/instrument-c__stub.adb index 6b340c13b..104c74e96 100644 --- a/tools/gnatcov/instrument-c__stub.adb +++ b/tools/gnatcov/instrument-c__stub.adb @@ -35,9 +35,8 @@ package body Instrument.C is --------------------- procedure Instrument_Unit - (Self : C_Family_Instrumenter_Type; + (Self : in out C_Family_Instrumenter_Type; CU_Name : Compilation_Unit_Name; - IC : in out Inst_Context; Unit_Info : in out Instrumented_Unit_Info) is begin raise Program_Error with Error_Msg; @@ -48,11 +47,11 @@ package body Instrument.C is ------------------------------- procedure Auto_Dump_Buffers_In_Main - (Self : C_Family_Instrumenter_Type; - IC : in out Inst_Context; - Main : Compilation_Unit_Name; - Filename : String; - Info : in out Project_Info) is + (Self : in out C_Family_Instrumenter_Type; + Filename : String; + Instr_Units : CU_Name_Vectors.Vector; + Dump_Config : Any_Dump_Config; + Info : in out Project_Info) is begin raise Program_Error with Error_Msg; end Auto_Dump_Buffers_In_Main; @@ -61,10 +60,10 @@ package body Instrument.C is -- Emit_Buffers_List_Unit -- ---------------------------- - procedure Emit_Buffers_List_Unit + overriding procedure Emit_Buffers_List_Unit (Self : C_Family_Instrumenter_Type; - IC : in out Inst_Context; - Root_Project_Info : in out Project_Info) is + Root_Project_Info : in out Project_Info; + Instr_Units : CU_Name_Vectors.Vector) is begin raise Program_Error with Error_Msg; end Emit_Buffers_List_Unit; diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index cdff4928e..6ca434a58 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -41,22 +41,21 @@ package Instrument.C is Source_File : GNATCOLL.Projects.File_Info) return Boolean; overriding procedure Instrument_Unit - (Self : C_Family_Instrumenter_Type; + (Self : in out C_Family_Instrumenter_Type; CU_Name : Compilation_Unit_Name; - IC : in out Inst_Context; Unit_Info : in out Instrumented_Unit_Info); overriding procedure Auto_Dump_Buffers_In_Main - (Self : C_Family_Instrumenter_Type; - IC : in out Inst_Context; - Main : Compilation_Unit_Name; - Filename : String; - Info : in out Project_Info); + (Self : in out C_Family_Instrumenter_Type; + Filename : String; + Instr_Units : CU_Name_Vectors.Vector; + Dump_Config : Any_Dump_Config; + Info : in out Project_Info); overriding procedure Emit_Buffers_List_Unit (Self : C_Family_Instrumenter_Type; - IC : in out Inst_Context; - Root_Project_Info : in out Project_Info); + Root_Project_Info : in out Project_Info; + Instr_Units : CU_Name_Vectors.Vector); type C_Instrumenter_Type is new C_Family_Instrumenter_Type with null record; @@ -74,8 +73,8 @@ package Instrument.C is (Self : CPP_Instrumenter_Type) return Src_Supported_Language is (CPP_Language); - C_Instrumenter : aliased constant C_Instrumenter_Type := (null record); - CPP_Instrumenter : aliased constant CPP_Instrumenter_Type := (null record); + C_Instrumenter : aliased C_Instrumenter_Type := (null record); + CPP_Instrumenter : aliased CPP_Instrumenter_Type := (null record); procedure Postprocess_Source (Preprocessed_Filename : String; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index d5589f756..e12d83a29 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -16,26 +16,17 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Characters.Conversions; with Ada.Containers; use Ada.Containers; with Ada.Directories; -pragma Warnings (Off, "* is an internal GNAT unit"); -with Ada.Strings.Wide_Wide_Unbounded.Aux; -pragma Warnings (On, "* is an internal GNAT unit"); with Ada.Unchecked_Deallocation; -with Interfaces; with GNAT.OS_Lib; -with Langkit_Support.Symbols; -with Libadalang.Common; -with Libadalang.Config_Pragmas; -with Libadalang.Sources; +with Interfaces; with Coverage; with Diagnostics; with Hex_Images; -with Outputs; use Outputs; with Paths; use Paths; with Project; use Project; with SCOs; @@ -49,19 +40,6 @@ package body Instrument.Common is -- the name of the symbol for the entity that contains the address of a -- coverage buffer for Instrumented_Unit. - procedure Remove_Warnings_And_Style_Checks_Pragmas - (Rewriter : Source_Rewriter); - -- Remove all Warnings/Style_Checks pragmas in Rewriter's unit - - procedure Create_LAL_Context (IC : in out Inst_Context); - -- Create a new Libadalang analysis context for IC, assigning it to - -- IC.Context. - -- - -- This helper takes care of passing the unit provider and the event - -- handler that we need for all such contexts, and resets - -- IC.Get_From_File_Count to 0, as the new context has not been used to - -- instrument any source file yet. - function Next_Bit (Last_Bit : in out Any_Bit_Id) return Any_Bit_Id; -- Convenience function to allocate a new coverage buffer bit: increment -- Last_Bit and return the new Last_Bit. @@ -179,255 +157,38 @@ package body Instrument.Common is return To_String (Result); end Format_Fingerprint; - --------------------- - -- Start_Rewriting -- - --------------------- - - procedure Start_Rewriting - (Self : out Source_Rewriter; - IC : in out Inst_Context; - Info : in out Project_Info; - Input_Filename : String) - is - Base_Filename : constant String := - Ada.Directories.Simple_Name (Input_Filename); - Output_Filename : constant String := - To_String (Info.Output_Dir) / Base_Filename; - Unit : constant Analysis_Unit := - Get_From_File (IC, Input_Filename); - begin - if Unit.Has_Diagnostics then - Outputs.Error ("instrumentation failed for " & Input_Filename); - Outputs.Error ("please make sure the original project can be " - & "compiled"); - for D of Unit.Diagnostics loop - Outputs.Error (Unit.Format_GNU_Diagnostic (D)); - end loop; - raise Xcov_Exit_Exc; - end if; - - Self.Input_Filename := To_Unbounded_String (Input_Filename); - Self.Output_Filename := To_Unbounded_String (Output_Filename); - Self.Unit := Unit; - Self.Handle := Start_Rewriting (IC.Context); - end Start_Rewriting; - - -------------------- - -- Rewritten_Unit -- - -------------------- - - function Rewritten_Unit - (Self : Source_Rewriter) return Libadalang.Analysis.Analysis_Unit is - begin - return Self.Unit; - end Rewritten_Unit; - - ---------------------------------------------- - -- Remove_Warnings_And_Style_Checks_Pragmas -- - ---------------------------------------------- - - procedure Remove_Warnings_And_Style_Checks_Pragmas - (Rewriter : Source_Rewriter) - is - use Langkit_Support.Symbols; - use Libadalang.Common; - use Libadalang.Sources; - - function Should_Remove (Node : Node_Rewriting_Handle) return Boolean; - -- Return whether Node is a pragma Warnings or Style_Checks - - procedure Process (Node : Node_Rewriting_Handle); - -- Remove all pragma Warnings/Style_Checks statements from Node and its - -- children. - - ------------------- - -- Should_Remove -- - ------------------- - - function Should_Remove (Node : Node_Rewriting_Handle) return Boolean is - begin - if Kind (Node) /= Ada_Pragma_Node then - return False; - end if; - - declare - Symbol : constant Symbolization_Result := - Canonicalize (Text (Child (Node, 1))); - begin - return (Symbol.Success - and then Symbol.Symbol in "warnings" | "style_checks"); - end; - end Should_Remove; - - ------------- - -- Process -- - ------------- - - procedure Process (Node : Node_Rewriting_Handle) is - begin - if Node = No_Node_Rewriting_Handle then - return; - end if; - - -- Go through all children in reverse order so that we can remove - -- pragmas in one pass. - - for I in reverse 1 .. Children_Count (Node) loop - declare - Child : constant Node_Rewriting_Handle := - Libadalang.Rewriting.Child (Node, I); - begin - if Child /= No_Node_Rewriting_Handle - and then Should_Remove (Child) - then - Remove_Child (Node, I); - else - Process (Child); - end if; - end; - end loop; - end Process; - - -- Start of processing for Remove_Warnings_And_Style_Checks_Pragmas - - begin - Process (Handle (Rewriter.Unit.Root)); - end Remove_Warnings_And_Style_Checks_Pragmas; - - ----------- - -- Apply -- - ----------- - - procedure Apply (Self : in out Source_Rewriter) is - begin - -- Automatically insert pragmas to disable style checks and - -- warnings in generated code: it is not our goal to make - -- instrumentation generate warning-free or well-formatted - -- code. - - Remove_Warnings_And_Style_Checks_Pragmas (Self); - - declare - use Ada.Strings.Wide_Wide_Unbounded.Aux; - - Unit : constant Unit_Rewriting_Handle := Handle (Self.Unit); - Source : constant Unbounded_Wide_Wide_String := Unparse (Unit); - - -- To avoid copying the potentially big string for sources on the - -- secondary stack (and reduce the amount of copies anyway), use the - -- internal GNAT API to retreive the internal string access and - -- process it by chunks. - - Source_Access : Big_Wide_Wide_String_Access; - Length : Natural; - - Chunk_Size : constant := 4096; - Position : Natural; - - Filename : constant String := To_String (Self.Output_Filename); - Out_File : Text_Files.File_Type; - begin - Abort_Rewriting (Self.Handle); - Out_File.Create (Filename); - Put_Warnings_And_Style_Checks_Pragmas (Out_File); - - Get_Wide_Wide_String (Source, Source_Access, Length); - Position := Source_Access.all'First; - - while Position <= Length loop - declare - Chunk_First : constant Natural := Position; - Chunk_Last : constant Natural := Natural'Min - (Chunk_First + Chunk_Size - 1, Length); - - Chunk : Wide_Wide_String renames - Source_Access.all (Chunk_First .. Chunk_Last); - Encoded_Chunk : constant String := - Ada.Characters.Conversions.To_String (Chunk); - begin - Out_File.Put (Encoded_Chunk); - Position := Chunk_Last + 1; - end; - end loop; - - Out_File.Close; - if Switches.Pretty_Print then - Text_Files.Run_GNATpp (Out_File); - end if; - end; - - Self.Finalize; - end Apply; - - -------------- - -- Finalize -- - -------------- - - overriding procedure Finalize (Self : in out Source_Rewriter) is - begin - if Self.Handle /= No_Rewriting_Handle then - Abort_Rewriting (Self.Handle); - end if; - Self.Unit := No_Analysis_Unit; - end Finalize; - ------------------------ - -- Create_LAL_Context -- + -- Trace_Filename_Tag -- ------------------------ - procedure Create_LAL_Context (IC : in out Inst_Context) is - begin - IC.Context := Create_Context - (Unit_Provider => IC.Provider, - Event_Handler => IC.Event_Handler); - IC.Get_From_File_Count := 0; - - -- Load configuration pragmas - -- TODO??? Remove the type convertion when the LAL API change for - -- VA07-037 makes it into stable-libadalang. + function Trace_Filename_Tag return String + is + -- Compute the tag for default source trace filenames. Use the current + -- time as a mostly unique identifier. Put it in hexadecimal form + -- without leading zeros to avoid too long names. - Libadalang.Config_Pragmas.Import_From_Project - (IC.Context, GNATCOLL.Projects.Project_Tree (Project.Project.all)); - end Create_LAL_Context; + use Interfaces; + Time : constant Unsigned_64 := + Unsigned_64 (GNAT.OS_Lib.To_C (GNAT.OS_Lib.Current_Time)); + Tag : constant String := + Hex_Images.Strip_Zero_Padding + (Hex_Images.Hex_Image (Time)); + begin + return Tag; + end Trace_Filename_Tag; -------------------- -- Create_Context -- -------------------- function Create_Context - (Provider : Libadalang.Analysis.Unit_Provider_Reference; - Event_Handler : Libadalang.Analysis.Event_Handler_Reference; - Dump_Config : Any_Dump_Config; - Language_Version : Any_Language_Version; - Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context is + (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context is begin return IC : Inst_Context do IC.Project_Name := +Ada.Directories.Base_Name (Project.Root_Project_Filename); -- TODO??? Get the original casing for the project name - -- Compute the tag for default source trace filenames. Use the - -- current time as a mostly unique identifier. Put it in hexadecimal - -- form without leading zeros to avoid too long names. - - declare - use Interfaces; - - Time : constant Unsigned_64 := - Unsigned_64 (GNAT.OS_Lib.To_C (GNAT.OS_Lib.Current_Time)); - Tag : constant String := - Hex_Images.Strip_Zero_Padding (Hex_Images.Hex_Image (Time)); - begin - IC.Tag := +Tag; - end; - - IC.Provider := Provider; - IC.Event_Handler := Event_Handler; - Create_LAL_Context (IC); - - IC.Dump_Config := Dump_Config; - IC.Language_Version := Language_Version; - IC.Ignored_Source_Files_Present := Ignored_Source_Files /= null; if Ignored_Source_Files /= null then IC.Ignored_Source_Files := Ignored_Source_Files.all; @@ -472,26 +233,6 @@ package body Instrument.Common is Context.Project_Info_Map := Project_Info_Maps.Empty_Map; end Destroy_Context; - ------------------- - -- Get_From_File -- - ------------------- - - function Get_From_File - (IC : in out Inst_Context; - Filename : String) return Libadalang.Analysis.Analysis_Unit - is - begin - -- If we exceeded the maximum number of calls to Get_From_File, start - -- with a new context. - - if IC.Get_From_File_Count >= Max_Get_From_File_Count then - Create_LAL_Context (IC); - end if; - IC.Get_From_File_Count := IC.Get_From_File_Count + 1; - - return IC.Context.Get_From_File (Filename); - end Get_From_File; - ---------------------------- -- Is_Ignored_Source_File -- ---------------------------- @@ -586,34 +327,14 @@ package body Instrument.Common is Standard.Project.Project.Info (File); CU_Name : constant Compilation_Unit_Name := To_Compilation_Unit_Name (File_Info); - begin - -- If this main is already a unit of interest, no need to register it: - -- we will instrument it as part of our regular instrumentation process. - -- However, mains can be passed via the command line or in the GPR file - -- and we don't know which main to use when first registering units of - -- interest. Since every unit of interest is marked as not begin a main, - -- this information must be updated here by setting Is_Main accordingly. - - declare - C : constant Instrumented_Unit_Maps.Cursor := - Context.Instrumented_Units.Find (CU_Name); - begin - if Instrumented_Unit_Maps.Has_Element (C) then - Instrumented_Unit_Maps.Element (C).Is_Main := True; - return; - end if; - end; - - declare - Prj_Info : constant Project_Info_Access := - Get_Or_Create_Project_Info (Context, Project); - begin - Mains.Append - (Main_To_Instrument' - (CU_Name => CU_Name, - File => File, - Prj_Info => Prj_Info)); - end; + Prj_Info : constant Project_Info_Access := + Get_Or_Create_Project_Info (Context, Project); + begin + Mains.Append + (Main_To_Instrument' + (CU_Name => CU_Name, + File => File, + Prj_Info => Prj_Info)); end Register_Main_To_Instrument; --------------------------- @@ -641,9 +362,7 @@ package body Instrument.Common is return; end if; - -- Because different main files than those given in the GPR file can - -- be passed via command line, set Is_Main to false for every - -- file and decide which to use as mains accordingly later. + -- Otherwise, add it to the list of instrumented units declare Unit_Info : constant Instrumented_Unit_Info_Access := @@ -651,7 +370,6 @@ package body Instrument.Common is (Filename => To_Unbounded_String (+Source_File.File.Full_Name), Prj_Info => Get_Or_Create_Project_Info (Context, Project), - Is_Main => False, Language => To_Language (Source_File.Language)); begin Context.Instrumented_Units.Insert (CU_Name, Unit_Info); @@ -688,64 +406,6 @@ package body Instrument.Common is File.Create (Filename); end Create_File; - ------------------------------------------- - -- Put_Warnings_And_Style_Checks_Pragmas -- - ------------------------------------------- - - procedure Put_Warnings_And_Style_Checks_Pragmas - (File : in out Text_Files.File_Type) - is - begin - File.Put_Line ("pragma Style_Checks (Off); pragma Warnings (Off);"); - end Put_Warnings_And_Style_Checks_Pragmas; - - ----------------------------- - -- Unit_Requested_Callback -- - ----------------------------- - - overriding procedure Unit_Requested_Callback - (Self : in out Missing_Src_Reporter; - Context : Libadalang.Analysis.Analysis_Context'Class; - Name : Langkit_Support.Text.Text_Type; - From : Libadalang.Analysis.Analysis_Unit'Class; - Found : Boolean; - Is_Not_Found_Error : Boolean) - is - begin - -- We need to warn about sources that we could not find *and* whose - -- presence is mandated by Ada. - - if Found or else not Is_Not_Found_Error then - return; - end if; - - -- Warn for a given source file only once, as Libadalang can invoke this - -- callback several times. For clarity, only mention the base name, - -- which should be unique in Ada projects anyway. - - declare - N : constant Unbounded_String := To_Unbounded_String - (Ada.Directories.Simple_Name (Langkit_Support.Text.Image (Name))); - begin - if Self.Reported_Files.Contains (N) then - return; - end if; - - -- If we have not done it yet, clarify which file we were - -- instrumenting when we noticed that the source file N was missing. - - if Length (Self.Instrumented_File) > 0 then - Warn ("While instrumenting " - & To_String (Self.Instrumented_File) - & "..."); - Self.Instrumented_File := Null_Unbounded_String; - end if; - - Self.Reported_Files.Include (N); - Warn ("Cannot find required source file: " & To_String (N)); - end; - end Unit_Requested_Callback; - -------------- -- Next_Bit -- -------------- diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 6364648fb..3566d9980 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -58,13 +58,11 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Hash; with Ada.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; +with GNAT.Regexp; + with GNATCOLL.Projects; use GNATCOLL.Projects; with GNATCOLL.VFS; -with Langkit_Support.Text; -with Libadalang.Analysis; use Libadalang.Analysis; -with Libadalang.Rewriting; use Libadalang.Rewriting; - with ALI_Files; use ALI_Files; with Files_Table; use Files_Table; with GNATcov_RTS; @@ -176,6 +174,11 @@ package Instrument.Common is -- returned literal expression (aggregate in Ada, compound expression in -- C/C++). + function Trace_Filename_Tag return String; + -- Tag for the source trace filename. This allows differentiating trace + -- files produced by a specific program instrumentation from the ones + -- produced by other instrumentations. + package File_Sets is new Ada.Containers.Hashed_Sets (Element_Type => Ada.Strings.Unbounded.Unbounded_String, "=" => Ada.Strings.Unbounded."=", @@ -229,9 +232,6 @@ package Instrument.Common is -- Reference to the Project_Info record corresponding to the project -- that owns the source file for this unit. - Is_Main : Boolean; - -- Whether this unit is a main - Language : Some_Language; -- Language for this unit end record; @@ -242,54 +242,10 @@ package Instrument.Common is (Key_Type => Compilation_Unit_Name, Element_Type => Instrumented_Unit_Info_Access); - Max_Get_From_File_Count : constant := 50; - -- In addition to nodes and text buffers for each loaded unit, Libadalang - -- maintains caches in Analysis_Context objects so that semantic queries - -- are fast. This means that if we keep the same context to process a lot - -- of units, we end up with excessive memory consumption, which can trigger - -- heap exhaustion on big projects. - -- - -- Replacing an analysis context with a new one clears all the caches, but - -- makes semantic queries slower, as the units are re-loaded and caches are - -- re-populated as needed. - -- - -- To compromise between memory consumption and performance, we reset the - -- analysis context each Max_Get_From_File_Count number of calls to - -- Libadalang's Get_From_File function. - type Inst_Context is limited record Project_Name : Ada.Strings.Unbounded.Unbounded_String; -- Name of the root project. It is also used to name the list of buffers - Tag : Ada.Strings.Unbounded.Unbounded_String; - -- String which allows differentiating trace files produced by a - -- specific program instrumentation from the ones produced by other - -- instrumentations. - -- - -- To achieve this, Tag is based on the date/time at which the - -- instrumentation takes place. Automatic coverage buffer dumps (in - -- instrumented mains) will pass this string to - -- GNATcov_RTS.Traces.Output.Files.Default_Trace_Name (unless the - -- --dump-trace-filename-simple option is passed to "gnatcov - -- instrument"). - - Provider : Libadalang.Analysis.Unit_Provider_Reference; - -- Unit provider to create an analysis context (Context member below) - - Event_Handler : Libadalang.Analysis.Event_Handler_Reference; - -- Event handler to warn about missing source files - - Context : Libadalang.Analysis.Analysis_Context; - -- Libadalang context to load all units to rewrite - - Get_From_File_Count : Natural; - -- Count how many times we called Context.Get_From_File. See the - -- Max_Get_From_File_Count constant. - - Dump_Config : Any_Dump_Config; - Language_Version : Any_Language_Version; - -- See the eponym arguments in Instrument.Intrument_Units_Of_Interest - Ignored_Source_Files_Present : Boolean; Ignored_Source_Files : GNAT.Regexp.Regexp; -- If present, instrumentation will ignore files whose names match the @@ -305,21 +261,12 @@ package Instrument.Common is end record; function Create_Context - (Provider : Libadalang.Analysis.Unit_Provider_Reference; - Event_Handler : Libadalang.Analysis.Event_Handler_Reference; - Dump_Config : Any_Dump_Config; - Language_Version : Any_Language_Version; - Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context; + (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context; -- Create an instrumentation context for the currently loaded project procedure Destroy_Context (Context : in out Inst_Context); -- Free dynamically allocated resources in Context - function Get_From_File - (IC : in out Inst_Context; - Filename : String) return Libadalang.Analysis.Analysis_Unit; - -- Fetch the analysis unit for the given filename - function Is_Ignored_Source_File (Context : Inst_Context; Filename : String) return Boolean; -- Return whether the instrumentation process must ignore the Filename @@ -341,8 +288,7 @@ package Instrument.Common is (Context : in out Inst_Context; Mains : in out Main_To_Instrument_Vectors.Vector; File : GNATCOLL.VFS.Virtual_File; - Project : Project_Type) - with Pre => Context.Dump_Config.Trigger /= Manual; + Project : Project_Type); -- Register in Mains a main to be instrumented so that it dumps coverage -- buffers. File is the source file for this main, and Project is the -- project that owns this main. If File is actually a unit of interest in @@ -368,76 +314,6 @@ package Instrument.Common is -- Name can be a basename, a relative name or an absolute one: in all -- cases, the basename is taken and the file is created in Info.Output_Dir. - procedure Put_Warnings_And_Style_Checks_Pragmas - (File : in out Text_Files.File_Type); - -- Code generation helper: write "pragma Style_Checks (Off); pragma - -- Warnings (Off);" to File. - -- - -- This is useful when writing instrumented sources, as they may introduce - -- warnings and break the original codebase's coding style, and since some - -- projects are built with "warnings-as-errors" (GNAT's -gnatwe option), - -- this could mean that instrumentation breaks the build. When written at - -- the very beginning of each written source, these pragmas avoid this. - - type Missing_Src_Reporter is new Libadalang.Analysis.Event_Handler_Interface - with record - Instrumented_File : Unbounded_String; - -- Base name for the file that is currently instrumented. Reset to the - -- empty string everytime we print the "While instrumenting XXX ..." - -- message, so that we print it at most once per instrumented file. - - Reported_Files : String_Sets.Set; - -- Set of source file names which were already reported as missing. - -- Libadalang does not guarantee that the Unit_Requested event is - -- triggered only once per source, so de-duplicate events with this set. - end record; - -- Implementation of the Libadalang event handler interface used in - -- Create_Missing_File_Reporter. - - type Missing_Src_Reporter_Access is access all Missing_Src_Reporter; - - overriding procedure Release (Self : in out Missing_Src_Reporter) is null; - - overriding procedure Unit_Requested_Callback - (Self : in out Missing_Src_Reporter; - Context : Libadalang.Analysis.Analysis_Context'Class; - Name : Langkit_Support.Text.Text_Type; - From : Libadalang.Analysis.Analysis_Unit'Class; - Found : Boolean; - Is_Not_Found_Error : Boolean); - -- If the requested unit is not found and that is an error, warn about it. - -- Make sure we warn only once about a given source file. - - ------------------------- - -- Source instrumenter -- - ------------------------- - - type Source_Rewriter is tagged limited private; - -- Helper object to instrument a source file - - procedure Start_Rewriting - (Self : out Source_Rewriter; - IC : in out Inst_Context; - Info : in out Project_Info; - Input_Filename : String); - -- Start a rewriting session for the given Input_Filename. If the rewriting - -- process is successful, the result will be written to a file in - -- Info.Output_Dir with the basename of Output_Filename. - -- - -- This registers the output file in Info.Instr_Files. - -- - -- If there are parsing errors while reading Input_Filename, this raises a - -- fatal error and prints the corresponding error messages. - - function Rewritten_Unit - (Self : Source_Rewriter) return Libadalang.Analysis.Analysis_Unit; - -- Return the analysis unit for the source that Self instruments - - procedure Apply (Self : in out Source_Rewriter); - -- Write the instrumented source to the filename passed as Output_Filename - -- to Start_Rewriting. If rewriting failed, raise a fatal error and print - -- the corresponding error message. - ------------------------------------------------------ -- Common declarations for Ada / C instrumentation -- ------------------------------------------------------ @@ -655,10 +531,9 @@ package Instrument.Common is -- files). procedure Instrument_Unit - (Self : Language_Instrumenter; - CU_Name : Compilation_Unit_Name; - IC : in out Inst_Context; - Unit_Info : in out Instrumented_Unit_Info) is abstract; + (Self : in out Language_Instrumenter; + CU_Name : Compilation_Unit_Name; + Unit_Info : in out Instrumented_Unit_Info) is abstract; -- Instrument a single source file for the language that Self supports. -- -- CU_Name must be the name of the compilation unit for this source file, @@ -666,42 +541,26 @@ package Instrument.Common is -- this source file. procedure Auto_Dump_Buffers_In_Main - (Self : Language_Instrumenter; - IC : in out Inst_Context; - Main : Compilation_Unit_Name; - Filename : String; - Info : in out Project_Info) is abstract; - -- Try to instrument the Main/Filename source file (whose language is - -- assumed to be Self's) to insert a call to dump the list of coverage - -- buffers for all units of interest in Main's closure. Do nothing if not + (Self : in out Language_Instrumenter; + Filename : String; + Instr_Units : CU_Name_Vectors.Vector; + Dump_Config : Any_Dump_Config; + Info : in out Project_Info) is abstract; + -- Try to instrument the Filename source file (whose language is assumed + -- to be Self's) to insert a call to dump the list of coverage buffers for + -- all Instr_Units, according to the Dump_Config options. Do nothing if not -- successful. -- -- Info must be the Project_Info record corresponding to the project that - -- owns the Main unit. + -- owns Filename's compilation unit. procedure Emit_Buffers_List_Unit (Self : Language_Instrumenter; - IC : in out Inst_Context; - Root_Project_Info : in out Project_Info) is abstract; - -- Emit in the root project a unit (in Self's language) to contain the list - -- of coverage buffers for all units of interest. - -- + Root_Project_Info : in out Project_Info; + Instr_Units : CU_Name_Vectors.Vector) is abstract; -- The variable holding the list of coverage buffers is exported to a -- unique C symbol whose name is defined by the Unit_Buffers_Array_Name -- function. This procedure should thus be called only once, for one of -- the supported languages of the project. -private - - type Source_Rewriter is limited new Ada.Finalization.Limited_Controlled with - record - Input_Filename : Ada.Strings.Unbounded.Unbounded_String; - Output_Filename : Ada.Strings.Unbounded.Unbounded_String; - - Unit : Libadalang.Analysis.Analysis_Unit; - Handle : Libadalang.Rewriting.Rewriting_Handle; - end record; - - overriding procedure Finalize (Self : in out Source_Rewriter); - end Instrument.Common; diff --git a/tools/gnatcov/instrument-find_ada_units.adb b/tools/gnatcov/instrument-find_ada_units.adb deleted file mode 100644 index f30dff892..000000000 --- a/tools/gnatcov/instrument-find_ada_units.adb +++ /dev/null @@ -1,148 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2008-2022, 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.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; - -with GNATCOLL.VFS; use GNATCOLL.VFS; - -with Langkit_Support.Text; -with Libadalang.Analysis; -with Libadalang.Common; use Libadalang.Common; - -with Outputs; use Outputs; - -procedure Instrument.Find_Ada_Units - (IC : in out Inst_Context; - CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info; - Process_Unit : access procedure - (CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info)) -is - package LAL renames Libadalang.Analysis; - package GPR renames GNATCOLL.Projects; - - function To_Qualified_Name - (Name : Libadalang.Analysis.Unbounded_Text_Type_Array) - return Ada_Qualified_Name; - -- Convert a Libadalang fully qualified name into our format - - ----------------------- - -- To_Qualified_Name -- - ----------------------- - - function To_Qualified_Name - (Name : Libadalang.Analysis.Unbounded_Text_Type_Array) - return Ada_Qualified_Name - is - use Langkit_Support.Text; - begin - return Result : Ada_Qualified_Name do - for N of Name loop - - -- ??? Same limitation regarding non-ASCII characters as above - - Result.Append - (To_Unbounded_String (Image (To_Wide_Wide_String (N)))); - end loop; - end return; - end To_Qualified_Name; - - function Process_Node (N : LAL.Ada_Node'Class) return Visit_Status; - - ------------------ - -- Process_Node -- - ------------------ - - function Process_Node (N : LAL.Ada_Node'Class) return Visit_Status is - begin - if N.Kind in Ada_Body_Stub then - begin - declare - Stub : constant LAL.Body_Stub := N.As_Body_Stub; - Subunit_FQN : constant LAL.Unbounded_Text_Type_Array := - Stub.P_Syntactic_Fully_Qualified_Name; - Subunit_Name : constant Compilation_Unit_Name := - CU_Name_For_Unit - (Unit => To_Qualified_Name (Subunit_FQN), - Part => GPR.Unit_Separate); - Subunit_Info : GPR.File_Info; - begin - if Subunit_FQN'Length = 0 then - raise Property_Error; - elsif Unit_Info (Subunit_Name, Subunit_Info) then - Find_Ada_Units - (IC, Subunit_Name, Subunit_Info, Process_Unit); - else - Warn ("cannot instrument " & Image (Subunit_Name) - & ": this unit does not belong to this project"); - end if; - end; - exception - when Property_Error => - -- TODO: location - Warn ("failed to locate the subunit for this stub"); - end; - return Over; - end if; - - return Into; - end Process_Node; - - Input_Filename : constant String := +Info.File.Full_Name; - Unit : constant LAL.Analysis_Unit := - Get_From_File (IC, Input_Filename); - --- Start of processing for Instrument.Find_Units - -begin - -- Abort if the input project is not compilable - - if Unit.Has_Diagnostics then - Error ("instrumentation failed for " & Input_Filename); - Error ("please make sure the original project can be compiled"); - for D of Unit.Diagnostics loop - Error (Unit.Format_GNU_Diagnostic (D)); - end loop; - raise Xcov_Exit_Exc; - end if; - - -- We cannot instrument files that contain only pragmas, but they are still - -- valid sources in the context of the GNAT runtime (for instance - -- g-os_lib.adb), so just ignore them. - - if Unit.Root.Kind = Ada_Pragma_Node_List then - return; - - -- Abort if a source file does not contain exactly one compilation unit - - elsif Unit.Root.Kind = Ada_Compilation_Unit_List then - Error ("instrumentation failed for " & Input_Filename); - Error ("source files containing multiple compilation units are not" - & " supported"); - raise Xcov_Exit_Exc; - end if; - - pragma Assert (Unit.Root.Kind = Ada_Compilation_Unit); - declare - CU : constant LAL.Compilation_Unit := Unit.Root.As_Compilation_Unit; - begin - Process_Unit (CU_Name, Info); - CU.Traverse (Process_Node'Access); - end; -end Instrument.Find_Ada_Units; diff --git a/tools/gnatcov/instrument-find_ada_units.ads b/tools/gnatcov/instrument-find_ada_units.ads deleted file mode 100644 index feb6a5207..000000000 --- a/tools/gnatcov/instrument-find_ada_units.ads +++ /dev/null @@ -1,34 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2008-2022, 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 GNATCOLL.Projects; - -with Instrument.Common; use Instrument.Common; -with Instrument.Base_Types; use Instrument.Base_Types; - -procedure Instrument.Find_Ada_Units - (IC : in out Inst_Context; - CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info; - Process_Unit : access procedure - (CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info)); --- Consider that Info is a source file to instrument (i.e. a unit of interest, --- CU_Name being the name of its compilation unit) and call Process_Unit for --- all compilation units that must be instrumented with it (i.e. related --- subunits, if present). diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 4f07a81d5..2c6a6b4de 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -46,7 +46,6 @@ with Instrument.Base_Types; use Instrument.Base_Types; with Instrument.Clean_Objdirs; with Instrument.C; with Instrument.Common; use Instrument.Common; -with Instrument.Find_Ada_Units; with JSON; use JSON; with Outputs; with Paths; use Paths; @@ -56,12 +55,6 @@ with Switches; use Switches; package body Instrument is - Instrumenters : constant array (Src_Supported_Language) - of access constant Language_Instrumenter'Class := - (Ada_Language => Ada_Unit.Instrumenter'Access, - C_Language => C.C_Instrumenter'Access, - CPP_Language => C.CPP_Instrumenter'Access); - package GPR renames GNATCOLL.Projects; type CU_Name_With_Ignore is record @@ -320,6 +313,22 @@ package body Instrument is Provider : constant Unit_Provider_Reference := Instrument.Ada_Unit_Provider.Create_Provider_From_Project; + -- Initialize all the instrumenters + + Ada_Instrumenter : aliased Instrument.Ada_Unit.Ada_Instrumenter_Type := + Instrument.Ada_Unit.Create_Ada_Instrumenter + (Provider, Language_Version); + C_Instrumenter : aliased Instrument.C.C_Instrumenter_Type := + (null record); + CPP_Instrumenter : aliased Instrument.C.CPP_Instrumenter_Type := + (null record); + + Instrumenters : constant array (Src_Supported_Language) + of access Language_Instrumenter'Class := + (Ada_Language => Ada_Instrumenter'Access, + C_Language => C_Instrumenter'Access, + CPP_Language => CPP_Instrumenter'Access); + -- Create a map from library units to lists of compilation units to -- instrument for them. @@ -329,26 +338,12 @@ package body Instrument is Mains_To_Instrument : array (Src_Supported_Language) of Main_To_Instrument_Vectors.Vector; - -- For each supported language, list of mains to instrument *which are - -- not units of interest*. Always empty when Dump_Config.Trigger is - -- Manual. - -- - -- We need a separate list for these as mains which are units of - -- interest are instrumented to dump coverage buffers at the same time - -- they are instrumented to fill coverage buffers. - - -- Then create the instrumenter context - - IC : Inst_Context := Create_Context - (Provider, - Create_Event_Handler_Reference (Missing_Src_Reporter'(others => <>)), - Dump_Config, - Language_Version, - Ignored_Source_Files); - - Event_Handler : Missing_Src_Reporter renames - Missing_Src_Reporter_Access (IC.Event_Handler.Unchecked_Get).all; - -- Handle to the event handler we use to report missing source files + -- For each supported language, list of mains to instrument. Always + -- empty when Dump_Config.Trigger is Manual. + + -- Create the instrumenter context + + IC : Inst_Context := Create_Context (Ignored_Source_Files); Root_Project_Info : constant Project_Info_Access := Get_Or_Create_Project_Info (IC, Project.Project.Root_Project); @@ -445,8 +440,11 @@ package body Instrument is case CU_Name.Language_Kind is when Unit_Based_Language => - Find_Ada_Units - (IC, CU_Name, Source_File, Add_Instrumented_Unit'Access); + Instrument.Ada_Unit.Find_Ada_Units + (Ada_Instrumenter, + CU_Name, + Source_File, + Add_Instrumented_Unit'Access); when File_Based_Language => Add_Instrumented_Unit (CU_Name, Source_File); end case; @@ -581,23 +579,13 @@ package body Instrument is All_Externally_Built := False; - -- In verbose mode, always print a notice for the - -- source file that we are about to instrument. In - -- non-verbose mode, just get prepared to print it in - -- case we emit a "source file missing" warning - -- through Libadalang's event handler. + -- Run the instrumentation for this file if Verbose then Put_Line ("Instrumenting " & Basename); - else - Event_Handler.Instrumented_File := - To_Unbounded_String (Basename); end if; - - -- Run the instrumentation for this file - Instrumenters (Unit_Info.Language).Instrument_Unit - (CU.Name, IC, Unit_Info); + (CU.Name, Unit_Info); -- Update the Ignore_Status of the CU we instrumented @@ -676,38 +664,59 @@ package body Instrument is Outputs.Fatal_Error ("No unit to instrument."); end if; - -- Emit the unit to contain the list of coverage buffers, exported to a - -- C symbol, in one of the language supported by the project. - -- - -- Note that this has an implicit hack to it: if Ada is a language of - -- the project, it will pick it over the others (as it is the first - -- enumeration member of the Src_Supported_Language type). This matters - -- as we make the assumption in the Emit_Dump_Helper_Unit implementation - -- in instrument-ada_unit.adb (when instrumenting for an Ada main) that - -- the Ada package for buffers list units always exists: we need to - -- include it in the main closure, as it puts buffer units in scope - -- by importing them (otherwise they aren't as they are used through - -- C symbol importations). - - for Language in Src_Supported_Language loop - if Project.Project.Root_Project.Has_Language (Image (Language)) - then - Instrumenters (Language).Emit_Buffers_List_Unit - (IC, Root_Project_Info.all); - exit; - end if; - end loop; + declare + Instrumented_Units : Instrument.Common.CU_Name_Vectors.Vector; + -- List of instrumented units - -- Instrument all the mains that are not unit of interest to add the - -- dump of coverage buffers: Instrument_Unit already took care of mains - -- that are units of interest. + begin + for Cur in IC.Instrumented_Units.Iterate loop + Instrumented_Units.Append (Instrumented_Unit_Maps.Key (Cur)); + end loop; - for Language in Src_Supported_Language loop - for Main of Mains_To_Instrument (Language) loop - Instrumenters (Language).Auto_Dump_Buffers_In_Main - (IC, Main.CU_Name, +Main.File.Full_Name, Main.Prj_Info.all); + -- Emit the unit to contain the list of coverage buffers, exported to + -- a C symbol, in one of the language supported by the project. + -- + -- Note that this has an implicit hack to it: if Ada is a language of + -- the project, it will pick it over the others (as it is the first + -- enumeration member of the Src_Supported_Language type). This + -- matters as we make the assumption in the Emit_Dump_Helper_Unit + -- implementation in instrument-ada_unit.adb (when instrumenting for + -- an Ada main) that the Ada package for buffers list units always + -- exists: we need to include it in the main closure, as it puts + -- buffer units in scope by importing them (otherwise they aren't + -- as they are used through C symbol importations). + + for Language in Src_Supported_Language loop + if Project.Project.Root_Project.Has_Language (Image (Language)) + then + Instrumenters (Language).Emit_Buffers_List_Unit + (Root_Project_Info.all, Instrumented_Units); + exit; + end if; end loop; - end loop; + + -- Instrument all the mains to add the dump of coverage buffers. + -- Make sure to pass the instrumented version if the main is a unit + -- of interest. + + for Language in Src_Supported_Language loop + + for Main of Mains_To_Instrument (Language) loop + declare + Filename : constant String := + (if IC.Instrumented_Units.Contains (Main.CU_Name) + then (+Main.Prj_Info.Output_Dir) / (+Main.File.Base_Name) + else +Main.File.Full_Name); + begin + Instrumenters (Language).Auto_Dump_Buffers_In_Main + (Filename, + Instrumented_Units, + Dump_Config, + Main.Prj_Info.all); + end; + end loop; + end loop; + end; -- Deallocate Ignored_Unit_Infos diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 51049d2d1..446af1d14 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -73,6 +73,7 @@ package Instrument is -- GNATcov_RTS.Traces.Output.Files). -- -- Controlled by --dump-filename-prefix. + when others => null; end case; From ce12cbcade37ff8a0d4fd6c42b56104c74311067 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 20 Mar 2023 15:55:05 +0100 Subject: [PATCH 0211/1483] 14-unused-separate-compilable: new test Check that gnatcov does not instrument an orphan subunit, i.e. a subunit that is not referenced in its parent unit. --- .../compilable/src/pkg-bar.adb | 5 +++ .../14-unused-separate/compilable/test.py | 35 +++++++++++++++++++ .../tests/14-unused-separate/src/main.adb | 6 ++++ .../tests/14-unused-separate/src/pkg.adb | 3 ++ .../tests/14-unused-separate/src/pkg.ads | 4 +++ 5 files changed, 53 insertions(+) create mode 100644 testsuite/tests/14-unused-separate/compilable/src/pkg-bar.adb create mode 100644 testsuite/tests/14-unused-separate/compilable/test.py create mode 100644 testsuite/tests/14-unused-separate/src/main.adb create mode 100644 testsuite/tests/14-unused-separate/src/pkg.adb create mode 100644 testsuite/tests/14-unused-separate/src/pkg.ads diff --git a/testsuite/tests/14-unused-separate/compilable/src/pkg-bar.adb b/testsuite/tests/14-unused-separate/compilable/src/pkg-bar.adb new file mode 100644 index 000000000..130a667d6 --- /dev/null +++ b/testsuite/tests/14-unused-separate/compilable/src/pkg-bar.adb @@ -0,0 +1,5 @@ +separate (Pkg) +procedure Bar is +begin + null; +end Bar; diff --git a/testsuite/tests/14-unused-separate/compilable/test.py b/testsuite/tests/14-unused-separate/compilable/test.py new file mode 100644 index 000000000..5a8c06756 --- /dev/null +++ b/testsuite/tests/14-unused-separate/compilable/test.py @@ -0,0 +1,35 @@ +""" +Check that instrumenting a project that contains an "orphan" subunit (i.e. a +subunit never referenced in its parent unit) works as expected. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], + srcdirs=["../src", "../../src"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], +) + +thistest.fail_if( + os.path.exists("obj/gen-gnatcov-instr/pkg-bar.adb"), + "separate orphan unit instrumented", +) + +expected_cov = { + "main.adb.xcov": {"+": {5}}, + "pkg.ads.xcov": {"+": {2}}, + "pkg.adb.xcov": {"-": {2}}, +} +check_xcov_reports("*.xcov", expected_cov, "obj") + +thistest.result() diff --git a/testsuite/tests/14-unused-separate/src/main.adb b/testsuite/tests/14-unused-separate/src/main.adb new file mode 100644 index 000000000..f759cb8a0 --- /dev/null +++ b/testsuite/tests/14-unused-separate/src/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; +end Main; diff --git a/testsuite/tests/14-unused-separate/src/pkg.adb b/testsuite/tests/14-unused-separate/src/pkg.adb new file mode 100644 index 000000000..d66dec94e --- /dev/null +++ b/testsuite/tests/14-unused-separate/src/pkg.adb @@ -0,0 +1,3 @@ +package body Pkg is + procedure Bar is null; +end Pkg; diff --git a/testsuite/tests/14-unused-separate/src/pkg.ads b/testsuite/tests/14-unused-separate/src/pkg.ads new file mode 100644 index 000000000..0b1273231 --- /dev/null +++ b/testsuite/tests/14-unused-separate/src/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + procedure Foo is null; + procedure Bar; +end Pkg; From f8b2a8d0cf39d51f7feb653e8c3ffd12a94960b1 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 20 Mar 2023 15:55:59 +0100 Subject: [PATCH 0212/1483] 14-unused-separate-uncompilable: new test Check that gnatcov does not issue analysis warnings for an uncompilable orphan subunit. --- .../uncompilable/src/pkg-bar.adb | 1 + .../14-unused-separate/uncompilable/test.opt | 1 + .../14-unused-separate/uncompilable/test.py | 36 +++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 testsuite/tests/14-unused-separate/uncompilable/src/pkg-bar.adb create mode 100644 testsuite/tests/14-unused-separate/uncompilable/test.opt create mode 100644 testsuite/tests/14-unused-separate/uncompilable/test.py diff --git a/testsuite/tests/14-unused-separate/uncompilable/src/pkg-bar.adb b/testsuite/tests/14-unused-separate/uncompilable/src/pkg-bar.adb new file mode 100644 index 000000000..98c680c56 --- /dev/null +++ b/testsuite/tests/14-unused-separate/uncompilable/src/pkg-bar.adb @@ -0,0 +1 @@ +uncompilable unit diff --git a/testsuite/tests/14-unused-separate/uncompilable/test.opt b/testsuite/tests/14-unused-separate/uncompilable/test.opt new file mode 100644 index 000000000..9f9485829 --- /dev/null +++ b/testsuite/tests/14-unused-separate/uncompilable/test.opt @@ -0,0 +1 @@ +src-traces XFAIL Unsupported with instrumentation for now, fix in #18 diff --git a/testsuite/tests/14-unused-separate/uncompilable/test.py b/testsuite/tests/14-unused-separate/uncompilable/test.py new file mode 100644 index 000000000..80707d165 --- /dev/null +++ b/testsuite/tests/14-unused-separate/uncompilable/test.py @@ -0,0 +1,36 @@ +""" +Check that instrumenting a project that contains an "orphan" subunit (i.e. a +subunit never referenced in its parent unit) that does not compile works as +expected, i.e. does not issue analysis warnings at `gnatcov instrument` time. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], + srcdirs=["../src", "../../src"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], +) + +thistest.fail_if( + os.path.exists("obj/gen-gnatcov-instr/pkg-bar.adb"), + "separate orphan unit instrumented", +) + +expected_cov = { + "main.adb.xcov": {"+": {5}}, + "pkg.ads.xcov": {"+": {2}}, + "pkg.adb.xcov": {"-": {2}}, +} +check_xcov_reports("*.xcov", expected_cov, "obj") + +thistest.result() From f5c2716291ed6014e273bed365c747c1ae055e46 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 21 Mar 2023 14:39:22 +0100 Subject: [PATCH 0213/1483] Fix regression with 32 bits configurations To have proper report messages, we need to postprocess the source files at `gnatcov coverage` time to match expected source locations computed by `gnatcov instrument`. This postprocessing was done by the Postprocess_Source function defined in the Instrument.C unit. This unit is now stubbed for 32-bits configurations (which we do not need instrumentation for), and the stubbed version of the procedure was not doing anything. In practice, this meant that retrieving code lines from this non-existing postprocess file yielded empty strings, resulting in missing information from the report when the code resulted from a macro expansion. --- tools/gnatcov/annotations.adb | 3 +- tools/gnatcov/files_table.adb | 101 ++++++++++++++++++++++++++++++++- tools/gnatcov/files_table.ads | 25 ++++++++ tools/gnatcov/instrument-c.adb | 94 ------------------------------ tools/gnatcov/instrument-c.ads | 23 -------- 5 files changed, 124 insertions(+), 122 deletions(-) diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index feab9f492..b81a25a51 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -32,7 +32,6 @@ with Coverage.Object; with Coverage.Source; use Coverage.Source; with Coverage.Tags; with Instrument.Base_Types; -with Instrument.C; with Outputs; use Outputs; with Subprocesses; with Switches; use Switches; @@ -737,7 +736,7 @@ package body Annotations is -- need to recompute there to have the right version -- of the source. - Instrument.C.Postprocess_Source + Postprocess_Source (Preprocessed_Filename, Postprocessed_Filename); Preprocessed_SFI := Get_Index_From_Generic_Name diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index ec1e45c90..050504b88 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -25,7 +25,7 @@ with System; with System.Address_To_Access_Conversions; with GNAT.OS_Lib; -with GNAT.Regpat; +with GNAT.Regpat; use GNAT.Regpat; with Osint; with GNATCOLL.VFS; use GNATCOLL.VFS; @@ -36,6 +36,7 @@ with Coverage; use Coverage; with Outputs; with Perf_Counters; use Perf_Counters; with Project; +with Strings; with Switches; package body Files_Table is @@ -297,7 +298,6 @@ package body Files_Table is ----------------------- procedure Add_Source_Rebase (Old_Prefix : String; New_Prefix : String) is - use GNAT.Regpat; E : Source_Rebase_Entry_Acc; Regexp : constant String := "^" & Paths.Glob_To_Regexp (Old_Prefix); @@ -1602,7 +1602,6 @@ package body Files_Table is -- Try to rebase (--source-rebase) declare - use GNAT.Regpat; E : Source_Rebase_Entry_Acc := First_Source_Rebase_Entry; Name : constant String := Name_For_Rebase (File); @@ -2199,4 +2198,100 @@ package body Files_Table is end loop; end Checkpoint_Load; + ------------------------ + -- Postprocess_Source -- + ------------------------ + + procedure Postprocess_Source + (Preprocessed_Filename : String; + Postprocessed_Filename : String) + is + use Ada.Strings.Unbounded; + use Strings; + Preprocessed_File : Ada.Text_IO.File_Type; + Postprocessed_File : Ada.Text_IO.File_Type; + begin + Open (Preprocessed_File, In_File, Preprocessed_Filename); + Create (Postprocessed_File, Out_File, Postprocessed_Filename); + declare + Line_Marker_Pattern : constant GNAT.Regpat.Pattern_Matcher := + Compile + ("\s*#\s*" + -- Start of the line directive + + & "([0-9]+)" + -- Line index + + & "\s+" + & "([^ \s]+)" + -- Filename + + & "(.*)" + -- Trailing flags; + + ); + + Add_New_Line : Boolean := True; + + Line_Marker_Line : Integer; + Line_Marker_File : Unbounded_String; + -- Line and file of the read line if it is a line marker + + Current_File : Unbounded_String; + Current_Line : Integer := 0; + -- Line and file of the currently-active line marker + + Matches : Match_Array (0 .. 3); + begin + while not End_Of_File (Preprocessed_File) loop + declare + Line : constant String := Get_Line (Preprocessed_File); + begin + Match (Line_Marker_Pattern, Line, Matches); + if Matches (0) /= No_Match then + Line_Marker_Line := + Integer'Value + (Line (Matches (1).First .. Matches (1).Last)); + Line_Marker_File := + +Line (Matches (2).First .. Matches (2).Last); + if Line_Marker_Line = Current_Line - 1 + and then Line_Marker_File = Current_File + then + -- We have a spurious line marker. Remove it, and write + -- the next line in continuation of the previous line. + + Add_New_Line := False; + Current_Line := Current_Line - 1; + else + -- Write this line marker, and set the current line and + -- the current file. + + Current_Line := Line_Marker_Line; + Current_File := Line_Marker_File; + + -- Line markers should always be inserted on their own + -- line. + + Add_New_Line := True; + New_Line (Postprocessed_File); + Put (Postprocessed_File, Line); + end if; + else + if Add_New_Line then + New_Line (Postprocessed_File); + end if; + Add_New_Line := True; + Put (Postprocessed_File, Line); + Current_Line := Current_Line + 1; + end if; + end; + end loop; + if Add_New_Line then + New_Line (Postprocessed_File); + end if; + end; + Close (Preprocessed_File); + Close (Postprocessed_File); + end Postprocess_Source; + end Files_Table; diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 49ce8a20d..6f5f637bd 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -572,6 +572,31 @@ package Files_Table is -- Ignore_Source_Files should be null if the checkpoint purpose is -- Consolidation. + procedure Postprocess_Source + (Preprocessed_Filename : String; + Postprocessed_Filename : String); + -- Specific to the C instrumentation. + -- + -- Postprocess the given Preprocessed_Filename to remove redundant line + -- markers. This is done to keep the following invariant intact: we must + -- be able to use presumed source locations to have unique SCOs source + -- locations. As a reminder, presumed locations are computed through + -- preprocessor-inserted line markers. + -- + -- This means that the following code: + -- # 1 main.c + -- int a; + -- # 1 main.c 3 + -- int ab; + -- + -- will be rewritten to + -- # 1 main.c + -- int a; int ab; + -- + -- Note that this will remove the "system header "flag (the "3" at the + -- end of the line marker). We expect that this won't be a problem in + -- practice. + private -- Describe a source file - one element per line diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 2f6764a38..81015950a 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2683,100 +2683,6 @@ package body Instrument.C is return Macro_Set_Cst_Access (Result); end Builtin_Macros; - ------------------------ - -- Postprocess_Source -- - ------------------------ - - procedure Postprocess_Source - (Preprocessed_Filename : String; - Postprocessed_Filename : String) - is - Preprocessed_File : Ada.Text_IO.File_Type; - Postprocessed_File : Ada.Text_IO.File_Type; - begin - Open (Preprocessed_File, In_File, Preprocessed_Filename); - Create (Postprocessed_File, Out_File, Postprocessed_Filename); - declare - Line_Marker_Pattern : constant GNAT.Regpat.Pattern_Matcher := - Compile - ("\s*#\s*" - -- Start of the line directive - - & "([0-9]+)" - -- Line index - - & "\s+" - & "([^ \s]+)" - -- Filename - - & "(.*)" - -- Trailing flags; - - ); - - Add_New_Line : Boolean := True; - - Line_Marker_Line : Integer; - Line_Marker_File : Unbounded_String; - -- Line and file of the read line if it is a line marker - - Current_File : Unbounded_String; - Current_Line : Integer := 0; - -- Line and file of the currently-active line marker - - Matches : Match_Array (0 .. 3); - begin - while not End_Of_File (Preprocessed_File) loop - declare - Line : constant String := Get_Line (Preprocessed_File); - begin - Match (Line_Marker_Pattern, Line, Matches); - if Matches (0) /= No_Match then - Line_Marker_Line := - Integer'Value - (Line (Matches (1).First .. Matches (1).Last)); - Line_Marker_File := - +Line (Matches (2).First .. Matches (2).Last); - if Line_Marker_Line = Current_Line - 1 - and then Line_Marker_File = Current_File - then - -- We have a spurious line marker. Remove it, and write - -- the next line in continuation of the previous line. - - Add_New_Line := False; - Current_Line := Current_Line - 1; - else - -- Write this line marker, and set the current line and - -- the current file. - - Current_Line := Line_Marker_Line; - Current_File := Line_Marker_File; - - -- Line markers should always be inserted on their own - -- line. - - Add_New_Line := True; - New_Line (Postprocessed_File); - Put (Postprocessed_File, Line); - end if; - else - if Add_New_Line then - New_Line (Postprocessed_File); - end if; - Add_New_Line := True; - Put (Postprocessed_File, Line); - Current_Line := Current_Line + 1; - end if; - end; - end loop; - if Add_New_Line then - New_Line (Postprocessed_File); - end if; - end; - Close (Preprocessed_File); - Close (Postprocessed_File); - end Postprocess_Source; - ----------------------- -- Preprocess_Source -- ----------------------- diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 6d0c0c596..3f3a98025 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -399,29 +399,6 @@ package Instrument.C is -- UIC.Sources_Of_Interest. Return whether this source file is a source of -- interest. - procedure Postprocess_Source - (Preprocessed_Filename : String; - Postprocessed_Filename : String); - -- Postprocess the given Preprocessed_Filename to remove redundant line - -- markers. This is done to keep the following invariant intact: we must - -- be able to use presumed source locations to have unique SCOs source - -- locations. As a reminder, presumed locations are computed through - -- preprocessor-inserted line markers. - -- - -- This means that the following code: - -- # 1 main.c - -- int a; - -- # 1 main.c 3 - -- int ab; - -- - -- will be rewritten to - -- # 1 main.c - -- int a; int ab; - -- - -- Note that this will remove the "system header "flag (the "3" at the - -- end of the line marker). We expect that this won't be a problem in - -- practice. - private function Find_Instrumented_Entities From d460e51ad342b4cdb64207fc4f3b36d14f6c830c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 20 Mar 2023 16:51:22 +0100 Subject: [PATCH 0214/1483] tests/instr-cov/file-context: avoid a spurious instrumentation warning TN: W213-002 --- testsuite/tests/instr-cov/file-context/main.adb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/tests/instr-cov/file-context/main.adb b/testsuite/tests/instr-cov/file-context/main.adb index 48c2672b7..1801cb505 100644 --- a/testsuite/tests/instr-cov/file-context/main.adb +++ b/testsuite/tests/instr-cov/file-context/main.adb @@ -1,3 +1,5 @@ +with Ada.Text_IO; use Ada.Text_IO; + with Pkg; with Missing_A; From 37a87373edcef33b13e2d111e3150fc4ad4d1e56 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 21 Mar 2023 14:57:56 +0100 Subject: [PATCH 0215/1483] Files_Table: add missing documentation for parameter TN: W321-029 --- tools/gnatcov/files_table.ads | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 6f5f637bd..729aea7ee 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -109,6 +109,10 @@ package Files_Table is -- -- Windows-looking absolute filenames are canonicalized by upper casing the -- drive letter and lower casing all other letters. + -- + -- If Insert_After_Freeze is True, allow the inserting after the files + -- table has been frozen. Note that this breaks the uniqueness invariant + -- of names returned by Get_Unique_Name. procedure Consolidate_File_Kind (Index : Valid_Source_File_Index; From 94f565acfedba999991be1d935f199a2c30d3d01 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 21 Mar 2023 15:00:19 +0100 Subject: [PATCH 0216/1483] Annotations: fix logic error We preprocess and postprocess the source file when slocs refer into macro expansion locations. A logic error resulted in doing that every time it was needed to access a macro expansion loc, which is very unefficient. Fix that. TN: W321-029 --- .../tests/duplicate_postprocess/test.opt | 1 + testsuite/tests/duplicate_postprocess/test.py | 28 +++++++++++++++++++ .../tests/duplicate_postprocess/test_macros.c | 18 ++++++++++++ tools/gnatcov/annotations.adb | 14 +++++----- 4 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 testsuite/tests/duplicate_postprocess/test.opt create mode 100644 testsuite/tests/duplicate_postprocess/test.py create mode 100644 testsuite/tests/duplicate_postprocess/test_macros.c diff --git a/testsuite/tests/duplicate_postprocess/test.opt b/testsuite/tests/duplicate_postprocess/test.opt new file mode 100644 index 000000000..ae9029965 --- /dev/null +++ b/testsuite/tests/duplicate_postprocess/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Test specific to instrumentation diff --git a/testsuite/tests/duplicate_postprocess/test.py b/testsuite/tests/duplicate_postprocess/test.py new file mode 100644 index 000000000..e1b298e73 --- /dev/null +++ b/testsuite/tests/duplicate_postprocess/test.py @@ -0,0 +1,28 @@ +""" +Regression test: check that we do not preprocess multiple times a file at +coverage time. +""" + +import re + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], + mains=["test_macros.c"])), + covlevel="stmt+mcdc", + mains=["test_macros"], + extra_coverage_args=["--annotate=xcov+", "-v"] +) + +thistest.fail_if( + len(re.findall("gcc -E", contents_of("coverage.log"))) != 1, + "source file was preprocessed multiple times" +) + +thistest.result() diff --git a/testsuite/tests/duplicate_postprocess/test_macros.c b/testsuite/tests/duplicate_postprocess/test_macros.c new file mode 100644 index 000000000..44d905d12 --- /dev/null +++ b/testsuite/tests/duplicate_postprocess/test_macros.c @@ -0,0 +1,18 @@ +#include + +#define PRINT_HW printf ("Hello world!\n"); + +// Code that is not covered to have coverage violations for code inside macro +// expansions. +void +macro_stmts () +{ + PRINT_HW; + PRINT_HW; +} + +int +main () +{ + return 0; +} diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index b81a25a51..67b5b0edd 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -708,13 +708,13 @@ package body Annotations is Preprocessed_Filename : constant String := Get_PP_Filename (SFI) & ".prepro"; Postprocessed_Filename : constant String := Get_PP_Filename (SFI); - Preprocessed_SFI : Source_File_Index := + Postprocessed_SFI : Source_File_Index := Get_Index_From_Generic_Name - (Preprocessed_Filename, + (Postprocessed_Filename, Source_File, Insert => False); begin - if Preprocessed_SFI = No_Source_File then + if Postprocessed_SFI = No_Source_File then declare use Instrument.Base_Types; use Subprocesses; @@ -738,7 +738,7 @@ package body Annotations is Postprocess_Source (Preprocessed_Filename, Postprocessed_Filename); - Preprocessed_SFI := + Postprocessed_SFI := Get_Index_From_Generic_Name (Postprocessed_Filename, Source_File, @@ -754,10 +754,10 @@ package body Annotations is end; end if; - if Preprocessed_SFI /= No_Source_File then - Sloc_Start.Source_File := Preprocessed_SFI; + if Postprocessed_SFI /= No_Source_File then + Sloc_Start.Source_File := Postprocessed_SFI; Sloc_Start.L := Info.PP_Source_Range.First_Sloc; - Sloc_End.Source_File := Preprocessed_SFI; + Sloc_End.Source_File := Postprocessed_SFI; Sloc_End.L := Info.PP_Source_Range.Last_Sloc; end if; end; From b007558120b9f603edd1ffe1871dc057d779db1c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 23 Mar 2023 10:54:24 +0100 Subject: [PATCH 0217/1483] duplicate_postprocess: fix gcc exec name for windows TN: W321-029 --- testsuite/tests/duplicate_postprocess/test.py | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/testsuite/tests/duplicate_postprocess/test.py b/testsuite/tests/duplicate_postprocess/test.py index e1b298e73..9ca45b0b0 100644 --- a/testsuite/tests/duplicate_postprocess/test.py +++ b/testsuite/tests/duplicate_postprocess/test.py @@ -6,6 +6,7 @@ import re from SCOV.minicheck import build_run_and_coverage +from SUITE.control import env from SUITE.cutils import contents_of, Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor, thistest @@ -13,16 +14,22 @@ Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], - mains=["test_macros.c"])), + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["test_macros.c"]) + ), covlevel="stmt+mcdc", mains=["test_macros"], - extra_coverage_args=["--annotate=xcov+", "-v"] + extra_coverage_args=["--annotate=xcov+", "-v"], ) thistest.fail_if( - len(re.findall("gcc -E", contents_of("coverage.log"))) != 1, - "source file was preprocessed multiple times" + len( + re.findall( + f"gcc{env.build.os.exeext} -E", contents_of("coverage.log") + ) + ) + != 1, + "source file was preprocessed multiple times", ) thistest.result() From 4077adc0f044a82b00c6dfbe062f97b88c598e81 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 23 Mar 2023 12:11:56 +0000 Subject: [PATCH 0218/1483] tests/instr-cov/file-context: minor typo fix --- testsuite/tests/instr-cov/file-context/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/instr-cov/file-context/test.py b/testsuite/tests/instr-cov/file-context/test.py index dff6fbf0e..24a8d3186 100644 --- a/testsuite/tests/instr-cov/file-context/test.py +++ b/testsuite/tests/instr-cov/file-context/test.py @@ -14,7 +14,7 @@ Wdir("tmp_") -# Create the object direcotry to avoid spurious notices +# Create the object directory to avoid spurious notices gprsw = GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])) mkdir("obj") From 69b8dbbee19c13c243e5cc231ac7870013fe471c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 3 Mar 2023 09:30:44 +0000 Subject: [PATCH 0219/1483] sc_obligations.ads: add a stub for Pragma_Exceptional_Cases The purpose of this commit is to just fix the internal-tests-T629-012-pragmas regression. Real support for this new pragma (if deemed useful) will come later. (cherry picked from commit acb8a0d2ae29de06b9c4b04f363799dfaa65a36f) --- tools/gnatcov/sc_obligations.ads | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index be3a8f541..cde34dd67 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -788,6 +788,7 @@ package SC_Obligations is Pragma_Elaboration_Checks, Pragma_Eliminate, Pragma_Enable_Atomic_Synchronization, + Pragma_Exceptional_Cases, Pragma_Export, Pragma_Export_Function, Pragma_Export_Object, @@ -1104,6 +1105,7 @@ package SC_Obligations is Pragma_Elaborate => False, Pragma_Elaborate_All => False, Pragma_Elaborate_Body => False, + Pragma_Exceptional_Cases => False, Pragma_Export => False, Pragma_Export_Function => False, Pragma_Export_Object => False, From b0a6453a4b75bcb3a164342557cad4ccec3e31cb Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 16 Mar 2023 17:41:21 +0100 Subject: [PATCH 0220/1483] Revert "XFAIL test pending resolution of W313-031" This reverts commit dd8fa854ffb9e4700be0f16c743aac3febd56896. (cherry picked from commit c60e1dd0552f0c0e50230ce5b41da7cca52a8f3b) --- .../Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt | 2 -- 1 file changed, 2 deletions(-) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt index d0da1f5ef..00dc3ce12 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/test.opt @@ -1,3 +1 @@ src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation -arm-elf,CARGS_O1 XFAIL W313-031: instruction debug info attached to wrong sloc -ppc-elf,CARGS_O1 XFAIL W313-031: instruction debug info attached to wrong sloc From 74271dbca04b94f0e8df5790217b56cf3268eb32 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 17 Mar 2023 11:49:39 +0100 Subject: [PATCH 0221/1483] W315-021-generic-preelab: new regression test (cherry picked from commit 9b84a17fdd9ccb6ad45564b0ecef8553456828b5) --- .../tests/W315-021-generic-preelab/pkg.adb | 5 ++++ .../tests/W315-021-generic-preelab/pkg.ads | 6 ++++ .../tests/W315-021-generic-preelab/test.adb | 7 +++++ .../tests/W315-021-generic-preelab/test.py | 30 +++++++++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 testsuite/tests/W315-021-generic-preelab/pkg.adb create mode 100644 testsuite/tests/W315-021-generic-preelab/pkg.ads create mode 100644 testsuite/tests/W315-021-generic-preelab/test.adb create mode 100644 testsuite/tests/W315-021-generic-preelab/test.py diff --git a/testsuite/tests/W315-021-generic-preelab/pkg.adb b/testsuite/tests/W315-021-generic-preelab/pkg.adb new file mode 100644 index 000000000..a25d2cf21 --- /dev/null +++ b/testsuite/tests/W315-021-generic-preelab/pkg.adb @@ -0,0 +1,5 @@ +package body Pkg is + Var : constant Integer := 2; + + procedure Foo is null; +end Pkg; diff --git a/testsuite/tests/W315-021-generic-preelab/pkg.ads b/testsuite/tests/W315-021-generic-preelab/pkg.ads new file mode 100644 index 000000000..0e87851ab --- /dev/null +++ b/testsuite/tests/W315-021-generic-preelab/pkg.ads @@ -0,0 +1,6 @@ +generic + A : Integer; +package Pkg is + pragma Preelaborate; + procedure Foo; +end Pkg; diff --git a/testsuite/tests/W315-021-generic-preelab/test.adb b/testsuite/tests/W315-021-generic-preelab/test.adb new file mode 100644 index 000000000..427fe2daf --- /dev/null +++ b/testsuite/tests/W315-021-generic-preelab/test.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Test is + package Pkg_Inst is new Pkg (2); +begin + Pkg_Inst.Foo; +end Test; diff --git a/testsuite/tests/W315-021-generic-preelab/test.py b/testsuite/tests/W315-021-generic-preelab/test.py new file mode 100644 index 000000000..66596ddca --- /dev/null +++ b/testsuite/tests/W315-021-generic-preelab/test.py @@ -0,0 +1,30 @@ +""" +Check that declarations of a generic preelaborate Ada unit are not +instrumented, as it would otherwise result in uncompilable code. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["test.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["test"], + extra_coverage_args=["--annotate=xcov"], +) + +check_xcov_reports( + "*.xcov", + { + "test.adb.xcov": {"+": {4, 6}}, + "pkg.ads.xcov": {"+": {}}, + "pkg.adb.xcov": {"+": {4}}, + }, + "obj", +) + +thistest.result() From 7be0ff9b5fd719a1d065d45e6a63872487221ae2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 27 Mar 2023 12:19:24 +0000 Subject: [PATCH 0222/1483] Remove obsolete files The switch from Gerrit to GitLab made these files obsolete: remove them to avoid the confusion. --- .gitattributes | 13 ------------- .gitreview | 6 ------ 2 files changed, 19 deletions(-) delete mode 100644 .gitattributes delete mode 100644 .gitreview diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 309ea38be..000000000 --- a/.gitattributes +++ /dev/null @@ -1,13 +0,0 @@ -testsuite/Qualif/**/*.adb no-precommit-check -testsuite/Qualif/**/*.ads no-precommit-check -testsuite/Qualif/**/*.c no-precommit-check -testsuite/Qualif/**/*.h no-precommit-check - -# gnattest auto generated files are not style-check compliant -examples/integration/tests/*-test_data-tests.adb no-precommit-check -examples/integration/tests/*-test_data-tests.ads no-precommit-check - -# Until converted to python 3 and full style compliance ... -testsuite/STR/*.py no-precommit-check -testsuite/Qualif/qmconf.py no-precommit-check -qualification/**/*.py no-precommit-check diff --git a/.gitreview b/.gitreview deleted file mode 100644 index a5d94509a..000000000 --- a/.gitreview +++ /dev/null @@ -1,6 +0,0 @@ -[gerrit] -host = git.adacore.com -port = 29418 -project = gnatcoverage -defaultbranch = master -defaultremote = origin From b25c56224e1ea055740668695ab94e78fbd939cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 28 Mar 2023 09:58:42 +0200 Subject: [PATCH 0223/1483] Add minimal VScode configuration for the gnatcov project This spares the initial setup for people wanting to use VScode to browse/edit the codebase. --- tools/gnatcov/.vscode/settings.json | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 tools/gnatcov/.vscode/settings.json diff --git a/tools/gnatcov/.vscode/settings.json b/tools/gnatcov/.vscode/settings.json new file mode 100644 index 000000000..a41a48f6c --- /dev/null +++ b/tools/gnatcov/.vscode/settings.json @@ -0,0 +1,8 @@ +{ + "ada.projectFile": "gnatcov.gpr", + "ada.scenarioVariables": { + "BUILD_MODE": "dev", + "PART": "gnatcov64", + "C_SUPPORT": "True" + } +} From 5882985fcd31116b8d8d08d3db1993cbb7b41448 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 27 Mar 2023 15:09:02 +0000 Subject: [PATCH 0224/1483] tests/duplicate_postprocess: adapt for restricted runtimes printf/puts may not be available with some bareboard runtimes. Adapt the testcase to run even on such restricted configurations. --- testsuite/tests/duplicate_postprocess/lib.c | 19 +++++++++++++++++++ .../tests/duplicate_postprocess/test_macros.c | 16 +++++++--------- 2 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 testsuite/tests/duplicate_postprocess/lib.c diff --git a/testsuite/tests/duplicate_postprocess/lib.c b/testsuite/tests/duplicate_postprocess/lib.c new file mode 100644 index 000000000..4d81d8d52 --- /dev/null +++ b/testsuite/tests/duplicate_postprocess/lib.c @@ -0,0 +1,19 @@ +extern void dummy_puts (const char *msg); + +#define PRINT_HW dummy_puts ("Hello world!\n"); + +/* Thanks to macro_stmts_enabled returning 0, macro_stmts is never executed, + and thus we get coverage violations inside macro expansion. */ + +int +macro_stmts_enabled (void) +{ + return 0; +} + +void +macro_stmts (void) +{ + PRINT_HW; + PRINT_HW; +} diff --git a/testsuite/tests/duplicate_postprocess/test_macros.c b/testsuite/tests/duplicate_postprocess/test_macros.c index 44d905d12..be45e319b 100644 --- a/testsuite/tests/duplicate_postprocess/test_macros.c +++ b/testsuite/tests/duplicate_postprocess/test_macros.c @@ -1,18 +1,16 @@ -#include +extern int macro_stmts_enabled (void); +extern void macro_stmts (void); -#define PRINT_HW printf ("Hello world!\n"); - -// Code that is not covered to have coverage violations for code inside macro -// expansions. void -macro_stmts () +dummy_puts (const char *msg) { - PRINT_HW; - PRINT_HW; + return; } int -main () +main (void) { + if (macro_stmts_enabled ()) + macro_stmts (); return 0; } From cd85befc9297aff331424f957b7a56d05b50fd22 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 29 Mar 2023 09:08:38 +0000 Subject: [PATCH 0225/1483] instrument-ada_unit.adb: minor reformatting --- tools/gnatcov/instrument-ada_unit.adb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 0e4485e2f..2fa9054fe 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6495,9 +6495,9 @@ package body Instrument.Ada_Unit is end; end Initialize_Rewriting; - ---------------------------- - -- Insert_Dump_Proc_Calls -- - ---------------------------- + ----------------------------------- + -- Insert_Simple_Dump_Proc_Calls -- + ----------------------------------- procedure Insert_Simple_Dump_Proc_Calls (RH : Rewriting_Handle; From 92e31a43137238c1b97260e3ec01b8e0f714d9e7 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 29 Mar 2023 09:52:38 +0000 Subject: [PATCH 0226/1483] instrument-ada_unit.adb: refactor the detection of main CU structure Move code that detects the structure of a main (for the purpose of insert the dump of coverage buffers) to a separate subprogram. Upcoming work will make this process more complex, so isolating to a dedicated subprogram will help maintainability. --- tools/gnatcov/instrument-ada_unit.adb | 248 ++++++++++++++++---------- 1 file changed, 157 insertions(+), 91 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 2fa9054fe..ca6e101fe 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -971,24 +971,6 @@ package body Instrument.Ada_Unit is function Parent_Decl (Decl : Basic_Decl'Class) return Basic_Decl; -- Return the parent declaration for Decl, or No_Basic_Decl if Decl has no -- parent, or if we cannot find it. - - procedure Insert_Simple_Dump_Proc_Calls - (RH : Rewriting_Handle; - Helper_Unit : Ada_Qualified_Name; - Subp_Body : LAL.Subp_Body); - -- Insert calls, in Subp_Body, to the .Dump_Buffers procedure - -- as the last statment of the top level handeled statments of the main, as - -- the last statement of each exception handler branch, and right before - -- each return statment returning from the main procedure. - - procedure Insert_Controlled_Dump_Object_Decl - (RH : Rewriting_Handle; - Helper_Unit : Ada_Qualified_Name; - Subp_Body : LAL.Subp_Body); - -- Insert, in Subp_Body, the declaration of a controlled object of type - -- .Dump_Controlled_Type to dump the coverage buffers during - -- finalization of said object. - -------------------------------- -- Instrumentation extensions -- -------------------------------- @@ -1154,6 +1136,61 @@ package body Instrument.Ada_Unit is -- If the unit to instrument is also a main and the buffers dump trigger -- is not manual, instrumented code will also dump the coverage buffers. + ---------------------------------- + -- Main instrumentation helpers -- + ---------------------------------- + + Cannot_Instrument_Main_Error : exception; + -- See Probe_Main + + type Main_Instrumentation_Description is record + Main : Compilation_Unit_Name; + -- Name of the compilation unit corresponding to the main body + + Controlled_Types_Available : Boolean; + -- Whether instrumentation can insert uses of controlled types + + Actual_Dump_Trigger : Auto_Dump_Trigger; + -- Resolved dump trigger after eventual override depending on the + -- features available on the runtime. + + Prelude : LAL.Ada_Node_List; + -- Prelude for the main compilation unit + + Subp_Body : LAL.Subp_Body; + -- Subprogram body in which to insert the code to dump coverage buffers. + end record; + -- Nodes needed to instrument main subprograms so that they can dump + -- coverage buffers. + + function Probe_Main + (Dump_Config : Any_Dump_Config; + Rewriter : Ada_Source_Rewriter'Class) + return Main_Instrumentation_Description; + -- Given a rewriter for the main source, return a description of the main + -- unit in which to trigger the dump of coverage buffers. + -- + -- Emit a warning and raise a Cannot_Instrument_Main_Error if the main does + -- not have a structure that is expected for a main. + + procedure Insert_Simple_Dump_Proc_Calls + (RH : Rewriting_Handle; + Helper_Unit : Ada_Qualified_Name; + Subp_Body : LAL.Subp_Body); + -- Insert calls, in Subp_Body, to the .Dump_Buffers procedure + -- as the last statment of the top level handeled statments of the main, as + -- the last statement of each exception handler branch, and right before + -- each return statment returning from the main procedure. + + procedure Insert_Controlled_Dump_Object_Decl + (RH : Rewriting_Handle; + Helper_Unit : Ada_Qualified_Name; + Decls : Node_Rewriting_Handle); + -- Assuming that Decls is a rewriting handle for the declaration list of a + -- subprogram body, insert at the beginning of it the declaration of a + -- controlled object of type .Dump_Controlled_Type to dump the + -- coverage buffers during finalization of said object. + -------------------------- -- Unit instrumentation -- -------------------------- @@ -6495,6 +6532,85 @@ package body Instrument.Ada_Unit is end; end Initialize_Rewriting; + ---------------- + -- Probe_Main -- + ---------------- + + function Probe_Main + (Dump_Config : Any_Dump_Config; + Rewriter : Ada_Source_Rewriter'Class) + return Main_Instrumentation_Description + is + U : Analysis_Unit; + Tmp : LAL.Ada_Node; + + CU : LAL.Compilation_Unit; + Subp_Body : LAL.Subp_Body; + + Controlled_Types_Available : Boolean; + Actual_Dump_Trigger : Auto_Dump_Trigger; + + Main : Compilation_Unit_Name (Unit_Based_Language) := + (Language_Kind => Unit_Based_Language, + Part => Unit_Body, + others => <>); + -- Note that we can't get the compilation unit name using the + -- To_Compilation_Unit_Name overload taking a File_Info parameter, + -- as the main we are instrumenting there may be the instrumented + -- version of the original version, in which case it won't belong + -- to the root project as it will be in the -gnatcov-instr + -- directory. + + begin + -- Make sure this main source has the expected structure: + -- + -- * a simple subprogram body in a compilation unit; + -- * a generic subprogram instantiation + -- + -- If this source matches none of the above, emit a warning and raise a + -- Cannot_Instrument_Main_Error exception. + + U := Unit (Handle (Rewriter.Rewritten_Unit)); + + Tmp := U.Root; + if Tmp.Kind /= Ada_Compilation_Unit then + raise Cannot_Instrument_Main_Error; + else + CU := Tmp.As_Compilation_Unit; + end if; + + Tmp := CU.F_Body; + if Tmp.Kind /= Ada_Library_Item then + raise Cannot_Instrument_Main_Error; + end if; + + Tmp := Tmp.As_Library_Item.F_Item.As_Ada_Node; + if Tmp.Kind /= Ada_Subp_Body then + raise Cannot_Instrument_Main_Error; + else + Subp_Body := Tmp.As_Subp_Body; + end if; + + Controlled_Types_Available := + not Finalization_Restricted_In_Unit (U.Context, CU); + + Actual_Dump_Trigger := + (if Dump_Config.Trigger = Main_End + and then not Controlled_Types_Available + and then not Task_Termination_Restricted (U.Context, CU) + then Ravenscar_Task_Termination + else Dump_Config.Trigger); + + Main.Unit := To_Qualified_Name (CU.P_Syntactic_Fully_Qualified_Name); + + return + (Main, + Controlled_Types_Available, + Actual_Dump_Trigger, + CU.F_Prelude, + Subp_Body); + end Probe_Main; + ----------------------------------- -- Insert_Simple_Dump_Proc_Calls -- ----------------------------------- @@ -6591,15 +6707,13 @@ package body Instrument.Ada_Unit is procedure Insert_Controlled_Dump_Object_Decl (RH : Rewriting_Handle; Helper_Unit : Ada_Qualified_Name; - Subp_Body : LAL.Subp_Body) + Decls : Node_Rewriting_Handle) is -- Declare an object of the type .Dump_Controlled_Type -- which will call the procedure Dump_Buffers when finalized. Controlled_Type_Name : Ada_Qualified_Name := Helper_Unit; Dump_Object_Decl : Node_Rewriting_Handle; - Decl_List : constant Node_Rewriting_Handle := - Handle (Subp_Body.F_Decls.F_Decls); begin Controlled_Type_Name.Append (To_Unbounded_String ("Dump_Controlled_Type")); @@ -6612,7 +6726,7 @@ package body Instrument.Ada_Unit is -- Insert the declaration as the first declaration in the -- list to ensure it is finalized last. - Insert_Child (Decl_List, 1, Dump_Object_Decl); + Insert_Child (Decls, 1, Dump_Object_Decl); end Insert_Controlled_Dump_Object_Decl; ---------------------------------- @@ -6925,77 +7039,28 @@ package body Instrument.Ada_Unit is Info : in out Project_Info) is Rewriter : Ada_Source_Rewriter; - - U : Analysis_Unit; - RH : Rewriting_Handle; - Tmp : LAL.Ada_Node; - - CU : LAL.Compilation_Unit; - Subp_Body : LAL.Subp_Body; - - Controlled_Types_Available : Boolean; - - Actual_Dump_Trigger : Auto_Dump_Trigger; - -- Resolved dump trigger after eventual override depending on the - -- features available on the runtime. + RH : Rewriting_Handle renames Rewriter.Handle; Helper_Unit : Ada_Qualified_Name; -- Name of unit to contain helpers implementing the buffers dump - Main : Compilation_Unit_Name (Unit_Based_Language) := - (Language_Kind => Unit_Based_Language, - Part => Unit_Body, - others => <>); - -- Note that we can't get the compilation unit name using the - -- To_Compilation_Unit_Name overload taking a File_Info parameter, - -- as the main we are instrumenting there may be the instrumented - -- version of the original version, in which case it won't belong - -- to the root project as it will be in the -gnatcov-instr - -- directory. - + Desc : Main_Instrumentation_Description; begin if Instr_Units.Is_Empty then return; end if; Start_Rewriting (Rewriter, Self, Info, Filename); - -- Make sure this main source has the expected structure: a - -- simple subprogram body in a compilation unit. If not, return without - -- doing anything. - - U := Unit (Handle (Rewriter.Rewritten_Unit)); - RH := Handle (U.Context); - Tmp := U.Root; - - if Tmp.Kind /= Ada_Compilation_Unit then - return; - else - CU := Tmp.As_Compilation_Unit; - end if; - - Tmp := CU.F_Body; - if Tmp.Kind /= Ada_Library_Item then - return; - end if; - - Tmp := Tmp.As_Library_Item.F_Item.As_Ada_Node; - if Tmp.Kind /= Ada_Subp_Body then - return; - else - Subp_Body := Tmp.As_Subp_Body; - end if; - - Controlled_Types_Available := - not Finalization_Restricted_In_Unit (U.Context, CU); - - Actual_Dump_Trigger := - (if Dump_Config.Trigger = Main_End - and then not Controlled_Types_Available - and then not Task_Termination_Restricted (U.Context, CU) - then Ravenscar_Task_Termination - else Dump_Config.Trigger); + -- Try to detect the structure of this main, to determine how to insert + -- the dump of coverage buffers. In case of failure, let Probe_Main emit + -- a warning and do nothing. - Main.Unit := To_Qualified_Name (CU.P_Syntactic_Fully_Qualified_Name); + begin + Desc := Probe_Main (Dump_Config, Rewriter); + exception + when Cannot_Instrument_Main_Error => + return; + end; -- Emit the helper unit and add a WITH clause for it @@ -7003,13 +7068,13 @@ package body Instrument.Ada_Unit is (Dump_Config, Info, Filename, - Main, + Desc.Main, Helper_Unit, - Override_Dump_Trigger => Actual_Dump_Trigger, - Has_Controlled => Controlled_Types_Available); + Override_Dump_Trigger => Desc.Actual_Dump_Trigger, + Has_Controlled => Desc.Controlled_Types_Available); declare - Prelude : constant Node_Rewriting_Handle := Handle (CU.F_Prelude); + Prelude : constant Node_Rewriting_Handle := Handle (Desc.Prelude); With_Clause : constant Node_Rewriting_Handle := Create_From_Template @@ -7041,7 +7106,7 @@ package body Instrument.Ada_Unit is -- Depending on the chosen coverage buffers dump trigger, insert the -- appropriate code. - case Actual_Dump_Trigger is + case Desc.Actual_Dump_Trigger is when At_Exit | Ravenscar_Task_Termination => @@ -7056,7 +7121,7 @@ package body Instrument.Ada_Unit is Call_Expr : Node_Rewriting_Handle; Call_Decl : Node_Rewriting_Handle; Decl_List : constant Node_Rewriting_Handle := - Handle (Subp_Body.F_Decls.F_Decls); + Handle (Desc.Subp_Body.F_Decls.F_Decls); begin Register_Function := Helper_Unit; Register_Function.Append (Register_Dump_Function_Name); @@ -7088,10 +7153,11 @@ package body Instrument.Ada_Unit is -- - If we do not have finalization or tasks then simply insert calls -- right before all the exit points of the main. - if not Finalization_Restricted_In_Unit (U.Context, CU) then - Insert_Controlled_Dump_Object_Decl (RH, Helper_Unit, Subp_Body); + if Desc.Controlled_Types_Available then + Insert_Controlled_Dump_Object_Decl + (RH, Helper_Unit, Handle (Desc.Subp_Body.F_Decls.F_Decls)); else - Insert_Simple_Dump_Proc_Calls (RH, Helper_Unit, Subp_Body); + Insert_Simple_Dump_Proc_Calls (RH, Helper_Unit, Desc.Subp_Body); end if; end case; Rewriter.Apply; From 018fd751b53623cb2d5927aca77e3e1e40e347a1 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 29 Mar 2023 09:56:53 +0000 Subject: [PATCH 0227/1483] instrument-ada_unit.adb: emit a warning when we cannot instrument main As revealed by the bug report in W328-016, aborting the process of inserting dump of coverage buffers silently is not a good idea: the instrumentation seemingly worked ("gnatcov instrument" exits with code 0 and without warnings) but the build fails later due to linking issues. To avoid confusion in the future, make gnatcov emit a warning in such cases. --- .../instr-cov/unexpected-ada-main/main.ads | 2 ++ .../instr-cov/unexpected-ada-main/test.py | 34 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 28 +++++++++++++-- 3 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/instr-cov/unexpected-ada-main/main.ads create mode 100644 testsuite/tests/instr-cov/unexpected-ada-main/test.py diff --git a/testsuite/tests/instr-cov/unexpected-ada-main/main.ads b/testsuite/tests/instr-cov/unexpected-ada-main/main.ads new file mode 100644 index 000000000..2ed96e9de --- /dev/null +++ b/testsuite/tests/instr-cov/unexpected-ada-main/main.ads @@ -0,0 +1,2 @@ +package Main is +end Main; diff --git a/testsuite/tests/instr-cov/unexpected-ada-main/test.py b/testsuite/tests/instr-cov/unexpected-ada-main/test.py new file mode 100644 index 000000000..94ab44dc2 --- /dev/null +++ b/testsuite/tests/instr-cov/unexpected-ada-main/test.py @@ -0,0 +1,34 @@ +""" +Check that "gnatcov instrument" emits a warning when it fails to insert the +dump of coverage buffers in mains. +""" + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + + +Wdir("tmp_") + +# Avoid the "creation output path" notice +mkdir("obj") + +xcov_instrument( + gprsw=GPRswitches(root_project=gprfor(mains=["main.ads"], srcdirs=[".."])), + covlevel="stmt", + out="instrument.log", + tolerate_messages=".", +) +thistest.fail_if_not_equal( + '"gnatcov instrument" output', + ( + "warning: cannot dump coverage buffers in main.ads:" + " subprogram body expected" + ), + contents_of("instrument.log").strip(), +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index ca6e101fe..7a2c42fed 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6541,6 +6541,28 @@ package body Instrument.Ada_Unit is Rewriter : Ada_Source_Rewriter'Class) return Main_Instrumentation_Description is + procedure Stop (Message : String) with No_Return; + -- Emit a warning with the given message and raise a + -- Cannot_Instrument_Main_Error exception. + + ---------- + -- Stop -- + ---------- + + procedure Stop (Message : String) is + Filename : constant String := + Ada.Directories.Simple_Name (To_String (Rewriter.Input_Filename)); + begin + -- TODO??? Ideally, we would like to display the source location in + -- Filename that led to abort the instrumentation of this main. This + -- is not possible today since we are possibly rewriting a source + -- file that was already instrumented, so slocs do not reflect the + -- sources that users see. + + Warn ("cannot dump coverage buffers in " & Filename & ": " & Message); + raise Cannot_Instrument_Main_Error; + end Stop; + U : Analysis_Unit; Tmp : LAL.Ada_Node; @@ -6574,19 +6596,19 @@ package body Instrument.Ada_Unit is Tmp := U.Root; if Tmp.Kind /= Ada_Compilation_Unit then - raise Cannot_Instrument_Main_Error; + Stop ("compilation unit expected"); else CU := Tmp.As_Compilation_Unit; end if; Tmp := CU.F_Body; if Tmp.Kind /= Ada_Library_Item then - raise Cannot_Instrument_Main_Error; + Stop ("library item expected"); end if; Tmp := Tmp.As_Library_Item.F_Item.As_Ada_Node; if Tmp.Kind /= Ada_Subp_Body then - raise Cannot_Instrument_Main_Error; + Stop ("subprogram body expected"); else Subp_Body := Tmp.As_Subp_Body; end if; From d787cb7a86846ee9ec6d1ae0c057276cacc828ea Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 21 Mar 2023 13:09:16 +0000 Subject: [PATCH 0228/1483] GNATcov_RTS: rework "base IO" units Extend comments in these units. Also merge Put/Put_Line: we need only one routine that is able to write bytes to the "output stream", having both Put and Put_Line brings little value and makes runtime customization more verbose. --- tools/gnatcov/rts/gnatcov_rts-base_io.adb | 15 +++-------- tools/gnatcov/rts/gnatcov_rts-base_io.ads | 10 +++---- tools/gnatcov/rts/gnatcov_rts_c-base_io.c | 16 +++--------- tools/gnatcov/rts/gnatcov_rts_c-base_io.h | 10 +++---- .../rts/gnatcov_rts_c-traces-output-base64.c | 26 +++++++++++-------- 5 files changed, 32 insertions(+), 45 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts-base_io.adb b/tools/gnatcov/rts/gnatcov_rts-base_io.adb index d42be21fa..d955bb67f 100644 --- a/tools/gnatcov/rts/gnatcov_rts-base_io.adb +++ b/tools/gnatcov/rts/gnatcov_rts-base_io.adb @@ -32,20 +32,11 @@ package body GNATcov_RTS.Base_IO is -- Put -- --------- - procedure Put (C : Character) is - begin - GNAT.IO.Put (C); - end Put; - - -------------- - -- Put_Line -- - -------------- - - procedure Put_Line (S : GNATcov_RTS_String) is + procedure Put (S : GNATcov_RTS_String) is Str : String (1 .. Integer (S.Length)); for Str'Address use S.Str; begin - GNAT.IO.Put_Line (Str); - end Put_Line; + GNAT.IO.Put (Str); + end Put; end GNATcov_RTS.Base_IO; diff --git a/tools/gnatcov/rts/gnatcov_rts-base_io.ads b/tools/gnatcov/rts/gnatcov_rts-base_io.ads index c2ef6e8fa..125f3d6c0 100644 --- a/tools/gnatcov/rts/gnatcov_rts-base_io.ads +++ b/tools/gnatcov/rts/gnatcov_rts-base_io.ads @@ -28,12 +28,12 @@ with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; package GNATcov_RTS.Base_IO is - pragma Preelaborate; + -- See the comment in gnatcov_rts_c-base_io.h for more information about + -- this package. - procedure Put (C : Character); - pragma Export (C, Entity => Put, External_Name => "gnatcov_rts_putchar"); + pragma Preelaborate; - procedure Put_Line (S : GNATcov_RTS_String); - pragma Export (C, Entity => Put_Line, External_Name => "gnatcov_rts_puts"); + procedure Put (S : GNATcov_RTS_String); + pragma Export (C, Entity => Put, External_Name => "gnatcov_rts_put_string"); end GNATcov_RTS.Base_IO; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-base_io.c b/tools/gnatcov/rts/gnatcov_rts_c-base_io.c index 22c5bad77..2f922c7cf 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-base_io.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-base_io.c @@ -21,19 +21,11 @@ #include "gnatcov_rts_c_strings.h" -/* The libc implementation always provides fwrite / putchar. Use these - functions to print to the standard output. */ +/* The libc implementation always provides fwrite. Use this function to print + to the standard output. */ -int -gnatcov_rts_puts (struct gnatcov_rts_string str) +void +gnatcov_rts_put_string (struct gnatcov_rts_string str) { fwrite (str.str, 1, str.length, stdout); - fwrite ("\n", 1, 1, stdout); - return 0; -} - -extern int -gnatcov_rts_putchar (int c) -{ - return putchar (c); } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-base_io.h b/tools/gnatcov/rts/gnatcov_rts_c-base_io.h index 62ec455b2..cbaf84889 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-base_io.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-base_io.h @@ -18,9 +18,10 @@ ****************************************************************************/ /* This header provides the smallest subset of functions needed to output - bytes. These functions are used in gnatcov_rts_c-traces-output-base64.c to - dump base64 traces to "the output": stdout when linking with a C runtime - only, and GNAT.IO.Standard_Output when linking with an Ada runtime. + bytes. These functions are used in gnatcov_rts_c-traces-output-base64.c + (and thus by the implementation of gnatcov's --dump-channel=base64-stdout + option) to dump base64 traces to "the output": stdout when linking with a C + runtime only, and GNAT.IO.Standard_Output when linking with an Ada runtime. In the former case, the gnatcov_rts_c-base_io.c module implements these functions, and in the latter case, it’s the GNATcov_RTS.Base_IO package that @@ -35,8 +36,7 @@ extern "C" #endif /* See gnatcov_rts-base_io.ads. */ - extern int gnatcov_rts_puts (struct gnatcov_rts_string str); - extern int gnatcov_rts_putchar (int c); + extern int gnatcov_rts_put_string (struct gnatcov_rts_string str); #ifdef __cplusplus } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c index f11d33875..873553b61 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c @@ -28,6 +28,12 @@ static const char *base64_alphabet static char base64_padding = '='; +/* Various gnatcov_rts_string constants. */ +static const struct gnatcov_rts_string newline_string = STR ("\n"); +static const struct gnatcov_rts_string begin_string + = STR ("== GNATcoverage source trace file ==\n"); +static const struct gnatcov_rts_string end_string = STR ("== End ==\n"); + typedef struct { /* We output base64 content by groups of 4 digits, which encode for 3 @@ -59,7 +65,7 @@ flush (gnatcov_rts_base64_buffer *output) { uint8_t *in_bytes = output->bytes; char out_digits[4]; - int i; + struct gnatcov_rts_string str; switch (output->next) { @@ -93,14 +99,15 @@ flush (gnatcov_rts_base64_buffer *output) a newline when needed in order to avoid exceeding 80 characters per line. */ - for (i = 0; i < 4; i++) - gnatcov_rts_putchar (out_digits[i]); + str.str = out_digits; + str.length = 4; + gnatcov_rts_put_string (str); output->columns += 4; if (output->columns >= 80) { output->columns = 0; - gnatcov_rts_putchar ('\n'); + gnatcov_rts_put_string (newline_string); } memset (output->bytes, 0, 4); @@ -133,15 +140,12 @@ gnatcov_rts_write_trace_file_base64 ( gnatcov_rts_base64_buffer buffer; buffer.next = 0; buffer.columns = 0; - struct gnatcov_rts_string begin_string - = STR ("== GNATcoverage source trace file =="); - struct gnatcov_rts_string end_string = STR ("== End =="); - gnatcov_rts_putchar ('\n'); - gnatcov_rts_puts (begin_string); + gnatcov_rts_put_string (newline_string); + gnatcov_rts_put_string (begin_string); gnatcov_rts_generic_write_trace_file (&buffer, buffers_groups, program_name, exec_date, user_data, write_bytes); flush (&buffer); if (buffer.columns != 0) - gnatcov_rts_puts (STR ("")); - gnatcov_rts_puts (end_string); + gnatcov_rts_put_string (newline_string); + gnatcov_rts_put_string (end_string); } From 2d255588c39f5cd63cff247f425922a19cc72a02 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 21 Mar 2023 15:42:38 +0000 Subject: [PATCH 0229/1483] GNATcov_RTS.Base_IO: remove the pragma Preelaborate Custom implementations for the Base IO may need runtime elaboration (to open an output file, a socket, ...). There is currently no actual need to have it preelaborated, so just remove the pragma Preelaborate. --- tools/gnatcov/rts/gnatcov_rts-base_io.ads | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts-base_io.ads b/tools/gnatcov/rts/gnatcov_rts-base_io.ads index 125f3d6c0..d21ed97c5 100644 --- a/tools/gnatcov/rts/gnatcov_rts-base_io.ads +++ b/tools/gnatcov/rts/gnatcov_rts-base_io.ads @@ -31,8 +31,6 @@ package GNATcov_RTS.Base_IO is -- See the comment in gnatcov_rts_c-base_io.h for more information about -- this package. - pragma Preelaborate; - procedure Put (S : GNATcov_RTS_String); pragma Export (C, Entity => Put, External_Name => "gnatcov_rts_put_string"); From 9593a7ce587f2811d3ece69f4836a0f1884a8578 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 21 Mar 2023 15:53:42 +0000 Subject: [PATCH 0230/1483] Document how to customize the coverage runtime --- doc/gnatcov/src_traces.rst | 118 +++++++++++++++++++++++++++++++++++-- 1 file changed, 113 insertions(+), 5 deletions(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 6fe1a6ddf..8b5534f90 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -185,11 +185,6 @@ the options passed to the latter take precedence. For instance: Note that the defaults that |gcvstp| uses for each target platform may change between versions of |gcp|. -.. TODO (U211-014): Document: - - * the project positional argument (to install an extending coverage runtime - project). - Instrumenting programs ====================== @@ -882,3 +877,116 @@ The build of instrumented tests then proceeds as follows:: And a regular execution in the host environment would produce a source trace in addition to performing the original functional operations. + + +Coverage runtime customization +============================== + +Basics +------ + +Some configurations have constraints that make the default coverage runtime +inadequate. For instance, targeting a board that has no serial port, making the +default implementation for ``--dump-channel=base64-stdout`` ineffective. In +order to accomodate for such special needs, it is possible to extend the +coverage runtime project and add/override some of its sources. + +First, build and install the default coverage runtime (``gnatcov_rts``): + +.. code-block:: sh + + # Add --target and --RTS if needed according to the toolchain to use + gnatcov setup + +Then create the project extension. The integration with the |gcvstp| workflow +requires the project file and the sources to be in a dedicated directory: + +.. code-block:: sh + + mkdir my_rts + cat > my_rts/my_rts.gpr < Put, External_Name => "gnatcov_rts_put_string"); + end GNATcov_RTS.Base_IO; + + -- gnatcov_rts-strings.ads + + with Interfaces.C; use Interfaces.C; + + package GNATcov_RTS.Strings is + pragma Pure; + type GNATcov_RTS_String is record + Str : System.Address; + Length : size_t; + end record; + pragma Convention (C_Pass_By_Copy, GNATcov_RTS_String); + end GNATcov_RTS.Strings; + +When Ada support is disabled, override the ``gnatcov_rts_c-base_io.c`` source +file so that it implements the interface described in the (unmodified) +``gnatcov_rts_c-base_io.h`` source file. + +.. code-block:: c + + /* gnatcov_rts_c-base_io.h */ + + #include "gnatcov_rts_c_strings.h" + extern int gnatcov_rts_put_string (struct gnatcov_rts_string str); + + /* gnatcov_rts_c_strings.h */ + + #include + struct gnatcov_rts_string + { + const char *str; + size_t length; + }; From 15bb67f91fe99565e26fad3539e4ee296e6e8658 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 31 Mar 2023 12:10:59 +0000 Subject: [PATCH 0231/1483] instrument-ada_unit.adb: rework syntax fields access in rewritten trees Currently, the `Libadalang.Rewriting` API provides a single primitive to access the syntax field of a rewritten node: ```ada function Child (Handle : Node_Rewriting_Handle; Index : Natural) return Node_Rewriting_Handle; ``` This API is both inconvenient (one has to compute ``Index`` for the requested field, which depends on the actual node type for ``Handle``) and error-prone (no guarantee when calling ``Child`` that the passed index is consistent with the actual node type). This refactoring creates a parallel set of primitives wrapping the above. They accept a syntax field reference instead of the index, and compute the index from the actual node type, which fixes both of the issues described above. --- tools/gnatcov/instrument-ada_unit.adb | 112 ++++++++++++++++++++------ 1 file changed, 86 insertions(+), 26 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 7a2c42fed..5d711c802 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -344,22 +344,85 @@ package body Instrument.Ada_Unit is Make_Identifier (UIC, D_Name))); -- Shortcut to create a defining identifier tree - ------------------------------------ - -- Indices for syntactic children -- - ------------------------------------ + ----------------------- + -- Rewriting helpers -- + ----------------------- + + -- TODO??? (eng/libadalang/langkit#642) Remove these helpers to use + -- Libadalang's once they are available. + + function Child_Index + (Handle : Node_Rewriting_Handle; + Field : Syntax_Field_Reference) return Positive + is (Index (Kind (Handle), Field)); + -- Return the index of the syntax field ``Field`` in the node designated by + -- ``Handle``. + + function Child + (Handle : Node_Rewriting_Handle; + Field : Syntax_Field_Reference) return Node_Rewriting_Handle; + -- Return the node that is in the syntax Field for Handle - I_Accept_Stmt_With_Stmts_F_Stmts : constant Integer := - Index (Ada_Accept_Stmt_With_Stmts, Accept_Stmt_With_Stmts_F_Stmts); - I_Expr_Function_F_Aspects : constant Integer := - Index (Ada_Expr_Function, Basic_Decl_F_Aspects); - I_Subp_Decl_F_Aspects : constant Integer := - Index (Ada_Subp_Decl, Basic_Decl_F_Aspects); - I_Handled_Stmts_F_Stmts : constant Integer := - Index (Ada_Handled_Stmts, Handled_Stmts_F_Stmts); - I_Subp_Spec_F_Subp_Params : constant Integer := - Index (Ada_Subp_Spec, Subp_Spec_F_Subp_Params); - I_Subp_Spec_F_Name : constant Integer := - Index (Ada_Subp_Spec, Subp_Spec_F_Subp_Name); + type Syntax_Field_Reference_Array is + array (Positive range <>) of Syntax_Field_Reference; + + function Child + (Handle : Node_Rewriting_Handle; + Fields : Syntax_Field_Reference_Array) return Node_Rewriting_Handle; + -- Return a child deep in the tree Handle. + -- + -- Assuming Fields'Range is 1 .. N, this is a shortcut for: + -- + -- C1 := Child (Handle, Fields (1)); + -- C2 := Child (C1, Fields (2)); + -- ... + -- CN_1 := Child (CN_2, Fields (N - 1)); + -- CN := Child (CN_1, Fields (N)); + + procedure Set_Child + (Handle : Node_Rewriting_Handle; + Field : Syntax_Field_Reference; + Child : Node_Rewriting_Handle); + -- If ``Child`` is ``No_Rewriting_Node``, untie the syntax field in + -- ``Handle`` corresponding to ``Field``, so it can be attached to another + -- one. Otherwise, ``Child`` must have no parent as it will be tied to + -- ``Handle``'s tree. + + ----------- + -- Child -- + ----------- + + function Child + (Handle : Node_Rewriting_Handle; + Field : Syntax_Field_Reference) return Node_Rewriting_Handle + is + begin + return Child (Handle, Child_Index (Handle, Field)); + end Child; + + function Child + (Handle : Node_Rewriting_Handle; + Fields : Syntax_Field_Reference_Array) return Node_Rewriting_Handle is + begin + return Result : Node_Rewriting_Handle := Handle do + for F of Fields loop + Result := Child (Result, F); + end loop; + end return; + end Child; + + --------------- + -- Set_Child -- + --------------- + + procedure Set_Child + (Handle : Node_Rewriting_Handle; + Field : Syntax_Field_Reference; + Child : Node_Rewriting_Handle) + is + begin + Set_Child (Handle, Index (Kind (Handle), Field), Child); + end Set_Child; --------------------- -- Unbounded texts -- @@ -2305,7 +2368,7 @@ package body Instrument.Ada_Unit is Set_Child (Handle (Common_Nodes.N_Spec), - I_Subp_Spec_F_Subp_Params, + Subp_Spec_F_Subp_Params, Create_Params (RC, Formal_Params)); -- If we also need a declaration for the augmented expression @@ -2328,14 +2391,14 @@ package body Instrument.Ada_Unit is -- Replace the original EF name by the augmented EF name Set_Child (New_Spec, - I_Subp_Spec_F_Name, + Subp_Spec_F_Subp_Name, Make_Identifier (UIC, Augmented_Expr_Func_Name)); -- Add the augmented params to this spec as well Set_Child (New_Spec, - I_Subp_Spec_F_Subp_Params, + Subp_Spec_F_Subp_Params, Create_Params (RC, Clone (Formal_Params))); Augmented_Expr_Function_Decl := Create_Subp_Decl @@ -2375,12 +2438,12 @@ package body Instrument.Ada_Unit is if Needs_Decl then Set_Child (Augmented_Expr_Function_Decl, - I_Subp_Decl_F_Aspects, + Basic_Decl_F_Aspects, Aspects); else Set_Child (Handle (Common_Nodes.N), - I_Expr_Function_F_Aspects, + Basic_Decl_F_Aspects, Aspects); end if; end; @@ -3236,12 +3299,9 @@ package body Instrument.Ada_Unit is -- statement list at first position. Insert_List := - Child - (Child - (SCE.Insertion_N, - I_Accept_Stmt_With_Stmts_F_Stmts), - I_Handled_Stmts_F_Stmts); - + Child (SCE.Insertion_N, + (Accept_Stmt_With_Stmts_F_Stmts, + Handled_Stmts_F_Stmts)); Insert_Pos := 1; else From 699326c8e5a9338f788806d7483562546d134664 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 16 Jan 2023 16:15:43 +0000 Subject: [PATCH 0232/1483] Generalize Qualif requirements for Ada exceptions handling Adjust the requirement text in Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst to encompass exception propagation without restriction. Adjust the associated testing strategy text to better cover the more general requirements and match the set of to be added test cases. Remove the explicit description of limitations wrt exception handling in the toplevel "Language Version and Scope" section of the TOR contents. --- .../Ada/stmt/1_Core/11_Exceptions/req.rst | 78 ++++++++++--------- testsuite/Qualif/Environment/content.tmpl | 17 ---- 2 files changed, 40 insertions(+), 55 deletions(-) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst index d70aeba10..63f4a13f4 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst @@ -6,65 +6,67 @@ SC requirements for ARM chap. 11 : Exceptions %REQ_ID% -For local exceptions, handled in the same subprogram as where it was raised, -Statement Coverage shall be assessed for Ada's exceptions mechanism as -described in Chapter 11 of the Ada Reference Manual. In particular: +Statement Coverage assessments shall handle the Ada exceptions related +features described in Chapter 11 of the language Reference Manual. This +requires accounting for exception handlers, implicit or explicit raise +operations and the effects of their control flow transfers. More precisely: -* ``raise`` statements shall be reported uncovered when unreached, +====== ====================================================================== +Rule # Description +====== ====================================================================== +1 Explicit ``raise`` statements shall be handled as regular + statements, reported uncovered when not reached, -* The control flow effects of implicit and explicit exception raises shall be - handled correctly: +2 Statements never reached in a sequence because of implicit or explicit + raise(s) earlier in the sequence shall be reported uncovered, - * statements that do not execute because of a raise shall be reported - as uncovered, +3 The complete set of Statement Coverage requirements apply to statements + that constitute exception handlers, - * statements that only execute partially because of an interrupted expression - evaluation shall *not* be reported as uncovered. +4 Statements that execute only partially, interrupted by a raise + during an expression evaluation as part of the statement's operation, + shall *not* be reported as uncovered. -* Statement coverage requirements apply to both predefined and - user-defined exceptions. - -* The full set of core SC requirements apply to all the statements within - exception handlers. - -The tool shall also produce correct Statement Coverage assessments for -subprogram bodies consisting of a call to subprogram which may raise an -exception followed by simple scalar assignments, all (call and assignments) -protected by a handler which only performs scalar assignments that never -raise. Statements never reached either because the outer subprogram isn't -called or because the inner subprogram raised, shall be reported uncovered. +5 Predefined and user-defined exceptions shall be handled in the same + manner. +====== ====================================================================== .. rubric:: Testing Strategy -For local exceptions, we validate the requirements through a set of testcases -that exercise implicit or explicit exceptions for purposes of control flow -transfer. All the tescases follow a common pattern, involving: +We first validate all the rules in contexts where handlers are within the +subprogram where the exceptions get raised, known as *local handers*. The set +of testcases exercise implicit or explicit exceptions for purposes of control +flow transfer, involving: * Explicit ``raise`` statements, executed or not, followed by other statements - or not + or not, * Variations of these in subprograms or package bodies, directly within the top-level sequence of statements, and within nested block, conditional or loop statements, -* With one or more candidate handlers at different levels of nesting, - within a single body. - -For exceptions that may propagate from a called subprogram as in the -conditions stated in the requirement, we exercise situations where: +* With one or more candidate handlers, possibly at different levels of + block nesting within a single function or procedure body. -* The outer subprogram isn't called at all, +.. qmlink:: TCIndexImporter -* The inner subprogram is called only in conditions so it raises, + LocalHandlers -* The inner subprogram is called only in conditions so it does not raise, -* The inner subprogram is called in conditions so it raises and in conditions - so it does not raise. +Rules #1, 2 and 5 are checked by variations in most testcases and verified +more specifically by the *Raise* testcase, dedicated to this purpose. -.. qmlink:: TCIndexImporter +Rule #4 is verified by the dedicated *CutEvals* set of testcases. - * +Rule #3 is verified by the *Within* family of testcases, which exercise +conditional constructs within exception handlers in a variety of contexts +where such handlers may appear. +When conditional guards are involved, the coverage outcome is always checked +at least for situations where a guard is tested True only and False only. Very +often, testcases also verify the outcome when a guard is tested both True and +False or not at all. +.. qmlink:: TCIndexImporter + Propagation diff --git a/testsuite/Qualif/Environment/content.tmpl b/testsuite/Qualif/Environment/content.tmpl index 46ef4333d..6efbce3b7 100644 --- a/testsuite/Qualif/Environment/content.tmpl +++ b/testsuite/Qualif/Environment/content.tmpl @@ -93,23 +93,6 @@ In addition: pragma Restriction_Warnings (No_Finalization); pragma Restriction_Warnings (No_Implicit_Dynamic_Code); -* The tool is only partially qualified for analysis in presence of exceptions - which propagate across subprograms, when the runtime library profile - supports this at all. - - One possible way to ensure that the code subject to analysis conforms to - what this qualification material encompasses is to verify that it compiles - without error under control of a Zero Footprint Runtime Library Profile, or - free of warnings out of the following set of configuration pragmas:: - - pragma Restriction_Warnings (No_Exception_Registration); - pragma Restriction_Warnings (No_Exception_Handlers); - - Otherwise, for all uses (in subprograms subject to the analysis) of handlers - for exceptions not raised by the subprogram itself, users shall verify - conformance to what the Operational Requirements specifically prescribe for - such cases (:ref:`exceptions`). - * For mcdc assessments, the tool requires the use of short-circuit variants for the Boolean binary operators composing decisions: ``&&`` or ``||`` in C, ``and then`` or ``or else`` in Ada. From e43b9944754fc5bc287ef2fe21e9d3f63c371735 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 8 Mar 2023 05:44:51 -0800 Subject: [PATCH 0233/1483] Setup a dedicated subdir for LocalHandlers in stmt/Exceptions Preliminary changes acknowledging full support for exceptions that propagate, first grouping the tests verifying features available with local exception handling. Within Qualif/Ada/stmt/1_Core/11_Exceptions, add LocalHandlers/ and move: BlockPropagation -> LocalHandlers/AcrossBlocks CutEvals -> LocalHandlers/CutEvals Raise -> LocalHandlers/Raise Handlers -> LocalHandlers/SelectHandler with tc.rst adjustments. then add LocalHandlers/WithinElab LocalHandlers/WithinHandler LocalHandlers/WithinProc --- .../stmt/1_Core/11_Exceptions/Handlers/tc.rst | 3 -- .../AcrossBlocks}/src/pack.adb | 0 .../AcrossBlocks}/src/pack.ads | 0 .../AcrossBlocks}/src/test_1.adb | 0 .../AcrossBlocks}/src/test_2.adb | 0 .../AcrossBlocks}/src/test_ce.adb | 0 .../AcrossBlocks}/src/test_multiple.adb | 0 .../AcrossBlocks}/src/test_no.adb | 0 .../AcrossBlocks}/src/test_no_exception.adb | 0 .../AcrossBlocks}/tc.rst | 0 .../AcrossBlocks}/test.py | 0 .../And/Assign/IndexCheck/src/fuand.adb | 0 .../CutEvals/And/Assign/IndexCheck/tc.rst | 0 .../CutEvals/And/Assign/IndexCheck/test.py | 0 .../And/Assign/RangeCheck/src/fuand.adb | 0 .../CutEvals/And/Assign/RangeCheck/tc.rst | 0 .../CutEvals/And/Assign/RangeCheck/test.py | 0 .../And/Assign/RemoteCheck/src/fuand.adb | 0 .../CutEvals/And/Assign/RemoteCheck/tc.rst | 0 .../CutEvals/And/Assign/RemoteCheck/test.py | 0 .../CutEvals/And/Assign/tc_set.rst | 0 .../CutEvals/And/If/IndexCheck/src/fuand.adb | 0 .../CutEvals/And/If/IndexCheck/tc.rst | 0 .../CutEvals/And/If/IndexCheck/test.py | 0 .../CutEvals/And/If/RangeCheck/src/fuand.adb | 0 .../CutEvals/And/If/RangeCheck/tc.rst | 0 .../CutEvals/And/If/RangeCheck/test.py | 0 .../CutEvals/And/If/RemoteCheck/src/fuand.adb | 0 .../CutEvals/And/If/RemoteCheck/tc.rst | 0 .../CutEvals/And/If/RemoteCheck/test.py | 0 .../CutEvals/And/If/tc_set.rst | 0 .../And/Return/IndexCheck/src/fuand.adb | 0 .../CutEvals/And/Return/IndexCheck/tc.rst | 0 .../CutEvals/And/Return/IndexCheck/test.py | 0 .../And/Return/RangeCheck/src/fuand.adb | 0 .../CutEvals/And/Return/RangeCheck/tc.rst | 0 .../CutEvals/And/Return/RangeCheck/test.py | 0 .../And/Return/RemoteCheck/src/fuand.adb | 0 .../CutEvals/And/Return/RemoteCheck/tc.rst | 0 .../CutEvals/And/Return/RemoteCheck/test.py | 0 .../CutEvals/And/Return/tc_set.rst | 0 .../CutEvals/And/src/fuand.ads | 0 .../CutEvals/And/src/fuand_helper.adb | 0 .../CutEvals/And/src/fuand_helper.ads | 0 .../CutEvals/And/src/test_fuand_0.adb | 0 .../CutEvals/And/src/test_fuand_f_rx.adb | 0 .../CutEvals/And/src/test_fuand_f_tr.adb | 0 .../CutEvals/And/src/test_fuand_fu_rx.adb | 0 .../CutEvals/And/src/test_fuand_fu_tr.adb | 0 .../CutEvals/And/src/test_fuand_fx.adb | 0 .../CutEvals/And/src/test_fuand_rx.adb | 0 .../CutEvals/And/src/test_fuand_t_rx.adb | 0 .../CutEvals/And/src/test_fuand_t_tr.adb | 0 .../CutEvals/And/src/test_fuand_tf.adb | 0 .../CutEvals/And/src/test_fuand_tr.adb | 0 .../CutEvals/And/src/test_fuand_tt.adb | 0 .../CutEvals/And/tc_set.rst | 0 .../Flip/Assign/IndexCheck/src/flip.adb | 0 .../CutEvals/Flip/Assign/IndexCheck/tc.rst | 0 .../CutEvals/Flip/Assign/IndexCheck/test.py | 0 .../Flip/Assign/RangeCheck/src/flip.adb | 0 .../CutEvals/Flip/Assign/RangeCheck/tc.rst | 0 .../CutEvals/Flip/Assign/RangeCheck/test.py | 0 .../Flip/Assign/RemoteCheck/src/flip.adb | 0 .../CutEvals/Flip/Assign/RemoteCheck/tc.rst | 0 .../CutEvals/Flip/Assign/RemoteCheck/test.py | 0 .../CutEvals/Flip/Assign/tc_set.rst | 0 .../CutEvals/Flip/If/IndexCheck/src/flip.adb | 0 .../CutEvals/Flip/If/IndexCheck/tc.rst | 0 .../CutEvals/Flip/If/IndexCheck/test.py | 0 .../CutEvals/Flip/If/RangeCheck/src/flip.adb | 0 .../CutEvals/Flip/If/RangeCheck/tc.rst | 0 .../CutEvals/Flip/If/RangeCheck/test.py | 0 .../CutEvals/Flip/If/RemoteCheck/src/flip.adb | 0 .../CutEvals/Flip/If/RemoteCheck/tc.rst | 0 .../CutEvals/Flip/If/RemoteCheck/test.py | 0 .../CutEvals/Flip/If/tc_set.rst | 0 .../Flip/Return/IndexCheck/src/flip.adb | 0 .../CutEvals/Flip/Return/IndexCheck/tc.rst | 0 .../CutEvals/Flip/Return/IndexCheck/test.py | 0 .../Flip/Return/RangeCheck/src/flip.adb | 0 .../CutEvals/Flip/Return/RangeCheck/tc.rst | 0 .../CutEvals/Flip/Return/RangeCheck/test.py | 0 .../Flip/Return/RemoteCheck/src/flip.adb | 0 .../CutEvals/Flip/Return/RemoteCheck/tc.rst | 0 .../CutEvals/Flip/Return/RemoteCheck/test.py | 0 .../CutEvals/Flip/Return/tc_set.rst | 0 .../CutEvals/Flip/src/flip.ads | 0 .../CutEvals/Flip/src/flip_helper.adb | 0 .../CutEvals/Flip/src/flip_helper.ads | 0 .../CutEvals/Flip/src/test_flip_0.adb | 0 .../CutEvals/Flip/src/test_flip_f.adb | 0 .../CutEvals/Flip/src/test_flip_f_r.adb | 0 .../CutEvals/Flip/src/test_flip_fu_r.adb | 0 .../CutEvals/Flip/src/test_flip_r.adb | 0 .../CutEvals/Flip/src/test_flip_t.adb | 0 .../CutEvals/Flip/src/test_flip_t_r.adb | 0 .../CutEvals/Flip/src/test_flip_tf.adb | 0 .../CutEvals/Flip/tc_set.rst | 0 .../Or/Assign/IndexCheck/src/fuor.adb | 0 .../CutEvals/Or/Assign/IndexCheck/tc.rst | 0 .../CutEvals/Or/Assign/IndexCheck/test.py | 0 .../Or/Assign/RangeCheck/src/fuor.adb | 0 .../CutEvals/Or/Assign/RangeCheck/tc.rst | 0 .../CutEvals/Or/Assign/RangeCheck/test.py | 0 .../Or/Assign/RemoteCheck/src/fuor.adb | 0 .../CutEvals/Or/Assign/RemoteCheck/tc.rst | 0 .../CutEvals/Or/Assign/RemoteCheck/test.py | 0 .../CutEvals/Or/Assign/tc_set.rst | 0 .../CutEvals/Or/If/IndexCheck/src/fuor.adb | 0 .../CutEvals/Or/If/IndexCheck/tc.rst | 0 .../CutEvals/Or/If/IndexCheck/test.py | 0 .../CutEvals/Or/If/RangeCheck/src/fuor.adb | 0 .../CutEvals/Or/If/RangeCheck/tc.rst | 0 .../CutEvals/Or/If/RangeCheck/test.py | 0 .../CutEvals/Or/If/RemoteCheck/src/fuor.adb | 0 .../CutEvals/Or/If/RemoteCheck/tc.rst | 0 .../CutEvals/Or/If/RemoteCheck/test.py | 0 .../CutEvals/Or/If/tc_set.rst | 0 .../Or/Return/IndexCheck/src/fuor.adb | 0 .../CutEvals/Or/Return/IndexCheck/tc.rst | 0 .../CutEvals/Or/Return/IndexCheck/test.py | 0 .../Or/Return/RangeCheck/src/fuor.adb | 0 .../CutEvals/Or/Return/RangeCheck/tc.rst | 0 .../CutEvals/Or/Return/RangeCheck/test.py | 0 .../Or/Return/RemoteCheck/src/fuor.adb | 0 .../CutEvals/Or/Return/RemoteCheck/tc.rst | 0 .../CutEvals/Or/Return/RemoteCheck/test.py | 0 .../CutEvals/Or/Return/tc_set.rst | 0 .../CutEvals/Or/src/fuor.ads | 0 .../CutEvals/Or/src/fuor_helper.adb | 0 .../CutEvals/Or/src/fuor_helper.ads | 0 .../CutEvals/Or/src/test_fuor_0.adb | 0 .../CutEvals/Or/src/test_fuor_f_fr.adb | 0 .../CutEvals/Or/src/test_fuor_f_rx.adb | 0 .../CutEvals/Or/src/test_fuor_ff.adb | 0 .../CutEvals/Or/src/test_fuor_fr.adb | 0 .../CutEvals/Or/src/test_fuor_ft.adb | 0 .../CutEvals/Or/src/test_fuor_fu_fr.adb | 0 .../CutEvals/Or/src/test_fuor_fu_rx.adb | 0 .../CutEvals/Or/src/test_fuor_rx.adb | 0 .../CutEvals/Or/src/test_fuor_t_fr.adb | 0 .../CutEvals/Or/src/test_fuor_t_rx.adb | 0 .../CutEvals/Or/src/test_fuor_tx.adb | 0 .../CutEvals/Or/tc_set.rst | 0 .../Value/Assign/IndexCheck/src/val.adb | 0 .../CutEvals/Value/Assign/IndexCheck/tc.rst | 0 .../CutEvals/Value/Assign/IndexCheck/test.py | 0 .../Value/Assign/RangeCheck/src/val.adb | 0 .../CutEvals/Value/Assign/RangeCheck/tc.rst | 0 .../CutEvals/Value/Assign/RangeCheck/test.py | 0 .../Value/Assign/RemoteCheck/src/val.adb | 0 .../CutEvals/Value/Assign/RemoteCheck/tc.rst | 0 .../CutEvals/Value/Assign/RemoteCheck/test.py | 0 .../CutEvals/Value/Assign/tc_set.rst | 0 .../CutEvals/Value/If/IndexCheck/src/val.adb | 0 .../CutEvals/Value/If/IndexCheck/tc.rst | 0 .../CutEvals/Value/If/IndexCheck/test.py | 0 .../CutEvals/Value/If/RangeCheck/src/val.adb | 0 .../CutEvals/Value/If/RangeCheck/tc.rst | 0 .../CutEvals/Value/If/RangeCheck/test.py | 0 .../CutEvals/Value/If/RemoteCheck/src/val.adb | 0 .../CutEvals/Value/If/RemoteCheck/tc.rst | 0 .../CutEvals/Value/If/RemoteCheck/test.py | 0 .../CutEvals/Value/If/tc_set.rst | 0 .../Value/Return/IndexCheck/src/val.adb | 0 .../CutEvals/Value/Return/IndexCheck/tc.rst | 0 .../CutEvals/Value/Return/IndexCheck/test.py | 0 .../Value/Return/RangeCheck/src/val.adb | 0 .../CutEvals/Value/Return/RangeCheck/tc.rst | 0 .../CutEvals/Value/Return/RangeCheck/test.py | 0 .../Value/Return/RemoteCheck/src/val.adb | 0 .../CutEvals/Value/Return/RemoteCheck/tc.rst | 0 .../CutEvals/Value/Return/RemoteCheck/test.py | 0 .../CutEvals/Value/Return/tc_set.rst | 0 .../CutEvals/Value/src/test_val_0.adb | 0 .../CutEvals/Value/src/test_val_f.adb | 0 .../CutEvals/Value/src/test_val_f_r.adb | 0 .../CutEvals/Value/src/test_val_fu_r.adb | 0 .../CutEvals/Value/src/test_val_r.adb | 0 .../CutEvals/Value/src/test_val_t.adb | 0 .../CutEvals/Value/src/test_val_t_r.adb | 0 .../CutEvals/Value/src/test_val_tf.adb | 0 .../CutEvals/Value/src/val.ads | 0 .../CutEvals/Value/src/val_helper.adb | 0 .../CutEvals/Value/src/val_helper.ads | 0 .../CutEvals/Value/tc_set.rst | 0 .../{ => LocalHandlers}/CutEvals/src/args.adb | 0 .../{ => LocalHandlers}/CutEvals/src/args.ads | 0 .../{ => LocalHandlers}/CutEvals/tc_set.rst | 4 +- .../{ => LocalHandlers}/Raise/src/pack.adb | 0 .../{ => LocalHandlers}/Raise/src/pack.ads | 0 .../{ => LocalHandlers}/Raise/src/test_0.adb | 0 .../Raise/src/test_all_exception_raise.adb | 0 .../Raise/src/test_full.adb | 0 .../Raise/src/test_no_raise.adb | 0 .../Raise/src/test_raise_predefined.adb | 0 .../Raise/src/test_raise_user.adb | 0 .../11_Exceptions/LocalHandlers/Raise/tc.rst | 17 +++++++++ .../{Handlers => LocalHandlers/Raise}/test.py | 0 .../SelectHandler}/src/pack.adb | 0 .../SelectHandler}/src/pack.ads | 0 .../SelectHandler}/src/test_no.adb | 0 .../SelectHandler}/src/test_no_raise.adb | 0 .../SelectHandler}/src/test_raise_all.adb | 0 .../SelectHandler}/src/test_raise_predef.adb | 0 .../SelectHandler}/src/test_raise_user.adb | 0 .../LocalHandlers/SelectHandler/tc.rst | 8 ++++ .../SelectHandler}/test.opt | 0 .../SelectHandler}/test.py | 0 .../LocalHandlers/WithinElab/src/ctxt.adb | 38 +++++++++++++++++++ .../LocalHandlers/WithinElab/tc.rst | 3 ++ .../LocalHandlers/WithinElab/test.py | 5 +++ .../LocalHandlers/WithinHandler/src/ctxt.adb | 22 +++++++++++ .../LocalHandlers/WithinHandler/tc.rst | 3 ++ .../LocalHandlers/WithinHandler/test.py | 5 +++ .../LocalHandlers/WithinProc/src/ctxt.adb | 17 +++++++++ .../LocalHandlers/WithinProc/tc.rst | 3 ++ .../LocalHandlers/WithinProc/test.py | 5 +++ .../11_Exceptions/LocalHandlers/src/ctxt.ads | 13 +++++++ .../LocalHandlers/src/test_ctxt_iraise.adb | 17 +++++++++ .../LocalHandlers/src/test_ctxt_noraise.adb | 17 +++++++++ .../LocalHandlers/src/test_ctxt_xraise.adb | 17 +++++++++ .../11_Exceptions/LocalHandlers/tc_set.rst | 6 +++ .../stmt/1_Core/11_Exceptions/Raise/tc.rst | 3 -- 225 files changed, 198 insertions(+), 8 deletions(-) delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/tc.rst rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{BlockPropagation => LocalHandlers/AcrossBlocks}/src/pack.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{BlockPropagation => LocalHandlers/AcrossBlocks}/src/pack.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{BlockPropagation => LocalHandlers/AcrossBlocks}/src/test_1.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{BlockPropagation => LocalHandlers/AcrossBlocks}/src/test_2.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{BlockPropagation => LocalHandlers/AcrossBlocks}/src/test_ce.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{BlockPropagation => LocalHandlers/AcrossBlocks}/src/test_multiple.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{BlockPropagation => LocalHandlers/AcrossBlocks}/src/test_no.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{BlockPropagation => LocalHandlers/AcrossBlocks}/src/test_no_exception.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{BlockPropagation => LocalHandlers/AcrossBlocks}/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{BlockPropagation => LocalHandlers/AcrossBlocks}/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Assign/IndexCheck/src/fuand.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Assign/IndexCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Assign/IndexCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Assign/RangeCheck/src/fuand.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Assign/RangeCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Assign/RangeCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Assign/RemoteCheck/src/fuand.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Assign/RemoteCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Assign/RemoteCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Assign/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/If/IndexCheck/src/fuand.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/If/IndexCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/If/IndexCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/If/RangeCheck/src/fuand.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/If/RangeCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/If/RangeCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/If/RemoteCheck/src/fuand.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/If/RemoteCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/If/RemoteCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/If/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Return/IndexCheck/src/fuand.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Return/IndexCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Return/IndexCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Return/RangeCheck/src/fuand.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Return/RangeCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Return/RangeCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Return/RemoteCheck/src/fuand.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Return/RemoteCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Return/RemoteCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/Return/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/fuand.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/fuand_helper.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/fuand_helper.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/test_fuand_0.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/test_fuand_f_rx.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/test_fuand_f_tr.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/test_fuand_fu_rx.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/test_fuand_fu_tr.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/test_fuand_fx.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/test_fuand_rx.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/test_fuand_t_rx.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/test_fuand_t_tr.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/test_fuand_tf.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/test_fuand_tr.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/src/test_fuand_tt.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/And/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Assign/IndexCheck/src/flip.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Assign/IndexCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Assign/IndexCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Assign/RangeCheck/src/flip.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Assign/RangeCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Assign/RangeCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Assign/RemoteCheck/src/flip.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Assign/RemoteCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Assign/RemoteCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Assign/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/If/IndexCheck/src/flip.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/If/IndexCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/If/IndexCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/If/RangeCheck/src/flip.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/If/RangeCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/If/RangeCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/If/RemoteCheck/src/flip.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/If/RemoteCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/If/RemoteCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/If/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Return/IndexCheck/src/flip.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Return/IndexCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Return/IndexCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Return/RangeCheck/src/flip.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Return/RangeCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Return/RangeCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Return/RemoteCheck/src/flip.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Return/RemoteCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Return/RemoteCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/Return/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/src/flip.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/src/flip_helper.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/src/flip_helper.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/src/test_flip_0.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/src/test_flip_f.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/src/test_flip_f_r.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/src/test_flip_fu_r.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/src/test_flip_r.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/src/test_flip_t.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/src/test_flip_t_r.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/src/test_flip_tf.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Flip/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Assign/IndexCheck/src/fuor.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Assign/IndexCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Assign/IndexCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Assign/RangeCheck/src/fuor.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Assign/RangeCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Assign/RangeCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Assign/RemoteCheck/src/fuor.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Assign/RemoteCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Assign/RemoteCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Assign/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/If/IndexCheck/src/fuor.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/If/IndexCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/If/IndexCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/If/RangeCheck/src/fuor.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/If/RangeCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/If/RangeCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/If/RemoteCheck/src/fuor.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/If/RemoteCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/If/RemoteCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/If/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Return/IndexCheck/src/fuor.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Return/IndexCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Return/IndexCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Return/RangeCheck/src/fuor.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Return/RangeCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Return/RangeCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Return/RemoteCheck/src/fuor.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Return/RemoteCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Return/RemoteCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/Return/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/fuor.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/fuor_helper.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/fuor_helper.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/test_fuor_0.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/test_fuor_f_fr.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/test_fuor_f_rx.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/test_fuor_ff.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/test_fuor_fr.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/test_fuor_ft.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/test_fuor_fu_fr.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/test_fuor_fu_rx.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/test_fuor_rx.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/test_fuor_t_fr.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/test_fuor_t_rx.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/src/test_fuor_tx.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Or/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Assign/IndexCheck/src/val.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Assign/IndexCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Assign/IndexCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Assign/RangeCheck/src/val.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Assign/RangeCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Assign/RangeCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Assign/RemoteCheck/src/val.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Assign/RemoteCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Assign/RemoteCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Assign/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/If/IndexCheck/src/val.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/If/IndexCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/If/IndexCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/If/RangeCheck/src/val.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/If/RangeCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/If/RangeCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/If/RemoteCheck/src/val.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/If/RemoteCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/If/RemoteCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/If/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Return/IndexCheck/src/val.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Return/IndexCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Return/IndexCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Return/RangeCheck/src/val.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Return/RangeCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Return/RangeCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Return/RemoteCheck/src/val.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Return/RemoteCheck/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Return/RemoteCheck/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/Return/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/src/test_val_0.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/src/test_val_f.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/src/test_val_f_r.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/src/test_val_fu_r.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/src/test_val_r.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/src/test_val_t.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/src/test_val_t_r.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/src/test_val_tf.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/src/val.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/src/val_helper.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/src/val_helper.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/Value/tc_set.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/src/args.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/src/args.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/CutEvals/tc_set.rst (87%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/Raise/src/pack.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/Raise/src/pack.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/Raise/src/test_0.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/Raise/src/test_all_exception_raise.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/Raise/src/test_full.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/Raise/src/test_no_raise.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/Raise/src/test_raise_predefined.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{ => LocalHandlers}/Raise/src/test_raise_user.adb (100%) create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/tc.rst rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{Handlers => LocalHandlers/Raise}/test.py (100%) mode change 100644 => 100755 rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{Handlers => LocalHandlers/SelectHandler}/src/pack.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{Handlers => LocalHandlers/SelectHandler}/src/pack.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{Handlers => LocalHandlers/SelectHandler}/src/test_no.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{Handlers => LocalHandlers/SelectHandler}/src/test_no_raise.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{Handlers => LocalHandlers/SelectHandler}/src/test_raise_all.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{Handlers => LocalHandlers/SelectHandler}/src/test_raise_predef.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{Handlers => LocalHandlers/SelectHandler}/src/test_raise_user.adb (100%) create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/tc.rst rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{Handlers => LocalHandlers/SelectHandler}/test.opt (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/{Raise => LocalHandlers/SelectHandler}/test.py (100%) mode change 100755 => 100644 create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/src/ctxt.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/tc.rst create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/test.py create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/src/ctxt.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/tc.rst create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/test.py create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/src/ctxt.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/tc.rst create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/test.py create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/ctxt.ads create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_iraise.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_noraise.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_xraise.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/tc_set.rst delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/tc.rst deleted file mode 100644 index 564eeec67..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/tc.rst +++ /dev/null @@ -1,3 +0,0 @@ -**Exercise SC on exception handlers for user-defined or standard exceptions** - -LRMREF: 11.2, 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/pack.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/pack.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/pack.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/pack.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/pack.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/pack.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/pack.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/pack.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_1.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_1.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_1.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_2.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_2.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_2.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_ce.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_ce.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_ce.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_ce.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_multiple.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_multiple.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_multiple.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_multiple.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_no.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_no.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_no.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_no_exception.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_no_exception.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/src/test_no_exception.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/src/test_no_exception.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/BlockPropagation/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/IndexCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/IndexCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/IndexCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/IndexCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RangeCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RangeCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RangeCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RangeCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RemoteCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RemoteCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RemoteCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RemoteCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Assign/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Assign/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/IndexCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/IndexCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/IndexCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/IndexCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RangeCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RangeCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RangeCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RangeCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RemoteCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RemoteCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RemoteCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RemoteCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/If/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/If/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/IndexCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/IndexCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RangeCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RangeCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RemoteCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/src/fuand.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RemoteCheck/src/fuand.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/src/fuand.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/Return/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/fuand.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/fuand.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/fuand.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/fuand.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/fuand_helper.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/fuand_helper.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/fuand_helper.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/fuand_helper.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/fuand_helper.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/fuand_helper.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/fuand_helper.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/fuand_helper.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_0.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_0.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_0.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_f_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_f_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_f_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_f_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_f_tr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_f_tr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_f_tr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_f_tr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_fu_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_fu_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_fu_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_fu_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_fu_tr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_fu_tr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_fu_tr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_fu_tr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_fx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_fx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_fx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_fx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_t_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_t_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_t_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_t_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_t_tr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_t_tr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_t_tr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_t_tr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_tf.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_tf.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_tf.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_tf.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_tr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_tr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_tr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_tr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_tt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_tt.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/src/test_fuand_tt.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/src/test_fuand_tt.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/And/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/IndexCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/IndexCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/IndexCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/IndexCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RangeCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RangeCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RangeCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RangeCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RemoteCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RemoteCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RemoteCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RemoteCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Assign/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Assign/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/IndexCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/IndexCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/IndexCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/IndexCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RangeCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RangeCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RangeCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RangeCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RemoteCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RemoteCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RemoteCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RemoteCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/If/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/If/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/IndexCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/IndexCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RangeCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RangeCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RemoteCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/src/flip.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RemoteCheck/src/flip.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/src/flip.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/Return/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/flip.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/flip.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/flip.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/flip.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/flip_helper.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/flip_helper.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/flip_helper.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/flip_helper.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/flip_helper.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/flip_helper.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/flip_helper.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/flip_helper.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_0.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_0.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_0.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_f.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_f.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_f.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_f.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_f_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_f_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_f_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_f_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_fu_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_fu_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_fu_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_fu_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_t.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_t.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_t.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_t.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_t_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_t_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_t_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_t_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_tf.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_tf.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/src/test_flip_tf.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/src/test_flip_tf.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Flip/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/IndexCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/IndexCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/IndexCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/IndexCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RangeCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RangeCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RangeCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RangeCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RemoteCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RemoteCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RemoteCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RemoteCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Assign/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Assign/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/IndexCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/IndexCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/IndexCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/IndexCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RangeCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RangeCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RangeCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RangeCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RemoteCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RemoteCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RemoteCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RemoteCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/If/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/If/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/IndexCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/IndexCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RangeCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RangeCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RemoteCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/src/fuor.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RemoteCheck/src/fuor.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/src/fuor.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/Return/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/fuor.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/fuor.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/fuor.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/fuor.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/fuor_helper.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/fuor_helper.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/fuor_helper.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/fuor_helper.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/fuor_helper.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/fuor_helper.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/fuor_helper.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/fuor_helper.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_0.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_0.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_0.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_f_fr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_f_fr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_f_fr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_f_fr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_f_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_f_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_f_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_f_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_ff.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_ff.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_ff.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_ff.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_fr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_fr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_fr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_fr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_ft.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_ft.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_ft.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_ft.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_fu_fr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_fu_fr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_fu_fr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_fu_fr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_fu_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_fu_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_fu_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_fu_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_t_fr.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_t_fr.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_t_fr.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_t_fr.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_t_rx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_t_rx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_t_rx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_t_rx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_tx.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_tx.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/src/test_fuor_tx.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/src/test_fuor_tx.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Or/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/IndexCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/IndexCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/IndexCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/IndexCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RangeCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RangeCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RangeCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RangeCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RemoteCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RemoteCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RemoteCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RemoteCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Assign/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Assign/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/IndexCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/IndexCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/IndexCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/IndexCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RangeCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RangeCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RangeCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RangeCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RemoteCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RemoteCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RemoteCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RemoteCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/If/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/If/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/IndexCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/IndexCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/IndexCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/IndexCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/IndexCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/IndexCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/IndexCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/IndexCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/IndexCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/IndexCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/IndexCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/IndexCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RangeCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RangeCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RangeCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RangeCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RangeCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RangeCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RemoteCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RemoteCheck/src/val.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RemoteCheck/src/val.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RemoteCheck/src/val.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RemoteCheck/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RemoteCheck/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RemoteCheck/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RemoteCheck/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RemoteCheck/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RemoteCheck/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/RemoteCheck/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RemoteCheck/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/Return/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_0.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_0.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_0.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_f.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_f.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_f.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_f.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_f_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_f_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_f_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_f_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_fu_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_fu_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_fu_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_fu_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_t.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_t.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_t.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_t.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_t_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_t_r.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_t_r.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_t_r.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_tf.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_tf.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/test_val_tf.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/test_val_tf.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/val.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/val.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/val.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/val.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/val_helper.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/val_helper.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/val_helper.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/val_helper.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/val_helper.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/val_helper.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/src/val_helper.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/src/val_helper.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/tc_set.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/Value/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/tc_set.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/src/args.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/src/args.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/src/args.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/src/args.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/src/args.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/src/args.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/src/args.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/src/args.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/tc_set.rst similarity index 87% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/tc_set.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/tc_set.rst index f2ddc3bb5..916ae179c 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/CutEvals/tc_set.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/tc_set.rst @@ -8,7 +8,7 @@ statements. For each variant, check a variety of situations where -* No exception gets raised at all +* No exception gets raised at all, * An exception gets raised as part of all the evaluation attempts, on the first or the last operand evaluation, @@ -16,7 +16,7 @@ For each variant, check a variety of situations where * An exception would be raised by one operand but is not because of the shortcircuit semantics, -* An exception is raised by some evaluation but not others +* An exception is raised by some evaluation but not others. .. qmlink:: TCIndexImporter diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/pack.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/pack.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/pack.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/pack.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/pack.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/pack.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/pack.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/pack.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_0.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_0.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_0.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_all_exception_raise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_all_exception_raise.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_all_exception_raise.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_all_exception_raise.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_full.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_full.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_full.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_no_raise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_no_raise.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_no_raise.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_no_raise.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_raise_predefined.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_raise_predefined.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_raise_predefined.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_raise_predefined.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_raise_user.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_raise_user.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/src/test_raise_user.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/src/test_raise_user.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/tc.rst new file mode 100644 index 000000000..bf5086418 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/tc.rst @@ -0,0 +1,17 @@ +**Exercise SC on a variety of situations involving raise operations** + +Exercise procedures and functions including conditional raise +statements for predefined or user defined exceptions, all handled +locally and followed by simple statements. Check situations where the +raise operation gets triggered or not, enforcing variations on the +conditionals guards. Verify that the explicit raise statements are +properly processed as regular statements and that the control flow +transfers are reflected on the coverage status of the statements +following the raise and in the exception handlers. + +Also exercise a few cases involving implicit raise events, for example +out of a range check. Verify that the control flow effects induced by +such events is also properly represented, on the triggering statements +and those that immediately follow. + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/test.py old mode 100644 new mode 100755 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/pack.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/pack.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/pack.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/pack.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/pack.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/pack.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/pack.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/pack.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_no.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_no.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_no.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_no_raise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_no_raise.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_no_raise.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_no_raise.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_raise_all.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_raise_all.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_raise_all.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_raise_all.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_raise_predef.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_raise_predef.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_raise_predef.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_raise_predef.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_raise_user.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_raise_user.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/src/test_raise_user.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/src/test_raise_user.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/tc.rst new file mode 100644 index 000000000..7c9b34677 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/tc.rst @@ -0,0 +1,8 @@ +**Exercise SC on subprograms with a choice of handlers for a block** + +Check a variety of subprograms which may raise either a standard +exception or a user defined one, handling the occurrence with a +dedicated handler selected either explicitly or as a default by +way of a "when others" alternative. + +LRMREF: 11.2, 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.opt similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Handlers/test.opt rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.opt diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.py old mode 100755 new mode 100644 similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/src/ctxt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/src/ctxt.adb new file mode 100644 index 000000000..603afb7b9 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/src/ctxt.adb @@ -0,0 +1,38 @@ +pragma Unsuppress (All_Checks); + +package body Ctxt is + + generic + Iraise : Boolean; + Xraise : Boolean; + package G_Checker is + end; + + package body G_Checker is + begin + declare + procedure Check (Iraise, Xraise : Boolean) is + begin + X := X + 1; -- # pre + if Iraise then -- # ieval + R0 := I1; -- # iraise + elsif Xraise then -- # xeval + raise Constraint_Error; -- # xraise + end if; + X := X + 1; -- # post + exception + when Constraint_Error => + Handled := Handled + 1; -- # handler + end; + begin + Check (Iraise => Iraise, Xraise => Xraise); -- # pre + end; + end; + + procedure Run (Iraise, Xraise : Boolean) is + package Checker is + new G_Checker (Iraise => Iraise, Xraise => Xraise); + begin + null; -- # pre + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/tc.rst new file mode 100644 index 000000000..fc6e7c780 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/tc.rst @@ -0,0 +1,3 @@ +**Exercise SC on local exceptions within a generic package elaboration** + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/src/ctxt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/src/ctxt.adb new file mode 100644 index 000000000..e5a4fcd4f --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/src/ctxt.adb @@ -0,0 +1,22 @@ +pragma Unsuppress (All_Checks); + +package body Ctxt is + procedure Run (Iraise, Xraise : Boolean) is + begin + R0 := I1; -- # pre + exception + when others => + begin + X := X + 1; -- # pre + if Iraise then -- # ieval + R0 := I1; -- # iraise + elsif Xraise then -- # xeval + raise Constraint_Error; -- # xraise + end if; + X := X + 1; -- # post + exception + when Constraint_Error => + Handled := Handled + 1; -- # handler + end; + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/tc.rst new file mode 100644 index 000000000..6ffdb3071 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/tc.rst @@ -0,0 +1,3 @@ +**Exercise SC on local exceptions within an exception handler** + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinHandler/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/src/ctxt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/src/ctxt.adb new file mode 100644 index 000000000..83e981f92 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/src/ctxt.adb @@ -0,0 +1,17 @@ +package body Ctxt is + pragma Unsuppress (All_Checks); + + procedure Run (Iraise, Xraise : Boolean) is + begin + X := X + 1; -- # pre + if Iraise then -- # ieval + R0 := I1; -- # iraise + elsif Xraise then -- # xeval + raise Constraint_Error; -- # xraise + end if; + X := X + 1; -- # post + exception + when Constraint_Error => + Handled := Handled + 1; -- # handler + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/tc.rst new file mode 100644 index 000000000..34b9aa113 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/tc.rst @@ -0,0 +1,3 @@ +**Exercise SC on local exceptions within a regular subprogram** + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinProc/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/ctxt.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/ctxt.ads new file mode 100644 index 000000000..87f807554 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/ctxt.ads @@ -0,0 +1,13 @@ + +package Ctxt is + -- Prevent compilation warnings on some versions of ctxt.adb + -- where X is accessed within generic bodies: + pragma Elaborate_Body; + + X : Integer; + R0 : Integer range 0 .. 0 := 0; + I1 : Integer := 1; + + Handled : Integer := 0; + procedure Run (Iraise, Xraise : Boolean); +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_iraise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_iraise.adb new file mode 100644 index 000000000..38b499bd7 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_iraise.adb @@ -0,0 +1,17 @@ +with Ctxt, Support; use Ctxt, Support; + +procedure Test_Ctxt_Iraise is +begin + Ctxt.Run (Iraise => True, Xraise => False); +end; + +--# ctxt.adb +-- /pre/ l+ ## 0 +-- /ieval/ l+ ## 0 +-- /iraise/ l+ ## 0 +-- /xeval/ l- ## s- +-- /xraise/ l- ## s- +-- /post/ l- ## s- +-- /handler/ l+ ## 0 +-- /other/ l- ## s- + diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_noraise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_noraise.adb new file mode 100644 index 000000000..332bb1470 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_noraise.adb @@ -0,0 +1,17 @@ +with Ctxt, Support; use Ctxt, Support; + +procedure Test_Ctxt_Noraise is +begin + Ctxt.Run (Iraise => False, Xraise => False); +end; + +--# ctxt.adb +-- /pre/ l+ ## 0 +-- /ieval/ l+ ## 0 +-- /iraise/ l- ## s- +-- /xeval/ l+ ## 0 +-- /xraise/ l- ## s- +-- /post/ l+ ## 0 +-- /handler/ l- ## s- +-- /other/ l- ## s- + diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_xraise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_xraise.adb new file mode 100644 index 000000000..1e1b9a709 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_xraise.adb @@ -0,0 +1,17 @@ +with Ctxt, Support; use Ctxt, Support; + +procedure Test_Ctxt_Xraise is +begin + Ctxt.Run (Iraise => False, Xraise => True); +end; + +--# ctxt.adb +-- /pre/ l+ ## 0 +-- /ieval/ l+ ## 0 +-- /iraise/ l- ## s- +-- /xeval/ l+ ## 0 +-- /xraise/ l+ ## 0 +-- /post/ l- ## s- +-- /handler/ l+ ## 0 +-- /other/ l- ## s- + diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/tc_set.rst new file mode 100644 index 000000000..b41abc5cc --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/tc_set.rst @@ -0,0 +1,6 @@ +Check SC with exceptions never propagating across subprograms +============================================================= + +.. qmlink:: TCIndexImporter + + * diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/tc.rst deleted file mode 100644 index 998393a41..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Raise/tc.rst +++ /dev/null @@ -1,3 +0,0 @@ -**Exercise SC with multiple kinds of raise operations, implicit or explicit** - -LRMREF: 11.2, 11.3, 11.4 From 4a2849616997f48bc227340c049b9f91f58a3d6f Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Tue, 14 Mar 2023 11:08:04 -0700 Subject: [PATCH 0234/1483] Refine our local testuite silent_last_chance handler Use exit(0) to terminate silently with a status code indicating success, replacing the current use of "abort" which entails an error exit code. This helps tests raising unhandled exceptions on purpose in native configurations and "exit" should now be available in all our supported configurations, modulo an explicit -lc with some BB runtimes. --- .../Qualif/Ada/src/silent_last_chance.adb | 18 +++++++++++++----- .../Qualif/Ada/src/silent_last_chance.ads | 4 ++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/testsuite/Qualif/Ada/src/silent_last_chance.adb b/testsuite/Qualif/Ada/src/silent_last_chance.adb index e5b394bd3..ed072d934 100644 --- a/testsuite/Qualif/Ada/src/silent_last_chance.adb +++ b/testsuite/Qualif/Ada/src/silent_last_chance.adb @@ -1,5 +1,14 @@ package body Silent_Last_Chance is + -- Use exit(0) to terminate silently with a status code + -- indicating success. Abort would result in an error status + -- and _exit would bypass the atexit handlers, crucial to + -- get meaningful traces out of instrumented programs in native + -- configurations. + + -- This requires dragging libc explicitly in BB configurations. + pragma Linker_Options ("-lc"); + ------------------------- -- Last_Chance_Handler -- ------------------------- @@ -7,12 +16,11 @@ package body Silent_Last_Chance is procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is pragma Unreferenced (Msg, Line); - procedure C_abort; - pragma Import (C, C_abort, "abort"); - pragma No_Return (C_abort); + procedure C_exit (Status : Integer); + pragma Import (C, C_exit, "exit"); + pragma No_Return (C_exit); begin - -- No return procedure. - C_abort; + C_exit(0); end Last_Chance_Handler; end; diff --git a/testsuite/Qualif/Ada/src/silent_last_chance.ads b/testsuite/Qualif/Ada/src/silent_last_chance.ads index 592d7f506..5b54a7b87 100644 --- a/testsuite/Qualif/Ada/src/silent_last_chance.ads +++ b/testsuite/Qualif/Ada/src/silent_last_chance.ads @@ -1,5 +1,9 @@ with System; +-- Provide a last_chance_handler for tests that trigger an unhandled +-- exception on purpose. The handler arranges not to output a message +-- and to terminate with a status code indicating success. + package Silent_Last_Chance is Unexpected_Last_Chance_Call : Integer := 0; From 3bd3bb9f75f3113e3e6b43afd4eb2d6bd7c79bcd Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 22 Feb 2023 14:12:21 -0800 Subject: [PATCH 0235/1483] Extend Qualif tests to exercise exception propagation Rename Propagation/Basic as Propagation/Basics Introduce a family of extended tests checking various exception kinds that propagate either directly or via a reraise and get handled in a variety of contexts, or not handled at all. --- .../Propagation/Basic/src/ops.adb | 51 ---------- .../Propagation/Basics/src/ops.adb | 94 +++++++++++++++++++ .../Propagation/{Basic => Basics}/src/ops.ads | 3 +- .../{Basic => Basics}/src/test_ops_fault.adb | 12 ++- .../{Basic => Basics}/src/test_ops_full.adb | 14 ++- .../src/test_ops_nofault.adb | 12 ++- .../Propagation/{Basic => Basics}/tc.rst | 0 .../Propagation/{Basic => Basics}/test.py | 0 .../Propagation/RaiseFromRTS/src/ops.adb | 15 --- .../Propagation/RaiseFromRTS/src/ops.ads | 4 - .../Propagation/RaiseFromRTS/src/test_0.adb | 12 --- .../Propagation/RaiseFromRTS/src/test_all.adb | 17 ---- .../RaiseFromRTS/src/test_fault.adb | 15 --- .../Propagation/RaiseFromRTS/src/test_ok.adb | 15 --- .../Propagation/RaiseFromRTS/tc.rst | 12 --- .../Propagation/Unhandled/src/ctxt.adb | 11 +++ .../Propagation/Unhandled/tc.rst | 3 + .../{RaiseFromRTS => Unhandled}/test.py | 0 .../Propagation/WithinHandler/src/ctxt.adb | 68 ++++++++++++++ .../Propagation/WithinHandler/tc.rst | 3 + .../Propagation/WithinHandler/test.py | 5 + .../Propagation/WithinProc/src/ctxt.adb | 17 ++++ .../Propagation/WithinProc/tc.rst | 3 + .../Propagation/WithinProc/test.py | 5 + .../11_Exceptions/Propagation/src/ctxt.ads | 15 +++ .../11_Exceptions/Propagation/src/doraise.adb | 83 ++++++++++++++++ .../11_Exceptions/Propagation/src/doraise.ads | 25 +++++ .../Propagation/src/test_ctxt_ice_r1.adb | 40 ++++++++ .../Propagation/src/test_ctxt_ice_ro.adb | 40 ++++++++ .../Propagation/src/test_ctxt_ice_st.adb | 40 ++++++++ .../Propagation/src/test_ctxt_noraise.adb | 40 ++++++++ .../Propagation/src/test_ctxt_rts_r1.adb | 40 ++++++++ .../Propagation/src/test_ctxt_rts_ro.adb | 40 ++++++++ .../Propagation/src/test_ctxt_rts_st.adb | 40 ++++++++ .../Propagation/src/test_ctxt_xpe_r1.adb | 40 ++++++++ .../Propagation/src/test_ctxt_xpe_ro.adb | 40 ++++++++ .../Propagation/src/test_ctxt_xpe_st.adb | 40 ++++++++ .../Propagation/src/test_ctxt_xue_r1.adb | 40 ++++++++ .../Propagation/src/test_ctxt_xue_ro.adb | 40 ++++++++ .../Propagation/src/test_ctxt_xue_st.adb | 40 ++++++++ .../11_Exceptions/Propagation/tc_set.rst | 3 - .../Ada/stmt/1_Core/11_Exceptions/req.rst | 21 ++++- 42 files changed, 905 insertions(+), 153 deletions(-) delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/ops.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.adb rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/{Basic => Basics}/src/ops.ads (59%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/{Basic => Basics}/src/test_ops_fault.adb (53%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/{Basic => Basics}/src/test_ops_full.adb (61%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/{Basic => Basics}/src/test_ops_nofault.adb (55%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/{Basic => Basics}/tc.rst (100%) rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/{Basic => Basics}/test.py (100%) delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.ads delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_0.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_all.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_fault.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_ok.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/tc.rst create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/src/ctxt.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/tc.rst rename testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/{RaiseFromRTS => Unhandled}/test.py (100%) create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/src/ctxt.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/tc.rst create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/test.py create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/src/ctxt.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/tc.rst create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/test.py create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/ctxt.ads create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.ads create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_r1.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_ro.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_st.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_noraise.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_r1.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_ro.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_st.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_r1.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_ro.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_st.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_r1.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_ro.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_st.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/ops.adb deleted file mode 100644 index d5492782b..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/ops.adb +++ /dev/null @@ -1,51 +0,0 @@ -package body Ops is - - procedure Div_CE (X, Y : Integer; T : out Integer) is - begin - if Y = 0 then -- # stmt - raise Constraint_Error; -- # fault - end if; - T := X / Y; -- # no_fault - end; - - Div_Error : exception; - - procedure Div_DE (X, Y : Integer; T : out Integer) is - begin - if Y = 0 then -- # stmt - raise Div_Error; -- # fault - end if; - T := X / Y; -- # no_fault - end; - - -- - - procedure Div - (X, Y : Integer; T : out Integer; Fault : out Boolean) - is - CE_Fault, DE_Fault : Boolean; - begin - begin - Div_CE (X, Y, T); -- # stmt - CE_Fault := False; -- # no_fault - exception - when Constraint_Error => - CE_Fault := True; -- # fault - when others => - null; -- # bad_handler - end; - - begin - Div_DE (X, Y, T); -- # stmt - DE_Fault := False; -- # no_fault - exception - when Div_Error => - DE_Fault := True; -- # fault - when others => - null; -- # bad_handler - end; - - Fault := CE_Fault or else DE_Fault; -- # stmt - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.adb new file mode 100644 index 000000000..c8c3c7c1f --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.adb @@ -0,0 +1,94 @@ +package body Ops is + + -- req-rule #4 + + pragma Unsuppress (All_Checks); + I2 : Integer := 2; + pragma Volatile (I2); + + procedure Fail_Range_Check is + subtype R1_1 is Integer range 1 .. 1; + X : R1_1; -- # stmt + begin + X := I2; -- # stmt + end; + + procedure Div_CE (X, Y : Integer; T : out Integer) is + begin + if Y = 0 then -- # stmt + raise Constraint_Error; -- # div_fault req-rule #1 and #5 + end if; + T := X / Y; -- # no_div_fault + end; + + Div_Error : exception; + + procedure Div_DE (X, Y : Integer; T : out Integer) is + begin + if Y = 0 then -- # stmt + raise Div_Error; -- # div_fault req-rule #1 and #5 + end if; + T := X / Y; -- # no_div_fault req-rule #2 + end; + + -- + + procedure Div + (X, Y : Integer; T : out Integer; Fault : out Boolean) + is + CE_Fault, DE_Fault : Boolean; + + begin + + -- req-rule #4 + + begin + Fail_Range_Check; -- # stmt + exception + when Constraint_Error => null; -- # stmt + end; + + begin + Div_CE (X, Y, T); -- # stmt + CE_Fault := False; -- # no_div_fault req-rule #2 + exception + when Constraint_Error => + CE_Fault := True; -- # div_fault req-rule #3 and #5 + when others => + null; -- # bad_handler req-rule #3 + end; + + begin + Div_DE (X, Y, T); -- # stmt + DE_Fault := False; -- # no_div_fault req-rule #2 + exception + when Div_Error => + DE_Fault := True; -- # div_fault req-rule #3 and #5 + when others => + null; -- # bad_handler req-rule #3 + end; + + Fault := CE_Fault or else DE_Fault; -- # stmt + end; + + -- + + pragma Unsuppress (All_Checks); + + procedure Do_Bump (X : in out Integer) is + One : Integer := 1; + pragma Volatile (One); + begin + -- This will raise constraint_error on integer'last + X := One * (X + One); -- # do_bump #4 + end; + + procedure Bump (X : in out Integer; Fault : out Boolean) is + begin + Do_Bump (X); -- # do_bump + Fault := False; -- # no_bump_fault #2 + exception + when Constraint_Error => + Fault := True; -- # bump_fault #3 + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/ops.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.ads similarity index 59% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/ops.ads rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.ads index dd79e1b99..82d51bebc 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/ops.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.ads @@ -1,5 +1,4 @@ package Ops is procedure Div (X, Y : Integer; T : out Integer; Fault : out Boolean); - - N_Faults : Integer := 0; + procedure Bump (X : in out Integer; Fault : out Boolean); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_fault.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_fault.adb similarity index 53% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_fault.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_fault.adb index 6fc05ac5c..14226cd21 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_fault.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_fault.adb @@ -6,10 +6,18 @@ procedure Test_Ops_Fault is begin Div (1, 0, T, Fault); Assert (Fault); + + T := Integer'Last; + Bump (T, Fault); + Assert (Fault); end; --# ops.adb --- /fault/ l+ ## 0 --- /no_fault/ l- ## s- +-- /div_fault/ l+ ## 0 +-- /no_div_fault/ l- ## s- -- /stmt/ l+ ## 0 -- /bad_handler/ l- ## s- + +-- /do_bump/ l+ ## 0 +-- /bump_fault/ l+ ## 0 +-- /no_bump_fault/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_full.adb similarity index 61% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_full.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_full.adb index 11c1e59d3..7af72cce7 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_full.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_full.adb @@ -6,10 +6,18 @@ procedure Test_Ops_Full is begin Div (4, 0, T, Fault); Assert (Fault); - + Div (4, 2, T, Fault); Assert (T = 2); Assert (not Fault); + + Bump (T, Fault); + Assert (T = 3); + Assert (not Fault); + + T := Integer'Last; + Bump (T, Fault); + Assert (Fault); end; --# ops.adb @@ -17,3 +25,7 @@ end; -- /no_fault/ l+ ## 0 -- /stmt/ l+ ## 0 -- /bad_handler/ l- ## s- + +-- /do_bump/ l+ ## 0 +-- /bump_fault/ l+ ## 0 +-- /no_bump_fault/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_nofault.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_nofault.adb similarity index 55% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_nofault.adb rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_nofault.adb index e4514ea6c..4526066d8 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/src/test_ops_nofault.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/test_ops_nofault.adb @@ -7,10 +7,18 @@ begin Div (4, 2, T, Fault); Assert (T = 2); Assert (not Fault); + + Bump (T, Fault); + Assert (T = 3); + Assert (not Fault); end; --# ops.adb --- /fault/ l- ## s- --- /no_fault/ l+ ## 0 +-- /div_fault/ l- ## s- +-- /no_div_fault/ l+ ## 0 -- /stmt/ l+ ## 0 -- /bad_handler/ l- ## s- + +-- /do_bump/ l+ ## 0 +-- /bump_fault/ l- ## s- +-- /no_bump_fault/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/tc.rst rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/tc.rst diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basic/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.adb deleted file mode 100644 index ab2c70425..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.adb +++ /dev/null @@ -1,15 +0,0 @@ - -package body Ops is - - procedure To_Integer - (S : String; Value : out Integer; Fault : out Boolean) - is - begin - Value := Integer'Value (S); -- # convert - Fault := False; -- # no_fault - exception - when others => - Value := 0; -- # fault - Fault := True; -- # fault - end; -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.ads deleted file mode 100644 index c142bdb9c..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/ops.ads +++ /dev/null @@ -1,4 +0,0 @@ -package Ops is - procedure To_Integer - (S : String; Value : out Integer; Fault : out Boolean); -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_0.adb deleted file mode 100644 index 163ce16fd..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_0.adb +++ /dev/null @@ -1,12 +0,0 @@ -with Support, Ops; use Support, Ops; - -procedure Test_0 is -begin - null; -end; - ---# ops.adb --- /convert/ l- ## s- --- /no_fault/ l- ## s- --- /fault/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_all.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_all.adb deleted file mode 100644 index 6ba2fb64a..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_all.adb +++ /dev/null @@ -1,17 +0,0 @@ -with Support, Ops; use Support, Ops; - -procedure Test_All is - X : Integer; - Fault : Boolean; -begin - To_Integer ("36", X, Fault); - Assert (X = 36 and then not Fault); - To_Integer ("blue", X, Fault); - Assert (X = 0 and then Fault); -end; - ---# ops.adb --- /convert/ l+ ## 0 --- /no_fault/ l+ ## 0 --- /fault/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_fault.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_fault.adb deleted file mode 100644 index 57eae52a5..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_fault.adb +++ /dev/null @@ -1,15 +0,0 @@ -with Support, Ops; use Support, Ops; - -procedure Test_fault is - X : Integer; - Fault : Boolean; -begin - To_Integer ("blue", X, Fault); - Assert (X = 0 and then Fault); -end; - ---# ops.adb --- /convert/ l+ ## 0 --- /no_fault/ l- ## s- --- /fault/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_ok.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_ok.adb deleted file mode 100644 index 885ef1d3f..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/src/test_ok.adb +++ /dev/null @@ -1,15 +0,0 @@ -with Support, Ops; use Support, Ops; - -procedure Test_Ok is - X : Integer; - Fault : Boolean; -begin - To_Integer ("54", X, Fault); - Assert (X = 54 and then not Fault); -end; - ---# ops.adb --- /convert/ l+ ## 0 --- /no_fault/ l+ ## 0 --- /fault/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/tc.rst deleted file mode 100644 index 7cf20f80b..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/tc.rst +++ /dev/null @@ -1,12 +0,0 @@ -**SC on a simple wrapper around an external service call which might raise** - -Check the case of a simple subprogram which invokes an external service which -might raise, catching all the possible exceptions and setting indicators to -convey whether an exception occurred or not. - -Exercise cases when the external service raises an exception, does not -raise an exception, or a combination thereof. - -LRMREF: 11.2, 11.4 - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/src/ctxt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/src/ctxt.adb new file mode 100644 index 000000000..342539077 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/src/ctxt.adb @@ -0,0 +1,11 @@ +with Silent_Last_Chance; +with Doraise; use Doraise; + +package body Ctxt is + procedure Run (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + X := X + 1; -- # pre + Dispatch (Rk, Rm); -- # run + X := X + 1; -- # post + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/tc.rst new file mode 100644 index 000000000..f642f7733 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/tc.rst @@ -0,0 +1,3 @@ +**Exercise SC with unhandled exception propagation** + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/RaiseFromRTS/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Unhandled/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/src/ctxt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/src/ctxt.adb new file mode 100644 index 000000000..2410dfb7e --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/src/ctxt.adb @@ -0,0 +1,68 @@ +with Doraise; use Doraise; + +package body Ctxt is + + procedure Case1 (Rk : Raise_Kind; Rm : Raise_Mode); + -- Trigger an inner raise and handle within the same handler + + procedure Case2 (Rk : Raise_Kind; Rm : Raise_Mode); + procedure Case2_Helper (Rk : Raise_Kind; Rm : Raise_Mode); + -- Trigger an inner raise from within a handler and handle + -- one level up. + + procedure Run (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + Case1 (Rk, Rm); -- # pre + Case2 (Rk, Rm); -- # pre + end; + + procedure Case1 (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + X := X + 1; -- # pre + + -- Arrange to reach a handler ... + raise Constraint_Error; -- # pre + exception + when others => + begin + X := X + 1; -- # pre + Dispatch (Rk, Rm); -- # run + X := X + 1; -- # post + exception + when Constraint_Error => + Handled := Handled + 1; -- # ce_handler + when Program_Error => + Handled := Handled + 1; -- # pe_handler + when User_Error => + Handled := Handled + 1; -- # ue_handler + end; + end; + + -- + + procedure Case2 (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + X := X + 1; -- # pre + Case2_Helper (Rk, Rm); -- # pre + exception + when Constraint_Error => + Handled := Handled + 1; -- # ce_handler + when Program_Error => + Handled := Handled + 1; -- # pe_handler + when User_Error => + Handled := Handled + 1; -- # ue_handler + end; + + procedure Case2_Helper (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + -- Arrange to reach a handler ... + raise Constraint_Error; -- # pre + exception + when others => + begin + X := X + 1; -- # pre + Dispatch (Rk, Rm); -- # run + X := X + 1; -- # post + end; + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/tc.rst new file mode 100644 index 000000000..933de7b83 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/tc.rst @@ -0,0 +1,3 @@ +**Exercise SC with exception propagation handled within an exception handler** + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinHandler/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/src/ctxt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/src/ctxt.adb new file mode 100644 index 000000000..0b84cdd23 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/src/ctxt.adb @@ -0,0 +1,17 @@ +with Doraise; use Doraise; + +package body Ctxt is + procedure Run (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + X := X + 1; -- # pre + Dispatch (Rk, Rm); -- # run + X := X + 1; -- # post + exception + when Constraint_Error => + Handled := Handled + 1; -- # ce_handler + when Program_Error => + Handled := Handled + 1; -- # pe_handler + when User_Error => + Handled := Handled + 1; -- # ue_handler + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/tc.rst new file mode 100644 index 000000000..f68f69afd --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/tc.rst @@ -0,0 +1,3 @@ +**Exercise SC with exception propagation handled within a regular subprogram** + +LRMREF: 11.2, 11.3, 11.4 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/test.py b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/WithinProc/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/ctxt.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/ctxt.ads new file mode 100644 index 000000000..1493115e6 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/ctxt.ads @@ -0,0 +1,15 @@ +with Doraise; use Doraise; + +package Ctxt is + + -- A few globals that let us insert statements at various + -- spots and sanity check the logic we ran through. + + X : Integer := 0; + Handled : Integer := 0; + + procedure Run (Rk : Raise_Kind; Rm : Raise_Mode); + -- Invoke and optionally handle Doraise operations in a specific + -- context. Body to be provided by the various testcases, each + -- exercising a particular situation. +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.adb new file mode 100644 index 000000000..1ad38c8fd --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.adb @@ -0,0 +1,83 @@ +with Ctxt; use Ctxt; + +package body Doraise is + + pragma Unsuppress (All_Checks); + + procedure Do_Raise (Rk : Raise_Kind) is + + -- This is the common procedure called to perform a raise to + -- be propagated. It is not called at all for Raise_Mode None, + -- so the "pre" or "run" anchors aren't appropriate here. + -- + -- do_raise-pre is introduced instead, needed at least for + -- the declarations below. + + -- Entities to help trigger specific kinds of occurrences + + R0 : Integer range 0 .. 0 := 0; -- # do_raise-pre + I1 : Integer := 1; -- # do_raise-pre + pragma Volatile (I1); + + Vint : Integer; -- # do_raise-pre + Vstr : String := "blue"; -- # do_raise-pre + pragma Volatile (Vstr); + + begin + X := X + 1; -- # do_raise-pre + if Rk = Implicit_CE then -- # ice-eval + R0 := I1; -- # ice-raise + + elsif Rk = Explicit_PE then -- # xpe-eval + raise Program_Error; -- # xpe-raise + + elsif Rk = Explicit_UE then -- # xue-eval + raise User_Error; -- # xue-raise + + elsif Rk = From_RTS then -- # rts-eval + Vint := Integer'Value(Vstr); -- # rts-raise + + end if; + X := X + 1; -- # do_raise-post + end; + + procedure Do_Reraise_One (Rk : Raise_Kind) is + begin + Do_Raise (Rk); -- # call_reraise_one + exception + when Constraint_Error => + Handled := Handled + 1; -- # reraise_one_ce_handler + raise; -- # reraise_one_ce_handler + when Program_Error => + Handled := Handled + 1; -- # reraise_one_pe_handler + raise; -- # reraise_one_pe_handler + when User_Error => + Handled := Handled + 1; -- # reraise_one_ue_handler + raise; -- # reraise_one_ue_handler + end; + + procedure Do_Reraise_Other (Rk : Raise_Kind) is + begin + Do_Raise (Rk); -- # call_reraise_other + exception + when others => + Handled := Handled + 1; -- # reraise_other_handler + raise; -- # reraise_other_handler + end; + + procedure Dispatch (Rk : Raise_Kind; Rm : Raise_Mode) is + begin + X := X + 1; -- # pre + case Rm is -- # pre + when Straight => + Do_Raise (Rk); -- # call_straight + when Reraise_Other => + Do_Reraise_Other (Rk); -- # call_reraise_other + when Reraise_One => + Do_Reraise_One (Rk); -- # call_reraise_one + when None => + null; -- # rm_none + end case; + X := X + 1; -- # post + end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.ads new file mode 100644 index 000000000..d69e36da0 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/doraise.ads @@ -0,0 +1,25 @@ +package Doraise is + + User_Error : exception; + + -- How a raise is to be propagated. If not None, this can be + -- either directly (Straight) or via an intermediate handler that + -- will re-raise (Reraise_One/Other). For Reraise_One, there is + -- a specific handler for each exception id (CE, PE, User). For + -- Reraise_Other, this would be a "when others": + + type Raise_Mode is + (Straight, Reraise_One, Reraise_Other, None); + + -- The kind of raise operation a testcase can request: + + type Raise_Kind is + (Implicit_CE, -- implicit Constraint_Error out of a range check + Explicit_PE, -- explicit raise Constraint_Error stmt + Explicit_UE, -- explicit raise User_Error stmt + From_RTS, -- a Constraint_Error out of a 'Valid call + None); -- a sensible choice to go with Raise_Mode None + + procedure Dispatch (Rk : Raise_Kind; Rm : Raise_Mode); + +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_r1.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_r1.adb new file mode 100644 index 000000000..51bb7b631 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_r1.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_ICE_R1 is +begin + Ctxt.Run (Rk => Implicit_CE, Rm => Reraise_One); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l+ ## 0 +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l+ ## 0 +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l+ ## 0 +-- /xpe-eval/ l- ## s- +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l+ ## 0 +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_ro.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_ro.adb new file mode 100644 index 000000000..7a452a6b8 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_ro.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_ICE_RO is +begin + Ctxt.Run (Rk => Implicit_CE, Rm => Reraise_Other); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l+ ## 0 +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l+ ## 0 +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l+ ## 0 +-- /xpe-eval/ l- ## s- +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_other_handler/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_st.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_st.adb new file mode 100644 index 000000000..69b54979b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_ice_st.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_ICE_ST is +begin + Ctxt.Run (Rk => Implicit_CE, Rm => Straight); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l+ ## 0 +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l+ ## 0 +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l+ ## 0 +-- /xpe-eval/ l- ## s- +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_noraise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_noraise.adb new file mode 100644 index 000000000..51d9e6964 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_noraise.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_Noraise is +begin + Ctxt.Run (Rk => None, Rm => None); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l+ ## 0 +-- /ce_handler/ l- ## s- +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l- ## s- +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l- ## s- +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l- ## s- +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l+ ## 0 +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_r1.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_r1.adb new file mode 100644 index 000000000..1e220918a --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_r1.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_RTS_R1 is +begin + Ctxt.Run (Rk => From_RTS, Rm => Reraise_One); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l+ ## 0 +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l+ ## 0 +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l+ ## 0 +-- /xue-raise/ l- ## s- +-- /rts-eval/ l+ ## 0 +-- /rts-raise/ l+ ## 0 + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l+ ## 0 +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_ro.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_ro.adb new file mode 100644 index 000000000..21ebd6c61 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_ro.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_RTS_RO is +begin + Ctxt.Run (Rk => From_RTS, Rm => Reraise_Other); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l+ ## 0 +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l+ ## 0 +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l+ ## 0 +-- /xue-raise/ l- ## s- +-- /rts-eval/ l+ ## 0 +-- /rts-raise/ l+ ## 0 + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_st.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_st.adb new file mode 100644 index 000000000..94c900543 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_rts_st.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_RTS_ST is +begin + Ctxt.Run (Rk => From_RTS, Rm => Straight); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l+ ## 0 +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l+ ## 0 +-- /pe_handler/ l- ## s- +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l+ ## 0 +-- /xue-raise/ l- ## s- +-- /rts-eval/ l+ ## 0 +-- /rts-raise/ l+ ## 0 + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_r1.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_r1.adb new file mode 100644 index 000000000..586512ad7 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_r1.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_XPE_R1 is +begin + Ctxt.Run (Rk => Explicit_PE, Rm => Reraise_One); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l+ ## 0 +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l- ## s- +-- /pe_handler/ l+ ## 0 +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l+ ## 0 +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l+ ## 0 +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_ro.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_ro.adb new file mode 100644 index 000000000..afc7ca339 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_ro.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_XPE_RO is +begin + Ctxt.Run (Rk => Explicit_PE, Rm => Reraise_Other); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l+ ## 0 +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l- ## s- +-- /pe_handler/ l+ ## 0 +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l+ ## 0 +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_st.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_st.adb new file mode 100644 index 000000000..5d8b78340 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xpe_st.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_XPE_ST is +begin + Ctxt.Run (Rk => Explicit_PE, Rm => Straight); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l+ ## 0 +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l- ## s- +-- /pe_handler/ l+ ## 0 +-- /ue_handler/ l- ## s- +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l+ ## 0 +-- /xue-eval/ l- ## s- +-- /xue-raise/ l- ## s- +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_r1.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_r1.adb new file mode 100644 index 000000000..39bba1acf --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_r1.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_XUE_R1 is +begin + Ctxt.Run (Rk => Explicit_UE, Rm => Reraise_One); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l+ ## 0 +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l- ## s- +-- /pe_handler/ l- ## s- +-- /ue_handler/ l+ ## 0 +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l+ ## 0 +-- /xue-raise/ l+ ## 0 +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l+ ## 0 +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_ro.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_ro.adb new file mode 100644 index 000000000..f0313acfe --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_ro.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_XUE_RO is +begin + Ctxt.Run (Rk => Explicit_UE, Rm => Reraise_Other); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l- ## s- +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l+ ## 0 +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l- ## s- +-- /pe_handler/ l- ## s- +-- /ue_handler/ l+ ## 0 +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l+ ## 0 +-- /xue-raise/ l+ ## 0 +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_st.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_st.adb new file mode 100644 index 000000000..7eec534b7 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/test_ctxt_xue_st.adb @@ -0,0 +1,40 @@ +with Ctxt, Doraise, Support; use Ctxt, Doraise, Support; + +procedure Test_Ctxt_XUE_ST is +begin + Ctxt.Run (Rk => Explicit_UE, Rm => Straight); +end; + +--# ctxt.adb doraise.adb + +-- common to both sources + +-- /run/ l+ ## 0 +-- /call_straight/ l+ ## 0 +-- /call_reraise_one/ l- ## s- +-- /call_reraise_other/ l- ## s- +-- /pre/ l+ ## 0 +-- /post/ l- ## s- +-- /ce_handler/ l- ## s- +-- /pe_handler/ l- ## s- +-- /ue_handler/ l+ ## 0 +-- /other/ l- ## s- + +-- specific to doraise.adb + +-- /do_raise-pre/ l+ ## 0 +-- /do_raise-post/ l- ## s- +-- /ice-eval/ l+ ## 0 +-- /ice-raise/ l- ## s- +-- /xpe-eval/ l+ ## 0 +-- /xpe-raise/ l- ## s- +-- /xue-eval/ l+ ## 0 +-- /xue-raise/ l+ ## 0 +-- /rts-eval/ l- ## s- +-- /rts-raise/ l- ## s- + +-- /rm_none/ l- ## s- +-- /reraise_one_ue_handler/ l- ## s- +-- /reraise_one_ce_handler/ l- ## s- +-- /reraise_one_pe_handler/ l- ## s- +-- /reraise_other_handler/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/tc_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/tc_set.rst index b7647625a..7de51433f 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/tc_set.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/tc_set.rst @@ -1,9 +1,6 @@ Check SC with exceptions propagating across subprograms ======================================================= -Verify the correctness of assessments in the current restricted -perimeter set by our parent requirement. - .. qmlink:: TCIndexImporter * diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst index 63f4a13f4..7ef5a4968 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst @@ -56,17 +56,34 @@ flow transfer, involving: Rules #1, 2 and 5 are checked by variations in most testcases and verified more specifically by the *Raise* testcase, dedicated to this purpose. -Rule #4 is verified by the dedicated *CutEvals* set of testcases. - Rule #3 is verified by the *Within* family of testcases, which exercise conditional constructs within exception handlers in a variety of contexts where such handlers may appear. +Rule #4 is verified by the dedicated *CutEvals* set of testcases. + When conditional guards are involved, the coverage outcome is always checked at least for situations where a guard is tested True only and False only. Very often, testcases also verify the outcome when a guard is tested both True and False or not at all. +For exceptions that propagate across subprograms, we first verify all +the requirement rules in a single *Basics* testcase, then check more +elaborate situations with a family of tests involving: + +* Various exception kinds (implicit standard exception raised from a + language check, explicit raise of standard or user defined exception, + raise from a Ada runtime facility); + +* That propagate either directly or via an intermediate handler and + a "raise;" statement propagating the original exception further, from + either a specific handler for the particular exception or from a + "when others" handler; + +* That are eventually either unhandled or handled in a variety of contexts, + for example within a library level subprogram or within a handler for + another exception occurrence. + .. qmlink:: TCIndexImporter Propagation From c4d6e3bbb7687f07457758bb5b49ff468fd9920f Mon Sep 17 00:00:00 2001 From: Fedor Rybin Date: Sun, 2 Apr 2023 22:32:27 +0300 Subject: [PATCH 0236/1483] Fix documentation for stub exclusion in gnattest Clarify that index of per-unti stub exclsion is the name of the file containing said unit's specification. Issue: eng/ide/libadalang-tools#42 --- doc/gnattest/gnattest_part.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/gnattest/gnattest_part.rst b/doc/gnattest/gnattest_part.rst index 22a1056d3..0e96b8992 100644 --- a/doc/gnattest/gnattest_part.rst +++ b/doc/gnattest/gnattest_part.rst @@ -307,9 +307,9 @@ Switches for ``gnattest`` in framework generation mode corresponding spec files, one per line. -:switch:`--exclude-from-stubbing:{unit}={filename}` +:switch:`--exclude-from-stubbing:{spec}={filename}` Same as above, but corresponding units will not be stubbed only when testing - specified ``unit``. + unit whose specification is declared in specified ``spec`` file. .. index:: --validate-type-extensions (gnattest) @@ -460,10 +460,10 @@ package ``Gnattest``. Here is the list of attributes: is used to specify the file with list of units whose bodies should not be stubbed, otherwise specified by ``--exclude-from-stubbing=filename``. -* ``Stub_Exclusion_List ("unit")`` +* ``Stub_Exclusion_List ("spec")`` is used to specify the file with list of units whose bodies should not - be stubbed when testing "unit", otherwise specified by - ``--exclude-from-stubbing:unit=filename``. + be stubbed when testing "spec", otherwise specified by + ``--exclude-from-stubbing:spec=filename``. Each of those attributes can be overridden from the command line if needed. Other ``gnattest`` switches can also be passed via the project From 0e9dd27e18cc9615ceb12dcf3654283d31102dbc Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 31 Mar 2023 13:58:17 +0000 Subject: [PATCH 0237/1483] .gitlab-ci.yml: add proper support for edge branches When testing the "edge" branch or a merge request that targets the "edge" branch, the CI should use the "edge" branch of the gnatcoverage-extra repository and build/test gnatcov in edge mode. --- .gitlab-ci.yml | 54 +++++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6f635beda..528a7536c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,6 +18,19 @@ variables: # CI_FRAGMENTS_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/it/$CI_FRAGMENTS GNATCOVERAGE_EXTRA_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/cov/gnatcoverage-extra +.edge_vars: &edge_vars + - | + if [ $CI_MERGE_REQUEST_TARGET_BRANCH_NAME = edge ] + then + EDGE_QUALIFIER="-Qedge" + EDGE_REPO_SUFFIX="-edge" + EDGE_BUILD_SPACE_SUFFIX="_edge" + else + EDGE_QUALIFIER="" + EDGE_REPO_SUFFIX="" + EDGE_BUILD_SPACE_SUFFIX="" + fi + stages: - build - test @@ -31,17 +44,18 @@ build: script: - . ~/.aws_container_credentials - export PATH=/it/e3/bin:$PATH + - *edge_vars # Setup the repository - cd /it/wave - - anod vcs --add-repo gnatcoverage $CI_PROJECT_DIR + - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR # Build using anod - - anod build --minimal gnatcov + - anod build --minimal gnatcov $EDGE_QUALIFIER # Create the package - tar czf $PACKAGE_ABSOLUTE_NAME -C / - it/wave/x86_64-linux/gnatcov-build/install/ + it/wave/x86_64-linux/gnatcov-build$EDGE_BUILD_SPACE_SUFFIX/install/ - cd $CI_PROJECT_DIR - ls -l $PACKAGE_BASE_NAME @@ -59,17 +73,19 @@ build_community: script: - . ~/.aws_container_credentials - export PATH=/it/e3/bin:$PATH + - *edge_vars # Setup the repository - cd /it/wave - - anod vcs --add-repo gnatcoverage $CI_PROJECT_DIR + - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR # Build using anod - - anod build --minimal gnatcov --qualifier=no-c + - anod build --minimal gnatcov -Qno-c $EDGE_QUALIFIER .common_test_bits: &retrieve_gnatcoverage_extras_and_setup_anod_repo - . ~/.aws_container_credentials - export PATH=/it/e3/bin:$PATH + - *edge_vars # Unpack the artifact then delete it - tar zxf $PACKAGE_ABSOLUTE_NAME -C / @@ -77,23 +93,30 @@ build_community: # Get the gnatcoverage-extra repository. If we're testing a 'sync/' branch, # expect the same for that repo. + - cd /tmp - EXTRA_BRANCH=master - if [[ $CI_COMMIT_BRANCH =~ ^sync/ ]]; then EXTRA_BRANCH=$CI_COMMIT_BRANCH; elif [[ $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ ^sync/ ]]; then EXTRA_BRANCH=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME; + elif [ $CI_COMMIT_BRANCH = edge ] || [ $CI_MERGE_REQUEST_TARGET_BRANCH_NAME = edge ]; then + EXTRA_BRANCH=edge; fi - git clone $GNATCOVERAGE_EXTRA_GIT -b $EXTRA_BRANCH # Setup the anod sandbox repositories - cd /it/wave - - anod vcs --add-repo gnatcoverage $CI_PROJECT_DIR - - anod vcs --add-repo gnatcoverage-extra /tmp/gnatcoverage-extra + - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR + - anod vcs --add-repo gnatcoverage-extra$EDGE_REPO_SUFFIX /tmp/gnatcoverage-extra - # Setup fingerprints so anod doesn't do unnecessary rebuilds + # Setup fingerprints so anod doesn't do unnecessary rebuilds and does not + # try to download gnatcov/edge: we have rebuilt it so we do not need to + # download the nightly one, which may not even exist (case of an edge build + # failure that was fixed on that day). - mkdir -p fingerprints - - touch fingerprints/x86_64-linux.gnatcov-build.install.json.assume-unchanged + - touch fingerprints/x86_64-linux.gnatcov-build$EDGE_BUILD_SPACE_SUFFIX.install.json.assume-unchanged + - touch fingerprints/x86_64-linux.gnatcov-build$EDGE_BUILD_SPACE_SUFFIX.download_bin.json.assume-unchanged .common_artifacts_bits: &artifacts artifacts: @@ -112,12 +135,12 @@ test_bin_traces: - *retrieve_gnatcoverage_extras_and_setup_anod_repo # Test using anod - - anod test gnatcov --target=leon3-elf --qualifier="RTS=embedded-leon3,-O0" + - anod test gnatcov --target=leon3-elf -QRTS=embedded-leon3,-O0 $EDGE_QUALIFIER - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name bin-traces - leon3-elf-linux64/gnatcov-O0-embedded-leon3-test/results/new/ + leon3-elf-linux64/gnatcov-O0-embedded-leon3$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ <<: *artifacts @@ -131,12 +154,12 @@ test_src_traces: - *retrieve_gnatcoverage_extras_and_setup_anod_repo # Test using anod - - anod test gnatcov --qualifier=src-traces + - anod test gnatcov -Qsrc-traces $EDGE_QUALIFIER - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name src-traces - x86_64-linux/gnatcov-src-traces-test/results/new/ + x86_64-linux/gnatcov-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ <<: *artifacts @@ -150,12 +173,11 @@ test_spark: - *retrieve_gnatcoverage_extras_and_setup_anod_repo # Test using anod - - anod test gnatcov --qualifier=spark-tests,src-traces + - anod test gnatcov -Qspark-tests,src-traces $EDGE_QUALIFIER - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name spark - x86_64-linux/gnatcov-spark-tests-src-traces-test/results/new/ + x86_64-linux/gnatcov-spark-tests-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ <<: *artifacts - From 4a55264b1864b719805f5dcd5954aa75a5d4fe99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 30 Mar 2023 13:48:57 +0200 Subject: [PATCH 0238/1483] Add a new language version for Ada 2022 The default language for gnatcov will still be Ada 2012 as support for Ada 2022 is still incomplete and in beta. --- tools/gnatcov/command_line.ads | 6 +++--- tools/gnatcov/gnatcov_bits_specific.adb | 2 ++ tools/gnatcov/instrument.ads | 2 +- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 1ae276a49..40a7d135b 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -775,13 +775,13 @@ package Command_Line is Opt_Ada => Create (Long_Name => "--ada", - Pattern => "83|95|05|12|1983|1995|2005|2012", + Pattern => "83|95|05|12|22|1983|1995|2005|2012|2022", Help => "Select a target language version for source" & " instrumentation. This restricts the set of" & " language constructs that can be introduced in " & " instrumented sources. Emit a warning when such a" - & " construct is needed. Use the latest language" - & " version by default.", + & " construct is needed. Use Ada 2012 by default as" + & " Ada 2022 support is in beta phase.", Commands => (Cmd_Instrument => True, others => False), At_Most_Once => False, Internal => False), diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 458fd4714..f03c15d0c 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1295,6 +1295,8 @@ begin Language_Version := Ada_2005; elsif V in "12" | "2012" then Language_Version := Ada_2012; + elsif V in "22" | "2022" then + Language_Version := Ada_2022; else Fatal_Error ("Bad Ada language version: " & V); end if; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 446af1d14..f09e0e692 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -81,7 +81,7 @@ package Instrument is -- Bundle for all configuration related to automatic dump of coverage -- buffers. - type Any_Language_Version is (Ada_83, Ada_95, Ada_2005, Ada_2012); + type Any_Language_Version is (Ada_83, Ada_95, Ada_2005, Ada_2012, Ada_2022); procedure Instrument_Units_Of_Interest (Dump_Config : Any_Dump_Config; From 5c4b411678703d9d7a2234ea4d5edd73c881faf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 30 Mar 2023 13:50:28 +0200 Subject: [PATCH 0239/1483] Add support for subtype indications in generalized loops iterations This isn't really usefull per say, as according to RM 5.5.2 5/5, the subtype indication in the loop must *statically* match the one of the cursor, thus rendering any decisions in the subtype static. --- testsuite/tests/Ada2022/extra.opt | 1 + .../Ada2022/subtype_ind_in_iter/src/pkg.adb | 34 +++++++++++++++++++ .../Ada2022/subtype_ind_in_iter/src/pkg.ads | 11 ++++++ .../subtype_ind_in_iter/src/test_pkg.adb | 14 ++++++++ .../tests/Ada2022/subtype_ind_in_iter/test.py | 15 ++++++++ tools/gnatcov/instrument-ada_unit.adb | 15 +++++--- 6 files changed, 86 insertions(+), 4 deletions(-) create mode 100644 testsuite/tests/Ada2022/extra.opt create mode 100644 testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.ads create mode 100644 testsuite/tests/Ada2022/subtype_ind_in_iter/src/test_pkg.adb create mode 100644 testsuite/tests/Ada2022/subtype_ind_in_iter/test.py diff --git a/testsuite/tests/Ada2022/extra.opt b/testsuite/tests/Ada2022/extra.opt new file mode 100644 index 000000000..ce977819b --- /dev/null +++ b/testsuite/tests/Ada2022/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD Ada 2022 not supported on bin traces diff --git a/testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.adb b/testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.adb new file mode 100644 index 000000000..a07193e09 --- /dev/null +++ b/testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.adb @@ -0,0 +1,34 @@ +pragma Ada_2022; + +package body Pkg is + + ------------ + -- Do_Sum -- + ------------ + + function Do_Sum (N_Values : Positive) return Natural + is + Arr : array (1 .. N_Values) of Positive range 1 .. Positive' + (If Constrained and then Really_Constrained -- # Constrained + then 10 + else Positive'Last) := + [for I in 1 .. N_Values => I]; + Acc : Natural := 0; + begin + -- According to RM 5.5.2 5/5, the subtype indication in the generalized + -- loop iteration must *statically* match the one of the component of + -- the iterated value. We thus can't produce any non-static decisions + -- in the subtype indication. + + for Val : Positive range 1 .. Positive' + (If Constrained and then Really_Constrained -- # Constrained + then 10 + else Positive'Last) + of Arr + loop + Acc := Acc + Val; + end loop; + return Acc; + end Do_Sum; + +end Pkg; diff --git a/testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.ads b/testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.ads new file mode 100644 index 000000000..922fbef6b --- /dev/null +++ b/testsuite/tests/Ada2022/subtype_ind_in_iter/src/pkg.ads @@ -0,0 +1,11 @@ +pragma Ada_2022; + +package Pkg is + + Constrained : constant Boolean := True; + Really_Constrained : constant Boolean := False; + + function Do_Sum (N_Values : Positive) return Natural; + -- Return the sum of the values from 1 to N_Values + +end Pkg; diff --git a/testsuite/tests/Ada2022/subtype_ind_in_iter/src/test_pkg.adb b/testsuite/tests/Ada2022/subtype_ind_in_iter/src/test_pkg.adb new file mode 100644 index 000000000..945008f94 --- /dev/null +++ b/testsuite/tests/Ada2022/subtype_ind_in_iter/src/test_pkg.adb @@ -0,0 +1,14 @@ +with Pkg; + +procedure Test_Pkg is + Res : Positive; + pragma Volatile (Res); +begin + Res := Pkg.Do_Sum (10); + if Res /= 55 then + raise Program_Error; + end if; +end Test_Pkg; + +--# pkg.adb +-- /Constrained/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/subtype_ind_in_iter/test.py b/testsuite/tests/Ada2022/subtype_ind_in_iter/test.py new file mode 100644 index 000000000..533e9342b --- /dev/null +++ b/testsuite/tests/Ada2022/subtype_ind_in_iter/test.py @@ -0,0 +1,15 @@ +""" +Test the correct handling of subtype indications in generalized loop +iterations. As the subtype indication in the loop must statically match the +type of the iterated cursor type, we can only create static decisions that are +not currently instrumented by gnatcov. This test thus only really checks that +there is no crash in the presence of this construct. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 5d711c802..a5bc9aab1 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -4600,13 +4600,20 @@ package body Instrument.Ada_Unit is -- In Libadalang, there is only one kind of FOR loop: -- both the RM's loop_parameter_specification and -- iterator_specification are materialized with - -- For_Loop_Spec nodes. In each case, decisions can - -- only appear in the "iteration expression", i.e. the - -- expression that comes before the LOOP keyword. + -- For_Loop_Spec nodes. + -- + -- Ada 2022 allows for a subtype indication to be + -- present in the loop specification, but it must + -- statically match the cursor type (RM 5.5.2 5/5). + -- This means that only static decisions could be + -- present in there, which will not be instrumented. + -- + -- Still go through them to generate SCOs, for the + -- sake of completeness. Extend_Statement_Sequence (UIC, N, 'F'); Process_Decisions_Defer - (ISC.As_For_Loop_Spec.F_Iter_Expr, 'X'); + (ISC.As_For_Loop_Spec, 'X'); end if; end if; From 802ccb20386570e347431d1830d01b0f23528480 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 4 Apr 2023 10:20:20 +0200 Subject: [PATCH 0240/1483] Kill Ada 2022 tests for old toolchains --- testsuite/tests/Ada2022/extra.opt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/tests/Ada2022/extra.opt b/testsuite/tests/Ada2022/extra.opt index ce977819b..087421040 100644 --- a/testsuite/tests/Ada2022/extra.opt +++ b/testsuite/tests/Ada2022/extra.opt @@ -1 +1,3 @@ +7.1.2 DEAD Ada 2022 not supported on old toolchains +5.04a1 DEAD Ada 2022 not supported on old toolchains bin-traces DEAD Ada 2022 not supported on bin traces From 9752b77a3de110b070157fde5b051b393609e89a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 6 Apr 2023 12:14:49 +0200 Subject: [PATCH 0241/1483] Remove duplicated source command This is already done in the (inherited) sandbox Docker image. --- .gitlab-ci.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 528a7536c..ced9d86da 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,7 +42,6 @@ build: - mem:16 stage: build script: - - . ~/.aws_container_credentials - export PATH=/it/e3/bin:$PATH - *edge_vars @@ -71,7 +70,6 @@ build_community: - mem:16 stage: test script: - - . ~/.aws_container_credentials - export PATH=/it/e3/bin:$PATH - *edge_vars @@ -83,7 +81,6 @@ build_community: - anod build --minimal gnatcov -Qno-c $EDGE_QUALIFIER .common_test_bits: &retrieve_gnatcoverage_extras_and_setup_anod_repo - - . ~/.aws_container_credentials - export PATH=/it/e3/bin:$PATH - *edge_vars From c637912f215a07e790ef5a1b31146f0cece2b2a2 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 5 Apr 2023 18:08:53 +0200 Subject: [PATCH 0242/1483] Exclude the gnatcov_rts_c-os_interface.[ch] file from the embedded build These files are not used in the embedded build configuration, so we can safely exclude them from it. --- tools/gnatcov/rts/gnatcov_rts.gpr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/rts/gnatcov_rts.gpr b/tools/gnatcov/rts/gnatcov_rts.gpr index ccceb5f05..034a88f05 100644 --- a/tools/gnatcov/rts/gnatcov_rts.gpr +++ b/tools/gnatcov/rts/gnatcov_rts.gpr @@ -65,6 +65,8 @@ library project GNATcov_RTS is Excluded_Source_Files & ("gnatcov_rts-traces-output-files.adb", "gnatcov_rts-traces-output-files.ads", + "gnatcov_rts_c-os_interface.c", + "gnatcov_rts_c-os_interface.h", "gnatcov_rts_c-traces-output-files.c", "gnatcov_rts_c-traces-output-files.h"); when "full" => null; From 82feaf969338e2d53c97b28d55952bc258f1ab34 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 5 Apr 2023 18:10:03 +0200 Subject: [PATCH 0243/1483] Add the freestanding switch to the embedded build The embedded build must have the minimal amount of dependency to system headers, and may not even be executed in a context where a libc is available. In this case, if the freestanding switch is specified, the compiler will use its own implementation of stdint.h and will not assume that one is provided by the system. --- tools/gnatcov/rts/gnatcov_rts.gpr | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/rts/gnatcov_rts.gpr b/tools/gnatcov/rts/gnatcov_rts.gpr index 034a88f05..b21b1f023 100644 --- a/tools/gnatcov/rts/gnatcov_rts.gpr +++ b/tools/gnatcov/rts/gnatcov_rts.gpr @@ -92,7 +92,21 @@ library project GNATcov_RTS is for Excluded_Source_Files use Excluded_Source_Files; package Compiler is - for Default_Switches ("C") use ("-O2", "-g", "-Wall", "-Wextra"); + C_Extra_Switches := (); + case RTS_Profile is + when "embedded" => + + -- The rts for the embedded profile needs to remain compilable + -- in "freestanding" environments, where we might not have a libc + -- at hand. + + C_Extra_Switches := ("-ffreestanding"); + when "full" => + null; + end case; + + for Default_Switches ("C") use + ("-O2", "-g", "-Wall", "-Wextra") & C_Extra_Switches; for Default_Switches ("Ada") use ("-O2", "-g", "-gnatwa"); end Compiler; From 06b4ad947abb603e790bb547a02410b0379e8219 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 5 Apr 2023 18:32:08 +0200 Subject: [PATCH 0244/1483] Rename gnatcov_rts_c_strings.h to gnatcov_rts_c-strings.h For consistency sake. --- tools/gnatcov/instrument-c.adb | 2 +- tools/gnatcov/rts/gnatcov_rts-strings.ads | 2 +- tools/gnatcov/rts/gnatcov_rts_c-base_io.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-base_io.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 2 +- .../rts/{gnatcov_rts_c_strings.h => gnatcov_rts_c-strings.h} | 0 tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output.h | 2 +- 9 files changed, 8 insertions(+), 8 deletions(-) rename tools/gnatcov/rts/{gnatcov_rts_c_strings.h => gnatcov_rts_c-strings.h} (100%) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 81015950a..544f9004e 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3786,7 +3786,7 @@ package body Instrument.C is Create_File (Info, File, Filename); - File.Put_Line ("#include ""gnatcov_rts_c_strings.h"""); + File.Put_Line ("#include ""gnatcov_rts_c-strings.h"""); case Dump_Config.Channel is when Binary_File => diff --git a/tools/gnatcov/rts/gnatcov_rts-strings.ads b/tools/gnatcov/rts/gnatcov_rts-strings.ads index 033ef2651..f8b509974 100644 --- a/tools/gnatcov/rts/gnatcov_rts-strings.ads +++ b/tools/gnatcov/rts/gnatcov_rts-strings.ads @@ -22,7 +22,7 @@ -- -- ------------------------------------------------------------------------------ --- Ada bindings for gnatcov_rts_c_strings.h +-- Ada bindings for gnatcov_rts_c-strings.h with Interfaces.C; use Interfaces.C; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-base_io.c b/tools/gnatcov/rts/gnatcov_rts_c-base_io.c index 2f922c7cf..d944db84d 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-base_io.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-base_io.c @@ -19,7 +19,7 @@ #include -#include "gnatcov_rts_c_strings.h" +#include "gnatcov_rts_c-strings.h" /* The libc implementation always provides fwrite. Use this function to print to the standard output. */ diff --git a/tools/gnatcov/rts/gnatcov_rts_c-base_io.h b/tools/gnatcov/rts/gnatcov_rts_c-base_io.h index cbaf84889..769403b74 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-base_io.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-base_io.h @@ -28,7 +28,7 @@ implements them (these two units conflict with each other, so we include only one of them at link time). */ -#include "gnatcov_rts_c_strings.h" +#include "gnatcov_rts_c-strings.h" #ifdef __cplusplus extern "C" diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index ad584520f..1402d60a4 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -22,7 +22,7 @@ #include -#include "gnatcov_rts_c_strings.h" +#include "gnatcov_rts_c-strings.h" #ifdef __cplusplus extern "C" diff --git a/tools/gnatcov/rts/gnatcov_rts_c_strings.h b/tools/gnatcov/rts/gnatcov_rts_c-strings.h similarity index 100% rename from tools/gnatcov/rts/gnatcov_rts_c_strings.h rename to tools/gnatcov/rts/gnatcov_rts_c-strings.h diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h index 59792be54..6f363e21e 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h @@ -18,7 +18,7 @@ ****************************************************************************/ #include "gnatcov_rts_c-buffers.h" -#include "gnatcov_rts_c_strings.h" +#include "gnatcov_rts_c-strings.h" #include #ifdef __cplusplus diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h index 16efcc789..e5c40b3f3 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h @@ -18,7 +18,7 @@ ****************************************************************************/ #include "gnatcov_rts_c-buffers.h" -#include "gnatcov_rts_c_strings.h" +#include "gnatcov_rts_c-strings.h" #include #ifdef __cplusplus diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h index 939ec31c8..063e172cf 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h @@ -18,7 +18,7 @@ ****************************************************************************/ #include "gnatcov_rts_c-buffers.h" -#include "gnatcov_rts_c_strings.h" +#include "gnatcov_rts_c-strings.h" #ifdef __cplusplus extern "C" From 88f6c95013bef53b7fd2789ec62b9011061e9e93 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 5 Apr 2023 18:38:07 +0200 Subject: [PATCH 0245/1483] Remove the dependency to string.h in the core runtime Bareboard runtimes may not provide the string.h header, but we can reasonably assume that they will provide a definition for memcpy and memset. Instead of relying on the string.h header, import their definition manually. Do that in all of the files that belong to the embedded configuration of the instrumentation runtime (what we call the core). The full configuration comes with less build constraints, so no need to do that there. If these functions are not provided by the runtime, the user will have to provide them: this is a pre-requisite of the instrumentation runtime. --- .../gnatcov/rts/gnatcov_rts_c-traces-output-base64.c | 1 - tools/gnatcov/rts/gnatcov_rts_c-traces-output.c | 1 - tools/gnatcov/rts/gnatcov_rts_c-traces-output.h | 11 +++++++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c index 873553b61..dad235af0 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c @@ -21,7 +21,6 @@ #include "gnatcov_rts_c-base_io.h" #include "gnatcov_rts_c-traces-output.h" #include -#include static const char *base64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index 7d7b322ba..7522b4328 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -20,7 +20,6 @@ #include "gnatcov_rts_c-traces-output.h" #include "gnatcov_rts_c-traces.h" #include -#include const unsigned alignment = sizeof (void *); diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h index 063e172cf..d6b4bb04b 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h @@ -25,6 +25,17 @@ extern "C" { #endif + /* Smallest subset of functions needed for memory manipulations (memcpy and + memset). These functions must either be defined by the runtime (even if it + is in a bareboard environment), or provided by the user. + + Note that we declare them ourselves, as the runtime may not provide the + string.h header: older versions of light runtimes did not package newlib, + and thus did not provide the string.h portable header. Though the memcpy + and memset functions are provided by the light runtime in this case. */ + extern void *memcpy (void *__dest, const void *__src, size_t __n); + extern void *memset (void *__s, int __c, size_t __n); + /* Callback for trace writing routines. Write the N bytes starting at SOURCE to the OUTPUT stream (OUTPUT is just forwarded from gnatcov_rts_generic_write_trace_file). Return 0 if the write was From d6afd3cd536609c5f106d8e7ab06fc1f9f3d267b Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 5 Apr 2023 18:40:29 +0200 Subject: [PATCH 0246/1483] Remove useless inclusion directive --- tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c index dad235af0..35e43823b 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c @@ -20,7 +20,6 @@ #include "gnatcov_rts_c-traces-output-base64.h" #include "gnatcov_rts_c-base_io.h" #include "gnatcov_rts_c-traces-output.h" -#include static const char *base64_alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; From b2701f073b406fbca61bdf5ff9dd6fb9ed21bd5f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 5 Apr 2023 18:41:06 +0200 Subject: [PATCH 0247/1483] update copyright headers for the runtime sources --- tools/gnatcov/rts/gnatcov_rts-base_io.adb | 2 +- tools/gnatcov/rts/gnatcov_rts-base_io.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-buffers.adb | 2 +- tools/gnatcov/rts/gnatcov_rts-buffers.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-strings.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb | 2 +- tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb | 2 +- tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-traces-output.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-traces.ads | 2 +- tools/gnatcov/rts/gnatcov_rts.ads | 2 +- tools/gnatcov/rts/gnatcov_rts_c-base_io.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-base_io.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-buffers.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-os_interface.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-os_interface.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-strings.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces.h | 2 +- 28 files changed, 28 insertions(+), 28 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts-base_io.adb b/tools/gnatcov/rts/gnatcov_rts-base_io.adb index d955bb67f..346cbfdae 100644 --- a/tools/gnatcov/rts/gnatcov_rts-base_io.adb +++ b/tools/gnatcov/rts/gnatcov_rts-base_io.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-2023, 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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-base_io.ads b/tools/gnatcov/rts/gnatcov_rts-base_io.ads index d21ed97c5..8032e1462 100644 --- a/tools/gnatcov/rts/gnatcov_rts-base_io.ads +++ b/tools/gnatcov/rts/gnatcov_rts-base_io.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-2023, 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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads index 7fc1a14d8..b2260e37d 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-2023, 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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.adb b/tools/gnatcov/rts/gnatcov_rts-buffers.adb index 745bf41d6..35356eab8 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.adb +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-2023, 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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index a1fda80fb..64e929593 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-2023, 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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-strings.ads b/tools/gnatcov/rts/gnatcov_rts-strings.ads index f8b509974..15720bddb 100644 --- a/tools/gnatcov/rts/gnatcov_rts-strings.ads +++ b/tools/gnatcov/rts/gnatcov_rts-strings.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2021-2022, AdaCore -- +-- Copyright (C) 2021-2023, 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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb index 9a52382c4..9dfc22f1c 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-2023, 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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads index 7efb3c7a5..39690b204 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-2023, 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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb index cedbc2d03..2521059bb 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-2023, 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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads index 1b272a8f0..0c3bbaf19 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-2023, 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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output.ads index e20301a40..379457bf2 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-2023, 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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces.ads b/tools/gnatcov/rts/gnatcov_rts-traces.ads index 1e0f6992a..94c2b3a0e 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2022, AdaCore -- +-- Copyright (C) 2022-2023, 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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts.ads b/tools/gnatcov/rts/gnatcov_rts.ads index 0c79490a4..2a29747cb 100644 --- a/tools/gnatcov/rts/gnatcov_rts.ads +++ b/tools/gnatcov/rts/gnatcov_rts.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-2023, 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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts_c-base_io.c b/tools/gnatcov/rts/gnatcov_rts_c-base_io.c index d944db84d..3e68f1026 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-base_io.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-base_io.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2022, AdaCore * + * Copyright (C) 2021-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-base_io.h b/tools/gnatcov/rts/gnatcov_rts_c-base_io.h index 769403b74..0716ef20b 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-base_io.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-base_io.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2022, AdaCore * + * Copyright (C) 2021-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c index 7a78eb5c1..48d60797a 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2022, AdaCore * + * Copyright (C) 2021-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index 1402d60a4..21cd45eac 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2022, AdaCore * + * Copyright (C) 2021-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.c b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.c index 912e1c913..db46c24c2 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2020-2022, AdaCore * + * Copyright (C) 2020-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h index 4a9ab24d5..8e9e7a057 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2020-2022, AdaCore * + * Copyright (C) 2020-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-strings.h b/tools/gnatcov/rts/gnatcov_rts_c-strings.h index 0e9d6b8cc..30ff71bef 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-strings.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-strings.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2022, AdaCore * + * Copyright (C) 2021-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c index 35e43823b..10aeb371c 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2022, AdaCore * + * Copyright (C) 2021-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h index 6f363e21e..3dc13f2b4 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2022, AdaCore * + * Copyright (C) 2021-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c index 840183079..eae8a38bf 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2022, AdaCore * + * Copyright (C) 2021-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h index e5c40b3f3..ae0543148 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2022, AdaCore * + * Copyright (C) 2021-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index 7522b4328..b2a96c101 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2022, AdaCore * + * Copyright (C) 2021-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h index d6b4bb04b..3cc71dd81 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2022, AdaCore * + * Copyright (C) 2021-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces.c b/tools/gnatcov/rts/gnatcov_rts_c-traces.c index bdfd0537b..16b1f5950 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2022, AdaCore * + * Copyright (C) 2021-2023, 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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces.h b/tools/gnatcov/rts/gnatcov_rts_c-traces.h index 386066ab1..6e3288395 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2022, AdaCore * + * Copyright (C) 2021-2023, 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 * From 293c4d0dca6f0ee9bab7d932ced17e65ac95c157 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 30 Mar 2023 13:19:26 +0000 Subject: [PATCH 0248/1483] instrument-ada_unit.adb: tune Remove_Warnings_And_Style_Checks_Pragmas Instead of taking a rewriter object, make it accept a rewriting handle for an analysis unit, since this is all what it needs to do its work. This makes it possible to use this API when no rewriter object is available. --- tools/gnatcov/instrument-ada_unit.adb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index a5bc9aab1..888a6d4bc 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1163,7 +1163,7 @@ package body Instrument.Ada_Unit is -- the corresponding error message. procedure Remove_Warnings_And_Style_Checks_Pragmas - (Rewriter : Ada_Source_Rewriter'Class); + (Unit : Unit_Rewriting_Handle); -- Remove all Warnings/Style_Checks pragmas in Rewriter's unit ---------------------------- @@ -6981,7 +6981,7 @@ package body Instrument.Ada_Unit is -- instrumentation generate warning-free or well-formatted -- code. - Remove_Warnings_And_Style_Checks_Pragmas (Self); + Remove_Warnings_And_Style_Checks_Pragmas (Handle (Self.Unit)); declare use Ada.Strings.Wide_Wide_Unbounded.Aux; @@ -7052,7 +7052,7 @@ package body Instrument.Ada_Unit is ---------------------------------------------- procedure Remove_Warnings_And_Style_Checks_Pragmas - (Rewriter : Ada_Source_Rewriter'Class) + (Unit : Unit_Rewriting_Handle) is function Should_Remove (Node : Node_Rewriting_Handle) return Boolean; @@ -7113,7 +7113,7 @@ package body Instrument.Ada_Unit is -- Start of processing for Remove_Warnings_And_Style_Checks_Pragmas begin - Process (Handle (Rewriter.Unit.Root)); + Process (Root (Unit)); end Remove_Warnings_And_Style_Checks_Pragmas; ------------------------------- From c4230b7c1ed0804c5b389bbc33fc1211987d989a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 30 Mar 2023 13:27:08 +0000 Subject: [PATCH 0249/1483] instrument-ada_unit.adb: create a dedicated subp. to write unit to file This is preliminary work to be able to write a rewritten unit without relying on Ada_Source_Rewriter's Apply primitive. --- tools/gnatcov/instrument-ada_unit.adb | 123 ++++++++++++++------------ 1 file changed, 67 insertions(+), 56 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 888a6d4bc..b4833d5aa 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1166,6 +1166,12 @@ package body Instrument.Ada_Unit is (Unit : Unit_Rewriting_Handle); -- Remove all Warnings/Style_Checks pragmas in Rewriter's unit + procedure Write_To_File (Unit : Unit_Rewriting_Handle; Filename : String); + -- Unparse Unit into the file at Filename (creating it if needed). + -- + -- Note that this calls Remove_Warnings_And_Style_Checks_Pragmas before + -- unparsing the unit. + ---------------------------- -- Source level rewriting -- ---------------------------- @@ -6976,62 +6982,8 @@ package body Instrument.Ada_Unit is procedure Apply (Self : in out Ada_Source_Rewriter'Class) is begin - -- Automatically insert pragmas to disable style checks and - -- warnings in generated code: it is not our goal to make - -- instrumentation generate warning-free or well-formatted - -- code. - - Remove_Warnings_And_Style_Checks_Pragmas (Handle (Self.Unit)); - - declare - use Ada.Strings.Wide_Wide_Unbounded.Aux; - - Unit : constant Unit_Rewriting_Handle := Handle (Self.Unit); - Source : constant Unbounded_Wide_Wide_String := Unparse (Unit); - - -- To avoid copying the potentially big string for sources on the - -- secondary stack (and reduce the amount of copies anyway), use the - -- internal GNAT API to retreive the internal string access and - -- process it by chunks. - - Source_Access : Big_Wide_Wide_String_Access; - Length : Natural; - - Chunk_Size : constant := 4096; - Position : Natural; - - Filename : constant String := To_String (Self.Output_Filename); - Out_File : Text_Files.File_Type; - begin - Abort_Rewriting (Self.Handle); - Out_File.Create (Filename); - Put_Warnings_And_Style_Checks_Pragmas (Out_File); - - Get_Wide_Wide_String (Source, Source_Access, Length); - Position := Source_Access.all'First; - - while Position <= Length loop - declare - Chunk_First : constant Natural := Position; - Chunk_Last : constant Natural := Natural'Min - (Chunk_First + Chunk_Size - 1, Length); - - Chunk : Wide_Wide_String renames - Source_Access.all (Chunk_First .. Chunk_Last); - Encoded_Chunk : constant String := - Ada.Characters.Conversions.To_String (Chunk); - begin - Out_File.Put (Encoded_Chunk); - Position := Chunk_Last + 1; - end; - end loop; - - Out_File.Close; - if Switches.Pretty_Print then - Text_Files.Run_GNATpp (Out_File); - end if; - end; - + Write_To_File (Handle (Self.Unit), To_String (Self.Output_Filename)); + Abort_Rewriting (Self.Handle); Self.Finalize; end Apply; @@ -7116,6 +7068,65 @@ package body Instrument.Ada_Unit is Process (Root (Unit)); end Remove_Warnings_And_Style_Checks_Pragmas; + ------------------- + -- Write_To_File -- + ------------------- + + procedure Write_To_File (Unit : Unit_Rewriting_Handle; Filename : String) is + begin + -- Automatically insert pragmas to disable style checks and warnings in + -- generated code: it is not our goal to make instrumentation generate + -- warning-free or well-formatted code. + + Remove_Warnings_And_Style_Checks_Pragmas (Unit); + + declare + use Ada.Strings.Wide_Wide_Unbounded.Aux; + + Source : constant Unbounded_Wide_Wide_String := Unparse (Unit); + + -- To avoid copying the potentially big string for sources on the + -- secondary stack (and reduce the amount of copies anyway), use the + -- internal GNAT API to retreive the internal string access and + -- process it by chunks. + + Source_Access : Big_Wide_Wide_String_Access; + Length : Natural; + + Chunk_Size : constant := 4096; + Position : Natural; + + Out_File : Text_Files.File_Type; + begin + Out_File.Create (Filename); + Put_Warnings_And_Style_Checks_Pragmas (Out_File); + + Get_Wide_Wide_String (Source, Source_Access, Length); + Position := Source_Access.all'First; + + while Position <= Length loop + declare + Chunk_First : constant Natural := Position; + Chunk_Last : constant Natural := Natural'Min + (Chunk_First + Chunk_Size - 1, Length); + + Chunk : Wide_Wide_String renames + Source_Access.all (Chunk_First .. Chunk_Last); + Encoded_Chunk : constant String := + Ada.Characters.Conversions.To_String (Chunk); + begin + Out_File.Put (Encoded_Chunk); + Position := Chunk_Last + 1; + end; + end loop; + + Out_File.Close; + if Switches.Pretty_Print then + Text_Files.Run_GNATpp (Out_File); + end if; + end; + end Write_To_File; + ------------------------------- -- Auto_Dump_Buffers_In_Main -- ------------------------------- From ea3fde432aa710d3804a2807d8b0212e6c30c6e6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 3 Apr 2023 12:32:58 +0000 Subject: [PATCH 0250/1483] instrument-ada_unit.adb: fix handling of mains that are specs Assuming that `Main` is a generic procedure instantiation acting as a main for the project to instrument: ```ada procedure [Main] is new ... ``` In order to insert code to automatically dump coverage buffers (`--dump-trigger=` anything but manual), we need a procedure body so that we can insert dumps for coverage buffers. We can do this with a wrapper procedure: ```ada with Original_[Main]; procedure [Main] is begin Original_[Main]; end [Main]; ``` However we also need `Main` to still be a spec-only unit, so that the GPR clause `for Main use ("[main].ads");` stays valid. To satisfy all these constraints, we also need to introduce an intermediate generic procedure instantiation so that we have: 1. The original generic procedure instantiation 2. A generic procedure that wraps 1.; this one can have a body, and thus host code to dump coverage buffers. 3. A generic procedure instantiation for 2., acting as the main for the instrumented project. This commits implements this scheme to fix the handling of such mains. --- .../instr-cov/main-spec/generic_main.adb | 6 + .../instr-cov/main-spec/generic_main.ads | 2 + .../tests/instr-cov/main-spec/inst_main.ads | 3 + .../instr-cov/main-spec/pkg-child_main.ads | 3 + testsuite/tests/instr-cov/main-spec/pkg.ads | 2 + testsuite/tests/instr-cov/main-spec/test.py | 44 ++ tools/gnatcov/instrument-ada_unit.adb | 527 +++++++++++++++--- 7 files changed, 521 insertions(+), 66 deletions(-) create mode 100644 testsuite/tests/instr-cov/main-spec/generic_main.adb create mode 100644 testsuite/tests/instr-cov/main-spec/generic_main.ads create mode 100644 testsuite/tests/instr-cov/main-spec/inst_main.ads create mode 100644 testsuite/tests/instr-cov/main-spec/pkg-child_main.ads create mode 100644 testsuite/tests/instr-cov/main-spec/pkg.ads create mode 100644 testsuite/tests/instr-cov/main-spec/test.py diff --git a/testsuite/tests/instr-cov/main-spec/generic_main.adb b/testsuite/tests/instr-cov/main-spec/generic_main.adb new file mode 100644 index 000000000..b10af690c --- /dev/null +++ b/testsuite/tests/instr-cov/main-spec/generic_main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Generic_Main is +begin + Put_Line ("Hello world"); +end Generic_Main; diff --git a/testsuite/tests/instr-cov/main-spec/generic_main.ads b/testsuite/tests/instr-cov/main-spec/generic_main.ads new file mode 100644 index 000000000..9a4ff9488 --- /dev/null +++ b/testsuite/tests/instr-cov/main-spec/generic_main.ads @@ -0,0 +1,2 @@ +generic +procedure Generic_Main; diff --git a/testsuite/tests/instr-cov/main-spec/inst_main.ads b/testsuite/tests/instr-cov/main-spec/inst_main.ads new file mode 100644 index 000000000..8969c0e8a --- /dev/null +++ b/testsuite/tests/instr-cov/main-spec/inst_main.ads @@ -0,0 +1,3 @@ +with Generic_Main; + +procedure Inst_Main is new Generic_Main; diff --git a/testsuite/tests/instr-cov/main-spec/pkg-child_main.ads b/testsuite/tests/instr-cov/main-spec/pkg-child_main.ads new file mode 100644 index 000000000..b911b12a5 --- /dev/null +++ b/testsuite/tests/instr-cov/main-spec/pkg-child_main.ads @@ -0,0 +1,3 @@ +with Generic_Main; + +procedure Pkg.Child_Main is new Generic_Main; diff --git a/testsuite/tests/instr-cov/main-spec/pkg.ads b/testsuite/tests/instr-cov/main-spec/pkg.ads new file mode 100644 index 000000000..2db1f1de6 --- /dev/null +++ b/testsuite/tests/instr-cov/main-spec/pkg.ads @@ -0,0 +1,2 @@ +package Pkg is +end Pkg; diff --git a/testsuite/tests/instr-cov/main-spec/test.py b/testsuite/tests/instr-cov/main-spec/test.py new file mode 100644 index 000000000..c3351a17f --- /dev/null +++ b/testsuite/tests/instr-cov/main-spec/test.py @@ -0,0 +1,44 @@ +""" +Check that instrumentation with automatic dump works correctly when the main is +an Ada spec. +""" + +import os.path + +from SCOV.instr import available_ada_dump_triggers +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir() + +main_sources = ["inst_main.ads", "pkg-child_main.ads"] +mains = [os.path.splitext(f)[0] for f in main_sources] + +# Explicitly test all available dump triggers to maximize coverage +for dump_trigger in available_ada_dump_triggers(): + thistest.log(f"== {dump_trigger} ==") + tmp.to_subdir(f"tmp_{dump_trigger}") + + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=main_sources, srcdirs=[".."]), + ), + covlevel="stmt", + mains=mains, + extra_coverage_args=["--annotate=xcov"], + ) + check_xcov_reports( + "*.xcov", + { + "generic_main.adb.xcov": {"+": {5}}, + "inst_main.ads.xcov": {}, + "pkg-child_main.ads.xcov": {}, + }, + "obj", + ) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index b4833d5aa..0ea790069 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -60,6 +60,7 @@ package body Instrument.Ada_Unit is package GPR renames GNATCOLL.Projects; package LAL renames Libadalang.Analysis; + package LALCO renames Libadalang.Common; function Create_Context_Instrument (N : Libadalang.Analysis.Ada_Node'Class) return Context_Handle; @@ -1169,8 +1170,8 @@ package body Instrument.Ada_Unit is procedure Write_To_File (Unit : Unit_Rewriting_Handle; Filename : String); -- Unparse Unit into the file at Filename (creating it if needed). -- - -- Note that this calls Remove_Warnings_And_Style_Checks_Pragmas before - -- unparsing the unit. + -- Note that this calls Remove_Warnings_And_Style_Checks_Pragmas and + -- Put_Warnings_And_Style_Checks_Pragmas before unparsing the unit. ---------------------------- -- Source level rewriting -- @@ -1212,7 +1213,8 @@ package body Instrument.Ada_Unit is Cannot_Instrument_Main_Error : exception; -- See Probe_Main - type Main_Instrumentation_Description is record + type Main_Instrumentation_Description (Synthetic : Boolean := False) + is record Main : Compilation_Unit_Name; -- Name of the compilation unit corresponding to the main body @@ -1223,17 +1225,37 @@ package body Instrument.Ada_Unit is -- Resolved dump trigger after eventual override depending on the -- features available on the runtime. - Prelude : LAL.Ada_Node_List; - -- Prelude for the main compilation unit + Prelude : Node_Rewriting_Handle; + -- Prelude (list of nodes) for the main compilation unit - Subp_Body : LAL.Subp_Body; - -- Subprogram body in which to insert the code to dump coverage buffers. + Main_Decls : Node_Rewriting_Handle; + -- List of declarations for the procedure body that implements the main + + Main_Stmts : Node_Rewriting_Handle; + -- List of statements for the procedure body that implements the main + + case Synthetic is + when False => + Subp_Body : LAL.Subp_Body; + -- Subprogram body in which to insert the code to dump coverage + -- buffers. + + when True => + Generic_Wrapper_Body_Filename : Unbounded_String; + Generic_Wrapper_Body : Node_Rewriting_Handle; + -- See homonym arguments in Expand_Main_Generic_Instantiation + end case; end record; -- Nodes needed to instrument main subprograms so that they can dump -- coverage buffers. + -- + -- Synthetic designates whether the main subprogram body comes from + -- sources (Synthetic => False) or was created to wrap a generic + -- subprogram instantiation (Synthetic => True). function Probe_Main (Dump_Config : Any_Dump_Config; + Info : in out Project_Info; Rewriter : Ada_Source_Rewriter'Class) return Main_Instrumentation_Description; -- Given a rewriter for the main source, return a description of the main @@ -1242,6 +1264,65 @@ package body Instrument.Ada_Unit is -- Emit a warning and raise a Cannot_Instrument_Main_Error if the main does -- not have a structure that is expected for a main. + procedure Stop_Probe_Main (Unit : Analysis_Unit; Message : String) + with No_Return; + -- Emit a warning with the given message and raise a + -- Cannot_Instrument_Main_Error exception. + + procedure Expand_Main_Generic_Instantiation + (Main : Generic_Subp_Instantiation; + Info : in out Project_Info; + Generic_Wrapper_Body_Filename : out Unbounded_String; + Generic_Wrapper_Body : out Node_Rewriting_Handle; + Prelude : out Node_Rewriting_Handle; + Main_Decls : out Node_Rewriting_Handle; + Main_Stmts : out Node_Rewriting_Handle); + -- Assuming that Main is a generic procedure instantiation acting as a main + -- for the project: + -- + -- procedure [Main] is new ... + -- + -- We need a procedure body in order to insert dumps for coverage buffers. + -- We also need Main to still be a spec-only unit, so that the GPR clause + -- "for Main use ("[main].ads");" stays valid. To satisfy all these + -- constraints, this procedure does the following steps: + -- + -- 1. Move the instantiation to a new unit: + -- + -- procedure Xcov_Wrapped_[Main] is new ... + -- + -- 2. Create a generic procedure (in which to insert dumps) wrapper for it: + -- + -- [spec] + -- generic + -- procedure Xcov_Genwrap_[Main]; + -- + -- [body] + -- with Xcov_Wrapped_[Main]; + -- + -- procedure Xcov_Genwrap_[Main] is + -- begin + -- Xcov_Wrapped_[Main]; + -- end Xcov_Genwrap_[Main]; + -- + -- 3. Replace the original main spec with the following instantiation: + -- + -- with Xcov_Genwrap_[Main]; + -- + -- procedure [Main] is new Xcov_Genwrap_[Main]; + -- + -- All new sources but the body of Xcov_Genwrap_[Main] are written to files + -- in Info's output directory. Nodes for the body are put into + -- Generic_Wrapper_Body/Main_Decls/Main_Stmts, and the filename where to + -- write it is assigned to Generic_Wrapper_Body_Filename. + + function Simple_Dump_Proc_Call + (RH : Rewriting_Handle; + Helper_Unit : Ada_Qualified_Name) return Node_Rewriting_Handle; + -- Assuming that RH is the rewriting handle for the main to instrument in + -- main-end mode and that Helper_Unit is the unit that contains the dump + -- procedure, return a call statement node for this dump procedure. + procedure Insert_Simple_Dump_Proc_Calls (RH : Rewriting_Handle; Helper_Unit : Ada_Qualified_Name; @@ -6611,37 +6692,14 @@ package body Instrument.Ada_Unit is function Probe_Main (Dump_Config : Any_Dump_Config; + Info : in out Project_Info; Rewriter : Ada_Source_Rewriter'Class) return Main_Instrumentation_Description is - procedure Stop (Message : String) with No_Return; - -- Emit a warning with the given message and raise a - -- Cannot_Instrument_Main_Error exception. - - ---------- - -- Stop -- - ---------- - - procedure Stop (Message : String) is - Filename : constant String := - Ada.Directories.Simple_Name (To_String (Rewriter.Input_Filename)); - begin - -- TODO??? Ideally, we would like to display the source location in - -- Filename that led to abort the instrumentation of this main. This - -- is not possible today since we are possibly rewriting a source - -- file that was already instrumented, so slocs do not reflect the - -- sources that users see. - - Warn ("cannot dump coverage buffers in " & Filename & ": " & Message); - raise Cannot_Instrument_Main_Error; - end Stop; - U : Analysis_Unit; + CU : LAL.Compilation_Unit; Tmp : LAL.Ada_Node; - CU : LAL.Compilation_Unit; - Subp_Body : LAL.Subp_Body; - Controlled_Types_Available : Boolean; Actual_Dump_Trigger : Auto_Dump_Trigger; @@ -6669,21 +6727,14 @@ package body Instrument.Ada_Unit is Tmp := U.Root; if Tmp.Kind /= Ada_Compilation_Unit then - Stop ("compilation unit expected"); + Stop_Probe_Main (U, "compilation unit expected"); else CU := Tmp.As_Compilation_Unit; end if; Tmp := CU.F_Body; if Tmp.Kind /= Ada_Library_Item then - Stop ("library item expected"); - end if; - - Tmp := Tmp.As_Library_Item.F_Item.As_Ada_Node; - if Tmp.Kind /= Ada_Subp_Body then - Stop ("subprogram body expected"); - else - Subp_Body := Tmp.As_Subp_Body; + Stop_Probe_Main (U, "library item expected"); end if; Controlled_Types_Available := @@ -6698,14 +6749,338 @@ package body Instrument.Ada_Unit is Main.Unit := To_Qualified_Name (CU.P_Syntactic_Fully_Qualified_Name); - return - (Main, - Controlled_Types_Available, - Actual_Dump_Trigger, - CU.F_Prelude, - Subp_Body); + Tmp := Tmp.As_Library_Item.F_Item.As_Ada_Node; + case Tmp.Kind is + when Ada_Subp_Body => + declare + Subp_Body : constant LAL.Subp_Body := Tmp.As_Subp_Body; + begin + return + (Synthetic => False, + Main => Main, + Controlled_Types_Available => Controlled_Types_Available, + Actual_Dump_Trigger => Actual_Dump_Trigger, + Prelude => Handle (CU.F_Prelude), + Main_Decls => + Handle (Subp_Body.F_Decls.F_Decls), + Main_Stmts => + Handle (Subp_Body.F_Stmts.F_Stmts), + Subp_Body => Subp_Body); + end; + + when Ada_Generic_Subp_Instantiation => + declare + Generic_Wrapper_Body_Filename : Unbounded_String; + Generic_Wrapper_Body : Node_Rewriting_Handle; + Prelude : Node_Rewriting_Handle; + Main_Decls : Node_Rewriting_Handle; + Main_Stmts : Node_Rewriting_Handle; + begin + Expand_Main_Generic_Instantiation + (Tmp.As_Generic_Subp_Instantiation, + Info, + Generic_Wrapper_Body_Filename, + Generic_Wrapper_Body, + Prelude, + Main_Decls, + Main_Stmts); + return + (Synthetic => True, + Main => Main, + Controlled_Types_Available => Controlled_Types_Available, + Actual_Dump_Trigger => Actual_Dump_Trigger, + Prelude => Prelude, + Main_Decls => Main_Decls, + Main_Stmts => Main_Stmts, + Generic_Wrapper_Body_Filename => + Generic_Wrapper_Body_Filename, + Generic_Wrapper_Body => Generic_Wrapper_Body); + end; + + -- Note that a renaming ("procedure X renames ...") cannot be used as + -- a main program. + + when others => + Stop_Probe_Main (U, "subprogram body expected"); + end case; end Probe_Main; + --------------------- + -- Stop_Probe_Main -- + --------------------- + + procedure Stop_Probe_Main (Unit : Analysis_Unit; Message : String) is + Filename : constant String := + Ada.Directories.Simple_Name (Unit.Get_Filename); + begin + -- TODO??? Ideally, we would like to display the source location in + -- Filename that led to abort the instrumentation of this main. This + -- is not possible today since we are possibly rewriting a source + -- file that was already instrumented, so slocs do not reflect the + -- sources that users see. + + Warn ("cannot dump coverage buffers in " & Filename & ": " & Message); + raise Cannot_Instrument_Main_Error; + end Stop_Probe_Main; + + --------------------------------------- + -- Expand_Main_Generic_Instantiation -- + --------------------------------------- + + procedure Expand_Main_Generic_Instantiation + (Main : Generic_Subp_Instantiation; + Info : in out Project_Info; + Generic_Wrapper_Body_Filename : out Unbounded_String; + Generic_Wrapper_Body : out Node_Rewriting_Handle; + Prelude : out Node_Rewriting_Handle; + Main_Decls : out Node_Rewriting_Handle; + Main_Stmts : out Node_Rewriting_Handle) + is + Unit : constant Analysis_Unit := Main.Unit; + UH : constant Unit_Rewriting_Handle := Handle (Unit); + RH : constant Rewriting_Handle := Handle (Unit.Context); + + function Wrap_Name + (Orig_Name : Defining_Name; + Prefix : String) return Node_Rewriting_Handle; + -- Return a node that is a copy of Orig_Name but with an additional + -- prefix for the identifier of the designated entity. + -- + -- For instance: + -- + -- Wrap_Name (, "Prefix") = + -- Wrap_Name (, "Prefix") = + + Output_Dir : constant String := To_String (Info.Output_Dir); + + function Filename + (Unit_Name : Node_Rewriting_Handle; Extension : String) return String; + -- Return the name of the source file in Output_Dir that contains a unit + -- of the given name and with the given extension. + + --------------- + -- Wrap_Name -- + --------------- + + function Wrap_Name + (Orig_Name : Defining_Name; + Prefix : String) return Node_Rewriting_Handle + is + Result : constant Node_Rewriting_Handle := + Clone (Handle (Orig_Name.F_Name)); + + -- Get the identifier to rewrite + + Id : LAL.Name := Orig_Name.F_Name; + R_Id : Node_Rewriting_Handle := Result; + begin + case Id.Kind is + when LALCO.Ada_Dotted_Name => + Id := Id.As_Dotted_Name.F_Suffix.As_Name; + R_Id := Child (R_Id, Dotted_Name_F_Suffix); + + when LALCO.Ada_Identifier => + null; + + when others => + Stop_Probe_Main + (Unit, "unexpected unit name component: " & Id.Kind'Image); + end case; + + -- Rewrite it and return the name + + Set_Text (R_Id, To_Text (Prefix) & Id.Text); + return Result; + end Wrap_Name; + + -------------- + -- Filename -- + -------------- + + function Filename + (Unit_Name : Node_Rewriting_Handle; Extension : String) return String + is + Result : Unbounded_String; + + procedure Visit (N : Node_Rewriting_Handle); + -- Append to Result N's contribution to the requested filename + + ----------- + -- Visit -- + ----------- + + procedure Visit (N : Node_Rewriting_Handle) is + begin + case Kind (N) is + when LALCO.Ada_Identifier => + Append (Result, To_UTF8 (Text (N))); + + when LALCO.Ada_Dotted_Name => + Visit (Child (N, Dotted_Name_F_Prefix)); + Append (Result, '-'); + Visit (Child (N, Dotted_Name_F_Suffix)); + + when others => + + -- Since we abort rewriting in Wrap_Name above for such + -- cases, the following should be unreachable. + + raise Program_Error with + "invalid unit name component: " & Kind (N)'Image; + end case; + end Visit; + + -- Start of processing for Filenaem + + begin + Visit (Unit_Name); + Append (Result, Extension); + return Output_Dir + / Ada.Characters.Handling.To_Lower (To_String (Result)); + end Filename; + + Wrapped_Prefix : constant String := "Xcov_Wrapped_"; + Generic_Wrapper_Prefix : constant String := "Xcov_Genwrap_"; + -- Prefixes used to create names for the additional units created while + -- expanding this main. + + Generic_Wrapper_Spec_Template : constant Text_Type := + "generic" & Chars.LF + & "procedure {};" & Chars.LF; + Generic_Wrapper_Body_Template : constant Text_Type := + "with {};" & Chars.LF + & Chars.LF + & "procedure {} is" & Chars.LF + & "begin" & Chars.LF + & " {};" & Chars.LF + & "end {};" & Chars.LF; + Main_Template : constant Text_Type := + "with {};" & Chars.LF + & Chars.LF + & "procedure {} is new {};" & Chars.LF; + -- Templates used to produce the synthetic sources created while + -- expanding this main. + + -- Step 1: rename the instantiation and move it to a new unit + + Orig_Name : constant Defining_Name := Main.F_Subp_Name; + + Main_Name : constant Node_Rewriting_Handle := + Clone (Handle (Orig_Name)); + Wrapped_Name : constant Node_Rewriting_Handle := + Wrap_Name (Orig_Name, Wrapped_Prefix); + Generic_Wrapper_Name : constant Node_Rewriting_Handle := + Wrap_Name (Orig_Name, Generic_Wrapper_Prefix); + + Has_Error : Boolean := False; + + -- Start of processing for Expand_Main_Generic_Instantiation + + begin + -- In order for the renaming to be valid, update all references to this + -- instantiation in this unit. Emit a warning and skip the renaming if + -- for some reason we cannot get the references to update. + + begin + for R of Orig_Name.P_Find_All_References (Units => (1 => Unit)) loop + case Kind (R) is + when Precise => + Replace (Handle (Ref (R)), Clone (Wrapped_Name)); + + when No_Ref | Imprecise => + null; + + when LALCO.Error => + Has_Error := True; + end case; + end loop; + exception + when Property_Error => + Has_Error := True; + end; + if Has_Error then + Report (Node => Orig_Name, + Msg => "Could not find all references to this subprogram", + Kind => Low_Warning); + end if; + + -- Rename the defining name itself and write the resulting unit in a new + -- source file (it will not change after this). + + Replace (Handle (Orig_Name.F_Name), Clone (Wrapped_Name)); + Write_To_File (UH, Filename (Wrapped_Name, ".ads")); + + -- Step 2: create a generic procedure (in which to insert dumps) wrapper + -- for it. Do not write the body to a file right now since main + -- instrumentation may modify it. + + Set_Root + (UH, + Create_From_Template + (RH, + Generic_Wrapper_Spec_Template, + (1 => Generic_Wrapper_Name), + Rule => Compilation_Unit_Rule)); + Write_To_File (UH, Filename (Generic_Wrapper_Name, ".ads")); + + Generic_Wrapper_Body := + Create_From_Template + (RH, + Generic_Wrapper_Body_Template, + (1 => Wrapped_Name, + 2 => Generic_Wrapper_Name, + 3 => Wrapped_Name, + 4 => Generic_Wrapper_Name), + Rule => Compilation_Unit_Rule); + Generic_Wrapper_Body_Filename := + To_Unbounded_String (Filename (Generic_Wrapper_Name, ".adb")); + + -- Code that is inserted to dump coverage buffers will land in this + -- wrapper: set Prelude, Main_Decls and Main_Stmts accordingly. + + Prelude := Child (Generic_Wrapper_Body, Compilation_Unit_F_Prelude); + declare + Subp_Body : constant Node_Rewriting_Handle := + Child + (Generic_Wrapper_Body, + (Compilation_Unit_F_Body, Library_Item_F_Item)); + begin + Main_Decls := + Child (Subp_Body, (Subp_Body_F_Decls, Declarative_Part_F_Decls)); + Main_Stmts := + Child (Subp_Body, (Subp_Body_F_Stmts, Handled_Stmts_F_Stmts)); + end; + + -- Step 3: replace the original main spec with the following + -- instantiation. No need to manually write it to a file: applying the + -- current rewriting session will do it. + + Set_Root + (UH, + Create_From_Template + (RH, + Main_Template, + (1 => Generic_Wrapper_Name, + 2 => Main_Name, + 3 => Generic_Wrapper_Name), + Rule => Compilation_Unit_Rule)); + end Expand_Main_Generic_Instantiation; + + --------------------------- + -- Simple_Dump_Proc_Call -- + --------------------------- + + function Simple_Dump_Proc_Call + (RH : Rewriting_Handle; + Helper_Unit : Ada_Qualified_Name) return Node_Rewriting_Handle + is + Dump_Procedure : Ada_Qualified_Name := Helper_Unit; + begin + Dump_Procedure.Append (Dump_Procedure_Name); + return Create_Regular_Node + (RH, Ada_Call_Stmt, (1 => To_Nodes (RH, Dump_Procedure))); + end Simple_Dump_Proc_Call; + ----------------------------------- -- Insert_Simple_Dump_Proc_Calls -- ----------------------------------- @@ -6720,10 +7095,8 @@ package body Instrument.Ada_Unit is -- statement list of each top level exception handler, and -- right before each return statment that applies to the main. - Dump_Procedure : Ada_Qualified_Name; - -- Name of the procedure to dump coverage buffers - - Call_Stmt : Node_Rewriting_Handle; + Call_Stmt : constant Node_Rewriting_Handle := + Simple_Dump_Proc_Call (RH, Helper_Unit); -- Call invoking the dump procedure function Process_Returns @@ -6760,11 +7133,6 @@ package body Instrument.Ada_Unit is -- Start of processing for Insert_Simple_Dump_Proc_Calls begin - Dump_Procedure := Helper_Unit; - Dump_Procedure.Append (Dump_Procedure_Name); - Call_Stmt := Create_Regular_Node - (RH, Ada_Call_Stmt, (1 => To_Nodes (RH, Dump_Procedure))); - -- Add a Dump_Buffer call at the end of the main's handeled statements Append_Child (Handled_Stmt_List, Call_Stmt); @@ -7156,7 +7524,7 @@ package body Instrument.Ada_Unit is -- a warning and do nothing. begin - Desc := Probe_Main (Dump_Config, Rewriter); + Desc := Probe_Main (Dump_Config, Info, Rewriter); exception when Cannot_Instrument_Main_Error => return; @@ -7174,8 +7542,6 @@ package body Instrument.Ada_Unit is Has_Controlled => Desc.Controlled_Types_Available); declare - Prelude : constant Node_Rewriting_Handle := Handle (Desc.Prelude); - With_Clause : constant Node_Rewriting_Handle := Create_From_Template (RH, @@ -7198,9 +7564,9 @@ package body Instrument.Ada_Unit is Rule => Pragma_Rule); begin - Append_Child (Prelude, With_Clause); - Append_Child (Prelude, With_RTS_Clause); - Append_Child (Prelude, Runtime_Version_Check_Node); + Append_Child (Desc.Prelude, With_Clause); + Append_Child (Desc.Prelude, With_RTS_Clause); + Append_Child (Desc.Prelude, Runtime_Version_Check_Node); end; -- Depending on the chosen coverage buffers dump trigger, insert the @@ -7220,8 +7586,6 @@ package body Instrument.Ada_Unit is Call_Expr : Node_Rewriting_Handle; Call_Decl : Node_Rewriting_Handle; - Decl_List : constant Node_Rewriting_Handle := - Handle (Desc.Subp_Body.F_Decls.F_Decls); begin Register_Function := Helper_Unit; Register_Function.Append (Register_Dump_Function_Name); @@ -7232,7 +7596,7 @@ package body Instrument.Ada_Unit is "Autodump_Dummy : {} := {};", (1 => To_Nodes (RH, Witness_Dummy_Type_Name), 2 => Call_Expr), Object_Decl_Rule); - Insert_Child (Decl_List, 1, Call_Decl); + Insert_Child (Desc.Main_Decls, 1, Call_Decl); end; when Main_End => @@ -7255,11 +7619,42 @@ package body Instrument.Ada_Unit is if Desc.Controlled_Types_Available then Insert_Controlled_Dump_Object_Decl - (RH, Helper_Unit, Handle (Desc.Subp_Body.F_Decls.F_Decls)); + (RH, Helper_Unit, Desc.Main_Decls); + + -- Past this, we know that we have to insert a call to the dump + -- procedure at points where to dump traces. + + elsif Desc.Synthetic then + + -- The code to instrument is synthetic: we do not have regular + -- nodes, and thus we cannot call Insert_Simple_Dump_Proc_Calls. + -- Fortunately, in this situation we know there there is only one + -- place where we want to dump coverage buffers: at the end of the + -- wrapper procedure body. + + Append_Child + (Desc.Main_Stmts, Simple_Dump_Proc_Call (RH, Helper_Unit)); + else Insert_Simple_Dump_Proc_Calls (RH, Helper_Unit, Desc.Subp_Body); end if; end case; + + -- In case we created synthetic sources, write them down before calling + -- Rewriter.Apply since these sources rely on the rewriting session. + + if Desc.Synthetic then + declare + UH : constant Unit_Rewriting_Handle := + Handle (Rewriter.Unit); + Saved_Root : constant Node_Rewriting_Handle := Root (UH); + begin + Set_Root (UH, Desc.Generic_Wrapper_Body); + Write_To_File (UH, To_String (Desc.Generic_Wrapper_Body_Filename)); + Set_Root (UH, Saved_Root); + end; + end if; + Rewriter.Apply; end Auto_Dump_Buffers_In_Main; From 24c4be20fb77273ab4bf0cabdbe21dcd41739ffb Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 11 Apr 2023 11:21:05 +0000 Subject: [PATCH 0251/1483] .gitlab-ci.yml: fix build of "edge" branches Previous changes for #50 handled builds that test a pull request that target the `edge` branch (`CI_MERGE_REQUEST_TARGET_BRANCH_NAME=edge` for them), but lacks support for builds testing the `edge` branch itself (`CI_COMMIT_BRANCH=edge` for them). --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ced9d86da..0fc152d20 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,7 +20,7 @@ variables: .edge_vars: &edge_vars - | - if [ $CI_MERGE_REQUEST_TARGET_BRANCH_NAME = edge ] + if [ $CI_COMMIT_BRANCH = edge ] || [ $CI_MERGE_REQUEST_TARGET_BRANCH_NAME = edge ] then EDGE_QUALIFIER="-Qedge" EDGE_REPO_SUFFIX="-edge" From 6ff80d8f9577c103765a72e9de0f6398cf834639 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 3 Apr 2023 12:21:26 +0200 Subject: [PATCH 0252/1483] instr-cov/main_no_ext: new regression test TN: U412-040 --- .../tests/instr-cov/main_no_ext/main.adb | 4 +++ testsuite/tests/instr-cov/main_no_ext/p.gpr | 5 ++++ testsuite/tests/instr-cov/main_no_ext/test.py | 30 +++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 testsuite/tests/instr-cov/main_no_ext/main.adb create mode 100644 testsuite/tests/instr-cov/main_no_ext/p.gpr create mode 100644 testsuite/tests/instr-cov/main_no_ext/test.py diff --git a/testsuite/tests/instr-cov/main_no_ext/main.adb b/testsuite/tests/instr-cov/main_no_ext/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/instr-cov/main_no_ext/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/main_no_ext/p.gpr b/testsuite/tests/instr-cov/main_no_ext/p.gpr new file mode 100644 index 000000000..358e08bd4 --- /dev/null +++ b/testsuite/tests/instr-cov/main_no_ext/p.gpr @@ -0,0 +1,5 @@ +project P is + for Source_Dirs use ("."); + for Object_Dir use "obj"; + for Main use ("main"); +end P; diff --git a/testsuite/tests/instr-cov/main_no_ext/test.py b/testsuite/tests/instr-cov/main_no_ext/test.py new file mode 100644 index 000000000..c89e9e2d1 --- /dev/null +++ b/testsuite/tests/instr-cov/main_no_ext/test.py @@ -0,0 +1,30 @@ +""" +Check that gnatcov correctly instruments as a main a file specified as a Main +through the Main attribute of the GPR file, but without an extension. Since +gnatcov instrument did not consider that main.adb as a main, it did not +instrument it as a main, and as a result coverage buffers were not included in +the link closure. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest + +Wdir("tmp_") + +gpr_obj_dir = os.path.join("..", "obj") +build_run_and_coverage( + gprsw=GPRswitches(root_project=os.path.join("..", "p.gpr")), + covlevel="stmt", + mains=["main"], + gpr_obj_dir=gpr_obj_dir, + gpr_exe_dir=gpr_obj_dir, + extra_coverage_args=["--annotate=xcov"], +) + +check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {3}}}, gpr_obj_dir) + +thistest.result() From 21fc5fd3eec31b9d87ffeb11b81175e1ffe93af5 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 11 Apr 2023 17:11:28 +0200 Subject: [PATCH 0253/1483] Instrument.C: fix handling of extending project We were not accounting for source dirs of the extended project when computing the list of switches to pass to the preprocessing invocation. --- .../tests/header_not_found/base_foo/base.gpr | 3 ++ .../tests/header_not_found/base_foo/support.h | 4 ++ .../header_not_found/include_base_foo/prj.gpr | 5 ++ .../header_not_found/include_base_foo/test.c | 6 +++ .../include_foo/headers/support.h | 6 +++ .../header_not_found/include_foo/prj.gpr | 5 ++ .../tests/header_not_found/include_foo/test.c | 6 +++ testsuite/tests/header_not_found/test.py | 46 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 8 +++- 9 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/header_not_found/base_foo/base.gpr create mode 100644 testsuite/tests/header_not_found/base_foo/support.h create mode 100644 testsuite/tests/header_not_found/include_base_foo/prj.gpr create mode 100644 testsuite/tests/header_not_found/include_base_foo/test.c create mode 100644 testsuite/tests/header_not_found/include_foo/headers/support.h create mode 100644 testsuite/tests/header_not_found/include_foo/prj.gpr create mode 100644 testsuite/tests/header_not_found/include_foo/test.c create mode 100644 testsuite/tests/header_not_found/test.py diff --git a/testsuite/tests/header_not_found/base_foo/base.gpr b/testsuite/tests/header_not_found/base_foo/base.gpr new file mode 100644 index 000000000..44b4bce9c --- /dev/null +++ b/testsuite/tests/header_not_found/base_foo/base.gpr @@ -0,0 +1,3 @@ +project Base is + for Languages use ("C"); +end Base; diff --git a/testsuite/tests/header_not_found/base_foo/support.h b/testsuite/tests/header_not_found/base_foo/support.h new file mode 100644 index 000000000..e05eb7e69 --- /dev/null +++ b/testsuite/tests/header_not_found/base_foo/support.h @@ -0,0 +1,4 @@ +int foo() +{ + return 0; +} diff --git a/testsuite/tests/header_not_found/include_base_foo/prj.gpr b/testsuite/tests/header_not_found/include_base_foo/prj.gpr new file mode 100644 index 000000000..def07ce5d --- /dev/null +++ b/testsuite/tests/header_not_found/include_base_foo/prj.gpr @@ -0,0 +1,5 @@ +project Prj extends "../base_foo/base.gpr" is + for Main use ("test.c"); + for Source_Dirs use ("."); + for Object_Dir use "obj"; +end Prj; diff --git a/testsuite/tests/header_not_found/include_base_foo/test.c b/testsuite/tests/header_not_found/include_base_foo/test.c new file mode 100644 index 000000000..5991bc01c --- /dev/null +++ b/testsuite/tests/header_not_found/include_base_foo/test.c @@ -0,0 +1,6 @@ +#include "support.h" + +int main() +{ + return foo(); +} diff --git a/testsuite/tests/header_not_found/include_foo/headers/support.h b/testsuite/tests/header_not_found/include_foo/headers/support.h new file mode 100644 index 000000000..85471f974 --- /dev/null +++ b/testsuite/tests/header_not_found/include_foo/headers/support.h @@ -0,0 +1,6 @@ +int foo() +{ + // Dummy comment to make this header different from its version in the + // extended project. + return 0; +} diff --git a/testsuite/tests/header_not_found/include_foo/prj.gpr b/testsuite/tests/header_not_found/include_foo/prj.gpr new file mode 100644 index 000000000..6f538b733 --- /dev/null +++ b/testsuite/tests/header_not_found/include_foo/prj.gpr @@ -0,0 +1,5 @@ +project Prj extends "../base_foo/base.gpr" is + for Main use ("test.c"); + for Source_Dirs use (".", "headers"); + for Object_dir use "obj"; +end Prj; diff --git a/testsuite/tests/header_not_found/include_foo/test.c b/testsuite/tests/header_not_found/include_foo/test.c new file mode 100644 index 000000000..5991bc01c --- /dev/null +++ b/testsuite/tests/header_not_found/include_foo/test.c @@ -0,0 +1,6 @@ +#include "support.h" + +int main() +{ + return foo(); +} diff --git a/testsuite/tests/header_not_found/test.py b/testsuite/tests/header_not_found/test.py new file mode 100644 index 000000000..df236b173 --- /dev/null +++ b/testsuite/tests/header_not_found/test.py @@ -0,0 +1,46 @@ +""" +Check that gnatcov correctly instruments an extending project when a source +includes a header belonging to the extended project. Also check that it picks +the version of the header that is in the ultimate extending project. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import thistest + +Wdir("tmp_") + + +def process(gpr_dir, expected_cov): + gpr_obj_dir = os.path.join(gpr_dir, "obj") + build_run_and_coverage( + gprsw=GPRswitches(root_project=os.path.join(gpr_dir, "prj.gpr")), + covlevel="stmt", + mains=["test"], + gpr_obj_dir=gpr_obj_dir, + gpr_exe_dir=gpr_obj_dir, + extra_coverage_args=["--annotate=xcov"], + ) + check_xcov_reports("*.xcov", expected_cov, gpr_obj_dir) + + +# Check that the header in the extended project is picked by gnatcov instrument +# when there is no version in the extending project. +expected_cov = { + "test.c.xcov": {"+": {5}}, + "support.h.xcov": {"+": {3}}, +} +process(os.path.join("..", "include_base_foo"), expected_cov) + +# If there is a version of the header in the extending project, check that this +# is the one picked. +expected_cov = { + "test.c.xcov": {"+": {5}}, + "support.h.xcov": {"+": {5}}, +} +process(os.path.join("..", "include_foo"), expected_cov) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 544f9004e..754baea18 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -4393,14 +4393,18 @@ package body Instrument.C is begin - -- Pass the source directories of the project file as -I options + -- Pass the source directories of the project file as -I options. Note + -- that this will duplicate with the project tree traversal below, but + -- we need this project source directories to be picked first. We thus + -- make sure to add them first to the PP_Search_Path list. Register_Source_Dirs (Info.Project); -- Pass the source directories of included projects as -I options Project.Iterate_Projects - (Info.Project, Register_Source_Dirs'Access, True); + (Info.Project, Register_Source_Dirs'Access, + Recursive => True, Include_Extended => True); -- Now get actual compiler switches from the project file for Filename. -- First try to get the switches specifically for Filename, then if From d0365b567ef3757176c7b3fccbc6f72b0b8d4324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 7 Apr 2023 12:21:33 +0200 Subject: [PATCH 0254/1483] Add sanity check for aspects attached to formal parameters Aspects specified for formal subprogram parameters should be instrumented in the same way as default expressions, so there is nothing in particular to be done. We also have no aspect that is supported by gnat and that accepts an expression executed at runtime, so we don't have the possibility to add a meaningful test for this. This is a sanity check to ensure there are no crashes in gnatcov while processing code with aspects attached to formal parameters. --- .../Ada2022/sanity/param_aspects/src/pkg.ads | 8 ++++++++ .../Ada2022/sanity/param_aspects/src/test_pkg.adb | 12 ++++++++++++ .../tests/Ada2022/sanity/param_aspects/test.py | 15 +++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 testsuite/tests/Ada2022/sanity/param_aspects/src/pkg.ads create mode 100644 testsuite/tests/Ada2022/sanity/param_aspects/src/test_pkg.adb create mode 100644 testsuite/tests/Ada2022/sanity/param_aspects/test.py diff --git a/testsuite/tests/Ada2022/sanity/param_aspects/src/pkg.ads b/testsuite/tests/Ada2022/sanity/param_aspects/src/pkg.ads new file mode 100644 index 000000000..8f670e8a9 --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/param_aspects/src/pkg.ads @@ -0,0 +1,8 @@ +pragma Ada_2022; + +package Pkg is + + function Foo (X : Integer; Y : Boolean with Unreferenced) return Integer is + (X); -- # expr + +end Pkg; diff --git a/testsuite/tests/Ada2022/sanity/param_aspects/src/test_pkg.adb b/testsuite/tests/Ada2022/sanity/param_aspects/src/test_pkg.adb new file mode 100644 index 000000000..a72492aec --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/param_aspects/src/test_pkg.adb @@ -0,0 +1,12 @@ +with Pkg; + +procedure Test_Pkg is +begin + if Pkg.Foo (1, True) /= 1 then + raise Program_Error; + end if; +end Test_Pkg; + +--# pkg.ads +-- +-- /expr/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/sanity/param_aspects/test.py b/testsuite/tests/Ada2022/sanity/param_aspects/test.py new file mode 100644 index 000000000..0310ec10c --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/param_aspects/test.py @@ -0,0 +1,15 @@ +""" +Sanity test checking that there are no crashes in gnatcov when processing +sources containing aspects attached to subprograms formal parameters. + +As the only aspect that can be attached to a formal subprogram parameter +supported by GNAT is Unreferenced, which accepts no argument, we currently +have no way of testing a hypothetical instrumentation of this kind of aspect. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() From 1b520844819744b36a05115d693cf7b611f1a158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 6 Apr 2023 11:15:15 +0200 Subject: [PATCH 0255/1483] Ada 2022: Add sanity test for default subtypes for generic formal types The default subtype indication in generic formal types may only be a subtype mark, i.e. a type name, so there is nothing to instrument as this constructs cannot yield coverage obligations. Add a simple test to ensure gnatcov does not crash in the presence of such constructs. --- .../sanity/dft-generic-subtype/src/gen_ident.adb | 6 ++++++ .../sanity/dft-generic-subtype/src/gen_ident.ads | 5 +++++ .../Ada2022/sanity/dft-generic-subtype/src/pkg.ads | 9 +++++++++ .../sanity/dft-generic-subtype/src/test_pkg.adb | 12 ++++++++++++ .../tests/Ada2022/sanity/dft-generic-subtype/test.py | 12 ++++++++++++ 5 files changed, 44 insertions(+) create mode 100644 testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.adb create mode 100644 testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.ads create mode 100644 testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/pkg.ads create mode 100644 testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/test_pkg.adb create mode 100644 testsuite/tests/Ada2022/sanity/dft-generic-subtype/test.py diff --git a/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.adb b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.adb new file mode 100644 index 000000000..bc92010dc --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.adb @@ -0,0 +1,6 @@ +pragma Ada_2022; + +function Gen_Ident (X : T) return T is +begin + return X; -- # ret +end Gen_Ident; diff --git a/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.ads b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.ads new file mode 100644 index 000000000..76228558a --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/gen_ident.ads @@ -0,0 +1,5 @@ +pragma Ada_2022; + +generic + type T is private or use Boolean; +function Gen_Ident (X : T) return T; diff --git a/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/pkg.ads b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/pkg.ads new file mode 100644 index 000000000..cf33136bb --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/pkg.ads @@ -0,0 +1,9 @@ +pragma Ada_2022; + +with Gen_Ident; + +package Pkg is + + function Default_Ident is new Gen_Ident; + +end Pkg; diff --git a/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/test_pkg.adb b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/test_pkg.adb new file mode 100644 index 000000000..0999e03e0 --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/src/test_pkg.adb @@ -0,0 +1,12 @@ +with Pkg; + +procedure Test_Pkg is +begin + if Pkg.Default_Ident (False) then + raise Program_Error; + end if; +end Test_Pkg; + +--# gen_ident.adb +-- +-- /ret/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/sanity/dft-generic-subtype/test.py b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/test.py new file mode 100644 index 000000000..9d8b420e5 --- /dev/null +++ b/testsuite/tests/Ada2022/sanity/dft-generic-subtype/test.py @@ -0,0 +1,12 @@ +""" +Sanity test to ensure gnatcov does not crash when instrumenting code +containing a default subtype mark for a generic formal type. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() From 3b14c6b112e9404388b9c699bff0d7461a33bc4c Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Sun, 9 Apr 2023 07:00:44 +0000 Subject: [PATCH 0256/1483] Introduce use of conf.gpr for libsupport parameters To robustify the consistency of the libsupport parameters used at build time and then at use time, this change arranges to convey the most important parameters through a "conf.gpr" project file instead of external variables. conf.gpr is generated at build time by Makefile.libsupport, instantiated from conf-template.gpr. --- testsuite/SUITE/context.py | 4 +-- .../examples/aunit_variant/aunit_variant.gpr | 4 +-- .../examples/aunit_variant/harness.gpr | 6 ++-- .../examples/branch_traces/branch_traces.gpr | 4 +-- .../mcdc_checkpoints/mcdc_checkpoints.gpr | 4 +-- .../examples/support/Makefile.libsupport | 34 ++++++++++-------- tools/gnatcov/examples/support/README.md | 8 ++++- tools/gnatcov/examples/support/common.gpr | 3 -- .../examples/support/conf-template.gpr | 8 +++++ tools/gnatcov/examples/support/libsupport.gpr | 35 ++++++++----------- tools/gnatcov/examples/xml/xml.gpr | 4 +-- 11 files changed, 61 insertions(+), 53 deletions(-) create mode 100644 tools/gnatcov/examples/support/conf-template.gpr diff --git a/testsuite/SUITE/context.py b/testsuite/SUITE/context.py index f13fa2161..b663e3a70 100644 --- a/testsuite/SUITE/context.py +++ b/testsuite/SUITE/context.py @@ -176,10 +176,8 @@ def __init__(self): # gprconfig base, selecting runtime '--config=%s' % os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR)] - self.gprvaroptions = ['-XTARGET=%s' % env.target.triplet] - if self.options.board: - self.gprvaroptions.append('-XBOARD=%s' % self.options.board) + self.gprvaroptions = [] # Workaround a desynchronization between default build configuration # for TMS570 and GNATemulator's settings: see O519-032. We may get rid diff --git a/tools/gnatcov/examples/aunit_variant/aunit_variant.gpr b/tools/gnatcov/examples/aunit_variant/aunit_variant.gpr index ca8cd2d44..4253c8923 100644 --- a/tools/gnatcov/examples/aunit_variant/aunit_variant.gpr +++ b/tools/gnatcov/examples/aunit_variant/aunit_variant.gpr @@ -1,7 +1,7 @@ -with "common.gpr"; +with "conf.gpr"; project Aunit_variant extends "base" is for Source_Dirs use ("src"); - for Object_Dir use "obj/" & Common.Target; + for Object_Dir use "obj/" & Conf.Target; end Aunit_variant; diff --git a/tools/gnatcov/examples/aunit_variant/harness.gpr b/tools/gnatcov/examples/aunit_variant/harness.gpr index 482667f5b..e08a511af 100644 --- a/tools/gnatcov/examples/aunit_variant/harness.gpr +++ b/tools/gnatcov/examples/aunit_variant/harness.gpr @@ -1,4 +1,4 @@ -with "common"; +with "conf"; with "aunit"; with "explore"; @@ -7,8 +7,8 @@ project Harness is for Languages use ("Ada"); for Main use ("test_explore.adb"); for Source_Dirs use ("harness/fixture", "harness/tests"); - for Object_Dir use "obj/" & Common.Target & "/harness"; - for Exec_Dir use "obj/" & Common.Target; + for Object_Dir use "obj/" & Conf.Target & "/harness"; + for Exec_Dir use "obj/" & Conf.Target; end Harness; diff --git a/tools/gnatcov/examples/branch_traces/branch_traces.gpr b/tools/gnatcov/examples/branch_traces/branch_traces.gpr index 9bce7edf7..17312aa2b 100644 --- a/tools/gnatcov/examples/branch_traces/branch_traces.gpr +++ b/tools/gnatcov/examples/branch_traces/branch_traces.gpr @@ -1,6 +1,6 @@ -with "common.gpr"; +with "conf.gpr"; project branch_traces extends "base" is for Source_Dirs use ("src"); - for Object_Dir use "obj/" & Common.Target; + for Object_Dir use "obj/" & Conf.Target; end branch_traces; diff --git a/tools/gnatcov/examples/mcdc_checkpoints/mcdc_checkpoints.gpr b/tools/gnatcov/examples/mcdc_checkpoints/mcdc_checkpoints.gpr index 97f95e87f..9137e3a02 100644 --- a/tools/gnatcov/examples/mcdc_checkpoints/mcdc_checkpoints.gpr +++ b/tools/gnatcov/examples/mcdc_checkpoints/mcdc_checkpoints.gpr @@ -1,6 +1,6 @@ -with "common.gpr"; +with "conf.gpr"; project MCDC_checkpoints extends "base" is for Source_Dirs use ("src"); - for Object_Dir use "obj/" & Common.Target; + for Object_Dir use "obj/" & Conf.Target; end MCDC_checkpoints; diff --git a/tools/gnatcov/examples/support/Makefile.libsupport b/tools/gnatcov/examples/support/Makefile.libsupport index 8e6b842a5..57e0db3a0 100644 --- a/tools/gnatcov/examples/support/Makefile.libsupport +++ b/tools/gnatcov/examples/support/Makefile.libsupport @@ -1,21 +1,26 @@ -# Simple makefile for building the zfp support library. +# Simple makefile for building the support library for tests and examples. include Makefile.common # Tailored compilation options for libsupport. Allow source -# coverage analysis by default, useful for testsuite at least: +# coverage analysis with binary traces by default. LIBSUPPORT_CFLAGS=-fdump-scos -fpreserve-control-flow -g -# Whether we want to have visibility on extra source directories for cross -# configurations. No way to achieve this from the project file by looking just -# at the value of "Target" in a manner compatible with old versions of -# gprbuild (typically for our 7.0.2 based runs): -USE_TARGET_SOURCE_DIRS = $(strip $(if $(TARGET), yes, no)) +all: $(SUPPORT_TARGET_SRC_DIR) $(LIBSUPPORT_DIR) LIBSUPPORT -LIBSUPPORT_ARCHIVE = $(LIBSUPPORT_DIR)/libsupport.a +# ---------------------------------------------------------------------------- -all: $(SUPPORT_TARGET_SRC_DIR) $(LIBSUPPORT_DIR) $(LIBSUPPORT_ARCHIVE) +# To provide a single spot of control shared between build time and use time, +# latch the libsupport configuration parameters as a set of variables in a +# "conf.gpr" project file rather than have them controlled with externals. + +conf.gpr: force + sed -e 's/%TARGET%/$(TARGET)/g' \ + -e 's/%BOARD%/$(BOARD)/g' \ + < conf-template.gpr > $@ + +# ---------------------------------------------------------------------------- # In addition to the library where the constructed library should go, make # sure the target specific support source dir exists. It might legitimately @@ -25,15 +30,14 @@ all: $(SUPPORT_TARGET_SRC_DIR) $(LIBSUPPORT_DIR) $(LIBSUPPORT_ARCHIVE) $(SUPPORT_TARGET_SRC_DIR) $(LIBSUPPORT_DIR): mkdir -p $@ -$(LIBSUPPORT_ARCHIVE): force - $(BUILDER) -XLIBSUPPORT_BUILD=yes -p -Plibsupport -f \ - -XUSE_TARGET_SOURCE_DIRS=$(USE_TARGET_SOURCE_DIRS) \ +LIBSUPPORT: conf.gpr force + $(BUILDER) -XLIBSUPPORT_BUILD=yes -p -Plibsupport.gpr -f \ -cargs $(LIBSUPPORT_CFLAGS) - $(BUILDER) -XLIBSUPPORT_BUILD=yes -p -Plibsupport -XUNITTEST=yes \ - -XUSE_TARGET_SOURCE_DIRS=$(USE_TARGET_SOURCE_DIRS) \ + $(BUILDER) -XLIBSUPPORT_BUILD=yes -p -Plibsupport.gpr -f \ + -XUNITTEST=yes \ -cargs $(LIBSUPPORT_CFLAGS) clean: $(RM) -rf lib obj -.PHONY: force clean +.PHONY: force clean LIBSUPPORT diff --git a/tools/gnatcov/examples/support/README.md b/tools/gnatcov/examples/support/README.md index d948dbe22..e45043729 100644 --- a/tools/gnatcov/examples/support/README.md +++ b/tools/gnatcov/examples/support/README.md @@ -24,7 +24,7 @@ General organization The facilities in this directory include a number of GNAT project files and Makefiles: -* `common.gpr`: project file with common definitions for... +* `common.gpr`: project file with common definitions * `libsupport.gpr`: project file for both build and use of the support library itself and @@ -32,9 +32,15 @@ Makefiles: * `base.gpr`: project file to be extended by each example project file, to inherit a number of common attributes. +Configuration parameters are latched in a `conf.gpr` project file at +build time, allowing use without having to re-specify all the values +through scenario variables afterwards. `conf.gpr` is generated from a +`conf-template.gpr` file by substituting patterns with actual values. + The general GPR hierarchy is as follows: : common.gpr + : conf.gpr <-- conf-template.gpr : w w : | | support/ : | libsupport.gpr (With common) diff --git a/tools/gnatcov/examples/support/common.gpr b/tools/gnatcov/examples/support/common.gpr index 8d9256313..ec0680d85 100644 --- a/tools/gnatcov/examples/support/common.gpr +++ b/tools/gnatcov/examples/support/common.gpr @@ -7,8 +7,5 @@ abstract project Common is type Yes_No_Type is ("yes", "no"); for Languages use (); - Target := external ("TARGET", ""); - Board := external ("BOARD", ""); - end Common; diff --git a/tools/gnatcov/examples/support/conf-template.gpr b/tools/gnatcov/examples/support/conf-template.gpr new file mode 100644 index 000000000..aa0dbb29f --- /dev/null +++ b/tools/gnatcov/examples/support/conf-template.gpr @@ -0,0 +1,8 @@ +-- Libsupport configuration parameters + +abstract project Conf is + + Target := "%TARGET%"; + Board := "%BOARD%"; + +end Conf; diff --git a/tools/gnatcov/examples/support/libsupport.gpr b/tools/gnatcov/examples/support/libsupport.gpr index f1ffddf78..5c108130d 100644 --- a/tools/gnatcov/examples/support/libsupport.gpr +++ b/tools/gnatcov/examples/support/libsupport.gpr @@ -3,7 +3,7 @@ -- == with startup/init and minimum IO services == -- ================================================================= -with "common"; +with "common.gpr", "conf.gpr"; library project Libsupport is @@ -15,15 +15,6 @@ library project Libsupport is -- Whether we are building/using for an Aunit context or not, with -- influence on the last_chance handler inclusion. - Use_Target_Source_Dirs : Common.Yes_No_Type - := external ("USE_TARGET_SOURCE_DIRS", "no"); - -- Whether we are building/using for an Aunit context or not, with - -- influence on the last_chance handler inclusion. - - Source_Dirs := ("src"); - -- Variable where we compute the Source_Dirs attribute to use, - -- depending on the target, the board, and on the use of Aunit. - -- Common library attributes: -- ========================== @@ -31,8 +22,8 @@ library project Libsupport is for Library_Auto_Init use "False"; for Languages use ("Ada", "C"); - for Library_Dir use "lib/" & Common.Target; - for Object_Dir use "obj/" & Common.Target; + for Library_Dir use "lib/" & Conf.Target; + for Object_Dir use "obj/" & Conf.Target; -- We might have needs for both aunit and !aunit libs for a run -- so pick a different libname for each case: @@ -49,16 +40,19 @@ library project Libsupport is when "yes" => for Externally_Built use "false"; end case; - case Use_Target_Source_Dirs is - when "no" => null; + -- Now compute the set of source directories to use. A common one, + -- always, then an additional Target specific one. FOR SELDOM USES + -- ONLY. We don't wan't yet another zfp support approx here: - when "yes" => - -- Now compute the set of source directories to use. A common one, - -- always, then an additional Target specific one. FOR SELDOM USES - -- ONLY. We don't wan't yet another zfp support approx here: + Source_Dirs := ("src"); + + case Conf.Target is + when "" => null; + + when others => Source_Dirs := Source_Dirs & ("src/memory"); - Source_Dirs := Source_Dirs & ("src/" & Common.Target); + Source_Dirs := Source_Dirs & ("src/" & Conf.Target); -- Add whatever we need to find our Last Chance Handler, to -- force termination even in ravenscar configurations, and to @@ -73,7 +67,8 @@ library project Libsupport is -- that the target RTS might not support. Allow board specific -- overrides of the last chance handler: - Source_Dirs := Source_Dirs & ("src/last_chance_" & Common.Board); + Source_Dirs := Source_Dirs & + ("src/last_chance_" & Conf.Board); end case; end case; diff --git a/tools/gnatcov/examples/xml/xml.gpr b/tools/gnatcov/examples/xml/xml.gpr index 43f18adfb..1ba92ee3c 100644 --- a/tools/gnatcov/examples/xml/xml.gpr +++ b/tools/gnatcov/examples/xml/xml.gpr @@ -1,6 +1,6 @@ -with "common.gpr"; +with "conf.gpr"; project XML extends "base" is for Source_Dirs use ("src"); - for Object_Dir use "obj/" & Common.Target; + for Object_Dir use "obj/" & Conf.Target; end XML; From 5005d28eb311aed1aea4c14929ee9b128b4939a3 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Tue, 4 Apr 2023 03:46:06 -0700 Subject: [PATCH 0257/1483] Move common support subprograms to libsupport Preparatory cleanup for a followup change that will introduce two variants of our silent_last_chance handler, resorting to either exit(0) or abort. This change - Moves the units provided by Qualif/Ada/src to libsupport (support.ad?, silent_last_chance.ad?, simple_pools.ad?) - Arranges to build and use libsupport in all configurations (testsuite.py + gprfor) - Removes copies or minor variants of such units spread throughout the testbase, - Removes "support" from the list of units explicitly excluded in tests with projects that don't have the unit in their sources any more, - Adjusts a few "support.h" files to match what libsupport exports (support.h could be moved to libsupport as well, but this is prevented by issue gnatcoverage#31) The Silent_Last_Chance unit is provided through a separate project, which allows better control of the relevant object file at link time. Note that we have the Appendix/Testsuite/Selftest/assert-failure test to verify that the testsuite correctly detects tests that terminate on unhandled exceptions unexpectedly. --- .../Testsuite/Selftest/src/support.adb | 20 -------- .../Testsuite/Selftest/src/support.ads | 6 --- testsuite/Qualif/C/src/support.adb | 10 ---- testsuite/Qualif/C/src/support.ads | 4 -- testsuite/Qualif/C/src/support.h | 3 -- .../Qualif/Common/Report/src/support.adb | 20 -------- .../Qualif/Common/Report/src/support.ads | 6 --- .../GPR/ByAttr/GlobUnits/test.py | 2 +- .../GPR/ByAttr/ListOut/test.py | 2 +- .../UnitsOfInterest/GPR/ByAttr/MixOut/test.py | 2 +- .../GPR/ByAttr/UnitsOut/test.py | 2 +- testsuite/Qualif/Common/src/support.adb | 8 ---- testsuite/Qualif/Common/src/support.ads | 3 -- testsuite/SUITE/control.py | 25 +--------- testsuite/SUITE/tutils.py | 32 ++++++++++--- testsuite/tests/ignored-c-header/identity.c | 2 +- testsuite/tests/ignored-c-header/test.c | 4 +- testsuite/testsuite.py | 47 ++++++++++++------- .../examples/support/Makefile.libsupport | 8 +++- tools/gnatcov/examples/support/README.md | 44 ++++++++++++----- tools/gnatcov/examples/support/base.gpr | 2 +- tools/gnatcov/examples/support/lch.gpr | 25 ++++++++++ .../support/lch}/silent_last_chance.adb | 6 +-- .../support/lch}/silent_last_chance.ads | 0 tools/gnatcov/examples/support/libsupport.gpr | 4 +- .../support/src/helpers}/simple_pools.adb | 0 .../support/src/helpers}/simple_pools.ads | 0 .../examples/support/src/helpers}/support.adb | 0 .../examples/support/src/helpers}/support.ads | 11 +++++ 29 files changed, 141 insertions(+), 157 deletions(-) delete mode 100644 testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.adb delete mode 100644 testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.ads delete mode 100644 testsuite/Qualif/C/src/support.adb delete mode 100644 testsuite/Qualif/C/src/support.ads delete mode 100644 testsuite/Qualif/Common/Report/src/support.adb delete mode 100644 testsuite/Qualif/Common/Report/src/support.ads delete mode 100644 testsuite/Qualif/Common/src/support.adb delete mode 100644 testsuite/Qualif/Common/src/support.ads create mode 100644 tools/gnatcov/examples/support/lch.gpr rename {testsuite/Qualif/Ada/src => tools/gnatcov/examples/support/lch}/silent_last_chance.adb (71%) rename {testsuite/Qualif/Ada/src => tools/gnatcov/examples/support/lch}/silent_last_chance.ads (100%) rename {testsuite/Qualif/Ada/src => tools/gnatcov/examples/support/src/helpers}/simple_pools.adb (100%) rename {testsuite/Qualif/Ada/src => tools/gnatcov/examples/support/src/helpers}/simple_pools.ads (100%) rename {testsuite/Qualif/Ada/src => tools/gnatcov/examples/support/src/helpers}/support.adb (100%) rename {testsuite/Qualif/Ada/src => tools/gnatcov/examples/support/src/helpers}/support.ads (51%) diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.adb b/testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.adb deleted file mode 100644 index e7e059c05..000000000 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.adb +++ /dev/null @@ -1,20 +0,0 @@ - -package body Support is - - procedure Assert (Cond : Boolean) is - begin - if not Cond then - raise Program_Error; - end if; - end; - - function Identity (X : Integer) return Integer is - begin - return X; - end; - - function Identity (B : Boolean) return Boolean is - begin - return B; - end; -end; diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.ads b/testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.ads deleted file mode 100644 index f7482f2e1..000000000 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/src/support.ads +++ /dev/null @@ -1,6 +0,0 @@ - -package Support is - procedure Assert (Cond : Boolean); - function Identity (X : Integer) return Integer; - function Identity (B : Boolean) return Boolean; -end; diff --git a/testsuite/Qualif/C/src/support.adb b/testsuite/Qualif/C/src/support.adb deleted file mode 100644 index 06edf576c..000000000 --- a/testsuite/Qualif/C/src/support.adb +++ /dev/null @@ -1,10 +0,0 @@ -package body Support is - - procedure Assert (Cond : Boolean) is - begin - if not Cond then - raise Program_Error; - end if; - end; - -end; diff --git a/testsuite/Qualif/C/src/support.ads b/testsuite/Qualif/C/src/support.ads deleted file mode 100644 index 69581ba52..000000000 --- a/testsuite/Qualif/C/src/support.ads +++ /dev/null @@ -1,4 +0,0 @@ -package Support is - procedure Assert (Cond : Boolean); - Pragma Export(C, Assert, "assert"); -end; diff --git a/testsuite/Qualif/C/src/support.h b/testsuite/Qualif/C/src/support.h index 73c084827..7e2983e28 100644 --- a/testsuite/Qualif/C/src/support.h +++ b/testsuite/Qualif/C/src/support.h @@ -8,7 +8,4 @@ extern void assert (char cond); -extern int -identity (char value); - #endif diff --git a/testsuite/Qualif/Common/Report/src/support.adb b/testsuite/Qualif/Common/Report/src/support.adb deleted file mode 100644 index e7e059c05..000000000 --- a/testsuite/Qualif/Common/Report/src/support.adb +++ /dev/null @@ -1,20 +0,0 @@ - -package body Support is - - procedure Assert (Cond : Boolean) is - begin - if not Cond then - raise Program_Error; - end if; - end; - - function Identity (X : Integer) return Integer is - begin - return X; - end; - - function Identity (B : Boolean) return Boolean is - begin - return B; - end; -end; diff --git a/testsuite/Qualif/Common/Report/src/support.ads b/testsuite/Qualif/Common/Report/src/support.ads deleted file mode 100644 index f7482f2e1..000000000 --- a/testsuite/Qualif/Common/Report/src/support.ads +++ /dev/null @@ -1,6 +0,0 @@ - -package Support is - procedure Assert (Cond : Boolean); - function Identity (X : Integer) return Integer; - function Identity (B : Boolean) return Boolean; -end; diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py index 9c2c55968..8c3f8f1a2 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py @@ -13,7 +13,7 @@ wd.to_subdir('wd_2') TestCase(category=None).run(covcontrol=CovControl( - units_out=['test*', 'support'], + units_out=['test*'], xreports=['ops.ads', 'ops.adb', 'ops-andthen.adb', 'ops-orelse.adb'])) wd.to_subdir('wd_3') diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py index c3cebaf70..4331b3bc5 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py @@ -3,7 +3,7 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, list_to_file -base_out = ["support", "test_or_ft", "test_and_tt", "test_and_tf"] +base_out = ["test_or_ft", "test_and_tt", "test_and_tf"] wd = Wdir() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py index dafdda2f3..46b580b9a 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py @@ -5,7 +5,7 @@ # Mixing units and lists to exclude -base_out = ["support", "test_or_ft", "test_and_tt", "test_and_tf"] +base_out = ["test_or_ft", "test_and_tt", "test_and_tf"] wd = Wdir() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py index cabb34f9b..5ba1f9d9f 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py @@ -4,7 +4,7 @@ from SUITE.cutils import Wdir -base_out = ['support', 'test_or_ft', 'test_and_tt', 'test_and_tf'] +base_out = ['test_or_ft', 'test_and_tt', 'test_and_tf'] wd = Wdir() # Check on lone node unit only diff --git a/testsuite/Qualif/Common/src/support.adb b/testsuite/Qualif/Common/src/support.adb deleted file mode 100644 index 624900713..000000000 --- a/testsuite/Qualif/Common/src/support.adb +++ /dev/null @@ -1,8 +0,0 @@ -package body Support is - procedure Assert (T : Boolean) is - begin - if not T then - raise Program_Error; - end if; - end; -end; diff --git a/testsuite/Qualif/Common/src/support.ads b/testsuite/Qualif/Common/src/support.ads deleted file mode 100644 index 15de51aa4..000000000 --- a/testsuite/Qualif/Common/src/support.ads +++ /dev/null @@ -1,3 +0,0 @@ -package Support is - procedure Assert (T : Boolean); -end; diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index a86afbbf9..7c6e63206 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -260,29 +260,6 @@ def __init__(self, runtime_name=None): else: assert False, 'Unknown runtime: {}'.format(runtime_name) - @property - def need_libsupport(self): - """Libsupport considerations. - - We rely on our support lib to provide a common last chance handler in - every configuration where this makes sense, in particular with light and - Ravenscar RTS libraries. - - * Light profiles because some of these don't provide a handler at all. - - * Ravenscar because some handlers fallthrough to a infinite idle loop, - unfriendly wrt testcase termination in automated nightly executions. - - In addition, providing our last chance handler ensures we get - consistent output on unexpected exception, on any target configuration. - - We can't override "last chance" handling and don't really need to for - full runtimes (which terminate on exceptions), native or cross. - - This function controls whether we build the library and link with it. - """ - return self.has_ravenscar_runtime or self.has_light_runtime - @property def gnatcov_rts_project(self): """Name of the gnatcov_rts project to use in instrumented projects.""" @@ -547,4 +524,4 @@ def add_shared_options_to(parser, toplevel): '--default-dump-channel', dest='default_dump_channel', help='Default dump channel to be passed to "gnatcov instrument,"' ' unless the test specifically overrides it.' - ) \ No newline at end of file + ) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index a420dabdf..e2e60ae5a 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -281,7 +281,7 @@ def gpr_emulator_package(): def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", - main_cargs=None, langs=None, deps=(), scenario_extra="", + main_cargs=None, langs=None, deps=None, scenario_extra="", compiler_extra="", extra=""): """ Generate a simple PRJID.gpr project file to build executables for each main @@ -293,7 +293,6 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", EXTRA, if any, at the end of the project file contents. Return the gpr file name. """ - deps = '\n'.join('with "%s";' % dep for dep in deps) mains = to_list(mains) srcdirs = to_list(srcdirs) @@ -326,11 +325,30 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", srcdirs = ', '.join('"%s"' % d for d in srcdirs_list) languages = ', '.join('"%s"' % lang for lang in langs) - # The base project file we need to extend, and the way to refer to it - # from the project contents. This provides a default last chance handler - # on which we rely to detect termination on exception occurrence. - basegpr = (("%s/support/base" % ROOT_DIR) - if RUNTIME_INFO.need_libsupport else None) + # In addition to the provided dependencies, figure out if this project + # should extend or with some support or helper facilities. These are + # designed with projects for test *programs* in mind, not for libraries, + # and would actually be plain incompatible with shared Library projects. + for_library = "Library" in extra + + # The base project file we need to extend, which drags libsupport, + # and the way to refer to it from the project contents. + basegpr = ( + "{}/support/base.gpr".format(ROOT_DIR) if not for_library else None) + + # For projects with an Ada main, provide visibility on the alternative + # last chance handlers. Restricting this to Ada mains ensures that the + # dedicated object file for a given handler only gets included in the + # closure if the program requests the corresponding unit explicitly via + # a "with" clause, e.g. "with Silent_Last_Chance;". + # + # Account for callers that expect the "deps" argument they provide to + # remain unmodified, or which provide a tuple on input (unmutable). + deps = list(deps) if deps else [] + if not for_library and ".adb" in gprmains: + deps.append("{}/support/lch.gpr".format(ROOT_DIR)) + + deps = '\n'.join('with "%s";' % dep for dep in deps) # If we have specific flags for the mains, append them. This is # typically something like: diff --git a/testsuite/tests/ignored-c-header/identity.c b/testsuite/tests/ignored-c-header/identity.c index 171abe411..e10714ed4 100644 --- a/testsuite/tests/ignored-c-header/identity.c +++ b/testsuite/tests/ignored-c-header/identity.c @@ -1,7 +1,7 @@ #include "identity.h" int -identity (int n) +id (int n) { return static_identity (n); } diff --git a/testsuite/tests/ignored-c-header/test.c b/testsuite/tests/ignored-c-header/test.c index b56d92982..4878ddf27 100644 --- a/testsuite/tests/ignored-c-header/test.c +++ b/testsuite/tests/ignored-c-header/test.c @@ -1,10 +1,10 @@ #include "twice.h" -extern int identity (int n); +extern int id (int n); int main () { - int n = identity (twice (2)); + int n = id (twice (2)); return 0; } diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 5fe6d21ef..64a9acb47 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1087,6 +1087,35 @@ def tool(self, name): else: return name + + def _build_libsupport(self): + + args = self.main.args + + libsup_vars = [] + + if args.target: + libsup_vars.append("TARGET={}".format(args.target)) + + if args.board: + libsup_vars.append("BOARD={}".format(args.board)) + + if args.RTS: + libsup_vars.append("RTS={}".format(args.RTS)) + + logfile = os.path.join(self.output_dir, 'build_support.out') + + p = Run(['make', '--debug', '-C', 'support', '-f', 'Makefile.libsupport'] + + libsup_vars, + output=logfile) + + if p.status != 0: + raise FatalError( + ("Problem during libsupport construction. %s:\n" % + logfile) + + contents_of(logfile)) + + def set_up(self): """ Prepare the testsuite run: compute and dump discriminants, run @@ -1204,23 +1233,7 @@ def set_up(self): # Build support library as needed - if control.runtime_info().need_libsupport: - - targetargs = ["TARGET=%s" % self.env.target.triplet] - if self.main.args.board: - targetargs.append("BOARD=%s" % self.main.args.board) - - logfile = os.path.join(self.output_dir, 'build_support.out') - - p = Run(['make', '-C', 'support', '-f', 'Makefile.libsupport'] + - targetargs + ["RTS=%s" % self.main.args.RTS], - output=logfile) - - if p.status != 0: - raise FatalError( - ("Problem during libsupport construction. %s:\n" % - logfile) + - contents_of(logfile)) + self._build_libsupport() # Initialize counter of consecutive failures, to stop the run # when it is visibly useless to keep going. diff --git a/tools/gnatcov/examples/support/Makefile.libsupport b/tools/gnatcov/examples/support/Makefile.libsupport index 57e0db3a0..e565de9d9 100644 --- a/tools/gnatcov/examples/support/Makefile.libsupport +++ b/tools/gnatcov/examples/support/Makefile.libsupport @@ -7,7 +7,7 @@ include Makefile.common LIBSUPPORT_CFLAGS=-fdump-scos -fpreserve-control-flow -g -all: $(SUPPORT_TARGET_SRC_DIR) $(LIBSUPPORT_DIR) LIBSUPPORT +all: $(SUPPORT_TARGET_SRC_DIR) $(LIBSUPPORT_DIR) LIBSUPPORT LCH # ---------------------------------------------------------------------------- @@ -37,7 +37,11 @@ LIBSUPPORT: conf.gpr force -XUNITTEST=yes \ -cargs $(LIBSUPPORT_CFLAGS) +LCH: conf.gpr force + $(BUILDER) -XLIBSUPPORT_BUILD=yes -p -Plch.gpr -f \ + -cargs $(LIBSUPPORT_CFLAGS) + clean: $(RM) -rf lib obj -.PHONY: force clean LIBSUPPORT +.PHONY: force clean LIBSUPPORT LCH diff --git a/tools/gnatcov/examples/support/README.md b/tools/gnatcov/examples/support/README.md index e45043729..67ae0f27e 100644 --- a/tools/gnatcov/examples/support/README.md +++ b/tools/gnatcov/examples/support/README.md @@ -5,18 +5,38 @@ This directory features a number of facilities to help automated build, execution and cov analysis of simple examples for several possible Qemu targets. -It also provides an internal "support" library, which offers a custom -exception last-chance handler to all the examples and testsuites. The common -last chance handler always outputs the same message and terminates the -program. This... - -* facilitates the execution of automated tests in batch mode (compared, for - example, to the handler in some Ravenscar libraries which just leave the - program running idle forever), and - -* provides an easy way to identify abornmal termination, with a stable output - whatever the RTS in use. - +It provides an internal "support" library, which offers + +* A set of common helpers for test programs, such as an "Assert" procedure + and a set of "Identity" functions, some of which implemented in Ada and + exposed to C with straight symbol names to accommodate legacy uses. + +* For cross configurations, a custom exception last-chance handler to all + the examples and testsuites, which always outputs the same message and + terminates the program. + + This facilitates the execution of automated tests in batch mode (compared, + for example, to the handler in some Ravenscar libraries which just leave the + program running idle forever), and provides an easy way to identify abornmal + termination, with a stable output whatever the RTS in use. + +* For cross configurations, a set of common memory oriented subprograms to + compensate their possible absence in some environments with very restricted + GNAT runtimes. + +The directory also offers, through an separate project file, an alernative +last_chance_handler which terminates a program silently without signalling an +error condition. This is useful for tests intended to verify the behavior +of the tool in situations where an unhandled exception occurs. + +This separate project is provided aside from the support library as a +non-library project to make sure that the alternative last chance +handler symbol gets incorporated in the link closure reliably with a +standalone object file. + +Both projects are built once early and then reused as Externally_Built +afterwards, possibly concurrently when the testsuite executes tests in +parallel. General organization -------------------- diff --git a/tools/gnatcov/examples/support/base.gpr b/tools/gnatcov/examples/support/base.gpr index aacb88021..858019292 100644 --- a/tools/gnatcov/examples/support/base.gpr +++ b/tools/gnatcov/examples/support/base.gpr @@ -2,7 +2,7 @@ -- == Base GPR file to be extended by example GPRs == -- ================================================== -with "common", "libsupport"; +with "common.gpr", "libsupport.gpr"; abstract project Base is diff --git a/tools/gnatcov/examples/support/lch.gpr b/tools/gnatcov/examples/support/lch.gpr new file mode 100644 index 000000000..448172e0a --- /dev/null +++ b/tools/gnatcov/examples/support/lch.gpr @@ -0,0 +1,25 @@ + +with "common.gpr", "conf.gpr"; + +project LCH is + + Do_Build : Common.Yes_No_Type := external ("LIBSUPPORT_BUILD", "no"); + -- Whether we're using this file to build the library or to link + -- with it. + + case Do_Build is + when "no" => for Externally_Built use "true"; + when "yes" => for Externally_Built use "false"; + end case; + + for Source_Dirs use ("lch"); + + -- Make sure recursive project file inclusions don't get + -- to produce reports for parts of this support lib, never + -- relevant to test results. + + package Coverage is + for Units use (); + end Coverage; + +end LCH; diff --git a/testsuite/Qualif/Ada/src/silent_last_chance.adb b/tools/gnatcov/examples/support/lch/silent_last_chance.adb similarity index 71% rename from testsuite/Qualif/Ada/src/silent_last_chance.adb rename to tools/gnatcov/examples/support/lch/silent_last_chance.adb index ed072d934..b863a29d1 100644 --- a/testsuite/Qualif/Ada/src/silent_last_chance.adb +++ b/tools/gnatcov/examples/support/lch/silent_last_chance.adb @@ -1,14 +1,10 @@ package body Silent_Last_Chance is -- Use exit(0) to terminate silently with a status code - -- indicating success. Abort would result in an error status - -- and _exit would bypass the atexit handlers, crucial to + -- indicating success and run atexit handlers, crucial to -- get meaningful traces out of instrumented programs in native -- configurations. - -- This requires dragging libc explicitly in BB configurations. - pragma Linker_Options ("-lc"); - ------------------------- -- Last_Chance_Handler -- ------------------------- diff --git a/testsuite/Qualif/Ada/src/silent_last_chance.ads b/tools/gnatcov/examples/support/lch/silent_last_chance.ads similarity index 100% rename from testsuite/Qualif/Ada/src/silent_last_chance.ads rename to tools/gnatcov/examples/support/lch/silent_last_chance.ads diff --git a/tools/gnatcov/examples/support/libsupport.gpr b/tools/gnatcov/examples/support/libsupport.gpr index 5c108130d..7c5bfb331 100644 --- a/tools/gnatcov/examples/support/libsupport.gpr +++ b/tools/gnatcov/examples/support/libsupport.gpr @@ -43,8 +43,8 @@ library project Libsupport is -- Now compute the set of source directories to use. A common one, -- always, then an additional Target specific one. FOR SELDOM USES -- ONLY. We don't wan't yet another zfp support approx here: - - Source_Dirs := ("src"); + + Source_Dirs := ("src", "src/helpers"); case Conf.Target is when "" => null; diff --git a/testsuite/Qualif/Ada/src/simple_pools.adb b/tools/gnatcov/examples/support/src/helpers/simple_pools.adb similarity index 100% rename from testsuite/Qualif/Ada/src/simple_pools.adb rename to tools/gnatcov/examples/support/src/helpers/simple_pools.adb diff --git a/testsuite/Qualif/Ada/src/simple_pools.ads b/tools/gnatcov/examples/support/src/helpers/simple_pools.ads similarity index 100% rename from testsuite/Qualif/Ada/src/simple_pools.ads rename to tools/gnatcov/examples/support/src/helpers/simple_pools.ads diff --git a/testsuite/Qualif/Ada/src/support.adb b/tools/gnatcov/examples/support/src/helpers/support.adb similarity index 100% rename from testsuite/Qualif/Ada/src/support.adb rename to tools/gnatcov/examples/support/src/helpers/support.adb diff --git a/testsuite/Qualif/Ada/src/support.ads b/tools/gnatcov/examples/support/src/helpers/support.ads similarity index 51% rename from testsuite/Qualif/Ada/src/support.ads rename to tools/gnatcov/examples/support/src/helpers/support.ads index f009ccc8c..f8a6f2972 100644 --- a/testsuite/Qualif/Ada/src/support.ads +++ b/tools/gnatcov/examples/support/src/helpers/support.ads @@ -1,7 +1,18 @@ package Support is + + -- First, common subprograms intended for either Ada or C tests. + -- "assert" offers a more uniform termination behavior for C and + -- Ada in case of failure. + procedure Assert (Cond : Boolean); function Identity (X : Integer) return Integer; + + pragma Export (C, Assert, "assert"); + pragma Export (C, Identity, "identity"); + + -- Extensions for Ada + function Identity (B : Boolean) return Boolean; function Value (X : Integer) return Integer renames Identity; From a8148544175fb0d366faf8d703f5dadbefcd9374 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Thu, 6 Apr 2023 06:21:35 -0700 Subject: [PATCH 0258/1483] Introduce exit/abort variants of the silent_last_chance_handler The use of abort() to terminate was causing trouble in native configurations as it was resulting in an error exit code from tests raising unhandled exceptions on purpose. We recently replaced it with calls to exit(0), relying on the availability of a minimum libc in all BB configurations. This caused other problems in BB environments using recent versions of newlib which now invoque IO unconditionally from exit(), resulting in undefined refs to write_r. An incidental issue was the unconditional addition of an explicit "-lc", which doesn't work on Windows. This change mitigates the issue by improving testsuite framework to feature two versions of the Silent_Last_Chance package body, one using abort() and the other using exit(0), and select a variant through a "naming" package in the generated project files. --- .../examples/support/Makefile.libsupport | 6 ++++++ .../examples/support/conf-template.gpr | 3 +++ tools/gnatcov/examples/support/lch.gpr | 4 ++++ .../support/lch/silent_last_chance-abort.adb | 21 +++++++++++++++++++ ...chance.adb => silent_last_chance-exit.adb} | 0 5 files changed, 34 insertions(+) create mode 100644 tools/gnatcov/examples/support/lch/silent_last_chance-abort.adb rename tools/gnatcov/examples/support/lch/{silent_last_chance.adb => silent_last_chance-exit.adb} (100%) diff --git a/tools/gnatcov/examples/support/Makefile.libsupport b/tools/gnatcov/examples/support/Makefile.libsupport index e565de9d9..aacaf0697 100644 --- a/tools/gnatcov/examples/support/Makefile.libsupport +++ b/tools/gnatcov/examples/support/Makefile.libsupport @@ -15,9 +15,15 @@ all: $(SUPPORT_TARGET_SRC_DIR) $(LIBSUPPORT_DIR) LIBSUPPORT LCH # latch the libsupport configuration parameters as a set of variables in a # "conf.gpr" project file rather than have them controlled with externals. +# Pick a default kind of silent last chance handler, that users of this +# Makefile can override if needed, e.g. for VxWorks kinds of configurations +# which are cross targets with "full" runtimes akin to native profiles. +SILENT_LCH = $(strip $(if $(TARGET), abort, exit)) + conf.gpr: force sed -e 's/%TARGET%/$(TARGET)/g' \ -e 's/%BOARD%/$(BOARD)/g' \ + -e 's/%SILENT_LCH%/$(SILENT_LCH)/g' \ < conf-template.gpr > $@ # ---------------------------------------------------------------------------- diff --git a/tools/gnatcov/examples/support/conf-template.gpr b/tools/gnatcov/examples/support/conf-template.gpr index aa0dbb29f..54b8045e9 100644 --- a/tools/gnatcov/examples/support/conf-template.gpr +++ b/tools/gnatcov/examples/support/conf-template.gpr @@ -5,4 +5,7 @@ abstract project Conf is Target := "%TARGET%"; Board := "%BOARD%"; + Silent_LCH := "%SILENT_LCH%"; + -- Filename suffix of the silent_last_chance package body to use. + end Conf; diff --git a/tools/gnatcov/examples/support/lch.gpr b/tools/gnatcov/examples/support/lch.gpr index 448172e0a..e7978b816 100644 --- a/tools/gnatcov/examples/support/lch.gpr +++ b/tools/gnatcov/examples/support/lch.gpr @@ -22,4 +22,8 @@ project LCH is for Units use (); end Coverage; + package Naming is + for Body ("Silent_Last_Chance") use + "silent_last_chance-" & Conf.Silent_Lch & ".adb"; + end Naming; end LCH; diff --git a/tools/gnatcov/examples/support/lch/silent_last_chance-abort.adb b/tools/gnatcov/examples/support/lch/silent_last_chance-abort.adb new file mode 100644 index 000000000..879bdfb77 --- /dev/null +++ b/tools/gnatcov/examples/support/lch/silent_last_chance-abort.adb @@ -0,0 +1,21 @@ +package body Silent_Last_Chance is + + -- Use abort() to terminate silently and expect this won't + -- trigger an error exit code out of whatever executes the + -- code. + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + + procedure C_Abort; + pragma Import (C, C_abort, "abort"); + pragma No_Return (C_abort); + begin + C_abort; + end Last_Chance_Handler; + +end; diff --git a/tools/gnatcov/examples/support/lch/silent_last_chance.adb b/tools/gnatcov/examples/support/lch/silent_last_chance-exit.adb similarity index 100% rename from tools/gnatcov/examples/support/lch/silent_last_chance.adb rename to tools/gnatcov/examples/support/lch/silent_last_chance-exit.adb From 048ecd0a1526ecbd8895d4730fada46f537cb2a8 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Tue, 11 Apr 2023 16:58:14 +0000 Subject: [PATCH 0259/1483] Check unhandled exceptions from the lower execution layers An unhandled exception raise from a test executed with a mere build_and_run call triggers a test failure only in native environments today, out of the program's execution status. There is no such automatic test failure in cross configurations where the notion of test execution status is more weakly defined. While SCOV tests workaround this with an explicit check on the programs' output, a more systematic approach is desirable. This change introduces a check at a much lower level, through which most if not all the executions should go. At least all the SCOV ones and all those resorting to build_and_run. --- testsuite/SCOV/internals/driver.py | 21 ++++--- testsuite/SUITE/cutils.py | 16 +++++ testsuite/SUITE/tutils.py | 98 ++++++++++++++++++++++++++---- 3 files changed, 113 insertions(+), 22 deletions(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 350507029..a4e838354 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -35,7 +35,7 @@ from SUITE.context import thistest from SUITE.control import language_info, runtime_info from SUITE.cutils import ext, to_list, list_to_file, match, no_ext -from SUITE.cutils import contents_of, lines_of +from SUITE.cutils import contents_of, lines_of, unhandled_exception_in from SUITE.gprutils import GPRswitches from SUITE.tutils import gprbuild, gprfor, xrun, xcov, frame from SUITE.tutils import gprbuild_cargs_with @@ -730,18 +730,19 @@ def abdir(self, attribute=False): def run_test(self, main): """Execute the MAIN program to produce an execution trace, and - trigger a failure if it raises an unhandled exception.""" + always trigger a failure if it raises an unhandled exception.""" out_file = self.mode_execute(main=main) - thistest.fail_if( - match( - r"(!!! EXCEPTION RAISED !!!" - r"|raised [A-Z_]+ : [-._a-zA-Z]+:[0-9]+ \w+)", - out_file - ), - "exception raised while running '%s'." % main - ) + # The exception check is performed by the lower execution + # layers if we don't expect a failure from this test (out of + # our register_failure requests). + + if self.testcase.expect_failures: + thistest.fail_if( + unhandled_exception_in(contents_of(out_file)), + "exception raised while running '%s'." % main + ) def gen_one_xcov_report(self, inputs, format, options=""): """Helper for gen_xcov_reports, to produce one specific report for a diff --git a/testsuite/SUITE/cutils.py b/testsuite/SUITE/cutils.py index 605a13502..6a035c988 100644 --- a/testsuite/SUITE/cutils.py +++ b/testsuite/SUITE/cutils.py @@ -15,6 +15,22 @@ from e3.os.fs import cd, which from e3.os.process import Run +def unhandled_exception_in(log): + """ + Whether the provided execution log contains an indication + of a unhandled exception occurrence. + """ + + # Account for patterns emitted by either a regular runtime or + # our custom last_chance_handlers. + return re.search( + pattern=( + r"(!!! EXCEPTION RAISED !!!" + r"|" + r"raised [A-Z_]+ : [-._a-zA-Z]+:[0-9]+ \w+)" + ), + string=log + ) def strip_prefix(prefix, string): """ diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index e2e60ae5a..01d949e83 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -27,7 +27,8 @@ # Then mind our own business -from SUITE.cutils import FatalError, contents_of, text_to_file, to_list +from SUITE.cutils import (FatalError, contents_of, text_to_file, to_list, + unhandled_exception_in) # Precompute some values we might be using repeatedly @@ -42,6 +43,53 @@ MEMCHECK_LOG = 'memcheck.log' CALLGRIND_LOG = 'callgrind-{}.log' +# ---------------------------------------------------------------------------- +# Notes on program and command execution paths +# +# Our tests execute lots of commands to instrument and build programs, to run +# the programs themselves, to produce reports from coverage traces. +# +# For robustness, we strive to minimize the paths controlling such executions +# within the testsuite. This lets us place important checks at critical spots +# and retain confidence in what we are testing as the testsuite grows. +# +# Of particular interest are the paths used to execute test programs as the +# notion of exit status may vary across execution environments and extra +# checks on the program outputs are sometimes needed to detect some kinds of +# failures. +# +# Here's a sketch of how various functions/methods cooperate for src/bin +# trace modes and cross/native configurations. _Please_ keep the general +# issue in mind when considering changes in this area. +# +# [test.py(bin)] [test.py(bin/src)] +# | build_and_run +# v | | +# o-------(bin)---o o----(src)-------o +# | | +# | | +# | [driver.py(bin/src)] | +# | mode_execute | +# | | | | +# | o----(bin)---o o---(src)----o | +# | | | | +# v v | | +# xrun | | +# | | | +# v | | +# xcov v v +# | run_cov_program +# | | +# | gnatcov run pgm | pgm (native) +# | (now cross only) | -gnatemu pgm (cross) +# | | +# o-------------o o------------o +# | | +# v v +# cmdrun +# +# ---------------------------------------------------------------------------- + run_processes = [] """ List of processes run through run_and_log. Useful for debugging. @@ -573,13 +621,21 @@ def xcov_suite_args(covcmd, covargs, return result -def cmdrun(cmd, inp=None, out=None, err=None, env=None, register_failure=True): +def cmdrun(cmd, for_pgm, inp=None, out=None, err=None, env=None, + register_failure=True): """ Execute the command+args list in CMD, redirecting its input, output and error streams to INP, OUT and ERR when not None, respectively. If ENV is - not None, pass it as the subprocess environment. Stop with a FatalError if - the execution status is not zero and REGISTER_FAILURE is True. Return the - process descriptor otherwise. + not None, pass it as the subprocess environment. + + FOR_PGM tells if this execution actually runs a user/test program. + + Stop with a FatalError if the execution status is not zero and + REGISTER_FAILURE is True. If FOR_PGM is also True (in addition to + REGISTER_FAILURE) also check the program's output for an occurrence + of unhandled exception in cross configurations. + + In absence of fatal error, return the process descriptor. """ # Setup a dictionary of Run input/output/error arguments for which a @@ -594,10 +650,25 @@ def cmdrun(cmd, inp=None, out=None, err=None, env=None, register_failure=True): p = run_and_log(cmd, timeout=thistest.options.timeout, **kwargs) - thistest.stop_if( - register_failure and p.status != 0, - FatalError('"%s"' % ' '.join(cmd) + ' exit in error', - outfile=out, outstr=p.out)) + # Check for FataError conditions. Minimize the situations where we look + # into the program's output as this is a central spot. + + if register_failure and p.status != 0: + output = contents_of(out) if out else p.out + thistest.stop( + FatalError( + '"%s"' % ' '.join(cmd) + ' exit in error', + outfile=out, outstr=output) + ) + + if register_failure and for_pgm and thistest.options.target: + output = contents_of(out) if out else p.out + thistest.stop_if( + unhandled_exception_in(output), + FatalError( + '"%s"' % ' '.join(cmd) + ' raised an unhandled exception', + outfile=out, outstr=output) + ) return p @@ -653,7 +724,8 @@ def xcov(args, out=None, err=None, inp=None, env=None, register_failure=True, # projects. They are pointless wrt coverage run or analysis activities # so we don't include them here. p = cmdrun(cmd=covpgm + covargs, inp=inp, out=out, err=err, env=env, - register_failure=register_failure) + register_failure=register_failure, + for_pgm=(covcmd == "run")) if thistest.options.enable_valgrind == 'memcheck': memcheck_log = contents_of(MEMCHECK_LOG) @@ -743,14 +815,16 @@ def run_cov_program(executable, out=None, env=None, exec_args=None, args.append(executable) args.extend(exec_args) - return cmdrun(args, out=out, inp=inp, env=env, register_failure=register_failure) + return cmdrun(args, out=out, inp=inp, env=env, + register_failure=register_failure, + for_pgm=True) def do(command): """ Execute COMMAND. Abort and dump output on failure. Return output otherwise. """ - p = cmdrun(cmd=to_list(command), register_failure=True) + p = cmdrun(cmd=to_list(command), register_failure=True, for_pgm=False) return p.out From da0e14190ff75065fa6cb124c15233877a7c046a Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Tue, 11 Apr 2023 10:08:00 +0000 Subject: [PATCH 0260/1483] Add tests/build_run-assert-failure Add a simple test verifying that an assertion failure from a test executed through build_and_run is visible as an exception raise message in the test execution log. Introduce a simple convention regarding the program execution logs out of build_and_run. --- testsuite/SCOV/minicheck.py | 10 +++-- .../tests/build_run-assert-failure/p.adb | 6 +++ .../tests/build_run-assert-failure/test.py | 43 +++++++++++++++++++ 3 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/build_run-assert-failure/p.adb create mode 100644 testsuite/tests/build_run-assert-failure/test.py diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 8bf9a5609..2cdcbf350 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -110,7 +110,8 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, :return: Incomplete list of arguments to pass to `xcov` in order to run "gnatcov coverage". The only mandatory argument that is missing is the annotation format. The last N arguments correspond to trace files for - the given N mains. + the given N mains. Upon return, the progam execution log for each main + M is available as M_output.txt. """ def abspath(path): return os.path.abspath(path) if absolute_paths else path @@ -174,6 +175,8 @@ def gprbuild_wrapper(root_project): if scos else gprsw.cov_switches) + out_file_ = '{}_output.txt' + if trace_mode == 'bin': # Build and run each main gprbuild_wrapper(gprsw.root_project) @@ -189,7 +192,8 @@ def gprbuild_wrapper(root_project): eargs = ["-eargs"] + exec_args for m in mains: - xrun(run_args + [exepath(m)] + eargs, out='run.log', + out_file = out_file_.format(m) + xrun(run_args + [exepath(m)] + eargs, out=out_file, env=program_env, register_failure=register_failure) trace_files = [abspath(tracename_for(m)) for m in mains] @@ -277,7 +281,7 @@ def gprbuild_wrapper(root_project): # multiple traces in the current directory. rm(srctrace_pattern_for(m)) - out_file = '{}_output.txt'.format(m) + out_file = out_file_.format(m) run_cov_program(exepath(m), out=out_file, env=program_env, register_failure=register_failure, exec_args=exec_args) diff --git a/testsuite/tests/build_run-assert-failure/p.adb b/testsuite/tests/build_run-assert-failure/p.adb new file mode 100644 index 000000000..d62d54a67 --- /dev/null +++ b/testsuite/tests/build_run-assert-failure/p.adb @@ -0,0 +1,6 @@ +with Support; + +procedure P is +begin + Support.Assert (False); +end; diff --git a/testsuite/tests/build_run-assert-failure/test.py b/testsuite/tests/build_run-assert-failure/test.py new file mode 100644 index 000000000..4eb60e0ec --- /dev/null +++ b/testsuite/tests/build_run-assert-failure/test.py @@ -0,0 +1,43 @@ +""" +Verify that the testsuite detects tests resulting in assertion +failures through build_and_run. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest, Test +from SUITE.cutils import Wdir, FatalError +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +gpr = gprfor(mains=["p.adb"], srcdirs=[".."]) + +# build_and_run with register_failure True and check +# the program's output for an exception indication. + +try: + build_and_run( + gprsw=GPRswitches(root_project=gpr, units=["p"]), + mains=["p"], + covlevel="stmt", + extra_coverage_args=[], + register_failure=True + ) +except FatalError: + pass +else: + thistest.stop( + FatalError( + "expected FatalError from build_and_run, got different exception") + ) + +# If we reach here, the test is PASSED. The failure registration +# closes the test logs though, so we need to reinstantiate to be able +# to report. Note that this brings us back at the test's home dir. + +thistest = Test() + +thistest.result() + From 4552fef2e3e66dd0cefd58a4e3d01fa63daffcfb Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 21 Mar 2023 18:01:48 +0100 Subject: [PATCH 0261/1483] Enhance the doc wrt. instr of package level decls --- doc/gnatcov/src_traces.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 8b5534f90..c55edce69 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -380,6 +380,21 @@ process, and the MC/DC coverage for each decision will be reported as ``Undetermined_Coverage`` state. Should the default limit not be satisfactory, it can be tuned with the option :cmd-option:`--path-count-limit`. +Source-coverage obligations limitations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In Ada, variable or type declarations at the package level can yield elaboration +code. Such code constructs are thus considered to have corresponding coverage +obligations + +In the case where a `pragma Preelaborate` or the `No_Elaboration_Code` +restriction affects the instrumented unit, variable / type declarations at the +package level are not considered as coverage obligations. In the former case, +elaboration code can still be emitted (in rare occurrences), but the pragma is +too restrictive to instrument such code constructs. In the latter case, no +elaboration code can be emitted so it is valid not to produce any coverage +obligation. + Global source traces limitations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From fd01322a69a84a3a6a0dff221a7ae3ebb5afc75c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 13 Mar 2023 12:06:53 +0100 Subject: [PATCH 0262/1483] scope metrics: add subp renamings and generic instantiations For consistency with the GNATstudio report, see VC12-030. --- tools/gnatcov/instrument-ada_unit.adb | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 0ea790069..3717bb451 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -4891,6 +4891,23 @@ package body Instrument.Ada_Unit is when Ada_Named_Stmt => Traverse_One (N.As_Named_Stmt.F_Stmt.As_Ada_Node); + when Ada_Package_Renaming_Decl + | Ada_Subp_Renaming_Decl + | Ada_Generic_Renaming_Decl + | Ada_Generic_Instantiation + => + Set_Statement_Entry; + Enter_Scope + (UIC => UIC, + Scope_Name => + N.As_Basic_Decl.P_Defining_Name.F_Name.Text, + Sloc => Sloc (N)); + Extend_Statement_Sequence + (UIC, N, + (if N.Kind in Ada_Generic_Instantiation then 'i' else 'r')); + Set_Statement_Entry; + Exit_Scope (UIC); + when others => -- Determine required type character code, or ASCII.NUL if @@ -4928,14 +4945,6 @@ package body Instrument.Ada_Unit is end if; end; - when Ada_Package_Renaming_Decl | - Ada_Subp_Renaming_Decl | - Ada_Generic_Renaming_Decl => - Typ := 'r'; - - when Ada_Generic_Instantiation => - Typ := 'i'; - when Ada_Package_Body_Stub | Ada_Protected_Body_Stub | Ada_Aspect_Clause From b3a06d21e7426a1085513b3f181ca50277566e56 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 21 Mar 2023 10:39:29 +0100 Subject: [PATCH 0263/1483] Isolate libadalang dependency to the Instrument.Ada_Unit unit This commit isolates the dependency to libadalang (which is a big one) to the Libadalang.Ada_Unit, making gnatcov dependency graph simpler. --- tools/gnatcov/instrument-ada_unit.adb | 7 +++++-- tools/gnatcov/instrument-ada_unit.ads | 3 +-- tools/gnatcov/instrument.adb | 12 +----------- 3 files changed, 7 insertions(+), 15 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 3717bb451..dc1baafe2 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -45,6 +45,7 @@ with Coverage; use Coverage; with Diagnostics; use Diagnostics; with Files_Table; use Files_Table; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with Instrument.Ada_Unit_Provider; with Namet; use Namet; with Outputs; use Outputs; with Paths; use Paths; @@ -6614,9 +6615,11 @@ package body Instrument.Ada_Unit is ----------------------------- function Create_Ada_Instrumenter - (Provider : Unit_Provider_Reference; - Language_Version : Any_Language_Version) return Ada_Instrumenter_Type + (Language_Version : Any_Language_Version) return Ada_Instrumenter_Type is + Provider : constant Unit_Provider_Reference := + Instrument.Ada_Unit_Provider.Create_Provider_From_Project; + Instrumenter : Ada_Instrumenter_Type; begin Instrumenter.Provider := Provider; diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index b10418ae2..71a633f61 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -60,8 +60,7 @@ package Instrument.Ada_Unit is -- Instrumentation primitives for Ada function Create_Ada_Instrumenter - (Provider : Unit_Provider_Reference; - Language_Version : Any_Language_Version) return Ada_Instrumenter_Type; + (Language_Version : Any_Language_Version) return Ada_Instrumenter_Type; -- Create an Ada instrumenter from the given provider, and the given -- language version. diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 2c6a6b4de..67ee8ecf4 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -34,14 +34,11 @@ with GNATCOLL.Projects; use GNATCOLL.Projects; with GNATCOLL.JSON; use GNATCOLL.JSON; with GNATCOLL.VFS; use GNATCOLL.VFS; -with Libadalang.Analysis; - with Checkpoints; with Coverage; with Files_Table; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Instrument.Ada_Unit; -with Instrument.Ada_Unit_Provider; with Instrument.Base_Types; use Instrument.Base_Types; with Instrument.Clean_Objdirs; with Instrument.C; @@ -305,19 +302,12 @@ package body Instrument is Ignored_Source_Files : access GNAT.Regexp.Regexp; Mains : String_Vectors.Vector) is - use Libadalang.Analysis; use String_Vectors; - -- First create the context for Libadalang - - Provider : constant Unit_Provider_Reference := - Instrument.Ada_Unit_Provider.Create_Provider_From_Project; - -- Initialize all the instrumenters Ada_Instrumenter : aliased Instrument.Ada_Unit.Ada_Instrumenter_Type := - Instrument.Ada_Unit.Create_Ada_Instrumenter - (Provider, Language_Version); + Instrument.Ada_Unit.Create_Ada_Instrumenter (Language_Version); C_Instrumenter : aliased Instrument.C.C_Instrumenter_Type := (null record); CPP_Instrumenter : aliased Instrument.C.CPP_Instrumenter_Type := From 7bc319a360d5ab4cbf5768712b87e9b65fef143c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 7 Dec 2022 15:42:55 +0100 Subject: [PATCH 0264/1483] Instrument: refactor stubs In some cases, gnatcov needs to be built w/o support for C/C++ instrumentation (for the community edition), and even w/o Ada instrumentation support (when building the gnatcov32 driver that is not used for instrumentation purposes). The community edition used to crash on projects containing a mix of Ada and C sources, when C instrumentation was enabled. It was not a problem for editions prior to 23.0, as C was not enabled by default. Now that C is activated in the default configuration, we need to rework this part. Also simplify the stubbing mechanism to make it easy to deactivate Ada instrumentation, C instrumentation or both. TN: VC07-019 --- tools/gnatcov/gnatcov.gpr | 7 ++- tools/gnatcov/instrument-ada_unit.ads | 5 ++ tools/gnatcov/instrument-ada_unit__stub.adb | 19 +++++++ tools/gnatcov/instrument-ada_unit__stub.ads | 50 +++++++++++++++++ tools/gnatcov/instrument-c__stub.adb | 56 +------------------ tools/gnatcov/instrument-c__stub.ads | 37 ++---------- tools/gnatcov/instrument-common.ads | 15 ++--- tools/gnatcov/instrument__stub.adb | 62 --------------------- 8 files changed, 92 insertions(+), 159 deletions(-) create mode 100644 tools/gnatcov/instrument-ada_unit__stub.adb create mode 100644 tools/gnatcov/instrument-ada_unit__stub.ads delete mode 100644 tools/gnatcov/instrument__stub.adb diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index cd444a77b..7e1a65cfe 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -105,7 +105,12 @@ project Gnatcov is case Part is when "lib32" | "lib64" | "driver" | "gnatcov32" => - for Body ("Instrument") use "instrument__stub.adb"; + for Specification ("Instrument.Ada_Unit") + use "instrument-ada_unit__stub.ads"; + for Body ("Instrument.Ada_Unit") + use "instrument-ada_unit__stub.adb"; + for Body ("Instrument.C") use "instrument-c__stub.adb"; + for Specification ("Instrument.C") use "instrument-c__stub.ads"; when "gnatcov64" => null; end case; diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 71a633f61..21fac98b1 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -85,6 +85,11 @@ package Instrument.Ada_Unit is Root_Project_Info : in out Project_Info; Instr_Units : CU_Name_Vectors.Vector); + overriding function Skip_Source_File + (Self : Ada_Instrumenter_Type; + Source_File : GNATCOLL.Projects.File_Info) return Boolean + is (False); + procedure Find_Ada_Units (Instrumenter : in out Ada_Instrumenter_Type; CU_Name : Compilation_Unit_Name; diff --git a/tools/gnatcov/instrument-ada_unit__stub.adb b/tools/gnatcov/instrument-ada_unit__stub.adb new file mode 100644 index 000000000..c4fd7d0ac --- /dev/null +++ b/tools/gnatcov/instrument-ada_unit__stub.adb @@ -0,0 +1,19 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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. -- +------------------------------------------------------------------------------ + +pragma No_Body; diff --git a/tools/gnatcov/instrument-ada_unit__stub.ads b/tools/gnatcov/instrument-ada_unit__stub.ads new file mode 100644 index 000000000..cf47448bd --- /dev/null +++ b/tools/gnatcov/instrument-ada_unit__stub.ads @@ -0,0 +1,50 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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. -- +------------------------------------------------------------------------------ + +-- Stub of Instrument.Ada_Unit, to avoid pulling a dependency to libadalang +-- when gnatcov is not built with Ada instrumentation support (basically the +-- gnatcov32 executable that have support for binary traces only). + +with GNATCOLL.Projects; use GNATCOLL.Projects; + +with Instrument.Base_Types; use Instrument.Base_Types; +with Instrument.Common; use Instrument.Common; +with Switches; use Switches; + +package Instrument.Ada_Unit is + + type Ada_Instrumenter_Type is new Language_Instrumenter with null record; + -- Common instrumentation primitives for Ada + + function Create_Ada_Instrumenter + (Language_Version : Any_Language_Version) return Ada_Instrumenter_Type + is (Ada_Instrumenter_Type'(null record)); + + overriding function Language + (Self : Ada_Instrumenter_Type) return Src_Supported_Language + is (Ada_Language); + + procedure Find_Ada_Units + (Instrumenter : in out Ada_Instrumenter_Type; + CU_Name : Compilation_Unit_Name; + Info : GNATCOLL.Projects.File_Info; + Process_Unit : access procedure + (CU_Name : Compilation_Unit_Name; + Info : GNATCOLL.Projects.File_Info)) is null; + +end Instrument.Ada_Unit; diff --git a/tools/gnatcov/instrument-c__stub.adb b/tools/gnatcov/instrument-c__stub.adb index 104c74e96..98400eb4d 100644 --- a/tools/gnatcov/instrument-c__stub.adb +++ b/tools/gnatcov/instrument-c__stub.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2023, 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 -- @@ -16,56 +16,4 @@ -- of the license. -- ------------------------------------------------------------------------------ -package body Instrument.C is - - Error_Msg : constant String := - "GNATcoverage not built with C support."; - - ---------------------- - -- Skip_Source_File -- - ---------------------- - - function Skip_Source_File - (Self : C_Family_Instrumenter_Type; - Source_File : GNATCOLL.Projects.File_Info) return Boolean - is (raise Program_Error with Error_Msg); - - --------------------- - -- Instrument_Unit -- - --------------------- - - procedure Instrument_Unit - (Self : in out C_Family_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Unit_Info : in out Instrumented_Unit_Info) is - begin - raise Program_Error with Error_Msg; - end Instrument_Unit; - - ------------------------------- - -- Auto_Dump_Buffers_In_Main -- - ------------------------------- - - procedure Auto_Dump_Buffers_In_Main - (Self : in out C_Family_Instrumenter_Type; - Filename : String; - Instr_Units : CU_Name_Vectors.Vector; - Dump_Config : Any_Dump_Config; - Info : in out Project_Info) is - begin - raise Program_Error with Error_Msg; - end Auto_Dump_Buffers_In_Main; - - ---------------------------- - -- Emit_Buffers_List_Unit -- - ---------------------------- - - overriding procedure Emit_Buffers_List_Unit - (Self : C_Family_Instrumenter_Type; - Root_Project_Info : in out Project_Info; - Instr_Units : CU_Name_Vectors.Vector) is - begin - raise Program_Error with Error_Msg; - end Emit_Buffers_List_Unit; - -end Instrument.C; +pragma No_Body; diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index 6ca434a58..6447bef4f 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2023, 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 -- @@ -17,18 +17,10 @@ ------------------------------------------------------------------------------ -- Stub of Instrument.C, to avoid pulling a dependency to libclang when --- gnatcov is not built with C support. --- --- TODO??? this will need rework when C is enabled by default (see V222-037). --- When gnatcov is built with C_SUPPORT=False, it will try to instrument C --- units, using the procedures defined here, which will result in a crash (all --- the procedures are empty stubs raising an error). +-- gnatcov is not built with C instrumentation support. -with GNATCOLL.Projects; use GNATCOLL.Projects; - -with Instrument.Base_Types; use Instrument.Base_Types; -with Instrument.Common; use Instrument.Common; -with Switches; use Switches; +with Instrument.Common; use Instrument.Common; +with Switches; use Switches; package Instrument.C is @@ -36,27 +28,6 @@ package Instrument.C is abstract new Language_Instrumenter with null record; -- Common instrumentation primitives for C/C++ - overriding function Skip_Source_File - (Self : C_Family_Instrumenter_Type; - Source_File : GNATCOLL.Projects.File_Info) return Boolean; - - overriding procedure Instrument_Unit - (Self : in out C_Family_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Unit_Info : in out Instrumented_Unit_Info); - - overriding procedure Auto_Dump_Buffers_In_Main - (Self : in out C_Family_Instrumenter_Type; - Filename : String; - Instr_Units : CU_Name_Vectors.Vector; - Dump_Config : Any_Dump_Config; - Info : in out Project_Info); - - overriding procedure Emit_Buffers_List_Unit - (Self : C_Family_Instrumenter_Type; - Root_Project_Info : in out Project_Info; - Instr_Units : CU_Name_Vectors.Vector); - type C_Instrumenter_Type is new C_Family_Instrumenter_Type with null record; -- Instrumentation primitives for C diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 3566d9980..30f468c2d 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -523,17 +523,14 @@ package Instrument.Common is function Skip_Source_File (Self : Language_Instrumenter; Source_File : GNATCOLL.Projects.File_Info) return Boolean - is (False); - -- Whether the instrumenter skips the given source file. - -- - -- There is currently only one case where this is needed: the C - -- instrumenter must skip header files, as it instruments only bodies (.c - -- files). + is (True); + -- Whether the instrumenter skips the given source file. The default + -- (undefined) instrumenter skips every source file. procedure Instrument_Unit (Self : in out Language_Instrumenter; CU_Name : Compilation_Unit_Name; - Unit_Info : in out Instrumented_Unit_Info) is abstract; + Unit_Info : in out Instrumented_Unit_Info) is null; -- Instrument a single source file for the language that Self supports. -- -- CU_Name must be the name of the compilation unit for this source file, @@ -545,7 +542,7 @@ package Instrument.Common is Filename : String; Instr_Units : CU_Name_Vectors.Vector; Dump_Config : Any_Dump_Config; - Info : in out Project_Info) is abstract; + Info : in out Project_Info) is null; -- Try to instrument the Filename source file (whose language is assumed -- to be Self's) to insert a call to dump the list of coverage buffers for -- all Instr_Units, according to the Dump_Config options. Do nothing if not @@ -557,7 +554,7 @@ package Instrument.Common is procedure Emit_Buffers_List_Unit (Self : Language_Instrumenter; Root_Project_Info : in out Project_Info; - Instr_Units : CU_Name_Vectors.Vector) is abstract; + Instr_Units : CU_Name_Vectors.Vector) is null; -- The variable holding the list of coverage buffers is exported to a -- unique C symbol whose name is defined by the Unit_Buffers_Array_Name -- function. This procedure should thus be called only once, for one of diff --git a/tools/gnatcov/instrument__stub.adb b/tools/gnatcov/instrument__stub.adb deleted file mode 100644 index e56a101ef..000000000 --- a/tools/gnatcov/instrument__stub.adb +++ /dev/null @@ -1,62 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2008-2022, 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. -- ------------------------------------------------------------------------------- - --- This is a stub version of the root Instrumentation package, which does not --- bring a dependency to the Instrument.Ada and the Instrument.C units. This --- allows us to no longer depend on libclang/libadalang for executables such --- as gnatcov32 that don't need the instrumentation capabilities, greatly --- reducing their size and compilation time. - -package body Instrument is - - Msg : constant String := "Stub of Instrument, unreachable code."; - - ----------- - -- Image -- - ----------- - - function Image (Dump_Trigger : Any_Dump_Trigger) return String - is (raise Program_Error with Msg); - - function Image (Dump_Channel : Any_Dump_Channel) return String - is (raise Program_Error with Msg); - - ----------- - -- Value -- - ----------- - - function Value (Dump_Trigger : String) return Any_Dump_Trigger - is (raise Program_Error with Msg); - - function Value (Dump_Channel : String) return Any_Dump_Channel - is (raise Program_Error with Msg); - - ---------------------------------- - -- Instrument_Units_Of_Interest -- - ---------------------------------- - - procedure Instrument_Units_Of_Interest - (Dump_Config : Any_Dump_Config; - Language_Version : Any_Language_Version; - Ignored_Source_Files : access GNAT.Regexp.Regexp; - Mains : String_Vectors.Vector) is - begin - raise Program_Error with Msg; - end Instrument_Units_Of_Interest; - -end Instrument; From 560ae2bd31412931e1974498ace25e9931a8f630 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 7 Dec 2022 17:28:11 +0100 Subject: [PATCH 0265/1483] Instrument: remove Instrument.Base_Types unit As we no longer need to stub the Instrument unit, we can have all the procedures required for instrumentation purposes defined here. Delete the Instrument.Base_Types unit and move its content to the Instrument unit. To avoid a cyclic dependency, also move some declarations from Instrument to Switches. TN: VC07-019 --- tools/gnatcov/annotations.adb | 4 +- tools/gnatcov/coverage-source.ads | 1 - tools/gnatcov/instrument-ada_unit.adb | 28 +- tools/gnatcov/instrument-ada_unit.ads | 5 - tools/gnatcov/instrument-ada_unit__stub.ads | 6 +- .../gnatcov/instrument-ada_unit_provider.adb | 1 - .../gnatcov/instrument-ada_unit_provider.ads | 2 - tools/gnatcov/instrument-base_types.adb | 404 ---------------- tools/gnatcov/instrument-base_types.ads | 166 ------- tools/gnatcov/instrument-c.adb | 7 +- tools/gnatcov/instrument-c.ads | 10 +- tools/gnatcov/instrument-c__stub.ads | 1 - tools/gnatcov/instrument-c_utils.adb | 2 +- tools/gnatcov/instrument-checkpoints.adb | 10 +- tools/gnatcov/instrument-common.ads | 8 - tools/gnatcov/instrument-input_traces.adb | 2 - tools/gnatcov/instrument-input_traces.ads | 2 - tools/gnatcov/instrument.adb | 453 +++++++++++++++--- tools/gnatcov/instrument.ads | 178 +++++-- tools/gnatcov/project.adb | 10 +- tools/gnatcov/setup_rts.adb | 1 - tools/gnatcov/setup_rts.ads | 4 +- tools/gnatcov/switches.adb | 55 ++- tools/gnatcov/switches.ads | 71 ++- 24 files changed, 663 insertions(+), 768 deletions(-) delete mode 100644 tools/gnatcov/instrument-base_types.adb delete mode 100644 tools/gnatcov/instrument-base_types.ads diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 67b5b0edd..a64156dda 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -31,7 +31,7 @@ with Coverage_Options; use Coverage_Options; with Coverage.Object; with Coverage.Source; use Coverage.Source; with Coverage.Tags; -with Instrument.Base_Types; +with Instrument; with Outputs; use Outputs; with Subprocesses; with Switches; use Switches; @@ -716,7 +716,7 @@ package body Annotations is begin if Postprocessed_SFI = No_Source_File then declare - use Instrument.Base_Types; + use Instrument; use Subprocesses; Preprocessed : Boolean; begin diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 834e51053..1f0968fa2 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -22,7 +22,6 @@ with Checkpoints; use Checkpoints; with Files_Table; use Files_Table; with Instrument; use Instrument; with Instrument.Input_Traces; use Instrument.Input_Traces; -with Instrument.Base_Types; use Instrument.Base_Types; with Traces; use Traces; with Traces_Names; use Traces_Names; with Traces_Lines; use Traces_Lines; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index dc1baafe2..17c78e804 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -39,23 +39,21 @@ with Libadalang.Sources; use Libadalang.Sources; with GNATCOLL.Utils; with GNATCOLL.VFS; -with ALI_Files; use ALI_Files; -with Coverage_Options; use Coverage_Options; -with Coverage; use Coverage; -with Diagnostics; use Diagnostics; -with Files_Table; use Files_Table; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with ALI_Files; use ALI_Files; +with Coverage_Options; use Coverage_Options; +with Coverage; use Coverage; +with Diagnostics; use Diagnostics; +with Files_Table; use Files_Table; with Instrument.Ada_Unit_Provider; -with Namet; use Namet; -with Outputs; use Outputs; -with Paths; use Paths; +with Namet; use Namet; +with Outputs; use Outputs; +with Paths; use Paths; with Project; with SCOs; with Slocs; -with Snames; use Snames; +with Snames; use Snames; with Table; -with Text_Files; use Text_Files; -with Switches; use Switches; +with Text_Files; use Text_Files; package body Instrument.Ada_Unit is @@ -132,7 +130,7 @@ package body Instrument.Ada_Unit is -- process only codepoints in the ASCII range and thus use -- Langkit_Support.Text.Image. - Identifier : constant Base_Types.Ada_Identifier := + Identifier : constant Ada_Identifier := To_Unbounded_String (Image (Name.Text)); begin Result.Append (Identifier); @@ -7947,7 +7945,7 @@ package body Instrument.Ada_Unit is begin return Ada_Identifier_Vectors."&" (Sys_Buffers_Lists, - Instrument.Base_Types.Ada_Identifier (+Project_Name_Slug)); + Instrument.Ada_Identifier (+Project_Name_Slug)); end Buffers_List_Unit; ---------------------- @@ -7957,7 +7955,7 @@ package body Instrument.Ada_Unit is function Pure_Buffer_Unit (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name is - Simple_Name : Instrument.Base_Types.Ada_Identifier; + Simple_Name : Instrument.Ada_Identifier; begin Append (Simple_Name, 'P'); Append (Simple_Name, Instrumented_Unit_Slug (Instrumented_Unit)); diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 21fac98b1..2a8bfb2d0 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -24,17 +24,12 @@ with Ada.Strings.Unbounded; with Ada.Strings.Wide_Wide_Hash; with Ada.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; -with GNATCOLL.Projects; use GNATCOLL.Projects; - with Langkit_Support.Text; use Langkit_Support.Text; with Libadalang.Analysis; use Libadalang.Analysis; with Libadalang.Rewriting; use Libadalang.Rewriting; -with Instrument.Base_Types; use Instrument.Base_Types; with Instrument.Common; use Instrument.Common; -with SC_Obligations; use SC_Obligations; with Switches; -with Types; use Types; package Instrument.Ada_Unit is diff --git a/tools/gnatcov/instrument-ada_unit__stub.ads b/tools/gnatcov/instrument-ada_unit__stub.ads index cf47448bd..1caac4fe2 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.ads +++ b/tools/gnatcov/instrument-ada_unit__stub.ads @@ -20,11 +20,7 @@ -- when gnatcov is not built with Ada instrumentation support (basically the -- gnatcov32 executable that have support for binary traces only). -with GNATCOLL.Projects; use GNATCOLL.Projects; - -with Instrument.Base_Types; use Instrument.Base_Types; -with Instrument.Common; use Instrument.Common; -with Switches; use Switches; +with Instrument.Common; use Instrument.Common; package Instrument.Ada_Unit is diff --git a/tools/gnatcov/instrument-ada_unit_provider.adb b/tools/gnatcov/instrument-ada_unit_provider.adb index 2585c74b7..cf0ad0b97 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.adb +++ b/tools/gnatcov/instrument-ada_unit_provider.adb @@ -20,7 +20,6 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Text_IO; use Ada.Text_IO; with GNATCOLL.Projects.Aux; use GNATCOLL.Projects.Aux; -with GNATCOLL.Projects; use GNATCOLL.Projects; with Libadalang.Unit_Files; diff --git a/tools/gnatcov/instrument-ada_unit_provider.ads b/tools/gnatcov/instrument-ada_unit_provider.ads index 14dbfd4db..3e2774b11 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.ads +++ b/tools/gnatcov/instrument-ada_unit_provider.ads @@ -26,8 +26,6 @@ with Langkit_Support.Text; use Langkit_Support.Text; with Libadalang.Analysis; use Libadalang.Analysis; with Libadalang.Common; use Libadalang.Common; -with Instrument.Base_Types; use Instrument.Base_Types; - -- Custom implementation of a libadalang unit provider, using the mapping -- file produced from the project file (that is passed to the compiler through -- the -gnatem switch). diff --git a/tools/gnatcov/instrument-base_types.adb b/tools/gnatcov/instrument-base_types.adb deleted file mode 100644 index fee57845c..000000000 --- a/tools/gnatcov/instrument-base_types.adb +++ /dev/null @@ -1,404 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2008-2022, 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; use Ada.Containers; -with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Strings.Unbounded.Equal_Case_Insensitive; -with Ada.Strings.Unbounded.Less_Case_Insensitive; - -with Interfaces; use Interfaces; - -with GNATCOLL.VFS; - -with Hex_Images; use Hex_Images; - -package body Instrument.Base_Types is - - ------------------- - -- Language_Kind -- - ------------------- - - function Language_Kind (Language : Some_Language) return Any_Language_Kind - is - begin - return (case Language is - when Ada_Language => Unit_Based_Language, - when C_Language - | CPP_Language => File_Based_Language); - end Language_Kind; - - ------------ - -- To_Ada -- - ------------ - - function To_Ada (Name : Ada_Qualified_Name) return String is - Result : Unbounded_String; - begin - for Id of Name loop - if Length (Result) > 0 then - Append (Result, "."); - end if; - Append (Result, To_String (Id)); - end loop; - - return +Result; - end To_Ada; - - --------- - -- "<" -- - --------- - - function "<" (Left, Right : Compilation_Unit_Name) return Boolean is - begin - if Left.Language_Kind = Right.Language_Kind then - case Left.Language_Kind is - when Unit_Based_Language => - if Left.Part = Right.Part then - if Left.Unit.Length = Right.Unit.Length then - for I in 1 .. Integer (Left.Unit.Length) loop - declare - Left_Id : constant Unbounded_String := - Unbounded_String (Left.Unit.Element (I)); - Right_Id : constant Unbounded_String := - Unbounded_String (Right.Unit.Element (I)); - begin - if not Equal_Case_Insensitive (Left_Id, Right_Id) - then - return Less_Case_Insensitive (Left_Id, Right_Id); - end if; - end; - end loop; - - -- If we get there, they are equal - - return False; - else - return Left.Unit.Length < Right.Unit.Length; - end if; - else - return Left.Part < Right.Part; - end if; - when File_Based_Language => - if Equal_Case_Insensitive - (Left.Project_Name, Right.Project_Name) - then - return Left.Filename < Right.Filename; - else - return Less_Case_Insensitive - (Left.Project_Name, Right.Project_Name); - end if; - end case; - else - return Left.Language_Kind < Right.Language_Kind; - end if; - end "<"; - - --------- - -- "=" -- - --------- - - function "=" (Left, Right : Compilation_Unit_Name) return Boolean - is - use Ada_Identifier_Vectors; - begin - if Left.Language_Kind = Right.Language_Kind then - case Left.Language_Kind is - when Unit_Based_Language => - if Left.Part = Right.Part - and then Left.Unit.Length = Right.Unit.Length - then - for I in 1 .. Integer (Left.Unit.Length) loop - if not Equal_Case_Insensitive - (Unbounded_String (Left.Unit.Element (I)), - Unbounded_String (Right.Unit.Element (I))) - then - return False; - end if; - end loop; - - -- If we get there, they are equal - - return True; - end if; - return False; - when File_Based_Language => - return Left.Filename = Right.Filename - and then Equal_Case_Insensitive - (Left.Project_Name, Right.Project_Name); - end case; - else - return False; - end if; - end "="; - - ------------------------- - -- Qualified_Name_Slug -- - ------------------------- - - function Qualified_Name_Slug (Name : Ada_Qualified_Name) return String - is - First : Boolean := True; - Result : Ada_Identifier; - begin - -- Create a unique slug from the qualified name: replace occurences of - -- 'z' with 'zz' and insert '_z_' between identifiers. - - for Id of Name loop - if First then - First := False; - else - Append (Result, "_z_"); - end if; - for I in 1 .. Length (Id) loop - declare - Char : constant Character := Element (Id, I); - begin - if Char in 'Z' | 'z' then - Append (Result, "zz"); - else - Append (Result, Char); - end if; - end; - end loop; - end loop; - return To_String (Result); - end Qualified_Name_Slug; - - ---------------------------- - -- Instrumented_Unit_Slug -- - ---------------------------- - - function Instrumented_Unit_Slug - (Instrumented_Unit : Compilation_Unit_Name) return String - is - begin - case Instrumented_Unit.Language_Kind is - when Unit_Based_Language => - declare - Result : Ada_Identifier; - begin - -- Add a single letter so that the spec and body of the same - -- unit don't conflict. - - Append (Result, Part_Tags (Instrumented_Unit.Part) & '_'); - - -- Append a unique suffix corresponding to the qualified name - -- of the unit to instrument. - - Append (Result, Qualified_Name_Slug (Instrumented_Unit.Unit)); - return To_String (Result); - end; - - when File_Based_Language => - declare - Result : Ada_Identifier; - begin - -- For a compilation unit in a file-based language, relying on - -- the filename only is not enough, as there can be multiple - -- sources with the same name belonging to different projects - -- in a project tree. To avoid name clashes, prepend the name - -- of the owning project to the computed slug. - - Append - (Result, - Qualified_Name_Slug - (To_Qualified_Name (+Instrumented_Unit.Project_Name))); - - -- Add an unambiguous separator between the project name and - -- the rest of the slug. - - Append (Result, "_z_z"); - - -- File names can contain characters that cannot appear in - -- identifiers. Furthermore, unlike for the identifier to - -- return, file names may be case sensitive. In order to - -- produce valid identifiers, encode everything that isn't a - -- lower case letter or a digit. - - for C of "+" (Instrumented_Unit.Filename) loop - if C in 'a' .. 'z' | '0' .. '9' then - Append (Result, C); - else - Append - (Result, - "_" & Hex_Image (Unsigned_8'(Character'Pos (C)))); - end if; - end loop; - - return To_String (Result); - end; - end case; - end Instrumented_Unit_Slug; - - ----------- - -- Image -- - ----------- - - function Image (CU_Name : Compilation_Unit_Name) return String is - begin - case CU_Name.Language_Kind is - when Unit_Based_Language => - return To_Ada (CU_Name.Unit) - & " " - & (case CU_Name.Part is - when Unit_Spec => "spec", - when Unit_Body => "body", - when Unit_Separate => "subunit"); - when File_Based_Language => - return +CU_Name.Filename; - end case; - end Image; - - ----------------------- - -- To_Qualified_Name -- - ----------------------- - - function To_Qualified_Name (Name : String) return Ada_Qualified_Name is - First : Positive := Name'First; - Unit : Ada_Qualified_Name; - begin - -- Split Ada qualified name into its components - - for J in Name'First .. Name'Last + 1 loop - if J = Name'Last + 1 or else Name (J) = '.' then - Unit.Append (To_Unbounded_String (Name (First .. J - 1))); - First := J + 1; - end if; - end loop; - return Unit; - end To_Qualified_Name; - - ------------------ - -- Canonicalize -- - ------------------ - - function Canonicalize (Name : Ada_Qualified_Name) return Ada_Qualified_Name - is - begin - return Result : Ada_Qualified_Name := Name do - for N of Result loop - N := To_Unbounded_String (To_Lower (To_String (N))); - end loop; - end return; - end Canonicalize; - - -------------------- - -- To_Symbol_Name -- - -------------------- - - function To_Symbol_Name (Name : Ada_Qualified_Name) return String is - Result : Unbounded_String; - begin - for Id of Name loop - if Length (Result) > 0 then - Append (Result, "_"); - end if; - Append (Result, To_Lower (To_String (Id))); - end loop; - - return +Result; - end To_Symbol_Name; - - ---------------------- - -- CU_Name_For_Unit -- - ---------------------- - - function CU_Name_For_Unit - (Unit : Ada_Qualified_Name; - Part : Unit_Parts) return Compilation_Unit_Name - is - begin - return (Unit_Based_Language, Unit, Part); - end CU_Name_For_Unit; - - ----------------------------- - -- CU_Name_For_File -- - ----------------------------- - - function CU_Name_For_File - (Filename : Unbounded_String; - Project_Name : Unbounded_String) return Compilation_Unit_Name - is - begin - return (File_Based_Language, Filename, Project_Name); - end CU_Name_For_File; - - ------------------------------ - -- To_Compilation_Unit_Name -- - ------------------------------ - - function To_Compilation_Unit_Name - (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Name - is - use GNATCOLL.VFS; - begin - case Language_Kind (To_Language (Source_File.Language)) is - when Unit_Based_Language => - return CU_Name_For_Unit - (Unit => To_Qualified_Name (Source_File.Unit_Name), - Part => Source_File.Unit_Part); - when File_Based_Language => - return CU_Name_For_File - (Filename => +GNATCOLL.VFS."+" (Source_File.File.Base_Name), - Project_Name => +Source_File.Project.Name); - end case; - end To_Compilation_Unit_Name; - - ----------------- - -- To_Filename -- - ----------------- - - function To_Filename - (Project : Project_Type; - CU_Name : Compilation_Unit_Name; - Language : Any_Language) return String - is - use GNATCOLL.VFS; - - begin - case CU_Name.Language_Kind is - when Unit_Based_Language => - return +Project.File_From_Unit - (Unit_Name => To_Ada (CU_Name.Unit), - Part => CU_Name.Part, - Language => Image (Language), - File_Must_Exist => False); - when File_Based_Language => - return +CU_Name.Filename; - end case; - end To_Filename; - - ---------------------------- - -- Find_Instrumented_Unit -- - ---------------------------- - - function Find_Instrumented_Unit - (CU_Name : Compilation_Unit_Name) return CU_Id - is - use Instrumented_Unit_To_CU_Maps; - - Position : constant Cursor := Instrumented_Unit_CUs.Find (CU_Name); - begin - if Has_Element (Position) then - return Element (Position); - else - return No_CU_Id; - end if; - end Find_Instrumented_Unit; - -end Instrument.Base_Types; diff --git a/tools/gnatcov/instrument-base_types.ads b/tools/gnatcov/instrument-base_types.ads deleted file mode 100644 index 711ec91c3..000000000 --- a/tools/gnatcov/instrument-base_types.ads +++ /dev/null @@ -1,166 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2008-2022, 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. -- ------------------------------------------------------------------------------- - --- Contains types to represent a compilation unit in the instrumentation --- process, with associated utilities. - -with Ada.Containers.Ordered_Maps; -with Ada.Containers.Vectors; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; - -with GNATCOLL.Projects; use GNATCOLL.Projects; - -with Types; use Types; - -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -with SC_Obligations; use SC_Obligations; -with Subprocesses; use Subprocesses; -with Switches; use Switches; - -package Instrument.Base_Types is - - function Language_Kind - (Language : Some_Language) return Any_Language_Kind; - -- Returns the language kind (unit-based or file-based) for the given - -- language. - - type Ada_Identifier is new Ada.Strings.Unbounded.Unbounded_String; - -- Simple Ada identifier - - package Ada_Identifier_Vectors is new Ada.Containers.Vectors - (Positive, Ada_Identifier); - - subtype Ada_Qualified_Name is Ada_Identifier_Vectors.Vector; - -- Sequence of ada identifiers, representing a qualified name. For - -- instance: Scope_A.Scope_B.Scope_C - - function "&" (Left, Right : Ada_Qualified_Name) return Ada_Qualified_Name - renames Ada_Identifier_Vectors."&"; - - function To_Ada (Name : Ada_Qualified_Name) return String - with Pre => not Name.Is_Empty; - -- Turn the given qualified name into Ada syntax - - type Compilation_Unit_Name - (Language_Kind : Any_Language_Kind := Unit_Based_Language) - is record - - case Language_Kind is - when Unit_Based_Language => - Unit : Ada_Qualified_Name := Ada_Identifier_Vectors.Empty_Vector; - Part : Unit_Parts := Unit_Body; - -- Identifies an Ada compilation unit (unit-based) - - when File_Based_Language => - Filename : US.Unbounded_String; - -- Fallback for file-based languages (like C). We will use the - -- simple filename for now. - - Project_Name : US.Unbounded_String; - -- We also need the project name as different projects can have - -- the same file. - - end case; - end record; - -- Unique identifier for an instrumented unit - - Part_Tags : constant array (Unit_Parts) of Character := - (Unit_Spec => 'S', - Unit_Body => 'B', - Unit_Separate => 'U'); - - function "=" (Left, Right : Compilation_Unit_Name) return Boolean; - - function "<" (Left, Right : Compilation_Unit_Name) return Boolean; - - function Image (CU_Name : Compilation_Unit_Name) return String; - -- Return a string representation of CU_Name for use in diagnostics - - function Qualified_Name_Slug (Name : Ada_Qualified_Name) return String; - -- Given a qualified name, return a unique identifier to describe it. This - -- identifier can be used as a filename suffix / unit name, as it does - -- not contain any '-'. - - function Instrumented_Unit_Slug - (Instrumented_Unit : Compilation_Unit_Name) return String; - -- Given a unit to instrument, return a unique identifier to describe it - -- (the so called slug). - -- - -- One can use this slug to generate unique names for this unit. - - function To_Qualified_Name (Name : String) return Ada_Qualified_Name; - -- Convert a String qualified name into our format - - function Canonicalize (Name : Ada_Qualified_Name) return Ada_Qualified_Name; - -- Fold casing of Ada identifiers - - function To_Symbol_Name (Name : Ada_Qualified_Name) return String - with Pre => not Name.Is_Empty; - -- Lower case each name of the qualified name, and joined them with an - -- underscore, to have a C-like syntax. - -- - -- Example: passing the qualified name Foo.Bar will return the string - -- "foo_bar". - - function CU_Name_For_Unit - (Unit : Ada_Qualified_Name; - Part : Unit_Parts) return Compilation_Unit_Name; - -- Return the compilation unit name for the Ada compilation unit - -- corresponding to the unit name and the unit part parameters. - - function CU_Name_For_File - (Filename : Unbounded_String; - Project_Name : Unbounded_String) return Compilation_Unit_Name; - -- Return the compilation unit name for the C translation unit - -- corresponding to the filename parameter. - - function To_Compilation_Unit_Name - (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Name; - -- Return the compilation unit name corresponding to the unit in - -- Source_File. - - function To_Filename - (Project : Project_Type; - CU_Name : Compilation_Unit_Name; - Language : Any_Language) return String; - -- Return the name of the file to contain the given compilation unit, - -- according to Project's naming scheme. - - package Instrumented_Unit_To_CU_Maps is new Ada.Containers.Ordered_Maps - (Key_Type => Compilation_Unit_Name, - Element_Type => CU_Id); - - Instrumented_Unit_CUs : Instrumented_Unit_To_CU_Maps.Map; - -- Associate a CU id for all instrumented units. Updated each time we - -- instrument a unit (or load a checkpoint) and used each time we read a - -- coverage buffer (or save to a checkpoint). - - package SFI_To_PP_Cmd_Maps is - new Ada.Containers.Ordered_Maps - (Key_Type => Source_File_Index, - Element_Type => Command_Type); - - PP_Cmds : SFI_To_PP_Cmd_Maps.Map; - -- Save the preprocessing command for each unit that supports it - - function Find_Instrumented_Unit - (CU_Name : Compilation_Unit_Name) return CU_Id; - -- Return the CU_Id corresponding to the given instrumented unit, or - -- No_CU_Id if not found. - -end Instrument.Base_Types; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 754baea18..be825090b 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -37,7 +37,6 @@ with Interfaces.C.Strings; use Interfaces.C.Strings; with ALI_Files; use ALI_Files; with Coverage; use Coverage; with Coverage_Options; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Hex_Images; use Hex_Images; with Inputs; use Inputs; with Instrument.C_Utils; use Instrument.C_Utils; @@ -45,7 +44,6 @@ with Outputs; use Outputs; with Paths; use Paths; with Project; use Project; with SCOs; -with Subprocesses; use Subprocesses; with System; use System; with Table; with Text_Files; use Text_Files; @@ -4289,9 +4287,7 @@ package body Instrument.C is overriding function Skip_Source_File (Self : C_Family_Instrumenter_Type; - Source_File : GNATCOLL.Projects.File_Info) return Boolean - is - use GNATCOLL.Projects; + Source_File : GNATCOLL.Projects.File_Info) return Boolean is begin -- Do not instrument C headers: code in C header is meant to be -- instrumented at the time it is included in a ".c" source. @@ -4660,7 +4656,6 @@ package body Instrument.C is -- if it is missing. declare - use GNATCOLL.Projects; use GNATCOLL.VFS; use Source_Of_Interest_Maps; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 3f3a98025..af0be0c00 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -29,17 +29,13 @@ with Ada.Strings.Unbounded.Hash; with GNATCOLL.Projects; with Namet; use Namet; -with Types; use Types; with Clang.Index; use Clang.Index; with Clang.Rewrite; use Clang.Rewrite; -with Files_Table; use Files_Table; -with Instrument.Base_Types; use Instrument.Base_Types; -with Instrument.Common; use Instrument.Common; -with SC_Obligations; use SC_Obligations; -with Slocs; use Slocs; -with Switches; use Switches; +with Files_Table; use Files_Table; +with Instrument.Common; use Instrument.Common; +with Slocs; use Slocs; package Instrument.C is diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index 6447bef4f..3d30db5f9 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -20,7 +20,6 @@ -- gnatcov is not built with C instrumentation support. with Instrument.Common; use Instrument.Common; -with Switches; use Switches; package Instrument.C is diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index b4388bbd9..f11b86b89 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -104,7 +104,7 @@ package body Instrument.C_Utils is File : aliased String_T; begin if Loc = Get_Null_Location then - return No_Location; + return Slocs.No_Location; end if; Get_Presumed_Location (Location => Loc, Filename => File'Access, diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index 0022f0265..abdc8c7e2 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -16,13 +16,9 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Diagnostics; use Diagnostics; -with Files_Table; use Files_Table; -with Instrument.Base_Types; use Instrument.Base_Types; -with Outputs; use Outputs; -with SC_Obligations; use SC_Obligations; -with Subprocesses; use Subprocesses; -with Types; use Types; +with Diagnostics; use Diagnostics; +with Files_Table; use Files_Table; +with Outputs; use Outputs; package body Instrument.Checkpoints is diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 30f468c2d..7293a2f1d 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -58,22 +58,14 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Hash; with Ada.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; -with GNAT.Regexp; - -with GNATCOLL.Projects; use GNATCOLL.Projects; with GNATCOLL.VFS; with ALI_Files; use ALI_Files; with Files_Table; use Files_Table; with GNATcov_RTS; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -with Instrument.Base_Types; use Instrument.Base_Types; with Namet; use Namet; -with SC_Obligations; use SC_Obligations; with Slocs; use Slocs; -with Switches; use Switches; with Text_Files; -with Types; use Types; package Instrument.Common is diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index c750a7ad1..a95b11453 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -30,8 +30,6 @@ with System.Storage_Elements; with GNAT.OS_Lib; use GNAT.OS_Lib; with GNAT.Byte_Swapping; use GNAT.Byte_Swapping; -with GNATCOLL.Projects; use GNATCOLL.Projects; - with Traces_Source; use Traces_Source; with Hex_Images; with Outputs; diff --git a/tools/gnatcov/instrument-input_traces.ads b/tools/gnatcov/instrument-input_traces.ads index f1fe7c1b7..7c8d7137c 100644 --- a/tools/gnatcov/instrument-input_traces.ads +++ b/tools/gnatcov/instrument-input_traces.ads @@ -18,8 +18,6 @@ -- Source trace files decoding -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -with Instrument.Base_Types; use Instrument.Base_Types; with SC_Obligations; with Traces_Files; with Traces_Source; diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 67ee8ecf4..0ef2f2eec 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -18,40 +18,407 @@ -- Source instrumentation +with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Containers; use Ada.Containers; with Ada.Containers.Indefinite_Ordered_Maps; -with Ada.Containers.Ordered_Maps; -with Ada.Containers.Vectors; with Ada.Directories; with Ada.Exceptions; with Ada.Strings.Fixed; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; -with Ada.Text_IO; use Ada.Text_IO; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Strings.Unbounded.Equal_Case_Insensitive; +with Ada.Strings.Unbounded.Less_Case_Insensitive; with Ada.Unchecked_Deallocation; +with Interfaces; use Interfaces; with GNAT.OS_Lib; -with GNATCOLL.Projects; use GNATCOLL.Projects; -with GNATCOLL.JSON; use GNATCOLL.JSON; -with GNATCOLL.VFS; use GNATCOLL.VFS; +with GNATCOLL.JSON; use GNATCOLL.JSON; +with GNATCOLL.VFS; use GNATCOLL.VFS; with Checkpoints; with Coverage; with Files_Table; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with Hex_Images; use Hex_Images; with Instrument.Ada_Unit; -with Instrument.Base_Types; use Instrument.Base_Types; with Instrument.Clean_Objdirs; with Instrument.C; -with Instrument.Common; use Instrument.Common; -with JSON; use JSON; +with Instrument.Common; use Instrument.Common; +with JSON; use JSON; with Outputs; -with Paths; use Paths; -with Project; use Project; -with SC_Obligations; -with Switches; use Switches; +with Paths; use Paths; +with Project; package body Instrument is + ------------------- + -- Language_Kind -- + ------------------- + + function Language_Kind (Language : Some_Language) return Any_Language_Kind + is + begin + return (case Language is + when Ada_Language => Unit_Based_Language, + when C_Language + | CPP_Language => File_Based_Language); + end Language_Kind; + + ------------ + -- To_Ada -- + ------------ + + function To_Ada (Name : Ada_Qualified_Name) return String is + Result : Unbounded_String; + begin + for Id of Name loop + if Length (Result) > 0 then + Append (Result, "."); + end if; + Append (Result, To_String (Id)); + end loop; + + return +Result; + end To_Ada; + + --------- + -- "<" -- + --------- + + function "<" (Left, Right : Compilation_Unit_Name) return Boolean is + begin + if Left.Language_Kind = Right.Language_Kind then + case Left.Language_Kind is + when Unit_Based_Language => + if Left.Part = Right.Part then + if Left.Unit.Length = Right.Unit.Length then + for I in 1 .. Integer (Left.Unit.Length) loop + declare + Left_Id : constant Unbounded_String := + Unbounded_String (Left.Unit.Element (I)); + Right_Id : constant Unbounded_String := + Unbounded_String (Right.Unit.Element (I)); + begin + if not Equal_Case_Insensitive (Left_Id, Right_Id) + then + return Less_Case_Insensitive (Left_Id, Right_Id); + end if; + end; + end loop; + + -- If we get there, they are equal + + return False; + else + return Left.Unit.Length < Right.Unit.Length; + end if; + else + return Left.Part < Right.Part; + end if; + when File_Based_Language => + if Equal_Case_Insensitive + (Left.Project_Name, Right.Project_Name) + then + return Left.Filename < Right.Filename; + else + return Less_Case_Insensitive + (Left.Project_Name, Right.Project_Name); + end if; + end case; + else + return Left.Language_Kind < Right.Language_Kind; + end if; + end "<"; + + --------- + -- "=" -- + --------- + + function "=" (Left, Right : Compilation_Unit_Name) return Boolean + is + use Ada_Identifier_Vectors; + begin + if Left.Language_Kind = Right.Language_Kind then + case Left.Language_Kind is + when Unit_Based_Language => + if Left.Part = Right.Part + and then Left.Unit.Length = Right.Unit.Length + then + for I in 1 .. Integer (Left.Unit.Length) loop + if not Equal_Case_Insensitive + (Unbounded_String (Left.Unit.Element (I)), + Unbounded_String (Right.Unit.Element (I))) + then + return False; + end if; + end loop; + + -- If we get there, they are equal + + return True; + end if; + return False; + when File_Based_Language => + return Left.Filename = Right.Filename + and then Equal_Case_Insensitive + (Left.Project_Name, Right.Project_Name); + end case; + else + return False; + end if; + end "="; + + ------------------------- + -- Qualified_Name_Slug -- + ------------------------- + + function Qualified_Name_Slug (Name : Ada_Qualified_Name) return String + is + First : Boolean := True; + Result : Ada_Identifier; + begin + -- Create a unique slug from the qualified name: replace occurences of + -- 'z' with 'zz' and insert '_z_' between identifiers. + + for Id of Name loop + if First then + First := False; + else + Append (Result, "_z_"); + end if; + for I in 1 .. Length (Id) loop + declare + Char : constant Character := Element (Id, I); + begin + if Char in 'Z' | 'z' then + Append (Result, "zz"); + else + Append (Result, Char); + end if; + end; + end loop; + end loop; + return To_String (Result); + end Qualified_Name_Slug; + + ---------------------------- + -- Instrumented_Unit_Slug -- + ---------------------------- + + function Instrumented_Unit_Slug + (Instrumented_Unit : Compilation_Unit_Name) return String + is + begin + case Instrumented_Unit.Language_Kind is + when Unit_Based_Language => + declare + Result : Ada_Identifier; + begin + -- Add a single letter so that the spec and body of the same + -- unit don't conflict. + + Append (Result, Part_Tags (Instrumented_Unit.Part) & '_'); + + -- Append a unique suffix corresponding to the qualified name + -- of the unit to instrument. + + Append (Result, Qualified_Name_Slug (Instrumented_Unit.Unit)); + return To_String (Result); + end; + + when File_Based_Language => + declare + Result : Ada_Identifier; + begin + -- For a compilation unit in a file-based language, relying on + -- the filename only is not enough, as there can be multiple + -- sources with the same name belonging to different projects + -- in a project tree. To avoid name clashes, prepend the name + -- of the owning project to the computed slug. + + Append + (Result, + Qualified_Name_Slug + (To_Qualified_Name (+Instrumented_Unit.Project_Name))); + + -- Add an unambiguous separator between the project name and + -- the rest of the slug. + + Append (Result, "_z_z"); + + -- File names can contain characters that cannot appear in + -- identifiers. Furthermore, unlike for the identifier to + -- return, file names may be case sensitive. In order to + -- produce valid identifiers, encode everything that isn't a + -- lower case letter or a digit. + + for C of "+" (Instrumented_Unit.Filename) loop + if C in 'a' .. 'z' | '0' .. '9' then + Append (Result, C); + else + Append + (Result, + "_" & Hex_Image (Unsigned_8'(Character'Pos (C)))); + end if; + end loop; + + return To_String (Result); + end; + end case; + end Instrumented_Unit_Slug; + + ----------- + -- Image -- + ----------- + + function Image (CU_Name : Compilation_Unit_Name) return String is + begin + case CU_Name.Language_Kind is + when Unit_Based_Language => + return To_Ada (CU_Name.Unit) + & " " + & (case CU_Name.Part is + when Unit_Spec => "spec", + when Unit_Body => "body", + when Unit_Separate => "subunit"); + when File_Based_Language => + return +CU_Name.Filename; + end case; + end Image; + + ----------------------- + -- To_Qualified_Name -- + ----------------------- + + function To_Qualified_Name (Name : String) return Ada_Qualified_Name is + First : Positive := Name'First; + Unit : Ada_Qualified_Name; + begin + -- Split Ada qualified name into its components + + for J in Name'First .. Name'Last + 1 loop + if J = Name'Last + 1 or else Name (J) = '.' then + Unit.Append (To_Unbounded_String (Name (First .. J - 1))); + First := J + 1; + end if; + end loop; + return Unit; + end To_Qualified_Name; + + ------------------ + -- Canonicalize -- + ------------------ + + function Canonicalize (Name : Ada_Qualified_Name) return Ada_Qualified_Name + is + begin + return Result : Ada_Qualified_Name := Name do + for N of Result loop + N := To_Unbounded_String (To_Lower (To_String (N))); + end loop; + end return; + end Canonicalize; + + -------------------- + -- To_Symbol_Name -- + -------------------- + + function To_Symbol_Name (Name : Ada_Qualified_Name) return String is + Result : Unbounded_String; + begin + for Id of Name loop + if Length (Result) > 0 then + Append (Result, "_"); + end if; + Append (Result, To_Lower (To_String (Id))); + end loop; + + return +Result; + end To_Symbol_Name; + + ---------------------- + -- CU_Name_For_Unit -- + ---------------------- + + function CU_Name_For_Unit + (Unit : Ada_Qualified_Name; + Part : Unit_Parts) return Compilation_Unit_Name + is + begin + return (Unit_Based_Language, Unit, Part); + end CU_Name_For_Unit; + + ----------------------------- + -- CU_Name_For_File -- + ----------------------------- + + function CU_Name_For_File + (Filename : Unbounded_String; + Project_Name : Unbounded_String) return Compilation_Unit_Name + is + begin + return (File_Based_Language, Filename, Project_Name); + end CU_Name_For_File; + + ------------------------------ + -- To_Compilation_Unit_Name -- + ------------------------------ + + function To_Compilation_Unit_Name + (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Name + is + begin + case Language_Kind (To_Language (Source_File.Language)) is + when Unit_Based_Language => + return CU_Name_For_Unit + (Unit => To_Qualified_Name (Source_File.Unit_Name), + Part => Source_File.Unit_Part); + when File_Based_Language => + return CU_Name_For_File + (Filename => +GNATCOLL.VFS."+" (Source_File.File.Base_Name), + Project_Name => +Source_File.Project.Name); + end case; + end To_Compilation_Unit_Name; + + ----------------- + -- To_Filename -- + ----------------- + + function To_Filename + (Project : Project_Type; + CU_Name : Compilation_Unit_Name; + Language : Any_Language) return String is + begin + case CU_Name.Language_Kind is + when Unit_Based_Language => + return +Project.File_From_Unit + (Unit_Name => To_Ada (CU_Name.Unit), + Part => CU_Name.Part, + Language => Image (Language), + File_Must_Exist => False); + when File_Based_Language => + return +CU_Name.Filename; + end case; + end To_Filename; + + ---------------------------- + -- Find_Instrumented_Unit -- + ---------------------------- + + function Find_Instrumented_Unit + (CU_Name : Compilation_Unit_Name) return CU_Id + is + use Instrumented_Unit_To_CU_Maps; + + Position : constant Cursor := Instrumented_Unit_CUs.Find (CU_Name); + begin + if Has_Element (Position) then + return Element (Position); + else + return No_CU_Id; + end if; + end Find_Instrumented_Unit; + package GPR renames GNATCOLL.Projects; type CU_Name_With_Ignore is record @@ -128,60 +495,6 @@ package body Instrument is -- Make sure we have the expected tree of directories for the -- instrumentation output. - ----------- - -- Image -- - ----------- - - function Image (Dump_Trigger : Any_Dump_Trigger) return String is - begin - return (case Dump_Trigger is - when Manual => "manual", - when At_Exit => "atexit", - when Ravenscar_Task_Termination => "ravenscar-task-termination", - when Main_End => "main-end"); - end Image; - - function Image (Dump_Channel : Any_Dump_Channel) return String is - begin - return (case Dump_Channel is - when Binary_File => "bin-file", - when Base64_Standard_Output => "base64-stdout"); - end Image; - - ----------- - -- Value -- - ----------- - - function Value (Dump_Trigger : String) return Any_Dump_Trigger is - begin - if Dump_Trigger = "manual" then - return Manual; - elsif Dump_Trigger = "atexit" then - return At_Exit; - elsif Dump_Trigger = "ravenscar-task-termination" then - return Ravenscar_Task_Termination; - elsif Dump_Trigger = "main-end" then - return Main_End; - else - return - (raise Constraint_Error - with "invalid dump trigger: " & Dump_Trigger); - end if; - end Value; - - function Value (Dump_Channel : String) return Any_Dump_Channel is - begin - if Dump_Channel = "bin-file" then - return Binary_File; - elsif Dump_Channel = "base64-stdout" then - return Base64_Standard_Output; - else - return - (raise Constraint_Error - with "invalid dump channel: " & Dump_Channel); - end if; - end Value; - ------------------- -- Get_Or_Create -- ------------------- @@ -441,8 +754,6 @@ package body Instrument is end; end Add_Instrumented_Unit_Wrapper; - use type Ada.Containers.Count_Type; - -- Start of processing for Instrument_Units_Of_Interest begin diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index f09e0e692..8596dfb96 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -18,70 +18,156 @@ -- Support for source instrumentation +with Ada.Containers.Ordered_Maps; +with Ada.Containers.Vectors; with Ada.Strings.Unbounded; with GNAT.Regexp; -with Strings; use Strings; +with GNATCOLL.Projects; use GNATCOLL.Projects; + +with Types; use Types; + +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with SC_Obligations; use SC_Obligations; +with Subprocesses; use Subprocesses; +with Strings; use Strings; +with Switches; use Switches; package Instrument is package US renames Ada.Strings.Unbounded; - type Any_Dump_Trigger is - (Manual, At_Exit, Ravenscar_Task_Termination, Main_End); - -- Trigger to dump coverage buffers in instrumented programs. See the user - -- documentation for the --dump-trigger command-line option. + function Language_Kind + (Language : Some_Language) return Any_Language_Kind; + -- Returns the language kind (unit-based or file-based) for the given + -- language. + + type Ada_Identifier is new Ada.Strings.Unbounded.Unbounded_String; + -- Simple Ada identifier - subtype Auto_Dump_Trigger is Any_Dump_Trigger range At_Exit .. Main_End; + package Ada_Identifier_Vectors is new Ada.Containers.Vectors + (Positive, Ada_Identifier); - type Any_Dump_Channel is (Binary_File, Base64_Standard_Output); - -- Channel where to dump coverage buffers. See the user documentation for - -- the --dump-channel command-line option. + subtype Ada_Qualified_Name is Ada_Identifier_Vectors.Vector; + -- Sequence of ada identifiers, representing a qualified name. For + -- instance: Scope_A.Scope_B.Scope_C - -- Serialization/deserialization functions for the enumeration types. The - -- deserialization ones raise Constraint_Error exceptions for invalid input - -- strings. + function "&" (Left, Right : Ada_Qualified_Name) return Ada_Qualified_Name + renames Ada_Identifier_Vectors."&"; - function Image (Dump_Trigger : Any_Dump_Trigger) return String; - function Image (Dump_Channel : Any_Dump_Channel) return String; - function Value (Dump_Trigger : String) return Any_Dump_Trigger; - function Value (Dump_Channel : String) return Any_Dump_Channel; + function To_Ada (Name : Ada_Qualified_Name) return String + with Pre => not Name.Is_Empty; + -- Turn the given qualified name into Ada syntax - type Any_Dump_Config (Channel : Any_Dump_Channel := Any_Dump_Channel'First) + type Compilation_Unit_Name + (Language_Kind : Any_Language_Kind := Unit_Based_Language) is record - Trigger : Any_Dump_Trigger := Manual; - - case Channel is - when Binary_File => - Filename_Simple : Boolean := False; - -- Whether to generate source traces with simple filenames. - -- - -- Controlled by --dump-filename-simple. - - Filename_Env_Var : US.Unbounded_String; - -- Name of the environment variable which, if set, contains the - -- default filename for created source traces. If empty, use the - -- default one (see Default_Trace_Filename_Env_Var in - -- GNATcov_RTS.Traces.Output.Files). - -- - -- Controlled by --dump-filename-env-var. - - Filename_Prefix : US.Unbounded_String; - -- Prefix for the source trace filename. If empty, use the - -- program's basename (see Default_Trace_Filename_Prefix in - -- GNATcov_RTS.Traces.Output.Files). - -- - -- Controlled by --dump-filename-prefix. - - when others => - null; + + case Language_Kind is + when Unit_Based_Language => + Unit : Ada_Qualified_Name := Ada_Identifier_Vectors.Empty_Vector; + Part : Unit_Parts := Unit_Body; + -- Identifies an Ada compilation unit (unit-based) + + when File_Based_Language => + Filename : US.Unbounded_String; + -- Fallback for file-based languages (like C). We will use the + -- simple filename for now. + + Project_Name : US.Unbounded_String; + -- We also need the project name as different projects can have + -- the same file. + end case; end record; - -- Bundle for all configuration related to automatic dump of coverage - -- buffers. + -- Unique identifier for an instrumented unit + + Part_Tags : constant array (Unit_Parts) of Character := + (Unit_Spec => 'S', + Unit_Body => 'B', + Unit_Separate => 'U'); + + function "=" (Left, Right : Compilation_Unit_Name) return Boolean; - type Any_Language_Version is (Ada_83, Ada_95, Ada_2005, Ada_2012, Ada_2022); + function "<" (Left, Right : Compilation_Unit_Name) return Boolean; + -- Compare the result of a call to Instrumented_Unit_Slug (which gives + -- unique identifiers for each compilation unit name) for both operands. + + function Image (CU_Name : Compilation_Unit_Name) return String; + -- Return a string representation of CU_Name for use in diagnostics + + function Qualified_Name_Slug (Name : Ada_Qualified_Name) return String; + -- Given a qualified name, return a unique identifier to describe it. This + -- identifier can be used as a filename suffix / unit name, as it does + -- not contain any '-'. + + function Instrumented_Unit_Slug + (Instrumented_Unit : Compilation_Unit_Name) return String; + -- Given a unit to instrument, return a unique identifier to describe it + -- (the so called slug). + -- + -- One can use this slug to generate unique names for this unit. + + function To_Qualified_Name (Name : String) return Ada_Qualified_Name; + -- Convert a String qualified name into our format + + function Canonicalize (Name : Ada_Qualified_Name) return Ada_Qualified_Name; + -- Fold casing of Ada identifiers + + function To_Symbol_Name (Name : Ada_Qualified_Name) return String + with Pre => not Name.Is_Empty; + -- Lower case each name of the qualified name, and joined them with an + -- underscore, to have a C-like syntax. + -- + -- Example: passing the qualified name Foo.Bar will return the string + -- "foo_bar". + + function CU_Name_For_Unit + (Unit : Ada_Qualified_Name; + Part : Unit_Parts) return Compilation_Unit_Name; + -- Return the compilation unit name for the Ada compilation unit + -- corresponding to the unit name and the unit part parameters. + + function CU_Name_For_File + (Filename : US.Unbounded_String; + Project_Name : US.Unbounded_String) return Compilation_Unit_Name; + -- Return the compilation unit name for the C translation unit + -- corresponding to the filename parameter. + + function To_Compilation_Unit_Name + (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Name; + -- Return the compilation unit name corresponding to the unit in + -- Source_File. + + function To_Filename + (Project : Project_Type; + CU_Name : Compilation_Unit_Name; + Language : Any_Language) return String; + -- Return the name of the file to contain the given compilation unit, + -- according to Project's naming scheme. + + package Instrumented_Unit_To_CU_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Compilation_Unit_Name, + Element_Type => CU_Id); + + Instrumented_Unit_CUs : Instrumented_Unit_To_CU_Maps.Map; + -- Associate a CU id for all instrumented units. Updated each time we + -- instrument a unit (or load a checkpoint) and used each time we read a + -- coverage buffer (or save to a checkpoint). + + package SFI_To_PP_Cmd_Maps is + new Ada.Containers.Ordered_Maps + (Key_Type => Source_File_Index, + Element_Type => Command_Type); + + PP_Cmds : SFI_To_PP_Cmd_Maps.Map; + -- Save the preprocessing command for each unit that supports it + + function Find_Instrumented_Unit + (CU_Name : Compilation_Unit_Name) return CU_Id; + -- Return the CU_Id corresponding to the given instrumented unit, or + -- No_CU_Id if not found. procedure Instrument_Units_Of_Interest (Dump_Config : Any_Dump_Config; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 29b714787..39e6d4fb1 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -34,11 +34,11 @@ with GNATCOLL.Traces; with GNATCOLL.Projects.Aux; with GNATCOLL.VFS; use GNATCOLL.VFS; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -with Instrument.Base_Types; use Instrument.Base_Types; -with Inputs; use Inputs; -with Outputs; use Outputs; -with Paths; use Paths; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with Instrument; use Instrument; +with Inputs; use Inputs; +with Outputs; use Outputs; +with Paths; use Paths; package body Project is diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 247a607f8..2af89144e 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -41,7 +41,6 @@ with Outputs; use Outputs; with Paths; use Paths; with Subprocesses; use Subprocesses; with Support_Files; -with Switches; use Switches; with Temp_Dirs; use Temp_Dirs; with Text_Files; diff --git a/tools/gnatcov/setup_rts.ads b/tools/gnatcov/setup_rts.ads index c3173959e..c583afdf0 100644 --- a/tools/gnatcov/setup_rts.ads +++ b/tools/gnatcov/setup_rts.ads @@ -20,8 +20,8 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; -with Instrument; use Instrument; -with Strings; use Strings; +with Strings; use Strings; +with Switches; use Switches; package Setup_RTS is diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 668ce9554..6a81218ff 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -19,7 +19,6 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Command_Line; with Ada.Exceptions; -with Ada.Strings.Unbounded; with Outputs; use Outputs; with Project; use Project; @@ -497,6 +496,60 @@ package body Switches is Copy_Arg (Opt_Config, CGPR_File); end Parse_Arguments; + ----------- + -- Image -- + ----------- + + function Image (Dump_Trigger : Any_Dump_Trigger) return String is + begin + return (case Dump_Trigger is + when Manual => "manual", + when At_Exit => "atexit", + when Ravenscar_Task_Termination => "ravenscar-task-termination", + when Main_End => "main-end"); + end Image; + + function Image (Dump_Channel : Any_Dump_Channel) return String is + begin + return (case Dump_Channel is + when Binary_File => "bin-file", + when Base64_Standard_Output => "base64-stdout"); + end Image; + + ----------- + -- Value -- + ----------- + + function Value (Dump_Trigger : String) return Any_Dump_Trigger is + begin + if Dump_Trigger = "manual" then + return Manual; + elsif Dump_Trigger = "atexit" then + return At_Exit; + elsif Dump_Trigger = "ravenscar-task-termination" then + return Ravenscar_Task_Termination; + elsif Dump_Trigger = "main-end" then + return Main_End; + else + return + (raise Constraint_Error + with "invalid dump trigger: " & Dump_Trigger); + end if; + end Value; + + function Value (Dump_Channel : String) return Any_Dump_Channel is + begin + if Dump_Channel = "bin-file" then + return Binary_File; + elsif Dump_Channel = "base64-stdout" then + return Base64_Standard_Output; + else + return + (raise Constraint_Error + with "invalid dump channel: " & Dump_Channel); + end if; + end Value; + --------------------- -- Common_Switches -- --------------------- diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 458563518..2c259b2af 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -17,6 +17,7 @@ ------------------------------------------------------------------------------ with Ada.Containers.Indefinite_Ordered_Maps; +with Ada.Strings.Unbounded; with GNAT.Strings; use GNAT.Strings; @@ -24,7 +25,6 @@ with Calendar_Utils; use Calendar_Utils; with Command_Line; use Command_Line; with Command_Line_Support; use Command_Line_Support; with Inputs; -with Instrument; use Instrument; with Strings; use Strings; package Switches is @@ -59,11 +59,6 @@ package Switches is List : in out Inputs.Inputs_Type); -- Copy the list of strings referenced in Option to the List input list - function Load_Dump_Config - (Default_Dump_Config : Any_Dump_Config) return Any_Dump_Config; - -- Create the Any_Dump_Config value corresponding to Default_Dump_Config - -- and the given --dump-* arguments for source trace dumping. - ---------------------------- -- Miscellaneous switches -- ---------------------------- @@ -214,7 +209,69 @@ package Switches is Debug_Switches (Ignore_Exemptions); Debug_File_Table : Boolean renames - Debug_Switches (File_Table); + Debug_Switches (File_Table); + + --------------------------------------- + -- Instrumentation-related switches -- + --------------------------------------- + + type Any_Language_Version is (Ada_83, Ada_95, Ada_2005, Ada_2012, Ada_2022); + + type Any_Dump_Trigger is + (Manual, At_Exit, Ravenscar_Task_Termination, Main_End); + -- Trigger to dump coverage buffers in instrumented programs. See the user + -- documentation for the --dump-trigger command-line option. + + subtype Auto_Dump_Trigger is Any_Dump_Trigger range At_Exit .. Main_End; + + type Any_Dump_Channel is (Binary_File, Base64_Standard_Output); + -- Channel where to dump coverage buffers. See the user documentation for + -- the --dump-channel command-line option. + + -- Serialization/deserialization functions for the enumeration types. The + -- deserialization ones raise Constraint_Error exceptions for invalid input + -- strings. + + function Image (Dump_Trigger : Any_Dump_Trigger) return String; + function Image (Dump_Channel : Any_Dump_Channel) return String; + function Value (Dump_Trigger : String) return Any_Dump_Trigger; + function Value (Dump_Channel : String) return Any_Dump_Channel; + + type Any_Dump_Config (Channel : Any_Dump_Channel := Any_Dump_Channel'First) + is record + Trigger : Any_Dump_Trigger := Manual; + + case Channel is + when Binary_File => + Filename_Simple : Boolean := False; + -- Whether to generate source traces with simple filenames. + -- + -- Controlled by --dump-filename-simple. + + Filename_Env_Var : Ada.Strings.Unbounded.Unbounded_String; + -- Name of the environment variable which, if set, contains the + -- default filename for created source traces. If empty, use the + -- default one (see Default_Trace_Filename_Env_Var in + -- GNATcov_RTS.Traces.Output.Files). + -- + -- Controlled by --dump-filename-env-var. + + Filename_Prefix : Ada.Strings.Unbounded.Unbounded_String; + -- Prefix for the source trace filename. If empty, use the + -- program's basename (see Default_Trace_Filename_Prefix in + -- GNATcov_RTS.Traces.Output.Files). + -- + -- Controlled by --dump-filename-prefix. + + when others => + null; + end case; + end record; + + function Load_Dump_Config + (Default_Dump_Config : Any_Dump_Config) return Any_Dump_Config; + -- Create the Any_Dump_Config value corresponding to Default_Dump_Config + -- and the given --dump-* arguments for source trace dumping. function Common_Switches (Cmd : Command_Line.Command_Type) return String_Vectors.Vector; From 2e70558b3d54d66a81a916db0836faea9bf6cbbd Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Thu, 13 Apr 2023 11:18:32 +0000 Subject: [PATCH 0266/1483] Fix testsuite.py setting of TARGET variable for libsupport The move to a more systematic build of libsupport brought a change in the value used to set the TARGET variable, from self.env.target.triplet to args.target just for consistency with how other variables were set. This was actually inappropriate as the variable is used as a --target gprbuild switch and args.target may contain extensions not fit for that use. Revert to the previous source of value and to a more canonical way to guard such references (self.env.is_cross). Part of work for issue eng/cov/gnatcoverage#3 --- testsuite/testsuite.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 64a9acb47..6b544e523 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1094,8 +1094,13 @@ def _build_libsupport(self): libsup_vars = [] - if args.target: - libsup_vars.append("TARGET={}".format(args.target)) + if self.env.is_cross: + # Beware that the TARGET variable set here is used as the + # --target switch to gprbuild calls from the Makefile, and + # the args.target value we receive might have os-version + # or machine extensions that aren't appropriate for that + # (e.g. aarch64-elf,unknown). + libsup_vars.append("TARGET={}".format(self.env.target.triplet)) if args.board: libsup_vars.append("BOARD={}".format(args.board)) From 488a854f1f3acfdf70abbedf211d797a0234dff2 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 31 Mar 2023 17:46:18 +0200 Subject: [PATCH 0267/1483] Introduce an instrumented build of gnatcov --- tools/gnatcov/Makefile | 25 ++++++++++++++++++++++++- tools/gnatcov/gnatcov.gpr | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index 5d0c497eb..4de3b3841 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -213,10 +213,33 @@ bin: exit 1; \ fi -# Start with the 64-bit gnatcov, which has the largest closure +ifdef INSTRUMENTED + # We need to instrument and build at the same time: the driver and gnatcov32 + # builds share the same object directory, meaning that gnatcov will remove + # files resulting from the instrumentation of gnatcov32 when instrumenting + # the driver. This will be a problem: in the former case, + # gnatcov_bits_specific.adb is instrumented as a main but not in the latter + # case (gnatcov.adb is). This means that if we use the version that was not + # instrumented as a main to compile gnatcov32, running gnatcov32 will not + # dump execution traces. + + gnatcov instrument -P gnatcov.gpr -XPART=gnatcov64 + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 \ + --src-subdirs=gnatcov-instr + + gnatcov instrument -P gnatcov.gpr -XPART=gnatcov32 + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov32 \ + --src-subdirs=gnatcov-instr + + gnatcov instrument -P gnatcov.gpr -XPART=driver + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver \ + --src-subdirs=gnatcov-instr +else + # Start with the 64-bit gnatcov, which has the largest closure $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov32 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver +endif ADAPTER_TARGETS=$(foreach a, $(ADAPTERS_LIST), adapter-$(a)) .PHONY: $(ADAPTERS_TARGETS) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 7e1a65cfe..b58c3bbf7 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -126,6 +126,44 @@ project Gnatcov is for Body_Suffix ("C++") use ".cc"; end Naming; + package Coverage is + + -- Ignore units that have an alternative implementation in both parts + -- and that consists only in type definitions. GNATcoverage does not + -- yet support consolidation when there are units with a different + -- implementation. + + Gnatcoverage_Excluded_Units := ("arch", "dis*", "qemu_traces_entries"); + + -- Also ignore the instrumentation part in the 32 bits part, consisting + -- only in stubs. + + case Part is + when "lib32" | "lib64" | "driver" | "gnatcov32" => + Gnatcoverage_Excluded_Units := Gnatcoverage_Excluded_Units + & ("instrument*"); + when "gnatcov64" => + null; + end case; + for Excluded_Units use Gnatcoverage_Excluded_Units; + + Common_Switches := ("--level=stmt", "--no-subprojects"); + for Switches ("instrument") use Common_Switches + + -- Include the part as a trace filename prefix to differentiate + -- traces produced by the execution of the driver / gnatcov32 / + -- gnatcov64 + + & ("--dump-filename-prefix=" & Part) + + -- Also rename the filename environment variable to avoid conflicting + -- with instrumented tests in the testing environment. + + & ("--dump-filename-env-var=GNATCOV_TRACE_DIR"); + + for Switches ("coverage") use Common_Switches; + end Coverage; + ---------------------------- -- Configuration of mains -- ---------------------------- From cbb5f9b80b38b281f9c8342d733bb670fc274ce5 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 31 Mar 2023 12:38:26 +0000 Subject: [PATCH 0268/1483] Update .gitlab-ci.yml file --- .gitlab-ci.yml | 47 ++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0fc152d20..261140f7a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -50,7 +50,7 @@ build: - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR # Build using anod - - anod build --minimal gnatcov $EDGE_QUALIFIER + - anod build --minimal gnatcov -Qinstr $EDGE_QUALIFIER # Create the package - tar czf $PACKAGE_ABSOLUTE_NAME -C / @@ -63,6 +63,23 @@ build: paths: - $PACKAGE_BASE_NAME +build_standard: + services: + - image:sandbox + - cpu:8 + - mem:16 + stage: test + script: + - export PATH=/it/e3/bin:$PATH + - *edge_vars + + # Setup the repository + - cd /it/wave + - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR + + # Build using anod + - anod build --minimal gnatcov $EDGE_QUALIFIER + build_community: services: - image:sandbox @@ -112,15 +129,23 @@ build_community: # download the nightly one, which may not even exist (case of an edge build # failure that was fixed on that day). - mkdir -p fingerprints - - touch fingerprints/x86_64-linux.gnatcov-build$EDGE_BUILD_SPACE_SUFFIX.install.json.assume-unchanged - - touch fingerprints/x86_64-linux.gnatcov-build$EDGE_BUILD_SPACE_SUFFIX.download_bin.json.assume-unchanged + - touch fingerprints/x86_64-linux.gnatcov-instr-build$EDGE_BUILD_SPACE_SUFFIX.install.json.assume-unchanged + - touch fingerprints/x86_64-linux.gnatcov-instr-build$EDGE_BUILD_SPACE_SUFFIX.download_bin.json.assume-unchanged + + # Setup the CI directory to host coverage results + - mkdir $CI_PROJECT_DIR/coverage .common_artifacts_bits: &artifacts artifacts: paths: - xunit_output.xml + - coverage/cobertura.xml + reports: junit: xunit_output.xml + coverage_report: + coverage_format: cobertura + path: coverage/cobertura.xml test_bin_traces: services: @@ -132,12 +157,13 @@ test_bin_traces: - *retrieve_gnatcoverage_extras_and_setup_anod_repo # Test using anod - - anod test gnatcov --target=leon3-elf -QRTS=embedded-leon3,-O0 $EDGE_QUALIFIER + - anod test gnatcov --target=leon3-elf -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name bin-traces - leon3-elf-linux64/gnatcov-O0-embedded-leon3$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ + leon3-elf-linux64/gnatcov-O0-embedded-leon3-instr$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ + - mv leon3-elf-linux64/gnatcov-O0-embedded-leon3-instr$EDGE_BUILD_SPACE_SUFFIX-test/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml <<: *artifacts @@ -151,12 +177,14 @@ test_src_traces: - *retrieve_gnatcoverage_extras_and_setup_anod_repo # Test using anod - - anod test gnatcov -Qsrc-traces $EDGE_QUALIFIER + - anod test gnatcov -Qsrc-traces,instr $EDGE_QUALIFIER - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name src-traces - x86_64-linux/gnatcov-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ + x86_64-linux/gnatcov-instr-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ + - cat /it/wave/log/x86_64-linux.gnatcov-instr-src-traces-test.test.log + - mv x86_64-linux/gnatcov-instr-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml <<: *artifacts @@ -170,11 +198,12 @@ test_spark: - *retrieve_gnatcoverage_extras_and_setup_anod_repo # Test using anod - - anod test gnatcov -Qspark-tests,src-traces $EDGE_QUALIFIER + - anod test gnatcov -Qspark-tests,src-traces,instr $EDGE_QUALIFIER - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name spark - x86_64-linux/gnatcov-spark-tests-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ + x86_64-linux/gnatcov-instr-spark-tests-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ + - mv x86_64-linux/gnatcov-instr-spark-tests-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml <<: *artifacts From cd204bee3109fab34dbc8454e060c8815c3cee55 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 14 Apr 2023 12:56:21 +0200 Subject: [PATCH 0269/1483] Use the gnatcov image that comes with a prebuilt binutils --- .gitlab-ci.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 261140f7a..46ee1979d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -37,7 +37,7 @@ stages: build: services: - - image:sandbox + - image:gnatcov - cpu:8 - mem:16 stage: build @@ -65,7 +65,7 @@ build: build_standard: services: - - image:sandbox + - image:gnatcov - cpu:8 - mem:16 stage: test @@ -82,7 +82,7 @@ build_standard: build_community: services: - - image:sandbox + - image:gnatcov - cpu:8 - mem:16 stage: test @@ -149,7 +149,7 @@ build_community: test_bin_traces: services: - - image:sandbox + - image:gnatcov - cpu:8 - mem:16 stage: test @@ -169,7 +169,7 @@ test_bin_traces: test_src_traces: services: - - image:sandbox + - image:gnatcov - cpu:8 - mem:16 stage: test @@ -190,7 +190,7 @@ test_src_traces: test_spark: services: - - image:sandbox + - image:gnatcov - cpu:8 - mem:16 stage: test From 217a42eec02b7e581cbc851e47de34543701a9d4 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 14 Apr 2023 12:57:21 +0200 Subject: [PATCH 0270/1483] Fix several occurrences of wrong package name for the instr build In the end it worked as the two bugs compensated for each other, but it resulted in building gnatcov for every test job. --- .gitlab-ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 46ee1979d..fd2c3781e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -54,7 +54,7 @@ build: # Create the package - tar czf $PACKAGE_ABSOLUTE_NAME -C / - it/wave/x86_64-linux/gnatcov-build$EDGE_BUILD_SPACE_SUFFIX/install/ + it/wave/x86_64-linux/gnatcov-instr$EDGE_BUILD_SPACE_SUFFIX/install/ - cd $CI_PROJECT_DIR - ls -l $PACKAGE_BASE_NAME @@ -129,8 +129,8 @@ build_community: # download the nightly one, which may not even exist (case of an edge build # failure that was fixed on that day). - mkdir -p fingerprints - - touch fingerprints/x86_64-linux.gnatcov-instr-build$EDGE_BUILD_SPACE_SUFFIX.install.json.assume-unchanged - - touch fingerprints/x86_64-linux.gnatcov-instr-build$EDGE_BUILD_SPACE_SUFFIX.download_bin.json.assume-unchanged + - touch fingerprints/x86_64-linux.gnatcov-instr$EDGE_BUILD_SPACE_SUFFIX.install.json.assume-unchanged + - touch fingerprints/x86_64-linux.gnatcov-instr$EDGE_BUILD_SPACE_SUFFIX.download_bin.json.assume-unchanged # Setup the CI directory to host coverage results - mkdir $CI_PROJECT_DIR/coverage From cfb67dcfc0aa2803e8b133981691bb89caeaa6ad Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Sat, 15 Apr 2023 08:25:04 +0000 Subject: [PATCH 0271/1483] Replace lch override from testsuite by libsupport lch entry hook The recent factorization of alternative last chance handlers within libsupport conflicts with the testsuite generation of yet another last chance handler alternative to perform coverage buffers dump for configurations combining an RTS without exception propagation and a main-end dump-trigger. This change simplifies the workaround strategy by introducing support for a last-chance-handler-entry hook that tests can override. The default implementation of the hook does nothing and tests needing a buffers dump at this point can now just provide a hook doing so instead of providing a complete alternative last chance handler which needs to abide by all the assumptions attached to such handlers (emitting messages formatted in a specific manner, using exit or abort to terminate, ...). --- testsuite/SCOV/instr.py | 69 ++++--------------- testsuite/SCOV/internals/driver.py | 24 ++++--- .../support/lch/silent_last_chance-abort.adb | 4 ++ .../support/lch/silent_last_chance-exit.adb | 4 ++ .../simple_last_chance_handler.adb | 5 ++ .../examples/support/src/libsupport.adb | 26 +++++++ .../examples/support/src/libsupport.ads | 13 +++- 7 files changed, 76 insertions(+), 69 deletions(-) create mode 100644 tools/gnatcov/examples/support/src/libsupport.adb diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index ab0433920..02626ce31 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -177,28 +177,10 @@ def xcov_convert_base64(base64_file, output_trace_file, out=None, err=None, out=out, err=err, register_failure=register_failure) -def add_last_chance_handler(project, obj_dir, subdirs, main_unit, silent): +def add_dumper_lch_hook(project, obj_dir, subdirs, main_unit): """ - Add a unit to instrumented sources to hold a last chance handler. - - Several mechanisms provide last chance handlers in cross setups. First, - libsupport.gpr provides a last chance handler (last_chance.adb) that prints - a "!!! ERROR !!!"-like pattern that the testsuite will detect as an error, - and base.gpr makes sure that the __gnat_last_chance_handler is undefined so - that the linker picks last_chance.o even though it is not in the main - compilation closure. - - Second, some tests additionally provide a "silence_last_chance.adb" source - that defines this symbol, only this time, the handler prints no message. - Test drivers explicitly WITH this unit, so the linker will not pull - last_chance.o. - - In instrumentation mode, we need the last chance handler to dump coverage - buffers, and to do that we want to call the procedure that dumps coverage - for the test driver closure. So we generate in the actual project - instrumented source directory ($obj_dir/gnatcov-instr or - $obj_dir/$subdirs/gnatcov-instr) a last chance handler. Which one precisely - depends on the ``silent`` argument. + Add a unit to instrumented sources to hold a last chance handler + entry hook dumping the coverage buffers for the given main_unit. :param str project: Instrumented project. This can be either the name of the project file, or the name of the project. @@ -206,11 +188,8 @@ def add_last_chance_handler(project, obj_dir, subdirs, main_unit, silent): project. :param None|str subdirs: Value of --subdirs passed to gnatcov and gprbuild. None if this argument is not passed. - :param str main_unit: Name of the main unit for which the handler will call + :param str main_unit: Name of the main unit for which the hook will call the coverage buffers dump routine. - :param bool silent: Whether the last chance handler should be silent. If - not, it will print a "!!! ERROR !!!"-like pattern that the testsuite - will detect as an error. """ # Amend obj_dir according to subdirs, if applicable if subdirs: @@ -226,7 +205,7 @@ def add_last_chance_handler(project, obj_dir, subdirs, main_unit, silent): # computation. main_unit_slug = main_unit.replace('z', 'zz') auto_dump_unit = 'GNATcov_RTS.Buffers.DB_{}'.format(main_unit_slug) - handler_unit = 'Silent_Last_Chance' if silent else 'Last_Chance' + handler_unit = "Last_Chance_Dumper"; def filename(prefix, ext): return os.path.join(obj_dir, '{}-gnatcov-instr'.format(project), @@ -235,52 +214,32 @@ def filename(prefix, ext): unit_prefix = handler_unit.lower() with open(filename(unit_prefix, 'ads'), 'w') as f: f.write(""" - with System; - package {unit_name} is - procedure Last_Chance_Handler - (Msg : System.Address; Line : Integer); - pragma Export - (C, Last_Chance_Handler, "__gnat_last_chance_handler"); - pragma No_Return (Last_Chance_Handler); + procedure Lch_Enter; + pragma Export (Ada, Lch_Enter, "__lch_enter"); end {unit_name}; """.format(unit_name=handler_unit)) with open(filename(unit_prefix, 'adb'), 'w') as f: f.write(""" - with System; - with GNAT.IO; with {auto_dump_unit}; package body {unit_name} is - procedure Last_Chance_Handler - (Msg : System.Address; Line : Integer) - is - pragma Unreferenced (Msg, Line); - procedure C_abort; - pragma Import (C, C_abort, "abort"); - pragma No_Return (C_abort); + procedure Lch_Enter is begin - if not {silent} then - GNAT.IO.New_Line; - GNAT.IO.Put_Line ("!!!!!!!!!!!!!!!!!!!!!!!!"); - GNAT.IO.Put_Line ("!!! EXCEPTION RAISED !!!"); - GNAT.IO.Put_Line ("!!!!!!!!!!!!!!!!!!!!!!!!"); - end if; {auto_dump_unit}.Dump_Buffers; - C_Abort; - end Last_Chance_Handler; + end; end {unit_name}; """.format(unit_name=handler_unit, - auto_dump_unit=auto_dump_unit, - silent=silent)) + auto_dump_unit=auto_dump_unit)) + + # Amend the main unit to "with" the generated package so it gets + # included in the build. Insert the "with" clause after all pragmas + # to keep the code valid. - # Add a "with" to this handler in the main to make sure the handler unit is - # included in the link. main_file = filename(main_unit, 'adb') with open(main_file, 'r') as f: lines = f.read().splitlines() - # Insert the "with" clause after all pragmas to keep the code valid for i, line in enumerate(lines): if not line.strip().lower().startswith('pragma'): break diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index a4e838354..e524a8cbe 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -28,7 +28,7 @@ from SCOV.tctl import CAT, CovControl -from SCOV.instr import (add_last_chance_handler, default_dump_channel, +from SCOV.instr import (add_dumper_lch_hook, default_dump_channel, default_dump_trigger, xcov_convert_base64, xcov_instrument) @@ -1307,10 +1307,13 @@ def mode_build(self): gpr_obj_dir=self.gpr_obj_dir, out=out) - # When exception propagation is not available, the "main-end" dump - # trigger will not work when the test driver ends with an unhandled - # exception. To workaround that, force the dump in the last chance - # handler. + # When exception propagation is not available, a test ending with an + # unhandled exception goes straight to the last_chance_handler from + # the point of the raise, bypassing the coverage buffers dump if the + # selected dump-trigger is "main-end". For such situations, provide by + # a last chance handler entry hook to dump the buffers at that point + # instead. + if (self.dump_trigger == 'main-end' and not runtime_info().has_exception_propagation): # The only tests with multiple drivers are consolidation ones, @@ -1320,12 +1323,11 @@ def mode_build(self): # driver to build. assert len(self.drivers) == 1 if (language_info(self.drivers[0]).name == "Ada"): - add_last_chance_handler( - instrument_gprsw.root_project, - self.gpr_obj_dir, - subdirs, - no_ext(self.drivers[0]), - silent=not self.testcase.expect_failures) + add_dumper_lch_hook( + project=instrument_gprsw.root_project, + obj_dir=self.gpr_obj_dir, + subdirs=subdirs, + main_unit=no_ext(self.drivers[0])) # Standard output might contain warnings indicating instrumentation # issues. This should not happen, so simply fail as soon as the output diff --git a/tools/gnatcov/examples/support/lch/silent_last_chance-abort.adb b/tools/gnatcov/examples/support/lch/silent_last_chance-abort.adb index 879bdfb77..cdc8b8ac6 100644 --- a/tools/gnatcov/examples/support/lch/silent_last_chance-abort.adb +++ b/tools/gnatcov/examples/support/lch/silent_last_chance-abort.adb @@ -14,7 +14,11 @@ package body Silent_Last_Chance is procedure C_Abort; pragma Import (C, C_abort, "abort"); pragma No_Return (C_abort); + + procedure Lch_Enter; + pragma Import (Ada, Lch_Enter, "__lch_enter"); begin + Lch_Enter; C_abort; end Last_Chance_Handler; diff --git a/tools/gnatcov/examples/support/lch/silent_last_chance-exit.adb b/tools/gnatcov/examples/support/lch/silent_last_chance-exit.adb index b863a29d1..cfd1632c3 100644 --- a/tools/gnatcov/examples/support/lch/silent_last_chance-exit.adb +++ b/tools/gnatcov/examples/support/lch/silent_last_chance-exit.adb @@ -15,7 +15,11 @@ package body Silent_Last_Chance is procedure C_exit (Status : Integer); pragma Import (C, C_exit, "exit"); pragma No_Return (C_exit); + + procedure Lch_Enter; + pragma Import (Ada, Lch_Enter, "__lch_enter"); begin + Lch_Enter; C_exit(0); end Last_Chance_Handler; diff --git a/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.adb b/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.adb index d9d8a40d2..faaa767c0 100644 --- a/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.adb +++ b/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.adb @@ -31,7 +31,12 @@ package body Simple_Last_Chance_Handler is procedure C_Abort; pragma Import (C, C_Abort, "abort"); pragma No_Return (C_Abort); + + procedure Lch_Enter; + pragma Import (Ada, Lch_Enter, "__lch_enter"); begin + Lch_Enter; + GNAT.IO.New_Line; GNAT.IO.Put_Line ("!!!!!!!!!!!!!!!!!!!!!!!!"); GNAT.IO.Put_Line ("!!! EXCEPTION RAISED !!!"); diff --git a/tools/gnatcov/examples/support/src/libsupport.adb b/tools/gnatcov/examples/support/src/libsupport.adb new file mode 100644 index 000000000..7cc72c705 --- /dev/null +++ b/tools/gnatcov/examples/support/src/libsupport.adb @@ -0,0 +1,26 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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. -- +------------------------------------------------------------------------------ + +package body Libsupport is + + procedure Lch_Enter is + begin + null; + end Lch_Enter; + +end Libsupport; diff --git a/tools/gnatcov/examples/support/src/libsupport.ads b/tools/gnatcov/examples/support/src/libsupport.ads index 14834f18a..047bdfc62 100644 --- a/tools/gnatcov/examples/support/src/libsupport.ads +++ b/tools/gnatcov/examples/support/src/libsupport.ads @@ -19,8 +19,15 @@ package Libsupport is -- Root package for our testsuite support library, aimed at filling RTS - -- gaps. This particular (empty) unit is always part of the closure, so - -- there's something to build a library from also in cases where no real - -- "support" is needed, e.g. with native configurations. + -- gaps. This particular unit is always part of the closure, so there's + -- something to build a library from also in cases where no real "support" + -- is needed, e.g. with native configurations. + + -- Default, noop, last_chance_handler entry hook, that individual tests + -- tests/examples may override by interposing an object file in the link + -- prior to the library archive. + + procedure Lch_Enter; + pragma Export (Ada, Lch_Enter, "__lch_enter"); end Libsupport; From 160bd9eaf43df03d1e8dce6d16e1a87cdeeed5e5 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 17 Apr 2023 14:47:25 +0000 Subject: [PATCH 0272/1483] Don't add bin trace cflags to native libsupport Compiling libsupport with -fpreserve-control-flow -fdump-scos is pointless and confusing for native configurations, which don't support binary traces any more. This also happened to break the instrumentation based runs for old versions of gnat that didn't support these switches. Part of work for issue eng/cov/gnatcoverage#3 --- tools/gnatcov/examples/support/Makefile.libsupport | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/examples/support/Makefile.libsupport b/tools/gnatcov/examples/support/Makefile.libsupport index aacaf0697..5ca39c4e8 100644 --- a/tools/gnatcov/examples/support/Makefile.libsupport +++ b/tools/gnatcov/examples/support/Makefile.libsupport @@ -3,9 +3,12 @@ include Makefile.common # Tailored compilation options for libsupport. Allow source -# coverage analysis with binary traces by default. -LIBSUPPORT_CFLAGS=-fdump-scos -fpreserve-control-flow -g +# coverage analysis with binary traces by default, cross only +# at this stage. +ifneq ($(TARGET),) +LIBSUPPORT_CFLAGS=-fdump-scos -fpreserve-control-flow -g +endif all: $(SUPPORT_TARGET_SRC_DIR) $(LIBSUPPORT_DIR) LIBSUPPORT LCH From 81f7c279b8fa7a83f09c7946f34e942304447c9c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 18 Apr 2023 12:11:22 +0200 Subject: [PATCH 0273/1483] Fix regressions Activate tests only for source traces, as the board information is not passed to gnatcov run when the -P switch is passed, resulting in regressions with binary traces. --- testsuite/tests/header_not_found/test.opt | 1 + testsuite/tests/instr-cov/main_no_ext/test.opt | 1 + 2 files changed, 2 insertions(+) create mode 100644 testsuite/tests/header_not_found/test.opt create mode 100644 testsuite/tests/instr-cov/main_no_ext/test.opt diff --git a/testsuite/tests/header_not_found/test.opt b/testsuite/tests/header_not_found/test.opt new file mode 100644 index 000000000..b91fcd5fd --- /dev/null +++ b/testsuite/tests/header_not_found/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Instrumentation specific problem diff --git a/testsuite/tests/instr-cov/main_no_ext/test.opt b/testsuite/tests/instr-cov/main_no_ext/test.opt new file mode 100644 index 000000000..b91fcd5fd --- /dev/null +++ b/testsuite/tests/instr-cov/main_no_ext/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Instrumentation specific problem From 1ab265b0c57bdcbe4106e588c9942f3c39b54808 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 19 Apr 2023 10:46:54 +0200 Subject: [PATCH 0274/1483] Copy coverage artifact before generating testsuite report The testsuite report invocation can exit with an error code if there are regressions in the testsuite, which means that commands after in the CI script won't be executed. We still want coverage data, so copy artifacts before generating the testsuite report. --- .gitlab-ci.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fd2c3781e..9ec60cfbb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -158,12 +158,12 @@ test_bin_traces: # Test using anod - anod test gnatcov --target=leon3-elf -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER + - mv leon3-elf-linux64/gnatcov-O0-embedded-leon3-instr$EDGE_BUILD_SPACE_SUFFIX-test/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name bin-traces leon3-elf-linux64/gnatcov-O0-embedded-leon3-instr$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ - - mv leon3-elf-linux64/gnatcov-O0-embedded-leon3-instr$EDGE_BUILD_SPACE_SUFFIX-test/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml <<: *artifacts @@ -178,13 +178,12 @@ test_src_traces: # Test using anod - anod test gnatcov -Qsrc-traces,instr $EDGE_QUALIFIER + - mv x86_64-linux/gnatcov-instr-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name src-traces x86_64-linux/gnatcov-instr-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ - - cat /it/wave/log/x86_64-linux.gnatcov-instr-src-traces-test.test.log - - mv x86_64-linux/gnatcov-instr-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml <<: *artifacts @@ -199,11 +198,11 @@ test_spark: # Test using anod - anod test gnatcov -Qspark-tests,src-traces,instr $EDGE_QUALIFIER + - mv x86_64-linux/gnatcov-instr-spark-tests-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name spark x86_64-linux/gnatcov-instr-spark-tests-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ - - mv x86_64-linux/gnatcov-instr-spark-tests-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml <<: *artifacts From 118c64d4050d16696c0d531a63b2feb3340bce89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Mon, 3 Apr 2023 14:57:58 +0200 Subject: [PATCH 0275/1483] Display exempted violations as default behavior Previously, it was possible to display the violations that occured in exempted block by using --all-messages. Now the violations are always displayed. TN: TC31-001 --- tools/gnatcov/annotations-report.adb | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 338b8923d..ad64771f2 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -470,7 +470,7 @@ package body Annotations.Report is end if; -- Output summary for this region: sloc range, exempted message count - -- and justification. + -- justification, and exempted violations. New_Line (Output.all); Put (Output.all, Image (To_Range (Sloc, End_Sloc))); @@ -494,16 +494,23 @@ package body Annotations.Report is Put_Line (Output.all, ", justification:"); Put_Line (Output.all, E.Message.all); - if Switches.All_Messages then + New_Line (Output.all); - New_Line (Output.all); + -- Output the contents of the exempted region: the observed exempted + -- violations. - if Pp.Exempted_Messages.Is_Empty then + declare + use Messages_Of_Exempted_Region; + + Messages_C : constant Messages_Of_Exempted_Region.Cursor := + Pp.Exempted_Messages.Find (Sloc); + begin + if Messages_C = Messages_Of_Exempted_Region.No_Element then Put_Line (Output.all, "No exempted violations."); else Put_Line (Output.all, "Exempted violations:"); - for C in Pp.Exempted_Messages (Sloc).Iterate loop + for C in Element (Messages_C).Iterate loop Output_Message (C); if Message_Vectors.Element (C).Kind /= Info then @@ -512,7 +519,7 @@ package body Annotations.Report is end if; end loop; end if; - end if; + end; Total_Exempted_Regions := Total_Exempted_Regions + 1; end Output_Exemption; From 3b0ec8304d6493ce157bab8aadc6dd162b112cb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Mon, 3 Apr 2023 15:00:00 +0200 Subject: [PATCH 0276/1483] Adapt testsuite to check the number and types of exempted violations TN: TC31-001 --- testsuite/SCOV/internals/cnotes.py | 96 ++++++++++- testsuite/SCOV/internals/driver.py | 28 ++-- testsuite/SCOV/internals/rnexpanders.py | 150 ++++++++---------- testsuite/SCOV/internals/xnexpanders.py | 7 +- testsuite/SCOV/internals/xnotep.py | 30 +++- .../TC31-001-show-exempted/src/exemptions.adb | 16 +- .../TC31-001-show-exempted/src/test_1.adb | 8 + .../tests/TC31-001-show-exempted/test.py | 5 +- 8 files changed, 210 insertions(+), 130 deletions(-) diff --git a/testsuite/SCOV/internals/cnotes.py b/testsuite/SCOV/internals/cnotes.py index 183d07f71..4b15733cb 100644 --- a/testsuite/SCOV/internals/cnotes.py +++ b/testsuite/SCOV/internals/cnotes.py @@ -99,6 +99,7 @@ # lx0 : line part of exempted block, 0 deviations (=xcov) # lx1 : line part of exempted block, >0 deviations (=xcov) # lx2 : line part of exempted block, >0 undet. cov. items (=xcov) +# lx : line part of exempted block, do not check deviations (=xcov) # lNoCov : line not covered (=xcov) # lPartCov : line partially covered (=xcov) @@ -141,10 +142,18 @@ # oPartCov : one outcome not covered (=report) # oNoCov : outcome never evaluated (=report) +# Exempted violations. These are a subset of the violations described above +# that are possible to find in exempted blocks. They have the same meaning but +# are simply prefixed by an uppercase 'X' to express that they can only be +# found in exempted regions. The relevant notes are: +# +# XsNoCov, XsPartCov, XsNotCoverable, XsUndetCov, XotNoCov, XofNoCov, +# XoPartCov, XoNoCov, XcPartCov, r0, r0c + # Annotations lower than strictNote won't trigger an unexpected annotation # failure if they appear in a place where they are not explicitly expected. -(lNoCode, lFullCov, +(lNoCode, lFullCov, lx, strictNote, r0, r0c, lx0, lx1, lx2, deviationNote, @@ -155,14 +164,18 @@ etNoCov, efNoCov, eNoCov, ePartCov, eUndetCov, otNoCov, ofNoCov, oNoCov, oPartCov, cPartCov, + XsNoCov, XsPartCov, XsNotCoverable, XsUndetCov, + XotNoCov, XofNoCov, XoPartCov, XoNoCov, + XcPartCov, + Xr0, Xr0c, blockNote, - xBlock0, xBlock1, xBlock2) = range(38) + xBlock0, xBlock1, xBlock2) = range(50) NK_image = {None: "None", lNoCode: "lNoCode", lNotCoverable: "lNotCoverable", lUndetCov: "lUndetCov", lFullCov: "lFullCov", lNoCov: "lNoCov", lPartCov: "lPartCov", - r0: "r0", r0c: "r0c", lx0: "lx0", lx1: "lx1", lx2: "lx2", + r0: "r0", r0c: "r0c", lx0: "lx0", lx1: "lx1", lx2: "lx2", lx: "lx", sNoCov: "sNoCov", sPartCov: "sPartCov", sNotCoverable: "sNotCoverable", sUndetCov: "sUndetCov", dtAlways: "dtAlways", dfAlways: "dfAlways", @@ -173,7 +186,13 @@ otNoCov: "otNoCov", ofNoCov: "ofNoCov", oNoCov: "oNoCov", oPartCov: "oPartCov", xBlock0: "xBlock0", xBlock1: "xBlock1", xBlock2: "xBlock2", - cPartCov: "cPartCov"} + cPartCov: "cPartCov", + XsNoCov: "XsNoCov", XsPartCov: "XsPartCov", + XsNotCoverable: "XsNotCoverable", XsUndetCov: "XsUndetCov", + XotNoCov: "XotNoCov", XofNoCov: "XofNoCov", XoPartCov: "XoPartCov", + XoNoCov: "XoNoCov", + XcPartCov: "XcPartCov", + Xr0: "Xr0", Xr0c: "Xr0c"} # =============================== @@ -185,7 +204,10 @@ elNoteKinds = (lNoCode, lNotCoverable, lUndetCov, lNoCov, lPartCov, lFullCov, lx0, lx1, lx2) -xlNoteKinds = elNoteKinds + +xlTransparentKinds = (lx,) + +xlNoteKinds = elNoteKinds+xlTransparentKinds # Report notes (=report), which feature anti-expectations that # explicitely state expection of absence of emitted notes @@ -202,6 +224,18 @@ # Exemption regions xNoteKinds = (xBlock0, xBlock1, xBlock2) + +# Exempted violations +XsNoteKinds = (XsNoCov, XsPartCov, XsNotCoverable, XsUndetCov) + +XoNoteKinds = (XotNoCov, XofNoCov, XoPartCov, XoNoCov) + +XcNoteKinds = (XcPartCov,) + +XrAntiKinds = (Xr0, Xr0c) + +XNoteKinds = XsNoteKinds + XoNoteKinds + XcNoteKinds + # Anti-expectations rAntiKinds = (r0, r0c) @@ -212,8 +246,8 @@ # kinds in the Emitted Report Notes set because we do want to handle them as # if they could be emitted and report them as unmatched. -erNoteKinds = sNoteKinds+dNoteKinds+cNoteKinds+xNoteKinds+tNoteKinds -xrNoteKinds = erNoteKinds+rAntiKinds +erNoteKinds = sNoteKinds+dNoteKinds+cNoteKinds+xNoteKinds+tNoteKinds+XNoteKinds +xrNoteKinds = erNoteKinds+rAntiKinds+XrAntiKinds # ========================== @@ -265,6 +299,52 @@ def anti_p(nkind): return nkind in rAntiKinds +def transparent_p(nkind): + """ + TRANSPARENT expectations are those that should not produce an expected note + to be matched. It is relevant for exempted regions. For an exempted region, + we have one _line_ note emitted for each line of the block, one _report_ + block note emitted for the entire region and one _report_ note for each + exempted violation within the region. For example: + + foo.adb.xcov: + 2 *: pragma Annotate (Exempt_On, "comment"); -- # ex-region + 3 *: if Debug then -- # ex-region-test + 4 *: Count := Count + 1; -- # ex-region-bump + 5 *: end if; -- # ex-region + 6 *: pragma Annotate (Exempt_Off); -- # ex-region + + report: + -- Exempted Regions -- + foo.adb:2:4-6:4: 2 exempted violations, justification: + "comment" + foo.adb:3:7 decision outcome True never exercised + foo.adb:4:7 statement not executed + + In expectation blocks, the line intended to match the emitted report block + note for the entire region is typically designed to match on all the lines + of the region to capture the sloc range. For example: + + --# foo.adb + --# /ex-region/ l* ## x1 + + This matches all the lines, from 2 to 6, and creates a "l*" line note + expectation for each line that is indeed discharged by the .xcov output. + + Now we need additional expectations for the emitted violation _report_ + notes, and we need to prevent these from creating new line notes + expectations that would never be discharged. On our example, this would be + achieved with: + + --# /ex-region-test l= ## dT- + --# /ex-region-bump l= ## s- + + where the "l=" expectation is "transparent". + """ + + return nkind in xlTransparentKinds + + # =========================== # == Coverage Note Classes == # =========================== @@ -344,7 +424,7 @@ class Enote(Cnote): """Emitted note, as extracted from an xcov report.""" def __init__(self, kind, segment, source, stag=None): - self.kind = kind # The kind of emitted note + Cnote.__init__(self, kind) self.segment = segment # The line segment it designates self.source = source # The corresponding source name self.stag = stag # The separation tag it contains diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index e524a8cbe..09a20fc7b 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -44,8 +44,10 @@ tracename_for, ckptname_for, run_cov_program) from .cnotes import r0, r0c, xBlock0, xBlock1, lx0, lx1, lFullCov, lPartCov +from .cnotes import Xr0, Xr0c from .cnotes import KnoteDict, elNoteKinds, erNoteKinds, rAntiKinds from .cnotes import xNoteKinds, sNoteKinds, dNoteKinds, cNoteKinds, tNoteKinds +from .cnotes import XsNoteKinds, XoNoteKinds, XcNoteKinds from .cnotes import strict_p, deviation_p, anti_p, positive_p from .xnexpanders import XnotesExpander @@ -187,9 +189,11 @@ def __init__(self, wdbase, bdbase, subdirhint): # Relevant emitted report notes r_ern_for = { - CAT.stmt: tNoteKinds + xNoteKinds + sNoteKinds, - CAT.decision: tNoteKinds + xNoteKinds + sNoteKinds + dNoteKinds, - CAT.mcdc: tNoteKinds + xNoteKinds + sNoteKinds + dNoteKinds + cNoteKinds, + CAT.stmt: tNoteKinds + xNoteKinds + sNoteKinds + XsNoteKinds, + CAT.decision: tNoteKinds + xNoteKinds + sNoteKinds + dNoteKinds + + XsNoteKinds + XoNoteKinds, + CAT.mcdc: tNoteKinds + xNoteKinds + sNoteKinds + dNoteKinds + cNoteKinds + + XsNoteKinds + XoNoteKinds + XcNoteKinds, } # Relevant report expectations @@ -253,7 +257,6 @@ def try_sat_over(self, ekind, xn): # expectations is stricter so the most correct in principle. for en in self.edict[ekind]: - if not en.discharges and self.__discharges(en=en, xn=xn): en.discharges = xn xn.discharger = en @@ -883,16 +886,7 @@ def check_expectations(self): # Checking that we do have the expected reports will be performed by # the regular coverage expectation assessments triggered below. - # Check if the "--all-messages" switch is activated. In the case of - # exempted violations, its use causes the report to show different - # informations than would otherwise be expected and that needs to be - # checked. - - all_messages = "--all-messages" in self.covoptions - - self.ernotes = RnotesExpander( - "test.rep", - all_messages=all_messages).ernotes + self.ernotes = RnotesExpander("test.rep").ernotes if self.covctl and self.covctl.xreports is not None: self.check_unexpected_reports() @@ -978,8 +972,10 @@ def check_expectations(self): # Then augment with what is allowed to hit "0" or "0c" expectation # statements: - r_discharge_kdict.update({r0: r_ern_for[relevance_cat], - r0c: r_ern_for[relevance_cat]}) + r_discharge_kdict.update({r0: r_ern_for[relevance_cat], + r0c: r_ern_for[relevance_cat], + Xr0: r_ern_for[relevance_cat], + Xr0c: r_ern_for[relevance_cat]}) # =xcov outputs, stricter_level micro relaxations only: diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index cd95c5e9b..204f8462a 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -11,8 +11,9 @@ from .cnotes import ( xBlock0, xBlock1, sNoCov, sPartCov, sNotCoverable, dfAlways, dtAlways, dfNoCov, dtNoCov, dNoCov, dPartCov, efNoCov, etNoCov, eNoCov, ePartCov, - cPartCov, Enote, KnoteDict, erNoteKinds, sUndetCov, - dUndetCov, eUndetCov, xBlock2 + cPartCov, Enote, KnoteDict, erNoteKinds, sUndetCov, dUndetCov, eUndetCov, + xBlock2, XsNoCov, XsPartCov, XsNotCoverable, XsUndetCov, XotNoCov, + XofNoCov, XoPartCov, XoNoCov, XcPartCov ) from .segments import Sloc, Sloc_from_match from .stags import Stag_from @@ -128,7 +129,7 @@ def ends_on(self, rline): self.end_hits.append(rline) return p - def check(self, all_messages=False): + def check(self): """ Once we're done reading the entire report, sanity check what we found for this block. Raise a test failure. @@ -338,15 +339,13 @@ def nkind_for(self, rline): class XREchapter(Nchapter): """Exemptions Regions chapter.""" - def __init__(self, re_start, re_notes, exempted_notes, - all_messages=False): - - self.all_messages = all_messages + def __init__(self, re_start, re_notes, exempted_notes): # The list of notes acceptable for an exempted violation self.exempted_notes = exempted_notes - self.ecount_violations = 0 + # The number of exempted violations found + self.ecount_exempted = 0 re_end = (r"(No|\d+) exempted region[s]*, " r"(No|\d+) exempted violation[s]*\.$") @@ -365,14 +364,20 @@ def __check_summary_count(self, sec, sum_count, sec_count): "summary found for section starts != 1 (%s)" % sec.name) def check_exempted_summary(self, sec, p): + # The emitted notes of exempted violations are logged in self.enotes + # to be checked for discharging expected notes later on. However + # we still need to check the number of notes belonging to the exempted + # region itself and the number of notes for exempted violations + # separatly. + ecount = len(self.enotes) - self.ecount_exempted + self.__check_summary_count(sec, self.value(p.group(1)), - len(self.enotes)) + ecount) - if self.all_messages: - self.__check_summary_count(sec, - self.value(p.group(2)), - self.ecount_violations) + self.__check_summary_count(sec, + self.value(p.group(2)), + self.ecount_exempted) def __validate(self, actual_count, count, element_counted): thistest.fail_if( @@ -383,47 +388,31 @@ def __validate(self, actual_count, count, element_counted): ) def ends_on(self, rline): - if not self.all_messages: - return Rblock.ends_on(self, rline) - else: - p = Rblock.ends_on(self, rline) - if p: - # Validate the number of exempted regions - self.__validate(len(self.enotes), - self.value(p.group(1)), - "exempted regions") - - # Validate the total number of exempted violations - self.__validate(self.ecount_violations, - self.value(p.group(2)), - "exempted violations") - return p - - def check_enote(self, rline, enote): - - # Within an exempted region, if the "--all-messages" switch is ised - # we expect the exempted violations to still be displayed. - # Enote.kind being None means that rline could be one of those. + p = Rblock.ends_on(self, rline) + if p: + # Validate the number of exempted regions + self.__validate(len(self.enotes) - self.ecount_exempted, + self.value(p.group(1)), + "exempted regions") - if enote.kind is None and self.all_messages: - exempted = False + # Validate the total number of exempted violations + self.__validate(self.ecount_exempted, + self.value(p.group(2)), + "exempted violations") - # Check that rline does indeed correspond to an exempted - # violation. The report does not provide any information regarding - # their type. We can only check their number. + return p - for key in self.exempted_notes: - if re.match(key, rline): - self.ecount_violations += 1 - exempted = True - break + def check_enote(self, rline, enote): + if enote.kind is None: + self.report_unexpected_enote(rline) + return None - if not exempted: - self.report_unexpected_enote(rline) + # Check if the note is that of an exempted violation in the region. If + # so, increment the exempted violations counter. + if enote.kind in self.exempted_notes.values(): + self.ecount_exempted += 1 - return None - else: - return enote + return enote class NCIchapter(Nchapter): @@ -459,9 +448,9 @@ def __init__(self, re_start, skeys): def try_match(self, sec, rline): p = re.match(self.skeys[sec], rline) if p: - # If the check is done on the exempted regions chapter and the - # the "--all-messages" switch is used then the verification has - # to be done on the number of regions and the number of violations + # If the check is done on the exempted regions chapter then the + # summary verification has to be done on the number of regions and + # the number of violations if sec.name == 'EXEMPTED REGIONS': sec.check_exempted_summary(sec, p) @@ -483,20 +472,11 @@ def try_parse(self, rline): self.try_match(sec, rline) return None - def check(self, all_messages=False): + def check(self): Rchapter.check(self) for sec in self.skeys: - # If "--all-messages" is used, the report will show the - # "OTHER ERRORS" section. This is expected and nothing is to be - # checked in it. - - other_errors = (all_messages and - len(sec.start_hits) == 1 and - "OTHER ERRORS" in sec.start_hits[0]) - thistest.fail_if( - not other_errors and len(sec.start_hits) > 0 and not self.checked[sec], "summary count check missing for section %s" % sec.name) @@ -522,7 +502,7 @@ def check(self, all_messages=False): # unexpected blocks: class Ublock(Rblock): - def check(self, all_messages=False): + def check(self): thistest.fail_if( len(self.start_hits) > 0, "Unexpected headers caught by %s:\n%s" @@ -553,7 +533,7 @@ def __init__(self, re_start): # process a report: class RblockSet: - def __init__(self, all_messages=False): + def __init__(self): # We need a list of all the blocks to drive the report parsing # process, and a list of all the note blocks to setup the analysis @@ -562,10 +542,6 @@ def __init__(self, all_messages=False): self.noteblocks = [] self.allblocks = [] - # Is "--all-messages" used - - self.all_messages = all_messages - # Violation sections stmt_notes = { @@ -617,7 +593,7 @@ def __init__(self, all_messages=False): UCIchapter(re_start="UNDETERMINED COVERAGE ITEMS", re_notes=ni_notes)) - # Exemptions regions + # Exempted regions xr_notes = { "0 exempted violation": xBlock0, @@ -626,13 +602,24 @@ def __init__(self, all_messages=False): r"coverage items?": xBlock2 } - lvl_notes = stmt_notes | dc_notes | mcdc_notes - all_notes = nc_notes | ni_notes | lvl_notes + # Exempted violations + + Xr_notes = { + "statement not executed": XsNoCov, + "multiple statements on line": XsPartCov, + "statement has no object code": XsNotCoverable, + "statement was not instrumented": XsUndetCov, + "decision outcome FALSE never": XofNoCov, + "decision outcome TRUE never": XotNoCov, + "decision outcome never evaluated": XoNoCov, + "decision not exercised in both directions": XoPartCov, + "condition has no independent influence pair": XcPartCov + } + self.noteblocks.append( XREchapter(re_start="EXEMPTED REGIONS", - re_notes=xr_notes, - exempted_notes=all_notes, - all_messages=self.all_messages)) + re_notes=xr_notes | Xr_notes, + exempted_notes=Xr_notes)) # Other note blocks @@ -666,9 +653,9 @@ def starts_with(self, rline): return rs return None - def check(self, all_messages=False): + def check(self): for rs in self.allblocks: - rs.check(all_messages) + rs.check() class RnotesExpander: @@ -679,13 +666,13 @@ def to_enotes(self, report): # We need to ignore everything not in the report sections # of interest, so until we know we're in ... - self.rset = RblockSet(self.all_messages) + self.rset = RblockSet() self.rs = None self.report = report Tfile(filename=self.report, process=self.process_tline) - self.rset.check(self.all_messages) + self.rset.check() def register(self, enote): source = enote.source @@ -726,15 +713,10 @@ def process_tline(self, tline): return enote - def __init__(self, report, all_messages=False): + def __init__(self, report): # xcov --annotate=report produces a single report featuring a list of # indications for slocs in all the units. self.ernotes = {} - - # True if the "--all-messages" switch is used. Its use changes what - # must be checked in case of exempted violations. - - self.all_messages = all_messages self.to_enotes(report) diff --git a/testsuite/SCOV/internals/xnexpanders.py b/testsuite/SCOV/internals/xnexpanders.py index 4161e007e..6405dcca0 100644 --- a/testsuite/SCOV/internals/xnexpanders.py +++ b/testsuite/SCOV/internals/xnexpanders.py @@ -53,12 +53,13 @@ # lx_lnote_list := lx_lnote_choice ["," lx_lnote_list] # lx_lnote_choice := [cov_level_test] [weak_mark] lx_lnote -# lx_lnote := +# lx_lnote := # lx_rnote_list := lx_rnote_choice [rnote_sep lx_rnote_list] # lx_rnote_choice := [cov_level_test] [weak_mark] lx_rnote -# lx_rnote_kind = -# lx_rnote := lx_rnote_kind[:"TEXT"][@(STAG)] +# lx_rnote_kind := +# lx_ernote_kind := +# lx_rnote := [:"TEXT"][@(STAG)] # rnote_sep is selected to be '#' if any # is found on the line, # or ',' if any , is found on the line, diff --git a/testsuite/SCOV/internals/xnotep.py b/testsuite/SCOV/internals/xnotep.py index 11b317a68..6ce7343b5 100644 --- a/testsuite/SCOV/internals/xnotep.py +++ b/testsuite/SCOV/internals/xnotep.py @@ -12,11 +12,13 @@ import re from .cnotes import ( - Xnote, block_p, cPartCov, dNoCov, dPartCov, dfAlways, dfNoCov, dtAlways, - dtNoCov, ePartCov, eNoCov, efNoCov, etNoCov, lFullCov, lNoCode, lNoCov, - lNotCoverable, lPartCov, lx0, lx1, lx2, oNoCov, oPartCov, ofNoCov, - otNoCov, r0, r0c, sNoCov, sNotCoverable, sPartCov, xBlock0, xBlock1, - xBlock2, xNoteKinds, lUndetCov, sUndetCov, dUndetCov, eUndetCov + Xnote, block_p, transparent_p, cPartCov, dNoCov, dPartCov, dfAlways, + dfNoCov, dtAlways, dtNoCov, ePartCov, eNoCov, efNoCov, etNoCov, lFullCov, + lNoCode, lNoCov, lNotCoverable, lPartCov, lx0, lx1, lx2, lx, oNoCov, + oPartCov, ofNoCov, otNoCov, r0, r0c, sNoCov, sNotCoverable, sPartCov, + xBlock0, xBlock1, xBlock2, xNoteKinds, lUndetCov, sUndetCov, dUndetCov, + eUndetCov, XsNoCov, XsPartCov, XsNotCoverable, XsUndetCov, XotNoCov, + XofNoCov, XoPartCov, XoNoCov, XcPartCov, Xr0, Xr0c ) from .segments import Line, Section, Segment from .stags import Stag_from @@ -169,7 +171,7 @@ class XnoteP: NK_for = {'l-': lNoCov, 'l!': lPartCov, 'l+': lFullCov, 'l.': lNoCode, 'l0': lNotCoverable, 'l?': lUndetCov, - 'l#': lx0, 'l*': lx1, 'l@': lx2, + 'l#': lx0, 'l*': lx1, 'l@': lx2, 'l=': lx, 's-': sNoCov, 's!': sPartCov, 's0': sNotCoverable, 's?': sUndetCov, 'dT*': dtAlways, 'dF*': dfAlways, @@ -180,7 +182,19 @@ class XnoteP: 'oT-': otNoCov, 'oF-': ofNoCov, 'o!': oPartCov, 'o-': oNoCov, 'c!': cPartCov, 'x0': xBlock0, 'x+': xBlock1, 'x?': xBlock2, - '0': r0, '0c': r0c} + '0': r0, '0c': r0c, + # Exempted notes + 'Xs-': XsNoCov, 'Xs!': XsPartCov, 'Xs0': XsNotCoverable, + 'Xs?': XsUndetCov, + 'XoT-': XotNoCov, 'XoF-': XofNoCov, 'Xo!': XoPartCov, + 'Xo-': XoNoCov, 'Xc!': XcPartCov, + 'X0': Xr0, 'X0c': Xr0c} + + # The notes prefixed with 'X' correspond to the type of violations we + # expect to encounter within an exempted block. In this context we cannot + # determine if a violation on a decision belongs to decision or MCDC + # coverage. Therefore we use the 'o' notes to express this lack of + # information. def __init__(self, text, stext=None, stag=None): @@ -244,6 +258,6 @@ def instanciate_over(self, tline, block, srules): else self.kind) return (None - if kind is None + if kind is None or transparent_p(kind) else self.factory.instanciate_over(tline=tline, block=block, kind=kind)) diff --git a/testsuite/tests/TC31-001-show-exempted/src/exemptions.adb b/testsuite/tests/TC31-001-show-exempted/src/exemptions.adb index 744097572..715aa8861 100644 --- a/testsuite/tests/TC31-001-show-exempted/src/exemptions.adb +++ b/testsuite/tests/TC31-001-show-exempted/src/exemptions.adb @@ -9,18 +9,18 @@ begin end if; pragma Annotate (Xcov, Exempt_On, "Exempt 1"); -- # exempt1 - if X = 3 then -- # exempt1 - X := X + 1; -- # exempt1 - X := X + 1; -- # exempt1 + if X = 3 then -- # exempt1_if1 + X := X + 1; -- # exempt1_inc1 + X := X + 1; -- # exempt1_inc2 end if; -- # exempt1 pragma Annotate (Xcov, Exempt_Off); -- # exempt1 pragma Annotate (Xcov, Exempt_On, "Exempt 2"); -- # exempt2 - if X = 3 then -- # exempt2 - X := X + 1; -- # exempt2 - X := X + 1; -- # exempt2 - X := X + 1; -- # exempt2 - X := X + 1; -- # exempt2 + if X = 3 then -- # exempt2_if2 + X := X + 1; -- # exempt2_inc3 + X := X + 1; -- # exempt2_inc4 + X := X + 1; -- # exempt2_inc5 + X := X + 1; -- # exempt2_inc6 end if; -- # exempt2 pragma Annotate (Xcov, Exempt_Off); -- # exempt2 end Exemptions; diff --git a/testsuite/tests/TC31-001-show-exempted/src/test_1.adb b/testsuite/tests/TC31-001-show-exempted/src/test_1.adb index 9d40e915f..96eae62f0 100644 --- a/testsuite/tests/TC31-001-show-exempted/src/test_1.adb +++ b/testsuite/tests/TC31-001-show-exempted/src/test_1.adb @@ -13,4 +13,12 @@ end Test_1; -- /if_2/ l! ## dT- -- /inc_2/ l- ## s- -- /exempt1/ l* ## x+ +-- /exempt1_if1/ l= ## XoT- +-- /exempt1_inc1/ l= ## Xs- +-- /exempt1_inc2/ l= ## Xs- -- /exempt2/ l* ## x+ +-- /exempt2_if2/ l= ## XoT- +-- /exempt2_inc3/ l= ## Xs- +-- /exempt2_inc4/ l= ## Xs- +-- /exempt2_inc5/ l= ## Xs- +-- /exempt2_inc6/ l= ## Xs- diff --git a/testsuite/tests/TC31-001-show-exempted/test.py b/testsuite/tests/TC31-001-show-exempted/test.py index 0d6cd4d49..cdc47c7ec 100644 --- a/testsuite/tests/TC31-001-show-exempted/test.py +++ b/testsuite/tests/TC31-001-show-exempted/test.py @@ -1,8 +1,7 @@ from SCOV.tc import TestCase -from SCOV.tctl import CAT, CovControl +from SCOV.tctl import CAT from SUITE.context import thistest -TestCase(category=CAT.decision).run(covcontrol=CovControl - (covoptions="--all-messages")) +TestCase(category=CAT.decision).run() thistest.result() From e00f89048727ac85a35f9d82a8f07f1ad1725c42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 29 Mar 2023 16:26:37 +0200 Subject: [PATCH 0277/1483] Update Qualif requirements and expectations wrt exemptions Account for the recent tool behavior changes, now always displaying exempted violations attached to exemption regions. TN: TC31-001 --- .../PrecondInBody/src/cons_valid.txt | 16 ++++++----- .../Exemptions/PrecondInBody/src/ranges.adb | 4 +-- .../PrecondInBody/src/test_ranges_invalid.adb | 16 ++++++----- .../src/test_ranges_no_overlap.adb | 16 ++++++----- .../PrecondInBody/src/test_ranges_overlap.adb | 16 ++++++----- .../ExemptedViolations/src/exemptions.adb | 12 ++++++++ .../src/test_call_debug.adb | 16 +++++++++++ .../src/test_call_debug_neg.adb | 16 +++++++++++ .../src/test_call_no_debug.adb | 16 +++++++++++ .../ExemptedViolations/src/test_no_call.adb | 18 ++++++++++++ .../mcdc/Exemptions/ExemptedViolations/tc.rst | 4 +++ .../Exemptions/ExemptedViolations/test.py | 5 ++++ .../PrecondInBody/src/cons_valid.txt | 1 + .../PrecondInBody/src/cons_valinvala.txt | 1 + .../PrecondInBody/src/cons_valinvalb.txt | 1 + .../Exemptions/PrecondInBody/src/ranges.adb | 2 +- .../src/test_ranges_invalid_a.adb | 1 + .../src/test_ranges_invalid_b.adb | 1 + .../src/test_ranges_no_overlap.adb | 1 + .../PrecondInBody/src/test_ranges_overlap.adb | 1 + .../Exemptions/MixInUnits/src/exemptions.adb | 8 +++--- .../Exemptions/MixInUnits/src/exemptions.ads | 4 +-- ..._exemptions_all_non_exempted_code_call.adb | 2 ++ .../src/test_exemptions_no_call.adb | 2 ++ ...test_exemptions_non_exempted_code_call.adb | 2 ++ .../Exemptions/StmtsInBody/src/stacks.adb | 8 +++--- .../Exemptions/StmtsInBody/src/test_0.adb | 16 +++++++---- .../Exemptions/StmtsInBody/src/test_pop_u.adb | 22 ++++++++------- .../StmtsInBody/src/test_push_0.adb | 23 ++++++++------- .../StmtsInBody/src/test_push_o.adb | 22 ++++++++------- .../StmtsInBody/src/test_pushpop_0.adb | 22 ++++++++------- .../StmtsInBody/src/test_pushpop_o.adb | 21 +++++++------- .../StmtsInBody/src/test_pushpop_u.adb | 21 +++++++------- .../stmt/Exemptions/StmtsInElab/src/com.adb | 2 +- .../stmt/Exemptions/StmtsInElab/src/gcom.adb | 2 +- .../Exemptions/StmtsInElab/src/test_com.adb | 5 ++-- .../StmtsInElab/src/test_gcom_f.adb | 5 ++-- .../Exemptions/StmtsInHandler/src/stacks.adb | 2 +- .../Exemptions/StmtsInHandler/src/test_0.adb | 27 +++++++++--------- .../StmtsInHandler/src/test_push_0.adb | 25 +++++++++-------- .../StmtsInHandler/src/test_pushpop_0.adb | 25 +++++++++-------- .../src/multiple_exemptions.adb | 14 +++++----- .../Exemptions/StmtsInSubprog/src/test_0.adb | 7 +++++ .../StmtsInSubprog/src/test_exempt_all.adb | 17 +++++++---- .../StmtsInSubprog/src/test_exempt_xr12.adb | 6 ++++ .../StmtsInSubprog/src/test_exempt_xr13.adb | 6 ++++ .../StmtsInSubprog/src/test_exempt_xr23.adb | 2 ++ .../Exemptions/SubprogsInUnit/src/stacks.adb | 22 +++++++-------- .../Exemptions/SubprogsInUnit/src/test_0.adb | 12 +++++++- .../SubprogsInUnit/src/test_pop_u.adb | 8 +++++- .../SubprogsInUnit/src/test_push_0.adb | 8 +++++- .../SubprogsInUnit/src/test_push_o.adb | 6 +++- .../SubprogsInUnit/src/test_pushpop_0.adb | 5 +++- .../SubprogsInUnit/src/test_pushpop_o.adb | 3 +- .../SubprogsInUnit/src/test_pushpop_u.adb | 3 +- .../Exemptions/WholeBody/src/test_tipos_0.adb | 5 +++- .../WholeBody/src/test_tipos_other.adb | 3 +- .../WholeBody/src/test_tipos_pos.adb | 3 +- .../stmt/Exemptions/WholeBody/src/tipos.adb | 6 ++-- testsuite/Qualif/Ada/stmt/Exemptions/req.rst | 28 +++++++++++-------- .../Common/Report/Exemptions/src/ranges.adb | 6 ++-- .../Exemptions/src/test_ranges_invalid.adb | 3 ++ .../Exemptions/src/test_ranges_overlap.adb | 3 ++ 63 files changed, 404 insertions(+), 202 deletions(-) create mode 100644 testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/exemptions.adb create mode 100644 testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug.adb create mode 100644 testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug_neg.adb create mode 100644 testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_no_debug.adb create mode 100644 testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_no_call.adb create mode 100644 testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/tc.rst create mode 100644 testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/test.py diff --git a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/cons_valid.txt b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/cons_valid.txt index a779144f4..8bb367943 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/cons_valid.txt +++ b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/cons_valid.txt @@ -4,10 +4,12 @@ drivers=_overlap|_no_overlap -- Exempted precondition evaluated True only. raise not covered. --# ranges.adb --- /checkValid/ l! ## dT- --- /assignValid/ l+ ## 0 --- /assignInvalid/ l- ## s- --- /preValid/ l* ## x+ --- /checkOverlap/ l+ ## 0 --- /overlapTrue/ l+ ## 0 --- /overlapFalse/ l+ ## 0 +-- /checkValid/ l! ## dT- +-- /assignValid/ l+ ## 0 +-- /assignInvalid/ l- ## s- +-- /preValid/ l* ## x+ +-- /preValid_if/ l= ## XoT- +-- /preValid_raise/ l= ## Xs- +-- /checkOverlap/ l+ ## 0 +-- /overlapTrue/ l+ ## 0 +-- /overlapFalse/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/ranges.adb b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/ranges.adb index 9026e82ca..2621a2f75 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/ranges.adb +++ b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/ranges.adb @@ -15,8 +15,8 @@ package body Ranges is begin pragma Annotate -- # preValid (Xcov, Exempt_On, "expect no invalid ranges"); -- # preValid - if not (R1.Valid and then R2.Valid) then -- # preValid - raise Program_Error; -- # preValid + if not (R1.Valid and then R2.Valid) then -- # preValid_if + raise Program_Error; -- # preValid_raise end if; -- # preValid pragma Annotate (Xcov, Exempt_Off); -- # preValid diff --git a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_invalid.adb b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_invalid.adb index e1035008d..4e2a60cb2 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_invalid.adb +++ b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_invalid.adb @@ -19,11 +19,13 @@ exception end; --# ranges.adb --- /checkValid/ l+ ## 0 --- /assignValid/ l+ ## 0 --- /assignInvalid/ l+ ## 0 --- /preValid/ l* ## x+ --- /checkOverlap/ l- ## s- --- /overlapTrue/ l- ## s- --- /overlapFalse/ l- ## s- +-- /checkValid/ l+ ## 0 +-- /assignValid/ l+ ## 0 +-- /assignInvalid/ l+ ## 0 +-- /preValid/ l* ## x+ +-- /preValid_if/ l= ## XoF- +-- /preValid_raise/ l= ## X0 +-- /checkOverlap/ l- ## s- +-- /overlapTrue/ l- ## s- +-- /overlapFalse/ l- ## s- diff --git a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb index 3464c8934..7b4055177 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb +++ b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb @@ -20,10 +20,12 @@ begin end; --# ranges.adb --- /checkValid/ l! ## dT- --- /assignValid/ l+ ## 0 --- /assignInvalid/ l- ## s- --- /preValid/ l* ## x+ --- /checkOverlap/ l! ## dT- --- /overlapTrue/ l- ## s- --- /overlapFalse/ l+ ## 0 +-- /checkValid/ l! ## dT- +-- /assignValid/ l+ ## 0 +-- /assignInvalid/ l- ## s- +-- /preValid/ l* ## x+ +-- /preValid_if/ l= ## XoT- +-- /preValid_raise/ l= ## Xs- +-- /checkOverlap/ l! ## dT- +-- /overlapTrue/ l- ## s- +-- /overlapFalse/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_overlap.adb b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_overlap.adb index fa751f210..ee39f3ece 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_overlap.adb +++ b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_overlap.adb @@ -36,11 +36,13 @@ begin end; --# ranges.adb --- /checkValid/ l! ## dT- --- /assignValid/ l+ ## 0 --- /assignInvalid/ l- ## s- --- /preValid/ l* ## x+ --- /checkOverlap/ l! ## dF- --- /overlapTrue/ l+ ## 0 --- /overlapFalse/ l- ## s- +-- /checkValid/ l! ## dT- +-- /assignValid/ l+ ## 0 +-- /assignInvalid/ l- ## s- +-- /preValid/ l* ## x+ +-- /preValid_if/ l= ## XoT- +-- /preValid_raise/ l= ## Xs- +-- /checkOverlap/ l! ## dF- +-- /overlapTrue/ l+ ## 0 +-- /overlapFalse/ l- ## s- diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/exemptions.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/exemptions.adb new file mode 100644 index 000000000..950bcb3a4 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/exemptions.adb @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Exemptions (Debug_Mode : Boolean; I : Integer) is +begin + pragma Annotate (Xcov, Exempt_On, "Exempted"); -- # ex + if Debug_Mode and then I < 0 then -- # ex_if_neg + Put_Line ("I is negative."); -- # ex_error + elsif Debug_Mode then -- # ex_if_debug + Put_Line ("No error."); -- # ex_no_error + end if; -- # ex + pragma Annotate (Xcov, Exempt_Off); -- # ex +end Exemptions; diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug.adb new file mode 100644 index 000000000..d01d2a398 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug.adb @@ -0,0 +1,16 @@ +with Exemptions; + +-- Test driver for exemptions. Call the subprogram and execute only part of +-- the exempted code, evaluating all conditions of all decisions. + +procedure Test_Call_Debug is +begin + Exemptions (True, 42); +end Test_Call_Debug; + +--# exemptions.adb +-- /ex/ l* ## x+ +-- /ex_if_neg/ l= ## s=>X0, dmu=>XoT- +-- /ex_error/ l= ## Xs- +-- /ex_if_debug/ l= ## XoF- +-- /ex_no_error/ l= ## X0 diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug_neg.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug_neg.adb new file mode 100644 index 000000000..f3bcbcbdb --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_debug_neg.adb @@ -0,0 +1,16 @@ +with Exemptions; + +-- Test driver for exemptions. Exercise only part of the exempted code, +-- evaluating only part of the decisions. + +procedure Test_Call_Debug_Neg is +begin + Exemptions (True, -42); +end Test_Call_Debug_Neg; + +--# exemptions.adb +-- /ex/ l* ## x+ +-- /ex_if_neg/ l= ## XoF- +-- /ex_error/ l= ## X0 +-- /ex_if_debug/ l= ## Xs- +-- /ex_no_error/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_no_debug.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_no_debug.adb new file mode 100644 index 000000000..8b8c69085 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_call_no_debug.adb @@ -0,0 +1,16 @@ +with Exemptions; + +-- Test driver for exemptions. Exercise only part of the exempted code, +-- evaluating all decisions but only part of the conditions. + +procedure Test_Call_No_Debug is +begin + Exemptions (False, 42); +end Test_Call_No_Debug; + +--# exemptions.adb +-- /ex/ l* ## x+ +-- /ex_if_neg/ l= ## XoT- +-- /ex_error/ l= ## Xs- +-- /ex_if_debug/ l= ## s=>X0, dmu=>XoT- +-- /ex_no_error/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_no_call.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_no_call.adb new file mode 100644 index 000000000..7b796ffcd --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/src/test_no_call.adb @@ -0,0 +1,18 @@ +with Exemptions; + +-- Test driver for exemptions. It only "withes" the functional code, so the +-- only constructs that are expected to be reported as covered are those that +-- are executed/elaborated when the spec and body of the package Exemptions +-- are elaborated, of which there are none. + +procedure Test_No_Call is +begin + null; +end; + +--# exemptions.adb +-- /ex/ l* ## x+ +-- /ex_if_neg/ l= ## Xs- +-- /ex_error/ l= ## Xs- +-- /ex_if_debug/ l= ## Xs- +-- /ex_no_error/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/tc.rst b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/tc.rst new file mode 100644 index 000000000..5ea46ada6 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/tc.rst @@ -0,0 +1,4 @@ +**Exercise exemptions over a group of statements and complex decisions** + +Exercice an exemption region within a subprogram body. + diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/test.py b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/ExemptedViolations/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valid.txt b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valid.txt index 417ceef31..1005dc17e 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valid.txt +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valid.txt @@ -8,4 +8,5 @@ drivers=_overlap|_no_overlap -- /assignValid/ l+ ## 0 -- /assignInvalid/ l- ## s- -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## XoF- -- /checkOverlap/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvala.txt b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvala.txt index bcf056ca2..4642b97cb 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvala.txt +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvala.txt @@ -9,4 +9,5 @@ drivers=_overlap|_no_overlap|invalid_a -- /assignValid/ l+ ## 0 -- /assignInvalid/ l+ ## 0 -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## Xc! -- /checkOverlap/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvalb.txt b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvalb.txt index dc331d162..c3638328a 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvalb.txt +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/cons_valinvalb.txt @@ -9,4 +9,5 @@ drivers=_overlap|_no_overlap|invalid_b -- /assignValid/ l+ ## 0 -- /assignInvalid/ l+ ## 0 -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## Xc! -- /checkOverlap/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/ranges.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/ranges.adb index 60fe80de3..03bb60845 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/ranges.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/ranges.adb @@ -14,7 +14,7 @@ package body Ranges is function Overlap (R1, R2 : XYrange) return Boolean is pragma Annotate -- # preValid (Xcov, Exempt_On, "expect no invalid ranges"); -- # preValid - pragma Precondition (R1.Valid and then R2.Valid); -- # preValid + pragma Precondition (R1.Valid and then R2.Valid); -- # preValid_cond pragma Annotate (Xcov, Exempt_Off); -- # preValid begin diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_a.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_a.adb index d6cca3064..a367a80a1 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_a.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_a.adb @@ -23,5 +23,6 @@ end; -- /assignValid/ l+ ## 0 -- /assignInvalid/ l+ ## 0 -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## XoT- -- /checkOverlap/ l- ## s- diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_b.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_b.adb index 2fe724395..e44f620fc 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_b.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_b.adb @@ -23,5 +23,6 @@ end; -- /assignValid/ l+ ## 0 -- /assignInvalid/ l+ ## 0 -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## XoT- -- /checkOverlap/ l- ## s- diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb index 1adfaed7d..78fe03d72 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb @@ -24,5 +24,6 @@ end; -- /assignValid/ l+ ## 0 -- /assignInvalid/ l- ## s- -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## XoF- -- /checkOverlap/ l! ## eT- diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_overlap.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_overlap.adb index 6b4c6ca4a..c3b3d77c8 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_overlap.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_overlap.adb @@ -40,5 +40,6 @@ end; -- /assignValid/ l+ ## 0 -- /assignInvalid/ l- ## s- -- /preValid/ l* ## x+ +-- /preValid_cond/ l= ## XoF- -- /checkOverlap/ l! ## eF- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.adb index c73bfe348..e13aed29f 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.adb @@ -6,7 +6,7 @@ package body Exemptions is pragma Annotate -- # xswap (Xcov, Exempt_On, "exemption on declarations"); -- # xswap - Tmp : Integer := J; -- # xswap + Tmp : Integer := J; -- # xswap_vio pragma Annotate (Xcov, Exempt_Off); -- # xswap begin J := I; -- # swap_stmt @@ -24,7 +24,7 @@ package body Exemptions is pragma Annotate -- # xfactorial (Xcov, Exempt_On, -- # xfactorial "exemption on statements in function"); -- # xfactorial - return Positive'Last; -- # xfactorial + return Positive'Last; -- # xfactorial_vio pragma Annotate (Xcov, Exempt_Off); -- # xfactorial else return X * Factorial (X - 1); -- # rec_factorial @@ -66,14 +66,14 @@ begin pragma Annotate -- # xelab_1 (Xcov, Exempt_On, -- # xelab_1 "exemption on elaboration code - 1"); -- # xelab_1 - Z := Identity (3); -- # xelab_1 + Z := Identity (3); -- # xelab_1_vio pragma Annotate (Xcov, Exempt_Off); -- # xelab_1 Another_Swap (X, Y); -- # elab pragma Annotate -- # xelab_2 (Xcov, Exempt_On, -- # xelab_2 - "exemption on elaboration code - 2"); -- # xelab_2 + "exemption on elaboration code - 2"); -- # xelab_2_vio Another_Swap (Z, X); -- # xelab_2 pragma Annotate (Xcov, Exempt_Off); -- # xelab_2 end Exemptions; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.ads b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.ads index e8ef3f37d..e65c7b770 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.ads +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/exemptions.ads @@ -15,11 +15,11 @@ package Exemptions is -- Mix of exempted and non-exempted declarations - X : Integer := Identity (1); -- # decl + X : Integer := Identity (1); -- # decl pragma Annotate -- # xdecl (Xcov, Exempt_On, "exemption on global declaration"); -- # xdecl - Y : Integer := Identity (2); -- # xdecl + Y : Integer := Identity (2); -- # xdecl_vio pragma Annotate (Xcov, Exempt_Off); -- # xdecl Z : Integer := 1; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_non_exempted_code_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_non_exempted_code_call.adb index 94ec629cd..dbb1ff30e 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_non_exempted_code_call.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_non_exempted_code_call.adb @@ -32,11 +32,13 @@ end Test_Exemptions_All_Non_Exempted_Code_Call; --# exemptions.adb -- /xswap/ l* ## x+ +-- /xswap_vio/ l= ## Xs- -- /swap_stmt/ l- ## s- -- /factorial/ l+ ## 0 -- /1_factorial/ l+ ## 0 -- /xfactorial/ l* ## x+ +-- /xfactorial_vio/ l= ## Xs- -- /elsif_factorial/ l+ ## 0 -- /rec_factorial/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb index 3ed02f507..b5689ce09 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb @@ -20,11 +20,13 @@ end Test_Exemptions_No_Call; --# exemptions.adb -- /xswap/ l* ## x+ +-- /xswap_vio/ l= ## Xs- -- /swap_stmt/ l- ## s- -- /factorial/ l- ## s- -- /1_factorial/ l- ## s- -- /xfactorial/ l* ## x+ +-- /xfactorial_vio/ l= ## Xs- -- /elsif_factorial/ l- ## s- -- /rec_factorial/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb index 060b67906..74e38a8f8 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb @@ -31,11 +31,13 @@ end Test_Exemptions_Non_Exempted_Code_Call; --# exemptions.adb -- /xswap/ l* ## x+ +-- /xswap_vio/ l= ## Xs- -- /swap_stmt/ l- ## s- -- /factorial/ l+ ## 0 -- /1_factorial/ l+ ## 0 -- /xfactorial/ l* ## x+ +-- /xfactorial_vio/ l= ## Xs- -- /elsif_factorial/ l+ ## 0 -- /rec_factorial/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/stacks.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/stacks.adb index 865f35ead..4739b87f8 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/stacks.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/stacks.adb @@ -6,8 +6,8 @@ package body Stacks is when Push => pragma Annotate -- # op_oflow (Xcov, Exempt_On, "no overflow"); -- # op_oflow - if S.Vcount = S.Size then -- # op_oflow - raise Constraint_Error; -- # op_oflow + if S.Vcount = S.Size then -- # op_oflow_v1 + raise Constraint_Error; -- # op_oflow_v2 end if; -- # op_oflow pragma Annotate (Xcov, Exempt_Off); -- # op_oflow @@ -17,8 +17,8 @@ package body Stacks is when Pop => pragma Annotate -- # op_uflow (Xcov, Exempt_On, "no underflow"); -- # op_uflow - if S.Vcount = 0 then -- # op_uflow - raise Constraint_Error; -- # op_uflow + if S.Vcount = 0 then -- # op_uflow_v1 + raise Constraint_Error; -- # op_uflow_v2 end if; -- # op_uflow pragma Annotate (Xcov, Exempt_Off); -- # op_uflow diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_0.adb index 932227699..9867b0aca 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_0.adb @@ -8,12 +8,16 @@ begin end; --# stacks.adb --- /op_case/ l- ## s- --- /op_push/ l- ## s- --- /op_pop/ l- ## s- --- /op_oflow/ l* ## x+ --- /op_uflow/ l* ## x+ --- /op_handler/ l- ## s- +-- /op_case/ l- ## s- +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /op_oflow/ l* ## x+ +-- /op_oflow_v1/ l= ## Xs- +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l* ## x+ +-- /op_uflow_v1/ l= ## Xs- +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l- ## s- -- /push_decl/ l- ## s- -- /push_body/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pop_u.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pop_u.adb index 8928f37f1..c77127091 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pop_u.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pop_u.adb @@ -12,14 +12,16 @@ begin end; --# stacks.adb --- /op_push/ l- ## s- --- /op_pop/ l- ## s- --- /op_oflow/ l* ## x+ --- /op_uflow/ l# ## x0 --- /op_handler/ l+ ## 0 +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /op_oflow/ l* ## x+ +-- /op_oflow_v1/ l= ## Xs- +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l# ## x0 +-- /op_handler/ l+ ## 0 --- /push_decl/ l- ## s- --- /push_body/ l- ## s- --- /pop_decl/ l+ ## 0 --- /pop_body/ l+ ## 0 --- /err_body/ l+ ## 0 +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_0.adb index db054a9e5..353642beb 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_0.adb @@ -11,14 +11,17 @@ begin end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l- ## s- --- /op_oflow/ l* ## x+ --- /op_uflow/ l* ## x+ --- /op_handler/ l- ## s- +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /op_oflow/ l* ## x+ +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l* ## x+ +-- /op_uflow_v1/ l= ## Xs- +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l- ## s- --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l- ## s- --- /pop_body/ l- ## s- --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_o.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_o.adb index 67d18c8d2..9839a964f 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_o.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_o.adb @@ -15,14 +15,16 @@ begin end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l- ## s- --- /op_oflow/ l# ## x0 --- /op_uflow/ l* ## x+ --- /op_handler/ l+ ## 0 +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /op_oflow/ l# ## x0 +-- /op_uflow/ l* ## x+ +-- /op_uflow_v1/ l= ## Xs- +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l+ ## 0 --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l- ## s- --- /pop_body/ l- ## s- --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_0.adb index 716f9c59b..ea1eefc79 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_0.adb @@ -19,14 +19,16 @@ begin end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l+ ## 0 --- /op_oflow/ l* ## x+ --- /op_uflow/ l* ## x+ --- /op_handler/ l- ## s- +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l* ## x+ +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l* ## x+ +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l- ## s- --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l+ ## 0 --- /pop_body/ l+ ## 0 --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_o.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_o.adb index c3c0ef250..04f397815 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_o.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_o.adb @@ -18,14 +18,15 @@ begin end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l+ ## 0 --- /op_oflow/ l# ## x0 --- /op_uflow/ l* ## x+ --- /op_handler/ l+ ## 0 +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l# ## x0 +-- /op_uflow/ l* ## x+ +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l+ ## 0 --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l+ ## 0 --- /pop_body/ l+ ## 0 --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_u.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_u.adb index 6ba181281..6c9635276 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_u.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_u.adb @@ -16,14 +16,15 @@ begin end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l+ ## 0 --- /op_oflow/ l* ## x+ --- /op_uflow/ l# ## x0 --- /op_handler/ l+ ## 0 +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l* ## x+ +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l# ## x0 +-- /op_handler/ l+ ## 0 --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l+ ## 0 --- /pop_body/ l+ ## 0 --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.adb index eb897d474..f505aaed2 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.adb @@ -18,7 +18,7 @@ begin pragma Annotate -- # init_call (Xcov, Exempt_On, "auto init off"); -- # init_call - Initialize; -- # init_call + Initialize; -- # init_call_violation pragma Annotate (Xcov, Exempt_Off); -- # init_call end if; end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/gcom.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/gcom.adb index 34a429409..33be8e459 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/gcom.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/gcom.adb @@ -15,7 +15,7 @@ begin pragma Annotate -- # init_call (Xcov, Exempt_On, "auto init off"); -- # init_call - Initialize; -- # init_call + Initialize; -- # init_call_violation pragma Annotate (Xcov, Exempt_Off); -- # init_call end if; end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_com.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_com.adb index 2eb75e790..d1c453f5d 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_com.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_com.adb @@ -10,5 +10,6 @@ begin end; --# com.adb --- /init_body/ l- ## s- --- /init_call/ l* ## x+ +-- /init_body/ l- ## s- +-- /init_call/ l* ## x+ +-- /init_call_violation/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_gcom_f.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_gcom_f.adb index 6e6523495..eaaed1e0a 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_gcom_f.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/test_gcom_f.adb @@ -8,5 +8,6 @@ begin end; --# gcom.adb --- /init_body/ l- ## s- --- /init_call/ l* ## x+ +-- /init_body/ l- ## s- +-- /init_call/ l* ## x+ +-- /init_call_violation/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/stacks.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/stacks.adb index fcbcbc478..bb1693137 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/stacks.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/stacks.adb @@ -26,7 +26,7 @@ package body Stacks is pragma Annotate -- # op_handler (Xcov, Exempt_On, "exception handler"); -- # op_handler - S.Ecount := S.Ecount + 1; -- # op_handler + S.Ecount := S.Ecount + 1; -- # op_handler_stmt pragma Annotate (Xcov, Exempt_Off); -- # op_handler end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_0.adb index d0a9511dc..50faca385 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_0.adb @@ -8,17 +8,18 @@ begin end; --# stacks.adb --- /op_case/ l- ## s- --- /op_push/ l- ## s- --- /op_pop/ l- ## s- --- /test_oflow/ l- ## s- --- /op_oflow/ l- ## s- --- /test_uflow/ l- ## s- --- /op_uflow/ l- ## s- --- /op_handler/ l* ## x+ +-- /op_case/ l- ## s- +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /test_oflow/ l- ## s- +-- /op_oflow/ l- ## s- +-- /test_uflow/ l- ## s- +-- /op_uflow/ l- ## s- +-- /op_handler/ l* ## x+ +-- /op_handler_stmt/ l= ## Xs- --- /push_decl/ l- ## s- --- /push_body/ l- ## s- --- /pop_decl/ l- ## s- --- /pop_body/ l- ## s- --- /err_body/ l- ## s- +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_push_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_push_0.adb index d98c992e8..347eee539 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_push_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_push_0.adb @@ -11,16 +11,17 @@ begin end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l- ## s- --- /test_oflow/ l+ ## 0 --- /op_oflow/ l- ## s- --- /test_uflow/ l- ## s- --- /op_uflow/ l- ## s- --- /op_handler/ l* ## x+ +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l- ## s- +-- /test_uflow/ l- ## s- +-- /op_uflow/ l- ## s- +-- /op_handler/ l* ## x+ +-- /op_handler_stmt/ l= ## Xs- --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l- ## s- --- /pop_body/ l- ## s- --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_pushpop_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_pushpop_0.adb index dfabd1777..2a09c98fa 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_pushpop_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInHandler/src/test_pushpop_0.adb @@ -19,16 +19,17 @@ begin end; --# stacks.adb --- /op_push/ l+ ## 0 --- /op_pop/ l+ ## 0 --- /test_oflow/ l+ ## 0 --- /op_oflow/ l- ## s- --- /test_uflow/ l+ ## 0 --- /op_uflow/ l- ## s- --- /op_handler/ l* ## x+ +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l- ## s- +-- /test_uflow/ l+ ## 0 +-- /op_uflow/ l- ## s- +-- /op_handler/ l* ## x+ +-- /op_handler_stmt/ l= ## Xs- --- /push_decl/ l+ ## 0 --- /push_body/ l+ ## 0 --- /pop_decl/ l+ ## 0 --- /pop_body/ l+ ## 0 --- /err_body/ l+ ## 0 +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/multiple_exemptions.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/multiple_exemptions.adb index ebe44229c..f2dc62257 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/multiple_exemptions.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/multiple_exemptions.adb @@ -25,7 +25,7 @@ begin Xf.X1 := True; -- # 1_flag pragma Annotate -- # 1_exem (Xcov, Exempt_On, "exemption section #1"); -- # 1_exem - raise Constraint_Error; -- # 1_exem + raise Constraint_Error; -- # 1_exem_v1 pragma Annotate (Xcov, Exempt_Off); -- # 1_exem end if; @@ -35,7 +35,7 @@ begin Xf.X2 := True; -- # 2_flag pragma Annotate -- # 2_exem (Xcov, Exempt_On, "exemption section #2"); -- # 2_exem - J := -J; -- # 2_exem + J := -J; -- # 2_exem_v1 pragma Annotate (Xcov, Exempt_Off); -- # 2_exem end if; I := Tmp; -- # 2_if @@ -47,7 +47,7 @@ begin Xf.X3 := True; -- # 3_flag pragma Annotate -- # 3_exem (Xcov, Exempt_On, "exemption section #3"); -- # 3_exem - J := 1; -- # 3_exem + J := 1; -- # 3_exem_v1 pragma Annotate (Xcov, Exempt_Off); -- # 3_exem end if; K := K + I; -- # 3_if @@ -61,9 +61,9 @@ exception pragma Annotate -- # h_exem (Xcov, Exempt_On, "exemption section in handler"); -- # h_exem - Tmp := I + J + K; -- # h_exem - I := Tmp; -- # h_exem - J := Tmp + 1; -- # h_exem - K := Tmp + 2; -- # h_exem + Tmp := I + J + K; -- # h_exem_v1 + I := Tmp; -- # h_exem_v2 + J := Tmp + 1; -- # h_exem_v3 + K := Tmp + 2; -- # h_exem_v4 pragma Annotate (Xcov, Exempt_Off); -- # h_exem end Multiple_Exemptions; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_0.adb index 6a7e8bf5c..fa6b14f28 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_0.adb @@ -13,13 +13,20 @@ end Test_0; -- /1_if/ l- ## s- -- /1_flag/ l- ## s- -- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- -- /stmt/ l- ## s- -- /2_if/ l- ## s- -- /2_flag/ l- ## s- -- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- -- /3_if/ l- ## s- -- /3_flag/ l- ## s- -- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- -- /h_flag/ l- ## s- -- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_all.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_all.adb index d408d7cd1..632346ad6 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_all.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_all.adb @@ -11,14 +11,21 @@ end; --# multiple_exemptions.adb -- /dcl/ l+ ## 0 -- /1_if/ l+ ## 0 --- /1_flag/ l- ## s- +-- /1_flag/ l- ## s- -- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- -- /stmt/ l+ ## 0 -- /2_if/ l+ ## 0 --- /2_flag/ l- ## s- +-- /2_flag/ l- ## s- -- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- -- /3_if/ l- ## s- --- /3_flag/ l- ## s- +-- /3_flag/ l- ## s- -- /3_exem/ l* ## x+ --- /h_flag/ l- ## s- --- /h_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- +-- /h_flag/ l- ## s- +-- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr12.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr12.adb index 5d88edf76..a6088e071 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr12.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr12.adb @@ -13,12 +13,18 @@ end; -- /1_if/ l+ ## 0 -- /1_flag/ l- ## s- -- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- -- /stmt/ l+ ## 0 -- /2_if/ l+ ## 0 -- /2_flag/ l- ## s- -- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- -- /3_if/ l+ ## 0 -- /3_flag/ l+ ## 0 -- /3_exem/ l# ## x0 -- /h_flag/ l- ## s- -- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr13.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr13.adb index 36f3b5b5f..174224dba 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr13.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr13.adb @@ -13,6 +13,7 @@ end; -- /1_if/ l+ ## 0 -- /1_flag/ l- ## s- -- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- -- /stmt/ l+ ## 0 -- /2_if/ l+ ## 0 -- /2_flag/ l+ ## 0 @@ -20,5 +21,10 @@ end; -- /3_if/ l- ## s- -- /3_flag/ l- ## s- -- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- -- /h_flag/ l- ## s- -- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr23.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr23.adb index c8a6741f8..716dfb969 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr23.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr23.adb @@ -22,8 +22,10 @@ end; -- /2_if/ l+ ## 0 -- /2_flag/ l- ## s- -- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- -- /3_if/ l- ## s- -- /3_flag/ l- ## s- -- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- -- /h_flag/ l+ ## 0 -- /h_exem/ l# ## x0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/stacks.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/stacks.adb index ab6aae143..2ae403847 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/stacks.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/stacks.adb @@ -9,31 +9,31 @@ package body Stacks is (S : in out Stack; Op : Op_Kind; V : in out Integer) -- # xregion is -- # xregion begin -- # xregion - case Op is -- # xregion + case Op is -- # xregion_1 when Push => -- # xregion - if S.Vcount = S.Size then -- # xregion - raise Constraint_Error; -- # xregion + if S.Vcount = S.Size then -- # xregion_2 + raise Constraint_Error; -- # xregion_3 end if; -- # xregion -- # xregion - S.Vcount := S.Vcount + 1; -- # xregion - S.Values (S.Vcount) := V; -- # xregion + S.Vcount := S.Vcount + 1; -- # xregion_4 + S.Values (S.Vcount) := V; -- # xregion_5 -- # xregion when Pop => -- # xregion - if S.Vcount = 0 then -- # xregion - raise Constraint_Error; -- # xregion + if S.Vcount = 0 then -- # xregion_6 + raise Constraint_Error; -- # xregion_7 end if; -- # xregion -- # xregion - V := S.Values (S.Vcount); -- # xregion - S.Vcount := S.Vcount - 1; -- # xregion + V := S.Values (S.Vcount); -- # xregion_8 + S.Vcount := S.Vcount - 1; -- # xregion_9 end case; -- # xregion exception -- # xregion when Constraint_Error => -- # xregion - S.Ecount := S.Ecount + 1; -- # xregion + S.Ecount := S.Ecount + 1; -- # xregion_10 end; -- # xregion -- # xregion function Errcount (S : in Stack) return Natural is -- # xregion begin -- # xregion - return S.Ecount; -- # xregion + return S.Ecount; -- # xregion_11 end; -- # xregion -- # xregion pragma Annotate (Xcov, Exempt_Off); -- # xregion diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_0.adb index 23dca794c..76a9e011d 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_0.adb @@ -8,7 +8,17 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_1/ l= ## Xs- +-- /xregion_2/ l= ## Xs- +-- /xregion_3/ l= ## Xs- +-- /xregion_4/ l= ## Xs- +-- /xregion_5/ l= ## Xs- +-- /xregion_6/ l= ## Xs- +-- /xregion_7/ l= ## Xs- +-- /xregion_8/ l= ## Xs- +-- /xregion_9/ l= ## Xs- +-- /xregion_10/ l= ## Xs- -- /push_decl/ l- ## s- -- /push_body/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pop_u.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pop_u.adb index b355ecc28..c2e43b187 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pop_u.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pop_u.adb @@ -11,7 +11,13 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_2/ l= ## Xs- +-- /xregion_3/ l= ## Xs- +-- /xregion_4/ l= ## Xs- +-- /xregion_5/ l= ## Xs- +-- /xregion_8/ l= ## Xs- +-- /xregion_9/ l= ## Xs- -- /push_decl/ l- ## s- -- /push_body/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_0.adb index 2d4c818ae..b93cb9493 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_0.adb @@ -11,7 +11,13 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_3/ l= ## Xs- +-- /xregion_6/ l= ## Xs- +-- /xregion_7/ l= ## Xs- +-- /xregion_8/ l= ## Xs- +-- /xregion_9/ l= ## Xs- +-- /xregion_10/ l= ## Xs- -- /push_decl/ l+ ## 0 -- /push_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_o.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_o.adb index 5ee282008..4e9bf2160 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_o.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_o.adb @@ -15,7 +15,11 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_6/ l= ## Xs- +-- /xregion_7/ l= ## Xs- +-- /xregion_8/ l= ## Xs- +-- /xregion_9/ l= ## Xs- -- /push_decl/ l+ ## 0 -- /push_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_0.adb index 3673fce4f..ceb981e76 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_0.adb @@ -19,7 +19,10 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_3/ l= ## Xs- +-- /xregion_7/ l= ## Xs- +-- /xregion_10/ l= ## Xs- -- /push_decl/ l+ ## 0 -- /push_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_o.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_o.adb index 857e36a97..5ed2e8edc 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_o.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_o.adb @@ -18,7 +18,8 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_7/ l= ## Xs- -- /push_decl/ l+ ## 0 -- /push_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_u.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_u.adb index 395db953a..26ec8ad68 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_u.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_u.adb @@ -16,7 +16,8 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ +-- /xregion/ l* ## x+ +-- /xregion_3/ l= ## Xs- -- /push_decl/ l+ ## 0 -- /push_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_0.adb index 871a749ce..c4c40190a 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_0.adb @@ -6,4 +6,7 @@ begin end; --# tipos.adb --- /xblock/ l* ## x+:"test exempting all" +-- /xblock/ l* ## x+:"test exempting all" +-- /xblock_if/ l= ## Xs- +-- /xblock_r1/ l= ## Xs- +-- /xblock_r2/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_other.adb b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_other.adb index 4de6b5f30..7e377b1f7 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_other.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_other.adb @@ -6,4 +6,5 @@ begin end; --# tipos.adb --- /xblock/ l* ## x+:"test exempting all" +-- /xblock/ l* ## x+:"test exempting all" +-- /xblock_r1/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_pos.adb b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_pos.adb index 534e1ebc4..c3b785427 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_pos.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/test_tipos_pos.adb @@ -6,4 +6,5 @@ begin end; --# tipos.adb --- /xblock/ l* ## x+:"test exempting all" +-- /xblock/ l* ## x+:"test exempting all" +-- /xblock_r2/ l= ## Xs- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.adb b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.adb index 7f9acb915..5ab7cc62b 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.adb @@ -4,10 +4,10 @@ begin pragma Annotate (Xcov, Exempt_On, -- # xblock "test exempting all"); -- # xblock - if X > 0 then -- # xblock - return X * 2; -- # xblock + if X > 0 then -- # xblock_if + return X * 2; -- # xblock_r1 else -- # xblock - return X; -- # xblock + return X; -- # xblock_r2 end if; -- # xblock pragma Annotate (Xcov, Exempt_Off); -- # xblock end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/req.rst b/testsuite/Qualif/Ada/stmt/Exemptions/req.rst index 90a53fada..b6153c063 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/req.rst +++ b/testsuite/Qualif/Ada/stmt/Exemptions/req.rst @@ -12,17 +12,21 @@ Rule # Description 1 Exempted regions shall all be synthesized in a distinct section of the output report, with a single message per region. -2 Each exemption message shall specify the range of source locations - covered by the region declaration, and indicate whether 0 or more - coverage violations were actually exempted within this range. +2 Each message describing an exempted region shall specify the range of + source locations covered by the region declaration, and indicate whether + 0 or more coverage violations were actually exempted within this range. -3 Exemption regions shall not affect the diagnostics reported for +3 The type and location of exempted violations shall be displayed under + the corresponding exempted region message. + +4 Exemption regions shall not affect the diagnostics reported for constructs outside of such regions. -4 The report section dedicated to exemption regions shall not contain - any other kind of information. +5 The report section dedicated to exemption regions shall indicate the + total number of exemption regions and total number of exempted + violations, and shall not contain any other kind of information. -5 Exemption regions may be declared to exempt various levels of +6 Exemption regions may be declared to exempt various levels of syntactic constructs such as statements or subprograms, and groups of such in all the contexts where they may appear. ====== ====================================================================== @@ -32,7 +36,7 @@ Rule # Description The following set of testcases checks compliance with this requirement. The testcases are partitioned into sections -according to point #5 - demonstrate ability to exempt +according to point #6 - demonstrate ability to exempt various groups of syntactic constructs: @@ -44,10 +48,10 @@ various groups of syntactic constructs: Each test contains a combination of exempted regions and regular code, exercised in several ways to cover well-identified sections of the program. -All the other aspects of the requirement (rules #1 to #4) are validated by +All the other aspects of the requirement (rules #1 to #5) are validated by demonstrating that all the tests run as expected. -For each stated expectation, exempted region, or non-exempted -violation, the testsuite driver checks if it appears in the expected report -section (in addition to its regular checks). +For each stated expectation, exempted region, exempted violation and +non-exempted violation, the testsuite driver checks if it appears in the +expected report section (in addition to its regular checks). diff --git a/testsuite/Qualif/Common/Report/Exemptions/src/ranges.adb b/testsuite/Qualif/Common/Report/Exemptions/src/ranges.adb index 92ed7ac63..94885d748 100644 --- a/testsuite/Qualif/Common/Report/Exemptions/src/ranges.adb +++ b/testsuite/Qualif/Common/Report/Exemptions/src/ranges.adb @@ -15,9 +15,9 @@ package body Ranges is begin pragma Annotate -- # preValid (Xcov, Exempt_On, "expect no invalid ranges"); -- # preValid - if not (R1.Valid and then R2.Valid) then -- # preValid - N_Invalid_Inputs := N_Invalid_Inputs + 1; -- # preValid - return True; -- # preValid + if not (R1.Valid and then R2.Valid) then -- # preValid_if + N_Invalid_Inputs := N_Invalid_Inputs + 1; -- # preValid_inc + return True; -- # preValid_ret end if; -- # preValid pragma Annotate (Xcov, Exempt_Off); -- # preValid diff --git a/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_invalid.adb b/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_invalid.adb index 5dfa0dfc9..782d0f36f 100644 --- a/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_invalid.adb +++ b/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_invalid.adb @@ -17,6 +17,9 @@ end; -- /assignValid/ l+ ## 0 -- /assignInvalid/ l+ ## 0 -- /preValid/ s=>l#, dum=>l* ## s=>x0, dum=>x+ +-- /preValid_if/ s=>l=, dum=>l= ## s=>X0, dum=>XoF- +-- /preValid_inc/ s=>l=, dum=>l= ## s=>X0, dum=>X0 +-- /preValid_ret/ s=>l=, dum=>l= ## s=>X0, dum=>X0 -- /checkOverlap/ l- ## s- -- /overlapTrue/ l- ## s- -- /overlapFalse/ l- ## s- diff --git a/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_overlap.adb b/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_overlap.adb index fa751f210..4955665a1 100644 --- a/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_overlap.adb +++ b/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_overlap.adb @@ -40,6 +40,9 @@ end; -- /assignValid/ l+ ## 0 -- /assignInvalid/ l- ## s- -- /preValid/ l* ## x+ +-- /preValid_if/ l= ## XoT- +-- /preValid_inc/ l= ## Xs- +-- /preValid_ret/ l= ## Xs- -- /checkOverlap/ l! ## dF- -- /overlapTrue/ l+ ## 0 -- /overlapFalse/ l- ## s- From adfb2c3883fc47a654f8f45a9c0da0efdfea8b5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Mon, 3 Apr 2023 15:10:19 +0200 Subject: [PATCH 0278/1483] Document gnatcov usage change for the display of exempted violations TN: TC31-001 --- doc/gnatcov/exemptions.rst | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/doc/gnatcov/exemptions.rst b/doc/gnatcov/exemptions.rst index f0cd6c7ef..317bc2e3e 100644 --- a/doc/gnatcov/exemptions.rst +++ b/doc/gnatcov/exemptions.rst @@ -137,15 +137,12 @@ The corresponding :cmd-option:`=report` excerpt below illustrates this for the No non-exempted DECISION violation. 1 exempted region. -It is possible to display the exempted violations to let the user check that -they match the expected ones. This can be done by using the -:cmd-option:`--all-messages` switch. That way, the report will show the -previously mentionned information along with the observed violations under -their corresponding exempted block, and the total number of exempted violations -found across all exempted regions. - -The :cmd-option:`=report` excerpt below produced while -:cmd-option:`--all-messages` is used illustrates this for the ``Eassert`` +The exempted violations are also displayed to let the user check that they +match the expected ones. The report shows the previously mentioned information +along with the observed violations under their corresponding exempted block, +and the total number of exempted violations found across all exempted regions. + +The :cmd-option:`=report` excerpt below illustrates this for the ``Eassert`` example:: ... From 087e2090cc3cf17d8fe18129e64ee76c4a4e3963 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 20 Mar 2023 12:50:20 +0100 Subject: [PATCH 0279/1483] Change the report produced for --annotate=html[+] There should be no reason to pick the HTML format over the dynamic HTML format. This commit switches the report produced when --annotate=html[+] is passed to the gnatcov coverage command to actually produce a dhtml report. We choose to keep for now the static HTML version, and produce it when the (undocumented) shtml[+] option is passed to the annotate switch. --- testsuite/tests/16-check-html/foo.adb | 14 +++++++++++ testsuite/tests/16-check-html/test.py | 29 ++++++++++++++++++++++ tools/gnatcov/annotations-dynamic_html.adb | 2 +- tools/gnatcov/annotations-html.adb | 2 +- tools/gnatcov/annotations.adb | 13 ++++++++-- tools/gnatcov/annotations.ads | 6 ++--- tools/gnatcov/command_line.ads | 2 +- tools/gnatcov/gnatcov_bits_specific.adb | 10 ++++---- 8 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 testsuite/tests/16-check-html/foo.adb create mode 100644 testsuite/tests/16-check-html/test.py diff --git a/testsuite/tests/16-check-html/foo.adb b/testsuite/tests/16-check-html/foo.adb new file mode 100644 index 000000000..ca4ad6568 --- /dev/null +++ b/testsuite/tests/16-check-html/foo.adb @@ -0,0 +1,14 @@ +procedure Foo is + function Fact (N : Natural) return Natural is + begin + if N <= 1 then + return 1; + else + return N * Fact (N - 1); + end if; + end Fact; +begin + if Fact (6) /= 720 then + raise Program_Error; + end if; +end Foo; diff --git a/testsuite/tests/16-check-html/test.py b/testsuite/tests/16-check-html/test.py new file mode 100644 index 000000000..fd6f7c45d --- /dev/null +++ b/testsuite/tests/16-check-html/test.py @@ -0,0 +1,29 @@ +""" +Check that --annotate=html produces a dynamic html report. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["foo.adb"], + srcdirs=[".."])), + covlevel="stmt", + mains=["foo"], + extra_coverage_args=["--annotate=html", "--output-dir=html"], +) + +js_file = os.path.join("html", "foo.adb.hunk.js") +thistest.fail_if( + not os.path.exists(js_file), + "expecting a dynamic html report" +) + +thistest.result() diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 11249fb48..3f30f6955 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -295,7 +295,7 @@ package body Annotations.Dynamic_Html is Annotations.Generate_Report (Pp, Show_Details => True, - Subdir => "dhtml"); + Subdir => "html"); end Generate_Report; ------------------------ diff --git a/tools/gnatcov/annotations-html.adb b/tools/gnatcov/annotations-html.adb index 4b42522fe..2eb037afc 100644 --- a/tools/gnatcov/annotations-html.adb +++ b/tools/gnatcov/annotations-html.adb @@ -224,7 +224,7 @@ package body Annotations.Html is Annotations.Generate_Report (Pp, Show_Details, - Subdir => (if Show_Details then "html+" else "html")); + Subdir => (if Show_Details then "shtml+" else "shtml")); end Generate_Report; --------- diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index a64156dda..cadb8641c 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -868,11 +868,20 @@ package body Annotations is elsif Option = "xcov+" then return Annotate_Xcov_Plus; + -- Note that we only keep these option names (html+ and dhtml) for + -- backward compatibility. + elsif Option = "html+" then - return Annotate_Html_Plus; + return Annotate_Html; elsif Option = "dhtml" then - return Annotate_Dynamic_Html; + return Annotate_Html; + + elsif Option = "shtml" then + return Annotate_Static_Html; + + elsif Option = "shtml+" then + return Annotate_Static_Html_Plus; elsif Option = "report" then return Annotate_Report; diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 925afff4e..7454f0180 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -41,10 +41,10 @@ package Annotations is type Annotation_Format is (Annotate_Asm, Annotate_Xcov, - Annotate_Html, + Annotate_Static_Html, Annotate_Xcov_Plus, - Annotate_Html_Plus, - Annotate_Dynamic_Html, + Annotate_Static_Html_Plus, + Annotate_Html, Annotate_Cobertura, Annotate_Xml, Annotate_Report, diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 40a7d135b..abe6c2b91 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -1084,7 +1084,7 @@ package Command_Line is Pattern => "[FORM|LIST]", Help => "Generate a FORM report. FORM is one of:" - & ASCII.LF & " asm, xcov, html, xcov+, html+, dhtml, report." + & ASCII.LF & " asm, xcov, html, xcov+, report." & ASCII.LF & "Multiple reports can be produced in a single" & " execution by passing a comma separated list of FORMs to this" & " option, or by specifying this option multiple times on the" diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index f03c15d0c..41c3e0d7d 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1663,7 +1663,7 @@ begin Fatal_Error ("XML report format support is not installed."); end if; - if Annotation (Annotate_Dynamic_Html) + if Annotation (Annotate_Html) and then not Annotations.Dynamic_Html.Installed then Fatal_Error @@ -2313,16 +2313,16 @@ begin Show_Details => Annotation (Annotate_Xcov_Plus)); end if; - if Annotation (Annotate_Html) - or else Annotation (Annotate_Html_Plus) + if Annotation (Annotate_Static_Html) + or else Annotation (Annotate_Static_Html_Plus) then Annotations.Html.Generate_Report (Context'Unchecked_Access, - Show_Details => Annotation (Annotate_Html_Plus), + Show_Details => Annotation (Annotate_Static_Html_Plus), Report_Title => Args.String_Args (Opt_Report_Title)); end if; - if Annotation (Annotate_Dynamic_Html) then + if Annotation (Annotate_Html) then Annotations.Dynamic_Html.Generate_Report (Context'Unchecked_Access, Report_Title => Args.String_Args (Opt_Report_Title)); From 9e9e97c6a2cb1a800bc0b97a83c7ce2d0a05f8c8 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 12 Apr 2023 16:09:13 +0200 Subject: [PATCH 0280/1483] Remove mentions to html+ and dhtml in the documentation Also update some figures to show the dhtml report, instead of the html report, and update documentation regarding dhtml to fit better. --- doc/gnatcov/appendix.rst | 7 +- doc/gnatcov/bin_intro.rst | 4 +- doc/gnatcov/cov_common_switches.rst | 24 ++-- doc/gnatcov/cov_object.rst | 58 +++----- doc/gnatcov/cov_source.rst | 135 ++++++++---------- ...l-index-lines.png => html-index-lines.png} | Bin ...gations.png => html-index-obligations.png} | Bin doc/gnatcov/sample_sc_html_index.png | Bin 160518 -> 115145 bytes doc/gnatcov/sample_sc_html_unit.png | Bin 53025 -> 98702 bytes .../examples/support/Makefile.examples | 6 +- 10 files changed, 101 insertions(+), 133 deletions(-) rename doc/gnatcov/{dhtml-index-lines.png => html-index-lines.png} (100%) rename doc/gnatcov/{dhtml-index-obligations.png => html-index-obligations.png} (100%) diff --git a/doc/gnatcov/appendix.rst b/doc/gnatcov/appendix.rst index 67e6ad730..0a26607e4 100644 --- a/doc/gnatcov/appendix.rst +++ b/doc/gnatcov/appendix.rst @@ -71,10 +71,9 @@ where is a source-filename:line:column source location of the problematic line. In annotated sources kinds of outputs, this materializes as '!' note indicating -partial coverage on the affected lines, with the :cmd-option:`=report` -violation text quoted above available as part of the line extra-details -expanded on demand (:cmd-option:`=html+` and :cmd-option:`xcov+` output -formats). +partial coverage on the affected lines, with the :cmd-option:`=report` violation +text quoted above available as part of the line extra-details expanded on demand +(:cmd-option:`=html` and :cmd-option:`xcov+` output formats). .. _mcdc-limitations: diff --git a/doc/gnatcov/bin_intro.rst b/doc/gnatcov/bin_intro.rst index eed05df17..398eebd1b 100644 --- a/doc/gnatcov/bin_intro.rst +++ b/doc/gnatcov/bin_intro.rst @@ -64,9 +64,9 @@ trace production modes: - Yes * - *New features* - Often not - - Yes (source level metrics for C++, scoped metrics in dhtml) + - Yes (source level metrics for C++, scoped metrics in html) + - Workflow overview ----------------- diff --git a/doc/gnatcov/cov_common_switches.rst b/doc/gnatcov/cov_common_switches.rst index 1bd6c8a27..76d295d7b 100644 --- a/doc/gnatcov/cov_common_switches.rst +++ b/doc/gnatcov/cov_common_switches.rst @@ -4,20 +4,20 @@ is used by default. :cmd-option:`--output-dir` : - Request that the report files (index and annotated sources for the - ``xcov``, ``html`` and ``dhtml`` output formats) be output in the provided - directory. If not specified, the default is the root project's object - directory if using projects, and the current directory if not. - If more than one of the above annotation formats is requested, then each - report will be placed in a subdirectory named accordingly. + Request that the report files (index and annotated sources for the ``xcov`` + and ``html`` output formats) be output in the provided directory. If not + specified, the default is the root project's object directory if using + projects, and the current directory if not. If more than one of the above + annotation formats is requested, then each report will be placed in a + subdirectory named accordingly. :cmd-option:`--report-title` : - Request that generated HTML documents (index and annotated sources for the - ``html`` and ``dhtml`` output formats) are assigned a customized title. For - instance, passing ``--report-title="Project ABC"`` will yield titles such - as: ``Project ABC - GNATcoverage Report``. If passed multiple times, passing - an empty string last will restore the default behavior. This option is - ignored is the selected output format does not support titles. + Request that generated HTML documents (index for the ``html`` output format) + are assigned a customized title. For instance, passing + ``--report-title="Project ABC"`` will yield titles such as: ``Project ABC - + GNATcoverage Report``. If passed multiple times, passing an empty string last + will restore the default behavior. This option is ignored is the selected + output format does not support titles. :cmd-option:`-T`, :cmd-option:`--trace` |marg|, |rarg| : Provide the set of execution traces for which a report is to be diff --git a/doc/gnatcov/cov_object.rst b/doc/gnatcov/cov_object.rst index 87106f6ec..f827c00cb 100644 --- a/doc/gnatcov/cov_object.rst +++ b/doc/gnatcov/cov_object.rst @@ -71,13 +71,12 @@ The available options are as follows: explained later in this chapter. :cmd-option:`-a`, :cmd-option:`--annotate` |marg|: - Request a specific output report format. The two possible criteria support - ``xcov[+]``, ``html[+]``, ``dhtml`` and ``asm``, with interpretations that - vary depending on the assessed criteria. See the corresponding - documentation later in this chapter for more details. - This option accepts comma separated values and/or can be specified multiple - times on the command line, in which case there will be one report produced - for each of the requested annotation formats. + Request a specific output report format. The two possible criteria support + ``xcov[+]``, ``html``, and ``asm``, with interpretations that vary depending + on the assessed criteria. See the corresponding documentation later in this + chapter for more details. This option accepts comma separated values and/or + can be specified multiple times on the command line, in which case there will + be one report produced for each of the requested annotation formats. .. include:: cov_common_switches.rst @@ -118,11 +117,11 @@ The :cmd-option:`asm` format produces an annotated assembly output, with a coverage indication attached to every single instruction. This is the base information of interest to object coverage analysis, simply presented in different manners through the other possible output formats. The -:cmd-option:`xcov`, :cmd-option:`html`, and :cmd-option:`dhtml` formats produce -a set of annotated source files, in the directory where |gcv| is launched -unless overriden with a :cmd-option:`--output-dir` option. Even though -presented on sources, the annotations remain representative of object coverage -metrics, synthesized for all the instructions associated with each source line. +:cmd-option:`xcov` and :cmd-option:`html` formats produce a set of annotated +source files, in the directory where |gcv| is launched unless overriden with a +:cmd-option:`--output-dir` option. Even though presented on sources, the +annotations remain representative of object coverage metrics, synthesized for +all the instructions associated with each source line. Later in this chapter we name output formats by the text to add to :cmd-option:`--annotate` on the command line. For example, we use "the @@ -257,37 +256,24 @@ With :cmd-option:`--annotate=xcov+` (extra ``+`` at the end), the machine instructions and their individual coverage status are printed next to their associated source line. -Annotated sources, html (:cmd-option:`=html[+]`) or dynamic html (:cmd-option:`=dhtml`) +Annotated sources, html (:cmd-option:`=html`) --------------------------------------------------------------------------------------- -For object coverage criteria, |gcvcov| :cmd-option:`--annotate=html` produces -an annotated version of each source file, in html format, named after the -original source with an extra ``.html`` extension at the end. Each annotated -source page contains a summary of the assessment results followed by the -original source lines, all numbered and marked with a coverage annotation as in -the :cmd-option:`--annotate=xcov` case. In addition, lines with obligations are +For object coverage criteria, |gcvcov| :cmd-option:`--annotate=html` produces an +annotated version of each source file. Each annotated source page contains a +summary of the assessment results followed by the original source lines, all +numbered and marked with a coverage annotation as in the +:cmd-option:`--annotate=xcov` case. In addition, lines with obligations are colorized in green, orange or red for ``+``, ``!`` or ``-`` coverage respectively. An `index.html` page is also produced, which contains a description of the assessment context (assessed criteria, set of trace files involved, ...) and a summary of the coverage results for all the units, with links to their annotated sources. -Similarily to the :cmd-option:`xcov` format case, -:cmd-option:`--annotate=html+` (with a trailing +) attaches to each line -details about the coverage status of all the individual instructions generated -for the line. These are folded within the line and expanded when a mouse click -hits it. - -The page style is governed by a set of Cascading Style Sheet (CSS) parameters, -fetched from a ``xcov.css`` file in the directory where |gcv| is launched. If -this file is available when |gcv| starts, |gcv| uses it so users may setup a -customized version if needed. If the file is not available, |gcv| creates a -default one. - -As for source coverage criteria, the :cmd-option:`dhtml` variant produces a -more elaborate kind of report, with sortable columns and per-project indexes on -the root page when the units of interest were specified using the -:cmd-option:`-P` option. +Similarily to the :cmd-option:`xcov` format case, :cmd-option:`--annotate=html` +attaches to each line details about the coverage status of all the individual +instructions generated for the line. These are folded within the line and +expanded when a mouse click hits it. .. _ocov-insn: @@ -656,7 +642,7 @@ the corresponding source line in the :cmd-option:`=xcov` output (``!`` on line 12 +: end Count; 13 .: end Genpos; -And the :cmd-option:`=xcov+` (or :cmd-option:`=html+`) output gathers +And the :cmd-option:`=xcov+` (or :cmd-option:`=html`) output gathers everything together, with the blocks of instructions coming from different instances identifiable by the associated object symbol names:: diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index a1beb025b..62972c5f9 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -51,13 +51,12 @@ The available options are as follows: :cmd-option:`stmt+uc_mcdc`, all explained later in this chapter. :cmd-option:`-a`, :cmd-option:`--annotate` |marg|: - Request one or more output report formats. All the criteria support - ``xcov[+]``, ``html[+]``, ``dhtml`` and ``report`` formats, with - interpretations that vary depending on the assessed criteria. See the - corresponding documentation later in this chapter for more details. - This option accepts comma separated values and/or can be specified - mulitple times on the command line, in which case there will be one - report produced for each of the requested formats. + Request one or more output report formats. All the criteria support + ``xcov[+]``, ``html`` and ``report`` formats, with interpretations that vary + depending on the assessed criteria. See the corresponding documentation later + in this chapter for more details. This option accepts comma separated values + and/or can be specified mulitple times on the command line, in which case + there will be one report produced for each of the requested formats. :cmd-option:`-o` : Request that the synthetic report produced by ``--annotate=report`` be @@ -184,7 +183,7 @@ the following sections:: gnatcov coverage --level=stmt+decision --scos=@alis --annotate=html t1 t2 # Statement and Decision coverage assessments for two traces "t1" and "t2", - # producing html report files in the current directory. + # producing an html report in the current directory. gnatcov coverage --level=stmt+decision --scos=@alis --annotate=html @mytraces # Same report, with t1 and t2 listed in the "mytraces" text file @@ -205,13 +204,12 @@ Output report formats (:cmd-option:`--annotate`) Source coverage reports may be produced in various formats, as requested with the :cmd-option:`--annotate` command line argument of |gcvcov|. The -:cmd-option:`xcov`, :cmd-option:`html` and :cmd-option:`dhtml` formats produce -a set of annotated source files, in the directory where |gcv| is launched -unless overriden with a :cmd-option:`--output-dir` option. The -:cmd-option:`report` output consists in a synthetic text report of -:term:`coverage violations ` with respect to the requested -criteria, produced on standard output by default or in the file specified by -the :cmd-option:`-o` command line option. +:cmd-option:`xcov` and :cmd-option:`html` formats produce a set of annotated +source files, in the directory where |gcv| is launched unless overriden with a +:cmd-option:`--output-dir` option. The :cmd-option:`report` output consists in a +synthetic text report of :term:`coverage violations ` with +respect to the requested criteria, produced on standard output by default or in +the file specified by the :cmd-option:`-o` command line option. Later in this chapter we name output formats by the text to add to :cmd-option:`--annotate` on the command line. For example, we use "the @@ -296,59 +294,44 @@ improperly satisfied obligation is an uncovered statement on line 7:: 7 -: return V >= X2 and then V <= X1; STATEMENT "return V ..." at 7:10 not executed -Annotated sources, html (:cmd-option:`=html[+]`) ------------------------------------------------- - -For source coverage criteria, |gcvcov| :cmd-option:`--annotate=html` produces -an annotated version of each source file, in html format, named after the -original source with an extra ``.html`` extension at the end. Each annotated -source page contains a summary of the assessment results followed by the -original source lines, all numbered and marked with a coverage annotation as in -the :cmd-option:`--annotate=xcov` case. Lines with obligations are colorized in -green, orange or red for ``+``, ``!`` or ``-`` coverage respectively. - -An `index.html` page is also produced, which contains a summary of the -assessment context (assessed criteria, trace files involved, ...) and of the -coverage results for all the units, with links to their annotated sources. -See our :ref:`sample html index ` appendix for an -example index page, which embeds a self-description of all the items it -contains. See the :ref:`sample annotated source ` -appendix for a sample of html annotated source. -The page style is governed by a set of Cascading Style Sheet (CSS) parameters, -fetched from a ``xcov.css`` file in the directory where |gcv| is launched. If -this file is available when |gcv| starts, |gcv| uses it so users may setup a -customized version if needed. If the file is not available, |gcv| creates a -default one. +Annotated sources, html (:cmd-option:`=html`) +--------------------------------------------- -Similarily to the :cmd-option:`xcov` format case, -:cmd-option:`--annotate=html+` (with a trailing +) adds details about -improperly satisfied obligations. In the html version, these extra details are -initially folded within their associated line and expanded by a mouse click on -the line. +For source coverage criteria, |gcvcov| :cmd-option:`--annotate=html` produces an +index-based report under the HTML format (the other command names are aliases +for backward compatibility). -Annotated sources, dynamic html (:cmd-option:`=dhtml`) ------------------------------------------------------- +To navigate the report, open the index.html file using the browser of your +choice. This index file contains a summary of the assessment context (assessed +criteria, trace files involved, ...) and of the coverage results for all the +units, with links to their annotated sources. If the :cmd-option:`-P` was used +to designate the source units of interest, sources are indexed per-project. -:cmd-option:`--annotate=dhtml` produces a *dynamic html* output, which -essentially features: +Note that some dynamic filtering / sorting can be applied: -* A more modern look & feel compared to the :cmd-option:`html` formats - described earlier, +* Filter by kind of coverage obligations: either reporting on lines, or on + statement / decision / MCDC (one or several) obligations, depending on the + coverage level. See :ref:`synthetic-metrics` for more information. -* The ability to sort indexes by clicking on column headers, allowing for - example sorts keyed on unit names or on relative coverage achievement, +* Sort indexes by clicking on column headers, allowing for example sorts keyed + on unit names or on relative coverage achievement. -* Per-project indexes on the root page when :cmd-option:`-P` was used to - designate the source units of interest. +See our :ref:`sample html index ` appendix for an +example index page, which embeds a self-description of all the items it +contains. -The option produces a set of `.js` javascript files implementing most of the -report displays and interactions, as well as an `index.html` root page which -users should open as an entry point to the report contents. +The user can browse through an annotated version of the sources from the index. +Each annotated source page contains a summary of the assessment results. This +summary can be expanded to print subprogram metrics: the user can click on a +subprogram's metrics to access it in the annotated source immediately. This +summary is followed by the original source lines, all numbered and marked with a +coverage annotation as in the :cmd-option:`--annotate=xcov` case. Lines with +obligations are colorized in green, orange or red for ``+``, ``!`` or ``-`` +coverage respectively. -The per-line details that differentiates :cmd-option:`html+` from -:cmd-option:`html` are always produced, initially folded and available on line -clicks as well. +See the :ref:`sample annotated source ` appendix for a +sample of html annotated source. Violations summary, text (:cmd-option:`=report`) @@ -827,8 +810,9 @@ following table summarizes the meaning of the possible annotations: absence of other known violations for that same line. When a trailing `+` is added to the format passed to :cmd-option:`--annotate` -(:cmd-option:`=xcov+` or :cmd-option:`=html+`), a precise description of the -actual violations is available for each line in addition to the annotation. +(:cmd-option:`=xcov+`), a precise description of the actual violations is +available for each line in addition to the annotation. The :cmd-option:`=html` +provides it by default. Example program and assessments ------------------------------- @@ -1444,14 +1428,14 @@ kind involved in the assessed level (here, for total number of obligations of the given kind and the ratio of such obligations which have been fully discharged. The ``xcov`` obligation metrics don't distinguish partially covered from uncovered items. This -information is available from the ``dhtml`` reports. +information is available from the ``html`` report. -For the ``dhtml`` output, synthetic metrics for all the units are +For the ``html`` output, synthetic metrics for all the units are first displayed on the index page, together with metrics for the entire analysis and for sets of units grouped by GPR project. Initially, the line count based metrics are displayed, as illustrated -by :numref:`dhtml-index-lines`. The main procedure source used in our ``xcov`` +by :numref:`html-index-lines`. The main procedure source used in our ``xcov`` report example is the ``main.adb`` source here, single source encompassed by the ``main.gpr`` project: @@ -1461,25 +1445,25 @@ names ("Stmt", "Decision" or "Mcdc"). Each kind of obligation can be selected alone. Selecting multiple kinds is also allowed and just sums the individual counts. -:numref:`dhtml-index-obligations` illustrates the results we get with +:numref:`html-index-obligations` illustrates the results we get with the ``Stmt`` and ``Decision`` kinds selected together for our previous example: -.. _dhtml-index-lines: +.. _html-index-lines: -.. figure:: dhtml-index-lines.* +.. figure:: html-index-lines.* :scale: 42% :align: center - Dhtml index with line count based synthetic metrics + Html index with line count based synthetic metrics -.. _dhtml-index-obligations: +.. _html-index-obligations: -.. figure:: dhtml-index-obligations.* +.. figure:: html-index-obligations.* :scale: 42% :align: center - Dhtml index with obligations count based synthetic metrics (stmt+decision) + Html index with obligations count based synthetic metrics (stmt+decision) .. _rebase_opts: @@ -1488,11 +1472,10 @@ Handling source relocation for annotated sources output formats =============================================================== For all annotated sources output formats -(:cmd-option:`--annotate=xcov[+]|html[+]|dhtml)`, |gcv| needs access -to the sources of the :term:`units of interest ` to -generate the output. The tool searches for sources in some default -locations which are usually correct when the whole coverage analysis -process is done on the same machine. +(:cmd-option:`--annotate=xcov[+]|html)`, |gcv| needs access to the sources of +the :term:`units of interest ` to generate the output. The +tool searches for sources in some default locations which are usually correct +when the whole coverage analysis process is done on the same machine. When coverage reports are produced on a different machine than the one where the coverage run was done, or when sources are moved in the diff --git a/doc/gnatcov/dhtml-index-lines.png b/doc/gnatcov/html-index-lines.png similarity index 100% rename from doc/gnatcov/dhtml-index-lines.png rename to doc/gnatcov/html-index-lines.png diff --git a/doc/gnatcov/dhtml-index-obligations.png b/doc/gnatcov/html-index-obligations.png similarity index 100% rename from doc/gnatcov/dhtml-index-obligations.png rename to doc/gnatcov/html-index-obligations.png diff --git a/doc/gnatcov/sample_sc_html_index.png b/doc/gnatcov/sample_sc_html_index.png index a4a7720d825d19e3feddd5b798b290cc5cab0dc2..d9ad654dd07d7c65b9001c54f7b8e4b3be9b5cdf 100644 GIT binary patch literal 115145 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%0DR|oRFKD?T6sqPWOFJnis1`)wc)kC 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 EAMLrZ?f?J) diff --git a/doc/gnatcov/sample_sc_html_unit.png b/doc/gnatcov/sample_sc_html_unit.png index 5a84d68d690d415c005cdbdbb0ad8a0cb6a7042d..e4f5ad5a0a7f958b26720962d769b01578601947 100644 GIT binary patch literal 98702 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 P_)knoTCjv)*ZcnfaFjPr diff --git a/tools/gnatcov/examples/support/Makefile.examples b/tools/gnatcov/examples/support/Makefile.examples index d54cd9917..9374e07e2 100644 --- a/tools/gnatcov/examples/support/Makefile.examples +++ b/tools/gnatcov/examples/support/Makefile.examples @@ -138,7 +138,7 @@ ckpt.list: force out-all-checkpoints/index.html: out-all-checkpoints $(ALL_CHECKPOINTS) ckpt.list $(XCOV) coverage --level=$(XCOVLEVEL) \ --checkpoint=@ckpt.list \ - --annotate=dhtml --output-dir=$(dir $@) + --annotate=html --output-dir=$(dir $@) %.ckpt: %.trace $(XCOV) coverage $(XCOVFILTER) --level=$(XCOVLEVEL) \ @@ -149,7 +149,7 @@ consolidate-traces: out-all-traces/index.html out-all-traces/index.html: out-all-traces $(ALL_TRACES) $(XCOV) coverage $(XCOVFILTER) --level=$(XCOVLEVEL) \ - --annotate=dhtml $(ALL_TRACES) \ + --annotate=html $(ALL_TRACES) \ --output-dir $(dir $@) # ----------------------------------------------------------------------- @@ -168,7 +168,7 @@ out-%: force out-%/index.html: out-% %.trace $(XCOV) coverage $(XCOVFILTER) \ - --level=$(XCOVLEVEL) --annotate=dhtml $*.trace --output-dir $(dir $@) + --level=$(XCOVLEVEL) --annotate=html $*.trace --output-dir $(dir $@) out-%/index.xml: out-% %.trace $(XCOV) coverage $(XCOVFILTER) \ From 28da32368ec0c202720f237bfe6a5c34b568dea1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 25 Apr 2023 15:25:13 +0200 Subject: [PATCH 0281/1483] gnatcov.gpr: add libsframe dependency in the linker options The bump to binutils 2.40 introduces a new sframe format support, and we thus need to link against this library in order for the gnatcov build to properly link. --- tools/gnatcov/gnatcov.gpr | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index b58c3bbf7..3a79dda86 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -243,6 +243,7 @@ project Gnatcov is (Binutils_Build_Dir & "/opcodes/libopcodes.a", Binutils_Build_Dir & "/bfd/libbfd.a", Binutils_Build_Dir & "/libiberty/libiberty.a", + Binutils_Build_Dir & "/libsframe/.libs/libsframe.a", "-lz", "-static-libstdc++", "-static-libgcc"); From f36e7805f336610acde789e374010f987baeae62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 2 May 2023 15:31:32 +0200 Subject: [PATCH 0282/1483] Fix report example in exemptions documentation Ref #59 --- doc/gnatcov/exemptions.rst | 41 +++++++++++--------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/doc/gnatcov/exemptions.rst b/doc/gnatcov/exemptions.rst index 317bc2e3e..ea8753a64 100644 --- a/doc/gnatcov/exemptions.rst +++ b/doc/gnatcov/exemptions.rst @@ -110,11 +110,13 @@ control. In synthetic text reports, a single indication is emitted for each exempted region as a whole, and the indications for all the regions are grouped in a -separate *Exempted Regions* report section, only present if there are -exemption regions in the analysis scope. This section lists the exempted -regions, displaying for each the source location span, the number of actually -exempted violations in the region and the exemption justification text. It -also includes a total count of the number of exempted regions at the end. +separate *Exempted Regions* report section, only present if there are exemption +regions in the analysis scope. This section lists the exempted regions, +displaying for each the source location span, the number of actually exempted +violations in the region, the exemption justification text and the observed +exempted violations per regions. It also includes a total count of the number +of exempted regions and another for exempted violations accross all sections at +the end. The corresponding :cmd-option:`=report` excerpt below illustrates this for the ``Eassert`` example:: @@ -127,7 +129,11 @@ The corresponding :cmd-option:`=report` excerpt below illustrates this for the eassert.adb:8:4-12:4: 2 exempted violations, justification: "assert condition never to be False" - 1 exempted region. + Exempted violations: + eassert.adb:8:4: decision outcome TRUE never exercised + eassert.adb:9:8: statement not executed + + 1 exempted region, 2 exempted violations. ========================= == 4. ANALYSIS SUMMARY == @@ -135,30 +141,7 @@ The corresponding :cmd-option:`=report` excerpt below illustrates this for the No non-exempted STMT violation. No non-exempted DECISION violation. - 1 exempted region. - -The exempted violations are also displayed to let the user check that they -match the expected ones. The report shows the previously mentioned information -along with the observed violations under their corresponding exempted block, -and the total number of exempted violations found across all exempted regions. - -The :cmd-option:`=report` excerpt below illustrates this for the ``Eassert`` -example:: - - ... - ========================= - == 3. EXEMPTED REGIONS == - ========================= - - eassert.adb:8:4-12:4: 2 exempted violations, justification: - "assert condition never to be False" - - Exempted violations: - eassert.adb:8:4: decision outcome TRUE never exercised - eassert.adb:9:8: statement not executed - 1 exempted region, 2 exempted violations. - ... The *Coverage Violations* section is renamed to convey that it contains "NON-EXEMPTED" violations only, and the *Analysis Summary* counters are From 053de2fa2b0d3a911dff84449e68ded481c8095f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Mon, 17 Apr 2023 17:29:42 +0200 Subject: [PATCH 0283/1483] Reject files passed as SID that do not have a .sid extension Previously all files given to --sid or listed in a file given to --sid were accepted an treated as such. This meant that any error occuring during the treatment of the file as a SID file was the only way to be aware of a file being invalid. Now only files whose name ends with ".sid" are accepted as SID files and the error message is adaped to make it explicit. TN: U429-016 --- tools/gnatcov/checkpoints.adb | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index a126c85f0..6a1803a78 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -515,8 +515,18 @@ package body Checkpoints is procedure SID_Load (Filename : String; - Ignored_Source_Files : access GNAT.Regexp.Regexp) is - begin + Ignored_Source_Files : access GNAT.Regexp.Regexp) + is + SID_Re : constant GNAT.Regexp.Regexp := GNAT.Regexp.Compile (".*\.sid"); + begin + if not GNAT.Regexp.Match (Filename, SID_Re) then + Fatal_Error ("invalid " + & Purpose_Name (Instrumentation) + & " file " + & Filename + & ", name of file should have .sid extension"); + end if; + Checkpoint_Load (Filename, Instrumentation, Ignored_Source_Files); end SID_Load; From 98ac91cba2f4fe43eac553d00dded41164fcbee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 18 Apr 2023 10:58:54 +0200 Subject: [PATCH 0284/1483] Improve messages upon misuse of --units The check for the use of --units without -P could never be satified so the appropriate error message was never printed, this is now fixed. A mention of the -P options to use along with --units has been added to the error message when there are no user provided SCOs. TN: U429-016 --- tools/gnatcov/gnatcov_bits_specific.adb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 41c3e0d7d..36475d42b 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -221,7 +221,8 @@ procedure GNATcov_Bits_Specific is then Report_Missing_Argument ("SCOs", - ", specifying Units in project or using --units/--scos/--sid"); + ", specifying Units in project or using " + & "[--units and -P]|--scos|--sid"); end if; end Check_User_Provided_SCOs; @@ -1040,7 +1041,7 @@ procedure GNATcov_Bits_Specific is Project.Compute_Units_Of_Interest (Units_Inputs); else - if Inputs.Length (Units_Inputs) /= 0 then + if not Args.String_List_Args (Opt_Units).Is_Empty then Fatal_Error ("--units requires -P"); end if; if not Args.String_List_Args (Opt_Projects).Is_Empty then From 7901ccdefe6a5c40824291f8f42d00f454072b07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 18 Apr 2023 18:05:10 +0200 Subject: [PATCH 0285/1483] Emit warning when --units is used along with -C Warn the user that the units of interest specified through --units will have no effect on the treatment of the checkpoints given through -C. TN: U429-016 --- tools/gnatcov/gnatcov_bits_specific.adb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 36475d42b..2d85786dc 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -470,7 +470,16 @@ procedure GNATcov_Bits_Specific is Copy_Arg_List (Opt_Routines, Routines_Inputs); Copy_Arg_List (Opt_Exec, Exe_Inputs); + + if not Args.String_List_Args (Opt_Checkpoint).Is_Empty + and then not Args.String_List_Args (Opt_Units).Is_Empty + then + Warn ("Specifying units of interest through --units has no effect on " + & "checkpoints"); + end if; + Copy_Arg_List (Opt_Checkpoint, Checkpoints_Inputs); + Copy_Arg_List (Opt_Ignore_Source_Files, Ignored_Source_Files); -- Compute the languages for which we want coverage analysis, or enable From 8e117944083bdb05d51570daf8033932936e2d03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Mon, 24 Apr 2023 17:47:32 +0200 Subject: [PATCH 0286/1483] Add test to check error messages when incorrectly providing SCOs Also make fail_if_no_match canonicalize line endings for the text to match againt the expected content TN: U429-016 --- testsuite/SUITE/context.py | 2 + .../tests/U429-016-gnatcov-misuse/main.adb | 4 ++ .../tests/U429-016-gnatcov-misuse/test.py | 65 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 testsuite/tests/U429-016-gnatcov-misuse/main.adb create mode 100644 testsuite/tests/U429-016-gnatcov-misuse/test.py diff --git a/testsuite/SUITE/context.py b/testsuite/SUITE/context.py index b663e3a70..2a169511a 100644 --- a/testsuite/SUITE/context.py +++ b/testsuite/SUITE/context.py @@ -253,6 +253,8 @@ def fail_if_no_match(self, what, regexp, actual): """Register a check failure when ACTUAL does not match regexp.""" if isinstance(regexp, str): regexp = re.compile(regexp) + # Canonicalize to Unix-style line endings to have cross-platform checks + actual = actual.replace('\r\n', '\n') self.fail_if( not regexp.match(actual), 'Unexpected {}. Expected:' diff --git a/testsuite/tests/U429-016-gnatcov-misuse/main.adb b/testsuite/tests/U429-016-gnatcov-misuse/main.adb new file mode 100644 index 000000000..4fe1236da --- /dev/null +++ b/testsuite/tests/U429-016-gnatcov-misuse/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end; diff --git a/testsuite/tests/U429-016-gnatcov-misuse/test.py b/testsuite/tests/U429-016-gnatcov-misuse/test.py new file mode 100644 index 000000000..97af9932c --- /dev/null +++ b/testsuite/tests/U429-016-gnatcov-misuse/test.py @@ -0,0 +1,65 @@ +""" +Check error messages upon incorrectly providing SCOs to gnatcov. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +# Generate a project, instrument it and run it +p = gprfor(mains=['main.adb'], srcdirs=['..']) + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p), + covlevel='stmt', + mains=['main'], + extra_coverage_args=[]) + +trace_file = xcov_args[-1] + + +def check_output(output_file, expected_content): + """ + Check that the content of the "output_file" text file matches + "expected_content". + """ + thistest.fail_if_no_match( + '"gnatcov coverage" output ({})'.format(output_file), + expected_content, + contents_of(output_file)) + + +def run_and_check(args, output_file, expected_content): + """ + Run gnatcov with the given command line arguments "args", latch the output + in "output_file" and check that this output matches the provided + "expected_content". + """ + p = xcov(args, out=output_file, register_failure=False) + thistest.fail_if( + p.status == 0, + 'the call to "gnatcov coverage" was expected to fail, yet it' + ' succeeded (see {})'.format(output_file) + ) + check_output(output_file, expected_content) + + +# Check that an error is emitted when using --units without -P +run_and_check( + ['coverage', "--level=stmt", "--units=main", trace_file], + 'missing_project.txt', + '.*gnatcov.*: --units requires -P') + +# Check the error message when not attempting to provide any SCOs +run_and_check( + ['coverage', "--level=stmt", trace_file], + 'missing_scos.txt', + '.*gnatcov.*: Please specify SCOs on the command line, specifying Units ' + 'in project or using \\[--units and -P\\]\\|--scos\\|--sid\\..*') + +thistest.result() From 1ffddab683be87517945a9f4296797624399f06a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 4 May 2023 12:24:28 +0000 Subject: [PATCH 0287/1483] instrument-input_traces.adb: fix handling of long lines in Base64 traces Do not use the `Ada.Text_IO.Get_Line` function, as it returns a `String` on the stack, so it may trigger stack overflows with too long lines. Use instead the `Get_Line` procedure that uses a fixed-size buffer, and just skip too long lines, which are never supposed to be part of source traces anyway. --- .../W502-023-base64-long-lines/main.adb | 8 ++ .../W502-023-base64-long-lines/test.py | 26 +++++++ tools/gnatcov/instrument-input_traces.adb | 78 ++++++++++++++----- 3 files changed, 94 insertions(+), 18 deletions(-) create mode 100644 testsuite/tests/instr-cov/W502-023-base64-long-lines/main.adb create mode 100644 testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py diff --git a/testsuite/tests/instr-cov/W502-023-base64-long-lines/main.adb b/testsuite/tests/instr-cov/W502-023-base64-long-lines/main.adb new file mode 100644 index 000000000..f5f08b178 --- /dev/null +++ b/testsuite/tests/instr-cov/W502-023-base64-long-lines/main.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + for I in 1 .. 10_000 loop + Put ((1 .. 1000 => 'A')); + end loop; +end Main; diff --git a/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py b/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py new file mode 100644 index 000000000..d09e7ad30 --- /dev/null +++ b/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py @@ -0,0 +1,26 @@ +""" +Check that "gnatcov extract-base64-trace" handles correctly input files with +very long lines (it used to crash with a stack overflow). +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], + trace_mode="src", + dump_trigger="main-end", + dump_channel="base64-stdout", +) + +check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {5, 6}}}, "obj") + +thistest.result() diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index a95b11453..bbecc8fd3 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -938,9 +938,10 @@ package body Instrument.Input_Traces is subtype Whitespace is Character with Static_Predicate => Whitespace in ' ' | ASCII.HT | ASCII.CR | ASCII.LF; - function Trim (S : String) return String; - -- Return S without its leading/trailing whitespaces, tabs, carriage - -- returns and newline characters (if any). + procedure Trim + (S : String; First : in out Positive; Last : in out Natural); + -- Adjust First/Last so that S (First .. Last) has no leading/trailing + -- whitespaces, tabs, carriage returns and newline characters. function Base64_Digit (C : Character) return Unsigned_8; -- Return the 6-bit number that the C Base64 digit means @@ -955,9 +956,8 @@ package body Instrument.Input_Traces is -- Trim -- ---------- - function Trim (S : String) return String is - First : Positive := S'First; - Last : Natural := S'Last; + procedure Trim + (S : String; First : in out Positive; Last : in out Natural) is begin while First in S'Range and then S (First) in Whitespace loop First := First + 1; @@ -965,7 +965,6 @@ package body Instrument.Input_Traces is while Last in S'Range and then S (Last) in Whitespace loop Last := Last - 1; end loop; - return S (First .. Last); end Trim; ------------------ @@ -1027,17 +1026,60 @@ package body Instrument.Input_Traces is <> while not TIO.End_Of_File (Input) loop declare - Line : constant String := Trim (TIO.Get_Line (Input)); + use type TIO.Count; + + Reading_Trace : constant Boolean := BIO.Is_Open (Output); + Buffer : String (1 .. 100); + First : Positive := 1; + Last : Natural; begin - if BIO.Is_Open (Output) then - if Line = End_Marker then + -- Try to read a line, abort if we reached the end of line + + begin + TIO.Get_Line (Input, Buffer, Last); + exception + when TIO.End_Error => + exit; + end; + + -- If the line is too long for our buffer: + -- + -- * If we are in the middle of reading a source trace, stop with + -- an error: this is not supposed to happen as we dump source + -- traces with at most 80-columns wide lines. + -- + -- * Otherwise, just skip that line. + -- + -- Note that, for some reason, End_Of_Line may return False even + -- if we managed to read the full line. To consider that we did + -- manage to read the full line in such cases, also check the + -- column (1 = we reached the next line, so we managed to read the + -- previous line in one go). + + if not TIO.End_Of_Line (Input) and then TIO.Col (Input) > 1 then + if Reading_Trace then + Outputs.Fatal_Error + ("Unexpected long line in Base64 trace"); + else + TIO.Skip_Line (Input); + goto Read_Next_Line; + end if; + end if; + + -- Remove leading/trailing whitespaces, which copy/pasting may + -- insert. + + Trim (Buffer, First, Last); + + if Reading_Trace then + if Buffer (First .. Last) = End_Marker then BIO.Close (Output); goto Read_Next_Line; end if; -- Expect groups of 4 characters - if Line'Length mod 4 /= 0 then + if Buffer (First .. Last)'Length mod 4 /= 0 then Outputs.Fatal_Error ("Invalid Base64 trace: incomplete group of 4 characters"); end if; @@ -1045,16 +1087,16 @@ package body Instrument.Input_Traces is -- Now process each group declare - Next : Positive := Line'First; + Next : Positive := First; function D (Index : Natural) return Unsigned_8 - is (Base64_Digit (Line (Next + Index))); + is (Base64_Digit (Buffer (Next + Index))); begin - while Next <= Line'Last loop + while Next <= Last loop -- Here, process the Base64 digits in the slice: -- - -- Line (Next .. Next + 3) + -- Buffer (Next .. Next + 3) -- -- This slice contains 4 Base64 digits, and each digit -- encodes 6 bits (total: 24 bits), so we can decode 3 @@ -1065,11 +1107,11 @@ package body Instrument.Input_Traces is BIO.Write (Output, Shift_Left (D (0), 2) or Shift_Right (D (1), 4)); - if Line (Next + 2) /= '=' then + if Buffer (Next + 2) /= '=' then BIO.Write (Output, Shift_Left (D (1), 4) or Shift_Right (D (2), 2)); - if Line (Next + 3) /= '=' then + if Buffer (Next + 3) /= '=' then BIO.Write (Output, Shift_Left (D (2), 6) or D (3)); end if; end if; @@ -1078,7 +1120,7 @@ package body Instrument.Input_Traces is end loop; end; - elsif Line = Start_Marker then + elsif Buffer (First .. Last) = Start_Marker then Had_One_Trace := True; BIO.Create (Output, BIO.Out_File, Output_File); end if; From e7fa47ed0141abf95685cfa1b1ce181f8237abfc Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 16 May 2023 08:07:10 +0000 Subject: [PATCH 0288/1483] instrument-input_traces.adb: fix typo in comment --- tools/gnatcov/instrument-input_traces.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index bbecc8fd3..397c4fa76 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -1033,7 +1033,7 @@ package body Instrument.Input_Traces is First : Positive := 1; Last : Natural; begin - -- Try to read a line, abort if we reached the end of line + -- Try to read a line, abort if we reached the end of file begin TIO.Get_Line (Input, Buffer, Last); From 044fb4050576237a9d0da8931ce115711e781f12 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 25 Apr 2023 14:31:23 +0200 Subject: [PATCH 0289/1483] Support the -o option with the cobertura report --- testsuite/tests/cobertura_validation/test.py | 14 +++++++----- tools/gnatcov/annotations-cobertura.adb | 23 ++++++++++++++------ 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/testsuite/tests/cobertura_validation/test.py b/testsuite/tests/cobertura_validation/test.py index 6decfa2ec..cc0b15d76 100644 --- a/testsuite/tests/cobertura_validation/test.py +++ b/testsuite/tests/cobertura_validation/test.py @@ -19,11 +19,15 @@ ) -def build_run_coverage_and_check(covlevel, source_root=None): +def build_run_coverage_and_check(covlevel, output_opt=None, source_root=None): extra_args = ["--annotate=cobertura"] - if source_root is not None: + if source_root: extra_args += ["--source-root", source_root] + filename = output_opt if output_opt else "cobertura.xml" + if output_opt: + extra_args += ["-o", output_opt] + build_run_and_coverage( gprsw=gprsw, covlevel=covlevel, @@ -31,15 +35,15 @@ def build_run_coverage_and_check(covlevel, source_root=None): extra_coverage_args=extra_args, ) parser = etree.XMLParser(dtd_validation=True) - return etree.parse(os.path.join("obj", "cobertura.xml"), parser) + return etree.parse(os.path.join("obj", filename), parser) # For both source and object coverage, check that the output "cobertura.xml" # file is valid according to the cobertura.dtd standard. build_run_coverage_and_check("stmt+mcdc") if thistest.options.trace_mode == "bin": - build_run_coverage_and_check("insn") - build_run_coverage_and_check("branch") + build_run_coverage_and_check("insn", "cobertura-insn.xml") + build_run_coverage_and_check("branch", "cobertura-branch.xml") # Check that the --source-root option works as expected diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb index a5a850084..0de7213cc 100644 --- a/tools/gnatcov/annotations-cobertura.adb +++ b/tools/gnatcov/annotations-cobertura.adb @@ -51,7 +51,8 @@ package body Annotations.Cobertura is (Pattern_Matcher, Pattern_Matcher_Acc); type Cobertura_Pretty_Printer is new Pretty_Printer with record - Report_File : File_Type; + Report_Filename : Unbounded_String; + Report_File : File_Type; -- "cobertura.xml" file Indentation : Natural := 0; @@ -77,8 +78,7 @@ package body Annotations.Cobertura is -- XML generation -- -------------------- - Xml_Header : constant String := ""; - Report_File_Name : constant String := "cobertura.xml"; + Xml_Header : constant String := ""; function A (Name : String; Value : String) return String; -- Return a string representing an xml attribute whose name and value are @@ -231,17 +231,26 @@ package body Annotations.Cobertura is -- always becomes "basename" instead of "/basename" regardless of -- whether the prefix is "/prefix" or "/prefix/". - Opt : Parser.String_Option renames Args.String_Args (Opt_Source_Root); + Source_Root_Opt : Parser.String_Option renames + Args.String_Args (Opt_Source_Root); + Output_Opt : Parser.String_Option renames + Args.String_Args (Opt_Output); begin - if Opt.Present then + if Source_Root_Opt.Present then declare - Prefix : constant String := +Opt.Value & "/"; + Prefix : constant String := +Source_Root_Opt.Value & "/"; begin Pp.Source_Prefix_Pattern := new Pattern_Matcher'(Compile (Paths.Glob_To_Regexp (Prefix))); end; end if; + if Output_Opt.Present then + Pp.Report_Filename := Output_Opt.Value; + else + Pp.Report_Filename := +"cobertura.xml"; + end if; + Annotations.Generate_Report (Pp, True, Subdir => "cobertura"); Free (Pp.Source_Prefix_Pattern); end Generate_Report; @@ -353,7 +362,7 @@ package body Annotations.Cobertura is & " to the output directory"); end if; - Create_Output_File (Pp.Report_File, Report_File_Name); + Create_Output_File (Pp.Report_File, +Pp.Report_Filename); Pp.P (Xml_Header); Pp.P (""); From 1beacfa9229fb9067045a83456c0e086ff81b756 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 25 Apr 2023 14:31:54 +0200 Subject: [PATCH 0290/1483] Document the cobertura coverage report --- doc/gnatcov/cov_source.rst | 40 +++++++++++++++++++++++++++++----- tools/gnatcov/command_line.ads | 4 ++-- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index 62972c5f9..97dd8166a 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -52,11 +52,12 @@ The available options are as follows: :cmd-option:`-a`, :cmd-option:`--annotate` |marg|: Request one or more output report formats. All the criteria support - ``xcov[+]``, ``html`` and ``report`` formats, with interpretations that vary - depending on the assessed criteria. See the corresponding documentation later - in this chapter for more details. This option accepts comma separated values - and/or can be specified mulitple times on the command line, in which case - there will be one report produced for each of the requested formats. + ``xcov[+]``, ``html``, ``cobertura`` and ``report`` formats, with + interpretations that vary depending on the assessed criteria. See the + corresponding documentation later in this chapter for more details. This + option accepts comma separated values and/or can be specified multiple times + on the command line, in which case there will be one report produced for each + of the requested formats. :cmd-option:`-o` : Request that the synthetic report produced by ``--annotate=report`` be @@ -209,7 +210,10 @@ source files, in the directory where |gcv| is launched unless overriden with a :cmd-option:`--output-dir` option. The :cmd-option:`report` output consists in a synthetic text report of :term:`coverage violations ` with respect to the requested criteria, produced on standard output by default or in -the file specified by the :cmd-option:`-o` command line option. +the file specified by the :cmd-option:`-o` command line option. The +:cmd-option:`cobertura` produce a single xml file containing a coverage report +in the Cobertura format. Its name is by default `cobertura.xml` and can be +altered using the :cmd-option:`-o` command line option. Later in this chapter we name output formats by the text to add to :cmd-option:`--annotate` on the command line. For example, we use "the @@ -334,6 +338,30 @@ See the :ref:`sample annotated source ` appendix for a sample of html annotated source. +Cobertura report (:cmd-option:`=cobertura`) +------------------------------------------- + +:cmd-option:`--annotate=cobertura` produces a coverage report in the Cobertura +format, as specified per the cobertura.dtd (document type description) that is +generated alongside. + +This format specification is not maintained by gnatcov, and it does not thus +provide all of the information that other report formats do, notably MC/DC +coverage information, violation messages. Decision violations are output using +the "branch" terminology of Cobertura (one decision being two branches, and +either 0, 1 or 2 of those branches are covered). + +It is mainly provided for integration with external tools, such as continuous +integration systems, e.g. gitlab, which supports integration of coverage reports +into merge requests using this format. + +File names in this coverage report are absolute. Depending on the use context of +this coverage report, it can also make sense to strip a given prefix from the +absolute paths to make them relative to, e.g. a project root. The +:cmd-option:`--source-root` command line option accepts a string prefix that +will be removed from absolute path references in the report. + + Violations summary, text (:cmd-option:`=report`) ------------------------------------------------ diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index abe6c2b91..1a355b49e 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -886,7 +886,7 @@ package Command_Line is & " specified prefix from the filenames in the report.", Commands => (Cmd_Coverage => True, others => False), At_Most_Once => True, - Internal => True) + Internal => False) ); String_List_Infos : constant String_List_Option_Info_Array := @@ -1084,7 +1084,7 @@ package Command_Line is Pattern => "[FORM|LIST]", Help => "Generate a FORM report. FORM is one of:" - & ASCII.LF & " asm, xcov, html, xcov+, report." + & ASCII.LF & " asm, xcov, html, xcov+, cobertura, report." & ASCII.LF & "Multiple reports can be produced in a single" & " execution by passing a comma separated list of FORMs to this" & " option, or by specifying this option multiple times on the" From e7e140116cb33069efd60c881510e3f0e3a5e9f4 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 12 May 2023 15:53:30 +0200 Subject: [PATCH 0291/1483] Document gnattest automatic generation capabilities --- doc/gnattest/gnattest_part.rst | 41 ++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/doc/gnattest/gnattest_part.rst b/doc/gnattest/gnattest_part.rst index 0e96b8992..734b58d5d 100644 --- a/doc/gnattest/gnattest_part.rst +++ b/doc/gnattest/gnattest_part.rst @@ -923,3 +923,44 @@ The tool currently has the following limitations: may result in elaboration circularities in the generated harness; * heavy usage of preprocessor that affects constructs like subprogram profiles or tagged type hierarchies may result in improper test driver generation. + +.. _Automatic_testcase_generation: + +Automatically generating test cases (alpha) +------------------------------------------- + +``gnattest`` provides a switch ``--gen-test-vectors`` that can be used to +automatically generate test cases for all of the supported subprogram profiles. +The number of generated test cases can be configured through the +``--gen-test-num`` switch. + +``gnattest`` can automatically generate test cases unless any of the following +are true: + +1. Any of the subprogram's "in" or "in out" mode parameters are of an + Access type or contain a sub-component of an Access type. +2. Any of the subprogram's "in" or "in out" mode parameters are Subprogram + Access Types. +3. Any of the subprogram's "in" or "in out" mode parameters are Limited types. +4. Any of the subprogram's "in" or "out" mode parameters are tagged types. +5. Any of the subprogram's "in" or "out" mode parameters is a private type of + a nested package. + +.. + TODO: document a bit the value generation (mostly random, except for + unconstrained arrays and discriminated record). + +The generated test cases are then stored in a ad-hoc (and yet to be specified) +JSON format, in files under the /gnattest/tests/JSON_Tests directory. +The generated JSON files are preserved through a ``gnattest`` rerun. The user is +thus free to modify them, to e.g. fill in expected return values, though +backward compatibility of the format is not guaranteed at this stage. + +``gnattest`` also generates Ada files to actually execute the test cases. Each test vector +has its own AUnit test case, and all test cases for a specific subprogram are all +stored in a dedicated file, namely +-test_data-test__.ad[bs]. The content of these +files is not preserved through a ``gnattest`` rerun. + +.. + TODO: document the --unparse switch From 6ad4a046f0cea3640744ee5442f7f361e86d85e0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 22 May 2023 09:53:56 +0000 Subject: [PATCH 0292/1483] SCOV.instr.xcov_instrument: fix access to the project file This function needs to read the content of the project file passed to `gnatcov instrument`. Since resolving a project file argument (`-P`) to an actual location in the filesystem is a non-trivial task (for instance, it may involve the `GPR_PROJECT_PATH` environment variable), delegate it to gprls. --- .../GPR/GprsOfInterest/test.py | 5 +++- testsuite/SCOV/instr.py | 5 ++-- testsuite/SUITE/tutils.py | 30 +++++++++++++++++++ 3 files changed, 37 insertions(+), 3 deletions(-) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py index 6cabb480b..252602aab 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py @@ -27,7 +27,10 @@ # --dump-units-to tests we need. cov_cmdline = build_and_run( - gprsw=GPRswitches(root_project=root_project), + gprsw=GPRswitches( + root_project=root_project, + xvars=[("BOARD", env.target.machine)], + ), mains=['root'], covlevel='stmt', gpr_obj_dir='../obj', diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 02626ce31..63c2269a8 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -7,7 +7,7 @@ from SUITE.context import thistest from SUITE.cutils import contents_of, ext, indent -from SUITE.tutils import RUNTIME_INFO, GNATCOV_INFO, xcov +from SUITE.tutils import RUNTIME_INFO, GNATCOV_INFO, locate_gpr_file, xcov def default_dump_trigger(mains): @@ -85,7 +85,8 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", # Capture the list of main file names, double quoted and comma separated. m = re.search( pattern=r"for Main use \((?P.*)\)", - string=contents_of(gprsw.root_project)) + string=contents_of(locate_gpr_file(gprsw)), + ) # If found, split then remove whitespaces and double quotes mains = [] diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 01d949e83..0e37468d1 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -10,6 +10,7 @@ import glob import os +import re import time @@ -43,6 +44,10 @@ MEMCHECK_LOG = 'memcheck.log' CALLGRIND_LOG = 'callgrind-{}.log' +# Pattern to match the line in gprls' verbose output that specifies the full +# path to the project file to analyze. +GPRLS_PARSING_RE = re.compile(r'^.*\.gpr: info: Parsing "(.*)"$') + # ---------------------------------------------------------------------------- # Notes on program and command execution paths # @@ -540,6 +545,31 @@ def platform_specific_symbols(symbols): return [TARGET_INFO.to_platform_specific_symbol(sym) for sym in symbols] +def locate_gpr_file(gprswitches): + """ + Use gprls to locate the GPR file for ``gprswitches``'s root project. + """ + # Run gprls to let GPR code do the complex project file resolution, enable + # verbose mode so that it prints the full path to the resolved file. + filename = gprswitches.root_project + args = ["gprls", "-P", filename, "-v"] + gprswitches.build_switches + if thistest.options.target: + args.append(f"--target={thistest.options.target}") + if thistest.options.RTS: + args.append(f"--RTS={thistest.options.RTS}") + gprls_output = Run(args).out + + # Look for the resolved project filename in the output, complain if we + # could not find one. + for line in gprls_output.splitlines(): + m = GPRLS_PARSING_RE.match(line) + if m is not None: + return m.group(1) + raise ValueError( + f"could not locate {filename} with gprls:\n{gprls_output}" + ) + + def xcov_suite_args(covcmd, covargs, auto_config_args=True, auto_target_args=True, From b2e9efb64a05e1a008239d0be2d79f0aa1408c25 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 22 May 2023 22:23:58 +0200 Subject: [PATCH 0293/1483] Take gnatcov doc appendix chapter out of numbered toc Appendix chapters are typically numbered on their own (like A. B. etc after numbers like 1. etc for regular doc chapters). There is no practical way to request this with sphinx so this change simply arranges not to assign an automatic number to appendix chapters and provide one manually instead. Part of V805-004 (put instrumentation forward in gnatcov doc) --- doc/gnatcov/gnatcov_bin_part.rst | 6 +++--- doc/index.rst | 4 ++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/gnatcov/gnatcov_bin_part.rst b/doc/gnatcov/gnatcov_bin_part.rst index b3e27ecce..34dfeb1b8 100644 --- a/doc/gnatcov/gnatcov_bin_part.rst +++ b/doc/gnatcov/gnatcov_bin_part.rst @@ -1,6 +1,6 @@ -########################################### -GNATcoverage Appendix - Using Binary Traces -########################################### +############################################# +Appendix A. Using GNATcoverage Binary Traces +############################################# .. toctree:: :maxdepth: 3 diff --git a/doc/index.rst b/doc/index.rst index 30fdea3bf..91d33436c 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -9,4 +9,8 @@ gnatcov/gnatcov_part gnattest/gnattest_part integration/integration_part + +.. Appendix part - manual numbering + +.. toctree:: gnatcov/gnatcov_bin_part From 83f487ff9aada63bf7868f09551448361bb52b40 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 25 May 2023 11:57:32 +0200 Subject: [PATCH 0294/1483] Build gnatcov before bootstrapping it (instrumenting it with itself) --- .gitlab-ci.yml | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9ec60cfbb..909fdb1f9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -50,6 +50,7 @@ build: - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR # Build using anod + - anod build --minimal gnatcov $EDGE_QUALIFIER - anod build --minimal gnatcov -Qinstr $EDGE_QUALIFIER # Create the package @@ -63,23 +64,6 @@ build: paths: - $PACKAGE_BASE_NAME -build_standard: - services: - - image:gnatcov - - cpu:8 - - mem:16 - stage: test - script: - - export PATH=/it/e3/bin:$PATH - - *edge_vars - - # Setup the repository - - cd /it/wave - - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR - - # Build using anod - - anod build --minimal gnatcov $EDGE_QUALIFIER - build_community: services: - image:gnatcov From 296121b839d3b2afaf7ee6c89b95458709afb657 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 25 May 2023 17:28:56 +0200 Subject: [PATCH 0295/1483] Change clang-format specification to allow line comments with no spaces Otherwise, this reflows the line comments stating expectations in test drivers, which thus breaks the test. --- .pre-commit-config.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index af4cb852d..aa805a5f1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,5 +13,9 @@ repos: IndentExternBlock: NoIndent, SpaceAfterCStyleCast: true, - UseTab: ForContinuationAndIndentation + UseTab: ForContinuationAndIndentation, + SpacesInLineCommentPrefix: { + Minimum: 0, + Maximum: -1 + } }"] From c22dba34d7c1d01722b53317f995712ad241d5c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 25 May 2023 17:05:14 +0200 Subject: [PATCH 0296/1483] instrument-c.adb: Do not process decisions in lambdas more than once Decisions nested inside a lambda expressions could be instrumented more than once if the construct in which the lambda is declared also contains a decision. This resulted in duplicate SCOs being emitted, causing gnatcov to crash. --- .../instr-cov/C++/68-lambda-decisions/src/pkg.cpp | 11 +++++++++++ .../instr-cov/C++/68-lambda-decisions/src/pkg.hh | 1 + .../C++/68-lambda-decisions/src/test_pkg.cpp | 14 ++++++++++++++ .../instr-cov/C++/68-lambda-decisions/test.py | 13 +++++++++++++ testsuite/tests/instr-cov/C++/extra.opt | 2 ++ tools/gnatcov/instrument-c.adb | 7 +++++++ 6 files changed, 48 insertions(+) create mode 100644 testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.cpp create mode 100644 testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.hh create mode 100644 testsuite/tests/instr-cov/C++/68-lambda-decisions/src/test_pkg.cpp create mode 100644 testsuite/tests/instr-cov/C++/68-lambda-decisions/test.py create mode 100644 testsuite/tests/instr-cov/C++/extra.opt diff --git a/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.cpp b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.cpp new file mode 100644 index 000000000..f5cf1b26d --- /dev/null +++ b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.cpp @@ -0,0 +1,11 @@ +#include "pkg.hh" + +int +overly_complex_fact (int n) +{ + return n ? n * // # top_level + [] (int m) { + return m > 1 ? overly_complex_fact (m) : 1; // # lambda + }(n - 1) + : 1; +} diff --git a/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.hh b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.hh new file mode 100644 index 000000000..8b9daab16 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.hh @@ -0,0 +1 @@ +extern int overly_complex_fact (int n); diff --git a/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/test_pkg.cpp b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/test_pkg.cpp new file mode 100644 index 000000000..107377e28 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/test_pkg.cpp @@ -0,0 +1,14 @@ +#include "pkg.hh" +#include + +int +main () +{ + assert (overly_complex_fact (2) == 2); + assert (overly_complex_fact (0) == 1); +} + +//# pkg.cpp +// +// /top_level/ l+ ## 0 +// /lambda/ l! ## dT- diff --git a/testsuite/tests/instr-cov/C++/68-lambda-decisions/test.py b/testsuite/tests/instr-cov/C++/68-lambda-decisions/test.py new file mode 100644 index 000000000..d7f890c99 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/68-lambda-decisions/test.py @@ -0,0 +1,13 @@ +""" +Check that instrumenting a lambda containing a decision +and that is declared in a statement containing a decision (other than nested in +the lambda) works as intended. gnatcov used to emit duplicate decision SCOs and +thus crash. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/extra.opt b/testsuite/tests/instr-cov/C++/extra.opt new file mode 100644 index 000000000..057749df0 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/extra.opt @@ -0,0 +1,2 @@ +!C++ DEAD Only run C++ tests if we have a supported C++ compiler +bin-traces DEAD C++ not supported with binary traces diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index be825090b..410348c38 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -1822,6 +1822,13 @@ package body Instrument.C is Process_Decisions (UIC, False_Expr, 'X'); return Child_Visit_Continue; end; + when Cursor_Lambda_Expr => + + -- Do not descend into lambdas, the decisions inside the lambda + -- will be taken care of while processing the statements in the + -- lambda. + + return Child_Visit_Continue; when others => null; end case; From 5709701b4b92d57411588a33ed4afab79661207a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 26 May 2023 10:59:02 +0200 Subject: [PATCH 0297/1483] Avoid triggering a gnatcov -Q instr build When testing with the instrumented gnatcov, we have a dependency to the instrumented gnatcov build tree, meaning that the anod spec will always try to build it. Fix the assume-unchanged to work in that case. Also package the build space, required as this is a build dependency. --- .gitlab-ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 909fdb1f9..9140d7c73 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -55,7 +55,7 @@ build: # Create the package - tar czf $PACKAGE_ABSOLUTE_NAME -C / - it/wave/x86_64-linux/gnatcov-instr$EDGE_BUILD_SPACE_SUFFIX/install/ + it/wave/x86_64-linux/gnatcov-instr$EDGE_BUILD_SPACE_SUFFIX/ - cd $CI_PROJECT_DIR - ls -l $PACKAGE_BASE_NAME @@ -113,8 +113,7 @@ build_community: # download the nightly one, which may not even exist (case of an edge build # failure that was fixed on that day). - mkdir -p fingerprints - - touch fingerprints/x86_64-linux.gnatcov-instr$EDGE_BUILD_SPACE_SUFFIX.install.json.assume-unchanged - - touch fingerprints/x86_64-linux.gnatcov-instr$EDGE_BUILD_SPACE_SUFFIX.download_bin.json.assume-unchanged + - touch fingerprints/x86_64-linux.gnatcov-instr$EDGE_BUILD_SPACE_SUFFIX.build.json.assume-unchanged # Setup the CI directory to host coverage results - mkdir $CI_PROJECT_DIR/coverage From 7428c8f2569b077819ad019d594ac917dc9e064b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 31 May 2023 12:49:29 +0200 Subject: [PATCH 0298/1483] xnexpanders.py: Restrict the accepted delimiters for fuzzy blocks Prior to this change, any tag on a line containing a lone "begin" or "end" in a source of interest would be considered as a start or end of a fuzzy block. These are obsolete and not used anymore, but their processing is quite deeply rooted is the testsuite sources, so simply restrict the range of tags that can be used to define a fuzzy block. This change also adapts one test that used to define a fuzzy block by accident, and no longer works once the fuzzy block is removed. --- .../Exemptions/SubprogsInUnit/src/stacks.adb | 18 +++++++------- .../Exemptions/SubprogsInUnit/src/test_0.adb | 23 +++++++++--------- .../SubprogsInUnit/src/test_pop_u.adb | 12 +++++----- .../SubprogsInUnit/src/test_push_0.adb | 10 ++++---- .../SubprogsInUnit/src/test_push_o.adb | 8 +++---- .../SubprogsInUnit/src/test_pushpop_0.adb | 4 ++-- .../SubprogsInUnit/src/test_pushpop_o.adb | 2 +- .../SubprogsInUnit/src/test_pushpop_u.adb | 2 +- testsuite/SCOV/internals/xnexpanders.py | 24 ------------------- 9 files changed, 40 insertions(+), 63 deletions(-) diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/stacks.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/stacks.adb index 2ae403847..39493b7ae 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/stacks.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/stacks.adb @@ -9,22 +9,22 @@ package body Stacks is (S : in out Stack; Op : Op_Kind; V : in out Integer) -- # xregion is -- # xregion begin -- # xregion - case Op is -- # xregion_1 + case Op is -- # xregion_01 when Push => -- # xregion - if S.Vcount = S.Size then -- # xregion_2 - raise Constraint_Error; -- # xregion_3 + if S.Vcount = S.Size then -- # xregion_02 + raise Constraint_Error; -- # xregion_03 end if; -- # xregion -- # xregion - S.Vcount := S.Vcount + 1; -- # xregion_4 - S.Values (S.Vcount) := V; -- # xregion_5 + S.Vcount := S.Vcount + 1; -- # xregion_04 + S.Values (S.Vcount) := V; -- # xregion_05 -- # xregion when Pop => -- # xregion - if S.Vcount = 0 then -- # xregion_6 - raise Constraint_Error; -- # xregion_7 + if S.Vcount = 0 then -- # xregion_06 + raise Constraint_Error; -- # xregion_07 end if; -- # xregion -- # xregion - V := S.Values (S.Vcount); -- # xregion_8 - S.Vcount := S.Vcount - 1; -- # xregion_9 + V := S.Values (S.Vcount); -- # xregion_08 + S.Vcount := S.Vcount - 1; -- # xregion_09 end case; -- # xregion exception -- # xregion when Constraint_Error => -- # xregion diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_0.adb index 76a9e011d..3186da809 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_0.adb @@ -8,17 +8,18 @@ begin end; --# stacks.adb --- /xregion/ l* ## x+ --- /xregion_1/ l= ## Xs- --- /xregion_2/ l= ## Xs- --- /xregion_3/ l= ## Xs- --- /xregion_4/ l= ## Xs- --- /xregion_5/ l= ## Xs- --- /xregion_6/ l= ## Xs- --- /xregion_7/ l= ## Xs- --- /xregion_8/ l= ## Xs- --- /xregion_9/ l= ## Xs- --- /xregion_10/ l= ## Xs- +-- /xregion/ l* ## x+ +-- /xregion_01/ l= ## Xs- +-- /xregion_02/ l= ## Xs- +-- /xregion_03/ l= ## Xs- +-- /xregion_04/ l= ## Xs- +-- /xregion_05/ l= ## Xs- +-- /xregion_06/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- +-- /xregion_10/ l= ## Xs- +-- /xregion_11/ l= ## Xs- -- /push_decl/ l- ## s- -- /push_body/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pop_u.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pop_u.adb index c2e43b187..02a4911e0 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pop_u.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pop_u.adb @@ -12,12 +12,12 @@ end; --# stacks.adb -- /xregion/ l* ## x+ --- /xregion_2/ l= ## Xs- --- /xregion_3/ l= ## Xs- --- /xregion_4/ l= ## Xs- --- /xregion_5/ l= ## Xs- --- /xregion_8/ l= ## Xs- --- /xregion_9/ l= ## Xs- +-- /xregion_02/ l= ## Xs- +-- /xregion_03/ l= ## Xs- +-- /xregion_04/ l= ## Xs- +-- /xregion_05/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- -- /push_decl/ l- ## s- -- /push_body/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_0.adb index b93cb9493..54f9fed66 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_0.adb @@ -12,11 +12,11 @@ end; --# stacks.adb -- /xregion/ l* ## x+ --- /xregion_3/ l= ## Xs- --- /xregion_6/ l= ## Xs- --- /xregion_7/ l= ## Xs- --- /xregion_8/ l= ## Xs- --- /xregion_9/ l= ## Xs- +-- /xregion_03/ l= ## Xs- +-- /xregion_06/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- -- /xregion_10/ l= ## Xs- -- /push_decl/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_o.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_o.adb index 4e9bf2160..6d871a716 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_o.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_push_o.adb @@ -16,10 +16,10 @@ end; --# stacks.adb -- /xregion/ l* ## x+ --- /xregion_6/ l= ## Xs- --- /xregion_7/ l= ## Xs- --- /xregion_8/ l= ## Xs- --- /xregion_9/ l= ## Xs- +-- /xregion_06/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- -- /push_decl/ l+ ## 0 -- /push_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_0.adb index ceb981e76..af94531be 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_0.adb @@ -20,8 +20,8 @@ end; --# stacks.adb -- /xregion/ l* ## x+ --- /xregion_3/ l= ## Xs- --- /xregion_7/ l= ## Xs- +-- /xregion_03/ l= ## Xs- +-- /xregion_07/ l= ## Xs- -- /xregion_10/ l= ## Xs- -- /push_decl/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_o.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_o.adb index 5ed2e8edc..9f37a886d 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_o.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_o.adb @@ -19,7 +19,7 @@ end; --# stacks.adb -- /xregion/ l* ## x+ --- /xregion_7/ l= ## Xs- +-- /xregion_07/ l= ## Xs- -- /push_decl/ l+ ## 0 -- /push_body/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_u.adb b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_u.adb index 26ec8ad68..0d0c5cef3 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_u.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/SubprogsInUnit/src/test_pushpop_u.adb @@ -17,7 +17,7 @@ end; --# stacks.adb -- /xregion/ l* ## x+ --- /xregion_3/ l= ## Xs- +-- /xregion_03/ l= ## Xs- -- /push_decl/ l+ ## 0 -- /push_body/ l+ ## 0 diff --git a/testsuite/SCOV/internals/xnexpanders.py b/testsuite/SCOV/internals/xnexpanders.py index 6405dcca0..68c576cb7 100644 --- a/testsuite/SCOV/internals/xnexpanders.py +++ b/testsuite/SCOV/internals/xnexpanders.py @@ -408,29 +408,6 @@ def instanciate_notes_for(self, lx, tline, block, srules): if rn: self.xrdict.register(rn) - # Fuzz block processing - # - # We identify block with the help of explicit comments, not with lone - # language constructs such as begin/end in Ada. Finding the proper couples - # of the latter is not easy and error prone. - - def blopen_p(self, tline): - return re.match(r"^\s*begin\s*-- #", tline.text) - - def blclose_p(self, tline): - return re.match(r"^\s*end;\s*-- #", tline.text) - - def check_block_on(self, tline): - - if self.blopen_p(tline): - self.current_block = Block(parent=self.current_block) - - if self.blclose_p(tline): - thistest.stop_if( - not self.current_block, - FatalError("end of nonexistant block at\n=> " + tline.text)) - self.current_block = self.current_block.parent - # Kind subsitution rules processing # # For shared drivers that exercise boolean expressions in different @@ -519,7 +496,6 @@ def process_tline(self, tline): if re.search(lx.lre, tline.text): self.instanciate_notes_for(lx, tline, self.current_block, self.current_srules) - self.check_block_on(tline) def __init__(self, sref, LXset): From c13111b8e5c16f964305eef357ef0c10fc0507d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 31 May 2023 13:03:24 +0200 Subject: [PATCH 0299/1483] Add support for declare expressions This requires turning the type Any_Bit_Id into a volatile one, and making all object added as part of the insturmentation (dummy witness return values, MCDC states) constant, as non-constant object declarations are not allowed in a declare expression. --- .../declare_expr/in_expr_func/src/pkg.adb | 15 ++++ .../Ada2022/declare_expr/in_expr_func/test.py | 12 +++ .../declare_expr/in_if_stmt/src/pkg.adb | 22 +++++ .../in_if_stmt/src/test_pkg_r.adb | 35 ++++++++ .../Ada2022/declare_expr/in_if_stmt/test.py | 12 +++ .../Ada2022/declare_expr/in_ret/src/pkg.adb | 18 ++++ .../tests/Ada2022/declare_expr/in_ret/test.py | 12 +++ .../tests/Ada2022/declare_expr/src/pkg.ads | 7 ++ .../Ada2022/declare_expr/src/test_pkg_0.adb | 22 +++++ .../Ada2022/declare_expr/src/test_pkg_f.adb | 50 +++++++++++ .../Ada2022/declare_expr/src/test_pkg_r.adb | 36 ++++++++ tools/gnatcov/instrument-ada_unit.adb | 88 ++++++++++++++++--- tools/gnatcov/instrument-ada_unit.ads | 6 ++ tools/gnatcov/rts/gnatcov_rts-buffers.ads | 6 ++ 14 files changed, 331 insertions(+), 10 deletions(-) create mode 100644 testsuite/tests/Ada2022/declare_expr/in_expr_func/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/declare_expr/in_expr_func/test.py create mode 100644 testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/test_pkg_r.adb create mode 100644 testsuite/tests/Ada2022/declare_expr/in_if_stmt/test.py create mode 100644 testsuite/tests/Ada2022/declare_expr/in_ret/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/declare_expr/in_ret/test.py create mode 100644 testsuite/tests/Ada2022/declare_expr/src/pkg.ads create mode 100644 testsuite/tests/Ada2022/declare_expr/src/test_pkg_0.adb create mode 100644 testsuite/tests/Ada2022/declare_expr/src/test_pkg_f.adb create mode 100644 testsuite/tests/Ada2022/declare_expr/src/test_pkg_r.adb diff --git a/testsuite/tests/Ada2022/declare_expr/in_expr_func/src/pkg.adb b/testsuite/tests/Ada2022/declare_expr/in_expr_func/src/pkg.adb new file mode 100644 index 000000000..5ef26c5a5 --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_expr_func/src/pkg.adb @@ -0,0 +1,15 @@ +pragma Ada_2022; + +package body Pkg is + + function Compute (A, B, C, D , Stop : Boolean) return Boolean is + (declare -- # ret_stmt + AB_AT : constant Boolean := A and then B; -- # at + CD_OE : constant Boolean := C or else D; -- # oe + Did_Stop : constant Boolean := -- # stop_stmt + (if Stop then raise Dummy_Error else Stop); -- # raise_expr + F : Boolean renames B; -- # rename + begin -- # begin + AB_AT or else CD_OE); -- # eval + +end Pkg; diff --git a/testsuite/tests/Ada2022/declare_expr/in_expr_func/test.py b/testsuite/tests/Ada2022/declare_expr/in_expr_func/test.py new file mode 100644 index 000000000..6cfe237bb --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_expr_func/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of declare expressions, +within an expression function. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/pkg.adb b/testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/pkg.adb new file mode 100644 index 000000000..3c130fec7 --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/pkg.adb @@ -0,0 +1,22 @@ +pragma Ada_2022; + +package body Pkg is + + function Compute (A, B, C, D , Stop : Boolean) return Boolean is + Res : Boolean := A; -- # before + begin + if (declare -- # if_stmt + AB_AT : constant Boolean := A and then B; -- # at + CD_OE : constant Boolean := C or else D; -- # oe + Did_Stop : constant Boolean := -- # stop_stmt + (if Stop then raise Dummy_Error else Stop); -- # raise_expr + F : Boolean renames B; -- # rename + begin -- # begin + AB_AT or else CD_OE) -- # eval + then + Res := True; -- # after_expr + end if; + return Res; -- # after_expr + end Compute; + +end Pkg; diff --git a/testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/test_pkg_r.adb b/testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/test_pkg_r.adb new file mode 100644 index 000000000..8a61d5869 --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_if_stmt/src/test_pkg_r.adb @@ -0,0 +1,35 @@ +with Support; +with Pkg; + +procedure Test_Pkg_R is + Res : Boolean; +begin + Res := Pkg.Compute + (A => False, + B => False, + C => False, + D => False, + Stop => True); + Support.Assert (False); +exception + when Pkg.Dummy_Error => + null; +end Test_Pkg_R; + +-- These test expectations are specialized for this particular test, as the +-- enclosing statement for the declare contains a decision and thus different +-- expectations are required. + +--# pkg.adb +-- +-- /before/ l+ ## 0 +-- /if_stmt/ l! ## d- +-- /declare/ l! ## 0 +-- /at/ l! ## eT- +-- /oe/ l! ## eT- +-- /stop_stmt/ l! ## 0 +-- /raise_expr/ l! ## dF- +-- /rename/ l! ## s- +-- /begin/ l! ## 0 +-- /eval/ l! ## e- +-- /after/ l- ## s- diff --git a/testsuite/tests/Ada2022/declare_expr/in_if_stmt/test.py b/testsuite/tests/Ada2022/declare_expr/in_if_stmt/test.py new file mode 100644 index 000000000..0841a6a9a --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_if_stmt/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of declare expressions, +within an if statement, as part of a decision. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/declare_expr/in_ret/src/pkg.adb b/testsuite/tests/Ada2022/declare_expr/in_ret/src/pkg.adb new file mode 100644 index 000000000..4e11e02ec --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_ret/src/pkg.adb @@ -0,0 +1,18 @@ +pragma Ada_2022; + +package body Pkg is + + function Compute (A, B, C, D , Stop : Boolean) return Boolean is + begin + return -- # ret_stmt + (declare -- # declare + AB_AT : constant Boolean := A and then B; -- # at + CD_OE : constant Boolean := C or else D; -- # oe + Did_Stop : constant Boolean := -- # stop_stmt + (if Stop then raise Dummy_Error else Stop); -- # raise_expr + F : Boolean renames B; -- # rename + begin -- # begin + AB_AT or else CD_OE); -- # eval + end Compute; + +end Pkg; diff --git a/testsuite/tests/Ada2022/declare_expr/in_ret/test.py b/testsuite/tests/Ada2022/declare_expr/in_ret/test.py new file mode 100644 index 000000000..4965f0a21 --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/in_ret/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of declare expressions, in a +simple statement. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/declare_expr/src/pkg.ads b/testsuite/tests/Ada2022/declare_expr/src/pkg.ads new file mode 100644 index 000000000..dba1e78c0 --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/src/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + Dummy_Error : Exception; + + function Compute (A, B, C, D, Stop : Boolean) return Boolean; + +end Pkg; diff --git a/testsuite/tests/Ada2022/declare_expr/src/test_pkg_0.adb b/testsuite/tests/Ada2022/declare_expr/src/test_pkg_0.adb new file mode 100644 index 000000000..6261ee04c --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/src/test_pkg_0.adb @@ -0,0 +1,22 @@ +with Support; +with Pkg; + +procedure Test_Pkg_0 is +begin + null; +end Test_Pkg_0; + +--# pkg.adb +-- +-- /before/ l- ## s- +-- /ret_stmt/ l- ## s- +-- /if_stmt/ l- ## s- +-- /declare/ l- ## 0 +-- /at/ l- ## s- +-- /oe/ l- ## s- +-- /stop_stmt/ l- ## s- +-- /raise_expr/ l- ## 0 +-- /rename/ l- ## s- +-- /begin/ l- ## 0 +-- /eval/ l- ## 0 +-- /after/ l- ## s- diff --git a/testsuite/tests/Ada2022/declare_expr/src/test_pkg_f.adb b/testsuite/tests/Ada2022/declare_expr/src/test_pkg_f.adb new file mode 100644 index 000000000..f195643de --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/src/test_pkg_f.adb @@ -0,0 +1,50 @@ +with Support; +with Pkg; + +procedure Test_Pkg_F is + Res : Boolean; +begin + Res := Pkg.Compute + (A => True, + B => False, + C => False, + D => False, + Stop => False); + Res := Pkg.Compute + (A => True, + B => True, + C => True, + D => False, + Stop => False); + Res := Pkg.Compute + (A => False, + B => True, + C => False, + D => True, + Stop => False); + Res := Pkg.Compute + (A => False, + B => False, + C => False, + D => False, + Stop => True); + Support.Assert (False); +exception + when Pkg.Dummy_Error => + null; +end Test_Pkg_F; + +--# pkg.adb +-- +-- /before/ l+ ## 0 +-- /ret_stmt/ l+ ## 0 +-- /if_stmt/ l+ ## 0 +-- /declare/ l+ ## 0 +-- /at/ l+ ## 0 +-- /oe/ l+ ## 0 +-- /stop_stmt/ l+ ## 0 +-- /raise_expr/ l+ ## 0 +-- /rename/ l+ ## 0 +-- /begin/ l+ ## 0 +-- /eval/ l+ ## 0 +-- /after/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/declare_expr/src/test_pkg_r.adb b/testsuite/tests/Ada2022/declare_expr/src/test_pkg_r.adb new file mode 100644 index 000000000..b192d052e --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/src/test_pkg_r.adb @@ -0,0 +1,36 @@ +with Support; +with Pkg; + +procedure Test_Pkg_R is + Res : Boolean; +begin + Res := Pkg.Compute + (A => False, + B => False, + C => False, + D => False, + Stop => True); + Support.Assert (False); +exception + when Pkg.Dummy_Error => + null; +end Test_Pkg_R; + +-- These test expectations are not applicable for the "in_if_stmt" test, as in +-- this test the enclosing statement for the declare contains a decision and +-- thus require different expectations. + +--# pkg.adb +-- +-- /before/ l+ ## 0 +-- /ret_stmt/ l+ ## 0 +-- /if_stmt/ l! ## d- +-- /declare/ l+ ## 0 +-- /at/ l! ## eT- +-- /oe/ l! ## eT- +-- /stop_stmt/ l+ ## 0 +-- /raise_expr/ l! ## dF- +-- /rename/ l! ## s- +-- /begin/ l+ ## 0 +-- /eval/ l! ## e- +-- /after/ l- ## s- diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 17c78e804..58e095a30 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -261,7 +261,10 @@ package body Instrument.Ada_Unit is is ((Natural (Sloc.Line), Natural (Sloc.Column))); function Expr_Needs_Parens (Kind : Ada_Node_Kind_Type) return Boolean - is (Kind in Ada_Quantified_Expr | Ada_If_Expr | Ada_Case_Expr); + is (Kind in Ada_Quantified_Expr + | Ada_If_Expr + | Ada_Case_Expr + | Ada_Decl_Expr); -- Whether nodes of type Kind must be wrapped with parens function Create_Identifier @@ -1566,9 +1569,10 @@ package body Instrument.Ada_Unit is function Decl_Img return String is ("Discard_" & UIC.Instrumented_Unit.Part'Img & Bit_Img - & " : {}." & (if In_Generic and then Switches.SPARK_Compat - then "Non_Volatile_" - else "") + & " :" & (if UIC.In_Decl_Expr then " constant" else "") & " {}." + & (if In_Generic and then Switches.SPARK_Compat + then "Non_Volatile_" + else "") & "Witness_Dummy_Type := " & Call_Img); -- Start of processing for Make_Statement_Witness @@ -1613,9 +1617,9 @@ package body Instrument.Ada_Unit is return; end if; - -- Special case of conditional and quantified expressions: we need to - -- move them along with their enclosing parentheses, if they exist. - -- Otherwise, add the needed parenthesis. + -- Special case of conditional, quantified and declare expressions: we + -- need to move them along with their enclosing parentheses, if they + -- exist. Otherwise, add the needed parenthesis. if Expr_Needs_Parens (N.Kind) and then Kind (N.Parent) = Ada_Paren_Expr @@ -1732,7 +1736,8 @@ package body Instrument.Ada_Unit is is E : Instrumentation_Entities renames UIC.Entities; Var_Decl_Img : constant String := - Name & "_Var : aliased {}.MCDC_State_Type;"; + Name & "_Var :" & (if UIC.In_Decl_Expr then " constant" else "") + & " {}.MCDC_State_Type := 0;"; Addr_Decl_Img : constant String := Name & " : constant GNATCov_RTS.Sys.Address := " & Name & "_Var'Address;"; @@ -3080,7 +3085,6 @@ package body Instrument.Ada_Unit is -- more localized. procedure Process_Decisions_Defer (N : Ada_Node'Class; T : Character); - pragma Inline (Process_Decisions_Defer); -- This routine is logically the same as Process_Decisions, except that -- the arguments are saved in the SD table for later processing when -- Set_Statement_Entry is called, which goes through the saved entries @@ -3088,6 +3092,8 @@ package body Instrument.Ada_Unit is -- enclosing statement must have already been added to the current -- statement sequence, so that nested decisions are properly -- identified as such. + -- + -- This also processes any nested declare expressions. procedure Set_Statement_Entry; -- Output CS entries for all statements saved in table SC, and end the @@ -3270,8 +3276,54 @@ package body Instrument.Ada_Unit is ----------------------------- procedure Process_Decisions_Defer (N : Ada_Node'Class; T : Character) is + function Process_Decl_Expr (N : Ada_Node'Class) return Visit_Status; + -- Helper to Libadalang's Traverse. Only operates on Decl_Exprs, + -- instrument each declaration as a statement and process the nested + -- expressions. + + ----------------------- + -- Process_Decl_Expr -- + ----------------------- + + function Process_Decl_Expr (N : Ada_Node'Class) return Visit_Status is + begin + if N.Kind in Ada_Decl_Expr then + declare + Saved_Inserter : constant Any_MCDC_State_Inserter := + UIC.MCDC_State_Inserter; + Saved_In_Decl_Expr : constant Boolean := UIC.In_Decl_Expr; + Local_Inserter : aliased Default_MCDC_State_Inserter := + (Local_Decls => Handle (N.As_Decl_Expr.F_Decls)); + begin + Set_Statement_Entry; + UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; + UIC.In_Decl_Expr := True; + + -- Traverse_declarations_And_Statements will instrument the + -- declarations as statements, as well as instrument the + -- nested decisions within those declarations. + + Traverse_Declarations_Or_Statements + (UIC, N.As_Decl_Expr.F_Decls); + UIC.MCDC_State_Inserter := Saved_Inserter; + UIC.In_Decl_Expr := Saved_In_Decl_Expr; + + -- End the statement sequence right away as there isn't + -- going to be any more statements that follow. + + Set_Statement_Entry; + return Over; + end; + else + return Into; + end if; + end Process_Decl_Expr; + begin SD.Append ((N.As_Ada_Node, T)); + if not N.Is_Null then + N.Traverse (Process_Decl_Expr'Access); + end if; end Process_Decisions_Defer; ------------------------- @@ -5882,6 +5934,14 @@ package body Instrument.Ada_Unit is return Into; end; + -- Declare expressions: do not process the nested decisions in the + -- declarations, as those will be processed when instrumenting + -- them, but do process the final expression. + + when Ada_Decl_Expr => + Process_Decisions (UIC, N.As_Decl_Expr.F_Expr, 'X'); + return Over; + -- All other cases, continue scan when others => @@ -5913,6 +5973,9 @@ package body Instrument.Ada_Unit is -- -- We know have a decision as soon as we have a logical operator (by -- definition) or an IF-expression (its condition is a decision). + -- + -- Do not recurse into the declarations of declare expressions as those + -- are handled separately. ----------- -- Visit -- @@ -5920,7 +5983,12 @@ package body Instrument.Ada_Unit is function Visit (N : Ada_Node'Class) return Visit_Status is begin - if N.Kind in Ada_Expr + if N.Kind in Ada_Decl_List_Range + and then N.Parent /= No_Ada_Node + and then N.Parent.Kind in Ada_Decl_Expr + then + return Over; + elsif N.Kind in Ada_Expr and then (Is_Complex_Decision (UIC, N.As_Expr) or else N.Kind = Ada_If_Expr) then diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 2a8bfb2d0..ae4bf0ed3 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -327,6 +327,12 @@ private -- the current scope entity. This is modified when entering a scope -- (updated to the current scope), and when leaving it (updated to -- the current scope parent, if any). + + In_Decl_Expr : Boolean := False; + -- True when traversing nodes that are child of a declare expression. + -- Used to only insert constant object declarations in the declare + -- expression, as non-constant objects are not allowed per + -- RM 4.5.9 (5/5). end record; function Insert_MCDC_State diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index 64e929593..0a95db446 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -40,7 +40,13 @@ package GNATcov_RTS.Buffers is pragma Pure; + -- Any_Bit_Id is declared volatile here, as in order to instrument declare + -- expressions we need to declare a constant MC_DC_State (a subtype of + -- Any_Bit_Id) object, but prevent the compiler from optimizing out the + -- variable. + type Any_Bit_Id is new int; + pragma Volatile (Any_Bit_Id); No_Bit_Id : constant Any_Bit_Id := -1; From b3112bc80d5a5cca9e3ebc4a25b3871f56dc99df Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 31 Mar 2023 12:25:25 +0000 Subject: [PATCH 0300/1483] instrument-ada_unit.adb: update after recent Langkit API change (cherry picked from commit 86f1d2a4e5e019d5d437b3a748bd452b8f754ad4) --- tools/gnatcov/instrument-ada_unit.adb | 76 ++++++++++++++++++++------- 1 file changed, 56 insertions(+), 20 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 58e095a30..9d05e5d19 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -28,12 +28,16 @@ with Ada.Strings.Wide_Wide_Unbounded.Aux; pragma Warnings (On, "* is an internal GNAT unit"); with Langkit_Support; +with Langkit_Support.Generic_API.Introspection; +use Langkit_Support.Generic_API.Introspection; with Langkit_Support.Slocs; use Langkit_Support.Slocs; with Langkit_Support.Symbols; use Langkit_Support.Symbols; with Libadalang.Common; use Libadalang.Common; with Libadalang.Config_Pragmas; with Libadalang.Expr_Eval; -with Libadalang.Introspection; use Libadalang.Introspection; +with Libadalang.Generic_API; +with Libadalang.Generic_API.Introspection; +use Libadalang.Generic_API.Introspection; with Libadalang.Sources; use Libadalang.Sources; with GNATCOLL.Utils; @@ -354,24 +358,26 @@ package body Instrument.Ada_Unit is -- TODO??? (eng/libadalang/langkit#642) Remove these helpers to use -- Libadalang's once they are available. + Generic_Kinds : array (Ada_Node_Kind_Type) of Type_Ref; + -- Translate a Ada_Node_Kind_Type value (node type in the Libadalang API) + -- to the corresponding Struct_Member_Ref value (node type in the generic + -- Langkit_Support API). + function Child_Index (Handle : Node_Rewriting_Handle; - Field : Syntax_Field_Reference) return Positive - is (Index (Kind (Handle), Field)); + Field : Struct_Member_Ref) return Positive + is (Syntax_Field_Index (Field, Generic_Kinds (Kind (Handle)))); -- Return the index of the syntax field ``Field`` in the node designated by -- ``Handle``. function Child (Handle : Node_Rewriting_Handle; - Field : Syntax_Field_Reference) return Node_Rewriting_Handle; + Field : Struct_Member_Ref) return Node_Rewriting_Handle; -- Return the node that is in the syntax Field for Handle - type Syntax_Field_Reference_Array is - array (Positive range <>) of Syntax_Field_Reference; - function Child (Handle : Node_Rewriting_Handle; - Fields : Syntax_Field_Reference_Array) return Node_Rewriting_Handle; + Fields : Struct_Member_Ref_Array) return Node_Rewriting_Handle; -- Return a child deep in the tree Handle. -- -- Assuming Fields'Range is 1 .. N, this is a shortcut for: @@ -384,7 +390,7 @@ package body Instrument.Ada_Unit is procedure Set_Child (Handle : Node_Rewriting_Handle; - Field : Syntax_Field_Reference; + Field : Struct_Member_Ref; Child : Node_Rewriting_Handle); -- If ``Child`` is ``No_Rewriting_Node``, untie the syntax field in -- ``Handle`` corresponding to ``Field``, so it can be attached to another @@ -397,7 +403,7 @@ package body Instrument.Ada_Unit is function Child (Handle : Node_Rewriting_Handle; - Field : Syntax_Field_Reference) return Node_Rewriting_Handle + Field : Struct_Member_Ref) return Node_Rewriting_Handle is begin return Child (Handle, Child_Index (Handle, Field)); @@ -405,7 +411,7 @@ package body Instrument.Ada_Unit is function Child (Handle : Node_Rewriting_Handle; - Fields : Syntax_Field_Reference_Array) return Node_Rewriting_Handle is + Fields : Struct_Member_Ref_Array) return Node_Rewriting_Handle is begin return Result : Node_Rewriting_Handle := Handle do for F of Fields loop @@ -420,11 +426,11 @@ package body Instrument.Ada_Unit is procedure Set_Child (Handle : Node_Rewriting_Handle; - Field : Syntax_Field_Reference; + Field : Struct_Member_Ref; Child : Node_Rewriting_Handle) is begin - Set_Child (Handle, Index (Kind (Handle), Field), Child); + Set_Child (Handle, Child_Index (Handle, Field), Child); end Set_Child; --------------------- @@ -2459,7 +2465,7 @@ package body Instrument.Ada_Unit is Set_Child (Handle (Common_Nodes.N_Spec), - Subp_Spec_F_Subp_Params, + Member_Refs.Subp_Spec_F_Subp_Params, Create_Params (RC, Formal_Params)); -- If we also need a declaration for the augmented expression @@ -2482,14 +2488,14 @@ package body Instrument.Ada_Unit is -- Replace the original EF name by the augmented EF name Set_Child (New_Spec, - Subp_Spec_F_Subp_Name, + Member_Refs.Subp_Spec_F_Subp_Name, Make_Identifier (UIC, Augmented_Expr_Func_Name)); -- Add the augmented params to this spec as well Set_Child (New_Spec, - Subp_Spec_F_Subp_Params, + Member_Refs.Subp_Spec_F_Subp_Params, Create_Params (RC, Clone (Formal_Params))); Augmented_Expr_Function_Decl := Create_Subp_Decl @@ -2529,12 +2535,12 @@ package body Instrument.Ada_Unit is if Needs_Decl then Set_Child (Augmented_Expr_Function_Decl, - Basic_Decl_F_Aspects, + Member_Refs.Basic_Decl_F_Aspects, Aspects); else Set_Child (Handle (Common_Nodes.N), - Basic_Decl_F_Aspects, + Member_Refs.Basic_Decl_F_Aspects, Aspects); end if; end; @@ -3438,8 +3444,8 @@ package body Instrument.Ada_Unit is Insert_List := Child (SCE.Insertion_N, - (Accept_Stmt_With_Stmts_F_Stmts, - Handled_Stmts_F_Stmts)); + (Member_Refs.Accept_Stmt_With_Stmts_F_Stmts, + Member_Refs.Handled_Stmts_F_Stmts)); Insert_Pos := 1; else @@ -8815,4 +8821,34 @@ package body Instrument.Ada_Unit is end; end Find_Ada_Units; + -- Initialize the Generic_Kinds mapping. Ada_Node_Kind_Type is the set of + -- all concrete (non-abstract nodes) while All_Node_Types also returns + -- abstract types. Nodes that are common to both lists appear in the same + -- order, so all we need in order to build a 1:1 mapping is to filter out + -- abstract nodes from the result of All_Node_Types. + -- + -- Reduced illustration: + -- + -- * All_Node_Types: + -- Ada_Node(abstract), Identifier, Expr(abstract), Int_Literal + -- * Ada_Node_Kind_Type: + -- Identifier, Int_Literal + + Nodes : constant Type_Ref_Array := + All_Node_Types (Libadalang.Generic_API.Ada_Lang_Id); + Next : Positive := Nodes'First; +begin + for Kind in Ada_Node_Kind_Type loop + Search_Next_Concrete : loop + declare + N : Type_Ref renames Nodes (Next); + begin + Next := Next + 1; + if not Is_Abstract (N) then + Generic_Kinds (Kind) := N; + exit Search_Next_Concrete; + end if; + end; + end loop Search_Next_Concrete; + end loop; end Instrument.Ada_Unit; From ead337967eb1ed4866280487265dd69510378e23 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 11 Apr 2023 07:46:35 +0000 Subject: [PATCH 0301/1483] instrument-ada_unit.adb: update after recent Langkit API change See changes from eng/libadalang/langkit!817 TN: W328-016 (cherry picked from commit 41a46935c6ee44da9afc7ba5553ec1dbf3512a9d) --- tools/gnatcov/instrument-ada_unit.adb | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 9d05e5d19..6269cdbf2 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6961,7 +6961,7 @@ package body Instrument.Ada_Unit is case Id.Kind is when LALCO.Ada_Dotted_Name => Id := Id.As_Dotted_Name.F_Suffix.As_Name; - R_Id := Child (R_Id, Dotted_Name_F_Suffix); + R_Id := Child (R_Id, Member_Refs.Dotted_Name_F_Suffix); when LALCO.Ada_Identifier => null; @@ -7000,9 +7000,9 @@ package body Instrument.Ada_Unit is Append (Result, To_UTF8 (Text (N))); when LALCO.Ada_Dotted_Name => - Visit (Child (N, Dotted_Name_F_Prefix)); + Visit (Child (N, Member_Refs.Dotted_Name_F_Prefix)); Append (Result, '-'); - Visit (Child (N, Dotted_Name_F_Suffix)); + Visit (Child (N, Member_Refs.Dotted_Name_F_Suffix)); when others => @@ -7122,17 +7122,25 @@ package body Instrument.Ada_Unit is -- Code that is inserted to dump coverage buffers will land in this -- wrapper: set Prelude, Main_Decls and Main_Stmts accordingly. - Prelude := Child (Generic_Wrapper_Body, Compilation_Unit_F_Prelude); + Prelude := + Child (Generic_Wrapper_Body, Member_Refs.Compilation_Unit_F_Prelude); declare Subp_Body : constant Node_Rewriting_Handle := Child (Generic_Wrapper_Body, - (Compilation_Unit_F_Body, Library_Item_F_Item)); + (Member_Refs.Compilation_Unit_F_Body, + Member_Refs.Library_Item_F_Item)); begin Main_Decls := - Child (Subp_Body, (Subp_Body_F_Decls, Declarative_Part_F_Decls)); + Child + (Subp_Body, + (Member_Refs.Subp_Body_F_Decls, + Member_Refs.Declarative_Part_F_Decls)); Main_Stmts := - Child (Subp_Body, (Subp_Body_F_Stmts, Handled_Stmts_F_Stmts)); + Child + (Subp_Body, + (Member_Refs.Subp_Body_F_Stmts, + Member_Refs.Handled_Stmts_F_Stmts)); end; -- Step 3: replace the original main spec with the following From fb8ce0408ff63f9ddc80c200dcf691fded408f5a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 3 May 2023 15:29:30 +0000 Subject: [PATCH 0302/1483] Add handling for the new Always_Terminates GNAT pragma TN: W310-005 (cherry picked from commit edb868141a7e7da0cac2ad130c0e204b65d76ee0) --- tools/gnatcov/sc_obligations.ads | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index cde34dd67..07ffe8ec6 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -729,6 +729,7 @@ package SC_Obligations is Pragma_Aggregate_Individually_Assign, Pragma_All_Calls_Remote, Pragma_Allow_Integer_Address, + Pragma_Always_Terminates, Pragma_Annotate, Pragma_Assert, Pragma_Assert_And_Cut, @@ -1078,6 +1079,7 @@ package SC_Obligations is Pragma_Abort_Defer => False, Pragma_Abstract_State => False, Pragma_All_Calls_Remote => False, + Pragma_Always_Terminates => False, Pragma_Async_Readers => False, Pragma_Async_Writers => False, Pragma_Asynchronous => False, From 3e7214bbff47dc249f69a93439bbd474c6dc76cd Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 26 Apr 2023 08:04:38 +0000 Subject: [PATCH 0303/1483] instrument-ada_unit.adb: remove helpers that were added to Libadalang (cherry picked from commit 5b032f118b7cc4cb9d1c9758665f9db6c845ec59) --- tools/gnatcov/instrument-ada_unit.adb | 114 -------------------------- 1 file changed, 114 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 6269cdbf2..39516a36d 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -28,8 +28,6 @@ with Ada.Strings.Wide_Wide_Unbounded.Aux; pragma Warnings (On, "* is an internal GNAT unit"); with Langkit_Support; -with Langkit_Support.Generic_API.Introspection; -use Langkit_Support.Generic_API.Introspection; with Langkit_Support.Slocs; use Langkit_Support.Slocs; with Langkit_Support.Symbols; use Langkit_Support.Symbols; with Libadalang.Common; use Libadalang.Common; @@ -351,88 +349,6 @@ package body Instrument.Ada_Unit is Make_Identifier (UIC, D_Name))); -- Shortcut to create a defining identifier tree - ----------------------- - -- Rewriting helpers -- - ----------------------- - - -- TODO??? (eng/libadalang/langkit#642) Remove these helpers to use - -- Libadalang's once they are available. - - Generic_Kinds : array (Ada_Node_Kind_Type) of Type_Ref; - -- Translate a Ada_Node_Kind_Type value (node type in the Libadalang API) - -- to the corresponding Struct_Member_Ref value (node type in the generic - -- Langkit_Support API). - - function Child_Index - (Handle : Node_Rewriting_Handle; - Field : Struct_Member_Ref) return Positive - is (Syntax_Field_Index (Field, Generic_Kinds (Kind (Handle)))); - -- Return the index of the syntax field ``Field`` in the node designated by - -- ``Handle``. - - function Child - (Handle : Node_Rewriting_Handle; - Field : Struct_Member_Ref) return Node_Rewriting_Handle; - -- Return the node that is in the syntax Field for Handle - - function Child - (Handle : Node_Rewriting_Handle; - Fields : Struct_Member_Ref_Array) return Node_Rewriting_Handle; - -- Return a child deep in the tree Handle. - -- - -- Assuming Fields'Range is 1 .. N, this is a shortcut for: - -- - -- C1 := Child (Handle, Fields (1)); - -- C2 := Child (C1, Fields (2)); - -- ... - -- CN_1 := Child (CN_2, Fields (N - 1)); - -- CN := Child (CN_1, Fields (N)); - - procedure Set_Child - (Handle : Node_Rewriting_Handle; - Field : Struct_Member_Ref; - Child : Node_Rewriting_Handle); - -- If ``Child`` is ``No_Rewriting_Node``, untie the syntax field in - -- ``Handle`` corresponding to ``Field``, so it can be attached to another - -- one. Otherwise, ``Child`` must have no parent as it will be tied to - -- ``Handle``'s tree. - - ----------- - -- Child -- - ----------- - - function Child - (Handle : Node_Rewriting_Handle; - Field : Struct_Member_Ref) return Node_Rewriting_Handle - is - begin - return Child (Handle, Child_Index (Handle, Field)); - end Child; - - function Child - (Handle : Node_Rewriting_Handle; - Fields : Struct_Member_Ref_Array) return Node_Rewriting_Handle is - begin - return Result : Node_Rewriting_Handle := Handle do - for F of Fields loop - Result := Child (Result, F); - end loop; - end return; - end Child; - - --------------- - -- Set_Child -- - --------------- - - procedure Set_Child - (Handle : Node_Rewriting_Handle; - Field : Struct_Member_Ref; - Child : Node_Rewriting_Handle) - is - begin - Set_Child (Handle, Child_Index (Handle, Field), Child); - end Set_Child; - --------------------- -- Unbounded texts -- --------------------- @@ -8829,34 +8745,4 @@ package body Instrument.Ada_Unit is end; end Find_Ada_Units; - -- Initialize the Generic_Kinds mapping. Ada_Node_Kind_Type is the set of - -- all concrete (non-abstract nodes) while All_Node_Types also returns - -- abstract types. Nodes that are common to both lists appear in the same - -- order, so all we need in order to build a 1:1 mapping is to filter out - -- abstract nodes from the result of All_Node_Types. - -- - -- Reduced illustration: - -- - -- * All_Node_Types: - -- Ada_Node(abstract), Identifier, Expr(abstract), Int_Literal - -- * Ada_Node_Kind_Type: - -- Identifier, Int_Literal - - Nodes : constant Type_Ref_Array := - All_Node_Types (Libadalang.Generic_API.Ada_Lang_Id); - Next : Positive := Nodes'First; -begin - for Kind in Ada_Node_Kind_Type loop - Search_Next_Concrete : loop - declare - N : Type_Ref renames Nodes (Next); - begin - Next := Next + 1; - if not Is_Abstract (N) then - Generic_Kinds (Kind) := N; - exit Search_Next_Concrete; - end if; - end; - end loop Search_Next_Concrete; - end loop; end Instrument.Ada_Unit; From 9d9a2daec0f422515548e9c52a1d57b4ffa3443c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 5 Jun 2023 15:52:50 +0200 Subject: [PATCH 0304/1483] .gitlab-ci.yml: always use up-to-date Anod specs The gnatcov CI often breaks when coupled anod-gnatcov changes are pushed at the same time: the CI uses the sources of Anod specs from the last nightly source packaging. Make the CI use a fresh Anod specs clone to avoid such issues. --- .gitlab-ci.yml | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9140d7c73..009b482ea 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -16,6 +16,7 @@ variables: # PACKAGE_REPOSITORY_PROJECT: eng/cov/ci-packages # CI_FRAGMENTS: ci-fragments # CI_FRAGMENTS_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/it/$CI_FRAGMENTS + ANOD_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/it/anod GNATCOVERAGE_EXTRA_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/cov/gnatcoverage-extra .edge_vars: &edge_vars @@ -31,6 +32,13 @@ variables: EDGE_BUILD_SPACE_SUFFIX="" fi +.common_anod_bits: &common_anod_bits + - cd /tmp + - git clone --depth 1 $ANOD_GIT + - cd /it/wave + - anod tune --anod-dir /tmp/anod + - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR + stages: - build - test @@ -46,8 +54,7 @@ build: - *edge_vars # Setup the repository - - cd /it/wave - - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR + - *common_anod_bits # Build using anod - anod build --minimal gnatcov $EDGE_QUALIFIER @@ -75,7 +82,10 @@ build_community: - *edge_vars # Setup the repository + - cd /tmp + - git clone --depth 1 $ANOD_GIT - cd /it/wave + - anod tune --anod-dir /tmp/anod - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR # Build using anod @@ -104,8 +114,7 @@ build_community: - git clone $GNATCOVERAGE_EXTRA_GIT -b $EXTRA_BRANCH # Setup the anod sandbox repositories - - cd /it/wave - - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR + - *common_anod_bits - anod vcs --add-repo gnatcoverage-extra$EDGE_REPO_SUFFIX /tmp/gnatcoverage-extra # Setup fingerprints so anod doesn't do unnecessary rebuilds and does not From b5965ef9be0645b07914bd7a4121f8590dde6e9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 9 Jun 2023 15:57:44 +0200 Subject: [PATCH 0305/1483] Kill declare expression tests on light runtimes These tests propagate exceptions, so they can't run in a light runtime environment. --- testsuite/tests/Ada2022/declare_expr/extra.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/Ada2022/declare_expr/extra.opt diff --git a/testsuite/tests/Ada2022/declare_expr/extra.opt b/testsuite/tests/Ada2022/declare_expr/extra.opt new file mode 100644 index 000000000..3abfb6047 --- /dev/null +++ b/testsuite/tests/Ada2022/declare_expr/extra.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD tests propagate exceptions From 26eb0597f6ba07ac175a3224c42996c703862384 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 7 Jun 2023 11:45:55 +0200 Subject: [PATCH 0306/1483] Update .gitignore to prepare the importation of gnatcoverage-extra tests --- testsuite/.gitignore | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/testsuite/.gitignore b/testsuite/.gitignore index 8a9351363..f2233cff7 100644 --- a/testsuite/.gitignore +++ b/testsuite/.gitignore @@ -3,6 +3,13 @@ uc_* dc_* st_* tmp_* +tmp +bin +obj1 +obj2 +devnul +gprbuild.out +__pycache__ wd_* test.py.* -.~undo-tree~ \ No newline at end of file +.~undo-tree~ From 357734997c3e99f5fc4ffcda6e372f0e01180d64 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 7 Jun 2023 12:13:42 +0200 Subject: [PATCH 0307/1483] Import tests from gnatcoverage-extra --- .../IC17_026-dc-while-not/src/counters.adb | 12 + .../IC17_026-dc-while-not/src/counters.ads | 9 + .../IC17_026-dc-while-not/src/docount.adb | 10 + .../src/test_docount.adb | 10 + .../decision/IC17_026-dc-while-not/test.py | 6 + .../decision/K202_014-elsif-abs/src/add.adb | 20 + .../decision/K202_014-elsif-abs/src/add.ads | 14 + .../K202_014-elsif-abs/src/test_add.adb | 16 + .../Ada/decision/K202_014-elsif-abs/test.py | 6 + .../decision/K303_016-exwhen-abs/src/plop.adb | 24 + .../decision/K303_016-exwhen-abs/src/plop.ads | 5 + .../K303_016-exwhen-abs/src/test_tf.adb | 8 + .../Ada/decision/K303_016-exwhen-abs/test.py | 16 + .../MA07-028-expr-context/src/expr.adb | 89 ++ .../MA07-028-expr-context/src/expr.ads | 31 + .../MA07-028-expr-context/src/test_t.adb | 29 + .../decision/MA07-028-expr-context/test.py | 6 + .../T922-011-cmp-empty-str/src/pkg.adb | 13 + .../T922-011-cmp-empty-str/src/pkg.ads | 15 + .../T922-011-cmp-empty-str/src/test_f.adb | 13 + .../T922-011-cmp-empty-str/src/test_no.adb | 13 + .../T922-011-cmp-empty-str/src/test_t.adb | 13 + .../T922-011-cmp-empty-str/src/test_tf.adb | 14 + .../decision/T922-011-cmp-empty-str/test.py | 6 + .../src/test_values_ft.adb | 14 + .../src/test_values_tf.adb | 12 + .../src/test_values_tt.adb | 12 + .../mcdc/K118_027-precond_not/src/values.adb | 8 + .../mcdc/K118_027-precond_not/src/values.ads | 10 + .../Ada/mcdc/K118_027-precond_not/test.py | 6 + .../K620-028_fold-inline/src/actuators.adb | 28 + .../K620-028_fold-inline/src/actuators.ads | 20 + .../K620-028_fold-inline/src/test_fast.adb | 15 + .../Ada/mcdc/K620-028_fold-inline/test.opt | 1 + .../Ada/mcdc/K620-028_fold-inline/test.py | 6 + .../src/assert.adb | 6 + .../src/expr.adb | 21 + .../src/expr.ads | 5 + .../src/test_a.adb | 23 + .../L803-037-short-circuit-and-or/test.opt | 3 + .../L803-037-short-circuit-and-or/test.py | 6 + .../tests/Ada/mcdc/OrElse-O1/src/orelse.adb | 15 + .../tests/Ada/mcdc/OrElse-O1/src/orelse.ads | 3 + .../Ada/mcdc/OrElse-O1/src/test_orelse_a.adb | 13 + testsuite/tests/Ada/mcdc/OrElse-O1/test.py | 6 + .../tests/Ada/stmt/CmpMin/src/in_range.adb | 10 + .../tests/Ada/stmt/CmpMin/src/in_range.ali | 19 + .../stmt/CmpMin/src/test_in_range_gtmax.adb | 16 + testsuite/tests/Ada/stmt/CmpMin/test.py | 6 + .../tests/Ada/stmt/DeclChain-O1/src/flips.adb | 20 + .../tests/Ada/stmt/DeclChain-O1/src/flips.ads | 4 + .../tests/Ada/stmt/DeclChain-O1/src/flips.ali | 27 + .../Ada/stmt/DeclChain-O1/src/test_flip_0.adb | 9 + testsuite/tests/Ada/stmt/DeclChain-O1/test.py | 6 + .../tests/Ada/stmt/IncompleteTask/src/pkg.adb | 30 + .../tests/Ada/stmt/IncompleteTask/src/pkg.ads | 10 + .../Ada/stmt/IncompleteTask/src/test_full.adb | 10 + .../Ada/stmt/IncompleteTask/src/test_no.adb | 10 + .../tests/Ada/stmt/IncompleteTask/test.opt | 2 + .../tests/Ada/stmt/IncompleteTask/test.py | 11 + .../J311_011-lone_return-O1/src/flips.adb | 14 + .../J311_011-lone_return-O1/src/flips.ads | 5 + .../src/test_flips.adb | 16 + .../Ada/stmt/J311_011-lone_return-O1/test.py | 6 + .../Ada/stmt/J312_016-GotoNext-O1/src/id.adb | 8 + .../Ada/stmt/J312_016-GotoNext-O1/src/id.ali | 18 + .../J312_016-GotoNext-O1/src/test_id0.adb | 10 + .../Ada/stmt/J312_016-GotoNext-O1/test.py | 6 + .../J316_020-trivial_loop-O1/src/inc_by.adb | 8 + .../stmt/J316_020-trivial_loop-O1/src/ops.adb | 11 + .../stmt/J316_020-trivial_loop-O1/src/ops.ads | 8 + .../J316_020-trivial_loop-O1/src/test.opt | 1 + .../J316_020-trivial_loop-O1/src/test_inc.adb | 12 + .../src/test_inc_0.adb | 10 + .../src/test_ops_0.adb | 10 + .../Ada/stmt/J316_020-trivial_loop-O1/test.py | 6 + .../stmt/K316-021_setjmp-sloc/src/plop.adb | 17 + .../stmt/K316-021_setjmp-sloc/src/plop.ads | 4 + .../stmt/K316-021_setjmp-sloc/src/test_ce.adb | 14 + .../Ada/stmt/K316-021_setjmp-sloc/test.opt | 1 + .../Ada/stmt/K316-021_setjmp-sloc/test.py | 6 + .../K620-028_fold-inline/src/actuators.adb | 29 + .../K620-028_fold-inline/src/actuators.ads | 20 + .../K620-028_fold-inline/src/test_fast.adb | 15 + .../Ada/stmt/K620-028_fold-inline/test.opt | 1 + .../Ada/stmt/K620-028_fold-inline/test.py | 6 + .../PC20-011-EmptyUnit_InLib/mylib/mylib.gpr | 7 + .../mylib/ops-values.adb | 6 + .../mylib/ops-values.ads | 4 + .../PC20-011-EmptyUnit_InLib/mylib/ops.ads | 9 + .../PC20-011-EmptyUnit_InLib/src/test_inc.adb | 25 + .../stmt/PC20-011-EmptyUnit_InLib/test.opt | 2 + .../Ada/stmt/PC20-011-EmptyUnit_InLib/test.py | 16 + .../Ada2012/decision/ForOf/src/test_f.adb | 20 + .../Ada2012/decision/ForOf/src/test_t.adb | 20 + .../Ada2012/decision/ForOf/src/values.adb | 15 + .../Ada2012/decision/ForOf/src/values.ads | 12 + .../tests/Ada2012/decision/ForOf/test.py | 6 + testsuite/tests/Ada2012/extra.opt | 4 + .../Invariants/MultiOp/src/multiop.adb | 7 + .../Invariants/MultiOp/src/multiop.ads | 19 + .../Invariants/MultiOp/src/test_multiop_f.adb | 13 + .../Invariants/MultiOp/src/test_multiop_t.adb | 10 + .../mcdc/Aspects/Invariants/MultiOp/tc.rst | 4 + .../mcdc/Aspects/Invariants/MultiOp/test.opt | 1 + .../mcdc/Aspects/Invariants/MultiOp/test.py | 6 + .../Invariants/SingleOp/src/singleop.adb | 8 + .../Invariants/SingleOp/src/singleop.ads | 19 + .../SingleOp/src/test_singleop_t.adb | 10 + .../mcdc/Aspects/Invariants/SingleOp/test.opt | 1 + .../mcdc/Aspects/Invariants/SingleOp/test.py | 6 + .../Ada2012/mcdc/Aspects/Invariants/req.rst | 4 + .../Aspects/Post/MultiOpBody/src/test_0.adb | 12 + .../Aspects/Post/MultiOpBody/src/test_a.adb | 16 + .../Aspects/Post/MultiOpBody/src/test_b.adb | 16 + .../Aspects/Post/MultiOpBody/src/test_f.adb | 14 + .../Aspects/Post/MultiOpBody/src/test_t.adb | 11 + .../Aspects/Post/MultiOpBody/src/values.adb | 19 + .../Aspects/Post/MultiOpBody/src/values.ads | 11 + .../mcdc/Aspects/Post/MultiOpBody/test.opt | 1 + .../mcdc/Aspects/Post/MultiOpBody/test.py | 6 + .../Aspects/Post/SingleOpSpec/src/test_0.adb | 12 + .../Aspects/Post/SingleOpSpec/src/test_f.adb | 13 + .../Aspects/Post/SingleOpSpec/src/test_t.adb | 9 + .../Aspects/Post/SingleOpSpec/src/values.adb | 7 + .../Aspects/Post/SingleOpSpec/src/values.ads | 9 + .../mcdc/Aspects/Post/SingleOpSpec/test.opt | 1 + .../mcdc/Aspects/Post/SingleOpSpec/test.py | 6 + .../Aspects/Pre/MultiOpSpec/src/test_a.adb | 17 + .../Aspects/Pre/MultiOpSpec/src/test_b.adb | 17 + .../Aspects/Pre/MultiOpSpec/src/test_f.adb | 13 + .../Aspects/Pre/MultiOpSpec/src/test_t.adb | 12 + .../Aspects/Pre/MultiOpSpec/src/values.adb | 8 + .../Aspects/Pre/MultiOpSpec/src/values.ads | 14 + .../mcdc/Aspects/Pre/MultiOpSpec/test.opt | 1 + .../mcdc/Aspects/Pre/MultiOpSpec/test.py | 6 + .../Aspects/Pre/SingleOpBody/src/test_0.adb | 12 + .../Aspects/Pre/SingleOpBody/src/test_f.adb | 13 + .../Aspects/Pre/SingleOpBody/src/test_t.adb | 9 + .../Aspects/Pre/SingleOpBody/src/values.adb | 17 + .../Aspects/Pre/SingleOpBody/src/values.ads | 5 + .../mcdc/Aspects/Pre/SingleOpBody/test.opt | 1 + .../mcdc/Aspects/Pre/SingleOpBody/test.py | 6 + .../tests/Ada2012/mcdc/ForOf/src/test_a.adb | 22 + .../tests/Ada2012/mcdc/ForOf/src/test_ab.adb | 23 + .../tests/Ada2012/mcdc/ForOf/src/test_b.adb | 22 + .../tests/Ada2012/mcdc/ForOf/src/test_f.adb | 19 + .../tests/Ada2012/mcdc/ForOf/src/test_t.adb | 19 + .../tests/Ada2012/mcdc/ForOf/src/values.adb | 12 + .../tests/Ada2012/mcdc/ForOf/src/values.ads | 11 + testsuite/tests/Ada2012/mcdc/ForOf/test.py | 6 + .../Ada2012/mcdc/IfExpr/AndOp/src/expr.ads | 12 + .../mcdc/IfExpr/AndOp/src/test_a_opa.adb | 22 + .../mcdc/IfExpr/AndOp/src/test_a_t.adb | 22 + .../mcdc/IfExpr/AndOp/src/test_ab_t.adb | 17 + .../mcdc/IfExpr/AndOp/src/test_b_opa.adb | 22 + .../mcdc/IfExpr/AndOp/src/test_opa.adb | 22 + .../mcdc/IfExpr/AndOp/src/test_opb.adb | 21 + .../mcdc/IfExpr/AndOp/src/test_opb0.adb | 18 + .../mcdc/IfExpr/AndOp/src/test_opfull.adb | 26 + .../Ada2012/mcdc/IfExpr/AndOp/src/test_t.adb | 15 + .../tests/Ada2012/mcdc/IfExpr/AndOp/test.py | 6 + .../Ada2012/mcdc/IfExpr/Elsif/src/expr.ads | 12 + .../Ada2012/mcdc/IfExpr/Elsif/src/test_a.adb | 15 + .../mcdc/IfExpr/Elsif/src/test_a_t.adb | 15 + .../Ada2012/mcdc/IfExpr/Elsif/src/test_t.adb | 11 + .../tests/Ada2012/mcdc/IfExpr/Elsif/test.py | 6 + .../mcdc/IfExpr/ExprSctlCval/src/expr.ads | 14 + .../mcdc/IfExpr/ExprSctlCval/src/test_t.adb | 16 + .../Ada2012/mcdc/IfExpr/ExprSctlCval/test.py | 6 + .../mcdc/IfExpr/ExprSctlSval/src/expr.ads | 15 + .../mcdc/IfExpr/ExprSctlSval/src/test_t.adb | 16 + .../Ada2012/mcdc/IfExpr/ExprSctlSval/test.py | 6 + .../mcdc/IfExpr/InDeadPost/src/plus.adb | 12 + .../mcdc/IfExpr/InDeadPost/src/test_0.adb | 11 + .../mcdc/IfExpr/InDeadPost/src/test_f.adb | 11 + .../mcdc/IfExpr/InDeadPost/src/test_t.adb | 11 + .../Ada2012/mcdc/IfExpr/InDeadPost/test.py | 6 + .../mcdc/IfExpr/InDeadPre/src/plus.adb | 12 + .../mcdc/IfExpr/InDeadPre/src/test_0.adb | 11 + .../mcdc/IfExpr/InDeadPre/src/test_f.adb | 11 + .../mcdc/IfExpr/InDeadPre/src/test_t.adb | 11 + .../Ada2012/mcdc/IfExpr/InDeadPre/test.py | 6 + .../mcdc/IfExpr/RetSctlCval/src/expr.adb | 12 + .../mcdc/IfExpr/RetSctlCval/src/expr.ads | 5 + .../mcdc/IfExpr/RetSctlCval/src/test_t.adb | 16 + .../Ada2012/mcdc/IfExpr/RetSctlCval/test.py | 6 + .../mcdc/IfExpr/RetSctlSval/src/expr.adb | 12 + .../mcdc/IfExpr/RetSctlSval/src/expr.ads | 11 + .../mcdc/IfExpr/RetSctlSval/src/test_t.adb | 16 + .../Ada2012/mcdc/IfExpr/RetSctlSval/test.py | 6 + .../tests/Ada2012/mcdc/InOut/src/expr.adb | 11 + .../tests/Ada2012/mcdc/InOut/src/expr.ads | 5 + .../Ada2012/mcdc/InOut/src/test_eval_f.adb | 16 + .../Ada2012/mcdc/InOut/src/test_eval_t.adb | 16 + .../Ada2012/mcdc/InOut/src/test_neval.adb | 16 + testsuite/tests/Ada2012/mcdc/InOut/test.py | 6 + .../Ada2012/mcdc/Membership/src/test_f.adb | 10 + .../Ada2012/mcdc/Membership/src/test_t.adb | 10 + .../Ada2012/mcdc/Membership/src/test_x.adb | 10 + .../Ada2012/mcdc/Membership/src/test_y.adb | 10 + .../Ada2012/mcdc/Membership/src/values.ads | 9 + .../tests/Ada2012/mcdc/Membership/test.py | 6 + .../mcdc/Quantified/ForAll/src/test_a.adb | 15 + .../mcdc/Quantified/ForAll/src/test_b.adb | 15 + .../mcdc/Quantified/ForAll/src/test_t.adb | 14 + .../mcdc/Quantified/ForAll/src/values.adb | 17 + .../mcdc/Quantified/ForAll/src/values.ads | 7 + .../Ada2012/mcdc/Quantified/ForAll/test.py | 6 + .../mcdc/Quantified/ForAllSome/src/test_a.adb | 10 + .../mcdc/Quantified/ForAllSome/src/test_b.adb | 13 + .../mcdc/Quantified/ForAllSome/src/test_t.adb | 12 + .../mcdc/Quantified/ForAllSome/src/values.adb | 8 + .../mcdc/Quantified/ForAllSome/src/values.ads | 5 + .../mcdc/Quantified/ForAllSome/test.py | 6 + .../mcdc/Quantified/ForSome/src/test_a.adb | 15 + .../mcdc/Quantified/ForSome/src/test_b.adb | 15 + .../mcdc/Quantified/ForSome/src/test_t.adb | 12 + .../mcdc/Quantified/ForSome/src/values.adb | 8 + .../mcdc/Quantified/ForSome/src/values.ads | 5 + .../Ada2012/mcdc/Quantified/ForSome/test.py | 6 + .../Quantified/NestedInAll/src/test_a.adb | 10 + .../Quantified/NestedInAll/src/test_b.adb | 10 + .../Quantified/NestedInAll/src/test_t.adb | 9 + .../Quantified/NestedInAll/src/values.adb | 8 + .../Quantified/NestedInAll/src/values.ads | 5 + .../mcdc/Quantified/NestedInAll/test.py | 6 + .../Quantified/NestedInSome/src/test_a.adb | 10 + .../Quantified/NestedInSome/src/test_b.adb | 10 + .../Quantified/NestedInSome/src/test_t.adb | 9 + .../Quantified/NestedInSome/src/values.adb | 8 + .../Quantified/NestedInSome/src/values.ads | 4 + .../mcdc/Quantified/NestedInSome/test.py | 6 + .../mcdc/Xfunctions/AndStr/src/fuand.adb | 80 ++ .../mcdc/Xfunctions/AndStr/src/fuand.ads | 23 + .../Xfunctions/AndStr/src/test_fuand_a.adb | 14 + .../Xfunctions/AndStr/src/test_fuand_b.adb | 14 + .../Xfunctions/AndStr/src/test_fuand_t.adb | 9 + .../Ada2012/mcdc/Xfunctions/AndStr/test.py | 6 + .../Xfunctions/Freezing/src/pkg-simple.adb | 24 + .../Xfunctions/Freezing/src/pkg-simple.ads | 11 + .../mcdc/Xfunctions/Freezing/src/pkg.adb | 22 + .../mcdc/Xfunctions/Freezing/src/pkg.ads | 23 + .../mcdc/Xfunctions/Freezing/src/test_no.adb | 21 + .../Ada2012/mcdc/Xfunctions/Freezing/test.opt | 1 + .../Ada2012/mcdc/Xfunctions/Freezing/test.py | 6 + .../mcdc/Xfunctions/pAndpOr/src/expr.ads | 6 + .../Xfunctions/pAndpOr/src/test_expr_a.adb | 10 + .../Xfunctions/pAndpOr/src/test_expr_f.adb | 10 + .../Xfunctions/pAndpOr/src/test_expr_t.adb | 11 + .../Ada2012/mcdc/Xfunctions/pAndpOr/test.py | 6 + testsuite/tests/Ada2012/status.txt | 114 ++ .../ForOf/ObjectArray/src/test_values_0.adb | 15 + .../ForOf/ObjectArray/src/test_values_arg.adb | 17 + .../ForOf/ObjectArray/src/test_values_gsa.adb | 15 + .../ForOf/ObjectArray/src/values-global.ads | 6 + .../stmt/ForOf/ObjectArray/src/values.adb | 8 + .../stmt/ForOf/ObjectArray/src/values.ads | 12 + .../Ada2012/stmt/ForOf/ObjectArray/test.py | 6 + .../ForOf/PackedArray/src/test_values_0.adb | 15 + .../ForOf/PackedArray/src/test_values_arg.adb | 17 + .../ForOf/PackedArray/src/test_values_gsa.adb | 14 + .../ForOf/PackedArray/src/values-global.ads | 5 + .../stmt/ForOf/PackedArray/src/values.adb | 6 + .../stmt/ForOf/PackedArray/src/values.ads | 10 + .../Ada2012/stmt/ForOf/PackedArray/test.py | 6 + .../StraightIntArray/src/test_values_0.adb | 15 + .../StraightIntArray/src/test_values_arg.adb | 17 + .../StraightIntArray/src/test_values_gsa.adb | 15 + .../StraightIntArray/src/values-global.ads | 5 + .../ForOf/StraightIntArray/src/values.adb | 6 + .../ForOf/StraightIntArray/src/values.ads | 5 + .../stmt/ForOf/StraightIntArray/test.py | 6 + .../ForOf/UncIntArray/src/test_values_0.adb | 15 + .../ForOf/UncIntArray/src/test_values_arg.adb | 18 + .../UncIntArray/src/test_values_empty.adb | 12 + .../ForOf/UncIntArray/src/test_values_gsa.adb | 13 + .../ForOf/UncIntArray/src/values-global.ads | 5 + .../stmt/ForOf/UncIntArray/src/values.adb | 6 + .../stmt/ForOf/UncIntArray/src/values.ads | 5 + .../Ada2012/stmt/ForOf/UncIntArray/test.py | 6 + .../Ada2012/stmt/ForOf/src/values-arg.adb | 12 + .../Ada2012/stmt/ForOf/src/values-arg.ads | 4 + .../Ada2012/stmt/ForOf/src/values-global.adb | 12 + .../tests/Ada2012/stmt/InOut/src/expr.adb | 11 + .../tests/Ada2012/stmt/InOut/src/expr.ads | 5 + .../tests/Ada2012/stmt/InOut/src/expr.ali | 22 + .../Ada2012/stmt/InOut/src/test_eval_f.adb | 16 + .../Ada2012/stmt/InOut/src/test_eval_t.adb | 16 + .../Ada2012/stmt/InOut/src/test_neval.adb | 16 + testsuite/tests/Ada2012/stmt/InOut/test.py | 6 + .../NullProc/AccClassWideParam/src/pak.adb | 9 + .../NullProc/AccClassWideParam/src/pak.ads | 8 + .../stmt/NullProc/AccClassWideParam/test.py | 6 + .../AccConstClassWideParam/src/pak.adb | 9 + .../AccConstClassWideParam/src/pak.ads | 8 + .../NullProc/AccConstClassWideParam/test.py | 6 + .../stmt/NullProc/AccConstParam/src/pak.adb | 9 + .../stmt/NullProc/AccConstParam/src/pak.ads | 6 + .../stmt/NullProc/AccConstParam/test.py | 6 + .../Ada2012/stmt/NullProc/AccFunc/src/pak.adb | 13 + .../Ada2012/stmt/NullProc/AccFunc/src/pak.ads | 8 + .../Ada2012/stmt/NullProc/AccFunc/test.py | 6 + .../stmt/NullProc/AccParam/src/pak.adb | 9 + .../stmt/NullProc/AccParam/src/pak.ads | 6 + .../Ada2012/stmt/NullProc/AccParam/test.py | 6 + .../Ada2012/stmt/NullProc/AccProc/src/pak.adb | 10 + .../Ada2012/stmt/NullProc/AccProc/src/pak.ads | 6 + .../Ada2012/stmt/NullProc/AccProc/test.py | 6 + .../AccPvtFullViewBodyParam/src/pak.adb | 11 + .../AccPvtFullViewBodyParam/src/pak.ads | 13 + .../NullProc/AccPvtFullViewBodyParam/test.py | 6 + .../AccPvtFullViewSpecParam/src/pak.adb | 9 + .../AccPvtFullViewSpecParam/src/pak.ads | 14 + .../NullProc/AccPvtFullViewSpecParam/test.py | 6 + .../stmt/NullProc/AccPvtParam/src/pak.adb | 9 + .../stmt/NullProc/AccPvtParam/src/pak.ads | 13 + .../Ada2012/stmt/NullProc/AccPvtParam/test.py | 6 + .../stmt/NullProc/AccTaggedParam/src/pak.adb | 9 + .../stmt/NullProc/AccTaggedParam/src/pak.ads | 8 + .../stmt/NullProc/AccTaggedParam/test.py | 6 + .../stmt/NullProc/ClassWideParam/src/pak.adb | 9 + .../stmt/NullProc/ClassWideParam/src/pak.ads | 7 + .../stmt/NullProc/ClassWideParam/test.py | 6 + .../Ada2012/stmt/NullProc/InParam/src/pak.adb | 8 + .../Ada2012/stmt/NullProc/InParam/src/pak.ads | 6 + .../Ada2012/stmt/NullProc/InParam/test.py | 6 + .../Ada2012/stmt/NullProc/NoParam/src/pak.adb | 8 + .../Ada2012/stmt/NullProc/NoParam/src/pak.ads | 6 + .../Ada2012/stmt/NullProc/NoParam/test.py | 6 + .../stmt/NullProc/NotNullAccParam/src/pak.adb | 9 + .../stmt/NullProc/NotNullAccParam/src/pak.ads | 6 + .../stmt/NullProc/NotNullAccParam/test.py | 6 + .../NotNullAccTaggedParam/src/pak.adb | 9 + .../NotNullAccTaggedParam/src/pak.ads | 7 + .../NullProc/NotNullAccTaggedParam/test.py | 6 + .../stmt/NullProc/TaggedParam/src/pak.adb | 9 + .../stmt/NullProc/TaggedParam/src/pak.ads | 7 + .../Ada2012/stmt/NullProc/TaggedParam/test.py | 6 + .../stmt/NullProc/src/test_pak_call.adb | 18 + .../Ada2012/stmt/NullProc/src/test_pak_no.adb | 18 + .../Ada2012/stmt/Xfunctions/src/expr.ads | 4 + .../Ada2012/stmt/Xfunctions/src/test_0.adb | 9 + .../tests/Ada2012/stmt/Xfunctions/test.py | 6 + testsuite/tests/C++/extra.opt | 2 + .../mcdc/AandB/As_LambdaValue/src/tryme.cpp | 14 + .../mcdc/AandB/As_LambdaValue/src/tryme.hh | 2 + .../C++/mcdc/AandB/As_LambdaValue/test.py | 5 + .../C++/mcdc/AandB/In_ClassDef/src/tryme.cpp | 23 + .../C++/mcdc/AandB/In_ClassDef/src/tryme.hh | 2 + .../tests/C++/mcdc/AandB/In_ClassDef/test.py | 5 + .../mcdc/AandB/In_ClassTemplate/src/tryme.cpp | 25 + .../mcdc/AandB/In_ClassTemplate/src/tryme.hh | 2 + .../C++/mcdc/AandB/In_ClassTemplate/test.py | 5 + .../C++/mcdc/AandB/In_Ctor/src/tryme.cpp | 21 + .../tests/C++/mcdc/AandB/In_Ctor/src/tryme.hh | 2 + .../tests/C++/mcdc/AandB/In_Ctor/test.py | 5 + .../mcdc/AandB/In_DefaultValue/src/tryme.cpp | 21 + .../mcdc/AandB/In_DefaultValue/src/tryme.hh | 2 + .../C++/mcdc/AandB/In_DefaultValue/test.opt | 1 + .../C++/mcdc/AandB/In_DefaultValue/test.py | 5 + .../C++/mcdc/AandB/In_Dtor/src/tryme.cpp | 35 + .../tests/C++/mcdc/AandB/In_Dtor/src/tryme.hh | 2 + .../tests/C++/mcdc/AandB/In_Dtor/test.py | 5 + .../C++/mcdc/AandB/In_ExternC/src/tryme.cpp | 17 + .../C++/mcdc/AandB/In_ExternC/src/tryme.hh | 2 + .../tests/C++/mcdc/AandB/In_ExternC/test.opt | 0 .../tests/C++/mcdc/AandB/In_ExternC/test.py | 5 + .../AandB/In_FunctionTemplate/src/tryme.cpp | 15 + .../AandB/In_FunctionTemplate/src/tryme.hh | 2 + .../mcdc/AandB/In_FunctionTemplate/test.py | 5 + .../mcdc/AandB/In_LambdaBody/src/tryme.cpp | 17 + .../C++/mcdc/AandB/In_LambdaBody/src/tryme.hh | 2 + .../C++/mcdc/AandB/In_LambdaBody/test.py | 5 + .../tests/C++/mcdc/AandB/src/test_tryme_a.cpp | 17 + .../tests/C++/mcdc/AandB/src/test_tryme_b.cpp | 17 + .../C++/mcdc/AandB/src/test_tryme_full.cpp | 18 + .../C++/mcdc/AandB/src/test_tryme_fx.cpp | 19 + .../C++/mcdc/AandB/src/test_tryme_skip.cpp | 24 + .../C++/mcdc/AandB/src/test_tryme_tf.cpp | 19 + .../C++/mcdc/AandB/src/test_tryme_tt.cpp | 19 + .../tests/C++/mcdc/AandB/src/tryme_api.hh | 1 + testsuite/tests/C++/mcdc/AandB/tc_set.rst | 24 + .../C++/stmt/ForRange/WithInit/src/sum.cpp | 13 + .../C++/stmt/ForRange/WithInit/src/sum.hh | 3 + .../C++/stmt/ForRange/WithInit/src/test_0.cpp | 16 + .../ForRange/WithInit/src/test_early_exit.cpp | 26 + .../stmt/ForRange/WithInit/src/test_full.cpp | 18 + .../stmt/ForRange/WithInit/src/validate.cpp | 11 + .../stmt/ForRange/WithInit/src/validate.hh | 3 + .../tests/C++/stmt/ForRange/WithInit/test.py | 5 + .../C++/stmt/ForRange/WithoutInit/src/sum.cpp | 14 + .../C++/stmt/ForRange/WithoutInit/src/sum.hh | 3 + .../stmt/ForRange/WithoutInit/src/test_0.cpp | 17 + .../WithoutInit/src/test_early_exit.cpp | 18 + .../ForRange/WithoutInit/src/test_empty.cpp | 18 + .../ForRange/WithoutInit/src/test_full.cpp | 18 + .../C++/stmt/ForRange/WithoutInit/test.py | 5 + .../C++/stmt/WhileDecl/src/count_digits.cpp | 13 + .../C++/stmt/WhileDecl/src/count_digits.hh | 1 + .../tests/C++/stmt/WhileDecl/src/test_0.cpp | 16 + .../C++/stmt/WhileDecl/src/test_empty.cpp | 17 + .../C++/stmt/WhileDecl/src/test_full.cpp | 17 + .../C++/stmt/WhileDecl/src/test_nodigit.cpp | 17 + testsuite/tests/C++/stmt/WhileDecl/test.py | 5 + .../tests/C/decision/CommaExpr/src/cmp.c | 12 + .../tests/C/decision/CommaExpr/src/cmp.h | 1 + .../C/decision/CommaExpr/src/cmp_internal.c | 5 + .../C/decision/CommaExpr/src/cmp_internal.h | 1 + .../tests/C/decision/CommaExpr/src/test_0.c | 15 + .../tests/C/decision/CommaExpr/src/test_f.c | 21 + .../tests/C/decision/CommaExpr/src/test_t.c | 21 + .../tests/C/decision/CommaExpr/src/test_tf.c | 21 + testsuite/tests/C/decision/CommaExpr/test.py | 6 + .../NA14-030-twisted-c-expr/src/aligned.c | 8 + .../NA14-030-twisted-c-expr/src/misc.ads | 4 + .../src/test_aligned_false.adb | 11 + .../src/test_aligned_true.adb | 11 + .../decision/NA14-030-twisted-c-expr/test.opt | 1 + .../decision/NA14-030-twisted-c-expr/test.py | 6 + testsuite/tests/C/extra.opt | 2 + testsuite/tests/C/mcdc/CommaExpr/src/cmp.c | 12 + testsuite/tests/C/mcdc/CommaExpr/src/cmp.h | 1 + .../tests/C/mcdc/CommaExpr/src/cmp_internal.c | 5 + .../tests/C/mcdc/CommaExpr/src/cmp_internal.h | 1 + testsuite/tests/C/mcdc/CommaExpr/src/test_0.c | 15 + testsuite/tests/C/mcdc/CommaExpr/src/test_f.c | 21 + testsuite/tests/C/mcdc/CommaExpr/src/test_t.c | 21 + .../tests/C/mcdc/CommaExpr/src/test_tf.c | 21 + testsuite/tests/C/mcdc/CommaExpr/test.py | 6 + .../tests/C/mcdc/Exemptions/Invalid/main.c | 21 + .../tests/C/mcdc/Exemptions/Invalid/test.py | 37 + .../tests/C/mcdc/Exemptions/Nominal/src/pkg.c | 35 + .../tests/C/mcdc/Exemptions/Nominal/src/pkg.h | 12 + .../Exemptions/Nominal/src/test_exemptions.c | 20 + .../tests/C/mcdc/Exemptions/Nominal/test.py | 10 + testsuite/tests/C/mcdc/Exemptions/extra.opt | 1 + testsuite/tests/C/mcdc/Macros/pkg.h | 1 + testsuite/tests/C/mcdc/Macros/test.opt | 3 + testsuite/tests/C/mcdc/Macros/test.py | 34 + testsuite/tests/C/mcdc/Macros/test_macros.c | 47 + .../C/mcdc/Macros/test_macros.c.xcov.expected | 99 ++ .../tests/C/mcdc/include-current-dir/pkg.c | 5 + .../tests/C/mcdc/include-current-dir/pkg.h | 9 + .../tests/C/mcdc/include-current-dir/test.c | 10 + .../tests/C/mcdc/include-current-dir/test.py | 39 + testsuite/tests/C/mcdc/misc/src/aligned.c | 6 + testsuite/tests/C/mcdc/misc/src/misc.ads | 5 + .../tests/C/mcdc/misc/src/test_aligned_x.adb | 11 + testsuite/tests/C/mcdc/misc/test.py | 6 + .../C/stmt/NA28-015-default-return/calc.c | 22 + .../C/stmt/NA28-015-default-return/process.c | 27 + .../C/stmt/NA28-015-default-return/process.h | 6 + .../C/stmt/NA28-015-default-return/test.opt | 1 + .../C/stmt/NA28-015-default-return/test.py | 79 ++ .../arm_be/symbolization.baseline | 8 + .../Disassemblers/arm_be/symbolization.s | 16 + .../arm_le/symbolization.baseline | 8 + .../Disassemblers/arm_le/symbolization.s | 16 + testsuite/tests/Disassemblers/disaconv.py | 75 ++ .../Disassemblers/leon/symbolization.baseline | 10 + .../tests/Disassemblers/leon/symbolization.s | 17 + .../Disassemblers/lmp/symbolization.baseline | 12 + .../tests/Disassemblers/lmp/symbolization.s | 19 + .../ppc_be/symbolization.baseline | 8 + .../Disassemblers/ppc_be/symbolization.s | 15 + .../ppc_le/symbolization.baseline | 8 + .../Disassemblers/ppc_le/symbolization.s | 15 + testsuite/tests/Disassemblers/test.py | 134 ++ .../thumb_be/symbolization.baseline | 8 + .../Disassemblers/thumb_be/symbolization.s | 19 + .../thumb_le/symbolization.baseline | 8 + .../Disassemblers/thumb_le/symbolization.s | 19 + .../Disassemblers/x86/symbolization.baseline | 10 + .../tests/Disassemblers/x86/symbolization.s | 17 + .../x86_64/symbolization.baseline | 10 + .../Disassemblers/x86_64/symbolization.s | 17 + .../tests/FullRuntime/Barrier/src/buffer.adb | 31 + .../tests/FullRuntime/Barrier/src/buffer.ads | 18 + .../FullRuntime/Barrier/src/test_pop.adb | 38 + .../Barrier/src/test_pop_push_pop.adb | 45 + .../FullRuntime/Barrier/src/test_push.adb | 32 + .../Barrier/src/test_push_push_pop.adb | 45 + testsuite/tests/FullRuntime/Barrier/test.opt | 2 + testsuite/tests/FullRuntime/Barrier/test.py | 8 + .../stmt/Entries/SelectDelay/Lib/src/ops.adb | 56 + .../stmt/Entries/SelectDelay/Lib/test.opt | 2 + .../stmt/Entries/SelectDelay/Lib/test.py | 6 + .../Entries/SelectDelay/Local/src/ops.adb | 56 + .../stmt/Entries/SelectDelay/Local/test.opt | 2 + .../stmt/Entries/SelectDelay/Local/test.py | 6 + .../stmt/Entries/SelectElse/Lib/src/ops.adb | 41 + .../stmt/Entries/SelectElse/Lib/test.opt | 2 + .../stmt/Entries/SelectElse/Lib/test.py | 6 + .../stmt/Entries/SelectElse/Local/src/ops.adb | 40 + .../stmt/Entries/SelectElse/Local/test.opt | 2 + .../stmt/Entries/SelectElse/Local/test.py | 6 + .../stmt/Entries/SelectOr/Lib/src/ops.adb | 35 + .../stmt/Entries/SelectOr/Lib/test.opt | 2 + .../stmt/Entries/SelectOr/Lib/test.py | 6 + .../stmt/Entries/SelectOr/Local/src/ops.adb | 35 + .../stmt/Entries/SelectOr/Local/test.opt | 2 + .../stmt/Entries/SelectOr/Local/test.py | 6 + .../Entries/SelectTerminate/Lib/src/ops.adb | 39 + .../stmt/Entries/SelectTerminate/Lib/test.opt | 2 + .../stmt/Entries/SelectTerminate/Lib/test.py | 6 + .../Entries/SelectTerminate/Local/src/ops.adb | 39 + .../Entries/SelectTerminate/Local/test.opt | 2 + .../Entries/SelectTerminate/Local/test.py | 6 + .../stmt/Entries/SelectWhen/Lib/src/ops.adb | 45 + .../stmt/Entries/SelectWhen/Lib/test.opt | 2 + .../stmt/Entries/SelectWhen/Lib/test.py | 6 + .../stmt/Entries/SelectWhen/Local/src/ops.adb | 45 + .../stmt/Entries/SelectWhen/Local/test.opt | 2 + .../stmt/Entries/SelectWhen/Local/test.py | 6 + .../Entries/StraightAccept/Lib/src/ops.adb | 30 + .../stmt/Entries/StraightAccept/Lib/test.opt | 2 + .../stmt/Entries/StraightAccept/Lib/test.py | 6 + .../Entries/StraightAccept/Local/src/ops.adb | 27 + .../Entries/StraightAccept/Local/test.opt | 2 + .../stmt/Entries/StraightAccept/Local/test.py | 6 + .../FullRuntime/stmt/Entries/src/ops.ads | 4 + .../FullRuntime/stmt/Entries/src/test_0.adb | 15 + .../stmt/Entries/src/test_ops_and_tt.adb | 15 + .../ProtectedObjects/Entries/Lib/src/ops.adb | 56 + .../ProtectedObjects/Entries/Lib/test.opt | 2 + .../stmt/ProtectedObjects/Entries/Lib/test.py | 6 + .../Entries/Local/src/ops.adb | 58 + .../ProtectedObjects/Entries/Local/test.opt | 2 + .../ProtectedObjects/Entries/Local/test.py | 6 + .../Operations/Lib/src/ops.adb | 37 + .../ProtectedObjects/Operations/Lib/test.opt | 2 + .../ProtectedObjects/Operations/Lib/test.py | 6 + .../Operations/Local/src/ops.adb | 38 + .../Operations/Local/test.opt | 2 + .../ProtectedObjects/Operations/Local/test.py | 6 + .../stmt/ProtectedObjects/src/ops.ads | 4 + .../stmt/ProtectedObjects/src/test_0.adb | 13 + .../ProtectedObjects/src/test_ops_and_tt.adb | 13 + .../Mode_Variants_MCDC/src/check_g.adb | 10 + .../Mode_Variants_MCDC/src/check_g.ads | 10 + .../Mode_Variants_MCDC/src/sensors.adb | 13 + .../Mode_Variants_MCDC/src/sensors.ads | 15 + .../Mode_Variants_MCDC/src/test_cbfn.adb | 54 + .../Mode_Variants_MCDC/src/test_cifn.adb | 49 + .../Mode_Variants_MCDC/src/test_cifo.adb | 55 + .../Mode_Variants_MCDC/src/test_cnfn.adb | 37 + .../Mode_Variants_MCDC/src/test_cnfo.adb | 40 + .../tests/Generics/Mode_Variants_MCDC/tc.txt | 100 ++ .../Generics/Mode_Variants_MCDC/test.opt | 3 + .../tests/Generics/Mode_Variants_MCDC/test.py | 27 + .../Mode_Variants_STMT/src/test_v5_reset.adb | 30 + .../Generics/Mode_Variants_STMT/src/v5.ads | 3 + .../Mode_Variants_STMT/src/vectors.adb | 32 + .../Mode_Variants_STMT/src/vectors.ads | 10 + .../Generics/Mode_Variants_STMT/test.opt | 1 + .../tests/Generics/Mode_Variants_STMT/test.py | 18 + .../tests/HA16-013_cleanups/src/assert.adb | 6 + testsuite/tests/HA16-013_cleanups/src/p1.adb | 8 + testsuite/tests/HA16-013_cleanups/src/p2.adb | 11 + .../HA16-013_cleanups/src/test_blobs.adb | 23 + .../tests/HA16-013_cleanups/src/vars.adb | 11 + .../tests/HA16-013_cleanups/src/vars.ads | 9 + testsuite/tests/HA16-013_cleanups/test.opt | 1 + testsuite/tests/HA16-013_cleanups/test.py | 5 + .../ObjectCoverage/DifferentOptions/test.opt | 1 + .../ObjectCoverage/DifferentOptions/test.py | 24 + .../ObjectCoverage/DifferentOptions/test_1.c | 8 + .../ObjectCoverage/DifferentOptions/test_2.c | 8 + .../With_Debug/Not-Fact/test.py | 25 + .../With_Debug/Not-Fact/test_1.c | 8 + .../With_Debug/Not-Fact/test_2.c | 8 + .../ObjectCoverage/With_Debug/Not-Not/test.py | 22 + .../With_Debug/Not-Not/test_1.c | 8 + .../With_Debug/Not-Not/test_2.c | 8 + .../ObjectCoverage/With_Debug/target.txt | 1 + .../NotDebug-NotDebug-NotNoDebug/test.py | 33 + .../NotDebug-NotDebug-NotNoDebug/test_1.c | 8 + .../NotDebug-NotDebug-NotNoDebug/test_2.c | 8 + .../NotDebug-NotDebug-NotNoDebug/test_3.c | 8 + .../Without_Debug/NotDebug-NotNoDebug/test.py | 26 + .../NotDebug-NotNoDebug/test_1.c | 8 + .../NotDebug-NotNoDebug/test_2.c | 8 + .../NotNoDebug-FactNoDebug/test.py | 26 + .../NotNoDebug-FactNoDebug/test_1.c | 9 + .../NotNoDebug-FactNoDebug/test_2.c | 8 + .../NotNoDebug-NotNoDebug/test.py | 25 + .../NotNoDebug-NotNoDebug/test_1.c | 8 + .../NotNoDebug-NotNoDebug/test_2.c | 8 + .../ObjectCoverage/Without_Debug/target.txt | 1 + .../HomonymSymbols/ObjectCoverage/extra.opt | 1 + .../ComplexConsolidation/src/cons_all.txt | 13 + .../ComplexConsolidation/src/test_12.c | 19 + .../ComplexConsolidation/src/test_13.c | 17 + .../ComplexConsolidation/test.py | 7 + .../SourceCoverage/DifferentOptions/scos.list | 1 + .../SourceCoverage/DifferentOptions/test.opt | 2 + .../SourceCoverage/DifferentOptions/test.py | 33 + .../SourceCoverage/DifferentOptions/test_1.c | 8 + .../SourceCoverage/DifferentOptions/test_2.c | 8 + .../FunctionSections/src/cons_all.txt | 7 + .../FunctionSections/src/test_1.c | 15 + .../FunctionSections/src/test_2.c | 15 + .../SourceCoverage/FunctionSections/test.py | 7 + .../NoConsolidation/src/test_full.c | 21 + .../NoConsolidation/src/test_no.c | 26 + .../NoConsolidation/src/test_partial.c | 19 + .../SourceCoverage/NoConsolidation/test.py | 7 + .../Simple/Not-Fact/src/cons_all.txt | 10 + .../Simple/Not-Fact/src/test_1.c | 13 + .../Simple/Not-Fact/src/test_2.c | 12 + .../SourceCoverage/Simple/Not-Fact/test.py | 7 + .../Simple/Not-Not/src/cons_all.txt | 6 + .../Simple/Not-Not/src/test_1.c | 13 + .../Simple/Not-Not/src/test_2.c | 13 + .../SourceCoverage/Simple/Not-Not/test.py | 7 + testsuite/tests/HomonymSymbols/extra.opt | 2 + testsuite/tests/HomonymSymbols/src/double.c | 13 + testsuite/tests/HomonymSymbols/src/double.h | 6 + testsuite/tests/HomonymSymbols/src/fact.c | 16 + testsuite/tests/HomonymSymbols/src/fact.h | 6 + testsuite/tests/HomonymSymbols/src/not.c | 20 + testsuite/tests/HomonymSymbols/src/not.h | 6 + testsuite/tests/HomonymSymbols/src/sum.c | 42 + testsuite/tests/HomonymSymbols/src/sum.h | 9 + testsuite/tests/HomonymSymbols/src/support.h | 6 + testsuite/tests/I401-009/src/engines.adb | 30 + testsuite/tests/I401-009/src/engines.ads | 39 + testsuite/tests/I401-009/src/test_engines.adb | 48 + testsuite/tests/I401-009/test.opt | 1 + testsuite/tests/I401-009/test.py | 21 + testsuite/tests/I427-029/src/assert.adb | 6 + testsuite/tests/I427-029/src/engines.adb | 30 + testsuite/tests/I427-029/src/engines.ads | 39 + .../tests/I427-029/src/test_engines_mm.adb | 11 + .../tests/I427-029/src/test_engines_mp.adb | 9 + .../tests/I427-029/src/test_engines_pm.adb | 9 + .../tests/I427-029/src/test_engines_pp.adb | 11 + testsuite/tests/I427-029/test.opt | 1 + testsuite/tests/I427-029/test.py | 106 ++ testsuite/tests/I505-018/src/services.adb | 16 + testsuite/tests/I505-018/src/services.ads | 9 + .../tests/I505-018/src/test_services.adb | 6 + testsuite/tests/I505-018/test.py | 30 + .../tests/I511-019-response-files/src/bar.adb | 11 + .../tests/I511-019-response-files/src/bar.ads | 5 + .../tests/I511-019-response-files/src/foo.adb | 5 + .../src/test_foobar.adb | 13 + .../tests/I511-019-response-files/test.py | 36 + testsuite/tests/I512-020/ppcstart.elf | Bin 0 -> 1740 bytes testsuite/tests/I512-020/test.opt | 1 + testsuite/tests/I512-020/test.py | 6 + testsuite/tests/I519-015/func.list | 1 + testsuite/tests/I519-015/min.adb | 11 + testsuite/tests/I519-015/min.ads | 2 + testsuite/tests/I519-015/test.opt | 2 + testsuite/tests/I519-015/test.py | 56 + testsuite/tests/I519-015/test_min.adb | 12 + testsuite/tests/I519-015/test_min1.adb | 11 + testsuite/tests/I519-015/test_min2.adb | 11 + testsuite/tests/I519-030/src/kops.adb | 8 + testsuite/tests/I519-030/src/kops.ads | 8 + testsuite/tests/I519-030/src/ops4.ads | 2 + testsuite/tests/I519-030/src/ops8.ads | 2 + testsuite/tests/I519-030/src/test_kops.adb | 11 + testsuite/tests/I519-030/src/vars.adb | 8 + testsuite/tests/I519-030/src/vars.ads | 6 + testsuite/tests/I519-030/test.opt | 5 + testsuite/tests/I519-030/test.py | 75 ++ testsuite/tests/I522-010/src/volp.adb | 8 + testsuite/tests/I522-010/test.opt | 1 + testsuite/tests/I522-010/test.py | 15 + testsuite/tests/I715-012/src/monitor.adb | 6 + testsuite/tests/I715-012/src/monitor.ads | 5 + testsuite/tests/I715-012/src/p.adb | 6 + testsuite/tests/I715-012/src/pack.adb | 10 + testsuite/tests/I715-012/src/pack.ads | 5 + testsuite/tests/I715-012/test.opt | 1 + testsuite/tests/I715-012/test.py | 28 + testsuite/tests/I716-009/func.list | 1 + testsuite/tests/I716-009/min.ads | 2 + testsuite/tests/I716-009/min_asm.s | 17 + testsuite/tests/I716-009/test.opt | 2 + testsuite/tests/I716-009/test.py | 27 + testsuite/tests/I716-009/test_min.adb | 12 + testsuite/tests/I716-021/src/p.adb | 11 + testsuite/tests/I716-021/src/p.ads | 8 + testsuite/tests/I716-021/src/test_p.adb | 19 + testsuite/tests/I716-021/test.opt | 1 + testsuite/tests/I716-021/test.py | 19 + testsuite/tests/I717-018/explore.list | 1 + testsuite/tests/I717-018/src/actors.adb | 38 + testsuite/tests/I717-018/src/actors.ads | 42 + testsuite/tests/I717-018/src/controls.ads | 51 + testsuite/tests/I717-018/src/explore.adb | 78 ++ testsuite/tests/I717-018/src/geomaps.adb | 72 ++ testsuite/tests/I717-018/src/geomaps.ads | 76 ++ testsuite/tests/I717-018/src/links.adb | 100 ++ testsuite/tests/I717-018/src/links.ads | 124 ++ testsuite/tests/I717-018/src/overview.ads | 153 +++ testsuite/tests/I717-018/src/queues.adb | 74 ++ testsuite/tests/I717-018/src/queues.ads | 49 + testsuite/tests/I717-018/src/robots.adb | 142 +++ testsuite/tests/I717-018/src/robots.ads | 62 + .../I717-018/src/robots_devices-dummy.adb | 219 ++++ .../I717-018/src/robots_devices-dummy.ads | 71 ++ .../tests/I717-018/src/robots_devices.ads | 71 ++ testsuite/tests/I717-018/src/stacks.adb | 61 + testsuite/tests/I717-018/src/stacks.ads | 48 + testsuite/tests/I717-018/src/stations.adb | 162 +++ testsuite/tests/I717-018/src/stations.ads | 51 + testsuite/tests/I717-018/test.opt | 1 + testsuite/tests/I717-018/test.py | 33 + testsuite/tests/I812-011/main.adb | 4 + testsuite/tests/I812-011/test.py | 64 + testsuite/tests/I914-023/src/robots.adb | 27 + testsuite/tests/I914-023/src/robots.ads | 12 + testsuite/tests/I914-023/src/test_robots.adb | 12 + testsuite/tests/I914-023/test.opt | 2 + testsuite/tests/I914-023/test.py | 44 + testsuite/tests/I914-023/test_robots | Bin 0 -> 75892 bytes testsuite/tests/I930-009-ppc-beq-bt-x2/gnu.ld | 159 +++ .../tests/I930-009-ppc-beq-bt-x2/src/cond.s | 14 + .../I930-009-ppc-beq-bt-x2/src/test_cond.adb | 17 + .../tests/I930-009-ppc-beq-bt-x2/test.opt | 2 + .../tests/I930-009-ppc-beq-bt-x2/test.py | 35 + .../tests/I930-009-ppc-beq-bt-x2/test_cond | Bin 0 -> 73177 bytes .../I930-009-ppc-beq-bt-x2/test_cond.gpr | 14 + testsuite/tests/I930-009-ppc-beq-bt/gnu.ld | 159 +++ .../tests/I930-009-ppc-beq-bt/src/cond.s | 14 + .../I930-009-ppc-beq-bt/src/test_cond.adb | 11 + testsuite/tests/I930-009-ppc-beq-bt/test.opt | 2 + testsuite/tests/I930-009-ppc-beq-bt/test.py | 35 + testsuite/tests/I930-009-ppc-beq-bt/test_cond | Bin 0 -> 73177 bytes .../tests/I930-009-ppc-beq-bt/test_cond.gpr | 14 + testsuite/tests/I930-009-ppc-beq-ft-x2/gnu.ld | 159 +++ .../tests/I930-009-ppc-beq-ft-x2/src/cond.s | 14 + .../I930-009-ppc-beq-ft-x2/src/test_cond.adb | 11 + .../tests/I930-009-ppc-beq-ft-x2/test.opt | 2 + .../tests/I930-009-ppc-beq-ft-x2/test.py | 35 + .../tests/I930-009-ppc-beq-ft-x2/test_cond | Bin 0 -> 73177 bytes .../I930-009-ppc-beq-ft-x2/test_cond.gpr | 14 + testsuite/tests/I930-009-ppc-beq-ft/gnu.ld | 159 +++ .../tests/I930-009-ppc-beq-ft/src/cond.s | 14 + .../I930-009-ppc-beq-ft/src/test_cond.adb | 8 + testsuite/tests/I930-009-ppc-beq-ft/test.opt | 2 + testsuite/tests/I930-009-ppc-beq-ft/test.py | 35 + testsuite/tests/I930-009-ppc-beq-ft/test_cond | Bin 0 -> 73177 bytes .../tests/I930-009-ppc-beq-ft/test_cond.gpr | 14 + .../tests/I930-009-ppc-beq-npg-bt/gnu.ld | 159 +++ .../tests/I930-009-ppc-beq-npg-bt/src/cond.s | 14 + .../I930-009-ppc-beq-npg-bt/src/test_cond.adb | 11 + .../tests/I930-009-ppc-beq-npg-bt/test.opt | 2 + .../tests/I930-009-ppc-beq-npg-bt/test.py | 35 + .../tests/I930-009-ppc-beq-npg-bt/test_cond | Bin 0 -> 73169 bytes .../I930-009-ppc-beq-npg-bt/test_cond.gpr | 14 + .../tests/I930-009-ppc-beq-npg-ft/gnu.ld | 159 +++ .../tests/I930-009-ppc-beq-npg-ft/src/cond.s | 14 + .../I930-009-ppc-beq-npg-ft/src/test_cond.adb | 8 + .../tests/I930-009-ppc-beq-npg-ft/test.opt | 2 + .../tests/I930-009-ppc-beq-npg-ft/test.py | 35 + .../tests/I930-009-ppc-beq-npg-ft/test_cond | Bin 0 -> 73169 bytes .../I930-009-ppc-beq-npg-ft/test_cond.gpr | 14 + .../tests/I930-009-ppc-beq-npg-tk/gnu.ld | 159 +++ .../tests/I930-009-ppc-beq-npg-tk/src/cond.s | 14 + .../I930-009-ppc-beq-npg-tk/src/test_cond.adb | 8 + .../tests/I930-009-ppc-beq-npg-tk/test.opt | 2 + .../tests/I930-009-ppc-beq-npg-tk/test.py | 34 + .../tests/I930-009-ppc-beq-npg-tk/test_cond | Bin 0 -> 73169 bytes .../I930-009-ppc-beq-npg-tk/test_cond.gpr | 14 + testsuite/tests/I930-009-ppc-beq-nt/gnu.ld | 159 +++ .../tests/I930-009-ppc-beq-nt/src/cond.s | 14 + .../I930-009-ppc-beq-nt/src/get_false.adb | 4 + .../I930-009-ppc-beq-nt/src/get_false.ads | 1 + .../I930-009-ppc-beq-nt/src/test_cond.adb | 12 + testsuite/tests/I930-009-ppc-beq-nt/test.opt | 2 + testsuite/tests/I930-009-ppc-beq-nt/test.py | 35 + testsuite/tests/I930-009-ppc-beq-nt/test_cond | Bin 0 -> 73320 bytes .../tests/I930-009-ppc-beq-nt/test_cond.gpr | 14 + testsuite/tests/I930-009-ppc-beq-tb-x2/gnu.ld | 159 +++ .../tests/I930-009-ppc-beq-tb-x2/src/cond.s | 14 + .../I930-009-ppc-beq-tb-x2/src/test_cond.adb | 17 + .../tests/I930-009-ppc-beq-tb-x2/test.opt | 2 + .../tests/I930-009-ppc-beq-tb-x2/test.py | 35 + .../tests/I930-009-ppc-beq-tb-x2/test_cond | Bin 0 -> 73177 bytes .../I930-009-ppc-beq-tb-x2/test_cond.gpr | 14 + testsuite/tests/I930-009-ppc-beq-tb/gnu.ld | 159 +++ .../tests/I930-009-ppc-beq-tb/src/cond.s | 14 + .../I930-009-ppc-beq-tb/src/test_cond.adb | 11 + testsuite/tests/I930-009-ppc-beq-tb/test.opt | 2 + testsuite/tests/I930-009-ppc-beq-tb/test.py | 35 + testsuite/tests/I930-009-ppc-beq-tb/test_cond | Bin 0 -> 73177 bytes .../tests/I930-009-ppc-beq-tb/test_cond.gpr | 14 + testsuite/tests/I930-009-ppc-beq-tk-x2/gnu.ld | 159 +++ .../tests/I930-009-ppc-beq-tk-x2/src/cond.s | 14 + .../I930-009-ppc-beq-tk-x2/src/test_cond.adb | 11 + .../tests/I930-009-ppc-beq-tk-x2/test.opt | 2 + .../tests/I930-009-ppc-beq-tk-x2/test.py | 35 + .../tests/I930-009-ppc-beq-tk-x2/test_cond | Bin 0 -> 73177 bytes .../I930-009-ppc-beq-tk-x2/test_cond.gpr | 14 + testsuite/tests/I930-009-ppc-beq-tk/gnu.ld | 159 +++ .../tests/I930-009-ppc-beq-tk/src/cond.s | 14 + .../I930-009-ppc-beq-tk/src/test_cond.adb | 8 + testsuite/tests/I930-009-ppc-beq-tk/test.opt | 2 + testsuite/tests/I930-009-ppc-beq-tk/test.py | 35 + testsuite/tests/I930-009-ppc-beq-tk/test_cond | Bin 0 -> 73177 bytes .../tests/I930-009-ppc-beq-tk/test_cond.gpr | 14 + testsuite/tests/I930-009-ppc-beqlr-bt/gnu.ld | 159 +++ .../tests/I930-009-ppc-beqlr-bt/src/cond.s | 12 + .../I930-009-ppc-beqlr-bt/src/test_cond.adb | 11 + .../tests/I930-009-ppc-beqlr-bt/test.opt | 2 + testsuite/tests/I930-009-ppc-beqlr-bt/test.py | 36 + .../tests/I930-009-ppc-beqlr-bt/test_cond | Bin 0 -> 73173 bytes .../tests/I930-009-ppc-beqlr-bt/test_cond.gpr | 14 + testsuite/tests/I930-009-ppc-beqlr-ft/gnu.ld | 159 +++ .../tests/I930-009-ppc-beqlr-ft/src/cond.s | 12 + .../I930-009-ppc-beqlr-ft/src/test_cond.adb | 8 + .../tests/I930-009-ppc-beqlr-ft/test.opt | 2 + testsuite/tests/I930-009-ppc-beqlr-ft/test.py | 36 + .../tests/I930-009-ppc-beqlr-ft/test_cond | Bin 0 -> 73173 bytes .../tests/I930-009-ppc-beqlr-ft/test_cond.gpr | 14 + testsuite/tests/I930-009-ppc-beqlr-tb/gnu.ld | 159 +++ .../tests/I930-009-ppc-beqlr-tb/src/cond.s | 12 + .../I930-009-ppc-beqlr-tb/src/test_cond.adb | 11 + .../tests/I930-009-ppc-beqlr-tb/test.opt | 2 + testsuite/tests/I930-009-ppc-beqlr-tb/test.py | 36 + .../tests/I930-009-ppc-beqlr-tb/test_cond | Bin 0 -> 73173 bytes .../tests/I930-009-ppc-beqlr-tb/test_cond.gpr | 14 + testsuite/tests/I930-009-ppc-beqlr-tk/gnu.ld | 159 +++ .../tests/I930-009-ppc-beqlr-tk/src/cond.s | 12 + .../I930-009-ppc-beqlr-tk/src/test_cond.adb | 8 + .../tests/I930-009-ppc-beqlr-tk/test.opt | 2 + testsuite/tests/I930-009-ppc-beqlr-tk/test.py | 36 + .../tests/I930-009-ppc-beqlr-tk/test_cond | Bin 0 -> 73173 bytes .../tests/I930-009-ppc-beqlr-tk/test_cond.gpr | 14 + .../tests/I930-009-sparc-be-a-ft/src/cond.c | 8 + .../tests/I930-009-sparc-be-a-ft/src/cond.s | 15 + .../src/last_chance_handler.adb | 17 + .../src/last_chance_handler.ads | 9 + .../I930-009-sparc-be-a-ft/src/test_cond.adb | 10 + .../tests/I930-009-sparc-be-a-ft/test.opt | 3 + .../tests/I930-009-sparc-be-a-ft/test.py | 37 + .../tests/I930-009-sparc-be-a-ft/test_cond | Bin 0 -> 72983 bytes .../I930-009-sparc-be-a-ft/test_cond.gpr | 20 + .../I930-009-sparc-be-a-npg-ft/src/cond.c | 8 + .../I930-009-sparc-be-a-npg-ft/src/cond.s | 17 + .../src/last_chance_handler.adb | 17 + .../src/last_chance_handler.ads | 9 + .../src/test_cond.adb | 10 + .../tests/I930-009-sparc-be-a-npg-ft/test.opt | 3 + .../tests/I930-009-sparc-be-a-npg-ft/test.py | 17 + .../I930-009-sparc-be-a-npg-ft/test_cond | Bin 0 -> 76072 bytes .../I930-009-sparc-be-a-npg-ft/test_cond.gpr | 20 + .../I930-009-sparc-be-a-npg-tk/src/cond.c | 8 + .../I930-009-sparc-be-a-npg-tk/src/cond.s | 17 + .../src/last_chance_handler.adb | 17 + .../src/last_chance_handler.ads | 9 + .../src/test_cond.adb | 10 + .../tests/I930-009-sparc-be-a-npg-tk/test.opt | 3 + .../tests/I930-009-sparc-be-a-npg-tk/test.py | 15 + .../I930-009-sparc-be-a-npg-tk/test_cond | Bin 0 -> 76072 bytes .../I930-009-sparc-be-a-npg-tk/test_cond.gpr | 20 + .../tests/I930-009-sparc-be-a-nt/src/cond.c | 8 + .../tests/I930-009-sparc-be-a-nt/src/cond.s | 15 + .../src/last_chance_handler.adb | 17 + .../src/last_chance_handler.ads | 9 + .../I930-009-sparc-be-a-nt/src/test_cond.adb | 10 + .../tests/I930-009-sparc-be-a-nt/test.opt | 3 + .../tests/I930-009-sparc-be-a-nt/test.py | 38 + .../tests/I930-009-sparc-be-a-nt/test_cond | Bin 0 -> 72983 bytes .../I930-009-sparc-be-a-nt/test_cond.gpr | 20 + .../tests/I930-009-sparc-be-a-tk/src/cond.c | 8 + .../tests/I930-009-sparc-be-a-tk/src/cond.s | 15 + .../src/last_chance_handler.adb | 17 + .../src/last_chance_handler.ads | 9 + .../I930-009-sparc-be-a-tk/src/test_cond.adb | 10 + .../tests/I930-009-sparc-be-a-tk/test.opt | 3 + .../tests/I930-009-sparc-be-a-tk/test.py | 38 + .../tests/I930-009-sparc-be-a-tk/test_cond | Bin 0 -> 72983 bytes .../I930-009-sparc-be-a-tk/test_cond.gpr | 20 + .../tests/I930-009-sparc-be-bt/src/cond.c | 8 + .../tests/I930-009-sparc-be-bt/src/cond.s | 16 + .../src/last_chance_handler.adb | 17 + .../src/last_chance_handler.ads | 9 + .../I930-009-sparc-be-bt/src/test_cond.adb | 13 + testsuite/tests/I930-009-sparc-be-bt/test.opt | 3 + testsuite/tests/I930-009-sparc-be-bt/test.py | 34 + .../tests/I930-009-sparc-be-bt/test_cond | Bin 0 -> 73031 bytes .../tests/I930-009-sparc-be-bt/test_cond.gpr | 20 + .../tests/I930-009-sparc-be-ft/src/cond.c | 8 + .../tests/I930-009-sparc-be-ft/src/cond.s | 16 + .../src/last_chance_handler.adb | 17 + .../src/last_chance_handler.ads | 9 + .../I930-009-sparc-be-ft/src/test_cond.adb | 10 + testsuite/tests/I930-009-sparc-be-ft/test.opt | 3 + testsuite/tests/I930-009-sparc-be-ft/test.py | 39 + .../tests/I930-009-sparc-be-ft/test_cond | Bin 0 -> 72983 bytes .../tests/I930-009-sparc-be-ft/test_cond.gpr | 20 + .../tests/I930-009-sparc-be-npg-bt/src/cond.c | 8 + .../tests/I930-009-sparc-be-npg-bt/src/cond.s | 18 + .../src/last_chance_handler.adb | 17 + .../src/last_chance_handler.ads | 9 + .../src/test_cond.adb | 13 + .../tests/I930-009-sparc-be-npg-bt/test.opt | 3 + .../tests/I930-009-sparc-be-npg-bt/test.py | 14 + .../tests/I930-009-sparc-be-npg-bt/test_cond | Bin 0 -> 76080 bytes .../I930-009-sparc-be-npg-bt/test_cond.gpr | 20 + .../tests/I930-009-sparc-be-npg-ft/src/cond.c | 8 + .../tests/I930-009-sparc-be-npg-ft/src/cond.s | 18 + .../src/last_chance_handler.adb | 17 + .../src/last_chance_handler.ads | 9 + .../src/test_cond.adb | 10 + .../tests/I930-009-sparc-be-npg-ft/test.opt | 3 + .../tests/I930-009-sparc-be-npg-ft/test.py | 15 + .../tests/I930-009-sparc-be-npg-ft/test_cond | Bin 0 -> 76080 bytes .../I930-009-sparc-be-npg-ft/test_cond.gpr | 20 + .../tests/I930-009-sparc-be-npg-tk/src/cond.c | 8 + .../tests/I930-009-sparc-be-npg-tk/src/cond.s | 18 + .../src/last_chance_handler.adb | 17 + .../src/last_chance_handler.ads | 9 + .../src/test_cond.adb | 10 + .../tests/I930-009-sparc-be-npg-tk/test.opt | 3 + .../tests/I930-009-sparc-be-npg-tk/test.py | 15 + .../tests/I930-009-sparc-be-npg-tk/test_cond | Bin 0 -> 76080 bytes .../I930-009-sparc-be-npg-tk/test_cond.gpr | 20 + .../tests/I930-009-sparc-be-nt/src/cond.c | 8 + .../tests/I930-009-sparc-be-nt/src/cond.s | 16 + .../src/last_chance_handler.adb | 17 + .../src/last_chance_handler.ads | 9 + .../I930-009-sparc-be-nt/src/test_cond.adb | 13 + testsuite/tests/I930-009-sparc-be-nt/test.opt | 3 + testsuite/tests/I930-009-sparc-be-nt/test.py | 35 + .../tests/I930-009-sparc-be-nt/test_cond | Bin 0 -> 73206 bytes .../tests/I930-009-sparc-be-nt/test_cond.gpr | 20 + .../tests/I930-009-sparc-be-tk/src/cond.c | 8 + .../tests/I930-009-sparc-be-tk/src/cond.s | 16 + .../src/last_chance_handler.adb | 17 + .../src/last_chance_handler.ads | 9 + .../I930-009-sparc-be-tk/src/test_cond.adb | 10 + testsuite/tests/I930-009-sparc-be-tk/test.opt | 3 + testsuite/tests/I930-009-sparc-be-tk/test.py | 34 + .../tests/I930-009-sparc-be-tk/test_cond | Bin 0 -> 72983 bytes .../tests/I930-009-sparc-be-tk/test_cond.gpr | 20 + .../I930-009-sparc-cross-boundary/src/cond.c | 8 + .../I930-009-sparc-cross-boundary/src/cond.s | 15 + .../src/last_chance_handler.adb | 17 + .../src/last_chance_handler.ads | 9 + .../src/test_cond.adb | 10 + .../I930-009-sparc-cross-boundary/test.opt | 3 + .../I930-009-sparc-cross-boundary/test.py | 36 + .../I930-009-sparc-cross-boundary/test_cond | Bin 0 -> 72989 bytes .../test_cond.gpr | 20 + testsuite/tests/I930-019/src/kops.adb | 8 + testsuite/tests/I930-019/src/kops.ads | 8 + testsuite/tests/I930-019/src/ops4.ads | 2 + testsuite/tests/I930-019/src/ops8.ads | 2 + testsuite/tests/I930-019/src/test_kops.adb | 11 + testsuite/tests/I930-019/src/vars.adb | 8 + testsuite/tests/I930-019/src/vars.ads | 6 + testsuite/tests/I930-019/test.py | 29 + testsuite/tests/IA01-015/src/monitor.adb | 6 + testsuite/tests/IA01-015/src/monitor.ads | 5 + testsuite/tests/IA01-015/src/trymon.adb | 25 + testsuite/tests/IA01-015/test.py | 54 + .../tests/IA06-008-override-exec/src/noop.adb | 25 + .../tests/IA06-008-override-exec/test.opt | 1 + .../tests/IA06-008-override-exec/test.py | 41 + .../tests/IA06-009-offset-from-sym/src/p.adb | 8 + .../tests/IA06-009-offset-from-sym/test.opt | 1 + .../tests/IA06-009-offset-from-sym/test.py | 24 + .../tests/IA09-021-unit-nosco/src/checks.adb | 8 + .../tests/IA09-021-unit-nosco/src/checks.ads | 5 + .../IA09-021-unit-nosco/src/test_assert.adb | 10 + testsuite/tests/IA09-021-unit-nosco/test.opt | 1 + testsuite/tests/IA09-021-unit-nosco/test.py | 17 + .../tests/IA13-015-loop-body/src/for_loop.adb | 14 + testsuite/tests/IA13-015-loop-body/test.opt | 1 + testsuite/tests/IA13-015-loop-body/test.py | 15 + .../IA16-028-disp-routines/baseline3.txt | 3 + .../IA16-028-disp-routines/src/monitor.adb | 7 + .../IA16-028-disp-routines/src/monitor.ads | 4 + .../tests/IA16-028-disp-routines/src/p.adb | 12 + .../tests/IA16-028-disp-routines/src/pack.adb | 13 + .../tests/IA16-028-disp-routines/src/pack.ads | 9 + .../tests/IA16-028-disp-routines/test.py | 59 + .../IA19-009-no-useless-srcs/src/engines.adb | 30 + .../IA19-009-no-useless-srcs/src/engines.ads | 39 + .../src/test_engines.adb | 48 + .../tests/IA19-009-no-useless-srcs/test.py | 29 + .../IA21-003-simple-decision-sco/src/p.adb | 25 + .../IA21-003-simple-decision-sco/src/pack.adb | 13 + .../IA21-003-simple-decision-sco/src/pack.ads | 9 + .../IA21-003-simple-decision-sco/test.opt | 1 + .../IA21-003-simple-decision-sco/test.py | 21 + .../src/nested_same_sloc.adb | 9 + testsuite/tests/IA21-009-nested-scos/test.py | 9 + .../tests/IA22-004-same-basename/.gitignore | 1 + .../tests/IA22-004-same-basename/d1/func.c | 5 + .../tests/IA22-004-same-basename/d2/func.c | 5 + testsuite/tests/IA22-004-same-basename/main.c | 29 + .../tests/IA22-004-same-basename/main.elf | Bin 0 -> 77580 bytes .../tests/IA22-004-same-basename/put.adb | 8 + .../tests/IA22-004-same-basename/put.ads | 4 + .../tests/IA22-004-same-basename/repro.adb | 8 + .../tests/IA22-004-same-basename/test.opt | 2 + .../tests/IA22-004-same-basename/test.py | 56 + .../IA29-020-basic-checks/src/engines.adb | 30 + .../IA29-020-basic-checks/src/engines.ads | 39 + .../src/test_engines.adb | 48 + .../tests/IA29-020-basic-checks/test.opt | 1 + testsuite/tests/IA29-020-basic-checks/test.py | 65 + .../IA29-023-source-search/src/engines.adb | 30 + .../IA29-023-source-search/src/engines.ads | 39 + .../src/test_engines.adb | 48 + .../tests/IA29-023-source-search/test.py | 43 + testsuite/tests/J618-019-disa-x86/insn.o | Bin 0 -> 466 bytes testsuite/tests/J618-019-disa-x86/insn.s | 6 + testsuite/tests/J618-019-disa-x86/test.opt | 1 + testsuite/tests/J618-019-disa-x86/test.py | 8 + .../ada_containers-aunit_lists.elf | Bin 0 -> 1018 bytes .../tests/J723-017-empty-debug-info/test.opt | 1 + .../tests/J723-017-empty-debug-info/test.py | 8 + testsuite/tests/JC09-015-set-file/hello.o | Bin 0 -> 2848 bytes testsuite/tests/JC09-015-set-file/hello.s | 319 +++++ testsuite/tests/JC09-015-set-file/test.opt | 1 + testsuite/tests/JC09-015-set-file/test.py | 8 + .../tests/K214-014-gc-sections/src/foo.adb | 8 + .../tests/K214-014-gc-sections/src/pck.adb | 16 + .../tests/K214-014-gc-sections/src/pck.ads | 5 + testsuite/tests/K214-014-gc-sections/test.opt | 3 + testsuite/tests/K214-014-gc-sections/test.py | 22 + .../K317-011_raven-textio/src/test_textio.adb | 8 + .../tests/K317-011_raven-textio/test.opt | 2 + testsuite/tests/K317-011_raven-textio/test.py | 6 + .../tests/K804-031_raise-taken/src/args.adb | 6 + .../tests/K804-031_raise-taken/src/args.ads | 8 + .../K804-031_raise-taken/src/test_val_ce.adb | 14 + .../K804-031_raise-taken/src/test_vif_r.adb | 12 + .../K804-031_raise-taken/src/test_vif_rf.adb | 13 + .../K804-031_raise-taken/src/test_vif_rt.adb | 13 + .../K804-031_raise-taken/src/test_vifn_r.adb | 12 + .../K804-031_raise-taken/src/test_vifn_rf.adb | 13 + .../K804-031_raise-taken/src/test_vifn_rt.adb | 13 + .../tests/K804-031_raise-taken/src/val.adb | 20 + .../tests/K804-031_raise-taken/src/val.ads | 5 + .../tests/K804-031_raise-taken/src/vif.adb | 18 + .../tests/K804-031_raise-taken/src/vif.ads | 7 + .../tests/K804-031_raise-taken/src/vifn.adb | 18 + .../tests/K804-031_raise-taken/src/vifn.ads | 7 + testsuite/tests/K804-031_raise-taken/test.py | 7 + .../tests/KB30-011-eargs-gnatemu/myinc.adb | 6 + .../tests/KB30-011-eargs-gnatemu/test.opt | 4 + .../tests/KB30-011-eargs-gnatemu/test.py | 111 ++ testsuite/tests/KC06-023-list_as_ali/plist | 1 + .../tests/KC06-023-list_as_ali/src/p.adb | 1 + testsuite/tests/KC06-023-list_as_ali/test.py | 18 + .../tests/KC23-012-ocov-exemptions/p.adb | 28 + .../tests/KC23-012-ocov-exemptions/test.opt | 1 + .../tests/KC23-012-ocov-exemptions/test.py | 47 + .../src/dom_debug.adb | 18 + .../L112-050-pro-through-disabled/test.py | 29 + .../tests/L209-010-asm-outfile/src/plop.adb | 6 + testsuite/tests/L209-010-asm-outfile/test.opt | 1 + testsuite/tests/L209-010-asm-outfile/test.py | 41 + .../L411-031_missing_gnateS/src/checks.adb | 15 + .../L411-031_missing_gnateS/src/checks.ads | 14 + .../src/test_assert.adb | 10 + .../tests/L411-031_missing_gnateS/test.opt | 1 + .../tests/L411-031_missing_gnateS/test.py | 80 ++ testsuite/tests/L613-012/app.gpr | 8 + testsuite/tests/L613-012/pak1.ads | 2 + testsuite/tests/L613-012/test.py | 14 + .../tests/L619-040-output-to-objdir/pgm.adb | 13 + .../tests/L619-040-output-to-objdir/test.py | 44 + .../tests/L707-006-src-in-cwd/engines.adb | 30 + .../tests/L707-006-src-in-cwd/engines.ads | 39 + testsuite/tests/L707-006-src-in-cwd/test.opt | 1 + testsuite/tests/L707-006-src-in-cwd/test.py | 13 + .../L707-006-src-in-cwd/test_engines.adb | 48 + testsuite/tests/L929-006/leon-elf-emptys.s | 44 + .../tests/L929-006/leon-elf-expected.out | 9 + testsuite/tests/L929-006/leon-elf-orphans.s | 44 + testsuite/tests/L929-006/powerpc-elf-emptys.s | 37 + .../tests/L929-006/powerpc-elf-expected.out | 9 + .../tests/L929-006/powerpc-elf-orphans.s | 36 + testsuite/tests/L929-006/test.opt | 3 + testsuite/tests/L929-006/test.py | 44 + .../LA17-032-scan-decisions/expected.out | 2 + testsuite/tests/LA17-032-scan-decisions/p.adb | 10 + .../tests/LA17-032-scan-decisions/state.ads | 4 + .../tests/LA17-032-scan-decisions/test.opt | 1 + .../tests/LA17-032-scan-decisions/test.py | 23 + .../tests/LA23-016_eargs-exe/src/myabs.adb | 9 + testsuite/tests/LA23-016_eargs-exe/src/p.adb | 7 + testsuite/tests/LA23-016_eargs-exe/test.opt | 1 + testsuite/tests/LA23-016_eargs-exe/test.py | 58 + .../tests/LB13-031-post-aspect/src/orelse.ads | 3 + .../tests/LB13-031-post-aspect/src/passor.adb | 5 + .../tests/LB13-031-post-aspect/src/passor.ads | 4 + .../src/test_passor_0.adb | 14 + .../src/test_passor_ff.adb | 16 + .../src/test_passor_ft.adb | 16 + .../src/test_passor_fu.adb | 17 + .../src/test_passor_tx.adb | 16 + testsuite/tests/LB13-031-post-aspect/tc.txt | 2 + testsuite/tests/LB13-031-post-aspect/test.opt | 4 + testsuite/tests/LB13-031-post-aspect/test.py | 7 + .../LB15-031-split-PPC-aspect/src/andthen.ads | 3 + .../LB15-031-split-PPC-aspect/src/passand.adb | 4 + .../LB15-031-split-PPC-aspect/src/passand.ads | 4 + .../src/test_passand_0.adb | 12 + .../src/test_passand_fu.adb | 17 + .../src/test_passand_fx.adb | 16 + .../src/test_passand_tf.adb | 16 + .../src/test_passand_tt.adb | 14 + .../tests/LB15-031-split-PPC-aspect/tc.txt | 2 + .../tests/LB15-031-split-PPC-aspect/test.opt | 4 + .../tests/LB15-031-split-PPC-aspect/test.py | 7 + testsuite/tests/LibExp/.gitignore | 2 + .../LibExp/AndXY/src/test_computing_v0.adb | 49 + .../LibExp/AndXY/src/test_computing_v02.adb | 49 + .../LibExp/AndXY/src/test_computing_v03.adb | 50 + .../LibExp/AndXY/src/test_computing_v23.adb | 50 + testsuite/tests/LibExp/extra.opt | 2 + testsuite/tests/LibExp/group.py | 3 + testsuite/tests/LibExp/set.txt | 38 + testsuite/tests/LibExp/src/support.h | 9 + .../M204-037-dc-in-aggregate/src/assert.adb | 6 + .../M204-037-dc-in-aggregate/src/test_1.adb | 15 + .../M204-037-dc-in-aggregate/src/values.adb | 13 + .../M204-037-dc-in-aggregate/src/values.ads | 10 + .../tests/M204-037-dc-in-aggregate/test.py | 8 + .../M502-040-default-prj-path/.gitignore | 2 + .../M502-040-default-prj-path/proj/proj.gpr | 4 + .../proj/ut/main.adb | 1 + .../proj/ut/ut.gpr.template | 11 + .../tests/M502-040-default-prj-path/test.opt | 1 + .../tests/M502-040-default-prj-path/test.py | 27 + testsuite/tests/M513-017/driver.adb | 8 + testsuite/tests/M513-017/lib.adb | 25 + testsuite/tests/M513-017/lib.ads | 4 + testsuite/tests/M513-017/test.opt | 1 + testsuite/tests/M513-017/test.py | 9 + .../M514-031-multiple-stmts-lines/src/ops.adb | 18 + .../M514-031-multiple-stmts-lines/src/ops.ads | 5 + .../src/test_full.adb | 10 + .../src/test_no.adb | 10 + .../M514-031-multiple-stmts-lines/test.py | 7 + testsuite/tests/M515-018/return-ternary.c | 11 + testsuite/tests/M515-018/test.opt | 3 + testsuite/tests/M515-018/test.py | 23 + .../M516-014-direct-bool-operators/req.txt | 12 + .../src/assert.adb | 6 + .../src/assert.ads | 1 + .../src/ops.adb | 18 + .../src/ops.ads | 5 + .../src/test_and.adb | 18 + .../src/test_ff.adb | 17 + .../src/test_ft.adb | 17 + .../src/test_or.adb | 18 + .../src/test_tf.adb | 17 + .../src/test_tt.adb | 17 + .../src/test_xor.adb | 18 + .../M516-014-direct-bool-operators/test.py | 8 + .../alternate/src/assert.adb | 7 + .../alternate/src/assert.ads | 1 + .../alternate/src/foo.adb | 42 + .../alternate/src/foo.ads | 6 + .../alternate/src/test_ff.adb | 14 + .../alternate/src/test_ft.adb | 14 + .../alternate/src/test_tx.adb | 14 + .../alternate/test.py | 8 + .../M528-002-transient-finalize/extra.opt | 3 + .../original/src/log.adb | 12 + .../original/src/test_main.adb | 63 + .../original/test.py | 8 + .../variant1/src/assert.adb | 6 + .../variant1/src/log.adb | 12 + .../variant1/src/pkg.adb | 15 + .../variant1/src/pkg.ads | 12 + .../variant1/src/test_df.adb | 15 + .../variant1/src/test_dt.adb | 15 + .../variant1/test.py | 8 + .../tests/M531-035-3264-ld_preload/sls.c | 8 + .../tests/M531-035-3264-ld_preload/test.opt | 2 + .../tests/M531-035-3264-ld_preload/test.py | 29 + testsuite/tests/M625-011-GPR-Cunits/src/bar.c | 7 + testsuite/tests/M625-011-GPR-Cunits/src/bar.h | 12 + testsuite/tests/M625-011-GPR-Cunits/src/foo.c | 7 + testsuite/tests/M625-011-GPR-Cunits/test.py | 43 + .../tests/M625-040-slow_on_windows/p.adb | 16 + .../tests/M625-040-slow_on_windows/test.opt | 2 + .../tests/M625-040-slow_on_windows/test.py | 54 + .../Const-Run-Run/src/ops.adb | 16 + .../Const-Run-Run/src/test_no.adb | 36 + .../Const-Run-Run/src/test_outcome_false.adb | 36 + .../Const-Run-Run/src/test_outcome_true.adb | 36 + .../Const-Run-Run/src/test_second.adb | 37 + .../Const-Run-Run/src/test_second_third.adb | 38 + .../Const-Run-Run/src/test_third.adb | 37 + .../Const-Run-Run/test.py | 8 + .../Const-Run/src/ops.adb | 9 + .../Const-Run/src/test_no.adb | 27 + .../Const-Run/src/test_outcome_true.adb | 27 + .../Const-Run/test.opt | 1 + .../Const-Run/test.py | 8 + .../InliningMakingConstant/src/ops.adb | 22 + .../InliningMakingConstant/src/test_no.adb | 42 + .../InliningMakingConstant/test.py | 8 + .../Run-Const-Run/src/ops.adb | 16 + .../Run-Const-Run/src/test_first.adb | 37 + .../Run-Const-Run/src/test_first_third.adb | 38 + .../Run-Const-Run/src/test_no.adb | 36 + .../Run-Const-Run/src/test_outcome_false.adb | 36 + .../Run-Const-Run/src/test_outcome_true.adb | 36 + .../Run-Const-Run/src/test_third.adb | 37 + .../Run-Const-Run/test.py | 8 + .../Run-ConstOutcome-Run/src/ops.adb | 16 + .../Run-ConstOutcome-Run/src/test_first.adb | 37 + .../src/test_first_third.adb | 38 + .../Run-ConstOutcome-Run/src/test_no.adb | 36 + .../src/test_outcome_false.adb | 36 + .../src/test_outcome_true.adb | 36 + .../Run-ConstOutcome-Run/src/test_third.adb | 37 + .../Run-ConstOutcome-Run/test.py | 8 + .../Run-ConstRCheck-Run/src/ops.adb | 16 + .../Run-ConstRCheck-Run/src/test_first.adb | 37 + .../src/test_first_third.adb | 38 + .../Run-ConstRCheck-Run/src/test_no.adb | 36 + .../src/test_outcome_false.adb | 36 + .../src/test_outcome_true.adb | 36 + .../Run-ConstRCheck-Run/src/test_third.adb | 37 + .../Run-ConstRCheck-Run/test.py | 8 + .../Run-Run-Const/src/ops.adb | 16 + .../Run-Run-Const/src/test_first.adb | 37 + .../Run-Run-Const/src/test_first_second.adb | 38 + .../Run-Run-Const/src/test_no.adb | 36 + .../Run-Run-Const/src/test_outcome_false.adb | 36 + .../Run-Run-Const/src/test_outcome_true.adb | 36 + .../Run-Run-Const/src/test_second.adb | 37 + .../Run-Run-Const/test.py | 8 + .../M716-023-constant-conditions/extra.opt | 2 + .../src/assert.adb | 6 + .../src/assert.ads | 1 + .../M716-023-constant-conditions/src/ops.ads | 24 + .../src/show_whether_local.adb | 33 + .../M724-035-eh-warnings/src/strict_head.adb | 11 + .../M724-035-eh-warnings/src/test_both.adb | 13 + .../M724-035-eh-warnings/src/test_exc.adb | 17 + .../M724-035-eh-warnings/src/test_glob.adb | 16 + .../M724-035-eh-warnings/src/test_loc.adb | 12 + testsuite/tests/M724-035-eh-warnings/test.opt | 2 + testsuite/tests/M724-035-eh-warnings/test.py | 7 + .../tests/M726-018-trace-exec-check/bar.adb | 31 + .../tests/M726-018-trace-exec-check/foo.adb | 14 + .../tests/M726-018-trace-exec-check/test.opt | 1 + .../tests/M726-018-trace-exec-check/test.py | 87 ++ testsuite/tests/MA08-031/src/f.adb | 8 + testsuite/tests/MA08-031/test.opt | 1 + testsuite/tests/MA08-031/test.py | 10 + .../decision/StaticInline/src/assert.adb | 7 + .../decision/StaticInline/src/counters.adb | 7 + .../decision/StaticInline/src/counters.ads | 6 + .../decision/StaticInline/src/falseonly.adb | 21 + .../StaticInline/src/test_falseonly.adb | 17 + .../StaticInline/src/test_truefalse.adb | 11 + .../StaticInline/src/test_trueonly.adb | 17 + .../decision/StaticInline/src/truefalse.adb | 22 + .../decision/StaticInline/src/trueonly.adb | 21 + .../decision/StaticInline/test.opt | 1 + .../decision/StaticInline/test.py | 7 + .../tests/MB05-039-not-coverable/extra.opt | 1 + .../MB05-039-not-coverable/src/state.adb | 10 + .../MB05-039-not-coverable/src/state.ads | 15 + .../stmt/Generics/src/check_local_nrnf.adb | 15 + .../stmt/Generics/src/check_local_nrpf.adb | 15 + .../stmt/Generics/src/check_local_prnf.adb | 16 + .../stmt/Generics/src/check_local_prpf.adb | 15 + .../stmt/Generics/src/test_local_nrnf.adb | 19 + .../stmt/Generics/src/test_local_nrpf.adb | 19 + .../stmt/Generics/src/test_local_prnf.adb | 20 + .../stmt/Generics/src/test_local_prpf.adb | 20 + .../stmt/Generics/src/test_values_mrmf.adb | 16 + .../stmt/Generics/src/test_values_nrnf.adb | 19 + .../stmt/Generics/src/test_values_nrpf.adb | 19 + .../stmt/Generics/src/test_values_prnf.adb | 18 + .../stmt/Generics/src/test_values_prpf.adb | 18 + .../stmt/Generics/src/values.adb | 32 + .../stmt/Generics/src/values.ads | 7 + .../stmt/Generics/src/values_mrmf.adb | 26 + .../stmt/Generics/src/values_mrmf.ads | 8 + .../stmt/Generics/src/values_nrnf.adb | 18 + .../stmt/Generics/src/values_nrnf.ads | 4 + .../stmt/Generics/src/values_nrpf.adb | 18 + .../stmt/Generics/src/values_nrpf.ads | 4 + .../stmt/Generics/src/values_prnf.adb | 18 + .../stmt/Generics/src/values_prnf.ads | 8 + .../stmt/Generics/src/values_prpf.adb | 18 + .../stmt/Generics/src/values_prpf.ads | 8 + .../stmt/Generics/test.py | 7 + .../stmt/HandlerElim/src/test_values.adb | 18 + .../stmt/HandlerElim/src/values.adb | 42 + .../stmt/HandlerElim/src/values.ads | 9 + .../stmt/HandlerElim/test.opt | 3 + .../stmt/HandlerElim/test.py | 7 + .../stmt/StaticGuard/src/ifs.adb | 133 ++ .../stmt/StaticGuard/src/ifs.ads | 20 + .../stmt/StaticGuard/src/test_ifs.adb | 46 + .../stmt/StaticGuard/test.py | 7 + .../stmt/SubprogElim/src/misc.adb | 50 + .../stmt/SubprogElim/src/misc.ads | 5 + .../stmt/SubprogElim/src/test_misc.adb | 20 + .../stmt/SubprogElim/tc.rst | 12 + .../stmt/SubprogElim/test.py | 7 + .../stmt/Unreachable/src/test_values.adb | 13 + .../stmt/Unreachable/src/values.adb | 19 + .../stmt/Unreachable/src/values.ads | 6 + .../stmt/Unreachable/test.py | 7 + .../tests/MB15-040-if-cst/src/monitor.adb | 14 + .../tests/MB15-040-if-cst/src/monitor.ads | 7 + .../MB15-040-if-cst/src/test_ifcst_call.adb | 11 + .../MB15-040-if-cst/src/test_ifcst_none.adb | 10 + testsuite/tests/MB15-040-if-cst/test.opt | 4 + testsuite/tests/MB15-040-if-cst/test.py | 7 + .../tests/MB15-041-verbose-open-crc32/foo.adb | 4 + .../MB15-041-verbose-open-crc32/test.opt | 1 + .../tests/MB15-041-verbose-open-crc32/test.py | 112 ++ .../tests/MB19-016-subprogram-less-code/foo.c | 5 + .../MB19-016-subprogram-less-code/test.opt | 1 + .../MB19-016-subprogram-less-code/test.py | 49 + .../tests/MC05-011-ref-executable/src/app.adb | 6 + .../MC05-011-ref-executable/src/assert.adb | 6 + .../MC05-011-ref-executable/src/bump.adb | 4 + .../MC05-011-ref-executable/src/double.adb | 5 + .../MC05-011-ref-executable/src/test_bump.adb | 8 + .../tests/MC05-011-ref-executable/test.py | 46 + .../tests/N106-020-tempfiles/src/actions.adb | 33 + .../tests/N106-020-tempfiles/src/actions.ads | 12 + .../N106-020-tempfiles/src/test_tags.adb | 29 + testsuite/tests/N106-020-tempfiles/test.py | 7 + testsuite/tests/N107-020-dhtml/foo.adb | 14 + testsuite/tests/N107-020-dhtml/test.py | 42 + .../tests/N107-029-crc32-validity/foo.adb | 14 + .../tests/N107-029-crc32-validity/test.opt | 1 + .../tests/N107-029-crc32-validity/test.py | 57 + .../N129-008-c-constant-conditions/src/foo.c | 10 + .../N129-008-c-constant-conditions/src/foo.h | 6 + .../src/test_foo.c | 31 + .../N129-008-c-constant-conditions/test.opt | 3 + .../N129-008-c-constant-conditions/test.py | 8 + .../N203-040-same-c-basename/src/a/foo.h | 8 + .../N203-040-same-c-basename/src/b/foo.h | 8 + .../N203-040-same-c-basename/src/test_foo.c | 24 + .../tests/N203-040-same-c-basename/test.opt | 3 + .../tests/N203-040-same-c-basename/test.py | 54 + .../N204-011-precond-aspects/src/foo.adb | 8 + .../N204-011-precond-aspects/src/foo.ads | 11 + .../N204-011-precond-aspects/src/log.adb | 5 + .../N204-011-precond-aspects/src/test_foo.adb | 12 + .../tests/N204-011-precond-aspects/test.opt | 4 + .../tests/N204-011-precond-aspects/test.py | 11 + testsuite/tests/N321-039-disas-wrapping/foo.s | 6 + .../tests/N321-039-disas-wrapping/test.opt | 3 + .../tests/N321-039-disas-wrapping/test.py | 38 + .../N321-045-ppc-disas-large-input/foo.adb | 14 + .../N321-045-ppc-disas-large-input/test.opt | 2 + .../N321-045-ppc-disas-large-input/test.py | 18 + .../N411-046-asm-consolidation/p-default.s | 8 + .../N411-046-asm-consolidation/p-win32.s | 11 + .../N411-046-asm-consolidation/p-win64.s | 11 + .../tests/N411-046-asm-consolidation/test.c | 8 + .../tests/N411-046-asm-consolidation/test.opt | 4 + .../tests/N411-046-asm-consolidation/test.py | 39 + .../src/assert.adb | 6 + .../src/pck-check.adb | 12 + .../N423-015-exempt-in-separate/src/pck.adb | 3 + .../N423-015-exempt-in-separate/src/pck.ads | 4 + .../src/test_i.adb | 14 + .../src/test_v.adb | 15 + .../N423-015-exempt-in-separate/test.opt | 3 + .../tests/N423-015-exempt-in-separate/test.py | 6 + .../ToMultiStmts/src/test_assert.c | 16 + .../N429-018-c-assert/ToMultiStmts/test.opt | 3 + .../N429-018-c-assert/ToMultiStmts/test.py | 11 + .../ToSingleStmt/src/test_assert.c | 15 + .../N429-018-c-assert/ToSingleStmt/test.opt | 2 + .../N429-018-c-assert/ToSingleStmt/test.py | 11 + .../tests/N429-018-c-tern-folding/src/foo.c | 11 + .../tests/N429-018-c-tern-folding/src/foo.h | 6 + .../N429-018-c-tern-folding/src/test_foo_ft.c | 17 + .../N429-018-c-tern-folding/src/test_foo_t.c | 20 + .../tests/N429-018-c-tern-folding/test.opt | 1 + .../tests/N429-018-c-tern-folding/test.py | 13 + .../tests/N429-018-c-void-ternary/src/foo.c | 16 + .../tests/N429-018-c-void-ternary/src/foo.h | 6 + .../N429-018-c-void-ternary/src/helpers.c | 9 + .../N429-018-c-void-ternary/src/helpers.h | 9 + .../N429-018-c-void-ternary/src/test_foo_0.c | 18 + .../N429-018-c-void-ternary/src/test_foo_f.c | 16 + .../N429-018-c-void-ternary/src/test_foo_t.c | 16 + .../N429-018-c-void-ternary/src/test_foo_tf.c | 17 + .../tests/N429-018-c-void-ternary/test.opt | 4 + .../tests/N429-018-c-void-ternary/test.py | 7 + .../tests/N429-020-loop-on-line-ada/foo.adb | 24 + .../tests/N429-020-loop-on-line-ada/test.opt | 1 + .../tests/N429-020-loop-on-line-ada/test.py | 10 + testsuite/tests/N429-020-loop-on-line/main.c | 19 + .../tests/N429-020-loop-on-line/test.opt | 2 + testsuite/tests/N429-020-loop-on-line/test.py | 10 + .../tests/N430-005-c-static-inline/extra.opt | 2 + .../supported/src/bar_false.c | 9 + .../supported/src/bar_true.c | 9 + .../supported/src/foo.c | 22 + .../supported/src/foo.h | 22 + .../supported/src/test_foo_0.c | 27 + .../supported/src/test_foo_f.c | 24 + .../supported/src/test_foo_t.c | 24 + .../supported/src/test_foo_tf.c | 22 + .../supported/test.py | 13 + .../unsupported/src/foo.c | 15 + .../unsupported/src/foo.h | 2 + .../unsupported/src/test_foo.c | 10 + .../unsupported/test.py | 57 + .../N505-008-c99-main-return/src/test_main.c | 7 + .../tests/N505-008-c99-main-return/test.opt | 2 + .../tests/N505-008-c99-main-return/test.py | 7 + .../N505-026-multstmtln-nocode/src/helper.c | 5 + .../N505-026-multstmtln-nocode/src/helper.h | 1 + .../N505-026-multstmtln-nocode/src/test_foo.c | 18 + .../tests/N505-026-multstmtln-nocode/test.opt | 4 + .../tests/N505-026-multstmtln-nocode/test.py | 8 + .../src/abort_or_exit.c | 19 + .../src/abort_or_exit.h | 1 + .../src/test_stop.c | 29 + .../N506-014-crash-on-padding-nop/test.opt | 3 + .../N506-014-crash-on-padding-nop/test.py | 10 + .../N513-004-dom-info-c-tern/src/test_main.c | 15 + .../tests/N513-004-dom-info-c-tern/test.opt | 4 + .../tests/N513-004-dom-info-c-tern/test.py | 7 + .../src/hello.adb | 42 + .../src/hello.ads | 3 + .../src/test_casual_nobody.adb | 15 + .../src/test_casual_someone.adb | 15 + .../src/test_formal_nobody.adb | 15 + .../src/test_formal_someone.adb | 15 + .../N521-029-dc-dynstack-twoways/test.opt | 3 + .../N521-029-dc-dynstack-twoways/test.py | 11 + testsuite/tests/N610-006-library/libops.gpr | 11 + .../tests/N610-006-library/libops/inc.adb | 4 + .../tests/N610-006-library/libops/mult.adb | 4 + testsuite/tests/N610-006-library/test.py | 74 ++ testsuite/tests/N610-006-library/test_inc.adb | 7 + .../tests/N610-006-library/test_mult.adb | 7 + testsuite/tests/N630-009-forward_p_x/foo.adb | 6 + testsuite/tests/N630-009-forward_p_x/test.opt | 1 + testsuite/tests/N630-009-forward_p_x/test.py | 32 + .../tests/NA29-019-unit-filters-for-C/abs.c | 8 + .../NA29-019-unit-filters-for-C/test.opt | 0 .../tests/NA29-019-unit-filters-for-C/test.py | 91 ++ .../NA29-019-unit-filters-for-C/test_abs.c | 15 + .../tests/NB07-026-header-shadow/src/box.h | 7 + .../tests/NB07-026-header-shadow/src/m1.c | 13 + .../tests/NB07-026-header-shadow/src/m2.c | 13 + .../NB07-026-header-shadow/src/test_main.c | 24 + .../tests/NB07-026-header-shadow/test.opt | 3 + .../tests/NB07-026-header-shadow/test.py | 7 + testsuite/tests/NC02-014-gpr-X/main.adb | 6 + testsuite/tests/NC02-014-gpr-X/test.py | 75 ++ testsuite/tests/NC08-027-target_attr/foo.adb | 6 + testsuite/tests/NC08-027-target_attr/test.opt | 1 + testsuite/tests/NC08-027-target_attr/test.py | 59 + .../tests/O302-015-src-path-in-project/p.gpr | 7 + .../O302-015-src-path-in-project/src/main.adb | 6 + .../src/pkg-hw.adb | 8 + .../src/pkg-hw.ads | 3 + .../src/pkg-io.adb | 6 + .../src/pkg-io.ads | 3 + .../O302-015-src-path-in-project/src/pkg.ads | 3 + .../O302-015-src-path-in-project/test.py | 69 ++ .../tests/O529-021-wrong-elf-class/code-32.o | Bin 0 -> 445 bytes .../tests/O529-021-wrong-elf-class/code-64.o | Bin 0 -> 657 bytes .../tests/O529-021-wrong-elf-class/code.s | 2 + .../tests/O529-021-wrong-elf-class/test.py | 23 + .../O916-035-padding-cons/foo-x86-linux.s | 194 +++ .../O916-035-padding-cons/foo-x86-windows.s | 187 +++ testsuite/tests/O916-035-padding-cons/foo.c | 11 + .../tests/O916-035-padding-cons/test.opt | 1 + testsuite/tests/O916-035-padding-cons/test.py | 197 +++ .../tests/OA05-051-sharedobjs-opt/foo.adb | 4 + .../tests/OA05-051-sharedobjs-opt/test.opt | 2 + .../tests/OA05-051-sharedobjs-opt/test.py | 48 + .../tests/OA05-051-sharedobjs/mylib1.gpr | 10 + .../tests/OA05-051-sharedobjs/mylib2.gpr | 10 + .../tests/OA05-051-sharedobjs/myprog.gpr | 11 + .../OA05-051-sharedobjs/src-mylib1/mylib1.adb | 8 + .../OA05-051-sharedobjs/src-mylib1/mylib1.ads | 5 + .../OA05-051-sharedobjs/src-mylib2/mylib2.adb | 8 + .../OA05-051-sharedobjs/src-mylib2/mylib2.ads | 5 + .../OA05-051-sharedobjs/src-myprog/myprog.adb | 13 + testsuite/tests/OA05-051-sharedobjs/test.opt | 2 + testsuite/tests/OA05-051-sharedobjs/test.py | 211 ++++ .../tests/OA16-009-exec-prefix/prj1/foo.adb | 8 + .../tests/OA16-009-exec-prefix/prj1/pkg.adb | 6 + .../tests/OA16-009-exec-prefix/prj1/pkg.ads | 3 + .../tests/OA16-009-exec-prefix/prj2/foo.adb | 10 + .../tests/OA16-009-exec-prefix/prj2/pkg.adb | 6 + .../tests/OA16-009-exec-prefix/prj2/pkg.ads | 3 + testsuite/tests/OA16-009-exec-prefix/test.opt | 1 + testsuite/tests/OA16-009-exec-prefix/test.py | 60 + .../tests/OA16-009-windows-suffix/foo.adb | 4 + .../tests/OA16-009-windows-suffix/test.opt | 2 + .../tests/OA16-009-windows-suffix/test.py | 30 + .../OA27-059-inlined-separate-cons/.gitignore | 5 + .../OA27-059-inlined-separate-cons/pkg.gpr | 5 + .../src/helpers.adb | 8 + .../src/helpers.ads | 3 + .../src/pkg-test_driver.adb | 5 + .../src/pkg.adb | 14 + .../src/pkg.ads | 4 + .../OA27-059-inlined-separate-cons/test.py | 111 ++ .../OA27-059-inlined-separate-cons/test1.gpr | 7 + .../test1/main_test1.adb | 6 + .../test1/pkg-test_driver.adb | 10 + .../OA27-059-inlined-separate-cons/test2.gpr | 7 + .../test2/main_test2.adb | 6 + .../test2/pkg-test_driver.adb | 13 + .../OA27-059-sep-cons-prj-override/.gitignore | 5 + .../pkg_under_test.gpr | 16 + .../pkg_under_test-pkg_test.adb | 6 + .../pkg_under_test-some_procedure.adb | 6 + .../src_under_test/pkg_under_test.adb | 17 + .../src_under_test/pkg_under_test.ads | 6 + .../OA27-059-sep-cons-prj-override/test.py | 119 ++ .../OA27-059-sep-cons-prj-override/test1.gpr | 8 + .../test1/main_test1.adb | 8 + .../test1/pkg_under_test-pkg_test.adb | 10 + .../OA27-059-sep-cons-prj-override/test2.gpr | 8 + .../test2/main_test2.adb | 8 + .../test2/pkg_under_test-pkg_test.adb | 9 + .../tests/OA27-059-sep-cons-prj/.gitignore | 5 + .../OA27-059-sep-cons-prj/pkg_under_test.gpr | 16 + .../pkg_under_test-pkg_test.adb | 6 + .../src_under_test/pkg_under_test.adb | 17 + .../src_under_test/pkg_under_test.ads | 5 + testsuite/tests/OA27-059-sep-cons-prj/test.py | 95 ++ .../tests/OA27-059-sep-cons-prj/test1.gpr | 8 + .../test1/main_test1.adb | 8 + .../test1/pkg_under_test-pkg_test.adb | 10 + .../tests/OA27-059-sep-cons-prj/test2.gpr | 8 + .../test2/main_test2.adb | 8 + .../test2/pkg_under_test-pkg_test.adb | 9 + .../pkg_under_test.gpr | 8 + .../src_under_test/pkg_under_test.adb | 17 + .../src_under_test/pkg_under_test.ads | 5 + .../OA27-059-separate-consolidation/test.opt | 1 + .../OA27-059-separate-consolidation/test.py | 105 ++ .../OA27-059-separate-consolidation/test1.gpr | 10 + .../test1/main_test1.adb | 8 + .../test1/pkg_under_test-pkg_test.adb | 10 + .../OA27-059-separate-consolidation/test2.gpr | 10 + .../test2/main_test2.adb | 8 + .../test2/pkg_under_test-pkg_test.adb | 9 + testsuite/tests/OB23-036/foo.adb | 4 + testsuite/tests/OB23-036/test.py | 28 + .../Aspects/src/tcheck.ads | 38 + .../Aspects/src/tnocheck.ads | 26 + .../OB26-040-type-invariants/Aspects/test.opt | 1 + .../OB26-040-type-invariants/Aspects/test.py | 7 + .../InvariantClass/src/test_t.adb | 19 + .../InvariantClass/src/types_a.adb | 8 + .../InvariantClass/src/types_a.ads | 41 + .../InvariantClass/test.opt | 1 + .../InvariantClass/test.py | 7 + .../Pragmas/src/tcheck.ads | 40 + .../Pragmas/src/tnocheck.ads | 26 + .../OB26-040-type-invariants/Pragmas/test.opt | 1 + .../OB26-040-type-invariants/Pragmas/test.py | 7 + .../tests/OB26-040-type-invariants/extra.opt | 1 + .../src/test_tcheck_t.adb | 20 + .../src/test_tnocheck_t.adb | 22 + testsuite/tests/P505-032-path-spaces/foo.adb | 5 + testsuite/tests/P505-032-path-spaces/test.opt | 1 + testsuite/tests/P505-032-path-spaces/test.py | 30 + .../P526-035-origin-project/src-p1/p1.adb | 12 + .../P526-035-origin-project/src-p1/p1.ads | 5 + .../P526-035-origin-project/src-p2/p2.adb | 7 + .../tests/P526-035-origin-project/test.opt | 1 + .../tests/P526-035-origin-project/test.py | 76 ++ .../src/cons_maps_math.txt | 37 + .../P614-002-incidental-coverage/src/maps.adb | 14 + .../P614-002-incidental-coverage/src/maps.ads | 7 + .../P614-002-incidental-coverage/src/math.adb | 23 + .../P614-002-incidental-coverage/src/math.ads | 6 + .../src/test_add.adb | 14 + .../src/test_area.adb | 16 + .../P614-002-incidental-coverage/test.py | 7 + .../src/characterize.adb | 13 + .../P622-010-stack-restore/src/test_0.adb | 14 + .../P622-010-stack-restore/src/test_n.adb | 15 + .../P622-010-stack-restore/src/test_p.adb | 14 + .../P622-010-stack-restore/src/test_z.adb | 14 + .../tests/P622-010-stack-restore/test.py | 7 + .../tests/P907-005-ckpt-covlevel/src/math.adb | 23 + .../tests/P907-005-ckpt-covlevel/src/math.ads | 4 + .../P907-005-ckpt-covlevel/src/test_add.adb | 7 + .../P907-005-ckpt-covlevel/src/test_mult.adb | 7 + .../tests/P907-005-ckpt-covlevel/test.py | 79 ++ .../tests/P907-005-incremental/src/math.adb | 23 + .../tests/P907-005-incremental/src/math.ads | 4 + .../P907-005-incremental/src/test_add.adb | 7 + .../P907-005-incremental/src/test_mult.adb | 7 + testsuite/tests/P907-005-incremental/test.py | 50 + .../P907-005-stubbing-generic/.gitignore | 2 + .../P907-005-stubbing-generic/common.gpr | 5 + .../sensors/int_control.ads | 7 + .../sensors/pressure_control.adb | 22 + .../sensors/pressure_control.ads | 5 + .../sensors/sensors.gpr | 3 + .../sensors/temperature_control.adb | 22 + .../sensors/temperature_control.ads | 5 + .../stub_pressure/pressure_control.adb | 6 + .../stub_temperature/temperature_control.adb | 6 + .../tests/P907-005-stubbing-generic/test.py | 74 ++ .../test_p/test_runner.gpr | 12 + .../P907-005-stubbing-generic/test_p/tp1.adb | 10 + .../test_sensors/test_runner.gpr | 12 + .../test_sensors/ts1.adb | 10 + .../test_t/test_runner.gpr | 12 + .../P907-005-stubbing-generic/test_t/tt1.adb | 10 + testsuite/tests/P907-005-stubbing/.gitignore | 2 + testsuite/tests/P907-005-stubbing/common.gpr | 5 + .../sensors/pressure_control.adb | 22 + .../sensors/pressure_control.ads | 3 + .../P907-005-stubbing/sensors/sensors.gpr | 3 + .../sensors/temperature_control.adb | 22 + .../sensors/temperature_control.ads | 3 + .../stub_pressure/pressure_control.adb | 6 + .../stub_temperature/temperature_control.adb | 6 + testsuite/tests/P907-005-stubbing/test.py | 73 ++ .../P907-005-stubbing/test_p/test_runner.gpr | 12 + .../tests/P907-005-stubbing/test_p/tp1.adb | 11 + .../test_sensors/test_runner.gpr | 12 + .../P907-005-stubbing/test_sensors/ts1.adb | 11 + .../P907-005-stubbing/test_t/test_runner.gpr | 12 + .../tests/P907-005-stubbing/test_t/tt1.adb | 11 + .../tests/P913-011-invalid-project/foo.adb | 6 + .../tests/P913-011-invalid-project/test.py | 35 + .../AB_C/src/p1.adb | 16 + .../AB_C/src/p1.ads | 15 + .../AB_C/src/test_1.adb | 14 + .../AB_C/src/test_14.adb | 14 + .../AB_C/src/test_2.adb | 12 + .../AB_C/src/test_3.adb | 14 + .../AB_C/src/test_4.adb | 14 + .../AB_C/src/test_5.adb | 12 + .../PA25-046-inlined-in-decision/AB_C/test.py | 6 + .../A_BC_D/src/p1.adb | 13 + .../A_BC_D/src/p1.ads | 18 + .../A_BC_D/src/test_1.adb | 16 + .../A_BC_D/src/test_1346.adb | 18 + .../A_BC_D/src/test_2.adb | 14 + .../A_BC_D/src/test_3.adb | 12 + .../A_BC_D/src/test_346.adb | 16 + .../A_BC_D/src/test_36.adb | 13 + .../A_BC_D/src/test_4.adb | 12 + .../A_BC_D/src/test_46.adb | 15 + .../A_BC_D/src/test_5.adb | 14 + .../A_BC_D/src/test_6.adb | 12 + .../A_BC_D/test.py | 7 + .../A_B_C/src/p1.adb | 10 + .../A_B_C/src/p1.ads | 13 + .../A_B_C/src/test_1.adb | 10 + .../A_B_C/src/test_12.adb | 10 + .../A_B_C/src/test_123.adb | 11 + .../A_B_C/src/test_1234.adb | 12 + .../A_B_C/src/test_124.adb | 11 + .../A_B_C/src/test_13.adb | 10 + .../A_B_C/src/test_134.adb | 11 + .../A_B_C/src/test_14.adb | 10 + .../A_B_C/src/test_2.adb | 10 + .../A_B_C/src/test_3.adb | 11 + .../A_B_C/src/test_4.adb | 11 + .../A_B_C/test.py | 7 + .../C_X/src/p2.adb | 15 + .../C_X/src/p2.ads | 11 + .../C_X/src/test_0.adb | 11 + .../C_X/src/test_1.adb | 12 + .../C_X/src/test_12.adb | 14 + .../C_X/src/test_123.adb | 18 + .../C_X/src/test_13.adb | 16 + .../C_X/src/test_2.adb | 12 + .../C_X/src/test_23.adb | 16 + .../C_X/src/test_3.adb | 13 + .../PA25-046-inlined-in-decision/C_X/test.py | 6 + .../PA25-046-inlined-in-decision/extra.opt | 1 + .../src/twisters.adb | 11 + .../src/twisters.ads | 9 + .../src-sub/sub_main.adb | 4 + .../PC09-022-auto-exename/src/main_proc.adb | 4 + .../PC09-022-auto-exename/src/other_proc.adb | 4 + .../tests/PC09-022-auto-exename/test.opt | 1 + testsuite/tests/PC09-022-auto-exename/test.py | 167 +++ .../src/ops-p1.adb | 6 + .../src/ops-p1.ads | 3 + .../src/ops.ads | 3 + .../src/test_p1.adb | 13 + .../test.py | 7 + .../tests/Q224-032-several-out-of-line/bar.c | 5 + .../Q224-032-several-out-of-line/foo.cpp | 7 + .../Q224-032-several-out-of-line/main.cpp | 16 + .../Q224-032-several-out-of-line/shared.hpp | 7 + .../Q224-032-several-out-of-line/test.opt | 2 + .../Q224-032-several-out-of-line/test.py | 29 + .../.gitignore | 2 + .../app/default.gpr | 5 + .../app/main.adb | 7 + .../libfoo/lib.adb | 12 + .../libfoo/lib.ads | 4 + .../libfoo/libfoo.gpr | 7 + .../Q308-041-crash-on-generic-in-lib/test.opt | 2 + .../Q308-041-crash-on-generic-in-lib/test.py | 51 + .../tests/Q327-016-glob-ignore/ignore.list | 5 + .../tests/Q327-016-glob-ignore/src/main.adb | 8 + .../Q327-016-glob-ignore/src/pkg_a-test.adb | 6 + .../tests/Q327-016-glob-ignore/src/pkg_a.adb | 8 + .../tests/Q327-016-glob-ignore/src/pkg_a.ads | 3 + .../Q327-016-glob-ignore/src/pkg_b-test.adb | 6 + .../tests/Q327-016-glob-ignore/src/pkg_b.adb | 8 + .../tests/Q327-016-glob-ignore/src/pkg_b.ads | 3 + .../Q327-016-glob-ignore/src/pkg_c-test.adb | 6 + .../tests/Q327-016-glob-ignore/src/pkg_c.adb | 8 + .../tests/Q327-016-glob-ignore/src/pkg_c.ads | 3 + testsuite/tests/Q327-016-glob-ignore/test.py | 33 + .../tests/Q329-018-create-output-dir/foo.adb | 6 + .../tests/Q329-018-create-output-dir/test.py | 35 + .../tests/Q414-016-task-accept/src/q.adb | 37 + .../tests/Q414-016-task-accept/src/q.ads | 3 + .../Q414-016-task-accept/src/test_tick.adb | 13 + testsuite/tests/Q414-016-task-accept/test.opt | 2 + testsuite/tests/Q414-016-task-accept/test.py | 5 + testsuite/tests/Q519-013-decision-map/bar.adb | 6 + testsuite/tests/Q519-013-decision-map/bar.ads | 3 + testsuite/tests/Q519-013-decision-map/foo.adb | 7 + .../tests/Q519-013-decision-map/test.opt | 1 + testsuite/tests/Q519-013-decision-map/test.py | 36 + .../tests/Q614-037-ckpt-pkg-renames/bar.ads | 3 + .../tests/Q614-037-ckpt-pkg-renames/foo.adb | 6 + .../tests/Q614-037-ckpt-pkg-renames/foo.ads | 3 + .../tests/Q614-037-ckpt-pkg-renames/main.adb | 6 + .../tests/Q614-037-ckpt-pkg-renames/test.py | 33 + testsuite/tests/Q901-012-report-title/foo.adb | 4 + testsuite/tests/Q901-012-report-title/test.py | 48 + testsuite/tests/Q905-005-compressed/foo.adb | 14 + testsuite/tests/Q905-005-compressed/test.opt | 2 + testsuite/tests/Q905-005-compressed/test.py | 24 + .../tests/QA23-039-nocode-pragmas/p1.ads | 3 + .../tests/QA23-039-nocode-pragmas/p2.ads | 4 + .../tests/QA23-039-nocode-pragmas/p3.ads | 5 + .../tests/QA23-039-nocode-pragmas/test.py | 54 + .../tests/QA23-039-nocode-pragmas/test_p1.adb | 7 + .../tests/QA23-039-nocode-pragmas/test_p2.adb | 6 + .../tests/QA23-039-nocode-pragmas/test_p3.adb | 5 + .../tests/QA27-024-prepare-target/foo.adb | 4 + .../tests/QA27-024-prepare-target/test.py | 93 ++ .../tests/QB14-023-stack-overflow/foo.adb | 4 + .../tests/QB14-023-stack-overflow/test.py | 23 + testsuite/tests/R404-023-object-stats/main | Bin 0 -> 138672 bytes .../tests/R404-023-object-stats/main.adb | 9 + .../R404-023-object-stats/main.trace.asset | Bin 0 -> 816 bytes testsuite/tests/R404-023-object-stats/p.gpr | 15 + testsuite/tests/R404-023-object-stats/pkg.adb | 30 + testsuite/tests/R404-023-object-stats/pkg.ads | 5 + .../tests/R404-023-object-stats/routines.txt | 3 + .../tests/R404-023-object-stats/test.opt | 1 + testsuite/tests/R404-023-object-stats/test.py | 35 + .../main.adb.xml.expected | 1096 +++++++++++++++++ .../tests/R417-010-scope-metrics/src/main.adb | 74 ++ .../tests/R417-010-scope-metrics/test.opt | 4 + .../tests/R417-010-scope-metrics/test.py | 28 + .../src1/foo.adb | 6 + .../src2/foo.adb | 7 + .../R420-002-aggregate-project-file/test.opt | 2 + .../R420-002-aggregate-project-file/test.py | 55 + .../tests/R507-014-trailing-byte-insn/f.s | 34 + .../tests/R507-014-trailing-byte-insn/main.c | 10 + .../R507-014-trailing-byte-insn/test.opt | 3 + .../tests/R507-014-trailing-byte-insn/test.py | 61 + .../bin-traces-index.xml.expected | 149 +++ testsuite/tests/R507-027-xml-summary/data.ads | 3 + testsuite/tests/R507-027-xml-summary/main.adb | 9 + testsuite/tests/R507-027-xml-summary/pkg.adb | 23 + testsuite/tests/R507-027-xml-summary/pkg.ads | 4 + .../src-traces-index.xml.expected | 149 +++ testsuite/tests/R507-027-xml-summary/test.opt | 1 + testsuite/tests/R507-027-xml-summary/test.py | 34 + .../tests/R521-002-profile-arcs/main.adb | 8 + .../tests/R521-002-profile-arcs/test.opt | 4 + testsuite/tests/R521-002-profile-arcs/test.py | 31 + testsuite/tests/R521-002-profile-arcs/util.c | 7 + testsuite/tests/R807-027-symbol-order/p.adb | 7 + testsuite/tests/R807-027-symbol-order/pkg.adb | 6 + testsuite/tests/R807-027-symbol-order/pkg.ads | 6 + .../tests/R807-027-symbol-order/test.opt | 2 + testsuite/tests/R807-027-symbol-order/test.py | 51 + testsuite/tests/RB13-019-win-paths/.gitignore | 9 + testsuite/tests/RB13-019-win-paths/Makefile | 12 + testsuite/tests/RB13-019-win-paths/driver.c | 26 + testsuite/tests/RB13-019-win-paths/test.opt | 2 + testsuite/tests/RB13-019-win-paths/test.py | 41 + testsuite/tests/RB13-019-win-paths/wibble.c | 14 + testsuite/tests/RB13-019-win-paths/wibble.h | 6 + testsuite/tests/RB16-008-gpr-tool/main.adb | 8 + testsuite/tests/RB16-008-gpr-tool/test.py | 78 ++ .../tests/RB16-008-gpr-tool/unit_env_var.adb | 6 + .../RB16-008-gpr-tool/unit_gnatcoverage.adb | 6 + .../tests/RB16-008-gpr-tool/unit_x_arg.adb | 6 + testsuite/tests/RC04-030-bad-trace/.gitignore | 7 + testsuite/tests/RC04-030-bad-trace/main_a.adb | 6 + testsuite/tests/RC04-030-bad-trace/main_b.adb | 6 + testsuite/tests/RC04-030-bad-trace/main_c.adb | 6 + testsuite/tests/RC04-030-bad-trace/pkg.adb | 22 + testsuite/tests/RC04-030-bad-trace/pkg.ads | 3 + testsuite/tests/RC04-030-bad-trace/test.opt | 1 + testsuite/tests/RC04-030-bad-trace/test.py | 106 ++ .../Explicit/src/raise_exception.adb | 10 + .../stmt/ExceptionHandler/Explicit/test.opt | 3 + .../stmt/ExceptionHandler/Explicit/test.py | 6 + .../Implicit/src/raise_exception.adb | 12 + .../stmt/ExceptionHandler/Implicit/test.opt | 3 + .../stmt/ExceptionHandler/Implicit/test.py | 6 + .../ReRaise/src/raise_exception.adb | 11 + .../stmt/ExceptionHandler/ReRaise/test.opt | 3 + .../stmt/ExceptionHandler/ReRaise/test.py | 6 + .../stmt/ExceptionHandler/notes.txt | 9 + .../ExceptionHandler/src/handle_exception.adb | 12 + .../ExceptionHandler/src/handle_exception.ads | 1 + .../stmt/ExceptionHandler/src/p.ads | 7 + .../ExceptionHandler/src/raise_exception.ads | 1 + .../src/test_raise_exception.adb | 20 + .../Local/NestedBlock1/src/elab.adb | 31 + .../PackageElab/Local/NestedBlock1/test.opt | 3 + .../PackageElab/Local/NestedBlock1/test.py | 6 + .../Local/NestedBlock2/src/elab.adb | 33 + .../PackageElab/Local/NestedBlock2/test.opt | 3 + .../PackageElab/Local/NestedBlock2/test.py | 6 + .../Local/SimpleBlock/src/elab.adb | 25 + .../PackageElab/Local/SimpleBlock/test.opt | 3 + .../PackageElab/Local/SimpleBlock/test.py | 6 + .../Local/src/test_elab_no_calls.adb | 27 + .../Local/src/test_elab_no_raise.adb | 31 + .../PackageElab/Local/src/test_elab_raise.adb | 31 + .../LibUnit/Predefined/src/elab.adb | 26 + .../LibUnit/Predefined/src/subp.adb | 13 + .../LibUnit/Predefined/src/subp.ads | 5 + .../Predefined/src/test_elab_exp_raise.adb | 26 + .../Predefined/src/test_elab_imp_raise.adb | 28 + .../Predefined/src/test_elab_no_calls.adb | 23 + .../Predefined/src/test_elab_no_raise.adb | 26 + .../Propagated/LibUnit/Predefined/test.opt | 3 + .../Propagated/LibUnit/Predefined/test.py | 6 + .../LibUnit/UserDefined/src/elab.adb | 29 + .../LibUnit/UserDefined/src/subp.adb | 13 + .../LibUnit/UserDefined/src/subp.ads | 7 + .../UserDefined/src/test_elab_exp_raise.adb | 25 + .../UserDefined/src/test_elab_no_calls.adb | 25 + .../UserDefined/src/test_elab_no_raise.adb | 25 + .../Propagated/LibUnit/UserDefined/test.opt | 3 + .../Propagated/LibUnit/UserDefined/test.py | 6 + .../NestedProc/Predefined/src/elab.adb | 36 + .../Predefined/src/test_elab_exp_raise.adb | 24 + .../Predefined/src/test_elab_imp_raise.adb | 27 + .../Predefined/src/test_elab_no_calls.adb | 23 + .../Predefined/src/test_elab_no_raise.adb | 25 + .../Propagated/NestedProc/Predefined/test.opt | 3 + .../Propagated/NestedProc/Predefined/test.py | 6 + .../NestedProc/UserDefined/src/elab.adb | 40 + .../UserDefined/src/test_elab_exp_raise.adb | 25 + .../UserDefined/src/test_elab_no_calls.adb | 32 + .../UserDefined/src/test_elab_no_raise.adb | 31 + .../NestedProc/UserDefined/test.opt | 3 + .../Propagated/NestedProc/UserDefined/test.py | 6 + .../Exceptions/stmt/PackageElab/notes.txt | 14 + .../stmt/PackageElab/src/global.ads | 4 + .../LocallyHandled/ExplicitRaise/src/div.adb | 17 + .../ExplicitRaise/src/test_divide_nok.adb | 22 + .../ExplicitRaise/src/test_divide_ok.adb | 22 + .../LocallyHandled/ExplicitRaise/test.opt | 3 + .../LocallyHandled/ExplicitRaise/test.py | 6 + .../LocallyHandled/ImplicitRaise/src/div.adb | 11 + .../ImplicitRaise/src/test_divide_nok.adb | 18 + .../ImplicitRaise/src/test_divide_ok.adb | 18 + .../LocallyHandled/ImplicitRaise/test.opt | 3 + .../LocallyHandled/ImplicitRaise/test.py | 6 + .../Propagated/ExplicitRaise/src/div.adb | 21 + .../ExplicitRaise/src/test_divide_nok.adb | 22 + .../ExplicitRaise/src/test_divide_ok.adb | 22 + .../Propagated/ExplicitRaise/test.opt | 3 + .../Propagated/ExplicitRaise/test.py | 6 + .../Propagated/ImplicitRaise/src/div.adb | 19 + .../ImplicitRaise/src/test_divide_nok.adb | 19 + .../ImplicitRaise/src/test_divide_ok.adb | 19 + .../Propagated/ImplicitRaise/test.opt | 3 + .../Propagated/ImplicitRaise/test.py | 6 + .../Exceptions/stmt/SubProgBody/notes.txt | 11 + .../Exceptions/stmt/SubProgBody/src/div.ads | 14 + .../stmt/example/src/cond_raise.adb | 26 + .../stmt/example/src/cond_raise.ads | 5 + .../stmt/example/src/test_cond_f.adb | 18 + .../stmt/example/src/test_cond_t.adb | 36 + .../Exceptions/stmt/example/test.opt | 3 + .../Ravenscar/Exceptions/stmt/example/test.py | 6 + .../Class_Wide/src/check_class_wide.adb | 25 + .../Core_Example/Class_Wide/src/test_f.adb | 46 + .../Core_Example/Class_Wide/src/test_no.adb | 41 + .../Core_Example/Class_Wide/src/test_t.adb | 46 + .../Core_Example/Class_Wide/src/test_tf.adb | 52 + .../Core_Example/Class_Wide/src/test_tfx.adb | 60 + .../Core_Example/Class_Wide/src/test_x.adb | 47 + .../decision/Core_Example/Class_Wide/tc.txt | 6 + .../decision/Core_Example/Class_Wide/test.opt | 3 + .../decision/Core_Example/Class_Wide/test.py | 6 + .../src/check_class_wide_condition.adb | 35 + .../Class_Wide_Condition/src/test_f.adb | 36 + .../Class_Wide_Condition/src/test_ft.adb | 51 + .../Class_Wide_Condition/src/test_ftx.adb | 46 + .../Class_Wide_Condition/src/test_no.adb | 31 + .../Class_Wide_Condition/src/test_t.adb | 37 + .../Class_Wide_Condition/src/test_x.adb | 36 + .../Core_Example/Class_Wide_Condition/tc.txt | 4 + .../Class_Wide_Condition/test.opt | 3 + .../Core_Example/Class_Wide_Condition/test.py | 6 + .../src/check_dispatching_condition.adb | 35 + .../Dispatching_Condition/src/test_f.adb | 35 + .../Dispatching_Condition/src/test_ft.adb | 49 + .../Dispatching_Condition/src/test_ftx.adb | 45 + .../Dispatching_Condition/src/test_no.adb | 30 + .../Dispatching_Condition/src/test_t.adb | 36 + .../Dispatching_Condition/src/test_x.adb | 35 + .../Core_Example/Dispatching_Condition/tc.txt | 4 + .../Dispatching_Condition/test.opt | 3 + .../Dispatching_Condition/test.py | 6 + .../src/check_dynamic_binding.adb | 27 + .../Dynamic_Binding/src/test_2_f_t.adb | 43 + .../Dynamic_Binding/src/test_2_ftx.adb | 60 + .../Dynamic_Binding/src/test_2_t_ft.adb | 43 + .../Dynamic_Binding/src/test_2_x.adb | 46 + .../Dynamic_Binding/src/test_no.adb | 31 + .../Core_Example/Dynamic_Binding/tc.txt | 6 + .../Core_Example/Dynamic_Binding/test.opt | 3 + .../Core_Example/Dynamic_Binding/test.py | 6 + .../OOP/decision/Core_Example/req.txt | 21 + .../Core_Example/src/parent-child1.adb | 23 + .../Core_Example/src/parent-child1.ads | 8 + .../Core_Example/src/parent-child2.adb | 23 + .../Core_Example/src/parent-child2.ads | 8 + .../OOP/decision/Core_Example/src/parent.adb | 17 + .../OOP/decision/Core_Example/src/parent.ads | 10 + testsuite/tests/Ravenscar/OOP/req.txt | 111 ++ .../Ravenscar/OOP/src/class_wide_ops.adb | 7 + .../Ravenscar/OOP/src/class_wide_ops.ads | 4 + .../OOP/src/new_alert_system-emergency.adb | 42 + .../OOP/src/new_alert_system-emergency.ads | 20 + .../OOP/src/new_alert_system-objects.ads | 15 + .../Ravenscar/OOP/src/new_alert_system.adb | 69 ++ .../Ravenscar/OOP/src/new_alert_system.ads | 49 + .../stmt/Class_Wide_Operations/src/test_1.adb | 40 + .../stmt/Class_Wide_Operations/src/test_2.adb | 40 + .../stmt/Class_Wide_Operations/src/test_3.adb | 40 + .../stmt/Class_Wide_Operations/src/test_4.adb | 42 + .../Class_Wide_Operations/src/test_full.adb | 51 + .../Class_Wide_Operations/src/test_no.adb | 39 + .../OOP/stmt/Class_Wide_Operations/tc.txt | 7 + .../OOP/stmt/Class_Wide_Operations/test.py | 6 + .../OOP/stmt/Dynamic_Binding/src/test_1.adb | 25 + .../OOP/stmt/Dynamic_Binding/src/test_2.adb | 25 + .../OOP/stmt/Dynamic_Binding/src/test_3.adb | 25 + .../OOP/stmt/Dynamic_Binding/src/test_4.adb | 38 + .../Ravenscar/OOP/stmt/Dynamic_Binding/tc.txt | 7 + .../OOP/stmt/Dynamic_Binding/test.py | 6 + .../stmt/Inheritance/src/test_inherited.adb | 28 + .../stmt/Inheritance/src/test_overriding.adb | 30 + .../Ravenscar/OOP/stmt/Inheritance/tc.txt | 12 + .../Ravenscar/OOP/stmt/Inheritance/test.py | 6 + .../OOP/stmt/Multiple_Inheritance/src/a.adb | 10 + .../OOP/stmt/Multiple_Inheritance/src/a.ads | 10 + .../OOP/stmt/Multiple_Inheritance/src/b.adb | 10 + .../OOP/stmt/Multiple_Inheritance/src/b.ads | 10 + .../OOP/stmt/Multiple_Inheritance/src/c.adb | 10 + .../OOP/stmt/Multiple_Inheritance/src/c.ads | 9 + .../stmt/Multiple_Inheritance/src/test_1.adb | 74 ++ .../stmt/Multiple_Inheritance/src/test_10.adb | 74 ++ .../stmt/Multiple_Inheritance/src/test_11.adb | 75 ++ .../stmt/Multiple_Inheritance/src/test_12.adb | 75 ++ .../stmt/Multiple_Inheritance/src/test_2.adb | 74 ++ .../stmt/Multiple_Inheritance/src/test_3.adb | 74 ++ .../stmt/Multiple_Inheritance/src/test_4.adb | 74 ++ .../stmt/Multiple_Inheritance/src/test_5.adb | 75 ++ .../stmt/Multiple_Inheritance/src/test_6.adb | 75 ++ .../stmt/Multiple_Inheritance/src/test_7.adb | 74 ++ .../stmt/Multiple_Inheritance/src/test_8.adb | 74 ++ .../stmt/Multiple_Inheritance/src/test_9.adb | 74 ++ .../Multiple_Inheritance/src/x-a_child.adb | 20 + .../Multiple_Inheritance/src/x-a_child.ads | 12 + .../Multiple_Inheritance/src/x-b_child.adb | 20 + .../Multiple_Inheritance/src/x-b_child.ads | 12 + .../Multiple_Inheritance/src/x-c_child.adb | 18 + .../Multiple_Inheritance/src/x-c_child.ads | 11 + .../OOP/stmt/Multiple_Inheritance/src/x.ads | 6 + .../Multiple_Inheritance/src/y-a_child.adb | 20 + .../Multiple_Inheritance/src/y-a_child.ads | 12 + .../Multiple_Inheritance/src/y-b_child.adb | 20 + .../Multiple_Inheritance/src/y-b_child.ads | 12 + .../Multiple_Inheritance/src/y-c_child.adb | 18 + .../Multiple_Inheritance/src/y-c_child.ads | 11 + .../OOP/stmt/Multiple_Inheritance/src/y.ads | 5 + .../OOP/stmt/Multiple_Inheritance/tc.txt | 7 + .../OOP/stmt/Multiple_Inheritance/test.opt | 4 + .../OOP/stmt/Multiple_Inheritance/test.py | 6 + .../OOP/stmt/Static_Binding/src/test_1.adb | 24 + .../OOP/stmt/Static_Binding/src/test_2.adb | 24 + .../OOP/stmt/Static_Binding/src/test_3.adb | 24 + .../OOP/stmt/Static_Binding/src/test_4.adb | 36 + .../Ravenscar/OOP/stmt/Static_Binding/tc.txt | 7 + .../Ravenscar/OOP/stmt/Static_Binding/test.py | 6 + .../ProtectedOps/decision/src/test_driver.adb | 17 + .../Tasking/ProtectedOps/decision/test.opt | 3 + .../Tasking/ProtectedOps/decision/test.py | 6 + .../ProtectedOps/src/synchronization.adb | 31 + .../ProtectedOps/src/synchronization.ads | 24 + .../ProtectedOps/stmt/src/test_driver.adb | 17 + .../Tasking/ProtectedOps/stmt/test.opt | 3 + .../Tasking/ProtectedOps/stmt/test.py | 6 + .../decision/src/test_driver.adb | 19 + .../SuspensionObjects/decision/test.opt | 3 + .../SuspensionObjects/decision/test.py | 6 + .../SuspensionObjects/src/synchronization.adb | 27 + .../SuspensionObjects/src/synchronization.ads | 21 + .../stmt/src/test_driver.adb | 19 + .../Tasking/SuspensionObjects/stmt/test.opt | 3 + .../Tasking/SuspensionObjects/stmt/test.py | 6 + .../TaskTypes/decision/src/test_driver.adb | 15 + .../Tasking/TaskTypes/decision/test.opt | 3 + .../Tasking/TaskTypes/decision/test.py | 6 + .../Tasking/TaskTypes/src/blocks_by_tasks.adb | 22 + .../Tasking/TaskTypes/src/blocks_by_tasks.ads | 19 + .../TaskTypes/stmt/src/test_driver.adb | 15 + .../Ravenscar/Tasking/TaskTypes/stmt/test.opt | 3 + .../Ravenscar/Tasking/TaskTypes/stmt/test.py | 6 + .../example0/decision/src/test_1.adb | 19 + .../Ravenscar/example0/decision/test.opt | 3 + .../tests/Ravenscar/example0/decision/test.py | 6 + .../tests/Ravenscar/example0/src/sync.adb | 53 + .../tests/Ravenscar/example0/src/sync.ads | 49 + .../Ravenscar/example0/stmt/src/test_1.adb | 18 + .../tests/Ravenscar/example0/stmt/test.opt | 3 + .../tests/Ravenscar/example0/stmt/test.py | 6 + .../S213-006-obligation-stats/src/foo.adb | 15 + .../S213-006-obligation-stats/src/test.adb | 6 + .../tests/S213-006-obligation-stats/test.py | 39 + testsuite/tests/S218-011-time-option/main.adb | 6 + testsuite/tests/S218-011-time-option/test.py | 38 + .../tests/S220-058-auto-scos-fetch/main.adb | 6 + .../tests/S220-058-auto-scos-fetch/test.py | 45 + .../tests/S506-014-mix-providers/main.adb | 4 + .../tests/S506-014-mix-providers/test.opt | 1 + .../tests/S506-014-mix-providers/test.py | 132 ++ .../tests/S527-004-ckpt-no-level/main.adb | 8 + .../tests/S527-004-ckpt-no-level/test.py | 43 + testsuite/tests/S529-038-isi-ckpt/main1.adb | 6 + testsuite/tests/S529-038-isi-ckpt/main2.adb | 16 + testsuite/tests/S529-038-isi-ckpt/test.py | 112 ++ .../S603-009-externally-built/main/main.adb | 7 + .../S603-009-externally-built/main/main.gpr | 6 + .../S603-009-externally-built/mylib/mylib.adb | 12 + .../S603-009-externally-built/mylib/mylib.ads | 3 + .../S603-009-externally-built/mylib/mylib.gpr | 5 + .../tests/S603-009-externally-built/test.opt | 8 + .../tests/S603-009-externally-built/test.py | 142 +++ .../generic_hello.adb | 6 + .../generic_hello.ads | 3 + .../S619-014-tag-provider-mismatch/main.adb | 13 + .../S619-014-tag-provider-mismatch/test.py | 43 + testsuite/tests/S621-026-mcdc-ckpt/main1.adb | 6 + testsuite/tests/S621-026-mcdc-ckpt/main2.adb | 16 + testsuite/tests/S621-026-mcdc-ckpt/test.py | 33 + testsuite/tests/S820-013-ckpt-dup-scos/bar.h | 8 + testsuite/tests/S820-013-ckpt-dup-scos/foo.c | 7 + testsuite/tests/S820-013-ckpt-dup-scos/main.c | 11 + .../tests/S820-013-ckpt-dup-scos/test.opt | 1 + .../tests/S820-013-ckpt-dup-scos/test.py | 32 + testsuite/tests/SB06-033-homonyms/.gitignore | 2 + .../tests/SB06-033-homonyms/app/default.gpr | 8 + .../tests/SB06-033-homonyms/app/main.adb | 7 + .../tests/SB06-033-homonyms/libfoo/lib.adb | 4 + .../tests/SB06-033-homonyms/libfoo/lib.ads | 13 + .../tests/SB06-033-homonyms/libfoo/libfoo.gpr | 11 + testsuite/tests/SB06-033-homonyms/test.opt | 5 + testsuite/tests/SB06-033-homonyms/test.py | 74 ++ .../decision/Engines/src/engines.adb | 33 + .../decision/Engines/src/engines.ads | 39 + .../Engines/src/test_engines_both.adb | 38 + .../Engines/src/test_engines_null.adb | 34 + .../Engines/src/test_engines_stable.adb | 35 + .../Engines/src/test_engines_unstable.adb | 35 + .../SanityCheck/decision/Engines/test.py | 6 + .../tests/T117-007-intf-thunks/src/action.ads | 14 + .../T117-007-intf-thunks/src/interface_a.ads | 9 + .../T117-007-intf-thunks/src/package_a.adb | 24 + .../T117-007-intf-thunks/src/package_a.ads | 33 + .../T117-007-intf-thunks/src/ut_main.adb | 18 + testsuite/tests/T117-007-intf-thunks/test.opt | 1 + testsuite/tests/T117-007-intf-thunks/test.py | 24 + testsuite/tests/T319-018-if-expr/src/pkg.adb | 26 + testsuite/tests/T319-018-if-expr/src/pkg.ads | 44 + testsuite/tests/T319-018-if-expr/src/proc.adb | 14 + .../tests/T319-018-if-expr/src/test_all.adb | 14 + .../tests/T319-018-if-expr/src/test_false.adb | 16 + .../tests/T319-018-if-expr/src/test_no.adb | 15 + .../tests/T319-018-if-expr/src/test_true.adb | 16 + testsuite/tests/T319-018-if-expr/test.opt | 2 + testsuite/tests/T319-018-if-expr/test.py | 7 + testsuite/tests/T331-043-native-warn/main.adb | 4 + testsuite/tests/T331-043-native-warn/test.py | 53 + .../tests/T520-035-exit-when/src/parser.adb | 29 + .../tests/T520-035-exit-when/src/parser.ads | 6 + .../T520-035-exit-when/src/test_parser_0.adb | 10 + .../src/test_parser_full.adb | 11 + .../T520-035-exit-when/src/test_parser_fx.adb | 10 + .../T520-035-exit-when/src/test_parser_tf.adb | 10 + .../T520-035-exit-when/src/test_parser_tt.adb | 10 + testsuite/tests/T520-035-exit-when/test.py | 7 + .../T528-018-dup-proj-crash/src-p1/p1.adb | 12 + .../T528-018-dup-proj-crash/src-p1/p1.ads | 5 + .../T528-018-dup-proj-crash/src-p2/p2.adb | 7 + .../tests/T528-018-dup-proj-crash/test.py | 27 + .../tests/T611-027-dump-units-to/main.adb | 6 + .../tests/T611-027-dump-units-to/pkg.adb | 8 + .../tests/T611-027-dump-units-to/pkg.ads | 3 + .../tests/T611-027-dump-units-to/test.py | 194 +++ testsuite/tests/T629-012-pragmas/test.py | 27 + testsuite/tests/T731-036-ckpt-bdd/test.opt | 1 + testsuite/tests/T731-036-ckpt-bdd/test.py | 143 +++ .../.gitignore | 2 + .../opslib/ops.adb | 9 + .../opslib/ops.ads | 4 + .../opslib/opslib.gpr | 14 + .../T807-011-externally-built-objdir/test.py | 67 + .../tests.gpr | 12 + .../tests/test_inc.adb | 7 + .../tests/T825-010-naming-scheme/main.adb | 6 + .../tests/T825-010-naming-scheme/p.1.ada | 4 + .../tests/T825-010-naming-scheme/p.2.ada | 6 + .../tests/T825-010-naming-scheme/p__q.1.ada | 4 + .../tests/T825-010-naming-scheme/p__q.2.ada | 8 + .../tests/T825-010-naming-scheme/test.py | 39 + .../tests/T828-018-tagged-aggr/src/pkg.adb | 11 + .../tests/T828-018-tagged-aggr/src/pkg.ads | 8 + .../T828-018-tagged-aggr/src/test_full.adb | 14 + .../T828-018-tagged-aggr/src/test_no.adb | 13 + testsuite/tests/T828-018-tagged-aggr/test.py | 7 + .../tests/T916-046-bdd-remapping/main.adb | 8 + .../pkg-compute_in_stub.adb | 9 + .../tests/T916-046-bdd-remapping/pkg.adb | 12 + .../tests/T916-046-bdd-remapping/pkg.ads | 4 + .../tests/T916-046-bdd-remapping/test.py | 25 + .../TA12-013-dump-ignore-src-files/foo.c | 7 + .../TA12-013-dump-ignore-src-files/identity.h | 5 + .../TA12-013-dump-ignore-src-files/main.adb | 14 + .../pkg-test-sep.adb | 6 + .../pkg-test.adb | 9 + .../TA12-013-dump-ignore-src-files/pkg.adb | 9 + .../TA12-013-dump-ignore-src-files/pkg.ads | 4 + .../pkh-test.adb | 6 + .../TA12-013-dump-ignore-src-files/pkh.adb | 9 + .../TA12-013-dump-ignore-src-files/pkh.ads | 4 + .../TA12-013-dump-ignore-src-files/test.py | 256 ++++ .../tests/TA14-011-show-mcdc-vectors/main.adb | 10 + .../tests/TA14-011-show-mcdc-vectors/pkg.adb | 26 + .../tests/TA14-011-show-mcdc-vectors/pkg.ads | 6 + .../tests/TA14-011-show-mcdc-vectors/test.py | 163 +++ .../src-test1/main.adb | 6 + .../src-test1/pkg-test.adb | 7 + .../TA15-063-ignore-fingerprint/src/main.adb | 6 + .../src/pkg-test.adb | 10 + .../TA15-063-ignore-fingerprint/src/pkg.adb | 4 + .../TA15-063-ignore-fingerprint/src/pkg.ads | 4 + .../tests/TA15-063-ignore-fingerprint/test.py | 71 ++ .../TA15-063-ignore-fingerprint/test1.gpr | 4 + .../main.adb | 7 + .../pkg-say_goodbye.adb | 11 + .../pkg.adb | 13 + .../pkg.ads | 4 + .../test.py | 83 ++ .../tests/TB13-020-expr-func-mcdc/main.adb | 23 + .../tests/TB13-020-expr-func-mcdc/pkg.adb | 12 + .../tests/TB13-020-expr-func-mcdc/pkg.ads | 8 + .../tests/TB13-020-expr-func-mcdc/test.opt | 1 + .../tests/TB13-020-expr-func-mcdc/test.py | 39 + .../tests/TB24-022-missing-sid/src-p1/p1.adb | 12 + .../tests/TB24-022-missing-sid/src-p1/p1.ads | 5 + .../tests/TB24-022-missing-sid/src-p2/p2.adb | 7 + testsuite/tests/TB24-022-missing-sid/test.py | 32 + .../tests/TC03-012-objcov-line-state/main.c | 16 + .../tests/TC03-012-objcov-line-state/main.s | 304 +++++ .../tests/TC03-012-objcov-line-state/test.opt | 2 + .../tests/TC03-012-objcov-line-state/test.py | 29 + .../tests/TC11-052-internal-error/main.adb | 11 + .../tests/TC11-052-internal-error/test.py | 84 ++ .../U128-004-displayed-percentages/main1.adb | 6 + .../U128-004-displayed-percentages/main99.adb | 6 + .../U128-004-displayed-percentages/pkg.adb | 250 ++++ .../U128-004-displayed-percentages/pkg.ads | 3 + .../U128-004-displayed-percentages/test.py | 27 + .../U128-029-missing-dump-trigger/main.adb | 6 + .../U128-029-missing-dump-trigger/test.py | 13 + testsuite/tests/U204-026-arch-mix/foo.gpr | 4 + testsuite/tests/U204-026-arch-mix/gen.sh | 124 ++ .../gnatcov_rts-buffers-bb_main_1.ads | 41 + .../gnatcov_rts-buffers-bb_main_2.ads | 41 + .../gnatcov_rts-buffers-bb_pkg.ads | 41 + .../gnatcov_rts-buffers-bs_pkg.ads | 41 + .../gnatcov_rts-buffers-db_main_1.adb | 15 + .../gnatcov_rts-buffers-db_main_1.ads | 6 + .../gnatcov_rts-buffers-db_main_2.adb | 15 + .../gnatcov_rts-buffers-db_main_2.ads | 6 + .../gnatcov_rts-buffers-lists-foo.ads | 25 + .../gnatcov_rts-buffers-pb_main_1.ads | 19 + .../gnatcov_rts-buffers-pb_main_2.ads | 19 + .../gnatcov_rts-buffers-pb_pkg.ads | 19 + .../gnatcov_rts-buffers-ps_pkg.ads | 19 + .../gen/arm-elf-linux/main_1.adb | 8 + .../gen/arm-elf-linux/main_1.sid | Bin 0 -> 387 bytes .../gen/arm-elf-linux/main_2.adb | 8 + .../gen/arm-elf-linux/main_2.sid | Bin 0 -> 387 bytes .../gen/arm-elf-linux/pkg.adb | 20 + .../gen/arm-elf-linux/pkg.ads | 5 + .../gen/arm-elf-linux/pkg.sid | Bin 0 -> 1046 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 0 -> 1878 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 0 -> 1888 bytes .../U204-026-arch-mix/gen/main_1.srctrace | Bin 0 -> 416 bytes .../U204-026-arch-mix/gen/main_2.srctrace | Bin 0 -> 388 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 0 -> 1942 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 0 -> 1851 bytes .../gnatcov_rts-buffers-bb_main_1.ads | 41 + .../gnatcov_rts-buffers-bb_main_2.ads | 41 + .../gnatcov_rts-buffers-bb_pkg.ads | 41 + .../gnatcov_rts-buffers-bs_pkg.ads | 41 + .../gnatcov_rts-buffers-db_main_1.adb | 15 + .../gnatcov_rts-buffers-db_main_1.ads | 6 + .../gnatcov_rts-buffers-db_main_2.adb | 15 + .../gnatcov_rts-buffers-db_main_2.ads | 6 + .../gnatcov_rts-buffers-lists-foo.ads | 25 + .../gnatcov_rts-buffers-pb_main_1.ads | 19 + .../gnatcov_rts-buffers-pb_main_2.ads | 19 + .../gnatcov_rts-buffers-pb_pkg.ads | 19 + .../gnatcov_rts-buffers-ps_pkg.ads | 19 + .../gen/x86_64-windows/main_1.adb | 8 + .../gen/x86_64-windows/main_1.sid | Bin 0 -> 389 bytes .../gen/x86_64-windows/main_2.adb | 8 + .../gen/x86_64-windows/main_2.sid | Bin 0 -> 389 bytes .../gen/x86_64-windows/pkg.adb | 20 + .../gen/x86_64-windows/pkg.ads | 5 + .../gen/x86_64-windows/pkg.sid | Bin 0 -> 1050 bytes testsuite/tests/U204-026-arch-mix/main_1.adb | 6 + testsuite/tests/U204-026-arch-mix/main_2.adb | 6 + testsuite/tests/U204-026-arch-mix/pkg.adb | 18 + testsuite/tests/U204-026-arch-mix/pkg.ads | 3 + testsuite/tests/U204-026-arch-mix/test.py | 183 +++ .../Ada/src/disjoint_main_1.adb | 9 + .../Ada/src/disjoint_main_2.adb | 9 + .../Ada/src/intersecting_main_1.adb | 10 + .../Ada/src/intersecting_main_2.adb | 10 + .../U204-029-source-rebase/Ada/src/pkg1.adb | 15 + .../U204-029-source-rebase/Ada/src/pkg1.ads | 5 + .../U204-029-source-rebase/Ada/src/pkg2.adb | 15 + .../U204-029-source-rebase/Ada/src/pkg2.ads | 5 + .../tests/U204-029-source-rebase/Ada/test.py | 80 ++ .../U204-029-source-rebase/C/src/a/pkg.h | 13 + .../U204-029-source-rebase/C/src/b/pkg.h | 13 + .../U204-029-source-rebase/C/src/main1.c | 10 + .../U204-029-source-rebase/C/src/main2.c | 10 + .../tests/U204-029-source-rebase/C/test.opt | 1 + .../tests/U204-029-source-rebase/C/test.py | 28 + .../U204-029-source-rebase/test_support.py | 160 +++ .../p-child-src/main.adb | 8 + .../tests/U208-020-child-project/p-child.gpr | 7 + .../U208-020-child-project/p-src/pkg.adb | 8 + .../U208-020-child-project/p-src/pkg.ads | 3 + testsuite/tests/U208-020-child-project/p.gpr | 4 + .../tests/U208-020-child-project/test.opt | 1 + .../tests/U208-020-child-project/test.py | 30 + testsuite/tests/U208-020-error-call/main.c | 8 + testsuite/tests/U208-020-error-call/test.opt | 1 + testsuite/tests/U208-020-error-call/test.py | 26 + .../U208-020-unique-language-project/main.adb | 4 + .../U208-020-unique-language-project/main.c | 5 + .../U208-020-unique-language-project/test.opt | 1 + .../U208-020-unique-language-project/test.py | 51 + .../tests/U211-014-setup/ext_rt/ext_rt.gpr | 4 + .../ext_rt/gnatcov_rts-base_io.adb | 47 + .../tests/U211-014-setup/src-ada/foo.adb | 6 + testsuite/tests/U211-014-setup/src-c/foo.c | 8 + .../tests/U211-014-setup/src-mixed/bar.c | 13 + .../tests/U211-014-setup/src-mixed/foo.adb | 12 + .../tests/U211-014-setup/src-mixed/pkg.adb | 10 + .../tests/U211-014-setup/src-mixed/pkg.ads | 12 + testsuite/tests/U211-014-setup/test.py | 260 ++++ .../U219-010-ali-entry-guard-sloc/main.adb | 29 + .../U219-010-ali-entry-guard-sloc/test.opt | 1 + .../U219-010-ali-entry-guard-sloc/test.py | 29 + .../main.adb | 8 + .../test.opt | 1 + .../test.py | 45 + testsuite/tests/U317-004-xml-report/main.adb | 6 + testsuite/tests/U317-004-xml-report/test.py | 29 + .../tests/U416-006-big-bdd/src/compute.c | 7 + .../tests/U416-006-big-bdd/src/test_eval.adb | 21 + .../U416-006-big-bdd/src/testconditions.adb | 31 + .../U416-006-big-bdd/src/testconditions.ads | 5 + testsuite/tests/U416-006-big-bdd/test.py | 69 ++ .../tests/U527-020-dc-from-mcdc/main.adb | 8 + testsuite/tests/U527-020-dc-from-mcdc/test.py | 42 + .../tests/U630-040-static-decision/src/p.ads | 30 + .../U630-040-static-decision/src/test_p.adb | 27 + .../tests/U630-040-static-decision/test.opt | 2 + .../tests/U630-040-static-decision/test.py | 17 + .../tests/U811-028-suppress-output/main.adb | 14 + .../tests/U811-028-suppress-output/test.py | 123 ++ testsuite/tests/U901-029-estamps/main.adb | 8 + testsuite/tests/U901-029-estamps/test.opt | 1 + testsuite/tests/U901-029-estamps/test.py | 65 + .../UA21-030-elab_mcdc_state/src/pkg.adb | 13 + .../UA21-030-elab_mcdc_state/src/pkg.ads | 13 + .../UA21-030-elab_mcdc_state/src/pkh.adb | 12 + .../UA21-030-elab_mcdc_state/src/pkh.ads | 11 + .../src/test_elab.adb | 28 + .../tests/UA21-030-elab_mcdc_state/test.py | 12 + .../UB18-055-switches-in-gprfile/a/main.adb | 6 + .../UB18-055-switches-in-gprfile/b/b.adb | 8 + .../UB18-055-switches-in-gprfile/b/b.ads | 3 + .../UB18-055-switches-in-gprfile/c/c.adb | 8 + .../UB18-055-switches-in-gprfile/c/c.ads | 3 + .../UB18-055-switches-in-gprfile/test.py | 43 + testsuite/tests/V120-034-dup-langs/main.adb | 8 + testsuite/tests/V120-034-dup-langs/test.py | 30 + .../tests/V201-010-multi-report/main.adb | 8 + testsuite/tests/V201-010-multi-report/test.py | 55 + .../tests/V304-007-missing-files/baz.adb | 6 + .../tests/V304-007-missing-files/foo.adb | 7 + .../tests/V304-007-missing-files/test.opt | 3 + .../tests/V304-007-missing-files/test.py | 34 + testsuite/tests/V309-017-setup-config/foo.adb | 6 + .../tests/V309-017-setup-config/test.opt | 4 + testsuite/tests/V309-017-setup-config/test.py | 106 ++ .../V520-019-duplicate-messages/main.adb | 8 + .../tests/V520-019-duplicate-messages/pkg.adb | 13 + .../tests/V520-019-duplicate-messages/pkg.ads | 7 + .../tests/V520-019-duplicate-messages/test.py | 43 + testsuite/tests/V616-028-xsd-check/lib.c | 5 + testsuite/tests/V616-028-xsd-check/pkg.adb | 6 + testsuite/tests/V616-028-xsd-check/pkg.ads | 9 + testsuite/tests/V616-028-xsd-check/test.adb | 18 + testsuite/tests/V616-028-xsd-check/test.py | 60 + .../tests/V824-005-sid-ext-prj/ext_pkg.gpr | 6 + testsuite/tests/V824-005-sid-ext-prj/pkg.gpr | 4 + .../V824-005-sid-ext-prj/src-ext_pkg/main.adb | 6 + .../V824-005-sid-ext-prj/src-pkg/pkg.adb | 14 + .../V824-005-sid-ext-prj/src-pkg/pkg.ads | 3 + testsuite/tests/V824-005-sid-ext-prj/test.py | 50 + .../ignore-main/foo.c | 5 + .../ignore-main/foo.h | 1 + .../ignore-main/test.c | 11 + .../ignore-main/test.py | 26 + .../main-unit-of-interest/test.c | 6 + .../main-unit-of-interest/test.py | 27 + .../VA04-023-non-instr-sco-reloc/main.adb | 10 + .../VA04-023-non-instr-sco-reloc/pkg_1.ads | 14 + .../VA04-023-non-instr-sco-reloc/pkg_2.ads | 14 + .../VA04-023-non-instr-sco-reloc/test.opt | 1 + .../VA04-023-non-instr-sco-reloc/test.py | 44 + .../tests/VB07-015-clean-output-dir/main.adb | 8 + .../tests/VB07-015-clean-output-dir/pkg.adb | 8 + .../tests/VB07-015-clean-output-dir/pkg.ads | 5 + .../tests/VB07-015-clean-output-dir/test.py | 78 ++ .../tests/VB18-035-default-opts/main.adb | 10 + testsuite/tests/VB18-035-default-opts/test.py | 64 + .../VB21-022-sid-srctrace-mismatch/main.adb | 15 + .../VB21-022-sid-srctrace-mismatch/test.py | 48 + testsuite/tests/Z999-999/test.opt | 1 + testsuite/tests/Z999-999/test.py | 9 + testsuite/tests/asm-consolidate/src/lib.adb | 19 + testsuite/tests/asm-consolidate/src/lib.ads | 6 + testsuite/tests/asm-consolidate/src/p1.adb | 11 + testsuite/tests/asm-consolidate/src/p2.adb | 9 + .../tests/asm-consolidate/src/stuff1.adb | 7 + .../tests/asm-consolidate/src/stuff1.ads | 4 + testsuite/tests/asm-consolidate/test.opt | 1 + testsuite/tests/asm-consolidate/test.py | 64 + .../IB11-006-compare-floats/inrange.adb | 5 + .../IB11-006-compare-floats/test.py | 6 + .../branch-cond/IB12-008-postcond/checkx.adb | 6 + .../branch-cond/IB12-008-postcond/test.py | 6 + .../IB12-016-lone-not/eval_not.adb | 7 + .../branch-cond/IB12-016-lone-not/not_if.adb | 9 + .../branch-cond/IB12-016-lone-not/test.py | 6 + .../branch-cond/IB12-019-fncalls/services.adb | 14 + .../branch-cond/IB12-019-fncalls/services.ads | 9 + .../branch-cond/IB12-019-fncalls/test.py | 6 + .../branch-cond/IB12-028-length/empty.adb | 8 + .../tests/branch-cond/IB12-028-length/test.py | 6 + .../IB13-014-const-instances/services.adb | 6 + .../IB13-014-const-instances/services.ads | 5 + .../IB13-014-const-instances/test.opt | 1 + .../IB13-014-const-instances/test.py | 7 + .../test_services.adb | 14 + .../IB15-004-spec-precond/checkx.adb | 6 + .../IB15-004-spec-precond/checkx.ads | 2 + .../IB15-004-spec-precond/services.adb | 6 + .../IB15-004-spec-precond/services.ads | 8 + .../branch-cond/IB15-004-spec-precond/test.py | 10 + .../IB15-004-spec-precond/test_services.ads | 2 + .../IB18-024-float-precond/checki.adb | 4 + .../IB18-024-float-precond/checki.ads | 2 + .../IB18-024-float-precond/checkx.adb | 4 + .../IB18-024-float-precond/checkx.ads | 2 + .../IB18-024-float-precond/test.py | 7 + .../IB19-001-precond-false/check.adb | 4 + .../IB19-001-precond-false/check.ads | 2 + .../IB19-001-precond-false/test.opt | 1 + .../IB19-001-precond-false/test.py | 6 + .../IB20-015-length-check/starts.adb | 6 + .../branch-cond/IB20-015-length-check/test.py | 7 + .../IB20-027-addr-compare/regions.adb | 11 + .../IB20-027-addr-compare/regions.ads | 11 + .../branch-cond/IB20-027-addr-compare/test.py | 6 + .../IB23-016-range-test/checkx.adb | 4 + .../branch-cond/IB23-016-range-test/test.py | 6 + .../IB25-022-shortcut-actions/services.adb | 33 + .../IB25-022-shortcut-actions/services.ads | 11 + .../IB25-022-shortcut-actions/test.py | 6 + .../branch-cond/IC01-011-null-fatp/fatp.adb | 10 + .../branch-cond/IC01-011-null-fatp/fatp.ads | 4 + .../branch-cond/IC01-011-null-fatp/test.py | 6 + .../IC01-032-itype-early-elab/starts.adb | 6 + .../IC01-032-itype-early-elab/test.py | 5 + .../IC02-013-nested-shortcut-action/check.adb | 13 + .../IC02-013-nested-shortcut-action/check.ads | 8 + .../IC02-013-nested-shortcut-action/test.py | 7 + .../IC02-020-shortcut-action/check.adb | 17 + .../IC02-020-shortcut-action/check.ads | 9 + .../IC02-020-shortcut-action/test.py | 7 + .../branch-cond/J205-019-and-not/check.adb | 5 + .../branch-cond/J205-019-and-not/foo.adb | 5 + .../branch-cond/J205-019-and-not/foo2.adb | 5 + .../branch-cond/J205-019-and-not/foo3.adb | 5 + .../branch-cond/J205-019-and-not/test.py | 9 + .../branch-cond/J205-021-slice-compare/p.adb | 10 + .../J205-021-slice-compare/test.py | 7 + testsuite/tests/branch-cond/extra.opt | 1 + testsuite/tests/exemptions-check/expected | 8 + .../tests/exemptions-check/src/hello.adb | 31 + testsuite/tests/exemptions-check/test.opt | 1 + testsuite/tests/exemptions-check/test.py | 22 + testsuite/tests/gnatcov-run.py | 94 ++ testsuite/tests/gpr-scos/src/dec.adb | 4 + testsuite/tests/gpr-scos/src/inc.adb | 4 + testsuite/tests/gpr-scos/src/test_ops.adb | 18 + testsuite/tests/gpr-scos/test.py | 70 ++ .../instr-cov/C++/c++_no_warnings/main.cpp | 5 + .../instr-cov/C++/c++_no_warnings/test.py | 25 + .../instr-cov/C++/cpp-extern-c-main/main.cpp | 8 + .../instr-cov/C++/cpp-extern-c-main/test.py | 24 + .../tests/instr-cov/C++/explicit_lang/main.c | 8 + .../tests/instr-cov/C++/explicit_lang/test.py | 35 + .../tests/instr-cov/C++/std-c++20/cmdline.cpp | 28 + .../tests/instr-cov/C++/std-c++20/cmdline.hh | 7 + .../tests/instr-cov/C++/std-c++20/main.cpp | 10 + .../tests/instr-cov/C++/std-c++20/test.py | 67 + .../instr-cov/C++/std-cond-code/main.cpp | 16 + .../tests/instr-cov/C++/std-cond-code/test.py | 67 + .../src-lib1/pkg1.c | 9 + .../src-lib1/pkg1.h | 3 + .../src-lib2/pkg2.c | 7 + .../src-lib2/pkg2.h | 1 + .../src/main.c | 9 + .../VB03-024-preprocess-included-proj/test.py | 57 + .../tests/instr-cov/basic_base64/main.adb | 9 + .../tests/instr-cov/basic_base64/pkg.adb | 12 + .../tests/instr-cov/basic_base64/pkg.ads | 5 + .../tests/instr-cov/basic_base64/test.py | 27 + .../tests/instr-cov/basic_decision/main.adb | 7 + .../tests/instr-cov/basic_decision/p.gpr | 4 + .../tests/instr-cov/basic_decision/pkg.adb | 12 + .../tests/instr-cov/basic_decision/pkg.ads | 5 + .../tests/instr-cov/basic_decision/test.py | 33 + testsuite/tests/instr-cov/basic_stmt/main.adb | 9 + testsuite/tests/instr-cov/basic_stmt/p.gpr | 4 + testsuite/tests/instr-cov/basic_stmt/pkg.adb | 12 + testsuite/tests/instr-cov/basic_stmt/pkg.ads | 5 + testsuite/tests/instr-cov/basic_stmt/test.py | 31 + .../tests/instr-cov/bin_file_tunings/main.adb | 6 + .../tests/instr-cov/bin_file_tunings/test.opt | 1 + .../tests/instr-cov/bin_file_tunings/test.py | 128 ++ .../tests/instr-cov/c_custom_naming/hello.cc | 7 + .../tests/instr-cov/c_custom_naming/main.cc | 13 + .../tests/instr-cov/c_custom_naming/test.opt | 1 + .../tests/instr-cov/c_custom_naming/test.py | 47 + .../tests/instr-cov/c_empty_source/main.c | 7 + .../tests/instr-cov/c_empty_source/pkg.c | 7 + .../tests/instr-cov/c_empty_source/pkg.h | 3 + .../tests/instr-cov/c_empty_source/test.py | 26 + testsuite/tests/instr-cov/c_gpr_opts/hello.c | 13 + testsuite/tests/instr-cov/c_gpr_opts/main.c | 20 + testsuite/tests/instr-cov/c_gpr_opts/test.py | 40 + testsuite/tests/instr-cov/c_header/fact.h | 8 + testsuite/tests/instr-cov/c_header/main.c | 8 + testsuite/tests/instr-cov/c_header/test.py | 42 + .../c_macros_no_cov_warnings/dummy-print.c | 4 + .../instr-cov/c_macros_no_cov_warnings/main.c | 12 + .../c_macros_no_cov_warnings/test.py | 28 + .../tests/instr-cov/c_multiline_stmt/main.c | 35 + .../tests/instr-cov/c_multiline_stmt/pkg.c | 5 + .../tests/instr-cov/c_multiline_stmt/pkg.h | 1 + .../tests/instr-cov/c_multiline_stmt/test.opt | 1 + .../tests/instr-cov/c_multiline_stmt/test.py | 75 ++ .../instr-cov/c_no_return/empty_main/main.c | 4 + .../instr-cov/c_no_return/no_return/main.c | 15 + testsuite/tests/instr-cov/c_no_return/test.py | 53 + testsuite/tests/instr-cov/c_opts/hello.c | 4 + testsuite/tests/instr-cov/c_opts/main.c | 15 + .../tests/instr-cov/c_opts/other/hello.h | 1 + testsuite/tests/instr-cov/c_opts/test.py | 54 + testsuite/tests/instr-cov/c_prep_error/main.c | 7 + .../tests/instr-cov/c_prep_error/test.py | 35 + .../instr-cov/c_special_filenames/$foo@bar$.c | 5 + .../c_special_filenames/ada_main.adb | 10 + .../instr-cov/c_special_filenames/main.c | 8 + .../instr-cov/c_special_filenames/test.opt | 1 + .../instr-cov/c_special_filenames/test.py | 34 + .../instr-cov/c_ternary_in_if_cond/main.c | 10 + .../instr-cov/c_ternary_in_if_cond/test.py | 29 + testsuite/tests/instr-cov/c_wrong_main/main.c | 5 + .../tests/instr-cov/c_wrong_main/test.py | 32 + .../instr-cov/checks_and_warnings/main.adb | 16 + .../tests/instr-cov/checks_and_warnings/p.gpr | 8 + .../instr-cov/checks_and_warnings/pkg.ads | 23 + .../instr-cov/checks_and_warnings/test.opt | 1 + .../instr-cov/checks_and_warnings/test.py | 35 + .../tests/instr-cov/consistency/main.adb | 6 + testsuite/tests/instr-cov/consistency/p.gpr | 4 + testsuite/tests/instr-cov/consistency/test.py | 93 ++ .../instr-cov/decl-inversion/src/test_foo.adb | 23 + .../tests/instr-cov/decl-inversion/test.opt | 2 + .../tests/instr-cov/decl-inversion/test.py | 12 + .../instr-cov/default_dump_channel/main.adb | 4 + .../instr-cov/default_dump_channel/test.opt | 2 + .../instr-cov/default_dump_channel/test.py | 67 + testsuite/tests/instr-cov/end_slocs/main.adb | 6 + testsuite/tests/instr-cov/end_slocs/p.gpr | 4 + testsuite/tests/instr-cov/end_slocs/test.py | 35 + testsuite/tests/instr-cov/endianity/main.adb | 9 + testsuite/tests/instr-cov/endianity/pkg.adb | 12 + testsuite/tests/instr-cov/endianity/pkg.ads | 5 + testsuite/tests/instr-cov/endianity/test.py | 51 + .../tests/instr-cov/explicit_mains/foo.s | 0 .../tests/instr-cov/explicit_mains/main1.adb | 8 + .../tests/instr-cov/explicit_mains/main2.adb | 8 + .../instr-cov/explicit_mains/mylib/pkg.adb | 16 + .../instr-cov/explicit_mains/mylib/pkg.ads | 5 + .../tests/instr-cov/explicit_mains/test.py | 186 +++ .../explicit_mains_ignore_gpr/bar.adb | 11 + .../explicit_mains_ignore_gpr/foo.adb | 6 + .../explicit_mains_ignore_gpr/test.py | 47 + .../instr-cov/explicit_mains_uoi/main.adb | 6 + .../instr-cov/explicit_mains_uoi/test.py | 25 + .../tests/instr-cov/expr_func/aggr/main.adb | 27 + .../tests/instr-cov/expr_func/aggr/p.gpr | 4 + .../tests/instr-cov/expr_func/aggr/test.py | 32 + .../aspects/no-rec_asp_no-prespec/src/foo.ads | 10 + .../aspects/no-rec_asp_no-prespec/test.py | 12 + .../aspects/no-rec_asp_prespec/src/foo.ads | 12 + .../aspects/no-rec_asp_prespec/test.py | 12 + .../no-rec_no-asp_no-prespec/src/foo.ads | 8 + .../aspects/no-rec_no-asp_no-prespec/test.py | 12 + .../aspects/no-rec_no-asp_prespec/src/foo.ads | 10 + .../aspects/no-rec_no-asp_prespec/test.py | 12 + .../instr-cov/expr_func/aspects/readme.txt | 10 + .../aspects/rec_asp_no-prespec/src/foo.ads | 10 + .../aspects/rec_asp_no-prespec/test.opt | 1 + .../aspects/rec_asp_no-prespec/test.py | 12 + .../aspects/rec_asp_prespec/src/foo.ads | 12 + .../aspects/rec_asp_prespec/test.opt | 1 + .../expr_func/aspects/rec_asp_prespec/test.py | 12 + .../aspects/rec_no-asp_no-prespec/src/foo.ads | 8 + .../aspects/rec_no-asp_no-prespec/test.opt | 1 + .../aspects/rec_no-asp_no-prespec/test.py | 12 + .../aspects/rec_no-asp_prespec/src/foo.ads | 10 + .../aspects/rec_no-asp_prespec/test.opt | 1 + .../aspects/rec_no-asp_prespec/test.py | 12 + .../expr_func/aspects/src/test_foo.adb | 21 + .../tests/instr-cov/expr_func/basic/main.adb | 16 + .../tests/instr-cov/expr_func/basic/p.gpr | 4 + .../tests/instr-cov/expr_func/basic/test.py | 32 + testsuite/tests/instr-cov/expr_func/extra.opt | 2 + .../instr-cov/expr_func/generic/src/pkg.ads | 21 + .../expr_func/generic/src/test_main.adb | 26 + .../tests/instr-cov/expr_func/generic/test.py | 48 + .../expr_func/generic_prim/src/inst.ads | 3 + .../expr_func/generic_prim/src/pkg.ads | 16 + .../expr_func/generic_prim/src/test_pkg.adb | 18 + .../instr-cov/expr_func/generic_prim/test.py | 12 + .../instr-cov/expr_func/ghost/src/pkg.adb | 14 + .../instr-cov/expr_func/ghost/src/pkg.ads | 17 + .../expr_func/ghost/src/test_main.adb | 14 + .../tests/instr-cov/expr_func/ghost/test.py | 13 + .../expr_func/overriding/src/pak.ads | 14 + .../expr_func/overriding/src/test_foo.adb | 17 + .../instr-cov/expr_func/overriding/test.py | 11 + .../expr_func/parameterless/main.adb | 5 + .../instr-cov/expr_func/parameterless/p.gpr | 4 + .../instr-cov/expr_func/parameterless/pak.ads | 6 + .../instr-cov/expr_func/parameterless/test.py | 33 + .../instr-cov/expr_func/prev_decl/src/bar.ads | 5 + .../instr-cov/expr_func/prev_decl/src/foo.ads | 16 + .../expr_func/prev_decl/src/test_decl.adb | 16 + .../instr-cov/expr_func/prev_decl/test.py | 13 + .../tests/instr-cov/expr_func/prim/main.adb | 7 + .../tests/instr-cov/expr_func/prim/p.gpr | 4 + .../tests/instr-cov/expr_func/prim/pak.ads | 18 + .../tests/instr-cov/expr_func/prim/test.opt | 1 + .../tests/instr-cov/expr_func/prim/test.py | 36 + .../tests/instr-cov/expr_func/prim2/main.adb | 9 + .../tests/instr-cov/expr_func/prim2/p.gpr | 4 + .../tests/instr-cov/expr_func/prim2/pak.adb | 10 + .../tests/instr-cov/expr_func/prim2/pak.ads | 25 + .../tests/instr-cov/expr_func/prim2/test.opt | 1 + .../tests/instr-cov/expr_func/prim2/test.py | 39 + .../expr_func/program_error/src/test_main.adb | 31 + .../expr_func/program_error/test.opt | 1 + .../instr-cov/expr_func/program_error/test.py | 13 + .../expr_func/quantifier/src/test_main.adb | 22 + .../instr-cov/expr_func/quantifier/test.py | 12 + .../src/obj-p/p-gnatcov-instr/dummy.txt | 1 + .../ext_gpr/src/obj-p/p-gnatcov-instr/pkg.ads | 1 + .../obj-p_ext1/p_ext1-gnatcov-instr/pkg.ads | 1 + .../obj-p_ext2/p_ext2-gnatcov-instr/pkg.ads | 1 + testsuite/tests/instr-cov/ext_gpr/src/p.gpr | 4 + .../tests/instr-cov/ext_gpr/src/p_ext1.gpr | 4 + .../tests/instr-cov/ext_gpr/src/p_ext2.gpr | 4 + .../tests/instr-cov/ext_gpr/src/src-p/pkg.ads | 3 + .../instr-cov/ext_gpr/src/src-p_ext1/pkg1.ads | 3 + .../instr-cov/ext_gpr/src/src-p_ext2/pkg2.ads | 3 + testsuite/tests/instr-cov/ext_gpr/test.py | 45 + .../tests/instr-cov/ghost_generic/gen.adb | 11 + .../tests/instr-cov/ghost_generic/gen.ads | 8 + .../tests/instr-cov/ghost_generic/main.adb | 16 + .../ghost_generic/non_ghost_inst.ads | 3 + .../tests/instr-cov/ghost_generic/test.py | 33 + .../instr-cov/hidden_standard/src/std.adb | 12 + .../instr-cov/hidden_standard/src/std.ads | 10 + .../hidden_standard/src/test_std.adb | 14 + .../tests/instr-cov/hidden_standard/test.py | 11 + .../instr-cov/library_projects/.gitignore | 3 + .../tests/instr-cov/library_projects/main.gpr | 8 + .../tests/instr-cov/library_projects/math.gpr | 4 + .../library_projects/src-main/main.adb | 14 + .../library_projects/src-math/math.adb | 18 + .../library_projects/src-math/math.ads | 15 + .../library_projects/src-vectors/vectors.adb | 32 + .../library_projects/src-vectors/vectors.ads | 22 + .../tests/instr-cov/library_projects/test.py | 40 + .../instr-cov/library_projects/vectors.gpr | 4 + .../disabled_lang/ada-main/main.adb | 10 + .../disabled_lang/ada-main/tested.c | 8 + .../main_autodump/disabled_lang/c-main/main.c | 10 + .../disabled_lang/c-main/pkg.adb | 27 + .../disabled_lang/c-main/pkg.ads | 13 + .../main_autodump/disabled_lang/test.py | 59 + .../nested_block/dotted-decl.adb | 19 + .../main_autodump/nested_block/dotted-exn.adb | 17 + .../nested_block/dotted-no_decl.adb | 12 + .../main_autodump/nested_block/dotted.adb | 15 + .../main_autodump/nested_block/dotted.ads | 8 + .../nested_block/simple_decl.adb | 21 + .../main_autodump/nested_block/simple_exn.adb | 17 + .../nested_block/simple_no_decl.adb | 11 + .../nested_block/simple_only_exn.adb | 21 + .../main_autodump/nested_block/test.opt | 1 + .../main_autodump/nested_block/test.py | 79 ++ .../main_autodump/pramga_prio/main.adb | 17 + .../main_autodump/pramga_prio/test.opt | 1 + .../main_autodump/pramga_prio/test.py | 37 + .../main_autodump/stubs/main-inner.adb | 6 + .../instr-cov/main_autodump/stubs/main.adb | 8 + .../instr-cov/main_autodump/stubs/test.py | 40 + .../stubs_controlled/main-inner.adb | 6 + .../main_autodump/stubs_controlled/main.adb | 16 + .../main_autodump/stubs_controlled/pkg.adb | 8 + .../main_autodump/stubs_controlled/pkg.ads | 8 + .../main_autodump/stubs_controlled/test.opt | 2 + .../main_autodump/stubs_controlled/test.py | 42 + .../main_autodump/task_in_main/main.adb | 20 + .../main_autodump/task_in_main/test.opt | 1 + .../main_autodump/task_in_main/test.py | 36 + .../instr-cov/manual-dump/covdump__cov.adb | 11 + .../instr-cov/manual-dump/covdump__nocov.adb | 4 + .../tests/instr-cov/manual-dump/main.adb | 6 + .../tests/instr-cov/manual-dump/test.opt | 2 + testsuite/tests/instr-cov/manual-dump/test.py | 51 + testsuite/tests/instr-cov/mixed_and/main.adb | 19 + testsuite/tests/instr-cov/mixed_and/p.gpr | 4 + testsuite/tests/instr-cov/mixed_and/test.py | 32 + .../tests/instr-cov/multiline_marker/main.c | 17 + .../tests/instr-cov/multiline_marker/test.opt | 1 + .../tests/instr-cov/multiline_marker/test.py | 29 + .../instr-cov/multiple_mains/src/test_a.adb | 4 + .../instr-cov/multiple_mains/src/test_b.adb | 6 + .../tests/instr-cov/multiple_mains/test.py | 24 + .../tests/instr-cov/nested_ternary/main.c | 6 + .../tests/instr-cov/nested_ternary/test.py | 26 + testsuite/tests/instr-cov/no_main/main.adb | 9 + testsuite/tests/instr-cov/no_main/p.gpr | 8 + testsuite/tests/instr-cov/no_main/pkg.adb | 12 + testsuite/tests/instr-cov/no_main/pkg.ads | 5 + testsuite/tests/instr-cov/no_main/test.py | 32 + testsuite/tests/instr-cov/not_array/main.adb | 16 + testsuite/tests/instr-cov/not_array/p.gpr | 4 + testsuite/tests/instr-cov/not_array/test.opt | 3 + testsuite/tests/instr-cov/not_array/test.py | 38 + .../instr-cov/null_proc_generic/src/main.adb | 7 + .../instr-cov/null_proc_generic/src/pkg.ads | 7 + .../instr-cov/null_proc_generic/test.opt | 2 + .../tests/instr-cov/null_proc_generic/test.py | 46 + .../instr-cov/null_proc_not_null/src/pkg.ads | 11 + .../null_proc_not_null/src/test_1.adb | 12 + .../null_proc_not_null/src/test_12.adb | 13 + .../null_proc_not_null/src/test_2.adb | 12 + .../null_proc_not_null/src/test_no.adb | 12 + .../instr-cov/null_proc_not_null/test.py | 12 + .../tests/instr-cov/pragma_after_cu/main.adb | 10 + .../instr-cov/pragma_after_cu/raise_error.adb | 4 + .../instr-cov/pragma_after_cu/raise_error.ads | 2 + .../tests/instr-cov/pragma_after_cu/test.opt | 1 + .../tests/instr-cov/pragma_after_cu/test.py | 27 + .../tests/instr-cov/pragma_assert/src/pkg.ads | 3 + .../instr-cov/pragma_assert/src/test_main.adb | 34 + .../tests/instr-cov/pragma_assert/test.opt | 1 + .../tests/instr-cov/pragma_assert/test.py | 13 + .../tests/instr-cov/pragma_no_body/main.adb | 6 + .../instr-cov/pragma_no_body/orig_pkg.adb | 6 + .../instr-cov/pragma_no_body/orig_pkg.ads | 3 + .../tests/instr-cov/pragma_no_body/pkg.adb | 1 + .../tests/instr-cov/pragma_no_body/pkg.ads | 3 + .../tests/instr-cov/pragma_no_body/test.opt | 1 + .../tests/instr-cov/pragma_no_body/test.py | 26 + .../instr-cov/protected_body/src/foo.adb | 20 + .../instr-cov/protected_body/src/foo.ads | 20 + .../instr-cov/protected_body/src/test_foo.adb | 36 + .../tests/instr-cov/protected_body/test.opt | 1 + .../tests/instr-cov/protected_body/test.py | 11 + testsuite/tests/instr-cov/pure_units/main.adb | 12 + testsuite/tests/instr-cov/pure_units/p.gpr | 8 + .../tests/instr-cov/pure_units/pkg-child.ads | 15 + testsuite/tests/instr-cov/pure_units/pkg.adb | 12 + testsuite/tests/instr-cov/pure_units/pkg.ads | 17 + testsuite/tests/instr-cov/pure_units/test.opt | 2 + testsuite/tests/instr-cov/pure_units/test.py | 35 + .../remove_extra_src/src-mylib/mylib.adb | 10 + .../remove_extra_src/src-mylib/mylib.ads | 3 + .../remove_extra_src/src-myprog/prog.adb | 8 + .../tests/instr-cov/remove_extra_src/test.py | 69 ++ testsuite/tests/instr-cov/scalar_and/main.adb | 7 + testsuite/tests/instr-cov/scalar_and/p.gpr | 4 + testsuite/tests/instr-cov/scalar_and/test.py | 27 + .../instr-cov/short_circuit_and_or/gnat.adc | 1 + .../instr-cov/short_circuit_and_or/main.adb | 136 ++ .../instr-cov/short_circuit_and_or/test.opt | 1 + .../instr-cov/short_circuit_and_or/test.py | 71 ++ .../short_circuit_and_or/type_pkg.ads | 7 + .../instr-cov/stmt_after_accept/main.adb | 33 + .../instr-cov/stmt_after_accept/test.opt | 1 + .../tests/instr-cov/stmt_after_accept/test.py | 26 + .../tests/instr-cov/unknown_unit/main.adb | 7 + testsuite/tests/instr-cov/unknown_unit/p.gpr | 4 + .../tests/instr-cov/unknown_unit/pkg.adb | 12 + .../tests/instr-cov/unknown_unit/pkg.ads | 5 + .../tests/instr-cov/unknown_unit/test.py | 54 + .../IB19_019-FormalDefault/src/andthen.adb | 22 + .../Andthen/IB19_019-FormalDefault/test.opt | 1 + .../Andthen/IB19_019-FormalDefault/test.py | 6 + .../JC16_008-ComponentDefault/src/andthen.adb | 15 + .../JC16_008-ComponentDefault/test.opt | 1 + .../Andthen/JC16_008-ComponentDefault/test.py | 6 + .../Ada/decision/Andthen/src/andthen.ads | 3 + .../decision/Andthen/src/test_andthen_0.adb | 12 + .../decision/Andthen/src/test_andthen_a.adb | 13 + .../decision/Andthen/src/test_andthen_ab.adb | 14 + .../decision/Andthen/src/test_andthen_b.adb | 13 + .../decision/Andthen/src/test_andthen_f.adb | 14 + .../decision/Andthen/src/test_andthen_t.adb | 12 + testsuite/tests/scos-overlap/test.c | 13 + testsuite/tests/scos-overlap/test.py | 103 ++ .../shared-libs/ada-main/src-main/main.adb | 7 + .../shared-libs/ada-main/src-mylib/mylib.adb | 12 + .../shared-libs/ada-main/src-mylib/mylib.ads | 5 + testsuite/tests/shared-libs/ada-main/test.py | 52 + .../tests/shared-libs/c-main/src-main/main.c | 14 + .../shared-libs/c-main/src-mylib/mylib.adb | 12 + .../shared-libs/c-main/src-mylib/mylib.ads | 6 + testsuite/tests/shared-libs/c-main/test.py | 52 + testsuite/tests/shared-libs/extra.opt | 2 + testsuite/tests/xml-check/src/andthen.adb | 4 + .../tests/xml-check/src/test_andthen_t.adb | 7 + testsuite/tests/xml-check/test.py | 28 + 2814 files changed, 51930 insertions(+) create mode 100644 testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.adb create mode 100644 testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.ads create mode 100644 testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/docount.adb create mode 100644 testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/test_docount.adb create mode 100644 testsuite/tests/Ada/decision/IC17_026-dc-while-not/test.py create mode 100644 testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.adb create mode 100644 testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.ads create mode 100644 testsuite/tests/Ada/decision/K202_014-elsif-abs/src/test_add.adb create mode 100644 testsuite/tests/Ada/decision/K202_014-elsif-abs/test.py create mode 100644 testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.adb create mode 100644 testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.ads create mode 100644 testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/test_tf.adb create mode 100644 testsuite/tests/Ada/decision/K303_016-exwhen-abs/test.py create mode 100644 testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.adb create mode 100644 testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.ads create mode 100644 testsuite/tests/Ada/decision/MA07-028-expr-context/src/test_t.adb create mode 100644 testsuite/tests/Ada/decision/MA07-028-expr-context/test.py create mode 100644 testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.adb create mode 100644 testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.ads create mode 100644 testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_f.adb create mode 100644 testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_no.adb create mode 100644 testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_t.adb create mode 100644 testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_tf.adb create mode 100644 testsuite/tests/Ada/decision/T922-011-cmp-empty-str/test.py create mode 100644 testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_ft.adb create mode 100644 testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tf.adb create mode 100644 testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tt.adb create mode 100644 testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.adb create mode 100644 testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.ads create mode 100644 testsuite/tests/Ada/mcdc/K118_027-precond_not/test.py create mode 100644 testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.adb create mode 100644 testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.ads create mode 100644 testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/test_fast.adb create mode 100644 testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.opt create mode 100644 testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.py create mode 100644 testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/assert.adb create mode 100644 testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.adb create mode 100644 testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.ads create mode 100644 testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/test_a.adb create mode 100644 testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.opt create mode 100644 testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.py create mode 100644 testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.adb create mode 100644 testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.ads create mode 100644 testsuite/tests/Ada/mcdc/OrElse-O1/src/test_orelse_a.adb create mode 100644 testsuite/tests/Ada/mcdc/OrElse-O1/test.py create mode 100644 testsuite/tests/Ada/stmt/CmpMin/src/in_range.adb create mode 100644 testsuite/tests/Ada/stmt/CmpMin/src/in_range.ali create mode 100644 testsuite/tests/Ada/stmt/CmpMin/src/test_in_range_gtmax.adb create mode 100644 testsuite/tests/Ada/stmt/CmpMin/test.py create mode 100644 testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.adb create mode 100644 testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ads create mode 100644 testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ali create mode 100644 testsuite/tests/Ada/stmt/DeclChain-O1/src/test_flip_0.adb create mode 100644 testsuite/tests/Ada/stmt/DeclChain-O1/test.py create mode 100644 testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.adb create mode 100644 testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.ads create mode 100644 testsuite/tests/Ada/stmt/IncompleteTask/src/test_full.adb create mode 100644 testsuite/tests/Ada/stmt/IncompleteTask/src/test_no.adb create mode 100644 testsuite/tests/Ada/stmt/IncompleteTask/test.opt create mode 100644 testsuite/tests/Ada/stmt/IncompleteTask/test.py create mode 100644 testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.adb create mode 100644 testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.ads create mode 100644 testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/test_flips.adb create mode 100644 testsuite/tests/Ada/stmt/J311_011-lone_return-O1/test.py create mode 100644 testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.adb create mode 100644 testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.ali create mode 100644 testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/test_id0.adb create mode 100644 testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/test.py create mode 100644 testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/inc_by.adb create mode 100644 testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.adb create mode 100644 testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.ads create mode 100644 testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test.opt create mode 100644 testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc.adb create mode 100644 testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc_0.adb create mode 100644 testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_ops_0.adb create mode 100644 testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/test.py create mode 100644 testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.adb create mode 100644 testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.ads create mode 100644 testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/test_ce.adb create mode 100644 testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.opt create mode 100644 testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.py create mode 100644 testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.adb create mode 100644 testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.ads create mode 100644 testsuite/tests/Ada/stmt/K620-028_fold-inline/src/test_fast.adb create mode 100644 testsuite/tests/Ada/stmt/K620-028_fold-inline/test.opt create mode 100644 testsuite/tests/Ada/stmt/K620-028_fold-inline/test.py create mode 100644 testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/mylib.gpr create mode 100644 testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.adb create mode 100644 testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.ads create mode 100644 testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops.ads create mode 100644 testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/src/test_inc.adb create mode 100644 testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.opt create mode 100644 testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.py create mode 100644 testsuite/tests/Ada2012/decision/ForOf/src/test_f.adb create mode 100644 testsuite/tests/Ada2012/decision/ForOf/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/decision/ForOf/src/values.adb create mode 100644 testsuite/tests/Ada2012/decision/ForOf/src/values.ads create mode 100644 testsuite/tests/Ada2012/decision/ForOf/test.py create mode 100644 testsuite/tests/Ada2012/extra.opt create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_f.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/tc.rst create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.opt create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/test_singleop_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.opt create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Invariants/req.rst create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_0.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_a.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_b.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_f.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.opt create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_0.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_f.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.opt create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_a.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_b.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_f.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.opt create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_0.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_f.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.opt create mode 100644 testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/ForOf/src/test_a.adb create mode 100644 testsuite/tests/Ada2012/mcdc/ForOf/src/test_ab.adb create mode 100644 testsuite/tests/Ada2012/mcdc/ForOf/src/test_b.adb create mode 100644 testsuite/tests/Ada2012/mcdc/ForOf/src/test_f.adb create mode 100644 testsuite/tests/Ada2012/mcdc/ForOf/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/ForOf/src/values.adb create mode 100644 testsuite/tests/Ada2012/mcdc/ForOf/src/values.ads create mode 100644 testsuite/tests/Ada2012/mcdc/ForOf/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/expr.ads create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_opa.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_ab_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_b_opa.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opa.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb0.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opfull.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/expr.ads create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/expr.ads create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/expr.ads create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/plus.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_0.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_f.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/plus.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_0.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_f.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.ads create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.ads create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/InOut/src/expr.adb create mode 100644 testsuite/tests/Ada2012/mcdc/InOut/src/expr.ads create mode 100644 testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_f.adb create mode 100644 testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/InOut/src/test_neval.adb create mode 100644 testsuite/tests/Ada2012/mcdc/InOut/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Membership/src/test_f.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Membership/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Membership/src/test_x.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Membership/src/test_y.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Membership/src/values.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Membership/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_a.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_b.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForAll/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_a.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_b.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_a.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_b.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/ForSome/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_a.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_b.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_a.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_b.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_a.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_b.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/test_no.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.opt create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.py create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/expr.ads create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_a.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_f.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_t.adb create mode 100644 testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/test.py create mode 100644 testsuite/tests/Ada2012/status.txt create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_0.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_arg.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_gsa.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values-global.ads create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.ads create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/test.py create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_0.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_arg.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_gsa.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values-global.ads create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.ads create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/PackedArray/test.py create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_0.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_arg.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_gsa.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values-global.ads create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.ads create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/test.py create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_0.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_arg.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_empty.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_gsa.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values-global.ads create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.ads create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/test.py create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.adb create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.ads create mode 100644 testsuite/tests/Ada2012/stmt/ForOf/src/values-global.adb create mode 100644 testsuite/tests/Ada2012/stmt/InOut/src/expr.adb create mode 100644 testsuite/tests/Ada2012/stmt/InOut/src/expr.ads create mode 100644 testsuite/tests/Ada2012/stmt/InOut/src/expr.ali create mode 100644 testsuite/tests/Ada2012/stmt/InOut/src/test_eval_f.adb create mode 100644 testsuite/tests/Ada2012/stmt/InOut/src/test_eval_t.adb create mode 100644 testsuite/tests/Ada2012/stmt/InOut/src/test_neval.adb create mode 100644 testsuite/tests/Ada2012/stmt/InOut/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccFunc/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccProc/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/InParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/NoParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.ads create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/test.py create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_call.adb create mode 100644 testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_no.adb create mode 100644 testsuite/tests/Ada2012/stmt/Xfunctions/src/expr.ads create mode 100644 testsuite/tests/Ada2012/stmt/Xfunctions/src/test_0.adb create mode 100644 testsuite/tests/Ada2012/stmt/Xfunctions/test.py create mode 100644 testsuite/tests/C++/extra.opt create mode 100644 testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.hh create mode 100644 testsuite/tests/C++/mcdc/AandB/As_LambdaValue/test.py create mode 100644 testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.hh create mode 100644 testsuite/tests/C++/mcdc/AandB/In_ClassDef/test.py create mode 100644 testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.hh create mode 100644 testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/test.py create mode 100644 testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.hh create mode 100644 testsuite/tests/C++/mcdc/AandB/In_Ctor/test.py create mode 100644 testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.hh create mode 100644 testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.opt create mode 100644 testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.py create mode 100644 testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.hh create mode 100644 testsuite/tests/C++/mcdc/AandB/In_Dtor/test.py create mode 100644 testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.hh create mode 100644 testsuite/tests/C++/mcdc/AandB/In_ExternC/test.opt create mode 100644 testsuite/tests/C++/mcdc/AandB/In_ExternC/test.py create mode 100644 testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.hh create mode 100644 testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/test.py create mode 100644 testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.hh create mode 100644 testsuite/tests/C++/mcdc/AandB/In_LambdaBody/test.py create mode 100644 testsuite/tests/C++/mcdc/AandB/src/test_tryme_a.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/src/test_tryme_b.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/src/test_tryme_full.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/src/test_tryme_fx.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/src/test_tryme_skip.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/src/test_tryme_tf.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/src/test_tryme_tt.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/src/tryme_api.hh create mode 100644 testsuite/tests/C++/mcdc/AandB/tc_set.rst create mode 100644 testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.cpp create mode 100644 testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.hh create mode 100644 testsuite/tests/C++/stmt/ForRange/WithInit/src/test_0.cpp create mode 100644 testsuite/tests/C++/stmt/ForRange/WithInit/src/test_early_exit.cpp create mode 100644 testsuite/tests/C++/stmt/ForRange/WithInit/src/test_full.cpp create mode 100644 testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.cpp create mode 100644 testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.hh create mode 100644 testsuite/tests/C++/stmt/ForRange/WithInit/test.py create mode 100644 testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.cpp create mode 100644 testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.hh create mode 100644 testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_0.cpp create mode 100644 testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_early_exit.cpp create mode 100644 testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_empty.cpp create mode 100644 testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_full.cpp create mode 100644 testsuite/tests/C++/stmt/ForRange/WithoutInit/test.py create mode 100644 testsuite/tests/C++/stmt/WhileDecl/src/count_digits.cpp create mode 100644 testsuite/tests/C++/stmt/WhileDecl/src/count_digits.hh create mode 100644 testsuite/tests/C++/stmt/WhileDecl/src/test_0.cpp create mode 100644 testsuite/tests/C++/stmt/WhileDecl/src/test_empty.cpp create mode 100644 testsuite/tests/C++/stmt/WhileDecl/src/test_full.cpp create mode 100644 testsuite/tests/C++/stmt/WhileDecl/src/test_nodigit.cpp create mode 100644 testsuite/tests/C++/stmt/WhileDecl/test.py create mode 100644 testsuite/tests/C/decision/CommaExpr/src/cmp.c create mode 100644 testsuite/tests/C/decision/CommaExpr/src/cmp.h create mode 100644 testsuite/tests/C/decision/CommaExpr/src/cmp_internal.c create mode 100644 testsuite/tests/C/decision/CommaExpr/src/cmp_internal.h create mode 100644 testsuite/tests/C/decision/CommaExpr/src/test_0.c create mode 100644 testsuite/tests/C/decision/CommaExpr/src/test_f.c create mode 100644 testsuite/tests/C/decision/CommaExpr/src/test_t.c create mode 100644 testsuite/tests/C/decision/CommaExpr/src/test_tf.c create mode 100644 testsuite/tests/C/decision/CommaExpr/test.py create mode 100644 testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/aligned.c create mode 100644 testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/misc.ads create mode 100644 testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_false.adb create mode 100644 testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_true.adb create mode 100644 testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.opt create mode 100644 testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.py create mode 100644 testsuite/tests/C/extra.opt create mode 100644 testsuite/tests/C/mcdc/CommaExpr/src/cmp.c create mode 100644 testsuite/tests/C/mcdc/CommaExpr/src/cmp.h create mode 100644 testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.c create mode 100644 testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.h create mode 100644 testsuite/tests/C/mcdc/CommaExpr/src/test_0.c create mode 100644 testsuite/tests/C/mcdc/CommaExpr/src/test_f.c create mode 100644 testsuite/tests/C/mcdc/CommaExpr/src/test_t.c create mode 100644 testsuite/tests/C/mcdc/CommaExpr/src/test_tf.c create mode 100644 testsuite/tests/C/mcdc/CommaExpr/test.py create mode 100644 testsuite/tests/C/mcdc/Exemptions/Invalid/main.c create mode 100644 testsuite/tests/C/mcdc/Exemptions/Invalid/test.py create mode 100644 testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.c create mode 100644 testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.h create mode 100644 testsuite/tests/C/mcdc/Exemptions/Nominal/src/test_exemptions.c create mode 100644 testsuite/tests/C/mcdc/Exemptions/Nominal/test.py create mode 100644 testsuite/tests/C/mcdc/Exemptions/extra.opt create mode 100644 testsuite/tests/C/mcdc/Macros/pkg.h create mode 100644 testsuite/tests/C/mcdc/Macros/test.opt create mode 100644 testsuite/tests/C/mcdc/Macros/test.py create mode 100644 testsuite/tests/C/mcdc/Macros/test_macros.c create mode 100644 testsuite/tests/C/mcdc/Macros/test_macros.c.xcov.expected create mode 100644 testsuite/tests/C/mcdc/include-current-dir/pkg.c create mode 100644 testsuite/tests/C/mcdc/include-current-dir/pkg.h create mode 100644 testsuite/tests/C/mcdc/include-current-dir/test.c create mode 100644 testsuite/tests/C/mcdc/include-current-dir/test.py create mode 100644 testsuite/tests/C/mcdc/misc/src/aligned.c create mode 100644 testsuite/tests/C/mcdc/misc/src/misc.ads create mode 100644 testsuite/tests/C/mcdc/misc/src/test_aligned_x.adb create mode 100644 testsuite/tests/C/mcdc/misc/test.py create mode 100644 testsuite/tests/C/stmt/NA28-015-default-return/calc.c create mode 100644 testsuite/tests/C/stmt/NA28-015-default-return/process.c create mode 100644 testsuite/tests/C/stmt/NA28-015-default-return/process.h create mode 100644 testsuite/tests/C/stmt/NA28-015-default-return/test.opt create mode 100644 testsuite/tests/C/stmt/NA28-015-default-return/test.py create mode 100644 testsuite/tests/Disassemblers/arm_be/symbolization.baseline create mode 100644 testsuite/tests/Disassemblers/arm_be/symbolization.s create mode 100644 testsuite/tests/Disassemblers/arm_le/symbolization.baseline create mode 100644 testsuite/tests/Disassemblers/arm_le/symbolization.s create mode 100644 testsuite/tests/Disassemblers/disaconv.py create mode 100644 testsuite/tests/Disassemblers/leon/symbolization.baseline create mode 100644 testsuite/tests/Disassemblers/leon/symbolization.s create mode 100644 testsuite/tests/Disassemblers/lmp/symbolization.baseline create mode 100644 testsuite/tests/Disassemblers/lmp/symbolization.s create mode 100644 testsuite/tests/Disassemblers/ppc_be/symbolization.baseline create mode 100644 testsuite/tests/Disassemblers/ppc_be/symbolization.s create mode 100644 testsuite/tests/Disassemblers/ppc_le/symbolization.baseline create mode 100644 testsuite/tests/Disassemblers/ppc_le/symbolization.s create mode 100644 testsuite/tests/Disassemblers/test.py create mode 100644 testsuite/tests/Disassemblers/thumb_be/symbolization.baseline create mode 100644 testsuite/tests/Disassemblers/thumb_be/symbolization.s create mode 100644 testsuite/tests/Disassemblers/thumb_le/symbolization.baseline create mode 100644 testsuite/tests/Disassemblers/thumb_le/symbolization.s create mode 100644 testsuite/tests/Disassemblers/x86/symbolization.baseline create mode 100644 testsuite/tests/Disassemblers/x86/symbolization.s create mode 100644 testsuite/tests/Disassemblers/x86_64/symbolization.baseline create mode 100644 testsuite/tests/Disassemblers/x86_64/symbolization.s create mode 100644 testsuite/tests/FullRuntime/Barrier/src/buffer.adb create mode 100644 testsuite/tests/FullRuntime/Barrier/src/buffer.ads create mode 100644 testsuite/tests/FullRuntime/Barrier/src/test_pop.adb create mode 100644 testsuite/tests/FullRuntime/Barrier/src/test_pop_push_pop.adb create mode 100644 testsuite/tests/FullRuntime/Barrier/src/test_push.adb create mode 100644 testsuite/tests/FullRuntime/Barrier/src/test_push_push_pop.adb create mode 100644 testsuite/tests/FullRuntime/Barrier/test.opt create mode 100644 testsuite/tests/FullRuntime/Barrier/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/src/ops.ads create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/src/test_0.adb create mode 100644 testsuite/tests/FullRuntime/stmt/Entries/src/test_ops_and_tt.adb create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/src/ops.adb create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.opt create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.py create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/ops.ads create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_0.adb create mode 100644 testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_ops_and_tt.adb create mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/check_g.adb create mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/check_g.ads create mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.adb create mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.ads create mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cbfn.adb create mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifn.adb create mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifo.adb create mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfn.adb create mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfo.adb create mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/tc.txt create mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/test.opt create mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/test.py create mode 100644 testsuite/tests/Generics/Mode_Variants_STMT/src/test_v5_reset.adb create mode 100644 testsuite/tests/Generics/Mode_Variants_STMT/src/v5.ads create mode 100644 testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.adb create mode 100644 testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.ads create mode 100644 testsuite/tests/Generics/Mode_Variants_STMT/test.opt create mode 100644 testsuite/tests/Generics/Mode_Variants_STMT/test.py create mode 100644 testsuite/tests/HA16-013_cleanups/src/assert.adb create mode 100644 testsuite/tests/HA16-013_cleanups/src/p1.adb create mode 100644 testsuite/tests/HA16-013_cleanups/src/p2.adb create mode 100644 testsuite/tests/HA16-013_cleanups/src/test_blobs.adb create mode 100644 testsuite/tests/HA16-013_cleanups/src/vars.adb create mode 100644 testsuite/tests/HA16-013_cleanups/src/vars.ads create mode 100644 testsuite/tests/HA16-013_cleanups/test.opt create mode 100644 testsuite/tests/HA16-013_cleanups/test.py create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.opt create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.py create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_1.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_2.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test.py create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_1.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_2.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test.py create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_1.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_2.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/target.txt create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test.py create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_1.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_2.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_3.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test.py create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_1.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_2.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test.py create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_1.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_2.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test.py create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_1.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_2.c create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/target.txt create mode 100644 testsuite/tests/HomonymSymbols/ObjectCoverage/extra.opt create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/cons_all.txt create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_12.c create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_13.c create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/test.py create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/scos.list create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.opt create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.py create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_1.c create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_2.c create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/cons_all.txt create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_1.c create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_2.c create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/test.py create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_full.c create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_no.c create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_partial.c create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/test.py create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/cons_all.txt create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_1.c create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_2.c create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/test.py create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/cons_all.txt create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_1.c create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_2.c create mode 100644 testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/test.py create mode 100644 testsuite/tests/HomonymSymbols/extra.opt create mode 100644 testsuite/tests/HomonymSymbols/src/double.c create mode 100644 testsuite/tests/HomonymSymbols/src/double.h create mode 100644 testsuite/tests/HomonymSymbols/src/fact.c create mode 100644 testsuite/tests/HomonymSymbols/src/fact.h create mode 100644 testsuite/tests/HomonymSymbols/src/not.c create mode 100644 testsuite/tests/HomonymSymbols/src/not.h create mode 100644 testsuite/tests/HomonymSymbols/src/sum.c create mode 100644 testsuite/tests/HomonymSymbols/src/sum.h create mode 100644 testsuite/tests/HomonymSymbols/src/support.h create mode 100644 testsuite/tests/I401-009/src/engines.adb create mode 100644 testsuite/tests/I401-009/src/engines.ads create mode 100644 testsuite/tests/I401-009/src/test_engines.adb create mode 100644 testsuite/tests/I401-009/test.opt create mode 100644 testsuite/tests/I401-009/test.py create mode 100644 testsuite/tests/I427-029/src/assert.adb create mode 100644 testsuite/tests/I427-029/src/engines.adb create mode 100644 testsuite/tests/I427-029/src/engines.ads create mode 100644 testsuite/tests/I427-029/src/test_engines_mm.adb create mode 100644 testsuite/tests/I427-029/src/test_engines_mp.adb create mode 100644 testsuite/tests/I427-029/src/test_engines_pm.adb create mode 100644 testsuite/tests/I427-029/src/test_engines_pp.adb create mode 100644 testsuite/tests/I427-029/test.opt create mode 100644 testsuite/tests/I427-029/test.py create mode 100644 testsuite/tests/I505-018/src/services.adb create mode 100644 testsuite/tests/I505-018/src/services.ads create mode 100644 testsuite/tests/I505-018/src/test_services.adb create mode 100644 testsuite/tests/I505-018/test.py create mode 100644 testsuite/tests/I511-019-response-files/src/bar.adb create mode 100644 testsuite/tests/I511-019-response-files/src/bar.ads create mode 100644 testsuite/tests/I511-019-response-files/src/foo.adb create mode 100644 testsuite/tests/I511-019-response-files/src/test_foobar.adb create mode 100644 testsuite/tests/I511-019-response-files/test.py create mode 100644 testsuite/tests/I512-020/ppcstart.elf create mode 100644 testsuite/tests/I512-020/test.opt create mode 100644 testsuite/tests/I512-020/test.py create mode 100644 testsuite/tests/I519-015/func.list create mode 100644 testsuite/tests/I519-015/min.adb create mode 100644 testsuite/tests/I519-015/min.ads create mode 100644 testsuite/tests/I519-015/test.opt create mode 100644 testsuite/tests/I519-015/test.py create mode 100644 testsuite/tests/I519-015/test_min.adb create mode 100644 testsuite/tests/I519-015/test_min1.adb create mode 100644 testsuite/tests/I519-015/test_min2.adb create mode 100644 testsuite/tests/I519-030/src/kops.adb create mode 100644 testsuite/tests/I519-030/src/kops.ads create mode 100644 testsuite/tests/I519-030/src/ops4.ads create mode 100644 testsuite/tests/I519-030/src/ops8.ads create mode 100644 testsuite/tests/I519-030/src/test_kops.adb create mode 100644 testsuite/tests/I519-030/src/vars.adb create mode 100644 testsuite/tests/I519-030/src/vars.ads create mode 100644 testsuite/tests/I519-030/test.opt create mode 100644 testsuite/tests/I519-030/test.py create mode 100644 testsuite/tests/I522-010/src/volp.adb create mode 100644 testsuite/tests/I522-010/test.opt create mode 100644 testsuite/tests/I522-010/test.py create mode 100644 testsuite/tests/I715-012/src/monitor.adb create mode 100644 testsuite/tests/I715-012/src/monitor.ads create mode 100644 testsuite/tests/I715-012/src/p.adb create mode 100644 testsuite/tests/I715-012/src/pack.adb create mode 100644 testsuite/tests/I715-012/src/pack.ads create mode 100644 testsuite/tests/I715-012/test.opt create mode 100644 testsuite/tests/I715-012/test.py create mode 100644 testsuite/tests/I716-009/func.list create mode 100644 testsuite/tests/I716-009/min.ads create mode 100644 testsuite/tests/I716-009/min_asm.s create mode 100644 testsuite/tests/I716-009/test.opt create mode 100644 testsuite/tests/I716-009/test.py create mode 100644 testsuite/tests/I716-009/test_min.adb create mode 100644 testsuite/tests/I716-021/src/p.adb create mode 100644 testsuite/tests/I716-021/src/p.ads create mode 100644 testsuite/tests/I716-021/src/test_p.adb create mode 100644 testsuite/tests/I716-021/test.opt create mode 100644 testsuite/tests/I716-021/test.py create mode 100644 testsuite/tests/I717-018/explore.list create mode 100644 testsuite/tests/I717-018/src/actors.adb create mode 100644 testsuite/tests/I717-018/src/actors.ads create mode 100644 testsuite/tests/I717-018/src/controls.ads create mode 100644 testsuite/tests/I717-018/src/explore.adb create mode 100644 testsuite/tests/I717-018/src/geomaps.adb create mode 100644 testsuite/tests/I717-018/src/geomaps.ads create mode 100644 testsuite/tests/I717-018/src/links.adb create mode 100644 testsuite/tests/I717-018/src/links.ads create mode 100644 testsuite/tests/I717-018/src/overview.ads create mode 100644 testsuite/tests/I717-018/src/queues.adb create mode 100644 testsuite/tests/I717-018/src/queues.ads create mode 100644 testsuite/tests/I717-018/src/robots.adb create mode 100644 testsuite/tests/I717-018/src/robots.ads create mode 100644 testsuite/tests/I717-018/src/robots_devices-dummy.adb create mode 100644 testsuite/tests/I717-018/src/robots_devices-dummy.ads create mode 100644 testsuite/tests/I717-018/src/robots_devices.ads create mode 100644 testsuite/tests/I717-018/src/stacks.adb create mode 100644 testsuite/tests/I717-018/src/stacks.ads create mode 100644 testsuite/tests/I717-018/src/stations.adb create mode 100644 testsuite/tests/I717-018/src/stations.ads create mode 100644 testsuite/tests/I717-018/test.opt create mode 100644 testsuite/tests/I717-018/test.py create mode 100644 testsuite/tests/I812-011/main.adb create mode 100644 testsuite/tests/I812-011/test.py create mode 100644 testsuite/tests/I914-023/src/robots.adb create mode 100644 testsuite/tests/I914-023/src/robots.ads create mode 100644 testsuite/tests/I914-023/src/test_robots.adb create mode 100644 testsuite/tests/I914-023/test.opt create mode 100644 testsuite/tests/I914-023/test.py create mode 100755 testsuite/tests/I914-023/test_robots create mode 100644 testsuite/tests/I930-009-ppc-beq-bt-x2/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beq-bt-x2/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beq-bt-x2/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beq-bt-x2/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beq-bt-x2/test.py create mode 100755 testsuite/tests/I930-009-ppc-beq-bt-x2/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beq-bt-x2/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beq-bt/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beq-bt/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beq-bt/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beq-bt/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beq-bt/test.py create mode 100755 testsuite/tests/I930-009-ppc-beq-bt/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beq-bt/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beq-ft-x2/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beq-ft-x2/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beq-ft-x2/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beq-ft-x2/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beq-ft-x2/test.py create mode 100755 testsuite/tests/I930-009-ppc-beq-ft-x2/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beq-ft-x2/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beq-ft/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beq-ft/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beq-ft/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beq-ft/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beq-ft/test.py create mode 100755 testsuite/tests/I930-009-ppc-beq-ft/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beq-ft/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-bt/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-bt/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-bt/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-bt/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-bt/test.py create mode 100755 testsuite/tests/I930-009-ppc-beq-npg-bt/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-bt/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-ft/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-ft/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-ft/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-ft/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-ft/test.py create mode 100755 testsuite/tests/I930-009-ppc-beq-npg-ft/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-ft/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-tk/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-tk/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-tk/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-tk/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-tk/test.py create mode 100755 testsuite/tests/I930-009-ppc-beq-npg-tk/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beq-npg-tk/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beq-nt/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beq-nt/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beq-nt/src/get_false.adb create mode 100644 testsuite/tests/I930-009-ppc-beq-nt/src/get_false.ads create mode 100644 testsuite/tests/I930-009-ppc-beq-nt/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beq-nt/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beq-nt/test.py create mode 100755 testsuite/tests/I930-009-ppc-beq-nt/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beq-nt/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beq-tb-x2/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beq-tb-x2/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beq-tb-x2/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beq-tb-x2/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beq-tb-x2/test.py create mode 100755 testsuite/tests/I930-009-ppc-beq-tb-x2/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beq-tb-x2/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beq-tb/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beq-tb/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beq-tb/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beq-tb/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beq-tb/test.py create mode 100755 testsuite/tests/I930-009-ppc-beq-tb/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beq-tb/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beq-tk-x2/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beq-tk-x2/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beq-tk-x2/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beq-tk-x2/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beq-tk-x2/test.py create mode 100755 testsuite/tests/I930-009-ppc-beq-tk-x2/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beq-tk-x2/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beq-tk/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beq-tk/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beq-tk/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beq-tk/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beq-tk/test.py create mode 100755 testsuite/tests/I930-009-ppc-beq-tk/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beq-tk/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beqlr-bt/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beqlr-bt/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beqlr-bt/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beqlr-bt/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beqlr-bt/test.py create mode 100755 testsuite/tests/I930-009-ppc-beqlr-bt/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beqlr-bt/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beqlr-ft/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beqlr-ft/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beqlr-ft/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beqlr-ft/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beqlr-ft/test.py create mode 100755 testsuite/tests/I930-009-ppc-beqlr-ft/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beqlr-ft/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beqlr-tb/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beqlr-tb/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beqlr-tb/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beqlr-tb/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beqlr-tb/test.py create mode 100755 testsuite/tests/I930-009-ppc-beqlr-tb/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beqlr-tb/test_cond.gpr create mode 100644 testsuite/tests/I930-009-ppc-beqlr-tk/gnu.ld create mode 100644 testsuite/tests/I930-009-ppc-beqlr-tk/src/cond.s create mode 100644 testsuite/tests/I930-009-ppc-beqlr-tk/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-ppc-beqlr-tk/test.opt create mode 100644 testsuite/tests/I930-009-ppc-beqlr-tk/test.py create mode 100755 testsuite/tests/I930-009-ppc-beqlr-tk/test_cond create mode 100644 testsuite/tests/I930-009-ppc-beqlr-tk/test_cond.gpr create mode 100644 testsuite/tests/I930-009-sparc-be-a-ft/src/cond.c create mode 100644 testsuite/tests/I930-009-sparc-be-a-ft/src/cond.s create mode 100644 testsuite/tests/I930-009-sparc-be-a-ft/src/last_chance_handler.adb create mode 100644 testsuite/tests/I930-009-sparc-be-a-ft/src/last_chance_handler.ads create mode 100644 testsuite/tests/I930-009-sparc-be-a-ft/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-sparc-be-a-ft/test.opt create mode 100644 testsuite/tests/I930-009-sparc-be-a-ft/test.py create mode 100755 testsuite/tests/I930-009-sparc-be-a-ft/test_cond create mode 100644 testsuite/tests/I930-009-sparc-be-a-ft/test_cond.gpr create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.c create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.s create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.adb create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.ads create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-ft/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-ft/test.opt create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-ft/test.py create mode 100755 testsuite/tests/I930-009-sparc-be-a-npg-ft/test_cond create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-ft/test_cond.gpr create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.c create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.s create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.adb create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.ads create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-tk/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-tk/test.opt create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-tk/test.py create mode 100755 testsuite/tests/I930-009-sparc-be-a-npg-tk/test_cond create mode 100644 testsuite/tests/I930-009-sparc-be-a-npg-tk/test_cond.gpr create mode 100644 testsuite/tests/I930-009-sparc-be-a-nt/src/cond.c create mode 100644 testsuite/tests/I930-009-sparc-be-a-nt/src/cond.s create mode 100644 testsuite/tests/I930-009-sparc-be-a-nt/src/last_chance_handler.adb create mode 100644 testsuite/tests/I930-009-sparc-be-a-nt/src/last_chance_handler.ads create mode 100644 testsuite/tests/I930-009-sparc-be-a-nt/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-sparc-be-a-nt/test.opt create mode 100644 testsuite/tests/I930-009-sparc-be-a-nt/test.py create mode 100755 testsuite/tests/I930-009-sparc-be-a-nt/test_cond create mode 100644 testsuite/tests/I930-009-sparc-be-a-nt/test_cond.gpr create mode 100644 testsuite/tests/I930-009-sparc-be-a-tk/src/cond.c create mode 100644 testsuite/tests/I930-009-sparc-be-a-tk/src/cond.s create mode 100644 testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.adb create mode 100644 testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.ads create mode 100644 testsuite/tests/I930-009-sparc-be-a-tk/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-sparc-be-a-tk/test.opt create mode 100644 testsuite/tests/I930-009-sparc-be-a-tk/test.py create mode 100755 testsuite/tests/I930-009-sparc-be-a-tk/test_cond create mode 100644 testsuite/tests/I930-009-sparc-be-a-tk/test_cond.gpr create mode 100644 testsuite/tests/I930-009-sparc-be-bt/src/cond.c create mode 100644 testsuite/tests/I930-009-sparc-be-bt/src/cond.s create mode 100644 testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.adb create mode 100644 testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.ads create mode 100644 testsuite/tests/I930-009-sparc-be-bt/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-sparc-be-bt/test.opt create mode 100644 testsuite/tests/I930-009-sparc-be-bt/test.py create mode 100755 testsuite/tests/I930-009-sparc-be-bt/test_cond create mode 100644 testsuite/tests/I930-009-sparc-be-bt/test_cond.gpr create mode 100644 testsuite/tests/I930-009-sparc-be-ft/src/cond.c create mode 100644 testsuite/tests/I930-009-sparc-be-ft/src/cond.s create mode 100644 testsuite/tests/I930-009-sparc-be-ft/src/last_chance_handler.adb create mode 100644 testsuite/tests/I930-009-sparc-be-ft/src/last_chance_handler.ads create mode 100644 testsuite/tests/I930-009-sparc-be-ft/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-sparc-be-ft/test.opt create mode 100644 testsuite/tests/I930-009-sparc-be-ft/test.py create mode 100755 testsuite/tests/I930-009-sparc-be-ft/test_cond create mode 100644 testsuite/tests/I930-009-sparc-be-ft/test_cond.gpr create mode 100644 testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.c create mode 100644 testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.s create mode 100644 testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.adb create mode 100644 testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.ads create mode 100644 testsuite/tests/I930-009-sparc-be-npg-bt/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-sparc-be-npg-bt/test.opt create mode 100644 testsuite/tests/I930-009-sparc-be-npg-bt/test.py create mode 100755 testsuite/tests/I930-009-sparc-be-npg-bt/test_cond create mode 100644 testsuite/tests/I930-009-sparc-be-npg-bt/test_cond.gpr create mode 100644 testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.c create mode 100644 testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.s create mode 100644 testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.adb create mode 100644 testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.ads create mode 100644 testsuite/tests/I930-009-sparc-be-npg-ft/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-sparc-be-npg-ft/test.opt create mode 100644 testsuite/tests/I930-009-sparc-be-npg-ft/test.py create mode 100755 testsuite/tests/I930-009-sparc-be-npg-ft/test_cond create mode 100644 testsuite/tests/I930-009-sparc-be-npg-ft/test_cond.gpr create mode 100644 testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.c create mode 100644 testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.s create mode 100644 testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.adb create mode 100644 testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.ads create mode 100644 testsuite/tests/I930-009-sparc-be-npg-tk/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-sparc-be-npg-tk/test.opt create mode 100644 testsuite/tests/I930-009-sparc-be-npg-tk/test.py create mode 100755 testsuite/tests/I930-009-sparc-be-npg-tk/test_cond create mode 100644 testsuite/tests/I930-009-sparc-be-npg-tk/test_cond.gpr create mode 100644 testsuite/tests/I930-009-sparc-be-nt/src/cond.c create mode 100644 testsuite/tests/I930-009-sparc-be-nt/src/cond.s create mode 100644 testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.adb create mode 100644 testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.ads create mode 100644 testsuite/tests/I930-009-sparc-be-nt/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-sparc-be-nt/test.opt create mode 100644 testsuite/tests/I930-009-sparc-be-nt/test.py create mode 100755 testsuite/tests/I930-009-sparc-be-nt/test_cond create mode 100644 testsuite/tests/I930-009-sparc-be-nt/test_cond.gpr create mode 100644 testsuite/tests/I930-009-sparc-be-tk/src/cond.c create mode 100644 testsuite/tests/I930-009-sparc-be-tk/src/cond.s create mode 100644 testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.adb create mode 100644 testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.ads create mode 100644 testsuite/tests/I930-009-sparc-be-tk/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-sparc-be-tk/test.opt create mode 100644 testsuite/tests/I930-009-sparc-be-tk/test.py create mode 100755 testsuite/tests/I930-009-sparc-be-tk/test_cond create mode 100644 testsuite/tests/I930-009-sparc-be-tk/test_cond.gpr create mode 100644 testsuite/tests/I930-009-sparc-cross-boundary/src/cond.c create mode 100644 testsuite/tests/I930-009-sparc-cross-boundary/src/cond.s create mode 100644 testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.adb create mode 100644 testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.ads create mode 100644 testsuite/tests/I930-009-sparc-cross-boundary/src/test_cond.adb create mode 100644 testsuite/tests/I930-009-sparc-cross-boundary/test.opt create mode 100644 testsuite/tests/I930-009-sparc-cross-boundary/test.py create mode 100755 testsuite/tests/I930-009-sparc-cross-boundary/test_cond create mode 100644 testsuite/tests/I930-009-sparc-cross-boundary/test_cond.gpr create mode 100644 testsuite/tests/I930-019/src/kops.adb create mode 100644 testsuite/tests/I930-019/src/kops.ads create mode 100644 testsuite/tests/I930-019/src/ops4.ads create mode 100644 testsuite/tests/I930-019/src/ops8.ads create mode 100644 testsuite/tests/I930-019/src/test_kops.adb create mode 100644 testsuite/tests/I930-019/src/vars.adb create mode 100644 testsuite/tests/I930-019/src/vars.ads create mode 100644 testsuite/tests/I930-019/test.py create mode 100644 testsuite/tests/IA01-015/src/monitor.adb create mode 100644 testsuite/tests/IA01-015/src/monitor.ads create mode 100644 testsuite/tests/IA01-015/src/trymon.adb create mode 100644 testsuite/tests/IA01-015/test.py create mode 100644 testsuite/tests/IA06-008-override-exec/src/noop.adb create mode 100644 testsuite/tests/IA06-008-override-exec/test.opt create mode 100644 testsuite/tests/IA06-008-override-exec/test.py create mode 100644 testsuite/tests/IA06-009-offset-from-sym/src/p.adb create mode 100644 testsuite/tests/IA06-009-offset-from-sym/test.opt create mode 100644 testsuite/tests/IA06-009-offset-from-sym/test.py create mode 100644 testsuite/tests/IA09-021-unit-nosco/src/checks.adb create mode 100644 testsuite/tests/IA09-021-unit-nosco/src/checks.ads create mode 100644 testsuite/tests/IA09-021-unit-nosco/src/test_assert.adb create mode 100644 testsuite/tests/IA09-021-unit-nosco/test.opt create mode 100644 testsuite/tests/IA09-021-unit-nosco/test.py create mode 100644 testsuite/tests/IA13-015-loop-body/src/for_loop.adb create mode 100644 testsuite/tests/IA13-015-loop-body/test.opt create mode 100644 testsuite/tests/IA13-015-loop-body/test.py create mode 100644 testsuite/tests/IA16-028-disp-routines/baseline3.txt create mode 100644 testsuite/tests/IA16-028-disp-routines/src/monitor.adb create mode 100644 testsuite/tests/IA16-028-disp-routines/src/monitor.ads create mode 100644 testsuite/tests/IA16-028-disp-routines/src/p.adb create mode 100644 testsuite/tests/IA16-028-disp-routines/src/pack.adb create mode 100644 testsuite/tests/IA16-028-disp-routines/src/pack.ads create mode 100644 testsuite/tests/IA16-028-disp-routines/test.py create mode 100644 testsuite/tests/IA19-009-no-useless-srcs/src/engines.adb create mode 100644 testsuite/tests/IA19-009-no-useless-srcs/src/engines.ads create mode 100644 testsuite/tests/IA19-009-no-useless-srcs/src/test_engines.adb create mode 100644 testsuite/tests/IA19-009-no-useless-srcs/test.py create mode 100644 testsuite/tests/IA21-003-simple-decision-sco/src/p.adb create mode 100644 testsuite/tests/IA21-003-simple-decision-sco/src/pack.adb create mode 100644 testsuite/tests/IA21-003-simple-decision-sco/src/pack.ads create mode 100644 testsuite/tests/IA21-003-simple-decision-sco/test.opt create mode 100644 testsuite/tests/IA21-003-simple-decision-sco/test.py create mode 100644 testsuite/tests/IA21-009-nested-scos/src/nested_same_sloc.adb create mode 100644 testsuite/tests/IA21-009-nested-scos/test.py create mode 100644 testsuite/tests/IA22-004-same-basename/.gitignore create mode 100644 testsuite/tests/IA22-004-same-basename/d1/func.c create mode 100644 testsuite/tests/IA22-004-same-basename/d2/func.c create mode 100644 testsuite/tests/IA22-004-same-basename/main.c create mode 100755 testsuite/tests/IA22-004-same-basename/main.elf create mode 100644 testsuite/tests/IA22-004-same-basename/put.adb create mode 100644 testsuite/tests/IA22-004-same-basename/put.ads create mode 100644 testsuite/tests/IA22-004-same-basename/repro.adb create mode 100644 testsuite/tests/IA22-004-same-basename/test.opt create mode 100644 testsuite/tests/IA22-004-same-basename/test.py create mode 100644 testsuite/tests/IA29-020-basic-checks/src/engines.adb create mode 100644 testsuite/tests/IA29-020-basic-checks/src/engines.ads create mode 100644 testsuite/tests/IA29-020-basic-checks/src/test_engines.adb create mode 100644 testsuite/tests/IA29-020-basic-checks/test.opt create mode 100644 testsuite/tests/IA29-020-basic-checks/test.py create mode 100644 testsuite/tests/IA29-023-source-search/src/engines.adb create mode 100644 testsuite/tests/IA29-023-source-search/src/engines.ads create mode 100644 testsuite/tests/IA29-023-source-search/src/test_engines.adb create mode 100644 testsuite/tests/IA29-023-source-search/test.py create mode 100644 testsuite/tests/J618-019-disa-x86/insn.o create mode 100644 testsuite/tests/J618-019-disa-x86/insn.s create mode 100644 testsuite/tests/J618-019-disa-x86/test.opt create mode 100644 testsuite/tests/J618-019-disa-x86/test.py create mode 100644 testsuite/tests/J723-017-empty-debug-info/ada_containers-aunit_lists.elf create mode 100644 testsuite/tests/J723-017-empty-debug-info/test.opt create mode 100644 testsuite/tests/J723-017-empty-debug-info/test.py create mode 100644 testsuite/tests/JC09-015-set-file/hello.o create mode 100644 testsuite/tests/JC09-015-set-file/hello.s create mode 100644 testsuite/tests/JC09-015-set-file/test.opt create mode 100644 testsuite/tests/JC09-015-set-file/test.py create mode 100644 testsuite/tests/K214-014-gc-sections/src/foo.adb create mode 100644 testsuite/tests/K214-014-gc-sections/src/pck.adb create mode 100644 testsuite/tests/K214-014-gc-sections/src/pck.ads create mode 100644 testsuite/tests/K214-014-gc-sections/test.opt create mode 100644 testsuite/tests/K214-014-gc-sections/test.py create mode 100644 testsuite/tests/K317-011_raven-textio/src/test_textio.adb create mode 100644 testsuite/tests/K317-011_raven-textio/test.opt create mode 100644 testsuite/tests/K317-011_raven-textio/test.py create mode 100644 testsuite/tests/K804-031_raise-taken/src/args.adb create mode 100644 testsuite/tests/K804-031_raise-taken/src/args.ads create mode 100644 testsuite/tests/K804-031_raise-taken/src/test_val_ce.adb create mode 100644 testsuite/tests/K804-031_raise-taken/src/test_vif_r.adb create mode 100644 testsuite/tests/K804-031_raise-taken/src/test_vif_rf.adb create mode 100644 testsuite/tests/K804-031_raise-taken/src/test_vif_rt.adb create mode 100644 testsuite/tests/K804-031_raise-taken/src/test_vifn_r.adb create mode 100644 testsuite/tests/K804-031_raise-taken/src/test_vifn_rf.adb create mode 100644 testsuite/tests/K804-031_raise-taken/src/test_vifn_rt.adb create mode 100644 testsuite/tests/K804-031_raise-taken/src/val.adb create mode 100644 testsuite/tests/K804-031_raise-taken/src/val.ads create mode 100644 testsuite/tests/K804-031_raise-taken/src/vif.adb create mode 100644 testsuite/tests/K804-031_raise-taken/src/vif.ads create mode 100644 testsuite/tests/K804-031_raise-taken/src/vifn.adb create mode 100644 testsuite/tests/K804-031_raise-taken/src/vifn.ads create mode 100644 testsuite/tests/K804-031_raise-taken/test.py create mode 100644 testsuite/tests/KB30-011-eargs-gnatemu/myinc.adb create mode 100644 testsuite/tests/KB30-011-eargs-gnatemu/test.opt create mode 100644 testsuite/tests/KB30-011-eargs-gnatemu/test.py create mode 100644 testsuite/tests/KC06-023-list_as_ali/plist create mode 100644 testsuite/tests/KC06-023-list_as_ali/src/p.adb create mode 100644 testsuite/tests/KC06-023-list_as_ali/test.py create mode 100644 testsuite/tests/KC23-012-ocov-exemptions/p.adb create mode 100644 testsuite/tests/KC23-012-ocov-exemptions/test.opt create mode 100644 testsuite/tests/KC23-012-ocov-exemptions/test.py create mode 100644 testsuite/tests/L112-050-pro-through-disabled/src/dom_debug.adb create mode 100644 testsuite/tests/L112-050-pro-through-disabled/test.py create mode 100644 testsuite/tests/L209-010-asm-outfile/src/plop.adb create mode 100644 testsuite/tests/L209-010-asm-outfile/test.opt create mode 100644 testsuite/tests/L209-010-asm-outfile/test.py create mode 100644 testsuite/tests/L411-031_missing_gnateS/src/checks.adb create mode 100644 testsuite/tests/L411-031_missing_gnateS/src/checks.ads create mode 100644 testsuite/tests/L411-031_missing_gnateS/src/test_assert.adb create mode 100644 testsuite/tests/L411-031_missing_gnateS/test.opt create mode 100644 testsuite/tests/L411-031_missing_gnateS/test.py create mode 100644 testsuite/tests/L613-012/app.gpr create mode 100644 testsuite/tests/L613-012/pak1.ads create mode 100644 testsuite/tests/L613-012/test.py create mode 100644 testsuite/tests/L619-040-output-to-objdir/pgm.adb create mode 100644 testsuite/tests/L619-040-output-to-objdir/test.py create mode 100644 testsuite/tests/L707-006-src-in-cwd/engines.adb create mode 100644 testsuite/tests/L707-006-src-in-cwd/engines.ads create mode 100644 testsuite/tests/L707-006-src-in-cwd/test.opt create mode 100644 testsuite/tests/L707-006-src-in-cwd/test.py create mode 100644 testsuite/tests/L707-006-src-in-cwd/test_engines.adb create mode 100644 testsuite/tests/L929-006/leon-elf-emptys.s create mode 100644 testsuite/tests/L929-006/leon-elf-expected.out create mode 100644 testsuite/tests/L929-006/leon-elf-orphans.s create mode 100644 testsuite/tests/L929-006/powerpc-elf-emptys.s create mode 100644 testsuite/tests/L929-006/powerpc-elf-expected.out create mode 100644 testsuite/tests/L929-006/powerpc-elf-orphans.s create mode 100644 testsuite/tests/L929-006/test.opt create mode 100644 testsuite/tests/L929-006/test.py create mode 100644 testsuite/tests/LA17-032-scan-decisions/expected.out create mode 100644 testsuite/tests/LA17-032-scan-decisions/p.adb create mode 100644 testsuite/tests/LA17-032-scan-decisions/state.ads create mode 100644 testsuite/tests/LA17-032-scan-decisions/test.opt create mode 100644 testsuite/tests/LA17-032-scan-decisions/test.py create mode 100644 testsuite/tests/LA23-016_eargs-exe/src/myabs.adb create mode 100644 testsuite/tests/LA23-016_eargs-exe/src/p.adb create mode 100644 testsuite/tests/LA23-016_eargs-exe/test.opt create mode 100644 testsuite/tests/LA23-016_eargs-exe/test.py create mode 100644 testsuite/tests/LB13-031-post-aspect/src/orelse.ads create mode 100644 testsuite/tests/LB13-031-post-aspect/src/passor.adb create mode 100644 testsuite/tests/LB13-031-post-aspect/src/passor.ads create mode 100644 testsuite/tests/LB13-031-post-aspect/src/test_passor_0.adb create mode 100644 testsuite/tests/LB13-031-post-aspect/src/test_passor_ff.adb create mode 100644 testsuite/tests/LB13-031-post-aspect/src/test_passor_ft.adb create mode 100644 testsuite/tests/LB13-031-post-aspect/src/test_passor_fu.adb create mode 100644 testsuite/tests/LB13-031-post-aspect/src/test_passor_tx.adb create mode 100644 testsuite/tests/LB13-031-post-aspect/tc.txt create mode 100644 testsuite/tests/LB13-031-post-aspect/test.opt create mode 100644 testsuite/tests/LB13-031-post-aspect/test.py create mode 100644 testsuite/tests/LB15-031-split-PPC-aspect/src/andthen.ads create mode 100644 testsuite/tests/LB15-031-split-PPC-aspect/src/passand.adb create mode 100644 testsuite/tests/LB15-031-split-PPC-aspect/src/passand.ads create mode 100644 testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_0.adb create mode 100644 testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fu.adb create mode 100644 testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fx.adb create mode 100644 testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tf.adb create mode 100644 testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tt.adb create mode 100644 testsuite/tests/LB15-031-split-PPC-aspect/tc.txt create mode 100644 testsuite/tests/LB15-031-split-PPC-aspect/test.opt create mode 100644 testsuite/tests/LB15-031-split-PPC-aspect/test.py create mode 100644 testsuite/tests/LibExp/.gitignore create mode 100644 testsuite/tests/LibExp/AndXY/src/test_computing_v0.adb create mode 100644 testsuite/tests/LibExp/AndXY/src/test_computing_v02.adb create mode 100644 testsuite/tests/LibExp/AndXY/src/test_computing_v03.adb create mode 100644 testsuite/tests/LibExp/AndXY/src/test_computing_v23.adb create mode 100644 testsuite/tests/LibExp/extra.opt create mode 100644 testsuite/tests/LibExp/group.py create mode 100644 testsuite/tests/LibExp/set.txt create mode 100644 testsuite/tests/LibExp/src/support.h create mode 100644 testsuite/tests/M204-037-dc-in-aggregate/src/assert.adb create mode 100644 testsuite/tests/M204-037-dc-in-aggregate/src/test_1.adb create mode 100644 testsuite/tests/M204-037-dc-in-aggregate/src/values.adb create mode 100644 testsuite/tests/M204-037-dc-in-aggregate/src/values.ads create mode 100644 testsuite/tests/M204-037-dc-in-aggregate/test.py create mode 100644 testsuite/tests/M502-040-default-prj-path/.gitignore create mode 100644 testsuite/tests/M502-040-default-prj-path/proj/proj.gpr create mode 100644 testsuite/tests/M502-040-default-prj-path/proj/ut/main.adb create mode 100644 testsuite/tests/M502-040-default-prj-path/proj/ut/ut.gpr.template create mode 100644 testsuite/tests/M502-040-default-prj-path/test.opt create mode 100644 testsuite/tests/M502-040-default-prj-path/test.py create mode 100644 testsuite/tests/M513-017/driver.adb create mode 100644 testsuite/tests/M513-017/lib.adb create mode 100644 testsuite/tests/M513-017/lib.ads create mode 100644 testsuite/tests/M513-017/test.opt create mode 100644 testsuite/tests/M513-017/test.py create mode 100644 testsuite/tests/M514-031-multiple-stmts-lines/src/ops.adb create mode 100644 testsuite/tests/M514-031-multiple-stmts-lines/src/ops.ads create mode 100644 testsuite/tests/M514-031-multiple-stmts-lines/src/test_full.adb create mode 100644 testsuite/tests/M514-031-multiple-stmts-lines/src/test_no.adb create mode 100644 testsuite/tests/M514-031-multiple-stmts-lines/test.py create mode 100644 testsuite/tests/M515-018/return-ternary.c create mode 100644 testsuite/tests/M515-018/test.opt create mode 100644 testsuite/tests/M515-018/test.py create mode 100644 testsuite/tests/M516-014-direct-bool-operators/req.txt create mode 100644 testsuite/tests/M516-014-direct-bool-operators/src/assert.adb create mode 100644 testsuite/tests/M516-014-direct-bool-operators/src/assert.ads create mode 100644 testsuite/tests/M516-014-direct-bool-operators/src/ops.adb create mode 100644 testsuite/tests/M516-014-direct-bool-operators/src/ops.ads create mode 100644 testsuite/tests/M516-014-direct-bool-operators/src/test_and.adb create mode 100644 testsuite/tests/M516-014-direct-bool-operators/src/test_ff.adb create mode 100644 testsuite/tests/M516-014-direct-bool-operators/src/test_ft.adb create mode 100644 testsuite/tests/M516-014-direct-bool-operators/src/test_or.adb create mode 100644 testsuite/tests/M516-014-direct-bool-operators/src/test_tf.adb create mode 100644 testsuite/tests/M516-014-direct-bool-operators/src/test_tt.adb create mode 100644 testsuite/tests/M516-014-direct-bool-operators/src/test_xor.adb create mode 100644 testsuite/tests/M516-014-direct-bool-operators/test.py create mode 100644 testsuite/tests/M528-002-transient-finalize/alternate/src/assert.adb create mode 100644 testsuite/tests/M528-002-transient-finalize/alternate/src/assert.ads create mode 100644 testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb create mode 100644 testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads create mode 100644 testsuite/tests/M528-002-transient-finalize/alternate/src/test_ff.adb create mode 100644 testsuite/tests/M528-002-transient-finalize/alternate/src/test_ft.adb create mode 100644 testsuite/tests/M528-002-transient-finalize/alternate/src/test_tx.adb create mode 100644 testsuite/tests/M528-002-transient-finalize/alternate/test.py create mode 100644 testsuite/tests/M528-002-transient-finalize/extra.opt create mode 100644 testsuite/tests/M528-002-transient-finalize/original/src/log.adb create mode 100644 testsuite/tests/M528-002-transient-finalize/original/src/test_main.adb create mode 100644 testsuite/tests/M528-002-transient-finalize/original/test.py create mode 100644 testsuite/tests/M528-002-transient-finalize/variant1/src/assert.adb create mode 100644 testsuite/tests/M528-002-transient-finalize/variant1/src/log.adb create mode 100644 testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.adb create mode 100644 testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.ads create mode 100644 testsuite/tests/M528-002-transient-finalize/variant1/src/test_df.adb create mode 100644 testsuite/tests/M528-002-transient-finalize/variant1/src/test_dt.adb create mode 100644 testsuite/tests/M528-002-transient-finalize/variant1/test.py create mode 100644 testsuite/tests/M531-035-3264-ld_preload/sls.c create mode 100644 testsuite/tests/M531-035-3264-ld_preload/test.opt create mode 100644 testsuite/tests/M531-035-3264-ld_preload/test.py create mode 100644 testsuite/tests/M625-011-GPR-Cunits/src/bar.c create mode 100644 testsuite/tests/M625-011-GPR-Cunits/src/bar.h create mode 100644 testsuite/tests/M625-011-GPR-Cunits/src/foo.c create mode 100644 testsuite/tests/M625-011-GPR-Cunits/test.py create mode 100644 testsuite/tests/M625-040-slow_on_windows/p.adb create mode 100644 testsuite/tests/M625-040-slow_on_windows/test.opt create mode 100644 testsuite/tests/M625-040-slow_on_windows/test.py create mode 100644 testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/ops.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_no.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_false.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_true.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second_third.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_third.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Const-Run-Run/test.py create mode 100644 testsuite/tests/M716-023-constant-conditions/Const-Run/src/ops.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_no.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_outcome_true.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Const-Run/test.opt create mode 100644 testsuite/tests/M716-023-constant-conditions/Const-Run/test.py create mode 100644 testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/ops.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/test_no.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/test.py create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/ops.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first_third.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_no.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_false.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_true.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_third.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Const-Run/test.py create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/ops.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first_third.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_no.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_false.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_true.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_third.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/test.py create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/ops.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first_third.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_no.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_false.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_true.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_third.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/test.py create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/ops.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first_second.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_no.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_false.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_true.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_second.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/Run-Run-Const/test.py create mode 100644 testsuite/tests/M716-023-constant-conditions/extra.opt create mode 100644 testsuite/tests/M716-023-constant-conditions/src/assert.adb create mode 100644 testsuite/tests/M716-023-constant-conditions/src/assert.ads create mode 100644 testsuite/tests/M716-023-constant-conditions/src/ops.ads create mode 100644 testsuite/tests/M724-035-eh-warnings/src/show_whether_local.adb create mode 100644 testsuite/tests/M724-035-eh-warnings/src/strict_head.adb create mode 100644 testsuite/tests/M724-035-eh-warnings/src/test_both.adb create mode 100644 testsuite/tests/M724-035-eh-warnings/src/test_exc.adb create mode 100644 testsuite/tests/M724-035-eh-warnings/src/test_glob.adb create mode 100644 testsuite/tests/M724-035-eh-warnings/src/test_loc.adb create mode 100644 testsuite/tests/M724-035-eh-warnings/test.opt create mode 100644 testsuite/tests/M724-035-eh-warnings/test.py create mode 100644 testsuite/tests/M726-018-trace-exec-check/bar.adb create mode 100644 testsuite/tests/M726-018-trace-exec-check/foo.adb create mode 100644 testsuite/tests/M726-018-trace-exec-check/test.opt create mode 100644 testsuite/tests/M726-018-trace-exec-check/test.py create mode 100644 testsuite/tests/MA08-031/src/f.adb create mode 100644 testsuite/tests/MA08-031/test.opt create mode 100644 testsuite/tests/MA08-031/test.py create mode 100644 testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/assert.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.ads create mode 100644 testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/falseonly.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_falseonly.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_truefalse.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_trueonly.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/truefalse.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/trueonly.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.opt create mode 100644 testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.py create mode 100644 testsuite/tests/MB05-039-not-coverable/extra.opt create mode 100644 testsuite/tests/MB05-039-not-coverable/src/state.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/src/state.ads create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrnf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrpf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prnf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prpf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrnf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrpf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prnf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prpf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_mrmf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrnf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrpf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prnf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prpf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.ads create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.ads create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.ads create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.ads create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.ads create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.ads create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Generics/test.py create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/test_values.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.ads create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.opt create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.py create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.ads create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/test_ifs.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/test.py create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.ads create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/test_misc.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/tc.rst create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/test.py create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/test_values.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.adb create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.ads create mode 100644 testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/test.py create mode 100644 testsuite/tests/MB15-040-if-cst/src/monitor.adb create mode 100644 testsuite/tests/MB15-040-if-cst/src/monitor.ads create mode 100644 testsuite/tests/MB15-040-if-cst/src/test_ifcst_call.adb create mode 100644 testsuite/tests/MB15-040-if-cst/src/test_ifcst_none.adb create mode 100644 testsuite/tests/MB15-040-if-cst/test.opt create mode 100644 testsuite/tests/MB15-040-if-cst/test.py create mode 100644 testsuite/tests/MB15-041-verbose-open-crc32/foo.adb create mode 100644 testsuite/tests/MB15-041-verbose-open-crc32/test.opt create mode 100644 testsuite/tests/MB15-041-verbose-open-crc32/test.py create mode 100644 testsuite/tests/MB19-016-subprogram-less-code/foo.c create mode 100644 testsuite/tests/MB19-016-subprogram-less-code/test.opt create mode 100644 testsuite/tests/MB19-016-subprogram-less-code/test.py create mode 100644 testsuite/tests/MC05-011-ref-executable/src/app.adb create mode 100644 testsuite/tests/MC05-011-ref-executable/src/assert.adb create mode 100644 testsuite/tests/MC05-011-ref-executable/src/bump.adb create mode 100644 testsuite/tests/MC05-011-ref-executable/src/double.adb create mode 100644 testsuite/tests/MC05-011-ref-executable/src/test_bump.adb create mode 100644 testsuite/tests/MC05-011-ref-executable/test.py create mode 100644 testsuite/tests/N106-020-tempfiles/src/actions.adb create mode 100644 testsuite/tests/N106-020-tempfiles/src/actions.ads create mode 100644 testsuite/tests/N106-020-tempfiles/src/test_tags.adb create mode 100644 testsuite/tests/N106-020-tempfiles/test.py create mode 100644 testsuite/tests/N107-020-dhtml/foo.adb create mode 100644 testsuite/tests/N107-020-dhtml/test.py create mode 100644 testsuite/tests/N107-029-crc32-validity/foo.adb create mode 100644 testsuite/tests/N107-029-crc32-validity/test.opt create mode 100644 testsuite/tests/N107-029-crc32-validity/test.py create mode 100644 testsuite/tests/N129-008-c-constant-conditions/src/foo.c create mode 100644 testsuite/tests/N129-008-c-constant-conditions/src/foo.h create mode 100644 testsuite/tests/N129-008-c-constant-conditions/src/test_foo.c create mode 100644 testsuite/tests/N129-008-c-constant-conditions/test.opt create mode 100644 testsuite/tests/N129-008-c-constant-conditions/test.py create mode 100644 testsuite/tests/N203-040-same-c-basename/src/a/foo.h create mode 100644 testsuite/tests/N203-040-same-c-basename/src/b/foo.h create mode 100644 testsuite/tests/N203-040-same-c-basename/src/test_foo.c create mode 100644 testsuite/tests/N203-040-same-c-basename/test.opt create mode 100644 testsuite/tests/N203-040-same-c-basename/test.py create mode 100644 testsuite/tests/N204-011-precond-aspects/src/foo.adb create mode 100644 testsuite/tests/N204-011-precond-aspects/src/foo.ads create mode 100644 testsuite/tests/N204-011-precond-aspects/src/log.adb create mode 100644 testsuite/tests/N204-011-precond-aspects/src/test_foo.adb create mode 100644 testsuite/tests/N204-011-precond-aspects/test.opt create mode 100644 testsuite/tests/N204-011-precond-aspects/test.py create mode 100644 testsuite/tests/N321-039-disas-wrapping/foo.s create mode 100644 testsuite/tests/N321-039-disas-wrapping/test.opt create mode 100644 testsuite/tests/N321-039-disas-wrapping/test.py create mode 100644 testsuite/tests/N321-045-ppc-disas-large-input/foo.adb create mode 100644 testsuite/tests/N321-045-ppc-disas-large-input/test.opt create mode 100644 testsuite/tests/N321-045-ppc-disas-large-input/test.py create mode 100644 testsuite/tests/N411-046-asm-consolidation/p-default.s create mode 100644 testsuite/tests/N411-046-asm-consolidation/p-win32.s create mode 100644 testsuite/tests/N411-046-asm-consolidation/p-win64.s create mode 100644 testsuite/tests/N411-046-asm-consolidation/test.c create mode 100644 testsuite/tests/N411-046-asm-consolidation/test.opt create mode 100644 testsuite/tests/N411-046-asm-consolidation/test.py create mode 100644 testsuite/tests/N423-015-exempt-in-separate/src/assert.adb create mode 100644 testsuite/tests/N423-015-exempt-in-separate/src/pck-check.adb create mode 100644 testsuite/tests/N423-015-exempt-in-separate/src/pck.adb create mode 100644 testsuite/tests/N423-015-exempt-in-separate/src/pck.ads create mode 100644 testsuite/tests/N423-015-exempt-in-separate/src/test_i.adb create mode 100644 testsuite/tests/N423-015-exempt-in-separate/src/test_v.adb create mode 100644 testsuite/tests/N423-015-exempt-in-separate/test.opt create mode 100644 testsuite/tests/N423-015-exempt-in-separate/test.py create mode 100644 testsuite/tests/N429-018-c-assert/ToMultiStmts/src/test_assert.c create mode 100644 testsuite/tests/N429-018-c-assert/ToMultiStmts/test.opt create mode 100644 testsuite/tests/N429-018-c-assert/ToMultiStmts/test.py create mode 100644 testsuite/tests/N429-018-c-assert/ToSingleStmt/src/test_assert.c create mode 100644 testsuite/tests/N429-018-c-assert/ToSingleStmt/test.opt create mode 100644 testsuite/tests/N429-018-c-assert/ToSingleStmt/test.py create mode 100644 testsuite/tests/N429-018-c-tern-folding/src/foo.c create mode 100644 testsuite/tests/N429-018-c-tern-folding/src/foo.h create mode 100644 testsuite/tests/N429-018-c-tern-folding/src/test_foo_ft.c create mode 100644 testsuite/tests/N429-018-c-tern-folding/src/test_foo_t.c create mode 100644 testsuite/tests/N429-018-c-tern-folding/test.opt create mode 100644 testsuite/tests/N429-018-c-tern-folding/test.py create mode 100644 testsuite/tests/N429-018-c-void-ternary/src/foo.c create mode 100644 testsuite/tests/N429-018-c-void-ternary/src/foo.h create mode 100644 testsuite/tests/N429-018-c-void-ternary/src/helpers.c create mode 100644 testsuite/tests/N429-018-c-void-ternary/src/helpers.h create mode 100644 testsuite/tests/N429-018-c-void-ternary/src/test_foo_0.c create mode 100644 testsuite/tests/N429-018-c-void-ternary/src/test_foo_f.c create mode 100644 testsuite/tests/N429-018-c-void-ternary/src/test_foo_t.c create mode 100644 testsuite/tests/N429-018-c-void-ternary/src/test_foo_tf.c create mode 100644 testsuite/tests/N429-018-c-void-ternary/test.opt create mode 100644 testsuite/tests/N429-018-c-void-ternary/test.py create mode 100644 testsuite/tests/N429-020-loop-on-line-ada/foo.adb create mode 100644 testsuite/tests/N429-020-loop-on-line-ada/test.opt create mode 100644 testsuite/tests/N429-020-loop-on-line-ada/test.py create mode 100644 testsuite/tests/N429-020-loop-on-line/main.c create mode 100644 testsuite/tests/N429-020-loop-on-line/test.opt create mode 100644 testsuite/tests/N429-020-loop-on-line/test.py create mode 100644 testsuite/tests/N430-005-c-static-inline/extra.opt create mode 100644 testsuite/tests/N430-005-c-static-inline/supported/src/bar_false.c create mode 100644 testsuite/tests/N430-005-c-static-inline/supported/src/bar_true.c create mode 100644 testsuite/tests/N430-005-c-static-inline/supported/src/foo.c create mode 100644 testsuite/tests/N430-005-c-static-inline/supported/src/foo.h create mode 100644 testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_0.c create mode 100644 testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_f.c create mode 100644 testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_t.c create mode 100644 testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_tf.c create mode 100644 testsuite/tests/N430-005-c-static-inline/supported/test.py create mode 100644 testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.c create mode 100644 testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.h create mode 100644 testsuite/tests/N430-005-c-static-inline/unsupported/src/test_foo.c create mode 100644 testsuite/tests/N430-005-c-static-inline/unsupported/test.py create mode 100644 testsuite/tests/N505-008-c99-main-return/src/test_main.c create mode 100644 testsuite/tests/N505-008-c99-main-return/test.opt create mode 100644 testsuite/tests/N505-008-c99-main-return/test.py create mode 100644 testsuite/tests/N505-026-multstmtln-nocode/src/helper.c create mode 100644 testsuite/tests/N505-026-multstmtln-nocode/src/helper.h create mode 100644 testsuite/tests/N505-026-multstmtln-nocode/src/test_foo.c create mode 100644 testsuite/tests/N505-026-multstmtln-nocode/test.opt create mode 100644 testsuite/tests/N505-026-multstmtln-nocode/test.py create mode 100644 testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.c create mode 100644 testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.h create mode 100644 testsuite/tests/N506-014-crash-on-padding-nop/src/test_stop.c create mode 100644 testsuite/tests/N506-014-crash-on-padding-nop/test.opt create mode 100644 testsuite/tests/N506-014-crash-on-padding-nop/test.py create mode 100644 testsuite/tests/N513-004-dom-info-c-tern/src/test_main.c create mode 100644 testsuite/tests/N513-004-dom-info-c-tern/test.opt create mode 100644 testsuite/tests/N513-004-dom-info-c-tern/test.py create mode 100644 testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.adb create mode 100644 testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.ads create mode 100644 testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_nobody.adb create mode 100644 testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_someone.adb create mode 100644 testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_nobody.adb create mode 100644 testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_someone.adb create mode 100644 testsuite/tests/N521-029-dc-dynstack-twoways/test.opt create mode 100644 testsuite/tests/N521-029-dc-dynstack-twoways/test.py create mode 100644 testsuite/tests/N610-006-library/libops.gpr create mode 100644 testsuite/tests/N610-006-library/libops/inc.adb create mode 100644 testsuite/tests/N610-006-library/libops/mult.adb create mode 100644 testsuite/tests/N610-006-library/test.py create mode 100644 testsuite/tests/N610-006-library/test_inc.adb create mode 100644 testsuite/tests/N610-006-library/test_mult.adb create mode 100644 testsuite/tests/N630-009-forward_p_x/foo.adb create mode 100644 testsuite/tests/N630-009-forward_p_x/test.opt create mode 100644 testsuite/tests/N630-009-forward_p_x/test.py create mode 100644 testsuite/tests/NA29-019-unit-filters-for-C/abs.c create mode 100644 testsuite/tests/NA29-019-unit-filters-for-C/test.opt create mode 100644 testsuite/tests/NA29-019-unit-filters-for-C/test.py create mode 100644 testsuite/tests/NA29-019-unit-filters-for-C/test_abs.c create mode 100644 testsuite/tests/NB07-026-header-shadow/src/box.h create mode 100644 testsuite/tests/NB07-026-header-shadow/src/m1.c create mode 100644 testsuite/tests/NB07-026-header-shadow/src/m2.c create mode 100644 testsuite/tests/NB07-026-header-shadow/src/test_main.c create mode 100644 testsuite/tests/NB07-026-header-shadow/test.opt create mode 100644 testsuite/tests/NB07-026-header-shadow/test.py create mode 100644 testsuite/tests/NC02-014-gpr-X/main.adb create mode 100644 testsuite/tests/NC02-014-gpr-X/test.py create mode 100644 testsuite/tests/NC08-027-target_attr/foo.adb create mode 100644 testsuite/tests/NC08-027-target_attr/test.opt create mode 100644 testsuite/tests/NC08-027-target_attr/test.py create mode 100644 testsuite/tests/O302-015-src-path-in-project/p.gpr create mode 100644 testsuite/tests/O302-015-src-path-in-project/src/main.adb create mode 100644 testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.adb create mode 100644 testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.ads create mode 100644 testsuite/tests/O302-015-src-path-in-project/src/pkg-io.adb create mode 100644 testsuite/tests/O302-015-src-path-in-project/src/pkg-io.ads create mode 100644 testsuite/tests/O302-015-src-path-in-project/src/pkg.ads create mode 100644 testsuite/tests/O302-015-src-path-in-project/test.py create mode 100644 testsuite/tests/O529-021-wrong-elf-class/code-32.o create mode 100644 testsuite/tests/O529-021-wrong-elf-class/code-64.o create mode 100644 testsuite/tests/O529-021-wrong-elf-class/code.s create mode 100644 testsuite/tests/O529-021-wrong-elf-class/test.py create mode 100644 testsuite/tests/O916-035-padding-cons/foo-x86-linux.s create mode 100644 testsuite/tests/O916-035-padding-cons/foo-x86-windows.s create mode 100644 testsuite/tests/O916-035-padding-cons/foo.c create mode 100644 testsuite/tests/O916-035-padding-cons/test.opt create mode 100644 testsuite/tests/O916-035-padding-cons/test.py create mode 100644 testsuite/tests/OA05-051-sharedobjs-opt/foo.adb create mode 100644 testsuite/tests/OA05-051-sharedobjs-opt/test.opt create mode 100644 testsuite/tests/OA05-051-sharedobjs-opt/test.py create mode 100644 testsuite/tests/OA05-051-sharedobjs/mylib1.gpr create mode 100644 testsuite/tests/OA05-051-sharedobjs/mylib2.gpr create mode 100644 testsuite/tests/OA05-051-sharedobjs/myprog.gpr create mode 100644 testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.adb create mode 100644 testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.ads create mode 100644 testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.adb create mode 100644 testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.ads create mode 100644 testsuite/tests/OA05-051-sharedobjs/src-myprog/myprog.adb create mode 100644 testsuite/tests/OA05-051-sharedobjs/test.opt create mode 100644 testsuite/tests/OA05-051-sharedobjs/test.py create mode 100644 testsuite/tests/OA16-009-exec-prefix/prj1/foo.adb create mode 100644 testsuite/tests/OA16-009-exec-prefix/prj1/pkg.adb create mode 100644 testsuite/tests/OA16-009-exec-prefix/prj1/pkg.ads create mode 100644 testsuite/tests/OA16-009-exec-prefix/prj2/foo.adb create mode 100644 testsuite/tests/OA16-009-exec-prefix/prj2/pkg.adb create mode 100644 testsuite/tests/OA16-009-exec-prefix/prj2/pkg.ads create mode 100644 testsuite/tests/OA16-009-exec-prefix/test.opt create mode 100644 testsuite/tests/OA16-009-exec-prefix/test.py create mode 100644 testsuite/tests/OA16-009-windows-suffix/foo.adb create mode 100644 testsuite/tests/OA16-009-windows-suffix/test.opt create mode 100644 testsuite/tests/OA16-009-windows-suffix/test.py create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/.gitignore create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/pkg.gpr create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.adb create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.ads create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/src/pkg-test_driver.adb create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.adb create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.ads create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/test.py create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/test1.gpr create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/test1/main_test1.adb create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/test1/pkg-test_driver.adb create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/test2.gpr create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/test2/main_test2.adb create mode 100644 testsuite/tests/OA27-059-inlined-separate-cons/test2/pkg-test_driver.adb create mode 100644 testsuite/tests/OA27-059-sep-cons-prj-override/.gitignore create mode 100644 testsuite/tests/OA27-059-sep-cons-prj-override/pkg_under_test.gpr create mode 100644 testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-pkg_test.adb create mode 100644 testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-some_procedure.adb create mode 100644 testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.adb create mode 100644 testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.ads create mode 100644 testsuite/tests/OA27-059-sep-cons-prj-override/test.py create mode 100644 testsuite/tests/OA27-059-sep-cons-prj-override/test1.gpr create mode 100644 testsuite/tests/OA27-059-sep-cons-prj-override/test1/main_test1.adb create mode 100644 testsuite/tests/OA27-059-sep-cons-prj-override/test1/pkg_under_test-pkg_test.adb create mode 100644 testsuite/tests/OA27-059-sep-cons-prj-override/test2.gpr create mode 100644 testsuite/tests/OA27-059-sep-cons-prj-override/test2/main_test2.adb create mode 100644 testsuite/tests/OA27-059-sep-cons-prj-override/test2/pkg_under_test-pkg_test.adb create mode 100644 testsuite/tests/OA27-059-sep-cons-prj/.gitignore create mode 100644 testsuite/tests/OA27-059-sep-cons-prj/pkg_under_test.gpr create mode 100644 testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test-pkg_test.adb create mode 100644 testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.adb create mode 100644 testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.ads create mode 100644 testsuite/tests/OA27-059-sep-cons-prj/test.py create mode 100644 testsuite/tests/OA27-059-sep-cons-prj/test1.gpr create mode 100644 testsuite/tests/OA27-059-sep-cons-prj/test1/main_test1.adb create mode 100644 testsuite/tests/OA27-059-sep-cons-prj/test1/pkg_under_test-pkg_test.adb create mode 100644 testsuite/tests/OA27-059-sep-cons-prj/test2.gpr create mode 100644 testsuite/tests/OA27-059-sep-cons-prj/test2/main_test2.adb create mode 100644 testsuite/tests/OA27-059-sep-cons-prj/test2/pkg_under_test-pkg_test.adb create mode 100644 testsuite/tests/OA27-059-separate-consolidation/pkg_under_test.gpr create mode 100644 testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.adb create mode 100644 testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.ads create mode 100644 testsuite/tests/OA27-059-separate-consolidation/test.opt create mode 100644 testsuite/tests/OA27-059-separate-consolidation/test.py create mode 100644 testsuite/tests/OA27-059-separate-consolidation/test1.gpr create mode 100644 testsuite/tests/OA27-059-separate-consolidation/test1/main_test1.adb create mode 100644 testsuite/tests/OA27-059-separate-consolidation/test1/pkg_under_test-pkg_test.adb create mode 100644 testsuite/tests/OA27-059-separate-consolidation/test2.gpr create mode 100644 testsuite/tests/OA27-059-separate-consolidation/test2/main_test2.adb create mode 100644 testsuite/tests/OA27-059-separate-consolidation/test2/pkg_under_test-pkg_test.adb create mode 100644 testsuite/tests/OB23-036/foo.adb create mode 100644 testsuite/tests/OB23-036/test.py create mode 100644 testsuite/tests/OB26-040-type-invariants/Aspects/src/tcheck.ads create mode 100644 testsuite/tests/OB26-040-type-invariants/Aspects/src/tnocheck.ads create mode 100644 testsuite/tests/OB26-040-type-invariants/Aspects/test.opt create mode 100644 testsuite/tests/OB26-040-type-invariants/Aspects/test.py create mode 100644 testsuite/tests/OB26-040-type-invariants/InvariantClass/src/test_t.adb create mode 100644 testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.adb create mode 100644 testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.ads create mode 100644 testsuite/tests/OB26-040-type-invariants/InvariantClass/test.opt create mode 100644 testsuite/tests/OB26-040-type-invariants/InvariantClass/test.py create mode 100644 testsuite/tests/OB26-040-type-invariants/Pragmas/src/tcheck.ads create mode 100644 testsuite/tests/OB26-040-type-invariants/Pragmas/src/tnocheck.ads create mode 100644 testsuite/tests/OB26-040-type-invariants/Pragmas/test.opt create mode 100644 testsuite/tests/OB26-040-type-invariants/Pragmas/test.py create mode 100644 testsuite/tests/OB26-040-type-invariants/extra.opt create mode 100644 testsuite/tests/OB26-040-type-invariants/src/test_tcheck_t.adb create mode 100644 testsuite/tests/OB26-040-type-invariants/src/test_tnocheck_t.adb create mode 100644 testsuite/tests/P505-032-path-spaces/foo.adb create mode 100644 testsuite/tests/P505-032-path-spaces/test.opt create mode 100644 testsuite/tests/P505-032-path-spaces/test.py create mode 100644 testsuite/tests/P526-035-origin-project/src-p1/p1.adb create mode 100644 testsuite/tests/P526-035-origin-project/src-p1/p1.ads create mode 100644 testsuite/tests/P526-035-origin-project/src-p2/p2.adb create mode 100644 testsuite/tests/P526-035-origin-project/test.opt create mode 100644 testsuite/tests/P526-035-origin-project/test.py create mode 100644 testsuite/tests/P614-002-incidental-coverage/src/cons_maps_math.txt create mode 100644 testsuite/tests/P614-002-incidental-coverage/src/maps.adb create mode 100644 testsuite/tests/P614-002-incidental-coverage/src/maps.ads create mode 100644 testsuite/tests/P614-002-incidental-coverage/src/math.adb create mode 100644 testsuite/tests/P614-002-incidental-coverage/src/math.ads create mode 100644 testsuite/tests/P614-002-incidental-coverage/src/test_add.adb create mode 100644 testsuite/tests/P614-002-incidental-coverage/src/test_area.adb create mode 100644 testsuite/tests/P614-002-incidental-coverage/test.py create mode 100644 testsuite/tests/P622-010-stack-restore/src/characterize.adb create mode 100644 testsuite/tests/P622-010-stack-restore/src/test_0.adb create mode 100644 testsuite/tests/P622-010-stack-restore/src/test_n.adb create mode 100644 testsuite/tests/P622-010-stack-restore/src/test_p.adb create mode 100644 testsuite/tests/P622-010-stack-restore/src/test_z.adb create mode 100644 testsuite/tests/P622-010-stack-restore/test.py create mode 100644 testsuite/tests/P907-005-ckpt-covlevel/src/math.adb create mode 100644 testsuite/tests/P907-005-ckpt-covlevel/src/math.ads create mode 100644 testsuite/tests/P907-005-ckpt-covlevel/src/test_add.adb create mode 100644 testsuite/tests/P907-005-ckpt-covlevel/src/test_mult.adb create mode 100644 testsuite/tests/P907-005-ckpt-covlevel/test.py create mode 100644 testsuite/tests/P907-005-incremental/src/math.adb create mode 100644 testsuite/tests/P907-005-incremental/src/math.ads create mode 100644 testsuite/tests/P907-005-incremental/src/test_add.adb create mode 100644 testsuite/tests/P907-005-incremental/src/test_mult.adb create mode 100644 testsuite/tests/P907-005-incremental/test.py create mode 100644 testsuite/tests/P907-005-stubbing-generic/.gitignore create mode 100644 testsuite/tests/P907-005-stubbing-generic/common.gpr create mode 100644 testsuite/tests/P907-005-stubbing-generic/sensors/int_control.ads create mode 100644 testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.adb create mode 100644 testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.ads create mode 100644 testsuite/tests/P907-005-stubbing-generic/sensors/sensors.gpr create mode 100644 testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.adb create mode 100644 testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.ads create mode 100644 testsuite/tests/P907-005-stubbing-generic/stub_pressure/pressure_control.adb create mode 100644 testsuite/tests/P907-005-stubbing-generic/stub_temperature/temperature_control.adb create mode 100644 testsuite/tests/P907-005-stubbing-generic/test.py create mode 100644 testsuite/tests/P907-005-stubbing-generic/test_p/test_runner.gpr create mode 100644 testsuite/tests/P907-005-stubbing-generic/test_p/tp1.adb create mode 100644 testsuite/tests/P907-005-stubbing-generic/test_sensors/test_runner.gpr create mode 100644 testsuite/tests/P907-005-stubbing-generic/test_sensors/ts1.adb create mode 100644 testsuite/tests/P907-005-stubbing-generic/test_t/test_runner.gpr create mode 100644 testsuite/tests/P907-005-stubbing-generic/test_t/tt1.adb create mode 100644 testsuite/tests/P907-005-stubbing/.gitignore create mode 100644 testsuite/tests/P907-005-stubbing/common.gpr create mode 100644 testsuite/tests/P907-005-stubbing/sensors/pressure_control.adb create mode 100644 testsuite/tests/P907-005-stubbing/sensors/pressure_control.ads create mode 100644 testsuite/tests/P907-005-stubbing/sensors/sensors.gpr create mode 100644 testsuite/tests/P907-005-stubbing/sensors/temperature_control.adb create mode 100644 testsuite/tests/P907-005-stubbing/sensors/temperature_control.ads create mode 100644 testsuite/tests/P907-005-stubbing/stub_pressure/pressure_control.adb create mode 100644 testsuite/tests/P907-005-stubbing/stub_temperature/temperature_control.adb create mode 100644 testsuite/tests/P907-005-stubbing/test.py create mode 100644 testsuite/tests/P907-005-stubbing/test_p/test_runner.gpr create mode 100644 testsuite/tests/P907-005-stubbing/test_p/tp1.adb create mode 100644 testsuite/tests/P907-005-stubbing/test_sensors/test_runner.gpr create mode 100644 testsuite/tests/P907-005-stubbing/test_sensors/ts1.adb create mode 100644 testsuite/tests/P907-005-stubbing/test_t/test_runner.gpr create mode 100644 testsuite/tests/P907-005-stubbing/test_t/tt1.adb create mode 100644 testsuite/tests/P913-011-invalid-project/foo.adb create mode 100644 testsuite/tests/P913-011-invalid-project/test.py create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.ads create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_1.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_14.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_2.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_3.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_4.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_5.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/AB_C/test.py create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.ads create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1346.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_2.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_3.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_346.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_36.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_4.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_46.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_5.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_6.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/test.py create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.ads create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_12.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_123.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1234.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_124.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_13.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_134.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_14.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_2.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_3.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_4.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/A_B_C/test.py create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.ads create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_0.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_1.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_12.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_123.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_13.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_2.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_23.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_3.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/C_X/test.py create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/extra.opt create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/src/twisters.adb create mode 100644 testsuite/tests/PA25-046-inlined-in-decision/src/twisters.ads create mode 100644 testsuite/tests/PC09-022-auto-exename/src-sub/sub_main.adb create mode 100644 testsuite/tests/PC09-022-auto-exename/src/main_proc.adb create mode 100644 testsuite/tests/PC09-022-auto-exename/src/other_proc.adb create mode 100644 testsuite/tests/PC09-022-auto-exename/test.opt create mode 100644 testsuite/tests/PC09-022-auto-exename/test.py create mode 100644 testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.adb create mode 100644 testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.ads create mode 100644 testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops.ads create mode 100644 testsuite/tests/PC23-018-missing-report-for-empty-unit/src/test_p1.adb create mode 100644 testsuite/tests/PC23-018-missing-report-for-empty-unit/test.py create mode 100644 testsuite/tests/Q224-032-several-out-of-line/bar.c create mode 100644 testsuite/tests/Q224-032-several-out-of-line/foo.cpp create mode 100644 testsuite/tests/Q224-032-several-out-of-line/main.cpp create mode 100644 testsuite/tests/Q224-032-several-out-of-line/shared.hpp create mode 100644 testsuite/tests/Q224-032-several-out-of-line/test.opt create mode 100644 testsuite/tests/Q224-032-several-out-of-line/test.py create mode 100644 testsuite/tests/Q308-041-crash-on-generic-in-lib/.gitignore create mode 100644 testsuite/tests/Q308-041-crash-on-generic-in-lib/app/default.gpr create mode 100644 testsuite/tests/Q308-041-crash-on-generic-in-lib/app/main.adb create mode 100644 testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.adb create mode 100644 testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.ads create mode 100644 testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/libfoo.gpr create mode 100644 testsuite/tests/Q308-041-crash-on-generic-in-lib/test.opt create mode 100644 testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py create mode 100644 testsuite/tests/Q327-016-glob-ignore/ignore.list create mode 100644 testsuite/tests/Q327-016-glob-ignore/src/main.adb create mode 100644 testsuite/tests/Q327-016-glob-ignore/src/pkg_a-test.adb create mode 100644 testsuite/tests/Q327-016-glob-ignore/src/pkg_a.adb create mode 100644 testsuite/tests/Q327-016-glob-ignore/src/pkg_a.ads create mode 100644 testsuite/tests/Q327-016-glob-ignore/src/pkg_b-test.adb create mode 100644 testsuite/tests/Q327-016-glob-ignore/src/pkg_b.adb create mode 100644 testsuite/tests/Q327-016-glob-ignore/src/pkg_b.ads create mode 100644 testsuite/tests/Q327-016-glob-ignore/src/pkg_c-test.adb create mode 100644 testsuite/tests/Q327-016-glob-ignore/src/pkg_c.adb create mode 100644 testsuite/tests/Q327-016-glob-ignore/src/pkg_c.ads create mode 100644 testsuite/tests/Q327-016-glob-ignore/test.py create mode 100644 testsuite/tests/Q329-018-create-output-dir/foo.adb create mode 100644 testsuite/tests/Q329-018-create-output-dir/test.py create mode 100644 testsuite/tests/Q414-016-task-accept/src/q.adb create mode 100644 testsuite/tests/Q414-016-task-accept/src/q.ads create mode 100644 testsuite/tests/Q414-016-task-accept/src/test_tick.adb create mode 100644 testsuite/tests/Q414-016-task-accept/test.opt create mode 100644 testsuite/tests/Q414-016-task-accept/test.py create mode 100644 testsuite/tests/Q519-013-decision-map/bar.adb create mode 100644 testsuite/tests/Q519-013-decision-map/bar.ads create mode 100644 testsuite/tests/Q519-013-decision-map/foo.adb create mode 100644 testsuite/tests/Q519-013-decision-map/test.opt create mode 100644 testsuite/tests/Q519-013-decision-map/test.py create mode 100644 testsuite/tests/Q614-037-ckpt-pkg-renames/bar.ads create mode 100644 testsuite/tests/Q614-037-ckpt-pkg-renames/foo.adb create mode 100644 testsuite/tests/Q614-037-ckpt-pkg-renames/foo.ads create mode 100644 testsuite/tests/Q614-037-ckpt-pkg-renames/main.adb create mode 100644 testsuite/tests/Q614-037-ckpt-pkg-renames/test.py create mode 100644 testsuite/tests/Q901-012-report-title/foo.adb create mode 100644 testsuite/tests/Q901-012-report-title/test.py create mode 100644 testsuite/tests/Q905-005-compressed/foo.adb create mode 100644 testsuite/tests/Q905-005-compressed/test.opt create mode 100644 testsuite/tests/Q905-005-compressed/test.py create mode 100644 testsuite/tests/QA23-039-nocode-pragmas/p1.ads create mode 100644 testsuite/tests/QA23-039-nocode-pragmas/p2.ads create mode 100644 testsuite/tests/QA23-039-nocode-pragmas/p3.ads create mode 100644 testsuite/tests/QA23-039-nocode-pragmas/test.py create mode 100644 testsuite/tests/QA23-039-nocode-pragmas/test_p1.adb create mode 100644 testsuite/tests/QA23-039-nocode-pragmas/test_p2.adb create mode 100644 testsuite/tests/QA23-039-nocode-pragmas/test_p3.adb create mode 100644 testsuite/tests/QA27-024-prepare-target/foo.adb create mode 100644 testsuite/tests/QA27-024-prepare-target/test.py create mode 100644 testsuite/tests/QB14-023-stack-overflow/foo.adb create mode 100644 testsuite/tests/QB14-023-stack-overflow/test.py create mode 100755 testsuite/tests/R404-023-object-stats/main create mode 100644 testsuite/tests/R404-023-object-stats/main.adb create mode 100644 testsuite/tests/R404-023-object-stats/main.trace.asset create mode 100644 testsuite/tests/R404-023-object-stats/p.gpr create mode 100644 testsuite/tests/R404-023-object-stats/pkg.adb create mode 100644 testsuite/tests/R404-023-object-stats/pkg.ads create mode 100644 testsuite/tests/R404-023-object-stats/routines.txt create mode 100644 testsuite/tests/R404-023-object-stats/test.opt create mode 100644 testsuite/tests/R404-023-object-stats/test.py create mode 100644 testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected create mode 100644 testsuite/tests/R417-010-scope-metrics/src/main.adb create mode 100644 testsuite/tests/R417-010-scope-metrics/test.opt create mode 100644 testsuite/tests/R417-010-scope-metrics/test.py create mode 100644 testsuite/tests/R420-002-aggregate-project-file/src1/foo.adb create mode 100644 testsuite/tests/R420-002-aggregate-project-file/src2/foo.adb create mode 100644 testsuite/tests/R420-002-aggregate-project-file/test.opt create mode 100644 testsuite/tests/R420-002-aggregate-project-file/test.py create mode 100644 testsuite/tests/R507-014-trailing-byte-insn/f.s create mode 100644 testsuite/tests/R507-014-trailing-byte-insn/main.c create mode 100644 testsuite/tests/R507-014-trailing-byte-insn/test.opt create mode 100644 testsuite/tests/R507-014-trailing-byte-insn/test.py create mode 100644 testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected create mode 100644 testsuite/tests/R507-027-xml-summary/data.ads create mode 100644 testsuite/tests/R507-027-xml-summary/main.adb create mode 100644 testsuite/tests/R507-027-xml-summary/pkg.adb create mode 100644 testsuite/tests/R507-027-xml-summary/pkg.ads create mode 100644 testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected create mode 100644 testsuite/tests/R507-027-xml-summary/test.opt create mode 100644 testsuite/tests/R507-027-xml-summary/test.py create mode 100644 testsuite/tests/R521-002-profile-arcs/main.adb create mode 100644 testsuite/tests/R521-002-profile-arcs/test.opt create mode 100644 testsuite/tests/R521-002-profile-arcs/test.py create mode 100644 testsuite/tests/R521-002-profile-arcs/util.c create mode 100644 testsuite/tests/R807-027-symbol-order/p.adb create mode 100644 testsuite/tests/R807-027-symbol-order/pkg.adb create mode 100644 testsuite/tests/R807-027-symbol-order/pkg.ads create mode 100644 testsuite/tests/R807-027-symbol-order/test.opt create mode 100644 testsuite/tests/R807-027-symbol-order/test.py create mode 100644 testsuite/tests/RB13-019-win-paths/.gitignore create mode 100644 testsuite/tests/RB13-019-win-paths/Makefile create mode 100644 testsuite/tests/RB13-019-win-paths/driver.c create mode 100644 testsuite/tests/RB13-019-win-paths/test.opt create mode 100644 testsuite/tests/RB13-019-win-paths/test.py create mode 100644 testsuite/tests/RB13-019-win-paths/wibble.c create mode 100644 testsuite/tests/RB13-019-win-paths/wibble.h create mode 100644 testsuite/tests/RB16-008-gpr-tool/main.adb create mode 100644 testsuite/tests/RB16-008-gpr-tool/test.py create mode 100644 testsuite/tests/RB16-008-gpr-tool/unit_env_var.adb create mode 100644 testsuite/tests/RB16-008-gpr-tool/unit_gnatcoverage.adb create mode 100644 testsuite/tests/RB16-008-gpr-tool/unit_x_arg.adb create mode 100644 testsuite/tests/RC04-030-bad-trace/.gitignore create mode 100644 testsuite/tests/RC04-030-bad-trace/main_a.adb create mode 100644 testsuite/tests/RC04-030-bad-trace/main_b.adb create mode 100644 testsuite/tests/RC04-030-bad-trace/main_c.adb create mode 100644 testsuite/tests/RC04-030-bad-trace/pkg.adb create mode 100644 testsuite/tests/RC04-030-bad-trace/pkg.ads create mode 100644 testsuite/tests/RC04-030-bad-trace/test.opt create mode 100644 testsuite/tests/RC04-030-bad-trace/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/src/raise_exception.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/src/raise_exception.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/src/raise_exception.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/notes.txt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.ads create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/p.ads create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/raise_exception.ads create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/test_raise_exception.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/src/elab.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/src/elab.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/src/elab.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_calls.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_raise.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_raise.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/elab.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.ads create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_exp_raise.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_imp_raise.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_calls.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_raise.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/elab.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.ads create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_exp_raise.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_calls.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_raise.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/elab.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_exp_raise.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_imp_raise.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_calls.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_raise.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/elab.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_exp_raise.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_calls.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_raise.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/notes.txt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/src/global.ads create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/div.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_nok.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_ok.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/div.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_nok.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_ok.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/div.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_nok.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_ok.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/div.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_nok.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_ok.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.py create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/notes.txt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/src/div.ads create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.ads create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_f.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_t.adb create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/example/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/example/test.py create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/check_class_wide.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_f.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_no.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_t.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tf.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tfx.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_x.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/tc.txt create mode 100644 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.opt create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.py create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/check_class_wide_condition.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_f.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ft.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ftx.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_no.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_t.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_x.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/tc.txt create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.opt create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.py create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/check_dispatching_condition.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_f.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ft.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ftx.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_no.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_t.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_x.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/tc.txt create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.opt create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.py create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/check_dynamic_binding.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_f_t.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_ftx.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_t_ft.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_x.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_no.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/tc.txt create mode 100644 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.opt create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.py create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/req.txt create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.ads create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.ads create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.adb create mode 100755 testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.ads create mode 100755 testsuite/tests/Ravenscar/OOP/req.txt create mode 100755 testsuite/tests/Ravenscar/OOP/src/class_wide_ops.adb create mode 100755 testsuite/tests/Ravenscar/OOP/src/class_wide_ops.ads create mode 100755 testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.adb create mode 100755 testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.ads create mode 100755 testsuite/tests/Ravenscar/OOP/src/new_alert_system-objects.ads create mode 100755 testsuite/tests/Ravenscar/OOP/src/new_alert_system.adb create mode 100755 testsuite/tests/Ravenscar/OOP/src/new_alert_system.ads create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_1.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_2.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_3.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_4.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_full.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_no.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/tc.txt create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/test.py create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_1.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_2.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_3.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_4.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/tc.txt create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/test.py create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_inherited.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_overriding.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Inheritance/tc.txt create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Inheritance/test.py create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.ads create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.ads create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.ads create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_1.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_10.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_11.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_12.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_2.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_3.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_4.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_5.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_6.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_7.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_8.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_9.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.ads create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.ads create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.ads create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x.ads create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.ads create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.ads create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.ads create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y.ads create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/tc.txt create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.opt create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.py create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_1.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_2.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_3.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_4.adb create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/tc.txt create mode 100755 testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/test.py create mode 100644 testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb create mode 100644 testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.opt create mode 100644 testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.py create mode 100644 testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.adb create mode 100644 testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.ads create mode 100644 testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/src/test_driver.adb create mode 100644 testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.opt create mode 100644 testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.py create mode 100644 testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/src/test_driver.adb create mode 100644 testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.opt create mode 100644 testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.py create mode 100644 testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.adb create mode 100644 testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.ads create mode 100644 testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/src/test_driver.adb create mode 100644 testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.opt create mode 100644 testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.py create mode 100644 testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/src/test_driver.adb create mode 100644 testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.opt create mode 100644 testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.py create mode 100644 testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.adb create mode 100644 testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.ads create mode 100644 testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/src/test_driver.adb create mode 100644 testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.opt create mode 100644 testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.py create mode 100644 testsuite/tests/Ravenscar/example0/decision/src/test_1.adb create mode 100644 testsuite/tests/Ravenscar/example0/decision/test.opt create mode 100644 testsuite/tests/Ravenscar/example0/decision/test.py create mode 100644 testsuite/tests/Ravenscar/example0/src/sync.adb create mode 100644 testsuite/tests/Ravenscar/example0/src/sync.ads create mode 100644 testsuite/tests/Ravenscar/example0/stmt/src/test_1.adb create mode 100644 testsuite/tests/Ravenscar/example0/stmt/test.opt create mode 100644 testsuite/tests/Ravenscar/example0/stmt/test.py create mode 100644 testsuite/tests/S213-006-obligation-stats/src/foo.adb create mode 100644 testsuite/tests/S213-006-obligation-stats/src/test.adb create mode 100644 testsuite/tests/S213-006-obligation-stats/test.py create mode 100644 testsuite/tests/S218-011-time-option/main.adb create mode 100644 testsuite/tests/S218-011-time-option/test.py create mode 100644 testsuite/tests/S220-058-auto-scos-fetch/main.adb create mode 100644 testsuite/tests/S220-058-auto-scos-fetch/test.py create mode 100644 testsuite/tests/S506-014-mix-providers/main.adb create mode 100644 testsuite/tests/S506-014-mix-providers/test.opt create mode 100644 testsuite/tests/S506-014-mix-providers/test.py create mode 100644 testsuite/tests/S527-004-ckpt-no-level/main.adb create mode 100644 testsuite/tests/S527-004-ckpt-no-level/test.py create mode 100644 testsuite/tests/S529-038-isi-ckpt/main1.adb create mode 100644 testsuite/tests/S529-038-isi-ckpt/main2.adb create mode 100644 testsuite/tests/S529-038-isi-ckpt/test.py create mode 100644 testsuite/tests/S603-009-externally-built/main/main.adb create mode 100644 testsuite/tests/S603-009-externally-built/main/main.gpr create mode 100644 testsuite/tests/S603-009-externally-built/mylib/mylib.adb create mode 100644 testsuite/tests/S603-009-externally-built/mylib/mylib.ads create mode 100644 testsuite/tests/S603-009-externally-built/mylib/mylib.gpr create mode 100644 testsuite/tests/S603-009-externally-built/test.opt create mode 100644 testsuite/tests/S603-009-externally-built/test.py create mode 100644 testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.adb create mode 100644 testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.ads create mode 100644 testsuite/tests/S619-014-tag-provider-mismatch/main.adb create mode 100644 testsuite/tests/S619-014-tag-provider-mismatch/test.py create mode 100644 testsuite/tests/S621-026-mcdc-ckpt/main1.adb create mode 100644 testsuite/tests/S621-026-mcdc-ckpt/main2.adb create mode 100644 testsuite/tests/S621-026-mcdc-ckpt/test.py create mode 100644 testsuite/tests/S820-013-ckpt-dup-scos/bar.h create mode 100644 testsuite/tests/S820-013-ckpt-dup-scos/foo.c create mode 100644 testsuite/tests/S820-013-ckpt-dup-scos/main.c create mode 100644 testsuite/tests/S820-013-ckpt-dup-scos/test.opt create mode 100644 testsuite/tests/S820-013-ckpt-dup-scos/test.py create mode 100644 testsuite/tests/SB06-033-homonyms/.gitignore create mode 100644 testsuite/tests/SB06-033-homonyms/app/default.gpr create mode 100644 testsuite/tests/SB06-033-homonyms/app/main.adb create mode 100644 testsuite/tests/SB06-033-homonyms/libfoo/lib.adb create mode 100644 testsuite/tests/SB06-033-homonyms/libfoo/lib.ads create mode 100644 testsuite/tests/SB06-033-homonyms/libfoo/libfoo.gpr create mode 100644 testsuite/tests/SB06-033-homonyms/test.opt create mode 100644 testsuite/tests/SB06-033-homonyms/test.py create mode 100644 testsuite/tests/SanityCheck/decision/Engines/src/engines.adb create mode 100644 testsuite/tests/SanityCheck/decision/Engines/src/engines.ads create mode 100644 testsuite/tests/SanityCheck/decision/Engines/src/test_engines_both.adb create mode 100644 testsuite/tests/SanityCheck/decision/Engines/src/test_engines_null.adb create mode 100644 testsuite/tests/SanityCheck/decision/Engines/src/test_engines_stable.adb create mode 100644 testsuite/tests/SanityCheck/decision/Engines/src/test_engines_unstable.adb create mode 100644 testsuite/tests/SanityCheck/decision/Engines/test.py create mode 100644 testsuite/tests/T117-007-intf-thunks/src/action.ads create mode 100644 testsuite/tests/T117-007-intf-thunks/src/interface_a.ads create mode 100644 testsuite/tests/T117-007-intf-thunks/src/package_a.adb create mode 100644 testsuite/tests/T117-007-intf-thunks/src/package_a.ads create mode 100644 testsuite/tests/T117-007-intf-thunks/src/ut_main.adb create mode 100644 testsuite/tests/T117-007-intf-thunks/test.opt create mode 100644 testsuite/tests/T117-007-intf-thunks/test.py create mode 100644 testsuite/tests/T319-018-if-expr/src/pkg.adb create mode 100644 testsuite/tests/T319-018-if-expr/src/pkg.ads create mode 100644 testsuite/tests/T319-018-if-expr/src/proc.adb create mode 100644 testsuite/tests/T319-018-if-expr/src/test_all.adb create mode 100644 testsuite/tests/T319-018-if-expr/src/test_false.adb create mode 100644 testsuite/tests/T319-018-if-expr/src/test_no.adb create mode 100644 testsuite/tests/T319-018-if-expr/src/test_true.adb create mode 100644 testsuite/tests/T319-018-if-expr/test.opt create mode 100644 testsuite/tests/T319-018-if-expr/test.py create mode 100644 testsuite/tests/T331-043-native-warn/main.adb create mode 100644 testsuite/tests/T331-043-native-warn/test.py create mode 100644 testsuite/tests/T520-035-exit-when/src/parser.adb create mode 100644 testsuite/tests/T520-035-exit-when/src/parser.ads create mode 100644 testsuite/tests/T520-035-exit-when/src/test_parser_0.adb create mode 100644 testsuite/tests/T520-035-exit-when/src/test_parser_full.adb create mode 100644 testsuite/tests/T520-035-exit-when/src/test_parser_fx.adb create mode 100644 testsuite/tests/T520-035-exit-when/src/test_parser_tf.adb create mode 100644 testsuite/tests/T520-035-exit-when/src/test_parser_tt.adb create mode 100644 testsuite/tests/T520-035-exit-when/test.py create mode 100644 testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.adb create mode 100644 testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.ads create mode 100644 testsuite/tests/T528-018-dup-proj-crash/src-p2/p2.adb create mode 100644 testsuite/tests/T528-018-dup-proj-crash/test.py create mode 100644 testsuite/tests/T611-027-dump-units-to/main.adb create mode 100644 testsuite/tests/T611-027-dump-units-to/pkg.adb create mode 100644 testsuite/tests/T611-027-dump-units-to/pkg.ads create mode 100644 testsuite/tests/T611-027-dump-units-to/test.py create mode 100644 testsuite/tests/T629-012-pragmas/test.py create mode 100644 testsuite/tests/T731-036-ckpt-bdd/test.opt create mode 100644 testsuite/tests/T731-036-ckpt-bdd/test.py create mode 100644 testsuite/tests/T807-011-externally-built-objdir/.gitignore create mode 100644 testsuite/tests/T807-011-externally-built-objdir/opslib/ops.adb create mode 100644 testsuite/tests/T807-011-externally-built-objdir/opslib/ops.ads create mode 100644 testsuite/tests/T807-011-externally-built-objdir/opslib/opslib.gpr create mode 100644 testsuite/tests/T807-011-externally-built-objdir/test.py create mode 100644 testsuite/tests/T807-011-externally-built-objdir/tests.gpr create mode 100644 testsuite/tests/T807-011-externally-built-objdir/tests/test_inc.adb create mode 100644 testsuite/tests/T825-010-naming-scheme/main.adb create mode 100644 testsuite/tests/T825-010-naming-scheme/p.1.ada create mode 100644 testsuite/tests/T825-010-naming-scheme/p.2.ada create mode 100644 testsuite/tests/T825-010-naming-scheme/p__q.1.ada create mode 100644 testsuite/tests/T825-010-naming-scheme/p__q.2.ada create mode 100644 testsuite/tests/T825-010-naming-scheme/test.py create mode 100644 testsuite/tests/T828-018-tagged-aggr/src/pkg.adb create mode 100644 testsuite/tests/T828-018-tagged-aggr/src/pkg.ads create mode 100644 testsuite/tests/T828-018-tagged-aggr/src/test_full.adb create mode 100644 testsuite/tests/T828-018-tagged-aggr/src/test_no.adb create mode 100644 testsuite/tests/T828-018-tagged-aggr/test.py create mode 100644 testsuite/tests/T916-046-bdd-remapping/main.adb create mode 100644 testsuite/tests/T916-046-bdd-remapping/pkg-compute_in_stub.adb create mode 100644 testsuite/tests/T916-046-bdd-remapping/pkg.adb create mode 100644 testsuite/tests/T916-046-bdd-remapping/pkg.ads create mode 100644 testsuite/tests/T916-046-bdd-remapping/test.py create mode 100644 testsuite/tests/TA12-013-dump-ignore-src-files/foo.c create mode 100644 testsuite/tests/TA12-013-dump-ignore-src-files/identity.h create mode 100644 testsuite/tests/TA12-013-dump-ignore-src-files/main.adb create mode 100644 testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test-sep.adb create mode 100644 testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test.adb create mode 100644 testsuite/tests/TA12-013-dump-ignore-src-files/pkg.adb create mode 100644 testsuite/tests/TA12-013-dump-ignore-src-files/pkg.ads create mode 100644 testsuite/tests/TA12-013-dump-ignore-src-files/pkh-test.adb create mode 100644 testsuite/tests/TA12-013-dump-ignore-src-files/pkh.adb create mode 100644 testsuite/tests/TA12-013-dump-ignore-src-files/pkh.ads create mode 100644 testsuite/tests/TA12-013-dump-ignore-src-files/test.py create mode 100644 testsuite/tests/TA14-011-show-mcdc-vectors/main.adb create mode 100644 testsuite/tests/TA14-011-show-mcdc-vectors/pkg.adb create mode 100644 testsuite/tests/TA14-011-show-mcdc-vectors/pkg.ads create mode 100644 testsuite/tests/TA14-011-show-mcdc-vectors/test.py create mode 100644 testsuite/tests/TA15-063-ignore-fingerprint/src-test1/main.adb create mode 100644 testsuite/tests/TA15-063-ignore-fingerprint/src-test1/pkg-test.adb create mode 100644 testsuite/tests/TA15-063-ignore-fingerprint/src/main.adb create mode 100644 testsuite/tests/TA15-063-ignore-fingerprint/src/pkg-test.adb create mode 100644 testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.adb create mode 100644 testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.ads create mode 100644 testsuite/tests/TA15-063-ignore-fingerprint/test.py create mode 100644 testsuite/tests/TA15-063-ignore-fingerprint/test1.gpr create mode 100644 testsuite/tests/TA27-015-ignore-source-files-source-coverage/main.adb create mode 100644 testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg-say_goodbye.adb create mode 100644 testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.adb create mode 100644 testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.ads create mode 100644 testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py create mode 100644 testsuite/tests/TB13-020-expr-func-mcdc/main.adb create mode 100644 testsuite/tests/TB13-020-expr-func-mcdc/pkg.adb create mode 100644 testsuite/tests/TB13-020-expr-func-mcdc/pkg.ads create mode 100644 testsuite/tests/TB13-020-expr-func-mcdc/test.opt create mode 100644 testsuite/tests/TB13-020-expr-func-mcdc/test.py create mode 100644 testsuite/tests/TB24-022-missing-sid/src-p1/p1.adb create mode 100644 testsuite/tests/TB24-022-missing-sid/src-p1/p1.ads create mode 100644 testsuite/tests/TB24-022-missing-sid/src-p2/p2.adb create mode 100644 testsuite/tests/TB24-022-missing-sid/test.py create mode 100644 testsuite/tests/TC03-012-objcov-line-state/main.c create mode 100644 testsuite/tests/TC03-012-objcov-line-state/main.s create mode 100644 testsuite/tests/TC03-012-objcov-line-state/test.opt create mode 100644 testsuite/tests/TC03-012-objcov-line-state/test.py create mode 100644 testsuite/tests/TC11-052-internal-error/main.adb create mode 100644 testsuite/tests/TC11-052-internal-error/test.py create mode 100644 testsuite/tests/U128-004-displayed-percentages/main1.adb create mode 100644 testsuite/tests/U128-004-displayed-percentages/main99.adb create mode 100644 testsuite/tests/U128-004-displayed-percentages/pkg.adb create mode 100644 testsuite/tests/U128-004-displayed-percentages/pkg.ads create mode 100644 testsuite/tests/U128-004-displayed-percentages/test.py create mode 100644 testsuite/tests/U128-029-missing-dump-trigger/main.adb create mode 100644 testsuite/tests/U128-029-missing-dump-trigger/test.py create mode 100644 testsuite/tests/U204-026-arch-mix/foo.gpr create mode 100755 testsuite/tests/U204-026-arch-mix/gen.sh create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_1.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_2.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.adb create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.adb create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.adb create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid create mode 100644 testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt create mode 100644 testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt create mode 100644 testsuite/tests/U204-026-arch-mix/gen/main_1.srctrace create mode 100644 testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace create mode 100644 testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt create mode 100644 testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_1.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_2.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.adb create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.adb create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.adb create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid create mode 100644 testsuite/tests/U204-026-arch-mix/main_1.adb create mode 100644 testsuite/tests/U204-026-arch-mix/main_2.adb create mode 100644 testsuite/tests/U204-026-arch-mix/pkg.adb create mode 100644 testsuite/tests/U204-026-arch-mix/pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/test.py create mode 100644 testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_1.adb create mode 100644 testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_2.adb create mode 100644 testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_1.adb create mode 100644 testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_2.adb create mode 100644 testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.adb create mode 100644 testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.ads create mode 100644 testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.adb create mode 100644 testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.ads create mode 100644 testsuite/tests/U204-029-source-rebase/Ada/test.py create mode 100644 testsuite/tests/U204-029-source-rebase/C/src/a/pkg.h create mode 100644 testsuite/tests/U204-029-source-rebase/C/src/b/pkg.h create mode 100644 testsuite/tests/U204-029-source-rebase/C/src/main1.c create mode 100644 testsuite/tests/U204-029-source-rebase/C/src/main2.c create mode 100644 testsuite/tests/U204-029-source-rebase/C/test.opt create mode 100644 testsuite/tests/U204-029-source-rebase/C/test.py create mode 100644 testsuite/tests/U204-029-source-rebase/test_support.py create mode 100644 testsuite/tests/U208-020-child-project/p-child-src/main.adb create mode 100644 testsuite/tests/U208-020-child-project/p-child.gpr create mode 100644 testsuite/tests/U208-020-child-project/p-src/pkg.adb create mode 100644 testsuite/tests/U208-020-child-project/p-src/pkg.ads create mode 100644 testsuite/tests/U208-020-child-project/p.gpr create mode 100644 testsuite/tests/U208-020-child-project/test.opt create mode 100644 testsuite/tests/U208-020-child-project/test.py create mode 100644 testsuite/tests/U208-020-error-call/main.c create mode 100644 testsuite/tests/U208-020-error-call/test.opt create mode 100644 testsuite/tests/U208-020-error-call/test.py create mode 100644 testsuite/tests/U208-020-unique-language-project/main.adb create mode 100644 testsuite/tests/U208-020-unique-language-project/main.c create mode 100644 testsuite/tests/U208-020-unique-language-project/test.opt create mode 100644 testsuite/tests/U208-020-unique-language-project/test.py create mode 100644 testsuite/tests/U211-014-setup/ext_rt/ext_rt.gpr create mode 100644 testsuite/tests/U211-014-setup/ext_rt/gnatcov_rts-base_io.adb create mode 100644 testsuite/tests/U211-014-setup/src-ada/foo.adb create mode 100644 testsuite/tests/U211-014-setup/src-c/foo.c create mode 100644 testsuite/tests/U211-014-setup/src-mixed/bar.c create mode 100644 testsuite/tests/U211-014-setup/src-mixed/foo.adb create mode 100644 testsuite/tests/U211-014-setup/src-mixed/pkg.adb create mode 100644 testsuite/tests/U211-014-setup/src-mixed/pkg.ads create mode 100644 testsuite/tests/U211-014-setup/test.py create mode 100644 testsuite/tests/U219-010-ali-entry-guard-sloc/main.adb create mode 100644 testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt create mode 100644 testsuite/tests/U219-010-ali-entry-guard-sloc/test.py create mode 100644 testsuite/tests/U219-010-wrong-sloc-dominant-decision/main.adb create mode 100644 testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.opt create mode 100644 testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.py create mode 100644 testsuite/tests/U317-004-xml-report/main.adb create mode 100644 testsuite/tests/U317-004-xml-report/test.py create mode 100644 testsuite/tests/U416-006-big-bdd/src/compute.c create mode 100644 testsuite/tests/U416-006-big-bdd/src/test_eval.adb create mode 100644 testsuite/tests/U416-006-big-bdd/src/testconditions.adb create mode 100644 testsuite/tests/U416-006-big-bdd/src/testconditions.ads create mode 100644 testsuite/tests/U416-006-big-bdd/test.py create mode 100644 testsuite/tests/U527-020-dc-from-mcdc/main.adb create mode 100644 testsuite/tests/U527-020-dc-from-mcdc/test.py create mode 100644 testsuite/tests/U630-040-static-decision/src/p.ads create mode 100644 testsuite/tests/U630-040-static-decision/src/test_p.adb create mode 100644 testsuite/tests/U630-040-static-decision/test.opt create mode 100644 testsuite/tests/U630-040-static-decision/test.py create mode 100644 testsuite/tests/U811-028-suppress-output/main.adb create mode 100644 testsuite/tests/U811-028-suppress-output/test.py create mode 100644 testsuite/tests/U901-029-estamps/main.adb create mode 100644 testsuite/tests/U901-029-estamps/test.opt create mode 100644 testsuite/tests/U901-029-estamps/test.py create mode 100644 testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.adb create mode 100644 testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.ads create mode 100644 testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.adb create mode 100644 testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.ads create mode 100644 testsuite/tests/UA21-030-elab_mcdc_state/src/test_elab.adb create mode 100644 testsuite/tests/UA21-030-elab_mcdc_state/test.py create mode 100644 testsuite/tests/UB18-055-switches-in-gprfile/a/main.adb create mode 100644 testsuite/tests/UB18-055-switches-in-gprfile/b/b.adb create mode 100644 testsuite/tests/UB18-055-switches-in-gprfile/b/b.ads create mode 100644 testsuite/tests/UB18-055-switches-in-gprfile/c/c.adb create mode 100644 testsuite/tests/UB18-055-switches-in-gprfile/c/c.ads create mode 100644 testsuite/tests/UB18-055-switches-in-gprfile/test.py create mode 100644 testsuite/tests/V120-034-dup-langs/main.adb create mode 100644 testsuite/tests/V120-034-dup-langs/test.py create mode 100644 testsuite/tests/V201-010-multi-report/main.adb create mode 100644 testsuite/tests/V201-010-multi-report/test.py create mode 100644 testsuite/tests/V304-007-missing-files/baz.adb create mode 100644 testsuite/tests/V304-007-missing-files/foo.adb create mode 100644 testsuite/tests/V304-007-missing-files/test.opt create mode 100644 testsuite/tests/V304-007-missing-files/test.py create mode 100644 testsuite/tests/V309-017-setup-config/foo.adb create mode 100644 testsuite/tests/V309-017-setup-config/test.opt create mode 100644 testsuite/tests/V309-017-setup-config/test.py create mode 100644 testsuite/tests/V520-019-duplicate-messages/main.adb create mode 100644 testsuite/tests/V520-019-duplicate-messages/pkg.adb create mode 100644 testsuite/tests/V520-019-duplicate-messages/pkg.ads create mode 100644 testsuite/tests/V520-019-duplicate-messages/test.py create mode 100644 testsuite/tests/V616-028-xsd-check/lib.c create mode 100644 testsuite/tests/V616-028-xsd-check/pkg.adb create mode 100644 testsuite/tests/V616-028-xsd-check/pkg.ads create mode 100644 testsuite/tests/V616-028-xsd-check/test.adb create mode 100644 testsuite/tests/V616-028-xsd-check/test.py create mode 100644 testsuite/tests/V824-005-sid-ext-prj/ext_pkg.gpr create mode 100644 testsuite/tests/V824-005-sid-ext-prj/pkg.gpr create mode 100644 testsuite/tests/V824-005-sid-ext-prj/src-ext_pkg/main.adb create mode 100644 testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.adb create mode 100644 testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.ads create mode 100644 testsuite/tests/V824-005-sid-ext-prj/test.py create mode 100644 testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.c create mode 100644 testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.h create mode 100644 testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.c create mode 100644 testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py create mode 100644 testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.c create mode 100644 testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py create mode 100644 testsuite/tests/VA04-023-non-instr-sco-reloc/main.adb create mode 100644 testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_1.ads create mode 100644 testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_2.ads create mode 100644 testsuite/tests/VA04-023-non-instr-sco-reloc/test.opt create mode 100644 testsuite/tests/VA04-023-non-instr-sco-reloc/test.py create mode 100644 testsuite/tests/VB07-015-clean-output-dir/main.adb create mode 100644 testsuite/tests/VB07-015-clean-output-dir/pkg.adb create mode 100644 testsuite/tests/VB07-015-clean-output-dir/pkg.ads create mode 100644 testsuite/tests/VB07-015-clean-output-dir/test.py create mode 100644 testsuite/tests/VB18-035-default-opts/main.adb create mode 100644 testsuite/tests/VB18-035-default-opts/test.py create mode 100644 testsuite/tests/VB21-022-sid-srctrace-mismatch/main.adb create mode 100644 testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py create mode 100644 testsuite/tests/Z999-999/test.opt create mode 100644 testsuite/tests/Z999-999/test.py create mode 100644 testsuite/tests/asm-consolidate/src/lib.adb create mode 100644 testsuite/tests/asm-consolidate/src/lib.ads create mode 100644 testsuite/tests/asm-consolidate/src/p1.adb create mode 100644 testsuite/tests/asm-consolidate/src/p2.adb create mode 100644 testsuite/tests/asm-consolidate/src/stuff1.adb create mode 100644 testsuite/tests/asm-consolidate/src/stuff1.ads create mode 100644 testsuite/tests/asm-consolidate/test.opt create mode 100644 testsuite/tests/asm-consolidate/test.py create mode 100644 testsuite/tests/branch-cond/IB11-006-compare-floats/inrange.adb create mode 100644 testsuite/tests/branch-cond/IB11-006-compare-floats/test.py create mode 100644 testsuite/tests/branch-cond/IB12-008-postcond/checkx.adb create mode 100644 testsuite/tests/branch-cond/IB12-008-postcond/test.py create mode 100644 testsuite/tests/branch-cond/IB12-016-lone-not/eval_not.adb create mode 100644 testsuite/tests/branch-cond/IB12-016-lone-not/not_if.adb create mode 100644 testsuite/tests/branch-cond/IB12-016-lone-not/test.py create mode 100644 testsuite/tests/branch-cond/IB12-019-fncalls/services.adb create mode 100644 testsuite/tests/branch-cond/IB12-019-fncalls/services.ads create mode 100644 testsuite/tests/branch-cond/IB12-019-fncalls/test.py create mode 100644 testsuite/tests/branch-cond/IB12-028-length/empty.adb create mode 100644 testsuite/tests/branch-cond/IB12-028-length/test.py create mode 100644 testsuite/tests/branch-cond/IB13-014-const-instances/services.adb create mode 100644 testsuite/tests/branch-cond/IB13-014-const-instances/services.ads create mode 100644 testsuite/tests/branch-cond/IB13-014-const-instances/test.opt create mode 100644 testsuite/tests/branch-cond/IB13-014-const-instances/test.py create mode 100644 testsuite/tests/branch-cond/IB13-014-const-instances/test_services.adb create mode 100644 testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.adb create mode 100644 testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.ads create mode 100644 testsuite/tests/branch-cond/IB15-004-spec-precond/services.adb create mode 100644 testsuite/tests/branch-cond/IB15-004-spec-precond/services.ads create mode 100644 testsuite/tests/branch-cond/IB15-004-spec-precond/test.py create mode 100644 testsuite/tests/branch-cond/IB15-004-spec-precond/test_services.ads create mode 100644 testsuite/tests/branch-cond/IB18-024-float-precond/checki.adb create mode 100644 testsuite/tests/branch-cond/IB18-024-float-precond/checki.ads create mode 100644 testsuite/tests/branch-cond/IB18-024-float-precond/checkx.adb create mode 100644 testsuite/tests/branch-cond/IB18-024-float-precond/checkx.ads create mode 100644 testsuite/tests/branch-cond/IB18-024-float-precond/test.py create mode 100644 testsuite/tests/branch-cond/IB19-001-precond-false/check.adb create mode 100644 testsuite/tests/branch-cond/IB19-001-precond-false/check.ads create mode 100644 testsuite/tests/branch-cond/IB19-001-precond-false/test.opt create mode 100644 testsuite/tests/branch-cond/IB19-001-precond-false/test.py create mode 100644 testsuite/tests/branch-cond/IB20-015-length-check/starts.adb create mode 100644 testsuite/tests/branch-cond/IB20-015-length-check/test.py create mode 100644 testsuite/tests/branch-cond/IB20-027-addr-compare/regions.adb create mode 100644 testsuite/tests/branch-cond/IB20-027-addr-compare/regions.ads create mode 100644 testsuite/tests/branch-cond/IB20-027-addr-compare/test.py create mode 100644 testsuite/tests/branch-cond/IB23-016-range-test/checkx.adb create mode 100644 testsuite/tests/branch-cond/IB23-016-range-test/test.py create mode 100644 testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.adb create mode 100644 testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.ads create mode 100644 testsuite/tests/branch-cond/IB25-022-shortcut-actions/test.py create mode 100644 testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.adb create mode 100644 testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.ads create mode 100644 testsuite/tests/branch-cond/IC01-011-null-fatp/test.py create mode 100644 testsuite/tests/branch-cond/IC01-032-itype-early-elab/starts.adb create mode 100644 testsuite/tests/branch-cond/IC01-032-itype-early-elab/test.py create mode 100644 testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.adb create mode 100644 testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.ads create mode 100644 testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/test.py create mode 100644 testsuite/tests/branch-cond/IC02-020-shortcut-action/check.adb create mode 100644 testsuite/tests/branch-cond/IC02-020-shortcut-action/check.ads create mode 100644 testsuite/tests/branch-cond/IC02-020-shortcut-action/test.py create mode 100644 testsuite/tests/branch-cond/J205-019-and-not/check.adb create mode 100644 testsuite/tests/branch-cond/J205-019-and-not/foo.adb create mode 100644 testsuite/tests/branch-cond/J205-019-and-not/foo2.adb create mode 100644 testsuite/tests/branch-cond/J205-019-and-not/foo3.adb create mode 100644 testsuite/tests/branch-cond/J205-019-and-not/test.py create mode 100644 testsuite/tests/branch-cond/J205-021-slice-compare/p.adb create mode 100644 testsuite/tests/branch-cond/J205-021-slice-compare/test.py create mode 100644 testsuite/tests/branch-cond/extra.opt create mode 100644 testsuite/tests/exemptions-check/expected create mode 100644 testsuite/tests/exemptions-check/src/hello.adb create mode 100644 testsuite/tests/exemptions-check/test.opt create mode 100644 testsuite/tests/exemptions-check/test.py create mode 100755 testsuite/tests/gnatcov-run.py create mode 100644 testsuite/tests/gpr-scos/src/dec.adb create mode 100644 testsuite/tests/gpr-scos/src/inc.adb create mode 100644 testsuite/tests/gpr-scos/src/test_ops.adb create mode 100644 testsuite/tests/gpr-scos/test.py create mode 100644 testsuite/tests/instr-cov/C++/c++_no_warnings/main.cpp create mode 100644 testsuite/tests/instr-cov/C++/c++_no_warnings/test.py create mode 100644 testsuite/tests/instr-cov/C++/cpp-extern-c-main/main.cpp create mode 100644 testsuite/tests/instr-cov/C++/cpp-extern-c-main/test.py create mode 100644 testsuite/tests/instr-cov/C++/explicit_lang/main.c create mode 100644 testsuite/tests/instr-cov/C++/explicit_lang/test.py create mode 100644 testsuite/tests/instr-cov/C++/std-c++20/cmdline.cpp create mode 100644 testsuite/tests/instr-cov/C++/std-c++20/cmdline.hh create mode 100644 testsuite/tests/instr-cov/C++/std-c++20/main.cpp create mode 100644 testsuite/tests/instr-cov/C++/std-c++20/test.py create mode 100644 testsuite/tests/instr-cov/C++/std-cond-code/main.cpp create mode 100644 testsuite/tests/instr-cov/C++/std-cond-code/test.py create mode 100644 testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.c create mode 100644 testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.h create mode 100644 testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.c create mode 100644 testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.h create mode 100644 testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src/main.c create mode 100644 testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py create mode 100644 testsuite/tests/instr-cov/basic_base64/main.adb create mode 100644 testsuite/tests/instr-cov/basic_base64/pkg.adb create mode 100644 testsuite/tests/instr-cov/basic_base64/pkg.ads create mode 100644 testsuite/tests/instr-cov/basic_base64/test.py create mode 100644 testsuite/tests/instr-cov/basic_decision/main.adb create mode 100644 testsuite/tests/instr-cov/basic_decision/p.gpr create mode 100644 testsuite/tests/instr-cov/basic_decision/pkg.adb create mode 100644 testsuite/tests/instr-cov/basic_decision/pkg.ads create mode 100644 testsuite/tests/instr-cov/basic_decision/test.py create mode 100644 testsuite/tests/instr-cov/basic_stmt/main.adb create mode 100644 testsuite/tests/instr-cov/basic_stmt/p.gpr create mode 100644 testsuite/tests/instr-cov/basic_stmt/pkg.adb create mode 100644 testsuite/tests/instr-cov/basic_stmt/pkg.ads create mode 100644 testsuite/tests/instr-cov/basic_stmt/test.py create mode 100644 testsuite/tests/instr-cov/bin_file_tunings/main.adb create mode 100644 testsuite/tests/instr-cov/bin_file_tunings/test.opt create mode 100644 testsuite/tests/instr-cov/bin_file_tunings/test.py create mode 100644 testsuite/tests/instr-cov/c_custom_naming/hello.cc create mode 100644 testsuite/tests/instr-cov/c_custom_naming/main.cc create mode 100644 testsuite/tests/instr-cov/c_custom_naming/test.opt create mode 100644 testsuite/tests/instr-cov/c_custom_naming/test.py create mode 100644 testsuite/tests/instr-cov/c_empty_source/main.c create mode 100644 testsuite/tests/instr-cov/c_empty_source/pkg.c create mode 100644 testsuite/tests/instr-cov/c_empty_source/pkg.h create mode 100644 testsuite/tests/instr-cov/c_empty_source/test.py create mode 100644 testsuite/tests/instr-cov/c_gpr_opts/hello.c create mode 100644 testsuite/tests/instr-cov/c_gpr_opts/main.c create mode 100644 testsuite/tests/instr-cov/c_gpr_opts/test.py create mode 100644 testsuite/tests/instr-cov/c_header/fact.h create mode 100644 testsuite/tests/instr-cov/c_header/main.c create mode 100644 testsuite/tests/instr-cov/c_header/test.py create mode 100644 testsuite/tests/instr-cov/c_macros_no_cov_warnings/dummy-print.c create mode 100644 testsuite/tests/instr-cov/c_macros_no_cov_warnings/main.c create mode 100644 testsuite/tests/instr-cov/c_macros_no_cov_warnings/test.py create mode 100644 testsuite/tests/instr-cov/c_multiline_stmt/main.c create mode 100644 testsuite/tests/instr-cov/c_multiline_stmt/pkg.c create mode 100644 testsuite/tests/instr-cov/c_multiline_stmt/pkg.h create mode 100644 testsuite/tests/instr-cov/c_multiline_stmt/test.opt create mode 100644 testsuite/tests/instr-cov/c_multiline_stmt/test.py create mode 100644 testsuite/tests/instr-cov/c_no_return/empty_main/main.c create mode 100644 testsuite/tests/instr-cov/c_no_return/no_return/main.c create mode 100644 testsuite/tests/instr-cov/c_no_return/test.py create mode 100644 testsuite/tests/instr-cov/c_opts/hello.c create mode 100644 testsuite/tests/instr-cov/c_opts/main.c create mode 100644 testsuite/tests/instr-cov/c_opts/other/hello.h create mode 100644 testsuite/tests/instr-cov/c_opts/test.py create mode 100644 testsuite/tests/instr-cov/c_prep_error/main.c create mode 100644 testsuite/tests/instr-cov/c_prep_error/test.py create mode 100644 testsuite/tests/instr-cov/c_special_filenames/$foo@bar$.c create mode 100644 testsuite/tests/instr-cov/c_special_filenames/ada_main.adb create mode 100644 testsuite/tests/instr-cov/c_special_filenames/main.c create mode 100644 testsuite/tests/instr-cov/c_special_filenames/test.opt create mode 100644 testsuite/tests/instr-cov/c_special_filenames/test.py create mode 100644 testsuite/tests/instr-cov/c_ternary_in_if_cond/main.c create mode 100644 testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py create mode 100644 testsuite/tests/instr-cov/c_wrong_main/main.c create mode 100644 testsuite/tests/instr-cov/c_wrong_main/test.py create mode 100644 testsuite/tests/instr-cov/checks_and_warnings/main.adb create mode 100644 testsuite/tests/instr-cov/checks_and_warnings/p.gpr create mode 100644 testsuite/tests/instr-cov/checks_and_warnings/pkg.ads create mode 100644 testsuite/tests/instr-cov/checks_and_warnings/test.opt create mode 100644 testsuite/tests/instr-cov/checks_and_warnings/test.py create mode 100644 testsuite/tests/instr-cov/consistency/main.adb create mode 100644 testsuite/tests/instr-cov/consistency/p.gpr create mode 100644 testsuite/tests/instr-cov/consistency/test.py create mode 100644 testsuite/tests/instr-cov/decl-inversion/src/test_foo.adb create mode 100644 testsuite/tests/instr-cov/decl-inversion/test.opt create mode 100644 testsuite/tests/instr-cov/decl-inversion/test.py create mode 100644 testsuite/tests/instr-cov/default_dump_channel/main.adb create mode 100644 testsuite/tests/instr-cov/default_dump_channel/test.opt create mode 100644 testsuite/tests/instr-cov/default_dump_channel/test.py create mode 100644 testsuite/tests/instr-cov/end_slocs/main.adb create mode 100644 testsuite/tests/instr-cov/end_slocs/p.gpr create mode 100644 testsuite/tests/instr-cov/end_slocs/test.py create mode 100644 testsuite/tests/instr-cov/endianity/main.adb create mode 100644 testsuite/tests/instr-cov/endianity/pkg.adb create mode 100644 testsuite/tests/instr-cov/endianity/pkg.ads create mode 100644 testsuite/tests/instr-cov/endianity/test.py create mode 100644 testsuite/tests/instr-cov/explicit_mains/foo.s create mode 100644 testsuite/tests/instr-cov/explicit_mains/main1.adb create mode 100644 testsuite/tests/instr-cov/explicit_mains/main2.adb create mode 100644 testsuite/tests/instr-cov/explicit_mains/mylib/pkg.adb create mode 100644 testsuite/tests/instr-cov/explicit_mains/mylib/pkg.ads create mode 100644 testsuite/tests/instr-cov/explicit_mains/test.py create mode 100644 testsuite/tests/instr-cov/explicit_mains_ignore_gpr/bar.adb create mode 100644 testsuite/tests/instr-cov/explicit_mains_ignore_gpr/foo.adb create mode 100644 testsuite/tests/instr-cov/explicit_mains_ignore_gpr/test.py create mode 100644 testsuite/tests/instr-cov/explicit_mains_uoi/main.adb create mode 100644 testsuite/tests/instr-cov/explicit_mains_uoi/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/aggr/main.adb create mode 100644 testsuite/tests/instr-cov/expr_func/aggr/p.gpr create mode 100644 testsuite/tests/instr-cov/expr_func/aggr/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/src/foo.ads create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/src/foo.ads create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/src/foo.ads create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/src/foo.ads create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/readme.txt create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/src/foo.ads create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.opt create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/src/foo.ads create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.opt create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/src/foo.ads create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.opt create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/src/foo.ads create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.opt create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/aspects/src/test_foo.adb create mode 100644 testsuite/tests/instr-cov/expr_func/basic/main.adb create mode 100644 testsuite/tests/instr-cov/expr_func/basic/p.gpr create mode 100644 testsuite/tests/instr-cov/expr_func/basic/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/extra.opt create mode 100644 testsuite/tests/instr-cov/expr_func/generic/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/expr_func/generic/src/test_main.adb create mode 100644 testsuite/tests/instr-cov/expr_func/generic/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/generic_prim/src/inst.ads create mode 100644 testsuite/tests/instr-cov/expr_func/generic_prim/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/expr_func/generic_prim/src/test_pkg.adb create mode 100644 testsuite/tests/instr-cov/expr_func/generic_prim/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/ghost/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/expr_func/ghost/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/expr_func/ghost/src/test_main.adb create mode 100644 testsuite/tests/instr-cov/expr_func/ghost/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/overriding/src/pak.ads create mode 100644 testsuite/tests/instr-cov/expr_func/overriding/src/test_foo.adb create mode 100644 testsuite/tests/instr-cov/expr_func/overriding/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/parameterless/main.adb create mode 100644 testsuite/tests/instr-cov/expr_func/parameterless/p.gpr create mode 100644 testsuite/tests/instr-cov/expr_func/parameterless/pak.ads create mode 100644 testsuite/tests/instr-cov/expr_func/parameterless/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/prev_decl/src/bar.ads create mode 100644 testsuite/tests/instr-cov/expr_func/prev_decl/src/foo.ads create mode 100644 testsuite/tests/instr-cov/expr_func/prev_decl/src/test_decl.adb create mode 100644 testsuite/tests/instr-cov/expr_func/prev_decl/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/prim/main.adb create mode 100644 testsuite/tests/instr-cov/expr_func/prim/p.gpr create mode 100644 testsuite/tests/instr-cov/expr_func/prim/pak.ads create mode 100644 testsuite/tests/instr-cov/expr_func/prim/test.opt create mode 100644 testsuite/tests/instr-cov/expr_func/prim/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/prim2/main.adb create mode 100644 testsuite/tests/instr-cov/expr_func/prim2/p.gpr create mode 100644 testsuite/tests/instr-cov/expr_func/prim2/pak.adb create mode 100644 testsuite/tests/instr-cov/expr_func/prim2/pak.ads create mode 100644 testsuite/tests/instr-cov/expr_func/prim2/test.opt create mode 100644 testsuite/tests/instr-cov/expr_func/prim2/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/program_error/src/test_main.adb create mode 100644 testsuite/tests/instr-cov/expr_func/program_error/test.opt create mode 100644 testsuite/tests/instr-cov/expr_func/program_error/test.py create mode 100644 testsuite/tests/instr-cov/expr_func/quantifier/src/test_main.adb create mode 100644 testsuite/tests/instr-cov/expr_func/quantifier/test.py create mode 100644 testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/dummy.txt create mode 100644 testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/pkg.ads create mode 100644 testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext1/p_ext1-gnatcov-instr/pkg.ads create mode 100644 testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext2/p_ext2-gnatcov-instr/pkg.ads create mode 100644 testsuite/tests/instr-cov/ext_gpr/src/p.gpr create mode 100644 testsuite/tests/instr-cov/ext_gpr/src/p_ext1.gpr create mode 100644 testsuite/tests/instr-cov/ext_gpr/src/p_ext2.gpr create mode 100644 testsuite/tests/instr-cov/ext_gpr/src/src-p/pkg.ads create mode 100644 testsuite/tests/instr-cov/ext_gpr/src/src-p_ext1/pkg1.ads create mode 100644 testsuite/tests/instr-cov/ext_gpr/src/src-p_ext2/pkg2.ads create mode 100644 testsuite/tests/instr-cov/ext_gpr/test.py create mode 100644 testsuite/tests/instr-cov/ghost_generic/gen.adb create mode 100644 testsuite/tests/instr-cov/ghost_generic/gen.ads create mode 100644 testsuite/tests/instr-cov/ghost_generic/main.adb create mode 100644 testsuite/tests/instr-cov/ghost_generic/non_ghost_inst.ads create mode 100644 testsuite/tests/instr-cov/ghost_generic/test.py create mode 100644 testsuite/tests/instr-cov/hidden_standard/src/std.adb create mode 100644 testsuite/tests/instr-cov/hidden_standard/src/std.ads create mode 100644 testsuite/tests/instr-cov/hidden_standard/src/test_std.adb create mode 100644 testsuite/tests/instr-cov/hidden_standard/test.py create mode 100644 testsuite/tests/instr-cov/library_projects/.gitignore create mode 100644 testsuite/tests/instr-cov/library_projects/main.gpr create mode 100644 testsuite/tests/instr-cov/library_projects/math.gpr create mode 100644 testsuite/tests/instr-cov/library_projects/src-main/main.adb create mode 100644 testsuite/tests/instr-cov/library_projects/src-math/math.adb create mode 100644 testsuite/tests/instr-cov/library_projects/src-math/math.ads create mode 100644 testsuite/tests/instr-cov/library_projects/src-vectors/vectors.adb create mode 100644 testsuite/tests/instr-cov/library_projects/src-vectors/vectors.ads create mode 100644 testsuite/tests/instr-cov/library_projects/test.py create mode 100644 testsuite/tests/instr-cov/library_projects/vectors.gpr create mode 100644 testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/main.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/tested.c create mode 100644 testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/main.c create mode 100644 testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.ads create mode 100644 testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py create mode 100644 testsuite/tests/instr-cov/main_autodump/nested_block/dotted-decl.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/nested_block/dotted-exn.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/nested_block/dotted-no_decl.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/nested_block/dotted.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/nested_block/dotted.ads create mode 100644 testsuite/tests/instr-cov/main_autodump/nested_block/simple_decl.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/nested_block/simple_exn.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/nested_block/simple_no_decl.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/nested_block/simple_only_exn.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/nested_block/test.opt create mode 100644 testsuite/tests/instr-cov/main_autodump/nested_block/test.py create mode 100644 testsuite/tests/instr-cov/main_autodump/pramga_prio/main.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/pramga_prio/test.opt create mode 100644 testsuite/tests/instr-cov/main_autodump/pramga_prio/test.py create mode 100644 testsuite/tests/instr-cov/main_autodump/stubs/main-inner.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/stubs/main.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/stubs/test.py create mode 100644 testsuite/tests/instr-cov/main_autodump/stubs_controlled/main-inner.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/stubs_controlled/main.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.ads create mode 100644 testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.opt create mode 100644 testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.py create mode 100644 testsuite/tests/instr-cov/main_autodump/task_in_main/main.adb create mode 100644 testsuite/tests/instr-cov/main_autodump/task_in_main/test.opt create mode 100644 testsuite/tests/instr-cov/main_autodump/task_in_main/test.py create mode 100644 testsuite/tests/instr-cov/manual-dump/covdump__cov.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/covdump__nocov.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/main.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/test.opt create mode 100644 testsuite/tests/instr-cov/manual-dump/test.py create mode 100644 testsuite/tests/instr-cov/mixed_and/main.adb create mode 100644 testsuite/tests/instr-cov/mixed_and/p.gpr create mode 100644 testsuite/tests/instr-cov/mixed_and/test.py create mode 100644 testsuite/tests/instr-cov/multiline_marker/main.c create mode 100644 testsuite/tests/instr-cov/multiline_marker/test.opt create mode 100644 testsuite/tests/instr-cov/multiline_marker/test.py create mode 100644 testsuite/tests/instr-cov/multiple_mains/src/test_a.adb create mode 100644 testsuite/tests/instr-cov/multiple_mains/src/test_b.adb create mode 100644 testsuite/tests/instr-cov/multiple_mains/test.py create mode 100644 testsuite/tests/instr-cov/nested_ternary/main.c create mode 100644 testsuite/tests/instr-cov/nested_ternary/test.py create mode 100644 testsuite/tests/instr-cov/no_main/main.adb create mode 100644 testsuite/tests/instr-cov/no_main/p.gpr create mode 100644 testsuite/tests/instr-cov/no_main/pkg.adb create mode 100644 testsuite/tests/instr-cov/no_main/pkg.ads create mode 100644 testsuite/tests/instr-cov/no_main/test.py create mode 100644 testsuite/tests/instr-cov/not_array/main.adb create mode 100644 testsuite/tests/instr-cov/not_array/p.gpr create mode 100644 testsuite/tests/instr-cov/not_array/test.opt create mode 100644 testsuite/tests/instr-cov/not_array/test.py create mode 100644 testsuite/tests/instr-cov/null_proc_generic/src/main.adb create mode 100644 testsuite/tests/instr-cov/null_proc_generic/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/null_proc_generic/test.opt create mode 100644 testsuite/tests/instr-cov/null_proc_generic/test.py create mode 100644 testsuite/tests/instr-cov/null_proc_not_null/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/null_proc_not_null/src/test_1.adb create mode 100644 testsuite/tests/instr-cov/null_proc_not_null/src/test_12.adb create mode 100644 testsuite/tests/instr-cov/null_proc_not_null/src/test_2.adb create mode 100644 testsuite/tests/instr-cov/null_proc_not_null/src/test_no.adb create mode 100644 testsuite/tests/instr-cov/null_proc_not_null/test.py create mode 100644 testsuite/tests/instr-cov/pragma_after_cu/main.adb create mode 100644 testsuite/tests/instr-cov/pragma_after_cu/raise_error.adb create mode 100644 testsuite/tests/instr-cov/pragma_after_cu/raise_error.ads create mode 100644 testsuite/tests/instr-cov/pragma_after_cu/test.opt create mode 100644 testsuite/tests/instr-cov/pragma_after_cu/test.py create mode 100644 testsuite/tests/instr-cov/pragma_assert/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/pragma_assert/src/test_main.adb create mode 100644 testsuite/tests/instr-cov/pragma_assert/test.opt create mode 100644 testsuite/tests/instr-cov/pragma_assert/test.py create mode 100644 testsuite/tests/instr-cov/pragma_no_body/main.adb create mode 100644 testsuite/tests/instr-cov/pragma_no_body/orig_pkg.adb create mode 100644 testsuite/tests/instr-cov/pragma_no_body/orig_pkg.ads create mode 100644 testsuite/tests/instr-cov/pragma_no_body/pkg.adb create mode 100644 testsuite/tests/instr-cov/pragma_no_body/pkg.ads create mode 100644 testsuite/tests/instr-cov/pragma_no_body/test.opt create mode 100644 testsuite/tests/instr-cov/pragma_no_body/test.py create mode 100644 testsuite/tests/instr-cov/protected_body/src/foo.adb create mode 100644 testsuite/tests/instr-cov/protected_body/src/foo.ads create mode 100644 testsuite/tests/instr-cov/protected_body/src/test_foo.adb create mode 100644 testsuite/tests/instr-cov/protected_body/test.opt create mode 100644 testsuite/tests/instr-cov/protected_body/test.py create mode 100644 testsuite/tests/instr-cov/pure_units/main.adb create mode 100644 testsuite/tests/instr-cov/pure_units/p.gpr create mode 100644 testsuite/tests/instr-cov/pure_units/pkg-child.ads create mode 100644 testsuite/tests/instr-cov/pure_units/pkg.adb create mode 100644 testsuite/tests/instr-cov/pure_units/pkg.ads create mode 100644 testsuite/tests/instr-cov/pure_units/test.opt create mode 100644 testsuite/tests/instr-cov/pure_units/test.py create mode 100644 testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.adb create mode 100644 testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.ads create mode 100644 testsuite/tests/instr-cov/remove_extra_src/src-myprog/prog.adb create mode 100644 testsuite/tests/instr-cov/remove_extra_src/test.py create mode 100644 testsuite/tests/instr-cov/scalar_and/main.adb create mode 100644 testsuite/tests/instr-cov/scalar_and/p.gpr create mode 100644 testsuite/tests/instr-cov/scalar_and/test.py create mode 100644 testsuite/tests/instr-cov/short_circuit_and_or/gnat.adc create mode 100644 testsuite/tests/instr-cov/short_circuit_and_or/main.adb create mode 100644 testsuite/tests/instr-cov/short_circuit_and_or/test.opt create mode 100644 testsuite/tests/instr-cov/short_circuit_and_or/test.py create mode 100644 testsuite/tests/instr-cov/short_circuit_and_or/type_pkg.ads create mode 100644 testsuite/tests/instr-cov/stmt_after_accept/main.adb create mode 100644 testsuite/tests/instr-cov/stmt_after_accept/test.opt create mode 100644 testsuite/tests/instr-cov/stmt_after_accept/test.py create mode 100644 testsuite/tests/instr-cov/unknown_unit/main.adb create mode 100644 testsuite/tests/instr-cov/unknown_unit/p.gpr create mode 100644 testsuite/tests/instr-cov/unknown_unit/pkg.adb create mode 100644 testsuite/tests/instr-cov/unknown_unit/pkg.ads create mode 100644 testsuite/tests/instr-cov/unknown_unit/test.py create mode 100644 testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/src/andthen.adb create mode 100644 testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.opt create mode 100644 testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.py create mode 100644 testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/src/andthen.adb create mode 100644 testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.opt create mode 100644 testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.py create mode 100644 testsuite/tests/limits/Ada/decision/Andthen/src/andthen.ads create mode 100644 testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_0.adb create mode 100644 testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_a.adb create mode 100644 testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_ab.adb create mode 100644 testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_b.adb create mode 100644 testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_f.adb create mode 100644 testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_t.adb create mode 100644 testsuite/tests/scos-overlap/test.c create mode 100644 testsuite/tests/scos-overlap/test.py create mode 100644 testsuite/tests/shared-libs/ada-main/src-main/main.adb create mode 100644 testsuite/tests/shared-libs/ada-main/src-mylib/mylib.adb create mode 100644 testsuite/tests/shared-libs/ada-main/src-mylib/mylib.ads create mode 100644 testsuite/tests/shared-libs/ada-main/test.py create mode 100644 testsuite/tests/shared-libs/c-main/src-main/main.c create mode 100644 testsuite/tests/shared-libs/c-main/src-mylib/mylib.adb create mode 100644 testsuite/tests/shared-libs/c-main/src-mylib/mylib.ads create mode 100644 testsuite/tests/shared-libs/c-main/test.py create mode 100644 testsuite/tests/shared-libs/extra.opt create mode 100644 testsuite/tests/xml-check/src/andthen.adb create mode 100644 testsuite/tests/xml-check/src/test_andthen_t.adb create mode 100644 testsuite/tests/xml-check/test.py diff --git a/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.adb b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.adb new file mode 100644 index 000000000..1eaf550c5 --- /dev/null +++ b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.adb @@ -0,0 +1,12 @@ +package body Counters is + + procedure Dec (C : Counter_Access) is + begin + C.Value := C.Value - 1; + end; + + function Zerop (C : Counter_Access) return Boolean is + begin + return C.Value = 0; + end; +end; diff --git a/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.ads b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.ads new file mode 100644 index 000000000..357824dad --- /dev/null +++ b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/counters.ads @@ -0,0 +1,9 @@ +package Counters is + type Counter is record + Value : Integer; + end record; + type Counter_Access is access all Counter; + + procedure Dec (C : Counter_Access); + function Zerop (C : Counter_Access) return Boolean; +end; diff --git a/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/docount.adb b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/docount.adb new file mode 100644 index 000000000..4fb0bd303 --- /dev/null +++ b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/docount.adb @@ -0,0 +1,10 @@ +with Counters; use Counters; + +procedure Docount is + C : aliased Counter := (Value => 5); + Cref : Counter_Access := C'Unchecked_Access; +begin + while not Zerop (Cref) loop -- # eval + Dec (Cref); + end loop; +end; diff --git a/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/test_docount.adb b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/test_docount.adb new file mode 100644 index 000000000..4db4f2f70 --- /dev/null +++ b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/src/test_docount.adb @@ -0,0 +1,10 @@ +with Support, Docount; use Support; + +procedure Test_Docount is +begin + Docount; + Assert (True); +end; + +--# docount.adb +-- /check/ l+ ## 0 diff --git a/testsuite/tests/Ada/decision/IC17_026-dc-while-not/test.py b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/decision/IC17_026-dc-while-not/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.adb b/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.adb new file mode 100644 index 000000000..f86f16813 --- /dev/null +++ b/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.adb @@ -0,0 +1,20 @@ +package body Add is + type Uint_64 is mod 2 ** 64; + + function "+" (Left : Time; Right : Time_Span) return Stamp is + begin + if Right >= 0 -- # tover0 + and then Uint_64 (Time'Last) - Uint_64 (Left) >= Uint_64 (Right) -- # tover1 + then + return (Valid => True, -- # retplus + Value => Time (Uint_64 (Left) + Uint_64 (Right))); -- # retplus + + elsif Right < 0 and then Left >= Time (abs (Right)) then -- # tunder + return (Valid => True, -- # retmin + Value => Time (Uint_64 (Left) - Uint_64 (abs (Right)))); -- # retmin + + else + return (Valid => False, Value => 0); -- # fault + end if; + end "+"; +end; diff --git a/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.ads b/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.ads new file mode 100644 index 000000000..adebe469d --- /dev/null +++ b/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/add.ads @@ -0,0 +1,14 @@ +package Add is + type Time is mod 2 ** 64; + for Time'Size use 64; + + type Time_Span is range -2 ** 63 .. 2 ** 63 - 1; + for Time_Span'Size use 64; + + type Stamp is record + Valid : Boolean; + Value : Time; + end record; + + function "+" (Left : Time; Right : Time_Span) return Stamp; +end Add; diff --git a/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/test_add.adb b/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/test_add.adb new file mode 100644 index 000000000..817e7f4eb --- /dev/null +++ b/testsuite/tests/Ada/decision/K202_014-elsif-abs/src/test_add.adb @@ -0,0 +1,16 @@ +with Support, Add; use Support, Add; + +procedure Test_Add is +begin + Assert (Time (123) + Time_Span (123) = (True, Time (246))); + Assert (Time (124) + Time_Span (-123) = (True, Time (1))); + Assert (Time (123) + Time_Span (-124) = (False, Time (0))); +end; + +--# add.adb +-- /tover0/ l+ ## 0 +-- /tover1/ l+ ## 0 +-- /retplus/ l+ ## 0 +-- /tunder/ l+ ## 0 +-- /retmin/ l+ ## 0 +-- /fault/ l+ ## 0 diff --git a/testsuite/tests/Ada/decision/K202_014-elsif-abs/test.py b/testsuite/tests/Ada/decision/K202_014-elsif-abs/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/decision/K202_014-elsif-abs/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.adb b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.adb new file mode 100644 index 000000000..92b52b761 --- /dev/null +++ b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.adb @@ -0,0 +1,24 @@ + +package body Plop is + + function Identity (V : Value) return Value; + + function Steps_To_LT (X, LB : Value; Max : Step) return Step is + V : Value := X; + N : Step := 0; + begin + loop + exit when abs(V) < LB or else N >= Max; -- # eval + V := Identity (V) - 1.0; -- # body + N := N + 1; -- # body + end loop; + return N; + end; + + function Identity (V : Value) return Value is + Latch : Value := V; + pragma Volatile (Latch); + begin + return Latch; + end; +end; diff --git a/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.ads b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.ads new file mode 100644 index 000000000..963981bb2 --- /dev/null +++ b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/plop.ads @@ -0,0 +1,5 @@ +package Plop is + type Step is new Long_Integer; + type Value is new Long_Long_Float; + function Steps_To_LT (X, LB : Value; Max : Step) return Step; +end; diff --git a/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/test_tf.adb b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/test_tf.adb new file mode 100644 index 000000000..d3be0803e --- /dev/null +++ b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/src/test_tf.adb @@ -0,0 +1,8 @@ +with Support, Plop; use Support, Plop; +procedure Test_TF is +begin + Assert (Steps_To_LT (X => 5.0, LB => 1.0, Max => 10) = 5); +end; + +--# plop.adb +-- /eval/ l+ ## 0 diff --git a/testsuite/tests/Ada/decision/K303_016-exwhen-abs/test.py b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/test.py new file mode 100644 index 000000000..80df4eeb4 --- /dev/null +++ b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/test.py @@ -0,0 +1,16 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest +from SUITE.control import env + + +# Customer had specific extra options on ppc. We haven't been able to trigger +# a failure on this sample case anyway +if 'power' in env.target.triplet: + target_options = '-mcpu=750 -mbig-endian -meabi -msdata=none -memb' +else: + target_options = '' + +TestCase( + extracargs='-fdata-sections -ffunction-sections ' + target_options).run() + +thistest.result() diff --git a/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.adb b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.adb new file mode 100644 index 000000000..08aa91387 --- /dev/null +++ b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.adb @@ -0,0 +1,89 @@ +with Support; use Support; + +package body Expr is + + procedure As_RHS (A, B : Boolean) is + begin + GB := A and then B; -- # eval + end; + + procedure As_CASE (A, B : Boolean) is + begin + case A and then B is -- # eval + when True => GX := GX + 1; -- # true + when False => GX := GX - 1; -- # false + end case; + end; + + procedure Set_GB (Value : Boolean) is + begin + GB := Value; + end; + + procedure As_ACTUAL (A, B : Boolean) is + begin + Set_GB (A and then B); -- # eval + end; + + function As_RETURN (A, B : Boolean) return Boolean is + begin + return A and then B; -- # eval + end; + + procedure As_DECLINIT (A, B : Boolean) is + X : Boolean := A and then B; -- # eval + pragma Volatile (X); + begin + GB := X; + end; + + type My_Bool (Value : Boolean) is null record; + + procedure As_DISCINIT (A, B : Boolean) is + X : My_Bool (Value => A and then B); -- # eval + pragma Volatile (X); + begin + GB := X.Value; + end; + + type My_Block is array (1 .. 1) of Boolean; + + procedure As_AGGREGATE (A, B : Boolean) is + X : My_Block := (others => A and then B); -- # eval + pragma Volatile (X); + begin + GB := X(X'First); + end; + + pragma Check_Policy (Precondition, On); + pragma Check_Policy (Postcondition, On); + + procedure As_BODYPRECOND (A, B : Boolean) is + pragma Precondition (A and then B); -- # freestanding-expr + begin + GX := GX + 1; + end; + + procedure As_BODYPOSTCOND (A, B : Boolean) is + pragma Postcondition (A and then B); -- # freestanding-expr + begin + GX := GX + 1; + end; + + procedure As_SPECPRECOND (A, B : Boolean) is + begin + GX := GX + 1; + end; + + procedure As_SPECPOSTCOND (A, B : Boolean) is + begin + GX := GX + 1; + end; + + procedure As_DEBUG_ASSERT (A, B : Boolean) is + pragma Debug_Policy (Check); + begin + pragma Debug (Assert (A and then B)); -- # eval + GX := GX + 1; + end; +end; diff --git a/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.ads b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.ads new file mode 100644 index 000000000..9200d7b86 --- /dev/null +++ b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.ads @@ -0,0 +1,31 @@ +package Expr is + + GX : Integer := 0; + pragma Volatile (GX); + + GB : Boolean; + pragma Volatile (GB); + + procedure As_RHS (A, B : Boolean); + procedure As_ACTUAL (A, B : Boolean); + procedure As_CASE (A, B : Boolean); + procedure As_AGGREGATE (A, B : Boolean); + procedure As_DECLINIT (A, B : Boolean); + procedure As_DISCINIT (A, B : Boolean); + + function As_RETURN (A, B : Boolean) return Boolean; + + procedure As_BODYPRECOND (A, B : Boolean); + procedure As_BODYPOSTCOND (A, B : Boolean); + + pragma Check_Policy (Precondition, On); + pragma Check_Policy (Postcondition, On); + + procedure As_SPECPRECOND (A, B : Boolean); + pragma Precondition (A and then B); -- # freestanding-expr + + procedure As_SPECPOSTCOND (A, B : Boolean); + pragma Postcondition (A and then B); -- # freestanding-expr + + procedure As_DEBUG_ASSERT (A, B : Boolean); +end; diff --git a/testsuite/tests/Ada/decision/MA07-028-expr-context/src/test_t.adb b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/test_t.adb new file mode 100644 index 000000000..b9b9168aa --- /dev/null +++ b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/test_t.adb @@ -0,0 +1,29 @@ +with Support, Expr; use Support; + +procedure Test_T is +begin + Expr.As_RHS (A => True, B => True); + Expr.As_ACTUAL (A => True, B => True); + Expr.As_CASE (A => True, B => True); + Expr.As_AGGREGATE (A => True, B => True); + Expr.As_DECLINIT (A => True, B => True); + Expr.As_DISCINIT (A => True, B => True); + + Expr.GB := Expr.As_RETURN (A => True, B => True); + + Expr.As_BODYPRECOND (A => True, B => True); + Expr.As_BODYPOSTCOND (A => True, B => True); + Expr.As_SPECPRECOND (A => True, B => True); + Expr.As_SPECPOSTCOND (A => True, B => True); + + Expr.As_DEBUG_ASSERT (A => True, B => True); +end; + +--# expr.adb +-- /eval/ l+ ## 0 +-- /freestanding-expr/ l. ## 0 +-- /true/ l+ ## 0 +-- /false/ l- ## s- + +--# expr.ads +-- /eval/ l+ ## 0 diff --git a/testsuite/tests/Ada/decision/MA07-028-expr-context/test.py b/testsuite/tests/Ada/decision/MA07-028-expr-context/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/decision/MA07-028-expr-context/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.adb b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.adb new file mode 100644 index 000000000..f80f1e9ed --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Dump (E : Enum) is + Img : constant String := Pkg.Enum_Images (E).all; -- # decl + begin + if Img /= "" then -- # cond + Put_Line ("Image: " & Img); -- # then + end if; + end Dump; + +end Pkg; diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.ads b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.ads new file mode 100644 index 000000000..2059a1e32 --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/pkg.ads @@ -0,0 +1,15 @@ +package Pkg is + + type Enum is (A, B, C); + + Enum_Image_A : aliased constant String := "A"; + Enum_Image_B : aliased constant String := "B"; + Enum_Image_C : aliased constant String := ""; + Enum_Images : constant array (Enum) of access constant String := + (Enum_Image_A'Access, + Enum_Image_B'Access, + Enum_Image_C'Access); + + procedure Dump (E : Enum); + +end Pkg; diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_f.adb b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_f.adb new file mode 100644 index 000000000..63dd51cd0 --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_f.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; + +procedure Test_F is +begin + Pkg.Dump (Pkg.C); +end Test_F; + +--# pkg.adb +-- /decl/ l+ ## 0 +-- /cond/ l! ## dT- +-- /then/ l- ## s- diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_no.adb b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_no.adb new file mode 100644 index 000000000..badf807f5 --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_no.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; + +procedure Test_No is +begin + Put_Line (Pkg.Enum_Images (Pkg.A).all); +end Test_No; + +--# pkg.adb +-- /decl/ l- ## s- +-- /cond/ l- ## s- +-- /then/ l- ## s- diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_t.adb b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_t.adb new file mode 100644 index 000000000..1010f3276 --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_t.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; + +procedure Test_T is +begin + Pkg.Dump (Pkg.A); +end Test_T; + +--# pkg.adb +-- /decl/ l+ ## 0 +-- /cond/ l! ## dF- +-- /then/ l+ ## 0 diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_tf.adb b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_tf.adb new file mode 100644 index 000000000..24a17446a --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/src/test_tf.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; + +procedure Test_TF is +begin + Pkg.Dump (Pkg.A); + Pkg.Dump (Pkg.C); +end Test_TF; + +--# pkg.adb +-- /decl/ l+ ## 0 +-- /cond/ l+ ## 0 +-- /then/ l+ ## 0 diff --git a/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/test.py b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/decision/T922-011-cmp-empty-str/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_ft.adb b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_ft.adb new file mode 100644 index 000000000..b310051fd --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_ft.adb @@ -0,0 +1,14 @@ +with Support, Values; use Support, Values; + +procedure Test_Values_FT is + I1 : Int; +begin + -- Cheat to force the first precond operand False + I1 := (Set => True, Val => 5); + Set (I1, 2, Reset_OK => True); +end; + +--# values.adb +-- /pre/ l! ## dF- +-- /set/ l+ ## 0 + diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tf.adb b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tf.adb new file mode 100644 index 000000000..576f1f6cd --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tf.adb @@ -0,0 +1,12 @@ +with Support, Values; use Support, Values; + +procedure Test_Values_TF is + I1 : Int; +begin + Set (I1, 2, Reset_OK => False); +end; + +--# values.adb +-- /pre/ l! ## dF- +-- /set/ l+ ## 0 + diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tt.adb b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tt.adb new file mode 100644 index 000000000..5f922e78b --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tt.adb @@ -0,0 +1,12 @@ +with Support, Values; use Support, Values; + +procedure Test_Values_TT is + I1 : Int; +begin + Set (I1, 2, Reset_OK => True); +end; + +--# values.adb +-- /pre/ l! ## dF- +-- /set/ l+ ## 0 + diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.adb b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.adb new file mode 100644 index 000000000..cd7a431f0 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.adb @@ -0,0 +1,8 @@ +pragma Check_Policy (Precondition, On); + +package body Values is + procedure Set (V : in out Int; Val : Integer; Reset_OK : Boolean) is + begin + V := (Set => True, Val => Val); -- # set + end; +end; diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.ads b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.ads new file mode 100644 index 000000000..c0972f0f5 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/values.ads @@ -0,0 +1,10 @@ +package Values is + + type Int is record + Val : Integer := 0; + Set : Boolean := False; + end record; + + procedure Set (V : in out Int; Val : Integer; Reset_Ok : Boolean); + pragma Precondition ((not V.Set) or else Reset_Ok); +end; diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/test.py b/testsuite/tests/Ada/mcdc/K118_027-precond_not/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.adb b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.adb new file mode 100644 index 000000000..6f32b6015 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.adb @@ -0,0 +1,28 @@ + +package body Actuators is + + type Update_Policy is (Fast, Safe); + + procedure Increment + (A : in out Actuator; Value : Integer; Policy : Update_Policy); + pragma Inline (Increment); + + procedure Increment + (A : in out Actuator; Value : Integer; Policy : Update_Policy) is + begin + if Policy = Safe and then A.Value + Value > A.Safety then -- # check + return; -- # punt + else + A.Value := A.Value + Value; -- # update + end if; + end; + + procedure Fast_Increment + (A : in out Actuator; Value : Integer) is + begin + Increment (A, Value, Policy => Fast); -- # call + end; + +end; + + diff --git a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.ads b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.ads new file mode 100644 index 000000000..7969bb92c --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.ads @@ -0,0 +1,20 @@ +package Actuators is + + -- A very basic Actuator abstraction + + type Actuator is limited record + + Value : Integer; + -- Current output level + + Safety : Integer; + -- Value threshold beyond which output might + -- cause hardware damage + + end record; + pragma Volatile (Actuator); + + procedure Fast_Increment + (A : in out Actuator; Value : Integer); +end; + diff --git a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/test_fast.adb b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/test_fast.adb new file mode 100644 index 000000000..6fd63f2b7 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/test_fast.adb @@ -0,0 +1,15 @@ +with Actuators, Support; use Actuators, Support; + +procedure Test_Fast is + + A : Actuator := (Value => 0, Safety => 2); +begin + Fast_Increment (A, 5); + Assert (A.Value = 5); +end; + +--# actuators.adb +-- /check/ l! ## dT- +-- /punt/ l- ## s- +-- /update/ l+ ## 0 +-- /call/ l+ ## 0 diff --git a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.opt b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.opt new file mode 100644 index 000000000..e7d6fd986 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.opt @@ -0,0 +1 @@ +bin-traces,CARGS_O1 XFAIL open question on inlining + constant folding diff --git a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.py b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/assert.adb b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.adb b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.adb new file mode 100644 index 000000000..f05ae0904 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.adb @@ -0,0 +1,21 @@ +pragma Short_Circuit_And_Or; + +package body Expr is + + function Bool_And (A, B : Boolean) return Boolean is + begin + return A and B; -- # lone-and + end; + + function Bool_Or (A, B : Boolean) return Boolean is + begin + return A or B; -- # lone-or + end; + + function Bool_And_Or (A, B, C : Boolean) return Boolean is + begin + return (A and B) or C; -- # and-or + end; + +end; + diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.ads b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.ads new file mode 100644 index 000000000..ea27d7e88 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.ads @@ -0,0 +1,5 @@ +package Expr is + function Bool_And (A, B : Boolean) return Boolean; + function Bool_Or (A, B : Boolean) return Boolean; + function Bool_And_Or (A, B, C : Boolean) return Boolean; +end; diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/test_a.adb b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/test_a.adb new file mode 100644 index 000000000..8a57201c9 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/test_a.adb @@ -0,0 +1,23 @@ +with Expr, Assert; use Expr; + +-- For all the expression evals, arrange to demonstrate independant +-- influence of A only. Expect condition independance not demonstrated +-- diagnostics on other conditions. + +procedure Test_A is +begin + Assert (Bool_And (True, True) = True); + Assert (Bool_and (False, True) = False); + + Assert (Bool_Or (False, False) = False); + Assert (Bool_or (True, False) = True); + + Assert (Bool_And_Or (False, True, False) = False); + Assert (Bool_And_Or (True, True, False) = True); +end; + +--# expr.adb +-- /lone-and/ l! ## c!:"B" +-- /lone-or/ l! ## c!:"B" +-- /and-or/ l! ## c!:"B", c!:"C" + diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.opt b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.opt new file mode 100644 index 000000000..9d8f75303 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD Implemented in the 7.4.0 compiler branch +7.2.2 DEAD Implemented in the 7.4.0 compiler branch +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.py b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.adb b/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.adb new file mode 100644 index 000000000..a46d275c0 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.adb @@ -0,0 +1,15 @@ +package body Orelse is + + procedure Eval_Or_Else (A, B : Boolean; E : out Boolean) is + begin + E := A or else B; -- # evaluate + end; + + function Or_Else (A, B : Boolean) return Boolean is + Value : Boolean; + begin + Eval_Or_Else (A, B, Value); -- # returnValue + return Value; -- # returnValue + end; +end; + diff --git a/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.ads b/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.ads new file mode 100644 index 000000000..de7a3b89f --- /dev/null +++ b/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.ads @@ -0,0 +1,3 @@ +package Orelse is + function Or_Else (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/Ada/mcdc/OrElse-O1/src/test_orelse_a.adb b/testsuite/tests/Ada/mcdc/OrElse-O1/src/test_orelse_a.adb new file mode 100644 index 000000000..038a3ded7 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/OrElse-O1/src/test_orelse_a.adb @@ -0,0 +1,13 @@ +with Support, Orelse; use Support, Orelse; + +procedure Test_OrElse_A is +begin + Assert (Or_Else (True, False) = True); + Assert (Or_Else (False, False) = False); +end; + +--# orelse.adb +-- /evaluate/ l! ## c!:"B" +-- /decisionTrue/ l+ ## 0 +-- /decisionFalse/ l+ ## 0 +-- /returnValue/ l+ ## 0 diff --git a/testsuite/tests/Ada/mcdc/OrElse-O1/test.py b/testsuite/tests/Ada/mcdc/OrElse-O1/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/mcdc/OrElse-O1/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/CmpMin/src/in_range.adb b/testsuite/tests/Ada/stmt/CmpMin/src/in_range.adb new file mode 100644 index 000000000..6d6ac08c3 --- /dev/null +++ b/testsuite/tests/Ada/stmt/CmpMin/src/in_range.adb @@ -0,0 +1,10 @@ +function In_Range (X , Min, Max : Integer) return Boolean is +begin + if X < Min then -- # XcmpMin + return False; -- # XoutMin + elsif X > Max then -- # XcmpMax + return False; -- # XoutMax + else + return True; -- # Xin + end if; +end; diff --git a/testsuite/tests/Ada/stmt/CmpMin/src/in_range.ali b/testsuite/tests/Ada/stmt/CmpMin/src/in_range.ali new file mode 100644 index 000000000..c4a4597b5 --- /dev/null +++ b/testsuite/tests/Ada/stmt/CmpMin/src/in_range.ali @@ -0,0 +1,19 @@ +V "GNAT Lib v6.4" +A -O1 +A -fpreserve-control-flow +A -fverbose-asm +A -mregnames +A -g +P +R nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn + +U in_range%b in_range.adb 0993fb61 NE OO SU + +D in_range.adb 20100310172111 0993fb61 +D system.ads 20100303101734 23e63bde +X 1 in_range.adb +1V10*In_Range{boolean} 1b10 1>20 1>24 1>29 10t4 +1i20 X{integer} 3r7 5r10 +1i24 Min{integer} 3r11 +1i29 Max{integer} 5r14 + diff --git a/testsuite/tests/Ada/stmt/CmpMin/src/test_in_range_gtmax.adb b/testsuite/tests/Ada/stmt/CmpMin/src/test_in_range_gtmax.adb new file mode 100644 index 000000000..2b79671bf --- /dev/null +++ b/testsuite/tests/Ada/stmt/CmpMin/src/test_in_range_gtmax.adb @@ -0,0 +1,16 @@ +with In_Range, Support; use Support; + +-- Exercize X > max only. Verify that the < min exit and the in-range case +-- are reported uncovered. + +procedure Test_In_Range_GTmax is +begin + Assert (not In_Range (4, 2, 3)); +end; + +--# in_range.adb +-- /XcmpMin/ l+ ## 0 +-- /XcmpMax/ l+ ## 0 +-- /XoutMax/ l+ ## 0 +-- /Xin/ l- ## s- +-- /XoutMin/ l- ## s- diff --git a/testsuite/tests/Ada/stmt/CmpMin/test.py b/testsuite/tests/Ada/stmt/CmpMin/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/CmpMin/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.adb b/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.adb new file mode 100644 index 000000000..339fbb0ae --- /dev/null +++ b/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.adb @@ -0,0 +1,20 @@ +package body Flips is + + Ob, T : Boolean := True; + pragma Volatile (T); + + procedure Flip (B : in out Boolean) is + begin + B := not B; -- # doflip + end; + + procedure Flip_If (P : Boolean) is + KB : constant Boolean := T; + B : Boolean := KB; + begin + if P then + Flip (B); -- # doflip + Ob := B; -- # doflip + end if; + end; +end; diff --git a/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ads b/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ads new file mode 100644 index 000000000..2ca76cba8 --- /dev/null +++ b/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ads @@ -0,0 +1,4 @@ +package Flips is + procedure Flip (B : in out Boolean); + procedure Flip_If (P : Boolean); +end; diff --git a/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ali b/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ali new file mode 100644 index 000000000..35aea58b0 --- /dev/null +++ b/testsuite/tests/Ada/stmt/DeclChain-O1/src/flips.ali @@ -0,0 +1,27 @@ +V "GNAT Lib v6.4" +A -O1 +A -fpreserve-control-flow +A -g +A -mregnames +P +R nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn + +U flips%b flips.adb ef4d54cb NE OO PK + +U flips%s flips.ads 81d0dffd EE NE OO PK + +D flips.ads 20100311144045 81d0dffd +D flips.adb 20100311150436 6e9d8b36 +D system.ads 20071215102046 2b00703b +X 1 flips.ads +1K9*Flips 4e4 2|1b14 20t4 +2U14*Flip 2=20 2|6b14 9t7 +2b20 B{boolean} 2|6b20 8m7 8r16 +3U14*Flip_If 3>23 2|11b14 19t7 +3b23 P{boolean} 2|11b23 15r10 +X 2 flips.adb +3b4 Ob{boolean} 17m10 +3b8 T{boolean} 4r21 12r32 +12b7 KB{boolean} 13r22 +13b7 B{boolean} 16m10 16r19 17r16 + diff --git a/testsuite/tests/Ada/stmt/DeclChain-O1/src/test_flip_0.adb b/testsuite/tests/Ada/stmt/DeclChain-O1/src/test_flip_0.adb new file mode 100644 index 000000000..fcf9ad8f7 --- /dev/null +++ b/testsuite/tests/Ada/stmt/DeclChain-O1/src/test_flip_0.adb @@ -0,0 +1,9 @@ +with Support, Flips; use Support, Flips; + +procedure Test_Flip_0 is +begin + Flip_If (False); +end; + +--# flips.adb +-- /doflip/ l- ## s- diff --git a/testsuite/tests/Ada/stmt/DeclChain-O1/test.py b/testsuite/tests/Ada/stmt/DeclChain-O1/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/DeclChain-O1/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.adb b/testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.adb new file mode 100644 index 000000000..b726597d0 --- /dev/null +++ b/testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.adb @@ -0,0 +1,30 @@ +package body Pkg is + + task body T is + begin + null; -- # stmt + end T; + + protected body P is + end P; + + procedure Run is + task ST; -- # stmt + task body ST is + begin + null; -- # stmt + end ST; + + protected SP is -- # stmt + end SP; + + protected body SP is + end SP; + + T_Instance : T; -- # stmt + P_Instance : P; -- # stmt + begin + null; -- # stmt + end Run; + +end Pkg; diff --git a/testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.ads b/testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.ads new file mode 100644 index 000000000..8de9a1aa9 --- /dev/null +++ b/testsuite/tests/Ada/stmt/IncompleteTask/src/pkg.ads @@ -0,0 +1,10 @@ +package Pkg is + + task type T; + + protected type P is + end P; + + procedure Run; + +end Pkg; diff --git a/testsuite/tests/Ada/stmt/IncompleteTask/src/test_full.adb b/testsuite/tests/Ada/stmt/IncompleteTask/src/test_full.adb new file mode 100644 index 000000000..d6179b3ca --- /dev/null +++ b/testsuite/tests/Ada/stmt/IncompleteTask/src/test_full.adb @@ -0,0 +1,10 @@ +with Pkg; + +procedure Test_Full is +begin + Pkg.Run; +end Test_Full; + +--# pkg.ads +--# pkg.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/Ada/stmt/IncompleteTask/src/test_no.adb b/testsuite/tests/Ada/stmt/IncompleteTask/src/test_no.adb new file mode 100644 index 000000000..58edb8b5b --- /dev/null +++ b/testsuite/tests/Ada/stmt/IncompleteTask/src/test_no.adb @@ -0,0 +1,10 @@ +with Pkg; + +procedure Test_No is +begin + null; +end Test_No; + +--# pkg.ads +--# pkg.adb +-- /stmt/ l- ## s- diff --git a/testsuite/tests/Ada/stmt/IncompleteTask/test.opt b/testsuite/tests/Ada/stmt/IncompleteTask/test.opt new file mode 100644 index 000000000..91bc868e9 --- /dev/null +++ b/testsuite/tests/Ada/stmt/IncompleteTask/test.opt @@ -0,0 +1,2 @@ +RTS_ZFP DEAD Test requires tasking +RTS_RAVENSCAR DEAD Test requires tasking hierarchy diff --git a/testsuite/tests/Ada/stmt/IncompleteTask/test.py b/testsuite/tests/Ada/stmt/IncompleteTask/test.py new file mode 100644 index 000000000..81870abe6 --- /dev/null +++ b/testsuite/tests/Ada/stmt/IncompleteTask/test.py @@ -0,0 +1,11 @@ +""" +Regression test for a crash in "gnatcov instrument" when processing incomplete +task type declarations. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.adb b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.adb new file mode 100644 index 000000000..06af42dc8 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.adb @@ -0,0 +1,14 @@ +package body Flips is + + procedure Flip (X : in out integer) is + begin + X := - X; -- # flipx + end; + + procedure Flip (B : in out Boolean) is + begin + B := not B; -- # flipb + end; + +end; + diff --git a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.ads b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.ads new file mode 100644 index 000000000..1e61128d6 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.ads @@ -0,0 +1,5 @@ +package Flips is + procedure Flip (X : in out integer); + procedure Flip (B : in out Boolean); +end; + diff --git a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/test_flips.adb b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/test_flips.adb new file mode 100644 index 000000000..93d91168d --- /dev/null +++ b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/test_flips.adb @@ -0,0 +1,16 @@ +with Flips, Support; use Flips, Support; + +procedure Test_Flips is + B : Boolean := True; + X : Integer := 5; +begin + Flip (B); + Assert (B = False); + + Flip (X); + Assert (X = -5); +end; + +--# flips.adb +-- /flipb/ l+ ## 0 +-- /flipx/ l+ ## 0 diff --git a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/test.py b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.adb b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.adb new file mode 100644 index 000000000..08436bca6 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.adb @@ -0,0 +1,8 @@ +function Id (X : Integer) return Integer is + X_Value : Integer; -- # decl +begin + X_Value := X; -- # Call + goto Done; -- # Call +<> + return X_Value; -- # Call +end; diff --git a/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.ali b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.ali new file mode 100644 index 000000000..09565ae7b --- /dev/null +++ b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/id.ali @@ -0,0 +1,18 @@ +V "GNAT Lib v6.4" +A -O1 +A -fpreserve-control-flow +A -gnatp +A -g +P +R nnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnnn + +U id%b id.adb ecec289f NE OO SU + +D id.adb 20100316135548 ecec289f +D system.ads 20100316073307 23e63bde +X 1 id.adb +1V10*Id{integer} 1b10 1>14 8t4 +1i14 X{integer} 4r15 +2i4 X_Value{integer} 4m4 7r12 +6L3 Done 5r9 + diff --git a/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/test_id0.adb b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/test_id0.adb new file mode 100644 index 000000000..84507e48a --- /dev/null +++ b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/src/test_id0.adb @@ -0,0 +1,10 @@ +with Id, Support; use Support; + +procedure Test_Id0 is +begin + Assert (True); +end; + +--# id.adb +-- /Call/ l- ## s- +-- /decl/ ~l- ## ~s- diff --git a/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/test.py b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J312_016-GotoNext-O1/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/inc_by.adb b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/inc_by.adb new file mode 100644 index 000000000..ed48ce070 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/inc_by.adb @@ -0,0 +1,8 @@ +procedure Inc_By (N : Natural; X : in out Integer) is + Ninc : Natural := 0; -- # decl +begin -- # + while Ninc /= N loop -- # incLoop + X := X + 1; -- # incX + Ninc := Ninc + 1; -- # incX + end loop; +end; -- # diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.adb b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.adb new file mode 100644 index 000000000..8ac4d76b4 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.adb @@ -0,0 +1,11 @@ +package body Ops is + + procedure Probe (N : Natural) is + Nprobes : Natural := 0; -- # decl + begin + while Nprobes /= N loop -- # loop + Latch := IOreg; -- # probe + Nprobes := Nprobes + 1; -- # probe + end loop; + end; +end; diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.ads b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.ads new file mode 100644 index 000000000..f8a055364 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/ops.ads @@ -0,0 +1,8 @@ +package Ops is + + Latch, IOreg : Integer; + pragma Volatile (IOreg); + pragma Volatile (Latch); + + procedure Probe (N : Natural); +end; diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test.opt b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test.opt new file mode 100644 index 000000000..8c23b2d3d --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test.opt @@ -0,0 +1 @@ +ALL XFAIL -O1 vs trivial loops J316-020 diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc.adb b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc.adb new file mode 100644 index 000000000..01f274991 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc.adb @@ -0,0 +1,12 @@ +with Inc_By, Support; use Support; + +procedure Test_Inc is + X : Integer := 12; +begin + Inc_By (15, X); + Assert (X = 27); +end; + +--# inc_by.adb +-- /decl/ ~l+ ## 0 +-- /incLoop|incX/ l+ ## 0 diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc_0.adb b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc_0.adb new file mode 100644 index 000000000..f55ec204e --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_inc_0.adb @@ -0,0 +1,10 @@ +with Inc_By, Support; use Support; + +procedure Test_Inc_0 is +begin + Assert (True); +end; + +--# inc_by.adb +-- /decl/ ~l- ## ~s- +-- /incLoop|incX/ l- ## s- diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_ops_0.adb b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_ops_0.adb new file mode 100644 index 000000000..ef7609bdd --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/src/test_ops_0.adb @@ -0,0 +1,10 @@ +with Ops, Support; use Ops, Support; + +procedure Test_Ops_0 is +begin + Assert (True); +end; + +--# ops.adb +-- /decl/ ~l- ## ~s- +-- /loop|probe/ l- ## s- diff --git a/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/test.py b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/J316_020-trivial_loop-O1/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.adb b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.adb new file mode 100644 index 000000000..0184bd34c --- /dev/null +++ b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.adb @@ -0,0 +1,17 @@ +package body Plop is + pragma Unsuppress (All_Checks); + + function F (I : My_Int) return My_Int is + Res : My_Int := I; + begin + begin + Res := Res * I; -- # mult + Res := Res / 2; -- # div + exception + when Constraint_Error => + return -1; -- # handle + end; + + return Res; -- # retval + end; +end; diff --git a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.ads b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.ads new file mode 100644 index 000000000..dac1596e2 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/plop.ads @@ -0,0 +1,4 @@ +package Plop is + type My_Int is range -100 .. 100; + function F (I : My_Int) return My_Int; +end; diff --git a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/test_ce.adb b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/test_ce.adb new file mode 100644 index 000000000..26764ac73 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/test_ce.adb @@ -0,0 +1,14 @@ +with Plop, Support; use Plop, Support; + +procedure Test_CE is +begin + Assert (F (50) = -1); +end; + +--# plop.adb +-- /mult/ l+ ## 0 +-- /div/ l- ## s- +-- /retval/ l- ## s- +-- /handle/ l+ ## 0 + + diff --git a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.opt b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.opt new file mode 100644 index 000000000..4c1ae3354 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.opt @@ -0,0 +1 @@ +RTS_RAVENSCAR,powerpc,7.0.3 SKIP !zfp sjlj eh issue fixed post 7.0, K316-021 diff --git a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.py b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.adb b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.adb new file mode 100644 index 000000000..bec6a172b --- /dev/null +++ b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.adb @@ -0,0 +1,29 @@ +with Support; + +package body Actuators is + + type Update_Policy is (Fast, Safe); + + procedure Increment + (A : in out Actuator; Value : Integer; Policy : Update_Policy); + pragma Inline (Increment); + + procedure Increment + (A : in out Actuator; Value : Integer; Policy : Update_Policy) is + begin + if Policy = Safe and then A.Value + Value > A.Safety then -- # check + return; -- # punt + else + A.Value := A.Value + Value; -- # update + end if; + end; + + procedure Fast_Increment + (A : in out Actuator; Value : Integer) is + begin + Increment (A, Value, Policy => Fast); -- # call + end; + +end; + + diff --git a/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.ads b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.ads new file mode 100644 index 000000000..7969bb92c --- /dev/null +++ b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.ads @@ -0,0 +1,20 @@ +package Actuators is + + -- A very basic Actuator abstraction + + type Actuator is limited record + + Value : Integer; + -- Current output level + + Safety : Integer; + -- Value threshold beyond which output might + -- cause hardware damage + + end record; + pragma Volatile (Actuator); + + procedure Fast_Increment + (A : in out Actuator; Value : Integer); +end; + diff --git a/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/test_fast.adb b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/test_fast.adb new file mode 100644 index 000000000..3fd6b8089 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/test_fast.adb @@ -0,0 +1,15 @@ +with Actuators, Support; use Actuators, Support; + +procedure Test_Fast is + + A : Actuator := (Value => 0, Safety => 2); +begin + Fast_Increment (A, 5); + Assert (A.Value = 5); +end; + +--# actuators.adb +-- /check/ l+ ## 0 +-- /punt/ l- ## s- +-- /update/ l+ ## 0 +-- /call/ l+ ## 0 diff --git a/testsuite/tests/Ada/stmt/K620-028_fold-inline/test.opt b/testsuite/tests/Ada/stmt/K620-028_fold-inline/test.opt new file mode 100644 index 000000000..e7d6fd986 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K620-028_fold-inline/test.opt @@ -0,0 +1 @@ +bin-traces,CARGS_O1 XFAIL open question on inlining + constant folding diff --git a/testsuite/tests/Ada/stmt/K620-028_fold-inline/test.py b/testsuite/tests/Ada/stmt/K620-028_fold-inline/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada/stmt/K620-028_fold-inline/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/mylib.gpr b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/mylib.gpr new file mode 100644 index 000000000..b7d344b86 --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/mylib.gpr @@ -0,0 +1,7 @@ +library project mylib is + for source_dirs use ("."); + for object_dir use "obj"; + for library_name use project'name; + for library_dir use "lib"; + for library_interface use ("ops", "ops.values"); +end mylib; \ No newline at end of file diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.adb b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.adb new file mode 100644 index 000000000..acab1997b --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.adb @@ -0,0 +1,6 @@ +package body Ops.Values is + procedure Inc (X : in out Integer) is + begin + X := X + 1; -- # stmt + end; +end; diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.ads b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.ads new file mode 100644 index 000000000..adb96ebc2 --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.ads @@ -0,0 +1,4 @@ +package Ops.Values is + procedure Inc (X : in out Integer); +end; + diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops.ads b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops.ads new file mode 100644 index 000000000..10cdb9b3c --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops.ads @@ -0,0 +1,9 @@ +-- Unit with only dummy statements, not generating code. Make sure +-- these aren't ignored by gnatcov and would get a violation if the +-- unit is perceived by gnatcov as absent from the test-closure. +-- +-- pragma Pure; would be a bad choice, for example. + +package Ops is + X : Integer; -- # decl +end; diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/src/test_inc.adb b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/src/test_inc.adb new file mode 100644 index 000000000..a7f225e40 --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/src/test_inc.adb @@ -0,0 +1,25 @@ +with Support, Ops.Values; use Support, Ops.Values; + +procedure Test_Inc is + + -- The library initialization procedure isn't called automatically in some + -- configurations so we call it explicitly from here. Calling it multiple + -- times is not a problem, so we're fine in configurations where it is + -- called automatically before reaching here. + + procedure Mylib_Init; + pragma Import (C, Mylib_Init, "mylibinit"); + + K : Integer := 12; + pragma Volatile (K); +begin + Mylib_Init; + Inc (K); +end; + +--# ../mylib/ops.ads +-- /decl/ l. ## 0 + +--# ../mylib/ops-values.adb +-- /stmt/ l+ ## 0 + diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.opt b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.opt new file mode 100644 index 000000000..7da54125d --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.opt @@ -0,0 +1,2 @@ +bareboard SKIP Static auto-initialized libraries are not supported in BB +src-traces XFAIL S916-064: src-traces and Library_Interface project attributes diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.py b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.py new file mode 100644 index 000000000..7c77975e4 --- /dev/null +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.py @@ -0,0 +1,16 @@ +import os.path + +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches + + +libdep = os.path.abspath("mylib/mylib.gpr") +TestCase().run( + covcontrol=CovControl( + deps=[libdep], + gprsw=GPRswitches( + root_project='gen.gpr', + units=['ops', 'ops.values']))) +thistest.result() diff --git a/testsuite/tests/Ada2012/decision/ForOf/src/test_f.adb b/testsuite/tests/Ada2012/decision/ForOf/src/test_f.adb new file mode 100644 index 000000000..0bc3c0992 --- /dev/null +++ b/testsuite/tests/Ada2012/decision/ForOf/src/test_f.adb @@ -0,0 +1,20 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_F is + + LA : Array_Type := + (1 => (X => 2, Count => 0)); +begin + Process (LA, Bump => False); + Assert (LA(1).Count = 0); + Assert (LA(1).X = 4); +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l! ## dT- +-- /true/ l- ## s- + + diff --git a/testsuite/tests/Ada2012/decision/ForOf/src/test_t.adb b/testsuite/tests/Ada2012/decision/ForOf/src/test_t.adb new file mode 100644 index 000000000..e3b3ab532 --- /dev/null +++ b/testsuite/tests/Ada2012/decision/ForOf/src/test_t.adb @@ -0,0 +1,20 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_T is + + LA : Array_Type := + (1 => (X => 2, Count => 0)); +begin + Process (LA, Bump => True); + Assert (LA(1).Count = 1); + Assert (LA(1).X = 4); +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 + + diff --git a/testsuite/tests/Ada2012/decision/ForOf/src/values.adb b/testsuite/tests/Ada2012/decision/ForOf/src/values.adb new file mode 100644 index 000000000..5aa0ab9f7 --- /dev/null +++ b/testsuite/tests/Ada2012/decision/ForOf/src/values.adb @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package body Values is + + procedure Process (A : in out Array_Type; Bump : Boolean) is + begin + for E of A loop -- # stmt + E.X := E.X * 2; -- # stmt + if Bump then -- # eval + E.Count := E.Count + 1; -- # true + end if; + end loop; + end; + +end; diff --git a/testsuite/tests/Ada2012/decision/ForOf/src/values.ads b/testsuite/tests/Ada2012/decision/ForOf/src/values.ads new file mode 100644 index 000000000..d29d8be75 --- /dev/null +++ b/testsuite/tests/Ada2012/decision/ForOf/src/values.ads @@ -0,0 +1,12 @@ + +package Values is + + type Object is tagged record + X : Integer; + Count : Natural; + end record; + + type Array_Type is array (Natural range <>) of Object; + + procedure Process (A : in out Array_Type; Bump : Boolean); +end; diff --git a/testsuite/tests/Ada2012/decision/ForOf/test.py b/testsuite/tests/Ada2012/decision/ForOf/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/decision/ForOf/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/extra.opt b/testsuite/tests/Ada2012/extra.opt new file mode 100644 index 000000000..e1aeef0d6 --- /dev/null +++ b/testsuite/tests/Ada2012/extra.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD support for Ada2012 constructs not in 7.0.3 +7.1.2 DEAD support for Ada2012 constructs weak in 7.1.2 +7.2.2 DEAD support for Ada2012 constructs weak in 7.2.2 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.adb new file mode 100644 index 000000000..acbc53d0d --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.adb @@ -0,0 +1,7 @@ +package body Multiop is + + procedure Set (I : in out Int; V : Integer) is + begin + I.Value := V; + end; +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.ads new file mode 100644 index 000000000..9416b856e --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.ads @@ -0,0 +1,19 @@ +pragma Ada_2012; +pragma Assertion_Policy (Type_Invariant => Check); + +-- exercise a multi-operand invariant (complex expr) + +package Multiop is + + type Int (LB, UB : Integer) is private; + + procedure Set (I : in out Int; V : Integer); + +private + + type Int (LB, UB : Integer) is record + Value : Integer := LB; + end record with + Type_Invariant => (Int.Value >= Int.LB and then Int.Value <= Int.UB); -- # eval + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_f.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_f.adb new file mode 100644 index 000000000..77eb7a1e4 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_f.adb @@ -0,0 +1,13 @@ +with Multiop; use Multiop; +with Silent_Last_Chance; + +procedure Test_Multiop_F is + O : Int (LB => 1, UB => 5); +begin + Set (O, V => 45); +exception + when others => null; +end; + +--# multiop.ads +-- /eval/ l! ## c!:"Int.Value >= Int.LB" diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_t.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_t.adb new file mode 100644 index 000000000..5198b6514 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/test_multiop_t.adb @@ -0,0 +1,10 @@ +with Multiop; use Multiop; + +procedure Test_Multiop_T is + O : Int (LB => 1, UB => 5); +begin + Set (O, V => 3); +end; + +--# multiop.ads +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/tc.rst b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/tc.rst new file mode 100644 index 000000000..94b8e4b47 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/tc.rst @@ -0,0 +1,4 @@ +Exercise a mono-operand type_invariant aspect + +Check that no dc violation is raised for an invariant always satisfied, as +mono-operand expressions are never decisions in this context. diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.opt b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.opt new file mode 100644 index 000000000..93fd7b411 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.opt @@ -0,0 +1 @@ +src-traces XFAIL S606-037: src-traces and contracts diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.py b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.adb new file mode 100644 index 000000000..78514b176 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.adb @@ -0,0 +1,8 @@ +package body SingleOp is + + procedure Set (I : in out Int; V : Integer) is + begin + I.Value := V; + end; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.ads new file mode 100644 index 000000000..0b1d1e9d4 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.ads @@ -0,0 +1,19 @@ +pragma Ada_2012; +pragma Assertion_Policy (Invariant => Check); + +-- exercise a mono-operand invariant (simple expr) + +package SingleOp is + + type Int (UB : Integer) is private; + + procedure Set (I : in out Int; V : Integer); + +private + + type Int (UB : Integer) is record + Value : Integer := UB; + end record with + Invariant => (Int.Value <= Int.UB); -- # eval + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/test_singleop_t.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/test_singleop_t.adb new file mode 100644 index 000000000..5f05ec763 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/test_singleop_t.adb @@ -0,0 +1,10 @@ +with Singleop; use Singleop; + +procedure Test_Singleop_T is + O : Int (UB => 5); +begin + Set (O, V => 3); +end; + +--# singleop.ads +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.opt b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.opt new file mode 100644 index 000000000..93fd7b411 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.opt @@ -0,0 +1 @@ +src-traces XFAIL S606-037: src-traces and contracts diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.py b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/req.rst b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/req.rst new file mode 100644 index 000000000..fd7cde47a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/req.rst @@ -0,0 +1,4 @@ +Invariant aspects shall be treated as Postconditions checked +after every operation on an object of the type. + +Only complex expressions are considered as decisions, for mcdc. diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_0.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_0.adb new file mode 100644 index 000000000..5fe656d47 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_0.adb @@ -0,0 +1,12 @@ +with Values; + +-- Don't even call in. Decision never evaluated and all stmts uncovered. + +procedure Test_0 is +begin + null; +end; + +--# values.adb +-- /eval/ l- ## d- +-- /stmt/ l- ## s- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_a.adb new file mode 100644 index 000000000..ba6ccc0fd --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_a.adb @@ -0,0 +1,16 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_A is + A : Int := (Value => 5, Valid => True); + B : Int := (Value => -7, Valid => True); + C : Int := (Value => 12, Valid => True); +begin + Filter (A, C); -- T T + Filter (B, C); -- F T +exception + when others => null; +end; + +--# values.adb +-- /eval/ l! ## c!:"B.Valid" diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_b.adb new file mode 100644 index 000000000..035b58174 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_b.adb @@ -0,0 +1,16 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_B is + A : Int := (Value => 5, Valid => True); + B : Int := (Value => -7, Valid => True); + C : Int := (Value => 12, Valid => True); +begin + Filter (A, C); -- T T + Filter (A, B); -- T F +exception + when others => null; +end; + +--# values.adb +-- /eval/ l! ## c!:"A.Valid" diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_f.adb new file mode 100644 index 000000000..01c7737a4 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_f.adb @@ -0,0 +1,14 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_F is + A : Int := (Value => 5, Valid => True); + B : Int := (Value => -7, Valid => True); +begin + Filter (A, B); +exception + when others => null; +end; + +--# values.adb +-- /eval/ l! ## dT- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_t.adb new file mode 100644 index 000000000..a43b281ce --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/test_t.adb @@ -0,0 +1,11 @@ +with Support, Values; use Support, Values; + +procedure Test_T is + A : Int := (Value => 5, Valid => True); + B : Int := (Value => 7, Valid => True); +begin + Filter (A, B); +end; + +--# values.adb +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.adb new file mode 100644 index 000000000..06f75d599 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.adb @@ -0,0 +1,19 @@ +pragma Ada_2012; +pragma Assertion_Policy (Post => Check); + +package body Values is + + procedure validate (A, B : in out Int) + with Post => (A.Valid and then B.Valid) -- # eval + is + begin + A.Valid := A.Value > 0; -- # stmt + B.Valid := B.Value > 0; -- # stmt + end; + + procedure Filter (A, B : in out Int) is + begin + Validate (A, B); -- # stmt + end; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.ads new file mode 100644 index 000000000..49f289cfe --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.ads @@ -0,0 +1,11 @@ + +package Values is + + type Int is record + Value : Integer; + Valid : Boolean; + end record; + + procedure Filter (A, B : in out Int); + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.opt b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.opt new file mode 100644 index 000000000..93fd7b411 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.opt @@ -0,0 +1 @@ +src-traces XFAIL S606-037: src-traces and contracts diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.py b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_0.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_0.adb new file mode 100644 index 000000000..5fe656d47 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_0.adb @@ -0,0 +1,12 @@ +with Values; + +-- Don't even call in. Decision never evaluated and all stmts uncovered. + +procedure Test_0 is +begin + null; +end; + +--# values.adb +-- /eval/ l- ## d- +-- /stmt/ l- ## s- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_f.adb new file mode 100644 index 000000000..6b97ca8e2 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_f.adb @@ -0,0 +1,13 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_F is + X : Integer; +begin + X := Plus (5, -8); +exception + when others => null; +end; + +--# values.ads +-- /eval/ l! ## dT- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_t.adb new file mode 100644 index 000000000..ad001f639 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/test_t.adb @@ -0,0 +1,9 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (Plus (5, 8) = 13); +end; + +--# values.ads +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.adb new file mode 100644 index 000000000..fc50359a5 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.adb @@ -0,0 +1,7 @@ +package body Values is + + function Plus (A, B : Integer) return Integer is + begin + return A + B; -- # stmt + end; +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.ads new file mode 100644 index 000000000..36afff401 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +pragma Assertion_Policy (Post => Check); + +package Values is + + function Plus (A, B : Integer) return Integer + with Post => (Plus'Result > 0); -- # eval + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.opt b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.opt new file mode 100644 index 000000000..93fd7b411 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.opt @@ -0,0 +1 @@ +src-traces XFAIL S606-037: src-traces and contracts diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.py b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_a.adb new file mode 100644 index 000000000..a888aadc8 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_a.adb @@ -0,0 +1,17 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_A is + X : Integer; +begin + Assert + (Plus ((Value => 5, Valid => True), + (Value => 7, Valid => True)) = 12 + ); + X := Plus ((Value => 5, Valid => True), (Value => -7, Valid => False)); +exception + when others => null; +end; + +--# values.ads +-- /eval/ l! ## c!:"A.Valid" diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_b.adb new file mode 100644 index 000000000..3ac6be1f5 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_b.adb @@ -0,0 +1,17 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_B is + X : Integer; +begin + Assert + (Plus ((Value => 5, Valid => True), + (Value => 7, Valid => True)) = 12 + ); + X := Plus ((Value => 5, Valid => False), (Value => -7, Valid => True)); +exception + when others => null; +end; + +--# values.ads +-- /eval/ l! ## c!:"B.Valid" diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_f.adb new file mode 100644 index 000000000..08648eaac --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_f.adb @@ -0,0 +1,13 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_F is + X : Integer; +begin + X := Plus ((Value => 5, Valid => True), (Value => -7, Valid => False)); +exception + when others => null; +end; + +--# values.ads +-- /eval/ l! ## dT- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_t.adb new file mode 100644 index 000000000..2d6a6083d --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_t.adb @@ -0,0 +1,12 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert + (Plus ((Value => 5, Valid => True), + (Value => 7, Valid => True)) = 12 + ); +end; + +--# values.ads +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.adb new file mode 100644 index 000000000..8c1d1625b --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.adb @@ -0,0 +1,8 @@ +package body Values is + + function Plus (A, B : Int) return Integer is + begin + return A.Value + B.Value; + end; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.ads new file mode 100644 index 000000000..31ba62fb8 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; +pragma Assertion_Policy (Pre => Check); + +package Values is + + type Int is record + Value : Integer; + Valid : Boolean; + end record; + + function Plus (A, B : Int) return Integer + with Pre => (A.Valid and then B.Valid); -- # eval + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.opt b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.opt new file mode 100644 index 000000000..93fd7b411 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.opt @@ -0,0 +1 @@ +src-traces XFAIL S606-037: src-traces and contracts diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.py b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_0.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_0.adb new file mode 100644 index 000000000..5fe656d47 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_0.adb @@ -0,0 +1,12 @@ +with Values; + +-- Don't even call in. Decision never evaluated and all stmts uncovered. + +procedure Test_0 is +begin + null; +end; + +--# values.adb +-- /eval/ l- ## d- +-- /stmt/ l- ## s- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_f.adb new file mode 100644 index 000000000..5da5317df --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_f.adb @@ -0,0 +1,13 @@ +with Support, Values; use Support, Values; +with Silent_Last_Chance; + +procedure Test_F is + X : Integer; +begin + X := Plus (5, -8); +exception + when others => null; +end; + +--# values.adb +-- /eval/ l! ## dT- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_t.adb new file mode 100644 index 000000000..aaa1accba --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/test_t.adb @@ -0,0 +1,9 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (Plus (5, 8) = 13); +end; + +--# values.adb +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.adb new file mode 100644 index 000000000..775eda248 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.adb @@ -0,0 +1,17 @@ +pragma Ada_2012; +pragma Assertion_Policy (Post => Check); + +package body Values is + + function CheckedPlus (A, B : Integer) return Integer + with Post => (CheckedPlus'Result > 0) -- # eval + is + begin + return A + B; -- # stmt + end; + + function Plus (A, B : Integer) return Integer is + begin + return CheckedPlus (A, B); -- # stmt + end; +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.ads new file mode 100644 index 000000000..de04efeb8 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.ads @@ -0,0 +1,5 @@ +package Values is + + function Plus (A, B : Integer) return Integer; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.opt b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.opt new file mode 100644 index 000000000..93fd7b411 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.opt @@ -0,0 +1 @@ +src-traces XFAIL S606-037: src-traces and contracts diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.py b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_a.adb new file mode 100644 index 000000000..45ae40daa --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_a.adb @@ -0,0 +1,22 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_A is + + LA : Array_Type := + (1 => (A => True, B => True, Expr => <>), + 2 => (A => False, B => True, Expr => <>) + ); + +begin + Process (LA); + for E of LA loop + Assert (E.Expr = (E.A and then E.B)); + end loop; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l! ## c!:"E.B" + diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_ab.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_ab.adb new file mode 100644 index 000000000..14141e6f1 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_ab.adb @@ -0,0 +1,23 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_AB is + + LA : Array_Type := + (1 => (A => True, B => True, Expr => <>), + 2 => (A => True, B => False, Expr => <>), + 3 => (A => False, B => True, Expr => <>) + ); + +begin + Process (LA); + for E of LA loop + Assert (E.Expr = (E.A and then E.B)); + end loop; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_b.adb new file mode 100644 index 000000000..6e2098710 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_b.adb @@ -0,0 +1,22 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_B is + + LA : Array_Type := + (1 => (A => True, B => True, Expr => <>), + 2 => (A => True, B => False, Expr => <>) + ); + +begin + Process (LA); + for E of LA loop + Assert (E.Expr = (E.A and then E.B)); + end loop; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l! ## c!:"E.A" + diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_f.adb new file mode 100644 index 000000000..f6e45368c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_f.adb @@ -0,0 +1,19 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_F is + + LA : Array_Type := + (1 => (A => True, B => False, Expr => <>)); +begin + Process (LA); + for E of LA loop + Assert (E.Expr = (E.A and then E.B)); + end loop; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l! ## eT- + diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_t.adb new file mode 100644 index 000000000..1f4bb86e3 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_t.adb @@ -0,0 +1,19 @@ +pragma Ada_2012; + +with Support, Values; use Support, Values; + +procedure Test_T is + + LA : Array_Type := + (1 => (A => True, B => True, Expr => <>)); +begin + Process (LA); + for E of LA loop + Assert (E.Expr = (E.A and then E.B)); + end loop; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /eval/ l! ## eF- + diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/values.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/values.adb new file mode 100644 index 000000000..a4324316d --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/values.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package body Values is + + procedure Process (A : in out Array_Type) is + begin + for E of A loop -- # stmt + E.Expr := E.A and then E.B; -- # eval + end loop; + end; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/values.ads b/testsuite/tests/Ada2012/mcdc/ForOf/src/values.ads new file mode 100644 index 000000000..df0627603 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/values.ads @@ -0,0 +1,11 @@ + +package Values is + + type Object is tagged record + A, B, Expr : Boolean; + end record; + + type Array_Type is array (Natural range <>) of Object; + + procedure Process (A : in out Array_Type); +end; diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/test.py b/testsuite/tests/Ada2012/mcdc/ForOf/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/ForOf/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/expr.ads new file mode 100644 index 000000000..dfae67258 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/expr.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Expr is + -- if-expressions as outer expression operands in expression context. + + -- one outer and-then expr-decision with two operands: "if a" + "if b" + -- plus two inner decisions: "A" and "B" controlling the if values. + + function Filter (A, Valat, Valaf, B, Valbt, Valbf : Boolean) return Boolean is + ((if A then Valat else Valaf) and then (if B then Valbt else Valbf)); -- # eval + +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_opa.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_opa.adb new file mode 100644 index 000000000..4b77c8c5b --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_opa.adb @@ -0,0 +1,22 @@ +with Expr, Support; use Expr, Support; + +procedure Test_A_Opa is +begin + -- A op1 B op2 Outer + -- F T F T T + -- T F F T F + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => True) = True); + + Assert (Filter (A => True, Valat => False, Valaf => False, + B => False, Valbt => True, Valbf => True) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"B", c!:"if B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dT-:"B", c!:"if B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_t.adb new file mode 100644 index 000000000..decef0956 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_t.adb @@ -0,0 +1,22 @@ +with Expr, Support; use Expr, Support; + +procedure Test_A_T is +begin + -- A op1 B op2 Outer + -- F T T T T + -- T T T T T + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => True, Valbt => True, Valbf => True) = True); + + Assert (Filter (A => True, Valat => True, Valaf => True, + B => True, Valbt => True, Valbf => True) = True); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## eF-:"if A", d!:"B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## eF-:"if A", dF-:"B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_ab_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_ab_t.adb new file mode 100644 index 000000000..4980eed7f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_ab_t.adb @@ -0,0 +1,17 @@ +with Expr, Support; use Expr, Support; + +procedure Test_AB_T is +begin + -- A op1 B op2 Outer + -- F T T T T + -- T T F T T + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => True, Valbt => True, Valbf => True) = True); + + Assert (Filter (A => True, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => True) = True); +end; + +--# expr.ads +-- /eval/ l! ## eF-:"if A" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_b_opa.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_b_opa.adb new file mode 100644 index 000000000..142a027d4 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_b_opa.adb @@ -0,0 +1,22 @@ +with Expr, Support; use Expr, Support; + +procedure Test_B_Opa is +begin + -- A op1 B op2 Outer + -- F T F T T + -- F T T F F + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => True) = True); + + Assert (Filter (A => False, Valat => False, Valaf => True, + B => True, Valbt => False, Valbf => True) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"A", c!:"if A" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dT-:"A", c!:"if A" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opa.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opa.adb new file mode 100644 index 000000000..166772520 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opa.adb @@ -0,0 +1,22 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Opa is +begin + -- A op1 B op2 Outer + -- F T F T T + -- F F F T F + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => True) = True); + + Assert (Filter (A => False, Valat => True, Valaf => False, + B => False, Valbt => True, Valbf => True) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"A", d!:"B", c!:"if B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dT-:"A", dT-:"B", c!:"if B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb.adb new file mode 100644 index 000000000..2e8b522d6 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb.adb @@ -0,0 +1,21 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Opb is +begin + -- A op1 B op2 Outer + -- F T F T T + -- F T F F F + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => True) = True); + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => False) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"A", d!:"B", c!:"if A" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dT-:"A", dT-:"B", c!:"if A" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb0.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb0.adb new file mode 100644 index 000000000..3ba378b83 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb0.adb @@ -0,0 +1,18 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Opb0 is +begin + -- A op1 B op2 Outer + -- F F X X F + + Assert (Filter (A => False, Valat => False, Valaf => False, + B => False, Valbt => True, Valbf => True) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"A", d-:"B", eT-:"if A" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dT-:"A", d-:"B", eT-:"if A" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opfull.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opfull.adb new file mode 100644 index 000000000..a52c20aae --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opfull.adb @@ -0,0 +1,26 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Opfull is +begin + -- A op1 B op2 Outer + -- F T F T T + -- F F F T F + -- F T F F F + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => True) = True); + + Assert (Filter (A => False, Valat => True, Valaf => False, + B => False, Valbt => True, Valbf => True) = False); + + Assert (Filter (A => False, Valat => True, Valaf => True, + B => False, Valbt => True, Valbf => False) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"A", d!:"B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dT-:"A", dT-:"B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_t.adb new file mode 100644 index 000000000..591afd41d --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_t.adb @@ -0,0 +1,15 @@ +with Expr, Support; use Expr, Support; + +procedure Test_T is +begin + Assert (Filter (A => False, Valat => True, Valaf => True, + B => True, Valbt => True, Valbf => False) = True); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## eF-:"if A", d!:"A", d!:"B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## eF-:"if A", dT-:"A", dF-:"B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/expr.ads new file mode 100644 index 000000000..b83662a26 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/expr.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Expr is + X : Boolean := True; -- arbitrary value for operand not evaluated + + function Filter (A, B : Boolean; Valt : Boolean) return Boolean is + ((if A then Valt elsif B then Valt else not Valt)); -- # eval + + -- The controlling expressions are mono-operand here, and we + -- have no dominated statement to disambiguate True from False + -- on partial coverage. +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a.adb new file mode 100644 index 000000000..80265282e --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a.adb @@ -0,0 +1,15 @@ +with Expr, Support; use Expr, Support; + +procedure Test_A is +begin + Assert (Filter (A => True, B => X, Valt => True) = True); + Assert (Filter (A => False, B => True, Valt => False) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dF-:"B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a_t.adb new file mode 100644 index 000000000..645ada9cb --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_a_t.adb @@ -0,0 +1,15 @@ +with Expr, Support; use Expr, Support; + +procedure Test_A_T is +begin + Assert (Filter (A => True, B => X, Valt => True) = True); + Assert (Filter (A => True, B => X, Valt => False) = False); +end; + +--# expr.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## d!:"if A", d-:"B" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## dF-:"if A", d-:"B" diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_t.adb new file mode 100644 index 000000000..83b5be57c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/src/test_t.adb @@ -0,0 +1,11 @@ +with Expr, Support; use Expr, Support; + +procedure Test_T is +begin + Assert (Filter (A => True, B => X, Valt => True) = True); + Assert (Filter (A => False, B => True, Valt => True) = True); + Assert (Filter (A => False, B => False, Valt => False) = True); +end; + +--# expr.ads +-- /eval/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/Elsif/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/expr.ads new file mode 100644 index 000000000..64576aa1a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/expr.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package Expr is + type Opkind is (Op_And, Op_Or); + + -- Simple controlling expression, complex value expressions, + -- as expression function + + function Eval (Op : Opkind; A, B : Boolean) return Boolean is + (if (Op = Op_And) -- # if-opand + then (A and then B) -- # then-and + else (A or else B) -- # else-or + ); +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/test_t.adb new file mode 100644 index 000000000..4578c532c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/test_t.adb @@ -0,0 +1,16 @@ +with Expr, Support; use Expr, Support; + +procedure Test_T is +begin + Assert (Eval (Op_And, True, True) = True); +end; + +--# expr.ads +-- /then-and/ l! ## eF- +-- /else-or/ l! ## e- +-- +--%opts: --trace-mode=bin +-- /if-opand/ l! ## d! +-- +--%opts: --trace-mode=src +-- /if-opand/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/expr.ads new file mode 100644 index 000000000..9b40bdd6f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/expr.ads @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package Expr is + + -- Simple controlling expression, simple value expressions, + -- as expression function. + + function Filter (A, B : Integer) return Boolean is + (if (A > 0) -- # ctl-apos + then B > A -- # then-bgt + else B < A -- # else-agt + ); + +end; + diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/test_t.adb new file mode 100644 index 000000000..1a5a9739f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/test_t.adb @@ -0,0 +1,16 @@ +with Expr, Support; use Expr, Support; + +procedure Test_T is +begin + Assert (Filter (5, 8) = True); -- A > 0 +end; + +--# expr.ads +-- /then-bgt/ l+ ## 0 +-- /else-agt/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /ctl-apos/ l! ## d! +-- +--%opts: --trace-mode=src +-- /ctl-apos/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/plus.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/plus.adb new file mode 100644 index 000000000..73f22952c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/plus.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; +pragma Assertion_Policy (Post => Disable); + +function Plus (A, B : Integer) return Integer + with Post => (if (A > 0) then (B > 0) else (B <= 0)) -- # eval +is +begin + return A + B; -- # stmt +end; + + + diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_0.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_0.adb new file mode 100644 index 000000000..a62f4eb7f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_0.adb @@ -0,0 +1,11 @@ +with Plus; + +procedure Test_0 is +begin + null; +end; + +--# plus.adb +-- /eval/ l. ## 0 +-- /stmt/ l- ## s- + diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_f.adb new file mode 100644 index 000000000..7a67115c6 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_f.adb @@ -0,0 +1,11 @@ +with Plus, Support; use Support; + +procedure Test_F is +begin + Assert (Plus (5, -3) = 2); +end; + +--# plus.adb +-- /eval/ l. ## 0 +-- /stmt/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_t.adb new file mode 100644 index 000000000..aa51bf828 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_t.adb @@ -0,0 +1,11 @@ +with Plus, Support; use Support; + +procedure Test_T is +begin + Assert (Plus (5, 6) = 11); +end; + +--# plus.adb +-- /eval/ l. ## 0 +-- /stmt/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/plus.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/plus.adb new file mode 100644 index 000000000..ce6ff9eca --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/plus.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; +pragma Assertion_Policy (Pre => Disable); + +function Plus (A, B : Integer) return Integer + with Pre => (if (A > 0) then (B > 0) else (B <= 0)) -- # eval +is +begin + return A + B; -- # stmt +end; + + + diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_0.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_0.adb new file mode 100644 index 000000000..a62f4eb7f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_0.adb @@ -0,0 +1,11 @@ +with Plus; + +procedure Test_0 is +begin + null; +end; + +--# plus.adb +-- /eval/ l. ## 0 +-- /stmt/ l- ## s- + diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_f.adb new file mode 100644 index 000000000..7a67115c6 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_f.adb @@ -0,0 +1,11 @@ +with Plus, Support; use Support; + +procedure Test_F is +begin + Assert (Plus (5, -3) = 2); +end; + +--# plus.adb +-- /eval/ l. ## 0 +-- /stmt/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_t.adb new file mode 100644 index 000000000..aa51bf828 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_t.adb @@ -0,0 +1,11 @@ +with Plus, Support; use Support; + +procedure Test_T is +begin + Assert (Plus (5, 6) = 11); +end; + +--# plus.adb +-- /eval/ l. ## 0 +-- /stmt/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.adb new file mode 100644 index 000000000..68bb2d99c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; +package body Expr is + function Eval (Op : Opkind; A, B : Boolean) return Boolean is + begin + -- Simple controlling expression, complex value expressions + + return (if (Op = Op_And) -- # if-opand + then (A and then B) -- # then-and + else (A or else B) -- # else-or + ); + end; +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.ads new file mode 100644 index 000000000..4c0aadff2 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.ads @@ -0,0 +1,5 @@ +package Expr is + type Opkind is (Op_And, Op_Or); + + function Eval (Op : Opkind; A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/test_t.adb new file mode 100644 index 000000000..b8de074f0 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/test_t.adb @@ -0,0 +1,16 @@ +with Expr, Support; use Expr, Support; + +procedure Test_T is +begin + Assert (Eval (Op_And, True, True) = True); +end; + +--# expr.adb +-- /then-and/ l! ## eF- +-- /else-or/ l! ## e- +-- +--%opts: --trace-mode=bin +-- /if-opand/ l! ## d! +-- +--%opts: --trace-mode=src +-- /if-opand/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.adb new file mode 100644 index 000000000..9ab2ab414 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package body Expr is + + function Filter (A, B : Integer) return Boolean is + begin + return (if (A > 0) -- # ctl-apos + then B > A -- # then-bgt + else B < A -- # else-agt + ); + end; +end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.ads new file mode 100644 index 000000000..d08bad391 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.ads @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package Expr is + + -- Simple controlling expression, simple value expressions, + -- as expression function. + + function Filter (A, B : Integer) return Boolean; + +end; + diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/test_t.adb new file mode 100644 index 000000000..9b6f5303a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/test_t.adb @@ -0,0 +1,16 @@ +with Expr, Support; use Expr, Support; + +procedure Test_T is +begin + Assert (Filter (5, 8) = True); -- A > 0 +end; + +--# expr.adb +-- /then-bgt/ l+ ## 0 +-- /else-agt/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /ctl-apos/ l! ## d! +-- +--%opts: --trace-mode=src +-- /ctl-apos/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/test.py b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/InOut/src/expr.adb b/testsuite/tests/Ada2012/mcdc/InOut/src/expr.adb new file mode 100644 index 000000000..a2abf3451 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/InOut/src/expr.adb @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package body Expr is + function Plus (X, Y : Integer; Pos: in out Boolean) return Integer is + begin + if Pos then -- # test + Pos := X > 0 and then Y > 0; -- # eval + end if; + return X + Y; -- # stmt + end; +end; diff --git a/testsuite/tests/Ada2012/mcdc/InOut/src/expr.ads b/testsuite/tests/Ada2012/mcdc/InOut/src/expr.ads new file mode 100644 index 000000000..4753272d7 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/InOut/src/expr.ads @@ -0,0 +1,5 @@ +pragma Ada_2012; + +package Expr is + function Plus (X, Y : Integer; Pos: in out Boolean) return Integer; +end; diff --git a/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_f.adb b/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_f.adb new file mode 100644 index 000000000..bea576cdf --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_f.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Support, Expr; use Support, Expr; + +procedure Test_Eval_F is + Pos : Boolean := True; +begin + Assert (Plus (5, -6, Pos) = -1); + Assert (Pos = False); +end; + +--# expr.adb +-- /stmt/ l+ ## 0 +-- /test/ l! ## dF- +-- /eval/ l! ## eT- + diff --git a/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_t.adb b/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_t.adb new file mode 100644 index 000000000..dff7c684a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_t.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Support, Expr; use Support, Expr; + +procedure Test_Eval_T is + Pos : Boolean := True; +begin + Assert (Plus (5, 6, Pos) = 11); + Assert (Pos = True); +end; + +--# expr.adb +-- /stmt/ l+ ## 0 +-- /test/ l! ## dF- +-- /eval/ l! ## eF- + diff --git a/testsuite/tests/Ada2012/mcdc/InOut/src/test_neval.adb b/testsuite/tests/Ada2012/mcdc/InOut/src/test_neval.adb new file mode 100644 index 000000000..cc53e6620 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/InOut/src/test_neval.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Support, Expr; use Support, Expr; + +procedure Test_Neval is + Pos : Boolean := False; +begin + Assert (Plus (5, 6, Pos) = 11); + Assert (Pos = False); +end; + +--# expr.adb +-- /stmt/ l+ ## 0 +-- /test/ l! ## dT- +-- /eval/ l- ## s- + diff --git a/testsuite/tests/Ada2012/mcdc/InOut/test.py b/testsuite/tests/Ada2012/mcdc/InOut/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/InOut/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Membership/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/Membership/src/test_f.adb new file mode 100644 index 000000000..3ec44f99f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Membership/src/test_f.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_F is +begin + Assert (not Even_Odd (2, 8)); + Assert (not Even_Odd (1, 7)); +end; + +--# values.ads +-- /eval/ l! ## eT- diff --git a/testsuite/tests/Ada2012/mcdc/Membership/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Membership/src/test_t.adb new file mode 100644 index 000000000..356448465 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Membership/src/test_t.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (Even_Odd (4, 7)); + Assert (Even_Odd (2, 1)); +end; + +--# values.ads +-- /eval/ l! ## eF- diff --git a/testsuite/tests/Ada2012/mcdc/Membership/src/test_x.adb b/testsuite/tests/Ada2012/mcdc/Membership/src/test_x.adb new file mode 100644 index 000000000..4919f6750 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Membership/src/test_x.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_X is +begin + Assert (Even_Odd (4, 7)); + Assert (not Even_Odd (1, 1)); +end; + +--# values.ads +-- /eval/ l! ## c!:"Y" diff --git a/testsuite/tests/Ada2012/mcdc/Membership/src/test_y.adb b/testsuite/tests/Ada2012/mcdc/Membership/src/test_y.adb new file mode 100644 index 000000000..ab9c6cb39 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Membership/src/test_y.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_Y is +begin + Assert (Even_Odd (4, 7)); + Assert (not Even_Odd (2, 8)); +end; + +--# values.ads +-- /eval/ l! ## c!:"X" diff --git a/testsuite/tests/Ada2012/mcdc/Membership/src/values.ads b/testsuite/tests/Ada2012/mcdc/Membership/src/values.ads new file mode 100644 index 000000000..5d8ab42e5 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Membership/src/values.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; + +package Values is + + type My_Int is new Integer range 1 .. 8; + + function Even_Odd (X, Y : My_Int) return Boolean is + (X in 2 | 4 | 6 | 8 and then Y in 1 | 3 | 5 | 7); -- # eval +end; diff --git a/testsuite/tests/Ada2012/mcdc/Membership/test.py b/testsuite/tests/Ada2012/mcdc/Membership/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Membership/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_a.adb new file mode 100644 index 000000000..460ec57af --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_a.adb @@ -0,0 +1,15 @@ +with Support, Values; use Support, Values; + +procedure Test_A is + Positives : Sequence := (1, 4, 12, 15, 20); + Negatives : Sequence := (-2, -4); +begin + Assert (All_Pos (Positives, Positives)); + Assert (not All_Pos (Negatives, Positives)); +end Test_A; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## c!:"for all E", d!:"E > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## c!:"for all E", dF-:"E > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_b.adb new file mode 100644 index 000000000..4848a065e --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_b.adb @@ -0,0 +1,15 @@ +with Support, Values; use Support, Values; + +procedure Test_B is + Positives : Sequence := (1, 4, 12, 15, 20); + Negatives : Sequence := (-2, -4); +begin + Assert (All_Pos (Positives, Positives)); + Assert (not All_Pos (Positives, Negatives)); +end Test_B; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## c!:"for all K", d!:"S1(K) > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## c!:"for all K", dF-:"S1(K) > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_t.adb new file mode 100644 index 000000000..46fd8495a --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/test_t.adb @@ -0,0 +1,14 @@ +with Support, Values; use Support, Values; + +procedure Test_T is + S1 : Sequence := (1, 4, 12, 15, 20); + S2 : Sequence := (1, 15, 13); +begin + Assert (All_Pos (S1, S2)); +end Test_T; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## eF-, d!:"S1(K) > 0", d!:"E > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## eF-, dF-:"S1(K) > 0", dF-:"E > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.adb new file mode 100644 index 000000000..0dde12bf9 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.adb @@ -0,0 +1,17 @@ +pragma Ada_2012; + +package body Values is + + function All_Pos (S1, S2: Sequence) return Boolean is + begin + -- Assertions are not (yet) supposed to be processed by gnatcov, + -- but this kind of construct can make the instrumenter fail + -- (see U526-032) so this assertion is here only to test the + -- instrumenter robustness for the moment. + -- Coverage results are irrelevant for the time being. + + pragma Assert (for all K in Value_Seq'Range => Value_Seq (K) > 0); + + return (for all K in S1'Range => S1(K) > 0) and then (for all E of S2 => E > 0); -- # eval + end All_Pos; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.ads b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.ads new file mode 100644 index 000000000..6e5f14570 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/src/values.ads @@ -0,0 +1,7 @@ +package Values is + type Sequence is array (Natural range <>) of Integer; + + function All_Pos (S1, S2: Sequence) return Boolean; + + Value_Seq : Sequence := (1, 2, 3, 4); +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/test.py b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAll/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_a.adb new file mode 100644 index 000000000..4a010beff --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_a.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_A is +begin + Assert (All_Pos_Some_Neg ((1, 5, 3), (1, 9, -1, 12))); + Assert (not All_Pos_Some_Neg ((1, -5, 3), (1, 9, -1, 12))); +end Test_A; + +--# values.adb +-- /eval/ l! ## c!:"for some E" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_b.adb new file mode 100644 index 000000000..203e56e95 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_b.adb @@ -0,0 +1,13 @@ +with Support, Values; use Support, Values; + +procedure Test_B is +begin + Assert (All_Pos_Some_Neg ((1, 5, 3), (1, 9, -1, 12))); + Assert (not All_Pos_Some_Neg ((1, 12, 3), (1, 9))); +end Test_B; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## c!:"for all K", d!:"S1(K) > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## c!:"for all K", dF-:"S1(K) > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_t.adb new file mode 100644 index 000000000..f22d83060 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/test_t.adb @@ -0,0 +1,12 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (All_Pos_Some_Neg ((1, 5, 3), (1, 9, -1, 12))); +end Test_T; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## eF-, d!:"S1(K) > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## eF-, dF-:"S1(K) > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.adb new file mode 100644 index 000000000..d0748ea56 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.adb @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package body Values is + function All_Pos_Some_neg (S1, S2: Sequence) return Boolean is + begin + return (for all K in S1'Range => S1(K) > 0) and then (for some E of S2 => E < 0); -- # eval + end; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.ads b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.ads new file mode 100644 index 000000000..58f31a0ad --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/src/values.ads @@ -0,0 +1,5 @@ +package Values is + type Sequence is array (Natural range <>) of Integer; + + function All_Pos_Some_Neg (S1, S2: Sequence) return Boolean; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/test.py b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForAllSome/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_a.adb new file mode 100644 index 000000000..60a0744d4 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_a.adb @@ -0,0 +1,15 @@ +with Support, Values; use Support, Values; + +procedure Test_A is + Positives : Sequence := (1, 4, 12, 15, 20); + Negatives : Sequence := (-2, -4); +begin + Assert (not Some_Pos (Negatives, Negatives)); + Assert (Some_Pos (Positives, Negatives)); +end Test_A; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## c!:"for some E", d!:"E > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## c!:"for some E", dT-:"E > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_b.adb new file mode 100644 index 000000000..9ba69f718 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_b.adb @@ -0,0 +1,15 @@ +with Support, Values; use Support, Values; + +procedure Test_B is + Positives : Sequence := (1, 4, 12, 15, 20); + Negatives : Sequence := (-2, -4); +begin + Assert (not Some_Pos (Negatives, Negatives)); + Assert (Some_Pos (Negatives, Positives)); +end Test_B; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## c!:"for some K", d!:"S1(K) > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## c!:"for some K", dT-:"S1(K) > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_t.adb new file mode 100644 index 000000000..d6abcb9ed --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/test_t.adb @@ -0,0 +1,12 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (Some_Pos ((-1, -2), (3, -8))); +end Test_T; + +--# values.adb +-- %opts: --trace-mode=bin +-- /eval/ l! ## eF-, d!:"S1(K) > 0", d!:"E > 0" +-- %opts: --trace-mode=src +-- /eval/ l! ## eF-, dT-:"S1(K) > 0", dF-:"E > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.adb b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.adb new file mode 100644 index 000000000..7c3d2213c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.adb @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package body Values is + function Some_Pos (S1, S2: Sequence) return Boolean is + begin + return (for some K in S1'Range => S1(K) > 0) or else (for some E of S2 => E > 0); -- # eval + end; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.ads b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.ads new file mode 100644 index 000000000..e312fee2e --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/src/values.ads @@ -0,0 +1,5 @@ +package Values is + type Sequence is array (Natural range <>) of Integer; + + function Some_Pos (S1, S2: Sequence) return Boolean; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/test.py b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/ForSome/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_a.adb new file mode 100644 index 000000000..41d6ec0d8 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_a.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_A is +begin + Assert (All_Pos_And_Even ((2, 8))); + Assert (not All_Pos_And_Even ((28, 8, -14))); +end Test_A; + +--# values.adb +-- /eval/ l! ## c!:"X mod 2" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_b.adb new file mode 100644 index 000000000..b278b95f0 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_b.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_B is +begin + Assert (All_Pos_And_Even ((2, 8))); + Assert (not All_Pos_And_Even ((28, 8, 7))); +end Test_B; + +--# values.adb +-- /eval/ l! ## c!:"X > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_t.adb new file mode 100644 index 000000000..ecb6c87ae --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/test_t.adb @@ -0,0 +1,9 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (All_Pos_And_Even ((2, 12, 28))); +end Test_T; + +--# values.adb +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.adb new file mode 100644 index 000000000..f128ad9d9 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.adb @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package body Values is + function All_Pos_And_Even (S1: Sequence) return Boolean is + begin + return (for all X of S1 => X > 0 and then X mod 2 = 0); -- # eval + end All_Pos_And_Even; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.ads b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.ads new file mode 100644 index 000000000..ead7740bf --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/src/values.ads @@ -0,0 +1,5 @@ +package Values is + type Sequence is array (Natural range <>) of Integer; + + function All_Pos_And_Even (S1: Sequence) return Boolean; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/test.py b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInAll/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_a.adb new file mode 100644 index 000000000..e83261122 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_a.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_A is +begin + Assert (not Some_Pos_Or_Even ((-1, -3, -7))); + Assert (Some_Pos_Or_Even ((-1, 5))); +end; + +--# values.adb +-- /eval/ l! ## c!:"S1(K) mod 2" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_b.adb new file mode 100644 index 000000000..d1176ebff --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_b.adb @@ -0,0 +1,10 @@ +with Support, Values; use Support, Values; + +procedure Test_B is +begin + Assert (not Some_Pos_Or_Even ((-1, -3, -7))); + Assert (Some_Pos_Or_Even ((-1, -8))); +end Test_B; + +--# values.adb +-- /eval/ l! ## c!:"S1(K) > 0" diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_t.adb new file mode 100644 index 000000000..5a6380b23 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/test_t.adb @@ -0,0 +1,9 @@ +with Support, Values; use Support, Values; + +procedure Test_T is +begin + Assert (Some_Pos_Or_Even ((2, 12, 28))); +end Test_T; + +--# values.adb +-- /eval/ l! ## dF- diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.adb b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.adb new file mode 100644 index 000000000..f60ee3108 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.adb @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package body Values is + function Some_Pos_Or_Even (S1: Sequence) return Boolean is + begin + return (for some K in S1'Range => S1(K) > 0 or else S1(K) mod 2 = 0); -- # eval + end Some_Pos_Or_Even; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.ads b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.ads new file mode 100644 index 000000000..87af86b8e --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/src/values.ads @@ -0,0 +1,4 @@ +package Values is + type Sequence is array (Natural range <>) of Integer; + function Some_Pos_Or_Even (S1: Sequence) return Boolean; +end Values; diff --git a/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/test.py b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Quantified/NestedInSome/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.adb new file mode 100644 index 000000000..c6c3d11ea --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.adb @@ -0,0 +1,80 @@ +with Support; use Support; + +package body FUAND is + + function To_String (C : Coord) return String is + begin + return (1 .. 1 => Character'Val (48 - C)); + end; + + function Line (O : Object) return String is + begin + return To_String (O.X); + end; + + function Col (O : Object) return String is + begin + return To_String (O.Y); + end; + + -- + + type Red_Circle is new Object with null record; + + function Shape (O : Red_Circle) return String; + function Color (O : Red_Circle) return String; + + function Shape (O : Red_Circle) return String is + begin + return "circle"; + end; + + function Color (O : Red_Circle) return String is + begin + return "red"; + end; + + -- + + type Blue_Square is new Object with null record; + + function Shape (O : Blue_Square) return String; + function Color (O : Blue_Square) return String; + + function Shape (O : Blue_Square) return String is + begin + return "square"; + end; + + function Color (O : Blue_Square) return String is + begin + return "blue"; + end; + + -- + + procedure TEST_A is + A : Red_Circle := (X => 1, Y => 2); + B : Blue_Square := (X => 1, Y => 2); + begin + Assert (Fight (A, B)); -- T T + Assert (not Fight (A, A)); -- F T + end; + + procedure TEST_B is + A : Red_Circle := (X => 1, Y => 2); + B : Blue_Square := (X => 1, Y => 2); + C : Blue_Square := (X => 1, Y => 3); + begin + Assert (Fight (A, B)); -- T T + Assert (not Fight (A, C)); -- T F + end; + + procedure TEST_T is + A : Red_Circle := (X => 1, Y => 2); + B : Blue_Square := (X => 1, Y => 2); + begin + Assert (Fight (A, B)); + end; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.ads b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.ads new file mode 100644 index 000000000..e22375666 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.ads @@ -0,0 +1,23 @@ +pragma Ada_2012; + +package FUAND is + + type Coord is range 0 .. 9; + type Object is abstract tagged record + X, Y : Coord; + end record; + + function Shape (O : Object) return String is abstract; + function Color (O : Object) return String is abstract; + + function Line (O : Object) return String; + function Col (O : Object) return String; + + function Fight (A, B : Object'Class) return Boolean is + ((Color(A) & "-" & Shape(A)) /= (Color(B) & "-" & Shape(B)) and then (Line(A) & Col(A)) = (Line(B) & Col(B))); -- # eval + + procedure Test_A; + procedure Test_B; + procedure Test_T; + +end; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_a.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_a.adb new file mode 100644 index 000000000..3d087228c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_a.adb @@ -0,0 +1,14 @@ +with Fuand; + +procedure Test_FUAND_A is +begin + Fuand.Test_A; +end; + +--# fuand.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## c!:"Line(A" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## c!:"(Line(A" diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_b.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_b.adb new file mode 100644 index 000000000..81c49b4cf --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_b.adb @@ -0,0 +1,14 @@ +with Fuand; + +procedure Test_FUAND_B is +begin + Fuand.Test_B; +end; + +--# fuand.ads +-- +--%opts: --trace-mode=bin +-- /eval/ l! ## c!:"Color(A" +-- +--%opts: --trace-mode=src +-- /eval/ l! ## c!:"(Color(A" diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_t.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_t.adb new file mode 100644 index 000000000..1d9bf96c3 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/test_fuand_t.adb @@ -0,0 +1,9 @@ +with Fuand; + +procedure Test_FUAND_T is +begin + Fuand.Test_T; +end; + +--# fuand.ads +-- /eval/ l! ## eF- diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/test.py b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.adb new file mode 100644 index 000000000..8ab828d99 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.adb @@ -0,0 +1,24 @@ +pragma Ada_2012; + +package body Pkg.Simple is + + ------------- + -- Is_Null -- + ------------- + + function Is_Null (Self : Simple_Object) return Boolean is + begin + return False; + end Is_Null; + + --------------- + -- Get_Model -- + --------------- + + function Get_Model (Self : Simple_Object) return Model'Class is + Result : constant Model := (Not_Null => True); + begin + return Result; + end Get_Model; + +end Pkg.Simple; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.ads b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.ads new file mode 100644 index 000000000..92ec2fa7c --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg-simple.ads @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package Pkg.Simple is + type Simple_Object is new Object with private; + Singleton : constant Simple_Object; + function Is_Null (Self : Simple_Object) return Boolean; + function Get_Model (Self : Simple_Object) return Model'Class; +private + type Simple_Object is new Object with null record; + Singleton : constant Simple_Object := (null record); +end Pkg.Simple; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.adb new file mode 100644 index 000000000..e72ce33f3 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.adb @@ -0,0 +1,22 @@ +package body Pkg is + + ----------- + -- Clone -- + ----------- + + function Clone (Self : Object'Class) return Object'Class + is + begin + return Self; -- # clone + end Clone; + + ------------- + -- Is_Null -- + ------------- + + function Is_Null (Self : Model'Class) return Boolean is + begin + return not Self.Not_Null; -- # is-null + end Is_Null; + +end Pkg; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.ads b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.ads new file mode 100644 index 000000000..a3c451c58 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/pkg.ads @@ -0,0 +1,23 @@ +pragma Ada_2012; + +package Pkg is + + type Model is tagged private; + type Object is interface; + + function Is_Null (Self : Object) return Boolean is abstract; + function Clone (Self : Object'Class) return Object'Class with + Post => not Clone'Result.Get_Model.Is_Null; + function Get_Model (Self : Object) return Model'Class is abstract; + function Get_Id (Self : Object'Class) return Natural is + (if Self.Is_Null or else Self.Clone.Is_Null -- # get-id-cond + then 0 -- # get-id-then + else 1); -- # get-id-else + + function Is_Null (Self : Model'Class) return Boolean; + +private + type Model is tagged record + Not_Null : Boolean; + end record; +end Pkg; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/test_no.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/test_no.adb new file mode 100644 index 000000000..8d3a64c06 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/src/test_no.adb @@ -0,0 +1,21 @@ +with Pkg.Simple; use Pkg.Simple; + +procedure Test_No is +begin + if Singleton.Is_Null then + raise Program_Error; + end if; + + if Singleton.Get_Model.Is_Null then + raise Program_Error; + end if; +end Test_No; + +--# pkg.ads +-- /get-id-cond/ l- ## s- +-- /get-id-then/ l- ## 0 +-- /get-id-else/ l- ## 0 + +--# pkg.adb +-- /clone/ l- ## s- +-- /is-null/ l+ ## 0 diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.opt b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.opt new file mode 100644 index 000000000..6c7b0a7ff --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD Test relies on advanced use of tagged types diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.py b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/expr.ads b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/expr.ads new file mode 100644 index 000000000..f8a15451f --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/expr.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Expr is + function F (A, B, C : Boolean) return Boolean is + ((A and then B) or else C); -- # eval +end; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_a.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_a.adb new file mode 100644 index 000000000..b2a762343 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_a.adb @@ -0,0 +1,10 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Expr_A is +begin + Assert (F (False, True, False) = False); + Assert (F (True, True, False) = True); +end; + +--# expr.ads +-- /eval/ l! ## c!:"B",c!:"C" diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_f.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_f.adb new file mode 100644 index 000000000..5447fb4c3 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_f.adb @@ -0,0 +1,10 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Expr_F is +begin + Assert (F (True, False, False) = False); + Assert (F (False, True, False) = False); +end; + +--# expr.ads +-- /eval/ l! ## eT- diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_t.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_t.adb new file mode 100644 index 000000000..caac52984 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/test_expr_t.adb @@ -0,0 +1,11 @@ +with Expr, Support; use Expr, Support; + +procedure Test_Expr_T is +begin + Assert (F (True, True, False) = True); + Assert (F (False, True, True) = True); + Assert (F (True, False, True) = True); +end; + +--# expr.ads +-- /eval/ l! ## eF- diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/test.py b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/status.txt b/testsuite/tests/Ada2012/status.txt new file mode 100644 index 000000000..9cd74fee8 --- /dev/null +++ b/testsuite/tests/Ada2012/status.txt @@ -0,0 +1,114 @@ +Ada2012 specific items +====================== + +----------- +Pre aspects +----------- + +No code when deactivated. +Few tests otherwise. + +Pre aspect is considered as a control flow context, so applies to dc & single +op expressions as well. Is this what we want ? We don't do that for pragmas. + +----------- +Post aspects +------------ + +Tool processing-wise, current status is same as Pre. + +Turning a Post False is tough in real life though, so ... + +*Background discussion* + + * keep as regular decision for mcdc ? + + * claim nothing of interest at all ? + + * in-between: "contract" expression, always same value, + but operand variations required ? + +---------------------- +Type_Invariant aspects +---------------------- + +Invariant expressions considered as decisions but are not processed +correctly. Additional complexity is the lack of debug info in invariant +checking subprograms (N212-009) + +Needs definition work prior to implementation. + +---------------- +For E of +---------------- + +Works fine, as a regular for statement SC'wise. Few tests. + +---------- +X in 1|2|7 +---------- + +Works fine, considered as single operand (condition). Few tests. + +*Background discussion* + +Should this be seen as a implicit nested decision with three tests ? +Would complicate matters a lot and why not wonder the same about X < 0 ? + +-------------- +Expr functions +-------------- + +Work fine. Few tests. + +-------------- +If expressions +-------------- + +In deactivated Pre or Post, no code => no violation ever. Few tests. + +As of now, + +* the IF is seen as a control flow context + => controlling expression is decision even if simple. + +* THEN/ELSE are not seen as control flow context and + expressions treated as decisions if complex, for mcdc + +* inaccurate results on degraded origins for ctl expr (N227-030) + +*Background discussion* + +How do we want to deal with the functional programming aspects of Ada2012 ? +(N214-014) + +Introduce "expression" coverage, where subexpressions of if or case +expressions need to be evaluated at least once ? + + +------------------ +subtype predicates +------------------ + +To be evaluated. + +------------------ +in out to function +------------------ + +Works fine. Few tests checking that things "work" with stmts assignining +to In Out of function, stmt & mcdc. + +---------------- +Case expressions +---------------- + +To be evaluated. + +---------------------- +Quantified Expressions +---------------------- + +Work fine. ForAll and ForSome are both considered as conditions. +Complex expressions nested in the for-all/for-some predicate are +seen as decisions. diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_0.adb b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_0.adb new file mode 100644 index 000000000..43f2ceed9 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_0.adb @@ -0,0 +1,15 @@ +with Values.Global, Values.Arg; + +procedure Test_Values_0 is +begin + null; +end; + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- + diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_arg.adb new file mode 100644 index 000000000..addf20221 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_arg.adb @@ -0,0 +1,17 @@ +pragma Ada_2012; + +with Values.ARG, Support; use Values, Support; + +procedure Test_Values_ARG is + LA : Array_Type := (others => (X => 5)); +begin + ARG.Do_Loop_Over (LA); + for E of LA loop + Assert (E.X = 6); + end loop; +end; + +--# values-arg.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_gsa.adb b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_gsa.adb new file mode 100644 index 000000000..af55a6cbf --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_gsa.adb @@ -0,0 +1,15 @@ +with Values.Global, Support; use Values, Support; + +procedure Test_Values_GSA is +begin + Global.GSA := (others => (X => 4)); + + Global.Do_Loop; + Assert (Global.GSA (1).X = 5); + Assert (Global.GSA (3).X = 5); +end; + +--# values-global.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values-global.ads b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values-global.ads new file mode 100644 index 000000000..b0a468686 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values-global.ads @@ -0,0 +1,6 @@ +package Values.Global is + + GSA : Array_Type; + + procedure Do_Loop; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.adb b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.adb new file mode 100644 index 000000000..ee25be553 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.adb @@ -0,0 +1,8 @@ +package body Values is + + procedure Touch (E : in out Object) is + begin + E.X := E.X + 1; + end; + +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.ads b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.ads new file mode 100644 index 000000000..d0d2c6781 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.ads @@ -0,0 +1,12 @@ + +package Values is + + type Object is tagged record + X : Integer; + end record; + + type Array_Type is array (1 .. 8) of Object; + + procedure Touch (E : in out Object); + +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/test.py b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_0.adb b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_0.adb new file mode 100644 index 000000000..43f2ceed9 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_0.adb @@ -0,0 +1,15 @@ +with Values.Global, Values.Arg; + +procedure Test_Values_0 is +begin + null; +end; + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- + diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_arg.adb new file mode 100644 index 000000000..77f439ec4 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_arg.adb @@ -0,0 +1,17 @@ +pragma Ada_2012; + +with Values.ARG, Support; use Values, Support; + +procedure Test_Values_ARG is + LA : Array_Type := (others => 1); +begin + ARG.Do_Loop_Over (LA); + for E of LA loop + Assert (E = 2); + end loop; +end; + +--# values-arg.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_gsa.adb b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_gsa.adb new file mode 100644 index 000000000..3acbb6ed4 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_gsa.adb @@ -0,0 +1,14 @@ +with Values.Global, Support; use Values, Support; + +procedure Test_Values_GSA is +begin + Global.GSA := (1 .. 2 => 1, 3 .. 4 => 2); + Global.Do_Loop; + Assert (Global.GSA (2) = 2); + Assert (Global.GSA (4) = 4); +end; + +--# values-global.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values-global.ads b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values-global.ads new file mode 100644 index 000000000..353d50994 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values-global.ads @@ -0,0 +1,5 @@ + +package Values.Global is + GSA : Array_Type; + procedure Do_Loop; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.adb b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.adb new file mode 100644 index 000000000..859ef8749 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.adb @@ -0,0 +1,6 @@ +package body Values is + procedure Touch (E : in out Num) is + begin + E := E * 2; + end; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.ads b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.ads new file mode 100644 index 000000000..febf6e08d --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.ads @@ -0,0 +1,10 @@ + +package Values is + type Num is mod 2**8; + for Num'Size use 8; + + type Array_Type is array (1 .. 4) of Num; + pragma Pack (Array_Type); + + procedure Touch (E : in out Num); +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/test.py b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_0.adb b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_0.adb new file mode 100644 index 000000000..43f2ceed9 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_0.adb @@ -0,0 +1,15 @@ +with Values.Global, Values.Arg; + +procedure Test_Values_0 is +begin + null; +end; + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- + diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_arg.adb new file mode 100644 index 000000000..1f8b82990 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_arg.adb @@ -0,0 +1,17 @@ +pragma Ada_2012; + +with Values.ARG, Support; use Values, Support; + +procedure Test_Values_ARG is + LA : Array_Type := (others => 5); +begin + ARG.Do_Loop_Over (LA); + for E of LA loop + Assert (E = 10); + end loop; +end; + +--# values-arg.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_gsa.adb b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_gsa.adb new file mode 100644 index 000000000..091b624a7 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_gsa.adb @@ -0,0 +1,15 @@ +with Values.Global, Support; use Values, Support; + +procedure Test_Values_GSA is +begin + Global.GSA := (1, 2, 3, 4, 5, 6, 7, 8); + + Global.Do_Loop; + Assert (Global.GSA (3) = 6); + Assert (Global.GSA (6) = 12); +end; + +--# values-global.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values-global.ads b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values-global.ads new file mode 100644 index 000000000..353d50994 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values-global.ads @@ -0,0 +1,5 @@ + +package Values.Global is + GSA : Array_Type; + procedure Do_Loop; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.adb b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.adb new file mode 100644 index 000000000..799aa7ad6 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.adb @@ -0,0 +1,6 @@ +package body Values is + procedure Touch (E : in out Integer) is + begin + E := E * 2; + end; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.ads b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.ads new file mode 100644 index 000000000..85e2e87bb --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.ads @@ -0,0 +1,5 @@ +package Values is + type Array_Type is array (1 .. 8) of Integer; + + procedure Touch (E : in out Integer); +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/test.py b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_0.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_0.adb new file mode 100644 index 000000000..43f2ceed9 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_0.adb @@ -0,0 +1,15 @@ +with Values.Global, Values.Arg; + +procedure Test_Values_0 is +begin + null; +end; + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- + +--# values-global.adb +-- /stmt/ l- ## s- +-- /loop_op/ l- ## s- + diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_arg.adb new file mode 100644 index 000000000..997457438 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_arg.adb @@ -0,0 +1,18 @@ +pragma Ada_2012; + +with Values.ARG, Support; use Values, Support; + +procedure Test_Values_ARG is + LA : Array_Type := (1 .. 12 => 5); + pragma Volatile (LA); +begin + ARG.Do_Loop_Over (LA); + for E of LA loop + Assert (E = 10); + end loop; +end; + +--# values-arg.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_empty.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_empty.adb new file mode 100644 index 000000000..d58b5795f --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_empty.adb @@ -0,0 +1,12 @@ +with Values.Arg, Support; use Values, Support; + +procedure Test_Values_EMPTY is + LA : Array_Type (1 .. 0); +begin + Arg.Do_Loop_Over (LA); +end; + +--# values-arg.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l- ## s- + diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_gsa.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_gsa.adb new file mode 100644 index 000000000..b42fdaed2 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_gsa.adb @@ -0,0 +1,13 @@ +with Values.Global, Support; use Values, Support; + +procedure Test_Values_GSA is +begin + Global.Do_Loop; + Assert (Global.GSA (3) = 2); + Assert (Global.GSA (6) = 4); +end; + +--# values-global.adb +-- /stmt/ l+ ## 0 +-- /loop_op/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values-global.ads b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values-global.ads new file mode 100644 index 000000000..ae6110c86 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values-global.ads @@ -0,0 +1,5 @@ + +package Values.Global is + GSA : Array_Type := (1 .. 4 => 1, 5 .. 8 => 2); + procedure Do_Loop; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.adb new file mode 100644 index 000000000..799aa7ad6 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.adb @@ -0,0 +1,6 @@ +package body Values is + procedure Touch (E : in out Integer) is + begin + E := E * 2; + end; +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.ads b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.ads new file mode 100644 index 000000000..51807d164 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.ads @@ -0,0 +1,5 @@ +package Values is + type Array_Type is array (Natural range <>) of Integer; + + procedure Touch (E : in out Integer); +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/test.py b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.adb new file mode 100644 index 000000000..cec6ab8b5 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package body Values.ARG is + + procedure Do_Loop_Over (A : in out Array_Type) is + begin + for E of A loop -- # stmt + Touch (E); -- # loop_op + end loop; + end; + +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.ads b/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.ads new file mode 100644 index 000000000..cfcd6361f --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.ads @@ -0,0 +1,4 @@ + +package Values.Arg is + procedure Do_Loop_Over (A : in out Array_Type); +end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/src/values-global.adb b/testsuite/tests/Ada2012/stmt/ForOf/src/values-global.adb new file mode 100644 index 000000000..29903de08 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/ForOf/src/values-global.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package body Values.Global is + + procedure Do_Loop is + begin + for E of GSA loop -- # stmt + Touch (E); -- # loop_op + end loop; + end; + +end; diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/expr.adb b/testsuite/tests/Ada2012/stmt/InOut/src/expr.adb new file mode 100644 index 000000000..a2abf3451 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/src/expr.adb @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package body Expr is + function Plus (X, Y : Integer; Pos: in out Boolean) return Integer is + begin + if Pos then -- # test + Pos := X > 0 and then Y > 0; -- # eval + end if; + return X + Y; -- # stmt + end; +end; diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/expr.ads b/testsuite/tests/Ada2012/stmt/InOut/src/expr.ads new file mode 100644 index 000000000..4753272d7 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/src/expr.ads @@ -0,0 +1,5 @@ +pragma Ada_2012; + +package Expr is + function Plus (X, Y : Integer; Pos: in out Boolean) return Integer; +end; diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/expr.ali b/testsuite/tests/Ada2012/stmt/InOut/src/expr.ali new file mode 100644 index 000000000..c07658cc1 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/src/expr.ali @@ -0,0 +1,22 @@ +V "GNAT Lib v7.3" +A -mtune=generic +A -march=x86-64 +P ZX + +RN +RV NO_IMPLEMENTATION_PRAGMAS + +U expr%b expr.adb 9afba2dd NE OO PK + +U expr%s expr.ads a0cd5364 EE NE OO PK + +D expr.ads 20140214111047 a0cd5364 +D expr.adb 20140214111226 3a36f1b9 +D system.ads 20120706154652 90249111 +X 1 expr.ads +3K9*Expr 5e4 2|3b14 11t4 +4V13*Plus{integer} 4>19 4>22 4=35 2|4b13 10t7 +4i19 X{integer} 2|4b19 7r17 9r14 +4i22 Y{integer} 2|4b22 7r32 9r18 +4b35 Pos{boolean} 2|4b35 6r10 7m10 + diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_f.adb b/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_f.adb new file mode 100644 index 000000000..b7199613b --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_f.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Support, Expr; use Support, Expr; + +procedure Test_Eval_F is + Pos : Boolean := True; +begin + Assert (Plus (5, -6, Pos) = -1); + Assert (Pos = False); +end; + +--# expr.adb +-- /stmt/ l+ ## 0 +-- /test/ l+ ## 0 +-- /eval/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_t.adb b/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_t.adb new file mode 100644 index 000000000..fe62f78b1 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_t.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Support, Expr; use Support, Expr; + +procedure Test_Eval_T is + Pos : Boolean := True; +begin + Assert (Plus (5, 6, Pos) = 11); + Assert (Pos = True); +end; + +--# expr.adb +-- /stmt/ l+ ## 0 +-- /test/ l+ ## 0 +-- /eval/ l+ ## 0 + diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/test_neval.adb b/testsuite/tests/Ada2012/stmt/InOut/src/test_neval.adb new file mode 100644 index 000000000..976c7e158 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/src/test_neval.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Support, Expr; use Support, Expr; + +procedure Test_Neval is + Pos : Boolean := False; +begin + Assert (Plus (5, 6, Pos) = 11); + Assert (Pos = False); +end; + +--# expr.adb +-- /stmt/ l+ ## 0 +-- /test/ l+ ## 0 +-- /eval/ l- ## s- + diff --git a/testsuite/tests/Ada2012/stmt/InOut/test.py b/testsuite/tests/Ada2012/stmt/InOut/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/InOut/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.adb new file mode 100644 index 000000000..3e37d82cb --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased R; -- # npc decl + begin + PR4 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.ads new file mode 100644 index 000000000..59232baad --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/src/pak.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package Pak is + type R is tagged limited null record; + procedure PR4 (X : access R'Class) is null; -- # npb + + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccClassWideParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.adb new file mode 100644 index 000000000..3bcdd3feb --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased constant R := (null record); -- # npc decl + begin + PR5 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.ads new file mode 100644 index 000000000..52256bb2b --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/src/pak.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package Pak is + type R is tagged limited null record; + procedure PR5 (X : access constant R'Class) is null; -- # npb + + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccConstClassWideParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.adb new file mode 100644 index 000000000..fd95d6af6 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased constant Integer := 1; -- # npc decl + begin + P4 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.ads new file mode 100644 index 000000000..34bf52b6c --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/src/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + procedure P4 (X : access constant Integer) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccConstParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.adb new file mode 100644 index 000000000..7c18d8e2e --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; + +package body Pak is + + function Callback (S : access String) return Natural + is (S.all'Length); -- # npp + + procedure Call is + begin + P2 (Callback'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.ads new file mode 100644 index 000000000..f854906f1 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/src/pak.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package Pak is + procedure P2 + (X : access function (S : access String) return Natural) + is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccFunc/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.adb new file mode 100644 index 000000000..297735871 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased Integer; -- # npc decl + begin + P2 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.ads new file mode 100644 index 000000000..dfebd4298 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccParam/src/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + procedure P2 (X : access Integer) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.adb new file mode 100644 index 000000000..e0aee321e --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.adb @@ -0,0 +1,10 @@ +package body Pak is + + procedure Callback is null; -- # npp + + procedure Call is + begin + P2 (Callback'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.ads new file mode 100644 index 000000000..b0c9d9454 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccProc/src/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + procedure P2 (X : access procedure) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccProc/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccProc/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccProc/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.adb new file mode 100644 index 000000000..df8954e8b --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.adb @@ -0,0 +1,11 @@ +package body Pak is + + procedure PPR2 (X : access PR) is null; -- # npb + + procedure Call is + X : aliased PR; -- # npc decl + begin + PPR2 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.ads new file mode 100644 index 000000000..0bd03811d --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.ads @@ -0,0 +1,13 @@ +pragma Ada_2012; + +package Pak is + type R is abstract tagged limited null record; + type PR is new R with private; + procedure PPR2 (X : access PR); + + procedure Call; + +private + type PR is new R with null record; +end Pak; + diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.adb new file mode 100644 index 000000000..e75f02451 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased PR; -- # npc decl + begin + PPR1 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.ads new file mode 100644 index 000000000..caf2dc177 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package Pak is + type R is abstract tagged limited null record; + type PR is new R with private; + procedure PPR1 (X : access PR); + + procedure Call; + +private + type PR is new R with null record; + procedure PPR1 (X : access PR) is null; -- # npb +end Pak; + diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.adb new file mode 100644 index 000000000..75c660547 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased PR; -- # npc decl + begin + PPR0 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.ads new file mode 100644 index 000000000..adea23fac --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.ads @@ -0,0 +1,13 @@ +pragma Ada_2012; + +package Pak is + type R is abstract tagged limited null record; + type PR is new R with private; + procedure PPR0 (X : access PR) is null; -- # npb + + procedure Call; + +private + type PR is new R with null record; +end Pak; + diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.adb new file mode 100644 index 000000000..e0762f1e4 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased R; -- # npc decl + begin + PR2 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.ads new file mode 100644 index 000000000..3a305f818 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package Pak is + type R is tagged limited null record; + procedure PR2 (X : access R) is null; -- # npb + procedure Call; +end Pak; + diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.adb new file mode 100644 index 000000000..f99ffc3bb --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : R; -- # npc decl + begin + PR1 (X); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.ads new file mode 100644 index 000000000..577432a34 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/src/pak.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; + +package Pak is + type R is tagged limited null record; + procedure PR1 (X : R'Class) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/ClassWideParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.adb new file mode 100644 index 000000000..2dc9c754e --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.adb @@ -0,0 +1,8 @@ +package body Pak is + + procedure Call is + begin + P1 (4); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.ads new file mode 100644 index 000000000..0d9b467c2 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/InParam/src/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + procedure P1 (X : Integer) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/InParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/InParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/InParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.adb new file mode 100644 index 000000000..e93aa2b62 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.adb @@ -0,0 +1,8 @@ +package body Pak is + + procedure Call is + begin + P0; -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.ads new file mode 100644 index 000000000..eef128b87 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NoParam/src/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + procedure P0 is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NoParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/NoParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NoParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.adb new file mode 100644 index 000000000..315f900ef --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased Integer; -- # npc decl + begin + P3 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.ads new file mode 100644 index 000000000..2a3eabcdc --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/src/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + procedure P3 (X : not null access Integer) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.adb new file mode 100644 index 000000000..db9b4d188 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : aliased R; -- # npc decl + begin + PR3 (X'Access); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.ads new file mode 100644 index 000000000..c74d94855 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/src/pak.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; + +package Pak is + type R is tagged limited null record; + procedure PR3 (X : not null access R) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/NotNullAccTaggedParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.adb b/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.adb new file mode 100644 index 000000000..185923d48 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.adb @@ -0,0 +1,9 @@ +package body Pak is + + procedure Call is + X : R; -- # npc decl + begin + PR0 (X); -- # npc + end Call; + +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.ads new file mode 100644 index 000000000..95facf357 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/src/pak.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; + +package Pak is + type R is tagged limited null record; + procedure PR0 (X : R) is null; -- # npb + procedure Call; +end Pak; diff --git a/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/test.py b/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/TaggedParam/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_call.adb b/testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_call.adb new file mode 100644 index 000000000..b0251fdfe --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_call.adb @@ -0,0 +1,18 @@ +with Pak; +procedure Test_Pak_Call is +begin + Pak.Call; +end Test_Pak_Call; + +--# pak.ads +-- /npc/ l+ ## 0 +-- /npp/ l- ## s- +-- /npb/ l+ ## 0 + +--# pak.adb +-- /npc/ l+ ## 0 +-- /npp/ l- ## s- +-- /npb/ l+ ## 0 +-- +--%opts: --trace-mode=bin %cargs:-O1 +-- =/npp/ l. ## 0 diff --git a/testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_no.adb b/testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_no.adb new file mode 100644 index 000000000..e2cb3a4ae --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/NullProc/src/test_pak_no.adb @@ -0,0 +1,18 @@ +with Pak; +procedure Test_Pak_No is +begin + null; +end Test_Pak_No; + +--# pak.ads +-- /npc/ l- ## s- +-- /npp/ l- ## s- +-- /npb/ l- ## s- + +--# pak.adb +-- /npc/ l- ## s- +-- /npp/ l- ## s- +-- /npb/ l- ## s- +-- +--%opts: --trace-mode=bin %cargs:-O1 +-- =/npp/ l. ## 0 diff --git a/testsuite/tests/Ada2012/stmt/Xfunctions/src/expr.ads b/testsuite/tests/Ada2012/stmt/Xfunctions/src/expr.ads new file mode 100644 index 000000000..735168bd2 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/Xfunctions/src/expr.ads @@ -0,0 +1,4 @@ +pragma Ada_2012; +package Expr is + function Plus (X, Y : Integer) return Integer is (X + Y); -- # stmt +end; diff --git a/testsuite/tests/Ada2012/stmt/Xfunctions/src/test_0.adb b/testsuite/tests/Ada2012/stmt/Xfunctions/src/test_0.adb new file mode 100644 index 000000000..662071ae5 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/Xfunctions/src/test_0.adb @@ -0,0 +1,9 @@ +with Support, expr; use Support, Expr; + +procedure Test_0 is +begin + null; +end; + +--# expr.ads +-- /stmt/ l- ## s- diff --git a/testsuite/tests/Ada2012/stmt/Xfunctions/test.py b/testsuite/tests/Ada2012/stmt/Xfunctions/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ada2012/stmt/Xfunctions/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/extra.opt b/testsuite/tests/C++/extra.opt new file mode 100644 index 000000000..057749df0 --- /dev/null +++ b/testsuite/tests/C++/extra.opt @@ -0,0 +1,2 @@ +!C++ DEAD Only run C++ tests if we have a supported C++ compiler +bin-traces DEAD C++ not supported with binary traces diff --git a/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.cpp new file mode 100644 index 000000000..e77247ae6 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.cpp @@ -0,0 +1,14 @@ +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + // Basic lambda function here, a mere expression return + + auto AndExpr = [] (int aa, int bb) { // # other + return aa > 0 && bb > 0; // # eval :o/e: + }; // # lambda_other + + volatile bool b = AndExpr (aa, bb); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/test.py b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.cpp new file mode 100644 index 000000000..7aeecfdb6 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.cpp @@ -0,0 +1,23 @@ +#include + +class AndExpr +{ +public: + int + eval (bool aa, bool bb) + { + if (aa && bb) // # eval :o/d: + return true; // # true + else + return false; // # false + } +}; + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + AndExpr ().eval (aa, bb); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ClassDef/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_ClassDef/test.py b/testsuite/tests/C++/mcdc/AandB/In_ClassDef/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ClassDef/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.cpp new file mode 100644 index 000000000..567a0b345 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.cpp @@ -0,0 +1,25 @@ +template class AndExpr +{ + bool _ev; + +public: + void + eval () + { + _ev = aa && bb; // # eval :o/e: + } +}; + +static bool a; +bool b; + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + a = aa; // # other + b = bb; // # other + AndExpr ().eval (); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/test.py b/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ClassTemplate/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.cpp new file mode 100644 index 000000000..2b8838f86 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.cpp @@ -0,0 +1,21 @@ +#include + +class AndExpr +{ + bool _value; + +public: + AndExpr (bool aa, bool bb) + { + _value = aa && bb; // # eval :o/e: + } +}; + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + AndExpr (aa, bb); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_Ctor/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_Ctor/test.py b/testsuite/tests/C++/mcdc/AandB/In_Ctor/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_Ctor/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.cpp new file mode 100644 index 000000000..c7585e64d --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.cpp @@ -0,0 +1,21 @@ +#include "tryme.hh" + +namespace glob +{ +bool aa, bb; +} + +void +bar (bool b = glob::aa || glob::bb) // # eval :o/e: +{ +} + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + glob::aa = aa; // # other + glob::bb = bb; // # other + bar (); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.opt b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.opt new file mode 100644 index 000000000..9b91bd331 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.opt @@ -0,0 +1 @@ +all XFAIL MCDC instrumentation of default initializers not supported \ No newline at end of file diff --git a/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.py b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.cpp new file mode 100644 index 000000000..cb87053ef --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.cpp @@ -0,0 +1,35 @@ +class AndExpr +{ +public: + AndExpr (bool a, bool b); + ~AndExpr (); + +private: + bool aa, bb; +}; + +AndExpr::AndExpr (bool a, bool b) +{ + this->aa = a; // # other + this->bb = b; // # other +} + +static bool evalue; + +AndExpr::~AndExpr () +{ + if (aa && bb) // # eval :o/d: + ::evalue = true; // # true + else + ::evalue = false; // # false +} + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + AndExpr *e = new AndExpr (aa, bb); // # other + delete e; // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_Dtor/test.py b/testsuite/tests/C++/mcdc/AandB/In_Dtor/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_Dtor/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.cpp new file mode 100644 index 000000000..752809650 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.cpp @@ -0,0 +1,17 @@ +extern "C" +{ + bool + AndExpr (bool aa, bool bb) + { + return aa && bb; // # eval :o/e: + } +} + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + volatile bool ev = AndExpr (aa, bb); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ExternC/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_ExternC/test.opt b/testsuite/tests/C++/mcdc/AandB/In_ExternC/test.opt new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/C++/mcdc/AandB/In_ExternC/test.py b/testsuite/tests/C++/mcdc/AandB/In_ExternC/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_ExternC/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.cpp new file mode 100644 index 000000000..408a24f82 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.cpp @@ -0,0 +1,15 @@ +template +bool +AndExpr (T aa, T bb) +{ + return aa && bb; // # eval :o/e: +} + +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + volatile bool b = AndExpr (aa, bb); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/test.py b/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_FunctionTemplate/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.cpp new file mode 100644 index 000000000..7f1c2adfe --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.cpp @@ -0,0 +1,17 @@ +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + // A lambda function with a real sequence of statements here + + auto AndExpr = [] (int aa, int bb) { // # other + if (aa > 0 && bb > 0) // # eval :o/d: + return true; // # lambda_true + else // # lambda_other + return false; // # lambda_false + }; // # lambda_other + + volatile bool b = AndExpr (aa, bb); // # other +} diff --git a/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/test.py b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_a.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_a.cpp new file mode 100644 index 000000000..b9583193a --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_a.cpp @@ -0,0 +1,17 @@ +#include + +int +main () +{ + tryme (/* aa */ true, /* bb */ true); + tryme (/* aa */ false, /* bb */ true); +} + +//# tryme.cpp tryme.hh +// /eval/ l! ## c!:"bb" +// /true/ l+ ## 0 +// /false/ l+ ## 0 +// /other/ l+ ## 0 + +// /test_skip/ l! ## dT- +// /skip/ l- ## s- diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_b.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_b.cpp new file mode 100644 index 000000000..601962c54 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_b.cpp @@ -0,0 +1,17 @@ +#include + +int +main () +{ + tryme (/* aa */ true, /* bb */ true); + tryme (/* aa */ true, /* bb */ false); +} + +//# tryme.cpp tryme.hh +// /eval/ l! ## c!:"aa" +// /true/ l+ ## 0 +// /false/ l+ ## 0 +// /other/ l+ ## 0 + +// /test_skip/ l! ## dT- +// /skip/ l- ## s- diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_full.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_full.cpp new file mode 100644 index 000000000..8ceb14f73 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_full.cpp @@ -0,0 +1,18 @@ +#include + +int +main () +{ + tryme (/* aa */ true, /* bb */ true); + tryme (/* aa */ true, /* bb */ false); + tryme (/* aa */ false, /* bb */ false); +} + +//# tryme.cpp tryme.hh +// /eval/ l+ ## 0 +// /true/ l+ ## 0 +// /false/ l+ ## 0 +// /other/ l+ ## 0 + +// /test_skip/ l! ## dT- +// /skip/ l- ## s- diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_fx.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_fx.cpp new file mode 100644 index 000000000..572a53763 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_fx.cpp @@ -0,0 +1,19 @@ +#include + +int +main () +{ + tryme (/* aa */ false, /* bb */ false); +} + +//# tryme.cpp tryme.hh +// /eval/ l! ## oT- +// /true/ l- ## s- +// /false/ l+ ## 0 +// /other/ l+ ## 0 + +// /lambda_true/ l! ## s- +// /lambda_false/ l+ ## 0 + +// /test_skip/ l! ## dT- +// /skip/ l- ## s- diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_skip.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_skip.cpp new file mode 100644 index 000000000..08da49ef3 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_skip.cpp @@ -0,0 +1,24 @@ +#include + +int +main () +{ + tryme (/* aa */ true, /* bb */ true, /* skip */ true); +} + +//# tryme.cpp tryme.hh +// /eval/ l- ## s- +// /true/ l- ## s- +// /false/ l- ## s- +// /other/ l- ## s- + +// All the lines of a stmt involving a lambda expr +// are noted '-' and the ones marked "other" don't +// have a nested entity of their own + +// /lambda_other/ l- ## 0c +// /lambda_true/ l- ## s- +// /lambda_false/ l- ## s- + +// /test_skip/ l! ## dF- +// /skip/ l+ ## 0 diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_tf.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_tf.cpp new file mode 100644 index 000000000..798084759 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_tf.cpp @@ -0,0 +1,19 @@ +#include + +int +main () +{ + tryme (/* aa */ true, /* bb */ false); +} + +//# tryme.cpp tryme.hh +// /eval/ l! ## oT- +// /true/ l- ## s- +// /false/ l+ ## 0 +// /other/ l+ ## 0 + +// /lambda_true/ l! ## s- +// /lambda_false/ l+ ## 0 + +// /test_skip/ l! ## dT- +// /skip/ l- ## s- diff --git a/testsuite/tests/C++/mcdc/AandB/src/test_tryme_tt.cpp b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_tt.cpp new file mode 100644 index 000000000..7e3c79980 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/test_tryme_tt.cpp @@ -0,0 +1,19 @@ +#include + +int +main () +{ + tryme (/* aa */ true, /* bb */ true); +} + +//# tryme.cpp tryme.hh +// /eval/ l! ## oF- +// /true/ l+ ## 0 +// /false/ l- ## s- +// /other/ l+ ## 0 + +// /lambda_true/ l+ ## 0 +// /lambda_false/ l! ## s- + +// /test_skip/ l! ## dT- +// /skip/ l- ## s- diff --git a/testsuite/tests/C++/mcdc/AandB/src/tryme_api.hh b/testsuite/tests/C++/mcdc/AandB/src/tryme_api.hh new file mode 100644 index 000000000..76a1f23c8 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/src/tryme_api.hh @@ -0,0 +1 @@ +extern void tryme (bool aa, bool bb, bool skip = false); diff --git a/testsuite/tests/C++/mcdc/AandB/tc_set.rst b/testsuite/tests/C++/mcdc/AandB/tc_set.rst new file mode 100644 index 000000000..317b03055 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/tc_set.rst @@ -0,0 +1,24 @@ +**Exercise mcdc on a "a && b" expression instated in a variety of contexts** + +-- + +The code to test always features a "tryme" entry point expecting +the Boolean values to use for "a" and "b", as well as a "skip" argument +to request an early return. + +Expectation anchors: + +/eval/ Line where the a && b expression is evaluated. +/true/ Regular code executed when the expr evaluates true. +/false/ Regular code executed when the expr evaluates false. +/other/ Regular code executed regardless of the expr value. + +/lambda_true/ Code executed when the expr evaluates true + as part of a lambda function. +/lambda_false/ Code executed when the expr evaluates false + as part of a lambda function. +/lambda_other/ Other lines constituting a lambda expression, + expected not to contain any stmt of their own. + +/test_skip/ Line testing the "skip" argument. +/skip/ Code executed when "skip" is true. diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.cpp b/testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.cpp new file mode 100644 index 000000000..dc2811cef --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.cpp @@ -0,0 +1,13 @@ +#include "sum.hh" +#include "validate.hh" + +int +sum (std::vector ints) +{ + int result = 0; // # init + for (validate (ints); // # for-init + const int &i : ints // # for-range + ) + result += i; // # add + return result; // # return +} diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.hh b/testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.hh new file mode 100644 index 000000000..1e4dd32b0 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/sum.hh @@ -0,0 +1,3 @@ +#include + +extern int sum (std::vector ints); diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_0.cpp b/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_0.cpp new file mode 100644 index 000000000..91f13c42c --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_0.cpp @@ -0,0 +1,16 @@ +#include "sum.hh" + +int +main (void) +{ + volatile bool b = false; + return b && sum ({ 0, 1 }); +} + +//# sum.cpp +// +// /init/ l- ## s- +// /for-init/ l- ## s- +// /for-range/ l- ## s- +// /add/ l- ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_early_exit.cpp b/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_early_exit.cpp new file mode 100644 index 000000000..d560f4e33 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_early_exit.cpp @@ -0,0 +1,26 @@ +#include "sum.hh" + +int +main (void) +{ + int result; + + try + { + result = sum ({ 0, 1 }); + } + catch (const char *msg) + { + return 0; + } + + return 1; +} + +//# sum.cpp +// +// /init/ l+ ## 0 +// /for-init/ l+ ## 0 +// /for-range/ l- ## s- +// /add/ l- ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_full.cpp b/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_full.cpp new file mode 100644 index 000000000..ffd905de3 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/test_full.cpp @@ -0,0 +1,18 @@ +#include "sum.hh" + +int +main (void) +{ + if (sum ({ 1, 2 }) != 3) + return 1; + return 0; +} + +//# sum.cpp +// +// /init/ l+ ## 0 +// /for-range/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-return/ l- ## s- +// /if-add/ l+ ## 0 +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.cpp b/testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.cpp new file mode 100644 index 000000000..38fc3101d --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.cpp @@ -0,0 +1,11 @@ +#include "validate.hh" + +void +validate (std::vector ints) +{ + for (const int &i : ints) + { + if (i == 0) + throw "invalid null element"; + } +} diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.hh b/testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.hh new file mode 100644 index 000000000..01c165241 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/src/validate.hh @@ -0,0 +1,3 @@ +#include + +extern void validate (std::vector ints); diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/test.py b/testsuite/tests/C++/stmt/ForRange/WithInit/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.cpp new file mode 100644 index 000000000..a3292f62d --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.cpp @@ -0,0 +1,14 @@ +#include "sum.hh" + +int +sum (std::vector ints) +{ + int result = 0; // # init + for (const int &i : ints) // # for-range + { + if (i == 0) // # if-cond + return 0; // # if-return + result += i; // # if-add + } + return result; // # return +} diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.hh b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.hh new file mode 100644 index 000000000..1e4dd32b0 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.hh @@ -0,0 +1,3 @@ +#include + +extern int sum (std::vector ints); diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_0.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_0.cpp new file mode 100644 index 000000000..a584fc402 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_0.cpp @@ -0,0 +1,17 @@ +#include "sum.hh" + +int +main (void) +{ + volatile bool b = false; + return b && sum ({ 0, 1 }); +} + +//# sum.cpp +// +// /init/ l- ## s- +// /for-range/ l- ## s- +// /if-cond/ l- ## s- +// /if-return/ l- ## s- +// /if-add/ l- ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_early_exit.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_early_exit.cpp new file mode 100644 index 000000000..d4a1ede07 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_early_exit.cpp @@ -0,0 +1,18 @@ +#include "sum.hh" + +int +main (void) +{ + if (sum ({ 0, 1 }) != 0) + return 1; + return 0; +} + +//# sum.cpp +// +// /init/ l+ ## 0 +// /for-range/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-return/ l+ ## 0 +// /if-add/ l- ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_empty.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_empty.cpp new file mode 100644 index 000000000..8e68d5def --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_empty.cpp @@ -0,0 +1,18 @@ +#include "sum.hh" + +int +main (void) +{ + if (sum ({}) != 0) + return 1; + return 0; +} + +//# sum.cpp +// +// /init/ l+ ## 0 +// /for-range/ l+ ## 0 +// /if-cond/ l- ## s- +// /if-return/ l- ## s- +// /if-add/ l- ## s- +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_full.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_full.cpp new file mode 100644 index 000000000..ffd905de3 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_full.cpp @@ -0,0 +1,18 @@ +#include "sum.hh" + +int +main (void) +{ + if (sum ({ 1, 2 }) != 3) + return 1; + return 0; +} + +//# sum.cpp +// +// /init/ l+ ## 0 +// /for-range/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-return/ l- ## s- +// /if-add/ l+ ## 0 +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/test.py b/testsuite/tests/C++/stmt/ForRange/WithoutInit/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C++/stmt/WhileDecl/src/count_digits.cpp b/testsuite/tests/C++/stmt/WhileDecl/src/count_digits.cpp new file mode 100644 index 000000000..23718f4aa --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/src/count_digits.cpp @@ -0,0 +1,13 @@ +#include "count_digits.hh" + +int +count_digits (const char *str) +{ + int result = 0; // # init + while (const char c = *str++) // # while-cond + { + if ('0' <= c && c <= '9') // # if-cond + result += 1; // # if-incr + } + return result; // # return +} diff --git a/testsuite/tests/C++/stmt/WhileDecl/src/count_digits.hh b/testsuite/tests/C++/stmt/WhileDecl/src/count_digits.hh new file mode 100644 index 000000000..38f39cf6d --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/src/count_digits.hh @@ -0,0 +1 @@ +extern int count_digits (const char *str); diff --git a/testsuite/tests/C++/stmt/WhileDecl/src/test_0.cpp b/testsuite/tests/C++/stmt/WhileDecl/src/test_0.cpp new file mode 100644 index 000000000..e8707d6ab --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/src/test_0.cpp @@ -0,0 +1,16 @@ +#include "count_digits.hh" + +int +main (void) +{ + volatile bool b = false; + return b && count_digits ("hello"); +} + +//# count_digits.cpp +// +// /init/ l- ## s- +// /while-cond/ l- ## s- +// /if-cond/ l- ## s- +// /if-incr/ l- ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/C++/stmt/WhileDecl/src/test_empty.cpp b/testsuite/tests/C++/stmt/WhileDecl/src/test_empty.cpp new file mode 100644 index 000000000..c3165bf25 --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/src/test_empty.cpp @@ -0,0 +1,17 @@ +#include "count_digits.hh" + +int +main (void) +{ + if (count_digits ("") != 0) + return 1; + return 0; +} + +//# count_digits.cpp +// +// /init/ l+ ## 0 +// /while-cond/ l+ ## 0 +// /if-cond/ l- ## s- +// /if-incr/ l- ## s- +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/WhileDecl/src/test_full.cpp b/testsuite/tests/C++/stmt/WhileDecl/src/test_full.cpp new file mode 100644 index 000000000..8d9caedf3 --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/src/test_full.cpp @@ -0,0 +1,17 @@ +#include "count_digits.hh" + +int +main (void) +{ + if (count_digits ("aa00") != 2) + return 1; + return 0; +} + +//# count_digits.cpp +// +// /init/ l+ ## 0 +// /while-cond/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-incr/ l+ ## 0 +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/WhileDecl/src/test_nodigit.cpp b/testsuite/tests/C++/stmt/WhileDecl/src/test_nodigit.cpp new file mode 100644 index 000000000..0cc3f3448 --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/src/test_nodigit.cpp @@ -0,0 +1,17 @@ +#include "count_digits.hh" + +int +main (void) +{ + if (count_digits ("aa") != 0) + return 1; + return 0; +} + +//# count_digits.cpp +// +// /init/ l+ ## 0 +// /while-cond/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-incr/ l- ## s- +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/WhileDecl/test.py b/testsuite/tests/C++/stmt/WhileDecl/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/stmt/WhileDecl/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C/decision/CommaExpr/src/cmp.c b/testsuite/tests/C/decision/CommaExpr/src/cmp.c new file mode 100644 index 000000000..dbf549e86 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/cmp.c @@ -0,0 +1,12 @@ +#include "cmp_internal.h" + +int +less_than (int a, int b) +{ + int result; // # decl + + if (compute_less_than (&result, a, b), result) // # if-cond + return 1; // # if-then + else + return 0; // # if-else +} diff --git a/testsuite/tests/C/decision/CommaExpr/src/cmp.h b/testsuite/tests/C/decision/CommaExpr/src/cmp.h new file mode 100644 index 000000000..7f2fb7b7c --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/cmp.h @@ -0,0 +1 @@ +extern int less_than (int a, int b); diff --git a/testsuite/tests/C/decision/CommaExpr/src/cmp_internal.c b/testsuite/tests/C/decision/CommaExpr/src/cmp_internal.c new file mode 100644 index 000000000..512c79a1b --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/cmp_internal.c @@ -0,0 +1,5 @@ +void +compute_less_than (int *result, int a, int b) +{ + *result = a < b; +} diff --git a/testsuite/tests/C/decision/CommaExpr/src/cmp_internal.h b/testsuite/tests/C/decision/CommaExpr/src/cmp_internal.h new file mode 100644 index 000000000..91b3e6dc5 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/cmp_internal.h @@ -0,0 +1 @@ +extern void compute_less_than (int *result, int a, int b); diff --git a/testsuite/tests/C/decision/CommaExpr/src/test_0.c b/testsuite/tests/C/decision/CommaExpr/src/test_0.c new file mode 100644 index 000000000..7ba70d919 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/test_0.c @@ -0,0 +1,15 @@ +#include "cmp.h" + +int +main (void) +{ + volatile int b = 0; + return b && less_than (1, 2); +} + +//# cmp.c +// +// /decl/ l- ## s- +// /if-cond/ l- ## s- +// /if-then/ l- ## s- +// /if-else/ l- ## s- diff --git a/testsuite/tests/C/decision/CommaExpr/src/test_f.c b/testsuite/tests/C/decision/CommaExpr/src/test_f.c new file mode 100644 index 000000000..5a7532ac4 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/test_f.c @@ -0,0 +1,21 @@ +#include "cmp.h" + +int +main (void) +{ + if (less_than (2, 1)) + { + return 1; + } + else + { + return 0; + } +} + +//# cmp.c +// +// /decl/ l+ ## 0 +// /if-cond/ l! ## dT- +// /if-then/ l- ## s- +// /if-else/ l+ ## 0 diff --git a/testsuite/tests/C/decision/CommaExpr/src/test_t.c b/testsuite/tests/C/decision/CommaExpr/src/test_t.c new file mode 100644 index 000000000..6323605d1 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/test_t.c @@ -0,0 +1,21 @@ +#include "cmp.h" + +int +main (void) +{ + if (less_than (1, 2)) + { + return 0; + } + else + { + return 1; + } +} + +//# cmp.c +// +// /decl/ l+ ## 0 +// /if-cond/ l! ## dF- +// /if-then/ l+ ## 0 +// /if-else/ l- ## s- diff --git a/testsuite/tests/C/decision/CommaExpr/src/test_tf.c b/testsuite/tests/C/decision/CommaExpr/src/test_tf.c new file mode 100644 index 000000000..1cd4b58b3 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/src/test_tf.c @@ -0,0 +1,21 @@ +#include "cmp.h" + +int +main (void) +{ + if (!less_than (1, 2) || less_than (2, 1)) + { + return 1; + } + else + { + return 0; + } +} + +//# cmp.c +// +// /decl/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-then/ l+ ## 0 +// /if-else/ l+ ## 0 diff --git a/testsuite/tests/C/decision/CommaExpr/test.py b/testsuite/tests/C/decision/CommaExpr/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/C/decision/CommaExpr/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/aligned.c b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/aligned.c new file mode 100644 index 000000000..dc326136b --- /dev/null +++ b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/aligned.c @@ -0,0 +1,8 @@ +char +aligned (int x, int y, int factor) +{ + if (!(x & (factor - 1)) && !(y && (factor - 1))) // # decision + return 1; // # stmt-true + else + return 0; // # stmt-false +} diff --git a/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/misc.ads b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/misc.ads new file mode 100644 index 000000000..bb85736e1 --- /dev/null +++ b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/misc.ads @@ -0,0 +1,4 @@ +package Misc is + function Aligned (X, Y, Factor : Integer) return Boolean; + pragma Import (C, Aligned, "aligned"); +end; diff --git a/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_false.adb b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_false.adb new file mode 100644 index 000000000..f9cc9fba8 --- /dev/null +++ b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_false.adb @@ -0,0 +1,11 @@ +with Misc, Support; use Misc, Support; + +procedure Test_Aligned_False is +begin + Assert (not Aligned (1, 0, 0)); +end; + +--# aligned.c +-- /decision/ l! ## dT- +-- /stmt-true/ l- ## s- +-- /stmt-false/ l+ ## 0 diff --git a/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_true.adb b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_true.adb new file mode 100644 index 000000000..3567b0330 --- /dev/null +++ b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/src/test_aligned_true.adb @@ -0,0 +1,11 @@ +with Misc, Support; use Misc, Support; + +procedure Test_Aligned_True is +begin + Assert (Aligned (0, 0, 0)); +end; + +--# aligned.c +-- /decision/ l! ## dF- +-- /stmt-true/ l+ ## 0 +-- /stmt-false/ l- ## s- diff --git a/testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.opt b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.opt new file mode 100644 index 000000000..32bb8756f --- /dev/null +++ b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.opt @@ -0,0 +1 @@ +7.2.2 DEAD requires compiler change from 2014-10, not in 7.2.2 diff --git a/testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.py b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/C/decision/NA14-030-twisted-c-expr/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C/extra.opt b/testsuite/tests/C/extra.opt new file mode 100644 index 000000000..0182653a4 --- /dev/null +++ b/testsuite/tests/C/extra.opt @@ -0,0 +1,2 @@ +7.0.3 DEAD 7.0.3 misses proper SCO support for C +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/cmp.c b/testsuite/tests/C/mcdc/CommaExpr/src/cmp.c new file mode 100644 index 000000000..dbf549e86 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/cmp.c @@ -0,0 +1,12 @@ +#include "cmp_internal.h" + +int +less_than (int a, int b) +{ + int result; // # decl + + if (compute_less_than (&result, a, b), result) // # if-cond + return 1; // # if-then + else + return 0; // # if-else +} diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/cmp.h b/testsuite/tests/C/mcdc/CommaExpr/src/cmp.h new file mode 100644 index 000000000..7f2fb7b7c --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/cmp.h @@ -0,0 +1 @@ +extern int less_than (int a, int b); diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.c b/testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.c new file mode 100644 index 000000000..512c79a1b --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.c @@ -0,0 +1,5 @@ +void +compute_less_than (int *result, int a, int b) +{ + *result = a < b; +} diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.h b/testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.h new file mode 100644 index 000000000..91b3e6dc5 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/cmp_internal.h @@ -0,0 +1 @@ +extern void compute_less_than (int *result, int a, int b); diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/test_0.c b/testsuite/tests/C/mcdc/CommaExpr/src/test_0.c new file mode 100644 index 000000000..7ba70d919 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/test_0.c @@ -0,0 +1,15 @@ +#include "cmp.h" + +int +main (void) +{ + volatile int b = 0; + return b && less_than (1, 2); +} + +//# cmp.c +// +// /decl/ l- ## s- +// /if-cond/ l- ## s- +// /if-then/ l- ## s- +// /if-else/ l- ## s- diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/test_f.c b/testsuite/tests/C/mcdc/CommaExpr/src/test_f.c new file mode 100644 index 000000000..5a7532ac4 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/test_f.c @@ -0,0 +1,21 @@ +#include "cmp.h" + +int +main (void) +{ + if (less_than (2, 1)) + { + return 1; + } + else + { + return 0; + } +} + +//# cmp.c +// +// /decl/ l+ ## 0 +// /if-cond/ l! ## dT- +// /if-then/ l- ## s- +// /if-else/ l+ ## 0 diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/test_t.c b/testsuite/tests/C/mcdc/CommaExpr/src/test_t.c new file mode 100644 index 000000000..6323605d1 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/test_t.c @@ -0,0 +1,21 @@ +#include "cmp.h" + +int +main (void) +{ + if (less_than (1, 2)) + { + return 0; + } + else + { + return 1; + } +} + +//# cmp.c +// +// /decl/ l+ ## 0 +// /if-cond/ l! ## dF- +// /if-then/ l+ ## 0 +// /if-else/ l- ## s- diff --git a/testsuite/tests/C/mcdc/CommaExpr/src/test_tf.c b/testsuite/tests/C/mcdc/CommaExpr/src/test_tf.c new file mode 100644 index 000000000..1cd4b58b3 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/src/test_tf.c @@ -0,0 +1,21 @@ +#include "cmp.h" + +int +main (void) +{ + if (!less_than (1, 2) || less_than (2, 1)) + { + return 1; + } + else + { + return 0; + } +} + +//# cmp.c +// +// /decl/ l+ ## 0 +// /if-cond/ l+ ## 0 +// /if-then/ l+ ## 0 +// /if-else/ l+ ## 0 diff --git a/testsuite/tests/C/mcdc/CommaExpr/test.py b/testsuite/tests/C/mcdc/CommaExpr/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/C/mcdc/CommaExpr/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c b/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c new file mode 100644 index 000000000..b72e8019e --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c @@ -0,0 +1,21 @@ + +int +fact (int n) +{ + if (n == 0) + { + return 1; + } + return n * fact (n - 1); +} + +int +main (void) +{ + return + /* GNATCOV_EXEMPT_ON "In statement"*/ + fact (0) == 1 + /* GNATCOV_EXEMPT_OFF)*/ + ? 0 + : 1; +} \ No newline at end of file diff --git a/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py b/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py new file mode 100644 index 000000000..8ae4ae796 --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py @@ -0,0 +1,37 @@ +""" +Check that gnatcov correctly rejects exemption markers intersecting SCOs. +""" + +# TODO: This may need to be moved to a Robustness chapter instead when +# proper qualification tests are written for C. + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.c"], srcdirs=[".."])), + extra_coverage_args=["--annotate=xcov"], + covlevel="stmt+mcdc", + mains=["main"], + trace_mode="src", + tolerate_instrument_messages="Exemption .* intersects" +) + +check_xcov_reports( + "*.xcov", + expected_cov={"main.c.xcov": {"+": {7, 15}, "!": {5, 17}, "-": {9}}}, + cwd="obj" +) + +thistest.fail_if_no_match( + what="Unexpected instrument output", + regexp=r"(warning: Exemption annotation at main\.c:\d+:\d+ intersects a" + r" coverage obligation \(.*\), ignoring it\n)+", + actual=contents_of("instrument.log")) + +thistest.result() diff --git a/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.c b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.c new file mode 100644 index 000000000..af887905c --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.c @@ -0,0 +1,35 @@ +#include "pkg.h" +#include + +#define NOT(A) !A + +// GNATCOV_EXEMPT_ON "whole function single line comment" // # exempt_at +bool // # exempt_at +andThen (bool a, bool b) // # exempt_at +{ // # exempt_at + return a && b; // # exempt_at +} // # exempt_at +// GNATCOV_EXEMPT_OFF // # exempt_at + +bool +orElse (bool a, bool b) +{ + // GNATCOV_EXEMPT_ON "if stmt" // # exempt_oe + if (a || b) // # exempt_oe_v1 + { // # exempt_oe + // GNATCOV_EXEMPT_OFF // # exempt_oe + return true; + } + else + { + return false; + } +} + +bool +negation (bool a) +{ + /* GNATCOV_EXEMPT_ON "single statement, multiline comment"*/ // # exempt_neg + return NOT (a); // # exempt_neg_v1 + /* GNATCOV_EXEMPT_OFF */ // # exempt_neg +} diff --git a/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.h b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.h new file mode 100644 index 000000000..419e178b8 --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.h @@ -0,0 +1,12 @@ +#ifndef PKG_H +#define PKG_H + +#include + +extern bool andThen (bool a, bool b); + +extern bool orElse (bool a, bool b); + +extern bool negation (bool a); + +#endif diff --git a/testsuite/tests/C/mcdc/Exemptions/Nominal/src/test_exemptions.c b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/test_exemptions.c new file mode 100644 index 000000000..10627e6ab --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/test_exemptions.c @@ -0,0 +1,20 @@ +#include "pkg.h" + +int +main (void) +{ + volatile bool x = orElse (false, true); + x = orElse (false, false); + x = andThen (true, true); + x = andThen (true, false); + x = andThen (false, false); + return 0; +} + +//# pkg.c +// +// /exempt_at/ l# ## x0 +// /exempt_oe/ l* ## x+ +// /exempt_oe_v1/ l= ## Xc! +// /exempt_neg/ l* ## x+ +// /exempt_neg_v1/ l= ## Xs- diff --git a/testsuite/tests/C/mcdc/Exemptions/Nominal/test.py b/testsuite/tests/C/mcdc/Exemptions/Nominal/test.py new file mode 100644 index 000000000..405e789c8 --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/Nominal/test.py @@ -0,0 +1,10 @@ +""" +Test proper support for exemptions in comments for C. +""" + + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C/mcdc/Exemptions/extra.opt b/testsuite/tests/C/mcdc/Exemptions/extra.opt new file mode 100644 index 000000000..279c887dd --- /dev/null +++ b/testsuite/tests/C/mcdc/Exemptions/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD exemptions not supported in bin traces for C \ No newline at end of file diff --git a/testsuite/tests/C/mcdc/Macros/pkg.h b/testsuite/tests/C/mcdc/Macros/pkg.h new file mode 100644 index 000000000..89015692e --- /dev/null +++ b/testsuite/tests/C/mcdc/Macros/pkg.h @@ -0,0 +1 @@ +#define PRINT_HW_PKG printf ("Hello world!\n"); diff --git a/testsuite/tests/C/mcdc/Macros/test.opt b/testsuite/tests/C/mcdc/Macros/test.opt new file mode 100644 index 000000000..b9f5a8268 --- /dev/null +++ b/testsuite/tests/C/mcdc/Macros/test.opt @@ -0,0 +1,3 @@ +bin-traces DEAD check SCO annotations emitted by the instrumenter +RTS_ZFP DEAD Uses printf, not available in light runtimes +!linux DEAD Check built-in macros, defined differently for each OS diff --git a/testsuite/tests/C/mcdc/Macros/test.py b/testsuite/tests/C/mcdc/Macros/test.py new file mode 100644 index 000000000..6627093d7 --- /dev/null +++ b/testsuite/tests/C/mcdc/Macros/test.py @@ -0,0 +1,34 @@ +""" +Check that we have the right annotations for SCOs that come from macro +expansion. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +Wdir("tmp_") + +# For simplicity, avoid commas in these arguments to avoid issues with the +# argument separator for --c-opts. +macro_args = [ + '-DCMDLINE_MACRO_STMT=printf ("Command-line macro");', + "-DCMDLINE_MACRO_DECL(x)=int x;", + "-DCMDLINE_MACRO_NO_VALUE(x)x", +] +copts_args = "--c-opts=" + ",".join(macro_args) +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], + mains=["test_macros.c"])), + covlevel="stmt+mcdc", + mains=["test_macros"], + extra_instr_args=[copts_args], + extra_coverage_args=["--annotate=xcov+"] +) + +thistest.fail_if_diff(os.path.join("..", "test_macros.c.xcov.expected"), + os.path.join("obj", "test_macros.c.xcov")) +thistest.result() diff --git a/testsuite/tests/C/mcdc/Macros/test_macros.c b/testsuite/tests/C/mcdc/Macros/test_macros.c new file mode 100644 index 000000000..9ad700592 --- /dev/null +++ b/testsuite/tests/C/mcdc/Macros/test_macros.c @@ -0,0 +1,47 @@ +#include "pkg.h" +#include + +#define PRINT_HW printf ("Hello world!\n"); +#define PRINT printf +#define HW "Hello world!\n" +#define PRINT_HW_PRINT_HW \ + PRINT_HW; \ + PRINT_HW +#define WRAPPER_PRINT_HW PRINT_HW +#define ID(x) x +#define AND(x, y) ID (x) && y +#define WRAP_AND(x, y) AND (x, y) +#define WRAP_CMDLINE_MACRO_STMT CMDLINE_MACRO_STMT + +void +macro_stmts () +{ + PRINT_HW_PKG; + PRINT_HW; + WRAPPER_PRINT_HW; + PRINT ("Hello world!\n"); + PRINT (HW); + PRINT_HW_PRINT_HW; + WRAP_CMDLINE_MACRO_STMT; + CMDLINE_MACRO_STMT; + CMDLINE_MACRO_DECL (a); + CMDLINE_MACRO_NO_VALUE (int b =); + // Test that coverage obligations coming from built-in macros are reported + // correctly. + __linux + 1; +} + +void +macro_decision_violations (int a, int b) +{ + if (WRAP_AND (ID (a), b)) + PRINT_HW; +} + +int +main () +{ + macro_decision_violations (1, 0); + macro_decision_violations (1, 1); + return 0; +} diff --git a/testsuite/tests/C/mcdc/Macros/test_macros.c.xcov.expected b/testsuite/tests/C/mcdc/Macros/test_macros.c.xcov.expected new file mode 100644 index 000000000..e95147f31 --- /dev/null +++ b/testsuite/tests/C/mcdc/Macros/test_macros.c.xcov.expected @@ -0,0 +1,99 @@ +25% of 16 lines covered +29% statement coverage (5 out of 17) +100% decision coverage (1 out of 1) +50% MC/DC coverage (1 out of 2) + +Coverage level: stmt+mcdc + 1 .: #include "pkg.h" + 2 .: #include + 3 .: + 4 .: #define PRINT_HW printf ("Hello world!\n"); + 5 .: #define PRINT printf + 6 .: #define HW "Hello world!\n" + 7 .: #define PRINT_HW_PRINT_HW \ + 8 .: PRINT_HW; \ + 9 .: PRINT_HW + 10 .: #define WRAPPER_PRINT_HW PRINT_HW + 11 .: #define ID(x) x + 12 .: #define AND(x, y) ID (x) && y + 13 .: #define WRAP_AND(x, y) AND (x, y) + 14 .: #define WRAP_CMDLINE_MACRO_STMT CMDLINE_MACRO_STMT + 15 .: + 16 .: void + 17 .: macro_stmts () + 18 .: { + 19 -: PRINT_HW_PKG; +statement "printf ("..." at 19:3 not executed + note: in definition of macro PRINT_HW_PKG at location pkg.h:1:22 + note: from expansion of macro PRINT_HW_PKG at location test_macros.c:19:3 + 20 -: PRINT_HW; +statement "printf ("..." at 20:3 not executed + note: in definition of macro PRINT_HW at location test_macros.c:4:18 + note: from expansion of macro PRINT_HW at location test_macros.c:20:3 + 21 -: WRAPPER_PRINT_HW; +statement "printf ("..." at 21:3 not executed + note: in definition of macro PRINT_HW at location test_macros.c:4:18 + note: from expansion of macro PRINT_HW at location test_macros.c:10:26 + note: from expansion of macro WRAPPER_PRINT_HW at location test_macros.c:21:3 + 22 -: PRINT ("Hello world!\n"); +statement "printf ("..." at 22:3 not executed + note: in definition of macro PRINT at location test_macros.c:5:15 + note: from expansion of macro PRINT at location test_macros.c:22:3 + 23 -: PRINT (HW); +statement "printf ("..." at 23:3 not executed + note: in definition of macro PRINT at location test_macros.c:5:15 + note: from expansion of macro PRINT at location test_macros.c:23:3 + 24 -: PRINT_HW_PRINT_HW; +statement "printf ("..." at 24:3 not executed + note: in definition of macro PRINT_HW at location test_macros.c:4:18 + note: from expansion of macro PRINT_HW at location test_macros.c:8:3 + note: from expansion of macro PRINT_HW_PRINT_HW at location test_macros.c:24:3 +statement "printf ("..." at 24:3 not executed + note: in definition of macro PRINT_HW at location test_macros.c:4:18 + note: from expansion of macro PRINT_HW at location test_macros.c:9:3 + note: from expansion of macro PRINT_HW_PRINT_HW at location test_macros.c:24:3 + 25 -: WRAP_CMDLINE_MACRO_STMT; +statement "printf ("..." at 25:3 not executed + note: in definition of macro CMDLINE_MACRO_STMT at location + note: from expansion of macro CMDLINE_MACRO_STMT at location test_macros.c:14:33 + note: from expansion of macro WRAP_CMDLINE_MACRO_STMT at location test_macros.c:25:3 + 26 -: CMDLINE_MACRO_STMT; +statement "printf ("..." at 26:3 not executed + note: in definition of macro CMDLINE_MACRO_STMT at location + note: from expansion of macro CMDLINE_MACRO_STMT at location test_macros.c:26:3 + 27 -: CMDLINE_MACRO_DECL (a); +statement "int a;" at 27:3 not executed + note: in definition of macro CMDLINE_MACRO_DECL at location + note: from expansion of macro CMDLINE_MACRO_DECL at location test_macros.c:27:3 + 28 -: CMDLINE_MACRO_NO_VALUE (int b =); +statement "int b = 1..." at 28:3 not executed + note: in definition of macro CMDLINE_MACRO_NO_VALUE at location + note: from expansion of macro CMDLINE_MACRO_NO_VALUE at location test_macros.c:28:3 + 29 .: // Test that coverage obligations coming from built-in macros are reported + 30 .: // correctly. + 31 -: __linux + 1; +statement "1 + 1" at 31:3 not executed + note: in definition of macro __linux at location + note: from expansion of macro __linux at location test_macros.c:31:3 + 32 .: } + 33 .: + 34 .: void + 35 .: macro_decision_violations (int a, int b) + 36 .: { + 37 !: if (WRAP_AND (ID (a), b)) +condition "a" at 37:7 has no independent influence pair, MC/DC not achieved + note: in definition of macro ID at location test_macros.c:11:15 + note: from expansion of macro ID at location test_macros.c:12:19 + note: from expansion of macro AND at location test_macros.c:13:24 + note: from expansion of macro WRAP_AND at location test_macros.c:37:7 + note: from expansion of macro ID at location test_macros.c:37:17 + 38 +: PRINT_HW; + 39 .: } + 40 .: + 41 .: int + 42 .: main () + 43 .: { + 44 +: macro_decision_violations (1, 0); + 45 +: macro_decision_violations (1, 1); + 46 +: return 0; + 47 .: } diff --git a/testsuite/tests/C/mcdc/include-current-dir/pkg.c b/testsuite/tests/C/mcdc/include-current-dir/pkg.c new file mode 100644 index 000000000..f939f7693 --- /dev/null +++ b/testsuite/tests/C/mcdc/include-current-dir/pkg.c @@ -0,0 +1,5 @@ +int +foo (int a, int b) +{ + return a && b; +} diff --git a/testsuite/tests/C/mcdc/include-current-dir/pkg.h b/testsuite/tests/C/mcdc/include-current-dir/pkg.h new file mode 100644 index 000000000..7c8a5c82e --- /dev/null +++ b/testsuite/tests/C/mcdc/include-current-dir/pkg.h @@ -0,0 +1,9 @@ +extern int foo (int a, int b); + +static int +bar (int a, int b) +{ + if (a || b) + return 1; + return 0; +} diff --git a/testsuite/tests/C/mcdc/include-current-dir/test.c b/testsuite/tests/C/mcdc/include-current-dir/test.c new file mode 100644 index 000000000..8fa741fed --- /dev/null +++ b/testsuite/tests/C/mcdc/include-current-dir/test.c @@ -0,0 +1,10 @@ +#include "pkg.h" + +int +main () +{ + bar (0, 1); + bar (0, 0); + int a = foo (0, 1); + return 0; +} diff --git a/testsuite/tests/C/mcdc/include-current-dir/test.py b/testsuite/tests/C/mcdc/include-current-dir/test.py new file mode 100644 index 000000000..7f547c0d0 --- /dev/null +++ b/testsuite/tests/C/mcdc/include-current-dir/test.py @@ -0,0 +1,39 @@ +""" +This test checks that coverage obligations in a header files are processed. It +also checks that running gnatcov instrument when the source files are in the +current directory works. gnatcov instrument used to ignore source files because +the sloc of nodes returned by libclang in that case is relative (./pkg.h +instead of /pkg.h). +""" + +import os.path + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import thistest, gprfor + + +wd = Wdir("tmp_") +for src in ("pkg.h", "pkg.c", "test.c"): + cp(os.path.join("..", src), src) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=['.'], mains=['test.c'])), + covlevel='stmt+mcdc', + mains=['test'], + extra_coverage_args=['--annotate=xcov', '--output-dir=xcov'], +) + +check_xcov_reports( + '*.xcov', + { + 'pkg.h.xcov': {'+': {7, 8}, '!': {6}}, + 'pkg.c.xcov': {'!': {4}}, + 'test.c.xcov': {'+': {6, 7, 8}} + }, + 'xcov') + +thistest.result() diff --git a/testsuite/tests/C/mcdc/misc/src/aligned.c b/testsuite/tests/C/mcdc/misc/src/aligned.c new file mode 100644 index 000000000..4cff388f7 --- /dev/null +++ b/testsuite/tests/C/mcdc/misc/src/aligned.c @@ -0,0 +1,6 @@ + +char +aligned (int x, int y, int factor) +{ + return !(x & (factor - 1)) && !(y & (factor - 1)); // # eval +} diff --git a/testsuite/tests/C/mcdc/misc/src/misc.ads b/testsuite/tests/C/mcdc/misc/src/misc.ads new file mode 100644 index 000000000..22b07e6da --- /dev/null +++ b/testsuite/tests/C/mcdc/misc/src/misc.ads @@ -0,0 +1,5 @@ +package Misc is + + function Aligned (X, Y, Factor : Integer) return Boolean; + pragma Import (C, Aligned, "aligned"); +end; diff --git a/testsuite/tests/C/mcdc/misc/src/test_aligned_x.adb b/testsuite/tests/C/mcdc/misc/src/test_aligned_x.adb new file mode 100644 index 000000000..0b8bc90cc --- /dev/null +++ b/testsuite/tests/C/mcdc/misc/src/test_aligned_x.adb @@ -0,0 +1,11 @@ +with Misc, Support; use Misc, Support; + +procedure Test_Aligned_X is +begin + Assert (Aligned (16, 24, 8)); + Assert (not Aligned (7, 24, 8)); +end; + +--# aligned.c +-- /eval/ l! ## c!:"!(y" + diff --git a/testsuite/tests/C/mcdc/misc/test.py b/testsuite/tests/C/mcdc/misc/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/C/mcdc/misc/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/C/stmt/NA28-015-default-return/calc.c b/testsuite/tests/C/stmt/NA28-015-default-return/calc.c new file mode 100644 index 000000000..e5e14845e --- /dev/null +++ b/testsuite/tests/C/stmt/NA28-015-default-return/calc.c @@ -0,0 +1,22 @@ +#include "process.h" +#include +#include + +void +usage () +{ + printf ("calc , print result of \n"); +} + +int +main (int argc, const char *argv[]) +{ + if (argc != 4) + { + usage (); + exit (1); + } + + process (argv); + return 0; +} diff --git a/testsuite/tests/C/stmt/NA28-015-default-return/process.c b/testsuite/tests/C/stmt/NA28-015-default-return/process.c new file mode 100644 index 000000000..eda0abf26 --- /dev/null +++ b/testsuite/tests/C/stmt/NA28-015-default-return/process.c @@ -0,0 +1,27 @@ +#include "process.h" +#include +#include + +void +process (const char *argv[]) +{ + int x = atoi (argv[1]), y = atoi (argv[2]); + char opcode = argv[3][0]; + + int result; + + switch (opcode) + { + case '*': + result = x * y; // # mult + break; // # mult + case '+': + result = x + y; // # plus + break; // # plus + default: + printf ("unsupported opcode %c\n", opcode); // # unsupp + return; // # unsupp + } + + printf ("%d %c %d = %d\n", x, opcode, y, result); // # result +} diff --git a/testsuite/tests/C/stmt/NA28-015-default-return/process.h b/testsuite/tests/C/stmt/NA28-015-default-return/process.h new file mode 100644 index 000000000..940dfaa0f --- /dev/null +++ b/testsuite/tests/C/stmt/NA28-015-default-return/process.h @@ -0,0 +1,6 @@ +#ifndef __PROCESS_H__ +#define __PROCESS_H__ + +extern void process (const char *argv[]); + +#endif diff --git a/testsuite/tests/C/stmt/NA28-015-default-return/test.opt b/testsuite/tests/C/stmt/NA28-015-default-return/test.opt new file mode 100644 index 000000000..6d0b18e7b --- /dev/null +++ b/testsuite/tests/C/stmt/NA28-015-default-return/test.opt @@ -0,0 +1 @@ +!x86-linux,!x86_64-linux DEAD test relies on passing command line arguments \ No newline at end of file diff --git a/testsuite/tests/C/stmt/NA28-015-default-return/test.py b/testsuite/tests/C/stmt/NA28-015-default-return/test.py new file mode 100644 index 000000000..3e9f92021 --- /dev/null +++ b/testsuite/tests/C/stmt/NA28-015-default-return/test.py @@ -0,0 +1,79 @@ +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import xcov, thistest +from SUITE.tutils import gprfor, srctracename_for, tracename_for + +import re + +Wdir('tmp_') + +# Point here is to exercise consolidation over distinct executions of the same +# program with different command line arguments. The SCOV circuitry isn't +# really suited for this so we're doing a rough approximation manually. + +# This also exercises a specific sequence of C constructs, with an explicit +# return in the default alternative of a switch case. + + +def run_trace_with_args(prefix, exec_args): + build_and_run( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], + mains=["calc.c"])), + covlevel="stmt", + mains=["calc"], + extra_coverage_args=[], + extra_run_args=["-o", f"{prefix}.trace"], + extra_instr_args=[f"--dump-filename-prefix={prefix}", + "--dump-filename-simple"], + register_failure=False, + exec_args=exec_args, + ) + + +def trycov(cases, xnocov): + """ + Consolidate the set of traces whose basenames are provided in CASES. Check + that we have '-' notes on lines designated by exprs in XNOCOV, and only + there. + """ + + fun_tracename = (srctracename_for if thistest.options.trace_mode == 'src' + else tracename_for) + + xcov('coverage --level=stmt --annotate=xcov' + ' -P gen.gpr %s' + % ' '.join(fun_tracename(c) for c in cases)) + + def check_mark_on(line): + m = re.search(string=line, pattern=r'^ *\d+ (?P.):') + if not m: + return + + note = m.group('note') + + m = re.search(string=line, pattern='// # (?P.*)') + mark = m.group('mark') if m else None + + thistest.fail_if(mark in xnocov and note != '-', + "missing expected '-' note on line:\n%s" % line) + + thistest.fail_if(note == '-' and mark not in xnocov, + "unexpected '-' note on line:\n %s" % line) + + print('checking cases=%s' % str(cases)) + with open('obj/process.c.xcov', 'r') as f: + for line in f: + check_mark_on(line=line.strip()) + + +run_trace_with_args("plus", ["2", "3", "+"]) +run_trace_with_args("mult", ["4", "5", "*"]) +run_trace_with_args("unsupp", ["4", "5", "#"]) + +trycov(cases=['mult', 'plus'], xnocov=['unsupp']) +trycov(cases=['plus'], xnocov=['mult', 'unsupp']) +trycov(cases=['mult'], xnocov=['plus', 'unsupp']) +trycov(cases=['mult', 'plus', 'unsupp'], xnocov=[]) + +thistest.result() diff --git a/testsuite/tests/Disassemblers/arm_be/symbolization.baseline b/testsuite/tests/Disassemblers/arm_be/symbolization.baseline new file mode 100644 index 000000000..cf9afd167 --- /dev/null +++ b/testsuite/tests/Disassemblers/arm_be/symbolization.baseline @@ -0,0 +1,8 @@ +Section .text: 00000000-00000013 +: +00000000 -: e0 80 00 00 add r0, r0, r0 +00000004 -: ea ff ff ff b 0x8 +00000008 -: e1 a0 f0 0e mov pc, lr +: +0000000c -: e3 a0 00 01 mov r0, #1 +00000010 -: eb ff ff fa bl 0x0 diff --git a/testsuite/tests/Disassemblers/arm_be/symbolization.s b/testsuite/tests/Disassemblers/arm_be/symbolization.s new file mode 100644 index 000000000..963e7de0c --- /dev/null +++ b/testsuite/tests/Disassemblers/arm_be/symbolization.s @@ -0,0 +1,16 @@ + .text + .align 0 + + .type f, %function +f: + add r0, r0, r0 + b local +local: + mov pc, lr + .size f, .-f + + .type foo, %function +foo: + mov r0, #1 + bl f + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/arm_le/symbolization.baseline b/testsuite/tests/Disassemblers/arm_le/symbolization.baseline new file mode 100644 index 000000000..905c3f196 --- /dev/null +++ b/testsuite/tests/Disassemblers/arm_le/symbolization.baseline @@ -0,0 +1,8 @@ +Section .text: 00000000-00000013 +: +00000000 -: 00 00 80 e0 add r0, r0, r0 +00000004 -: ff ff ff ea b 0x8 +00000008 -: 0e f0 a0 e1 mov pc, lr +: +0000000c -: 01 00 a0 e3 mov r0, #1 +00000010 -: fa ff ff eb bl 0x0 diff --git a/testsuite/tests/Disassemblers/arm_le/symbolization.s b/testsuite/tests/Disassemblers/arm_le/symbolization.s new file mode 100644 index 000000000..963e7de0c --- /dev/null +++ b/testsuite/tests/Disassemblers/arm_le/symbolization.s @@ -0,0 +1,16 @@ + .text + .align 0 + + .type f, %function +f: + add r0, r0, r0 + b local +local: + mov pc, lr + .size f, .-f + + .type foo, %function +foo: + mov r0, #1 + bl f + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/disaconv.py b/testsuite/tests/Disassemblers/disaconv.py new file mode 100644 index 000000000..755e2d961 --- /dev/null +++ b/testsuite/tests/Disassemblers/disaconv.py @@ -0,0 +1,75 @@ +#! /usr/bin/env python + +import argparse +import re +import sys + + +# Command-line parsing + +parser = argparse.ArgumentParser( + description=( + 'Convert a objdump/gnatcov disassembly dump to a simple format' + ) +) +parser.add_argument( + '-o', '--output', type=argparse.FileType('w'), default=sys.stdout, + dest='output' +) +parser.add_argument( + 'input', type=argparse.FileType('r'), nargs='?', default=sys.stdin, +) + + +# Internal data structures + +def section(match): + return 'Section' + + +def insn(match): + addr = int(match.group('addr'), 16) + return 'Insn: {:08x}'.format(addr) + + +# Input matching + +# These are the pattern generated by objdump: +OBJDUMP_SECTION = re.compile('^Disassembly of section (?P.+):$') +OBJDUMP_INSN = re.compile( + '^ *(?P[0-9a-f]+):\t[ 0-9a-f]+\t' + '(?P[^ ]*)' +) + +# And those ones are generated by gnatcov disassemble: +GNATCOV_SECTION = re.compile('^Section') +GNATCOV_INSN = re.compile( + '(?P[0-9a-f]+) -: (?: [0-9a-f]{2})+ {3,}' + '(?P[^ ]+)' +) + + +# Matching table: associate a pattern with an action. + +MATCHING_TABLE = ( + (OBJDUMP_SECTION, section), + (OBJDUMP_INSN, insn), + (GNATCOV_SECTION, section), + (GNATCOV_INSN, insn), +) + + +def disaconv(fin, fout): + # For each line in the input file, try to find a matching pattern and write + # the result of the associated action to the output file. + for line in fin: + for pattern, action in MATCHING_TABLE: + m = pattern.match(line) + if m: + fout.write(action(m)) + fout.write('\n') + + +if __name__ == '__main__': + args = parser.parse_args() + disaconv(args.input, args.output) diff --git a/testsuite/tests/Disassemblers/leon/symbolization.baseline b/testsuite/tests/Disassemblers/leon/symbolization.baseline new file mode 100644 index 000000000..2d06cef3f --- /dev/null +++ b/testsuite/tests/Disassemblers/leon/symbolization.baseline @@ -0,0 +1,10 @@ +Section .text: 00000000-0000001b +: +00000000 -: 9d e3 bf a0 save %sp, -96, %sp +00000004 -: 80 00 00 00 add %g0, %g0, %g0 +00000008 -: 10 80 00 01 b 0xc +0000000c -: 81 e8 00 00 restore +00000010 -: 81 c3 e0 08 retl +: +00000014 -: b0 10 00 00 mov %g0, %i0 +00000018 -: 06 bf ff fa bl 0x0 diff --git a/testsuite/tests/Disassemblers/leon/symbolization.s b/testsuite/tests/Disassemblers/leon/symbolization.s new file mode 100644 index 000000000..a5d7af26a --- /dev/null +++ b/testsuite/tests/Disassemblers/leon/symbolization.s @@ -0,0 +1,17 @@ + .text + + .type f, %function +f: + save %sp, -96, %sp + add %g0, %g0, %g0 + b local +local: + restore + jmp %o7+8 + .size f, .-f + + .type foo, %function +foo: + mov %g0, %i0 + bl f + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/lmp/symbolization.baseline b/testsuite/tests/Disassemblers/lmp/symbolization.baseline new file mode 100644 index 000000000..d840f9462 --- /dev/null +++ b/testsuite/tests/Disassemblers/lmp/symbolization.baseline @@ -0,0 +1,12 @@ +Section .text: 00000000-00000023 +: +00000000 -: 86 00 00 04 add.l r0,r0,r0 +00000004 -: ff 80 00 04 bra tr,r0,r0 +00000008 -: 00 00 00 00 nop +0000000c -: 7f 95 00 04 bra tr,r21,r0 +00000010 -: 00 00 00 00 nop +: +00000014 -: 84 aa 00 00 moviu r10,0x0000 +00000018 -: 84 aa 00 00 moviu r10,0x0000 +0000001c -: 7f 8a 54 04 bra tr,r10,r21 +00000020 -: 00 00 00 00 nop diff --git a/testsuite/tests/Disassemblers/lmp/symbolization.s b/testsuite/tests/Disassemblers/lmp/symbolization.s new file mode 100644 index 000000000..00d74dbb0 --- /dev/null +++ b/testsuite/tests/Disassemblers/lmp/symbolization.s @@ -0,0 +1,19 @@ + .text + + .type f, %function +f: + add.l r0,r0,r0 + bra tr,r0,r0 + nop +local: + bra tr,r21,r0 + nop + .size f, .-f + + .type foo, %function +foo: + moviu r10,%u f + moviu r10,%l f + bra tr,r10,r21 + nop + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/ppc_be/symbolization.baseline b/testsuite/tests/Disassemblers/ppc_be/symbolization.baseline new file mode 100644 index 000000000..6b1ef110e --- /dev/null +++ b/testsuite/tests/Disassemblers/ppc_be/symbolization.baseline @@ -0,0 +1,8 @@ +Section .text: 00000000-00000013 +: +00000000 -: 48 00 00 08 b 0x8 +00000004 -: 60 00 00 00 nop +00000008 -: 4e 80 00 20 blr +: +0000000c -: 4b ff ff f5 bl 0x0 +00000010 -: 60 00 00 00 nop diff --git a/testsuite/tests/Disassemblers/ppc_be/symbolization.s b/testsuite/tests/Disassemblers/ppc_be/symbolization.s new file mode 100644 index 000000000..7f65f2c54 --- /dev/null +++ b/testsuite/tests/Disassemblers/ppc_be/symbolization.s @@ -0,0 +1,15 @@ + .text + + .type f, %function +f: + b local + nop +local: + blr + .size f, .-f + + .type foo, %function +foo: + bl f + nop + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/ppc_le/symbolization.baseline b/testsuite/tests/Disassemblers/ppc_le/symbolization.baseline new file mode 100644 index 000000000..707bea161 --- /dev/null +++ b/testsuite/tests/Disassemblers/ppc_le/symbolization.baseline @@ -0,0 +1,8 @@ +Section .text: 00000000-00000013 +: +00000000 -: 08 00 00 48 b 0x8 +00000004 -: 00 00 00 60 nop +00000008 -: 20 00 80 4e blr +: +0000000c -: f5 ff ff 4b bl 0x0 +00000010 -: 00 00 00 60 nop diff --git a/testsuite/tests/Disassemblers/ppc_le/symbolization.s b/testsuite/tests/Disassemblers/ppc_le/symbolization.s new file mode 100644 index 000000000..7f65f2c54 --- /dev/null +++ b/testsuite/tests/Disassemblers/ppc_le/symbolization.s @@ -0,0 +1,15 @@ + .text + + .type f, %function +f: + b local + nop +local: + blr + .size f, .-f + + .type foo, %function +foo: + bl f + nop + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/test.py b/testsuite/tests/Disassemblers/test.py new file mode 100644 index 000000000..87fe4da14 --- /dev/null +++ b/testsuite/tests/Disassemblers/test.py @@ -0,0 +1,134 @@ +""" +Test the integration of libopcodes in gnatcov's disassembling machinery. + +gnatcov delegates object code disassembling to binutils's libopcodes, so it +makes no sense here to test for all possible instructions. What we rather check +is whether the integration of libopcodes in gnatcov works as expected. + +To do so, we compare the output of `gnatcov disassemble` against baselines for +assembly files corresponding to the current target architecture, in both +endianity when applicable. Testcase should demonstrate that generally +libopcodes is properly used, and that symbolization works as expected. +""" + +from collections import OrderedDict +import os.path + +from e3.diff import diff + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor, xcov + + +# Mapping: architecture discriminant -> tests directory. If one discriminant +# is a key for this mapping, the associated directory names are used to get +# testcases. + +class Testcase(object): + def __init__(self, test_dir, discriminant, cargs=(), asm_spec=''): + self.test_dir = test_dir + self.discriminant = discriminant + self.cargs = cargs + self.asm_spec = asm_spec + + self.spec_file = None + + def prepare(self): + if self.asm_spec: + self.spec_file = os.path.abspath('{}.spec'.format(self.test_dir)) + with open(self.spec_file, 'w') as f: + f.write('*asm:\n') + f.write('+ {}\n'.format(self.asm_spec)) + + self.cargs = (list(self.cargs) + + ['-specs={}'.format(self.spec_file)]) + + +testcases = OrderedDict() + +for tc in ( + # Avoid running this on Windows platforms as the assembler will fail + # processing the test material, there. + Testcase('x86', 'x86-linux'), + Testcase('x86_64', 'x86_64-linux'), + + Testcase('lmp', 'visium-elf', ['-mcpu=gr6']), + + # Use GCC's spec files, in particular the "asm" rule to force the + # assemblers' endianity. This short-circuits the -m{little,big}-endian flag + # we get from the testuite-wide project configuration file. + Testcase('arm_le', 'arm', ['-mcpu=cortex-r4f'], '-EL'), + Testcase('arm_be', 'arm', ['-mcpu=cortex-r4f'], '-EB'), + Testcase('thumb_le', 'arm', ['-mthumb'], '-EL'), + Testcase('thumb_be', 'arm', ['-mthumb'], '-EB'), + + Testcase('ppc_be', 'ppc-elf', ['-mbig-endian']), + Testcase('ppc_le', 'ppc-elf', ['-mlittle-endian']), + + Testcase('leon', 'leon3-elf'), +): + testcases[tc.test_dir] = tc + + +def with_ext(name, ext): + """Return the given name suffixed by an extension.""" + return '{}{}{}'.format(name, os.path.extsep, ext) + + +def is_asm(filename): + """Return if the given filename is an assembly source.""" + return os.path.splitext(filename)[-1] == '.s' + + +tmp = Wdir('tmp_') + +# Run tests in each test directory that matches architecture discriminants. +for test_dir, tc in testcases.items(): + if tc.discriminant not in thistest.options.tags: + continue + tc.prepare() + + path = os.path.join(tmp.homedir, test_dir) + tmp_sub = Wdir(test_dir) + + testcases = list(sorted(filter(is_asm, os.listdir(path)))) + + # Prepare object file from assembly sources. + project = gprfor( + testcases, srcdirs=path, + main_cargs=tc.cargs + ) + gprbuild(project, gargs=['-c']) + + # And then iterate on each testcase to run it. + for testcase in testcases: + + compile_unit = os.path.splitext(testcase)[0] + objfile = os.path.join('obj', with_ext(compile_unit, 'o')) + + baseline = os.path.join( + path, with_ext(compile_unit, 'baseline') + ) + disa_gnatcov = with_ext(compile_unit, 'disassembly') + + # Disassemble it using gnatcov. + xcov(['disassemble', objfile], out=disa_gnatcov) + + # And finally compare it to the baseline. + disaconv_diff = diff(baseline, disa_gnatcov) + thistest.log( + 'Comparing the disassembly of {}/{}...'.format(test_dir, testcase) + ) + if disaconv_diff: + thistest.log(disaconv_diff) + else: + thistest.log('No difference') + thistest.fail_if( + disaconv_diff, + '{}/{}: disassemblies are not the same'.format(test_dir, testcase) + ) + + tmp_sub.to_homedir() + +thistest.result() diff --git a/testsuite/tests/Disassemblers/thumb_be/symbolization.baseline b/testsuite/tests/Disassemblers/thumb_be/symbolization.baseline new file mode 100644 index 000000000..df9701cc1 --- /dev/null +++ b/testsuite/tests/Disassemblers/thumb_be/symbolization.baseline @@ -0,0 +1,8 @@ +Section .text: 00000000-0000000b +: +00000000 -: 30 03 adds r0, #3 +00000002 -: e7 ff b.n 0x4 +00000004 -: 46 f7 mov pc, lr +: +00000006 -: 20 01 movs r0, #1 +00000008 -: f7 ff ff fa bl 0x0 diff --git a/testsuite/tests/Disassemblers/thumb_be/symbolization.s b/testsuite/tests/Disassemblers/thumb_be/symbolization.s new file mode 100644 index 000000000..ff0dad4a9 --- /dev/null +++ b/testsuite/tests/Disassemblers/thumb_be/symbolization.s @@ -0,0 +1,19 @@ + .text + .arch armv4t + .syntax unified + .thumb + .align 0 + + .type f, %function +f: + adds r0, #3 + b local +local: + mov pc, lr + .size f, .-f + + .type foo, %function +foo: + movs r0, #1 + bl f + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/thumb_le/symbolization.baseline b/testsuite/tests/Disassemblers/thumb_le/symbolization.baseline new file mode 100644 index 000000000..884766d65 --- /dev/null +++ b/testsuite/tests/Disassemblers/thumb_le/symbolization.baseline @@ -0,0 +1,8 @@ +Section .text: 00000000-0000000b +: +00000000 -: 03 30 adds r0, #3 +00000002 -: ff e7 b.n 0x4 +00000004 -: f7 46 mov pc, lr +: +00000006 -: 01 20 movs r0, #1 +00000008 -: ff f7 fa ff bl 0x0 diff --git a/testsuite/tests/Disassemblers/thumb_le/symbolization.s b/testsuite/tests/Disassemblers/thumb_le/symbolization.s new file mode 100644 index 000000000..ff0dad4a9 --- /dev/null +++ b/testsuite/tests/Disassemblers/thumb_le/symbolization.s @@ -0,0 +1,19 @@ + .text + .arch armv4t + .syntax unified + .thumb + .align 0 + + .type f, %function +f: + adds r0, #3 + b local +local: + mov pc, lr + .size f, .-f + + .type foo, %function +foo: + movs r0, #1 + bl f + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/x86/symbolization.baseline b/testsuite/tests/Disassemblers/x86/symbolization.baseline new file mode 100644 index 000000000..12a8393d7 --- /dev/null +++ b/testsuite/tests/Disassemblers/x86/symbolization.baseline @@ -0,0 +1,10 @@ +Section .text: 00000000-00000011 +: +00000000 -: 83 c0 02 add $0x2,%eax +00000003 -: eb 01 jmp 0x6 +00000005 -: 90 nop +00000006 -: c3 ret +: +00000007 -: b8 01 00 00 00 mov $0x1,%eax +0000000c -: e8 ef ff ff ff call 0x0 +00000011 -: c3 ret diff --git a/testsuite/tests/Disassemblers/x86/symbolization.s b/testsuite/tests/Disassemblers/x86/symbolization.s new file mode 100644 index 000000000..b595b820b --- /dev/null +++ b/testsuite/tests/Disassemblers/x86/symbolization.s @@ -0,0 +1,17 @@ + .text + + .type f, %function +f: + add $2, %eax + jmp local + nop +local: + ret + .size f, .-f + + .type foo, %function +foo: + mov $1, %eax + call f + ret + .size foo, .-foo diff --git a/testsuite/tests/Disassemblers/x86_64/symbolization.baseline b/testsuite/tests/Disassemblers/x86_64/symbolization.baseline new file mode 100644 index 000000000..bb4ea5a2f --- /dev/null +++ b/testsuite/tests/Disassemblers/x86_64/symbolization.baseline @@ -0,0 +1,10 @@ +Section .text: 0000000000000000-0000000000000011 +: +0000000000000000 -: 83 c0 02 add $0x2,%eax +0000000000000003 -: eb 01 jmp 0x6 +0000000000000005 -: 90 nop +0000000000000006 -: c3 ret +: +0000000000000007 -: b8 01 00 00 00 mov $0x1,%eax +000000000000000c -: e8 ef ff ff ff call 0x0 +0000000000000011 -: c3 ret diff --git a/testsuite/tests/Disassemblers/x86_64/symbolization.s b/testsuite/tests/Disassemblers/x86_64/symbolization.s new file mode 100644 index 000000000..b595b820b --- /dev/null +++ b/testsuite/tests/Disassemblers/x86_64/symbolization.s @@ -0,0 +1,17 @@ + .text + + .type f, %function +f: + add $2, %eax + jmp local + nop +local: + ret + .size f, .-f + + .type foo, %function +foo: + mov $1, %eax + call f + ret + .size foo, .-foo diff --git a/testsuite/tests/FullRuntime/Barrier/src/buffer.adb b/testsuite/tests/FullRuntime/Barrier/src/buffer.adb new file mode 100644 index 000000000..94d929115 --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/src/buffer.adb @@ -0,0 +1,31 @@ +with GNAT.IO; use GNAT.IO; + +package body Buffer is + + protected body Buffer is + + entry Push (V : Integer; Tell : Boolean) + when not Has_Value -- # push_guard + is + begin + if Tell then -- # push_test_tell + Put_Line ("push " & Integer'Image (V)); -- # push_tell + end if; + Value := V; -- # push_do + Has_Value := True; -- # push_do + end Push; + + entry Pop (V : out Integer; Tell : Boolean) + when Has_Value -- # pop_guard + is + begin + if Tell then -- # pop_test_tell + Put_Line ("pop " & Integer'Image (V)); -- # pop_tell + end if; + V := Value; -- # pop_do + Has_Value := False; -- # pop_do + end Pop; + + end Buffer; + +end Buffer; diff --git a/testsuite/tests/FullRuntime/Barrier/src/buffer.ads b/testsuite/tests/FullRuntime/Barrier/src/buffer.ads new file mode 100644 index 000000000..ab1d4edc6 --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/src/buffer.ads @@ -0,0 +1,18 @@ +package Buffer is + + protected type Buffer is + + -- Synchronisation buffer for two threads. + + entry Push (V : Integer; Tell : Boolean); + -- Hang until the buffer is free and fill it with V + + entry Pop (V : out Integer; Tell : Boolean); + -- Hang until the buffer is filled, set V and make the buffer empty + + private + Value : Integer; -- # component_decl + Has_Value : Boolean := False; -- # component_decl + end; + +end Buffer; diff --git a/testsuite/tests/FullRuntime/Barrier/src/test_pop.adb b/testsuite/tests/FullRuntime/Barrier/src/test_pop.adb new file mode 100644 index 000000000..73cc0b288 --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/src/test_pop.adb @@ -0,0 +1,38 @@ +with Buffer; + +procedure Test_Pop is + Buf : Buffer.Buffer; + V : Integer; +begin + select + Buf.Pop (V, False); + else + null; + end select; +end Test_Pop; + +--# buffer.adb + +--%cov: --level=stmt +-- =/push_guard/ l. ## 0 +-- =/push_do/ l- ## s- +-- =/push_test_tell/ l- ## s- +-- =/push_tell/ l- ## s- +-- =/pop_guard/ l. ## 0 +-- =/pop_do/ l- ## s- +-- =/pop_tell/ l- ## s- +-- =/pop_test_tell/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/push_guard/ l. ## 0 +-- =/push_do/ l- ## s- +-- =/push_test_tell/ l- ## s- +-- =/push_tell/ l- ## s- +-- =/pop_guard/ l. ## 0 +-- =/pop_do/ l- ## s- +-- =/pop_tell/ l- ## s- +-- =/pop_test_tell/ l- ## s- + +--# buffer.ads + +-- =/component_decl/ l+ ## 0 \ No newline at end of file diff --git a/testsuite/tests/FullRuntime/Barrier/src/test_pop_push_pop.adb b/testsuite/tests/FullRuntime/Barrier/src/test_pop_push_pop.adb new file mode 100644 index 000000000..c77cc03bc --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/src/test_pop_push_pop.adb @@ -0,0 +1,45 @@ +with Buffer; + +procedure Test_Pop_Push_Pop is + Buf : Buffer.Buffer; + V : Integer; +begin + select + Buf.Pop (V, False); + else + null; + end select; + V := 1; + Buf.Push (V, True); + V := 2; + Buf.Pop (V, False); + if V /= 1 then + raise Program_Error; + end if; +end Test_Pop_Push_Pop; + +--# buffer.adb + +--%cov: --level=stmt +-- =/push_guard/ l. ## 0 +-- =/push_do/ l+ ## 0 +-- =/push_test_tell/ l+ ## 0 +-- =/push_tell/ l+ ## 0 +-- =/pop_guard/ l. ## 0 +-- =/pop_do/ l+ ## 0 +-- =/pop_tell/ l- ## s- +-- =/pop_test_tell/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/push_guard/ l. ## 0 +-- =/push_do/ l+ ## 0 +-- =/push_test_tell/ l! ## dF- +-- =/push_tell/ l+ ## 0 +-- =/pop_guard/ l. ## 0 +-- =/pop_do/ l+ ## 0 +-- =/pop_tell/ l- ## s- +-- =/pop_test_tell/ l! ## dT- + +--# buffer.ads + +-- =/component_decl/ l+ ## 0 diff --git a/testsuite/tests/FullRuntime/Barrier/src/test_push.adb b/testsuite/tests/FullRuntime/Barrier/src/test_push.adb new file mode 100644 index 000000000..3c119ddc4 --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/src/test_push.adb @@ -0,0 +1,32 @@ +with Buffer; + +procedure Test_Push is + Buf : Buffer.Buffer; +begin + Buf.Push (1, False); +end Test_Push; + +--# buffer.adb + +--%cov: --level=stmt +-- =/push_guard/ l. ## 0 +-- =/push_do/ l+ ## 0 +-- =/push_test_tell/ l+ ## 0 +-- =/push_tell/ l- ## s- +-- =/pop_guard/ l. ## 0 +-- =/pop_do/ l- ## s- +-- =/pop_tell/ l- ## s- +-- =/pop_test_tell/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/push_guard/ l. ## 0 +-- =/push_do/ l+ ## 0 +-- =/push_test_tell/ l! ## dT- +-- =/push_tell/ l- ## s- +-- =/pop_guard/ l. ## 0 +-- =/pop_do/ l- ## s- +-- =/pop_test_tell/ l- ## s- + +--# buffer.ads + +-- =/component_decl/ l+ ## 0 \ No newline at end of file diff --git a/testsuite/tests/FullRuntime/Barrier/src/test_push_push_pop.adb b/testsuite/tests/FullRuntime/Barrier/src/test_push_push_pop.adb new file mode 100644 index 000000000..b18c85b9d --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/src/test_push_push_pop.adb @@ -0,0 +1,45 @@ +with Buffer; + +procedure Test_Push_Push_Pop is + Buf : Buffer.Buffer; + V : Integer; +begin + V := 1; + Buf.Push (V, False); + select + Buf.Push (V, False); + else + null; + end select; + V := 2; + Buf.Pop (V, True); + if V /= 1 then + raise Program_Error; + end if; +end Test_Push_Push_Pop; + +--# buffer.adb + +--%cov: --level=stmt +-- =/push_guard/ l. ## 0 +-- =/push_do/ l+ ## 0 +-- =/push_test_tell/ l+ ## 0 +-- =/push_tell/ l- ## s- +-- =/pop_guard/ l. ## 0 +-- =/pop_do/ l+ ## 0 +-- =/pop_tell/ l+ ## 0 +-- =/pop_test_tell/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/push_guard/ l. ## 0 +-- =/push_do/ l+ ## 0 +-- =/push_test_tell/ l! ## dT- +-- =/push_tell/ l- ## s- +-- =/pop_guard/ l. ## 0 +-- =/pop_do/ l+ ## 0 +-- =/pop_tell/ l+ ## 0 +-- =/pop_test_tell/ l! ## dF- + +--# buffer.ads + +-- =/component_decl/ l+ ## 0 diff --git a/testsuite/tests/FullRuntime/Barrier/test.opt b/testsuite/tests/FullRuntime/Barrier/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/Barrier/test.py b/testsuite/tests/FullRuntime/Barrier/test.py new file mode 100644 index 000000000..5541cb162 --- /dev/null +++ b/testsuite/tests/FullRuntime/Barrier/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in (CAT.stmt, CAT.decision): + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/src/ops.adb new file mode 100644 index 000000000..a95f55b77 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/src/ops.adb @@ -0,0 +1,56 @@ +with Ada.Real_Time; use Ada.Real_Time; +with Ada.Text_IO; use Ada.Text_IO; + +package body Ops is + + task type Opmaster is + entry Start (O : Opkind); + entry Compute (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + Op : Opkind; + begin + accept Start (O : Opkind) do -- # compute + Op := O; -- # compute + end Start; + + select -- # compute + accept Compute (A, B : Boolean; Result : out Boolean) do -- # compute + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + + end; + or + delay To_Duration (Minutes (1)); + end select; + end; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + T : Opmaster; + Result : Boolean; + begin + select + T.Compute (A, B, Result); -- # compute + or + delay until Clock + Seconds (1); -- # compute + Put_Line ("T.Compute timed out"); -- # sometimes-timeout + end select; + + T.Start (Op); -- # compute + + select + T.Compute (A, B, Result); -- # compute + or + delay until Clock + Minutes (1); + Put_Line ("T.Compute timed out"); -- # never-timeout + end select; + + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/src/ops.adb new file mode 100644 index 000000000..305057c62 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/src/ops.adb @@ -0,0 +1,56 @@ +with Ada.Real_Time; use Ada.Real_Time; +with Ada.Text_IO; use Ada.Text_IO; + +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + task type Opmaster is + entry Start (O : Opkind); + entry Compute (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + Op : Opkind; + begin + accept Start (O : Opkind) do -- # compute + Op := O; -- # compute + end Start; + + select -- # compute + accept Compute (A, B : Boolean; Result : out Boolean) do -- # compute + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + + end; + or + delay To_Duration (Minutes (1)); + end select; + end; + + T : Opmaster; + Result : Boolean; + begin + select + T.Compute (A, B, Result); -- # compute + or + delay until Clock + Seconds (1); -- # compute + Put_Line ("T.Compute timed out"); -- # sometimes-timeout + end select; + + T.Start (Op); -- # compute + + select + T.Compute (A, B, Result); -- # compute + or + delay until Clock + Minutes (1); + Put_Line ("T.Compute timed out"); -- # never-timeout + end select; + + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/src/ops.adb new file mode 100644 index 000000000..71d6f02b2 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/src/ops.adb @@ -0,0 +1,41 @@ + +package body Ops is + + task type Opmaster is + entry Stop; + entry Compute_And (A, B : Boolean; Result : out Boolean); + entry Compute_Or (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + select -- # compute + accept Stop; -- # kill + else + + select -- # compute + accept Compute_And (A, B : Boolean; Result : out Boolean) do -- # do_and + Result := A and then B; -- # do_and + end; + or + accept Compute_Or (A, B : Boolean; Result : out Boolean) do -- # do_or + Result := A or else B; -- # do_or + end; + end select; + end select; + end; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + T : Opmaster; + Result : Boolean; + begin + case Op is -- # compute + when Op_And => T.Compute_And (A, B, Result); -- # do_and + when Op_Or => T.Compute_Or (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.opt new file mode 100644 index 000000000..d2a350ccc --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.opt @@ -0,0 +1,2 @@ +ALL DEAD +RTS_FULL diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/src/ops.adb new file mode 100644 index 000000000..8d0912570 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/src/ops.adb @@ -0,0 +1,40 @@ +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + task type Opmaster is + entry Stop; + entry Compute_And (A, B : Boolean; Result : out Boolean); + entry Compute_Or (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + select -- # compute + accept Stop; -- # kill + else + + select -- # compute + accept Compute_And (A, B : Boolean; Result : out Boolean) do -- # do_and + Result := A and then B; -- # do_and + end; + or + accept Compute_Or (A, B : Boolean; Result : out Boolean) do -- # do_or + Result := A or else B; -- # do_or + end; + end select; + end select; + end; + + T : Opmaster; + Result : Boolean; + begin + case Op is -- # compute + when Op_And => T.Compute_And (A, B, Result); -- # do_and + when Op_Or => T.Compute_Or (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.opt new file mode 100644 index 000000000..d2a350ccc --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.opt @@ -0,0 +1,2 @@ +ALL DEAD +RTS_FULL diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/src/ops.adb new file mode 100644 index 000000000..a28dd017e --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/src/ops.adb @@ -0,0 +1,35 @@ + +package body Ops is + + task type Opmaster is + entry Compute_And (A, B : Boolean; Result : out Boolean); + entry Compute_Or (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + select -- # compute + accept Compute_And (A, B : Boolean; Result : out Boolean) do -- # do_and + Result := A and then B; -- # do_and + end; + or + accept Compute_Or (A, B : Boolean; Result : out Boolean) do -- # do_or + Result := A or else B; -- # do_or + end; + end select; + end; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + T : Opmaster; + Result : Boolean; + begin + case Op is -- # compute + when Op_And => T.Compute_And (A, B, Result); -- # do_and + when Op_Or => T.Compute_Or (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.opt new file mode 100644 index 000000000..d2a350ccc --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.opt @@ -0,0 +1,2 @@ +ALL DEAD +RTS_FULL diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/src/ops.adb new file mode 100644 index 000000000..815d9eb5d --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/src/ops.adb @@ -0,0 +1,35 @@ + +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + task type Opmaster is + entry Compute_And (A, B : Boolean; Result : out Boolean); + entry Compute_Or (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + select -- # compute + accept Compute_And (A, B : Boolean; Result : out Boolean) do -- # do_and + Result := A and then B; -- # do_and + end; + or + accept Compute_Or (A, B : Boolean; Result : out Boolean) do -- # do_or + Result := A or else B; -- # do_or + end; + end select; + end; + + T : Opmaster; + Result : Boolean; + begin + case Op is -- # compute + when Op_And => T.Compute_And (A, B, Result); -- # do_and + when Op_Or => T.Compute_Or (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.opt new file mode 100644 index 000000000..d2a350ccc --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.opt @@ -0,0 +1,2 @@ +ALL DEAD +RTS_FULL diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/src/ops.adb new file mode 100644 index 000000000..7dc68bda4 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/src/ops.adb @@ -0,0 +1,39 @@ + +package body Ops is + + task type Opmaster (Op : Opkind) is + entry Compute (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + loop + select -- # compute + accept Compute (A, B : Boolean; Result : out Boolean) do -- # compute + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end; + or + terminate; + end select; + end loop; + end; + + + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + T_And : Opmaster (Op_And); + T_Or : Opmaster (Op_Or); + Result : Boolean; + begin + case Op is -- # compute + when Op_And => T_And.Compute (A, B, Result); -- # do_and + when Op_Or => T_Or.Compute (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/src/ops.adb new file mode 100644 index 000000000..b0fd8df7e --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/src/ops.adb @@ -0,0 +1,39 @@ +with Ada.Real_Time; use Ada.Real_Time; + +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + task type Opmaster (Op : Opkind) is + entry Compute (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + loop + select -- # compute + accept Compute (A, B : Boolean; Result : out Boolean) do -- # compute + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end; + or + terminate; + end select; + end loop; + end; + + T_And : Opmaster (Op_And); + T_Or : Opmaster (Op_Or); + Result : Boolean; + begin + case Op is -- # compute + when Op_And => T_And.Compute (A, B, Result); -- # do_and + when Op_Or => T_Or.Compute (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/src/ops.adb new file mode 100644 index 000000000..683fbfab3 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/src/ops.adb @@ -0,0 +1,45 @@ + +package body Ops is + + task type Opmaster is + entry Push_Opkind (O : Opkind); + entry Compute_And (A, B : Boolean; Result : out Boolean); + entry Compute_Or (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + Op : Opkind; + begin + accept Push_Opkind (O : Opkind) do -- # compute + Op := O; -- # compute + end Push_Opkind; + + select -- # compute + when Op = Op_And => + accept Compute_And (A, B : Boolean; Result : out Boolean) do -- # do_and + Result := A and then B; -- # do_and + end; + or + when Op = Op_Or => + accept Compute_Or (A, B : Boolean; Result : out Boolean) do -- # do_or + Result := A or else B; -- # do_or + end; + end select; + end; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + T : Opmaster; + Result : Boolean; + begin + T.Push_Opkind (Op); -- # compute + + case Op is -- # compute + when Op_And => T.Compute_And (A, B, Result); -- # do_and + when Op_Or => T.Compute_Or (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.opt new file mode 100644 index 000000000..006a31f27 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/src/ops.adb new file mode 100644 index 000000000..5b12ef802 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/src/ops.adb @@ -0,0 +1,45 @@ + +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + task type Opmaster is + entry Push_Opkind (O : Opkind); + entry Compute_And (A, B : Boolean; Result : out Boolean); + entry Compute_Or (A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + Op : Opkind; + begin + accept Push_Opkind (O : Opkind) do -- # compute + Op := O; -- # compute + end Push_Opkind; + + select -- # compute + when Op = Op_And => + accept Compute_And (A, B : Boolean; Result : out Boolean) do -- # do_and + Result := A and then B; -- # do_and + end; + or + when Op = Op_Or => + accept Compute_Or (A, B : Boolean; Result : out Boolean) do -- # do_or + Result := A or else B; -- # do_or + end; + end select; + end; + + T : Opmaster; + Result : Boolean; + begin + T.Push_Opkind (Op); -- # compute + + case Op is -- # compute + when Op_And => T.Compute_And (A, B, Result); -- # do_and + when Op_Or => T.Compute_Or (A, B, Result); -- # do_or + end case; + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.opt new file mode 100644 index 000000000..006a31f27 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.py b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/src/ops.adb new file mode 100644 index 000000000..f822b4f59 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/src/ops.adb @@ -0,0 +1,30 @@ + +package body Ops is + + task type Opmaster is + entry Compute (Op : Opkind; A, B : Boolean; Result : out Boolean); + end Opmaster; + + task body Opmaster is + begin + accept Compute + (Op : Opkind; A, B : Boolean; Result : out Boolean) + do + case Op is + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end; + end; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + T : Opmaster; + Result : Boolean; + begin + T.Compute (Op, A, B, Result); -- # compute + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.py b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/src/ops.adb new file mode 100644 index 000000000..845780d63 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/src/ops.adb @@ -0,0 +1,27 @@ +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + task T is + entry Compute (Op : Opkind; A, B : Boolean; Result : out Boolean); + end; + + task body T is + begin + accept Compute + (Op : Opkind; A, B : Boolean; Result : out Boolean) + do + case Op is + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end; + end; + + Result : Boolean; + begin + T.Compute (Op, A, B, Result); -- # compute + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.py b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/Entries/src/ops.ads b/testsuite/tests/FullRuntime/stmt/Entries/src/ops.ads new file mode 100644 index 000000000..cbbc1b55b --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/src/ops.ads @@ -0,0 +1,4 @@ +package Ops is + type Opkind is (Op_And, Op_Or); + function Compute (Op : Opkind; A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/FullRuntime/stmt/Entries/src/test_0.adb b/testsuite/tests/FullRuntime/stmt/Entries/src/test_0.adb new file mode 100644 index 000000000..7c764a7c1 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/src/test_0.adb @@ -0,0 +1,15 @@ +with Support, Ops; use Support, Ops; + +procedure Test_0 is +begin + Assert (True); +end; + + +--# ops.adb +-- /do_and/ l- ## s- +-- /do_or/ l- ## s- +-- /compute/ l- ## s- +-- /kill/ l- ## s- +-- /sometimes-timeout/ l- ## s- +-- /never-timeout/ l- ## s- diff --git a/testsuite/tests/FullRuntime/stmt/Entries/src/test_ops_and_tt.adb b/testsuite/tests/FullRuntime/stmt/Entries/src/test_ops_and_tt.adb new file mode 100644 index 000000000..2b264422e --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/Entries/src/test_ops_and_tt.adb @@ -0,0 +1,15 @@ +with Support, Ops; use Support, Ops; + +procedure Test_Ops_And_TT is +begin + Assert (Ops.Compute (Op_And, True, True) = True); +end; + + +--# ops.adb +-- /do_and/ l+ ## 0 +-- /do_or/ l- ## s- +-- /compute/ l+ ## 0 +-- /kill/ l- ## s- +-- /sometimes-timeout/ l+ ## 0 +-- /never-timeout/ l- ## s- diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/src/ops.adb new file mode 100644 index 000000000..c49c2310b --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/src/ops.adb @@ -0,0 +1,56 @@ + +package body Ops is + + protected type Opmaster is + entry Take_And; + entry Take_Or; + procedure Release; + procedure Compute (A, B : Boolean; Result : out Boolean); + + private + Op : Opkind; -- # decl + Free : Boolean := True; -- # decl + Count : Natural := 0; -- # decl + end Opmaster; + + protected body Opmaster is + entry Take_And when Op = Op_And or else Count = 0 is + begin + Count := Count + 1; -- # do_and + Op := Op_And; -- # do_and + end Take_And; + + entry Take_Or when Op = Op_Or or else Count = 0 is + begin + Count := Count + 1; -- # do_or + Op := Op_Or; -- # do_or + end Take_Or; + + procedure Release is + begin + Count := Count - 1; -- # compute + end Release; + + procedure Compute (A, B : Boolean; Result : out Boolean) is + begin + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end Compute; + end Opmaster; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + PO : Opmaster; -- # compute + Result : Boolean; + begin + case Op is -- # compute + when Op_And => PO.Take_And; -- # do_and + when Op_Or => PO.Take_Or; -- # do_or + end case; + PO.Compute (A, B, Result); -- # compute + PO.Release; + return Result; -- # compute + end; + +end; diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.py b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/src/ops.adb new file mode 100644 index 000000000..8035786c9 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/src/ops.adb @@ -0,0 +1,58 @@ + +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + protected type Opmaster is + entry Take_And; + entry Take_Or; + procedure Release; + procedure Compute (A, B : Boolean; Result : out Boolean); + + private + Op : Opkind; -- # decl + Free : Boolean := True; -- # decl + Count : Natural := 0; -- # decl + end Opmaster; + + protected body Opmaster is + entry Take_And when Op = Op_And or else Count = 0 is + begin + Count := Count + 1; -- # do_and + Op := Op_And; -- # do_and + end Take_And; + + entry Take_Or when Op = Op_Or or else Count = 0 is + begin + Count := Count + 1; -- # do_or + Op := Op_Or; -- # do_or + end Take_Or; + + procedure Release is + begin + Count := Count - 1; -- # compute + end Release; + + procedure Compute (A, B : Boolean; Result : out Boolean) is + begin + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end Compute; + end Opmaster; + + PO : Opmaster; -- # compute + Result : Boolean; + begin + case Op is -- # compute + when Op_And => PO.Take_And; -- # do_and + when Op_Or => PO.Take_Or; -- # do_or + end case; + PO.Compute (A, B, Result); -- # compute + PO.Release; + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.opt b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.py b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/src/ops.adb new file mode 100644 index 000000000..d8b9020ff --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/src/ops.adb @@ -0,0 +1,37 @@ + +package body Ops is + + protected type Opmaster is + procedure Set_Op (O : Opkind); + procedure Compute (A, B : Boolean; Result : out Boolean); + + private + Op : Opkind; -- # decl + end Opmaster; + + protected body Opmaster is + procedure Set_Op (O : Opkind) is + begin + Op := O; -- # compute + end Set_Op; + + procedure Compute (A, B : Boolean; Result : out Boolean) is + begin + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end Compute; + end Opmaster; + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + PO : Opmaster; + Result : Boolean; + begin + PO.Set_Op (Op); -- # compute + PO.Compute (A, B, Result); -- # compute + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.py b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/src/ops.adb new file mode 100644 index 000000000..41aecf5ab --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/src/ops.adb @@ -0,0 +1,38 @@ + +package body Ops is + + function Compute (Op : Opkind; A, B : Boolean) return Boolean is + + protected type Opmaster is + procedure Set_Op (O : Opkind); + procedure Compute (A, B : Boolean; Result : out Boolean); + + private + Op : Opkind; -- # decl + end Opmaster; + + protected body Opmaster is + procedure Set_Op (O : Opkind) is + begin + Op := O; -- # compute + end Set_Op; + + procedure Compute (A, B : Boolean; Result : out Boolean) is + begin + case Op is -- # compute + when Op_And => Result := A and then B; -- # do_and + when Op_Or => Result := A or else B; -- # do_or + end case; + end Compute; + end Opmaster; + + PO : Opmaster; + Result : Boolean; + begin + PO.Set_Op (Op); -- # compute + PO.Compute (A, B, Result); -- # compute + return Result; -- # compute + end; + +end; + diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.opt b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.py b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/ops.ads b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/ops.ads new file mode 100644 index 000000000..cbbc1b55b --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/ops.ads @@ -0,0 +1,4 @@ +package Ops is + type Opkind is (Op_And, Op_Or); + function Compute (Op : Opkind; A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_0.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_0.adb new file mode 100644 index 000000000..a684509e3 --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_0.adb @@ -0,0 +1,13 @@ +with Support, Ops; use Support, Ops; + +procedure Test_0 is +begin + Assert (True); +end; + + +--# ops.adb +-- /do_and/ l- ## s- +-- /do_or/ l- ## s- +-- /compute/ l- ## s- +-- /decl/ l+ ## 0 diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_ops_and_tt.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_ops_and_tt.adb new file mode 100644 index 000000000..ab7f704af --- /dev/null +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/src/test_ops_and_tt.adb @@ -0,0 +1,13 @@ +with Support, Ops; use Support, Ops; + +procedure Test_Ops_And_TT is +begin + Assert (Ops.Compute (Op_And, True, True) = True); +end; + + +--# ops.adb +-- /do_and/ l+ ## 0 +-- /do_or/ l- ## s- +-- /compute/ l+ ## 0 +-- /decl/ l+ ## 0 diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/check_g.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/check_g.adb new file mode 100644 index 000000000..bb514d75b --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/check_g.adb @@ -0,0 +1,10 @@ +package body Check_G is + procedure Test (Value : T) is + begin + if Low > Value or else High < Value then -- # test-out + Out_Of_Range_Count := Out_Of_Range_Count + 1; -- # out-range + else + In_Range_Count := In_Range_Count + 1; -- # in-range + end if; + end Test; +end Check_G; diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/check_g.ads b/testsuite/tests/Generics/Mode_Variants_MCDC/src/check_g.ads new file mode 100644 index 000000000..6c18d8129 --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/check_g.ads @@ -0,0 +1,10 @@ +generic + type T is new Float; + Low, High : T; +package Check_G is + procedure Test (Value : T); + pragma Inline (Test); + + In_Range_Count : Natural := 0; + Out_Of_Range_Count : Natural := 0; +end Check_G; diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.adb new file mode 100644 index 000000000..7bb9a328d --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.adb @@ -0,0 +1,13 @@ +package body Sensors is + + procedure Test (Value : Float; Unit : Temp_Unit) is + begin + if Unit = C then -- # check-test-c + N_Tests_C := N_Tests_C + 1; -- # check-do-c + RC.Test (Temp_C (Value)); -- # check-do-c + else + N_Tests_F := N_Tests_F + 1; -- # check-do-f + RF.Test (Temp_F (Value)); -- # check-do-f + end if; + end Test; +end Sensors; diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.ads b/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.ads new file mode 100644 index 000000000..ca588cbfc --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.ads @@ -0,0 +1,15 @@ +with Check_G; + +package Sensors is + type Temp_C is new Float range -273.15 .. Float'Last; + package RC is new Check_G (Temp_C, 0.0, 100.0); -- # i:RC + + type Temp_F is new Float range -459.67 .. Float'Last; + package RF is new Check_G (Temp_F, 32.0, 212.0);-- # i:RF + + type Temp_Unit is (C, F); + + procedure Test (Value : Float; Unit : Temp_Unit); + + N_Tests_C, N_Tests_F : Natural := 0; +end Sensors; diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cbfn.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cbfn.adb new file mode 100644 index 000000000..157c2fa77 --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cbfn.adb @@ -0,0 +1,54 @@ +with Sensors, Support; use Sensors, Support; + +-- CBFN : Invoking Both in and out of range for unit "C". None for unit "F". + +procedure Test_CBFN is +begin + -- C in range (!low !high => Out-False) + + Sensors.Test (37.0, C); + + -- C out of range (!low, high => Out-True) + + Sensors.Test (200.0, C); + + Assert (Sensors.N_Tests_C = 2); + Assert (Sensors.N_Tests_F = 0); + + Assert (RC.In_Range_Count = 1); + Assert (RC.Out_Of_Range_Count = 1); + Assert (RF.In_Range_Count = 0); + Assert (RF.Out_Of_Range_Count = 0); + +end Test_CBFN; + +--# sensors.adb +-- /check-test-c/ s=>l+, dmu=>l! ## s=>0, dmu=>dF- +-- /check-do-c/ l+ ## 0 +-- /check-do-f/ l- ## s- + +-- %cov: -S instance +-- Not a generic body, so no possible instance tag. + +-- %cov: -S routine +-- =/check-test-c/ s=>l+, dmu=>l! ## s=>0, dmu=>dF-@(sensors__test) +-- =/check-do-f/ l- ## s-@(sensors__test) + +--# sensors.ads +-- No expectation for this unit. Reference is needed here, still, to +-- get visibility on generic instantiations in this source. + +--# check_g.adb +-- /test-out/ ds=>l+, mu=>l! ## c!:"Low" +-- /in-range/ l+ ## 0 +-- /out-range/ l+ ## 0 + +-- %cov: -S instance +-- =/test-out/ l! ## s-@(i:RF), c!:"Low"@(i:RC) +-- =/in-range/ l! ## s-@(i:RF) +-- =/out-range/ l! ## s-@(i:RF) + +-- %cov: -S routine %cargs: !-gnatn +-- =/test-out/ l! ## s-@(sensors__rf__test), c!:"Low"@(sensors__rc__test) +-- =/in-range/ l! ## s-@(sensors__rf__test) +-- =/out-range/ l! ## s-@(sensors__rf__test) diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifn.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifn.adb new file mode 100644 index 000000000..a6be1950f --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifn.adb @@ -0,0 +1,49 @@ +with Support, Sensors; use Support, Sensors; + +procedure Test_CIFN is +begin + -- C in range + + Sensors.Test (37.0, C); + + Assert (Sensors.N_Tests_C = 1); + Assert (Sensors.N_Tests_F = 0); + + Assert (RC.In_Range_Count = 1); + Assert (RC.Out_Of_Range_Count = 0); + Assert (RF.In_Range_Count = 0); + Assert (RF.Out_Of_Range_Count = 0); +end Test_CIFN; + +--# sensors.adb +-- /check-test-c/ s=>l+, dmu=>l! ## s=>0, dmu=>dF- +-- /check-do-c/ l+ ## 0 +-- /check-do-f/ l- ## s- + +-- %cov: -S instance +-- Not a generic body, so no possible instance tag. + +-- %cov: -S routine +-- =/check-test-c/ s=>l+, dmu=>l! ## s=>0, dmu=>dF-@(sensors__test) +-- =/check-do-f/ l- ## s-@(sensors__test) + +--# sensors.ads +-- No expectation for this unit. Reference is needed here, still, to +-- get visibility on generic instantiations in this source. + +--# check_g.adb +-- /test-out/ s=>l+, dmu=>l! ## s=>0, dmu=>dT- +-- /in-range/ l+ ## 0 +-- /out-range/ l- ## s- + +-- %cov: -S instance +-- =/test-out/ l! ## s-@(i:RF), dT-@(i:RC) +-- =/in-range/ l! ## s-@(i:RF) +-- =/out-range/ l- ## s-@(i:RF), s-@(i:RC) + +-- %cov: -S routine %cargs: !-gnatn +-- =/test-out/ l! ## s-@(sensors__rf__test), dT-@(sensors__rc__test) +-- =/in-range/ l! ## s-@(sensors__rf__test) +-- =/out-range/ l- ## s-@(sensors__rf__test), s-@(sensors__rc__test) + + diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifo.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifo.adb new file mode 100644 index 000000000..079eef813 --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifo.adb @@ -0,0 +1,55 @@ +with Sensors, Support; use Sensors, Support; + +procedure Test_CIFO is +begin + -- C in range + + Sensors.Test (37.0, C); + + -- F out of range + + Sensors.Test (0.0, F); + + Assert (Sensors.N_Tests_C = 1); + Assert (Sensors.N_Tests_F = 1); + + Assert (RC.In_Range_Count = 1); + Assert (RC.Out_Of_Range_Count = 0); + Assert (RF.In_Range_Count = 0); + Assert (RF.Out_Of_Range_Count = 1); + +end Test_CIFO; + +--# sensors.adb +-- /check-test-c/ l+ ## 0 +-- /check-do-c/ l+ ## 0 +-- /check-do-f/ l+ ## 0 + +-- %cov: -S instance +-- Not a generic body, so no possible instance tag. + +-- %cov: -S routine +-- =/check-test-c/ l+ ## 0 +-- =/check-do-f/ l+ ## 0 + +--# sensors.ads +-- No expectation for this unit. Reference is needed here, still, to +-- get visibility on generic instantiations in this source. + +--# check_g.adb +-- defaults, for instances conslidated: +-- /test-out/ l+, mu=>l! ## c!:"High" +-- /in-range/ l+ ## 0 +-- /out-range/ l+ ## 0 + +-- %cov: -S instance +-- =/test-out/ s=>l+, dmu=>l! ## dT-@(i:RC), dF-@(i:RF) +-- =/in-range/ l! ## s-@(i:RF) +-- =/out-range/ l! ## s-@(i:RC) + +-- %cov: -S routine %cargs: !-gnatn +-- =/test-out/ s=>l+, dmu=>l! ## dT-@(sensors__rc__test), dF-@(sensors__rf__test) +-- =/in-range/ l! ## s-@(sensors__rf__test) +-- =/out-range/ l! ## s-@(sensors__rc__test) + +-- %cov: -S routine %cargs: -gnatn %cancel: diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfn.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfn.adb new file mode 100644 index 000000000..704413886 --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfn.adb @@ -0,0 +1,37 @@ +with Sensors; use Sensors; +procedure Test_CNFN is +begin + null; +end Test_CNFN; + +--# sensors.adb +-- /check-test-c/ l- ## s- +-- /check-do-c/ l- ## s- +-- /check-do-f/ l- ## s- + +-- %cov: -S instance +-- Not a generic body, so no possible instance tag. + +-- %cov: -S routine +-- =/check-test-c/ l- ## s-@(sensors__test) +-- =/check-do-c/ l- ## s-@(sensors__test) +-- =/check-do-f/ l- ## s-@(sensors__test) + +--# sensors.ads +-- No expectation for this unit. Reference is needed here, still, to +-- get visibility on generic instantiations in this source. + +--# check_g.adb +-- /test-out/ l- ## s- +-- /in-range/ l- ## s- +-- /out-range/ l- ## s- + +-- %cov: -S instance +-- =/test-out/ l- ## s-@(i:RF), s-@(i:RC) +-- =/in-range/ l- ## s-@(i:RF), s-@(i:RC) +-- =/out-range/ l- ## s-@(i:RF), s-@(i:RC) + +-- %cov: -S routine %cargs: !-gnatn +-- =/test-out/ l- ## s-@(sensors__rf__test), s-@(sensors__rc__test) +-- =/in-range/ l- ## s-@(sensors__rf__test), s-@(sensors__rc__test) +-- =/out-range/ l- ## s-@(sensors__rc__test), s-@(sensors__rf__test) diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfo.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfo.adb new file mode 100644 index 000000000..7ceaa83fd --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfo.adb @@ -0,0 +1,40 @@ +with Sensors; use Sensors; +procedure Test_CNFO is +begin + -- F out of range + + Sensors.Test (0.0, F); +end Test_CNFO; + +--# sensors.adb +-- /check-test-c/ s=>l+, dmu=>l! ## s=>0, dmu=>dT- +-- /check-do-c/ l- ## s- +-- /check-do-f/ l+ ## 0 + +-- %cov: -S instance +-- Not a generic body, so no possible instance tag. + +-- %cov: -S routine +-- =/check-test-c/ s=>l+, dmu=>l! ## s=>0, dmu=>dT-@(sensors__test) +-- =/check-do-c/ l- ## s-@(sensors__test) + +--# sensors.ads +-- No expectation for this unit. Reference is needed here, still, to +-- get visibility on generic instantiations in this source. + +--# check_g.adb +-- /test-out/ s=>l+, dmu=>l! ## s=>0, dmu=>dF- +-- /in-range/ l- ## s- +-- /out-range/ l+ ## 0 + +-- %cov: -S instance +-- =/test-out/ l! ## s-@(i:RC), dF-@(i:RF) +-- =/in-range/ l- ## s-@(i:RF), s-@(i:RC) +-- =/out-range/ l! ## s-@(i:RC) + +-- %cov: -S routine %cargs: !-gnatn +-- =/test-out/ l! ## s-@(sensors__rc__test), dF-@(sensors__rf__test) +-- =/in-range/ l- ## s-@(sensors__rf__test), s-@(sensors__rc__test) +-- =/out-range/ l! ## s-@(sensors__rc__test) + + diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/tc.txt b/testsuite/tests/Generics/Mode_Variants_MCDC/tc.txt new file mode 100644 index 000000000..bf1644cb4 --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/tc.txt @@ -0,0 +1,100 @@ +We consider a general program construction like +one sketched below: + + generic + package G is + procedure Test is + begin -- slocs below designated as + if For_I1 then -- "test_in_g" + stmt_1_here; -- "stmt1_in_g" + else + stmt_2_here; -- "stmt2_in_g" + end if; + end; + end; + + package Sensors is + package I1 is new G (For_I1); + package I2 is new G (For_I2); + + procedure Dispatch; + end; + + package body Sensors is + procedure Dispatch is + begin -- slocs below designated as + if Do_I1 then -- "test_in_dispatch" + I1.Test; -- "call1_in_dispatch" + else + I2.Test; -- "call2_in_dispatch" + end if; + end; + + -- The generated code for this body includes the code for + -- the generic instances, as two low level routines: + -- + -- sensors__i1__test and sensors__i2__test. + + end; + +For -S routine, special care needs to be observed regarding inlining. + +WITHOUT inlining, we have machine code like: + + sensors__i1__test: ## slocs referenced by machine instructions + if for_i1: -> test_in_g + insns for stmt_1 -> stmt1_in_g + else: + insns for stmt_2 -> stmt2_in_g + + sensors__i2__test: + if for_i1: -> test_in_g + insns for stmt_1 -> stmt1_in_g + else: + insns for stmt_2 -> stmt2_in_g + + sensors_dispatch + test i1: -> test_in_dispatch + call sensors_i1_test -> call1_in_dispatch + else: + call sensors_i2_test -> call2_in_dispatch + +WITH inlining, the same except for: + + sensors_dispatch + test i1: -> test_in_dispatch + insns for stmt_1 -> stmt1_in_g + insns for stmt_2 -> stmt2_in_g + [insns for arg setup] -> call1_in_dispatch + else: + insns for stmt_1 -> stmt1_in_g + insns for stmt_2 -> stmt2_in_g + [insns for arg setup] -> call2_in_dispatch + +Whether instructions for the call statements and for other parts of the +inlined-instanciated code remain in each branch depends on the generic source +code structure and on how much optimization is performed. In general, the call +and the pieces corresponding to the other instances might for example entirely +disappear when the call arguments are constant. In this particular testcase, +the generic source code is structured to make sure that insns for both cases +remain in each inlined copy. + +Note that in addition to having references to "g" slocs from +"sensors__dispatch", if all the calls are inlined, no code from the original +instance subpgrograms is executed at all any more. + +In expectations, we distinguish four different cases: + +-- /stmt1_in_g/ ... (No separation tag, cflags irrelevant) + +-- %cov: -S instance +-- =/stmt1_in_g/ ... (Separation on instance, cflags irrelevant) + +-- %cov: -S routine %cargs: -O1, -gnatn +-- =/stmt1_in_g/ ... (Separation on routine name, with inlining) + +-- %cov: -S routine %cargs: !-gnatn +-- =/stmt1_in_g/ ... (Separation on routine name, without inlining) + +CB - testing for "C" temp unit, Both in range and out of range + diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/test.opt b/testsuite/tests/Generics/Mode_Variants_MCDC/test.opt new file mode 100644 index 000000000..c6c004f52 --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD testing per-instance analysis of generics, implemented post 7.0.3 +src-traces XFAIL S628-011: src-traces and per-instance coverage of generics +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/test.py b/testsuite/tests/Generics/Mode_Variants_MCDC/test.py new file mode 100644 index 000000000..e6e2b281b --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/test.py @@ -0,0 +1,27 @@ +""" +This is a complement to the existing tests for generics in the Qualif part of +the testsuite. These are grouped in the stmt coverage part and focus on the +distinction between the default mode and -S instance, assuming that the +combination circuits are orthogonal to the criteria. + +Here we mean to test -S routine as well, and take the opportunity to test with +a different criterion while we're at it. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + + +tc = TestCase(category=CAT.mcdc) + +tc.run() +tc.run(covcontrol=CovControl(covoptions="-S instance"), + subdirhint="r_") + +# -S routine is intractable with inlining +if '-gnatn' not in thistest.suite_cargs_for('Ada'): + tc.run(covcontrol=CovControl(covoptions="-S routine"), + subdirhint="r_") + +thistest.result() diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/src/test_v5_reset.adb b/testsuite/tests/Generics/Mode_Variants_STMT/src/test_v5_reset.adb new file mode 100644 index 000000000..119a9f614 --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_STMT/src/test_v5_reset.adb @@ -0,0 +1,30 @@ +with V5; use V5; + +procedure Test_V5_Reset is + V : V5.Vector; +begin + V5.Apply (Op=>Reset, V=>V); +end; + +--# vectors.adb +-- /apply_op/ l+ ## 0 +-- /apply_reset/ l+ ## 0 +-- /iterate/ l+ ## 0 +-- /do_reset/ l+ ## 0 + +-- /do_bump/ l- ## s- +-- /apply_bump/ l- ## s- + +-- %cov: -S instance +-- =/do_bump/ l- ## s-@(i:V5) +-- =/apply_bump/ l- ## s-@(i:V5) + +-- %cov: -S routine +-- =/apply_bump/ l- ## s-@(v5__apply) +-- =/do_bump/ l- ## s-@(v5__do_bump) + +-- -S instance needs visibility on ALIs where +-- instances of interest are + +--# v5.ads + diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/src/v5.ads b/testsuite/tests/Generics/Mode_Variants_STMT/src/v5.ads new file mode 100644 index 000000000..2b8368830 --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_STMT/src/v5.ads @@ -0,0 +1,3 @@ +with Vectors; +package V5 is new Vectors (Size => 5); -- # i:V5 + diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.adb b/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.adb new file mode 100644 index 000000000..b7bc017be --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.adb @@ -0,0 +1,32 @@ +package body Vectors is + + function Do_Reset (I : Integer) return Integer is + begin + return 0; -- # do_reset + end; + + function Do_Bump (I : Integer) return Integer is + begin + return I + 1; -- # do_bump + end; + + type Operator is access function (X : Integer) return Integer; + + procedure Iterate_On (V : in out Vector; Op : Operator) is + begin + for I in V'Range loop -- # iterate + V(I) := Op (V (I)); -- # iterate + end loop; + end; + + procedure Apply (Op : Opkind; V : in out Vector) is + begin + case Op is -- # apply_op + when Reset => Iterate_On (V, Do_Reset'Access); -- # apply_reset + when Bump => Iterate_On (V, Do_Bump'Access); -- # apply_bump + end case; + end; + +end; + + diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.ads b/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.ads new file mode 100644 index 000000000..e15dbdb5a --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.ads @@ -0,0 +1,10 @@ +generic + Size : Natural; +package Vectors is + + type Vector is array (1 .. Size) of Integer; + + type Opkind is (Reset, Bump); + + procedure Apply (Op : Opkind; V : in out Vector); +end; diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/test.opt b/testsuite/tests/Generics/Mode_Variants_STMT/test.opt new file mode 100644 index 000000000..ebe705ffc --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_STMT/test.opt @@ -0,0 +1 @@ +src-traces XFAIL S628-011: src-traces and per-instance coverage of generics diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/test.py b/testsuite/tests/Generics/Mode_Variants_STMT/test.py new file mode 100644 index 000000000..c4a65c292 --- /dev/null +++ b/testsuite/tests/Generics/Mode_Variants_STMT/test.py @@ -0,0 +1,18 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + + +tc = TestCase(category=CAT.stmt) + +tc.run() + +tc.run(covcontrol=CovControl(covoptions="-S instance"), + subdirhint="i_") + +# -S routine is intractable with inlining +if '-gnatn' not in thistest.suite_cargs_for('Ada'): + tc.run(covcontrol=CovControl(covoptions="-S routine"), + subdirhint="r_") + +thistest.result() diff --git a/testsuite/tests/HA16-013_cleanups/src/assert.adb b/testsuite/tests/HA16-013_cleanups/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/HA16-013_cleanups/src/p1.adb b/testsuite/tests/HA16-013_cleanups/src/p1.adb new file mode 100644 index 000000000..5c5de3729 --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/src/p1.adb @@ -0,0 +1,8 @@ +with Vars; +procedure P1 is + S : string (1 .. Vars.N); + pragma Volatile (S); +begin + Vars.Raise_PE; -- # call_raise + Vars.Post_Raise; -- # post_raise +end; diff --git a/testsuite/tests/HA16-013_cleanups/src/p2.adb b/testsuite/tests/HA16-013_cleanups/src/p2.adb new file mode 100644 index 000000000..d4476b909 --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/src/p2.adb @@ -0,0 +1,11 @@ +with Vars; +procedure P2 is +begin + declare + S : string (1 .. Vars.N); + pragma Volatile (S); + begin + Vars.Raise_PE; -- # call_raise + Vars.Post_Raise; -- # post_raise + end; +end; diff --git a/testsuite/tests/HA16-013_cleanups/src/test_blobs.adb b/testsuite/tests/HA16-013_cleanups/src/test_blobs.adb new file mode 100644 index 000000000..69e06e514 --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/src/test_blobs.adb @@ -0,0 +1,23 @@ +with Vars, P1, P2, Assert; + +procedure Test_Blobs is +begin + begin + P1; + Assert (Vars.N_Post_Raise = 0); + exception + when Program_Error => null; + end; + + begin + P2; + Assert (Vars.N_Post_Raise = 0); + exception + when Program_Error => null; + end; + +end; + +--# p1.adb p2.adb vars.adb +-- /call_raise/ l+ ## 0 +-- /post_raise/ l- ## s- diff --git a/testsuite/tests/HA16-013_cleanups/src/vars.adb b/testsuite/tests/HA16-013_cleanups/src/vars.adb new file mode 100644 index 000000000..a6a0d5ff5 --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/src/vars.adb @@ -0,0 +1,11 @@ +package body Vars is + procedure Raise_PE is + begin + raise Program_Error; -- # call_raise + end; + + procedure Post_Raise is + begin + N_Post_Raise := N_Post_Raise + 1; -- # post_raise + end; +end; diff --git a/testsuite/tests/HA16-013_cleanups/src/vars.ads b/testsuite/tests/HA16-013_cleanups/src/vars.ads new file mode 100644 index 000000000..4e5c13b64 --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/src/vars.ads @@ -0,0 +1,9 @@ +package Vars is + + N : Integer := 12; -- to be used for VLA sizing + + procedure Raise_PE; + + procedure Post_Raise; + N_Post_Raise : Integer := 0; +end; diff --git a/testsuite/tests/HA16-013_cleanups/test.opt b/testsuite/tests/HA16-013_cleanups/test.opt new file mode 100644 index 000000000..72097dd49 --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/test.opt @@ -0,0 +1 @@ +!RTS_RAVENSCAR,!RTS_FULL DEAD test on exception propagation cleanups, zfp-irrelevant \ No newline at end of file diff --git a/testsuite/tests/HA16-013_cleanups/test.py b/testsuite/tests/HA16-013_cleanups/test.py new file mode 100644 index 000000000..3a558099a --- /dev/null +++ b/testsuite/tests/HA16-013_cleanups/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(category=None).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.opt b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.opt new file mode 100644 index 000000000..878ab70b6 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.opt @@ -0,0 +1 @@ +CARGS_O1 DEAD already testing with both -O0 and -O1 diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.py new file mode 100644 index 000000000..ca1c4c6bc --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.py @@ -0,0 +1,24 @@ +""" +Check that gnatcov tries and fails to consolidate two "f" symbols, both with +debug information and from the same compilation unit. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + + +# Test expectations +test_drivers = {'test_1': {'not.c': ['-g', '-O0']}, + 'test_2': {'not.c': ['-g', '-O1']}} +coverage_expectations = { + # The two not.c:f() are compiled with different levels of optimization. In + # object coverage, gnatcov is supposed to fail: there is no coverage + # expectation. + 'f': {'-': 0, '!': 0, '+': 0}, +} + +tc = TestCase(test_drivers, coverage_expectations, + extra_sourcedirs=['../../../src']) +thistest.fail_if(tc.run(register_failure=False), + '"gnatcov coverage" was supposed to fail, but it did not') +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_2.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test_2.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test.py new file mode 100644 index 000000000..3bac5bc5d --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test.py @@ -0,0 +1,25 @@ +""" +Check that "f" symbols, both with debug information but from different +compilation units, are not consolidated. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + + +# Test expectations. All compile units have debug symbols. +switches = ['-O0', '-g'] +test_drivers = {'test_1': {'not.c': switches, 'fact.c': switches}, + 'test_2': {'not.c': switches, 'fact.c': switches}} +coverage_expectations = { + # - In test_1, not.c:f() is partially covered + # - In test_2, fact.c:f() is fully covered + # + # There is no consolidation, so there will be one partially covered + # routine and one fully covered one. + 'f': {'-': 0, '!': 1, '+': 1}, +} + +TestCase(test_drivers, coverage_expectations, + extra_sourcedirs=['../../../../src']).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_2.c new file mode 100644 index 000000000..6043eafd3 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test_2.c @@ -0,0 +1,8 @@ +#include "fact.h" + +int +main (void) +{ + compute_fact (2); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test.py new file mode 100644 index 000000000..99a8aff83 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test.py @@ -0,0 +1,22 @@ +""" +Check that "f" symbols, both with debug information and from the same +compilation unit, are consolidated. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + +switches = ['-O0', '-g'] + +# Test expectations +test_drivers = {'test_1': {'not.c': switches}, + 'test_2': {'not.c': switches}} +coverage_expectations = { + # Both not.c:f() are partially covered (each one covers a complementary + # part), so there is one fully covered routine after consolidation. + 'f': {'-': 0, '!': 0, '+': 1}, +} + +TestCase(test_drivers, coverage_expectations, + extra_sourcedirs=['../../../../src']).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_2.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test_2.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/target.txt b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/target.txt new file mode 100644 index 000000000..5a7a8f08f --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/target.txt @@ -0,0 +1 @@ +Test the requirement: consolidates two symbols if and only if they have the same compilation unit. diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test.py new file mode 100644 index 000000000..86c13c0f4 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test.py @@ -0,0 +1,33 @@ +""" +Check that "f" symbols, one with (in "test_1.c") and the other without debug +information (in "test_2.c") are not consolidated whereas they are in the same +compile unit. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + + +# We are trying to consolidate the traces of these test drivers. Each test +# driver has its own project, since it can use different compilation options +# for test controllers: +test_drivers = {'test_1': {'not.c': ['-g', '-O0']}, + 'test_2': {'not.c': ['-g', '-O0']}, + 'test_3': {'not.c': ['-g0', '-O0']}} +# Here, the "not.c" compile unit has debug info except in one test driver (the +# last one). + +coverage_expectations = { + # - In test_1, not.c:f() is half-covered + # - The other half is covered in test_2 + # - Some part is covered in test_3 + # + # test_1 and test_2 are consolidated, so there must be one f() that is + # fully covered. One other is partially covered for test_3 that do not + # consolidate. + 'f': {'-': 0, '!': 1, '+': 1}, +} + +TestCase(test_drivers, coverage_expectations, + extra_sourcedirs=['../../../../src']).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_2.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_2.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_3.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_3.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test_3.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test.py new file mode 100644 index 000000000..527b71093 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test.py @@ -0,0 +1,26 @@ +""" +Check that "f" symbols, one with (in "test_1.c") and the other without debug +information (in "test_2.c") are not consolidated whereas they are in the same +compile unit. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + + +# We are trying to consolidate the traces of these test drivers. Each test +# driver has its own project, since it can use different compilation options +# for test controllers: +test_drivers = {'test_1': {'not.c': ['-g0', '-O0']}, + 'test_2': {'not.c': ['-g', '-O0']}} +# Here, the "not.c" compile unit has debug info only in one test driver. + +coverage_expectations = { + # Both not.c:f() are partially covered (each one covers a complementary + # part, so they would be fully covered if consolidated). + 'f': {'-': 0, '!': 2, '+': 0}, +} + +TestCase(test_drivers, coverage_expectations, + extra_sourcedirs=['../../../../src']).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_2.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test_2.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test.py new file mode 100644 index 000000000..39d0a3b2f --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test.py @@ -0,0 +1,26 @@ +""" +Check that "f" symbols, both without debug information, in "test_1.c" and +"test_2.c" are not consolidated (they are not in the same compile unit, +anyway). +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + + +# We are trying to consolidate the traces of these test drivers. Each test +# driver has its own project, since it can use different compilation options +# for test controllers: +test_drivers = {'test_1': {'not.c': ['-g0', '-O0']}, + 'test_2': {'fact.c': ['-g0', '-O0']}} +# Here, no compile unit has specific compilation flag: no one has debug info. + +coverage_expectations = { + # not.c:f() is fully covered + # fact.c:f() is partially covered + 'f': {'-': 0, '!': 1, '+': 1}, +} + +TestCase(test_drivers, coverage_expectations, + extra_sourcedirs=['../../../../src']).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_1.c new file mode 100644 index 000000000..8ec4a4109 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_1.c @@ -0,0 +1,9 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_2.c new file mode 100644 index 000000000..c4963c184 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test_2.c @@ -0,0 +1,8 @@ +#include "fact.h" + +int +main (void) +{ + compute_fact (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test.py new file mode 100644 index 000000000..3fb4ab2df --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test.py @@ -0,0 +1,25 @@ +""" +Check that "f" symbols, both without debug information, in "test_1.c" and +"test_2.c" are not consolidated whereas they are in the same compile unit. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest + + +# We are trying to consolidate the traces of these test drivers. Each test +# driver has its own project, since it can use different compilation options +# for test controllers: +test_drivers = {'test_1': {'not.c': ['-g0', '-O0']}, + 'test_2': {'not.c': ['-g0', '-O0']}} +# Here, no compile unit has debug info. + +coverage_expectations = { + # Both not.c:f() are partially covered (each one covers a complementary + # part, so they would be fully covered if consolidated). + 'f': {'-': 0, '!': 2, '+': 0}, +} + +TestCase(test_drivers, coverage_expectations, + extra_sourcedirs=['../../../../src']).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_1.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_2.c b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_2.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test_2.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/target.txt b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/target.txt new file mode 100644 index 000000000..410189baf --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/target.txt @@ -0,0 +1 @@ +Test the requirement: if a symbol has no compilation unit, never consolidate it. diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/extra.opt b/testsuite/tests/HomonymSymbols/ObjectCoverage/extra.opt new file mode 100644 index 000000000..6a57c8a7a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/extra.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage is supported in binary trace mode only diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/cons_all.txt b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/cons_all.txt new file mode 100644 index 000000000..d419f4d90 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/cons_all.txt @@ -0,0 +1,13 @@ +drivers=test_12|test_13 + +--# fact.c +-- /fact-partial/ l+ ## 0 +-- /fact-full/ l+ ## 0 + +--# not.c +-- /not-all/ l+ ## 0 +-- /not-false/ l+ ## 0 +-- /not-true/ l- ## s- + +--# double.c +-- /double-partial/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_12.c b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_12.c new file mode 100644 index 000000000..94f852ada --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_12.c @@ -0,0 +1,19 @@ +#include "fact.h" +#include "not.h" + +int +main (void) +{ + compute_fact (2); + compute_not (0); + return 0; +} + +//# fact.c +// /fact-partial/ l+ ## 0 +// /fact-full/ l+ ## 0 + +//# not.c +// /not-all/ l+ ## 0 +// /not-false/ l+ ## 0 +// /not-true/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_13.c b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_13.c new file mode 100644 index 000000000..2f5883337 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/src/test_13.c @@ -0,0 +1,17 @@ +#include "double.h" +#include "fact.h" + +int +main (void) +{ + compute_fact (0); + compute_double (0); + return 0; +} + +//# fact.c +// /fact-partial/ l+ ## 0 +// /fact-full/ l- ## s- + +//# double.c +// /double-partial/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/ComplexConsolidation/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/scos.list b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/scos.list new file mode 100644 index 000000000..7173224ec --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/scos.list @@ -0,0 +1 @@ +test_1-obj/not.gli diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.opt b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.opt new file mode 100644 index 000000000..28d2879e2 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.opt @@ -0,0 +1,2 @@ +CARGS_O1 DEAD already testing with both -O0 and -O1 +src-traces DEAD test for binary traces diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.py new file mode 100644 index 000000000..5b655d4d3 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.py @@ -0,0 +1,33 @@ +""" +Check that gnatcov tries and fails to consolidate in source coverage two "f" +symbols, both with debug information and from the same compilation unit, but +compiled with different options. +""" + +from OCOV.tc import TestCase +from SUITE.context import thistest +from SUITE.cutils import Wdir + + +test_drivers = {'test_1': {'not.c': ['-O0']}, + 'test_2': {'not.c': ['-O1']}} +coverage_expectations = { + # There is no object coverage expectation. This entry is to add "f" to the + # routines to consolidate. + 'f': None, +} + +# SCOs are the same for each project: not.gli +wd = Wdir('tmp_') +with open('scos.list', 'w') as f: + for sco_f in ['not.gli']: + f.write('test_1-obj/{}\n'.format(sco_f)) +wd.to_homedir() + +tc = TestCase(test_drivers, coverage_expectations, + extra_sourcedirs=['../../../src'], + level='stmt', annotate='xcov', + extra_xcov_args=['--scos=@scos.list']) +thistest.fail_if(tc.run(register_failure=False), + '"gnatcov coverage" was supposed to fail, but it did not') +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_1.c b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_1.c new file mode 100644 index 000000000..4934c558a --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_1.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_2.c b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_2.c new file mode 100644 index 000000000..b2ac561b1 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test_2.c @@ -0,0 +1,8 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/cons_all.txt b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/cons_all.txt new file mode 100644 index 000000000..022f07853 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/cons_all.txt @@ -0,0 +1,7 @@ +drivers=test_1|test_2 + +--# sum.c +-- /sum-all/ l+ ## 0 +-- /sum-add/ l+ ## 0 +-- /sum-sub/ l+ ## 0 +-- /sum-none/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_1.c b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_1.c new file mode 100644 index 000000000..46211a0b3 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_1.c @@ -0,0 +1,15 @@ +#include "sum.h" + +int +main (void) +{ + int array[4] = { 1, 2, 3, 4 }; + compute_sum (array, 4, SUM_ADD); + return 0; +} + +//# sum.c +// /sum-all/ l+ ## 0 +// /sum-add/ l+ ## 0 +// /sum-sub/ l- ## s- +// /sum-none/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_2.c b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_2.c new file mode 100644 index 000000000..34f83a4db --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/src/test_2.c @@ -0,0 +1,15 @@ +#include "sum.h" + +int +main (void) +{ + int array[4] = { 1, 2, 3, 4 }; + compute_sum (array, 4, SUM_SUB); + return 0; +} + +//# sum.c +// /sum-all/ l+ ## 0 +// /sum-add/ l- ## s- +// /sum-sub/ l+ ## 0 +// /sum-none/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/test.py new file mode 100644 index 000000000..5280b5ac9 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(extracargs='-ffunction-sections', category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_full.c b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_full.c new file mode 100644 index 000000000..97460f972 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_full.c @@ -0,0 +1,21 @@ +#include "fact.h" +#include "not.h" + +int +main (void) +{ + compute_fact (0); + compute_fact (2); + compute_not (0); + compute_not (1); + return 0; +} + +//# fact.c +// /fact-partial/ l+ ## 0 +// /fact-full/ l+ ## 0 + +//# not.c +// /not-all/ l+ ## 0 +// /not-true/ l+ ## 0 +// /not-false/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_no.c b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_no.c new file mode 100644 index 000000000..761181c21 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_no.c @@ -0,0 +1,26 @@ +#include "fact.h" +#include "not.h" + +int cov = 0; + +int +main (void) +{ + /* Never call "run*", but reference then anyway so that they are included by + the linker (gnatcov will not cover them otherwise). */ + if (cov) + { + compute_fact (0); + compute_not (0); + } + return 0; +} + +//# fact.c +// /fact-partial/ l- ## s- +// /fact-full/ l- ## s- + +//# not.c +// /not-all/ l- ## s- +// /not-true/ l- ## s- +// /not-false/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_partial.c b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_partial.c new file mode 100644 index 000000000..7b3629595 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/src/test_partial.c @@ -0,0 +1,19 @@ +#include "fact.h" +#include "not.h" + +int +main (void) +{ + compute_fact (0); + compute_not (0); + return 0; +} + +//# fact.c +// /fact-partial/ l+ ## 0 +// /fact-full/ l- ## s- + +//# not.c +// /not-all/ l+ ## 0 +// /not-false/ l+ ## 0 +// /not-true/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/NoConsolidation/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/cons_all.txt b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/cons_all.txt new file mode 100644 index 000000000..d53ece098 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/cons_all.txt @@ -0,0 +1,10 @@ +drivers=test_1|test_2 + +--# not.c +-- /not-all/ l+ ## 0 +-- /not-false/ l+ ## 0 +-- /not-true/ l- ## s- + +--# fact.c +-- /fact-partial/ l+ ## 0 +-- /fact-full/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_1.c b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_1.c new file mode 100644 index 000000000..695d20bf5 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_1.c @@ -0,0 +1,13 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} + +//# not.c +// /not-all/ l+ ## 0 +// /not-false/ l+ ## 0 +// /not-true/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_2.c b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_2.c new file mode 100644 index 000000000..54bd12dac --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/src/test_2.c @@ -0,0 +1,12 @@ +#include "fact.h" + +int +main (void) +{ + compute_fact (2); + return 0; +} + +//# fact.c +// /fact-partial/ l+ ## 0 +// /fact-full/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Fact/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/cons_all.txt b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/cons_all.txt new file mode 100644 index 000000000..f3a30cfdf --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/cons_all.txt @@ -0,0 +1,6 @@ +drivers=test_1|test_2 + +--# not.c +-- /not-all/ l+ ## 0 +-- /not-false/ l+ ## 0 +-- /not-true/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_1.c b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_1.c new file mode 100644 index 000000000..695d20bf5 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_1.c @@ -0,0 +1,13 @@ +#include "not.h" + +int +main (void) +{ + compute_not (0); + return 0; +} + +//# not.c +// /not-all/ l+ ## 0 +// /not-false/ l+ ## 0 +// /not-true/ l- ## s- diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_2.c b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_2.c new file mode 100644 index 000000000..ff3c92326 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/src/test_2.c @@ -0,0 +1,13 @@ +#include "not.h" + +int +main (void) +{ + compute_not (1); + return 0; +} + +//# not.c +// /not-all/ l+ ## 0 +// /not-false/ l- ## s- +// /not-true/ l+ ## 0 diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/Simple/Not-Not/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/HomonymSymbols/extra.opt b/testsuite/tests/HomonymSymbols/extra.opt new file mode 100644 index 000000000..4ad105b5d --- /dev/null +++ b/testsuite/tests/HomonymSymbols/extra.opt @@ -0,0 +1,2 @@ +7.0.3 DEAD C specific tests for which 7.0.3 misses proper SCO support +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/HomonymSymbols/src/double.c b/testsuite/tests/HomonymSymbols/src/double.c new file mode 100644 index 000000000..fead82d16 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/double.c @@ -0,0 +1,13 @@ +#include "double.h" + +static int +f (int n) +{ + return 2 * n; // # double-partial +} + +int +compute_double (int n) +{ + return f (n); // # double-partial +} diff --git a/testsuite/tests/HomonymSymbols/src/double.h b/testsuite/tests/HomonymSymbols/src/double.h new file mode 100644 index 000000000..9ad39f0b6 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/double.h @@ -0,0 +1,6 @@ +#ifndef DOUBLE_H +#define DOUBLE_H + +int compute_double (int n); + +#endif diff --git a/testsuite/tests/HomonymSymbols/src/fact.c b/testsuite/tests/HomonymSymbols/src/fact.c new file mode 100644 index 000000000..8a9a0bc1b --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/fact.c @@ -0,0 +1,16 @@ +#include "fact.h" + +static int +f (int n) +{ + if (n <= 1) // # fact-partial + return 1; // # fact-partial + else + return n * f (n - 1); // # fact-full +} + +int +compute_fact (int n) +{ + return f (n); // # fact-partial +} diff --git a/testsuite/tests/HomonymSymbols/src/fact.h b/testsuite/tests/HomonymSymbols/src/fact.h new file mode 100644 index 000000000..503d565a9 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/fact.h @@ -0,0 +1,6 @@ +#ifndef FACT_H +#define FACT_H + +int compute_fact (int n); + +#endif diff --git a/testsuite/tests/HomonymSymbols/src/not.c b/testsuite/tests/HomonymSymbols/src/not.c new file mode 100644 index 000000000..dac4eea81 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/not.c @@ -0,0 +1,20 @@ +#include "not.h" +#include "support.h" + +/* -O1 removes this "f" function if it is static. */ +int +f (int b) +{ + /* -O1 inlines the call to "f" from "compute_not" without the following call + to "identity". Inlining yields unexpected results in object coverage. */ + if (!identity (b)) // # not-all + return 1; // # not-false + else + return 0; // # not-true +} + +int +compute_not (int b) +{ + return f (b); // # not-all +} diff --git a/testsuite/tests/HomonymSymbols/src/not.h b/testsuite/tests/HomonymSymbols/src/not.h new file mode 100644 index 000000000..d2d644515 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/not.h @@ -0,0 +1,6 @@ +#ifndef NOT_H +#define NOT_H + +int compute_not (int b); + +#endif diff --git a/testsuite/tests/HomonymSymbols/src/sum.c b/testsuite/tests/HomonymSymbols/src/sum.c new file mode 100644 index 000000000..b44b438bb --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/sum.c @@ -0,0 +1,42 @@ +#include "sum.h" + +int +sum_add (int *array, unsigned size) +{ + int result = 0; // # sum-add + unsigned i = 0; // # sum-add + + while (i < size) // # sum-add + { + result += array[i]; // # sum-add + ++i; // # sum-add + } + + return result; // # sum-add +} + +int +sum_sub (int *array, unsigned size) +{ + int result = 0; // # sum-sub + unsigned i = 0; // # sum-sub + + while (i < size) // # sum-sub + { + result -= array[i]; // # sum-sub + ++i; // # sum-sub + } + + return result; // # sum-sub +} + +int +compute_sum (int *array, unsigned size, int mode) +{ + if (mode == SUM_ADD) // # sum-all + return sum_add (array, size); // # sum-add + else if (mode == SUM_SUB) // # sum-sub + return sum_sub (array, size); // # sum-sub + else + return 0; // # sum-none +} diff --git a/testsuite/tests/HomonymSymbols/src/sum.h b/testsuite/tests/HomonymSymbols/src/sum.h new file mode 100644 index 000000000..dff60f1d7 --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/sum.h @@ -0,0 +1,9 @@ +#ifndef SUM_H +#define SUM_H + +#define SUM_ADD 1 +#define SUM_SUB 2 + +int compute_sum (int *array, unsigned size, int mode); + +#endif diff --git a/testsuite/tests/HomonymSymbols/src/support.h b/testsuite/tests/HomonymSymbols/src/support.h new file mode 100644 index 000000000..89c7b234c --- /dev/null +++ b/testsuite/tests/HomonymSymbols/src/support.h @@ -0,0 +1,6 @@ +#ifndef SUPPORT_H +#define SUPPORT_H + +extern int identity (int n); /* from libsupport. */ + +#endif diff --git a/testsuite/tests/I401-009/src/engines.adb b/testsuite/tests/I401-009/src/engines.adb new file mode 100644 index 000000000..6c8a1fb08 --- /dev/null +++ b/testsuite/tests/I401-009/src/engines.adb @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + return E.P < Stable_P and then E.T < Stable_T; + end Stable; +end Engines; diff --git a/testsuite/tests/I401-009/src/engines.ads b/testsuite/tests/I401-009/src/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/I401-009/src/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/I401-009/src/test_engines.adb b/testsuite/tests/I401-009/src/test_engines.adb new file mode 100644 index 000000000..fdec19174 --- /dev/null +++ b/testsuite/tests/I401-009/src/test_engines.adb @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; + +------------------ +-- Test_Engines -- +------------------ +procedure Test_Engines is + E : Engine; + + procedure Assert (X : Boolean); + + procedure Assert (X : Boolean) is + begin + if not X then + raise Program_Error; + end if; + end Assert; +begin + + -- Exercise various condition/decision combinations in Stable. + + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); + + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); + +end Test_Engines; diff --git a/testsuite/tests/I401-009/test.opt b/testsuite/tests/I401-009/test.opt new file mode 100644 index 000000000..6a57c8a7a --- /dev/null +++ b/testsuite/tests/I401-009/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage is supported in binary trace mode only diff --git a/testsuite/tests/I401-009/test.py b/testsuite/tests/I401-009/test.py new file mode 100644 index 000000000..c3ff8b75e --- /dev/null +++ b/testsuite/tests/I401-009/test.py @@ -0,0 +1,21 @@ +""" +We run a partial test of the simple 'engines' example and expect the analyzer +to report only partial coverage of the relevant subprogram return statement. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +Wdir('tmp_') + +gprbuild(gprfor(['test_engines.adb'], srcdirs='../src')) + +xrun(exepath_to('test_engines')) +xcov(['coverage', '--level=branch', '--annotate=xcov', + tracename_for('test_engines')]) + +thistest.fail_if(not match(r' \!:.*return.*Stable_P', 'engines.adb.xcov')) +thistest.result() diff --git a/testsuite/tests/I427-029/src/assert.adb b/testsuite/tests/I427-029/src/assert.adb new file mode 100644 index 000000000..075669142 --- /dev/null +++ b/testsuite/tests/I427-029/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (X : Boolean) is +begin + if not X then + raise Program_Error; + end if; +end Assert; diff --git a/testsuite/tests/I427-029/src/engines.adb b/testsuite/tests/I427-029/src/engines.adb new file mode 100644 index 000000000..6c8a1fb08 --- /dev/null +++ b/testsuite/tests/I427-029/src/engines.adb @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + return E.P < Stable_P and then E.T < Stable_T; + end Stable; +end Engines; diff --git a/testsuite/tests/I427-029/src/engines.ads b/testsuite/tests/I427-029/src/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/I427-029/src/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/I427-029/src/test_engines_mm.adb b/testsuite/tests/I427-029/src/test_engines_mm.adb new file mode 100644 index 000000000..3d1303e2a --- /dev/null +++ b/testsuite/tests/I427-029/src/test_engines_mm.adb @@ -0,0 +1,11 @@ +with Assert, Engines; use Engines; + +procedure Test_Engines_MM is + E : Engine; +begin + -- MM case: Both values set to stability threshold Minus one + + E.P := Stable_P - 1; + E.T := Stable_T - 1; + Assert (Stable (E)); +end; diff --git a/testsuite/tests/I427-029/src/test_engines_mp.adb b/testsuite/tests/I427-029/src/test_engines_mp.adb new file mode 100644 index 000000000..6c6f50445 --- /dev/null +++ b/testsuite/tests/I427-029/src/test_engines_mp.adb @@ -0,0 +1,9 @@ +with Assert, Engines; use Engines; + +procedure Test_Engines_MP is + E : Engine; +begin + E.P := Stable_P - 1; + E.T := Stable_T + 1; + Assert (not Stable (E)); +end; diff --git a/testsuite/tests/I427-029/src/test_engines_pm.adb b/testsuite/tests/I427-029/src/test_engines_pm.adb new file mode 100644 index 000000000..c2964b30a --- /dev/null +++ b/testsuite/tests/I427-029/src/test_engines_pm.adb @@ -0,0 +1,9 @@ +with Assert, Engines; use Engines; + +procedure Test_Engines_PM is + E : Engine; +begin + E.P := Stable_P + 1; + E.T := Stable_T - 1; + Assert (not Stable (E)); +end; diff --git a/testsuite/tests/I427-029/src/test_engines_pp.adb b/testsuite/tests/I427-029/src/test_engines_pp.adb new file mode 100644 index 000000000..34176836f --- /dev/null +++ b/testsuite/tests/I427-029/src/test_engines_pp.adb @@ -0,0 +1,11 @@ +with Assert, Engines; use Engines; + +procedure Test_Engines_PP is + E : Engine; +begin + -- PP case: Both values set to stability threshold Plus one + + E.P := Stable_P + 1; + E.T := Stable_T + 1; + Assert (not Stable (E)); +end; diff --git a/testsuite/tests/I427-029/test.opt b/testsuite/tests/I427-029/test.opt new file mode 100644 index 000000000..6a57c8a7a --- /dev/null +++ b/testsuite/tests/I427-029/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage is supported in binary trace mode only diff --git a/testsuite/tests/I427-029/test.py b/testsuite/tests/I427-029/test.py new file mode 100644 index 000000000..f20a71b8c --- /dev/null +++ b/testsuite/tests/I427-029/test.py @@ -0,0 +1,106 @@ +""" +Perform a bunch of xcov related operations to validate the basic toolset +functionalities. +""" + +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import Wdir, match +from SUITE.tutils import (exepath_to, gprbuild, gprfor, maybe_valgrind, + tracename_for, xcov, xrun) + + +Wdir('tmp_') + +# Context information, basic command line interface checks +print('maybe_valgrind prepends ... ' + str(maybe_valgrind([]))) +xcov(['--version']) +xcov(['--help']) + +# Core functions checks over the Engines example + +# We will first work on a set of operations around the "engines" simple +# example, with different executables to exercise various combinations of +# value/thresold relationships on pressure and temperature. +# +# Each variant sets the engine P/T parameters to the P/T stability threshold +# plus or minus one and checks that the Stable function returns the expected +# value. Doing so, it exercises a subset of the possible path combinations +# through the function return boolean expression. +# +# We name each variant with a couple of letters, one per Pressure/Temperature +# parameter, each either P or M to denote whether the parameter is set to the +# threshold Plus or Minus one. +variants = ['mm', 'mp', 'pm', 'pp'] + + +# The sources are named accordingly (e.g. test_engines_mm.adb), and we we play +# with a number of related outputs (test_engines_mm executable, .trace file +# out of qemu, etc.). We Define a class to help handle such variants: + +class Vtest: + def __init__(self, basename, variant): + self.basename = basename + self.variant = variant + + def filename(self, suffix=''): + """ + Return the name to use for a file related to this variant, suffixed + with SUFFIX. + """ + return self.basename + '_' + self.variant + suffix + + def tag(self): + """Return a trace tag to associate with this test variant.""" + return '%s, %s variant' % (self.basename, self.variant) + + +# Build all the executable variants from a single multi-mains project file +gprbuild(gprfor([Vtest('test_engines', v).filename('.adb') for v in variants], + srcdirs='../src')) + +# First, a number of tests over individual variants: +for variant in variants: + vt = Vtest('test_engines', variant) + + # Xrun & stick a dedicated tag into the trace output + xrun([exepath_to(vt.filename()), '--tag=' + vt.tag()]) + + # Compute branch coverage for this variant & check that there's only + # partial coverage of the return expression + xcov(['coverage', '--level=branch', '--annotate=xcov', + vt.filename(tracename_for(''))]) + thistest.fail_if( + not match(r' \!:.*return.*Stable_P', 'engines.adb.xcov'), + 'single input, expected partial coverage over return expr') + + # Verify that we can dump the trace and find the tag in the dump output + xcov( + ['dump-trace', tracename_for(vt.filename())], + vt.filename('.tracedump')) + thistest.fail_if( + not match('Tag.*(User_Tag).*\nLen.*\nData.*%s' % vt.tag(), + vt.filename('.tracedump')), + 'single input, expected user tag from --dump-trace') + +# Now, check that we can combine the trace results from all the variants +# and obtain full branch coverage of the return boolean expression. Build +# a consolidation routine list for this purpose. +with open('list.stable', 'w') as rl: + rl.write(target_info().to_platform_specific_symbol('engines__stable\n')) + +xcov(['coverage', '--level=branch', '--annotate=xcov', + '--routines=@list.stable'] + + [tracename_for(Vtest('test_engines', v).filename()) + for v in variants]) +thistest.fail_if( + not match(r' \+:.*return.*Stable_P', 'engines.adb.xcov'), + 'combined inputs, expected full branch coverage over return expr') + +# Check that we can produce html without crashing as well ... +xcov(['coverage', '--level=branch', '--annotate=html+', + '--routines=@list.stable'] + + [Vtest('test_engines', v).filename(tracename_for('')) + for v in variants]) + +thistest.result() diff --git a/testsuite/tests/I505-018/src/services.adb b/testsuite/tests/I505-018/src/services.adb new file mode 100644 index 000000000..bdec49021 --- /dev/null +++ b/testsuite/tests/I505-018/src/services.adb @@ -0,0 +1,16 @@ +package body Services is + + Counter : Integer; + + procedure To_Be_Called is + begin + Counter := Counter + 1; + end; + + procedure Not_To_Be_Called is + begin + raise Program_Error; + end; +end; + + diff --git a/testsuite/tests/I505-018/src/services.ads b/testsuite/tests/I505-018/src/services.ads new file mode 100644 index 000000000..c90c53757 --- /dev/null +++ b/testsuite/tests/I505-018/src/services.ads @@ -0,0 +1,9 @@ +-- This unit is to be compiled with -ffunction-sections and must expose at +-- least to entry points to exercise the targetted internal circuits. + +package Services is + procedure To_Be_Called; + procedure Not_To_Be_Called; +end; + + diff --git a/testsuite/tests/I505-018/src/test_services.adb b/testsuite/tests/I505-018/src/test_services.adb new file mode 100644 index 000000000..9654c4b4c --- /dev/null +++ b/testsuite/tests/I505-018/src/test_services.adb @@ -0,0 +1,6 @@ +with Services; + +procedure Test_Services is +begin + Services.To_Be_Called; +end; diff --git a/testsuite/tests/I505-018/test.py b/testsuite/tests/I505-018/test.py new file mode 100644 index 000000000..6a3121aab --- /dev/null +++ b/testsuite/tests/I505-018/test.py @@ -0,0 +1,30 @@ +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +Wdir('tmp_') + +# Check that "gnatcov coverage" produces reports for units exposing more than +# one entry point when compiled with -ffunction-sections. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor( + mains=['test_services.adb'], + srcdirs='../src', + compiler_extra='for Default_Switches ("Ada")' + ' use ("-ffunction-sections");')), + covlevel='stmt', + mains=['test_services'], + extra_coverage_args=['--annotate=xcov'], + scos=['obj/services', 'obj/test_services']) + +# Use match to both verify that expected reports are there and +# that coverage results are as we expect as well, while we're at it. +thistest.fail_if( + not match('100% of [1-9] lines covered', 'test_services.adb.xcov')) +thistest.fail_if( + not match('-:.*raise Program_Error;', 'services.adb.xcov')) + +thistest.result() diff --git a/testsuite/tests/I511-019-response-files/src/bar.adb b/testsuite/tests/I511-019-response-files/src/bar.adb new file mode 100644 index 000000000..121dc18fc --- /dev/null +++ b/testsuite/tests/I511-019-response-files/src/bar.adb @@ -0,0 +1,11 @@ +package body Bar is + procedure Proc1 is + begin + null; + end; + + procedure Proc2 is + begin + null; + end; +end; diff --git a/testsuite/tests/I511-019-response-files/src/bar.ads b/testsuite/tests/I511-019-response-files/src/bar.ads new file mode 100644 index 000000000..86dcb8e3f --- /dev/null +++ b/testsuite/tests/I511-019-response-files/src/bar.ads @@ -0,0 +1,5 @@ + +package Bar is + procedure Proc1; + procedure Proc2; +end; diff --git a/testsuite/tests/I511-019-response-files/src/foo.adb b/testsuite/tests/I511-019-response-files/src/foo.adb new file mode 100644 index 000000000..a71566ccb --- /dev/null +++ b/testsuite/tests/I511-019-response-files/src/foo.adb @@ -0,0 +1,5 @@ + +procedure Foo is +begin + null; +end; diff --git a/testsuite/tests/I511-019-response-files/src/test_foobar.adb b/testsuite/tests/I511-019-response-files/src/test_foobar.adb new file mode 100644 index 000000000..0b05245d3 --- /dev/null +++ b/testsuite/tests/I511-019-response-files/src/test_foobar.adb @@ -0,0 +1,13 @@ +with Foo; with Bar; + +procedure Test_Foobar is +begin + Foo; + Bar.Proc1; + Bar.Proc2; + + -- This test is designed for command line checks, + -- not to be run + + raise Program_Error; +end; diff --git a/testsuite/tests/I511-019-response-files/test.py b/testsuite/tests/I511-019-response-files/test.py new file mode 100644 index 000000000..851c718fe --- /dev/null +++ b/testsuite/tests/I511-019-response-files/test.py @@ -0,0 +1,36 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, set_from +from SUITE.tutils import gprbuild, gprfor, xcov + + +Wdir('tmp_') + +# Build a dummy project, to generate objects that we will query with +# disp-routines via an explicit list or a response file, to compare +# the results. +gprbuild(gprfor(['test_foobar.adb'], srcdirs='../src')) +objects = ['obj/foo.o', 'obj/bar.o'] + +# Get disp-routines output from explicit command line arguments +xcov(args=['disp-routines'] + objects, + out='explicit.out') + +# Build response file with same list of objects, and get disp-routines +# output from this +with open('foobar.list', 'w') as f: + f.write('\n'.join(objects) + '\n') + +xcov(args=['disp-routines', '@foobar.list'], + out='response.out') + +# Check that both outputs are the same and non-empty, with at least one +# of the bits we expect there. Do not rely on symbols ordering: it is not +# specified. +response = set_from('response.out') +explicit = set_from('explicit.out') +thistest.fail_if( + explicit != response, + 'expect disp-routines output identical from args or response file') +thistest.fail_if(not any('bar' in symbol for symbol in explicit), + 'expect "bar" in disp-routines output') +thistest.result() diff --git a/testsuite/tests/I512-020/ppcstart.elf b/testsuite/tests/I512-020/ppcstart.elf new file mode 100644 index 0000000000000000000000000000000000000000..e2fe1ebbbe2eef093a0ab48aa4c6ad02cacab3b7 GIT binary patch literal 1740 zcmah~O-~b16um>IrAUDygplB3h?TG)qZnh*U?Rq^Mbj7%!=lM_hK|@sTb-F2NKC|y zzrdwG!Jp($aN)w83q9w}+;IvEZgS_I`|-}b@4e~t)05^?Yr>LTELj9D27a5|9rIk5 z1*va4BAr!{t&SrfJ67X4>Zz?WabPJgWdhF)+xjy*BNhZ6)Nx#sQA0>UiH+UcR zM{b<9D|3k~ty0!75*DSQ(jq4`9J_{BZ1Nc~gg4LgJ-*-G>Gq=0Zuo8(_mW|B+HU%T zqxL}(#)&*@?K?Yr&TV&dOU^87Uh0+oN~yY1y-{5#E3rr;>-9e(axHUg4gQ5FhP{v% zH$LqregK<9sePj;3Xgp^2~QGnyME$}8^p1=CK`oth_J!kFc=+q$Gt%~7U&IL53$fB z{UC_K4`XRR!iGcTOUtrQVcyH2g94s)B`f4xpnGIU?_mWvKa;Hd7Gm>R4RbZKZ`#4t+(CiRN1Hi+t?cfRb-2%aPB6>Ka1+WUfM0G#4SDn2@ur zYY{BZmePk7`<}qpzU;>w?H6c~?;(5#s-k?K5h(I~gRk$wY?dP*_oa6WXm#-T3RTfw zwC1yrChVWEzo6XnG?cySP@YkNulxi4b*PH+sei#@@mLM~0-tf%OKXS=p9+&d?{lVH zK*o7$f4`b<>G*P1%Jd=vCkE&vDPANuB bMKQ-!jQMjO>_3l#$6)Re^?40v<68S4hyQ|v): .* (bclr|bge|blt|bnl)', contents_of('test_min1.out')) + +thistest.fail_if(not m, "couldn't find expected partially covered branch") + +dir1 = m.group(1) +insn1 = m.group(2) + +# Seek the other partial branch coverage for the second test exercising only +# the other side of the 'if' stmt. +alt_sign = {'>': 'v', 'v': '>'} + +xrun(exepath_to('test_min2')) +xcov('coverage --level=branch --annotate=asm --routines=@../func.list ' + + tracename_for('test_min2'), + out='test_min2.out') +thistest.fail_if(not match(alt_sign[dir1] + ': .* ' + insn1, 'test_min2.out'), + "couldn't find alternate branch coverage") + +thistest.result() diff --git a/testsuite/tests/I519-015/test_min.adb b/testsuite/tests/I519-015/test_min.adb new file mode 100644 index 000000000..cf684bc88 --- /dev/null +++ b/testsuite/tests/I519-015/test_min.adb @@ -0,0 +1,12 @@ +with Min; + +procedure Test_Min is + V : Float; +begin + V := 1.5; + V := Min (V, 0.5); + V := Min (V, 2.0); + if V /= 0.5 then + raise Program_Error; + end if; +end Test_Min; diff --git a/testsuite/tests/I519-015/test_min1.adb b/testsuite/tests/I519-015/test_min1.adb new file mode 100644 index 000000000..3115ac9ac --- /dev/null +++ b/testsuite/tests/I519-015/test_min1.adb @@ -0,0 +1,11 @@ +with Min; + +procedure Test_Min1 is + V : Float; +begin + V := 1.5; + V := Min (V, 0.5); + if V /= 0.5 then + raise Program_Error; + end if; +end Test_Min1; diff --git a/testsuite/tests/I519-015/test_min2.adb b/testsuite/tests/I519-015/test_min2.adb new file mode 100644 index 000000000..c4c72c989 --- /dev/null +++ b/testsuite/tests/I519-015/test_min2.adb @@ -0,0 +1,11 @@ +with Min; + +procedure Test_Min2 is + V : Float; +begin + V := 1.5; + V := Min (V, 2.5); + if V /= 1.5 then + raise Program_Error; + end if; +end Test_Min2; diff --git a/testsuite/tests/I519-030/src/kops.adb b/testsuite/tests/I519-030/src/kops.adb new file mode 100644 index 000000000..550f382aa --- /dev/null +++ b/testsuite/tests/I519-030/src/kops.adb @@ -0,0 +1,8 @@ + +package body Kops is + procedure Inc (X : in out Integer) is + begin + X := X + K; + end Inc; +end; + diff --git a/testsuite/tests/I519-030/src/kops.ads b/testsuite/tests/I519-030/src/kops.ads new file mode 100644 index 000000000..589ab169d --- /dev/null +++ b/testsuite/tests/I519-030/src/kops.ads @@ -0,0 +1,8 @@ + +generic + K : Integer; +package Kops is + procedure Inc (X : in out Integer); + pragma Inline (Inc); +end; + diff --git a/testsuite/tests/I519-030/src/ops4.ads b/testsuite/tests/I519-030/src/ops4.ads new file mode 100644 index 000000000..1d4738d2d --- /dev/null +++ b/testsuite/tests/I519-030/src/ops4.ads @@ -0,0 +1,2 @@ +with Kops; +package Ops4 is new Kops (K => 4); diff --git a/testsuite/tests/I519-030/src/ops8.ads b/testsuite/tests/I519-030/src/ops8.ads new file mode 100644 index 000000000..d69b950a1 --- /dev/null +++ b/testsuite/tests/I519-030/src/ops8.ads @@ -0,0 +1,2 @@ +with Kops; +package Ops8 is new Kops (K => 8); diff --git a/testsuite/tests/I519-030/src/test_kops.adb b/testsuite/tests/I519-030/src/test_kops.adb new file mode 100644 index 000000000..0b479da84 --- /dev/null +++ b/testsuite/tests/I519-030/src/test_kops.adb @@ -0,0 +1,11 @@ +with Ops4, Ops8, Vars; + +procedure Test_Kops is + Vx : Integer := Vars.X; +begin + Ops4.Inc (Vx); + Vars.Assert_Eq (Vx, 16); + + Ops8.Inc (Vx); + Vars.Assert_Eq (Vx, 24); +end; diff --git a/testsuite/tests/I519-030/src/vars.adb b/testsuite/tests/I519-030/src/vars.adb new file mode 100644 index 000000000..b36792c78 --- /dev/null +++ b/testsuite/tests/I519-030/src/vars.adb @@ -0,0 +1,8 @@ +package body Vars is + procedure Assert_Eq (Value, Expected : Integer) is + begin + if Value /= Expected then + raise Program_Error; + end if; + end; +end; diff --git a/testsuite/tests/I519-030/src/vars.ads b/testsuite/tests/I519-030/src/vars.ads new file mode 100644 index 000000000..06a24b27f --- /dev/null +++ b/testsuite/tests/I519-030/src/vars.ads @@ -0,0 +1,6 @@ +package Vars is + X : Integer := 12; + pragma Volatile (X); + + procedure Assert_Eq (Value, Expected : Integer); +end; diff --git a/testsuite/tests/I519-030/test.opt b/testsuite/tests/I519-030/test.opt new file mode 100644 index 000000000..45c00da6b --- /dev/null +++ b/testsuite/tests/I519-030/test.opt @@ -0,0 +1,5 @@ +-- This is an -O1 specific test. No need to noise the runs we do for +-- qualification tests at other levels. This test is also specific to object +-- coverage, so applicable only to binary traces. +bin-traces,CARGS_O1 +ALL DEAD diff --git a/testsuite/tests/I519-030/test.py b/testsuite/tests/I519-030/test.py new file mode 100644 index 000000000..be4c10c51 --- /dev/null +++ b/testsuite/tests/I519-030/test.py @@ -0,0 +1,75 @@ +""" +Check object coverage results in presence of inlining, with a single trivial +public routine called once from another unit. +""" + +import re + +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import Wdir, match +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +Wdir('tmp_') + +# We expect the routine machine code to appear in two places: in the +# associated unit object and at the unique call site. We expect both to be +# attached to the routine source and only the latter to be exercised. +# +# With generics involved, similar expectations with multiple versions of the +# object code all attached to the unique generic source. +_target_info = target_info() + +# Build with inlining activated. Don't force unreferenced symbols away. +gprbuild(project=gprfor(['test_kops.adb'], srcdirs='../src'), + extracargs=['-O1', '-gnatn', '-save-temps']) + +# Run, then check results. +xrun(exepath_to('test_kops')) + +instances = ['ops4', 'ops8'] + +# We expect all the source level calls to have been inlined, hence the base +# object code alone never to be called +xcov(['disp-routines'] + ['obj/' + i + '.o' for i in instances], + out='kops.list') +xcov(['coverage', '--level=branch', '--annotate=xcov+', + '--routines=@kops.list', tracename_for('test_kops')]) +thistest.fail_if(not match(r'-:.*X := X \+ K', 'kops.adb.xcov'), + 'expect body of inlined not to be covered') + +# And full object code coverage should report partial coverage only +xcov(['coverage', '--level=branch', '--annotate=xcov', + tracename_for('test_kops')]) +thistest.fail_if(not match(r'!:.*X := X \+ K', 'kops.adb.xcov')) + +# Besides, attached to the generic source, we expect distinct object code +# sequences from the testing code (all covered, but we don't check for that). +# We request asm inserts for this purpose, and can't be sure about the exact +# layout of lines so have '.' match newlines as well. +xcov(['coverage', '--level=branch', '--annotate=xcov+', + tracename_for('test_kops')]) + +symbol = _target_info.to_platform_specific_symbol('_ada_test_kops') +thistest.fail_if( + not match('procedure Inc' + '.*' + + '<{}.*'.format(symbol) * len(instances) + + 'end Inc', + 'kops.adb.xcov', flags=re.DOTALL), + 'expect body of inlined attached to inlined source') + +# Likewise, we expect one object code sequence for each generic instance (all +# uncovered, but we don't check for that). There's no guarantee on the order +# in which the instances object code will show up, so iterate on searches. +for i in instances: + symbol = _target_info.to_platform_specific_symbol(i) + thistest.fail_if( + not match('procedure Inc' + '.*' + + '<' + symbol + '__inc' + + '.*' + 'end Inc', + 'kops.adb.xcov', flags=re.DOTALL), + 'expect %s inlined machine code attached to inlined source' % symbol) + +thistest.result() diff --git a/testsuite/tests/I522-010/src/volp.adb b/testsuite/tests/I522-010/src/volp.adb new file mode 100644 index 000000000..e94334282 --- /dev/null +++ b/testsuite/tests/I522-010/src/volp.adb @@ -0,0 +1,8 @@ +procedure Volp is + X : Integer := 10; + pragma Volatile (X); +begin + if X /= 10 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I522-010/test.opt b/testsuite/tests/I522-010/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/I522-010/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/I522-010/test.py b/testsuite/tests/I522-010/test.py new file mode 100644 index 000000000..0391f8407 --- /dev/null +++ b/testsuite/tests/I522-010/test.py @@ -0,0 +1,15 @@ +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import Wdir +from SUITE.tutils import exepath_to, gprbuild, gprfor, xrun + + +Wdir('tmp_') + +extralargs = ',--entry=volp' if target_info().partiallinks else '' +gprbuild(project=gprfor(['volp.adb'], srcdirs='../src'), + extracargs='-ffunction-sections', + largs='-Wl,--gc-sections' + extralargs) +xrun(exepath_to('volp')) + +thistest.result() diff --git a/testsuite/tests/I715-012/src/monitor.adb b/testsuite/tests/I715-012/src/monitor.adb new file mode 100644 index 000000000..efc5cd47b --- /dev/null +++ b/testsuite/tests/I715-012/src/monitor.adb @@ -0,0 +1,6 @@ +package body Monitor is + procedure Touch is + begin + N_Ops := N_Ops + 1; + end; +end; diff --git a/testsuite/tests/I715-012/src/monitor.ads b/testsuite/tests/I715-012/src/monitor.ads new file mode 100644 index 000000000..ae8097029 --- /dev/null +++ b/testsuite/tests/I715-012/src/monitor.ads @@ -0,0 +1,5 @@ +package Monitor is + N_Ops : Integer := 0; + + procedure Touch; +end; diff --git a/testsuite/tests/I715-012/src/p.adb b/testsuite/tests/I715-012/src/p.adb new file mode 100644 index 000000000..06a6afc10 --- /dev/null +++ b/testsuite/tests/I715-012/src/p.adb @@ -0,0 +1,6 @@ +with Pack; + +procedure P is +begin + Pack.Func; +end P; diff --git a/testsuite/tests/I715-012/src/pack.adb b/testsuite/tests/I715-012/src/pack.adb new file mode 100644 index 000000000..fd4e4de60 --- /dev/null +++ b/testsuite/tests/I715-012/src/pack.adb @@ -0,0 +1,10 @@ +with Monitor; + +package body Pack is + + procedure Func is + begin + Monitor.Touch; + end Func; + +end Pack; diff --git a/testsuite/tests/I715-012/src/pack.ads b/testsuite/tests/I715-012/src/pack.ads new file mode 100644 index 000000000..fdf6d56b0 --- /dev/null +++ b/testsuite/tests/I715-012/src/pack.ads @@ -0,0 +1,5 @@ +package Pack is + + procedure Func; + +end Pack; diff --git a/testsuite/tests/I715-012/test.opt b/testsuite/tests/I715-012/test.opt new file mode 100644 index 000000000..6a57c8a7a --- /dev/null +++ b/testsuite/tests/I715-012/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage is supported in binary trace mode only diff --git a/testsuite/tests/I715-012/test.py b/testsuite/tests/I715-012/test.py new file mode 100644 index 000000000..463b78d7e --- /dev/null +++ b/testsuite/tests/I715-012/test.py @@ -0,0 +1,28 @@ +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir, list_to_tmp +from SUITE.tutils import (exepath_to, gprbuild, gprfor, + platform_specific_symbols, tracename_for, xcov, xrun) + + +wd = Wdir('tmp_') +gprbuild(project=gprfor(srcdirs=['../src'], mains=['p.adb'])) +symfile = list_to_tmp(platform_specific_symbols(['pack__func'])) + +xrun(exepath_to('p')) +xcov(['coverage', '--level=branch', + '--routines=@' + symfile, + '--annotate=xcov+', tracename_for('p')]) + +# This test should check that xcov does not generate null report files +# for sources that are not considered in the coverage operation. +# Here, only pack.adb.xcov should be generated, as the routine list +# contains only pack__func, fully defined in pack.adb. +thistest.fail_if(not os.path.exists('pack.adb.xcov') + or os.path.exists('text_io.adb.xcov') + or os.path.exists('monitor.ads.xcov') + or os.path.exists('monitor.adb.xcov') + or os.path.exists('p.adb.xcov')) + +thistest.result() diff --git a/testsuite/tests/I716-009/func.list b/testsuite/tests/I716-009/func.list new file mode 100644 index 000000000..1bd8f61d2 --- /dev/null +++ b/testsuite/tests/I716-009/func.list @@ -0,0 +1 @@ +min diff --git a/testsuite/tests/I716-009/min.ads b/testsuite/tests/I716-009/min.ads new file mode 100644 index 000000000..03da5c0a8 --- /dev/null +++ b/testsuite/tests/I716-009/min.ads @@ -0,0 +1,2 @@ +function Min (X, Y : in Integer) return Integer; +pragma Import (Ada, Min); diff --git a/testsuite/tests/I716-009/min_asm.s b/testsuite/tests/I716-009/min_asm.s new file mode 100644 index 000000000..a18ba3195 --- /dev/null +++ b/testsuite/tests/I716-009/min_asm.s @@ -0,0 +1,17 @@ + .file "min.adb" + .gnu_attribute 4, 1 + .gnu_attribute 8, 1 + .section ".text" + .align 2 + .globl min + .type min, @function +min: + mr 0,3 + mr 3,4 +# cmpw 7,4,0 +# blelr 7 + cmpw 7,0,4 + bgtlr 7 + mr 3,0 + blr + .size min, .-min diff --git a/testsuite/tests/I716-009/test.opt b/testsuite/tests/I716-009/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I716-009/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I716-009/test.py b/testsuite/tests/I716-009/test.py new file mode 100644 index 000000000..22524099c --- /dev/null +++ b/testsuite/tests/I716-009/test.py @@ -0,0 +1,27 @@ +""" +This test performs a bunch of xcov related operations to validate the basic +toolset functionalities. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import (exepath_to, gprbuild, gprfor, maybe_valgrind, + tracename_for, xcov, xrun) + + +Wdir('tmp_') + +# Context information, basic command line interface checks +print('maybe_valgrind prepends ...', maybe_valgrind([])) + +gprbuild(project=gprfor(mains=['test_min.adb'], + langs=['Ada', 'Asm'], + srcdirs=['..'])) +xrun(exepath_to('test_min')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_min')], + 'test_min.out') +thistest.fail_if(not match(r'min \+:.*', 'test_min.out'), + 'full coverage expected') + +thistest.result() diff --git a/testsuite/tests/I716-009/test_min.adb b/testsuite/tests/I716-009/test_min.adb new file mode 100644 index 000000000..4efd8abed --- /dev/null +++ b/testsuite/tests/I716-009/test_min.adb @@ -0,0 +1,12 @@ +with Min; + +procedure Test_Min is + V : Integer; +begin + V := 3; + V := Min (V, 4); + V := Min (V, 1); + if V /= 1 then + raise Program_Error; + end if; +end Test_Min; diff --git a/testsuite/tests/I716-021/src/p.adb b/testsuite/tests/I716-021/src/p.adb new file mode 100644 index 000000000..86ea6ebc8 --- /dev/null +++ b/testsuite/tests/I716-021/src/p.adb @@ -0,0 +1,11 @@ +package body P is + function Head_Of (B : Block_T) return System.Address is + Blength : constant Integer := B'Last - B'First + 1; + Baddr : System.Address := System.Null_Address; + begin + if Blength > 0 then + Baddr := B(B'First)'Address; + end if; + return Baddr; + end; +end; diff --git a/testsuite/tests/I716-021/src/p.ads b/testsuite/tests/I716-021/src/p.ads new file mode 100644 index 000000000..4c2be74ca --- /dev/null +++ b/testsuite/tests/I716-021/src/p.ads @@ -0,0 +1,8 @@ +with System; + +package P is + subtype Index_T is Integer range 0 .. 255; + type Block_T is array (Integer range <>) of Integer; + + function Head_Of (B : Block_T) return System.Address; +end; diff --git a/testsuite/tests/I716-021/src/test_p.adb b/testsuite/tests/I716-021/src/test_p.adb new file mode 100644 index 000000000..5dc06f8be --- /dev/null +++ b/testsuite/tests/I716-021/src/test_p.adb @@ -0,0 +1,19 @@ +with System, P; use P; + +procedure Test_P is + My_Block : Block_T (1 ..2) := (1, 2); + My_Empty_Block : Block_T (2 .. 1); + + Addr : System.Address; + use type System.Address; +begin + Addr := Head_Of (My_Block); + if Addr /= My_Block (My_Block'First)'Address then + raise Program_Error; + end if; + + Addr := Head_Of (My_Empty_Block); + if Addr /= System.Null_Address then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I716-021/test.opt b/testsuite/tests/I716-021/test.opt new file mode 100644 index 000000000..6a57c8a7a --- /dev/null +++ b/testsuite/tests/I716-021/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage is supported in binary trace mode only diff --git a/testsuite/tests/I716-021/test.py b/testsuite/tests/I716-021/test.py new file mode 100644 index 000000000..08e277b83 --- /dev/null +++ b/testsuite/tests/I716-021/test.py @@ -0,0 +1,19 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +Wdir('tmp_') +gprbuild(project=gprfor(['test_p.adb'], srcdirs='../src')) +xrun(exepath_to('test_p')) +xcov(['coverage', '--level=branch', '--annotate=xcov+', + tracename_for('test_p')]) + +# We expect the test to exercise the single branch in p.head_of +# both ways, and that this branch is associated with the "if" statement +# there, something like +# +# 6 +: if Blength > 0 then +thistest.fail_if(not match(r'[0-9]+ \+:.*if .* then', 'p.adb.xcov')) +thistest.result() diff --git a/testsuite/tests/I717-018/explore.list b/testsuite/tests/I717-018/explore.list new file mode 100644 index 000000000..4d6021ab5 --- /dev/null +++ b/testsuite/tests/I717-018/explore.list @@ -0,0 +1 @@ +robots__robot_control_inport diff --git a/testsuite/tests/I717-018/src/actors.adb b/testsuite/tests/I717-018/src/actors.adb new file mode 100644 index 000000000..ec41c8261 --- /dev/null +++ b/testsuite/tests/I717-018/src/actors.adb @@ -0,0 +1,38 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Actors is + + ---------- + -- Live -- + ---------- + function Live (A : Actor'Class) return Boolean is + begin + return A.Live; + end Live; + + ---------- + -- Kill -- + ---------- + procedure Kill (A : in out Actor'Class) is + begin + A.Live := False; + end Kill; + +end Actors; diff --git a/testsuite/tests/I717-018/src/actors.ads b/testsuite/tests/I717-018/src/actors.ads new file mode 100644 index 000000000..dbcbc22a5 --- /dev/null +++ b/testsuite/tests/I717-018/src/actors.ads @@ -0,0 +1,42 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This unit exposes the root Actor abstraction for the Explore example, +-- meant to be used for active entities in the system, such as the robot +-- or the control station. +-- +-- This is useful to allow associations of arbitrary entities to other +-- software components, for instance to support port/actor ownership. + +package Actors is + type Actor is abstract tagged private; + type Actor_Ref is access all Actor'Class; + + procedure Kill (A : in out Actor'Class); + -- Called when something bad happened to/in A and it is + -- not to be relied upon any more. + + function Live (A : Actor'Class) return Boolean; + -- True until A is killed + +private + type Actor is abstract tagged record + Live : Boolean := True; + end record; +end Actors; diff --git a/testsuite/tests/I717-018/src/controls.ads b/testsuite/tests/I717-018/src/controls.ads new file mode 100644 index 000000000..1c768f6d1 --- /dev/null +++ b/testsuite/tests/I717-018/src/controls.ads @@ -0,0 +1,51 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This unit exposes the Robot command/control enumerals and the associated +-- Link abstraction for the Explore example. + +with Links; + +package Controls is + + -- Possible Robot Operational modes + + type Robot_Opmode is + (Cautious, -- The Robot won't execute potentially damaging commands + Dumb -- The Robot executes all the commands it receives + ); + + -- Commands the robot understands on its "robot control" input port. + + type Robot_Command is + (Nop, -- Do nothing + Opmode, -- Switch to new operational mode + Step_Forward, -- Step forward + Rotate_Right, -- Rotate 90 deg, counterclockwise + Rotate_Left, -- Rotate 90 deg, clockwise + Probe -- Probe field one step ahead and report + ); + + type Robot_Control is record + Code : Robot_Command; + Value : Integer; -- Possible argument associated with command CODE. + end record; + + package Robot_Control_Links is new Links (Data_Type => Robot_Control); +end Controls; diff --git a/testsuite/tests/I717-018/src/explore.adb b/testsuite/tests/I717-018/src/explore.adb new file mode 100644 index 000000000..4a8179912 --- /dev/null +++ b/testsuite/tests/I717-018/src/explore.adb @@ -0,0 +1,78 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This is the main unit for the Explore example, a sample application used +-- to introduce/illustrate a number of concepts in the Xcov documentation. +-- +-- This example features a fake robot exploring a field, controled through +-- communication channels by a inhabited control station off the field. See +-- the Overview dummy spec for a functional and organisational overview, +-- separated out to allow inclusion into the documentation. + +with Overview, Actors, Robots, Stations, Controls, Geomaps; +use Overview, Actors, Robots, Stations, Controls, Geomaps; + +with Robots_Devices.Dummy; + +------------- +-- Explore -- +------------- + +-- This is the main subprogram for this example. It instanciates the +-- actors, the communication links, and schedules the actors runs in a +-- simple cyclic fashion. +-- +-- The field and the robot disposition are implicitly created by the +-- Robot fake radar and locator devices, which both let it evaluate its +-- current situation. + +procedure Explore is + + -- Instanciate the Robot and Station actors + + R : Robot_Access := new Robot; + S : Station_Access := new Station; + +begin + Init (R, Robots_Devices.Dummy.Get_Hardware); + Init (S); + + -- Instantiate the Station/Robot communication Links and attach them + -- to their dedicated ports on both sides. + + declare + SR_Control_Link : Robot_Control_Links.IOlink_Access + := new Robot_Control_Links.IOlink; + SR_Situation_Link : Situation_Links.IOlink_Access + := new Situation_Links.IOlink; + begin + Robot_Control_Links.Connect + (Robot_Control_Outport (S.all), Robot_Control_Inport (R.all), + SR_Control_Link); + Situation_Links.Connect + (Robot_Situation_Outport (R.all), Robot_Situation_Inport (S.all), + SR_Situation_Link); + end; + + -- Then run just one cycle + + Run (S); + Run (R); + +end Explore; diff --git a/testsuite/tests/I717-018/src/geomaps.adb b/testsuite/tests/I717-018/src/geomaps.adb new file mode 100644 index 000000000..5fdc43345 --- /dev/null +++ b/testsuite/tests/I717-018/src/geomaps.adb @@ -0,0 +1,72 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with GNAT.IO; use GNAT.IO; + +package body Geomaps is + + -- Characters to printout for each possible kind of field Square, + -- and to represent an actor heading to a specific direction. + + Square_Image : array (Square) of Character + := (Ground => ' ', Block => '#', Water => '~', Unknown => '?'); + + Situ_Image : array (Direction) of Character + := (North => '^', West => '<', East => '>', South => 'v'); + + ---------- + -- Dump -- + ---------- + + procedure Dump (Map : Geomap; Situ : Situation) is + begin + New_Line; + for Y in Map'Range (Sqy) loop + for X in Map'Range (Sqx) loop + if Situ.Pos = (X, Y) then + Put (Situ_Image (Situ.Dir)); + else + Put (Square_Image (Map (X, Y))); + end if; + end loop; + New_Line; + end loop; + end Dump; + + ------------------ + -- Pos_Ahead_Of -- + ------------------ + + function Pos_Ahead_Of (Situ : Situation) return Position is + subtype Move_XYrange is Integer range -1 .. +1; + + type Move is record + Dx, Dy : Move_XYrange; + end record; + + XYmoves : constant array (Direction) of Move + := (West => (Dx => -1, Dy => 0), East => (Dx => +1, Dy => 0), + South => (Dx => 0, Dy => +1), North => (Dx => 0, Dy => -1)); + + XYmove : Move renames XYmoves (Situ.Dir); + begin + return (X => Situ.Pos.X + XYmove.Dx, Y => Situ.Pos.Y + XYmove.Dy); + end Pos_Ahead_Of; + +end Geomaps; diff --git a/testsuite/tests/I717-018/src/geomaps.ads b/testsuite/tests/I717-018/src/geomaps.ads new file mode 100644 index 000000000..ba229457a --- /dev/null +++ b/testsuite/tests/I717-018/src/geomaps.ads @@ -0,0 +1,76 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This unit exposes very basic Geographical Map abstractions for the +-- field in the Explore example. + +-- The field is very simply abstracted as a two dimensions array of +-- squares, each with an (x, y) position relative to (1, 1) for the +-- north-west corner. + +with Links; + +package Geomaps is + + ------------------------------ + -- Directions and Positions -- + ------------------------------ + + type Direction is (West, North, East, South); + + subtype XYrange is Integer range 1 .. 5; + type Position is record + X, Y : XYrange; + end record; + + ---------------- + -- Situations -- + ---------------- + + -- A Situation on the field encompasses an actor position, the + -- direction it is heading at and the kind of Square one step ahead + -- in this direction. + + type Square is (Ground, Block, Water, Unknown); + + type Situation is record + Pos : Position; + Dir : Direction; + Sqa : Square; + end record; + + function Pos_Ahead_Of (Situ : Situation) return Position; + -- Position of the square ahead the position in SITU, looking into + -- the direction held there as well. + + package Situation_Links is new Links (Data_Type => Situation); + + ----------------------------------------- + -- The field map representation per se -- + ----------------------------------------- + + type Geomap is array (XYrange'Range, XYrange'Range) of Square; + Sqx : constant := 1; + Sqy : constant := 2; + + procedure Dump (Map : Geomap; Situ : Situation); + -- Printout field MAP to standard output, and represent a robot + -- situation SITU on top. + +end Geomaps; diff --git a/testsuite/tests/I717-018/src/links.adb b/testsuite/tests/I717-018/src/links.adb new file mode 100644 index 000000000..4d36d895f --- /dev/null +++ b/testsuite/tests/I717-018/src/links.adb @@ -0,0 +1,100 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Links is + + ----------------------- + -- IOport operations -- + ----------------------- + + function Create_IOport + (Capacity : Natural; Owner : Actor_Ref) return IOport_Access + is + Ret : IOport_Access := new IOport (Capacity); + begin + Ret.Owner := Owner; + return Ret; + end Create_IOport; + + procedure On_Push + (Port : IOport_Access; Callback : Callback_Access) is + begin + Port.Push_Callback := Callback; + end On_Push; + + procedure Push (Item : Data_Type; Port : IOport_Access) is + begin + Push (Item, Port.Data); + if Port.Push_Callback /= null then + Port.Push_Callback.all (Port); + end if; + end Push; + + procedure Pop (Item : out Data_Type; Port : IOport_Access) is + begin + Pop (Item, Port.Data); + end Pop; + + function Full (Port : IOport_Access) return Boolean is + begin + return Full (Port.Data); + end Full; + + function Empty (Port : IOport_Access) return Boolean is + begin + return Empty (Port.Data); + end Empty; + + function Owner (Port : IOport_Access) return Actor_Ref is + begin + return Port.Owner; + end Owner; + + ------------------------ + -- IOlinks operations -- + ------------------------ + + procedure Flush (Port : IOport_Access); + -- Flush all the data available from Port through the Link to which it + -- is connected. This is called when data is pushed into Port after it + -- has been Connected (linked) to another one. + + procedure Flush (Port : IOport_Access) is + Link : IOlink_Access := Port.Link; + Data : Data_Type; + begin + while not Empty (Link.Outp) loop + Pop (Data, Link.Outp); + Push (Data, Link.Inp); + end loop; + end Flush; + + procedure Connect + (Outp, Inp : IOport_Access; Link : IOlink_Access) is + begin + Inp.Link := Link; + Outp.Link := Link; + + Link.Inp := Inp; + Link.Outp := Outp; + + On_Push (Outp, Flush'Access); + end Connect; + +end Links; diff --git a/testsuite/tests/I717-018/src/links.ads b/testsuite/tests/I717-018/src/links.ads new file mode 100644 index 000000000..2f40dfb5c --- /dev/null +++ b/testsuite/tests/I717-018/src/links.ads @@ -0,0 +1,124 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes IO Ports and Links abstractions to represent +-- interconnections between Actors. + +-- A Port is an abstract interface point into which data may be pushed +-- or out of which data may be popped, possibly buffered up to a specified +-- Capacity. A Link is an abstract communication channel which connects an +-- output Port to an input Port, all for a specific data type. + +-- Ports are meant to be attached to (owned by) an Actor to let it either +-- receive data (input ports) or emit data (output ports), not both. +-- +-- Links are meant to allow interconnections between actors via the ports +-- they own. The simple figure below illustrates such an interconnection +-- between +-- +-- a source actor Sa with an output port Op, and +-- a destination actor Da with an input port Ip +-- +-- +======+ +======+ +-- | Da Ip <---- Link ----< Op Sa | +-- +======+ +======+ +-- +-- Operation-wise, Links operate as data push propagators. In the example +-- above, data Pushed by Sa into Op becomes available for a Pop out of Ip +-- by Da at the other end of the Link. +-- +-- At this stage, a port may connect to at most one link and links support +-- only one to one connections. + +with Actors, Queues; +use Actors; + +generic + type Data_Type is private; +package Links is + + ------------ + -- IOport -- + ------------ + + type IOport (<>) is private; + type IOport_Access is access IOport; + + function Create_IOport + (Capacity : Natural; Owner : Actor_Ref) return IOport_Access; + -- The IO Port constructor. + + function Full (Port : IOport_Access) return Boolean; + -- Whether Port is full with respect to its Capacity. + + function Empty (Port : IOport_Access) return Boolean; + -- Whether Port is empty. + + procedure Push (Item : Data_Type; Port : IOport_Access); + -- Push Item on top into Port if it is not Full, + -- raise Program_Error and leave Port unchanged otherwise. + + procedure Pop (Item : out Data_Type; Port : IOport_Access); + -- Pop the oldest data Item out of Port if it is not Empty, + -- raise Program_Error and leave Item undefined otherwise. + + function Owner (Port : IOport_Access) return Actor_Ref; + -- Retrieve the owner of the port. + + ------------ + -- IOlink -- + ------------ + + type IOlink is private; + type IOlink_Access is access IOlink; + + procedure Connect (Outp, Inp : IOport_Access; Link : IOlink_Access); + -- Connect the output port Outp to the input port Inp via Link. Data + -- pushed into Outp is immediately popped out of it and pushed into Inp. + +private + + -- While they are intended to represent almost concrete concepts, ports + -- as we expose them much resemble queues, except for the support of a + -- callback on push. + + package Data_Queue_P is new Queues (Data_Type => Data_Type); + use Data_Queue_P; + + subtype Data_Queue is Data_Queue_P.Queue; + + type Callback_Access is access procedure (Port : IOport_Access); + + type IOport (Capacity : Natural) is record + Data : Data_Queue (Capacity => Capacity); + Push_Callback : Callback_Access; + + Owner : Actor_Ref; + Link : IOlink_Access; + end record; + + procedure On_Push (Port : IOport_Access; Callback : Callback_Access); + -- Register Callback as a subprogram to be called every time data is + -- pushed into Port. + + type IOlink is record + Inp, Outp : IOport_Access; + end record; + +end Links; diff --git a/testsuite/tests/I717-018/src/overview.ads b/testsuite/tests/I717-018/src/overview.ads new file mode 100644 index 000000000..73d47069a --- /dev/null +++ b/testsuite/tests/I717-018/src/overview.ads @@ -0,0 +1,153 @@ +------------------------------------------------------------------------------ +-- Couverture/Explore example -- +-- Copyright (C) 2008-2009, AdaCore -- +------------------------------------------------------------------------------ + +------------------------- +-- Functional overview -- +------------------------- + +-- This example implements software pieces involved in the following +-- imaginary situation: +-- +-- - A pilotless robot is set on a field to explore, where we expect to +-- find either regular ground or rock blocks. +-- +-- - An inhabited station off the field communicates with the robot to +-- control it and visualize the explored portions of the field. + +-- The robot is equipped with several devices: +-- +-- - a steering engine, able to have the robot perform a short step +-- forward or rotate 90 deg either way without advancing, +-- +-- - a front radar, able to probe the field characteristics (ground or +-- block) one step ahead, +-- +-- - a locator, able to evaluate the robot's position and orientation on +-- the field. +-- +-- The robot communicates with the station via two communication links: +-- +-- - a control link, through which the station sends commands for the +-- robot to execute (probe ahead, step forward, ...) +-- +-- - a situation link, through which the robot sends info about it's +-- current situation (position, orientation, field ahead). +-- +-- The field is modeled as a set of squares, each represented by a +-- single character to denote the square nature: +-- +-- '#' is a rock block, ' ' is regular ground, '~' is water +-- +-- '?' is a square yet unexplored +-- +-- '<', '>', '^' or 'v' is the robot heading west, east, north +-- or south, respectively. + +-- Below is a schematic illustration of the various parts involved +-- for a rectangular field delimited by rock blocks, a robot heading +-- south and an 'S' to materialize the Station: +-- +-- field view +-- ########## ?????????? +-- # # # <- control link ? # ? ?? +-- # v<==========================>S ?? R ?? +-- # ~ # situation link -> ? ? ?? +-- ########## ?????????? +-- +-- The Robot and Station active entities are both called Actors in this +-- world, and Links are attached to local Ports owned by these actors. +-- +-- The Robot runs in one of two modes: in Cautious mode, it wont execute +-- unsafe commands like stepping forward with a rock block ahead. In Dumb +-- mode it executes all the commands it receives. + +-------------------- +-- Sample session -- +-------------------- + +-- A user running the program is like sitting at the Station, able to type +-- commands for the Robot to execute and to receive feedback on the new +-- situation, from which the local view of the field is updated. Below is +-- sample session with explanatory comments in []: +-- +-- $ ./explore +-- +-- [The fake initial field is setup as a 5x5 area with blocks all around +-- and 1 in the middle, like +-- +-- ##### +-- # # +-- # # # +-- # # +-- ##### +-- +-- Robot is arbitrarily placed in the upperwest corner, heading east] +-- +-- 'C'autious mode, 'D'umb mode +-- 'P'robe, 'S'tep, Rotate 'L'eft/'R'ight, 'Q'uit ? P +-- +-- [Station asks for user input, user types "P" to probe ahead. +-- Robot answers with it's current situation: position (x=2, y=2), +-- looking east, square ahead is regular ground. +-- Station displays its current knowledge of the field]: +-- +-- ????? +-- ?> ?? +-- ????? +-- ????? +-- ????? +-- +-- [Probe command processing done, Next cycle ...] +-- +-- 'C'autious mode, 'D'umb mode +-- 'P'robe, 'S'tep, Rotate 'L'eft/'R'ight, 'Q'uit ? L +-- +-- [User asks "rotate left (counterclockwise)", station sends out +-- command followed by a Probe request. +-- Robot processes both requests and answers: position unchanged, +-- now heading north, square ahead is a block. +-- Station displays its current knowledge of the field]: +-- +-- ?#??? +-- ?^ ?? +-- ????? +-- ????? +-- ????? +-- +-- [etc until user requests 'Q'uit or crashes the robot by asking +-- it to step forward into a block, in Dumb mode] +-- + +----------------------------------- +-- General software organization -- +----------------------------------- + +-- The set of units and essential abstractions involved is sketched below - +-- units underlined, associated abstractions parenthesized). +-- +-- This set is a pretty straightforward mapping of the general concepts +-- involved, as described in the Functional Overview. Only "Queues" is a +-- pure support unit, offering the well known datastructure abstraction. +-- +-- See the package specs for extra descriptive details. +-- +-- ======= +-- Explore +-- ======= +-- +-- Geomaps (field Map, Situations + Situation_Links) +-- ======= +-- +-- Actors (Actor) Robots (Robot) Stations (Station) +-- ====== ====== ======== +-- +-- Links (IOports, IOlinks) Queues (Queue) +-- ===== ====== +-- +-- Controls (Robot_Control + Robot_Control_Links) +-- ======== + +package Overview is +end Overview; diff --git a/testsuite/tests/I717-018/src/queues.adb b/testsuite/tests/I717-018/src/queues.adb new file mode 100644 index 000000000..ad2cf4264 --- /dev/null +++ b/testsuite/tests/I717-018/src/queues.adb @@ -0,0 +1,74 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Queues is + + ------------------------- + -- Classical accessors -- + ------------------------- + + function Size (Q : Queue) return Natural; + -- The number of items available in Q + + function Size (Q : Queue) return Natural is + begin + return Q.Size; + end Size; + + function Full (Q : Queue) return Boolean is + begin + return Size (Q) = Q.Capacity; + end Full; + + function Empty (Q : Queue) return Boolean is + begin + return Size (Q) = 0; + end Empty; + + procedure Pop (Item : out Data_Type; Q : in out Queue) is + begin + if Empty (Q) then + raise Program_Error; + end if; + + Item := Q.Items (Q.Front); + if Q.Front = Q.Items'Last then + Q.Front := Q.Items'First; + else + Q.Front := Q.Front + 1; + end if; + Q.Size := Q.Size - 1; + end Pop; + + procedure Push (Item : Data_Type; Q : in out Queue) is + begin + if Full (Q) then + raise Program_Error; + end if; + + Q.Items (Q.Back) := Item; + if Q.Back = Q.Items'Last then + Q.Back := Q.Items'First; + else + Q.Back := Q.Back + 1; + end if; + Q.Size := Q.Size + 1; + end Push; + +end Queues; diff --git a/testsuite/tests/I717-018/src/queues.ads b/testsuite/tests/I717-018/src/queues.ads new file mode 100644 index 000000000..d7aa74c1a --- /dev/null +++ b/testsuite/tests/I717-018/src/queues.ads @@ -0,0 +1,49 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package offers a simple "bounded queue" data structure abstraction + +generic + type Data_Type is private; -- The elements data type +package Queues is + type Queue (Capacity : Natural) is private; + + function Full (Q : Queue) return Boolean; + -- Whether Q is full with respect to its Capacity. + + function Empty (Q : Queue) return Boolean; + -- Whether Q is empty. + + procedure Push (Item : Data_Type; Q : in out Queue); + -- Push Item at the back of queue Q if it is not Full, + -- raise Program_Error and leave Q unchanged otherwise. + + procedure Pop (Item : out Data_Type; Q : in out Queue); + -- Pop the top element off the head of Q into Item if Q is not Empty, + -- raise Program_Error and leave Item undefined otherwise. + +private + + type Data_Array is array (Natural range <>) of Data_Type; + type Queue (Capacity : Natural) is record + Items : Data_Array (1 .. Capacity); + Size : Natural := 0; + Front, Back : Natural := 1; + end record; +end Queues; diff --git a/testsuite/tests/I717-018/src/robots.adb b/testsuite/tests/I717-018/src/robots.adb new file mode 100644 index 000000000..2556c24d5 --- /dev/null +++ b/testsuite/tests/I717-018/src/robots.adb @@ -0,0 +1,142 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Robots is + + -------------------- + -- IOports access -- + -------------------- + + function Robot_Control_Inport + (R : Robot) return Robot_Control_Links.IOport_Access is + begin + return R.Robot_Control_Inp; + end Robot_Control_Inport; + + function Robot_Situation_Outport + (R : Robot) return Situation_Links.IOport_Access is + begin + return R.Robot_Situation_Outp; + end Robot_Situation_Outport; + + ---------------------- + -- Input processing -- + ---------------------- + + use Robot_Control_Links; + + function Unsafe (Cmd : Robot_Command; Sqa : Square) return Boolean; + -- Whether execution of CMD is unsafe with the SQA square ahead + + pragma Export (Ada, Unsafe, "robots__unsafe"); + -- ??? prevent inlining + + procedure Process_Next_Control (Port : Robot_Control_Links.IOport_Access); + -- Process the next control command available from PORT + + ------------ + -- Unsafe -- + ------------ + + function Unsafe (Cmd : Robot_Command; Sqa : Square) return Boolean is + begin + -- Stepping forward into a rock block or a water pit is Unsafe + + return Cmd = Step_Forward + and then (Sqa = Block or else Sqa = Water); + end Unsafe; + + -------------------------- + -- Process_Next_Control -- + -------------------------- + + procedure Process_Next_Control + (Port : Robot_Control_Links.IOport_Access) + is + Ctrl : Robot_Control; + Robot : Robot_Access := Robot_Access (Owner (Port)); + + begin + Pop (Ctrl, Port); + + -- In Cautious mode, the robot refuses to process unsafe controls + + if Robot.Mode = Cautious + and then Unsafe (Ctrl.Code, Probe_Ahead (Robot.Hw.Rad)) + then + return; + end if; + + case Ctrl.Code is + when Nop => + return; + + when Opmode => + Robot.Mode := Robot_Opmode'Val (Ctrl.Value); + + when Step_Forward => + Step_Forward (Robot.Hw.Eng); + + when Rotate_Left => + Rotate_Left (Robot.Hw.Eng); + + when Rotate_Right => + Rotate_Right (Robot.Hw.Eng); + + when Probe => + Situation_Links.Push + (Situation' + (Pos => Get_Position (Robot.Hw.Loc), + Dir => Get_Direction (Robot.Hw.Loc), + Sqa => Probe_Ahead (Robot.Hw.Rad)), + Robot_Situation_Outport (Robot.all)); + + end case; + end Process_Next_Control; + + --------- + -- Run -- + --------- + + procedure Run (R : Robot_Access) is + Control_Port : IOport_Access := Robot_Control_Inport (R.all); + begin + while not Empty (Control_Port) loop + Process_Next_Control (Control_Port); + end loop; + end Run; + + ---------- + -- Init -- + ---------- + + procedure Init (R : Robot_Access; Hw : Robot_Hardware) is + begin + R.Robot_Situation_Outp := + Situation_Links.Create_IOport + (Capacity => 1, + Owner => Actor_Ref (R)); + R.Robot_Control_Inp := + Robot_Control_Links.Create_IOport + (Capacity => 2, + Owner => Actor_Ref (R)); + R.Hw := Hw; + end Init; + +end Robots; diff --git a/testsuite/tests/I717-018/src/robots.ads b/testsuite/tests/I717-018/src/robots.ads new file mode 100644 index 000000000..ce231350e --- /dev/null +++ b/testsuite/tests/I717-018/src/robots.ads @@ -0,0 +1,62 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This unit exposes the Robot abstraction of the Explore example. +-- +-- A Robot is an active entity able to execute Robot_Control commands +-- received through an input Control port. Placed on a field, the Robot is +-- able to evaluate its current Situation (location, orientation, field +-- square ahead), and send this through an output Situation port. +-- +-- A Robot operates in one of several modes, as described in the Controls +-- abstraction. + +with Actors, Geomaps, Controls, Robots_Devices; +use Actors, Geomaps, Controls, Robots_Devices; + +package Robots is + + type Robot is new Actor with private; + type Robot_Access is access all Robot; + + function Robot_Control_Inport + (R : Robot) return Robot_Control_Links.IOport_Access; + function Robot_Situation_Outport + (R : Robot) return Situation_Links.IOport_Access; + + procedure Init (R : Robot_Access; Hw : Robot_Hardware); + -- Initialize robot R using the hardware Hw - setup ports and internal + -- devices + + procedure Run (R : Robot_Access); + -- Run robot R - process pending messages on input ports + + type Robot_Opmode is (Cautious, Dumb); + +private + + type Robot is new Actor with record + Robot_Control_Inp : Robot_Control_Links.IOport_Access; + Robot_Situation_Outp : Situation_Links.IOport_Access; + + Hw : Robot_Hardware; + Mode : Robot_Opmode := Cautious; + end record; + +end Robots; diff --git a/testsuite/tests/I717-018/src/robots_devices-dummy.adb b/testsuite/tests/I717-018/src/robots_devices-dummy.adb new file mode 100644 index 000000000..c532a699d --- /dev/null +++ b/testsuite/tests/I717-018/src/robots_devices-dummy.adb @@ -0,0 +1,219 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Geomaps; use Geomaps; + +package body Robots_Devices.Dummy is + + procedure Update_Square_Ahead (Device : access Dummy_Engine); + -- Update the square ahead after an engine action + + procedure Fake_Map (Map : in out Geomap); + -- Build a fake field MAP to perform pretended probes from, with + -- block borders and a few blocks within. + + ------------------ + -- Step_Forward -- + ------------------ + + procedure Step_Forward (Device : access Dummy_Engine) is + Sq : Square; + begin + Device.Env.Situ.Pos := Pos_Ahead_Of (Device.Env.Situ); + Sq := Device.Env.Map (Device.Env.Situ.Pos.X, Device.Env.Situ.Pos.Y); + + -- If we steped on Water or into a block, we're destroyed ... + if Sq = Water or else Sq = Block then + raise Program_Error; + end if; + + Update_Square_Ahead (Device); + end Step_Forward; + + ----------------- + -- Rotate_Left -- + ----------------- + + procedure Rotate_Left (Device : access Dummy_Engine) is + begin + if Device.Env.Situ.Dir = Direction'First then + Device.Env.Situ.Dir := Direction'Last; + else + Device.Env.Situ.Dir := Direction'Pred (Device.Env.Situ.Dir); + end if; + + Update_Square_Ahead (Device); + end Rotate_Left; + + ------------------ + -- Rotate_Right -- + ------------------ + + procedure Rotate_Right (Device : access Dummy_Engine) is + begin + if Device.Env.Situ.Dir = Direction'Last then + Device.Env.Situ.Dir := Direction'First; + else + Device.Env.Situ.Dir := Direction'Succ (Device.Env.Situ.Dir); + end if; + + Update_Square_Ahead (Device); + end Rotate_Right; + + ----------------- + -- Probe_Ahead -- + ----------------- + + function Probe_Ahead (Device : access Dummy_Radar) return Square is + begin + return Device.Env.Situ.Sqa; + end Probe_Ahead; + + ------------------ + -- Get_Position -- + ------------------ + + function Get_Position (Device : access Dummy_Locator) return Position is + begin + return Device.Env.Situ.Pos; + end Get_Position; + + ------------------- + -- Get_Direction -- + ------------------- + + function Get_Direction (Device : access Dummy_Locator) return Direction is + begin + return Device.Env.Situ.Dir; + end Get_Direction; + + ------------------ + -- Get_Hardware -- + ------------------ + + function Get_Hardware return Robot_Hardware is + Hw : Robot_Hardware; + Env : Environment_Access := new Environment; + begin + -- Create the hardware set. + Hw := (Eng => new Dummy_Engine, + Rad => new Dummy_Radar, + Loc => new Dummy_Locator); + + -- All devices share the same environment. + Dummy_Engine (Hw.Eng.all).Env := Env; + Dummy_Radar (Hw.Rad.all).Env := Env; + Dummy_Locator (Hw.Loc.all).Env := Env; + + -- We now initialize the environment with a dummy map and initial + -- position + Fake_Map (Env.Map); + Env.Situ := + (Pos => (X => 2, Y => 2), + Dir => East, + Sqa => Ground); + + -- Verify that the Sqa value is correct. + Update_Square_Ahead (Dummy_Engine (Hw.Eng.all)'Access); + + return Hw; + end Get_Hardware; + + ------------------------- + -- Update_Square_Ahead -- + ------------------------- + + procedure Update_Square_Ahead (Device : access Dummy_Engine) is + Posa : Position renames Pos_Ahead_Of (Device.Env.Situ); + begin + Device.Env.Situ.Sqa := Device.Env.Map (Posa.X, Posa.Y); + end Update_Square_Ahead; + + -------------- + -- Fake_Map -- + -------------- + + procedure Fake_Map (Map : in out Geomap) is + + procedure Block_Borders_On (Map : in out Geomap); + procedure Clear_Playzone_On (Map : in out Geomap); + procedure Setup_Blocks_On (Map : in out Geomap); + + procedure Block_Borders_On (Map : in out Geomap) is + X, Y : Natural; + begin + X := Map'First (Sqx); + for Y in Map'Range (Sqy) loop + Map (X, Y) := Block; + end loop; + X := Map'Last (Sqx); + for Y in Map'Range (Sqy) loop + Map (X, Y) := Water; + end loop; + + Y := Map'First (Sqy); + for X in Map'Range (Sqx) loop + Map (X, Y) := Block; + end loop; + Y := Map'Last (Sqy); + for X in Map'Range (Sqx) loop + Map (X, Y) := Block; + end loop; + end Block_Borders_On; + + procedure Clear_Playzone_On (Map : in out Geomap) is + begin + for X in Map'First (Sqx) + 1 .. Map'Last (Sqx) - 1 loop + for Y in Map'First (Sqy) + 1 .. Map'Last (Sqy) - 1 loop + Map (X, Y) := Ground; + end loop; + end loop; + end Clear_Playzone_On; + + procedure Setup_Blocks_On (Map : in out Geomap) is + X, Y : Natural; + + -- Setup ~ 1 block per five squares in both directions + + Wx : Natural := Map'Length (Sqx); + Wy : Natural := Map'Length (Sqy); + Nx : Natural := Wx / 5; + Ny : Natural := Wy / 5; + + Stepx : Natural := Wx / (Nx + 1); + Stepy : Natural := Wy / (Ny + 1); + begin + Y := Map'First (Sqy) + Stepy; + while Y <= Map'Last (Sqy) loop + X := Map'First (Sqx) + Stepx; + while X <= Map'Last (Sqx) loop + Map (X, Y) := Block; + X := X + Stepx; + end loop; + Y := Y + Stepy; + end loop; + end Setup_Blocks_On; + + begin + Block_Borders_On (Map); + Clear_Playzone_On (Map); + Setup_Blocks_On (Map); + end Fake_Map; + +end Robots_Devices.Dummy; diff --git a/testsuite/tests/I717-018/src/robots_devices-dummy.ads b/testsuite/tests/I717-018/src/robots_devices-dummy.ads new file mode 100644 index 000000000..c375a2eb3 --- /dev/null +++ b/testsuite/tests/I717-018/src/robots_devices-dummy.ads @@ -0,0 +1,71 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- Fake implementation of robots devices, using a static Map. + +package Robots_Devices.Dummy is + + type Dummy_Engine is new Robots_Devices.Engine with private; + + procedure Step_Forward (Device : access Dummy_Engine); + -- Make the Engines step forward + + procedure Rotate_Left (Device : access Dummy_Engine); + -- Make the Engines rotate left + + procedure Rotate_Right (Device : access Dummy_Engine); + -- Make the Engines rotate right + + type Dummy_Radar is new Robots_Devices.Radar with private; + + function Probe_Ahead (Device : access Dummy_Radar) return Square; + -- Use the radar to determine what kind of square is ahead + + type Dummy_Locator is new Robots_Devices.Locator with private; + + function Get_Position (Device : access Dummy_Locator) return Position; + function Get_Direction (Device : access Dummy_Locator) return Direction; + -- Use the locator to retrieve the current position and direction. + + function Get_Hardware return Robot_Hardware; + -- Get a complete hardware set based on the above devices. + +private + + type Environment is record + Map : Geomap; + Situ : Situation; + end record; + + type Environment_Access is access Environment; + -- Shared environment for all devices. + + type Dummy_Engine is new Robots_Devices.Engine with record + Env : Environment_Access; + end record; + + type Dummy_Radar is new Robots_Devices.Radar with record + Env : Environment_Access; + end record; + + type Dummy_Locator is new Robots_Devices.Locator with record + Env : Environment_Access; + end record; + +end Robots_Devices.Dummy; diff --git a/testsuite/tests/I717-018/src/robots_devices.ads b/testsuite/tests/I717-018/src/robots_devices.ads new file mode 100644 index 000000000..1eb4d6d67 --- /dev/null +++ b/testsuite/tests/I717-018/src/robots_devices.ads @@ -0,0 +1,71 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This unit offers a simple device access internal API to the Robot +-- abstraction of the Explore example. +-- +-- This API abstracts the capabilities of +-- +-- - a steering engine, able to have the robot perform a short step +-- forward or rotate 90 deg either way without advancing, +-- +-- - a front radar, able to probe the field characteristics one step ahead, +-- +-- - a locator, able to evaluate the robot's position and orientation on +-- the field. + +with Controls, Geomaps; +use Controls, Geomaps; + +package Robots_Devices is + + type Engine is abstract tagged null record; + type Engine_Access is access all Engine'Class; + + procedure Step_Forward (Device : access Engine) is abstract; + -- Make the Engines step forward + + procedure Rotate_Left (Device : access Engine) is abstract; + -- Make the Engines rotate left + + procedure Rotate_Right (Device : access Engine) is abstract; + -- Make the Engines rotate right + + type Radar is abstract tagged null record; + type Radar_Access is access all Radar'Class; + + function Probe_Ahead (Device : access Radar) return Square is abstract; + -- Use the radar to determine what kind of square is ahead + + type Locator is abstract tagged null record; + type Locator_Access is access all Locator'Class; + + function Get_Position + (Device : access Locator) return Position is abstract; + function Get_Direction + (Device : access Locator) return Direction is abstract; + -- Use the locator to retrieve the current position and direction. + + type Robot_Hardware is record + Eng : Engine_Access; + Rad : Radar_Access; + Loc : Locator_Access; + end record; + +end Robots_Devices; diff --git a/testsuite/tests/I717-018/src/stacks.adb b/testsuite/tests/I717-018/src/stacks.adb new file mode 100644 index 000000000..1d4c1313d --- /dev/null +++ b/testsuite/tests/I717-018/src/stacks.adb @@ -0,0 +1,61 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Stacks is + + ------------------------- + -- Classical accessors -- + ------------------------- + + function Size (S : Stack) return Natural; + + function Size (S : Stack) return Natural is + begin + return S.Size; + end Size; + + function Full (S : Stack) return Boolean is + begin + return Size (S) = S.Capacity; + end Full; + + function Empty (S : Stack) return Boolean is + begin + return Size (S) = 0; + end Empty; + + procedure Pop (Item : out Data_Type; S : in out Stack) is + begin + if Empty (S) then + raise Program_Error; + end if; + Item := S.Items (S.Size); + S.Size := S.Size - 1; + end Pop; + + procedure Push (Item : Data_Type; S : in out Stack) is + begin + if Full (S) then + raise Program_Error; + end if; + S.Size := S.Size + 1; + S.Items (S.Size) := Item; + end Push; + +end Stacks; diff --git a/testsuite/tests/I717-018/src/stacks.ads b/testsuite/tests/I717-018/src/stacks.ads new file mode 100644 index 000000000..89f6a0dbb --- /dev/null +++ b/testsuite/tests/I717-018/src/stacks.ads @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package offers a simple "bounded stack" data structure abstraction + +generic + type Data_Type is private; -- The elements data type +package Stacks is + type Stack (Capacity : Natural) is private; + + function Full (S : Stack) return Boolean; + -- Whether S is full with respect to its Capacity. + + function Empty (S : Stack) return Boolean; + -- Whether S is empty. + + procedure Push (Item : Data_Type; S : in out Stack); + -- Push Item on top of stack S if it is not Full, + -- raise Program_Error and leave S unchanged otherwise. + + procedure Pop (Item : out Data_Type; S : in out Stack); + -- Pop the top element off stack S into Item if S is not Empty, + -- raise Program_Error and leave Item undefined otherwise. + +private + type Data_Array is array (Natural range <>) of Data_Type; + type Stack (Capacity : Natural) is record + Items : Data_Array (1 .. Capacity); + Size : Natural := 0; + -- The number of Items currently available in the stack + end record; +end Stacks; diff --git a/testsuite/tests/I717-018/src/stations.adb b/testsuite/tests/I717-018/src/stations.adb new file mode 100644 index 000000000..321b7803e --- /dev/null +++ b/testsuite/tests/I717-018/src/stations.adb @@ -0,0 +1,162 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with GNAT.IO; use GNAT.IO; + +package body Stations is + + -------------------- + -- IOports access -- + -------------------- + + function Robot_Control_Outport + (Sta : Station) return Robot_Control_Links.IOport_Access is + begin + return Sta.Robot_Control_Outp; + end Robot_Control_Outport; + + function Robot_Situation_Inport + (Sta : Station) return Situation_Links.IOport_Access is + begin + return Sta.Robot_Situation_Inp; + end Robot_Situation_Inport; + + use Robot_Control_Links, Situation_Links; + + --------- + -- Run -- + --------- + + procedure Run (Sta : Station_Access) is + + procedure Update (Map : in out Geomap; Situ : Situation); + -- Update MAP from the info found in SITU, about the kind of square + -- probed ahead of a given position. + + procedure Update (Map : in out Geomap; Situ : Situation) is + Posa : constant Position := Pos_Ahead_Of (Situ); + begin + Map (Posa.X, Posa.Y) := Situ.Sqa; + end Update; + + procedure Process_Pending_Inputs (Sta : Station_Access); + -- Fetch and process pending Situation inputs - update and + -- dump the map of our local view of the field. + + procedure Process_Pending_Inputs (Sta : Station_Access) is + Situ : Situation; + begin + while not Empty (Robot_Situation_Inport (Sta.all)) loop + Pop (Situ, Robot_Situation_Inport (Sta.all)); + Update (Sta.Map, Situ); + Dump (Sta.Map, Situ); + end loop; + end Process_Pending_Inputs; + + function Control_For (C : Character) return Robot_Control; + -- Map user input character C to Robot_Control command, Nop if + -- the input isn't recognized. + + function Control_For + (C : Character) return Robot_Control is + begin + case C is + when 'p' | 'P' => + return (Code => Probe, Value => 0); + when 's' | 'S' => + return (Code => Step_Forward, Value => 0); + when 'l' | 'L' => + return (Code => Rotate_Left, Value => 0); + when 'r' | 'R' => + return (Code => Rotate_Right, Value => 0); + when 'c' | 'C' => + return (Code => Opmode, Value => Robot_Opmode'Pos (Cautious)); + when 'd' | 'D' => + return (Code => Opmode, Value => Robot_Opmode'Pos (Dumb)); + when others => + return (Code => Nop, Value => 0); + end case; + end Control_For; + + procedure Execute_Command (C : Character) is + Ctrl : Robot_Control := Control_For (C); + begin + + -- Push the command out to the robot, so that it executes, and + -- follow with a probe request so that a situation update gets + -- sent if this is not just what we asked. + + Push (Ctrl, Robot_Control_Outport (Sta.all)); + if Ctrl.Code /= Probe then + Push (Control_For ('P'), Robot_Control_Outport (Sta.all)); + end if; + + -- In case the Robot reacts instantly ... + + Process_Pending_Inputs (Sta); + end; + + begin + + -- In case something came in since last time ... + + Process_Pending_Inputs (Sta); + + -- Get the next command from the terminal line and map it to an + -- internal control code. + + Put_Line ("'C'autious mode, 'D'umb mode"); + Put ("'P'robe, 'S'tep, Rotate 'L'eft/'R'ight, 'Q'uit ? "); + + -- Dummy version here, for compilation and basic run check in + -- batch mode. + + end Run; + + ---------- + -- Init -- + ---------- + + procedure Init (Sta : Station_Access) is + + procedure All_Unknown (Map : in out Geomap); + -- Fill all the squares in MAP as Unknown + + procedure All_Unknown (Map : in out Geomap) is + begin + for X in Map'Range (Sqx) loop + for Y in Map'Range (Sqy) loop + Map (X, Y) := Unknown; + end loop; + end loop; + end All_Unknown; + + begin + Sta.Robot_Control_Outp := + Robot_Control_Links.Create_IOport + (Capacity => 2, + Owner => Actor_Ref (Sta)); + Sta.Robot_Situation_Inp := + Situation_Links.Create_IOport + (Capacity => 1, + Owner => Actor_Ref (Sta)); + All_Unknown (Sta.Map); + end Init; + +end Stations; diff --git a/testsuite/tests/I717-018/src/stations.ads b/testsuite/tests/I717-018/src/stations.ads new file mode 100644 index 000000000..39e800830 --- /dev/null +++ b/testsuite/tests/I717-018/src/stations.ads @@ -0,0 +1,51 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This unit exposes the Control Station abstraction of the Explore +-- example. The station gets user input about the next robot order to +-- transmit, sends them over the control link, receives the situation +-- report over the situation link and maintains a local view of the field +-- as it gets explored. + +with Actors, Controls, Geomaps; use Actors, Controls, Geomaps; + +package Stations is + + type Station is new Actor with private; + type Station_Access is access all Station; + + function Robot_Control_Outport + (Sta : Station) return Robot_Control_Links.IOport_Access; + function Robot_Situation_Inport + (Sta : Station) return Situation_Links.IOport_Access; + + procedure Init (Sta : Station_Access); + -- Initialize station STA - setup ports and local field view + + procedure Run (Sta : Station_Access); + -- Run a single command processing cycle on station STA + +private + type Station is new Actor with record + Robot_Control_Outp : Robot_Control_Links.IOport_Access; + Robot_Situation_Inp : Situation_Links.IOport_Access; + + Map : Geomap; + end record; +end Stations; diff --git a/testsuite/tests/I717-018/test.opt b/testsuite/tests/I717-018/test.opt new file mode 100644 index 000000000..6a57c8a7a --- /dev/null +++ b/testsuite/tests/I717-018/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage is supported in binary trace mode only diff --git a/testsuite/tests/I717-018/test.py b/testsuite/tests/I717-018/test.py new file mode 100644 index 000000000..cf6d84747 --- /dev/null +++ b/testsuite/tests/I717-018/test.py @@ -0,0 +1,33 @@ +""" +This test checks that a line with empty instruction range at the beginning of a +function is not associated to the function that precedes it in the text +segment. +""" + +import re + +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import Wdir, match +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +Wdir('tmp_') +gprbuild(project=gprfor(['explore.adb'], srcdirs='../src')) + +xrun(exepath_to('explore')) + +xcov(['coverage', '--level=branch', '--annotate=xcov+', + '--routines={}'.format(target_info().to_platform_specific_symbol( + 'robots__robot_control_inport' + )), + tracename_for('explore')]) + +thistest.fail_if( + not match(r'\.: function Robot_Situation_Outport', + 'robots.adb.xcov', + flags=re.DOTALL), + 'expect line with empty instruction range dropped') + +thistest.result() diff --git a/testsuite/tests/I812-011/main.adb b/testsuite/tests/I812-011/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/I812-011/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/I812-011/test.py b/testsuite/tests/I812-011/test.py new file mode 100644 index 000000000..2dd326117 --- /dev/null +++ b/testsuite/tests/I812-011/test.py @@ -0,0 +1,64 @@ +""" +Check that --output-dir maked gnatcov produce all annotated reports in the +output directory, none in the current directory. +""" + +import os.path + +from e3.fs import mkdir + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, list_to_tmp, match +from SUITE.tutils import gprfor, xcov + + +Wdir('tmp_') + + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(['main.adb'], srcdirs='..')), + covlevel='stmt', + mains=['main'], + scos=['obj/main'], + extra_coverage_args=['--level=stmt']) + + +# Check that the annotated reports are produced in the expected directory +mkdir('xcovs') +mkdir('htmls') +xcov(xcov_args + ['--annotate=xcov', '--output-dir=./xcovs']) +xcov(xcov_args + ['--annotate=html', '--output-dir=./htmls']) +xcov_report = 'main.adb.xcov' +html_report = 'index.html' +thistest.fail_if(os.path.exists('./' + xcov_report) + or os.path.exists('./' + html_report) + or not os.path.exists('./htmls/' + html_report) + or not os.path.exists('./xcovs/' + xcov_report), + 'reports in the wrong output dir') + +# Check that a proper error message is given when the output dir is not a +# directory. +p = xcov(xcov_args + ['--annotate=html', '--output-dir=./gen.gpr'], + out='gen.gpr.out', register_failure=False) + +thistest.fail_if(p.status == 0 + or not match(': cannot create output path ./gen.gpr: ', + 'gen.gpr.out'), + 'no error if output dir is not a directory') + +# Check that gnatcov can take a list of traces using the '@' prefix with the +# various forms to pass trace files on the command line, checking the output +# report in all cases. +trace_file = xcov_args.pop() +tlist = '@' + list_to_tmp([trace_file]) +for arg in [ + ['--trace=' + tlist], + ['-T', tlist], + [tlist] +]: + xcov(xcov_args + ['--annotate=xcov'] + arg) + check_xcov_reports('*.xcov', {'main.adb.xcov': {'+': {3}}}) + +thistest.result() diff --git a/testsuite/tests/I914-023/src/robots.adb b/testsuite/tests/I914-023/src/robots.adb new file mode 100644 index 000000000..1ac8c86ed --- /dev/null +++ b/testsuite/tests/I914-023/src/robots.adb @@ -0,0 +1,27 @@ +package body Robots is + + function Current_Mode (R : Robot) return Opmode is + begin + return R.Mode; + end; + + function Unsafe (C : Command) return Boolean is + begin + return C = Step; + end; + + procedure Run (R : in out Robot; C : Command) is + Mode : Opmode; + begin + Mode := Current_Mode (R); + if Mode = Cautious + and then Unsafe (C) + then + return; + end if; + R.Exec := R.Exec + 1; + end; + +end; + + diff --git a/testsuite/tests/I914-023/src/robots.ads b/testsuite/tests/I914-023/src/robots.ads new file mode 100644 index 000000000..2402ce292 --- /dev/null +++ b/testsuite/tests/I914-023/src/robots.ads @@ -0,0 +1,12 @@ + +package Robots is + type Opmode is (Cautious, Dumb); + type Command is (Nop, Rotate, Step); + + type Robot is record + Mode : Opmode := Cautious; + Exec : Integer := 0; + end record; + + procedure Run (R : in out Robot; C : Command); +end; diff --git a/testsuite/tests/I914-023/src/test_robots.adb b/testsuite/tests/I914-023/src/test_robots.adb new file mode 100644 index 000000000..957bcc2b5 --- /dev/null +++ b/testsuite/tests/I914-023/src/test_robots.adb @@ -0,0 +1,12 @@ +with Robots; use Robots; + +procedure Test_Robots is + R : Robot; +begin + Run (R, Nop); + Run (R, Rotate); + + if R.Exec /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I914-023/test.opt b/testsuite/tests/I914-023/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I914-023/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I914-023/test.py b/testsuite/tests/I914-023/test.py new file mode 100644 index 000000000..94cddc761 --- /dev/null +++ b/testsuite/tests/I914-023/test.py @@ -0,0 +1,44 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project = gprfor(['test_robots.adb'])) + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: +xrun(exepath_to('../test_robots')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_robots')], 'robots.out') + +# Expect something like ... + +# 17 +: if Mode = Cautious +# [...] +# fffc01e8 >: 40 9e 00 20 bne- cr7,0xfffc021c +# 18 +: and then Unsafe (C) +# [...] +# fffc0204 >: 40 9e 00 20 bne- cr7,0xfffc0238 +thistest.fail_if(not match('fff003dc v: 40 9e 00 20 bne', 'robots.out'), + 'expect Mode = Cautious always true') +thistest.fail_if(not match('fff003f8 v: 40 9e 00 48 bne', 'robots.out'), + 'expect Unsafe (C) always false') + +thistest.result() diff --git a/testsuite/tests/I914-023/test_robots b/testsuite/tests/I914-023/test_robots new file mode 100755 index 0000000000000000000000000000000000000000..f6709ccc951434caced164f02e0a2aaeb4feb903 GIT binary patch literal 75892 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 w>(Or9d&RioE>G7hro^OE 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 literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-ppc-beq-bt-x2/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-bt-x2/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt-x2/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-bt/gnu.ld b/testsuite/tests/I930-009-ppc-beq-bt/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-bt/src/cond.s b/testsuite/tests/I930-009-ppc-beq-bt/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-bt/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-bt/src/test_cond.adb new file mode 100644 index 000000000..9ee2290b1 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt/src/test_cond.adb @@ -0,0 +1,11 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-bt/test.opt b/testsuite/tests/I930-009-ppc-beq-bt/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-bt/test.py b/testsuite/tests/I930-009-ppc-beq-bt/test.py new file mode 100644 index 000000000..d7ac308ce --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt/test.py @@ -0,0 +1,35 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('fff01004 \\+: 41 9e 00 0c beq', 'cond.out'), + 'branch should be taken on both dir') + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-bt/test_cond b/testsuite/tests/I930-009-ppc-beq-bt/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..99032e11f47ce3b61383d21634c39f3693de83b4 GIT binary patch literal 73177 zcmeH~e{5UT701uB-8RqyW<)5^ZoIBxBqedvG#yUUtVz4l^oKf66ea}d<<)*ktR{A3 zyI`12+6GOam5HkC2NP{UTdS=@+xTn$blR#7G{*j5Qiq1bpo~rG;E$PUNELK_`=0m1 zaokPv|?_!waDuj`^32RUQgF2ro^N} zu9n5B*EP51caiuhzsmw&qrWCBOxUPSx`Mv2t~cVRR2S%>_F8OCZ(@(x1^qcs(~i?c z!u`JWC-6HWhUWRHZBH(DYn7JBi6;zcJ^Yp|sccwWPL7I<$W{NSWS5p#JtpPhqtZ5L zy0v6B-j>`a3wOM@`T)4S2Rj3Hrvtl4lid}8-Any565qF2VwINYiP?AE3sw7`^3Hu? z>e=C$I8xNENq;totsQpDG&YT+zcZdXv_V?7yY6Z9VeB(6=YK?E&sOgL;KZ)w!0T!!`Q8?l#lxqiMfuMBW?QS)ci?T;#d&e`w`Pvj zhET88$2W+98cTJ>_VUnC_uM|%&0?QdE9^}!mv~SsuNLsxw&B-a-Ii@QD{^?h#0TDp zj~;$jS}T>M<;sy2x)%%Y-syRcy1N~a~`*X-u&#OG_`%r%a$RBYSi0?|+ zJr1S#l7hQMe=sB5rVa(44WwkSvs%}lCmUrSgdB?YZ z>Q>jSymS3@btLuGp#$zIWjJ(7+WLp3CHbQ3R#*16_76$-Q(Ikk)i=QNr8VWDBhu1u z;x6Hw{!ZB3vaJ<$>^QVsI$*oFe>r%ZmexbV(uTDzz0Y9ShkSZ8zlNOjnQR3!*`LPy zWX0n0w>L@4A*Ro z^wRf6@V;nyda?JexZvBEw+8Q)E`7IL#-_D@kGTpqt$6?RT+T+%)Q)4>NPq-LfCNZ@ z1U>}>{BK}@@ol{fRYZZ_nzrJ$A#dK6=u7lG5Ng+UiX@5;PL=H47)u3zoCs$Hr|6U%sViAL{E|%={o}whMCW&-@YRbu#J|5MjFgMT_x-}iNOH6-)<}G0UdGx?8 zf~oea+wc>%a8Cyo)Gp%I;?QfCABIL4L%SZ#L%UOA#7{NY=rpuj7ut!Km};Nb)Q7f> z=sJ&jHkbMf?Y7Rd^Zj*UEo|YrU%^5Py87!913gxcNo_-aU&GwDi zAYYALecz7mwZQ+bCb?ddKwp5rKfvZ*I8%SmHrbzSl7G=8ha%v4`TSPo8E*~2D8E-i z1Jj@URmA)PrV(5i<@Z5YpSZW*0At))G+YAcjq4z{&)FNF^Ro2xdY*BsTU(&|kAKk)?abF*W+eSW7 zyq8U=z53vOMQ_3R-uv9&A5F}!Z**AN>%0+vbO-D;|6BZcqxYa*KZ2YL&dW9V|N8uV zqK^jmp%U1CH;}bV>i>Atc_-ak3ph$Fi0^saSIz%Su>V)c7mTG8=wC!U|ArjYGx{>( zL0u$xEKxAwQMKiJ;@ z1S+STEs5oSN|c;p$x7#QnS`C$ExRpi{({}@Or|F$Y)@-vY|C=WX=l2W&F6}iHEHYS z2|Jf|Ec|9Boq}ae?=2;I*YvEB@$PKi+gI$KveP&&5cK0E&{%hTdAQfwIDE%uONx{B z{f>s6-ecjbXVQ`4gT<0FWm(ugkr)fJYY@27xsCJ*<7}iwI^X@dFRVV%27iAa1Sz~b#h@Gz5X2EXnUvC0(Pj6 zw-_d)*@q!&j%f|ay_6in;8fNX0YY6au zr%=SrZi*ndFM(Iz+-I&2pjet#{i#6|fuVmreRId&ot^I$N$DjK?^&$x-dIm?{+$Pb z{B&J6SJry+xI-b_&6lw&T7|Iu&G*pSTXd{+!I~Vi@NY@u1JZoo{8YRG`v5O-g?e3j Q_&EMynR@`elCF{e0+WOW*8l(j literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-ppc-beq-bt/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-bt/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-bt/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/gnu.ld b/testsuite/tests/I930-009-ppc-beq-ft-x2/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft-x2/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/src/cond.s b/testsuite/tests/I930-009-ppc-beq-ft-x2/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft-x2/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-ft-x2/src/test_cond.adb new file mode 100644 index 000000000..1b60d0b41 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft-x2/src/test_cond.adb @@ -0,0 +1,11 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/test.opt b/testsuite/tests/I930-009-ppc-beq-ft-x2/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft-x2/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/test.py b/testsuite/tests/I930-009-ppc-beq-ft-x2/test.py new file mode 100644 index 000000000..cd9c23dd1 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft-x2/test.py @@ -0,0 +1,35 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('fff01004 v: 41 9e 00 0c beq', 'cond.out'), + 'branch should be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/test_cond b/testsuite/tests/I930-009-ppc-beq-ft-x2/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..05a87c49c51df1f26d5d833234ea9a9db8309be8 GIT binary patch literal 73177 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 MEYlC5Dd}qYFIRX5DgXcg literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-ft-x2/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft-x2/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-ft/gnu.ld b/testsuite/tests/I930-009-ppc-beq-ft/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-ft/src/cond.s b/testsuite/tests/I930-009-ppc-beq-ft/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-ft/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-ft/src/test_cond.adb new file mode 100644 index 000000000..ce4dd93fe --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft/src/test_cond.adb @@ -0,0 +1,8 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-ft/test.opt b/testsuite/tests/I930-009-ppc-beq-ft/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-ft/test.py b/testsuite/tests/I930-009-ppc-beq-ft/test.py new file mode 100644 index 000000000..cd9c23dd1 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft/test.py @@ -0,0 +1,35 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('fff01004 v: 41 9e 00 0c beq', 'cond.out'), + 'branch should be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-ft/test_cond b/testsuite/tests/I930-009-ppc-beq-ft/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..81cce4cb59e736feec2ef2e227a483dc798e54d4 GIT binary patch literal 73177 zcmeH~U2GiH701u)ZW5P-uoMd!l9owhiXEJd<2YrV#EqR0;(RFGia><`jVHU~colos z+TFlHcX1M<3e->$g?>U)f?S8Pd0 zhb)$bs@FAtIv66!)4`B=fkuCASlF;popgm`enW31PpdA}Lv60ajNZl`y9@erM$?Yd zMWX$I^?%`aNG#3s|Mq%fnLk}?iJf}flGdZ|$fDZDh1K-1SVMB<-)i|K)m4v5Z1A|W z_1pe*I-hJyACUPwUtWC(++OLMl;nYhlBl)BPffk=U#PoxS9cu{TYW~phCx>C=IGCc zXSTy`sh+9+`#O`EBO9e6j-1xjWLQr+k0+!^w5E8|_pYu{?p!My`v}S>$-t$Mc4;w!xP8@G`r*S&#GY9g_G9 zxL<%iF<0L|jJ)>U;P(&UzTKAkj!dQ>-QL$?`Soq_Q}Da!@FQY9^-ZxhiGTjn+T-j$ z?(i?ZiTg@rrA+(nN#E`CFCIN3Ey{QD*V|jQZtLImeVmuXcxUqI=>gQM^|6g&p>|SV zzN0#D+&^~!c2n4AYK6V&Ws(eQWoiMRZ5w}O>b7*_S&^d$CAt2se~P&3d9{ZEAL?&C@<$vN;=2NNkAbOx;q-rE82UM@ ztU@+z2RBRN;Bt|v-(fr_3GMUs7kz*7_&J$;YbY~#%y6=551s!p&gh(c`rJTxM*Ea9 z*JlbfLF`Krx2?4b&v~tuzc{hsz{p5_#r4(n30Z_Qd+XbWGQ$s#?5(e`zf&K&IFWwI z_tWo4OMP!oYrXT@iP}qRs`ZYc%;!4gih5@zQ{R@!EbGK`@?K#72OZsKsudnE7?HiDlPj2)5Ro?*5SJqSqj!8?Ojb6ezeVwqmX?rW` z*l}c;bij6D-!kwxBdtdUr44Ic+RtFvi+s8@zowk@nQR3!Ihe)!WckACw>L}65zMjY zq;l65*+B=qvdYYvOipkw@|(8Uy@T+FMU3;iHQOKsD`w$z5L_MKvN`L-PP2js9>*BFN{eQ$*Ci#8 zz{b8ge7AJzyX7)At$q9KRj_Hr`=|SIHhQKG9LtLYNPq-LfCNZ@1R4Z_Z)JSL4NENe zb`kSGT*WI_oNTd>OS!o{u->|BaJPM@S1RX=g>`nORJ3nN^`^S-w>x^eSFi2vUA=Z? zZ(pZ~B_^Ww`Sq0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq z5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH* zAOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8} z0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq z5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH* zAOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8} z0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq5+DH*AOR8}0TLhq z5+H&9Spr)(Z(e72Y~6K7r`?v95?p^&QyJMtSvbXLU+-+w{Mf;XiZ>szL zNV~REBvpQ3yyEV`y;2J9qtUG7mA#6jDqa=8rDD#lxRUZlosp6|?qP#2^x(dyT*fU> zmn&{|Us+OElT@}iKJFDNpN{Ghm|Gb0{b{}Fkc9q(ms!C43mBnY3{xG8+wc=z(Vh-0 zs9nsTPC~Cko{fxfkLKqtnQ4U1TR>W2$4;r9Sl9grW1evANV=WVdaW zUEr?^Yta>*`xPv-V5q+?u`m*inAA4%_chD|yM*0s>};&eT#?;9Skk%XjhV@}&&-1# z)#oGKsB*tejn*3e26slifExICq zk=(ck{a`j58-F@D4$jOZsISo*|By`$A%qNV;|ubMA2z^vr)%QXU)h3^fVZLgkzHf_^q5s`; zIdm^B2W{9cO;>|pX|5&Mgn#?Uaz z@587*NwePqWArR8Gy(M1HIUn9?5)q6ER9~zvu^gM6Bi&3eb&TpeHn9e+2+@}6Z^F; z;dxeF;z51jAM4h)pf{F~aklk+e|mvo1{pl8lQZ#YJ*}U>enpeNGt%1dr}|g@>G?m0 zzBP>J59lxT-xkVmNUUM6=l=!%n)ChpY<+Bjc^cp#;1jzB@o0Q@;4iiW@peEC&x@t! z?B6jvzt~;i1#@{m++T_MA5lUPn~M4uGUAIp(X=1=#h#v{{}J|Q;O{Eb6OD=9oy8;e zI^wNBKMU98eIy|p1$N$%7=M#Stw{ONg`|LfuYUqU|yxf1GMMm)cV9M&`bD&kQd3B-%%A^ryRXPfl@ zgkJNp0)67DF#fRL6W7Ck>x_Nk7RWmxw*==WoZ0=7*x!^t@<|+m{RY^F^++J!`TuH? zpGQ8oLLN2#@OQmbSy?KMr;6faC-!$cX2r}`&ze6tGU1FDb6%+Os`-jI!KXyUD_5Ls zv5-r-xjnMSab_>LE4{Jo=%{P7Zq9WaubTBHD*0le>^NhtZXR_DSzARN6mLnPW2Qxf71b6Txdj4RFy}PQL6^s^I759+(|^^D#Xk z#SqP9ii^F`x27|iD+R7h+chYd%7j2nBEj6iR<`4a(3vO|_u_-qDd+V&1aT?J%VgFlARL+RT@cj!Og83Y*%T}aHOktMYYOl_uT(~7&xs)Hm(Xiq9x&Gj zP#jIG@zfxS&@gDvz}$29kcbXKcj5za`BN$lQJlQZWS%0AAt>^}6)%z4(V^<^eP%T_gVnj4t@- literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-ppc-beq-ft/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-ft/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-ft/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/gnu.ld b/testsuite/tests/I930-009-ppc-beq-npg-bt/gnu.ld new file mode 100644 index 000000000..8bb68d779 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-bt/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000) - 8; + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/src/cond.s b/testsuite/tests/I930-009-ppc-beq-npg-bt/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-bt/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-npg-bt/src/test_cond.adb new file mode 100644 index 000000000..9ee2290b1 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-bt/src/test_cond.adb @@ -0,0 +1,11 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/test.opt b/testsuite/tests/I930-009-ppc-beq-npg-bt/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-bt/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/test.py b/testsuite/tests/I930-009-ppc-beq-npg-bt/test.py new file mode 100644 index 000000000..7f5119962 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-bt/test.py @@ -0,0 +1,35 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('fff00ffc \\+: 41 9e 00 0c beq', 'cond.out'), + 'branch should be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/test_cond b/testsuite/tests/I930-009-ppc-beq-npg-bt/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..7ac9b8ed5d394fdb0cf2e8ba677ba8c63b02ff59 GIT binary patch literal 73169 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 literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-npg-bt/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-bt/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/gnu.ld b/testsuite/tests/I930-009-ppc-beq-npg-ft/gnu.ld new file mode 100644 index 000000000..8bb68d779 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-ft/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000) - 8; + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/src/cond.s b/testsuite/tests/I930-009-ppc-beq-npg-ft/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-ft/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-npg-ft/src/test_cond.adb new file mode 100644 index 000000000..ce4dd93fe --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-ft/src/test_cond.adb @@ -0,0 +1,8 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/test.opt b/testsuite/tests/I930-009-ppc-beq-npg-ft/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-ft/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/test.py b/testsuite/tests/I930-009-ppc-beq-npg-ft/test.py new file mode 100644 index 000000000..f62e19437 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-ft/test.py @@ -0,0 +1,35 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('fff00ffc v: 41 9e 00 0c beq', 'cond.out'), + 'branch should be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/test_cond b/testsuite/tests/I930-009-ppc-beq-npg-ft/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..0286d3750bfcf29c4151a0de917590e938f99969 GIT binary patch literal 73169 zcmeH~e{5UT701uBoi?MTHN!%IvhlKpk(9(u({wmZvnDO2PFr=E2y6(@%ZvSzSWRrp zcEK>4v<;d-D-%`O4<=fQMk|e>ZAg{2KbW>^1C6min8eWd2imbo2sF)`HmQQrx9`30 zJ;!l7X-xZP+V@HKy?gFC_uO+n=RD_Se#f5MjF2JqD)jC4SXS2?(bG!j>!H$DWKnOz-t30{tk!hk z^u_&p>A!JHilO5EzrCJlcWaf_(5c4_i5)#BD=S-9loJzTB<0F;mCTy*`bQ-+a$MSm zOt+TEM5BoVvTV=G8xDcnD+BWqJ+ML|mDcd7h4_=-Q`|9dPZ6m-}ztcimAE{zT>($FN$$){^{B<>J@uzs~D)ARM+k< z4-v6r5k)p+6G<3=f{Yc{xrYvP8l4B&{vxw56yq~{WAJz zlhsbj?5g?y!GG$AV(6 z-YL`sv0sn4O;s!ZoYyLui}@`FrlzXvt}7=_$V!~qU)_})n|OF?y1LH%W;J;+pLof2 z6X&G0I^7qmc3qRNytJ`g?M#k+s!Oh@c8!fyN5{t6yYQa8=h;7bv+GvgyCz>vj(u_X zko%%yIQ*it4U9-@;$_#ZuIq~p3`@_GqprLDtKj*{#`5qnX&o@pOE_ns3pO|HilL63 zN7|(mwkrnO!Q+g?j*Lhf*1A$|5jY^ zY|NYe-J#1q5{pr1&jXF~e9LtLYNPq-LfCNZ@1jPGB#<$yqguHJS z(f_-ZoMOpJ<+ACxot^}zoqI>d%{!e!F_X(~HpdD%^Oksjy!U>yv#)oLUSiR0&N;=RJ?(5ZSvwLS0TLhq5+DH*AOR8}0TLhq5+H&9h(PAVE35pC2A&MP z`-&3Bn#5DNxj83W`gkOUR#VQq7%zrb#EiJj-K z8*9N8ocjeVv|=cK-C|%w>M<$Xz~7fJ_v|8OueLL>vUmk{_h3oQRo@#sJOh8~sfyrT#?=ptv^);sN{s6;R33``ComfPT^obyr&tTFz+WKO zpI$%c&DzGTdB?$-o_O`udhH*wt|0`Up{adAZtB*5$~@WL-y5L-sT_hD7SLYcwyS2y#h{;dt_>IqFt}j#HjXSYl)x|&0 zs7lzY5By`@_&W635;D#{}KKg^Zm6S^AlsQ66JUuX^D?OZ%BlxW(& zdue{5yTA+P^1Q#l6!bsxg(9>N^smP!^hCpcO1sL`8VYqGN6K-pW2mKYkDR`f~{o(l1`i4iO zqs|-ghxfqVg#Vkoc*A$2UI!p2{PVI+{=c#`pYS7oKaBhK-|}TuCguNR(|OM!pR@2E z@#A~Jt+lB9U-$R_4EkBfC13wC;`t3^zkkB7A|Ayff_U*hgx`SvY=i!9(5w0zo<6eL zkKgb2$aU}^TeOed0(lSQR`2|XwX|O%`y28{K9NJP-vWET9uefb?C%Zo^T_8`$TQj> z{;n5FJ%!v{JSSEvzrWYgD|)_R$^5~oyfv3gJHE;(XG&supAsdfSh7;NY&veICuP#I zmM+*m&TMLC#@1RpZCjR8PC5BfCYLQ*)~u~I&)C_NW8t2jbqbc1-(QONZS37B(>y=&#WWG2Z|+U&a$w3CX;o% zh^-xBS?a^an$6j1%+#ms|_)Yq-7bH6nUU)ZM?GuccjW6#3K z(&x*+m7@v)z%^t<>tusC`n);5(e~$+1?*5Cy%;2;vJXO3k*m%2WUf#WRRxugCg7LS z%g#F>lPx)g!v1`z$z;Z{^OnvN!K;Mo;DWQPOwlTp!Ou=Vur&0>WBPoGKAOuE7kh(m zO=~7y@LcJ(t5eXG@qy?>yt#(0*v=tBD__V>(axg@ej-53#d!FQT_?|@c91# literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-npg-ft/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-ft/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/gnu.ld b/testsuite/tests/I930-009-ppc-beq-npg-tk/gnu.ld new file mode 100644 index 000000000..8bb68d779 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-tk/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000) - 8; + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/src/cond.s b/testsuite/tests/I930-009-ppc-beq-npg-tk/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-tk/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-npg-tk/src/test_cond.adb new file mode 100644 index 000000000..67f39c8be --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-tk/src/test_cond.adb @@ -0,0 +1,8 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/test.opt b/testsuite/tests/I930-009-ppc-beq-npg-tk/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-tk/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/test.py b/testsuite/tests/I930-009-ppc-beq-npg-tk/test.py new file mode 100644 index 000000000..17d5f4e4e --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-tk/test.py @@ -0,0 +1,34 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project = gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr'); + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in + +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== + +# We seek the reported status of the associated cond branch instructions +# directly: +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('fff00ffc >: 41 9e 00 0c beq', 'cond.out'), + 'branch should be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/test_cond b/testsuite/tests/I930-009-ppc-beq-npg-tk/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..5f5d0c42725da586731d0628c45e7eacadeabe2e GIT binary patch literal 73169 zcmeH~e{37&8ONWqoi=L=HN!%IvT<3%h)d$8X*!&yS(BDhr>(k71U3Zda!L(HyXpH^AB!eWJvuANepwtt%XkE*(b&oV_MfIrbMJu zE|--`uh!g}H$d01U-R-)kF|ycaUdn$;B2QQD`QYSO`YpFI|KZ8uLo&YQDUtCLBAqQF zkb44sa=~@S9*l0TTyG|l$mKDdY}C3cnHD3p`lFT<*0z`u9&a~$8uf^OcS^#~<9QzX zNV9%$9Chux&K(@WbC)UA-J_#}IPLwdhFcv8pM>944<8oeiEoIpP26*z)E=?_u-m=x z2ARrjv?{*yzuFa3eH(b&brCO$ad!U6+7S8`dt|E^=$%y8?k*1< zci%Yxy9Mmiy~5sPyF~q7>0ZER+ty#|zFoWZjL6Z05*>Im`qiUPORQ2^Q?49aTOM%D zRY_Y~5wj!6Atj;V^~b>cxC|-Xz?;%G;37XiN96RE`GvR3;5dkLwHfl@{P*80H-P$)hk^W7!0r(+6)>#*JBGfWGm4eZ zrtRQ%i5y%jvhZ7sXCXVc3NibtyHca$4^B>1*O}k0rY_7SUv%B% zS!u0K^~S34tL7>%ZY))bvx*s2L-SuAw&zCorhmJ{WzlpPiIQ?~9B;(-J!}ENxipQs)^A`%q7hs;{9Y^-jjXOb({;d$M+A`CHqi^$6zJb3$=f zy$E`^+x_U=pn2|c#0c4O`N@$H^?QYb_3_ulj_;7eSrL^3{21zNJw9S~Dj9y1zD4QB z(#tPgy!KY(nta#ygB%TIn;bW#GH!J25u?jB)&UthfNH>KRuVSQ8Cp(SY9MR0wh2JBtQZrAl^4JzTL(pu(L%h*d?=9B8x6_)+rY4DQC0E-jM(akN^pg011!)36KB@kN^pg015m@1P;INuJAV+cwU8} zp4a)$c075J011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@ zkN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg z011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!) z36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36KB@kN^pg011!)36Q}5 z9D$wNw{JE(ckaC{ZuTYm6C2Imo(-FN`Zj#Q?3~OO%$<9O$IQ_}-n=Q%m*}}S&~A#0 zB#QUVmh1^UO9k&a9n1<&(J4uy^O`hvD0WFjeF7C~m>_55wllG^cm;NMVM)zZ-I(cm`}N$rDV-Wu zU?8S{8PUID<^&?1fj{+BP4F(`$_GVS9))lj#x)qK4#oac7!CfejzRTvtOZx#FOcg` z?>y+u+QzMU;owY9y#8vv_77S25Q5Lp)V?6Mcuwo`vL<=CFY7+QUh#w%@WcgK)lk16 zuYgd`J0kAiAz$X!!X3Vm%I|9A`Rs<@=UE>H8mRlIuP3 z^#%BQ1~zvgxQhRDll`+z@=u%OKm|-Fvgk1g+lR

Ql{WN|I`*jWePD`xrPw8KAYs-EHeaz42 z_ik`gE0K@N&-DC-)*#=`#dx7))BfE{ z>kHihUND#E{Qafi{G(ndLJPt9_4tGyYuJzaLQgj7e~A4l_*;#B;$Y(JF5wY+4f&R! zAM)e9f%wls9`)sSp+5z==J5{w6ZNPBqnzO34${GVuw_blo;1OE{} zzvtari>m)MfB!F_pMhNR^)Dfx-$C}zPxuw&qj*G+FW!gn>(HNR(EkH^)qlg&M^^j! z`{zA!4gALz?ISlq-UGSSiyyI;o|nk}hWb%Y0nrxDH<)W?gjv2MM2xYyb?eCrNNiZk{-j!HYd&%#&Fj3dSSiX~^(vaowPn{&L3 ztsP=n>chsG$=eys)whmc?NrV#Sync$Z9GrK?EQ|^*R7m$uQdZ-*ryk>xojzG&%nsi z@#SOHs8RrM4H?-wxgd{TZ;o%Y{d39!cIb~@42n_J2Pvw|)n>6zXqC#~XJ_tPntEfHUZ0|m<`T`t-r!r) zn$8qFSNho1Dd^7lKy)GAT*FpuXOW>bSIAG{gVoBZk5~ph6SkxRcmq$3Etxria6O#8TjYL_v)E@%+(7hmMW|M)*uVt z&^w-X3+j7wfyX)eBsD=0PAoSJy4JwO%~VPylzwCG3h;A!vW|Ikff{ q9V=b1W+pBCThjP~G@m!G6y0DC;6<*`uZx3E;UAX87f`o!qx=g+5&9Vb literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-npg-tk/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-npg-tk/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-nt/gnu.ld b/testsuite/tests/I930-009-ppc-beq-nt/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-nt/src/cond.s b/testsuite/tests/I930-009-ppc-beq-nt/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-nt/src/get_false.adb b/testsuite/tests/I930-009-ppc-beq-nt/src/get_false.adb new file mode 100644 index 000000000..598a2fdb6 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/src/get_false.adb @@ -0,0 +1,4 @@ +function Get_False return Boolean is +begin + return False; +end Get_False; diff --git a/testsuite/tests/I930-009-ppc-beq-nt/src/get_false.ads b/testsuite/tests/I930-009-ppc-beq-nt/src/get_false.ads new file mode 100644 index 000000000..94abd0fe4 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/src/get_false.ads @@ -0,0 +1 @@ +function Get_False return Boolean; diff --git a/testsuite/tests/I930-009-ppc-beq-nt/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-nt/src/test_cond.adb new file mode 100644 index 000000000..e33d5ce90 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/src/test_cond.adb @@ -0,0 +1,12 @@ +with Get_False; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Get_False then + if Cond (1) /= 2 then + raise Program_Error; + end if; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-nt/test.opt b/testsuite/tests/I930-009-ppc-beq-nt/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-nt/test.py b/testsuite/tests/I930-009-ppc-beq-nt/test.py new file mode 100644 index 000000000..36ad3bde8 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/test.py @@ -0,0 +1,35 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('fff01004 -: 41 9e 00 0c beq', 'cond.out'), + 'branch should not be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-nt/test_cond b/testsuite/tests/I930-009-ppc-beq-nt/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..86a52dfc618151393982ae1c7c8c7051c9efdff4 GIT binary patch literal 73320 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 literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-ppc-beq-nt/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-nt/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-nt/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/gnu.ld b/testsuite/tests/I930-009-ppc-beq-tb-x2/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb-x2/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/src/cond.s b/testsuite/tests/I930-009-ppc-beq-tb-x2/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb-x2/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-tb-x2/src/test_cond.adb new file mode 100644 index 000000000..d5b06cd17 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb-x2/src/test_cond.adb @@ -0,0 +1,17 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/test.opt b/testsuite/tests/I930-009-ppc-beq-tb-x2/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb-x2/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/test.py b/testsuite/tests/I930-009-ppc-beq-tb-x2/test.py new file mode 100644 index 000000000..d7ac308ce --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb-x2/test.py @@ -0,0 +1,35 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('fff01004 \\+: 41 9e 00 0c beq', 'cond.out'), + 'branch should be taken on both dir') + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/test_cond b/testsuite/tests/I930-009-ppc-beq-tb-x2/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..440f7d9744bd2e582be0b85249c516f48d8120c9 GIT binary patch literal 73177 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 lweW9A^8?b_Z+8m!WA-gOVRvRT zGw5h%TwqP3DK--94;w*E3u&!s>tFqcrX{VW*8X7=YHDH?YnxF0qhnJOqLkO~x$nK% z*?}gS_)p{aCU@>V_ndp~IiGXi+qYAjcid{lENQfuv}11h_1Nned&Ro?ZlmiJTN2VK zSIT_V>zZE=x=8Y5&}B}b(O(-DHf&TU%fmjmp|_GJRTt`^HZ3uux3R}w4*gl9S&Gv| zqWyvOC-6HYmgf1XZI3VZ>(#c{iN`EyKk}9=sBV~FNe_!PBv<^Snp;>|`G~{@k4Z)Fwna3yNjqCXSHwiI@YG&YT+uPd23yg}Nw`~E5PLF}_H<$p*L&s6XI;KZ)%n|^ib z!xMuCWqAG5BE!c;I_HQ$?vC{7Y2V-VP;zbcMmv>8ERW*}0FwpjELdE1{x3sVTW?Ez zc(L8xtjGEH3`zWXjOU?GwCekZk=NcE{Qd!q+ia~1pF>I^srb@ zep9TC;-CAt_Bi`b+x-i#VO*iClxe>`<-1+}g(Ih=P5Dm!W?Q?~cir2*kMok~Z%sW_ zA3(j@AKf4pYAm%S+baXd{ImOEH;sL!R@j?fEXlA|rWWwovEkRIZi_aY5jk=|lIz|` z4j*|&+N;%tmFm$Ym36+oAni&U&RiPBFobKg@+g=elL6JOdqXs*87h;syRcy1O00F`*Xxq&#OKd_)vfAkU!$E5Z~pn zdlXCs4D0`kVd&?KvI^OB9M~j@14~4ve~N_XQW*}Ml#aeZX-mK8`?X~~?R^8X;)$)kzw#U4`O@mjz)@-I zvvHSjPG1*nZraw4I(8mjES<2O-?tb%PD%UWLFvHSa=p)B*o%C+HNU2u^qFi2GdYmO z`((-d%C|R3+hNSH=eTm$T0}M6?*HdpzkTjXoDp-oiY^8>!YuU+qGF9&WUIY z@MG!SdSa{HsWSYievayQW#?VEcAsYWo~a$jvXKA@kN^pg z0112w2n652_%<7sSny3E=6|!YS1LQ%LVhIWj_d}9EjtHy*>`xwQm&9+YiEiD`<7I1 zs{1~>v!{F2n(p3JYgY93b%{9ci0d>qi)_u?<8G;JXUE)p*0b?DGVT>cGDUC18_ngt z5!|0X3sqXtC?V2u;RO$YSvb!5&xfqON(X8l|yt1UqUIo9!!iZaTCFPAd zqeXYZ!v z9@@n))qZ6Mexerb>BNHC#r%2_dhPPV$OvO(*Nu5(cT%k6$tD|}Ms{l>I}saG?X#Nt z(6$j>=W%0mvA@V}>nyv#-*T))EjsrrSZG66f6K)}Pc&ju+sNP7Fc0h!cDJ#!u`<&l zySuTZbIltwlW(7y2S2LQelP2l)!W9^VlfX?)iq-g=XKBlJ<7Ro@F)@2WPH zH-!0W?CSegbkjoryISN%O+tMU{{8@)yWvdzJ=0?UY>WJh7C90D&*bx4k*CcXf>D02 zLd4a&b{mXuR?iuLY!+8FP`vp-tLitsRHSG2LzrkN~zW$BaMxT`!hb6blonf;id9ecg^(G4oZk<`0ZcIunHv zFI0JzTv?ppQ=;sZ%1*YBA4$0*yJffI%wBL;c;nfzG1q9_5!Z3NO4ge!=L-3f;f`|@CqvvKgY&5o4D z-FrO^JG-go;22-ymy~74qw=37IXPrIp>bU$T8>3N6Jw{0B{2t(R%qPj-FtSZ?t`rY5_ac z$1Fz4X!cQv8o6$EcNdCf(JE*@hCo=#AiLmzT)ylTi~APpgV#l{_a~bjC*={9DrefVAGXAQe;K0N_QgP_K&* P--CZxW*$IO($(@`;}Hg_ literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-ppc-beq-tb/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-tb/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tb/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/gnu.ld b/testsuite/tests/I930-009-ppc-beq-tk-x2/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk-x2/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/src/cond.s b/testsuite/tests/I930-009-ppc-beq-tk-x2/src/cond.s new file mode 100644 index 000000000..4c7ef8f76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk-x2/src/cond.s @@ -0,0 +1,14 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + beq %cr7,.L1 + # != 0 + li %r3,2 + blr +.L1: + li %r3,120 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beq-tk-x2/src/test_cond.adb new file mode 100644 index 000000000..865176e19 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk-x2/src/test_cond.adb @@ -0,0 +1,11 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/test.opt b/testsuite/tests/I930-009-ppc-beq-tk-x2/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk-x2/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/test.py b/testsuite/tests/I930-009-ppc-beq-tk-x2/test.py new file mode 100644 index 000000000..174b10077 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk-x2/test.py @@ -0,0 +1,35 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('fff01004 >: 41 9e 00 0c beq', 'cond.out'), + 'branch should be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/test_cond b/testsuite/tests/I930-009-ppc-beq-tk-x2/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..27488031298406fa749085f20dad6aa25a6bcc4b GIT binary patch literal 73177 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: 41 9e 00 0c beq', 'cond.out'), + 'branch should be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-tk/test_cond b/testsuite/tests/I930-009-ppc-beq-tk/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..07a300e51bee275b2d5e43cc4b0c676ffbb44ba5 GIT binary patch literal 73177 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 A0ssI2 literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-ppc-beq-tk/test_cond.gpr b/testsuite/tests/I930-009-ppc-beq-tk/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beq-tk/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/gnu.ld b/testsuite/tests/I930-009-ppc-beqlr-bt/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-bt/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/src/cond.s b/testsuite/tests/I930-009-ppc-beqlr-bt/src/cond.s new file mode 100644 index 000000000..c8f3e4d00 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-bt/src/cond.s @@ -0,0 +1,12 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + li %r3,120 + beqlr %cr7 + # != 0 + li %r3,2 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beqlr-bt/src/test_cond.adb new file mode 100644 index 000000000..9ee2290b1 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-bt/src/test_cond.adb @@ -0,0 +1,11 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/test.opt b/testsuite/tests/I930-009-ppc-beqlr-bt/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-bt/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/test.py b/testsuite/tests/I930-009-ppc-beqlr-bt/test.py new file mode 100644 index 000000000..4a779024b --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-bt/test.py @@ -0,0 +1,36 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if( + not match('fff01008 \\+: 4d 9e 00 20 beqlr cr7', 'cond.out'), + 'branch should be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/test_cond b/testsuite/tests/I930-009-ppc-beqlr-bt/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..1a400e3b035ceef0707fc384659135aa87a6f065 GIT binary patch literal 73173 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 literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-ppc-beqlr-ft/test_cond.gpr b/testsuite/tests/I930-009-ppc-beqlr-ft/test_cond.gpr new file mode 100644 index 000000000..01a049244 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-ft/test_cond.gpr @@ -0,0 +1,14 @@ +project test_cond is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + + package linker is + for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); + end linker; + +end test_cond; diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/gnu.ld b/testsuite/tests/I930-009-ppc-beqlr-tb/gnu.ld new file mode 100644 index 000000000..44702fd76 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tb/gnu.ld @@ -0,0 +1,159 @@ +OUTPUT_FORMAT("elf32-powerpc", "elf32-powerpc", + "elf32-powerpc") +OUTPUT_ARCH(powerpc:common) +ENTRY(_start_rom) + +__stack_size = 64 * 1024; +__heap_size = 1024 * 1024; + +SECTIONS +{ + + /* First instruction is fetched at this address */ + . = 0xfff00100; + .reset : AT (0xfff00100) + { + KEEP(*(.reset)) + } + + /* Start of ROM. */ + . = 0xfff00200; + + /* Code sections, merged into text segment: */ + .text : + { + __text = .; + *(.text .text.* .gnu.linkonce.t.*) + *(.gnu.warning) + . = ALIGN (0x1000); + *(.text_cond) + } = 0 + + /* Read-only sections, merged into rodata segment: */ + .rodata : + { + . = ALIGN(4); + *(.rodata .rodata.* .gnu.linkonce.r.*) + *(.rodata1) + *(.got2) + . = ALIGN(4); + } =0 + + /* init, ctors and dtors sections. Assume we really need them + when they happen to be generated, so KEEP to prevent garbage + collection of per-object pieces. */ + + .init : { KEEP(*(.init)) } + .ctors : { KEEP(SORT_BY_NAME(*)(.ctors)) } + .dtors : { KEEP(SORT_BY_NAME(*)(.dtors)) } + + .eh_frame_hdr : + { + __eh_frame_hdr = .; + *(.eh_frame_hdr) + } + + .eh_frame : { KEEP (*(.eh_frame)) } + .gcc_except_table : { *(.gcc_except_table .gcc_except_table.*) } + + __rom_end = .; + + /* Leave room for exception vectors. */ + . = 0x2000; + __sdata2_load = __rom_end; + .sdata2 : AT (__sdata2_load) + { + __sdata2_start = .; + PROVIDE (_SDA2_BASE_ = 32768); + *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) + . = ALIGN(4); + __sdata2_end = .; + } + .sbss2 : + { + __sbss2_start = .; + *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) + . = ALIGN(4); + __sbss2_end = .; + } + __data_load = LOADADDR(.sdata2) + SIZEOF(.sdata2); + __data_start = .; + + .data : AT(__data_load) + { + __data = .; + *(.data .data.* .gnu.linkonce.d.*) + KEEP (*(.gnu.linkonce.d.*personality*)) + SORT(CONSTRUCTORS) + *(.data1) + PROVIDE (_SDA_BASE_ = 32768); + *(.sdata .sdata.* .gnu.linkonce.s.*) + . = ALIGN(4); + } + + __data_end = .; + + .sbss : + { + __sbss_start = .; + *(.dynsbss) + *(.sbss .sbss.* .gnu.linkonce.sb.*) + *(.scommon) + __sbss_end = .; + } + .stacks : + { + . = ALIGN(8); + __interrupt_stack_start = .; + *(.interrupt_stacks) + __interrupt_stack_end = .; + + /* Separate stack per CPU */ + __stack_start = .; + + __cpu0_stack_start = .; + . = . + __stack_size; + __cpu0_stack_end = .; + + __cpu1_stack_start = .; + . = . + __stack_size; + __cpu1_stack_end = .; + + __stack_end = .; + } + .bss : + { + __bss_start = .; + *(.dynbss) + *(.bss .bss.* .gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(4); + __bss_end = .; + + . = ALIGN(8); + /* One heap */ + __heap_start = .; + . = . + __heap_size; + __heap_end = .; + + _end = .; + } + + /* DWARF 1.1 and DWARF 2 */ + .debug_aranges 0 : { *(.debug_aranges) } + .debug_pubnames 0 : { *(.debug_pubnames) } + /* DWARF 2 */ + .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } + .debug_abbrev 0 : { *(.debug_abbrev) } + .debug_line 0 : { *(.debug_line) } + .debug_frame 0 : { *(.debug_frame) } + .debug_str 0 : { *(.debug_str) } + .debug_loc 0 : { *(.debug_loc) } + .debug_macinfo 0 : { *(.debug_macinfo) } + /* SGI/MIPS DWARF 2 extensions */ + .debug_weaknames 0 : { *(.debug_weaknames) } + .debug_funcnames 0 : { *(.debug_funcnames) } + .debug_typenames 0 : { *(.debug_typenames) } + .debug_varnames 0 : { *(.debug_varnames) } + /DISCARD/ : { *(.note.GNU-stack) } +} diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/src/cond.s b/testsuite/tests/I930-009-ppc-beqlr-tb/src/cond.s new file mode 100644 index 000000000..c8f3e4d00 --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tb/src/cond.s @@ -0,0 +1,12 @@ + .section ".text_cond" + .align 2 + .globl cond + .type cond, @function +cond: + cmpwi %cr7,%r3,%r0 + li %r3,120 + beqlr %cr7 + # != 0 + li %r3,2 + blr + .size cond, .-cond diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/src/test_cond.adb b/testsuite/tests/I930-009-ppc-beqlr-tb/src/test_cond.adb new file mode 100644 index 000000000..81411b26a --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tb/src/test_cond.adb @@ -0,0 +1,11 @@ +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/test.opt b/testsuite/tests/I930-009-ppc-beqlr-tb/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tb/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/test.py b/testsuite/tests/I930-009-ppc-beqlr-tb/test.py new file mode 100644 index 000000000..4a779024b --- /dev/null +++ b/testsuite/tests/I930-009-ppc-beqlr-tb/test.py @@ -0,0 +1,36 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if( + not match('fff01008 \\+: 4d 9e 00 20 beqlr cr7', 'cond.out'), + 'branch should be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/test_cond b/testsuite/tests/I930-009-ppc-beqlr-tb/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..b2cce0d8ce82e306a33b9bb16d55935fb31aaefd GIT binary patch literal 73173 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: 4d 9e 00 20 beqlr cr7', 'cond.out'), + 'branch should be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beqlr-tk/test_cond b/testsuite/tests/I930-009-ppc-beqlr-tk/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..efdb4222a5f9c263f54410b8d6ecc0c356a636ec GIT binary patch literal 73173 zcmeH~e{3Ap5yxlmE{U52ILZkHLd&Kx#SYHJah!5a;>J!0aS}ImMW981)|>M>KE=MX z?k;f9JDkL*3Tmi`LVr+^04j-8irOL}HGfdGQ41=ie^7~{@(+YUB?^Dkt*8`1$o4yL zchBcbDuL90s(x2`w{PCen>X{B+4XvA%izsc%#!*QlN9EbKNEWn_inK+|Ax_Zi!BLh zlS^fh>UGVZ35H1WR4`;-pwV9&7B*~DCmrFKU)Nj7Q>qK~P@5|;tGBVo?tuOsqiMzI zBGLZ9`oHiyAeQF&e|tT$%%7>Y#7;hJN$TiZvbef&Q6)1hG9Z`yt(sd}S@ob)`j5+! zUfZ9^ND~MSE6=J`ZM8~ zt+2aB&s6_C?a9F-8>MB3@1MrVVV`|5{{xbEvU>N2CwFDv^s7@Jo$Nm-!yBFu89pJ> zHctd{XQafqSeOs(e;-CGr_Bi`b zJN)yn)((i>wUx*#)z2yIyL=v1sr?PSL-16PW|Zp z3i@X)WD9Z)KJE(lX0SKeu=mH|UJLtQ?X^Xe#e?m3oAS{7OrK3Httbb?&<0<(ubS3) z{Ii<#)Y~6brnRrpqnb1HgBX{?-=8C{dS3PZz=!%c2?jbN0Fr4{M3`0L> zlvT)P$$`z1IIvt~`u7-5OG5j6{dwP?I{vOqy)iJQs`sD$Db8r0di>qK@Ql`J zWv?vYVQ2xhW(?XwG~%aGEc~2oY`I5J}@-=!04XZ3j2Gtf%B7@ z7koeSmbBFNbfs$TS58)6SW~IB4Gev*T^82bhlXm~hK824<2iXRuz&Oh-><%R1R3Fq{*!{++! zDb%s;$TDez?V_G#;Bi_~NBU(6);hGG!LS?obZUMLIq5T*0y8;~#rtIWqRMwSOUn_= zvFC(x*IGn1+~I$Gw%0y;Db9$w?eg;@+w^^f#`@%I;gTC`S9Zbq3)kLkT$3M!eh{OjwwYmDs>4?6pjaKgErX?J8dEVu6L-(}zC6-&87ew{s3EZ8@uyVITb*lk^%tJijR zuU@;dyQf{maYtOIzFA~j-X3>LWjj0O=ChuS-;r^zC^A&^M!eBn-W##KO4ge!!>?U* zb0sXeWm|47c}4pIiw=9jE0x?m-a5M;JtrhU0wh2JBtQZrKmsH{0wh2JBtQb6l)#}6 z{Dq;dh5MBldcQWjFTzQ zcc(k=iL`6mMbf2vC(7<_+{?w_J{HZ2UdbyJ>g)ZE8 zmrA$=>QdRw?k!0gYm&|uCMLXm`O^_y3Udo%zCWWk9g@(W@G=XSe*q)3i(#tc(iDE8 zE85eB1+|O$GfC)m$WxIK?vY(5=8@egv6816Y;+pgt&8kLY)o~`xzvYVn=o`9H#Qgg zi|n?|u?zflU@f|$bH9p(77X>*Ar?lW9+TQe{=SZRV3)8vjh&5^*(K|h$y#>Srsj)OBZ3F>R~#y@0JLkJ;5+xUV!FK}9y=Qqgi@|m`=^`aUo^>)2zVx+--@Q*( zL&GS)52N}d&3+4v(X+VF1khVoKyID2w?1#OGpzxh z+P`CNezDuZ3+D1nxW63rKca*pHXZdZWW*PHq+vhui#^_?{|WXF!rx`6CmIvIJBLT? zRm59{zArrQb)5eUH{LI;b>4_SJ_!3(*k2#S8@~hf+7CGso|kX(|INAi#1Do2uq(9xekg01)c=X5 z^PWaNXW%~(ybdd^FL^i zpFuu1K^`;y@OQmfURf+mqzmF?C--$aX2r}`&zavhI_XRlM!ZnvRdQugF*wpYmrst9N%dBCe;FVsE=8UlF{s=5H)h$?CvfU z%c51#d<=oGltFgE0l9qHD;D=nmYYn*Ja^JDc_MgCs17bV%gL3Tas~X{k$dNc-grz` zNHIink>X-+^sVWPjT8e{rtRt!Ol3kKCXrxnU@O}RMCeQw3w!Xv>g4sK)p2GEsM>~V zp_Lq`OM True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-a-ft/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-ft/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-a-ft/src/test_cond.adb new file mode 100644 index 000000000..fdab3b4e7 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-ft/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/test.opt b/testsuite/tests/I930-009-sparc-be-a-ft/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-ft/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/test.py b/testsuite/tests/I930-009-sparc-be-a-ft/test.py new file mode 100644 index 000000000..d94232269 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-ft/test.py @@ -0,0 +1,37 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('40001404 v: 32 80 00 02 bne,a', 'cond.out'), + 'branch should not be taken') +thistest.fail_if(not match('40001408 -: 90 10 20 02 mov', 'cond.out'), + 'delay slot should not be executed') + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/test_cond b/testsuite/tests/I930-009-sparc-be-a-ft/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..40231af199dc82e44ef30973e97b14af36d45b70 GIT binary patch literal 72983 zcmeI$Z)_WP83*v^E(!5OC!E$D6&c$VG@3}Qn|3Lr%cNbGhIU$;hPFc*LY$rW+E{h$ zU^{C%0XwH@32aR1RHnQra2?w;x`KdJ2oR7m+809%6^Xq-Dk#%HDiero8WVq3!uPp9 zsS|}4V=tyn->aV7J-`3=xjUch2YPpX+%OGU*i12TY}jEzrx>dngTqd-#E>>gNR!s% zpJ*Emk<>|%a|mhHa&8o$00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZ zKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt z00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun z0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP z3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbF zC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epy zpa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZ@XizP zlOpX&X{=qeP(EsCq7j@r9oJ0Ho@k7Lq5kEov457a-Jcf82@g(9Y#2Lg{#CH(m ze#TfiGygXo>nOfkOe8mAY}>3&+EVjGnnW5WlD-v})jz8fNy`{dWNsdpjB%{ZGmdun ziQ1HH>NwhOJYk!jpAplORXE3{@npvP`5Id;BA!D$kN6GZ1;p!t=d`wwd{>y2iDr_fyvNsiY*;LLF?8 zsZ$^Jy~uCjw~*OxU;fzbC$4n+$-i{_Yfkrzd~?0ke7e&zYA2;-uG_a>>-O9J(d~D< z(d~EDuHbrHfX}Zyd3sBxx%O52hI*Hv9&P4Y(XSQ#TG6l7@0xAJJgu0g74x+EYt%f5 zXe@QpzQ?eiNccB@5$n+FJ_+Y9wTroQolDpCU_07vvYIDbq-pXxYhK6l{PT^tzOU-~ z^qSUPGqe7h)vq7FAvL|+WKDWcWMri$*SA|D$Wv#p&op>X_y)=vaJ=Ho>L71K-uUt@ zRtotF-PbO7u<;w;>Nwv@TM2*tMyWj{srvQBeleTSW9_ePCX$&Gc%F=B+pun!)#~b(PPPWe;UBHjXhAfDMOu=29)Gti!#!Np?_!@=J#Sfo>pSh^|@$27i3}m2-?Fa z*tGu`@Yul@5?eH1RqP;*^UtIG=TKrr?ctSDpLqPQ*mrnAhp7LfXg`aB8>9B$ zL;Fc>fcf?Oo(u1yh53HFWWGP3eZMvjeT;v{pEu$7CO(f-b?0NI;^!`^w=ln6qt0-C z^OnW)nH$kRz8+YQdB@`Qn>&|`e-H9DjMo;f$Aq75_;L{VnVJgsrqCt2f6NO}cl6i$)%-Q; zhfo&IH}m9 zBiTX$Z85K#Tk_@_aIU?Lf>&7~t1q^pY;n+a@Hba*%R#x*zjx1WXW#y9d-sduxMTUM zEYtMPOd}lOZ=d5;f3QuQ+?R#Y+mh=I?g}?^mUfaD;tfo8G?d@qEiH8kVvD zfSWHKjLsY5hv$6Pr*HznRKZcWZhemj;3MVIL7lyr9d^a(*|n$VZf9SAZ?DdXs}ikO z<+MUa&~DM#y0F1QY4DJ9pzMBj)GZDk3D45i(}N0XLYs&S_mh6bkZKtec!d`*=i;vv tPS{Nx9b(~|#+^8W-rde_;0J4nz)JvEweW&2oKvrqwI;YI%Yf~Z{{oVGf5iX* literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-a-ft/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-ft/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.c b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.s b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.s new file mode 100644 index 000000000..ba3b613aa --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/cond.s @@ -0,0 +1,17 @@ + .section ".text.cond" + .align 4 +pad_cond: + .fill 3064 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + mov 120, %o0 + bne,a .LL2 + mov 2, %o0 +.LL2: + jmp %o7+8 + nop + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/test_cond.adb new file mode 100644 index 000000000..fdab3b4e7 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.opt b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.py b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.py new file mode 100644 index 000000000..fd9438597 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.py @@ -0,0 +1,17 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild('test_cond.gpr') +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('40001ffc v: 32 80 00 02 bne,a', 'cond.out'), + 'branch should be not taken') +thistest.fail_if(not match('40002000 -: 90 10 20 02 mov', 'cond.out'), + "delay slot shouldn't be executed") + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/test_cond b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..316dfd3979e53b86fb969c425b16a4ac6c025d0a GIT binary patch literal 76072 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 btswy~0$kPN3p#gB-BQw;=%OqFwnzR8mkfmL literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.c b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.s b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.s new file mode 100644 index 000000000..ba3b613aa --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/cond.s @@ -0,0 +1,17 @@ + .section ".text.cond" + .align 4 +pad_cond: + .fill 3064 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + mov 120, %o0 + bne,a .LL2 + mov 2, %o0 +.LL2: + jmp %o7+8 + nop + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/test_cond.adb new file mode 100644 index 000000000..adfefbe24 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.opt b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.py b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.py new file mode 100644 index 000000000..3a0798a2b --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.py @@ -0,0 +1,15 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild('test_cond.gpr') +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('40001ffc >: 32 80 00 02 bne,a', 'cond.out'), + 'branch should be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/test_cond b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..afa57ce4d79210cfea1caf683918d69acc30ee36 GIT binary patch literal 76072 zcmeI$Z*1Il83*vkPP*JgC!GG7Dy6LM5Njf3*Q`xZStjBB3GK8r&Dw$(n&xwIZgcA8 zF5F$#bOOznrdrP3Q&Lo6rcbFC_n)UP=Epy zpa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+ zfC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O z0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC z1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo z6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)U zP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=EpypumSu zAhbl3ED6`fB5^oqF;1jPYK_`=HymSs$H# zZlx{N^K1LmJim1*J}(@( z-u&v$?;_6cvFq*pcs}#*cY4r+p9kds{=Uc8&xiZBxM3#s&j$5H!E31F4j$5`dmddOdlZhS{n;u<&Le(-cn$Gu#OsLPA>Kgz0r6+VUlD&p zTt@r@@h`-?h$R>Y>zQn_q~n-1J*j3>n*$k_FcpMBL+jbucXf?xQ6H|bCr?^psf9W? zB9kXS9tMfu+;1V%U7`G`D@?uF69O|LHse<2I9^Z2xmK(jX4Sg-1^HxhAMZT3?(CI^ zXJ==09PHmo_7@kMV`g2r{q1$(PRtSger27V{g1ZeMga;?fC3bt00k&O0Sa9I0>RU^ z;CsvHhCod0&D!@3J@blRuDAomLN@JX`;qVH-LlXAoL?&EiiJDvzEaWtWV$omama4n z&~Zlx{%^Rwb7Px`>t#K6uCvJZR_;1_&*oF^OMdf(uKVvDd*GMZcXWL7-!p;k7u$Ah z+jghjx}*2AZFXmRV|tUFOtI14Uo6?tN)}rHW>1$74^_N=>?@^sKUh1e_@fm`XT6Fi z>HczA(gVezA-_;rYytnftOZs2mFWgY+eBZU?7SW(TPoSF#a?S09I=PRK!~hH)V5l? zbtuqdZFfQpgoH@vHXTE^c7z^xXd+QN`BZcq|Is>)W<*0=q$T!w{M|H{$89v#w&q;9 zaqC_9nMBhj#LWmzEX0k7y76v9JM%4+)ixbx(alLp(K%}4r~@|S(Y(lUu2Ft%{5aRS z4JVr37}aCMM;vJ$#~$-X`3mGyIPOXETO3)o6vr2mydC*P9A}bz3&wMBtecM4i~g}? zoZpA_=v=z#`h2vXiL$tU811*$<)g^+b@@@u*It)Dj=aA9n@JsDXD{RU%!2$U3-Z?; zS$;Js)AjzoR&T}qFJb;@y;i)w%UJ*YXw!%r0PT$%kRL~GAjkO_tLOJOZVQrvcsyf0 z<~xZZYgycXt24j82jdN*s5XATBU6*w1oPwi8AFb&xq@_6(!bwYOW9|JXZf`cDzV3X?kJVm>NqrmU*K5`p&u^yZ&u4B%|6$at2i9ZmoWFka-UZ`7 zfZRs&)?_{K(+xioM*b%5ujO~4z)9wNWWKlgwFUVT81M6FpZJ-lL;|EW5A#JQ%A)n* z{xDx!u>Mz)`)O%1|2d2|fiB7YW4@MjPkhbaqCSJNc)mfelr8yXzaqs4{nGw?@sNxZ zvdPi@{78AwJ(MeCi-*cG;&&xpG_ex0hC(}QeqZmFU3YJj zp6=bf?w;-)C^}H^DsF$t_YS({idU*g$s0%*yn#WS7M76p_sXE}4JQrs znJn&}Ewv>@U2_llf(Ne}Nj$>dxJ`HO_S$@lEE=e_3(@cA3I`GZj31x#-Cw{7L{mja z@w)W^AIT4wiU)M|f;Z%gyRB#UwtL*YecjzUBQ8&}UX{}d9YMP#W9z~O^2LFJ?*5Yh z#Sy True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-a-nt/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-nt/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-a-nt/src/test_cond.adb new file mode 100644 index 000000000..fdab3b4e7 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-nt/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/test.opt b/testsuite/tests/I930-009-sparc-be-a-nt/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-nt/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/test.py b/testsuite/tests/I930-009-sparc-be-a-nt/test.py new file mode 100644 index 000000000..4a2ab07c8 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-nt/test.py @@ -0,0 +1,38 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('40001404 v: 32 80 00 02 bne,a', 'cond.out'), + 'branch should not be taken') + +thistest.fail_if(not match('40001408 -: 90 10 20 02 mov', 'cond.out'), + 'delay slot should not be executed') + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/test_cond b/testsuite/tests/I930-009-sparc-be-a-nt/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..40231af199dc82e44ef30973e97b14af36d45b70 GIT binary patch literal 72983 zcmeI$Z)_WP83*v^E(!5OC!E$D6&c$VG@3}Qn|3Lr%cNbGhIU$;hPFc*LY$rW+E{h$ zU^{C%0XwH@32aR1RHnQra2?w;x`KdJ2oR7m+809%6^Xq-Dk#%HDiero8WVq3!uPp9 zsS|}4V=tyn->aV7J-`3=xjUch2YPpX+%OGU*i12TY}jEzrx>dngTqd-#E>>gNR!s% zpJ*Emk<>|%a|mhHa&8o$00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZ zKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt z00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun z0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP z3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbF zC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epy zpa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZ@XizP zlOpX&X{=qeP(EsCq7j@r9oJ0Ho@k7Lq5kEov457a-Jcf82@g(9Y#2Lg{#CH(m ze#TfiGygXo>nOfkOe8mAY}>3&+EVjGnnW5WlD-v})jz8fNy`{dWNsdpjB%{ZGmdun ziQ1HH>NwhOJYk!jpAplORXE3{@npvP`5Id;BA!D$kN6GZ1;p!t=d`wwd{>y2iDr_fyvNsiY*;LLF?8 zsZ$^Jy~uCjw~*OxU;fzbC$4n+$-i{_Yfkrzd~?0ke7e&zYA2;-uG_a>>-O9J(d~D< z(d~EDuHbrHfX}Zyd3sBxx%O52hI*Hv9&P4Y(XSQ#TG6l7@0xAJJgu0g74x+EYt%f5 zXe@QpzQ?eiNccB@5$n+FJ_+Y9wTroQolDpCU_07vvYIDbq-pXxYhK6l{PT^tzOU-~ z^qSUPGqe7h)vq7FAvL|+WKDWcWMri$*SA|D$Wv#p&op>X_y)=vaJ=Ho>L71K-uUt@ zRtotF-PbO7u<;w;>Nwv@TM2*tMyWj{srvQBeleTSW9_ePCX$&Gc%F=B+pun!)#~b(PPPWe;UBHjXhAfDMOu=29)Gti!#!Np?_!@=J#Sfo>pSh^|@$27i3}m2-?Fa z*tGu`@Yul@5?eH1RqP;*^UtIG=TKrr?ctSDpLqPQ*mrnAhp7LfXg`aB8>9B$ zL;Fc>fcf?Oo(u1yh53HFWWGP3eZMvjeT;v{pEu$7CO(f-b?0NI;^!`^w=ln6qt0-C z^OnW)nH$kRz8+YQdB@`Qn>&|`e-H9DjMo;f$Aq75_;L{VnVJgsrqCt2f6NO}cl6i$)%-Q; zhfo&IH}m9 zBiTX$Z85K#Tk_@_aIU?Lf>&7~t1q^pY;n+a@Hba*%R#x*zjx1WXW#y9d-sduxMTUM zEYtMPOd}lOZ=d5;f3QuQ+?R#Y+mh=I?g}?^mUfaD;tfo8G?d@qEiH8kVvD zfSWHKjLsY5hv$6Pr*HznRKZcWZhemj;3MVIL7lyr9d^a(*|n$VZf9SAZ?DdXs}ikO z<+MUa&~DM#y0F1QY4DJ9pzMBj)GZDk3D45i(}N0XLYs&S_mh6bkZKtec!d`*=i;vv tPS{Nx9b(~|#+^8W-rde_;0J4nz)JvEweW&2oKvrqwI;YI%Yf~Z{{oVGf5iX* literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-a-nt/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-nt/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/src/cond.c b/testsuite/tests/I930-009-sparc-be-a-tk/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/src/cond.s b/testsuite/tests/I930-009-sparc-be-a-tk/src/cond.s new file mode 100644 index 000000000..ad8a8f5d3 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/src/cond.s @@ -0,0 +1,15 @@ + .section ".text" + .align 4 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + mov 120, %o0 + bne,a .LL2 + mov 2, %o0 +.LL2: + jmp %o7+8 + nop + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-a-tk/src/test_cond.adb new file mode 100644 index 000000000..adfefbe24 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/test.opt b/testsuite/tests/I930-009-sparc-be-a-tk/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/test.py b/testsuite/tests/I930-009-sparc-be-a-tk/test.py new file mode 100644 index 000000000..3432109ee --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/test.py @@ -0,0 +1,38 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('40001404 >: 32 80 00 02 bne,a', 'cond.out'), + 'branch should be taken') + +thistest.fail_if(not match('40001408 \\+: 90 10 20 02 mov', 'cond.out'), + 'delay slot should be executed') + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/test_cond b/testsuite/tests/I930-009-sparc-be-a-tk/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..16204f37a010f3ca90210c47d35b9ce31f31c7f9 GIT binary patch literal 72983 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 literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-a-tk/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-a-tk/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-bt/src/cond.c b/testsuite/tests/I930-009-sparc-be-bt/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-bt/src/cond.s b/testsuite/tests/I930-009-sparc-be-bt/src/cond.s new file mode 100644 index 000000000..57f0014a8 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/src/cond.s @@ -0,0 +1,16 @@ + .section ".text" + .align 4 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + bne .LL2 + nop + jmp %o7+8 + mov 120, %o0 +.LL2: + jmp %o7+8 + mov 2, %o0 + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-bt/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-bt/src/test_cond.adb new file mode 100644 index 000000000..108814c01 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/src/test_cond.adb @@ -0,0 +1,13 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-bt/test.opt b/testsuite/tests/I930-009-sparc-be-bt/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-bt/test.py b/testsuite/tests/I930-009-sparc-be-bt/test.py new file mode 100644 index 000000000..6dddab52d --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-bt/test.py @@ -0,0 +1,34 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('40001430 \\+: 12 80 00 04 bne', 'cond.out'), + 'branch should be taken on both dir') + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-bt/test_cond b/testsuite/tests/I930-009-sparc-be-bt/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..e85f0f0508fe97f841863650f873317cbb610a33 GIT binary patch literal 73031 zcmeI$e{7U@9S88w^R%_M$l?LVLhRfgTqdo7qikgXx?~S46_!D%z>G7-=dQg6df|Fk z@2;be=$>beSf&XzZ4`I2G&r^E}U$ zYjgfF_s6p3{g6+e=kxvjyq@Q|=eUQvw|&Ym4Vl|aF>!3zVL^u&%Q}L?4za|LR*6ZI z*5jXO8x4`fl*oC6G;29G3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun z0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP z3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbF zC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epy zpa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+ zfC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O z0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u*@v z3HWi5wzxD_E?M$S+>*zxSYqHbs_{U;!h@T>UhWG_Se_wbCaT4(i;uPXE;w<6^ zh*3XfESZ@7n~rq|-z~=CYcRHLR*u?I@kE+L8pq$I&F&azVIw~pSaI0q= zYWHK6aof~!wBKmVHa$NjrYB2rj!mQS)VYhxZMlSa0r4xuZxAmbeuwxy;uXZ75PwGe z74bUa?})b%*APt@2kW`q9GBHc;?tMaY;wIPW8%j=-)m@{n7yWJT!DH&VO>5Rm$+J} zgDrCW_-(!y`OWbXZ2^30XYT>057h`mO)y z^xOa4>94O`#r2qi&x@X%S(j?AeAB+E)+MM%o0%5$YeByj^lS0gPq$#67R=Lvd0PDC zY92&1mbz)*!`P3-{9C_*b?9|J3g@r3iMeo{3)l5X8``b4nvX7)rlU7lvpSaNPd4KE zzM<>WYg%*7%-U;KyMFwJ)bv`Db-{Z&B}+WHvCR@eo;Z7Bs=<5OH&E7q<3*>J1$iU# z#@BAQ637?nzB1*(#&3ML<9sh^#r#!kr1GdFYS&jC|68w492>`PX12⁢fB9dmuGp zdeW@9-gD#e)YixGtf0*&wG8bI94Bkqn|0cM7;SFRHo>)gembVdI-ia?7EfKo^JhHQ zit~hVrKWyCJ|5lo-g7G_-h6m=c1Fj+{;g<#rQRGfEB(!Htn{~Hj^OvM_{8jgw4L{q zrPre|=z}?NE+aZO_GZ~Fm7V@VK9fvm`p|Yu&!*khXWU{bTgY#;dW!|?u4G5DeZSRu zM|=B*wRfytx4PrbHW4SCNjr0$MV>!+=I#5}f5&;&U3{hU^Pe95!Y?y#VK_1WIpgWR z-nONyYopb=rRRY*t0Q@5a-9`TahJ8HP_%-T)LQ^%PnHf0meYOMmy6+kpn6nxN6M1S zq|0eZ_LWMK>@N%sy7_Xw1^n-_7E~$Mhiq-5N0KMmKpFC2-r#)0{QCG| zu5%l9FugIN#|S(>i^s6PJIWKtCvm(j%5Sk{$s!zIiSkv*U&e7N$~R#=8^^locs=MJ zT88<9SkJkjHe8>J_A^ng?T65Qb4@;iJXez+#(b-4^2d?a)_*&y1MKYUI6k`||M`Oa zrD`4z+rNVO)IwEsJy)^bC$MkC1=su<@{8CT$l+@&#c{BO{f&=#^Yc&Gvh+n1#g_#A zjScqv`Yw#;qbM5RfY15M+641Api2hzdcHSD{j;`KVvFW0iyfrZ{7aZm&)JIF!z*zd zd3F4++xK`uhp7LPsK-=u1Gw+rU`1KNAqJoGXCRsFmP+nf0O zPSl)_nW#Q@QN4xr>iyFZuGhSM{(R;d^w(!PT90|p{Pmk#7mWV^^3S4qYq%a0e!Ahy zMBr~0FyGxM7>efm@_cXe$b$S4j5m(-qdmFd(txu+ zo6i*Xmt-(q+UI2RWw%%y9x6LI_aQeY{W&*XjG9PkUv|jB80oTP3d4Ol*E#4G3zE%e z%TclB`jI`D&gPwBVYr;lyHY!iq;om6#k_7t=3YL*o2$>c{x%8I>ZmKRR=$bv~ z3f`|uBjE_U!ZzJKo2&EHSu`xG{(WvXzc)H>j31u!eV@Y#1XBe^;kxxb9)J%O3ww3; ze0tCor)%4euKS%`z1`h9Bd$ucUX{}d9YMQAW9!2DbA|qW&Yq(C#bGz!e;_ True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-ft/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-ft/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-ft/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-ft/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-ft/src/test_cond.adb new file mode 100644 index 000000000..fdab3b4e7 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-ft/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-ft/test.opt b/testsuite/tests/I930-009-sparc-be-ft/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-ft/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-ft/test.py b/testsuite/tests/I930-009-sparc-be-ft/test.py new file mode 100644 index 000000000..d9a5ca4d8 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-ft/test.py @@ -0,0 +1,39 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. + +The test intently gets into the 'Run' function twice in Cautious mode for a +safe command. We expect, then, partial coverage for both conditions in + + procedure Run (R : in out Robot; C : Command) is + Mode : Opmode; + begin + Mode := Current_Mode (R); + if Mode = Cautious <== + and then Unsafe (C) <== + +We seek the reported status of the associated cond branch instructions +directly. +""" + +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr'); +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') + +thistest.fail_if( + not match(re.escape('40001400 v: 12 80 00 04 ' + 'bne 0x40001410 '), + 'cond.out'), + 'branch should be taken on fall-through') +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-ft/test_cond b/testsuite/tests/I930-009-sparc-be-ft/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..372c198caec1ee01e5de23d434478480747f36f2 GIT binary patch literal 72983 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 literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-sparc-be-ft/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-ft/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-ft/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.c b/testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.s b/testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.s new file mode 100644 index 000000000..f1178ec87 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/src/cond.s @@ -0,0 +1,18 @@ + .section ".text.cond" + .align 4 +pad_cond: + .fill 3020 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + bne .LL2 + nop + jmp %o7+8 + mov 120, %o0 +.LL2: + jmp %o7+8 + mov 2, %o0 + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-npg-bt/src/test_cond.adb new file mode 100644 index 000000000..108814c01 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/src/test_cond.adb @@ -0,0 +1,13 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/test.opt b/testsuite/tests/I930-009-sparc-be-npg-bt/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/test.py b/testsuite/tests/I930-009-sparc-be-npg-bt/test.py new file mode 100644 index 000000000..984ce8b24 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/test.py @@ -0,0 +1,14 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + +Wdir('tmp_') + +# gprbuild('test_cond.gpr') +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('40001ffc \\+: 12 80 00 04 bne', 'cond.out'), + 'branch should be taken on both dir') + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/test_cond b/testsuite/tests/I930-009-sparc-be-npg-bt/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..7378057b555699043b3b9015a8d543fd88dc3c6a GIT binary patch literal 76080 zcmeI$U2Ggz6$kJ$W2fGVRE!h1isaIai)d_=Y@F5sx30wG!z5K5$4vrK5$f#PJBe3W z@0#6p<3vK8b)3{dRh%jyKLj!rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC z1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo z6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)U zP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZ zKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt z00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZvy z+7k#Ykq%25D;I5f(z4~mC0h)fMm64V9@T1_tjt9<&JI-Tx6MAYA!WSZdLMTG4(sD{ zPu*xs5#u440L>xyJcW1~aSriA z#6*xXR-Iq?ht@iZ&lZ!`M$~r9%9JA&Uu1eOZljOiWlQ|CehVxrq1`;$_5d5U(J9k9ZC7N5o$ce?$Bo zaRu>D#Jh<15Gzmz>zQe?r1Q8nH=|~=-M&mpknjV)q5b^Ad%DIpv-(mz zPp@gsH8X3kS?&7q8&cx(3VX_bA| zDZ2&vN`0)n=))#x{GfGykhBxQ`i)X~L|SUsSFQh@Kb@bM#&2ehG;Gjz+zYq|QsbsC zO`7XHH*KZXJcj3rBl2lIhW-Znx7GAF>-7H^`ro2`!fW}$TtfGCKCL-vrB2}aXIyB< zdBV6-)4nX9j_><{3+v9m_0Yn?yw<_v+wtS2dUMRL3%0+xF4&1V!r!~B^9%pce%vTP z0SZun0u-PC1t>s)Yg52~+}7__jp65ie1E|Al5zbWfk#u%sO*)>?oc70Nv1P{$anN_ z*=K*zE0(f_{9X1yv0#5D*_G@(WVhem*?H%t+c$l7L)RT0B5pd9b{7YWyl~{~yZ3gV zcAxc{FZF!+zKI8Zoq1d9oBx{k^|9WzW81d7?Die~U+A#Al6NFG+wm0L_WnZA4p&ld z0hm2mIy_QN58|<0j2?%pdu4CDEXho|oR;KZsU*pv!pMl1FV|bZ|321=CMCPh(LUjq zBD=OkLJwnWLuhM*Blfr$2$7o+)velZ9S-Qe_B$yCLIR|Vo7T{6Jwo?8HIcBN+!^ji z|Flh`8PO0O(j)fE_`i8EkNRk;eZ%V$Im6Y+l06Yp^1gK9#K>8HuN*!z_IG4 zb?R`)|83`UemEc=e;OW`YO(%v z=s%?$a8S?hx8YR_bM-Y|TQ=Wc(SJajBOkM|`uY>qH=EI3b3W!Ls?Wo?y#wpj`>88h zubEsrpV^J^<7ki9WA0qKe)GO%^&ddqj_&R8df=xUek=_AP269r@5X`Ac)o|1dYj)| zmY+nu6#B=0=4lZhsa8}E^BE`1!u8?)FrQtv{^#TSX=ObB1=O3ykof*F^>rlN;(EVB z`!Ehf^9`qqnW9(n%2IgHEAGz~4#`+P6YuTMjg^MoL)m<$aHu3B>C!0;bPN(Zx}E^4I9k|~T0<~;X^S1d?2pDo9SHP@H$k#sii77JtLY~GXF zX(XM?p)cn3GRxk{2HmUgPT^ZyF0F5L!|D8x=i+}R=M}@_qv=fe{wMChp543Lz5BN8 z*(a{+jc3bJXUx`m2i;zb*nWTimRY?%sjk zUY!w_Ctk10X@geKVR3C;*if!8bkN;j^u99Y<%bSOXX)wbK?N<5P0WQGOFw%^xd;lp zx92eD($5-hG)!DAvG@^WE6$*Im%9u2;TmG_0>D)*x}b~a)GI}82`@?=u)XqMsUeP# literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-npg-bt/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.c b/testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.s b/testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.s new file mode 100644 index 000000000..34cd5d5bf --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/src/cond.s @@ -0,0 +1,18 @@ + .section ".text.cond" + .align 4 +pad_cond: + .fill 3068 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + bne .LL2 + nop + jmp %o7+8 + mov 120, %o0 +.LL2: + jmp %o7+8 + mov 2, %o0 + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-npg-ft/src/test_cond.adb new file mode 100644 index 000000000..fdab3b4e7 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (0) /= 120 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/test.opt b/testsuite/tests/I930-009-sparc-be-npg-ft/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/test.py b/testsuite/tests/I930-009-sparc-be-npg-ft/test.py new file mode 100644 index 000000000..41f6dfa37 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/test.py @@ -0,0 +1,15 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild('test_cond.gpr') +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('40001ffc v: 12 80 00 04 bne', 'cond.out'), + 'branch should be taken fall-through') + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/test_cond b/testsuite/tests/I930-009-sparc-be-npg-ft/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..985c4a67a3fc1102e2831b4e3f8295d69b4febd9 GIT binary patch literal 76080 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 literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-npg-ft/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.c b/testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.s b/testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.s new file mode 100644 index 000000000..34cd5d5bf --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/src/cond.s @@ -0,0 +1,18 @@ + .section ".text.cond" + .align 4 +pad_cond: + .fill 3068 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + bne .LL2 + nop + jmp %o7+8 + mov 120, %o0 +.LL2: + jmp %o7+8 + mov 2, %o0 + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-npg-tk/src/test_cond.adb new file mode 100644 index 000000000..adfefbe24 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/test.opt b/testsuite/tests/I930-009-sparc-be-npg-tk/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/test.py b/testsuite/tests/I930-009-sparc-be-npg-tk/test.py new file mode 100644 index 000000000..94a899a5c --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/test.py @@ -0,0 +1,15 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild ('test_cond.gpr') +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('40001ffc \\>: 12 80 00 04 bne', 'cond.out'), + 'branch should be taken on both dir') + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/test_cond b/testsuite/tests/I930-009-sparc-be-npg-tk/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..26a501fa7162afcd613f1ee3432948d75a405334 GIT binary patch literal 76080 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 literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-npg-tk/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-nt/src/cond.c b/testsuite/tests/I930-009-sparc-be-nt/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-nt/src/cond.s b/testsuite/tests/I930-009-sparc-be-nt/src/cond.s new file mode 100644 index 000000000..57f0014a8 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/src/cond.s @@ -0,0 +1,16 @@ + .section ".text" + .align 4 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + bne .LL2 + nop + jmp %o7+8 + mov 120, %o0 +.LL2: + jmp %o7+8 + mov 2, %o0 + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-nt/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-nt/src/test_cond.adb new file mode 100644 index 000000000..c20d60c81 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/src/test_cond.adb @@ -0,0 +1,13 @@ +with Get_False; +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Get_False then + if Cond (1) /= 2 then + raise Program_Error; + end if; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-nt/test.opt b/testsuite/tests/I930-009-sparc-be-nt/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-nt/test.py b/testsuite/tests/I930-009-sparc-be-nt/test.py new file mode 100644 index 000000000..b5557ffe2 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/test.py @@ -0,0 +1,35 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project=gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: + +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('40001444 -: 12 80 00 04 bne', 'cond.out'), + 'branch should not be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-nt/test_cond b/testsuite/tests/I930-009-sparc-be-nt/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..8442eff921fab52203755b6e719d3d1eabc231d1 GIT binary patch literal 73206 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 literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-sparc-be-nt/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-nt/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-nt/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-be-tk/src/cond.c b/testsuite/tests/I930-009-sparc-be-tk/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-be-tk/src/cond.s b/testsuite/tests/I930-009-sparc-be-tk/src/cond.s new file mode 100644 index 000000000..57f0014a8 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/src/cond.s @@ -0,0 +1,16 @@ + .section ".text" + .align 4 + .global cond + .type cond, #function + .proc 04 +cond: + cmp %o0, 0 + bne .LL2 + nop + jmp %o7+8 + mov 120, %o0 +.LL2: + jmp %o7+8 + mov 2, %o0 + .size cond, .-cond + diff --git a/testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-be-tk/src/test_cond.adb b/testsuite/tests/I930-009-sparc-be-tk/src/test_cond.adb new file mode 100644 index 000000000..adfefbe24 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-be-tk/test.opt b/testsuite/tests/I930-009-sparc-be-tk/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-be-tk/test.py b/testsuite/tests/I930-009-sparc-be-tk/test.py new file mode 100644 index 000000000..cd9b2bd67 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/test.py @@ -0,0 +1,34 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + + +Wdir('tmp_') + +# gprbuild(project = gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr'); + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in + +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== + +# We seek the reported status of the associated cond branch instructions +# directly: +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') +thistest.fail_if(not match('40001400 >: 12 80 00 04 bne', 'cond.out'), + 'branch should be taken') + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-tk/test_cond b/testsuite/tests/I930-009-sparc-be-tk/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..7acbe7ea9d020df19519aa09f6c2d164175481fc GIT binary patch literal 72983 zcmeI$TWlP66$bD#V;gTpDkjOMig0Nspfo~#Cf}AR?{19N$n@Sq4jSwIpp(GDQ6a|SsAO+;AAcYEqTa}7SgZa)} zoV8^hN*}6L-&n^p=YOBy%S(1n<*xa4JRt-5@SVkc-SSj7}72&Y0-N8 zh_=xXNgo$EgOFA&=SBevP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo z6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)U zP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZ zKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt z00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun z0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP z3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo?>&LQ z66vs{xqiWxr!8BKU9`o(X(aJ>^JuJ9u_J3pS!{QI3A^x*da`M>|(6U5ID`u~N;5lb^*eNb|TA*hyLAvpR0s##kzQIkt>hS^wuN9l3yb0r4W@H;9)IzeD^U@iO91h(9C#ig*q2 zcf>ytR}d{22kV(?wPfv4YkEq}&TaH%T!NGz_)YC+XRqiQSD`*g+fyejvD88x9FfTr z9}E20Z|;8~)7^pmu{%gz?hdTKbO$R>_KQ5R#%?{?WgGS5vUH|9u;1to+W*lVbiUOc zY^-0#^*9foU-|OvhHPv7QRliwm#`jfX4=rN4gK2CuPxX(-G+JEFi#uiX$w}Wc^L6n z>ZW~9O|LHseIyZI~nc|CM!i_CMOrf818z=CBXu#JL>Qxv@8EUbW^9mP`3e zE_Tl+Teu|Mfms)cgtcDuh)wr|UHWjYVo?YDGxZd!lK`VDKlZtW0pbNQS**IDE{ zD|Q^YXX7{A=e(sCyFdMjvCsT6|0aeL^ItQ*?ibs(_VnCtw{Pvcx5Mtr+?v^7$5Y&9 z?=4sCa3zZ^0JCSRhlXpp0qkp)Xg`!3)x3i>$>ejjoMZ;7RmlvNhljmVZLtOX@3J;j zDc1)aZKFq$ZX6<|CD>LWw6@8S^g%HYBG)65EorwJ1$wOQj-%aid{QKBbgyIRwg#cc zoti}LWK(z?{n9#(rHH1eNK4W$;`fHRJZhtY{Q>R!wRz-Y{5$!)iN-had7N%IA2XdicX7Rq`SlugMe8+h znm?bp4*iqsf%TYo&R@T|ZNd2WB5%id?a_Kn`00i(2cf@N#(a06z=`Mk!hCP@=z{zq zjF(0G*w1_npXNvt5A#VU%rw{g!#uTM{m;es(~`LUM;LDsUE=%4JRf&Qf4yJLU!#5q zWzl>?xk|p`RlS;&@AoQui{%3{TFS>qdyAvhA@@L`lrJBs%5bi_-z}7CUZpZRQge&m z{a#T9i(al0H<9Z8!ibA8ay7}9M+b_Y`+!#|OQBS##l@QINA_^8P;x8f(ORM8N#it< zD;Cif^Llxid-;TKt^xPz+bAq3=Jdrjlq(H-E`H~WUL`Dd`*-c!;qKnEdDk9sUGHF_ zCW|z^Yq3JN7d^Jz*SC4c-956scW0lwt9L7k_LXuqcc9|s_Pfkb4G!UK@TSdsyJg7Bjl>P~)hq6<&B>C&u7w9Y!TVKdBpP9N)TXy@OETXgi-u+5 zKj0Ng`{MJ)_|ZAv{VAM4I8}HQty|yYA^1q8yiaE@<%T_Rd$#ZFxyRkz-`lG*;;O{! zRXMHD5wu%8wk~Y2SRUN(?yY#A9ra3shoZCe^z@*Dn#d;R!u_OQF{D-j1zzDr%sKxn tg&TDfSBIFp*mvO!dUv=xfFG_Q1}_6#)uIbJcTT-h(VFn0ECRM${tJzsfz$v1 literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-sparc-be-tk/test_cond.gpr b/testsuite/tests/I930-009-sparc-be-tk/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-be-tk/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/src/cond.c b/testsuite/tests/I930-009-sparc-cross-boundary/src/cond.c new file mode 100644 index 000000000..298de49d6 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/src/cond.c @@ -0,0 +1,8 @@ +int +cond (int v) +{ + if (v == 0) + return 3; + else + return 120; +} diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/src/cond.s b/testsuite/tests/I930-009-sparc-cross-boundary/src/cond.s new file mode 100644 index 000000000..fd96ab66f --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/src/cond.s @@ -0,0 +1,15 @@ + .section ".text" + .align 4 + .global cond + .type cond, #function + .proc 04 +cond: + mov 2, %o0 +.LL2: + jmp %o7+8 + .size cond, .-cond + .type cond1, #function +cond1: + nop + .size cond1, .-cond1 + diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.adb b/testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.adb new file mode 100644 index 000000000..ee663a3a0 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.adb @@ -0,0 +1,17 @@ +with System.Machine_Code; + +package body Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + begin + loop + System.Machine_Code.Asm ("mov 0, %%g1; ta 0", Volatile => True); + end loop; + end Last_Chance_Handler; + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.ads b/testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.ads new file mode 100644 index 000000000..2a39f4d82 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/src/last_chance_handler.ads @@ -0,0 +1,9 @@ +with System; + +package Last_Chance_Handler is + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Last_Chance_Handler; diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/src/test_cond.adb b/testsuite/tests/I930-009-sparc-cross-boundary/src/test_cond.adb new file mode 100644 index 000000000..adfefbe24 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/src/test_cond.adb @@ -0,0 +1,10 @@ +with Last_Chance_Handler; + +procedure Test_Cond is + function Cond (V : Integer) return Integer; + pragma Import (C, Cond); +begin + if Cond (1) /= 2 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/test.opt b/testsuite/tests/I930-009-sparc-cross-boundary/test.opt new file mode 100644 index 000000000..0ca9ff786 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/test.opt @@ -0,0 +1,3 @@ +leon-elf +leon3-elf +ALL DEAD leon*-elf only diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/test.py b/testsuite/tests/I930-009-sparc-cross-boundary/test.py new file mode 100644 index 000000000..4b677b7fd --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/test.py @@ -0,0 +1,36 @@ +""" +This test is about a xcov/qemu misinteraction on very specific branch +sequences. We built once from the sources in src and re-exercise the binary. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import exepath_to, tracename_for, xcov, xrun + +Wdir('tmp_') + +# gprbuild(project = gprfor(['test_robots.adb'])) +# gprbuild('test_cond.gpr') + +# The test intently gets into the 'Run' function twice in Cautious mode for a +# safe command. We expect, then, partial coverage for both conditions in +# +# procedure Run (R : in out Robot; C : Command) is +# Mode : Opmode; +# begin +# Mode := Current_Mode (R); +# if Mode = Cautious <== +# and then Unsafe (C) <== +# +# We seek the reported status of the associated cond branch instructions +# directly: +xrun(exepath_to('../test_cond')) +xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('test_cond')], 'cond.out') + +thistest.fail_if(not match('40001400 \\+: 81 c3 e0 08 retl', 'cond.out'), + 'cond should be covered') +thistest.fail_if(not match('40001404 \\+: 01 00 00 00 nop', 'cond.out'), + 'cond1 should be covered') + +thistest.result() diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/test_cond b/testsuite/tests/I930-009-sparc-cross-boundary/test_cond new file mode 100755 index 0000000000000000000000000000000000000000..bc01f0acbaf74bb0bf28ff888ba191144c6da082 GIT binary patch literal 72989 zcmeI$TWlO>6$kJ$V;gTp3X{}{LS3~JDu^wTtT^A zSzG3z^r33?pXhkL^WEn+vpbIO?ceo&!!%^^FvUdKaH5KCG1@ML#cr|1kPb;ni?-vR zXdexcwz|k!gtTfs4+>C#0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt z00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun z0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP z3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbF zC_n)UP=Epypa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epy zpa2CZKmiI+fC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+ zfC3bt00k&O0SZun0u-PC1t>rP3Q&Lo6rcbFC_n)UP=Epypa2CZKmiI+fC3bF;|TQg==h?vNGd8S?|bs#Lp1FK>P~vG~zdi-y{Bj_!Hte#9t9F zApU{)7vdE}3+BOorduu9e4jNpt!C%8Ri!RLsv1uoRAaxzzlF^81oBKzkb1T!u>R5$tUom<@|8_?>#1(rsC`aW&-VoOrJkVUpFKg> z%RRxi+OxPHPr~QtRe5Y{rnUBYXI-O9*p5E)?HJdNaqSq_9&DRy$2#p;ryc9G2kX^5 zjCd|})3L{JuBU?QK81bgeV>N&r#r=5zR%_Ry1x_sw%D!HtEFZ73VT84ss`tpaerUb z{pmezxMybLJ!{-Q{)W`@e2YCcfG7x+auYon9N}&B&Xd zf0x~ce3hPSPgY?QG{4q)zLvIA!KNFec3j#T_m|B7g+IWCUUnF5I|h39 z*&p&t+V4$wr@Ic>9XED$-Mr<-E$`dheN(51>t#K6aj?iY*X}-c=e94o z-}YBu=(+m?Qy+UO`x2%T^WXDTJ+E}^=kyh)h$|2c^IeU8=5we^4xMMk z!-;D#IP4QTpbmMsZg{;>etG^V*R>5NT;7<}GUBa{tcH!;8s}}u&!N04&aZW3%_@{H z#Q7%V7g5f{c`xR3P}W1|8^HL;GRp75e#XPrXn#KX&&Rp;A4mV~4f!PUd_#T=>uqYt zA4J~R{>8WrunRAsd}dj$_bEK$_NTEQb!Y~buK&BJRc}f-{?AxnZB$9y|AzkiaBju} zfZS+8UPEpm*D2nCa(G1Jjq9sRb9h~K5>?ikX#8!?()OL0FN3ONe%Fz+)7k~=m3m%Oq2X5`hOBNcHIAd%zroXWd6@Ow^hRd@%WSIKZlBI;{M-7 z|K$4h`hJ-_&2j(VE?e&z^mj1cihN8X`TmLen{PvV!}XX~C!fQ({oPn!?^$=WzWJV| z>zP|IeiZHMf&G~MOZRUMESvwM$k(HLN4y{S>49GkLVt4t>)nb9Ctk0<)Z0A1EI)zy z2GKwEGf#?CktY7;X(!CW{o(mAA78fr@5j&6s(Afb%vZ&b`1vuPiicx=`uv%{M*D|R z7p*tym9izj>{q0Ck6+rKFCLPKLN+e#&rg&`-9x!Tws@#4V_x~7n=4fOQfXqm;^zH( z{Jf0heXkUEk@CUZxQjWwie!ru!+GC5;+Kk&E95G1wdVR2KIY{LZmBp?$rXHQTt>Wn z9(}Q{pOwXzQTQesb}zr3!iv17FS=2$Fyg!Tna%s9uwLJNTf`mQyJxpMw6AyXK5<=t zGFOom2Hd_;Zk8K+PA*lL-z4f@qn&g@Wy;``*!W=yVD&S?C;kVac|=N zs+>0H3_2{HTQ@e6FOD2^_m})nO!$S7!_igxdU;SmOJoys;i=MJJfuLd%WuaO^zU|e13%nD3|<7dszo<+@tXRjq%Gl1SpjTF{tLwyd^i9A literal 0 HcmV?d00001 diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/test_cond.gpr b/testsuite/tests/I930-009-sparc-cross-boundary/test_cond.gpr new file mode 100644 index 000000000..799c9d743 --- /dev/null +++ b/testsuite/tests/I930-009-sparc-cross-boundary/test_cond.gpr @@ -0,0 +1,20 @@ +--with "../../support/support"; + +project gen is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada", "Asm"); + + for Main use ("test_cond.adb"); + +-- package Builder renames Support.Builder; + +-- package Compiler renames Support.Compiler; + +-- package linker is +-- for Switches ("test_cond.adb") use ("-Wl,-T,../gnu.ld,-v"); +-- end linker; + +end gen; diff --git a/testsuite/tests/I930-019/src/kops.adb b/testsuite/tests/I930-019/src/kops.adb new file mode 100644 index 000000000..550f382aa --- /dev/null +++ b/testsuite/tests/I930-019/src/kops.adb @@ -0,0 +1,8 @@ + +package body Kops is + procedure Inc (X : in out Integer) is + begin + X := X + K; + end Inc; +end; + diff --git a/testsuite/tests/I930-019/src/kops.ads b/testsuite/tests/I930-019/src/kops.ads new file mode 100644 index 000000000..589ab169d --- /dev/null +++ b/testsuite/tests/I930-019/src/kops.ads @@ -0,0 +1,8 @@ + +generic + K : Integer; +package Kops is + procedure Inc (X : in out Integer); + pragma Inline (Inc); +end; + diff --git a/testsuite/tests/I930-019/src/ops4.ads b/testsuite/tests/I930-019/src/ops4.ads new file mode 100644 index 000000000..1d4738d2d --- /dev/null +++ b/testsuite/tests/I930-019/src/ops4.ads @@ -0,0 +1,2 @@ +with Kops; +package Ops4 is new Kops (K => 4); diff --git a/testsuite/tests/I930-019/src/ops8.ads b/testsuite/tests/I930-019/src/ops8.ads new file mode 100644 index 000000000..d69b950a1 --- /dev/null +++ b/testsuite/tests/I930-019/src/ops8.ads @@ -0,0 +1,2 @@ +with Kops; +package Ops8 is new Kops (K => 8); diff --git a/testsuite/tests/I930-019/src/test_kops.adb b/testsuite/tests/I930-019/src/test_kops.adb new file mode 100644 index 000000000..0b479da84 --- /dev/null +++ b/testsuite/tests/I930-019/src/test_kops.adb @@ -0,0 +1,11 @@ +with Ops4, Ops8, Vars; + +procedure Test_Kops is + Vx : Integer := Vars.X; +begin + Ops4.Inc (Vx); + Vars.Assert_Eq (Vx, 16); + + Ops8.Inc (Vx); + Vars.Assert_Eq (Vx, 24); +end; diff --git a/testsuite/tests/I930-019/src/vars.adb b/testsuite/tests/I930-019/src/vars.adb new file mode 100644 index 000000000..b36792c78 --- /dev/null +++ b/testsuite/tests/I930-019/src/vars.adb @@ -0,0 +1,8 @@ +package body Vars is + procedure Assert_Eq (Value, Expected : Integer) is + begin + if Value /= Expected then + raise Program_Error; + end if; + end; +end; diff --git a/testsuite/tests/I930-019/src/vars.ads b/testsuite/tests/I930-019/src/vars.ads new file mode 100644 index 000000000..06a24b27f --- /dev/null +++ b/testsuite/tests/I930-019/src/vars.ads @@ -0,0 +1,6 @@ +package Vars is + X : Integer := 12; + pragma Volatile (X); + + procedure Assert_Eq (Value, Expected : Integer); +end; diff --git a/testsuite/tests/I930-019/test.py b/testsuite/tests/I930-019/test.py new file mode 100644 index 000000000..af9134ba5 --- /dev/null +++ b/testsuite/tests/I930-019/test.py @@ -0,0 +1,29 @@ +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +Wdir('tmp_') + + +# Run, then check results. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor('test_kops.adb', srcdirs='../src')), + covlevel='stmt', + mains=['test_kops'], + extra_coverage_args=['--annotate=xcov'], + scos=['obj/kops', 'obj/ops4', 'obj/ops8', 'obj/test_kops', 'obj/vars']) + +thistest.fail_if(not match(r'4 \+:', 'test_kops.adb.xcov'), + 'test_kops.adb:4 not covered') +thistest.fail_if(not match(r'6 \+:', 'test_kops.adb.xcov'), + 'test_kops.adb:6 not covered') +thistest.fail_if(not match(r'7 \+:', 'test_kops.adb.xcov'), + 'test_kops.adb:7 not covered') +thistest.fail_if(not match(r'9 \+:', 'test_kops.adb.xcov'), + 'test_kops.adb:9 not covered') +thistest.fail_if(not match(r'10 \+:', 'test_kops.adb.xcov'), + 'test_kops.adb:10 not covered') +thistest.result() diff --git a/testsuite/tests/IA01-015/src/monitor.adb b/testsuite/tests/IA01-015/src/monitor.adb new file mode 100644 index 000000000..efc5cd47b --- /dev/null +++ b/testsuite/tests/IA01-015/src/monitor.adb @@ -0,0 +1,6 @@ +package body Monitor is + procedure Touch is + begin + N_Ops := N_Ops + 1; + end; +end; diff --git a/testsuite/tests/IA01-015/src/monitor.ads b/testsuite/tests/IA01-015/src/monitor.ads new file mode 100644 index 000000000..ae8097029 --- /dev/null +++ b/testsuite/tests/IA01-015/src/monitor.ads @@ -0,0 +1,5 @@ +package Monitor is + N_Ops : Integer := 0; + + procedure Touch; +end; diff --git a/testsuite/tests/IA01-015/src/trymon.adb b/testsuite/tests/IA01-015/src/trymon.adb new file mode 100644 index 000000000..bc6d6a5ab --- /dev/null +++ b/testsuite/tests/IA01-015/src/trymon.adb @@ -0,0 +1,25 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Monitor; + +procedure Trymon is +begin + Monitor.Touch; +end; diff --git a/testsuite/tests/IA01-015/test.py b/testsuite/tests/IA01-015/test.py new file mode 100644 index 000000000..518696106 --- /dev/null +++ b/testsuite/tests/IA01-015/test.py @@ -0,0 +1,54 @@ +""" +We check that gnatcov can take a list of ALI/SID files using the '@' prefix or +a single input file. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, list_to_tmp +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +wd = Wdir('tmp_') +trace_file = build_and_run( + gprsw=GPRswitches(root_project=gprfor(srcdirs=['../src'], + mains=['trymon.adb'])), + covlevel='stmt', + mains=['trymon'], + extra_coverage_args=[])[-1] + +coverage_base_args = ['coverage', '--level=stmt', '--annotate=xcov', + trace_file] +expected_reports = { + 'trymon.adb.xcov': {'+': {24}}, + 'monitor.adb.xcov': {'+': {4}}, + 'monitor.ads.xcov': {}, +} +# Unlike in binary trace mode, where it is no-code, instrumentation allows to +# detect that the Integer library-level variable declaration at line 2 is +# covered. +if thistest.options.trace_mode == 'src': + expected_reports['monitor.ads.xcov'] = {'+': {2}} + + +def tryseq(label, scoargs): + thistest.log('== {} =='.format(label)) + xcov(coverage_base_args + scoargs) + check_xcov_reports('*.xcov', expected_reports) + + +if thistest.options.trace_mode == 'src': + option = 'sid' + ext = 'sid' +else: + option = 'scos' + ext = 'ali' + +sco_files = ['obj/trymon.{}'.format(ext), + 'obj/monitor.{}'.format(ext)] +tryseq('one_response_file', + scoargs=['--{}'.format(option), '@{}'.format(list_to_tmp(sco_files))]) +tryseq('multiple_files', + scoargs=['--{}={}'.format(option, ali) for ali in sco_files]) +thistest.result() diff --git a/testsuite/tests/IA06-008-override-exec/src/noop.adb b/testsuite/tests/IA06-008-override-exec/src/noop.adb new file mode 100644 index 000000000..545d3b1f6 --- /dev/null +++ b/testsuite/tests/IA06-008-override-exec/src/noop.adb @@ -0,0 +1,25 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +procedure NOOP is + X : Integer := 1; + pragma Volatile (X); +begin + X := X + 1; +end; diff --git a/testsuite/tests/IA06-008-override-exec/test.opt b/testsuite/tests/IA06-008-override-exec/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/IA06-008-override-exec/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/IA06-008-override-exec/test.py b/testsuite/tests/IA06-008-override-exec/test.py new file mode 100644 index 000000000..ee492a266 --- /dev/null +++ b/testsuite/tests/IA06-008-override-exec/test.py @@ -0,0 +1,41 @@ +"""Check that --exec works properly.""" + +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, + unixpath_to, xcov, xrun) + + +wd = Wdir('tmp_') + +gprbuild(gprfor(srcdirs=['../src'], mains=['noop.adb'])) +xrun(unixpath_to('noop')) + +# On Windows, we cannot override an existing file during a renaming. +if os.path.exists('nop'): + os.unlink('nop') +os.rename(exepath_to('noop'), 'nop') + +p = xcov(['coverage', '--level=branch', '--annotate=asm', + tracename_for('noop')], + out='not_found.out', register_failure=False) +thistest.fail_if( + p.status == 0 + or not match( + 'Cannot open ELF file %s for trace file' % unixpath_to('noop'), + 'not_found.out'), + 'no error if exec not found') + +# We are not interested in the exact coverage status of the main symbol, so +# just look if we have some coverage indication for it as a sanity check that +# the coverage analysis request did something. Beware that "main" might be +# named after the main subprogram on VxWorks systems. +xcov(['coverage', '--level=branch', '--annotate=asm', + '--exec=nop', tracename_for('noop')], + out='noop.stdout') +thistest.fail_if(not match('main|noop [+!]:', 'noop.stdout'), + '--exec overrides trace file info') + +thistest.result() diff --git a/testsuite/tests/IA06-009-offset-from-sym/src/p.adb b/testsuite/tests/IA06-009-offset-from-sym/src/p.adb new file mode 100644 index 000000000..37843ce02 --- /dev/null +++ b/testsuite/tests/IA06-009-offset-from-sym/src/p.adb @@ -0,0 +1,8 @@ + +procedure P is + X : Integer := 0; + pragma Volatile (X); +begin + X := X + 1; +end; + diff --git a/testsuite/tests/IA06-009-offset-from-sym/test.opt b/testsuite/tests/IA06-009-offset-from-sym/test.opt new file mode 100644 index 000000000..141c4c88d --- /dev/null +++ b/testsuite/tests/IA06-009-offset-from-sym/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Tests object coverage diff --git a/testsuite/tests/IA06-009-offset-from-sym/test.py b/testsuite/tests/IA06-009-offset-from-sym/test.py new file mode 100644 index 000000000..96ea6fd7a --- /dev/null +++ b/testsuite/tests/IA06-009-offset-from-sym/test.py @@ -0,0 +1,24 @@ +""" +Check that start of block addresses are offsets from the corresponding symbol, +not absolute addresses. +""" + +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import Wdir, match +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + +wd = Wdir('tmp_') +symbol = target_info().to_platform_specific_symbol('_ada_p') + +gprbuild(gprfor(srcdirs=['../src'], mains=['p.adb'])) +xrun(exepath_to('p')) +xcov(['coverage', + '--level=insn', '--annotate=xcov+', + '--routines={}'.format(symbol), tracename_for('p')]) + +thistest.fail_if( + not match(r'<{}\+(00000000){{1,2}}>:'.format(symbol), 'p.adb.xcov'), + 'offset from symbols') +thistest.result() diff --git a/testsuite/tests/IA09-021-unit-nosco/src/checks.adb b/testsuite/tests/IA09-021-unit-nosco/src/checks.adb new file mode 100644 index 000000000..3d4bea996 --- /dev/null +++ b/testsuite/tests/IA09-021-unit-nosco/src/checks.adb @@ -0,0 +1,8 @@ +package body Checks is + procedure Assert (Cond : Boolean) is + begin + if not Cond then + raise Program_Error; + end if; + end; +end; diff --git a/testsuite/tests/IA09-021-unit-nosco/src/checks.ads b/testsuite/tests/IA09-021-unit-nosco/src/checks.ads new file mode 100644 index 000000000..ee6427f07 --- /dev/null +++ b/testsuite/tests/IA09-021-unit-nosco/src/checks.ads @@ -0,0 +1,5 @@ +-- A spec with a mere suprogram declaration. No SCO at all for this file. + +package Checks is + procedure Assert (Cond : Boolean); +end; diff --git a/testsuite/tests/IA09-021-unit-nosco/src/test_assert.adb b/testsuite/tests/IA09-021-unit-nosco/src/test_assert.adb new file mode 100644 index 000000000..c01f2e38b --- /dev/null +++ b/testsuite/tests/IA09-021-unit-nosco/src/test_assert.adb @@ -0,0 +1,10 @@ +with Checks; + +procedure Test_Assert is + X : Integer := 12; + pragma Volatile (X); +begin + Checks.Assert (X = 12); +end; + + diff --git a/testsuite/tests/IA09-021-unit-nosco/test.opt b/testsuite/tests/IA09-021-unit-nosco/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/IA09-021-unit-nosco/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/IA09-021-unit-nosco/test.py b/testsuite/tests/IA09-021-unit-nosco/test.py new file mode 100644 index 000000000..3644ce365 --- /dev/null +++ b/testsuite/tests/IA09-021-unit-nosco/test.py @@ -0,0 +1,17 @@ +""" +Check that gnatcov doesn't crash while processing the ALI file for +a unit producing not a single SCO. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +Wdir('tmp_') +gprbuild(gprfor(['test_assert.adb'], srcdirs='../src')) +xrun(exepath_to('test_assert')) +xcov(['coverage', '--level=stmt', '--annotate=xcov', + '--scos=obj/checks.ali', tracename_for('test_assert')]) +thistest.result() diff --git a/testsuite/tests/IA13-015-loop-body/src/for_loop.adb b/testsuite/tests/IA13-015-loop-body/src/for_loop.adb new file mode 100644 index 000000000..60618ac6d --- /dev/null +++ b/testsuite/tests/IA13-015-loop-body/src/for_loop.adb @@ -0,0 +1,14 @@ +procedure For_Loop is + X : Integer := 0; + procedure Inc_X (N : Integer) is + begin + for I in 1 .. N loop + X := X + 1; + end loop; + end; +begin + Inc_X (0); + if X /= 0 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/IA13-015-loop-body/test.opt b/testsuite/tests/IA13-015-loop-body/test.opt new file mode 100644 index 000000000..141c4c88d --- /dev/null +++ b/testsuite/tests/IA13-015-loop-body/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Tests object coverage diff --git a/testsuite/tests/IA13-015-loop-body/test.py b/testsuite/tests/IA13-015-loop-body/test.py new file mode 100644 index 000000000..d461d66e1 --- /dev/null +++ b/testsuite/tests/IA13-015-loop-body/test.py @@ -0,0 +1,15 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +Wdir('tmp_') +gprbuild(gprfor(['for_loop.adb'], srcdirs='../src'), gargs='-O0') +xrun(exepath_to('for_loop')) +xcov('coverage --level=branch --annotate=xcov ' + tracename_for('for_loop')) + +# We expect the for loop body to be uncovered +thistest.fail_if(not match(r'[0-9]+ -:.*X := X \+ 1', 'for_loop.adb.xcov'), + 'expect loop body to be uncovered') +thistest.result() diff --git a/testsuite/tests/IA16-028-disp-routines/baseline3.txt b/testsuite/tests/IA16-028-disp-routines/baseline3.txt new file mode 100644 index 000000000..bf0ee31d5 --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/baseline3.txt @@ -0,0 +1,3 @@ +_ada_p +pack__q +pack__r diff --git a/testsuite/tests/IA16-028-disp-routines/src/monitor.adb b/testsuite/tests/IA16-028-disp-routines/src/monitor.adb new file mode 100644 index 000000000..12e627068 --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/src/monitor.adb @@ -0,0 +1,7 @@ +package body Monitor is + + procedure Touch is + begin + Nops := Nops + 1; + end; +end; diff --git a/testsuite/tests/IA16-028-disp-routines/src/monitor.ads b/testsuite/tests/IA16-028-disp-routines/src/monitor.ads new file mode 100644 index 000000000..a3cd6bf2c --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/src/monitor.ads @@ -0,0 +1,4 @@ +package Monitor is + procedure Touch; + Nops : Integer := 0; +end; diff --git a/testsuite/tests/IA16-028-disp-routines/src/p.adb b/testsuite/tests/IA16-028-disp-routines/src/p.adb new file mode 100644 index 000000000..764987377 --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/src/p.adb @@ -0,0 +1,12 @@ +with Monitor; +with Pack; use Pack; + +procedure P is +begin + I := I + 1; + Q; + R; + if I > 2 then + Monitor.Touch; + end if; +end P; diff --git a/testsuite/tests/IA16-028-disp-routines/src/pack.adb b/testsuite/tests/IA16-028-disp-routines/src/pack.adb new file mode 100644 index 000000000..f05c2c2bd --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/src/pack.adb @@ -0,0 +1,13 @@ +package body Pack is + + procedure Q is + begin + I := I + 2; + end Q; + + procedure R is + begin + I := I + 3; + end R; + +end Pack; diff --git a/testsuite/tests/IA16-028-disp-routines/src/pack.ads b/testsuite/tests/IA16-028-disp-routines/src/pack.ads new file mode 100644 index 000000000..3d5f47dc2 --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/src/pack.ads @@ -0,0 +1,9 @@ +package Pack is + + I : Integer := 3; + + procedure Q; + + procedure R; + +end Pack; diff --git a/testsuite/tests/IA16-028-disp-routines/test.py b/testsuite/tests/IA16-028-disp-routines/test.py new file mode 100644 index 000000000..282413c9d --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/test.py @@ -0,0 +1,59 @@ +import os.path +import re +from shutil import copy + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of, set_from +from SUITE.tutils import (exepath_to, gprbuild, gprfor, + platform_specific_symbols, xcov) + + +Wdir('tmp_') + +# Check that --exclude/--include options are properly supported. + +gprbuild(gprfor(srcdirs=['../src'], mains=['p.adb'])) +exe = exepath_to('p') + +# Simple usage of disp-routines: + +xcov(['disp-routines', exe, '--exclude', 'obj/b__p.o'], + out='routines1.txt') + +r1 = contents_of('routines1.txt') + +for pattern in ('pack__q', 'pack__r', '_ada_p'): + thistest.fail_if(not re.search(pattern, r1), + "'%s' not found in disp-routines output" % pattern) + + +# Check that "p.o - S" return the empty set if p.o is in S: + +xcov(['disp-routines', '--include', 'obj/p.o', '--exclude', exe], + out='routines2.txt') + +thistest.fail_if( + os.path.getsize('routines2.txt') > 0, + 'disp-routines -i p.o -o p.exe should return an empty set. Got:\n' + + contents_of('routines2.txt')) + +# Check various properties: that "S + p.o - p.o" is idempotent iff p.o is in S, +# that "p.o + b~p.o - p.o - b~p.o + p.o" do exclude b~p.o... comparing the +# output of disp-routines against a baseline (do not rely on the order of +# output symbols, it is not defined). + +copy('obj/p.o', 'obj/p1.o') +copy('obj/p.o', 'obj/p2.o') +copy('obj/b__p.o', 'obj/b__p1.o') + +xcov(['disp-routines', 'obj/p.o', 'obj/b__p.o', '--include', 'obj/pack.o', + '--exclude', 'obj/p1.o', 'obj/b__p1.o', '--include', 'obj/p2.o'], + out='routines3.txt') + +baseline3 = set(platform_specific_symbols(set_from('../baseline3.txt'))) +routines3 = set_from('routines3.txt') + +thistest.fail_if(baseline3 != routines3, + 'Advanced usage of disp-routines') + +thistest.result() diff --git a/testsuite/tests/IA19-009-no-useless-srcs/src/engines.adb b/testsuite/tests/IA19-009-no-useless-srcs/src/engines.adb new file mode 100644 index 000000000..6c8a1fb08 --- /dev/null +++ b/testsuite/tests/IA19-009-no-useless-srcs/src/engines.adb @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + return E.P < Stable_P and then E.T < Stable_T; + end Stable; +end Engines; diff --git a/testsuite/tests/IA19-009-no-useless-srcs/src/engines.ads b/testsuite/tests/IA19-009-no-useless-srcs/src/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/IA19-009-no-useless-srcs/src/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/IA19-009-no-useless-srcs/src/test_engines.adb b/testsuite/tests/IA19-009-no-useless-srcs/src/test_engines.adb new file mode 100644 index 000000000..fdec19174 --- /dev/null +++ b/testsuite/tests/IA19-009-no-useless-srcs/src/test_engines.adb @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; + +------------------ +-- Test_Engines -- +------------------ +procedure Test_Engines is + E : Engine; + + procedure Assert (X : Boolean); + + procedure Assert (X : Boolean) is + begin + if not X then + raise Program_Error; + end if; + end Assert; +begin + + -- Exercise various condition/decision combinations in Stable. + + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); + + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); + +end Test_Engines; diff --git a/testsuite/tests/IA19-009-no-useless-srcs/test.py b/testsuite/tests/IA19-009-no-useless-srcs/test.py new file mode 100644 index 000000000..f3905c13b --- /dev/null +++ b/testsuite/tests/IA19-009-no-useless-srcs/test.py @@ -0,0 +1,29 @@ +""" +Check that "gnatcov coverage" does not produce reports for units that are not +of interest. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(['test_engines.adb'], + srcdirs='../src'), + units=['engines']), + covlevel='stmt', + mains=['test_engines'], + extra_coverage_args=['--annotate=xcov'], + scos=['obj/engines']) + +thistest.fail_if(not os.path.exists('engines.adb.xcov') + or os.path.exists('test_engines.adb.xcov'), + 'no annotated file when no sco') +thistest.result() diff --git a/testsuite/tests/IA21-003-simple-decision-sco/src/p.adb b/testsuite/tests/IA21-003-simple-decision-sco/src/p.adb new file mode 100644 index 000000000..a7c50d3a4 --- /dev/null +++ b/testsuite/tests/IA21-003-simple-decision-sco/src/p.adb @@ -0,0 +1,25 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Pack; use Pack; + +procedure Hello is +begin + Not_Fully_Covered_Stmt_Wise; +end; diff --git a/testsuite/tests/IA21-003-simple-decision-sco/src/pack.adb b/testsuite/tests/IA21-003-simple-decision-sco/src/pack.adb new file mode 100644 index 000000000..5675e9c71 --- /dev/null +++ b/testsuite/tests/IA21-003-simple-decision-sco/src/pack.adb @@ -0,0 +1,13 @@ + +package body Pack is + + procedure Not_Fully_Covered_Stmt_Wise is + begin + if Where then + N_True := N_True + 1; + else + N_False := N_False + 1; + end if; + end Not_Fully_Covered_Stmt_Wise; + +end Pack; diff --git a/testsuite/tests/IA21-003-simple-decision-sco/src/pack.ads b/testsuite/tests/IA21-003-simple-decision-sco/src/pack.ads new file mode 100644 index 000000000..89a530e9f --- /dev/null +++ b/testsuite/tests/IA21-003-simple-decision-sco/src/pack.ads @@ -0,0 +1,9 @@ +package Pack is + + N_True, N_False : Natural := 0; + + Where : Boolean := False; + + procedure Not_Fully_Covered_Stmt_Wise; + +end Pack; diff --git a/testsuite/tests/IA21-003-simple-decision-sco/test.opt b/testsuite/tests/IA21-003-simple-decision-sco/test.opt new file mode 100644 index 000000000..4ac701d56 --- /dev/null +++ b/testsuite/tests/IA21-003-simple-decision-sco/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Tests compiler-provided SCOs diff --git a/testsuite/tests/IA21-003-simple-decision-sco/test.py b/testsuite/tests/IA21-003-simple-decision-sco/test.py new file mode 100644 index 000000000..6463762c7 --- /dev/null +++ b/testsuite/tests/IA21-003-simple-decision-sco/test.py @@ -0,0 +1,21 @@ +""" +Check that gnatcov correctly loads and interprets a simple decision SCO. +""" +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +Wdir('tmp_') + +gprbuild(gprfor(srcdirs=['../src'], mains=['p.adb'])) +xrun(exepath_to('p')) + +xcov(['map-routines', '--scos=obj/pack.ali']) +xcov(['coverage', '--level=stmt', '--annotate=report', '--scos=obj/pack.ali', + '--report=out', tracename_for('p')]) +thistest.fail_if(not match('pack.adb:7:.* statement not executed', 'out'), + 'missing expected s- diagnostic with simple decision sco') + +thistest.result() diff --git a/testsuite/tests/IA21-009-nested-scos/src/nested_same_sloc.adb b/testsuite/tests/IA21-009-nested-scos/src/nested_same_sloc.adb new file mode 100644 index 000000000..979a55925 --- /dev/null +++ b/testsuite/tests/IA21-009-nested-scos/src/nested_same_sloc.adb @@ -0,0 +1,9 @@ +pragma Warnings (Off); +procedure Nested_Same_Sloc is + A, B : Boolean; +begin + if (A and then B) = True then + null; + end if; + raise Program_Error; +end Nested_Same_Sloc; diff --git a/testsuite/tests/IA21-009-nested-scos/test.py b/testsuite/tests/IA21-009-nested-scos/test.py new file mode 100644 index 000000000..2bcf63374 --- /dev/null +++ b/testsuite/tests/IA21-009-nested-scos/test.py @@ -0,0 +1,9 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor, xcov + + +Wdir('tmp_') +gprbuild(gprfor(['nested_same_sloc.adb'], srcdirs='../src')) +xcov(['map-routines', '--scos=obj/nested_same_sloc.ali']) +thistest.result() diff --git a/testsuite/tests/IA22-004-same-basename/.gitignore b/testsuite/tests/IA22-004-same-basename/.gitignore new file mode 100644 index 000000000..1861073fc --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/.gitignore @@ -0,0 +1 @@ +main.elf.trace diff --git a/testsuite/tests/IA22-004-same-basename/d1/func.c b/testsuite/tests/IA22-004-same-basename/d1/func.c new file mode 100644 index 000000000..fe91e5b7f --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/d1/func.c @@ -0,0 +1,5 @@ +int +func1 (int a) +{ + return a * 2; +} diff --git a/testsuite/tests/IA22-004-same-basename/d2/func.c b/testsuite/tests/IA22-004-same-basename/d2/func.c new file mode 100644 index 000000000..3e7b7055e --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/d2/func.c @@ -0,0 +1,5 @@ +int +func2 (int a) +{ + return a * 3; +} diff --git a/testsuite/tests/IA22-004-same-basename/main.c b/testsuite/tests/IA22-004-same-basename/main.c new file mode 100644 index 000000000..6bea78070 --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/main.c @@ -0,0 +1,29 @@ +extern int func1 (int); +extern int func2 (int); +extern void putchar (int); + +void +put_digit (int a) +{ + putchar ('0' + a); +} + +void +put_str (char *s) +{ + while (*s) + putchar (*s++); +} + +int +c_main (void) +{ + put_str ("func2: "); + put_digit (func2 (1)); + putchar ('\n'); + put_str ("func1: "); + put_digit (func1 (2)); + putchar ('\n'); + + return 0; +} diff --git a/testsuite/tests/IA22-004-same-basename/main.elf b/testsuite/tests/IA22-004-same-basename/main.elf new file mode 100755 index 0000000000000000000000000000000000000000..ccdc729269176219cb8baf0ad02aa1a387860591 GIT binary patch literal 77580 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 literal 0 HcmV?d00001 diff --git a/testsuite/tests/IA22-004-same-basename/put.adb b/testsuite/tests/IA22-004-same-basename/put.adb new file mode 100644 index 000000000..2668ad7b5 --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/put.adb @@ -0,0 +1,8 @@ +with ada.text_io; + +package body put is + procedure putchar (c : integer) is + begin + ada.text_io.put (Character'val (C)); + end putchar; +end put; diff --git a/testsuite/tests/IA22-004-same-basename/put.ads b/testsuite/tests/IA22-004-same-basename/put.ads new file mode 100644 index 000000000..f40a17fd6 --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/put.ads @@ -0,0 +1,4 @@ +package put is + procedure putchar (c : integer); + pragma export (c, putchar); +end put; diff --git a/testsuite/tests/IA22-004-same-basename/repro.adb b/testsuite/tests/IA22-004-same-basename/repro.adb new file mode 100644 index 000000000..af1c4ac36 --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/repro.adb @@ -0,0 +1,8 @@ +with put; + +procedure repro is + procedure c_main; + pragma import (c, c_main); +begin + c_main; +end repro; diff --git a/testsuite/tests/IA22-004-same-basename/test.opt b/testsuite/tests/IA22-004-same-basename/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/IA22-004-same-basename/test.py b/testsuite/tests/IA22-004-same-basename/test.py new file mode 100644 index 000000000..eb4d28258 --- /dev/null +++ b/testsuite/tests/IA22-004-same-basename/test.py @@ -0,0 +1,56 @@ +""" +Perform a bunch of xcov related operations to validate the basic toolset +functionalities. +""" + +import os + +from SUITE.context import thistest +from SUITE.cutils import match +from SUITE.tutils import maybe_valgrind, xcov, xrun + + +# Built with: +# powerpc-elf-gcc -g -c d1/func.c -o d1/func.o +# powerpc-elf-gcc -g -c d2/func.c -o d2/func.o +# powerpc-elf-gcc -g -c main.c +# gprbuild --target=powerpc-elf --RTS=zfp-mpc8641 -g repro -largs main.o \ +# */func.o +# mv repro main.elf + +# Context information, basic command line interface checks +print('maybe_valgrind prepends ...', maybe_valgrind([])) + +xrun('main.elf') + +formats = [('xml', '{slug}.xml', r''), + ('html', '{slug}.hunk.js', r'"coverage":"\+","assembly"'), + ('xcov+', '{slug}.xcov', r' *[0-9]+ \+:')] + + +# The pre-built binary embeds full paths to the sources at their build +# time location. We need to rebase to find the files in the current +# dir. The paths gnatcov uses are internally canonicalized, which yields +# Windows or Unix paths depending on the host ... + +def hostify(path): + return ("C:" + path.replace('/', '\\') + if thistest.env.build.os.name == 'windows' + else path) + + +rebase_args = [ + "--source-rebase={}={}".format( + hostify(f"{path}/tests/IA22-004-same-basename"), os.getcwd()) + for path in ("/home/pmderodat/_git/gnatcoverage/testsuite", + "/home/pmderodat/_git/gnatcoverage-extra")] + +for fmt, filename, pattern in formats: + xcov(['coverage', '--level=insn', '--annotate=' + fmt, 'main.elf.trace', + '--output-dir=tmp'] + rebase_args) + + for slug in ('d1-func.c', 'd2-func.c'): + output = 'tmp/' + filename.format(base='func.c', slug=slug) + thistest.fail_if(not match(pattern, output), + 'no line covered in {}'.format(output)) +thistest.result() diff --git a/testsuite/tests/IA29-020-basic-checks/src/engines.adb b/testsuite/tests/IA29-020-basic-checks/src/engines.adb new file mode 100644 index 000000000..6c8a1fb08 --- /dev/null +++ b/testsuite/tests/IA29-020-basic-checks/src/engines.adb @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + return E.P < Stable_P and then E.T < Stable_T; + end Stable; +end Engines; diff --git a/testsuite/tests/IA29-020-basic-checks/src/engines.ads b/testsuite/tests/IA29-020-basic-checks/src/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/IA29-020-basic-checks/src/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/IA29-020-basic-checks/src/test_engines.adb b/testsuite/tests/IA29-020-basic-checks/src/test_engines.adb new file mode 100644 index 000000000..fdec19174 --- /dev/null +++ b/testsuite/tests/IA29-020-basic-checks/src/test_engines.adb @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; + +------------------ +-- Test_Engines -- +------------------ +procedure Test_Engines is + E : Engine; + + procedure Assert (X : Boolean); + + procedure Assert (X : Boolean) is + begin + if not X then + raise Program_Error; + end if; + end Assert; +begin + + -- Exercise various condition/decision combinations in Stable. + + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); + + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); + +end Test_Engines; diff --git a/testsuite/tests/IA29-020-basic-checks/test.opt b/testsuite/tests/IA29-020-basic-checks/test.opt new file mode 100644 index 000000000..d2cc065d3 --- /dev/null +++ b/testsuite/tests/IA29-020-basic-checks/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test uses object coverage diff --git a/testsuite/tests/IA29-020-basic-checks/test.py b/testsuite/tests/IA29-020-basic-checks/test.py new file mode 100644 index 000000000..b7d6f30ac --- /dev/null +++ b/testsuite/tests/IA29-020-basic-checks/test.py @@ -0,0 +1,65 @@ +""" +Check that a we can run the engines example with all possible coverage +level/annotations without crashing. And check the xcov/xcov+ annotated reports. +""" + +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import FatalError, Wdir, match +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +Wdir('tmp_') +gprbuild(project=gprfor(['test_engines.adb'], srcdirs='../src')) +xrun(exepath_to('test_engines')) +line = ': return E.P < Stable_P and then E.T < Stable_T;' + + +def src_cov(cov_level, annotate_level, line_coverage): + try: + xcov(['coverage', + '--level=' + cov_level, '--annotate=' + annotate_level, + '--scos=obj/engines.ali', tracename_for('test_engines')]) + if annotate_level.find('xcov') != -1: + thistest.fail_if(not match('[0-9]+ ' + line_coverage + line, + 'engines.adb.xcov'), + 'check ' + cov_level + + ' coverage results on engines example') + except FatalError: + pass + + +def obj_cov(cov_level, annotate_level, line_coverage): + symbol = target_info().to_platform_specific_symbol('engines__stable') + xcov(['coverage', + '--level=' + cov_level, '--annotate=' + annotate_level, + '--routines={}'.format(symbol), tracename_for('test_engines')]) + if annotate_level.find('xcov') != -1: + thistest.fail_if(not match('[0-9]+ ' + line_coverage + line, + 'engines.adb.xcov'), + 'check ' + cov_level + + ' coverage results on engines example') + + +src_cov_levels = ['stmt', 'stmt+decision', 'stmt+mcdc'] +annotate_levels = ['xcov', 'html'] + +obj_cov_levels = ['insn', 'branch'] +obj_annotate_levels = annotate_levels + ['asm', 'html+', 'xcov+'] + +line_coverage = {'insn': r'\+', + 'branch': '!', + 'stmt': r'\+', + 'stmt+decision': r'\+', + 'stmt+mcdc': '!'} + +for cov_level in obj_cov_levels: + for annotate_level in obj_annotate_levels: + obj_cov(cov_level, annotate_level, line_coverage[cov_level]) + +for cov_level in src_cov_levels: + for annotate_level in annotate_levels: + src_cov(cov_level, annotate_level, line_coverage[cov_level]) + +thistest.result() diff --git a/testsuite/tests/IA29-023-source-search/src/engines.adb b/testsuite/tests/IA29-023-source-search/src/engines.adb new file mode 100644 index 000000000..6c8a1fb08 --- /dev/null +++ b/testsuite/tests/IA29-023-source-search/src/engines.adb @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + return E.P < Stable_P and then E.T < Stable_T; + end Stable; +end Engines; diff --git a/testsuite/tests/IA29-023-source-search/src/engines.ads b/testsuite/tests/IA29-023-source-search/src/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/IA29-023-source-search/src/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/IA29-023-source-search/src/test_engines.adb b/testsuite/tests/IA29-023-source-search/src/test_engines.adb new file mode 100644 index 000000000..fdec19174 --- /dev/null +++ b/testsuite/tests/IA29-023-source-search/src/test_engines.adb @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; + +------------------ +-- Test_Engines -- +------------------ +procedure Test_Engines is + E : Engine; + + procedure Assert (X : Boolean); + + procedure Assert (X : Boolean) is + begin + if not X then + raise Program_Error; + end if; + end Assert; +begin + + -- Exercise various condition/decision combinations in Stable. + + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); + + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); + +end Test_Engines; diff --git a/testsuite/tests/IA29-023-source-search/test.py b/testsuite/tests/IA29-023-source-search/test.py new file mode 100644 index 000000000..a72bcb14f --- /dev/null +++ b/testsuite/tests/IA29-023-source-search/test.py @@ -0,0 +1,43 @@ +""" +Basic test on the --source-search option +""" +import os + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, empty +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +Wdir("tmp_") + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(["test_engines.adb"], + srcdirs="../src")), + covlevel="stmt", + mains=["test_engines"], + extra_coverage_args=["--annotate=xcov"], + scos=["obj/engines"] +) + +xcov(xcov_args + ["--source-search=./src"], out="warnings1.txt") +thistest.fail_if(not empty("warnings1.txt"), "no source warning") + +os.rename("../src", "../newsrc") + +xcov(xcov_args + ["--source-search=../newsrc"], out="warnings2.txt") +thistest.fail_if(not empty("warnings2.txt"), "Source search unsuccessful") + +# Same test but with a response file +source_search_filename = os.path.abspath("src-search.txt") +with open(source_search_filename, 'w') as f: + f.write(os.path.join("..", "newsrc")) + +xcov(xcov_args + [f"--source-search=@{source_search_filename}"], out="warnings3.txt") +thistest.fail_if(not empty("warnings3.txt"), + "Source search unsuccessful (response file)") + +os.rename("../newsrc", "../src") + +thistest.result() diff --git a/testsuite/tests/J618-019-disa-x86/insn.o b/testsuite/tests/J618-019-disa-x86/insn.o new file mode 100644 index 0000000000000000000000000000000000000000..edff7874bef87d8de2a148c4651fff2ef93a9a3c GIT binary patch literal 466 zcmb<-^>JflWMqH=Mh0dE1do9s1u9_zrZpJY8CV$jmmXqZ&?~OYElErQ(j`R@Is?Wk zNv$Yh&`U`yNo3GVDlUc@O^}ubssP!|22}~NlNrheQ7lllB9I2DgUMMy#bFdoojOo} zg9vqkNNPZ4fXveYF`xhz9w3?tCJ3Z!fC2$P8suJ(oggd##GF73a~qJ!a0aLj<|hyz eW*&%*3!ugV$UJ15L41S?kX=F`Q`1WGk{JMLAQvkD literal 0 HcmV?d00001 diff --git a/testsuite/tests/J618-019-disa-x86/insn.s b/testsuite/tests/J618-019-disa-x86/insn.s new file mode 100644 index 000000000..fcb6f17cf --- /dev/null +++ b/testsuite/tests/J618-019-disa-x86/insn.s @@ -0,0 +1,6 @@ + .text + .globl func + .type func,@function +func: + shld %cl,%eax,%edx + .size func, . - func diff --git a/testsuite/tests/J618-019-disa-x86/test.opt b/testsuite/tests/J618-019-disa-x86/test.opt new file mode 100644 index 000000000..3724a5c21 --- /dev/null +++ b/testsuite/tests/J618-019-disa-x86/test.opt @@ -0,0 +1 @@ +!32bits DEAD diff --git a/testsuite/tests/J618-019-disa-x86/test.py b/testsuite/tests/J618-019-disa-x86/test.py new file mode 100644 index 000000000..e8f355d23 --- /dev/null +++ b/testsuite/tests/J618-019-disa-x86/test.py @@ -0,0 +1,8 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + + +Wdir('tmp_') +xcov(['disassemble', '../insn.o'], 'insn.dis') +thistest.result() diff --git a/testsuite/tests/J723-017-empty-debug-info/ada_containers-aunit_lists.elf b/testsuite/tests/J723-017-empty-debug-info/ada_containers-aunit_lists.elf new file mode 100644 index 0000000000000000000000000000000000000000..15473fc101d8bc1f93ec83d51adb0dafdfba9bb5 GIT binary patch literal 1018 zcma)4O-sW-5Z&1NQ9nS%o0s)u1zn=H9y|!8*j}WF=)qIi*r)-UNV4_gB>1~L_?HB| z3H4376Bj{r;AP&tH#@so_UZ7b<4t&?3{R|pJA!yGyhib@iv=+Y)@`@l ztD17h-}e2+_O854GuiF6PUUfy%01Ok{=KYQcV|Piuz2Yz85TR#s@{wzRQ@vJ?(0Bf zPWEqoC$^8zM}6)(=I2)Tkty~7ItvH&5yEsd`d|_H7Fc#_p0@;z_ayrn$cWhBKFSj; zf_{R(0`tHePz4r&8sN;Uyr4b+ICvh{oJ+kbMsF-q#<0?}wR4WbclIl4I!hTaC(8l^ zHNUAsMm_z*r*~2YeEKJ81rHZCEp%T87inTNUVWBt>0uI^;3m#Zu5>^AVF!WZ2Z!Pd DKtW!z literal 0 HcmV?d00001 diff --git a/testsuite/tests/J723-017-empty-debug-info/test.opt b/testsuite/tests/J723-017-empty-debug-info/test.opt new file mode 100644 index 000000000..3724a5c21 --- /dev/null +++ b/testsuite/tests/J723-017-empty-debug-info/test.opt @@ -0,0 +1 @@ +!32bits DEAD diff --git a/testsuite/tests/J723-017-empty-debug-info/test.py b/testsuite/tests/J723-017-empty-debug-info/test.py new file mode 100644 index 000000000..bf4812dc7 --- /dev/null +++ b/testsuite/tests/J723-017-empty-debug-info/test.py @@ -0,0 +1,8 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + + +Wdir('tmp_') +xcov(['dump-lines', '../ada_containers-aunit_lists.elf'], 'dwarf.out') +thistest.result() diff --git a/testsuite/tests/JC09-015-set-file/hello.o b/testsuite/tests/JC09-015-set-file/hello.o new file mode 100644 index 0000000000000000000000000000000000000000..785839fb926d99e0cb22c619f5bf777587be61df GIT binary patch literal 2848 zcmeH}TW=dx5XaBPldBy!m$pzs;cuXA5}J+o+Bhw_5K0h4Q6-Wmkir_Gz=W$jp58>&0JRCLf&dKQ?e? zog2mZe6F}qoOR}$nK5HVT(eoo71#53^WSWx*)7hBt(y@UNS;J_nh!T6?3=SDWBSw@ zj+8CvJZoB()wy@b`Lj4}95zm}JLX}%*=)N>ttu-TC(XL=o?96VWjK`4P{u=fXDHW( zvNDujS!qvc1@sirQ%FxSJq7g?)l*ncaec-071vi>UvYiK^%d7wTwig0#q||8P~1Rq z1H}y#H&EO_aRbE-6gN=ZKygFG4HY+3+)!~t#SIlVRNPQ;L&XghH&Wb4aU;cz6gN`b zNO2>@jTARh+(>a_#f=p=R@_)|W5taXH&)zOabv}eGp;eC>B~63Q7X|0Cf~G)uPysXzDuOP7W>7eEW37eUuSFM(bL0aOCL z0(uqn8t4Y-Cg>Ju5wrwa2E7it4O#)YpjA*A$u<sd;JzPnSdtdzaT93{2nDBUsC zzOlQ1i0xW}(2ZOle%a%{a)?H|gWdh@13c)o5xb#V{tS!RY_QZ{Z_Mt_&N>#k#nOLV zzs;M}{Bi3n{bkCNGvO2*<90tk?Il$nd!7FH(5hbjyl326(o2k6?RHt#t7peYNwwOk ze`?%Ly_saGlUAesk3{pNRk!ur&bS}9PfzPDZpVB#>Ge7%)w5o`E8FJ3HQAtL56(7s z!@s8eO+0Hr*;vZza{bt8W_deE53yV96YS5byUjIrjY#RY%x=xjZF0hDk>B%S!xpKz zb=LM=Sx$Y;hi}>C2WpgE<_hc&*mb|3dCKLSH9PknCse<@e0#`x={KIuN&F$ZtSPgz zjmhgM*J4fP#E-Ml*0ng6bGBydK51WE{9%*a?+4bxwkCCAv+UVDmT>GxK0FqcnXQvC z-6Hz=$tOJi#9n02v&%Kkuurn9ep5A$ud`dT{cLQM=eEeL=w6wmKeg25%`zN15>HAdT)3<&29ZAZKT## N_+Kwun>(~Me*?wpbcz4~ literal 0 HcmV?d00001 diff --git a/testsuite/tests/JC09-015-set-file/hello.s b/testsuite/tests/JC09-015-set-file/hello.s new file mode 100644 index 000000000..60c75c4a3 --- /dev/null +++ b/testsuite/tests/JC09-015-set-file/hello.s @@ -0,0 +1,319 @@ + .file "hello.adb" + .gnu_attribute 4, 1 + .gnu_attribute 8, 1 + .gnu_attribute 12, 1 + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .section .debug_line,"",@progbits +.Ldebug_line0: + .section ".text" +.Ltext0: + .align 2 + .globl _ada_hello + .type _ada_hello, @function +_ada_hello: +.LFB1: + .file 1 "hello.adb" + .loc 1 2 0 + stwu 1,-16(1) + stw 31,12(1) + mr 31,1 + .loc 1 4 0 + nop + .loc 1 5 0 + nop + .loc 1 6 0 + nop + .file 2 "file2.x" + .loc 2 6 0 + nop + .file 3 "file3.x" + .loc 3 6 0 + nop + .file 4 "file4.x" + .loc 4 6 0 + nop + .file 5 "file5.x" + .loc 5 6 0 + nop + .file 6 "file6.x" + .loc 6 6 0 + nop + .file 7 "file7.x" + .loc 7 6 0 + nop + .file 8 "file8.x" + .loc 8 6 0 + nop + .file 9 "file9.x" + .loc 9 6 0 + nop + .file 10 "file10.x" + .loc 10 6 0 + nop + .file 11 "file11.x" + .loc 11 6 0 + nop + .file 12 "file12.x" + .loc 12 6 0 + nop + .file 13 "file13.x" + .loc 13 6 0 + nop + .file 14 "file14.x" + .loc 14 6 0 + nop + .file 15 "file15.x" + .loc 15 6 0 + nop + .file 16 "file16.x" + .loc 16 6 0 + nop + .file 17 "file17.x" + .loc 17 6 0 + nop + .file 18 "file18.x" + .loc 18 6 0 + nop + .file 19 "file19.x" + .loc 19 6 0 + nop + .file 20 "file20.x" + .loc 20 6 0 + nop + .file 21 "file21.x" + .loc 21 6 0 + nop + .file 22 "file22.x" + .loc 22 6 0 + nop + .file 23 "file23.x" + .loc 23 6 0 + nop + .file 24 "file24.x" + .loc 24 6 0 + nop + .file 25 "file25.x" + .loc 25 6 0 + nop + .file 26 "file26.x" + .loc 26 6 0 + nop + .file 27 "file27.x" + .loc 27 6 0 + nop + .file 28 "file28.x" + .loc 28 6 0 + nop + .file 29 "file29.x" + .loc 29 6 0 + nop + .file 30 "file30.x" + .loc 30 6 0 + nop + .file 31 "file31.x" + .loc 31 6 0 + nop + .file 32 "file32.x" + .loc 32 6 0 + nop + .file 33 "file33.x" + .loc 33 6 0 + nop + .file 34 "file34.x" + .loc 34 6 0 + nop + .file 35 "file35.x" + .loc 35 6 0 + nop + .file 36 "file36.x" + .loc 36 6 0 + nop + .file 37 "file37.x" + .loc 37 6 0 + nop + .file 38 "file38.x" + .loc 38 6 0 + nop + .file 39 "file39.x" + .loc 39 6 0 + nop + .file 40 "file40.x" + .loc 40 6 0 + nop + .file 41 "file41.x" + .loc 41 6 0 + nop + .file 42 "file42.x" + .loc 42 6 0 + nop + .file 43 "file43.x" + .loc 43 6 0 + nop + .file 44 "file44.x" + .loc 44 6 0 + nop + .file 45 "file45.x" + .loc 45 6 0 + nop + .file 46 "file46.x" + .loc 46 6 0 + nop + .file 47 "file47.x" + .loc 47 6 0 + nop + .file 48 "file48.x" + .loc 48 6 0 + nop + .file 49 "file49.x" + .loc 49 6 0 + nop + .file 50 "file50.x" + .loc 50 6 0 + nop + .file 51 "file51.x" + .loc 51 6 0 + nop + .file 52 "file52.x" + .loc 52 6 0 + nop + .file 53 "file53.x" + .loc 53 6 0 + nop + .file 54 "file54.x" + .loc 54 6 0 + nop + .file 55 "file55.x" + .loc 55 6 0 + nop + .file 56 "file56.x" + .loc 56 6 0 + nop + .file 57 "file57.x" + .loc 57 6 0 + nop + .file 58 "file58.x" + .loc 58 6 0 + nop + .file 59 "file59.x" + .loc 59 6 0 + nop + .file 60 "file60.x" + .loc 60 6 0 + nop + .file 61 "file61.x" + .loc 61 6 0 + nop + .file 62 "file62.x" + .loc 62 6 0 + nop + .file 63 "file63.x" + .loc 63 6 0 + nop + .file 64 "file64.x" + .loc 64 6 0 + nop + .file 65 "file65.x" + .loc 65 6 0 + nop + .file 66 "file66.x" + .loc 66 6 0 + nop + .file 67 "file67.x" + .loc 67 6 0 + nop + .file 68 "file68.x" + .loc 68 6 0 + nop + .file 69 "file69.x" + .loc 69 6 0 + nop + addi 11,31,16 + lwz 31,-4(11) + mr 1,11 + blr +.LFE1: + .size _ada_hello, .-_ada_hello + .align 2 +.LEFDE0: + .section ".text" +.Letext0: + .section .debug_info + .4byte 0x3a + .2byte 0x2 + .4byte .Ldebug_abbrev0 + .byte 0x4 + .uleb128 0x1 + .4byte .LASF0 + .byte 0xd + .4byte .LASF1 + .4byte .LASF2 + .4byte .Ltext0 + .4byte .Letext0 + .4byte .Ldebug_line0 + .uleb128 0x2 + .byte 0x1 + .4byte .LASF3 + .byte 0x1 + .byte 0x2 + .4byte .LASF4 + .4byte .LFB1 + .4byte .LFE1 + .4byte .LLST0 + .byte 0x0 + .section .debug_abbrev + .uleb128 0x1 + .uleb128 0x11 + .byte 0x1 + .uleb128 0x25 + .uleb128 0xe + .uleb128 0x13 + .uleb128 0xb + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x1b + .uleb128 0xe + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x1 + .uleb128 0x10 + .uleb128 0x6 + .byte 0x0 + .byte 0x0 + .uleb128 0x2 + .uleb128 0x2e + .byte 0x0 + .uleb128 0x3f + .uleb128 0xc + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x2007 + .uleb128 0xe + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x1 + .uleb128 0x40 + .uleb128 0x6 + .byte 0x0 + .byte 0x0 + .byte 0x0 + .section .debug_str,"MS",@progbits,1 +.LASF2: + .string "/Users/gingold/TN/JC09-015" +.LASF4: + .string "_ada_hello" +.LASF1: + .string "hello.adb" +.LASF0: + .string "GNU Ada 4.5.2 20101004 for GNAT Pro 6.4.0w (20101003)" +.LASF3: + .string "hello" + .ident "GCC: (GNU) 4.5.2 20101004 for GNAT Pro 6.4.0w (20101003)" diff --git a/testsuite/tests/JC09-015-set-file/test.opt b/testsuite/tests/JC09-015-set-file/test.opt new file mode 100644 index 000000000..3724a5c21 --- /dev/null +++ b/testsuite/tests/JC09-015-set-file/test.opt @@ -0,0 +1 @@ +!32bits DEAD diff --git a/testsuite/tests/JC09-015-set-file/test.py b/testsuite/tests/JC09-015-set-file/test.py new file mode 100644 index 000000000..107738555 --- /dev/null +++ b/testsuite/tests/JC09-015-set-file/test.py @@ -0,0 +1,8 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + + +Wdir('tmp_') +xcov(['dump-lines', '../hello.o'], 'dwarf.out') +thistest.result() diff --git a/testsuite/tests/K214-014-gc-sections/src/foo.adb b/testsuite/tests/K214-014-gc-sections/src/foo.adb new file mode 100644 index 000000000..335884ad2 --- /dev/null +++ b/testsuite/tests/K214-014-gc-sections/src/foo.adb @@ -0,0 +1,8 @@ +with Pck; use Pck; + +procedure Foo is +begin + Break_Me (1); + Break_Me (True); +end Foo; + diff --git a/testsuite/tests/K214-014-gc-sections/src/pck.adb b/testsuite/tests/K214-014-gc-sections/src/pck.adb new file mode 100644 index 000000000..7eaf4b4b4 --- /dev/null +++ b/testsuite/tests/K214-014-gc-sections/src/pck.adb @@ -0,0 +1,16 @@ +package body Pck is + procedure Break_Me (I : Integer) is + begin + null; -- COVERED + end Break_Me; + + procedure Discard is + begin + null; -- ELIMINATED + end Discard; + + procedure Break_Me (B : Boolean) is + begin + null; + end Break_Me; +end Pck; diff --git a/testsuite/tests/K214-014-gc-sections/src/pck.ads b/testsuite/tests/K214-014-gc-sections/src/pck.ads new file mode 100644 index 000000000..4def5b16d --- /dev/null +++ b/testsuite/tests/K214-014-gc-sections/src/pck.ads @@ -0,0 +1,5 @@ +package Pck is + procedure Break_Me (I : Integer); + procedure Discard; + procedure Break_Me (B : Boolean); +end Pck; diff --git a/testsuite/tests/K214-014-gc-sections/test.opt b/testsuite/tests/K214-014-gc-sections/test.opt new file mode 100644 index 000000000..fcd9f35d9 --- /dev/null +++ b/testsuite/tests/K214-014-gc-sections/test.opt @@ -0,0 +1,3 @@ +ppc-vx6 XFAIL minor issue of debug info not stripped through gc-section, L815-002 +e500v2-vx6 XFAIL minor issue of debug info not stripped through gc-section, L815-002 +!bin-traces DEAD Test a behavior that is specific to binary traces diff --git a/testsuite/tests/K214-014-gc-sections/test.py b/testsuite/tests/K214-014-gc-sections/test.py new file mode 100644 index 000000000..b068eb6be --- /dev/null +++ b/testsuite/tests/K214-014-gc-sections/test.py @@ -0,0 +1,22 @@ +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.cutils import Wdir, match +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +Wdir('tmp_') +extralargs = ',--entry=foo' if target_info().partiallinks else '' + +gprbuild(gprfor(['foo.adb'], srcdirs='../src'), + extracargs='-ffunction-sections', + largs='-Wl,--gc-sections' + extralargs) +xrun(exepath_to('foo')) +xcov(['coverage', '--level=stmt', '--annotate=xcov', '--scos=obj/pck.ali', + tracename_for('foo')], out='ignore.out') + +thistest.fail_if(not match(r'\.: null; -- ELIMINATED', 'pck.adb.xcov'), + 'eliminated code not reported') +thistest.fail_if(not match(r'\+: null; -- COVERED', 'pck.adb.xcov'), + 'code not eliminated not reported') +thistest.result() diff --git a/testsuite/tests/K317-011_raven-textio/src/test_textio.adb b/testsuite/tests/K317-011_raven-textio/src/test_textio.adb new file mode 100644 index 000000000..c6398d035 --- /dev/null +++ b/testsuite/tests/K317-011_raven-textio/src/test_textio.adb @@ -0,0 +1,8 @@ +with Text_IO; +procedure test_textio is +begin + Text_IO.Put_Line ("cover me"); -- # run +end; + +--# test_textio.adb +-- /self/ l+ ## 0 diff --git a/testsuite/tests/K317-011_raven-textio/test.opt b/testsuite/tests/K317-011_raven-textio/test.opt new file mode 100644 index 000000000..65d7415e5 --- /dev/null +++ b/testsuite/tests/K317-011_raven-textio/test.opt @@ -0,0 +1,2 @@ +powerpc,RTS_RAVENSCAR +ALL DEAD diff --git a/testsuite/tests/K317-011_raven-textio/test.py b/testsuite/tests/K317-011_raven-textio/test.py new file mode 100644 index 000000000..4cf790490 --- /dev/null +++ b/testsuite/tests/K317-011_raven-textio/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase(category=None).run() +thistest.result() diff --git a/testsuite/tests/K804-031_raise-taken/src/args.adb b/testsuite/tests/K804-031_raise-taken/src/args.adb new file mode 100644 index 000000000..174c74e35 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/args.adb @@ -0,0 +1,6 @@ +package body Args is + function Id (X : Num) return Num is + begin + return X; + end; +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/args.ads b/testsuite/tests/K804-031_raise-taken/src/args.ads new file mode 100644 index 000000000..d2fdc703e --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/args.ads @@ -0,0 +1,8 @@ +package Args is + + -- Constrained value subject to easy out-of-range check failure + + type Num is range -10 .. 10; + + function Id (X : Num) return Num; +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/test_val_ce.adb b/testsuite/tests/K804-031_raise-taken/src/test_val_ce.adb new file mode 100644 index 000000000..e85c1eb60 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_val_ce.adb @@ -0,0 +1,14 @@ +with Args, Val; use Args, Val; + +procedure Test_Val_CE is + X : Boolean; +begin + X := Ge0 (Num'Last); +end; + +--# val.adb +-- /eval/ l! ## d- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /handler/ l+ ## 0 + diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vif_r.adb b/testsuite/tests/K804-031_raise-taken/src/test_vif_r.adb new file mode 100644 index 000000000..ebafd904a --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_vif_r.adb @@ -0,0 +1,12 @@ +with Args, Vif; use Args, Vif; + +procedure Test_Vif_R is +begin + Check_Ge0 (Num'Last); +end; + +--# vif.adb +-- /eval/ l! ## d- +-- /true/ l- ## s- +-- /handler/ l+ ## 0 + diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vif_rf.adb b/testsuite/tests/K804-031_raise-taken/src/test_vif_rf.adb new file mode 100644 index 000000000..077e61b14 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_vif_rf.adb @@ -0,0 +1,13 @@ +with Args, Vif; use Args, Vif; + +procedure Test_Vif_RF is +begin + Check_Ge0 (Num'Last); + Check_Ge0 (-1); +end; + +--# vif.adb +-- /eval/ l! ## dT- +-- /true/ l- ## s- +-- /handler/ l+ ## 0 + diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vif_rt.adb b/testsuite/tests/K804-031_raise-taken/src/test_vif_rt.adb new file mode 100644 index 000000000..7e08bc5c8 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_vif_rt.adb @@ -0,0 +1,13 @@ +with Args, Vif; use Args, Vif; + +procedure Test_Vif_RT is +begin + Check_Ge0 (Num'Last); + Check_Ge0 (1); +end; + +--# vif.adb +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /handler/ l+ ## 0 + diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vifn_r.adb b/testsuite/tests/K804-031_raise-taken/src/test_vifn_r.adb new file mode 100644 index 000000000..3d26c7fd1 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_vifn_r.adb @@ -0,0 +1,12 @@ +with Args, Vifn; use Args, Vifn; + +procedure Test_Vifn_R is +begin + Check_Ge0 (Num'Last); +end; + +--# vifn.adb +-- /eval/ l! ## d- +-- /true/ l- ## s- +-- /handler/ l+ ## 0 + diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vifn_rf.adb b/testsuite/tests/K804-031_raise-taken/src/test_vifn_rf.adb new file mode 100644 index 000000000..9fd9d931c --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_vifn_rf.adb @@ -0,0 +1,13 @@ +with Args, Vifn; use Args, Vifn; + +procedure Test_Vifn_RF is +begin + Check_Ge0 (Num'Last); + Check_Ge0 (-1); +end; + +--# vifn.adb +-- /eval/ l! ## dT- +-- /true/ l- ## s- +-- /handler/ l+ ## 0 + diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vifn_rt.adb b/testsuite/tests/K804-031_raise-taken/src/test_vifn_rt.adb new file mode 100644 index 000000000..a3b704fb8 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/test_vifn_rt.adb @@ -0,0 +1,13 @@ +with Args, Vifn; use Args, Vifn; + +procedure Test_Vifn_RT is +begin + Check_Ge0 (Num'Last); + Check_Ge0 (1); +end; + +--# vifn.adb +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /handler/ l+ ## 0 + diff --git a/testsuite/tests/K804-031_raise-taken/src/val.adb b/testsuite/tests/K804-031_raise-taken/src/val.adb new file mode 100644 index 000000000..d3b37c0c8 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/val.adb @@ -0,0 +1,20 @@ +package body Val is + + -- Tests rely on the runtime check for the Id argument: we need a runtime + -- check even when compiled with -gnatp. + + pragma Unsuppress (All_Checks); + + function GE0 (X : Num) return Boolean is + begin + if Id (X + 1) > 0 then -- # eval + return True; -- # true + else + return False; -- # false + end if; + exception + when Constraint_Error => + return X >= 0; -- # handler + end; + +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/val.ads b/testsuite/tests/K804-031_raise-taken/src/val.ads new file mode 100644 index 000000000..2f63303a1 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/val.ads @@ -0,0 +1,5 @@ +with Args; use Args; + +package Val is + function GE0 (X : Num) return Boolean; +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/vif.adb b/testsuite/tests/K804-031_raise-taken/src/vif.adb new file mode 100644 index 000000000..9e29b3a52 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/vif.adb @@ -0,0 +1,18 @@ +package body Vif is + + -- Tests rely on the runtime check for the Id argument: we need a runtime + -- check even when compiled with -gnatp. + + pragma Unsuppress (All_Checks); + + procedure Check_GE0 (X : Num) is + begin + if Id (X + 1) > 0 then -- # eval + N_Ge0 := N_Ge0 + 1; -- # true + end if; + exception + when Constraint_Error => + N_Check_Raise := N_Check_Raise + 1; -- # handler + end; + +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/vif.ads b/testsuite/tests/K804-031_raise-taken/src/vif.ads new file mode 100644 index 000000000..df057bbd9 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/vif.ads @@ -0,0 +1,7 @@ +with Args; use Args; + +package Vif is + N_Ge0 : Integer := 0; + N_Check_Raise : Integer := 0; + procedure Check_GE0 (X : Num); +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/vifn.adb b/testsuite/tests/K804-031_raise-taken/src/vifn.adb new file mode 100644 index 000000000..e5570de7e --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/vifn.adb @@ -0,0 +1,18 @@ +package body Vifn is + + -- Tests rely on the runtime check for the Id argument: we need a runtime + -- check even when compiled with -gnatp. + + pragma Unsuppress (All_Checks); + + procedure Check_GE0 (X : Num) is + begin + if not (Id (X + 1) <= 0) then -- # eval + N_Ge0 := N_Ge0 + 1; -- # true + end if; + exception + when Constraint_Error => + N_Check_Raise := N_Check_Raise + 1; -- # handler + end; + +end; diff --git a/testsuite/tests/K804-031_raise-taken/src/vifn.ads b/testsuite/tests/K804-031_raise-taken/src/vifn.ads new file mode 100644 index 000000000..2e3173472 --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/src/vifn.ads @@ -0,0 +1,7 @@ +with Args; use Args; + +package Vifn is + N_Ge0 : Integer := 0; + N_Check_Raise : Integer := 0; + procedure Check_GE0 (X : Num); +end; diff --git a/testsuite/tests/K804-031_raise-taken/test.py b/testsuite/tests/K804-031_raise-taken/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/K804-031_raise-taken/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/KB30-011-eargs-gnatemu/myinc.adb b/testsuite/tests/KB30-011-eargs-gnatemu/myinc.adb new file mode 100644 index 000000000..bcbcba5cd --- /dev/null +++ b/testsuite/tests/KB30-011-eargs-gnatemu/myinc.adb @@ -0,0 +1,6 @@ +procedure MyInc is + X : Integer := 1; + pragma Volatile (X); +begin + X := X + 1; +end; diff --git a/testsuite/tests/KB30-011-eargs-gnatemu/test.opt b/testsuite/tests/KB30-011-eargs-gnatemu/test.opt new file mode 100644 index 000000000..9815b3e57 --- /dev/null +++ b/testsuite/tests/KB30-011-eargs-gnatemu/test.opt @@ -0,0 +1,4 @@ +native DEAD checking argument passing to qemu & gnatemu, NA on this platform +visium-elf DEAD checking argument passing to qemu & gnatemu, NA on this platform +lmp-elf DEAD checking argument passing to qemu & gnatemu, NA on this platform +vxworks XFAIL mcdc without scos run on purpose, trace size limit overrun diff --git a/testsuite/tests/KB30-011-eargs-gnatemu/test.py b/testsuite/tests/KB30-011-eargs-gnatemu/test.py new file mode 100644 index 000000000..3f6278df3 --- /dev/null +++ b/testsuite/tests/KB30-011-eargs-gnatemu/test.py @@ -0,0 +1,111 @@ +import os.path +import re + +from e3.os.process import Run + +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of, to_list +from SUITE.tutils import gprbuild, gprfor, tracename_for, unixpath_to, xrun + + +Wdir('tmp_') + +pgm = 'myinc' +unit = pgm + '.adb' +exe = unixpath_to(pgm) +trace = tracename_for(pgm) + +# "gnatcov run" normalizes the name of the output trace file before spawning +# the low-level trace producer. Because GNAT's filename normalization is +# different from Python's, we cannot guess here what is the extract trace file +# name that will appear in logs. Workaround this by only try to match the +# basename. +trace_basename = os.path.basename(trace) + +gprbuild(gprfor(mains=[unit], srcdirs=['..'])) + + +def check_eargs(output, eargs, exe): + m = re.search('exec:\n .*gnatemu.*', output) + e = m.group(0) + thistest.fail_if( + not re.search('--eargs .*%(eargs)s.* --eargs-end.*%(exe)s' + % {'eargs': eargs, 'exe': exe}, e), + "failed to match eargs='%s' and exe='%s' in output: <<\n%s\n>>" + % (eargs, exe, output)) + + +def gnatcovrun(extra, exe, register_failure=False, eargs=None): + outfile = 'gnatcov.out' + xrun('-v %(extra)s %(exe)s %(eargs)s' + % {'extra': extra, 'exe': exe, + 'eargs': ('-eargs %s' % eargs) if eargs else ''}, + out=outfile, register_failure=register_failure) + return contents_of(outfile) + + +def gnatemulator(args, exe): + outfile = 'gnatemu.out' + Run(to_list('%(target)s-gnatemu %(args)s %(kernel)s %(exe)s' + % {'target': env.target.triplet, + 'args': args, + 'kernel': (('--kernel=' + thistest.options.kernel) + if thistest.options.kernel else ''), + 'exe': exe}), + output=outfile) + return contents_of(outfile) + + +# stmt coverage, base check on exe expansion + no history request for traces +# absence of eargs +extra = '--level=stmt' +thistest.log(extra) +output = gnatcovrun(extra=extra, exe=exe) +check_eargs(output, eargs=trace, exe=exe) + +# Check absence of "history" trace request for decision coverage +extra = '--level=stmt+decision' +thistest.log(extra) +output = gnatcovrun(extra=extra, exe=exe) +check_eargs(output, eargs=trace, exe=exe) + +# Check "history" trace request + warning for mcdc coverage without scos. +# This should activate the history for all branches and might overrun the +# trace size limits in some configurations. In particular VxWorks, where we +# run the entire OS, and targets where we might encounter busy loops in the +# runtime for cache management. +extra = '--level=stmt+mcdc' +thistest.log(extra) +is_ignored_target = any(t in env.target.triplet for t in ['vx', 'aarch64']) +output = gnatcovrun(register_failure=not is_ignored_target, + extra=extra, exe=exe) +check_eargs(output, eargs='history,[^,]*%s' % trace_basename, exe=exe) +thistest.fail_if( + not re.search('warning: No SCOs specified for MC/DC level', output), + 'failed to match no-sco warning') + +# Check "history" trace request with map + absence of warning. The decision map +# filename is random, so use a wide matcher (anything but a comma) for it. +extra = '--level=stmt+mcdc --scos=obj/%s.ali' % pgm +thistest.log(extra) +output = gnatcovrun(extra=extra, exe=exe) +check_eargs(output, eargs='histmap=[^,]+,[^,]*%s' % trace_basename, exe=exe) + +# Basic call with -eargs, check that they are included in the (single) +# --eargs group as well, and check that qemu sees them +eargs = '-version -m 512' +extra = '--level=stmt' +thistest.log(extra + ' eargs for qemu') +output = gnatcovrun(extra=extra, exe=exe, eargs=eargs) +check_eargs(output, eargs=eargs, exe=exe) + +eargs1 = '-m 512' +eargs2 = '-version' +output = gnatemulator('-v --eargs %s --eargs-end --eargs %s --eargs-end' + % (eargs1, eargs2), exe) +thistest.fail_if( + not re.search('exec:.*qemu.*%s.*%s' % (eargs1, eargs2), output), + 'failed to match both --eargs sequences') + +thistest.result() diff --git a/testsuite/tests/KC06-023-list_as_ali/plist b/testsuite/tests/KC06-023-list_as_ali/plist new file mode 100644 index 000000000..b0f4e4021 --- /dev/null +++ b/testsuite/tests/KC06-023-list_as_ali/plist @@ -0,0 +1 @@ +obj/p.ali diff --git a/testsuite/tests/KC06-023-list_as_ali/src/p.adb b/testsuite/tests/KC06-023-list_as_ali/src/p.adb new file mode 100644 index 000000000..f7c91e133 --- /dev/null +++ b/testsuite/tests/KC06-023-list_as_ali/src/p.adb @@ -0,0 +1 @@ +procedure P is begin null; end; diff --git a/testsuite/tests/KC06-023-list_as_ali/test.py b/testsuite/tests/KC06-023-list_as_ali/test.py new file mode 100644 index 000000000..2655c95e4 --- /dev/null +++ b/testsuite/tests/KC06-023-list_as_ali/test.py @@ -0,0 +1,18 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import gprbuild, gprfor, xcov + + +Wdir('tmp_') +gprbuild(gprfor(['p.adb'], srcdirs='../src')) + +# Expect silent success +xcov(['map-routines', '--scos=@../plist', 'obj/p.o']) + +# Expect failure +p = xcov(['map-routines', '--scos=../plist', 'obj/p.o'], + out='list_as_ali.out', register_failure=False) +thistest.fail_if(p.status == 0 or + not match('malformed ALI file', 'list_as_ali.out'), + 'no error on malformed ALI file') +thistest.result() diff --git a/testsuite/tests/KC23-012-ocov-exemptions/p.adb b/testsuite/tests/KC23-012-ocov-exemptions/p.adb new file mode 100644 index 000000000..9c397740b --- /dev/null +++ b/testsuite/tests/KC23-012-ocov-exemptions/p.adb @@ -0,0 +1,28 @@ + +procedure P is + + procedure Assert (T : Boolean) is + begin + pragma Annotate (Xcov, Exempt_On, "assert expected never to trip"); + if not T then -- # expect-never-true + raise Program_Error; -- # expect-uncovered + end if; + pragma Annotate (Xcov, Exempt_Off, "assert expected never to trip"); + end; + + procedure Inc (X : in out Integer) is + begin + X := X + 1; + end; + + V : Integer := 12; + pragma Volatile (V); + +begin + Inc (V); + Assert (V = 13); +end; + + + + diff --git a/testsuite/tests/KC23-012-ocov-exemptions/test.opt b/testsuite/tests/KC23-012-ocov-exemptions/test.opt new file mode 100644 index 000000000..d2cc065d3 --- /dev/null +++ b/testsuite/tests/KC23-012-ocov-exemptions/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test uses object coverage diff --git a/testsuite/tests/KC23-012-ocov-exemptions/test.py b/testsuite/tests/KC23-012-ocov-exemptions/test.py new file mode 100644 index 000000000..c3e9f7c8f --- /dev/null +++ b/testsuite/tests/KC23-012-ocov-exemptions/test.py @@ -0,0 +1,47 @@ +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +Wdir('tmp_') + +# Build and run a program with an "assert" function whose body is covered by an +# exemption region. +gpr = gprfor(srcdirs=['..'], mains=['p.adb']) +gprbuild(gpr) +xrun(exepath_to('p')) + +# Exercise branch coverage different ways ... +# +# Without any sco/ali designation, the exemption region is expected not to be +# honored. With --scos or --alis designating the proper ali, the exemption +# region is expected to exempt something: +base_coverage = ['coverage', '--level=branch', '--annotate=xcov', + tracename_for('p')] + + +def check(ali_spec): + xcov(base_coverage + ali_spec) + this_report = contents_of('p.adb.xcov') + + xnote_never_true = r'\*' if ali_spec else '!' + xnote_uncovered = r'\*' if ali_spec else '-' + hint = ' '.join(ali_spec) if ali_spec else 'no ali' + thistest.fail_if( + not re.search(pattern='%s:.*# expect-never-true' % xnote_never_true, + string=this_report), + '%s, unmatched expected-never-true' % hint) + thistest.fail_if( + not re.search(pattern='%s:.*# expect-uncovered' % xnote_uncovered, + string=this_report), + '%s, unmatched expected-uncovered' % hint) + + +check(ali_spec=[]) +check(ali_spec=['--scos=obj/p.ali']) +check(ali_spec=['--alis=obj/p.ali']) +check(ali_spec=['-P', 'gen.gpr']) +thistest.result() diff --git a/testsuite/tests/L112-050-pro-through-disabled/src/dom_debug.adb b/testsuite/tests/L112-050-pro-through-disabled/src/dom_debug.adb new file mode 100644 index 000000000..96021eae6 --- /dev/null +++ b/testsuite/tests/L112-050-pro-through-disabled/src/dom_debug.adb @@ -0,0 +1,18 @@ +procedure Dom_Debug is + + procedure Proc is begin null; end Proc; + function F return Integer is begin return 0; end F; + + X0 : Integer; + pragma Debug (Proc); + + procedure P is begin null; end P; + -- The presence of this body prevents direct chaining of the following + -- declaration to X0, instead a dominance marker denoting the pragma Debug + -- permits propagation. + + X1 : Integer := F; + +begin + null; +end Dom_Debug; diff --git a/testsuite/tests/L112-050-pro-through-disabled/test.py b/testsuite/tests/L112-050-pro-through-disabled/test.py new file mode 100644 index 000000000..1d6cf0348 --- /dev/null +++ b/testsuite/tests/L112-050-pro-through-disabled/test.py @@ -0,0 +1,29 @@ +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=['../src'], + mains=['dom_debug.adb'])), + covlevel='stmt', + mains=['dom_debug'], + extra_coverage_args=['--annotate=xcov'], + scos=['obj/dom_debug'], + extra_gprbuild_args=['-O0']) + +# We expect the first variable declaration to be covered (through back +# propagation through disabled dominant pragma Debug). +thistest.fail_if( + not match(r'[0-9]+ \+:.*X0 : Integer;', 'dom_debug.adb.xcov'), + 'expect X0 to be covered') + +# The pragma itself is disabled and must be reported as NO CODE +thistest.fail_if( + not match(r'[0-9]+ \.:.*pragma Debug', 'dom_debug.adb.xcov'), + 'expect pragma Debug to be marked no-code') +thistest.result() diff --git a/testsuite/tests/L209-010-asm-outfile/src/plop.adb b/testsuite/tests/L209-010-asm-outfile/src/plop.adb new file mode 100644 index 000000000..ebbea1340 --- /dev/null +++ b/testsuite/tests/L209-010-asm-outfile/src/plop.adb @@ -0,0 +1,6 @@ +procedure Plop is + X : Integer := 0; + pragma Volatile (X); +begin + X := X + 12; +end; diff --git a/testsuite/tests/L209-010-asm-outfile/test.opt b/testsuite/tests/L209-010-asm-outfile/test.opt new file mode 100644 index 000000000..cbe3ef302 --- /dev/null +++ b/testsuite/tests/L209-010-asm-outfile/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test runs object coverage diff --git a/testsuite/tests/L209-010-asm-outfile/test.py b/testsuite/tests/L209-010-asm-outfile/test.py new file mode 100644 index 000000000..2772137e1 --- /dev/null +++ b/testsuite/tests/L209-010-asm-outfile/test.py @@ -0,0 +1,41 @@ +""" +Check that gnatcov coverage -o produces report in output file for =asm or +=report requests. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of, match +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +Wdir('tmp_') + +pgm = 'plop' +pgreport = pgm + '.cov' +pgout = pgm + '.stdout' + +gprbuild(project=gprfor(pgm + '.adb', srcdirs='../src')) +xrun(exepath_to(pgm)) + + +def check_output(spec): + fmt = spec['fmt'] + level = spec['level'] + key = spec['key'] + + xcov('coverage --level=%s --annotate=%s --scos=%s -o %s %s' % ( + level, fmt, 'obj/' + pgm + '.ali', pgreport, tracename_for(pgm)), + out=pgout) + thistest.fail_if( + not match(key, pgreport), + 'expect asm dump in -o argument (%s), %s format' % (pgreport, fmt)) + thistest.fail_if( + len(contents_of(pgout)) > 0, + 'expect empty stdout (directed to %s), %s format' % (pgout, fmt)) + + +for spec in [{'level': 'branch', 'fmt': 'asm', 'key': 'level'}, + {'level': 'stmt', 'fmt': 'report', 'key': 'VIOLATIONS'}]: + check_output(spec) +thistest.result() diff --git a/testsuite/tests/L411-031_missing_gnateS/src/checks.adb b/testsuite/tests/L411-031_missing_gnateS/src/checks.adb new file mode 100644 index 000000000..387579035 --- /dev/null +++ b/testsuite/tests/L411-031_missing_gnateS/src/checks.adb @@ -0,0 +1,15 @@ +package body Checks is + + -- To control compilation options, we produce our own local project, + -- without any libsupport consideration. We must make sure that we don't + -- need a libsupport at all: + + pragma Suppress (All_Checks); + + procedure Assert (Cond : Boolean) is + begin + if not Cond then + Assert_Failures := Assert_Failures + 1; + end if; + end; +end; diff --git a/testsuite/tests/L411-031_missing_gnateS/src/checks.ads b/testsuite/tests/L411-031_missing_gnateS/src/checks.ads new file mode 100644 index 000000000..b3f94f64e --- /dev/null +++ b/testsuite/tests/L411-031_missing_gnateS/src/checks.ads @@ -0,0 +1,14 @@ +package Checks is + + -- Weak assertion checking service that just counts assertion + -- failures. + + -- The point of this code is to offer something to build and run to check + -- for warnings about missing compilation options. We don't care about the + -- actual coverage assessments here and need to minimize dependencies + -- against runtime services such as an exception last chance handler. + + Assert_Failures : Natural := 0; + procedure Assert (Cond : Boolean); + +end; diff --git a/testsuite/tests/L411-031_missing_gnateS/src/test_assert.adb b/testsuite/tests/L411-031_missing_gnateS/src/test_assert.adb new file mode 100644 index 000000000..c01f2e38b --- /dev/null +++ b/testsuite/tests/L411-031_missing_gnateS/src/test_assert.adb @@ -0,0 +1,10 @@ +with Checks; + +procedure Test_Assert is + X : Integer := 12; + pragma Volatile (X); +begin + Checks.Assert (X = 12); +end; + + diff --git a/testsuite/tests/L411-031_missing_gnateS/test.opt b/testsuite/tests/L411-031_missing_gnateS/test.opt new file mode 100644 index 000000000..52989de77 --- /dev/null +++ b/testsuite/tests/L411-031_missing_gnateS/test.opt @@ -0,0 +1 @@ +src-traces DEAD Checks compilation flags for binary coverage \ No newline at end of file diff --git a/testsuite/tests/L411-031_missing_gnateS/test.py b/testsuite/tests/L411-031_missing_gnateS/test.py new file mode 100644 index 000000000..cc6042777 --- /dev/null +++ b/testsuite/tests/L411-031_missing_gnateS/test.py @@ -0,0 +1,80 @@ +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import exepath_to, gprbuild, tracename_for, xcov, xrun + + +Wdir("tmp_") + +# The intent of this test is to check that gnatcov warns when it is queried to +# perform source coverage analysis on a unit for which a critical compilation +# option was not used. We exercise various combinations of option selections. +critical_opts = ("-g", "-fdump-scos", "-fpreserve-control-flow") + +# We need full control over the compilation options here, so disconnect +# all the default ones +_cargs = {'scovcargs': False, + 'suitecargs': False} + +gprtemplate = """ +project %(name)s is + for Source_Dirs use ("../src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + for Languages use ("Ada"); + package Compiler is + for Default_Switches ("Ada") use (%(opts)s); + end Compiler; +end %(name)s; +""" + + +def trywith(thisid, thisopts): + gprname = thisid+".gpr" + with open(gprname, 'w') as gpr: + gpr.write(gprtemplate % { + "name": thisid, + "opts": ','.join('"%s"' % opt for opt in thisopts)}) + + gprbuild(gprname, gargs=["test_assert.adb"], **_cargs) + xrun(exepath_to("test_assert")) + out = thisid+".out" + ali = "obj/checks.ali" + xcov(['coverage', '--level=stmt+decision', '--annotate=xcov', + '--scos=%s' % ali, tracename_for("test_assert")], + out=out) + + # Check that we get warning for each critical option not in the set we + # passed. For warning checks purposes, equate -gnateS to -fdump-scos. + thisopts = ["-fdump-scos" if opt == "-gnateS" else opt + for opt in thisopts] + out = contents_of(out) + + for opt in critical_opts: + if opt not in thisopts: + thistest.fail_if( + not re.search("warning: %s: unit compiled without .*%s" + % (ali, opt), out), + 'case "%s" missing warning on %s' % (thisid, opt)) + + +# Now exercise the variants, with shortcut for option names +g = "-g" +p = "-fpreserve-control-flow" +d = "-fdump-scos" + +trywith(thisid="g", thisopts=[g]) +trywith(thisid="p", thisopts=[p]) +trywith(thisid="d", thisopts=[d]) + +trywith(thisid="pdg", thisopts=[p, d, g]) + +trywith(thisid="gp", thisopts=[g, p]) +trywith(thisid="gd", thisopts=[g, d]) +trywith(thisid="pd", thisopts=[p, d]) + +# Check that -gnateS can be used as a replacement for -fdump-scos +trywith(thisid="epg", thisopts=["-gnateS", p, g]) + +thistest.result() diff --git a/testsuite/tests/L613-012/app.gpr b/testsuite/tests/L613-012/app.gpr new file mode 100644 index 000000000..8fd71da09 --- /dev/null +++ b/testsuite/tests/L613-012/app.gpr @@ -0,0 +1,8 @@ +project App is + for Source_Dirs use ("."); + for Object_Dir use "obj"; + package Coverage is + for Units use ("PAK1", "PAK2"); + -- PAK1 exists with different casing, PAK2 does not exist + end Coverage; +end App; diff --git a/testsuite/tests/L613-012/pak1.ads b/testsuite/tests/L613-012/pak1.ads new file mode 100644 index 000000000..edc923d23 --- /dev/null +++ b/testsuite/tests/L613-012/pak1.ads @@ -0,0 +1,2 @@ +package Pak1 is +end Pak1; diff --git a/testsuite/tests/L613-012/test.py b/testsuite/tests/L613-012/test.py new file mode 100644 index 000000000..91daa8e94 --- /dev/null +++ b/testsuite/tests/L613-012/test.py @@ -0,0 +1,14 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprbuild, xcov + + +wd = Wdir('tmp_') + +gprbuild('../app.gpr') +xcov(args='map-routines -P../app', out='xcov.out') +output = contents_of('xcov.out') + +thistest.fail_if( + 'no unit PAK2 in project App (coverage.units attribute)' not in output) +thistest.result() diff --git a/testsuite/tests/L619-040-output-to-objdir/pgm.adb b/testsuite/tests/L619-040-output-to-objdir/pgm.adb new file mode 100644 index 000000000..7bdb573cf --- /dev/null +++ b/testsuite/tests/L619-040-output-to-objdir/pgm.adb @@ -0,0 +1,13 @@ +procedure PGM is + + -- This is GPR specific test for which we produce our own local project, + -- without any libsupport consideration. We must make sure that we don't + -- need a libsupport at all: + + pragma Suppress (All_Checks); + + X : Integer := 12; + pragma Volatile (X); +begin + X := X + 1; +end; diff --git a/testsuite/tests/L619-040-output-to-objdir/test.py b/testsuite/tests/L619-040-output-to-objdir/test.py new file mode 100644 index 000000000..775e14655 --- /dev/null +++ b/testsuite/tests/L619-040-output-to-objdir/test.py @@ -0,0 +1,44 @@ +""" +Check that gnatcov coverage uses the root project file's object dir to store +reports by default. Check that this can be overriden with --output-dir. +""" + +import os.path + +from e3.fs import rm + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +wd = Wdir(subdir='tmp_') + +# Setup a project file with an explicit object directory specified, build it +# and execute the main. +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=['pgm.adb'], srcdirs=['..'], + objdir='obj', exedir='obj')), + gpr_obj_dir='obj', + covlevel='stmt', + mains=['pgm'], + gpr_exe_dir='obj', + extra_coverage_args=['--annotate=xcov']) + +# Analyze, letting gnatcov pick a place for the report. Check that it picks the +# project's object dir: +rm('obj/pgm.adb.xcov') +xcov(xcov_args, out='coverage1.log') +thistest.fail_if(not os.path.exists('obj/pgm.adb.xcov'), + 'could not find expected report in obj dir') + +# Analyze again, requesting a specific place for the report. Check that it is +# created there: +rm('pgm.adb.xcov') +xcov(xcov_args + ['--output-dir=.'], out='coverage2.log') +thistest.fail_if(not os.path.exists('pgm.adb.xcov'), + 'could not find expected report in current dir') + +thistest.result() diff --git a/testsuite/tests/L707-006-src-in-cwd/engines.adb b/testsuite/tests/L707-006-src-in-cwd/engines.adb new file mode 100644 index 000000000..6c8a1fb08 --- /dev/null +++ b/testsuite/tests/L707-006-src-in-cwd/engines.adb @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + return E.P < Stable_P and then E.T < Stable_T; + end Stable; +end Engines; diff --git a/testsuite/tests/L707-006-src-in-cwd/engines.ads b/testsuite/tests/L707-006-src-in-cwd/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/L707-006-src-in-cwd/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/L707-006-src-in-cwd/test.opt b/testsuite/tests/L707-006-src-in-cwd/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/L707-006-src-in-cwd/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/L707-006-src-in-cwd/test.py b/testsuite/tests/L707-006-src-in-cwd/test.py new file mode 100644 index 000000000..66ef24ea4 --- /dev/null +++ b/testsuite/tests/L707-006-src-in-cwd/test.py @@ -0,0 +1,13 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +Wdir('tmp_') + +gprbuild(gprfor(['test_engines.adb'], srcdirs="..")) +xrun(exepath_to("test_engines")) +xcov(['coverage', '--level=stmt', '--annotate=xcov', + tracename_for("test_engines"), '--scos=obj/engines.ali']) +thistest.result() diff --git a/testsuite/tests/L707-006-src-in-cwd/test_engines.adb b/testsuite/tests/L707-006-src-in-cwd/test_engines.adb new file mode 100644 index 000000000..fdec19174 --- /dev/null +++ b/testsuite/tests/L707-006-src-in-cwd/test_engines.adb @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; + +------------------ +-- Test_Engines -- +------------------ +procedure Test_Engines is + E : Engine; + + procedure Assert (X : Boolean); + + procedure Assert (X : Boolean) is + begin + if not X then + raise Program_Error; + end if; + end Assert; +begin + + -- Exercise various condition/decision combinations in Stable. + + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); + + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); + +end Test_Engines; diff --git a/testsuite/tests/L929-006/leon-elf-emptys.s b/testsuite/tests/L929-006/leon-elf-emptys.s new file mode 100644 index 000000000..386a6c360 --- /dev/null +++ b/testsuite/tests/L929-006/leon-elf-emptys.s @@ -0,0 +1,44 @@ +# With +# - empty symbols at the beginning, +# - empty symbol and orphan region in the middle, +# - empty symbol at the end + + .section ".text" + # + .global empty_sym_at_start + .type empty_sym_at_start, #function +empty_sym_at_start: + .size empty_sym_at_start, 0 + # + .global plop + .type plop, #function + .proc 020 +plop: + save %sp, -96, %sp + restore + jmp %o7+8 + nop + .size plop, .-plop + # + .global empty_sym_in_between + .type empty_sym_in_between, #function +empty_sym_in_between: + .size empty_sym_in_between, 0 + # + .skip 1024 + # + .global plop1 + .type plop1, #function + .proc 020 +plop1: + save %sp, -96, %sp + restore + jmp %o7+8 + nop + .size plop1, .-plop1 + # + .global empty_sym_at_end + .type empty_sym_at_end, #function +empty_sym_at_end: + .size empty_sym_at_end, 0 + \ No newline at end of file diff --git a/testsuite/tests/L929-006/leon-elf-expected.out b/testsuite/tests/L929-006/leon-elf-expected.out new file mode 100644 index 000000000..cc6d005a7 --- /dev/null +++ b/testsuite/tests/L929-006/leon-elf-expected.out @@ -0,0 +1,9 @@ +warning: empty symbol empty_sym_in_between at 00000410 in section .text +warning: empty symbol empty_last_sym at 00000820 in section .text +warning: no symbols for 00000000-000003ff in section .text [ 1 ] +warning: no symbols for 00000410-0000080f in section .text [ 1 ] +warning: no symbols for 00000820-00000c1f in section .text [ 1 ] +warning: empty symbol empty_sym_at_start at 00000000 in section .text +warning: empty symbol empty_sym_in_between at 00000010 in section .text +warning: empty symbol empty_sym_at_end at 00000420 in section .text +warning: no symbols for 00000010-0000040f in section .text [ 1 ] diff --git a/testsuite/tests/L929-006/leon-elf-orphans.s b/testsuite/tests/L929-006/leon-elf-orphans.s new file mode 100644 index 000000000..29006e841 --- /dev/null +++ b/testsuite/tests/L929-006/leon-elf-orphans.s @@ -0,0 +1,44 @@ +# With +# - orphan region at the beginning, +# - empty symbol and orphan region in the middle, +# - empty last symbol, then orphan region at the end + + .section ".text" + # + .skip 1024 + .align 4 + # + .global plop + .type plop, #function + .proc 020 +plop: + save %sp, -96, %sp + restore + jmp %o7+8 + nop + .size plop, .-plop + # + .global empty_sym_in_between + .type empty_sym_in_between, #function +empty_sym_in_between: + .size empty_sym_in_between, 0 + # + .skip 1024 + # + .global plop1 + .type plop1, #function + .proc 020 +plop1: + save %sp, -96, %sp + restore + jmp %o7+8 + nop + .size plop1, .-plop1 + # + .global empty_last_sym + .type empty_last_sym, #function +empty_last_sym: + .size empty_last_sym, 0 + # + .skip 1024 + \ No newline at end of file diff --git a/testsuite/tests/L929-006/powerpc-elf-emptys.s b/testsuite/tests/L929-006/powerpc-elf-emptys.s new file mode 100644 index 000000000..7d0bd3f04 --- /dev/null +++ b/testsuite/tests/L929-006/powerpc-elf-emptys.s @@ -0,0 +1,37 @@ +# With +# - empty symbols at the beginning, +# - empty symbol and orphan region in the middle, +# - empty symbol at the end + + .file "t.c" + .section ".text" + # + .global empty_sym_at_start + .type empty_sym_at_start, @function +empty_sym_at_start: + .size empty_sym_at_start, 0 + # + .globl plop + .type plop, @function +plop: + blr + .size plop, .-plop + # + .global empty_sym_in_between + .type empty_sym_in_between, @function +empty_sym_in_between: + .size empty_sym_in_between, 0 + # + .skip 1024 + # + .globl plop1 + .type plop1, @function +plop1: + blr + .size plop1, .-plop1 + # + .global empty_sym_at_end + .type empty_sym_at_end, @function +empty_sym_at_end: + .size empty_sym_at_end, 0 + diff --git a/testsuite/tests/L929-006/powerpc-elf-expected.out b/testsuite/tests/L929-006/powerpc-elf-expected.out new file mode 100644 index 000000000..f1c98c903 --- /dev/null +++ b/testsuite/tests/L929-006/powerpc-elf-expected.out @@ -0,0 +1,9 @@ +warning: empty symbol empty_sym_in_between at 00000404 in section .text +warning: empty symbol empty_last_sym at 00000808 in section .text +warning: no symbols for 00000000-000003ff in section .text [ 1 ] +warning: no symbols for 00000404-00000803 in section .text [ 1 ] +warning: no symbols for 00000808-00000c07 in section .text [ 1 ] +warning: empty symbol empty_sym_at_start at 00000000 in section .text +warning: empty symbol empty_sym_in_between at 00000004 in section .text +warning: empty symbol empty_sym_at_end at 00000408 in section .text +warning: no symbols for 00000004-00000403 in section .text [ 1 ] diff --git a/testsuite/tests/L929-006/powerpc-elf-orphans.s b/testsuite/tests/L929-006/powerpc-elf-orphans.s new file mode 100644 index 000000000..95767b520 --- /dev/null +++ b/testsuite/tests/L929-006/powerpc-elf-orphans.s @@ -0,0 +1,36 @@ +# With +# - orphan region at the beginning, +# - empty symbol and orphan region in the middle, +# - empty last symbol, then orphan region at the end + + .section ".text" + # + .skip 1024 + .align 4 + # + .global plop + .type plop, @function +plop: + blr + .size plop, .-plop + # + .global empty_sym_in_between + .type empty_sym_in_between, @function +empty_sym_in_between: + .size empty_sym_in_between, 0 + # + .skip 1024 + # + .global plop1 + .type plop1, @function +plop1: + blr + .size plop1, .-plop1 + # + .global empty_last_sym + .type empty_last_sym, @function +empty_last_sym: + .size empty_last_sym, 0 + # + .skip 1024 + \ No newline at end of file diff --git a/testsuite/tests/L929-006/test.opt b/testsuite/tests/L929-006/test.opt new file mode 100644 index 000000000..a8b9c4e88 --- /dev/null +++ b/testsuite/tests/L929-006/test.opt @@ -0,0 +1,3 @@ +leon-elf +powerpc-elf +ALL DEAD test needs adaptation to run for target \ No newline at end of file diff --git a/testsuite/tests/L929-006/test.py b/testsuite/tests/L929-006/test.py new file mode 100644 index 000000000..9a63d6919 --- /dev/null +++ b/testsuite/tests/L929-006/test.py @@ -0,0 +1,44 @@ +from e3.diff import diff +from e3.os.process import Run + +from SUITE.context import env, thistest +from SUITE.cutils import Wdir, list_to_file +from SUITE.tutils import xcov + + +Wdir('tmp_') + +sfiles_for = { + "leon-elf": ["leon-elf-orphans.s", "leon-elf-emptys.s"], + "powerpc-elf": ["powerpc-elf-orphans.s", "powerpc-elf-emptys.s"] +} + + +def do_for(target): + + def to_object(sfile): + ofile = sfile.replace('.s', '.o') + Run([target + "-gcc", "-c", '../' + sfile, "-o", ofile]) + return ofile + + ofiles = [to_object(sfile) for sfile in sfiles_for[target]] + + out_actual = target + "-actual.out" + out_expected = '../' + target + "-expected.out" + + xcov(["scan-objects"] + ofiles, out=out_actual) + + thistest.fail_if( + diff(out_actual, out_expected), + "%s != %s, using explicit list" % (out_actual, out_expected)) + + xcov(["scan-objects", "@" + list_to_file(ofiles)], out=out_actual) + + thistest.fail_if( + diff(out_actual, out_expected), + "%s != %s, using list file argument" % (out_actual, out_expected)) + + +do_for(env.target.triplet) + +thistest.result() diff --git a/testsuite/tests/LA17-032-scan-decisions/expected.out b/testsuite/tests/LA17-032-scan-decisions/expected.out new file mode 100644 index 000000000..571559db7 --- /dev/null +++ b/testsuite/tests/LA17-032-scan-decisions/expected.out @@ -0,0 +1,2 @@ +*** p.adb:7:32: warning: condition is reachable through multiple paths +*** p.adb:9:32: warning: condition is reachable through multiple paths diff --git a/testsuite/tests/LA17-032-scan-decisions/p.adb b/testsuite/tests/LA17-032-scan-decisions/p.adb new file mode 100644 index 000000000..72c69bd34 --- /dev/null +++ b/testsuite/tests/LA17-032-scan-decisions/p.adb @@ -0,0 +1,10 @@ +with State; use State; + +procedure P is +begin + X := A and then B; -- tree bdd + + Y := (A and then B) or else C; -- !tree bdd + + Z := (A or else B) and then C; -- !tree bdd +end; diff --git a/testsuite/tests/LA17-032-scan-decisions/state.ads b/testsuite/tests/LA17-032-scan-decisions/state.ads new file mode 100644 index 000000000..3495c72f9 --- /dev/null +++ b/testsuite/tests/LA17-032-scan-decisions/state.ads @@ -0,0 +1,4 @@ +package State is + A, B, C : Boolean; + X, Y, Z : Boolean; +end; diff --git a/testsuite/tests/LA17-032-scan-decisions/test.opt b/testsuite/tests/LA17-032-scan-decisions/test.opt new file mode 100644 index 000000000..9366f25e8 --- /dev/null +++ b/testsuite/tests/LA17-032-scan-decisions/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test runs "gnatcov scan-decisions" diff --git a/testsuite/tests/LA17-032-scan-decisions/test.py b/testsuite/tests/LA17-032-scan-decisions/test.py new file mode 100644 index 000000000..e3894fad3 --- /dev/null +++ b/testsuite/tests/LA17-032-scan-decisions/test.py @@ -0,0 +1,23 @@ +""" +Check that scan-decisions reports decisions with !tree BDDs. +""" + +from e3.diff import diff + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor, xcov + + +Wdir('tmp_') +gprbuild(gprfor(srcdirs=['..'], mains=['p.adb'])) + +xcov(['scan-decisions', '--scos=obj/p.ali'], out='out-alis') +dif = diff('../expected.out', 'out-alis') +thistest.fail_if(dif, 'out-alis != expected regarding scan-decisions:\n' + dif) + +xcov(['scan-decisions', '-Pgen.gpr'], out='out-gpr') +dif = diff('../expected.out', 'out-gpr') +thistest.fail_if(dif, 'out-gpr != expected regarding scan-decisions:\n' + dif) + +thistest.result() diff --git a/testsuite/tests/LA23-016_eargs-exe/src/myabs.adb b/testsuite/tests/LA23-016_eargs-exe/src/myabs.adb new file mode 100644 index 000000000..5c208e4ac --- /dev/null +++ b/testsuite/tests/LA23-016_eargs-exe/src/myabs.adb @@ -0,0 +1,9 @@ +function Myabs (X : Integer) return Integer is +begin + if X < 0 then + return -X; + else + return X; + end if; +end; + diff --git a/testsuite/tests/LA23-016_eargs-exe/src/p.adb b/testsuite/tests/LA23-016_eargs-exe/src/p.adb new file mode 100644 index 000000000..6776953e7 --- /dev/null +++ b/testsuite/tests/LA23-016_eargs-exe/src/p.adb @@ -0,0 +1,7 @@ +with Myabs; + +procedure P is + V : Integer; +begin + V := Myabs (3); +end; diff --git a/testsuite/tests/LA23-016_eargs-exe/test.opt b/testsuite/tests/LA23-016_eargs-exe/test.opt new file mode 100644 index 000000000..8060b1b39 --- /dev/null +++ b/testsuite/tests/LA23-016_eargs-exe/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Tests the command-line for "gnatcov run" diff --git a/testsuite/tests/LA23-016_eargs-exe/test.py b/testsuite/tests/LA23-016_eargs-exe/test.py new file mode 100644 index 000000000..83a6fa86f --- /dev/null +++ b/testsuite/tests/LA23-016_eargs-exe/test.py @@ -0,0 +1,58 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, empty, contents_of, match +from SUITE.tutils import exepath_to, gprbuild, gprfor, xcov, xrun + + +Wdir("tmp_") + +gprbuild(gprfor(srcdirs=["../src"], mains=['p.adb'])) +exe = exepath_to("p") + + +# Check that "xcov run p" and "xcov run -eargs p" +# both work and produce the same result. + +def run_check(id, args): + rlog = id + ".rlog" + trace = id + ".trace" + xrun(["-o", trace] + args, out=rlog) + thistest.fail_if( + not empty(rlog) and not match("/runkernel", rlog), + "unexpected output from %s run:\n%s" % (id, contents_of(rlog))) + + +def cov_check(id): + clog = id + ".clog" + trace = id + ".trace" + rep = id + ".rep" + xcov(["coverage", "--level=stmt", "--scos=obj/myabs.ali", + "--annotate=report", trace, "-o", rep], + out=clog) + + thistest.fail_if( + not match("statement not executed", rep), + "missing expected stmt coverage violation note in %s" % rep) + + thistest.fail_if( + not empty(clog), + "unexpected output from %s coverage :\n%s" % (id, contents_of(clog))) + + +id = "base" +run_check(id, args=[exe]) +cov_check(id) + +id = "eargs" +run_check(id, args=["-eargs", exe]) +cov_check(id) + +# Check that a bare "xcov run" complains about absence of executable +# on the command line. +log = "noexe.log" +xrun("", out=log, register_failure=False) + +thistest.fail_if( + not match(": Please specify an executable to run", log), + "missing expected error in log for run without exe") + +thistest.result() diff --git a/testsuite/tests/LB13-031-post-aspect/src/orelse.ads b/testsuite/tests/LB13-031-post-aspect/src/orelse.ads new file mode 100644 index 000000000..de7a3b89f --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/orelse.ads @@ -0,0 +1,3 @@ +package Orelse is + function Or_Else (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/LB13-031-post-aspect/src/passor.adb b/testsuite/tests/LB13-031-post-aspect/src/passor.adb new file mode 100644 index 000000000..e54219acc --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/passor.adb @@ -0,0 +1,5 @@ +procedure Passor (A, B : Boolean) is +begin + null; -- # stmt +end; + diff --git a/testsuite/tests/LB13-031-post-aspect/src/passor.ads b/testsuite/tests/LB13-031-post-aspect/src/passor.ads new file mode 100644 index 000000000..cf315df5d --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/passor.ads @@ -0,0 +1,4 @@ +pragma Ada_2012; +pragma Check_Policy (Post, On); +procedure Passor (A, B : Boolean) + with Post => A or else B; -- # eval diff --git a/testsuite/tests/LB13-031-post-aspect/src/test_passor_0.adb b/testsuite/tests/LB13-031-post-aspect/src/test_passor_0.adb new file mode 100644 index 000000000..e7927e39c --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/test_passor_0.adb @@ -0,0 +1,14 @@ +with Passor; + +-- nothing called, no stmt covered + +procedure Test_Passor_0 is +begin + null; +end; + +--# passor.ads +-- /eval/ l- ## d- + +--# passor.adb +-- /stmt/ l- ## s- diff --git a/testsuite/tests/LB13-031-post-aspect/src/test_passor_ff.adb b/testsuite/tests/LB13-031-post-aspect/src/test_passor_ff.adb new file mode 100644 index 000000000..a5e536b06 --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/test_passor_ff.adb @@ -0,0 +1,16 @@ +with Passor, Silent_Last_Chance; + +-- evalcond False only, body stmt covered + +procedure Test_Passor_FF is +begin + Passor (False, False); +exception + when others => null; +end; + +--# passor.ads +-- /eval/ l! ## dT- + +--# passor.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/LB13-031-post-aspect/src/test_passor_ft.adb b/testsuite/tests/LB13-031-post-aspect/src/test_passor_ft.adb new file mode 100644 index 000000000..375b04170 --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/test_passor_ft.adb @@ -0,0 +1,16 @@ +with Passor, Silent_Last_Chance; + +-- evalcond True only (from B), all stmt covered + +procedure Test_Passor_FT is +begin + Passor (False, True); +exception + when others => null; +end; + +--# passor.ads +-- /eval/ l! ## dF- + +--# passor.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/LB13-031-post-aspect/src/test_passor_fu.adb b/testsuite/tests/LB13-031-post-aspect/src/test_passor_fu.adb new file mode 100644 index 000000000..a2bc75f47 --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/test_passor_fu.adb @@ -0,0 +1,17 @@ +with Passor, Silent_Last_Chance; + +-- evalcond true and false, all stmt covered + +procedure Test_Passor_FU is +begin + Passor (True, False); + Passor (False, False); +exception + when others => null; +end; + +--# passor.ads +-- /eval/ l+ ## 0 + +--# passor.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/LB13-031-post-aspect/src/test_passor_tx.adb b/testsuite/tests/LB13-031-post-aspect/src/test_passor_tx.adb new file mode 100644 index 000000000..86921fcf7 --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/src/test_passor_tx.adb @@ -0,0 +1,16 @@ +with Passor; + +-- evalcond True only (from A), all stmt covered + +procedure Test_Passor_Tx is +begin + for X in False .. True loop + Passor (True, X); + end loop; +end; + +--# passor.ads +-- /eval/ l! ## dF- + +--# passor.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/LB13-031-post-aspect/tc.txt b/testsuite/tests/LB13-031-post-aspect/tc.txt new file mode 100644 index 000000000..cec5a65e4 --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/tc.txt @@ -0,0 +1,2 @@ +Check DC on ``A or else B`` as a Post aspect attached to a subprogram +declaration. diff --git a/testsuite/tests/LB13-031-post-aspect/test.opt b/testsuite/tests/LB13-031-post-aspect/test.opt new file mode 100644 index 000000000..4b967bbd5 --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/test.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD testing coverage of expressions in aspects, implemented post 7.0.3 +src-traces XFAIL S606-037: src-traces and contracts +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 +leon3-elf,CARGS_O1,bin-traces XFAIL V906-019: contracts with NOP subp body in delay slot diff --git a/testsuite/tests/LB13-031-post-aspect/test.py b/testsuite/tests/LB13-031-post-aspect/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/LB13-031-post-aspect/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/andthen.ads b/testsuite/tests/LB15-031-split-PPC-aspect/src/andthen.ads new file mode 100644 index 000000000..087fa3b2c --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/andthen.ads @@ -0,0 +1,3 @@ +package Andthen is + function And_Then (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/passand.adb b/testsuite/tests/LB15-031-split-PPC-aspect/src/passand.adb new file mode 100644 index 000000000..1dde59173 --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/passand.adb @@ -0,0 +1,4 @@ +procedure Passand (A, B : Boolean) is +begin + null; -- # stmt +end; diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/passand.ads b/testsuite/tests/LB15-031-split-PPC-aspect/src/passand.ads new file mode 100644 index 000000000..32744be6d --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/passand.ads @@ -0,0 +1,4 @@ +pragma Ada_2012; +pragma Check_Policy (Pre, On); +procedure Passand (A, B : Boolean) + with Pre => A and then B; -- # eval diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_0.adb b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_0.adb new file mode 100644 index 000000000..4d31043f7 --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_0.adb @@ -0,0 +1,12 @@ +with Passand; + +procedure Test_Passand_0 is +begin + null; +end; + +--# passand.ads +-- /eval/ l- ## d- + +--# passand.adb +-- /stmt/ l- ## s- diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fu.adb b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fu.adb new file mode 100644 index 000000000..4bf9c372a --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fu.adb @@ -0,0 +1,17 @@ +with Passand, Silent_Last_Chance; + +-- eval both True and False, all stmt covered + +procedure Test_Passand_FU is +begin + Passand (True, True); + Passand (True, False); +exception + when others => null; +end; + +--# passand.ads +-- /eval/ l+ ## 0 + +--# passand.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fx.adb b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fx.adb new file mode 100644 index 000000000..7526e8366 --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_fx.adb @@ -0,0 +1,16 @@ +with Passand, Silent_Last_Chance; + +-- eval False only (from A), body stmt uncovered + +procedure Test_Passand_FX is +begin + Passand (False, True); +exception + when others => null; +end; + +--# passand.ads +-- /eval/ l! ## dT- + +--# passand.adb +-- /stmt/ l- ## s- diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tf.adb b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tf.adb new file mode 100644 index 000000000..a6462bcaf --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tf.adb @@ -0,0 +1,16 @@ +with Passand, Silent_Last_Chance; + +-- eval False only (from B), body stmt uncovered + +procedure Test_Passand_TF is +begin + Passand (True, False); +exception + when others => null; +end; + +--# passand.ads +-- /eval/ l! ## dT- + +--# passand.adb +-- /stmt/ l- ## s- diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tt.adb b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tt.adb new file mode 100644 index 000000000..e5cc006c8 --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/src/test_passand_tt.adb @@ -0,0 +1,14 @@ +with Passand; + +-- eval True only, all stmts covered + +procedure Test_Passand_TT is +begin + Passand (True, True); +end; + +--# passand.ads +-- /eval/ l! ## dF- + +--# passand.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/tc.txt b/testsuite/tests/LB15-031-split-PPC-aspect/tc.txt new file mode 100644 index 000000000..0f50a3a6e --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/tc.txt @@ -0,0 +1,2 @@ +Check DC on ``A and then B`` as a Pre aspect attached to a subprogram +declaration. diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/test.opt b/testsuite/tests/LB15-031-split-PPC-aspect/test.opt new file mode 100644 index 000000000..925ef8d60 --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/test.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD relies on compiler support for 2012 Aspects, not all in 7.0.3 +7.2.2 DEAD relies on compiler support for 2012 Aspects, not all in 7.2.2 +src-traces XFAIL S606-037: src-traces and contracts +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/LB15-031-split-PPC-aspect/test.py b/testsuite/tests/LB15-031-split-PPC-aspect/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/LB15-031-split-PPC-aspect/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/LibExp/.gitignore b/testsuite/tests/LibExp/.gitignore new file mode 100644 index 000000000..5c1079086 --- /dev/null +++ b/testsuite/tests/LibExp/.gitignore @@ -0,0 +1,2 @@ +C +Ada diff --git a/testsuite/tests/LibExp/AndXY/src/test_computing_v0.adb b/testsuite/tests/LibExp/AndXY/src/test_computing_v0.adb new file mode 100644 index 000000000..9481eada8 --- /dev/null +++ b/testsuite/tests/LibExp/AndXY/src/test_computing_v0.adb @@ -0,0 +1,49 @@ +with Run; use Run; + +-- Topology: _ and then _ + +procedure Test_Computing_V0 is +begin + Run_FF_F; +end; + +-- eval-x, eval-y if evaluators are on different lines +-- opX, opY if they are on the same line + +--# computing.adb|computing.c + +-- /on-true/ l- ## s- +-- /on-false/ l+ ## 0 + +--%cov: --level=stmt + +-- =/eval-X1 :d:/ l+ ## 0 +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l+ ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l+ ## 0 +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+decision + +-- =/eval-X1 :d:/ l! ## dT- +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l! ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l! ## dT- +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc + +-- =/eval-X1 :d:/ l! ## dT- +-- =/eval-X1 :e:/ l! ## eT- + +-- =/eval-X2 :d:/ l! ## 0 +-- =/eval-X2 :e:/ l! ## 0 + +-- =/eval-all :d:/ l! ## dT- +-- =/eval-all :e:/ l! ## eT- diff --git a/testsuite/tests/LibExp/AndXY/src/test_computing_v02.adb b/testsuite/tests/LibExp/AndXY/src/test_computing_v02.adb new file mode 100644 index 000000000..5f3339502 --- /dev/null +++ b/testsuite/tests/LibExp/AndXY/src/test_computing_v02.adb @@ -0,0 +1,49 @@ +with Run; use Run; + +-- Topology: _ and then _ + +procedure Test_Computing_V02 is +begin + Run_FF_F; + Run_TF_F; +end; + +-- eval-x, eval-y if evaluators are on different lines +-- opX, opY if they are on the same line + +--# computing.adb|computing.c + +-- /on-true/ l- ## s- +-- /on-false/ l+ ## 0 + +--%cov: --level=stmt +-- =/eval-X1 :d:/ l+ ## 0 +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l+ ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l+ ## 0 +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+decision + +-- =/eval-X1 :d:/ l! ## dT- +-- =/eval-X1 :e:/ l+ ## eT- + +-- =/eval-X2 :d:/ l! ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l! ## dT- +-- =/eval-all :e:/ l+ ## eT- + +--%cov: --level=stmt\+(uc_)?mcdc + +-- =/eval-X1 :d:/ l! ## dT- +-- =/eval-X1 :e:/ l! ## eT- + +-- =/eval-X2 :d:/ l! ## 0 +-- =/eval-X2 :e:/ l! ## 0 + +-- =/eval-all :d:/ l! ## dT- +-- =/eval-all :e:/ l! ## eT- diff --git a/testsuite/tests/LibExp/AndXY/src/test_computing_v03.adb b/testsuite/tests/LibExp/AndXY/src/test_computing_v03.adb new file mode 100644 index 000000000..adc5bd5c4 --- /dev/null +++ b/testsuite/tests/LibExp/AndXY/src/test_computing_v03.adb @@ -0,0 +1,50 @@ +with Run; use Run; + +-- Topology: _ and then _ + +procedure Test_Computing_V03 is +begin + Run_FF_F; + Run_TT_T; +end; + +-- eval-x, eval-y if evaluators are on different lines +-- opX, opY if they are on the same line + +--# computing.adb|computing.c + +-- /on-true/ l+ ## 0 +-- /on-false/ l+ ## 0 + +--%cov: --level=stmt + +-- =/eval-X1 :d:/ l+ ## 0 +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l+ ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l+ ## 0 +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+decision + +-- =/eval-X1 :d:/ l+ ## 0 +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l+ ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l+ ## 0 +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc + +-- =/eval-X1 :d:/ l! ## 0 +-- =/eval-X1 :e:/ l! ## 0 + +-- =/eval-X2 :d:/ l! ## c!:"(X2*)" +-- =/eval-X2 :e:/ l! ## c!:"(X2*)" + +-- =/eval-all :d:/ l! ## c!:"(X2*)" +-- =/eval-all :e:/ l! ## c!:"(X2*)" diff --git a/testsuite/tests/LibExp/AndXY/src/test_computing_v23.adb b/testsuite/tests/LibExp/AndXY/src/test_computing_v23.adb new file mode 100644 index 000000000..5357df07f --- /dev/null +++ b/testsuite/tests/LibExp/AndXY/src/test_computing_v23.adb @@ -0,0 +1,50 @@ +with Run; use Run; + +-- Topology: _ and then _ + +procedure Test_Computing_V23 is +begin + Run_TF_F; + Run_TT_T; +end; + +-- eval-x, eval-y if evaluators are on different lines +-- opX, opY if they are on the same line + +--# computing.adb|computing.c + +-- /on-true/ l+ ## 0 +-- /on-false/ l+ ## 0 + +--%cov: --level=stmt + +-- =/eval-X1 :d:/ l+ ## 0 +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l+ ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l+ ## 0 +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+decision + +-- =/eval-X1 :d:/ l+ ## 0 +-- =/eval-X1 :e:/ l+ ## 0 + +-- =/eval-X2 :d:/ l+ ## 0 +-- =/eval-X2 :e:/ l+ ## 0 + +-- =/eval-all :d:/ l+ ## 0 +-- =/eval-all :e:/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc + +-- =/eval-X1 :d:/ l! ## c!:"(X1*)" +-- =/eval-X1 :e:/ l! ## c!:"(X1*)" + +-- =/eval-X2 :d:/ l! ## 0 +-- =/eval-X2 :e:/ l! ## 0 + +-- =/eval-all :d:/ l! ## c!:"(X1*)" +-- =/eval-all :e:/ l! ## c!:"(X1*)" diff --git a/testsuite/tests/LibExp/extra.opt b/testsuite/tests/LibExp/extra.opt new file mode 100644 index 000000000..783e24c6c --- /dev/null +++ b/testsuite/tests/LibExp/extra.opt @@ -0,0 +1,2 @@ +LANG_C,7.0.3 DEAD 7.0.3 misses proper SCO support for C +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/LibExp/group.py b/testsuite/tests/LibExp/group.py new file mode 100644 index 000000000..8815c92cf --- /dev/null +++ b/testsuite/tests/LibExp/group.py @@ -0,0 +1,3 @@ +from SCOV.expgen.generator.engine import run + +run(__file__) diff --git a/testsuite/tests/LibExp/set.txt b/testsuite/tests/LibExp/set.txt new file mode 100644 index 000000000..14b51bf3c --- /dev/null +++ b/testsuite/tests/LibExp/set.txt @@ -0,0 +1,38 @@ +This directory hosts libraries of test drivers and functional +code for expressions of a given topology. Ideas: + +o One family of drivers for e.g. + + X and then Y + X or else Y + etc + +o State expectations for all the possible criteria + (stmt, decision, mcdc) + +o Provide helpers + functional code for a variety + of operand kinds. Drivers should be generic enough + not to care. + +o Each chapter should feature a "instanciation" + request to trigger execution of the test and validation + for the criterion it represents. + +o think about ways to have the tests accounted for in qualification runs + (if not in a subdir of / for example) + +DriverLib + Drivers written in Ada, used for C instances as well + +Ada/ExprLib + Ada implementation of the helpers and functional variants + +C/ExprLib + C implementation of the helpers and functional variants + +Testcase description: + Check correctness of _the criterion_ assessment etc + + +test.py ?? QMAT tree ?? + diff --git a/testsuite/tests/LibExp/src/support.h b/testsuite/tests/LibExp/src/support.h new file mode 100644 index 000000000..d9a58ffff --- /dev/null +++ b/testsuite/tests/LibExp/src/support.h @@ -0,0 +1,9 @@ +#ifndef SUPPORT_H +#define SUPPORT_H + +/* Prototypes for libsupport functions we'll use. */ + +extern void assert (char cond); +extern int identity (int x); + +#endif diff --git a/testsuite/tests/M204-037-dc-in-aggregate/src/assert.adb b/testsuite/tests/M204-037-dc-in-aggregate/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/M204-037-dc-in-aggregate/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/M204-037-dc-in-aggregate/src/test_1.adb b/testsuite/tests/M204-037-dc-in-aggregate/src/test_1.adb new file mode 100644 index 000000000..05c5c16ed --- /dev/null +++ b/testsuite/tests/M204-037-dc-in-aggregate/src/test_1.adb @@ -0,0 +1,15 @@ +with Assert; +with Values; use Values; + +procedure Test_1 is + B : Bool; +begin + Equal (X => 1, Y => 2, B => B); + Assert (B.Value = False); + Equal2 (X => 1, Y => 1, Z => 4, T => 8, B => B); + Assert (B.Value = False); +end; + +--# values.adb +-- /eq/ l+ ## 0 +-- /andthen/ d=>l+, mu=>l! ## d=>0, mu=>eT- diff --git a/testsuite/tests/M204-037-dc-in-aggregate/src/values.adb b/testsuite/tests/M204-037-dc-in-aggregate/src/values.adb new file mode 100644 index 000000000..640233788 --- /dev/null +++ b/testsuite/tests/M204-037-dc-in-aggregate/src/values.adb @@ -0,0 +1,13 @@ +package body Values is + + procedure Equal (X, Y : Integer; B : out Bool) is + begin + B := (Value => X = Y); -- # eq + end; + + procedure Equal2 (X, Y : Integer; Z, T : Integer; B : out Bool) is + begin + B := (Value => (X = Y) and then (Z = T)); -- # andthen + end; + +end; diff --git a/testsuite/tests/M204-037-dc-in-aggregate/src/values.ads b/testsuite/tests/M204-037-dc-in-aggregate/src/values.ads new file mode 100644 index 000000000..70a07c46b --- /dev/null +++ b/testsuite/tests/M204-037-dc-in-aggregate/src/values.ads @@ -0,0 +1,10 @@ +package Values is + + type Bool is record + Value : Boolean; + end record; + + procedure Equal (X, Y : Integer; B : out Bool); + procedure Equal2 (X, Y : Integer; Z, T : Integer; B : out Bool); + +end; diff --git a/testsuite/tests/M204-037-dc-in-aggregate/test.py b/testsuite/tests/M204-037-dc-in-aggregate/test.py new file mode 100644 index 000000000..49089f5e1 --- /dev/null +++ b/testsuite/tests/M204-037-dc-in-aggregate/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.htc import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/M502-040-default-prj-path/.gitignore b/testsuite/tests/M502-040-default-prj-path/.gitignore new file mode 100644 index 000000000..cd56e8c6d --- /dev/null +++ b/testsuite/tests/M502-040-default-prj-path/.gitignore @@ -0,0 +1,2 @@ +proj/ut/ut.gpr +proj/ut/main.trace diff --git a/testsuite/tests/M502-040-default-prj-path/proj/proj.gpr b/testsuite/tests/M502-040-default-prj-path/proj/proj.gpr new file mode 100644 index 000000000..8f8cb36a6 --- /dev/null +++ b/testsuite/tests/M502-040-default-prj-path/proj/proj.gpr @@ -0,0 +1,4 @@ +project Proj is + +end Proj; + diff --git a/testsuite/tests/M502-040-default-prj-path/proj/ut/main.adb b/testsuite/tests/M502-040-default-prj-path/proj/ut/main.adb new file mode 100644 index 000000000..5207ed884 --- /dev/null +++ b/testsuite/tests/M502-040-default-prj-path/proj/ut/main.adb @@ -0,0 +1 @@ +procedure Main is begin null; end; diff --git a/testsuite/tests/M502-040-default-prj-path/proj/ut/ut.gpr.template b/testsuite/tests/M502-040-default-prj-path/proj/ut/ut.gpr.template new file mode 100644 index 000000000..dd9c5f3ef --- /dev/null +++ b/testsuite/tests/M502-040-default-prj-path/proj/ut/ut.gpr.template @@ -0,0 +1,11 @@ +project UT extends "proj.gpr" is + + for Source_Dirs use ("."); + for Object_Dir use "obj"; + + for Main use ("main.adb"); + + {pkg_emulator} + +end UT; + diff --git a/testsuite/tests/M502-040-default-prj-path/test.opt b/testsuite/tests/M502-040-default-prj-path/test.opt new file mode 100644 index 000000000..a24154dc9 --- /dev/null +++ b/testsuite/tests/M502-040-default-prj-path/test.opt @@ -0,0 +1 @@ +native DEAD test works by simulating a missing/non-working native gnatls diff --git a/testsuite/tests/M502-040-default-prj-path/test.py b/testsuite/tests/M502-040-default-prj-path/test.py new file mode 100644 index 000000000..5d55419ef --- /dev/null +++ b/testsuite/tests/M502-040-default-prj-path/test.py @@ -0,0 +1,27 @@ +import os +import os.path + +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import contents_of, text_to_file +from SUITE.tutils import exepath_to, gpr_emulator_package, gprbuild, xrun + + +env.add_search_path(env_var='PATH', + path=os.path.join(os.getcwd(), 'bin'), + append=True) +env.add_search_path(env_var='GPR_PROJECT_PATH', + path=os.path.join(os.getcwd(), 'proj')) + +os.chdir('proj/ut') +text_to_file( + contents_of('ut.gpr.template').format( + pkg_emulator=gpr_emulator_package() + ), + 'ut.gpr' +) + +gprbuild('ut') +xrun(['-P', 'ut', exepath_to('obj/main')]) + +thistest.result() diff --git a/testsuite/tests/M513-017/driver.adb b/testsuite/tests/M513-017/driver.adb new file mode 100644 index 000000000..0793d4545 --- /dev/null +++ b/testsuite/tests/M513-017/driver.adb @@ -0,0 +1,8 @@ +with Lib; use Lib; + +procedure Driver is +begin + if Get (11) then + raise Program_Error; + end if; +end Driver; diff --git a/testsuite/tests/M513-017/lib.adb b/testsuite/tests/M513-017/lib.adb new file mode 100644 index 000000000..2e206e9ee --- /dev/null +++ b/testsuite/tests/M513-017/lib.adb @@ -0,0 +1,25 @@ +package body Lib is + + function Image (I : Integer) return String is + begin + if I < 0 then + return '-' & Integer'Image (I); + else + return Integer'Image (I); + end if; + end Image; + + function Get (I : Integer) return Boolean is + begin + if Image (I) = Image (1) & "0" then + return True; + else + return False; + end if; + end Get; + + function Get2 (I : Integer) return Boolean is + begin + return Image (I) /= "10" and then Image (I) /= "20"; + end Get2; +end Lib; diff --git a/testsuite/tests/M513-017/lib.ads b/testsuite/tests/M513-017/lib.ads new file mode 100644 index 000000000..fdc97a635 --- /dev/null +++ b/testsuite/tests/M513-017/lib.ads @@ -0,0 +1,4 @@ +package Lib is + function Get (I : Integer) return Boolean; + function Get2 (I : Integer) return Boolean; +end Lib; diff --git a/testsuite/tests/M513-017/test.opt b/testsuite/tests/M513-017/test.opt new file mode 100644 index 000000000..a3304d764 --- /dev/null +++ b/testsuite/tests/M513-017/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test runs "gnatcov map-routines" diff --git a/testsuite/tests/M513-017/test.py b/testsuite/tests/M513-017/test.py new file mode 100644 index 000000000..9e97074d6 --- /dev/null +++ b/testsuite/tests/M513-017/test.py @@ -0,0 +1,9 @@ +import os.path + +from SCOV.map import MapChecker +from SUITE.context import thistest + + +MapChecker(['driver.adb'], + alis=[os.path.join('obj', 'lib.ali')]).run() +thistest.result() diff --git a/testsuite/tests/M514-031-multiple-stmts-lines/src/ops.adb b/testsuite/tests/M514-031-multiple-stmts-lines/src/ops.adb new file mode 100644 index 000000000..a2a98b1ff --- /dev/null +++ b/testsuite/tests/M514-031-multiple-stmts-lines/src/ops.adb @@ -0,0 +1,18 @@ +package body Ops is + procedure Compute + (A, B, C : Integer; + X, Y : out Integer) is + begin + -- This test is about checking that gnatcov do not complain when + -- multiple statements are on the same line as long as debug info slocs + -- have column information. + + -- Currently, the compiler generates column information only for + -- conditional branch instructions. We know that the full "mod" + -- implementation involves branches, so we are sure that using such + -- operations in both of our statements will generate column + -- information. + + X := A mod B; Y := A mod C; -- # multi-stmts + end Compute; +end Ops; diff --git a/testsuite/tests/M514-031-multiple-stmts-lines/src/ops.ads b/testsuite/tests/M514-031-multiple-stmts-lines/src/ops.ads new file mode 100644 index 000000000..3605ce006 --- /dev/null +++ b/testsuite/tests/M514-031-multiple-stmts-lines/src/ops.ads @@ -0,0 +1,5 @@ +package Ops is + procedure Compute + (A, B, C : Integer; + X, Y : out Integer); +end Ops; diff --git a/testsuite/tests/M514-031-multiple-stmts-lines/src/test_full.adb b/testsuite/tests/M514-031-multiple-stmts-lines/src/test_full.adb new file mode 100644 index 000000000..b3aaffea9 --- /dev/null +++ b/testsuite/tests/M514-031-multiple-stmts-lines/src/test_full.adb @@ -0,0 +1,10 @@ +with Ops; use Ops; + +procedure Test_Full is + X, Y : Integer; +begin + Compute (32, 10, 20, X, Y); +end Test_Full; + +--# ops.adb +-- /multi-stmts/ l+ ## 0 diff --git a/testsuite/tests/M514-031-multiple-stmts-lines/src/test_no.adb b/testsuite/tests/M514-031-multiple-stmts-lines/src/test_no.adb new file mode 100644 index 000000000..2dcdd1158 --- /dev/null +++ b/testsuite/tests/M514-031-multiple-stmts-lines/src/test_no.adb @@ -0,0 +1,10 @@ +with Ops; use Ops; + +procedure Test_No is + X, Y : Integer; +begin + null; +end Test_No; + +--# ops.adb +-- /multi-stmts/ l- ## s-, s- diff --git a/testsuite/tests/M514-031-multiple-stmts-lines/test.py b/testsuite/tests/M514-031-multiple-stmts-lines/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/M514-031-multiple-stmts-lines/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/M515-018/return-ternary.c b/testsuite/tests/M515-018/return-ternary.c new file mode 100644 index 000000000..445328d64 --- /dev/null +++ b/testsuite/tests/M515-018/return-ternary.c @@ -0,0 +1,11 @@ +int +my_abs (int n) +{ + return (n < 0) ? -n : n; +} + +int +main (void) +{ + return my_abs (1); +} diff --git a/testsuite/tests/M515-018/test.opt b/testsuite/tests/M515-018/test.opt new file mode 100644 index 000000000..9de3b425b --- /dev/null +++ b/testsuite/tests/M515-018/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD testing properties of C SCOs, implemented post 7.0.3 +!bin-traces DEAD test using map-routines +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/M515-018/test.py b/testsuite/tests/M515-018/test.py new file mode 100644 index 000000000..8a969c23c --- /dev/null +++ b/testsuite/tests/M515-018/test.py @@ -0,0 +1,23 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor, xcov + + +Wdir('tmp_') + +# First build the program +gprbuild(gprfor(mains=['return-ternary.c'], srcdirs='..')) + +# Then invoke map-routines so that SCOs are loaded. +xcov(['map-routines', + '--scos=obj/return-ternary.c.gli', 'obj/return-ternary.o'], + out='map-routines.txt') + +# The test fail if we find something like: +# !!! return-ternary.c:3:10: unexpected SCO nesting in SCO #1: STATEMENT at +# return-ternary.c:3:3-25, discarding nested SCO +thistest.fail_if( + any(line.startswith('!!!') + for line in open('map-routines.txt', 'r').readlines()), + 'map-routines has found something wrong') +thistest.result() diff --git a/testsuite/tests/M516-014-direct-bool-operators/req.txt b/testsuite/tests/M516-014-direct-bool-operators/req.txt new file mode 100644 index 000000000..db58c4484 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/req.txt @@ -0,0 +1,12 @@ +The and/or/xor non-shortcircuit operators are allowed for sc and dc +assessments. They shall be processed as any other kind of computational +operator. + +Testing Strategy: +----------------- + +Provide testcases involving and/or/xor operators in decisions. Check +that they are all accepted and processed without any particularity. + +Check that the presence of and/or/xor operators in an expression +doesn't make it a decision out of explicit control-flow contexts. diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/assert.adb b/testsuite/tests/M516-014-direct-bool-operators/src/assert.adb new file mode 100644 index 000000000..075669142 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (X : Boolean) is +begin + if not X then + raise Program_Error; + end if; +end Assert; diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/assert.ads b/testsuite/tests/M516-014-direct-bool-operators/src/assert.ads new file mode 100644 index 000000000..ab78e4405 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/assert.ads @@ -0,0 +1 @@ +procedure Assert (X : Boolean); diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/ops.adb b/testsuite/tests/M516-014-direct-bool-operators/src/ops.adb new file mode 100644 index 000000000..fb6fae6c0 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/ops.adb @@ -0,0 +1,18 @@ +package body Ops is + + procedure Eval (A, B : Boolean) is + begin + if A and B then -- # eval-and + N_And := N_And + 1; -- # and-true + end if; + if A or B then -- # eval-or + N_Or := N_Or + 1; -- # or-true + end if; + if A xor B then -- # eval-xor + N_Xor := N_Xor + 1; -- # xor-true + end if; + end; +end; + + + diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/ops.ads b/testsuite/tests/M516-014-direct-bool-operators/src/ops.ads new file mode 100644 index 000000000..2ab2631b3 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/ops.ads @@ -0,0 +1,5 @@ +package Ops is + procedure Eval (A, B : Boolean); + + N_And, N_Or, N_Xor : Integer := 0; +end; diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_and.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_and.adb new file mode 100644 index 000000000..8177ca924 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_and.adb @@ -0,0 +1,18 @@ +with Assert; +with Ops; use Ops; + +procedure Test_And is +begin + Eval (A => True, B => True); + Eval (A => True, B => False); + Assert (N_And = 1 and then N_Or = 2 and then N_Xor = 1); +end; + +--# ops.adb +-- /eval-and/ l+ ## 0 +-- /and-true/ l+ ## 0 +-- /eval-or/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /or-true/ l+ ## 0 +-- /eval-xor/ l+ ## 0 +-- /xor-true/ l+ ## 0 + diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_ff.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_ff.adb new file mode 100644 index 000000000..f7984d6ea --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_ff.adb @@ -0,0 +1,17 @@ +with Assert; +with Ops; use Ops; + +procedure Test_FF is +begin + Eval (A => False, B => False); + Assert (N_And = 0 and then N_Or = 0 and then N_Xor = 0); +end; + +--# ops.adb +-- /eval-and/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /and-true/ l- ## s- +-- /eval-or/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /or-true/ l- ## s- +-- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /xor-true/ l- ## s- + diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_ft.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_ft.adb new file mode 100644 index 000000000..6b1b770b1 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_ft.adb @@ -0,0 +1,17 @@ +with Assert; +with Ops; use Ops; + +procedure Test_FT is +begin + Eval (A => False, B => True); + Assert (N_And = 0 and then N_Or = 1 and then N_Xor = 1); +end; + +--# ops.adb +-- /eval-and/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /and-true/ l- ## s- +-- /eval-or/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /or-true/ l+ ## 0 +-- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /xor-true/ l+ ## 0 + diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_or.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_or.adb new file mode 100644 index 000000000..7c01bef25 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_or.adb @@ -0,0 +1,18 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Or is +begin + Eval (A => False, B => False); + Eval (A => True, B => True); + Assert (N_And = 1 and then N_Or = 1 and then N_Xor = 0); +end; + +--# ops.adb +-- /eval-and/ l+ ## 0 +-- /and-true/ l+ ## 0 +-- /eval-or/ l+ ## 0 +-- /or-true/ l+ ## 0 +-- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /xor-true/ l- ## s- + diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_tf.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_tf.adb new file mode 100644 index 000000000..328aaf00f --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_tf.adb @@ -0,0 +1,17 @@ +with Assert; +with Ops; use Ops; + +procedure Test_TF is +begin + Eval (A => True, B => False); + Assert (N_And = 0 and then N_Or = 1 and then N_Xor = 1); +end; + +--# ops.adb +-- /eval-and/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /and-true/ l- ## s- +-- /eval-or/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /or-true/ l+ ## 0 +-- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /xor-true/ l+ ## 0 + diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_tt.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_tt.adb new file mode 100644 index 000000000..bcb432ac6 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_tt.adb @@ -0,0 +1,17 @@ +with Assert; +with Ops; use Ops; + +procedure Test_TT is +begin + Eval (A => True, B => True); + Assert (N_And = 1 and then N_Or = 1 and then N_Xor = 0); +end; + +--# ops.adb +-- /eval-and/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /and-true/ l+ ## 0 +-- /eval-or/ s=>l+, d=>l! ## s=>0, d=>dF- +-- /or-true/ l+ ## 0 +-- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /xor-true/ l- ## s- + diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_xor.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_xor.adb new file mode 100644 index 000000000..b477a5401 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_xor.adb @@ -0,0 +1,18 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Xor is +begin + Eval (A => False, B => False); + Eval (A => True, B => False); + Assert (N_And = 0 and then N_Or = 1 and then N_Xor = 1); +end; + +--# ops.adb +-- /eval-and/ s=>l+, d=>l! ## s=>0, d=>dT- +-- /and-true/ l- ## s- +-- /eval-or/ l+ ## 0 +-- /or-true/ l+ ## 0 +-- /eval-xor/ l+ ## 0 +-- /xor-true/ l+ ## 0 + diff --git a/testsuite/tests/M516-014-direct-bool-operators/test.py b/testsuite/tests/M516-014-direct-bool-operators/test.py new file mode 100644 index 000000000..64dab3c68 --- /dev/null +++ b/testsuite/tests/M516-014-direct-bool-operators/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.adb new file mode 100644 index 000000000..e0d4595be --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.adb @@ -0,0 +1,7 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; + diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.ads b/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.ads new file mode 100644 index 000000000..119c7f9f2 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.ads @@ -0,0 +1 @@ +procedure Assert (T : Boolean); diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb new file mode 100644 index 000000000..2d38e22b0 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb @@ -0,0 +1,42 @@ +with Ada.Finalization; use Ada.Finalization; + +package body Foo is + + type Witness is new Ada.Finalization.Controlled with record + Value : Integer; + end record; + + procedure Adjust (X : in out Witness); + procedure Finalize (X : in out Witness); + + procedure Adjust (X : in out Witness) is + begin + N_Adjust := N_Adjust + 1; -- # adjust + end Adjust; + + procedure Finalize (X : in out Witness) is + begin + N_Finalize := N_Finalize + 1; -- # final + end Finalize; + + function Make (V : Integer) return Witness is + begin + return (Controlled with V); -- # make + end Make; + + function Val (X : Witness) return Integer is + begin + return X.Value; -- # val + end Val; + + procedure Try (V : Integer) is + begin + if Val(Make(1)) = V or else Val(Make(2)) = V then -- # eval + N_Then := N_Then + 1; -- # then + else + N_Else := N_Else + 1; -- # else + end if; + end Try; + +end; + diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads new file mode 100644 index 000000000..e1188ef7e --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads @@ -0,0 +1,6 @@ + +package Foo is + procedure Try (V : Integer); + + N_Finalize, N_Adjust, N_Then, N_Else : Natural := 0; +end; diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/test_ff.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/test_ff.adb new file mode 100644 index 000000000..e30c3c0be --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/test_ff.adb @@ -0,0 +1,14 @@ +with Foo; use Foo; +with Assert; + +procedure Test_FF is +begin + Foo.Try (V => 4); + Assert (N_Then = 0); + Assert (N_Else = 1); +end; + +--# foo.adb +-- /eval/ l! ## dT- +-- /then/ l- ## s- +-- /else/ l+ ## 0 diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/test_ft.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/test_ft.adb new file mode 100644 index 000000000..c32b6ee65 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/test_ft.adb @@ -0,0 +1,14 @@ +with Foo; use Foo; +with Assert; + +procedure Test_FT is +begin + Foo.Try (V => 2); + Assert (N_Then = 1); + Assert (N_Else = 0); +end; + +--# foo.adb +-- /eval/ l! ## dF- +-- /then/ l+ ## 0 +-- /else/ l- ## s- diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/test_tx.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/test_tx.adb new file mode 100644 index 000000000..58266d08d --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/test_tx.adb @@ -0,0 +1,14 @@ +with Foo; use Foo; +with Assert; + +procedure Test_TX is +begin + Foo.Try (V => 1); + Assert (N_Then = 1); + Assert (N_Else = 0); +end; + +--# foo.adb +-- /eval/ l! ## dF- +-- /then/ l+ ## 0 +-- /else/ l- ## s- diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/test.py b/testsuite/tests/M528-002-transient-finalize/alternate/test.py new file mode 100644 index 000000000..e795c2214 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/alternate/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/M528-002-transient-finalize/extra.opt b/testsuite/tests/M528-002-transient-finalize/extra.opt new file mode 100644 index 000000000..5367f0143 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/extra.opt @@ -0,0 +1,3 @@ +RTS_ZFP DEAD Involves controlled objects +7.0.3 DEAD testing transient controlled finalizers, requires post 7.0.3 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/M528-002-transient-finalize/original/src/log.adb b/testsuite/tests/M528-002-transient-finalize/original/src/log.adb new file mode 100644 index 000000000..eadce41ef --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/original/src/log.adb @@ -0,0 +1,12 @@ +with System; + +-- A fake replacement for Put_Line so the original source constructs in +-- callers are generally preserved and we can exercise arbitrary an RTS +-- profile. + +procedure Log (Status : String) is + Outreg : System.Address; + pragma Volatile (Outreg); +begin + Outreg := Status'Address; +end; diff --git a/testsuite/tests/M528-002-transient-finalize/original/src/test_main.adb b/testsuite/tests/M528-002-transient-finalize/original/src/test_main.adb new file mode 100644 index 000000000..5c056da2b --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/original/src/test_main.adb @@ -0,0 +1,63 @@ +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Log; + +procedure Test_Main is + + abc : constant Unbounded_String := To_Unbounded_String ("abc"); + def : constant Unbounded_String := To_Unbounded_String ("def"); + ghi : constant Unbounded_String := To_Unbounded_String ("ghi"); + bool : constant Unbounded_String := To_Unbounded_String ("bool"); + + function Foo (Var : Unbounded_String) return Boolean is + begin + if Var = To_Unbounded_String ("abc") -- # evalA + or else Var = To_Unbounded_String ("def") -- # evalB + or else Var = To_Unbounded_String ("ghi") -- # evalC + then + return True; -- # dtrue + else + return False; -- # dfalse + end if; + end Foo; + + +begin + if Foo (abc) then -- # outer_test_xok + Log ("ok"); -- # outer_ok + else + Log ("err"); -- # outer_err_xok + end if; + + if Foo (def) then -- # outer_test_xok + Log ("ok"); -- # outer_ok + else + Log ("err"); -- # outer_err + end if; + + if Foo (ghi) then -- # outer_test_xok + Log ("ok"); -- # outer_ok + else + Log ("err"); -- # outer_err + end if; + + if Foo (bool) then -- # outer_test_xfail + Log ("err"); -- # outer_err + else + Log ("ok"); -- # outer_ok + end if; +end; + +-- Self test, originating from customer, mcdc complete ... + +--# test_main.adb +-- /evalA/ l+ ## 0 +-- /evalB/ l+ ## 0 +-- /evalC/ l+ ## 0 +-- /dtrue/ l+ ## 0 +-- /dfalse/ l+ ## 0 + +-- /outer_test_xok/ s=>l+, dmu=>l! ## s=>0, dmu=>dF- +-- /outer_test_xfail/ s=>l+, dmu=>l! ## s=>0, dmu=>dT- +-- /outer_err/ l- ## s- +-- /outer_ok/ l+ ## 0 + diff --git a/testsuite/tests/M528-002-transient-finalize/original/test.py b/testsuite/tests/M528-002-transient-finalize/original/test.py new file mode 100644 index 000000000..e795c2214 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/original/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/assert.adb b/testsuite/tests/M528-002-transient-finalize/variant1/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/log.adb b/testsuite/tests/M528-002-transient-finalize/variant1/src/log.adb new file mode 100644 index 000000000..eadce41ef --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/log.adb @@ -0,0 +1,12 @@ +with System; + +-- A fake replacement for Put_Line so the original source constructs in +-- callers are generally preserved and we can exercise arbitrary an RTS +-- profile. + +procedure Log (Status : String) is + Outreg : System.Address; + pragma Volatile (Outreg); +begin + Outreg := Status'Address; +end; diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.adb b/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.adb new file mode 100644 index 000000000..7354e37e8 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.adb @@ -0,0 +1,15 @@ +package body Pkg is + + function Foo (Var : Unbounded_String) return Boolean is + begin + if Var = To_Unbounded_String ("abc") -- # evalA + or else Var = To_Unbounded_String ("def") -- # evalB + or else Var = To_Unbounded_String ("ghi") -- # evalC + then + return True; -- # dtrue + else + return False; -- # dfalse + end if; + end Foo; + +end; diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.ads b/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.ads new file mode 100644 index 000000000..2b490827f --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.ads @@ -0,0 +1,12 @@ +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; + +package Pkg is + + abc : constant Unbounded_String := To_Unbounded_String ("abc"); + def : constant Unbounded_String := To_Unbounded_String ("def"); + ghi : constant Unbounded_String := To_Unbounded_String ("ghi"); + bool : constant Unbounded_String := To_Unbounded_String ("bool"); + + function Foo (Var : Unbounded_String) return Boolean; + +end; diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/test_df.adb b/testsuite/tests/M528-002-transient-finalize/variant1/src/test_df.adb new file mode 100644 index 000000000..430f86196 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/test_df.adb @@ -0,0 +1,15 @@ +with Assert, Pkg; use Pkg; + +procedure Test_DF is +begin + Assert (not Foo (bool)); +end; + +--# pkg.adb +-- /evalA/ s=>l+, dmu=>l! ## s=>0, dmu=>dT- +-- /evalB/ s=>l+, dmu=>l! ## 0 +-- /evalC/ s=>l+, dmu=>l! ## 0 +-- /dtrue/ l- ## s- +-- /dfalse/ l+ ## 0 + + diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/test_dt.adb b/testsuite/tests/M528-002-transient-finalize/variant1/src/test_dt.adb new file mode 100644 index 000000000..cbb24aa6b --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/test_dt.adb @@ -0,0 +1,15 @@ +with Assert, Pkg; use Pkg; + +procedure Test_DT is +begin + Assert (Foo (abc)); +end; + +--# pkg.adb +-- /evalA/ s=>l+, dmu=>l! ## s=>0, dmu=>dF- +-- /evalB/ s=>l+, dmu=>l! ## 0 +-- /evalC/ s=>l+, dmu=>l! ## 0 +-- /dtrue/ l+ ## 0 +-- /dfalse/ l- ## s- + + diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/test.py b/testsuite/tests/M528-002-transient-finalize/variant1/test.py new file mode 100644 index 000000000..e795c2214 --- /dev/null +++ b/testsuite/tests/M528-002-transient-finalize/variant1/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/M531-035-3264-ld_preload/sls.c b/testsuite/tests/M531-035-3264-ld_preload/sls.c new file mode 100644 index 000000000..c5512d4bc --- /dev/null +++ b/testsuite/tests/M531-035-3264-ld_preload/sls.c @@ -0,0 +1,8 @@ +#include + +int +main () +{ + system ("ls"); + return 0; +} diff --git a/testsuite/tests/M531-035-3264-ld_preload/test.opt b/testsuite/tests/M531-035-3264-ld_preload/test.opt new file mode 100644 index 000000000..7810bf39c --- /dev/null +++ b/testsuite/tests/M531-035-3264-ld_preload/test.opt @@ -0,0 +1,2 @@ +!x86-linux,!x86_64-linux DEAD test behavior on program using "system" +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/M531-035-3264-ld_preload/test.py b/testsuite/tests/M531-035-3264-ld_preload/test.py new file mode 100644 index 000000000..3a3d91219 --- /dev/null +++ b/testsuite/tests/M531-035-3264-ld_preload/test.py @@ -0,0 +1,29 @@ +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import exepath_to, gprbuild, gprfor, xrun + +Wdir("tmp_") + +# Point of this test is to check that the execution of a program using the +# "system" function works fine, without triggering LD_PRELOAD warning from +# valgrind when this happens to be our underlying execution engine. + +# We build and check the output of a program doing system("ls") + +gprbuild(gprfor(mains=['sls.c'], srcdirs='..')) + +p = xrun(exepath_to("sls")) + +thistest.fail_if( + re.search(pattern="LD_PRELOAD", string=p.out), + "spurious occurrence of LD_PRELOAD in the gnatcov run output" +) + +thistest.fail_if( + not re.search(pattern="gen.gpr", string=p.out), + "missing expected nls.c from the program output" +) + +thistest.result() diff --git a/testsuite/tests/M625-011-GPR-Cunits/src/bar.c b/testsuite/tests/M625-011-GPR-Cunits/src/bar.c new file mode 100644 index 000000000..20ba45704 --- /dev/null +++ b/testsuite/tests/M625-011-GPR-Cunits/src/bar.c @@ -0,0 +1,7 @@ +#include "bar.h" + +int +bar (int x) +{ + return x + 1; +} \ No newline at end of file diff --git a/testsuite/tests/M625-011-GPR-Cunits/src/bar.h b/testsuite/tests/M625-011-GPR-Cunits/src/bar.h new file mode 100644 index 000000000..90792bc00 --- /dev/null +++ b/testsuite/tests/M625-011-GPR-Cunits/src/bar.h @@ -0,0 +1,12 @@ +#ifndef BAR_H +#define BAR_H + +int bar (int x); + +static int +baz (int x) +{ + return x - 1; +} + +#endif // BAR_H \ No newline at end of file diff --git a/testsuite/tests/M625-011-GPR-Cunits/src/foo.c b/testsuite/tests/M625-011-GPR-Cunits/src/foo.c new file mode 100644 index 000000000..13906f359 --- /dev/null +++ b/testsuite/tests/M625-011-GPR-Cunits/src/foo.c @@ -0,0 +1,7 @@ +#include "bar.h" + +int +main (void) +{ + return baz (bar (0)); +} diff --git a/testsuite/tests/M625-011-GPR-Cunits/test.py b/testsuite/tests/M625-011-GPR-Cunits/test.py new file mode 100644 index 000000000..c3dec0732 --- /dev/null +++ b/testsuite/tests/M625-011-GPR-Cunits/test.py @@ -0,0 +1,43 @@ +""" +Check that gnatcov uses projects files to find SCOs for C units. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, empty, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +wd = Wdir('tmp_') + +# Create a very simple C project +gpr = gprfor(mains='foo.c', srcdirs=['../src'], langs=["C"]) + +# By default build_and_run will use -P to designate the units of interest, +# which is what we want here. + +coverage_log = 'coverage.log' + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + mains=['foo'], + covlevel='stmt', + extra_coverage_args=['-axcov', '--output-dir=.'], + out=coverage_log +) + +thistest.fail_if( + not empty(coverage_log), + comment='"gnatcov coverage" output not empty:\n' + + contents_of(coverage_log) +) + +check_xcov_reports('*.xcov', { + 'foo.c.xcov': {'+': {6}}, + 'bar.c.xcov': {'+': {6}}, + 'bar.h.xcov': {'+': {9}} +} +) + +thistest.result() diff --git a/testsuite/tests/M625-040-slow_on_windows/p.adb b/testsuite/tests/M625-040-slow_on_windows/p.adb new file mode 100644 index 000000000..64f041b55 --- /dev/null +++ b/testsuite/tests/M625-040-slow_on_windows/p.adb @@ -0,0 +1,16 @@ + +procedure P is + X : Integer := 0; + pragma Volatile (X); + + N_Increments : Integer := 5000; + pragma Volatile (N_increments); + +begin + for I in 1 .. N_Increments loop + X := X + 1; + end loop; + if X /= N_Increments then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/M625-040-slow_on_windows/test.opt b/testsuite/tests/M625-040-slow_on_windows/test.opt new file mode 100644 index 000000000..71e7fba49 --- /dev/null +++ b/testsuite/tests/M625-040-slow_on_windows/test.opt @@ -0,0 +1,2 @@ +# test is there to allow manual investigation of timing issues. +ALL DEAD test meant to facilitate manual timing investigation diff --git a/testsuite/tests/M625-040-slow_on_windows/test.py b/testsuite/tests/M625-040-slow_on_windows/test.py new file mode 100644 index 000000000..8cba10dd7 --- /dev/null +++ b/testsuite/tests/M625-040-slow_on_windows/test.py @@ -0,0 +1,54 @@ +import cProfile +import pstats +import time + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import exename_for, gprbuild, gprfor, xrun + + +Wdir('tmp_') +gpr = gprfor(srcdirs=['..'], mains=['p.adb']) + + +def run(action, repeat, tag): + start = time.clock() + for i in range(repeat): + action() + end = time.clock() + print '%s: %2.5f' % (tag, end-start) + + +def eval_gprbuild(): + run(action=lambda: gprbuild(gpr), repeat=50, tag="gprbuild") + + +def eval_xrun(): + run(action=lambda: xrun(exename_for("p")), repeat=50, tag="xrun") + + +def eval(what): + profiler = cProfile.Profile() + profiler.run("eval_%s()" % what) + + ps = pstats.Stats(profiler) + ps.strip_dirs() + ps.sort_stats('time') + + print "===================" + print "== %s ==" % what + + print "-- profiling stats --" + ps.print_stats() + + print "-- callers --" + ps.print_callers() + + print "-- callees --" + ps.print_callees() + + +eval("gprbuild") +eval("xrun") + +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/ops.adb new file mode 100644 index 000000000..5fd1782b7 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/ops.adb @@ -0,0 +1,16 @@ +package body Ops is + function Eval (Idx : Cond_Index) return Boolean is + begin + if -- # cond + Cond_1'Length /= 0 -- # first + and then -- # op + Cond_1 (Idx) -- # second + and then -- # op + Cond_2 (Idx) -- # third + then + return True; -- # true + else + return False; -- # false + end if; + end; +end; diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_no.adb new file mode 100644 index 000000000..a0ad1f85c --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_no.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_false.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_false.adb new file mode 100644 index 000000000..064a1f2ac --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_false.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_False is +begin + Assert (Eval (4) = False); +end Test_Outcome_False; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_true.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_true.adb new file mode 100644 index 000000000..0f8c4ba04 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_outcome_true.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_True is +begin + Assert (Eval (1) = True); +end Test_Outcome_True; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second.adb new file mode 100644 index 000000000..7d6a5a011 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Second is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); +end Test_Second; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## 0 +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second_third.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second_third.adb new file mode 100644 index 000000000..ede79cdea --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_second_third.adb @@ -0,0 +1,38 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Second_Third is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); + Assert (Eval (3) = False); +end Test_Second_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_third.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_third.adb new file mode 100644 index 000000000..6d414087f --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/src/test_third.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Third is +begin + Assert (Eval (1) = True); + Assert (Eval (3) = False); +end Test_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/test.py b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run-Run/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run/src/ops.adb new file mode 100644 index 000000000..a38dd4472 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run/src/ops.adb @@ -0,0 +1,9 @@ +package body Ops is + function Eval (Idx : Cond_Index) return Boolean is + begin + return -- # stmt + Cond_1'Length /= 0 -- # first + and then -- # op + Cond_1 (Idx); -- # second + end Eval; +end; diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_no.adb new file mode 100644 index 000000000..ce6b7d8d7 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_no.adb @@ -0,0 +1,27 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/stmt/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 + +--%cov: --level=stmt\+decision +-- =/stmt/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/stmt/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_outcome_true.adb b/testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_outcome_true.adb new file mode 100644 index 000000000..9337eddde --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run/src/test_outcome_true.adb @@ -0,0 +1,27 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_True is +begin + Assert (Eval (1) = True); +end Test_Outcome_True; + +--# ops.adb + +--%cov: --level=stmt +-- =/stmt/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/stmt/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/stmt/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## eF- +-- =/second/ l! ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run/test.opt b/testsuite/tests/M716-023-constant-conditions/Const-Run/test.opt new file mode 100644 index 000000000..29a6a1776 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run/test.opt @@ -0,0 +1 @@ +bin-traces XFAIL M716-006: inlining and condition folding diff --git a/testsuite/tests/M716-023-constant-conditions/Const-Run/test.py b/testsuite/tests/M716-023-constant-conditions/Const-Run/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Const-Run/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/ops.adb new file mode 100644 index 000000000..ff24e14db --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/ops.adb @@ -0,0 +1,22 @@ +package body Ops is + function Eval_Cond + (Idx : Cond_Index; + Conds : Cond_Array_Option) return Boolean + is + begin + return -- # stmt-2 + Conds.Available -- # first-2 + and then -- # op-2 + Conds.Cond (Idx) -- # second-2 + and then -- # op-2 + Cond_1 (Idx); -- # third-2 + end Eval_Cond; + + function Eval (Idx : Cond_Index) return Boolean is + begin + return -- # stmt-1 + Cond_2 (Idx) -- # first-1 + and then -- # op-1 + Eval_Cond (Idx, (True, Cond_1)); -- # second-1 + end Eval; +end Ops; diff --git a/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/test_no.adb new file mode 100644 index 000000000..5bebd8a67 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/src/test_no.adb @@ -0,0 +1,42 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/stmt-1/ l- ## s- +-- =/op-1/ l- ## 0 +-- =/first-1/ l- ## 0 +-- =/second-1/ l- ## 0 +-- =/stmt-2/ l- ## s- +-- =/op-2/ l- ## 0 +-- =/first-2/ l- ## 0 +-- =/second-2/ l- ## 0 +-- =/third-2/ l- ## 0 + +--%cov: --level=stmt\+decision +-- =/stmt-1/ l- ## s- +-- =/op-1/ l- ## 0 +-- =/first-1/ l- ## 0 +-- =/second-1/ l- ## 0 +-- =/stmt-2/ l- ## s- +-- =/op-2/ l- ## 0 +-- =/first-2/ l- ## 0 +-- =/second-2/ l- ## 0 +-- =/third-2/ l- ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/stmt-1/ l- ## s- +-- =/op-1/ l- ## 0 +-- =/first-1/ l- ## 0 +-- =/second-1/ l- ## 0 +-- =/stmt-2/ l- ## s- +-- =/op-2/ l- ## 0 +-- =/first-2/ l- ## 0 +-- =/second-2/ l- ## 0 +-- =/third-2/ l- ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/test.py b/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/InliningMakingConstant/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/ops.adb new file mode 100644 index 000000000..9305d0195 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/ops.adb @@ -0,0 +1,16 @@ +package body Ops is + function Eval (Idx : Cond_Index) return Boolean is + begin + if -- # cond + Cond_1 (Idx) -- # first + and then -- # op + Cond_1'Length /= 0 -- # second + and then -- # op + Cond_2 (Idx) -- # third + then + return True; -- # true + else + return False; -- # false + end if; + end; +end; diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first.adb new file mode 100644 index 000000000..dabe1f5b9 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); +end Test_First; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first_third.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first_third.adb new file mode 100644 index 000000000..e5cc0a19f --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_first_third.adb @@ -0,0 +1,38 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First_Third is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); + Assert (Eval (3) = False); +end Test_First_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_no.adb new file mode 100644 index 000000000..a0ad1f85c --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_no.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_false.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_false.adb new file mode 100644 index 000000000..064a1f2ac --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_false.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_False is +begin + Assert (Eval (4) = False); +end Test_Outcome_False; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_true.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_true.adb new file mode 100644 index 000000000..0f8c4ba04 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_outcome_true.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_True is +begin + Assert (Eval (1) = True); +end Test_Outcome_True; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_third.adb b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_third.adb new file mode 100644 index 000000000..6d414087f --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/src/test_third.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Third is +begin + Assert (Eval (1) = True); + Assert (Eval (3) = False); +end Test_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/test.py b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Const-Run/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/ops.adb new file mode 100644 index 000000000..78e859bef --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/ops.adb @@ -0,0 +1,16 @@ +package body Ops is + function Eval (Idx : Cond_Index) return Boolean is + begin + if -- # cond + (Cond_1 (Idx) -- # first + and then -- # op + Cond_1'Length /= 0) -- # second + or else -- # op + Cond_2 (Idx) -- # third + then + return True; -- # true + else + return False; -- # false + end if; + end; +end; diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first.adb new file mode 100644 index 000000000..d9d5c816a --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First is +begin + Assert (Eval (3) = True); + Assert (Eval (4) = False); +end Test_First; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first_third.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first_third.adb new file mode 100644 index 000000000..504ba7ccf --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_first_third.adb @@ -0,0 +1,38 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First_Third is +begin + Assert (Eval (2) = True); + Assert (Eval (3) = True); + Assert (Eval (4) = False); +end Test_First_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_no.adb new file mode 100644 index 000000000..a0ad1f85c --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_no.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_false.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_false.adb new file mode 100644 index 000000000..064a1f2ac --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_false.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_False is +begin + Assert (Eval (4) = False); +end Test_Outcome_False; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_true.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_true.adb new file mode 100644 index 000000000..0f8c4ba04 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_outcome_true.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_True is +begin + Assert (Eval (1) = True); +end Test_Outcome_True; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_third.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_third.adb new file mode 100644 index 000000000..e6da51c96 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/src/test_third.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Third is +begin + Assert (Eval (2) = True); + Assert (Eval (4) = False); +end Test_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/test.py b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstOutcome-Run/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/ops.adb new file mode 100644 index 000000000..188c5134a --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/ops.adb @@ -0,0 +1,16 @@ +package body Ops is + function Eval (Idx : Cond_Index) return Boolean is + begin + if -- # cond + Cond_Array_Current.Cond (Idx) -- # first + and then -- # op + Cond_Array_Current.Cond'Length /= 0 -- # second + and then -- # op + Cond_2 (Idx) -- # third + then + return True; -- # true + else + return False; -- # false + end if; + end; +end; diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first.adb new file mode 100644 index 000000000..dabe1f5b9 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); +end Test_First; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first_third.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first_third.adb new file mode 100644 index 000000000..e5cc0a19f --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_first_third.adb @@ -0,0 +1,38 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First_Third is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); + Assert (Eval (3) = False); +end Test_First_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_no.adb new file mode 100644 index 000000000..a0ad1f85c --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_no.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_false.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_false.adb new file mode 100644 index 000000000..064a1f2ac --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_false.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_False is +begin + Assert (Eval (4) = False); +end Test_Outcome_False; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_true.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_true.adb new file mode 100644 index 000000000..0f8c4ba04 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_outcome_true.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_True is +begin + Assert (Eval (1) = True); +end Test_Outcome_True; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_third.adb b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_third.adb new file mode 100644 index 000000000..6d414087f --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/src/test_third.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Third is +begin + Assert (Eval (1) = True); + Assert (Eval (3) = False); +end Test_Third; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## c! +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/test.py b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-ConstRCheck-Run/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/ops.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/ops.adb new file mode 100644 index 000000000..a91e3ce31 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/ops.adb @@ -0,0 +1,16 @@ +package body Ops is + function Eval (Idx : Cond_Index) return Boolean is + begin + if -- # cond + Cond_1 (Idx) -- # first + and then -- # op + Cond_2 (Idx) -- # second + and then -- # op + Cond_1'Length /= 0 -- # third + then + return True; -- # true + else + return False; -- # false + end if; + end; +end; diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first.adb new file mode 100644 index 000000000..dabe1f5b9 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); +end Test_First; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## c! +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first_second.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first_second.adb new file mode 100644 index 000000000..685210dbb --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_first_second.adb @@ -0,0 +1,38 @@ +with Assert; +with Ops; use Ops; + +procedure Test_First_Second is +begin + Assert (Eval (1) = True); + Assert (Eval (2) = False); + Assert (Eval (3) = False); +end Test_First_Second; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## 0 +-- =/second/ l! ## 0 +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_no.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_no.adb new file mode 100644 index 000000000..a0ad1f85c --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_no.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_No is +begin + null; +end Test_No; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l- ## s- +-- =/op/ l- ## 0 +-- =/first/ l- ## 0 +-- =/second/ l- ## 0 +-- =/third/ l- ## 0 +-- =/true/ l- ## s- +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_false.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_false.adb new file mode 100644 index 000000000..064a1f2ac --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_false.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_False is +begin + Assert (Eval (4) = False); +end Test_Outcome_False; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dT- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l- ## s- +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_true.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_true.adb new file mode 100644 index 000000000..0f8c4ba04 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_outcome_true.adb @@ -0,0 +1,36 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Outcome_True is +begin + Assert (Eval (1) = True); +end Test_Outcome_True; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## dF- +-- =/second/ l! ## 0 +-- =/third/ l! ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l- ## s- diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_second.adb b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_second.adb new file mode 100644 index 000000000..74d04868b --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/src/test_second.adb @@ -0,0 +1,37 @@ +with Assert; +with Ops; use Ops; + +procedure Test_Second is +begin + Assert (Eval (1) = True); + Assert (Eval (3) = False); +end Test_Second; + +--# ops.adb + +--%cov: --level=stmt +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+decision +-- =/cond/ l+ ## 0 +-- =/op/ l+ ## 0 +-- =/first/ l+ ## 0 +-- =/second/ l+ ## 0 +-- =/third/ l+ ## 0 +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 + +--%cov: --level=stmt\+(uc_)?mcdc +-- =/cond/ l+ ## 0 +-- =/op/ l! ## 0 +-- =/first/ l! ## c! +-- =/second/ l! ## 0 +-- =/third/ l! ## c! +-- =/true/ l+ ## 0 +-- =/false/ l+ ## 0 diff --git a/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/test.py b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/Run-Run-Const/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/M716-023-constant-conditions/extra.opt b/testsuite/tests/M716-023-constant-conditions/extra.opt new file mode 100644 index 000000000..a6d8c9c4c --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/extra.opt @@ -0,0 +1,2 @@ +7.0.3 DEAD testing support of constant conditions, implemented post 7.0.3 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/M716-023-constant-conditions/src/assert.adb b/testsuite/tests/M716-023-constant-conditions/src/assert.adb new file mode 100644 index 000000000..075669142 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (X : Boolean) is +begin + if not X then + raise Program_Error; + end if; +end Assert; diff --git a/testsuite/tests/M716-023-constant-conditions/src/assert.ads b/testsuite/tests/M716-023-constant-conditions/src/assert.ads new file mode 100644 index 000000000..ab78e4405 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/src/assert.ads @@ -0,0 +1 @@ +procedure Assert (X : Boolean); diff --git a/testsuite/tests/M716-023-constant-conditions/src/ops.ads b/testsuite/tests/M716-023-constant-conditions/src/ops.ads new file mode 100644 index 000000000..0ab93ed51 --- /dev/null +++ b/testsuite/tests/M716-023-constant-conditions/src/ops.ads @@ -0,0 +1,24 @@ +package Ops is + subtype Cond_Index is Natural range 1 .. 4; + type Cond_Array is array (Cond_Index) of Boolean; + Cond_1 : constant Cond_Array := (True, False, True, False); + Cond_2 : constant Cond_Array := (True, True, False, False); + + type Cond_Array_Option (Available : Boolean) is record + case Available is + when False => + null; + when True => + Cond : Cond_Array; + end case; + end record; + + Cond_Array_Unavailable : aliased Cond_Array_Option := + (Available => False); + Cond_Array_Available : aliased Cond_Array_Option := + (Available => True, Cond => Cond_1); + Cond_Array_Current : access Cond_Array_Option := + Cond_Array_Available'Access; + + function Eval (Idx : Cond_Index) return Boolean; +end Ops; diff --git a/testsuite/tests/M724-035-eh-warnings/src/show_whether_local.adb b/testsuite/tests/M724-035-eh-warnings/src/show_whether_local.adb new file mode 100644 index 000000000..a791a6a85 --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/src/show_whether_local.adb @@ -0,0 +1,33 @@ +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Exceptions; +with Ada.Text_IO; use Ada.Text_IO; + +with Strict_Head; +procedure Show_Whether_Local (Var_Name : String) is + use Ada.Exceptions; + + function Is_Local_Var (S : Unbounded_String) return Boolean is + R : Boolean; + begin + if To_String (Strict_Head (S, 2)) = "_L" then -- # evalA + R := True; -- # true + else + R := False; -- # false + end if; + return R; -- # ret + exception + when E : others => + declare + Name : constant String := Exception_Name (E); -- # exc + Msg : constant String := Exception_Message (E); -- # exc + begin + Put_Line ("Got exception: " & Name & "(" & Msg & ")"); -- # exc + end; + raise; -- # exc + end Is_Local_Var; + +begin + if Is_Local_Var (To_Unbounded_String (Var_Name)) then -- # evalD + Put_Line ("local"); -- # true + end if; +end Show_Whether_Local; diff --git a/testsuite/tests/M724-035-eh-warnings/src/strict_head.adb b/testsuite/tests/M724-035-eh-warnings/src/strict_head.adb new file mode 100644 index 000000000..3be38c288 --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/src/strict_head.adb @@ -0,0 +1,11 @@ +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; + +function Strict_Head + (S : Unbounded_String; Len : Positive) return Unbounded_String +is +begin + if Length (S) < Len then + raise Constraint_Error; + end if; + return Head (S, Len); +end Strict_Head; diff --git a/testsuite/tests/M724-035-eh-warnings/src/test_both.adb b/testsuite/tests/M724-035-eh-warnings/src/test_both.adb new file mode 100644 index 000000000..51fe28333 --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/src/test_both.adb @@ -0,0 +1,13 @@ +with Show_Whether_Local; +procedure Test_Both is +begin + Show_Whether_Local ("_Local"); + Show_Whether_Local ("Global"); +end Test_Both; + +--# show_whether_local.adb +-- /eval/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 +-- /ret/ l+ ## 0 +-- /exc/ l- ## s- diff --git a/testsuite/tests/M724-035-eh-warnings/src/test_exc.adb b/testsuite/tests/M724-035-eh-warnings/src/test_exc.adb new file mode 100644 index 000000000..52a67659d --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/src/test_exc.adb @@ -0,0 +1,17 @@ +with Show_Whether_Local; +with Ada.Text_IO; use Ada.Text_IO; +procedure Test_Exc is +begin + Show_Whether_Local ("x"); + raise Program_Error with "expected C_E"; +exception + when Constraint_Error => + Put_Line ("got expected exception"); +end Test_Exc; + +--# show_whether_local.adb +-- /eval/ l! ## d- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /ret/ l- ## s- +-- /exc/ l+ ## 0 diff --git a/testsuite/tests/M724-035-eh-warnings/src/test_glob.adb b/testsuite/tests/M724-035-eh-warnings/src/test_glob.adb new file mode 100644 index 000000000..00ca91ebb --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/src/test_glob.adb @@ -0,0 +1,16 @@ +with Show_Whether_Local; +procedure Test_Glob is +begin + Show_Whether_Local ("_Global"); +end Test_Glob; + +--# show_whether_local.adb +-- /evalA/ l! ## dT- +-- /evalD/ l! ## d! +-- /true/ l- ## s- +-- /false/ l+ ## 0 +-- /ret/ l+ ## 0 +-- /exc/ l- ## s- +-- +-- %opts: --trace-mode=src +-- =/evalD/ l! ## dT- diff --git a/testsuite/tests/M724-035-eh-warnings/src/test_loc.adb b/testsuite/tests/M724-035-eh-warnings/src/test_loc.adb new file mode 100644 index 000000000..ef2840c77 --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/src/test_loc.adb @@ -0,0 +1,12 @@ +with Show_Whether_Local; +procedure Test_Loc is +begin + Show_Whether_Local ("_Local"); +end Test_Loc; +--# show_whether_local.adb +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /false/ l- ## s- +-- /ret/ l+ ## 0 +-- /exc/ l- ## s- + diff --git a/testsuite/tests/M724-035-eh-warnings/test.opt b/testsuite/tests/M724-035-eh-warnings/test.opt new file mode 100644 index 000000000..b00e5f3be --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/test.opt @@ -0,0 +1,2 @@ +ALL DEAD +native diff --git a/testsuite/tests/M724-035-eh-warnings/test.py b/testsuite/tests/M724-035-eh-warnings/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/M724-035-eh-warnings/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/M726-018-trace-exec-check/bar.adb b/testsuite/tests/M726-018-trace-exec-check/bar.adb new file mode 100644 index 000000000..bcd771f66 --- /dev/null +++ b/testsuite/tests/M726-018-trace-exec-check/bar.adb @@ -0,0 +1,31 @@ +with Foo; + +procedure Bar is + + function Fibo (N : Natural) return Natural is + + function Helper (Step, N1, N2 : Natural) return Natural is + begin + if Step >= N then + return N1; + else + return Helper(Step + 1, N2, N1 + N2); + end if; + end Helper; + + begin + return Helper (0, 0, 1); + end Fibo; + + Fibo_Ref : constant array (Natural range <>) of Natural := + (0, 1, 1, 2, 3, 5, 8, 13, 21); + +begin + Foo; + + for N in Fibo_Ref'Range loop + if Fibo (N) /= Fibo_Ref (N) then + raise Program_Error; + end if; + end loop; +end Bar; diff --git a/testsuite/tests/M726-018-trace-exec-check/foo.adb b/testsuite/tests/M726-018-trace-exec-check/foo.adb new file mode 100644 index 000000000..ca4ad6568 --- /dev/null +++ b/testsuite/tests/M726-018-trace-exec-check/foo.adb @@ -0,0 +1,14 @@ +procedure Foo is + function Fact (N : Natural) return Natural is + begin + if N <= 1 then + return 1; + else + return N * Fact (N - 1); + end if; + end Fact; +begin + if Fact (6) /= 720 then + raise Program_Error; + end if; +end Foo; diff --git a/testsuite/tests/M726-018-trace-exec-check/test.opt b/testsuite/tests/M726-018-trace-exec-check/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/M726-018-trace-exec-check/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/M726-018-trace-exec-check/test.py b/testsuite/tests/M726-018-trace-exec-check/test.py new file mode 100644 index 000000000..4eed6ba08 --- /dev/null +++ b/testsuite/tests/M726-018-trace-exec-check/test.py @@ -0,0 +1,87 @@ +from collections import namedtuple +import os +import shutil + +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import (exename_for, exepath_to, tracename_for, gprbuild, + gprfor, xrun, xcov,) + +# Work in a subdirectory +wd = Wdir(subdir='tmp_') + +gpr = gprfor(mains=['foo.adb', 'bar.adb'], + srcdirs=['..']) + +# Executable used to generate the reference trace +expected_program = exename_for('foo') + +# Executable that is different +unexpected_program = exename_for('bar') + +# Executable that is corrupted +corrupted_program = exename_for('foo-corrupted') + +# Real name for the executable used by the trace, convenient for substituing +# other executables still keeping the original one. +program_name = exename_for('program') +program_path = exepath_to('program') +trace_name = tracename_for('program') + +# Prepare the test material +gprbuild(project=gpr) + +expected_timestamp = (os.stat(expected_program).st_mtime, ) * 2 +unexpected_timestamp = (expected_timestamp[0] + 10, ) * 2 + +shutil.copy(expected_program, corrupted_program) + +# Add a 'A' byte to expected_program, and a 'B' byte to the corrupted_program. +# This way, they will have the same size, but a different checksum. +with open(expected_program, 'ab') as f: + f.write(b'\x00') +with open(corrupted_program, 'ab') as f: + f.write(b'\x01') + +# Generate the reference trace +shutil.copy(expected_program, program_name) +os.utime(program_name, expected_timestamp) +xrun(program_path) + +# Actually run the tests. +Case = namedtuple('Case', 'program timestamp expect_warning label') +for case in ( + Case(expected_program, expected_timestamp, False, + 'GOOD filesize, timestamp, checksum'), + Case(expected_program, unexpected_timestamp, True, + 'GOOD program, checksum; BAD timestamp'), + Case(unexpected_program, expected_timestamp, True, + 'GOOD timestamp, checksum; BAD program'), + Case(corrupted_program, expected_timestamp, True, + 'GOOD program, timestamp; BAD checksum'), +): + shutil.copy(case.program, program_name) + os.utime(program_name, case.timestamp) + + process = xcov( + 'coverage -P{} -c stmt -a report {}'.format(gpr, trace_name), + err='log.err', register_failure=False + ) + + xcov_warned = contents_of('log.err').startswith('warning: executable file') + + def expected_repr(expected): + return 'expected' if expected else 'unexpected' + + thistest.fail_if( + xcov_warned != case.expect_warning, + '{} ({})'.format( + 'Warnings expected, got no one' + if case.expect_warning else + 'Expected no warnings, but got one', + + case.label + ) + ) + +thistest.result() diff --git a/testsuite/tests/MA08-031/src/f.adb b/testsuite/tests/MA08-031/src/f.adb new file mode 100644 index 000000000..d97b8b76e --- /dev/null +++ b/testsuite/tests/MA08-031/src/f.adb @@ -0,0 +1,8 @@ +function F (A, B, C, D : Boolean) return Boolean is +begin + if (A and then B) or (C or D) then + return True; + else + return False; + end if; +end; diff --git a/testsuite/tests/MA08-031/test.opt b/testsuite/tests/MA08-031/test.opt new file mode 100644 index 000000000..a3304d764 --- /dev/null +++ b/testsuite/tests/MA08-031/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test runs "gnatcov map-routines" diff --git a/testsuite/tests/MA08-031/test.py b/testsuite/tests/MA08-031/test.py new file mode 100644 index 000000000..40aaf8248 --- /dev/null +++ b/testsuite/tests/MA08-031/test.py @@ -0,0 +1,10 @@ +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import gprfor, gprbuild, xcov + + +Wdir('tmp_') +gprbuild(gprfor(['f.adb'], srcdirs='../src'), gargs='-c') +xcov(['map-routines', '--scos=obj/f.ali', 'obj/f.o'], out='xcov.out') +thistest.fail_if(match('warning:', 'xcov.out'), 'no labeling warning expected') +thistest.result() diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/assert.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/assert.adb new file mode 100644 index 000000000..c391fc68a --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/assert.adb @@ -0,0 +1,7 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.adb new file mode 100644 index 000000000..d5c12fb4f --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.adb @@ -0,0 +1,7 @@ +package body Counters is + procedure Bump (X : in out Natural) is + begin + X := X + 1; + end; +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.ads b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.ads new file mode 100644 index 000000000..a16467c03 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.ads @@ -0,0 +1,6 @@ +package Counters is + Nthen, Nelse : Natural := 0; + + procedure Bump (X : in out Natural); +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/falseonly.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/falseonly.adb new file mode 100644 index 000000000..0c9326c4f --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/falseonly.adb @@ -0,0 +1,21 @@ +with Support, Counters; use Support; + +procedure Falseonly is + + function Pos (X : Integer) return Boolean is + begin + if X > 0 then -- # test + Counters.Bump (Counters.Nthen); -- # then + return True; -- # then + else + Counters.Bump (Counters.Nelse); -- # else + return False; -- # else + end if; + end Pos; + +begin + Assert (Pos (-1) = False); + Assert (Counters.Nthen = 0); + Assert (Counters.Nelse = 1); +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_falseonly.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_falseonly.adb new file mode 100644 index 000000000..5321a76b6 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_falseonly.adb @@ -0,0 +1,17 @@ +with Falseonly; + +procedure Test_Falseonly is +begin + Falseonly; +end; + +--# falseonly.adb +-- /test/ l! ## dT- +-- /then/ l. ## 0 +-- /else/ l+ ## 0 + +-- %cov: --non-coverable +-- =/then/ l0 ## s0 + + + diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_truefalse.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_truefalse.adb new file mode 100644 index 000000000..eab07046c --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_truefalse.adb @@ -0,0 +1,11 @@ +with Truefalse; +procedure Test_Truefalse is +begin + Truefalse; +end; + +--# truefalse.adb +-- /test/ l+ ## 0 +-- /then/ l+ ## 0 +-- /else/ l+ ## 0 + diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_trueonly.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_trueonly.adb new file mode 100644 index 000000000..279ab3b23 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_trueonly.adb @@ -0,0 +1,17 @@ +with Trueonly; + +procedure Test_Trueonly is +begin + Trueonly; +end; + +--# trueonly.adb +-- /test/ l! ## dF- +-- /then/ l+ ## 0 +-- /else/ l. ## 0 + +-- %cov: --non-coverable +-- =/else/ l0 ## s0 + + + diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/truefalse.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/truefalse.adb new file mode 100644 index 000000000..addb2bd46 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/truefalse.adb @@ -0,0 +1,22 @@ +with Support, Counters; use Support; + +procedure Truefalse is + + function Pos (X : Integer) return Boolean is + begin + if X > 0 then -- # test + Counters.Bump (Counters.Nthen); -- # then + return True; -- # then + else + Counters.Bump (Counters.Nelse); -- # else + return False; -- # else + end if; + end Pos; + +begin + Assert (Pos (1) = True); + Assert (Pos (-1) = False); + Assert (Counters.Nthen = 1); + Assert (Counters.Nelse = 1); +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/trueonly.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/trueonly.adb new file mode 100644 index 000000000..ab81d0d15 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/trueonly.adb @@ -0,0 +1,21 @@ +with Support, Counters; use Support; + +procedure Trueonly is + + function Pos (X : Integer) return Boolean is + begin + if X > 0 then -- # test + Counters.Bump (Counters.Nthen); -- # then + return True; -- # then + else + Counters.Bump (Counters.Nelse); -- # else + return False; -- # else + end if; + end Pos; + +begin + Assert (Pos (1) = True); + Assert (Counters.Nthen = 1); + Assert (Counters.Nelse = 0); +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.opt b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.opt new file mode 100644 index 000000000..22baf97a0 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.opt @@ -0,0 +1 @@ +bin-traces,!CARGS_O1,!CARGS_gnatn DEAD diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.py b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.py new file mode 100644 index 000000000..95ff64f52 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest + + +TestCase().run(covcontrol=CovControl(covoptions="--non-coverable")) +thistest.result() diff --git a/testsuite/tests/MB05-039-not-coverable/extra.opt b/testsuite/tests/MB05-039-not-coverable/extra.opt new file mode 100644 index 000000000..aaa8c50c6 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/extra.opt @@ -0,0 +1 @@ +src-traces XFAIL S711-049: src-traces and assertion/check policy diff --git a/testsuite/tests/MB05-039-not-coverable/src/state.adb b/testsuite/tests/MB05-039-not-coverable/src/state.adb new file mode 100644 index 000000000..02d6368b4 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/src/state.adb @@ -0,0 +1,10 @@ +package body State is + procedure Tick is + begin + Ticks := Ticks + 1; + end; + procedure Dtick is + begin + Dticks := Dticks + 1; + end; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/src/state.ads b/testsuite/tests/MB05-039-not-coverable/src/state.ads new file mode 100644 index 000000000..2290511aa --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/src/state.ads @@ -0,0 +1,15 @@ +package State is + + -- Liveness ticks, expected to click + + Ticks : Integer := 0; + pragma Volatile (Ticks); + + -- Death ticks, expected never to clisk + + Dticks : Integer := 0; + pragma Volatile (Dticks); + + procedure Tick; + procedure Dtick; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrnf.adb new file mode 100644 index 000000000..317b59e05 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrnf.adb @@ -0,0 +1,15 @@ +with Support, Values; use Support; + +procedure Check_Local_NRNF is + + type My_Range is range -100 .. -1; + My_Factor : constant := -3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + X : My_Range := -12; +begin + Assert (My_Processor.F(X) = Integer(X-4) + My_Factor); +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrpf.adb new file mode 100644 index 000000000..33cbaf715 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrpf.adb @@ -0,0 +1,15 @@ +with Support, Values; use Support; + +procedure Check_Local_NRPF is + + type My_Range is range -100 .. -1; + My_Factor : constant := 3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + X : My_Range := -12; +begin + Assert (My_Processor.F(X) = Integer(X-4) + 2*My_Factor); +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prnf.adb new file mode 100644 index 000000000..8fe026af1 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prnf.adb @@ -0,0 +1,16 @@ +with Support, Values; use Support; + +procedure Check_Local_PRNF is + + type My_Range is range 1 .. 100; + My_Factor : constant := -3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + X : My_Range := 12; +begin + Assert (My_Processor.F(X) = Integer(X+1) + My_Factor); +end; + + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prpf.adb new file mode 100644 index 000000000..a642452e2 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prpf.adb @@ -0,0 +1,15 @@ +with Support, Values; use Support; + +procedure Check_Local_PRPF is + + type My_Range is range 1 .. 100; + My_Factor : constant := 3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + X : My_Range := 12; +begin + Assert (My_Processor.F(X) = Integer(X+1) + 2*My_Factor); +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrnf.adb new file mode 100644 index 000000000..536483927 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrnf.adb @@ -0,0 +1,19 @@ +with Check_Local_NRNF; + +procedure Test_Local_NRNF is +begin + Check_Local_NRNF; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xneg/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l0 ## s0 +-- /fneg/ l+ ## 0 + +-- /xpos/ l- ## s- + +-- %cargs: -O1 +-- =/xpos/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrpf.adb new file mode 100644 index 000000000..85793fb5b --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_nrpf.adb @@ -0,0 +1,19 @@ +with Check_Local_NRPF; + +procedure Test_Local_NRPF is +begin + Check_Local_NRPF; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xneg/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l+ ## 0 +-- /fneg/ l0 ## s0 + +-- /xpos/ l- ## s- + +-- %cargs: -O1 +-- =/xpos/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prnf.adb new file mode 100644 index 000000000..47cab03c5 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prnf.adb @@ -0,0 +1,20 @@ +with Check_Local_PRNF; + +procedure Test_Local_PRNF is +begin + Check_Local_PRNF; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l0 ## s0 +-- /fneg/ l+ ## 0 + +-- /xneg/ l- ## s- + +-- %cargs: -O1 +-- =/xneg/ l0 ## s0 + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prpf.adb new file mode 100644 index 000000000..6196ed64e --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prpf.adb @@ -0,0 +1,20 @@ +with Check_Local_PRPF; + +procedure Test_Local_PRPF is +begin + Check_Local_PRPF; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l+ ## 0 +-- /fneg/ l0 ## s0 + +-- /xneg/ l- ## s- + +-- %cargs: -O1 +-- =/xneg/ l0 ## s0 + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_mrmf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_mrmf.adb new file mode 100644 index 000000000..64d8c2e52 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_mrmf.adb @@ -0,0 +1,16 @@ +with Values_MRMF; + +procedure Test_Values_MRMF is +begin + Values_MRMF.Check; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l+ ## 0 +-- /xneg/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l+ ## 0 +-- /fneg/ l+ ## 0 + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrnf.adb new file mode 100644 index 000000000..7b2d87943 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrnf.adb @@ -0,0 +1,19 @@ +with Values_NRNF; + +procedure Test_Values_NRNF is +begin + Values_NRNF.Check; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l- ## s- +-- /xneg/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l0 ## s0 +-- /fneg/ l+ ## 0 + +-- %cargs: -O1 +-- =/xpos/ l0 ## s0 + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrpf.adb new file mode 100644 index 000000000..1aeb439e6 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrpf.adb @@ -0,0 +1,19 @@ +with Values_NRPF; + +procedure Test_Values_NRPF is +begin + Values_NRPF.Check; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l- ## s- +-- /xneg/ l+ ## 0 +-- /test_factor/ l+ ## 0 +-- /fpos/ l+ ## 0 +-- /fneg/ l0 ## s0 + +-- %cargs: -O1 +-- =/xpos/ l0 ## s0 + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prnf.adb new file mode 100644 index 000000000..289ba99c7 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prnf.adb @@ -0,0 +1,18 @@ +with Values_PRNF; + +procedure Test_Values_PRNF is +begin + Values_PRNF.Check; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l+ ## 0 +-- /xneg/ l- ## s- +-- /test_factor/ l+ ## 0 +-- /fpos/ l0 ## s0 +-- /fneg/ l+ ## 0 + +-- %cargs: -O1 +-- =/xneg/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prpf.adb new file mode 100644 index 000000000..03e13dbe4 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_prpf.adb @@ -0,0 +1,18 @@ +with Values_PRPF; + +procedure Test_Values_PRPF is +begin + Values_PRPF.Check; +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /test_x/ l+ ## 0 +-- /xpos/ l+ ## 0 +-- /xneg/ l- ## s- +-- /test_factor/ l+ ## 0 +-- /fpos/ l+ ## 0 +-- /fneg/ l0 ## s0 + +-- %cargs: -O1 +-- =/xneg/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.adb new file mode 100644 index 000000000..1503f769c --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.adb @@ -0,0 +1,32 @@ +with State; use State; + +-- A few items of note here: +-- +-- * The X > 0 test can be always True (or False) for some definitions +-- of Value_T. The compiler would normally optimize this away in instances +-- on request (-O1), even with -fpreserve-control-flow. +-- +-- * The tests on formal "in" parameters are always known at +-- at compiler time for a given instance, and the compiler +-- takes advantage of that to simplify early, even at O0. + +package body Values is + function F (X : in Value_T) return Integer Is + Adjusted_Factor : Integer; + V : Integer; + begin + if X > 0 then -- # test_x + V := Integer (X + 1); -- # xpos + else + V := Integer (X - 4); -- # xneg + end if; + + if Factor > 0 then -- # test_factor + Adjusted_Factor := Factor * 2; -- # fpos + else + Adjusted_Factor := Factor; -- # fneg + end if; + + return V + Adjusted_Factor; -- # stmt + end; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.ads new file mode 100644 index 000000000..5a661e743 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.ads @@ -0,0 +1,7 @@ +generic + type Value_T is range <>; + Factor : in Integer; + +package Values is + function F (X : in Value_T) return Integer; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.adb new file mode 100644 index 000000000..89d2eaac6 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.adb @@ -0,0 +1,26 @@ +with Support, Values; use Support; + +package body Values_MRMF is + + type My_P_Range is range 1 .. 100; + My_P_Factor : constant := 3; + + package My_Processor_P is new + Values (Value_T => My_P_Range, Factor => My_P_Factor); + + type My_N_Range is range -100 .. -1; + My_N_Factor : constant := -3; + + package My_Processor_N is new + Values (Value_T => My_N_Range, Factor => My_N_Factor); + + procedure Check is + XP : My_P_Range := 12; + XN : My_N_Range := -12; + begin + Assert (My_Processor_P.F(XP) = Integer(XP+1) + 2*My_P_Factor); + Assert (My_Processor_N.F(XN) = Integer(XN-4) + My_N_Factor); + end; + +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.ads new file mode 100644 index 000000000..d3a1afd9e --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.ads @@ -0,0 +1,8 @@ + +-- expose a sanity check subprogram operating on two instantiations of the +-- generic Values package with Mixed Ranges (MR, both positive and negative) +-- and Mixed Factors (MF) + +package Values_MRMF is + procedure Check; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.adb new file mode 100644 index 000000000..fdf1e121b --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.adb @@ -0,0 +1,18 @@ +with Support, Values; use Support; + +package body Values_NRNF is + + type My_Range is range -100 .. -1; + My_Factor : constant := -3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + procedure Check is + X : My_Range := -12; + begin + Assert (My_Processor.F(X) = Integer(X-4) + My_Factor); + end; + +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.ads new file mode 100644 index 000000000..e81428fd4 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.ads @@ -0,0 +1,4 @@ +package Values_NRNF is + procedure Check; +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.adb new file mode 100644 index 000000000..6290d3694 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.adb @@ -0,0 +1,18 @@ +with Support, Values; use Support; + +package body Values_NRPF is + + type My_Range is range -100 .. -1; + My_Factor : constant := 3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + procedure Check is + X : My_Range := -12; + begin + Assert (My_Processor.F(X) = Integer(X-4) + 2*My_Factor); + end; + +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.ads new file mode 100644 index 000000000..e7859cd77 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.ads @@ -0,0 +1,4 @@ +package Values_NRPF is + procedure Check; +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.adb new file mode 100644 index 000000000..85c067df5 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.adb @@ -0,0 +1,18 @@ +with Support, Values; use Support; + +package body Values_PRNF is + + type My_Range is range 1 .. 100; + My_Factor : constant := -3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + procedure Check is + X : My_Range := 12; + begin + Assert (My_Processor.F(X) = Integer(X+1) + My_Factor); + end; + +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.ads new file mode 100644 index 000000000..a18f1bcc1 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.ads @@ -0,0 +1,8 @@ + +-- expose a sanity check subprogram operating on an instantiation of the +-- generic Values package with a Positive Range (PR) and a Negative Factor +-- (NF) + +package Values_PRNF is + procedure Check; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.adb new file mode 100644 index 000000000..813beb61d --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.adb @@ -0,0 +1,18 @@ +with Support, Values; use Support; + +package body Values_PRPF is + + type My_Range is range 1 .. 100; + My_Factor : constant := 3; + + package My_Processor is new + Values (Value_T => My_Range, Factor => My_Factor); + + procedure Check is + X : My_Range := 12; + begin + Assert (My_Processor.F(X) = Integer(X+1) + 2*My_Factor); + end; + +end; + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.ads new file mode 100644 index 000000000..ace56c6b8 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.ads @@ -0,0 +1,8 @@ + +-- expose a sanity check subprogram operating on an instantiation of the +-- generic Values package with a Positive Range (PR) and a Positive Factor +-- (PF) + +package Values_PRPF is + procedure Check; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/test.py b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/test.py new file mode 100644 index 000000000..95ff64f52 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest + + +TestCase().run(covcontrol=CovControl(covoptions="--non-coverable")) +thistest.result() diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/test_values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/test_values.adb new file mode 100644 index 000000000..170308f4e --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/test_values.adb @@ -0,0 +1,18 @@ +with Values, Support; use Values, Support; + +procedure Test_Values is + V : Integer; +begin + Assert (One = 1.0); + + V := Value_Of (X => 15); + Assert (V = 15); + + Latch (V => 12); + V := Value_Of_X; + Assert (V = 12); +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /out/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.adb new file mode 100644 index 000000000..988efc12a --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.adb @@ -0,0 +1,42 @@ +with State; use State; + +package body Values is + + function One return Float is + begin + return 1.0; -- # stmt + exception + when Constraint_Error => + Dtick; -- # out + return 2.0; -- # out + end; + + function Value_Of (X : Integer) return Integer is + begin + return X; -- # stmt + exception + when Constraint_Error => + return 0; -- # out + when Program_Error => + return 66; -- # out + end; + + function Value_Of_X return Integer is + begin + return X; -- # stmt + exception + when others => return 50; -- # out + end; + + procedure Latch (V : Integer) is + begin + Tick; -- # stmt + begin + X := V; -- # stmt + exception + when Program_Error => Dtick; -- # out + end; + end; +end; + + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.ads b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.ads new file mode 100644 index 000000000..831955303 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.ads @@ -0,0 +1,9 @@ +package Values is + X : Integer := 1; + + function One return Float; + + procedure Latch (V : Integer); + function Value_Of (X : Integer) return Integer; + function Value_Of_X return Integer; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.opt b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.opt new file mode 100644 index 000000000..6399c1943 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.opt @@ -0,0 +1,3 @@ +7.0.2 DEAD 7.0 doesn't perform handler elimination reliably +7.0.3 DEAD 7.0 doesn't perform handler elimination reliably +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.py b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.py new file mode 100644 index 000000000..95ff64f52 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest + + +TestCase().run(covcontrol=CovControl(covoptions="--non-coverable")) +thistest.result() diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.adb b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.adb new file mode 100644 index 000000000..8b77db6aa --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.adb @@ -0,0 +1,133 @@ +with State; use State; + +package body IFS is + + -- Expose various cases with if statements controled by constant guards, + -- which are simplified early-on by the compiler front-end. + + -- Whether a code-less "if XX then" stmt becomes coverable itself + -- depends on whether it dominates coverable statements. + + procedure If_F_Var_Last is + begin + Tick; -- # reach + if GF then -- # out + Dtick; -- # out + end if; + end; + + procedure If_F_Cmp_Last is + begin + Tick; -- # reach + if GT = False then -- # out + Dtick; -- # out + end if; + end; + + procedure If_F_Var_Not_Last is + begin + Tick; -- # reach + if GF then -- # test + Dtick; -- # out + end if; + Tick; -- # reach + end; + + procedure If_F_Cmp_Not_Last is + begin + Tick; -- # reach + if GT = False then -- # test + Dtick; -- # out + end if; + Tick; -- # reach + end; + + -- + + procedure Ifelse_F_Var_Last is + begin + Tick; -- # reach + if GF then -- # test + Dtick; -- # out + else + Tick; -- # reach + end if; + end; + + procedure Ifelse_F_Cmp_Last is + begin + Tick; -- # reach + if GT = False then -- # test + Dtick; -- # out + else + Tick; -- # reach + end if; + end; + + procedure Ifelse_F_Var_Not_Last is + begin + Tick; -- # reach + if GF then -- # test + Dtick; -- # out + else + Tick; -- # reach + end if; + Tick; -- # reach + end; + + procedure Ifelse_F_Cmp_Not_Last is + begin + Tick; -- # reach + if GT = False then -- # test + Dtick; -- # out + else + Tick; -- # reach + end if; + Tick; -- # reach + end; + + -- + + procedure Ifelse_T_Var_Last is + begin + Tick; -- # reach + if GT then -- # test + Tick; -- # reach + else + Dtick; -- # out + end if; + end; + + procedure Ifelse_T_Cmp_Last is + begin + Tick; -- # reach + if GT = True then -- # test + Tick; -- # reach + else + Dtick; -- # out + end if; + end; + + procedure Ifelse_T_Var_Not_Last is + begin + Tick; -- # reach + if GT then -- # test + Tick; -- # reach + else + Dtick; -- # out + end if; + Tick; -- # reach + end; + + procedure Ifelse_T_Cmp_Not_Last is + begin + Tick; -- # reach + if GT = True then -- # test + Tick; -- # reach + else + Dtick; -- # out + end if; + Tick; -- # reach + end; + +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.ads b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.ads new file mode 100644 index 000000000..4659e4434 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.ads @@ -0,0 +1,20 @@ +package IFS is + + GT : constant Boolean := True; + GF : constant Boolean := False; + + procedure If_F_Var_Last; + procedure If_F_Cmp_Last; + procedure If_F_Var_Not_Last; + procedure If_F_Cmp_Not_Last; + + procedure Ifelse_F_Var_Last; + procedure Ifelse_F_Cmp_Last; + procedure Ifelse_F_Var_Not_Last; + procedure Ifelse_F_Cmp_Not_Last; + + procedure Ifelse_T_Var_Last; + procedure Ifelse_T_Cmp_Last; + procedure Ifelse_T_Var_Not_Last; + procedure Ifelse_T_Cmp_Not_Last; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/test_ifs.adb b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/test_ifs.adb new file mode 100644 index 000000000..ead89f85f --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/test_ifs.adb @@ -0,0 +1,46 @@ +with Ifs, State; use Ifs, State; +with Support; use Support; + +procedure Test_Ifs is +begin + If_F_Var_Last; + Assert (Ticks = 1); + + If_F_Cmp_Last; + Assert (Ticks = 2); + + If_F_Var_Not_Last; + Assert (Ticks = 4); + + If_F_Cmp_Not_Last; + Assert (Ticks = 6); + + Ifelse_F_Var_Last; + Assert (Ticks = 8); + + Ifelse_F_Cmp_Last; + Assert (Ticks = 10); + + Ifelse_F_Var_Not_Last; + Assert (Ticks = 13); + + Ifelse_F_Cmp_Not_Last; + Assert (Ticks = 16); + + Ifelse_T_Var_Last; + Assert (Ticks = 18); + + Ifelse_T_Cmp_Last; + Assert (Ticks = 20); + + Ifelse_T_Var_Not_Last; + Assert (Ticks = 23); + + Ifelse_T_Cmp_Not_Last; + Assert (Ticks = 26); +end; + +--# ifs.adb +-- /reach/ l+ ## 0 +-- /out/ l0 ## s0 +-- /test/ l+ ## 0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/test.py b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/test.py new file mode 100644 index 000000000..95ff64f52 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest + + +TestCase().run(covcontrol=CovControl(covoptions="--non-coverable")) +thistest.result() diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.adb b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.adb new file mode 100644 index 000000000..d401e1bd8 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.adb @@ -0,0 +1,50 @@ +with State; use State; + +-- # out is used to mark statements that we expect to be taken out always. +-- # opt_out is for statements taken out only when optimizing. + +package body Misc is + + -- A local library level subprogram just unused. + + procedure Dump_Old_Log; + + procedure Dump_Old_Log is + begin + Dtick; -- # opt_out + end; + + -- A local subprogram which only gets called in a section guarded by a + -- constant False test: + + procedure Dump_Debug_Log is + begin + Dtick; -- # opt_out + end; + + procedure Check_State is + + -- A nested subprogram just unused + + procedure Crash_Me is + begin + Dtick; -- # out + end; + + -- A nested subprogram called in a guarded false + -- sequence of statements + + procedure Maybe_Crash_Me is + begin + Dtick; -- # out + end; + + begin + Tick; -- # stmt + if GF then -- # out + Dump_Debug_Log; -- # out + Maybe_Crash_Me; -- # out + end if; + end; + +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.ads b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.ads new file mode 100644 index 000000000..06c42bdfc --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.ads @@ -0,0 +1,5 @@ +package Misc is + GF : constant Boolean := False; + + procedure Check_State; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/test_misc.adb b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/test_misc.adb new file mode 100644 index 000000000..28b2f737b --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/test_misc.adb @@ -0,0 +1,20 @@ +with Support, Misc, State; use Support, Misc; + +procedure Test_Misc is +begin + Check_State; + Assert (State.Ticks = 1); + Assert (State.Dticks = 0); +end; + +--# misc.adb +-- /stmt/ l+ ## 0 +-- /out/ l0 ## s0 + +-- %cargs: !-O1 +-- /opt_out/ l- ## s- + +-- %cargs: -O1 +-- /opt_out/ l0 ## s0 + + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/tc.rst b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/tc.rst new file mode 100644 index 000000000..6dbe56d4e --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/tc.rst @@ -0,0 +1,12 @@ +Exercise statements within eliminated subprograms + +Verify that statements within eliminated subprograms are reported +non-coverable on request. Check + +* private library level or local subprograms not called at all + +* private library level or local subprograms called only in a + conditional section guarded by a constant False test + + + diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/test.py b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/test.py new file mode 100644 index 000000000..95ff64f52 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest + + +TestCase().run(covcontrol=CovControl(covoptions="--non-coverable")) +thistest.result() diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/test_values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/test_values.adb new file mode 100644 index 000000000..57eeefa72 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/test_values.adb @@ -0,0 +1,13 @@ +with State, Support, Values; use State, Support, Values; + +procedure Test_Values is +begin + Assert (Abs_Of(5) = 5); + Assert (Abs_Of(-2) = 2); +end; + +--# values.adb +-- /stmt/ l+ ## 0 +-- /xpos/ l+ ## 0 +-- /neg/ l+ ## 0 +-- /out/ l0 ## s0 diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.adb new file mode 100644 index 000000000..daa959467 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.adb @@ -0,0 +1,19 @@ +with State; use State; + +package body Values is + + function Abs_Of (X : Integer) return Integer is + + begin + if X > 0 then -- # stmt + return X; -- # xpos + else + return -X; -- # xneg + end if; + + -- We always return prior to this point + + Dtick; -- # out + end; + +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.ads new file mode 100644 index 000000000..c0505b416 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.ads @@ -0,0 +1,6 @@ + +package Values is + + function Abs_Of (X : Integer) return Integer; + +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/test.py b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/test.py new file mode 100644 index 000000000..95ff64f52 --- /dev/null +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl +from SUITE.context import thistest + + +TestCase().run(covcontrol=CovControl(covoptions="--non-coverable")) +thistest.result() diff --git a/testsuite/tests/MB15-040-if-cst/src/monitor.adb b/testsuite/tests/MB15-040-if-cst/src/monitor.adb new file mode 100644 index 000000000..45554ed8b --- /dev/null +++ b/testsuite/tests/MB15-040-if-cst/src/monitor.adb @@ -0,0 +1,14 @@ + +package body Monitor is + + Moncalls : Natural := 0; + pragma Volatile (Moncalls); + + procedure Op is + begin + if Count_Ops then -- # called + Opcount := Opcount + 1; + end if; + Moncalls := Moncalls + 1; -- # called + end; +end; diff --git a/testsuite/tests/MB15-040-if-cst/src/monitor.ads b/testsuite/tests/MB15-040-if-cst/src/monitor.ads new file mode 100644 index 000000000..69619fddd --- /dev/null +++ b/testsuite/tests/MB15-040-if-cst/src/monitor.ads @@ -0,0 +1,7 @@ + +package Monitor is + Count_Ops : constant Boolean := False; + Opcount : Natural := 0; + + procedure Op; +end; diff --git a/testsuite/tests/MB15-040-if-cst/src/test_ifcst_call.adb b/testsuite/tests/MB15-040-if-cst/src/test_ifcst_call.adb new file mode 100644 index 000000000..1d849d342 --- /dev/null +++ b/testsuite/tests/MB15-040-if-cst/src/test_ifcst_call.adb @@ -0,0 +1,11 @@ +with Monitor; +procedure Test_Ifcst_Call is + X : Integer := 0; + pragma Volatile (X); +begin + X := X + 1; + Monitor.Op; +end; + +--# monitor.adb +-- /called/ l+ ## 0 diff --git a/testsuite/tests/MB15-040-if-cst/src/test_ifcst_none.adb b/testsuite/tests/MB15-040-if-cst/src/test_ifcst_none.adb new file mode 100644 index 000000000..34746842f --- /dev/null +++ b/testsuite/tests/MB15-040-if-cst/src/test_ifcst_none.adb @@ -0,0 +1,10 @@ +with Monitor; +procedure Test_Ifcst_None is + X : Integer := 0; + pragma Volatile (X); +begin + X := X + 1; +end; + +--# monitor.adb +-- /called/ l- ## s- diff --git a/testsuite/tests/MB15-040-if-cst/test.opt b/testsuite/tests/MB15-040-if-cst/test.opt new file mode 100644 index 000000000..1ab8d0b6c --- /dev/null +++ b/testsuite/tests/MB15-040-if-cst/test.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD constant conditions, compiler change on 2013-11-18, not in 7.0.3 +7.2.2 DEAD constant conditions, compiler change on 2013-11-18, not in 7.2.2 +src-traces XFAIL S628-012: src-traces and inhibited code +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/MB15-040-if-cst/test.py b/testsuite/tests/MB15-040-if-cst/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/MB15-040-if-cst/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/MB15-041-verbose-open-crc32/foo.adb b/testsuite/tests/MB15-041-verbose-open-crc32/foo.adb new file mode 100644 index 000000000..f7b0acefa --- /dev/null +++ b/testsuite/tests/MB15-041-verbose-open-crc32/foo.adb @@ -0,0 +1,4 @@ +procedure Foo is +begin + null; +end Foo; diff --git a/testsuite/tests/MB15-041-verbose-open-crc32/test.opt b/testsuite/tests/MB15-041-verbose-open-crc32/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/MB15-041-verbose-open-crc32/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/MB15-041-verbose-open-crc32/test.py b/testsuite/tests/MB15-041-verbose-open-crc32/test.py new file mode 100644 index 000000000..feefe57a9 --- /dev/null +++ b/testsuite/tests/MB15-041-verbose-open-crc32/test.py @@ -0,0 +1,112 @@ +from binascii import crc32 +import os.path +import re + +from e3.os.fs import unixpath + +from SUITE.cutils import Wdir, FatalError, lines_of +from SUITE.tutils import (exepath_to, gprbuild, gprfor, thistest, + tracename_for, xcov, xrun) + +tmp_ = Wdir('tmp_') + +GPR_FILE = gprfor('foo.adb', srcdirs='..') +EXE_FILE = exepath_to('foo') +TRACE_FILE = tracename_for('foo') +SCOS_FILES = [ + os.path.join('obj', 'foo.ali'), +] + +CWD_LINE_PREFIX = 'CWD = ' +LOG_OPEN_RE = re.compile( + r'--- notice: open "(?P[^"]+)"' + r' \(CRC32 = 0x(?P[0-9a-f]{8})\)' +) + + +def list_to_text(items): + return ''.join( + ' - {}\n'.format(item) + for item in items + ) or ' \n' + + +def check_same_files(expected, found): + expected = set(unixpath(path) for path in expected) + found = set(unixpath(path) for path in found) + thistest.fail_if( + expected != found, + 'Expecting:\n{}' + 'but found:\n{}'.format( + list_to_text(expected), list_to_text(found) + ) + ) + + +def check_logging(log_file, expected_files): + """ + Check that `log_file` contains correct checksums for all `expected_files`, + and only for them. + """ + # Rebase all input path to the temporary directory. + base = os.getcwd() + expected_files = set( + os.path.join(base, path) + for path in expected_files + ) + + checksums = {} + gnatcov_cwd = None + + # First, get GNATcov's CWD and all the CRC32 checksums from the verbose + # logging. + for line in lines_of(log_file): + if line.startswith(CWD_LINE_PREFIX): + gnatcov_cwd = line[len(CWD_LINE_PREFIX):].strip() + + else: + m = LOG_OPEN_RE.match(line) + if not m: + continue + + thistest.stop_if( + not gnatcov_cwd, + FatalError("Got a checksum before GNATcov's CWD") + ) + + filepath = os.path.join(gnatcov_cwd, m.group('file')) + checksums[filepath] = int(m.group('crc32'), 16) + + # Check that these checksums match the set of files. + check_same_files(expected_files, set(checksums.keys())) + + # Then check that each checksum is valid. + for filename, checksum in checksums.items(): + with open(filename, 'rb') as fp: + expected_checksum = crc32(fp.read()) & 0xffffffff + thistest.fail_if( + expected_checksum != checksum, + 'Bad checksum for {}: expecting CRC32={:#08x}, but found {:#08x}' + .format(filename, expected_checksum, checksum) + ) + + +# Build the project +gprbuild(GPR_FILE) + +# Produce some trace and check the verbose logging. +xrun( + ['--verbose', '--level=stmt+mcdc', '-P{}'.format(GPR_FILE), EXE_FILE], + out='xcov-run.log' +) +check_logging('xcov-run.log', [EXE_FILE] + SCOS_FILES) + +# Then compute the coverage report and check again the verbose logging. +xcov( + ['coverage', '--verbose', '--level=stmt+mcdc', '--annotate=report', + '-P{}'.format(GPR_FILE), TRACE_FILE], + out='xcov-coverage.log' +) +check_logging('xcov-coverage.log', [EXE_FILE, TRACE_FILE] + SCOS_FILES) + +thistest.result() diff --git a/testsuite/tests/MB19-016-subprogram-less-code/foo.c b/testsuite/tests/MB19-016-subprogram-less-code/foo.c new file mode 100644 index 000000000..398ec675a --- /dev/null +++ b/testsuite/tests/MB19-016-subprogram-less-code/foo.c @@ -0,0 +1,5 @@ +int +main (void) +{ + return 0; +} diff --git a/testsuite/tests/MB19-016-subprogram-less-code/test.opt b/testsuite/tests/MB19-016-subprogram-less-code/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/MB19-016-subprogram-less-code/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/MB19-016-subprogram-less-code/test.py b/testsuite/tests/MB19-016-subprogram-less-code/test.py new file mode 100644 index 000000000..cfb559151 --- /dev/null +++ b/testsuite/tests/MB19-016-subprogram-less-code/test.py @@ -0,0 +1,49 @@ +""" +Check that we can compute object coverage .xcov reports from +a binary which contains asm-level debug line info not attached +to any subprogram from the dwarf standpoint. +""" + +import os.path + +from e3.fs import rm + +from SUITE.cutils import Wdir +from SUITE.tutils import ( + exepath_to, gprbuild, gprfor, thistest, tracename_for, xcov, xrun +) + +rm('tmp_', recursive=True) +tmp_ = Wdir('tmp_') + +# We are producing object coverage reports and need fine control over the +# compilation options here +_cargs = {'scovcargs': False, + 'suitecargs': False} + +# First stage: compile the C source code to assembly. We want no debug +# information at this stage. +gpr_stage1 = gprfor( + 'foo.c', prjid='stage1', srcdirs='..', exedir='.', + main_cargs='-g0 -save-temps', langs=('C', )) +gprbuild(gpr_stage1, gargs='-c', **_cargs) + +# Second stage: assemble to object code with debug information relative to the +# assembly. +gpr_stage2 = gprfor( + 'foo.s', prjid='stage2', srcdirs='obj', exedir='.', + main_cargs='-g', langs=('Asm', )) +gprbuild(gpr_stage2, **_cargs) + +gnatcov_flags = ['-P', gpr_stage2, '--level=branch'] + +# Run and compute code coverage. +xrun(gnatcov_flags + [exepath_to('foo')]) +xcov(['coverage'] + gnatcov_flags + ['--annotate=xcov', tracename_for('foo')]) + +thistest.fail_if( + not os.path.exists(os.path.join('obj', 'foo.s.xcov')), + 'There is no XCOV report for foo.s' +) + +thistest.result() diff --git a/testsuite/tests/MC05-011-ref-executable/src/app.adb b/testsuite/tests/MC05-011-ref-executable/src/app.adb new file mode 100644 index 000000000..e2a65643e --- /dev/null +++ b/testsuite/tests/MC05-011-ref-executable/src/app.adb @@ -0,0 +1,6 @@ +with Assert, Double, Bump; + +procedure App is +begin + null; +end; diff --git a/testsuite/tests/MC05-011-ref-executable/src/assert.adb b/testsuite/tests/MC05-011-ref-executable/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/MC05-011-ref-executable/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/MC05-011-ref-executable/src/bump.adb b/testsuite/tests/MC05-011-ref-executable/src/bump.adb new file mode 100644 index 000000000..48e8439eb --- /dev/null +++ b/testsuite/tests/MC05-011-ref-executable/src/bump.adb @@ -0,0 +1,4 @@ +procedure Bump (X : in out Integer) is +begin + X := X + 1; +end; diff --git a/testsuite/tests/MC05-011-ref-executable/src/double.adb b/testsuite/tests/MC05-011-ref-executable/src/double.adb new file mode 100644 index 000000000..24520d5d0 --- /dev/null +++ b/testsuite/tests/MC05-011-ref-executable/src/double.adb @@ -0,0 +1,5 @@ +procedure Double (X : in out Integer) is +begin + X := X * 2; +end; + diff --git a/testsuite/tests/MC05-011-ref-executable/src/test_bump.adb b/testsuite/tests/MC05-011-ref-executable/src/test_bump.adb new file mode 100644 index 000000000..0940bcec8 --- /dev/null +++ b/testsuite/tests/MC05-011-ref-executable/src/test_bump.adb @@ -0,0 +1,8 @@ +with Assert, Bump; + +procedure Test_Bump is + X : Integer := 12; +begin + Bump (X); + Assert (X = 13); +end; diff --git a/testsuite/tests/MC05-011-ref-executable/test.py b/testsuite/tests/MC05-011-ref-executable/test.py new file mode 100644 index 000000000..7d4284c2b --- /dev/null +++ b/testsuite/tests/MC05-011-ref-executable/test.py @@ -0,0 +1,46 @@ +""" +Check that statements from a unit entirely untested are reported uncovered +regardless of the visibility on the unit object code in the analysis scope. +""" + +import re + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import exepath_to, gprfor, xcov + + +Wdir('tmp_') + + +# Build App which encloses two units (bump and double), and a unit test for +# just the bump unit. Then run the unit test. +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(srcdirs=['../src'], + mains=['test_bump.adb', 'app.adb'])), + covlevel='stmt', + mains=['test_bump'], + extra_coverage_args=['--annotate=report'], + scos=['obj/bump', 'obj/double']) + + +# Do stmt coverage analysis providing scos for all the units and the unit test +# trace. Check that we have diagnostics of absence of coverage on the elements +# part of the untested unit with or without an additional --exec. + +def trycov(exec_args): + p = xcov(xcov_args + exec_args) + thistest.fail_if( + not re.search(r'double.adb:\d+:\d+: statement not executed', p.out), + 'Missing stmt violation on double.adb, exec_args: %s' % str(exec_args)) + + +trycov(exec_args=[]) + +# --exec does not make sense (and is not allowed) in source trace mode +if thistest.options.trace_mode == "bin": + trycov(exec_args=['--exec=%s' % exepath_to('app')]) + +thistest.result() diff --git a/testsuite/tests/N106-020-tempfiles/src/actions.adb b/testsuite/tests/N106-020-tempfiles/src/actions.adb new file mode 100644 index 000000000..a46fcebc7 --- /dev/null +++ b/testsuite/tests/N106-020-tempfiles/src/actions.adb @@ -0,0 +1,33 @@ +package body Actions is + + Value : Integer := 0; + pragma Volatile (Value); + + procedure Process_Positive (X : Integer) is + begin + if X <= 0 then -- # test_pos + raise Constraint_Error; -- # unreach_pos + end if; + Value := Value + X; -- # do_pos + end; + + procedure Process_Negative (X : Integer) is + begin + if X >= 0 then -- # test_neg + raise Constraint_Error; -- # unreach_neg + end if; + Value := Value + X; -- # do_neg + end; + + procedure Process_Zero (X : Integer) is + begin + if X /= 0 then -- # test_zero + raise Constraint_Error; -- # unreach_zero + end if; + end; + + procedure Process (X : Integer; Action : Action_Access) is + begin + Action.all (X); + end; +end; diff --git a/testsuite/tests/N106-020-tempfiles/src/actions.ads b/testsuite/tests/N106-020-tempfiles/src/actions.ads new file mode 100644 index 000000000..6658199cf --- /dev/null +++ b/testsuite/tests/N106-020-tempfiles/src/actions.ads @@ -0,0 +1,12 @@ +package Actions is + + type Action_Access is access procedure (X : Integer); + + procedure Process_Positive (X : Integer); + procedure Process_Negative (X : Integer); + procedure Process_Zero (X : Integer); + + procedure Process (X : Integer; Action : Action_Access); + +end; + diff --git a/testsuite/tests/N106-020-tempfiles/src/test_tags.adb b/testsuite/tests/N106-020-tempfiles/src/test_tags.adb new file mode 100644 index 000000000..4500ca655 --- /dev/null +++ b/testsuite/tests/N106-020-tempfiles/src/test_tags.adb @@ -0,0 +1,29 @@ +with Actions; use Actions; + +-- Basic test for the %tags support in expectations, allowing +-- conditional sections of expectation statements depending on +-- the testsuite discriminants. + +procedure Test_Tags is +begin + Process (5, Process_Positive'Access); + Process (-5, Process_Negative'Access); + Process (0, Process_Zero'Access); +end; + +-- ALL is expected to always be part of the suite discriminants +-- NEVER is expected never to be there + +--# actions.adb + +-- %tags: ALL +-- /unreach_pos/ l- ## s- + +-- %tags: !NEVER +-- /unreach_neg/ l- ## s- + +-- %tags: ALL, !NEVER +-- /unreach_zero/ l- ## s- + +-- %tags: NEVER +-- /check/ l- ## s- diff --git a/testsuite/tests/N106-020-tempfiles/test.py b/testsuite/tests/N106-020-tempfiles/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/N106-020-tempfiles/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/N107-020-dhtml/foo.adb b/testsuite/tests/N107-020-dhtml/foo.adb new file mode 100644 index 000000000..ca4ad6568 --- /dev/null +++ b/testsuite/tests/N107-020-dhtml/foo.adb @@ -0,0 +1,14 @@ +procedure Foo is + function Fact (N : Natural) return Natural is + begin + if N <= 1 then + return 1; + else + return N * Fact (N - 1); + end if; + end Fact; +begin + if Fact (6) /= 720 then + raise Program_Error; + end if; +end Foo; diff --git a/testsuite/tests/N107-020-dhtml/test.py b/testsuite/tests/N107-020-dhtml/test.py new file mode 100644 index 000000000..cea0e585a --- /dev/null +++ b/testsuite/tests/N107-020-dhtml/test.py @@ -0,0 +1,42 @@ +""" +Check that --annotate=dthml succeeds and produces something, with a project +file or without. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +def check(label, scos): + """ + Check that --annotate=dhtml produces something, using -P or --scos. + """ + wd = Wdir(subdir=f"tmp_{label}") + + build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=['foo.adb'], + srcdirs=['..'])), + covlevel="stmt", + mains=["foo"], + extra_coverage_args=["--annotate=dhtml", "--output-dir=dhtml-report"], + scos=scos, + ) + + index = os.path.join("dhtml-report", 'index.html') + thistest.fail_if( + not os.path.isfile(index) or os.path.getsize(index) == 0, + f"missing or empty {index} for {label}" + ) + + wd.to_homedir() + + +check("scos", scos=["obj/foo"]) +check("prj", scos=None) + +thistest.result() diff --git a/testsuite/tests/N107-029-crc32-validity/foo.adb b/testsuite/tests/N107-029-crc32-validity/foo.adb new file mode 100644 index 000000000..ca4ad6568 --- /dev/null +++ b/testsuite/tests/N107-029-crc32-validity/foo.adb @@ -0,0 +1,14 @@ +procedure Foo is + function Fact (N : Natural) return Natural is + begin + if N <= 1 then + return 1; + else + return N * Fact (N - 1); + end if; + end Fact; +begin + if Fact (6) /= 720 then + raise Program_Error; + end if; +end Foo; diff --git a/testsuite/tests/N107-029-crc32-validity/test.opt b/testsuite/tests/N107-029-crc32-validity/test.opt new file mode 100644 index 000000000..2aeb03b2c --- /dev/null +++ b/testsuite/tests/N107-029-crc32-validity/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/N107-029-crc32-validity/test.py b/testsuite/tests/N107-029-crc32-validity/test.py new file mode 100644 index 000000000..89be86fab --- /dev/null +++ b/testsuite/tests/N107-029-crc32-validity/test.py @@ -0,0 +1,57 @@ +""" +This test sanity checks that the CRC32 value computed by gnatcov for the +executable file for an example program, stored in excution trace headers, +matches the CRC32 value computed by a reference implementation on the same +executable. The Python library is used as the reference implementation. +""" + +import binascii + +from SUITE.context import thistest +from SUITE.cutils import lines_of, Wdir +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +# Work in a subdirectory +wd = Wdir(subdir='tmp_') + +# Generate the program executable, then run it to get an execution trace: +gpr = gprfor(mains=['foo.adb'], srcdirs=['..']) +gprbuild(project=gpr) + +program_path = exepath_to('foo') +trace_name = tracename_for('foo') + +xrun(program_path) + +# Fetch the CRC32 value computed by gnatcov and stored in the trace header as: +# +# Tag : EXEC_FILE_CRC32 +# Data : +xcov(['dump-trace', trace_name], out='trace.dump') +trace_dump = [line.strip() for line in lines_of('trace.dump')] + +tag_line_no = trace_dump.index('Tag : EXEC_FILE_CRC32') +data_line = trace_dump[tag_line_no + 2] + +# Get the decimal checksum +prefix = 'Data : ' +thistest.stop_if( + not data_line.startswith(prefix), + ValueError('Invalid trace text dump (invalid "Data" line): {!r}' + .format(data_line)) +) +gnatcov_checksum = int(data_line[len(prefix):]) + +# And then compare it with the one Python computes +with open(program_path, 'rb') as f: + # binascii.crc32 returns a signed 32-bit integer. Make it unsigned to be + # consistent with GNATcoverage. + expected_checksum = binascii.crc32(f.read()) & 0xffffffff +thistest.stop_if( + gnatcov_checksum != expected_checksum, + ValueError('CRC32 mismatch: {} (expected) != {} (got)' + .format(expected_checksum, gnatcov_checksum))) + +thistest.result() diff --git a/testsuite/tests/N129-008-c-constant-conditions/src/foo.c b/testsuite/tests/N129-008-c-constant-conditions/src/foo.c new file mode 100644 index 000000000..2d9e9cddb --- /dev/null +++ b/testsuite/tests/N129-008-c-constant-conditions/src/foo.c @@ -0,0 +1,10 @@ +#include "foo.h" + +int +foo (int a, int b) +{ + if (((long int) (sizeof (long long))) < 0) // # cond-expr + return a; // # cond-true + else + return b; // # cond-false +} diff --git a/testsuite/tests/N129-008-c-constant-conditions/src/foo.h b/testsuite/tests/N129-008-c-constant-conditions/src/foo.h new file mode 100644 index 000000000..8f101cdc7 --- /dev/null +++ b/testsuite/tests/N129-008-c-constant-conditions/src/foo.h @@ -0,0 +1,6 @@ +#ifndef FOO_H +#define FOO_H + +extern int foo (int a, int b); + +#endif diff --git a/testsuite/tests/N129-008-c-constant-conditions/src/test_foo.c b/testsuite/tests/N129-008-c-constant-conditions/src/test_foo.c new file mode 100644 index 000000000..e68af6451 --- /dev/null +++ b/testsuite/tests/N129-008-c-constant-conditions/src/test_foo.c @@ -0,0 +1,31 @@ +#include "foo.h" + +int +main (void) +{ + foo (1, 2); + return 0; +} + +//# foo.c + +// For binary traces, as the if condition is constant, the then part will +// be no code, and there won't be a decision obligation. + +//%opts: --trace-mode=bin +// /cond-expr/ l+ ## 0 +// /cond-true/ l. ## 0 +// /cond-false/ l+ ## 0 + +//%opts: --trace-mode=src +// /cond-true/ l- ## s- +// /cond-false/ l+ ## 0 + +//%cov: --level=stmt %opts: --trace-mode=src +// =/cond-expr/ l+ ## 0 + +//%cov: --level=stmt\+decision %opts: --trace-mode=src +// =/cond-expr/ l! ## dT- + +//%cov: --level=stmt\+(uc_)?mcdc %opts: --trace-mode=src +// =/cond-expr/ l! ## dT- diff --git a/testsuite/tests/N129-008-c-constant-conditions/test.opt b/testsuite/tests/N129-008-c-constant-conditions/test.opt new file mode 100644 index 000000000..a00b47c87 --- /dev/null +++ b/testsuite/tests/N129-008-c-constant-conditions/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD test relies on a compiler change introduced on 2014-01, not in 7.0.3 +7.2.2 DEAD test relies on a compiler change introduced on 2014-01, not in 7.2.2 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N129-008-c-constant-conditions/test.py b/testsuite/tests/N129-008-c-constant-conditions/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/N129-008-c-constant-conditions/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/N203-040-same-c-basename/src/a/foo.h b/testsuite/tests/N203-040-same-c-basename/src/a/foo.h new file mode 100644 index 000000000..22cefa132 --- /dev/null +++ b/testsuite/tests/N203-040-same-c-basename/src/a/foo.h @@ -0,0 +1,8 @@ +static int +foo (int a) +{ + if (a) // # toplev-stmt + return a + 1; // # toplev-true + else + return a - 1; // # toplev-false +} diff --git a/testsuite/tests/N203-040-same-c-basename/src/b/foo.h b/testsuite/tests/N203-040-same-c-basename/src/b/foo.h new file mode 100644 index 000000000..2f225bf99 --- /dev/null +++ b/testsuite/tests/N203-040-same-c-basename/src/b/foo.h @@ -0,0 +1,8 @@ +static int +other_foo (int a) +{ + if (a) // # other-stmt + return 2 * a; // # other-true + else + return a / 2; // # other-false +} diff --git a/testsuite/tests/N203-040-same-c-basename/src/test_foo.c b/testsuite/tests/N203-040-same-c-basename/src/test_foo.c new file mode 100644 index 000000000..7a1d12ce3 --- /dev/null +++ b/testsuite/tests/N203-040-same-c-basename/src/test_foo.c @@ -0,0 +1,24 @@ +#include "a/foo.h" +#include "b/foo.h" + +int +main (void) +{ + volatile int a = 1; // # dummy + a = foo (a) * other_foo (a); // # dummy + + return 0; // # dummy +} + +//# test_foo.c +// /dummy/ l+ ## 0 + +//# +a/foo.h +// /toplev-stmt/ l+ ## 0 +// /toplev-true/ l+ ## 0 +// /toplev-false/ l- ## s- + +//# +b/foo.h +// /other-stmt/ l+ ## 0 +// /other-true/ l+ ## 0 +// /other-false/ l- ## s- diff --git a/testsuite/tests/N203-040-same-c-basename/test.opt b/testsuite/tests/N203-040-same-c-basename/test.opt new file mode 100644 index 000000000..a49fdb1c9 --- /dev/null +++ b/testsuite/tests/N203-040-same-c-basename/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD 7.0.3 misses proper SCO support for C +!bin-traces DEAD Coverage for C supported only with binary traces +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N203-040-same-c-basename/test.py b/testsuite/tests/N203-040-same-c-basename/test.py new file mode 100644 index 000000000..47cf95048 --- /dev/null +++ b/testsuite/tests/N203-040-same-c-basename/test.py @@ -0,0 +1,54 @@ +""" +Test that there is no issue with C sources that have the same basename. +""" + +import os.path + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +# This must work for source coverage... +TestCase(category=CAT.stmt).run() + +# ... and for object coverage, too! +tmp_ = Wdir('tmp_') + +gprfile = gprfor('test_foo.c', srcdirs=os.path.join('..', 'src')) +exefile = exepath_to('test_foo') +tracefile = tracename_for('test_foo') +logfile = 'xcov-coverage.log' + +routinesfile = 'routines.list' +with open(routinesfile, 'w') as f: + for symbol in ('main', 'foo', 'other_foo'): + f.write('{}\n'.format(symbol)) + +gprbuild(gprfile) +xrun(exefile) + +# If this test fail, we expect this is because the following command will emit +# warnings about various source files having the same base name. +xcov( + [ + 'coverage', + '-P{}'.format(gprfile), + '--level=insn', '--annotate=xcov', + '--routines=@{}'.format(routinesfile), + tracefile + ], + out=logfile +) + +thistest.fail_if( + os.path.getsize(logfile) > 0, + 'xcov standard output not empty ({}):\n--\n{}'.format( + logfile, contents_of(logfile) + ) +) + +thistest.result() diff --git a/testsuite/tests/N204-011-precond-aspects/src/foo.adb b/testsuite/tests/N204-011-precond-aspects/src/foo.adb new file mode 100644 index 000000000..3c1a66d82 --- /dev/null +++ b/testsuite/tests/N204-011-precond-aspects/src/foo.adb @@ -0,0 +1,8 @@ +package body Foo is + + function Bar (L, R : Integer) return Integer is + begin + return L - R; + end Bar; + +end Foo; diff --git a/testsuite/tests/N204-011-precond-aspects/src/foo.ads b/testsuite/tests/N204-011-precond-aspects/src/foo.ads new file mode 100644 index 000000000..c2012b4c0 --- /dev/null +++ b/testsuite/tests/N204-011-precond-aspects/src/foo.ads @@ -0,0 +1,11 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Foo is + + function Bar (L, R : Integer) return Integer + with Pre => + L > 100 -- # decision-1 + and then R < 100; -- # decision-2 + +end Foo; diff --git a/testsuite/tests/N204-011-precond-aspects/src/log.adb b/testsuite/tests/N204-011-precond-aspects/src/log.adb new file mode 100644 index 000000000..082ac3f1c --- /dev/null +++ b/testsuite/tests/N204-011-precond-aspects/src/log.adb @@ -0,0 +1,5 @@ +procedure Log (I : Integer) is + pragma Unreferenced (I); +begin + null; +end; diff --git a/testsuite/tests/N204-011-precond-aspects/src/test_foo.adb b/testsuite/tests/N204-011-precond-aspects/src/test_foo.adb new file mode 100644 index 000000000..e16d1f46f --- /dev/null +++ b/testsuite/tests/N204-011-precond-aspects/src/test_foo.adb @@ -0,0 +1,12 @@ +with Foo; +with Log; + +procedure Test_Foo is + +begin + Log (Foo.Bar (110, 70)); +end Test_Foo; + +--# foo.ads +-- =/decision-1/ l! ## dF- +-- =/decision-2/ l- ## 0 diff --git a/testsuite/tests/N204-011-precond-aspects/test.opt b/testsuite/tests/N204-011-precond-aspects/test.opt new file mode 100644 index 000000000..925ef8d60 --- /dev/null +++ b/testsuite/tests/N204-011-precond-aspects/test.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD relies on compiler support for 2012 Aspects, not all in 7.0.3 +7.2.2 DEAD relies on compiler support for 2012 Aspects, not all in 7.2.2 +src-traces XFAIL S606-037: src-traces and contracts +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N204-011-precond-aspects/test.py b/testsuite/tests/N204-011-precond-aspects/test.py new file mode 100644 index 000000000..5c679f78e --- /dev/null +++ b/testsuite/tests/N204-011-precond-aspects/test.py @@ -0,0 +1,11 @@ +""" +Test that there is no static analysis issue with Pre aspects (preconditions). +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/N321-039-disas-wrapping/foo.s b/testsuite/tests/N321-039-disas-wrapping/foo.s new file mode 100644 index 000000000..910228d0b --- /dev/null +++ b/testsuite/tests/N321-039-disas-wrapping/foo.s @@ -0,0 +1,6 @@ +.text +.globl _start +.type _start, @function +_start: + nop +.size _start, .-_start diff --git a/testsuite/tests/N321-039-disas-wrapping/test.opt b/testsuite/tests/N321-039-disas-wrapping/test.opt new file mode 100644 index 000000000..9feabe86d --- /dev/null +++ b/testsuite/tests/N321-039-disas-wrapping/test.opt @@ -0,0 +1,3 @@ +x86-linux,bin-traces +x86_64-linux,bin-traces +ALL DEAD diff --git a/testsuite/tests/N321-039-disas-wrapping/test.py b/testsuite/tests/N321-039-disas-wrapping/test.py new file mode 100644 index 000000000..9fbd7b823 --- /dev/null +++ b/testsuite/tests/N321-039-disas-wrapping/test.py @@ -0,0 +1,38 @@ +""" +Check that the 'dump-cfg' and 'disassemble-insn-properties' subcommands handle +well instructions at the end of the address space. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, gprbuild, xcov + +tmp_ = Wdir('tmp_') + +# We want to link the code at the end of the address space, so get the correct +# upper address depending on the architecture. + +address = ( + 2**32 - 1 + if '32bits' in thistest.options.tags else + 2**64 - 1 +) + +gprfile = gprfor( + ['foo.s'], + srcdirs="..", + langs=('Asm'), + extra=''' + package Linker is + for Default_Switches ("Asm") use ("-nostdlib", "-Ttext={}"); + end Linker; +'''.format(address)) +exefile = 'foo' + +gprbuild(gprfile) + +for subcmd in ('dump-cfg', 'disassemble-insn-properties'): + # As long as GNATcov do not crash/hangs, everything is fine! + xcov([subcmd, exefile, '_start']) + +thistest.result() diff --git a/testsuite/tests/N321-045-ppc-disas-large-input/foo.adb b/testsuite/tests/N321-045-ppc-disas-large-input/foo.adb new file mode 100644 index 000000000..b14199355 --- /dev/null +++ b/testsuite/tests/N321-045-ppc-disas-large-input/foo.adb @@ -0,0 +1,14 @@ +procedure Foo is + function Fact (I : Integer) return Integer is + begin + if I <= 1 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; +begin + if Fact (6) /= 0 then + raise Program_Error; + end if; +end Foo; diff --git a/testsuite/tests/N321-045-ppc-disas-large-input/test.opt b/testsuite/tests/N321-045-ppc-disas-large-input/test.opt new file mode 100644 index 000000000..15a456bdc --- /dev/null +++ b/testsuite/tests/N321-045-ppc-disas-large-input/test.opt @@ -0,0 +1,2 @@ +ppc-elf +ALL DEAD diff --git a/testsuite/tests/N321-045-ppc-disas-large-input/test.py b/testsuite/tests/N321-045-ppc-disas-large-input/test.py new file mode 100644 index 000000000..dc329e6f3 --- /dev/null +++ b/testsuite/tests/N321-045-ppc-disas-large-input/test.py @@ -0,0 +1,18 @@ +""" +Check that the PPC disassembler (the Disassemble_Insn procedure) handles well +input that is larger than a single instruction. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, gprbuild, xcov + +tmp_ = Wdir('tmp_') + +gprfile = gprfor(['foo.adb'], srcdirs="..") +gprbuild(gprfile) + +# As long as GNATcov do not crash/hangs, everything is fine! +xcov(['disassemble-insn-properties', 'foo', '_ada_foo']) + +thistest.result() diff --git a/testsuite/tests/N411-046-asm-consolidation/p-default.s b/testsuite/tests/N411-046-asm-consolidation/p-default.s new file mode 100644 index 000000000..731b897b9 --- /dev/null +++ b/testsuite/tests/N411-046-asm-consolidation/p-default.s @@ -0,0 +1,8 @@ + .text + .align 2 + .globl p + .type p, @function +p: + ret + + .size p, .-p diff --git a/testsuite/tests/N411-046-asm-consolidation/p-win32.s b/testsuite/tests/N411-046-asm-consolidation/p-win32.s new file mode 100644 index 000000000..c76b463b5 --- /dev/null +++ b/testsuite/tests/N411-046-asm-consolidation/p-win32.s @@ -0,0 +1,11 @@ + .text + .align 2 + .globl _p + .def _p; .scl 2; .type 32; .endef +_p: + ret + + .globl _dummy + .def _dummy; .scl 2; .type 32; .endef +_dummy: + ret diff --git a/testsuite/tests/N411-046-asm-consolidation/p-win64.s b/testsuite/tests/N411-046-asm-consolidation/p-win64.s new file mode 100644 index 000000000..b9d2cdf38 --- /dev/null +++ b/testsuite/tests/N411-046-asm-consolidation/p-win64.s @@ -0,0 +1,11 @@ + .text + .align 2 + .globl p + .def p; .scl 2; .type 32; .endef +p: + ret + + .globl dummy + .def dummy; .scl 2; .type 32; .endef +dummy: + ret diff --git a/testsuite/tests/N411-046-asm-consolidation/test.c b/testsuite/tests/N411-046-asm-consolidation/test.c new file mode 100644 index 000000000..82a82bc31 --- /dev/null +++ b/testsuite/tests/N411-046-asm-consolidation/test.c @@ -0,0 +1,8 @@ +extern void p (void); + +int +main (void) +{ + p (); + return 0; +} diff --git a/testsuite/tests/N411-046-asm-consolidation/test.opt b/testsuite/tests/N411-046-asm-consolidation/test.opt new file mode 100644 index 000000000..f07cdbf24 --- /dev/null +++ b/testsuite/tests/N411-046-asm-consolidation/test.opt @@ -0,0 +1,4 @@ +-- Binary traces specific testcase +bin-traces,x86 +bin-traces,x86_64 +ALL DEAD Embeds x86* assembly sources diff --git a/testsuite/tests/N411-046-asm-consolidation/test.py b/testsuite/tests/N411-046-asm-consolidation/test.py new file mode 100644 index 000000000..b81df1f93 --- /dev/null +++ b/testsuite/tests/N411-046-asm-consolidation/test.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- + +""" +Check that if GNATcov is provided twice the same trace file, it consolidates as +expected an assembly-defined procedure assembled with -g (it has a compile +unit DIE, but no subprogram DIE in the DWARF info). +""" + +import os.path +import shutil + +from OCOV.tc import TestCase +from SUITE.context import env, thistest +from SUITE.cutils import Wdir +from SUITE.tutils import tracename_for + +test_drivers = { + 'test': {'p.s': ['-g']}, +} + +coverage_expectations = { + # There is only one "p" routine and we should consolidate them: we expect + # only one "+" covered "p" routine. + 'p': {'-': 0, '!': 0, '+': 1}, +} + +tmp = Wdir('tmp_') + +shutil.copy(os.path.join('..', 'test.c'), 'test.c') + +# Select an assembly source that fits the build platform +variant = 'default' +if env.build.os.name == 'windows': + variant = 'win32' if env.build.cpu.bits == 32 else 'win64' +shutil.copy(os.path.join('..', 'p-{}.s'.format(variant)), 'p.s') + +TestCase(test_drivers, coverage_expectations, + extra_xcov_args=[tracename_for('test')]).run() +thistest.result() diff --git a/testsuite/tests/N423-015-exempt-in-separate/src/assert.adb b/testsuite/tests/N423-015-exempt-in-separate/src/assert.adb new file mode 100644 index 000000000..db46a01f7 --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/src/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (T : Boolean) is +begin + if not T then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/N423-015-exempt-in-separate/src/pck-check.adb b/testsuite/tests/N423-015-exempt-in-separate/src/pck-check.adb new file mode 100644 index 000000000..1b90a70d2 --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/src/pck-check.adb @@ -0,0 +1,12 @@ + +separate (Pck) +procedure Check (Valid : Boolean) is +begin + if Valid then + Valids := Valids + 1; -- # valids + else + pragma Annotate (Xcov, Exempt_On, "Invalids unexpected"); -- # invalids + Invalids := Invalids + 1; -- # invalids_inc + pragma Annotate (Xcov, Exempt_Off); -- # invalids + end if; +end; diff --git a/testsuite/tests/N423-015-exempt-in-separate/src/pck.adb b/testsuite/tests/N423-015-exempt-in-separate/src/pck.adb new file mode 100644 index 000000000..9c1d9baac --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/src/pck.adb @@ -0,0 +1,3 @@ +package body Pck is + procedure Check (Valid : Boolean) is separate; +end Pck; diff --git a/testsuite/tests/N423-015-exempt-in-separate/src/pck.ads b/testsuite/tests/N423-015-exempt-in-separate/src/pck.ads new file mode 100644 index 000000000..8fd9a0a99 --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/src/pck.ads @@ -0,0 +1,4 @@ +package Pck is + procedure Check (Valid : Boolean); + Valids, Invalids : Natural := 0; +end Pck; diff --git a/testsuite/tests/N423-015-exempt-in-separate/src/test_i.adb b/testsuite/tests/N423-015-exempt-in-separate/src/test_i.adb new file mode 100644 index 000000000..b1659d4ff --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/src/test_i.adb @@ -0,0 +1,14 @@ +with Pck, Assert; + +procedure Test_I is +begin + Pck.Check (Valid => False); + Assert (Pck.Valids = 0); + Assert (Pck.Invalids = 1); +end; + +--# pck.adb + +--# pck-check.adb +-- /valids/ l- ## s- +-- /invalids/ l# ## x0 diff --git a/testsuite/tests/N423-015-exempt-in-separate/src/test_v.adb b/testsuite/tests/N423-015-exempt-in-separate/src/test_v.adb new file mode 100644 index 000000000..280e84bf9 --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/src/test_v.adb @@ -0,0 +1,15 @@ +with Pck, Assert; + +procedure Test_V is +begin + Pck.Check (Valid => True); + Assert (Pck.Valids = 1); + Assert (Pck.Invalids = 0); +end; + +--# pck.adb + +--# pck-check.adb +-- /valids/ l+ ## 0 +-- /invalids/ l* ## x+ +-- /invalids_inc/ l= ## Xs- diff --git a/testsuite/tests/N423-015-exempt-in-separate/test.opt b/testsuite/tests/N423-015-exempt-in-separate/test.opt new file mode 100644 index 000000000..fb7c5a771 --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD ticket exposed a compiler issue fixed on 2014-04, not in 7.0.3 +7.2.2 DEAD ticket exposed a compiler issue fixed on 2014-04, not in 7.2.2 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N423-015-exempt-in-separate/test.py b/testsuite/tests/N423-015-exempt-in-separate/test.py new file mode 100644 index 000000000..11e55638b --- /dev/null +++ b/testsuite/tests/N423-015-exempt-in-separate/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/N429-018-c-assert/ToMultiStmts/src/test_assert.c b/testsuite/tests/N429-018-c-assert/ToMultiStmts/src/test_assert.c new file mode 100644 index 000000000..9ceab8ba5 --- /dev/null +++ b/testsuite/tests/N429-018-c-assert/ToMultiStmts/src/test_assert.c @@ -0,0 +1,16 @@ +#include + +int +main (int argc, char *argv[]) +{ + volatile int a = 0; // # stmt-simple + assert (a == 0); // # stmt-assert + return 0; // # stmt-simple +} + +//# test_assert.c +// /stmt-simple/ l+ ## 0 +// /stmt-assert/ l! ## s- +// On GNU/Linux, "assert" is usually implemented as a macro which, after +// expansion, yields multiple statements. Given the current state of the +// technology, one of them is expected not to be covered. See NB17-025. diff --git a/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.opt b/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.opt new file mode 100644 index 000000000..5954ef81d --- /dev/null +++ b/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.opt @@ -0,0 +1,3 @@ +!native DEAD Test relies on host standard header files +!bin-traces DEAD Coverage for C supported only with binary traces +windows DEAD This test variant has platform-specific expectations diff --git a/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.py b/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.py new file mode 100644 index 000000000..dbe2d1f1e --- /dev/null +++ b/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.py @@ -0,0 +1,11 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase( + # Note that when C support for GNATcoverage will be ready, this flag + # should be automatically enabled with -fdump-scos. + extracargs='-no-integrated-cpp', + category=CAT.stmt +).run() +thistest.result() diff --git a/testsuite/tests/N429-018-c-assert/ToSingleStmt/src/test_assert.c b/testsuite/tests/N429-018-c-assert/ToSingleStmt/src/test_assert.c new file mode 100644 index 000000000..7d4111e0d --- /dev/null +++ b/testsuite/tests/N429-018-c-assert/ToSingleStmt/src/test_assert.c @@ -0,0 +1,15 @@ +#include + +int +main (int argc, char *argv[]) +{ + volatile int a = 0; // # stmt-simple + assert (a == 0); // # stmt-assert + return 0; // # stmt-simple +} + +//# test_assert.c +// /stmt-simple/ l+ ## 0 +// /stmt-assert/ l+ ## 0 +// On Windows, "assert" is usually implemented as a macro which, after +// expansion, yields a single statement. diff --git a/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.opt b/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.opt new file mode 100644 index 000000000..91ba4f86e --- /dev/null +++ b/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.opt @@ -0,0 +1,2 @@ +!native DEAD Test relies on host standard header files +!windows DEAD This test variant has platform-specific expectations diff --git a/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.py b/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.py new file mode 100644 index 000000000..dbe2d1f1e --- /dev/null +++ b/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.py @@ -0,0 +1,11 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase( + # Note that when C support for GNATcoverage will be ready, this flag + # should be automatically enabled with -fdump-scos. + extracargs='-no-integrated-cpp', + category=CAT.stmt +).run() +thistest.result() diff --git a/testsuite/tests/N429-018-c-tern-folding/src/foo.c b/testsuite/tests/N429-018-c-tern-folding/src/foo.c new file mode 100644 index 000000000..624a59003 --- /dev/null +++ b/testsuite/tests/N429-018-c-tern-folding/src/foo.c @@ -0,0 +1,11 @@ +#include "foo.h" + +int +foo (int a, int b) +{ + /* Currently, the following expression is folded by GCC's C frontend into: + !(a == 0) || (b == 0) + Because of this, SCOs won't match sources and thus reported violations + will not be the expected ones. */ + return (a == 0) ? (b == 0) : 1; // # decision +} diff --git a/testsuite/tests/N429-018-c-tern-folding/src/foo.h b/testsuite/tests/N429-018-c-tern-folding/src/foo.h new file mode 100644 index 000000000..8f101cdc7 --- /dev/null +++ b/testsuite/tests/N429-018-c-tern-folding/src/foo.h @@ -0,0 +1,6 @@ +#ifndef FOO_H +#define FOO_H + +extern int foo (int a, int b); + +#endif diff --git a/testsuite/tests/N429-018-c-tern-folding/src/test_foo_ft.c b/testsuite/tests/N429-018-c-tern-folding/src/test_foo_ft.c new file mode 100644 index 000000000..7dcd99fe6 --- /dev/null +++ b/testsuite/tests/N429-018-c-tern-folding/src/test_foo_ft.c @@ -0,0 +1,17 @@ +#include "foo.h" + +int +main (int argc, char *argv[]) +{ + foo (0, 0); + foo (1, 0); + return 0; +} + +//# foo.c +//%cov: --level=stmt +// =/decision/ l+ ## 0 +//%cov: --level=stmt\+decision +// =/decision/ l+ ## 0 +//%cov: --level=stmt\+(uc_)?mcdc +// =/decision/ l+ ## 0 diff --git a/testsuite/tests/N429-018-c-tern-folding/src/test_foo_t.c b/testsuite/tests/N429-018-c-tern-folding/src/test_foo_t.c new file mode 100644 index 000000000..0f0886342 --- /dev/null +++ b/testsuite/tests/N429-018-c-tern-folding/src/test_foo_t.c @@ -0,0 +1,20 @@ +#include "foo.h" + +int +main (int argc, char *argv[]) +{ + foo (0, 0); + return 0; +} + +//# foo.c +//%cov: --level=stmt +// =/decision/ l+ ## 0 +//%cov: --level=stmt\+decision %opts: --trace-mode=bin +// =/decision/ l! ## d! +//%cov: --level=stmt\+decision %opts: --trace-mode=src +// =/decision/ l! ## dF- +//%cov: --level=stmt\+(uc_)?mcdc %opts: --trace-mode=bin +// =/decision/ l! ## d! +//%cov: --level=stmt\+(uc_)?mcdc %opts: --trace-mode=src +// =/decision/ l! ## dF- diff --git a/testsuite/tests/N429-018-c-tern-folding/test.opt b/testsuite/tests/N429-018-c-tern-folding/test.opt new file mode 100644 index 000000000..5bd7238f9 --- /dev/null +++ b/testsuite/tests/N429-018-c-tern-folding/test.opt @@ -0,0 +1 @@ +!native DEAD test relies on host standard header files diff --git a/testsuite/tests/N429-018-c-tern-folding/test.py b/testsuite/tests/N429-018-c-tern-folding/test.py new file mode 100644 index 000000000..8bede2117 --- /dev/null +++ b/testsuite/tests/N429-018-c-tern-folding/test.py @@ -0,0 +1,13 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase( + # Note that when C support for GNATcoverage will be ready, this flag + # should be automatically enabled with -fdump-scos. + extracargs='-no-integrated-cpp', + category=cat + ).run() +thistest.result() diff --git a/testsuite/tests/N429-018-c-void-ternary/src/foo.c b/testsuite/tests/N429-018-c-void-ternary/src/foo.c new file mode 100644 index 000000000..fd00ea014 --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/foo.c @@ -0,0 +1,16 @@ +#include "foo.h" +#include "helpers.h" + +int +foo (int cond) +{ + if (identity (cond)) // # if-expr + bar1 (); // # if-then + else + bar2 (); // # if-else + + (identity (cond)) ? bar1 () : bar2 (); // # tern-void-stmt + (identity (cond)) ? identity (cond) : identity (!cond); // # tern-int-stmt + + return ((identity (cond)) ? bar1 () : bar2 ()), 1; // # tern-void-expr +} diff --git a/testsuite/tests/N429-018-c-void-ternary/src/foo.h b/testsuite/tests/N429-018-c-void-ternary/src/foo.h new file mode 100644 index 000000000..8be1505e5 --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/foo.h @@ -0,0 +1,6 @@ +#ifndef FOO_H +#define FOO_H + +extern int foo (int cond); + +#endif diff --git a/testsuite/tests/N429-018-c-void-ternary/src/helpers.c b/testsuite/tests/N429-018-c-void-ternary/src/helpers.c new file mode 100644 index 000000000..f62c5ba4b --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/helpers.c @@ -0,0 +1,9 @@ +void +bar1 (void) +{ +} + +void +bar2 (void) +{ +} diff --git a/testsuite/tests/N429-018-c-void-ternary/src/helpers.h b/testsuite/tests/N429-018-c-void-ternary/src/helpers.h new file mode 100644 index 000000000..785fa787c --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/helpers.h @@ -0,0 +1,9 @@ +#ifndef HELPERS_H +#define HELPERS_H + +extern int identity (int cond); /* from libsupport. */ + +extern void bar1 (void); +extern void bar2 (void); + +#endif diff --git a/testsuite/tests/N429-018-c-void-ternary/src/test_foo_0.c b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_0.c new file mode 100644 index 000000000..61d101f93 --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_0.c @@ -0,0 +1,18 @@ +#include "foo.h" + +int +main (void) +{ + /* Prevent the linker from optimize away "foo". */ + if (identity (0)) + foo (0); + return 0; +} + +//# foo.c +// /if-expr/ l- ## s- +// /if-then/ l- ## s- +// /if-else/ l- ## s- +// /tern-void-stmt/ l- ## s-, s-, s- +// /tern-int-stmt/ l- ## s- +// /tern-void-expr/ l- ## s- diff --git a/testsuite/tests/N429-018-c-void-ternary/src/test_foo_f.c b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_f.c new file mode 100644 index 000000000..00ca4c517 --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_f.c @@ -0,0 +1,16 @@ +#include "foo.h" + +int +main (void) +{ + foo (0); + return 0; +} + +//# foo.c +// /if-expr/ l+ ## 0 +// /if-then/ l- ## s- +// /if-else/ l+ ## 0 +// /tern-void-stmt/ l! ## s- +// /tern-int-stmt/ l+ ## 0 +// /tern-void-expr/ l+ ## 0 diff --git a/testsuite/tests/N429-018-c-void-ternary/src/test_foo_t.c b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_t.c new file mode 100644 index 000000000..7c49b5990 --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_t.c @@ -0,0 +1,16 @@ +#include "foo.h" + +int +main (void) +{ + foo (1); + return 0; +} + +//# foo.c +// /if-expr/ l+ ## 0 +// /if-then/ l+ ## 0 +// /if-else/ l- ## s- +// /tern-void-stmt/ l! ## s- +// /tern-int-stmt/ l+ ## 0 +// /tern-void-expr/ l+ ## 0 diff --git a/testsuite/tests/N429-018-c-void-ternary/src/test_foo_tf.c b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_tf.c new file mode 100644 index 000000000..fb2fa4b5d --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_tf.c @@ -0,0 +1,17 @@ +#include "foo.h" + +int +main (void) +{ + foo (0); + foo (1); + return 0; +} + +//# foo.c +// /if-expr/ l+ ## 0 +// /if-then/ l+ ## 0 +// /if-else/ l+ ## 0 +// /tern-void-stmt/ l+ ## 0 +// /tern-int-stmt/ l+ ## 0 +// /tern-void-expr/ l+ ## 0 diff --git a/testsuite/tests/N429-018-c-void-ternary/test.opt b/testsuite/tests/N429-018-c-void-ternary/test.opt new file mode 100644 index 000000000..5ea0df450 --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/test.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD test requires compiler change from 2014-04, not in 7.0.3 +7.2.2 DEAD test requires compiler change from 2014-04, not in 7.2.2 +!bin-traces DEAD Coverage for C supported only with binary traces +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N429-018-c-void-ternary/test.py b/testsuite/tests/N429-018-c-void-ternary/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/N429-018-c-void-ternary/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/N429-020-loop-on-line-ada/foo.adb b/testsuite/tests/N429-020-loop-on-line-ada/foo.adb new file mode 100644 index 000000000..202138979 --- /dev/null +++ b/testsuite/tests/N429-020-loop-on-line-ada/foo.adb @@ -0,0 +1,24 @@ +procedure Foo is + type Void_PP is access Integer; + + N : Integer := 0; + P : Void_PP; + pragma Volatile (P); +begin + N := 1; + while N < 32 and then p.all /= 0 loop N := N + 1; end loop; + + null; + + -- Note: we used to have here: + + -- if N = 32 then + -- N := N - 1; + -- end if; + + -- But this is eliminated entirely at -O1 (because the value of + -- N is never used), so use a NULL statement instead so that we + -- don't get an additional junk warning for no cond branch found + -- for the IF statement. + +end Foo; diff --git a/testsuite/tests/N429-020-loop-on-line-ada/test.opt b/testsuite/tests/N429-020-loop-on-line-ada/test.opt new file mode 100644 index 000000000..a3304d764 --- /dev/null +++ b/testsuite/tests/N429-020-loop-on-line-ada/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test runs "gnatcov map-routines" diff --git a/testsuite/tests/N429-020-loop-on-line-ada/test.py b/testsuite/tests/N429-020-loop-on-line-ada/test.py new file mode 100644 index 000000000..a288ad03c --- /dev/null +++ b/testsuite/tests/N429-020-loop-on-line-ada/test.py @@ -0,0 +1,10 @@ +import os.path + +from SCOV.map import MapChecker +from SUITE.tutils import thistest + +MapChecker( + ['foo.adb'], + alis=[os.path.join('obj', 'foo.ali')] +).run() +thistest.result() diff --git a/testsuite/tests/N429-020-loop-on-line/main.c b/testsuite/tests/N429-020-loop-on-line/main.c new file mode 100644 index 000000000..3aeb7d1d7 --- /dev/null +++ b/testsuite/tests/N429-020-loop-on-line/main.c @@ -0,0 +1,19 @@ +#include + +#define MAX_FD 32 +#define NULL ((void *) 0) + +int +main (int argc, char *argv[]) +{ + // void** p = &get_api_data()->file_desc[STDERR_FILENO+1]; + void **p; + int n = 0; + for (n = 1; n < MAX_FD && *p != NULL; n++, p++) + ; + if (n == MAX_FD) + { + n = -1; + } + return n; +} diff --git a/testsuite/tests/N429-020-loop-on-line/test.opt b/testsuite/tests/N429-020-loop-on-line/test.opt new file mode 100644 index 000000000..d2ab6f91b --- /dev/null +++ b/testsuite/tests/N429-020-loop-on-line/test.opt @@ -0,0 +1,2 @@ +!native DEAD +!bin-traces DEAD test with map-routines diff --git a/testsuite/tests/N429-020-loop-on-line/test.py b/testsuite/tests/N429-020-loop-on-line/test.py new file mode 100644 index 000000000..eb1505ae4 --- /dev/null +++ b/testsuite/tests/N429-020-loop-on-line/test.py @@ -0,0 +1,10 @@ +import os.path + +from SCOV.map import MapChecker +from SUITE.tutils import thistest + +MapChecker( + ['main.c'], + alis=[os.path.join('obj', 'main.c.gli')] +).run() +thistest.result() diff --git a/testsuite/tests/N430-005-c-static-inline/extra.opt b/testsuite/tests/N430-005-c-static-inline/extra.opt new file mode 100644 index 000000000..0182653a4 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/extra.opt @@ -0,0 +1,2 @@ +7.0.3 DEAD 7.0.3 misses proper SCO support for C +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/bar_false.c b/testsuite/tests/N430-005-c-static-inline/supported/src/bar_false.c new file mode 100644 index 000000000..671c373ee --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/bar_false.c @@ -0,0 +1,9 @@ +#include "foo.h" + +int * +bar_false (void) +{ + get_process (1); // # bar-false + set_current (identity (0)); // # bar-false + return process_current (); // # bar-false +} diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/bar_true.c b/testsuite/tests/N430-005-c-static-inline/supported/src/bar_true.c new file mode 100644 index 000000000..225eaae3c --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/bar_true.c @@ -0,0 +1,9 @@ +#include "foo.h" + +int * +bar_true (void) +{ + get_process (1); // # bar-true + set_current (identity (1)); // # bar-true + return process_current (); // # bar-true +} diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/foo.c b/testsuite/tests/N430-005-c-static-inline/supported/src/foo.c new file mode 100644 index 000000000..c4aba3221 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/foo.c @@ -0,0 +1,22 @@ +#include "foo.h" + +static int current = 0; +static int processes[10]; + +void +set_current (int p) +{ + current = p; // # foo-exercised +} + +int +get_current (void) +{ + return current; // # foo-exercised +} + +int * +get_process (int p) +{ + return &processes[p]; // # foo-exercised +} diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/foo.h b/testsuite/tests/N430-005-c-static-inline/supported/src/foo.h new file mode 100644 index 000000000..2bc03f114 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/foo.h @@ -0,0 +1,22 @@ +#ifndef FOO_H +#define FOO_H + +extern int identity (int x); /* from libsupport. */ + +extern void set_current (int p); +extern int get_current (void); +extern int *get_process (int p); + +extern int *bar_false (void); +extern int *bar_true (void); + +static inline int * +process_current (void) +{ + if (get_current ()) // # if-expr + return get_process (get_current ()); // # if-then + else + return (int *) 0; // # if-else +} + +#endif diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_0.c b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_0.c new file mode 100644 index 000000000..0e1baae2c --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_0.c @@ -0,0 +1,27 @@ +#include "foo.h" + +int +main (void) +{ + /* Prevent the linker from optimize away "bar_*". */ + if (identity (0)) + { + bar_true (); + bar_false (); + } + else + return 0; +} + +//# bar_true.c +// /bar-true/ l- ## s- +//# bar_false.c +// /bar-false/ l- ## s- + +//# foo.c +// /foo-exercised/ l- ## s- + +//# foo.h +// /if-expr/ l- ## s- +// /if-then/ l- ## s- +// /if-else/ l- ## s- diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_f.c b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_f.c new file mode 100644 index 000000000..1a884fd72 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_f.c @@ -0,0 +1,24 @@ +#include "foo.h" + +int +main (void) +{ + /* Prevent the linker from optimize away "bar_true". */ + if (identity (0)) + bar_true (); + bar_false (); + return 0; +} + +//# bar_true.c +// /bar-true/ l- ## s- +//# bar_false.c +// /bar-false/ l+ ## 0 + +//# foo.c +// /foo-exercised/ l+ ## 0 + +//# foo.h +// /if-expr/ s=>l+, dmu=>l! ## s=>0, dmu=>dT- +// /if-then/ l- ## s- +// /if-else/ l+ ## 0 diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_t.c b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_t.c new file mode 100644 index 000000000..afd636bf0 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_t.c @@ -0,0 +1,24 @@ +#include "foo.h" + +int +main (void) +{ + /* Prevent the linker from optimize away "bar_false". */ + if (identity (0)) + bar_false (); + bar_true (); + return 0; +} + +//# bar_true.c +// /bar-true/ l+ ## 0 +//# bar_false.c +// /bar-false/ l- ## s- + +//# foo.c +// /foo-exercised/ l+ ## 0 + +//# foo.h +// /if-expr/ s=>l+, dmu=>l! ## s=>0, dmu=>dF- +// /if-then/ l+ ## 0 +// /if-else/ l- ## s- diff --git a/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_tf.c b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_tf.c new file mode 100644 index 000000000..97d75556a --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/src/test_foo_tf.c @@ -0,0 +1,22 @@ +#include "foo.h" + +int +main (void) +{ + bar_true (); + bar_false (); + return 0; +} + +//# bar_true.c +// /bar-true/ l+ ## 0 +//# bar_false.c +// /bar-false/ l+ ## 0 + +//# foo.c +// /foo-exercised/ l+ ## 0 + +//# foo.h +// /if-expr/ l+ ## 0 +// /if-then/ l+ ## 0 +// /if-else/ l+ ## 0 diff --git a/testsuite/tests/N430-005-c-static-inline/supported/test.py b/testsuite/tests/N430-005-c-static-inline/supported/test.py new file mode 100644 index 000000000..8bede2117 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/supported/test.py @@ -0,0 +1,13 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase( + # Note that when C support for GNATcoverage will be ready, this flag + # should be automatically enabled with -fdump-scos. + extracargs='-no-integrated-cpp', + category=cat + ).run() +thistest.result() diff --git a/testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.c b/testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.c new file mode 100644 index 000000000..5c10f8ccc --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.c @@ -0,0 +1,15 @@ +int +one_int (void) +{ +#define TYPE int +#include "foo.h" +#undef TYPE +} + +unsigned +one_unsigned (void) +{ +#define TYPE unsigned +#include "foo.h" +#undef TYPE +} diff --git a/testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.h b/testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.h new file mode 100644 index 000000000..52d517fd9 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/unsupported/src/foo.h @@ -0,0 +1,2 @@ +TYPE ret = 0; +return (TYPE) ret + 1; diff --git a/testsuite/tests/N430-005-c-static-inline/unsupported/src/test_foo.c b/testsuite/tests/N430-005-c-static-inline/unsupported/src/test_foo.c new file mode 100644 index 000000000..24d8d44fb --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/unsupported/src/test_foo.c @@ -0,0 +1,10 @@ +extern int one_int (void); +extern unsigned one_unsigned (void); + +int +main (void) +{ + return one_unsigned () - one_int (); +} + +//# foo.c diff --git a/testsuite/tests/N430-005-c-static-inline/unsupported/test.py b/testsuite/tests/N430-005-c-static-inline/unsupported/test.py new file mode 100644 index 000000000..7be3ccdef --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/unsupported/test.py @@ -0,0 +1,57 @@ +""" +Check that gnatcov reject SCO overlapping cases with a warning. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +wd = Wdir(subdir='tmp_') + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + mains=['test_foo.c'], + srcdirs=os.path.join('..', 'src'), + langs=['C'], + ), + units=['foo.c'], + ), + covlevel='stmt', + mains=['test_foo'], + extra_coverage_args=['-axcov'], + tolerate_instrument_messages="unexpected SCO overlapping", +) + +# With source traces, the warning is emitted at instrumentation time, whereas +# it is emitted at coverage time with binary traces. +# +# As SCOs source locations differ for binary and source traces, we get +# different warnings. Note that the instrumentation warning is the most +# precise. + +if thistest.options.trace_mode == 'src': + output_string = 'gnatcov instrument output' + output_file = 'instrument.log' + expected_output = ('!!! foo.h:1:1: unexpected SCO overlapping with SCO #1: ' + 'STATEMENT at foo.h:1:1-13, discarding overlapping SCO\n' + '!!! foo.h:2:1: unexpected SCO overlapping with SCO #2: ' + 'STATEMENT at foo.h:2:1-21, discarding overlapping SCO') +else: + output_string = 'gnatcov coverage output' + output_file = 'coverage.log' + expected_output = ('!!! foo.h:2:8: unexpected SCO overlapping with SCO #2: ' + 'STATEMENT at foo.h:2:8-20, discarding overlapping SCO') + +thistest.fail_if_no_match( + output_string, + expected_output, + contents_of(output_file) +) + +thistest.result() diff --git a/testsuite/tests/N505-008-c99-main-return/src/test_main.c b/testsuite/tests/N505-008-c99-main-return/src/test_main.c new file mode 100644 index 000000000..9f028c342 --- /dev/null +++ b/testsuite/tests/N505-008-c99-main-return/src/test_main.c @@ -0,0 +1,7 @@ +int +main (int argc, char *argv[]) +{ + return 0; +} + +//# test_main.c diff --git a/testsuite/tests/N505-008-c99-main-return/test.opt b/testsuite/tests/N505-008-c99-main-return/test.opt new file mode 100644 index 000000000..0182653a4 --- /dev/null +++ b/testsuite/tests/N505-008-c99-main-return/test.opt @@ -0,0 +1,2 @@ +7.0.3 DEAD 7.0.3 misses proper SCO support for C +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N505-008-c99-main-return/test.py b/testsuite/tests/N505-008-c99-main-return/test.py new file mode 100644 index 000000000..00903c8b1 --- /dev/null +++ b/testsuite/tests/N505-008-c99-main-return/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt, extracargs='-std=c99').run() +thistest.result() diff --git a/testsuite/tests/N505-026-multstmtln-nocode/src/helper.c b/testsuite/tests/N505-026-multstmtln-nocode/src/helper.c new file mode 100644 index 000000000..16a8eb65d --- /dev/null +++ b/testsuite/tests/N505-026-multstmtln-nocode/src/helper.c @@ -0,0 +1,5 @@ +void +nop (void) +{ + return; +} diff --git a/testsuite/tests/N505-026-multstmtln-nocode/src/helper.h b/testsuite/tests/N505-026-multstmtln-nocode/src/helper.h new file mode 100644 index 000000000..000ce51b0 --- /dev/null +++ b/testsuite/tests/N505-026-multstmtln-nocode/src/helper.h @@ -0,0 +1 @@ +extern void nop (void); diff --git a/testsuite/tests/N505-026-multstmtln-nocode/src/test_foo.c b/testsuite/tests/N505-026-multstmtln-nocode/src/test_foo.c new file mode 100644 index 000000000..b91509b0f --- /dev/null +++ b/testsuite/tests/N505-026-multstmtln-nocode/src/test_foo.c @@ -0,0 +1,18 @@ +#include "helper.h" + +int +check (int argc) +{ + (argc < 10) ? (void) 0 : nop (); // # tern + return 0; +} + +int +main (void) +{ + (void) check (1); + return 0; +} + +//# test_foo.c +// /tern/ sd=>l! ## s=>s-, d=>s-,dF- diff --git a/testsuite/tests/N505-026-multstmtln-nocode/test.opt b/testsuite/tests/N505-026-multstmtln-nocode/test.opt new file mode 100644 index 000000000..922d8fb08 --- /dev/null +++ b/testsuite/tests/N505-026-multstmtln-nocode/test.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD 7.0.3 required SCO support for C implemented post 7.0 (may 2014) +7.2.2 DEAD 7.2.2 required SCO support for C implemented post 7.2 (may 2014) +!bin-traces DEAD Coverage for C supported only with binary traces +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N505-026-multstmtln-nocode/test.py b/testsuite/tests/N505-026-multstmtln-nocode/test.py new file mode 100644 index 000000000..64dab3c68 --- /dev/null +++ b/testsuite/tests/N505-026-multstmtln-nocode/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.c b/testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.c new file mode 100644 index 000000000..9ca02dbed --- /dev/null +++ b/testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.c @@ -0,0 +1,19 @@ + +/* All the runtimes we link against expose abort(), and we have it on native + platforms as well. It causes abnormal termination on these platforms + though, so we'd better use exit in this case. But exit isn't available + everywhere ... */ + +#include + +extern __attribute__ ((noreturn)) void abort (); +extern __attribute__ ((weak, noreturn)) void exit (int code); + +__attribute__ ((noinline)) void +abort_or_exit (int code) +{ + if (exit != 0) + exit (code); + else + abort (); +} diff --git a/testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.h b/testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.h new file mode 100644 index 000000000..e7ba0083a --- /dev/null +++ b/testsuite/tests/N506-014-crash-on-padding-nop/src/abort_or_exit.h @@ -0,0 +1 @@ +__attribute__ ((noinline, noreturn)) void abort_or_exit (int code); diff --git a/testsuite/tests/N506-014-crash-on-padding-nop/src/test_stop.c b/testsuite/tests/N506-014-crash-on-padding-nop/src/test_stop.c new file mode 100644 index 000000000..26ef84543 --- /dev/null +++ b/testsuite/tests/N506-014-crash-on-padding-nop/src/test_stop.c @@ -0,0 +1,29 @@ +#include + +__attribute__ ((noinline)) __attribute__ ((noreturn)) void +stop (int code) +{ + if (code < 0) // # stop-cond + code = -code + 1; // # stop-then + abort_or_exit (code); +} + +int +check (int code) +{ + if (code > 0) // # check-cond + code = 0; + + stop (code); +} + +int +main (int argc, char *argv[]) +{ + check (1); +} + +//# test_stop.c +// /stop-cond/ l! ## dT- +// /stop-then/ l- ## s- +// /check-cond/ l! ## dF- diff --git a/testsuite/tests/N506-014-crash-on-padding-nop/test.opt b/testsuite/tests/N506-014-crash-on-padding-nop/test.opt new file mode 100644 index 000000000..817e5694a --- /dev/null +++ b/testsuite/tests/N506-014-crash-on-padding-nop/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD 7.0.3 misses proper SCO support for C +!bin-traces DEAD Testing binary traces-specific bug +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N506-014-crash-on-padding-nop/test.py b/testsuite/tests/N506-014-crash-on-padding-nop/test.py new file mode 100644 index 000000000..de3ab802f --- /dev/null +++ b/testsuite/tests/N506-014-crash-on-padding-nop/test.py @@ -0,0 +1,10 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase( + extracargs=['-no-integrated-cpp', '-falign-functions=32'], + category=CAT.decision +).run() +thistest.result() diff --git a/testsuite/tests/N513-004-dom-info-c-tern/src/test_main.c b/testsuite/tests/N513-004-dom-info-c-tern/src/test_main.c new file mode 100644 index 000000000..a2719905d --- /dev/null +++ b/testsuite/tests/N513-004-dom-info-c-tern/src/test_main.c @@ -0,0 +1,15 @@ +int +check (int argc) +{ + (argc < 10) ? (void) 0 : (void) (argc = argc / 2 + 1); // # tern + return argc; +} + +int +main (int argc, char *argv[]) +{ + return check (0); +} + +//# test_main.c +// /tern/ l! ## dF-, s- diff --git a/testsuite/tests/N513-004-dom-info-c-tern/test.opt b/testsuite/tests/N513-004-dom-info-c-tern/test.opt new file mode 100644 index 000000000..eebe9f4af --- /dev/null +++ b/testsuite/tests/N513-004-dom-info-c-tern/test.opt @@ -0,0 +1,4 @@ +7.0.3 DEAD requires compiler change from 2014-05, not in 7.0.3 +7.2.2 DEAD requires compiler change from 2014-05, not in 7.2.2 +!bin-traces DEAD Coverage for C supported only with binary traces +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N513-004-dom-info-c-tern/test.py b/testsuite/tests/N513-004-dom-info-c-tern/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/N513-004-dom-info-c-tern/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.adb new file mode 100644 index 000000000..e142910a5 --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.adb @@ -0,0 +1,42 @@ + +package body Hello is + + function Get_Hello (Formal : Boolean) return String; + -- Returns Hello or Hi depending on the Formal parameter + + --------------- + -- Get_Hello -- + --------------- + + function Get_Hello (Formal : Boolean) return String is + begin + if Formal then -- # test_formal + return "Hello"; -- # formal + else + return "Hi"; -- # casual + end if; + end Get_Hello; + + procedure Process (S : String) is + Len : Integer; + pragma Volatile (Len); + begin + Len := S'Length; + end; + + --------------- + -- Say_Hello -- + --------------- + + procedure Say_Hello (Who : String; Formal : Boolean := True) is + Hello : constant String := Get_Hello (Formal); + begin + if Who = "" then -- # test_nobody + Process (Hello & "!"); -- # nobody + else + Process (Hello & " " & Who & "!"); -- # someone + end if; + end Say_Hello; + +end Hello; + diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.ads b/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.ads new file mode 100644 index 000000000..1c09682ef --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.ads @@ -0,0 +1,3 @@ +package Hello is + procedure Say_Hello (Who : String; Formal : Boolean := True); +end Hello; diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_nobody.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_nobody.adb new file mode 100644 index 000000000..f108ef2c8 --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_nobody.adb @@ -0,0 +1,15 @@ +with Hello; use Hello; + +procedure Test_Casual_Nobody is +begin + Say_Hello ("", Formal => False); +end; + +--# hello.adb +-- /test_nobody/ l! ## dF- +-- /nobody/ l+ ## 0 +-- /someone/ l- ## s- +-- /test_formal/ l! ## dT- +-- /formal/ l- ## s- +-- /casual/ l+ ## 0 + diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_someone.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_someone.adb new file mode 100644 index 000000000..343b7f65b --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_someone.adb @@ -0,0 +1,15 @@ +with Hello; use Hello; + +procedure Test_Casual_Someone is +begin + Say_Hello ("Jerome", Formal => False); +end; + +--# hello.adb +-- /test_nobody/ l! ## dT- +-- /nobody/ l- ## s- +-- /someone/ l+ ## 0 +-- /test_formal/ l! ## dT- +-- /formal/ l- ## s- +-- /casual/ l+ ## 0 + diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_nobody.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_nobody.adb new file mode 100644 index 000000000..bbb96dfdf --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_nobody.adb @@ -0,0 +1,15 @@ +with Hello; use Hello; + +procedure Test_Formal_Nobody is +begin + Say_Hello ("", Formal => True); +end; + +--# hello.adb +-- /test_nobody/ l! ## dF- +-- /nobody/ l+ ## 0 +-- /someone/ l- ## s- +-- /test_formal/ l! ## dF- +-- /formal/ l+ ## 0 +-- /casual/ l- ## s- + diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_someone.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_someone.adb new file mode 100644 index 000000000..6add91be6 --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_someone.adb @@ -0,0 +1,15 @@ +with Hello; use Hello; + +procedure Test_Formal_Someone is +begin + Say_Hello ("Jerome", Formal => True); +end; + +--# hello.adb +-- /test_nobody/ l! ## dT- +-- /nobody/ l- ## s- +-- /someone/ l+ ## 0 +-- /test_formal/ l! ## dF- +-- /formal/ l+ ## 0 +-- /casual/ l- ## s- + diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/test.opt b/testsuite/tests/N521-029-dc-dynstack-twoways/test.opt new file mode 100644 index 000000000..2d37e0886 --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD ticket exposed a compiler issue fixed on 2014-05, not in 7.0.3 +7.2.2 DEAD ticket exposed a compiler issue fixed on 2014-05, not in 7.2.2 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/test.py b/testsuite/tests/N521-029-dc-dynstack-twoways/test.py new file mode 100644 index 000000000..5c679f78e --- /dev/null +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/test.py @@ -0,0 +1,11 @@ +""" +Test that there is no static analysis issue with Pre aspects (preconditions). +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/N610-006-library/libops.gpr b/testsuite/tests/N610-006-library/libops.gpr new file mode 100644 index 000000000..c2207bdb9 --- /dev/null +++ b/testsuite/tests/N610-006-library/libops.gpr @@ -0,0 +1,11 @@ +library project Libops is + for Languages use ("Ada"); + for Source_Dirs use ("libops"); + for Object_Dir use "obj"; + + for Library_Name use "ops"; + for Library_Kind use "static"; + for Library_Dir use "lib"; + +end Libops; + diff --git a/testsuite/tests/N610-006-library/libops/inc.adb b/testsuite/tests/N610-006-library/libops/inc.adb new file mode 100644 index 000000000..faf7049d7 --- /dev/null +++ b/testsuite/tests/N610-006-library/libops/inc.adb @@ -0,0 +1,4 @@ +procedure Inc (X : in out Integer; Amount : Integer) is +begin + X := X + Amount; +end; diff --git a/testsuite/tests/N610-006-library/libops/mult.adb b/testsuite/tests/N610-006-library/libops/mult.adb new file mode 100644 index 000000000..11251a64b --- /dev/null +++ b/testsuite/tests/N610-006-library/libops/mult.adb @@ -0,0 +1,4 @@ +procedure Mult (X : in out Integer; Amount : Integer) is +begin + X := X * Amount; +end; diff --git a/testsuite/tests/N610-006-library/test.py b/testsuite/tests/N610-006-library/test.py new file mode 100644 index 000000000..d44280cfc --- /dev/null +++ b/testsuite/tests/N610-006-library/test.py @@ -0,0 +1,74 @@ +import re + +from SCOV.minicheck import build_and_run +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + +Wdir('tmp_') + +# We have a library with two units and a test exercising only one +# of them. Check that gnatcov reports the untested stmts as uncovered +# and emits an explicit notice of absence of object code on stderr +# with --verbose. + +prj = gprfor(['test_inc.adb'], + srcdirs=['..'], + objdir='obj', + deps=['../libops']) + +xcov_args = build_and_run(gprsw=GPRswitches(root_project=prj), + covlevel='stmt', + mains=['test_inc'], + extra_coverage_args=[]) + + +def trycov(verbose, annotate): + + # last argument of xcov_args it the trace_file name + # Note that coverage collection is on the library, not on + # the test project given to build_and_run + base_cov_command = ( + 'coverage --level=stmt --annotate=%s -P../libops.gpr %s' + % (annotate, xcov_args[-1])) + + cov_command = base_cov_command + if verbose: + cov_command += ' --verbose' + + if annotate != 'report': + cov_command += ' --source-search=libops --output-dir=.' + + p = xcov(cov_command) + + nocode_notified = re.search(pattern='no object code for mult.ali', + string=p.out) + + bin_mode = thistest.options.trace_mode == 'bin' + + if bin_mode and verbose and not nocode_notified: + thistest.failed('missing notice of absence of object code,' + ' verbose=%s, annotate=%s' % (verbose, annotate)) + + if bin_mode and nocode_notified and not verbose: + thistest.failed('unexpected notice of absence of object code,' + ' verbose=%s, annotate=%s' % (verbose, annotate)) + + if annotate == 'report': + thistest.fail_if( + not re.search(pattern='mult.adb.*: statement not executed', + string=p.out), + 'missing expected stmt violation for mult.adb in report') + + if annotate == 'xcov': + thistest.fail_if( + not re.search(pattern='[0-9]+ -:', + string=contents_of('mult.adb.xcov')), + 'missing expected l- in mult.adb.xcov') + + +for v in (True, False): + for a in ('report', 'xcov'): + trycov(verbose=v, annotate=a) + +thistest.result() diff --git a/testsuite/tests/N610-006-library/test_inc.adb b/testsuite/tests/N610-006-library/test_inc.adb new file mode 100644 index 000000000..7c30dbe39 --- /dev/null +++ b/testsuite/tests/N610-006-library/test_inc.adb @@ -0,0 +1,7 @@ +with Inc; + +procedure Test_Inc is + X : Integer := 0; +begin + Inc (X, 1); +end; diff --git a/testsuite/tests/N610-006-library/test_mult.adb b/testsuite/tests/N610-006-library/test_mult.adb new file mode 100644 index 000000000..d856d26c7 --- /dev/null +++ b/testsuite/tests/N610-006-library/test_mult.adb @@ -0,0 +1,7 @@ +with Mult; + +procedure Test_Mult is + X : Integer := 2; +begin + Mult (X, 2); +end; diff --git a/testsuite/tests/N630-009-forward_p_x/foo.adb b/testsuite/tests/N630-009-forward_p_x/foo.adb new file mode 100644 index 000000000..1089b97f8 --- /dev/null +++ b/testsuite/tests/N630-009-forward_p_x/foo.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("hello there"); +end; diff --git a/testsuite/tests/N630-009-forward_p_x/test.opt b/testsuite/tests/N630-009-forward_p_x/test.opt new file mode 100644 index 000000000..ce433215b --- /dev/null +++ b/testsuite/tests/N630-009-forward_p_x/test.opt @@ -0,0 +1 @@ +native DEAD testing gnatcov/gnatemu interaction, no gnatemu on native diff --git a/testsuite/tests/N630-009-forward_p_x/test.py b/testsuite/tests/N630-009-forward_p_x/test.py new file mode 100644 index 000000000..1df8eec7b --- /dev/null +++ b/testsuite/tests/N630-009-forward_p_x/test.py @@ -0,0 +1,32 @@ +"""Check that the -P and -X command line args are passed to gnatemu.""" + +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import exepath_to, gprbuild, gprfor, xrun + + +# Work in a subdirectory +wd = Wdir(subdir='tmp_') + +# Build a program expected to run fine for our current target +gpr = gprfor(mains=['foo.adb'], srcdirs=['..']) +gprbuild(project=gpr) + +program_path = exepath_to('foo') + +# Pass a correct -P and fake -X options together with -v. Check that the -P +# and -X options are found in the gnatemu command executed, as displayed by +# -v. Beware that the -P option may be passed down in various ways, e.g. +# -P gen.gpr or -Pgen.gpr, regardless of how we pass it to gnatcov run. +xargs = ['-XFOO=foo1', '-Xbar=bar1'] +xcovargs = ['-P', gpr, '-v', program_path] + xargs + +p = xrun(xcovargs) +for arg in xargs + ['-P *%s' % gpr]: + thistest.fail_if( + not re.search('gnatemu.*%s' % arg, p.out), + 'couldn\'t find "%s" on the gnatemu command line out of %s' % + (arg, ' '.join(xcovargs))) +thistest.result() diff --git a/testsuite/tests/NA29-019-unit-filters-for-C/abs.c b/testsuite/tests/NA29-019-unit-filters-for-C/abs.c new file mode 100644 index 000000000..67338f5e4 --- /dev/null +++ b/testsuite/tests/NA29-019-unit-filters-for-C/abs.c @@ -0,0 +1,8 @@ +int +absval (int x) +{ + if (x < 0) + return -x; + else + return x; +} diff --git a/testsuite/tests/NA29-019-unit-filters-for-C/test.opt b/testsuite/tests/NA29-019-unit-filters-for-C/test.opt new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/NA29-019-unit-filters-for-C/test.py b/testsuite/tests/NA29-019-unit-filters-for-C/test.py new file mode 100644 index 000000000..2a688fc89 --- /dev/null +++ b/testsuite/tests/NA29-019-unit-filters-for-C/test.py @@ -0,0 +1,91 @@ +""" +Verify the correct behavior of the unit selection facilities for C. + +We perform basic tests here and assume that more sophisticated will work as +well as they all build up on top of the same internal circuits. + +We have one functional unit and one test driver unit, with a template project +file from which we can build, then analyse. We perform different analysis +attempts, all intended to produce results for the functional unit only. This is +achieved by either exluding the harness unit out of the default, leaving only +the functional unit, or by explicitly including the functional unit only. +""" + +import re + +from e3.fs import mkdir, ls + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +Wdir('tmp_') + + +def gengpr(attributes, prjname): + return gprfor( + mains=["test_abs.c"], + prjid=prjname, + srcdirs='..', + objdir='obj', + exedir='.', + langs=['C'], + extra=""" + package Coverage is + {} + end Coverage; + """.format('\n'.join(attributes)) + ) + + +# Build and run first +gprname = gengpr(attributes=[], prjname='build') +xcov_args = build_and_run(GPRswitches(gprname), "stmt", ["test_abs"], + extra_coverage_args=["--annotate=xcov"]) + +# Now analyse with different unit selection schemes ... Assign a different +# directory to each attempt. Expect reports for the functional unit(s) only. + + +def trycov(attributes, outdir): + # Create dedicated dir and analyse with the specific attributes: + mkdir(outdir) + gprname = gengpr(attributes=attributes, prjname=outdir) + xcov('%s -P%s --output-dir=%s' % (' '.join(xcov_args), gprname, outdir)) + + # Check that we have no report for the harness unit and that we have + # a report which looks correct for the functional unit: + harness_reports = ls('%s/test*.xcov' % outdir) + thistest.fail_if(harness_reports, + 'unexpected coverage reports for harness units: %s' + % str(harness_reports)) + + all_reports = ls('%s/*.xcov' % outdir) + thistest.fail_if( + not all_reports, + 'missing expected coverage reports for !harness units in %s' % outdir) + + # We expect to find a mix of coverage notes in each expected + # report: + + def check_report(r): + contents = contents_of(r) + + for note in ('+', '-', '.'): + notes = re.findall(r'\d+ \%c:' % note, contents) + thistest.fail_if( + not notes, "missing expected '%c' notes in %s" % (note, r)) + + for r in all_reports: + check_report(r) + + +trycov(attributes=['for excluded_units use ("test_abs.c");'], + outdir='exclude_harness') +trycov(attributes=['for units use ("abs.c");'], + outdir='include_functional') + +thistest.result() diff --git a/testsuite/tests/NA29-019-unit-filters-for-C/test_abs.c b/testsuite/tests/NA29-019-unit-filters-for-C/test_abs.c new file mode 100644 index 000000000..a3ee16d25 --- /dev/null +++ b/testsuite/tests/NA29-019-unit-filters-for-C/test_abs.c @@ -0,0 +1,15 @@ +extern int absval (int x); + +void +test_abs (void) +{ + volatile int x = -5; + volatile int y = absval (x); +} + +int +main (void) +{ + test_abs (); + return 0; +} diff --git a/testsuite/tests/NB07-026-header-shadow/src/box.h b/testsuite/tests/NB07-026-header-shadow/src/box.h new file mode 100644 index 000000000..bd0e9f3af --- /dev/null +++ b/testsuite/tests/NB07-026-header-shadow/src/box.h @@ -0,0 +1,7 @@ +static int +twice (int x) +{ + return x * 2; +} + +extern void print_log (const char *fmt, ...); diff --git a/testsuite/tests/NB07-026-header-shadow/src/m1.c b/testsuite/tests/NB07-026-header-shadow/src/m1.c new file mode 100644 index 000000000..56a8eb6e6 --- /dev/null +++ b/testsuite/tests/NB07-026-header-shadow/src/m1.c @@ -0,0 +1,13 @@ +#include "box.h" +#include + +static int v = 12; + +void +m1 (bool compute) +{ + if (compute) + print_log ("m1: twice (v) = %d\n", twice (v)); // # m1-true + else + print_log ("m1: don't compute\n"); // # m1-false +} diff --git a/testsuite/tests/NB07-026-header-shadow/src/m2.c b/testsuite/tests/NB07-026-header-shadow/src/m2.c new file mode 100644 index 000000000..492bec425 --- /dev/null +++ b/testsuite/tests/NB07-026-header-shadow/src/m2.c @@ -0,0 +1,13 @@ +#include "box.h" +#include + +static int v = 7; + +void +m2 (bool compute) +{ + if (compute) + print_log ("m2: twice (v) = %d\n", twice (v)); // # m2-true + else + print_log ("m2: don't compute\n"); // # m2-false +} diff --git a/testsuite/tests/NB07-026-header-shadow/src/test_main.c b/testsuite/tests/NB07-026-header-shadow/src/test_main.c new file mode 100644 index 000000000..c114c8e83 --- /dev/null +++ b/testsuite/tests/NB07-026-header-shadow/src/test_main.c @@ -0,0 +1,24 @@ +#include + +extern void m1 (bool compute); +extern void m2 (bool compute); + +void +print_log (const char *fmt, ...) +{ +} + +int +main () +{ + m1 (true); + m2 (false); + return 0; +} + +//# m1.c +// /m1-true/ l+ ## 0 +// /m1-false/ l- ## s- +//# m2.c +// /m2-true/ l- ## s- +// /m2-false/ l+ ## 0 diff --git a/testsuite/tests/NB07-026-header-shadow/test.opt b/testsuite/tests/NB07-026-header-shadow/test.opt new file mode 100644 index 000000000..f8b21b735 --- /dev/null +++ b/testsuite/tests/NB07-026-header-shadow/test.opt @@ -0,0 +1,3 @@ +7.0.3 DEAD fixed by a compiler change introduced in the 7.4.0w timeframe, ported to 7.3 +7.2.2 DEAD fixed by a compiler change introduced in the 7.4.0w timeframe, ported to 7.3 +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/NB07-026-header-shadow/test.py b/testsuite/tests/NB07-026-header-shadow/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/NB07-026-header-shadow/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/NC02-014-gpr-X/main.adb b/testsuite/tests/NC02-014-gpr-X/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/NC02-014-gpr-X/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/NC02-014-gpr-X/test.py b/testsuite/tests/NC02-014-gpr-X/test.py new file mode 100644 index 000000000..1a976abbd --- /dev/null +++ b/testsuite/tests/NC02-014-gpr-X/test.py @@ -0,0 +1,75 @@ +""" +Exercise the use of -X on the gnatcov command line to control project files +operations, with -X appearing either before or after -P. +""" + +import os.path +import shutil + +from e3.fs import ls + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +# We use a scenario variable to select the output directory for coverage +# reports. +extra = """ + type Report_Type is ("f", "g", "all"); + This_Report : Report_Type := external ("THIS_REPORT", "all"); + package Coverage is + for Switches ("coverage") use ("--output-dir", "output-" & This_Report); + end Coverage; +""" + +report_types = ['f', 'g'] + + +def output_dir(what): + return 'output-{}'.format(what) + + +# Build and run once, in a dedicated temp directory +wd = Wdir('tmp_') + +base_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=['main.adb'], + srcdirs=['..'], extra=extra)), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov']) + + +# Now perform analysis variants + +def trycov(this_report, where): + # Clear output directories, to notice what is created that should not + for what in report_types: + d = output_dir(what) + if os.path.isdir(d): + shutil.rmtree(d) + + # THIS_REPORT conveys what value to pass as -XTHIS_REPORT. + # WHERE conveys whether -X should be placed 'before' or 'after' -P. + args = list(base_args) + arg_i = len(args) if where == 'after' else 1 + args.insert(arg_i, '-XTHIS_REPORT={}'.format(this_report)) + xcov(args) + + this_output_dir = output_dir(this_report) + expected_report = os.path.join(this_output_dir, 'main.adb.xcov') + reports = ls(os.path.join(output_dir('*'), '*.xcov')) + + thistest.fail_if( + len(reports) > 1 or expected_report not in reports, + 'expected a single {}, got {}'.format(expected_report, reports)) + + +for what in report_types: + for where in ('before', 'after'): + trycov(this_report=what, where=where) + +thistest.result() diff --git a/testsuite/tests/NC08-027-target_attr/foo.adb b/testsuite/tests/NC08-027-target_attr/foo.adb new file mode 100644 index 000000000..1089b97f8 --- /dev/null +++ b/testsuite/tests/NC08-027-target_attr/foo.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("hello there"); +end; diff --git a/testsuite/tests/NC08-027-target_attr/test.opt b/testsuite/tests/NC08-027-target_attr/test.opt new file mode 100644 index 000000000..0c7704396 --- /dev/null +++ b/testsuite/tests/NC08-027-target_attr/test.opt @@ -0,0 +1 @@ +native DEAD testing --target interactions, no --target at all for native. diff --git a/testsuite/tests/NC08-027-target_attr/test.py b/testsuite/tests/NC08-027-target_attr/test.py new file mode 100644 index 000000000..bd86b8224 --- /dev/null +++ b/testsuite/tests/NC08-027-target_attr/test.py @@ -0,0 +1,59 @@ +""" +Alternate test for NC08-027, complementary to the one within the GPR subset of +our suite. +""" + +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir, indent +from SUITE.tutils import exepath_to, gprbuild, gprfor, xrun + + +# Work in a subdirectory +wd = Wdir(subdir='tmp_') + +# Build a program expected to run fine for our current target +gpr = gprfor(mains=['foo.adb'], srcdirs=['..']) +gprbuild(project=gpr) + +program_path = exepath_to('foo') + +# Check that a Target attribute in a project file is accounted for +# by gnatcov run. +# +# Try to run with a project file containing a fake Target value. +# Expect an error complaining about an unknown target. +gpr = gprfor(mains=[], srcdirs=['..'], + extra='for Target use "foo-bar";\n') +runargs = ['-P', gpr, program_path] +p = xrun(runargs, register_failure=False, + auto_config_args=False, + auto_target_args=False) + +if thistest.bits() == 32: + thistest.fail_if( + not re.search('No builtin or GNATemulator execution driver found for' + ' target: foo-bar', p.out), + "couldn't find indication of unknown target error in gnatcov" + " run output:\n {}".format(indent(p.out))) +else: + # thistest.bits() == 64 + # In that case, as gnatcov32 is picked by default if the given target + # is invalid, it will fail when loading the executable file. + + thistest.fail_if( + not re.search('unsupported ELF class', p.out), + "couldn't find indication of ELF class unsupported error in gnatcov" + " run output:\n {}".format(indent(p.out))) + +# Check that an explicit --target on the command line overrides the +# Target project file attribute. +# +# Same arguments as in the previous test, plus correct --target and --RTS +# arguments. This one should succeed. +xrun(runargs, + auto_config_args=False, + auto_target_args=True) + +thistest.result() diff --git a/testsuite/tests/O302-015-src-path-in-project/p.gpr b/testsuite/tests/O302-015-src-path-in-project/p.gpr new file mode 100644 index 000000000..8453bffd8 --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/p.gpr @@ -0,0 +1,7 @@ +project P is + for Languages use ("Ada"); + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Main use ("main.adb"); + +end P; diff --git a/testsuite/tests/O302-015-src-path-in-project/src/main.adb b/testsuite/tests/O302-015-src-path-in-project/src/main.adb new file mode 100644 index 000000000..7d5971394 --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/src/main.adb @@ -0,0 +1,6 @@ +with Pkg.HW; + +procedure Main is +begin + Pkg.HW.Hello_World; +end Main; diff --git a/testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.adb b/testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.adb new file mode 100644 index 000000000..1423f3f61 --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.adb @@ -0,0 +1,8 @@ +with Pkg.IO; + +package body Pkg.HW is + procedure Hello_World is + begin + Pkg.IO.Put_Line ("Hello, world!"); + end Hello_World; +end Pkg.HW; diff --git a/testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.ads b/testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.ads new file mode 100644 index 000000000..7fda7d644 --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/src/pkg-hw.ads @@ -0,0 +1,3 @@ +package Pkg.HW is + procedure Hello_World; +end Pkg.HW; diff --git a/testsuite/tests/O302-015-src-path-in-project/src/pkg-io.adb b/testsuite/tests/O302-015-src-path-in-project/src/pkg-io.adb new file mode 100644 index 000000000..1e0c0d562 --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/src/pkg-io.adb @@ -0,0 +1,6 @@ +package body Pkg.IO is + procedure Put_Line (S : String) is + begin + null; + end Put_Line; +end Pkg.IO; diff --git a/testsuite/tests/O302-015-src-path-in-project/src/pkg-io.ads b/testsuite/tests/O302-015-src-path-in-project/src/pkg-io.ads new file mode 100644 index 000000000..cfb9eb837 --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/src/pkg-io.ads @@ -0,0 +1,3 @@ +package Pkg.IO is + procedure Put_Line (S : String); +end Pkg.IO; diff --git a/testsuite/tests/O302-015-src-path-in-project/src/pkg.ads b/testsuite/tests/O302-015-src-path-in-project/src/pkg.ads new file mode 100644 index 000000000..2131e57ff --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + pragma Warnings (Off); +end Pkg; diff --git a/testsuite/tests/O302-015-src-path-in-project/test.py b/testsuite/tests/O302-015-src-path-in-project/test.py new file mode 100644 index 000000000..8c7096dc0 --- /dev/null +++ b/testsuite/tests/O302-015-src-path-in-project/test.py @@ -0,0 +1,69 @@ +""" +Check that we can build, run and analyse a program featuring dummy units with +or without a project file, relying on debug info to locate the sources in the +case. +""" + +import os.path + +from e3.fs import rm + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + + +bin_traces = thistest.options.trace_mode == 'bin' + + +# Precompute absolute paths before going to the temporary directory +prj_path = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') +pkg_ads_report_path = os.path.join(obj_dir, 'pkg.ads.xcov') +scos = [os.path.join(obj_dir, name) + for name in ('pkg', 'pkg-hw', 'pkg-io', 'main')] + +wd = Wdir(subdir='tmp_') + + +# Build the project and produce a trace for its main. This is using MCDC + SCOs +# as in the original test we received (when SCOs are available, i.e. in binary +# trace mode). +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=prj_path), + covlevel='stmt+mcdc', + mains=['main'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + scos=scos, + extra_coverage_args=['--annotate=xcov']) +trace_file = xcov_args[-1] + + +# Now check that analysis works one way or the other: with SCOs and with -P in +# binary trace mode, and with -P only in other modes. + +def try_coverage(xcov_args, use_project): + rm(pkg_ads_report_path) + + if not use_project: + xcov_args = xcov_args + ['--output-dir={}'.format(obj_dir)] + p = xcov(xcov_args) + + thistest.fail_if( + p.out, + '"gnatcov coverage" output is not empty:\n--\n{}'.format(p.out)) + thistest.fail_if( + not os.path.isfile(pkg_ads_report_path), + '"gnatcov coverage" could not produce a report file for pkg.ads') + + +try_coverage(xcov_args, use_project=False) +if bin_traces: + try_coverage(['coverage', '-P', prj_path, '--level=stmt+mcdc', + '--annotate=xcov', trace_file], + use_project=True) + +thistest.result() diff --git a/testsuite/tests/O529-021-wrong-elf-class/code-32.o b/testsuite/tests/O529-021-wrong-elf-class/code-32.o new file mode 100644 index 0000000000000000000000000000000000000000..71ebc15ed56af0e613d655ded73f7589cda15d43 GIT binary patch literal 445 zcmb<-^>JflWMqH=Mh0dE1do9s1u9_zrZpJY8CV!5Fz6Lm=9VNT0qK$=2%Q0Am84db zFzBTumLxLhB^4LL%q51F1}XyC%?4ErvJ=@YFt#F8oEfUl6iUM=m^yW!00$5gQYVO{ z24n`vJRJ}N3Sj1eXeO8-kgfp=H~?vods(1Z07!EJG0aXNlVJ}~9n1_6ADIo}V*{wM N05T8RW)L4}0{}~<6iEO8 literal 0 HcmV?d00001 diff --git a/testsuite/tests/O529-021-wrong-elf-class/code-64.o b/testsuite/tests/O529-021-wrong-elf-class/code-64.o new file mode 100644 index 0000000000000000000000000000000000000000..ce564609708b7688a2b82f5ed311e366034bb899 GIT binary patch literal 657 zcmb<-^>JfjWMqH=Mg}_u1P><4z)*l-GB|+Q4h-xJEDRGE^olEUOA?cSbV(6}&VaE> zQY%Ur^imQ_5*hT8ii?qqAe$)-)CqDQ8=46YP(Hfb(fNu%bs#ZjsCpRX2xFkp==#-x z@*F@+u6{u*dO=pg?AHNtkN~>: +# [regular instructions] +# : +# [regular instructions] +# nop +# When consolidating the two, GNATcoverage needs to acknowledge that the NOP +# can be discarded in order to have two routines with the same instructions. +# +# This testcase does exactly that: it has one reference assembly file got from +# the compilation of a C source (one assembly file per platform: see foo.c and +# foo-*.s). This reference assembly file is built as a program and we also +# generate variants of this assembly file to embed various padding (and +# not-padding!) instructions. Then, we generate trace for all of these and we +# try to consolidate them: then we only have to check that GNATcoverage raises +# errors for variants with non-padding instructions and behaves fine with +# padding ones. + + +# As the set of padding instructions is completely architecture-dependent (we +# are talking about ISA), we need some testcase database. Upper-case ones come +# from the Intel Manual (look for: Recommended Multi-Byte Sequence of NOP +# Instruction). + +insns_x86 = [ + # 1-byte padding + (True, 'nop'), + + # 2-bytes padding + (True, 'xchg %ax, %ax'), + (False, 'xchg %ax, %bx'), + (True, '# 66 NOP\n' + '.byte 0x66, 0x90'), + + # 3-bytes padding + (True, 'lea 0x0(%eax),%eax'), + (True, 'lea 0x0(%esi),%esi'), + (False, 'lea 0x0(%eax),%esi'), + (False, 'lea 0x1(%eax),%eax'), + (False, 'lea 0x0(%eax,%eax),%eax'), + (False, 'lea 0x0(%eax,%eax,2),%eax'), + (True, 'lea 0x0(%eax,2),%eax'), + (True, '# NOP DWORD ptr [EAX]\n' + '.byte 0x0F, 0x1F, 0x00'), + + # 4-bytes padding + (True, '# lea 0x0(%esi,%eiz,1),%esi\n' + '.byte 0x8d, 0x74, 0x26, 0x00'), + (True, '# lea 0x0(%esi,%eiz,2),%esi\n' + '.byte 0x8d, 0x74, 0x66, 0x00'), + (False, '# lea 0x0(%ebp,%eiz,1),%esi\n' + '.byte 0x8d, 0x74, 0x25, 0x00'), + (False, '# lea 0x0(%esi,%esi,1),%esi\n' + '.byte 0x8d, 0x74, 0x36, 0x00'), + (True, '# NOP DWORD ptr [EAX + 00H]\n' + '.byte 0x0F, 0x1F, 0x40, 0x00'), + + # 5-bytes padding + (True, '# NOP DWORD ptr [EAX + EAX*1 + 00H]\n' + '.byte 0x0F, 0x1F, 0x44, 0x00, 0x00'), + + # 6-bytes padding + (True, '# lea 0x0(%esi),%esi\n' + '.byte 0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00'), + (False, '# lea 0x0(%eax),%esi\n' + '.byte 0x8d, 0xb0, 0x00, 0x00, 0x00, 0x00'), + (True, '# 66 NOP DWORD ptr [EAX + EAX*1 + 00H]\n' + '.byte 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00'), + + # 7-bytes padding + (True, '# lea 0x0(%esi,%eiz,1),%esi\n' + '.byte 0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, 0x00'), + (False, '# lea 0x0(%ebp,%eiz,1),%esi\n' + '.byte 0x8d, 0xb4, 0x25, 0x00, 0x00, 0x00, 0x00'), + (False, '# lea 0x0(,%eiz,1),%esi\n' + '.byte 0x8d, 0x34, 0x25, 0x00, 0x00, 0x00, 0x00'), + (True, '# lea 0x0(,%esi,1),%esi\n' + '.byte 0x8d, 0x34, 0x35, 0x00, 0x00, 0x00, 0x00'), + (False, '# lea 0x0(,%edi,1),%esi\n' + '.byte 0x8d, 0x34, 0x3d, 0x00, 0x00, 0x00, 0x00'), + (False, '# lea 0x0(%eax,%eax,1),%esi\n' + '.byte 0x8d, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00'), + (True, '# NOP DWORD ptr [EAX + 00000000H]\n' + '.byte 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00'), + + # 8-bytes padding + (True, '# NOP DWORD ptr [EAX + EAX*1 + 00000000H]\n' + '.byte 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00'), + + # 9-bytes padding + (True, '# 66 NOP DWORD ptr [EAX + EAX*1 + 00000000H]\n' + '.byte 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00'), +] + + +test_database = { + 'x86-linux': insns_x86, + 'x86-windows': insns_x86, +} + + +def run_test(platform, insns): + asm_src = os.path.abspath('foo-{}.s'.format(platform)) + Wdir('tmp_') + + def build_material(name, padding_insn=None): + tmp = Wdir('build-{}'.format(name)) + + asm_code = contents_of(asm_src).format(padding=padding_insn or '') + asm_filename = text_to_file(asm_code, 'foo.s') + project = gprfor([asm_filename], srcdirs=['.'], objdir='.', + langs=['Asm']) + # The assembly files already contain debug information: ask the + # assembler not to produce it itself. + gprbuild(project, extracargs='-g0') + xrun(exepath_to('foo')) + trace_name = os.path.abspath(tracename_for('foo')) + + tmp.to_homedir() + return trace_name + + # First, build all test material: build programs (reference and + # with-padding programs) and generate traces for them. + + trace_ref = build_material('ref') + traces = [] + for i, (_, insn) in enumerate(insns): + traces.append(build_material(str(i), insn)) + + # Then try to consolidate each with-padding program with the reference one + routine = target_info().to_platform_specific_symbol('foo') + for i, ((is_padding, insn), trace_file) in enumerate(zip(insns, traces)): + args = ['coverage', '--level=insn', '--annotate=asm', + '--routines={}'.format(routine), + trace_ref, trace_file] + out_file = 'object-cons-{}.txt'.format(i) + p = xcov(args, out=out_file, register_failure=False) + + insn_label = insn.split('\n')[0] + consolidation_failed = p.status != 0 + command = 'gnatcov {}'.format(' '.join(args)) + + # First, if consolidation failed, make sure it is because of symbol + # matching. + thistest.fail_if( + consolidation_failed and not + match('TRACES_NAMES.CONSOLIDATION_ERROR', out_file), + '[{}] "gnatcov coverage" failed in an unexpected way\n' + ' Command was: {}'.format(i, command) + ) + + # Now, check if GNATcoverage correctly matched inserted code as padding + # (or as no padding). + if is_padding: + thistest.fail_if( + consolidation_failed, + '[{}] "{}" was not considered as padding (it is)\n' + ' Command was: {}'.format(i, insn_label, command) + ) + else: + thistest.fail_if( + not consolidation_failed, + '[{}] "{}" was considered as padding (it is not)\n' + ' Command was: {}'.format(i, insn_label, command) + ) + + +platform = env.target.platform +try: + insns = test_database[platform] +except KeyError: + thistest.comment('Nothing to test for {}'.format(platform)) +else: + run_test(platform, insns) + +thistest.result() diff --git a/testsuite/tests/OA05-051-sharedobjs-opt/foo.adb b/testsuite/tests/OA05-051-sharedobjs-opt/foo.adb new file mode 100644 index 000000000..f7b0acefa --- /dev/null +++ b/testsuite/tests/OA05-051-sharedobjs-opt/foo.adb @@ -0,0 +1,4 @@ +procedure Foo is +begin + null; +end Foo; diff --git a/testsuite/tests/OA05-051-sharedobjs-opt/test.opt b/testsuite/tests/OA05-051-sharedobjs-opt/test.opt new file mode 100644 index 000000000..b22c473a1 --- /dev/null +++ b/testsuite/tests/OA05-051-sharedobjs-opt/test.opt @@ -0,0 +1,2 @@ +!bin-traces DEAD Binary traces specific testcase +!linux DEAD Testcase written for Linux diff --git a/testsuite/tests/OA05-051-sharedobjs-opt/test.py b/testsuite/tests/OA05-051-sharedobjs-opt/test.py new file mode 100644 index 000000000..f8f3ef595 --- /dev/null +++ b/testsuite/tests/OA05-051-sharedobjs-opt/test.py @@ -0,0 +1,48 @@ +"""Test validation of --shared-object command-line option usage.""" + +import re + +from SUITE.cutils import Wdir, indent +from SUITE.tutils import exepath_to, gprbuild, gprfor, thistest, xrun + + +wdir = Wdir('tmp_') + + +gprbuild(gprfor(['foo.adb'], srcdirs='..')) +exe = exepath_to('foo') + +for opt, err_msg in [ + ('none', None), + ('all', None), + ('foo.so', None), + ('foo.so bar.so', None), + + ('none all', '"none" and "all" cannot be used at the same time'), + ('all none', '"none" and "all" cannot be used at the same time'), + + ('none foo.so', 'cannot provide shared objects with "none"'), + ('foo.so none', 'cannot provide shared objects with "none"'), + + ('all foo.so', 'cannot provide shared objects with "all"'), + ('foo.so all', 'cannot provide shared objects with "all"'), +]: + args = [] + for arg in opt.split(): + args.extend(['-L', arg]) + args.append(exe) + p = xrun(args, register_failure=err_msg is None) + if err_msg: + pattern = r'.*gnatcov.*: --shared-object\|-L: {}'.format( + re.escape(err_msg)) + thistest.fail_if( + p.status == 0, + '"{}" was expected to fail, but it did not'.format(' '.join(args))) + thistest.fail_if( + not re.match(pattern, p.out.strip()), + '\nError mesage:' + '\n{}' + '\nDoes not match the expected pattern:' + '\n{}'.format(indent(p.out), indent(pattern))) + +thistest.result() diff --git a/testsuite/tests/OA05-051-sharedobjs/mylib1.gpr b/testsuite/tests/OA05-051-sharedobjs/mylib1.gpr new file mode 100644 index 000000000..be784ec15 --- /dev/null +++ b/testsuite/tests/OA05-051-sharedobjs/mylib1.gpr @@ -0,0 +1,10 @@ +library project Mylib1 is + + for Library_Name use "mylib1"; + for Library_Kind use "relocatable"; + + for Source_Dirs use ("src-mylib1"); + for Library_Dir use "tmp/lib"; + for Object_Dir use "tmp/obj"; + +end Mylib1; diff --git a/testsuite/tests/OA05-051-sharedobjs/mylib2.gpr b/testsuite/tests/OA05-051-sharedobjs/mylib2.gpr new file mode 100644 index 000000000..99e73cb26 --- /dev/null +++ b/testsuite/tests/OA05-051-sharedobjs/mylib2.gpr @@ -0,0 +1,10 @@ +library project Mylib2 is + + for Library_Name use "mylib2"; + for Library_Kind use "relocatable"; + + for Source_Dirs use ("src-mylib2"); + for Library_Dir use "tmp/lib"; + for Object_Dir use "tmp/obj"; + +end Mylib2; diff --git a/testsuite/tests/OA05-051-sharedobjs/myprog.gpr b/testsuite/tests/OA05-051-sharedobjs/myprog.gpr new file mode 100644 index 000000000..98f2c3107 --- /dev/null +++ b/testsuite/tests/OA05-051-sharedobjs/myprog.gpr @@ -0,0 +1,11 @@ +with "mylib1"; +with "mylib2"; + +project Myprog is + + for Source_Dirs use ("src-myprog"); + for Object_Dir use "tmp/obj"; + for Exec_Dir use "tmp/bin"; + for Main use ("myprog"); + +end Myprog; diff --git a/testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.adb b/testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.adb new file mode 100644 index 000000000..e418498f5 --- /dev/null +++ b/testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.adb @@ -0,0 +1,8 @@ +package body Mylib1 is + + function F (I : Integer) return Integer is + begin + return I / 2; + end F; + +end Mylib1; diff --git a/testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.ads b/testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.ads new file mode 100644 index 000000000..070e481d5 --- /dev/null +++ b/testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.ads @@ -0,0 +1,5 @@ +package Mylib1 is + + function F (I : Integer) return Integer; + +end Mylib1; diff --git a/testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.adb b/testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.adb new file mode 100644 index 000000000..fa3cc6cfd --- /dev/null +++ b/testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.adb @@ -0,0 +1,8 @@ +package body Mylib2 is + + function F (I : Integer) return Integer is + begin + return ((I / 3) + 1) * 2; + end F; + +end Mylib2; diff --git a/testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.ads b/testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.ads new file mode 100644 index 000000000..68fc9bb85 --- /dev/null +++ b/testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.ads @@ -0,0 +1,5 @@ +package Mylib2 is + + function F (I : Integer) return Integer; + +end Mylib2; diff --git a/testsuite/tests/OA05-051-sharedobjs/src-myprog/myprog.adb b/testsuite/tests/OA05-051-sharedobjs/src-myprog/myprog.adb new file mode 100644 index 000000000..dd00a9422 --- /dev/null +++ b/testsuite/tests/OA05-051-sharedobjs/src-myprog/myprog.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with GNAT.OS_Lib; use GNAT.OS_Lib; + +with Mylib1; +with Mylib2; + +procedure Myprog is +begin + Put_Line ("Hello, world!"); + Put_Line ("-> " & Natural'Image (Mylib1.F (1))); + Put_Line ("-> " & Natural'Image (Mylib2.F (2))); +end Myprog; diff --git a/testsuite/tests/OA05-051-sharedobjs/test.opt b/testsuite/tests/OA05-051-sharedobjs/test.opt new file mode 100644 index 000000000..b22c473a1 --- /dev/null +++ b/testsuite/tests/OA05-051-sharedobjs/test.opt @@ -0,0 +1,2 @@ +!bin-traces DEAD Binary traces specific testcase +!linux DEAD Testcase written for Linux diff --git a/testsuite/tests/OA05-051-sharedobjs/test.py b/testsuite/tests/OA05-051-sharedobjs/test.py new file mode 100644 index 000000000..72edc0eea --- /dev/null +++ b/testsuite/tests/OA05-051-sharedobjs/test.py @@ -0,0 +1,211 @@ +""" +This peculiar testcase attemps to test shared objects support in source +coverage in "gnatcov" without the corresponding handling in trace producers. + +In order to do this, it crafts multiple "artificial" trace files with various +trace entries and checks that "gnatcov coverage" produces the reports we expect +for each trace file. +""" + +import os.path +import struct +import subprocess + +from e3.fs import mkdir, rm + +from SUITE.cutils import lines_of +from SUITE.tutils import gprbuild, thistest, xcov + +from SUITE.tracelib import ( + TraceEntry, TraceSpecial, TraceFile, TraceOp, TraceKind, + create_exec_infos, create_trace_header) + + +# Clean artifaacts from previous runs +if os.path.exists('tmp'): + rm('tmp', recursive=True) +mkdir('tmp') + + +def in_tmp(*elts): + return os.path.join('tmp', *elts) + + +# Build the program along with the shared libraries. Since we build with shared +# libraries, set LIBRARY_TYPE accordingly so that the implict with of +# gnatcov_rts_full works fine. +gprbuild('myprog', gargs=['-XLIBRARY_TYPE=relocatable']) +myprog_filename = in_tmp('bin', 'myprog') + + +# And now create a set of traces we'll use to test "gnatcov coverage" + +class Symbol(object): + def __init__(self, addr, size): + self.addr = addr + self.size = size + + @property + def first(self): + return self.addr + + @property + def last(self): + return self.addr + self.size - 1 + + +def get_symbol(filename, symbol): + for line in subprocess.check_output( + ['nm', '-S', filename] + ).decode('utf-8').splitlines(): + if line.endswith(symbol): + addr, size, _ = line.split(None, 2) + return Symbol(int(addr, 16), int(size, 16)) + raise ValueError('Could not find symbol {} in {}'.format( + symbol, filename + )) + + +ELFHeader = struct.Struct( + '<16s' # e_ident + 'H' # e_type + 'H' # e_machine +) +EI_CLASS = 4 +ELFCLASS32 = 1 +ELFCLASS64 = 2 + +EI_DATA = 5 +ELFDATA2LSB = 1 +ELFDATA2MSB = 2 + +# Get architecture properties from the ELF we just built +with open(myprog_filename, 'rb') as f: + hdr = ELFHeader.unpack(f.read(ELFHeader.size)) + e_ident = hdr[0] + e_type = hdr[1] + e_machine = hdr[2] + + bits = {ELFCLASS32: 32, ELFCLASS64: 64}[e_ident[EI_CLASS]] + big_endian = e_ident[EI_DATA] == ELFDATA2MSB + machine = (((e_machine & 0xff) << 8) | (e_machine >> 8) + if big_endian else + e_machine) + +so_load_addr = 0xccff0000 + +trace_file_info = create_exec_infos(myprog_filename) + +libnames = ('mylib1', 'mylib2') +libfiles = { + libname: in_tmp('lib', 'lib{}.so'.format(libname)) + for libname in libnames +} +syms = { + libname: get_symbol(libfile, '{}__f'.format(libname)) + for libname, libfile in libfiles.items() +} + +load_events = { + libname: TraceEntry( + bits, so_load_addr, + TraceSpecial.LoadSharedObject, TraceOp.Special, + create_exec_infos(libfiles[libname], code_size=sym.last + 1) + ) + for libname, sym in syms.items() +} +unload_event = TraceEntry(bits, so_load_addr, TraceSpecial.UnloadSharedObject, + TraceOp.Special) + + +def write_traces(trace_filename, executed_libs): + entries = [] + for libname in libnames: + entries.append(load_events[libname]) + if libname in executed_libs: + sym = syms[libname] + entries.append(TraceEntry(bits, so_load_addr + sym.addr, + sym.size, + TraceOp.Block)) + entries.append(unload_event) + + tf = TraceFile( + create_trace_header(TraceKind.Info, bits // 8, big_endian, machine), + trace_file_info, + create_trace_header(TraceKind.Flat, bits // 8, big_endian, machine), + entries + ) + + with open(trace_filename, 'wb') as f: + tf.write(f) + + +for trace_filename, executed_libs in [ + ('myprog_0.trace', []), + ('myprog_1.trace', ['mylib1']), + ('myprog_2.trace', ['mylib2']), + ('myprog_12.trace', ['mylib1', 'mylib2']), +]: + write_traces(in_tmp(trace_filename), executed_libs) + + +# Traces are ready: let's see how coverage goes! + +def cov_report_summary(output_dir): + summary = [] + for cov_file in os.listdir(output_dir): + cov_set = set() + cov_filepath = os.path.join(output_dir, cov_file) + assert cov_file.endswith('.xcov') + cov_file = cov_file[:-5] + for line in lines_of(cov_filepath): + try: + prefix, _ = line.split(':', 1) + _, prefix = prefix.rsplit(' ', 1) + except ValueError: + continue + if prefix in '+-': + cov_set.add(prefix) + summary.append((cov_file, ''.join(sorted(cov_set)))) + return sorted(summary) + + +def format_summary(summary, indent=''): + return '\n'.join( + '{}{}: {}'.format(indent, cov_file, cov_set) + for cov_file, cov_set in summary + ) + + +expectations = { + '0': [('mylib1.adb', '-'), + ('mylib2.adb', '-'), + ('myprog.adb', '-')], + '1': [('mylib1.adb', '+'), + ('mylib2.adb', '-'), + ('myprog.adb', '-')], + '2': [('mylib1.adb', '-'), + ('mylib2.adb', '+'), + ('myprog.adb', '-')], + '12': [('mylib1.adb', '+'), + ('mylib2.adb', '+'), + ('myprog.adb', '-')]} + +for tag, exp in expectations.items(): + output_dir = in_tmp('report-{}'.format(tag)) + if os.path.exists(in_tmp(output_dir)): + rm(output_dir, recursive=True) + mkdir(output_dir) + + xcov(['coverage', '-Pmyprog', '--level=stmt', '--annotate=xcov', + '--output-dir', output_dir, in_tmp('myprog_{}.trace'.format(tag))]) + summary = cov_report_summary(output_dir) + thistest.fail_if( + summary != exp, + 'Expected the following coverage report:\n' + '{}\n' + 'But got the following one instead:\n' + '{}'.format(format_summary(exp, ' '), + format_summary(summary, ' '))) + +thistest.result() diff --git a/testsuite/tests/OA16-009-exec-prefix/prj1/foo.adb b/testsuite/tests/OA16-009-exec-prefix/prj1/foo.adb new file mode 100644 index 000000000..d67dbe807 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/prj1/foo.adb @@ -0,0 +1,8 @@ +with Pkg; + +-- This is prj1's foo.adb + +procedure Foo is +begin + Pkg.Do_Nothing; +end Foo; diff --git a/testsuite/tests/OA16-009-exec-prefix/prj1/pkg.adb b/testsuite/tests/OA16-009-exec-prefix/prj1/pkg.adb new file mode 100644 index 000000000..899286010 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/prj1/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + procedure Do_Nothing is + begin + null; + end Do_Nothing; +end Pkg; diff --git a/testsuite/tests/OA16-009-exec-prefix/prj1/pkg.ads b/testsuite/tests/OA16-009-exec-prefix/prj1/pkg.ads new file mode 100644 index 000000000..0fca99536 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/prj1/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Do_Nothing; +end Pkg; diff --git a/testsuite/tests/OA16-009-exec-prefix/prj2/foo.adb b/testsuite/tests/OA16-009-exec-prefix/prj2/foo.adb new file mode 100644 index 000000000..4557dafd7 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/prj2/foo.adb @@ -0,0 +1,10 @@ +with Pkg; + +-- This is prj2's foo.adb + +procedure Foo is +begin + for I in 1 .. 10 loop + Pkg.Do_Nothing; + end loop; +end Foo; diff --git a/testsuite/tests/OA16-009-exec-prefix/prj2/pkg.adb b/testsuite/tests/OA16-009-exec-prefix/prj2/pkg.adb new file mode 100644 index 000000000..899286010 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/prj2/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + procedure Do_Nothing is + begin + null; + end Do_Nothing; +end Pkg; diff --git a/testsuite/tests/OA16-009-exec-prefix/prj2/pkg.ads b/testsuite/tests/OA16-009-exec-prefix/prj2/pkg.ads new file mode 100644 index 000000000..0fca99536 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/prj2/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Do_Nothing; +end Pkg; diff --git a/testsuite/tests/OA16-009-exec-prefix/test.opt b/testsuite/tests/OA16-009-exec-prefix/test.opt new file mode 100644 index 000000000..1aa3b57f9 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test for --exec-prefix, which is useless without binary traces diff --git a/testsuite/tests/OA16-009-exec-prefix/test.py b/testsuite/tests/OA16-009-exec-prefix/test.py new file mode 100644 index 000000000..add496766 --- /dev/null +++ b/testsuite/tests/OA16-009-exec-prefix/test.py @@ -0,0 +1,60 @@ +"""Test that the --exec-prefix option is implemented properly.""" + +import os +import os.path +import shutil + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import (exename_for, tracename_for, gprfor, gprbuild, xrun, + xcov) + + +# This test needs a clean temporary directory because already existing files +# from previous testsuite runs will disturb the executable lookup process. +if os.path.exists('tmp_'): + shutil.rmtree('tmp_') +wd = Wdir('tmp_') + +# Build the two set of sources as two projects. Each one has its own object +# directory (which is the exec directory as well). +for src_dir in ('prj1', 'prj2'): + obj_dir = 'obj-{}'.format(src_dir) + gprbuild(gprfor(srcdirs=[os.path.join('..', src_dir)], + objdir=obj_dir, + exedir=obj_dir, + mains=['foo.adb'])) + +exename = exename_for('foo') +tracename = tracename_for('foo') + +prj1_exe = os.path.join('obj-prj1', exename) +prj2_exe = os.path.join('obj-prj2', exename) +doesnotexist_exe = os.path.join('doesnotexist', exename) + +# Generate traces and coverage report for prj2's foo.adb while there is a "foo" +# executable in the current directory: make sure it works on prj2's program by +# making sure we find prj2 source chunks in Xcov reports. +shutil.copy(prj1_exe, exename) +xrun([prj2_exe]) +xcov(['coverage', '--level=stmt', '--annotate=xcov', + '--scos={}'.format(os.path.join('obj-prj2', 'foo.ali')), + tracename]) +thistest.fail_if( + "This is prj2's foo.adb" not in contents_of('foo.adb.xcov'), + '"gnatcov coverage" did not use the correct program' +) + +# Now, when the provided path does not exists, make sure GNATcoverage does not +# find the executable in the current directory without the --exec-prefix +# option. +p = xrun([doesnotexist_exe], register_failure=False) +thistest.fail_if( + p.status == 0, + '"gnatcov run" found a program without --exec-prefix' +) + +# And finally make sure it finds the executable with --exec-prefix +p = xrun([doesnotexist_exe, '--exec-prefix=obj-prj2'], register_failure=True) + +thistest.result() diff --git a/testsuite/tests/OA16-009-windows-suffix/foo.adb b/testsuite/tests/OA16-009-windows-suffix/foo.adb new file mode 100644 index 000000000..f7b0acefa --- /dev/null +++ b/testsuite/tests/OA16-009-windows-suffix/foo.adb @@ -0,0 +1,4 @@ +procedure Foo is +begin + null; +end Foo; diff --git a/testsuite/tests/OA16-009-windows-suffix/test.opt b/testsuite/tests/OA16-009-windows-suffix/test.opt new file mode 100644 index 000000000..8a957cb72 --- /dev/null +++ b/testsuite/tests/OA16-009-windows-suffix/test.opt @@ -0,0 +1,2 @@ +bin-traces,windows +ALL DEAD This test variant has platform specific expectations and checks "gnatcov run" (bin traces specific) diff --git a/testsuite/tests/OA16-009-windows-suffix/test.py b/testsuite/tests/OA16-009-windows-suffix/test.py new file mode 100644 index 000000000..1e8c333e9 --- /dev/null +++ b/testsuite/tests/OA16-009-windows-suffix/test.py @@ -0,0 +1,30 @@ +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor, xcov, xrun + + +wd = Wdir("tmp_") +gprbuild(gprfor(srcdirs=[".."], mains=['foo.adb'])) + +# We want to check that "gnatcov run" will find the executable even though the +# input casing is different and even though it misses the ".exe" suffix. +os.rename('foo.exe', 'Foo.Exe') +xrun('foo') + +# Here, we also want to check that the default filename for the trace file is +# based on the actual filesystem name, not the name "gnatcov run" received in +# the command line. +xcov(['coverage', + '--level=stmt', '--annotate=xcov', + '--scos=obj\\foo.ali', + 'Foo.Exe.trace']) + +thistest.fail_if( + not os.path.exists('foo.adb.xcov'), + '"gnatcov coverage" did not produce a XCOV report for the main source' + ' file.' +) + +thistest.result() diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/.gitignore b/testsuite/tests/OA27-059-inlined-separate-cons/.gitignore new file mode 100644 index 000000000..4425349ca --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/.gitignore @@ -0,0 +1,5 @@ +bin +obj +obj1 +obj2 +tmp_ diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/pkg.gpr b/testsuite/tests/OA27-059-inlined-separate-cons/pkg.gpr new file mode 100644 index 000000000..5371325d3 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/pkg.gpr @@ -0,0 +1,5 @@ +project Pkg is + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + +end Pkg; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.adb b/testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.adb new file mode 100644 index 000000000..156fc47ee --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.adb @@ -0,0 +1,8 @@ +package body Helpers is + + function Id (I : Integer) return Integer is + begin + return I; + end Id; + +end Helpers; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.ads b/testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.ads new file mode 100644 index 000000000..a0e520804 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/src/helpers.ads @@ -0,0 +1,3 @@ +package Helpers is + function Id (I : Integer) return Integer; +end Helpers; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg-test_driver.adb b/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg-test_driver.adb new file mode 100644 index 000000000..ba02473b0 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg-test_driver.adb @@ -0,0 +1,5 @@ +separate (Pkg) +procedure Test_Driver is +begin + null; +end Test_Driver; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.adb b/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.adb new file mode 100644 index 000000000..7f459a706 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.adb @@ -0,0 +1,14 @@ +package body Pkg is + + function Is_Even (I : Integer) return Boolean is + begin + if I mod 2 = 0 then + return True; + else + return False; + end if; + end Is_Even; + + procedure Test_Driver is separate; + +end Pkg; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.ads b/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.ads new file mode 100644 index 000000000..c374bba3e --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/src/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + function Is_Even (I : Integer) return Boolean; + procedure Test_Driver; +end Pkg; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test.py b/testsuite/tests/OA27-059-inlined-separate-cons/test.py new file mode 100644 index 000000000..888d8c3c3 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test.py @@ -0,0 +1,111 @@ +""" +Test that we have no consolidation error in source coverage for two binaries +that bring different versions of the same separate procedure. The separate +procedure is part of an unit of interest, but the coverage campaign ignores the +separate itself. +""" + +import os +import os.path +import shutil + +from SCOV.minicheck import (build_run_and_coverage, checked_xcov, + check_xcov_reports) +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import tracename_for, xcov + + +wd = Wdir('tmp_') + + +class Testcase(object): + def __init__(self, name, objdir): + self.name = name + self._objdir = objdir + + @property + def project_file(self): + return os.path.join('..', '{}.gpr'.format(self.name)) + + @property + def main(self): + return 'main_{}'.format(self.name) + + def obj_dir(self, *args): + return os.path.join('..', self._objdir, *args) + + def exe_dir(self, *args): + return os.path.join('..', 'bin', *args) + + @property + def tracename(self): + return tracename_for('main_{}'.format(self.name)) + + @property + def checkpoint(self): + return '{}.ckpt'.format(self.name) + + +def clean_output_directory(): + if os.path.exists('output'): + shutil.rmtree('output') + os.mkdir('output') + + +test1 = Testcase('test1', 'obj1') +test2 = Testcase('test2', 'obj2') +testcases = [test1, test2] + +covlevel = 'stmt+decision' +extra_args = ['--units=pkg'], +output_arg = '--output-dir=output' + + +# Build the test material (program and traces) and produce checkpoints +for testcase in testcases: + thistest.log(f"== {testcase.name} ==") + build_run_and_coverage( + gprsw=GPRswitches(root_project=testcase.project_file, units=['pkg']), + covlevel=covlevel, + mains=[testcase.main], + ignored_source_files=['pkg-test_driver.adb'], + gpr_obj_dir=testcase.obj_dir(), + gpr_exe_dir=testcase.exe_dir(), + extra_coverage_args=['--save-checkpoint', testcase.checkpoint], + out='ckpt-{}.log'.format(testcase.name), + scos_for_run=False) + +# When inlining is enabled, consolidation without checkpoints cannot work, even +# with --ignore-source-files. +if ( + thistest.options.trace_mode == 'bin' and + '-O1' in thistest.suite_cargs_for('Ada') +): + p = xcov(['coverage', '-c', covlevel, '--annotate=report', output_arg, + test1.tracename, test2.tracename]) + thistest.fail_if( + p.status == 0, + '"gnatcov coverage" is supposed to complain about different symbols' + ' during consolidation, but it did not.' + ) + +# Check that consolidation behaves as expected with the --ignore-source-files +# switch: expected number of reports and expected report content. +clean_output_directory() +checked_xcov(['coverage', '-c', covlevel, '--annotate=xcov', output_arg, + '-C', test1.checkpoint, + '-C', test2.checkpoint], + 'cons.log') + +# Finally, check we have the expected reports +check_xcov_reports( + os.path.join('output', '*.xcov'), + { + os.path.join('output', 'pkg.adb.xcov'): { + '+': {5, 6, 8}, + }, + } +) +thistest.result() diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test1.gpr b/testsuite/tests/OA27-059-inlined-separate-cons/test1.gpr new file mode 100644 index 000000000..59494366d --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test1.gpr @@ -0,0 +1,7 @@ +project Test1 extends "pkg.gpr" is + for Source_Dirs use ("test1"); + for Main use ("main_test1.adb"); + for Exec_Dir use "bin"; + for Object_Dir use "obj1"; + +end Test1; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test1/main_test1.adb b/testsuite/tests/OA27-059-inlined-separate-cons/test1/main_test1.adb new file mode 100644 index 000000000..bed186fbb --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test1/main_test1.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_Test1 is +begin + Pkg.Test_Driver; +end Main_Test1; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test1/pkg-test_driver.adb b/testsuite/tests/OA27-059-inlined-separate-cons/test1/pkg-test_driver.adb new file mode 100644 index 000000000..b441fe324 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test1/pkg-test_driver.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Helpers; + +separate (Pkg) +procedure Test_Driver is +begin + if not Is_Even (Helpers.Id (0)) then + Put_Line ("Error!"); + end if; +end Test_Driver; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test2.gpr b/testsuite/tests/OA27-059-inlined-separate-cons/test2.gpr new file mode 100644 index 000000000..0dc0d50a5 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test2.gpr @@ -0,0 +1,7 @@ +project Test2 extends "pkg.gpr" is + for Source_Dirs use ("test2"); + for Main use ("main_test2.adb"); + for Exec_Dir use "bin"; + for Object_Dir use "obj2"; + +end Test2; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test2/main_test2.adb b/testsuite/tests/OA27-059-inlined-separate-cons/test2/main_test2.adb new file mode 100644 index 000000000..4df94b631 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test2/main_test2.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_Test2 is +begin + Pkg.Test_Driver; +end Main_Test2; diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test2/pkg-test_driver.adb b/testsuite/tests/OA27-059-inlined-separate-cons/test2/pkg-test_driver.adb new file mode 100644 index 000000000..83c43eba6 --- /dev/null +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test2/pkg-test_driver.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Helpers; + +separate (Pkg) +procedure Test_Driver is + +begin + + if Is_Even (Helpers.Id (Helpers.Id (1))) then + Put_Line ("Error!"); + end if; + +end Test_Driver; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/.gitignore b/testsuite/tests/OA27-059-sep-cons-prj-override/.gitignore new file mode 100644 index 000000000..4425349ca --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/.gitignore @@ -0,0 +1,5 @@ +bin +obj +obj1 +obj2 +tmp_ diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/pkg_under_test.gpr b/testsuite/tests/OA27-059-sep-cons-prj-override/pkg_under_test.gpr new file mode 100644 index 000000000..e46233907 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/pkg_under_test.gpr @@ -0,0 +1,16 @@ +project Pkg_Under_Test is + + for Source_Dirs use ("src_under_test"); + for Exec_Dir use "bin"; + for Object_Dir use "obj"; + + package Coverage is + for Switches ("Coverage") use + ("--level=stmt+decision", "--annotate=xcov"); + for Switches ("Instrument") use ("--level=stmt+decision"); + for Units use ("Pkg_Under_Test"); + for Ignored_Source_Files use ("pkg_under_test-some_procedure.adb"); + end Coverage; + + +end Pkg_Under_Test; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..fc818434d --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-pkg_test.adb @@ -0,0 +1,6 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is +begin + null; +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-some_procedure.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-some_procedure.adb new file mode 100644 index 000000000..4c6a7306c --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test-some_procedure.adb @@ -0,0 +1,6 @@ +separate (Pkg_Under_Test) + +procedure Some_Procedure is +begin + null; +end Some_Procedure; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.adb new file mode 100644 index 000000000..d2290fb5f --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.adb @@ -0,0 +1,17 @@ +with ADA.TEXT_IO; + +package body PKG_UNDER_TEST is + + procedure PROC_UNDER_TEST (A : in Integer) is + begin + if (A > 10) then + ADA.TEXT_IO.PUT_LINE ("A is over 10"); + else + ADA.TEXT_IO.PUT_LINE ("A is under 10"); + end if; + end PROC_UNDER_TEST; + + procedure PKG_TEST is separate; + procedure Some_Procedure is separate; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.ads b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.ads new file mode 100644 index 000000000..3d7431733 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/src_under_test/pkg_under_test.ads @@ -0,0 +1,6 @@ +package PKG_UNDER_TEST is + + procedure PKG_TEST; + procedure Some_Procedure; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test.py b/testsuite/tests/OA27-059-sep-cons-prj-override/test.py new file mode 100644 index 000000000..a2dee0c00 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test.py @@ -0,0 +1,119 @@ +""" +Using similar material as for OA27-059-separate-consolidation, test that the +Coverage'Ignore_Source_Files project attribute is overidden by the +--ignore-source-files command line argument. +""" + +import os.path + +from e3.fs import mkdir, rm, sync_tree + +from SCOV.minicheck import build_and_run, checked_xcov, check_xcov_reports +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild + + +wd = Wdir('tmp_') + +# Copy project sources in the temporary director +for f in [ + 'pkg_under_test.gpr', + 'src_under_test', + 'test1', + 'test1.gpr', + 'test2', + 'test2.gpr' +]: + sync_tree(os.path.join('..', f), f) + + +class Testcase(object): + def __init__(self, name, objdir): + self.name = name + self._objdir = objdir + + @property + def project_file(self): + return f'{self.name}.gpr' + + @property + def main(self): + return f'main_{self.name}' + + def obj_dir(self, *args): + return os.path.join(self._objdir, *args) + + def exe_dir(self, *args): + return os.path.join('bin', *args) + + +def clean_output_directory(): + rm('output') + mkdir('output') + + +test1 = Testcase('test1', 'obj1') +test2 = Testcase('test2', 'obj2') +testcases = [test1, test2] +gprsw_for_cov = GPRswitches(root_project='pkg_under_test.gpr') + +# The goal of this testcase is to check that the --ignore-source-files +# command-line argument, when provided, takes precedence over the +# Coverage'Ignored_Source_Files project attribute. +# +# In pkg_under_test.gpr, that attribute is defined so that +# pkg_under_test-some_procedure.adb is ignored. To check that +# --ignore-source-files take precedence, we pass it to ignore only +# pkg_under_test-pkg_test.adb, so that pkg_under_test-some_procedure.adb +# should show up in coverage reports. +overriding_ignored_source_file = 'pkg_under_test-pkg_test.adb' + +# Build the test material: program and traces +trace_files = [] +for testcase in testcases: + xcov_args = build_and_run( + gprsw=GPRswitches(root_project=testcase.project_file), + covlevel=None, + mains=[testcase.main], + gpr_obj_dir=testcase.obj_dir(), + gpr_exe_dir=testcase.exe_dir(), + extra_coverage_args=[], + ignored_source_files=[overriding_ignored_source_file], + gprsw_for_coverage=gprsw_for_cov, + scos_for_run=False, + ) + trace_files.append(xcov_args.pop()) + +# This testcase builds extending projects and then runs gnatcov on the extended +# project. This requires the extended project to have its own ALI/SID files, so +# build this project (in binary trace mode, to get ALI files) or instrument it +# (in source trace mode, to get SID files). Since instrumentation uses the +# "ignore source files" information, we also need to pass --ignore-source-files +# here. +if thistest.options.trace_mode == 'bin': + gprbuild(gprsw_for_cov.root_project) +else: + xcov_instrument( + gprsw=gprsw_for_cov, + covlevel=None, + extra_args=[f'--ignore-source-files={overriding_ignored_source_file}'], + ) + +# The presence of pkg_under_test-some_procedure.adb and the absence of +# pkg_under_test-pkg_test.adb prove that --ignored-source-files took +# precedence over the Coverage'Ignored_Source_Files project attribute. +clean_output_directory() +p = checked_xcov(xcov_args + ['--output-dir=output'] + trace_files, 'cons.log') +check_xcov_reports( + '*.xcov', + { + 'pkg_under_test.adb.xcov': {'+': {7, 8, 10}}, + 'pkg_under_test-some_procedure.adb.xcov': {'-': {5}}, + }, + 'output', +) + +thistest.result() diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test1.gpr b/testsuite/tests/OA27-059-sep-cons-prj-override/test1.gpr new file mode 100644 index 000000000..5e0c3f34b --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test1.gpr @@ -0,0 +1,8 @@ +project Test1 extends "pkg_under_test" is + + for Source_Dirs use ("test1"); + for Main use ("main_test1.adb"); + for Exec_Dir use "bin"; + for Object_Dir use "obj1"; + +end Test1; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test1/main_test1.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/test1/main_test1.adb new file mode 100644 index 000000000..f43dbb391 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test1/main_test1.adb @@ -0,0 +1,8 @@ +with PKG_UNDER_TEST; + +procedure MAIN_TEST1 is +begin + + PKG_UNDER_TEST.PKG_TEST; + +end MAIN_TEST1; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test1/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/test1/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..91abb676b --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test1/pkg_under_test-pkg_test.adb @@ -0,0 +1,10 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is + +begin + + PROC_UNDER_TEST(5); + PROC_UNDER_TEST(7); + +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test2.gpr b/testsuite/tests/OA27-059-sep-cons-prj-override/test2.gpr new file mode 100644 index 000000000..ddd07adc3 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test2.gpr @@ -0,0 +1,8 @@ +project Test2 extends "pkg_under_test" is + + for Source_Dirs use ("test2"); + for Main use ("main_test2.adb"); + for Exec_Dir use "bin"; + for Object_Dir use "obj2"; + +end Test2; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test2/main_test2.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/test2/main_test2.adb new file mode 100644 index 000000000..9f2707841 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test2/main_test2.adb @@ -0,0 +1,8 @@ +with PKG_UNDER_TEST; + +procedure MAIN_TEST2 is +begin + + PKG_UNDER_TEST.PKG_TEST; + +end MAIN_TEST2; diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test2/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-sep-cons-prj-override/test2/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..546a5d974 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test2/pkg_under_test-pkg_test.adb @@ -0,0 +1,9 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is + +begin + + PROC_UNDER_TEST(15); + +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/.gitignore b/testsuite/tests/OA27-059-sep-cons-prj/.gitignore new file mode 100644 index 000000000..4425349ca --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/.gitignore @@ -0,0 +1,5 @@ +bin +obj +obj1 +obj2 +tmp_ diff --git a/testsuite/tests/OA27-059-sep-cons-prj/pkg_under_test.gpr b/testsuite/tests/OA27-059-sep-cons-prj/pkg_under_test.gpr new file mode 100644 index 000000000..e6ede6f6c --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/pkg_under_test.gpr @@ -0,0 +1,16 @@ +project Pkg_Under_Test is + + for Source_Dirs use ("src_under_test"); + for Exec_Dir use "bin"; + for Object_Dir use "obj"; + + package Coverage is + for Switches ("Coverage") use + ("--level=stmt+decision", "--annotate=xcov"); + for Switches ("Instrument") use ("--level=stmt+decision"); + for Units use ("Pkg_Under_Test"); + for Ignored_Source_Files use ("pkg_under_test-pkg_test.adb"); + end Coverage; + + +end Pkg_Under_Test; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..fc818434d --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test-pkg_test.adb @@ -0,0 +1,6 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is +begin + null; +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.adb b/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.adb new file mode 100644 index 000000000..87089da4d --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.adb @@ -0,0 +1,17 @@ +with ADA.TEXT_IO; + +package body PKG_UNDER_TEST is + + procedure PROC_UNDER_TEST (A : in Integer) is + begin + if (A > 10) then + ADA.TEXT_IO.PUT_LINE ("A is over 10"); + else + ADA.TEXT_IO.PUT_LINE ("A is under 10"); + end if; + end PROC_UNDER_TEST; + + + procedure PKG_TEST is separate; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.ads b/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.ads new file mode 100644 index 000000000..9ca0a0d9b --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/src_under_test/pkg_under_test.ads @@ -0,0 +1,5 @@ +package PKG_UNDER_TEST is + + procedure PKG_TEST; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test.py b/testsuite/tests/OA27-059-sep-cons-prj/test.py new file mode 100644 index 000000000..9eb4f0c3a --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test.py @@ -0,0 +1,95 @@ +""" +Using similar material as for OA27-059-separate-consolidation, test that the +Coverage'Ignore_Source_Files project attribute is handled correctly. +""" + +import os.path + +from e3.fs import mkdir, rm, sync_tree + +from SCOV.minicheck import build_and_run, checked_xcov, check_xcov_reports +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild + + +wd = Wdir('tmp_') + +# Copy project sources in the temporary director +for f in [ + 'pkg_under_test.gpr', + 'src_under_test', + 'test1', + 'test1.gpr', + 'test2', + 'test2.gpr' +]: + sync_tree(os.path.join('..', f), f) + + +class Testcase(object): + def __init__(self, name, objdir): + self.name = name + self._objdir = objdir + + @property + def project_file(self): + return f'{self.name}.gpr' + + @property + def main(self): + return f'main_{self.name}' + + def obj_dir(self, *args): + return os.path.join(self._objdir, *args) + + def exe_dir(self, *args): + return os.path.join('bin', *args) + + +def clean_output_directory(): + rm('output') + mkdir('output') + + +test1 = Testcase('test1', 'obj1') +test2 = Testcase('test2', 'obj2') +testcases = [test1, test2] +gprsw_for_cov = GPRswitches(root_project='pkg_under_test.gpr') + +# Build the test material: program and traces +trace_files = [] +for testcase in testcases: + xcov_args = build_and_run( + gprsw=GPRswitches(root_project=testcase.project_file), + covlevel=None, + mains=[testcase.main], + gpr_obj_dir=testcase.obj_dir(), + gpr_exe_dir=testcase.exe_dir(), + extra_coverage_args=[], + gprsw_for_coverage=gprsw_for_cov, + scos_for_run=False, + ) + trace_files.append(xcov_args.pop()) + +# This testcase builds extending projects and then runs gnatcov on the extended +# project. This requires the extended project to have its own ALI/SID files, so +# build this project (in binary trace mode, to get ALI files) or instrument it +# (in source trace mode, to get SID files). +if thistest.options.trace_mode == 'bin': + gprbuild(gprsw_for_cov.root_project) +else: + xcov_instrument(gprsw=gprsw_for_cov, covlevel=None) + +# Check that the Ignore_Source_Files project attribute makes gnatcov ignore the +# conflicting symbols between test1 and test2, and succeeds to create a report +# with the expected coverage data. +clean_output_directory() +p = checked_xcov(xcov_args + ['--output-dir=output'] + trace_files, 'cons.log') +check_xcov_reports( + '*.xcov', {'pkg_under_test.adb.xcov': {'+': {7, 8, 10}}}, 'output' +) + +thistest.result() diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test1.gpr b/testsuite/tests/OA27-059-sep-cons-prj/test1.gpr new file mode 100644 index 000000000..5e0c3f34b --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test1.gpr @@ -0,0 +1,8 @@ +project Test1 extends "pkg_under_test" is + + for Source_Dirs use ("test1"); + for Main use ("main_test1.adb"); + for Exec_Dir use "bin"; + for Object_Dir use "obj1"; + +end Test1; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test1/main_test1.adb b/testsuite/tests/OA27-059-sep-cons-prj/test1/main_test1.adb new file mode 100644 index 000000000..f43dbb391 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test1/main_test1.adb @@ -0,0 +1,8 @@ +with PKG_UNDER_TEST; + +procedure MAIN_TEST1 is +begin + + PKG_UNDER_TEST.PKG_TEST; + +end MAIN_TEST1; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test1/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-sep-cons-prj/test1/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..91abb676b --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test1/pkg_under_test-pkg_test.adb @@ -0,0 +1,10 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is + +begin + + PROC_UNDER_TEST(5); + PROC_UNDER_TEST(7); + +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test2.gpr b/testsuite/tests/OA27-059-sep-cons-prj/test2.gpr new file mode 100644 index 000000000..ddd07adc3 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test2.gpr @@ -0,0 +1,8 @@ +project Test2 extends "pkg_under_test" is + + for Source_Dirs use ("test2"); + for Main use ("main_test2.adb"); + for Exec_Dir use "bin"; + for Object_Dir use "obj2"; + +end Test2; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test2/main_test2.adb b/testsuite/tests/OA27-059-sep-cons-prj/test2/main_test2.adb new file mode 100644 index 000000000..9f2707841 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test2/main_test2.adb @@ -0,0 +1,8 @@ +with PKG_UNDER_TEST; + +procedure MAIN_TEST2 is +begin + + PKG_UNDER_TEST.PKG_TEST; + +end MAIN_TEST2; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test2/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-sep-cons-prj/test2/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..546a5d974 --- /dev/null +++ b/testsuite/tests/OA27-059-sep-cons-prj/test2/pkg_under_test-pkg_test.adb @@ -0,0 +1,9 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is + +begin + + PROC_UNDER_TEST(15); + +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-separate-consolidation/pkg_under_test.gpr b/testsuite/tests/OA27-059-separate-consolidation/pkg_under_test.gpr new file mode 100644 index 000000000..381f24b46 --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/pkg_under_test.gpr @@ -0,0 +1,8 @@ +project PKG_UNDER_TEST is + + for SOURCE_DIRS use ("src_under_test"); + + for EXEC_DIR use "bin"; + for OBJECT_DIR use "obj"; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.adb b/testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.adb new file mode 100644 index 000000000..87089da4d --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.adb @@ -0,0 +1,17 @@ +with ADA.TEXT_IO; + +package body PKG_UNDER_TEST is + + procedure PROC_UNDER_TEST (A : in Integer) is + begin + if (A > 10) then + ADA.TEXT_IO.PUT_LINE ("A is over 10"); + else + ADA.TEXT_IO.PUT_LINE ("A is under 10"); + end if; + end PROC_UNDER_TEST; + + + procedure PKG_TEST is separate; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.ads b/testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.ads new file mode 100644 index 000000000..9ca0a0d9b --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/src_under_test/pkg_under_test.ads @@ -0,0 +1,5 @@ +package PKG_UNDER_TEST is + + procedure PKG_TEST; + +end PKG_UNDER_TEST; diff --git a/testsuite/tests/OA27-059-separate-consolidation/test.opt b/testsuite/tests/OA27-059-separate-consolidation/test.opt new file mode 100644 index 000000000..f99af998d --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test.opt @@ -0,0 +1 @@ +!bin-traces XFAIL SB12-022: trouble with GPR's Main attribute diff --git a/testsuite/tests/OA27-059-separate-consolidation/test.py b/testsuite/tests/OA27-059-separate-consolidation/test.py new file mode 100644 index 000000000..f130d1fca --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test.py @@ -0,0 +1,105 @@ +""" +Test that we have no consolidation error in source coverage for two binaries +that bring different versions of the same separate procedure. The separate +procedure is part of an unit of interest, but the coverage campaign ignores the +separate itself. +""" + +import os +import os.path +import shutil + +from SCOV.minicheck import build_and_run, checked_xcov, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + + +# Clean up projects build artifacts +for obj_dir in ('bin', 'obj1', 'obj2'): + if os.path.exists(obj_dir): + shutil.rmtree(obj_dir) + +wd = Wdir('tmp_') + + +class Testcase(object): + def __init__(self, name, objdir): + self.name = name + self._objdir = objdir + + @property + def project_file(self): + return os.path.join('..', '{}.gpr'.format(self.name)) + + @property + def main(self): + return 'main_{}'.format(self.name) + + def obj_dir(self, *args): + return os.path.join('..', self._objdir, *args) + + def exe_dir(self, *args): + return os.path.join('..', 'bin', *args) + + +def clean_output_directory(): + if os.path.exists('output'): + shutil.rmtree('output') + os.mkdir('output') + + +test1 = Testcase('test1', 'obj1') +test2 = Testcase('test2', 'obj2') +testcases = [test1, test2] + + +def build_and_run_tests(ignored_source_files=[]): + """ + Build the test material: program and traces. + """ + trace_files = [] + for testcase in testcases: + xcov_args = build_and_run( + gprsw=GPRswitches(root_project=testcase.project_file, + units=['pkg_under_test']), + covlevel='stmt+decision', + mains=[testcase.main], + ignored_source_files=ignored_source_files, + gpr_obj_dir=testcase.obj_dir(), + gpr_exe_dir=testcase.exe_dir(), + extra_coverage_args=['--annotate=xcov', '--output-dir=output'], + scos_for_run=False) + trace_files.append(xcov_args.pop()) + + return xcov_args + trace_files + + +# Build and run tests without ignored source files. Check that we indeed have a +# consolidation error by default. +clean_output_directory() +xcov_args = build_and_run_tests() +p = xcov(xcov_args, out='cons-1.log', register_failure=False) +thistest.fail_if( + p.status == 0, + '"gnatcov coverage" is supposed to complain about different symbols during' + ' consolidation, but it did not.' +) + +# Build and run tests with ignored source files. Check that the new option +# makes it ignore the problematic symbols, and succeeds to create a report with +# the expected coverage data. +clean_output_directory() +xcov_args = build_and_run_tests(['pkg_under_test-pkg_test.adb']) +p = checked_xcov(xcov_args, 'cons-2.log') +check_xcov_reports( + os.path.join('output', '*.xcov'), + { + os.path.join('output', 'pkg_under_test.adb.xcov'): { + '+': {7, 8, 10}, + } + } +) + +thistest.result() diff --git a/testsuite/tests/OA27-059-separate-consolidation/test1.gpr b/testsuite/tests/OA27-059-separate-consolidation/test1.gpr new file mode 100644 index 000000000..bb4754a75 --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test1.gpr @@ -0,0 +1,10 @@ +project TEST1 is + + for SOURCE_DIRS use ("src_under_test", "test1"); + + for MAIN use ("main_test1.adb"); + + for EXEC_DIR use "bin"; + for OBJECT_DIR use "obj1"; + +end TEST1; diff --git a/testsuite/tests/OA27-059-separate-consolidation/test1/main_test1.adb b/testsuite/tests/OA27-059-separate-consolidation/test1/main_test1.adb new file mode 100644 index 000000000..f43dbb391 --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test1/main_test1.adb @@ -0,0 +1,8 @@ +with PKG_UNDER_TEST; + +procedure MAIN_TEST1 is +begin + + PKG_UNDER_TEST.PKG_TEST; + +end MAIN_TEST1; diff --git a/testsuite/tests/OA27-059-separate-consolidation/test1/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-separate-consolidation/test1/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..91abb676b --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test1/pkg_under_test-pkg_test.adb @@ -0,0 +1,10 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is + +begin + + PROC_UNDER_TEST(5); + PROC_UNDER_TEST(7); + +end PKG_TEST; diff --git a/testsuite/tests/OA27-059-separate-consolidation/test2.gpr b/testsuite/tests/OA27-059-separate-consolidation/test2.gpr new file mode 100644 index 000000000..2cca9363d --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test2.gpr @@ -0,0 +1,10 @@ +project TEST2 is + + for SOURCE_DIRS use ("src_under_test", "test2"); + + for MAIN use ("main_test2"); + + for EXEC_DIR use "bin"; + for OBJECT_DIR use "obj2"; + +end TEST2; diff --git a/testsuite/tests/OA27-059-separate-consolidation/test2/main_test2.adb b/testsuite/tests/OA27-059-separate-consolidation/test2/main_test2.adb new file mode 100644 index 000000000..9f2707841 --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test2/main_test2.adb @@ -0,0 +1,8 @@ +with PKG_UNDER_TEST; + +procedure MAIN_TEST2 is +begin + + PKG_UNDER_TEST.PKG_TEST; + +end MAIN_TEST2; diff --git a/testsuite/tests/OA27-059-separate-consolidation/test2/pkg_under_test-pkg_test.adb b/testsuite/tests/OA27-059-separate-consolidation/test2/pkg_under_test-pkg_test.adb new file mode 100644 index 000000000..546a5d974 --- /dev/null +++ b/testsuite/tests/OA27-059-separate-consolidation/test2/pkg_under_test-pkg_test.adb @@ -0,0 +1,9 @@ +separate (PKG_UNDER_TEST) + +procedure PKG_TEST is + +begin + + PROC_UNDER_TEST(15); + +end PKG_TEST; diff --git a/testsuite/tests/OB23-036/foo.adb b/testsuite/tests/OB23-036/foo.adb new file mode 100644 index 000000000..f7b0acefa --- /dev/null +++ b/testsuite/tests/OB23-036/foo.adb @@ -0,0 +1,4 @@ +procedure Foo is +begin + null; +end Foo; diff --git a/testsuite/tests/OB23-036/test.py b/testsuite/tests/OB23-036/test.py new file mode 100644 index 000000000..9d1929661 --- /dev/null +++ b/testsuite/tests/OB23-036/test.py @@ -0,0 +1,28 @@ +""" +Test that "gnatcov disp-routines" command does not crash with twice the same +program. +""" + +import os +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import exename_for, gprbuild, gprfor, xcov + + +wd = Wdir('tmp_') + +gprbuild(gprfor(srcdirs=[os.path.join(wd.homedir)], + mains=['foo.adb'])) +exename = exename_for('foo') + +xcov(['disp-routines', + '--include', exename, + '--exclude', exename], out='disp-routines.out') +thistest.fail_if( + contents_of('disp-routines.out') != '', + '"gnatcov disp-routines" did not yield the expected list of routines' +) + +thistest.result() diff --git a/testsuite/tests/OB26-040-type-invariants/Aspects/src/tcheck.ads b/testsuite/tests/OB26-040-type-invariants/Aspects/src/tcheck.ads new file mode 100644 index 000000000..d53e7a32a --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Aspects/src/tcheck.ads @@ -0,0 +1,38 @@ +pragma Ada_2012; + +package Tcheck is + pragma Assertion_Policy (Invariant => Check, Type_Invariant => Check); + + type Int (UB : Integer) is tagged record + Value : Integer := UB; + end record; + + -- In type names, I stands for Invariant, TI for Type_Invariant, + -- S for Simple, C for Complex + + type SI is new Int with private; + type CI is new Int with private; + type STI is new Int with private; + type CTI is new Int with private; + +private + + -- Invariant Aspects, Simple then Complex + + type SI is new Int with null record + with Invariant => SI.Value <= SI.UB; -- # si + + type CI is new Int with null record + with Invariant => + CI.Value <= CI.UB and then CI.Value > 0; -- # ci + + -- Type_Invariant Aspects, Simple then Complex + + type STI is new Int with null record + with Type_Invariant => STI.Value > 0; -- # si + + type CTI is new Int with null record + with Type_Invariant => + CTI.Value <= CTI.UB and then CTI.Value > 0; -- # ci + +end; diff --git a/testsuite/tests/OB26-040-type-invariants/Aspects/src/tnocheck.ads b/testsuite/tests/OB26-040-type-invariants/Aspects/src/tnocheck.ads new file mode 100644 index 000000000..d5ac47bc6 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Aspects/src/tnocheck.ads @@ -0,0 +1,26 @@ +pragma Ada_2012; + +package Tnocheck is + pragma Assertion_Policy (Invariant => Disable, Type_Invariant => Disable); + + type Int (UB : Integer) is tagged record + Value : Integer := UB; + end record; + + -- In type names, I stands for Invariant, TI for Type_Invariant, + -- S for Simple, C for Complex + + type SI is new Int with private; + type STI is new Int with private; + +private + + -- Invariant and Type_Invariant Aspects, Simple + + type SI is new Int with null record + with Invariant => SI.Value <= SI.UB; -- # si + + type STI is new Int with null record + with Type_Invariant => STI.Value > 0; -- # si + +end; diff --git a/testsuite/tests/OB26-040-type-invariants/Aspects/test.opt b/testsuite/tests/OB26-040-type-invariants/Aspects/test.opt new file mode 100644 index 000000000..99c8cf2cb --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Aspects/test.opt @@ -0,0 +1 @@ +7.1.2 DEAD assertion policy pragma in package not supported in 7.1.2 \ No newline at end of file diff --git a/testsuite/tests/OB26-040-type-invariants/Aspects/test.py b/testsuite/tests/OB26-040-type-invariants/Aspects/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Aspects/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/test_t.adb b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/test_t.adb new file mode 100644 index 000000000..423dd2440 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/test_t.adb @@ -0,0 +1,19 @@ +with Types_A; use Types_A; + +procedure Test_T is + SIO : SI (UB => 5); + CIO : CI (UB => 2); + STIO : STI (UB => 10); + CTIO : CTI (UB => 4); + +begin + null; +end; + +--# types_a.ads +-- /base/ l! ## dF- +-- /si/ l! ## dF- +-- /ci/ l! ## dF- +-- /sti/ l! ## dF- +-- /cti/ l! ## dF- + diff --git a/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.adb b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.adb new file mode 100644 index 000000000..860fe450d --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.adb @@ -0,0 +1,8 @@ +package body Types_A is + + function Valid (X : Int) return Boolean is + begin + return X.Value <= X.UB; + end; + +end; diff --git a/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.ads b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.ads new file mode 100644 index 000000000..e4f1b9c88 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.ads @@ -0,0 +1,41 @@ +pragma Ada_2012; + +package Types_A is + pragma Assertion_Policy (Invariant => Check, Type_Invariant => Check); + + type Int (UB : Integer) is tagged private + with Type_Invariant'Class => Valid (Int); -- # base + + function Valid (X : Int) return Boolean; + + -- In type names, I stands for Invariant, TI for Type_Invariant, + -- S for Simple, C for Complex + + type SI is new Int with private; + type CI is new Int with private; + type STI is new Int with private; + type CTI is new Int with private; + +private + + type Int (UB : Integer) is tagged record + Value : Integer := UB; + end record; + + -- Invariant Aspects, Simple then Complex + + type SI is new Int with null record + with Invariant => SI.Value > 0; -- # si + + type CI is new Int with null record + with Invariant => CI.Value > 0; -- # ci + + -- Type_Invariant Aspects, Simple then Complex + + type STI is new Int with null record + with Type_Invariant => STI.Value > 0; -- # sti + + type CTI is new Int with null record + with Type_Invariant => CTI.Value > 0; -- # cti + +end; diff --git a/testsuite/tests/OB26-040-type-invariants/InvariantClass/test.opt b/testsuite/tests/OB26-040-type-invariants/InvariantClass/test.opt new file mode 100644 index 000000000..e248e7893 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/InvariantClass/test.opt @@ -0,0 +1 @@ +ALL SKIP processing of Invariant_Class aspects, not defined yet diff --git a/testsuite/tests/OB26-040-type-invariants/InvariantClass/test.py b/testsuite/tests/OB26-040-type-invariants/InvariantClass/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/InvariantClass/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/OB26-040-type-invariants/Pragmas/src/tcheck.ads b/testsuite/tests/OB26-040-type-invariants/Pragmas/src/tcheck.ads new file mode 100644 index 000000000..1529c8292 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Pragmas/src/tcheck.ads @@ -0,0 +1,40 @@ +pragma Ada_2012; + +package TCheck is + pragma Assertion_Policy (Invariant => Check, Type_Invariant => Check); + + type Int (UB : Integer) is tagged record + Value : Integer := UB; + end record; + + -- In type names, I stands for Invariant, TI for Type_Invariant, + -- S for Simple, C for Complex. + + type SI is new Int with private; + type CI is new Int with private; + type STI is new Int with private; + type CTI is new Int with private; + +private + + -- Invariant Pragmas, Simple then Complex + + type SI is new Int with null record; + pragma Invariant + (SI, Check => SI.Value <= SI.UB); -- # si + + type CI is new Int with null record; + pragma Invariant + (CI, Check => CI.Value <= CI.UB and then CI.Value > 0); -- # ci + + -- Type_Invariant Pragmas, Simple then Complex + + type STI is new Int with null record; + pragma Type_Invariant + (STI, Check => STI.Value <= STI.UB); -- # si + + type CTI is new Int with null record; + pragma Type_Invariant + (CTI, Check => CTI.Value <= CTI.UB and then CTI.Value > 0); -- # ci + +end; diff --git a/testsuite/tests/OB26-040-type-invariants/Pragmas/src/tnocheck.ads b/testsuite/tests/OB26-040-type-invariants/Pragmas/src/tnocheck.ads new file mode 100644 index 000000000..c092cd08f --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Pragmas/src/tnocheck.ads @@ -0,0 +1,26 @@ +pragma Ada_2012; + +package TNocheck is + pragma Assertion_Policy (Invariant => Ignore, Type_Invariant => Ignore); + + type Int (UB : Integer) is tagged record + Value : Integer; + end record; + + -- In type names, I stands for Invariant, TI for Type_Invariant, + -- S for Simple, C for Complex. + + type SI is new Int with private; + type STI is new Int with private; + +private + + type SI is new Int with null record; + pragma Invariant + (SI, Check => SI.Value <= SI.UB); -- # si + + type STI is new Int with null record; + pragma Type_Invariant + (STI, Check => STI.Value <= STI.UB); -- # si + +end; diff --git a/testsuite/tests/OB26-040-type-invariants/Pragmas/test.opt b/testsuite/tests/OB26-040-type-invariants/Pragmas/test.opt new file mode 100644 index 000000000..99c8cf2cb --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Pragmas/test.opt @@ -0,0 +1 @@ +7.1.2 DEAD assertion policy pragma in package not supported in 7.1.2 \ No newline at end of file diff --git a/testsuite/tests/OB26-040-type-invariants/Pragmas/test.py b/testsuite/tests/OB26-040-type-invariants/Pragmas/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/Pragmas/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/OB26-040-type-invariants/extra.opt b/testsuite/tests/OB26-040-type-invariants/extra.opt new file mode 100644 index 000000000..ee78ca999 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD extension declarations not available in 5.04 diff --git a/testsuite/tests/OB26-040-type-invariants/src/test_tcheck_t.adb b/testsuite/tests/OB26-040-type-invariants/src/test_tcheck_t.adb new file mode 100644 index 000000000..90f283c6c --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/src/test_tcheck_t.adb @@ -0,0 +1,20 @@ +with tcheck; use tCheck; + +procedure Test_tCheck_T is + SIO : SI (UB => 5); + CIO : CI (UB => 2); + STIO : STI (UB => 10); + CTIO : CTI (UB => 4); + +begin + null; +end; + +--# tcheck.ads +-- +--%opts: --trace-mode=bin +-- /si/ l! ## dF- +-- /ci/ l! ## dF- +-- +-- In source-traces mode, we do not emit coverage obligations for the +-- pragmas by default, as we don't know what the assertion policy is. diff --git a/testsuite/tests/OB26-040-type-invariants/src/test_tnocheck_t.adb b/testsuite/tests/OB26-040-type-invariants/src/test_tnocheck_t.adb new file mode 100644 index 000000000..4232f6556 --- /dev/null +++ b/testsuite/tests/OB26-040-type-invariants/src/test_tnocheck_t.adb @@ -0,0 +1,22 @@ +with tNoCheck; use tNoCheck; + +procedure Test_tNocheck_T is + SIO : SI (UB => 5); + STIO : STI (UB => 10); +begin + null; +end; + +--# tnocheck.ads + +-- We expect only l. or l+ on type declarations in +-- this case (invariants disabled), which depends on +-- whether or not code gets generated, in turn varying +-- with the kind of runtime configuration. + +-- Not worth tracking the exact different scenarii, so +-- we don't state any particular expectation so l+ or +-- l. will go by regardless. + +-- If code gets generated and turns out uncovered, we +-- will get a failure out of an unexpected violation. diff --git a/testsuite/tests/P505-032-path-spaces/foo.adb b/testsuite/tests/P505-032-path-spaces/foo.adb new file mode 100644 index 000000000..8d89dda55 --- /dev/null +++ b/testsuite/tests/P505-032-path-spaces/foo.adb @@ -0,0 +1,5 @@ +with Ada.Text_IO; use Ada.Text_IO; +procedure Foo is +begin + Put_Line ("Hello, world!"); +end Foo; diff --git a/testsuite/tests/P505-032-path-spaces/test.opt b/testsuite/tests/P505-032-path-spaces/test.opt new file mode 100644 index 000000000..e0b4e7570 --- /dev/null +++ b/testsuite/tests/P505-032-path-spaces/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercizes "gnatcov run" diff --git a/testsuite/tests/P505-032-path-spaces/test.py b/testsuite/tests/P505-032-path-spaces/test.py new file mode 100644 index 000000000..36b74ecee --- /dev/null +++ b/testsuite/tests/P505-032-path-spaces/test.py @@ -0,0 +1,30 @@ +""" +This test checks that "gnatcov run" behaves correctly when the main program and +the output file paths passed to it contain whitespaces. + +This used not to work with the DynamoRIO adapter on x86-windows. +""" + +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir, match +from SUITE.tutils import (exename_for, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +Wdir('tmp/with spaces') + +gpr_file = gprfor(srcdirs=['../..'], mains=['foo.adb'], objdir='obj') +gprbuild(gpr_file) + +foo_exe = os.path.abspath(exename_for('foo')) +foo_trace = os.path.abspath(tracename_for('foo')) + +xrun(['-o', foo_trace, foo_exe]) +xcov(['coverage', '-P', gpr_file, '-c', 'stmt', '-a', 'xcov', foo_trace]) + +thistest.fail_if( + not match(r'4 \+: *Put_Line', os.path.join('obj', 'foo.adb.xcov')), + 'Statement at foo.adb:4 is not covered whereas it should be') +thistest.result() diff --git a/testsuite/tests/P526-035-origin-project/src-p1/p1.adb b/testsuite/tests/P526-035-origin-project/src-p1/p1.adb new file mode 100644 index 000000000..993018799 --- /dev/null +++ b/testsuite/tests/P526-035-origin-project/src-p1/p1.adb @@ -0,0 +1,12 @@ +package body P1 is + + ---------- + -- Next -- + ---------- + + function Next (I : Integer) return Integer is + begin + return I + 1; + end Next; + +end P1; diff --git a/testsuite/tests/P526-035-origin-project/src-p1/p1.ads b/testsuite/tests/P526-035-origin-project/src-p1/p1.ads new file mode 100644 index 000000000..cd9d6a897 --- /dev/null +++ b/testsuite/tests/P526-035-origin-project/src-p1/p1.ads @@ -0,0 +1,5 @@ +package P1 is + + function Next (I : Integer) return Integer; + +end P1; diff --git a/testsuite/tests/P526-035-origin-project/src-p2/p2.adb b/testsuite/tests/P526-035-origin-project/src-p2/p2.adb new file mode 100644 index 000000000..23b6dcf98 --- /dev/null +++ b/testsuite/tests/P526-035-origin-project/src-p2/p2.adb @@ -0,0 +1,7 @@ +with P1; + +procedure P2 is + Dummy : constant Integer := P1.Next (1); +begin + null; +end P2; diff --git a/testsuite/tests/P526-035-origin-project/test.opt b/testsuite/tests/P526-035-origin-project/test.opt new file mode 100644 index 000000000..83cb05b0d --- /dev/null +++ b/testsuite/tests/P526-035-origin-project/test.opt @@ -0,0 +1 @@ +src-traces DEAD Option "projects" not working rightfully with source coverage. \ No newline at end of file diff --git a/testsuite/tests/P526-035-origin-project/test.py b/testsuite/tests/P526-035-origin-project/test.py new file mode 100644 index 000000000..b0de3219c --- /dev/null +++ b/testsuite/tests/P526-035-origin-project/test.py @@ -0,0 +1,76 @@ +""" +Check that gnatcov correctly handles the Origin_Project project attribute. +""" + +import glob +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, tracename_for + +tmp = Wdir('tmp_') + + +def xcov_list(): + """ + Return the list of *.xcov files in the "obj" subdirectory. + """ + return set(os.path.basename(f) + for f in glob.glob(os.path.join('obj', '*.xcov'))) + + +def clean_xcov(): + """ + Remove all *.xcov files in the "obj" subdirectory. + """ + for filename in glob.glob(os.path.join('obj', '*.xcov')): + os.remove(filename) + + +gprfor(prjid='p1', srcdirs=['../src-p1'], mains=None, langs='Ada') + +p2 = gprfor(prjid='p2', srcdirs=['../src-p2'], mains=['p2.adb'], + deps=['p1'], + extra='for Origin_Project use \"p1\";') + +# Check that the Origin_Project provides a default for coverage analysis and +# that this default is overiden by the --projects switch. +for args, xcovs in [ + ([], {'p1.adb.xcov'}), + (['--projects=p2'], {'p2.adb.xcov'}), + (['--projects=p1', '--projects=p2'], {'p1.adb.xcov', 'p2.adb.xcov'}), +]: + clean_xcov() + + # Build the projects and produce a trace for the main + # Passing the same --projects option as given to `gnatcov coverage` + # to be consistent with gnatcov use model. + # If these options are not accounted at instrumentation time, + # there won't be SID files for every wanted unit of interest. + build_run_and_coverage(gprsw=GPRswitches(root_project=p2), + covlevel='stmt', + mains=['p2'], + extra_coverage_args=['-a', 'xcov', + '--no-subprojects'], + extra_args=args) + + p2_trace = tracename_for('p2') + + expected = ('\n'.join('* {}'.format(f) for f in sorted(xcovs)) or + ' ') + got = ('\n'.join('* {}'.format(f) for f in sorted(xcov_list())) or + ' ') + + thistest.fail_if( + expected != got, + '[{}switches: {}]\n' + 'Unexpected XCOV files. Expected:\n' + '{}\n' + 'But got instead:\n' + '{}\n'.format(p2_trace, ' '.join(args), expected, got)) + +thistest.result() diff --git a/testsuite/tests/P614-002-incidental-coverage/src/cons_maps_math.txt b/testsuite/tests/P614-002-incidental-coverage/src/cons_maps_math.txt new file mode 100644 index 000000000..8f7220705 --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/cons_maps_math.txt @@ -0,0 +1,37 @@ +drivers=test_add|test_area + +-- We have the test on map area using a mult operation from the Math unit. +-- +-- But this is not part of the tests of this unit per se, and is not specifying +-- any expectation for it. We expect the indirect coverage to be visible when +-- consolidating from traces, not from checkpoints. +-- +-- In source trace mode, the trace for the "area" test does not contain any +-- coverage information for the "math" unit, so trace-based consolidation +-- behaves like the checkpoint-based one. + +--# maps.adb +-- /eval/ l+ ## 0 + +--# math.adb + +-- %cons: traces %opts: --trace-mode=bin + +-- /check-add/ l+ ## 0 +-- /add/ l+ ## 0 +-- /check-mult/ l! ## dF- +-- /mult/ l+ ## 0 + +-- %cons: traces %opts: --trace-mode=src + +-- /check-add/ l! ## dF- +-- /add/ l+ ## 0 +-- /check-mult/ l- ## s- +-- /mult/ l- ## s- + +-- %cons: checkpoints + +-- /check-add/ l! ## dF- +-- /add/ l+ ## 0 +-- /check-mult/ l- ## s- +-- /mult/ l- ## s- diff --git a/testsuite/tests/P614-002-incidental-coverage/src/maps.adb b/testsuite/tests/P614-002-incidental-coverage/src/maps.adb new file mode 100644 index 000000000..635ad5986 --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/maps.adb @@ -0,0 +1,14 @@ + + +-- We happen to use the Math package for basic operations here, +-- but we're not part of the unit tests for this unit. + +with Math; use Math; + +package body Maps is + + function Area (R : Rectangle_T) return Natural is + begin + return Eval (Mult, R.L, R.W); -- # eval + end; +end; diff --git a/testsuite/tests/P614-002-incidental-coverage/src/maps.ads b/testsuite/tests/P614-002-incidental-coverage/src/maps.ads new file mode 100644 index 000000000..c5f113f5b --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/maps.ads @@ -0,0 +1,7 @@ +package Maps is + type Rectangle_T is record + L, W : Natural; + end record; + + function Area (R : Rectangle_T) return Natural; +end; diff --git a/testsuite/tests/P614-002-incidental-coverage/src/math.adb b/testsuite/tests/P614-002-incidental-coverage/src/math.adb new file mode 100644 index 000000000..b9a8f15f5 --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/math.adb @@ -0,0 +1,23 @@ +package body Math is + + N_Adds, N_Mults : Natural := 0; + + procedure Inc (X : in out Integer) is + begin + X := X + 1; -- # inc + end; + + function Eval (Op : Binop_T; X, Y : Integer) return Integer is + begin + if Op = Add then -- # check-add + Inc (N_Adds); -- # add + return X + Y; -- # add + end if; + + if Op = Mult then -- # check-mult + Inc (N_Mults); -- # mult + return X * Y; -- # mult + end if; + end; + +end; diff --git a/testsuite/tests/P614-002-incidental-coverage/src/math.ads b/testsuite/tests/P614-002-incidental-coverage/src/math.ads new file mode 100644 index 000000000..60b26c3bb --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/math.ads @@ -0,0 +1,6 @@ +package Math is + + type Binop_T is (Add, Mult); + function Eval (Op : Binop_T; X, Y : Integer) return Integer; +end; + diff --git a/testsuite/tests/P614-002-incidental-coverage/src/test_add.adb b/testsuite/tests/P614-002-incidental-coverage/src/test_add.adb new file mode 100644 index 000000000..ac03eb57b --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/test_add.adb @@ -0,0 +1,14 @@ +with Math; use Math; +with Support; use Support; + +procedure Test_Add is +begin + Assert (Eval (Op => Add, X => 4, Y => 5) = 9); +end; + +--# math.adb +-- /check-add/ l! ## dF- +-- /add/ l+ ## 0 +-- /check-mult/ l- ## s- +-- /mult/ l- ## s- + diff --git a/testsuite/tests/P614-002-incidental-coverage/src/test_area.adb b/testsuite/tests/P614-002-incidental-coverage/src/test_area.adb new file mode 100644 index 000000000..a31d1e2a4 --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/src/test_area.adb @@ -0,0 +1,16 @@ +with Support; use Support; +with Maps; use Maps; + +-- This is a unit test for the Maps unit + +procedure Test_Area is + R : Rectangle_T := (L => 3, W => 9); +begin + Assert (Area (R) = 27); +end; + +-- No expectation on the Math unit here + +--# maps.adb +-- /eval/ l+ ## 0 + diff --git a/testsuite/tests/P614-002-incidental-coverage/test.py b/testsuite/tests/P614-002-incidental-coverage/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/P614-002-incidental-coverage/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/P622-010-stack-restore/src/characterize.adb b/testsuite/tests/P622-010-stack-restore/src/characterize.adb new file mode 100644 index 000000000..45444187b --- /dev/null +++ b/testsuite/tests/P622-010-stack-restore/src/characterize.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Characterize (X : Integer) is + Ximg : constant String := Integer'Image (X); -- # decl +begin + if X > 0 then -- # first-cond + Put_Line (Ximg & " is Positive"); -- # first-stmt + elsif X < 0 then -- # second-cond + Put_Line (Ximg & " is Negative"); -- # second-stmt + else + Put_Line (Ximg & " is Null"); -- # third-stmt + end if; +end; diff --git a/testsuite/tests/P622-010-stack-restore/src/test_0.adb b/testsuite/tests/P622-010-stack-restore/src/test_0.adb new file mode 100644 index 000000000..d3049377d --- /dev/null +++ b/testsuite/tests/P622-010-stack-restore/src/test_0.adb @@ -0,0 +1,14 @@ +with Characterize; + +procedure Test_0 is +begin + null; +end Test_0; + +--# characterize.adb +-- /decl/ l- ## s- +-- /first-cond/ l- ## s- +-- /first-stmt/ l- ## s- +-- /second-cond/ l- ## s- +-- /second-stmt/ l- ## s- +-- /third-stmt/ l- ## s- diff --git a/testsuite/tests/P622-010-stack-restore/src/test_n.adb b/testsuite/tests/P622-010-stack-restore/src/test_n.adb new file mode 100644 index 000000000..c8ae8d6c8 --- /dev/null +++ b/testsuite/tests/P622-010-stack-restore/src/test_n.adb @@ -0,0 +1,15 @@ +with Characterize; + +procedure Test_N is +begin + Characterize (-1); +end Test_N; + +--# characterize.adb +-- /decl/ l+ ## 0 +-- /first-cond/ l! ## dT- +-- /first-stmt/ l- ## s- +-- /second-cond/ l! ## dF- +-- /second-stmt/ l+ ## 0 +-- /third-stmt/ l- ## s- + diff --git a/testsuite/tests/P622-010-stack-restore/src/test_p.adb b/testsuite/tests/P622-010-stack-restore/src/test_p.adb new file mode 100644 index 000000000..29d148c16 --- /dev/null +++ b/testsuite/tests/P622-010-stack-restore/src/test_p.adb @@ -0,0 +1,14 @@ +with Characterize; + +procedure Test_P is +begin + Characterize (1); +end Test_P; + +--# characterize.adb +-- /decl/ l+ ## 0 +-- /first-cond/ l! ## dF- +-- /first-stmt/ l+ ## 0 +-- /second-cond/ l- ## s- +-- /second-stmt/ l- ## s- +-- /third-stmt/ l- ## s- diff --git a/testsuite/tests/P622-010-stack-restore/src/test_z.adb b/testsuite/tests/P622-010-stack-restore/src/test_z.adb new file mode 100644 index 000000000..af8c456fb --- /dev/null +++ b/testsuite/tests/P622-010-stack-restore/src/test_z.adb @@ -0,0 +1,14 @@ +with Characterize; + +procedure Test_Z is +begin + Characterize (0); +end Test_Z; + +--# characterize.adb +-- /decl/ l+ ## 0 +-- /first-cond/ l! ## dT- +-- /first-stmt/ l- ## s- +-- /second-cond/ l! ## dT- +-- /second-stmt/ l- ## s- +-- /third-stmt/ l+ ## 0 diff --git a/testsuite/tests/P622-010-stack-restore/test.py b/testsuite/tests/P622-010-stack-restore/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/P622-010-stack-restore/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/P907-005-ckpt-covlevel/src/math.adb b/testsuite/tests/P907-005-ckpt-covlevel/src/math.adb new file mode 100644 index 000000000..426783d0e --- /dev/null +++ b/testsuite/tests/P907-005-ckpt-covlevel/src/math.adb @@ -0,0 +1,23 @@ +package body Math is + + N_Adds, N_Mults : Natural := 0; + + procedure Inc (X : in out Integer) is + begin + X := X + 1; -- # inc + end; + + function Eval (Op : Binop_T; X, Y : Integer) return Integer is + begin + if Op = Add then -- # check-add + Inc (N_Adds); -- # add + return X + Y; -- # add + end if; + + if Op = Mult then -- # check-mult + Inc (N_Mults); -- # mult + return X * Y; -- # mult + end if; + end; + +end; diff --git a/testsuite/tests/P907-005-ckpt-covlevel/src/math.ads b/testsuite/tests/P907-005-ckpt-covlevel/src/math.ads new file mode 100644 index 000000000..2e567f79d --- /dev/null +++ b/testsuite/tests/P907-005-ckpt-covlevel/src/math.ads @@ -0,0 +1,4 @@ +package Math is + type Binop_T is (Add, Mult); + function Eval (Op : Binop_T; X, Y : Integer) return Integer; +end; diff --git a/testsuite/tests/P907-005-ckpt-covlevel/src/test_add.adb b/testsuite/tests/P907-005-ckpt-covlevel/src/test_add.adb new file mode 100644 index 000000000..139595116 --- /dev/null +++ b/testsuite/tests/P907-005-ckpt-covlevel/src/test_add.adb @@ -0,0 +1,7 @@ +with Math; use Math; +with Support; use Support; + +procedure Test_Add is +begin + Assert (Eval (Op => Add, X => 4, Y => 5) = 9); +end; diff --git a/testsuite/tests/P907-005-ckpt-covlevel/src/test_mult.adb b/testsuite/tests/P907-005-ckpt-covlevel/src/test_mult.adb new file mode 100644 index 000000000..e0b809d3a --- /dev/null +++ b/testsuite/tests/P907-005-ckpt-covlevel/src/test_mult.adb @@ -0,0 +1,7 @@ +with Math; use Math; +with Support; use Support; + +procedure Test_Mult is +begin + Assert (Eval (Op => Mult, X => 4, Y => 5) = 20); +end; diff --git a/testsuite/tests/P907-005-ckpt-covlevel/test.py b/testsuite/tests/P907-005-ckpt-covlevel/test.py new file mode 100644 index 000000000..bbaa4de45 --- /dev/null +++ b/testsuite/tests/P907-005-ckpt-covlevel/test.py @@ -0,0 +1,79 @@ +import os +import os.path +import re +import shutil + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +wd = Wdir('tmp_') + + +def create_checkpoint(name, covlevel): + gpr_exe_dir = 'exe-{}'.format(name) + gpr_obj_dir = 'obj-{}'.format(name) + prj_file = gprfor(mains=['test_{}.adb'.format(name)], + prjid=name, + srcdirs=os.path.join('..', 'src'), + objdir=gpr_obj_dir, + exedir=gpr_exe_dir, + extra='package Coverage is\n' + ' for Units use ("math");\n' + 'end Coverage;') + ckpt = 'test_{}.ckpt'.format(name) + build_run_and_coverage( + gprsw=GPRswitches(root_project=prj_file), + covlevel=covlevel, + mains=['test_{}'.format(name)], + gpr_obj_dir=gpr_obj_dir, + gpr_exe_dir=gpr_exe_dir, + extra_coverage_args=['--save-checkpoint={}'.format(ckpt)]) + return ckpt + + +def clean_output_directory(): + if os.path.exists('output'): + shutil.rmtree('output') + os.mkdir('output') + + +# Create two checkpoints with different coverage levels +add_ckpt = create_checkpoint('add', 'stmt') +mult_ckpt = create_checkpoint('mult', 'stmt+decision') + +# Consolidate both. The only attempt that is expected to suceed is the one +# with the weakest common coverage level criteria, i.e. stmt. +args = ['coverage', '--annotate=xcov', '--output-dir=output', '-C', add_ckpt, + '-C', mult_ckpt] + +# Attempting to consolidate them in stmt+decision mode should fail since one +# checkpoint was produced with a weaker coverage criteria (stmt). +# TODO: refine the expected error message. +clean_output_directory() +p = xcov(args + ['--level=stmt+decision'], 'cons-stmt-decision.log', + register_failure=False) +thistest.fail_if( + p.status == 0 or not re.match( + r'.*gnatcov.*: incompatible coverage level: .*test_add.*ckpt was' + r' produced with "stmt" but we expect at least "stmt\+decision"', + contents_of('cons-stmt-decision.log').strip() + ), + 'gnatcov did not complain about inconsistent coverage criteria across' + ' input checkpoints') + +clean_output_directory() +xcov(args + ['--level=stmt'], 'cons-stmt.log') + +expected = { + os.path.join('output', 'math.adb.xcov'): { + '+': {7, 12, 13, 14, 17, 18, 19}}, + os.path.join('output', 'math.ads.xcov'): {}} + +# Finally, check we have the expected reports for the --level=stmt +# consolidation. +check_xcov_reports(os.path.join('output', '*.xcov'), expected) +thistest.result() diff --git a/testsuite/tests/P907-005-incremental/src/math.adb b/testsuite/tests/P907-005-incremental/src/math.adb new file mode 100644 index 000000000..426783d0e --- /dev/null +++ b/testsuite/tests/P907-005-incremental/src/math.adb @@ -0,0 +1,23 @@ +package body Math is + + N_Adds, N_Mults : Natural := 0; + + procedure Inc (X : in out Integer) is + begin + X := X + 1; -- # inc + end; + + function Eval (Op : Binop_T; X, Y : Integer) return Integer is + begin + if Op = Add then -- # check-add + Inc (N_Adds); -- # add + return X + Y; -- # add + end if; + + if Op = Mult then -- # check-mult + Inc (N_Mults); -- # mult + return X * Y; -- # mult + end if; + end; + +end; diff --git a/testsuite/tests/P907-005-incremental/src/math.ads b/testsuite/tests/P907-005-incremental/src/math.ads new file mode 100644 index 000000000..2e567f79d --- /dev/null +++ b/testsuite/tests/P907-005-incremental/src/math.ads @@ -0,0 +1,4 @@ +package Math is + type Binop_T is (Add, Mult); + function Eval (Op : Binop_T; X, Y : Integer) return Integer; +end; diff --git a/testsuite/tests/P907-005-incremental/src/test_add.adb b/testsuite/tests/P907-005-incremental/src/test_add.adb new file mode 100644 index 000000000..139595116 --- /dev/null +++ b/testsuite/tests/P907-005-incremental/src/test_add.adb @@ -0,0 +1,7 @@ +with Math; use Math; +with Support; use Support; + +procedure Test_Add is +begin + Assert (Eval (Op => Add, X => 4, Y => 5) = 9); +end; diff --git a/testsuite/tests/P907-005-incremental/src/test_mult.adb b/testsuite/tests/P907-005-incremental/src/test_mult.adb new file mode 100644 index 000000000..e0b809d3a --- /dev/null +++ b/testsuite/tests/P907-005-incremental/src/test_mult.adb @@ -0,0 +1,7 @@ +with Math; use Math; +with Support; use Support; + +procedure Test_Mult is +begin + Assert (Eval (Op => Mult, X => 4, Y => 5) = 20); +end; diff --git a/testsuite/tests/P907-005-incremental/test.py b/testsuite/tests/P907-005-incremental/test.py new file mode 100644 index 000000000..08bff3ccb --- /dev/null +++ b/testsuite/tests/P907-005-incremental/test.py @@ -0,0 +1,50 @@ +import os +import os.path + +from SCOV.minicheck import build_and_run, checked_xcov, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +wd = Wdir('tmp_') + +# Generate a project for test drivers, build and run them to get trace files +prj_file = gprfor(['test_add.adb', 'test_mult.adb'], + srcdirs=os.path.join('..', 'src'), + extra='package Coverage is' + '\n for Units use ("math");' + '\nend Coverage;') +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=prj_file), + covlevel='stmt+decision', + mains=['test_add', 'test_mult'], + extra_coverage_args=[]) + +# Extract trace files arguments from "xcov_args" +base_args = xcov_args[:-2] +add_trace = xcov_args[-2] +mult_trace = xcov_args[-1] + +# Now, consolidate one trace file after the other, accumulating results in a +# single checkpoint (this is incremental coverage). +checked_xcov(base_args + ['--save-checkpoint=c1.ckpt', add_trace], + 'checkpoint-1.log') +checked_xcov(base_args + ['--checkpoint=c1.ckpt', + '--save-checkpoint=c2.ckpt', mult_trace], + 'checkpoint-2.log') + +# Generate the final report and check we have the expected result +checked_xcov(base_args + ['--annotate=xcov', '--checkpoint=c2.ckpt', + '--output-dir=.'], + 'report.log') + + +# Finally, check we have the expected reports +check_xcov_reports( + '*.xcov', + {'math.adb.xcov': {'+': {7, 12, 13, 14, 18, 19}, '!': {17}}, + 'math.ads.xcov': {}}) + +thistest.result() diff --git a/testsuite/tests/P907-005-stubbing-generic/.gitignore b/testsuite/tests/P907-005-stubbing-generic/.gitignore new file mode 100644 index 000000000..e12db4626 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/.gitignore @@ -0,0 +1,2 @@ +sensors-gnatcov-instr +*.sid diff --git a/testsuite/tests/P907-005-stubbing-generic/common.gpr b/testsuite/tests/P907-005-stubbing-generic/common.gpr new file mode 100644 index 000000000..4efd6b94b --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/common.gpr @@ -0,0 +1,5 @@ +abstract project common is + package compiler is + for switches ("Ada") use ("-gnata"); + end compiler; +end common; \ No newline at end of file diff --git a/testsuite/tests/P907-005-stubbing-generic/sensors/int_control.ads b/testsuite/tests/P907-005-stubbing-generic/sensors/int_control.ads new file mode 100644 index 000000000..10909b979 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/sensors/int_control.ads @@ -0,0 +1,7 @@ +with Temperature_Control; +with Pressure_Control; + +package Int_Control is + package TC is new Temperature_Control (Integer); + package PC is new Pressure_Control (Integer); +end Int_Control; diff --git a/testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.adb b/testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.adb new file mode 100644 index 000000000..3667230fc --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.adb @@ -0,0 +1,22 @@ +package body Pressure_Control is + + Ticks : Integer := 0; + Inc_Period : Integer := 3; + + Live_Pressure : T := 6; + + procedure Update_Live_Pressure is + begin + Ticks := Ticks + 1; + if Ticks mod Inc_Period = 0 then + Live_Pressure := Live_Pressure + 1; + end if; + end; + + function Current_Pressure return T is + begin + Update_Live_Pressure; + return Live_Pressure; + end; + +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.ads b/testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.ads new file mode 100644 index 000000000..c0585bb6c --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/sensors/pressure_control.ads @@ -0,0 +1,5 @@ +generic + type T is range <>; +package Pressure_Control is + function Current_Pressure return T; +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/sensors/sensors.gpr b/testsuite/tests/P907-005-stubbing-generic/sensors/sensors.gpr new file mode 100644 index 000000000..c262fcf29 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/sensors/sensors.gpr @@ -0,0 +1,3 @@ +project sensors is + for languages use ("Ada"); +end sensors; diff --git a/testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.adb b/testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.adb new file mode 100644 index 000000000..fef1aefbe --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.adb @@ -0,0 +1,22 @@ +package body Temperature_Control is + + Ticks : Integer := 0; + Inc_Period : Integer := 5; + + Live_Temperature : T := 0; + + procedure Update_Live_Temperature is + begin + Ticks := Ticks + 1; + if Ticks mod Inc_Period = 0 then + Live_Temperature := Live_Temperature + 1; + end if; + end; + + function Current_Temperature return T is + begin + Update_Live_Temperature; + return Live_Temperature; + end; + +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.ads b/testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.ads new file mode 100644 index 000000000..06c689e59 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/sensors/temperature_control.ads @@ -0,0 +1,5 @@ +generic + type T is range <>; +package Temperature_Control is + function Current_Temperature return T; +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/stub_pressure/pressure_control.adb b/testsuite/tests/P907-005-stubbing-generic/stub_pressure/pressure_control.adb new file mode 100644 index 000000000..489708a65 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/stub_pressure/pressure_control.adb @@ -0,0 +1,6 @@ +package body Pressure_Control is + function Current_Pressure return T is + begin + return -1; + end; +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/stub_temperature/temperature_control.adb b/testsuite/tests/P907-005-stubbing-generic/stub_temperature/temperature_control.adb new file mode 100644 index 000000000..5588bd745 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/stub_temperature/temperature_control.adb @@ -0,0 +1,6 @@ +package body Temperature_Control is + function Current_Temperature return T is + begin + return -1; + end; +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/test.py b/testsuite/tests/P907-005-stubbing-generic/test.py new file mode 100644 index 000000000..37dc70d30 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test.py @@ -0,0 +1,74 @@ +import os +import os.path +import shutil + +from SCOV.minicheck import (build_run_and_coverage, checked_xcov, + check_xcov_reports) +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +class TestDriver(object): + def __init__(self, test_dir, exename): + self.test_dir = test_dir + self.exename = exename + + self.obj_dir = os.path.join('..', test_dir, 'obj') + self.prj_file = os.path.join('..', test_dir, 'test_runner.gpr') + self.ckpt_file = exename + '.ckpt' + + +test_drivers = [TestDriver('test_p', 'tp1'), + TestDriver('test_t', 'tt1'), + TestDriver('test_sensors', 'ts1')] + + +# Cleanup any previous test run artefacts +for td in test_drivers: + if os.path.exists(td.obj_dir): + shutil.rmtree(td.obj_dir) + + +wd = Wdir('tmp_') + + +# Build projects, generate trace and checkpoints for each test drivers +for td in test_drivers: + build_run_and_coverage( + gprsw=GPRswitches(root_project=td.prj_file), + covlevel='stmt+decision', + mains=[td.exename], + gpr_obj_dir=td.obj_dir, + gpr_exe_dir=td.obj_dir, + extra_coverage_args=['--save-checkpoint', td.ckpt_file], + out='ckpt-{}.log'.format(td.exename), + scos_for_run=False) + + +# Now, generate the final report +ckpt_args = ['--checkpoint={}'.format(td.ckpt_file) + for td in test_drivers] +checked_xcov(['coverage', '-P', os.path.join('..', 'sensors', 'sensors.gpr'), + '--level=stmt+decision', '--annotate=xcov', + '--output-dir=.'] + ckpt_args, + 'cons.log') + +# Finally, check we have the expected reports +check_xcov_reports( + '*.xcov', + { + 'pressure_control.adb.xcov': { + '+': {10, 18, 19}, + '!': {11}, + '-': {12}, + }, + 'temperature_control.adb.xcov': { + '+': {10, 18, 19}, + '!': {11}, + '-': {12}, + } + } +) + +thistest.result() diff --git a/testsuite/tests/P907-005-stubbing-generic/test_p/test_runner.gpr b/testsuite/tests/P907-005-stubbing-generic/test_p/test_runner.gpr new file mode 100644 index 000000000..5b9a81650 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test_p/test_runner.gpr @@ -0,0 +1,12 @@ +with "../common.gpr"; + +project Test_Runner extends "../sensors/sensors.gpr" is + for Source_Dirs use ("../stub_temperature", "."); + for Object_Dir use "obj"; + for Main use ("tp1.adb"); + package Compiler renames Common.Compiler; + + package Coverage is + for Units use ("pressure_control"); + end Coverage; +end Test_Runner; diff --git a/testsuite/tests/P907-005-stubbing-generic/test_p/tp1.adb b/testsuite/tests/P907-005-stubbing-generic/test_p/tp1.adb new file mode 100644 index 000000000..f4c953661 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test_p/tp1.adb @@ -0,0 +1,10 @@ +with Int_Control; use Int_Control; + +procedure TP1 is + T : Integer; +begin + T := TC.Current_Temperature; + pragma Assert (T < 0); + T := PC.Current_Pressure; + pragma Assert (T >= 0); +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/test_sensors/test_runner.gpr b/testsuite/tests/P907-005-stubbing-generic/test_sensors/test_runner.gpr new file mode 100644 index 000000000..81f347636 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test_sensors/test_runner.gpr @@ -0,0 +1,12 @@ +with "../common.gpr"; + +project Test_Runner extends "../sensors/sensors.gpr" is + for Source_Dirs use ("."); + for Object_Dir use "obj"; + for Main use ("ts1.adb"); + package Compiler renames Common.Compiler; + + package Coverage is + for Units use ("pressure_control", "temperature_control"); + end Coverage; +end test_runner; diff --git a/testsuite/tests/P907-005-stubbing-generic/test_sensors/ts1.adb b/testsuite/tests/P907-005-stubbing-generic/test_sensors/ts1.adb new file mode 100644 index 000000000..b2de37530 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test_sensors/ts1.adb @@ -0,0 +1,10 @@ +with Int_Control; use Int_Control; + +procedure TS1 is + T : Integer; +begin + T := TC.Current_Temperature; + pragma Assert (T >= 0); + T := PC.Current_Pressure; + pragma Assert (T >= 0); +end; diff --git a/testsuite/tests/P907-005-stubbing-generic/test_t/test_runner.gpr b/testsuite/tests/P907-005-stubbing-generic/test_t/test_runner.gpr new file mode 100644 index 000000000..09957b890 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test_t/test_runner.gpr @@ -0,0 +1,12 @@ +with "../common.gpr"; + +project Test_Runner extends "../sensors/sensors.gpr" is + for Source_Dirs use ("../stub_pressure", "."); + for Object_Dir use "obj"; + for Main use ("tt1.adb"); + package Compiler renames Common.Compiler; + + package Coverage is + for Units use ("temperature_control"); + end Coverage; +end Test_Runner; diff --git a/testsuite/tests/P907-005-stubbing-generic/test_t/tt1.adb b/testsuite/tests/P907-005-stubbing-generic/test_t/tt1.adb new file mode 100644 index 000000000..0e20b55df --- /dev/null +++ b/testsuite/tests/P907-005-stubbing-generic/test_t/tt1.adb @@ -0,0 +1,10 @@ +with Int_Control; use Int_Control; + +procedure TT1 is + T : Integer; +begin + T := TC.Current_Temperature; + pragma Assert (T >= 0); + T := PC.Current_Pressure; + pragma Assert (T < 0); +end; diff --git a/testsuite/tests/P907-005-stubbing/.gitignore b/testsuite/tests/P907-005-stubbing/.gitignore new file mode 100644 index 000000000..e12db4626 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/.gitignore @@ -0,0 +1,2 @@ +sensors-gnatcov-instr +*.sid diff --git a/testsuite/tests/P907-005-stubbing/common.gpr b/testsuite/tests/P907-005-stubbing/common.gpr new file mode 100644 index 000000000..4efd6b94b --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/common.gpr @@ -0,0 +1,5 @@ +abstract project common is + package compiler is + for switches ("Ada") use ("-gnata"); + end compiler; +end common; \ No newline at end of file diff --git a/testsuite/tests/P907-005-stubbing/sensors/pressure_control.adb b/testsuite/tests/P907-005-stubbing/sensors/pressure_control.adb new file mode 100644 index 000000000..1d27794a9 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/sensors/pressure_control.adb @@ -0,0 +1,22 @@ +package body Pressure_Control is + + Ticks : Integer := 0; + Inc_Period : Integer := 3; + + Live_Pressure : Integer := 6; + + procedure Update_Live_Pressure is + begin + Ticks := Ticks + 1; + if Ticks mod Inc_Period = 0 then + Live_Pressure := Live_Pressure + 1; + end if; + end; + + function Current_Pressure return Integer is + begin + Update_Live_Pressure; + return Live_Pressure; + end; + +end; diff --git a/testsuite/tests/P907-005-stubbing/sensors/pressure_control.ads b/testsuite/tests/P907-005-stubbing/sensors/pressure_control.ads new file mode 100644 index 000000000..f7138110d --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/sensors/pressure_control.ads @@ -0,0 +1,3 @@ +package Pressure_Control is + function Current_Pressure return Integer; +end; diff --git a/testsuite/tests/P907-005-stubbing/sensors/sensors.gpr b/testsuite/tests/P907-005-stubbing/sensors/sensors.gpr new file mode 100644 index 000000000..c262fcf29 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/sensors/sensors.gpr @@ -0,0 +1,3 @@ +project sensors is + for languages use ("Ada"); +end sensors; diff --git a/testsuite/tests/P907-005-stubbing/sensors/temperature_control.adb b/testsuite/tests/P907-005-stubbing/sensors/temperature_control.adb new file mode 100644 index 000000000..845fc4698 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/sensors/temperature_control.adb @@ -0,0 +1,22 @@ +package body Temperature_Control is + + Ticks : Integer := 0; + Inc_Period : Integer := 5; + + Live_Temperature : Integer := 0; + + procedure Update_Live_Temperature is + begin + Ticks := Ticks + 1; + if Ticks mod Inc_Period = 0 then + Live_Temperature := Live_Temperature + 1; + end if; + end; + + function Current_Temperature return Integer is + begin + Update_Live_Temperature; + return Live_Temperature; + end; + +end; diff --git a/testsuite/tests/P907-005-stubbing/sensors/temperature_control.ads b/testsuite/tests/P907-005-stubbing/sensors/temperature_control.ads new file mode 100644 index 000000000..f51af2995 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/sensors/temperature_control.ads @@ -0,0 +1,3 @@ +package Temperature_Control is + function Current_Temperature return Integer; +end; diff --git a/testsuite/tests/P907-005-stubbing/stub_pressure/pressure_control.adb b/testsuite/tests/P907-005-stubbing/stub_pressure/pressure_control.adb new file mode 100644 index 000000000..9324a5d19 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/stub_pressure/pressure_control.adb @@ -0,0 +1,6 @@ +package body Pressure_Control is + function Current_Pressure return Integer is + begin + return -1; + end; +end; diff --git a/testsuite/tests/P907-005-stubbing/stub_temperature/temperature_control.adb b/testsuite/tests/P907-005-stubbing/stub_temperature/temperature_control.adb new file mode 100644 index 000000000..7a53a14f1 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/stub_temperature/temperature_control.adb @@ -0,0 +1,6 @@ +package body Temperature_Control is + function Current_Temperature return Integer is + begin + return -1; + end; +end; diff --git a/testsuite/tests/P907-005-stubbing/test.py b/testsuite/tests/P907-005-stubbing/test.py new file mode 100644 index 000000000..a1bf453f9 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test.py @@ -0,0 +1,73 @@ +import os +import os.path +import shutil + +from SCOV.minicheck import (build_run_and_coverage, checked_xcov, + check_xcov_reports) +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +class TestDriver(object): + def __init__(self, test_dir, exename): + self.test_dir = test_dir + self.exename = exename + + self.obj_dir = os.path.join('..', test_dir, 'obj') + self.prj_file = os.path.join('..', test_dir, 'test_runner.gpr') + self.ckpt_file = exename + '.ckpt' + + +test_drivers = [TestDriver('test_p', 'tp1'), + TestDriver('test_t', 'tt1'), + TestDriver('test_sensors', 'ts1')] + + +# Cleanup any previous test run artefacts +for td in test_drivers: + if os.path.exists(td.obj_dir): + shutil.rmtree(td.obj_dir) + + +wd = Wdir('tmp_') + +# Build projects, generate trace and checkpoints for each test drivers +for td in test_drivers: + build_run_and_coverage( + gprsw=GPRswitches(root_project=td.prj_file), + covlevel='stmt+decision', + mains=[td.exename], + gpr_obj_dir=td.obj_dir, + gpr_exe_dir=td.obj_dir, + extra_coverage_args=['--save-checkpoint', td.ckpt_file], + out='ckpt-{}.log'.format(td.exename), + scos_for_run=False) + + +# Now, generate the final report +ckpt_args = ['--checkpoint={}'.format(td.ckpt_file) + for td in test_drivers] +checked_xcov(['coverage', '-P', os.path.join('..', 'sensors', 'sensors.gpr'), + '--level=stmt+decision', '--annotate=xcov', + '--output-dir=.'] + ckpt_args, + 'cons.log') + +# Finally, check we have the expected reports +check_xcov_reports( + '*.xcov', + { + 'pressure_control.adb.xcov': { + '+': {10, 18, 19}, + '!': {11}, + '-': {12}, + }, + 'temperature_control.adb.xcov': { + '+': {10, 18, 19}, + '!': {11}, + '-': {12}, + } + } +) + +thistest.result() diff --git a/testsuite/tests/P907-005-stubbing/test_p/test_runner.gpr b/testsuite/tests/P907-005-stubbing/test_p/test_runner.gpr new file mode 100644 index 000000000..5b9a81650 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test_p/test_runner.gpr @@ -0,0 +1,12 @@ +with "../common.gpr"; + +project Test_Runner extends "../sensors/sensors.gpr" is + for Source_Dirs use ("../stub_temperature", "."); + for Object_Dir use "obj"; + for Main use ("tp1.adb"); + package Compiler renames Common.Compiler; + + package Coverage is + for Units use ("pressure_control"); + end Coverage; +end Test_Runner; diff --git a/testsuite/tests/P907-005-stubbing/test_p/tp1.adb b/testsuite/tests/P907-005-stubbing/test_p/tp1.adb new file mode 100644 index 000000000..e910eafed --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test_p/tp1.adb @@ -0,0 +1,11 @@ +with Temperature_Control; use Temperature_Control; +with Pressure_Control; use Pressure_Control; + +procedure TP1 is + T : Integer; +begin + T := Current_Temperature; + pragma Assert (T < 0); + T := Current_Pressure; + pragma Assert (T >= 0); +end; diff --git a/testsuite/tests/P907-005-stubbing/test_sensors/test_runner.gpr b/testsuite/tests/P907-005-stubbing/test_sensors/test_runner.gpr new file mode 100644 index 000000000..81f347636 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test_sensors/test_runner.gpr @@ -0,0 +1,12 @@ +with "../common.gpr"; + +project Test_Runner extends "../sensors/sensors.gpr" is + for Source_Dirs use ("."); + for Object_Dir use "obj"; + for Main use ("ts1.adb"); + package Compiler renames Common.Compiler; + + package Coverage is + for Units use ("pressure_control", "temperature_control"); + end Coverage; +end test_runner; diff --git a/testsuite/tests/P907-005-stubbing/test_sensors/ts1.adb b/testsuite/tests/P907-005-stubbing/test_sensors/ts1.adb new file mode 100644 index 000000000..828164c21 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test_sensors/ts1.adb @@ -0,0 +1,11 @@ +with Temperature_Control; use Temperature_Control; +with Pressure_Control; use Pressure_Control; + +procedure TS1 is + T : Integer; +begin + T := Current_Temperature; + pragma Assert (T >= 0); + T := Current_Pressure; + pragma Assert (T >= 0); +end; diff --git a/testsuite/tests/P907-005-stubbing/test_t/test_runner.gpr b/testsuite/tests/P907-005-stubbing/test_t/test_runner.gpr new file mode 100644 index 000000000..09957b890 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test_t/test_runner.gpr @@ -0,0 +1,12 @@ +with "../common.gpr"; + +project Test_Runner extends "../sensors/sensors.gpr" is + for Source_Dirs use ("../stub_pressure", "."); + for Object_Dir use "obj"; + for Main use ("tt1.adb"); + package Compiler renames Common.Compiler; + + package Coverage is + for Units use ("temperature_control"); + end Coverage; +end Test_Runner; diff --git a/testsuite/tests/P907-005-stubbing/test_t/tt1.adb b/testsuite/tests/P907-005-stubbing/test_t/tt1.adb new file mode 100644 index 000000000..f1d204011 --- /dev/null +++ b/testsuite/tests/P907-005-stubbing/test_t/tt1.adb @@ -0,0 +1,11 @@ +with Temperature_Control; use Temperature_Control; +with Pressure_Control; use Pressure_Control; + +procedure TT1 is + T : Integer; +begin + T := Current_Temperature; + pragma Assert (T >= 0); + T := Current_Pressure; + pragma Assert (T < 0); +end; diff --git a/testsuite/tests/P913-011-invalid-project/foo.adb b/testsuite/tests/P913-011-invalid-project/foo.adb new file mode 100644 index 000000000..e9f45d970 --- /dev/null +++ b/testsuite/tests/P913-011-invalid-project/foo.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("Hello, world!"); +end Foo; diff --git a/testsuite/tests/P913-011-invalid-project/test.py b/testsuite/tests/P913-011-invalid-project/test.py new file mode 100644 index 000000000..091716235 --- /dev/null +++ b/testsuite/tests/P913-011-invalid-project/test.py @@ -0,0 +1,35 @@ +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import exename_for, gprbuild, gprfor, xcov + + +wd = Wdir('tmp_') +gprbuild(gprfor(['foo.adb'], srcdirs=['..'])) + +p = xcov(['run', '-P', 'does_not_exist.gpr', exename_for('foo')], + out='gnatcov-run.out', + err='gnatcov-run.err', + register_failure=False) + +out_content = contents_of('gnatcov-run.out') +err_content = contents_of('gnatcov-run.err') +expected_err = re.compile( + '^does_not_exist.gpr is not a regular file\n' + '[^\n]*gnatcov(\\.exe)?: Could not load the project file, aborting.\n$') + +thistest.fail_if( + p.status != 1, + 'gnatcov returned status code {}, but 1 expected'.format(p.status)) +thistest.fail_if( + out_content, + 'gnatcov output not empty:\n' + '\n{}\n'.format(out_content)) +thistest.fail_if( + not expected_err.match(err_content), + 'gnatcov error output mismatch:\n' + 'Expected pattern:\n{!r}\n\n' + 'Got:\n{}'.format(expected_err.pattern, err_content)) + +thistest.result() diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.adb new file mode 100644 index 000000000..255375ede --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.adb @@ -0,0 +1,16 @@ +package body P1 is + + function F1 (A, B : Boolean) return Boolean; + pragma Inline (F1); + + function F1 (A, B : Boolean) return Boolean is + begin + return A and then B; -- # and + end; + + procedure Combine (A, B, C : Boolean) is + begin + R := F1 (A, B) or else C; -- # or + end; + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.ads b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.ads new file mode 100644 index 000000000..2136ace3d --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.ads @@ -0,0 +1,15 @@ +package P1 is + + R : Boolean; + + procedure Combine (A, B, C : Boolean); + + -- A B and C R + -- 1 F X F F F + -- 2 T F F F F + -- 3 T T T X T + + -- 4 F X F T T + -- 5 T F F T T + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_1.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_1.adb new file mode 100644 index 000000000..fa6cd986e --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_1.adb @@ -0,0 +1,14 @@ +with Support, P1; use Support, P1; + +procedure Test_1 is +begin + for X in False .. True loop + Combine (False, X, False); + Assert (R = False); + end loop; +end; + + +--# p1.adb +-- /and/ l! ## eT- +-- /or/ l! ## eT- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_14.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_14.adb new file mode 100644 index 000000000..2d6ed61d4 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_14.adb @@ -0,0 +1,14 @@ +with Support, P1; use Support, P1; + +procedure Test_14 is +begin + Combine (False, False, False); + Assert (R = False); + Combine (False, False, True); + Assert (R = True); +end; + + +--# p1.adb +-- /and/ l! ## eT- +-- /or/ l! ## c!:"F1" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_2.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_2.adb new file mode 100644 index 000000000..f37e587ad --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_2.adb @@ -0,0 +1,12 @@ +with Support, P1; use Support, P1; + +procedure Test_2 is +begin + Combine (True, False, False); + Assert (R = False); +end; + + +--# p1.adb +-- /and/ l! ## eT- +-- /or/ l! ## eT- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_3.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_3.adb new file mode 100644 index 000000000..9f6c55eb8 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_3.adb @@ -0,0 +1,14 @@ +with Support, P1; use Support, P1; + +procedure Test_3 is +begin + for X in False .. True loop + Combine (True, True, X); + Assert (R = True); + end loop; +end; + + +--# p1.adb +-- /and/ l! ## eF- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_4.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_4.adb new file mode 100644 index 000000000..0740f9787 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_4.adb @@ -0,0 +1,14 @@ +with Support, P1; use Support, P1; + +procedure Test_4 is +begin + for X in False .. True loop + Combine (False, X, True); + Assert (R = True); + end loop; +end; + + +--# p1.adb +-- /and/ l! ## eT- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_5.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_5.adb new file mode 100644 index 000000000..1a10c59ba --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/test_5.adb @@ -0,0 +1,12 @@ +with Support, P1; use Support, P1; + +procedure Test_5 is +begin + Combine (True, False, True); + Assert (R = True); +end; + + +--# p1.adb +-- /and/ l! ## eT- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/test.py b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/test.py new file mode 100644 index 000000000..6987337a8 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.adb new file mode 100644 index 000000000..6636563f7 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.adb @@ -0,0 +1,13 @@ +package body P1 is + + function Orelse (B, C : Boolean) return Boolean is + begin + return B or else C; -- # or + end; + + procedure Combine (A, B, C, D : Boolean) is + begin + R := A and then Orelse (B, C) and then D; -- # comb + end; + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.ads b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.ads new file mode 100644 index 000000000..dfa12fbd6 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.ads @@ -0,0 +1,18 @@ +package P1 is + + R : Boolean; + + function Orelse (B, C : Boolean) return Boolean; + pragma Inline (Orelse); + + procedure Combine (A, B, C, D : Boolean); + + -- A && (B C or) && D R + -- 1 F X X X X F + -- 2 T T X T F F + -- 3 T F T T F F + -- 4 T F F F X F + -- 5 T T X T T T + -- 6 T F T T T T + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1.adb new file mode 100644 index 000000000..b4f623cd2 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1.adb @@ -0,0 +1,16 @@ +with Support, P1; use Support, P1; + +procedure Test_1 is +begin + for Xbc in False .. True loop + for Xd in False .. True loop + Combine (False, Xbc, Xbc, Xd); + Assert (R = False); + end loop; + end loop; +end; + + +--# p1.adb +-- /comb/ l! ## eT- +-- /or/ l- ## s- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1346.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1346.adb new file mode 100644 index 000000000..40d84c582 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_1346.adb @@ -0,0 +1,18 @@ +with Support, P1; use Support, P1; + +procedure Test_1346 is + X : Boolean := False; +begin + Combine (False, X, X, X); -- 1 + Assert (R = False); + Combine (True, False, True, False); -- 3 + Assert (R = False); + Combine (True, False, False, X); -- 4 + Assert (R = False); + Combine (True, False, True, True); -- 6 + Assert (R = True); +end; + +--# p1.adb +-- /comb/ l+ ## 0 +-- /or/ l! ## c!:"B" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_2.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_2.adb new file mode 100644 index 000000000..64cb7b802 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_2.adb @@ -0,0 +1,14 @@ +with Support, P1; use Support, P1; + +procedure Test_2 is +begin + for X in False .. True loop + Combine (True, True, X, False); + Assert (R = False); + end loop; +end; + + +--# p1.adb +-- /comb/ l! ## eT- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_3.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_3.adb new file mode 100644 index 000000000..9bd46de79 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_3.adb @@ -0,0 +1,12 @@ +with Support, P1; use Support, P1; + +procedure Test_3 is +begin + Combine (True, False, True, False); + Assert (R = False); +end; + + +--# p1.adb +-- /comb/ l! ## eT- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_346.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_346.adb new file mode 100644 index 000000000..ade34ef6e --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_346.adb @@ -0,0 +1,16 @@ +with Support, P1; use Support, P1; + +procedure Test_346 is + X : Boolean := False; +begin + Combine (True, False, True, False); -- 3 + Assert (R = False); + Combine (True, False, False, X); -- 4 + Assert (R = False); + Combine (True, False, True, True); -- 6 + Assert (R = True); +end; + +--# p1.adb +-- /comb/ l! ## c!:"A" +-- /or/ l! ## c!:"B" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_36.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_36.adb new file mode 100644 index 000000000..d66b1bd47 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_36.adb @@ -0,0 +1,13 @@ +with Support, P1; use Support, P1; + +procedure Test_36 is +begin + Combine (True, False, True, False); -- 3 + Assert (R = False); + Combine (True, False, True, True); -- 6 + Assert (R = True); +end; + +--# p1.adb +-- /comb/ l! ## c!:"A",c!:"Or" +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_4.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_4.adb new file mode 100644 index 000000000..ce8b75293 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_4.adb @@ -0,0 +1,12 @@ +with Support, P1; use Support, P1; + +procedure Test_4 is +begin + Combine (True, False, False, False); + Assert (R = False); +end; + + +--# p1.adb +-- /comb/ l! ## eT- +-- /or/ l! ## eT- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_46.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_46.adb new file mode 100644 index 000000000..f31af5c70 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_46.adb @@ -0,0 +1,15 @@ +with Support, P1; use Support, P1; + +procedure Test_46 is + X : Boolean := True; +begin + Combine (True, False, False, X); -- 4 + Assert (R = False); + Combine (True, False, True, True); -- 6 + Assert (R = True); +end; + + +--# p1.adb +-- /comb/ l! ## c!:"A",c!:"D" +-- /or/ l! ## c!:"B" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_5.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_5.adb new file mode 100644 index 000000000..a6d30425c --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_5.adb @@ -0,0 +1,14 @@ +with Support, P1; use Support, P1; + +procedure Test_5 is +begin + for X in False .. True loop + Combine (True, True, X, True); + Assert (R = True); + end loop; +end; + + +--# p1.adb +-- /comb/ l! ## eF- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_6.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_6.adb new file mode 100644 index 000000000..b807dde7c --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/test_6.adb @@ -0,0 +1,12 @@ +with Support, P1; use Support, P1; + +procedure Test_6 is +begin + Combine (True, False, True, True); + Assert (R = True); +end; + + +--# p1.adb +-- /comb/ l! ## eF- +-- /or/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/test.py b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/test.py new file mode 100644 index 000000000..e4fa11967 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.adb new file mode 100644 index 000000000..1e20557ed --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.adb @@ -0,0 +1,10 @@ +with Twisters; use Twisters; + +package body P1 is + + procedure Andthen (A, B, C : Boolean) is + begin + R := A and then Identity (B) and then C; -- # comb + end; + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.ads b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.ads new file mode 100644 index 000000000..1c4fbfc28 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.ads @@ -0,0 +1,13 @@ +package P1 is + + R : Boolean; + + procedure Andthen (A, B, C : Boolean); + + -- A B C R + -- 1 T T T T + -- 2 T T F F + -- 3 T F X F + -- 4 F X X F + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1.adb new file mode 100644 index 000000000..99b746f9f --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1.adb @@ -0,0 +1,10 @@ +with Support, P1; use Support, P1; + +procedure Test_1 is +begin + Andthen (True, True, True); + Assert (R = True); +end; + +--# p1.adb +-- /comb/ l! ## eF- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_12.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_12.adb new file mode 100644 index 000000000..c88c66c3f --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_12.adb @@ -0,0 +1,10 @@ +with Test_1, Test_2; + +procedure Test_12 is +begin + Test_1; + Test_2; +end; + +--# p1.adb +-- /comb/ l! ## c!:"A", c!:"Id" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_123.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_123.adb new file mode 100644 index 000000000..4d1eae5e1 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_123.adb @@ -0,0 +1,11 @@ +with Test_1, Test_2, Test_3; + +procedure Test_123 is +begin + Test_1; + Test_2; + Test_3; +end; + +--# p1.adb +-- /comb/ l! ## c!:"A" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1234.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1234.adb new file mode 100644 index 000000000..0fe912b5c --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_1234.adb @@ -0,0 +1,12 @@ +with Test_1, Test_2, Test_3, Test_4; + +procedure Test_1234 is +begin + Test_1; + Test_2; + Test_3; + Test_4; +end; + +--# p1.adb +-- /comb/ l+ ## 0 diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_124.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_124.adb new file mode 100644 index 000000000..eb22e4c9c --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_124.adb @@ -0,0 +1,11 @@ +with Test_1, Test_2, Test_4; + +procedure Test_124 is +begin + Test_1; + Test_2; + Test_4; +end; + +--# p1.adb +-- /comb/ l! ## c!:"Id" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_13.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_13.adb new file mode 100644 index 000000000..d686e7375 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_13.adb @@ -0,0 +1,10 @@ +with Test_1, Test_3; + +procedure Test_13 is +begin + Test_1; + Test_3; +end; + +--# p1.adb +-- /comb/ l! ## c!:"A", c!:"C" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_134.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_134.adb new file mode 100644 index 000000000..792c4ac3b --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_134.adb @@ -0,0 +1,11 @@ +with Test_1, Test_3, Test_4; + +procedure Test_134 is +begin + Test_1; + Test_3; + Test_4; +end; + +--# p1.adb +-- /comb/ l! ## c!:"C" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_14.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_14.adb new file mode 100644 index 000000000..cbd2d1771 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_14.adb @@ -0,0 +1,10 @@ +with Test_1, Test_4; + +procedure Test_14 is +begin + Test_1; + Test_4; +end; + +--# p1.adb +-- /comb/ l! ## c!:"Id", c!:"C" diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_2.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_2.adb new file mode 100644 index 000000000..e1c2a23e0 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_2.adb @@ -0,0 +1,10 @@ +with Support, P1; use Support, P1; + +procedure Test_2 is +begin + Andthen (True, True, False); + Assert (R = False); +end; + +--# p1.adb +-- /comb/ l! ## eT- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_3.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_3.adb new file mode 100644 index 000000000..b68df8fec --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_3.adb @@ -0,0 +1,11 @@ +with Support, P1; use Support, P1; + +procedure Test_3 is + X : Boolean := False; +begin + Andthen (True, False, X); + Assert (R = False); +end; + +--# p1.adb +-- /comb/ l! ## eT- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_4.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_4.adb new file mode 100644 index 000000000..e568a6391 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/test_4.adb @@ -0,0 +1,11 @@ +with Support, P1; use Support, P1; + +procedure Test_4 is + X : Boolean := False; +begin + Andthen (False, X, X); + Assert (R = False); +end; + +--# p1.adb +-- /comb/ l! ## eT- diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/test.py b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/test.py new file mode 100644 index 000000000..e4fa11967 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.adb new file mode 100644 index 000000000..f9655952f --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.adb @@ -0,0 +1,15 @@ +package body P2 is + + function F2 (X : Integer) return Boolean; + pragma Inline (F2); + + function F2 (X : Integer) return Boolean is + begin + return CX + X > 10; -- # comp + end; + + procedure Combine (C : Boolean; X : Integer) is + begin + R := C or else F2 (X); -- # or + end; +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.ads b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.ads new file mode 100644 index 000000000..f79a4628f --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.ads @@ -0,0 +1,11 @@ +package P2 is + R : Boolean; + CX : Integer := 0; + procedure Combine (C : Boolean; X : Integer); + + -- V# C X>10 R + -- 1 F F F + -- 2 F T T + -- 3 T X T + +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_0.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_0.adb new file mode 100644 index 000000000..d515c91ee --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_0.adb @@ -0,0 +1,11 @@ +with Support, P2; use Support, P2; + +procedure Test_0 is +begin + null; +end; + +--# p2.adb +-- /or/ l- ## s- +-- /comp/ l- ## s- + diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_1.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_1.adb new file mode 100644 index 000000000..f2e5d859a --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_1.adb @@ -0,0 +1,12 @@ +with Support, P2; use Support, P2; + +procedure Test_1 is +begin + Combine (False, 5); + Assert (R = False); +end; + +--# p2.adb +-- /or/ l! ## eT- +-- /comp/ l+ ## 0 + diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_12.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_12.adb new file mode 100644 index 000000000..015af4a08 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_12.adb @@ -0,0 +1,14 @@ +with Support, P2; use Support, P2; + +procedure Test_12 is +begin + Combine (False, 5); + Assert (R = False); + Combine (False, 15); + Assert (R = True); +end; + +--# p2.adb +-- /or/ l! ## c!:"C" +-- /comp/ l+ ## 0 + diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_123.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_123.adb new file mode 100644 index 000000000..1e277afd8 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_123.adb @@ -0,0 +1,18 @@ +with Support, P2; use Support, P2; + +procedure Test_123 is +begin + Combine (False, 5); + Assert (R = False); + Combine (False, 15); + Assert (R = True); + Combine (True, 5); + Assert (R = True); + Combine (True, 15); + Assert (R = True); +end; + +--# p2.adb +-- /or/ l+ ## 0 +-- /comp/ l+ ## 0 + diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_13.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_13.adb new file mode 100644 index 000000000..e123eec72 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_13.adb @@ -0,0 +1,16 @@ +with Support, P2; use Support, P2; + +procedure Test_13 is +begin + Combine (False, 5); + Assert (R = False); + Combine (True, 5); + Assert (R = True); + Combine (True, 15); + Assert (R = True); +end; + +--# p2.adb +-- /or/ l! ## c!:"F2" +-- /comp/ l+ ## 0 + diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_2.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_2.adb new file mode 100644 index 000000000..779c07951 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_2.adb @@ -0,0 +1,12 @@ +with Support, P2; use Support, P2; + +procedure Test_2 is +begin + Combine (False, 15); + Assert (R = True); +end; + +--# p2.adb +-- /or/ l! ## eF- +-- /comp/ l+ ## 0 + diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_23.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_23.adb new file mode 100644 index 000000000..b8e9ab83c --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_23.adb @@ -0,0 +1,16 @@ +with Support, P2; use Support, P2; + +procedure Test_23 is +begin + Combine (False, 15); + Assert (R = True); + Combine (True, 5); + Assert (R = True); + Combine (True, 15); + Assert (R = True); +end; + +--# p2.adb +-- /or/ l! ## eF- +-- /comp/ l+ ## 0 + diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_3.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_3.adb new file mode 100644 index 000000000..5a57d0d1a --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_3.adb @@ -0,0 +1,13 @@ +with Support, P2; use Support, P2; + +procedure Test_3 is +begin + Combine (True, 5); + Combine (True, 15); + Assert (R = True); +end; + +--# p2.adb +-- /or/ l! ## eF- +-- /comp/ l- ## s- + diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/test.py b/testsuite/tests/PA25-046-inlined-in-decision/C_X/test.py new file mode 100644 index 000000000..6987337a8 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/PA25-046-inlined-in-decision/extra.opt b/testsuite/tests/PA25-046-inlined-in-decision/extra.opt new file mode 100644 index 000000000..a4e1eba80 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.adb b/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.adb new file mode 100644 index 000000000..6a805b1bd --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.adb @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package body Twisters is + function Identity (B : Boolean) return Boolean is + begin + -- The goal is to have conditional branches coming from other + -- functions inlined within decisions. The conditional expression + -- is there to force the production of conditional branches. + return (if B then True else False); + end; +end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.ads b/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.ads new file mode 100644 index 000000000..cd81c9b36 --- /dev/null +++ b/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.ads @@ -0,0 +1,9 @@ +package Twisters is + + function Identity (B : Boolean) return Boolean; + + -- We really care about inlining in the middle of decisions + -- in this series of tests, so: + pragma Inline_Always (Identity); + +end; diff --git a/testsuite/tests/PC09-022-auto-exename/src-sub/sub_main.adb b/testsuite/tests/PC09-022-auto-exename/src-sub/sub_main.adb new file mode 100644 index 000000000..379623393 --- /dev/null +++ b/testsuite/tests/PC09-022-auto-exename/src-sub/sub_main.adb @@ -0,0 +1,4 @@ +procedure Sub_Main is +begin + null; +end Sub_Main; diff --git a/testsuite/tests/PC09-022-auto-exename/src/main_proc.adb b/testsuite/tests/PC09-022-auto-exename/src/main_proc.adb new file mode 100644 index 000000000..9af7453ca --- /dev/null +++ b/testsuite/tests/PC09-022-auto-exename/src/main_proc.adb @@ -0,0 +1,4 @@ +procedure Main_Proc is +begin + null; +end Main_Proc; diff --git a/testsuite/tests/PC09-022-auto-exename/src/other_proc.adb b/testsuite/tests/PC09-022-auto-exename/src/other_proc.adb new file mode 100644 index 000000000..00c822a2f --- /dev/null +++ b/testsuite/tests/PC09-022-auto-exename/src/other_proc.adb @@ -0,0 +1,4 @@ +procedure Other_Proc is +begin + null; +end Other_Proc; diff --git a/testsuite/tests/PC09-022-auto-exename/test.opt b/testsuite/tests/PC09-022-auto-exename/test.opt new file mode 100644 index 000000000..53ce9d379 --- /dev/null +++ b/testsuite/tests/PC09-022-auto-exename/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD This test checks "gnatcov run", specific to binary traces diff --git a/testsuite/tests/PC09-022-auto-exename/test.py b/testsuite/tests/PC09-022-auto-exename/test.py new file mode 100644 index 000000000..15d0fe9f4 --- /dev/null +++ b/testsuite/tests/PC09-022-auto-exename/test.py @@ -0,0 +1,167 @@ +""" +Test that "gnatcov run" properly auto-detects the name of the executable from a +project file, or that it properly reports when there is not one single main. +""" + +from collections import OrderedDict +import os +import os.path +import re + +from SUITE.context import thistest +from SUITE.cutils import FatalError, Wdir, contents_of, indent +from SUITE.tutils import gprbuild, gprfor, xrun + + +wd = Wdir('tmp_') + + +class Project(object): + def __init__(self, projects, name, srcdir, mains=(), deps=(), build=True, + should_succeed=True): + self.projects = projects + self.name = name + self.srcdir = srcdir + self.mains = list(mains) + self.deps = deps + self.build = build + self.should_succeed = should_succeed + + self.objdir = 'obj-{}'.format(self.name) + self.exedir = 'exe-{}'.format(self.name) + + self.prj_file = None + + @property + def dep_projects(self): + """ + Return the list of all projects "self" depends on. + """ + return [self.projects[d] for d in self.deps] + + @property + def all_mains(self): + """ + Return the set of mains for this projects and all its dependencies'. + """ + result = set() + for main in self.mains: + result.add(main.split('.')[0]) + for p in self.dep_projects: + result.update(p.all_mains) + return result + + def prepare(self): + print('Preparing {}...'.format(self.name)) + self.prj_file = gprfor( + mains=self.mains, + prjid=self.name, + srcdirs=os.path.join('..', self.srcdir), + objdir=self.objdir, + exedir=self.exedir, + langs=['Ada'], + deps=self.deps) + if self.build: + gprbuild(self.prj_file) + + # Make sure that in all case, output directories exist so that warning + # messages don't pollute gnatcov's error messages. + for dirname in (self.objdir, self.exedir): + if not os.path.isdir(dirname): + os.mkdir(dirname) + + def run(self): + print('') + print('== Running {} =='.format(self.name)) + + error_msg_re = None + all_mains = self.all_mains + + if len(all_mains) != 1: + print('Not exactly one main: should fail') + error_msg_re = ( + r'.*gnatcov.*: Please specify an executable to run \(EXE\)' + r' on the command line.*') + elif not self.build: + main = all_mains.pop() + print('Not built: should fail') + error_msg_re = '.*gnatcov.*: .*{}.*: File not found'.format( + re.escape(main)) + else: + print('Should succeed') + + we_think_it_should_succeed = not error_msg_re + thistest.stop_if( + we_think_it_should_succeed != self.should_succeed, + FatalError('Test declaration disagrees with test framework about' + ' whether this test should fail')) + + log_file = 'run-{}.txt'.format(self.name) + p = xrun(['-P', self.prj_file], + register_failure=not error_msg_re, + out=log_file) + if error_msg_re: + thistest.fail_if( + p.status == 0, + 'gnatcov run suceeded whereas it was expected to fail') + out = contents_of(log_file).strip() + thistest.fail_if( + not re.match(error_msg_re, out), + '\nFor {}, error message ({}):' + '\n{}' + '\nDoes not match the expected pattern:' + '\n{}' + .format(self.name, log_file, + indent(out), indent(error_msg_re))) + + +project_files = OrderedDict() +for p in ( + # Test that the most regular case (one project, one main) succeeds + Project(project_files, 'single', 'src', + mains=('main_proc.adb', ), + should_succeed=True), + + # We expect an error when there is no main at all + Project(project_files, 'nomain', 'src', + should_succeed=False), + + # Likewise when there are too many mains + Project(project_files, 'double', 'src', + mains=('main_proc.adb', 'other_proc.adb'), + should_succeed=False), + + # Likewise when there is one main but it has not been built + Project(project_files, 'no_build', 'src', + mains=('main_proc.adb', ), + build=False, + should_succeed=False), + + # Check success when there is one single main in the whole project closure: + # once when the main is in the root project... + Project(project_files, 'sub', 'src-sub', + mains=('sub_main.adb', ), + deps=('nomain', ), + should_succeed=True), + + # ... and once when it is in a dep project + Project(project_files, 'sub_main_in_dep', 'src-sub', + mains=(), + deps=('single', ), + should_succeed=True), + + # Check that we have an error when there is at most one main per project + # and multiple projects with a main. + Project(project_files, 'sub_double', 'src-sub', + mains=('sub_main.adb', ), + deps=('single', ), + should_succeed=False), +): + assert p.name not in project_files + project_files[p.name] = p + p.prepare() + +for p in project_files.values(): + p.run() + +thistest.result() diff --git a/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.adb b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.adb new file mode 100644 index 000000000..b19d8daf4 --- /dev/null +++ b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.adb @@ -0,0 +1,6 @@ +package body Ops.P1 is + procedure Inc (X : in out Integer) is + begin + X := X + 1; -- # stmt + end; +end; diff --git a/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.ads b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.ads new file mode 100644 index 000000000..4e6acc2e1 --- /dev/null +++ b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops-p1.ads @@ -0,0 +1,3 @@ +package Ops.P1 is + procedure Inc (X : in out Integer); +end; diff --git a/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops.ads b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops.ads new file mode 100644 index 000000000..f4c3f25e7 --- /dev/null +++ b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/ops.ads @@ -0,0 +1,3 @@ +package Ops is + pragma Pure; -- # pragma +end; diff --git a/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/test_p1.adb b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/test_p1.adb new file mode 100644 index 000000000..c2603ebf7 --- /dev/null +++ b/testsuite/tests/PC23-018-missing-report-for-empty-unit/src/test_p1.adb @@ -0,0 +1,13 @@ +with Ops, Ops.P1; + +procedure Test_P1 is + X : Integer := 12; +begin + Ops.P1.Inc (X); +end; + +--# ops.ads +-- /pragma/ l. ## 0 + +--# ops-p1.adb +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/PC23-018-missing-report-for-empty-unit/test.py b/testsuite/tests/PC23-018-missing-report-for-empty-unit/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/PC23-018-missing-report-for-empty-unit/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/Q224-032-several-out-of-line/bar.c b/testsuite/tests/Q224-032-several-out-of-line/bar.c new file mode 100644 index 000000000..2e6c8275b --- /dev/null +++ b/testsuite/tests/Q224-032-several-out-of-line/bar.c @@ -0,0 +1,5 @@ +void +bar (void) +{ + return; +} diff --git a/testsuite/tests/Q224-032-several-out-of-line/foo.cpp b/testsuite/tests/Q224-032-several-out-of-line/foo.cpp new file mode 100644 index 000000000..8e770502d --- /dev/null +++ b/testsuite/tests/Q224-032-several-out-of-line/foo.cpp @@ -0,0 +1,7 @@ +#include "shared.hpp" + +void +foo () +{ + shared (); +} diff --git a/testsuite/tests/Q224-032-several-out-of-line/main.cpp b/testsuite/tests/Q224-032-several-out-of-line/main.cpp new file mode 100644 index 000000000..2031513f2 --- /dev/null +++ b/testsuite/tests/Q224-032-several-out-of-line/main.cpp @@ -0,0 +1,16 @@ +#include "shared.hpp" + +extern void foo (); + +extern "C" +{ + extern void bar (); +} + +int +main () +{ + shared (); + foo (); + bar (); +} diff --git a/testsuite/tests/Q224-032-several-out-of-line/shared.hpp b/testsuite/tests/Q224-032-several-out-of-line/shared.hpp new file mode 100644 index 000000000..804108221 --- /dev/null +++ b/testsuite/tests/Q224-032-several-out-of-line/shared.hpp @@ -0,0 +1,7 @@ +#include + +extern void shared(); + +inline void shared() { + std::cout << "Hello, world!" << std::endl; +} diff --git a/testsuite/tests/Q224-032-several-out-of-line/test.opt b/testsuite/tests/Q224-032-several-out-of-line/test.opt new file mode 100644 index 000000000..942aab8f4 --- /dev/null +++ b/testsuite/tests/Q224-032-several-out-of-line/test.opt @@ -0,0 +1,2 @@ +C++,bin-traces +ALL DEAD Requires a C++ compiler + tests a binary trace-specific behavior diff --git a/testsuite/tests/Q224-032-several-out-of-line/test.py b/testsuite/tests/Q224-032-several-out-of-line/test.py new file mode 100644 index 000000000..2170266d7 --- /dev/null +++ b/testsuite/tests/Q224-032-several-out-of-line/test.py @@ -0,0 +1,29 @@ +""" +Check that "gnatcov coverage" does not crash when processing a binary with +debug info that contains multiple definitions for the same function over +different compilation units. + +This testcase does this with the original customer use case: a C++ inline +function defined in a header included in several compilation units. +""" + +from SCOV.minicheck import checked_xcov, check_xcov_reports +from SUITE.cutils import Wdir +from SUITE.tutils import (exepath_to, gprfor, gprbuild, thistest, + tracename_for, xrun) + + +wd = Wdir('tmp_') +main = exepath_to('main') +trace = tracename_for('main') + +gpr = gprfor(['main.cpp'], srcdirs='..', langs=['C', 'C++']) +gprbuild(gpr) + +xrun([main], 'run.log') +checked_xcov(['coverage', '-P{}'.format(gpr), '-cstmt', '-axcov', + '--output-dir=.', trace], + 'coverage.log') +check_xcov_reports('*.xcov', {'bar.c.xcov': {'+': {4}}, }) + +thistest.result() diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/.gitignore b/testsuite/tests/Q308-041-crash-on-generic-in-lib/.gitignore new file mode 100644 index 000000000..ca5215678 --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/.gitignore @@ -0,0 +1,2 @@ +*.trace +install diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/app/default.gpr b/testsuite/tests/Q308-041-crash-on-generic-in-lib/app/default.gpr new file mode 100644 index 000000000..ab744582e --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/app/default.gpr @@ -0,0 +1,5 @@ +with "../libfoo/install/gpr/libfoo.gpr"; +project Default is + for Main use ("main.adb"); + for Object_Dir use "obj"; +end Default; diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/app/main.adb b/testsuite/tests/Q308-041-crash-on-generic-in-lib/app/main.adb new file mode 100644 index 000000000..165f6ee7b --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/app/main.adb @@ -0,0 +1,7 @@ +with Lib; + +procedure Main is + package B is new Lib; +begin + B.Foo; +end; diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.adb b/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.adb new file mode 100644 index 000000000..db835dcb4 --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.adb @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Lib is + + procedure Foo is + begin + Put_Line ("foo"); + end; + +begin + Put_Line ("elaboration"); +end; diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.ads b/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.ads new file mode 100644 index 000000000..f93bda713 --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/lib.ads @@ -0,0 +1,4 @@ +generic +package Lib is + procedure Foo; +end; diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/libfoo.gpr b/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/libfoo.gpr new file mode 100644 index 000000000..457330ac2 --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/libfoo.gpr @@ -0,0 +1,7 @@ +library project Libfoo is + for Library_Kind use "static"; + for Library_Name use "foo"; + for Object_Dir use "obj"; + for Library_Dir use "lib"; + +end Libfoo; diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.opt b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.opt new file mode 100644 index 000000000..63306d93b --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.opt @@ -0,0 +1,2 @@ +bin-traces,native,linux +ALL DEAD diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py new file mode 100644 index 000000000..6a4c75d23 --- /dev/null +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py @@ -0,0 +1,51 @@ +""" +Check that "gnatcov coverage" does not crash when processing a program that +exposes two paths for the same source (once before and one after installation). + +Note that in this testcase, one absolute path comes from the debug info line +mapping (.debug_lines) while the other only comes from the debug info +DW_TAG_compilation_unit entry (.debug_info). +""" + +import os + +from e3.fs import rm +from e3.os.process import Run + +from SUITE.tutils import thistest + + +def try_run(cmd): + p = Run(cmd) + thistest.fail_if( + p.status != 0, + 'Unexpected failure.\n' + 'Command was:\n' + '%s\n' + 'Output was:\n' + '%s' % (' '.join(cmd), p.out)) + + +home = os.getcwd() + +os.chdir('%s/libfoo' % home) +rm('install', recursive=True) + +try_run(['gprbuild', '-f', '-Plibfoo.gpr', '-p']) +try_run(['gprinstall', '-f', '-Plibfoo.gpr', '-p', + '--prefix=install', '--project-subdir=gpr']) + +os.chdir('%s/app' % home) + +try_run(['gprbuild', '-f', '-Pdefault.gpr', '-p']) +try_run(['gnatcov', 'run', 'obj/main']) + +# The very goal of this testcase is to compute code coverage for a unit that +# belongs to a project installed with gprinstall, so we need to enable the +# processing of externally built projects. +try_run(['gnatcov', 'coverage', + '--annotate=xcov', + '--level=stmt', + '-Pdefault', '--projects=libfoo', '--externally-built-projects', + 'main.trace']) +thistest.result() diff --git a/testsuite/tests/Q327-016-glob-ignore/ignore.list b/testsuite/tests/Q327-016-glob-ignore/ignore.list new file mode 100644 index 000000000..77aa615db --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/ignore.list @@ -0,0 +1,5 @@ +# Ignore packages B and C +pkg_[bc].adb + +# Ignore all test procedures +*-test.adb diff --git a/testsuite/tests/Q327-016-glob-ignore/src/main.adb b/testsuite/tests/Q327-016-glob-ignore/src/main.adb new file mode 100644 index 000000000..c5fe5be83 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/main.adb @@ -0,0 +1,8 @@ +with Pkg_A, Pkg_B, Pkg_C; +with Pkg_A.Test, Pkg_B.Test, Pkg_C.Test; + +procedure Main is +begin + Pkg_A.Main; Pkg_B.Main; Pkg_C.Main; + Pkg_A.Test; Pkg_B.Test; Pkg_C.Test; +end Main; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_a-test.adb b/testsuite/tests/Q327-016-glob-ignore/src/pkg_a-test.adb new file mode 100644 index 000000000..05a599066 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_a-test.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Pkg_A.Test is +begin + Put_Line ("A.Test"); +end Pkg_A.Test; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_a.adb b/testsuite/tests/Q327-016-glob-ignore/src/pkg_a.adb new file mode 100644 index 000000000..9d04529f9 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_a.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg_A is + procedure Main is + begin + Put_Line ("A"); + end Main; +end Pkg_A; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_a.ads b/testsuite/tests/Q327-016-glob-ignore/src/pkg_a.ads new file mode 100644 index 000000000..35e72457d --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_a.ads @@ -0,0 +1,3 @@ +package Pkg_A is + procedure Main; +end Pkg_A; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_b-test.adb b/testsuite/tests/Q327-016-glob-ignore/src/pkg_b-test.adb new file mode 100644 index 000000000..2a7eb9178 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_b-test.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Pkg_B.Test is +begin + Put_Line ("B.Test"); +end Pkg_B.Test; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_b.adb b/testsuite/tests/Q327-016-glob-ignore/src/pkg_b.adb new file mode 100644 index 000000000..40ecdbd03 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_b.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg_B is + procedure Main is + begin + Put_Line ("B"); + end Main; +end Pkg_B; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_b.ads b/testsuite/tests/Q327-016-glob-ignore/src/pkg_b.ads new file mode 100644 index 000000000..e1489c942 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_b.ads @@ -0,0 +1,3 @@ +package Pkg_B is + procedure Main; +end Pkg_B; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_c-test.adb b/testsuite/tests/Q327-016-glob-ignore/src/pkg_c-test.adb new file mode 100644 index 000000000..3349b06b6 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_c-test.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Pkg_C.Test is +begin + Put_Line ("C.Test"); +end Pkg_C.Test; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_c.adb b/testsuite/tests/Q327-016-glob-ignore/src/pkg_c.adb new file mode 100644 index 000000000..6addf3ddc --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_c.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg_C is + procedure Main is + begin + Put_Line ("C"); + end Main; +end Pkg_C; diff --git a/testsuite/tests/Q327-016-glob-ignore/src/pkg_c.ads b/testsuite/tests/Q327-016-glob-ignore/src/pkg_c.ads new file mode 100644 index 000000000..c28ad3ce9 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/src/pkg_c.ads @@ -0,0 +1,3 @@ +package Pkg_C is + procedure Main; +end Pkg_C; diff --git a/testsuite/tests/Q327-016-glob-ignore/test.py b/testsuite/tests/Q327-016-glob-ignore/test.py new file mode 100644 index 000000000..fdb8f41b3 --- /dev/null +++ b/testsuite/tests/Q327-016-glob-ignore/test.py @@ -0,0 +1,33 @@ +""" +Check that the --ignore-source-file option works as expected. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +src_dir = os.path.abspath('src') +ignore_list = os.path.abspath('ignore.list') + +wd = Wdir('tmp_') + + +# Produce a report with specific patterns to ignore some source files +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(['main.adb'], srcdirs=src_dir)), + covlevel='stmt', + mains=['main'], + ignored_source_files=['@' + ignore_list], + extra_coverage_args=['-a', 'xcov', '--output-dir=.']) + +# Check we have the expected reports +check_xcov_reports( + '*.xcov', + {'main.adb.xcov': {'+': {6, 7}}, + 'pkg_a.adb.xcov': {'+': {6}}}) +thistest.result() diff --git a/testsuite/tests/Q329-018-create-output-dir/foo.adb b/testsuite/tests/Q329-018-create-output-dir/foo.adb new file mode 100644 index 000000000..e9f45d970 --- /dev/null +++ b/testsuite/tests/Q329-018-create-output-dir/foo.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("Hello, world!"); +end Foo; diff --git a/testsuite/tests/Q329-018-create-output-dir/test.py b/testsuite/tests/Q329-018-create-output-dir/test.py new file mode 100644 index 000000000..d63189006 --- /dev/null +++ b/testsuite/tests/Q329-018-create-output-dir/test.py @@ -0,0 +1,35 @@ +import os.path + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov + + +src_dir = os.path.abspath('.') +wd = Wdir('tmp_') +output_dir = os.path.join('report', 'foo') + +# Generate a project for our sources, build it and generate a trace for it +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(['foo.adb'], srcdirs=src_dir)), + covlevel='stmt', + mains=['foo'], + extra_coverage_args=['-axcov', '--output-dir={}'.format(output_dir)]) + +# Now, try to produce a report in a directory that does not exist (even its +# parent does not exist!). +assert not os.path.exists('report') +xcov(xcov_args, 'coverage.log') + +# Check that gnatcov reports that it creates these directories +thistest.fail_if( + 'info: creating output path ' not in contents_of('coverage.log'), + 'gnatcov does not say it is creating directories, it should') + +# Finally, check we have the expected reports +check_xcov_reports( + os.path.join(output_dir, '*.xcov'), + {os.path.join(output_dir, 'foo.adb.xcov'): {'+': {5}}}) +thistest.result() diff --git a/testsuite/tests/Q414-016-task-accept/src/q.adb b/testsuite/tests/Q414-016-task-accept/src/q.adb new file mode 100644 index 000000000..a20c2e448 --- /dev/null +++ b/testsuite/tests/Q414-016-task-accept/src/q.adb @@ -0,0 +1,37 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Q is + Ticks, Laps : Integer := 0; + + task Clock is + entry Start; + entry Tick; + end Clock; + + task body Clock is + Counting : Boolean := False; + begin + loop + select + accept Start do -- # start_accept + Counting := True; -- # start_stmt + end; + or + accept Tick do -- # tick_accept + if Counting then -- # tick_if + Ticks := Ticks + 1; -- # tick_stmt + end if; + end; + or + terminate; + end select; + end loop; + end Clock; + + procedure Tryme is + begin + Clock.Tick; + Put_Line (Integer'Image (Ticks)); + end Tryme; + +end Q; diff --git a/testsuite/tests/Q414-016-task-accept/src/q.ads b/testsuite/tests/Q414-016-task-accept/src/q.ads new file mode 100644 index 000000000..8c9d7983a --- /dev/null +++ b/testsuite/tests/Q414-016-task-accept/src/q.ads @@ -0,0 +1,3 @@ +package Q is + procedure Tryme; +end Q; diff --git a/testsuite/tests/Q414-016-task-accept/src/test_tick.adb b/testsuite/tests/Q414-016-task-accept/src/test_tick.adb new file mode 100644 index 000000000..4b206f582 --- /dev/null +++ b/testsuite/tests/Q414-016-task-accept/src/test_tick.adb @@ -0,0 +1,13 @@ +with Q; + +procedure Test_Tick is +begin + Q.Tryme; +end Test_Tick; + +--# q.adb +-- /start_accept/ l- ## s- +-- /start_stmt/ l- ## s- +-- /tick_accept/ l+ ## 0 +-- /tick_if/ l+ ## 0 +-- /tick_stmt/ l- ## s- diff --git a/testsuite/tests/Q414-016-task-accept/test.opt b/testsuite/tests/Q414-016-task-accept/test.opt new file mode 100644 index 000000000..006a31f27 --- /dev/null +++ b/testsuite/tests/Q414-016-task-accept/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Q414-016-task-accept/test.py b/testsuite/tests/Q414-016-task-accept/test.py new file mode 100644 index 000000000..da130c4cd --- /dev/null +++ b/testsuite/tests/Q414-016-task-accept/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase, thistest +from SCOV.tctl import CAT + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/Q519-013-decision-map/bar.adb b/testsuite/tests/Q519-013-decision-map/bar.adb new file mode 100644 index 000000000..7d2ebfea1 --- /dev/null +++ b/testsuite/tests/Q519-013-decision-map/bar.adb @@ -0,0 +1,6 @@ +package body Bar is + function F (A, B, C : Boolean) return Boolean is + begin + return (A and then B) or else C; + end F; +end Bar; diff --git a/testsuite/tests/Q519-013-decision-map/bar.ads b/testsuite/tests/Q519-013-decision-map/bar.ads new file mode 100644 index 000000000..7c0846550 --- /dev/null +++ b/testsuite/tests/Q519-013-decision-map/bar.ads @@ -0,0 +1,3 @@ +package Bar is + function F (A, B, C : Boolean) return Boolean; +end Bar; diff --git a/testsuite/tests/Q519-013-decision-map/foo.adb b/testsuite/tests/Q519-013-decision-map/foo.adb new file mode 100644 index 000000000..78cf91a65 --- /dev/null +++ b/testsuite/tests/Q519-013-decision-map/foo.adb @@ -0,0 +1,7 @@ +with Bar; + +procedure Foo is + B : Boolean := Bar.F (True, False, True); +begin + null; +end Foo; diff --git a/testsuite/tests/Q519-013-decision-map/test.opt b/testsuite/tests/Q519-013-decision-map/test.opt new file mode 100644 index 000000000..e4be71a9a --- /dev/null +++ b/testsuite/tests/Q519-013-decision-map/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Exercizes map-routines diff --git a/testsuite/tests/Q519-013-decision-map/test.py b/testsuite/tests/Q519-013-decision-map/test.py new file mode 100644 index 000000000..f194bba52 --- /dev/null +++ b/testsuite/tests/Q519-013-decision-map/test.py @@ -0,0 +1,36 @@ +import os.path +import re + +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.tutils import exepath_to, gprbuild, gprfor, thistest, xcov + + +src_dir = os.path.abspath('.') +wd = Wdir('tmp_') +exe_path = exepath_to('foo') +dmap_path = exe_path + '.dmap' + + +# Generate a project for our sources, build it and generate a decision map for +# foo.adb +prj_file = gprfor(['foo.adb'], srcdirs=src_dir, objdir='.') +gprbuild(prj_file) +xcov(['map-routines', '--scos=bar.ali', exe_path]) +xcov(['dump-trace', dmap_path], out='dump-trace.txt') + +dump_trace = contents_of('dump-trace.txt') +pattern = """\ +Kind: DECISION_MAP + +Traces: +[0-9a-f]+-[0-9a-f]+ \\?: 00 ---- +.*""" +thistest.fail_if( + not re.match(pattern, dump_trace, re.DOTALL), + 'Could not match "gnatcov dump-trace" output:\n' + '{}\n' + 'against the expected pattern:\n' + '{}\n'.format(indent(dump_trace), indent(pattern)) +) + +thistest.result() diff --git a/testsuite/tests/Q614-037-ckpt-pkg-renames/bar.ads b/testsuite/tests/Q614-037-ckpt-pkg-renames/bar.ads new file mode 100644 index 000000000..376d7b7a8 --- /dev/null +++ b/testsuite/tests/Q614-037-ckpt-pkg-renames/bar.ads @@ -0,0 +1,3 @@ +with Foo; + +package Bar renames Foo; diff --git a/testsuite/tests/Q614-037-ckpt-pkg-renames/foo.adb b/testsuite/tests/Q614-037-ckpt-pkg-renames/foo.adb new file mode 100644 index 000000000..8fd05946a --- /dev/null +++ b/testsuite/tests/Q614-037-ckpt-pkg-renames/foo.adb @@ -0,0 +1,6 @@ +package body Foo is + procedure P is + begin + null; + end P; +end Foo; diff --git a/testsuite/tests/Q614-037-ckpt-pkg-renames/foo.ads b/testsuite/tests/Q614-037-ckpt-pkg-renames/foo.ads new file mode 100644 index 000000000..3db125be0 --- /dev/null +++ b/testsuite/tests/Q614-037-ckpt-pkg-renames/foo.ads @@ -0,0 +1,3 @@ +package Foo is + procedure P; +end Foo; diff --git a/testsuite/tests/Q614-037-ckpt-pkg-renames/main.adb b/testsuite/tests/Q614-037-ckpt-pkg-renames/main.adb new file mode 100644 index 000000000..eb59be279 --- /dev/null +++ b/testsuite/tests/Q614-037-ckpt-pkg-renames/main.adb @@ -0,0 +1,6 @@ +with Bar; + +procedure Main is +begin + Bar.P; +end Main; diff --git a/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py b/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py new file mode 100644 index 000000000..267d60945 --- /dev/null +++ b/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py @@ -0,0 +1,33 @@ +import glob +import os.path + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + + +src_dir = os.path.abspath('.') +wd = Wdir('tmp_') + + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(['main.adb'], srcdirs=src_dir, + objdir='.')), + gpr_obj_dir='.', + covlevel='stmt', + mains=['main'], + extra_coverage_args=['--save-checkpoint=main.ckpt'], + scos=['bar', 'foo', 'main']) +xcov(['coverage', '-cstmt', '-axcov', '-Cmain.ckpt']) + +expected_reports = ['foo.adb.xcov', 'main.adb.xcov'] +got_reports = sorted(glob.glob('*.xcov')) +thistest.fail_if( + got_reports != expected_reports, + ('Expected the following reports: {}\n' + 'But got instead: {}'.format( + expected_reports, got_reports)) +) + +thistest.result() diff --git a/testsuite/tests/Q901-012-report-title/foo.adb b/testsuite/tests/Q901-012-report-title/foo.adb new file mode 100644 index 000000000..f7b0acefa --- /dev/null +++ b/testsuite/tests/Q901-012-report-title/foo.adb @@ -0,0 +1,4 @@ +procedure Foo is +begin + null; +end Foo; diff --git a/testsuite/tests/Q901-012-report-title/test.py b/testsuite/tests/Q901-012-report-title/test.py new file mode 100644 index 000000000..08be60116 --- /dev/null +++ b/testsuite/tests/Q901-012-report-title/test.py @@ -0,0 +1,48 @@ +import os.path +import re + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir, match +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + + +src_dir = os.path.abspath('.') +wd = Wdir('tmp_') + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(['foo.adb'], srcdirs=src_dir, + objdir='.')), + gpr_obj_dir='.', + covlevel='stmt', + mains=['foo'], + extra_coverage_args=[], + scos=['foo']) + + +def run_checks(name, report_title, prefix): + html_dir = '{}-html'.format(name) + + args = list(xcov_args) + if report_title is None: + pass + else: + args.append('--report-title={}'.format(report_title)) + + xcov(args + ['-ahtml', '--output-dir={}'.format(html_dir)]) + + def do_match(title, dirname, filename): + path = os.path.join(dirname, filename) + text = '{}'.format(title) + thistest.fail_if( + not match(re.escape(text), path), + 'Could not match {} in {}'.format(repr(text), path) + ) + + do_match(prefix + 'GNATcoverage Report', html_dir, 'index.html') + + +run_checks('none', None, '') +run_checks('empty', '', '') +run_checks('full', 'My +# +# This is supposed to produce a trace file with only the trace info section +# (header and info entries). + +gpr = gprfor(srcdirs=[".."], mains=["foo.adb"]) + +gprbuild(gpr) + +exefile = exepath_to("foo") + +# We run a straigtht "gnatcov run" of our own, bypassing the 'xcov' +# function circuitry to prevent the addition of a real --target in +# cross configurations. + +bits = env.target.cpu.bits +cmd = ['gnatcov', 'run', f'--target=prepare{bits}', exepath_to("foo")] +p = Run(cmd) +thistest.fail_if( + p.status != 0, "command '%s' failed ; output was:\n%s" % ( + ' '.join(cmd), p.out)) + +tracefile = tracename_for("foo") + +with open(tracefile, 'rb') as fp: + trace = TraceFile.read(ByteStreamDecoder(fp)) + +# Check that the trace file contains the info section and at least some of the +# bits we expect there + +thistest.fail_if( + not trace.first_header, "info header missing from trace file") + +thistest.fail_if( + not trace.infos, "info entries missing from trace file") + +trace_info = trace.infos.infos + +# Entry kinds we expect to find in the info section header, and a regexp that +# the corresponding value should match. We're not trying to match a specific +# date (e.g. today()) in the exec time stamp to prevent getting into timezone +# intricacies. + +expected_entries = { + InfoKind.ExecFileName: re.escape(exefile.encode('utf-8')), + InfoKind.ExecTimeStamp: ( + r'\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d'.encode('ascii') + ) +} + +found_entries = {} + +for info_entry in trace_info.values(): + + thistest.fail_if( + info_entry.kind in found_entries, + "info entry kind %d found more than once in trace" % info_entry.kind) + + if info_entry.kind in expected_entries: + expected_contents = expected_entries[info_entry.kind] + thistest.fail_if( + not re.match(pattern=expected_contents, string=info_entry.data), + "expected contents '%s' not found in entry of kind %d;\n" + "value was '%s'" % (expected_contents, info_entry.kind, + info_entry.data)) + found_entries[info_entry.kind] = info_entry + +thistest.fail_if( + len(found_entries) != len(expected_entries), + "trace info section missing expected contents") + +# Check that the trace file does not contain the execution section. + +thistest.fail_if( + trace.second_header, "exec section header found in trace file, unexpected") + +thistest.result() diff --git a/testsuite/tests/QB14-023-stack-overflow/foo.adb b/testsuite/tests/QB14-023-stack-overflow/foo.adb new file mode 100644 index 000000000..f7b0acefa --- /dev/null +++ b/testsuite/tests/QB14-023-stack-overflow/foo.adb @@ -0,0 +1,4 @@ +procedure Foo is +begin + null; +end Foo; diff --git a/testsuite/tests/QB14-023-stack-overflow/test.py b/testsuite/tests/QB14-023-stack-overflow/test.py new file mode 100644 index 000000000..23d1090a1 --- /dev/null +++ b/testsuite/tests/QB14-023-stack-overflow/test.py @@ -0,0 +1,23 @@ +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of, text_to_file +from SUITE.tutils import exepath_to, gprfor, gprbuild, xcov + + +wd = Wdir('tmp_') +main = exepath_to('foo') + +gpr = gprfor(['foo.adb'], srcdirs='..') +gprbuild(gpr) + +# Patch the SCOs so that a statement covers an insanely huge amount of lines +ali_file = os.path.join('obj', 'foo.ali') +text_to_file(contents_of(ali_file).replace('CS 3:4-3:4', 'CS 3:4-1000000:4'), + ali_file) + +# Just check that the following command does not crash (it used to yield a +# stack overflow). +xcov(['map-routines', '-P{}'.format(gpr), main]) + +thistest.result() diff --git a/testsuite/tests/R404-023-object-stats/main b/testsuite/tests/R404-023-object-stats/main new file mode 100755 index 0000000000000000000000000000000000000000..301680ecb7ef5432f954ee175d4ee39b39952756 GIT binary patch literal 138672 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 L{Ew?wym9{zk{_2T literal 0 HcmV?d00001 diff --git a/testsuite/tests/R404-023-object-stats/main.adb b/testsuite/tests/R404-023-object-stats/main.adb new file mode 100644 index 000000000..052e24d0b --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/main.adb @@ -0,0 +1,9 @@ +with Pkg; use Pkg; + +procedure Main is +begin + Not_Executed_Branch; + Partially_Covered_Branch; + Fully_Covered_Branch (False); + Fully_Covered_Branch (True); +end Main; diff --git a/testsuite/tests/R404-023-object-stats/main.trace.asset b/testsuite/tests/R404-023-object-stats/main.trace.asset new file mode 100644 index 0000000000000000000000000000000000000000..3aaf17c1778b56e10637212ae4903b901e362c52 GIT binary patch literal 816 zcmYk3O=}ZT6oyZRF&SzolQD{jNU&N&80RA&4Z)SDh*YT(cY;jQX{qg1gg68r+|(rP*{X$%8xNjXW4{CHZK&oo2~6_0tD=mIQe^ z%V)vOPT29oxb06@@1>*MpXCYBNwTq3C0C8rirW3&Qf$5tq2n;>`%&!2Q7h^Vy78dB zWcoO$-nbjJJ5e``VpQ>4_`i4Un%o7CAAv@4RzlG{A=*c^@=KTSi6;Frc?4ozbS0~>tTJwE|F8m5N;pGFxxi@9qtLO`y zdk;Ud&oHRt$u_jf^P#NM=Lzcgns5%TKno5HT{!`(=uM-^Q^rq~@yF06?-Qu^_yo1D zeRvFgy;Agb9%_6UYW`pBdvJ)JC%$TY%n2SPo%DBK z?{S>_seciw{}pk~_YLaYe;R*7_FcGspx&d{x8%3+dGZI&ORMx*GQg+ryGY!D n&$y53vry+%%%vgE(VCA<^L{UluOVUSzi9lf?3MMul=c4tkqunp literal 0 HcmV?d00001 diff --git a/testsuite/tests/R404-023-object-stats/p.gpr b/testsuite/tests/R404-023-object-stats/p.gpr new file mode 100644 index 000000000..1f60edee6 --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/p.gpr @@ -0,0 +1,15 @@ +-- In order to regenerate main.trace.asset, run: +-- +-- gprbuild -Pp -p && gnatcov run -Pp -o main.trace.asset + +project P is + for Target use "arm-eabi"; + for Runtime ("Ada") use "zfp-stm32f4"; + for Exec_Dir use "."; + for Object_Dir use "obj"; + for Main use ("main.adb"); + + package Compiler is + for Default_Switches ("Ada") use ("-O1", "-gnatp", "-g"); + end Compiler; +end P; diff --git a/testsuite/tests/R404-023-object-stats/pkg.adb b/testsuite/tests/R404-023-object-stats/pkg.adb new file mode 100644 index 000000000..33aad1828 --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/pkg.adb @@ -0,0 +1,30 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Not_Executed_Branch (B1, B2 : Boolean := False) is + begin + if B1 then + if B2 then + Put_Line ("Not_Executed_Branch"); + end if; + end if; + end Not_Executed_Branch; + + procedure Partially_Covered_Branch (B : Boolean := False) is + begin + if B then + Put_Line ("Partially_Covered_Branch"); + end if; + end Partially_Covered_Branch; + + procedure Fully_Covered_Branch (B : Boolean) is + begin + if B then + Put_Line ("Fully_Covered_Branch: True"); + else + Put_Line ("Fully_Covered_Branch: False"); + end if; + end Fully_Covered_Branch; + +end Pkg; diff --git a/testsuite/tests/R404-023-object-stats/pkg.ads b/testsuite/tests/R404-023-object-stats/pkg.ads new file mode 100644 index 000000000..71966c409 --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + procedure Not_Executed_Branch (B1, B2 : Boolean := False); + procedure Partially_Covered_Branch (B : Boolean := False); + procedure Fully_Covered_Branch (B : Boolean); +end Pkg; diff --git a/testsuite/tests/R404-023-object-stats/routines.txt b/testsuite/tests/R404-023-object-stats/routines.txt new file mode 100644 index 000000000..24ccc62e1 --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/routines.txt @@ -0,0 +1,3 @@ +pkg__not_executed_branch +pkg__partially_covered_branch +pkg__fully_covered_branch diff --git a/testsuite/tests/R404-023-object-stats/test.opt b/testsuite/tests/R404-023-object-stats/test.opt new file mode 100644 index 000000000..3724a5c21 --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/test.opt @@ -0,0 +1 @@ +!32bits DEAD diff --git a/testsuite/tests/R404-023-object-stats/test.py b/testsuite/tests/R404-023-object-stats/test.py new file mode 100644 index 000000000..437b6d654 --- /dev/null +++ b/testsuite/tests/R404-023-object-stats/test.py @@ -0,0 +1,35 @@ +import os.path + +from SUITE.cutils import Wdir, lines_of, indent +from SUITE.tutils import thistest, xcov + +# main.trace.asset contains an absolute path to the corresponding executable. +# As it was produced on some specific machine, this absolute path is not valid +# everywhere, so help gnatcov locate it anyway with the --exec option. + +exec_path = os.path.abspath('main') +tmp = Wdir('tmp_') +xcov(['coverage', '--level=branch', '--annotate=asm', + '--routines=@../routines.txt', '--exec={}'.format(exec_path), + '../main.trace.asset'], + out='asm-report.txt') +lines = lines_of('asm-report.txt') + +baseline = """\ +26 instructions analyzed: + 14 covered + 12 not executed +4 conditional branches analyzed: + 1 fully covered + 2 partially covered + 1 not executed""" +result = '\n'.join(l.rstrip() for l in lines[-7:]) + +thistest.fail_if( + baseline != result, + 'Unexpected output for "gnatcov coverage". Expected:\n' + '{}\n' + 'but got:\n' + '{}'.format(indent(baseline), indent(result))) + +thistest.result() diff --git a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected new file mode 100644 index 000000000..37b70b71f --- /dev/null +++ b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected @@ -0,0 +1,1096 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/tests/R417-010-scope-metrics/src/main.adb b/testsuite/tests/R417-010-scope-metrics/src/main.adb new file mode 100644 index 000000000..2ba30be91 --- /dev/null +++ b/testsuite/tests/R417-010-scope-metrics/src/main.adb @@ -0,0 +1,74 @@ +pragma Ada_2012; + +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + + function "+" (Item : String) return Unbounded_String + renames To_Unbounded_String; + + package A is + + Size_Chunk : constant := 2_048; + + function And_Then (A, B : Boolean) return Boolean; + + function Id (A : Boolean) return Boolean is (A); + end A; + + package body A is + function And_Then (A, B : Boolean) return Boolean is + begin + return A and then B; + end And_Then; + end A; + + protected Obj is + procedure Set (V : Integer); + entry Get (V : out Integer); + private + Local : Integer; + Is_Set : Boolean := False; + end Obj; + + protected body Obj is + procedure Set (V : Integer) is + begin + Local := V; + Is_Set := True; + end Set; + + entry Get (V : out Integer) + when Is_Set is + -- Entry is blocked until the + -- condition is true. The barrier + -- is evaluated at call of entries + -- and at exits of procedures and + -- entries. The calling task sleeps + -- until the barrier is released. + begin + V := Local; + Is_Set := False; + end Get; + end Obj; + + N : Integer := 0; + + task T; + + task body T is + begin + Put_Line ("Task T will delay for 4 seconds..."); + delay 4.0; + Put_Line ("Task T will set Obj..."); + Obj.Set (5); + Put_Line ("Task T has just set Obj..."); + end T; +begin + Put_Line ("Main application will get Obj..."); + Obj.Get (N); + Put_Line ("Main application has just retrieved Obj..."); + Put_Line ("Number is: " & Integer'Image (N)); + +end Main; diff --git a/testsuite/tests/R417-010-scope-metrics/test.opt b/testsuite/tests/R417-010-scope-metrics/test.opt new file mode 100644 index 000000000..079fe371b --- /dev/null +++ b/testsuite/tests/R417-010-scope-metrics/test.opt @@ -0,0 +1,4 @@ +bin-traces DEAD no support for body metrics with binary traces +RTS_ZFP DEAD no tasking support in light runtimes +RTS_RAVENSCAR DEAD violates restrictions in the Jorvik profile +5.04a1 DEAD Requires Ada 2012, unavailable in 5.04a1 \ No newline at end of file diff --git a/testsuite/tests/R417-010-scope-metrics/test.py b/testsuite/tests/R417-010-scope-metrics/test.py new file mode 100644 index 000000000..7aa886c6a --- /dev/null +++ b/testsuite/tests/R417-010-scope-metrics/test.py @@ -0,0 +1,28 @@ +""" +Check that gnatcov computes correct scope metrics using the XML report format. +produced by gnatcov. Check this for all acceptions: task, entry, subprogram, +package and expression function. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[os.path.join("..", "src")], + mains=["main.adb"])), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["--annotate=xml"] +) + +thistest.fail_if_diff( + os.path.join("..", "main.adb.xml.expected"), + os.path.join("obj", "main.adb.xml") +) +thistest.result() diff --git a/testsuite/tests/R420-002-aggregate-project-file/src1/foo.adb b/testsuite/tests/R420-002-aggregate-project-file/src1/foo.adb new file mode 100644 index 000000000..e9f45d970 --- /dev/null +++ b/testsuite/tests/R420-002-aggregate-project-file/src1/foo.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("Hello, world!"); +end Foo; diff --git a/testsuite/tests/R420-002-aggregate-project-file/src2/foo.adb b/testsuite/tests/R420-002-aggregate-project-file/src2/foo.adb new file mode 100644 index 000000000..2a837257d --- /dev/null +++ b/testsuite/tests/R420-002-aggregate-project-file/src2/foo.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("Hello, world!"); + Put_Line ("Second edition..."); +end Foo; diff --git a/testsuite/tests/R420-002-aggregate-project-file/test.opt b/testsuite/tests/R420-002-aggregate-project-file/test.opt new file mode 100644 index 000000000..df872a03f --- /dev/null +++ b/testsuite/tests/R420-002-aggregate-project-file/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/R420-002-aggregate-project-file/test.py b/testsuite/tests/R420-002-aggregate-project-file/test.py new file mode 100644 index 000000000..8dbb95d7b --- /dev/null +++ b/testsuite/tests/R420-002-aggregate-project-file/test.py @@ -0,0 +1,55 @@ +import os.path +import re + +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.tutils import (exepath_to, gprbuild, gprfor, thistest, + tracename_for, xcov, xrun) + + +root_dir = os.path.abspath('.') +wd = Wdir('tmp_') + + +gpr1 = gprfor(['foo.adb'], prjid='src1', + srcdirs=os.path.join(root_dir, 'src1'), + objdir='obj1', exedir='obj1') +gpr2 = gprfor(['foo.adb'], prjid='gpr', + srcdirs=os.path.join(root_dir, 'src2'), + objdir='obj2', exedir='obj2') +aggr = 'aggr.gpr' + +with open(aggr, 'w') as f: + f.write("""aggregate project Aggr is + for Project_Files use ("{}", "{}"); +end Aggr; +""".format(gpr1, gpr2)) + +exe1 = os.path.join('obj1', 'foo') +exe2 = os.path.join('obj2', 'foo') +trace1 = tracename_for(exe1) +trace2 = tracename_for(exe2) + +gprbuild(aggr, extracargs=["-fdump-scos"]) +xrun([exepath_to(exe1), '-o', trace1]) +xrun([exepath_to(exe2), '-o', trace2]) +xcov(['coverage', '-P', aggr, '-cstmt', '-areport', trace1, trace2], + out='coverage.txt', register_failure=False) +log = contents_of('coverage.txt') + +pattern = """\ +.*gnatcov.*: error: the following source file: + foo\\.adb +appears as the main source file in: + .*obj1.foo.ali + .*obj2.foo.ali +Is the same ALI file provided twice\\?\ +""" +thistest.fail_if( + not re.match(pattern, log, re.DOTALL), + 'Could not match "gnatcov coverage" output:\n' + '{}\n' + 'against the expected pattern:\n' + '{}\n'.format(indent(log), indent(pattern)) +) + +thistest.result() diff --git a/testsuite/tests/R507-014-trailing-byte-insn/f.s b/testsuite/tests/R507-014-trailing-byte-insn/f.s new file mode 100644 index 000000000..ffd7335e7 --- /dev/null +++ b/testsuite/tests/R507-014-trailing-byte-insn/f.s @@ -0,0 +1,34 @@ + .text + .file "f.c" + .globl f # -- Begin function f + .p2align 4, 0x90 + .type f,@function +f: # @f + .cfi_startproc +# %bb.0: + testl %edi, %edi + jle .LBB0_1 +# %bb.3: + xorl %ecx, %ecx + xorl %eax, %eax + .p2align 4, 0x90 +.LBB0_4: # =>This Inner Loop Header: Depth=1 + movl %ecx, %edx + andl %edi, %edx + addl %edx, %eax + inc %ecx + cmpl %ecx, %edi + jne .LBB0_4 +# %bb.2: + jmp .LBB0_5 +.LBB0_1: + xorl %eax, %eax +.LBB0_5: + retq +.Lfunc_end0: + .size f, .Lfunc_end0-f + .cfi_endproc + # -- End function + + .ident "clang version 6.0.0 (tags/RELEASE_600/final)" + .section ".note.GNU-stack","",@progbits diff --git a/testsuite/tests/R507-014-trailing-byte-insn/main.c b/testsuite/tests/R507-014-trailing-byte-insn/main.c new file mode 100644 index 000000000..be64ef8ba --- /dev/null +++ b/testsuite/tests/R507-014-trailing-byte-insn/main.c @@ -0,0 +1,10 @@ +#include + +int f (int n); + +int +main () +{ + printf ("%i\n", f (1)); + return 0; +} diff --git a/testsuite/tests/R507-014-trailing-byte-insn/test.opt b/testsuite/tests/R507-014-trailing-byte-insn/test.opt new file mode 100644 index 000000000..2a96f27e2 --- /dev/null +++ b/testsuite/tests/R507-014-trailing-byte-insn/test.opt @@ -0,0 +1,3 @@ +5.04a1 DEAD Requires assembly features not in 5.04a1 +!bin-traces DEAD Binary traces specific testcase +!x86_64-linux DEAD Contains assembly code for x86_64-linux diff --git a/testsuite/tests/R507-014-trailing-byte-insn/test.py b/testsuite/tests/R507-014-trailing-byte-insn/test.py new file mode 100644 index 000000000..869c7b66f --- /dev/null +++ b/testsuite/tests/R507-014-trailing-byte-insn/test.py @@ -0,0 +1,61 @@ +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +wd = Wdir('tmp_') +main = exepath_to('main') +main_trace = tracename_for('main') + +gpr = gprfor(['main.c'], srcdirs='..', langs=('C', 'Asm')) +gprbuild(gpr) + +xrun(main) +xcov(['coverage', '-cbranch', '-aasm', main_trace, '--routines=f'], + out='coverage.log') + +pattern = """\ +Coverage level: branch +f !: [0-9a-f]+-[0-9a-f]+ +[0-9a-f]+ \\+: 85 ff test %edi,%edi +[0-9a-f]+ v: 7e 1a jle 0x[0-9a-f]+ +[0-9a-f]+ \\+: 31 c9 xor %ecx,%ecx +[0-9a-f]+ \\+: 31 c0 xor %eax,%eax +[0-9a-f]+ \\+: 0f 1f 84 00 00 00 00 00 nopl 0x0\\(%rax,%rax,1\\) +[0-9a-f]+ \\+: 89 ca mov %ecx,%edx +[0-9a-f]+ \\+: 21 fa and %edi,%edx +[0-9a-f]+ \\+: 01 d0 add %edx,%eax +[0-9a-f]+ \\+: ff c1 inc %ecx +[0-9a-f]+ \\+: 39 cf cmp %ecx,%edi +[0-9a-f]+ v: 75 f4 jne 0x[0-9a-f]+ +[0-9a-f]+ \\+: eb 02 jmp 0x[0-9a-f]+ +[0-9a-f]+ -: 31 c0 xor %eax,%eax +[0-9a-f]+ \\+: c3 ret +14 instructions analyzed: + 13 covered + 1 not executed +2 conditional branches analyzed: + 0 fully covered + 2 partially covered + 0 not executed""" + +pattern_lines = pattern.splitlines() +log_lines = contents_of('coverage.log').splitlines() + +thistest.fail_if( + len(pattern_lines) != len(log_lines), + 'The output of "gnatcov coverage" is {} lines long, {} expected'.format( + len(log_lines), len(pattern_lines))) + +for pat, log in zip(pattern_lines, log_lines): + thistest.fail_if( + not re.match(pat, log), + 'Could not match "gnatcov coverage" output:\n' + '{}\n' + 'against the expected pattern:\n' + '{}\n'.format(indent(log), indent(pat))) + +thistest.result() diff --git a/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected b/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected new file mode 100644 index 000000000..126080317 --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/tests/R507-027-xml-summary/data.ads b/testsuite/tests/R507-027-xml-summary/data.ads new file mode 100644 index 000000000..67b68cec0 --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/data.ads @@ -0,0 +1,3 @@ +package Data is + One : Integer := 1; +end Data; diff --git a/testsuite/tests/R507-027-xml-summary/main.adb b/testsuite/tests/R507-027-xml-summary/main.adb new file mode 100644 index 000000000..c25a537ac --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/main.adb @@ -0,0 +1,9 @@ +with Data; +with Pkg; + +procedure Main is + X : Boolean := Pkg.F1 (Data.One); + Y : Boolean := Pkg.F2 (Data.One); +begin + null; +end Main; diff --git a/testsuite/tests/R507-027-xml-summary/pkg.adb b/testsuite/tests/R507-027-xml-summary/pkg.adb new file mode 100644 index 000000000..a3c1a0ea4 --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/pkg.adb @@ -0,0 +1,23 @@ +package body Pkg is + + function F1 (I : Integer) return Boolean is + begin + if I < 0 then + return False; + else + return True; + end if; + end F1; + + function F2 (I : Integer) return Boolean is + begin + pragma Annotate (Xcov, Exempt_On, "Exempted because this is a test"); + if I > 10 then + return False; + else + return True; + end if; + pragma Annotate (Xcov, Exempt_Off); + end F2; + +end Pkg; diff --git a/testsuite/tests/R507-027-xml-summary/pkg.ads b/testsuite/tests/R507-027-xml-summary/pkg.ads new file mode 100644 index 000000000..d5aa3e275 --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + function F1 (I : Integer) return Boolean; + function F2 (I : Integer) return Boolean; +end Pkg; diff --git a/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected b/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected new file mode 100644 index 000000000..34fa134e3 --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/tests/R507-027-xml-summary/test.opt b/testsuite/tests/R507-027-xml-summary/test.opt new file mode 100644 index 000000000..a4e1eba80 --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/R507-027-xml-summary/test.py b/testsuite/tests/R507-027-xml-summary/test.py new file mode 100644 index 000000000..69784063e --- /dev/null +++ b/testsuite/tests/R507-027-xml-summary/test.py @@ -0,0 +1,34 @@ +""" +Check the content of an XML summary. This test verifies part of the +implementation done in the course of S213-006 (obligation metrics). +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +wd = Wdir('tmp_') + +gpr = gprfor(['main.adb'], srcdirs='..') +xcov_args = build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + covlevel='stmt+decision', + mains=['main'], + extra_coverage_args=['-axml']) + +if thistest.options.trace_mode == 'bin': + thistest.fail_if_diff( + os.path.join("..", "bin-traces-index.xml.expected"), + os.path.join("obj", "index.xml") + ) +else: + assert(thistest.options.trace_mode == 'src') + thistest.fail_if_diff( + os.path.join("..", "src-traces-index.xml.expected"), + os.path.join("obj", "index.xml") + ) + +thistest.result() diff --git a/testsuite/tests/R521-002-profile-arcs/main.adb b/testsuite/tests/R521-002-profile-arcs/main.adb new file mode 100644 index 000000000..1dd86779e --- /dev/null +++ b/testsuite/tests/R521-002-profile-arcs/main.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + function Compute return Integer; + pragma Import (C, Compute); +begin + Put_Line ("Hello, world!" & Integer'Image (Compute)); +end Main; diff --git a/testsuite/tests/R521-002-profile-arcs/test.opt b/testsuite/tests/R521-002-profile-arcs/test.opt new file mode 100644 index 000000000..a8ec33335 --- /dev/null +++ b/testsuite/tests/R521-002-profile-arcs/test.opt @@ -0,0 +1,4 @@ +7.0.2 DEAD Test relies on a compiler change introduced on 2018-06, not in 7.0.2 +!native DEAD Test relies on a working gcov setup, which we only have with native toolchains +!bin-traces DEAD Test makes sense only with compiler SCOs +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/R521-002-profile-arcs/test.py b/testsuite/tests/R521-002-profile-arcs/test.py new file mode 100644 index 000000000..cee89301e --- /dev/null +++ b/testsuite/tests/R521-002-profile-arcs/test.py @@ -0,0 +1,31 @@ +import re + +from SUITE.cutils import Wdir, lines_of +from SUITE.tutils import (exepath_to, gprfor, gprbuild, thistest, + tracename_for, xcov, xrun) + + +wd = Wdir('tmp_') +main = exepath_to('main') +main_trace = tracename_for('main') + +gpr = gprfor(['main.adb'], srcdirs='..', langs=('Ada', 'C')) +gprbuild(gpr, extracargs='-fprofile-arcs', + largs='-fprofile-arcs -ftest-coverage') + +xrun(main) +xcov(['coverage', '-P', gpr, '-cstmt+decision', '-axml', main_trace], + out='coverage.log') + +warning_template = (r'warning: .*{}: unit compiled with instrumentation' + r' \(-fprofile-arcs\)') + +for unit in ('main.ali', 'util.c.gli'): + thistest.fail_if( + not any(re.match(warning_template.format(re.escape(unit)), line) + for line in lines_of('coverage.log')), + 'Warning about -fprofile-arcs for {} not found in output of' + ' "gnatcov coverage"'.format(unit) + ) + +thistest.result() diff --git a/testsuite/tests/R521-002-profile-arcs/util.c b/testsuite/tests/R521-002-profile-arcs/util.c new file mode 100644 index 000000000..add85606c --- /dev/null +++ b/testsuite/tests/R521-002-profile-arcs/util.c @@ -0,0 +1,7 @@ +extern int compute (void); + +int +compute (void) +{ + return 1; +} diff --git a/testsuite/tests/R807-027-symbol-order/p.adb b/testsuite/tests/R807-027-symbol-order/p.adb new file mode 100644 index 000000000..5e8d5a76a --- /dev/null +++ b/testsuite/tests/R807-027-symbol-order/p.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure P is +begin + Pkg.Foo; + Pkg.Bar; +end P; diff --git a/testsuite/tests/R807-027-symbol-order/pkg.adb b/testsuite/tests/R807-027-symbol-order/pkg.adb new file mode 100644 index 000000000..0f2fbc4d7 --- /dev/null +++ b/testsuite/tests/R807-027-symbol-order/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + + procedure Foo is null; + procedure Bar is null; + +end Pkg; diff --git a/testsuite/tests/R807-027-symbol-order/pkg.ads b/testsuite/tests/R807-027-symbol-order/pkg.ads new file mode 100644 index 000000000..5b7f7c375 --- /dev/null +++ b/testsuite/tests/R807-027-symbol-order/pkg.ads @@ -0,0 +1,6 @@ +package Pkg is + + procedure Foo; + procedure Bar; + +end Pkg; diff --git a/testsuite/tests/R807-027-symbol-order/test.opt b/testsuite/tests/R807-027-symbol-order/test.opt new file mode 100644 index 000000000..df872a03f --- /dev/null +++ b/testsuite/tests/R807-027-symbol-order/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 +!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/R807-027-symbol-order/test.py b/testsuite/tests/R807-027-symbol-order/test.py new file mode 100644 index 000000000..8945a853c --- /dev/null +++ b/testsuite/tests/R807-027-symbol-order/test.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- + +""" +Check that the order of symbols in GNATcov's assembly coverage report is +deterministic (sorted, even). +""" + +import re +from SUITE.control import target_info +from SUITE.cutils import Wdir, lines_of +from SUITE.tutils import (exepath_to, gprfor, gprbuild, thistest, + tracename_for, xcov, xrun) + + +tmp = Wdir('tmp_') + +symbols = [target_info().to_platform_specific_symbol(s) + for s in ['pkg__bar', 'pkg__foo']] + +routines = 'routines.txt' +report = 'coverage-report.txt' +with open(routines, 'w') as f: + for s in symbols: + f.write(s + '\n') + +prj = gprfor('p.adb', srcdirs='..') +gprbuild(prj) + +xrun(exepath_to('p')) +xcov(['coverage', '-cinsn', '-aasm', '-o', report, + '--routines=@routines.txt', tracename_for('p')]) + +report_symbols = sorted( + line.split()[0] for line in lines_of(report) + if re.match('^[a-z_]* [+!-]: [0-9a-f]+-[0-9a-f]+', line.rstrip()) +) + + +def fmt_list(items): + return '\n'.join(' ' + line for line in items) + + +thistest.fail_if( + symbols != report_symbols, + 'Unexpected sequence of symbols, expected:\n' + '{}\n' + 'but got:\n' + '{}'.format(fmt_list(symbols), fmt_list(report_symbols)) +) + +thistest.result() diff --git a/testsuite/tests/RB13-019-win-paths/.gitignore b/testsuite/tests/RB13-019-win-paths/.gitignore new file mode 100644 index 000000000..6f4743e41 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/.gitignore @@ -0,0 +1,9 @@ +coverage +driver +driver.exe +*.gli +*.dmap +*.o +*.trace +*.i +*.s diff --git a/testsuite/tests/RB13-019-win-paths/Makefile b/testsuite/tests/RB13-019-win-paths/Makefile new file mode 100644 index 000000000..10e06edde --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/Makefile @@ -0,0 +1,12 @@ +CC=gcc +CFLAGS=-fpreserve-control-flow -fdump-scos -g -save-temps +LDFLAGS=$(CFLAGS) -no-pie + +driver: driver.o wibble.o + +wibble.o: wibble.c wibble.h + +driver.o: wibble.h driver.c + +clean: + rm -f *.o *.exe driver *.c.gli *.i *.s diff --git a/testsuite/tests/RB13-019-win-paths/driver.c b/testsuite/tests/RB13-019-win-paths/driver.c new file mode 100644 index 000000000..e9a0c646a --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/driver.c @@ -0,0 +1,26 @@ +#include "wibble.h" + +#include +#include + +int +check (int condition) +{ + if (condition) + { + printf ("PASS\n"); + } + else + { + printf ("FAIL\n"); + } +} + +int +main (int argc, char **argv) +{ + check (foo (3, 2) == 0); + check (foo (3, 3) == 1); + // check(foo(3, 7) == 1); + check (foo (0, 0) == 0); +} diff --git a/testsuite/tests/RB13-019-win-paths/test.opt b/testsuite/tests/RB13-019-win-paths/test.opt new file mode 100644 index 000000000..321d779fb --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/test.opt @@ -0,0 +1,2 @@ +!native DEAD +src-traces DEAD source instrumentation not available for C diff --git a/testsuite/tests/RB13-019-win-paths/test.py b/testsuite/tests/RB13-019-win-paths/test.py new file mode 100644 index 000000000..4881b1302 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/test.py @@ -0,0 +1,41 @@ +""" +Check that gnatcov does not complain about "same base name for files" and +computes the expected code coverage when C files are compiled with a Makefile. + +This used not to work because in this build scenario on Windows, debug info +used to contain unexpected double slash as directory separators. +""" + +import os.path + +import shutil + +from e3.os.process import Run + +from SCOV.minicheck import check_xcov_reports +from SUITE.cutils import FatalError +from SUITE.tutils import exepath_to, thistest, tracename_for, xcov, xrun + + +if os.path.exists('coverage'): + shutil.rmtree('coverage') +p = Run(['make', 'clean']) + +main = exepath_to('driver') +main_trace = tracename_for('driver') + +p = Run(['make']) +thistest.stop_if(p.status != 0, FatalError('call to "make" failed')) + +xcflags = ['-cstmt+mcdc', '--scos=wibble.c.gli', '--scos=driver.c.gli'] + +xrun(xcflags + [main]) +xcov(['coverage'] + xcflags + + ['-axcov', '--output-dir=coverage', '-T', main_trace]) + +check_xcov_reports( + os.path.join('coverage', 'wibble.c.xcov'), + {os.path.join('coverage', 'wibble.c.xcov'): {'+': {8, 12}, '!': {6}}} +) + +thistest.result() diff --git a/testsuite/tests/RB13-019-win-paths/wibble.c b/testsuite/tests/RB13-019-win-paths/wibble.c new file mode 100644 index 000000000..62e0d785b --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/wibble.c @@ -0,0 +1,14 @@ +#include "wibble.h" + +int +foo (int a, int b) +{ + if (a > 0 && (b == 3 || b == 7)) + { + return 1; + } + else + { + return 0; + } +} diff --git a/testsuite/tests/RB13-019-win-paths/wibble.h b/testsuite/tests/RB13-019-win-paths/wibble.h new file mode 100644 index 000000000..2b57aeae1 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/wibble.h @@ -0,0 +1,6 @@ +#ifndef __WIBBLE_H +#define __WIBBLE_H + +int foo (int a, int b); + +#endif diff --git a/testsuite/tests/RB16-008-gpr-tool/main.adb b/testsuite/tests/RB16-008-gpr-tool/main.adb new file mode 100644 index 000000000..424a11933 --- /dev/null +++ b/testsuite/tests/RB16-008-gpr-tool/main.adb @@ -0,0 +1,8 @@ +with Unit_GNATcoverage, Unit_Env_Var, Unit_X_Arg; + +procedure Main is +begin + Unit_GNATcoverage; + Unit_Env_Var; + Unit_X_Arg; +end Main; diff --git a/testsuite/tests/RB16-008-gpr-tool/test.py b/testsuite/tests/RB16-008-gpr-tool/test.py new file mode 100644 index 000000000..30afa2705 --- /dev/null +++ b/testsuite/tests/RB16-008-gpr-tool/test.py @@ -0,0 +1,78 @@ +""" +Check that gnatcov processes the GPR_TOOL environment variable/scenario +variables as expected. +""" + +import glob +import os.path + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +# Ways to convey to gnatcov a value for the GPR_TOOL variable +env_var = 'env_var' # Environment variable +x_arg = 'x_arg' # -X command-line argument + +# List of scenarios to test. Each tuple contains: +# +# 1) The set of ways to convey the GPR_TOOL variable to gnatcov +# 2) The unit of interest we expect for this scenario. +# +# -X arguments take precedence over everything else. Then comes the environment +# variable, and finally, by default GPR_TOOL is supposed to be "gnatcoverage". +test_scenarios = [ + (set(), 'unit_gnatcoverage'), + ({env_var}, 'unit_env_var'), + ({x_arg}, 'unit_x_arg'), + ({env_var, x_arg}, 'unit_x_arg'), +] + +for ways, expected_unit in test_scenarios: + ways_str = '-'.join(sorted(ways)) or 'default' + + wd = Wdir(f"tmp_{ways_str}") + + # Build the test program and produce a trace + gpr = gprfor(['main.adb'], srcdirs='..', extra=""" + GPR_Tool := external ("GPR_TOOL", ""); + package Coverage is + for Units use ("unit_" & GPR_Tool); + end Coverage; + """) + + # Prepare the (sometimes conflicting) ways to convey the GPR_TOOL variable + # to gnatcov. + common_xcov_args = [] + os.environ.pop('GPR_TOOL', None) + if env_var in ways: + os.environ['GPR_TOOL'] = 'env_var' + if x_arg in ways: + common_xcov_args.append('-XGPR_TOOL=x_arg') + + # Produce a coverage report for this configuration + build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov'], + extra_args=common_xcov_args) + + # Check that the report contains what we expect + reported_units = sorted(glob.glob(os.path.join("obj", "*.xcov"))) + expected_report = os.path.join("obj", f"{expected_unit}.adb.xcov") + + thistest.fail_if( + reported_units != [expected_report], + 'Unexpected set of coverage reports, expected:\n' + ' {}\n' + 'but got:\n' + '{}'.format(expected_report, '\n'.join(' {}'.format(f) + for f in reported_units))) + + wd.to_homedir() + +thistest.result() diff --git a/testsuite/tests/RB16-008-gpr-tool/unit_env_var.adb b/testsuite/tests/RB16-008-gpr-tool/unit_env_var.adb new file mode 100644 index 000000000..2ca42ee58 --- /dev/null +++ b/testsuite/tests/RB16-008-gpr-tool/unit_env_var.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; + +procedure Unit_Env_Var is +begin + Ada.Text_IO.Put_Line ("In Unit_Env_Var"); +end; diff --git a/testsuite/tests/RB16-008-gpr-tool/unit_gnatcoverage.adb b/testsuite/tests/RB16-008-gpr-tool/unit_gnatcoverage.adb new file mode 100644 index 000000000..1aeece17c --- /dev/null +++ b/testsuite/tests/RB16-008-gpr-tool/unit_gnatcoverage.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; + +procedure Unit_GNATcoverage is +begin + Ada.Text_IO.Put_Line ("In Unit_GNATcoverage"); +end; diff --git a/testsuite/tests/RB16-008-gpr-tool/unit_x_arg.adb b/testsuite/tests/RB16-008-gpr-tool/unit_x_arg.adb new file mode 100644 index 000000000..0b54fe52b --- /dev/null +++ b/testsuite/tests/RB16-008-gpr-tool/unit_x_arg.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; + +procedure Unit_X_Arg is +begin + Ada.Text_IO.Put_Line ("In Unit_X_Arg"); +end; diff --git a/testsuite/tests/RC04-030-bad-trace/.gitignore b/testsuite/tests/RC04-030-bad-trace/.gitignore new file mode 100644 index 000000000..511ee6c49 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/.gitignore @@ -0,0 +1,7 @@ +coverage +driver +driver.exe +*.gli +*.dmap +*.o +*.trace diff --git a/testsuite/tests/RC04-030-bad-trace/main_a.adb b/testsuite/tests/RC04-030-bad-trace/main_a.adb new file mode 100644 index 000000000..eee397a62 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/main_a.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_A is +begin + Pkg.Run (True, False, False); +end Main_A; diff --git a/testsuite/tests/RC04-030-bad-trace/main_b.adb b/testsuite/tests/RC04-030-bad-trace/main_b.adb new file mode 100644 index 000000000..8dafa2700 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/main_b.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_B is +begin + Pkg.Run (False, True, False); +end Main_B; diff --git a/testsuite/tests/RC04-030-bad-trace/main_c.adb b/testsuite/tests/RC04-030-bad-trace/main_c.adb new file mode 100644 index 000000000..107d21a13 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/main_c.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_C is +begin + Pkg.Run (False, False, True); +end Main_C; diff --git a/testsuite/tests/RC04-030-bad-trace/pkg.adb b/testsuite/tests/RC04-030-bad-trace/pkg.adb new file mode 100644 index 000000000..927091668 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/pkg.adb @@ -0,0 +1,22 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + --------- + -- Run -- + --------- + + procedure Run (A, B, C : Boolean) is + begin + if A then + Put_Line ("A is true"); + end if; + if B then + Put_Line ("B is true"); + end if; + if C then + Put_Line ("C is true"); + end if; + end Run; + +end Pkg; diff --git a/testsuite/tests/RC04-030-bad-trace/pkg.ads b/testsuite/tests/RC04-030-bad-trace/pkg.ads new file mode 100644 index 000000000..40be93447 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Run (A, B, C : Boolean); +end Pkg; diff --git a/testsuite/tests/RC04-030-bad-trace/test.opt b/testsuite/tests/RC04-030-bad-trace/test.opt new file mode 100644 index 000000000..a42e26bd4 --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test feature related to binary traces diff --git a/testsuite/tests/RC04-030-bad-trace/test.py b/testsuite/tests/RC04-030-bad-trace/test.py new file mode 100644 index 000000000..eb7ecea5f --- /dev/null +++ b/testsuite/tests/RC04-030-bad-trace/test.py @@ -0,0 +1,106 @@ +""" +Check that, with --keep-reading-traces, when processing malformed trace files, +gnatcov emits diagnostics that are useful to identify which trace file is +malformed. Also check that the computation of the coverage report go to +completion, and that gnatcov still exits with an error status code. +""" + +import os +import os.path +import re + +from SCOV.minicheck import check_xcov_reports +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.tutils import (exepath_to, gprfor, gprbuild, thistest, + tracename_for, xcov, xrun) + + +def indexes(string, substr): + """ + Return the list of all indexes in "string" at which the given substring can + be found. + """ + result = [] + start = 0 + while start < len(string): + i = string.find(substr, start) + if i == -1: + break + result.append(i) + start = i + 1 + return result + + +tmp = Wdir('tmp_') +os.mkdir('traces') + +mains = ('main_a', 'main_b', 'main_c') +tracefiles = [os.path.join('traces', tracename_for(m)) for m in mains] + +prj = gprfor(['{}.adb'.format(m) for m in mains], srcdirs='..') +gprbuild(prj) + +# Produce trace files for all mains +for main, tracefile in zip(mains, tracefiles): + xrun([exepath_to(main), + '-o', tracefile, + '-T', 'Trace for {}'.format(main)]) + +# Corrupt the trace for main_b. Look for the second trace header and truncate +# the file in the middle of a trace entry. We go through this to get an error +# that is consistent across runs. +with open(tracefiles[1], 'rb') as f: + data = f.read() +header_indexes = indexes(data, b'#QEMU-Traces') +header_size = 20 # See Qemu_Traces.Trace_Header +with open(tracefiles[1], 'wb') as f: + f.write(data[:header_indexes[1] + header_size + 5]) + + +def gnatcov_coverage(keep_reading_traces): + log_file = 'coverage-{}.log'.format( + 'krt' if keep_reading_traces else 'default') + + argv = ['coverage', '-axcov', '-cstmt', '-P{}'.format(prj)] + if keep_reading_traces: + argv.append('--keep-reading-traces') + + p = xcov(argv + tracefiles, out=log_file, register_failure=False) + thistest.fail_if(p.status == 0, + '"gnatcov coverage" status code is 0 (error expected)') + + coverage_log = contents_of(log_file).strip() + expected_log = re.compile( + # Regexp to accommodate output differences between the various + # supported platforms. + '[^\n]*gnatcov[^\n]*: traces[/\\\\]main_b[^\n]*.trace: file truncated') + thistest.fail_if(not expected_log.match(coverage_log), + 'Unexpected output for "gnatcov coverage". Expected:\n' + '{}\n' + 'but got:\n' + '{}'.format(indent(expected_log.pattern), + indent(coverage_log))) + + +# Make sure that without --keep-reading-traces, no coverage report is produced +gnatcov_coverage(False) +check_xcov_reports('obj/*.xcov', {}) + + +def in_obj(filename): + return os.path.join('obj', filename) + + +# Make sure that with it, both the first and the last trace files contributed +# to coverage assessment, while the middle one was skipped. +gnatcov_coverage(True) +check_xcov_reports( + in_obj('*.xcov'), + {in_obj('pkg.adb.xcov'): {'+': {11, 12, 14, 17, 18}, + '-': {15}}, + in_obj('main_a.adb.xcov'): {'+': {5}}, + in_obj('main_b.adb.xcov'): {'-': {5}}, + in_obj('main_c.adb.xcov'): {'+': {5}}} +) + +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/src/raise_exception.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/src/raise_exception.adb new file mode 100644 index 000000000..116f8abfb --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/src/raise_exception.adb @@ -0,0 +1,10 @@ +with Support; use Support; +with P; use P; + +procedure Raise_Exception is +begin + raise Force_Exception; -- # force_exception +exception + when Force_Exception => + raise Constraint_Error; -- # raise +end Raise_Exception; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/src/raise_exception.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/src/raise_exception.adb new file mode 100644 index 000000000..087584c82 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/src/raise_exception.adb @@ -0,0 +1,12 @@ +with Support; use Support; +with P; use P; + +procedure Raise_Exception is + X: Integer; + pragma Unsuppress (All_Checks); +begin + raise Force_Exception; -- # force_exception +exception + when Force_Exception => + X := Identity(5)/Identity (0); -- # raise +end Raise_Exception; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/src/raise_exception.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/src/raise_exception.adb new file mode 100644 index 000000000..e13ecd3c9 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/src/raise_exception.adb @@ -0,0 +1,11 @@ +with P; use P; + +procedure Raise_Exception is +begin + raise Constraint_Error; -- # force_exception +exception + when Constraint_Error => + raise; -- # raise + when others => + Wrong_Exception_Propagated := True; -- # wrong_exception +end; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/notes.txt b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/notes.txt new file mode 100644 index 000000000..f355d7772 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/notes.txt @@ -0,0 +1,9 @@ +Check coverage of exceptions that are raised in an exception handler + +We check for exceptions raised: + + - implicitly, e.g. an arithmetic operation that raises CE + + - explicitly, via a "raise CE" stmt + + - reraised exceptions, i.e. via a "raise;" statement diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.adb new file mode 100644 index 000000000..4a22eb4ef --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.adb @@ -0,0 +1,12 @@ +with P; use P; +with Raise_Exception; + +procedure Handle_Exception is +begin + Raise_Exception; -- # raise +exception + when Constraint_Error => + Correct_Exception_Propagated := True; -- # handled + when others => + Wrong_Exception_Propagated := True; -- # mis_handled +end Handle_Exception; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.ads new file mode 100644 index 000000000..3a1aacd52 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/handle_exception.ads @@ -0,0 +1 @@ +procedure Handle_Exception; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/p.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/p.ads new file mode 100644 index 000000000..9c3a26db9 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/p.ads @@ -0,0 +1,7 @@ +package P is + Force_Exception: Exception; + + Correct_Exception_Propagated : Boolean := False; + Wrong_Exception_Propagated : Boolean := False; + +end P; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/raise_exception.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/raise_exception.ads new file mode 100644 index 000000000..a9ef4e099 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/raise_exception.ads @@ -0,0 +1 @@ +procedure raise_exception; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/test_raise_exception.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/test_raise_exception.adb new file mode 100644 index 000000000..fe5b64e5b --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/src/test_raise_exception.adb @@ -0,0 +1,20 @@ +with Support; use Support; +with P; use P; +with Handle_Exception; +procedure test_raise_exception is +begin + Handle_Exception; + + Assert (Correct_Exception_Propagated = True); + Assert (Wrong_Exception_Propagated = False); + +end; + +--# handle_exception.adb +-- /raise/ l+ ## 0 +-- /handled/ l+ ## 0 +-- /mis_handled/ l- ## s- +--# raise_exception.adb +-- /force_exception/ l+ ## 0 +-- /raise/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/src/elab.adb new file mode 100644 index 000000000..0fcc753aa --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/src/elab.adb @@ -0,0 +1,31 @@ +pragma Unsuppress (All_Checks); + +with Support; use Support; +with Global; use Global; +procedure Elab (Val_In_Range: Integer) is +begin + + begin -- outer + declare + X : integer ; -- # decl + package Pack is + I : integer range 2..10 := Val_In_Range; -- # violation + end Pack; + begin + X := Identity (5); -- # stmt + exception + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; + exception + when storage_error | program_error => + Wrong_Exception_Raised := True; -- # wrong_handler + end; --outer +exception + when Constraint_Error => + Correct_Exception_Raised := True; -- # properly_handled + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/src/elab.adb new file mode 100644 index 000000000..beab14adb --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/src/elab.adb @@ -0,0 +1,33 @@ +pragma Unsuppress (All_Checks); + +with Support; use Support; +with Global; use Global; +procedure Elab (Val_In_Range: Integer) is +begin + + begin -- outer + declare + X : integer ; -- # decl + package Pack is + I : integer range 2..10 := Val_In_Range; -- # violation + end Pack; + begin + X := Identity (5); -- # stmt + exception + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; + exception + when storage_error | program_error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Correct_Exception_Raised := True; -- # properly_handled + end; --outer +exception + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_exception + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/src/elab.adb new file mode 100644 index 000000000..cbf090676 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/src/elab.adb @@ -0,0 +1,25 @@ +pragma Unsuppress (All_Checks); + +with Support; use Support; +with Global; use Global; +procedure Elab (Val_In_Range: Integer) is +begin + declare + X : integer ; -- # decl + package Pack is + I : integer range 2..10 := Val_In_Range; -- # violation + end Pack; + begin + X := Identity (5); -- # stmt + exception + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; +exception + when Constraint_Error => + Correct_Exception_Raised := True; -- # properly_handled + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_calls.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_calls.adb new file mode 100644 index 000000000..98ad04673 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_calls.adb @@ -0,0 +1,27 @@ +-- Driver to test intrasubprogram package elaboration. +-- Do not call the procedure containing the package elaboration. +-- All of the code should be uncovered. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_calls is +begin + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /decl/ l- ## s- +-- /violation/ l- ## s- +-- /stmt/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- + +-- 7.0.3 misses dominance markers that would +-- allow marking our bare decls accurately: + +--%tags: 7.0.3 +-- =/decl/ ~l- ## ~s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_raise.adb new file mode 100644 index 000000000..dd2017d34 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_no_raise.adb @@ -0,0 +1,31 @@ +-- Driver to test intrasubprogram package elaboration. +-- Call procedure Elab so that the package elaboration nested within +-- it does not raise an exception. Check that the entire block is +-- executed and that the code of the exception handlers are +-- uncovered. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_raise is +begin + Elab (2); + + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /decl/ l+ ## 0 +-- /violation/ l+ ## 0 +-- /stmt/ l+ ## 0 +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- + +-- 7.0.3 misses dominance markers that would +-- allow marking our bare decls accurately: + +--%tags: 7.0.3 +-- =/decl/ ~l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_raise.adb new file mode 100644 index 000000000..c3d790de7 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/src/test_elab_raise.adb @@ -0,0 +1,31 @@ +-- Driver to test intrasubprogram package elaboration. +-- Call procedure Elab so that the package elaboration nested within +-- it raises an exception. Check that the exception is handled +-- properly, and that the statements of the block in which the +-- exception are uncovered -- i.e. not executed. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_raise is +begin + Elab (20); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /decl/ l+ ## 0 +-- /violation/ l+ ## 0 +-- /stmt/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- + +-- 7.0.3 misses dominance markers that would +-- allow marking our bare decls accurately: + +--%tags: 7.0.3 +-- =/decl/ ~l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/elab.adb new file mode 100644 index 000000000..caf6a8b12 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/elab.adb @@ -0,0 +1,26 @@ +pragma Unsuppress (All_Checks); + +with Support; use Support; +with Global; use Global; +with SubP; use SubP; +procedure Elab (Val: Integer) is +begin + declare + X : Integer ; -- # decl + package Pack is + I : integer range 2..10 := func(Val); -- # implicit_violation + end Pack; + begin + X := Identity (5); -- # no_imp_violation + exception + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; +exception + when Constraint_Error => + Correct_Exception_Raised := True; -- # properly_handled + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.adb new file mode 100644 index 000000000..3b6724020 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.adb @@ -0,0 +1,13 @@ +package body SubP is + + function func (x: integer) return integer is + -- x must be in range 1 thru 10 + begin + if x < 1 or x >=10 then -- # test + raise Constraint_Error; -- # explicit_violation + else + return x; -- # no_exp_violation + end if; + end func; + +end SubP; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.ads new file mode 100644 index 000000000..215f64e9a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/subp.ads @@ -0,0 +1,5 @@ +package SubP is + + function func (x: integer) return integer; + +end SubP; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_exp_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_exp_raise.adb new file mode 100644 index 000000000..370ce569b --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_exp_raise.adb @@ -0,0 +1,26 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that Constraint_Error +-- is explicitly raised and propagated to the calling subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_exp_raise is +begin + Elab (20); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# subp.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l+ ## 0 +-- /no_exp_violation/ l- ## s- +--# elab.adb +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_imp_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_imp_raise.adb new file mode 100644 index 000000000..78c215ec4 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_imp_raise.adb @@ -0,0 +1,28 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that Constraint_Error +-- is implicitly raised. +-- Note: in this case, the exception is actually not propagated to +-- another subprogram, but handled by the same subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_imp_raise is +begin + Elab (1); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# subp.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l- ## s- +--# elab.adb +-- /no_exp_violation/ l+ ## 0 +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_calls.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_calls.adb new file mode 100644 index 000000000..972c9e1e3 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_calls.adb @@ -0,0 +1,23 @@ +-- Driver to test exception propagation across subprograms. +-- Do not call the functional code. Everything should be uncovered. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_calls is +begin + Assert (Wrong_Exception_Raised = False); +end; + +--# subp.adb +-- /test/ l- ## s- +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l- ## s- +--# elab.adb +-- /decl/ ~l- ## ~s- +-- /implicit_violation/ l- ## s- +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_raise.adb new file mode 100644 index 000000000..496d00285 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/src/test_elab_no_raise.adb @@ -0,0 +1,26 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that Constraint_Error +-- is not raised at all. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_raise is +begin + Elab (2); + + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# subp.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l+ ## 0 +--# elab.adb +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l+ ## 0 +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/elab.adb new file mode 100644 index 000000000..d84bf8f99 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/elab.adb @@ -0,0 +1,29 @@ +with Support; use Support; +with Global; use Global; +with SubP; use SubP; +procedure Elab (Val: Integer) is + +begin + declare + X : Integer ; -- # decl + package Pack is + I : integer range 2..10 := func(Val); -- # implicit_violation + end Pack; + begin + X := Identity (5); -- # no_imp_violation + exception + when My_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; +exception + when My_Error => + Correct_Exception_Raised := True; -- # properly_handled + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_exception + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.adb new file mode 100644 index 000000000..95d0779b8 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.adb @@ -0,0 +1,13 @@ +package body SubP is + + function func (x: integer) return integer is + -- x must be in range 1 thru 10 + begin + if x < 1 or x >=10 then -- # test + raise My_Error; -- # explicit_violation + else + return x; -- # no_exp_violation + end if; + end func; + +end SubP; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.ads new file mode 100644 index 000000000..c24d2fc66 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.ads @@ -0,0 +1,7 @@ +package SubP is + + function func (x: integer) return integer; + + My_Error: Exception; + +end SubP; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_exp_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_exp_raise.adb new file mode 100644 index 000000000..74ee58999 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_exp_raise.adb @@ -0,0 +1,25 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that a user +-- defined exception is raised and propagated to the calling subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_exp_raise is +begin + Elab (20); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l+ ## 0 +-- /no_exp_violation/ l- ## s- +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_calls.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_calls.adb new file mode 100644 index 000000000..73475c839 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_calls.adb @@ -0,0 +1,25 @@ +-- Driver to test exception propagation across subprograms. +-- Do not call the functional code. No exception raised, everything +-- is uncovered. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_calls is +begin + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# subp.adb +-- /test/ l- ## s- +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l- ## s- +--# elab.adb +-- /decl/ ~l- ## ~s- +-- /implicit_violation/ l- ## s- +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_raise.adb new file mode 100644 index 000000000..9c04e9f04 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/test_elab_no_raise.adb @@ -0,0 +1,25 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that the user +-- defined exception is not raised and propagated to the calling subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_raise is +begin + Elab (2); + + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l+ ## 0 +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l+ ## 0 +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/elab.adb new file mode 100644 index 000000000..1e671b23d --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/elab.adb @@ -0,0 +1,36 @@ +pragma Unsuppress (All_Checks); + +with Support; use Support; +with Global; use Global; +procedure Elab (Val: Integer) is + + function func (x: integer) return integer is + -- x must be in range 1 thru 10 + begin + if x < 1 or x > 10 then -- # test + raise Constraint_Error; -- # explicit_violation + else + return x; -- # no_exp_violation + end if; + end func; + +begin + declare + X : Integer range 0..9; -- # decl + package Pack is + I : integer range 2..10 := func(Val); -- # implicit_violation + end Pack; + begin + X := Identity (5); -- # no_imp_violation + exception + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; +exception + when Constraint_Error => + Correct_Exception_Raised := True; -- # properly_handled + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_exp_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_exp_raise.adb new file mode 100644 index 000000000..692bbf7df --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_exp_raise.adb @@ -0,0 +1,24 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that Constraint_Error +-- is explicitly raised and propagated to the calling subprogram. +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_exp_raise is +begin + Elab (20); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l+ ## 0 +-- /no_exp_violation/ l- ## s- +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_imp_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_imp_raise.adb new file mode 100644 index 000000000..0932fa3e0 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_imp_raise.adb @@ -0,0 +1,27 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that Constraint_Error +-- is implicitly raised. +-- Note: in this case, the exception is actually not propagated to +-- another subprogram, but handled by the same subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_imp_raise is +begin + Elab (1); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l+ ## 0 +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_calls.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_calls.adb new file mode 100644 index 000000000..2908d10e8 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_calls.adb @@ -0,0 +1,23 @@ +-- Driver to test exception propagation across subprograms. +-- Do not call the functional code. Everything should be uncovered. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_calls is +begin + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /decl/ ~l- ## ~s- +-- /test/ l- ## s- +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l- ## s- +-- /implicit_violation/ l- ## s- +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_raise.adb new file mode 100644 index 000000000..7bae01f87 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/src/test_elab_no_raise.adb @@ -0,0 +1,25 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that Constraint_Error +-- is not raised at all. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_raise is +begin + Elab (2); + + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l+ ## 0 +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l+ ## 0 +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/elab.adb new file mode 100644 index 000000000..ec0e62ba6 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/elab.adb @@ -0,0 +1,40 @@ +with Support; use Support; +with Global; use Global; +procedure Elab (Val: Integer) is + + My_Error: Exception; -- # exception_decl + + function func (x: integer) return integer is + -- x must be in range 1 thru 10 + begin + if x < 1 or x > 10 then -- # test + raise My_Error; -- # explicit_violation + else + return x; -- # no_exp_violation + end if; + end func; + +begin + declare + X : integer ; -- # decl + package Pack is + I : integer range 2..10 := func(Val); -- # implicit_violation + end Pack; + begin + X := Identity (5); -- # no_imp_violation + exception + when My_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_handler + when others => + Wrong_Exception_Raised := True; -- # wrong_handler + end; +exception + when My_Error => + Correct_Exception_Raised := True; -- # properly_handled + when Constraint_Error => + Wrong_Exception_Raised := True; -- # wrong_exception + when others => + Wrong_Exception_Raised := True; -- # wrong_exception +end Elab; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_exp_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_exp_raise.adb new file mode 100644 index 000000000..74ee58999 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_exp_raise.adb @@ -0,0 +1,25 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that a user +-- defined exception is raised and propagated to the calling subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_exp_raise is +begin + Elab (20); + + Assert (Correct_Exception_Raised = True); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l+ ## 0 +-- /no_exp_violation/ l- ## s- +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l+ ## 0 +-- /wrong_exception/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_calls.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_calls.adb new file mode 100644 index 000000000..d7281c7b3 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_calls.adb @@ -0,0 +1,32 @@ +-- Driver to test exception propagation across subprograms. +-- Do not call the functional code. No exception raised, everything +-- is uncovered. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_calls is +begin + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /exception_decl/ l- ## s- +-- /test/ l- ## s- +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l- ## s- +-- /decl/ l- ## s- +-- /implicit_violation/ l- ## s- +-- /no_imp_violation/ l- ## s- +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- + +-- 7.0.3 misses dominance markers that would +-- allow marking our bare decls accurately: + +--%tags: 7.0.3 +-- =/exception_decl/ ~l- ## ~s- +-- =/decl/ ~l- ## ~s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_raise.adb new file mode 100644 index 000000000..f1eb5c0cf --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/test_elab_no_raise.adb @@ -0,0 +1,31 @@ +-- Driver to test exception propagation across subprograms. +-- Call a procedure containing a package spec, so that the user +-- defined exception is not raised and propagated to the calling subprogram. + +with Support; use Support; +with Elab; +with Global; use Global; + +procedure test_elab_no_raise is +begin + Elab (2); + + Assert (Correct_Exception_Raised = False); + Assert (Wrong_Exception_Raised = False); +end; + +--# elab.adb +-- /test/ l+ ## 0 +-- /explicit_violation/ l- ## s- +-- /no_exp_violation/ l+ ## 0 +-- /implicit_violation/ l+ ## 0 +-- /no_imp_violation/ l+ ## 0 +-- /wrong_handler/ l- ## s- +-- /properly_handled/ l- ## s- +-- /wrong_exception/ l- ## s- + +-- 7.0.3 misses dominance markers that would +-- allow marking our bare decls accurately: + +--%tags: 7.0.3 +-- =/decl/ ~l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/notes.txt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/notes.txt new file mode 100644 index 000000000..f2e3400da --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/notes.txt @@ -0,0 +1,14 @@ +Check for exception raised during package elaboration: + +We check: + Package elaborations in which the exceptions are raised and + handled within the same subprogram. These packages specs can appear + in a simple block, or a nexted block. The exceptions are either + handled immediately or propagated to an outer block within the same + subprogram. + + Package elaborations in which the exceptions are propagated and + handled by another (calling) subprogram. We test exceptions raised + in library units and exceptions that are raised within a nested + subprogram. User defined as well as predefined (implicit and explicit) + exceptions are tested. diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/src/global.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/src/global.ads new file mode 100644 index 000000000..74eed9e85 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/src/global.ads @@ -0,0 +1,4 @@ +package Global is + Correct_Exception_Raised : Boolean := False; + Wrong_Exception_Raised : Boolean := False; +end Global; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/div.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/div.adb new file mode 100644 index 000000000..fd7f6ff89 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/div.adb @@ -0,0 +1,17 @@ +package body Div is + procedure Divide (X, Y: Integer; Res: out Integer) is + begin + if Y = 0 then -- # explicit_check + raise My_Constraint_Error; -- # explicit_raise + else + Res := X/Y; -- # computation + end if; + exception + when My_Constraint_Error => + N_In_MyCE_Handler := N_In_MyCE_Handler + 1; -- # explicit_handler + when Constraint_Error => + N_In_Wrong_Handler := N_In_Wrong_Handler + 1; -- # wrong_handler + when others => + N_In_Wrong_Handler := N_In_Wrong_Handler + 1; -- # wrong_handler + end Divide; +end Div; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_nok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_nok.adb new file mode 100644 index 000000000..e1a1e10d1 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_nok.adb @@ -0,0 +1,22 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Nok is + + Result : Integer; + +begin + + Divide (12, 0, Result); + + Assert (N_In_MyCE_Handler = 1); + Assert (N_In_Wrong_Handler = 0); + +end Test_Divide_Nok; + +--# div.adb +-- /explicit_check/ l+ ## 0 +-- /explicit_raise/ l+ ## 0 +-- /computation/ l- ## s- +-- /explicit_handler/ l+ ## 0 +-- /wrong_handler/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_ok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_ok.adb new file mode 100644 index 000000000..fc4118363 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/test_divide_ok.adb @@ -0,0 +1,22 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Ok is + + Result : Integer; + +begin + + Divide (12, 2, Result); + + Assert (N_In_MyCE_Handler = 0); + Assert (N_In_Wrong_Handler = 0); + +end Test_Divide_Ok; + +--# div.adb +-- /explicit_check/ l+ ## 0 +-- /explicit_raise/ l- ## s- +-- /computation/ l+ ## 0 +-- /explicit_handler/ l- ## s- +-- /wrong_handler/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/div.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/div.adb new file mode 100644 index 000000000..eecf722d1 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/div.adb @@ -0,0 +1,11 @@ +pragma Unsuppress (All_Checks); + +package body Div is + procedure Divide (X, Y: Integer; Res: out Integer) is + begin + Res := X/Y; -- # division + exception + when Constraint_Error => + N_In_Handler := N_In_Handler + 1; -- # in_handler + end Divide; +end Div; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_nok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_nok.adb new file mode 100644 index 000000000..d330fb368 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_nok.adb @@ -0,0 +1,18 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Nok is + + Result : Integer; + +begin + + Divide (12, 0, Result); + + Assert (N_In_Handler = 1); + +end Test_Divide_Nok; + +--# div.adb +-- /division/ l+ ## 0 +-- /in_handler/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_ok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_ok.adb new file mode 100644 index 000000000..6d789ca47 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/src/test_divide_ok.adb @@ -0,0 +1,18 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Ok is + + Result : Integer; + +begin + + Divide (12, 2, Result); + + Assert (N_In_Handler = 0); + +end Test_Divide_Ok; + +--# div.adb +-- /division/ l+ ## 0 +-- /in_handler/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/div.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/div.adb new file mode 100644 index 000000000..9b7dbcf6e --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/div.adb @@ -0,0 +1,21 @@ +package body Div is + function Unhandled_Divide (X, Y: Integer) return Integer is + begin + if Y = 0 then -- # explicit_check + raise Constraint_Error; -- # explicit_raise + else + return X/Y; -- # computation + end if; + end Unhandled_Divide; + + procedure Divide (X, Y: Integer; Res: out Integer) is + begin + Res := Unhandled_Divide (X,Y); -- # division + N_Comp_Success := N_Comp_Success + 1; -- # no_exception + exception + when Constraint_Error => + N_Excpt_Prop := N_Excpt_Prop + 1; -- # propagated_up + when others => + N_Wrong_Excpt_Prop := N_Wrong_Excpt_Prop + 1; -- # wrong_excpt + end; +end Div; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_nok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_nok.adb new file mode 100644 index 000000000..bc33e63c2 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_nok.adb @@ -0,0 +1,22 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Nok is + Result: Integer; +begin + Divide (10,0, Result); + + Assert (N_Comp_Success = 0); + Assert (N_Excpt_Prop = 1); + Assert (N_Wrong_Excpt_Prop = 0); + +end Test_Divide_Nok; + +--# div.adb +-- /division/ l+ ## 0 +-- /no_exception/ l- ## s- +-- /propagated_up/ l+ ## 0 +-- /wrong_excpt/ l- ## s- +-- /explicit_check/ l+ ## 0 +-- /explicit_raise/ l+ ## 0 +-- /computation/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_ok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_ok.adb new file mode 100644 index 000000000..9d921b47a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/src/test_divide_ok.adb @@ -0,0 +1,22 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Ok is + Result: Integer; +begin + Divide (10,5, Result); + + Assert (N_Comp_Success = 1); + Assert (N_Excpt_Prop = 0); + Assert (N_Wrong_Excpt_Prop = 0); + +end Test_Divide_Ok; + +--# div.adb +-- /division/ l+ ## 0 +-- /no_exception/ l+ ## 0 +-- /propagated_up/ l- ## s- +-- /wrong_excpt/ l- ## s- +-- /explicit_check/ l+ ## 0 +-- /explicit_raise/ l- ## s- +-- /computation/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/div.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/div.adb new file mode 100644 index 000000000..a922b2e57 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/div.adb @@ -0,0 +1,19 @@ +pragma Unsuppress (All_Checks); + +package body Div is + function Unhandled_Divide (X, Y: Integer) return Integer is + begin + return X/Y; -- # division + end Unhandled_Divide; + + procedure Divide (X, Y: Integer; Res: out Integer) is + begin + Res := Unhandled_Divide (X,Y); -- # division + N_Comp_Success := N_Comp_Success + 1; -- # no_exception + exception + when Constraint_Error => + N_Excpt_Prop := N_Excpt_Prop + 1; -- # propagated_up + when others => + N_Wrong_Excpt_Prop := N_Wrong_Excpt_Prop + 1; -- # wrong_excpt + end; +end Div; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_nok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_nok.adb new file mode 100644 index 000000000..bb791240c --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_nok.adb @@ -0,0 +1,19 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Nok is + Result: Integer; +begin + Divide (10,0, Result); + + Assert (N_Comp_Success = 0); + Assert (N_Excpt_Prop = 1); + Assert (N_Wrong_Excpt_Prop = 0); + +end Test_Divide_Nok; + +--# div.adb +-- /division/ l+ ## 0 +-- /no_exception/ l- ## s- +-- /propagated_up/ l+ ## 0 +-- /wrong_excpt/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_ok.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_ok.adb new file mode 100644 index 000000000..e3257f086 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/src/test_divide_ok.adb @@ -0,0 +1,19 @@ +with Support; use Support; +with Div; use Div; + +procedure Test_Divide_Ok is + Result: Integer; +begin + Divide (10,5, Result); + + Assert (N_Comp_Success = 1); + Assert (N_Excpt_Prop = 0); + Assert (N_Wrong_Excpt_Prop = 0); + +end Test_Divide_Ok; + +--# div.adb +-- /division/ l+ ## 0 +-- /no_exception/ l+ ## 0 +-- /propagated_up/ l- ## s- +-- /wrong_excpt/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/notes.txt b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/notes.txt new file mode 100644 index 000000000..bdf1e9301 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/notes.txt @@ -0,0 +1,11 @@ +Check coverage of excpetions that are raised in a subprogram body. + +We check for exceptions raised: + + - in a subprogram with a local handler + + - in a subprogram without local handler, exception propogated upawards + + - unhandled exceptions? + +Implicitly and Explicitly raised exceptions. diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/src/div.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/src/div.ads new file mode 100644 index 000000000..977ea0f37 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/src/div.ads @@ -0,0 +1,14 @@ +package Div is + + N_In_Handler : Natural := 0; + My_Constraint_Error: exception; + N_In_MyCE_Handler: Natural := 0; + N_In_Wrong_Handler: Natural := 0; + + procedure Divide (X, Y: Integer; Res: out Integer); + + N_Comp_Success : Integer := 0; + N_Excpt_Prop : Integer := 0; + N_Wrong_Excpt_Prop : Integer := 0; + +end Div; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.adb new file mode 100644 index 000000000..070ad9152 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.adb @@ -0,0 +1,26 @@ +package body Cond_Raise is + + procedure Raise_If (Cond : Boolean) is + begin + if Cond then -- # test_cond + N_Raise := N_Raise + 1; -- # raise + raise Constraint_Error; -- # raise + + -- Repeating # raise is done on purpose here, to let + -- test drivers designate the set of lines/statements + -- that all get to execute or not depending on Cond. + end if; + N_Past_Test := N_Past_Test + 1; -- # past_test + end; + + procedure Check_For (Cond : Boolean) is + begin + Raise_If (Cond => Cond); -- # call + N_Past_Call := N_Past_Call + 1; -- # past_call + exception + when Constraint_Error => + N_In_Handler := N_In_Handler + 1; -- # in_handler + end; +end; + + diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.ads new file mode 100644 index 000000000..e68f92c1a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.ads @@ -0,0 +1,5 @@ +package Cond_Raise is + procedure Check_For (Cond : Boolean); + + N_Past_Call, N_In_Handler, N_Raise, N_Past_Test : Natural := 0; +end; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_f.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_f.adb new file mode 100644 index 000000000..4db6fafcd --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_f.adb @@ -0,0 +1,18 @@ +with Support, Cond_Raise; use Support; + +procedure Test_Cond_F is +begin + Cond_Raise.Check_For (Cond => False); + Assert (Cond_Raise.N_Raise = 0); + Assert (Cond_Raise.N_Past_Test = 1); + Assert (Cond_Raise.N_In_Handler = 0); + Assert (Cond_Raise.N_Past_Call = 1); +end; + +--# cond_raise.adb +-- /test_cond/ l+ ## 0 +-- /raise/ l- ## s- +-- /past_test/ l+ ## 0 +-- /call/ l+ ## 0 +-- /past_call/ l+ ## 0 +-- /in_handler/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_t.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_t.adb new file mode 100644 index 000000000..9a914a282 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_t.adb @@ -0,0 +1,36 @@ +with Support, Cond_Raise; use Support; + +procedure Test_Cond_T is +begin + Cond_Raise.Check_For (Cond => True); + + -- We called once only, raising. So ... + + -- We raised and went into the exception handler once + + Assert (Cond_Raise.N_Raise = 1); + Assert (Cond_Raise.N_In_Handler = 1); + + -- We never reached the code past the test deciding if we should raise + -- (which we only reach when we call the function without raising). + -- Likewise for the code past the inner call, skipped by the exception + -- propagation. + + Assert (Cond_Raise.N_Past_Test = 0); + Assert (Cond_Raise.N_Past_Call = 0); + +end; + +-- Expectations on =xcov and =report coverage outcome follow. Note the single +-- reference to the "raise" marker to designate multiple lines/statements in +-- the Raise_If suprogram, for which we indeed always expect the same kind of +-- outcome (all the lines/statements are expected to be covered/uncovered in +-- a consistent fashion). + +--# cond_raise.adb +-- /test_cond/ l+ ## 0 +-- /raise/ l+ ## 0 +-- /past_test/ l- ## s- +-- /call/ l+ ## 0 +-- /past_call/ l- ## s- +-- /in_handler/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/example/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/example/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/test.py b/testsuite/tests/Ravenscar/Exceptions/stmt/example/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/example/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/check_class_wide.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/check_class_wide.adb new file mode 100755 index 000000000..3f77df31a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/check_class_wide.adb @@ -0,0 +1,25 @@ +with Parent; use Parent; +with Parent.Child1; use Parent.Child1; +with Parent.Child2; use Parent.Child2; +procedure Check_Class_Wide + (Check_Var : Integer; + Result : out Integer) +is + type Access_T_Class is access T'Class; + Var : Access_T_Class; + +begin + case Check_Var is + when 1 => + Var := new T1_T'(C1 => 1); + when 2 => + Var := new T2_T'(C1 => 1); + when 3 => + Var := new T2_T'(C1 => 101); + when others => + null; + end case; + + Result := Compute_C (Var.all); + +end Check_Class_Wide; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_f.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_f.adb new file mode 100755 index 000000000..8d04b7297 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_f.adb @@ -0,0 +1,46 @@ +-- Test driver for checking DC in case when a class-wide operation is +-- involved. The class-wide operation to check is not a condition in any +-- decision, it is just called on its own. +-- +-- The driver calls a class-wide operation in such a way that a top-level +-- decision in its body is evaluated to False. DC for the called dispatching +-- operations (here we have dynamic dispatching) is also checked. + +with Check_Class_Wide; + +with Support; use Support; +procedure Test_F is + Result : Integer; +begin + Check_Class_Wide + (Check_Var => 2, + Result => Result); + + Assert (Result = 0); +end Test_F; + +--# parent.adb +-- /compute_c_eval/ l! ## dT- +-- /compute_c_true/ l- ## s- +-- /compute_c_false/ l+ ## 0 +-- /valid_c/ l- ## s- + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dF- +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_no.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_no.adb new file mode 100755 index 000000000..c41102288 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_no.adb @@ -0,0 +1,41 @@ +-- Test driver for checking DC in case when a class-wide operation is +-- involved. The class-wide operation to check is not a condition in any +-- decision, it is just called on its own. +-- +-- The driver does not call anything - the check is made that no code of +-- interest is reported as covered. + +with Check_Class_Wide; + +with Support; use Support; +procedure Test_No is + Result : Integer; +begin + Assert (True); +end Test_No; + +--# parent.adb +-- /compute_c_eval/ l- ## s- +-- /compute_c_true/ l- ## s- +-- /compute_c_false/ l- ## s- +-- /valid_c/ l- ## s- + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_t.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_t.adb new file mode 100755 index 000000000..0cf209d00 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_t.adb @@ -0,0 +1,46 @@ +-- Test driver for checking DC in case when a class-wide operation is +-- involved. The class-wide operation to check is not a condition in any +-- decision, it is just called on its own. +-- +-- The driver calls a class-wide operation in such a way that a top-level +-- decision in its body is evaluated to True. DC for the called dispatching +-- operations (here we have dynamic dispatching) is also checked. + +with Check_Class_Wide; + +with Support; use Support; +procedure Test_T is + Result : Integer; +begin + Check_Class_Wide + (Check_Var => 1, + Result => Result); + + Assert (Result = 1); +end Test_T; + +--# parent.adb +-- /compute_c_eval/ l! ## dF- +-- /compute_c_true/ l+ ## 0 +-- /compute_c_false/ l- ## s- +-- /valid_c/ l- ## s- + +--# parent-child1.adb +-- /compute_eval/ l! ## dF- +-- /compute_true/ l+ ## 0 +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dF- +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tf.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tf.adb new file mode 100755 index 000000000..6347132f9 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tf.adb @@ -0,0 +1,52 @@ +-- Test driver for checking DC in case when a class-wide operation is +-- involved. The class-wide operation to check is not a condition in any +-- decision, it is just called on its own. +-- +-- The driver calls a class-wide operation twice, and as a result a top-level +-- decision in its body is evaluated to True and to False. DC for the called +-- dispatching operations (here we have dynamic dispatching) is also checked. + +with Check_Class_Wide; + +with Support; use Support; +procedure Test_TF is + Result : Integer; +begin + Check_Class_Wide + (Check_Var => 1, + Result => Result); + + Assert (Result = 1); + + Check_Class_Wide + (Check_Var => 2, + Result => Result); + + Assert (Result = 0); +end Test_TF; + +--# parent.adb +-- /compute_c_eval/ l+ ## 0 +-- /compute_c_true/ l+ ## 0 +-- /compute_c_false/ l+ ## 0 +-- /valid_c/ l- ## s- + +--# parent-child1.adb +-- /compute_eval/ l! ## dF- +-- /compute_true/ l+ ## 0 +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dF- +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dF- +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tfx.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tfx.adb new file mode 100755 index 000000000..409e4d34d --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_tfx.adb @@ -0,0 +1,60 @@ +-- Test driver for checking DC in case when a class-wide operation is +-- involved. The class-wide operation to check is not a condition in any +-- decision, it is just called on its own. +-- +-- The driver calls a class-wide operation three, and as a result a top-level +-- decision in its body is evaluated to True, to False and raises an +-- exception. DC for the called dispatching operations (here we have dynamic +-- dispatching) is also checked. + +with Check_Class_Wide; + +with Support; use Support; +procedure Test_TFX is + Result : Integer; +begin + Check_Class_Wide + (Check_Var => 1, + Result => Result); + + Assert (Result = 1); + + Check_Class_Wide + (Check_Var => 2, + Result => Result); + + Assert (Result = 0); + + Check_Class_Wide + (Check_Var => 3, + Result => Result); +exception + when others => + Assert (Result = 0); +end; + +--# parent.adb +-- /compute_c_eval/ l+ ## 0 +-- /compute_c_true/ l+ ## 0 +-- /compute_c_false/ l+ ## 0 +-- /valid_c/ l- ## s- + +--# parent-child1.adb +-- /compute_eval/ l! ## dF- +-- /compute_true/ l+ ## 0 +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dF- +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l+ ## 0 +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l! ## dT- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_x.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_x.adb new file mode 100755 index 000000000..b7471bb37 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/src/test_x.adb @@ -0,0 +1,47 @@ +-- Test driver for checking DC in case when a class-wide operation is +-- involved. The class-wide operation to check is not a condition in any +-- decision, it is just called on its own. +-- +-- The driver calls a class-wide operation in such a way that evaluation of a +-- top-level decision in its body raises an exception. DC for the called +-- dispatching operations (here we have dynamic dispatching) is also checked. + +with Check_Class_Wide; + +with Support; use Support; +procedure Test_X is + Result : Integer := 13; +begin + Check_Class_Wide + (Check_Var => 3, + Result => Result); +exception + when others => + Assert (Result = 13); +end Test_X; + +--# parent.adb +-- /compute_c_eval/ l! ## d- +-- /compute_c_true/ l- ## s- +-- /compute_c_false/ l- ## s- +-- /valid_c/ l- ## s- + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dT- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l! ## dT- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/tc.txt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/tc.txt new file mode 100755 index 000000000..c20aecec9 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/tc.txt @@ -0,0 +1,6 @@ +Check DC when a class-wide operation is called (not as a condition of some +decision). DC is checked for the code of the dispatching operation itself and +for the code of dispatching operations that can be called by the class-wide +operation. The class-wide operation contains an IF statement (with ELSE part +and with no ELSIF part). The tests are structured according to the +coverage of the decision in this IF statement. diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.opt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.py b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/check_class_wide_condition.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/check_class_wide_condition.adb new file mode 100755 index 000000000..c72db9fed --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/check_class_wide_condition.adb @@ -0,0 +1,35 @@ +with Parent; use Parent; +with Parent.Child1; use Parent.Child1; +with Parent.Child2; use Parent.Child2; +procedure Check_Class_Wide_Condition + (Check_Var : Integer; + Result : out Integer) +is + type Access_T_Class is access T'Class; -- # dcl + Var : Access_T_Class; -- # dcl + +begin + case Check_Var is -- # case + when 1 => + Var := new T1_T'(C1 => 1); -- # var_1 + when 2 => + Var := new T2_T'(C1 => 1); -- # var_2 + when 3 => + Var := new T1_T'(C1 => 101); -- # var_3 + when others => + null; -- # var_others + end case; + + if Valid_C (Var.all) then -- # eval + Result := 10; -- # true + else + Result := 20; -- # false + end if; + +exception + when Constraint_Error => + Result := 0; -- # exc +end Check_Class_Wide_Condition; + + + diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_f.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_f.adb new file mode 100755 index 000000000..bdd80ecc2 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_f.adb @@ -0,0 +1,36 @@ +-- Test driver for checking DC in case when a decision contains call to a +-- class-wide-operation. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is the call to the class-wide operation and no logical +-- operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a class-wide operation in such a way that a decision to +-- check is evaluated to False. + +with Check_Class_Wide_Condition; + +with Support; use Support; +procedure Test_F is + Result : Integer; +begin + Check_Class_Wide_Condition + (Check_Var => 2, + Result => Result); + + Assert (Result = 20); +end Test_F; + +--# check_class_wide_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l- ## s- +-- /var_2/ l+ ## 0 +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l! ## dT- +-- /true/ l- ## s- +-- /false/ l+ ## 0 +-- /exc/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ft.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ft.adb new file mode 100755 index 000000000..9dfbd855f --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ft.adb @@ -0,0 +1,51 @@ +-- Test driver for checking DC in case when a decision contains call to a +-- class-wide-operation. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is the call to the class-wide operation and no logical +-- operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a class-wide operation twice - first time in such a way +-- that a decision to check is evaluated to False, and second time to +-- evaluate it to True. + +with Check_Class_Wide_Condition; + +with Support; use Support; +procedure Test_FT is + Result : Integer; +begin + Check_Class_Wide_Condition + (Check_Var => 2, + Result => Result); + + Assert (Result = 20); + + Check_Class_Wide_Condition + (Check_Var => 1, + Result => Result); + + Assert (Result = 10); +end Test_FT; + +--# check_class_wide_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l+ ## 0 +-- /var_2/ l+ ## 0 +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 +-- /exc/ l- ## s- + + + + + + + + diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ftx.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ftx.adb new file mode 100755 index 000000000..5b04769e2 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ftx.adb @@ -0,0 +1,46 @@ +-- Test driver for checking DC in case when a decision contains call to a +-- class-wide-operation. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is the call to the class-wide operation and no logical +-- operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a class-wide operation three times to get all possible +-- results - False, True and raising an exception. + +with Check_Class_Wide_Condition; + +with Support; use Support; +procedure Test_FTX is + Result : Integer; +begin + Check_Class_Wide_Condition + (Check_Var => 2, + Result => Result); + Assert (Result = 20); + + Check_Class_Wide_Condition + (Check_Var => 1, + Result => Result); + Assert (Result = 10); + + Check_Class_Wide_Condition + (Check_Var => 3, + Result => Result); + + Assert (Result = 0); +end Test_FTX; + +--# check_class_wide_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l+ ## 0 +-- /var_2/ l+ ## 0 +-- /var_3/ l+ ## 0 +-- /var_others/ l- ## s- +-- /eval/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 +-- /exc/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_no.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_no.adb new file mode 100755 index 000000000..9ee4505c1 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_no.adb @@ -0,0 +1,31 @@ +-- Test driver for checking DC in case when a decision contains call to a +-- class-wide-operation. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is the call to the class-wide operation and no logical +-- operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver does not call anything - so nothing from the functional code is +-- expected to be reported as covered. + +with Check_Class_Wide_Condition; + +with Support; use Support; +procedure Test_No is +begin + Assert (True); +end Test_No; + +--# check_class_wide_condition.adb +-- /dcl/ l- ## s- +-- /case/ l- ## s- +-- /var_1/ l- ## s- +-- /var_2/ l- ## s- +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l- ## s- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /exc/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_t.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_t.adb new file mode 100755 index 000000000..2333961a0 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_t.adb @@ -0,0 +1,37 @@ +-- Test driver for checking DC in case when a decision contains call to a +-- class-wide-operation. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is the call to the class-wide operation and no logical +-- operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a class-wide operation in such a way that a decision to +-- check is evaluated to False. + +with Check_Class_Wide_Condition; + +with Support; use Support; +procedure Test_T is + Result : Integer; +begin + Check_Class_Wide_Condition + (Check_Var => 1, + Result => Result); + + Assert (Result = 10); +end Test_T; + +--# check_class_wide_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l+ ## 0 +-- /var_2/ l- ## s- +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /false/ l- ## s- +-- /exc/ l- ## s- + diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_x.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_x.adb new file mode 100755 index 000000000..57e8050ac --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_x.adb @@ -0,0 +1,36 @@ +-- Test driver for checking DC in case when a decision contains call to a +-- class-wide-operation. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is the call to the class-wide operation and no logical +-- operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a class-wide operation in such a way that evaluation if +-- the decision raises an exception. + +with Check_Class_Wide_Condition; + +with Support; use Support; +procedure Test_X is + Result : Integer; +begin + Check_Class_Wide_Condition + (Check_Var => 3, + Result => Result); + + Assert (Result = 0); +end Test_X; + +--# check_class_wide_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l- ## s- +-- /var_2/ l- ## s- +-- /var_3/ l+ ## 0 +-- /var_others/ l- ## s- +-- /eval/ l! ## d- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /exc/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/tc.txt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/tc.txt new file mode 100755 index 000000000..18e8e7ec3 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/tc.txt @@ -0,0 +1,4 @@ +Check DC when a condition contains a call to class-wide operation as a +condition. The simplest structure of a decision is used - it contains the +only condition and no logical operations. The coverage of the code of the +dispatching operations called from the decision is not checked. diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.opt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.opt new file mode 100755 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.py b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/check_dispatching_condition.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/check_dispatching_condition.adb new file mode 100755 index 000000000..ac63bd866 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/check_dispatching_condition.adb @@ -0,0 +1,35 @@ +with Parent; use Parent; +with Parent.Child1; use Parent.Child1; +with Parent.Child2; use Parent.Child2; +procedure Check_Dispatching_Condition + (Check_Var : Integer; + Result : out Integer) +is + type Access_T_Class is access T'Class; -- # dcl + Var : Access_T_Class; -- # dcl + +begin + case Check_Var is -- # case + when 1 => + Var := new T1_T'(C1 => 1); -- # var_1 + when 2 => + Var := new T2_T'(C1 => 1); -- # var_2 + when 3 => + Var := new T1_T'(C1 => 101); -- # var_3 + when others => + null; -- # var_others + end case; + + if Valid (Var.all) then -- # eval + Result := 10; -- # true + else + Result := 20; -- # false + end if; + +exception + when Constraint_Error => + Result := 0; -- # exc +end Check_Dispatching_Condition; + + + diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_f.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_f.adb new file mode 100755 index 000000000..c74a84d46 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_f.adb @@ -0,0 +1,35 @@ +-- Test driver for checking DC in case when a decision contains a (dynamically +-- resolved) dispatching call. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is a dispatching call and no logical operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a dispatching operation in such a way that a decision to +-- check is evaluated to False. + +with Check_Dispatching_Condition; + +with Support; use Support; +procedure Test_F is + Result : Integer; +begin + Check_Dispatching_Condition + (Check_Var => 2, + Result => Result); + + Assert (Result = 20); +end Test_F; + +--# check_dispatching_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l- ## s- +-- /var_2/ l+ ## 0 +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l! ## dT- +-- /true/ l- ## s- +-- /false/ l+ ## 0 +-- /exc/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ft.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ft.adb new file mode 100755 index 000000000..de8982998 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ft.adb @@ -0,0 +1,49 @@ +-- Test driver for checking DC in case when a decision contains a (dynamically +-- resolved) dispatching call. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is a dispatching call and no logical operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a dispatching operation twice - first time in such a way +-- that a decision to check is evaluated to False, and second time to +-- evaluate it to True. + +with Check_Dispatching_Condition; + +with Support; use Support; +procedure Test_FT is + Result : Integer; +begin + Check_Dispatching_Condition + (Check_Var => 2, + Result => Result); + + Assert (Result = 20); + Check_Dispatching_Condition + (Check_Var => 1, + Result => Result); + + Assert (Result = 10); +end Test_FT; + +--# check_dispatching_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l+ ## 0 +-- /var_2/ l+ ## 0 +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 +-- /exc/ l- ## s- + + + + + + + + diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ftx.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ftx.adb new file mode 100755 index 000000000..1ae69b695 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ftx.adb @@ -0,0 +1,45 @@ +-- Test driver for checking DC in case when a decision contains a (dynamically +-- resolved) dispatching call. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is a dispatching call and no logical operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a dispatching operation three times to get all possible +-- results - False, True and raising an exception. + +with Check_Dispatching_Condition; + +with Support; use Support; +procedure Test_FTX is + Result : Integer; +begin + Check_Dispatching_Condition + (Check_Var => 2, + Result => Result); + + Assert (Result = 20); + Check_Dispatching_Condition + (Check_Var => 1, + Result => Result); + + Assert (Result = 10); + Check_Dispatching_Condition + (Check_Var => 3, + Result => Result); + + Assert (Result = 0); +end Test_FTX; + +--# check_dispatching_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l+ ## 0 +-- /var_2/ l+ ## 0 +-- /var_3/ l+ ## 0 +-- /var_others/ l- ## s- +-- /eval/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 +-- /exc/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_no.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_no.adb new file mode 100755 index 000000000..6d6250895 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_no.adb @@ -0,0 +1,30 @@ +-- Test driver for checking DC in case when a decision contains a (dynamically +-- resolved) dispatching call. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is a dispatching call and no logical operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver does not call anything - so nothing from the functional code is +-- expected to be reported as covered. + +with Check_Dispatching_Condition; + +with Support; use Support; +procedure Test_No is +begin + Assert (True); +end Test_No; + +--# check_dispatching_condition.adb +-- /dcl/ l- ## s- +-- /case/ l- ## s- +-- /var_1/ l- ## s- +-- /var_2/ l- ## s- +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l- ## s- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /exc/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_t.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_t.adb new file mode 100755 index 000000000..a9b20e428 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_t.adb @@ -0,0 +1,36 @@ +-- Test driver for checking DC in case when a decision contains a (dynamically +-- resolved) dispatching call. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is a dispatching call and no logical operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a dispatching operation in such a way that a decision to +-- check is evaluated to True. + +with Check_Dispatching_Condition; + +with Support; use Support; +procedure Test_T is + Result : Integer; +begin + Check_Dispatching_Condition + (Check_Var => 1, + Result => Result); + + Assert (Result = 10); +end Test_T; + +--# check_dispatching_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l+ ## 0 +-- /var_2/ l- ## s- +-- /var_3/ l- ## s- +-- /var_others/ l- ## s- +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /false/ l- ## s- +-- /exc/ l- ## s- + diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_x.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_x.adb new file mode 100755 index 000000000..adf8fb4e7 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_x.adb @@ -0,0 +1,35 @@ +-- Test driver for checking DC in case when a decision contains a (dynamically +-- resolved) dispatching call. +-- +-- The simplest structure of the decision is used - it contains the only +-- condition that is a dispatching call and no logical operation. +-- +-- The coverage of the code of called dispatching operation is NOT checked. +-- +-- The driver calls a dispatching operation in such a way that evaluation if +-- the decision raises an exception. + +with Check_Dispatching_Condition; + +with Support; use Support; +procedure Test_X is + Result : Integer; +begin + Check_Dispatching_Condition + (Check_Var => 3, + Result => Result); + + Assert (Result = 0); +end Test_X; + +--# check_dispatching_condition.adb +-- /dcl/ l+ ## 0 +-- /case/ l+ ## 0 +-- /var_1/ l- ## s- +-- /var_2/ l- ## s- +-- /var_3/ l+ ## 0 +-- /var_others/ l- ## s- +-- /eval/ l! ## d- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /exc/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/tc.txt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/tc.txt new file mode 100755 index 000000000..022f7657a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/tc.txt @@ -0,0 +1,4 @@ +Check DC when a condition contains a (dynamically resolved) dispatching call +as a condition. The simplest structure of a decision is used - it contains the +only condition and no logical operations. The coverage of the code of the +dispatching operations called from the decision is not checked. diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.opt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.opt new file mode 100755 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.py b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/check_dynamic_binding.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/check_dynamic_binding.adb new file mode 100755 index 000000000..b3940aa69 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/check_dynamic_binding.adb @@ -0,0 +1,27 @@ +with Parent; use Parent; +with Parent.Child1; use Parent.Child1; +with Parent.Child2; use Parent.Child2; +procedure Check_Dynamic_Binding + (Check_Var : Integer; + Result : out Integer) +is + type Access_T_Class is access T'Class; + Var : Access_T_Class; + +begin + case Check_Var is + when 1 => + Var := new T1_T'(C1 => 1); + when 2 => + Var := new T2_T'(C1 => 1); + when 3 => + Var := new T2_T'(C1 => 20); + when 4 => + Var := new T2_T'(C1 => 101); + when others => + null; + end case; + + Result := Compute (Var.all); + +end Check_Dynamic_Binding; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_f_t.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_f_t.adb new file mode 100755 index 000000000..c21be8686 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_f_t.adb @@ -0,0 +1,43 @@ +-- Test driver for checking DC in case when a dispatching operations are +-- involved. The top-level dispatching operation to check is not a condition +-- in any decision, it is just called on its own. +-- +-- The driver calls a top dispatching operation in such a way that +-- * operations of T2 are executed +-- * the decision in its body of the primitive that is called first is +-- evaluated to False, +-- * the IF decision in the primitive called from the first primitive is +-- evaluated. to True. + + with Check_Dynamic_Binding; + +with Support; use Support; +procedure Test_2_F_T is + Result : Integer; +begin + Check_Dynamic_Binding + (Check_Var => 2, + Result => Result); + + Assert (Result = 999); +end Test_2_F_T; + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l! ## dT- +-- /compute_true/ l- ## s- +-- /compute_false/ l+ ## 0 +-- /valid_if_eval/ l! ## dF- +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_ftx.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_ftx.adb new file mode 100755 index 000000000..385db4275 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_ftx.adb @@ -0,0 +1,60 @@ +-- Test driver for checking DC in case when a dispatching operations are +-- involved. The top-level dispatching operation to check is not a condition +-- in any decision, it is just called on its own. +-- +-- The driver calls a top dispatching operation three times in such a way that +-- * operations of T2 are executed; +-- * the decision in its body of the primitive that is called first is +-- evaluated to False, to True and raises and exception; +-- * the IF decision in the primitive called from the first primitive is +-- evaluated to False and to True, and ELSIF decision - to True. + + with Check_Dynamic_Binding; + +with Support; use Support; +procedure Test_2_FTX is + Result : Integer; +begin + Check_Dynamic_Binding + (Check_Var => 2, + Result => Result); + + Assert (Result = 999); + + Check_Dynamic_Binding + (Check_Var => 3, + Result => Result); + + Assert (Result = -20); + + Result := 13; + + Check_Dynamic_Binding + (Check_Var => 4, + Result => Result); + + Assert (False); +exception + when Constraint_Error => + Assert (Result = 13); +end Test_2_FTX; + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l+ ## 0 +-- /compute_true/ l+ ## 0 +-- /compute_false/ l+ ## 0 +-- /valid_if_eval/ l+ ## 0 +-- /valid_if_true/ l+ ## 0 +-- /valid_elsif_eval/ l+ ## 0 +-- /valid_elsif_ true/ l+ ## 0 +-- /valid_false/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_t_ft.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_t_ft.adb new file mode 100755 index 000000000..d0dea616f --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_t_ft.adb @@ -0,0 +1,43 @@ +-- Test driver for checking DC in case when a dispatching operations are +-- involved. The top-level dispatching operation to check is not a condition +-- in any decision, it is just called on its own. +-- +-- The driver calls a top dispatching operation in such a way that +-- * operations of T2 are executed; +-- * the decision in its body of the primitive that is called first is +-- evaluated to True; +-- * the IF decision in the primitive called from the first primitive is +-- evaluated to False, and ELSIF decision - to True. + + with Check_Dynamic_Binding; + +with Support; use Support; +procedure Test_2_T_FT is + Result : Integer; +begin + Check_Dynamic_Binding + (Check_Var => 3, + Result => Result); + + Assert (Result = -20); +end Test_2_T_FT; + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l! ## dF- +-- /compute_true/ l+ ## 0 +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dT- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l! ## dF- +-- /valid_elsif_ true/ l+ ## 0 +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_x.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_x.adb new file mode 100755 index 000000000..c87af377d --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_2_x.adb @@ -0,0 +1,46 @@ +-- Test driver for checking DC in case when a dispatching operations are +-- involved. The top-level dispatching operation to check is not a condition +-- in any decision, it is just called on its own. +-- +-- The driver calls a top dispatching operation in such a way that +-- * operations of T2 are executed; +-- * evaluation of the decision in its body of the primitive raises an +-- exception; +-- * IF and ELSIF decisions in the primitive called from the first primitive +-- are both evaluated to False + + with Check_Dynamic_Binding; + +with Support; use Support; +procedure Test_2_X is + Result : Integer := 1; +begin + Check_Dynamic_Binding + (Check_Var => 4, + Result => Result); + + Assert (False); +exception + when Constraint_Error => + Assert (Result = 1); +end Test_2_X; + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l! ## d- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l! ## dT- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l! ## dT- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_no.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_no.adb new file mode 100755 index 000000000..5507de793 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/src/test_no.adb @@ -0,0 +1,31 @@ +-- Test driver for checking DC in case when a dispatching operations are +-- involved. Does not call anything, so everything should be reported as +-- non-covered + + with Check_Dynamic_Binding; + +with Support; use Support; +procedure Test_No is +begin + Assert (True); +end Test_No; + +--# parent-child1.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- + +--# parent-child2.adb +-- /compute_eval/ l- ## s- +-- /compute_true/ l- ## s- +-- /compute_false/ l- ## s- +-- /valid_if_eval/ l- ## s- +-- /valid_if_true/ l- ## s- +-- /valid_elsif_eval/ l- ## s- +-- /valid_elsif_ true/ l- ## s- +-- /valid_false/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/tc.txt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/tc.txt new file mode 100755 index 000000000..45cbee4a0 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/tc.txt @@ -0,0 +1,6 @@ +Check DC when a dispatching operation is called (not as a condition of some +decision, but on its own), and the called subprogram cannot be detected +statically. DC is checked for the code of the dispatching operation itself and +for the code of dispatching operations that can be called by it. The tests are +structured according to the coverage of the decision in this IF statements in +the dispatching operations being executed. diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.opt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.opt new file mode 100644 index 000000000..91ac4985a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.opt @@ -0,0 +1,3 @@ +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.py b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dynamic_Binding/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/req.txt b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/req.txt new file mode 100755 index 000000000..eafa6f3bf --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/req.txt @@ -0,0 +1,21 @@ +The following things should be checked: + +1. If a decision in some control structure contains a call to a dispatching + operation as one of the conditions involved then the coverage information + is correctly computed for this construct in case of dynamic binding. + +2. If a decision in some control structure contains a call to a class-wide + operation (containing some dynamic dispatching in its body) as one of the + conditions involved then the coverage information is correctly computed for + this construct in case of dynamic binding. + +3. For the body of a class-wide operation, the coverage information is + correctly computed. + +4. For the body a dispatching operation the coverage information is correctly + computed in case of a dynamic binding. + +For the initial version of the test suite, the simplest form is used for each +decision - it contains exactly one condition. The other parts of the test +suite exercises complex decisions, and here we check only things specific to +Ada OO features. diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.adb new file mode 100755 index 000000000..88896b6dd --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.adb @@ -0,0 +1,23 @@ +package body Parent.Child1 is + + function Compute (X : T1_T) return Integer is + begin + if Valid (T1_T'Class (X)) then -- # compute_eval + return X.C1; -- # compute_true + else + return 0; -- # compute_false + end if; + end Compute; + + function Valid (X : T1_T) return Boolean is + begin + if X.C1 in -10 .. 10 then -- # valid_if_eval + return True; -- # valid_if_true + elsif X.C1 in -100 .. 100 then -- # valid_elsif_eval + return False; -- # valid_elsif_ true + else + raise Constraint_Error; -- # valid_false + end if; + end Valid; + +end Parent.Child1; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.ads b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.ads new file mode 100755 index 000000000..bbd76573c --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child1.ads @@ -0,0 +1,8 @@ +package Parent.Child1 is + type T1_T is new T with record + C1 : Integer; + end record; + + function Compute (X : T1_T) return Integer; + function Valid (X : T1_T) return Boolean; +end Parent.Child1; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.adb new file mode 100755 index 000000000..419fcf2d0 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.adb @@ -0,0 +1,23 @@ +package body Parent.Child2 is + + function Compute (X : T2_T) return Integer is + begin + if Valid (T2_T'Class (X)) then -- # compute_eval + return -X.C1; -- # compute_true + else + return 999; -- # compute_false + end if; + end Compute; + + function Valid (X : T2_T) return Boolean is + begin + if X.C1 in -10 .. 10 then -- # valid_if_eval + return False; -- # valid_if_true + elsif X.C1 in -100 .. 100 then -- # valid_elsif_eval + return True; -- # valid_elsif_ true + else + raise Constraint_Error; -- # valid_false + end if; + end Valid; + +end Parent.Child2; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.ads b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.ads new file mode 100755 index 000000000..8495e9f89 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent-child2.ads @@ -0,0 +1,8 @@ +package Parent.Child2 is + type T2_T is new T with record + C1 : Integer; + end record; + + function Compute (X : T2_T) return Integer; + function Valid (X : T2_T) return Boolean; +end Parent.Child2; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.adb new file mode 100755 index 000000000..bde7e0ec1 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.adb @@ -0,0 +1,17 @@ +package body Parent is + + function Compute_C (X : T'Class) return Integer is + begin + if Valid (X) then -- # compute_c_eval + return Compute (X); -- # compute_c_true + else + return 0; -- # compute_c_false + end if; + end Compute_C; + + function Valid_C (X : T'Class) return Boolean is + begin + return Valid (X); -- # valid_c + end Valid_C; + +end Parent; diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.ads b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.ads new file mode 100755 index 000000000..0dbb3ad1c --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/src/parent.ads @@ -0,0 +1,10 @@ +package Parent is + type T is abstract tagged null record; + + function Compute (X : T) return Integer is abstract; + function Valid (X : T) return Boolean is abstract; + + + function Compute_C (X : T'Class) return Integer; + function Valid_C (X : T'Class) return Boolean; +end Parent; diff --git a/testsuite/tests/Ravenscar/OOP/req.txt b/testsuite/tests/Ravenscar/OOP/req.txt new file mode 100755 index 000000000..f4c2a8993 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/req.txt @@ -0,0 +1,111 @@ +This is the first attempt to describe the testing strategy for "Tagged Types +and Dispatching" (Ada OO features) part of the gnatcov test suite. + +1. In this particular part of the test suite tagged types and dispatching + should be considered as a specific language feature (a set of features) + that can bring a specific set of problems and difficulties to coverage + assessment tools, so they should be tested namely as a specific feature, + but not along with all the other language constructs. In particular this + means that we does not have to check all possible combinations of Ada OO + features with all possible syntax constructs. + +2. The testing strategy is based on a hypothesis that may be called as a + hypothesis of relative correctness: + + "When testing the interaction between the various language constructs, it + is assumed that each of these constructs is implemented correctly. This + implies that the concrete representation of each construct is not + important." + + Without such a hypothesis we will end up with combinatorial explosion very + soon. + +3. Ada OO features can bring the following difficulties to coverage analysis. + + - Inheritance: in the inheritance hierarchy we may have operations + implicitly inherited from other operations. Such operations may be + called as ordinary subprograms, but they do not have the code + associated with them, instead, the code of the explicitly declared + subprogram the called operation is inherited from is actually executed. + It should be checked that the coverage information is generated for the + code that actually is called, and for nothing else. + + - Overriding: when we have different "implementations" for "the same" + (primitive) operation in some inheritance hierarchy, it should be checked + that the coverage information is generated for the "implementation" that + actually is called, but not for the others (in particular, the coverage + information should not be generated for overridden subprogram in case + when an overriding subprogram is called); + + - Dynamic dispatching (dynamic binding): we may have a situation when it is + not possible to determine which subprogram from the set of different + implementations of a primitive operation of some type is called. We + should check that the coverage information is generated only for the + actually called subprograms; + + - Class-wide operations: they are interested in three aspects. First, + they may be considered as a special case of a subprogram (that can + operate on objects that have types that are not known in advance). + Second, a class-wide operation usually contains dispatching calls that + can be resolved only dynamically. Third, a class-wide operation can be + written for an abstract type when all the type operations defined as + abstract, and it may know nothing at all about subprograms it actually + calls. + +4. Ada OO features are closely related to each other, so we cannot avoid some + overlaps in testing strategy, requirements, test cases. We should not + consider this as any disadvantage, getting rid of these overlaps may be + more expensive for both developers and users of the test suite. + +5. Statement coverage. + +The following aspects should be checked: + +- Inheritance : when a derived subprogram is called, the coverage information + for the explicitly declared parent subprogram is generated + correctly; + +- Static binding: when in the hierarchy of dynamic types the called operation + can be detected statically, the code information for the + is correctly generated for the body of the subprogram that is + actually called, and no other code for no other subprogram + from the hierarchy is reported as covered; + +- Discpatching (dynamic binding) : if the subprogram to call is detected + dynamically, the coverage information is correctly generated + for the subprogram that has actually be called, and no other + code for no other subprogram from the hierarchy is reported as + covered; + +- Class-Wide operations: if a class-wide operation is called, the coverage + information is correctly generated for its code as well as for + all the subprograms called from the class-wide operation. The + subprograms that may be called from the class-wide operation + but that are not actually called with the given argument + should be reported as non-covered. + +- Multiple inheritance: similar to 'Dispatching', but called subprograms could + be from different inheritance hierarchies. + +6. Decision coverage. + +The following aspects should be checked: + +1. If a decision in some control structure contains a call to a dispatching + operation as one of the conditions involved then the coverage information + is correctly computed for this construct in case of dynamic binding. + +2. If a decision in some control structure contains a call to a class-wide + operation (containing some dynamic dispatching in its body) as one of the + conditions involved then the coverage information is correctly computed for + this construct in case of dynamic binding. + +3. For the body of a class-wide operation, the coverage information is + correctly computed, as well as for the dispatching operations that are + actually called from this class-wide operation. + +4. For the body a dispatching operation the coverage information is correctly + computed in case of a dynamic binding. + +The simplest form is used for each decision - it contains exactly one +condition with no logical operation. diff --git a/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.adb b/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.adb new file mode 100755 index 000000000..44f4179a8 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.adb @@ -0,0 +1,7 @@ +package body Class_Wide_Ops is + procedure Handle_Alert (A : in out Alert'Class) is + begin + Handle (A); + end Handle_Alert; +end; + diff --git a/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.ads b/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.ads new file mode 100755 index 000000000..89956f0a0 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.ads @@ -0,0 +1,4 @@ +with New_Alert_System; use New_Alert_System; +package Class_Wide_Ops is + procedure Handle_Alert (A : in out Alert'Class); +end; diff --git a/testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.adb b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.adb new file mode 100755 index 000000000..da6c1abca --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.adb @@ -0,0 +1,42 @@ +with New_Alert_System.Objects; use New_Alert_System.Objects; + +package body New_Alert_System.Emergency is + + procedure Handle (EA: in out Emergency_Alert) is + begin + Handle (New_Alert_System.Alert (EA)); -- # ea_handle + + if EA.Time_Of_Arrival >= New_Alert_System.Critical_Time then -- # ea_handle + EA.Catastrophe := True; -- # ea_hand_catastrophe + else + EA.Catastrophe := False; -- # ea_hand_no_catastrophe + end if; + end Handle; + + procedure Display (EA : in Emergency_Alert; + On : out Device) + is + begin + if EA.Catastrophe then -- # ea_display + On := 0; -- # ea_displ_catastrophe + else + Display (New_Alert_System.Alert (EA), On); -- # ea_displ_no_catastrophe + end if; + end Display; + + function Log (EA: in Emergency_Alert) return Natural is + begin + return Log (New_Alert_System.Alert (EA)) + 100; -- # ea_log + end Log; + + function Catastrophe (EA: in Emergency_Alert) return Boolean is + begin + return EA.Catastrophe; -- # ea_catastrophe + end Catastrophe; + + function Get_Empty_Emergency_Alert return Emergency_Alert is + begin + return Emergency_Alert'(Empty_Alert with Catastrophe => False); -- # ea_get + end Get_Empty_Emergency_Alert; + +end New_Alert_System.Emergency; diff --git a/testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.ads b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.ads new file mode 100755 index 000000000..d86d2fee1 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-emergency.ads @@ -0,0 +1,20 @@ +with New_Alert_System; +package New_Alert_System.Emergency is + type Emergency_Alert is new New_Alert_System.Alert with private; + + procedure Handle (EA: in out Emergency_Alert); + + procedure Display (EA : in Emergency_Alert; + On : out Device); + + function Log (EA: in Emergency_Alert) return Natural; + + function Catastrophe (EA: in Emergency_Alert) return Boolean; + + function Get_Empty_Emergency_Alert return Emergency_Alert; + +private + type Emergency_Alert is new New_Alert_System.Alert with record + Catastrophe : Boolean; + end record; +end New_Alert_System.Emergency; diff --git a/testsuite/tests/Ravenscar/OOP/src/new_alert_system-objects.ads b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-objects.ads new file mode 100755 index 000000000..468c6b816 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-objects.ads @@ -0,0 +1,15 @@ +package New_Alert_System.Objects is + Empty_Alert : Alert := + (Idx => 0, + Time_Of_Arrival => Zero_Time, + Message => No_Message); + + Empty_Low_Alert : Low_Alert := Low_Alert'(Empty_Alert with null record); + + Empty_Medium_Alert : Medium_Alert := + Medium_Alert'(Empty_Alert with Action_Officer => Volunteer); + + Empty_High_Alert : High_Alert := + High_Alert'(Empty_Medium_Alert with Ring_Alarm_At => Zero_Time); +end New_Alert_System.Objects; + diff --git a/testsuite/tests/Ravenscar/OOP/src/new_alert_system.adb b/testsuite/tests/Ravenscar/OOP/src/new_alert_system.adb new file mode 100755 index 000000000..91e51baa7 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/new_alert_system.adb @@ -0,0 +1,69 @@ +package body New_Alert_System is + + Current_Idx : Natural := Natural'First; + + function Get_Idx return Natural is + begin + Current_Idx := Current_Idx + 1; -- # get_idx + return Current_Idx - 1; -- # get_idx + end Get_Idx; + + Current_Time : My_Time := My_Time'First; + + function My_Clock return My_Time is + begin + Current_Time := Current_Time + 1; -- # my_clock + return Current_Time; -- # my_clock + end My_Clock; + + procedure Set_Time (New_Time : My_Time) is + begin + Current_Time := New_Time; -- # set_time + end Set_Time; + + procedure Handle (A : in out Alert) is + begin + A.Idx := Get_Idx; -- # a_handle + A.Time_Of_Arrival := My_Clock; -- # a_handle + end Handle; + + procedure Display (A : in Alert; + On : out Device) + is + begin + On := Device (Log (Alert'Class (A))) + Device (A.Time_Of_Arrival); -- # a_display +-- On := Device (Log (Alert'Class (A))) + +-- Device (A.Time_Of_Arrival); + end Display; + + function Log (A : in Alert) return Natural is + begin + return A.Idx; -- # a_log + end Log; + + procedure Handle (MA : in out Medium_Alert) is + begin + Handle (Alert (MA)); -- handle as plain alert -- # ma_handle + MA.Action_Officer := Volunteer; -- # ma_handle + end Handle; + + + procedure Handle (HA : in out High_Alert) is + begin + Handle (Medium_Alert (HA)); -- conversion -- # ha_handle + HA.Action_Officer := Soldier; -- # ha_handle + Set_Alarm (HA); -- # ha_handle + Display (HA, System_Device); -- # ha_handle + end Handle; + + procedure Set_Alarm (HA: in out High_Alert) is + begin + HA.Ring_Alarm_At := HA.Time_Of_Arrival + 1; -- # ha_set_alarm + HA.Action_Officer := Sergeant; -- # ha_set_alarm + end Set_Alarm; + + function Log (HA : in High_Alert) return Natural is + begin + return HA.Idx * 10 + 10; -- # ha_log + end Log; +end New_Alert_System; diff --git a/testsuite/tests/Ravenscar/OOP/src/new_alert_system.ads b/testsuite/tests/Ravenscar/OOP/src/new_alert_system.ads new file mode 100755 index 000000000..52a1a30f0 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/src/new_alert_system.ads @@ -0,0 +1,49 @@ +package New_Alert_System is + + type My_Time is new Natural; + Zero_Time : My_Time := My_Time'First; + Critical_Time : My_Time := 100; + + function My_Clock return My_Time; + procedure Set_Time (New_Time : My_Time); + + type Device is new Natural; + System_Device : Device; + + type Person is (Volunteer, Soldier, Sergeant, Major); + type Text is new String (1 .. 10); + No_Message : Text := (others => ' '); + + type Alert is tagged record + Idx : Natural; + Time_Of_Arrival : My_Time; + Message : Text; + end record; + + procedure Handle (A : in out Alert); + + procedure Display (A : in Alert; + On : out Device); + + function Log (A : in Alert) return Natural; + + + type Low_Alert is new Alert with null record; + + type Medium_Alert is new Alert with record + Action_Officer: Person; + end record; + + -- now override inherited operation + procedure Handle (MA : in out Medium_Alert); + + type High_Alert is new Medium_Alert with record + Ring_Alarm_At: My_Time; + end record; + + procedure Handle (HA : in out High_Alert); + procedure Set_Alarm (HA : in out High_Alert); + function Log (HA : in High_Alert) return Natural; + + +end New_Alert_System; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_1.adb b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_1.adb new file mode 100755 index 000000000..1a8e13fca --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_1.adb @@ -0,0 +1,40 @@ +-- Test driver for checking the coverage information in case when the call to +-- a class-wide operation results in dynamic dispatching. Only one +-- implementation of the called discpatching operation is actually called, all +-- the other operations should be reported as fully uncovered + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with New_Alert_System.Objects; use New_Alert_System.Objects; +with Class_Wide_Ops; use Class_Wide_Ops; + +with Support; use Support; + +procedure Test_1 is +begin + Handle_Alert (Empty_Low_Alert); + Assert (Empty_Low_Alert.Idx = 0); +end Test_1; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- + +--# new_alert_system-emergency.adb +-- /ea_handle/ l- ## s- +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l- ## s- +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l- ## s- +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_2.adb b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_2.adb new file mode 100755 index 000000000..9b59b1bc3 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_2.adb @@ -0,0 +1,40 @@ +-- Test driver for checking the coverage information in case when the call to +-- a class-wide operation results in dynamic dispatching. Only one +-- implementation of the called discpatching operation is actually called, all +-- the other operations should be reported as fully uncovered + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Objects; use New_Alert_System.Objects; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with Class_Wide_Ops; use Class_Wide_Ops; + +with Support; use Support; + +procedure Test_2 is +begin + Handle_Alert (Empty_Medium_Alert); + Assert (Empty_Medium_Alert.Idx = 0); +end Test_2; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- + +--# new_alert_system-emergency.adb +-- /ea_handle/ l- ## s- +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l- ## s- +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l- ## s- +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_3.adb b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_3.adb new file mode 100755 index 000000000..a95e97aaa --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_3.adb @@ -0,0 +1,40 @@ +-- Test driver for checking the coverage information in case when the call to +-- a class-wide operation results in dynamic dispatching. Only one +-- implementation of the called discpatching operation is actually called, all +-- the other operations should be reported as fully uncovered + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with New_Alert_System.Objects; use New_Alert_System.Objects; +with Class_Wide_Ops; use Class_Wide_Ops; + +with Support; use Support; + +procedure Test_3 is +begin + Handle_Alert (Empty_High_Alert); + Assert (Empty_High_Alert.Idx = 0); +end Test_3; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l+ ## 0 +-- /a_log/ l- ## s- +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l+ ## 0 +-- /ha_set_alarm/ l+ ## 0 +-- /ha_log/ l+ ## 0 + +--# new_alert_system-emergency.adb +-- /ea_handle/ l- ## s- +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l- ## s- +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l- ## s- +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_4.adb b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_4.adb new file mode 100755 index 000000000..2bda355a5 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_4.adb @@ -0,0 +1,42 @@ +-- Test driver for checking the coverage information in case when the call to +-- a class-wide operation results in dynamic dispatching. Only one +-- implementation of the called discpatching operation is actually called, all +-- the other operations should be reported as fully uncovered + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with New_Alert_System.Objects; use New_Alert_System.Objects; +with Class_Wide_Ops; use Class_Wide_Ops; + +with Support; use Support; + +procedure Test_4 is + EA : Emergency_Alert := Get_Empty_Emergency_Alert; + +begin + Handle_Alert (EA); + Assert (Log (EA) = 100); +end Test_4; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l+ ## 0 +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- + +--# new_alert_system-emergency.adb +-- /ea_handle/ l+ ## 0 +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l+ ## 0 +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l+ ## 0 +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_full.adb b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_full.adb new file mode 100755 index 000000000..5446bd214 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_full.adb @@ -0,0 +1,51 @@ +-- Test driver for checking the coverage information in case when the call to +-- a class-wide operation results in dynamic dispatching. All the +-- implementations of the called discpatching operations are called, so +-- coverage information should be reported for all of them + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with New_Alert_System.Objects; use New_Alert_System.Objects; +with Class_Wide_Ops; use Class_Wide_Ops; + +with Support; use Support; + +procedure Test_Full is + EA : Emergency_Alert := Get_Empty_Emergency_Alert; + +begin + Handle_Alert (Empty_Low_Alert); + Assert (Empty_Low_Alert.Idx = 0); + + Handle_Alert (Empty_Medium_Alert); + Assert (Empty_Medium_Alert.Idx = 1); + + Handle_Alert (Empty_High_Alert); + Assert (Empty_High_Alert.Idx = 2); + + Handle_Alert (EA); + Assert (Log (EA) = 103); +end Test_Full; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l+ ## 0 +-- /a_log/ l+ ## 0 +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l+ ## 0 +-- /ha_set_alarm/ l+ ## 0 +-- /ha_log/ l+ ## 0 + +--# new_alert_system-emergency.adb +-- /ea_handle/ l+ ## 0 +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l+ ## 0 +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l+ ## 0 +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_no.adb b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_no.adb new file mode 100755 index 000000000..ee7c1e083 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/src/test_no.adb @@ -0,0 +1,39 @@ +-- Test driver for checking the coverage information in case of class-wide +-- operation. Check that when a class-wide operation is not called, nothing +-- from the operation itself as well as from the dispatching operation it can +-- call is reported as covered. + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with New_Alert_System.Objects; use New_Alert_System.Objects; +with Class_Wide_Ops; use Class_Wide_Ops; + +with Support; use Support; + +procedure Test_No is +begin + Assert (True); +end Test_No; + +--# new_alert_system.adb +-- /get_idx/ l- ## s- +-- /my_clock/ l- ## s- +-- /set_time/ l- ## s- +-- /a_handle/ l- ## s- +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- + +--# new_alert_system-emergency.adb +-- /ea_handle/ l- ## s- +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l- ## s- +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l- ## s- +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/tc.txt b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/tc.txt new file mode 100755 index 000000000..ee3e66e2a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/tc.txt @@ -0,0 +1,7 @@ +In the hierarchy of a (tagged) derived types, call primitive subprograms from +the class-wide operation in such a way that the called subprogram is detected +only dinamically. + +Verify that: + +* only the code of actually called subprograms is reported as covered; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/test.py b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Class_Wide_Operations/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_1.adb b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_1.adb new file mode 100755 index 000000000..fa04fde72 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_1.adb @@ -0,0 +1,25 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver cannot be resolved statically. +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Objects; use New_Alert_System.Objects; + +with Support; use Support; + +procedure Test_1 is + LA : Alert'Class := Empty_Low_Alert; +begin + Handle (LA); + Assert (LA.Idx = 0); +end Test_1; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_2.adb b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_2.adb new file mode 100755 index 000000000..29f45f82c --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_2.adb @@ -0,0 +1,25 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver cannot be resolved statically +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Objects; use New_Alert_System.Objects; + +with Support; use Support; + +procedure Test_2 is + MA : Alert'Class := Empty_Medium_Alert; +begin + Handle (MA); + Assert (MA.Idx = 0); +end Test_2; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_3.adb b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_3.adb new file mode 100755 index 000000000..667715eec --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_3.adb @@ -0,0 +1,25 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver cannot be resolved statically +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Objects; use New_Alert_System.Objects; + +with Support; use Support; + +procedure Test_3 is + HA : Alert'Class := Empty_High_Alert; +begin + Handle (HA); + Assert (HA.Idx = 0); +end Test_3; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l+ ## 0 +-- /a_log/ l- ## s- +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l+ ## 0 +-- /ha_set_alarm/ l+ ## 0 +-- /ha_log/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_4.adb b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_4.adb new file mode 100755 index 000000000..30be2931d --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/src/test_4.adb @@ -0,0 +1,38 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver cannot be resolved statically +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; +with New_Alert_System.Objects; use New_Alert_System.Objects; + +with Support; use Support; + +procedure Test_4 is + EA : Alert'Class := Get_Empty_Emergency_Alert; + +begin + Handle (EA); + Assert (Log (EA) = 100); +end Test_4; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l+ ## 0 +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- + +--# new_alert_system-emergency.adb +-- /ea_handle/ l+ ## 0 +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l+ ## 0 +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l+ ## 0 +-- /ea_catastrophe/ l- ## s- +-- /ea_get/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/tc.txt b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/tc.txt new file mode 100755 index 000000000..33f890e2d --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/tc.txt @@ -0,0 +1,7 @@ +In the hierarchy of a (tagged) derived types, call primitive subprograms in +such a way that the called subprogram is detected only dinamically. No +class-wide operation is involved + +Verify that: + +* only the code of actually called subprograms is reported as covered; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/test.py b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Dynamic_Binding/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_inherited.adb b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_inherited.adb new file mode 100755 index 000000000..9111476e9 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_inherited.adb @@ -0,0 +1,28 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- Checks that in case when an implicitly declared inherited subprogram is +-- called, the coverage information is correctly generated for the explicit +-- subprogram it is derived from + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Objects; use New_Alert_System.Objects; + +with Support; use Support; + +procedure Test_Inherited is + Res : Natural := Log (Empty_Medium_Alert); +begin + Assert (Res = 0); + null; +end Test_Inherited; + +--# new_alert_system.adb +-- /get_idx/ l- ## s- +-- /my_clock/ l- ## s- +-- /set_time/ l- ## s- +-- /a_handle/ l- ## s- +-- /a_display/ l- ## s- +-- /a_log/ l+ ## 0 +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_overriding.adb b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_overriding.adb new file mode 100755 index 000000000..b3df889b4 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/src/test_overriding.adb @@ -0,0 +1,30 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- Checks that in case when an explicitely declared subprogram that ovverrides +-- the implicitely declared inherited subprogram is called, the coverage +-- information is correctly generated for this explicit subprogram, but not +-- for the (explicitely declared) subprogram from that the overriden +-- subprogram is inherited + +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Objects; use New_Alert_System.Objects; + +with Support; use Support; + +procedure Test_Overriding is + Res : Natural := Log (Empty_High_Alert); +begin + Assert (Res = 10); + null; +end; + +--# new_alert_system.adb +-- /get_idx/ l- ## s- +-- /my_clock/ l- ## s- +-- /set_time/ l- ## s- +-- /a_handle/ l- ## s- +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/tc.txt b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/tc.txt new file mode 100755 index 000000000..e282cc6e9 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/tc.txt @@ -0,0 +1,12 @@ +In the hierarchy of a (tagged) derived types, call inherited subprograms and +subprograms that overrides the implicitly inherited operations. + +Verify that: + +* If an implicitly declared inherited subprogram is called, only (a part of) + the code of the explicitly declared subprogram it is inherited from is + reported as covered; + +* If an explicitly declared subprogram that overrides the implicitly + inherited subprogram is called, the code of the overriding subprogram is + reported as covered, but not the code of the subprogram being overridden; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/test.py b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Inheritance/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.adb new file mode 100755 index 000000000..9b0e433a6 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.adb @@ -0,0 +1,10 @@ +package body A is + procedure Class_Wide_IA (X : in out IA'Class) is + begin + if Test_IA (X) then -- # class_wide_ia + P_IA_1 (X); -- # if_cw_ia + else + P_IA_2 (X); -- # else_cw_ia + end if; + end Class_Wide_IA; +end A; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.ads new file mode 100755 index 000000000..146a30855 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/a.ads @@ -0,0 +1,10 @@ +package A is + type IA is interface; + + procedure P_IA_1 (X : in out IA) is null; + procedure P_IA_2 (X : in out IA) is null; + + function Test_IA (X : IA) return Boolean is abstract; + + procedure Class_Wide_IA (X : in out IA'Class); +end A; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.adb new file mode 100755 index 000000000..ad1563185 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.adb @@ -0,0 +1,10 @@ +package body B is + procedure Class_Wide_IB (X : in out IB'Class) is + begin + if Test_IB (X) then -- # class_wide_ib + P_IB_1 (X); -- # if_cw_ib + else + P_IB_2 (X); -- # else_cw_ib + end if; + end Class_Wide_IB; +end B; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.ads new file mode 100755 index 000000000..229c75c1d --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/b.ads @@ -0,0 +1,10 @@ +package B is + type IB is interface; + + procedure P_IB_1 (X : in out IB) is null; + procedure P_IB_2 (X : in out IB) is null; + + function Test_IB (X : IB) return Boolean is abstract; + + procedure Class_Wide_IB (X : in out IB'Class); +end B; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.adb new file mode 100755 index 000000000..d699720f8 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.adb @@ -0,0 +1,10 @@ +package body C is + procedure Class_Wide_IC (X : in out IC'Class) is + begin + if Test_IC (X) then -- # class_wide_ic + Class_Wide_IA (X); -- # if_cw_ic + else + Class_Wide_IB (X); -- # else_cw_ic + end if; + end Class_Wide_IC; +end C; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.ads new file mode 100755 index 000000000..6916a4075 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/c.ads @@ -0,0 +1,9 @@ +with A; use A; +with B; use B; +package C is + type IC is interface and IA and IB; + + function Test_IC (X : IC) return Boolean is abstract; + + procedure Class_Wide_IC (X : in out IC'Class); +end C; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_1.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_1.adb new file mode 100755 index 000000000..653055db2 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_1.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_1 is + Var : T_X_A := (I1 => 1, I2 => 1); +begin + Class_Wide_IA (Var); + Assert (Var.I1 = 11 and then Var.I2 = 21); +end Test_1; + +--# a.adb +-- /class_wide_ia/ l+ ## 0 +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l+ ## 0 + +--# b.adb +-- /class_wide_ib/ l- ## s- +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l+ ## 0 +-- /xa_test_ia/ l+ ## 0 + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_10.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_10.adb new file mode 100755 index 000000000..0316cf09a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_10.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_10 is + Var : T_Y_B := (I1 => 1, I2 => 2); +begin + Class_Wide_IB (Var); + Assert (Var.I1 = 100 and then Var.I2 = 100); +end Test_10; + +--# a.adb +-- /class_wide_ia/ l- ## s- +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l+ ## 0 +-- /if_cw_ib/ l+ ## 0 +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l+ ## 0 +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l+ ## 0 + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_11.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_11.adb new file mode 100755 index 000000000..b467713c9 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_11.adb @@ -0,0 +1,75 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_11 is + Var : T_Y_C := (I1 => 1, I2 => 1); +begin + Class_Wide_IC (Var); + -- Class-wide operation calls null procedures for P_I(A|B)_(1|2)! + Assert (Var.I1 = 1 and then Var.I2 = 1); +end Test_11; + +--# a.adb +-- /class_wide_ia/ l- ## s- +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l+ ## 0 +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l+ ## 0 + +--# c.adb +-- /class_wide_ic/ l+ ## 0 +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l+ ## 0 + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l+ ## 0 +-- /yc_test_ic/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_12.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_12.adb new file mode 100755 index 000000000..7734075f3 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_12.adb @@ -0,0 +1,75 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_12 is + Var : T_Y_C := (I1 => 2, I2 => 1); +begin + Class_Wide_IC (Var); + -- Class-wide operation calls null procedures for P_I(A|B)_(1|2)! + Assert (Var.I1 = 2 and then Var.I2 = 1); +end Test_12; + +--# a.adb +-- /class_wide_ia/ l+ ## 0 +-- /if_cw_ia/ l+ ## 0 +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l- ## s- +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l+ ## 0 +-- /if_cw_ic/ l+ ## 0 +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l+ ## 0 +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_2.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_2.adb new file mode 100755 index 000000000..e27fa2fcb --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_2.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_2 is + Var : T_X_A := (I1 => 2, I2 => 1); +begin + Class_Wide_IA (Var); + Assert (Var.I1 = 0 and then Var.I2 = 0); +end Test_2; + +--# a.adb +-- /class_wide_ia/ l+ ## 0 +-- /if_cw_ia/ l+ ## 0 +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l- ## s- +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l+ ## 0 +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l+ ## 0 + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_3.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_3.adb new file mode 100755 index 000000000..eb13298e5 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_3.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_3 is + Var : T_X_B := (I1 => 1, I2 => 1); +begin + Class_Wide_IB (Var); + Assert (Var.I1 = 11 and then Var.I2 = 21); +end Test_3; + +--# a.adb +-- /class_wide_ia/ l- ## s- +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l+ ## 0 +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l+ ## 0 + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l+ ## 0 +-- /xb_test_ib/ l+ ## 0 + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_4.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_4.adb new file mode 100755 index 000000000..feb842ba5 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_4.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_4 is + Var : T_X_B := (I1 => 2, I2 => 1); +begin + Class_Wide_IB (Var); + Assert (Var.I1 = 0 and then Var.I2 = 0); +end Test_4; + +--# a.adb +-- /class_wide_ia/ l- ## s- +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l+ ## 0 +-- /if_cw_ib/ l+ ## 0 +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l+ ## 0 +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l+ ## 0 + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_5.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_5.adb new file mode 100755 index 000000000..7a68b9167 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_5.adb @@ -0,0 +1,75 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_5 is + Var : T_X_C := (I1 => 1, I2 => 1); +begin + Class_Wide_IC (Var); + -- Class-wide operation calls null procedures for P_I(A|B)_(1|2)! + Assert (Var.I1 = 1 and then Var.I2 = 1); +end Test_5; + +--# a.adb +-- /class_wide_ia/ l- ## s- +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l+ ## 0 +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l+ ## 0 + +--# c.adb +-- /class_wide_ic/ l+ ## 0 +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l+ ## 0 + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l+ ## 0 +-- /xc_test_ic/ l+ ## 0 + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_6.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_6.adb new file mode 100755 index 000000000..907222b9f --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_6.adb @@ -0,0 +1,75 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_6 is + Var : T_X_C := (I1 => 2, I2 => 1); +begin + Class_Wide_IC (Var); + -- Class-wide operation calls null procedures for P_I(A|B)_(1|2)! + Assert (Var.I1 = 2 and then Var.I2 = 1); +end Test_6; + +--# a.adb +-- /class_wide_ia/ l+ ## 0 +-- /if_cw_ia/ l+ ## 0 +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l- ## s- +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l+ ## 0 +-- /if_cw_ic/ l+ ## 0 +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l+ ## 0 +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l+ ## 0 + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_7.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_7.adb new file mode 100755 index 000000000..a02ed6808 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_7.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_7 is + Var : T_Y_A := (I1 => 1, I2 => 1); +begin + Class_Wide_IA (Var); + Assert (Var.I1 = -9 and then Var.I2 = -19); +end Test_7; + +--# a.adb +-- /class_wide_ia/ l+ ## 0 +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l+ ## 0 + +--# b.adb +-- /class_wide_ib/ l- ## s- +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l+ ## 0 +-- /ya_test_ia/ l+ ## 0 + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_8.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_8.adb new file mode 100755 index 000000000..3b9d54a1c --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_8.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_8 is + Var : T_Y_A := (I1 => 1, I2 => 2); +begin + Class_Wide_IA (Var); + Assert (Var.I1 = 100 and then Var.I2 = 100); +end Test_8; + +--# a.adb +-- /class_wide_ia/ l+ ## 0 +-- /if_cw_ia/ l+ ## 0 +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l- ## s- +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l- ## s- + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l+ ## 0 +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l+ ## 0 + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l- ## s- +-- /yb_test_ib/ l- ## s- + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_9.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_9.adb new file mode 100755 index 000000000..95d9dbfcc --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/test_9.adb @@ -0,0 +1,74 @@ +-- Test driver for checking the coverage information in case of dispatching +-- in the situation of multiple inheritance. The dispatching takes place in +-- a class-wide operation that is defined for an interface type, and this +-- interface is used in more then one inheritance hierarchies. The check is +-- made that only the actually called implementations of the operations +-- defined for interfaces are reported as covered. + +with A; use A; +with B; use B; +with C; use C; + +with X; use X; +with X.A_Child; use X.A_Child; +with X.B_Child; use X.B_Child; +with X.C_Child; use X.C_Child; + +with Y; use Y; +with Y.A_Child; use Y.A_Child; +with Y.B_Child; use Y.B_Child; +with Y.C_Child; use Y.C_Child; + +with Support; use Support; + +procedure Test_9 is + Var : T_Y_B := (I1 => 1, I2 => 1); +begin + Class_Wide_IB (Var); + Assert (Var.I1 = -9 and then Var.I2 = -19); +end Test_9; + +--# a.adb +-- /class_wide_ia/ l- ## s- +-- /if_cw_ia/ l- ## s- +-- /else_cw_ia/ l- ## s- + +--# b.adb +-- /class_wide_ib/ l+ ## 0 +-- /if_cw_ib/ l- ## s- +-- /else_cw_ib/ l+ ## 0 + +--# c.adb +-- /class_wide_ic/ l- ## s- +-- /if_cw_ic/ l- ## s- +-- /else_cw_ic/ l- ## s- + +--# x-a_child.adb +-- /xa_p_ia_1/ l- ## s- +-- /xa_p_ia_2/ l- ## s- +-- /xa_test_ia/ l- ## s- + +--# x-b_child.adb +-- /xb_p_ib_1/ l- ## s- +-- /xb_p_ib_2/ l- ## s- +-- /xb_test_ib/ l- ## s- + +--# x-c_child.adb +-- /xc_test_ia/ l- ## s- +-- /xc_test_ib/ l- ## s- +-- /xc_test_ic/ l- ## s- + +--# y-a_child.adb +-- /ya_p_ia_1/ l- ## s- +-- /ya_p_ia_2/ l- ## s- +-- /ya_test_ia/ l- ## s- + +--# y-b_child.adb +-- /yb_p_ib_1/ l- ## s- +-- /yb_p_ib_2/ l+ ## 0 +-- /yb_test_ib/ l+ ## 0 + +--# y-c_child.adb +-- /yc_test_ia/ l- ## s- +-- /yc_test_ib/ l- ## s- +-- /yc_test_ic/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.adb new file mode 100755 index 000000000..05e049a1f --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.adb @@ -0,0 +1,20 @@ +package body X.A_Child is + + procedure P_IA_1 (X : in out T_X_A) is + begin + X.I1 := 0; -- # xa_p_ia_1 + X.I2 := 0; -- # xa_p_ia_1 + end P_IA_1; + + procedure P_IA_2 (X : in out T_X_A) is + begin + X.I1 := X.I1 + 10; -- # xa_p_ia_2 + X.I2 := X.I2 + 20; -- # xa_p_ia_2 + end P_IA_2; + + function Test_IA (X : T_X_A) return Boolean is + begin + return X.I1 > X.I2; -- # xa_test_ia + end Test_IA; + +end X.A_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.ads new file mode 100755 index 000000000..587b2d681 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-a_child.ads @@ -0,0 +1,12 @@ +with A; use A; +package X.A_Child is + type T_X_A is new T_X and IA with record + I2 : Integer; + end record; + + procedure P_IA_1 (X : in out T_X_A); + procedure P_IA_2 (X : in out T_X_A); + + function Test_IA (X : T_X_A) return Boolean; + +end X.A_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.adb new file mode 100755 index 000000000..71c7c4ef4 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.adb @@ -0,0 +1,20 @@ +package body X.B_Child is + + procedure P_IB_1 (X : in out T_X_B) is + begin + X.I1 := 0; -- # xb_p_ib_1 + X.I2 := 0; -- # xb_p_ib_1 + end P_IB_1; + + procedure P_IB_2 (X : in out T_X_B) is + begin + X.I1 := X.I1 + 10; -- # xb_p_ib_2 + X.I2 := X.I2 + 20; -- # xb_p_ib_2 + end P_IB_2; + + function Test_IB (X : T_X_B) return Boolean is + begin + return X.I1 > X.I2; -- # xb_test_ib + end Test_IB; + +end X.B_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.ads new file mode 100755 index 000000000..6ef30fd6a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-b_child.ads @@ -0,0 +1,12 @@ +with B; use B; +package X.B_Child is + type T_X_B is new T_X and IB with record + I2 : Integer; + end record; + + procedure P_IB_1 (X : in out T_X_B); + procedure P_IB_2 (X : in out T_X_B); + + function Test_IB (X : T_X_B) return Boolean; + +end X.B_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.adb new file mode 100755 index 000000000..69354c022 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.adb @@ -0,0 +1,18 @@ +package body X.C_Child is + + function Test_IA (X : T_X_C) return Boolean is + begin + return X.I1 > X.I2; -- # xc_test_ia + end Test_IA; + + function Test_IB (X : T_X_C) return Boolean is + begin + return X.I1 > X.I2; -- # xc_test_ib + end Test_IB; + + function Test_IC (X : T_X_C) return Boolean is + begin + return X.I1 > X.I2; -- # xc_test_ic + end Test_IC; + +end X.C_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.ads new file mode 100755 index 000000000..2f0516dd1 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x-c_child.ads @@ -0,0 +1,11 @@ +with C; use C; +package X.C_Child is + type T_X_C is new T_X and IC with record + I2 : Integer; + end record; + + function Test_IA (X : T_X_C) return Boolean; + function Test_IB (X : T_X_C) return Boolean; + function Test_IC (X : T_X_C) return Boolean; + +end X.C_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x.ads new file mode 100755 index 000000000..beb2b177a --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/x.ads @@ -0,0 +1,6 @@ +package X is + type T_X is tagged record + I1 : Integer; + end record; + +end X; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.adb new file mode 100755 index 000000000..9ecb35f84 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.adb @@ -0,0 +1,20 @@ +package body Y.A_Child is + + procedure P_IA_1 (Y : in out T_Y_A) is + begin + Y.I1 := 100; -- # ya_p_ia_1 + Y.I2 := 100; -- # ya_p_ia_1 + end P_IA_1; + + procedure P_IA_2 (Y : in out T_Y_A) is + begin + Y.I1 := Y.I1 - 10; -- # ya_p_ia_2 + Y.I2 := Y.I2 - 20; -- # ya_p_ia_2 + end P_IA_2; + + function Test_IA (Y : T_Y_A) return Boolean is + begin + return Y.I1 < Y.I2; -- # ya_test_ia + end Test_IA; + +end Y.A_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.ads new file mode 100755 index 000000000..e48531e26 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-a_child.ads @@ -0,0 +1,12 @@ +with A; use A; +package Y.A_Child is + type T_Y_A is new T_Y and IA with record + I2 : Integer; + end record; + + procedure P_IA_1 (Y : in out T_Y_A); + procedure P_IA_2 (Y : in out T_Y_A); + + function Test_IA (Y : T_Y_A) return Boolean; + +end Y.A_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.adb new file mode 100755 index 000000000..58af4b641 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.adb @@ -0,0 +1,20 @@ +package body Y.B_Child is + + procedure P_IB_1 (Y : in out T_Y_B) is + begin + Y.I1 := 100; -- # yb_p_ib_1 + Y.I2 := 100; -- # yb_p_ib_1 + end P_IB_1; + + procedure P_IB_2 (Y : in out T_Y_B) is + begin + Y.I1 := Y.I1 - 10; -- # yb_p_ib_2 + Y.I2 := Y.I2 - 20; -- # yb_p_ib_2 + end P_IB_2; + + function Test_IB (Y : T_Y_B) return Boolean is + begin + return Y.I1 < Y.I2; -- # yb_test_ib + end Test_IB; + +end Y.B_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.ads new file mode 100755 index 000000000..2ff6bc51b --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-b_child.ads @@ -0,0 +1,12 @@ +with B; use B; +package Y.B_Child is + type T_Y_B is new T_Y and IB with record + I2 : Integer; + end record; + + procedure P_IB_1 (Y : in out T_Y_B); + procedure P_IB_2 (Y : in out T_Y_B); + + function Test_IB (Y : T_Y_B) return Boolean; + +end Y.B_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.adb b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.adb new file mode 100755 index 000000000..c2c23a31f --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.adb @@ -0,0 +1,18 @@ +package body Y.C_Child is + + function Test_IA (Y : T_Y_C) return Boolean is + begin + return Y.I1 > Y.I2; -- # yc_test_ia + end Test_IA; + + function Test_IB (Y : T_Y_C) return Boolean is + begin + return Y.I1 > Y.I2; -- # yc_test_ib + end Test_IB; + + function Test_IC (Y : T_Y_C) return Boolean is + begin + return Y.I1 > Y.I2; -- # yc_test_ic + end Test_IC; + +end Y.C_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.ads new file mode 100755 index 000000000..8929513f7 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y-c_child.ads @@ -0,0 +1,11 @@ +with C; use C; +package Y.C_Child is + type T_Y_C is new T_Y and IC with record + I2 : Integer; + end record; + + function Test_IA (Y : T_Y_C) return Boolean; + function Test_IB (Y : T_Y_C) return Boolean; + function Test_IC (Y : T_Y_C) return Boolean; + +end Y.C_Child; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y.ads b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y.ads new file mode 100755 index 000000000..fcecde92d --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/src/y.ads @@ -0,0 +1,5 @@ +package Y is + type T_Y is tagged record + I1 : Integer; + end record; +end Y; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/tc.txt b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/tc.txt new file mode 100755 index 000000000..d9a6fcec5 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/tc.txt @@ -0,0 +1,7 @@ +In case of multiple inheritance, define class-vide operations for interface +types and then check what is called and reported as covered in different +hierarchies. + +Verify that: + +* only the code of actually called subprograms is reported as covered; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.opt b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.opt new file mode 100755 index 000000000..69fd8e815 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.opt @@ -0,0 +1,4 @@ +5.04a1 DEAD stack overflow not caused by instrumentation in 5.04 +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.py b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Multiple_Inheritance/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_1.adb b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_1.adb new file mode 100755 index 000000000..d1101c699 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_1.adb @@ -0,0 +1,24 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver can be resolved statically. +with New_Alert_System; use New_Alert_System; + +with Support; use Support; + +procedure Test_1 is + LA : Low_Alert; +begin + Handle (LA); + Assert (LA.Idx = 0); +end Test_1; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_2.adb b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_2.adb new file mode 100755 index 000000000..1faf46059 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_2.adb @@ -0,0 +1,24 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver can be resolved statically +with New_Alert_System; use New_Alert_System; + +with Support; use Support; + +procedure Test_2 is + MA : Medium_Alert; +begin + Handle (MA); + Assert (MA.Action_Officer = Volunteer); +end Test_2; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_3.adb b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_3.adb new file mode 100755 index 000000000..60b1bec10 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_3.adb @@ -0,0 +1,24 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver can be resolved statically +with New_Alert_System; use New_Alert_System; + +with Support; use Support; + +procedure Test_3 is + HA : High_Alert; +begin + Handle (HA); + Assert (HA.Action_Officer = Sergeant); +end Test_3; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l+ ## 0 +-- /a_log/ l- ## s- +-- /ma_handle/ l+ ## 0 +-- /ha_handle/ l+ ## 0 +-- /ha_set_alarm/ l+ ## 0 +-- /ha_log/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_4.adb b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_4.adb new file mode 100755 index 000000000..d8ea95b40 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/src/test_4.adb @@ -0,0 +1,36 @@ +-- Test driver for checking the coverage information in case of inheritance. +-- The call to Handle in the test driver can be resolved statically +with New_Alert_System; use New_Alert_System; +with New_Alert_System.Emergency; use New_Alert_System.Emergency; + +with Support; use Support; + +procedure Test_4 is + EA : Emergency_Alert; +begin + Handle (EA); + Assert (not Catastrophe (EA)); +end Test_4; + +--# new_alert_system.adb +-- /get_idx/ l+ ## 0 +-- /my_clock/ l+ ## 0 +-- /set_time/ l- ## s- +-- /a_handle/ l+ ## 0 +-- /a_display/ l- ## s- +-- /a_log/ l- ## s- +-- /ma_handle/ l- ## s- +-- /ha_handle/ l- ## s- +-- /ha_set_alarm/ l- ## s- +-- /ha_log/ l- ## s- + +--# new_alert_system-emergency.adb +-- /ea_handle/ l+ ## 0 +-- /ea_hand_catastrophe/ l- ## s- +-- /ea_hand_no_catastrophe/ l+ ## 0 +-- /ea_display/ l- ## s- +-- /ea_displ_catastrophe/ l- ## s- +-- /ea_displ_no_catastrophe/ l- ## s- +-- /ea_log/ l- ## s- +-- /ea_catastrophe/ l+ ## 0 +-- /ea_get/ l- ## s- diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/tc.txt b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/tc.txt new file mode 100755 index 000000000..99197908f --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/tc.txt @@ -0,0 +1,7 @@ +In the hierarchy of a (tagged) derived types, call primitive subprograms in +such a way that the called subprogram is statically detected from arguments +types. + +Verify that: + +* only the code of actually called subprograms is reported as covered; diff --git a/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/test.py b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/test.py new file mode 100755 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/OOP/stmt/Static_Binding/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb new file mode 100644 index 000000000..97f44f284 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb @@ -0,0 +1,17 @@ +with Synchronization; + +procedure Test_Driver is +begin + null; +end; + + +--# synchronization.adb +-- /prod/ l+ ## 0 +-- /cons/ l+ ## 0 +-- /test/ l! ## dT- +-- /exception/ l- ## s- +-- /put_element/ l+ ## 0 +-- /open_barrier/ l+ ## 0 +-- /get_element/ l+ ## 0 +-- /close_barrier/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.opt b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.opt new file mode 100644 index 000000000..9b3f40f99 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR,!native +RTS_FULL,!native +ALL DEAD [M305-011] relies on Ravenscar constructs + strict priority based scheduling diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.py b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.adb b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.adb new file mode 100644 index 000000000..4f0f7d511 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.adb @@ -0,0 +1,31 @@ +package body Synchronization is + + task body Producer is + begin + Buffer.Put (1); -- # prod + end Producer; + + task body Consumer is + Element : Integer; + begin + Buffer.Get (Element); -- # cons + if Element /= 1 then -- # test + raise Program_Error; -- # exception + end if; + end Consumer; + + protected body Buffer is + procedure Put (Item : Integer) is + begin + Element := Item; -- # put_element + Barrier := True; -- # open_barrier + end Put; + + entry Get (Item : out Integer) when Barrier is + begin + Item := Element; -- # get_element + Barrier := False; -- # close_barrier + end Get; + end Buffer; + +end Synchronization; diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.ads b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.ads new file mode 100644 index 000000000..dfed4dcfd --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.ads @@ -0,0 +1,24 @@ +-- Test to check whether we can analyze correctly parts of an execution +-- which are covered after a task is blocked. + +with System; + +package Synchronization is + + task Producer is + pragma Priority (System.Priority'Last - 1); + end Producer; + + task Consumer is + pragma Priority (System.Priority'Last); + end Consumer; + + protected Buffer is + procedure Put (Item : Integer); + entry Get (Item : out Integer); + private + Element : Integer := 0; + Barrier : Boolean := False; + end Buffer; + +end Synchronization; diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/src/test_driver.adb new file mode 100644 index 000000000..5e65baa5c --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/src/test_driver.adb @@ -0,0 +1,17 @@ +with Synchronization; + +procedure Test_Driver is +begin + null; +end; + + +--# synchronization.adb +-- /prod/ l+ ## 0 +-- /cons/ l+ ## 0 +-- /test/ l+ ## 0 +-- /exception/ l- ## s- +-- /put_element/ l+ ## 0 +-- /open_barrier/ l+ ## 0 +-- /get_element/ l+ ## 0 +-- /close_barrier/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.opt b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.opt new file mode 100644 index 000000000..44f4c3589 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.py b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/stmt/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/src/test_driver.adb new file mode 100644 index 000000000..310e4c3e0 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/src/test_driver.adb @@ -0,0 +1,19 @@ +with Synchronization; + +procedure Test_Driver is +begin + null; +end; + + +--# synchronization.adb +-- /prod/ l+ ## 0 +-- /signal_send/ l+ ## 0 +-- /signal_ack_wait/ l+ ## 0 +-- /test_2/ l! ## dT- +-- /exception_2/ l- ## s- +-- /signal_wait/ l+ ## 0 +-- /test_1/ l! ## dF- +-- /change/ l+ ## 0 +-- /signal_ack_send/ l+ ## 0 +-- /exception_1/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.opt b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.opt new file mode 100644 index 000000000..44f4c3589 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.py b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/decision/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.adb b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.adb new file mode 100644 index 000000000..4fd07800d --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.adb @@ -0,0 +1,27 @@ +with Ada.Synchronous_Task_Control; use Ada.Synchronous_Task_Control; + +package body Synchronization is + + task body Signaler is + begin + Buffer := 1; -- # prod + Set_True (Signal_Sent); -- # signal_send + Suspend_Until_True (Signal_Ack); -- # signal_ack_wait + if Buffer /= 2 then -- # test_2 + raise Program_Error; -- # exception_2 + end if; + end Signaler; + + task body Waiter is + Element : Integer; + begin + Suspend_Until_True (Signal_Sent); -- # signal_wait + if Buffer = 1 then -- # test_1 + Buffer := 2; -- # change + Set_True (Signal_Ack); -- # signal_ack_send + else + raise Program_Error; -- # exception_1 + end if; + end Waiter; + +end Synchronization; diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.ads b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.ads new file mode 100644 index 000000000..441b87ba2 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/src/synchronization.ads @@ -0,0 +1,21 @@ +-- Test to check whether we can analyze correctly parts of an execution +-- which are covered after a task is blocked in a suspension object. + +with System; +with Ada.Synchronous_Task_Control; + +package Synchronization is + + task Signaler is + pragma Priority (System.Priority'Last - 1); + end Signaler; + + task Waiter is + pragma Priority (System.Priority'Last); + end Waiter; + + Signal_Sent, Signal_Ack : Ada.Synchronous_Task_Control.Suspension_Object; + Buffer : Integer := 0; + pragma Volatile (Buffer); + +end Synchronization; diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/src/test_driver.adb new file mode 100644 index 000000000..1b71a77f9 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/src/test_driver.adb @@ -0,0 +1,19 @@ +with Synchronization; + +procedure Test_Driver is +begin + null; +end; + + +--# synchronization.adb +-- /prod/ l+ ## 0 +-- /signal_send/ l+ ## 0 +-- /signal_ack_wait/ l+ ## 0 +-- /test_2/ l+ ## 0 +-- /exception_2/ l- ## s- +-- /signal_wait/ l+ ## 0 +-- /test_1/ l+ ## 0 +-- /change/ l+ ## 0 +-- /signal_ack send/ l+ ## 0 +-- /exception_1/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.opt b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.opt new file mode 100644 index 000000000..44f4c3589 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.py b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/SuspensionObjects/stmt/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/src/test_driver.adb new file mode 100644 index 000000000..2c44b2069 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/src/test_driver.adb @@ -0,0 +1,15 @@ +with Blocks_By_Tasks; + +procedure Test_Driver is +begin + null; +end; + + +--# blocks_by_tasks.adb +-- /blk1_tst/ l+ ## 0 +-- /blk1_stmt/ l+ ## 0 +-- /blk2_tst/ l+ ## 0 +-- /blk2_stmt/ l+ ## 0 +-- /blk3_tst/ l! ## dT- +-- /blk3_stmt/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.opt b/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.opt new file mode 100644 index 000000000..44f4c3589 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.py b/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/decision/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.adb b/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.adb new file mode 100644 index 000000000..bc164c88d --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.adb @@ -0,0 +1,22 @@ +package body Blocks_By_Tasks is + First_Block, Second_Block, Third_Block : Boolean := False; + + task body Processing is + begin + -- Block to be covered by instances of type Block1 + if Kind = Block1 then -- # blk1_tst + First_Block := True; -- # blk1_stmt + end if; + + -- Block to be covered by instances of type Block2 + if Kind = Block2 then -- # blk2_tst + Second_Block := True; -- # blk2_stmt + end if; + + -- Block to be covered by instances of type Block3, but none + -- created in this test case. + if Kind = Block3 then -- # blk3_tst + Third_Block := True; -- # blk3_stmt + end if; + end Processing; +end Blocks_By_Tasks; diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.ads b/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.ads new file mode 100644 index 000000000..c36af64dd --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.ads @@ -0,0 +1,19 @@ +-- Test to check whether we can analyze correctly parts of a task type +-- covered by different instances of the type. There are three if +-- statements, each of them checking the discriminant used in the +-- task instantiation. There are two tasks instances, intended to +-- cover the first two blocks, and a third block is not covered +-- because no task instance is declared to cover that block. + +with System; + +package Blocks_By_Tasks is + type Task_Kind is (Block1, Block2, Block3); + + task type Processing (Kind : Task_Kind) is + pragma Priority (System.Priority'Last); + end Processing; + + T1 : Processing (Block1); + T2 : Processing (Block2); +end Blocks_By_Tasks; diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/src/test_driver.adb new file mode 100644 index 000000000..de5339ab1 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/src/test_driver.adb @@ -0,0 +1,15 @@ +with Blocks_By_Tasks; + +procedure Test_Driver is +begin + null; +end; + + +--# blocks_by_tasks.adb +-- /blk1_tst/ l+ ## 0 +-- /blk1_stmt/ l+ ## 0 +-- /blk2_tst/ l+ ## 0 +-- /blk2_stmt/ l+ ## 0 +-- /blk3_tst/ l+ ## 0 +-- /blk3_stmt/ l- ## s- diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.opt b/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.opt new file mode 100644 index 000000000..44f4c3589 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.py b/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/stmt/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb b/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb new file mode 100644 index 000000000..eab3a20c3 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb @@ -0,0 +1,19 @@ +with Sync; use Sync; +procedure Test_1 is +begin + Termination.Wait; +end; + + +--# sync.adb +-- /pro_do/ l+ ## 0 +-- /con_do/ l+ ## 0 +-- /psh_do/ l+ ## 0 +-- /psh_ttell/ l! ## dT- +-- /psh_tell/ l- ## s- +-- /pop_do/ l+ ## 0 +-- /pop_ttell/ l! ## dF- +-- /pop_tell/ l+ ## 0 +-- /rch_do/ l+ ## 0 +-- /wat_guard/ l. ## 0 +-- /wat_do/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/example0/decision/test.opt b/testsuite/tests/Ravenscar/example0/decision/test.opt new file mode 100644 index 000000000..9b3f40f99 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/decision/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR,!native +RTS_FULL,!native +ALL DEAD [M305-011] relies on Ravenscar constructs + strict priority based scheduling diff --git a/testsuite/tests/Ravenscar/example0/decision/test.py b/testsuite/tests/Ravenscar/example0/decision/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/decision/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/Ravenscar/example0/src/sync.adb b/testsuite/tests/Ravenscar/example0/src/sync.adb new file mode 100644 index 000000000..37e0f873a --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/src/sync.adb @@ -0,0 +1,53 @@ +with GNAT.IO; use GNAT.IO; +package body Sync is + + protected body Buffer is + procedure Push (V : Integer; Tell : Boolean) is + begin + if Tell then -- # psh_ttell + Put_Line ("push " & Integer'Image (V)); -- # psh_tell + end if; + Value := V; -- # psh_do + Has_Value := True; -- # psh_do + end; + + entry Pop (V : out Integer; Tell : Boolean) when Has_Value is + begin + V := Value; -- # pop_do + if Tell then -- # pop_ttell + Put_Line ("pop " & Integer'Image (V)); -- # pop_tell + end if; + Has_Value := False; -- # pop_do + end; + end Buffer; + + protected body Sync_Point is + procedure Reach is + begin + Reaches_So_Far := Reaches_So_Far + 1; -- # rch_do + Pass := Reaches_So_Far >= N; -- # rch_do + end; + + entry Wait when Pass is -- # wat_guard + begin + null; -- # wat_do + end; + end Sync_Point; + + -- + + B0 : Buffer; + + task body Producer is + begin + B0.Push (V => 12, Tell => False); -- # pro_do + Termination.Reach; -- # pro_do + end; + + task body Consumer is + V : Integer; + begin + B0.Pop (V => V, Tell => True); -- # con_do + Termination.Reach; -- # con_do + end; +end; diff --git a/testsuite/tests/Ravenscar/example0/src/sync.ads b/testsuite/tests/Ravenscar/example0/src/sync.ads new file mode 100644 index 000000000..ebf12aa65 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/src/sync.ads @@ -0,0 +1,49 @@ +with System; + +package Sync is + + -- Simple 1 slot protected buffer + + protected type Buffer is + procedure Push (V : Integer; Tell : Boolean); + entry Pop (V : out Integer; Tell : Boolean); + private + Value : Integer; + Has_Value : Boolean := False; + end; + + -- One producer and one consumer of Buffer data. + -- See the Notes at the end for the choice of priorities. + + task Producer is + pragma Priority (System.Default_Priority-2); + end; + + task Consumer is + pragma Priority (System.Default_Priority-1); + end; + + -- Simple environment termination control + + protected type Sync_Point (N : Positive) is + procedure Reach; + entry Wait; -- until N calls to Reach + private + Reaches_So_Far : Natural := 0; + Pass : Boolean := False; + end; + + -- To let the environment task know when both + -- the Consumer and the Producer tasks are done + + Termination : Sync_Point (N => 2); + + -- Notes: the priorties are chosen to have + -- + -- prio (environment) > prio (consumer) > prio (producer) + -- + -- to make sure that the guards are exercised both ways, False + -- then True. + +end; + diff --git a/testsuite/tests/Ravenscar/example0/stmt/src/test_1.adb b/testsuite/tests/Ravenscar/example0/stmt/src/test_1.adb new file mode 100644 index 000000000..fbafee363 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/stmt/src/test_1.adb @@ -0,0 +1,18 @@ +with Sync; use Sync; +procedure Test_1 is +begin + Termination.Wait; +end; + + +--# sync.adb +-- /pro_do/ l+ ## 0 +-- /con_do/ l+ ## 0 +-- /psh_do/ l+ ## 0 +-- /psh_ttell/ l+ ## 0 +-- /psh_tell/ l- ## s- +-- /pop_do/ l+ ## 0 +-- /pop_ttell/ l+ ## 0 +-- /pop_tell/ l+ ## 0 +-- /rch_do/ l+ ## 0 +-- /wat_do/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/example0/stmt/test.opt b/testsuite/tests/Ravenscar/example0/stmt/test.opt new file mode 100644 index 000000000..44f4c3589 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/stmt/test.opt @@ -0,0 +1,3 @@ +RTS_RAVENSCAR +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/Ravenscar/example0/stmt/test.py b/testsuite/tests/Ravenscar/example0/stmt/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/Ravenscar/example0/stmt/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/S213-006-obligation-stats/src/foo.adb b/testsuite/tests/S213-006-obligation-stats/src/foo.adb new file mode 100644 index 000000000..ad66f7103 --- /dev/null +++ b/testsuite/tests/S213-006-obligation-stats/src/foo.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo + (A : Boolean; + B : Boolean; + C : Boolean; + D : Boolean) is +begin + if A and then (B or else + (C and then D)) + then + Put_Line + ("Hello world!"); + end if; +end Foo; diff --git a/testsuite/tests/S213-006-obligation-stats/src/test.adb b/testsuite/tests/S213-006-obligation-stats/src/test.adb new file mode 100644 index 000000000..d263be4d2 --- /dev/null +++ b/testsuite/tests/S213-006-obligation-stats/src/test.adb @@ -0,0 +1,6 @@ +with Foo; + +procedure Test is +begin + Foo (True, True, False, False); +end Test; diff --git a/testsuite/tests/S213-006-obligation-stats/test.py b/testsuite/tests/S213-006-obligation-stats/test.py new file mode 100644 index 000000000..b2bd2bcda --- /dev/null +++ b/testsuite/tests/S213-006-obligation-stats/test.py @@ -0,0 +1,39 @@ +""" +Checks that coverage obligations spanning on multiple lines are not counted +several times in the reported obligation statistics. Checking the XML content +(which also provides the obligation statistics) is verified in +R507-027-xml-summary. +""" + +import re + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + +tmp = Wdir("tmp_") + +covargs = build_and_run( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], + mains=["test.adb"])), + covlevel="stmt+mcdc", mains=["test"], + extra_coverage_args=[]) + +xcov(covargs + ["-axcov"]) +thistest.fail_if_no_match( + 'foo.adb.xcov', + re.compile( + ".*\n" + r"100% statement coverage \(2 out of 2\)\n" + r"0% decision coverage \(0 out of 1\)\n" + r"0% MC/DC coverage \(0 out of 4\)\n" + ".*", + re.DOTALL + ), + contents_of("obj/foo.adb.xcov") +) + +thistest.result() diff --git a/testsuite/tests/S218-011-time-option/main.adb b/testsuite/tests/S218-011-time-option/main.adb new file mode 100644 index 000000000..2d5ca66b2 --- /dev/null +++ b/testsuite/tests/S218-011-time-option/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello World!"); +end Main; diff --git a/testsuite/tests/S218-011-time-option/test.py b/testsuite/tests/S218-011-time-option/test.py new file mode 100644 index 000000000..8732793a0 --- /dev/null +++ b/testsuite/tests/S218-011-time-option/test.py @@ -0,0 +1,38 @@ +import datetime + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + +tmp = Wdir("tmp_") + +prj = gprfor(srcdirs=[".."], mains=["main.adb"]) + +xcov_args = build_and_run(gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-a", "xml"]) + +# Check that by default, date is displayed in local time +xcov(xcov_args) +timezone_offset = datetime.datetime.now().astimezone().strftime("%z") +formatted_offset = timezone_offset[:3] + ":" + timezone_offset[3:5] +thistest.fail_if(formatted_offset not in contents_of("obj/trace.xml"), + "Date displayed in xml report should be specified " + "as local time by default.") + +# Check that passing explicitely local displays the date under the right format +xcov(xcov_args + ["--timezone=local"]) +thistest.fail_if(formatted_offset not in contents_of("obj/trace.xml"), + "Date displayed in xml report does not have the right " + "annotation (time offset expected).") + +# Check that passing explicitely UTC displays the date under the right format +xcov(xcov_args + ["--timezone=utc"]) +thistest.fail_if("UTC" not in contents_of("obj/trace.xml"), + "Date displayed in xml report does not have the right " + "annotation (UTC expected).") + +thistest.result() diff --git a/testsuite/tests/S220-058-auto-scos-fetch/main.adb b/testsuite/tests/S220-058-auto-scos-fetch/main.adb new file mode 100644 index 000000000..650125032 --- /dev/null +++ b/testsuite/tests/S220-058-auto-scos-fetch/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("hello there"); +end Main; diff --git a/testsuite/tests/S220-058-auto-scos-fetch/test.py b/testsuite/tests/S220-058-auto-scos-fetch/test.py new file mode 100644 index 000000000..997196ad3 --- /dev/null +++ b/testsuite/tests/S220-058-auto-scos-fetch/test.py @@ -0,0 +1,45 @@ +""" +Test that "gnatcov coverage" does not fetch ALI/SID files when only loading a +checkpoint (i.e. not processing a trace file). +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.tutils import gprfor, xcov + + +wd = Wdir('tmp_') + +# Generate a checkpoint +ckpt = 'run0.ckpt' +gpr = gprfor(['main.adb'], srcdirs='..') +build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['--save-checkpoint', ckpt], + scos=['obj/main']) + +# Override ALI/SID files with invalid content, so that attempts to load them +# result in errors. +for f in ['obj/main.sid', 'obj/main.ali']: + with open(f, 'w') as f: + f.write('INVALID FILE\n') + +# Use the checkpoint to produce a report. Since there is no trace file to +# process, this should not try to load any ALI/SID file even though the loaded +# project makes them available. +log = 'coverage-ckpt.log' +xcov(['coverage', '--level=stmt', '--annotate=xcov', + '--checkpoint', ckpt, + '-P', gpr, + '--output-dir=.'], + out=log) +log_content = contents_of(log) +thistest.fail_if(log_content, + 'Output of gnatcov not empty:\n{}' + .format(indent(log_content))) + +thistest.result() diff --git a/testsuite/tests/S506-014-mix-providers/main.adb b/testsuite/tests/S506-014-mix-providers/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/S506-014-mix-providers/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/S506-014-mix-providers/test.opt b/testsuite/tests/S506-014-mix-providers/test.opt new file mode 100644 index 000000000..84ed65118 --- /dev/null +++ b/testsuite/tests/S506-014-mix-providers/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Requires support for binary traces diff --git a/testsuite/tests/S506-014-mix-providers/test.py b/testsuite/tests/S506-014-mix-providers/test.py new file mode 100644 index 000000000..82c6fbc85 --- /dev/null +++ b/testsuite/tests/S506-014-mix-providers/test.py @@ -0,0 +1,132 @@ +""" +Check that gnatcov properly warns when a unit is processed both with +instrumentation and regular SCOs. + +Also check that passing both kind of traces is rejected by gnatcov. +""" + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + +import re + + +tmp = Wdir('tmp_') +prj = gprfor(srcdirs=['..'], mains=['main.adb']) + + +def check(tc_name, coverage_args, expected_results, expect_failure): + p = xcov(['coverage', '-P', prj, '-axcov', '-cstmt'] + coverage_args, + out=f"{tc_name}.log", register_failure=not expect_failure) + if expect_failure: + thistest.fail_if(p.status == 0, + "gnatcov did not exit with an error ({tc_name})") + + actual = '\n'.join(line.rstrip() + for line in contents_of(f"{tc_name}.log").splitlines()) + + thistest.fail_if_no_match(f"unexpected gnatcov output ({tc_name})", + regexp=expected_results, + actual=actual) + + +# First, build and run the program in src-traces mode to produce SIDs and a +# source trace. +src_trace = build_and_run( + gprsw=GPRswitches(root_project=prj), + covlevel='stmt', + extra_coverage_args=[], + mains=['main'], + extra_gprbuild_args=['-XBUILD_MODE=src-traces'], + trace_mode='src' +)[-1] + +# Second, build and run the program to produce SCOs (ALIs) and a binary trace +bin_trace = build_and_run( + gprsw=GPRswitches(root_project=prj), + covlevel='stmt', + extra_coverage_args=[], + mains=['main'], + extra_gprbuild_args=['-XBUILD_MODE=bin-traces', + '-cargs', '-g', '-fdump-scos', + '-fpreserve-control-flow'], + trace_mode='bin' +)[-1] + +# We can now try to compute code coverage with both the instrumentation +# checpoint and the compiler SCOs. This requires passing --mix-trace-kind +# to gnatcov to allow mixing trace kinds. + +expected_log = re.escape( + 'warning: Mixing source traces and binary traces is not supported. ' + 'Please only use a single kind of traces.' + '\nwarning: ignoring duplicate SCOs for main.adb (from main.ali)' + '\nwarning: previous SCOs for this unit came from instrumenting main.adb' + '\nwarning: Using option --sid with binary trace files has no effect.' + '\nPlease consider using option --scos or -P in conjunction' + ' with --units to specify units of interest.' + '\nwarning: Using option --scos with source trace files has no effect.' + '\nPlease consider using option --sid or -P in conjunction' + ' with --units to specify units of interest.') + +check("trace_mix", + coverage_args=['--mix-trace-kind', + '--scos', 'obj/main.ali', + '--sid', 'obj/main.sid', + src_trace, bin_trace], + expected_results=expected_log, + expect_failure=False) + +# Check that without --mix-trace-kind, providing traces of different kind +# results in an error. + +check("mix_not_allowed", + coverage_args=['--scos', 'obj/main.ali', + '--sid', 'obj/main.sid', + src_trace, bin_trace], + expected_results=r'.*gnatcov(\.exe)?: Mixing source traces and binary' + r' traces is not supported\. Please only use a single kind of traces\.', + expect_failure=True) + +# Check that using --scos in source trace mode emits a warning. +# Also produce a checkpoint for later testing. + +check("scos_with_src", + coverage_args=['--scos', 'obj/main.ali', '--sid', 'obj/main.sid', + '--save-checkpoint=src.ckpt', + src_trace], + expected_results=re.escape( + 'warning: Using option --scos with source trace files' + ' has no effect.\nPlease consider using option --sid or' + ' -P in conjunction with --units to specify units of' + ' interest.' + ), + expect_failure=False) + +# Check that using --sid with binary traces emits a warning. +# Also produce a checkpoint for later testing. + +check("sid_with_bin", + coverage_args=['--scos', 'obj/main.ali', '--sid', 'obj/main.sid', + '--save-checkpoint=bin.ckpt', + bin_trace], + expected_results=re.escape( + 'warning: Using option --sid with binary trace files' + ' has no effect.\nPlease consider using option --scos or' + ' -P in conjunction with --units to specify units of' + ' interest.' + ), + expect_failure=False) + +# Check that mixing tarce kinds through checkpoints is rejected + +check("mixed_checkpoint", + coverage_args=['-Csrc.ckpt', '-Cbin.ckpt'], + expected_results=r'.*gnatcov(\.exe)?: Mixing source traces and binary' + r' traces is not supported\. Please only use a single kind of traces\.', + expect_failure=True) + + +thistest.result() diff --git a/testsuite/tests/S527-004-ckpt-no-level/main.adb b/testsuite/tests/S527-004-ckpt-no-level/main.adb new file mode 100644 index 000000000..0dff0b39e --- /dev/null +++ b/testsuite/tests/S527-004-ckpt-no-level/main.adb @@ -0,0 +1,8 @@ +procedure Main is + Val : Boolean := True; + pragma Volatile (Val); +begin + if Val then + Val := False; + end if; +end Main; diff --git a/testsuite/tests/S527-004-ckpt-no-level/test.py b/testsuite/tests/S527-004-ckpt-no-level/test.py new file mode 100644 index 000000000..a5e168583 --- /dev/null +++ b/testsuite/tests/S527-004-ckpt-no-level/test.py @@ -0,0 +1,43 @@ +""" +Check the warning message that "gnatcov coverage" emits when a checkpoint is +provided but no coverage level is, and check that we got the expected +statement coverage results. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov, thistest + +tmp = Wdir("tmp_") + +# Create a checkpoint with --level=stmt+decision +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=["main.adb"], srcdirs=[".."]), + ), + extra_coverage_args=["--save-checkpoint=my_checkpoint.ckpt"], + covlevel="stmt+mcdc", + mains=["main"], + trace_mode="src", +) + +# Try to load the checkpoint without specifying the coverage level and +# check the coverage results expecting stmt level coverage. +log_file = "gnatcov.out" +p = xcov( + ["coverage", "--annotate=xcov", "--checkpoint=my_checkpoint.ckpt"], + out=log_file, +) + + +thistest.fail_if_no_match( + what="Missing warning in the gnatcov coverage output", + regexp=r"warning: Coverage level not specified on the command line" + r' or in the project file \(--level=.*\), defaulting to "stmt"\.', + actual=contents_of(log_file), +) + +check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {2, 5, 6}}}) + +thistest.result() diff --git a/testsuite/tests/S529-038-isi-ckpt/main1.adb b/testsuite/tests/S529-038-isi-ckpt/main1.adb new file mode 100644 index 000000000..2a5e24e04 --- /dev/null +++ b/testsuite/tests/S529-038-isi-ckpt/main1.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; + +procedure Main1 is +begin + Ada.Text_IO.Put_Line ("Hello, world!"); +end Main1; diff --git a/testsuite/tests/S529-038-isi-ckpt/main2.adb b/testsuite/tests/S529-038-isi-ckpt/main2.adb new file mode 100644 index 000000000..5f6babf84 --- /dev/null +++ b/testsuite/tests/S529-038-isi-ckpt/main2.adb @@ -0,0 +1,16 @@ +procedure Main2 is + function And_Then (X, Y : Boolean) return Boolean is + begin + if X and then Y then + return True; + else + return False; + end if; + end And_Then; + + Dummy : array (Positive range <>) of Boolean := + (And_Then (False, False), + And_Then (True, True)); +begin + null; +end Main2; diff --git a/testsuite/tests/S529-038-isi-ckpt/test.py b/testsuite/tests/S529-038-isi-ckpt/test.py new file mode 100644 index 000000000..1cf8c73df --- /dev/null +++ b/testsuite/tests/S529-038-isi-ckpt/test.py @@ -0,0 +1,112 @@ +""" +Check that gnatcov processes SID files and consolidation checkpoints as +completely separate concepts. + +In particular: check that it complains when a consolidation checkpoint is +provided where an SID file is expected and conversely, and check that +information in SID files does not "leak" to consolidation checkpoints. +""" + +import re + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, contents_of, indent, lines_of +from SUITE.tutils import gprfor, srctracename_for, xcov + + +tmp = Wdir('tmp_') + + +def main(i): + return 'main{}'.format(i) + + +def sid(i): + return 'i{}.sid'.format(i) + + +def ckpt(i): + return 'c{}.ckpt'.format(i) + + +def trace(i): + return srctracename_for('main{}'.format(i)) + + +def check_error(argv, log_name, expected_error): + p = xcov(argv, out=log_name, register_failure=False) + actual_error = contents_of(log_name).strip() + + expected_re = re.compile( + # Regexp to accommodate output differences between the various + # supported platforms. + '[^\n]*gnatcov[^\n]*: {}'.format(re.escape(expected_error))) + + thistest.fail_if(p.status == 0, + 'gnatcov was expected to fail, it did not') + thistest.fail_if( + not expected_re.match(actual_error), + 'Unexpected output for "gnatcov coverage" ({}). Expected:\n' + '{}\n' + 'but got:\n' + '{}'.format(log_name, + indent(repr(expected_re.pattern)), + indent(actual_error))) + + +gpr = gprfor(['main1.adb', 'main2.adb'], srcdirs='..') + +# Prepare material for the checks: instrument both main1 and main2, produce +# traces and create consolidation checkpoints for them. +for i in (1, 2): + sid_file = 'obj/main{}.sid'.format(i) + build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr, units=[main(i)]), + covlevel='stmt+mcdc', + mains=[main(i)], + extra_coverage_args=[ + '--save-checkpoint', ckpt(i), + '--sid', sid_file], + trace_mode='src') + cp(sid_file, sid(i)) + + +# Check that gnatcov complains when passing a consolidation checkpoint as an +# SID file. +check_error(argv=['coverage', '--annotate=xcov', '--level=stmt+mcdc', + '--sid', ckpt(1), trace(1)], + log_name='ckpt_as_sid.log', + expected_error=('invalid Source Instrumentation Data (SID) file ' + '{}, name of file should have .sid extension' + .format(ckpt(1)))) + +# Check that gnatcov complains when passing an SID file as a consolidation +# checkpoint. +check_error(argv=['coverage', '--level=stmt+mcdc', + '--checkpoint', sid(1), + '--checkpoint', sid(2), + '--save-checkpoint', 'consolidated.ckpt'], + log_name='sid_as_ckpt.log', + expected_error='{} is a Source Instrumentation Data (SID) while a' + ' checkpoint was expected'.format(sid(1))) + + +# Finally, check that information from SID files does not leak into +# checkpoints. This means that one needs to provide an SID file in order to +# decode the corresponding source traces. +# +# Here, even though c1.ckpt was produced while i1.sid was loaded, one must +# provide i1.sid in order to decode main1.srctrace: loading c1.ckpt is not +# enough. +xcov(['coverage', '-v', '--annotate=xcov', '--level=stmt+mcdc', + '--checkpoint', ckpt(1), trace(1)], + out='leak.log') +thistest.fail_if( + 'discarding source trace entry for unknown instrumented unit: body of' + ' main1' not in lines_of('leak.log')) + +thistest.result() diff --git a/testsuite/tests/S603-009-externally-built/main/main.adb b/testsuite/tests/S603-009-externally-built/main/main.adb new file mode 100644 index 000000000..52965a61f --- /dev/null +++ b/testsuite/tests/S603-009-externally-built/main/main.adb @@ -0,0 +1,7 @@ +with Mylib; + +procedure Main is + Dummy : Natural := Mylib.Fact (1); +begin + null; +end Main; diff --git a/testsuite/tests/S603-009-externally-built/main/main.gpr b/testsuite/tests/S603-009-externally-built/main/main.gpr new file mode 100644 index 000000000..e6fc16ab5 --- /dev/null +++ b/testsuite/tests/S603-009-externally-built/main/main.gpr @@ -0,0 +1,6 @@ +with "mylib"; + +project Main is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end Main; diff --git a/testsuite/tests/S603-009-externally-built/mylib/mylib.adb b/testsuite/tests/S603-009-externally-built/mylib/mylib.adb new file mode 100644 index 000000000..608652d6e --- /dev/null +++ b/testsuite/tests/S603-009-externally-built/mylib/mylib.adb @@ -0,0 +1,12 @@ +package body Mylib is + + function Fact (N : Natural) return Natural is + begin + if N < 2 then + return N; + else + return N * Fact (N - 1); + end if; + end Fact; + +end Mylib; diff --git a/testsuite/tests/S603-009-externally-built/mylib/mylib.ads b/testsuite/tests/S603-009-externally-built/mylib/mylib.ads new file mode 100644 index 000000000..e1c518f78 --- /dev/null +++ b/testsuite/tests/S603-009-externally-built/mylib/mylib.ads @@ -0,0 +1,3 @@ +package Mylib is + function Fact (N : Natural) return Natural; +end Mylib; diff --git a/testsuite/tests/S603-009-externally-built/mylib/mylib.gpr b/testsuite/tests/S603-009-externally-built/mylib/mylib.gpr new file mode 100644 index 000000000..46809fb8d --- /dev/null +++ b/testsuite/tests/S603-009-externally-built/mylib/mylib.gpr @@ -0,0 +1,5 @@ +library project Mylib is + for Library_Name use "mylib"; + for Library_Dir use "lib"; + for Object_Dir use "obj"; +end Mylib; diff --git a/testsuite/tests/S603-009-externally-built/test.opt b/testsuite/tests/S603-009-externally-built/test.opt new file mode 100644 index 000000000..4bb4b05b9 --- /dev/null +++ b/testsuite/tests/S603-009-externally-built/test.opt @@ -0,0 +1,8 @@ +src-traces +native +ALL DEAD +-- gnatls -v output does not reflect GPR_PROJECT_PATH modifications (with +-- GNAT5.04a1), and GNATcoll.projects uses it to compute environment +-- information. This should be fixed when transitioning to libgpr2. +5.04a1 XFAIL Incompatibility between gnatls and GNATCOLL.Projects +src-traces XFAIL Pending resolution of gprinstall bug in V923-009 \ No newline at end of file diff --git a/testsuite/tests/S603-009-externally-built/test.py b/testsuite/tests/S603-009-externally-built/test.py new file mode 100644 index 000000000..0489d950c --- /dev/null +++ b/testsuite/tests/S603-009-externally-built/test.py @@ -0,0 +1,142 @@ +""" +Check that GNATcoverage does not process externally built projects, unless +--externally-built-projects is passed. +""" + +import os.path +import re +import shutil + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprbuild, gprinstall, xcov + + +mylib_gpr = os.path.abspath(os.path.join('mylib', 'mylib.gpr')) +mylib_obj_dir = os.path.abspath(os.path.join('mylib', 'obj')) +main_dir = os.path.abspath('main') +main_gpr = os.path.join(main_dir, 'main.gpr') +main_obj_dir = os.path.join(main_dir, 'obj') + +# Create the installation directory and add it to gprbuild's project lookup +# path. +tmp = Wdir('tmp_') +install_dir = os.path.abspath('install') +gpr_install_dir = os.path.join(install_dir, 'share', 'gpr') +installed_mylib_gpr = os.path.join(gpr_install_dir, 'mylib.gpr') +os.mkdir(install_dir) + +old_path = os.environ.get('GPR_PROJECT_PATH', '') +if old_path: + new_path = '{}{}{}'.format(gpr_install_dir, os.path.pathsep, old_path) +else: + new_path = gpr_install_dir +os.environ['GPR_PROJECT_PATH'] = new_path + +# Build and install the library project +if thistest.options.trace_mode == 'src': + xcov_instrument( + gprsw=GPRswitches(root_project=mylib_gpr), + covlevel='stmt', + gpr_obj_dir=mylib_obj_dir + ) +gprbuild(mylib_gpr) + +if thistest.options.trace_mode == 'src': + gprinstall( + mylib_gpr, + [ + f'--prefix={install_dir}', + '--src-subdirs=gnatcov-instr', + '--implicit-with=gnatcov_rts' + ] + ) +else: + gprinstall(mylib_gpr, f'--prefix={install_dir}') + +# Build the main project using this and run it to produce a trace file +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=main_gpr, externally_built_projects=True), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov'], + gpr_obj_dir=main_obj_dir, + gpr_exe_dir=main_obj_dir, + gprsw_for_coverage=False +) +trace_file = xcov_args[-1] + +# Check that the instrumenter hasn't tried to instrument the installed project +thistest.fail_if( + os.path.exists(os.path.join(install_dir, + 'share', 'gpr', 'mylib-gnatcov-instr')), + '"gnatcov instrument" instrumented the installed project' +) + +output_dir = 'xcov-report' +gnatcov_log = 'gnatcov.log' + + +def check_coverage(project, externally_built, expected_cov, + register_failure=True): + if os.path.isdir(output_dir): + shutil.rmtree(output_dir) + os.mkdir(output_dir) + + args = ['coverage', '-cstmt', '-axcov', '-P', project, + '--output-dir', output_dir, trace_file] + if externally_built: + args.append('--externally-built-projects') + p = xcov(args, out=gnatcov_log, register_failure=register_failure) + + if not register_failure: + return p + + check_xcov_reports(os.path.join(output_dir, '*.xcov'), expected_cov) + + +# First, make sure that "gnatcov coverage" on an externally built project +# returns an error. +p = check_coverage( + project=installed_mylib_gpr, externally_built=False, expected_cov=None, + register_failure=False) +thistest.fail_if( + p.status == 0, + 'gnatcov was supposed to complain when provided an externally built' + ' project') +coverage_log = contents_of(gnatcov_log).strip() +expected_log = re.compile( + # Regexp to accommodate output differences between the various + # supported platforms. + '[^\n]*gnatcov[^\n]*: {}'.format(re.escape( + 'Root project is marked as externally built, while externally built' + ' projects are ignored by default. Consider using' + ' --externally-built-projects.'))) +thistest.fail_if(not expected_log.match(coverage_log), + 'Unexpected output for "gnatcov coverage". Expected:\n' + '{}\n' + 'but got:\n' + '{}'.format(indent(expected_log.pattern), + indent(coverage_log))) + +# It should not complain with --externally-built-projects +p = check_coverage( + project='mylib.gpr', externally_built=True, + expected_cov={os.path.join(output_dir, 'mylib.adb.xcov'): {'+': {5, 6}, + '-': {8}}}) + +# Make sure coverage computation gives the expected result with and without +# --externally-built-projects +check_coverage( + project=main_gpr, externally_built=False, + expected_cov={os.path.join(output_dir, 'main.adb.xcov'): {'+': {4, 6}}}) +check_coverage( + project=main_gpr, externally_built=True, + expected_cov={os.path.join(output_dir, 'main.adb.xcov'): {'+': {4, 6}}, + os.path.join(output_dir, 'mylib.adb.xcov'): {'+': {5, 6}, + '-': {8}}}) + +thistest.result() diff --git a/testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.adb b/testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.adb new file mode 100644 index 000000000..b0dc586ab --- /dev/null +++ b/testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; + +procedure Generic_Hello is +begin + Ada.Text_IO.Put_Line ("Hello " & Who & "!"); +end Generic_Hello; diff --git a/testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.ads b/testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.ads new file mode 100644 index 000000000..4645e28d6 --- /dev/null +++ b/testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.ads @@ -0,0 +1,3 @@ +generic + Who : String; +procedure Generic_Hello; diff --git a/testsuite/tests/S619-014-tag-provider-mismatch/main.adb b/testsuite/tests/S619-014-tag-provider-mismatch/main.adb new file mode 100644 index 000000000..d832a4a2b --- /dev/null +++ b/testsuite/tests/S619-014-tag-provider-mismatch/main.adb @@ -0,0 +1,13 @@ +with Generic_Hello; + +procedure Main is + procedure Hello_World is new Generic_Hello ("world"); + procedure Hello_There is new Generic_Hello ("there"); + + S : constant String := "hello"; +begin + Hello_World; + if S = "never-going-to-be-true" then + Hello_There; + end if; +end Main; diff --git a/testsuite/tests/S619-014-tag-provider-mismatch/test.py b/testsuite/tests/S619-014-tag-provider-mismatch/test.py new file mode 100644 index 000000000..22add3160 --- /dev/null +++ b/testsuite/tests/S619-014-tag-provider-mismatch/test.py @@ -0,0 +1,43 @@ +""" +Check that "gnatcov coverage" complains when loading a checkpoint created with +a different tag provider, i.e. asking for inconsistent separate coverage. Also +check that the coverage report correctly disregards coverage data from the +loaded checkpoint. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +wd = Wdir('tmp_') + +# First, create a checkpoint using the default tag provider +ckpt = 'c.ckpt' +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(['main.adb'], srcdirs='..')), + covlevel='stmt+decision', + mains=['main'], + extra_coverage_args=['--save-checkpoint', ckpt]) + +# Now try to load it while asking for the non-default tag provider. Don't pass +# the trace file, as we are interested only in checkpoint processing. +xcov(['coverage', '-cstmt+decision', '-axcov', '-Sinstance', '-C', ckpt, + '--output-dir=.'], + out='consolidate.log') + +expected = ('warning: cannot merge coverage information from {} as it is' + ' separated by default'.format(ckpt)) +actual = contents_of('consolidate.log').strip() +thistest.fail_if(expected != actual, + 'Unexpected output for "gnatcov coverage". Expected:\n' + '{}\n' + 'but got:\n' + '{}'.format(indent(expected), indent(actual))) + +check_xcov_reports('*.xcov', {'main.adb.xcov': {}, + 'generic_hello.adb.xcov': {}}) + +thistest.result() diff --git a/testsuite/tests/S621-026-mcdc-ckpt/main1.adb b/testsuite/tests/S621-026-mcdc-ckpt/main1.adb new file mode 100644 index 000000000..2a5e24e04 --- /dev/null +++ b/testsuite/tests/S621-026-mcdc-ckpt/main1.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; + +procedure Main1 is +begin + Ada.Text_IO.Put_Line ("Hello, world!"); +end Main1; diff --git a/testsuite/tests/S621-026-mcdc-ckpt/main2.adb b/testsuite/tests/S621-026-mcdc-ckpt/main2.adb new file mode 100644 index 000000000..5f6babf84 --- /dev/null +++ b/testsuite/tests/S621-026-mcdc-ckpt/main2.adb @@ -0,0 +1,16 @@ +procedure Main2 is + function And_Then (X, Y : Boolean) return Boolean is + begin + if X and then Y then + return True; + else + return False; + end if; + end And_Then; + + Dummy : array (Positive range <>) of Boolean := + (And_Then (False, False), + And_Then (True, True)); +begin + null; +end Main2; diff --git a/testsuite/tests/S621-026-mcdc-ckpt/test.py b/testsuite/tests/S621-026-mcdc-ckpt/test.py new file mode 100644 index 000000000..dadf1fc98 --- /dev/null +++ b/testsuite/tests/S621-026-mcdc-ckpt/test.py @@ -0,0 +1,33 @@ +"""Regression testcase for the use of checkpoints and MC/DC coverage.""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov + + +tmp = Wdir('tmp_') + +gpr = gprfor(['main1.adb', 'main2.adb'], srcdirs='..') + +# Create a checkpoint for the execution of "main1" and another for "main2" +for i in (1, 2): + build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + covlevel='stmt+mcdc', + mains=['main{}'.format(i)], + extra_coverage_args=['--save-checkpoint=c{}.ckpt'.format(i)], + scos=['obj/main{}'.format(i)]) + +# Now consolidate both. c1.ckpt comes first in order to check that, when +# c2.ckpt is loaded, all SCOs in it, and in particular the ones in evaluation +# vectors for MC/DC, are properly remapped. +xcov(['coverage', '--annotate=xcov', '--level=stmt+mcdc', + '--checkpoint=c1.ckpt', '--checkpoint=c2.ckpt']) + +check_xcov_reports('*.xcov', { + 'main1.adb.xcov': {'+': {5}}, + 'main2.adb.xcov': {'+': {5, 7, 11, 12, 13, 15}, '!': {4}}}) + +thistest.result() diff --git a/testsuite/tests/S820-013-ckpt-dup-scos/bar.h b/testsuite/tests/S820-013-ckpt-dup-scos/bar.h new file mode 100644 index 000000000..20dba0330 --- /dev/null +++ b/testsuite/tests/S820-013-ckpt-dup-scos/bar.h @@ -0,0 +1,8 @@ +static inline int +fact (int n) +{ + if (n > 1) + return n * fact (n - 1); + else + return n; +} diff --git a/testsuite/tests/S820-013-ckpt-dup-scos/foo.c b/testsuite/tests/S820-013-ckpt-dup-scos/foo.c new file mode 100644 index 000000000..7f3505691 --- /dev/null +++ b/testsuite/tests/S820-013-ckpt-dup-scos/foo.c @@ -0,0 +1,7 @@ +#include "bar.h" + +int +foo (int n) +{ + return n + fact (n); +} diff --git a/testsuite/tests/S820-013-ckpt-dup-scos/main.c b/testsuite/tests/S820-013-ckpt-dup-scos/main.c new file mode 100644 index 000000000..2d4164717 --- /dev/null +++ b/testsuite/tests/S820-013-ckpt-dup-scos/main.c @@ -0,0 +1,11 @@ +#include "bar.h" + +extern int foo (int); + +int +main (void) +{ + int n = fact (3); + foo (fact (3)); + return 0; +} diff --git a/testsuite/tests/S820-013-ckpt-dup-scos/test.opt b/testsuite/tests/S820-013-ckpt-dup-scos/test.opt new file mode 100644 index 000000000..7ba7cedac --- /dev/null +++ b/testsuite/tests/S820-013-ckpt-dup-scos/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test involves C units diff --git a/testsuite/tests/S820-013-ckpt-dup-scos/test.py b/testsuite/tests/S820-013-ckpt-dup-scos/test.py new file mode 100644 index 000000000..312151534 --- /dev/null +++ b/testsuite/tests/S820-013-ckpt-dup-scos/test.py @@ -0,0 +1,32 @@ +""" +Test that checkpoints consolidation does not crash in the presence of "null" +SCOs, i.e. duplicated SCOs removed from the SCO vector in +Process_Low_Level_SCOs. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, + xrun) + + +wd = Wdir('tmp_') + +exe = exepath_to('main') +trace = tracename_for('main') +gpr = gprfor(['main.c'], srcdirs='..') + +# Build the test program and generate a trace file +gprbuild(gpr) +xrun([exe]) + +# Load the duplicated ALIs and create a checkpoint +ckpt = 'c.ckpt' +xcov(['coverage', '-c', 'stmt', '--save-checkpoint', ckpt, + '--scos=obj/main.c.gli', '--scos=obj/foo.c.gli', + trace]) + +# Now try to generate a report from this checkpoint +xcov(['coverage', '-a', 'xcov', '-c', 'stmt', '--checkpoint', ckpt]) + +thistest.result() diff --git a/testsuite/tests/SB06-033-homonyms/.gitignore b/testsuite/tests/SB06-033-homonyms/.gitignore new file mode 100644 index 000000000..ca5215678 --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/.gitignore @@ -0,0 +1,2 @@ +*.trace +install diff --git a/testsuite/tests/SB06-033-homonyms/app/default.gpr b/testsuite/tests/SB06-033-homonyms/app/default.gpr new file mode 100644 index 000000000..08e41a7d5 --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/app/default.gpr @@ -0,0 +1,8 @@ +with "../libfoo/install/gpr/libfoo.gpr"; +project Default is + for Main use ("main.adb"); + for Object_Dir use "obj"; + package Compiler is + for Switches ("Ada") use ("-g", "-fpreserve-control-flow", "-fdump-scos"); + end Compiler; +end Default; diff --git a/testsuite/tests/SB06-033-homonyms/app/main.adb b/testsuite/tests/SB06-033-homonyms/app/main.adb new file mode 100644 index 000000000..e7f57c6ce --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/app/main.adb @@ -0,0 +1,7 @@ +with Lib; + +procedure Main is + Dummy : constant Integer := Lib.Next (Lib.First); +begin + null; +end; diff --git a/testsuite/tests/SB06-033-homonyms/libfoo/lib.adb b/testsuite/tests/SB06-033-homonyms/libfoo/lib.adb new file mode 100644 index 000000000..ab47e2689 --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/libfoo/lib.adb @@ -0,0 +1,4 @@ +package body Lib is + function First return Integer is (1); + function Next (I : Integer) return Integer is (I + 1); +end; diff --git a/testsuite/tests/SB06-033-homonyms/libfoo/lib.ads b/testsuite/tests/SB06-033-homonyms/libfoo/lib.ads new file mode 100644 index 000000000..d37d29aeb --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/libfoo/lib.ads @@ -0,0 +1,13 @@ +package Lib is + function First return Integer; + function Next (I : Integer) return Integer + with Inline_Always; + -- Always inlining this function is necessary to introduce code that + -- references installed source files (i.e. stub files from gnatcov's point + -- of view) for lib.adb into the _ada_main symbol (i.e. a routine analyzed + -- for source coverage, from main.adb). + -- + -- This makes "gnatcov coverage" try to get line info for this inlined + -- code, i.e. get line info on a stub file, which used to make gnatcov fail + -- on a precondition. +end; diff --git a/testsuite/tests/SB06-033-homonyms/libfoo/libfoo.gpr b/testsuite/tests/SB06-033-homonyms/libfoo/libfoo.gpr new file mode 100644 index 000000000..e87f208cb --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/libfoo/libfoo.gpr @@ -0,0 +1,11 @@ +library project Libfoo is + for Library_Kind use "static"; + for Library_Name use "foo"; + for Object_Dir use "obj"; + for Library_Dir use "lib"; + + package Compiler is + for Switches ("Ada") use + ("-g", "-O0", "-fpreserve-control-flow", "-fdump-scos"); + end Compiler; +end Libfoo; diff --git a/testsuite/tests/SB06-033-homonyms/test.opt b/testsuite/tests/SB06-033-homonyms/test.opt new file mode 100644 index 000000000..a22f4846b --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/test.opt @@ -0,0 +1,5 @@ +-- This test checks the processing of gnatcov on externally built projects, +-- which is supported only on native targets and with binary traces. +!native DEAD +!linux DEAD +src-traces DEAD S918-031: src-traces and externally built projects diff --git a/testsuite/tests/SB06-033-homonyms/test.py b/testsuite/tests/SB06-033-homonyms/test.py new file mode 100644 index 000000000..e657d792e --- /dev/null +++ b/testsuite/tests/SB06-033-homonyms/test.py @@ -0,0 +1,74 @@ +""" +Check that "gnatcov coverage" does not crash when processing a program that +exposes two paths for the same source (once before and one after installation). + +Note that in this testcase, both absolute paths come from debug info line +mapping (.debug_lines). +""" + +import os + +from e3.fs import rm +from e3.os.process import Run + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of + + +wd = Wdir('tmp_') +log_dir = os.getcwd() +wd.to_homedir() + + +def in_home(*args): + return os.path.join(wd.homedir, *args) + + +def try_run(cmd, out_file): + out_file = os.path.join(log_dir, out_file) + p = Run(cmd, output=out_file) + out = contents_of(out_file) + thistest.fail_if( + p.status != 0, + 'Unexpected failure.\n' + 'Command was:\n' + '%s\n' + 'Output was:\n' + '%s' % (' '.join(cmd), out)) + return out + + +os.chdir(in_home('libfoo')) +rm('install', recursive=True) + +try_run(['gprbuild', '-f', '-Plibfoo.gpr', '-p'], 'gprbuild-libfoo.txt') +try_run(['gprinstall', '-f', '-Plibfoo.gpr', '-p', + '--prefix=install', '--project-subdir=gpr'], + 'gprinstall.txt') + +os.chdir(in_home('app')) + +try_run(['gprbuild', '-f', '-Pdefault.gpr', '-p'], 'gprbuild-app.txt') +try_run(['gnatcov', 'run', 'obj/main'], 'gnatcov-run.txt') + +# The very goal of this testcase is to compute code coverage for a unit that +# belongs to a project installed with gprinstall, so we need to enable the +# processing of externally built projects. +log_file = 'gnatcov-coverage.txt' +log = try_run(['gnatcov', 'coverage', + '--annotate=xcov', + '--level=stmt', + '-Pdefault', '--externally-built-projects', + 'main.trace'], log_file) +thistest.fail_if_no_match( + '"gnatcov output" ({})'.format(log_file), + 'Warning: same base name for files:' + '\r?\n [^\n]+{}' + '\r?\n [^\n]+{}' + .format(os.path.join('SB06-033-homonyms', 'libfoo', 'install', 'include', + 'libfoo', 'lib.adb'), + os.path.join('SB06-033-homonyms', 'libfoo', 'lib.adb')), + log +) + +thistest.result() diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/engines.adb b/testsuite/tests/SanityCheck/decision/Engines/src/engines.adb new file mode 100644 index 000000000..5ef8c9cad --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/src/engines.adb @@ -0,0 +1,33 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +package body Engines is + + ------------ + -- Stable -- + ------------ + + function Stable (E : Engine) return Boolean is + begin + if E.P < Stable_P and then E.T < Stable_T then -- # eval + return True; -- # true + end if; + return False; -- # false + end Stable; +end Engines; diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/engines.ads b/testsuite/tests/SanityCheck/decision/Engines/src/engines.ads new file mode 100644 index 000000000..e5e8a5c0b --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/src/engines.ads @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +-- This package exposes a very basic and incomplete Engine abstraction + +package Engines is + + -- The Engine abstraction per se + + type Engine is record + P, T : Integer; -- Internal state: Pressure & Temperature + end record; + + -- Pressure and Temperature thresholds wrt engine stability + + Stable_P : constant := 10; + Stable_T : constant := 50; + + function Stable (E : Engine) return Boolean; + -- Whether the engine E is stable, iff both Pressure and Temperature + -- are below the stability threshold. + +end Engines; diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_both.adb b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_both.adb new file mode 100644 index 000000000..36970e5de --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_both.adb @@ -0,0 +1,38 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; +with Support; use Support; + +procedure Test_Engines_Both is + E : Engine; +begin + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); + + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); +end Test_Engines_Both; + +--# engines.adb +-- /eval/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_null.adb b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_null.adb new file mode 100644 index 000000000..dcd8fb752 --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_null.adb @@ -0,0 +1,34 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; +with Support; use Support; + +procedure Test_Engines_Null is + E : Engine; + pragma Unreferenced (E); +begin + Assert (True); +end Test_Engines_Null; + +--# engines.adb +-- /eval/ l- ## s- +-- /true/ l- ## s- +-- /false/ l- ## s- + diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_stable.adb b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_stable.adb new file mode 100644 index 000000000..31f0e574e --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_stable.adb @@ -0,0 +1,35 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; +with Support; use Support; + +procedure Test_Engines_Stable is + E : Engine; +begin + E.T := Stable_T - 1; + E.P := Stable_P - 1; + Assert (Stable (E)); +end Test_Engines_Stable; + +--# engines.adb +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /false/ l- ## s- + diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_unstable.adb b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_unstable.adb new file mode 100644 index 000000000..d78f01a20 --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_unstable.adb @@ -0,0 +1,35 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2009, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with Engines; use Engines; +with Support; use Support; + +procedure Test_Engines_Unstable is + E : Engine; +begin + E.T := Stable_T + 1; + E.P := Stable_P + 1; + Assert (not Stable (E)); +end Test_Engines_Unstable; + +--# engines.adb +-- /eval/ l! ## dT- +-- /true/ l- ## s- +-- /false/ l+ ## 0 + diff --git a/testsuite/tests/SanityCheck/decision/Engines/test.py b/testsuite/tests/SanityCheck/decision/Engines/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/SanityCheck/decision/Engines/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/T117-007-intf-thunks/src/action.ads b/testsuite/tests/T117-007-intf-thunks/src/action.ads new file mode 100644 index 000000000..1c21b6ec7 --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/src/action.ads @@ -0,0 +1,14 @@ +package Action is + + type T_Action is abstract tagged private; + + type T_NA_Action_Class is not null access all T_Action'Class; + + procedure Init (Obj : in out T_Action) is abstract; + + procedure Run (Obj : in out T_Action) is abstract; + +private + type T_Action is abstract tagged null record; + +end Action; diff --git a/testsuite/tests/T117-007-intf-thunks/src/interface_a.ads b/testsuite/tests/T117-007-intf-thunks/src/interface_a.ads new file mode 100644 index 000000000..99aa47802 --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/src/interface_a.ads @@ -0,0 +1,9 @@ +package Interface_A is + + type T_Interface_A is interface; + + function Get_Variable (This : in T_Interface_A) return Integer is abstract; + + type T_A_Interface_A_Class is access all T_Interface_A'Class; + +end Interface_A; diff --git a/testsuite/tests/T117-007-intf-thunks/src/package_a.adb b/testsuite/tests/T117-007-intf-thunks/src/package_a.adb new file mode 100644 index 000000000..9352c3393 --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/src/package_a.adb @@ -0,0 +1,24 @@ +pragma Ada_2012; +package body Package_A is + + The_Instance : aliased T_A; + + NA_Intance : T_NA_A := The_Instance'Access; + + function NA_A return T_NA_A is (NA_Intance); + + overriding procedure Init (Obj : in out T_A) + is + begin + Obj.Variable := 15; + end Init; + + overriding procedure Run (Obj : in out T_A) + is + begin + Obj.Enumeration := DEF; + end Run; + + overriding function Get_Variable (Obj : in T_A) return Integer is (1); + +end Package_A; diff --git a/testsuite/tests/T117-007-intf-thunks/src/package_a.ads b/testsuite/tests/T117-007-intf-thunks/src/package_a.ads new file mode 100644 index 000000000..c7a43d209 --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/src/package_a.ads @@ -0,0 +1,33 @@ +pragma Ada_2012; +with Action; +with Interface_A; + + +package Package_A is + + type T_A is new Action.T_Action + and Interface_A.T_Interface_A + with private; -- Statement on the line was not executed + + type T_NA_A is not null access all T_A; -- Statement on the line was not executed + + function NA_A return T_NA_A; + + overriding procedure Init (Obj : in out T_A); + + overriding procedure Run (Obj : in out T_A); + + overriding function Get_Variable (Obj : in T_A) return Integer; + + type Enum is (ABC, DEF); -- Statement on the line was not executed + +private + + type T_A is new Action.T_Action -- Statement on the line was not executed + and Interface_A.T_Interface_A + with record + Variable : Integer; + Enumeration : Enum; + end record; + +end Package_A; diff --git a/testsuite/tests/T117-007-intf-thunks/src/ut_main.adb b/testsuite/tests/T117-007-intf-thunks/src/ut_main.adb new file mode 100644 index 000000000..73c843c6a --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/src/ut_main.adb @@ -0,0 +1,18 @@ + +with Package_A; + +procedure Ut_Main is + + Instance : aliased Package_A.T_A; + + A_Instance : Package_A.T_NA_A := Package_A.NA_A; + + returnValue : Integer; + +begin + + Instance.Init; + Instance.Run; + returnValue := Instance.Get_Variable; + +end Ut_Main; diff --git a/testsuite/tests/T117-007-intf-thunks/test.opt b/testsuite/tests/T117-007-intf-thunks/test.opt new file mode 100644 index 000000000..a4e1eba80 --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/T117-007-intf-thunks/test.py b/testsuite/tests/T117-007-intf-thunks/test.py new file mode 100644 index 000000000..b053c1eca --- /dev/null +++ b/testsuite/tests/T117-007-intf-thunks/test.py @@ -0,0 +1,24 @@ +import re + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + + +tmp_ = Wdir('tmp_') + +gpr = gprfor(srcdirs='../src', mains=['ut_main.adb']) +build_run_and_coverage(gprsw=GPRswitches(root_project=gpr), + covlevel='stmt', mains=['ut_main'], + extra_coverage_args=['--annotate=xcov']) + +# We do not expect uncovered lines in package_a, as the code generated +# for the interface type declaration is thunk code, which is to be +# ignored for coverage purposes. + +report_package_a = contents_of('obj/package_a.ads.xcov') +thistest.fail_if(re.search(string=report_package_a, pattern=r'-:'), + "unexpected uncovered code") + +thistest.result() diff --git a/testsuite/tests/T319-018-if-expr/src/pkg.adb b/testsuite/tests/T319-018-if-expr/src/pkg.adb new file mode 100644 index 000000000..595e445f3 --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/pkg.adb @@ -0,0 +1,26 @@ +package body Pkg is + + function Null_Out_Data_Port return Out_Data_Port'Class is + begin + return Out_Data_Port'Class (Simple_Out_Data_Port'(null record)); + end Null_Out_Data_Port; + + overriding function Image (Out_P : Simple_Out_Data_Port) return String is + begin + return "foo"; + end Image; + + overriding function Incoming_Signal + (I : Simple_In_Data_Port) return Signal'Class + is + begin + return Signal'Class + (Simple_Signal'(Is_Null => I.Incoming_Signal_Is_Null)); + end Incoming_Signal; + + function Src_Port (S : Simple_Signal) return Out_Port'Class is + begin + return Out_Port'Class (Simple_Out_Data_Port'(null record)); + end Src_Port; + +end Pkg; diff --git a/testsuite/tests/T319-018-if-expr/src/pkg.ads b/testsuite/tests/T319-018-if-expr/src/pkg.ads new file mode 100644 index 000000000..46593d9fa --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/pkg.ads @@ -0,0 +1,44 @@ +pragma Ada_2012; + +package Pkg is + + ----------------- + -- Interfaces -- + ----------------- + + type Signal; + + type Out_Port is interface; + type Out_Data_Port is interface and Out_Port; + function Image (Out_P : Out_Data_Port) return String is abstract; + + type In_Port is interface; + function Incoming_Signal (I : In_Port) return Signal'Class is abstract; + + type In_Data_Port is interface and In_Port; + + type Signal is interface; + function Is_Not_Null (S : Signal) return Boolean is abstract; + function Src_Port (S : Signal) return Out_Port'Class is abstract; + + function Null_Out_Data_Port return Out_Data_Port'Class; + + --------------------- + -- Implementations -- + --------------------- + + type Simple_Out_Data_Port is new Out_Data_Port with null record; + overriding function Image (Out_P : Simple_Out_Data_Port) return String; + + type Simple_In_Data_Port is new In_Data_Port with record + Incoming_Signal_Is_Null : Boolean; + end record; + overriding function Incoming_Signal + (I : Simple_In_Data_Port) return Signal'Class; + + type Simple_Signal is new Signal with record + Is_Null : Boolean; + end record; + function Is_Not_Null (S : Simple_Signal) return Boolean is (not S.Is_Null); + function Src_Port (S : Simple_Signal) return Out_Port'Class; +end Pkg; diff --git a/testsuite/tests/T319-018-if-expr/src/proc.adb b/testsuite/tests/T319-018-if-expr/src/proc.adb new file mode 100644 index 000000000..3ff792f97 --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/proc.adb @@ -0,0 +1,14 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Proc (In_P : In_Data_Port'Class) +is + Orig_Out_P : constant Out_Data_Port'Class := -- # uncond + (if In_P.Incoming_Signal.Is_Not_Null -- # decision + then Out_Data_Port'Class (In_P.Incoming_Signal.Src_Port) -- # out-true + else Null_Out_Data_Port); -- # out-false +begin + Put_Line (Orig_Out_P.Image); -- # uncond +end Proc; diff --git a/testsuite/tests/T319-018-if-expr/src/test_all.adb b/testsuite/tests/T319-018-if-expr/src/test_all.adb new file mode 100644 index 000000000..5041edc19 --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/test_all.adb @@ -0,0 +1,14 @@ +with Pkg; use Pkg; +with Proc; + +procedure Test_All is +begin + Proc (Simple_In_Data_Port'(Incoming_Signal_Is_Null => False)); + Proc (Simple_In_Data_Port'(Incoming_Signal_Is_Null => True)); +end Test_All; + +--# proc.adb +-- /uncond/ l+ ## 0 +-- /decision/ l+ ## 0 +-- /out-true/ l+ ## 0 +-- /out-false/ l+ ## 0 diff --git a/testsuite/tests/T319-018-if-expr/src/test_false.adb b/testsuite/tests/T319-018-if-expr/src/test_false.adb new file mode 100644 index 000000000..660214eaa --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/test_false.adb @@ -0,0 +1,16 @@ +with Pkg; use Pkg; +with Proc; + +procedure Test_False is +begin + Proc (Simple_In_Data_Port'(Incoming_Signal_Is_Null => False)); +end Test_False; + +--# proc.adb +-- /uncond/ l+ ## 0 +-- /decision/ l! ## d! +-- /out-true/ l+ ## 0 +-- /out-false/ l+ ## 0 +-- +-- %opts: --trace-mode=src +-- =/decision/ l! ## dF- diff --git a/testsuite/tests/T319-018-if-expr/src/test_no.adb b/testsuite/tests/T319-018-if-expr/src/test_no.adb new file mode 100644 index 000000000..e04a61546 --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/test_no.adb @@ -0,0 +1,15 @@ +with Pkg; use Pkg; +with Proc; + +procedure Test_No is +begin + if Null_Out_Data_Port.Image = "" then + Proc (Simple_In_Data_Port'(Incoming_Signal_Is_Null => False)); + end if; +end Test_No; + +--# proc.adb +-- /uncond/ l- ## s- +-- /decision/ l- ## 0 +-- /out-true/ l- ## 0 +-- /out-false/ l- ## 0 diff --git a/testsuite/tests/T319-018-if-expr/src/test_true.adb b/testsuite/tests/T319-018-if-expr/src/test_true.adb new file mode 100644 index 000000000..ba491cc03 --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/src/test_true.adb @@ -0,0 +1,16 @@ +with Pkg; use Pkg; +with Proc; + +procedure Test_True is +begin + Proc (Simple_In_Data_Port'(Incoming_Signal_Is_Null => True)); +end Test_True; + +--# proc.adb +-- /uncond/ l+ ## 0 +-- /decision/ l! ## d! +-- /out-true/ l+ ## 0 +-- /out-false/ l+ ## 0 +-- +-- %opts: --trace-mode=src +-- =/decision/ l! ## dT- diff --git a/testsuite/tests/T319-018-if-expr/test.opt b/testsuite/tests/T319-018-if-expr/test.opt new file mode 100644 index 000000000..135a50b26 --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/test.opt @@ -0,0 +1,2 @@ +RTS_ZFP DEAD Test requires dynamic interface conversions +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/T319-018-if-expr/test.py b/testsuite/tests/T319-018-if-expr/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/T319-018-if-expr/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/T331-043-native-warn/main.adb b/testsuite/tests/T331-043-native-warn/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/T331-043-native-warn/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/T331-043-native-warn/test.py b/testsuite/tests/T331-043-native-warn/test.py new file mode 100644 index 000000000..2843966da --- /dev/null +++ b/testsuite/tests/T331-043-native-warn/test.py @@ -0,0 +1,53 @@ +"""Check that "gnatcov run" warns when running a native program.""" + +import os + +from e3.env import Env + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + + +tmp = Wdir('tmp') + + +# The testsuite automatically disables the warning we want to test: override +# this decision just for this testcase. +os.environ.pop('GNATCOV_NO_NATIVE_WARNING', None) + +is_native = not Env().is_cross +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.adb'])), + covlevel='stmt', + mains=['main'], + extra_coverage_args=["-axcov"]) + + +warning_exceprt = ( + 'Support for coverage of non-instrumented native programs is deprecated' +) + + +def check_warning_absent(logfile): + thistest.fail_if(warning_exceprt in contents_of(logfile), + "unexpected warning in {}".format(logfile)) + + +def check_warning_present(logfile): + thistest.fail_if(warning_exceprt not in contents_of(logfile), + "missing warning in {}".format(logfile)) + + +# Depending on the trace mode and the target, check the presence/absence of the +# warning. +if thistest.options.trace_mode == 'src': + check_warning_absent('instrument.log') +elif is_native: + check_warning_present('main_output.txt') +else: + check_warning_absent('main_output.txt') +check_warning_absent('coverage.log') + +thistest.result() diff --git a/testsuite/tests/T520-035-exit-when/src/parser.adb b/testsuite/tests/T520-035-exit-when/src/parser.adb new file mode 100644 index 000000000..206338c1a --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/parser.adb @@ -0,0 +1,29 @@ +package body Parser is + + procedure Skip_Line_Sep is null; + procedure Append is null; -- # append + + procedure Parse_Array (T : Toks) is + TI : Natural := T'First; + + function Scan_Tok return Tok is + Result : Tok := T (TI); + begin + TI := TI + 1; + return Result; + end Scan_Tok; + + begin + loop + -- Skip ';' or EOL + Skip_Line_Sep; -- # stmt + + -- If ']' is alone on its line + exit when Scan_Tok = Tok_Close_Bracket; -- # ex1 + + Append; -- # append + exit when Scan_Tok /= Tok_Semicolon and then Scan_Tok /= Tok_EOL; -- # ex2 + end loop; + end Parse_Array; + +end Parser; diff --git a/testsuite/tests/T520-035-exit-when/src/parser.ads b/testsuite/tests/T520-035-exit-when/src/parser.ads new file mode 100644 index 000000000..4f20fcd83 --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/parser.ads @@ -0,0 +1,6 @@ +package Parser is + type Tok is (Tok_Close_Bracket, Tok_Semicolon, Tok_EOL, Tok_Stuff); + type Toks is array (Natural range <>) of Tok; + + procedure Parse_Array (T : Toks); +end Parser; diff --git a/testsuite/tests/T520-035-exit-when/src/test_parser_0.adb b/testsuite/tests/T520-035-exit-when/src/test_parser_0.adb new file mode 100644 index 000000000..fe32bd332 --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/test_parser_0.adb @@ -0,0 +1,10 @@ +with Parser; use Parser; +procedure Test_Parser_0 is +begin + Parser.Parse_Array ((0 => Tok_Close_Bracket)); +end Test_Parser_0; + +--# parser.adb +-- /append/ l- ## s- +-- /ex1/ l! ## dF- +-- /ex2/ l- ## s- diff --git a/testsuite/tests/T520-035-exit-when/src/test_parser_full.adb b/testsuite/tests/T520-035-exit-when/src/test_parser_full.adb new file mode 100644 index 000000000..8d04d3481 --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/test_parser_full.adb @@ -0,0 +1,11 @@ +with Parser; use Parser; +procedure Test_Parser_Full is +begin + Parser.Parse_Array ((Tok_Stuff, Tok_Stuff, Tok_Stuff, Tok_Close_Bracket)); + Parser.Parse_Array ((Tok_Stuff, Tok_Semicolon, Tok_Close_Bracket)); +end Test_Parser_Full; + +--# parser.adb +-- /append/ l+ ## 0 +-- /ex1/ l+ ## 0 +-- /ex2/ l+ ## 0 diff --git a/testsuite/tests/T520-035-exit-when/src/test_parser_fx.adb b/testsuite/tests/T520-035-exit-when/src/test_parser_fx.adb new file mode 100644 index 000000000..183c2a967 --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/test_parser_fx.adb @@ -0,0 +1,10 @@ +with Parser; use Parser; +procedure Test_Parser_FX is +begin + Parser.Parse_Array ((Tok_Stuff, Tok_Semicolon, Tok_Close_Bracket)); +end Test_Parser_FX; + +--# parser.adb +-- /append/ l+ ## 0 +-- /ex1/ l+ ## 0 +-- /ex2/ l! ## dT- diff --git a/testsuite/tests/T520-035-exit-when/src/test_parser_tf.adb b/testsuite/tests/T520-035-exit-when/src/test_parser_tf.adb new file mode 100644 index 000000000..cfa1b5577 --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/test_parser_tf.adb @@ -0,0 +1,10 @@ +with Parser; use Parser; +procedure Test_Parser_TF is +begin + Parser.Parse_Array ((Tok_Stuff, Tok_Stuff, Tok_EOL, Tok_Close_Bracket)); +end Test_Parser_TF; + +--# parser.adb +-- /append/ l+ ## 0 +-- /ex1/ l+ ## 0 +-- /ex2/ l! ## dT- diff --git a/testsuite/tests/T520-035-exit-when/src/test_parser_tt.adb b/testsuite/tests/T520-035-exit-when/src/test_parser_tt.adb new file mode 100644 index 000000000..18fa6df83 --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/src/test_parser_tt.adb @@ -0,0 +1,10 @@ +with Parser; use Parser; +procedure Test_Parser_TT is +begin + Parser.Parse_Array ((Tok_Stuff, Tok_Stuff, Tok_Stuff, Tok_Close_Bracket)); +end Test_Parser_TT; + +--# parser.adb +-- /append/ l+ ## 0 +-- /ex1/ l! ## dT- +-- /ex2/ l! ## dF- diff --git a/testsuite/tests/T520-035-exit-when/test.py b/testsuite/tests/T520-035-exit-when/test.py new file mode 100644 index 000000000..cdc47c7ec --- /dev/null +++ b/testsuite/tests/T520-035-exit-when/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.adb b/testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.adb new file mode 100644 index 000000000..993018799 --- /dev/null +++ b/testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.adb @@ -0,0 +1,12 @@ +package body P1 is + + ---------- + -- Next -- + ---------- + + function Next (I : Integer) return Integer is + begin + return I + 1; + end Next; + +end P1; diff --git a/testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.ads b/testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.ads new file mode 100644 index 000000000..cd9d6a897 --- /dev/null +++ b/testsuite/tests/T528-018-dup-proj-crash/src-p1/p1.ads @@ -0,0 +1,5 @@ +package P1 is + + function Next (I : Integer) return Integer; + +end P1; diff --git a/testsuite/tests/T528-018-dup-proj-crash/src-p2/p2.adb b/testsuite/tests/T528-018-dup-proj-crash/src-p2/p2.adb new file mode 100644 index 000000000..23b6dcf98 --- /dev/null +++ b/testsuite/tests/T528-018-dup-proj-crash/src-p2/p2.adb @@ -0,0 +1,7 @@ +with P1; + +procedure P2 is + Dummy : constant Integer := P1.Next (1); +begin + null; +end P2; diff --git a/testsuite/tests/T528-018-dup-proj-crash/test.py b/testsuite/tests/T528-018-dup-proj-crash/test.py new file mode 100644 index 000000000..d2fbe5e0a --- /dev/null +++ b/testsuite/tests/T528-018-dup-proj-crash/test.py @@ -0,0 +1,27 @@ +""" +Regression test: gnatcov used to crash when the same project was processed +multiple times. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir('tmp_') +p1 = gprfor(prjid='p1', srcdirs=['../src-p1'], objdir='obj-p1', + mains=[], langs=['Ada']) +p2 = gprfor(prjid='p2', srcdirs=['../src-p2'], objdir='obj-p2', + deps=['p1'], mains=['p2.adb']) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p2, projects=['p1', 'p2']), + covlevel='stmt', + mains=['p2'], + gpr_obj_dir='obj-p2', + extra_coverage_args=['-axcov']) + + +thistest.result() diff --git a/testsuite/tests/T611-027-dump-units-to/main.adb b/testsuite/tests/T611-027-dump-units-to/main.adb new file mode 100644 index 000000000..9771e014c --- /dev/null +++ b/testsuite/tests/T611-027-dump-units-to/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Say_Hello; +end Main; diff --git a/testsuite/tests/T611-027-dump-units-to/pkg.adb b/testsuite/tests/T611-027-dump-units-to/pkg.adb new file mode 100644 index 000000000..dcf5ce77e --- /dev/null +++ b/testsuite/tests/T611-027-dump-units-to/pkg.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + procedure Say_Hello is + begin + Put_Line ("Hello, world!"); + end Say_Hello; +end Pkg; diff --git a/testsuite/tests/T611-027-dump-units-to/pkg.ads b/testsuite/tests/T611-027-dump-units-to/pkg.ads new file mode 100644 index 000000000..0728a72dd --- /dev/null +++ b/testsuite/tests/T611-027-dump-units-to/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Say_Hello; +end Pkg; diff --git a/testsuite/tests/T611-027-dump-units-to/test.py b/testsuite/tests/T611-027-dump-units-to/test.py new file mode 100644 index 000000000..6ce8730fc --- /dev/null +++ b/testsuite/tests/T611-027-dump-units-to/test.py @@ -0,0 +1,194 @@ +""" +Check that --dump-units-at works as expected. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +# Generate a project, instrument it and run it +p = gprfor(mains=['main.adb'], srcdirs=['..']) +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p), + covlevel='stmt', + mains=['main'], + extra_coverage_args=[]) +xcov_args_no_trace = xcov_args[:-1] +trace_file = xcov_args[-1] + + +def check_output(output_file, expected_content, regexp=False): + """ + Check that the content of the "output_file" text file matches + "expected_content". Check for equality if "regexp" is False and consider + that "expected_content" is a regexp otherwise. + + :param str output_file: Name of the text file whose content needs to be + checked. + :param str expected_content: Expected content for this file. + :param bool regexp: Whether to match as a regexp (by default, check + content equality). + """ + checker = (thistest.fail_if_no_match + if regexp + else thistest.fail_if_not_equal) + checker( + '"gnatcov coverage" output ({})'.format(output_file), + expected_content, + + # Canonicalize to Unix-style line endings to have cross-platform checks + contents_of(output_file).replace('\r\n', '\n')) + + +def run_and_check(args, output_file, expected_content, regexp=False, + success_expected=True): + """ + Run gnatcov with the given arguments. + + :param str output_file: Name of the temporary file to store the content of + gnatcov's standard output. + :param str expected_content: See the corresponding argument in "check". + :param bool regexp: See the corresponding argument in "check". + :param bool success_expected: If true, the test fails if gnatcov exits with + an error code. If false, the test fails if gnatcov exits with the zero + status code. + """ + p = xcov(args, out=output_file, register_failure=success_expected) + if not success_expected: + thistest.fail_if( + p.status == 0, + 'the call to "gnatcov coverage" was expected to fail, yet it' + ' succeeded (see {})'.format(output_file) + ) + check_output(output_file, expected_content, regexp) + + +# Check that --dump-units-to is rejected when used in object coverage mode +run_and_check( + ['coverage', '-cinsn', '-aasm', trace_file, '-P', p, '--dump-units-to=-'], + 'objcov.txt', + '.*gnatcov.*: --dump-units-to works in source coverage only', + regexp=True, + success_expected=False) + +# Check that nothing is dumped without --dump-units-to +run_and_check(xcov_args + ['-axcov'], 'xcov-nodump.txt', '') + +# Check that when *not* using the "report" format, the list is printed on +# stdout with --dump-units-to=-. +run_and_check(xcov_args + ['-axcov', '--dump-units-to=-'], + 'xcov-stdout1.txt', 'main\npkg\n') +run_and_check(xcov_args + ['-axcov', '--units=main', '--dump-units-to=-'], + 'xcov-stdout2.txt', 'main\n') + +# Check that the list is written to the designated file (foo1.txt) and not on +# the standard output with --dump-units-to=foo1.txt. +run_and_check(xcov_args + ['-axcov', '--dump-units-to=foo1.txt'], + 'xcov-foo.txt', '') +check_output('foo1.txt', 'main\npkg\n') + +# Check that with --dump-units-to=-, the list is included in the "report" +# annotation format... + +REPORT_PATTERN = ( + '(.|\n)*=+' + '\n== 4\\. UNITS OF INTEREST ==' + '\n=+' + '\n' + '\nmain' + '\npkg' + '\n' + '\n\\*\\* END OF REPORT \\*\\*' + '\n(.|\n)*') + +# ... on the standard output... +run_and_check( + xcov_args + ['-areport', '--dump-units-to=-'], 'report-stdout.txt', + REPORT_PATTERN, regexp=True) + +# ... or in the designated report file +run_and_check( + xcov_args + ['-areport', '--dump-units-to=-', '--output=report1.txt'], + 'report-stdout.txt', '') +check_output('report1.txt', REPORT_PATTERN, regexp=True) + +# Check that even with "-a report", the list is put in the designated file +# (foo2.txt) with --dump-units-to=foo2.txt. Check also that the report does +# *not* contain the list of units of interest. +run_and_check( + xcov_args + ['-areport', '--dump-units-to=foo2.txt', + '--output=report2.txt'], + 'report-redirected.txt', '') +check_output( + 'report2.txt', + '(.|\n)*=+' + '\n== 3\\. ANALYSIS SUMMARY ==' + '\n=+' + '\n' + '\nNo STMT violation.' + '\n' + '\n\\*\\* END OF REPORT \\*\\*' + '\n(.|\n)*', + regexp=True) +check_output('foo2.txt', 'main\npkg\n') + +# Now check that gnatcov refuses to dump the list of units of interest when +# --scos or --sid is involved. +if thistest.options.trace_mode == 'bin': + scos_optname = '--scos' + scos_ext = 'ali' +else: + scos_optname = '--sid' + scos_ext = 'sid' +scos_arg = '{}=obj/main.{}'.format(scos_optname, scos_ext) +run_and_check( + xcov_args + ['-axcov', '--dump-units-to=.', scos_arg], + 'xcov-scos.txt', + 'We will not be able to dump the list of units of interest: {} is' + ' present\n' + '.*gnatcov.*: Cannot dump the list of names for units of interest: see' + ' above.'.format(scos_optname), + regexp=True, + success_expected=False) + +# Check that the list of units of interest is written when just creating a +# checkpoint and --dump-units-to is passed. +run_and_check( + xcov_args + ['--units=main', '--dump-units-to=-', + '--save-checkpoint=c1.ckpt'], + 'ckpt-1.txt', + 'main\n') +run_and_check( + xcov_args + ['--units=pkg', '--save-checkpoint=c2.ckpt'], + 'ckpt-2.txt', + '') + +# Now check that it is properly reconstitued during checkpoint consolidation +run_and_check( + ['coverage', '-cstmt', '-axcov', '--dump-units-to=-', + '-Cc1.ckpt', '-Cc2.ckpt'], + 'ckpt-cons.txt', + 'main\npkg\n') + +# Finally, check that trying to dump units after loading a checkpoint which +# was created using --scos/--sid is rejected. +run_and_check( + xcov_args + ['--save-checkpoint=c3.ckpt', scos_arg], + 'ckpt-3.txt', + '') +run_and_check( + xcov_args_no_trace + ['-axcov', '--dump-units-to=.', '-Cc3.ckpt'], + 'ckpt-cons-invalid.txt', + 'We will not be able to dump the list of units of interest: c3.ckpt does' + ' not contain the list of units \\(produced with --scos or --sid\\)\n' + '.*gnatcov.*: Cannot dump the list of names for units of interest: see' + ' above.', + regexp=True, + success_expected=False) + +thistest.result() diff --git a/testsuite/tests/T629-012-pragmas/test.py b/testsuite/tests/T629-012-pragmas/test.py new file mode 100644 index 000000000..1d75df8f6 --- /dev/null +++ b/testsuite/tests/T629-012-pragmas/test.py @@ -0,0 +1,27 @@ +""" +Check that GNATcoverage knows about all pragmas listed in GNAT. +""" + +from SUITE.context import thistest +from SUITE.tutils import xcov +from SUITE.cutils import Wdir, lines_of + + +wd = Wdir('tmp_') + +# Get the list of pragmas that gnatcov knows +xcov(['dump-pragmas'], out='gnatcov.txt') +gnatcov_names = set(line.strip() for line in lines_of('gnatcov.txt')) + +# Get the list of pragmas that GNAT knows +xcov(['dump-pragmas', '--gnat-pragmas'], out='gnat.txt') +gnat_names = set(line.strip() for line in lines_of('gnat.txt')) + +# Check that gnatcov knows about all pragmas from gnat_util +missing_names = '\n'.join(sorted(gnat_names - gnatcov_names)) +thistest.fail_if( + missing_names, + 'gnatcov does not know about the following pragmas:\n' + missing_names) + + +thistest.result() diff --git a/testsuite/tests/T731-036-ckpt-bdd/test.opt b/testsuite/tests/T731-036-ckpt-bdd/test.opt new file mode 100644 index 000000000..c811f2f27 --- /dev/null +++ b/testsuite/tests/T731-036-ckpt-bdd/test.opt @@ -0,0 +1 @@ +arm-elf,src-traces DEAD The test program and its src-cov buffers are too big for this board diff --git a/testsuite/tests/T731-036-ckpt-bdd/test.py b/testsuite/tests/T731-036-ckpt-bdd/test.py new file mode 100644 index 000000000..bc2c70ffe --- /dev/null +++ b/testsuite/tests/T731-036-ckpt-bdd/test.py @@ -0,0 +1,143 @@ +""" +Regression testcase for the loading of BDD nodes from checkpoints. + +When loading a checkpoint, gnatcov used to load the whole BDD table once per +loaded CU (whereas the BDD table contains all BDDs for all CUs). For some usage +patterns, this could even trigger a memory exhaustion in gnatcov. This testcase +checks that the BDD table does not grow when we load/save the same checkpoint +over and over. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, list_to_file, text_to_file +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +# Generate sources for the test program. The point of this program is to have +# one unit (DC_Unit) that generates lots of BDD nodes (i.e. lots of decisions), +# several other units (Simple_Unit_*), and a main that uses all these units. + +# First emit a helper for DC_Unit +helper_ads_text = """ +package Helper is + function A return Boolean; + function B return Boolean; + function C return Boolean; +end Helper; +""" +helper_adb_text = """ +package body Helper is + function A return Boolean is + begin + return False; + end A; + function B return Boolean is + begin + return True; + end B; + function C return Boolean is + begin + return False; + end C; +end Helper; +""" +text_to_file(helper_ads_text, 'helper.ads') +text_to_file(helper_adb_text, 'helper.adb') + +# Emit DC_Unit itself, with 1000 decisions (3 BDD nodes each) +dc_unit_ads_text = """ +package DC_Unit is + procedure Run; +end DC_Unit; +""" +dc_unit_adb_text = [ + 'with Helper; use Helper;', + 'package body DC_Unit is', + ' procedure Run is', + ' begin' +] +for _ in range(1000): + dc_unit_adb_text.extend([ + ' if (A and then B) or C then', + ' raise Program_Error;', + ' end if;' + ]) +dc_unit_adb_text.extend([ + ' end Run;', + 'end DC_Unit;' +]) +text_to_file(dc_unit_ads_text, 'dc_unit.ads') +list_to_file(dc_unit_adb_text, 'dc_unit.adb') + +# Start the preparation of source excerpts for the Main unit +main_adb_context_clauses = ['with DC_Unit;'] +main_adb_statements = ['DC_Unit.Run;'] + +# Generate sources for the Simple_Unit_* units +simple_unit_ads = """ +package Simple_Unit_{n} is + procedure Run; +end Simple_Unit_{n}; +""" +simple_unit_adb = """ +package body Simple_Unit_{n} is + procedure Run is + begin + null; + end Run; +end Simple_Unit_{n}; +""" +for n in range(1, 11): + text_to_file(simple_unit_ads.format(n=n), + 'simple_unit_{}.ads'.format(n)) + text_to_file(simple_unit_adb.format(n=n), + 'simple_unit_{}.adb'.format(n)) + main_adb_context_clauses.append('with Simple_Unit_{};'.format(n)) + main_adb_statements.append('Simple_Unit_{}.Run;'.format(n)) + +# Finally, generate the Main unit +main_adb_sources = ( + main_adb_context_clauses + ['procedure Main is', 'begin'] + + main_adb_statements + ['end Main;'] +) +list_to_file(main_adb_sources, 'main.adb') + +# Generate the project file, run the instrumenter, run the program and produce +# a checkpoint. +p = gprfor(mains=['main.adb'], srcdirs=['.']) +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['--save-checkpoint=c0.ckpt'], + extra_gprbuild_args=['-j128']) + +# Load the same checkpoint multiple times. This used to create redundant BDDs, +# making the checkpoint grow over time. Checking that each loading/saving cycle +# does not make the checkpoint grow verifies that this bug is gone. +expected_size = None +for n in range(5): + prev_checkpoint = 'c{}.ckpt'.format(n) + next_checkpoint = 'c{}.ckpt'.format(n + 1) + ckpt_list = 'ckpt_list_{}.txt'.format(n) + list_to_file([prev_checkpoint] * 50, ckpt_list) + xcov(['coverage', '-cstmt', '-C@{}'.format(ckpt_list), + '--save-checkpoint', next_checkpoint]) + + size = os.path.getsize(next_checkpoint) + if expected_size is None: + expected_size = size + else: + thistest.fail_if_not_equal( + f"Unexpected size for {next_checkpoint}", + expected_size, + size, + ) + +thistest.result() diff --git a/testsuite/tests/T807-011-externally-built-objdir/.gitignore b/testsuite/tests/T807-011-externally-built-objdir/.gitignore new file mode 100644 index 000000000..255b407b1 --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/.gitignore @@ -0,0 +1,2 @@ +opslib/obj-opslib +opslib/lib-opslib diff --git a/testsuite/tests/T807-011-externally-built-objdir/opslib/ops.adb b/testsuite/tests/T807-011-externally-built-objdir/opslib/ops.adb new file mode 100644 index 000000000..55ef999ad --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/opslib/ops.adb @@ -0,0 +1,9 @@ + package body Ops is + procedure Apply (Op : Op_Kind; X : in out Integer) is + begin + case Op is + when Increment => X := X + 1; + when Decrement => X := X - 1; + end case; + end Apply; + end Ops; diff --git a/testsuite/tests/T807-011-externally-built-objdir/opslib/ops.ads b/testsuite/tests/T807-011-externally-built-objdir/opslib/ops.ads new file mode 100644 index 000000000..50271fc3d --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/opslib/ops.ads @@ -0,0 +1,4 @@ +package Ops is + type Op_Kind is (Increment, Decrement); + procedure Apply (Op : Op_Kind; X : in out Integer); +end Ops; diff --git a/testsuite/tests/T807-011-externally-built-objdir/opslib/opslib.gpr b/testsuite/tests/T807-011-externally-built-objdir/opslib/opslib.gpr new file mode 100644 index 000000000..a478a47b3 --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/opslib/opslib.gpr @@ -0,0 +1,14 @@ +library project Opslib is + + for Library_Name use "opslib"; + for Library_Kind use "static"; + + for Library_Dir use "lib-" & Project'Library_Name; + for Object_Dir use "obj-" & Project'Library_Name; + + for Source_Dirs use ("."); + + type Boolean is ("false", "true"); + for Externally_Built use external ("OPSLIB_EXTERNALLY_BUILT", "false"); + +end Opslib; diff --git a/testsuite/tests/T807-011-externally-built-objdir/test.py b/testsuite/tests/T807-011-externally-built-objdir/test.py new file mode 100644 index 000000000..72f5891ea --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/test.py @@ -0,0 +1,67 @@ +""" +Check that "gnatcov instrument" does not remove instrumented sources in the +object directory of externally built projects. +""" + +import os.path + +from e3.fs import ls, rm + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +opslib_gpr = os.path.join('..', 'opslib', 'opslib.gpr') +tests_gpr = os.path.join('..', 'tests.gpr') +tests_obj_dir = os.path.join('..', 'obj') +sid_pattern = os.path.join('..', 'opslib', 'obj-opslib', '*.sid') + +tests_gprsw = GPRswitches(root_project=tests_gpr, + xvars=[('OPSLIB_EXTERNALLY_BUILT', 'true')], + externally_built_projects=True) + +# First, instrument and build the opslib library project +xcov_instrument( + gprsw=GPRswitches(root_project=opslib_gpr), + covlevel='stmt+decision' +) +gprbuild(opslib_gpr, trace_mode='src', out='gprbuild-opslib.out') + +# Now instrument, build and run the test driver. When run on this test project, +# the instrumenter used to remove the instrumented sources in the opslib +# directory, which is invalid since opslib is externally built during this +# step, and as a result, building the instrumented main (from tests.gpr) failed +# because of the missing buffer units in opslib. +build_run_and_coverage( + gprsw=tests_gprsw, + covlevel='stmt+decision', + mains=['test_inc'], + extra_coverage_args=['-axcov', '--output-dir=report'], + gpr_obj_dir=tests_obj_dir, + gpr_exe_dir=tests_obj_dir, + trace_mode='src' +) + +check_xcov_reports('report/*.xcov', { + 'report/ops.ads.xcov': {}, + 'report/ops.adb.xcov': {'+': {4, 5}, '-': {6}}, +}) + +# Re-run the instrumenter on the main, to check that it does not re-create a +# SID file for the opslib externall built project. +rm(sid_pattern) +xcov_instrument(gprsw=tests_gprsw, covlevel='stmt+decision') +sids = ls(sid_pattern) +thistest.fail_if( + sids, + '"gnatcov instrument" wrongly re-created SID files: {}' + .format(sorted(sids)), +) + +thistest.result() diff --git a/testsuite/tests/T807-011-externally-built-objdir/tests.gpr b/testsuite/tests/T807-011-externally-built-objdir/tests.gpr new file mode 100644 index 000000000..93222dd5c --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/tests.gpr @@ -0,0 +1,12 @@ +with "opslib/opslib.gpr"; + +project Tests is + for Source_Dirs use ("tests"); + for Object_Dir use "obj"; + + for Main use ("test_inc.adb"); + + package Coverage is + for Units use (); + end Coverage; +end Tests; diff --git a/testsuite/tests/T807-011-externally-built-objdir/tests/test_inc.adb b/testsuite/tests/T807-011-externally-built-objdir/tests/test_inc.adb new file mode 100644 index 000000000..2213c45c9 --- /dev/null +++ b/testsuite/tests/T807-011-externally-built-objdir/tests/test_inc.adb @@ -0,0 +1,7 @@ +with Ops; +procedure Test_Inc is + X : Integer := 4; +begin + Ops.Apply (Ops.Increment, X); + pragma Assert (X = 5); +end Test_Inc; diff --git a/testsuite/tests/T825-010-naming-scheme/main.adb b/testsuite/tests/T825-010-naming-scheme/main.adb new file mode 100644 index 000000000..66acef3b1 --- /dev/null +++ b/testsuite/tests/T825-010-naming-scheme/main.adb @@ -0,0 +1,6 @@ +with P.Q; + +procedure Main is +begin + P.Q.Proc (1); +end Main; diff --git a/testsuite/tests/T825-010-naming-scheme/p.1.ada b/testsuite/tests/T825-010-naming-scheme/p.1.ada new file mode 100644 index 000000000..c8ef9f5c5 --- /dev/null +++ b/testsuite/tests/T825-010-naming-scheme/p.1.ada @@ -0,0 +1,4 @@ +package P is + type Int is new Integer; + function Identity (Value : Int) return Int; +end P; diff --git a/testsuite/tests/T825-010-naming-scheme/p.2.ada b/testsuite/tests/T825-010-naming-scheme/p.2.ada new file mode 100644 index 000000000..b07cb8a29 --- /dev/null +++ b/testsuite/tests/T825-010-naming-scheme/p.2.ada @@ -0,0 +1,6 @@ +package body P is + function Identity (Value : Int) return Int is + begin + return Value; + end Identity; +end P; diff --git a/testsuite/tests/T825-010-naming-scheme/p__q.1.ada b/testsuite/tests/T825-010-naming-scheme/p__q.1.ada new file mode 100644 index 000000000..c8ae1e709 --- /dev/null +++ b/testsuite/tests/T825-010-naming-scheme/p__q.1.ada @@ -0,0 +1,4 @@ +package P.Q is + procedure Proc (I : Int); + V : constant Int := Identity (2); +end P.Q; diff --git a/testsuite/tests/T825-010-naming-scheme/p__q.2.ada b/testsuite/tests/T825-010-naming-scheme/p__q.2.ada new file mode 100644 index 000000000..85c318345 --- /dev/null +++ b/testsuite/tests/T825-010-naming-scheme/p__q.2.ada @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body P.Q is + procedure Proc (I : Int) is + begin + Put_Line (Int'Image (I)); + end Proc; +end P.Q; diff --git a/testsuite/tests/T825-010-naming-scheme/test.py b/testsuite/tests/T825-010-naming-scheme/test.py new file mode 100644 index 000000000..0a1f7aa61 --- /dev/null +++ b/testsuite/tests/T825-010-naming-scheme/test.py @@ -0,0 +1,39 @@ +""" +Check that gnatcov works fine on projects using non-standard naming schemes. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +p = gprfor( + mains=['main.adb'], prjid='p', srcdirs=['..'], + extra=""" + package Naming is + for Spec_Suffix ("Ada") use ".1.ada"; + for Body_Suffix ("Ada") use ".2.ada"; + for Dot_Replacement use "__"; + for Body ("main") use "main.adb"; + end Naming; + """ +) +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=report'] +) +check_xcov_reports('report/*.xcov', { + 'report/main.adb.xcov': {'+': {5}}, + 'report/p.1.ada.xcov': {}, + 'report/p.2.ada.xcov': {'+': {4}}, + 'report/p__q.1.ada.xcov': {'+': {3}}, + 'report/p__q.2.ada.xcov': {'+': {6}}, +}) + +thistest.result() diff --git a/testsuite/tests/T828-018-tagged-aggr/src/pkg.adb b/testsuite/tests/T828-018-tagged-aggr/src/pkg.adb new file mode 100644 index 000000000..5adf673a6 --- /dev/null +++ b/testsuite/tests/T828-018-tagged-aggr/src/pkg.adb @@ -0,0 +1,11 @@ +package body Pkg is + function Create (I : Integer) return T is + begin + return (I => I); -- # create + end Create; + + procedure Foo is + begin + null; -- # foo + end Foo; +end Pkg; diff --git a/testsuite/tests/T828-018-tagged-aggr/src/pkg.ads b/testsuite/tests/T828-018-tagged-aggr/src/pkg.ads new file mode 100644 index 000000000..575125068 --- /dev/null +++ b/testsuite/tests/T828-018-tagged-aggr/src/pkg.ads @@ -0,0 +1,8 @@ +package Pkg is + type T is tagged record + I : Integer; + end record; + + function Create (I : Integer) return T; + procedure Foo; -- # foo +end Pkg; diff --git a/testsuite/tests/T828-018-tagged-aggr/src/test_full.adb b/testsuite/tests/T828-018-tagged-aggr/src/test_full.adb new file mode 100644 index 000000000..c781e8fa0 --- /dev/null +++ b/testsuite/tests/T828-018-tagged-aggr/src/test_full.adb @@ -0,0 +1,14 @@ +with Pkg; + +procedure Test_Full is + V : constant Pkg.T := Pkg.Create (1); +begin + Pkg.Foo; +end Test_Full; + +--# pkg.ads +-- /foo/ l. ## 0 +-- +--# pkg.adb +-- /create/ l+ ## 0 +-- /foo/ l+ ## 0 diff --git a/testsuite/tests/T828-018-tagged-aggr/src/test_no.adb b/testsuite/tests/T828-018-tagged-aggr/src/test_no.adb new file mode 100644 index 000000000..1b504c0a0 --- /dev/null +++ b/testsuite/tests/T828-018-tagged-aggr/src/test_no.adb @@ -0,0 +1,13 @@ +with Pkg; + +procedure Test_No is +begin + Pkg.Foo; +end Test_No; + +--# pkg.ads +-- /foo/ l. ## 0 +-- +--# pkg.adb +-- /create/ l- ## s- +-- /foo/ l+ ## 0 diff --git a/testsuite/tests/T828-018-tagged-aggr/test.py b/testsuite/tests/T828-018-tagged-aggr/test.py new file mode 100644 index 000000000..4f11e47a2 --- /dev/null +++ b/testsuite/tests/T828-018-tagged-aggr/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/T916-046-bdd-remapping/main.adb b/testsuite/tests/T916-046-bdd-remapping/main.adb new file mode 100644 index 000000000..1f627c209 --- /dev/null +++ b/testsuite/tests/T916-046-bdd-remapping/main.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Main is + Dummy : Integer := + Pkg.Compute (True, False) + Pkg.Compute_In_Stub (False, True); +begin + null; +end Main; diff --git a/testsuite/tests/T916-046-bdd-remapping/pkg-compute_in_stub.adb b/testsuite/tests/T916-046-bdd-remapping/pkg-compute_in_stub.adb new file mode 100644 index 000000000..4179c26d6 --- /dev/null +++ b/testsuite/tests/T916-046-bdd-remapping/pkg-compute_in_stub.adb @@ -0,0 +1,9 @@ +separate (Pkg) +function Compute_In_Stub (A, B : Boolean) return Integer is +begin + if A and then B then + return 2; + else + return 3; + end if; +end Compute_In_Stub; diff --git a/testsuite/tests/T916-046-bdd-remapping/pkg.adb b/testsuite/tests/T916-046-bdd-remapping/pkg.adb new file mode 100644 index 000000000..96543fe86 --- /dev/null +++ b/testsuite/tests/T916-046-bdd-remapping/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + function Compute (A, B : Boolean) return Integer is + begin + if A and then B then + return 2; + else + return 3; + end if; + end Compute; + + function Compute_In_Stub (A, B : Boolean) return Integer is separate; +end Pkg; diff --git a/testsuite/tests/T916-046-bdd-remapping/pkg.ads b/testsuite/tests/T916-046-bdd-remapping/pkg.ads new file mode 100644 index 000000000..00946638c --- /dev/null +++ b/testsuite/tests/T916-046-bdd-remapping/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + function Compute (A, B : Boolean) return Integer; + function Compute_In_Stub (A, B : Boolean) return Integer; +end Pkg; diff --git a/testsuite/tests/T916-046-bdd-remapping/test.py b/testsuite/tests/T916-046-bdd-remapping/test.py new file mode 100644 index 000000000..a51643489 --- /dev/null +++ b/testsuite/tests/T916-046-bdd-remapping/test.py @@ -0,0 +1,25 @@ +""" +Check that "gnatcov coverage" is able to process BDD data for the decisions to +cover. This used to crash in source trace mode when a single compilation unit +(in the GCC sense: the unit for pkg.ads, pkg.adb and pkg-compute_in_stub.adb) +contains multiple "CU" (pkg.ads, pkg.adb and pkg-compute_in_stub.adb are 3 CUs +for gnatcov), with multiple CUs containing decisions. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir('tmp_') + +p = gprfor(srcdirs=['..'], mains=['main.adb']) +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel='stmt+mcdc', + mains=['main'], + extra_coverage_args=['--save-checkpoint=partial.ckpt']) + +thistest.result() diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/foo.c b/testsuite/tests/TA12-013-dump-ignore-src-files/foo.c new file mode 100644 index 000000000..cba07c41a --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/foo.c @@ -0,0 +1,7 @@ +#include "identity.h" + +int +foo (int i) +{ + return identity (2 * i); +} diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/identity.h b/testsuite/tests/TA12-013-dump-ignore-src-files/identity.h new file mode 100644 index 000000000..a9a41fc1c --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/identity.h @@ -0,0 +1,5 @@ +static int +identity (int i) +{ + return i; +} diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/main.adb b/testsuite/tests/TA12-013-dump-ignore-src-files/main.adb new file mode 100644 index 000000000..0ce6b0c64 --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/main.adb @@ -0,0 +1,14 @@ +with Pkg; +with Pkh; + +procedure Main is + function C_Foo (I : Integer) return Integer; + pragma Import (C, C_Foo, "foo"); + + Dummy : Integer := C_Foo (1); +begin + Pkg.Say_Hello; + Pkg.Test; + Pkh.Say_Hello; + Pkh.Test; +end Main; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test-sep.adb b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test-sep.adb new file mode 100644 index 000000000..f1fbfac5a --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test-sep.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +separate (pkg.test) procedure Sep is +begin + Put_Line("This double separate is super useless!"); +end Sep; \ No newline at end of file diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test.adb b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test.adb new file mode 100644 index 000000000..0da377c2c --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; + +separate (pkg) procedure Test is + procedure Sep; + procedure Sep is separate; +begin + Put_Line ("This test procedure is useless!"); + Sep; +end Test; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkg.adb b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg.adb new file mode 100644 index 000000000..d1e7159b5 --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + procedure Say_Hello is + begin + Put_Line ("Hello, world!"); + end Say_Hello; + procedure Test is separate; +end Pkg; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkg.ads b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg.ads new file mode 100644 index 000000000..ab3cad927 --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + procedure Say_Hello; + procedure Test; +end Pkg; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkh-test.adb b/testsuite/tests/TA12-013-dump-ignore-src-files/pkh-test.adb new file mode 100644 index 000000000..d4cb21592 --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkh-test.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +separate (pkh) procedure Test is +begin + Put_Line ("This test procedure is useless!"); +end Test; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkh.adb b/testsuite/tests/TA12-013-dump-ignore-src-files/pkh.adb new file mode 100644 index 000000000..9445b60f7 --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkh.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkh is + procedure Say_Hello is + begin + Put_Line ("Hello, world!"); + end Say_Hello; + procedure Test is separate; +end Pkh; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkh.ads b/testsuite/tests/TA12-013-dump-ignore-src-files/pkh.ads new file mode 100644 index 000000000..1674205ed --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkh.ads @@ -0,0 +1,4 @@ +package Pkh is + procedure Say_Hello; + procedure Test; +end Pkh; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/test.py b/testsuite/tests/TA12-013-dump-ignore-src-files/test.py new file mode 100644 index 000000000..d60d9dcb3 --- /dev/null +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/test.py @@ -0,0 +1,256 @@ +""" +Check that --dump-units-to shows the individually ignored source files. +This extends test T611-027-dump-units-to. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +# Generate a project, instrument it and run it +p = gprfor(mains=['main.adb'], srcdirs=['..'], langs=['Ada', 'C']) +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p), + covlevel='stmt', + mains=['main'], + extra_coverage_args=[]) +xcov_args_no_trace = xcov_args[:-1] +trace_file = xcov_args[-1] + + +def check_output(output_file, expected_content, regexp=False): + """ + Check that the content of the "output_file" text file matches + "expected_content". Check for equality if "regexp" is False and consider + that "expected_content" is a regexp otherwise. + + :param str output_file: Name of the text file whose content needs to be + checked. + :param str expected_content: Expected content for this file. + :param bool regexp: Whether to match as a regexp (by default, check + content equality). + """ + checker = (thistest.fail_if_no_match + if regexp + else thistest.fail_if_not_equal) + checker( + '"gnatcov coverage" output ({})'.format(output_file), + expected_content, + + # Canonicalize to Unix-style line endings to have cross-platform checks + contents_of(output_file).replace('\r\n', '\n')) + + +def run_and_check(args, output_file, expected_content, regexp=False, + success_expected=True): + """ + Run gnatcov with the given arguments. + + :param str output_file: Name of the temporary file to store the content of + gnatcov's standard output. + :param str expected_content: See the corresponding argument in "check". + :param bool regexp: See the corresponding argument in "check". + :param bool success_expected: If true, the test fails if gnatcov exits with + an error code. If false, the test fails if gnatcov exits with the zero + status code. + """ + p = xcov(args, out=output_file, register_failure=success_expected) + if not success_expected: + thistest.fail_if( + p.status == 0, + 'the call to "gnatcov coverage" was expected to fail, yet it' + ' succeeded (see {})'.format(output_file) + ) + check_output(output_file, expected_content, regexp) + + +# Check that nothing is dumped without --dump-units-to +run_and_check(xcov_args + ['-axcov'], 'xcov-nodump.txt', '') + +# Check that when *not* using the "--ignored-source-files" option, the list of +# units is still printed. +run_and_check( + xcov_args + [ + '-axcov', '--dump-units-to=-', '--save-checkpoint=all_files.ckpt' + ], + 'xcov-stdout1.txt', + expected_content=( + 'foo.c\n' + 'identity.h\n' + 'main\n' + 'pkg\n' + 'pkh\n' + ), +) +run_and_check( + xcov_args + ['-axcov', '--units=main', '--dump-units-to=-'], + 'xcov-stdout2.txt', + expected_content='main\n', +) + +# Check that dumping the list of units with ignored source files works on the +# "report" output. +REPORT_PATTERN = ( + '(.|\n)*=+' + '\n== 4\\. UNITS OF INTEREST ==' + '\n=+' + '\n' + '\nfoo.c' + '\nidentity.h' + '\n identity.h always ignored' + '\nmain' + '\npkg' + '\n pkg-test.adb always ignored' + '\npkh' + '\n pkh-test.adb always ignored' + '\n' + '\n\\*\\* END OF REPORT \\*\\*' + '\n(.|\n)*') +run_and_check( + xcov_args + [ + '-areport', + '--dump-units-to=-', + '--ignore-source-files=*-test.adb', + '--ignore-source-files=identity.h', + ], + 'report-stdout.txt', + REPORT_PATTERN, regexp=True) + +# Check that the units of separates of level deeper than one is listed under +# the correct unit. +run_and_check( + xcov_args + [ + '-axcov', '--dump-units-to=-', '--ignore-source-files=pkg-test-sep.adb' + ], + 'xcov-stdout3.txt', + expected_content=( + 'foo.c\n' + 'identity.h\n' + 'main\n' + 'pkg\n' + ' pkg-test-sep.adb always ignored\n' + 'pkh\n' + ), +) + +# Check that a file ignored but that isn't part of a unit of interest +# is not listed. +run_and_check( + xcov_args + [ + '-axcov', + '--dump-units-to=-', + '--units=pkg', + '--ignore-source-files=*-test.adb', + '--ignore-source-files=identity.h', + '--save-checkpoint=pkg.ckpt', + ], + 'xcov-stdout4.txt', + expected_content=( + 'pkg\n' + ' pkg-test.adb always ignored\n' + ), +) + +# Check that a file ignored that is part of a unit of interest is listed +run_and_check( + xcov_args + [ + '-axcov', + '--dump-units-to=-', + '--units=pkh', + '--ignore-source-files=pkh-test.adb', + '--save-checkpoint=pkh.ckpt', + ], + 'xcov-stdout5.txt', + expected_content=( + 'pkh\n' + ' pkh-test.adb always ignored\n' + ), +) + +# Check that loading results from a checkpoint shows files that were ignored +# when creating the checkpoint. +run_and_check( + xcov_args_no_trace + ['-axcov', '--dump-units-to=-', '-Cpkh.ckpt'], + 'xcov-stdout6.txt', + expected_content=( + 'foo.c\n' + 'identity.h\n' + 'main\n' + 'pkg\n' + 'pkh\n' + ' pkh-test.adb always ignored\n' + ), +) + +run_and_check( + xcov_args_no_trace + [ + '-axcov', '--dump-units-to=-', '-Cpkg.ckpt', '-Cpkh.ckpt' + ], + 'xcov-stdout7.txt', + expected_content=( + 'foo.c\n' + 'identity.h\n' + 'main\n' + 'pkg\n' + ' pkg-test.adb always ignored\n' + 'pkh\n' + ' pkh-test.adb always ignored\n' + ), +) + +# Check that combining results from runs were a file was ignored in some +# of them but not all displays the files as 'sometimes ignored'. +run_and_check( + xcov_args_no_trace + [ + '-axcov', '--dump-units-to=-', '-Cpkg.ckpt', '-Call_files.ckpt', + ], + 'xcov-stdout8.txt', + expected_content=( + 'foo.c\n' + 'identity.h\n' + 'main\n' + 'pkg\n' + ' pkg-test.adb sometimes ignored\n' + 'pkh\n' + ), +) + +# Check that --ignore-source-files filters trace analysis but not checkpoints, +# and that if a file is ignored when analyzing a trace but is present in a +# checkpoint, then it is marked as 'sometimes ignored'. +run_and_check( + xcov_args + [ + '-axcov', + '--ignore-source-files=pkh-test.adb', + '--save-checkpoint=pkh_not_pkg.ckpt', + ], + 'xcov-sdtout9.txt', + '', +) +run_and_check( + xcov_args + [ + '-axcov', + '--dump-units-to=-', + '--ignore-source-files=*test.adb', + '--ignore-source-files=identity.h', + '-Cpkh_not_pkg.ckpt', + ], + 'xcov-stdout9.txt', + expected_content=( + 'foo.c\n' + 'identity.h\n' + ' identity.h sometimes ignored\n' + 'main\n' + 'pkg\n' + ' pkg-test.adb sometimes ignored\n' + 'pkh\n' + ' pkh-test.adb always ignored\n' + ), +) + +thistest.result() diff --git a/testsuite/tests/TA14-011-show-mcdc-vectors/main.adb b/testsuite/tests/TA14-011-show-mcdc-vectors/main.adb new file mode 100644 index 000000000..6e6dc8c9b --- /dev/null +++ b/testsuite/tests/TA14-011-show-mcdc-vectors/main.adb @@ -0,0 +1,10 @@ +with Pkg; use Pkg; +procedure Main is +begin + Mystery (False, True, True); + Mystery (False, False, False); + Mystery (True, True, True); + Mystery (True, True, False); + Other_Proc (True, True); + Other_Proc (False, True); +end Main; \ No newline at end of file diff --git a/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.adb b/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.adb new file mode 100644 index 000000000..8151a7c53 --- /dev/null +++ b/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.adb @@ -0,0 +1,26 @@ +with Ada.Text_IO; use Ada.Text_IO; +package body Pkg is + + procedure Mystery (A, B, C : Boolean) is + begin + if (A and then B and then C) or else A then + Put_Line ("Great success!"); + else + Put_Line ("Failed"); + end if; + if A then + Put_Line ("A is True"); + else + Put_Line ("A is False"); + end if; + end Mystery; + + procedure Other_Proc (A, B : Boolean) is + begin + if A and then B then + Put_Line ("Stuff"); + else + Put_Line ("not Stuff"); + end if; + end Other_Proc; +end Pkg; \ No newline at end of file diff --git a/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.ads b/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.ads new file mode 100644 index 000000000..6d0f7ef24 --- /dev/null +++ b/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.ads @@ -0,0 +1,6 @@ +package Pkg is + + procedure Mystery (A, B, C : Boolean); + + procedure Other_Proc (A, B : Boolean); +end Pkg; \ No newline at end of file diff --git a/testsuite/tests/TA14-011-show-mcdc-vectors/test.py b/testsuite/tests/TA14-011-show-mcdc-vectors/test.py new file mode 100644 index 000000000..d6d8188b5 --- /dev/null +++ b/testsuite/tests/TA14-011-show-mcdc-vectors/test.py @@ -0,0 +1,163 @@ +""" +Check that --show-mcdc-vectors works as expected. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +# Generate a project, instrument it if necessary and run it, +p = gprfor(mains=['main.adb'], srcdirs=['..']) +xcov_args_mcdc = build_and_run( + gprsw=GPRswitches(root_project=p), + covlevel='stmt+mcdc', + mains=['main'], + extra_coverage_args=[]) + + +def check_output(output_file, expected_content, regexp=False): + """ + Check that the content of the "output_file" text file matches + "expected_content". Check for equality if "regexp" is False and consider + that "expected_content" is a regexp otherwise. + + :param str output_file: Name of the text file whose content needs to be + checked. + :param str expected_content: Expected content for this file. + :param bool regexp: Whether to match as a regexp (by default, check + content equality). + """ + checker = (thistest.fail_if_no_match + if regexp + else thistest.fail_if_not_equal) + checker( + '"gnatcov coverage" output ({})'.format(output_file), + expected_content, + + # Canonicalize to Unix-style line endings to have cross-platform checks + contents_of(output_file).replace('\r\n', '\n')) + + +def run_and_check(args, output_file, expected_content, regexp=False, + success_expected=True): + """ + Run gnatcov with the given arguments. + + :param str output_file: Name of the temporary file to store the content of + gnatcov's standard output. + :param str expected_content: See the corresponding argument in "check". + :param bool regexp: See the corresponding argument in "check". + :param bool success_expected: If true, the test fails if gnatcov exits with + an error code. If false, the test fails if gnatcov exits with the zero + status code. + """ + p = xcov(args, out=output_file, register_failure=success_expected) + if not success_expected: + thistest.fail_if( + p.status == 0, + 'the call to "gnatcov coverage" was expected to fail, yet it' + ' succeeded (see {})'.format(output_file) + ) + check_output(output_file, expected_content, regexp) + + +# Check that no vector information is dumped without the option +# --show-mcdc-vectors + +REPORT_PATTERN_NO_VECTORS = ( + '(.|\n)*' + '\n' + r'\n2\.3\. MCDC COVERAGE' + '\n-+' + '\n' + r'\npkg\.adb:6:22: condition has no independent influence pair' + ', MC/DC not achieved' + r'\npkg\.adb:6:33: condition has no independent influence pair' + ', MC/DC not achieved' + r'\npkg\.adb:20:21: condition has no independent influence pair' + ', MC/DC not achieved' + '\n' + r'\n3 violations\.') + +run_and_check(xcov_args_mcdc + ['-areport'], 'report-stdout.txt', + REPORT_PATTERN_NO_VECTORS, regexp=True) + +# Check that mcdc vectors are displayed under the corresponding +# condition violations, and show the conditions indexes in violation messages. + +REPORT_PATTERN_MCDC = ( + '(.|\n)*' + '\n' + r'\n2\.3\. MCDC COVERAGE' + '\n-+' + '\n' + r'\npkg\.adb:6:22: condition 1 \("B"\) has no independent influence pair' + ', MC/DC not achieved' + r'\npkg\.adb:6:33: condition 2 \("C"\) has no independent influence pair' + ', MC/DC not achieved' + r'\npkg.adb:6:11: Decision of the form \(\(\(C0 and then C1\)' + r' and then C2\) or else C3\)' + '\nEvaluation vectors found:' + '\n F - - F -> FALSE In a pair for C0, C3' + '\n T T F T -> TRUE In a pair for C3' + '\n T T T - -> TRUE In a pair for C0' + '\n' + r'\npkg\.adb:20:21: condition 1 \("B"\) has no independent influence pair' + ', MC/DC not achieved' + r'\npkg.adb:20:10: Decision of the form \(C0 and then C1\)' + '\nEvaluation vectors found:' + '\n F - -> FALSE In a pair for C0' + '\n T T -> TRUE In a pair for C0' + '\n' + '\n' + r'\n3 violations\.') + +run_and_check(xcov_args_mcdc + ['-areport', '--show-mcdc-vectors'], + 'report-stdout.txt', REPORT_PATTERN_MCDC, regexp=True) + + +# Check that evaluation vectors not part of any pair are displayed +# below the other vectors. + +# No need to re-run since we only change the coverage from "stmt+mcdc" to +# "stmt+uc_mcdc". +xcov_args_uc_mcdc = xcov_args_mcdc + ["--level=stmt+uc_mcdc"] + +REPORT_PATTERN_UC_MCDC = ( + '(.|\n)*' + '\n' + r'\n2\.3\. UC_MCDC COVERAGE' + '\n-+' + '\n' + r'\npkg\.adb:6:22: condition 1 \("B"\) has no independent influence pair' + ', MC/DC not achieved' + r'\npkg\.adb:6:33: condition 2 \("C"\) has no independent influence pair' + ', MC/DC not achieved' + r'\npkg\.adb:6:44: condition 3 \("A"\) has no independent influence pair' + ', MC/DC not achieved' + r'\npkg.adb:6:11: Decision of the form \(\(\(C0 and then C1\)' + r' and then C2\) or else C3\)' + '\nEvaluation vectors found:' + '\n F - - F -> FALSE In a pair for C0' + '\n T T T - -> TRUE In a pair for C0' + '\n T T F T -> TRUE Not part of any pair' + '\n' + r'\npkg\.adb:20:21: condition 1 \("B"\) has no independent influence pair' + ', MC/DC not achieved' + r'\npkg.adb:20:10: Decision of the form \(C0 and then C1\)' + '\nEvaluation vectors found:' + '\n F - -> FALSE In a pair for C0' + '\n T T -> TRUE In a pair for C0' + '\n' + '\n' + r'\n4 violations\.') + +run_and_check(xcov_args_uc_mcdc + ['-areport', '--show-mcdc-vectors'], + 'report-stdout.txt', REPORT_PATTERN_UC_MCDC, regexp=True) + +thistest.result() diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/src-test1/main.adb b/testsuite/tests/TA15-063-ignore-fingerprint/src-test1/main.adb new file mode 100644 index 000000000..ea86ea180 --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/src-test1/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Test; +end Main; diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/src-test1/pkg-test.adb b/testsuite/tests/TA15-063-ignore-fingerprint/src-test1/pkg-test.adb new file mode 100644 index 000000000..2d801bc89 --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/src-test1/pkg-test.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +separate (Pkg) +procedure Test is +begin + Put_Line ("Test 1"); +end Test; diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/src/main.adb b/testsuite/tests/TA15-063-ignore-fingerprint/src/main.adb new file mode 100644 index 000000000..10e85a255 --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/src/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Do_Things; +end Main; diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg-test.adb b/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg-test.adb new file mode 100644 index 000000000..60cc4a6e8 --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg-test.adb @@ -0,0 +1,10 @@ +-- Tests override this unit to implement testcases + +with Ada.Text_IO; use Ada.Text_IO; + +separate (Pkg) +procedure Test is +begin + Put_Line ("!!! Test stub called in production setup"); + raise Program_Error; +end Test; diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.adb b/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.adb new file mode 100644 index 000000000..8802e8cc3 --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.adb @@ -0,0 +1,4 @@ +package body Pkg is + procedure Do_Things is null; + procedure Test is separate; +end Pkg; diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.ads b/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.ads new file mode 100644 index 000000000..4b9eed974 --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/src/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + procedure Do_Things; + procedure Test; +end Pkg; diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/test.py b/testsuite/tests/TA15-063-ignore-fingerprint/test.py new file mode 100644 index 000000000..52b5c413d --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/test.py @@ -0,0 +1,71 @@ +""" +Check that the consolidation of two checkpoints produced with different +--ignore-source-files options on the same set of sources works as expected. A +warning used to be emitted in that case, because of a low level SCO tables +fingerprint mismatch. +""" + +import os.path + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +def check_empty(filename): + content = contents_of(filename) + thistest.fail_if( + content, + f'Output of "gnatcov coverage" not empty ({filename}):\n\n{content}' + ) + + +tmp = Wdir("tmp_") + +p = gprfor(prjid="p", srcdirs=["../src"], mains=["main.adb"]) +test1 = os.path.abspath("test1.gpr") +cp("../test1.gpr", test1) + +# Build and run p.gpr's main.adb, then compute a partial coverage report +# (c1.ckpt), ignoring no source file. +build_run_and_coverage( + gprsw=GPRswitches(root_project=p, projects=["p"]), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--save-checkpoint=c1.ckpt"], + out="log-cov1.txt") +check_empty("log-cov1.txt") + +# Build and run test1.gpr's main.adb, then compute a partial coverage report +# (c2.ckpt) on p.gpr's source files, however, ignore pkg-test.adb this time. +build_run_and_coverage( + gprsw=GPRswitches(root_project=test1, projects=["p"], units=["pkg"]), + covlevel="stmt", + gpr_obj_dir="obj-test1", + gpr_exe_dir="obj-test1", + mains=["main"], + ignored_source_files=["pkg-test.adb"], + extra_coverage_args=["--save-checkpoint=c2.ckpt"], + out="log-cov2.txt") +check_empty("log-cov2.txt") + +# Avoid the "info: creating output path report" message +os.mkdir("report") + +# Consolidate both partial reports and produce an XCOV report +xcov(["coverage", "-P", p, "--projects", "p", "-cstmt", "-axcov", + "--output-dir=report", + "-Cc1.ckpt", "-Cc2.ckpt"], + out="log-cons.txt") +check_empty("log-cons.txt") +check_xcov_reports("report/*.xcov", { + "report/main.adb.xcov": {"+": {5}}, + "report/pkg.adb.xcov": {"+": {2}}, + "report/pkg-test.adb.xcov": {"-": {8, 9}}, +}) + +thistest.result() diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/test1.gpr b/testsuite/tests/TA15-063-ignore-fingerprint/test1.gpr new file mode 100644 index 000000000..436bcd7fb --- /dev/null +++ b/testsuite/tests/TA15-063-ignore-fingerprint/test1.gpr @@ -0,0 +1,4 @@ +project Test1 extends "p.gpr" is + for Source_Dirs use ("../src-test1"); + for Object_Dir use "obj-test1"; +end Test1; diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/main.adb b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/main.adb new file mode 100644 index 000000000..08d358367 --- /dev/null +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is +begin + Pkg.Say_Hello; + Pkg.Say_Goodbye; +end Main; diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg-say_goodbye.adb b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg-say_goodbye.adb new file mode 100644 index 000000000..d3c34f2a1 --- /dev/null +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg-say_goodbye.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +separate (Pkg) +procedure Say_Goodbye is +begin + if True then + Put_Line ("Goodbye!"); + else + Put_Line ("But not really!"); + end if; +end Say_Goodbye; diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.adb b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.adb new file mode 100644 index 000000000..7934788a7 --- /dev/null +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + procedure Say_Hello is + begin + if False then + Put_Line ("Hello, world!"); + else + Put_Line ("Not Hello World!"); + end if; + end Say_Hello; + procedure Say_Goodbye is separate; +end Pkg; diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.ads b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.ads new file mode 100644 index 000000000..b59060210 --- /dev/null +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + procedure Say_Hello; + procedure Say_Goodbye; +end Pkg; diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py new file mode 100644 index 000000000..1ae63fb4c --- /dev/null +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py @@ -0,0 +1,83 @@ +""" +Check that, in source instrumentation mode, --ignore-source-files can be used +when loading SID files, and that it does not interfere with the loading of +checkpoints otherwise. +""" + +from SCOV.minicheck import build_and_run, checked_xcov, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches +import os + + +tmp = Wdir('tmp_') + +# Generate a project, instrument it and run it +p = gprfor(mains=['main.adb'], srcdirs=['..']) +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p), + covlevel='stmt', + mains=['main'], + trace_mode='src', + extra_coverage_args=[]) +xcov_args_no_trace = xcov_args[:-1] +trace_file = xcov_args[-1] + +expected_res_dict = {'pkg.adb.xcov': {'-': {7}}, + 'pkg-say_goodbye.adb.xcov': {'-': {9}}} + + +def check(report_name, args, expected_files): + """ + Run gnatcov coverage with the given set of arguments in xcov mode, + and store the results in directory 'report_name'. Check that a report is + generated exactly for the files listed in 'expected_files', given the + fact that the results for a file should be the same accross all runs + and than coverage results match corresponding ones in expected_res_dict. + """ + + # Create report dir to avoid warning message + os.mkdir(report_name) + checked_xcov(args + ['-axcov', '--output-dir='+report_name], + f'{report_name}_out.txt') + expected = { + os.path.join(report_name, filename): + expected_res_dict[filename] + for filename in expected_files + } + check_xcov_reports(os.path.join(report_name, 'pkg*.xcov'), expected) + + +# Check that not passing the option has no effect +check('report0', xcov_args + ['--save-checkpoint=full.ckpt'], + ['pkg.adb.xcov', 'pkg-say_goodbye.adb.xcov']) + +# Check that --ignore-source-files has the expected effect on the 'coverage' +# command. +check('report1', xcov_args + ['--ignore-source-files=pkg-say_goodbye.adb'], + ['pkg.adb.xcov']) + +# Check that --ignore-source-files does not filter checkpoint loading +check('report2', xcov_args_no_trace + + ['--ignore-source-files=pkg-say_goodbye.adb', '-Cfull.ckpt'], + ['pkg.adb.xcov', 'pkg-say_goodbye.adb.xcov']) + +# Check that in presence of bot a checkpoint and a SID file, +# --ignore-source-files filters the SID file but not the checkpoint. +checked_xcov(xcov_args + ['--ignore-source-files=pkg-say_goodbye.adb', + '--save-checkpoint=pkg.ckpt'], + 'report3_out.txt') +check('report3', xcov_args + ['--ignore-source-files=pkg*.adb', '-Cpkg.ckpt'], + ['pkg.adb.xcov']) + +# Check that if a file is ignored when creating the checkpoint, then it is not +# present when loading that checkpoint. +checked_xcov(xcov_args + ['--save-checkpoint=pkg_goodbye.ckpt', + '--ignore-source-files=pkg.adb'], + 'report4_out.txt') +check('report4', xcov_args_no_trace + ['-Cpkg_goodbye.ckpt'], + ['pkg-say_goodbye.adb.xcov']) + +thistest.result() diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/main.adb b/testsuite/tests/TB13-020-expr-func-mcdc/main.adb new file mode 100644 index 000000000..ac487bc3a --- /dev/null +++ b/testsuite/tests/TB13-020-expr-func-mcdc/main.adb @@ -0,0 +1,23 @@ +pragma Ada_2012; + +with Pkg; + +procedure Main is + Dummy : constant Integer := (if Pkg.Flag then 1 else 2); + + function Is_Null (Self : Pkg.Point) return Boolean is + (Pkg.Is_Null (Self.X) and then Pkg.Is_Null (Self.Y)); + + P1 : constant Pkg.Point := (0, 0); + P2 : constant Pkg.Point := (0, 1); +begin + + if not Is_Null (P1) then + raise Program_Error; + end if; + + if Is_Null (P2) then + raise Program_Error; + end if; + +end Main; diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/pkg.adb b/testsuite/tests/TB13-020-expr-func-mcdc/pkg.adb new file mode 100644 index 000000000..fee4b7187 --- /dev/null +++ b/testsuite/tests/TB13-020-expr-func-mcdc/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + ------------- + -- Is_Null -- + ------------- + + function Is_Null (I : Integer) return Boolean is + begin + return I = 0; + end Is_Null; + +end Pkg; diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/pkg.ads b/testsuite/tests/TB13-020-expr-func-mcdc/pkg.ads new file mode 100644 index 000000000..71e6109e4 --- /dev/null +++ b/testsuite/tests/TB13-020-expr-func-mcdc/pkg.ads @@ -0,0 +1,8 @@ +package Pkg is + Flag : Boolean := True; + type Point is record + X, Y : Integer; + end record; + + function Is_Null (I : Integer) return Boolean; +end Pkg; diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/test.opt b/testsuite/tests/TB13-020-expr-func-mcdc/test.opt new file mode 100644 index 000000000..a4e1eba80 --- /dev/null +++ b/testsuite/tests/TB13-020-expr-func-mcdc/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/test.py b/testsuite/tests/TB13-020-expr-func-mcdc/test.py new file mode 100644 index 000000000..8935e0eb4 --- /dev/null +++ b/testsuite/tests/TB13-020-expr-func-mcdc/test.py @@ -0,0 +1,39 @@ +""" +Regression testcase for the instrumentation of expression functions that +trigger MC/DC obligations. + +(No reason not to also run it with binary traces.) +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +p = gprfor(prjid="p", srcdirs=[".."], mains=["main.adb"]) + +# Avoid the "info: creating output path report" message +os.mkdir("report") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=report"]) + +check_xcov_reports("report/*.xcov", { + "report/main.adb.xcov": { + "!": {6, 9, 15, 19}, + "+": {11, 12}, + "-": {16, 20}}, + "report/pkg.ads.xcov": {}, + "report/pkg.adb.xcov": {"+": {9}}, +}) + +thistest.result() diff --git a/testsuite/tests/TB24-022-missing-sid/src-p1/p1.adb b/testsuite/tests/TB24-022-missing-sid/src-p1/p1.adb new file mode 100644 index 000000000..993018799 --- /dev/null +++ b/testsuite/tests/TB24-022-missing-sid/src-p1/p1.adb @@ -0,0 +1,12 @@ +package body P1 is + + ---------- + -- Next -- + ---------- + + function Next (I : Integer) return Integer is + begin + return I + 1; + end Next; + +end P1; diff --git a/testsuite/tests/TB24-022-missing-sid/src-p1/p1.ads b/testsuite/tests/TB24-022-missing-sid/src-p1/p1.ads new file mode 100644 index 000000000..cd9d6a897 --- /dev/null +++ b/testsuite/tests/TB24-022-missing-sid/src-p1/p1.ads @@ -0,0 +1,5 @@ +package P1 is + + function Next (I : Integer) return Integer; + +end P1; diff --git a/testsuite/tests/TB24-022-missing-sid/src-p2/p2.adb b/testsuite/tests/TB24-022-missing-sid/src-p2/p2.adb new file mode 100644 index 000000000..23b6dcf98 --- /dev/null +++ b/testsuite/tests/TB24-022-missing-sid/src-p2/p2.adb @@ -0,0 +1,7 @@ +with P1; + +procedure P2 is + Dummy : constant Integer := P1.Next (1); +begin + null; +end P2; diff --git a/testsuite/tests/TB24-022-missing-sid/test.py b/testsuite/tests/TB24-022-missing-sid/test.py new file mode 100644 index 000000000..196b8bfc6 --- /dev/null +++ b/testsuite/tests/TB24-022-missing-sid/test.py @@ -0,0 +1,32 @@ +""" +Check that gnatcov correctly detects missing SID. +""" +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +gprfor(prjid="p1", srcdirs=["../src-p1"], mains=None, langs="Ada") + +p2 = gprfor(prjid="p2", srcdirs=["../src-p2"], mains=["p2.adb"], + deps=["p1"], + extra="for Origin_Project use \"p1\";") + +# Build the projects and produce a trace for the main +build_run_and_coverage(gprsw=GPRswitches(root_project=p2), + covlevel="stmt", + mains=["p2"], + extra_coverage_args=["-a", "xcov", + "--no-subprojects", + "--projects=p2", + "-v"], + trace_mode="src") + +thistest.fail_if("warning: no SID file found for unit p2" + not in contents_of("coverage.log"), + "No warning for missing SID file (for p2)") + +thistest.result() diff --git a/testsuite/tests/TC03-012-objcov-line-state/main.c b/testsuite/tests/TC03-012-objcov-line-state/main.c new file mode 100644 index 000000000..54a207666 --- /dev/null +++ b/testsuite/tests/TC03-012-objcov-line-state/main.c @@ -0,0 +1,16 @@ +int +add_n (int a, int b) +{ + int res = b; + for (int x = 0; x < a; x++) + { + res += 1; + } + return res; +} + +int +main () +{ + return add_n (0, 0); +} \ No newline at end of file diff --git a/testsuite/tests/TC03-012-objcov-line-state/main.s b/testsuite/tests/TC03-012-objcov-line-state/main.s new file mode 100644 index 000000000..457b39b09 --- /dev/null +++ b/testsuite/tests/TC03-012-objcov-line-state/main.s @@ -0,0 +1,304 @@ + .file "main.c" + .text +.Ltext0: + .globl add_n + .type add_n, @function +add_n: +.LFB0: + .file 1 "main.c" + .loc 1 1 24 + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movl %edi, -20(%rbp) + movl %esi, -24(%rbp) + .loc 1 2 7 + movl -24(%rbp), %eax + movl %eax, -4(%rbp) +.LBB2: + .loc 1 3 11 + movl $0, -8(%rbp) + .loc 1 3 3 + jmp .L2 +.L3: + addl $1, -8(%rbp) + .loc 1 4 8 discriminator 3 + addl $1, -4(%rbp) +.L2: + .loc 1 3 20 discriminator 1 + movl -8(%rbp), %eax + cmpl -20(%rbp), %eax + jl .L3 +.LBE2: + .loc 1 6 10 + movl -4(%rbp), %eax + nop + .loc 1 7 1 + popq %rbp + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE0: + .size add_n, .-add_n + .globl main + .type main, @function +main: +.LFB1: + .loc 1 9 12 + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + .loc 1 10 10 + movl $0, %esi + movl $0, %edi + call add_n + .loc 1 11 1 + nop + popq %rbp + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE1: + .size main, .-main +.Letext0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .long 0xb6 + .value 0x4 + .long .Ldebug_abbrev0 + .byte 0x8 + .uleb128 0x1 + .long .LASF0 + .byte 0xc + .long .LASF1 + .long .LASF2 + .quad .Ltext0 + .quad .Letext0-.Ltext0 + .long .Ldebug_line0 + .uleb128 0x2 + .long .LASF3 + .byte 0x1 + .byte 0x9 + .byte 0x5 + .long 0x4b + .quad .LFB1 + .quad .LFE1-.LFB1 + .uleb128 0x1 + .byte 0x9c + .uleb128 0x3 + .byte 0x4 + .byte 0x5 + .string "int" + .uleb128 0x4 + .long .LASF4 + .byte 0x1 + .byte 0x1 + .byte 0x5 + .long 0x4b + .quad .LFB0 + .quad .LFE0-.LFB0 + .uleb128 0x1 + .byte 0x9c + .uleb128 0x5 + .string "a" + .byte 0x1 + .byte 0x1 + .byte 0xf + .long 0x4b + .uleb128 0x2 + .byte 0x91 + .sleb128 -36 + .uleb128 0x5 + .string "b" + .byte 0x1 + .byte 0x1 + .byte 0x16 + .long 0x4b + .uleb128 0x2 + .byte 0x91 + .sleb128 -40 + .uleb128 0x6 + .string "res" + .byte 0x1 + .byte 0x2 + .byte 0x7 + .long 0x4b + .uleb128 0x2 + .byte 0x91 + .sleb128 -20 + .uleb128 0x7 + .quad .LBB2 + .quad .LBE2-.LBB2 + .uleb128 0x6 + .string "x" + .byte 0x1 + .byte 0x3 + .byte 0xb + .long 0x4b + .uleb128 0x2 + .byte 0x91 + .sleb128 -24 + .byte 0 + .byte 0 + .byte 0 + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .uleb128 0x1 + .uleb128 0x11 + .byte 0x1 + .uleb128 0x25 + .uleb128 0xe + .uleb128 0x13 + .uleb128 0xb + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x1b + .uleb128 0xe + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x7 + .uleb128 0x10 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x2 + .uleb128 0x2e + .byte 0 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x39 + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x7 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2116 + .uleb128 0x19 + .byte 0 + .byte 0 + .uleb128 0x3 + .uleb128 0x24 + .byte 0 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3e + .uleb128 0xb + .uleb128 0x3 + .uleb128 0x8 + .byte 0 + .byte 0 + .uleb128 0x4 + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x39 + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x7 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x2117 + .uleb128 0x19 + .byte 0 + .byte 0 + .uleb128 0x5 + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x39 + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x6 + .uleb128 0x34 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x39 + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x7 + .uleb128 0xb + .byte 0x1 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x7 + .byte 0 + .byte 0 + .byte 0 + .section .debug_aranges,"",@progbits + .long 0x2c + .value 0x2 + .long .Ldebug_info0 + .byte 0x8 + .byte 0 + .value 0 + .value 0 + .quad .Ltext0 + .quad .Letext0-.Ltext0 + .quad 0 + .quad 0 + .section .debug_line,"",@progbits +.Ldebug_line0: + .section .debug_str,"MS",@progbits,1 +.LASF4: + .string "add_n" +.LASF1: + .string "main.c" +.LASF2: + .string ".." +.LASF3: + .string "main" +.LASF0: + .string "GNU C17 10.2.1 20210111 (for GNAT Pro 22.0w 20210111) -mtune=generic -march=x86-64 -g" + .ident "GCC: (GNU) 10.2.1 20210111 (for GNAT Pro 22.0w 20210111)" + .section .note.GNU-stack,"",@progbits diff --git a/testsuite/tests/TC03-012-objcov-line-state/test.opt b/testsuite/tests/TC03-012-objcov-line-state/test.opt new file mode 100644 index 000000000..f5b84ac3c --- /dev/null +++ b/testsuite/tests/TC03-012-objcov-line-state/test.opt @@ -0,0 +1,2 @@ +!bin-traces DEAD Binary traces specific testcase +!x86_64-linux DEAD Embeds x86_64 assembly sources for Linux diff --git a/testsuite/tests/TC03-012-objcov-line-state/test.py b/testsuite/tests/TC03-012-objcov-line-state/test.py new file mode 100644 index 000000000..431d437c7 --- /dev/null +++ b/testsuite/tests/TC03-012-objcov-line-state/test.py @@ -0,0 +1,29 @@ +""" +Testcase for TC03-012: Check that line coverage state is correctly computed, +even if some debug information is missing from the executable. +""" + +import os +from e3.os.process import Run + +from SCOV.minicheck import check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import exepath_to, exename_for, gprfor, xcov, xrun, tracename_for + +Wdir('tmp') + +prj = gprfor(srcdirs=['..'], objdir='.', mains=['main.c'], prjid='gen') + +# Compile assembly +Run(['gcc', '-o', exename_for('main'), os.path.join('..', 'main.s')]) + +# Run and coverage +xrun(['-cinsn', exepath_to('main')]) +xcov(['coverage', '-cinsn', '-axcov', '-Pgen', tracename_for('main')]) + +# Check that line 3 is correctly marked as partially covered +check_xcov_reports('main.c.xcov', + {'main.c.xcov': {'-': {4}, '!': {3}}}) + +thistest.result() diff --git a/testsuite/tests/TC11-052-internal-error/main.adb b/testsuite/tests/TC11-052-internal-error/main.adb new file mode 100644 index 000000000..782870a93 --- /dev/null +++ b/testsuite/tests/TC11-052-internal-error/main.adb @@ -0,0 +1,11 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + type T is null record; + procedure Do_Nothing is null; +begin + Put_Line ("Hello World!"); + Do_Nothing; +end Main; diff --git a/testsuite/tests/TC11-052-internal-error/test.py b/testsuite/tests/TC11-052-internal-error/test.py new file mode 100644 index 000000000..1789f93d4 --- /dev/null +++ b/testsuite/tests/TC11-052-internal-error/test.py @@ -0,0 +1,84 @@ +""" +Check that gnatcov reports internal errors as expected. +""" + +import re +import os + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov + + +def check(args, trigger, info): + # Run gnatcov with the given arguments and trigger + out = f"{trigger}.log" + env = dict(os.environ) + env["GNATCOV_INTERNAL_ERROR_TRIGGER"] = trigger + p = xcov(args, out=out, env=env, register_failure=False) + thistest.fail_if( + p.status == 0, + "gnatcov returned success exit code, error expected" + ) + + expected_output = re.compile( + "\n".join([ + ".*", + "== gnatcov bug detected ==", + "", + "gnatcov just encountered an internal error:", + f"raised CONSTRAINT_ERROR : {trigger.upper().replace('-', '_')}", + # Depending on how gnatcov is built, exception info may contain + # stack traces. + "((Load address: [x0-9a-f]+\n)?Call stack traceback locations:", + "[x0-9a-f ]+", + ")?", + "", + "(?P.*)", + "", + "This is gnatcov version .*", + ]), + re.MULTILINE + ) + + # The difference between expected and actual output generally is + # specifically in the "info" part. To make error messages easier to read, + # first match the global structure of the output. If that succeeds, compare + # the "info" part separately. + output = contents_of(out) + thistest.fail_if_no_match( + what=f"[{trigger}] gnatcov output", + regexp=expected_output, + actual=output, + ) + + m = expected_output.match(output) + if m: + thistest.fail_if_no_match( + what=f"[{trigger}] context info in gnatcov output", + regexp=re.compile(info, re.MULTILINE), + actual=m.group("info"), + ) + + +tmp = Wdir("tmp_") +prj = gprfor(srcdirs=[".."], mains=["main.adb"]) +os.mkdir("obj") + +check(args=["coverage"], + trigger="arguments-loading", + info=r"No coverage processing context information available\.") + +check(args=["instrument", "-P", prj, "--level=stmt"], + trigger="ada-instrument-start-file", + info=r"Instrumenting [^\n]*main\.adb") + +check(args=["instrument", "-P", prj, "--level=stmt"], + trigger="ada-instrument-null-proc", + info=r"Instrumenting NullSubpDecl at [^\n]*main\.adb:7:4-7:33") + +check(args=["instrument", "-P", prj, "--level=stmt"], + trigger="ada-instrument-insert-stmt-witness", + info=r"Instrumenting ConcreteTypeDecl at [^\n]*main\.adb:6:4-6:26") + +thistest.result() diff --git a/testsuite/tests/U128-004-displayed-percentages/main1.adb b/testsuite/tests/U128-004-displayed-percentages/main1.adb new file mode 100644 index 000000000..877836be8 --- /dev/null +++ b/testsuite/tests/U128-004-displayed-percentages/main1.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main1 is +begin + Pkg.Process (True); +end Main1; diff --git a/testsuite/tests/U128-004-displayed-percentages/main99.adb b/testsuite/tests/U128-004-displayed-percentages/main99.adb new file mode 100644 index 000000000..ecb470e56 --- /dev/null +++ b/testsuite/tests/U128-004-displayed-percentages/main99.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main99 is +begin + Pkg.Process (False); +end Main99; diff --git a/testsuite/tests/U128-004-displayed-percentages/pkg.adb b/testsuite/tests/U128-004-displayed-percentages/pkg.adb new file mode 100644 index 000000000..333babbc1 --- /dev/null +++ b/testsuite/tests/U128-004-displayed-percentages/pkg.adb @@ -0,0 +1,250 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + procedure Process (B : Boolean) is + begin + if B then + Put_Line("Hello World!"); + else + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + null; + end if; + end Process; +end Pkg; diff --git a/testsuite/tests/U128-004-displayed-percentages/pkg.ads b/testsuite/tests/U128-004-displayed-percentages/pkg.ads new file mode 100644 index 000000000..cea167fa1 --- /dev/null +++ b/testsuite/tests/U128-004-displayed-percentages/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Process (B : Boolean); +end Pkg; diff --git a/testsuite/tests/U128-004-displayed-percentages/test.py b/testsuite/tests/U128-004-displayed-percentages/test.py new file mode 100644 index 000000000..2d49044b2 --- /dev/null +++ b/testsuite/tests/U128-004-displayed-percentages/test.py @@ -0,0 +1,27 @@ +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +prj = gprfor(srcdirs=[".."], mains=["main1.adb", "main99.adb"]) + +build_run_and_coverage(gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main99"], + extra_coverage_args=["-a", "xcov"]) +# For percentages > 99%, GNATcoverage should always round down +thistest.fail_if("99% of 241 lines covered" not in + contents_of("obj/pkg.adb.xcov")) + +build_run_and_coverage(gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main1"], + extra_coverage_args=["-a", "xcov"]) +# Symetrically, for percentages < 1%, GNATcoverage should round up +thistest.fail_if("1% of 241 lines covered" not in + contents_of("obj/pkg.adb.xcov")) + +thistest.result() diff --git a/testsuite/tests/U128-029-missing-dump-trigger/main.adb b/testsuite/tests/U128-029-missing-dump-trigger/main.adb new file mode 100644 index 000000000..2d5ca66b2 --- /dev/null +++ b/testsuite/tests/U128-029-missing-dump-trigger/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello World!"); +end Main; diff --git a/testsuite/tests/U128-029-missing-dump-trigger/test.py b/testsuite/tests/U128-029-missing-dump-trigger/test.py new file mode 100644 index 000000000..3073b4d3e --- /dev/null +++ b/testsuite/tests/U128-029-missing-dump-trigger/test.py @@ -0,0 +1,13 @@ +""" +Regression testcase for a gnatcov crash when gnatcov instrument is called +without the dump-trigger option. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov + +tmp = Wdir("tmp_") +prj = gprfor(srcdirs=[".."], mains=["main.adb"]) +xcov(["instrument", "-P", prj, "--level=stmt"]) +thistest.result() diff --git a/testsuite/tests/U204-026-arch-mix/foo.gpr b/testsuite/tests/U204-026-arch-mix/foo.gpr new file mode 100644 index 000000000..5d6ea4e09 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/foo.gpr @@ -0,0 +1,4 @@ +project Foo is + for Object_Dir use "obj"; + for Main use ("main_1.adb", "main_2.adb"); +end Foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen.sh b/testsuite/tests/U204-026-arch-mix/gen.sh new file mode 100755 index 000000000..c16a448a3 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen.sh @@ -0,0 +1,124 @@ +#! /bin/sh + +# Script to generate instrumented sources, SID, traces and checkpoint files to +# be used in this test. +# +# Since our testsuite infrastructure does not allow us to run several hosts and +# toolchains at the same time, we pre-generate these files manually and add +# them as material to the testsuite. + +set -ex + +os="$1" +case "$os" in + linux) + expected_cwd="/tmp/U204-026-arch-mix" + ;; + windows) + expected_cwd="/cygdrive/c/tmp/U204-026-arch-mix" + ;; + *) + echo "Invalid OS: $os" + exit 1 + ;; +esac +if [ "$expected_cwd" != "$PWD" ] +then + echo "Please run this script from the $expected_cwd directory" + exit 1 +fi + +XCOV_INSTR="gnatcov instrument -Pfoo -cstmt+mcdc \ + --dump-trigger=main-end --dump-channel=base64-stdout" +XCOV_COV="gnatcov coverage -Pfoo -cstmt+mcdc" +CROSS32_OPTS="--target=arm-eabi --RTS=light-stm32f4" +CROSS64_OPTS="--target=aarch64-elf --RTS=light-zynqmp" +SRC_BUILD_OPTS="--src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts" +SRC_BUILD_CROSS_OPTS="--src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts" +BIN_BUILD_OPTS="-cargs -g -fdump-scos -fpreserve-control-flow" + +rm -rf gen +mkdir gen + +# +# 1. Check that we can instrument on one host and build+run+coverage on another +# + +# On Windows, instrument the "foo" project for the native target. "test.py" +# will find the SIDs and the instrumented sources in "gen/x86_64-windows". +# +# On Linux, instrument the "foo" project for ARM ELF. "test.py" will find the +# SIDs and the instrumented sources in "gen/arm-elf-linux" + +case $os in + windows) + $XCOV_INSTR + dest=x86_64-windows + ;; + linux) + $XCOV_INSTR $CROSS32_OPTS + dest=arm-elf-linux + ;; +esac +mkdir gen/$dest +cp obj/*.sid obj/foo-gnatcov-instr/* gen/$dest + +# +# 2. Check that we can mix checkpoints created from source traces even when +# these source traces were produced for different targets, possibly from +# different hosts. +# + +# On Windows, build the "foo" instrumented project (previously for the native +# target) and run main_1 to produce a source trace. +# +# On Linux, do the same for ARM ELF/main_2. +# +# In both cases, create a checkpoint from the trace. + +case $os in + windows) + gprbuild -Pfoo $SRC_BUILD_OPTS + obj/main_1 > main_1-out.txt + gnatcov extract-base64-trace main_1-out.txt gen/main_1.srctrace + $XCOV_COV --save-checkpoint=gen/src-main_1.ckpt gen/main_1.srctrace + ;; + linux) + gprbuild $CROSS32_OPTS -Pfoo $SRC_BUILD_CROSS_OPTS + arm-eabi-gnatemu --board=stm32f4 obj/main_2 > main_2-out.txt + gnatcov extract-base64-trace main_2-out.txt gen/main_2.srctrace + $XCOV_COV --save-checkpoint=gen/src-main_2.ckpt gen/main_2.srctrace + ;; +esac + +# +# 3. Reject mix of checkpoints created with binary traces for different +# "bits-target" (32 vs 64-bit). +# + +# On Linux, build+run+create checkpoints (with binary traces) for both 32 and +# 64-bit targets. + +case $os in + linux) + gprbuild -Pfoo $CROSS32_OPTS $BIN_BUILD_OPTS + gnatcov run --target=arm-eabi,stm32f4 -o bin-main_1.trace obj/main_1 + $XCOV_COV $CROSS32_OPTS --save-checkpoint=gen/bin-main_1.ckpt \ + bin-main_1.trace + + gprbuild -Pfoo $CROSS64_OPTS $BIN_BUILD_OPTS + gnatcov run --target=aarch64-elf -o bin-main_2.trace obj/main_2 + $XCOV_COV $CROSS64_OPTS --save-checkpoint=gen/bin-main_2.ckpt \ + bin-main_2.trace + ;; +esac + +# +# 4. Check that we can use source traces produced on a different host +# + +# Nothing to do here: step 2 already added source traces to the "gen" +# directory. + +# Clean up permissions (i.e. remove execution bits on Windows) +find gen -type f | xargs chmod 644 diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_1.ads new file mode 100644 index 000000000..a29e8e4dd --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_1.ads @@ -0,0 +1,41 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GNATcov_RTS.Buffers.BB_main_1 is + + pragma Preelaborate; + + Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1"); + + Unit_Name : constant String := "main_1"; + Project_Name : constant String := ""; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (125, 27, 0, 113, 188, 140, 235, 155, 190, 125, 180, 238, 139, 95, 108, 198, 229, 72, 222, 11), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), + Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 0, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); + + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_1_buffers"); + +end GNATcov_RTS.Buffers.BB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_2.ads new file mode 100644 index 000000000..4f546cde7 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_2.ads @@ -0,0 +1,41 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GNATcov_RTS.Buffers.BB_main_2 is + + pragma Preelaborate; + + Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2"); + + Unit_Name : constant String := "main_2"; + Project_Name : constant String := ""; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (242, 237, 33, 15, 121, 175, 106, 160, 145, 225, 226, 10, 175, 16, 207, 223, 26, 27, 27, 148), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), + Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 0, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); + + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_2_buffers"); + +end GNATcov_RTS.Buffers.BB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads new file mode 100644 index 000000000..39a532e60 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads @@ -0,0 +1,41 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GNATcov_RTS.Buffers.BB_pkg is + + pragma Preelaborate; + + Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg"); + + Unit_Name : constant String := "pkg"; + Project_Name : constant String := ""; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), + Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 2, + Decision_Last_Bit => 1, + MCDC_Last_Bit => 2); + + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_pkg_buffers"); + +end GNATcov_RTS.Buffers.BB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads new file mode 100644 index 000000000..f041e06e8 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads @@ -0,0 +1,41 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GNATcov_RTS.Buffers.BS_pkg is + + pragma Preelaborate; + + Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg"); + + Unit_Name : constant String := "pkg"; + Project_Name : constant String := ""; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), + Language => Unit_Based_Language, + Unit_Part => Unit_Spec, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), + Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => -1, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); + + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_S_pkg_buffers"); + +end GNATcov_RTS.Buffers.BS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.adb new file mode 100644 index 000000000..1923cd7da --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.adb @@ -0,0 +1,15 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Traces.Output.Base64; +with Interfaces.C; +with GNATcov_RTS.Buffers.Lists.foo; +package body GNATcov_RTS.Buffers.DB_main_1 is + + procedure Dump_Buffers is + begin + GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper + (GNATcov_RTS.Buffers.Lists.foo.List, + Program_Name => "main_1", + Exec_Date => 0); + end Dump_Buffers; + +end GNATcov_RTS.Buffers.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.ads new file mode 100644 index 000000000..e8975f8ba --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.ads @@ -0,0 +1,6 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +package GNATcov_RTS.Buffers.DB_main_1 is + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); +end GNATcov_RTS.Buffers.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.adb new file mode 100644 index 000000000..c868d1f17 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.adb @@ -0,0 +1,15 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Traces.Output.Base64; +with Interfaces.C; +with GNATcov_RTS.Buffers.Lists.foo; +package body GNATcov_RTS.Buffers.DB_main_2 is + + procedure Dump_Buffers is + begin + GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper + (GNATcov_RTS.Buffers.Lists.foo.List, + Program_Name => "main_2", + Exec_Date => 0); + end Dump_Buffers; + +end GNATcov_RTS.Buffers.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.ads new file mode 100644 index 000000000..5a1450133 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.ads @@ -0,0 +1,6 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +package GNATcov_RTS.Buffers.DB_main_2 is + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); +end GNATcov_RTS.Buffers.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads new file mode 100644 index 000000000..63f03b9f4 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads @@ -0,0 +1,25 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers.BB_main_1; +with GNATcov_RTS.Buffers.BB_main_2; +with GNATcov_RTS.Buffers.BB_pkg; +with GNATcov_RTS.Buffers.BS_pkg; + +package GNATcov_RTS.Buffers.Lists.foo is + + pragma Preelaborate; + + gnatcov_rts_buffers_B_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_B_main_1_buffers,"gnatcov_rts_buffers_B_main_1_buffers"); + gnatcov_rts_buffers_B_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_B_main_2_buffers,"gnatcov_rts_buffers_B_main_2_buffers"); + gnatcov_rts_buffers_B_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_B_pkg_buffers,"gnatcov_rts_buffers_B_pkg_buffers"); + gnatcov_rts_buffers_S_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_S_pkg_buffers,"gnatcov_rts_buffers_S_pkg_buffers"); + List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( + 1 => gnatcov_rts_buffers_B_main_1_buffers'Access, + 2 => gnatcov_rts_buffers_B_main_2_buffers'Access, + 3 => gnatcov_rts_buffers_B_pkg_buffers'Access, + 4 => gnatcov_rts_buffers_S_pkg_buffers'Access); + +end GNATcov_RTS.Buffers.Lists.foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads new file mode 100644 index 000000000..1d0b35bd8 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads @@ -0,0 +1,19 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GNATcov_RTS.Buffers.PB_main_1 is + + pragma Pure; + + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1"); + +end GNATcov_RTS.Buffers.PB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads new file mode 100644 index 000000000..f9f18da05 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads @@ -0,0 +1,19 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GNATcov_RTS.Buffers.PB_main_2 is + + pragma Pure; + + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2"); + +end GNATcov_RTS.Buffers.PB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads new file mode 100644 index 000000000..2f84e5165 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads @@ -0,0 +1,19 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GNATcov_RTS.Buffers.PB_pkg is + + pragma Pure; + + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg"); + +end GNATcov_RTS.Buffers.PB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads new file mode 100644 index 000000000..71406c7f1 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads @@ -0,0 +1,19 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GNATcov_RTS.Buffers.PS_pkg is + + pragma Pure; + + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg"); + +end GNATcov_RTS.Buffers.PS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb new file mode 100644 index 000000000..7a94497f7 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb @@ -0,0 +1,8 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Pkg; + +with GNATcov_RTS.Buffers.PB_main_1;with GNATcov_RTS.Buffers.DB_main_1;with GNATcov_RTS;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +begin + GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_main_1.Statement_Buffer,0);Pkg.Compute (True, False); +GNATcov_RTS.Buffers.DB_main_1.Dump_Buffers;end Main_1; + diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid new file mode 100644 index 0000000000000000000000000000000000000000..255ad5bef91d788cd2cd950cee8283d653c7128c GIT binary patch literal 387 zcmZ?wa|}t&FH=a)NKMWz$j{6xVc=$f07f8SVg$00u_BPKUy@s(A8KS^qHADerkhxl zoS~bWS)resn3)%EsF#?M#K_1DHUg{>SvQOgu>eTcN;4Gh>3KbSU+tE6-SIico_gGa zSr0b>#P|;cF#6NWjcc~nab-6)S%tcq$b5RTKkyICU=Ym)#J*s+fLs9*K?h*fFfFV= xSr#A$(XvpLLLiz6%E3wfgvr3{fEfvL0VFiw)`O(jfjA{KEwMDG1f&zD3jj^aH?9Bx literal 0 HcmV?d00001 diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb new file mode 100644 index 000000000..19b3ac3c0 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb @@ -0,0 +1,8 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Pkg; + +with GNATcov_RTS.Buffers.PB_main_2;with GNATcov_RTS.Buffers.DB_main_2;with GNATcov_RTS;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +begin + GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_main_2.Statement_Buffer,0);Pkg.Compute (True, True); +GNATcov_RTS.Buffers.DB_main_2.Dump_Buffers;end Main_2; + diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid new file mode 100644 index 0000000000000000000000000000000000000000..5f4bce5b445a8722d50b04b2496a8451c8be5a78 GIT binary patch literal 387 zcmZ?wa|}t&FH=a)NKMWz$j{6xVc=$f07f8SVg$00u_BPKUy@s(A8KS^qHADerkhxl zoS~bWS)resn3)%Eq?eeI#K_1DHUg{>SvQOgu>eSZdaKA^xjt*b#D|Z#)(f1!FC{HK z1uh9>fHZ)>e;|O-pI&ZUv$c*ZyRpeC)YU}h)06#ye_#fKXf`1B1-k|03YZBX-7o-F z4b#F36lDQo5G?~$Aq1kCpd6gkPnZnM4w#W37eGP-Zaqkf9f(s>(-KQ_N-pcwsBd!GqU=KM=UKI#_wVKITqn)%|15M=jhkzS^#9EF-sEx1iRUt~T7%O&y z(G0vIcOy4rHtM)D5M8B~5350m{qc;tl21p!DCmn?KnFR@j)yFapqbV58a9%k2Cz?) h|Feds*1O@{_(17jY{m;{U_gA(SbQm3SjjU5`~f3DTsr^& literal 0 HcmV?d00001 diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt new file mode 100644 index 0000000000000000000000000000000000000000..f97e9f4da28c6ff76cc7c8d7cdf5fdc8f1cac8c2 GIT binary patch literal 1878 zcmbtV&ubGw6y8Z{{nd(;s?dY1f?%oB>~2fc(jGjBcqv6&yjdojX|guE87 zPo`7005Q>7nZ+2(9jg1t1;pM&g=9@QfzWsG&_R_o`cWl2d z{pDsHM9MmBSr%jD_))YD0Z9D}#gYn}r3KHKojd*KP@nAimFIDIFN!zC?=ptF^Iy?%VhE_g~isMxXpxoc?@)J$?$@ z7#9C!5FSFJ5+pDr;Lyp)0uFXzH{bodclYJ$ns=kWJbUr#uUB72=LpZt6vzN1kPvzx z8aXM|y#qIAV4JItMm|L!-_(aE)&`%weg5L|L+~=&wR$>>mdRKFNkTMPI%P3^1asry z%rM;%761ShEW{J!up#^zHu7C+AmZuU zNVSA7^*eimCeD7?9G#n9cx{MP*^!O78Olg;)shnU1M*rVl>P$69oZ5!Y4f?IIJUXp zR-qaT{i<(su0*RQ)r@F`T#8CS$hG?=Xf4>UGBNITb}aHPdTnV<~UQ10|v~*Kl||31poj5 literal 0 HcmV?d00001 diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt new file mode 100644 index 0000000000000000000000000000000000000000..6d8d58fee919991e9661b3c759ba00fa266c61f2 GIT binary patch literal 1888 zcmbtV&ubGw6y8Z{{nd(;s?dY1f`?M4*{mhn&>TF7cqv6&yjiE4NwPM(8|x`Uw2oYudTb+`wP>PSAM_vGCD(hshI|80t;w` zgCiQ>X_ zJkT3)m>f0)LJSq?1O0m0mdbb}(F3uoN0&ssdtel5|Ko0NZ;bPSbXiu!ow_nVbA2bW z+VIjNz|IVmw_*(KrY}aM8DoFQ05I0OM`zarsr95aB#mD+0Hs$hu7IJ}A(ltU7yOVX zuX5ECp441k(ZlI2~oxN77`_-D_E6d^Sph2mYXiL8JO)FJpnCoCj zpE_lCT*r)w1hh}*ff;V~)`tz55pvgYU7pW#H*e<)MfZHsaqTh3DLM`iFcbd*nNZiE literal 0 HcmV?d00001 diff --git a/testsuite/tests/U204-026-arch-mix/gen/main_1.srctrace b/testsuite/tests/U204-026-arch-mix/gen/main_1.srctrace new file mode 100644 index 0000000000000000000000000000000000000000..e974fe606809e2446ccda493c4435fcb631ccfa8 GIT binary patch literal 416 zcmZ?wa|}t&FH4VF*7gTkbwav4io|d zW*7rXgVcfmNFN+9GSo^l6z=JHJ$qm6mUrFpIme!Q+~fZAa^sq<|0{w+E&lhk2jgD)LvZ&ss3?;Uli~0_X2bNlQ<`ZJrU_B@8h4f@qLmzzSw-E)l!$Woa=KWT%4-V}%+Cb0^3w z5P+Ev;Xz3zhBfUK&4G@qZp{gwC8zA3u#9hE?G2$l@6Gb(=v94)N`E9?r5rwIXYV1n F`2Z(WWLp3L literal 0 HcmV?d00001 diff --git a/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace b/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace new file mode 100644 index 0000000000000000000000000000000000000000..ef244cfe7684d3d525848372a52cb172a6761f00 GIT binary patch literal 388 zcmZ?wa|}t&FH4VF*7gTh=Bnl&H=hF0O^ARMuu8xhQd8PuV?S8-SVzGKIhm|k9*voUT$2owT>&hvB@gb)kNmg zll_5zAodtSbmB1U(_2OU%Jo?bCO&+`wO-)-eJN?_DY(r7x*6mam^(o<$PZvXBg0CM z5s&#l*8xj>^%fF4*(qB BWLW?J literal 0 HcmV?d00001 diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt new file mode 100644 index 0000000000000000000000000000000000000000..1ddccc5b96d894fca0916193751ec3b474e86839 GIT binary patch literal 1942 zcmb7FJ!lkB5Z-r*iZLWnvB{~dq*212d&_arph8HI6e>{^n}xWyySc1)w|n00C1;V! z!a^It#-Bnh1Vu9kwXv|ym0sW zr_Vi$18+VKrqegD$O%lbtlMG;5dxdAZUq1|7V&V>es;g#T*|igZ|Yb> z0tdsNDivXP_T=&w!pDP3wGq0=0L2gi2iil*rO1^c9$#r*J~j5}{hf2S_6|*)f6#Yt z;TpqWGhqS{L-!m;N_VniFQa6Us0h$3 zN$pC;@y@W=RW>dY=%FJL^Kp-@NI3FPxF+^RE!Z?EWTUM1Q4VUrZt!F%LkdqIdn2U% z29xa~=C38Ab$fUTL(z*zopZ7jl zI&$_k(gsM4Tt=T)_ZzxlWV42T0Qe#)z29epifcMCjs%F>2 zN;q7x9b473x;5u&?N8xR%tAwG@jUc}4AoWUL)$pIRw)3TlnoM+Jv^dodX|2wo*mV7 M`l-XxLp+4-A0zbR)Bpeg literal 0 HcmV?d00001 diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt new file mode 100644 index 0000000000000000000000000000000000000000..51f0e832b41f306029db7f010049ec7ea8ed7d08 GIT binary patch literal 1851 zcmb7FJ!lkB5Z-qe6{93kvB_!JU>WvqZxMr{La;~*f1(&{0&(4Yxtz(~o_Cug7O5;O zv=OxMr%($)5n>_ONJ_C2yI^5Zuo5j|qm4S>?9OIS6VD7cH*e?7H$UJ0yy25WXT6|l zdQ;k)t_789XlyeKL$N9&gGEQ;FpPd$7ec>Q7<26XmhBv{+`2bq`IWhX?^dc4#k^a( zpj1`?xS2HaX5tj>;Le(GCmX~2$gWepHeDucLrMcdE@{0jFzGo45QXaBfv;nQA0$neChALym0aUjSn9?7kb_- z_vUgpu_*uqCwUWg5TQ^+R9MFbL_NJacjffZlXv&d-RavmeEw0_gZZUsEBa42A$|o8 zp~$+GG##WKk9aR0c8{;*-+mi>c4o)XpT}?86w?w6;OKN223Tl1*A}`y7WlQjQQUjz(MhN zpi$V}q!4~&+V_!3=je=a$N@6ZTT1~9EdU_^G4z7KuyjZOI@lgNVc<6uXl7Eg={Ttj zi>ll>1L&e961~ZsNhB70QzR$qA{T6q6tYoPy9k3Eup7KHgkX^gxHs}(_~_fk?IPx{ zEhl+;WDDHVXD1>s1&RF$_lO6zB|YiR&V=$>!EIz&Xemj>qt@~89f(i_=Pxg&fm False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1"); + + Unit_Name : constant String := "main_1"; + Project_Name : constant String := ""; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (125, 27, 0, 113, 188, 140, 235, 155, 190, 125, 180, 238, 139, 95, 108, 198, 229, 72, 222, 11), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), + Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 0, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); + + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_1_buffers"); + +end GNATcov_RTS.Buffers.BB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_2.ads new file mode 100644 index 000000000..fb7e669bc --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_2.ads @@ -0,0 +1,41 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GNATcov_RTS.Buffers.BB_main_2 is + + pragma Preelaborate; + + Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2"); + + Unit_Name : constant String := "main_2"; + Project_Name : constant String := ""; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (242, 237, 33, 15, 121, 175, 106, 160, 145, 225, 226, 10, 175, 16, 207, 223, 26, 27, 27, 148), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), + Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 0, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); + + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_2_buffers"); + +end GNATcov_RTS.Buffers.BB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads new file mode 100644 index 000000000..8d1bde3aa --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads @@ -0,0 +1,41 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GNATcov_RTS.Buffers.BB_pkg is + + pragma Preelaborate; + + Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg"); + + Unit_Name : constant String := "pkg"; + Project_Name : constant String := ""; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), + Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 2, + Decision_Last_Bit => 1, + MCDC_Last_Bit => 2); + + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_pkg_buffers"); + +end GNATcov_RTS.Buffers.BB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads new file mode 100644 index 000000000..4c9260685 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads @@ -0,0 +1,41 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GNATcov_RTS.Buffers.BS_pkg is + + pragma Preelaborate; + + Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg"); + + Unit_Name : constant String := "pkg"; + Project_Name : constant String := ""; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), + Language => Unit_Based_Language, + Unit_Part => Unit_Spec, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), + Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => -1, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); + + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_S_pkg_buffers"); + +end GNATcov_RTS.Buffers.BS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.adb new file mode 100644 index 000000000..18ea1e0ed --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.adb @@ -0,0 +1,15 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Traces.Output.Base64; +with Interfaces.C; +with GNATcov_RTS.Buffers.Lists.foo; +package body GNATcov_RTS.Buffers.DB_main_1 is + + procedure Dump_Buffers is + begin + GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper + (GNATcov_RTS.Buffers.Lists.foo.List, + Program_Name => "main_1", + Exec_Date => 0); + end Dump_Buffers; + +end GNATcov_RTS.Buffers.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads new file mode 100644 index 000000000..ca5c6b54d --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads @@ -0,0 +1,6 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +package GNATcov_RTS.Buffers.DB_main_1 is + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); +end GNATcov_RTS.Buffers.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.adb new file mode 100644 index 000000000..02b84cc6a --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.adb @@ -0,0 +1,15 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Traces.Output.Base64; +with Interfaces.C; +with GNATcov_RTS.Buffers.Lists.foo; +package body GNATcov_RTS.Buffers.DB_main_2 is + + procedure Dump_Buffers is + begin + GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper + (GNATcov_RTS.Buffers.Lists.foo.List, + Program_Name => "main_2", + Exec_Date => 0); + end Dump_Buffers; + +end GNATcov_RTS.Buffers.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads new file mode 100644 index 000000000..06f972268 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads @@ -0,0 +1,6 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +package GNATcov_RTS.Buffers.DB_main_2 is + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); +end GNATcov_RTS.Buffers.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads new file mode 100644 index 000000000..dfb98dbbb --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads @@ -0,0 +1,25 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers.BB_main_1; +with GNATcov_RTS.Buffers.BB_main_2; +with GNATcov_RTS.Buffers.BB_pkg; +with GNATcov_RTS.Buffers.BS_pkg; + +package GNATcov_RTS.Buffers.Lists.foo is + + pragma Preelaborate; + + gnatcov_rts_buffers_B_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_B_main_1_buffers,"gnatcov_rts_buffers_B_main_1_buffers"); + gnatcov_rts_buffers_B_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_B_main_2_buffers,"gnatcov_rts_buffers_B_main_2_buffers"); + gnatcov_rts_buffers_B_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_B_pkg_buffers,"gnatcov_rts_buffers_B_pkg_buffers"); + gnatcov_rts_buffers_S_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_S_pkg_buffers,"gnatcov_rts_buffers_S_pkg_buffers"); + List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( + 1 => gnatcov_rts_buffers_B_main_1_buffers'Access, + 2 => gnatcov_rts_buffers_B_main_2_buffers'Access, + 3 => gnatcov_rts_buffers_B_pkg_buffers'Access, + 4 => gnatcov_rts_buffers_S_pkg_buffers'Access); + +end GNATcov_RTS.Buffers.Lists.foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads new file mode 100644 index 000000000..baf5c0f4c --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads @@ -0,0 +1,19 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GNATcov_RTS.Buffers.PB_main_1 is + + pragma Pure; + + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1"); + +end GNATcov_RTS.Buffers.PB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads new file mode 100644 index 000000000..f40226dce --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads @@ -0,0 +1,19 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GNATcov_RTS.Buffers.PB_main_2 is + + pragma Pure; + + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2"); + +end GNATcov_RTS.Buffers.PB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads new file mode 100644 index 000000000..638a84ec2 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads @@ -0,0 +1,19 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GNATcov_RTS.Buffers.PB_pkg is + + pragma Pure; + + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg"); + +end GNATcov_RTS.Buffers.PB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads new file mode 100644 index 000000000..c8f18f74f --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads @@ -0,0 +1,19 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GNATcov_RTS.Buffers.PS_pkg is + + pragma Pure; + + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg"); + +end GNATcov_RTS.Buffers.PS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb new file mode 100644 index 000000000..61decca75 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb @@ -0,0 +1,8 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Pkg; + +with GNATcov_RTS.Buffers.PB_main_1;with GNATcov_RTS.Buffers.DB_main_1;with GNATcov_RTS;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +begin + GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_main_1.Statement_Buffer,0);Pkg.Compute (True, False); +GNATcov_RTS.Buffers.DB_main_1.Dump_Buffers;end Main_1; + diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid new file mode 100644 index 0000000000000000000000000000000000000000..b5f7a753eb7df7f191cc68d5518e5a7abea5f66d GIT binary patch literal 389 zcmZ?wa|}t&FH=a)NKMWz$j{6xVc=$f07f8SVg$00u`-bFY!y?ITM$!fWMHCeU}UD7 zSd^Tho10k?lbe{C7jLMSn3BZE$P6|FtQA>5j192@NY+X-6z=JHJ$qm6mUrFpIme!Q z+=Dp)ZUTt$9|&Odr literal 0 HcmV?d00001 diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb new file mode 100644 index 000000000..abc8df404 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb @@ -0,0 +1,8 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Pkg; + +with GNATcov_RTS.Buffers.PB_main_2;with GNATcov_RTS.Buffers.DB_main_2;with GNATcov_RTS;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +begin + GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_main_2.Statement_Buffer,0);Pkg.Compute (True, True); +GNATcov_RTS.Buffers.DB_main_2.Dump_Buffers;end Main_2; + diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid new file mode 100644 index 0000000000000000000000000000000000000000..4620b0b2d72e80f0b27da7fbfb1dbaacf7d76911 GIT binary patch literal 389 zcmZ?wa|}t&FH=a)NKMWz$j{6xVc=$f07f8SVg$00u`-bFY!y?ITM$!fWMHCeU}UD7 zSd^Tho10k?lbe{C7jLAOn3BZE$P6|FtQA>5j192@NPc>&$X~fWYr({akGR$goWCz6 zEj_2t2_W4t z09Fmt!U_~+0b&p>163geqM4u^oYYU449pIgksud9LIZ9+NQxbZQ&Q6sOLIy1n7AylI*0fhN z2Rg30H79(QoU(huGQNeiH(-+gfdIrtriJ#rH_M-+SM?z({gHT;a`>E`y@z1xK@P$N zSRoROOdtkCA;^Is7EFW@ECAzyTn&;1yBNd(VNlWl34mx(AO-<&asjEv3x0xA63h%P zpjwz2ATeCjI0i3Gl&M+3RVk? zDioC<|H0e{R|yLpMwpo(dqHM_XlWn@0U;1UI7HxP@Bx*B%mC3cKnwyzngLOaunp!c hkb{A_5ga@qHE81CGzk+2g?CD7T4HHV2}}q?0{~j3UWNbw literal 0 HcmV?d00001 diff --git a/testsuite/tests/U204-026-arch-mix/main_1.adb b/testsuite/tests/U204-026-arch-mix/main_1.adb new file mode 100644 index 000000000..d60a8b539 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/main_1.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_1 is +begin + Pkg.Compute (True, False); +end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/main_2.adb b/testsuite/tests/U204-026-arch-mix/main_2.adb new file mode 100644 index 000000000..ec8ec5d02 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/main_2.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main_2 is +begin + Pkg.Compute (True, True); +end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/pkg.adb b/testsuite/tests/U204-026-arch-mix/pkg.adb new file mode 100644 index 000000000..92d16a2a2 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/pkg.adb @@ -0,0 +1,18 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + ------------- + -- Compute -- + ------------- + + procedure Compute (A, B : Boolean) is + begin + if A and then B then + Put_Line ("true"); + else + Put_Line ("false"); + end if; + end Compute; + +end Pkg; diff --git a/testsuite/tests/U204-026-arch-mix/pkg.ads b/testsuite/tests/U204-026-arch-mix/pkg.ads new file mode 100644 index 000000000..b7f30c150 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Compute (A, B : Boolean); +end Pkg; diff --git a/testsuite/tests/U204-026-arch-mix/test.py b/testsuite/tests/U204-026-arch-mix/test.py new file mode 100644 index 000000000..1d48d7a72 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/test.py @@ -0,0 +1,183 @@ +""" +Check that "gnatcov coverage" can deal with SID and checkpoint files produced +in various cross-configuration scenarios. +""" + +import glob +import os.path + +from e3.env import Env +from e3.fs import cp, mkdir + +from SCOV.instr import xcov_convert_base64 +from SCOV.minicheck import check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import exename_for, gprbuild, gprfor, run_cov_program, xcov + + +src_dir = os.getcwd() +env = Env() +tmp = Wdir("tmp_") + + +def gen_project(name): + """ + Generate in the current directory a project file with the given name for + this testcases' sources. Return its filename as well as its object/exec + directory (computed from the given name). + """ + obj_dir = f"obj-{name}" + p = gprfor( + mains=["main_1.adb", "main_2.adb"], + prjid=name, + srcdirs=[".."], + objdir=obj_dir, + exedir=obj_dir, + ) + return (p, obj_dir) + + +def check_reports(xcov_dir): + """ + Check that the "*.xcov" coverage reports in the given directory have the + expected content. This assumes coverage data from the execution of both + mains. + """ + check_xcov_reports( + "*.xcov", + { + "main_1.adb.xcov": {"+": {5}}, + "main_2.adb.xcov": {"+": {5}}, + "pkg.adb.xcov": {"+": {12, 14}, "!": {11}} + }, + xcov_dir, + ) + + +# Checkpoints were produced in a specific location both on Windows and Linux. +# Use the appropriate source rebasing arguments so that gnatcov can find all +# source files in the testcase's directory. +src_rebase_args = [ + f"--source-rebase=c:\\tmp\\u204-026-arch-mix={src_dir}", + f"--source-rebase=/tmp/U204-026-arch-mix={src_dir}", +] +cov_args = ["coverage", "-cstmt+mcdc", "-axcov"] + src_rebase_args + + +# +# 1. Check that we can instrument on one host and build+run+coverage on another +# + +# The instrumentation part was done in "gen.sh". Restore SIDs and instrumented +# sources for the two cases to test and do the build+run+coverage. +for name, gen_dir_name in [("win", "x86_64-windows"), + ("linux", "arm-elf-linux")]: + thistest.log(f"== 1. {name} ==") + + # Generate a dedicated project for this + p, obj_dir = gen_project(name) + + instr_dir = os.path.join(obj_dir, f"{name}-gnatcov-instr") + mkdir(obj_dir) + mkdir(instr_dir) + + # Copy SIDs and instrumented sources where expected in its object directory + gen_dir = os.path.join("..", "gen", gen_dir_name) + cp(os.path.join(gen_dir, "*.sid"), obj_dir) + cp(os.path.join(gen_dir, "*.ad*"), instr_dir) + + # Build and run the instrumented program, collecting source traces + traces = [] + gprbuild(p, trace_mode="src") + for main in ["main_1", "main_2"]: + out_file = f"{name}-{main}-out.txt" + run_cov_program( + executable=exename_for(os.path.join(obj_dir, main)), out=out_file + ) + + trace_file = f"{name}-{main}.srctrace" + xcov_convert_base64(out_file, trace_file) + traces.append(trace_file) + + # Finally, generate and check the coverage report from these traces + xcov(cov_args + ["-P", p] + traces) + check_reports(obj_dir) + + +# +# 2. Check that we can mix checkpoints created from source traces even when +# these source traces were produced for different targets, possibly from +# different hosts. +# + +thistest.log("== 2. src-checkpoints mix ==") +mkdir("2-xcov") +xcov( + cov_args + + ["--output-dir=2-xcov"] + + [f"--checkpoint={os.path.join('..', 'gen', ckpt)}" + for ckpt in ["src-main_1.ckpt", "src-main_2.ckpt"]] +) +check_reports("2-xcov") + + +# +# 3. Reject mix of checkpoints created with binary traces for different +# "bits-target" (32 vs 64-bit). +# + +thistest.log("== 3. bin-checkpoints mix ==") +mkdir("3-xcov") +p = xcov( + cov_args + + ["--output-dir=3-xcov"] + + [f"--checkpoint={os.path.join('..', 'gen', ckpt)}" + for ckpt in ["bin-main_1.ckpt", "bin-main_2.ckpt"]], + out="3-coverage-out.txt", + register_failure=False, +) +thistest.fail_if( + p.status == 0, + "'gnatcov coverage' exited with status code 0 while an error was expected" +) + +# Since the checkpoint for main_1 was created for 32-bits while the checkpoint +# for main_2 was created for 64-bits, the error message depends on the target +# platform for which we run the testsuite. +if env.target.cpu.bits == 32: + ckpt = "bin-main_2.ckpt" + ckpt_bits = "64-bit" + req_bits = "32-bit" +else: + assert env.target.cpu.bits == 64 + ckpt = "bin-main_1.ckpt" + ckpt_bits = "32-bit" + req_bits = "64-bit" +thistest.fail_if_no_match( + "'gnatcov coverage' output", + f".*gnatcov.*: .*{ckpt} was created with {ckpt_bits} traces whereas the" + f" selected target requires {req_bits} traces", + contents_of("3-coverage-out.txt"), +) + +# +# 4. Check that we can use source traces produced on a different host +# + +thistest.log("== 3. src-traces mix ==") +mkdir("4-xcov") +sid_list = "sids.txt" +with open(sid_list, "w") as f: + for sid in sorted(glob.glob(os.path.join("..", "gen", "*", "*.sid"))): + f.write(os.path.abspath(sid)) + f.write("\n") +xcov( + cov_args + + ["--output-dir=4-xcov", f"--sid=@{sid_list}"] + + [os.path.join("..", "gen", f"main_{i}.srctrace") for i in range(1, 3)], + out="4-coverage-out.txt", +) +check_reports("4-xcov") + +thistest.result() diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_1.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_1.adb new file mode 100644 index 000000000..b150ed2fc --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_1.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; Use Ada.Text_IO; + +with Pkg1; + +procedure Disjoint_Main_1 is +begin + Put_Line ("Pkg1.Fn1 (True) :" & Integer'Image (Pkg1.Fn1 (True))); + Put_Line ("Pkg1.Fn1 (False):" & Integer'Image (Pkg1.Fn1 (False))); +end Disjoint_Main_1; \ No newline at end of file diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_2.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_2.adb new file mode 100644 index 000000000..d950ac46f --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_2.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; Use Ada.Text_IO; + +with Pkg2; + +procedure Disjoint_Main_2 is +begin + Put_Line ("Pkg2.Fn2 (True) :" & Integer'Image (Pkg2.Fn2 (True))); + Put_Line ("Pkg2.Fn2 (False):" & Integer'Image (Pkg2.Fn2 (False))); +end Disjoint_Main_2; \ No newline at end of file diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_1.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_1.adb new file mode 100644 index 000000000..9fd15ef6e --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_1.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; Use Ada.Text_IO; + +with Pkg1; +with Pkg2; + +procedure Intersecting_Main_1 is +begin + Put_Line ("Pkg1.Fn1 (True):" & Integer'Image (Pkg1.Fn1 (True))); + Put_Line ("Pkg2.Fn2 (True):" & Integer'Image (Pkg2.Fn2 (True))); +end Intersecting_Main_1; \ No newline at end of file diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_2.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_2.adb new file mode 100644 index 000000000..ac77f98a1 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_2.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; Use Ada.Text_IO; + +with Pkg1; +with Pkg2; + +procedure Intersecting_Main_2 is +begin + Put_Line ("Pkg1.Fn1 (False):" & Integer'Image (Pkg1.Fn1 (False))); + Put_Line ("Pkg2.Fn2 (False):" & Integer'Image (Pkg2.Fn2 (False))); +end Intersecting_Main_2; \ No newline at end of file diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.adb new file mode 100644 index 000000000..839be84f5 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.adb @@ -0,0 +1,15 @@ +package body Pkg1 is + + X : Integer := 0; + pragma Volatile(X); + + function Fn1 (B : Boolean) return Integer is + begin + if B then + return X - 1; + else + return x + 1; + end if; + end Fn1; + +end Pkg1; \ No newline at end of file diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.ads b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.ads new file mode 100644 index 000000000..9568ad0c6 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.ads @@ -0,0 +1,5 @@ +package Pkg1 is + + function Fn1 (B : Boolean) return Integer; + +end Pkg1; \ No newline at end of file diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.adb new file mode 100644 index 000000000..dd261a064 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.adb @@ -0,0 +1,15 @@ +package body Pkg2 is + + Y : Integer := 42; + pragma Volatile (Y); + + function Fn2 (B : Boolean) return Integer is + begin + if B then + return Y - 1; + else + return Y + 1; + end if; + end Fn2; + +end Pkg2; \ No newline at end of file diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.ads b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.ads new file mode 100644 index 000000000..f4f9f7b07 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.ads @@ -0,0 +1,5 @@ +package Pkg2 is + + function Fn2 (B : Boolean) return Integer; + +end Pkg2; \ No newline at end of file diff --git a/testsuite/tests/U204-029-source-rebase/Ada/test.py b/testsuite/tests/U204-029-source-rebase/Ada/test.py new file mode 100644 index 000000000..63b28ca19 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/Ada/test.py @@ -0,0 +1,80 @@ +""" +Test the behaviour of the --source-rebase option under various configurations +for Ada projects. +""" + +from SUITE.context import thistest +from test_support import run_variant + +# Test that specifiying a wrong rebase prefix still outputs warnings about +# files not found. +run_variant( + variant_basename="no_src", + mains_list=["disjoint_main_1.adb"], + units_lists=[["Pkg1"]], + origin_src_dir="src", + expected_xcov_results={}, + rebase_dir="/some/random/dir", + expect_failure=True, + suppress_src_dir=True, +) + +# Test that specifying a wrong rebase prefix outputs no warning if the original +# sources are still on the disk. +run_variant( + variant_basename="no_coverage_src", + mains_list=["disjoint_main_1.adb"], + units_lists=[["Pkg1"]], + origin_src_dir="src", + expected_xcov_results={"pkg1.adb.xcov": {'+': {8, 9, 11}}}, + rebase_dir="/some/random/dir", +) + +# Check the absence of warnings when the source rebase does redirect to +# existing sources. +run_variant( + variant_basename="simple", + mains_list=["disjoint_main_1.adb"], + units_lists=[["Pkg1"]], + origin_src_dir="src", + expected_xcov_results={"pkg1.adb.xcov": {'+': {8, 9, 11}}}, + suppress_src_dir=True, +) + +# Check that source rebase is done correctly when rebasing sources from two +# checkpoints, concerning disjoint set of sources for each checkpoint. +run_variant( + variant_basename="disjoint", + mains_list=["disjoint_main_1.adb", "disjoint_main_2.adb"], + units_lists=[["Pkg1"], ["Pkg2"]], + origin_src_dir="src", + expected_xcov_results={ + "pkg1.adb.xcov": {'+': {8, 9, 11}}, + "pkg2.adb.xcov": {'+': {8, 9, 11}} + }, + suppress_src_dir=True, +) + +# Check that source rebase is done correctly when rebasing sources from two +# checkpoints, where the set of sources from each checkpoint is overlapping. +# In particular, check that gnatcov doesn't consider that a same file coming +# from two different checkpoints is two separate files. +# +# This is also useful to check that source-rebase actually rebases when both +# the original and the rebase source files exist. Indeed, if GNATcoverage did +# not rebase, we would get ``Warning: same base name for files`` as both +# checkpoints would hold the same units, with the same base name but with a +# different full name. As by default, warnings are registered as errors in a +# test execution, this would fail. +run_variant( + variant_basename="intersecting", + mains_list=["intersecting_main_1.adb", "intersecting_main_2.adb"], + units_lists=[["Pkg1", "Pkg2"]] * 2, + origin_src_dir="src", + expected_xcov_results={ + "pkg1.adb.xcov": {'+': {8, 9, 11}}, + "pkg2.adb.xcov": {'+': {8, 9, 11}} + }, +) + +thistest.result() diff --git a/testsuite/tests/U204-029-source-rebase/C/src/a/pkg.h b/testsuite/tests/U204-029-source-rebase/C/src/a/pkg.h new file mode 100644 index 000000000..ef1db960f --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/C/src/a/pkg.h @@ -0,0 +1,13 @@ + +static int +return_a_number (int x) +{ + if (x < 0) + { + return x - 3; + } + else + { + return x + 2; + } +} diff --git a/testsuite/tests/U204-029-source-rebase/C/src/b/pkg.h b/testsuite/tests/U204-029-source-rebase/C/src/b/pkg.h new file mode 100644 index 000000000..316e0af4b --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/C/src/b/pkg.h @@ -0,0 +1,13 @@ + +static int +return_some_number (int x) +{ + if (x < 0) + { + return x - 1; + } + else + { + return x + 1; + } +} diff --git a/testsuite/tests/U204-029-source-rebase/C/src/main1.c b/testsuite/tests/U204-029-source-rebase/C/src/main1.c new file mode 100644 index 000000000..e67ea1dac --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/C/src/main1.c @@ -0,0 +1,10 @@ +#include "a/pkg.h" +#include "b/pkg.h" + +int +main () +{ + volatile int dummy = return_a_number (2); + dummy = return_some_number (2); + return 0; +} diff --git a/testsuite/tests/U204-029-source-rebase/C/src/main2.c b/testsuite/tests/U204-029-source-rebase/C/src/main2.c new file mode 100644 index 000000000..cfb93caea --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/C/src/main2.c @@ -0,0 +1,10 @@ +#include "a/pkg.h" +#include "b/pkg.h" + +int +main () +{ + volatile int dummy = return_a_number (-3); + dummy = return_some_number (-1); + return 0; +} diff --git a/testsuite/tests/U204-029-source-rebase/C/test.opt b/testsuite/tests/U204-029-source-rebase/C/test.opt new file mode 100644 index 000000000..41ff4f9fb --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/C/test.opt @@ -0,0 +1 @@ +src-traces XFAIL C instrumentation does not yet support header analysis. diff --git a/testsuite/tests/U204-029-source-rebase/C/test.py b/testsuite/tests/U204-029-source-rebase/C/test.py new file mode 100644 index 000000000..8fc1ab830 --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/C/test.py @@ -0,0 +1,28 @@ +""" +Test the behaviour of the --source-rebase option under various configurations +for C projects. +""" + +from SUITE.context import thistest +from test_support import run_variant + + +# Check that source rebase is done correctly when rebasing sources from two +# checkpoints, where the set of sources from each checkpoint is overlapping. +# In particular, check that gnatcov doesn't consider that a same file comming +# from two different checkpoints is two separate files. +run_variant( + variant_basename="intersecting", + mains_list=["main1.c", "main2.c"], + units_lists=[["main1.c", ], ["main2.c"]], + origin_src_dir="src", + expected_xcov_results={ + "main1.c.xcov": {"+": {7, 8, 9}}, + "main2.c.xcov": {"+": {7, 8, 9}}, + "a-pkg.h.xcov": {"+": {5, 7, 11}}, + "b-pkg.h.xcov": {"+": {5, 7, 11}} + }, +) + + +thistest.result() diff --git a/testsuite/tests/U204-029-source-rebase/test_support.py b/testsuite/tests/U204-029-source-rebase/test_support.py new file mode 100644 index 000000000..f142d6a5f --- /dev/null +++ b/testsuite/tests/U204-029-source-rebase/test_support.py @@ -0,0 +1,160 @@ +import os +import shutil + +from e3.fs import cp, mkdir + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.cutils import Wdir, contents_of, empty +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +def out_of_source_checkpoint( + variant_name, main, units, origin_src_dir, suppress_src_dir +): + """ + Create a checkpoint with a copy of the sources in origin_src_dir, using + main as the main program and units as the list of units of interest. + + This operates on a copy of the given sources, the copies are deleted after + the checkpoint creation if suppress_src_dir is True, so that gnatcov cannot + find the source in their original location when producing a report. + + Returns the name of the created checkpoint and the absolute path to the + directory where the sources were when creating the checkpoint. + """ + local_src_dir = f"src_{variant_name}" + cp(origin_src_dir, local_src_dir, recursive=True) + checkpoint_name = f"{main}.ckpt" + + build_run_and_coverage( + gprsw=GPRswitches( + gprfor(mains=[main], + srcdirs=local_src_dir, + objdir="obj"), + units=units), + covlevel="stmt", + mains=[os.path.splitext(main)[0]], + extra_coverage_args=[f"--save-checkpoint={checkpoint_name}"]) + + if suppress_src_dir: + shutil.rmtree(local_src_dir) + + return (checkpoint_name, os.path.abspath(local_src_dir)) + + +def consolidate_and_check(variant_basename, + expected_xcov_results, + expect_failure, + checkpoints, + rebase_opts, + output_dir_name): + """ + Consolidate the given set of checkpoints and create xcov reports. + The xcov reports are checked against expected_xcov_results, and if + expect_failure is True, check that gnatcov emits warnings concerning files + not found. Otherwise check that gnatcov does not emmit any warnings. + """ + log_filename = f"coverage-{output_dir_name}.log" + mkdir(output_dir_name) + xcov(["coverage", "-cstmt", "-axcov", f"--output-dir={output_dir_name}"] + + [f"-C{checkpoint}" for checkpoint in checkpoints] + + rebase_opts, + out=log_filename) + + if expect_failure: + thistest.fail_if_no_match( + f"'gnatcov coverage' output ({variant_basename}-{output_dir_name})", + r"^(warning: can't open .*\n)+$", + contents_of(log_filename)) + else: + thistest.fail_if( + not empty(log_filename), + f"'gnatcov coverage' output ({variant_basename}-{output_dir_name})" + " not empty:\n " + contents_of(log_filename) + ) + + check_xcov_reports( + os.path.join(output_dir_name, "*.xcov"), + {os.path.join(output_dir_name, filename): results + for filename, results in expected_xcov_results.items()} + ) + + +def run_variant(variant_basename, + mains_list, + units_lists, + origin_src_dir, + expected_xcov_results, + rebase_dir=None, + expect_failure=False, + suppress_src_dir=False): + """ + Create a set of checkpoints using, for checkpoint i, the sources in + origin_src_dir, the main in mains_list[i] and the units in units_lists[i]. + If suppress_src_dir is True, remove the created source directory that is a + copy of origin_src_dir. + + Try to rebase the source to rebase_dir if specified, or to origin_src_dir + otherwise. + """ + origin_src_dir = os.path.abspath(origin_src_dir) + + wd = Wdir(f"tmp_{variant_basename}") + # If no rebase_dir is specified, use origin_src_dir as the place to search + # for sources after rebase. + if rebase_dir is None: + rebase_dir = origin_src_dir + else: + rebase_dir = os.path.abspath(rebase_dir) + + # Create a checkpoint for each set of main/units_of_interest and retrieve + # the checkpoint's name, as well as the path to the source directory used + # to create said checkpoint. + checkpoints, prefixes = zip(*[ + out_of_source_checkpoint( + f"{variant_basename}_{i}", main, units, origin_src_dir, + suppress_src_dir) + for i, (main, units) in enumerate(zip(mains_list, units_lists)) + ]) + + # Test individual options passed to gnatcov for each checkpoint + consolidate_and_check( + variant_basename, + expected_xcov_results, + expect_failure, + checkpoints, + rebase_opts=[ + f"--source-rebase={prefix}={rebase_dir}" for prefix in prefixes], + output_dir_name="simple" + ) + + # Test using one globbing pattern to specify source rebase for all + # checkpoints. + glob_pattern = os.path.join(wd.homedir, "*", "src_*") + consolidate_and_check( + variant_basename, + expected_xcov_results, + expect_failure, + checkpoints, + rebase_opts=[f"--source-rebase={glob_pattern}={rebase_dir}"], + output_dir_name="globbing_pattern" + ) + + # Test using a response file to specify source rebase for all checkpoints + response_file_name = "src-rebase.txt" + + with open(response_file_name, 'w') as f: + f.writelines([f"{prefix}={rebase_dir}\n" for prefix in prefixes]) + + consolidate_and_check( + variant_basename, + expected_xcov_results, + expect_failure, + checkpoints, + rebase_opts=[f"--source-rebase=@{response_file_name}"], + output_dir_name="response_file" + ) + + wd.to_homedir() diff --git a/testsuite/tests/U208-020-child-project/p-child-src/main.adb b/testsuite/tests/U208-020-child-project/p-child-src/main.adb new file mode 100644 index 000000000..13844d0f9 --- /dev/null +++ b/testsuite/tests/U208-020-child-project/p-child-src/main.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Main is +begin + if Pkg.Foo (True) then + null; + end if; +end; diff --git a/testsuite/tests/U208-020-child-project/p-child.gpr b/testsuite/tests/U208-020-child-project/p-child.gpr new file mode 100644 index 000000000..7bb2061ed --- /dev/null +++ b/testsuite/tests/U208-020-child-project/p-child.gpr @@ -0,0 +1,7 @@ +with "p"; + +project P.Child is + for Source_Dirs use ("p-child-src"); + for Main use ("main.adb"); + for Object_Dir use "obj/p-child"; +end P.Child; diff --git a/testsuite/tests/U208-020-child-project/p-src/pkg.adb b/testsuite/tests/U208-020-child-project/p-src/pkg.adb new file mode 100644 index 000000000..46672538f --- /dev/null +++ b/testsuite/tests/U208-020-child-project/p-src/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + function Foo (B : Boolean) return Boolean is + begin + return B; + end Foo; + +end Pkg; diff --git a/testsuite/tests/U208-020-child-project/p-src/pkg.ads b/testsuite/tests/U208-020-child-project/p-src/pkg.ads new file mode 100644 index 000000000..9ffbd4f6b --- /dev/null +++ b/testsuite/tests/U208-020-child-project/p-src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + function Foo (B : Boolean) return Boolean; +end Pkg; diff --git a/testsuite/tests/U208-020-child-project/p.gpr b/testsuite/tests/U208-020-child-project/p.gpr new file mode 100644 index 000000000..6ef24db5d --- /dev/null +++ b/testsuite/tests/U208-020-child-project/p.gpr @@ -0,0 +1,4 @@ +project P is + for Source_Dirs use ("p-src"); + for Object_Dir use "obj/p"; +end P; diff --git a/testsuite/tests/U208-020-child-project/test.opt b/testsuite/tests/U208-020-child-project/test.opt new file mode 100644 index 000000000..e42397385 --- /dev/null +++ b/testsuite/tests/U208-020-child-project/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific behavior \ No newline at end of file diff --git a/testsuite/tests/U208-020-child-project/test.py b/testsuite/tests/U208-020-child-project/test.py new file mode 100644 index 000000000..6c62622cf --- /dev/null +++ b/testsuite/tests/U208-020-child-project/test.py @@ -0,0 +1,30 @@ +""" +This test checks that the instrumentation of a child project produces valid +instrumented sources. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + +p_gpr = os.path.abspath('p-child.gpr') +obj_dir = os.path.abspath('obj/p-child') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') +check_xcov_reports('xcov/*.xcov', + {'xcov/main.adb.xcov': {'+': {5, 6}}, + 'xcov/pkg.adb.xcov': {'+': {5}}}) + +thistest.result() diff --git a/testsuite/tests/U208-020-error-call/main.c b/testsuite/tests/U208-020-error-call/main.c new file mode 100644 index 000000000..b919edf78 --- /dev/null +++ b/testsuite/tests/U208-020-error-call/main.c @@ -0,0 +1,8 @@ +#include + +int +main () +{ + errno = ENOENT; + return 0; +} diff --git a/testsuite/tests/U208-020-error-call/test.opt b/testsuite/tests/U208-020-error-call/test.opt new file mode 100644 index 000000000..6aa810fbc --- /dev/null +++ b/testsuite/tests/U208-020-error-call/test.opt @@ -0,0 +1 @@ +!RTS_FULL DEAD Uses errno, which is not defined in embedded / light runtimes diff --git a/testsuite/tests/U208-020-error-call/test.py b/testsuite/tests/U208-020-error-call/test.py new file mode 100644 index 000000000..ecea0f505 --- /dev/null +++ b/testsuite/tests/U208-020-error-call/test.py @@ -0,0 +1,26 @@ +""" +This test checks that dumping traces with errno set to a non-zero value +works. It can be the case in user code if a system call fails. + +The source traces dump used to crash as we were checking the errno value +to check for an I/O error when writing the trace file (instead of checking +that we had a valid file descriptor for instance). +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(prjid="p", srcdirs=[".."], mains=["main.c"], langs=["C"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"]) + +check_xcov_reports('obj/main.c.xcov', {'obj/main.c.xcov': {'+': {6, 7}}}) +thistest.result() diff --git a/testsuite/tests/U208-020-unique-language-project/main.adb b/testsuite/tests/U208-020-unique-language-project/main.adb new file mode 100644 index 000000000..4fe1236da --- /dev/null +++ b/testsuite/tests/U208-020-unique-language-project/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end; diff --git a/testsuite/tests/U208-020-unique-language-project/main.c b/testsuite/tests/U208-020-unique-language-project/main.c new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/U208-020-unique-language-project/main.c @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/U208-020-unique-language-project/test.opt b/testsuite/tests/U208-020-unique-language-project/test.opt new file mode 100644 index 000000000..e42397385 --- /dev/null +++ b/testsuite/tests/U208-020-unique-language-project/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific behavior \ No newline at end of file diff --git a/testsuite/tests/U208-020-unique-language-project/test.py b/testsuite/tests/U208-020-unique-language-project/test.py new file mode 100644 index 000000000..fe8404224 --- /dev/null +++ b/testsuite/tests/U208-020-unique-language-project/test.py @@ -0,0 +1,51 @@ +""" +This test checks that the instrumentation of an Ada project produces +only Ada files. Likewise for C. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.control import LANGINFO +from SUITE.cutils import ext, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor( + prjid="ada_prj", srcdirs=[".."], + mains=["main.adb"], langs=["Ada"] + )), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"]) + +for f in os.listdir("obj/ada_prj-gnatcov-instr"): + if ext(f) not in LANGINFO["Ada"].src_ext: + thistest.failed( + f"{f} is not an Ada source. Instrumentation " + "of an Ada project should only produce Ada files.") + break + +check_xcov_reports('obj/main.adb.xcov', {'obj/main.adb.xcov': {'+': {3}}}) + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(prjid="c_prj", srcdirs=[".."], mains=["main.c"], langs=["C"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"]) + +for f in os.listdir("obj/c_prj-gnatcov-instr"): + if ext(f) not in LANGINFO["C"].src_ext: + thistest.failed( + f"{f} is not a C source. Instrumentation " + "of a C project should only produce C files.") + break + +check_xcov_reports('obj/main.c.xcov', {'obj/main.c.xcov': {'+': {4}}}) +thistest.result() diff --git a/testsuite/tests/U211-014-setup/ext_rt/ext_rt.gpr b/testsuite/tests/U211-014-setup/ext_rt/ext_rt.gpr new file mode 100644 index 000000000..f5b9ed954 --- /dev/null +++ b/testsuite/tests/U211-014-setup/ext_rt/ext_rt.gpr @@ -0,0 +1,4 @@ +project Ext_RT extends "gnatcov_rts" is + for Object_Dir use "obj" & GNATcov_RTS'Object_Dir; + for Library_Dir use "obj" & GNATcov_RTS'Library_Dir; +end Ext_RT; diff --git a/testsuite/tests/U211-014-setup/ext_rt/gnatcov_rts-base_io.adb b/testsuite/tests/U211-014-setup/ext_rt/gnatcov_rts-base_io.adb new file mode 100644 index 000000000..4e0b62c37 --- /dev/null +++ b/testsuite/tests/U211-014-setup/ext_rt/gnatcov_rts-base_io.adb @@ -0,0 +1,47 @@ +with GNAT.IO; + +package body GNATcov_RTS.Base_Io is + + Printed_Tag : Boolean := False; + + function Dummy_Predicate return Boolean; + procedure Print_Tag; + + --------------------- + -- Dummy_Predicate -- + --------------------- + + function Dummy_Predicate return Boolean is + begin + GNAT.IO.Put_Line (""); + GNAT.IO.New_Line; + return True; + end Dummy_Predicate; + + --------------- + -- Print_Tag -- + --------------- + + procedure Print_Tag is + begin + if not Printed_Tag then + Printed_Tag := True; + pragma Assert (Dummy_Predicate); + GNAT.IO.Put_Line (""); + GNAT.IO.New_Line; + end if; + end Print_Tag; + + --------- + -- Put -- + --------- + + procedure Put (S : GNATcov_RTS_String) is + Str : String (1 .. Integer (S.Length)); + for Str'Address use S.Str; + begin + Print_Tag; + GNAT.IO.Put_Line (Str); + end Put; + +end GNATcov_RTS.Base_Io; diff --git a/testsuite/tests/U211-014-setup/src-ada/foo.adb b/testsuite/tests/U211-014-setup/src-ada/foo.adb new file mode 100644 index 000000000..3072b68a4 --- /dev/null +++ b/testsuite/tests/U211-014-setup/src-ada/foo.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("Hello world!"); +end Foo; diff --git a/testsuite/tests/U211-014-setup/src-c/foo.c b/testsuite/tests/U211-014-setup/src-c/foo.c new file mode 100644 index 000000000..ef8f6dc90 --- /dev/null +++ b/testsuite/tests/U211-014-setup/src-c/foo.c @@ -0,0 +1,8 @@ +#include + +int +main (void) +{ + puts ("Hello, world!"); + return 0; +} diff --git a/testsuite/tests/U211-014-setup/src-mixed/bar.c b/testsuite/tests/U211-014-setup/src-mixed/bar.c new file mode 100644 index 000000000..c55b18592 --- /dev/null +++ b/testsuite/tests/U211-014-setup/src-mixed/bar.c @@ -0,0 +1,13 @@ +typedef void (*put_char_ptr) (char c); + +void +bar (put_char_ptr put_char) +{ + const char *message = "Hello, world!"; + int i; + + for (i = 0; message[i]; ++i) + { + put_char (message[i]); + } +} diff --git a/testsuite/tests/U211-014-setup/src-mixed/foo.adb b/testsuite/tests/U211-014-setup/src-mixed/foo.adb new file mode 100644 index 000000000..86c85ce33 --- /dev/null +++ b/testsuite/tests/U211-014-setup/src-mixed/foo.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +with Pkg; + +procedure Foo is + + procedure Bar (Put_Char : Pkg.Put_Char_Access); + pragma Import (C, Bar, "bar"); + +begin + Bar (Pkg.Put_Char'Access); +end; diff --git a/testsuite/tests/U211-014-setup/src-mixed/pkg.adb b/testsuite/tests/U211-014-setup/src-mixed/pkg.adb new file mode 100644 index 000000000..4c3ac6781 --- /dev/null +++ b/testsuite/tests/U211-014-setup/src-mixed/pkg.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Put_Char (C : Character) is + begin + Put (C); + end Put_Char; + +end Pkg; diff --git a/testsuite/tests/U211-014-setup/src-mixed/pkg.ads b/testsuite/tests/U211-014-setup/src-mixed/pkg.ads new file mode 100644 index 000000000..e2c00043b --- /dev/null +++ b/testsuite/tests/U211-014-setup/src-mixed/pkg.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Pkg is + + type Put_Char_Access is + access procedure (C : Character); + pragma Convention (C, Put_Char_Access); + + procedure Put_Char (C : Character); + pragma Export (C, Put_Char, "pkg_put_char"); + +end Pkg; diff --git a/testsuite/tests/U211-014-setup/test.py b/testsuite/tests/U211-014-setup/test.py new file mode 100644 index 000000000..4864a0f6d --- /dev/null +++ b/testsuite/tests/U211-014-setup/test.py @@ -0,0 +1,260 @@ +""" +Check that the "gnatcov setup" command works as expected. + +Note that all tests use a non-standard project name for the installed +instrumentation runtime project, as a way to avoid checks working just because +they actually use the runtime project already present in the testsuite +environment. + +Also note that, due to the testsuite infrastructure, we cannot test the +"default prefix", i.e. letting gprinstall put the instrumentation runtime +project in the toolchain prefix, as the testsuite is not allowed to modify it. +""" + +from dataclasses import dataclass +import os.path +from typing import List, Dict, Set + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprbuild, gprfor, xcov +from SUITE.gprutils import GPRswitches + + +# Project file for an extended runtime +rt_ext_file = os.path.join(os.path.abspath("ext_rt"), "ext_rt.gpr") + + +tmp = Wdir("tmp_") + +# Name of the installed instrumentation runtime project +rt_prj = "rt_prj" + +# Installation directory for the instrumentation runtime project and directory +# for the project path. +rt_install_dir = os.path.abspath("install") +rt_path_dir = os.path.join(rt_install_dir, "share", "gpr") + +# Make this install available to GPR tools +env.add_search_path("GPR_PROJECT_PATH", rt_path_dir) + +ExpectedCov = Dict[str, Dict[str, Set[int]]] + + +@dataclass +class PrjConfig: + """ + Project file, executable name and expected coverage report. + """ + project_file: str + objdir: str + expected_cov: ExpectedCov + + @classmethod + def create(cls, + tag: str, + langs: List[str], + main: str, + expected_cov: ExpectedCov): + objdir = f"obj-{tag}" + return cls( + project_file=gprfor( + prjid=f"{tag}_prj", + langs=langs, + mains=[main], + srcdirs=[f"../src-{tag}"], + objdir=objdir, + ), + objdir=objdir, + expected_cov=expected_cov, + ) + + @property + def gprsw(self): + return GPRswitches(root_project=self.project_file) + + +# Create simple projects to host our experiments +ada_prj = PrjConfig.create( + tag="ada", langs=["Ada"], main="foo.adb", + expected_cov={"foo.adb.xcov": {"+": {5}}}, +) +c_prj = PrjConfig.create( + tag="c", langs=["C"], main="foo.c", + expected_cov={"foo.c.xcov": {"+": {6, 7}}}, +) +mixed_prj = PrjConfig.create( + tag="mixed", langs=["Ada", "C"], main="foo.adb", + expected_cov={ + "foo.adb.xcov": {"+": {11}}, + "pkg.ads.xcov": {"+": {5, 6}}, + "pkg.adb.xcov": {"+": {7}}, + "bar.c.xcov": {"+": {6}}, + }, +) + + +def xsetup(args, out, register_failure=True, auto_config_args=True): + """ + "xcov" wrapper to run "gnatcov setup". + + This wrapper just automatically pass --install-name and --prefix + arguments. + """ + return xcov( + ["setup", f"--install-name={rt_prj}", f"--prefix={rt_install_dir}"] + + args, + out=out, + register_failure=register_failure, + auto_config_args=auto_config_args, + force_project_args=True, + ) + + +def check_full(label, setup_args, prj_config, runtime_project=rt_prj, + dump_channel="auto", auto_config_args=True): + """ + Run "gnatcov setup" with the arguments (setup_args), then compute code + coverage and check the report for the given project (prj_config). + + Also check that `gnatcov instrument` successfully loaded the setup + configuration file. + """ + thistest.log(f"== {label} ==") + xsetup(setup_args, f"setup-{label}.txt", auto_config_args=auto_config_args) + build_run_and_coverage( + gprsw=prj_config.gprsw, + covlevel="stmt", + mains=["foo"], + gpr_obj_dir=prj_config.objdir, + extra_coverage_args=["-axcov", f"--output-dir=xcov-{label}"], + trace_mode="src", + runtime_project=runtime_project, + dump_channel=dump_channel, + extra_instr_args=["-v"] + ) + thistest.fail_if( + "Successfully loaded the setup configuration file" + not in contents_of("instrument.log"), + "Failed to load the setup config file in `gnatcov instrument`") + check_xcov_reports("*.xcov", prj_config.expected_cov, f"xcov-{label}") + + +# "gnatcov setup" (+ relevant target options) is supposed to work out of the +# box and use most of the RTS capabilities. +check_full("basic-mixed", [], mixed_prj) + +# Check that --restricted-to-languages works as expected +check_full("basic-ada", ["--restricted-to-languages=Ada,C"], ada_prj) + +# Our current testsuite runs use Ada runtimes, which do not provide fwrite and +# other similar routines on embedded targets. This means that we cannot test +# our C-only instrumentation runtime on these targets. +# +# Do not pass the testsuite project configuration file to gnatcov setup as it +# was generated for Ada, C and C++, and thus defines Ada specific attributes +# (such as the runtime directory) which would not normally be present in a C +# only project. +if not env.is_cross: + check_full( + "basic-c", + ["--restricted-to-languages=C"], + c_prj, + auto_config_args=False, + ) + +# The core runtime is implemented in C, so C must be enabled +thistest.log("== ada-only ==") +log_file = "setup-ada-only.txt" +p = xsetup(["--restricted-to-languages=Ada"], + log_file, + register_failure=False) +thistest.fail_if(p.status == 0, + "gnatcov setup succeeded when we expected it to fail") +thistest.fail_if_no_match( + log_file, + '.*The C language must be enabled.*', + contents_of(log_file), +) + +# ... so also check that misusing it fails, as expected too: the previous tests +# could fail because --restricted-to-languages is actually ignored (and thus +# the installed runtime always support both Ada and C). Here, we check that +# actually have an error when trying to build instrumented Ada code while the +# runtime has support for C only. +# +# Same remark as above concerning the configuration file. +thistest.log("== basic-bad-lang ==") +log_file = "gprbuild-basic-bad-lang.txt" +xsetup( + ["--restricted-to-languages=C"], + "setup-basic-bad-lang.txt", + auto_config_args=False, +) +xcov_instrument( + gprsw=mixed_prj.gprsw, + covlevel="stmt", + runtime_project=rt_prj, + out="instr-basic-bad-lang.txt" +) +p = gprbuild( + mixed_prj.project_file, + gargs=["--src-subdirs=gnatcov-instr"], + trace_mode="src", + runtime_project=rt_prj, + out=log_file, + register_failure=False, +) +thistest.fail_if(p.status == 0, + "gprbuild succeeded when we expected it to fail") +thistest.fail_if_no_match( + log_file, + '.*foo.adb:.*"gnatcov_rts.ads" not found.*', + contents_of(log_file), +) + +# Check the installation of an alternative runtime project. Our modified +# runtime (designed for base64-stdout only) just prints a "Hello, world", so we +# can check that our modified runtime is correctly used looking at the main +# output. +# +# Accept just the hello world message or more, as the output may contain a +# base64 trace depending on the testsuite mode. +check_full("ext_rt", [rt_ext_file], ada_prj, dump_channel="base64-stdout") +thistest.fail_if( + "" not in contents_of("foo_output.txt"), + " not in the program output", +) + +# Now, check that -gargs arguments are passed to gprbuild. To do this, build +# the instrumentation runtime with -gnata. This will make GNAT compile with +# assertions enabled (they are disabled by default), and will thus trigger the +# execution of a Put_Line that is otherwise disabled. +check_full( + "ext_rt", + [rt_ext_file, "-gargs", "-cargs:Ada", "-gnata"], + ada_prj, + dump_channel="base64-stdout", +) +thistest.fail_if( + "" not in contents_of("foo_output.txt"), + " not in the program output", +) + +# Check C89 backward-compatibility, as we want to support instrumentation +# with older toolchains. +check_full("ext_rt", [rt_ext_file, "-gargs", "-cargs:C", "-std=c89"], + ada_prj, dump_channel="base64-stdout") + +# Check that passing a full path to --runtime-project works +check_full( + "full_path", + [], + ada_prj, + runtime_project=os.path.join(rt_path_dir, rt_prj), +) + +thistest.result() diff --git a/testsuite/tests/U219-010-ali-entry-guard-sloc/main.adb b/testsuite/tests/U219-010-ali-entry-guard-sloc/main.adb new file mode 100644 index 000000000..eadb48f5c --- /dev/null +++ b/testsuite/tests/U219-010-ali-entry-guard-sloc/main.adb @@ -0,0 +1,29 @@ +procedure Main is + + task type My_Task is + entry P1; + entry P2; + entry P3; + end My_Task; + + task body My_Task is + begin + select + accept P1 do + null; + end P1; + or when (not True) => + accept P2 do + null; + end P2; + or + accept P3 do + null; + end P3; + end select; + end My_Task; + + T : My_Task; +begin + T.P1; +end Main; diff --git a/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt new file mode 100644 index 000000000..a34c07f1d --- /dev/null +++ b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt @@ -0,0 +1 @@ +!native DEAD Uses full runtime only constructs diff --git a/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py new file mode 100644 index 000000000..cad97dfe2 --- /dev/null +++ b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py @@ -0,0 +1,29 @@ +""" +Regression test for source location of dominance markers referencing +decisions in entry guards. It used to be wrong in ali files. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports, checked_xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) + +# Check that there is no warning + +checked_xcov(xcov_args, "coverage.log") + +check_xcov_reports("obj/*.xcov", { + "obj/main.adb.xcov": {"+": {11, 12, 13}, "-": {16, 17, 20, 21}}, +}) + +thistest.result() diff --git a/testsuite/tests/U219-010-wrong-sloc-dominant-decision/main.adb b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/main.adb new file mode 100644 index 000000000..ba8b55b4c --- /dev/null +++ b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/main.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + if True then + Put_Line ("Hello World"); + end if; +end Main; diff --git a/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.opt b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.opt new file mode 100644 index 000000000..0a73d5eda --- /dev/null +++ b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.opt @@ -0,0 +1 @@ +src-traces DEAD Test SCOs in ALI files diff --git a/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.py b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.py new file mode 100644 index 000000000..878d36606 --- /dev/null +++ b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.py @@ -0,0 +1,45 @@ +""" +Check that gnatcov does not crash on wrong source location for dominance +information. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +tmp = Wdir("tmp_") + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], + mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) + +# Artificially create wrong source locations to check that gnatcov does +# not crash on these. + +with open('obj/main.ali', 'r') as f: + content = f.read() + assert "CS >T5:4 6:7-6:17" in content + content = content.replace(">T5:4", ">T5:5") + +with open('obj/main.ali', 'w') as f: + f.write(content) + +xcov(xcov_args, out="coverage.log") + +# Check that a warning is issued + +thistest.fail_if_not_equal( + "gnatcov coverage output", + "!!! main.adb:6:7: dominant decision of statement SCO #4: STATEMENT " + "at main.adb:6:7-17 has no associated SCO, discarding dominance " + "information\n", + contents_of("coverage.log")) + +thistest.result() diff --git a/testsuite/tests/U317-004-xml-report/main.adb b/testsuite/tests/U317-004-xml-report/main.adb new file mode 100644 index 000000000..78cf5e255 --- /dev/null +++ b/testsuite/tests/U317-004-xml-report/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello"); +end Main; diff --git a/testsuite/tests/U317-004-xml-report/test.py b/testsuite/tests/U317-004-xml-report/test.py new file mode 100644 index 000000000..5b68660be --- /dev/null +++ b/testsuite/tests/U317-004-xml-report/test.py @@ -0,0 +1,29 @@ +""" +Check that the right column numbers are output for a statement coverage +obligation in the XML report. +""" +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains="main.adb")), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-a", "xml"]) + +if thistest.options.trace_mode == 'src': + expected_match = \ + '' +else: + expected_match = \ + '' + +thistest.fail_if(expected_match not in contents_of('obj/main.adb.xml')) +thistest.result() diff --git a/testsuite/tests/U416-006-big-bdd/src/compute.c b/testsuite/tests/U416-006-big-bdd/src/compute.c new file mode 100644 index 000000000..82101e1a3 --- /dev/null +++ b/testsuite/tests/U416-006-big-bdd/src/compute.c @@ -0,0 +1,7 @@ +int +c_compute (int c1, int c2, int c3, int c4, int c5, int c6, int c7, int c8) +{ + return ((((((((c1 || c2) && c3) || c4) && c5) || c6) && c7) || c8) + && (((((((c1 || c2) && c3) || c4) && c5) || c6) && c7) || c8) + && (((((((c1 || c2) && c3) || c4) && c5) || c6) && c7) || c8)); +} diff --git a/testsuite/tests/U416-006-big-bdd/src/test_eval.adb b/testsuite/tests/U416-006-big-bdd/src/test_eval.adb new file mode 100644 index 000000000..760da21af --- /dev/null +++ b/testsuite/tests/U416-006-big-bdd/src/test_eval.adb @@ -0,0 +1,21 @@ +with Ada.Text_IO; + +with Interfaces.C; use Interfaces.C; + +with TestConditions; + +procedure Test_Eval is + function C_Compute (C1, C2, C3, C4, C5, C6, C7, C8 : int) return int; + pragma Import (C, C_Compute); + + Dummy : int; +begin + Ada.Text_IO.Put_Line ("Hello_World"); + TestConditions.Run; + + -- Exercize both outcomes so that conditions are labeled with undetermined + -- coverage. + + Dummy := C_Compute (0, 0, 0, 0, 0, 0, 0, 0); + Dummy := C_Compute (0, 0, 0, 0, 0, 0, 0, 1); +end Test_Eval; diff --git a/testsuite/tests/U416-006-big-bdd/src/testconditions.adb b/testsuite/tests/U416-006-big-bdd/src/testconditions.adb new file mode 100644 index 000000000..4fb4c9f44 --- /dev/null +++ b/testsuite/tests/U416-006-big-bdd/src/testconditions.adb @@ -0,0 +1,31 @@ +with Ada.Text_IO; + +package body TestConditions is + + C1 : Boolean := False; + C2 : Boolean := False; + C3 : Boolean := True; + C4 : Boolean := False; + C5 : Boolean := True; + C6 : Boolean := False; + C7 : Boolean := False; + C8 : Boolean := True; + + function Is_Activated return Boolean is + begin + return + ((((((((((((((( C1 or else C2 ) and then C3 ) or else (( C1 or else C2 ) and then C3 )) or else ((( C4 or else C1 ) or else C2 ) and then C3 )) or else ((( C4 or else C1 ) or else C2 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else (( C7 or else C1 ) and then C3 )) or else (( C7 or else C1 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else (( C1 or else C7 ) and then C3 )) or else ((((( C5 or else C6 ) or else C4 ) or else C1 ) or else C7 ) and then C3 )) or else (( C5 or else C8 ) and then C3 ); + end Is_Activated; + + procedure Run is + begin + if Is_Activated then + Ada.Text_IO.Put_Line ("Is Activated"); + C3 := False; + C5 := False; + C8 := False; + Run; + end if; + end Run; + +end TestConditions; diff --git a/testsuite/tests/U416-006-big-bdd/src/testconditions.ads b/testsuite/tests/U416-006-big-bdd/src/testconditions.ads new file mode 100644 index 000000000..485fe0e62 --- /dev/null +++ b/testsuite/tests/U416-006-big-bdd/src/testconditions.ads @@ -0,0 +1,5 @@ +package TestConditions is + + procedure Run; + +end TestConditions; diff --git a/testsuite/tests/U416-006-big-bdd/test.py b/testsuite/tests/U416-006-big-bdd/test.py new file mode 100644 index 000000000..84dd20643 --- /dev/null +++ b/testsuite/tests/U416-006-big-bdd/test.py @@ -0,0 +1,69 @@ +""" +Check that gnatcov (instrument/run/coverage) successfully handles very big +decisions in MC/DC. For such decisions with an overly large BDD path count, the +tool is simply expected not to instrument the decision and thus report +undetermined MC/DC coverage for it. +""" + +import re + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +gpr = gprfor(mains=["test_eval.adb"], srcdirs=["../src"], langs=["Ada", "C"]) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + extra_coverage_args=["--annotate=xcov"], + covlevel="stmt+mcdc", + mains=["test_eval"], + trace_mode="src", + tolerate_instrument_messages=\ + "Number of distinct paths .* exceeds the limit", +) + +check_xcov_reports( + "*.xcov", + expected_cov={ + "test_eval.adb.xcov": {"+": {11, 13, 19, 20}}, + "testconditions.adb.xcov": {"?": {17}, "+": {22, 23, 24, 25, 26, 27}}, + "compute.c.xcov": {"?": {4}, "+": {5, 6}}, + }, + cwd="obj", +) + + +def warning_re_for(filename, sloc): + """ + Return a regexp for the warning expected for the given file name and source + location. + """ + return ( + r"\*\*\* {filename}:{sloc}: warning: Number of distinct paths in the" + r" decision exceeds the limit \(\d+\)\. MC/DC coverage for this" + r" decision will be left undetermined in coverage reports\. Use option" + r" --path-count-limit to adjust the limit if the default value is too" + r" low\." + ).format(filename=re.escape(filename), sloc=re.escape(sloc)) + + +# The order in which sources are instrumented is not specified, so sort lines +# in the output of "gnatcov instrument" to get deterministic test execution. +log = "\n".join(sorted(contents_of("instrument.log").splitlines())) + +thistest.fail_if_no_match( + what="Unexpected/missing warnings for MC/DC path limit", + regexp="^" + "\n".join([ + warning_re_for("compute.c", "4:11"), + warning_re_for("testconditions.adb", "17:9"), + ]), + actual=log, +) + +thistest.result() diff --git a/testsuite/tests/U527-020-dc-from-mcdc/main.adb b/testsuite/tests/U527-020-dc-from-mcdc/main.adb new file mode 100644 index 000000000..c3064790a --- /dev/null +++ b/testsuite/tests/U527-020-dc-from-mcdc/main.adb @@ -0,0 +1,8 @@ +procedure Main is + X : Integer := 12; + pragma Volatile (X); +begin + if X < 0 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/U527-020-dc-from-mcdc/test.py b/testsuite/tests/U527-020-dc-from-mcdc/test.py new file mode 100644 index 000000000..74fc09df1 --- /dev/null +++ b/testsuite/tests/U527-020-dc-from-mcdc/test.py @@ -0,0 +1,42 @@ +""" +Test that stmt+decision analysis is allowed and functional +on top of stmt+mcdc instrumentation. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov, gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir('tmp_') + +gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) + +# Instrument, build and produce a trace for stmt+mcdc on a very simple +# program. Retrieve the base arguments that we would need to pass to gnatcov +# coverage for an analysis of the same SCOs at that --level: + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gpr), + extra_coverage_args=[], + covlevel='stmt+mcdc', + mains=['main'], + trace_mode='src') + +# Switch to --level=stmt+decision, add the arguments for the +# output format/location then check that we can produce a report: + +xcov_args = [ + '--level=stmt+decision' if arg.startswith('--level') else arg + for arg in xcov_args] + +xcov_args.extend(['--annotate=xcov', '--output-dir=xcov']) + +xcov(xcov_args) + +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'+': {2}, '!': {5}, '-': {6}}, +}) + +thistest.result() diff --git a/testsuite/tests/U630-040-static-decision/src/p.ads b/testsuite/tests/U630-040-static-decision/src/p.ads new file mode 100644 index 000000000..61bc4dfee --- /dev/null +++ b/testsuite/tests/U630-040-static-decision/src/p.ads @@ -0,0 +1,30 @@ +pragma Ada_2012; + +package P is + subtype Priority is Integer range 10 .. 20; + + FUNNY_PRIO : constant Integer := 999; + + USE_FUNNY_PRIO : constant Boolean := False; + -- constant boolean to guard out of range computation + + Base_Prio : Priority := + (if USE_FUNNY_PRIO then FUNNY_PRIO - 1 else Priority'First); -- # eval + + -- When instrumenting, the tool needs to prevent a Witness call on + -- the static USE_FUNNY_PRIO. Such a call would make the if-expr control + -- non-static, which would get the compiler to evaluate both possible + -- values and error out on FUNNY_PRIO - 1 with: + -- + -- error: value not in range of type "Priority" defined at line 4 + -- error: static expression fails Constraint_Check + + -- And likewise for mcdc conditions: + + FORCE_BASE_PRIO : constant Boolean := False; + + function Prio_Val return Priority is + (if USE_FUNNY_PRIO and then not FORCE_BASE_PRIO -- # complex + then FUNNY_PRIO + else Base_Prio); +end P; diff --git a/testsuite/tests/U630-040-static-decision/src/test_p.adb b/testsuite/tests/U630-040-static-decision/src/test_p.adb new file mode 100644 index 000000000..2ef0dff68 --- /dev/null +++ b/testsuite/tests/U630-040-static-decision/src/test_p.adb @@ -0,0 +1,27 @@ +with P; + +procedure Test_P is + Prio : P.Priority := P.Prio_Val; + pragma Volatile (Prio); +begin + if Prio /= P.Priority'First then + raise Program_Error; + end if; +end; + +-- The "complex" decision case, even though involving a +-- static expression as well, is provided through an expression +-- function for which the compiler generates code. +-- +-- The simpler "eval" case boils down to a static constant, +-- for which no code at all is visible to binary traces. + +--# p.ads +-- +-- /complex/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /eval/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /eval/ l+ ## 0 diff --git a/testsuite/tests/U630-040-static-decision/test.opt b/testsuite/tests/U630-040-static-decision/test.opt new file mode 100644 index 000000000..0635bc667 --- /dev/null +++ b/testsuite/tests/U630-040-static-decision/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Missing feature (if expression) in GNAT 5.04 +7.1.2 DEAD expression functions support weak in GNAT 7.1.2 \ No newline at end of file diff --git a/testsuite/tests/U630-040-static-decision/test.py b/testsuite/tests/U630-040-static-decision/test.py new file mode 100644 index 000000000..d0218cecf --- /dev/null +++ b/testsuite/tests/U630-040-static-decision/test.py @@ -0,0 +1,17 @@ +""" +This test checks that gnatcov correctly deals with static decisions. The +instrumenter used to produce code triggering constraint violations as it +made such decisions not static anymore by wrapping them in witness calls. + +Also check that the inner conditions are not wrapped in witness calls, as +this too renders the expression non-static. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.decision).run() +TestCase(category=CAT.mcdc).run() + +thistest.result() diff --git a/testsuite/tests/U811-028-suppress-output/main.adb b/testsuite/tests/U811-028-suppress-output/main.adb new file mode 100644 index 000000000..e55ea674d --- /dev/null +++ b/testsuite/tests/U811-028-suppress-output/main.adb @@ -0,0 +1,14 @@ +procedure Main is + + Bool1 : Boolean := False; + pragma Volatile (Bool1); + + Bool2 : Boolean := True; + pragma Volatile (Bool2); + + Res : Boolean; + pragma Volatile (Res); + +begin + Res := Bool1 or else Bool2; +end Main; \ No newline at end of file diff --git a/testsuite/tests/U811-028-suppress-output/test.py b/testsuite/tests/U811-028-suppress-output/test.py new file mode 100644 index 000000000..f6231b383 --- /dev/null +++ b/testsuite/tests/U811-028-suppress-output/test.py @@ -0,0 +1,123 @@ +""" +Check that --cancel-annotate prevents the emmission of a coverage +report. +""" + +import os +from os import listdir +from os.path import exists + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of, empty +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +p = gprfor( + mains=["main.adb"], + srcdirs=[".."], + extra='package Coverage is' + '\n for Switches ("Coverage") use ("--annotate=report");' + '\nend Coverage;\n' +) + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p), + gpr_obj_dir="obj", + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=[], +) + +# check that specifying --cancel-annotate without specifying +# --save-checkpoint is not allowed. + +# As the gnatcov command is a full path by default on windows, we will +# explicitely specify it to avoid spurious diffs. +env = dict(os.environ) +env.update({"GNATCOV_CMD": "gnatcov"}) + +process = xcov( + args=xcov_args + ["--cancel-annotate"], + register_failure=False, + out="no-save-checkpoint.txt", + env=env, +) + +thistest.fail_if( + process.status == 0, + comment="Gnatcov returned 0 with --cancel-annotate" + " and no --save-checkpoint option specified", +) +thistest.fail_if_not_equal( + what="Unexpected error message from gnatcov", + expected="gnatcov: Please specify --save-checkpoint on the command line" + " when --cancel-annotate is also specified.\n" + "Usage: gnatcov coverage [OPTIONS] TRACE_FILEs\n" + "Run 'gnatcov coverage --help' for more information.\n", + actual=contents_of("no-save-checkpoint.txt"), +) + +# Check that specifying --cancel-annotate suppresses the emission +# of a coverage report specified in the project file but a checkpoint +# is still emitted. + +xcov(xcov_args + ["--cancel-annotate", "--save-checkpoint=prj_attr.ckpt"], + out='suppress-report-project-file.txt') +thistest.fail_if( + not empty("suppress-report-project-file.txt"), + comment="report output not suppressed (from project file)" +) +thistest.fail_if( + not exists("prj_attr.ckpt"), + comment="Checkpoint file does not exist (project attribute)" +) + + +# Check that specifying --cancel-annotate with --annotate=report on the command +# line does suppress the report output. + +xcov( + args=xcov_args + + [ + "--annotate=report", + "--cancel-annotate", + "--save-checkpoint=cmd_line_report.ckpt", + ], + out="suppress-report.txt", +) + +thistest.fail_if( + not empty("suppress-report.txt"), + comment="report output not suppressed (from command line)" +) +thistest.fail_if( + not exists("cmd_line_report.ckpt"), + comment="Checkpoint file does not exists (--annotate=report)" +) + +# Check that specifying --annotate=supress-output with --annotate=xcov on the +# command line does prevent the creation of .xcov files. + +xcov( + xcov_args + + [ + "--annotate=xcov", + "--output-dir=xcov", + "--cancel-annotate", + "--save-checkpoint=cmd_line_xcov.ckpt", + ] +) + +thistest.fail_if( + len(listdir("xcov")) > 0, + comment="xcov report produced with --cancel-annotate", +) +thistest.fail_if( + not exists("cmd_line_xcov.ckpt"), + comment="Checkpoint file does not exist (--annotate=xcov)" +) + +thistest.result() diff --git a/testsuite/tests/U901-029-estamps/main.adb b/testsuite/tests/U901-029-estamps/main.adb new file mode 100644 index 000000000..c3064790a --- /dev/null +++ b/testsuite/tests/U901-029-estamps/main.adb @@ -0,0 +1,8 @@ +procedure Main is + X : Integer := 12; + pragma Volatile (X); +begin + if X < 0 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/U901-029-estamps/test.opt b/testsuite/tests/U901-029-estamps/test.opt new file mode 100644 index 000000000..6da46e6e4 --- /dev/null +++ b/testsuite/tests/U901-029-estamps/test.opt @@ -0,0 +1 @@ +src-traces,!native DEAD checking trace stamp, no way to get from BB programs diff --git a/testsuite/tests/U901-029-estamps/test.py b/testsuite/tests/U901-029-estamps/test.py new file mode 100644 index 000000000..eeab9f5f8 --- /dev/null +++ b/testsuite/tests/U901-029-estamps/test.py @@ -0,0 +1,65 @@ +""" +Check that the command execution and trace creation dates +advertised in reports look reasonable. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +import re +from datetime import date + +tmp = Wdir('tmp_') + +gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) + +# Build, run, and analyze to produce a "report" output, then verify that the +# dates advertised in the report are consistent with what we perceive is the +# current date. + +report = 'report' + +xcov_args = build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + extra_coverage_args=["--annotate=report", "-o", report], + covlevel='stmt', + mains=['main']) + +# We expect to find two items mentioning the date: +# +# Date and time of execution: 2021-09-15 20:20:50 +02:00 +# +# Then: +# +# Trace files: +# +# main.trace +# ... +# date : 2021-09-15 20:20:50 +02:00 +# +# Fetch the date components and check: + +today = date.today().isoformat() + +report = contents_of(report) + +date_re = r"\d{4}-\d{2}-\d{2}" + +for pattern in ( + r"Date.*execution: (?P%s)" % date_re, + r"date *: (?P%s)" % date_re +): + m = re.search(pattern=pattern, string=report) + + thistest.fail_if( + not m, + "couldn't find a match for pattern '%s' in report" % pattern) + + thistest.fail_if( + m.group('date') != today, + "date found (%s) doesn't match today (%s)" % (m.group('date'), today)) + +thistest.result() diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.adb b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.adb new file mode 100644 index 000000000..832e755c2 --- /dev/null +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.adb @@ -0,0 +1,13 @@ +package body Pkg is + + Ret_Val : Boolean; -- # decl + pragma Volatile (Ret_Val); + + function Foo return Boolean is + begin + return Ret_Val; -- # fun + end Foo; + +begin + Ret_Val := A or else C; -- # elab_body +end Pkg; \ No newline at end of file diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.ads b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.ads new file mode 100644 index 000000000..5d5d8bc1f --- /dev/null +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.ads @@ -0,0 +1,13 @@ +package Pkg is + + A : Boolean := False; -- # decl + pragma Volatile (A); + B : Boolean := True; -- # decl + pragma Volatile (B); + + function Foo return Boolean; + + C : Boolean := A and then B; -- # elab_spec + pragma Volatile (C); + +end Pkg; \ No newline at end of file diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.adb b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.adb new file mode 100644 index 000000000..366dca18b --- /dev/null +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.adb @@ -0,0 +1,12 @@ +package body Pkh is + + function Bar (X : Boolean) return Boolean is + + package Inner_Bar is + Res_Val : Boolean := X and then C; -- # elab_fun + end Inner_Bar; + + begin + return Inner_Bar.Res_Val; + end Bar; +end Pkh; \ No newline at end of file diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.ads b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.ads new file mode 100644 index 000000000..b26bb2526 --- /dev/null +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.ads @@ -0,0 +1,11 @@ +package Pkh is + A : constant Boolean := True; + + B : constant Boolean := False; + + C : Boolean := A and then B; -- elab_spec + + function Bar (X : Boolean) return Boolean; + +end Pkh; +pragma Preelaborate (Pkh); diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/test_elab.adb b/testsuite/tests/UA21-030-elab_mcdc_state/src/test_elab.adb new file mode 100644 index 000000000..c854c3e0e --- /dev/null +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/test_elab.adb @@ -0,0 +1,28 @@ +with Pkg; use Pkg; +with Pkh; use Pkh; + +procedure Test_Elab is + Dummy : Boolean; + pragma Volatile (Dummy); +begin + Dummy := Bar (Foo); +end Test_Elab; + +--# pkg.ads +-- +-- /decl/ l+ ## 0 +-- /elab_spec/ l! ## eT- + +--# pkg.adb +-- +-- /decl/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /elab_body/ l! ## eT- + +--# pkh.adb +-- +-- /elab_spec/ l. ## 0 + +--# pkh.adb +-- +-- /elab_fun/ l! ## eT- \ No newline at end of file diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/test.py b/testsuite/tests/UA21-030-elab_mcdc_state/test.py new file mode 100644 index 000000000..4d9cc8388 --- /dev/null +++ b/testsuite/tests/UA21-030-elab_mcdc_state/test.py @@ -0,0 +1,12 @@ +""" +Test that decisions in elaboration code (both declarations and package body +statments) are proprely instrumented for MCDC. +""" + + +from SCOV.tc import TestCase +from SUITE.context import thistest +from SCOV.tctl import CAT + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/a/main.adb b/testsuite/tests/UB18-055-switches-in-gprfile/a/main.adb new file mode 100644 index 000000000..6d9c9e0c6 --- /dev/null +++ b/testsuite/tests/UB18-055-switches-in-gprfile/a/main.adb @@ -0,0 +1,6 @@ +with B; + +procedure Main is +begin + B.Plop; +end Main; diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/b/b.adb b/testsuite/tests/UB18-055-switches-in-gprfile/b/b.adb new file mode 100644 index 000000000..e44832103 --- /dev/null +++ b/testsuite/tests/UB18-055-switches-in-gprfile/b/b.adb @@ -0,0 +1,8 @@ +with C; + +package body B is + procedure Plop is + begin + C.Plop; + end Plop; +end B; diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/b/b.ads b/testsuite/tests/UB18-055-switches-in-gprfile/b/b.ads new file mode 100644 index 000000000..7306088a1 --- /dev/null +++ b/testsuite/tests/UB18-055-switches-in-gprfile/b/b.ads @@ -0,0 +1,3 @@ +package B is + procedure Plop; +end B; diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/c/c.adb b/testsuite/tests/UB18-055-switches-in-gprfile/c/c.adb new file mode 100644 index 000000000..ba627c0fb --- /dev/null +++ b/testsuite/tests/UB18-055-switches-in-gprfile/c/c.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; + +package body C is + procedure Plop is + begin + Ada.Text_IO.Put_Line ("Plop"); + end Plop; +end C; diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/c/c.ads b/testsuite/tests/UB18-055-switches-in-gprfile/c/c.ads new file mode 100644 index 000000000..834e07b09 --- /dev/null +++ b/testsuite/tests/UB18-055-switches-in-gprfile/c/c.ads @@ -0,0 +1,3 @@ +package C is + procedure Plop; +end C; diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/test.py b/testsuite/tests/UB18-055-switches-in-gprfile/test.py new file mode 100644 index 000000000..ef6ffc0fd --- /dev/null +++ b/testsuite/tests/UB18-055-switches-in-gprfile/test.py @@ -0,0 +1,43 @@ +""" +This regression test checks that we consider the --projects / --no-subproject +switches when they are given in a project file Coverage.Switches attribute. +""" + +import os + +from SUITE.tutils import gprfor +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports + +tmp = Wdir('tmp_') + +gpr_coverage_package = """ + package Coverage is + for Switches ("coverage") use ("--level=stmt+decision", + "--projects", "b", + "--no-subprojects"); + end Coverage; +""" + +a_gpr = gprfor(mains=["main.adb"], prjid="a", srcdirs=os.path.join("..", "a"), + objdir="obj-a", deps=["b"], extra=gpr_coverage_package) +b_gpr = gprfor(mains=[], prjid="b", srcdirs=os.path.join("..", "b"), + langs=["Ada"], objdir="obj-b", deps=["c"]) +c_gpr = gprfor(mains=[], prjid="c", srcdirs=os.path.join("..", "c"), + langs=["Ada"], objdir="obj-c") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=a_gpr), + covlevel='stmt', + mains=["main"], + gpr_obj_dir="obj-a", + extra_coverage_args=['-axcov', "--output-dir=."]) + +# Check that we have coverage result only for the project of interest, as +# specified in the gpr file. + +check_xcov_reports("*.xcov", {"b.adb.xcov": {"+": {6}}}) + +thistest.result() diff --git a/testsuite/tests/V120-034-dup-langs/main.adb b/testsuite/tests/V120-034-dup-langs/main.adb new file mode 100644 index 000000000..c3064790a --- /dev/null +++ b/testsuite/tests/V120-034-dup-langs/main.adb @@ -0,0 +1,8 @@ +procedure Main is + X : Integer := 12; + pragma Volatile (X); +begin + if X < 0 then + raise Program_Error; + end if; +end; diff --git a/testsuite/tests/V120-034-dup-langs/test.py b/testsuite/tests/V120-034-dup-langs/test.py new file mode 100644 index 000000000..99244db59 --- /dev/null +++ b/testsuite/tests/V120-034-dup-langs/test.py @@ -0,0 +1,30 @@ +""" +Check that we handle duplication and casing differences for language names in +--restricted-to-languages. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) + +xcov_args = build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + extra_coverage_args=["--annotate=xcov"], + extra_instr_args=["--restricted-to-languages=Ada,ada"], + covlevel="stmt", + mains=["main"], + trace_mode="src", +) + +check_xcov_reports("obj/*.xcov", { + "obj/main.adb.xcov": {"+": {2, 5}, "-": {6}}, +}) + +thistest.result() diff --git a/testsuite/tests/V201-010-multi-report/main.adb b/testsuite/tests/V201-010-multi-report/main.adb new file mode 100644 index 000000000..83fcc87e6 --- /dev/null +++ b/testsuite/tests/V201-010-multi-report/main.adb @@ -0,0 +1,8 @@ +procedure Main is + X : Integer := 12; + pragma Volatile (X); +begin + if X < 0 then + raise Program_Error; + end if; +end Main; diff --git a/testsuite/tests/V201-010-multi-report/test.py b/testsuite/tests/V201-010-multi-report/test.py new file mode 100644 index 000000000..935ee49a9 --- /dev/null +++ b/testsuite/tests/V201-010-multi-report/test.py @@ -0,0 +1,55 @@ +""" +Check that gnatcov correctly produces multiple reports when requested +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +import os + + +tmp = Wdir("tmp_") + +gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) + +xcov_args = build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + extra_coverage_args=["--annotate=report,xcov,dhtml", + "--annotate=xml"], + covlevel="stmt", + mains=["main"], + out="coverage.log" +) + +# For the xcov report kind we can check the actual content +check_xcov_reports("obj/xcov/*.xcov", { + "obj/xcov/main.adb.xcov": {"+": {2, 5}, "-": {6}}, +}) + +# Check that there is a report in the log of the coverage command +thistest.fail_if_no_match( + what="did not find report in the coverage output", + regexp=r'(.|\n)*' + r'\n\*\* COVERAGE REPORT \*\*' + r'(.|\n)*' + r'\n\*\* END OF REPORT \*\*', + actual=contents_of('coverage.log') +) + +# For the others, we'll fall back to checking that there are files produced +# in the expected directories + +thistest.fail_if( + not os.path.exists("obj/html/main.adb.hunk.js"), + "no html report produced" +) + +thistest.fail_if( + not os.path.exists("obj/xml/main.adb.xml"), + "no xml report produced" +) + +thistest.result() diff --git a/testsuite/tests/V304-007-missing-files/baz.adb b/testsuite/tests/V304-007-missing-files/baz.adb new file mode 100644 index 000000000..a44560963 --- /dev/null +++ b/testsuite/tests/V304-007-missing-files/baz.adb @@ -0,0 +1,6 @@ +with Bar; + +procedure Baz is +begin + Bar.Do_Things; +end Baz; diff --git a/testsuite/tests/V304-007-missing-files/foo.adb b/testsuite/tests/V304-007-missing-files/foo.adb new file mode 100644 index 000000000..973507ac2 --- /dev/null +++ b/testsuite/tests/V304-007-missing-files/foo.adb @@ -0,0 +1,7 @@ +with Bar, Baz; + +procedure Foo is +begin + Baz; + Bar.Do_Things; +end Foo; diff --git a/testsuite/tests/V304-007-missing-files/test.opt b/testsuite/tests/V304-007-missing-files/test.opt new file mode 100644 index 000000000..46bf1b3c9 --- /dev/null +++ b/testsuite/tests/V304-007-missing-files/test.opt @@ -0,0 +1,3 @@ +-- This test intentionally misses source files, so the instrumenter gets +-- errors from Libadalang (turned into noisy warnings). +all-warnings DEAD diff --git a/testsuite/tests/V304-007-missing-files/test.py b/testsuite/tests/V304-007-missing-files/test.py new file mode 100644 index 000000000..38a95ddc7 --- /dev/null +++ b/testsuite/tests/V304-007-missing-files/test.py @@ -0,0 +1,34 @@ +""" +Check that "gnatcov instrument" warns about missing files. +""" + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") +gpr = gprfor(mains=["foo.adb"], srcdirs=[".."]) +mkdir("obj") + +xcov_instrument( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt", + out="instrument.log", + tolerate_messages=".", +) + +thistest.fail_if_not_equal( + what="'gnatcov instrument' output", + expected=( + "warning: While instrumenting baz.adb...\n" + "warning: Cannot find required source file: bar.ads\n" + ), + actual=contents_of("instrument.log"), +) + +thistest.result() diff --git a/testsuite/tests/V309-017-setup-config/foo.adb b/testsuite/tests/V309-017-setup-config/foo.adb new file mode 100644 index 000000000..3072b68a4 --- /dev/null +++ b/testsuite/tests/V309-017-setup-config/foo.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Foo is +begin + Put_Line ("Hello world!"); +end Foo; diff --git a/testsuite/tests/V309-017-setup-config/test.opt b/testsuite/tests/V309-017-setup-config/test.opt new file mode 100644 index 000000000..11b852e4b --- /dev/null +++ b/testsuite/tests/V309-017-setup-config/test.opt @@ -0,0 +1,4 @@ +-- This test needs to check that --dump-channel is properly handled in a +-- typical gnatcov usage workflow. To do this, it needs multiple dump channels +-- to be supported, i.e. a native platform (bin-file and base64-stdout). +!native DEAD diff --git a/testsuite/tests/V309-017-setup-config/test.py b/testsuite/tests/V309-017-setup-config/test.py new file mode 100644 index 000000000..624c9a1ff --- /dev/null +++ b/testsuite/tests/V309-017-setup-config/test.py @@ -0,0 +1,106 @@ +""" +Check that dump options passed to "gnatcov setup" are used as defaults for the +subsequent "gnatcov instrument" using the installed instrumentation runtime. + +Note that for test simplicity, here we only check this for --dump-channel: dump +config code being shared in gnatcov, in principle it should work for all other +--dump-* options (there are lots of such options and checking that they are +used is not trivial). +""" + +import json +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Installation directory for the instrumentation runtime projects and directory +# for the project path. +rt_install_dir = os.path.abspath("install") +rt_path_dir = os.path.join(rt_install_dir, "share", "gpr") + +# Make this install available to GPR tools +env.add_search_path("GPR_PROJECT_PATH", rt_path_dir) + + +def xsetup(install_name, args): + """ + "xcov" wrapper to run "gnatcov setup". + + This wrapper just automatically passes --install-name and --prefix + arguments. + """ + xcov( + [ + "setup", + f"--install-name={install_name}", + f"--prefix={rt_install_dir}" + ] + args, + force_project_args=True, + ) + + +# Test project to instrument +prj = gprfor(srcdirs=[".."], mains=["foo.adb"]) + +# Install two runtime projects, each with different dump-channel defaults. The +# default is --dump-channel=bin-file. +for rt_name, dump_args in [ + ("rt_def", []), + ("rt_b64", ["--dump-channel=base64-stdout"]), +]: + xsetup(rt_name, dump_args) + +# Now instrument and build the test program in various scenarios. For each +# case, we just call build_run_and_coverage, which relies on the metadata that +# "gnatcov instrument" writes to the object directory in order to know how to +# read traces ("*.srctrace" binary file or decode base64 trace from the +# stdout). +# +# We expect the dump channel to be the first parameter in the following list +# (when passed): +# +# * --dump-channel passed to "gnatcov instrument"; +# * --dump-channel passed to "gnatcov setup"; +# * bin-file (the ultimate default for native targets). +for label, rt_name, dump_args, expected_dump_channel in [ + ("def_def", "rt_def", [], "bin-file"), + ("def_base64", + "rt_def", + ["--dump-channel=base64-stdout"], + "base64-stdout"), + + ("b64_def", "rt_b64", [], "base64-stdout"), + ("b64_binfile", "rt_b64", ["--dump-channel=bin-file"], "bin-file"), +]: + thistest.log(f"== {label} ==") + build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["foo"], + extra_instr_args=dump_args + ["--runtime-project", rt_name], + runtime_project=rt_name, + extra_coverage_args=["-axcov", "--output-dir=."], + dump_channel=None, + trace_mode="src", + ) + check_xcov_reports("*.xcov", {"foo.adb.xcov": {"+": {5}}}) + + # Make sure that the metadata contains the expected dump channel + with open("obj/gnatcov-instr.json") as f: + params = json.load(f) + thistest.fail_if_not_equal( + "actual dump trigger", "atexit", params["dump-trigger"], + ) + thistest.fail_if_not_equal( + "actual dump channel", expected_dump_channel, params["dump-channel"], + ) + +thistest.result() diff --git a/testsuite/tests/V520-019-duplicate-messages/main.adb b/testsuite/tests/V520-019-duplicate-messages/main.adb new file mode 100644 index 000000000..572bd9f46 --- /dev/null +++ b/testsuite/tests/V520-019-duplicate-messages/main.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Main is + X : Integer := Pkg.Foo; + pragma Volatile (X); +begin + null; +end Main; \ No newline at end of file diff --git a/testsuite/tests/V520-019-duplicate-messages/pkg.adb b/testsuite/tests/V520-019-duplicate-messages/pkg.adb new file mode 100644 index 000000000..795d346c6 --- /dev/null +++ b/testsuite/tests/V520-019-duplicate-messages/pkg.adb @@ -0,0 +1,13 @@ +package body Pkg is + + function Foo return Integer is + begin + return 1; + end Foo; + + function Bar return Integer is + begin + return 2; + end Bar; + +end Pkg; \ No newline at end of file diff --git a/testsuite/tests/V520-019-duplicate-messages/pkg.ads b/testsuite/tests/V520-019-duplicate-messages/pkg.ads new file mode 100644 index 000000000..51f8bdaa4 --- /dev/null +++ b/testsuite/tests/V520-019-duplicate-messages/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + function Foo return Integer; + + function Bar return Integer; + +end Pkg; \ No newline at end of file diff --git a/testsuite/tests/V520-019-duplicate-messages/test.py b/testsuite/tests/V520-019-duplicate-messages/test.py new file mode 100644 index 000000000..13e5162f5 --- /dev/null +++ b/testsuite/tests/V520-019-duplicate-messages/test.py @@ -0,0 +1,43 @@ +""" +Check that when producing multiple reports in one "gnatcov coverage" +execution messages are not emitted multiple times. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +# Test project to instrument +prj = gprfor(srcdirs=[".."], mains=["main.adb"], objdir="obj") + +# Generate multiple reports for prj in a single "gnatcov coverage" execution +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-areport,xcov", "--output-dir=obj"], + out="coverage.log" +) + +# Check the expected results +check_xcov_reports("*.xcov", + {"main.adb.xcov": {}, + "pkg.adb.xcov" : {'-': {10}}}, + cwd="obj") + +# Check that we do not have any duplicate messages. In this case, we only +# expect a single statment violation. +thistest.fail_if_no_match("More than one violation detected", + r"(.|\n)*2.1. STMT COVERAGE" + r"\n------------------" + r"\n" + r"\npkg.adb:10:7: statement not executed" + r"\n" + r"\n1 violation.(.|\n)*", + contents_of("coverage.log")) + +thistest.result() diff --git a/testsuite/tests/V616-028-xsd-check/lib.c b/testsuite/tests/V616-028-xsd-check/lib.c new file mode 100644 index 000000000..c1524eef2 --- /dev/null +++ b/testsuite/tests/V616-028-xsd-check/lib.c @@ -0,0 +1,5 @@ +int +and_then (int a, int b) +{ + return a && b; +} diff --git a/testsuite/tests/V616-028-xsd-check/pkg.adb b/testsuite/tests/V616-028-xsd-check/pkg.adb new file mode 100644 index 000000000..1f3b12e57 --- /dev/null +++ b/testsuite/tests/V616-028-xsd-check/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + function Id (A : Boolean) return Boolean is + begin + return A; + end Id; +end Pkg; diff --git a/testsuite/tests/V616-028-xsd-check/pkg.ads b/testsuite/tests/V616-028-xsd-check/pkg.ads new file mode 100644 index 000000000..4c73d86df --- /dev/null +++ b/testsuite/tests/V616-028-xsd-check/pkg.ads @@ -0,0 +1,9 @@ +with Interfaces.C; use Interfaces.C; + +package Pkg is + function And_Then (A, B : int) return int; + pragma Import + (Convention => C, Entity => And_Then, External_Name => "and_then"); + + function Id (A : Boolean) return Boolean; +end Pkg; diff --git a/testsuite/tests/V616-028-xsd-check/test.adb b/testsuite/tests/V616-028-xsd-check/test.adb new file mode 100644 index 000000000..7d416f467 --- /dev/null +++ b/testsuite/tests/V616-028-xsd-check/test.adb @@ -0,0 +1,18 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Interfaces.C; use Interfaces.C; + +with Pkg; + +procedure Test is + function And_Then (A, B : Boolean) return Boolean; + + function And_Then (A, B : Boolean) return Boolean is + begin + return A and then B; + end And_Then; + +begin + Put_Line (int'Image (Pkg.And_Then (0, 1))); + Put_Line (Boolean'Image (And_Then (Pkg.Id (True), False))); +end Test; diff --git a/testsuite/tests/V616-028-xsd-check/test.py b/testsuite/tests/V616-028-xsd-check/test.py new file mode 100644 index 000000000..68bf5c56f --- /dev/null +++ b/testsuite/tests/V616-028-xsd-check/test.py @@ -0,0 +1,60 @@ +""" +Check that the distributed XSD validates different kinds of XML reports +produced by gnatcov. +""" + +import os + +from lxml import etree + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +Wdir("tmp_") + + +def check_xml(xsd_file, xml_file): + xsd_doc = etree.parse(xsd_file) + xsd = etree.XMLSchema(xsd_doc) + xml = etree.parse(xml_file) + xml.xinclude() + try: + xsd.assertValid(xml) + except Exception as exc: + thistest.failed( + "The XSD does not validate {}: \n {}".format( + os.path.abspath(xml_file), + exc + ) + ) + + +# The XML Schema is generated in the output directory with the XML report +def xsd_file(output_dir): + return os.path.join(output_dir, "gnatcov-xml-report.xsd") + + +def xml_file(output_dir): + return os.path.join(output_dir, "index.xml") + + +def build_run_coverage_and_check(covlevel): + build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], + mains=["test.adb"])), + covlevel=covlevel, + mains=["test"], + extra_coverage_args=["--annotate=xml"] + ) + check_xml(xsd_file("obj"), xml_file("obj")) + + +build_run_coverage_and_check("stmt+mcdc") + +if thistest.options.trace_mode == "bin": + build_run_coverage_and_check("insn") + build_run_coverage_and_check("branch") + +thistest.result() diff --git a/testsuite/tests/V824-005-sid-ext-prj/ext_pkg.gpr b/testsuite/tests/V824-005-sid-ext-prj/ext_pkg.gpr new file mode 100644 index 000000000..511b46e91 --- /dev/null +++ b/testsuite/tests/V824-005-sid-ext-prj/ext_pkg.gpr @@ -0,0 +1,6 @@ +project Ext_Pkg extends "pkg.gpr" is + for Source_Dirs use ("src-ext_pkg"); + for Main use ("main.adb"); + for Exec_Dir use "."; + for Object_Dir use "obj-ext_pkg"; +end Ext_Pkg; diff --git a/testsuite/tests/V824-005-sid-ext-prj/pkg.gpr b/testsuite/tests/V824-005-sid-ext-prj/pkg.gpr new file mode 100644 index 000000000..6227043a4 --- /dev/null +++ b/testsuite/tests/V824-005-sid-ext-prj/pkg.gpr @@ -0,0 +1,4 @@ +project Pkg is + for Source_Dirs use ("src-pkg"); + for Object_Dir use "obj-pkg"; +end Pkg; diff --git a/testsuite/tests/V824-005-sid-ext-prj/src-ext_pkg/main.adb b/testsuite/tests/V824-005-sid-ext-prj/src-ext_pkg/main.adb new file mode 100644 index 000000000..f759cb8a0 --- /dev/null +++ b/testsuite/tests/V824-005-sid-ext-prj/src-ext_pkg/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; +end Main; diff --git a/testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.adb b/testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.adb new file mode 100644 index 000000000..69661642e --- /dev/null +++ b/testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + --------- + -- Foo -- + --------- + + procedure Foo is + begin + Put_Line ("Hello, world!"); + end Foo; + +end Pkg; diff --git a/testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.ads b/testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.ads new file mode 100644 index 000000000..d91f3ae51 --- /dev/null +++ b/testsuite/tests/V824-005-sid-ext-prj/src-pkg/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Foo; +end Pkg; diff --git a/testsuite/tests/V824-005-sid-ext-prj/test.py b/testsuite/tests/V824-005-sid-ext-prj/test.py new file mode 100644 index 000000000..9c3575459 --- /dev/null +++ b/testsuite/tests/V824-005-sid-ext-prj/test.py @@ -0,0 +1,50 @@ +""" +Test that SID files are created in the object directory of the extending +project (i.e. not in the extended project's object directory). +""" + +import os.path + +from e3.fs import sync_tree + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + + +wd = Wdir("tmp_") + +# Copy the projec tree in the temporary directory +for filename in ["src-pkg", "src-ext_pkg", "pkg.gpr", "ext_pkg.gpr"]: + sync_tree(os.path.join("..", filename), filename) + +# Go through the instrument/build/run cycle +xcov_args = build_and_run( + gprsw=GPRswitches(root_project="ext_pkg.gpr", units=["pkg"]), + covlevel="stmt", + mains=["main"], + gpr_obj_dir="obj-ext_pkg", + extra_coverage_args=["--annotate=xcov", "--output-dir=output"], + trace_mode="src", +) + +# Make sure that SID files were created in the extending project tree, not in +# the extended project tree. +orig_sid = os.path.join("obj-pkg", "pkg.sid") +ext_sid = os.path.join("obj-ext_pkg", "pkg.sid") +thistest.fail_if(os.path.exists(orig_sid), f"Spurious {orig_sid} found") +thistest.fail_if(not os.path.exists(ext_sid), f"Missing expected {ext_sid}") + +# Before running "gnatcov coverage", create a dummy SID file in the extended +# project. "gnatcov coverage" should not try to use it, as there is a SID file +# in the extending project. +with open(orig_sid, "w") as f: + f.write("dummy SID file\n") + +# Compute the coverage report and check its contents (sanity check) +xcov(xcov_args, out="coverage.log") +check_xcov_reports("*.xcov", {"pkg.adb.xcov": {'+': {11}}}, "output") + +thistest.result() diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.c b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.c new file mode 100644 index 000000000..a1b61ceef --- /dev/null +++ b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.c @@ -0,0 +1,5 @@ +int +foo (void) +{ + return 0; +} diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.h b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.h new file mode 100644 index 000000000..2fe431a4f --- /dev/null +++ b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/foo.h @@ -0,0 +1 @@ +extern int foo (void); diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.c b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.c new file mode 100644 index 000000000..acdc74a63 --- /dev/null +++ b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.c @@ -0,0 +1,11 @@ +#include "foo.h" + +int +main () +{ + int volatile a = 1, b = 0; + if (a && b) + return 0; + else + return foo (); +} diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py new file mode 100644 index 000000000..f7fb0eb15 --- /dev/null +++ b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py @@ -0,0 +1,26 @@ +""" +Check that gnatcov --dump-trigger=main-end produces valid code when the main +is not a unit of interest and thus when the main code was not curlified. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=['test.c'], srcdirs=['..']), + units=["foo.c"]), + covlevel='stmt+mcdc', + mains=['test'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src', + dump_trigger='main-end', +) + +check_xcov_reports('*.xcov', {'foo.c.xcov': {'+': {4}}}, 'xcov') + +thistest.result() diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.c b/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.c new file mode 100644 index 000000000..118ce390d --- /dev/null +++ b/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.c @@ -0,0 +1,6 @@ +int +main () +{ + int volatile a = 1, b = 0; + return a && b; +} diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py b/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py new file mode 100644 index 000000000..e7248eb1f --- /dev/null +++ b/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py @@ -0,0 +1,27 @@ +""" +Check that gnatcov --dump-trigger=main-end actually dump coverage buffers after +the return expression has been executed. +TODO: add a lambda expression and turn this into a C++ test when C++ support +lands in master. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=['test.c'], srcdirs=['..'])), + covlevel='stmt+mcdc', + mains=['test'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src', + dump_trigger='main-end', +) + +check_xcov_reports('*.xcov', {'test.c.xcov': {'+': {4}, '!': {5}}}, 'xcov') + +thistest.result() diff --git a/testsuite/tests/VA04-023-non-instr-sco-reloc/main.adb b/testsuite/tests/VA04-023-non-instr-sco-reloc/main.adb new file mode 100644 index 000000000..24f762c65 --- /dev/null +++ b/testsuite/tests/VA04-023-non-instr-sco-reloc/main.adb @@ -0,0 +1,10 @@ +with Pkg_1; +with Pkg_2; + +procedure Main is + function Incr is new Pkg_1.Generic_Incr; + function Decr is new Pkg_2.Generic_Decr; + Dummy : constant Integer := Decr (Incr (1)); +begin + null; +end Main; diff --git a/testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_1.ads b/testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_1.ads new file mode 100644 index 000000000..a19ed1ecd --- /dev/null +++ b/testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_1.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package Pkg_1 is + + generic + Incr : Natural := 1; + function Generic_Incr (Value : Integer) return Integer; + + function Generic_Incr (Value : Integer) return Integer + is (Value + Incr); + + I : Integer := 0; + +end Pkg_1; diff --git a/testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_2.ads b/testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_2.ads new file mode 100644 index 000000000..9c72502b9 --- /dev/null +++ b/testsuite/tests/VA04-023-non-instr-sco-reloc/pkg_2.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package Pkg_2 is + + generic + Decr : Natural := 1; + function Generic_Decr (Value : Integer) return Integer; + + function Generic_Decr (Value : Integer) return Integer + is (Value - Decr); + + I : Integer := 0; + +end Pkg_2; diff --git a/testsuite/tests/VA04-023-non-instr-sco-reloc/test.opt b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.opt new file mode 100644 index 000000000..4d7631d98 --- /dev/null +++ b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Bug reproducer requires expression functions diff --git a/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py new file mode 100644 index 000000000..799e159e9 --- /dev/null +++ b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py @@ -0,0 +1,44 @@ +""" +Regression test: the relocation logic for non instrumented SCOs when loading +SCOs/checkpoints used to be buggy and some non-instrumented SCOs ended up being +instrumented during "gnatcov coverage". +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) + +# Instrument the pkg_1 and pkg_2 units. Both contain unsupported constructs +# (generic expression functions), so both will create non-instrumented SCO +# statements. +# +# The coverage step will load SID files for both units, and this step used to +# discard the non-instrumented info for the second SID file loaded because of a +# bug in the SCO_Id relocation mechanism for non-instrumented SCOs. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr, units=["pkg_1", "pkg_2"]), + extra_coverage_args=["--annotate=xcov"], + covlevel="stmt+mcdc", + mains=["main"], + trace_mode="src", + tolerate_instrument_messages=\ + "cannot instrument generic expression function", +) + +check_xcov_reports( + "*.xcov", + expected_cov={ + "pkg_1.ads.xcov": {"?": {10}, "+": {12}}, + "pkg_2.ads.xcov": {"?": {10}, "+": {12}}, + }, + cwd="obj", +) + +thistest.result() diff --git a/testsuite/tests/VB07-015-clean-output-dir/main.adb b/testsuite/tests/VB07-015-clean-output-dir/main.adb new file mode 100644 index 000000000..a628319b4 --- /dev/null +++ b/testsuite/tests/VB07-015-clean-output-dir/main.adb @@ -0,0 +1,8 @@ +with Pkg; use Pkg; + +procedure Main is + X : Integer := 4; + pragma Volatile (X); +begin + X := Ident (X); +end Main; \ No newline at end of file diff --git a/testsuite/tests/VB07-015-clean-output-dir/pkg.adb b/testsuite/tests/VB07-015-clean-output-dir/pkg.adb new file mode 100644 index 000000000..9cdf868ac --- /dev/null +++ b/testsuite/tests/VB07-015-clean-output-dir/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + function Ident (X : Integer) return Integer is + begin + return X; + end Ident; + +end Pkg; \ No newline at end of file diff --git a/testsuite/tests/VB07-015-clean-output-dir/pkg.ads b/testsuite/tests/VB07-015-clean-output-dir/pkg.ads new file mode 100644 index 000000000..1cca38ca0 --- /dev/null +++ b/testsuite/tests/VB07-015-clean-output-dir/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Ident (X : Integer) return Integer; + +end Pkg; \ No newline at end of file diff --git a/testsuite/tests/VB07-015-clean-output-dir/test.py b/testsuite/tests/VB07-015-clean-output-dir/test.py new file mode 100644 index 000000000..34c986691 --- /dev/null +++ b/testsuite/tests/VB07-015-clean-output-dir/test.py @@ -0,0 +1,78 @@ +""" +Check that gnatcov correctly cleans any previously existing xcov report before +producing a new one. +""" + +from SCOV.minicheck import build_and_run, xcov, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +from e3.fs import mkdir + +import os + +tmp = Wdir("tmp_") + +expected_cov_per_unit = { + "main": {"+": {4, 7}}, + "pkg": {"+": {5}}, +} + +possible_output_dirs = ["obj", os.path.join("obj", "xcov")] + + +def check_one(units, output_dir, xcov_args): + """ + Run gnatcov coverage with the specified xcov_args and check that we only + get a coverage report for units in output_dir. Also check that all + directories that are not output_dir contain no .xcov files. + """ + xcov(xcov_args) + for dir in possible_output_dirs: + thistest.log(f"inspecting {dir}") + check_xcov_reports( + "*.xcov", + {f"{unit}.adb.xcov": expected_cov_per_unit[unit] for unit in units} + if dir == output_dir + else {}, + cwd=dir, + ) + + +# Create the traces +xcov_args = build_and_run( + gprsw=GPRswitches(gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], +) + +# Create the possible output dirs +for dir in possible_output_dirs: + mkdir(os.path.join(os.getcwd(), dir)) + +# First, produce a report for all units, with a single report format specified +thistest.log("=== Step 1: all units in obj ===") +check_one(["main", "pkg"], "obj", xcov_args + ["-axcov"]) + +# Then only create a report for pkg, still a single report format +thistest.log("=== Step 2: pkg in obj ===") +check_one(["pkg"], "obj", xcov_args + ["-axcov", "--units=pkg"]) + +# Now create a report for both units, but specifying two output formats +# (thus creating a subdir). +thistest.log("=== Step 3: all units in obj/xcov ===") +check_one( + ["main", "pkg"], + os.path.join("obj", "xcov"), + xcov_args + ["-axcov,html"] +) + +# An finally check that the subdir is also cleaned when once again generating +# report with a single report format. +thistest.log("=== Step 4: pkg in obj ===") +check_one(["pkg"], "obj", xcov_args + ["-axcov", "--units=pkg"]) + +thistest.result() diff --git a/testsuite/tests/VB18-035-default-opts/main.adb b/testsuite/tests/VB18-035-default-opts/main.adb new file mode 100644 index 000000000..55db5185b --- /dev/null +++ b/testsuite/tests/VB18-035-default-opts/main.adb @@ -0,0 +1,10 @@ +procedure Main is + Val : Boolean := True; + pragma Volatile (Val); +begin + if Val then + Val := False; + else + Val := True; + end if; +end Main; diff --git a/testsuite/tests/VB18-035-default-opts/test.py b/testsuite/tests/VB18-035-default-opts/test.py new file mode 100644 index 000000000..ae7795c66 --- /dev/null +++ b/testsuite/tests/VB18-035-default-opts/test.py @@ -0,0 +1,64 @@ +""" +Test that gnatcov chooses the correct defaults for the level and the +annotation format, and that it emits a warning concerning the level default +value. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +def check_log(command, log_file): + thistest.fail_if_no_match( + what=f"Missing warning about default level for command {command}", + regexp=r"warning: Coverage level not specified on the command line or" + r' in the project file \(--level=.*\), defaulting to "stmt"\.', + actual=contents_of(log_file), + ) + + +tmp = Wdir("tmp_") + +# 1. Check the instrument command by not specifying a coverage level to +# build_and_run. Tolerate any warning, we'll check the log. +cov_args = build_and_run( + GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel=None, + mains=["main"], + tolerate_instrument_messages="Coverage level not specified", + extra_coverage_args=[], +) + +if thistest.options.trace_mode == "src": + check_log("instrument", "instrument.log") + +# We do not check the output of gnatcov run as it was already possible +# not to specify a coverage level for that command. + +# 2. Check the output of the coverage command while specifying an annotation +# format, and check that the coverage report corresponds to a stmt level. +cov_log = "coverage_no_level.log" +xcov(cov_args + ["-axcov"], out=cov_log) + +check_log("coverage", cov_log) +check_xcov_reports( + "*.xcov", + {"main.adb.xcov": {"+": {2, 5, 6}, "-": {8}}}, + cwd="obj" +) + +# 3. Run the coverage command without specifying an annotation format and +# check if there is a report on the standard output. + +cov_log = "coverage_no_annotate.log" +xcov(cov_args + ["-cstmt"], out=cov_log) +thistest.fail_if_no_match( + what="Missing report on the standard output without annotation format", + regexp=r"\*\* COVERAGE REPORT \*\*", + actual=contents_of(cov_log), +) + +thistest.result() diff --git a/testsuite/tests/VB21-022-sid-srctrace-mismatch/main.adb b/testsuite/tests/VB21-022-sid-srctrace-mismatch/main.adb new file mode 100644 index 000000000..6e42d1bc2 --- /dev/null +++ b/testsuite/tests/VB21-022-sid-srctrace-mismatch/main.adb @@ -0,0 +1,15 @@ +procedure Main is + function F (A, B : Boolean) return Boolean is + begin + if A and then B then + return True; + else + return False; + end if; + end F; + + C : Boolean := F (False, True); + D : Boolean := F (True, True); +begin + null; +end Main; diff --git a/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py b/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py new file mode 100644 index 000000000..b1299e477 --- /dev/null +++ b/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py @@ -0,0 +1,48 @@ +""" +Check that "gnatcov coverage" properly rejects mismatching SID files and source +trace files (i.e. source traces generated by an instrumented program, and SID +files created by an incompatible instrumentation of this program). +""" + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov + + +wd = Wdir("tmp_") + +gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) +gprsw = GPRswitches(root_project=gpr) + +# Go through the instrument/build/run cycle in stmt+mcdc mode +xcov_args = build_and_run( + gprsw=gprsw, + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], + trace_mode="src", +) + +# Re-instrument in stmt mode +xcov_instrument(gprsw=gprsw, covlevel="stmt") + +# Now compute code coverage using 1) the old trace 2) the new SIDs. We expect a +# warning about inconsistent Source Instrumentation Data and discarded coverage +# info (i.e. code not covered). +level_arg = xcov_args.index("--level=stmt+mcdc") +xcov_args[level_arg] = "--level=stmt" +xcov(xcov_args, out="coverage.log") +thistest.fail_if_no_match( + "'gnatcov coverage' output", + r"warning: traces for body of main \(from main.*\.srctrace\) are" + " inconsistent with the corresponding Source Instrumentation Data", + contents_of("coverage.log").strip(), +) +check_xcov_reports( + "*.xcov", {"main.adb.xcov": {"-": {4, 5, 7, 11, 12, 14}}}, "obj" +) + +thistest.result() diff --git a/testsuite/tests/Z999-999/test.opt b/testsuite/tests/Z999-999/test.opt new file mode 100644 index 000000000..e01fc68f8 --- /dev/null +++ b/testsuite/tests/Z999-999/test.opt @@ -0,0 +1 @@ +ALL XFAIL [should always fail] diff --git a/testsuite/tests/Z999-999/test.py b/testsuite/tests/Z999-999/test.py new file mode 100644 index 000000000..06cb5382c --- /dev/null +++ b/testsuite/tests/Z999-999/test.py @@ -0,0 +1,9 @@ +from SUITE.tutils import maybe_valgrind + +print("tool versions are now emitted as comments attached to this run") + +print('valgrind control: ' + str(maybe_valgrind([]))) + +print('End of Z999-999') + +# This test will fail by not calling thistest.result() diff --git a/testsuite/tests/asm-consolidate/src/lib.adb b/testsuite/tests/asm-consolidate/src/lib.adb new file mode 100644 index 000000000..a7746fee5 --- /dev/null +++ b/testsuite/tests/asm-consolidate/src/lib.adb @@ -0,0 +1,19 @@ +package body Lib is + + -- We will be checking full object coverage by just exercising the source + -- condition True and False. Possible overflow checks are not part of the + -- goal. + + pragma Suppress (All_Checks); + + procedure Adjust (X : in out Integer) is + begin + if X > 0 then + X := X - 1; + else + X := X + 1; + end if; + end; + +end; + diff --git a/testsuite/tests/asm-consolidate/src/lib.ads b/testsuite/tests/asm-consolidate/src/lib.ads new file mode 100644 index 000000000..53dc12ae1 --- /dev/null +++ b/testsuite/tests/asm-consolidate/src/lib.ads @@ -0,0 +1,6 @@ +package Lib is + + procedure Adjust (X : in out Integer); + +end; + diff --git a/testsuite/tests/asm-consolidate/src/p1.adb b/testsuite/tests/asm-consolidate/src/p1.adb new file mode 100644 index 000000000..c7bb84eea --- /dev/null +++ b/testsuite/tests/asm-consolidate/src/p1.adb @@ -0,0 +1,11 @@ +with Stuff1, Lib; + +procedure P1 is + X : Integer := 7; + pragma Volatile (X); +begin + Stuff1.Run; + Lib.Adjust (X); +end; + + diff --git a/testsuite/tests/asm-consolidate/src/p2.adb b/testsuite/tests/asm-consolidate/src/p2.adb new file mode 100644 index 000000000..29290cf96 --- /dev/null +++ b/testsuite/tests/asm-consolidate/src/p2.adb @@ -0,0 +1,9 @@ +with Lib; +procedure P2 is + X : Integer := -12; + pragma Volatile (X); +begin + Lib.Adjust (X); +end; + + diff --git a/testsuite/tests/asm-consolidate/src/stuff1.adb b/testsuite/tests/asm-consolidate/src/stuff1.adb new file mode 100644 index 000000000..42dc976f7 --- /dev/null +++ b/testsuite/tests/asm-consolidate/src/stuff1.adb @@ -0,0 +1,7 @@ + +package body Stuff1 is + procedure Run is + begin + Counter := Counter + 1; + end; +end; diff --git a/testsuite/tests/asm-consolidate/src/stuff1.ads b/testsuite/tests/asm-consolidate/src/stuff1.ads new file mode 100644 index 000000000..5b01d0bb7 --- /dev/null +++ b/testsuite/tests/asm-consolidate/src/stuff1.ads @@ -0,0 +1,4 @@ +package Stuff1 is + Counter : Integer := 0; + procedure Run; +end; diff --git a/testsuite/tests/asm-consolidate/test.opt b/testsuite/tests/asm-consolidate/test.opt new file mode 100644 index 000000000..99b5b4ca1 --- /dev/null +++ b/testsuite/tests/asm-consolidate/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Object coverage-specific test diff --git a/testsuite/tests/asm-consolidate/test.py b/testsuite/tests/asm-consolidate/test.py new file mode 100644 index 000000000..19af6b2bf --- /dev/null +++ b/testsuite/tests/asm-consolidate/test.py @@ -0,0 +1,64 @@ +""" +Verify that consolidation works for object-coverage with asm outputs. +""" + +import re + +from SUITE.context import thistest +from SUITE.control import target_info +from SUITE.tutils import (exename_for, exepath_to, gprbuild, gprfor, xcov, + xrun, tracename_for) +from SUITE.cutils import Wdir + + +Wdir("tmp_") + +# Build two programs using a common "lib" unit, organized so the unit object +# code is placed at different addresses in the two executables. +gpr = gprfor(srcdirs=["../src"], mains=['p1.adb', 'p2.adb']) +gprbuild(gpr) + +# Check that the lib subprograms are at different addresses +libsym = target_info().to_platform_specific_symbol('lib__adjust') + + +def address_range_for(symname, bin): + m = re.search( + pattern=r'(?P\S*-\S*) symbol for %s' % symname, + string=xcov(['dump-symbols', bin]).out) + + return m.group('address_range') + + +thistest.fail_if( + address_range_for(libsym, exename_for('p1')) + == address_range_for(libsym, exename_for('p2')), + 'address ranges for %s are identical' % libsym) + +# Execute both programs: +xrun(exepath_to('p1')) +xrun(exepath_to('p2')) + +# Do object level coverage analysis. We expect each program to cover the +# lib symbol only partially, and the two combined to cover the lib symbol +# complete. + + +def check(pgmlist): + covnote = '!' if len(pgmlist) == 1 else '+' + + out = xcov( + 'coverage --level=branch --annotate=asm %s --routines=%s' % ( + ' '.join(tracename_for(pgm) for pgm in pgmlist), libsym)).out + + results = re.findall(string=out, pattern='%s \\%c:' % (libsym, covnote)) + thistest.fail_if( + len(results) != 1, + "unexpected #matches for %s:\n%s" % (pgmlist, results)) + + +check(pgmlist=['p1']) +check(pgmlist=['p2']) +check(pgmlist=['p1', 'p2']) + +thistest.result() diff --git a/testsuite/tests/branch-cond/IB11-006-compare-floats/inrange.adb b/testsuite/tests/branch-cond/IB11-006-compare-floats/inrange.adb new file mode 100644 index 000000000..e3614a0fd --- /dev/null +++ b/testsuite/tests/branch-cond/IB11-006-compare-floats/inrange.adb @@ -0,0 +1,5 @@ +function Inrange (L, H, X : Float) return Boolean is +begin + return X >= L and then X <= H; +end; + diff --git a/testsuite/tests/branch-cond/IB11-006-compare-floats/test.py b/testsuite/tests/branch-cond/IB11-006-compare-floats/test.py new file mode 100644 index 000000000..80d3b242a --- /dev/null +++ b/testsuite/tests/branch-cond/IB11-006-compare-floats/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("inrange.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB12-008-postcond/checkx.adb b/testsuite/tests/branch-cond/IB12-008-postcond/checkx.adb new file mode 100644 index 000000000..7f7e0cacd --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-008-postcond/checkx.adb @@ -0,0 +1,6 @@ +procedure CheckX (X : Integer) is + pragma Postcondition (X > 0); +begin + null; +end; + diff --git a/testsuite/tests/branch-cond/IB12-008-postcond/test.py b/testsuite/tests/branch-cond/IB12-008-postcond/test.py new file mode 100644 index 000000000..27c761be3 --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-008-postcond/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("checkx.adb", options="-gnata -save-temps").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB12-016-lone-not/eval_not.adb b/testsuite/tests/branch-cond/IB12-016-lone-not/eval_not.adb new file mode 100644 index 000000000..bbbee6891 --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-016-lone-not/eval_not.adb @@ -0,0 +1,7 @@ +procedure Eval_Not (A : Boolean; E : out Boolean) is + Ain : Boolean; +begin + Ain := A; + E := not A; +end; + diff --git a/testsuite/tests/branch-cond/IB12-016-lone-not/not_if.adb b/testsuite/tests/branch-cond/IB12-016-lone-not/not_if.adb new file mode 100644 index 000000000..ca73380f5 --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-016-lone-not/not_if.adb @@ -0,0 +1,9 @@ +function Not_If (A, B : Boolean) return Boolean is +begin + if B then + return A; + else + return not A; + end if; +end; + diff --git a/testsuite/tests/branch-cond/IB12-016-lone-not/test.py b/testsuite/tests/branch-cond/IB12-016-lone-not/test.py new file mode 100644 index 000000000..1a7a134de --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-016-lone-not/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker(["eval_not.adb", "not_if.adb"], ensure_dcscos=False).run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB12-019-fncalls/services.adb b/testsuite/tests/branch-cond/IB12-019-fncalls/services.adb new file mode 100644 index 000000000..a0f93410e --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-019-fncalls/services.adb @@ -0,0 +1,14 @@ +package body Services is + function GT (X, Y : Int) return Boolean is + begin + return X.Value > Y.Value; + end; + function EQ (X, Y : Int) return Boolean is + begin + return X.Value = Y.Value; + end; + function GE (X, Y : Int) return Boolean is + begin + return GT (X, Y) or else EQ (X, Y); + end; +end; diff --git a/testsuite/tests/branch-cond/IB12-019-fncalls/services.ads b/testsuite/tests/branch-cond/IB12-019-fncalls/services.ads new file mode 100644 index 000000000..a0466607b --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-019-fncalls/services.ads @@ -0,0 +1,9 @@ +package Services is + type Int is record + Value : Integer; + end record; + + function GT (X, Y : Int) return Boolean; + function EQ (X, Y : Int) return Boolean; + function GE (X, Y : Int) return Boolean; +end; diff --git a/testsuite/tests/branch-cond/IB12-019-fncalls/test.py b/testsuite/tests/branch-cond/IB12-019-fncalls/test.py new file mode 100644 index 000000000..9c13267dd --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-019-fncalls/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("services.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB12-028-length/empty.adb b/testsuite/tests/branch-cond/IB12-028-length/empty.adb new file mode 100644 index 000000000..edd5badbb --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-028-length/empty.adb @@ -0,0 +1,8 @@ +function Empty (S : String) return Boolean is +begin + if S'Length > 0 then + return True; + else + return False; + end if; +end; diff --git a/testsuite/tests/branch-cond/IB12-028-length/test.py b/testsuite/tests/branch-cond/IB12-028-length/test.py new file mode 100644 index 000000000..198c452ed --- /dev/null +++ b/testsuite/tests/branch-cond/IB12-028-length/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("empty.adb", options="-fverbose-asm -save-temps").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB13-014-const-instances/services.adb b/testsuite/tests/branch-cond/IB13-014-const-instances/services.adb new file mode 100644 index 000000000..5b8a62fb0 --- /dev/null +++ b/testsuite/tests/branch-cond/IB13-014-const-instances/services.adb @@ -0,0 +1,6 @@ +package body Services is + function Has_Mid_Precision (N : Number) return Boolean is + begin + return Number'Digits >= 6 and then Number'Digits <= 12; + end; +end; diff --git a/testsuite/tests/branch-cond/IB13-014-const-instances/services.ads b/testsuite/tests/branch-cond/IB13-014-const-instances/services.ads new file mode 100644 index 000000000..ab6d0a5cc --- /dev/null +++ b/testsuite/tests/branch-cond/IB13-014-const-instances/services.ads @@ -0,0 +1,5 @@ +generic + type Number is digits <>; +package Services is + function Has_Mid_Precision (N : Number) return Boolean; +end; diff --git a/testsuite/tests/branch-cond/IB13-014-const-instances/test.opt b/testsuite/tests/branch-cond/IB13-014-const-instances/test.opt new file mode 100644 index 000000000..6843f4505 --- /dev/null +++ b/testsuite/tests/branch-cond/IB13-014-const-instances/test.opt @@ -0,0 +1 @@ +ALL DEAD !! decisions const in instances IB13-014 diff --git a/testsuite/tests/branch-cond/IB13-014-const-instances/test.py b/testsuite/tests/branch-cond/IB13-014-const-instances/test.py new file mode 100644 index 000000000..9f1f9fdde --- /dev/null +++ b/testsuite/tests/branch-cond/IB13-014-const-instances/test.py @@ -0,0 +1,7 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker(sources=["services.adb", "test_services.adb"], + execs=["test_services"], alis="obj/services.ali").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB13-014-const-instances/test_services.adb b/testsuite/tests/branch-cond/IB13-014-const-instances/test_services.adb new file mode 100644 index 000000000..b9b1a1dc5 --- /dev/null +++ b/testsuite/tests/branch-cond/IB13-014-const-instances/test_services.adb @@ -0,0 +1,14 @@ +with Services; + +procedure Test_Services is + type T1 is digits 1; + package P1 is new Services (Number => T1); + + type T8 is digits 8; + package P8 is new Services (number => T8); + + B1, B8 : Boolean; +begin + B1 := P1.Has_Mid_Precision (1.0); + B8 := P8.Has_Mid_Precision (2.0); +end; diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.adb b/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.adb new file mode 100644 index 000000000..1b15a477c --- /dev/null +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.adb @@ -0,0 +1,6 @@ +procedure Checkx (X : Float) is +begin + null; +end; + + diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.ads b/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.ads new file mode 100644 index 000000000..617940e5a --- /dev/null +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.ads @@ -0,0 +1,2 @@ +procedure Checkx (X : Float); +pragma Precondition (X > 1.0); diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/services.adb b/testsuite/tests/branch-cond/IB15-004-spec-precond/services.adb new file mode 100644 index 000000000..7c84972c2 --- /dev/null +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/services.adb @@ -0,0 +1,6 @@ +package body Services is + procedure Checkn (N : T) is + begin + null; + end; +end; diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/services.ads b/testsuite/tests/branch-cond/IB15-004-spec-precond/services.ads new file mode 100644 index 000000000..f8e5fdd6f --- /dev/null +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/services.ads @@ -0,0 +1,8 @@ +generic + type T is digits <>; +package Services is + procedure CheckN (N : T); + pragma Precondition (N > 1.0); +end; + + diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/test.py b/testsuite/tests/branch-cond/IB15-004-spec-precond/test.py new file mode 100644 index 000000000..ab3d00c67 --- /dev/null +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/test.py @@ -0,0 +1,10 @@ +from SUITE.context import thistest +from SUITE.tutils import exename_for +from SCOV.map import MapChecker + + +MapChecker("checkx.adb", options="-gnata -save-temps").run() +MapChecker(sources=["services.adb", "test_services.ads"], options="-gnata", + execs=[exename_for("test_services")], + alis=["obj/services.ali"]).run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/test_services.ads b/testsuite/tests/branch-cond/IB15-004-spec-precond/test_services.ads new file mode 100644 index 000000000..57c9bef6b --- /dev/null +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/test_services.ads @@ -0,0 +1,2 @@ +with Services; +package Test_Services is new Services (Float); diff --git a/testsuite/tests/branch-cond/IB18-024-float-precond/checki.adb b/testsuite/tests/branch-cond/IB18-024-float-precond/checki.adb new file mode 100644 index 000000000..f8157270f --- /dev/null +++ b/testsuite/tests/branch-cond/IB18-024-float-precond/checki.adb @@ -0,0 +1,4 @@ +procedure CheckI (I, Lb, Hb : Integer) is +begin + null; +end; diff --git a/testsuite/tests/branch-cond/IB18-024-float-precond/checki.ads b/testsuite/tests/branch-cond/IB18-024-float-precond/checki.ads new file mode 100644 index 000000000..c0e421574 --- /dev/null +++ b/testsuite/tests/branch-cond/IB18-024-float-precond/checki.ads @@ -0,0 +1,2 @@ +procedure CheckI (I, Lb, Hb : Integer); +pragma Precondition (Lb > 0 and then I >= Lb and then I <= Hb); diff --git a/testsuite/tests/branch-cond/IB18-024-float-precond/checkx.adb b/testsuite/tests/branch-cond/IB18-024-float-precond/checkx.adb new file mode 100644 index 000000000..1a9012ed3 --- /dev/null +++ b/testsuite/tests/branch-cond/IB18-024-float-precond/checkx.adb @@ -0,0 +1,4 @@ +procedure CheckX (X, Lb, Hb : Float) is +begin + null; +end; diff --git a/testsuite/tests/branch-cond/IB18-024-float-precond/checkx.ads b/testsuite/tests/branch-cond/IB18-024-float-precond/checkx.ads new file mode 100644 index 000000000..b89f68542 --- /dev/null +++ b/testsuite/tests/branch-cond/IB18-024-float-precond/checkx.ads @@ -0,0 +1,2 @@ +procedure CheckX (X, Lb, Hb : Float); +pragma Precondition (Lb > 0.0 and then X >= Lb and then X <= Hb); diff --git a/testsuite/tests/branch-cond/IB18-024-float-precond/test.py b/testsuite/tests/branch-cond/IB18-024-float-precond/test.py new file mode 100644 index 000000000..64ba0b4d9 --- /dev/null +++ b/testsuite/tests/branch-cond/IB18-024-float-precond/test.py @@ -0,0 +1,7 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("checkx.adb", options="-gnata -save-temps").run() +MapChecker("checki.adb", options="-gnata -save-temps").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB19-001-precond-false/check.adb b/testsuite/tests/branch-cond/IB19-001-precond-false/check.adb new file mode 100644 index 000000000..979fdb757 --- /dev/null +++ b/testsuite/tests/branch-cond/IB19-001-precond-false/check.adb @@ -0,0 +1,4 @@ +procedure Check is +begin + null; +end; diff --git a/testsuite/tests/branch-cond/IB19-001-precond-false/check.ads b/testsuite/tests/branch-cond/IB19-001-precond-false/check.ads new file mode 100644 index 000000000..06c3dd06e --- /dev/null +++ b/testsuite/tests/branch-cond/IB19-001-precond-false/check.ads @@ -0,0 +1,2 @@ +procedure Check; +pragma Precondition (False); diff --git a/testsuite/tests/branch-cond/IB19-001-precond-false/test.opt b/testsuite/tests/branch-cond/IB19-001-precond-false/test.opt new file mode 100644 index 000000000..357adb47e --- /dev/null +++ b/testsuite/tests/branch-cond/IB19-001-precond-false/test.opt @@ -0,0 +1 @@ +ALL DEAD !! no branch for condition False IB19-001 diff --git a/testsuite/tests/branch-cond/IB19-001-precond-false/test.py b/testsuite/tests/branch-cond/IB19-001-precond-false/test.py new file mode 100644 index 000000000..db1abbcae --- /dev/null +++ b/testsuite/tests/branch-cond/IB19-001-precond-false/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("check.adb", options="-gnata -save-temps").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB20-015-length-check/starts.adb b/testsuite/tests/branch-cond/IB20-015-length-check/starts.adb new file mode 100644 index 000000000..0d5ca483c --- /dev/null +++ b/testsuite/tests/branch-cond/IB20-015-length-check/starts.adb @@ -0,0 +1,6 @@ +function Starts (S : String; Key : String) return Boolean is +begin + return Key'Length = 3 + and then S (S'First .. S'First + Key'Length) = "abc"; -- # contents +end; + diff --git a/testsuite/tests/branch-cond/IB20-015-length-check/test.py b/testsuite/tests/branch-cond/IB20-015-length-check/test.py new file mode 100644 index 000000000..2a61d3df4 --- /dev/null +++ b/testsuite/tests/branch-cond/IB20-015-length-check/test.py @@ -0,0 +1,7 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("starts.adb", options="-gnata").run() +MapChecker("starts.adb", options="-gnata -gnatp").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.adb b/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.adb new file mode 100644 index 000000000..2d4aac61a --- /dev/null +++ b/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.adb @@ -0,0 +1,11 @@ +with System; use System; + +package body Regions is + procedure Check (R : Region) is + pragma Precondition + (R'Address /= System.Null_Address + and then R.Data'Address /= System.Null_Address); + begin + null; + end; +end; diff --git a/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.ads b/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.ads new file mode 100644 index 000000000..73716d9bb --- /dev/null +++ b/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.ads @@ -0,0 +1,11 @@ + +package Regions is + type Region (Size : Natural) is record + Data : String (1 .. Size); + end record; + pragma Suppress_Initialization (Region); + + procedure Check (R : Region); +end; + + diff --git a/testsuite/tests/branch-cond/IB20-027-addr-compare/test.py b/testsuite/tests/branch-cond/IB20-027-addr-compare/test.py new file mode 100644 index 000000000..44f5ddcde --- /dev/null +++ b/testsuite/tests/branch-cond/IB20-027-addr-compare/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("regions.adb", options="-gnata -save-temps").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB23-016-range-test/checkx.adb b/testsuite/tests/branch-cond/IB23-016-range-test/checkx.adb new file mode 100644 index 000000000..1e9da635c --- /dev/null +++ b/testsuite/tests/branch-cond/IB23-016-range-test/checkx.adb @@ -0,0 +1,4 @@ +function CheckX (X, Lb, Hb : Integer; Docheck : Boolean) return Boolean is +begin + return Docheck and then X in Lb .. Hb; +end; diff --git a/testsuite/tests/branch-cond/IB23-016-range-test/test.py b/testsuite/tests/branch-cond/IB23-016-range-test/test.py new file mode 100644 index 000000000..27c761be3 --- /dev/null +++ b/testsuite/tests/branch-cond/IB23-016-range-test/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("checkx.adb", options="-gnata -save-temps").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.adb b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.adb new file mode 100644 index 000000000..53416b9b3 --- /dev/null +++ b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.adb @@ -0,0 +1,33 @@ +with System; use System; + +package body Services is + procedure Validate (T : Boolean) is + begin + if not T then + raise Program_Error; + end if; + end; + + procedure Check_Value_And (This : in out Str_Type) is + begin + Validate (This.Size = 0 or else This.Value (1) = 'X'); + end; + + procedure Check_Value_Or (This : in out Str_Type) is + begin + Validate (This.Size = 0 or else This.Value (1) = 'X'); + end; + + procedure Check_Addr_And (This : Str_Type) is + begin + Validate (This'Address /= System.Null_Address + and then This.Value'Address /= System.Null_Address); + end; + + procedure Check_Addr_Or (This : Str_Type) is + begin + Validate (This'Address /= System.Null_Address + or else This.Value'Address /= System.Null_Address); + end; + +end; diff --git a/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.ads b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.ads new file mode 100644 index 000000000..e5a493d1f --- /dev/null +++ b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.ads @@ -0,0 +1,11 @@ +package Services is + type Str_Type (Size : Integer) is record + Value : String (1 .. Size); + end record; + + procedure Check_Value_And (This : in out Str_Type); + procedure Check_Value_Or (This : in out Str_Type); + procedure Check_Addr_And (This : Str_Type); + procedure Check_Addr_Or (This : Str_Type); +end; + diff --git a/testsuite/tests/branch-cond/IB25-022-shortcut-actions/test.py b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/test.py new file mode 100644 index 000000000..9c13267dd --- /dev/null +++ b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/test.py @@ -0,0 +1,6 @@ +from SUITE.context import thistest +from SCOV.map import MapChecker + + +MapChecker("services.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.adb b/testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.adb new file mode 100644 index 000000000..757384f4c --- /dev/null +++ b/testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.adb @@ -0,0 +1,10 @@ +package body Fatp is + function Is_Null (S : String_Access) return Boolean is + begin + if S = null then + return True; + else + return False; + end if; + end; +end; diff --git a/testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.ads b/testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.ads new file mode 100644 index 000000000..361d50f54 --- /dev/null +++ b/testsuite/tests/branch-cond/IC01-011-null-fatp/fatp.ads @@ -0,0 +1,4 @@ +package Fatp is + type String_Access is access all String; + function Is_Null (S : String_Access) return Boolean; +end; diff --git a/testsuite/tests/branch-cond/IC01-011-null-fatp/test.py b/testsuite/tests/branch-cond/IC01-011-null-fatp/test.py new file mode 100644 index 000000000..6524cef06 --- /dev/null +++ b/testsuite/tests/branch-cond/IC01-011-null-fatp/test.py @@ -0,0 +1,6 @@ +from SCOV.map import MapChecker +from SUITE.context import thistest + + +MapChecker("fatp.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IC01-032-itype-early-elab/starts.adb b/testsuite/tests/branch-cond/IC01-032-itype-early-elab/starts.adb new file mode 100644 index 000000000..56d6fa64e --- /dev/null +++ b/testsuite/tests/branch-cond/IC01-032-itype-early-elab/starts.adb @@ -0,0 +1,6 @@ +function Starts (S : String; Key : String) return Boolean is +begin + return Key'Length <= S'Length -- # startsLength + and then S (S'First .. S'First + Key'Length - 1) = Key; -- # startsKey +end; + diff --git a/testsuite/tests/branch-cond/IC01-032-itype-early-elab/test.py b/testsuite/tests/branch-cond/IC01-032-itype-early-elab/test.py new file mode 100644 index 000000000..dcdaf0dcd --- /dev/null +++ b/testsuite/tests/branch-cond/IC01-032-itype-early-elab/test.py @@ -0,0 +1,5 @@ +from SCOV.map import MapChecker +from SUITE.context import thistest + +MapChecker("starts.adb", options="-gnata -save-temps -gnatp").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.adb b/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.adb new file mode 100644 index 000000000..91e33c9e4 --- /dev/null +++ b/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.adb @@ -0,0 +1,13 @@ +with System; use System; +package body Check is + + function Valid (S : T_Str; X, Y : Integer) return Boolean is + begin + return (X > 10 + and then + (Y = 0 + or else + (Y = 1 + and then S.Value'Address /= System.Null_address))); + end; +end; diff --git a/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.ads b/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.ads new file mode 100644 index 000000000..0ba52afe3 --- /dev/null +++ b/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/check.ads @@ -0,0 +1,8 @@ +package Check is + + type T_Str (Size : Integer) is record + Value : String (1 .. Size); + end record; + + function Valid (S : T_Str; X, Y : Integer) return Boolean; +end; diff --git a/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/test.py b/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/test.py new file mode 100644 index 000000000..3f4ab4a0f --- /dev/null +++ b/testsuite/tests/branch-cond/IC02-013-nested-shortcut-action/test.py @@ -0,0 +1,7 @@ +from SCOV.map import MapChecker +from SUITE.context import thistest + + +MapChecker("check.adb", options="-gnatp").run() +MapChecker("check.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.adb b/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.adb new file mode 100644 index 000000000..1127677ca --- /dev/null +++ b/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.adb @@ -0,0 +1,17 @@ +package body Check is + + K_Nul : constant Character := '0'; + + function Validate (This : T_Str; Str : String) return Boolean is + begin + pragma Warnings (Off, "index for * may assume lower bound of 1"); + return + (This.Len <= This.Size + and then ((This.Len = 0 and then Str (1) = K_Nul) + or else (Str (1) = This.Tab (1) + and then Str (This.Len) = This.Tab (This.Len) + and then Str (This.Len + 1) = K_Nul))); + pragma Warnings (On, "index for * may assume lower bound of 1"); + end; +end; + diff --git a/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.ads b/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.ads new file mode 100644 index 000000000..d9175a09a --- /dev/null +++ b/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.ads @@ -0,0 +1,9 @@ +package Check is + + type T_Str (Size : Integer) is record + Len : Integer; + Tab : String (1 .. Size); + end record; + + function Validate (This : T_Str; Str : String) return Boolean; +end; diff --git a/testsuite/tests/branch-cond/IC02-020-shortcut-action/test.py b/testsuite/tests/branch-cond/IC02-020-shortcut-action/test.py new file mode 100644 index 000000000..3f4ab4a0f --- /dev/null +++ b/testsuite/tests/branch-cond/IC02-020-shortcut-action/test.py @@ -0,0 +1,7 @@ +from SCOV.map import MapChecker +from SUITE.context import thistest + + +MapChecker("check.adb", options="-gnatp").run() +MapChecker("check.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/J205-019-and-not/check.adb b/testsuite/tests/branch-cond/J205-019-and-not/check.adb new file mode 100644 index 000000000..25f18ab5d --- /dev/null +++ b/testsuite/tests/branch-cond/J205-019-and-not/check.adb @@ -0,0 +1,5 @@ +function Check (A, B, C : Boolean) return Boolean is +begin + return A and then not (B and then C); +end; + diff --git a/testsuite/tests/branch-cond/J205-019-and-not/foo.adb b/testsuite/tests/branch-cond/J205-019-and-not/foo.adb new file mode 100644 index 000000000..f6767dd83 --- /dev/null +++ b/testsuite/tests/branch-cond/J205-019-and-not/foo.adb @@ -0,0 +1,5 @@ +function Foo (A, B, C, D : Boolean) return Boolean is +begin + return A and then B and then (not C and then not D); +end; + diff --git a/testsuite/tests/branch-cond/J205-019-and-not/foo2.adb b/testsuite/tests/branch-cond/J205-019-and-not/foo2.adb new file mode 100644 index 000000000..593e2c94f --- /dev/null +++ b/testsuite/tests/branch-cond/J205-019-and-not/foo2.adb @@ -0,0 +1,5 @@ +function Foo2 (A, B, C : Boolean) return Boolean is +begin + return not A and then (B or else C); +end; + diff --git a/testsuite/tests/branch-cond/J205-019-and-not/foo3.adb b/testsuite/tests/branch-cond/J205-019-and-not/foo3.adb new file mode 100644 index 000000000..ff2bc34b8 --- /dev/null +++ b/testsuite/tests/branch-cond/J205-019-and-not/foo3.adb @@ -0,0 +1,5 @@ +function Foo3 (A, B, C : Boolean) return Boolean is +begin + return A and then not B and then not C; +end; + diff --git a/testsuite/tests/branch-cond/J205-019-and-not/test.py b/testsuite/tests/branch-cond/J205-019-and-not/test.py new file mode 100644 index 000000000..1afe9f1e7 --- /dev/null +++ b/testsuite/tests/branch-cond/J205-019-and-not/test.py @@ -0,0 +1,9 @@ +from SCOV.map import MapChecker +from SUITE.context import thistest + + +MapChecker("check.adb").run() +MapChecker("foo.adb").run() +MapChecker("foo2.adb").run() +MapChecker("foo3.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/J205-021-slice-compare/p.adb b/testsuite/tests/branch-cond/J205-021-slice-compare/p.adb new file mode 100644 index 000000000..1b6955d73 --- /dev/null +++ b/testsuite/tests/branch-cond/J205-021-slice-compare/p.adb @@ -0,0 +1,10 @@ +function P (S1, S2 : String; L : Integer) return Boolean is +begin + pragma Warnings (Off, "index for * may assume lower bound of 1"); + if S1 (1 .. L) = S2 (1 .. L) then + return True; + else + return False; + end if; + pragma Warnings (On, "index for * may assume lower bound of 1"); +end; diff --git a/testsuite/tests/branch-cond/J205-021-slice-compare/test.py b/testsuite/tests/branch-cond/J205-021-slice-compare/test.py new file mode 100644 index 000000000..8e39094e5 --- /dev/null +++ b/testsuite/tests/branch-cond/J205-021-slice-compare/test.py @@ -0,0 +1,7 @@ +from SCOV.map import MapChecker +from SUITE.context import thistest + + +MapChecker("p.adb", options="-gnatp").run() +MapChecker("p.adb").run() +thistest.result() diff --git a/testsuite/tests/branch-cond/extra.opt b/testsuite/tests/branch-cond/extra.opt new file mode 100644 index 000000000..a29228f15 --- /dev/null +++ b/testsuite/tests/branch-cond/extra.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise map-routines, specific to binary trace mode diff --git a/testsuite/tests/exemptions-check/expected b/testsuite/tests/exemptions-check/expected new file mode 100644 index 000000000..3e3f709cc --- /dev/null +++ b/testsuite/tests/exemptions-check/expected @@ -0,0 +1,8 @@ +!!! hello.adb:4:4: unexpected EXEMPT_OFF BAD lone at start (expected EXEMPT_ON) +!!! hello.adb:15:4: empty message for EXEMPT_ON +!!! hello.adb:19:4: unexpected EXEMPT_OFF BAD1 mismatch (expected BAD1) +!!! hello.adb:22:4: unexpected EXEMPT_ON BAD2 nested (expected EXEMPT_OFF) +!!! hello.adb:24:4: unexpected EXEMPT_OFF BAD2 (expected EXEMPT_ON) +!!! hello.adb:29:4: bad annotation exempt_bad1 +!!! hello.adb:30:4: bad annotation exempt_bad2 +!!! hello.adb:26:4: missing Exempt_Off BAD lone at end diff --git a/testsuite/tests/exemptions-check/src/hello.adb b/testsuite/tests/exemptions-check/src/hello.adb new file mode 100644 index 000000000..3dabe6eb0 --- /dev/null +++ b/testsuite/tests/exemptions-check/src/hello.adb @@ -0,0 +1,31 @@ +procedure Hello is +begin + null; + pragma Annotate (Xcov, Exempt_Off, "BAD lone at start"); + + pragma Annotate (Xcov, Exempt_On, "OK"); + pragma Annotate (Xcov, Exempt_Off, "OK"); + + pragma Annotate (Xcov, Exempt_On, "OK2"); + pragma Annotate (Xcov, Exempt_Off, ""); + + pragma Annotate (Xcov, Exempt_On, "OK3"); + pragma Annotate (Xcov, Exempt_Off); + + pragma Annotate (Xcov, Exempt_On); + pragma Annotate (Xcov, Exempt_Off); + + pragma Annotate (Xcov, Exempt_On, "BAD1"); + pragma Annotate (Xcov, Exempt_Off, "BAD1 mismatch"); + + pragma Annotate (Xcov, Exempt_On, "BAD2"); + pragma Annotate (Xcov, Exempt_On, "BAD2 nested"); + pragma Annotate (Xcov, Exempt_Off, "BAD2 nested"); + pragma Annotate (Xcov, Exempt_Off, "BAD2"); + + pragma Annotate (Xcov, Exempt_On, "BAD lone at end"); + + pragma Annotate (Xcov); + pragma Annotate (Xcov, Exempt_Bad1); + pragma Annotate (Xcov, Exempt_Bad2, "foo"); +end Hello; diff --git a/testsuite/tests/exemptions-check/test.opt b/testsuite/tests/exemptions-check/test.opt new file mode 100644 index 000000000..aea7bfc5c --- /dev/null +++ b/testsuite/tests/exemptions-check/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Check map-routines, specific to binary traces mode diff --git a/testsuite/tests/exemptions-check/test.py b/testsuite/tests/exemptions-check/test.py new file mode 100644 index 000000000..7632138e1 --- /dev/null +++ b/testsuite/tests/exemptions-check/test.py @@ -0,0 +1,22 @@ +""" +Check that a simple decision SCO is correctly loaded and interpreted by xcov. +""" + +from e3.diff import diff + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor, xcov + + +tmp = Wdir('tmp_') + +gprbuild(gprfor(['hello.adb'], srcdirs='../src')) + +xcov(['map-routines', '--scos=obj/hello.ali', 'obj/hello.o'], "out") + +dif = diff("../expected", "out") +thistest.fail_if( + dif, "out != expected on exemption pragma placement rules:\n" + dif) + +thistest.result() diff --git a/testsuite/tests/gnatcov-run.py b/testsuite/tests/gnatcov-run.py new file mode 100755 index 000000000..788abf72a --- /dev/null +++ b/testsuite/tests/gnatcov-run.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python + +""" +Example script to be used as a testsuite.py --gnatcov-run argument, which the +suite engine will call instead of "gnatcov run" to execute programs and produce +an execution trace that "gnatcov coverage" can process later on. + +This should return/exit with code 0 in case of success, with another value +otherwise. More generally This needs to be ready to honor the "gnatcov run" +interface, at least the subset of arguments that the testsuite driver might use +for your target configuration. Simplest is to error out on unrecognized +options. + +The code below eventually resorts to a real "gnatcov run" invocation. While +there is no real added value in doing that, this code is useful as an example +of a possible way to achieve the goal of replacing gnatcov run in other +situations. A typical case is one where the program execution is performed on a +real target board, producing a some trace that needs to be converted to a +format gnatcov can process. +""" + +import os +import optparse + +from e3.os.process import Run + + +class Runner: + def __init__(self): + self.parse_command_line() + self.run() + + def parse_command_line(self): + """Parse this script's command line.""" + + op = optparse.OptionParser() + + # --level and --target are expected to always be there: + op.add_option('--level', dest='covlevel', default=None) + op.add_option('--target', dest='target', default=None) + + # For source coverage tests not using project files: + op.add_option('--scos', dest='scos', default=None) + + # For tests using project files + op.add_option('-P', dest='gpr', default=None) + op.add_option('--recursive', dest='recurse', default=False, + action='store_true') + op.add_option('--projects', dest='projects', default=None) + op.add_option('--units', dest='units', default=None) + + # Then a few optional items + op.add_option('-o', dest='ofile', default=None) + self.options, self.args = op.parse_args() + + def run_command_line(self): + """Compute a list of command line arguments to pass to + gnatcov run from what we have received.""" + + args = ['--level=%s' % self.options.covlevel, + '--target=%s' % self.options.target] + + if self.options.scos: + args.append('--scos=%s' % self.options.scos) + + if self.options.gpr: + args.append('-P=%s' % self.options.gpr) + if self.options.gpr: + args.append('--projects=%s' % self.options.projects) + if self.options.gpr: + args.append('--units=%s' % self.options.units) + if self.options.recurse: + args.append('--recursive') + + if self.options.ofile: + args.append('-o %s' % self.options.ofile) + + return args + + def run(self): + + print '============== GNATCOV RUN ===================' + + if not self.args: + print 'gnatcov: missing EXE for run' + os.exit(1) + + Run( + ['gnatcov', 'run'] + self.run_command_line() + self.args) + + print '==============================================' + + +runner = Runner() diff --git a/testsuite/tests/gpr-scos/src/dec.adb b/testsuite/tests/gpr-scos/src/dec.adb new file mode 100644 index 000000000..3e681318a --- /dev/null +++ b/testsuite/tests/gpr-scos/src/dec.adb @@ -0,0 +1,4 @@ +procedure Dec (X : in out Integer) is +begin + X := X - 1; +end; diff --git a/testsuite/tests/gpr-scos/src/inc.adb b/testsuite/tests/gpr-scos/src/inc.adb new file mode 100644 index 000000000..62ef0bdc5 --- /dev/null +++ b/testsuite/tests/gpr-scos/src/inc.adb @@ -0,0 +1,4 @@ +procedure Inc (X : in out Integer) is +begin + X := X + 1; +end; diff --git a/testsuite/tests/gpr-scos/src/test_ops.adb b/testsuite/tests/gpr-scos/src/test_ops.adb new file mode 100644 index 000000000..0d33f5180 --- /dev/null +++ b/testsuite/tests/gpr-scos/src/test_ops.adb @@ -0,0 +1,18 @@ +with Inc, Dec; + +procedure Test_Ops is + + procedure Assert (P : Boolean) is + begin + if not P then + raise Program_Error; + end if; + end; + + X : Integer := 12; +begin + Inc (X); + Assert (X = 13); + Dec (X); + Assert (X = 12); +end; diff --git a/testsuite/tests/gpr-scos/test.py b/testsuite/tests/gpr-scos/test.py new file mode 100644 index 000000000..2d6654077 --- /dev/null +++ b/testsuite/tests/gpr-scos/test.py @@ -0,0 +1,70 @@ +""" +Check the interactions between --scos/--sid and -P regarding the set of units +of interest. Essentially, --scos/--sid is expected to override whatever the -P +family would yield. +""" + +from e3.fs import ls, rm + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +wd = Wdir('tmp_') + +# Build and run our example test, 1 driver + 2 units +project = gprfor(srcdirs=['../src'], mains=['test_ops.adb']) +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=project), + covlevel='stmt', + mains=['test_ops'], + extra_coverage_args=['--annotate=xcov']) + + +# Now exercise various combinations of units of interest +# specifications with --scos and/or -P, and check they produce +# the set of .xcov reports we expect. + +# Arrange to always produce the reports in the current directory, +# regardless of --scos or -P, so they are straightforward to find +# or remove in all circumstances. + +def trycov(sco_units, with_project, expected_reports): + rm('*.xcov', recursive=False) + + src_trace = thistest.options.trace_mode == 'src' + sco_args = [ + '--{}=obj/{}.{}'.format('sid' if src_trace else 'scos', + unit, + 'sid' if src_trace else 'ali') + for unit in sco_units + ] + project_args = ['-P', project] if with_project else [] + xcov(xcov_args + sco_args + project_args + ['--output-dir=.']) + + reports = ls('*.xcov') + + thistest.fail_if( + set(reports) != set(expected_reports), + 'With %s, %s (found) != %s (expected)' % ( + str(sco_args), str(reports), str(expected_reports))) + + +# --scos/--sid alone +trycov(sco_units=['inc'], with_project=False, + expected_reports=['inc.adb.xcov']) + +# -P alone +trycov(sco_units=[], with_project=True, + expected_reports=['inc.adb.xcov', + 'dec.adb.xcov', + 'test_ops.adb.xcov']) + +# --scos with -P, check that --scos prevails +trycov(sco_units=['dec'], with_project=True, + expected_reports=['dec.adb.xcov']) + +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/c++_no_warnings/main.cpp b/testsuite/tests/instr-cov/C++/c++_no_warnings/main.cpp new file mode 100644 index 000000000..398ec675a --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_no_warnings/main.cpp @@ -0,0 +1,5 @@ +int +main (void) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py b/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py new file mode 100644 index 000000000..0c71856b8 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py @@ -0,0 +1,25 @@ +""" +Check that the instrumentation produces code that compiles without warnings. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.cpp'])), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + extra_gprbuild_cargs=['-Werror'], + trace_mode='src', +) + +check_xcov_reports('xcov/*.xcov', {'xcov/main.cpp.xcov': {'+': {4}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/cpp-extern-c-main/main.cpp b/testsuite/tests/instr-cov/C++/cpp-extern-c-main/main.cpp new file mode 100644 index 000000000..fece5f42a --- /dev/null +++ b/testsuite/tests/instr-cov/C++/cpp-extern-c-main/main.cpp @@ -0,0 +1,8 @@ +extern "C" +{ + int + main (int argc, char **argv) + { + return 0; + } +} diff --git a/testsuite/tests/instr-cov/C++/cpp-extern-c-main/test.py b/testsuite/tests/instr-cov/C++/cpp-extern-c-main/test.py new file mode 100644 index 000000000..bfd0f9a06 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/cpp-extern-c-main/test.py @@ -0,0 +1,24 @@ +""" +Check that gnatcov correctly instruments a main that is in an extern "C" +linkage specifier. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.cpp"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports("*.xcov", {"main.cpp.xcov": {"+": {6}}}, "xcov") +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/explicit_lang/main.c b/testsuite/tests/instr-cov/C++/explicit_lang/main.c new file mode 100644 index 000000000..ba8918dc9 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/explicit_lang/main.c @@ -0,0 +1,8 @@ +#include + +int +main () +{ + std::cout << "Hello World!"; + return 0; +} diff --git a/testsuite/tests/instr-cov/C++/explicit_lang/test.py b/testsuite/tests/instr-cov/C++/explicit_lang/test.py new file mode 100644 index 000000000..cea21b4c0 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/explicit_lang/test.py @@ -0,0 +1,35 @@ +""" +Check that gnatcov explicitly passes the language to the compiler / parsing +command, otherwise the file might be preprocessed as C code instead of C++ +and reciprocally. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +p = gprfor( + srcdirs=[".."], mains=["main.c"], langs=["C++"], + extra=""" + package Naming is + for Body_Suffix ("C++") use ".c"; + end Naming; + """, +) +# Build and produce a coverage report for the test project. +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src', +) + +check_xcov_reports("*.xcov", {"main.c.xcov": {"+": {6, 7}}}, "xcov") + +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/std-c++20/cmdline.cpp b/testsuite/tests/instr-cov/C++/std-c++20/cmdline.cpp new file mode 100644 index 000000000..0ed5edbc3 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/std-c++20/cmdline.cpp @@ -0,0 +1,28 @@ +#include "cmdline.hh" + +std::vector +add_dashes (std::string name) +{ + // Multi-letter linker options can be preceded by either a single + // dash or double dashes except ones starting with "o", which must + // be preceded by double dashes. For example, "-omagic" is + // interpreted as "-o magic". If you really want to specify the + // "omagic" option, you have to pass "--omagic". + if (name[0] == 'o') + return { "--" + name }; + return { "-" + name, "--" + name }; +} + +bool +read_flag (std::span &args, std::string name) +{ + for (std::string opt : add_dashes (name)) + { + if (args[0] == opt) + { + args = args.subspan (1); + return true; + } + } + return false; +} diff --git a/testsuite/tests/instr-cov/C++/std-c++20/cmdline.hh b/testsuite/tests/instr-cov/C++/std-c++20/cmdline.hh new file mode 100644 index 000000000..1a3e157e6 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/std-c++20/cmdline.hh @@ -0,0 +1,7 @@ +#include +#include +#include + +extern std::vector add_dashes (std::string name); + +extern bool read_flag (std::span &args, std::string name); diff --git a/testsuite/tests/instr-cov/C++/std-c++20/main.cpp b/testsuite/tests/instr-cov/C++/std-c++20/main.cpp new file mode 100644 index 000000000..e4b09704d --- /dev/null +++ b/testsuite/tests/instr-cov/C++/std-c++20/main.cpp @@ -0,0 +1,10 @@ +#include "cmdline.hh" + +int +main (int argc, char **argv) +{ + std::vector args_vec (argv, argv + argc); + std::span args = args_vec; + read_flag (args, "output"); + read_flag (args, "version"); +} diff --git a/testsuite/tests/instr-cov/C++/std-c++20/test.py b/testsuite/tests/instr-cov/C++/std-c++20/test.py new file mode 100644 index 000000000..d1b65f61a --- /dev/null +++ b/testsuite/tests/instr-cov/C++/std-c++20/test.py @@ -0,0 +1,67 @@ +""" +Check that gnatcov can deal with C/C++ code in another standard than the +default. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor +from SUITE.gprutils import GPRswitches + + +def gen_prj(): + return GPRswitches(root_project=gprfor(srcdirs=[".."], + mains=["main.cpp"])) + + +tmp = Wdir("tmp_valid-instrumentation") + +# Check that passing std=c++20 to both the instrumenter, and the builder, +# compiles and produces the right coverage report. + +build_run_and_coverage( + gprsw=gen_prj(), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--c++-opts=-std=c++20"], + extra_gprbuild_cargs=["-std=c++20"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "*.xcov", + { + "main.cpp.xcov": {"+": {6, 7, 8, 9}}, + "cmdline.cpp.xcov": {"+": {11, 12, 13, 21, 27}, "-": {23, 24}}, + }, + "xcov" +) + +tmp.to_homedir() + +# Now check that when we do not pass std=c++20 to the instrumenter, we +# produce invalid code, that will fail to compile. +# +# TODO: gnatcov instrument should emit warnings. We get diagnostics when +# parsing with clang, but we choose not to emit them, as we are bound to get +# diagnostics even for valid code. One thing we could try would be to filter +# out the diagnostics that we will surely get (references to gcc builtins for +# instance), and print the other ones. + +tmp = Wdir("tmp_invalid-instrumentation") + +gprsw = gen_prj() +xcov_instrument(gprsw=gprsw, covlevel="stmt") +p = gprbuild( + gprsw.root_project, + extracargs=["-std=c++20"], + trace_mode="src", + register_failure=False, +) + +thistest.fail_if(p.status == 0, "Expecting compilation failure") + +thistest.result() diff --git a/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp b/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp new file mode 100644 index 000000000..84f4d82b9 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp @@ -0,0 +1,16 @@ +#include + +int +main () +{ +#if defined(__STDC_VERSION__) + // This is true if the code is preprocessed as C code + std::cout << "This is C code" << std::endl; +#elif __cplusplus == 202002L + // This is true if the code is preprocessed as C++20 code + std::cout << "This is C++20 code" << std::endl; +#else + std::cout << "This is C++ code" << std::endl; +#endif + return 0; +} diff --git a/testsuite/tests/instr-cov/C++/std-cond-code/test.py b/testsuite/tests/instr-cov/C++/std-cond-code/test.py new file mode 100644 index 000000000..229d1e9e4 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/std-cond-code/test.py @@ -0,0 +1,67 @@ +""" +Check that gnatcov produces valid code when the code needs to be preprocessed +with the right preprocessor configuration. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +def run_variant(variant_name, extra_instr_cppargs, extra_gprbuild_cargs, + tolerate_instrument_messages=None, pred=lambda: True): + """ + Build and run the project with the given arguments, and check the predicate + holds. + + :param variant_name: Name of the variant, used as the working dir name. + :param extra_instr_cpp_args: Args passed to gnatcov instrument --c++-opts. + :param extra_gprbuild_cargs: Args passed to gprbuild -cargs. + :param pred: Predicate checked after building and running. + """ + + tmp = Wdir(f"tmp_{variant_name}") + build_and_run( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], + mains=["main.cpp"])), + covlevel="stmt", + mains=["main"], + extra_instr_args=[f"--c++-opts={','.join(extra_instr_cppargs)}"], + extra_gprbuild_cargs=extra_gprbuild_cargs, + trace_mode="src", + tolerate_instrument_messages=tolerate_instrument_messages, + extra_coverage_args=[], + register_failure=False, + ) + + thistest.fail_if( + not pred(), + f"Unexpected assertion failure for variant {variant_name}" + ) + + tmp.to_homedir() + + +run_variant( + variant_name="gprbuild-c++20", + extra_instr_cppargs=[], + extra_gprbuild_cargs=["-std=c++20"], + pred=lambda: "This is C++ code" in contents_of("main_output.txt"), +) +run_variant( + variant_name="instr-c89", + extra_instr_cppargs=["-std=c89"], + extra_gprbuild_cargs=[], + tolerate_instrument_messages="Failed to parse", + pred=lambda: "Failed to parse" in contents_of("instrument.log"), +) +run_variant( + variant_name="instr-gprbuild-c++20", + extra_instr_cppargs=["-std=c++20"], + extra_gprbuild_cargs=["-std=c++20"], + pred=lambda: "This is C++20 code" in contents_of("main_output.txt"), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.c b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.c new file mode 100644 index 000000000..e7ae34c15 --- /dev/null +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.c @@ -0,0 +1,9 @@ +#include "pkg1.h" +#include "pkg2.h" + +int +foo () +{ + int x = bar (); + return x; +} diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.h b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.h new file mode 100644 index 000000000..7d22617d4 --- /dev/null +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib1/pkg1.h @@ -0,0 +1,3 @@ +#include + +extern int foo (); diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.c b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.c new file mode 100644 index 000000000..9e73ed8dd --- /dev/null +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.c @@ -0,0 +1,7 @@ +#include + +int +bar () +{ + return 42; +} diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.h b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.h new file mode 100644 index 000000000..3d2c231a6 --- /dev/null +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src-lib2/pkg2.h @@ -0,0 +1 @@ +extern int bar (); diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src/main.c b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src/main.c new file mode 100644 index 000000000..b895b71b2 --- /dev/null +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/src/main.c @@ -0,0 +1,9 @@ +#include "pkg1.h" + +int +main () +{ + int x = foo (); + x += 1; + return 0; +} diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py new file mode 100644 index 000000000..d86a005af --- /dev/null +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py @@ -0,0 +1,57 @@ +""" +Regression testcase: check that the instrumentation of a C source including a +header from a project dependency works. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +def create_lib_gpr(name, deps=[]): + """ + Create a gpr file for the library. + + :param name: Name of the library. + """ + + return gprfor(mains=[], + prjid=name, + srcdirs=f"../src-{name}", + langs=["C"], + deps=deps, + extra=f""" + for Library_Name use "{name}"; + for Library_Dir use "{name}"; + """ + ) + + +tmp = Wdir("tmp_") + +# Create the GPR file for the root project +src_gpr = gprfor(mains=["main.c"], + prjid="main", + srcdirs="../src", + objdir="obj", + langs=["C"], + deps=["lib1", "lib2"] + ) + +# Create the GPR files for the libraries +lib1_gpr = create_lib_gpr("lib1", ["lib2"]) +lib2_gpr = create_lib_gpr("lib2") + +gprsw = GPRswitches(root_project=src_gpr) + +build_run_and_coverage(gprsw=gprsw, covlevel="stmt", mains=["main"], + extra_coverage_args=["-axcov"]) + +check_xcov_reports("obj/*.xcov", + {"obj/main.c.xcov": {"+": {6, 7, 8}}, + "obj/pkg1.c.xcov": {"+": {7, 8}}, + "obj/pkg2.c.xcov": {"+": {6}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/basic_base64/main.adb b/testsuite/tests/instr-cov/basic_base64/main.adb new file mode 100644 index 000000000..4937d0976 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_base64/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Main is + Who : constant String := "world"; +begin + Put_Line ("Hello, " & Who & "!"); + Put_Line ("Fact (6) = " & Integer'Image (Pkg.Fact (6))); +end Main; diff --git a/testsuite/tests/instr-cov/basic_base64/pkg.adb b/testsuite/tests/instr-cov/basic_base64/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_base64/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/basic_base64/pkg.ads b/testsuite/tests/instr-cov/basic_base64/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_base64/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/basic_base64/test.py b/testsuite/tests/instr-cov/basic_base64/test.py new file mode 100644 index 000000000..d48901a21 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_base64/test.py @@ -0,0 +1,27 @@ +""" +Test that instrumented source coverage works as expected when using +base64-stdout as the dump channel. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs='..', mains=['main.adb'])), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src', + dump_trigger='main-end', + dump_channel='base64-stdout') +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'+': {5, 7, 8}}, + 'xcov/pkg.adb.xcov': {'+': {5, 6, 8}}, +}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/basic_decision/main.adb b/testsuite/tests/instr-cov/basic_decision/main.adb new file mode 100644 index 000000000..1f27ba2c3 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_decision/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is + Dummy : constant Integer := Pkg.Fact (0); +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/basic_decision/p.gpr b/testsuite/tests/instr-cov/basic_decision/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_decision/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/basic_decision/pkg.adb b/testsuite/tests/instr-cov/basic_decision/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_decision/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/basic_decision/pkg.ads b/testsuite/tests/instr-cov/basic_decision/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_decision/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/basic_decision/test.py b/testsuite/tests/instr-cov/basic_decision/test.py new file mode 100644 index 000000000..083f5135d --- /dev/null +++ b/testsuite/tests/instr-cov/basic_decision/test.py @@ -0,0 +1,33 @@ +""" +Check that coverage for stmt+decision with source instrumentation works on a +basic project. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt+decision', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'+': {4, 6}}, + 'xcov/pkg.adb.xcov': {'+': {6}, '!': {5}, '-': {8}}, +}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/basic_stmt/main.adb b/testsuite/tests/instr-cov/basic_stmt/main.adb new file mode 100644 index 000000000..4937d0976 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_stmt/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Main is + Who : constant String := "world"; +begin + Put_Line ("Hello, " & Who & "!"); + Put_Line ("Fact (6) = " & Integer'Image (Pkg.Fact (6))); +end Main; diff --git a/testsuite/tests/instr-cov/basic_stmt/p.gpr b/testsuite/tests/instr-cov/basic_stmt/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_stmt/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/basic_stmt/pkg.adb b/testsuite/tests/instr-cov/basic_stmt/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_stmt/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/basic_stmt/pkg.ads b/testsuite/tests/instr-cov/basic_stmt/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_stmt/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/basic_stmt/test.py b/testsuite/tests/instr-cov/basic_stmt/test.py new file mode 100644 index 000000000..0bc235949 --- /dev/null +++ b/testsuite/tests/instr-cov/basic_stmt/test.py @@ -0,0 +1,31 @@ +""" +Test that instrumented source coverage works as expected on a basic scenario. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'+': {5, 7, 8}}, + 'xcov/pkg.adb.xcov': {'+': {5, 6, 8}}, +}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/bin_file_tunings/main.adb b/testsuite/tests/instr-cov/bin_file_tunings/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/instr-cov/bin_file_tunings/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/instr-cov/bin_file_tunings/test.opt b/testsuite/tests/instr-cov/bin_file_tunings/test.opt new file mode 100644 index 000000000..a78189307 --- /dev/null +++ b/testsuite/tests/instr-cov/bin_file_tunings/test.opt @@ -0,0 +1 @@ +!native DEAD Test specific to source trace binary files directly produced by automatic main instrumentation diff --git a/testsuite/tests/instr-cov/bin_file_tunings/test.py b/testsuite/tests/instr-cov/bin_file_tunings/test.py new file mode 100644 index 000000000..5c6ed9bd0 --- /dev/null +++ b/testsuite/tests/instr-cov/bin_file_tunings/test.py @@ -0,0 +1,128 @@ +""" +Check that the --dump-filename-env-var, --dump-filename-prefix and +--dump-filename-simple options work as expected. +""" + +from dataclasses import dataclass +import glob +import os +from typing import Dict, List + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +@dataclass +class Testcase: + test_name: str + """Name for this testcase.""" + + extra_args: List[str] + """Extra arguments to pass to "gnatcov instrument".""" + + extra_env_vars: Dict[str, str] + """Extra environment variables to pass to the instrumented program.""" + + expected_trace: str + """Glob pattern whose expansion must return exactly one source trace.""" + + +trace_prefix = "main" +if thistest.env.target.os.name == "windows": + trace_prefix += ".exe" + +for tc in [ + # Kind of sanity check: only use defaults, like all other testcases + Testcase("regular", [], {}, f"{trace_prefix}-*.srctrace"), + + # Check that with default instrumentation options and + # GNATCOV_TRACE_FILE set to a filename, the trace file is created using + # that filename. + Testcase("env_filename", + [], + {"GNATCOV_TRACE_FILE": "foo.srctrace"}, + "foo.srctrace"), + + # Check that with default instrumentation options and + # GNATCOV_TRACE_FILE set to a directory name, the trace file is created + # with a standard name under that directory. + Testcase("env_dir", + [], + {"GNATCOV_TRACE_FILE": "traces-dir/"}, + f"traces-dir/{trace_prefix}-*.srctrace"), + + # Check that with --dump-filename-env-var, the name of the environment + # variable changes. + Testcase("foo_env_1", + ["--dump-filename-env-var=FOO"], + {"GNATCOV_TRACE_FILE": "foo.srctrace"}, + f"{trace_prefix}-*.srctrace"), + Testcase("foo_env_2", + ["--dump-filename-env-var=FOO"], + {"FOO": "foo.srctrace"}, + "foo.srctrace"), + + # Check that with --dump-file-name-prefix, the given prefix replaces the + # program basename. + Testcase("prefix", ["--dump-filename-prefix=bar"], {}, "bar-*.srctrace"), + + # Check that with --dump-file-name-simple, the produced trace has a + # deterministic name. + Testcase("simple", + ["--dump-filename-simple"], + {}, + f"{trace_prefix}.srctrace"), +]: + thistest.log(f"==== {tc.test_name} ====") + + wd = Wdir(f"tmp_{tc.test_name}") + os.mkdir("traces-dir") + try: + env = dict(os.environ) + env.update(tc.extra_env_vars) + + xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], + mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_instr_args=tc.extra_args, + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + program_env=env, + + # The very goal of this testcase is to produce trace files with + # non-default names. build_and_run cannot deal with them, so skip + # checks here: the computing below are enough to check that the + # expected source trace file was produced. + register_failure=False, + ) + + # Check that we have the expected trace: + traces = glob.glob(tc.expected_trace) + if not traces: + thistest.fail_if( + True, + f"No source trace matched {tc.expected_trace}", + ) + continue + if len(traces) > 1: + thistest.fail_if( + True, + f"Too many source trace matched {tc.expected_trace}:\n" + + "\n".join(f"* {tf}" for tf in traces) + ) + continue + + # Sanity check that expected trace + xcov(xcov_args + traces, out="coverage.log") + check_xcov_reports("xcov/*.xcov", { + "xcov/main.adb.xcov": {"+": {5}}, + }) + finally: + wd.to_homedir() + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_custom_naming/hello.cc b/testsuite/tests/instr-cov/c_custom_naming/hello.cc new file mode 100644 index 000000000..62afcdf8c --- /dev/null +++ b/testsuite/tests/instr-cov/c_custom_naming/hello.cc @@ -0,0 +1,7 @@ +extern void dummy_putf (const char *fmt, ...); + +void +hello (const char *who) +{ + dummy_putf ("Hello %s\n", who); +} diff --git a/testsuite/tests/instr-cov/c_custom_naming/main.cc b/testsuite/tests/instr-cov/c_custom_naming/main.cc new file mode 100644 index 000000000..212dc502d --- /dev/null +++ b/testsuite/tests/instr-cov/c_custom_naming/main.cc @@ -0,0 +1,13 @@ +extern void hello (const char *who); + +void +dummy_putf (const char *fmt, ...) +{ +} + +int +main (void) +{ + hello ("world"); + return 0; +} diff --git a/testsuite/tests/instr-cov/c_custom_naming/test.opt b/testsuite/tests/instr-cov/c_custom_naming/test.opt new file mode 100644 index 000000000..3d918a25a --- /dev/null +++ b/testsuite/tests/instr-cov/c_custom_naming/test.opt @@ -0,0 +1 @@ +!C++ DEAD test requires a supported C++ compiler \ No newline at end of file diff --git a/testsuite/tests/instr-cov/c_custom_naming/test.py b/testsuite/tests/instr-cov/c_custom_naming/test.py new file mode 100644 index 000000000..b191e1555 --- /dev/null +++ b/testsuite/tests/instr-cov/c_custom_naming/test.py @@ -0,0 +1,47 @@ +""" +Check that custom naming conventions for file-based languages are properly +handled. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + # gprfor assumes standard naming convention for mains, so we must + # control the mains manually. + root_project=gprfor( + srcdirs=[".."], + mains=[], + langs=["C++"], + extra=""" + for Main use ("main.cc"); + package Naming is + for Body_Suffix ("C++") use ".cc"; + for Spec_Suffix ("C++") use ".hh"; + end Naming; + """, + ), + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "*.xcov", + { + "main.cc.xcov": {"+": {11, 12}}, + "hello.cc.xcov": {"+": {6}}, + }, + cwd="xcov", +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_empty_source/main.c b/testsuite/tests/instr-cov/c_empty_source/main.c new file mode 100644 index 000000000..1d28fd918 --- /dev/null +++ b/testsuite/tests/instr-cov/c_empty_source/main.c @@ -0,0 +1,7 @@ +#include "pkg.h" + +int +main () +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/c_empty_source/pkg.c b/testsuite/tests/instr-cov/c_empty_source/pkg.c new file mode 100644 index 000000000..59db5edf9 --- /dev/null +++ b/testsuite/tests/instr-cov/c_empty_source/pkg.c @@ -0,0 +1,7 @@ +#ifdef UNDEFINED_MACRO +int +foo () +{ + return 0; +} +#endif diff --git a/testsuite/tests/instr-cov/c_empty_source/pkg.h b/testsuite/tests/instr-cov/c_empty_source/pkg.h new file mode 100644 index 000000000..ee9b424fe --- /dev/null +++ b/testsuite/tests/instr-cov/c_empty_source/pkg.h @@ -0,0 +1,3 @@ +#ifdef UNDEFINED_MACRO +int foo (); +#endif diff --git a/testsuite/tests/instr-cov/c_empty_source/test.py b/testsuite/tests/instr-cov/c_empty_source/test.py new file mode 100644 index 000000000..9806e7be2 --- /dev/null +++ b/testsuite/tests/instr-cov/c_empty_source/test.py @@ -0,0 +1,26 @@ +""" +Regression testcase: checks that gnatcov does not crash when one of the sources +of interest is empty. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +# Build and produce a coverage report for the test project. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.c'])), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src', +) + +check_xcov_reports('*.xcov', {'main.c.xcov': {'+': {6}}}, 'xcov') + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_gpr_opts/hello.c b/testsuite/tests/instr-cov/c_gpr_opts/hello.c new file mode 100644 index 000000000..a2affa303 --- /dev/null +++ b/testsuite/tests/instr-cov/c_gpr_opts/hello.c @@ -0,0 +1,13 @@ +extern void dummy_putf (const char *fmt, ...); + +void +hello (const char *who) +{ +#ifdef A + dummy_putf ("Hello %s\n", who); +#endif + +#ifdef B + dummy_putf ("Goodbye %s\n", who); +#endif +} diff --git a/testsuite/tests/instr-cov/c_gpr_opts/main.c b/testsuite/tests/instr-cov/c_gpr_opts/main.c new file mode 100644 index 000000000..4af127a44 --- /dev/null +++ b/testsuite/tests/instr-cov/c_gpr_opts/main.c @@ -0,0 +1,20 @@ +extern void hello (const char *who); + +void +dummy_putf (const char *fmt, ...) +{ +} + +int +main (void) +{ +#ifdef A + hello ("A"); +#endif + +#ifdef B + hello ("B"); +#endif + + return 0; +} diff --git a/testsuite/tests/instr-cov/c_gpr_opts/test.py b/testsuite/tests/instr-cov/c_gpr_opts/test.py new file mode 100644 index 000000000..3fad21d70 --- /dev/null +++ b/testsuite/tests/instr-cov/c_gpr_opts/test.py @@ -0,0 +1,40 @@ +""" +Check that compiler switches are properly imported from project files. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=[".."], + mains=["main.c"], + compiler_extra=""" + for Default_Switches ("C") use ("-DA"); + for Switches ("main.c") use ("-DB"); + """, + ), + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "*.xcov", + { + "main.c.xcov": {"+": {16, 19}}, + "hello.c.xcov": {"+": {7}}, + }, + cwd="xcov", +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_header/fact.h b/testsuite/tests/instr-cov/c_header/fact.h new file mode 100644 index 000000000..4cbc8f9a4 --- /dev/null +++ b/testsuite/tests/instr-cov/c_header/fact.h @@ -0,0 +1,8 @@ +static int +fact (int n) +{ + if (n <= 1) + return 1; + else + return n * fact (n - 1); +} diff --git a/testsuite/tests/instr-cov/c_header/main.c b/testsuite/tests/instr-cov/c_header/main.c new file mode 100644 index 000000000..8daba19a4 --- /dev/null +++ b/testsuite/tests/instr-cov/c_header/main.c @@ -0,0 +1,8 @@ +#include "fact.h" + +int +main (void) +{ + int dummy = fact (6); + return 0; +} diff --git a/testsuite/tests/instr-cov/c_header/test.py b/testsuite/tests/instr-cov/c_header/test.py new file mode 100644 index 000000000..4e8af9c7e --- /dev/null +++ b/testsuite/tests/instr-cov/c_header/test.py @@ -0,0 +1,42 @@ +""" +Check that the instrumentation of a C project does not instrument the header +files: we only instrument the code in header files once it has been included in +a ".c" file *when* we instrument that ".c" file. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +# Build and produce a coverage report for the test project. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src', +) +check_xcov_reports( + '*.xcov', + { + 'main.c.xcov': {'+': {6, 7}}, + 'fact.h.xcov': {'+': {4, 5, 7}}, + }, + "xcov" +) + +# Check that the header file is not instrumented +instr_header = os.path.join("obj", "gen-gnatcov-instr", "fact.h") +thistest.fail_if( + os.path.isfile(instr_header), + f"Found spurious {instr_header} file", +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_macros_no_cov_warnings/dummy-print.c b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/dummy-print.c new file mode 100644 index 000000000..1e5067822 --- /dev/null +++ b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/dummy-print.c @@ -0,0 +1,4 @@ +void +print_str (const char *str) +{ +} diff --git a/testsuite/tests/instr-cov/c_macros_no_cov_warnings/main.c b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/main.c new file mode 100644 index 000000000..4fcecf768 --- /dev/null +++ b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/main.c @@ -0,0 +1,12 @@ +#include + +extern void print_str (const char *str); + +#define PRINT_HW print_str ("Hello world!\n"); + +int +main (void) +{ + PRINT_HW; + return 0; +} diff --git a/testsuite/tests/instr-cov/c_macros_no_cov_warnings/test.py b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/test.py new file mode 100644 index 000000000..911368e02 --- /dev/null +++ b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/test.py @@ -0,0 +1,28 @@ +""" +Check that we have no warnings at coverage time for a format report that +needs to preprocess the file, to emit macro reporting. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.c'])), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axml'], + trace_mode='src', +) + +# Check that gnatcov coverage did not raise any warning +thistest.fail_if_not_equal( + "gnatcov coverage output", "", contents_of("coverage.log") +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/main.c b/testsuite/tests/instr-cov/c_multiline_stmt/main.c new file mode 100644 index 000000000..260024cfb --- /dev/null +++ b/testsuite/tests/instr-cov/c_multiline_stmt/main.c @@ -0,0 +1,35 @@ +#include "pkg.h" + +int +id (int x) +{ + return x; +} + +int +main () +{ + int x = 2, i; + + // Check do-while statement. A closing brace should be inserted before the + // while. + do + x++ + // dumb-token + ; + while (x < 2); + + // Check nested if-else statements. For each un-braced control flow stmt, + // a closing brace should be inserted before the next statement, or before + // the else / while if the control flow stmt is featured in a then part / a + // do body respectively. + if (id (x) != x) + for (i = 0; i++; i < 10) + return 0 + // dumb-token + ; + else if (foo ()) + return 0 + // dumb-token + ; +} diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/pkg.c b/testsuite/tests/instr-cov/c_multiline_stmt/pkg.c new file mode 100644 index 000000000..414317712 --- /dev/null +++ b/testsuite/tests/instr-cov/c_multiline_stmt/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 1; +} diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/pkg.h b/testsuite/tests/instr-cov/c_multiline_stmt/pkg.h new file mode 100644 index 000000000..f8f1dde0b --- /dev/null +++ b/testsuite/tests/instr-cov/c_multiline_stmt/pkg.h @@ -0,0 +1 @@ +extern int foo (); diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/test.opt b/testsuite/tests/instr-cov/c_multiline_stmt/test.opt new file mode 100644 index 000000000..e42397385 --- /dev/null +++ b/testsuite/tests/instr-cov/c_multiline_stmt/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific behavior \ No newline at end of file diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/test.py b/testsuite/tests/instr-cov/c_multiline_stmt/test.py new file mode 100644 index 000000000..a5da42c35 --- /dev/null +++ b/testsuite/tests/instr-cov/c_multiline_stmt/test.py @@ -0,0 +1,75 @@ +""" +Regression testcase: checks that gnatcov can correctly instrument a statement +body of a control flow statement, when it spans on several lines and has at +least one token separating the statement expression and the terminating +semicolon, e.g. + + if + + // dumb-token + ; + +should be instrumented as + + if () + { + + // dumb-token + ; + } + +gnatcov used to insert the closing brace before the terminating semicolon. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_with_main") + +# Check when the main is a unit of interest +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "*.xcov", + { + "main.c.xcov": {"+": {6, 12, 17, 26, 31, 32}, "-": {27, 28}}, + "pkg.c.xcov": {"+": {4}}, + }, + "xcov", +) + +tmp.to_homedir() +tmp = Wdir("tmp_without_main") + +# Also check when the main needs to be instrumented to dump the buffers with +# main-end but is not a unit of interest. We used to surround the return +# statement with braces, as we needed to declare a variable holding the return +# expression beforehand. This variable is now declared at the beginning of the +# main. +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.c"]), + units=["pkg.c"], + ), + covlevel="stmt", + mains=["main"], + dump_trigger="main-end", + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports("*.xcov", {"pkg.c.xcov": {"+": {4}}}, "xcov") + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_no_return/empty_main/main.c b/testsuite/tests/instr-cov/c_no_return/empty_main/main.c new file mode 100644 index 000000000..70b41462b --- /dev/null +++ b/testsuite/tests/instr-cov/c_no_return/empty_main/main.c @@ -0,0 +1,4 @@ +int +main () +{ +} diff --git a/testsuite/tests/instr-cov/c_no_return/no_return/main.c b/testsuite/tests/instr-cov/c_no_return/no_return/main.c new file mode 100644 index 000000000..e8241104d --- /dev/null +++ b/testsuite/tests/instr-cov/c_no_return/no_return/main.c @@ -0,0 +1,15 @@ +int +fact (int a) +{ + if (a == 1) + return 1; + return a * fact (a - 1); +} + +int +main (void) +{ + int dummy = fact (6); + if (!dummy) + return 0; +} diff --git a/testsuite/tests/instr-cov/c_no_return/test.py b/testsuite/tests/instr-cov/c_no_return/test.py new file mode 100644 index 000000000..127bac479 --- /dev/null +++ b/testsuite/tests/instr-cov/c_no_return/test.py @@ -0,0 +1,53 @@ +""" +Check that gnatcov always insert a call to dump buffers, even when the main +does not end with a return statement, when the dump-trigger is main-end. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp_no_return = Wdir("tmp_no_return") + +# Check when the main function does not exit through a return +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[os.path.join("..", "no_return")], mains=["main.c"]) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="main-end", + + # With older toolchains, a missing return results in an arbitrary exit + # code, so let's ignore failures. + + register_failure=False, +) +check_xcov_reports( + "*.xcov", {"main.c.xcov": {"+": {4, 5, 6, 12, 13}, "-": {14}}}, "xcov" +) + +tmp_no_return.to_homedir() +tmp = Wdir("tmp_empty_main") + +# Check that we have a source trace even if the main is empty +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=[os.path.join("..", "empty_main")], mains=["main.c"] + ) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="main-end", +) +thistest.result() diff --git a/testsuite/tests/instr-cov/c_opts/hello.c b/testsuite/tests/instr-cov/c_opts/hello.c new file mode 100644 index 000000000..677b9f6e6 --- /dev/null +++ b/testsuite/tests/instr-cov/c_opts/hello.c @@ -0,0 +1,4 @@ +void +hello (const char *who) +{ +} diff --git a/testsuite/tests/instr-cov/c_opts/main.c b/testsuite/tests/instr-cov/c_opts/main.c new file mode 100644 index 000000000..6e296318a --- /dev/null +++ b/testsuite/tests/instr-cov/c_opts/main.c @@ -0,0 +1,15 @@ +#include "hello.h" + +int +main (void) +{ +#ifdef A + hello ("A"); +#endif + +#ifdef B + hello ("B"); +#endif + + return 0; +} diff --git a/testsuite/tests/instr-cov/c_opts/other/hello.h b/testsuite/tests/instr-cov/c_opts/other/hello.h new file mode 100644 index 000000000..d4370d4a9 --- /dev/null +++ b/testsuite/tests/instr-cov/c_opts/other/hello.h @@ -0,0 +1 @@ +extern void hello (const char *who); diff --git a/testsuite/tests/instr-cov/c_opts/test.py b/testsuite/tests/instr-cov/c_opts/test.py new file mode 100644 index 000000000..208aeac73 --- /dev/null +++ b/testsuite/tests/instr-cov/c_opts/test.py @@ -0,0 +1,54 @@ +""" +Check that --c-opts option for "gnatcov instrument" works as expected. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +other_dir = os.path.abspath("other") +tmp = Wdir("tmp_") + +c_opts = [ + # Without these arguments, "hello.h" cannot be imported, and the A macro is + # not defined. Exercize the various forms for these arguments: -XA, -X A). + # Also add these as two "--c-opts" arguments. + ["-DA", "-D", "B", "-UB"], + ["-I", other_dir], + + # Check the processing of backslashes + ["-DBACKSLASH=\\"], + ["-DDOUBLE_BACKSLASH=\\\\"], + ["-DCOMMA=\\,"], +] + +log_file = "instrument.log" +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.c"]), + units=["main.c"], + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=( + ["--c-opts={}".format(",".join(args)) for args in c_opts] + + ["-v"] + ), + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +for excerpt in ["-DBACKSLASH=\\", "-DDOUBLE_BACKSLASH=\\", "-DCOMMA=,"]: + thistest.fail_if( + excerpt not in contents_of(log_file), + f"{excerpt} macro definition not found in {log_file}" + ) + +check_xcov_reports("*.xcov", {"main.c.xcov": {"+": {7, 14}}}, cwd="xcov") + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_prep_error/main.c b/testsuite/tests/instr-cov/c_prep_error/main.c new file mode 100644 index 000000000..3929d095e --- /dev/null +++ b/testsuite/tests/instr-cov/c_prep_error/main.c @@ -0,0 +1,7 @@ +#include "foo.hh" + +int +main () +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/c_prep_error/test.py b/testsuite/tests/instr-cov/c_prep_error/test.py new file mode 100644 index 000000000..82b4bd517 --- /dev/null +++ b/testsuite/tests/instr-cov/c_prep_error/test.py @@ -0,0 +1,35 @@ +""" +Check that C/C++ preprocessing failures are properly reported. +""" + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +log_file = "instr.txt" +p = xcov_instrument( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + out=log_file, + register_failure=False, +) + +# Make sure that preprocessing fails with exit code 1, that the output mentions +# the missing file (the bit that is useful to users in order to understand what +# went wrong), plus the "abort" message. + +thistest.fail_if_not_equal("'gnatcov instrument' exit code", 1, p.status) + +log = contents_of(log_file) +for excerpt in ["foo.hh", "Preprocessing failed: aborting"]: + thistest.fail_if( + excerpt not in log, + f"Missing excerpt in {log_file}: {repr(excerpt)}" + ) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_special_filenames/$foo@bar$.c b/testsuite/tests/instr-cov/c_special_filenames/$foo@bar$.c new file mode 100644 index 000000000..82907e5e7 --- /dev/null +++ b/testsuite/tests/instr-cov/c_special_filenames/$foo@bar$.c @@ -0,0 +1,5 @@ +int +foo (int i) +{ + return 2 * i; +} diff --git a/testsuite/tests/instr-cov/c_special_filenames/ada_main.adb b/testsuite/tests/instr-cov/c_special_filenames/ada_main.adb new file mode 100644 index 000000000..6fe842a78 --- /dev/null +++ b/testsuite/tests/instr-cov/c_special_filenames/ada_main.adb @@ -0,0 +1,10 @@ +with Interfaces.C; use Interfaces.C; + +procedure Ada_Main is + function Foo (I : int) return int; + pragma Import (C, Foo, "foo"); + + I : constant int := Foo (1); +begin + null; +end Ada_Main; diff --git a/testsuite/tests/instr-cov/c_special_filenames/main.c b/testsuite/tests/instr-cov/c_special_filenames/main.c new file mode 100644 index 000000000..ec9915a9c --- /dev/null +++ b/testsuite/tests/instr-cov/c_special_filenames/main.c @@ -0,0 +1,8 @@ +extern int foo (int i); + +int +main (void) +{ + int result = foo (0); + return result; +} diff --git a/testsuite/tests/instr-cov/c_special_filenames/test.opt b/testsuite/tests/instr-cov/c_special_filenames/test.opt new file mode 100644 index 000000000..930d7837e --- /dev/null +++ b/testsuite/tests/instr-cov/c_special_filenames/test.opt @@ -0,0 +1 @@ +!C++ DEAD test requires C++ compiler \ No newline at end of file diff --git a/testsuite/tests/instr-cov/c_special_filenames/test.py b/testsuite/tests/instr-cov/c_special_filenames/test.py new file mode 100644 index 000000000..a82f2d837 --- /dev/null +++ b/testsuite/tests/instr-cov/c_special_filenames/test.py @@ -0,0 +1,34 @@ +""" +Test that the instrumentation of C sources with filenames that contain uncommon +characters produces valid instrumented sources. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=['..'], mains=['main.c', 'ada_main.adb']) + ), + covlevel='stmt', + mains=['main', 'ada_main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src', +) +check_xcov_reports( + '*.xcov', + { + 'main.c.xcov': {'+': {6}}, + '$foo@bar$.c.xcov': {'+': {4}}, + 'ada_main.adb.xcov': {'+': {9}}, + }, + 'xcov', +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_ternary_in_if_cond/main.c b/testsuite/tests/instr-cov/c_ternary_in_if_cond/main.c new file mode 100644 index 000000000..a8dea3024 --- /dev/null +++ b/testsuite/tests/instr-cov/c_ternary_in_if_cond/main.c @@ -0,0 +1,10 @@ +int +main () +{ + int i = 0; + if (i ? 0 : 1) + { + return 0; + } + return 0; +} diff --git a/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py b/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py new file mode 100644 index 000000000..8c6bea041 --- /dev/null +++ b/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py @@ -0,0 +1,29 @@ +""" +Check that the instrumentation of a decision whose condition is a ternary +expression works. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +# Build and produce a coverage report for the test project. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.c'])), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src', +) +check_xcov_reports( + '*.xcov', + {'main.c.xcov': {'+': {4, 5, 7}, '-': {9}}}, + 'xcov' +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_wrong_main/main.c b/testsuite/tests/instr-cov/c_wrong_main/main.c new file mode 100644 index 000000000..5fe6f506f --- /dev/null +++ b/testsuite/tests/instr-cov/c_wrong_main/main.c @@ -0,0 +1,5 @@ +int +not_a_main (void) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/c_wrong_main/test.py b/testsuite/tests/instr-cov/c_wrong_main/test.py new file mode 100644 index 000000000..de829d9d6 --- /dev/null +++ b/testsuite/tests/instr-cov/c_wrong_main/test.py @@ -0,0 +1,32 @@ +""" +Check that gnatcov emits a fatal error when a main file does not contain the +main program. +""" + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +# Create object directory to avoid GPR warning +mkdir("obj") + +p = xcov_instrument( + GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.c'])), + covlevel='stmt', + register_failure=False, +) +thistest.fail_if_not_equal('gnatcov instrument status code', 1, p.status) +thistest.fail_if_no_match( + 'gnatcov instrument output', + '.*gnatcov.*: Could not find main function in main.c', + contents_of('instrument.log').strip(), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/checks_and_warnings/main.adb b/testsuite/tests/instr-cov/checks_and_warnings/main.adb new file mode 100644 index 000000000..cc02a39d8 --- /dev/null +++ b/testsuite/tests/instr-cov/checks_and_warnings/main.adb @@ -0,0 +1,16 @@ +with Pkg; + +procedure Main is + pragma Warnings (On); + pragma Warnings ("a"); + pragma Style_Checks (On); + pragma Style_Checks ("yg"); + + -- The insertion of the witness call will make the following like exceed + -- the 80 characters limit. Also, S is an unused variable, GNAT will warn + -- about it. + + S : String := "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; +begin + Pkg.P; +end Main; diff --git a/testsuite/tests/instr-cov/checks_and_warnings/p.gpr b/testsuite/tests/instr-cov/checks_and_warnings/p.gpr new file mode 100644 index 000000000..a37807ae5 --- /dev/null +++ b/testsuite/tests/instr-cov/checks_and_warnings/p.gpr @@ -0,0 +1,8 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); + + package Compiler is + for Default_Switches ("Ada") use ("-gnatwae", "-gnatyg"); + end Compiler; +end P; diff --git a/testsuite/tests/instr-cov/checks_and_warnings/pkg.ads b/testsuite/tests/instr-cov/checks_and_warnings/pkg.ads new file mode 100644 index 000000000..39bfceb1a --- /dev/null +++ b/testsuite/tests/instr-cov/checks_and_warnings/pkg.ads @@ -0,0 +1,23 @@ +package Pkg is + procedure P is null; + -- This test checks that no style warnings are issued when compiling + -- instrumented sources. + -- As a reminder, each instrumented unit has an associated buffer + -- unit (defining the buffers and exporting them as symbols), and a + -- pure buffer unit (defining pointers to coverage buffers and + -- importing the definition symbols). The pure buffer unit is imported + -- into the instrumented unit and the buffers declared in this unit are + -- used for coverage analysis. These generated buffer units do not + -- respect any style conventions, just like instrumented files. + -- + -- Sometimes, gnatcov also needs to generate additional code, to + -- support specific language constructions, such as null procedures. + -- In this case, additional code will be generated in the pure buffer + -- unit body (otherwise, there will be no body for this unit, only a + -- spec, as no actual code is required), as it is the unit imported by + -- the instrumented file. + -- As this testcase should exercise all different kinds of files + -- generated by gnatcov (instrumented files, buffers spec / body), + -- it also exercises this corner case. This explains the null procedure + -- here. +end Pkg; diff --git a/testsuite/tests/instr-cov/checks_and_warnings/test.opt b/testsuite/tests/instr-cov/checks_and_warnings/test.opt new file mode 100644 index 000000000..a4e1eba80 --- /dev/null +++ b/testsuite/tests/instr-cov/checks_and_warnings/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/instr-cov/checks_and_warnings/test.py b/testsuite/tests/instr-cov/checks_and_warnings/test.py new file mode 100644 index 000000000..063aacf2f --- /dev/null +++ b/testsuite/tests/instr-cov/checks_and_warnings/test.py @@ -0,0 +1,35 @@ +""" +Test that style check issues and warnings are properly disabled in instrumented +sources. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt+decision', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + extra_gprbuild_cargs=['-gnatwae'], + check_gprbuild_output=True, + trace_mode='src') +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'+': {13}}, + 'xcov/pkg.ads.xcov': {'+': {2}}, +}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/consistency/main.adb b/testsuite/tests/instr-cov/consistency/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/instr-cov/consistency/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/instr-cov/consistency/p.gpr b/testsuite/tests/instr-cov/consistency/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/consistency/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/consistency/test.py b/testsuite/tests/instr-cov/consistency/test.py new file mode 100644 index 000000000..8857645e0 --- /dev/null +++ b/testsuite/tests/instr-cov/consistency/test.py @@ -0,0 +1,93 @@ +""" +Test that gnatcov properly report source trace files that are inconsistent with +the provided SID files. +""" + +import os +import os.path + +from e3.fs import cp, mkdir + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, xcov + + +p_gpr = 'p.gpr' +first_sid_file = 'first.sid' + +tmp = Wdir('tmp_') + +# As this test modifies source files, create a working copy +for filename in ('p.gpr', 'main.adb'): + cp(os.path.join('..', filename), filename) + + +# Instrument the input project and back up the SID file for main.adb +xcov_instrument( + gprsw=GPRswitches(root_project=p_gpr), + gpr_obj_dir='obj', + covlevel='stmt') +cp(os.path.join('obj', 'main.sid'), first_sid_file) + +# Modify the source file and re-instrument it +with open('main.adb', 'w') as f: + f.write(""" +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 2); + end if; + end Fact; + +begin + Put_Line ("Fact (6) = " & Integer'Image (Fact (6))); +end Main; +""") + +# Now, instrument and build it. Then run the main program, letting it produce a +# trace. +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt', + gpr_obj_dir='obj', + gpr_exe_dir='obj', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src') +srctrace = xcov_args[-1] + +# Now try to run a coverage analysis with the trace file produced for the +# second SID file but giving gnatcov the first one. +out_file = 'gnatcov.out' +mkdir('xcov') +xcov(['coverage', '-axcov', '-cstmt', '--output-dir=xcov', + '--sid', first_sid_file, srctrace], out=out_file) + +# Check that gnatcov warns about inconsistent fingerprints +actual = contents_of(out_file).strip() +expected = ('warning: traces for body of main (from {}) are' + ' inconsistent with the corresponding Source Instrumentation Data' + .format(srctrace)) +thistest.fail_if(expected != actual, + 'Unexpected output for "gnatcov coverage". Expected:\n' + '{}\n' + 'but got:\n' + '{}'.format(indent(expected), indent(actual))) + +# gnatcov only see the first SID file, so it is expected to have the coverage +# obligations coming from the first instrumentation. Besides, since it +# discarded info from the trace file, gnatcov is supposed to report violations +# for all coverage obligations related to the first version of "main.adb". +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'-': {5}}, +}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/decl-inversion/src/test_foo.adb b/testsuite/tests/instr-cov/decl-inversion/src/test_foo.adb new file mode 100644 index 000000000..3bbf356c2 --- /dev/null +++ b/testsuite/tests/instr-cov/decl-inversion/src/test_foo.adb @@ -0,0 +1,23 @@ +pragma Ada_2012; + +procedure Test_Foo is + Bool1 : Boolean := True; + pragma Volatile (Bool1); + Bool2 : Boolean := True; + pragma Volatile (Bool2); + + -- This test would fail to build if the intrumentation inverted the order + -- of the declaration of Int1 and of the function Foo. + + Int1 : Integer := (if Bool1 and then Bool2 then 0 else 1); -- # Integer + pragma Volatile (Int1); + + function Foo return Integer is (Int1); -- # Expr_Fun +begin + Int1 := Foo; +end Test_Foo; + +--# test_foo.adb +-- +-- /Integer/ l! ## dF- +-- /Expr_Fun/ l+ ## 0 \ No newline at end of file diff --git a/testsuite/tests/instr-cov/decl-inversion/test.opt b/testsuite/tests/instr-cov/decl-inversion/test.opt new file mode 100644 index 000000000..498980ea4 --- /dev/null +++ b/testsuite/tests/instr-cov/decl-inversion/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD expression functions not available in 5.04 +7.1.2 DEAD support for expression functions weak in 7.1.2 \ No newline at end of file diff --git a/testsuite/tests/instr-cov/decl-inversion/test.py b/testsuite/tests/instr-cov/decl-inversion/test.py new file mode 100644 index 000000000..91e833410 --- /dev/null +++ b/testsuite/tests/instr-cov/decl-inversion/test.py @@ -0,0 +1,12 @@ +""" +Check that instrumentation of declarations preserves the initial order of the +declarations in the region. +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT +from SCOV.tc import TestCase + +TestCase(category=CAT.mcdc).run() + +thistest.result() diff --git a/testsuite/tests/instr-cov/default_dump_channel/main.adb b/testsuite/tests/instr-cov/default_dump_channel/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/instr-cov/default_dump_channel/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/default_dump_channel/test.opt b/testsuite/tests/instr-cov/default_dump_channel/test.opt new file mode 100644 index 000000000..cb7409573 --- /dev/null +++ b/testsuite/tests/instr-cov/default_dump_channel/test.opt @@ -0,0 +1,2 @@ +!src-traces DEAD Checks a feature specific to the instrumenter +!native DEAD Checks the default dump channel (bin-file, native only) diff --git a/testsuite/tests/instr-cov/default_dump_channel/test.py b/testsuite/tests/instr-cov/default_dump_channel/test.py new file mode 100644 index 000000000..2d2ae01f2 --- /dev/null +++ b/testsuite/tests/instr-cov/default_dump_channel/test.py @@ -0,0 +1,67 @@ +""" +Test that programs instrumented with the default dump channel (no +--dump-channel argument) behave as expected given the --dump-filename-* +arguments that are passed (or omitted) to "gnatcov instrument". + +gnatcov used to ignore --dump-trigger and --dump-filename-* options when +--dump-channel was omitted. +""" + +from __future__ import annotations + +from dataclasses import dataclass, field +import glob +import os + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import (exename_for, exepath_to, gprbuild, gprfor, + run_cov_program, xcov) + + +@dataclass +class Test: + label: str + """Simple string to identify the test.""" + + srctrace_pattern: str + """Glob pattern for the expected source trace file.""" + + options: list[str] = field(default_factory=list) + """List of additional options for "gnatcov instrument".""" + + env: dict[str, str] = field(default_factory=dict) + """Additional environment variables for the executed program.""" + + +# Default prefix for the created source trace ("main.exe" on Windows) +default_prefix = exename_for("main") + +for t in [ + Test("none", f"{default_prefix}-*-*-*.srctrace"), + Test("simple", f"{default_prefix}.srctrace", ["--dump-filename-simple"]), + Test("prefix", "bar-*-*-*.srctrace", ["--dump-filename-prefix=bar"]), + Test("env-var", + "mytrace.srctrace", + ["--dump-filename-env-var=MY_TRACE_FILE"], + {"MY_TRACE_FILE": "mytrace.srctrace"}), +]: + tmp = Wdir(f"tmp_{t.label}") + + prj = gprfor(mains=["main.adb"], srcdirs=[".."]) + xcov(["instrument", "-P", prj, "-cstmt", "--dump-trigger=atexit"] + + t.options) + gprbuild(prj, trace_mode="src") + + env = dict(os.environ) + env.update(t.env) + run_cov_program(exepath_to("main"), out="run.log", env=env) + + thistest.fail_if( + len(glob.glob(t.srctrace_pattern)) != 1, + f"{t.label}: could not find a file matching {t.srctrace_pattern}" + ) + + tmp.to_homedir() + +thistest.result() diff --git a/testsuite/tests/instr-cov/end_slocs/main.adb b/testsuite/tests/instr-cov/end_slocs/main.adb new file mode 100644 index 000000000..ffb7d45cf --- /dev/null +++ b/testsuite/tests/instr-cov/end_slocs/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put ("Hello ");Put_Line ("world!"); +end Main; diff --git a/testsuite/tests/instr-cov/end_slocs/p.gpr b/testsuite/tests/instr-cov/end_slocs/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/end_slocs/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/end_slocs/test.py b/testsuite/tests/instr-cov/end_slocs/test.py new file mode 100644 index 000000000..49d84b061 --- /dev/null +++ b/testsuite/tests/instr-cov/end_slocs/test.py @@ -0,0 +1,35 @@ +""" +Regression test: gnatcov used to warn bout duplicate statement SCOs when two +statements were on the same line and not separated by a space. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath('p.gpr') + +# If it does not exist, create p.gpr's object directory to avoid noise in +# gnatcov's output. +obj_dir = os.path.abspath('obj') +if not os.path.isdir(obj_dir): + os.mkdir(obj_dir) + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') +check_xcov_reports('xcov/*.xcov', {'xcov/main.adb.xcov': {'+': {5}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/endianity/main.adb b/testsuite/tests/instr-cov/endianity/main.adb new file mode 100644 index 000000000..7824944ff --- /dev/null +++ b/testsuite/tests/instr-cov/endianity/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Main is + Who : constant String := "world"; +begin + Put_Line ("Hello, " & Who & "!"); + Put_Line ("Fact (6) = " & Integer'Image (Pkg.Fact (6, True))); +end Main; diff --git a/testsuite/tests/instr-cov/endianity/pkg.adb b/testsuite/tests/instr-cov/endianity/pkg.adb new file mode 100644 index 000000000..7012163f8 --- /dev/null +++ b/testsuite/tests/instr-cov/endianity/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer; B : Boolean) return Integer is + begin + if I < 2 and then B then + return 1; + else + return I * Fact (I - 1, B); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/endianity/pkg.ads b/testsuite/tests/instr-cov/endianity/pkg.ads new file mode 100644 index 000000000..29d56f436 --- /dev/null +++ b/testsuite/tests/instr-cov/endianity/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer; B : Boolean) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/endianity/test.py b/testsuite/tests/instr-cov/endianity/test.py new file mode 100644 index 000000000..3818dc291 --- /dev/null +++ b/testsuite/tests/instr-cov/endianity/test.py @@ -0,0 +1,51 @@ +""" +Test that gnatcov can read source trace files in any endianity. + +This test rewrites an existing trace file itself so that we can test both +endianity even though we are running programs on a host that supports a single +endianity. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.srctracelib import SrcTraceFile +from SUITE.stream_decoder import ByteStreamDecoder +from SUITE.tutils import gprfor, xcov + + +tmp = Wdir('tmp_') + +# Build a project, run it and create a source trace file +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor('main.adb', srcdirs='..')), + covlevel='stmt+mcdc', + mains=['main'], + extra_coverage_args=['-axcov'], + trace_mode='src') +trace_file = xcov_args[-1] + +# Read this trace file and generate two other files, one per endianity +with open(trace_file, 'rb') as f: + tf = SrcTraceFile.read(ByteStreamDecoder(f)) +with open('le.srctrace', 'wb') as f: + tf.endianity = 'little-endian' + tf.write(f) +with open('be.srctrace', 'wb') as f: + tf.endianity = 'big-endian' + tf.write(f) + +# Check that gnatcov decodes both the same way +xcov(xcov_args + ['--output-dir=xcov-le', 'le.srctrace'], + out='coverage-le.log') +xcov(xcov_args + ['--output-dir=xcov-be', 'be.srctrace'], + out='coverage-be.log') +check_xcov_reports('xcov-*/*.xcov', { + 'xcov-le/main.adb.xcov': {'+': {5, 7, 8}}, + 'xcov-be/main.adb.xcov': {'+': {5, 7, 8}}, + 'xcov-le/pkg.adb.xcov': {'+': {6, 8}, '!': {5}}, + 'xcov-be/pkg.adb.xcov': {'+': {6, 8}, '!': {5}}, +}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/explicit_mains/foo.s b/testsuite/tests/instr-cov/explicit_mains/foo.s new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/instr-cov/explicit_mains/main1.adb b/testsuite/tests/instr-cov/explicit_mains/main1.adb new file mode 100644 index 000000000..9f4eac637 --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains/main1.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; use Pkg; + +procedure Main1 is +begin + Put_Line ("Fact (0) = " & Integer'Image (Pkg.Fact (6))); +end Main1; diff --git a/testsuite/tests/instr-cov/explicit_mains/main2.adb b/testsuite/tests/instr-cov/explicit_mains/main2.adb new file mode 100644 index 000000000..fb79c6a0c --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains/main2.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; use Pkg; + +procedure Main2 is +begin + Put_Line ("Fact (0) = " & Integer'Image (Pkg.Fact (0))); +end Main2; diff --git a/testsuite/tests/instr-cov/explicit_mains/mylib/pkg.adb b/testsuite/tests/instr-cov/explicit_mains/mylib/pkg.adb new file mode 100644 index 000000000..8bb9c95f0 --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains/mylib/pkg.adb @@ -0,0 +1,16 @@ +package body Pkg is + + ---------- + -- Fact -- + ---------- + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/explicit_mains/mylib/pkg.ads b/testsuite/tests/instr-cov/explicit_mains/mylib/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains/mylib/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/explicit_mains/test.py b/testsuite/tests/instr-cov/explicit_mains/test.py new file mode 100644 index 000000000..7b090ad57 --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains/test.py @@ -0,0 +1,186 @@ +""" +Check that passing an explicit list of mains to "gnatcov instrument"'s command +line works as expected. +""" + +import glob +import re + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, srctracename_for +from SUITE.gprutils import GPRswitches + + +def create_gprsw(mains, with_asm=False): + """ + Generate the test project in the current directory (must be the temporary + directory) and return the corresponding GPRswitches instance. + + :param mains: List of source files for the mains. + :param with_asm: Whether to include "Asm" in the list of languages. + """ + # First create a GPR file for the library to test. Make it standalone and + # auto initialized so that buffer units gets linked even if a main contains + # no buffer dumps and thus does not pull it into the link. + gprfor( + mains=[], + prjid="mylib", + srcdirs="../mylib", + objdir="obj-mylib", + langs=["Ada"], + extra=""" + for Library_Name use "mylib"; + for Library_Dir use "lib"; + for Library_Interface use ("pkg"); + for Library_Standalone use "standard"; + """, + ) + + # Then create the GPR file for the mains + langs = ["Ada"] + if with_asm: + langs.append("Asm") + mains_gpr = gprfor( + mains=mains, prjid="mains", srcdirs="..", langs=langs, deps=["mylib"], + ) + + # Create object/library directories to avoid GPR warnings that they are + # missing. + mkdir("obj-mylib") + mkdir("lib") + mkdir("obj") + + return GPRswitches(root_project=mains_gpr, projects=["mylib"]) + + +# First, test error cases + +wd = Wdir("tmp_errors") + +gprsw = create_gprsw(mains=[], with_asm=True) + + +def check_error(label, mains, expected_error_msg): + """ + Run a test variant to check an error case. + + :param label: Name for this test variant. + :param mains: List of mains to pass on the command line of + "gnatcov instrument". + :param expected_error_msg: Expected error message from + "gnatcov instrument". + """ + thistest.log(f"== {label} ==") + log_file = f"output-{label}.txt" + p = xcov_instrument( + gprsw=gprsw, + covlevel="stmt", + extra_args=mains, + out=log_file, + register_failure=False, + ) + thistest.fail_if_not_equal("gnatcov instrument status code", 1, p.status) + thistest.fail_if_no_match( + "gnatcov instrument output", + f".*gnatcov.*: {re.escape(expected_error_msg)}", + contents_of(log_file).strip(), + ) + + +check_error( + "nosuchfile", ["nosuchfile.adb"], "No such source file: nosuchfile.adb" +) +check_error( + "badlang", + ["foo.s"], + "Cannot instrument main source file (unsupported language): foo.s", +) + +wd.to_homedir() + + +# Now, check that expected mains are instrumented for each cases: no explicit +# main on the command line, one or several explicit mains. Go through the whole +# instrument/build/run cycle and check the absence or presence of a trace file +# in each case. + + +def check_gen_traces(label, + gpr_mains, + xcov_mains, + program_for_expected_traces): + """ + Run a test variant to check mains with coverage buffer dumps. + + :param label: Name for this test variant. + :param gpr_mains: List of source files to consider as mains in the project + file. + :param xcov_mains: List of source files to pass as mains to + "gnatcov instrument". + :param program_for_expected_traces: List of program names for which we + expect a source trace to be produced. + """ + thistest.log(f"== {label} ==") + wd = Wdir(f"tmp_{label}") + + build_and_run( + gprsw=create_gprsw(gpr_mains), + covlevel="stmt", + + # Build and run all actual mains in all cases (we want to check the + # instrumentation status for all of them). + extra_gprbuild_args=["main1.adb", "main2.adb"], + mains=["main1", "main2"], + + extra_instr_args=xcov_mains, + extra_coverage_args=[], + trace_mode="src", + + # Since instrumentation may insert coverage buffer dumps only for a + # subset of mains, calls to "gnatcov extract-base64-trace" will fail + # for mains that do not dump. This is as expected, so ignore these + # errors. + register_failure=False, + ) + + # Check that we get exactly the traces that we were expecting + expected_traces = sorted( + srctracename_for(program) for program in program_for_expected_traces + ) + actual_traces = sorted(glob.glob("*.srctrace")) + thistest.fail_if_not_equal( + "Source trace files", expected_traces, actual_traces + ) + + wd.to_homedir() + + +# No mains defined in GPR nor on the gnatcov cmdline: no main creates a trace +# file. +check_gen_traces("gpr0-xcov0", [], [], []) + +# Only the GPR file declares a main: only that main creates a trace file +check_gen_traces("gpr1-xcov0", ["main1.adb"], [], ["main1"]) + +# The GPR file declares one main, but the gnatcov cmdline declares another +# main: the latter takes precedence. +check_gen_traces("gpr1-xcov2", ["main1.adb"], ["main2.adb"], ["main2"]) + +# Likewise, but the gnatcov cmdline declares two mains +check_gen_traces( + "gpr1-xcov12", + ["main1.adb"], + ["main1.adb", "main2.adb"], + ["main1", "main2"], +) + +# The GPR file declares no main, but the gnatcov cmdline declares one: the +# latter creates a trace file. +check_gen_traces("gpr0-xcov1", [], ["main1.adb"], ["main1"]) + +thistest.result() diff --git a/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/bar.adb b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/bar.adb new file mode 100644 index 000000000..df1e48b3f --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/bar.adb @@ -0,0 +1,11 @@ +with Foo; + +procedure Bar is + X : Natural := 0; + pragma volatile (X); +begin + if X > 0 then + Foo; + end if; + X := 1; +end Bar; diff --git a/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/foo.adb b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/foo.adb new file mode 100644 index 000000000..275310a20 --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/foo.adb @@ -0,0 +1,6 @@ +procedure Foo is + X : Natural := 0; + pragma volatile (X); +begin + X := 1; +end Foo; diff --git a/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/test.py b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/test.py new file mode 100644 index 000000000..1079bf726 --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/test.py @@ -0,0 +1,47 @@ +""" +Check that when mains are provided in the GPR file and in "gnatcov +instrument"'s command line only those in the command line are instrumented as +mains. +""" + +import glob + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, srctracename_for +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +gpr_file = gprfor(mains=["foo.adb", "bar.adb"], srcdirs=[".."]) + +gprsw = GPRswitches(gpr_file) + +build_and_run( + gprsw=gprsw, + covlevel="stmt", + extra_coverage_args=[], + trace_mode="src", + + # Only instrument foo.adb as a main + extra_instr_args=["foo.adb"], + + # Build and execute foo.adb and bar.adb + extra_gprbuild_args=["foo.adb", "bar.adb"], + mains=["foo", "bar"], + + # We expect there not to be a trace file for bar, so don't register not + # finding it as an error. + register_failure=False +) + +# Check that we only get traces for foo +expected_traces = [srctracename_for("foo")] +actual_traces = sorted(glob.glob("*.srctrace")) + +thistest.fail_if_not_equal( + "Source trace files", expected_traces, actual_traces +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/explicit_mains_uoi/main.adb b/testsuite/tests/instr-cov/explicit_mains_uoi/main.adb new file mode 100644 index 000000000..8e387a0ab --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains_uoi/main.adb @@ -0,0 +1,6 @@ +procedure Main is + X : Natural := 0; + pragma volatile (X); +begin + X := 1; +end Main; diff --git a/testsuite/tests/instr-cov/explicit_mains_uoi/test.py b/testsuite/tests/instr-cov/explicit_mains_uoi/test.py new file mode 100644 index 000000000..420202d48 --- /dev/null +++ b/testsuite/tests/instr-cov/explicit_mains_uoi/test.py @@ -0,0 +1,25 @@ +""" +Check that passing an explicit main that is already a unit of interest to +"gnatcov instrument"'s command line works as expected. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +gpr_file = gprfor(mains=[], srcdirs=[".."]) + +gprsw = GPRswitches(gpr_file) + +build_run_and_coverage(gprsw=gprsw, covlevel="stmt", mains=["main"], + extra_coverage_args=["-axcov"], + extra_instr_args=["main.adb"], + extra_gprbuild_args=["main.adb"]) + +check_xcov_reports("obj/*.xcov", {"obj/main.adb.xcov": {"+": {2, 5}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aggr/main.adb b/testsuite/tests/instr-cov/expr_func/aggr/main.adb new file mode 100644 index 000000000..f29953d2d --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aggr/main.adb @@ -0,0 +1,27 @@ +pragma Ada_2012; + +procedure Main is + type Enum_Type is (A, B, C, D); + type Flags_Type is array (Enum_Type) of Boolean; + + type Options_Type is record + A, B, C : Boolean; + end record; + + function Get_Flags (B : Boolean) return Flags_Type is + (others => B); + function Get_Some_Flags (B : Boolean) return Flags_type is + (A => True, Others => B); + + function Get_Options (B : Boolean) return Options_Type is + (others => B); + function Get_Some_Options (B : Boolean) return Options_type is + (A => True, Others => B); + + F1 : Flags_Type := Get_Flags (True); + F2 : Flags_Type := Get_Some_Flags (True); + O1 : Options_Type := Get_Options (True); + O2 : Options_Type := Get_Some_Options (True); +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/expr_func/aggr/p.gpr b/testsuite/tests/instr-cov/expr_func/aggr/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aggr/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/expr_func/aggr/test.py b/testsuite/tests/instr-cov/expr_func/aggr/test.py new file mode 100644 index 000000000..ad248ece2 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aggr/test.py @@ -0,0 +1,32 @@ +""" +Check that we properly instrument expression functions whose expression is only +an aggregate. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') +check_xcov_reports('xcov/*.xcov', {'xcov/main.adb.xcov': { + '+': {4, 5, 7, 12, 14, 17, 19, 21, 22, 23, 24} +}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/src/foo.ads new file mode 100644 index 000000000..6ad8edce9 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/src/foo.ads @@ -0,0 +1,10 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return integer is + (if N > 1 then N * (N -1) else N) -- # expr_func + with Pre => N > 0, + Post => Fact'Result >= N; + +end Foo; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/test.py new file mode 100644 index 000000000..e4cb071b3 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument non-recursive expression functions, +with aspects and no previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/src/foo.ads new file mode 100644 index 000000000..ee19a0d15 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/src/foo.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return Integer + with Pre => N > 0, + Post => Fact'Result >= N; + + function Fact (N : Integer) return integer is + (if N > 1 then N * (N -1) else N); -- # expr_func + +end Foo; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/test.py new file mode 100644 index 000000000..ff98ed535 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument non-recursive expression functions +with aspects and that have a previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/src/foo.ads new file mode 100644 index 000000000..c9f670ca4 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/src/foo.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return integer is + (if N > 1 then N * (N -1) else N); -- # expr_func + +end Foo; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/test.py new file mode 100644 index 000000000..5580d63cc --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument non recursive expression functions +without aspects and no previsou declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/src/foo.ads new file mode 100644 index 000000000..91573ff28 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/src/foo.ads @@ -0,0 +1,10 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return Integer; + + function Fact (N : Integer) return integer is + (if N > 1 then N * (N -1) else N); -- # expr_func + +end Foo; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/test.py new file mode 100644 index 000000000..cf7f1610c --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument non-recursive expression functions +without aspects, but with a previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/readme.txt b/testsuite/tests/instr-cov/expr_func/aspects/readme.txt new file mode 100644 index 000000000..d367b8027 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/readme.txt @@ -0,0 +1,10 @@ +Tests in this dir test the instrumentation of various kinds of expression functions +depending on if: +1- they have a previous spec or not +2- they have aspects or not +3- they are self-referencing (or recursive) or not. + +This lead to 8 tests. For each dir, if the expression function under test +is recursive the folder name contains "rec", if it does not it contains "no-rec"; +if it has aspects, it contain "asp", if it does not it contains "no-asp"; +if it has a previous spec it contains "prespec", if it does not, it contains "no-prespec". diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/src/foo.ads new file mode 100644 index 000000000..3c0268477 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/src/foo.ads @@ -0,0 +1,10 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return integer is + (if N > 1 then N * Fact (N -1) else N) -- # expr_func + with Pre => N > 0, + Post => Fact'Result >= N; + +end Foo; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.opt b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.opt new file mode 100644 index 000000000..8212a024b --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.opt @@ -0,0 +1 @@ +bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.py new file mode 100644 index 000000000..70ede0c54 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument recursive expression functions +with aspects but with no previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/src/foo.ads new file mode 100644 index 000000000..d5246ca11 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/src/foo.ads @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return Integer + with Pre => N > 0, + Post => Fact'Result >= N; + + function Fact (N : Integer) return integer is + (if N > 1 then N * Fact (N -1) else N); -- # expr_func + +end Foo; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.opt b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.opt new file mode 100644 index 000000000..8212a024b --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.opt @@ -0,0 +1 @@ +bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.py new file mode 100644 index 000000000..4ec0303ee --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument recursive expression functions with aspects +and a previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/src/foo.ads new file mode 100644 index 000000000..8426ad93f --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/src/foo.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return integer is + (if N > 1 then N * Fact (N -1) else N); -- # expr_func + +end Foo; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.opt b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.opt new file mode 100644 index 000000000..8212a024b --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.opt @@ -0,0 +1 @@ +bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.py new file mode 100644 index 000000000..0bdfb8eed --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument recursive expression functions +without aspects and without a previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/src/foo.ads new file mode 100644 index 000000000..4af6d0793 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/src/foo.ads @@ -0,0 +1,10 @@ +pragma Ada_2012; + +package Foo is + + function Fact (N : Integer) return Integer; + + function Fact (N : Integer) return integer is + (if N > 1 then N * Fact (N -1) else N); -- # expr_func + +end Foo; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.opt b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.opt new file mode 100644 index 000000000..8212a024b --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.opt @@ -0,0 +1 @@ +bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.py b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.py new file mode 100644 index 000000000..ba6df99a2 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument recursive expression functions +without aspects but with a previous declaration. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aspects/src/test_foo.adb b/testsuite/tests/instr-cov/expr_func/aspects/src/test_foo.adb new file mode 100644 index 000000000..5d7addcd1 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/aspects/src/test_foo.adb @@ -0,0 +1,21 @@ +pragma Ada_2012; + +with Foo; + +procedure Test_Foo is + + procedure Null_Proc (Param : Integer) is null -- # null_proc + with Inline; + +begin + + Null_Proc (Foo.Fact (0)); + +end Test_Foo; + +--# foo.ads +-- +--%opts: --trace-mode=src +-- /expr_func/ l! ## dT- +--%opts: --trace-mode=bin +-- /expr_func/ l! ## d! \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/basic/main.adb b/testsuite/tests/instr-cov/expr_func/basic/main.adb new file mode 100644 index 000000000..e864bba2e --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/basic/main.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + function Fact (I : Integer) return Integer is + (if I < 2 + then 1 + else I * Fact (I - 1)); + + X, Y : Boolean; + function X_And_Then_Y return Boolean is (X and then Y); + +begin + Put_Line ("Fact (6) = " & Integer'Image (Fact (6))); +end Main; diff --git a/testsuite/tests/instr-cov/expr_func/basic/p.gpr b/testsuite/tests/instr-cov/expr_func/basic/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/basic/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/expr_func/basic/test.py b/testsuite/tests/instr-cov/expr_func/basic/test.py new file mode 100644 index 000000000..d80777a6c --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/basic/test.py @@ -0,0 +1,32 @@ +""" +Test that instrumented source coverage works as expected on expression +functions. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'+': {7, 9, 11, 15}, '-': {12}} +}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/extra.opt b/testsuite/tests/instr-cov/expr_func/extra.opt new file mode 100644 index 000000000..0ae5a81d5 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/extra.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Requires Ada 2012, unavailable in 5.04a1 +7.1.2 DEAD support for expression functions weak in 7.1.2 \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/generic/src/pkg.ads b/testsuite/tests/instr-cov/expr_func/generic/src/pkg.ads new file mode 100644 index 000000000..27fe4ba68 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic/src/pkg.ads @@ -0,0 +1,21 @@ +pragma Ada_2012; + +package Pkg is + + generic + type Value_Type is private; + with function Weight (Self : Value_Type) return Natural; + function Weight_Sum (Left, Right : Value_Type) return Natural; + + generic + type Value_Type is private; + with function Weight (Self : Value_Type) return Natural; + function Both_Weights_Null (Left, Right : Value_Type) return Boolean; + + function Weight_Sum (Left, Right : Value_Type) return Natural is + (Weight (Left) + Weight (Right)); + + function Both_Weights_Null (Left, Right : Value_Type) return Boolean is + (Weight (Left) = 0 and then Weight (Right) = 0); + +end Pkg; diff --git a/testsuite/tests/instr-cov/expr_func/generic/src/test_main.adb b/testsuite/tests/instr-cov/expr_func/generic/src/test_main.adb new file mode 100644 index 000000000..62372d526 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic/src/test_main.adb @@ -0,0 +1,26 @@ +pragma Ada_2012; + +with Pkg; + +procedure Test_Main is + + type Rec_Type is record + Value : Natural; + end record; + + function Weight (Self : Rec_Type) return Natural is (Self.Value); + + function Weight_Sum is new Pkg.Weight_Sum (Rec_Type, Weight); + function Both_Weights_Null is new Pkg.Both_Weights_Null (Rec_Type, Weight); + + A : constant Rec_Type := (Value => 1); + B : constant Rec_Type := (Value => 2); + +begin + if Weight_Sum (A, B) /= 3 then + raise Program_Error; + end if; + if Both_Weights_Null (A, B) then + raise Program_Error; + end if; +end Test_Main; diff --git a/testsuite/tests/instr-cov/expr_func/generic/test.py b/testsuite/tests/instr-cov/expr_func/generic/test.py new file mode 100644 index 000000000..41cbea501 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic/test.py @@ -0,0 +1,48 @@ +""" +Check that the instrumentation of generic expression functions produces valid +code. It used to create non-generic expression functions that could reference +generic formals. + +For now we do not know how to instrument generic expression functions, so we +emit a warning for them at instrumentation time and always consider them +non-instrumented. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["test_main.adb"]), + units=["pkg"], + ), + covlevel="stmt+mcdc", + mains=["test_main"], + extra_coverage_args=["-axcov", "--output-dir=."], + trace_mode="src", + tolerate_instrument_messages=\ + "cannot instrument generic expression function", +) + +# We only expect non-instrumented lines +check_xcov_reports("*.xcov", {"pkg.ads.xcov": {"?": {16, 19}}}) + +# Check that both expression functions are reported as warnings +warning_msg = ( + "gnatcov limitation: cannot instrument generic expression functions." + " Consider turning it into a regular function body." +) +thistest.fail_if_not_equal( + "'gnatcov instrument' log", + f"!!! pkg.ads:15:4: {warning_msg}\n" + f"!!! pkg.ads:18:4: {warning_msg}\n", + contents_of("instrument.log"), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/generic_prim/src/inst.ads b/testsuite/tests/instr-cov/expr_func/generic_prim/src/inst.ads new file mode 100644 index 000000000..bd66baaa6 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic_prim/src/inst.ads @@ -0,0 +1,3 @@ +with Pkg; + +package Inst is new Pkg (T => Boolean, Init => True); \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/generic_prim/src/pkg.ads b/testsuite/tests/instr-cov/expr_func/generic_prim/src/pkg.ads new file mode 100644 index 000000000..aeaf8cca4 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic_prim/src/pkg.ads @@ -0,0 +1,16 @@ +pragma Ada_2012; + +generic + type T (<>) is private; + Init : Boolean; +package Pkg is + + type Tagged_Typ is tagged record + Bool : Boolean; + end record; + + function Foo (Self : Tagged_Typ) return Boolean is (Self.Bool); -- # expr + + Obj : constant Tagged_Typ := (Bool => Init); + +end Pkg; diff --git a/testsuite/tests/instr-cov/expr_func/generic_prim/src/test_pkg.adb b/testsuite/tests/instr-cov/expr_func/generic_prim/src/test_pkg.adb new file mode 100644 index 000000000..82eca6a86 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic_prim/src/test_pkg.adb @@ -0,0 +1,18 @@ +pragma Ada_2012; + +with Inst; + +procedure Test_Pkg is + + Res : Boolean with Volatile; + +begin + Res := Inst.Obj.Foo; +end Test_Pkg; + +-- The coverage expectations do not matter much, the point of this test is to +-- check that the instrumented code is accepted by gnat. + +--# pkg.ads +-- +-- /expr/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/expr_func/generic_prim/test.py b/testsuite/tests/instr-cov/expr_func/generic_prim/test.py new file mode 100644 index 000000000..bb840a4be --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/generic_prim/test.py @@ -0,0 +1,12 @@ +""" +Check that we properly instrument expression functions that are primitives, +declared in a generic package without triggering any freezing bug. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/ghost/src/pkg.adb b/testsuite/tests/instr-cov/expr_func/ghost/src/pkg.adb new file mode 100644 index 000000000..5f73c963f --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ghost/src/pkg.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; + +package body Pkg is + + -------------- + -- Say_Even -- + -------------- + + procedure Say_Even is + begin + Ada.Text_IO.Put_Line ("Counter is even"); -- # say-even + end Say_Even; + +end Pkg; diff --git a/testsuite/tests/instr-cov/expr_func/ghost/src/pkg.ads b/testsuite/tests/instr-cov/expr_func/ghost/src/pkg.ads new file mode 100644 index 000000000..de1bfe63a --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ghost/src/pkg.ads @@ -0,0 +1,17 @@ +pragma Ada_2012; + +package Pkg is + + Counter : Natural := 0 with Ghost; + + function Is_Even return Boolean + is (Counter > 0 and then Counter mod 2 = 0) -- # is-even + with Ghost; + + Dummy : Integer; + -- Dummy variable just so that "pkg.ads" appears in the debug info and so + -- that "gnatcov coverage" finds it in binary traces mode. + + procedure Say_Even with Pre => Is_Even; + +end Pkg; diff --git a/testsuite/tests/instr-cov/expr_func/ghost/src/test_main.adb b/testsuite/tests/instr-cov/expr_func/ghost/src/test_main.adb new file mode 100644 index 000000000..fe5074008 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ghost/src/test_main.adb @@ -0,0 +1,14 @@ +pragma Ada_2012; + +with Pkg; + +procedure Test_Main is +begin + Pkg.Say_Even; +end Test_Main; + +--# pkg.adb +-- /say-even/ l+ ## 0 +-- +--# pkg.ads +-- /is-even/ l. ## 0 diff --git a/testsuite/tests/instr-cov/expr_func/ghost/test.py b/testsuite/tests/instr-cov/expr_func/ghost/test.py new file mode 100644 index 000000000..5472c5ec4 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ghost/test.py @@ -0,0 +1,13 @@ +""" +Check that the instrumentation of ghost expression functions produces valid +code. It used to create non-ghost expression functions that could reference +ghost entities. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/overriding/src/pak.ads b/testsuite/tests/instr-cov/expr_func/overriding/src/pak.ads new file mode 100644 index 000000000..ffbb2c3e7 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/overriding/src/pak.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package Pak is + + type T is record + X : Integer; + end record; + function Make (Cond : Boolean) return T is (T'(X => 1)); + + type TT is new T; + overriding function Make (Cond : Boolean) return TT is + (TT'(X => (if Cond then 2 else 3))); -- # dc + +end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/overriding/src/test_foo.adb b/testsuite/tests/instr-cov/expr_func/overriding/src/test_foo.adb new file mode 100644 index 000000000..3bd172523 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/overriding/src/test_foo.adb @@ -0,0 +1,17 @@ +pragma Ada_2012; + +with Pak; use Pak; + +procedure Test_Foo is + Dummy_1 : constant T := Make (False); + Dummy_2 : constant TT := Make (True); +begin + null; +end Test_Foo; + +--# pak.ads +-- +--%opts: --trace-mode=src +-- /dc/ l! ## dF- +--%opts: --trace-mode=bin +-- /dc/ l! ## d! diff --git a/testsuite/tests/instr-cov/expr_func/overriding/test.py b/testsuite/tests/instr-cov/expr_func/overriding/test.py new file mode 100644 index 000000000..e6092f08a --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/overriding/test.py @@ -0,0 +1,11 @@ +""" +Check that we properly instrument overriding expression functions for MC/DC. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/parameterless/main.adb b/testsuite/tests/instr-cov/expr_func/parameterless/main.adb new file mode 100644 index 000000000..30c74ef1f --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/parameterless/main.adb @@ -0,0 +1,5 @@ +with Pak; +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/expr_func/parameterless/p.gpr b/testsuite/tests/instr-cov/expr_func/parameterless/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/parameterless/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/expr_func/parameterless/pak.ads b/testsuite/tests/instr-cov/expr_func/parameterless/pak.ads new file mode 100644 index 000000000..6d45ec710 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/parameterless/pak.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pak is + A, B : Boolean; + function And_Then return Boolean is (A and then B); +end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/parameterless/test.py b/testsuite/tests/instr-cov/expr_func/parameterless/test.py new file mode 100644 index 000000000..a33c5a846 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/parameterless/test.py @@ -0,0 +1,33 @@ +""" +Check that we properly instrument expression functions with no parameters +for MC/DC. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt+uc_mcdc', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') +check_xcov_reports('xcov/*.xcov', + {'xcov/main.adb.xcov': {'+': {4}}, + 'xcov/pak.ads.xcov': {'+': {4}, '-': {5}}}) + + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/prev_decl/src/bar.ads b/testsuite/tests/instr-cov/expr_func/prev_decl/src/bar.ads new file mode 100644 index 000000000..e47b0cdf9 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prev_decl/src/bar.ads @@ -0,0 +1,5 @@ +pragma Ada_2012; + +package Bar is + type T_Bar is new Boolean; +end Bar; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/prev_decl/src/foo.ads b/testsuite/tests/instr-cov/expr_func/prev_decl/src/foo.ads new file mode 100644 index 000000000..028449938 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prev_decl/src/foo.ads @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Bar; + +package Foo is + + type T is tagged null record; + + function Prim (Self : T) return Bar.T_Bar; -- # decl + +private + use Bar; + + function Prim (Self : T) return T_Bar is + (False); -- # EF +end Foo; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/prev_decl/src/test_decl.adb b/testsuite/tests/instr-cov/expr_func/prev_decl/src/test_decl.adb new file mode 100644 index 000000000..fb7e29d0e --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prev_decl/src/test_decl.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +with Foo; +with Bar; +procedure Test_Decl is + Obj : Foo.T; + Res : Bar.T_Bar; + pragma Volatile (Res); +begin + Res := Obj.Prim; +end Test_Decl; + +--# foo.ads +-- +-- /decl/ l. ## 0 +-- /EF/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/expr_func/prev_decl/test.py b/testsuite/tests/instr-cov/expr_func/prev_decl/test.py new file mode 100644 index 000000000..e91b3c754 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prev_decl/test.py @@ -0,0 +1,13 @@ +""" +Check that the previous declaration inserted for an augmented expression +function is valid. This test is not so much about what the coverage results +we ge but rather about having the instrumenter emit valid code. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/prim/main.adb b/testsuite/tests/instr-cov/expr_func/prim/main.adb new file mode 100644 index 000000000..b67975340 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim/main.adb @@ -0,0 +1,7 @@ +pragma Ada_2012; +with Pak; + +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/expr_func/prim/p.gpr b/testsuite/tests/instr-cov/expr_func/prim/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/expr_func/prim/pak.ads b/testsuite/tests/instr-cov/expr_func/prim/pak.ads new file mode 100644 index 000000000..2418a0f0b --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim/pak.ads @@ -0,0 +1,18 @@ +pragma Ada_2012; + +package Pak is + type T is tagged record + X : Integer; + end record; + function And_Then (X : T; A, B : Boolean) return Boolean is + (A and then B); + function Or_Else (X : T; A, B : Boolean) return Boolean is + (A or else B); + function Make (Cond : Boolean) return T is (T'(X => (if Cond then 1 else 2))); + + type TT is new T with record + Y : Integer; + end record; + overriding function Make (Cond : Boolean) return TT is (TT'(X => 3, Y => 4)); + +end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/prim/test.opt b/testsuite/tests/instr-cov/expr_func/prim/test.opt new file mode 100644 index 000000000..08dc59c5a --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim/test.opt @@ -0,0 +1 @@ +ALL XFAIL triggers compiler bug T114-003 diff --git a/testsuite/tests/instr-cov/expr_func/prim/test.py b/testsuite/tests/instr-cov/expr_func/prim/test.py new file mode 100644 index 000000000..bbb766a11 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim/test.py @@ -0,0 +1,36 @@ +""" +Check that we properly instrument expression functions that are primitives +of tagged types for MC/DC. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt+uc_mcdc', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') + +# TODO: update coverage expectations once compiler bug +# has been fixed and XFAIL is removed. + +check_xcov_reports('xcov/*.xcov', {'xcov/main.adb.xcov': { + '+': {4, 5, 7, 12, 14, 17, 19, 21, 22, 23, 24} +}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/prim2/main.adb b/testsuite/tests/instr-cov/expr_func/prim2/main.adb new file mode 100644 index 000000000..f725e2c80 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim2/main.adb @@ -0,0 +1,9 @@ +pragma Ada_2012; +with Pak; use Pak; + +procedure Main is + Obj : T := Make (True); + Obj2 : TT := Make (False); +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/expr_func/prim2/p.gpr b/testsuite/tests/instr-cov/expr_func/prim2/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim2/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/expr_func/prim2/pak.adb b/testsuite/tests/instr-cov/expr_func/prim2/pak.adb new file mode 100644 index 000000000..fab1782a6 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim2/pak.adb @@ -0,0 +1,10 @@ +pragma Ada_2012; + +package body Pak is + + function Make_Internal (Cond : Boolean) return T is + (T'(X => (if Cond then 1 else 2))); + + function Make_Internal (Cond : Boolean) return TT is (TT'(X => 3, Y => 4)); + +end Pak; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/expr_func/prim2/pak.ads b/testsuite/tests/instr-cov/expr_func/prim2/pak.ads new file mode 100644 index 000000000..e243859c2 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim2/pak.ads @@ -0,0 +1,25 @@ +pragma Ada_2012; + +package Pak is + type T is tagged record + X : Integer; + end record; + function And_Then (X : T; A, B : Boolean) return Boolean is + (A and then B); + function Or_Else (X : T; A, B : Boolean) return Boolean is + (A or else B); + + function Make_Internal (Cond : Boolean) return T; + + function Make (Cond : Boolean) return T is (Make_Internal (Cond)); + + type TT is new T with record + Y : Integer; + end record; + + overriding function Make_Internal (Cond : Boolean) return TT; + + overriding function Make (Cond : Boolean) return TT is + (Make_Internal (Cond)); + +end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/prim2/test.opt b/testsuite/tests/instr-cov/expr_func/prim2/test.opt new file mode 100644 index 000000000..41403b657 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim2/test.opt @@ -0,0 +1 @@ +ALL XFAIL expr func in test no longer instrumented (U625-016) diff --git a/testsuite/tests/instr-cov/expr_func/prim2/test.py b/testsuite/tests/instr-cov/expr_func/prim2/test.py new file mode 100644 index 000000000..a5c6a0f57 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/prim2/test.py @@ -0,0 +1,39 @@ +""" +Check that we properly instrument expression functions that are primitives +of tagged types for MC/DC. The test focuses mainly on primitives where the +tagged type is the return type of the expression function. This variant of +the test does not trigger the compiler bug in T114-003 +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt+uc_mcdc', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') + +# Coverage expectations aren't really important, we want to check that +# the instrumented code is valid. + +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'+': {6}}, + 'xcov/pak.ads.xcov' : {'+': {4, 5, 6, 14, 16, 17, 18, 23}, '-': {8, 10}}, + 'xcov/pak.adb.xcov' : {'!': {6}, '+': {8}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/program_error/src/test_main.adb b/testsuite/tests/instr-cov/expr_func/program_error/src/test_main.adb new file mode 100644 index 000000000..383233aab --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/program_error/src/test_main.adb @@ -0,0 +1,31 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Containers.Ordered_Sets; + + +procedure Test_Main is + package File_Sets is new Ada.Containers.Ordered_Sets + (Element_Type => Unbounded_String); + + type R is record + Source_Files : File_Sets.Set; + end record; + + function It + (Self : R) + return File_Sets.Set_Iterator_Interfaces.Reversible_Iterator'Class + is (Self.Source_Files.Iterate); -- # stmt + + Files : R; +begin + Files.Source_Files.Include (To_Unbounded_String ("A")); -- # stmt + for File in It (Files) loop -- # stmt + Put_Line (To_String (File_Sets.Element (File))); -- # stmt + end loop; +end Test_Main; + +--# test_main.adb +-- +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/expr_func/program_error/test.opt b/testsuite/tests/instr-cov/expr_func/program_error/test.opt new file mode 100644 index 000000000..a1aa0f330 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/program_error/test.opt @@ -0,0 +1 @@ +!native DEAD Testcase requires standard Ada containers diff --git a/testsuite/tests/instr-cov/expr_func/program_error/test.py b/testsuite/tests/instr-cov/expr_func/program_error/test.py new file mode 100644 index 000000000..8d30e03bf --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/program_error/test.py @@ -0,0 +1,13 @@ +""" +Check that the instrumentation of expression functions does not trigger a GNAT +miscompilation bug. The instrumented test program used to crash with a +Program_Error/Storage_Error. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/quantifier/src/test_main.adb b/testsuite/tests/instr-cov/expr_func/quantifier/src/test_main.adb new file mode 100644 index 000000000..e71551a9b --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/quantifier/src/test_main.adb @@ -0,0 +1,22 @@ +pragma Ada_2012; + +procedure Test_Main is + + type Int_Array is array (Positive range <>) of Integer; + + function All_Multiple_Of_2_And_3 (IA : Int_Array) return Boolean is + (for all I in IA'Range => -- # func-stmt + IA (I) mod 2 = 0 and then IA (I) mod 3 = 0); -- # func-dc + +begin + if All_Multiple_Of_2_And_3 ((2, 4, 12)) then -- # call-dc + raise Program_Error; -- # call-error + end if; +end Test_Main; + +--# test_main.adb +-- +-- /func-stmt/ l+ ## 0 +-- /func-dc/ l! ## dT- +-- /call-dc/ l! ## dT- +-- /call-error/ l- ## s- diff --git a/testsuite/tests/instr-cov/expr_func/quantifier/test.py b/testsuite/tests/instr-cov/expr_func/quantifier/test.py new file mode 100644 index 000000000..bbc385463 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/quantifier/test.py @@ -0,0 +1,12 @@ +""" +Check that the instrumentation in MC/DC mode of an expression function that +contains defining identifiers does not crash (it used to). +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/dummy.txt b/testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/dummy.txt new file mode 100644 index 000000000..972323daa --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/dummy.txt @@ -0,0 +1 @@ +dummy source file, supposed to be deleted during instrumentation diff --git a/testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/pkg.ads b/testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/pkg.ads new file mode 100644 index 000000000..972323daa --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/obj-p/p-gnatcov-instr/pkg.ads @@ -0,0 +1 @@ +dummy source file, supposed to be deleted during instrumentation diff --git a/testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext1/p_ext1-gnatcov-instr/pkg.ads b/testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext1/p_ext1-gnatcov-instr/pkg.ads new file mode 100644 index 000000000..972323daa --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext1/p_ext1-gnatcov-instr/pkg.ads @@ -0,0 +1 @@ +dummy source file, supposed to be deleted during instrumentation diff --git a/testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext2/p_ext2-gnatcov-instr/pkg.ads b/testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext2/p_ext2-gnatcov-instr/pkg.ads new file mode 100644 index 000000000..972323daa --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/obj-p_ext2/p_ext2-gnatcov-instr/pkg.ads @@ -0,0 +1 @@ +dummy source file, supposed to be deleted during instrumentation diff --git a/testsuite/tests/instr-cov/ext_gpr/src/p.gpr b/testsuite/tests/instr-cov/ext_gpr/src/p.gpr new file mode 100644 index 000000000..d4e3ff4d4 --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/p.gpr @@ -0,0 +1,4 @@ +project P is + for Source_Dirs use ("src-p"); + for Object_Dir use "obj-p"; +end P; diff --git a/testsuite/tests/instr-cov/ext_gpr/src/p_ext1.gpr b/testsuite/tests/instr-cov/ext_gpr/src/p_ext1.gpr new file mode 100644 index 000000000..e60e3f710 --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/p_ext1.gpr @@ -0,0 +1,4 @@ +project P_Ext1 extends "p" is + for Source_Dirs use ("src-p_ext1"); + for Object_Dir use "obj-p_ext1"; +end P_Ext1; diff --git a/testsuite/tests/instr-cov/ext_gpr/src/p_ext2.gpr b/testsuite/tests/instr-cov/ext_gpr/src/p_ext2.gpr new file mode 100644 index 000000000..19dd8d70a --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/p_ext2.gpr @@ -0,0 +1,4 @@ +project P_Ext2 extends "p_ext1" is + for Source_Dirs use ("src-p_ext2"); + for Object_Dir use "obj-p_ext2"; +end P_Ext2; diff --git a/testsuite/tests/instr-cov/ext_gpr/src/src-p/pkg.ads b/testsuite/tests/instr-cov/ext_gpr/src/src-p/pkg.ads new file mode 100644 index 000000000..f78912afe --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/src-p/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + I : Integer; +end Pkg; diff --git a/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext1/pkg1.ads b/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext1/pkg1.ads new file mode 100644 index 000000000..7b7b3258b --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext1/pkg1.ads @@ -0,0 +1,3 @@ +package Pkg_1 is + I : Integer; +end Pkg_1; diff --git a/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext2/pkg2.ads b/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext2/pkg2.ads new file mode 100644 index 000000000..36281d26b --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext2/pkg2.ads @@ -0,0 +1,3 @@ +package Pkg_2 is + I : Integer; +end Pkg_2; diff --git a/testsuite/tests/instr-cov/ext_gpr/test.py b/testsuite/tests/instr-cov/ext_gpr/test.py new file mode 100644 index 000000000..1238e3215 --- /dev/null +++ b/testsuite/tests/instr-cov/ext_gpr/test.py @@ -0,0 +1,45 @@ +""" +Check that "gnatcov instrument" correctly deals with directories for +instrumented sources in project extension configurations. +""" + +import glob + +from e3.fs import sync_tree + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Create a copy of the testcase material (project sources and dummy object +# directories) and run the instrumenter on the ultimate extending project. +sync_tree("../src", ".") +xcov_instrument(gprsw=GPRswitches(root_project="p_ext2.gpr"), covlevel="stmt") + +# Check that directories for instrumented sources are all empty except for the +# ultimate extending project, which should contain all instrumented sources. +thistest.fail_if_not_equal( + "instrumented directories", + "\n".join([ + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-bs_pkg.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-bs_pkg1.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-bs_pkg2.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-lists-p_ext2.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-ps_pkg.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-ps_pkg1.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-ps_pkg2.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/pkg.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/pkg1.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/pkg2.ads", + ]), + "\n".join( + f.replace("\\", "/") + for f in sorted(glob.glob("obj-*/*-gnatcov-instr/*")) + ), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/ghost_generic/gen.adb b/testsuite/tests/instr-cov/ghost_generic/gen.adb new file mode 100644 index 000000000..046d47ac4 --- /dev/null +++ b/testsuite/tests/instr-cov/ghost_generic/gen.adb @@ -0,0 +1,11 @@ +package body Gen is + function Eq (X : T) return Boolean is + begin + return X = Val; + end Eq; + + function Non_Eq (X : T) return Boolean is + begin + return X /= Val; + end Non_Eq; +end Gen; diff --git a/testsuite/tests/instr-cov/ghost_generic/gen.ads b/testsuite/tests/instr-cov/ghost_generic/gen.ads new file mode 100644 index 000000000..90ccf8cb8 --- /dev/null +++ b/testsuite/tests/instr-cov/ghost_generic/gen.ads @@ -0,0 +1,8 @@ +generic + type T is (<>); + Init : T; +package Gen is + Val : T := Init; + function Eq (X : T) return Boolean; + function Non_Eq (X : T) return Boolean; +end Gen; diff --git a/testsuite/tests/instr-cov/ghost_generic/main.adb b/testsuite/tests/instr-cov/ghost_generic/main.adb new file mode 100644 index 000000000..d3250370f --- /dev/null +++ b/testsuite/tests/instr-cov/ghost_generic/main.adb @@ -0,0 +1,16 @@ +with Gen; +with Non_Ghost_Inst; + +procedure Main is + + package Ghost_Pak is + pragma Ghost; + package Ghost_Gen is new Gen (T => Boolean, Init => True); + end Ghost_Pak; + + Res : Boolean; + pragma Volatile (Res); +begin + pragma Assert (Ghost_Pak.Ghost_Gen.Eq (True)); + Res := Non_Ghost_Inst.Non_Eq (False); +end Main; diff --git a/testsuite/tests/instr-cov/ghost_generic/non_ghost_inst.ads b/testsuite/tests/instr-cov/ghost_generic/non_ghost_inst.ads new file mode 100644 index 000000000..97d0305ce --- /dev/null +++ b/testsuite/tests/instr-cov/ghost_generic/non_ghost_inst.ads @@ -0,0 +1,3 @@ +with Gen; + +package Non_Ghost_Inst is new Gen (T => Boolean, Init => True); diff --git a/testsuite/tests/instr-cov/ghost_generic/test.py b/testsuite/tests/instr-cov/ghost_generic/test.py new file mode 100644 index 000000000..3a830103a --- /dev/null +++ b/testsuite/tests/instr-cov/ghost_generic/test.py @@ -0,0 +1,33 @@ +""" +Check that generics that are instantiated as ghost entites can be correctly +compiled when instrumented with --spark-compat. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--spark-compat"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": {"+": {11, 15}}, + "gen.adb.xcov": {"+": {9}, "-": {4}}, + "gen.ads.xcov": {}, + "non_ghost_inst.ads.xcov": {} + }, + cwd="xcov", +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/hidden_standard/src/std.adb b/testsuite/tests/instr-cov/hidden_standard/src/std.adb new file mode 100644 index 000000000..0e1074238 --- /dev/null +++ b/testsuite/tests/instr-cov/hidden_standard/src/std.adb @@ -0,0 +1,12 @@ +package body Std is + Top_Category : Boolean := (Cat = Premium); + + type My_Bool is new Boolean; + + procedure Process (X : in out Integer) is + begin + if My_Bool (Top_Category) then -- # eval + X := X + 15; + end if; + end Process; +end Std; diff --git a/testsuite/tests/instr-cov/hidden_standard/src/std.ads b/testsuite/tests/instr-cov/hidden_standard/src/std.ads new file mode 100644 index 000000000..7e55af6a7 --- /dev/null +++ b/testsuite/tests/instr-cov/hidden_standard/src/std.ads @@ -0,0 +1,10 @@ +pragma Ada_2012; + +package Std is + type Category is (Standard, System, Premium); + + Cat : Category := Premium; + pragma Volatile (Cat); + + procedure Process (X : in out Integer); +end; diff --git a/testsuite/tests/instr-cov/hidden_standard/src/test_std.adb b/testsuite/tests/instr-cov/hidden_standard/src/test_std.adb new file mode 100644 index 000000000..5e9991bae --- /dev/null +++ b/testsuite/tests/instr-cov/hidden_standard/src/test_std.adb @@ -0,0 +1,14 @@ +-- test_std.adb + +with Std; +with Support; use Support; + +procedure Test_Std is + X : Integer := 12; +begin + Std.Process (X); + Assert (X = 12 + 15); +end; + +--# std.adb +-- /eval/ l! ## dF- diff --git a/testsuite/tests/instr-cov/hidden_standard/test.py b/testsuite/tests/instr-cov/hidden_standard/test.py new file mode 100644 index 000000000..36055a8ed --- /dev/null +++ b/testsuite/tests/instr-cov/hidden_standard/test.py @@ -0,0 +1,11 @@ +""" +This is a regression test that checks that gnatcov produces valid code even +if the standard package is hidden by a user-defined enumeration member. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/library_projects/.gitignore b/testsuite/tests/instr-cov/library_projects/.gitignore new file mode 100644 index 000000000..429797921 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/.gitignore @@ -0,0 +1,3 @@ +obj-main +obj-math +obj-vectors diff --git a/testsuite/tests/instr-cov/library_projects/main.gpr b/testsuite/tests/instr-cov/library_projects/main.gpr new file mode 100644 index 000000000..df0b267e7 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/main.gpr @@ -0,0 +1,8 @@ +with "math"; +with "vectors"; + +project Main is + for Source_Dirs use ("src-main"); + for Object_Dir use "obj-main"; + for Main use ("main.adb"); +end Main; diff --git a/testsuite/tests/instr-cov/library_projects/math.gpr b/testsuite/tests/instr-cov/library_projects/math.gpr new file mode 100644 index 000000000..c7c1baaa5 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/math.gpr @@ -0,0 +1,4 @@ +project Math is + for Source_Dirs use ("src-math"); + for Object_Dir use "obj-math"; +end Math; diff --git a/testsuite/tests/instr-cov/library_projects/src-main/main.adb b/testsuite/tests/instr-cov/library_projects/src-main/main.adb new file mode 100644 index 000000000..22e390882 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/src-main/main.adb @@ -0,0 +1,14 @@ +with Math; +with Vectors; + +procedure Main is + package Number_Vectors is new Vectors (Math.Number, 10); + + use Math, Number_Vectors; + + V : Vector; +begin + Push (V, From_Integer (1)); + Push (V, From_Integer (2)); + Push (V, Element (V, 1) + Element (V, Last_Index (V))); +end Main; diff --git a/testsuite/tests/instr-cov/library_projects/src-math/math.adb b/testsuite/tests/instr-cov/library_projects/src-math/math.adb new file mode 100644 index 000000000..08fd53202 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/src-math/math.adb @@ -0,0 +1,18 @@ +package body Math is + + function From_Integer (Value : Integer) return Number is + begin + return (Value => Value); + end From_Integer; + + function "+" (Left, Right : Number) return Number is + begin + return (Value => Left.Value + Right.Value); + end "+"; + + function "-" (Left, Right : Number) return Number is + begin + return (Value => Left.Value - Right.Value); + end "-"; + +end Math; diff --git a/testsuite/tests/instr-cov/library_projects/src-math/math.ads b/testsuite/tests/instr-cov/library_projects/src-math/math.ads new file mode 100644 index 000000000..493a7c2dc --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/src-math/math.ads @@ -0,0 +1,15 @@ +package Math is + + type Number is private; + + function From_Integer (Value : Integer) return Number; + function "+" (Left, Right : Number) return Number; + function "-" (Left, Right : Number) return Number; + +private + + type Number is record + Value : Integer; + end record; + +end Math; diff --git a/testsuite/tests/instr-cov/library_projects/src-vectors/vectors.adb b/testsuite/tests/instr-cov/library_projects/src-vectors/vectors.adb new file mode 100644 index 000000000..a54bd10ab --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/src-vectors/vectors.adb @@ -0,0 +1,32 @@ +package body Vectors is + + function Last_Index (Self : Vector) return Natural is + begin + return Self.Last_Index; + end Last_Index; + + function Element (Self : Vector; Index : Positive) return Element_Type is + begin + return Self.Elements (Index); + end Element; + + procedure Push (Self : in out Vector; Element : Element_Type) is + begin + if Self.Last_Index = Capacity then + raise Constraint_Error; + else + Self.Last_Index := Self.Last_Index + 1; + Self.Elements (Self.Last_Index) := ElemenT; + end if; + end Push; + + procedure Pop (Self : in out Vector) is + begin + if Self.Last_Index = 0 then + raise Constraint_Error; + else + Self.Last_Index := Self.Last_Index - 1; + end if; + end Pop; + +end Vectors; diff --git a/testsuite/tests/instr-cov/library_projects/src-vectors/vectors.ads b/testsuite/tests/instr-cov/library_projects/src-vectors/vectors.ads new file mode 100644 index 000000000..c600f2a90 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/src-vectors/vectors.ads @@ -0,0 +1,22 @@ +generic + type Element_Type is private; + Capacity : Natural; +package Vectors is + + type Vector is private; + + function Last_Index (Self : Vector) return Natural; + function Element (Self : Vector; Index : Positive) return Element_Type; + procedure Push (Self : in out Vector; Element : Element_Type); + procedure Pop (Self : in out Vector); + +private + + type Element_Array is array (1 .. Capacity) of Element_Type; + + type Vector is record + Elements : Element_Array; + Last_Index : Natural := 0; + end record; + +end Vectors; diff --git a/testsuite/tests/instr-cov/library_projects/test.py b/testsuite/tests/instr-cov/library_projects/test.py new file mode 100644 index 000000000..de77cca8d --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/test.py @@ -0,0 +1,40 @@ +""" +Test that instrumented source coverage works as expected on a setup of library +projects and one program project. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +main_gpr = os.path.abspath('main.gpr') +main_obj_dir = os.path.abspath('obj-main') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=main_gpr, + projects=['main', 'math', 'vectors']), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=main_obj_dir, + gpr_exe_dir=main_obj_dir, + trace_mode='src') +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'+': {5, 9, 11, 12, 13}}, + + 'xcov/vectors.ads.xcov': {'+': {6, 15, 17, 18, 19, 20}}, + 'xcov/vectors.adb.xcov': {'+': {5, 10, 15, 18, 19}, + '-': {16, 25, 26, 28}}, + + 'xcov/math.ads.xcov': {'+': {3, 11, 12, 13}}, + 'xcov/math.adb.xcov': {'+': {5, 10}, '-': {15}}, +}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/library_projects/vectors.gpr b/testsuite/tests/instr-cov/library_projects/vectors.gpr new file mode 100644 index 000000000..3509e8264 --- /dev/null +++ b/testsuite/tests/instr-cov/library_projects/vectors.gpr @@ -0,0 +1,4 @@ +project Vectors is + for Source_Dirs use ("src-vectors"); + for Object_Dir use "obj-vectors"; +end Vectors; diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/main.adb b/testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/main.adb new file mode 100644 index 000000000..026a2fb5d --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/main.adb @@ -0,0 +1,10 @@ +with Interfaces.C; use Interfaces.C; + +procedure Main is + function fact (N : int) return int; + pragma Import (C, fact); +begin + if fact (1) /= 1 then + raise Program_Error; + end if; +end Main; diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/tested.c b/testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/tested.c new file mode 100644 index 000000000..6b157b0fe --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/ada-main/tested.c @@ -0,0 +1,8 @@ +int +fact (int n) +{ + if (n <= 1) + return n; + else + return n * fact (n - 1); +} diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/main.c b/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/main.c new file mode 100644 index 000000000..b22f14e53 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/main.c @@ -0,0 +1,10 @@ +extern int fact (int n); +extern void check (int c); + +int +main (void) +{ + int n = fact (1); + check (n == 1); + return 0; +} diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.adb b/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.adb new file mode 100644 index 000000000..9debcbf5f --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.adb @@ -0,0 +1,27 @@ +package body Pkg is + + ---------- + -- Fact -- + ---------- + + function Fact (N : int) return int is + begin + if N <= 1 then + return N; + else + return N * Fact (N - 1); + end if; + end Fact; + + ----------- + -- Check -- + ----------- + + procedure Check (Cond : int) is + begin + if Cond = 0 then + raise Program_Error; + end if; + end Check; + +end Pkg; diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.ads b/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.ads new file mode 100644 index 000000000..eecc1958c --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/c-main/pkg.ads @@ -0,0 +1,13 @@ +with Interfaces.C; use Interfaces.C; + +package Pkg is + + function Fact (N : int) return int; + pragma Export (C, Fact, "fact"); + + procedure Check (Cond : int); + pragma Export (C, Check, "check"); + -- This is akin to "assert", with an int arg and not + -- conflicting with the libsupport exposed one. + +end Pkg; diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py b/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py new file mode 100644 index 000000000..20c51f021 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py @@ -0,0 +1,59 @@ +""" +Check that gnatcov correctly instruments mains for the automatic dump of +coverage buffers even if these mains are in languages for which coverage is +disabled. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +# First check with a project that contains a C unit (to analyze) driven by an +# Ada main (not to analyze). +tmp = Wdir("tmp_ada-main") +thistest.log("== ada-main ==") +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../ada-main"], mains=["main.adb"]), + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--restricted-to-languages=C"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + auto_languages=False, +) +check_xcov_reports( + "*.xcov", {"tested.c.xcov": {"+": {5}, "-": {7}}}, cwd="xcov" +) +tmp.to_homedir() + +# Now check with a project that contains an Ada unit (to analyze) driven by a +# C main (not to analyze). +tmp = Wdir("tmp_c-main") +thistest.log("== c-main ==") +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../c-main"], mains=["main.c"]), + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--restricted-to-languages=Ada"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + auto_languages=False, +) +check_xcov_reports( + "*.xcov", + { + "pkg.adb.xcov": {"+": {10, 22}, "-": {12, 23}}, + "pkg.ads.xcov": {}, + }, + cwd="xcov" +) +tmp.to_homedir() + +thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-decl.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-decl.adb new file mode 100644 index 000000000..16e774d85 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-decl.adb @@ -0,0 +1,19 @@ +procedure Dotted.Decl is + procedure Foo; + procedure Bar; + + procedure Foo is + begin + null; + end Foo; + + procedure Bar is + begin + Dotted.Decl.Foo; + Decl.Foo; + end Bar; + +begin + Dotted.Decl.Bar; + Decl.Foo; +end Dotted.Decl; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-exn.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-exn.adb new file mode 100644 index 000000000..69cc2c09e --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-exn.adb @@ -0,0 +1,17 @@ +procedure Dotted.Exn is + procedure Foo is + begin + raise Program_Error; + end Foo; + + procedure Bar is + begin + null; + end Bar; +begin + Dotted.Exn.Bar; + Exn.Foo; +exception + when Program_Error => + Exn.Bar; +end Dotted.Exn; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-no_decl.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-no_decl.adb new file mode 100644 index 000000000..62cbd8f7b --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-no_decl.adb @@ -0,0 +1,12 @@ +procedure Dotted.No_Decl is +begin + Block : declare + procedure Foo is + begin + null; + end Foo; + begin + Dotted.No_Decl.Block.Foo; + No_Decl.Block.Foo; + end Block; +end Dotted.No_Decl; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.adb new file mode 100644 index 000000000..80e18c78b --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.adb @@ -0,0 +1,15 @@ +package body Dotted is + + package body Simple_Decl is + procedure Foo is + begin + null; + end Foo; + end Simple_Decl; + + procedure Bar is + begin + raise Program_Error; + end Bar; + +end Dotted; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.ads b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.ads new file mode 100644 index 000000000..412536ca0 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.ads @@ -0,0 +1,8 @@ +package Dotted is + package Simple_Decl is + procedure Foo; + end Simple_Decl; + + procedure Bar; + +end Dotted; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_decl.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_decl.adb new file mode 100644 index 000000000..0942da694 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_decl.adb @@ -0,0 +1,21 @@ +with Dotted; + +procedure Simple_Decl is + + procedure Foo; + procedure Bar; + + procedure Foo is + begin + null; + end Foo; + + procedure Bar is + begin + Simple_Decl.Foo; + Dotted.Simple_Decl.Foo; + end Bar; +begin + Simple_Decl.Bar; + Dotted.Simple_Decl.Foo; +end Simple_Decl; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_exn.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_exn.adb new file mode 100644 index 000000000..bdef7bf6f --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_exn.adb @@ -0,0 +1,17 @@ +procedure Simple_Exn is + procedure Foo is + begin + raise Program_Error; + end Foo; + + procedure Bar is + begin + null; + end Bar; +begin + Bar; + Simple_Exn.Foo; +exception + when Program_Error => + Simple_Exn.Bar; +end Simple_Exn; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_no_decl.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_no_decl.adb new file mode 100644 index 000000000..6c05c89a0 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_no_decl.adb @@ -0,0 +1,11 @@ +procedure Simple_No_Decl is +begin + Block : declare + procedure Foo is + begin + null; + end Foo; + begin + Simple_No_Decl.Block.Foo; + end Block; +end Simple_No_Decl; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_only_exn.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_only_exn.adb new file mode 100644 index 000000000..13be0bda0 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_only_exn.adb @@ -0,0 +1,21 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Dotted; + +procedure Simple_Only_Exn is +begin + Block : declare + procedure Foo is + begin + Put_Line ("Foo was called"); + end Foo; + begin + Simple_Only_Exn.Block.Foo; + Dotted.Bar; + end Block; +exception + when Program_Error => + Put_Line ("Program_Error"); + when Constraint_Error => + Put_Line ("Constraint_Error"); +end Simple_Only_Exn; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/test.opt b/testsuite/tests/instr-cov/main_autodump/nested_block/test.opt new file mode 100644 index 000000000..e239b0933 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/test.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD Test only makes sense with exception propagation diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/test.py b/testsuite/tests/instr-cov/main_autodump/nested_block/test.py new file mode 100644 index 000000000..ca11a73ef --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/test.py @@ -0,0 +1,79 @@ +""" +Check that the instrumenter correctly renames qualified names in the mains. +This test mainly checks that the various mains used are correctly built after +instrumentation, and that their coverage results are correct. +This also checks the instrumentation of the main source correctly inserts +buffers dump code when the main procedure has top-level exception handlers. +(Former test S607-033-instr-exc-handler) +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir() + +# Names of the various mains tested. +# +# Mains of the form "test_simple*"" are mains with a simple name +# (i.e. not dotted) whereas those of the form "test_dotted*" are mains with +# a dotted name. +# +# Mains of the form "*decl" are mains with top level declarations, +# those of the form "*exn" are mains with top level exception handlers, +# and should have their qualified names be modified. +# +# The mains of the form "*no_decl" have no top level decalrations nor exception +# handlers, and should not have their qualified names renamed. +main_names = ["simple_no_decl", "simple_decl", "simple_exn", "simple_only_exn", + "dotted-decl", "dotted-no_decl", "dotted-exn"] + +# The expected results are not really of imporance here, what matters is that +# the mains got instrumented and build correctly. +expected_results = { + "dotted-decl": { + "xcov/dotted-decl.adb.xcov": {'+': {7, 12, 13, 17, 18}} + }, + "dotted-no_decl": { + "xcov/dotted-no_decl.adb.xcov": {'+': {6, 9, 10}} + }, + "dotted-exn": { + "xcov/dotted-exn.adb.xcov": {'+': {4, 9, 12, 13, 16}} + }, + "simple_decl": { + "xcov/simple_decl.adb.xcov": {'+': {10, 15, 16, 19, 20}} + }, + "simple_no_decl": { + "xcov/simple_no_decl.adb.xcov": {'+': {6, 9}} + }, + "simple_exn": { + "xcov/simple_exn.adb.xcov": {'+': {4, 9, 12, 13, 16}} + }, + "simple_only_exn": { + "xcov/simple_only_exn.adb.xcov": {'+': {10, 13, 14, 18}, '-': {20}} + } +} + + +def do_one_main(main_name): + """ + create a project, instrument build and compute coverage reports for the given + main, from the expected results dictionnary defined above. + """ + tmp.to_subdir(f'tmp_{main_name}') + p = gprfor(mains=[f"{main_name}.adb"], + srcdirs=[".."]) + build_run_and_coverage( + gprsw=GPRswitches(root_project=p, units=[main_name.replace('-', '.')]), + covlevel='stmt', + mains=[main_name], + extra_coverage_args=['-axcov', '--output-dir=xcov']) + check_xcov_reports('xcov/*.xcov', expected_results[main_name]) + + +for main_name in main_names: + do_one_main(main_name) + +thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/pramga_prio/main.adb b/testsuite/tests/instr-cov/main_autodump/pramga_prio/main.adb new file mode 100644 index 000000000..d3259195e --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/pramga_prio/main.adb @@ -0,0 +1,17 @@ +with System; use System; + +procedure Main is + pragma Priority (Priority'First); + + function Ident (X : Boolean) return Boolean; + + function Ident (X : Boolean) return Boolean is + begin + return X; + end; + + X : Boolean := True; + pragma Volatile (X); +begin + X := Ident (X); +end Main; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.opt b/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.opt new file mode 100644 index 000000000..c63def349 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD requires tasking pragma availability \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.py b/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.py new file mode 100644 index 000000000..5f542a790 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.py @@ -0,0 +1,37 @@ +""" +Check that the instrumentation of Ada mains is compatible with the presence of +a pragma Priority in the main. It should be left in the top level declarations +of the main, otherwise the main will fail to compile. +""" + +from SCOV.instr import available_ada_dump_triggers +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir() + +# Explicitly test all available dump triggers to maximize coverage +for dump_trigger in available_ada_dump_triggers(): + tmp.to_subdir(f"tmp_{dump_trigger}") + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.adb"]) + ), + covlevel="stmt", + mains=["main"], + dump_trigger=dump_trigger, + extra_coverage_args=["-axcov"], + trace_mode="src", + ) + + # We expect all lines to be covered + check_xcov_reports( + "*.xcov", + {"main.adb.xcov": {"+": {10, 13, 16}}}, + cwd="obj", + ) + +thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/stubs/main-inner.adb b/testsuite/tests/instr-cov/main_autodump/stubs/main-inner.adb new file mode 100644 index 000000000..937b467b9 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs/main-inner.adb @@ -0,0 +1,6 @@ +separate (Main) + +function Inner (X : Boolean) return Boolean is +begin + return X; +end Inner; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/stubs/main.adb b/testsuite/tests/instr-cov/main_autodump/stubs/main.adb new file mode 100644 index 000000000..bca58ba32 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs/main.adb @@ -0,0 +1,8 @@ +procedure Main is + function Inner (X : Boolean) return Boolean is separate; + + X : Boolean := True; + pragma Volatile (X); +begin + X := Inner (X); +end Main; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/stubs/test.py b/testsuite/tests/instr-cov/main_autodump/stubs/test.py new file mode 100644 index 000000000..2bfe6777c --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs/test.py @@ -0,0 +1,40 @@ +""" +Check that the instrumentation of Ada mains is compatible with the presence of +stub declarations in the declarative part of the main. +""" + +from SCOV.instr import available_ada_dump_triggers +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir() + +# Explicitly test all available dump triggers to maximize coverage +for dump_trigger in available_ada_dump_triggers(): + tmp.to_subdir(f"tmp_{dump_trigger}") + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.adb"]) + ), + covlevel="stmt", + mains=["main"], + dump_trigger=dump_trigger, + extra_coverage_args=["-axcov"], + trace_mode="src", + ) + + # We expect all lines to be covered + check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": {"+": {4, 7}}, + "main-inner.adb.xcov": {"+": {5}}, + }, + cwd="obj", + ) + + +thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main-inner.adb b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main-inner.adb new file mode 100644 index 000000000..937b467b9 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main-inner.adb @@ -0,0 +1,6 @@ +separate (Main) + +function Inner (X : Boolean) return Boolean is +begin + return X; +end Inner; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main.adb b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main.adb new file mode 100644 index 000000000..cfa3c6310 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main.adb @@ -0,0 +1,16 @@ +with System; use System; + +with Pkg; use Pkg; + +procedure Main is + pragma Priority (Priority'First); + + function Inner (X : Boolean) return Boolean is separate; + + X : Boolean := True; + pragma Volatile (X); + + Ctrl_Object : Ctrl_Type; +begin + X := Inner (X); +end Main; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.adb b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.adb new file mode 100644 index 000000000..d4f7ce8b3 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + procedure Finalize (Self : in out Ctrl_type) is + begin + Put_Line ("Got finalized"); + end Finalize; +end Pkg; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.ads b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.ads new file mode 100644 index 000000000..63f644a27 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.ads @@ -0,0 +1,8 @@ +with Ada.Finalization; + +package Pkg is + + type Ctrl_Type is new Ada.Finalization.Controlled with null record; + + procedure Finalize (Self : in out Ctrl_Type); +end Pkg; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.opt b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.opt new file mode 100644 index 000000000..6a242f522 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.opt @@ -0,0 +1,2 @@ +RTS_ZFP DEAD uses controlled types not available in light runtimes +RTS_LIGHT_TASKING DEAD uses controlled types not available in light-tasking runtimes \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.py b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.py new file mode 100644 index 000000000..ab944db8c --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.py @@ -0,0 +1,42 @@ +""" +Check that the instrumentation of Ada mains is compatible with both the +presence of stub declarations in the declarative part of the main, and the +presence of controlled types in the main. +""" + +from SCOV.instr import available_ada_dump_triggers +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir() + +# Explicitly test all available dump triggers to maximize coverage +for dump_trigger in available_ada_dump_triggers(): + tmp.to_subdir(f"tmp_{dump_trigger}") + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.adb"]) + ), + covlevel="stmt", + mains=["main"], + dump_trigger=dump_trigger, + extra_coverage_args=["-axcov"], + trace_mode="src", + ) + + # We expect all lines to be covered + check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": {"+": {10, 13, 15}}, + "main-inner.adb.xcov": {"+": {5}}, + "pkg.adb.xcov": {"+": {6}}, + "pkg.ads.xcov": {"+": {5}}, + }, + cwd="obj", + ) + +thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/task_in_main/main.adb b/testsuite/tests/instr-cov/main_autodump/task_in_main/main.adb new file mode 100644 index 000000000..8b2f5b711 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/task_in_main/main.adb @@ -0,0 +1,20 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Real_Time; use Ada.Real_Time; + +procedure Main is + + Val : Boolean := False; + pragma Volatile (Val); + + task T; + + task body T is + begin + delay until Clock + Seconds (5); + Put_Line ("In Task"); + Val := True; + end T; + +begin + Put_Line ("In main"); +end Main; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/task_in_main/test.opt b/testsuite/tests/instr-cov/main_autodump/task_in_main/test.opt new file mode 100644 index 000000000..06689ed1a --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/task_in_main/test.opt @@ -0,0 +1 @@ +!RTS_FULL DEAD embedded runtimes do not support task hierarchy \ No newline at end of file diff --git a/testsuite/tests/instr-cov/main_autodump/task_in_main/test.py b/testsuite/tests/instr-cov/main_autodump/task_in_main/test.py new file mode 100644 index 000000000..45393f7a1 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/task_in_main/test.py @@ -0,0 +1,36 @@ +""" +Check that coverage of code inside tasks depending on the main, but +which terminates after the main's handled statements, is correctly assessed. +""" + +from SCOV.instr import available_ada_dump_triggers +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir() + +# Explicitly test all available dump triggers to maximize coverage +for dump_trigger in available_ada_dump_triggers(): + tmp.to_subdir(f"tmp_{dump_trigger}") + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.adb"]) + ), + covlevel="stmt", + mains=["main"], + dump_trigger=dump_trigger, + extra_coverage_args=["-axcov"], + trace_mode="src", + ) + + # We expect all lines to be covered + check_xcov_reports( + "*.xcov", + {"main.adb.xcov": {"+": {6, 9, 13, 14, 15, 19}}}, + cwd="obj", + ) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb b/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb new file mode 100644 index 000000000..6c40b1da8 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb @@ -0,0 +1,11 @@ +with Ada.Command_Line; + +with GNATcov_RTS.Buffers.Lists.P; +with GNATcov_RTS.Traces.Output.Files; + +procedure Covdump is +begin + GNATcov_RTS.Traces.Output.Files.Write_Trace_File + (Buffers_Groups => GNATcov_RTS.Buffers.Lists.P.List, + Filename => Ada.Command_Line.Command_Name & ".srctrace"); +end Covdump; diff --git a/testsuite/tests/instr-cov/manual-dump/covdump__nocov.adb b/testsuite/tests/instr-cov/manual-dump/covdump__nocov.adb new file mode 100644 index 000000000..f696c5b21 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/covdump__nocov.adb @@ -0,0 +1,4 @@ +procedure Covdump is +begin + null; +end Covdump; diff --git a/testsuite/tests/instr-cov/manual-dump/main.adb b/testsuite/tests/instr-cov/manual-dump/main.adb new file mode 100644 index 000000000..485e3b597 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/main.adb @@ -0,0 +1,6 @@ +with Covdump; + +procedure Main is +begin + Covdump; +end Main; diff --git a/testsuite/tests/instr-cov/manual-dump/test.opt b/testsuite/tests/instr-cov/manual-dump/test.opt new file mode 100644 index 000000000..1dfb5a7b0 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD Check features specific to instrumentation. +!RTS_FULL DEAD Uses the full instrumentation runtime. diff --git a/testsuite/tests/instr-cov/manual-dump/test.py b/testsuite/tests/instr-cov/manual-dump/test.py new file mode 100644 index 000000000..a4ebf93c7 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/test.py @@ -0,0 +1,51 @@ +""" +This test checks that we don't break the GNATcov_RTS API for manual trace +dumps. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor( + prjid="p", + srcdirs=[".."], + mains=["main.adb"], + langs=["Ada"], + + # Depending on the build mode, use a different implementation of + # the Covdump procedure. This allows the regular build to work (no + # dependency on GNATcov_RTS nor coverage buffers) and at the same + # time, allows the coverage build to do the coverage dump. + scenario_extra=""" + type Boolean is ("False", "True"); + Cov_Build : Boolean := external ("COV_BUILD", "False"); + """, + extra=""" + package Naming is + case Cov_Build is + when "False" => + for Body ("covdump") use "covdump__nocov.adb"; + when "True" => + for Body ("covdump") use "covdump__cov.adb"; + end case; + end Naming; + """, + ), + units=["main"], + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--dump-trigger=manual"], + extra_gprbuild_args=["-XCOV_BUILD=True"], + extra_coverage_args=["--annotate=xcov", "-XCOV_BUILD=True"], +) +check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {5}}}, "obj") + +thistest.result() diff --git a/testsuite/tests/instr-cov/mixed_and/main.adb b/testsuite/tests/instr-cov/mixed_and/main.adb new file mode 100644 index 000000000..7e338c326 --- /dev/null +++ b/testsuite/tests/instr-cov/mixed_and/main.adb @@ -0,0 +1,19 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + Who : constant String := "world"; +begin + if Who'Length = 0 then + raise Constraint_Error; + elsif Who'Length = 1 and Who (Who'First) = 'h' then + raise Constraint_Error; + elsif Who'Length = 0 or Who (Who'First) = 'h' then + raise Constraint_Error; + elsif Who'Length = 0 xor Who (Who'First) = 'h' then + raise Constraint_Error; + elsif Who'Length = 0 or else Who (Who'First) = 'h' then + raise Constraint_Error; + else + Put_Line ("Hello " & Who); + end if; +end Main; diff --git a/testsuite/tests/instr-cov/mixed_and/p.gpr b/testsuite/tests/instr-cov/mixed_and/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/mixed_and/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/mixed_and/test.py b/testsuite/tests/instr-cov/mixed_and/test.py new file mode 100644 index 000000000..4a9c616c4 --- /dev/null +++ b/testsuite/tests/instr-cov/mixed_and/test.py @@ -0,0 +1,32 @@ +""" +Test that AND/OR/XOR boolean expressions are correctly wrapped in parens when +inserting a witness call before them. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'+': {4, 6, 8, 10, 12, 14, 17}, + '-': {7, 9, 11, 13, 15}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/multiline_marker/main.c b/testsuite/tests/instr-cov/multiline_marker/main.c new file mode 100644 index 000000000..57138847f --- /dev/null +++ b/testsuite/tests/instr-cov/multiline_marker/main.c @@ -0,0 +1,17 @@ +#include + +int +main (int argc, char *argv[]) +{ + volatile int a = 0, b = 0; + + // Implicit example: the expansion of the assert macro will generate + // redundant line markers. + assert (a == 0 && b == 0); + + // Explicit example with redundant line markers +#line 14 + int c; +#line 14 + return 0; +} diff --git a/testsuite/tests/instr-cov/multiline_marker/test.opt b/testsuite/tests/instr-cov/multiline_marker/test.opt new file mode 100644 index 000000000..17f984f55 --- /dev/null +++ b/testsuite/tests/instr-cov/multiline_marker/test.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD No libc in light runtimes \ No newline at end of file diff --git a/testsuite/tests/instr-cov/multiline_marker/test.py b/testsuite/tests/instr-cov/multiline_marker/test.py new file mode 100644 index 000000000..957d88ea3 --- /dev/null +++ b/testsuite/tests/instr-cov/multiline_marker/test.py @@ -0,0 +1,29 @@ +""" +Check that gnatcov produces correct SCOs (i.e. with no source location nesting) +when there are redundant line markers resulting in nested SCOs. + +This can happen with macro expansions mixing user-code and systems-header code +(such as the assert macro). The resulting expansion will have multiple line +markers, with a special flag for the code that comes from system headers. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +wd = Wdir("tmp_") + +# Build and produce a coverage report for the test project. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src', +) +check_xcov_reports("*.xcov", {"main.c.xcov": {"+": {6, 10, 14}}}, "xcov") + +thistest.result() diff --git a/testsuite/tests/instr-cov/multiple_mains/src/test_a.adb b/testsuite/tests/instr-cov/multiple_mains/src/test_a.adb new file mode 100644 index 000000000..bcb125fc0 --- /dev/null +++ b/testsuite/tests/instr-cov/multiple_mains/src/test_a.adb @@ -0,0 +1,4 @@ +procedure Test_A is +begin + null; +end Test_A; diff --git a/testsuite/tests/instr-cov/multiple_mains/src/test_b.adb b/testsuite/tests/instr-cov/multiple_mains/src/test_b.adb new file mode 100644 index 000000000..58bc27953 --- /dev/null +++ b/testsuite/tests/instr-cov/multiple_mains/src/test_b.adb @@ -0,0 +1,6 @@ +with Test_A; + +procedure Test_B is +begin + null; +end Test_B; diff --git a/testsuite/tests/instr-cov/multiple_mains/test.py b/testsuite/tests/instr-cov/multiple_mains/test.py new file mode 100644 index 000000000..b490c546a --- /dev/null +++ b/testsuite/tests/instr-cov/multiple_mains/test.py @@ -0,0 +1,24 @@ +""" +Check that the instrumentation of multiple mains, with one of the main being +in the closure of the other, works. + +With gnatcov instrument, we used to generate a unique C symbol for the +Dump_Buffer procedure, that resulted in symbol name clashing when linking. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_and_run( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], + mains=["test_a.adb", "test_b.adb"])), + covlevel="stmt", mains=[], extra_coverage_args=[], trace_mode="src", +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/nested_ternary/main.c b/testsuite/tests/instr-cov/nested_ternary/main.c new file mode 100644 index 000000000..a50a7a7a0 --- /dev/null +++ b/testsuite/tests/instr-cov/nested_ternary/main.c @@ -0,0 +1,6 @@ +int +main () +{ + int a = 1 ? 0 : 1 ? 0 : 1; + return a; +} diff --git a/testsuite/tests/instr-cov/nested_ternary/test.py b/testsuite/tests/instr-cov/nested_ternary/test.py new file mode 100644 index 000000000..2a121a4b8 --- /dev/null +++ b/testsuite/tests/instr-cov/nested_ternary/test.py @@ -0,0 +1,26 @@ +""" +Check that the instrumentation of a nested ternary expression works. It used +to produce duplicate SCOs and make gnatcov crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +# Build and produce a coverage report for the test project. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel='stmt+decision', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src', +) + +check_xcov_reports('*.xcov', {'main.c.xcov': {'!': {4}}}, "xcov") + +thistest.result() diff --git a/testsuite/tests/instr-cov/no_main/main.adb b/testsuite/tests/instr-cov/no_main/main.adb new file mode 100644 index 000000000..4937d0976 --- /dev/null +++ b/testsuite/tests/instr-cov/no_main/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Main is + Who : constant String := "world"; +begin + Put_Line ("Hello, " & Who & "!"); + Put_Line ("Fact (6) = " & Integer'Image (Pkg.Fact (6))); +end Main; diff --git a/testsuite/tests/instr-cov/no_main/p.gpr b/testsuite/tests/instr-cov/no_main/p.gpr new file mode 100644 index 000000000..0208ec6ab --- /dev/null +++ b/testsuite/tests/instr-cov/no_main/p.gpr @@ -0,0 +1,8 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); + + package Coverage is + for Units use ("pkg"); + end Coverage; +end P; diff --git a/testsuite/tests/instr-cov/no_main/pkg.adb b/testsuite/tests/instr-cov/no_main/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/no_main/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/no_main/pkg.ads b/testsuite/tests/instr-cov/no_main/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/no_main/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/no_main/test.py b/testsuite/tests/instr-cov/no_main/test.py new file mode 100644 index 000000000..092b2b58b --- /dev/null +++ b/testsuite/tests/instr-cov/no_main/test.py @@ -0,0 +1,32 @@ +""" +Test the instrumentation (--auto-dump-buffers) of a main that is not a unit of +interest. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') +check_xcov_reports('xcov/*.xcov', { + 'xcov/pkg.adb.xcov': {'+': {5, 6, 8}}, +}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/not_array/main.adb b/testsuite/tests/instr-cov/not_array/main.adb new file mode 100644 index 000000000..1b0fb51b4 --- /dev/null +++ b/testsuite/tests/instr-cov/not_array/main.adb @@ -0,0 +1,16 @@ +pragma Ada_2012; + +procedure Main is + type Enum_Type is (A, B, C, D); + type Flags_Type is array (Enum_Type) of Boolean; + + function Identity (B : Boolean) return Boolean is (B); + function Get_Flags (B : Boolean) return Flags_Type + is (Flags_Type'(others => B)); + + X : Boolean := Identity (True); + Y : Boolean := Identity (False); + Flags : Flags_Type := not Get_Flags (X and then Y); +begin + Flags := not Flags; +end Main; diff --git a/testsuite/tests/instr-cov/not_array/p.gpr b/testsuite/tests/instr-cov/not_array/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/not_array/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/not_array/test.opt b/testsuite/tests/instr-cov/not_array/test.opt new file mode 100644 index 000000000..6f632999b --- /dev/null +++ b/testsuite/tests/instr-cov/not_array/test.opt @@ -0,0 +1,3 @@ +RTS_ZFP DEAD Test requires System.Boolean_Array_Operations.Vector_Not +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 +7.1.2 DEAD support for expression functions weak in 7.1.2 \ No newline at end of file diff --git a/testsuite/tests/instr-cov/not_array/test.py b/testsuite/tests/instr-cov/not_array/test.py new file mode 100644 index 000000000..ba03248f5 --- /dev/null +++ b/testsuite/tests/instr-cov/not_array/test.py @@ -0,0 +1,38 @@ +""" +Check that we don't consider "not" as a decision operation when standalone. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') + +tmp = Wdir('tmp_') + +# Use --all-decisions so that, even though we are using stmt+decision, we can +# check if the "X and then Y" decision is properly instrumented (thanks to its +# "outcome True not exercized" violation). +# +# TODO: use MC/DC instead not to use --all-decisions. This currently creates +# sources that make GNAT crash. +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt+decision', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov', '--all-decisions'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') +check_xcov_reports('xcov/*.xcov', {'xcov/main.adb.xcov': { + '+': {4, 5, 7, 9, 11, 12, 15}, + '!': {13}, +}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/null_proc_generic/src/main.adb b/testsuite/tests/instr-cov/null_proc_generic/src/main.adb new file mode 100644 index 000000000..51ce6a341 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_generic/src/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is + procedure P is new Pkg.P (Integer); +begin + P (0); +end Main; diff --git a/testsuite/tests/instr-cov/null_proc_generic/src/pkg.ads b/testsuite/tests/instr-cov/null_proc_generic/src/pkg.ads new file mode 100644 index 000000000..5873d9a1b --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_generic/src/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + generic + type T is private; + procedure P (Item : T); + + procedure P (Item : T) is null; +end Pkg; diff --git a/testsuite/tests/instr-cov/null_proc_generic/test.opt b/testsuite/tests/instr-cov/null_proc_generic/test.opt new file mode 100644 index 000000000..efd316f1d --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_generic/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Requires Ada 2012, unavailable in 5.04a1 +7.1.2 DEAD overloading of generic null procedures not supported in 7.1.2 \ No newline at end of file diff --git a/testsuite/tests/instr-cov/null_proc_generic/test.py b/testsuite/tests/instr-cov/null_proc_generic/test.py new file mode 100644 index 000000000..9f962ac03 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_generic/test.py @@ -0,0 +1,46 @@ +""" +Check that the instrumentation of generic null procedures produces valid +code. It used to instantiate generic packages with a generic formal not +available at that point, which is not valid Ada code. + +For now we do not know how to instrument generic null procedures, so we +emit a warning for them at instrumentation time and always consider them +non-instrumented. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["main.adb"]), + units=["pkg"], + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=."], + trace_mode="src", + tolerate_instrument_messages="cannot instrument generic null procedures", +) + +# We only expect non-instrumented lines +check_xcov_reports("*.xcov", {"pkg.ads.xcov": {"?": {6}}}) + +# Check that the null procedure is reported as a warning +warning_msg = ( + "gnatcov limitation: cannot instrument generic null procedures." + " Consider turning it into a regular procedure body." +) +thistest.fail_if_not_equal( + "'gnatcov instrument' log", + f"!!! pkg.ads:6:4: {warning_msg}\n", + contents_of("instrument.log"), +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/null_proc_not_null/src/pkg.ads b/testsuite/tests/instr-cov/null_proc_not_null/src/pkg.ads new file mode 100644 index 000000000..588b28283 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_not_null/src/pkg.ads @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package Pkg is + + type String_Access is access all String; + My_String : aliased String := "hello world"; + + procedure Ignore_1 (S : not null String_Access) is null; -- # p-1 + procedure Ignore_2 (S : not null access constant String) is null; -- # p-2 + +end Pkg; diff --git a/testsuite/tests/instr-cov/null_proc_not_null/src/test_1.adb b/testsuite/tests/instr-cov/null_proc_not_null/src/test_1.adb new file mode 100644 index 000000000..70d61acf3 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_not_null/src/test_1.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +with Pkg; + +procedure Test_1 is +begin + Pkg.Ignore_1 (Pkg.My_String'Access); +end Test_1; + +--# pkg.ads +-- /p-1/ l+ ## 0 +-- /p-2/ l- ## s- diff --git a/testsuite/tests/instr-cov/null_proc_not_null/src/test_12.adb b/testsuite/tests/instr-cov/null_proc_not_null/src/test_12.adb new file mode 100644 index 000000000..4dd290aca --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_not_null/src/test_12.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; + +with Pkg; + +procedure Test_12 is +begin + Pkg.Ignore_1 (Pkg.My_String'Access); + Pkg.Ignore_2 (Pkg.My_String'Access); +end Test_12; + +--# pkg.ads +-- /p-1/ l+ ## 0 +-- /p-2/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/null_proc_not_null/src/test_2.adb b/testsuite/tests/instr-cov/null_proc_not_null/src/test_2.adb new file mode 100644 index 000000000..8dcb6c390 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_not_null/src/test_2.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +with Pkg; + +procedure Test_2 is +begin + Pkg.Ignore_2 (Pkg.My_String'Access); +end Test_2; + +--# pkg.ads +-- /p-1/ l- ## s- +-- /p-2/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/null_proc_not_null/src/test_no.adb b/testsuite/tests/instr-cov/null_proc_not_null/src/test_no.adb new file mode 100644 index 000000000..f58d70201 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_not_null/src/test_no.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +with Pkg; + +procedure Test_No is +begin + Pkg.My_String (Pkg.My_String'First) := 'H'; +end Test_No; + +--# pkg.ads +-- /p-1/ l- ## s- +-- /p-2/ l- ## s- diff --git a/testsuite/tests/instr-cov/null_proc_not_null/test.py b/testsuite/tests/instr-cov/null_proc_not_null/test.py new file mode 100644 index 000000000..f24ecfe05 --- /dev/null +++ b/testsuite/tests/instr-cov/null_proc_not_null/test.py @@ -0,0 +1,12 @@ +""" +Check that the instrumentation of null procedures with a "not null" argument +produces valid code. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/pragma_after_cu/main.adb b/testsuite/tests/instr-cov/pragma_after_cu/main.adb new file mode 100644 index 000000000..5a68074d4 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_after_cu/main.adb @@ -0,0 +1,10 @@ +with Raise_Error; +with Silent_Last_Chance; + +procedure Main is +begin + Raise_Error; +exception + when Program_Error => + null; +end Main; diff --git a/testsuite/tests/instr-cov/pragma_after_cu/raise_error.adb b/testsuite/tests/instr-cov/pragma_after_cu/raise_error.adb new file mode 100644 index 000000000..a14c78034 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_after_cu/raise_error.adb @@ -0,0 +1,4 @@ +procedure Raise_Error is +begin + raise Program_Error; +end Raise_Error; diff --git a/testsuite/tests/instr-cov/pragma_after_cu/raise_error.ads b/testsuite/tests/instr-cov/pragma_after_cu/raise_error.ads new file mode 100644 index 000000000..3d1de63cd --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_after_cu/raise_error.ads @@ -0,0 +1,2 @@ +procedure Raise_Error; +pragma No_Return (Raise_Error); diff --git a/testsuite/tests/instr-cov/pragma_after_cu/test.opt b/testsuite/tests/instr-cov/pragma_after_cu/test.opt new file mode 100644 index 000000000..a1ace576d --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_after_cu/test.opt @@ -0,0 +1 @@ +src-traces,RTS_ZFP DEAD Cannot dump coverage buffers in this test without non-local execption propagation diff --git a/testsuite/tests/instr-cov/pragma_after_cu/test.py b/testsuite/tests/instr-cov/pragma_after_cu/test.py new file mode 100644 index 000000000..4bb0159ea --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_after_cu/test.py @@ -0,0 +1,27 @@ +""" +Check that units whose compilation unit contains pragmas after the body are +properly handled. They used to make the instrumenter crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], +) +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'+': {6}}, + 'xcov/raise_error.adb.xcov': {'+': {3}}, + 'xcov/raise_error.ads.xcov': {}, +}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/pragma_assert/src/pkg.ads b/testsuite/tests/instr-cov/pragma_assert/src/pkg.ads new file mode 100644 index 000000000..dff448938 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_assert/src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + Foo, Bar : Boolean := True; +end Pkg; diff --git a/testsuite/tests/instr-cov/pragma_assert/src/test_main.adb b/testsuite/tests/instr-cov/pragma_assert/src/test_main.adb new file mode 100644 index 000000000..84d0c535c --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_assert/src/test_main.adb @@ -0,0 +1,34 @@ +pragma Ada_2012; +with Pkg; + +procedure Test_Main is + + -- We expect gnatcov to detect two decisions below: one for the whole + -- IF expression, and one for its condition (Pkg.Foo). + + pragma Assert -- # assert_stmt + ((if -- # inner_decision + Pkg.Foo -- # inner_cond_1 + then Pkg.Bar) and then Pkg.Foo); -- # inner_cond_2 + +begin + for J in 1 .. 3 loop + + -- Regression test: gnatcov used to instrument Loop_Invariant as + -- statements, by inserting a witness statement right before. This + -- does not work, as Loop_Invariant pragmas must be groupped + -- together. + + pragma Loop_Invariant (Pkg.Foo); --# loop_invariant_1 + pragma Loop_Invariant (Pkg.Bar); --# loop_invariant_2 + end loop; +end Test_Main; + +--# test_main.adb +-- +-- /assert_stmt/ l. ## 0 +-- /inner_decision/ l. ## 0 +-- /inner_cond_1/ l. ## 0 +-- /inner_cond_2/ l. ## 0 +-- /loop_invariant_1/ l. ## 0 +-- /loop_invariant_2/ l. ## 0 diff --git a/testsuite/tests/instr-cov/pragma_assert/test.opt b/testsuite/tests/instr-cov/pragma_assert/test.opt new file mode 100644 index 000000000..a4e1eba80 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_assert/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/instr-cov/pragma_assert/test.py b/testsuite/tests/instr-cov/pragma_assert/test.py new file mode 100644 index 000000000..f702a743e --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_assert/test.py @@ -0,0 +1,13 @@ +""" +Check that the coverage of nested decisions in pragma Assert works as expected. +TODO: revisit this test once we decide on how to enable instrumentation of +assertions (U528-022) +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT +from SCOV.tc import TestCase + +TestCase(category=CAT.mcdc).run() + +thistest.result() diff --git a/testsuite/tests/instr-cov/pragma_no_body/main.adb b/testsuite/tests/instr-cov/pragma_no_body/main.adb new file mode 100644 index 000000000..f759cb8a0 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; +end Main; diff --git a/testsuite/tests/instr-cov/pragma_no_body/orig_pkg.adb b/testsuite/tests/instr-cov/pragma_no_body/orig_pkg.adb new file mode 100644 index 000000000..679ab442a --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/orig_pkg.adb @@ -0,0 +1,6 @@ +package body Orig_Pkg is + procedure Foo is + begin + null; + end Foo; +end Orig_Pkg; diff --git a/testsuite/tests/instr-cov/pragma_no_body/orig_pkg.ads b/testsuite/tests/instr-cov/pragma_no_body/orig_pkg.ads new file mode 100644 index 000000000..678e99088 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/orig_pkg.ads @@ -0,0 +1,3 @@ +package Orig_Pkg is + procedure Foo; +end Orig_Pkg; diff --git a/testsuite/tests/instr-cov/pragma_no_body/pkg.adb b/testsuite/tests/instr-cov/pragma_no_body/pkg.adb new file mode 100644 index 000000000..4eede424d --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/pkg.adb @@ -0,0 +1 @@ +pragma No_Body; diff --git a/testsuite/tests/instr-cov/pragma_no_body/pkg.ads b/testsuite/tests/instr-cov/pragma_no_body/pkg.ads new file mode 100644 index 000000000..81b994920 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/pkg.ads @@ -0,0 +1,3 @@ +with Orig_Pkg; + +package Pkg renames Orig_Pkg; diff --git a/testsuite/tests/instr-cov/pragma_no_body/test.opt b/testsuite/tests/instr-cov/pragma_no_body/test.opt new file mode 100644 index 000000000..258f07a37 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD 5.04a1 does not support pragma No_Body diff --git a/testsuite/tests/instr-cov/pragma_no_body/test.py b/testsuite/tests/instr-cov/pragma_no_body/test.py new file mode 100644 index 000000000..759c8a17b --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_body/test.py @@ -0,0 +1,26 @@ +""" +Check that units only containing "pragma No_Body;" are properly handled. They +used to make the instrumenter crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], +) +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'+': {5}}, + 'xcov/orig_pkg.adb.xcov': {'+': {4}}, +}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/protected_body/src/foo.adb b/testsuite/tests/instr-cov/protected_body/src/foo.adb new file mode 100644 index 000000000..a03047ad0 --- /dev/null +++ b/testsuite/tests/instr-cov/protected_body/src/foo.adb @@ -0,0 +1,20 @@ +pragma Ada_2012; + +package body Foo is + + protected body Obj_Type is + + procedure Set (X : Integer) is + begin + Val := X; + end Set; + + procedure Do_Nothing (X : Integer) is null; -- # null_proc + + function Get return Integer is (Val); -- # int_expr + + function Cond return Boolean is (Val > 0 or else Val = -5); -- # bool_expr + + end Obj_Type; + +end Foo; diff --git a/testsuite/tests/instr-cov/protected_body/src/foo.ads b/testsuite/tests/instr-cov/protected_body/src/foo.ads new file mode 100644 index 000000000..2afb6dcfa --- /dev/null +++ b/testsuite/tests/instr-cov/protected_body/src/foo.ads @@ -0,0 +1,20 @@ +pragma Ada_2012; + +package Foo is + + protected type Obj_Type is + procedure Set (X : Integer); + + procedure Do_Nothing (X : Integer); + + function Get return Integer; + + function Cond return Boolean; + + private + Val : Integer := 0; -- # decl + end Obj_Type; + + Obj : Obj_Type; + +end Foo; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/protected_body/src/test_foo.adb b/testsuite/tests/instr-cov/protected_body/src/test_foo.adb new file mode 100644 index 000000000..2bb48290f --- /dev/null +++ b/testsuite/tests/instr-cov/protected_body/src/test_foo.adb @@ -0,0 +1,36 @@ +pragma Ada_2012; + +with Support; use Support; + +with Foo; use Foo; + +procedure Test_Foo is +begin + Obj.Set (3); + Assert (Obj.Get = 3); + Assert (Obj.Cond); + Obj.Do_Nothing (0); + Obj.Set (-3); + Assert (not Obj.Cond); +end Test_Foo; + +--# foo.adb + +-- /null_proc/ l+ ## 0 +-- /int_expr/ l+ ## 0 +-- /bool_expr/ l! ## c!:"Val = -5" + +-- Declarations in protected type private parts only started getting +-- SCOS from the compiler after the 22 release branch, and the gnatcov +-- instrumenter was adjusted accordingly just before the branch. +-- +-- So, for binary traces only, we can't count on a SCO until GNAT Pro 23. +-- +-- We don't have a way to check for versions in a flexible manner and +-- this is very minor so just stick a weak expectation at this stage. + +--# foo.ads + +-- /decl/ ~l+ ## 0 + + diff --git a/testsuite/tests/instr-cov/protected_body/test.opt b/testsuite/tests/instr-cov/protected_body/test.opt new file mode 100644 index 000000000..f404c4646 --- /dev/null +++ b/testsuite/tests/instr-cov/protected_body/test.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD Protected objects not available in zfp runtimes \ No newline at end of file diff --git a/testsuite/tests/instr-cov/protected_body/test.py b/testsuite/tests/instr-cov/protected_body/test.py new file mode 100644 index 000000000..ed32e5903 --- /dev/null +++ b/testsuite/tests/instr-cov/protected_body/test.py @@ -0,0 +1,11 @@ +""" +Check that degenerate subprograms are correctly instrumented in protected +bodies +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/pure_units/main.adb b/testsuite/tests/instr-cov/pure_units/main.adb new file mode 100644 index 000000000..ff20c1dc0 --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/main.adb @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; use Pkg; +with Pkg.Child; use Pkg.Child; + +procedure Main is + Dummy : Boolean := Pkg.Opposite (True); +begin + Put_Line ("Fact (0) = " & Integer'Image (Pkg.Fact (0))); + Pkg.Do_Nothing_2; + Pkg.Child.Do_Nothing_3; +end Main; diff --git a/testsuite/tests/instr-cov/pure_units/p.gpr b/testsuite/tests/instr-cov/pure_units/p.gpr new file mode 100644 index 000000000..000deffc5 --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/p.gpr @@ -0,0 +1,8 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); + + package Coverage is + for Units use ("pkg", "pkg.child"); + end Coverage; +end P; diff --git a/testsuite/tests/instr-cov/pure_units/pkg-child.ads b/testsuite/tests/instr-cov/pure_units/pkg-child.ads new file mode 100644 index 000000000..d6d05df4e --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/pkg-child.ads @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package Pkg.Child is + + pragma Pure (Child); + + type Stuff_Child is null record; + + procedure Do_Nothing_3 is null; + procedure Do_Nothing_4 is null; + + function Identity_Child (B : Boolean) return Boolean is (B); + function Opposite_Child (B : Boolean) return Boolean is (not B); + +end Pkg.Child; diff --git a/testsuite/tests/instr-cov/pure_units/pkg.adb b/testsuite/tests/instr-cov/pure_units/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/pure_units/pkg.ads b/testsuite/tests/instr-cov/pure_units/pkg.ads new file mode 100644 index 000000000..97b754550 --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/pkg.ads @@ -0,0 +1,17 @@ +pragma Ada_2012; + +package Pkg is + + pragma Pure; + + function Fact (I : Integer) return Integer; + + type Stuff is null record; + + procedure Do_Nothing_1 is null; + procedure Do_Nothing_2 is null; + + function Identity (B : Boolean) return Boolean is (B); + function Opposite (B : Boolean) return Boolean is (not B); + +end Pkg; diff --git a/testsuite/tests/instr-cov/pure_units/test.opt b/testsuite/tests/instr-cov/pure_units/test.opt new file mode 100644 index 000000000..99be653e1 --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 +7.1.2 DEAD support for expression functions weak in 7.1.2 \ No newline at end of file diff --git a/testsuite/tests/instr-cov/pure_units/test.py b/testsuite/tests/instr-cov/pure_units/test.py new file mode 100644 index 000000000..852857eb3 --- /dev/null +++ b/testsuite/tests/instr-cov/pure_units/test.py @@ -0,0 +1,35 @@ +""" +Check that we can compute code coverage for Pure units. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') +check_xcov_reports( + '*.xcov', + {'pkg.ads.xcov': {'+': {12, 15}, '-': {11, 14}}, + 'pkg.adb.xcov': {'+': {5, 6}, '-': {8}}, + 'pkg-child.ads.xcov': {'+': {9}, '-': {10, 12, 13}}}, + "xcov" +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.adb b/testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.adb new file mode 100644 index 000000000..0e1a12f3b --- /dev/null +++ b/testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.adb @@ -0,0 +1,10 @@ +package body Mylib is + function Foo (B : Boolean) return Integer is + begin + if B then + return 1; + else + return 2; + end if; + end Foo; +end Mylib; diff --git a/testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.ads b/testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.ads new file mode 100644 index 000000000..e655a845e --- /dev/null +++ b/testsuite/tests/instr-cov/remove_extra_src/src-mylib/mylib.ads @@ -0,0 +1,3 @@ +package Mylib is + function Foo (B : Boolean) return Integer; +end Mylib; diff --git a/testsuite/tests/instr-cov/remove_extra_src/src-myprog/prog.adb b/testsuite/tests/instr-cov/remove_extra_src/src-myprog/prog.adb new file mode 100644 index 000000000..fdcbe8493 --- /dev/null +++ b/testsuite/tests/instr-cov/remove_extra_src/src-myprog/prog.adb @@ -0,0 +1,8 @@ +with Mylib; + +procedure Prog is +begin + if Mylib.Foo (True) = 3 then + raise Program_Error; + end if; +end Prog; diff --git a/testsuite/tests/instr-cov/remove_extra_src/test.py b/testsuite/tests/instr-cov/remove_extra_src/test.py new file mode 100644 index 000000000..2fa7ef7a9 --- /dev/null +++ b/testsuite/tests/instr-cov/remove_extra_src/test.py @@ -0,0 +1,69 @@ +""" +Test that "gnatcov instrument" removes "$project_name-gnatcov-instr" +directories for projects that are not of interest. + +Create a hierarchy of three projects: a library (mylib), a dummy project +(dummy) and a program using them (myprog). First instrument only the library +(to produce the "$project_name-gnatcov-instr" directory in the library's object +directory). Then, instrument only the program. + +The latter is supposed to remove the library's "$project_name-gnatcov-instr" +directory. If it does not, building the program will trigger link errors: +gprbuild will blindly use the library's instrumented units but the instrumented +main will not pull the buffer units. + +The dummy project has the same object directory as myprog. This used to make +gnatcov remove myprog's all instrumented source files, so the presence of dummy +in the tree of projects is here to check this does not happen anymore. +""" + +import os.path + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +Wdir('tmp_') + +# Create projects +mylib_gpr = gprfor(prjid='mylib', mains=[], langs=['Ada'], + srcdirs=['../src-mylib'], + objdir='obj-mylib') +dummy_gpr = gprfor(prjid='dummy', mains=[], langs=['C'], + srcdirs=['../src-myprog'], + objdir='obj-myprog') +myprog_gpr = gprfor(prjid='myprog', mains=['prog.adb'], + srcdirs=['../src-myprog'], + objdir='obj-myprog', + deps=['mylib', 'dummy']) + +# Instrument mylib.gpr +xcov_instrument( + gprsw=GPRswitches(root_project=mylib_gpr), + covlevel='stmt', + gpr_obj_dir='obj-mylib', + out='instr-mylib.log') + +# Create a non-empty directory in the mylib-gnatcov-instr folder, to check that +# the removal machinery handles it well (ignores it). +subdir = os.path.join('obj-mylib', 'mylib-gnatcov-instr', 'foo') +os.mkdir(subdir) +with open(os.path.join(subdir, 'foo.txt'), 'w') as f: + pass + +# Instrument, build, run and generate a coverage report for myprog.gpr (and not +# mylib.gpr). +build_run_and_coverage( + gprsw=GPRswitches(root_project=myprog_gpr, no_subprojects=True), + covlevel='stmt', + mains=['prog'], + gpr_obj_dir='obj-myprog', + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src') +check_xcov_reports('xcov/*.xcov', {'xcov/prog.adb.xcov': {'+': {5}, '-': {6}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/scalar_and/main.adb b/testsuite/tests/instr-cov/scalar_and/main.adb new file mode 100644 index 000000000..4ee776bfc --- /dev/null +++ b/testsuite/tests/instr-cov/scalar_and/main.adb @@ -0,0 +1,7 @@ +with Interfaces; use Interfaces; + +procedure Main is + U : Unsigned_32 := 1337; +begin + U := U and 255; +end Main; diff --git a/testsuite/tests/instr-cov/scalar_and/p.gpr b/testsuite/tests/instr-cov/scalar_and/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/scalar_and/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/scalar_and/test.py b/testsuite/tests/instr-cov/scalar_and/test.py new file mode 100644 index 000000000..12711f082 --- /dev/null +++ b/testsuite/tests/instr-cov/scalar_and/test.py @@ -0,0 +1,27 @@ +"""Check that we don't instrument "A and B" as a decision.""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p_gpr), + covlevel='stmt+decision', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') +check_xcov_reports('xcov/*.xcov', {'xcov/main.adb.xcov': {'+': {4, 6}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/gnat.adc b/testsuite/tests/instr-cov/short_circuit_and_or/gnat.adc new file mode 100644 index 000000000..1773c462c --- /dev/null +++ b/testsuite/tests/instr-cov/short_circuit_and_or/gnat.adc @@ -0,0 +1 @@ +pragma Short_Circuit_And_Or; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/main.adb b/testsuite/tests/instr-cov/short_circuit_and_or/main.adb new file mode 100644 index 000000000..2aa195da3 --- /dev/null +++ b/testsuite/tests/instr-cov/short_circuit_and_or/main.adb @@ -0,0 +1,136 @@ +-- TODO: Type_Pkg needed to avoid problems with type conversion in the main +-- when instrumenting for MC/DC (U706-036) + +with Type_Pkg; use Type_Pkg; + +procedure Main is + + procedure Regular_And_Or (L, R : Typ; Res_And, Res_Or : out Typ); + + procedure Regular_And_Or_Use_Pkg (L, R : Typ; Res_And, Res_Or: out Typ); + + procedure Overloaded_And_Or (L, R : Typ; Res_And, Res_Or : out Typ); + + procedure Derived_And_Or (L, R : Derived; Res_And, Res_Or : out Derived); + + package Pkg is + function "and" (Left, Right : Typ) return Typ; + function "or" (Left, Right : Typ) return Typ; + end Pkg; + + package body Pkg is + function "and" (Left, Right : Typ) return Typ is + begin + if Left then + return Right; + end if; + return False; + end "and"; + + function "or" (Left, Right : Typ) return Typ is + begin + if Left then + return True; + else + return Right; + end if; + end "or"; + end Pkg; + + procedure Regular_And_Or (L, R : Typ; Res_And, Res_Or : out Typ) is + begin + Res_And := L and R; -- Should be instrumented for MCDC + Res_Or := L or R; -- Same + end Regular_And_Or; + + procedure Regular_And_Or_Use_Pkg (L, R : Typ; Res_And, Res_Or: out Typ) is + use Pkg; + begin + -- Use clause visibility cannot hide declarations happening within the + -- Standard Ada package, so the following should resolve to the + -- Standard.Boolean operators, which need to be instrumented for MC/DC. + + Res_And := L and R; + Res_Or := L or R; + end Regular_And_Or_Use_Pkg; + + procedure Overloaded_And_Or (L, R : Typ; Res_And, Res_Or : out Typ) is + function "and" (Left, Right : Typ) return Typ is + begin + if Left then + return Right; + else + return False; + end if; + end "and"; + + function "or" (Left, Right : Typ) return Typ is + begin + if Left then + return True; + else + return Right; + end if; + end "or"; + + begin + -- Here there is no use clause visibility involved, so the operators + -- used are the ones defined above, and should not be instrumented for + -- MCDC. + + Res_And := L and R; + Res_Or := L or R; + end Overloaded_And_Or; + + procedure Derived_And_Or (L, R : Derived; Res_And, Res_Or : out Derived) is + begin + Res_And := L and R; + Res_Or := L or R; + end Derived_And_Or; + + True_Var : Boolean := True; + pragma Volatile (True_Var); + + False_Var : Boolean := False; + pragma Volatile (False_Var); + + True_Var_Der : Derived := True; + pragma Volatile (True_Var_Der); + + False_Var_Der : Derived := False; + pragma Volatile (False_Var_Der); + + Res_And, Res_Or : Typ; + pragma Volatile (Res_And); + pragma Volatile (Res_Or); + + Res_And_Der, Res_Or_Der : Derived; + pragma Volatile (Res_And_Der); + pragma Volatile (Res_Or_Der); + +begin + + Regular_And_Or (True_Var, True_Var, Res_And, Res_Or); + Regular_And_Or (False_Var, False_Var, Res_And, Res_Or); + + Regular_And_Or_Use_Pkg (True_Var, True_Var, Res_And, Res_Or); + Regular_And_Or_Use_Pkg (False_Var, False_Var, Res_And, Res_Or); + + Overloaded_And_Or (True_Var, True_Var, Res_And, Res_Or); + Overloaded_And_Or (False_Var, False_Var, Res_And, Res_Or); + + Derived_And_Or (True_Var_Der, True_Var_Der, Res_And_Der, Res_Or_Der); + Derived_And_Or (False_Var_Der, False_Var_Der, Res_And_Der, Res_Or_Der); + + -- These do not actively test anything, but are used to make sure the + -- procedures "and" and "or" in package Pkg are marked as covered, + -- so coverage violation only happen in lines where the operators are + -- called. + + Res_And := Pkg."and" (True_Var, True_Var); + Res_And := Pkg."and" (False_Var, False_Var); + + Res_Or := Pkg."or" (True_Var, True_Var); + Res_Or := Pkg."or" (False_Var, False_Var); + +end Main; diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/test.opt b/testsuite/tests/instr-cov/short_circuit_and_or/test.opt new file mode 100644 index 000000000..cb67a102b --- /dev/null +++ b/testsuite/tests/instr-cov/short_circuit_and_or/test.opt @@ -0,0 +1 @@ +src-traces XFAIL U705-016: overloading resolution bug in LAL \ No newline at end of file diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/test.py b/testsuite/tests/instr-cov/short_circuit_and_or/test.py new file mode 100644 index 000000000..539e7f0ab --- /dev/null +++ b/testsuite/tests/instr-cov/short_circuit_and_or/test.py @@ -0,0 +1,71 @@ +""" +Test that when --short-circuit-and-or is passed, or in the presence +of a Short_Circuit_And_Or configuration pragma, gnatcov considers the 'and' +and 'or' boolean operators as having short-circuit semantics, and instruments +their operands as conditions for MC/DC coverage. + +This test checks that the Standard.Boolean and/or operators are +considered to have short-circuit semantics (including for subtypes of +Standard.Boolean) but that the and/or operators for a type derived from +Standard.Boolean are not. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +def check_results(): + check_xcov_reports( + "main.adb.xcov", + {"main.adb.xcov": {"!": {42, 43, 53, 54}, "+": {81, 82, 87, 88}}}, + cwd="obj", + ) + + +tmp = Wdir() + +# First, verify that passing --short-circuit-and-or activates the +# instrumentation of non-short circuit boolean operators for MC/DC. +# This part of the test is deactivated for bin traces as the option +# only controls the instrumenter. +if thistest.options.trace_mode == "src": + tmp.to_subdir("tmp_switch") + prj = gprfor( + mains=["main.adb"], + srcdirs=[".."], + ) + + build_run_and_coverage( + gprsw=GPRswitches(prj), + covlevel="stmt+mcdc", + mains=["main"], + extra_instr_args=["--short-circuit-and-or"], + extra_coverage_args=["-axcov"], + ) + + check_results() + + +# Then, check that the presence of a "pragma Short_Circuit_And_Or" is +# correctly taken into account during instrumentation. +tmp.to_subdir("tmp_config") + +prj = gprfor( + mains=["main.adb"], + srcdirs=[".."], + compiler_extra='for Local_Configuration_Pragmas use "../gnat.adc";', +) + +build_run_and_coverage( + gprsw=GPRswitches(prj), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov"], +) + +check_results() + +thistest.result() diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/type_pkg.ads b/testsuite/tests/instr-cov/short_circuit_and_or/type_pkg.ads new file mode 100644 index 000000000..3557da2b6 --- /dev/null +++ b/testsuite/tests/instr-cov/short_circuit_and_or/type_pkg.ads @@ -0,0 +1,7 @@ +package Type_Pkg is + + subtype Typ is Boolean; + + type Derived is new Boolean; + +end Type_Pkg; \ No newline at end of file diff --git a/testsuite/tests/instr-cov/stmt_after_accept/main.adb b/testsuite/tests/instr-cov/stmt_after_accept/main.adb new file mode 100644 index 000000000..f92ba8aa0 --- /dev/null +++ b/testsuite/tests/instr-cov/stmt_after_accept/main.adb @@ -0,0 +1,33 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + + task type My_Task is + entry Pass_Boolean (B : Boolean); + entry Pass_Integer (I : Integer); + end My_Task; + + task body My_Task is + Stored_B : Boolean; + begin + select + accept Pass_Boolean (B : Boolean) do + Stored_B := B; + end Pass_Boolean; + + Put_Line ("Hello, world!"); + if Stored_B then + Put_Line ("B was True"); + end if; + or + accept Pass_Integer (I : Integer) do + pragma Unreferenced (I); + null; + end Pass_Integer; + end select; + end My_Task; + + T : My_Task; +begin + T.Pass_Boolean (False); +end Main; diff --git a/testsuite/tests/instr-cov/stmt_after_accept/test.opt b/testsuite/tests/instr-cov/stmt_after_accept/test.opt new file mode 100644 index 000000000..a34c07f1d --- /dev/null +++ b/testsuite/tests/instr-cov/stmt_after_accept/test.opt @@ -0,0 +1 @@ +!native DEAD Uses full runtime only constructs diff --git a/testsuite/tests/instr-cov/stmt_after_accept/test.py b/testsuite/tests/instr-cov/stmt_after_accept/test.py new file mode 100644 index 000000000..6ad2d2095 --- /dev/null +++ b/testsuite/tests/instr-cov/stmt_after_accept/test.py @@ -0,0 +1,26 @@ +""" +Regression test for the instrumenter. It used to crash when instrumenting +statements that appear after "accept" blocks. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports("xcov/*.xcov", { + "xcov/main.adb.xcov": {"+": {14, 15, 18, 19, 30, 32}, "-": {20, 23, 25}}, +}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/unknown_unit/main.adb b/testsuite/tests/instr-cov/unknown_unit/main.adb new file mode 100644 index 000000000..a2ed76204 --- /dev/null +++ b/testsuite/tests/instr-cov/unknown_unit/main.adb @@ -0,0 +1,7 @@ +with Pkg; use Pkg; + +procedure Main is + Dummy : Integer := Pkg.Fact (6); +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/unknown_unit/p.gpr b/testsuite/tests/instr-cov/unknown_unit/p.gpr new file mode 100644 index 000000000..c96f36767 --- /dev/null +++ b/testsuite/tests/instr-cov/unknown_unit/p.gpr @@ -0,0 +1,4 @@ +project P is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/instr-cov/unknown_unit/pkg.adb b/testsuite/tests/instr-cov/unknown_unit/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/unknown_unit/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/unknown_unit/pkg.ads b/testsuite/tests/instr-cov/unknown_unit/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/unknown_unit/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/unknown_unit/test.py b/testsuite/tests/instr-cov/unknown_unit/test.py new file mode 100644 index 000000000..bcd174a0f --- /dev/null +++ b/testsuite/tests/instr-cov/unknown_unit/test.py @@ -0,0 +1,54 @@ +""" +Check that "gnatcov coverage" properly report a source trace entry referencing +an unknown instrumented unit. +""" + +import os +import os.path + +from e3.fs import cp, mkdir + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, lines_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import xcov + + +p_gpr = os.path.abspath('p.gpr') +obj_dir = os.path.abspath('obj') +unrelated_sid = 'unrelated_instr.sid' + +tmp = Wdir('tmp_') + +# Instrument the main, only to get an SID file that is unrelated to the units +# we want to cover (pkg). +xcov_instrument( + gprsw=GPRswitches(root_project=p_gpr, units=['main']), + gpr_obj_dir='obj', + covlevel='stmt') +cp(os.path.join('..', 'obj', 'main.sid'), unrelated_sid) + +# Instrument/build/run the project only for the "pkg" unit +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=p_gpr, units=['pkg']), + covlevel='stmt', + mains=['main'], + extra_coverage_args=[], + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, + trace_mode='src') +trace_file = xcov_args[-1] + +# Try to produce a coverage report for it, but providing the wrong SID +mkdir('xcov') +p = xcov(['coverage', '-v', '-axcov', '--output-dir=xcov', + '--level', 'stmt', + '--sid', unrelated_sid, trace_file], + out='coverage.log') +thistest.fail_if( + 'discarding source trace entry for unknown instrumented unit: body of pkg' + not in lines_of('coverage.log')) + +thistest.result() diff --git a/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/src/andthen.adb b/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/src/andthen.adb new file mode 100644 index 000000000..20237f05c --- /dev/null +++ b/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/src/andthen.adb @@ -0,0 +1,22 @@ +package body Andthen is + + AA, BB : Boolean; + + function Expr + (Value : Boolean := AA and then BB) -- # andthen + return Boolean + is + begin + return Value; + end; + + function And_Then (A, B : Boolean) return Boolean is + begin + AA := A; -- # retVal + BB := B; -- # retVal + return Expr; -- # retVal + end; +end; + + + diff --git a/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.opt b/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.opt new file mode 100644 index 000000000..c7e7a8b8d --- /dev/null +++ b/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.opt @@ -0,0 +1 @@ +ALL DEAD diff --git a/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.py b/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/src/andthen.adb b/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/src/andthen.adb new file mode 100644 index 000000000..44c418345 --- /dev/null +++ b/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/src/andthen.adb @@ -0,0 +1,15 @@ +package body Andthen is + + type Expr (A, B : Boolean) is record + Value : Boolean := A and then B; -- # andthen + end record; + + function And_Then (A, B : Boolean) return Boolean is + E : Expr (A, B); + begin + return E.Value; -- # retVal + end; +end; + + + diff --git a/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.opt b/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.opt new file mode 100644 index 000000000..c7e7a8b8d --- /dev/null +++ b/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.opt @@ -0,0 +1 @@ +ALL DEAD diff --git a/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.py b/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.py new file mode 100644 index 000000000..1cad9a009 --- /dev/null +++ b/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/andthen.ads b/testsuite/tests/limits/Ada/decision/Andthen/src/andthen.ads new file mode 100644 index 000000000..087fa3b2c --- /dev/null +++ b/testsuite/tests/limits/Ada/decision/Andthen/src/andthen.ads @@ -0,0 +1,3 @@ +package Andthen is + function And_Then (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_0.adb b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_0.adb new file mode 100644 index 000000000..bf3770488 --- /dev/null +++ b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_0.adb @@ -0,0 +1,12 @@ +with Support, Andthen; use Support, Andthen; + +procedure Test_Andthen_0 is +begin + Assert (True); +end; + +--# andthen.adb +-- /andthen/ l- ## s- +-- /retTrue/ l- ## s- +-- /retFalse/ l- ## s- +-- /retVal/ l- ## s- diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_a.adb b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_a.adb new file mode 100644 index 000000000..0bb327f84 --- /dev/null +++ b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_a.adb @@ -0,0 +1,13 @@ +with Support, Andthen; use Support, Andthen; + +procedure Test_Andthen_A is +begin + Assert (And_Then (True, True) = True); + Assert (And_Then (False, True) = False); +end; + +--# andthen.adb +-- /andthen/ l+ ## 0 +-- /retTrue/ l+ ## 0 +-- /retFalse/ l+ ## 0 +-- /retVal/ l+ ## 0 diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_ab.adb b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_ab.adb new file mode 100644 index 000000000..ae1f17976 --- /dev/null +++ b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_ab.adb @@ -0,0 +1,14 @@ +with Support, Andthen ; use Support, Andthen; + +procedure Test_Andthen_AB is +begin + Assert (And_Then (True, True) = True); + Assert (And_Then (True, False) = False); + Assert (And_Then (False, True) = False); +end; + +--# andthen.adb +-- /andthen/ l+ ## 0 +-- /retTrue/ l+ ## 0 +-- /retFalse/ l+ ## 0 +-- /retVal/ l+ ## 0 diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_b.adb b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_b.adb new file mode 100644 index 000000000..90e057226 --- /dev/null +++ b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_b.adb @@ -0,0 +1,13 @@ +with Support, Andthen; use Support, Andthen; + +procedure Test_Andthen_B is +begin + Assert (And_Then (True, True) = True); + Assert (And_Then (True, False) = False); +end; + +--# andthen.adb +-- /andthen/ l+ ## 0 +-- /retTrue/ l+ ## 0 +-- /retFalse/ l+ ## 0 +-- /retVal/ l+ ## 0 diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_f.adb b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_f.adb new file mode 100644 index 000000000..e060ff611 --- /dev/null +++ b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_f.adb @@ -0,0 +1,14 @@ +with Support, Andthen; use Support, Andthen; + +procedure Test_Andthen_F is +begin + Assert (And_Then (False, True) = False); + Assert (And_Then (True, False) = False); +end; + +--# andthen.adb +-- /andthen/ l! ## dT- +-- /retTrue/ l- ## s- +-- /retFalse/ l+ ## 0 +-- /retVal/ l+ ## 0 + diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_t.adb b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_t.adb new file mode 100644 index 000000000..6c8fa7db4 --- /dev/null +++ b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_t.adb @@ -0,0 +1,12 @@ +with Support, Andthen; use Support, Andthen; + +procedure Test_Andthen_T is +begin + Assert (And_Then (True, True) = True); +end; + +--# andthen.adb +-- /andthen/ l! ## dF- +-- /retTrue/ l+ ## 0 +-- /retFalse/ l- ## s- +-- /retVal/ l+ ## 0 diff --git a/testsuite/tests/scos-overlap/test.c b/testsuite/tests/scos-overlap/test.c new file mode 100644 index 000000000..abd162711 --- /dev/null +++ b/testsuite/tests/scos-overlap/test.c @@ -0,0 +1,13 @@ +extern void foo (void (*f) (const char *str)); + +static void +callback (const char *str) +{ +} + +int +main (void) +{ + foo (callback); + return 0; +} diff --git a/testsuite/tests/scos-overlap/test.py b/testsuite/tests/scos-overlap/test.py new file mode 100644 index 000000000..b13730661 --- /dev/null +++ b/testsuite/tests/scos-overlap/test.py @@ -0,0 +1,103 @@ +""" +Check that gnatcov rejects invalid configurations for overlapping SCO +statements. +""" + +from dataclasses import dataclass + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import thistest, gprfor + + +@dataclass +class W: + """Helper to represent expected warnings.""" + + col: str + sco_num: str + col_range: str + + def __str__(self): + return ( + f"!!! foo.c:5:{self.col}:" + f" unexpected SCO overlapping with SCO {self.sco_num}:" + f" STATEMENT at foo.c:5:{self.col_range}," + " discarding overlapping SCO" + ) + + +def run_variant(label, col_ranges, expected_warnings): + """ + Generate C code that will generate SCOS for the column number ranges in + ``col_ranges``, instrument it and check that gnatcov emits the given + expected warnings. + """ + thistest.log(f"== {label} ==") + wd = Wdir("tmp_" + label) + + # Generate C code and instrument it + + with open("foo.c", "w") as f: + f.write("void\n") + f.write("foo (void (*f) (const char *str))\n") + f.write("{\n") + for start, end in col_ranges: + # Add an empty line after line directive to prevent the + # postprocessing step in gnatcov from merging the lines together + # (thus undoing the SCO nesting). + f.write("#line 4\n\n") + + # Make sure the range is wide enough for us to insert a statement + # (a call to the "f" function with a string literal argument). + range_length = end - start + 1 + arg_length = range_length - 6 + assert arg_length >= 0 + + f.write(" " * (start - 1)) + f.write('f("') + f.write("A" * arg_length) + f.write('");') + f.write("\n") + f.write("}\n") + + log = "instr.log" + mkdir("obj") + xcov_instrument( + gprsw=GPRswitches( + root_project=gprfor(mains=["test.c"], srcdirs=["..", "."]), + units=["foo.c"], + ), + covlevel="stmt", + out=log, + tolerate_messages="unexpected SCO overlap", + ) + + # Check that the instrumenter emits the expected warnings. For convenience + # and platform independence, harmonize line terminators in the output. + thistest.fail_if_not_equal( + '"gnatcov instrument" warnings', + "\n".join(str(w) for w in expected_warnings), + "\n".join(line.rstrip() for line in contents_of(log).splitlines()) + ) + + wd.to_homedir() + + +run_variant("no-overlap", [(1, 10), (11, 20)], []) +run_variant("simple-nesting", [(1, 20), (2, 19)], []) +run_variant("contiguous-nesting", [(1, 20), (2, 10), (11, 19)], []) +run_variant("reverse-contiguous-nesting", [(11, 19), (2, 10), (1, 20)], []) + +run_variant("nok-nesting-left", [(1, 20), (1, 19)], [W("1", "#1", "1-20")]) +run_variant("nok-nesting-right", [(1, 20), (2, 20)], [W("2", "#1", "1-20")]) +run_variant("overlap-left", [(1, 10), (5, 15)], [W("5", "#1", "1-10")]) +run_variant("overlap-right", [(5, 15), (1, 10)], [W("1", "#1", "5-15")]) +run_variant( + "nested-overlap", [(1, 20), (10, 19), (2, 10)], [W("2", "#2", "10-19")] +) + +thistest.result() diff --git a/testsuite/tests/shared-libs/ada-main/src-main/main.adb b/testsuite/tests/shared-libs/ada-main/src-main/main.adb new file mode 100644 index 000000000..42da3e81b --- /dev/null +++ b/testsuite/tests/shared-libs/ada-main/src-main/main.adb @@ -0,0 +1,7 @@ +with Mylib; + +procedure Main is + Dummy : constant Natural := Mylib.Fact (1); +begin + null; +end Main; diff --git a/testsuite/tests/shared-libs/ada-main/src-mylib/mylib.adb b/testsuite/tests/shared-libs/ada-main/src-mylib/mylib.adb new file mode 100644 index 000000000..8ffae146d --- /dev/null +++ b/testsuite/tests/shared-libs/ada-main/src-mylib/mylib.adb @@ -0,0 +1,12 @@ +package body Mylib is + + function Fact (N : Natural) return Natural is + begin + if N <= 1 then + return 1; + else + return N * Fact (N - 1); + end if; + end Fact; + +end Mylib; diff --git a/testsuite/tests/shared-libs/ada-main/src-mylib/mylib.ads b/testsuite/tests/shared-libs/ada-main/src-mylib/mylib.ads new file mode 100644 index 000000000..6d5364017 --- /dev/null +++ b/testsuite/tests/shared-libs/ada-main/src-mylib/mylib.ads @@ -0,0 +1,5 @@ +package Mylib is + + function Fact (N : Natural) return Natural; + +end Mylib; diff --git a/testsuite/tests/shared-libs/ada-main/test.py b/testsuite/tests/shared-libs/ada-main/test.py new file mode 100644 index 000000000..b61a030a2 --- /dev/null +++ b/testsuite/tests/shared-libs/ada-main/test.py @@ -0,0 +1,52 @@ +""" +Test that we can compute code coverage on Ada code located in a shared library. +Beyond the library, the program is composed of an Ada unit. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +wd = Wdir('tmp_') + + +# Create one project file to build the pure Ada library to test +mylib_gpr = gprfor( + mains=[], prjid='mylib', langs=['Ada'], + srcdirs='../src-mylib', objdir='obj-mylib', + extra='for Library_Name use "mylib";' + '\nfor Library_Kind use "relocatable";' + '\nfor Library_Dir use "lib-mylib";') + +# Create another project to build Ada program to test the library +main_gpr = gprfor( + mains=['main.adb'], prjid='main', langs=['Ada'], deps=['mylib'], + srcdirs='../src-main', objdir='obj-main') + +# Make sure that subprocesses can import the shared library for mylib. On Unix +# systems, there is nothing specific to do thanks to RPATH magic, but on +# Windows we need to add its directory to PATH. +lib_dir = os.path.abspath('lib-mylib') +os.environ['PATH'] = '{}{}{}'.format( + lib_dir, os.path.pathsep, os.environ['PATH']) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=main_gpr, + projects=['mylib']), + covlevel='stmt', + gpr_obj_dir='obj-main', + mains=['main'], + extra_coverage_args=['--annotate=xcov', '--output-dir=.'], + # There are several projects in the closure: main_gpr, mylib_gpr and + # gnatcov_rts_full. GPRbuild will complain if one library does not have the + # same kind as the others, so force relocatable. + extra_gprbuild_args=['-XLIBRARY_TYPE=relocatable']) + +check_xcov_reports('*.xcov', {'mylib.adb.xcov': {'+': {5, 6}, '-': {8}}}) + +thistest.result() diff --git a/testsuite/tests/shared-libs/c-main/src-main/main.c b/testsuite/tests/shared-libs/c-main/src-main/main.c new file mode 100644 index 000000000..ed6af4b93 --- /dev/null +++ b/testsuite/tests/shared-libs/c-main/src-main/main.c @@ -0,0 +1,14 @@ +extern void adainit (void); +extern int mylib__fact (int); + +int +main (int argc, const char **argv) +{ + /* Run elaboration for both the runtime and our Ada units. */ + adainit (); + + /* Run the code to cover. */ + mylib__fact (1); + + return 0; +} diff --git a/testsuite/tests/shared-libs/c-main/src-mylib/mylib.adb b/testsuite/tests/shared-libs/c-main/src-mylib/mylib.adb new file mode 100644 index 000000000..8ffae146d --- /dev/null +++ b/testsuite/tests/shared-libs/c-main/src-mylib/mylib.adb @@ -0,0 +1,12 @@ +package body Mylib is + + function Fact (N : Natural) return Natural is + begin + if N <= 1 then + return 1; + else + return N * Fact (N - 1); + end if; + end Fact; + +end Mylib; diff --git a/testsuite/tests/shared-libs/c-main/src-mylib/mylib.ads b/testsuite/tests/shared-libs/c-main/src-mylib/mylib.ads new file mode 100644 index 000000000..deb270a99 --- /dev/null +++ b/testsuite/tests/shared-libs/c-main/src-mylib/mylib.ads @@ -0,0 +1,6 @@ +package Mylib is + + function Fact (N : Natural) return Natural; + pragma Export (C, Fact, "mylib__fact"); + +end Mylib; diff --git a/testsuite/tests/shared-libs/c-main/test.py b/testsuite/tests/shared-libs/c-main/test.py new file mode 100644 index 000000000..c4adc3c5d --- /dev/null +++ b/testsuite/tests/shared-libs/c-main/test.py @@ -0,0 +1,52 @@ +""" +Test that we can compute code coverage on Ada code located in a shared library. +Beyond the library, the program is a mix of Ada and C, and the main is in C. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +wd = Wdir('tmp_') + + +# Create one project file to build the pure Ada library to test +mylib_gpr = gprfor( + mains=[], prjid='mylib', langs=['Ada'], + srcdirs='../src-mylib', objdir='obj-mylib', + extra='for Library_Name use "mylib";' + '\nfor Library_Kind use "relocatable";' + '\nfor Library_Dir use "lib-mylib";') + +# Create another project to build the mixed C/Ada program to test the library. +main_gpr = gprfor( + mains=['main.c'], prjid='main', langs=['Ada', 'C'], deps=['mylib'], + srcdirs='../src-main', objdir='obj-main', +) + +# Make sure that subprocesses can import the shared library for mylib. On Unix +# systems, there is nothing specific to do thanks to RPATH magic, but on +# Windows we need to add its directory to PATH. +lib_dir = os.path.abspath('lib-mylib') +os.environ['PATH'] = '{}{}{}'.format( + lib_dir, os.path.pathsep, os.environ['PATH']) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=main_gpr, + projects=['mylib']), + covlevel='stmt', + gpr_obj_dir='obj-main', + mains=['main'], + extra_coverage_args=['--annotate=xcov', '--output-dir=.'], + extra_gprbuild_args=['-XLIBRARY_TYPE=relocatable']) + +check_xcov_reports('*.xcov', { + 'mylib.adb.xcov': {'+': {5, 6}, '-': {8}}, + 'mylib.ads.xcov': {}}) + +thistest.result() diff --git a/testsuite/tests/shared-libs/extra.opt b/testsuite/tests/shared-libs/extra.opt new file mode 100644 index 000000000..cd0601689 --- /dev/null +++ b/testsuite/tests/shared-libs/extra.opt @@ -0,0 +1,2 @@ +!native DEAD Shared libraries exist only for native platforms +bin-traces XFAIL OA05-051: bin-traces and shared libs diff --git a/testsuite/tests/xml-check/src/andthen.adb b/testsuite/tests/xml-check/src/andthen.adb new file mode 100644 index 000000000..49cba2788 --- /dev/null +++ b/testsuite/tests/xml-check/src/andthen.adb @@ -0,0 +1,4 @@ +function Andthen (A, B : Boolean) return Boolean is +begin + return A and then B; +end; diff --git a/testsuite/tests/xml-check/src/test_andthen_t.adb b/testsuite/tests/xml-check/src/test_andthen_t.adb new file mode 100644 index 000000000..9c702799d --- /dev/null +++ b/testsuite/tests/xml-check/src/test_andthen_t.adb @@ -0,0 +1,7 @@ +with Support, Andthen; use Support; + +procedure Test_Andthen_T is +begin + Assert (Andthen (True, True) = True); +end; + diff --git a/testsuite/tests/xml-check/test.py b/testsuite/tests/xml-check/test.py new file mode 100644 index 000000000..f0b771686 --- /dev/null +++ b/testsuite/tests/xml-check/test.py @@ -0,0 +1,28 @@ +"""Sanity check our ability to produce XML reports.""" + +from xml.dom import minidom + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor + + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor("test_andthen_t.adb", + srcdirs='../src')), + covlevel='stmt+mcdc', + mains=['test_andthen_t'], + extra_coverage_args=['--annotate=xml', '--output-dir=.'], + scos=['obj/andthen']) + +xmldoc = minidom.parse('andthen.adb.xml') +print(xmldoc.toxml()) + +xmldoc = minidom.parse('index.xml') +print(xmldoc.toxml()) + +thistest.result() From 9bc07ee61ce5dadb28c38a826f20317f0057347d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 9 Jun 2023 13:26:40 +0000 Subject: [PATCH 0308/1483] SCOV.minicheck.build_and_run: add the "extra_gprbuild_largs" argument This argument allows `build_and_run` callers to easily add linker arguments to the test program build. It simply binds `SUITE.tutils.gprbuild`'s own `largs` argument. --- testsuite/SCOV/minicheck.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 2cdcbf350..7a325cf3e 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -30,11 +30,12 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, gpr_obj_dir=None, gpr_exe_dir=None, ignored_source_files=[], separate_coverage=None, extra_args=[], extra_run_args=None, extra_instr_args=None, extra_gprbuild_args=[], - extra_gprbuild_cargs=[], absolute_paths=False, - dump_trigger="auto", dump_channel="auto", - check_gprbuild_output=False, trace_mode=None, - runtime_project=None, gprsw_for_coverage=None, - scos_for_run=True, register_failure=True, program_env=None, + extra_gprbuild_cargs=[], extra_gprbuild_largs=[], + absolute_paths=False, dump_trigger="auto", + dump_channel="auto", check_gprbuild_output=False, + trace_mode=None, runtime_project=None, + gprsw_for_coverage=None, scos_for_run=True, + register_failure=True, program_env=None, tolerate_instrument_messages=None, exec_args=None, auto_languages=True): """ @@ -80,6 +81,8 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, gprbuild. :param list[str] extra_gprbuild_cargs: List of arguments to pass to gprbuild's -cargs section. + :param list[str] extra_gprbuild_largs: List of arguments to pass to + gprbuild's -largs section. :param bool absolute_paths: If true, use absolute paths in the result. :param None|str dump_trigger: See xcov_instrument. :param None|str dump_channel: See xcov_instrument. @@ -128,6 +131,7 @@ def gprbuild_wrapper(root_project): gprbuild(root_project, gargs=gprsw.build_switches + extra_gprbuild_args, extracargs=extra_gprbuild_cargs, + largs=extra_gprbuild_largs, trace_mode=trace_mode, runtime_project=runtime_project) From 678c995967eefaa3b12514ca164894c18aedc6a2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 13 Jun 2023 11:23:25 +0000 Subject: [PATCH 0309/1483] RB13-019-win-paths: adapt to work with cross targets --- testsuite/tests/RB13-019-win-paths/Makefile | 14 +-- .../RB13-019-win-paths/{ => libsrc}/driver.c | 8 +- .../RB13-019-win-paths/{ => libsrc}/wibble.c | 0 .../RB13-019-win-paths/{ => libsrc}/wibble.h | 0 testsuite/tests/RB13-019-win-paths/main.adb | 8 ++ testsuite/tests/RB13-019-win-paths/main.gpr | 33 +++++++ testsuite/tests/RB13-019-win-paths/test.opt | 4 +- testsuite/tests/RB13-019-win-paths/test.py | 85 ++++++++++++++----- testsuite/tests/RB13-019-win-paths/utils.adb | 15 ++++ testsuite/tests/RB13-019-win-paths/utils.ads | 6 ++ 10 files changed, 143 insertions(+), 30 deletions(-) rename testsuite/tests/RB13-019-win-paths/{ => libsrc}/driver.c (67%) rename testsuite/tests/RB13-019-win-paths/{ => libsrc}/wibble.c (100%) rename testsuite/tests/RB13-019-win-paths/{ => libsrc}/wibble.h (100%) create mode 100644 testsuite/tests/RB13-019-win-paths/main.adb create mode 100644 testsuite/tests/RB13-019-win-paths/main.gpr create mode 100644 testsuite/tests/RB13-019-win-paths/utils.adb create mode 100644 testsuite/tests/RB13-019-win-paths/utils.ads diff --git a/testsuite/tests/RB13-019-win-paths/Makefile b/testsuite/tests/RB13-019-win-paths/Makefile index 10e06edde..9f68ae1cd 100644 --- a/testsuite/tests/RB13-019-win-paths/Makefile +++ b/testsuite/tests/RB13-019-win-paths/Makefile @@ -1,12 +1,14 @@ CC=gcc +AR=ar CFLAGS=-fpreserve-control-flow -fdump-scos -g -save-temps LDFLAGS=$(CFLAGS) -no-pie -driver: driver.o wibble.o +all: libdriver.a -wibble.o: wibble.c wibble.h +libdriver.a: driver.o wibble.o + $(AR) cru libdriver.a driver.o wibble.o -driver.o: wibble.h driver.c - -clean: - rm -f *.o *.exe driver *.c.gli *.i *.s +wibble.o: libsrc/wibble.c libsrc/wibble.h + $(CC) -o $@ -c $< $(CFLAGS) +driver.o: libsrc/driver.c libsrc/wibble.h + $(CC) -o $@ -c $< $(CFLAGS) diff --git a/testsuite/tests/RB13-019-win-paths/driver.c b/testsuite/tests/RB13-019-win-paths/libsrc/driver.c similarity index 67% rename from testsuite/tests/RB13-019-win-paths/driver.c rename to testsuite/tests/RB13-019-win-paths/libsrc/driver.c index e9a0c646a..75cfdefd0 100644 --- a/testsuite/tests/RB13-019-win-paths/driver.c +++ b/testsuite/tests/RB13-019-win-paths/libsrc/driver.c @@ -3,21 +3,23 @@ #include #include +extern void utils_print (const char *msg); + int check (int condition) { if (condition) { - printf ("PASS\n"); + utils_print ("PASS\n"); } else { - printf ("FAIL\n"); + utils_print ("FAIL\n"); } } int -main (int argc, char **argv) +driver_main (void) { check (foo (3, 2) == 0); check (foo (3, 3) == 1); diff --git a/testsuite/tests/RB13-019-win-paths/wibble.c b/testsuite/tests/RB13-019-win-paths/libsrc/wibble.c similarity index 100% rename from testsuite/tests/RB13-019-win-paths/wibble.c rename to testsuite/tests/RB13-019-win-paths/libsrc/wibble.c diff --git a/testsuite/tests/RB13-019-win-paths/wibble.h b/testsuite/tests/RB13-019-win-paths/libsrc/wibble.h similarity index 100% rename from testsuite/tests/RB13-019-win-paths/wibble.h rename to testsuite/tests/RB13-019-win-paths/libsrc/wibble.h diff --git a/testsuite/tests/RB13-019-win-paths/main.adb b/testsuite/tests/RB13-019-win-paths/main.adb new file mode 100644 index 000000000..9b3a41998 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/main.adb @@ -0,0 +1,8 @@ +with Utils; + +procedure Main is + procedure Driver_Main; + pragma Import (C, Driver_Main, "driver_main"); +begin + Driver_Main; +end Main; diff --git a/testsuite/tests/RB13-019-win-paths/main.gpr b/testsuite/tests/RB13-019-win-paths/main.gpr new file mode 100644 index 000000000..7a8723365 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/main.gpr @@ -0,0 +1,33 @@ +-- Template GPR file for tests requiring executables to be built. + +-- This is read by the gprfor() helper routine, which substitutes +-- the python string template fields with proper values. + +with "/home/derodat/_git/gnatcoverage/testsuite/support/lch.gpr"; + +project main extends "/home/derodat/_git/gnatcoverage/testsuite/support/base.gpr" is + + + +for Source_Dirs use ("."); +for Exec_Dir use "."; +for Object_Dir use "./obj"; + +for Languages use ("Ada"); + +package Compiler is +for Switches("main.adb") use + Compiler'Default_Switches ("Ada") & (); + + +end Compiler; + +for Main use ("main.adb"); + +package Emulator is + for Board use "stm32f4"; +end Emulator; + + + +end main; diff --git a/testsuite/tests/RB13-019-win-paths/test.opt b/testsuite/tests/RB13-019-win-paths/test.opt index 321d779fb..1df01ed06 100644 --- a/testsuite/tests/RB13-019-win-paths/test.opt +++ b/testsuite/tests/RB13-019-win-paths/test.opt @@ -1,2 +1,2 @@ -!native DEAD -src-traces DEAD source instrumentation not available for C +arm-elf,stm32f4,bin-traces +ALL DEAD Test tailored for bin traces on arm-elf/stm32f4 diff --git a/testsuite/tests/RB13-019-win-paths/test.py b/testsuite/tests/RB13-019-win-paths/test.py index 4881b1302..ac16e2159 100644 --- a/testsuite/tests/RB13-019-win-paths/test.py +++ b/testsuite/tests/RB13-019-win-paths/test.py @@ -3,39 +3,86 @@ computes the expected code coverage when C files are compiled with a Makefile. This used not to work because in this build scenario on Windows, debug info -used to contain unexpected double slash as directory separators. +used contains unexpected double backslashes as directory separators. """ import os.path - import shutil -from e3.os.process import Run +from e3.fs import cp +from e3.os.process import PIPE, Run, STDOUT -from SCOV.minicheck import check_xcov_reports -from SUITE.cutils import FatalError -from SUITE.tutils import exepath_to, thistest, tracename_for, xcov, xrun +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.control import env +from SUITE.cutils import FatalError, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import ( + exepath_to, gprfor, thistest, tracename_for, xcov, xrun +) -if os.path.exists('coverage'): - shutil.rmtree('coverage') -p = Run(['make', 'clean']) +tmp = Wdir("tmp_") -main = exepath_to('driver') -main_trace = tracename_for('driver') -p = Run(['make']) -thistest.stop_if(p.status != 0, FatalError('call to "make" failed')) +# Copy the C project in this temporary directory to avoid clutter in the test +# sources. +for f in ["Makefile", "libsrc"]: + cp(os.path.join("..", f), f, recursive=True) -xcflags = ['-cstmt+mcdc', '--scos=wibble.c.gli', '--scos=driver.c.gli'] +# Build libdriver.a +p = Run( + [ + "make", + f"CC={env.target.triplet}-gcc", + f"AR={env.target.triplet}-ar", + "CFLAGS={}".format(" ".join([ + "-fpreserve-control-flow", + "-fdump-scos", + "-g", + "-save-temps", -xrun(xcflags + [main]) -xcov(['coverage'] + xcflags - + ['-axcov', '--output-dir=coverage', '-T', main_trace]) + # TODO??? This is necessary in order to have the C sources build + # with an arm-elf toolchain and a stm32f4 RTS, it is not clear if + # we could make this more generic. + "-mlittle-endian", + "-mfloat-abi=hard", + "-mcpu=cortex-m4", + "-mfpu=fpv4-sp-d16", + ])), + ], + output=PIPE, + error=STDOUT, +) +thistest.log("make output:\n" + p.out) +thistest.stop_if(p.status != 0, FatalError('call to "make" failed')) + +# Build the test program, run it and produce a coverage report +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + prjid="main", + srcdirs=[".."], + mains=["main.adb"], + langs=["Ada"], + ), + ), + covlevel="stmt+mcdc", + mains=["main"], + scos=["obj/main"], + extra_gprbuild_args=["-vh"], + extra_gprbuild_largs=[f"-L{os.getcwd()}", "-ldriver"], + extra_coverage_args=[ + "-axcov", + "--output-dir=coverage", + "--scos=wibble.c.gli", + "--scos=driver.c.gli", + ], +) check_xcov_reports( - os.path.join('coverage', 'wibble.c.xcov'), - {os.path.join('coverage', 'wibble.c.xcov'): {'+': {8, 12}, '!': {6}}} + "wibble.c.xcov", + {"wibble.c.xcov": {"+": {8, 12}, "!": {6}}}, + cwd="coverage" ) thistest.result() diff --git a/testsuite/tests/RB13-019-win-paths/utils.adb b/testsuite/tests/RB13-019-win-paths/utils.adb new file mode 100644 index 000000000..3ce4e6819 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/utils.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Utils is + + ----------- + -- Print -- + ----------- + + procedure Print (Msg : chars_ptr) is + Ada_Msg : constant String := Value (Msg); + begin + Put_Line (Ada_Msg); + end Print; + +end Utils; diff --git a/testsuite/tests/RB13-019-win-paths/utils.ads b/testsuite/tests/RB13-019-win-paths/utils.ads new file mode 100644 index 000000000..d28436231 --- /dev/null +++ b/testsuite/tests/RB13-019-win-paths/utils.ads @@ -0,0 +1,6 @@ +with Interfaces.C.Strings; use Interfaces.C.Strings; + +package Utils is + procedure Print (Msg : chars_ptr); + pragma Export (C, Print, "utils_print"); +end Utils; From 0e4bec69390d090c3bcf93b11992911c92bb979d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 12 May 2023 17:03:30 +0200 Subject: [PATCH 0310/1483] Add an API to make the dump config explicit --- tools/gnatcov/switches.adb | 41 ++++++++++++++++++++++++++++++++++++++ tools/gnatcov/switches.ads | 5 +++++ 2 files changed, 46 insertions(+) diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 6a81218ff..22498f738 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -186,6 +186,47 @@ package body Switches is end return; end Load_Dump_Config; + -------------------- + -- Unparse_Config -- + -------------------- + + function Unparse_Config + (Dump_Config : Any_Dump_Config) return String_Vectors.Vector + is + use Ada.Strings.Unbounded; + Result : String_Vectors.Vector; + begin + Result.Append (+"--dump-triger"); + case Dump_Config.Trigger is + when Manual => + Result.Append (+"manual"); + when At_Exit => + Result.Append (+"atexit"); + when Ravenscar_Task_Termination => + Result.Append (+"ravenscar-task-termination"); + when Main_End => + Result.Append (+"main-end"); + end case; + case Dump_Config.Channel is + when Binary_File => + Result.Append (+"--dump-channel=bin-file"); + if Dump_Config.Filename_Simple then + Result.Append (+"--dump-filename-simple"); + end if; + if Length (Dump_Config.Filename_Env_Var) /= 0 then + Result.Append + ("--dump-filename-env-var=" & Dump_Config.Filename_Env_Var); + end if; + if Length (Dump_Config.Filename_Prefix) /= 0 then + Result.Append + (+"--dump-filename-prefix=" & Dump_Config.Filename_Prefix); + end if; + when Base64_Standard_Output => + Result.Append (+"--dump-channel=base64-stdout"); + end case; + return Result; + end Unparse_Config; + ----------------- -- To_Language -- ----------------- diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 2c259b2af..4a425987a 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -273,6 +273,11 @@ package Switches is -- Create the Any_Dump_Config value corresponding to Default_Dump_Config -- and the given --dump-* arguments for source trace dumping. + function Unparse_Config + (Dump_Config : Any_Dump_Config) return String_Vectors.Vector; + -- Return a suitable set of gnatcov command line switches that represent + -- the given dump config. + function Common_Switches (Cmd : Command_Line.Command_Type) return String_Vectors.Vector; -- Return the unparsed command line arguments supported by the given From 0ce9a8d532768a4490830a542de66f5962e87da8 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 12 May 2023 17:08:21 +0200 Subject: [PATCH 0311/1483] Fix the subprocess asynchronous API It was not tested in gnatcov master (as it is only used by the parallelized version of the instrumentation for now), and it was not working properly. --- tools/gnatcov/subprocesses.adb | 38 ++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 33c2b5901..25edace20 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -361,21 +361,24 @@ package body Subprocesses is Output_File : Mapped_File; Region : Mapped_Region; Str : Str_Access; - Str_Last : Natural := Last (Region); + Str_Last : Natural; begin Output_File := Open_Read (+Self.Process_Infos (Id).Output_File); Region := Read (Output_File); Str := Data (Region); + Str_Last := Last (Region); -- The finalization of Ada.Text_IO always emits a newline after a -- call to Put. To avoid redundant line breaks in this situation, -- do not pass that newline to Put and call New_Line instead. - if Str_Last > 0 and then Str (Str_Last) = ASCII.LF then - Str_Last := Str_Last - 1; + if Str_Last > 0 then + if Str (Str_Last) = ASCII.LF then + Str_Last := Str_Last - 1; + end if; + Put (Str (1 .. Str_Last)); + New_Line; end if; - Put (Str (1 .. Str_Last)); - New_Line; Free (Region); Close (Output_File); @@ -430,22 +433,31 @@ package body Subprocesses is Pool.Process_Infos (Id).Output_File := +Output_File; Pool.Process_Infos (Id).Origin_Command_Name := +Origin_Command_Name; Pool.Process_Infos (Id).Command := +Command; + if Output_File = "" then + + -- Redirect the output to a temporary file to avoid mangling + -- on the standard output. The dump of the output is done in + -- Wait_And_Finalize, through a later call to Run_Command, or + -- through the finalization of the process pool. + + Pool.Process_Infos (Id).Output_File := + +(Pool.Output_Dir.Directory_Name / "job-" + & Strings.Img (Id) & ".txt"); + Pool.Process_Infos (Id).Output_To_Stdout := True; + else + Pool.Process_Infos (Id).Output_To_Stdout := False; + end if; Pool.Handles (Id) := Run_Command (Command, Arguments, Origin_Command_Name, Environment, + +Pool.Process_Infos (Id).Output_File, - -- Redirect the output to a temporary file to avoid mangling on the - -- standard output. The dump of the output is done in - -- Wait_And_Finalize, through a later call to Run_Command, or - -- through the finalization of the process pool. + -- TODO???: there will be mangling on the stderr if stdout was + -- redirected to an output file. - (if Output_File = "" - then Pool.Output_Dir.Directory_Name / "job-" - & Strings.Img (Id) & ".txt" - else Output_File), Err_To_Out => Output_File = "", Out_To_Null => Out_To_Null, In_To_Null => In_To_Null, From 5ff128d0aef77f2811188c587571f6794e6e1530 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 12 May 2023 17:12:11 +0200 Subject: [PATCH 0312/1483] Fix typo --- .../Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py | 4 ++-- testsuite/tests/excluded_unit_imported_prj/test.py | 2 +- tools/gnatcov/gnatcov_bits_specific.adb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py index 2ec633226..729910a2c 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py @@ -19,7 +19,7 @@ recurse=False, xreports=['boolops']) -# -Pgen --projects=boolops.gpr --projects=intops.gpr, not recusrive +# -Pgen --projects=boolops.gpr --projects=intops.gpr, not recursive # expect boolops & intops related reports check( @@ -28,7 +28,7 @@ recurse=False, xreports=['boolops', 'intops']) -# -Pgen --projects=boolops.gpr --projects=counters.gpr, not recusrive +# -Pgen --projects=boolops.gpr --projects=counters.gpr, not recursive # expect boolops & counters related reports check( diff --git a/testsuite/tests/excluded_unit_imported_prj/test.py b/testsuite/tests/excluded_unit_imported_prj/test.py index 0991ac8d6..126c5b972 100644 --- a/testsuite/tests/excluded_unit_imported_prj/test.py +++ b/testsuite/tests/excluded_unit_imported_prj/test.py @@ -13,7 +13,7 @@ prj1 = gprfor(mains=[], prjid='prj1', srcdirs=['../prj1'], objdir='obj-prj1') # Check that ignoring pkg.c in the main project yields a warning, as the pkg.c -# unit is in thr prj1 dependency and not in the root project. +# unit is in the prj1 dependency and not in the root project. extra_p = """ package Coverage is for Excluded_Units use ("pkg.c"); diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 2d85786dc..71920e33c 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1336,7 +1336,7 @@ begin Warn ("With source traces, entry barrier analysis (enabled" & " with --analyze-entry-barriers) is only supported when" & " when using a full runtime profile. In particular," - & " enabeling this option with a ravenscar profile will" + & " enabling this option with a ravenscar profile will" & " result in invalid code being emitted."); end if; From a6ad18b75781dc77b9815b2483735f6ca18b7f74 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 12 May 2023 17:19:43 +0200 Subject: [PATCH 0313/1483] Add information about gnatcov build configuration This is required to make sure we ignore source files of unsupported languages when instrumenting a project. The change of behavior regarding the instrumentation is introduced in a later patch. --- tools/gnatcov/instrument-ada_unit__stub.adb | 5 ++++- tools/gnatcov/instrument-ada_unit__stub.ads | 2 ++ tools/gnatcov/instrument-c__stub.adb | 6 +++++- tools/gnatcov/instrument-c__stub.ads | 2 ++ tools/gnatcov/switches.ads | 5 +++++ 5 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit__stub.adb b/tools/gnatcov/instrument-ada_unit__stub.adb index c4fd7d0ac..523d98f83 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.adb +++ b/tools/gnatcov/instrument-ada_unit__stub.adb @@ -16,4 +16,7 @@ -- of the license. -- ------------------------------------------------------------------------------ -pragma No_Body; +package body Instrument.Ada_Unit is +begin + Builtin_Support (Ada_Language) := False; +end Instrument.Ada_Unit; diff --git a/tools/gnatcov/instrument-ada_unit__stub.ads b/tools/gnatcov/instrument-ada_unit__stub.ads index 1caac4fe2..624b98d26 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.ads +++ b/tools/gnatcov/instrument-ada_unit__stub.ads @@ -24,6 +24,8 @@ with Instrument.Common; use Instrument.Common; package Instrument.Ada_Unit is + pragma Elaborate_Body; + type Ada_Instrumenter_Type is new Language_Instrumenter with null record; -- Common instrumentation primitives for Ada diff --git a/tools/gnatcov/instrument-c__stub.adb b/tools/gnatcov/instrument-c__stub.adb index 98400eb4d..1b0c5d7f1 100644 --- a/tools/gnatcov/instrument-c__stub.adb +++ b/tools/gnatcov/instrument-c__stub.adb @@ -16,4 +16,8 @@ -- of the license. -- ------------------------------------------------------------------------------ -pragma No_Body; +package body Instrument.C is +begin + Builtin_Support (C_Language) := False; + Builtin_Support (CPP_Language) := False; +end Instrument.C; diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index 3d30db5f9..2a575f3ed 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -23,6 +23,8 @@ with Instrument.Common; use Instrument.Common; package Instrument.C is + pragma Elaborate_Body; + type C_Family_Instrumenter_Type is abstract new Language_Instrumenter with null record; -- Common instrumentation primitives for C/C++ diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 4a425987a..0cb91236a 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -158,6 +158,11 @@ package Switches is -- List of languages for which source files should be instrumented. -- Initialized during command line arguments parsing. + Builtin_Support : array (Src_Supported_Language) of Boolean := + (others => True); + -- Whether gnatcov supports the given language. Used when building gnatcov + -- without C instrumentation support. + ------------------------ -- Target information -- ------------------------ From 234cc94e12c6072f27208afdaf94c6fd1a7cbbe7 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 17 May 2023 12:10:37 +0200 Subject: [PATCH 0314/1483] Identify units of file-based language by their fullname We used to rely on the base name + project name, but incoming changes wrt. Parallelized instrumentation will make it harder to identify the project name. When instrumenting a single unit, we won't have any more project information as we only load the project once: when instrumenting the whole project tree, which then delegates the instrumentation of units to subprocesses not loading the project again. We could theoretically pass all this information on the command-line, but it is not convenient and it goes against the end goal of integrated instrumentation, aiming at supporting other build systems than gprbuild. Also use this as an opportunity to tackle our handling of subunits. Add them explicitly in the unit map. --- tools/gnatcov/coverage-source.adb | 80 +------- tools/gnatcov/files_table.ads | 20 +- tools/gnatcov/instrument-c.adb | 18 +- tools/gnatcov/instrument-input_traces.adb | 2 +- tools/gnatcov/instrument.adb | 112 ++++++------ tools/gnatcov/instrument.ads | 13 +- tools/gnatcov/project.adb | 211 ++++++++++------------ tools/gnatcov/project.ads | 14 +- tools/gnatcov/strings.adb | 41 +++-- tools/gnatcov/strings.ads | 12 +- 10 files changed, 207 insertions(+), 316 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 58527f599..5e45fff78 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -21,7 +21,6 @@ with Ada.Containers.Vectors; with Ada.Containers.Ordered_Sets; with Ada.Containers.Ordered_Maps; with Ada.Streams; use Ada.Streams; -with Ada.Strings.Fixed; with Ada.Strings.Unbounded; with Ada.Tags; with Ada.Unchecked_Deallocation; @@ -226,22 +225,6 @@ package body Coverage.Source is Ignored_SF_Map : Unit_To_Ignored_Maps.Map; - function Unit_Name_For_Subunit (Qualified_Name : String) return String; - -- Return the unit name for the subunit whose name is Qualified_Name. - -- For instance, if foo-test.adb is a subunit for package Foo, - -- GNATCOLL.Projects should give us Foo.Test as a unit name, and this - -- function will return Foo. - -- - -- As a safeguard, this checks that the result is the name of a unit of - -- interest: subunits cannot be units of interest. - -- - -- If it can't be determined that the source file belongs to a unit of - -- interest, the empty string will be returned, and a warning will be - -- emitted. - -- - -- Note that the Ada language rules guarantee that the name of the owning - -- unit is a prefix of the name of its subunits. - -------------------------- -- Basic_Block_Has_Code -- -------------------------- @@ -290,47 +273,6 @@ package body Coverage.Source is end if; end Add_Unit; - --------------------------- - -- Unit_Name_For_Subunit -- - --------------------------- - - function Unit_Name_For_Subunit (Qualified_Name : String) return String - is - use Ada.Strings.Fixed; - First : constant Natural := Qualified_Name'First; - Sep : Natural := Qualified_Name'Last; - begin - loop - Sep := Index (Source => Qualified_Name, - Pattern => ".", - From => Sep, - Going => Ada.Strings.Backward); - - if Unit_List.Contains - (Project_Unit' - (Language => Unit_Based_Language, - Unit_Name => - US.To_Unbounded_String - (Qualified_Name (First .. Sep - 1)))) - then - return Qualified_Name (First .. Sep - 1); - end if; - exit when Sep = 0; - - -- Move past '.' character to start searching again - - Sep := Sep - 1; - end loop; - - -- If we got here, then there is no unit of interest whose name is a - -- prefix of the name of the subunit we are processing. - - Report (Msg => "Could not find the name of the owning unit of subunit " - & Qualified_Name & " among the units of interest", - Kind => Warning); - return ""; - end Unit_Name_For_Subunit; - ------------------------------------------- -- Compute_Unit_Name_For_Ignored_Sources -- ------------------------------------------- @@ -353,6 +295,7 @@ package body Coverage.Source is (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); @@ -362,26 +305,7 @@ package body Coverage.Source is begin if FI /= null and then not FI.Unit.Known then declare - use type GNATCOLL.Projects.Unit_Parts; - - Language : constant Some_Language := - To_Language (File.Language); - - -- For Ada, get the unit name for the compilation unit (no - -- subunit names). For file-based languages, - -- GNATCOLL.Projects.Unit_Name returns an empty string: we need - -- to get the file base name instead. - - Unit_Name : constant String := - (case Language is - when Ada_Language => - (if File.Unit_Part = GNATCOLL.Projects.Unit_Separate - then Unit_Name_For_Subunit (File.Unit_Name) - else File.Unit_Name), - when others => Get_Simple_Name (SFI)); - - Unit : constant Project_Unit := - To_Project_Unit (Unit_Name, Project, Language); + Unit : constant Project_Unit := To_Project_Unit (File); begin Consolidate_Source_File_Unit (SFI, Unit); end; diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 729aea7ee..77855f1e8 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -308,18 +308,10 @@ package Files_Table is type Project_Unit (Language : Any_Language_Kind := Unit_Based_Language) is record Unit_Name : Ada.Strings.Unbounded.Unbounded_String; - - case Language is - when File_Based_Language => - Project_Name : Ada.Strings.Unbounded.Unbounded_String; - when others => - null; - end case; end record; - -- To uniquely identify a unit in a project tree, we need its unit name (or - -- base name for a C unit). For file-based languages such as C or C++, we - -- might have homonym base file names in different projects so we keep - -- track of the project name in addition. + -- To uniquely identify a unit in a project tree, we need its unit name. + -- It is the unit name for unit-based language, and the file fullname for + -- file-based languages. use type Ada.Strings.Unbounded.Unbounded_String; @@ -328,10 +320,8 @@ package Files_Table is when Unit_Based_Language => To_Lower (Ada.Strings.Unbounded.To_String (U.Unit_Name)), when File_Based_Language => - Ada.Strings.Unbounded.To_String (U.Project_Name) - & ":" - & Fold_Filename_Casing - (Ada.Strings.Unbounded.To_String (U.Unit_Name))); + Fold_Filename_Casing + (Ada.Strings.Unbounded.To_String (U.Unit_Name))); function "<" (L, R : Project_Unit) return Boolean is (Image (L) < Image (R)); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 410348c38..82b3d27b7 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3113,7 +3113,7 @@ package body Instrument.C is UIC.Instrumented_Unit := CU_Name; UIC.Buffer_Unit := - CU_Name_For_File (+Buffer_Filename, CU_Name.Project_Name); + CU_Name_For_File (+Buffer_Filename); -- Import analysis options for the file to preprocess, then run the -- preprocessor. @@ -3655,8 +3655,7 @@ package body Instrument.C is & " .unit_name = " & Format_Str_Constant (+CU_Name.Filename) & "," & ASCII.LF - & " .project_name = " - & Format_Str_Constant (+CU_Name.Project_Name) & "," + & " .project_name = """"," & ASCII.LF & " .bit_maps_fingerprint = " @@ -3894,8 +3893,7 @@ package body Instrument.C is Rew : C_Source_Rewriter; Main : constant Compilation_Unit_Name := (Language_Kind => File_Based_Language, - Filename => +Ada.Directories.Simple_Name (Filename), - Project_Name => +Info.Project.Name); + Filename => +Ada.Directories.Full_Name (Filename)); Insert_Extern_Location : Source_Location_T; -- Where to insert extern declarations @@ -3909,8 +3907,9 @@ package body Instrument.C is Start_Sloc (Get_Translation_Unit_Cursor (Rew.TU)); Main_Cursor := Get_Main (Rew.TU); if Main_Cursor = Get_Null_Cursor then - Outputs.Fatal_Error ("Could not find main function in " - & (+Main.Filename)); + Outputs.Fatal_Error + ("Could not find main function in " + & (Ada.Directories.Simple_Name (+Main.Filename))); end if; Emit_Dump_Helper_Unit @@ -4683,10 +4682,7 @@ package body Instrument.C is (Of_Interest => True, SFI => Get_Index_From_Generic_Name (+File, Source_File), - CU_Name => - CU_Name_For_File - (Filename => +Simple_Name (+File), - Project_Name => UIC.Instrumented_Unit.Project_Name)); + CU_Name => CU_Name_For_File (File)); else SOI := (Of_Interest => False); end if; diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 397c4fa76..35367363d 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -767,7 +767,7 @@ package body Instrument.Input_Traces is (Unit => To_Qualified_Name (Unit_Name), Part => Unit_Part_Map (Entry_Header.Unit_Part)); when GNATcov_RTS.Buffers.File_Based_Language => - CU_Name := CU_Name_For_File (+Unit_Name, +Project_Name); + CU_Name := CU_Name_For_File (+Unit_Name); end case; On_Trace_Entry diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 0ef2f2eec..99677aa31 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -26,6 +26,7 @@ with Ada.Exceptions; with Ada.Strings.Fixed; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; +with Ada.Strings.Hash; with Ada.Strings.Unbounded.Equal_Case_Insensitive; with Ada.Strings.Unbounded.Less_Case_Insensitive; with Ada.Unchecked_Deallocation; @@ -116,14 +117,7 @@ package body Instrument is return Left.Part < Right.Part; end if; when File_Based_Language => - if Equal_Case_Insensitive - (Left.Project_Name, Right.Project_Name) - then - return Left.Filename < Right.Filename; - else - return Less_Case_Insensitive - (Left.Project_Name, Right.Project_Name); - end if; + return Left.Filename < Right.Filename; end case; else return Left.Language_Kind < Right.Language_Kind; @@ -142,10 +136,10 @@ package body Instrument is case Left.Language_Kind is when Unit_Based_Language => if Left.Part = Right.Part - and then Left.Unit.Length = Right.Unit.Length + and then Length (Left.Unit) = Length (Right.Unit) then - for I in 1 .. Integer (Left.Unit.Length) loop - if not Equal_Case_Insensitive + for I in 1 .. Integer (Length (Left.Unit)) loop + if not Ada.Strings.Unbounded.Equal_Case_Insensitive (Unbounded_String (Left.Unit.Element (I)), Unbounded_String (Right.Unit.Element (I))) then @@ -159,15 +153,12 @@ package body Instrument is end if; return False; when File_Based_Language => - return Left.Filename = Right.Filename - and then Equal_Case_Insensitive - (Left.Project_Name, Right.Project_Name); + return Left.Filename = Right.Filename; end case; else return False; end if; end "="; - ------------------------- -- Qualified_Name_Slug -- ------------------------- @@ -227,46 +218,55 @@ package body Instrument is end; when File_Based_Language => - declare - Result : Ada_Identifier; - begin - -- For a compilation unit in a file-based language, relying on - -- the filename only is not enough, as there can be multiple - -- sources with the same name belonging to different projects - -- in a project tree. To avoid name clashes, prepend the name - -- of the owning project to the computed slug. - - Append - (Result, - Qualified_Name_Slug - (To_Qualified_Name (+Instrumented_Unit.Project_Name))); - - -- Add an unambiguous separator between the project name and - -- the rest of the slug. - - Append (Result, "_z_z"); - - -- File names can contain characters that cannot appear in - -- identifiers. Furthermore, unlike for the identifier to - -- return, file names may be case sensitive. In order to - -- produce valid identifiers, encode everything that isn't a - -- lower case letter or a digit. - - for C of "+" (Instrumented_Unit.Filename) loop - if C in 'a' .. 'z' | '0' .. '9' then - Append (Result, C); - else - Append - (Result, - "_" & Hex_Image (Unsigned_8'(Character'Pos (C)))); - end if; - end loop; - - return To_String (Result); - end; + return Filename_Slug (+Instrumented_Unit.Filename); end case; end Instrumented_Unit_Slug; + ------------------- + -- Filename_Slug -- + ------------------- + + function Filename_Slug (Fullname : String) return String is + use Ada.Directories; + Result : Ada_Identifier; + begin + -- We use the basename slug, followed by a hash of the fullname, which + -- makes us confident that homonym files will be correctly handled. + + -- File names can contain characters that cannot appear in + -- identifiers. Furthermore, unlike for the identifier to + -- return, file names may be case sensitive. In order to + -- produce valid identifiers, encode everything that isn't a + -- lower case letter or a digit. + + -- To avoid a leading underscore, add a prefix + + Append (Result, "z"); + + for C of Simple_Name (Fullname) loop + if C in 'a' .. 'z' | '0' .. '9' then + Append (Result, C); + else + Append + (Result, + "_" & Hex_Image + (Interfaces.Unsigned_8'(Character'Pos (C)))); + end if; + end loop; + + -- Then, suffix with the hash + + declare + Hash_Str : constant String := + Ada.Containers.Hash_Type'Image (Ada.Strings.Hash (Fullname)); + begin + -- Do not forget to remove the leading whitespace... + + Append (Result, Hash_Str (2 .. Hash_Str'Last)); + end; + return To_String (Result); + end Filename_Slug; + ----------- -- Image -- ----------- @@ -353,11 +353,10 @@ package body Instrument is ----------------------------- function CU_Name_For_File - (Filename : Unbounded_String; - Project_Name : Unbounded_String) return Compilation_Unit_Name + (Filename : US.Unbounded_String) return Compilation_Unit_Name is begin - return (File_Based_Language, Filename, Project_Name); + return (File_Based_Language, Filename); end CU_Name_For_File; ------------------------------ @@ -375,8 +374,7 @@ package body Instrument is Part => Source_File.Unit_Part); when File_Based_Language => return CU_Name_For_File - (Filename => +GNATCOLL.VFS."+" (Source_File.File.Base_Name), - Project_Name => +Source_File.Project.Name); + (Filename => +(+Source_File.File.Full_Name)); end case; end To_Compilation_Unit_Name; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 8596dfb96..47a8d8b22 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -75,10 +75,6 @@ package Instrument is -- Fallback for file-based languages (like C). We will use the -- simple filename for now. - Project_Name : US.Unbounded_String; - -- We also need the project name as different projects can have - -- the same file. - end case; end record; -- Unique identifier for an instrumented unit @@ -109,6 +105,12 @@ package Instrument is -- -- One can use this slug to generate unique names for this unit. + function Filename_Slug (Fullname : String) return String; + -- Given a filename to instrument, return a unique identifier to describe + -- it (the so called slug). + -- + -- One can use this slug to generate unique names for this unit. + function To_Qualified_Name (Name : String) return Ada_Qualified_Name; -- Convert a String qualified name into our format @@ -130,8 +132,7 @@ package Instrument is -- corresponding to the unit name and the unit part parameters. function CU_Name_For_File - (Filename : US.Unbounded_String; - Project_Name : US.Unbounded_String) return Compilation_Unit_Name; + (Filename : US.Unbounded_String) return Compilation_Unit_Name; -- Return the compilation unit name for the C translation unit -- corresponding to the filename parameter. diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 39e6d4fb1..9168877fc 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -16,14 +16,11 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Containers.Hashed_Maps; with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Containers.Indefinite_Ordered_Sets; -with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; with Ada.Directories; use Ada.Directories; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; -with Ada.Strings.Unbounded.Hash; with Ada.Tags; with Ada.Text_IO; use Ada.Text_IO; @@ -242,17 +239,17 @@ package body Project is -- To_Project_Unit -- --------------------- - function To_Project_Unit - (Unit_Name : String; - Project : Project_Type; - Language : Some_Language) return Files_Table.Project_Unit + function To_Project_Unit (Info : File_Info) return Files_Table.Project_Unit is - U : Project_Unit (Language_Kind (Language)); + Language : constant Some_Language := To_Language (Info.Language); + U : Project_Unit (Language_Kind (Language)); begin - U.Unit_Name := +Unit_Name; - if U.Language = File_Based_Language then - U.Project_Name := +Project.Name; - end if; + case U.Language is + when File_Based_Language => + U.Unit_Name := +(+Info.File.Full_Name); + when Unit_Based_Language => + U.Unit_Name := +Info.Unit_Name; + end case; return U; end To_Project_Unit; @@ -294,8 +291,7 @@ package body Project is Orig_Name : constant Unbounded_String := +Fold_Filename_Casing (Original_Name); - Unit_Name : constant Project_Unit := - To_Project_Unit (Original_Name, Info.Project, Language); + Unit_Name : constant Project_Unit := To_Project_Unit (Info); Ignored_Inserted : Boolean; begin @@ -485,31 +481,17 @@ package body Project is -- Is_Unit_Of_Interest -- ------------------------- - function Is_Unit_Of_Interest - (Project : Project_Type; - Unit_Name : String; - Language : Some_Language) return Boolean - is - U : constant Project_Unit := - To_Project_Unit (Unit_Name, Project, Language); - begin - return Unit_Map.Contains (U); - end Is_Unit_Of_Interest; - - ------------------------- - -- Is_Unit_Of_Interest -- - ------------------------- - function Is_Unit_Of_Interest (Full_Name : String) return Boolean is FI : constant File_Info := Prj_Tree.Info (Create (+Full_Name)); + LK : constant Any_Language_Kind := + Language_Kind (To_Language (FI.Language)); Unit_Name : constant String := - (case Language_Kind (To_Language (FI.Language)) is + (case LK is when Unit_Based_Language => FI.Unit_Name, - when File_Based_Language => +FI.File.Base_Name); + when File_Based_Language => Full_Name); begin - return Is_Unit_Of_Interest - (FI.Project, Unit_Name, To_Language (FI.Language)); + return Unit_Map.Contains (Project_Unit'(LK, +Unit_Name)); end Is_Unit_Of_Interest; ------------------------- @@ -539,23 +521,8 @@ package body Project is declare use Unit_Maps; - LI_Source_Unit : constant String := LI.Source.Unit_Name; - LI_Source_File : constant String := +LI.Source.File.Base_Name; - - U : constant String := - (if LI_Source_Unit'Length > 0 - then LI_Source_Unit - else LI_Source_File); - -- For unit-based languages (Ada), retrieve unit name from - -- SCOs file. For file-based languages (C), fall back to - -- translation unit source file name instead. - Cur : constant Cursor := - Unit_Map.Find - (To_Project_Unit - (U, - Project_Type (LI.LI_Project.all), - To_Language (LI.Source.Language))); + Unit_Map.Find (To_Project_Unit (LI.Source.all)); begin if Has_Element (Cur) then Callback.all (+LI.Library_File.Full_Name); @@ -599,17 +566,30 @@ package body Project is -- Process_Source_File -- ------------------------- - procedure Process_Source_File (Info : File_Info; Unit_Name : String) is + procedure Process_Source_File (Info : File_Info; Unit_Name : String) + is + pragma Unreferenced (Unit_Name); + Info_Lang : constant Some_Language := To_Language (Info.Language); begin - if (Language = All_Languages - or else - Language = To_Language (Info.Language)) - and then - (Include_Stubs - or else Is_Unit_Of_Interest - (Info.Project, Unit_Name, To_Language (Info.Language))) - then - Callback (Info.Project, Info); + if Language = All_Languages or else Language = Info_Lang then + + -- If this is a header, consider it a unit of interest. For now, + -- they can only be ignored through the --ignore-source-files + -- switch. + + if (Language_Kind (Info_Lang) = File_Based_Language + and then Info.Unit_Part = Unit_Spec) + + -- Otherwise, check if the unit is in the units of interest + -- map + + or else + (Unit_Map.Contains (To_Project_Unit (Info)) + and then (Info.Unit_Part /= Unit_Separate + or else Include_Stubs)) + then + Callback (Info.Project, Info); + end if; end if; end Process_Source_File; @@ -994,20 +974,25 @@ package body Project is procedure Process_Source_File (Info : File_Info; Unit_Name : String) is - Cur : Unit_Maps.Cursor; + Cur : Unit_Maps.Cursor; + Actual_Unit_Name : constant String := + (if Info.Unit_Part = Unit_Separate + then Prj_Tree.Info + (Prj_Tree.Other_File (Info.File)).Unit_Name + else Unit_Name); begin -- Never try to perform coverage on our coverage runtime -- library (in one of the gnatcov_rts*.gpr projects) or on -- our coverage buffer units (in user projects). - if Strings.Has_Prefix (Unit_Name, "gnatcov_rts.") then + if Strings.Has_Prefix (Actual_Unit_Name, "gnatcov_rts.") then return; end if; if not Units_Specified or else (Has_Matcher and then GNAT.Regexp.Match - (To_Lower (Unit_Name), + (To_Lower (Actual_Unit_Name), Units_Specified_Matcher)) then Add_Unit @@ -1089,7 +1074,8 @@ package body Project is Units_Present : String_Vectors.Vector; -- All units that were included - Patterns_Not_Covered : String_Vectors.Vector; + Patterns_Not_Covered : String_Sets.Set := + To_String_Set (Unit_Patterns); -- Patterns that do not match any of the present units procedure Add_To_Unit_Presents (C : Unit_Maps.Cursor); @@ -1098,9 +1084,16 @@ package body Project is -- Add_To_Unit_Presents -- -------------------------- - procedure Add_To_Unit_Presents (C : Unit_Maps.Cursor) is + procedure Add_To_Unit_Presents (C : Unit_Maps.Cursor) + is + P_Unit : constant Project_Unit := Unit_Maps.Key (C); + Unit_Name : constant Unbounded_String := + (case P_Unit.Language is + when File_Based_Language => + +Ada.Directories.Simple_Name (+P_Unit.Unit_Name), + when Unit_Based_Language => P_Unit.Unit_Name); begin - Units_Present.Append (Unit_Maps.Key (C).Unit_Name); + Units_Present.Append (Unit_Name); end Add_To_Unit_Presents; begin @@ -1211,39 +1204,16 @@ package body Project is Units : out Unit_Maps.Map; Defined : out Boolean) is - package FI_Vectors is new Ada.Containers.Vectors - (Index_Type => Positive, Element_Type => File_Info); - - use type FI_Vectors.Vector; - - package Unit_Name_FI_Vector_Maps is new Ada.Containers.Ordered_Maps - (Key_Type => Unbounded_String, - Element_Type => FI_Vectors.Vector); - - Units_Present : String_Vectors.Vector; - -- List of all units in Prj - - Unit_Present_To_FI : Unit_Name_FI_Vector_Maps.Map; - -- Map a unit name to a file information vector. A unit name can be - -- be mapped to multiple file info if there are homonym source files. - - package Unit_Language_Maps is new Ada.Containers.Hashed_Maps - (Key_Type => Unbounded_String, - Element_Type => Some_Language, - Equivalent_Keys => "=", - Hash => Hash); - Unit_Languages : Unit_Language_Maps.Map; - -- Language for each unit in Units_Present Unit_Patterns : String_Vectors.Vector; Attr_For_Pattern : String_Maps.Map; -- Patterns identifying unit names and project attribute from which we -- got the pattern. We use Attr_For_Pattern for reporting purposes. - Patterns_Not_Covered : String_Vectors.Vector; + Patterns_Not_Covered : String_Sets.Set; -- Patterns that do not match any of the present unit - Ignored_Cur : Unit_Maps.Cursor; + Cur : Unit_Maps.Cursor; procedure Add_Pattern (Attr, Item : String); -- Add Item to Unit_Patterns. Also save from which project attribute @@ -1267,18 +1237,39 @@ package body Project is ------------------------- procedure Process_Source_File (Info : File_Info; Unit_Name : String) is + use type Ada.Containers.Count_Type; + use String_Vectors; + Actual_Unit_Name : Vector := + To_Vector + (+(if Info.Unit_Part = Unit_Separate + then Prj_Tree.Info + (Prj_Tree.Other_File (Info.File)).Unit_Name + else Unit_Name), + 1); + begin + Match_Pattern_List + (Patterns_List => Unit_Patterns, + Strings_List => Actual_Unit_Name, + Patterns_Not_Covered => Patterns_Not_Covered); - use Unit_Name_FI_Vector_Maps; + -- Add it only if it matches one of the patterns - Key : constant Unbounded_String := +Unit_Name; - Cur : constant Cursor := Unit_Present_To_FI.Find (Key); - begin - Units_Present.Append (Key); - Unit_Languages.Include (Key, To_Language (Info.Language)); - if Has_Element (Cur) then - Unit_Present_To_FI.Reference (Cur).Append (Info); - else - Unit_Present_To_FI.Insert (Key, FI_Vectors.To_Vector (Info, 1)); + if not Actual_Unit_Name.Is_Empty then + declare + Lang : constant Some_Language := To_Language (Info.Language); + begin + Add_Unit + (Units, + Cur, + Unit_Name, + Info, + Lang); + Units.Reference (Cur).Is_Stub := + (Info.Unit_Part = Unit_Separate + or else + (Lang in C_Family_Language + and then Info.Unit_Part = Unit_Spec)); + end; end if; end Process_Source_File; @@ -1291,6 +1282,7 @@ package body Project is List_From_Project (Prj, List_Attr, List_File_Attr, Add_Pattern'Access, Defined); + Patterns_Not_Covered := To_String_Set (Unit_Patterns); if not Defined then return; @@ -1301,28 +1293,13 @@ package body Project is -- source file name. Iterate_Source_Files - (Prj, Process_Source_File'Access, Recursive => False); - - Match_Pattern_List (Patterns_List => Unit_Patterns, - Strings_List => Units_Present, - Patterns_Not_Covered => Patterns_Not_Covered); + (Prj, Process_Source_File'Access, + Recursive => False, Include_Stubs => True); for Pattern of Patterns_Not_Covered loop Warn ("no unit " & (+Pattern) & " in project " & Prj.Name & " (" & (+Attr_For_Pattern.Element (Pattern)) & " attribute)"); end loop; - - for Unit_Name of Units_Present loop - for Info of Unit_Present_To_FI (Unit_Name) loop - Add_Unit - (Units, - Ignored_Cur, - +Unit_Name, - Info, - Unit_Languages.Element (Unit_Name)); - end loop; - end loop; - end Units_From_Project; ----------------------- diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index fb8b60812..88c0ee7f3 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -114,10 +114,7 @@ package Project is -- path of its main executable (including its suffix, for instance ".exe"). -- Otherwise, return an empty string. - function To_Project_Unit - (Unit_Name : String; - Project : Project_Type; - Language : Some_Language) return Files_Table.Project_Unit; + function To_Project_Unit (Info : File_Info) return Files_Table.Project_Unit; -- Return the Project_Unit value that designates the same unit as -- Unit_Name/Project/Language. @@ -132,15 +129,8 @@ package Project is -- and Is_Stub corresponds to the Unit_Info.Is_Stub field (see -- project.adb). - function Is_Unit_Of_Interest - (Project : Project_Type; - Unit_Name : String; - Language : Some_Language) return Boolean; - -- Return whether the unit Unit_Name that belongs to the project Project - -- is a unit of interest. - function Is_Unit_Of_Interest (Full_Name : String) return Boolean; - -- Same as above, but given a full name + -- Return whether the given file is a unit of interest procedure Enumerate_SCOs_Files (Callback : access procedure (Lib_Name : String); diff --git a/tools/gnatcov/strings.adb b/tools/gnatcov/strings.adb index 3ee5ea3b0..b7c343fc2 100644 --- a/tools/gnatcov/strings.adb +++ b/tools/gnatcov/strings.adb @@ -92,6 +92,20 @@ package body Strings is and then S (S'Last - Length + 1 .. S'Last) = Suffix; end Has_Suffix; + -------------------- + -- To_String_Sets -- + -------------------- + + function To_String_Set (V : String_Vectors.Vector) return String_Sets.Set + is + Result : String_Sets.Set; + begin + for Elem of V loop + Result.Include (Elem); + end loop; + return Result; + end To_String_Set; + -------------------- -- Vector_To_List -- -------------------- @@ -163,7 +177,7 @@ package body Strings is procedure Match_Pattern_List (Patterns_List : String_Vectors.Vector; Strings_List : in out String_Vectors.Vector; - Patterns_Not_Covered : out String_Vectors.Vector) + Patterns_Not_Covered : in out String_Sets.Set) is use Ada.Characters.Handling; use Ada.Strings.Unbounded; @@ -173,10 +187,6 @@ package body Strings is Regexps : array (0 .. Pattern_Length - 1) of GNAT.Regexp.Regexp; -- List of regexps, one for each pattern in Patterns_List - Regexps_Covered : array (0 .. Pattern_Length - 1) of Boolean := - (others => False); - -- Record which Regexp of Regexps matched at least once - Matching_Strings : String_Vectors.Vector; -- Result holder for Strings_List @@ -202,9 +212,18 @@ package body Strings is end if; -- A unit matching this pattern was found; the pattern is - -- covered. - - Regexps_Covered (I) := True; + -- covered. Remove it from Patterns_Not_Covered. + + declare + Pattern : constant Unbounded_String := + Patterns_List.Element (I); + Cur : String_Sets.Cursor := + Patterns_Not_Covered.Find (Pattern); + begin + if String_Sets.Has_Element (Cur) then + Patterns_Not_Covered.Delete (Cur); + end if; + end; -- Continue the search in case other patterns match Str so that -- we can mark them as covered as well. @@ -228,12 +247,6 @@ package body Strings is Strings_List := Matching_Strings; - for I in Regexps_Covered'Range loop - if not Regexps_Covered (I) then - Patterns_Not_Covered.Append (Patterns_List.Element (I)); - end if; - end loop; - end Match_Pattern_List; end Strings; diff --git a/tools/gnatcov/strings.ads b/tools/gnatcov/strings.ads index 8d58d1e6f..a1c5df035 100644 --- a/tools/gnatcov/strings.ads +++ b/tools/gnatcov/strings.ads @@ -77,9 +77,11 @@ package Strings is "=" => Ada.Strings.Unbounded.Equal_Case_Insensitive); -- Case insensitive string set + function To_String_Set (V : String_Vectors.Vector) return String_Sets.Set; + -- Convert the given strings vector to a strings set + function Vector_To_List - (V : String_Vectors.Vector) - return String_List_Access; + (V : String_Vectors.Vector) return String_List_Access; -- The stream type below allows arbitrary objects to be streamed -- from/to an unbounded string, which is used as a buffer of bytes. @@ -87,11 +89,11 @@ package Strings is procedure Match_Pattern_List (Patterns_List : String_Vectors.Vector; Strings_List : in out String_Vectors.Vector; - Patterns_Not_Covered : out String_Vectors.Vector); + Patterns_Not_Covered : in out String_Sets.Set); -- Try matching each pattern of Patterns_List against each item of -- Strings_List (case-insensitively). Every item not matched is removed - -- from Strings_List. Also, each pattern that did not match at least once - -- is returned in Patterns_Not_Covered. + -- from Strings_List. Also, each pattern that matched at least once is + -- removed from Patterns_Not_Covered. type Unbounded_String_Stream (S : access Ada.Strings.Unbounded.Unbounded_String) From d12127f2df8424b2e014635e38e522a9a71e2069 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 17 May 2023 14:47:49 +0200 Subject: [PATCH 0315/1483] Move code for compiler switches parsing to Instrument.Common This is preparatory work for the parallelized instrumentation. As compiler switches can be specified in a project file, and as we want to drop the dependency to projects the most we can in the unit instrumentation process, we will need to pass such switches before instrumenting the unit. This means that functions used for compiler switches parsing purposes must be exposed, and we would rather expose them in the Instrument.Common unit, rather than in the Instrument.C unit that is stubbed (and thus everytime we add public API, we have to stub it). --- tools/gnatcov/instrument-c.adb | 274 --------------------------- tools/gnatcov/instrument-c.ads | 60 ------ tools/gnatcov/instrument-c_utils.ads | 4 +- tools/gnatcov/instrument-common.adb | 227 ++++++++++++++++++++++ tools/gnatcov/instrument-common.ads | 107 +++++++++++ 5 files changed, 336 insertions(+), 336 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 82b3d27b7..726dbed6c 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -90,38 +90,6 @@ package body Instrument.C is -- Preprocessing utilities -- ------------------------------ - Macro_Cmdline_Regexp : constant Pattern_Matcher := Compile ( - "([a-zA-Z_]\w*)" - -- The name of the macro - - & "(\(.*\))?" - -- The optional list of macro arguments - - & "([^ =]+)?" - -- Then, there can be any character before the assignment: they will be - -- part of the macro value (e.g. A(b)b will yield #define A b 1) - - & "(?:=(.*))?" - -- The macro value itself - ); - - Macro_Def_Regexp : constant Pattern_Matcher := Compile ( - "#define" - & "(?: |\t)+" - -- "#define", then a non-empty blank - - & "([a-zA-Z_]\w*)" - -- The name of the macro - - & "(\(.*\))?" - -- The optional list of macro arguments - - & "(.*)" - -- The macro value itself - ); - -- Regular expression to analyze definitions for builtin macros (see - -- Builtin_Macros) - type Macro_Set_Access is access Macro_Set; type Macro_Set_Cst_Access is access constant Macro_Set; package Compiler_Macros_Maps is new Ada.Containers.Hashed_Maps @@ -134,22 +102,6 @@ package body Instrument.C is -- compiler command every time a file is instrumented. Used in the -- Builtin_Macros function only. - -- The three following functions are not used, but could be in the future, - -- when we will refine what is done with macros. - - procedure Parse_Macro_Definition - (Str : String; - Parsed_Def : out Macro_Definition; - Success : out Boolean); - -- Parse a macro definition. If the parsing failed, set Success to False. - -- Otherwise, set Parsed_Def to the parsed definition and set Success to - -- True. - - procedure Parse_Cmdline_Macro_Definition - (Str : String; - Parsed_Def : out Macro_Definition; - Success : out Boolean); - -- Same as above, but with a command-line macro definition function Builtin_Macros (Lang, Compiler, Std, Output_Dir : String) return Macro_Set_Cst_Access; @@ -2536,71 +2488,6 @@ package body Instrument.C is UIC.MCDC_State_Declaration_Node := Saved_MCDC_State_Declaration_Node; end Traverse_Declarations; - ---------------------------- - -- Parse_Macro_Definition -- - ---------------------------- - - procedure Parse_Macro_Definition - (Str : String; - Parsed_Def : out Macro_Definition; - Success : out Boolean) - is - Matches : Match_Array (0 .. 3); - begin - Match (Macro_Def_Regexp, Str, Matches); - if Matches (0) = No_Match then - Success := False; - else - Success := True; - Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); - if Matches (2) /= No_Match then - Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); - end if; - Parsed_Def.Value := +Str (Matches (3).First .. Matches (3).Last); - end if; - end Parse_Macro_Definition; - - ------------------------------------ - -- Parse_Cmdline_Macro_Definition -- - ------------------------------------ - - procedure Parse_Cmdline_Macro_Definition - (Str : String; - Parsed_Def : out Macro_Definition; - Success : out Boolean) - is - Matches : Match_Array (0 .. 4); - begin - Match (Macro_Cmdline_Regexp, Str, Matches); - if Matches (0) = No_Match then - Success := False; - else - Success := True; - Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); - if Matches (2) /= No_Match then - Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); - end if; - - -- Command line macros can have part of their value before the - -- assignment, e.g. "-DA(b)b" is equivalent to "#define A(b) b 1". - - if Matches (3) /= No_Match then - Append - (Parsed_Def.Value, - Str (Matches (3).First .. Matches (3).Last) & " "); - end if; - - -- If no value is given, then it is implicitly 1 - - if Matches (4) /= No_Match then - Append - (Parsed_Def.Value, Str (Matches (4).First .. Matches (4).Last)); - else - Append (Parsed_Def.Value, " 1"); - end if; - end if; - end Parse_Cmdline_Macro_Definition; - -------------------- -- Builtin_Macros -- -------------------- @@ -4301,67 +4188,6 @@ package body Instrument.C is return Source_File.Unit_Part = Unit_Spec; end Skip_Source_File; - ----------------- - -- Add_Options -- - ----------------- - - procedure Add_Options - (Args : in out String_Vectors.Vector; - Options : Analysis_Options; - Pass_Builtins : Boolean := True; - Preprocessed : Boolean := False) is - - procedure Add_Macro_Switches (Macros : Macro_Set); - -- Add the given macro switches to Args - - ------------------------ - -- Add_Macro_Switches -- - ------------------------ - - procedure Add_Macro_Switches (Macros : Macro_Set) is - begin - for M of Macros loop - if M.Define then - Args.Append ("-D" & M.Name & M.Args & "=" & M.Value); - else - Args.Append ("-U" & M.Name); - end if; - end loop; - end Add_Macro_Switches; - - begin - for Dir of Options.PP_Search_Path loop - Args.Append (+"-I"); - Args.Append (Dir); - end loop; - - -- If the file was already pre-processed, do not pass macro command - -- line switches. Since preprocessed code can contain names of defined - -- macros, passing macro arguments for the parsing step could trigger - -- other expansions, and thus feed the parser with unexpected code. - - if not Preprocessed then - - -- Add builtin macros before macros from command line switches, as - -- the latter should have precedence over builtins and thus must - -- come last in Args. - - if Pass_Builtins then - Add_Macro_Switches (Options.Builtin_Macros); - end if; - Add_Macro_Switches (Options.PP_Macros); - end if; - - -- The -std switch also indicates the C/C++ version used, and - -- influences both the configuration of the preprocessor, and the - -- parsing of the file. - - if Length (Options.Std) /= 0 then - Args.Append (Options.Std); - end if; - - end Add_Options; - ------------------------- -- Import_From_Project -- ------------------------- @@ -4440,106 +4266,6 @@ package body Instrument.C is end if; end Import_From_Project; - ---------------------- - -- Import_From_Args -- - ---------------------- - - procedure Import_From_Args - (Self : in out Analysis_Options; Args : String_Vectors.Vector) - is - I : Natural := Args.First_Index; - Last : constant Integer := Args.Last_Index; - - function Read_With_Argument - (Arg : String; - Option_Name : Character; - Value : out Unbounded_String) return Boolean; - -- Assuming that Arg starts with "-X" where X is Option_Name, try to - -- fetch the value for this option. If we managed to get one, return - -- True and set Value to it. Return False otherwise. - - ------------------------ - -- Read_With_Argument -- - ------------------------ - - function Read_With_Argument - (Arg : String; - Option_Name : Character; - Value : out Unbounded_String) return Boolean - is - Prefix : constant String := "-" & Option_Name; - begin - if Arg = Prefix then - - -- Option and value are two separate arguments (-O VALUE) - - I := I + 1; - if I <= Last then - Value := Args (I); - return True; - end if; - - elsif Has_Prefix (Arg, Prefix) then - - -- Option and value are combined in a single argument (-OVALUE) - - Value := +Arg (Arg'First + Prefix'Length .. Arg'Last); - return True; - end if; - - return False; - end Read_With_Argument; - - -- Start of processing for Import_From_Args - - begin - while I <= Last loop - declare - A : constant String := +Args (I); - Value : Unbounded_String; - begin - - -- Process arguments we manage to handle, silently discard unknown - -- ones. - -- - -- TODO??? In order to avoid surprising situations for users (for - -- instance typos in command line arguments), maybe we should emit - -- a warning for unknown arguments. However, given that this - -- procedure is called at least once per instrumented source file, - -- we would need to avoid emitting duplicate warnings. - - if Read_With_Argument (A, 'I', Value) then - Self.PP_Search_Path.Append (Value); - - elsif Read_With_Argument (A, 'D', Value) then - declare - Macro_Def : Macro_Definition (Define => True); - Success : Boolean; - begin - Parse_Cmdline_Macro_Definition - (Str => +Value, - Parsed_Def => Macro_Def, - Success => Success); - if Success then - Self.PP_Macros.Include (Macro_Def); - else - Warn ("Failed to parse command-line macro definition: " - & (+Value)); - end if; - end; - - elsif Read_With_Argument (A, 'U', Value) then - Self.PP_Macros.Include ((Define => False, Name => Value)); - - elsif Has_Prefix (A, "-std=") then - Self.Std := +A; - end if; - - I := I + 1; - end; - end loop; - end Import_From_Args; - ---------------- -- Split_Args -- ---------------- diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index af0be0c00..09777a7c0 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -20,7 +20,6 @@ with Ada.Containers.Hashed_Maps; with Ada.Containers.Ordered_Maps; -with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; with Ada.Finalization; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; @@ -232,60 +231,6 @@ package Instrument.C is (Key_Type => Nat, Element_Type => PP_Info); - type Macro_Definition (Define : Boolean := True) is record - Name : Unbounded_String; - -- Name of the macro - - case Define is - when True => - Args : Unbounded_String; - -- String representation of the macro arguments, e.g. (x, y) - - Value : Unbounded_String; - -- Value for the macro definition - - when False => - null; - end case; - end record; - -- Whether a macro should be defined, its name, and when it must be - -- defined, its optional arguments and value. - - function "<" (L, R : Macro_Definition) return Boolean is (L.Name < R.Name); - -- As we store Macro_Definition in sets, we do not want two conflicting - -- definitions of the same macro to coexist. Thus, we compare only the - -- name, meaning that when we insert a new definition, it will replace - -- the previous one. - - package Macro_Sets is new Ada.Containers.Ordered_Sets (Macro_Definition); - subtype Macro_Set is Macro_Sets.Set; - - type Analysis_Options is record - PP_Search_Path : String_Vectors.Vector; - -- List of directories to search when looking for an included file - - Builtin_Macros : Macro_Set; - -- Set of predefined macros for the project compiler driver - - PP_Macros : Macro_Set; - -- Set of macros for the preprocessor - - Std : Unbounded_String; - -- -std=X argument to pass to the preprocessor and the parser, or the - -- empty string. - end record; - -- Options to analyze (preprocess and/or parse) a compilation unit - - procedure Add_Options - (Args : in out String_Vectors.Vector; - Options : Analysis_Options; - Pass_Builtins : Boolean := True; - Preprocessed : Boolean := False); - -- Append to Args the command line options corresponding to Options. If - -- Pass_Builtins is True, pass builtin macros in Options to Args. If - -- Preprocessed is True, consider that we will use these options on a - -- file that was already preprocessed. - procedure Import_From_Project (Self : out Analysis_Options; Language : C_Family_Language; @@ -294,11 +239,6 @@ package Instrument.C is -- Initialize Self from compiler switches corresponding to the Filename -- source file in the Info project. - procedure Import_From_Args - (Self : in out Analysis_Options; Args : String_Vectors.Vector); - -- Extract analysis options from the Args command line arguments and update - -- Self accordingly. - function Split_Args (Args : Unbounded_String) return String_Vectors.Vector; -- Split a comma-separated list of arguments diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 6b3fda8ea..82a80f2be 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -23,8 +23,8 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Clang.Index; use Clang.Index; with Clang.Rewrite; use Clang.Rewrite; -with Instrument.C; use Instrument.C; -with Slocs; use Slocs; +with Instrument.Common; use Instrument.Common; +with Slocs; use Slocs; package Instrument.C_Utils is diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index e12d83a29..8d344e3c1 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -27,6 +27,7 @@ with Interfaces; with Coverage; with Diagnostics; with Hex_Images; +with Outputs; use Outputs; with Paths; use Paths; with Project; use Project; with SCOs; @@ -582,6 +583,232 @@ package body Instrument.Common is end loop; end Remap_Scope_Entity; + ----------------- + -- Add_Options -- + ----------------- + + procedure Add_Options + (Args : in out String_Vectors.Vector; + Options : Analysis_Options; + Pass_Builtins : Boolean := True; + Preprocessed : Boolean := False) is + + procedure Add_Macro_Switches (Macros : Macro_Set); + -- Add the given macro switches to Args + + ------------------------ + -- Add_Macro_Switches -- + ------------------------ + + procedure Add_Macro_Switches (Macros : Macro_Set) is + begin + for M of Macros loop + if M.Define then + Args.Append ("-D" & M.Name & M.Args & "=" & M.Value); + else + Args.Append ("-U" & M.Name); + end if; + end loop; + end Add_Macro_Switches; + + begin + for Dir of Options.PP_Search_Path loop + Args.Append (+"-I"); + Args.Append (Dir); + end loop; + + -- If the file was already pre-processed, do not pass macro command + -- line switches. Since preprocessed code can contain names of defined + -- macros, passing macro arguments for the parsing step could trigger + -- other expansions, and thus feed the parser with unexpected code. + + if not Preprocessed then + + -- Add builtin macros before macros from command line switches, as + -- the latter should have precedence over builtins and thus must + -- come last in Args. + + if Pass_Builtins then + Add_Macro_Switches (Options.Builtin_Macros); + end if; + Add_Macro_Switches (Options.PP_Macros); + end if; + + -- The -std switch also indicates the C/C++ version used, and + -- influences both the configuration of the preprocessor, and the + -- parsing of the file. + + if Length (Options.Std) /= 0 then + Args.Append (Options.Std); + end if; + + end Add_Options; + + ---------------------------- + -- Parse_Macro_Definition -- + ---------------------------- + + procedure Parse_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean) + is + Matches : Match_Array (0 .. 3); + begin + Match (Macro_Def_Regexp, Str, Matches); + if Matches (0) = No_Match then + Success := False; + else + Success := True; + Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); + if Matches (2) /= No_Match then + Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); + end if; + Parsed_Def.Value := +Str (Matches (3).First .. Matches (3).Last); + end if; + end Parse_Macro_Definition; + + ------------------------------------ + -- Parse_Cmdline_Macro_Definition -- + ------------------------------------ + + procedure Parse_Cmdline_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean) + is + Matches : Match_Array (0 .. 4); + begin + Match (Macro_Cmdline_Regexp, Str, Matches); + if Matches (0) = No_Match then + Success := False; + else + Success := True; + Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); + if Matches (2) /= No_Match then + Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); + end if; + + -- Command line macros can have part of their value before the + -- assignment, e.g. "-DA(b)b" is equivalent to "#define A(b) b 1". + + if Matches (3) /= No_Match then + Append + (Parsed_Def.Value, + Str (Matches (3).First .. Matches (3).Last) & " "); + end if; + + -- If no value is given, then it is implicitly 1 + + if Matches (4) /= No_Match then + Append + (Parsed_Def.Value, Str (Matches (4).First .. Matches (4).Last)); + else + Append (Parsed_Def.Value, " 1"); + end if; + end if; + end Parse_Cmdline_Macro_Definition; + + ---------------------- + -- Import_From_Args -- + ---------------------- + + procedure Import_From_Args + (Self : in out Analysis_Options; Args : String_Vectors.Vector) + is + I : Natural := Args.First_Index; + Last : constant Integer := Args.Last_Index; + + function Read_With_Argument + (Arg : String; + Option_Name : Character; + Value : out Unbounded_String) return Boolean; + -- Assuming that Arg starts with "-X" where X is Option_Name, try to + -- fetch the value for this option. If we managed to get one, return + -- True and set Value to it. Return False otherwise. + + ------------------------ + -- Read_With_Argument -- + ------------------------ + + function Read_With_Argument + (Arg : String; + Option_Name : Character; + Value : out Unbounded_String) return Boolean + is + Prefix : constant String := "-" & Option_Name; + begin + if Arg = Prefix then + + -- Option and value are two separate arguments (-O VALUE) + + I := I + 1; + if I <= Last then + Value := Args (I); + return True; + end if; + + elsif Has_Prefix (Arg, Prefix) then + + -- Option and value are combined in a single argument (-OVALUE) + + Value := +Arg (Arg'First + Prefix'Length .. Arg'Last); + return True; + end if; + + return False; + end Read_With_Argument; + + -- Start of processing for Import_From_Args + + begin + while I <= Last loop + declare + A : constant String := +Args (I); + Value : Unbounded_String; + begin + + -- Process arguments we manage to handle, silently discard unknown + -- ones. + -- + -- TODO??? In order to avoid surprising situations for users (for + -- instance typos in command line arguments), maybe we should emit + -- a warning for unknown arguments. However, given that this + -- procedure is called at least once per instrumented source file, + -- we would need to avoid emitting duplicate warnings. + + if Read_With_Argument (A, 'I', Value) then + Self.PP_Search_Path.Append (Value); + + elsif Read_With_Argument (A, 'D', Value) then + declare + Macro_Def : Macro_Definition (Define => True); + Success : Boolean; + begin + Parse_Cmdline_Macro_Definition + (Str => +Value, + Parsed_Def => Macro_Def, + Success => Success); + if Success then + Self.PP_Macros.Include (Macro_Def); + else + Warn ("Failed to parse command-line macro definition: " + & (+Value)); + end if; + end; + + elsif Read_With_Argument (A, 'U', Value) then + Self.PP_Macros.Include ((Define => False, Name => Value)); + + elsif Has_Prefix (A, "-std=") then + Self.Std := +A; + end if; + + I := I + 1; + end; + end loop; + end Import_From_Args; + ------------------------------ -- Buffer_Units_For_Closure -- ------------------------------ diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 7293a2f1d..aae7ea275 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -53,12 +53,14 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Containers.Hashed_Maps; with Ada.Containers.Hashed_Sets; with Ada.Containers.Ordered_Maps; +with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Hash; with Ada.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; with GNATCOLL.VFS; +with GNAT.Regpat; use GNAT.Regpat; with ALI_Files; use ALI_Files; with Files_Table; use Files_Table; @@ -552,4 +554,109 @@ package Instrument.Common is -- function. This procedure should thus be called only once, for one of -- the supported languages of the project. + type Macro_Definition (Define : Boolean := True) is record + Name : Unbounded_String; + -- Name of the macro + + case Define is + when True => + Args : Unbounded_String; + -- String representation of the macro arguments, e.g. (x, y) + + Value : Unbounded_String; + -- Value for the macro definition + + when False => + null; + end case; + end record; + -- Whether a macro should be defined, its name, and when it must be + -- defined, its optional arguments and value. + + function "<" (L, R : Macro_Definition) return Boolean is (L.Name < R.Name); + -- As we store Macro_Definition in sets, we do not want two conflicting + -- definitions of the same macro to coexist. Thus, we compare only the + -- name, meaning that when we insert a new definition, it will replace + -- the previous one. + + package Macro_Sets is new Ada.Containers.Ordered_Sets (Macro_Definition); + subtype Macro_Set is Macro_Sets.Set; + + type Analysis_Options is record + PP_Search_Path : String_Vectors.Vector; + -- List of directories to search when looking for an included file + + Builtin_Macros : Macro_Set; + -- Set of predefined macros for the project compiler driver + + PP_Macros : Macro_Set; + -- Set of macros for the preprocessor + + Std : Unbounded_String; + -- -std=X argument to pass to the preprocessor and the parser, or the + -- empty string. + end record; + -- Options to analyze (preprocess and/or parse) a compilation unit + + Macro_Cmdline_Regexp : constant Pattern_Matcher := Compile ( + "([a-zA-Z_]\w*)" + -- The name of the macro + + & "(\(.*\))?" + -- The optional list of macro arguments + + & "([^ =]+)?" + -- Then, there can be any character before the assignment: they will be + -- part of the macro value (e.g. A(b)b will yield #define A b 1) + + & "(?:=(.*))?" + -- The macro value itself + ); + + Macro_Def_Regexp : constant Pattern_Matcher := Compile ( + "#define" + & "(?: |\t)+" + -- "#define", then a non-empty blank + + & "([a-zA-Z_]\w*)" + -- The name of the macro + + & "(\(.*\))?" + -- The optional list of macro arguments + + & "(.*)" + -- The macro value itself + ); + -- Regular expression to analyze definitions for builtin macros (see + -- Builtin_Macros) + + procedure Parse_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean); + -- Parse a macro definition. If the parsing failed, set Success to False. + -- Otherwise, set Parsed_Def to the parsed definition and set Success to + -- True. + + procedure Parse_Cmdline_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean); + -- Same as above, but with a command-line macro definition + + procedure Add_Options + (Args : in out String_Vectors.Vector; + Options : Analysis_Options; + Pass_Builtins : Boolean := True; + Preprocessed : Boolean := False); + -- Append to Args the command line options corresponding to Options. If + -- Pass_Builtins is True, pass builtin macros in Options to Args. If + -- Preprocessed is True, consider that we will use these options on a + -- file that was already preprocessed. + + procedure Import_From_Args + (Self : in out Analysis_Options; Args : String_Vectors.Vector); + -- Extract analysis options from the Args command line arguments and update + -- Self accordingly. + end Instrument.Common; From 14edf9cb5b00421c819b019ffd4ef4134f7943ac Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 22 May 2023 14:30:56 +0200 Subject: [PATCH 0316/1483] Implement the parallelized instrumentation --- testsuite/SUITE/srctracelib.py | 23 +- testsuite/tests/instr-cov/orphan-unit/test.py | 2 +- tools/gnatcov/command_line.ads | 235 +++- tools/gnatcov/gnatcov_bits_specific.adb | 102 +- tools/gnatcov/inputs.adb | 16 + tools/gnatcov/inputs.ads | 4 + tools/gnatcov/instrument-ada_unit.adb | 1040 ++++++++------ tools/gnatcov/instrument-ada_unit.ads | 99 +- tools/gnatcov/instrument-ada_unit__stub.ads | 18 +- .../gnatcov/instrument-ada_unit_provider.adb | 20 + .../gnatcov/instrument-ada_unit_provider.ads | 10 +- tools/gnatcov/instrument-c.adb | 659 ++++----- tools/gnatcov/instrument-c.ads | 54 +- tools/gnatcov/instrument-c__stub.ads | 9 +- tools/gnatcov/instrument-c_utils.ads | 3 +- tools/gnatcov/instrument-common.adb | 374 +---- tools/gnatcov/instrument-common.ads | 239 +--- tools/gnatcov/instrument-config.adb | 50 + tools/gnatcov/instrument-input_traces.adb | 6 +- tools/gnatcov/instrument-main.adb | 41 + tools/gnatcov/instrument-projects.adb | 1231 +++++++++++++++++ tools/gnatcov/instrument-source.adb | 66 + tools/gnatcov/instrument.adb | 711 ++-------- tools/gnatcov/instrument.ads | 89 +- tools/gnatcov/project.adb | 100 +- tools/gnatcov/project.ads | 15 +- tools/gnatcov/switches.adb | 2 +- tools/gnatcov/switches.ads | 4 + 28 files changed, 3047 insertions(+), 2175 deletions(-) create mode 100644 tools/gnatcov/instrument-config.adb create mode 100644 tools/gnatcov/instrument-main.adb create mode 100644 tools/gnatcov/instrument-projects.adb create mode 100644 tools/gnatcov/instrument-source.adb diff --git a/testsuite/SUITE/srctracelib.py b/testsuite/SUITE/srctracelib.py index a43943212..195fe36de 100755 --- a/testsuite/SUITE/srctracelib.py +++ b/testsuite/SUITE/srctracelib.py @@ -32,7 +32,6 @@ trace_entry_header_struct = Struct( 'trace entry header', ('unit_name_length', 'I'), - ('project_name_length', 'I'), ('stmt_bit_count', 'I'), ('dc_bit_count', 'I'), ('mcdc_bit_count', 'I'), @@ -41,7 +40,7 @@ ('bit_buffer_encoding', 'B'), ('fingerprint', '20B'), ('bit_maps_fingerprint', '20B'), - ('padding', 'B'), + ('padding', '5B'), ) @@ -196,7 +195,6 @@ def format_buffer(b): ''.join('{:02x}'.format(b) for b in e.fingerprint), ''.join('{:02x}'.format(b) for b in e.bit_maps_fingerprint) )) - print(' Project: {}'.format(e.project_name)) print(' Stmt buffer: {}'.format(format_buffer(e.stmt_buffer))) print(' Dc buffer: {}'.format(format_buffer(e.dc_buffer))) print(' MCDC buffer: {}'.format(format_buffer(e.mcdc_buffer))) @@ -276,13 +274,11 @@ class TraceEntry(object): BIT_BUFFER_ENCODING_CODES = { value: key for key, value in BIT_BUFFER_ENCODING_NAMES.items()} - def __init__(self, language, unit_part, unit_name, project_name, - fingerprint, bit_maps_fingerprint, stmt_buffer, dc_buffer, - mcdc_buffer): + def __init__(self, language, unit_part, unit_name, fingerprint, + bit_maps_fingerprint, stmt_buffer, dc_buffer, mcdc_buffer): self.language = language self.unit_part = unit_part self.unit_name = unit_name - self.project_name = project_name self.fingerprint = fingerprint self.bit_maps_fingerprint = bit_maps_fingerprint self.stmt_buffer = stmt_buffer @@ -303,7 +299,7 @@ def read(cls, fp, trace_file, big_endian): language = cls.LANGUAGE_NAMES[header['language']] - if header['padding'] != 0: + if header['padding'] != (0, 0, 0, 0, 0): raise ValueError('Invalid padding: {}' .format(header['padding'])) @@ -314,11 +310,6 @@ def read(cls, fp, trace_file, big_endian): unit_name = read_aligned( fp, header['unit_name_length'], trace_file.alignment) - with fp.label_context('project name'): - project_name = (read_aligned(fp, header['project_name_length'], - trace_file.alignment) - or "") - with fp.label_context('stmt buffer'): stmt_buffer = TraceBuffer.read( fp, trace_file, bit_buffer_encoding, @@ -332,7 +323,7 @@ def read(cls, fp, trace_file, big_endian): fp, trace_file, bit_buffer_encoding, header['mcdc_bit_count']) - return cls(language, unit_part, unit_name, project_name, + return cls(language, unit_part, unit_name, header['fingerprint'], header['bit_maps_fingerprint'], stmt_buffer, dc_buffer, mcdc_buffer) @@ -340,7 +331,6 @@ def write(self, fp, big_endian, alignment): """Write this trace info entry to the `fp` file.""" trace_entry_header_struct.write(fp, { 'unit_name_length': len(self.unit_name), - 'project_name_length': len(self.project_name), 'stmt_bit_count': len(self.stmt_buffer.bits), 'dc_bit_count': len(self.dc_buffer.bits), 'mcdc_bit_count': len(self.mcdc_buffer.bits), @@ -350,11 +340,10 @@ def write(self, fp, big_endian, alignment): self.BIT_BUFFER_ENCODING_CODES['lsb_first_bytes'], 'fingerprint': self.fingerprint, 'bit_maps_fingerprint': self.bit_maps_fingerprint, - 'padding': 0, + 'padding': (0, 0, 0, 0, 0), }, big_endian=big_endian) write_aligned(fp, self.unit_name, alignment) - write_aligned(fp, self.project_name, alignment) self.stmt_buffer.write(fp, alignment) self.dc_buffer.write(fp, alignment) diff --git a/testsuite/tests/instr-cov/orphan-unit/test.py b/testsuite/tests/instr-cov/orphan-unit/test.py index 60d3db495..1880b8f65 100644 --- a/testsuite/tests/instr-cov/orphan-unit/test.py +++ b/testsuite/tests/instr-cov/orphan-unit/test.py @@ -27,7 +27,7 @@ thistest.fail_if_not_equal( '"gnatcov instrument" output', ( - "warning: While instrumenting pkg-child.adb...\n" + "warning: While instrumenting pkg-child.ads...\n" "warning: Cannot find required source file: pkg.ads" ), contents_of("instrument.log").strip(), diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 1a355b49e..56bdafe4b 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -59,7 +59,9 @@ package Command_Line is Cmd_Scan_Objects, Cmd_Setup, - Cmd_Instrument); + Cmd_Instrument_Project, + Cmd_Instrument_Source, + Cmd_Instrument_Main); -- Set of commands we support. More complete descriptions below. type Bool_Options is @@ -113,6 +115,7 @@ package Command_Line is Opt_Dump_Channel, Opt_Dump_Filename_Env_Var, Opt_Dump_Filename_Prefix, + Opt_Dump_Filename_Tag, Opt_Ada, Opt_Dump_Units_To, Opt_Timezone, @@ -121,6 +124,15 @@ package Command_Line is Opt_Path_Count_Limit, Opt_Install_Name, Opt_Runtime_Project, + Opt_Lang, + Opt_Parallelism_Level, + Opt_Compiler_Driver, + Opt_Spec_Suffix, + Opt_Body_Suffix, + Opt_Dot_Replacement, + Opt_Gnatem, + Opt_Gnatec, + Opt_Project_Name, Opt_Source_Root); -- Set of string options we support. More complete descriptions below. @@ -145,9 +157,14 @@ package Command_Line is Opt_Restricted_To_Languages, Opt_Annotation_Format, Opt_C_Opts, - Opt_CPP_Opts); + Opt_CPP_Opts, + Opt_Files, + Opt_Runtime_Dir); -- Set of string list options we support. More complete descriptions below. + subtype Cmd_Instrument is Command_Type + range Cmd_Instrument_Project .. Cmd_Instrument_Main; + package Parser is new Argparse (Command_Type, Bool_Options, String_Options, String_List_Options); use Parser; @@ -338,11 +355,24 @@ package Command_Line is & " instrumentation and set up default arguments" & " for future ""gnatcov instrument"" invocations.", Internal => False), - Cmd_Instrument => Create + Cmd_Instrument_Project => Create (Name => "instrument", Description => ("Instrument the given project and produce the" & " associated Source Instrumentation Data files."), - Internal => False)); + Internal => False), + Cmd_Instrument_Source => Create + (Name => "instrument-source", + Description => "Instrument the given files, all belonging to the" + & " same unit.", + Pattern => "[FILES]", + Internal => True), + Cmd_Instrument_Main => Create + (Name => "instrument-main", + Description => "Insert dump trigger code in the the given main file," + & " dumping coverage buffers of all of the specified" + & " files (through the --files switch).", + Pattern => "--files= [MAIN]", + Internal => True)); Bool_Infos : constant Bool_Option_Info_Array := (Opt_Verbose => Create @@ -356,7 +386,7 @@ package Command_Line is & " transitively imported project.", Commands => (Cmd_Run | Cmd_Coverage - | Cmd_Instrument + | Cmd_Instrument_Project | Cmd_Dump_CFG => True, others => False), Internal => False), @@ -367,7 +397,7 @@ package Command_Line is & " transitively imported projects are not considered.", Commands => (Cmd_Run | Cmd_Coverage - | Cmd_Instrument + | Cmd_Instrument_Project | Cmd_Dump_CFG => True, others => False), Internal => False), @@ -465,7 +495,10 @@ package Command_Line is Help => "Valid only when --dump-channel=bin-file. Create simple" & " filenames for source trace files (no PID/timestamp" & " variations).", - Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), + Commands => (Cmd_Setup + | Cmd_Instrument_Project + | Cmd_Instrument_Main => True, + others => False), Internal => False), Opt_Allow_Mix_Trace_Kind => Create @@ -526,10 +559,13 @@ package Command_Line is Pattern => "[GPR]", Help => "Use GPR as root project to locate SCOs, select" & " units to analyze and find default options.", - Commands => (Cmd_Setup => False, others => True), + Commands => (Cmd_Setup + | Cmd_Instrument_Source + | Cmd_Instrument_Main => False, + others => True), At_Most_Once => True, Internal => False), - Opt_Subdirs => Create + Opt_Subdirs => Create (Long_Name => "--subdirs", Pattern => "[SUBDIR]", Help => "When using project files, look for ALI/SID files in" @@ -588,7 +624,9 @@ package Command_Line is Pattern => "[SUBDIR]", Help => "Subdirectory where XCOV or HTML report files should" & " be produced.", - Commands => (Cmd_Coverage => True, others => False), + Commands => (Cmd_Coverage + | Cmd_Instrument_Source + | Cmd_Instrument_Main => True, others => False), At_Most_Once => False, Internal => False), Opt_Tag => Create @@ -753,7 +791,10 @@ package Command_Line is & " to dump a base64 trace on the standard output" & " using Ada.Text_IO. This is the preferred channel" & " for non-native programs.", - Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), + Commands => (Cmd_Setup + | Cmd_Instrument_Project + | Cmd_Instrument_Main => True, + others => False), At_Most_Once => False, Internal => False, Pattern => "bin-file|base64-stdout"), @@ -762,14 +803,31 @@ package Command_Line is Help => "Valid only when --dump-channel=bin-file. Name of the" & " environment variable which, if set, contains the" & " filename for created source traces.", - Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), + Commands => (Cmd_Setup + | Cmd_Instrument_Project + | Cmd_Instrument_Main => True, + others => False), At_Most_Once => False, Internal => False), Opt_Dump_Filename_Prefix => Create (Long_Name => "--dump-filename-prefix", Help => "Valid only when --dump-channel=bin-file. Select a" & " filename prefix for created source traces.", - Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), + Commands => (Cmd_Setup + | Cmd_Instrument_Project + | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => False), + + Opt_Dump_Filename_Tag => Create + (Long_Name => "--dump-filename-tag", + Help => "Valid only when --dump-channel=bin-file. Select a" + & " filename tag for created source traces.", + Commands => (Cmd_Setup + | Cmd_Instrument_Project + | Cmd_Instrument_Main => True, + others => False), At_Most_Once => False, Internal => False), @@ -878,6 +936,107 @@ package Command_Line is At_Most_Once => False, Internal => False), + Opt_Lang => Create + (Long_Name => "--lang", + Pattern => "[C|C++|Ada]", + Help => "Language for the given compilation unit", + Commands => (Cmd_Instrument_Main | Cmd_Instrument_Source => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Parallelism_Level => Create + (Short_Name => "-j", + Long_Name => "--jobs", + Pattern => "POSITIVE", + Help => + "Maximal number of concurrently running tasks. Number of processors" + & " of the machine if set to 0. Defaults to 1.", + Commands => (Cmd_Instrument_Project => True, others => False), + At_Most_Once => False, + Internal => False), + + Opt_Compiler_Driver => Create + (Long_Name => "--compiler-driver", + Pattern => "NAME", + Help => + "Compiler driver used to compile the source (e.g. gcc). This is" + & " used when instrumenting a C/C++ source, to retrieve builtin" + & " macros that may modify the file preprocessing.", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Body_Suffix => Create + (Long_Name => "--body-suffix", + Pattern => "NAME", + Help => + "Body suffix for source files created by the instrumenter for the" + & " instrumentation of a source", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Spec_Suffix => Create + (Long_Name => "--spec-suffix", + Pattern => "NAME", + Help => + "Spec suffix for source files created by the instrumenter for the" + & " instrumentation of a source", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Dot_Replacement => Create + (Long_Name => "--dot-replacement", + Pattern => "NAME", + Help => + "Dot replacement for source files created by the instrumenter for" + & " the instrumentation of a source", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Gnatem => Create + (Long_Name => "--gnatem", + Pattern => "NAME", + Help => + "Name of the file containing unit dependencies in the GNAT format.", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Gnatec => Create + (Long_Name => "--gnatec", + Pattern => "NAME", + Help => + "Name of the file containing configuration pragmas.", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Project_Name => Create + (Long_Name => "--project-name", + Pattern => "NAME", + Help => + "Name of the root project, without its gpr extension.", + Commands => + (Cmd_Instrument_Main => True, others => False), + At_Most_Once => False, + Internal => True), + Opt_Source_Root => Create (Long_Name => "--source-root", Pattern => "PATH", @@ -900,7 +1059,10 @@ package Command_Line is Pattern => "[GPR|@LISTFILE]", Help => "Focus on specific projects within the transitive" & " closure reachable from the root designated by -P.", - Commands => (Cmd_Setup => False, others => True), + Commands => (Cmd_Setup + | Cmd_Instrument_Source + | Cmd_Instrument_Main => False, + others => True), Internal => False), Opt_Scenario_Var => Create (Short_Name => "-X", @@ -951,8 +1113,8 @@ package Command_Line is | Cmd_Coverage | Cmd_Scan_Decisions | Cmd_Map_Routines - | Cmd_Instrument => True, - others => False), + | Cmd_Instrument_Project => True, + others => False), Internal => False), Opt_SID => Create (Long_Name => "--sid", @@ -960,7 +1122,8 @@ package Command_Line is Help => "Load Source Instrumentation Data from FILE for this" & " operation; or do that for each file listed in" & " LISTFILE.", - Commands => (Cmd_Coverage => True, others => False), + Commands => (Cmd_Coverage | Cmd_Instrument_Source => True, + others => False), Internal => False), Opt_Routines => Create (Long_Name => "--routines", @@ -1042,10 +1205,19 @@ package Command_Line is & " Supports globbing patterns.", Commands => (Cmd_Coverage | Cmd_Map_Routines - | Cmd_Instrument => True, - others => False), + | Cmd_Instrument_Project => True, + others => False), Internal => False), + Opt_Files => Create + (Long_Name => "--files", + Pattern => "[FILE|@LISTFILE]", + Help => "Specify a list of source files of interest by their" + & " full name.", + Commands => (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + Internal => True), + Opt_Shared_Object => Create (Long_Name => "--shared-object", Short_Name => "-L", @@ -1070,12 +1242,13 @@ package Command_Line is (Long_Name => "--restricted-to-languages", Pattern => "[LANGUAGE|LIST|@LISTFILE]", Help => - "Restrict the set of languages for instrumentation. Supports Ada" - & " and C. As C support is still in beta state, the default is" - & " --restricted-to-languages=Ada. To enable both, pass" - & " --restricted-to-languages=Ada,C.", - Commands => (Cmd_Setup | Cmd_Instrument => True, - others => False), + "Restrict the set of languages for instrumentation. Supports Ada, C" + & " and C++. As C++ support is still in beta state, the default is" + & " --restricted-to-languages=Ada,C. To enable C++, pass" + & " --restricted-to-languages=Ada,C,C++.", + Commands => (Cmd_Setup + | Cmd_Instrument_Project => True, + others => False), Internal => False, Accepts_Comma_Separator => True), Opt_Annotation_Format => Create @@ -1109,7 +1282,17 @@ package Command_Line is "List of additional compiler switches to analayze C++ source" & " files.", Commands => (Cmd_Instrument => True, others => False), - Internal => False) + Internal => False), + + Opt_Runtime_Dir => Create + (Long_Name => "--runtime-dir", + Pattern => "NAME", + Help => + "Directories containing the compiler runtime sources.", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + Internal => True) ); procedure Bool_Callback diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 71920e33c..c53b72790 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -27,6 +27,8 @@ with GNAT.OS_Lib; with GNAT.Regexp; with GNAT.Strings; use GNAT.Strings; +with System.Multiprocessors; + with Snames; with ALI_Files; @@ -56,8 +58,13 @@ with Execs_Dbase; use Execs_Dbase; with Files_Table; use Files_Table; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Inputs; use Inputs; +with Instrument; +with Instrument.Common; use Instrument.Common; +with Instrument.Config; +with Instrument.Main; +with Instrument.Projects; +with Instrument.Source; with Instrument.Input_Traces; -with Instrument; use Instrument; with Object_Locations; with Outputs; use Outputs; with Perf_Counters; @@ -98,6 +105,7 @@ procedure GNATcov_Bits_Specific is Checkpoints_Inputs : Inputs.Inputs_Type; SID_Inputs : Inputs.Inputs_Type; Ignored_Source_Files : Inputs.Inputs_Type; + Files_Of_Interest : Inputs.Inputs_Type; Source_Rebase_Inputs : Inputs.Inputs_Type; Source_Search_Inputs : Inputs.Inputs_Type; Text_Start : Pc_Type := 0; @@ -481,6 +489,8 @@ procedure GNATcov_Bits_Specific is Copy_Arg_List (Opt_Checkpoint, Checkpoints_Inputs); Copy_Arg_List (Opt_Ignore_Source_Files, Ignored_Source_Files); + Copy_Arg_List (Opt_Files, Files_Of_Interest); + Switches.Files_Of_Interest := To_String_Set (Files_Of_Interest); -- Compute the languages for which we want coverage analysis, or enable -- just the default ones. @@ -1029,6 +1039,32 @@ procedure GNATcov_Bits_Specific is Copy_Arg_List (Opt_C_Opts, C_Opts); Copy_Arg_List (Opt_CPP_Opts, CPP_Opts); + if Args.String_Args (Opt_Parallelism_Level).Present then + declare + Parallelism_Level : Natural; + begin + begin + Parallelism_Level := + Natural'Value + (+Args.String_Args (Opt_Parallelism_Level).Value); + exception + when Constraint_Error => + Fatal_Error ("Parallelism level (-j or --jobs)" + & " must be a natural integer value"); + end; + + -- Limit the number of spawned subprocesses to the number + -- of cores. + + if Parallelism_Level = 0 then + Instrument.Parallelism_Level := + Positive (System.Multiprocessors.Number_Of_CPUs); + else + Instrument.Parallelism_Level := Parallelism_Level; + end if; + end; + end if; + when others => null; end case; @@ -1260,7 +1296,7 @@ begin Gargs => Args.String_List_Args (Opt_Gargs)); end; - when Cmd_Instrument => + when Cmd_Instrument_Project => if not Is_Project_Loaded then Fatal_Error ("instrumentation requires a project file;" & " please use the -P option"); @@ -1287,10 +1323,8 @@ begin -- Matcher for the source files to ignore Language_Version : Any_Language_Version; + pragma Unreferenced (Language_Version); - Mains : String_Vectors.Vector renames Args.Remaining_Args; - -- Treat remaining command line arguments as a list of source - -- files to be processed as mains. begin Create_Matcher (Ignored_Source_Files, Matcher, Has_Matcher); @@ -1322,16 +1356,6 @@ begin ("(selected runtime from " & (+Setup_Cfg.Project_File) & ")"); end if; - -- Even though instrumentation does not create any traces, the - -- structure of a SID file is basically a checkpoint, so it has a - -- Trace_Kind field in its header. Instead of leaving it to - -- Unknown (default value) mark it as Source_Trace_File so that - -- when the .sid file is loaded, it will set gnatcov in - -- "source trace mode" and it will be rejected if binary traces - -- have already been loaded. - - Update_Current_Trace_Kind (Source_Trace_File); - if Analyze_Entry_Barriers then Warn ("With source traces, entry barrier analysis (enabled" & " with --analyze-entry-barriers) is only supported when" @@ -1340,12 +1364,54 @@ begin & " result in invalid code being emitted."); end if; - Instrument.Instrument_Units_Of_Interest + Instrument.Projects (Dump_Config => Dump_Config, - Language_Version => Language_Version, Ignored_Source_Files => (if Has_Matcher then Matcher'Access else null), - Mains => Mains); + Mains => Args.Remaining_Args); + end; + + when Cmd_Instrument_Source => + -- For the instrument-source command, and for the instrument-main, + -- we do not check the command-line semantics as these commands are + -- internal and spawned by a gnatcov main process. They are thus by + -- default well-formed, and if they are not, it is a gnatcov bug. + -- + -- The unit to instrument is the trailing argument + + declare + Instrumenter : Language_Instrumenter'Class := Instrument.Config; + begin + Instrument.Source + (Instrumenter => Instrumenter, + Files_Of_Interest => Switches.Files_Of_Interest, + Prj => Instrument.Load_From_Command_Line, + Unit_Name => +Args.Remaining_Args.First_Element, + SID_Name => + +Args.String_List_Args (Opt_SID).First_Element); + end; + + when Cmd_Instrument_Main => + declare + -- The dump config is loaded from the command line. The + -- implementation of the main instrumentation process assumes that + -- it is fully explicited, i.e. that nothing is left as default. + + Dump_Config : constant Any_Dump_Config := + Load_Dump_Config (Any_Dump_Config'(others => <>)); + + -- Trailing argument is the main to instrument + + Main_Filename : constant String := + +Args.Remaining_Args.First_Element; + + Instrumenter : Language_Instrumenter'Class := Instrument.Config; + begin + Instrument.Main + (Instrumenter, + Dump_Config, + Main_Filename, + Instrument.Load_From_Command_Line); end; when Cmd_Scan_Objects => diff --git a/tools/gnatcov/inputs.adb b/tools/gnatcov/inputs.adb index 300aac1cd..2b4072985 100644 --- a/tools/gnatcov/inputs.adb +++ b/tools/gnatcov/inputs.adb @@ -262,6 +262,22 @@ package body Inputs is return Res; end To_String_Vector; + ------------------- + -- To_String_Set -- + ------------------- + + function To_String_Set + (Inputs : Inputs_Type) return String_Sets.Set + is + use String_Sets; + Res : Set; + begin + for IE of Inputs loop + Res.Include (+IE.Name.all); + end loop; + return Res; + end To_String_Set; + -------------------- -- Create_Matcher -- -------------------- diff --git a/tools/gnatcov/inputs.ads b/tools/gnatcov/inputs.ads index b53251ec3..3aa804365 100644 --- a/tools/gnatcov/inputs.ads +++ b/tools/gnatcov/inputs.ads @@ -79,6 +79,10 @@ package Inputs is (Inputs : Inputs_Type) return String_Vectors.Vector; -- Convert an inputs list into a String_Vectors.Vector + function To_String_Set + (Inputs : Inputs_Type) return String_Sets.Set; + -- Convert an inputs list into a String_Sets.Set + procedure Create_Matcher (Pattern_List : String_Vectors.Vector; Matcher : out GNAT.Regexp.Regexp; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 39516a36d..c801e4aec 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -18,14 +18,14 @@ with Ada.Characters.Conversions; use Ada.Characters.Conversions; with Ada.Characters.Handling; -with Ada.Containers; use Ada.Containers; with Ada.Directories; +with Ada.Containers; use Ada.Containers; with Ada.Exceptions; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Wide_Wide_Fixed; pragma Warnings (Off, "* is an internal GNAT unit"); with Ada.Strings.Wide_Wide_Unbounded.Aux; pragma Warnings (On, "* is an internal GNAT unit"); +with Ada.Text_IO; use Ada.Text_IO; with Langkit_Support; with Langkit_Support.Slocs; use Langkit_Support.Slocs; @@ -39,18 +39,14 @@ use Libadalang.Generic_API.Introspection; with Libadalang.Sources; use Libadalang.Sources; with GNATCOLL.Utils; -with GNATCOLL.VFS; with ALI_Files; use ALI_Files; with Coverage_Options; use Coverage_Options; with Coverage; use Coverage; with Diagnostics; use Diagnostics; -with Files_Table; use Files_Table; -with Instrument.Ada_Unit_Provider; with Namet; use Namet; with Outputs; use Outputs; with Paths; use Paths; -with Project; with SCOs; with Slocs; with Snames; use Snames; @@ -104,6 +100,14 @@ package body Instrument.Ada_Unit is -- Import the low level SCO in UIC marked as non-instrumented in the high -- level non-instrumented SCO_Id sets. + procedure Find_Ada_Units + (Instrumenter : in out Ada_Instrumenter_Type; + Filename : String; + Process_Unit : access procedure (Filename : String)); + -- Consider that Filename is a source file to instrument (i.e. a unit of + -- interest) and call Process_Unit for all compilation units that must be + -- instrumented with it (i.e. related subunits, if present). + ----------------------- -- To_Qualified_Name -- ----------------------- @@ -930,6 +934,12 @@ package body Instrument.Ada_Unit is -- to get the analysis unit for System. Used to avoid emitting duplicate -- messages. + function Has_Unit + (Context : Analysis_Context; + Unit : String; + Part : Analysis_Unit_Kind) return Boolean; + -- Return whether the given unit exists + function Pragma_Restricts_Finalization (Prag_Node : Pragma_Node) return Boolean; -- Return True if Prag_Node imposes a restrictions on use of finalization @@ -1033,7 +1043,8 @@ package body Instrument.Ada_Unit is -- to perform semantic analysis (so mandated by Ada), but which are not -- available. - procedure Create_LAL_Context (Instrumenter : in out Ada_Instrumenter_Type); + procedure Create_LAL_Context + (Instrumenter : in out Ada_Instrumenter_Type'Class); -- Create a new Libadalang analysis context for Instrumenter, assigning it -- to Instrumenter.Context. -- @@ -1043,7 +1054,7 @@ package body Instrument.Ada_Unit is -- used to instrument any source file yet. function Get_From_File - (Instrumenter : in out Ada_Instrumenter_Type; + (Instrumenter : in out Ada_Instrumenter_Type'Class; Filename : String) return Libadalang.Analysis.Analysis_Unit; -- Fetch the analysis unit for the given filename @@ -1065,8 +1076,8 @@ package body Instrument.Ada_Unit is procedure Start_Rewriting (Self : out Ada_Source_Rewriter'Class; - Instrumenter : in out Ada_Instrumenter_Type; - Info : in out Project_Info; + Instrumenter : in out Ada_Instrumenter_Type'Class; + Prj : Prj_Desc; Input_Filename : String); -- Start a rewriting session for the given Input_Filename. If the rewriting -- process is successful, the result will be written to a file in @@ -1113,22 +1124,17 @@ package body Instrument.Ada_Unit is -- the very beginning of each written source, these pragmas avoid this. procedure Initialize_Rewriting - (Instrumenter : Ada_Instrumenter_Type; - UIC : out Ada_Unit_Inst_Context; - Instrumented_Unit : Compilation_Unit_Name); + (UIC : in out Ada_Unit_Inst_Context; + Instrumenter : Ada_Instrumenter_Type'Class); -- Initialize a unit instrumentation context for the given unit to -- instrument. procedure Instrument_Source_File - (CU_Name : Compilation_Unit_Name; - Unit_Info : Instrumented_Unit_Info; - Prj_Info : in out Project_Info; + (UIC : in out Ada_Unit_Inst_Context; + Filename : String; Instrumenter : in out Ada_Instrumenter_Type; - UIC : out Ada_Unit_Inst_Context); - -- Generate the instrumented source corresponding to CU_Name/Unit_Info. - -- - -- If the unit to instrument is also a main and the buffers dump trigger - -- is not manual, instrumented code will also dump the coverage buffers. + Prj : Prj_Desc); + -- Generate the instrumented source corresponding to Filename ---------------------------------- -- Main instrumentation helpers -- @@ -1178,8 +1184,8 @@ package body Instrument.Ada_Unit is -- subprogram instantiation (Synthetic => True). function Probe_Main - (Dump_Config : Any_Dump_Config; - Info : in out Project_Info; + (Prj : Prj_Desc; + Dump_Config : Any_Dump_Config; Rewriter : Ada_Source_Rewriter'Class) return Main_Instrumentation_Description; -- Given a rewriter for the main source, return a description of the main @@ -1195,7 +1201,7 @@ package body Instrument.Ada_Unit is procedure Expand_Main_Generic_Instantiation (Main : Generic_Subp_Instantiation; - Info : in out Project_Info; + Prj : Prj_Desc; Generic_Wrapper_Body_Filename : out Unbounded_String; Generic_Wrapper_Body : out Node_Rewriting_Handle; Prelude : out Node_Rewriting_Handle; @@ -1272,35 +1278,57 @@ package body Instrument.Ada_Unit is function Buffers_List_Unit (Project_Name : String) return Ada_Qualified_Name; -- Returns the name of the unit containing the array of coverage buffers. - -- It is named after the root project name (e.g. if the root project is - -- p.gpr, its name is .). + -- It is named after the given project main name (e.g. if the + -- project p.gpr, its name is .). + + function Buffer_Unit + (Unit_Name : Ada_Qualified_Name) return Ada_Qualified_Name; + -- Given a file to instrument, return the name of the unit that holds + -- its coverage buffers (Coverage_Buffer_Type and + -- GNATcov_RTS_Coverage_Buffers records). function Pure_Buffer_Unit - (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name; + (Unit_Name : Ada_Qualified_Name) return Ada_Qualified_Name; -- Given a unit to instrument, return the name of the unit that holds -- addresses to its coverage buffers. procedure Emit_Buffer_Unit - (Info : in out Project_Info; UIC : Ada_Unit_Inst_Context'Class); + (Buffer_Unit : Compilation_Unit_Name; + Prj : Prj_Desc; + Unit : Project_Unit; + Unit_Bits : Allocated_Bits_Vectors.Vector; + CU_Names : CU_Name_Vectors.Vector; + CUs : CU_Id_Vectors.Vector); -- Emit the unit to contain coverage buffers for the given instrumented -- unit. procedure Emit_Pure_Buffer_Unit - (Info : in out Project_Info; UIC : Ada_Unit_Inst_Context'Class); - -- Emit the unit to contain addresses for the coverage buffers + (PB_Unit : Compilation_Unit_Name; + Prj : Prj_Desc; + CU_Names : CU_Name_Vectors.Vector; + Language_Version : Unbounded_Wide_Wide_String; + Degenerate_Subprogram_Generics : Generic_Subp_Vectors.Vector); + -- Emit the unit to contain addresses for the coverage buffers of all of + -- the compilation unit parts in CU_Names. PB_Unit holds the name of + -- the pure buffer unit, which is generated in the output dir specified in + -- the project description Prj. + -- + -- See the documentation of the eponym fields of the Ada_Unit_Inst_Context + -- record for the Language_Version and Degenerate_Subprogram_Generics + -- parameters. procedure Emit_Dump_Helper_Unit (Dump_Config : Any_Dump_Config; - Info : in out Project_Info; - Main_Filename : String; + Instrumenter : Ada_Instrumenter_Type'Class; + Prj : Prj_Desc; Main : Compilation_Unit_Name; Helper_Unit : out Ada_Qualified_Name; Override_Dump_Trigger : Any_Dump_Trigger := Manual; Has_Controlled : Boolean := False); -- Emit the unit to contain helpers to implement the automatic dump of - -- coverage buffers for the given Main unit implemented in Main_Filename. - -- Info must be the project that owns this main. Upon return, the name of - -- this helper unit is stored in Helper_Unit. + -- coverage buffers for the given Main unit. Prj must contain information + -- about the project that owns this main. Upon return, the name of this + -- helper unit is stored in Helper_Unit. -- -- If Override_Dump_Trigger is anything other than Manual, it will be used -- as a dump trigger instead of the one defined in IC.Dump_Config. @@ -6468,14 +6496,14 @@ package body Instrument.Ada_Unit is procedure Start_Rewriting (Self : out Ada_Source_Rewriter'Class; - Instrumenter : in out Ada_Instrumenter_Type; - Info : in out Project_Info; + Instrumenter : in out Ada_Instrumenter_Type'Class; + Prj : Prj_Desc; Input_Filename : String) is Base_Filename : constant String := Ada.Directories.Simple_Name (Input_Filename); Output_Filename : constant String := - To_String (Info.Output_Dir) / Base_Filename; + New_File (Prj, Base_Filename); Unit : constant Analysis_Unit := Get_From_File (Instrumenter, Input_Filename); begin @@ -6546,22 +6574,22 @@ package body Instrument.Ada_Unit is declare Source_Name : constant String := To_String (N); begin - if GNATCOLL.Utils.Starts_With (Source_Name, "gnatcov_rts") then - return; + if not GNATCOLL.Utils.Starts_With (Source_Name, "gnatcov_rts") + then + -- If we have not done it yet, clarify which file we were + -- instrumenting when we noticed that the source file N was + -- missing. + + if Length (Self.Instrumented_File) > 0 then + Warn ("While instrumenting " + & To_String (Self.Instrumented_File) + & "..."); + Self.Instrumented_File := Null_Unbounded_String; + end if; + + Warn ("Cannot find required source file: " & Source_Name); end if; end; - - -- If we have not done it yet, clarify which file we were - -- instrumenting when we noticed that the source file N was missing. - - if Length (Self.Instrumented_File) > 0 then - Warn ("While instrumenting " - & To_String (Self.Instrumented_File) - & "..."); - Self.Instrumented_File := Null_Unbounded_String; - end if; - - Warn ("Cannot find required source file: " & To_String (N)); end; end Unit_Requested_Callback; @@ -6581,48 +6609,33 @@ package body Instrument.Ada_Unit is -- Create_LAL_Context -- ------------------------ - procedure Create_LAL_Context (Instrumenter : in out Ada_Instrumenter_Type) - is + procedure Create_LAL_Context + (Instrumenter : in out Ada_Instrumenter_Type'Class) is begin Instrumenter.Context := Create_Context - (Unit_Provider => Instrumenter.Provider, + (Unit_Provider => + Create_Unit_Provider_Reference (Instrumenter.Provider), Event_Handler => Instrumenter.Event_Handler); Instrumenter.Get_From_File_Count := 0; - -- Load configuration pragmas - -- TODO??? Remove the type convertion when the LAL API change for - -- VA07-037 makes it into stable-libadalang. + -- Load configuration pragmas. TODO???: clarify what happens when there + -- is a local configuration pragma file. - Libadalang.Config_Pragmas.Import_From_Project + Libadalang.Config_Pragmas.Set_Mapping (Instrumenter.Context, - GNATCOLL.Projects.Project_Tree (Project.Project.all)); + Libadalang.Config_Pragmas.Config_Pragmas_Mapping' + (Global_Pragmas => + Instrumenter.Context.Get_From_File + (+Instrumenter.Config_Pragmas_Filename), + others => <>)); end Create_LAL_Context; - ----------------------------- - -- Create_Ada_Instrumenter -- - ----------------------------- - - function Create_Ada_Instrumenter - (Language_Version : Any_Language_Version) return Ada_Instrumenter_Type - is - Provider : constant Unit_Provider_Reference := - Instrument.Ada_Unit_Provider.Create_Provider_From_Project; - - Instrumenter : Ada_Instrumenter_Type; - begin - Instrumenter.Provider := Provider; - Instrumenter.Event_Handler := Create_Missing_File_Reporter; - Create_LAL_Context (Instrumenter); - Instrumenter.Language_Version := Language_Version; - return Instrumenter; - end Create_Ada_Instrumenter; - ------------------- -- Get_From_File -- ------------------- function Get_From_File - (Instrumenter : in out Ada_Instrumenter_Type; + (Instrumenter : in out Ada_Instrumenter_Type'Class; Filename : String) return Libadalang.Analysis.Analysis_Unit is begin @@ -6654,33 +6667,50 @@ package body Instrument.Ada_Unit is -------------------------- procedure Initialize_Rewriting - (Instrumenter : Ada_Instrumenter_Type; - UIC : out Ada_Unit_Inst_Context; - Instrumented_Unit : Compilation_Unit_Name) is + (UIC : in out Ada_Unit_Inst_Context; + Instrumenter : Ada_Instrumenter_Type'Class) is begin - UIC.Instrumented_Unit := Instrumented_Unit; - UIC.Buffer_Unit := - CU_Name_For_Unit (Buffer_Unit (Instrumented_Unit), GPR.Unit_Spec); - UIC.Pure_Buffer_Unit := - CU_Name_For_Unit (Pure_Buffer_Unit (Instrumented_Unit), GPR.Unit_Spec); UIC.Rewriting_Context := Handle (Instrumenter.Context); declare RH : constant Rewriting_Handle := UIC.Rewriting_Context; E : Instrumentation_Entities renames UIC.Entities; + + function Indexed_Buffer + (Buffer_Kind : Ada_Qualified_Name) return Node_Rewriting_Handle; + -- Suffix Buffer_Kind with the buffer index for the currently + -- instrumented source file. See the comment for the package + -- Allocated_Bits_Vectors in Instrument.Common for more information. + + -------------------- + -- Indexed_Buffer -- + -------------------- + + function Indexed_Buffer + (Buffer_Kind : Ada_Qualified_Name) return Node_Rewriting_Handle + is + Buffer : constant Ada_Qualified_Name := + To_Qualified_Name ("Buffers_" & Img (E.Buffers_Index)) + & Buffer_Kind; + begin + return Create_From_Template + (Handle => RH, + Template => + To_Text (To_Ada (UIC.Pure_Buffer_Unit.Unit & Buffer)), + Arguments => (1 .. 0 => No_Node_Rewriting_Handle), + Rule => Expr_Rule); + end Indexed_Buffer; + begin E.Common_Buffers := To_Nodes (RH, Sys_Buffers); E.Unit_Buffers := To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit); - E.Statement_Buffer := - To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit & Statement_Buffer_Name); + E.Statement_Buffer := Indexed_Buffer (Statement_Buffer_Name); if Coverage.Enabled (Decision) or else MCDC_Coverage_Enabled then - E.Decision_Buffer := - To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit & Decision_Buffer_Name); + E.Decision_Buffer := Indexed_Buffer (Decision_Buffer_Name); if MCDC_Coverage_Enabled then - E.MCDC_Buffer := - To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit & MCDC_Buffer_Name); + E.MCDC_Buffer := Indexed_Buffer (MCDC_Buffer_Name); end if; end if; end; @@ -6691,8 +6721,8 @@ package body Instrument.Ada_Unit is ---------------- function Probe_Main - (Dump_Config : Any_Dump_Config; - Info : in out Project_Info; + (Prj : Prj_Desc; + Dump_Config : Any_Dump_Config; Rewriter : Ada_Source_Rewriter'Class) return Main_Instrumentation_Description is @@ -6778,7 +6808,7 @@ package body Instrument.Ada_Unit is begin Expand_Main_Generic_Instantiation (Tmp.As_Generic_Subp_Instantiation, - Info, + Prj, Generic_Wrapper_Body_Filename, Generic_Wrapper_Body, Prelude, @@ -6829,7 +6859,7 @@ package body Instrument.Ada_Unit is procedure Expand_Main_Generic_Instantiation (Main : Generic_Subp_Instantiation; - Info : in out Project_Info; + Prj : Prj_Desc; Generic_Wrapper_Body_Filename : out Unbounded_String; Generic_Wrapper_Body : out Node_Rewriting_Handle; Prelude : out Node_Rewriting_Handle; @@ -6851,7 +6881,7 @@ package body Instrument.Ada_Unit is -- Wrap_Name (, "Prefix") = -- Wrap_Name (, "Prefix") = - Output_Dir : constant String := To_String (Info.Output_Dir); + Output_Dir : constant String := +Prj.Output_Dir; function Filename (Unit_Name : Node_Rewriting_Handle; Extension : String) return String; @@ -7244,6 +7274,19 @@ package body Instrument.Ada_Unit is end Has_Matching_Pragma_For_Unit; + -------------- + -- Has_Unit -- + -------------- + + function Has_Unit + (Context : Analysis_Context; + Unit : String; + Part : Analysis_Unit_Kind) return Boolean is + begin + return Context.Unit_Provider.Get.Get_Unit_Filename + (To_Text (Unit), Part) /= ""; + end Has_Unit; + ----------------------------------- -- Pragma_Restricts_Finalization -- ----------------------------------- @@ -7289,7 +7332,7 @@ package body Instrument.Ada_Unit is (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean is begin - return not Project.Runtime_Supports_Finalization + return not Has_Unit (Context, "Ada.Finalization", Unit_Specification) or else Has_Matching_Pragma_For_Unit (Context, Unit, Pragma_Restricts_Finalization'Access); end Finalization_Restricted_In_Unit; @@ -7347,9 +7390,11 @@ package body Instrument.Ada_Unit is (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean is begin - return not Project.Runtime_Supports_Task_Termination - or else Has_Matching_Pragma_For_Unit - (Context, Unit, Pragma_Prevents_Task_Termination'Access); + return not Has_Unit (Context, "Ada.Task.Termination", Unit_Specification) + or else not Has_Unit + (Context, "Ada.Task.Identification", Unit_Specification) + or else Has_Matching_Pragma_For_Unit + (Context, Unit, Pragma_Prevents_Task_Termination'Access); end Task_Termination_Restricted; ----------- @@ -7508,11 +7553,10 @@ package body Instrument.Ada_Unit is ------------------------------- overriding procedure Auto_Dump_Buffers_In_Main - (Self : in out Ada_Instrumenter_Type; - Filename : String; - Instr_Units : CU_Name_Vectors.Vector; - Dump_Config : Any_Dump_Config; - Info : in out Project_Info) + (Self : in out Ada_Instrumenter_Type; + Filename : String; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc) is Rewriter : Ada_Source_Rewriter; RH : Rewriting_Handle renames Rewriter.Handle; @@ -7522,17 +7566,14 @@ package body Instrument.Ada_Unit is Desc : Main_Instrumentation_Description; begin - if Instr_Units.Is_Empty then - return; - end if; - Start_Rewriting (Rewriter, Self, Info, Filename); + Start_Rewriting (Rewriter, Self, Prj, Filename); -- Try to detect the structure of this main, to determine how to insert -- the dump of coverage buffers. In case of failure, let Probe_Main emit -- a warning and do nothing. begin - Desc := Probe_Main (Dump_Config, Info, Rewriter); + Desc := Probe_Main (Prj, Dump_Config, Rewriter); exception when Cannot_Instrument_Main_Error => return; @@ -7542,8 +7583,8 @@ package body Instrument.Ada_Unit is Emit_Dump_Helper_Unit (Dump_Config, - Info, - Filename, + Self, + Prj, Desc.Main, Helper_Unit, Override_Dump_Trigger => Desc.Actual_Dump_Trigger, @@ -7671,14 +7712,13 @@ package body Instrument.Ada_Unit is ---------------------------- procedure Instrument_Source_File - (CU_Name : Compilation_Unit_Name; - Unit_Info : Instrumented_Unit_Info; - Prj_Info : in out Project_Info; + (UIC : in out Ada_Unit_Inst_Context; + Filename : String; Instrumenter : in out Ada_Instrumenter_Type; - UIC : out Ada_Unit_Inst_Context) + Prj : Prj_Desc) is + CU_Name : Compilation_Unit_Name (Language_Kind => Unit_Based_Language); Rewriter : Ada_Source_Rewriter; - Filename : constant String := To_String (Unit_Info.Filename); Dummy_Ctx : constant Context_Handle := Create_Context ("Instrumenting " & Filename); @@ -7696,7 +7736,7 @@ package body Instrument.Ada_Unit is -- Whether there is a pragma Short_Circuit_And_Or that applies to this -- unit. begin - Start_Rewriting (Rewriter, Instrumenter, Prj_Info, Filename); + Start_Rewriting (Rewriter, Instrumenter, Prj, Filename); Root_Analysis_Unit := Rewriter.Rewritten_Unit; @@ -7705,6 +7745,13 @@ package body Instrument.Ada_Unit is UIC.Root_Unit := Root_Analysis_Unit.Root.As_Compilation_Unit; + CU_Name.Part := + (case UIC.Root_Unit.P_Unit_Kind is + when Unit_Body => Unit_Body, + when Unit_Specification => Unit_Spec); + CU_Name.Unit := To_Qualified_Name + (UIC.Root_Unit.P_Decl.P_Fully_Qualified_Name_Array); + begin Preelab := (UIC.Root_Unit.P_Is_Preelaborable or else UIC.Root_Unit.P_Has_Restriction @@ -7723,7 +7770,22 @@ package body Instrument.Ada_Unit is Preelab := False; end; - Initialize_Rewriting (Instrumenter, UIC, CU_Name); + -- Reset the unit inst context for the currently instrumented source + -- file. + + UIC.Annotations.Clear; + UIC.Current_Scope_Entity := null; + UIC.Degenerate_Subprogram_Index := 0; + UIC.Source_Decisions := Source_Decision_Vectors.Empty; + UIC.Source_Conditions := Source_Condition_Vectors.Empty; + UIC.Unit_Bits.Last_Statement_Bit := No_Bit_Id; + UIC.Unit_Bits.Last_Outcome_Bit := No_Bit_Id; + UIC.Unit_Bits.Last_Path_Bit := No_Bit_Id; + UIC.Unit_Bits.Decision_Bits := LL_Decision_SCO_Bit_Allocs.Empty; + UIC.Unit_Bits.Statement_Bits := LL_Statement_SCO_Bit_Allocs.Empty; + + Initialize_Rewriting (UIC, Instrumenter); + UIC.Instrumented_Unit := CU_Name; begin Has_Pragma_SCAO := UIC.Root_Unit.P_Config_Pragmas @@ -7755,6 +7817,7 @@ package body Instrument.Ada_Unit is (Filename, Kind => Files_Table.Source_File, Indexed_Simple_Name => True); + UIC.Fullname := +Filename; UIC.Unit_Bits.SFI := UIC.SFI; -- Then run SCOs generation. This inserts calls to witness @@ -7929,6 +7992,19 @@ package body Instrument.Ada_Unit is -- Emit the instrumented source file Rewriter.Apply; + + -- Track which CU_Id maps to which instrumented unit + + Instrumented_Unit_CUs.Insert (CU_Name, UIC.CU); + + -- Update the Ignore_Status of the CU we instrumented + + Files_Table.Consolidate_Ignore_Status + (Index => Files_Table.Get_Index_From_Generic_Name + (Name => Filename, + Kind => Files_Table.Source_File, + Indexed_Simple_Name => True), + Status => Files_Table.Never); end Instrument_Source_File; ----------------------- @@ -7942,21 +8018,36 @@ package body Instrument.Ada_Unit is Qualified_Name_Slug (To_Qualified_Name (Project_Name)); begin return Ada_Identifier_Vectors."&" - (Sys_Buffers_Lists, - Instrument.Ada_Identifier (+Project_Name_Slug)); + (Sys_Buffers_Lists, Instrument.Ada_Identifier (+Project_Name_Slug)); end Buffers_List_Unit; + ----------------- + -- Buffer_Unit -- + ----------------- + + function Buffer_Unit + (Unit_Name : Ada_Qualified_Name) return Ada_Qualified_Name + is + Simple_Name : Ada_Identifier; + begin + Append (Simple_Name, "B"); + Append (Simple_Name, Ada_Identifier (+Qualified_Name_Slug (Unit_Name))); + return CU_Name : Ada_Qualified_Name := Sys_Buffers do + CU_Name.Append (Simple_Name); + end return; + end Buffer_Unit; + ---------------------- -- Pure_Buffer_Unit -- ---------------------- function Pure_Buffer_Unit - (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name + (Unit_Name : Ada_Qualified_Name) return Ada_Qualified_Name is Simple_Name : Instrument.Ada_Identifier; begin Append (Simple_Name, 'P'); - Append (Simple_Name, Instrumented_Unit_Slug (Instrumented_Unit)); + Append (Simple_Name, Ada_Identifier (+Qualified_Name_Slug (Unit_Name))); return CU_Name : Ada_Qualified_Name := Sys_Buffers do CU_Name.Append (Simple_Name); end return; @@ -7967,153 +8058,180 @@ package body Instrument.Ada_Unit is ---------------------- procedure Emit_Buffer_Unit - (Info : in out Project_Info; UIC : Ada_Unit_Inst_Context'Class) + (Buffer_Unit : Compilation_Unit_Name; + Prj : Prj_Desc; + Unit : Project_Unit; + Unit_Bits : Allocated_Bits_Vectors.Vector; + CU_Names : CU_Name_Vectors.Vector; + CUs : CU_Id_Vectors.Vector) is - CU_Name : Compilation_Unit_Name renames UIC.Buffer_Unit; - File : Text_Files.File_Type; + Pkg_Name : constant String := To_Ada (Buffer_Unit.Unit); + -- Package name for the buffer unit + File : Text_Files.File_Type; + Last_Buffer_Index : constant Natural := Natural (Unit_Bits.Length); begin - Create_File (Info, - File, - To_Filename (Info.Project, CU_Name, Switches.Ada_Language)); + Create_File (Prj, File, To_Filename (Prj, Ada_Language, Buffer_Unit)); Put_Warnings_And_Style_Checks_Pragmas (File); File.Put_Line ("with Interfaces.C; use Interfaces.C;"); File.Put_Line ("with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists;"); - declare - Pkg_Name : constant String := To_Ada (CU_Name.Unit); - -- Package name for the buffer unit - - Fingerprint : Unbounded_String; - -- Fingerprint for the instrumented unit - - Unit_Name : constant String := Ada.Characters.Handling.To_Lower - (To_Ada (UIC.Instrumented_Unit.Unit)); - -- Lower-case name for the instrumented unit - - Unit_Part : constant String := - (case UIC.Instrumented_Unit.Part is - when GPR.Unit_Spec => "Unit_Spec", - when GPR.Unit_Body => "Unit_Body", - when GPR.Unit_Separate => "Unit_Separate"); - -- Do not use 'Image so that we use the original casing for the - -- enumerators, and thus avoid compilation warnings/errors. - - Statement_Last_Bit : constant String := Img - (UIC.Unit_Bits.Last_Statement_Bit); - Decision_Last_Bit : constant String := Img - (UIC.Unit_Bits.Last_Outcome_Bit); - MCDC_Last_Bit : constant String := Img - (UIC.Unit_Bits.Last_Path_Bit); - - begin - -- Turn the fingerprint value into the corresponding Ada literal + File.Put_Line ("package " & Pkg_Name & " is"); + File.New_Line; + File.Put_Line (" pragma Preelaborate;"); + File.New_Line; + for I in 1 .. Last_Buffer_Index loop declare - First : Boolean := True; - begin - Append (Fingerprint, "("); - for Byte of SC_Obligations.Fingerprint (UIC.CU) loop - if First then - First := False; - else - Append (Fingerprint, ", "); - end if; - Append (Fingerprint, Strings.Img (Integer (Byte))); - end loop; - Append (Fingerprint, ")"); - end; - - File.Put_Line ("package " & Pkg_Name & " is"); - File.New_Line; - File.Put_Line (" pragma Preelaborate;"); - File.New_Line; + Unit_Bit : constant Allocated_Bits := Unit_Bits.Element (I); + CU_Name : constant Compilation_Unit_Name := CU_Names.Element (I); + CU : constant CU_Id := CUs.Element (I); + + Fingerprint : Unbounded_String; + -- Fingerprint for the instrumented unit + + Unit_Name : constant String := Ada.Characters.Handling.To_Lower + (To_Ada (CU_Name.Unit)); + -- Lower-case name for the instrumented unit + + Unit_Part : constant String := + (case CU_Name.Part is + when GPR.Unit_Spec => "Unit_Spec", + when GPR.Unit_Body => "Unit_Body", + when GPR.Unit_Separate => "Unit_Separate"); + -- Do not use 'Image so that we use the original casing for the + -- enumerators, and thus avoid compilation warnings/errors. + + Statement_Last_Bit : constant String := Img + (Unit_Bit.Last_Statement_Bit); + Decision_Last_Bit : constant String := Img + (Unit_Bit.Last_Outcome_Bit); + MCDC_Last_Bit : constant String := Img + (Unit_Bit.Last_Path_Bit); + + Suffix : constant String := "_" & Img (I); - -- Create declarations for individual buffers (statement, decision - -- and MC/DC) as well as their exported addresses. - - File.Put_Line (" Statement_Buffer : Coverage_Buffer_Type" - & " (0 .. " & Statement_Last_Bit & ") :=" - & " (others => False);"); - File.Put_Line (" Statement_Buffer_Address : constant System.Address" - & " := Statement_Buffer'Address;"); - File.Put_Line (" pragma Export (C, Statement_Buffer_Address, """ - & Statement_Buffer_Symbol (UIC.Instrumented_Unit) - & """);"); - File.New_Line; + begin + -- Turn the fingerprint value into the corresponding Ada literal - File.Put_Line (" Decision_Buffer : Coverage_Buffer_Type" - & " (0 .. " & Decision_Last_Bit & ") :=" - & " (others => False);"); - File.Put_Line (" Decision_Buffer_Address : constant System.Address" - & " := Decision_Buffer'Address;"); - File.Put_Line (" pragma Export (C, Decision_Buffer_Address, """ - & Decision_Buffer_Symbol (UIC.Instrumented_Unit) - & """);"); - File.New_Line; + declare + First : Boolean := True; + begin + Append (Fingerprint, "("); + for Byte of SC_Obligations.Fingerprint (CU) loop + if First then + First := False; + else + Append (Fingerprint, ", "); + end if; + Append (Fingerprint, Strings.Img (Integer (Byte))); + end loop; + Append (Fingerprint, ")"); + end; - File.Put_Line (" MCDC_Buffer : Coverage_Buffer_Type" - & " (0 .. " & MCDC_Last_Bit & ") :=" - & " (others => False);"); - File.Put_Line (" MCDC_Buffer_Address : constant System.Address" - & " := MCDC_Buffer'Address;"); - File.Put_Line (" pragma Export (C, MCDC_Buffer_Address, """ - & MCDC_Buffer_Symbol (UIC.Instrumented_Unit) - & """);"); - File.New_Line; + -- Create declarations for individual buffers (statement, decision + -- and MC/DC) as well as their exported addresses. Put this in + -- an individual package, to avoid having to suffix each + -- declaration + + File.Put_Line ("package Buffers" & Suffix & " is"); + + File.Put_Line (" Statement_Buffer" + & " : Coverage_Buffer_Type" + & " (0 .. " & Statement_Last_Bit & ") :=" + & " (others => False);"); + File.Put_Line (" Statement_Buffer_Address" + & " : constant System.Address" + & " := Statement_Buffer'Address;"); + File.Put_Line (" pragma Export (C, Statement_Buffer_Address, """ + & Statement_Buffer_Symbol (CU_Name) & Suffix + & """);"); + File.New_Line; - -- Create the GNATcov_RTS_Coverage_Buffers record + File.Put_Line (" Decision_Buffer : Coverage_Buffer_Type" + & " (0 .. " & Decision_Last_Bit & ") :=" + & " (others => False);"); + File.Put_Line (" Decision_Buffer_Address" + & " : constant System.Address" + & " := Decision_Buffer'Address;"); + File.Put_Line (" pragma Export (C, Decision_Buffer_Address, """ + & Decision_Buffer_Symbol (CU_Name) & Suffix + & """);"); + File.New_Line; - File.Put_Line (" Unit_Name : constant String := """ & Unit_Name - & """;"); - File.Put_Line (" Project_Name : constant String := """";"); - File.New_Line; + File.Put_Line (" MCDC_Buffer : Coverage_Buffer_Type" + & " (0 .. " & MCDC_Last_Bit & ") :=" + & " (others => False);"); + File.Put_Line (" MCDC_Buffer_Address : constant System.Address" + & " := MCDC_Buffer'Address;"); + File.Put_Line (" pragma Export (C, MCDC_Buffer_Address, """ + & MCDC_Buffer_Symbol (CU_Name) + & Suffix & """);"); + File.New_Line; - File.Put_Line (" Buffers : aliased constant" - & " GNATcov_RTS_Coverage_Buffers :="); - File.Put_Line - (" (Fingerprint => " - & Format_Fingerprint (SC_Obligations.Fingerprint (UIC.CU)) & ","); + -- Create the GNATcov_RTS_Coverage_Buffers record - File.Put_Line (" Language => Unit_Based_Language,"); - File.Put_Line (" Unit_Part => " & Unit_Part & ","); - File.Put_Line (" Unit_Name =>" - & " (Unit_Name'Address, Unit_Name'Length),"); + File.Put_Line (" Unit_Name : constant String := """ + & Unit_Name & """;"); + File.Put_Line (" Project_Name : constant String := """";"); + File.New_Line; - File.Put_Line (" Project_Name =>" - & " (Project_Name'Address, Project_Name'Length),"); + File.Put_Line (" Buffers : aliased constant" + & " GNATcov_RTS_Coverage_Buffers :="); + File.Put_Line (" (Fingerprint => " + & Format_Fingerprint + (SC_Obligations.Fingerprint (CU)) + & ","); + + File.Put_Line (" Language => Unit_Based_Language,"); + File.Put_Line (" Unit_Part => " & Unit_Part & ","); + File.Put_Line (" Unit_Name =>" + & " (Unit_Name'Address, Unit_Name'Length),"); + + File.Put_Line (" Project_Name =>" + & " (Project_Name'Address, Project_Name'Length),"); + + File.Put_Line (" Bit_Maps_Fingerprint => " + & Format_Fingerprint + (SC_Obligations.Bit_Maps_Fingerprint (CU)) + & ","); + + File.Put_Line (" Statement => Statement_Buffer'Address,"); + File.Put_Line (" Decision => Decision_Buffer'Address,"); + File.Put_Line (" MCDC => MCDC_Buffer'Address,"); + + File.Put_Line (" Statement_Last_Bit => " & Statement_Last_Bit + & ","); + File.Put_Line (" Decision_Last_Bit => " & Decision_Last_Bit + & ","); + File.Put_Line (" MCDC_Last_Bit => " & MCDC_Last_Bit & ");"); + File.Put_Line ("end Buffers" & Suffix & ";"); + File.New_Line; + end; + end loop; - File.Put_Line - (" Bit_Maps_Fingerprint => " - & Format_Fingerprint (SC_Obligations.Bit_Maps_Fingerprint (UIC.CU)) - & ","); - - File.Put_Line (" Statement => Statement_Buffer'Address,"); - File.Put_Line (" Decision => Decision_Buffer'Address,"); - File.Put_Line (" MCDC => MCDC_Buffer'Address,"); - - File.Put_Line (" Statement_Last_Bit => " & Statement_Last_Bit - & ","); - File.Put_Line (" Decision_Last_Bit => " & Decision_Last_Bit - & ","); - File.Put_Line (" MCDC_Last_Bit => " & MCDC_Last_Bit & ");"); - File.New_Line; + -- Create the buffers group - -- Create the buffers group + File.Put_Line + (" Buffers_Group : aliased constant Coverage_Buffers_Group :="); + File.Put (" ("); - File.Put_Line - (" Buffers_Group : aliased constant Coverage_Buffers_Group :=" - & " (1 => Buffers'Access);"); - File.Put_Line - (" C_Buffers_Group : aliased constant" - & " GNATcov_RTS_Coverage_Buffers_Group :=" - & " (1, Buffers_Group'Address);"); - File.Put_Line (" pragma Export (C, C_Buffers_Group, """ - & Unit_Buffers_Name (UIC.Instrumented_Unit) & """);"); - File.New_Line; + for I in 1 .. Last_Buffer_Index loop + File.Put (Img (I) & " => Buffers_" & Img (I) & ".Buffers'Access"); + if I /= Last_Buffer_Index then + File.Put_Line (","); + end if; + end loop; + File.Put_Line (");"); + File.Put_Line + (" C_Buffers_Group : aliased constant" + & " GNATcov_RTS_Coverage_Buffers_Group :=" + & " (" & Last_Buffer_Index'Image & ", Buffers_Group'Address);"); + File.Put_Line (" pragma Export (C, C_Buffers_Group, """ + & Unit_Buffers_Name (Unit) & """);"); + File.New_Line; - File.Put_Line ("end " & Pkg_Name & ";"); - end; + File.Put_Line ("end " & Pkg_Name & ";"); end Emit_Buffer_Unit; --------------------------- @@ -8121,11 +8239,14 @@ package body Instrument.Ada_Unit is --------------------------- procedure Emit_Pure_Buffer_Unit - (Info : in out Project_Info; UIC : Ada_Unit_Inst_Context'Class) + (PB_Unit : Compilation_Unit_Name; + Prj : Prj_Desc; + CU_Names : CU_Name_Vectors.Vector; + Language_Version : Unbounded_Wide_Wide_String; + Degenerate_Subprogram_Generics : Generic_Subp_Vectors.Vector) is - - CU_Name : Compilation_Unit_Name := UIC.Pure_Buffer_Unit; - Pkg_Name : constant String := To_Ada (CU_Name.Unit); + Last_Buffer_Index : constant Natural := Natural (CU_Names.Length); + Pkg_Name : constant String := To_Ada (PB_Unit.Unit); File : Text_Files.File_Type; procedure Put_Language_Version_Pragma; @@ -8139,10 +8260,10 @@ package body Instrument.Ada_Unit is procedure Put_Language_Version_Pragma is begin - if Length (UIC.Language_Version_Pragma) > 0 then + if Length (Language_Version) > 0 then File.Put_Line ("pragma " - & To_String (To_Wide_Wide_String (UIC.Language_Version_Pragma)) + & To_String (To_Wide_Wide_String (Language_Version)) & ";"); File.New_Line; end if; @@ -8151,9 +8272,7 @@ package body Instrument.Ada_Unit is -- Start of processing for Emit_Pure_Buffer_Unit begin - Create_File (Info, - File, - To_Filename (Info.Project, CU_Name, Switches.Ada_Language)); + Create_File (Prj, File, To_Filename (Prj, Ada_Language, PB_Unit)); Put_Warnings_And_Style_Checks_Pragmas (File); Put_Language_Version_Pragma; @@ -8167,23 +8286,32 @@ package body Instrument.Ada_Unit is File.New_Line; File.Put_Line (" pragma Pure;"); File.New_Line; - File.Put_Line (" Statement_Buffer : constant System.Address;"); - File.Put_Line (" pragma Import (C, Statement_Buffer, """ - & Statement_Buffer_Symbol (UIC.Instrumented_Unit) - & """);"); - File.New_Line; - File.Put_Line (" Decision_Buffer : constant System.Address;"); - File.Put_Line (" pragma Import (C, Decision_Buffer, """ - & Decision_Buffer_Symbol (UIC.Instrumented_Unit) - & """);"); - File.New_Line; - File.Put_Line (" MCDC_Buffer : constant System.Address;"); - File.Put_Line (" pragma Import (C, MCDC_Buffer, """ - & MCDC_Buffer_Symbol (UIC.Instrumented_Unit) - & """);"); - File.New_Line; + for I in 1 .. Last_Buffer_Index loop + declare + Suffix : constant String := "_" & Img (I); + CU_Name : constant Compilation_Unit_Name := CU_Names.Element (I); + begin + File.Put_Line ("package Buffers" & Suffix & " is"); + File.Put_Line (" Statement_Buffer : constant System.Address;"); + File.Put_Line (" pragma Import (C, Statement_Buffer, """ + & Statement_Buffer_Symbol (CU_Name) & Suffix + & """);"); + File.New_Line; + File.Put_Line (" Decision_Buffer : constant System.Address;"); + File.Put_Line (" pragma Import (C, Decision_Buffer, """ + & Decision_Buffer_Symbol (CU_Name) & Suffix + & """);"); + File.New_Line; + File.Put_Line (" MCDC_Buffer : constant System.Address;"); + File.Put_Line (" pragma Import (C, MCDC_Buffer, """ + & MCDC_Buffer_Symbol (CU_Name) & Suffix & """);"); + File.New_Line; + File.Put_Line ("end Buffers" & Suffix & ";"); + File.New_Line; + end; + end loop; - for G of UIC.Degenerate_Subprogram_Generics loop + for G of Degenerate_Subprogram_Generics loop File.Put_Line (" " & To_String (To_Wide_Wide_String (G.Generic_Subp_Decl))); end loop; @@ -8194,28 +8322,31 @@ package body Instrument.Ada_Unit is Text_Files.Run_GNATpp (File); end if; - if not UIC.Degenerate_Subprogram_Generics.Is_Empty then - CU_Name.Part := GNATCOLL.Projects.Unit_Body; + if not Degenerate_Subprogram_Generics.Is_Empty then + declare + PB_Unit_Body : Compilation_Unit_Name := PB_Unit; + begin + PB_Unit_Body.Part := GNATCOLL.Projects.Unit_Body; - Create_File - (Info, - File, - To_Filename (Info.Project, CU_Name, Switches.Ada_Language)); + Create_File + (Prj, File, To_Filename (Prj, Ada_Language, PB_Unit_Body)); - Put_Warnings_And_Style_Checks_Pragmas (File); - Put_Language_Version_Pragma; - File.Put_Line ("package body " & Pkg_Name & " is"); - File.New_Line; - for G of UIC.Degenerate_Subprogram_Generics loop - File.Put_Line - (" " & To_String (To_Wide_Wide_String (G.Generic_Subp_Body))); - end loop; - File.Put_Line ("end " & Pkg_Name & ";"); + Put_Warnings_And_Style_Checks_Pragmas (File); + Put_Language_Version_Pragma; + File.Put_Line ("package body " & Pkg_Name & " is"); + File.New_Line; + for G of Degenerate_Subprogram_Generics loop + File.Put_Line + (" " + & To_String (To_Wide_Wide_String (G.Generic_Subp_Body))); + end loop; + File.Put_Line ("end " & Pkg_Name & ";"); - Text_Files.Close (File); - if Switches.Pretty_Print then - Text_Files.Run_GNATpp (File); - end if; + Text_Files.Close (File); + if Switches.Pretty_Print then + Text_Files.Run_GNATpp (File); + end if; + end; end if; end Emit_Pure_Buffer_Unit; @@ -8225,16 +8356,13 @@ package body Instrument.Ada_Unit is procedure Emit_Dump_Helper_Unit (Dump_Config : Any_Dump_Config; - Info : in out Project_Info; - Main_Filename : String; + Instrumenter : Ada_Instrumenter_Type'Class; + Prj : Prj_Desc; Main : Compilation_Unit_Name; Helper_Unit : out Ada_Qualified_Name; Override_Dump_Trigger : Any_Dump_Trigger := Manual; Has_Controlled : Boolean := False) is - Root_Prj_Name : constant String := - Project.Project.Root_Project.Name; - File : Text_Files.File_Type; procedure Put_With (Unit : Ada_Qualified_Name); @@ -8294,13 +8422,13 @@ package body Instrument.Ada_Unit is -- trace file. Create_File - (Info, + (Prj, File, Name => To_Filename - (Info.Project, - CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Spec), - Switches.Ada_Language)); + (Prj, + Ada_Language, + CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Spec))); Put_Warnings_And_Style_Checks_Pragmas (File); Put_With (Sys_Buffers); @@ -8338,13 +8466,13 @@ package body Instrument.Ada_Unit is -- Emit the package body Create_File - (Info, + (Prj, File, Name => To_Filename - (Info.Project, - CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Body), - Switches.Ada_Language)); + (Prj, + Ada_Language, + CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Body))); Put_Warnings_And_Style_Checks_Pragmas (File); @@ -8360,7 +8488,7 @@ package body Instrument.Ada_Unit is end case; File.Put_Line - ("with " & To_Ada (Buffers_List_Unit (Root_Prj_Name)) & ";"); + ("with " & To_Ada (Buffers_List_Unit (+Prj.Prj_Name)) & ";"); File.Put_Line ("package body " & Helper_Unit_Name & " is"); File.New_Line; @@ -8375,12 +8503,10 @@ package body Instrument.Ada_Unit is File.Put (" ("); File.Put_Line - (To_Ada (Buffers_List_Unit (Root_Prj_Name)) & ".List,"); + (To_Ada (Buffers_List_Unit (+Prj.Prj_Name)) & ".List,"); case Dump_Config.Channel is when Binary_File => declare - use GNATCOLL.VFS; - U : constant String := To_Ada (Output_Unit); Indent1 : constant String := " "; Indent2 : constant String := Indent1 & " "; @@ -8391,14 +8517,8 @@ package body Instrument.Ada_Unit is else """" & To_String (Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := - (if Length (Dump_Config.Filename_Prefix) = 0 - then """" & String'(+Info.Project.Executable_Name - (File => +Main_Filename, - Include_Suffix => True)) & """" - else """" & To_String (Dump_Config.Filename_Prefix) - & """"); - Tag : constant String := - """" & Trace_Filename_Tag & """"; + """" & To_String (Dump_Config.Filename_Prefix) & """"; + Tag : constant String := """" & (+Instrumenter.Tag) & """"; Simple : constant String := (if Dump_Config.Filename_Simple then "True" @@ -8509,28 +8629,22 @@ package body Instrument.Ada_Unit is ---------------------------- overriding procedure Emit_Buffers_List_Unit - (Self : Ada_Instrumenter_Type; - Root_Project_Info : in out Project_Info; - Instr_Units : CU_Name_Vectors.Vector) + (Self : Ada_Instrumenter_Type; + Instr_Units : Unit_Sets.Set; + Prj : Prj_Desc) is - Prj_Name : constant String := Root_Project_Info.Project.Name; - CU_Name : constant Compilation_Unit_Name := + Buffers_CU_Name : constant Compilation_Unit_Name := CU_Name_For_Unit - (Buffers_List_Unit (Prj_Name), GNATCOLL.Projects.Unit_Spec); - File : Text_Files.File_Type; + (Buffers_List_Unit (+Prj.Prj_Name), GNATCOLL.Projects.Unit_Spec); + File : Text_Files.File_Type; begin -- Emit the unit to contain the list of buffers declare - Unit_Name_Str : constant String := To_Ada (CU_Name.Unit); + Unit_Name : constant String := To_Ada (Buffers_CU_Name.Unit); begin Create_File - (Root_Project_Info, - File, - To_Filename - (Root_Project_Info.Project, - CU_Name, - Switches.Ada_Language)); + (Prj, File, To_Filename (Prj, Ada_Language, Buffers_CU_Name)); Put_Warnings_And_Style_Checks_Pragmas (File); for Instr_Unit of Instr_Units loop @@ -8542,13 +8656,16 @@ package body Instrument.Ada_Unit is -- would not include them in the link as they would not be in the -- dependency closure. - if Instr_Unit.Language_Kind = Unit_Based_Language then - File.Put_Line ("with " & To_Ada (Buffer_Unit (Instr_Unit)) - & ";"); + if Instr_Unit.Language = Unit_Based_Language then + File.Put_Line + ("with " + & To_Ada + (Buffer_Unit (To_Qualified_Name (+Instr_Unit.Unit_Name))) + & ";"); end if; end loop; File.New_Line; - File.Put_Line ("package " & Unit_Name_Str & " is"); + File.Put_Line ("package " & Unit_Name & " is"); File.New_Line; File.Put_Line (" pragma Preelaborate;"); File.New_Line; @@ -8571,93 +8688,197 @@ package body Instrument.Ada_Unit is File.Put_Line (" List : constant GNATcov_RTS.Buffers.Lists" & ".Coverage_Buffers_Group_Array := ("); - for Cur in Instr_Units.Iterate loop - declare - use CU_Name_Vectors; - - Index : constant Positive := To_Index (Cur); - Index_Img : constant String := Img (To_Index (Cur)); - Buffer_Name : constant String := - Unit_Buffers_Name (Element (Cur)); - begin + declare + Index : Positive := 1; + Last : constant Natural := Natural (Instr_Units.Length); + begin + for Instr_Unit of Instr_Units loop File.Put - (" " & Index_Img & " => " & Buffer_Name & "'Access"); - if Index = Instr_Units.Last_Index then + (" " & Img (Index) & " => " + & Unit_Buffers_Name (Instr_Unit) & "'Access"); + if Index = Last then File.Put_Line (");"); else File.Put_Line (","); end if; - end; - end loop; + Index := Index + 1; + end loop; + end; + File.Put_Line (" C_List : constant GNATcov_RTS.Buffers.Lists" & ".GNATcov_RTS_Coverage_Buffers_Group_Array :="); File.Put_Line (" (" & Instr_Units.Length'Image - & " , List'Address);"); + & ", List'Address);"); File.Put_Line (" pragma Export (C, C_List, """ - & Unit_Buffers_Array_Name (Prj_Name) - & """);"); + & Unit_Buffers_Array_Name (+Prj.Prj_Name) & """);"); File.New_Line; - File.Put_Line ("end " & Unit_Name_Str & ";"); + File.Put_Line ("end " & Unit_Name & ";"); end; end Emit_Buffers_List_Unit; + ----------------------------- + -- Create_Ada_Instrumenter -- + ----------------------------- + + function Create_Ada_Instrumenter + (Tag : Unbounded_String; + Config_Pragmas_Filename, + Mapping_Filename : String; + Predefined_Source_Dirs : String_Vectors.Vector) + return Ada_Instrumenter_Type + is + Instrumenter : Ada_Instrumenter_Type; + begin + Instrumenter.Tag := Tag; + + -- First create the context for Libadalang + + Instrumenter.Provider := + Instrument.Ada_Unit_Provider.Create_Provider + (Predefined_Source_Dirs, Mapping_Filename); + + -- Create the event handler, to report when Libadalang cannot read a + -- required source file. + + Instrumenter.Event_Handler := Create_Missing_File_Reporter; + + -- Save the location of the file holding the configuration pragmas + + Instrumenter.Config_Pragmas_Filename := +Config_Pragmas_Filename; + + -- Then, create the analysis context + + Create_LAL_Context (Instrumenter); + return Instrumenter; + end Create_Ada_Instrumenter; + --------------------- -- Instrument_Unit -- --------------------- - overriding procedure Instrument_Unit - (Self : in out Ada_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Unit_Info : in out Instrumented_Unit_Info) + procedure Instrument_Unit + (Self : in out Ada_Instrumenter_Type; + Unit_Name : String; + Prj : Prj_Desc; + Files_Of_Interest : String_Sets.Set) is - Prj_Info : Project_Info renames Unit_Info.Prj_Info.all; - UIC : Ada_Unit_Inst_Context; + Allocated_Bits : Allocated_Bits_Vectors.Vector; + Last_Buffer_Index : Natural := 0; + CU_Names : CU_Name_Vectors.Vector; + CUs : CU_Id_Vectors.Vector; + Unit : constant Project_Unit := + (Language => Unit_Based_Language, Unit_Name => +Unit_Name); - Event_Handler : Missing_Src_Reporter renames - Missing_Src_Reporter_Access (Self.Event_Handler.Unchecked_Get).all; - -- Handle to the event handler we use to report missing source files + UIC : Ada_Unit_Inst_Context; - Filename : constant String := To_String (Unit_Info.Filename); - Basename : constant String := Ada.Directories.Simple_Name (Filename); - begin - -- If we are in verbose mode, we already printed the source file that - -- we are about to instrument. Otherwise, just get prepared to print it - -- in case we emit a "source file missing" warning through Libadalang's - -- event handler. + procedure Instrument_Source_File_Wrapper (Filename : String); + -- Wrapper around Instrument_Source_File. Instrument the given filename + -- if it is a file of interest. - if not Verbose then - Event_Handler.Instrumented_File := To_Unbounded_String (Basename); - end if; + ------------------------------------ + -- Instrument_Source_File_Wrapper -- + ------------------------------------ - -- Instrument the source file and create a unit to contain its coverage - -- buffers. + procedure Instrument_Source_File_Wrapper (Filename : String) + is + Event_Handler : Missing_Src_Reporter renames + Missing_Src_Reporter_Access (Self.Event_Handler.Unchecked_Get).all; + -- Handle to the event handler we use to report missing source files; - Instrument_Source_File - (CU_Name => CU_Name, - Unit_Info => Unit_Info, - Prj_Info => Prj_Info, - Instrumenter => Self, - UIC => UIC); - Emit_Buffer_Unit (Prj_Info, UIC); - Emit_Pure_Buffer_Unit (Prj_Info, UIC); + Basename : constant String := + Ada.Directories.Simple_Name (Filename); - -- Track which CU_Id maps to which instrumented unit + begin + -- Instrument the file only if it is a file of interest - Instrumented_Unit_CUs.Insert (CU_Name, UIC.CU); + if Files_Of_Interest.Contains (+Filename) then + + -- In verbose mode, always print a notice for the source file + -- that we are about to instrument. In non-verbose mode, just get + -- prepared to print it in case we emit a "source file missing" + -- warning through Libadalang's event handler. + + if Verbose then + Put_Line ("Instrumenting " & Basename); + else + Event_Handler.Instrumented_File := + To_Unbounded_String (Basename); + end if; + + Last_Buffer_Index := Last_Buffer_Index + 1; + UIC.Entities.Buffers_Index := Last_Buffer_Index; + Instrument_Source_File + (UIC => UIC, + Filename => Filename, + Instrumenter => Self, + Prj => Prj); + CU_Names.Append (UIC.Instrumented_Unit); + CUs.Append (UIC.CU); + Allocated_Bits.Append (UIC.Unit_Bits); + end if; + end Instrument_Source_File_Wrapper; + begin + -- Initialize the buffer unit to match the unit name. It will contain + -- coverage buffers for all parts of the unit: specification, body, + -- and separates. + + UIC.Buffer_Unit := + CU_Name_For_Unit + (Buffer_Unit (To_Qualified_Name (Unit_Name)), GPR.Unit_Spec); + UIC.Pure_Buffer_Unit := + CU_Name_For_Unit + (Pure_Buffer_Unit (To_Qualified_Name (Unit_Name)), GPR.Unit_Spec); + + -- Try to find the spec and / or the body for this compilation unit + -- using the unit provider. Then retrieve the separate unit from the + -- spec / body / both. + + for Part in Analysis_Unit_Kind loop + declare + function Convert (Part : Analysis_Unit_Kind) return Unit_Parts is + (case Part is + when Unit_Body => Unit_Body, + when Unit_Specification => Unit_Spec); + begin + if Self.Provider.Has_Unit (Unit_Name, Convert (Part)) then + Find_Ada_Units + (Self, + Self.Provider.Get_Unit_Filename + (Langkit_Support.Text.From_UTF8 (Unit_Name), Part), + Instrument_Source_File_Wrapper'Access); + end if; + end; + end loop; + + -- Once the unit was instrumented, emit the coverage buffer units + + Emit_Buffer_Unit + (Buffer_Unit => UIC.Buffer_Unit, + Prj => Prj, + Unit => Unit, + Unit_Bits => Allocated_Bits, + CU_Names => CU_Names, + CUs => CUs); + Emit_Pure_Buffer_Unit + (PB_Unit => UIC.Pure_Buffer_Unit, + Prj => Prj, + CU_Names => CU_Names, + Language_Version => UIC.Language_Version_Pragma, + Degenerate_Subprogram_Generics => UIC.Degenerate_Subprogram_Generics); end Instrument_Unit; + -------------------- + -- Find_Ada_Units -- + -------------------- + procedure Find_Ada_Units (Instrumenter : in out Ada_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info; - Process_Unit : access procedure - (CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info)) + Filename : String; + Process_Unit : access procedure (Filename : String)) is - use GNATCOLL.VFS; function Process_Node (N : LAL.Ada_Node'Class) return Visit_Status; @@ -8670,26 +8891,18 @@ package body Instrument.Ada_Unit is if N.Kind in Ada_Body_Stub then begin declare - Stub : constant LAL.Body_Stub := N.As_Body_Stub; - Subunit_FQN : constant LAL.Unbounded_Text_Type_Array := - Stub.P_Syntactic_Fully_Qualified_Name; - Subunit_Name : constant Compilation_Unit_Name := - CU_Name_For_Unit - (Unit => To_Qualified_Name (Subunit_FQN), - Part => GPR.Unit_Separate); - Subunit_Info : GPR.File_Info; + Stub : constant LAL.Body_Stub := N.As_Body_Stub; + Subunit_FQN : constant Text_Type := + Stub.P_Fully_Qualified_Name; begin if Subunit_FQN'Length = 0 then raise Property_Error; - elsif Unit_Info (Subunit_Name, Subunit_Info) then + else Find_Ada_Units (Instrumenter, - Subunit_Name, - Subunit_Info, - Process_Unit); - else - Warn ("cannot instrument " & Image (Subunit_Name) - & ": this unit does not belong to this project"); + Instrumenter.Context.Unit_Provider.Get + .Get_Unit_Filename (Subunit_FQN, Unit_Body), + Process_Unit); end if; end; exception @@ -8703,14 +8916,13 @@ package body Instrument.Ada_Unit is return Into; end Process_Node; - Input_Filename : constant String := +Info.File.Full_Name; - Unit : constant LAL.Analysis_Unit := - Get_From_File (Instrumenter, Input_Filename); + Unit : constant LAL.Analysis_Unit := + Get_From_File (Instrumenter, Filename); begin -- Abort if the input project is not compilable if Unit.Has_Diagnostics then - Outputs.Error ("instrumentation failed for " & Input_Filename); + Outputs.Error ("instrumentation failed for " & Filename); Outputs.Error ("please make sure the original project can be compiled"); for D of Unit.Diagnostics loop @@ -8730,7 +8942,7 @@ package body Instrument.Ada_Unit is -- unit. elsif Unit.Root.Kind = Ada_Compilation_Unit_List then - Outputs.Error ("instrumentation failed for " & Input_Filename); + Outputs.Error ("instrumentation failed for " & Filename); Outputs.Error ("source files containing multiple compilation units" & " are not supported"); raise Xcov_Exit_Exc; @@ -8740,7 +8952,7 @@ package body Instrument.Ada_Unit is declare CU : constant LAL.Compilation_Unit := Unit.Root.As_Compilation_Unit; begin - Process_Unit (CU_Name, Info); + Process_Unit (Filename); CU.Traverse (Process_Node'Access); end; end Find_Ada_Units; diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index ae4bf0ed3..9e7ee015e 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -28,74 +28,72 @@ with Langkit_Support.Text; use Langkit_Support.Text; with Libadalang.Analysis; use Libadalang.Analysis; with Libadalang.Rewriting; use Libadalang.Rewriting; -with Instrument.Common; use Instrument.Common; +with Files_Table; use Files_Table; +with Instrument.Ada_Unit_Provider; +with Instrument.Common; use Instrument.Common; with Switches; package Instrument.Ada_Unit is - type Ada_Instrumenter_Type is new Language_Instrumenter - with record - Provider : Libadalang.Analysis.Unit_Provider_Reference; - -- Unit provider to create an analysis context (Context member below) + type Ada_Instrumenter_Type is new Language_Instrumenter with + record + Provider : Instrument.Ada_Unit_Provider.Provider_Type; + -- Unit provider to create an analysis context (Context member + -- below). We use a custom provider there, to be able to turn + -- a filename to our Compilation_Unit_Name internal representation, + -- and to not depend on project files in the unit instrumentation + -- process. - Event_Handler : Libadalang.Analysis.Event_Handler_Reference; - -- Event handler to warn about missing source files + Event_Handler : Libadalang.Analysis.Event_Handler_Reference; + -- Event handler to warn about missing source files - Context : Libadalang.Analysis.Analysis_Context; - -- Libadalang context to load all units to rewrite + Config_Pragmas_Filename : Unbounded_String; + -- File holding the list of configuration pragmas - Get_From_File_Count : Natural; - -- Count how many times we called Context.Get_From_File. See the - -- Max_Get_From_File_Count constant. + Context : Libadalang.Analysis.Analysis_Context; + -- Libadalang context to load all units to rewrite - Language_Version : Any_Language_Version; - -- See the eponym arguments in Instrument.Intrument_Units_Of_Interest + Get_From_File_Count : Natural; + -- Count how many times we called Context.Get_From_File. See the + -- Max_Get_From_File_Count constant. - end record; + end record; -- Instrumentation primitives for Ada - function Create_Ada_Instrumenter - (Language_Version : Any_Language_Version) return Ada_Instrumenter_Type; - -- Create an Ada instrumenter from the given provider, and the given - -- language version. - overriding function Language (Self : Ada_Instrumenter_Type) return Switches.Src_Supported_Language is (Switches.Ada_Language); overriding procedure Instrument_Unit - (Self : in out Ada_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Unit_Info : in out Instrumented_Unit_Info); + (Self : in out Ada_Instrumenter_Type; + Unit_Name : String; + Prj : Prj_Desc; + Files_Of_Interest : String_Sets.Set); overriding procedure Auto_Dump_Buffers_In_Main - (Self : in out Ada_Instrumenter_Type; - Filename : String; - Instr_Units : CU_Name_Vectors.Vector; - Dump_Config : Any_Dump_Config; - Info : in out Project_Info); + (Self : in out Ada_Instrumenter_Type; + Filename : String; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc); overriding procedure Emit_Buffers_List_Unit - (Self : Ada_Instrumenter_Type; - Root_Project_Info : in out Project_Info; - Instr_Units : CU_Name_Vectors.Vector); - - overriding function Skip_Source_File (Self : Ada_Instrumenter_Type; - Source_File : GNATCOLL.Projects.File_Info) return Boolean - is (False); - - procedure Find_Ada_Units - (Instrumenter : in out Ada_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info; - Process_Unit : access procedure - (CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info)); - -- Consider that Info is a source file to instrument (i.e. a unit of - -- interest, CU_Name being the name of its compilation unit) and call - -- Process_Unit for all compilation units that must be instrumented with - -- it (i.e. related subunits, if present). + Instr_Units : Unit_Sets.Set; + Prj : Prj_Desc); + + function Create_Ada_Instrumenter + (Tag : Unbounded_String; + Config_Pragmas_Filename, + Mapping_Filename : String; + Predefined_Source_Dirs : String_Vectors.Vector) + return Ada_Instrumenter_Type; + -- Create an Ada instrumenter. Config_Pragmas_Filename is the fullname + -- to the configuration pragma file. Mapping_Filename is the fullname + -- to the mapping file, which maps unit names to file fullnames, and + -- Predefined_Source_Dirs is the list of directories hosting runtime + -- files. The two last parameters are used to instantiate our + -- custom unit provider, which does not rely on project files + -- (see Instrument.Ada_Unit_Provider). -- Private declarations relative to the AST traversal private @@ -216,6 +214,10 @@ private new Ada.Containers.Vectors (Natural, Source_Condition); type Instrumentation_Entities is record + Buffers_Index : Natural := 0; + -- Index into the set of this units' coverage buffers group for the + -- source file being instrumented. + Common_Buffers : Node_Rewriting_Handle := No_Node_Rewriting_Handle; -- Qualified name for the unit that contains coverage buffer types and -- witness subprograms. @@ -262,6 +264,9 @@ private type Ada_Unit_Inst_Context is new Instrument.Common.Unit_Inst_Context with record + Language_Version_Pragma : Unbounded_Wide_Wide_String; + -- Language version configuration pragma for unit, if any + CU : CU_Id := No_CU_Id; -- SCO identifier of the compilation unit being instrumented diff --git a/tools/gnatcov/instrument-ada_unit__stub.ads b/tools/gnatcov/instrument-ada_unit__stub.ads index 624b98d26..a1dddb09d 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.ads +++ b/tools/gnatcov/instrument-ada_unit__stub.ads @@ -29,20 +29,16 @@ package Instrument.Ada_Unit is type Ada_Instrumenter_Type is new Language_Instrumenter with null record; -- Common instrumentation primitives for Ada - function Create_Ada_Instrumenter - (Language_Version : Any_Language_Version) return Ada_Instrumenter_Type - is (Ada_Instrumenter_Type'(null record)); - overriding function Language (Self : Ada_Instrumenter_Type) return Src_Supported_Language is (Ada_Language); - procedure Find_Ada_Units - (Instrumenter : in out Ada_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info; - Process_Unit : access procedure - (CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info)) is null; + function Create_Ada_Instrumenter + (Tag : Unbounded_String; + Config_Pragmas_Filename, + Mapping_Filename : String; + Predefined_Source_Dirs : String_Vectors.Vector) + return Ada_Instrumenter_Type + is (Ada_Instrumenter_Type'(others => <>)); end Instrument.Ada_Unit; diff --git a/tools/gnatcov/instrument-ada_unit_provider.adb b/tools/gnatcov/instrument-ada_unit_provider.adb index cf0ad0b97..02bff2b50 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.adb +++ b/tools/gnatcov/instrument-ada_unit_provider.adb @@ -63,6 +63,8 @@ package body Instrument.Ada_Unit_Provider is Get_Line (Dependencies_File); begin Provider.Unit_Map.Insert (To_Lower (Unit_Name), File_Fullname); + Provider.Filename_Map.Insert + (File_Fullname, To_Lower (Unit_Name)); end; end loop; exception @@ -196,4 +198,22 @@ package body Instrument.Ada_Unit_Provider is end if; end Get_Unit; + -------------- + -- Has_Unit -- + -------------- + + function Has_Unit + (Provider : Provider_Type; + Unit_Name : String; + Unit_Part : Unit_Parts) return Boolean + is + Unit_Name_And_Part : constant String := + To_Lower (Unit_Name) + & (case Unit_Part is + when Unit_Spec => "%s", + when others => "%b"); + begin + return Provider.Unit_Map.Contains (Unit_Name_And_Part); + end Has_Unit; + end Instrument.Ada_Unit_Provider; diff --git a/tools/gnatcov/instrument-ada_unit_provider.ads b/tools/gnatcov/instrument-ada_unit_provider.ads index 3e2774b11..fd851e9a3 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.ads +++ b/tools/gnatcov/instrument-ada_unit_provider.ads @@ -65,9 +65,14 @@ package Instrument.Ada_Unit_Provider is overriding procedure Release (Provider : in out Provider_Type) is null; + function Has_Unit + (Provider : Provider_Type; + Unit_Name : String; + Unit_Part : Unit_Parts) return Boolean; + -- Returns whether given unit is in the provider unit closure + private - use US; use type GNATCOLL.VFS.Virtual_File; package String_Maps is new Ada.Containers.Indefinite_Hashed_Maps @@ -81,6 +86,9 @@ private Unit_Map : String_Maps.Map; -- Mapping from unit name to file fullnames + Filename_Map : String_Maps.Map; + -- Mapping from file fullnames to unit names + Runtime_Files : String_Maps.Map; -- Mapping from a runtime file basename to its fullname diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 726dbed6c..1da7cd9ed 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -26,9 +26,6 @@ with Clang.Extensions; use Clang.Extensions; with GNAT.OS_Lib; use GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; -with GNAT.Strings; - -with GNATCOLL.VFS; with Interfaces; use Interfaces; with Interfaces.C; use Interfaces.C; @@ -42,7 +39,6 @@ with Inputs; use Inputs; with Instrument.C_Utils; use Instrument.C_Utils; with Outputs; use Outputs; with Paths; use Paths; -with Project; use Project; with SCOs; with System; use System; with Table; @@ -50,7 +46,6 @@ with Text_Files; use Text_Files; package body Instrument.C is - package GPR renames GNATCOLL.Projects; package US renames Ada.Strings.Unbounded; function To_Chars_Ptr_Array @@ -61,19 +56,6 @@ package body Instrument.C is procedure Free (Self : in out chars_ptr_array); -- Free all strings in Self - function Compiler_Driver - (Project : GNATCOLL.Projects.Project_Type; - Language : C_Family_Language) return String; - -- Return the command name for the compiler for Language in the given - -- Project. - - function Source_Suffix - (Instrumenter : C_Family_Instrumenter_Type'Class; - Part : GNATCOLL.Projects.Unit_Parts; - Project : GNATCOLL.Projects.Project_Type) return String; - -- Return the filename suffix corresponding for Part files and the language - -- that Instrumenter handles in the given project. - procedure Filter_Annotations; -- Remove any exemption annotations from the map that intersects a -- statement SCO. This is not part of Import_Annotations as this is only @@ -92,16 +74,6 @@ package body Instrument.C is type Macro_Set_Access is access Macro_Set; type Macro_Set_Cst_Access is access constant Macro_Set; - package Compiler_Macros_Maps is new Ada.Containers.Hashed_Maps - (Key_Type => Unbounded_String, - Element_Type => Macro_Set_Access, - Equivalent_Keys => "=", - Hash => Ada.Strings.Unbounded.Hash); - Compiler_Macros : Compiler_Macros_Maps.Map; - -- Cache for computed compiler builtin macros, to avoid relaunching the - -- compiler command every time a file is instrumented. Used in the - -- Builtin_Macros function only. - function Builtin_Macros (Lang, Compiler, Std, Output_Dir : String) return Macro_Set_Cst_Access; @@ -117,8 +89,8 @@ package body Instrument.C is procedure Preprocess_Source (Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; PP_Filename : out Unbounded_String; - Info : in out Project_Info; Options : in out Analysis_Options); -- Preprocess the source at Filename and extend Options using the -- preprocessor output. @@ -305,40 +277,30 @@ package body Instrument.C is ---------------------------- procedure Record_PP_Info - (Unit_Info : Instrumented_Unit_Info; - UIC : in out C_Unit_Inst_Context); + (Orig_Filename : String; + UIC : in out C_Unit_Inst_Context; + Instrumenter : C_Family_Instrumenter_Type'Class); -- Emit the low-level SCOs for the given unit. Do not process them: this is -- left to the other (instrumentation) pass. - procedure Instrument_Source_File - (CU_Name : Compilation_Unit_Name; - Unit_Info : Instrumented_Unit_Info; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj_Info : in out Project_Info; - UIC : out C_Unit_Inst_Context); - -- Generate the instrumented source corresponding to CU_Name/Unit_Info. - -- Record instrumentation information in IC. - -- - -- If the unit to instrument is also a main and the buffers dump trigger - -- is not manual, instrumented code will also dump the coverage buffers. - ---------------------------- -- Source instrumentation -- ---------------------------- procedure Emit_Buffer_Unit - (Info : in out Project_Info; - UIC : C_Unit_Inst_Context'Class; - Instrumenter : C_Family_Instrumenter_Type'Class); + (UIC : C_Unit_Inst_Context'Class; + Unit : Project_Unit; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc); -- Emit the unit to contain coverage buffers for the given instrumented -- unit, for the given instrumenter. procedure Emit_Dump_Helper_Unit - (Dump_Config : Any_Dump_Config; - Info : in out Project_Info; - Main : Compilation_Unit_Name; - Helper_Unit : out US.Unbounded_String; - Instrumenter : C_Family_Instrumenter_Type'Class); + (Dump_Config : Any_Dump_Config; + Main : Compilation_Unit_Name; + Helper_Unit : out US.Unbounded_String; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc); -- Emit the unit to contain helpers to implement the automatic dump of -- coverage buffers for the given Main unit. Info must be the project that -- owns this main. Upon return, the name of this helper unit is stored in @@ -349,9 +311,9 @@ package body Instrument.C is procedure Start_Rewriting (Self : out C_Source_Rewriter; - Info : in out Project_Info; Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; Preprocessed : Boolean := False); -- Start a rewriting session for the given file identified by its full -- name. @@ -475,24 +437,6 @@ package body Instrument.C is end loop; end Free; - --------------------- - -- Compiler_Driver -- - --------------------- - - function Compiler_Driver - (Project : GNATCOLL.Projects.Project_Type; - Language : C_Family_Language) return String is - begin - return Result : constant String := - GNATCOLL.Projects.Attribute_Value - (Project, GPR.Compiler_Driver_Attribute, Image (Language)) - do - if Result = "" then - Fatal_Error ("could not find a compiler for " & Image (Language)); - end if; - end return; - end Compiler_Driver; - ------------------------ -- Filter_Annotations -- ------------------------ @@ -534,47 +478,6 @@ package body Instrument.C is end loop; end Filter_Annotations; - ------------------- - -- Source_Suffix -- - ------------------- - - function Source_Suffix - (Instrumenter : C_Family_Instrumenter_Type'Class; - Part : GNATCOLL.Projects.Unit_Parts; - Project : GNATCOLL.Projects.Project_Type) return String - is - L : constant C_Family_Language := Instrumenter.Language; - Attr : constant GPR.Attribute_Pkg_String := - GPR.Build - (Package_Name => "Naming", - Attribute_Name => - (case Part is - when GPR.Unit_Body => "Body_Suffix", - when GPR.Unit_Spec => "Spec_Suffix", - when GPR.Unit_Separate => raise Program_Error)); - begin - case Part is - when GPR.Unit_Body => - return Project.Attribute_Value - (Attribute => Attr, - Index => Image (L), - Default => (case L is - when C_Language => ".c", - when CPP_Language => ".cpp")); - - when GPR.Unit_Spec => - return Project.Attribute_Value - (Attribute => Attr, - Index => Image (L), - Default => (case L is - when C_Language => ".h", - when CPP_Language => ".hh")); - - when GPR.Unit_Separate => - return (raise Program_Error); - end case; - end Source_Suffix; - ----------------- -- Enter_Scope -- ----------------- @@ -2496,82 +2399,68 @@ package body Instrument.C is (Lang, Compiler, Std, Output_Dir : String) return Macro_Set_Cst_Access is use Ada.Characters.Handling; - use Compiler_Macros_Maps; + + PID : constant Unsigned_64 := + Unsigned_64 (Pid_To_Integer (Current_Process_Id)); L : constant String := To_Lower (Lang); Key : constant Unbounded_String := +Compiler & " -x " & L & " " & Std; - Cur : constant Cursor := Compiler_Macros.Find (Key); - Result : Macro_Set_Access; + Result : constant Macro_Set_Access := new Macro_Set; + + Args : String_Vectors.Vector; + Basename : constant String := + Ada.Directories.Simple_Name (Compiler) + & "_builtins_" + & Hex_Image (PID); + Filename : constant String := Output_Dir / Basename; + File : Ada.Text_IO.File_Type; begin - -- If we already computed builtin macros for Compiler, return the cached - -- result. Compute it now otherwise. + -- Run the preprocessor on an empty file and write the + -- preprocessed sources to Filename. - if Has_Element (Cur) then - Result := Element (Cur); - - else - Result := new Macro_Set; + Args.Append (+"-x"); + Args.Append (+L); + if Std'Length /= 0 then + Args.Append (+Std); + end if; + Args.Append (+"-E"); + Args.Append (+"-dM"); + Args.Append (+"-"); + + Run_Command + (Command => Compiler, + Arguments => Args, + Origin_Command_Name => + "getting built-in macros for " & (+Key), + Output_File => Filename, + In_To_Null => True); + + -- Decode all macro definitions in Filename and store them in Result + + Open (File, In_File, Filename); + while not End_Of_File (File) loop declare - Args : String_Vectors.Vector; - Basename : constant String := - Ada.Directories.Simple_Name (Compiler) & "_builtins"; - Filename : constant String := Output_Dir / Basename; - File : Ada.Text_IO.File_Type; + Line : constant String := Get_Line (File); + Macro_Def : Macro_Definition (Define => True); + Success : Boolean; begin - -- Run the preprocessor on an empty file and write the - -- preprocessed sources to Filename. - - Args.Append (+"-x"); - Args.Append (+L); - if Std'Length /= 0 then - Args.Append (+Std); + Parse_Macro_Definition + (Line, + Macro_Def, + Success); + if Success then + Result.Include (Macro_Def); + else + Warn + ("Cannot parse a built-in macro definition for " + & Compiler & ", ignoring it:" & ASCII.LF & " " + & Line); end if; - Args.Append (+"-E"); - Args.Append (+"-dM"); - Args.Append (+"-"); - - Run_Command - (Command => Compiler, - Arguments => Args, - Origin_Command_Name => - "getting built-in macros for " & (+Key), - Output_File => Filename, - In_To_Null => True); - - -- Decode all macro definitions in Filename and store them in - -- Result. - - Open (File, In_File, Filename); - while not End_Of_File (File) loop - declare - Line : constant String := Get_Line (File); - Macro_Def : Macro_Definition (Define => True); - Success : Boolean; - begin - Parse_Macro_Definition - (Line, - Macro_Def, - Success); - if Success then - Result.Include (Macro_Def); - else - Warn - ("Cannot parse a built-in macro definition for " - & Compiler & ", ignoring it:" & ASCII.LF & " " - & Line); - end if; - end; - end loop; - Close (File); - Delete_File (Filename); - - -- Save Result in the cache for later use - - Compiler_Macros.Insert (Key, Result); end; - end if; - + end loop; + Close (File); + Delete_File (Filename); return Macro_Set_Cst_Access (Result); end Builtin_Macros; @@ -2582,8 +2471,8 @@ package body Instrument.C is procedure Preprocess_Source (Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; PP_Filename : out Unbounded_String; - Info : in out Project_Info; Options : in out Analysis_Options) is Cmd : Command_Type; @@ -2596,31 +2485,26 @@ package body Instrument.C is Unsigned_64 (Pid_To_Integer (Current_Process_Id)); Preprocessed_Filename : constant String := - (+Info.Output_Dir) / ("pp-" & Strip_Zero_Padding (Hex_Image (PID))); + (+Prj.Output_Dir) / ("pp-" & Strip_Zero_Padding (Hex_Image (PID))); -- Preprocessed file. We then postprocess it to remove redundant line -- markers inserted by the preprocessor. Preprocessor_Output_Filename : constant String := - (+Info.Output_Dir) / + (+Prj.Output_Dir) / ("pp-output-" & Strip_Zero_Padding (Hex_Image (PID))); Preprocessor_Output_File : Ada.Text_IO.File_Type; -- File containing the preprocessor output (used to get include search -- paths). begin - PP_Filename := +New_File (Info, Filename); - - -- The file may have been preprocessed already, if we are instrumenting - -- it as a main after having instrumented it as a source. In this case, - -- we should not preprocess it again (as it will fail). HACK: if the - -- original filename is an instrumented file (in which case it is - -- equal to PP_Filename), skip the preprocessing step. + PP_Filename := +New_File (Prj, Filename); + -- HACK: consider that the file was already preprocessed in that case if +PP_Filename = Filename then return; end if; Cmd := - (Command => +Compiler_Driver (Info.Project, Instrumenter.Language), + (Command => Prj.Compiler_Driver (Instrumenter.Language), others => <>); -- Add the preprocessing flag @@ -2765,9 +2649,9 @@ package body Instrument.C is procedure Start_Rewriting (Self : out C_Source_Rewriter; - Info : in out Project_Info; Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; Preprocessed : Boolean := False) is PP_Filename : Unbounded_String := +Filename; @@ -2775,10 +2659,10 @@ package body Instrument.C is Options : Analysis_Options; Args : String_Vectors.Vector; begin - Import_Options (Options, Instrumenter.Language, Info, Filename); + Import_Options (Options, Instrumenter, Prj, Filename); if not Preprocessed then Preprocess_Source - (Filename, Instrumenter, PP_Filename, Info, Options); + (Filename, Instrumenter, Prj, PP_Filename, Options); end if; Self.CIdx := @@ -2868,11 +2752,11 @@ package body Instrument.C is -------------------- procedure Record_PP_Info - (Unit_Info : Instrumented_Unit_Info; - UIC : in out C_Unit_Inst_Context) + (Orig_Filename : String; + UIC : in out C_Unit_Inst_Context; + Instrumenter : C_Family_Instrumenter_Type'Class) is - Orig_Filename : constant String := +Unit_Info.Filename; - Args : String_Vectors.Vector; + Args : String_Vectors.Vector; begin UIC.Pass := Record_PP_Info_Pass'Access; UIC.CIdx := @@ -2884,7 +2768,8 @@ package body Instrument.C is -- the user's preprocessor. Add_Options (Args, UIC.Options); - String_Vectors.Append (Args, Common_Parse_TU_Args (Unit_Info.Language)); + String_Vectors.Append + (Args, Common_Parse_TU_Args (Instrumenter.Language)); -- TODO??? We should also inhibit the use of clang predefined macros, -- with the -undef option, but doing this yields parsing errors, and a @@ -2924,24 +2809,31 @@ package body Instrument.C is end Record_PP_Info; - ---------------------------- - -- Instrument_Source_File -- - ---------------------------- + --------------------- + -- Instrument_Unit -- + --------------------- - procedure Instrument_Source_File - (CU_Name : Compilation_Unit_Name; - Unit_Info : Instrumented_Unit_Info; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj_Info : in out Project_Info; - UIC : out C_Unit_Inst_Context) + procedure Instrument_Unit + (Self : in out C_Family_Instrumenter_Type; + Unit_Name : String; + Prj : Prj_Desc; + Files_Of_Interest : String_Sets.Set) is - Orig_Filename : constant String := +Unit_Info.Filename; + UIC : C_Unit_Inst_Context; + CU_Name : constant Compilation_Unit_Name := + CU_Name_For_File (+Unit_Name); + + Orig_Filename : constant String := Unit_Name; PP_Filename : Unbounded_String; -- Respectively original, and preprocessed filename Buffer_Filename : constant String := - To_Symbol_Name (Sys_Buffers) & "_b_" & Instrumented_Unit_Slug (CU_Name) - & Source_Suffix (Instrumenter, GPR.Unit_Body, Prj_Info.Project); + New_File + (Prj, + To_Symbol_Name (Sys_Buffers) & "_b_" + & Instrumented_Unit_Slug (CU_Name) + & (+Prj.Body_Suffix + (C_Family_Instrumenter_Type'Class (Self).Language))); -- Name of the generated source file holding the coverage buffers Rewriter : C_Source_Rewriter; @@ -2979,7 +2871,7 @@ package body Instrument.C is Put_Extern_Decl (UIC.Rewriter, Insert_Extern_Location, - Instrumenter, + Self, C_Type, Name, Array_Size, @@ -2989,30 +2881,47 @@ package body Instrument.C is -- Start of processing for Instrument_Source_File begin + -- Exit early if there is no compiler driver found to preprocess the + -- source. + + declare + Compiler_Driver : constant Unbounded_String := + Prj.Compiler_Driver + (C_Family_Instrumenter_Type'Class (Self).Language); + begin + if Compiler_Driver = Null_Unbounded_String then + Outputs.Fatal_Error + ("could not find a compiler for " + & Image + (C_Family_Instrumenter_Type'Class (Self).Language)); + end if; + end; + SCOs.Initialize; UIC.SFI := Get_Index_From_Generic_Name (Orig_Filename, Kind => Files_Table.Source_File, Indexed_Simple_Name => True); + UIC.Fullname := +Orig_Filename; -- Initialize the C instrumentation context UIC.Instrumented_Unit := CU_Name; UIC.Buffer_Unit := CU_Name_For_File (+Buffer_Filename); + UIC.Files_Of_Interest := Files_Of_Interest; -- Import analysis options for the file to preprocess, then run the -- preprocessor. - Import_Options - (UIC.Options, Instrumenter.Language, Prj_Info, Orig_Filename); + Import_Options (UIC.Options, Self, Prj, Unit_Name); Preprocess_Source - (Orig_Filename, Instrumenter, PP_Filename, Prj_Info, UIC.Options); + (Orig_Filename, Self, Prj, PP_Filename, UIC.Options); -- Start by recording preprocessing information - Record_PP_Info (Unit_Info, UIC); + Record_PP_Info (Orig_Filename, UIC, Self); -- Then record exemption annotations in the comments. Reuse the TU from -- the preprocessing information recording pass as we want the @@ -3078,11 +2987,12 @@ package body Instrument.C is UIC.Pass := Instrument_Pass'Access; - Start_Rewriting (Self => Rewriter, - Info => Prj_Info, - Filename => +PP_Filename, - Instrumenter => Instrumenter, - Preprocessed => True); + Start_Rewriting + (Self => Rewriter, + Filename => +PP_Filename, + Instrumenter => Self, + Prj => Prj, + Preprocessed => True); UIC.TU := Rewriter.TU; UIC.Rewriter := Rewriter.Rewriter; Insert_Extern_Location := @@ -3204,7 +3114,7 @@ package body Instrument.C is end if; end if; - -- Create mappings from alloacted bits to the corresponding SCO + -- Create mappings from allocated bits to the corresponding SCO -- discharging information (Bit_Maps). Bit_Maps := @@ -3334,7 +3244,29 @@ package body Instrument.C is & " unsigned value"); Rewriter.Apply; - end Instrument_Source_File; + + -- Generate a buffer compilation unit defining coverage buffers that + -- will store execution witnesses. This CU is a C file rather than an + -- Ada file exporting the defined symboled to C. Indeed, we want it to + -- be compatible with a C-only compiler. + + Emit_Buffer_Unit + (UIC, + Project_Unit' + (Language => File_Based_Language, + Unit_Name => UIC.Fullname), + Self, + Prj); + + -- Update the Ignore_Status of the CU we instrumented + + Files_Table.Consolidate_Ignore_Status + (Index => Files_Table.Get_Index_From_Generic_Name + (Name => Orig_Filename, + Kind => Files_Table.Source_File, + Indexed_Simple_Name => True), + Status => Files_Table.Never); + end Instrument_Unit; ---------------------------- -- Format_Array_Init_Expr -- @@ -3375,9 +3307,10 @@ package body Instrument.C is ---------------------- procedure Emit_Buffer_Unit - (Info : in out Project_Info; - UIC : C_Unit_Inst_Context'Class; - Instrumenter : C_Family_Instrumenter_Type'Class) + (UIC : C_Unit_Inst_Context'Class; + Unit : Project_Unit; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc) is CU_Name : Compilation_Unit_Name renames UIC.Buffer_Unit; File : Text_Files.File_Type; @@ -3422,12 +3355,12 @@ package body Instrument.C is begin -- Compute Buffers_Filenames and Buffers_Projects - for Cur in UIC.Sources_Of_Interest.Iterate loop + for Cur in UIC.Sources_Of_Interest_Info.Iterate loop declare use Created_Unit_Maps; SOI : Source_Of_Interest renames - UIC.Sources_Of_Interest.Constant_Reference (Cur); + UIC.Sources_Of_Interest_Info.Constant_Reference (Cur); Cur : Cursor; Index : Natural; begin @@ -3451,7 +3384,7 @@ package body Instrument.C is -- Start to emit the buffer unit - Create_File (Info, File, +CU_Name.Filename); + Create_File (Prj, File, +CU_Name.Filename); File.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); File.New_Line; @@ -3628,7 +3561,7 @@ package body Instrument.C is (File, Instrumenter, "const struct gnatcov_rts_coverage_buffers_group", - Unit_Buffers_Name (UIC.Instrumented_Unit), + Unit_Buffers_Name (Unit), Init_Expr => "{" & Img (Buffers_Count) & ", &" & Buffers_Array & "[0]}"); end; @@ -3639,11 +3572,11 @@ package body Instrument.C is --------------------------- procedure Emit_Dump_Helper_Unit - (Dump_Config : Any_Dump_Config; - Info : in out Project_Info; - Main : Compilation_Unit_Name; - Helper_Unit : out US.Unbounded_String; - Instrumenter : C_Family_Instrumenter_Type'Class) + (Dump_Config : Any_Dump_Config; + Main : Compilation_Unit_Name; + Helper_Unit : out US.Unbounded_String; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc) is File : Text_Files.File_Type; @@ -3663,8 +3596,7 @@ package body Instrument.C is To_Symbol_Name (Sys_Buffers) & "_d_" & Instrumented_Unit_Slug (Main) - & US.To_Unbounded_String - (Source_Suffix (Instrumenter, GPR.Unit_Body, Info.Project)); + & Prj.Body_Suffix (Instrumenter.Language); -- Compute the qualified names we need for instrumentation @@ -3675,7 +3607,7 @@ package body Instrument.C is begin -- Emit the package body - Create_File (Info, File, Filename); + Create_File (Prj, File, Filename); File.Put_Line ("#include ""gnatcov_rts_c-strings.h"""); @@ -3696,7 +3628,7 @@ package body Instrument.C is (File, Instrumenter, "const struct gnatcov_rts_coverage_buffers_group_array", - Unit_Buffers_Array_Name (Project.Project.Root_Project.Name)); + Unit_Buffers_Array_Name (+Prj.Prj_Name)); -- Emit the procedure to write the trace file @@ -3706,26 +3638,18 @@ package body Instrument.C is File.Put_Line (Indent1 & Output_Proc & " ("); File.Put_Line - (Indent2 & "&" - & Unit_Buffers_Array_Name (Project.Project.Root_Project.Name) - & ","); + (Indent2 & "&" + & Unit_Buffers_Array_Name (+Prj.Prj_Name) & ","); case Dump_Config.Channel is when Binary_File => declare - use GNATCOLL.VFS; - Env_Var : constant String := (if US.Length (Dump_Config.Filename_Env_Var) = 0 then "GNATCOV_RTS_DEFAULT_TRACE_FILENAME_ENV_VAR" else """" & (+Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := - (if US.Length (Dump_Config.Filename_Prefix) = 0 - then """" & String'(+Info.Project.Executable_Name - (+(+Main.Filename), - Include_Suffix => True)) & """" - else """" & (+Dump_Config.Filename_Prefix) & """"); - Tag : constant String := - """" & Trace_Filename_Tag & """"; + """" & (+Dump_Config.Filename_Prefix) & """"; + Tag : constant String := """" & (+Instrumenter.Tag) & """"; Simple : constant String := (if Dump_Config.Filename_Simple then "1" else "0"); begin @@ -3767,13 +3691,11 @@ package body Instrument.C is ------------------------------- overriding procedure Auto_Dump_Buffers_In_Main - (Self : in out C_Family_Instrumenter_Type; - Filename : String; - Instr_Units : CU_Name_Vectors.Vector; - Dump_Config : Any_Dump_Config; - Info : in out Project_Info) + (Self : in out C_Family_Instrumenter_Type; + Filename : String; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc) is - Helper_Filename : US.Unbounded_String; -- Name of file to contain helpers implementing the buffers dump @@ -3788,7 +3710,7 @@ package body Instrument.C is Main_Cursor : Cursor_T; -- Cursor of the main declaration begin - Rew.Start_Rewriting (Info, Filename, Self); + Rew.Start_Rewriting (Filename, Self, Prj); Insert_Extern_Location := Start_Sloc (Get_Translation_Unit_Cursor (Rew.TU)); @@ -3800,7 +3722,7 @@ package body Instrument.C is end if; Emit_Dump_Helper_Unit - (Dump_Config, Info, Main, Helper_Filename, Self); + (Dump_Config, Main, Helper_Filename, Self, Prj); Put_Extern_Decl (Rew.Rewriter, @@ -4087,30 +4009,34 @@ package body Instrument.C is (Format_Extern_Decl (Instrumenter, C_Type, Name, Func_Args)); end Put_Extern_Decl; - ---------------------------- - -- Emit_Buffers_List_Unit -- - ---------------------------- - overriding procedure Emit_Buffers_List_Unit - (Self : C_Family_Instrumenter_Type; - Root_Project_Info : in out Project_Info; - Instr_Units : CU_Name_Vectors.Vector) + (Self : C_Family_Instrumenter_Type; + Instr_Units : Unit_Sets.Set; + Prj : Prj_Desc) is - Project_Name : String renames Root_Project_Info.Project.Name; - CU_Name_Body : constant String := - "gnatcov_rts_c-buffers-lists-" & Project_Name - & Source_Suffix (Self, GPR.Unit_Body, Root_Project_Info.Project); - File_Body : Text_Files.File_Type; + Base_Filename : constant String := + "gnatcov_rts_c-buffers-lists-" & (+Prj.Prj_Name); + CU_Name_Body : constant String := + Base_Filename + & (+Prj.Body_Suffix + (C_Family_Instrumenter_Type'Class (Self).Language)); + CU_Name_Header : constant String := + Base_Filename + & (+Prj.Spec_Suffix + (C_Family_Instrumenter_Type'Class (Self).Language)); + + File_Body : Text_Files.File_Type; + File_Header : Text_Files.File_Type; Buffer_Array_Decl : constant String := "const struct gnatcov_rts_coverage_buffers_group_array " - & Unit_Buffers_Array_Name (Project_Name); + & Unit_Buffers_Array_Name (+Prj.Prj_Name); Buffer_Unit_Length : constant String := Count_Type'Image (Instr_Units.Length); begin -- Emit the body to contain the list of buffers - Create_File (Root_Project_Info, File_Body, CU_Name_Body); + Create_File (Prj, File_Body, CU_Name_Body); File_Body.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); @@ -4124,147 +4050,33 @@ package body Instrument.C is Unit_Buffers_Name (Instr_Unit)); end loop; - -- Then create an extern declaration for the buffer array (necessary - -- in C++ to set the C linkage), and finally the definition for that - -- array. + -- Then create an extern declaration for the buffer array (necessary in + -- C++ to set the C linkage), and finally the definition for that array. File_Body.Put_Line (Self.Extern_Prefix & Buffer_Array_Decl & ";"); File_Body.Put_Line (Buffer_Array_Decl & " = {"); File_Body.Put_Line (" " & Buffer_Unit_Length & ","); File_Body.Put_Line (" (const struct gnatcov_rts_coverage_buffers_group *[]) {"); - for Cur in Instr_Units.Iterate loop - declare - use CU_Name_Vectors; - begin - File_Body.Put (" &" & Unit_Buffers_Name (Element (Cur))); - if To_Index (Cur) = Instr_Units.Last_Index then - File_Body.Put_Line ("}};"); - else - File_Body.Put_Line (","); - end if; - end; + for Instr_Unit of Instr_Units loop + File_Body.Put (" &" & Unit_Buffers_Name (Instr_Unit)); + if Instr_Unit = Instr_Units.Last_Element then + File_Body.Put_Line ("}};"); + else + File_Body.Put_Line (","); + end if; end loop; - end Emit_Buffers_List_Unit; - --------------------- - -- Instrument_Unit -- - --------------------- + -- Emit the extern declaration of the buffers array in the header file - overriding procedure Instrument_Unit - (Self : in out C_Family_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Unit_Info : in out Instrumented_Unit_Info) - is - Prj_Info : Project_Info renames Unit_Info.Prj_Info.all; - UIC : C_Unit_Inst_Context; - begin - Instrument_Source_File - (CU_Name => CU_Name, - Unit_Info => Unit_Info, - Instrumenter => Self, - Prj_Info => Prj_Info, - UIC => UIC); + Create_File (Prj, File_Header, CU_Name_Header); - -- Generate a buffer compilation unit defining coverage buffers that - -- will store execution witnesses. This CU is a C file rather than an - -- Ada file exporting the defined symboled to C. Indeed, we want it to - -- be compatible with a C-only compiler. - - Emit_Buffer_Unit (Prj_Info, UIC, Self); - end Instrument_Unit; - - ---------------------- - -- Skip_Source_File -- - ---------------------- - - overriding function Skip_Source_File - (Self : C_Family_Instrumenter_Type; - Source_File : GNATCOLL.Projects.File_Info) return Boolean is - begin - -- Do not instrument C headers: code in C header is meant to be - -- instrumented at the time it is included in a ".c" source. - - return Source_File.Unit_Part = Unit_Spec; - end Skip_Source_File; - - ------------------------- - -- Import_From_Project -- - ------------------------- - - procedure Import_From_Project - (Self : out Analysis_Options; - Language : C_Family_Language; - Info : Project_Info; - Filename : String) - is - procedure Register_Source_Dirs (P : GNATCOLL.Projects.Project_Type); - -- Add the source directories of P's project file to the search paths - -- to be passed as -I arguments later. The order in which the paths are - -- added to the search paths vector is the same order in which GNATCOLL - -- retrieves the files in the project tree. gprbuild also depends on - -- GNATCOLL which ensures we have the same behavior here. - - -------------------------- - -- Register_Source_Dirs -- - -------------------------- - - procedure Register_Source_Dirs (P : GNATCOLL.Projects.Project_Type) is - begin - for Dir of P.Source_Dirs loop - Self.PP_Search_Path.Append - (+GNATCOLL.VFS."+" (GNATCOLL.VFS.Dir_Name (Dir))); - end loop; - end Register_Source_Dirs; - - Switches : GNAT.Strings.String_List_Access; - - begin - - -- Pass the source directories of the project file as -I options. Note - -- that this will duplicate with the project tree traversal below, but - -- we need this project source directories to be picked first. We thus - -- make sure to add them first to the PP_Search_Path list. - - Register_Source_Dirs (Info.Project); - - -- Pass the source directories of included projects as -I options - - Project.Iterate_Projects - (Info.Project, Register_Source_Dirs'Access, - Recursive => True, Include_Extended => True); - - -- Now get actual compiler switches from the project file for Filename. - -- First try to get the switches specifically for Filename, then if - -- there are none fall back to default switches for C. - - Switches := - Info.Project.Attribute_Value - (Attribute => GPR.Build ("compiler", "switches"), - Index => Simple_Name (Filename)); - - if Switches = null then - Switches := - Info.Project.Attribute_Value - (Attribute => GPR.Compiler_Default_Switches_Attribute, - Index => Image (Language)); - end if; - - -- If we manage to find appropriate switches, convert them to a string - -- vector import the switches. - - if Switches /= null then - declare - Args : String_Vectors.Vector; - begin - for S of Switches.all loop - Args.Append (To_Unbounded_String (S.all)); - end loop; - GNAT.Strings.Free (Switches); - Import_From_Args (Self, Args); - end; - end if; - end Import_From_Project; + Put_Extern_Decl + (File_Header, + Self, + "const struct gnatcov_rts_coverage_buffers_group_array", + Unit_Buffers_Array_Name (+Prj.Prj_Name)); + end Emit_Buffers_List_Unit; ---------------- -- Split_Args -- @@ -4336,18 +4148,31 @@ package body Instrument.C is -------------------- procedure Import_Options - (Self : out Analysis_Options; - Language : C_Family_Language; - Info : Project_Info; - Filename : String) + (Self : out Analysis_Options; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; + Filename : String) is Cmdline_Opts : constant String_Vectors.Vector := To_String_Vector - (case Language is + (case C_Family_Language (Instrumenter.Language) is when C_Language => C_Opts, when CPP_Language => CPP_Opts); + Prj_Options : String_Vectors.Vector; begin - Import_From_Project (Self, Language, Info, Filename); + -- Grab the options from the project description. Note that the project + -- description is filled with compiler options in the -j1 + -- implementation. Otherwise, the compiler switches in the project files + -- are passed through the command line directly. + + if Prj.Compiler_Options_Unit.Contains (+Filename) then + Prj_Options.Append (Prj.Compiler_Options_Unit.Element (+Filename)); + else + Prj_Options.Append (Prj.Compiler_Options (Instrumenter.Language)); + end if; + Prj_Options.Append (Prj.Search_Paths); + + Import_From_Args (Self, Prj_Options); for Args of Cmdline_Opts loop Import_From_Args (Self, Split_Args (Args)); end loop; @@ -4357,10 +4182,10 @@ package body Instrument.C is Self.Builtin_Macros := Builtin_Macros - (Image (Language), - Compiler_Driver (Info.Project, Language), + (Image (C_Family_Language (Instrumenter.Language)), + +Prj.Compiler_Driver (Instrumenter.Language), +Self.Std, - +Info.Output_Dir).all; + +Prj.Output_Dir).all; end Import_Options; --------------------------- @@ -4388,22 +4213,20 @@ package body Instrument.C is -- if it is missing. declare - use GNATCOLL.VFS; use Source_Of_Interest_Maps; - Cur : constant Cursor := UIC.Sources_Of_Interest.Find (File); + Cur : constant Cursor := UIC.Sources_Of_Interest_Info.Find (File); SOI : Source_Of_Interest; - FI : GNATCOLL.Projects.File_Info; begin if Has_Element (Cur) then - return UIC.Sources_Of_Interest.Reference (Cur).Of_Interest; + return UIC.Sources_Of_Interest_Info.Reference (Cur).Of_Interest; end if; -- Consider that File is of interest iff it belongs to a loaded - -- project. + -- project. TODO???: this should also consider units of interest + -- switches. - FI := Project.Project.Info (Create (+To_String (File))); - if FI.Project /= No_Project then + if UIC.Files_Of_Interest.Contains (File) then SOI := (Of_Interest => True, SFI => Get_Index_From_Generic_Name @@ -4412,7 +4235,7 @@ package body Instrument.C is else SOI := (Of_Interest => False); end if; - UIC.Sources_Of_Interest.Insert (File, SOI); + UIC.Sources_Of_Interest_Info.Insert (File, SOI); return SOI.Of_Interest; end; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 09777a7c0..fa5d85ca7 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -22,11 +22,8 @@ with Ada.Containers.Hashed_Maps; with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; with Ada.Finalization; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Hash; -with GNATCOLL.Projects; - with Namet; use Namet; with Clang.Index; use Clang.Index; @@ -42,26 +39,22 @@ package Instrument.C is abstract new Language_Instrumenter with null record; -- Common instrumentation primitives for C/C++ - overriding function Skip_Source_File - (Self : C_Family_Instrumenter_Type; - Source_File : GNATCOLL.Projects.File_Info) return Boolean; - overriding procedure Instrument_Unit - (Self : in out C_Family_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Unit_Info : in out Instrumented_Unit_Info); + (Self : in out C_Family_Instrumenter_Type; + Unit_Name : String; + Prj : Prj_Desc; + Files_Of_Interest : String_Sets.Set); overriding procedure Auto_Dump_Buffers_In_Main (Self : in out C_Family_Instrumenter_Type; Filename : String; - Instr_Units : CU_Name_Vectors.Vector; Dump_Config : Any_Dump_Config; - Info : in out Project_Info); + Prj : Prj_Desc); overriding procedure Emit_Buffers_List_Unit - (Self : C_Family_Instrumenter_Type; - Root_Project_Info : in out Project_Info; - Instr_Units : CU_Name_Vectors.Vector); + (Self : C_Family_Instrumenter_Type; + Instr_Units : Unit_Sets.Set; + Prj : Prj_Desc); function Extern_Prefix (Self : C_Family_Instrumenter_Type) return String @@ -76,6 +69,12 @@ package Instrument.C is (Self : C_Instrumenter_Type) return Src_Supported_Language is (C_Language); + function Create_C_Instrumenter + (Tag : Unbounded_String) return C_Instrumenter_Type + is (C_Instrumenter_Type'(Tag => Tag)); + -- Create a C instrumenter. See the definition of the + -- Language_Instrumenter type for the arguments semantic. + type CPP_Instrumenter_Type is new C_Family_Instrumenter_Type with null record; -- Instrumentation primitives for C++ @@ -88,6 +87,12 @@ package Instrument.C is (Self : CPP_Instrumenter_Type) return String is ("extern ""C"" "); + function Create_CPP_Instrumenter + (Tag : Unbounded_String) return CPP_Instrumenter_Type + is (CPP_Instrumenter_Type'(Tag => Tag)); + -- Create a C++ instrumenter. See the definition of the + -- Language_Instrumenter type for the arguments semantic. + type Instr_Scheme_Type is (Instr_Stmt, Instr_Expr); -- Depending on the statement construct, we can instrument it either with -- another statement right before (Instr_Stmt), which is the case for most @@ -231,22 +236,14 @@ package Instrument.C is (Key_Type => Nat, Element_Type => PP_Info); - procedure Import_From_Project - (Self : out Analysis_Options; - Language : C_Family_Language; - Info : Project_Info; - Filename : String); - -- Initialize Self from compiler switches corresponding to the Filename - -- source file in the Info project. - function Split_Args (Args : Unbounded_String) return String_Vectors.Vector; -- Split a comma-separated list of arguments procedure Import_Options - (Self : out Analysis_Options; - Language : C_Family_Language; - Info : Project_Info; - Filename : String); + (Self : out Analysis_Options; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; + Filename : String); -- Shortcut to call Import_From_Project, and Import_From_Args on the -- --c-opts/--c++-opts option. @@ -301,7 +298,8 @@ package Instrument.C is LL_PP_Info_Map : LL_SCO_PP_Info_Maps.Map; -- Preprocessing information for low level SCOs - Sources_Of_Interest : Source_Of_Interest_Maps.Map; + Files_Of_Interest : String_Sets.Set; + Sources_Of_Interest_Info : Source_Of_Interest_Maps.Map; -- Records for each source file processed during the instrumentation -- whether it is a source of interest, and some properties if it is. diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index 2a575f3ed..287fd99b9 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -37,6 +37,10 @@ package Instrument.C is (Self : C_Instrumenter_Type) return Src_Supported_Language is (C_Language); + function Create_C_Instrumenter + (Tag : Unbounded_String) return C_Instrumenter_Type + is (C_Instrumenter_Type'(others => <>)); + type CPP_Instrumenter_Type is new C_Family_Instrumenter_Type with null record; -- Instrumentation primitives for C++ @@ -45,8 +49,9 @@ package Instrument.C is (Self : CPP_Instrumenter_Type) return Src_Supported_Language is (CPP_Language); - C_Instrumenter : aliased C_Instrumenter_Type := (null record); - CPP_Instrumenter : aliased CPP_Instrumenter_Type := (null record); + function Create_CPP_Instrumenter + (Tag : Unbounded_String) return CPP_Instrumenter_Type + is (CPP_Instrumenter_Type'(others => <>)); procedure Postprocess_Source (Preprocessed_Filename : String; diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 82a80f2be..58155939e 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -16,9 +16,8 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Containers; use Ada.Containers; +with Ada.Containers; use Ada.Containers; with Ada.Containers.Vectors; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Clang.Index; use Clang.Index; with Clang.Rewrite; use Clang.Rewrite; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 8d344e3c1..cb1994d0e 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -18,18 +18,13 @@ with Ada.Containers; use Ada.Containers; with Ada.Directories; -with Ada.Unchecked_Deallocation; -with GNAT.OS_Lib; - -with Interfaces; +with GNATCOLL.VFS; with Coverage; with Diagnostics; -with Hex_Images; with Outputs; use Outputs; with Paths; use Paths; -with Project; use Project; with SCOs; package body Instrument.Common is @@ -88,30 +83,18 @@ package body Instrument.Common is return Buffer_Symbol (Instrumented_Unit, "mcdc"); end MCDC_Buffer_Symbol; - ----------------- - -- Buffer_Unit -- - ----------------- - - function Buffer_Unit - (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name - is - Simple_Name : Ada_Identifier; - begin - Append (Simple_Name, 'B'); - Append (Simple_Name, Instrumented_Unit_Slug (Instrumented_Unit)); - return CU_Name : Ada_Qualified_Name := Sys_Buffers do - CU_Name.Append (Simple_Name); - end return; - end Buffer_Unit; - ----------------------- -- Unit_Buffers_Name -- ----------------------- - function Unit_Buffers_Name (Unit : Compilation_Unit_Name) return String is + function Unit_Buffers_Name (Unit : Project_Unit) return String is + Slug : constant String := + (case Unit.Language is + when Unit_Based_Language => + Qualified_Name_Slug (To_Qualified_Name (+Unit.Unit_Name)), + when File_Based_Language => Filename_Slug (+Unit.Unit_Name)); begin - return To_Symbol_Name (Sys_Buffers) & "_" & Instrumented_Unit_Slug (Unit) - & "_buffers"; + return To_Symbol_Name (Sys_Buffers) & "_" & Slug & "_buffers"; end Unit_Buffers_Name; ------------------------ @@ -158,255 +141,6 @@ package body Instrument.Common is return To_String (Result); end Format_Fingerprint; - ------------------------ - -- Trace_Filename_Tag -- - ------------------------ - - function Trace_Filename_Tag return String - is - -- Compute the tag for default source trace filenames. Use the current - -- time as a mostly unique identifier. Put it in hexadecimal form - -- without leading zeros to avoid too long names. - - use Interfaces; - Time : constant Unsigned_64 := - Unsigned_64 (GNAT.OS_Lib.To_C (GNAT.OS_Lib.Current_Time)); - Tag : constant String := - Hex_Images.Strip_Zero_Padding - (Hex_Images.Hex_Image (Time)); - begin - return Tag; - end Trace_Filename_Tag; - - -------------------- - -- Create_Context -- - -------------------- - - function Create_Context - (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context is - begin - return IC : Inst_Context do - IC.Project_Name := +Ada.Directories.Base_Name - (Project.Root_Project_Filename); - -- TODO??? Get the original casing for the project name - - IC.Ignored_Source_Files_Present := Ignored_Source_Files /= null; - if Ignored_Source_Files /= null then - IC.Ignored_Source_Files := Ignored_Source_Files.all; - end if; - end return; - end Create_Context; - - --------------------- - -- Destroy_Context -- - --------------------- - - procedure Destroy_Context (Context : in out Inst_Context) is - procedure Free is new Ada.Unchecked_Deallocation - (Instrumented_Unit_Info, Instrumented_Unit_Info_Access); - procedure Free is new Ada.Unchecked_Deallocation - (Project_Info, Project_Info_Access); - begin - -- Deallocate all Insrtrumented_Unit_Info in Context, and then clear the - -- hashed map, both to avoid dangling pointers and to make - -- Destroy_Context callable more than once, like conventional - -- deallocation procedures in Ada. - - for Cur in Context.Instrumented_Units.Iterate loop - declare - IU : Instrumented_Unit_Info_Access := - Instrumented_Unit_Maps.Element (Cur); - begin - Free (IU); - end; - end loop; - Context.Instrumented_Units := Instrumented_Unit_Maps.Empty_Map; - - -- Likewise for Project_Info records - - for Cur in Context.Project_Info_Map.Iterate loop - declare - PI : Project_Info_Access := Project_Info_Maps.Element (Cur); - begin - Free (PI); - end; - end loop; - Context.Project_Info_Map := Project_Info_Maps.Empty_Map; - end Destroy_Context; - - ---------------------------- - -- Is_Ignored_Source_File -- - ---------------------------- - - function Is_Ignored_Source_File - (Context : Inst_Context; Filename : String) return Boolean is - begin - return - Context.Ignored_Source_Files_Present - and then GNAT.Regexp.Match - (S => Fold_Filename_Casing (Filename), - R => Context.Ignored_Source_Files); - end Is_Ignored_Source_File; - - -------------------------------- - -- Get_Or_Create_Project_Info -- - -------------------------------- - - function Get_Or_Create_Project_Info - (Context : in out Inst_Context; - Project : Project_Type) return Project_Info_Access - is - use Project_Info_Maps; - - -- Look for an existing Project_Info record corresponding to Project - - Project_Name : constant Unbounded_String := +Project.Name; - Position : constant Cursor := Context.Project_Info_Map.Find - (Project_Name); - begin - if Has_Element (Position) then - return Element (Position); - - else - -- The requested Project_Info record does not exist yet. Create it, - -- register it and return it. - - declare - Storage_Project : constant Project_Type := - Project.Extending_Project (Recurse => True); - -- Actual project that will host instrumented sources: even when - -- we instrument an extended project, the resulting instrumented - -- sources must go to the ultimate extending project's object - -- directory. This is similar to the object directory that hosts - -- object files when GPRbuild processes a project that is - -- extended. - - Result : constant Project_Info_Access := new Project_Info' - (Project => Project, - Externally_Built => Project.Externally_Built, - Output_Dir => +Project_Output_Dir (Storage_Project)); - begin - Context.Project_Info_Map.Insert (Project_Name, Result); - return Result; - end; - end if; - end Get_Or_Create_Project_Info; - - --------------- - -- Unit_Info -- - --------------- - - function Unit_Info - (CU_Name : Compilation_Unit_Name; - Info : out GNATCOLL.Projects.File_Info) return Boolean - is - Prj : Project_Type renames Project.Project.Root_Project; - File : constant GNATCOLL.VFS.Filesystem_String := Prj.File_From_Unit - (Unit_Name => To_Ada (CU_Name.Unit), - Part => CU_Name.Part, - Language => "Ada"); - begin - if File'Length = 0 then - return False; - end if; - - Info := Prj.Create_From_Project (File); - return True; - end Unit_Info; - - --------------------------------- - -- Register_Main_To_Instrument -- - --------------------------------- - - procedure Register_Main_To_Instrument - (Context : in out Inst_Context; - Mains : in out Main_To_Instrument_Vectors.Vector; - File : GNATCOLL.VFS.Virtual_File; - Project : Project_Type) - is - File_Info : constant GNATCOLL.Projects.File_Info := - Standard.Project.Project.Info (File); - CU_Name : constant Compilation_Unit_Name := - To_Compilation_Unit_Name (File_Info); - Prj_Info : constant Project_Info_Access := - Get_Or_Create_Project_Info (Context, Project); - begin - Mains.Append - (Main_To_Instrument' - (CU_Name => CU_Name, - File => File, - Prj_Info => Prj_Info)); - end Register_Main_To_Instrument; - - --------------------------- - -- Add_Instrumented_Unit -- - --------------------------- - - procedure Add_Instrumented_Unit - (Context : in out Inst_Context; - Project : GNATCOLL.Projects.Project_Type; - Source_File : GNATCOLL.Projects.File_Info) - is - use GNATCOLL.VFS; - - SF_Basename : constant Filesystem_String := Source_File.File.Base_Name; - begin - pragma Assert (not (Is_Ignored_Source_File (Context, +SF_Basename))); - - declare - CU_Name : constant Compilation_Unit_Name := - To_Compilation_Unit_Name (Source_File); - begin - -- If we already planned to instrument this unit, do nothing more - - if Context.Instrumented_Units.Contains (CU_Name) then - return; - end if; - - -- Otherwise, add it to the list of instrumented units - - declare - Unit_Info : constant Instrumented_Unit_Info_Access := - new Instrumented_Unit_Info' - (Filename => To_Unbounded_String - (+Source_File.File.Full_Name), - Prj_Info => Get_Or_Create_Project_Info (Context, Project), - Language => To_Language (Source_File.Language)); - begin - Context.Instrumented_Units.Insert (CU_Name, Unit_Info); - end; - end; - end Add_Instrumented_Unit; - - -------------- - -- New_File -- - -------------- - - function New_File - (Info : Project_Info; Name : String) return String - is - Base_Filename : constant String := - Ada.Directories.Simple_Name (Name); - Output_Filename : constant String := - To_String (Info.Output_Dir) / Base_Filename; - begin - return Output_Filename; - end New_File; - - ----------------- - -- Create_File -- - ----------------- - - procedure Create_File - (Info : in out Project_Info; - File : in out Text_Files.File_Type; - Name : String) - is - Filename : constant String := New_File (Info, Name); - begin - File.Create (Filename); - end Create_File; - -------------- -- Next_Bit -- -------------- @@ -583,6 +317,67 @@ package body Instrument.Common is end loop; end Remap_Scope_Entity; + -------------- + -- New_File -- + -------------- + + function New_File + (Prj : Prj_Desc; Name : String) return String + is + Base_Filename : constant String := + Ada.Directories.Simple_Name (Name); + Output_Filename : constant String := + To_String (Prj.Output_Dir) / Base_Filename; + begin + return Output_Filename; + end New_File; + + ----------------- + -- Create_File -- + ----------------- + + procedure Create_File + (Prj : Prj_Desc; + File : in out Text_Files.File_Type; + Name : String) + is + Filename : constant String := New_File (Prj, Name); + begin + File.Create (Filename); + end Create_File; + + ----------------- + -- To_Filename -- + ----------------- + + function To_Filename + (Prj : Prj_Desc; + Lang : Src_Supported_Language; + CU_Name : Compilation_Unit_Name) return String + is + Filename : Unbounded_String; + begin + case CU_Name.Language_Kind is + when Unit_Based_Language => + for Id of CU_Name.Unit loop + if Length (Filename) > 0 then + Append (Filename, Prj.Dot_Replacement); + end if; + Append (Filename, To_Lower (To_String (Id))); + end loop; + + case CU_Name.Part is + when Unit_Body | Unit_Separate => + Append (Filename, Prj.Body_Suffix (Lang)); + when Unit_Spec => + Append (Filename, Prj.Spec_Suffix (Lang)); + end case; + when File_Based_Language => + Filename := CU_Name.Filename; + end case; + return +Filename; + end To_Filename; + ----------------- -- Add_Options -- ----------------- @@ -809,37 +604,6 @@ package body Instrument.Common is end loop; end Import_From_Args; - ------------------------------ - -- Buffer_Units_For_Closure -- - ------------------------------ - - function Instr_Units_For_Closure - (IC : Inst_Context; - Main : Compilation_Unit_Name) - return CU_Name_Vectors.Vector - is - pragma Unreferenced (Main); - Result : CU_Name_Vectors.Vector; - begin - -- TODO??? Here, we need the list of files needed to build Main: specs - -- for units WITHed by main, their bodies, the separates, etc. It's - -- unclear what GNATCOLL.Projects.Get_Closure does, but experimentations - -- show that it's not what we want. So for now, return an approximation: - -- buffer units for all instrumented units. In the future, we should - -- either get this service from GNATCOLL.Projects, either re-implement - -- it on top of Libadalang. - - for Cur in IC.Instrumented_Units.Iterate loop - declare - Instr_Unit : constant Compilation_Unit_Name := - Instrumented_Unit_Maps.Key (Cur); - begin - Result.Append (Instr_Unit); - end; - end loop; - return Result; - end Instr_Units_For_Closure; - begin Sys_Prefix.Append (To_Unbounded_String ("GNATcov_RTS")); diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index aae7ea275..af4f4051f 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -50,23 +50,21 @@ -- buffers for the unit. with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Containers.Hashed_Maps; with Ada.Containers.Hashed_Sets; with Ada.Containers.Ordered_Maps; with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Hash; -with Ada.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; -with GNATCOLL.VFS; with GNAT.Regpat; use GNAT.Regpat; -with ALI_Files; use ALI_Files; -with Files_Table; use Files_Table; +with GNATCOLL.JSON; use GNATCOLL.JSON; + +with ALI_Files; use ALI_Files; +with Files_Table; use Files_Table; with GNATcov_RTS; -with Namet; use Namet; -with Slocs; use Slocs; +with Namet; use Namet; +with Slocs; use Slocs; with Text_Files; package Instrument.Common is @@ -133,15 +131,9 @@ package Instrument.Common is -- Given a unit to instrument, return the name of the symbol to use for the -- entity that contains address of the decision coverage buffer. - function Buffer_Unit - (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name; - -- Given a unit to instrument, return the name of the unit that holds - -- its coverage buffers (Coverage_Buffer_Type and - -- GNATcov_RTS_Coverage_Buffers records). - - function Unit_Buffers_Name (Unit : Compilation_Unit_Name) return String; + function Unit_Buffers_Name (Unit : Project_Unit) return String; -- Name of the symbol that references the - -- gnatcov_rts_coverage_buffers_group struct for this unit. + -- gnatcov_rts_coverage_buffers_group struct for this file. function Unit_Buffers_Array_Name (Prj_Name : String) return String is ("gnatcov_rts_buffers_array_" & Prj_Name); @@ -168,64 +160,16 @@ package Instrument.Common is -- returned literal expression (aggregate in Ada, compound expression in -- C/C++). - function Trace_Filename_Tag return String; - -- Tag for the source trace filename. This allows differentiating trace - -- files produced by a specific program instrumentation from the ones - -- produced by other instrumentations. - package File_Sets is new Ada.Containers.Hashed_Sets (Element_Type => Ada.Strings.Unbounded.Unbounded_String, "=" => Ada.Strings.Unbounded."=", Equivalent_Elements => Ada.Strings.Unbounded."=", Hash => Ada.Strings.Unbounded.Hash); - type Project_Info is record - Project : Project_Type; - -- Project that this record describes - - Externally_Built : Boolean; - -- Whether this project is externally built. In that case, we assume its - -- units of interest have already been instrumented. - - Output_Dir : Ada.Strings.Unbounded.Unbounded_String; - -- Subdirectory in the project file's object directory. All we generate - -- for this project must land in it. - end record; - - type Project_Info_Access is access all Project_Info; - - package Project_Info_Maps is new Ada.Containers.Hashed_Maps - (Key_Type => Ada.Strings.Unbounded.Unbounded_String, - Element_Type => Project_Info_Access, - Equivalent_Keys => Ada.Strings.Unbounded."=", - Hash => Ada.Strings.Unbounded.Hash); - -- Mapping from project name (as returned by GNATCOLL.Projects.Name) to - -- Project_Info records. Project_Info records are owned by this map, and - -- thus must be deallocated when maps are deallocated. - - type Main_To_Instrument is record - CU_Name : Compilation_Unit_Name; - -- Compilation unit of the main to instrument - - File : GNATCOLL.VFS.Virtual_File; - -- Source file to instrument - - Prj_Info : Project_Info_Access; - -- Reference to the Project_Info record corresponding to the project - -- that owns the main to instrument. - end record; - - package Main_To_Instrument_Vectors is new Ada.Containers.Vectors - (Positive, Main_To_Instrument); - type Instrumented_Unit_Info is record Filename : Ada.Strings.Unbounded.Unbounded_String; -- Name of the source file for this unit - Prj_Info : Project_Info_Access; - -- Reference to the Project_Info record corresponding to the project - -- that owns the source file for this unit. - Language : Some_Language; -- Language for this unit end record; @@ -236,78 +180,6 @@ package Instrument.Common is (Key_Type => Compilation_Unit_Name, Element_Type => Instrumented_Unit_Info_Access); - type Inst_Context is limited record - Project_Name : Ada.Strings.Unbounded.Unbounded_String; - -- Name of the root project. It is also used to name the list of buffers - - Ignored_Source_Files_Present : Boolean; - Ignored_Source_Files : GNAT.Regexp.Regexp; - -- If present, instrumentation will ignore files whose names match the - -- accessed pattern. - - Instrumented_Units : Instrumented_Unit_Maps.Map; - -- Mapping from instrumented unit names to information used during - -- instrumentation. - - Project_Info_Map : Project_Info_Maps.Map; - -- For each project that contains units of interest, this tracks a - -- Project_Info record. - end record; - - function Create_Context - (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context; - -- Create an instrumentation context for the currently loaded project - - procedure Destroy_Context (Context : in out Inst_Context); - -- Free dynamically allocated resources in Context - - function Is_Ignored_Source_File - (Context : Inst_Context; Filename : String) return Boolean; - -- Return whether the instrumentation process must ignore the Filename - -- source file. - - function Get_Or_Create_Project_Info - (Context : in out Inst_Context; - Project : Project_Type) return Project_Info_Access; - -- Return the Project_Info record corresponding to Project. Create it if it - -- does not exist. - - function Unit_Info - (CU_Name : Compilation_Unit_Name; - Info : out GNATCOLL.Projects.File_Info) return Boolean; - -- Look for a compilation unit in the loaded project. If found, put its - -- file info in Info and return True. Return False otherwise. - - procedure Register_Main_To_Instrument - (Context : in out Inst_Context; - Mains : in out Main_To_Instrument_Vectors.Vector; - File : GNATCOLL.VFS.Virtual_File; - Project : Project_Type); - -- Register in Mains a main to be instrumented so that it dumps coverage - -- buffers. File is the source file for this main, and Project is the - -- project that owns this main. If File is actually a unit of interest in - -- Context, do nothing. - - procedure Add_Instrumented_Unit - (Context : in out Inst_Context; - Project : GNATCOLL.Projects.Project_Type; - Source_File : GNATCOLL.Projects.File_Info); - -- Add the given source file to the list of units to instrument - - function New_File - (Info : Project_Info; Name : String) return String; - -- Compute the path to the file to create in Info.Output_Dir - - procedure Create_File - (Info : in out Project_Info; - File : in out Text_Files.File_Type; - Name : String); - -- Shortcut to Text_Files.Create: create a text file with the given name in - -- Info.Output_Dir. - -- - -- Name can be a basename, a relative name or an absolute one: in all - -- cases, the basename is taken and the file is created in Info.Output_Dir. - ------------------------------------------------------ -- Common declarations for Ada / C instrumentation -- ------------------------------------------------------ @@ -397,9 +269,12 @@ package Instrument.Common is package Allocated_Bits_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Allocated_Bits); -- Allocated bits in coverage buffers for low-level SCOs (one per source - -- file). Because of #include directives in C/C++, a single compilation - -- unit may yield multiple sets of coverage buffers: one for the compiled - -- source file, one for each included source. + -- file). A single compilation unit may yield multiple sets of coverage + -- buffers: one for each part of the unit in the case of unit-based + -- language units (the spec, the body, and the separates). It may also be + -- the case for unit of file-based languages: one for the compiled source + -- file and one for each included source (e.g. through inclusion directives + -- for C and C++). function Create_Unit_Bits (Allocated_Bits : in out Allocated_Bits_Vectors.Vector; @@ -438,12 +313,12 @@ package Instrument.Common is Instrumented_Unit : Compilation_Unit_Name; -- Name of the compilation unit being instrumented - Language_Version_Pragma : Unbounded_Wide_Wide_String; - -- Language version configuration pragma for unit, if any - SFI : Source_File_Index := No_Source_File; -- Source file index of the compilation unit being instrumented + Fullname : Unbounded_String; + -- Fullname of the compilation unit being instrumented + Buffer_Unit : Compilation_Unit_Name; -- Name of the compilation unit that holds coverage buffers for the -- unit currently being instrumented (see Common.Buffer_Unit). @@ -501,12 +376,11 @@ package Instrument.Common is Element_Type => Ada_Qualified_Name, "=" => Ada_Identifier_Vectors."="); - function Instr_Units_For_Closure - (IC : Inst_Context; - Main : Compilation_Unit_Name) return CU_Name_Vectors.Vector; - -- Return the list of instrumented units in Main's closure + type Language_Instrumenter is abstract tagged record + Tag : Unbounded_String; + -- Tag specific to an instrumentation run - type Language_Instrumenter is abstract tagged null record; + end record; -- Set of operations to allow the instrumentation of sources files for a -- given language. @@ -514,46 +388,63 @@ package Instrument.Common is (Self : Language_Instrumenter) return Src_Supported_Language is abstract; -- Return the language that this instrumenter is designed to process - function Skip_Source_File - (Self : Language_Instrumenter; - Source_File : GNATCOLL.Projects.File_Info) return Boolean - is (True); - -- Whether the instrumenter skips the given source file. The default - -- (undefined) instrumenter skips every source file. - procedure Instrument_Unit - (Self : in out Language_Instrumenter; - CU_Name : Compilation_Unit_Name; - Unit_Info : in out Instrumented_Unit_Info) is null; + (Self : in out Language_Instrumenter; + Unit_Name : String; + Prj : Prj_Desc; + Files_Of_Interest : String_Sets.Set) is null; -- Instrument a single source file for the language that Self supports. -- - -- CU_Name must be the name of the compilation unit for this source file, - -- and Unit_Info must be the Instrumented_Unit_Info record corresponding to - -- this source file. + -- Unit_Name identifies this compilation unit (either through a unit name, + -- for Unit_Based_Language, or through a full name, for file-based). Prj + -- describes information coming from the project, and relevant to the + -- instrumentation of the unit. Files_Of_Interest provides the list of + -- files of interest, to ignore e.g. part of the unit (e.g. a separate) + -- when instrumenting it. procedure Auto_Dump_Buffers_In_Main - (Self : in out Language_Instrumenter; - Filename : String; - Instr_Units : CU_Name_Vectors.Vector; - Dump_Config : Any_Dump_Config; - Info : in out Project_Info) is null; + (Self : in out Language_Instrumenter; + Filename : String; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc) is null; -- Try to instrument the Filename source file (whose language is assumed - -- to be Self's) to insert a call to dump the list of coverage buffers for - -- all Instr_Units, according to the Dump_Config options. Do nothing if not - -- successful. - -- - -- Info must be the Project_Info record corresponding to the project that - -- owns Filename's compilation unit. + -- to be Self's) to insert a call to dump the list of coverage buffers, + -- assumed to be named after Prj.Prj_Name. Do nothing if not successful. procedure Emit_Buffers_List_Unit - (Self : Language_Instrumenter; - Root_Project_Info : in out Project_Info; - Instr_Units : CU_Name_Vectors.Vector) is null; + (Self : Language_Instrumenter; + Instr_Units : Unit_Sets.Set; + Prj : Prj_Desc) is null; + -- Emit in the root project a unit (in Self's language) to contain the list + -- of coverage buffers for the given instrumented files. + -- -- The variable holding the list of coverage buffers is exported to a -- unique C symbol whose name is defined by the Unit_Buffers_Array_Name -- function. This procedure should thus be called only once, for one of -- the supported languages of the project. + function New_File + (Prj : Prj_Desc; Name : String) return String; + -- Compute the path to the file to create in Self.Output_Dir + + procedure Create_File + (Prj : Prj_Desc; + File : in out Text_Files.File_Type; + Name : String); + -- Shortcut to Text_Files.Create: create a text file with the given name in + -- Prj.Output_Dir. + -- + -- Name can be a basename, a relative name or an absolute one: in all + -- cases, the basename is taken and the file is created in Prj.Output_Dir. + + function To_Filename + (Prj : Prj_Desc; + Lang : Src_Supported_Language; + CU_Name : Compilation_Unit_Name) return String; + -- Convert a Compilation_Unit_Name to a file basename, using the body / + -- spec suffix and dot replacement (for unit based languages) defined in + -- Prj. + type Macro_Definition (Define : Boolean := True) is record Name : Unbounded_String; -- Name of the macro diff --git a/tools/gnatcov/instrument-config.adb b/tools/gnatcov/instrument-config.adb new file mode 100644 index 000000000..52c04a534 --- /dev/null +++ b/tools/gnatcov/instrument-config.adb @@ -0,0 +1,50 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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 Command_Line; use Command_Line; +with Instrument.Ada_Unit; use Instrument.Ada_Unit; +with Instrument.C; use Instrument.C; +with Instrument.Common; use Instrument.Common; +with Strings; use Strings; + +-- Return the instrumenter configuration generated from the command line + +function Instrument.Config return Language_Instrumenter'Class +is + use Command_Line.Parser; + Language : constant Some_Language := + To_Language (+Args.String_Args (Opt_Lang).Value); + Tag : constant Unbounded_String := + Value_Or_Null (Args.String_Args (Opt_Dump_Filename_Tag)); +begin + case Language is + when Ada_Language => + return Create_Ada_Instrumenter + (Tag => Tag, + Config_Pragmas_Filename => + +Args.String_Args (Opt_Gnatec).Value, + Mapping_Filename => + +Args.String_Args (Opt_Gnatem).Value, + Predefined_Source_Dirs => + Args.String_List_Args (Opt_Runtime_Dir)); + when C_Language => + return Create_C_Instrumenter (Tag => Tag); + when CPP_Language => + return Create_CPP_Instrumenter (Tag => Tag); + end case; +end Instrument.Config; diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 35367363d..22a1529db 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -164,7 +164,7 @@ package body Instrument.Input_Traces is (Stream : in out Binary_Stream; File_Header : Trace_File_Header; Kind : out Supported_Info_Kind; - Data : out String_Access; + Data : out GNAT.OS_Lib.String_Access; Result : in out Read_Result) with Pre => Result.Success; -- Read a trace info entry from Stream. Return an error if something wrong @@ -395,7 +395,7 @@ package body Instrument.Input_Traces is (Stream : in out Binary_Stream; File_Header : Trace_File_Header; Kind : out Supported_Info_Kind; - Data : out String_Access; + Data : out GNAT.OS_Lib.String_Access; Result : in out Read_Result) is Ignored_EOF : Boolean; @@ -661,7 +661,7 @@ package body Instrument.Input_Traces is loop declare Kind : Supported_Info_Kind; - Data : String_Access; + Data : GNAT.OS_Lib.String_Access; begin Read_Trace_Info (Stream, File_Header, Kind, Data, Result); if not Result.Success then diff --git a/tools/gnatcov/instrument-main.adb b/tools/gnatcov/instrument-main.adb new file mode 100644 index 000000000..134475d8b --- /dev/null +++ b/tools/gnatcov/instrument-main.adb @@ -0,0 +1,41 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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 Instrument.Common; use Instrument.Common; + +-- Implementation of the gnatcov instrument-main, which inserts a call to +-- dump coverage buffers according to the various dump options passed +-- on the command line. + +procedure Instrument.Main + (Instrumenter : in out Language_Instrumenter'Class; + Dump_Config : Any_Dump_Config; + Main_Filename : String; + Prj : Prj_Desc) is +begin + -- If the dump-trigger is manual, there is nothing to do + + if Dump_Config.Trigger = Manual then + return; + end if; + + Instrumenter.Auto_Dump_Buffers_In_Main + (Filename => Main_Filename, + Dump_Config => Dump_Config, + Prj => Prj); +end Instrument.Main; diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb new file mode 100644 index 000000000..4227c83b4 --- /dev/null +++ b/tools/gnatcov/instrument-projects.adb @@ -0,0 +1,1231 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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.Characters.Handling; use Ada.Characters.Handling; +with Ada.Containers.Hashed_Maps; +with Ada.Containers.Indefinite_Ordered_Maps; +with Ada.Containers.Indefinite_Ordered_Sets; +with Ada.Directories; +with Ada.Exceptions; +with Ada.Strings; +with Ada.Strings.Fixed; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Strings.Unbounded.Hash; +with Ada.Unchecked_Deallocation; + +with Interfaces; use Interfaces; + +with GNAT.OS_Lib; +with GNAT.Regexp; +with GNAT.Strings; + +with GNATCOLL.JSON; use GNATCOLL.JSON; +with GNATCOLL.VFS; +with GNATCOLL.Projects.Aux; use GNATCOLL.Projects.Aux; + +with Command_Line; use Command_Line; +with Files_Table; +with Hex_Images; use Hex_Images; +with Instrument.Ada_Unit; use Instrument.Ada_Unit; +with Instrument.C; use Instrument.C; +with Instrument.Clean_Objdirs; +with Instrument.Common; use Instrument.Common; +with Instrument.Main; +with Instrument.Source; +with JSON; use JSON; +with Outputs; +with Paths; use Paths; +with Project; +with Strings; use Strings; +with Support_Files; +with Text_Files; use Text_Files; + +-- Generate instrumented sources for the source files of all units of +-- interest. Also save mappings between coverage buffers and SCOs for each +-- library units to SID files (one per library unit). +-- +-- Depending on Dump_Config, instrument mains to schedule a call to the +-- dump procedure for the list of coverage buffers in all mains in the +-- project. +-- +-- Language_Version restricts what source constructs the instrumenter is +-- allowed to use. For instance, if Ada_2005 (or a lower version) is +-- passed, it will not be allowed to introduce expression functions, and +-- thus will emit a warning when it needed to do so. +-- +-- If Ignored_Source_File is non-null, ignore files whose names match the +-- accessed pattern. +-- +-- Mains is the list of source files that were listed on the command line: +-- if non-empty, they replace the mains specified in project files. + +procedure Instrument.Projects + (Dump_Config : Any_Dump_Config; + Ignored_Source_Files : access GNAT.Regexp.Regexp; + Mains : String_Vectors.Vector) +is + Prj_Tree : constant Project_Tree_Access := Project.Project; + + type Project_Info is record + Project : Project_Type; + -- Project that this record describes + + Externally_Built : Boolean; + -- Whether this project is externally built. In that case, we assume its + -- units of interest have already been instrumented. + + Output_Dir : Ada.Strings.Unbounded.Unbounded_String; + -- Subdirectory in the project file's object directory. All we generate + -- for this project must land in it. + + Desc : Prj_Desc; + + end record; + + type Project_Info_Access is access all Project_Info; + + package Project_Info_Maps is new Ada.Containers.Hashed_Maps + (Key_Type => Ada.Strings.Unbounded.Unbounded_String, + Element_Type => Project_Info_Access, + Equivalent_Keys => Ada.Strings.Unbounded."=", + Hash => Ada.Strings.Unbounded.Hash); + -- Mapping from project name (as returned by GNATCOLL.Projects.Name) to + -- Project_Info records. Project_Info records are owned by this map, and + -- thus must be deallocated when maps are deallocated. + + type Main_To_Instrument is record + CU_Name : Compilation_Unit_Name; + -- Compilation unit of the main to instrument + + File : GNATCOLL.VFS.Virtual_File; + -- Source file to instrument + + Prj_Info : Project_Info_Access; + -- Reference to the Project_Info record corresponding to the project + -- that owns the main to instrument. + end record; + + package Main_To_Instrument_Vectors is new Ada.Containers.Vectors + (Positive, Main_To_Instrument); + + use type GNATCOLL.VFS.Filesystem_String; + function Less (L, R : File_Info) return Boolean is + (L.File.Full_Name < R.File.Full_Name); + function Equal (L, R : File_Info) return Boolean is + (L.File.Full_Name = R.File.Full_Name); + + package File_Info_Sets is new Ada.Containers.Indefinite_Ordered_Sets + (Element_Type => File_Info, "<" => Less, "=" => Equal); + + type Library_Unit_Info is record + Unit_Name : Unbounded_String; + -- Name of this unit: unit name for unit-based languages, simple name + -- for file-based languages. + + Instr_Project : GPR.Project_Type; + -- Project in which instrumentation artifacts for this unit are + -- generated. + + Language_Kind : Any_Language_Kind; + -- Higher level representation of a language (unit-based or file-based) + + Language : Any_Language; + -- Actual language representation + + All_Externally_Built : Boolean; + -- Whether all of the parts of this unit belongs to an externally-built + -- project. If it is the case, the unit won't be instrumented; + -- otherwise, every unit part will. + + end record; + + package Unit_Maps is new + Ada.Containers.Indefinite_Ordered_Maps (String, Library_Unit_Info); + -- Map to unit names to unit info of files implementing this unit. For + -- file- based languages, the unit name is the full name (to simplify + -- dealing with homonym in different projects). + + type Inst_Context is limited record + Mapping_File, Config_Pragmas_File : Unbounded_String; + + Predefined_Source_Dirs : String_Vectors.Vector; + + Sources_Of_Interest_Response_File : Unbounded_String; + -- File containing the list of units of interest, identified by their + -- fullname. This is passed on to gnatcov instrument-source invokations + -- (for Ada), to know which part of a unit (spec / body / separate) must + -- be instrumented. + + Ignored_Source_Files_Present : Boolean; + Ignored_Source_Files : GNAT.Regexp.Regexp; + -- If present, instrumentation will ignore files whose names match the + -- accessed pattern. + + Project_Info_Map : Project_Info_Maps.Map; + -- For each project that contains units of interest, this tracks a + -- Project_Info record. + + Tag : Unbounded_String; + -- Tag relative to the current instrumentation run + + end record; + + function Create_Context + (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context; + -- Create an instrumentation context for the currently loaded project + + procedure Destroy_Context (Context : in out Inst_Context); + -- Free dynamically allocated resources in Context + + function Is_Ignored_Source_File + (Context : Inst_Context; Filename : String) return Boolean; + -- Return whether the instrumentation process must ignore the Filename + -- source file. + + function Get_Or_Create_Project_Info + (Context : in out Inst_Context; + Project : Project_Type) return Project_Info_Access; + -- Return the Project_Info record corresponding to Project. Create it if it + -- does not exist. + + procedure Register_Main_To_Instrument + (Context : in out Inst_Context; + Mains : in out Main_To_Instrument_Vectors.Vector; + File : GNATCOLL.VFS.Virtual_File; + Project : Project_Type); + -- Register in Mains a main to be instrumented so that it dumps coverage + -- buffers. File is the source file for this main, and Project is the + -- project that owns this main. + + procedure Prepare_Output_Dirs (IC : Inst_Context); + -- Make sure we have the expected tree of directories for the + -- instrumentation output. + + function SID_Filename + (LU_Info : Library_Unit_Info; In_Library_Dir : Boolean) return String; + -- Return the filename of the SID file to create for the given library + -- unit. If In_Library_Dir is true, then return a filename located in the + -- project library directory. Otherwise, the filename is located in the + -- object directory. + + function Load_From_Project (Prj : Project_Type) return Prj_Desc; + -- Load the project description from the given project + + function Compilation_Unit_Options + (IC : Inst_Context; + Prj : Prj_Desc; + LU_Info : Library_Unit_Info) return String_Vectors.Vector; + -- Return the list of options to pass to a gnatcov instrument-source / + -- instrument-main (depending on Purpose) for the given compilation unit + -- LU_Info, belonging to the project Prj. + + procedure Add_Instrumented_Unit + (Project : GPR.Project_Type; Source_File : GPR.File_Info); + -- Add this source file to the list of units to instrument + + ----------------------- + -- Load_From_Project -- + ----------------------- + + function Load_From_Project (Prj : Project_Type) return Prj_Desc + is + Dot_Replacement : constant String := + Prj.Attribute_Value + (Attribute => Build ("Naming", "Dot_Replacement")); + Result : Prj_Desc; + begin + for Lang in Some_Language loop + if Builtin_Support (Lang) then + declare + Body_Suffix : constant String := + Project.Source_Suffix (Lang, GPR.Unit_Body, Prj); + Spec_Suffix : constant String := + Project.Source_Suffix (Lang, GPR.Unit_Spec, Prj); + begin + Result.Body_Suffix (Lang) := +Body_Suffix; + Result.Spec_Suffix (Lang) := +Spec_Suffix; + end; + end if; + end loop; + + Result.Prj_Name := +Prj.Name; + Result.Dot_Replacement := +Dot_Replacement; + + -- Load the set of compiler switches for languages requiring it + + for Lang in C_Family_Language loop + declare + use type GNAT.Strings.String_List_Access; + Options : Analysis_Options; + Compiler_Opts : String_Vectors.Vector; + Switches : GNAT.Strings.String_List_Access; + Compiler_Driver : constant String := + GNATCOLL.Projects.Attribute_Value + (Prj, + GPR.Compiler_Driver_Attribute, + Image (Lang)); + + procedure Register_Source_Dirs + (P : GNATCOLL.Projects.Project_Type); + -- Add the source directories of P's project file to the search + -- paths to be passed as -I arguments later. The order in which + -- the paths are added to the search paths vector is the same + -- order in which GNATCOLL retrieves the files in the project + -- tree. gprbuild also depends on GNATCOLL which ensures we + -- have the same behavior here. + + -------------------------- + -- Register_Source_Dirs -- + -------------------------- + + procedure Register_Source_Dirs + (P : GNATCOLL.Projects.Project_Type) is + begin + for Dir of P.Source_Dirs loop + Result.Search_Paths.Append + ("-I" & (+GNATCOLL.VFS."+" (GNATCOLL.VFS.Dir_Name (Dir)))); + end loop; + end Register_Source_Dirs; + begin + -- Pass the source directories of the project file as -I options. + -- Note that this will duplicate with the project tree traversal + -- below, but we need this project source directories to be + -- picked first. We thus make sure to add them first to the + -- PP_Search_Path list. + + Register_Source_Dirs (Prj); + + -- Pass the source directories of included projects as -I options + + Project.Iterate_Projects + (Prj, Register_Source_Dirs'Access, + Recursive => True, Include_Extended => True); + + -- Get the compiler switches from the project file. When + -- registering a compilation unit for instrumentation, we also + -- fill the compilation unit specific switches that will override + -- the project defaults, if there are any (see + -- Add_Instrumented_Unit). + + Switches := + Prj.Attribute_Value + (Attribute => GPR.Compiler_Default_Switches_Attribute, + Index => Image (Lang)); + + -- If we manage to find appropriate switches, convert them to a + -- string vector import the switches. + + if Switches /= null then + declare + Args : String_Vectors.Vector; + begin + for S of Switches.all loop + Args.Append (To_Unbounded_String (S.all)); + end loop; + GNAT.Strings.Free (Switches); + Import_From_Args (Options, Args); + end; + end if; + + Add_Options (Compiler_Opts, Options, Pass_Builtins => False); + + Result.Compiler_Options (Lang) := Compiler_Opts; + Result.Compiler_Driver (Lang) := +Compiler_Driver; + end; + end loop; + + return Result; + end Load_From_Project; + + -------------------- + -- Create_Context -- + -------------------- + + function Create_Context + (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context is + begin + return IC : Inst_Context do + IC.Ignored_Source_Files_Present := Ignored_Source_Files /= null; + if Ignored_Source_Files /= null then + IC.Ignored_Source_Files := Ignored_Source_Files.all; + end if; + end return; + end Create_Context; + + --------------------- + -- Destroy_Context -- + --------------------- + + procedure Destroy_Context (Context : in out Inst_Context) is + procedure Free is new Ada.Unchecked_Deallocation + (Project_Info, Project_Info_Access); + begin + -- Deallocate all Project_Info in Context, and then clear the hashed + -- map, both to avoid dangling pointers and to make Destroy_Context + -- callable more than once, like conventional deallocation procedures + -- in Ada. + + for Cur in Context.Project_Info_Map.Iterate loop + declare + PI : Project_Info_Access := Project_Info_Maps.Element (Cur); + begin + Free (PI); + end; + end loop; + Context.Project_Info_Map := Project_Info_Maps.Empty_Map; + end Destroy_Context; + + ---------------------------- + -- Is_Ignored_Source_File -- + ---------------------------- + + function Is_Ignored_Source_File + (Context : Inst_Context; Filename : String) return Boolean + is + begin + return + Context.Ignored_Source_Files_Present + and then GNAT.Regexp.Match + (S => Fold_Filename_Casing (Filename), + R => Context.Ignored_Source_Files); + end Is_Ignored_Source_File; + + -------------------------------- + -- Get_Or_Create_Project_Info -- + -------------------------------- + + function Get_Or_Create_Project_Info + (Context : in out Inst_Context; + Project : Project_Type) return Project_Info_Access + is + use Project_Info_Maps; + + -- Look for an existing Project_Info record corresponding to Project + + Project_Name : constant Unbounded_String := +Project.Name; + Position : constant Cursor := Context.Project_Info_Map.Find + (Project_Name); + begin + if Has_Element (Position) then + return Element (Position); + + else + -- The requested Project_Info record does not exist yet. Create it, + -- register it and return it. + + declare + Storage_Project : constant Project_Type := + Project.Extending_Project (Recurse => True); + -- Actual project that will host instrumented sources: even when + -- we instrument an extended project, the resulting instrumented + -- sources must go to the ultimate extending project's object + -- directory. This is similar to the object directory that hosts + -- object files when GPRbuild processes a project that is + -- extended. + + Result : constant Project_Info_Access := new Project_Info' + (Project => Project, + Externally_Built => Project.Externally_Built, + Output_Dir => +Project_Output_Dir (Storage_Project), + Desc => Load_From_Project (Project)); + begin + Result.Desc.Output_Dir := Result.Output_Dir; + Context.Project_Info_Map.Insert (Project_Name, Result); + return Result; + end; + end if; + end Get_Or_Create_Project_Info; + + ------------------------- + -- Prepare_Output_Dirs -- + ------------------------- + + procedure Prepare_Output_Dirs (IC : Inst_Context) is + use Project_Info_Maps; + begin + for Cur in IC.Project_Info_Map.Iterate loop + declare + Prj_Info : Project_Info renames Element (Cur).all; + Output_Dir : constant String := +(Element (Cur).Output_Dir); + begin + -- Do not create output directories for externally built projects: + -- we don't instrument them and we may not have filesystem + -- permissions to create directories there. + + if not Prj_Info.Externally_Built + and then not Ada.Directories.Exists (Output_Dir) + then + Ada.Directories.Create_Path (Output_Dir); + end if; + end; + end loop; + end Prepare_Output_Dirs; + + --------------------------------- + -- Register_Main_To_Instrument -- + --------------------------------- + + procedure Register_Main_To_Instrument + (Context : in out Inst_Context; + Mains : in out Main_To_Instrument_Vectors.Vector; + File : GNATCOLL.VFS.Virtual_File; + Project : Project_Type) + is + File_Info : constant GNATCOLL.Projects.File_Info := + Standard.Project.Project.Info (File); + CU_Name : constant Compilation_Unit_Name := + To_Compilation_Unit_Name (File_Info); + Prj_Info : constant Project_Info_Access := + Get_Or_Create_Project_Info (Context, Project); + begin + Mains.Append + (Main_To_Instrument' + (CU_Name => CU_Name, + File => File, + Prj_Info => Prj_Info)); + end Register_Main_To_Instrument; + + ------------------ + -- SID_Filename -- + ------------------ + + function SID_Filename + (LU_Info : Library_Unit_Info; + In_Library_Dir : Boolean) return String + is + use GNATCOLL.VFS; + + -- Determine in which project we will put this SID file, and the + -- basename for the SID file to create. Mimic how GNAT creates ALI + -- files: use the project of the main source of the library unit, start + -- from the basename of that source file, replace the last extension + -- with ".sid". Also make sure to use the most extending project in the + -- hierarchy, which is where GPRbuild puts ALI/object files. + + SID_Basename : US.Unbounded_String; + + Project : constant GPR.Project_Type := + GPR.Extending_Project + (Project => LU_Info.Instr_Project, + Recurse => True); + pragma Assert (Project /= GPR.No_Project); + + Output_Directory : constant Virtual_File := + (if In_Library_Dir + then Project.Library_Ali_Directory + else Project.Object_Dir); + begin + case Language_Kind (LU_Info.Language) is + when Unit_Based_Language => + declare + Src_Body_Basename : constant String := +Project.File_From_Unit + (Unit_Name => +LU_Info.Unit_Name, + Part => Unit_Body, + Language => Image (LU_Info.Language), + File_Must_Exist => True); + Src_Spec_Basename : constant String := +Project.File_From_Unit + (Unit_Name => +LU_Info.Unit_Name, + Part => Unit_Spec, + Language => Image (LU_Info.Language), + File_Must_Exist => True); + Src_Basename : constant String := + (if Src_Body_Basename = "" + then Src_Spec_Basename + else Src_Body_Basename); + Src_Ext_Index : constant Positive := + Ada.Strings.Fixed.Index + (Src_Basename, ".", Ada.Strings.Backward); + begin + SID_Basename := + +(Src_Basename (Src_Basename'First .. Src_Ext_Index) + & "sid"); + end; + when File_Based_Language => + SID_Basename := + +Ada.Directories.Simple_Name (+LU_Info.Unit_Name) & ".sid"; + end case; + + return String'(+Output_Directory.Full_Name) / (+SID_Basename); + end SID_Filename; + + ------------------------------ + -- Compilation_Unit_Options -- + ------------------------------ + + function Compilation_Unit_Options + (IC : Inst_Context; + Prj : Prj_Desc; + LU_Info : Library_Unit_Info) return String_Vectors.Vector + is + Result : String_Vectors.Vector; + + procedure Compilation_Unit_Options_Ada; + + ---------------------------------- + -- Compilation_Unit_Options_Ada -- + ---------------------------------- + + procedure Compilation_Unit_Options_Ada is + begin + Result.Append ("--gnatem=" & IC.Mapping_File); + Result.Append ("--gnatec=" & IC.Config_Pragmas_File); + + -- Load the predefined source directories + + for Dir of IC.Predefined_Source_Dirs loop + Result.Append ("--runtime-dir=" & Dir); + end loop; + end Compilation_Unit_Options_Ada; + + begin + -- Depending on the language, pass the right set of options + + case LU_Info.Language is + when Ada_Language => + Compilation_Unit_Options_Ada; + when others => + null; + end case; + + -- Pass the list of sources of interest, to e.g. skip the + -- instrumentation of the spec / body / subunit for an Ada unit if + -- it was requested through a --ignored-source-files switch. + + Result.Append ("--files=@" & IC.Sources_Of_Interest_Response_File); + + -- Pass the right language + + Result.Append (+"--lang=" & Image (LU_Info.Language)); + + -- Pass the project description options + + Result.Append + (String_Vectors.Vector' + (Unparse (Prj, LU_Info.Unit_Name, LU_Info.Language))); + + return Result; + end Compilation_Unit_Options; + + -- Create the instrumenter context + + IC : Inst_Context := Create_Context (Ignored_Source_Files); + + Root_Project_Info : constant Project_Info_Access := + Get_Or_Create_Project_Info (IC, Project.Project.Root_Project); + + -- Create a map from library units to lists of compilation units to + -- instrument for them. + + Instrumented_Sources : Unit_Maps.Map; + -- List of units that should be instrumented + + Files_Of_Interest_Str_Set : String_Sets.Set; + Files_Of_Interest : File_Info_Sets.Set; + -- List of files of interest. + -- + -- This is passed on to instrument-source invocations when instrumenting + -- an Ada file (to know which part of a compilation unit must be + -- instrumented, i.e. spec / body / separates). + + --------------------------- + -- Add_Instrumented_Unit -- + --------------------------- + + procedure Add_Instrumented_Unit + (Project : GPR.Project_Type; Source_File : GPR.File_Info) + is + Language : constant Src_Supported_Language := + To_Language (Source_File.Language); + Lang_Kind : constant Any_Language_Kind := Language_Kind (Language); + + use Unit_Maps; + Unit_Name : constant String := + (case Lang_Kind is + when Unit_Based_Language => + (if Source_File.Unit_Part = Unit_Separate + then Prj_Tree.Info + (Prj_Tree.Other_File (Source_File.File)).Unit_Name + else Source_File.Unit_Name), + when File_Based_Language => + GNATCOLL.VFS."+" (Source_File.File.Full_Name)); + + Prj : constant Project_Info_Access := + Get_Or_Create_Project_Info (IC, Source_File.Project); + + LU_Info : constant Library_Unit_Info := + (Unit_Name => +Unit_Name, + Instr_Project => Project, + Language_Kind => Lang_Kind, + Language => Language, + All_Externally_Built => Prj.Externally_Built); + + begin + -- Check if this is an ignored source file + + if Is_Ignored_Source_File (IC, +Source_File.File.Base_Name) then + return; + end if; + + -- Check if gnatcov was built with support for this language. If not, + -- exit early. + + if not Builtin_Support (Language) then + return; + end if; + + -- Otherwise, this is a source of interest + + Files_Of_Interest.Insert (Source_File); + Files_Of_Interest_Str_Set.Insert (+(+Source_File.File.Full_Name)); + + -- Headers are not instrumented by themselves, so exit early as soon + -- as they have been added to the sources of interest. + + if (Language in C_Family_Language + and then Source_File.Unit_Part = Unit_Spec) + then + return; + end if; + + if not Instrumented_Sources.Contains (Unit_Name) then + Instrumented_Sources.Insert (Unit_Name, LU_Info); + end if; + declare + Cur_Ref : constant Unit_Maps.Reference_Type := + Instrumented_Sources.Reference (Unit_Name); + begin + if not Prj.Externally_Built then + Cur_Ref.Instr_Project := Project; + Cur_Ref.All_Externally_Built := False; + end if; + end; + + -- If the unit belongs to an externally built project, exit after it + -- was added it to the instrumented sources. We won't instrument it + -- in the current instrumentation run, so there is no need to grab + -- information useful for instrumentation purposes. + + if Source_File.Project.Externally_Built + then + return; + end if; + + -- Also get compiler switches that are file-specific and register them + -- in the project description. + + if Language in C_Family_Language then + declare + use type GNAT.Strings.String_List_Access; + Options : Analysis_Options; + Compiler_Opts : String_Vectors.Vector; + Switches : GNAT.Strings.String_List_Access; + Basename : constant String := +Source_File.File.Base_Name; + begin + Switches := + Project.Attribute_Value + (Attribute => GPR.Build ("compiler", "switches"), + Index => Basename); + if Switches /= null then + declare + Args : String_Vectors.Vector; + begin + for S of Switches.all loop + Args.Append (To_Unbounded_String (S.all)); + end loop; + GNAT.Strings.Free (Switches); + Import_From_Args (Options, Args); + end; + Add_Options (Compiler_Opts, Options, Pass_Builtins => False); + Prj.Desc.Compiler_Options_Unit.Insert + (LU_Info.Unit_Name, Compiler_Opts); + end if; + end; + end if; + end Add_Instrumented_Unit; + + Mains_To_Instrument : array (Src_Supported_Language) + of Main_To_Instrument_Vectors.Vector; + -- For each supported language, list of mains to instrument. Note that + -- this is filled even when dump-trigger is manual: in that case the + -- instrumentation of the main will do nothing. + + Exec_Filename : constant String := Ada.Directories.Compose + (Support_Files.Libexec_Dir, + "gnatcov64" & GNAT.OS_Lib.Get_Executable_Suffix.all); + -- Launch gnatcov64 for gnatcov subprocesses (when instrumenting sources + -- and mains), to bypass the wrapper and save some execution time. + + Ada_Instrumenter : aliased Instrument.Ada_Unit.Ada_Instrumenter_Type; + C_Instrumenter : aliased Instrument.C.C_Instrumenter_Type; + CPP_Instrumenter : aliased Instrument.C.CPP_Instrumenter_Type; + Instrumenters : constant array (Src_Supported_Language) + of access Language_Instrumenter'Class := + (Ada_Language => Ada_Instrumenter'Access, + C_Language => C_Instrumenter'Access, + CPP_Language => CPP_Instrumenter'Access); + + -- Start of processing for Instrument_Units_Of_Interest + +begin + -- Set the instrumentation tag + + declare + Time : constant Unsigned_64 := + Unsigned_64 + (GNAT.OS_Lib.To_C (GNAT.OS_Lib.Current_Time)); + Tag : constant String := + Hex_Images.Strip_Zero_Padding + (Hex_Images.Hex_Image (Time)); + -- Tag for the current instrumentation run. Passed on to instrument-main + -- invocations, to have the same tag for mains instrumented at the + -- same time. + + begin + IC.Tag := +Tag; + end; + + -- Delete output directories from previous instrumentations + + Clean_Objdirs; + + -- First get the list of all units of interest + + for Lang in Src_Supported_Language loop + if Src_Enabled_Languages (Lang) + and then Root_Project_Info.Project.Has_Language (Image (Lang)) + then + Project.Enumerate_Sources + (Add_Instrumented_Unit'Access, Lang, Include_Stubs => True); + end if; + end loop; + + -- Remove all of the separate whose parent unit was not instrumented, as + -- this is not supported. TODO???: we should probably issue a warning + -- there. + + for Source of Files_Of_Interest.Copy loop + if Source.Unit_Part = Unit_Separate then + declare + Parent_Unit : constant GNATCOLL.Projects.File_Info := + Project.Project.Info + (Project.Project.Other_File (Source.File)); + begin + if not Files_Of_Interest.Contains (Parent_Unit) then + Files_Of_Interest.Delete (Source); + end if; + end; + end if; + end loop; + + -- If we need to instrument all the mains, also go through them now, so + -- that we can prepare output directories for their projects later on. + -- Note that for user convenience, we want to do this for all the + -- languages that gnatcov supports, even those that are not considered + -- for coverage analysis. + -- + -- If no source file was specified on the command line to be a main, + -- use the list of mains specified in project files. + + if Mains.Is_Empty then + for Lang in Src_Supported_Language loop + for Main of Project.Enumerate_Mains (Lang) loop + Register_Main_To_Instrument + (IC, Mains_To_Instrument (Lang), Main.File, Main.Project); + end loop; + end loop; + + -- Otherwise, make sure we can find the source file of each main in + -- the project tree and that we can instrument them (supported + -- language). + + else + for Filename of Mains loop + declare + use GNATCOLL.VFS; + + F : constant String := +Filename; + Info : constant File_Info := + Project.Project.Root_Project.Create_From_Project (+F); + File : constant Virtual_File := Info.File; + Project : constant Project_Type := Info.Project; + Lang : Any_Language; + begin + if File = No_File or else Project = No_Project then + Outputs.Fatal_Error ("No such source file: " & F); + end if; + + Lang := To_Language_Or_All (Info.Language); + if Lang not in Src_Supported_Language + or else not Builtin_Support (Lang) + then + Outputs.Fatal_Error + ("Cannot instrument main source file (unsupported" + & " language): " & F); + end if; + + Register_Main_To_Instrument + (IC, Mains_To_Instrument (Lang), File, Project); + end; + end loop; + end if; + + -- Check early if there are no sources of interest + + if Files_Of_Interest.Length = 0 then + Outputs.Fatal_Error ("No unit to instrument."); + end if; + + -- Now that we know all the sources we need to instrument, prepare + -- output directories. + + Prepare_Output_Dirs (IC); + + -- Record in a file all of the files and headers of interest. We separate + -- both as we do not expect to have coverage buffers for header files (the + -- coverage data is in including bodies' coverage buffers). + + IC.Mapping_File := + +Create_Ada_Mapping_File (Project.Project.Root_Project); + IC.Config_Pragmas_File := + +Create_Config_Pragmas_File (Project.Project.Root_Project); + IC.Sources_Of_Interest_Response_File := + +To_String (Root_Project_Info.all.Output_Dir) / ".sources_of_interest"; + + -- Set the runtime directories + + declare + use GNATCOLL.VFS; + begin + for Dir of + Project.Project.Root_Project.Get_Environment.Predefined_Source_Path + loop + IC.Predefined_Source_Dirs.Append (+(+Full_Name (Dir))); + end loop; + end; + + -- Initialize the instrumenters: we will use them when parallelization is + -- disabled, but also to generate the unit holding the list of buffers, + -- in one of the supported languages. + + Ada_Instrumenter := + Create_Ada_Instrumenter + (IC.Tag, + +IC.Config_Pragmas_File, + +IC.Mapping_File, + IC.Predefined_Source_Dirs); + C_Instrumenter := Create_C_Instrumenter (IC.Tag); + CPP_Instrumenter := Create_CPP_Instrumenter (IC.Tag); + + -- Write the files of interest to temporary files in the instrumentation + -- directory. + + declare + Sources_Of_Interest_File : Text_Files.File_Type; + -- File containing the list of sources of interest + + begin + Sources_Of_Interest_File.Create + (+IC.Sources_Of_Interest_Response_File); + for Source of Files_Of_Interest loop + Sources_Of_Interest_File.Put_Line (+Source.File.Full_Name); + end loop; + Sources_Of_Interest_File.Close; + end; + + -- Instrument every unit of interest asynchronously + + declare + Instrument_Source_Pool : Process_Pool (Parallelism_Level); + + Instrument_Source_Args : String_Vectors.Vector; + -- Common arguments for all of the gnatcov instrument-source + -- invocations. + + begin + Instrument_Source_Args.Append (+"instrument-source"); + Instrument_Source_Args.Append + (Common_Switches (Cmd_Instrument_Source)); + for Cur in Instrumented_Sources.Iterate loop + declare + Unit_Args : String_Vectors.Vector := + Instrument_Source_Args.Copy; + -- Args specific to a gnatcov instrument-source invocation + -- (e.g. the common arguments + the sources that must be + -- instrumented for a specific unit). + + Unit_Name : constant String := Unit_Maps.Key (Cur); + LU_Info : constant Library_Unit_Info := Unit_Maps.Element (Cur); + + Obj_SID : constant String := + SID_Filename (LU_Info, In_Library_Dir => False); + + Prj : constant Project_Type := LU_Info.Instr_Project; + Desc : constant Prj_Desc := + IC.Project_Info_Map.Element (+Prj.Name).Desc; + begin + -- Skip instrumentation of the unit if it was already + -- instrumented. + + if LU_Info.All_Externally_Built then + goto Continue; + end if; + + -- Add the arguments that are specific to the compilation unit + + Unit_Args.Append + (Compilation_Unit_Options + (IC, + Desc, + LU_Info)); + + Unit_Args.Append (+"--sid=" & Obj_SID); + + -- We instrument the body, spec and separates as a whole + + Unit_Args.Append (+Unit_Name); + + -- According to the set parallelism level, instrument in + -- the same process (thus reusing the libadalang context, which + -- is a big gain of time), or spawn another instrmentation + -- process. + + if Parallelism_Level = 1 then + Instrument.Source + (Unit_Name => Unit_Name, + SID_Name => Obj_SID, + Instrumenter => Instrumenters (LU_Info.Language).all, + Files_Of_Interest => Files_Of_Interest_Str_Set, + Prj => Desc); + else + -- Asynchronously instrument + + Instrument_Source_Pool.Run_Command + (Command => Exec_Filename, + Arguments => Unit_Args, + Origin_Command_Name => "gnatcov instrument", + Ignore_Error => False); + end if; + end; + <> + end loop; + end; + + -- Copy SID files into the library directory + + for LU_Info of Instrumented_Sources loop + declare + Obj_SID : constant String := + SID_Filename (LU_Info, In_Library_Dir => False); + Lib_SID : constant String := + SID_Filename (LU_Info, In_Library_Dir => True); + Success : Boolean; + begin + if not LU_Info.All_Externally_Built and then Obj_SID /= Lib_SID then + + -- Unlike the object directory, which GNATCOLL.Project + -- creates automatically, the library directory may not + -- exist: create it if needed. + + declare + use GNATCOLL.VFS; + begin + Create (Create (+Lib_SID).Dir_Name).Make_Dir; + exception + when Exc : VFS_Directory_Error => + Outputs.Fatal_Error + (Ada.Exceptions.Exception_Message (Exc)); + end; + + GNAT.OS_Lib.Copy_File + (Name => Obj_SID, + Pathname => Lib_SID, + Success => Success, + Mode => GNAT.OS_Lib.Overwrite); + if not Success then + Outputs.Fatal_Error + ("Error while copying " & Obj_SID + & " to the library directory: " & Lib_SID); + end if; + end if; + end; + end loop; + + -- Then, instrument asynchronously every main + + declare + Instrument_Main_Pool : Process_Pool (Parallelism_Level); + Instrument_Main_Args : String_Vectors.Vector; + + Main_Filename : Unbounded_String; + -- Fullname for the main. It can either be an instrumented version of + -- the main (if it also was instrumented as a source), or the original + -- version. + + Explicit_Dump_Config : Any_Dump_Config := Dump_Config; + -- Dump config with explicited defaults. The only interesting thing + -- is the dump-filename-prefix that is computed after the name of + -- the main in the project file, if not specified explicitly on the + -- command line. + + begin + Instrument_Main_Args.Append (+"instrument-main"); + + -- Add the root project name, as the symbol holding the list of + -- coverage buffers is defined accordingly. + + Instrument_Main_Args.Append + (+"--project-name=" & Root_Project_Info.Project.Name); + + Instrument_Main_Args.Append (Common_Switches (Cmd_Instrument_Main)); + + for Language in Src_Supported_Language loop + for Main of Mains_To_Instrument (Language) loop + declare + Unit_Name : constant Unbounded_String := + +(case Main.CU_Name.Language_Kind is + when Unit_Based_Language => + To_Ada (Main.CU_Name.Unit), + when File_Based_Language => (+Main.File.Full_Name)); + Unit_Args : String_Vectors.Vector := + Instrument_Main_Args.Copy; + begin + Unit_Args.Append + (Compilation_Unit_Options + (IC, + Main.Prj_Info.Desc, + Library_Unit_Info' + (Unit_Name => Unit_Name, + Instr_Project => Main.Prj_Info.Project, + Language_Kind => Language_Kind (Language), + Language => Language, + All_Externally_Built => False))); + + -- Pass main-specific dump-config options + + if Dump_Config.Channel = Binary_File then + + -- If no dump filename prefix was specified, compute it + -- here: we use the executable name, that is retrieved from + -- the project. + + if Length (Dump_Config.Filename_Prefix) = 0 then + Explicit_Dump_Config.Filename_Prefix := + +(+Root_Project_Info.Project.Executable_Name + (Main.File.Full_Name)); + end if; + end if; + + Unit_Args.Append (Unparse_Config (Explicit_Dump_Config)); + + -- Then append the main filename. If the main was instrumented + -- as a unit of interest before, then pass the instrumented + -- version. + + if Instrumented_Sources.Contains (+Unit_Name) then + Main_Filename := + +(+Root_Project_Info.Output_Dir) / (+Main.File.Base_Name); + else + Main_Filename := +(+Main.File.Full_Name); + end if; + + Unit_Args.Append (Main_Filename); + + if Parallelism_Level = 1 then + declare + Instr_Units : String_Sets.Set; + begin + for Source of Files_Of_Interest loop + Instr_Units.Insert (+(+Source.File.Full_Name)); + end loop; + Instrument.Main + (Instrumenter => Instrumenters (Language).all, + Dump_Config => Explicit_Dump_Config, + Main_Filename => +Main_Filename, + Prj => Main.Prj_Info.Desc); + end; + else + Instrument_Main_Pool.Run_Command + (Command => Exec_Filename, + Arguments => Unit_Args, + Origin_Command_Name => "gnatcov instrument", + Ignore_Error => False); + end if; + end; + end loop; + end loop; + end; + + if not Args.Bool_Args (Opt_Save_Temps) then + Ada.Directories.Delete_File (+IC.Sources_Of_Interest_Response_File); + end if; + + -- Emit the unit to contain the list of coverage buffers, exported to a + -- C symbol, in one of the language supported by the project. + -- + -- Note that this has an implicit hack to it: if Ada is a language of + -- the project, it will pick it over the others (as it is the first + -- enumeration member of the Src_Supported_Language type). This matters + -- as we make the assumption in the Emit_Dump_Helper_Unit implementation + -- in instrument-ada_unit.adb (when instrumenting for an Ada main) that + -- the Ada package for buffers list units always exists: we need to + -- include it in the main closure, as it puts buffer units in scope + -- by importing them (otherwise they aren't as they are used through + -- C symbol importations). + + declare + use Files_Table; + Instr_Units : Unit_Sets.Set; + begin + for LU_Info of Instrumented_Sources loop + Instr_Units.Insert + (Project_Unit'(LU_Info.Language_Kind, LU_Info.Unit_Name)); + end loop; + for Lang in Src_Supported_Language loop + if Builtin_Support (Lang) + and then Root_Project_Info.Project.Has_Language (Image (Lang)) + then + Instrumenters (Lang).Emit_Buffers_List_Unit + (Instr_Units, Root_Project_Info.Desc); + exit; + end if; + end loop; + end; + + Destroy_Context (IC); + + -- Save the dump trigger+channel information in the root project's + -- object directory. This allows user scripts to automatically know + -- where to expect source trace files (dump channel) without inspecting + -- all inputs (command-line arguments, project file, instrumentation + -- runtime, etc.) and whether that info is reliable (it is not if the + -- dump trigger is manual). + -- + -- TODO: this should go at some point in Instrument_Main (in which case + -- one would be generated per main). + + declare + J : constant GNATCOLL.JSON.JSON_Value := Create_Object; + Filename : constant String := + Project.Output_Dir & "/gnatcov-instr.json"; + begin + J.Set_Field ("dump-trigger", Image (Dump_Config.Trigger)); + J.Set_Field ("dump-channel", Image (Dump_Config.Channel)); + Write (Filename, J, Compact => False); + end; + +end Instrument.Projects; diff --git a/tools/gnatcov/instrument-source.adb b/tools/gnatcov/instrument-source.adb new file mode 100644 index 000000000..1749140fe --- /dev/null +++ b/tools/gnatcov/instrument-source.adb @@ -0,0 +1,66 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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 Checkpoints; use Checkpoints; +with Coverage; +with Instrument.Common; use Instrument.Common; +with Strings; use Strings; +with Traces_Files; use Traces_Files; + +-- Implementation of the gnatcov instrument-source command, which instrument +-- the given command-line unit. If the unit is of a unit based language, the +-- unit name is the name of the unit, otherwise, it is the (full) filename. + +procedure Instrument.Source + (Unit_Name : String; + SID_Name : String; + Instrumenter : in out Language_Instrumenter'Class; + Files_Of_Interest : String_Sets.Set; + Prj : Prj_Desc) +is + Context : aliased Coverage.Context := Coverage.Get_Context; +begin + -- Even though instrumentation does not create any traces, the structure + -- of a SID file is basically a checkpoint, so it has a Trace_Kind field + -- in its header. Instead of leaving it to Unknown (default value) mark it + -- as Source_Trace_File so that when the .sid file is loaded, it will set + -- gnatcov in "source trace mode" and it will be rejected if binary traces + -- have already been loaded. + + Update_Current_Trace_Kind (Source_Trace_File); + + -- Instrument all of the source files implementing the compilation unit. + -- For Ada, this means instrumenting the body / spec / separates, and for + -- C/C++, this means instrumenting the .c file and the included headers. + + Instrumenter.Instrument_Unit (Unit_Name, Prj, Files_Of_Interest); + + -- Save the SCOs for the unit in the SID file + + Checkpoints.Checkpoint_Save + (SID_Name, + Context'Access, + Purpose => Checkpoints.Instrumentation); + + if Switches.Verbose then + SC_Obligations.Dump_All_SCOs; + end if; + + Checkpoints.Checkpoint_Clear; + +end Instrument.Source; diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 99677aa31..3cd906b01 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -19,36 +19,18 @@ -- Source instrumentation with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Containers; use Ada.Containers; -with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Directories; -with Ada.Exceptions; -with Ada.Strings.Fixed; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; -with Ada.Text_IO; use Ada.Text_IO; +with Ada.Strings; with Ada.Strings.Hash; with Ada.Strings.Unbounded.Equal_Case_Insensitive; with Ada.Strings.Unbounded.Less_Case_Insensitive; -with Ada.Unchecked_Deallocation; with Interfaces; use Interfaces; -with GNAT.OS_Lib; - -with GNATCOLL.JSON; use GNATCOLL.JSON; -with GNATCOLL.VFS; use GNATCOLL.VFS; - -with Checkpoints; -with Coverage; -with Files_Table; -with Hex_Images; use Hex_Images; -with Instrument.Ada_Unit; -with Instrument.Clean_Objdirs; -with Instrument.C; -with Instrument.Common; use Instrument.Common; -with JSON; use JSON; -with Outputs; -with Paths; use Paths; -with Project; + +with GNATCOLL.VFS; use GNATCOLL.VFS; + +with Command_Line; use Command_Line; +with Hex_Images; use Hex_Images; package body Instrument is @@ -417,629 +399,118 @@ package body Instrument is end if; end Find_Instrumented_Unit; - package GPR renames GNATCOLL.Projects; - - type CU_Name_With_Ignore is record - Name : Compilation_Unit_Name; - Ignored : Boolean; - end record; - - function "<" (Left, Right : CU_Name_With_Ignore) return Boolean - is (if Left.Name = Right.Name - then Left.Ignored < Right.Ignored - else Left.Name < Right.Name); - - package CU_Name_Vectors is new Ada.Containers.Vectors - (Positive, CU_Name_With_Ignore); - - type Library_Unit_Info is record - CU_Names : CU_Name_Vectors.Vector; - -- List of compilation units implementing this library unit - - Body_Project, Spec_Project : GPR.Project_Type; - -- Projects that own the body/spec for this library unit - - Language_Kind : Any_Language_Kind; - -- Higher level representation of a language (unit-based or file-based) - - Language : Any_Language; - -- Actual language representation - end record; - type Library_Unit_Info_Access is access Library_Unit_Info; - - type Ignored_Unit_Info is record - Filename : Unbounded_String; - -- Name of the source file for this unit - - Prj_Info : Project_Info_Access; - -- Reference to the Project_Info record corresponding to the project - -- that owns the source file for this unit. - end record; - - type Ignored_Unit_Info_Access is access all Ignored_Unit_Info; - - package Ignored_Units_Maps is new Ada.Containers.Ordered_Maps - (Compilation_Unit_Name, Ignored_Unit_Info_Access); - - procedure Free is new Ada.Unchecked_Deallocation - (Ignored_Unit_Info, Ignored_Unit_Info_Access); - - package Library_Unit_Maps is new Ada.Containers.Indefinite_Ordered_Maps - (String, Library_Unit_Info_Access); - -- Map to associate a list of compilation units to instrument to a library - -- unit (indexed by the library unit name, i.e. the unit name or the - -- full name depending on the language kind for the library unit). - -- - -- For file-based languages, the library unit only has one compilation - -- unit associated to it (that is the library unit itself, for which the - -- name is the actual base filename). - - procedure Get_Or_Create - (Map : in out Library_Unit_Maps.Map; - Library_Unit : String; - Info : out Library_Unit_Info_Access); - -- Look for the info corresponding to Library_Unit in Map. Create it if - -- it does not exist yet and put it in Info. - - function SID_Filename - (Cur : Library_Unit_Maps.Cursor; - In_Library_Dir : Boolean) return String; - -- Return the filename of the SID file to create for the given library - -- unit. If In_Library_Dir is true, then return a filename located in the - -- project library directory. Otherwise, the filename is located in the - -- object directory. - - procedure Prepare_Output_Dirs (IC : Inst_Context); - -- Make sure we have the expected tree of directories for the - -- instrumentation output. - - ------------------- - -- Get_Or_Create -- - ------------------- - - procedure Get_Or_Create - (Map : in out Library_Unit_Maps.Map; - Library_Unit : String; - Info : out Library_Unit_Info_Access) - is - use Library_Unit_Maps; - Cur : constant Cursor := Map.Find (Library_Unit); - begin - if Has_Element (Cur) then - Info := Element (Cur); - else - Info := new Library_Unit_Info; - Info.Body_Project := GPR.No_Project; - Info.Spec_Project := GPR.No_Project; - Map.Insert (Library_Unit, Info); - end if; - end Get_Or_Create; - - ------------------ - -- SID_Filename -- - ------------------ - - function SID_Filename - (Cur : Library_Unit_Maps.Cursor; - In_Library_Dir : Boolean) return String - is - use Library_Unit_Maps; - - LU_Name : constant String := Key (Cur); - Info : Library_Unit_Info renames Element (Cur).all; - - -- Determine in which project we will put this SID file, and the - -- basename for the SID file to create. Mimic how GNAT creates ALI - -- files: use the project of the main source of the library unit, start - -- from the basename of that source file, replace the last extension - -- with ".sid". Also make sure to use the most extending project in the - -- hierarchy, which is where GPRbuild puts ALI/object files. - - SID_Basename : US.Unbounded_String; - - Use_Spec : constant Boolean := - Info.Body_Project = GPR.No_Project; - Project : constant GPR.Project_Type := - GPR.Extending_Project - (Project => (if Use_Spec - then Info.Spec_Project - else Info.Body_Project), - Recurse => True); - pragma Assert (Project /= GPR.No_Project); - - Output_Directory : constant Virtual_File := - (if In_Library_Dir - then Project.Library_Ali_Directory - else Project.Object_Dir); - begin - case Info.Language_Kind is - when Unit_Based_Language => - declare - Src_Basename : constant String := +Project.File_From_Unit - (Unit_Name => LU_Name, - Part => (if Use_Spec - then Unit_Spec - else Unit_Body), - Language => Image (Info.Language), - File_Must_Exist => False); - Src_Ext_Index : constant Positive := - Ada.Strings.Fixed.Index - (Src_Basename, ".", Ada.Strings.Backward); - begin - SID_Basename := - +(Src_Basename (Src_Basename'First .. Src_Ext_Index) - & "sid"); - end; - when File_Based_Language => - SID_Basename := +(Ada.Directories.Simple_Name (LU_Name & ".sid")); - end case; - - return String'(+Output_Directory.Full_Name) / (+SID_Basename); - end SID_Filename; - - ------------------------- - -- Prepare_Output_Dirs -- - ------------------------- - - procedure Prepare_Output_Dirs (IC : Inst_Context) is - use Project_Info_Maps; - begin - for Cur in IC.Project_Info_Map.Iterate loop - declare - Prj_Info : Project_Info renames Element (Cur).all; - Output_Dir : constant String := - +(Element (Cur).Output_Dir); - begin - -- Do not create output directories for externally built projects: - -- we don't instrument them and we may not have filesystem - -- permissions to create directories there. - - if not Prj_Info.Externally_Built - and then not Ada.Directories.Exists (Output_Dir) - then - Ada.Directories.Create_Path (Output_Dir); - end if; - end; - end loop; - end Prepare_Output_Dirs; - - ---------------------------------- - -- Instrument_Units_Of_Interest -- - ---------------------------------- - - procedure Instrument_Units_Of_Interest - (Dump_Config : Any_Dump_Config; - Language_Version : Any_Language_Version; - Ignored_Source_Files : access GNAT.Regexp.Regexp; - Mains : String_Vectors.Vector) - is - use String_Vectors; - - -- Initialize all the instrumenters - - Ada_Instrumenter : aliased Instrument.Ada_Unit.Ada_Instrumenter_Type := - Instrument.Ada_Unit.Create_Ada_Instrumenter (Language_Version); - C_Instrumenter : aliased Instrument.C.C_Instrumenter_Type := - (null record); - CPP_Instrumenter : aliased Instrument.C.CPP_Instrumenter_Type := - (null record); - - Instrumenters : constant array (Src_Supported_Language) - of access Language_Instrumenter'Class := - (Ada_Language => Ada_Instrumenter'Access, - C_Language => C_Instrumenter'Access, - CPP_Language => CPP_Instrumenter'Access); - - -- Create a map from library units to lists of compilation units to - -- instrument for them. - - LU_Map : Library_Unit_Maps.Map; - Current_LU_Info : Library_Unit_Info_Access; - Ignored_Units : Ignored_Units_Maps.Map; - - Mains_To_Instrument : array (Src_Supported_Language) - of Main_To_Instrument_Vectors.Vector; - -- For each supported language, list of mains to instrument. Always - -- empty when Dump_Config.Trigger is Manual. - - -- Create the instrumenter context - - IC : Inst_Context := Create_Context (Ignored_Source_Files); + ---------------------------- + -- Load_From_Command_Line -- + ---------------------------- - Root_Project_Info : constant Project_Info_Access := - Get_Or_Create_Project_Info (IC, Project.Project.Root_Project); + function Load_From_Command_Line return Prj_Desc is + use Command_Line.Parser; + Language : constant Some_Language := + To_Language (+Args.String_Args (Opt_Lang).Value); + Result : Prj_Desc; - procedure Add_Instrumented_Unit_Wrapper - (Project : GPR.Project_Type; Source_File : GPR.File_Info); - -- Add this source file to the list of units to instrument. For unit- - -- based languages, also add subunits that depend on this source file. + procedure Fill_If_Present + (Opt : String_Options; Field : out Unbounded_String); - ----------------------------------- - -- Add_Instrumented_Unit_Wrapper -- - ----------------------------------- + --------------------- + -- Fill_If_Present -- + --------------------- - procedure Add_Instrumented_Unit_Wrapper - (Project : GPR.Project_Type; Source_File : GPR.File_Info) + procedure Fill_If_Present + (Opt : String_Options; Field : out Unbounded_String) is - procedure Add_Instrumented_Unit - (CU_Name : Compilation_Unit_Name; Info : GPR.File_Info); - -- Wrapper for Instrument.Common.Add_Instrumented_Unit - - --------------------------- - -- Add_Instrumented_Unit -- - --------------------------- - - procedure Add_Instrumented_Unit - (CU_Name : Compilation_Unit_Name; Info : GPR.File_Info) - is - Should_Ignore : constant Boolean := - Is_Ignored_Source_File (IC, +Info.File.Base_Name); - begin - Current_LU_Info.CU_Names.Append - (CU_Name_With_Ignore'(Name => CU_Name, - Ignored => Should_Ignore)); - if Should_Ignore then - Ignored_Units.Insert - (CU_Name, - new Ignored_Unit_Info' - (Filename => To_Unbounded_String (+Info.File.Base_Name), - Prj_Info => Get_Or_Create_Project_Info - (IC, Info.Project))); - else - Add_Instrumented_Unit (IC, Info.Project, Info); - end if; - end Add_Instrumented_Unit; - - Language : constant Src_Supported_Language := - To_Language (Source_File.Language); - - -- Start of processing for Add_Instrumented_Unit_Wrapper - + Opt_Ref : constant Option_Reference := (String_Opt, Opt); begin - -- Skip this source file if the instrumenter requires it - - if Instrumenters (Language).Skip_Source_File (Source_File) then - return; + if Is_Present (Args, Opt_Ref) then + Field := +Value (Args, Opt); end if; - - declare - CU_Name : constant Compilation_Unit_Name := - To_Compilation_Unit_Name (Source_File); - - Unit_Name : constant String := - (case CU_Name.Language_Kind is - when Unit_Based_Language => To_Ada (CU_Name.Unit), - - -- For file-based languages, we need to use the full - -- name to account for homonyms. - - when File_Based_Language => +Source_File.File.Full_Name); - - begin - -- Get the vector in which we will record the compilation units - -- that the following call to Find_Units will list. - - Get_Or_Create (LU_Map, Unit_Name, Current_LU_Info); - - -- Keep track of projects that own this library unit's source - -- files for its spec/body. - - case Source_File.Unit_Part is - when GPR.Unit_Body => Current_LU_Info.Body_Project := Project; - when GPR.Unit_Spec => Current_LU_Info.Spec_Project := Project; - - -- Subunits cannot be units of interest, so Enumerate_Sources - -- should not be able to call Find_Units_Wrapper with a - -- subunit. Hence, the following should be unreachable. - - when GPR.Unit_Separate => - raise Program_Error with "unreachable code"; - end case; - - Current_LU_Info.Language_Kind := CU_Name.Language_Kind; - Current_LU_Info.Language := To_Language (Source_File.Language); - - case CU_Name.Language_Kind is - when Unit_Based_Language => - Instrument.Ada_Unit.Find_Ada_Units - (Ada_Instrumenter, - CU_Name, - Source_File, - Add_Instrumented_Unit'Access); - when File_Based_Language => - Add_Instrumented_Unit (CU_Name, Source_File); - end case; - end; - end Add_Instrumented_Unit_Wrapper; - - -- Start of processing for Instrument_Units_Of_Interest - + end Fill_If_Present; begin - -- Delete output directories from previous instrumentations - - Clean_Objdirs; + if Language in C_Family_Language then + Fill_If_Present + (Opt_Compiler_Driver, Result.Compiler_Driver (Language)); + end if; + Fill_If_Present (Opt_Output_Directory, Result.Output_Dir); + Fill_If_Present (Opt_Spec_Suffix, Result.Spec_Suffix (Language)); + Fill_If_Present (Opt_Body_Suffix, Result.Body_Suffix (Language)); + Fill_If_Present (Opt_Project_Name, Result.Prj_Name); + Fill_If_Present (Opt_Dot_Replacement, Result.Dot_Replacement); - -- First get the list of all units of interest + -- Compiler options are loaded through the --c/c++-opts switch - for Lang in Src_Supported_Language loop - if Src_Enabled_Languages (Lang) then - Project.Enumerate_Sources - (Add_Instrumented_Unit_Wrapper'Access, Lang); - end if; - end loop; + return Result; + end Load_From_Command_Line; - -- If we need to instrument all the mains, also go through them now, so - -- that we can prepare output directories for their projects later on. - -- Note that for user convenience, we want to do this for all the - -- languages that gnatcov supports, even those that are not considered - -- for coverage analysis. + ------------- + -- Unparse -- + ------------- - if Dump_Config.Trigger /= Manual then + function Unparse + (Desc : Prj_Desc; + Unit_Name : Unbounded_String; + Lang : Src_Supported_Language) return String_Vectors.Vector + is + Result : String_Vectors.Vector; + Compiler_Opts : String_Vectors.Vector; + begin + -- Pass the right body / spec suffixes - -- If no source file was specified on the command line to be a main, - -- use the list of mains specified in project files. + if Desc.Body_Suffix (Lang) /= Null_Unbounded_String then + Result.Append (+"--body-suffix"); + Result.Append (Desc.Body_Suffix (Lang)); + end if; - if Mains.Is_Empty then - for Lang in Src_Supported_Language loop - for Main of Project.Enumerate_Mains (Lang) loop - Register_Main_To_Instrument - (IC, Mains_To_Instrument (Lang), Main.File, Main.Project); - end loop; - end loop; + if Desc.Spec_Suffix (Lang) /= Null_Unbounded_String then + Result.Append (+"--spec-suffix"); + Result.Append (Desc.Spec_Suffix (Lang)); + end if; - -- Otherwise, make sure we can find the source file of each main in - -- the project tree and that we can instrument them (supported - -- language). + if Desc.Dot_Replacement /= Null_Unbounded_String then + Result.Append (+"--dot-replacement"); + Result.Append (Desc.Dot_Replacement); + end if; + if Lang in C_Family_Language then + Compiler_Opts.Append (Desc.Search_Paths); + if Desc.Compiler_Options_Unit.Contains (Unit_Name) then + Compiler_Opts.Append + (Desc.Compiler_Options_Unit.Element (Unit_Name)); else - for Filename of Mains loop - declare - F : constant String := +Filename; - Info : constant File_Info := - Project.Project.Root_Project.Create_From_Project (+F); - File : constant Virtual_File := Info.File; - Project : constant Project_Type := Info.Project; - Lang : Any_Language; - begin - if File = No_File or else Project = No_Project then - Outputs.Fatal_Error ("No such source file: " & F); - end if; - - Lang := To_Language_Or_All (Info.Language); - if Lang not in Src_Supported_Language then - Outputs.Fatal_Error - ("Cannot instrument main source file (unsupported" - & " language): " & F); - end if; - - Register_Main_To_Instrument - (IC, Mains_To_Instrument (Lang), File, Project); - end; - end loop; + Compiler_Opts.Append (Desc.Compiler_Options (Lang)); + end if; + if not Compiler_Opts.Is_Empty then + case C_Family_Language (Lang) is + when CPP_Language => + Result.Append (+"--c++-opts"); + when C_Language => + Result.Append (+"--c-opts"); + end case; end if; - end if; - - -- Know that we know all the sources we need to instrument, prepare - -- output directories. - - Prepare_Output_Dirs (IC); - - -- For each library unit... - - for Cur in LU_Map.Iterate loop - - -- Instrument compilation units (only the ones this library unit - -- owns). Sort them first, so that the instrumentation order is - -- deterministic. - declare - package Sorting is new CU_Name_Vectors.Generic_Sorting; - - LU_Info : constant Library_Unit_Info_Access := - Library_Unit_Maps.Element (Cur); - All_Externally_Built : Boolean := True; + First : Boolean := True; + Compiler_Opts_Str : Unbounded_String; begin - Sorting.Sort (LU_Info.CU_Names); - for CU of LU_Info.CU_Names loop - if CU.Ignored then - declare - Unit_Info : Ignored_Unit_Info renames - Ignored_Units.Element (CU.Name).all; - Filename : constant String := To_String - (Unit_Info.Filename); - begin - -- Simply add the unit to the file table if it is not - -- externally built. - - if not Unit_Info.Prj_Info.Externally_Built then - All_Externally_Built := False; - Files_Table.Consolidate_Ignore_Status - (Index => Files_Table.Get_Index_From_Generic_Name - (Name => Filename, - Kind => Files_Table.Source_File), - Status => Files_Table.Always); - end if; - end; + for Compiler_Opt of Compiler_Opts loop + if First then + First := False; else - declare - Unit_Info : Instrumented_Unit_Info renames - IC.Instrumented_Units.Element (CU.Name).all; - Filename : constant String := - To_String (Unit_Info.Filename); - Basename : constant String := - Ada.Directories.Simple_Name (Filename); - begin - -- Do not process units from externally built projects - - if not Unit_Info.Prj_Info.Externally_Built then - - -- Keep a note that we are processing at least one - -- source file from a non-externally built project. - - All_Externally_Built := False; - - -- Run the instrumentation for this file - - if Verbose then - Put_Line ("Instrumenting " & Basename); - end if; - Instrumenters (Unit_Info.Language).Instrument_Unit - (CU.Name, Unit_Info); - - -- Update the Ignore_Status of the CU we instrumented - - Files_Table.Consolidate_Ignore_Status - (Index => Files_Table.Get_Index_From_Generic_Name - (Name => Filename, - Kind => Files_Table.Source_File, - Indexed_Simple_Name => True), - Status => Files_Table.Never); - end if; - end; + Append (Compiler_Opts_Str, ","); end if; + Append (Compiler_Opts_Str, Compiler_Opt); end loop; - - -- Except for units entirely externally built (the spec, the body, - -- and potential subunits all belong to externally built - -- projects), emit a SID file to contain mappings between bits in - -- coverage buffers and SCOs. - - if not All_Externally_Built then - declare - Context : aliased Coverage.Context := Coverage.Get_Context; - Obj_SID : constant String := - SID_Filename (Cur, In_Library_Dir => False); - Lib_SID : constant String := - SID_Filename (Cur, In_Library_Dir => True); - Success : Boolean; - begin - Checkpoints.Checkpoint_Save - (Obj_SID, - Context'Access, - Purpose => Checkpoints.Instrumentation); - - -- If the object directory is different from the library - -- directory, copy the SID file to the library directory. - -- This allows "gnatcov coverage" to automatically pick it - -- up if the project is later made externally built. - - if Obj_SID /= Lib_SID then - - -- Unlike the object directory, which GNATCOLL.Project - -- creates automatically, the library directory may not - -- exist: create it if needed. - - begin - Create (Create (+Lib_SID).Dir_Name).Make_Dir; - exception - when Exc : VFS_Directory_Error => - Outputs.Fatal_Error - (Ada.Exceptions.Exception_Message (Exc)); - end; - - GNAT.OS_Lib.Copy_File - (Name => Obj_SID, - Pathname => Lib_SID, - Success => Success, - Mode => GNAT.OS_Lib.Overwrite); - if not Success then - Outputs.Fatal_Error - ("Error while copying " & Obj_SID - & " to the library directory: " & Lib_SID); - end if; - end if; - end; - - if Switches.Verbose then - SC_Obligations.Dump_All_SCOs; - end if; - end if; + Result.Append (Compiler_Opts_Str); end; - Checkpoints.Checkpoint_Clear; - end loop; - - if IC.Instrumented_Units.Length = 0 then - Outputs.Fatal_Error ("No unit to instrument."); + if Desc.Compiler_Driver (Lang) /= Null_Unbounded_String then + Result.Append (+"--compiler-driver"); + Result.Append (Desc.Compiler_Driver (Lang)); + end if; end if; - declare - Instrumented_Units : Instrument.Common.CU_Name_Vectors.Vector; - -- List of instrumented units + Result.Append (+"--output-dir"); + Result.Append (Desc.Output_Dir); - begin - for Cur in IC.Instrumented_Units.Iterate loop - Instrumented_Units.Append (Instrumented_Unit_Maps.Key (Cur)); - end loop; - - -- Emit the unit to contain the list of coverage buffers, exported to - -- a C symbol, in one of the language supported by the project. - -- - -- Note that this has an implicit hack to it: if Ada is a language of - -- the project, it will pick it over the others (as it is the first - -- enumeration member of the Src_Supported_Language type). This - -- matters as we make the assumption in the Emit_Dump_Helper_Unit - -- implementation in instrument-ada_unit.adb (when instrumenting for - -- an Ada main) that the Ada package for buffers list units always - -- exists: we need to include it in the main closure, as it puts - -- buffer units in scope by importing them (otherwise they aren't - -- as they are used through C symbol importations). - - for Language in Src_Supported_Language loop - if Project.Project.Root_Project.Has_Language (Image (Language)) - then - Instrumenters (Language).Emit_Buffers_List_Unit - (Root_Project_Info.all, Instrumented_Units); - exit; - end if; - end loop; - - -- Instrument all the mains to add the dump of coverage buffers. - -- Make sure to pass the instrumented version if the main is a unit - -- of interest. - - for Language in Src_Supported_Language loop - - for Main of Mains_To_Instrument (Language) loop - declare - Filename : constant String := - (if IC.Instrumented_Units.Contains (Main.CU_Name) - then (+Main.Prj_Info.Output_Dir) / (+Main.File.Base_Name) - else +Main.File.Full_Name); - begin - Instrumenters (Language).Auto_Dump_Buffers_In_Main - (Filename, - Instrumented_Units, - Dump_Config, - Main.Prj_Info.all); - end; - end loop; - end loop; - end; - - -- Deallocate Ignored_Unit_Infos - - for IU of Ignored_Units loop - Free (IU); - end loop; - Ignored_Units := Ignored_Units_Maps.Empty_Map; - - -- Save the dump trigger+channel information in the root project's - -- object directory. This allows user scripts to automatically know - -- where to expect source trace files (dump channel) without inspecting - -- all inputs (command-line arguments, project file, instrumentation - -- runtime, etc.) and whether that info is reliable (it is not if the - -- dump trigger is manual). - - declare - J : constant JSON_Value := Create_Object; - Filename : constant String := - Project.Output_Dir & "/gnatcov-instr.json"; - begin - J.Set_Field ("dump-trigger", Image (Dump_Config.Trigger)); - J.Set_Field ("dump-channel", Image (Dump_Config.Channel)); - Write (Filename, J, Compact => False); - end; - end Instrument_Units_Of_Interest; + return Result; + end Unparse; end Instrument; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 47a8d8b22..3b89e5387 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -18,11 +18,11 @@ -- Support for source instrumentation +with Ada.Containers.Hashed_Maps; with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; -with Ada.Strings.Unbounded; - -with GNAT.Regexp; +with Ada.Strings.Unbounded.Hash; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with GNATCOLL.Projects; use GNATCOLL.Projects; @@ -38,6 +38,12 @@ package Instrument is package US renames Ada.Strings.Unbounded; + package GPR renames GNATCOLL.Projects; + + use type Ada.Containers.Count_Type; + + Parallelism_Level : Natural := 1; + function Language_Kind (Language : Some_Language) return Any_Language_Kind; -- Returns the language kind (unit-based or file-based) for the given @@ -170,27 +176,58 @@ package Instrument is -- Return the CU_Id corresponding to the given instrumented unit, or -- No_CU_Id if not found. - procedure Instrument_Units_Of_Interest - (Dump_Config : Any_Dump_Config; - Language_Version : Any_Language_Version; - Ignored_Source_Files : access GNAT.Regexp.Regexp; - Mains : String_Vectors.Vector); - -- Generate instrumented sources for the source files of all units of - -- interest. Also save mappings between coverage buffers and SCOs for each - -- library units to SID files (one per library unit). - -- - -- Depending on Dump_Config, instrument mains to schedule a call to the - -- dump procedure for the list of coverage buffers in all mains in the - -- project. - -- - -- Language_Version restricts what source constructs the instrumenter is - -- allowed to use. For instance, if Ada_2005 (or a lower version) is - -- passed, it will not be allowed to introduce expression functions, and - -- thus will emit a warning when it needed to do so. - -- - -- If Ignored_Source_File is non-null, ignore files whose names match the - -- accessed pattern. - -- - -- Mains is the list of source files that were listed on the command line: - -- if non-empty, they replace the mains specified in project files. + type Lang_Array is array (Src_Supported_Language range <>) + of Unbounded_String; + type C_Lang_Array_Vec is array (C_Family_Language) of String_Vectors.Vector; + + package String_Vectors_Maps is new Ada.Containers.Hashed_Maps + (Key_Type => Unbounded_String, + Element_Type => String_Vectors.Vector, + Equivalent_Keys => Ada.Strings.Unbounded."=", + Hash => Ada.Strings.Unbounded.Hash, + "=" => String_Vectors."="); + + type Prj_Desc is record + Prj_Name : Unbounded_String; + -- Name for the project + + Output_Dir : Unbounded_String; + -- Where the instrumented sources and coverage buffer units are + -- generated. + + Spec_Suffix, Body_Suffix : Lang_Array (Src_Supported_Language); + -- Suffixes for the body and the spec + + Dot_Replacement : Unbounded_String; + -- Character to use as identifier separator for file naming (used for + -- unit-based languages). + + Compiler_Driver : Lang_Array (C_Family_Language); + -- Compiler used to compile the sources + + Compiler_Options : C_Lang_Array_Vec; + -- For languages resorting to the compiler to preprocess sources, list + -- of compiler switches to pass to the preprocessor invocation. + + Compiler_Options_Unit : String_Vectors_Maps.Map; + -- Compiler switches applying to a specific unit + + Search_Paths : String_Vectors.Vector; + -- List of compiler switches to look up the project source directories + + end record; + -- This record stores the information that is required from the project + -- for instrumentation purposes. + + type Prj_Desc_Access is access Prj_Desc; + + function Load_From_Command_Line return Prj_Desc; + + function Unparse + (Desc : Prj_Desc; + Unit_Name : Unbounded_String; + Lang : Src_Supported_Language) return String_Vectors.Vector; + -- Return a list of command line switches holding all the project + -- information for the given Unit_Name of the language Lang. + end Instrument; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 9168877fc..b1f69e211 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -31,9 +31,10 @@ with GNATCOLL.Traces; with GNATCOLL.Projects.Aux; with GNATCOLL.VFS; use GNATCOLL.VFS; +with Command_Line; use Command_Line; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -with Instrument; use Instrument; with Inputs; use Inputs; +with Instrument; use Instrument; with Outputs; use Outputs; with Paths; use Paths; @@ -231,10 +232,6 @@ package body Project is -- Note that this also returns source files for mains that are not units of -- interest. - function Runtime_Has_File (Filename : Filesystem_String) return Boolean; - -- Return whether Filename can be found among the sources of the - -- configured Ada runtime. - --------------------- -- To_Project_Unit -- --------------------- @@ -631,51 +628,6 @@ package body Project is end; end Find_Source_File; - ---------------------- - -- Runtime_Has_File -- - ---------------------- - - function Runtime_Has_File (Filename : Filesystem_String) return Boolean is - Result_File : Virtual_File; - -- Virtual_File for Ada.Finalization. Only search predefined sources. - Ambiguous : Boolean; - -- Required in the call for GNATCOLL.Projects.Create - begin - GNATCOLL.Projects.Create - (Self => Prj_Tree.all, - Name => Filename, - Use_Object_Path => False, - Ambiguous => Ambiguous, - File => Result_File, - Predefined_Only => True); - - -- We don't expect there to be multiple homonyms for the runtime files - - pragma Assert (not Ambiguous); - return Result_File /= No_File; - end Runtime_Has_File; - - ------------------------------ - -- Runtime_Has_Finalization -- - ------------------------------ - - function Runtime_Supports_Finalization return Boolean is - (Runtime_Has_File ("a-finali.ads")); - - --------------------------------------- - -- Runtime_Supports_Task_Termination -- - --------------------------------------- - - function Runtime_Supports_Task_Termination return Boolean is - begin - -- We need both Ada.Task_Identification (a-taside.ads) and - -- Ada.Task_Termination (a-taster.ads) to be able to use task - -- termination. - - return Runtime_Has_File ("a-taster.ads") - and then Runtime_Has_File ("a-taside.ads"); - end Runtime_Supports_Task_Termination; - ---------------- -- Initialize -- ---------------- @@ -1009,7 +961,9 @@ package body Project is -- Units attributes only apply to the project itself. Iterate_Source_Files - (Project, Process_Source_File'Access, Recursive => False); + (Project, Process_Source_File'Access, + Recursive => False, + Include_Stubs => True); Inc_Units_Defined := True; end; end if; @@ -1646,7 +1600,7 @@ package body Project is procedure Finalize is begin - if Prj_Tree /= null then + if Prj_Tree /= null and then not Args.Bool_Args (Opt_Save_Temps) then GNATCOLL.Projects.Aux.Delete_All_Temp_Files (Prj_Tree.Root_Project); end if; end Finalize; @@ -1660,4 +1614,46 @@ package body Project is return Prj_Tree; end Project; + ------------------- + -- Source_Suffix -- + ------------------- + + function Source_Suffix + (Lang : Src_Supported_Language; + Part : GNATCOLL.Projects.Unit_Parts; + Project : GNATCOLL.Projects.Project_Type) return String + is + Attr : constant Attribute_Pkg_String := + Build + (Package_Name => "Naming", + Attribute_Name => + (case Part is + when Unit_Body => "Body_Suffix", + when Unit_Spec => "Spec_Suffix", + when Unit_Separate => raise Program_Error)); + begin + case Part is + when Unit_Body => + return Project.Attribute_Value + (Attribute => Attr, + Index => Image (Lang), + Default => (case Lang is + when Ada_Language => ".adb", + when C_Language => ".c", + when CPP_Language => ".cpp")); + + when Unit_Spec => + return Project.Attribute_Value + (Attribute => Attr, + Index => Image (Lang), + Default => (case Lang is + when Ada_Language => ".ads", + when C_Language => ".h", + when CPP_Language => ".hh")); + + when Unit_Separate => + return (raise Program_Error); + end case; + end Source_Suffix; + end Project; diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 88c0ee7f3..f342244f4 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -182,15 +182,6 @@ package Project is -- -- If no project is loaded, just return null. - function Runtime_Supports_Finalization return Boolean with - Pre => Is_Project_Loaded; - -- Return whether the configured runtime includes the Ada.Finalization unit - - function Runtime_Supports_Task_Termination return Boolean with - Pre => Is_Project_Loaded; - -- Return whether the configured runtime has necessary units to implement - -- the ravenscar-task-termination dump trigger. - function Switches (Op : String) return String_List_Access with Pre => Is_Project_Loaded; -- Return a list of gnatcov switches defined by the root project. Caller @@ -244,4 +235,10 @@ package Project is -- Unless Include_Extended is True, only process ultimate extending -- projects. + function Source_Suffix + (Lang : Src_Supported_Language; + Part : GNATCOLL.Projects.Unit_Parts; + Project : GNATCOLL.Projects.Project_Type) return String; + -- Return the filename suffix corresponding for Part files and Lang + end Project; diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 22498f738..6d6d5b325 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -196,7 +196,7 @@ package body Switches is use Ada.Strings.Unbounded; Result : String_Vectors.Vector; begin - Result.Append (+"--dump-triger"); + Result.Append (+"--dump-trigger"); case Dump_Config.Trigger is when Manual => Result.Append (+"manual"); diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 0cb91236a..67817c1f8 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -119,6 +119,10 @@ package Switches is SPARK_Compat : Boolean := False; -- When True, tune the instrumenter for maximum SPARK compatibility + Files_Of_Interest : String_Sets.Set; + -- Lower abstraction for files of interest, when the --files switch is + -- used. + type Separated_Source_Coverage_Type is (None, Routines, Instances); Separated_Source_Coverage : Separated_Source_Coverage_Type := None; From 164e98771ac138816742b594e8682ee48072ff6d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 24 May 2023 12:17:04 +0200 Subject: [PATCH 0317/1483] Add entry to gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 1ddf255c3..f65e4e605 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ obj +obj-* lib *.pyc *.pkl From 846949964f15be521b5e696a67973ddf49006fd2 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 24 May 2023 12:17:35 +0200 Subject: [PATCH 0318/1483] instr-cov/gpr-complex: new test --- .../tests/instr-cov/gpr-complex/main_body.gpr | 5 + .../tests/instr-cov/gpr-complex/main_sep.gpr | 5 + .../instr-cov/gpr-complex/main_simple.gpr | 6 + .../tests/instr-cov/gpr-complex/main_spec.gpr | 5 + .../instr-cov/gpr-complex/src-lib/lib.gpr | 4 + .../instr-cov/gpr-complex/src-lib/pkg-bar.adb | 4 + .../instr-cov/gpr-complex/src-lib/pkg.adb | 9 ++ .../instr-cov/gpr-complex/src-lib/pkg.ads | 4 + .../gpr-complex/src-main_body/main.adb | 7 + .../gpr-complex/src-main_body/pkg.adb | 11 ++ .../gpr-complex/src-main_sep/main.adb | 7 + .../gpr-complex/src-main_sep/pkg-bar.adb | 6 + .../gpr-complex/src-main_simple/main.adb | 7 + .../gpr-complex/src-main_spec/main.adb | 8 ++ .../gpr-complex/src-main_spec/pkg.ads | 5 + .../tests/instr-cov/gpr-complex/test.opt | 1 + testsuite/tests/instr-cov/gpr-complex/test.py | 121 ++++++++++++++++++ 17 files changed, 215 insertions(+) create mode 100644 testsuite/tests/instr-cov/gpr-complex/main_body.gpr create mode 100644 testsuite/tests/instr-cov/gpr-complex/main_sep.gpr create mode 100644 testsuite/tests/instr-cov/gpr-complex/main_simple.gpr create mode 100644 testsuite/tests/instr-cov/gpr-complex/main_spec.gpr create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-lib/lib.gpr create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-lib/pkg-bar.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.ads create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_body/main.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_body/pkg.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_sep/main.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_simple/main.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_spec/main.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_spec/pkg.ads create mode 100644 testsuite/tests/instr-cov/gpr-complex/test.opt create mode 100644 testsuite/tests/instr-cov/gpr-complex/test.py diff --git a/testsuite/tests/instr-cov/gpr-complex/main_body.gpr b/testsuite/tests/instr-cov/gpr-complex/main_body.gpr new file mode 100644 index 000000000..109449cf5 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/main_body.gpr @@ -0,0 +1,5 @@ +project Main_Body extends "lib" is + for Source_Dirs use ("src-main_body"); + for Object_Dir use "obj-main_body"; + for Main use ("main.adb"); +end Main_Body; diff --git a/testsuite/tests/instr-cov/gpr-complex/main_sep.gpr b/testsuite/tests/instr-cov/gpr-complex/main_sep.gpr new file mode 100644 index 000000000..d4ba368f8 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/main_sep.gpr @@ -0,0 +1,5 @@ +project Main_Sep extends "lib" is + for Source_Dirs use ("src-main_sep"); + for Object_Dir use "obj-main_sep"; + for Main use ("main.adb"); +end Main_Sep; diff --git a/testsuite/tests/instr-cov/gpr-complex/main_simple.gpr b/testsuite/tests/instr-cov/gpr-complex/main_simple.gpr new file mode 100644 index 000000000..e2e925761 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/main_simple.gpr @@ -0,0 +1,6 @@ +project Main_Simple extends "lib" is + for Source_Dirs use ("src-main_simple"); + for Object_Dir use "obj-main_simple"; + for Library_Dir use "lib-main_simple"; + for Main use ("main.adb"); +end Main_Simple; diff --git a/testsuite/tests/instr-cov/gpr-complex/main_spec.gpr b/testsuite/tests/instr-cov/gpr-complex/main_spec.gpr new file mode 100644 index 000000000..ffa5ac70a --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/main_spec.gpr @@ -0,0 +1,5 @@ +project Main_Spec extends "lib" is + for Source_Dirs use ("src-main_spec"); + for Object_Dir use "obj-main_spec"; + for Main use ("main.adb"); +end Main_Spec; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-lib/lib.gpr b/testsuite/tests/instr-cov/gpr-complex/src-lib/lib.gpr new file mode 100644 index 000000000..f88001ac7 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-lib/lib.gpr @@ -0,0 +1,4 @@ +project Lib is + for Source_Dirs use ("."); + for Object_Dir use "obj"; +end Lib; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg-bar.adb b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg-bar.adb new file mode 100644 index 000000000..f5189aa0d --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg-bar.adb @@ -0,0 +1,4 @@ +separate (Pkg) procedure Bar is +begin + null; +end Bar; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.adb b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.adb new file mode 100644 index 000000000..fa79eb10a --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.adb @@ -0,0 +1,9 @@ +package body Pkg is + + procedure Foo is + begin + null; + end Foo; + + procedure Bar is separate; +end Pkg; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.ads b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.ads new file mode 100644 index 000000000..52d41a411 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + procedure Foo; + procedure Bar; +end Pkg; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_body/main.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_body/main.adb new file mode 100644 index 000000000..b8658aeb6 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_body/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; + Pkg.Bar; +end Main; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_body/pkg.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_body/pkg.adb new file mode 100644 index 000000000..3c7879b61 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_body/pkg.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Foo is + begin + Put_Line ("Hello from main-body"); + end Foo; + + procedure Bar is separate; +end Pkg; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_sep/main.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_sep/main.adb new file mode 100644 index 000000000..b8658aeb6 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_sep/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; + Pkg.Bar; +end Main; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb new file mode 100644 index 000000000..5fab031ea --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +separate (Pkg) procedure Bar is +begin + Put_Line ("Hello from main-sep"); +end Bar; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_simple/main.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_simple/main.adb new file mode 100644 index 000000000..b8658aeb6 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_simple/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; + Pkg.Bar; +end Main; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_spec/main.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_spec/main.adb new file mode 100644 index 000000000..2d8a449a0 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_spec/main.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; + Pkg.Bar; + Pkg.Baz; +end Main; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_spec/pkg.ads b/testsuite/tests/instr-cov/gpr-complex/src-main_spec/pkg.ads new file mode 100644 index 000000000..953e0ab4b --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_spec/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + procedure Foo; + procedure Bar; + procedure Baz is null; +end Pkg; diff --git a/testsuite/tests/instr-cov/gpr-complex/test.opt b/testsuite/tests/instr-cov/gpr-complex/test.opt new file mode 100644 index 000000000..57b6bf345 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/test.opt @@ -0,0 +1 @@ +!native DEAD hardcoded project files without board information diff --git a/testsuite/tests/instr-cov/gpr-complex/test.py b/testsuite/tests/instr-cov/gpr-complex/test.py new file mode 100644 index 000000000..235241be6 --- /dev/null +++ b/testsuite/tests/instr-cov/gpr-complex/test.py @@ -0,0 +1,121 @@ +""" +This test checks that gnatcov correctly instruments projects with a complex +structure, and with unit parts implemented in different projects of the project +tree, some of them being instrumented while some of them not (through project +extension). +""" + +import os + +from e3.fs import cp + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import no_ext, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprbuild, gprinstall + + +Wdir("tmp_") + +# Start by installing the library. Every main subproject depends on it. +install_dir = os.path.abspath("install") +cp(os.path.join("..", "src-lib"), ".", recursive=True) +lib_prj = os.path.join("src-lib", "lib.gpr") +xcov_instrument( + gprsw=GPRswitches(root_project=lib_prj), + covlevel="stmt", +) +gprbuild(lib_prj) +gprinstall( + lib_prj, + [ + f"--prefix={install_dir}", + "--src-subdirs=gnatcov-instr", + "--implicit-with=gnatcov_rts", + ], +) + +# Add the newly installed library to gprbuild's project lookup path +gpr_install_dir = os.path.join(install_dir, "share", "gpr") +old_path = os.environ.get("GPR_PROJECT_PATH", "") +if old_path: + new_path = "{}{}{}".format(gpr_install_dir, os.path.pathsep, old_path) +else: + new_path = gpr_install_dir +os.environ["GPR_PROJECT_PATH"] = new_path + + +def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): + cp(os.path.join("..", main_prj), ".", recursive=True) + cp(os.path.join("..", f"src-{no_ext(main_prj)}"), ".", recursive=True) + build_run_and_coverage( + gprsw=GPRswitches(root_project=os.path.join(main_prj)), + covlevel="stmt", + mains=["main"], + gpr_obj_dir=main_prj_obj_dir, + gpr_exe_dir=main_prj_obj_dir, + extra_coverage_args=[ + "--annotate=xcov", + "--externally-built-projects", + "--units=pkg", + ], + ) + check_xcov_reports("*.xcov", expected_xcov, main_prj_obj_dir) + + +# Try the simple case: the main project extends the library, but does not +# redefine anything. +thistest.log("== Simple case ==") +expected_xcov = {"pkg.adb.xcov": {"+": {5}}, "pkg-bar.adb.xcov": {"+": {3}}} +build_run_cov_and_check( + "main_simple.gpr", + main_prj_obj_dir="obj-main_simple", + expected_xcov=expected_xcov, +) + +# Now the main project defines an alternate body. TODO! as we reinstrument the +# whole unit if a part of it was redefined (including the parts that were not +# redefined), we end up instrumenting the instrumented version for sources +# belonging to the library. We should fix this (and adjust coverage +# expectations) if possible. +thistest.log("== Redefining Pkg body ==") +expected_xcov = {"pkg.adb.xcov": {"+": {7}}, "pkg-bar.adb.xcov": {"+": {4}}} +# Should be: {"pkg.adb.xcov": {"+": {7}}, "pkg-bar.adb.xcov": {"+": {5}}} +build_run_cov_and_check( + "main_body.gpr", + main_prj_obj_dir="obj-main_body", + expected_xcov=expected_xcov, +) + + +# Now the main project defines an alternate separate. +thistest.log("== Redefining Pkg.Bar separate ==") +expected_xcov = {"pkg.adb.xcov": {"+": {6}}, "pkg-bar.adb.xcov": {"+": {5}}} +# Should be: {"pkg.adb.xcov": {"+": {5}}, "pkg-bar.adb.xcov": {"+": {5}}} +build_run_cov_and_check( + "main_sep.gpr", + main_prj_obj_dir="obj-main_sep", + expected_xcov=expected_xcov, +) + +# Now the main project defines an alternate spec. +thistest.log("== Redefining Pkg spec ==") +expected_xcov = { + "pkg.adb.xcov": {"+": {6}}, + "pkg-bar.adb.xcov": {"+": {4}}, + "pkg.ads.xcov": {"+": {4}}, +} +# Should be: { +# "pkg.adb.xcov": {"+": {5}}, +# "pkg-bar.adb.xcov": {"+": {3}}, +# "pkg.ads.xcov": {"+": {4}}, +# } +build_run_cov_and_check( + "main_spec.gpr", + main_prj_obj_dir="obj-main_spec", + expected_xcov=expected_xcov, +) + +thistest.result() From 0d046d2f2ba7d7eedba42d016f37d4544f2b9ff3 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 24 May 2023 18:11:20 +0200 Subject: [PATCH 0319/1483] Avoid freezing the files table too early The file table should not be frozen when loading checkpoints (as otherwise latter checkpoints loading will fail in dev mode, when there are additional checks). We don't need a unique name to output this warning message so output the full name. --- tools/gnatcov/instrument-checkpoints.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index abdc8c7e2..b16eb7541 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -128,7 +128,7 @@ package body Instrument.Checkpoints is /= PP_Cmds.Reference (Cur) then Warn ("inconsistent information for instrumented file " - & Get_Unique_Name (SFI)); + & Get_Full_Name (SFI)); end if; end; end if; From b567aca989fa1a718f80987d9c45e5dfb4bb1839 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 24 May 2023 18:13:02 +0200 Subject: [PATCH 0320/1483] Remove occurrences of project name It is no longer necessary as we now use full names to identify units belonging to file-based languages. --- tools/gnatcov/instrument-ada_unit.adb | 4 --- tools/gnatcov/instrument-c.adb | 4 +-- tools/gnatcov/instrument-input_traces.adb | 14 ++-------- tools/gnatcov/instrument-projects.adb | 4 +-- tools/gnatcov/rts/gnatcov_rts-buffers.ads | 1 - tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 4 --- .../gnatcov/rts/gnatcov_rts_c-traces-output.c | 6 +---- tools/gnatcov/rts/gnatcov_rts_c-traces.h | 7 +---- tools/gnatcov/traces_source.ads | 26 +++++++------------ 9 files changed, 17 insertions(+), 53 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index c801e4aec..12eb7f7f2 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8173,7 +8173,6 @@ package body Instrument.Ada_Unit is File.Put_Line (" Unit_Name : constant String := """ & Unit_Name & """;"); - File.Put_Line (" Project_Name : constant String := """";"); File.New_Line; File.Put_Line (" Buffers : aliased constant" @@ -8188,9 +8187,6 @@ package body Instrument.Ada_Unit is File.Put_Line (" Unit_Name =>" & " (Unit_Name'Address, Unit_Name'Length),"); - File.Put_Line (" Project_Name =>" - & " (Project_Name'Address, Project_Name'Length),"); - File.Put_Line (" Bit_Maps_Fingerprint => " & Format_Fingerprint (SC_Obligations.Bit_Maps_Fingerprint (CU)) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 1da7cd9ed..6d8f28545 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3475,8 +3475,6 @@ package body Instrument.C is & " .unit_name = " & Format_Str_Constant (+CU_Name.Filename) & "," & ASCII.LF - & " .project_name = """"," - & ASCII.LF & " .bit_maps_fingerprint = " & Format_Fingerprint (SC_Obligations.Bit_Maps_Fingerprint (CU)) @@ -4064,7 +4062,7 @@ package body Instrument.C is File_Body.Put_Line ("}};"); else File_Body.Put_Line (","); - end if; + end if; end loop; -- Emit the extern declaration of the buffers array in the header file diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 22a1529db..47d544537 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -136,7 +136,6 @@ package body Instrument.Input_Traces is type Trace_Entry_Elements is record Unit_Name : System.Address; - Project_Name : System.Address; Statement_Buffer : System.Address; Decision_Buffer : System.Address; MCDC_Buffer : System.Address; @@ -493,7 +492,6 @@ package body Instrument.Input_Traces is if File_Header.Endianity /= Native_Endianity then Swap4 (Raw_Header.Unit_Name_Length'Address); - Swap4 (Raw_Header.Project_Name_Length'Address); Swap4 (Raw_Header.Statement_Bit_Count'Address); Swap4 (Raw_Header.Decision_Bit_Count'Address); Swap4 (Raw_Header.MCDC_Bit_Count'Address); @@ -525,7 +523,7 @@ package body Instrument.Input_Traces is Create_Error (Result, "invalid bit buffer encoding"); return False; - elsif Raw_Header.Padding /= (1 => ASCII.NUL) then + elsif Raw_Header.Padding /= (1 .. 5 => ASCII.NUL) then Create_Error (Result, "invalid entry header padding"); return False; end if; @@ -540,12 +538,9 @@ package body Instrument.Input_Traces is Unit_Name_Range : constant Buffer_Range := Range_For (File_Header.Alignment, 0, Natural (Entry_Header.Unit_Name_Length)); - Project_Name_Range : constant Buffer_Range := - Range_For (File_Header.Alignment, Offset_After (Unit_Name_Range), - Natural (Entry_Header.Project_Name_Length)); Statement_Buffer_Range : constant Buffer_Range := Range_For (File_Header.Alignment, - Offset_After (Project_Name_Range), + Offset_After (Unit_Name_Range), Buffer_Size (Entry_Header.Bit_Buffer_Encoding, Entry_Header.Statement_Bit_Count)); Decision_Buffer_Range : constant Buffer_Range := @@ -578,7 +573,6 @@ package body Instrument.Input_Traces is Base_Address := Buffer_Address (Stream); Trace_Entry := (Base_Address + Unit_Name_Range.Offset, - Base_Address + Project_Name_Range.Offset, Base_Address + Statement_Buffer_Range.Offset, Base_Address + Decision_Buffer_Range.Offset, Base_Address + MCDC_Buffer_Range.Offset); @@ -689,10 +683,6 @@ package body Instrument.Input_Traces is (1 .. Natural (Entry_Header.Unit_Name_Length)) with Import, Address => Trace_Entry.Unit_Name; - Project_Name : constant String - (1 .. Natural (Entry_Header.Project_Name_Length)) - with Import, Address => Trace_Entry.Project_Name; - function Convert is new Ada.Unchecked_Conversion (GNATcov_RTS.Buffers.Fingerprint_Type, SC_Obligations.Fingerprint_Type); diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 4227c83b4..9603e8d78 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -696,8 +696,8 @@ is -- Headers are not instrumented by themselves, so exit early as soon -- as they have been added to the sources of interest. - if (Language in C_Family_Language - and then Source_File.Unit_Part = Unit_Spec) + if Language in C_Family_Language + and then Source_File.Unit_Part = Unit_Spec then return; end if; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index 0a95db446..158e8cdec 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -78,7 +78,6 @@ package GNATcov_RTS.Buffers is Language : Any_Language_Kind; Unit_Part : Any_Unit_Part; Unit_Name : GNATcov_RTS_String; - Project_Name : GNATcov_RTS_String; Bit_Maps_Fingerprint : Fingerprint_Type; Statement, Decision, MCDC : System.Address; Statement_Last_Bit, Decision_Last_Bit, diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index 21cd45eac..e1ef95be9 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -93,10 +93,6 @@ extern "C" enum gnatcov_rts_unit_part unit_part; struct gnatcov_rts_string unit_name; - /* Project name for this compilation unit. This is only initialized for - file-based languages (otherwise, it is an empty string). */ - struct gnatcov_rts_string project_name; - /* Hash of buffer bit mappings for this unit, as gnatcov computes it (see SC_Obligations). Used as a fast way to check that gnatcov will be able to interpret buffer bits from a source traces using buffer bit mappings diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index b2a96c101..fe2d272ba 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -118,14 +118,13 @@ write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, { struct trace_entry_header header; header.unit_name_length = (uint32_t) buffers->unit_name.length; - header.project_name_length = (uint32_t) buffers->project_name.length; header.statement_bit_count = (uint32_t) buffers->statement_last_bit + 1; header.decision_bit_count = (uint32_t) buffers->decision_last_bit + 1; header.mcdc_bit_count = (uint32_t) buffers->mcdc_last_bit + 1; header.language_kind = (uint8_t) buffers->language_kind; header.unit_part = (uint8_t) buffers->unit_part; header.bit_buffer_encoding = GNATCOV_RTS_LSB_FIRST_BYTES; - memset (header.padding, 0, 1); + memset (header.padding, 0, 5); memcpy (&header.fingerprint, buffers->fingerprint, FINGERPRINT_SIZE); memcpy (&header.bit_maps_fingerprint, buffers->bit_maps_fingerprint, FINGERPRINT_SIZE); @@ -133,9 +132,6 @@ write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, write_bytes (output, (char *) &header, sizeof (header)); write_bytes (output, buffers->unit_name.str, buffers->unit_name.length); write_padding (write_bytes, output, buffers->unit_name.length); - write_bytes (output, buffers->project_name.str, - buffers->project_name.length); - write_padding (write_bytes, output, buffers->project_name.length); write_buffer (write_bytes, output, buffers->statement, buffers->statement_last_bit + 1); write_buffer (write_bytes, output, buffers->decision, diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces.h b/tools/gnatcov/rts/gnatcov_rts_c-traces.h index 6e3288395..33664a30d 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces.h @@ -115,11 +115,6 @@ extern "C" describes. */ uint32_t unit_name_length; - /* For file-based languages, length of the project name this file belongs - to. For unit-based languages, the unit name is unique so this piece of - information is not needed (and thus will be 0). */ - uint32_t project_name_length; - /* Number of bits in the statement, decision and MC/DC coverage buffers. */ uint32_t statement_bit_count; uint32_t decision_bit_count; @@ -148,7 +143,7 @@ extern "C" /* Padding used only to make the size of this trace entry header a multiple of 8 bytes. Must be zero. */ - uint8_t padding[1]; + uint8_t padding[5]; }; #ifdef __cplusplus diff --git a/tools/gnatcov/traces_source.ads b/tools/gnatcov/traces_source.ads index 230867cd4..ad7fb5fd8 100644 --- a/tools/gnatcov/traces_source.ads +++ b/tools/gnatcov/traces_source.ads @@ -225,11 +225,6 @@ package Traces_Source is -- Length of the unit name / filename for the unit this trace entry -- describes. - Project_Name_Length : Unsigned_32; - -- For file-based languages, length of the project name this file - -- belongs to. For unit-based languages, the unit name is unique so this - -- piece of information is not needed (thus will be 0). - Statement_Bit_Count : Any_Bit_Count; Decision_Bit_Count : Any_Bit_Count; MCDC_Bit_Count : Any_Bit_Count; @@ -256,23 +251,22 @@ package Traces_Source is -- be able to interpret buffer bits from a source traces using buffer -- bit mappings from SID files. - Padding : String (1 .. 1); + Padding : String (1 .. 5); -- Padding used only to make the size of this trace entry header a -- multiple of 8 bytes. Must be zero. end record; for Trace_Entry_Header use record Unit_Name_Length at 0 range 0 .. 31; - Project_Name_Length at 4 range 0 .. 31; - Statement_Bit_Count at 8 range 0 .. 31; - Decision_Bit_Count at 12 range 0 .. 31; - MCDC_Bit_Count at 16 range 0 .. 31; - Language_Kind at 20 range 0 .. 7; - Unit_Part at 21 range 0 .. 7; - Bit_Buffer_Encoding at 22 range 0 .. 7; - Fingerprint at 23 range 0 .. 20 * 8 - 1; - Bit_Maps_Fingerprint at 43 range 0 .. 20 * 8 - 1; - Padding at 63 range 0 .. 7; + Statement_Bit_Count at 4 range 0 .. 31; + Decision_Bit_Count at 8 range 0 .. 31; + MCDC_Bit_Count at 12 range 0 .. 31; + Language_Kind at 16 range 0 .. 7; + Unit_Part at 17 range 0 .. 7; + Bit_Buffer_Encoding at 18 range 0 .. 7; + Fingerprint at 19 range 0 .. 20 * 8 - 1; + Bit_Maps_Fingerprint at 39 range 0 .. 20 * 8 - 1; + Padding at 59 range 0 .. 5 * 8 - 1; end record; for Trace_Entry_Header'Size use 64 * 8; From e583c6a97bf5c159d4dfff1198b79d528434fc3f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 6 Jun 2023 11:30:49 +0200 Subject: [PATCH 0321/1483] Parallelize gnatcov instrumentation of itself This will adds some basic testing for the parallelized instrumentation, good as a first step. --- tools/gnatcov/Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index 4de3b3841..a05392273 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -223,15 +223,15 @@ ifdef INSTRUMENTED # instrumented as a main to compile gnatcov32, running gnatcov32 will not # dump execution traces. - gnatcov instrument -P gnatcov.gpr -XPART=gnatcov64 + gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov64 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 \ --src-subdirs=gnatcov-instr - gnatcov instrument -P gnatcov.gpr -XPART=gnatcov32 + gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov32 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov32 \ --src-subdirs=gnatcov-instr - gnatcov instrument -P gnatcov.gpr -XPART=driver + gnatcov instrument -j0 -P gnatcov.gpr -XPART=driver $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver \ --src-subdirs=gnatcov-instr else From f1c9464e2c341912024e9ff8af39477055ea1ebc Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 6 Jun 2023 14:58:34 +0200 Subject: [PATCH 0322/1483] Rename Compilation_Unit_Name to Compilation_Unit_Part In Ada, a compilation unit is the aggregation of a unit spec / body and its separates. The Compilation_Unit_Name type could be use to represent a unit part name, so the name was misleading. Rename it to Compilation_Unit_Part. --- tools/gnatcov/coverage-source.adb | 2 +- tools/gnatcov/coverage-source.ads | 2 +- tools/gnatcov/instrument-ada_unit.adb | 26 +++++++++++------------ tools/gnatcov/instrument-ada_unit.ads | 2 +- tools/gnatcov/instrument-c.adb | 14 ++++++------ tools/gnatcov/instrument-c.ads | 2 +- tools/gnatcov/instrument-checkpoints.adb | 2 +- tools/gnatcov/instrument-common.adb | 12 +++++------ tools/gnatcov/instrument-common.ads | 20 ++++++++--------- tools/gnatcov/instrument-input_traces.adb | 6 +++--- tools/gnatcov/instrument-input_traces.ads | 2 +- tools/gnatcov/instrument-projects.adb | 4 ++-- tools/gnatcov/instrument.adb | 18 ++++++++-------- tools/gnatcov/instrument.ads | 24 ++++++++++----------- 14 files changed, 68 insertions(+), 68 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 5e45fff78..fa911007a 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -1705,7 +1705,7 @@ package body Coverage.Source is procedure Compute_Source_Coverage (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 1f0968fa2..62ad3ff0d 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -52,7 +52,7 @@ package Coverage.Source is procedure Compute_Source_Coverage (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 12eb7f7f2..df4928c56 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1145,7 +1145,7 @@ package body Instrument.Ada_Unit is type Main_Instrumentation_Description (Synthetic : Boolean := False) is record - Main : Compilation_Unit_Name; + Main : Compilation_Unit_Part; -- Name of the compilation unit corresponding to the main body Controlled_Types_Available : Boolean; @@ -1293,7 +1293,7 @@ package body Instrument.Ada_Unit is -- addresses to its coverage buffers. procedure Emit_Buffer_Unit - (Buffer_Unit : Compilation_Unit_Name; + (Buffer_Unit : Compilation_Unit_Part; Prj : Prj_Desc; Unit : Project_Unit; Unit_Bits : Allocated_Bits_Vectors.Vector; @@ -1303,7 +1303,7 @@ package body Instrument.Ada_Unit is -- unit. procedure Emit_Pure_Buffer_Unit - (PB_Unit : Compilation_Unit_Name; + (PB_Unit : Compilation_Unit_Part; Prj : Prj_Desc; CU_Names : CU_Name_Vectors.Vector; Language_Version : Unbounded_Wide_Wide_String; @@ -1321,7 +1321,7 @@ package body Instrument.Ada_Unit is (Dump_Config : Any_Dump_Config; Instrumenter : Ada_Instrumenter_Type'Class; Prj : Prj_Desc; - Main : Compilation_Unit_Name; + Main : Compilation_Unit_Part; Helper_Unit : out Ada_Qualified_Name; Override_Dump_Trigger : Any_Dump_Trigger := Manual; Has_Controlled : Boolean := False); @@ -6733,7 +6733,7 @@ package body Instrument.Ada_Unit is Controlled_Types_Available : Boolean; Actual_Dump_Trigger : Auto_Dump_Trigger; - Main : Compilation_Unit_Name (Unit_Based_Language) := + Main : Compilation_Unit_Part (Unit_Based_Language) := (Language_Kind => Unit_Based_Language, Part => Unit_Body, others => <>); @@ -7717,7 +7717,7 @@ package body Instrument.Ada_Unit is Instrumenter : in out Ada_Instrumenter_Type; Prj : Prj_Desc) is - CU_Name : Compilation_Unit_Name (Language_Kind => Unit_Based_Language); + CU_Name : Compilation_Unit_Part (Language_Kind => Unit_Based_Language); Rewriter : Ada_Source_Rewriter; Dummy_Ctx : constant Context_Handle := Create_Context ("Instrumenting " & Filename); @@ -8058,7 +8058,7 @@ package body Instrument.Ada_Unit is ---------------------- procedure Emit_Buffer_Unit - (Buffer_Unit : Compilation_Unit_Name; + (Buffer_Unit : Compilation_Unit_Part; Prj : Prj_Desc; Unit : Project_Unit; Unit_Bits : Allocated_Bits_Vectors.Vector; @@ -8084,7 +8084,7 @@ package body Instrument.Ada_Unit is for I in 1 .. Last_Buffer_Index loop declare Unit_Bit : constant Allocated_Bits := Unit_Bits.Element (I); - CU_Name : constant Compilation_Unit_Name := CU_Names.Element (I); + CU_Name : constant Compilation_Unit_Part := CU_Names.Element (I); CU : constant CU_Id := CUs.Element (I); Fingerprint : Unbounded_String; @@ -8235,7 +8235,7 @@ package body Instrument.Ada_Unit is --------------------------- procedure Emit_Pure_Buffer_Unit - (PB_Unit : Compilation_Unit_Name; + (PB_Unit : Compilation_Unit_Part; Prj : Prj_Desc; CU_Names : CU_Name_Vectors.Vector; Language_Version : Unbounded_Wide_Wide_String; @@ -8285,7 +8285,7 @@ package body Instrument.Ada_Unit is for I in 1 .. Last_Buffer_Index loop declare Suffix : constant String := "_" & Img (I); - CU_Name : constant Compilation_Unit_Name := CU_Names.Element (I); + CU_Name : constant Compilation_Unit_Part := CU_Names.Element (I); begin File.Put_Line ("package Buffers" & Suffix & " is"); File.Put_Line (" Statement_Buffer : constant System.Address;"); @@ -8320,7 +8320,7 @@ package body Instrument.Ada_Unit is if not Degenerate_Subprogram_Generics.Is_Empty then declare - PB_Unit_Body : Compilation_Unit_Name := PB_Unit; + PB_Unit_Body : Compilation_Unit_Part := PB_Unit; begin PB_Unit_Body.Part := GNATCOLL.Projects.Unit_Body; @@ -8354,7 +8354,7 @@ package body Instrument.Ada_Unit is (Dump_Config : Any_Dump_Config; Instrumenter : Ada_Instrumenter_Type'Class; Prj : Prj_Desc; - Main : Compilation_Unit_Name; + Main : Compilation_Unit_Part; Helper_Unit : out Ada_Qualified_Name; Override_Dump_Trigger : Any_Dump_Trigger := Manual; Has_Controlled : Boolean := False) @@ -8629,7 +8629,7 @@ package body Instrument.Ada_Unit is Instr_Units : Unit_Sets.Set; Prj : Prj_Desc) is - Buffers_CU_Name : constant Compilation_Unit_Name := + Buffers_CU_Name : constant Compilation_Unit_Part := CU_Name_For_Unit (Buffers_List_Unit (+Prj.Prj_Name), GNATCOLL.Projects.Unit_Spec); File : Text_Files.File_Type; diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 9e7ee015e..8bc50a75b 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -283,7 +283,7 @@ private Entities : Instrumentation_Entities; -- Bank of nodes to use during instrumentation - Pure_Buffer_Unit : Compilation_Unit_Name; + Pure_Buffer_Unit : Compilation_Unit_Part; -- Name of the compilation unit that holds addresses for the coverage -- buffers of the unit being instrumented. diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 6d8f28545..b28157215 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -297,7 +297,7 @@ package body Instrument.C is procedure Emit_Dump_Helper_Unit (Dump_Config : Any_Dump_Config; - Main : Compilation_Unit_Name; + Main : Compilation_Unit_Part; Helper_Unit : out US.Unbounded_String; Instrumenter : C_Family_Instrumenter_Type'Class; Prj : Prj_Desc); @@ -2820,7 +2820,7 @@ package body Instrument.C is Files_Of_Interest : String_Sets.Set) is UIC : C_Unit_Inst_Context; - CU_Name : constant Compilation_Unit_Name := + CU_Name : constant Compilation_Unit_Part := CU_Name_For_File (+Unit_Name); Orig_Filename : constant String := Unit_Name; @@ -3308,11 +3308,11 @@ package body Instrument.C is procedure Emit_Buffer_Unit (UIC : C_Unit_Inst_Context'Class; - Unit : Project_Unit; + Unit : Compilation_Unit; Instrumenter : C_Family_Instrumenter_Type'Class; Prj : Prj_Desc) is - CU_Name : Compilation_Unit_Name renames UIC.Buffer_Unit; + CU_Name : Compilation_Unit_Part renames UIC.Buffer_Unit; File : Text_Files.File_Type; Buffers_Count : constant Natural := Natural (UIC.Allocated_Bits.Length); @@ -3414,7 +3414,7 @@ package body Instrument.C is UIC.Allocated_Bits.Constant_Reference (Buffers_Index); CU : constant CU_Id := Buffers_CUs (Buffers_Index); - CU_Name : Compilation_Unit_Name renames + CU_Name : Compilation_Unit_Part renames Buffers_CU_Names.Constant_Reference (Buffers_Index); -- Symbol name for each kind of static buffer @@ -3571,7 +3571,7 @@ package body Instrument.C is procedure Emit_Dump_Helper_Unit (Dump_Config : Any_Dump_Config; - Main : Compilation_Unit_Name; + Main : Compilation_Unit_Part; Helper_Unit : out US.Unbounded_String; Instrumenter : C_Family_Instrumenter_Type'Class; Prj : Prj_Desc) @@ -3698,7 +3698,7 @@ package body Instrument.C is -- Name of file to contain helpers implementing the buffers dump Rew : C_Source_Rewriter; - Main : constant Compilation_Unit_Name := + Main : constant Compilation_Unit_Part := (Language_Kind => File_Based_Language, Filename => +Ada.Directories.Full_Name (Filename)); diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index fa5d85ca7..f9d89c4c5 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -253,7 +253,7 @@ package Instrument.C is null; when True => SFI : Valid_Source_File_Index; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; end case; end record; -- Descriptor for a source file: Of_Interest determines if we should diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index b16eb7541..62c3e77ba 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -59,7 +59,7 @@ package body Instrument.Checkpoints is for Cur in CP_IU_Map.Iterate loop declare - CP_Unit_Name : constant Compilation_Unit_Name := Key (Cur); + CP_Unit_Name : constant Compilation_Unit_Part := Key (Cur); Existing_Cur : constant Cursor := Instrumented_Unit_CUs.Find (CP_Unit_Name); CU_Ignored : constant Boolean := diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index cb1994d0e..0988357df 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -30,7 +30,7 @@ with SCOs; package body Instrument.Common is function Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name; + (Instrumented_Unit : Compilation_Unit_Part; Buffer_Name : String) return String; -- Helper for Statement_Buffer_Symbol and Decision_Buffer_Symbol. Return -- the name of the symbol for the entity that contains the address of a @@ -45,7 +45,7 @@ package body Instrument.Common is ------------------- function Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name; + (Instrumented_Unit : Compilation_Unit_Part; Buffer_Name : String) return String is Slug : constant String := Instrumented_Unit_Slug (Instrumented_Unit); @@ -58,7 +58,7 @@ package body Instrument.Common is ----------------------------- function Statement_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name) return String is + (Instrumented_Unit : Compilation_Unit_Part) return String is begin return Buffer_Symbol (Instrumented_Unit, "stmt"); end Statement_Buffer_Symbol; @@ -68,7 +68,7 @@ package body Instrument.Common is ---------------------------- function Decision_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name) return String is + (Instrumented_Unit : Compilation_Unit_Part) return String is begin return Buffer_Symbol (Instrumented_Unit, "dc"); end Decision_Buffer_Symbol; @@ -78,7 +78,7 @@ package body Instrument.Common is ------------------------ function MCDC_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name) return String is + (Instrumented_Unit : Compilation_Unit_Part) return String is begin return Buffer_Symbol (Instrumented_Unit, "mcdc"); end MCDC_Buffer_Symbol; @@ -353,7 +353,7 @@ package body Instrument.Common is function To_Filename (Prj : Prj_Desc; Lang : Src_Supported_Language; - CU_Name : Compilation_Unit_Name) return String + CU_Name : Compilation_Unit_Part) return String is Filename : Unbounded_String; begin diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index af4f4051f..337307e90 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -110,28 +110,28 @@ package Instrument.Common is -- handler. function Dump_Procedure_Symbol - (Main : Compilation_Unit_Name) return String + (Main : Compilation_Unit_Part) return String is ("gnatcov_rts_" & Instrumented_Unit_Slug (Main) & "_" & To_Lower (To_String (Dump_Procedure_Name))); -- Return the name of the exported symbol for the Dump_Buffers function function Statement_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name) return String; + (Instrumented_Unit : Compilation_Unit_Part) return String; -- Given a unit to instrument, return the name of the symbol to use for the -- entity that contains address of the statement coverage buffer. function Decision_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name) return String; + (Instrumented_Unit : Compilation_Unit_Part) return String; -- Given a unit to instrument, return the name of the symbol to use for the -- entity that contains address of the decision coverage buffer. function MCDC_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name) return String; + (Instrumented_Unit : Compilation_Unit_Part) return String; -- Given a unit to instrument, return the name of the symbol to use for the -- entity that contains address of the decision coverage buffer. - function Unit_Buffers_Name (Unit : Project_Unit) return String; + function Unit_Buffers_Name (Unit : Compilation_Unit) return String; -- Name of the symbol that references the -- gnatcov_rts_coverage_buffers_group struct for this file. @@ -177,7 +177,7 @@ package Instrument.Common is type Instrumented_Unit_Info_Access is access all Instrumented_Unit_Info; package Instrumented_Unit_Maps is new Ada.Containers.Ordered_Maps - (Key_Type => Compilation_Unit_Name, + (Key_Type => Compilation_Unit_Part, Element_Type => Instrumented_Unit_Info_Access); ------------------------------------------------------ @@ -310,7 +310,7 @@ package Instrument.Common is (Index_Type => Positive, Element_Type => Annotation_Couple); type Unit_Inst_Context is tagged record - Instrumented_Unit : Compilation_Unit_Name; + Instrumented_Unit : Compilation_Unit_Part; -- Name of the compilation unit being instrumented SFI : Source_File_Index := No_Source_File; @@ -319,7 +319,7 @@ package Instrument.Common is Fullname : Unbounded_String; -- Fullname of the compilation unit being instrumented - Buffer_Unit : Compilation_Unit_Name; + Buffer_Unit : Compilation_Unit_Part; -- Name of the compilation unit that holds coverage buffers for the -- unit currently being instrumented (see Common.Buffer_Unit). @@ -369,7 +369,7 @@ package Instrument.Common is package CU_Name_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, - Element_Type => Compilation_Unit_Name); + Element_Type => Compilation_Unit_Part); package Ada_Qualified_Name_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, @@ -440,7 +440,7 @@ package Instrument.Common is function To_Filename (Prj : Prj_Desc; Lang : Src_Supported_Language; - CU_Name : Compilation_Unit_Name) return String; + CU_Name : Compilation_Unit_Part) return String; -- Convert a Compilation_Unit_Name to a file basename, using the body / -- spec suffix and dot replacement (for unit based languages) defined in -- Prj. diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 47d544537..18da8e0a4 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -715,7 +715,7 @@ package body Instrument.Input_Traces is function Last_Bit (Bit_Count : Any_Bit_Count) return Any_Bit_Id is (Any_Bit_Id (Bit_Count) - 1); - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; begin Reserve (Statement_Buffer, Entry_Header.Statement_Bit_Count); @@ -793,7 +793,7 @@ package body Instrument.Input_Traces is procedure On_Trace_Entry (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; @@ -833,7 +833,7 @@ package body Instrument.Input_Traces is procedure On_Trace_Entry (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/instrument-input_traces.ads b/tools/gnatcov/instrument-input_traces.ads index 7c8d7137c..43ed20190 100644 --- a/tools/gnatcov/instrument-input_traces.ads +++ b/tools/gnatcov/instrument-input_traces.ads @@ -34,7 +34,7 @@ package Instrument.Input_Traces is with procedure On_Trace_Entry (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 9603e8d78..c2af231ae 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -109,7 +109,7 @@ is -- thus must be deallocated when maps are deallocated. type Main_To_Instrument is record - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; -- Compilation unit of the main to instrument File : GNATCOLL.VFS.Virtual_File; @@ -488,7 +488,7 @@ is is File_Info : constant GNATCOLL.Projects.File_Info := Standard.Project.Project.Info (File); - CU_Name : constant Compilation_Unit_Name := + CU_Name : constant Compilation_Unit_Part := To_Compilation_Unit_Name (File_Info); Prj_Info : constant Project_Info_Access := Get_Or_Create_Project_Info (Context, Project); diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 3cd906b01..fc2309603 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -68,7 +68,7 @@ package body Instrument is -- "<" -- --------- - function "<" (Left, Right : Compilation_Unit_Name) return Boolean is + function "<" (Left, Right : Compilation_Unit_Part) return Boolean is begin if Left.Language_Kind = Right.Language_Kind then case Left.Language_Kind is @@ -110,7 +110,7 @@ package body Instrument is -- "=" -- --------- - function "=" (Left, Right : Compilation_Unit_Name) return Boolean + function "=" (Left, Right : Compilation_Unit_Part) return Boolean is use Ada_Identifier_Vectors; begin @@ -179,7 +179,7 @@ package body Instrument is ---------------------------- function Instrumented_Unit_Slug - (Instrumented_Unit : Compilation_Unit_Name) return String + (Instrumented_Unit : Compilation_Unit_Part) return String is begin case Instrumented_Unit.Language_Kind is @@ -253,7 +253,7 @@ package body Instrument is -- Image -- ----------- - function Image (CU_Name : Compilation_Unit_Name) return String is + function Image (CU_Name : Compilation_Unit_Part) return String is begin case CU_Name.Language_Kind is when Unit_Based_Language => @@ -324,7 +324,7 @@ package body Instrument is function CU_Name_For_Unit (Unit : Ada_Qualified_Name; - Part : Unit_Parts) return Compilation_Unit_Name + Part : Unit_Parts) return Compilation_Unit_Part is begin return (Unit_Based_Language, Unit, Part); @@ -335,7 +335,7 @@ package body Instrument is ----------------------------- function CU_Name_For_File - (Filename : US.Unbounded_String) return Compilation_Unit_Name + (Filename : US.Unbounded_String) return Compilation_Unit_Part is begin return (File_Based_Language, Filename); @@ -346,7 +346,7 @@ package body Instrument is ------------------------------ function To_Compilation_Unit_Name - (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Name + (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Part is begin case Language_Kind (To_Language (Source_File.Language)) is @@ -366,7 +366,7 @@ package body Instrument is function To_Filename (Project : Project_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Language : Any_Language) return String is begin case CU_Name.Language_Kind is @@ -386,7 +386,7 @@ package body Instrument is ---------------------------- function Find_Instrumented_Unit - (CU_Name : Compilation_Unit_Name) return CU_Id + (CU_Name : Compilation_Unit_Part) return CU_Id is use Instrumented_Unit_To_CU_Maps; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 3b89e5387..46c5eb4b3 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -66,7 +66,7 @@ package Instrument is with Pre => not Name.Is_Empty; -- Turn the given qualified name into Ada syntax - type Compilation_Unit_Name + type Compilation_Unit_Part (Language_Kind : Any_Language_Kind := Unit_Based_Language) is record @@ -83,20 +83,20 @@ package Instrument is end case; end record; - -- Unique identifier for an instrumented unit + -- Unique identifier for an instrumented unit part Part_Tags : constant array (Unit_Parts) of Character := (Unit_Spec => 'S', Unit_Body => 'B', Unit_Separate => 'U'); - function "=" (Left, Right : Compilation_Unit_Name) return Boolean; + function "=" (Left, Right : Compilation_Unit_Part) return Boolean; - function "<" (Left, Right : Compilation_Unit_Name) return Boolean; + function "<" (Left, Right : Compilation_Unit_Part) return Boolean; -- Compare the result of a call to Instrumented_Unit_Slug (which gives -- unique identifiers for each compilation unit name) for both operands. - function Image (CU_Name : Compilation_Unit_Name) return String; + function Image (CU_Name : Compilation_Unit_Part) return String; -- Return a string representation of CU_Name for use in diagnostics function Qualified_Name_Slug (Name : Ada_Qualified_Name) return String; @@ -105,7 +105,7 @@ package Instrument is -- not contain any '-'. function Instrumented_Unit_Slug - (Instrumented_Unit : Compilation_Unit_Name) return String; + (Instrumented_Unit : Compilation_Unit_Part) return String; -- Given a unit to instrument, return a unique identifier to describe it -- (the so called slug). -- @@ -133,29 +133,29 @@ package Instrument is function CU_Name_For_Unit (Unit : Ada_Qualified_Name; - Part : Unit_Parts) return Compilation_Unit_Name; + Part : Unit_Parts) return Compilation_Unit_Part; -- Return the compilation unit name for the Ada compilation unit -- corresponding to the unit name and the unit part parameters. function CU_Name_For_File - (Filename : US.Unbounded_String) return Compilation_Unit_Name; + (Filename : US.Unbounded_String) return Compilation_Unit_Part; -- Return the compilation unit name for the C translation unit -- corresponding to the filename parameter. function To_Compilation_Unit_Name - (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Name; + (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Part; -- Return the compilation unit name corresponding to the unit in -- Source_File. function To_Filename (Project : Project_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Language : Any_Language) return String; -- Return the name of the file to contain the given compilation unit, -- according to Project's naming scheme. package Instrumented_Unit_To_CU_Maps is new Ada.Containers.Ordered_Maps - (Key_Type => Compilation_Unit_Name, + (Key_Type => Compilation_Unit_Part, Element_Type => CU_Id); Instrumented_Unit_CUs : Instrumented_Unit_To_CU_Maps.Map; @@ -172,7 +172,7 @@ package Instrument is -- Save the preprocessing command for each unit that supports it function Find_Instrumented_Unit - (CU_Name : Compilation_Unit_Name) return CU_Id; + (CU_Name : Compilation_Unit_Part) return CU_Id; -- Return the CU_Id corresponding to the given instrumented unit, or -- No_CU_Id if not found. From 94f37286224684085c9a8ccb8b7eb70d2daa0ea0 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 6 Jun 2023 15:04:53 +0200 Subject: [PATCH 0323/1483] Rename Project_Unit to Compilation_Unit This type can be used to identify any unit (in a compilation context), and there is no dependency anymore to the notion of project, so rename it adequately. --- tools/gnatcov/coverage-source.adb | 18 +++++++------ tools/gnatcov/coverage-source.ads | 5 ++-- tools/gnatcov/files_table.adb | 8 +++--- tools/gnatcov/files_table.ads | 21 ++++++++------- tools/gnatcov/gnatcov_bits_specific.adb | 4 +-- tools/gnatcov/instrument-ada_unit.adb | 24 ++++++++--------- tools/gnatcov/instrument-ada_unit.ads | 2 +- tools/gnatcov/instrument-c.adb | 4 +-- tools/gnatcov/instrument-common.adb | 2 +- tools/gnatcov/instrument-projects.adb | 2 +- tools/gnatcov/project.adb | 36 +++++++++++++------------ tools/gnatcov/project.ads | 8 +++--- 12 files changed, 70 insertions(+), 64 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index fa911007a..4ea295a9c 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -220,7 +220,8 @@ package body Coverage.Source is -- 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 => Project_Unit, Element_Type => Ignored_Sources_Vector_Access); + (Key_Type => Compilation_Unit, + Element_Type => Ignored_Sources_Vector_Access); -- Map units of interest to the list of associated ignored source files Ignored_SF_Map : Unit_To_Ignored_Maps.Map; @@ -266,7 +267,7 @@ package body Coverage.Source is -- Add_Unit -- -------------- - procedure Add_Unit (Unit : Project_Unit) is + procedure Add_Unit (Unit : Compilation_Unit) is begin if not Unit_List_Invalidated then Unit_List.Include (Unit); @@ -305,7 +306,7 @@ package body Coverage.Source is begin if FI /= null and then not FI.Unit.Known then declare - Unit : constant Project_Unit := To_Project_Unit (File); + Unit : constant Compilation_Unit := To_Compilation_Unit (File); begin Consolidate_Source_File_Unit (SFI, Unit); end; @@ -373,7 +374,8 @@ package body Coverage.Source is -------------------------- procedure Iterate_On_Unit_List - (Process_Unit : not null access procedure (Name : Project_Unit); + (Process_Unit : not null access procedure + (Name : Compilation_Unit); Process_Source_File : not null access procedure (FI : File_Info)) is begin @@ -396,7 +398,7 @@ package body Coverage.Source 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 : Project_Unit); + procedure Print_Unit_Name (Unit : Compilation_Unit); -- Print the unit name ------------------------ @@ -416,7 +418,7 @@ package body Coverage.Source is -- Print_Unit_Name -- --------------------- - procedure Print_Unit_Name (Unit : Project_Unit) is + procedure Print_Unit_Name (Unit : Compilation_Unit) is begin Put_Line (File, +Unit.Unit_Name); end Print_Unit_Name; @@ -444,7 +446,7 @@ package body Coverage.Source is if not Unit_List_Invalidated then Ada.Containers.Count_Type'Output (CSS, Unit_List.Length); for N of Unit_List loop - Project_Unit'Output (CSS, N); + Compilation_Unit'Output (CSS, N); end loop; end if; end if; @@ -598,7 +600,7 @@ package body Coverage.Source is end if; US.Unbounded_String'Read (CLS, Dummy); else - Unit_List.Include (Project_Unit'Input (CLS)); + Unit_List.Include (Compilation_Unit'Input (CLS)); end if; end loop; end if; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 62ad3ff0d..38c2b903e 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -104,7 +104,7 @@ package Coverage.Source is -- message is used for logging purposes, so that users can find out why we -- cannot dump the list of units of interest. - procedure Add_Unit (Unit : Project_Unit); + procedure Add_Unit (Unit : Compilation_Unit); -- Add Unit to the list of units of interest. For convenience, do nothing -- if it is invalid. @@ -117,7 +117,8 @@ package Coverage.Source is -- unit names, linking them to the list of ignored source files. procedure Iterate_On_Unit_List - (Process_Unit : not null access procedure (Name : Project_Unit); + (Process_Unit : not null access procedure + (Name : Compilation_Unit); Process_Source_File : not null access procedure (FI : File_Info)) with Pre => Unit_List_Is_Valid; -- Call Process_Unit for each unit of interest, passing to it the name of diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 050504b88..4bd99d7a8 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -621,7 +621,7 @@ package body Files_Table is ---------------------------------- procedure Consolidate_Source_File_Unit - (Index : Valid_Source_File_Index; New_Unit : Project_Unit) + (Index : Valid_Source_File_Index; New_Unit : Compilation_Unit) is use Ada.Strings.Unbounded; FI : File_Info renames Files_Table.Element (Index).all; @@ -1890,7 +1890,7 @@ package body Files_Table is Any_Ignore_Status'Write (S, FI.Ignore_Status); Boolean'Write (S, FI.Unit.Known); if FI.Unit.Known then - Project_Unit'Output (S, FI.Unit.Name); + Compilation_Unit'Output (S, FI.Unit.Name); end if; end if; end; @@ -2042,7 +2042,7 @@ package body Files_Table is if Unit_Known then -- Starting with the version 13 of checkpoints, - -- owning units are represented as Project_Unit + -- owning units are represented as Compilation_Unit -- values (they were mere strings before). Consider -- the owning unit unknown if we do not have recent -- formats. @@ -2055,7 +2055,7 @@ package body Files_Table is end; else FE.Unit := (Known => True, - Name => Project_Unit'Input (S)); + Name => Compilation_Unit'Input (S)); end if; end if; end; diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 77855f1e8..9a9aafb29 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -305,17 +305,18 @@ package Files_Table is -- option --ignore-source-files. Consolidation rules are described in -- procedure Consolidate_Ignore_Status. - type Project_Unit (Language : Any_Language_Kind := Unit_Based_Language) - is record + type Compilation_Unit is record + Language : Any_Language_Kind; Unit_Name : Ada.Strings.Unbounded.Unbounded_String; end record; - -- To uniquely identify a unit in a project tree, we need its unit name. - -- It is the unit name for unit-based language, and the file fullname for + -- This record is used to uniquely identify a unit of any language + -- supported by gnatcov. The unique identifier, stored as Unit_Name is + -- the unit name for unit-based language, and the file fullname for -- file-based languages. use type Ada.Strings.Unbounded.Unbounded_String; - function Image (U : Project_Unit) return String is + function Image (U : Compilation_Unit) return String is (case U.Language is when Unit_Based_Language => To_Lower (Ada.Strings.Unbounded.To_String (U.Unit_Name)), @@ -323,18 +324,18 @@ package Files_Table is Fold_Filename_Casing (Ada.Strings.Unbounded.To_String (U.Unit_Name))); - function "<" (L, R : Project_Unit) return Boolean is + function "<" (L, R : Compilation_Unit) return Boolean is (Image (L) < Image (R)); - function "=" (L, R : Project_Unit) return Boolean is + function "=" (L, R : Compilation_Unit) return Boolean is (Image (L) = Image (R)); package Unit_Sets is new Ada.Containers.Ordered_Sets - (Element_Type => Project_Unit); + (Element_Type => Compilation_Unit); type Owning_Unit (Known : Boolean := False) is record case Known is - when True => Name : Project_Unit; + when True => Name : Compilation_Unit; when False => null; end case; end record; @@ -456,7 +457,7 @@ package Files_Table is (Index : Source_File_Index) return File_Info_Access; procedure Consolidate_Source_File_Unit - (Index : Valid_Source_File_Index; New_Unit : Project_Unit) + (Index : Valid_Source_File_Index; New_Unit : Compilation_Unit) with Pre => Get_File (Index).Kind = Source_File; -- Update the unit name info for the source file represented by Index. -- Does nothing if the new unit name is the empty string. diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index c53b72790..90fa1992e 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1763,7 +1763,7 @@ begin -- Build the list of units of interest from project files option declare - procedure Add_Unit (Unit : Project_Unit; Is_Stub : Boolean); + procedure Add_Unit (Unit : Compilation_Unit; Is_Stub : Boolean); -- Add Name to the list of names for units of interest. Do nothing -- if this is a stub for a unit-based language, since such stubs -- are implicitly part of another unit of interest. @@ -1772,7 +1772,7 @@ begin -- Add_Unit -- -------------- - procedure Add_Unit (Unit : Project_Unit; Is_Stub : Boolean) is + procedure Add_Unit (Unit : Compilation_Unit; Is_Stub : Boolean) is begin if not Is_Stub or else Unit.Language = File_Based_Language then Add_Unit (Unit); diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index df4928c56..e6e3e7193 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -923,7 +923,7 @@ package body Instrument.Ada_Unit is function Has_Matching_Pragma_For_Unit (Context : Analysis_Context; - Unit : Compilation_Unit; + Unit : LAL.Compilation_Unit; Filter : access function (Node : Pragma_Node) return Boolean) return Boolean; -- Return whether Filter return True on at least one configuration pragma @@ -945,7 +945,7 @@ package body Instrument.Ada_Unit is -- Return True if Prag_Node imposes a restrictions on use of finalization function Finalization_Restricted_In_Unit - (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean; + (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean; -- Return True if Finalization is not available in this runtime, or if -- some control pragma restricts the usage of finalization in either Unit -- or the whole project. @@ -956,7 +956,7 @@ package body Instrument.Ada_Unit is -- Ada.Task_Termination and/or Ada.Task_Identification. function Task_Termination_Restricted - (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean; + (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean; -- Return True if tasking is not available in this runtime, or if some -- configuration pragma prevents the use of tasks and/or -- Ada.Task_Termination and/or Ada.Task_Identification in either the whole @@ -1295,7 +1295,7 @@ package body Instrument.Ada_Unit is procedure Emit_Buffer_Unit (Buffer_Unit : Compilation_Unit_Part; Prj : Prj_Desc; - Unit : Project_Unit; + Unit : Files_Table.Compilation_Unit; Unit_Bits : Allocated_Bits_Vectors.Vector; CU_Names : CU_Name_Vectors.Vector; CUs : CU_Id_Vectors.Vector); @@ -4251,7 +4251,7 @@ package body Instrument.Ada_Unit is when Ada_Compilation_Unit => declare - CUN : constant Compilation_Unit := + CUN : constant LAL.Compilation_Unit := N.As_Compilation_Unit; CUN_Body : constant Ada_Node := CUN.F_Body; Is_Subunit : constant Boolean := @@ -7236,7 +7236,7 @@ package body Instrument.Ada_Unit is function Has_Matching_Pragma_For_Unit (Context : Analysis_Context; - Unit : Compilation_Unit; + Unit : LAL.Compilation_Unit; Filter : access function (Node : Pragma_Node) return Boolean) return Boolean is @@ -7329,7 +7329,7 @@ package body Instrument.Ada_Unit is ------------------------------------- function Finalization_Restricted_In_Unit - (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean + (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean is begin return not Has_Unit (Context, "Ada.Finalization", Unit_Specification) @@ -7387,7 +7387,7 @@ package body Instrument.Ada_Unit is --------------------------------- function Task_Termination_Restricted - (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean + (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean is begin return not Has_Unit (Context, "Ada.Task.Termination", Unit_Specification) @@ -8060,7 +8060,7 @@ package body Instrument.Ada_Unit is procedure Emit_Buffer_Unit (Buffer_Unit : Compilation_Unit_Part; Prj : Prj_Desc; - Unit : Project_Unit; + Unit : Files_Table.Compilation_Unit; Unit_Bits : Allocated_Bits_Vectors.Vector; CU_Names : CU_Name_Vectors.Vector; CUs : CU_Id_Vectors.Vector) @@ -8761,11 +8761,11 @@ package body Instrument.Ada_Unit is Prj : Prj_Desc; Files_Of_Interest : String_Sets.Set) is - Allocated_Bits : Allocated_Bits_Vectors.Vector; + Allocated_Bits : Allocated_Bits_Vectors.Vector; Last_Buffer_Index : Natural := 0; CU_Names : CU_Name_Vectors.Vector; - CUs : CU_Id_Vectors.Vector; - Unit : constant Project_Unit := + CUs : CU_Id_Vectors.Vector; + Unit : constant Files_Table.Compilation_Unit := (Language => Unit_Based_Language, Unit_Name => +Unit_Name); UIC : Ada_Unit_Inst_Context; diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 8bc50a75b..a27d22e80 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -270,7 +270,7 @@ private CU : CU_Id := No_CU_Id; -- SCO identifier of the compilation unit being instrumented - Root_Unit : Compilation_Unit; + Root_Unit : Libadalang.Analysis.Compilation_Unit; -- Node of compilation unit Source_Decisions : Source_Decision_Vectors.Vector; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index b28157215..5d68635c7 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -289,7 +289,7 @@ package body Instrument.C is procedure Emit_Buffer_Unit (UIC : C_Unit_Inst_Context'Class; - Unit : Project_Unit; + Unit : Compilation_Unit; Instrumenter : C_Family_Instrumenter_Type'Class; Prj : Prj_Desc); -- Emit the unit to contain coverage buffers for the given instrumented @@ -3252,7 +3252,7 @@ package body Instrument.C is Emit_Buffer_Unit (UIC, - Project_Unit' + Compilation_Unit' (Language => File_Based_Language, Unit_Name => UIC.Fullname), Self, diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 0988357df..5eca7b58e 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -87,7 +87,7 @@ package body Instrument.Common is -- Unit_Buffers_Name -- ----------------------- - function Unit_Buffers_Name (Unit : Project_Unit) return String is + function Unit_Buffers_Name (Unit : Compilation_Unit) return String is Slug : constant String := (case Unit.Language is when Unit_Based_Language => diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index c2af231ae..1a8193396 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -1193,7 +1193,7 @@ begin begin for LU_Info of Instrumented_Sources loop Instr_Units.Insert - (Project_Unit'(LU_Info.Language_Kind, LU_Info.Unit_Name)); + (Compilation_Unit'(LU_Info.Language_Kind, LU_Info.Unit_Name)); end loop; for Lang in Src_Supported_Language loop if Builtin_Support (Lang) diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index b1f69e211..92685ea7d 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -40,8 +40,8 @@ with Paths; use Paths; package body Project is - subtype Project_Unit is Files_Table.Project_Unit; - use type Project_Unit; + subtype Compilation_Unit is Files_Table.Compilation_Unit; + use type Compilation_Unit; Coverage_Package : aliased String := "coverage"; Coverage_Package_List : aliased String_List := @@ -156,7 +156,7 @@ package body Project is end record; package Unit_Maps is new Ada.Containers.Indefinite_Ordered_Maps - (Key_Type => Project_Unit, + (Key_Type => Compilation_Unit, Element_Type => Unit_Info); procedure Add_Unit @@ -166,7 +166,7 @@ package body Project is Info : File_Info; Language : Some_Language); -- Add a Unit_Info entry to Units. The key for this new entry (which is a - -- Project_Unit) is computed using the Original_Name, and the + -- Compilation_Unit) is computed using the Original_Name, and the -- Info.Project_Name if the unit is of a file-based language. procedure Warn_Missing_Info (What_Info : String; Unit : in out Unit_Info); @@ -232,15 +232,17 @@ package body Project is -- Note that this also returns source files for mains that are not units of -- interest. - --------------------- - -- To_Project_Unit -- - --------------------- + ------------------------- + -- To_Compilation_Unit -- + ------------------------- - function To_Project_Unit (Info : File_Info) return Files_Table.Project_Unit + function To_Compilation_Unit + (Info : File_Info) return Files_Table.Compilation_Unit is Language : constant Some_Language := To_Language (Info.Language); - U : Project_Unit (Language_Kind (Language)); + U : Compilation_Unit; begin + U.Language := Language_Kind (Language); case U.Language is when File_Based_Language => U.Unit_Name := +(+Info.File.Full_Name); @@ -248,7 +250,7 @@ package body Project is U.Unit_Name := +Info.Unit_Name; end case; return U; - end To_Project_Unit; + end To_Compilation_Unit; --------- -- "+" -- @@ -288,7 +290,7 @@ package body Project is Orig_Name : constant Unbounded_String := +Fold_Filename_Casing (Original_Name); - Unit_Name : constant Project_Unit := To_Project_Unit (Info); + Unit_Name : constant Compilation_Unit := To_Compilation_Unit (Info); Ignored_Inserted : Boolean; begin @@ -460,7 +462,7 @@ package body Project is --------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Files_Table.Project_Unit; + (Callback : access procedure (Name : Files_Table.Compilation_Unit; Is_Stub : Boolean)) is use Unit_Maps; @@ -488,7 +490,7 @@ package body Project is when Unit_Based_Language => FI.Unit_Name, when File_Based_Language => Full_Name); begin - return Unit_Map.Contains (Project_Unit'(LK, +Unit_Name)); + return Unit_Map.Contains (Compilation_Unit'(LK, +Unit_Name)); end Is_Unit_Of_Interest; ------------------------- @@ -519,7 +521,7 @@ package body Project is use Unit_Maps; Cur : constant Cursor := - Unit_Map.Find (To_Project_Unit (LI.Source.all)); + Unit_Map.Find (To_Compilation_Unit (LI.Source.all)); begin if Has_Element (Cur) then Callback.all (+LI.Library_File.Full_Name); @@ -581,7 +583,7 @@ package body Project is -- map or else - (Unit_Map.Contains (To_Project_Unit (Info)) + (Unit_Map.Contains (To_Compilation_Unit (Info)) and then (Info.Unit_Part /= Unit_Separate or else Include_Stubs)) then @@ -974,7 +976,7 @@ package body Project is for Cur in Inc_Units.Iterate loop declare use Unit_Maps; - K : constant Project_Unit := Key (Cur); + K : constant Compilation_Unit := Key (Cur); begin if not Exc_Units.Contains (K) then declare @@ -1040,7 +1042,7 @@ package body Project is procedure Add_To_Unit_Presents (C : Unit_Maps.Cursor) is - P_Unit : constant Project_Unit := Unit_Maps.Key (C); + P_Unit : constant Compilation_Unit := Unit_Maps.Key (C); Unit_Name : constant Unbounded_String := (case P_Unit.Language is when File_Based_Language => diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index f342244f4..35e9a1e22 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -114,16 +114,16 @@ package Project is -- path of its main executable (including its suffix, for instance ".exe"). -- Otherwise, return an empty string. - function To_Project_Unit (Info : File_Info) return Files_Table.Project_Unit; - -- Return the Project_Unit value that designates the same unit as - -- Unit_Name/Project/Language. + function To_Compilation_Unit + (Info : File_Info) return Files_Table.Compilation_Unit; + -- Return the Compilation_Unit for Info -------------------------------------- -- Accessors for project properties -- -------------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Files_Table.Project_Unit; + (Callback : access procedure (Name : Files_Table.Compilation_Unit; Is_Stub : Boolean)); -- Call Callback once for every unit of interest. Name is the unit name, -- and Is_Stub corresponds to the Unit_Info.Is_Stub field (see From 3b4c7de57e0e018137b4c6d3214710a18bc36946 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 6 Jun 2023 15:09:03 +0200 Subject: [PATCH 0324/1483] Cosmetic changes --- tools/gnatcov/instrument-ada_unit.adb | 5 +++-- tools/gnatcov/instrument-c.adb | 3 +-- tools/gnatcov/instrument.adb | 9 ++++----- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index e6e3e7193..f3e72d058 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6960,7 +6960,7 @@ package body Instrument.Ada_Unit is end case; end Visit; - -- Start of processing for Filenaem + -- Start of processing for Filename begin Visit (Unit_Name); @@ -8067,7 +8067,8 @@ package body Instrument.Ada_Unit is is Pkg_Name : constant String := To_Ada (Buffer_Unit.Unit); -- Package name for the buffer unit - File : Text_Files.File_Type; + + File : Text_Files.File_Type; Last_Buffer_Index : constant Natural := Natural (Unit_Bits.Length); begin Create_File (Prj, File, To_Filename (Prj, Ada_Language, Buffer_Unit)); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 5d68635c7..d780b43a6 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2908,8 +2908,7 @@ package body Instrument.C is -- Initialize the C instrumentation context UIC.Instrumented_Unit := CU_Name; - UIC.Buffer_Unit := - CU_Name_For_File (+Buffer_Filename); + UIC.Buffer_Unit := CU_Name_For_File (+Buffer_Filename); UIC.Files_Of_Interest := Files_Of_Interest; -- Import analysis options for the file to preprocess, then run the diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index fc2309603..c8de37499 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -215,11 +215,10 @@ package body Instrument is -- We use the basename slug, followed by a hash of the fullname, which -- makes us confident that homonym files will be correctly handled. - -- File names can contain characters that cannot appear in - -- identifiers. Furthermore, unlike for the identifier to - -- return, file names may be case sensitive. In order to - -- produce valid identifiers, encode everything that isn't a - -- lower case letter or a digit. + -- File names can contain characters that cannot appear in identifiers. + -- Furthermore, unlike for the identifier to return, file names may + -- be case sensitive. In order to produce valid identifiers, encode + -- everything that isn't a lower case letter or a digit. -- To avoid a leading underscore, add a prefix From e81de5bf92b275e9b7a21571485f4f2e11aed1b2 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 6 Jun 2023 15:14:47 +0200 Subject: [PATCH 0325/1483] Shorten filenames for generated instrumentation files As we now add the hash of the fullname to have a unique slug for compilation units identified by file fullnames (for file-based languages, such as C / C++), generated instrumentation files (such as coverage buffers) have longer names. This could be a problem on windows, as the paths can't exceed a certain length. To make the generated filenames shorter, we can both: * Use an hexadecimal image of the hash to have a shorter slug * Generate instrumentation files with a shorter prefix than the current one, which is "gnatcov_rts-buffers": we replace it with "gcvrt". --- tools/gnatcov/instrument-ada_unit.adb | 43 ++++++++++++++++++++------- tools/gnatcov/instrument-c.adb | 2 +- tools/gnatcov/instrument-common.adb | 7 ++--- tools/gnatcov/instrument-common.ads | 6 +--- tools/gnatcov/instrument.adb | 4 +-- tools/gnatcov/project.adb | 4 ++- tools/gnatcov/rts/gcvrt.ads | 23 ++++++++++++++ 7 files changed, 65 insertions(+), 24 deletions(-) create mode 100644 tools/gnatcov/rts/gcvrt.ads diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index f3e72d058..6cdf086ca 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1279,7 +1279,7 @@ package body Instrument.Ada_Unit is (Project_Name : String) return Ada_Qualified_Name; -- Returns the name of the unit containing the array of coverage buffers. -- It is named after the given project main name (e.g. if the - -- project p.gpr, its name is .). + -- project p.gpr, its name is .). function Buffer_Unit (Unit_Name : Ada_Qualified_Name) return Ada_Qualified_Name; @@ -4337,14 +4337,23 @@ package body Instrument.Ada_Unit is -- corresponding unit that contains coverage buffers. declare - Buffers_Unit : constant Node_Rewriting_Handle := To_Nodes - (UIC.Rewriting_Context, UIC.Pure_Buffer_Unit.Unit); - With_Clause : constant Node_Rewriting_Handle := + Buffers_Unit : constant Node_Rewriting_Handle := + To_Nodes + (UIC.Rewriting_Context, UIC.Pure_Buffer_Unit.Unit); + With_Buffers_Clause : constant Node_Rewriting_Handle := + Create_From_Template + (UIC.Rewriting_Context, "with {};", + (1 => To_Nodes + (UIC.Rewriting_Context, Sys_Buffers)), + With_Clause_Rule); + With_PB_Clause : constant Node_Rewriting_Handle := Create_From_Template (UIC.Rewriting_Context, "with {};", (1 => Buffers_Unit), With_Clause_Rule); begin - Append_Child (Handle (CUN.F_Prelude), With_Clause); + Append_Child (Handle (CUN.F_Prelude), + With_Buffers_Clause); + Append_Child (Handle (CUN.F_Prelude), With_PB_Clause); end; end; @@ -6574,7 +6583,8 @@ package body Instrument.Ada_Unit is declare Source_Name : constant String := To_String (N); begin - if not GNATCOLL.Utils.Starts_With (Source_Name, "gnatcov_rts") + if not (GNATCOLL.Utils.Starts_With (Source_Name, "gnatcov_rts") + or else GNATCOLL.Utils.Starts_With (Source_Name, "gcvrt")) then -- If we have not done it yet, clarify which file we were -- instrumenting when we noticed that the source file N was @@ -7605,6 +7615,13 @@ package body Instrument.Ada_Unit is Arguments => (1 .. 0 => No_Node_Rewriting_Handle), Rule => With_Clause_Rule); + With_Buffers_Clause : constant Node_Rewriting_Handle := + Create_From_Template + (RH, + Template => "with GNATcov_RTS.Buffers;", + Arguments => (1 .. 0 => No_Node_Rewriting_Handle), + Rule => With_Clause_Rule); + Runtime_Version_Check_Node : constant Node_Rewriting_Handle := Create_From_Template (RH, @@ -7615,6 +7632,7 @@ package body Instrument.Ada_Unit is begin Append_Child (Desc.Prelude, With_Clause); Append_Child (Desc.Prelude, With_RTS_Clause); + Append_Child (Desc.Prelude, With_Buffers_Clause); Append_Child (Desc.Prelude, Runtime_Version_Check_Node); end; @@ -8018,7 +8036,7 @@ package body Instrument.Ada_Unit is Qualified_Name_Slug (To_Qualified_Name (Project_Name)); begin return Ada_Identifier_Vectors."&" - (Sys_Buffers_Lists, Instrument.Ada_Identifier (+Project_Name_Slug)); + (Sys_Prefix, Instrument.Ada_Identifier (+Project_Name_Slug)); end Buffers_List_Unit; ----------------- @@ -8032,7 +8050,7 @@ package body Instrument.Ada_Unit is begin Append (Simple_Name, "B"); Append (Simple_Name, Ada_Identifier (+Qualified_Name_Slug (Unit_Name))); - return CU_Name : Ada_Qualified_Name := Sys_Buffers do + return CU_Name : Ada_Qualified_Name := Sys_Prefix do CU_Name.Append (Simple_Name); end return; end Buffer_Unit; @@ -8048,7 +8066,7 @@ package body Instrument.Ada_Unit is begin Append (Simple_Name, 'P'); Append (Simple_Name, Ada_Identifier (+Qualified_Name_Slug (Unit_Name))); - return CU_Name : Ada_Qualified_Name := Sys_Buffers do + return CU_Name : Ada_Qualified_Name := Sys_Prefix do CU_Name.Append (Simple_Name); end return; end Pure_Buffer_Unit; @@ -8074,6 +8092,8 @@ package body Instrument.Ada_Unit is Create_File (Prj, File, To_Filename (Prj, Ada_Language, Buffer_Unit)); Put_Warnings_And_Style_Checks_Pragmas (File); File.Put_Line ("with Interfaces.C; use Interfaces.C;"); + File.Put_Line ("with System;"); + File.Put_Line ("with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers;"); File.Put_Line ("with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists;"); @@ -8276,6 +8296,7 @@ package body Instrument.Ada_Unit is File.Put_Line ("with System;"); File.Put_Line ("with GNATcov_RTS;"); + File.Put_Line ("with GNATcov_RTS.Buffers;"); File.Put_Line (Runtime_Version_Check); File.New_Line; @@ -8389,7 +8410,7 @@ package body Instrument.Ada_Unit is begin -- Create the name of the helper unit - Helper_Unit := Sys_Buffers; + Helper_Unit := Sys_Prefix; Helper_Unit.Append (To_Unbounded_String ("D") & Instrumented_Unit_Slug (Main)); @@ -8643,6 +8664,8 @@ package body Instrument.Ada_Unit is Create_File (Prj, File, To_Filename (Prj, Ada_Language, Buffers_CU_Name)); Put_Warnings_And_Style_Checks_Pragmas (File); + File.Put_Line + ("with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists;"); for Instr_Unit of Instr_Units loop diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index d780b43a6..cf64a2857 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2830,7 +2830,7 @@ package body Instrument.C is Buffer_Filename : constant String := New_File (Prj, - To_Symbol_Name (Sys_Buffers) & "_b_" + To_Symbol_Name (Sys_Prefix) & "_b_" & Instrumented_Unit_Slug (CU_Name) & (+Prj.Body_Suffix (C_Family_Instrumenter_Type'Class (Self).Language))); diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 5eca7b58e..f31c7ed72 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -605,14 +605,11 @@ package body Instrument.Common is end Import_From_Args; begin - Sys_Prefix.Append (To_Unbounded_String ("GNATcov_RTS")); + Sys_Prefix.Append (To_Unbounded_String ("GCVRT")); - Sys_Buffers := Sys_Prefix; + Sys_Buffers.Append (To_Unbounded_String ("GNATcov_RTS")); Sys_Buffers.Append (To_Unbounded_String ("Buffers")); - Sys_Buffers_Lists := Sys_Buffers; - Sys_Buffers_Lists.Append (To_Unbounded_String ("Lists")); - Statement_Buffer_Name.Append (To_Unbounded_String ("Statement_Buffer")); Decision_Buffer_Name.Append (To_Unbounded_String ("Decision_Buffer")); MCDC_Buffer_Name.Append (To_Unbounded_String ("MCDC_Buffer")); diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 337307e90..dc050968d 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -76,11 +76,7 @@ package Instrument.Common is -- sources. Sys_Buffers : Ada_Qualified_Name; - -- Scope in Sys_Prefix for all packages to contain coverage buffers - - Sys_Buffers_Lists : Ada_Qualified_Name; - -- Scope in Sys_Prefix for all packages to contain generic procedures for - -- iterations on coverage buffers. + -- Runtime package containing coverage buffer type definitions Statement_Buffer_Name : Ada_Qualified_Name; -- Qualified name (relative to the unit buffer package) of the buffer to diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index c8de37499..27fb6e360 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -224,7 +224,7 @@ package body Instrument is Append (Result, "z"); - for C of Simple_Name (Fullname) loop + for C of Base_Name (Fullname) loop if C in 'a' .. 'z' | '0' .. '9' then Append (Result, C); else @@ -239,7 +239,7 @@ package body Instrument is declare Hash_Str : constant String := - Ada.Containers.Hash_Type'Image (Ada.Strings.Hash (Fullname)); + Hex_Image (Unsigned_32 (Ada.Strings.Hash (Fullname))); begin -- Do not forget to remove the leading whitespace... diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 92685ea7d..a025333d2 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -939,7 +939,9 @@ package body Project is -- library (in one of the gnatcov_rts*.gpr projects) or on -- our coverage buffer units (in user projects). - if Strings.Has_Prefix (Actual_Unit_Name, "gnatcov_rts.") then + if Strings.Has_Prefix (Actual_Unit_Name, "gnatcov_rts.") + or else Strings.Has_Prefix (Actual_Unit_Name, "gcvrt") + then return; end if; diff --git a/tools/gnatcov/rts/gcvrt.ads b/tools/gnatcov/rts/gcvrt.ads new file mode 100644 index 000000000..44de3e1a7 --- /dev/null +++ b/tools/gnatcov/rts/gcvrt.ads @@ -0,0 +1,23 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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. -- +------------------------------------------------------------------------------ + +-- Namespace for units generated for instrumentation purposes + +package GCVRT is + pragma Pure; +end GCVRT; From d565eb3b73f80ef131e8115fbeab16abb7e652e8 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 14 Jun 2023 07:42:47 +0200 Subject: [PATCH 0326/1483] Simplify handling of units of interest Do not put separate units in the Unit_Map, and remove the machinery dedicated to them. --- tools/gnatcov/coverage-source.adb | 20 +++--- tools/gnatcov/gnatcov_bits_specific.adb | 23 +------ tools/gnatcov/instrument-projects.adb | 18 ++---- tools/gnatcov/project.adb | 85 +++++++++---------------- tools/gnatcov/project.ads | 15 ++--- 5 files changed, 55 insertions(+), 106 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 4ea295a9c..1d1383175 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -20,6 +20,7 @@ with Ada.Characters.Latin_1; 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.Strings.Unbounded; with Ada.Tags; @@ -222,9 +223,9 @@ package body Coverage.Source is package Unit_To_Ignored_Maps is new Ada.Containers.Ordered_Maps (Key_Type => Compilation_Unit, Element_Type => Ignored_Sources_Vector_Access); - -- Map units of interest to the list of associated ignored source files Ignored_SF_Map : Unit_To_Ignored_Maps.Map; + -- Map units of interest to the list of associated ignored source files -------------------------- -- Basic_Block_Has_Code -- @@ -306,7 +307,8 @@ package body Coverage.Source is begin if FI /= null and then not FI.Unit.Known then declare - Unit : constant Compilation_Unit := To_Compilation_Unit (File); + Unit : constant Compilation_Unit := + To_Compilation_Unit (File); begin Consolidate_Source_File_Unit (SFI, Unit); end; @@ -346,13 +348,6 @@ package body Coverage.Source is if FI.Kind = Source_File and then FI.Ignore_Status in Always .. Sometimes then - -- If FI is a separate (Ada) or a header file (C/C++), it is not a - -- unit of interest itself: only the compilation unit is, so - -- Is_Unit_Of_Interest (FI.Full_Name.all) return False. Still, the - -- unit that owns this file is supposed to be known by now, so it - -- should be valid to access FI.Unit.Name (i.e. FI.Unit.Known - -- should be True). - if not Ignored_SF_Map.Contains (FI.Unit.Name) then Vec := new Ignored_Sources_Vector.Vector; Ignored_SF_Map.Insert (FI.Unit.Name, Vec); @@ -420,7 +415,12 @@ package body Coverage.Source is procedure Print_Unit_Name (Unit : Compilation_Unit) is begin - Put_Line (File, +Unit.Unit_Name); + 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 diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 90fa1992e..4953f453c 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -56,7 +56,6 @@ with Decision_Map; use Decision_Map; with Disassemble_Insn_Properties; with Execs_Dbase; use Execs_Dbase; with Files_Table; use Files_Table; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Inputs; use Inputs; with Instrument; with Instrument.Common; use Instrument.Common; @@ -1760,27 +1759,9 @@ begin Check_User_Provided_SCOs; - -- Build the list of units of interest from project files option + -- Build the list of units of interest from project files - declare - procedure Add_Unit (Unit : Compilation_Unit; Is_Stub : Boolean); - -- Add Name to the list of names for units of interest. Do nothing - -- if this is a stub for a unit-based language, since such stubs - -- are implicitly part of another unit of interest. - - -------------- - -- Add_Unit -- - -------------- - - procedure Add_Unit (Unit : Compilation_Unit; Is_Stub : Boolean) is - begin - if not Is_Stub or else Unit.Language = File_Based_Language then - Add_Unit (Unit); - end if; - end Add_Unit; - begin - Enumerate_Units_Of_Interest (Add_Unit'Access); - end; + Enumerate_Units_Of_Interest (Add_Unit'Access); -- Load routines from command line diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 1a8193396..98c1b9139 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -50,7 +50,7 @@ with Instrument.Source; with JSON; use JSON; with Outputs; with Paths; use Paths; -with Project; +with Project; use Project; with Strings; use Strings; with Support_Files; with Text_Files; use Text_Files; @@ -79,8 +79,6 @@ procedure Instrument.Projects Ignored_Source_Files : access GNAT.Regexp.Regexp; Mains : String_Vectors.Vector) is - Prj_Tree : constant Project_Tree_Access := Project.Project; - type Project_Info is record Project : Project_Type; -- Project that this record describes @@ -656,15 +654,11 @@ is use Unit_Maps; Unit_Name : constant String := (case Lang_Kind is - when Unit_Based_Language => - (if Source_File.Unit_Part = Unit_Separate - then Prj_Tree.Info - (Prj_Tree.Other_File (Source_File.File)).Unit_Name - else Source_File.Unit_Name), + when Unit_Based_Language => Owning_Unit_Name (Source_File), when File_Based_Language => GNATCOLL.VFS."+" (Source_File.File.Full_Name)); - Prj : constant Project_Info_Access := + Prj_Info : constant Project_Info_Access := Get_Or_Create_Project_Info (IC, Source_File.Project); LU_Info : constant Library_Unit_Info := @@ -672,7 +666,7 @@ is Instr_Project => Project, Language_Kind => Lang_Kind, Language => Language, - All_Externally_Built => Prj.Externally_Built); + All_Externally_Built => Prj_Info.Externally_Built); begin -- Check if this is an ignored source file @@ -709,7 +703,7 @@ is Cur_Ref : constant Unit_Maps.Reference_Type := Instrumented_Sources.Reference (Unit_Name); begin - if not Prj.Externally_Built then + if not Prj_Info.Externally_Built then Cur_Ref.Instr_Project := Project; Cur_Ref.All_Externally_Built := False; end if; @@ -751,7 +745,7 @@ is Import_From_Args (Options, Args); end; Add_Options (Compiler_Opts, Options, Pass_Builtins => False); - Prj.Desc.Compiler_Options_Unit.Insert + Prj_Info.Desc.Compiler_Options_Unit.Insert (LU_Info.Unit_Name, Compiler_Opts); end if; end; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index a025333d2..dda567487 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -137,14 +137,6 @@ package body Project is -- Whether we found at least one source file in the projects of interest -- that matches this unit. - Is_Stub : Boolean; - -- Whether this record describes a source file that is not a bona fide - -- unit of interest: a subunit (Ada) or a header file (C/C++). - -- - -- Such source files are not units of their own (in particular they - -- don't have their own LI file), but we still need them to appear in - -- unit lists, for reporting purposes. - Language : Some_Language; -- Language for this unit @@ -174,7 +166,9 @@ package body Project is -- Unit. Unit_Map : Unit_Maps.Map; - -- Map lower-case unit names to Unit_Info records for all units of interest + -- Map lower-case unit names to Unit_Info records for all units of + -- interest. This map contains header files (C/C++) but does not contain + -- separate (Ada) units. procedure Initialize (Target, Runtime, CGPR_File : GNAT.Strings.String_Access) @@ -232,6 +226,19 @@ package body Project is -- Note that this also returns source files for mains that are not units of -- interest. + ---------------------- + -- Owning_Unit_Name -- + ---------------------- + + function Owning_Unit_Name (Info : File_Info) return String is + begin + if Info.Unit_Part = Unit_Separate then + return Prj_Tree.Info (Prj_Tree.Other_File (Info.File)).Unit_Name; + else + return Info.Unit_Name; + end if; + end Owning_Unit_Name; + ------------------------- -- To_Compilation_Unit -- ------------------------- @@ -247,7 +254,7 @@ package body Project is when File_Based_Language => U.Unit_Name := +(+Info.File.Full_Name); when Unit_Based_Language => - U.Unit_Name := +Info.Unit_Name; + U.Unit_Name := +Owning_Unit_Name (Info); end case; return U; end To_Compilation_Unit; @@ -282,29 +289,27 @@ package body Project is Info : File_Info; Language : Some_Language) is - Unit_Part : constant Unit_Parts := Info.Unit_Part; - Is_Stub : constant Boolean := - (case Language is - when C_Family_Language => Unit_Part = Unit_Spec, - when Ada_Language => Unit_Part = Unit_Separate); - Orig_Name : constant Unbounded_String := +Fold_Filename_Casing (Original_Name); Unit_Name : constant Compilation_Unit := To_Compilation_Unit (Info); Ignored_Inserted : Boolean; + Is_Header : Boolean := False; begin - -- Disable warnings for stub units as they do not have a corresponding + -- Disable warnings for header files as they do not have a corresponding -- library file. + if Language in C_Family_Language and then Info.Unit_Part = Unit_Spec then + Is_Header := True; + end if; + Units.Insert (Key => Unit_Name, New_Item => (Original_Name => Orig_Name, Present_In_Projects => False, - Is_Stub => Is_Stub, Language => Language, - LI_Seen => Is_Stub, - Warned_About_Missing_Info => Is_Stub), + LI_Seen => Is_Header, + Warned_About_Missing_Info => Is_Header), Position => Cur, Inserted => Ignored_Inserted); end Add_Unit; @@ -462,37 +467,15 @@ package body Project is --------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Files_Table.Compilation_Unit; - Is_Stub : Boolean)) + (Callback : access procedure (Name : Files_Table.Compilation_Unit)) is use Unit_Maps; begin for Cur in Unit_Map.Iterate loop - declare - Info : Unit_Info renames Reference (Unit_Map, Cur); - begin - Callback (Key (Cur), Info.Is_Stub); - end; + Callback (Key (Cur)); end loop; end Enumerate_Units_Of_Interest; - ------------------------- - -- Is_Unit_Of_Interest -- - ------------------------- - - function Is_Unit_Of_Interest (Full_Name : String) return Boolean is - FI : constant File_Info := - Prj_Tree.Info (Create (+Full_Name)); - LK : constant Any_Language_Kind := - Language_Kind (To_Language (FI.Language)); - Unit_Name : constant String := - (case LK is - when Unit_Based_Language => FI.Unit_Name, - when File_Based_Language => Full_Name); - begin - return Unit_Map.Contains (Compilation_Unit'(LK, +Unit_Name)); - end Is_Unit_Of_Interest; - ------------------------- -- Enumerate_SCO_Files -- ------------------------- @@ -931,8 +914,7 @@ package body Project is Cur : Unit_Maps.Cursor; Actual_Unit_Name : constant String := (if Info.Unit_Part = Unit_Separate - then Prj_Tree.Info - (Prj_Tree.Other_File (Info.File)).Unit_Name + then Owning_Unit_Name (Info) else Unit_Name); begin -- Never try to perform coverage on our coverage runtime @@ -1162,7 +1144,6 @@ package body Project is Units : out Unit_Maps.Map; Defined : out Boolean) is - Unit_Patterns : String_Vectors.Vector; Attr_For_Pattern : String_Maps.Map; -- Patterns identifying unit names and project attribute from which we @@ -1200,8 +1181,7 @@ package body Project is Actual_Unit_Name : Vector := To_Vector (+(if Info.Unit_Part = Unit_Separate - then Prj_Tree.Info - (Prj_Tree.Other_File (Info.File)).Unit_Name + then Owning_Unit_Name (Info) else Unit_Name), 1); begin @@ -1222,11 +1202,6 @@ package body Project is Unit_Name, Info, Lang); - Units.Reference (Cur).Is_Stub := - (Info.Unit_Part = Unit_Separate - or else - (Lang in C_Family_Language - and then Info.Unit_Part = Unit_Spec)); end; end if; end Process_Source_File; @@ -1644,7 +1619,7 @@ package body Project is Default => (case Lang is when Ada_Language => ".adb", when C_Language => ".c", - when CPP_Language => ".cpp")); + when CPP_Language => ".cc")); when Unit_Spec => return Project.Attribute_Value diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 35e9a1e22..981ab4c6a 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -114,6 +114,11 @@ package Project is -- path of its main executable (including its suffix, for instance ".exe"). -- Otherwise, return an empty string. + function Owning_Unit_Name (Info : File_Info) return String + with Pre => Is_Project_Loaded; + -- Return the owning unit name meaning the unit name if this is a body / + -- specification, and the top parent unit name if this is a separate. + function To_Compilation_Unit (Info : File_Info) return Files_Table.Compilation_Unit; -- Return the Compilation_Unit for Info @@ -123,14 +128,8 @@ package Project is -------------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Files_Table.Compilation_Unit; - Is_Stub : Boolean)); - -- Call Callback once for every unit of interest. Name is the unit name, - -- and Is_Stub corresponds to the Unit_Info.Is_Stub field (see - -- project.adb). - - function Is_Unit_Of_Interest (Full_Name : String) return Boolean; - -- Return whether the given file is a unit of interest + (Callback : access procedure (Name : Files_Table.Compilation_Unit)); + -- Call Callback once for every unit of interest. Name is the unit name procedure Enumerate_SCOs_Files (Callback : access procedure (Lib_Name : String); From ea055c4ef5b4d4eeb3d286ed806eb977a44f4ead Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 14 Jun 2023 00:19:15 +0200 Subject: [PATCH 0327/1483] U204-026-arch-mix: Update baseline --- .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 0 -> 644 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 0 -> 2020 bytes ...uffers-bb_main_1.ads => gcvrt-bmain_1.ads} | 23 +++--- ...uffers-bb_main_2.ads => gcvrt-bmain_2.ads} | 23 +++--- .../gen/arm-elf-linux/gcvrt-bpkg.ads | 74 ++++++++++++++++++ ...fers-db_main_1.adb => gcvrt-db_main_1.adb} | 8 +- ...fers-db_main_1.ads => gcvrt-db_main_1.ads} | 6 +- ...fers-db_main_2.adb => gcvrt-db_main_2.adb} | 8 +- ...fers-db_main_2.ads => gcvrt-db_main_2.ads} | 6 +- .../gen/arm-elf-linux/gcvrt-foo.ads | 25 ++++++ .../gcvrt-pmain_1.ads} | 42 +++++----- .../gcvrt-pmain_2.ads} | 42 +++++----- .../gen/arm-elf-linux/gcvrt-ppkg.ads | 35 +++++++++ .../gnatcov_rts-buffers-bb_pkg.ads | 41 ---------- .../gnatcov_rts-buffers-bs_pkg.ads | 41 ---------- .../gnatcov_rts-buffers-lists-foo.ads | 25 ------ .../gnatcov_rts-buffers-pb_pkg.ads | 19 ----- .../gnatcov_rts-buffers-ps_pkg.ads | 19 ----- .../gen/arm-elf-linux/main_1.adb | 7 +- .../gen/arm-elf-linux/main_1.sid | Bin 387 -> 387 bytes .../gen/arm-elf-linux/main_2.adb | 7 +- .../gen/arm-elf-linux/main_2.sid | Bin 387 -> 387 bytes .../gen/arm-elf-linux/pkg.adb | 10 +-- .../gen/arm-elf-linux/pkg.ads | 2 +- .../gen/arm-elf-linux/pkg.sid | Bin 1046 -> 1046 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1878 -> 1906 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1888 -> 1916 bytes .../U204-026-arch-mix/gen/main_1.srctrace | Bin 416 -> 416 bytes .../U204-026-arch-mix/gen/main_2.srctrace | Bin 388 -> 388 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 1942 -> 1943 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 1851 -> 1879 bytes ...uffers-bb_main_1.ads => gcvrt-bmain_1.ads} | 23 +++--- ...uffers-bb_main_2.ads => gcvrt-bmain_2.ads} | 23 +++--- .../gen/x86_64-windows/gcvrt-bpkg.ads | 74 ++++++++++++++++++ ...fers-db_main_1.adb => gcvrt-db_main_1.adb} | 13 ++- .../gen/x86_64-windows/gcvrt-db_main_1.ads | 13 +++ ...fers-db_main_2.adb => gcvrt-db_main_2.adb} | 13 ++- .../gen/x86_64-windows/gcvrt-db_main_2.ads | 13 +++ .../gen/x86_64-windows/gcvrt-foo.ads | 25 ++++++ .../gcvrt-pmain_1.ads} | 42 +++++----- .../gcvrt-pmain_2.ads} | 42 +++++----- .../gen/x86_64-windows/gcvrt-ppkg.ads | 35 +++++++++ .../gnatcov_rts-buffers-bb_pkg.ads | 41 ---------- .../gnatcov_rts-buffers-bs_pkg.ads | 41 ---------- .../gnatcov_rts-buffers-db_main_1.ads | 6 -- .../gnatcov_rts-buffers-db_main_2.ads | 6 -- .../gnatcov_rts-buffers-lists-foo.ads | 25 ------ .../gnatcov_rts-buffers-pb_pkg.ads | 19 ----- .../gnatcov_rts-buffers-ps_pkg.ads | 19 ----- .../gen/x86_64-windows/main_1.adb | 13 +-- .../gen/x86_64-windows/main_1.sid | Bin 389 -> 389 bytes .../gen/x86_64-windows/main_2.adb | 13 +-- .../gen/x86_64-windows/main_2.sid | Bin 389 -> 389 bytes .../gen/x86_64-windows/pkg.adb | 10 +-- .../gen/x86_64-windows/pkg.ads | 2 +- .../gen/x86_64-windows/pkg.sid | Bin 1050 -> 1050 bytes .../tests/U204-026-arch-mix/main_2-out.txt | 11 +++ 57 files changed, 517 insertions(+), 468 deletions(-) create mode 100644 testsuite/tests/U204-026-arch-mix/bin-main_1.trace create mode 100644 testsuite/tests/U204-026-arch-mix/bin-main_2.trace rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gnatcov_rts-buffers-bb_main_1.ads => gcvrt-bmain_1.ads} (79%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gnatcov_rts-buffers-bb_main_2.ads => gcvrt-bmain_2.ads} (79%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bpkg.ads rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gnatcov_rts-buffers-db_main_1.adb => gcvrt-db_main_1.adb} (64%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gnatcov_rts-buffers-db_main_1.ads => gcvrt-db_main_1.ads} (60%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gnatcov_rts-buffers-db_main_2.adb => gcvrt-db_main_2.adb} (64%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gnatcov_rts-buffers-db_main_2.ads => gcvrt-db_main_2.ads} (60%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads rename testsuite/tests/U204-026-arch-mix/gen/{x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads => arm-elf-linux/gcvrt-pmain_1.ads} (66%) rename testsuite/tests/U204-026-arch-mix/gen/{x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads => arm-elf-linux/gcvrt-pmain_2.ads} (66%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gnatcov_rts-buffers-bb_main_1.ads => gcvrt-bmain_1.ads} (77%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gnatcov_rts-buffers-bb_main_2.ads => gcvrt-bmain_2.ads} (77%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bpkg.ads rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gnatcov_rts-buffers-db_main_1.adb => gcvrt-db_main_1.adb} (55%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gnatcov_rts-buffers-db_main_2.adb => gcvrt-db_main_2.adb} (55%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads rename testsuite/tests/U204-026-arch-mix/gen/{arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads => x86_64-windows/gcvrt-pmain_1.ads} (63%) rename testsuite/tests/U204-026-arch-mix/gen/{arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads => x86_64-windows/gcvrt-pmain_2.ads} (63%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/main_2-out.txt diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace new file mode 100644 index 0000000000000000000000000000000000000000..1b7f06c4baf411743211d5529cc59e75e7336f5e GIT binary patch literal 644 zcmYk&y-LGS6u|M5TH8ylVq=vKQi7HuLa|Ac7CT9)P6{ejocvZ){6ZIT6h|j<=;Yu7 z_y|6MgM*{H-~)(*ga4CcuyFg!IrrXkk~6+EyRcH}Tx{*^U0R8x$b<<0VpyN)RR3__ zv{*c6SZCWuQzu)8ryH(FiddK92EONuqo$W%SgTLZ*1Seg z_5GR~5JkW7|NXTy{ofK|l9H2ZTFjW(vW$7$M?*eq#3b;Yb0g%xFiRY1%XgU1NufuK z&Hg0ny+~U;Vy%CGUG`~f=B=ExsjGG7d&M~9k5TL2;5GiD-s{Bu8Gu3VC*)C9$!b(z6aiJ9zZMePdN?S^T7zqNBl0Z^N2SGsiY1qUBqGDoV zq5^@KsF*-jEMWpMfj~@DA`v7Y5C{YU!M**S?;LVY(&RpS-|y#q=iIx}y<2x5)b79D zc>H8@=~Q6M2V*kEnB>WPUs*nX>0H+=CC_J*->XN@uD;lK`to6H%rc&^*@&V}D_Ti- zHTlI++^9vZTD=j*^=`f1U289LrSV}azSdgnH0#X-Sf&5#r_Q9lu8g^`c-%QHe;LDJ zD4aJJ7Y|K1fP0oD{^n)z7ff#PFn|Mi29=l=s|>1S|7^GiP?I3(W$)_g~> z)<5?2PjH*~zt%7N2})8gp#BeZorlw*n2-lnJL zA^Q*D9{zP$=hwC@ey0ofy?g_>!g)uq)_1zZkI{4bzQASraq+VM(GBT8kALLFyMD#* z@=Lu5{;J+bSnuaYtBc>UAchiq+vI_KHfwjMR`f*N{-lwmy#+x&u zS2^!0yiUG0`TFn_*7yL{dCg$G|0i&k{9mjt`-|vDzc07pGW90(qx*Y~uHWx1Sob%> zul False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1_1"); Unit_Name : constant String := "main_1"; - Project_Name : constant String := ""; Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := (Fingerprint => (125, 27, 0, 113, 188, 140, 235, 155, 190, 125, 180, 238, 139, 95, 108, 198, 229, 72, 222, 11), Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, @@ -33,9 +34,11 @@ package GNATcov_RTS.Buffers.BB_main_1 is Statement_Last_Bit => 0, Decision_Last_Bit => -1, MCDC_Last_Bit => -1); +end Buffers_1; - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_1_buffers"); + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_1_buffers"); -end GNATcov_RTS.Buffers.BB_main_1; +end GCVRT.Bmain_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_2.ads similarity index 79% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_2.ads index 4f546cde7..db6822381 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_2.ads @@ -1,31 +1,32 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Interfaces.C; use Interfaces.C; +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GNATcov_RTS.Buffers.BB_main_2 is +package GCVRT.Bmain_2 is pragma Preelaborate; +package Buffers_1 is Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2_1"); Unit_Name : constant String := "main_2"; - Project_Name : constant String := ""; Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := (Fingerprint => (242, 237, 33, 15, 121, 175, 106, 160, 145, 225, 226, 10, 175, 16, 207, 223, 26, 27, 27, 148), Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, @@ -33,9 +34,11 @@ package GNATcov_RTS.Buffers.BB_main_2 is Statement_Last_Bit => 0, Decision_Last_Bit => -1, MCDC_Last_Bit => -1); +end Buffers_1; - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_2_buffers"); + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_2_buffers"); -end GNATcov_RTS.Buffers.BB_main_2; +end GCVRT.Bmain_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bpkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bpkg.ads new file mode 100644 index 000000000..16884c68b --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bpkg.ads @@ -0,0 +1,74 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GCVRT.Bpkg is + + pragma Preelaborate; + +package Buffers_1 is + Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg_1"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg_1"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg_1"); + + Unit_Name : constant String := "pkg"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), + Language => Unit_Based_Language, + Unit_Part => Unit_Spec, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => -1, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); +end Buffers_1; + +package Buffers_2 is + Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg_2"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg_2"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg_2"); + + Unit_Name : constant String := "pkg"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 2, + Decision_Last_Bit => 1, + MCDC_Last_Bit => 2); +end Buffers_2; + + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access, +2 => Buffers_2.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 2, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_pkg_buffers"); + +end GCVRT.Bpkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.adb similarity index 64% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.adb rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.adb index 1923cd7da..b57053032 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.adb @@ -1,15 +1,15 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; -with GNATcov_RTS.Buffers.Lists.foo; -package body GNATcov_RTS.Buffers.DB_main_1 is +with GCVRT.Foo; +package body GCVRT.DB_main_1 is procedure Dump_Buffers is begin GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GNATcov_RTS.Buffers.Lists.foo.List, + (GCVRT.Foo.List, Program_Name => "main_1", Exec_Date => 0); end Dump_Buffers; -end GNATcov_RTS.Buffers.DB_main_1; +end GCVRT.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.ads similarity index 60% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.ads index e8975f8ba..8a501b2da 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.ads @@ -1,6 +1,8 @@ pragma Style_Checks (Off); pragma Warnings (Off); -package GNATcov_RTS.Buffers.DB_main_1 is +with GNATcov_RTS.Buffers; +package GCVRT.DB_main_1 is procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); -end GNATcov_RTS.Buffers.DB_main_1; + +end GCVRT.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.adb similarity index 64% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.adb rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.adb index c868d1f17..ccab2ae8d 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.adb @@ -1,15 +1,15 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; -with GNATcov_RTS.Buffers.Lists.foo; -package body GNATcov_RTS.Buffers.DB_main_2 is +with GCVRT.Foo; +package body GCVRT.DB_main_2 is procedure Dump_Buffers is begin GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GNATcov_RTS.Buffers.Lists.foo.List, + (GCVRT.Foo.List, Program_Name => "main_2", Exec_Date => 0); end Dump_Buffers; -end GNATcov_RTS.Buffers.DB_main_2; +end GCVRT.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.ads similarity index 60% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.ads index 5a1450133..0f4078092 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.ads @@ -1,6 +1,8 @@ pragma Style_Checks (Off); pragma Warnings (Off); -package GNATcov_RTS.Buffers.DB_main_2 is +with GNATcov_RTS.Buffers; +package GCVRT.DB_main_2 is procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); -end GNATcov_RTS.Buffers.DB_main_2; + +end GCVRT.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads new file mode 100644 index 000000000..8a33e62aa --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads @@ -0,0 +1,25 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +with GCVRT.Bmain_1; +with GCVRT.Bmain_2; +with GCVRT.Bpkg; + +package GCVRT.Foo is + + pragma Preelaborate; + + gnatcov_rts_buffers_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_main_1_buffers,"gnatcov_rts_buffers_main_1_buffers"); + gnatcov_rts_buffers_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_main_2_buffers,"gnatcov_rts_buffers_main_2_buffers"); + gnatcov_rts_buffers_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_pkg_buffers,"gnatcov_rts_buffers_pkg_buffers"); + List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( + 1 => gnatcov_rts_buffers_main_1_buffers'Access, + 2 => gnatcov_rts_buffers_main_2_buffers'Access, + 3 => gnatcov_rts_buffers_pkg_buffers'Access); + C_List : constant GNATcov_RTS.Buffers.Lists.GNATcov_RTS_Coverage_Buffers_Group_Array := + ( 3, List'Address); + pragma Export (C, C_List, "gnatcov_rts_buffers_array_Foo"); + +end GCVRT.Foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_1.ads similarity index 66% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_1.ads index baf5c0f4c..adbaa4d71 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_1.ads @@ -1,19 +1,23 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PB_main_1 is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1"); - -end GNATcov_RTS.Buffers.PB_main_1; +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pmain_1 is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1_1"); + +end Buffers_1; + +end GCVRT.Pmain_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_2.ads similarity index 66% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_2.ads index f40226dce..504bd5e24 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_2.ads @@ -1,19 +1,23 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PB_main_2 is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2"); - -end GNATcov_RTS.Buffers.PB_main_2; +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pmain_2 is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2_1"); + +end Buffers_1; + +end GCVRT.Pmain_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads new file mode 100644 index 000000000..d057902c9 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads @@ -0,0 +1,35 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Ppkg is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg_1"); + +end Buffers_1; + +package Buffers_2 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg_2"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg_2"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg_2"); + +end Buffers_2; + +end GCVRT.Ppkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads deleted file mode 100644 index 39a532e60..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads +++ /dev/null @@ -1,41 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; -with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GNATcov_RTS.Buffers.BB_pkg is - - pragma Preelaborate; - - Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); - Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg"); - - Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); - Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg"); - - MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); - MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg"); - - Unit_Name : constant String := "pkg"; - Project_Name : constant String := ""; - - Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := - (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), - Language => Unit_Based_Language, - Unit_Part => Unit_Body, - Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), - Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), - Statement => Statement_Buffer'Address, - Decision => Decision_Buffer'Address, - MCDC => MCDC_Buffer'Address, - Statement_Last_Bit => 2, - Decision_Last_Bit => 1, - MCDC_Last_Bit => 2); - - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_pkg_buffers"); - -end GNATcov_RTS.Buffers.BB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads deleted file mode 100644 index f041e06e8..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads +++ /dev/null @@ -1,41 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; -with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GNATcov_RTS.Buffers.BS_pkg is - - pragma Preelaborate; - - Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg"); - - Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg"); - - MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg"); - - Unit_Name : constant String := "pkg"; - Project_Name : constant String := ""; - - Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := - (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), - Language => Unit_Based_Language, - Unit_Part => Unit_Spec, - Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), - Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), - Statement => Statement_Buffer'Address, - Decision => Decision_Buffer'Address, - MCDC => MCDC_Buffer'Address, - Statement_Last_Bit => -1, - Decision_Last_Bit => -1, - MCDC_Last_Bit => -1); - - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_S_pkg_buffers"); - -end GNATcov_RTS.Buffers.BS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads deleted file mode 100644 index 63f03b9f4..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads +++ /dev/null @@ -1,25 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers.BB_main_1; -with GNATcov_RTS.Buffers.BB_main_2; -with GNATcov_RTS.Buffers.BB_pkg; -with GNATcov_RTS.Buffers.BS_pkg; - -package GNATcov_RTS.Buffers.Lists.foo is - - pragma Preelaborate; - - gnatcov_rts_buffers_B_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_B_main_1_buffers,"gnatcov_rts_buffers_B_main_1_buffers"); - gnatcov_rts_buffers_B_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_B_main_2_buffers,"gnatcov_rts_buffers_B_main_2_buffers"); - gnatcov_rts_buffers_B_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_B_pkg_buffers,"gnatcov_rts_buffers_B_pkg_buffers"); - gnatcov_rts_buffers_S_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_S_pkg_buffers,"gnatcov_rts_buffers_S_pkg_buffers"); - List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( - 1 => gnatcov_rts_buffers_B_main_1_buffers'Access, - 2 => gnatcov_rts_buffers_B_main_2_buffers'Access, - 3 => gnatcov_rts_buffers_B_pkg_buffers'Access, - 4 => gnatcov_rts_buffers_S_pkg_buffers'Access); - -end GNATcov_RTS.Buffers.Lists.foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads deleted file mode 100644 index 2f84e5165..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads +++ /dev/null @@ -1,19 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PB_pkg is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg"); - -end GNATcov_RTS.Buffers.PB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads deleted file mode 100644 index 71406c7f1..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads +++ /dev/null @@ -1,19 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PS_pkg is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg"); - -end GNATcov_RTS.Buffers.PS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb index 7a94497f7..cfb135284 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb @@ -1,8 +1,9 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Pkg; -with GNATcov_RTS.Buffers.PB_main_1;with GNATcov_RTS.Buffers.DB_main_1;with GNATcov_RTS;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +with GNATcov_RTS.Buffers;with GCVRT.Pmain_1;with GCVRT.DB_main_1;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is begin - GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_main_1.Statement_Buffer,0);Pkg.Compute (True, False); -GNATcov_RTS.Buffers.DB_main_1.Dump_Buffers;end Main_1; + GNATcov_RTS.Buffers.Witness(GCVRT.Pmain_1.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); +GCVRT.DB_main_1.Dump_Buffers;end Main_1; + diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index 255ad5bef91d788cd2cd950cee8283d653c7128c..a136b1e8d13a1557ad20f0640ee748747697bde7 100644 GIT binary patch delta 35 qcmZo>Ze|v7_j3$M&M#9)&PYwpF38W!D`DW>D5Am0_; delta 35 qcmZo>Ze|v7_j3$M&M#9)&PYwpF38W!D`DW?D5Am0_;a!?qZZe|v7_j3$M&M#9)&PYwpF38W!D`DW>D5Am0_; delta 35 qcmZo>Ze|v7_j3$M&M#9)&PYwpF38W!D`DW?D5Am0_;a!?qZ TiZV=AW=!KTf|$w$ zc4qv&`4qDxBarii z1<0AK!3rXCSd}MFW)++KpOtU&Qr0j-kf~tjfM^us!BQw9Mj$nl_1JXS3yRD$9bQeI loXB=g-B{PaOxMs@!N}Ok(9p`%TtVBw$jZO~q!R>SGyp5ZLInT- delta 316 zcmeywca2ZP-On*3IloLHIU_YWyC6R^uY`enqKJc+kzQg>CKCe_0|OZI0%KYj;7@AobnOhkcDrg%RSQ!|AjfEKxqyfRhL|Om< diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index 6d8d58fee919991e9661b3c759ba00fa266c61f2..4f6f771d824294e26979c7bbf23af408470bbe67 100644 GIT binary patch delta 299 zcmaFB_lHl!-On*3IloLHIU_YWyC6R^uY`ejqKL!f1&r*hObiSROq16zN(uoP42(d` z2E@6EnR)Ss6X%JufJ7&5Z3WYltr*jIjPw$7GMN~-fZ|*e6AUo58BM;-XgK)7eP`(#$;2FBl$+nAjhe{Vj;tjGxDykP-yCL6GV$P!j%W}u0aSFmQk;!IkI_v`JHG3RhO`e>|c0t`(*T78I&{)C9*vin*%G5$Z Q+rY@mzyNFo)J%{*0FXdEApigX delta 282 zcmeyv_kd5t-On*3IloLHIU_YWyC6R^uY`enqKE^JkzQg>CKCe_0|Nuou7=KQl#_Y`abMq}`MMfa!4-1ep*?|>Awy-Ks7G@Kg z{GL^8@Q3fE$P0Y-TH)LR71aW|XZQ@#MUJwH;VFYAM4rG*=oXe;U7A?q5 S2T3w8PyB1m43acwR0II4?+=^+ delta 82 zcmZ3$ynuN^3?swDNNdsD#LT>SLk0#$1_)pSQ4?1}C5)h=K#Cc}ob1SGJ-LBVVd4+L P$*hd}90l3wAYldoq!ABY diff --git a/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace b/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace index ef244cfe7684d3d525848372a52cb172a6761f00..f9310f2c01f1f50fa8eb8d28c7a4d558556fa316 100644 GIT binary patch delta 86 zcmZo+ZegAfGcmzJkO2sC6EpMT4M8jh2DXVStr3Do3=E7wLFUP>jMkhW>4NNZ2Ih%h PtwrD*AcF~rS%4S-@dysG delta 84 zcmZo+ZegAf!^ki((poS#F*7gTkO2(XK;*=wP(dRG21X#C86-H_l+jwWAUhq*V*(1W Nz+@(Vv}OTG006GK4wC=? diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 1ddccc5b96d894fca0916193751ec3b474e86839..2ea341c6bba732d35d81f98a0fb29faaeff9b510 100644 GIT binary patch delta 376 zcmbQnKb>F1-On*3IloLHIU_YWyC6R^uY`ejqKG>S0}xD%c7)J#EGG*vvO?Im%s7)6 z8JQVD3MPv(USMRJ9LMCs#t4#SnS772X!0Va4#wY;wV9pSe?vt}nQhsBGeK1BWR~Fs z=>>zy_n0-n=CVxYW>JQ+j9FBntXMd!odswD)U?wqwm|baS;H7vCMU3pGcr%EU|p>N zG7sb^HXzPT%*=~7#1Jt8iA=U<(~dd|WZdAHcK+tu$tOUX1b{dtwJbF!zaTd?uSB<` zC^Z!%J_U%Ktzt6rb5mndD~l3KQ)1Hd5=(#qmRgjUo*Gk^; delta 394 zcmbQvKaF3+-On*3IloLHIU_YWyC6R^uY`enqKNy%c*luLELoEn8JQU;J~Lx21~De9 zGG3VM&Xmo^$il$D0K!~A%sKfRqswFiW{%0bm>L*=PPS%tX8*~^43uG>+{$dr{*wv9 zKFKV@31V>rG5h3q%o?l^acLH1D9f2e70Swmv!=5EO@Nwqo5dDrz9efHBlF|}R&hp_ z$sMe#Wf+0xu>o;zVrE{vAqvlEax|NE{R^PvyB$26H`s)p07(k~v5|?MLAip4k%5ts zp`nq1CP;ie5IbANWaQ_j#-yYc<)We(O8I;R(2vHK{SMz6k;W$v#|)rbmB*7 zE!g-0mRf~0HvU2y=k4WUqQedIX6DV#yW4w7ekAkzhr37B=1s18d0wrznzgHIC*e2_ zStmyUM3DGB&wtl50&UZk*s5PBzqkIk=KA>+zY|Y|)Tn^QS?%hy6!G)M`&TZaVs`{v zg9Q$EX)mFq1xF{wMtM3wCn_^Qw0Nl%Mo$PQ4Lg{m+^Rwg&xa;&cc{OqPO7{bOeLs4Tih~6p4^%#Nx%Rsj6YkGOtAm} literal 1851 zcmb7FJ!lkB5Z-qe6{93kvB_!JU>WvqZxMr{La;~*f1(&{0&(4Yxtz(~o_Cug7O5;O zv=OxMr%($)5n>_ONJ_C2yI^5Zuo5j|qm4S>?9OIS6VD7cH*e?7H$UJ0yy25WXT6|l zdQ;k)t_789XlyeKL$N9&gGEQ;FpPd$7ec>Q7<26XmhBv{+`2bq`IWhX?^dc4#k^a( zpj1`?xS2HaX5tj>;Le(GCmX~2$gWepHeDucLrMcdE@{0jFzGo45QXaBfv;nQA0$neChALym0aUjSn9?7kb_- z_vUgpu_*uqCwUWg5TQ^+R9MFbL_NJacjffZlXv&d-RavmeEw0_gZZUsEBa42A$|o8 zp~$+GG##WKk9aR0c8{;*-+mi>c4o)XpT}?86w?w6;OKN223Tl1*A}`y7WlQjQQUjz(MhN zpi$V}q!4~&+V_!3=je=a$N@6ZTT1~9EdU_^G4z7KuyjZOI@lgNVc<6uXl7Eg={Ttj zi>ll>1L&e961~ZsNhB70QzR$qA{T6q6tYoPy9k3Eup7KHgkX^gxHs}(_~_fk?IPx{ zEhl+;WDDHVXD1>s1&RF$_lO6zB|YiR&V=$>!EIz&Xemj>qt@~89f(i_=Pxg&fm False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1_1"); Unit_Name : constant String := "main_1"; - Project_Name : constant String := ""; Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := (Fingerprint => (125, 27, 0, 113, 188, 140, 235, 155, 190, 125, 180, 238, 139, 95, 108, 198, 229, 72, 222, 11), Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, @@ -33,9 +34,11 @@ package GNATcov_RTS.Buffers.BB_main_1 is Statement_Last_Bit => 0, Decision_Last_Bit => -1, MCDC_Last_Bit => -1); +end Buffers_1; - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_1_buffers"); + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_1_buffers"); -end GNATcov_RTS.Buffers.BB_main_1; +end GCVRT.Bmain_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_2.ads similarity index 77% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_2.ads index fb7e669bc..d68593c7f 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_2.ads @@ -1,31 +1,32 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Interfaces.C; use Interfaces.C; +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GNATcov_RTS.Buffers.BB_main_2 is +package GCVRT.Bmain_2 is pragma Preelaborate; +package Buffers_1 is Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2_1"); Unit_Name : constant String := "main_2"; - Project_Name : constant String := ""; Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := (Fingerprint => (242, 237, 33, 15, 121, 175, 106, 160, 145, 225, 226, 10, 175, 16, 207, 223, 26, 27, 27, 148), Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, @@ -33,9 +34,11 @@ package GNATcov_RTS.Buffers.BB_main_2 is Statement_Last_Bit => 0, Decision_Last_Bit => -1, MCDC_Last_Bit => -1); +end Buffers_1; - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_2_buffers"); + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_2_buffers"); -end GNATcov_RTS.Buffers.BB_main_2; +end GCVRT.Bmain_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bpkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bpkg.ads new file mode 100644 index 000000000..46d0ddbc6 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bpkg.ads @@ -0,0 +1,74 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GCVRT.Bpkg is + + pragma Preelaborate; + +package Buffers_1 is + Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg_1"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg_1"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg_1"); + + Unit_Name : constant String := "pkg"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), + Language => Unit_Based_Language, + Unit_Part => Unit_Spec, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => -1, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); +end Buffers_1; + +package Buffers_2 is + Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg_2"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg_2"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg_2"); + + Unit_Name : constant String := "pkg"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 2, + Decision_Last_Bit => 1, + MCDC_Last_Bit => 2); +end Buffers_2; + + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access, +2 => Buffers_2.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 2, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_pkg_buffers"); + +end GCVRT.Bpkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.adb similarity index 55% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.adb rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.adb index 18ea1e0ed..79e3fa3de 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.adb @@ -1,15 +1,20 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; -with GNATcov_RTS.Buffers.Lists.foo; -package body GNATcov_RTS.Buffers.DB_main_1 is +with GCVRT.Foo; +package body GCVRT.DB_main_1 is procedure Dump_Buffers is begin GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GNATcov_RTS.Buffers.Lists.foo.List, + (GCVRT.Foo.List, Program_Name => "main_1", Exec_Date => 0); end Dump_Buffers; -end GNATcov_RTS.Buffers.DB_main_1; + overriding procedure Finalize (Self : in out Dump_Controlled_Type) is + begin + Dump_Buffers; + end Finalize; + +end GCVRT.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads new file mode 100644 index 000000000..fb6f2406e --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads @@ -0,0 +1,13 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers; +with Ada.Finalization; +package GCVRT.DB_main_1 is + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); + + type Dump_Controlled_Type is new Ada.Finalization.Controlled with + null record; + overriding procedure Finalize (Self : in out Dump_Controlled_Type); + +end GCVRT.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.adb similarity index 55% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.adb rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.adb index 02b84cc6a..d684712eb 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.adb @@ -1,15 +1,20 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; -with GNATcov_RTS.Buffers.Lists.foo; -package body GNATcov_RTS.Buffers.DB_main_2 is +with GCVRT.Foo; +package body GCVRT.DB_main_2 is procedure Dump_Buffers is begin GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GNATcov_RTS.Buffers.Lists.foo.List, + (GCVRT.Foo.List, Program_Name => "main_2", Exec_Date => 0); end Dump_Buffers; -end GNATcov_RTS.Buffers.DB_main_2; + overriding procedure Finalize (Self : in out Dump_Controlled_Type) is + begin + Dump_Buffers; + end Finalize; + +end GCVRT.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads new file mode 100644 index 000000000..691c4c538 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads @@ -0,0 +1,13 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers; +with Ada.Finalization; +package GCVRT.DB_main_2 is + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); + + type Dump_Controlled_Type is new Ada.Finalization.Controlled with + null record; + overriding procedure Finalize (Self : in out Dump_Controlled_Type); + +end GCVRT.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads new file mode 100644 index 000000000..c9aac77d4 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads @@ -0,0 +1,25 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +with GCVRT.Bmain_1; +with GCVRT.Bmain_2; +with GCVRT.Bpkg; + +package GCVRT.Foo is + + pragma Preelaborate; + + gnatcov_rts_buffers_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_main_1_buffers,"gnatcov_rts_buffers_main_1_buffers"); + gnatcov_rts_buffers_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_main_2_buffers,"gnatcov_rts_buffers_main_2_buffers"); + gnatcov_rts_buffers_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_pkg_buffers,"gnatcov_rts_buffers_pkg_buffers"); + List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( + 1 => gnatcov_rts_buffers_main_1_buffers'Access, + 2 => gnatcov_rts_buffers_main_2_buffers'Access, + 3 => gnatcov_rts_buffers_pkg_buffers'Access); + C_List : constant GNATcov_RTS.Buffers.Lists.GNATcov_RTS_Coverage_Buffers_Group_Array := + ( 3, List'Address); + pragma Export (C, C_List, "gnatcov_rts_buffers_array_Foo"); + +end GCVRT.Foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_1.ads similarity index 63% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_1.ads index 1d0b35bd8..c5a253048 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_1.ads @@ -1,19 +1,23 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PB_main_1 is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1"); - -end GNATcov_RTS.Buffers.PB_main_1; +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pmain_1 is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1_1"); + +end Buffers_1; + +end GCVRT.Pmain_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_2.ads similarity index 63% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_2.ads index f9f18da05..8bbd8b5ce 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_2.ads @@ -1,19 +1,23 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PB_main_2 is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2"); - -end GNATcov_RTS.Buffers.PB_main_2; +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pmain_2 is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2_1"); + +end Buffers_1; + +end GCVRT.Pmain_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads new file mode 100644 index 000000000..91152a7b1 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads @@ -0,0 +1,35 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Ppkg is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg_1"); + +end Buffers_1; + +package Buffers_2 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg_2"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg_2"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg_2"); + +end Buffers_2; + +end GCVRT.Ppkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads deleted file mode 100644 index 8d1bde3aa..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads +++ /dev/null @@ -1,41 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; -with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GNATcov_RTS.Buffers.BB_pkg is - - pragma Preelaborate; - - Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); - Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg"); - - Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); - Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg"); - - MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); - MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg"); - - Unit_Name : constant String := "pkg"; - Project_Name : constant String := ""; - - Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := - (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), - Language => Unit_Based_Language, - Unit_Part => Unit_Body, - Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), - Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), - Statement => Statement_Buffer'Address, - Decision => Decision_Buffer'Address, - MCDC => MCDC_Buffer'Address, - Statement_Last_Bit => 2, - Decision_Last_Bit => 1, - MCDC_Last_Bit => 2); - - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_pkg_buffers"); - -end GNATcov_RTS.Buffers.BB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads deleted file mode 100644 index 4c9260685..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads +++ /dev/null @@ -1,41 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; -with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GNATcov_RTS.Buffers.BS_pkg is - - pragma Preelaborate; - - Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg"); - - Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg"); - - MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg"); - - Unit_Name : constant String := "pkg"; - Project_Name : constant String := ""; - - Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := - (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), - Language => Unit_Based_Language, - Unit_Part => Unit_Spec, - Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), - Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), - Statement => Statement_Buffer'Address, - Decision => Decision_Buffer'Address, - MCDC => MCDC_Buffer'Address, - Statement_Last_Bit => -1, - Decision_Last_Bit => -1, - MCDC_Last_Bit => -1); - - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_S_pkg_buffers"); - -end GNATcov_RTS.Buffers.BS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads deleted file mode 100644 index ca5c6b54d..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads +++ /dev/null @@ -1,6 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -package GNATcov_RTS.Buffers.DB_main_1 is - - procedure Dump_Buffers; - pragma Convention (C, Dump_Buffers); -end GNATcov_RTS.Buffers.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads deleted file mode 100644 index 06f972268..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads +++ /dev/null @@ -1,6 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -package GNATcov_RTS.Buffers.DB_main_2 is - - procedure Dump_Buffers; - pragma Convention (C, Dump_Buffers); -end GNATcov_RTS.Buffers.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads deleted file mode 100644 index dfb98dbbb..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads +++ /dev/null @@ -1,25 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers.BB_main_1; -with GNATcov_RTS.Buffers.BB_main_2; -with GNATcov_RTS.Buffers.BB_pkg; -with GNATcov_RTS.Buffers.BS_pkg; - -package GNATcov_RTS.Buffers.Lists.foo is - - pragma Preelaborate; - - gnatcov_rts_buffers_B_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_B_main_1_buffers,"gnatcov_rts_buffers_B_main_1_buffers"); - gnatcov_rts_buffers_B_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_B_main_2_buffers,"gnatcov_rts_buffers_B_main_2_buffers"); - gnatcov_rts_buffers_B_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_B_pkg_buffers,"gnatcov_rts_buffers_B_pkg_buffers"); - gnatcov_rts_buffers_S_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_S_pkg_buffers,"gnatcov_rts_buffers_S_pkg_buffers"); - List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( - 1 => gnatcov_rts_buffers_B_main_1_buffers'Access, - 2 => gnatcov_rts_buffers_B_main_2_buffers'Access, - 3 => gnatcov_rts_buffers_B_pkg_buffers'Access, - 4 => gnatcov_rts_buffers_S_pkg_buffers'Access); - -end GNATcov_RTS.Buffers.Lists.foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads deleted file mode 100644 index 638a84ec2..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads +++ /dev/null @@ -1,19 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PB_pkg is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg"); - -end GNATcov_RTS.Buffers.PB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads deleted file mode 100644 index c8f18f74f..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads +++ /dev/null @@ -1,19 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PS_pkg is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg"); - -end GNATcov_RTS.Buffers.PS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb index 61decca75..c9267341a 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb @@ -1,8 +1,9 @@ pragma Style_Checks (Off); pragma Warnings (Off); -with Pkg; - -with GNATcov_RTS.Buffers.PB_main_1;with GNATcov_RTS.Buffers.DB_main_1;with GNATcov_RTS;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is -begin - GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_main_1.Statement_Buffer,0);Pkg.Compute (True, False); -GNATcov_RTS.Buffers.DB_main_1.Dump_Buffers;end Main_1; +with Pkg; + +with GNATcov_RTS.Buffers;with GCVRT.Pmain_1;with GCVRT.DB_main_1;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +GNATcov_Dump_Object:GCVRT.DB_main_1.Dump_Controlled_Type;begin + GNATcov_RTS.Buffers.Witness(GCVRT.Pmain_1.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); +end Main_1; + diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid index b5f7a753eb7df7f191cc68d5518e5a7abea5f66d..6095ca35ca556f6bbca09c4f490391ed56311f51 100644 GIT binary patch delta 35 qcmZo=ZeD5Ay4_D5Ay4_)s;RLFHfXP#sG@xn@GATn@FPT)K mEMaCC%a$2v0>tRajm)-;zbEf!R$yeB{D4`Uk#X`5W+ebZej#Z9 delta 189 zcmbQmF^faQ-On*3IloLHIU_YWyC6R^uY`enqKG|P5+frs1JguJeLe;tU;<)BMi4Ps zgz*d?BZv>e96-!IabCgX1SXEjFBt7uA!@XlY}tP@LD>0BGMpe5H%RH^DNGtrH3ylL rp{$oos!*0NGmK@+3^W01V Date: Wed, 14 Jun 2023 07:28:44 +0200 Subject: [PATCH 0328/1483] Update tests following instrumentation changes --- testsuite/tests/instr-cov/ext_gpr/test.py | 14 +++++++------- .../tests/instr-cov/manual-dump/covdump__cov.adb | 4 ++-- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/testsuite/tests/instr-cov/ext_gpr/test.py b/testsuite/tests/instr-cov/ext_gpr/test.py index 1238e3215..b76c9b08c 100644 --- a/testsuite/tests/instr-cov/ext_gpr/test.py +++ b/testsuite/tests/instr-cov/ext_gpr/test.py @@ -25,13 +25,13 @@ thistest.fail_if_not_equal( "instrumented directories", "\n".join([ - "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-bs_pkg.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-bs_pkg1.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-bs_pkg2.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-lists-p_ext2.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-ps_pkg.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-ps_pkg1.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-ps_pkg2.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bpkg.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bpkg1.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bpkg2.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-p_ext2.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-ppkg.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-ppkg1.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-ppkg2.ads", "obj-p_ext2/p_ext2-gnatcov-instr/pkg.ads", "obj-p_ext2/p_ext2-gnatcov-instr/pkg1.ads", "obj-p_ext2/p_ext2-gnatcov-instr/pkg2.ads", diff --git a/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb b/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb index 6c40b1da8..f53e6de38 100644 --- a/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb +++ b/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb @@ -1,11 +1,11 @@ with Ada.Command_Line; -with GNATcov_RTS.Buffers.Lists.P; +with GCVRT.P; with GNATcov_RTS.Traces.Output.Files; procedure Covdump is begin GNATcov_RTS.Traces.Output.Files.Write_Trace_File - (Buffers_Groups => GNATcov_RTS.Buffers.Lists.P.List, + (Buffers_Groups => GCVRT.P.List, Filename => Ada.Command_Line.Command_Name & ".srctrace"); end Covdump; From 6cbd138a01948097f71c9ba367254746c9118a8d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 16 Jun 2023 11:15:23 +0200 Subject: [PATCH 0329/1483] U204-026-arch-mix: kill test for light profiles When using --dump-trigger=main-end on a native profile, we use controlled objects and finalization to make sure that we do not miss any code execution (notably the execution of finalizers for controlled objects declared at the beginning of the main). This is not compatible with cross targets under light profiles, as controlled objects are not available in these configuration. Kill the tests there, as its main goal is to check inter-host compatibility. The limitation of having sources instrumented natively not being compilable for cross light profiles is acceptable. --- testsuite/tests/U204-026-arch-mix/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/U204-026-arch-mix/test.opt diff --git a/testsuite/tests/U204-026-arch-mix/test.opt b/testsuite/tests/U204-026-arch-mix/test.opt new file mode 100644 index 000000000..fefea3e78 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/test.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD Native instrumentation not compatible with cross light profiles From 22a3bde0af4f90902f2c51de8da35bc4d12c578e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 8 Jun 2023 11:09:33 +0000 Subject: [PATCH 0330/1483] Remove obsolete trace adapters The gdb trace adapter has not been used in at least 10 years. The valgrind and dynamorio adapters have been unsupported for 2 years and are not used nor tested for months. Remove them and simplify the build system accordingly (i.e. avoid dead code). --- tools/gnatcov/Makefile | 69 +- tools/gnatcov/trace_adapters/README.md | 4 +- .../trace_adapters/dynamorio/CMakeLists.txt | 23 - .../gnatcov/trace_adapters/dynamorio/Makefile | 52 -- .../gnatcov/trace_adapters/dynamorio/qtrace.c | 673 ------------------ .../gnatcov/trace_adapters/dynamorio/qtrace.h | 76 -- .../trace_adapters/gdb/gdbtrace-exec_info.adb | 189 ----- .../trace_adapters/gdb/gdbtrace-gdb_mi_io.adb | 169 ----- tools/gnatcov/trace_adapters/gdb/gdbtrace.adb | 627 ---------------- .../gnatcov/trace_adapters/valgrind/Makefile | 81 --- .../gnatcov/trace_adapters/valgrind/README.md | 22 - .../trace_adapters/valgrind/cov_main.c | 401 ----------- .../trace_adapters/valgrind/cov_traces.c | 483 ------------- .../trace_adapters/valgrind/cov_traces.h | 142 ---- 14 files changed, 13 insertions(+), 2998 deletions(-) delete mode 100644 tools/gnatcov/trace_adapters/dynamorio/CMakeLists.txt delete mode 100644 tools/gnatcov/trace_adapters/dynamorio/Makefile delete mode 100644 tools/gnatcov/trace_adapters/dynamorio/qtrace.c delete mode 100644 tools/gnatcov/trace_adapters/dynamorio/qtrace.h delete mode 100644 tools/gnatcov/trace_adapters/gdb/gdbtrace-exec_info.adb delete mode 100644 tools/gnatcov/trace_adapters/gdb/gdbtrace-gdb_mi_io.adb delete mode 100644 tools/gnatcov/trace_adapters/gdb/gdbtrace.adb delete mode 100644 tools/gnatcov/trace_adapters/valgrind/Makefile delete mode 100644 tools/gnatcov/trace_adapters/valgrind/README.md delete mode 100644 tools/gnatcov/trace_adapters/valgrind/cov_main.c delete mode 100644 tools/gnatcov/trace_adapters/valgrind/cov_traces.c delete mode 100644 tools/gnatcov/trace_adapters/valgrind/cov_traces.h diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index a05392273..d7a00b0af 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -12,7 +12,7 @@ # # all # bin <- default -# adapters [ADAPTERS_LIST=dynamorio|valgrind|...] +# adapters [ADAPTERS_LIST=trace32|...] # ---------------- # -- To install -- @@ -22,7 +22,7 @@ # install-bin # install-examples # -# install-adapters [ADAPTERS_LIST=dynamorio|valgrind|...] +# install-adapters [ADAPTERS_LIST=trace32|...] # # All working with the PREFIX variable, that users may specify: @@ -34,29 +34,6 @@ PREFIX=$(PWD)/local # By default, assume that the binutils dependency was built in the source tree. BINUTILS_BUILD_DIR?=$(BINUTILS_SRC_DIR) -# Note for the trace adapters: -# ---------------------------- - -# When *building* adapters for native configurations, we usually need to know -# the execution engine "prefix" to get access to e.g. header files (valgrind) -# or cmake artifacts (dynamoRIO). - -# By default, we infer that prefix from the location of "valgrind" or "drrun" -# on the PATH, and users may specify an alternate location by setting the -# VALGRIND_PREFIX or DYNRIO_PREFIX Makefile variable. - -# When *installing* adapters, we need the location of the valgrind install -# tree where the valgrind adapter needs to go. By default, we infer that from -# the location of "valgrind" on the PATH. Users may alter that choice by -# setting the VALGRIND_PREFIX variable. - -# dynamorio doesn't need the client to be installed within it's own tree, so -# we install within the bundled install tree, rooted at PREFIX and gnatcov -# passes the complete client path to dynamorio. - -# Alternatively, users may specify a final location by setting the -# VALGRIND_TOOL_INSTALL_DIR or DYNRIO_CLIENT_INSTALL_DIR variable. - # ---------------- # -- To cleanup -- # ---------------- @@ -106,11 +83,11 @@ endif # users get the core only by default in case they don't need the # adapters for their host, e.g. when building for gnatemu targets. -# For example, a user who needs to build gnatcov on linux to perform -# ppc-elf coverage only doesn't need the valgrind adapter for native -# coverage. He might moreover be on a system where the adapter build -# would fail (e.g. missing header files), so we really shouldn't try -# to build these adapters by default. +# For example, a user who needs to build gnatcov on linux to perform ppc-elf +# coverage only doesn't need the trace32 adapter for the corresponding probe. +# He might moreover be on a system where the adapter build would fail (e.g. +# missing probe-specific files), so we really shouldn't try to build these +# adapters by default. # So ... # @@ -130,17 +107,17 @@ include architecture.mk ifeq ($(HOST_OS), windows) ifeq ($(BITS_ARCH), 32) -DEFAULT_ADAPTERS = nexus dynamorio trace32 +DEFAULT_ADAPTERS = nexus trace32 else -DEFAULT_ADAPTERS = dynamorio +DEFAULT_ADAPTERS = endif endif ifeq ($(HOST_OS), linux) ifeq ($(BITS_ARCH), 32) -DEFAULT_ADAPTERS = valgrind +DEFAULT_ADAPTERS = else -DEFAULT_ADAPTERS = valgrind trace32 +DEFAULT_ADAPTERS = trace32 endif endif @@ -153,30 +130,6 @@ BUILD_MODE=dev # == Variables to pass down to sub-makefiles for trace adapters == # ================================================================ -# For valgrind, we need a prefix indication at build time to find header -# files, and at install time to place the "tool" within the valgrind install -# tree. - -VALGRIND_PREFIX?=$(shell dirname `which valgrind`)/.. - -valgrind_ADAPTER_BUILD_VARS=\ - VALGRIND_PREFIX?=$(VALGRIND_PREFIX) - -valgrind_ADAPTER_INSTALL_VARS=\ - VALGRIND_TOOL_INSTALL_DIR?=$(VALGRIND_PREFIX)/libexec/valgrind - -# For dynamorio, we need a prefix indication at build time to find header -# files and cmake artifacts, and can always install within the gnatcov install -# tree. - -DYNRIO_PREFIX?=$(shell dirname `which drrun`)/.. - -dynamorio_ADAPTER_BUILD_VARS=\ - DYNRIO_PREFIX?=$(DYNRIO_PREFIX) - -dynamorio_ADAPTER_INSTALL_VARS=\ - DYNRIO_CLIENT_INSTALL_DIR?=$(PREFIX)/libexec/gnatcoverage/lib$(BITS_ARCH) - # Trace32 and Nexus (iSystem) adapters use the same prefix as GNATcov trace32_ADAPTER_INSTALL_VARS=PREFIX=$(PREFIX) nexus_ADAPTER_INSTALL_VARS=PREFIX=$(PREFIX) diff --git a/tools/gnatcov/trace_adapters/README.md b/tools/gnatcov/trace_adapters/README.md index cecae9fe2..ea88d3be3 100644 --- a/tools/gnatcov/trace_adapters/README.md +++ b/tools/gnatcov/trace_adapters/README.md @@ -1,3 +1,3 @@ -This directory hosts trace adapters for GNATcoverage, which are programs -or plugins used to help the production of execution traces in a format that +This directory hosts trace adapters for GNATcoverage, which are programs or +plugins used to help the production of execution binary traces in a format that gnatcov coverage knows to process. diff --git a/tools/gnatcov/trace_adapters/dynamorio/CMakeLists.txt b/tools/gnatcov/trace_adapters/dynamorio/CMakeLists.txt deleted file mode 100644 index 85a7ad1e5..000000000 --- a/tools/gnatcov/trace_adapters/dynamorio/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -# Usage: -# -# cmake -DDynamoRIO_DIR=$PWD/../dynamorio/cmake ../dr-gnatcov -# make -# ../dynamorio/bin64/drrun -client libqtrace.so 0 -- /bin/ls - -cmake_minimum_required(VERSION 2.6) - -add_library(qtrace SHARED qtrace.c) -find_package(DynamoRIO) -if (NOT DynamoRIO_FOUND) - message(FATAL_ERROR "DynamoRIO package required to build") -endif(NOT DynamoRIO_FOUND) - -use_DynamoRIO_extension(qtrace drx) - -configure_DynamoRIO_client(qtrace) - -if(CMAKE_COMPILER_IS_GNUCC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra") -else(CMAKE_COMPILER_IS_GNUCC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall") -endif(CMAKE_COMPILER_IS_GNUCC) diff --git a/tools/gnatcov/trace_adapters/dynamorio/Makefile b/tools/gnatcov/trace_adapters/dynamorio/Makefile deleted file mode 100644 index 4f2637050..000000000 --- a/tools/gnatcov/trace_adapters/dynamorio/Makefile +++ /dev/null @@ -1,52 +0,0 @@ -include ../../architecture.mk -include ../../host.mk - - -DYNRIO_CONFIG=Release -DYNRIO_CLIENT=INVALID - -ifeq ($(HOST_OS), windows) -DYNRIO_CLIENT=build/$(DYNRIO_CONFIG)/qtrace.dll -ifeq ($(BITS_ARCH), 32) -G_OPTION=-G"Visual Studio 12" -else -G_OPTION=-G"Visual Studio 12 Win64" -endif -endif - -ifeq ($(HOST_OS), linux) -DYNRIO_CLIENT=build/libqtrace.so -G_OPTION= -endif - -######### -# Build # -######### - -all: $(DYNRIO_CLIENT) - -.PHONY: $(DYNRIO_CLIENT) - -$(DYNRIO_CLIENT): - mkdir build || true - cd build && cmake -DDynamoRIO_DIR=$(DYNRIO_PREFIX)/cmake $(G_OPTION) .. - cd build && cmake --build . --config $(DYNRIO_CONFIG) - -################ -# Installation # -################ - -.PHONY: install - -install: - mkdir -p $(DYNRIO_CLIENT_INSTALL_DIR) - cp -p $(DYNRIO_CLIENT) $(DYNRIO_CLIENT_INSTALL_DIR) - -########### -# Cleanup # -########### - -.PHONY: clean - -clean: - rm -f $(DYNRIO_CLIENT) diff --git a/tools/gnatcov/trace_adapters/dynamorio/qtrace.c b/tools/gnatcov/trace_adapters/dynamorio/qtrace.c deleted file mode 100644 index eeeda0522..000000000 --- a/tools/gnatcov/trace_adapters/dynamorio/qtrace.c +++ /dev/null @@ -1,673 +0,0 @@ -/* - Copyright (C) 2013-2021, AdaCore - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY 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 - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307, USA. - - The GNU General Public License is contained in the file COPYING. -*/ - -#include -#include - -#ifdef LINUX - /* For pid_t, used in dr_defines.h. */ -# include -# include -#endif - -#include "dr_api.h" -#include "dr_tools.h" - -#include "qtrace.h" - -/* The DR_LOG_ALL macro used to be named LOG_ALL prior to DRIO 7.1. - Accommodate both conventions. */ -#ifndef DR_LOG_ALL -#define DR_LOG_ALL LOG_ALL -#endif - -/* History map. This is a sorted and fixed array of PCs for which a trace - must be written each time the instruction is executed. */ -static int nbr_histmap_entries; -static pctype *histmap_entries; -static int tracefile_history; - -static module_data_t *main_module; -static client_id_t client_id; -static file_t tracefile; - -/* Buffer of traces to be written on disk. */ -#define NBR_ENTRIES 1024 -static trace_entry trace_buffer[NBR_ENTRIES]; -static int nbr_entries = 0; -static void *trace_buffer_lock; - -/* Cache for traces, to coallesce flags. */ -struct trace_cache_entry -{ - /* Address of the first instruction for the trace entry. */ - app_pc addr; - - /* Size of the code for the trace entry. */ - uint16_t size; - - /* Branch flags. Same as a trace entry. - If the block has not been executed the value stay 0. */ - unsigned char op; -}; - -/* Buffer for traces caches, they are referenced in the translated code. */ -#define NBR_CACHE_ENTRIES 102400 -static struct trace_cache_entry cache_entries[NBR_CACHE_ENTRIES]; -static int cache_entries_idx = 0; - -/* LRU hash table for trace caches, to reuse them when retranslating code. The - key is the address of the first byte in the basic block and the value is the - index of a trace cache entry in CACHE_ENTRIES. - - This hash table has NBR_LRU_BUCKETS rows and each row has room for at most - NBR_LRU_ENTRIES collision. In one bucket, free cells are always last. - - Each cell contains either 0 (for no entry present) or N + 1 where N is the - index for the trace cache entry in CACHE_ENTRIES. */ -#define NBR_LRU_BUCKETS (0xffff + 1) -#define NBR_LRU_ENTRIES 4 -static int trace_lru_entries[NBR_LRU_BUCKETS][NBR_LRU_ENTRIES]; -static void *trace_lru_entries_lock; - -/* Compute the bucket index in TRACE_LRU_ENTRIES corresponding to the BB_ADDR - basic block address. - - Discard the address least significant bit as most basic block addresses are - aligned with 2 bytes. */ -#define LRU_BUCKET(BB_ADDR) \ - ((((intptr_t) BB_ADDR) >> 1) & (NBR_LRU_BUCKETS - 1)) - -static void -copy_string (char *destination, const char *source, size_t size) -{ - size_t source_size = strlen (source); - - if (source_size > size) - source_size = size - 1; - - memcpy (destination, source, source_size); - destination[source_size] = 0; -} - -static int -tracefile_history_search (pctype pc) -{ - if (tracefile_history) - return 1; - - if (nbr_histmap_entries) - { - int low = 0; - int high = nbr_histmap_entries - 1; - - while (low <= high) - { - int mid = low + (high - low) / 2; - pctype hist_pc = histmap_entries[mid]; - - if (hist_pc == pc) - return 1; - if (pc < hist_pc) - high = mid - 1; - else - low = mid + 1; - } - } - return 0; -} - -static void -flush_traces (void) -{ - ssize_t len = nbr_entries * sizeof (trace_entry); - - if (nbr_entries == 0) - return; - - ssize_t ret = dr_write_file (tracefile, trace_buffer, len); - if (ret != len) - { - dr_fprintf (STDERR, "error: cannot write trace (ret=%ld)\n", ret); - dr_exit_process (127); - } - - nbr_entries = 0; -} - -static void -write_trace (app_pc pc, unsigned int size, unsigned char op) -{ - trace_entry *ent; - - if (nbr_entries == NBR_ENTRIES) - flush_traces (); - - /* FIXME: atomic access ? */ - ent = &trace_buffer[nbr_entries++]; - ent->pc = (pctype) pc; - ent->size = size; - ent->op = op; -} - -static void -write_trace_cache_entry (struct trace_cache_entry *tce) -{ - write_trace (tce->addr, tce->size, tce->op); -} - -/* Callback invoked when a region has been flushed. Flush CACHE_ENTRIES. */ -static void -flush_cb (int id) -{ - int i; - - (void) id; - dr_mutex_lock (trace_buffer_lock); - dr_mutex_lock (trace_lru_entries_lock); - for (i = 0; i < cache_entries_idx; i++) { - /* Don't write the entries which has not been executed at all. They will - be executed later from a newly translated basic block. */ - if (cache_entries[i].op) { - write_trace_cache_entry (&cache_entries[i]); - } - } - cache_entries_idx = 0; - dr_mutex_unlock (trace_lru_entries_lock); - dr_mutex_unlock (trace_buffer_lock); -} - -/* Return through TCE_P a pointer to a trace entry for the code block that - starts at ADDR and that is SIZE bytes long. This returns whether a new - entry was created for this purpose otherwise, a previously cached one is - returned. - - If we are soon running out of available trace entries, this requests a trace - entry flush and translated code flush: both will happen at DynamoRIO's - earliest convenience, so prepare this before there is no entry left at - all. */ -static bool -get_trace_cache_entry (app_pc addr, uint16_t size, - struct trace_cache_entry **tce_p) -{ - struct trace_cache_entry *tce; - int *cell = NULL; - int *first_free_cell = NULL; - int i; - - dr_mutex_lock (trace_lru_entries_lock); - - /* First look for an existing entry for ADDR. */ - const int row = LRU_BUCKET (addr); - for (i = 0; i < NBR_LRU_ENTRIES; ++i) - { - cell = &trace_lru_entries[row][i]; - - /* This cell is free. */ - if (*cell == 0) - { - first_free_cell = cell; - break; - } - - /* This cell references a trace cache entry: if this is a collision, go - on, otherwise we found an existing entry for ADDR. */ - tce = &cache_entries[*cell - 1]; - if (tce->addr == addr && tce->size == size) - { - *tce_p = tce; - dr_mutex_unlock (trace_lru_entries_lock); - return false; - } - } - - /* If we reach this point, there is no trace entry for ADDR: allocate a new - one. */ - tce = &cache_entries[cache_entries_idx++]; - - /* Near end of cache. */ - if (cache_entries_idx >= NBR_CACHE_ENTRIES - 16) - { - /* Request for a flush. */ - if (cache_entries_idx == NBR_CACHE_ENTRIES - 16) - { - if (!dr_delay_flush_region (0, (size_t)-1, 0, flush_cb)) - dr_abort (); - } - else if (cache_entries_idx == NBR_CACHE_ENTRIES) - { - /* No more entries -> abort. */ - dr_abort (); - } - } - - /* Last thing to do is to register this trace cache entry in the LRU - cache. If there is no free cell left, pop the first one to make the last - one free. */ - if (first_free_cell == NULL) - { - int *row_ptr = &trace_lru_entries[row][0]; - for (i = 0; i < NBR_LRU_ENTRIES - 1; ++i) - row_ptr[i] = row_ptr[i + 1]; - first_free_cell = &row_ptr[NBR_LRU_ENTRIES - 1]; - } - *first_free_cell = cache_entries_idx - 1; - - *tce_p = tce; - dr_mutex_unlock (trace_lru_entries_lock); - return true; -} - -/* Clean call for the cbr */ -static void -at_cbr2_nocache(app_pc inst_addr, app_pc targ_addr, app_pc fall_addr, - int taken, void *bb_addr) -{ - uintptr_t bb_size = inst_addr + 2 - (app_pc) bb_addr; - - (void) targ_addr; - (void) fall_addr; - dr_mutex_lock (trace_buffer_lock); - write_trace ((app_pc)bb_addr, (unsigned) bb_size, - TRACE_OP_BLOCK | (taken ? TRACE_OP_BR0 : TRACE_OP_BR1)); - dr_mutex_unlock (trace_buffer_lock); -} - -static void -at_cbr6_nocache(app_pc inst_addr, app_pc targ_addr, app_pc fall_addr, - int taken, void *bb_addr) -{ - uintptr_t bb_size = inst_addr + 6 - (app_pc) bb_addr; - - (void) targ_addr; - (void) fall_addr; - dr_mutex_lock (trace_buffer_lock); - write_trace ((app_pc)bb_addr, (unsigned) bb_size, - TRACE_OP_BLOCK | (taken ? TRACE_OP_BR0 : TRACE_OP_BR1)); - dr_mutex_unlock (trace_buffer_lock); -} - -static void -at_cache(app_pc inst_addr, app_pc targ_addr, app_pc fall_addr, - int taken, void *arg) -{ - struct trace_cache_entry *tce = (struct trace_cache_entry *)arg; - - (void) inst_addr; - (void) targ_addr; - (void) fall_addr; - - /* This assumes that we cannot execute this block while we are flushing the - basic block which seems correct here. So no need to grab the lock - here. */ - tce->op |= TRACE_OP_BLOCK; - tce->op |= taken ? TRACE_OP_BR0 : TRACE_OP_BR1; -} - -static dr_emit_flags_t -event_basic_block(void *drcontext, void *tag, instrlist_t *bb, - bool for_trace, bool translating) -{ - instr_t *instr; - app_pc bb_pc = dr_fragment_app_pc(tag); - - (void) for_trace; - (void) translating; - - /* No instrumentation if not part of the main module. */ - if (bb_pc < main_module->start || bb_pc > main_module->end) - return DR_EMIT_DEFAULT; - - /* For each instruction of the basic block. */ - for (instr = instrlist_first_app (bb); instr != NULL; ) - { - instr_t *next_instr = instr_get_next_app(instr); - - if (instr_is_cbr(instr)) - { - app_pc br_pc = instr_get_app_pc (instr); - int br_len; - - /* Instruction is a conditional branch. */ - if (next_instr != NULL) - { - /* Should be the last one of the basic block. */ - instrlist_disassemble(drcontext, tag, bb, STDOUT); - dr_exit_process (126); - } - - br_len = instr_length (drcontext, instr); - - /* Insert a call to at_cbr to always generate a trace. */ - if (tracefile_history_search ((pctype)br_pc)) - { - void *at_fun; - - switch (br_len) - { - case 2: - /* Conditionnal jump with a byte offset. */ - at_fun = (void *) at_cbr2_nocache; - break; - case 6: - /* Conditionnal jump with a long word offset. */ - at_fun = (void *) at_cbr6_nocache; - break; - default: - dr_abort (); - } - dr_insert_cbr_instrumentation_ex - (drcontext, bb, instr, at_fun, OPND_CREATE_INTPTR(bb_pc)); - } - else - { - struct trace_cache_entry *tce; - uint16_t size = (uint16_t) ((br_pc + br_len) - bb_pc); - - if (get_trace_cache_entry (bb_pc, size, &tce)) - { - tce->addr = bb_pc; - tce->size = size; - tce->op = 0; - } - - dr_insert_cbr_instrumentation_ex - (drcontext, bb, instr, at_cache, OPND_CREATE_INTPTR (tce)); - } - } - else if (instr_is_call_direct(instr) - || instr_is_call_indirect(instr) - || instr_is_return(instr) - || instr_is_ubr(instr) - || instr_is_mbr(instr)) - { - if (next_instr != NULL) - { - /* Must be the last instruction of the basic block. */ - instrlist_disassemble(drcontext, tag, bb, STDOUT); - dr_exit_process (126); - } - - /* This is an unconditional branch. No need to create yet another - trace entry if this block was already executed. */ - if (for_trace || translating) - return DR_EMIT_DEFAULT; - - app_pc next_pc = instr_get_app_pc (instr) - + instr_length (drcontext, instr); - - /* Generate the trace now, assuming the basic block will be - fully executed. */ - dr_mutex_lock (trace_buffer_lock); - write_trace (bb_pc, (unsigned) (next_pc - bb_pc), TRACE_OP_BLOCK); - dr_mutex_unlock (trace_buffer_lock); - } - instr = next_instr; - } - return DR_EMIT_DEFAULT; -} - -#ifdef LINUX -/* Disable all client features/effects for child processes. */ -static void -event_fork_init (void *drcontext) -{ - (void) drcontext; - - /* Invalidate all translated blocks so that all instrumentation is gone. */ - if (!dr_delay_flush_region (0, (size_t)-1, 0, NULL)) - dr_abort (); - - dr_unregister_bb_event (event_basic_block); -} -#endif - -static void -event_exit(void) -{ - int i; - - /* No need for locking, here: the event exit should not run in parallel with - other trace manipulating code. */ - -#if 0 - dr_fprintf (STDERR, "flushing caches\n"); - write_trace (0, 0, 0); -#endif - - for (i = 0; i < cache_entries_idx; i++) - write_trace_cache_entry (&cache_entries[i]); - flush_traces (); - - dr_close_file (tracefile); - dr_mutex_destroy (trace_buffer_lock); - dr_mutex_destroy (trace_lru_entries); - tracefile = INVALID_FILE; -} - -static void -read_map_file(const char *filename) -{ - file_t histfile; - struct trace_header hdr; - uint64 length; - int ent_sz; - int i; - - histfile = dr_open_file (filename, DR_FILE_READ); - - if (tracefile == INVALID_FILE) - { - dr_fprintf (STDERR, "cannot open file %s\n", filename); - dr_exit_process (127); - } - - if (dr_read_file (histfile, &hdr, sizeof(hdr)) != sizeof(hdr)) - { - dr_fprintf (STDERR, - "cannot read trace header for histmap file '%s'\n", - filename); - dr_exit_process (127); - } - - if (memcmp (hdr.magic, QEMU_TRACE_MAGIC, sizeof(hdr.magic)) != 0 - || hdr.version != QEMU_TRACE_VERSION - || hdr.kind != QEMU_TRACE_KIND_DECISION_MAP - || hdr.sizeof_target_pc != sizeof (void *) - || (hdr.big_endian != 0 && hdr.big_endian != 1) - || hdr.machine[0] != (ELF_MACHINE >> 8) - || hdr.machine[1] != (ELF_MACHINE & 0xff) - || hdr._pad != 0) - { - dr_fprintf (STDERR, "bad header for histmap file '%s'\n", filename); - dr_exit_process (127); - } - - /* Get number of entries. */ - if (!dr_file_size (histfile, &length)) - { - dr_fprintf (STDERR, "cannot get size of histmap file '%s'\n", filename); - dr_exit_process (127); - } - - if (!dr_file_seek (histfile, sizeof(hdr), DR_SEEK_SET)) - { - dr_fprintf (STDERR, "cannot set seek of histmap file '%s'\n", filename); - dr_exit_process (127); - } - - length -= sizeof(hdr); - if (sizeof (void *) == 4) - ent_sz = sizeof(struct trace_entry32); - else - ent_sz = sizeof(struct trace_entry64); - - if ((length % ent_sz) != 0) - { - dr_fprintf (STDERR, "bad length of histmap file '%s'\n", filename); - dr_exit_process (127); - } - - nbr_histmap_entries = (int)(length / ent_sz); - if (nbr_histmap_entries) - histmap_entries = dr_global_alloc (nbr_histmap_entries * sizeof(void *)); - - for (i = 0; i < nbr_histmap_entries; i++) - { - trace_entry ent; - - if (dr_read_file (histfile, &ent, sizeof(ent)) != sizeof(ent)) - { - dr_fprintf (STDERR, "cannot read histmap entry from '%s'\n", - filename); - dr_exit_process (127); - } - if (i > 0 && ent.pc < histmap_entries[i - 1]) - { - dr_fprintf (STDERR, "unordered entry #%d in histmap file '%s'\n", - i, filename); - dr_exit_process (127); - } - - histmap_entries[i] = ent.pc; - } - dr_close_file (histfile); -} - -static void -create_trace_file (const char *filename) -{ - struct trace_header hdr; - - tracefile = dr_open_file (filename, - DR_FILE_CLOSE_ON_FORK | DR_FILE_WRITE_APPEND); - - if (tracefile == INVALID_FILE) - { - dr_fprintf (STDERR, "cannot open file %s\n", filename); - dr_exit_process (127); - } - - memcpy (hdr.magic, QEMU_TRACE_MAGIC, strlen (QEMU_TRACE_MAGIC)); - hdr.version = QEMU_TRACE_VERSION; - hdr.sizeof_target_pc = sizeof (void *); - hdr.kind = QEMU_TRACE_KIND_RAW; - hdr.big_endian = 0; /* x86 is little endian. */ - hdr.machine[0] = ELF_MACHINE >> 8; - hdr.machine[1] = ELF_MACHINE & 0xff; - - if (dr_write_file (tracefile, &hdr, sizeof(hdr)) != sizeof(hdr)) - { - dr_fprintf (STDERR, "cannot write trace header\n"); - dr_exit_process (127); - } -} - -DR_EXPORT -void dr_client_main(client_id_t id, int argc, const char *argv[]) -{ - char filename[MAXIMUM_PATH] = "dynamorio.trace"; - char histmap[MAXIMUM_PATH] = ""; - -#ifdef WINDOWS - dr_enable_console_printing(); -#endif /* WINDOWS */ - - dr_set_client_name("DynamoRIO Sample Client 'qtrace'", - "http://dynamorio.org/issues"); - dr_log(NULL, DR_LOG_ALL, 1, "Client 'qtrace' initializing"); - client_id = id; - - trace_buffer_lock = dr_mutex_create (); - trace_lru_entries_lock = dr_mutex_create (); - if (trace_buffer_lock == NULL || trace_lru_entries_lock == NULL) - { - dr_fprintf (STDERR, "error: could not create mutexes\n"); - dr_exit_process (1); - } - - /* Decode options. */ - for (int i = 1; i < argc; ++i) - { - if (strcmp (argv[i], "-o") == 0) - { - i++; - if (i >= argc) - { - dr_fprintf (STDERR, "error: missing trace output filename\n"); - dr_exit_process (1); - } - - /* Strip 'history,' and 'histmap='. */ - const char *arg = argv[i]; - - if (memcmp (arg, "history,", 8) == 0) - arg = arg + 8; - - if (memcmp (arg, "histmap=", 8) == 0) - { - const char *histmap_start = arg + 8; - const char *histmap_end = histmap_start; - - while (*histmap_end && *histmap_end != ',') - ++histmap_end; - const unsigned histmap_len - = (unsigned) (histmap_end - histmap_start); - - memcpy (histmap, histmap_start, histmap_len); - histmap[histmap_len] = 0; - - if (*histmap_end == 0) - { - dr_fprintf (STDERR, - "error: missing trace output filename\n"); - dr_exit_process (1); - } - arg = histmap_end + 1; - } - else - histmap[0] = 0; - - copy_string (filename, arg, sizeof (filename)); - } - else - { - dr_fprintf (STDERR, "error: invalid option: %s\n", argv[i]); - dr_exit_process (1); - } - } - - /* Intercept all BB translation. */ - dr_register_bb_event(event_basic_block); - -#ifdef LINUX - dr_register_fork_init_event(event_fork_init); -#endif - dr_register_exit_event(event_exit); - - if (histmap[0]) - read_map_file (histmap); - - create_trace_file (filename); - - main_module = dr_get_main_module (); - DR_ASSERT_MSG (main_module != NULL, "cannot get main_module"); -} diff --git a/tools/gnatcov/trace_adapters/dynamorio/qtrace.h b/tools/gnatcov/trace_adapters/dynamorio/qtrace.h deleted file mode 100644 index 0afbb9dc0..000000000 --- a/tools/gnatcov/trace_adapters/dynamorio/qtrace.h +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef QTRACE_H -#define QTRACE_H - -#define EM_386 3 /* Intel 80386 */ -#define EM_X86_64 62 /* AMD x86-64 architecture */ - -/* File header definition. */ -struct trace_header { - char magic[12]; -#define QEMU_TRACE_MAGIC "#QEMU-Traces" - - unsigned char version; -#define QEMU_TRACE_VERSION 1 - - /* File kind. */ - unsigned char kind; -#define QEMU_TRACE_KIND_RAW 0 -#define QEMU_TRACE_KIND_HISTORY 1 -#define QEMU_TRACE_KIND_INFO 2 -#define QEMU_TRACE_KIND_DECISION_MAP 3 -#define QEMU_TRACE_KIND_CONSOLIDATED 248 - - /* Sizeof (target_pc). Indicates struct trace_entry length. */ - unsigned char sizeof_target_pc; - - /* True if host was big endian. All the trace data used the host - endianness. */ - unsigned char big_endian; - - /* Target machine (use ELF number) - always in big endian. */ - unsigned char machine[2]; - - unsigned short _pad; -}; - -/* Header is followed by trace entries. */ - -typedef unsigned long pctype32; - -struct trace_entry32 { - pctype32 pc; - unsigned short size; - unsigned char op; - unsigned char _pad[1]; -}; - -typedef unsigned long long pctype64; - -struct trace_entry64 { - pctype64 pc; - unsigned short size; - unsigned char op; - unsigned char _pad[5]; -}; - -/* _BLOCK means pc .. pc+size-1 was executed. */ -#define TRACE_OP_BLOCK 0x10 /* Block fully executed. */ -#define TRACE_OP_FAULT 0x20 /* Fault at pc. */ -#define TRACE_OP_BR0 0x01 /* Branch */ -#define TRACE_OP_BR1 0x02 /* Fallthrough */ - -#define TRACE_OP_HIST_SET 0x80 - -#ifdef X86_32 -# define ELF_MACHINE EM_386 -typedef struct trace_entry32 trace_entry; -typedef pctype32 pctype; -#elif defined(X86_64) -# define ELF_MACHINE EM_X86_64 -typedef struct trace_entry64 trace_entry; -typedef pctype64 pctype; -#else -# error "unhandled machine" -#endif - -#endif diff --git a/tools/gnatcov/trace_adapters/gdb/gdbtrace-exec_info.adb b/tools/gnatcov/trace_adapters/gdb/gdbtrace-exec_info.adb deleted file mode 100644 index 4ea74933a..000000000 --- a/tools/gnatcov/trace_adapters/gdb/gdbtrace-exec_info.adb +++ /dev/null @@ -1,189 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2010-2022, 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 Elf_Files; use Elf_Files; -with Elf_Arch; use Elf_Arch; -with Elf_Common; use Elf_Common; -with Interfaces; use Interfaces; -with Swaps; use Swaps; - -with Ada.Text_IO; use Ada.Text_IO; -with GNAT.OS_Lib; use GNAT.OS_Lib; - -separate (Gdbtrace) -package body Exec_Info is - - procedure Process_Exec - (Exe_Filename : String; - CBA_Ptr : out Code_Block_Array_Ptr_T; - Exit_Addr : out Unsigned_32) - is - File_Data : Elf_File; - - -- Getting instructions (creating code blocks) from .text section. - -- Should look for all sections marked as containing executable - -- instructions ??? - - Text_Shdr_Idx : Elf_Half; - Text_Shdr_Ptr : Elf_Shdr_Acc; - Text_Section_Len : Elf_Size; - Text_First_Addr : Unsigned_32; - type Insns_Array is array (Positive range <>) of Unsigned_32; - Insns_Ptr : access Insns_Array; - N_Insns : Positive; - - Strtab_Shdr_Idx : Elf_Half; - Strtab_Len : Elf_Size; - Strtab_Ptr : Elf_Strtab_Acc; - Ending_Symbol_Str : constant String := "abort"; - -- Make string above into parameter ??? - - Symtab_Shdr_Idx : Elf_Half; - Symtab_Len : Elf_Size; - type Sym_Array is array (Elf_Size range <>) of Elf_Sym; - Sym_Array_Ptr : access Sym_Array; - N_Syms : Elf_Size; - - Strtab_Idx : Elf_Size; - End_Symbol_Found : Boolean; - End_Symbol_Idx : Elf_Size; - - Op_Code : Unsigned_32; - N_Blocks : Natural; - First_Insn_Idx : Positive; - Block_N : Positive; - Block_Start : Unsigned_32; - - begin - - Open_File (File_Data, Exe_Filename); - if Get_Status (File_Data) /= Status_Ok then - raise Program_Error - with "Error opening executable : " & Exe_Filename & '.'; - end if; - Load_Shdr (File_Data); - -- Opening file and retrieving the section header table are - -- necessary steps for subsequent operations. - - Text_Shdr_Idx := Get_Shdr_By_Name (File_Data, ".text"); - Text_Shdr_Ptr := Get_Shdr (File_Data, Text_Shdr_Idx); - Text_First_Addr := Text_Shdr_Ptr.Sh_Addr; - Text_Section_Len := Text_Shdr_Ptr.Sh_Size; - if Text_Section_Len < 4 then - raise Program_Error with ".text section too small."; - end if; - -- Load .text into an array of insns. - -- Swap is unconditional still (to be fixed) ??? - - -- Need to find all sections containing code ??? - - N_Insns := Positive (Text_Section_Len / 4); - Insns_Ptr := new Insns_Array (1 .. N_Insns); - Load_Section (File_Data, Text_Shdr_Idx, - Insns_Ptr (Insns_Ptr'First)'Address); - for J in Insns_Ptr'Range loop - Insns_Ptr (J) := Swap (Insns_Ptr (J)); - end loop; - - N_Blocks := 0; - for J in Insns_Ptr'Range loop - Op_Code := Shift_Right (Insns_Ptr (J), 26); - if Op_Code = 18 or else Op_Code = 16 or else Op_Code = 19 then - N_Blocks := N_Blocks + 1; - elsif J = Insns_Ptr'Last then - N_Blocks := N_Blocks + 1; - end if; - end loop; - -- Make a pass over instructions to count the number of blocks. - - if N_Blocks = 0 then - raise Program_Error with "No code blocks found."; - end if; - - CBA_Ptr := new Code_Block_Array_T (1 .. N_Blocks); - Block_N := 1; - Block_Start := Text_First_Addr; - First_Insn_Idx := Insns_Ptr'First; - CBA_Ptr (Block_N).Start := Block_Start; - for J in Insns_Ptr'Range loop - Op_Code := Shift_Right (Insns_Ptr (J), 26); - if Op_Code = 18 or else Op_Code = 16 or else Op_Code = 19 then - N_Insns := J - First_Insn_Idx + 1; - CBA_Ptr (Block_N).N_Insns := N_Insns; - exit when J = Insns_Ptr'Last; - Block_N := Block_N + 1; - Block_Start := Block_Start + Unsigned_32 (N_Insns * 4); - First_Insn_Idx := J + 1; - CBA_Ptr (Block_N).Start := Block_Start; - elsif J = Insns_Ptr'Last then - N_Insns := J - First_Insn_Idx + 1; - CBA_Ptr (Block_N).N_Insns := N_Insns; - exit; - end if; - end loop; - -- Allocate and populate CBA; - - Strtab_Shdr_Idx := Get_Shdr_By_Name (File_Data, ".strtab"); - Strtab_Len := Get_Section_Length (File_Data, Strtab_Shdr_Idx); - Strtab_Ptr := - new Elf_Strtab (Elf_Size'First .. Elf_Size'First + Strtab_Len - 1); - Load_Section (File_Data, Strtab_Shdr_Idx, - Strtab_Ptr (Elf_Size'First)'Address); - Symtab_Shdr_Idx := Get_Shdr_By_Name (File_Data, ".symtab"); - Symtab_Len := Get_Section_Length (File_Data, Symtab_Shdr_Idx); - N_Syms := Symtab_Len / 16; - Sym_Array_Ptr := - new Sym_Array (Elf_Size'First .. Elf_Size'First + N_Syms - 1); - Load_Section (File_Data, Symtab_Shdr_Idx, - Sym_Array_Ptr (Elf_Size'First)'Address); - for J in Elf_Size'First .. Elf_Size'First + N_Syms - 1 loop - Sym_Array_Ptr (J) := Get_Sym (File_Data, Sym_Array_Ptr (J)'Address); - end loop; - -- Need the strings table and symbol table to get the - -- address of the symbol which indicates completion. - - End_Symbol_Found := False; - for J in Sym_Array_Ptr'Range loop - Strtab_Idx := Sym_Array_Ptr (J).St_Name; - if Strtab_Idx /= 0 then - for K in Ending_Symbol_Str'Range loop - exit when Strtab_Idx > Strtab_Ptr'Last; - exit when Strtab_Ptr (Strtab_Idx) /= Ending_Symbol_Str (K); - if K = Ending_Symbol_Str'Last then - Strtab_Idx := Strtab_Idx + 1; - if Strtab_Idx <= Strtab_Ptr'Last - and then Strtab_Ptr (Strtab_Idx) = ASCII.NUL - then - End_Symbol_Found := True; - End_Symbol_Idx := J; - end if; - exit; - end if; - Strtab_Idx := Strtab_Idx + 1; - end loop; - end if; - end loop; - if not End_Symbol_Found then - raise Program_Error with "End symbol not found."; - end if; - -- Find the end symbol's address. - - Exit_Addr := Sym_Array_Ptr (End_Symbol_Idx).St_Value; - - end Process_Exec; -end Exec_Info; diff --git a/tools/gnatcov/trace_adapters/gdb/gdbtrace-gdb_mi_io.adb b/tools/gnatcov/trace_adapters/gdb/gdbtrace-gdb_mi_io.adb deleted file mode 100644 index acc1192ac..000000000 --- a/tools/gnatcov/trace_adapters/gdb/gdbtrace-gdb_mi_io.adb +++ /dev/null @@ -1,169 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2010-2022, 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.Text_IO; use Ada.Text_IO; -with Ada.Calendar; use Ada.Calendar; - -separate (Gdbtrace) -package body Gdb_MI_IO is - Initialized : Boolean := False; - Time_Initialized : Time; - To_Gdb, From_Gdb : File_Descriptor; - Logging_On : Boolean; - Log_File : File_Type; - package Duration_IO is new Fixed_IO (Duration); - use Duration_IO; - - procedure Initialize_MI - (Gdb_In : File_Descriptor; - Gdb_Out : File_Descriptor; - Log : Boolean := False) is - begin - To_Gdb := Gdb_In; - From_Gdb := Gdb_Out; - Logging_On := Log; - if Logging_On then - Create (Log_File, Name => "rgdb.log"); - end if; - Initialized := True; - Time_Initialized := Clock; - end Initialize_MI; - - function Get_MI_Output_Record return MI_Record_T is - Return_Record : MI_Record_T; - L : Natural; - begin - -- Not considering 'token's for now ??? - - L := Get_Gdb_Line; - Return_Record.Length := L; - if L < 1 then - Return_Record.Record_Type := Unknown_Record; - elsif Gdb_Output_Buffer (1) = '~' then - Return_Record.Record_Type := Console_Stream_Output; - elsif Gdb_Output_Buffer (1) = '@' then - Return_Record.Record_Type := Target_Stream_Output; - elsif Gdb_Output_Buffer (1) = '&' then - Return_Record.Record_Type := Log_Stream_Output; - elsif Gdb_Output_Buffer (1) = '*' then - Return_Record.Record_Type := Exec_Async_Record; - elsif Gdb_Output_Buffer (1) = '+' then - Return_Record.Record_Type := Status_Async_Record; - elsif Gdb_Output_Buffer (1) = '=' then - Return_Record.Record_Type := Notify_Async_Record; - elsif Gdb_Output_Buffer (1) = '^' then - Return_Record.Record_Type := Result_Record; - if L >= 5 and then Gdb_Output_Buffer (2 .. 5) = "done" then - Return_Record.Result_Class := Done_Result; - elsif L >= 8 and then Gdb_Output_Buffer (2 .. 8) = "running" then - Return_Record.Result_Class := Running_Result; - elsif L >= 10 and then Gdb_Output_Buffer (2 .. 10) = "connected" then - Return_Record.Result_Class := Connected_Result; - elsif L >= 6 and then Gdb_Output_Buffer (2 .. 6) = "error" then - Return_Record.Result_Class := Error_Result; - elsif L >= 5 and then Gdb_Output_Buffer (2 .. 5) = "exit" then - Return_Record.Result_Class := Exit_Result; - else - Return_Record.Record_Type := Error_Record; - Return_Record.Almost_Type := Result_Record; - end if; - elsif Gdb_Output_Buffer (1) = '(' then - if L = 6 and Gdb_Output_Buffer (2 .. 6) = "gdb) " then - Return_Record.Record_Type := Prompt_Record; - else - Return_Record.Record_Type := Unknown_Record; - end if; - end if; - return Return_Record; - end Get_MI_Output_Record; - - function Get_Gdb_Line return Natural is - B_Idx : Natural; - N_Read : Integer; - C : Character; - procedure Log_Gdb_Output; - - procedure Log_Gdb_Output is - S : constant String := Gdb_Output_Buffer (1 .. B_Idx); - begin - if Logging_On then - Put (Log_File, Clock - Time_Initialized, Fore => 5, Aft => 2); - Put (Log_File, " <-- "); - Put (Log_File, S); - New_Line (Log_File); - end if; - end Log_Gdb_Output; - - begin - if not Initialized then - Put_Line (Standard_Error, - "Gdb_Line_IO not initialized when Gdb_Get_Line called."); - OS_Exit (1); - end if; - - B_Idx := 1; - loop - N_Read := Read (From_Gdb, Gdb_Output_Buffer (B_Idx)'Address, 1); - if N_Read /= 1 then - Put_Line (Standard_Error, "Error reading gdb output."); - OS_Exit (1); - end if; - if Gdb_Output_Buffer (B_Idx) = ASCII.LF then - B_Idx := B_Idx - 1; - Log_Gdb_Output; - return B_Idx; - end if; - if B_Idx = Gdb_Output_Buffer'Last then - Log_Gdb_Output; - Put_Line (Standard_Error, "Gdb_Output_Buffer overflow"); - loop - N_Read := Read (From_Gdb, C'Address, 1); - if N_Read /= 1 then - Put_Line (Standard_Error, "Error reading gdb output."); - OS_Exit (1); - end if; - exit when C = ASCII.LF; - end loop; - return B_Idx; - else - B_Idx := B_Idx + 1; - end if; - end loop; - end Get_Gdb_Line; - - procedure Put_Gdb_Line (S : String) is - C : Character := ASCII.LF; - N : Integer; - pragma Unreferenced (N); - begin - if not Initialized then - Put_Line (Standard_Error, - "Gdb_Line_IO not initialized when Put_Gdb__Line called."); - OS_Exit (1); - end if; - if Logging_On then - Put (Log_File, Clock - Time_Initialized, Fore => 5, Aft => 2); - Put (Log_File, " --> "); - Put (Log_File, S); - New_Line (Log_File); - end if; - N := Write (To_Gdb, S'Address, S'Length); - N := Write (To_Gdb, C'Address, 1); - end Put_Gdb_Line; - -end Gdb_MI_IO; diff --git a/tools/gnatcov/trace_adapters/gdb/gdbtrace.adb b/tools/gnatcov/trace_adapters/gdb/gdbtrace.adb deleted file mode 100644 index daa3030ad..000000000 --- a/tools/gnatcov/trace_adapters/gdb/gdbtrace.adb +++ /dev/null @@ -1,627 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2010-2022, 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 GNAT.Expect; use GNAT.Expect; -with Ada.Text_IO; use Ada.Text_IO; -with Ada.Command_Line; use Ada.Command_Line; -with GNAT.OS_Lib; use GNAT.OS_Lib; -with Interfaces; use Interfaces; -with Ada.Calendar; use Ada.Calendar; -with Ada.Unchecked_Deallocation; - -with Traces_Dbase; use Traces_Dbase; -with Traces; use Traces; -with Qemu_Traces; use Qemu_Traces; -with Traces_Files; use Traces_Files; - --- Gdbtrace implements a gdb-based mechanism for creating trace information --- from execution of a program on a remote target. --- --- It has been developed with execution on a bare board, and loading/ --- execution via gdb's remote serial protocol in mind. It is PowerPC --- target specific, and deals only with code that follows the branch --- instructions in the executable (no interrupts or exceptions are --- handled). --- --- The design in influenced by the great overhead of running the target --- programs under gdb control, when the outcome of every branch needs --- to be detected and recorded at run time. --- --- The program preprocesses the target executable, and creates an --- array of structures which represent a block of code with only one --- branch instrucion in it, at the end of the block. The basic loop --- involved in running the program under gdb control consists of --- finding which block the PC is in, setting a temporary HW breakpoint --- in that branch, run to the break, single step, record which way --- the branch went, and repeat. - -procedure Gdbtrace is - - Executable_Name_Ptr : String_Access; - Remote_Target_Name_Ptr : String_Access; - Spawn_Timeout : Duration; - - procedure Process_Command_Line; - -- Process_Command_Line reads the gdbtrace command line and sets - -- the values of the variables above. It causes the program to - -- exit with an error code if the command line is invalid. For - -- the Usage string as well as default values of optional parameters - -- see the body of the procedure. - - Failure_Exit_Code : constant Integer := 1; - - procedure Process_Command_Line is - Usage : constant String - := "usage: gdbtrace [--spawn-timeout=Secs] remote-targ-name prog-name"; - -- The first required argument is the string that should complete - -- the "target remote" command to gdb. The second is the filename - -- of the target executable file. - - Current_Arg : Positive; - S : String_Access; - - function Prefix_Cmp - (Pref : String; S_Ptr : String_Access) return Boolean; - -- Returns True iff the String pointed to by Ptr is a prefix - -- of S. - function Prefix_Cmp - (Pref : String; S_Ptr : String_Access) return Boolean is - begin - if Pref'Length > S_Ptr'Length then - return False; - end if; - return Pref = S_Ptr (S_Ptr'First .. S_Ptr'First + Pref'Length - 1); - end Prefix_Cmp; - - begin - Spawn_Timeout := 12.0; - - if Argument_Count < 2 then - Put_Line (Standard_Error, "Too few arguments."); - Put_Line (Standard_Error, Usage); - OS_Exit (Failure_Exit_Code); - end if; - - Current_Arg := 1; - loop - if Current_Arg + 1 > Argument_Count then - Put_Line (Standard_Error, "Too few arguments."); - Put_Line (Standard_Error, Usage); - OS_Exit (Failure_Exit_Code); - end if; - S := new String'(Argument (Current_Arg)); - if Prefix_Cmp ("--", S) then - if Prefix_Cmp ("--spawn-timeout=", S) then - null; - else - Put_Line (Standard_Error, "Invalid argument: " & S.all); - Put_Line (Standard_Error, Usage); - OS_Exit (Failure_Exit_Code); - end if; - else - exit; - end if; - Free (S); - Current_Arg := Current_Arg + 1; - end loop; - Remote_Target_Name_Ptr := S; - Executable_Name_Ptr := new String'(Argument (Current_Arg + 1)); - end Process_Command_Line; - - -- The Exec_Info package contains the data structures for representing - -- blocks of code, and the procedure for extracting that information - -- from a target exectuable file. - - package Exec_Info is - - type Code_Block_T is record - Start : Unsigned_32; - N_Insns : Positive; - end record; - -- The type Code_Block_T is used to represent a blocksof code in - -- the target program being executed. A block of consists of - -- a sequence of zero or more non-branch instructions, followed - -- by a single branch. The member Start contains the starting - -- address of the block, and N_Insns contains a count of number - -- of instructions in the block (including the branch). - - type Code_Block_Array_T is array (Positive range <>) of Code_Block_T; - type Code_Block_Array_Ptr_T is access Code_Block_Array_T; - - procedure Process_Exec - (Exe_Filename : String; - CBA_Ptr : out Code_Block_Array_Ptr_T; - Exit_Addr : out Unsigned_32); - -- Before the program is loaded and run, it is processed by the - -- Process_Exec procedure, resulting in an array of Code_Block_T - -- elements, which together cover all of the executable code in - -- the program. - -- - -- The address which tells gdbtrace to stop execution (i.e., when - -- the PC contains this address after a branch) is also returned. - -- Currently, this is hardcoded as the value of the symbol 'abort' ??? - -- - -- Process_Exec will raise Program_Error for error conditions including - -- inability to process executable file, no code blocks found, and - -- the designated stop symbol not found. - end Exec_Info; - package body Exec_Info is separate; - use Exec_Info; - - CBA : Code_Block_Array_Ptr_T; - PC_Val : Unsigned_32; - First_Addr : Unsigned_32; - Last_Addr : Unsigned_32; - -- CBA contains the code block array calculated by Process_Exec. - -- The other variables are used in the main loop of the program - -- to keep track of the PC and identify the code block that contains - -- the PC at any time. - - -- The capacity to keep track of some data about the history of - -- the execution of the target program.... may or may not be - -- needed depending up the functionality of the QEMU trace - -- interface, which is not understood at this point. ??? ... - -- or different data than that represented by the declarations - -- below, may be needed. - - type Block_History_T is record - Branch_Was_Taken_Start : Unsigned_32; - Branch_Not_Taken_Start : Unsigned_32; - end record; - - type Block_History_Array_T is array (Positive range <>) of Block_History_T; - type Block_History_Array_Ptr_T is access Block_History_Array_T; - Block_History : Block_History_Array_Ptr_T; - pragma Unreferenced (Block_History); - -- The variable Block_History points to an array of Block_History_T - -- records, and parallels the Code_Block_Array caluculated and - -- returned by Exec_Info.Process_Exec. During the execution of the - -- target program, each Block_History_T element in the array, keeps - -- track of data about instructions in the corresponding Code_Block. - -- - -- When the value in Branch_Was_Taken_Start component is outside the - -- range of addresses of the corresponding block, then the target program - -- has not executed instructions within the block that resulted in - -- the terminating branch instruction being taken. If the value - -- of Branch_Was_Taken_Start is an address in the block, then at - -- some time during program execution, the block was entered at - -- Branch_Was_Taken_Start, the instructions up to the branch at the - -- end of the block were executed and the branch was taken. The value - -- is the lowest address in the block for which that happened. - -- Branch_Not_Taken_Start has the same function except it tracks - -- executions within the block that result in the final branch - -- not being taken. - - Tbase : Traces_Base; - Trace_Filename_Ptr : String_Access; - Pc_B, Pc_E : Pc_Type := 0; - Tfile : Trace_File_Type; - At_Start : Boolean; - Op : Unsigned_8; - - -- A package for using the MI interface to interact with gdb could - -- be useful. Currently (until further research), this small package - -- is defined here to meet gdbtrace's requirements for interacting - -- with gdb using the MI interface. - - package Gdb_MI_IO is - Gdb_Output_Buffer : String (1 .. 4096); - -- Make into something that grows as needed ??? - - type MI_Record_Type_T is (Result_Record, Exec_Async_Record, - Status_Async_Record, Notify_Async_Record, - Console_Stream_Output, Target_Stream_Output, - Log_Stream_Output, Prompt_Record, - Unknown_Record, Error_Record); - -- MI_Record_Type represent the types of records returned from - -- gdb via the MI interface. - -- - -- Result_Record records start with the '^' character followed by - -- the name of the result-class. - -- Exec_Async_Record records start with a '*', followed by an - -- async class name. - -- Status_Async_Record records start with a '+', followed by an - -- async class name. - -- Notify_Async_Record records start with a '=', followed by an - -- async class name. - -- Records consisting of "(gdb) " are of type Prompt_Record; - -- When a record's type is not recognized it is of type Unknown_Reocrd; - -- When a record looks like a known type (e.g. by the first character), - -- but is malformed (e.g. unknown result class) it is classified - -- as an Error_Record. - - type Result_Class_T is (Done_Result, Running_Result, Connected_Result, - Error_Result, Exit_Result); - - type Async_Class_T is (Stopped_Async, Running_Async, Other_Async); - pragma Unreferenced (Stopped_Async); - pragma Unreferenced (Running_Async); - pragma Unreferenced (Other_Async); - - type MI_Record_T is record - Record_Type : MI_Record_Type_T; - Almost_Type : MI_Record_Type_T; - Result_Class : Result_Class_T; - Async_Class : Async_Class_T; - Length : Natural; - end record; - -- Get_MI_Output_Record (below) returns values of this type. It - -- contains information about a gdb mi output record. - -- - Almost_Type is filled in when Record_Type is Error_Record, - -- It contains that type indicated by the first charaacter (before - -- a problem was found). - -- - Result_Class is filled in when Record_Type is Result_Record. - -- - Async_Class isn't yet used. - -- - Length is the length of the record (which can be found in - -- Gdb_Output_Buffer after Get_MI_Output_Record returns). - - procedure Initialize_MI - (Gdb_In : File_Descriptor; - Gdb_Out : File_Descriptor; - Log : Boolean := False); - - function Get_MI_Output_Record return MI_Record_T; - - function Get_Gdb_Line return Natural; - -- Gets the string output by GDB MI, placing it in Gdb_Output_Buffer. - -- This is used by Get_MI_Output_Rcord (so maybe should be made - -- internal???). - - procedure Put_Gdb_Line (S : String); - -- Sends a gdb command over MI. - end Gdb_MI_IO; - package body Gdb_MI_IO is separate; - use Gdb_MI_IO; - - MI_Output : MI_Record_T; - - GDB_Process : Process_Descriptor; - -- The Process_Descriptor type comes from GNAT.Expect. The Expect - -- package is only used to spawn gdb and retrieving the file - -- descriptors for communicating with gdb. - -- Handy interface for that functionality without all the - -- stuff of Expect??? - - procedure Command_Gdb (Command : String; T : Duration; Err_Msg : String); - -- Send Command to gdb. Set the watchdog timer to timeout after T, - -- changing any previous deadline. If T is 0, then the watchdog timer - -- is turned off. The error message output by the watchdog timer is - -- given by Err_Msg. - - function Get_Hval (S : String) return Unsigned_32; - -- Used to read a hex value from gdb output. - - procedure Addr_Str_In_C (Addr : Unsigned_32; S : in out String); - -- Create a string representation of Addr in a format that can - -- be passed to gdb. - - C_Addr : String (1 .. 10); - - function Get_Hval (S : String) return Unsigned_32 is - V : Unsigned_32 := 0; - HD : Unsigned_32; - J : Natural; - - Bad_Hex_Char : constant Unsigned_32 := 16; - - function Hex_Digit (C : Character) return Unsigned_32; - -- Returns a value in 0 .. 15 unless C is not a valid - -- hex digit, in which case Bad_Hex_Char is returned; - - function Hex_Digit (C : Character) return Unsigned_32 is - begin - if C in '0' .. '9' then - return Unsigned_32 (Character'Pos (C) - Character'Pos ('0')); - elsif C in 'a' .. 'f' then - return Unsigned_32 (Character'Pos (C) - Character'Pos ('a') + 10); - elsif C in 'A' .. 'F' then - return Unsigned_32 (Character'Pos (C) - Character'Pos ('A') + 10); - end if; - return Bad_Hex_Char; - end Hex_Digit; - begin - J := S'First; - loop - exit when J > S'Last; - HD := Hex_Digit (S (J)); - exit when HD = Bad_Hex_Char; - V := V * 16 + HD; - J := J + 1; - end loop; - return V; - end Get_Hval; - - procedure Addr_Str_In_C (Addr : Unsigned_32; S : in out String) is - J : Positive; - A : Unsigned_32 := Addr; - Digs : constant String := ("0123456789abcdef"); - begin - J := S'Last; - loop - if A = 0 then - while J > S'First + 1 loop - S (J) := '0'; - J := J - 1; - end loop; - S (S'First + 1) := 'x'; - S (S'First) := '0'; - exit; - end if; - S (J) := Digs (Integer (A mod 16) + 1); - A := A / 16; - J := J - 1; - end loop; - end Addr_Str_In_C; - - Stop_Addr : Unsigned_32; - - task Timeout; - -- This is a simple watchdog timer. At regular intervals it checks - -- to see if it is supposed to be turned on. If so, it compares - -- Clock time to a timeout time, and if the timeout time has been - -- passed, it prints out an error message and force the program - -- to exit with an error code. - - type Timeout_Err_Msg is access String; - type Wd_Info is record - T : Time; - M : Timeout_Err_Msg; - On : Boolean; - end record; - -- An object of this type contains the data used by Timeout task. - -- It is shared between Timeout and other tasks via the protected - -- type below. - - protected Wd_Timer is - procedure Set_Timeout (D : Duration; E : String); - procedure Clear_Timeout; - function Get_Timeout return Wd_Info; - private - Timer : Wd_Info := (Clock, null, False); - end Wd_Timer; - protected body Wd_Timer is - procedure Set_Timeout (D : Duration; E : String) is - procedure Free is new Ada.Unchecked_Deallocation - (String, Timeout_Err_Msg); - begin - if Timer.M = null then - if E'Length /= 0 then - Timer.M := new String'(E); - end if; - elsif Timer.M.all /= E then - Free (Timer.M); - if E'Length /= 0 then - Timer.M := new String'(E); - end if; - end if; - - Timer.T := Clock + D; - Timer.On := True; - end Set_Timeout; - - procedure Clear_Timeout is - begin - Timer.On := False; - end Clear_Timeout; - - function Get_Timeout return Wd_Info is - begin - return Timer; - end Get_Timeout; - end Wd_Timer; - - task body Timeout is - T : Wd_Info; - begin - loop - delay 2.0; - T := Wd_Timer.Get_Timeout; - if T.On and then Clock > T.T then - Put_Line (T.M.all); - OS_Exit (1); - end if; - end loop; - end Timeout; - - procedure Command_Gdb (Command : String; T : Duration; Err_Msg : String) is - begin - Put_Gdb_Line (Command); - if T = 0.0 then - Wd_Timer.Clear_Timeout; - else - Wd_Timer.Set_Timeout (T, Err_Msg); - end if; - end Command_Gdb; - -begin - - Process_Command_Line; - - Trace_Filename_Ptr := new String'(Executable_Name_Ptr.all & ".trace"); - Init_Base (Tbase); - - Process_Exec (Executable_Name_Ptr.all, CBA, Stop_Addr); - - Non_Blocking_Spawn - (GDB_Process, - "powerpc-elf-gdb", - (1 => new String'("--quiet"), - 2 => new String'("--interpreter=mi"), - 3 => Executable_Name_Ptr)); - - Initialize_MI (Get_Input_Fd (GDB_Process), - Get_Output_Fd (GDB_Process), - True); - - Wd_Timer.Set_Timeout - (Spawn_Timeout, "Timeout waiting for gdb prompt following spawn."); - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type /= Console_Stream_Output; - end loop; - if MI_Output.Record_Type /= Prompt_Record then - Put_Line (Standard_Error, - "Unexpected output after spawn."); - OS_Exit (Failure_Exit_Code); - end if; - - Command_Gdb ("-target-select remote " & Remote_Target_Name_Ptr.all, 10.0, - "Timeout following ""-target-select remote"""); - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Prompt_Record; - end loop; - - Command_Gdb ("-target-download", 25.0, - "Timeout waiting for target download"); - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Result_Record and then - MI_Output.Result_Class = Done_Result; - end loop; - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Prompt_Record; - end loop; - - Command_Gdb ("-var-create Program_Counter * $pc", 8.0, - "Timeout creating Program_Counter variable."); - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Result_Record and then - MI_Output.Result_Class = Done_Result; - end loop; - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Prompt_Record; - end loop; - - At_Start := True; - loop - Command_Gdb ("-var-evaluate-expression Program_Counter", 8.0, - "Timeout Evaluating Program_Counter"); - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Result_Record and then - MI_Output.Result_Class = Done_Result; - end loop; - if Gdb_Output_Buffer (6 .. 15) /= ",value=""0x" then - Put_Line (Standard_Error, - "Unexpected output after -var_evaluate_expression."); - OS_Exit (1); - end if; - PC_Val := Get_Hval (Gdb_Output_Buffer (16 .. 24)); - if not At_Start then - if PC_Val = Unsigned_32 (Pc_E) + 1 then - Op := Trace_Op_Br1 or Trace_Op_Block; - else - Op := Trace_Op_Br0 or Trace_Op_Block; - end if; - Add_Entry (Tbase, Pc_B, Pc_E, Op); - else - At_Start := False; - end if; - - exit when PC_Val = Stop_Addr; - - for CB_Index in CBA'Range loop - First_Addr := CBA (CB_Index).Start; - Last_Addr - := First_Addr + Unsigned_32 (CBA (CB_Index).N_Insns - 1) * 4; - exit when PC_Val >= First_Addr and then PC_Val <= Last_Addr; - if CB_Index = CBA'Last then - Put_Line (Standard_Error, "Couldn't find code block."); - OS_Exit (1); - end if; - end loop; - Pc_B := Pc_Type (PC_Val); - Pc_E := Pc_Type (Last_Addr + 3); - - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Prompt_Record; - end loop; - - if Last_Addr > PC_Val then - Addr_Str_In_C (Last_Addr, C_Addr); - Command_Gdb ("-break-insert -t -h *" & C_Addr, 8.0, - "Timeout inserting breakpoint."); - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Result_Record and then - MI_Output.Result_Class = Done_Result; - end loop; - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Prompt_Record; - end loop; - Command_Gdb ("-exec-continue", 30.0, - "Timeout after continue."); - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Result_Record and then - MI_Output.Result_Class = Running_Result; - end loop; - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Prompt_Record; - end loop; - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Exec_Async_Record and then - Gdb_Output_Buffer (2 .. 8) = "stopped"; - end loop; - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Prompt_Record; - end loop; - end if; - - Command_Gdb ("-exec-step-instruction", 10.0, - "Timeout following Step Instruction."); - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Result_Record and then - MI_Output.Result_Class = Running_Result; - end loop; - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Exec_Async_Record and then - Gdb_Output_Buffer (2 .. 8) = "stopped"; - end loop; - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Prompt_Record; - end loop; - Command_Gdb ("-var-update Program_Counter", 10.0, - "Timeout updating Program_Counter"); - loop - MI_Output := Get_MI_Output_Record; - exit when MI_Output.Record_Type = Prompt_Record; - end loop; - end loop; - Wd_Timer.Clear_Timeout; - - Put_Gdb_Line ("-gdb-exit"); - Traces.Machine := 20; - Create_Trace_File (Flat, Tfile); - Append_Info (Tfile, Exec_File_Name, Executable_Name_Ptr.all); - - Write_Trace_File (Trace_Filename_Ptr.all, Tfile, Tbase); - -end Gdbtrace; diff --git a/tools/gnatcov/trace_adapters/valgrind/Makefile b/tools/gnatcov/trace_adapters/valgrind/Makefile deleted file mode 100644 index 471fe44a7..000000000 --- a/tools/gnatcov/trace_adapters/valgrind/Makefile +++ /dev/null @@ -1,81 +0,0 @@ -include ../../architecture.mk -include ../../host.mk - -######### -# Build # -######### - -VALGRIND_INCLUDE=$(VALGRIND_PREFIX)/include/valgrind - -# Figure out the place from which we need to fetch the valgrind -# libraries to craft our coverage tool. We rely on this expanding into -# a single dir. We use of a wildcard expansion to find either -# prefix/lib or prefix/lib64, then need to watch out for a possible -# prefix/libexec. - -VALGRIND_LIBDIRS=$(wildcard $(VALGRIND_PREFIX)/lib*/valgrind) -VALGRIND_LIBS=$(filter-out %/libexec/valgrind, $(VALGRIND_LIBDIRS)) - -CPP_FLAGS=-I. -I$(VALGRIND_INCLUDE) \ - -DVGA_$(VALGRIND_ARCH)=1 -DVGO_linux=1 \ - -DVGP_$(VALGRIND_ARCH)_linux=1 \ - -DVGPV_$(VALGRIND_ARCH)_linux_vanilla=1 - -# TODO:where did the -mpreferred-stack-boundary=2 option come from? - -# Some versions of valgrind (observed with 3.16) fail loading the tool -# when it has a .note.gnu.property section, with an error like -# -# valgrind: mmap(0x400000, 12288) failed in UME with error 22 -# -# -Wa,-mx86-used-note=no is intended to prevent the production of -# such .note sections. - -CFLAGS=-O2 -g \ - -fno-strict-aliasing -fno-builtin -fno-stack-protector \ - -Wa,-mx86-used-note=no \ - -Wall -Wmissing-prototypes -Wshadow -Wpointer-arith -Wstrict-prototypes \ - -Wmissing-declarations -Wno-format-zero-length \ - -Wno-long-long -Wno-pointer-sign - -LDFLAGS=-static -nodefaultlibs -nostartfiles -u _start -Wl,--build-id=none - -LIBS=$(VALGRIND_LIBS)/libcoregrind-$(VALGRIND_ARCH)-linux.a \ - $(VALGRIND_LIBS)/libvex-$(VALGRIND_ARCH)-linux.a -lgcc - -COVERAGE_TOOL=coverage-$(VALGRIND_ARCH)-linux - -all: $(COVERAGE_TOOL) - -%.o: %.c - gcc $(CPP_FLAGS) $(CFLAGS) -c $< -o $@ - -COVERAGE_OBJECTS=cov_traces.o cov_main.o - -cov_traces.o: cov_traces.c cov_traces.h -cov_main.o: cov_main.c cov_traces.h - -# The address 0x38000000 is the valt_load_address value from valgrind build. -# This value should be changed for Darwin (0x138000000). -$(COVERAGE_TOOL): $(COVERAGE_OBJECTS) - gcc $(CFLAGS) -o $@ $(COVERAGE_OBJECTS) \ - $(LDFLAGS) -Wl,-Ttext=0x38000000 $(LIBS) - -################ -# Installation # -################ - -.PHONY: install - -install: - $(MKDIR) $(VALGRIND_TOOL_INSTALL_DIR) - cp -p $(COVERAGE_TOOL) $(VALGRIND_TOOL_INSTALL_DIR) - -########### -# Cleanup # -########### - -.PHONY: clean - -clean: - rm -f $(COVERAGE_TOOL) $(COVERAGE_OBJECTS) diff --git a/tools/gnatcov/trace_adapters/valgrind/README.md b/tools/gnatcov/trace_adapters/valgrind/README.md deleted file mode 100644 index 87e0d0a08..000000000 --- a/tools/gnatcov/trace_adapters/valgrind/README.md +++ /dev/null @@ -1,22 +0,0 @@ -This directory holds the Valgrind trace adapter for GNATcoverage. - -This adapter consists in pieces allowing the construction of an instrumented -version of Valgrind, able to produce (upon request) execution traces suitable -for analysis by `gnatcov coverage`. - -In order to build it: - -* Make sure you have Valgrind 3.7.0 installed (with headers): - - ``` - /bin/valgrind - /lib/valgrind/ - /include/valgrind/ - ``` - -* Build and install: - - ```shell - $ make - $ sudo make install - ``` diff --git a/tools/gnatcov/trace_adapters/valgrind/cov_main.c b/tools/gnatcov/trace_adapters/valgrind/cov_main.c deleted file mode 100644 index cf11877a9..000000000 --- a/tools/gnatcov/trace_adapters/valgrind/cov_main.c +++ /dev/null @@ -1,401 +0,0 @@ - -/*--------------------------------------------------------------------*/ -/*--- Coverage: Execution traces for GNATcoverage. cov_main.c ---*/ -/*--------------------------------------------------------------------*/ - -/* - Copyright (C) 2013-2021, AdaCore - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY 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 - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307, USA. - - The GNU General Public License is contained in the file COPYING. -*/ - -#include "valgrind.h" /* __VALGRIND_MINOR__ */ - -#include "pub_tool_basics.h" -#include "pub_tool_tooliface.h" -#include "pub_tool_libcprint.h" /* VG_(printf) */ -#include "pub_tool_libcassert.h" /* tl_assert */ -#include "pub_tool_machine.h" /* VG_(fnptr_to_fnentry) */ -#include "pub_tool_options.h" /* command line options */ -#include "pub_tool_libcbase.h" /* VG_(strlen) */ - -#include "libvex_basictypes.h" -#include "libvex.h" - -#include "cov_traces.h" - -/* filenames */ -static const UChar *clo_cov_exec_file=NULL; - -//#define DEBUG -static VG_REGPARM(2) void per_branch(struct trace_entry *te, Word taken) -{ - if (tracefile_history_for_te(te) && (te->op & 0x3) != 0) { - /* If we save history for this "te" and there's already a branch state - * is already set, create a new "te". - */ - te = new_trace_entry(te->pc, te->size); - te->op |= TRACE_OP_HIST_SET; - } - - te->op |= TRACE_OP_BLOCK | (taken ? TRACE_OP_BR0 : TRACE_OP_BR1); - -#ifdef DEBUG - VG_(printf)("Branch (0x%08x:%u) cond: %d\n", (unsigned int)te->pc, - (unsigned int)te->size, (int)taken); -#endif -} - -/* From libvex pre 3.11. */ - -#if VEX_HOST_WORDSIZE == 8 - static inline void* ULong_to_Ptr ( ULong n ) { - return (void*)n; - } -#elif VEX_HOST_WORDSIZE == 4 - static inline void* ULong_to_Ptr ( ULong n ) { - UInt w = (UInt)n; - return (void*)w; - } -#endif - -/* From Callgrind */ - -static Addr IRConst2Addr(IRConst* con) -{ - Addr addr; - - if (sizeof(Addr) == 4) { - tl_assert(con->tag == Ico_U32); - addr = con->Ico.U32; - } else if (sizeof(Addr) == 8) { - tl_assert(con->tag == Ico_U64); - addr = con->Ico.U64; - } else { - VG_(tool_panic)("Coverage: invalid Addr type"); - } - - return addr; -} - -static IRSB* cov_instrument (VgCallbackClosure* closure, - IRSB* sbIn, - const VexGuestLayout* vgl, - const VexGuestExtents* vge, - const VexArchInfo* vai, - IRType gWordTy, - IRType hWordTy) -{ - Int i; - IRStmt* st; - IRSB *sbOut; - Addr64 origAddr; - IRDirty *di; - IRExpr **argv, *arg1, *arg2; - Int regparms; - uint16_t te_size = 0; - struct trace_entry *te; - Addr instrAddr, jumpDst; - UInt instrLen; - Bool toNextInstr = False; - Bool has_branch = False; - - -#ifdef DEBUG - VG_(printf)("Coverage: BEFORE\n"); - for (i = 0; i < sbIn->stmts_used; i++) { - st = sbIn->stmts[i]; - if (st) { - ppIRStmt(st); - VG_(printf)("\n"); - } - } -#endif - - /* Set up SB */ - sbOut = deepCopyIRSBExceptStmts(sbIn); - - /* Find first IMark */ - for (i = 0; (i < sbIn->stmts_used) && (sbIn->stmts[i]->tag != Ist_IMark); - i++) { - continue; - } - - /* Get the first statement */ - tl_assert(sbIn->stmts_used > 0); - st = sbIn->stmts[i]; - - /* Double check we are at a Mark statement */ - tl_assert(Ist_IMark == st->tag); - - /* Save address of the first instruction */ - origAddr = st->Ist.IMark.addr; - - /* Find last IMark */ - for (; i < sbIn->stmts_used; i++) { - if (sbIn->stmts[i] != NULL && sbIn->stmts[i]->tag == Ist_IMark) { - st = sbIn->stmts[i]; - } - } - - /* Double check we are at a Mark statement */ - tl_assert(Ist_IMark == st->tag); - - /* Compute BB size */ - /* META: instruction mark. Marks the start of the statements - that represent a single machine instruction (the end of - those statements is marked by the next IMark or the end of - the IRSB). Contains the address and length of the - instruction. - - It also contains a delta value. The delta must be - subtracted from a guest program counter value before - attempting to establish, by comparison with the address - and length values, whether or not that program counter - value refers to this instruction. For x86, amd64, ppc32, - ppc64 and arm, the delta value is zero. For Thumb - instructions, the delta value is one. This is because, on - Thumb, guest PC values (guest_R15T) are encoded using the - top 31 bits of the instruction address and a 1 in the lsb; - hence they appear to be (numerically) 1 past the start of - the instruction they refer to. IOW, guest_R15T on ARM - holds a standard ARM interworking address. - - ppIRStmt output: ------ IMark(, , ) ------, - eg. ------ IMark(0x4000792, 5, 0) ------, - */ - - /* I don't know how to get the size of the super block, so I compute - * it from the address of the last instruction (i.e. the last - * IMark) and its size. - */ - te_size = st->Ist.IMark.addr + st->Ist.IMark.len - - st->Ist.IMark.delta - origAddr; - - - /* Save addr and len of the last IMark for branch inversion - * heuristic. - */ - instrAddr = (Addr)ULong_to_Ptr(st->Ist.IMark.addr); - instrLen = st->Ist.IMark.len; - -#ifdef DEBUG - VG_(printf)("\nStart SB addr: %llx size:%d...\n", origAddr, te_size); -#endif - - /* Get trace entry for this BB */ - te = get_trace_entry(origAddr, te_size); - tl_assert(te != NULL); - - for (i = 0; i < sbIn->stmts_used; i++) { - st = sbIn->stmts[i]; - if (!st) { - continue; - } - - switch (st->tag) { - case Ist_Exit: { - Bool guest_exit, inverted = False; - - /* Add instrumentation only if this is a branch in guest code */ - guest_exit = (st->Ist.Exit.jk == Ijk_Boring) || - (st->Ist.Exit.jk == Ijk_Call) || - (st->Ist.Exit.jk == Ijk_Ret); - - if (guest_exit) { - - if (has_branch) { -#ifdef DEBUG - int index; - VG_(printf)("Coverage: Not a basic block\n"); - for (index = 0; index < sbIn->stmts_used; index++) { - st = sbIn->stmts[index]; - if (st) { - ppIRStmt(st); - VG_(printf)("\n"); - } - } -#endif - - VG_(tool_panic)("Coverage: More than one branch in this" - " block (not a basic block)"); - } - - /* FIXME: This case has to be fixed as coverage analysis - * needs basic block, we just ignore it for now. - */ - /* has_branch = True; */ - - /* Stuff to widen the guard expression to a host word, so - * we can pass it to the branch coverage function easily. - */ - IRType tyW = hWordTy; - IROp widen = tyW==Ity_I32 ? Iop_1Uto32 : Iop_1Uto64; - IROp opXOR = tyW==Ity_I32 ? Iop_Xor32 : Iop_Xor64; - IRTemp guard1 = newIRTemp(sbOut->tyenv, Ity_I1); - IRTemp guardW = newIRTemp(sbOut->tyenv, tyW); - IRTemp guard = newIRTemp(sbOut->tyenv, tyW); - IRExpr* one = tyW==Ity_I32 ? IRExpr_Const(IRConst_U32(1)) - : IRExpr_Const(IRConst_U64(1)); - - /* Widen the guard expression. */ - addStmtToIRSB(sbOut, - IRStmt_WrTmp(guard1, st->Ist.Exit.guard )); - addStmtToIRSB(sbOut, - IRStmt_WrTmp(guardW, - IRExpr_Unop(widen, - IRExpr_RdTmp(guard1)))); - - - /* VEX code generation sometimes inverts conditional branches. - * Coverage has to correct inversions. The heuristic is the - * following: - * Inversion is assumed if the branch jumps to the address of - * the next guest instruction in memory. - */ - - /* We assume that there is only one jump in each SB */ - jumpDst = IRConst2Addr(st->Ist.Exit.dst); - toNextInstr = (jumpDst == instrAddr + instrLen); - - /* if the last instructions of BB conditionally jumps to next - * instruction (= first instruction of next BB in memory), this - * is inverted by VEX. - */ - inverted = toNextInstr; - - /* If the exit is inverted, invert the sense of the guard. */ - addStmtToIRSB( - sbOut, - IRStmt_WrTmp( - guard, - inverted ? IRExpr_Binop(opXOR, IRExpr_RdTmp(guardW), one) - : IRExpr_RdTmp(guardW))); - - regparms = 2; - arg1 = mkIRExpr_HWord( (HWord)te); - arg2 = IRExpr_RdTmp(guard); - argv = mkIRExprVec_2(arg1, arg2); - - di = unsafeIRDirty_0_N(regparms, "per_branch", - VG_(fnptr_to_fnentry)(&per_branch), - argv); - - /* Insert our call */ - addStmtToIRSB(sbOut, IRStmt_Dirty(di)); - } - break; - } - - default: - break; - } - - /* Always keep the original statement */ - addStmtToIRSB(sbOut, st); - - } - - /* If the block is instrumented we will at least execute it */ - te->op |= TRACE_OP_BLOCK; - -#ifdef DEBUG - VG_(printf)("Coverage: AFTER\n"); - for (i = 0; i < sbOut->stmts_used; i++) { - st = sbOut->stmts[i]; - if (st) { - ppIRStmt(st); - VG_(printf)("\n"); - } - } - VG_(printf)("Coverage: END\n"); -#endif - return sbOut; -} - -/*--------------------------------------------------------------------*/ -/*--- Setup ---*/ -/*--------------------------------------------------------------------*/ - -static void cov_post_clo_init(void) -{ - /* Try a closer approximation of basic blocks */ - -#if __VALGRIND_MINOR__ < 16 - /* --vex-guest-chase-thresh=0 */ - VG_(clo_vex_control).guest_chase_thresh = 0; -#else - /* --vex-guest-chase=no */ - VG_(clo_vex_control).guest_chase = False; -#endif - - trace_init(clo_cov_exec_file); -} - -static Bool cov_process_cmd_line_option(const HChar* arg) -{ - if VG_STR_CLO (arg, "--cov-exec-file", clo_cov_exec_file) {} - else { - return False; - } - - return True; -} - -static void cov_print_usage(void) -{ - VG_(printf)( -" --cov-exec-file= filename for execution trace file (and options)\n" - ); -} - -static void cov_print_debug_usage(void) -{ - VG_(printf)(" (none)\n"); -} - -static void cov_fini(Int exitcode) -{ - trace_cleanup(); -} - -static void cov_pre_clo_init(void) -{ - VG_(details_name) ("Coverage"); - VG_(details_version) ("1.0.0w"); - VG_(details_description) ("Execution traces for GNATcoverage"); - VG_(details_copyright_author)("Copyright (C) 2012, AdaCore"); - VG_(details_bug_reports_to) ("report@adacore.com"); - - VG_(details_avg_translation_sizeB) ( 275 ); - - VG_(basic_tool_funcs) (cov_post_clo_init, - cov_instrument, - cov_fini); - - VG_(needs_command_line_options)(cov_process_cmd_line_option, - cov_print_usage, - cov_print_debug_usage); - /* No needs, no core events to track */ -} - -VG_DETERMINE_INTERFACE_VERSION(cov_pre_clo_init) - -/*--------------------------------------------------------------------*/ -/*--- end ---*/ -/*--------------------------------------------------------------------*/ diff --git a/tools/gnatcov/trace_adapters/valgrind/cov_traces.c b/tools/gnatcov/trace_adapters/valgrind/cov_traces.c deleted file mode 100644 index 9ce83abfd..000000000 --- a/tools/gnatcov/trace_adapters/valgrind/cov_traces.c +++ /dev/null @@ -1,483 +0,0 @@ - -/*--------------------------------------------------------------------*/ -/*--- Coverage: Execution traces for GNATcoverage. cov_traces.c ---*/ -/*--------------------------------------------------------------------*/ - -/* - Copyright (C) 2013, AdaCore - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY 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 - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307, USA. - - The GNU General Public License is contained in the file COPYING. -*/ - -#include -#include - -#include "pub_tool_basics.h" -#include "pub_tool_tooliface.h" -#include "pub_tool_vki.h" /* vki_stat */ -#include "pub_tool_libcfile.h" /* VG_(write) */ -#include "pub_tool_libcbase.h" /* VG_(memcmp)() */ -#include "pub_tool_libcprint.h" /* VG_(messages) */ -#include "pub_tool_libcassert.h" /* VG_(exit) */ -#include "pub_tool_mallocfree.h" /* plain_free */ -#include "cov_traces.h" - -/* Legal values for e_machine (architecture). */ - -#define EM_NONE 0 /* No machine */ -#define EM_M32 1 /* AT&T WE 32100 */ -#define EM_SPARC 2 /* SUN SPARC */ -#define EM_386 3 /* Intel 80386 */ -#define EM_68K 4 /* Motorola m68k family */ -#define EM_88K 5 /* Motorola m88k family */ -#define EM_486 6 /* Intel 80486 */ -#define EM_860 7 /* Intel 80860 */ -#define EM_MIPS 8 /* MIPS R3000 big-endian */ -#define EM_S370 9 /* Amdahl */ -#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */ -#define EM_RS6000 11 /* RS6000 */ -#define EM_X86_64 62 /* AMD x86-64 architecture */ - -#if defined(VGP_x86_linux) -# define ELF_MACHINE EM_386 -#elif defined(VGP_amd64_linux) -# define ELF_MACHINE EM_X86_64 -#elif defined(VGP_ppc32_linux) -# define ELF_MACHINE EM_PPC -#elif defined(VGP_ppc64_linux) -# define ELF_MACHINE EM_PPC64 -#elif defined(VGP_arm_linux) -# define ELF_MACHINE EM_ARM -#elif defined(VGP_s390x_linux) -# define ELF_MACHINE EM_S390 -#else -# error Unknown platform -#endif - -#define bswap_16(x) \ -({ \ - uint16_t __x = (x); \ - ((uint16_t)( \ - (((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \ - (((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \ - }) - -#define bswap_32(x) \ -({ \ - uint32_t __x = (x); \ - ((uint32_t)( \ - (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \ - (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \ - (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \ - (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \ - }) - -#define bswap_64(x) \ -({ \ - uint64_t __x = (x); \ - ((uint64_t)( \ - (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \ - (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \ - (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \ - (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \ - (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \ - (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \ - (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \ - (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \ - }) - - -static Int tracefile; - -struct trace_entry *te_list_head = NULL; -struct trace_entry *te_list_tail = NULL; - -int tracefile_enabled; -static int tracefile_nobuf; -static int tracefile_history; - -static int nbr_histmap_entries; -static HWord *histmap_entries; - -int tracefile_history_for_te(struct trace_entry *te) -{ - if (!(te->op & TRACE_OP_HIST_CACHE)) { - tracefile_history_for_te_search(te); - } - -#ifdef DEBUG - if (te->op & TRACE_OP_HIST_SET) { - VG_(message)(Vg_FailMsg, "At pc:0x%08x size:0x%08x Hist_Set\n", - te->pc, te->size); - } -#endif - - return te->op & TRACE_OP_HIST_SET; -} - -void tracefile_history_for_te_search(struct trace_entry *te) -{ - te->op |= TRACE_OP_HIST_CACHE; - - if (tracefile_history) { - te->op |= TRACE_OP_HIST_SET; - return; - } - - if (nbr_histmap_entries) { - int low = 0; - int high = nbr_histmap_entries - 1; - - while (low <= high) { - int mid = low + (high - low) / 2; - HWord pc = histmap_entries[mid]; - - if (pc >= te->pc && pc < te->pc + te->size) { - te->op |= TRACE_OP_HIST_SET; - return; - } - if (te->pc < pc) { - high = mid - 1; - } else { - low = mid + 1; - } - } - } -} - -static void trace_flush(void) -{ - struct trace_entry32 e32; - struct trace_entry64 e64; - struct trace_entry *ret; - - unsigned int ent_sz; - void *ent; - - if (sizeof(HWord) == 4) { - ent_sz = sizeof(e32); - ent = &e32; - } else { - ent_sz = sizeof(e64); - ent = &e64; - } - - for (ret = te_list_head; ret != NULL; ret = ret->next) { - /* Write trace entries with non-null op */ - if (ret->op != 0) { - if (sizeof (HWord) == 4) { - e32.pc = ret->pc; - e32.size = ret->size; - e32.op = ret->op; - } else { - e64.pc = ret->pc; - e64.size = ret->size; - e64.op = ret->op; - } - VG_(write)(tracefile, ent, ent_sz); - } - } -} - -void trace_cleanup(void) -{ - if (tracefile_enabled) { - trace_flush(); - VG_(close)(tracefile); - } -} - -static void read_map_file(const char *filename) -{ - Int histfile; - struct trace_header hdr; - off_t length; - int ent_sz; - int i; - int my_endian; - - histfile = VG_(fd_open)(filename, VKI_O_RDONLY, - VKI_S_IRUSR|VKI_S_IWUSR|VKI_S_IRGRP|VKI_S_IWGRP); - if (histfile < 0) { - VG_(message)(Vg_FailMsg, "cannot open histmap file '%s': %m\n", - filename); - VG_(exit)(1); - } - if (VG_(read)(histfile, &hdr, sizeof(hdr)) != sizeof(hdr)) { - VG_(message)(Vg_FailMsg, - "cannot read trace header for histmap file '%s'\n", - filename); - VG_(exit)(1); - } - if (VG_(memcmp)(hdr.magic, QEMU_TRACE_MAGIC, sizeof(hdr.magic)) != 0 - || hdr.version != QEMU_TRACE_VERSION - || hdr.kind != QEMU_TRACE_KIND_DECISION_MAP - || hdr.sizeof_target_pc != sizeof(HWord) - || (hdr.big_endian != 0 && hdr.big_endian != 1) - || hdr.machine[0] != (ELF_MACHINE >> 8) - || hdr.machine[1] != (ELF_MACHINE & 0xff) - || hdr._pad != 0) { - VG_(message)(Vg_FailMsg, "bad header for histmap file '%s'\n", - filename); - VG_(exit)(1); - } - - /* Get number of entries. */ - if ((length = VG_(lseek)(histfile, 0, VKI_SEEK_END)) == -1) { - VG_(message)(Vg_FailMsg, "cannot get size of histmap file '%s'\n", - filename); - - VG_(exit)(1); - } - - if (VG_(lseek)(histfile, sizeof(hdr), VKI_SEEK_SET) == -1) { - VG_(message)(Vg_FailMsg, "cannot set seek of histmap file '%s'\n", - filename); - - VG_(exit)(1); - } - - length -= sizeof(hdr); - if (sizeof(HWord) == 4) { - ent_sz = sizeof(struct trace_entry32); - } else { - ent_sz = sizeof(struct trace_entry64); - } - - if ((length % ent_sz) != 0) { - VG_(message)(Vg_FailMsg, "bad length of histmap file '%s'\n", filename); - VG_(exit)(1); - } - nbr_histmap_entries = length / ent_sz; - if (nbr_histmap_entries) { - histmap_entries = VG_(malloc)("cov_histmap_entries", - nbr_histmap_entries * sizeof(HWord)); - } - -#ifdef WORDS_BIGENDIAN - my_endian = 1; -#else - my_endian = 0; -#endif - - if (sizeof(HWord) == 4) { - for (i = 0; i < nbr_histmap_entries; i++) { - struct trace_entry32 ent; - - if (VG_(read)(histfile, &ent, sizeof(ent)) != sizeof(ent)) { - VG_(message)(Vg_FailMsg, - "cannot read histmap file entry from '%s'\n", - filename); - VG_(exit)(1); - } - if (my_endian != hdr.big_endian) { - ent.pc = bswap_32(ent.pc); - } - if (i > 0 && ent.pc < histmap_entries[i - 1]) { - VG_(message)(Vg_FailMsg, - "unordered entry #%d in histmap file '%s'\n", - i, filename); - VG_(exit)(1); - } - - histmap_entries[i] = ent.pc; -#ifdef DEBUG - VG_(message)(Vg_DebugMsg, "histmap_entries[%d] = 0x%08x;\n", - i, ent.pc); -#endif - - } - } else { - for (i = 0; i < nbr_histmap_entries; i++) { - struct trace_entry64 ent; - - if (VG_(read)(histfile, &ent, sizeof(ent)) != sizeof(ent)) { - VG_(message)(Vg_FailMsg, - "cannot read histmap file entry from '%s'\n", - filename); - VG_(exit)(1); - } - if (my_endian != hdr.big_endian) { - ent.pc = bswap_64(ent.pc); - } - if (i > 0 && ent.pc < histmap_entries[i - 1]) { - VG_(message)(Vg_FailMsg, - "unordered entry #%d in histmap file '%s'\n", - i, filename); - VG_(exit)(1); - } - - histmap_entries[i] = ent.pc; -#ifdef DEBUG - VG_(message)(Vg_DebugMsg, "histmap_entries[%d] = 0x%016llx;\n", - i, (unsigned int)ent.pc); -#endif - } - } - VG_(close)(histfile); -} - -void trace_init(const char *cov_exec_arg) -{ - static struct trace_header hdr = { QEMU_TRACE_MAGIC }; - static int opt_trace_seen; - int noappend = 0; - int kind = QEMU_TRACE_KIND_RAW; - char **s_array = NULL; - char *cov_exec_file = NULL; - int s_index = 0; - - - if (cov_exec_arg == NULL) { - /* No arg: trace file disabled */ - return; - } - - if (opt_trace_seen) { - VG_(message)(Vg_FailMsg, "option --cov-exec-file already specified\n"); - VG_(exit)(1); - } - opt_trace_seen = 1; - - /* Parse coverage argument */ - s_array = split_trace_arg(cov_exec_arg); - - for (s_index = 0; s_array[s_index] != NULL; s_index++) { - if (VG_(strncmp)(s_array[s_index], "nobuf", 6) == 0) { - tracefile_nobuf = 1; - } else if (VG_(strncmp)(s_array[s_index], "history", 8) == 0) { - tracefile_history = 1; - kind = QEMU_TRACE_KIND_HISTORY; - } else if (VG_(strncmp)(s_array[s_index], "noappend", 9) == 0) { - noappend = 1; - } else if (VG_(strncmp)(s_array[s_index], "histmap=", 8) == 0) { - read_map_file(s_array[s_index] + 8); - kind = QEMU_TRACE_KIND_HISTORY; - } else { - cov_exec_file = s_array[s_index]; - } - } - - tracefile = VG_(fd_open)(cov_exec_file, - VKI_O_WRONLY | VKI_O_CREAT | (noappend ? 0 : VKI_O_APPEND), - VKI_S_IRUSR|VKI_S_IWUSR|VKI_S_IRGRP|VKI_S_IWGRP); - - - if (tracefile < 0) { - VG_(message)(Vg_FailMsg, "can't open file '%s': %m\n", cov_exec_file); - VG_(exit)(1); - } - - hdr.version = QEMU_TRACE_VERSION; - hdr.sizeof_target_pc = sizeof(HWord); - hdr.kind = kind; -#ifdef WORDS_BIGENDIAN - hdr.big_endian = 1; -#else - hdr.big_endian = 0; -#endif - hdr.machine[0] = ELF_MACHINE >> 8; - hdr.machine[1] = ELF_MACHINE & 0xff; - if (VG_(write)(tracefile, &hdr, sizeof(hdr)) != sizeof(hdr)) { - VG_(message)(Vg_FailMsg, "can't write trace header on %s\n", - cov_exec_file); - VG_(exit)(1); - } - - tracefile_enabled = 1; -} - -struct trace_entry *new_trace_entry(HWord pc, uint16_t size) -{ - struct trace_entry *ret; - - ret = VG_(malloc)("cov_malloc", sizeof(struct trace_entry)); - ret->pc = pc; - ret->size = size; - ret->op = 0; - ret->next = NULL; - - /* Insert to tail to keep execution order */ - if (te_list_head == NULL) { - /* First element */ - te_list_head = ret; - te_list_tail = ret; - } else { - te_list_tail->next = ret; - te_list_tail = ret; - } - return ret; -} - -struct trace_entry *get_trace_entry(HWord pc, uint16_t size) -{ - struct trace_entry *ret; - - for (ret = te_list_head; ret != NULL; ret = ret->next) { - if (ret != NULL && ret->pc == pc && ret->size == size) { - return ret; - } - } - - return new_trace_entry(pc, size); -} - -char **split_trace_arg(const char *trace) -{ - char **s_array = NULL; - int s_nbr = 0; - int start = 0; - int end = 0; - - for (; 1; end++) { - if (trace[end] == ',' || trace[end] == '\0') { - /* split here */ - - if (start == end) { - /* empty string: skip */ - continue; - } - - /* Make room for a new sub-string */ - s_nbr++; - s_array = VG_(realloc)("cov_malloc", s_array, - sizeof(char *) * s_nbr); - - /* Allocate and copy the new sub-string */ - s_array[s_nbr - 1] = VG_(malloc)("cov_malloc", - sizeof(char) * (end - start + 1)); - VG_(memmove)(s_array[s_nbr - 1], &trace[start], end - start); - /* Add the trailing \0 to make valid null-terminated string */ - s_array[s_nbr - 1][end - start] = '\0'; - - /* New start point after the end of the current sub-string */ - start = end + 1; - } - if (trace[end] == '\0') { - break; - } - } - - /* Null terminated array */ - s_nbr++; - s_array = VG_(realloc)("cov_malloc", s_array, - sizeof(char *) * s_nbr); - s_array[s_nbr - 1] = NULL; - - return s_array; -} diff --git a/tools/gnatcov/trace_adapters/valgrind/cov_traces.h b/tools/gnatcov/trace_adapters/valgrind/cov_traces.h deleted file mode 100644 index 851d792f4..000000000 --- a/tools/gnatcov/trace_adapters/valgrind/cov_traces.h +++ /dev/null @@ -1,142 +0,0 @@ - -/*--------------------------------------------------------------------*/ -/*--- Coverage: Execution traces for GNATcoverage. cov_traces.h ---*/ -/*--------------------------------------------------------------------*/ - -/* - Copyright (C) 2013, AdaCore - - This program is free software; you can redistribute it and/or - modify it under the terms of the GNU General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY 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 - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307, USA. - - The GNU General Public License is contained in the file COPYING. -*/ - - -#ifndef COV_TRACES_H -#define COV_TRACES_H - -#include "libvex_basictypes.h" - -#define DEBUG_TRACE - -/* - * Qemu trace file format. - * It requires proper definition for uintXX_t where XX is 8, 16, 32 and 64 - * and HWord (32 or 64 bits). - */ - -typedef UChar uint8_t; -typedef UShort uint16_t; -typedef UInt uint32_t; -typedef ULong uint64_t; - -/* File header definition. */ -struct trace_header { - char magic[12]; -#define QEMU_TRACE_MAGIC "#QEMU-Traces" - - uint8_t version; -#define QEMU_TRACE_VERSION 1 - - /* File kind. */ - uint8_t kind; -#define QEMU_TRACE_KIND_RAW 0 -#define QEMU_TRACE_KIND_HISTORY 1 -#define QEMU_TRACE_KIND_INFO 2 -#define QEMU_TRACE_KIND_DECISION_MAP 3 -#define QEMU_TRACE_KIND_CONSOLIDATED 248 - - /* Sizeof (target_pc). Indicates struct trace_entry length. */ - uint8_t sizeof_target_pc; - - /* True if host was big endian. All the trace data used the host - endianness. */ - uint8_t big_endian; - - /* Target machine (use ELF number) - always in big endian. */ - uint8_t machine[2]; - - uint16_t _pad; -}; - -struct trace_entry; - -/* Header is followed by trace entries. */ - -struct trace_entry32 { - uint32_t pc; - uint16_t size; - uint8_t op; - uint8_t _pad[1]; -}; - -struct trace_entry64 { - uint64_t pc; - uint16_t size; - uint8_t op; - uint8_t _pad[5]; -}; - -/* - * Trace operations for RAW and HISTORY - */ - -/* _BLOCK means pc .. pc+size-1 was executed. */ -#define TRACE_OP_BLOCK 0x10 /* Block fully executed. */ -#define TRACE_OP_FAULT 0x20 /* Fault at pc. */ -#define TRACE_OP_BR0 0x01 /* Branch */ -#define TRACE_OP_BR1 0x02 /* Fallthrough */ - -/* Only used internally */ -#define TRACE_OP_HIST_SET 0x100 /* Set in the map file. */ -#define TRACE_OP_HIST_CACHE 0x200 /* Has already been searched. */ - -/* trace entry list */ -struct trace_entry { - HWord pc; - uint16_t size; - uint16_t op; - struct trace_entry *next; - struct trace_entry *prev; -}; - -extern int tracefile_enabled; - -void trace_init(const char *cov_exec_file); -void trace_cleanup(void); - -/* True when full history is desired, either for all instructions or for the - * conditional jump instruction at the end of the tb. - */ -int tracefile_history_for_te(struct trace_entry *te); -void tracefile_history_for_te_search(struct trace_entry *te); - -/* Insert a new trace_entry even if there's already one with the same pc and - * size. This is require for branch history. - */ -struct trace_entry *new_trace_entry(HWord pc, uint16_t size); - -/* Try to find a trace_entry with the same pc and size or allocate a new one if - * needed. - */ -struct trace_entry *get_trace_entry(HWord pc, uint16_t size); - -/* Takes a string containing coma separated options and returns a - * null-terminated array of strings. - */ -char **split_trace_arg(const char *trace); - -#endif /* COV_TRACES_H */ From 7fd251e5549f477aaa328933c55b1f94978d567d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 19 Jun 2023 14:14:33 +0000 Subject: [PATCH 0331/1483] Revert "Merge branch 'eyraud/squashed_parallelized' into 'master'" This reverts merge request !178 --- .gitignore | 1 - .../GPR/ByCmdLine/ProjectSets/test.py | 4 +- testsuite/SUITE/srctracelib.py | 23 +- .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 644 -> 0 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2020 -> 0 bytes .../gen/arm-elf-linux/gcvrt-bpkg.ads | 74 - .../gen/arm-elf-linux/gcvrt-foo.ads | 25 - .../gen/arm-elf-linux/gcvrt-ppkg.ads | 35 - ....ads => gnatcov_rts-buffers-bb_main_1.ads} | 23 +- ....ads => gnatcov_rts-buffers-bb_main_2.ads} | 23 +- .../gnatcov_rts-buffers-bb_pkg.ads | 41 + .../gnatcov_rts-buffers-bs_pkg.ads | 41 + ....adb => gnatcov_rts-buffers-db_main_1.adb} | 8 +- ....ads => gnatcov_rts-buffers-db_main_1.ads} | 6 +- ....adb => gnatcov_rts-buffers-db_main_2.adb} | 8 +- ....ads => gnatcov_rts-buffers-db_main_2.ads} | 6 +- .../gnatcov_rts-buffers-lists-foo.ads | 25 + ....ads => gnatcov_rts-buffers-pb_main_1.ads} | 14 +- ....ads => gnatcov_rts-buffers-pb_main_2.ads} | 14 +- .../gnatcov_rts-buffers-pb_pkg.ads | 19 + .../gnatcov_rts-buffers-ps_pkg.ads | 19 + .../gen/arm-elf-linux/main_1.adb | 7 +- .../gen/arm-elf-linux/main_1.sid | Bin 387 -> 387 bytes .../gen/arm-elf-linux/main_2.adb | 7 +- .../gen/arm-elf-linux/main_2.sid | Bin 387 -> 387 bytes .../gen/arm-elf-linux/pkg.adb | 10 +- .../gen/arm-elf-linux/pkg.ads | 2 +- .../gen/arm-elf-linux/pkg.sid | Bin 1046 -> 1046 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1906 -> 1878 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1916 -> 1888 bytes .../U204-026-arch-mix/gen/main_1.srctrace | Bin 416 -> 416 bytes .../U204-026-arch-mix/gen/main_2.srctrace | Bin 388 -> 388 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 1943 -> 1942 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 1879 -> 1851 bytes .../gen/x86_64-windows/gcvrt-bpkg.ads | 74 - .../gen/x86_64-windows/gcvrt-db_main_1.ads | 13 - .../gen/x86_64-windows/gcvrt-db_main_2.ads | 13 - .../gen/x86_64-windows/gcvrt-foo.ads | 25 - .../gen/x86_64-windows/gcvrt-ppkg.ads | 35 - ....ads => gnatcov_rts-buffers-bb_main_1.ads} | 23 +- ....ads => gnatcov_rts-buffers-bb_main_2.ads} | 23 +- .../gnatcov_rts-buffers-bb_pkg.ads | 41 + .../gnatcov_rts-buffers-bs_pkg.ads | 41 + ....adb => gnatcov_rts-buffers-db_main_1.adb} | 13 +- .../gnatcov_rts-buffers-db_main_1.ads | 6 + ....adb => gnatcov_rts-buffers-db_main_2.adb} | 13 +- .../gnatcov_rts-buffers-db_main_2.ads | 6 + .../gnatcov_rts-buffers-lists-foo.ads | 25 + ....ads => gnatcov_rts-buffers-pb_main_1.ads} | 14 +- ....ads => gnatcov_rts-buffers-pb_main_2.ads} | 14 +- .../gnatcov_rts-buffers-pb_pkg.ads | 19 + .../gnatcov_rts-buffers-ps_pkg.ads | 19 + .../gen/x86_64-windows/main_1.adb | 13 +- .../gen/x86_64-windows/main_1.sid | Bin 389 -> 389 bytes .../gen/x86_64-windows/main_2.adb | 13 +- .../gen/x86_64-windows/main_2.sid | Bin 389 -> 389 bytes .../gen/x86_64-windows/pkg.adb | 10 +- .../gen/x86_64-windows/pkg.ads | 2 +- .../gen/x86_64-windows/pkg.sid | Bin 1050 -> 1050 bytes .../tests/U204-026-arch-mix/main_2-out.txt | 11 - .../tests/excluded_unit_imported_prj/test.py | 2 +- testsuite/tests/instr-cov/ext_gpr/test.py | 14 +- .../tests/instr-cov/gpr-complex/main_body.gpr | 5 - .../tests/instr-cov/gpr-complex/main_sep.gpr | 5 - .../instr-cov/gpr-complex/main_simple.gpr | 6 - .../tests/instr-cov/gpr-complex/main_spec.gpr | 5 - .../instr-cov/gpr-complex/src-lib/lib.gpr | 4 - .../instr-cov/gpr-complex/src-lib/pkg-bar.adb | 4 - .../instr-cov/gpr-complex/src-lib/pkg.adb | 9 - .../instr-cov/gpr-complex/src-lib/pkg.ads | 4 - .../gpr-complex/src-main_body/main.adb | 7 - .../gpr-complex/src-main_body/pkg.adb | 11 - .../gpr-complex/src-main_sep/main.adb | 7 - .../gpr-complex/src-main_sep/pkg-bar.adb | 6 - .../gpr-complex/src-main_simple/main.adb | 7 - .../gpr-complex/src-main_spec/main.adb | 8 - .../gpr-complex/src-main_spec/pkg.ads | 5 - .../tests/instr-cov/gpr-complex/test.opt | 1 - testsuite/tests/instr-cov/gpr-complex/test.py | 121 -- .../instr-cov/manual-dump/covdump__cov.adb | 4 +- testsuite/tests/instr-cov/orphan-unit/test.py | 2 +- tools/gnatcov/Makefile | 6 +- tools/gnatcov/command_line.ads | 235 +--- tools/gnatcov/coverage-source.adb | 116 +- tools/gnatcov/coverage-source.ads | 7 +- tools/gnatcov/files_table.adb | 8 +- tools/gnatcov/files_table.ads | 37 +- tools/gnatcov/gnatcov_bits_specific.adb | 127 +- tools/gnatcov/inputs.adb | 16 - tools/gnatcov/inputs.ads | 4 - tools/gnatcov/instrument-ada_unit.adb | 1096 ++++++--------- tools/gnatcov/instrument-ada_unit.ads | 103 +- tools/gnatcov/instrument-ada_unit__stub.adb | 5 +- tools/gnatcov/instrument-ada_unit__stub.ads | 20 +- .../gnatcov/instrument-ada_unit_provider.adb | 20 - .../gnatcov/instrument-ada_unit_provider.ads | 10 +- tools/gnatcov/instrument-c.adb | 958 +++++++++---- tools/gnatcov/instrument-c.ads | 116 +- tools/gnatcov/instrument-c__stub.adb | 6 +- tools/gnatcov/instrument-c__stub.ads | 11 +- tools/gnatcov/instrument-c_utils.ads | 7 +- tools/gnatcov/instrument-checkpoints.adb | 4 +- tools/gnatcov/instrument-common.adb | 602 ++++---- tools/gnatcov/instrument-common.ads | 368 ++--- tools/gnatcov/instrument-config.adb | 50 - tools/gnatcov/instrument-input_traces.adb | 28 +- tools/gnatcov/instrument-input_traces.ads | 2 +- tools/gnatcov/instrument-main.adb | 41 - tools/gnatcov/instrument-projects.adb | 1225 ----------------- tools/gnatcov/instrument-source.adb | 66 - tools/gnatcov/instrument.adb | 838 +++++++++-- tools/gnatcov/instrument.ads | 124 +- tools/gnatcov/project.adb | 384 +++--- tools/gnatcov/project.ads | 46 +- tools/gnatcov/rts/gcvrt.ads | 23 - tools/gnatcov/rts/gnatcov_rts-buffers.ads | 1 + tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 4 + .../gnatcov/rts/gnatcov_rts_c-traces-output.c | 6 +- tools/gnatcov/rts/gnatcov_rts_c-traces.h | 7 +- tools/gnatcov/strings.adb | 41 +- tools/gnatcov/strings.ads | 12 +- tools/gnatcov/subprocesses.adb | 38 +- tools/gnatcov/switches.adb | 41 - tools/gnatcov/switches.ads | 14 - tools/gnatcov/traces_source.ads | 26 +- 125 files changed, 3488 insertions(+), 4549 deletions(-) delete mode 100644 testsuite/tests/U204-026-arch-mix/bin-main_1.trace delete mode 100644 testsuite/tests/U204-026-arch-mix/bin-main_2.trace delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bpkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-bmain_1.ads => gnatcov_rts-buffers-bb_main_1.ads} (79%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-bmain_2.ads => gnatcov_rts-buffers-bb_main_2.ads} (79%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-db_main_1.adb => gnatcov_rts-buffers-db_main_1.adb} (64%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-db_main_1.ads => gnatcov_rts-buffers-db_main_1.ads} (60%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-db_main_2.adb => gnatcov_rts-buffers-db_main_2.adb} (64%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-db_main_2.ads => gnatcov_rts-buffers-db_main_2.ads} (60%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-pmain_1.ads => gnatcov_rts-buffers-pb_main_1.ads} (66%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-pmain_2.ads => gnatcov_rts-buffers-pb_main_2.ads} (66%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bpkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-bmain_1.ads => gnatcov_rts-buffers-bb_main_1.ads} (77%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-bmain_2.ads => gnatcov_rts-buffers-bb_main_2.ads} (77%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-db_main_1.adb => gnatcov_rts-buffers-db_main_1.adb} (55%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-db_main_2.adb => gnatcov_rts-buffers-db_main_2.adb} (55%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-pmain_1.ads => gnatcov_rts-buffers-pb_main_1.ads} (63%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-pmain_2.ads => gnatcov_rts-buffers-pb_main_2.ads} (63%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/main_2-out.txt delete mode 100644 testsuite/tests/instr-cov/gpr-complex/main_body.gpr delete mode 100644 testsuite/tests/instr-cov/gpr-complex/main_sep.gpr delete mode 100644 testsuite/tests/instr-cov/gpr-complex/main_simple.gpr delete mode 100644 testsuite/tests/instr-cov/gpr-complex/main_spec.gpr delete mode 100644 testsuite/tests/instr-cov/gpr-complex/src-lib/lib.gpr delete mode 100644 testsuite/tests/instr-cov/gpr-complex/src-lib/pkg-bar.adb delete mode 100644 testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.adb delete mode 100644 testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.ads delete mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_body/main.adb delete mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_body/pkg.adb delete mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_sep/main.adb delete mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb delete mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_simple/main.adb delete mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_spec/main.adb delete mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_spec/pkg.ads delete mode 100644 testsuite/tests/instr-cov/gpr-complex/test.opt delete mode 100644 testsuite/tests/instr-cov/gpr-complex/test.py delete mode 100644 tools/gnatcov/instrument-config.adb delete mode 100644 tools/gnatcov/instrument-main.adb delete mode 100644 tools/gnatcov/instrument-projects.adb delete mode 100644 tools/gnatcov/instrument-source.adb delete mode 100644 tools/gnatcov/rts/gcvrt.ads diff --git a/.gitignore b/.gitignore index f65e4e605..1ddf255c3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ obj -obj-* lib *.pyc *.pkl diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py index 729910a2c..2ec633226 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py @@ -19,7 +19,7 @@ recurse=False, xreports=['boolops']) -# -Pgen --projects=boolops.gpr --projects=intops.gpr, not recursive +# -Pgen --projects=boolops.gpr --projects=intops.gpr, not recusrive # expect boolops & intops related reports check( @@ -28,7 +28,7 @@ recurse=False, xreports=['boolops', 'intops']) -# -Pgen --projects=boolops.gpr --projects=counters.gpr, not recursive +# -Pgen --projects=boolops.gpr --projects=counters.gpr, not recusrive # expect boolops & counters related reports check( diff --git a/testsuite/SUITE/srctracelib.py b/testsuite/SUITE/srctracelib.py index 195fe36de..a43943212 100755 --- a/testsuite/SUITE/srctracelib.py +++ b/testsuite/SUITE/srctracelib.py @@ -32,6 +32,7 @@ trace_entry_header_struct = Struct( 'trace entry header', ('unit_name_length', 'I'), + ('project_name_length', 'I'), ('stmt_bit_count', 'I'), ('dc_bit_count', 'I'), ('mcdc_bit_count', 'I'), @@ -40,7 +41,7 @@ ('bit_buffer_encoding', 'B'), ('fingerprint', '20B'), ('bit_maps_fingerprint', '20B'), - ('padding', '5B'), + ('padding', 'B'), ) @@ -195,6 +196,7 @@ def format_buffer(b): ''.join('{:02x}'.format(b) for b in e.fingerprint), ''.join('{:02x}'.format(b) for b in e.bit_maps_fingerprint) )) + print(' Project: {}'.format(e.project_name)) print(' Stmt buffer: {}'.format(format_buffer(e.stmt_buffer))) print(' Dc buffer: {}'.format(format_buffer(e.dc_buffer))) print(' MCDC buffer: {}'.format(format_buffer(e.mcdc_buffer))) @@ -274,11 +276,13 @@ class TraceEntry(object): BIT_BUFFER_ENCODING_CODES = { value: key for key, value in BIT_BUFFER_ENCODING_NAMES.items()} - def __init__(self, language, unit_part, unit_name, fingerprint, - bit_maps_fingerprint, stmt_buffer, dc_buffer, mcdc_buffer): + def __init__(self, language, unit_part, unit_name, project_name, + fingerprint, bit_maps_fingerprint, stmt_buffer, dc_buffer, + mcdc_buffer): self.language = language self.unit_part = unit_part self.unit_name = unit_name + self.project_name = project_name self.fingerprint = fingerprint self.bit_maps_fingerprint = bit_maps_fingerprint self.stmt_buffer = stmt_buffer @@ -299,7 +303,7 @@ def read(cls, fp, trace_file, big_endian): language = cls.LANGUAGE_NAMES[header['language']] - if header['padding'] != (0, 0, 0, 0, 0): + if header['padding'] != 0: raise ValueError('Invalid padding: {}' .format(header['padding'])) @@ -310,6 +314,11 @@ def read(cls, fp, trace_file, big_endian): unit_name = read_aligned( fp, header['unit_name_length'], trace_file.alignment) + with fp.label_context('project name'): + project_name = (read_aligned(fp, header['project_name_length'], + trace_file.alignment) + or "") + with fp.label_context('stmt buffer'): stmt_buffer = TraceBuffer.read( fp, trace_file, bit_buffer_encoding, @@ -323,7 +332,7 @@ def read(cls, fp, trace_file, big_endian): fp, trace_file, bit_buffer_encoding, header['mcdc_bit_count']) - return cls(language, unit_part, unit_name, + return cls(language, unit_part, unit_name, project_name, header['fingerprint'], header['bit_maps_fingerprint'], stmt_buffer, dc_buffer, mcdc_buffer) @@ -331,6 +340,7 @@ def write(self, fp, big_endian, alignment): """Write this trace info entry to the `fp` file.""" trace_entry_header_struct.write(fp, { 'unit_name_length': len(self.unit_name), + 'project_name_length': len(self.project_name), 'stmt_bit_count': len(self.stmt_buffer.bits), 'dc_bit_count': len(self.dc_buffer.bits), 'mcdc_bit_count': len(self.mcdc_buffer.bits), @@ -340,10 +350,11 @@ def write(self, fp, big_endian, alignment): self.BIT_BUFFER_ENCODING_CODES['lsb_first_bytes'], 'fingerprint': self.fingerprint, 'bit_maps_fingerprint': self.bit_maps_fingerprint, - 'padding': (0, 0, 0, 0, 0), + 'padding': 0, }, big_endian=big_endian) write_aligned(fp, self.unit_name, alignment) + write_aligned(fp, self.project_name, alignment) self.stmt_buffer.write(fp, alignment) self.dc_buffer.write(fp, alignment) diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace deleted file mode 100644 index 1b7f06c4baf411743211d5529cc59e75e7336f5e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 644 zcmYk&y-LGS6u|M5TH8ylVq=vKQi7HuLa|Ac7CT9)P6{ejocvZ){6ZIT6h|j<=;Yu7 z_y|6MgM*{H-~)(*ga4CcuyFg!IrrXkk~6+EyRcH}Tx{*^U0R8x$b<<0VpyN)RR3__ zv{*c6SZCWuQzu)8ryH(FiddK92EONuqo$W%SgTLZ*1Seg z_5GR~5JkW7|NXTy{ofK|l9H2ZTFjW(vW$7$M?*eq#3b;Yb0g%xFiRY1%XgU1NufuK z&Hg0ny+~U;Vy%CGUG`~f=B=ExsjGG7d&M~9k5TL2;5GiD-s{Bu8Gu3VC*)C9$!b(z6aiJ9zZMePdN?S^T7zqNBl0Z^N2SGsiY1qUBqGDoV zq5^@KsF*-jEMWpMfj~@DA`v7Y5C{YU!M**S?;LVY(&RpS-|y#q=iIx}y<2x5)b79D zc>H8@=~Q6M2V*kEnB>WPUs*nX>0H+=CC_J*->XN@uD;lK`to6H%rc&^*@&V}D_Ti- zHTlI++^9vZTD=j*^=`f1U289LrSV}azSdgnH0#X-Sf&5#r_Q9lu8g^`c-%QHe;LDJ zD4aJJ7Y|K1fP0oD{^n)z7ff#PFn|Mi29=l=s|>1S|7^GiP?I3(W$)_g~> z)<5?2PjH*~zt%7N2})8gp#BeZorlw*n2-lnJL zA^Q*D9{zP$=hwC@ey0ofy?g_>!g)uq)_1zZkI{4bzQASraq+VM(GBT8kALLFyMD#* z@=Lu5{;J+bSnuaYtBc>UAchiq+vI_KHfwjMR`f*N{-lwmy#+x&u zS2^!0yiUG0`TFn_*7yL{dCg$G|0i&k{9mjt`-|vDzc07pGW90(qx*Y~uHWx1Sob%> zul False); - Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg_1"); - - Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg_1"); - - MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg_1"); - - Unit_Name : constant String := "pkg"; - - Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := - (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), - Language => Unit_Based_Language, - Unit_Part => Unit_Spec, - Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), - Statement => Statement_Buffer'Address, - Decision => Decision_Buffer'Address, - MCDC => MCDC_Buffer'Address, - Statement_Last_Bit => -1, - Decision_Last_Bit => -1, - MCDC_Last_Bit => -1); -end Buffers_1; - -package Buffers_2 is - Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); - Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg_2"); - - Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); - Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg_2"); - - MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); - MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg_2"); - - Unit_Name : constant String := "pkg"; - - Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := - (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), - Language => Unit_Based_Language, - Unit_Part => Unit_Body, - Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), - Statement => Statement_Buffer'Address, - Decision => Decision_Buffer'Address, - MCDC => MCDC_Buffer'Address, - Statement_Last_Bit => 2, - Decision_Last_Bit => 1, - MCDC_Last_Bit => 2); -end Buffers_2; - - Buffers_Group : aliased constant Coverage_Buffers_Group := - (1 => Buffers_1.Buffers'Access, -2 => Buffers_2.Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 2, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_pkg_buffers"); - -end GCVRT.Bpkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads deleted file mode 100644 index 8a33e62aa..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads +++ /dev/null @@ -1,25 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -with GCVRT.Bmain_1; -with GCVRT.Bmain_2; -with GCVRT.Bpkg; - -package GCVRT.Foo is - - pragma Preelaborate; - - gnatcov_rts_buffers_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_main_1_buffers,"gnatcov_rts_buffers_main_1_buffers"); - gnatcov_rts_buffers_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_main_2_buffers,"gnatcov_rts_buffers_main_2_buffers"); - gnatcov_rts_buffers_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_pkg_buffers,"gnatcov_rts_buffers_pkg_buffers"); - List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( - 1 => gnatcov_rts_buffers_main_1_buffers'Access, - 2 => gnatcov_rts_buffers_main_2_buffers'Access, - 3 => gnatcov_rts_buffers_pkg_buffers'Access); - C_List : constant GNATcov_RTS.Buffers.Lists.GNATcov_RTS_Coverage_Buffers_Group_Array := - ( 3, List'Address); - pragma Export (C, C_List, "gnatcov_rts_buffers_array_Foo"); - -end GCVRT.Foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads deleted file mode 100644 index d057902c9..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads +++ /dev/null @@ -1,35 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GCVRT.Ppkg is - - pragma Pure; - -package Buffers_1 is - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg_1"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg_1"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg_1"); - -end Buffers_1; - -package Buffers_2 is - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg_2"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg_2"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg_2"); - -end Buffers_2; - -end GCVRT.Ppkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_1.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_1.ads similarity index 79% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_1.ads index abd0f2006..a29e8e4dd 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_1.ads @@ -1,32 +1,31 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Interfaces.C; use Interfaces.C; -with System; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GCVRT.Bmain_1 is +package GNATcov_RTS.Buffers.BB_main_1 is pragma Preelaborate; -package Buffers_1 is Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1"); Unit_Name : constant String := "main_1"; + Project_Name : constant String := ""; Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := (Fingerprint => (125, 27, 0, 113, 188, 140, 235, 155, 190, 125, 180, 238, 139, 95, 108, 198, 229, 72, 222, 11), Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, @@ -34,11 +33,9 @@ package Buffers_1 is Statement_Last_Bit => 0, Decision_Last_Bit => -1, MCDC_Last_Bit => -1); -end Buffers_1; - Buffers_Group : aliased constant Coverage_Buffers_Group := - (1 => Buffers_1.Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_1_buffers"); + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_1_buffers"); -end GCVRT.Bmain_1; +end GNATcov_RTS.Buffers.BB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_2.ads similarity index 79% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_2.ads index db6822381..4f546cde7 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_2.ads @@ -1,32 +1,31 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Interfaces.C; use Interfaces.C; -with System; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GCVRT.Bmain_2 is +package GNATcov_RTS.Buffers.BB_main_2 is pragma Preelaborate; -package Buffers_1 is Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2"); Unit_Name : constant String := "main_2"; + Project_Name : constant String := ""; Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := (Fingerprint => (242, 237, 33, 15, 121, 175, 106, 160, 145, 225, 226, 10, 175, 16, 207, 223, 26, 27, 27, 148), Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, @@ -34,11 +33,9 @@ package Buffers_1 is Statement_Last_Bit => 0, Decision_Last_Bit => -1, MCDC_Last_Bit => -1); -end Buffers_1; - Buffers_Group : aliased constant Coverage_Buffers_Group := - (1 => Buffers_1.Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_2_buffers"); + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_2_buffers"); -end GCVRT.Bmain_2; +end GNATcov_RTS.Buffers.BB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads new file mode 100644 index 000000000..39a532e60 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads @@ -0,0 +1,41 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GNATcov_RTS.Buffers.BB_pkg is + + pragma Preelaborate; + + Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg"); + + Unit_Name : constant String := "pkg"; + Project_Name : constant String := ""; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), + Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 2, + Decision_Last_Bit => 1, + MCDC_Last_Bit => 2); + + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_pkg_buffers"); + +end GNATcov_RTS.Buffers.BB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads new file mode 100644 index 000000000..f041e06e8 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads @@ -0,0 +1,41 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GNATcov_RTS.Buffers.BS_pkg is + + pragma Preelaborate; + + Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg"); + + Unit_Name : constant String := "pkg"; + Project_Name : constant String := ""; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), + Language => Unit_Based_Language, + Unit_Part => Unit_Spec, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), + Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => -1, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); + + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_S_pkg_buffers"); + +end GNATcov_RTS.Buffers.BS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.adb similarity index 64% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.adb rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.adb index b57053032..1923cd7da 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.adb @@ -1,15 +1,15 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; -with GCVRT.Foo; -package body GCVRT.DB_main_1 is +with GNATcov_RTS.Buffers.Lists.foo; +package body GNATcov_RTS.Buffers.DB_main_1 is procedure Dump_Buffers is begin GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GCVRT.Foo.List, + (GNATcov_RTS.Buffers.Lists.foo.List, Program_Name => "main_1", Exec_Date => 0); end Dump_Buffers; -end GCVRT.DB_main_1; +end GNATcov_RTS.Buffers.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.ads similarity index 60% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.ads index 8a501b2da..e8975f8ba 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.ads @@ -1,8 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers; -package GCVRT.DB_main_1 is +package GNATcov_RTS.Buffers.DB_main_1 is procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); - -end GCVRT.DB_main_1; +end GNATcov_RTS.Buffers.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.adb similarity index 64% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.adb rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.adb index ccab2ae8d..c868d1f17 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.adb @@ -1,15 +1,15 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; -with GCVRT.Foo; -package body GCVRT.DB_main_2 is +with GNATcov_RTS.Buffers.Lists.foo; +package body GNATcov_RTS.Buffers.DB_main_2 is procedure Dump_Buffers is begin GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GCVRT.Foo.List, + (GNATcov_RTS.Buffers.Lists.foo.List, Program_Name => "main_2", Exec_Date => 0); end Dump_Buffers; -end GCVRT.DB_main_2; +end GNATcov_RTS.Buffers.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.ads similarity index 60% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.ads index 0f4078092..5a1450133 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.ads @@ -1,8 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers; -package GCVRT.DB_main_2 is +package GNATcov_RTS.Buffers.DB_main_2 is procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); - -end GCVRT.DB_main_2; +end GNATcov_RTS.Buffers.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads new file mode 100644 index 000000000..63f03b9f4 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads @@ -0,0 +1,25 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers.BB_main_1; +with GNATcov_RTS.Buffers.BB_main_2; +with GNATcov_RTS.Buffers.BB_pkg; +with GNATcov_RTS.Buffers.BS_pkg; + +package GNATcov_RTS.Buffers.Lists.foo is + + pragma Preelaborate; + + gnatcov_rts_buffers_B_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_B_main_1_buffers,"gnatcov_rts_buffers_B_main_1_buffers"); + gnatcov_rts_buffers_B_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_B_main_2_buffers,"gnatcov_rts_buffers_B_main_2_buffers"); + gnatcov_rts_buffers_B_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_B_pkg_buffers,"gnatcov_rts_buffers_B_pkg_buffers"); + gnatcov_rts_buffers_S_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_S_pkg_buffers,"gnatcov_rts_buffers_S_pkg_buffers"); + List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( + 1 => gnatcov_rts_buffers_B_main_1_buffers'Access, + 2 => gnatcov_rts_buffers_B_main_2_buffers'Access, + 3 => gnatcov_rts_buffers_B_pkg_buffers'Access, + 4 => gnatcov_rts_buffers_S_pkg_buffers'Access); + +end GNATcov_RTS.Buffers.Lists.foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_1.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads similarity index 66% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads index adbaa4d71..1d0b35bd8 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads @@ -1,23 +1,19 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; -with GNATcov_RTS.Buffers; pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); -package GCVRT.Pmain_1 is +package GNATcov_RTS.Buffers.PB_main_1 is pragma Pure; -package Buffers_1 is Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1_1"); + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1"); Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1_1"); + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1"); MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1_1"); + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1"); -end Buffers_1; - -end GCVRT.Pmain_1; +end GNATcov_RTS.Buffers.PB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads similarity index 66% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads index 504bd5e24..f9f18da05 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads @@ -1,23 +1,19 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; -with GNATcov_RTS.Buffers; pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); -package GCVRT.Pmain_2 is +package GNATcov_RTS.Buffers.PB_main_2 is pragma Pure; -package Buffers_1 is Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2_1"); + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2"); Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2_1"); + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2"); MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2_1"); + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2"); -end Buffers_1; - -end GCVRT.Pmain_2; +end GNATcov_RTS.Buffers.PB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads new file mode 100644 index 000000000..2f84e5165 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads @@ -0,0 +1,19 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GNATcov_RTS.Buffers.PB_pkg is + + pragma Pure; + + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg"); + +end GNATcov_RTS.Buffers.PB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads new file mode 100644 index 000000000..71406c7f1 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads @@ -0,0 +1,19 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GNATcov_RTS.Buffers.PS_pkg is + + pragma Pure; + + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg"); + +end GNATcov_RTS.Buffers.PS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb index cfb135284..7a94497f7 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb @@ -1,9 +1,8 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pmain_1;with GCVRT.DB_main_1;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +with GNATcov_RTS.Buffers.PB_main_1;with GNATcov_RTS.Buffers.DB_main_1;with GNATcov_RTS;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is begin - GNATcov_RTS.Buffers.Witness(GCVRT.Pmain_1.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); -GCVRT.DB_main_1.Dump_Buffers;end Main_1; - + GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_main_1.Statement_Buffer,0);Pkg.Compute (True, False); +GNATcov_RTS.Buffers.DB_main_1.Dump_Buffers;end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index a136b1e8d13a1557ad20f0640ee748747697bde7..255ad5bef91d788cd2cd950cee8283d653c7128c 100644 GIT binary patch delta 35 qcmZo>Ze|v7_j3$M&M#9)&PYwpF38W!D`DW?D5Am0_;a!?qZZe|v7_j3$M&M#9)&PYwpF38W!D`DW>D5Am0_; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb index 23a05a782..19b3ac3c0 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb @@ -1,9 +1,8 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pmain_2;with GCVRT.DB_main_2;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +with GNATcov_RTS.Buffers.PB_main_2;with GNATcov_RTS.Buffers.DB_main_2;with GNATcov_RTS;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is begin - GNATcov_RTS.Buffers.Witness(GCVRT.Pmain_2.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); -GCVRT.DB_main_2.Dump_Buffers;end Main_2; - + GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_main_2.Statement_Buffer,0);Pkg.Compute (True, True); +GNATcov_RTS.Buffers.DB_main_2.Dump_Buffers;end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid index bdd702aa80720a2806c547d1f145029adf069292..5f4bce5b445a8722d50b04b2496a8451c8be5a78 100644 GIT binary patch delta 35 qcmZo>Ze|v7_j3$M&M#9)&PYwpF38W!D`DW?D5Am0_;a!?qZZe|v7_j3$M&M#9)&PYwpF38W!D`DW>D5Am0_; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.adb index 02f132e03..676e5b9d6 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.adb @@ -1,18 +1,18 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Ada.Text_IO; use Ada.Text_IO; -with GNATcov_RTS.Buffers;with GCVRT.Ppkg;package body Pkg is +with GNATcov_RTS.Buffers.PB_pkg;package body Pkg is ------------- -- Compute -- ------------- procedure Compute (A, B : Boolean) is - MCDC_State_2_Var:GNATcov_RTS.Buffers.MCDC_State_Type:=0;MCDC_State_2:constant GNATCov_RTS.Sys.Address:=MCDC_State_2_Var'Address;begin - GNATcov_RTS.Buffers.Witness(GCVRT.Ppkg.Buffers_2.Statement_Buffer,0);if GNATcov_RTS.Buffers.Witness(GCVRT.Ppkg.Buffers_2.Decision_Buffer,0,1,GCVRT.Ppkg.Buffers_2.MCDC_Buffer,0,MCDC_State_2,GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,TRUE,A )and then GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,FALSE,B ))then - GNATcov_RTS.Buffers.Witness(GCVRT.Ppkg.Buffers_2.Statement_Buffer,1);Put_Line ("true"); + MCDC_State_2_Var:aliased GNATcov_RTS.Buffers.MCDC_State_Type;MCDC_State_2:constant GNATCov_RTS.Sys.Address:=MCDC_State_2_Var'Address;begin + GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_pkg.Statement_Buffer,0);if GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_pkg.Decision_Buffer,0,1,GNATcov_RTS.Buffers.PB_pkg.MCDC_Buffer,0,MCDC_State_2,GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,TRUE,A )and then GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,FALSE,B ))then + GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_pkg.Statement_Buffer,1);Put_Line ("true"); else - GNATcov_RTS.Buffers.Witness(GCVRT.Ppkg.Buffers_2.Statement_Buffer,2);Put_Line ("false"); + GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_pkg.Statement_Buffer,2);Put_Line ("false"); end if; end Compute; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.ads index 956e2d9a3..378466db6 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.ads @@ -1,5 +1,5 @@ pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers;with GCVRT.Ppkg;package Pkg is +with GNATcov_RTS.Buffers.PS_pkg;package Pkg is procedure Compute (A, B : Boolean); end Pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid index 1bfd0c55b74d5d31c4a81352b75d4fca0d8261d3..52ca1a8f2f09efccbd5038548c9f9eeb20e4721c 100644 GIT binary patch delta 66 zcmbQnF^xmS-On*3IloLHIU_YWyC6R^uY`enqeuV~(@& TCKCe_0|OZI0%KYj;7@AobnOhkcDrg%RSQ!|AjfEKxqyfRhL|Om< delta 322 zcmcb{_lZx$-On*3IloLHIU_YWyC6R^uY`ejqKJctpiZV=AW=!KTf|$w$ zc4qv&`4qDxBarii z1<0AK!3rXCSd}MFW)++KpOtU&Qr0j-kf~tjfM^us!BQw9Mj$nl_1JXS3yRD$9bQeI loXB=g-B{PaOxMs@!N}Ok(9p`%TtVBw$jZO~q!R>SGyp5ZLInT- diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index 4f6f771d824294e26979c7bbf23af408470bbe67..6d8d58fee919991e9661b3c759ba00fa266c61f2 100644 GIT binary patch delta 282 zcmeyv_kd5t-On*3IloLHIU_YWyC6R^uY`enqKE^JkzQg>CKCe_0|Nuou7=KQl#_Y`abMq}`MMfa!4-1ep*?|>Awy-Ks7G@Kg z{GL^8@7eP`(#$;2FBl$+nAjhe{Vj;tjGxDykP-yCL6GV$P!j%W}u0aSFmQk;!IkI_v`JHG3RhO`e>|c0t`(*T78I&{)C9*vin*%G5$Z Q+rY@mzyNFo)J%{*0FXdEApigX diff --git a/testsuite/tests/U204-026-arch-mix/gen/main_1.srctrace b/testsuite/tests/U204-026-arch-mix/gen/main_1.srctrace index 9713cd6378a77d8f2729fb72a13d77c439225cd2..e974fe606809e2446ccda493c4435fcb631ccfa8 100644 GIT binary patch delta 82 zcmZ3$ynuN^3?swDNNdsD#LT>SLk0#$1_)pSQ4?1}C5)h=K#Cc}ob1SGJ-LBVVd4+L P$*hd}90l3wAYldoq!ABY delta 81 zcmZ3$ynuN^%)|r>Q3fE$P0Y-TH)LR71aW|XZQ@#MUJwH;VFYAM4rG*=oXe;U7A?q5 S2T3w8PyB1m43acwR0II4?+=^+ diff --git a/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace b/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace index f9310f2c01f1f50fa8eb8d28c7a4d558556fa316..ef244cfe7684d3d525848372a52cb172a6761f00 100644 GIT binary patch delta 84 zcmZo+ZegAf!^ki((poS#F*7gTkO2(XK;*=wP(dRG21X#C86-H_l+jwWAUhq*V*(1W Nz+@(Vv}OTG006GK4wC=? delta 86 zcmZo+ZegAfGcmzJkO2sC6EpMT4M8jh2DXVStr3Do3=E7wLFUP>jMkhW>4NNZ2Ih%h PtwrD*AcF~rS%4S-@dysG diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 2ea341c6bba732d35d81f98a0fb29faaeff9b510..1ddccc5b96d894fca0916193751ec3b474e86839 100644 GIT binary patch delta 394 zcmbQvKaF3+-On*3IloLHIU_YWyC6R^uY`enqKNy%c*luLELoEn8JQU;J~Lx21~De9 zGG3VM&Xmo^$il$D0K!~A%sKfRqswFiW{%0bm>L*=PPS%tX8*~^43uG>+{$dr{*wv9 zKFKV@31V>rG5h3q%o?l^acLH1D9f2e70Swmv!=5EO@Nwqo5dDrz9efHBlF|}R&hp_ z$sMe#Wf+0xu>o;zVrE{vAqvlEax|NE{R^PvyB$26H`s)p07(k~v5|?MLAip4k%5ts zp`nq1CP;ie5IbANWaQ_j#-yYc<)F1-On*3IloLHIU_YWyC6R^uY`ejqKG>S0}xD%c7)J#EGG*vvO?Im%s7)6 z8JQVD3MPv(USMRJ9LMCs#t4#SnS772X!0Va4#wY;wV9pSe?vt}nQhsBGeK1BWR~Fs z=>>zy_n0-n=CVxYW>JQ+j9FBntXMd!odswD)U?wqwm|baS;H7vCMU3pGcr%EU|p>N zG7sb^HXzPT%*=~7#1Jt8iA=U<(~dd|WZdAHcK+tu$tOUX1b{dtwJbF!zaTd?uSB<` zC^Z!%J_U%Ktzt6rb5mndD~l3KQ)1Hd5=(#qmRgjUo*Gk^; diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt index fe7835a353df381011330558d8a6d119db11893f..51f0e832b41f306029db7f010049ec7ea8ed7d08 100644 GIT binary patch literal 1851 zcmb7FJ!lkB5Z-qe6{93kvB_!JU>WvqZxMr{La;~*f1(&{0&(4Yxtz(~o_Cug7O5;O zv=OxMr%($)5n>_ONJ_C2yI^5Zuo5j|qm4S>?9OIS6VD7cH*e?7H$UJ0yy25WXT6|l zdQ;k)t_789XlyeKL$N9&gGEQ;FpPd$7ec>Q7<26XmhBv{+`2bq`IWhX?^dc4#k^a( zpj1`?xS2HaX5tj>;Le(GCmX~2$gWepHeDucLrMcdE@{0jFzGo45QXaBfv;nQA0$neChALym0aUjSn9?7kb_- z_vUgpu_*uqCwUWg5TQ^+R9MFbL_NJacjffZlXv&d-RavmeEw0_gZZUsEBa42A$|o8 zp~$+GG##WKk9aR0c8{;*-+mi>c4o)XpT}?86w?w6;OKN223Tl1*A}`y7WlQjQQUjz(MhN zpi$V}q!4~&+V_!3=je=a$N@6ZTT1~9EdU_^G4z7KuyjZOI@lgNVc<6uXl7Eg={Ttj zi>ll>1L&e961~ZsNhB70QzR$qA{T6q6tYoPy9k3Eup7KHgkX^gxHs}(_~_fk?IPx{ zEhl+;WDDHVXD1>s1&RF$_lO6zB|YiR&V=$>!EIz&Xemj>qt@~89f(i_=Pxg&fmWe(O8I;R(2vHK{SMz6k;W$v#|)rbmB*7 zE!g-0mRf~0HvU2y=k4WUqQedIX6DV#yW4w7ekAkzhr37B=1s18d0wrznzgHIC*e2_ zStmyUM3DGB&wtl50&UZk*s5PBzqkIk=KA>+zY|Y|)Tn^QS?%hy6!G)M`&TZaVs`{v zg9Q$EX)mFq1xF{wMtM3wCn_^Qw0Nl%Mo$PQ4Lg{m+^Rwg&xa;&cc{OqPO7{bOeLs4Tih~6p4^%#Nx%Rsj6YkGOtAm} diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bpkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bpkg.ads deleted file mode 100644 index 46d0ddbc6..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bpkg.ads +++ /dev/null @@ -1,74 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; -with System; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GCVRT.Bpkg is - - pragma Preelaborate; - -package Buffers_1 is - Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg_1"); - - Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg_1"); - - MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg_1"); - - Unit_Name : constant String := "pkg"; - - Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := - (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), - Language => Unit_Based_Language, - Unit_Part => Unit_Spec, - Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), - Statement => Statement_Buffer'Address, - Decision => Decision_Buffer'Address, - MCDC => MCDC_Buffer'Address, - Statement_Last_Bit => -1, - Decision_Last_Bit => -1, - MCDC_Last_Bit => -1); -end Buffers_1; - -package Buffers_2 is - Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); - Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg_2"); - - Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); - Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg_2"); - - MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); - MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg_2"); - - Unit_Name : constant String := "pkg"; - - Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := - (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), - Language => Unit_Based_Language, - Unit_Part => Unit_Body, - Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), - Statement => Statement_Buffer'Address, - Decision => Decision_Buffer'Address, - MCDC => MCDC_Buffer'Address, - Statement_Last_Bit => 2, - Decision_Last_Bit => 1, - MCDC_Last_Bit => 2); -end Buffers_2; - - Buffers_Group : aliased constant Coverage_Buffers_Group := - (1 => Buffers_1.Buffers'Access, -2 => Buffers_2.Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 2, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_pkg_buffers"); - -end GCVRT.Bpkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads deleted file mode 100644 index fb6f2406e..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads +++ /dev/null @@ -1,13 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers; -with Ada.Finalization; -package GCVRT.DB_main_1 is - - procedure Dump_Buffers; - pragma Convention (C, Dump_Buffers); - - type Dump_Controlled_Type is new Ada.Finalization.Controlled with - null record; - overriding procedure Finalize (Self : in out Dump_Controlled_Type); - -end GCVRT.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads deleted file mode 100644 index 691c4c538..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads +++ /dev/null @@ -1,13 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers; -with Ada.Finalization; -package GCVRT.DB_main_2 is - - procedure Dump_Buffers; - pragma Convention (C, Dump_Buffers); - - type Dump_Controlled_Type is new Ada.Finalization.Controlled with - null record; - overriding procedure Finalize (Self : in out Dump_Controlled_Type); - -end GCVRT.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads deleted file mode 100644 index c9aac77d4..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads +++ /dev/null @@ -1,25 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -with GCVRT.Bmain_1; -with GCVRT.Bmain_2; -with GCVRT.Bpkg; - -package GCVRT.Foo is - - pragma Preelaborate; - - gnatcov_rts_buffers_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_main_1_buffers,"gnatcov_rts_buffers_main_1_buffers"); - gnatcov_rts_buffers_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_main_2_buffers,"gnatcov_rts_buffers_main_2_buffers"); - gnatcov_rts_buffers_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_pkg_buffers,"gnatcov_rts_buffers_pkg_buffers"); - List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( - 1 => gnatcov_rts_buffers_main_1_buffers'Access, - 2 => gnatcov_rts_buffers_main_2_buffers'Access, - 3 => gnatcov_rts_buffers_pkg_buffers'Access); - C_List : constant GNATcov_RTS.Buffers.Lists.GNATcov_RTS_Coverage_Buffers_Group_Array := - ( 3, List'Address); - pragma Export (C, C_List, "gnatcov_rts_buffers_array_Foo"); - -end GCVRT.Foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads deleted file mode 100644 index 91152a7b1..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads +++ /dev/null @@ -1,35 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GCVRT.Ppkg is - - pragma Pure; - -package Buffers_1 is - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg_1"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg_1"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg_1"); - -end Buffers_1; - -package Buffers_2 is - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg_2"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg_2"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg_2"); - -end Buffers_2; - -end GCVRT.Ppkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_1.ads similarity index 77% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_1.ads index f21637825..11f8b2437 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_1.ads @@ -1,32 +1,31 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Interfaces.C; use Interfaces.C; -with System; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GCVRT.Bmain_1 is +package GNATcov_RTS.Buffers.BB_main_1 is pragma Preelaborate; -package Buffers_1 is Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1"); Unit_Name : constant String := "main_1"; + Project_Name : constant String := ""; Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := (Fingerprint => (125, 27, 0, 113, 188, 140, 235, 155, 190, 125, 180, 238, 139, 95, 108, 198, 229, 72, 222, 11), Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, @@ -34,11 +33,9 @@ package Buffers_1 is Statement_Last_Bit => 0, Decision_Last_Bit => -1, MCDC_Last_Bit => -1); -end Buffers_1; - Buffers_Group : aliased constant Coverage_Buffers_Group := - (1 => Buffers_1.Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_1_buffers"); + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_1_buffers"); -end GCVRT.Bmain_1; +end GNATcov_RTS.Buffers.BB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_2.ads similarity index 77% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_2.ads index d68593c7f..fb7e669bc 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_2.ads @@ -1,32 +1,31 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Interfaces.C; use Interfaces.C; -with System; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GCVRT.Bmain_2 is +package GNATcov_RTS.Buffers.BB_main_2 is pragma Preelaborate; -package Buffers_1 is Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2"); Unit_Name : constant String := "main_2"; + Project_Name : constant String := ""; Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := (Fingerprint => (242, 237, 33, 15, 121, 175, 106, 160, 145, 225, 226, 10, 175, 16, 207, 223, 26, 27, 27, 148), Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, @@ -34,11 +33,9 @@ package Buffers_1 is Statement_Last_Bit => 0, Decision_Last_Bit => -1, MCDC_Last_Bit => -1); -end Buffers_1; - Buffers_Group : aliased constant Coverage_Buffers_Group := - (1 => Buffers_1.Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_2_buffers"); + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_2_buffers"); -end GCVRT.Bmain_2; +end GNATcov_RTS.Buffers.BB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads new file mode 100644 index 000000000..8d1bde3aa --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads @@ -0,0 +1,41 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GNATcov_RTS.Buffers.BB_pkg is + + pragma Preelaborate; + + Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg"); + + Unit_Name : constant String := "pkg"; + Project_Name : constant String := ""; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), + Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 2, + Decision_Last_Bit => 1, + MCDC_Last_Bit => 2); + + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_pkg_buffers"); + +end GNATcov_RTS.Buffers.BB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads new file mode 100644 index 000000000..4c9260685 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads @@ -0,0 +1,41 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GNATcov_RTS.Buffers.BS_pkg is + + pragma Preelaborate; + + Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg"); + + Unit_Name : constant String := "pkg"; + Project_Name : constant String := ""; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), + Language => Unit_Based_Language, + Unit_Part => Unit_Spec, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Project_Name => (Project_Name'Address, Project_Name'Length), + Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => -1, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); + + Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_S_pkg_buffers"); + +end GNATcov_RTS.Buffers.BS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.adb similarity index 55% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.adb rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.adb index 79e3fa3de..18ea1e0ed 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.adb @@ -1,20 +1,15 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; -with GCVRT.Foo; -package body GCVRT.DB_main_1 is +with GNATcov_RTS.Buffers.Lists.foo; +package body GNATcov_RTS.Buffers.DB_main_1 is procedure Dump_Buffers is begin GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GCVRT.Foo.List, + (GNATcov_RTS.Buffers.Lists.foo.List, Program_Name => "main_1", Exec_Date => 0); end Dump_Buffers; - overriding procedure Finalize (Self : in out Dump_Controlled_Type) is - begin - Dump_Buffers; - end Finalize; - -end GCVRT.DB_main_1; +end GNATcov_RTS.Buffers.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads new file mode 100644 index 000000000..ca5c6b54d --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads @@ -0,0 +1,6 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +package GNATcov_RTS.Buffers.DB_main_1 is + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); +end GNATcov_RTS.Buffers.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.adb similarity index 55% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.adb rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.adb index d684712eb..02b84cc6a 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.adb @@ -1,20 +1,15 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; -with GCVRT.Foo; -package body GCVRT.DB_main_2 is +with GNATcov_RTS.Buffers.Lists.foo; +package body GNATcov_RTS.Buffers.DB_main_2 is procedure Dump_Buffers is begin GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GCVRT.Foo.List, + (GNATcov_RTS.Buffers.Lists.foo.List, Program_Name => "main_2", Exec_Date => 0); end Dump_Buffers; - overriding procedure Finalize (Self : in out Dump_Controlled_Type) is - begin - Dump_Buffers; - end Finalize; - -end GCVRT.DB_main_2; +end GNATcov_RTS.Buffers.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads new file mode 100644 index 000000000..06f972268 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads @@ -0,0 +1,6 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +package GNATcov_RTS.Buffers.DB_main_2 is + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); +end GNATcov_RTS.Buffers.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads new file mode 100644 index 000000000..dfb98dbbb --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads @@ -0,0 +1,25 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers.BB_main_1; +with GNATcov_RTS.Buffers.BB_main_2; +with GNATcov_RTS.Buffers.BB_pkg; +with GNATcov_RTS.Buffers.BS_pkg; + +package GNATcov_RTS.Buffers.Lists.foo is + + pragma Preelaborate; + + gnatcov_rts_buffers_B_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_B_main_1_buffers,"gnatcov_rts_buffers_B_main_1_buffers"); + gnatcov_rts_buffers_B_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_B_main_2_buffers,"gnatcov_rts_buffers_B_main_2_buffers"); + gnatcov_rts_buffers_B_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_B_pkg_buffers,"gnatcov_rts_buffers_B_pkg_buffers"); + gnatcov_rts_buffers_S_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_S_pkg_buffers,"gnatcov_rts_buffers_S_pkg_buffers"); + List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( + 1 => gnatcov_rts_buffers_B_main_1_buffers'Access, + 2 => gnatcov_rts_buffers_B_main_2_buffers'Access, + 3 => gnatcov_rts_buffers_B_pkg_buffers'Access, + 4 => gnatcov_rts_buffers_S_pkg_buffers'Access); + +end GNATcov_RTS.Buffers.Lists.foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads similarity index 63% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads index c5a253048..baf5c0f4c 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads @@ -1,23 +1,19 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; -with GNATcov_RTS.Buffers; pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); -package GCVRT.Pmain_1 is +package GNATcov_RTS.Buffers.PB_main_1 is pragma Pure; -package Buffers_1 is Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1_1"); + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1"); Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1_1"); + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1"); MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1_1"); + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1"); -end Buffers_1; - -end GCVRT.Pmain_1; +end GNATcov_RTS.Buffers.PB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads similarity index 63% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads index 8bbd8b5ce..f40226dce 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads @@ -1,23 +1,19 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; -with GNATcov_RTS.Buffers; pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); -package GCVRT.Pmain_2 is +package GNATcov_RTS.Buffers.PB_main_2 is pragma Pure; -package Buffers_1 is Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2_1"); + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2"); Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2_1"); + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2"); MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2_1"); + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2"); -end Buffers_1; - -end GCVRT.Pmain_2; +end GNATcov_RTS.Buffers.PB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads new file mode 100644 index 000000000..638a84ec2 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads @@ -0,0 +1,19 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GNATcov_RTS.Buffers.PB_pkg is + + pragma Pure; + + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg"); + +end GNATcov_RTS.Buffers.PB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads new file mode 100644 index 000000000..c8f18f74f --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads @@ -0,0 +1,19 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GNATcov_RTS.Buffers.PS_pkg is + + pragma Pure; + + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg"); + +end GNATcov_RTS.Buffers.PS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb index c9267341a..61decca75 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb @@ -1,9 +1,8 @@ pragma Style_Checks (Off); pragma Warnings (Off); -with Pkg; - -with GNATcov_RTS.Buffers;with GCVRT.Pmain_1;with GCVRT.DB_main_1;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is -GNATcov_Dump_Object:GCVRT.DB_main_1.Dump_Controlled_Type;begin - GNATcov_RTS.Buffers.Witness(GCVRT.Pmain_1.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); -end Main_1; - +with Pkg; + +with GNATcov_RTS.Buffers.PB_main_1;with GNATcov_RTS.Buffers.DB_main_1;with GNATcov_RTS;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +begin + GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_main_1.Statement_Buffer,0);Pkg.Compute (True, False); +GNATcov_RTS.Buffers.DB_main_1.Dump_Buffers;end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid index 6095ca35ca556f6bbca09c4f490391ed56311f51..b5f7a753eb7df7f191cc68d5518e5a7abea5f66d 100644 GIT binary patch delta 35 qcmZo=ZeD5Ay4_D5Ay4_e96-!IabCgX1SXEjFBt7uA!@XlY}tP@LD>0BGMpe5H%RH^DNGtrH3ylL rp{$oos!*0NGmK@+3^W01V)s;RLFHfXP#sG@xn@GATn@FPT)K mEMaCC%a$2v0>tRajm)-;zbEf!R$yeB{D4`Uk#X`5W+ebZej#Z9 diff --git a/testsuite/tests/U204-026-arch-mix/main_2-out.txt b/testsuite/tests/U204-026-arch-mix/main_2-out.txt deleted file mode 100644 index d32628f61..000000000 --- a/testsuite/tests/U204-026-arch-mix/main_2-out.txt +++ /dev/null @@ -1,11 +0,0 @@ -true - -== GNATcoverage source trace file == -R05BVGNvdiBzb3VyY2UgdHJhY2UgZmlsZQAAAAAAAAACAAAABAAAAAEAAAAGAAAAbWFpbl8yAAACAAAA -CAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAYAAAABAAAAAAAAAAAAAAAAAQB9GwBxvIzrm759tO6L -X2zG5UjeC/Lpsay1fgprgYI6VUU0HPLkv1H8AAAAAABtYWluXzEAAAAAAAAGAAAAAQAAAAAAAAAAAAAA -AAEA8u0hD3mvaqCR4eIKrxDP3xobG5Ty6bGstX4Ka4GCOlVFNBzy5L9R/AAAAAAAbWFpbl8yAAABAAAA -AwAAAAAAAAAAAAAAAAAAAAACAKyHeINRQaranFeaHiNHYKYOoX3YErzvNm+cLnrwWmfiF3ojV5y5jcIA -AAAAAHBrZwADAAAAAwAAAAIAAAADAAAAAAEAqUhjt6IPXPIu0fM3sFIRPv5MmTChG7yK8fUJlo8Atcxa -mERYu95qKgAAAAAAcGtnAAMAAAACAAAABAAAAA== -== End == diff --git a/testsuite/tests/excluded_unit_imported_prj/test.py b/testsuite/tests/excluded_unit_imported_prj/test.py index 126c5b972..0991ac8d6 100644 --- a/testsuite/tests/excluded_unit_imported_prj/test.py +++ b/testsuite/tests/excluded_unit_imported_prj/test.py @@ -13,7 +13,7 @@ prj1 = gprfor(mains=[], prjid='prj1', srcdirs=['../prj1'], objdir='obj-prj1') # Check that ignoring pkg.c in the main project yields a warning, as the pkg.c -# unit is in the prj1 dependency and not in the root project. +# unit is in thr prj1 dependency and not in the root project. extra_p = """ package Coverage is for Excluded_Units use ("pkg.c"); diff --git a/testsuite/tests/instr-cov/ext_gpr/test.py b/testsuite/tests/instr-cov/ext_gpr/test.py index b76c9b08c..1238e3215 100644 --- a/testsuite/tests/instr-cov/ext_gpr/test.py +++ b/testsuite/tests/instr-cov/ext_gpr/test.py @@ -25,13 +25,13 @@ thistest.fail_if_not_equal( "instrumented directories", "\n".join([ - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bpkg.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bpkg1.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bpkg2.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-p_ext2.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-ppkg.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-ppkg1.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-ppkg2.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-bs_pkg.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-bs_pkg1.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-bs_pkg2.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-lists-p_ext2.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-ps_pkg.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-ps_pkg1.ads", + "obj-p_ext2/p_ext2-gnatcov-instr/gnatcov_rts-buffers-ps_pkg2.ads", "obj-p_ext2/p_ext2-gnatcov-instr/pkg.ads", "obj-p_ext2/p_ext2-gnatcov-instr/pkg1.ads", "obj-p_ext2/p_ext2-gnatcov-instr/pkg2.ads", diff --git a/testsuite/tests/instr-cov/gpr-complex/main_body.gpr b/testsuite/tests/instr-cov/gpr-complex/main_body.gpr deleted file mode 100644 index 109449cf5..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/main_body.gpr +++ /dev/null @@ -1,5 +0,0 @@ -project Main_Body extends "lib" is - for Source_Dirs use ("src-main_body"); - for Object_Dir use "obj-main_body"; - for Main use ("main.adb"); -end Main_Body; diff --git a/testsuite/tests/instr-cov/gpr-complex/main_sep.gpr b/testsuite/tests/instr-cov/gpr-complex/main_sep.gpr deleted file mode 100644 index d4ba368f8..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/main_sep.gpr +++ /dev/null @@ -1,5 +0,0 @@ -project Main_Sep extends "lib" is - for Source_Dirs use ("src-main_sep"); - for Object_Dir use "obj-main_sep"; - for Main use ("main.adb"); -end Main_Sep; diff --git a/testsuite/tests/instr-cov/gpr-complex/main_simple.gpr b/testsuite/tests/instr-cov/gpr-complex/main_simple.gpr deleted file mode 100644 index e2e925761..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/main_simple.gpr +++ /dev/null @@ -1,6 +0,0 @@ -project Main_Simple extends "lib" is - for Source_Dirs use ("src-main_simple"); - for Object_Dir use "obj-main_simple"; - for Library_Dir use "lib-main_simple"; - for Main use ("main.adb"); -end Main_Simple; diff --git a/testsuite/tests/instr-cov/gpr-complex/main_spec.gpr b/testsuite/tests/instr-cov/gpr-complex/main_spec.gpr deleted file mode 100644 index ffa5ac70a..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/main_spec.gpr +++ /dev/null @@ -1,5 +0,0 @@ -project Main_Spec extends "lib" is - for Source_Dirs use ("src-main_spec"); - for Object_Dir use "obj-main_spec"; - for Main use ("main.adb"); -end Main_Spec; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-lib/lib.gpr b/testsuite/tests/instr-cov/gpr-complex/src-lib/lib.gpr deleted file mode 100644 index f88001ac7..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/src-lib/lib.gpr +++ /dev/null @@ -1,4 +0,0 @@ -project Lib is - for Source_Dirs use ("."); - for Object_Dir use "obj"; -end Lib; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg-bar.adb b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg-bar.adb deleted file mode 100644 index f5189aa0d..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg-bar.adb +++ /dev/null @@ -1,4 +0,0 @@ -separate (Pkg) procedure Bar is -begin - null; -end Bar; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.adb b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.adb deleted file mode 100644 index fa79eb10a..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.adb +++ /dev/null @@ -1,9 +0,0 @@ -package body Pkg is - - procedure Foo is - begin - null; - end Foo; - - procedure Bar is separate; -end Pkg; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.ads b/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.ads deleted file mode 100644 index 52d41a411..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.ads +++ /dev/null @@ -1,4 +0,0 @@ -package Pkg is - procedure Foo; - procedure Bar; -end Pkg; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_body/main.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_body/main.adb deleted file mode 100644 index b8658aeb6..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/src-main_body/main.adb +++ /dev/null @@ -1,7 +0,0 @@ -with Pkg; - -procedure Main is -begin - Pkg.Foo; - Pkg.Bar; -end Main; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_body/pkg.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_body/pkg.adb deleted file mode 100644 index 3c7879b61..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/src-main_body/pkg.adb +++ /dev/null @@ -1,11 +0,0 @@ -with Ada.Text_IO; use Ada.Text_IO; - -package body Pkg is - - procedure Foo is - begin - Put_Line ("Hello from main-body"); - end Foo; - - procedure Bar is separate; -end Pkg; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_sep/main.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_sep/main.adb deleted file mode 100644 index b8658aeb6..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/src-main_sep/main.adb +++ /dev/null @@ -1,7 +0,0 @@ -with Pkg; - -procedure Main is -begin - Pkg.Foo; - Pkg.Bar; -end Main; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb deleted file mode 100644 index 5fab031ea..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb +++ /dev/null @@ -1,6 +0,0 @@ -with Ada.Text_IO; use Ada.Text_IO; - -separate (Pkg) procedure Bar is -begin - Put_Line ("Hello from main-sep"); -end Bar; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_simple/main.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_simple/main.adb deleted file mode 100644 index b8658aeb6..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/src-main_simple/main.adb +++ /dev/null @@ -1,7 +0,0 @@ -with Pkg; - -procedure Main is -begin - Pkg.Foo; - Pkg.Bar; -end Main; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_spec/main.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_spec/main.adb deleted file mode 100644 index 2d8a449a0..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/src-main_spec/main.adb +++ /dev/null @@ -1,8 +0,0 @@ -with Pkg; - -procedure Main is -begin - Pkg.Foo; - Pkg.Bar; - Pkg.Baz; -end Main; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_spec/pkg.ads b/testsuite/tests/instr-cov/gpr-complex/src-main_spec/pkg.ads deleted file mode 100644 index 953e0ab4b..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/src-main_spec/pkg.ads +++ /dev/null @@ -1,5 +0,0 @@ -package Pkg is - procedure Foo; - procedure Bar; - procedure Baz is null; -end Pkg; diff --git a/testsuite/tests/instr-cov/gpr-complex/test.opt b/testsuite/tests/instr-cov/gpr-complex/test.opt deleted file mode 100644 index 57b6bf345..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/test.opt +++ /dev/null @@ -1 +0,0 @@ -!native DEAD hardcoded project files without board information diff --git a/testsuite/tests/instr-cov/gpr-complex/test.py b/testsuite/tests/instr-cov/gpr-complex/test.py deleted file mode 100644 index 235241be6..000000000 --- a/testsuite/tests/instr-cov/gpr-complex/test.py +++ /dev/null @@ -1,121 +0,0 @@ -""" -This test checks that gnatcov correctly instruments projects with a complex -structure, and with unit parts implemented in different projects of the project -tree, some of them being instrumented while some of them not (through project -extension). -""" - -import os - -from e3.fs import cp - -from SCOV.instr import xcov_instrument -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -from SUITE.context import thistest -from SUITE.cutils import no_ext, Wdir -from SUITE.gprutils import GPRswitches -from SUITE.tutils import gprbuild, gprinstall - - -Wdir("tmp_") - -# Start by installing the library. Every main subproject depends on it. -install_dir = os.path.abspath("install") -cp(os.path.join("..", "src-lib"), ".", recursive=True) -lib_prj = os.path.join("src-lib", "lib.gpr") -xcov_instrument( - gprsw=GPRswitches(root_project=lib_prj), - covlevel="stmt", -) -gprbuild(lib_prj) -gprinstall( - lib_prj, - [ - f"--prefix={install_dir}", - "--src-subdirs=gnatcov-instr", - "--implicit-with=gnatcov_rts", - ], -) - -# Add the newly installed library to gprbuild's project lookup path -gpr_install_dir = os.path.join(install_dir, "share", "gpr") -old_path = os.environ.get("GPR_PROJECT_PATH", "") -if old_path: - new_path = "{}{}{}".format(gpr_install_dir, os.path.pathsep, old_path) -else: - new_path = gpr_install_dir -os.environ["GPR_PROJECT_PATH"] = new_path - - -def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): - cp(os.path.join("..", main_prj), ".", recursive=True) - cp(os.path.join("..", f"src-{no_ext(main_prj)}"), ".", recursive=True) - build_run_and_coverage( - gprsw=GPRswitches(root_project=os.path.join(main_prj)), - covlevel="stmt", - mains=["main"], - gpr_obj_dir=main_prj_obj_dir, - gpr_exe_dir=main_prj_obj_dir, - extra_coverage_args=[ - "--annotate=xcov", - "--externally-built-projects", - "--units=pkg", - ], - ) - check_xcov_reports("*.xcov", expected_xcov, main_prj_obj_dir) - - -# Try the simple case: the main project extends the library, but does not -# redefine anything. -thistest.log("== Simple case ==") -expected_xcov = {"pkg.adb.xcov": {"+": {5}}, "pkg-bar.adb.xcov": {"+": {3}}} -build_run_cov_and_check( - "main_simple.gpr", - main_prj_obj_dir="obj-main_simple", - expected_xcov=expected_xcov, -) - -# Now the main project defines an alternate body. TODO! as we reinstrument the -# whole unit if a part of it was redefined (including the parts that were not -# redefined), we end up instrumenting the instrumented version for sources -# belonging to the library. We should fix this (and adjust coverage -# expectations) if possible. -thistest.log("== Redefining Pkg body ==") -expected_xcov = {"pkg.adb.xcov": {"+": {7}}, "pkg-bar.adb.xcov": {"+": {4}}} -# Should be: {"pkg.adb.xcov": {"+": {7}}, "pkg-bar.adb.xcov": {"+": {5}}} -build_run_cov_and_check( - "main_body.gpr", - main_prj_obj_dir="obj-main_body", - expected_xcov=expected_xcov, -) - - -# Now the main project defines an alternate separate. -thistest.log("== Redefining Pkg.Bar separate ==") -expected_xcov = {"pkg.adb.xcov": {"+": {6}}, "pkg-bar.adb.xcov": {"+": {5}}} -# Should be: {"pkg.adb.xcov": {"+": {5}}, "pkg-bar.adb.xcov": {"+": {5}}} -build_run_cov_and_check( - "main_sep.gpr", - main_prj_obj_dir="obj-main_sep", - expected_xcov=expected_xcov, -) - -# Now the main project defines an alternate spec. -thistest.log("== Redefining Pkg spec ==") -expected_xcov = { - "pkg.adb.xcov": {"+": {6}}, - "pkg-bar.adb.xcov": {"+": {4}}, - "pkg.ads.xcov": {"+": {4}}, -} -# Should be: { -# "pkg.adb.xcov": {"+": {5}}, -# "pkg-bar.adb.xcov": {"+": {3}}, -# "pkg.ads.xcov": {"+": {4}}, -# } -build_run_cov_and_check( - "main_spec.gpr", - main_prj_obj_dir="obj-main_spec", - expected_xcov=expected_xcov, -) - -thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb b/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb index f53e6de38..6c40b1da8 100644 --- a/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb +++ b/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb @@ -1,11 +1,11 @@ with Ada.Command_Line; -with GCVRT.P; +with GNATcov_RTS.Buffers.Lists.P; with GNATcov_RTS.Traces.Output.Files; procedure Covdump is begin GNATcov_RTS.Traces.Output.Files.Write_Trace_File - (Buffers_Groups => GCVRT.P.List, + (Buffers_Groups => GNATcov_RTS.Buffers.Lists.P.List, Filename => Ada.Command_Line.Command_Name & ".srctrace"); end Covdump; diff --git a/testsuite/tests/instr-cov/orphan-unit/test.py b/testsuite/tests/instr-cov/orphan-unit/test.py index 1880b8f65..60d3db495 100644 --- a/testsuite/tests/instr-cov/orphan-unit/test.py +++ b/testsuite/tests/instr-cov/orphan-unit/test.py @@ -27,7 +27,7 @@ thistest.fail_if_not_equal( '"gnatcov instrument" output', ( - "warning: While instrumenting pkg-child.ads...\n" + "warning: While instrumenting pkg-child.adb...\n" "warning: Cannot find required source file: pkg.ads" ), contents_of("instrument.log").strip(), diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index d7a00b0af..7ed129754 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -176,15 +176,15 @@ ifdef INSTRUMENTED # instrumented as a main to compile gnatcov32, running gnatcov32 will not # dump execution traces. - gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov64 + gnatcov instrument -P gnatcov.gpr -XPART=gnatcov64 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 \ --src-subdirs=gnatcov-instr - gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov32 + gnatcov instrument -P gnatcov.gpr -XPART=gnatcov32 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov32 \ --src-subdirs=gnatcov-instr - gnatcov instrument -j0 -P gnatcov.gpr -XPART=driver + gnatcov instrument -P gnatcov.gpr -XPART=driver $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver \ --src-subdirs=gnatcov-instr else diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 56bdafe4b..1a355b49e 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -59,9 +59,7 @@ package Command_Line is Cmd_Scan_Objects, Cmd_Setup, - Cmd_Instrument_Project, - Cmd_Instrument_Source, - Cmd_Instrument_Main); + Cmd_Instrument); -- Set of commands we support. More complete descriptions below. type Bool_Options is @@ -115,7 +113,6 @@ package Command_Line is Opt_Dump_Channel, Opt_Dump_Filename_Env_Var, Opt_Dump_Filename_Prefix, - Opt_Dump_Filename_Tag, Opt_Ada, Opt_Dump_Units_To, Opt_Timezone, @@ -124,15 +121,6 @@ package Command_Line is Opt_Path_Count_Limit, Opt_Install_Name, Opt_Runtime_Project, - Opt_Lang, - Opt_Parallelism_Level, - Opt_Compiler_Driver, - Opt_Spec_Suffix, - Opt_Body_Suffix, - Opt_Dot_Replacement, - Opt_Gnatem, - Opt_Gnatec, - Opt_Project_Name, Opt_Source_Root); -- Set of string options we support. More complete descriptions below. @@ -157,14 +145,9 @@ package Command_Line is Opt_Restricted_To_Languages, Opt_Annotation_Format, Opt_C_Opts, - Opt_CPP_Opts, - Opt_Files, - Opt_Runtime_Dir); + Opt_CPP_Opts); -- Set of string list options we support. More complete descriptions below. - subtype Cmd_Instrument is Command_Type - range Cmd_Instrument_Project .. Cmd_Instrument_Main; - package Parser is new Argparse (Command_Type, Bool_Options, String_Options, String_List_Options); use Parser; @@ -355,24 +338,11 @@ package Command_Line is & " instrumentation and set up default arguments" & " for future ""gnatcov instrument"" invocations.", Internal => False), - Cmd_Instrument_Project => Create + Cmd_Instrument => Create (Name => "instrument", Description => ("Instrument the given project and produce the" & " associated Source Instrumentation Data files."), - Internal => False), - Cmd_Instrument_Source => Create - (Name => "instrument-source", - Description => "Instrument the given files, all belonging to the" - & " same unit.", - Pattern => "[FILES]", - Internal => True), - Cmd_Instrument_Main => Create - (Name => "instrument-main", - Description => "Insert dump trigger code in the the given main file," - & " dumping coverage buffers of all of the specified" - & " files (through the --files switch).", - Pattern => "--files= [MAIN]", - Internal => True)); + Internal => False)); Bool_Infos : constant Bool_Option_Info_Array := (Opt_Verbose => Create @@ -386,7 +356,7 @@ package Command_Line is & " transitively imported project.", Commands => (Cmd_Run | Cmd_Coverage - | Cmd_Instrument_Project + | Cmd_Instrument | Cmd_Dump_CFG => True, others => False), Internal => False), @@ -397,7 +367,7 @@ package Command_Line is & " transitively imported projects are not considered.", Commands => (Cmd_Run | Cmd_Coverage - | Cmd_Instrument_Project + | Cmd_Instrument | Cmd_Dump_CFG => True, others => False), Internal => False), @@ -495,10 +465,7 @@ package Command_Line is Help => "Valid only when --dump-channel=bin-file. Create simple" & " filenames for source trace files (no PID/timestamp" & " variations).", - Commands => (Cmd_Setup - | Cmd_Instrument_Project - | Cmd_Instrument_Main => True, - others => False), + Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), Internal => False), Opt_Allow_Mix_Trace_Kind => Create @@ -559,13 +526,10 @@ package Command_Line is Pattern => "[GPR]", Help => "Use GPR as root project to locate SCOs, select" & " units to analyze and find default options.", - Commands => (Cmd_Setup - | Cmd_Instrument_Source - | Cmd_Instrument_Main => False, - others => True), + Commands => (Cmd_Setup => False, others => True), At_Most_Once => True, Internal => False), - Opt_Subdirs => Create + Opt_Subdirs => Create (Long_Name => "--subdirs", Pattern => "[SUBDIR]", Help => "When using project files, look for ALI/SID files in" @@ -624,9 +588,7 @@ package Command_Line is Pattern => "[SUBDIR]", Help => "Subdirectory where XCOV or HTML report files should" & " be produced.", - Commands => (Cmd_Coverage - | Cmd_Instrument_Source - | Cmd_Instrument_Main => True, others => False), + Commands => (Cmd_Coverage => True, others => False), At_Most_Once => False, Internal => False), Opt_Tag => Create @@ -791,10 +753,7 @@ package Command_Line is & " to dump a base64 trace on the standard output" & " using Ada.Text_IO. This is the preferred channel" & " for non-native programs.", - Commands => (Cmd_Setup - | Cmd_Instrument_Project - | Cmd_Instrument_Main => True, - others => False), + Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), At_Most_Once => False, Internal => False, Pattern => "bin-file|base64-stdout"), @@ -803,31 +762,14 @@ package Command_Line is Help => "Valid only when --dump-channel=bin-file. Name of the" & " environment variable which, if set, contains the" & " filename for created source traces.", - Commands => (Cmd_Setup - | Cmd_Instrument_Project - | Cmd_Instrument_Main => True, - others => False), + Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), At_Most_Once => False, Internal => False), Opt_Dump_Filename_Prefix => Create (Long_Name => "--dump-filename-prefix", Help => "Valid only when --dump-channel=bin-file. Select a" & " filename prefix for created source traces.", - Commands => (Cmd_Setup - | Cmd_Instrument_Project - | Cmd_Instrument_Main => True, - others => False), - At_Most_Once => False, - Internal => False), - - Opt_Dump_Filename_Tag => Create - (Long_Name => "--dump-filename-tag", - Help => "Valid only when --dump-channel=bin-file. Select a" - & " filename tag for created source traces.", - Commands => (Cmd_Setup - | Cmd_Instrument_Project - | Cmd_Instrument_Main => True, - others => False), + Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), At_Most_Once => False, Internal => False), @@ -936,107 +878,6 @@ package Command_Line is At_Most_Once => False, Internal => False), - Opt_Lang => Create - (Long_Name => "--lang", - Pattern => "[C|C++|Ada]", - Help => "Language for the given compilation unit", - Commands => (Cmd_Instrument_Main | Cmd_Instrument_Source => True, - others => False), - At_Most_Once => False, - Internal => True), - - Opt_Parallelism_Level => Create - (Short_Name => "-j", - Long_Name => "--jobs", - Pattern => "POSITIVE", - Help => - "Maximal number of concurrently running tasks. Number of processors" - & " of the machine if set to 0. Defaults to 1.", - Commands => (Cmd_Instrument_Project => True, others => False), - At_Most_Once => False, - Internal => False), - - Opt_Compiler_Driver => Create - (Long_Name => "--compiler-driver", - Pattern => "NAME", - Help => - "Compiler driver used to compile the source (e.g. gcc). This is" - & " used when instrumenting a C/C++ source, to retrieve builtin" - & " macros that may modify the file preprocessing.", - Commands => - (Cmd_Instrument_Source | Cmd_Instrument_Main => True, - others => False), - At_Most_Once => False, - Internal => True), - - Opt_Body_Suffix => Create - (Long_Name => "--body-suffix", - Pattern => "NAME", - Help => - "Body suffix for source files created by the instrumenter for the" - & " instrumentation of a source", - Commands => - (Cmd_Instrument_Source | Cmd_Instrument_Main => True, - others => False), - At_Most_Once => False, - Internal => True), - - Opt_Spec_Suffix => Create - (Long_Name => "--spec-suffix", - Pattern => "NAME", - Help => - "Spec suffix for source files created by the instrumenter for the" - & " instrumentation of a source", - Commands => - (Cmd_Instrument_Source | Cmd_Instrument_Main => True, - others => False), - At_Most_Once => False, - Internal => True), - - Opt_Dot_Replacement => Create - (Long_Name => "--dot-replacement", - Pattern => "NAME", - Help => - "Dot replacement for source files created by the instrumenter for" - & " the instrumentation of a source", - Commands => - (Cmd_Instrument_Source | Cmd_Instrument_Main => True, - others => False), - At_Most_Once => False, - Internal => True), - - Opt_Gnatem => Create - (Long_Name => "--gnatem", - Pattern => "NAME", - Help => - "Name of the file containing unit dependencies in the GNAT format.", - Commands => - (Cmd_Instrument_Source | Cmd_Instrument_Main => True, - others => False), - At_Most_Once => False, - Internal => True), - - Opt_Gnatec => Create - (Long_Name => "--gnatec", - Pattern => "NAME", - Help => - "Name of the file containing configuration pragmas.", - Commands => - (Cmd_Instrument_Source | Cmd_Instrument_Main => True, - others => False), - At_Most_Once => False, - Internal => True), - - Opt_Project_Name => Create - (Long_Name => "--project-name", - Pattern => "NAME", - Help => - "Name of the root project, without its gpr extension.", - Commands => - (Cmd_Instrument_Main => True, others => False), - At_Most_Once => False, - Internal => True), - Opt_Source_Root => Create (Long_Name => "--source-root", Pattern => "PATH", @@ -1059,10 +900,7 @@ package Command_Line is Pattern => "[GPR|@LISTFILE]", Help => "Focus on specific projects within the transitive" & " closure reachable from the root designated by -P.", - Commands => (Cmd_Setup - | Cmd_Instrument_Source - | Cmd_Instrument_Main => False, - others => True), + Commands => (Cmd_Setup => False, others => True), Internal => False), Opt_Scenario_Var => Create (Short_Name => "-X", @@ -1113,8 +951,8 @@ package Command_Line is | Cmd_Coverage | Cmd_Scan_Decisions | Cmd_Map_Routines - | Cmd_Instrument_Project => True, - others => False), + | Cmd_Instrument => True, + others => False), Internal => False), Opt_SID => Create (Long_Name => "--sid", @@ -1122,8 +960,7 @@ package Command_Line is Help => "Load Source Instrumentation Data from FILE for this" & " operation; or do that for each file listed in" & " LISTFILE.", - Commands => (Cmd_Coverage | Cmd_Instrument_Source => True, - others => False), + Commands => (Cmd_Coverage => True, others => False), Internal => False), Opt_Routines => Create (Long_Name => "--routines", @@ -1205,19 +1042,10 @@ package Command_Line is & " Supports globbing patterns.", Commands => (Cmd_Coverage | Cmd_Map_Routines - | Cmd_Instrument_Project => True, - others => False), + | Cmd_Instrument => True, + others => False), Internal => False), - Opt_Files => Create - (Long_Name => "--files", - Pattern => "[FILE|@LISTFILE]", - Help => "Specify a list of source files of interest by their" - & " full name.", - Commands => (Cmd_Instrument_Source | Cmd_Instrument_Main => True, - others => False), - Internal => True), - Opt_Shared_Object => Create (Long_Name => "--shared-object", Short_Name => "-L", @@ -1242,13 +1070,12 @@ package Command_Line is (Long_Name => "--restricted-to-languages", Pattern => "[LANGUAGE|LIST|@LISTFILE]", Help => - "Restrict the set of languages for instrumentation. Supports Ada, C" - & " and C++. As C++ support is still in beta state, the default is" - & " --restricted-to-languages=Ada,C. To enable C++, pass" - & " --restricted-to-languages=Ada,C,C++.", - Commands => (Cmd_Setup - | Cmd_Instrument_Project => True, - others => False), + "Restrict the set of languages for instrumentation. Supports Ada" + & " and C. As C support is still in beta state, the default is" + & " --restricted-to-languages=Ada. To enable both, pass" + & " --restricted-to-languages=Ada,C.", + Commands => (Cmd_Setup | Cmd_Instrument => True, + others => False), Internal => False, Accepts_Comma_Separator => True), Opt_Annotation_Format => Create @@ -1282,17 +1109,7 @@ package Command_Line is "List of additional compiler switches to analayze C++ source" & " files.", Commands => (Cmd_Instrument => True, others => False), - Internal => False), - - Opt_Runtime_Dir => Create - (Long_Name => "--runtime-dir", - Pattern => "NAME", - Help => - "Directories containing the compiler runtime sources.", - Commands => - (Cmd_Instrument_Source | Cmd_Instrument_Main => True, - others => False), - Internal => True) + Internal => False) ); procedure Bool_Callback diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 1d1383175..58527f599 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -20,8 +20,8 @@ with Ada.Characters.Latin_1; 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.Strings.Fixed; with Ada.Strings.Unbounded; with Ada.Tags; with Ada.Unchecked_Deallocation; @@ -221,11 +221,26 @@ package body Coverage.Source is -- 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); + (Key_Type => Project_Unit, Element_Type => Ignored_Sources_Vector_Access); + -- Map units of interest to the list of associated ignored source files Ignored_SF_Map : Unit_To_Ignored_Maps.Map; - -- Map units of interest to the list of associated ignored source files + + function Unit_Name_For_Subunit (Qualified_Name : String) return String; + -- Return the unit name for the subunit whose name is Qualified_Name. + -- For instance, if foo-test.adb is a subunit for package Foo, + -- GNATCOLL.Projects should give us Foo.Test as a unit name, and this + -- function will return Foo. + -- + -- As a safeguard, this checks that the result is the name of a unit of + -- interest: subunits cannot be units of interest. + -- + -- If it can't be determined that the source file belongs to a unit of + -- interest, the empty string will be returned, and a warning will be + -- emitted. + -- + -- Note that the Ada language rules guarantee that the name of the owning + -- unit is a prefix of the name of its subunits. -------------------------- -- Basic_Block_Has_Code -- @@ -268,13 +283,54 @@ package body Coverage.Source is -- Add_Unit -- -------------- - procedure Add_Unit (Unit : Compilation_Unit) is + procedure Add_Unit (Unit : Project_Unit) is begin if not Unit_List_Invalidated then Unit_List.Include (Unit); end if; end Add_Unit; + --------------------------- + -- Unit_Name_For_Subunit -- + --------------------------- + + function Unit_Name_For_Subunit (Qualified_Name : String) return String + is + use Ada.Strings.Fixed; + First : constant Natural := Qualified_Name'First; + Sep : Natural := Qualified_Name'Last; + begin + loop + Sep := Index (Source => Qualified_Name, + Pattern => ".", + From => Sep, + Going => Ada.Strings.Backward); + + if Unit_List.Contains + (Project_Unit' + (Language => Unit_Based_Language, + Unit_Name => + US.To_Unbounded_String + (Qualified_Name (First .. Sep - 1)))) + then + return Qualified_Name (First .. Sep - 1); + end if; + exit when Sep = 0; + + -- Move past '.' character to start searching again + + Sep := Sep - 1; + end loop; + + -- If we got here, then there is no unit of interest whose name is a + -- prefix of the name of the subunit we are processing. + + Report (Msg => "Could not find the name of the owning unit of subunit " + & Qualified_Name & " among the units of interest", + Kind => Warning); + return ""; + end Unit_Name_For_Subunit; + ------------------------------------------- -- Compute_Unit_Name_For_Ignored_Sources -- ------------------------------------------- @@ -297,7 +353,6 @@ package body Coverage.Source is (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); @@ -307,8 +362,26 @@ package body Coverage.Source is begin if FI /= null and then not FI.Unit.Known then declare - Unit : constant Compilation_Unit := - To_Compilation_Unit (File); + use type GNATCOLL.Projects.Unit_Parts; + + Language : constant Some_Language := + To_Language (File.Language); + + -- For Ada, get the unit name for the compilation unit (no + -- subunit names). For file-based languages, + -- GNATCOLL.Projects.Unit_Name returns an empty string: we need + -- to get the file base name instead. + + Unit_Name : constant String := + (case Language is + when Ada_Language => + (if File.Unit_Part = GNATCOLL.Projects.Unit_Separate + then Unit_Name_For_Subunit (File.Unit_Name) + else File.Unit_Name), + when others => Get_Simple_Name (SFI)); + + Unit : constant Project_Unit := + To_Project_Unit (Unit_Name, Project, Language); begin Consolidate_Source_File_Unit (SFI, Unit); end; @@ -348,6 +421,13 @@ package body Coverage.Source is if FI.Kind = Source_File and then FI.Ignore_Status in Always .. Sometimes then + -- If FI is a separate (Ada) or a header file (C/C++), it is not a + -- unit of interest itself: only the compilation unit is, so + -- Is_Unit_Of_Interest (FI.Full_Name.all) return False. Still, the + -- unit that owns this file is supposed to be known by now, so it + -- should be valid to access FI.Unit.Name (i.e. FI.Unit.Known + -- should be True). + if not Ignored_SF_Map.Contains (FI.Unit.Name) then Vec := new Ignored_Sources_Vector.Vector; Ignored_SF_Map.Insert (FI.Unit.Name, Vec); @@ -369,8 +449,7 @@ package body Coverage.Source is -------------------------- procedure Iterate_On_Unit_List - (Process_Unit : not null access procedure - (Name : Compilation_Unit); + (Process_Unit : not null access procedure (Name : Project_Unit); Process_Source_File : not null access procedure (FI : File_Info)) is begin @@ -393,7 +472,7 @@ package body Coverage.Source 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); + procedure Print_Unit_Name (Unit : Project_Unit); -- Print the unit name ------------------------ @@ -413,14 +492,9 @@ package body Coverage.Source is -- Print_Unit_Name -- --------------------- - procedure Print_Unit_Name (Unit : Compilation_Unit) is + procedure Print_Unit_Name (Unit : Project_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; + Put_Line (File, +Unit.Unit_Name); end Print_Unit_Name; -- Start of processing for Report_Units @@ -446,7 +520,7 @@ package body Coverage.Source is if not Unit_List_Invalidated then Ada.Containers.Count_Type'Output (CSS, Unit_List.Length); for N of Unit_List loop - Compilation_Unit'Output (CSS, N); + Project_Unit'Output (CSS, N); end loop; end if; end if; @@ -600,7 +674,7 @@ package body Coverage.Source is end if; US.Unbounded_String'Read (CLS, Dummy); else - Unit_List.Include (Compilation_Unit'Input (CLS)); + Unit_List.Include (Project_Unit'Input (CLS)); end if; end loop; end if; @@ -1707,7 +1781,7 @@ package body Coverage.Source is procedure Compute_Source_Coverage (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Part; + CU_Name : Compilation_Unit_Name; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 38c2b903e..1f0968fa2 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -52,7 +52,7 @@ package Coverage.Source is procedure Compute_Source_Coverage (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Part; + CU_Name : Compilation_Unit_Name; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; @@ -104,7 +104,7 @@ package Coverage.Source is -- message is used for logging purposes, so that users can find out why we -- cannot dump the list of units of interest. - procedure Add_Unit (Unit : Compilation_Unit); + procedure Add_Unit (Unit : Project_Unit); -- Add Unit to the list of units of interest. For convenience, do nothing -- if it is invalid. @@ -117,8 +117,7 @@ package Coverage.Source is -- unit names, linking them to the list of ignored source files. procedure Iterate_On_Unit_List - (Process_Unit : not null access procedure - (Name : Compilation_Unit); + (Process_Unit : not null access procedure (Name : Project_Unit); Process_Source_File : not null access procedure (FI : File_Info)) with Pre => Unit_List_Is_Valid; -- Call Process_Unit for each unit of interest, passing to it the name of diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 4bd99d7a8..050504b88 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -621,7 +621,7 @@ package body Files_Table is ---------------------------------- procedure Consolidate_Source_File_Unit - (Index : Valid_Source_File_Index; New_Unit : Compilation_Unit) + (Index : Valid_Source_File_Index; New_Unit : Project_Unit) is use Ada.Strings.Unbounded; FI : File_Info renames Files_Table.Element (Index).all; @@ -1890,7 +1890,7 @@ package body Files_Table is Any_Ignore_Status'Write (S, FI.Ignore_Status); Boolean'Write (S, FI.Unit.Known); if FI.Unit.Known then - Compilation_Unit'Output (S, FI.Unit.Name); + Project_Unit'Output (S, FI.Unit.Name); end if; end if; end; @@ -2042,7 +2042,7 @@ package body Files_Table is if Unit_Known then -- Starting with the version 13 of checkpoints, - -- owning units are represented as Compilation_Unit + -- owning units are represented as Project_Unit -- values (they were mere strings before). Consider -- the owning unit unknown if we do not have recent -- formats. @@ -2055,7 +2055,7 @@ package body Files_Table is end; else FE.Unit := (Known => True, - Name => Compilation_Unit'Input (S)); + Name => Project_Unit'Input (S)); end if; end if; end; diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 9a9aafb29..729aea7ee 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -305,37 +305,46 @@ package Files_Table is -- option --ignore-source-files. Consolidation rules are described in -- procedure Consolidate_Ignore_Status. - type Compilation_Unit is record - Language : Any_Language_Kind; + type Project_Unit (Language : Any_Language_Kind := Unit_Based_Language) + is record Unit_Name : Ada.Strings.Unbounded.Unbounded_String; + + case Language is + when File_Based_Language => + Project_Name : Ada.Strings.Unbounded.Unbounded_String; + when others => + null; + end case; end record; - -- This record is used to uniquely identify a unit of any language - -- supported by gnatcov. The unique identifier, stored as Unit_Name is - -- the unit name for unit-based language, and the file fullname for - -- file-based languages. + -- To uniquely identify a unit in a project tree, we need its unit name (or + -- base name for a C unit). For file-based languages such as C or C++, we + -- might have homonym base file names in different projects so we keep + -- track of the project name in addition. use type Ada.Strings.Unbounded.Unbounded_String; - function Image (U : Compilation_Unit) return String is + function Image (U : Project_Unit) return String is (case U.Language is when Unit_Based_Language => To_Lower (Ada.Strings.Unbounded.To_String (U.Unit_Name)), when File_Based_Language => - Fold_Filename_Casing - (Ada.Strings.Unbounded.To_String (U.Unit_Name))); + Ada.Strings.Unbounded.To_String (U.Project_Name) + & ":" + & Fold_Filename_Casing + (Ada.Strings.Unbounded.To_String (U.Unit_Name))); - function "<" (L, R : Compilation_Unit) return Boolean is + function "<" (L, R : Project_Unit) return Boolean is (Image (L) < Image (R)); - function "=" (L, R : Compilation_Unit) return Boolean is + function "=" (L, R : Project_Unit) return Boolean is (Image (L) = Image (R)); package Unit_Sets is new Ada.Containers.Ordered_Sets - (Element_Type => Compilation_Unit); + (Element_Type => Project_Unit); type Owning_Unit (Known : Boolean := False) is record case Known is - when True => Name : Compilation_Unit; + when True => Name : Project_Unit; when False => null; end case; end record; @@ -457,7 +466,7 @@ package Files_Table is (Index : Source_File_Index) return File_Info_Access; procedure Consolidate_Source_File_Unit - (Index : Valid_Source_File_Index; New_Unit : Compilation_Unit) + (Index : Valid_Source_File_Index; New_Unit : Project_Unit) with Pre => Get_File (Index).Kind = Source_File; -- Update the unit name info for the source file represented by Index. -- Does nothing if the new unit name is the empty string. diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 4953f453c..2d85786dc 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -27,8 +27,6 @@ with GNAT.OS_Lib; with GNAT.Regexp; with GNAT.Strings; use GNAT.Strings; -with System.Multiprocessors; - with Snames; with ALI_Files; @@ -56,14 +54,10 @@ with Decision_Map; use Decision_Map; with Disassemble_Insn_Properties; with Execs_Dbase; use Execs_Dbase; with Files_Table; use Files_Table; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Inputs; use Inputs; -with Instrument; -with Instrument.Common; use Instrument.Common; -with Instrument.Config; -with Instrument.Main; -with Instrument.Projects; -with Instrument.Source; with Instrument.Input_Traces; +with Instrument; use Instrument; with Object_Locations; with Outputs; use Outputs; with Perf_Counters; @@ -104,7 +98,6 @@ procedure GNATcov_Bits_Specific is Checkpoints_Inputs : Inputs.Inputs_Type; SID_Inputs : Inputs.Inputs_Type; Ignored_Source_Files : Inputs.Inputs_Type; - Files_Of_Interest : Inputs.Inputs_Type; Source_Rebase_Inputs : Inputs.Inputs_Type; Source_Search_Inputs : Inputs.Inputs_Type; Text_Start : Pc_Type := 0; @@ -488,8 +481,6 @@ procedure GNATcov_Bits_Specific is Copy_Arg_List (Opt_Checkpoint, Checkpoints_Inputs); Copy_Arg_List (Opt_Ignore_Source_Files, Ignored_Source_Files); - Copy_Arg_List (Opt_Files, Files_Of_Interest); - Switches.Files_Of_Interest := To_String_Set (Files_Of_Interest); -- Compute the languages for which we want coverage analysis, or enable -- just the default ones. @@ -1038,32 +1029,6 @@ procedure GNATcov_Bits_Specific is Copy_Arg_List (Opt_C_Opts, C_Opts); Copy_Arg_List (Opt_CPP_Opts, CPP_Opts); - if Args.String_Args (Opt_Parallelism_Level).Present then - declare - Parallelism_Level : Natural; - begin - begin - Parallelism_Level := - Natural'Value - (+Args.String_Args (Opt_Parallelism_Level).Value); - exception - when Constraint_Error => - Fatal_Error ("Parallelism level (-j or --jobs)" - & " must be a natural integer value"); - end; - - -- Limit the number of spawned subprocesses to the number - -- of cores. - - if Parallelism_Level = 0 then - Instrument.Parallelism_Level := - Positive (System.Multiprocessors.Number_Of_CPUs); - else - Instrument.Parallelism_Level := Parallelism_Level; - end if; - end; - end if; - when others => null; end case; @@ -1295,7 +1260,7 @@ begin Gargs => Args.String_List_Args (Opt_Gargs)); end; - when Cmd_Instrument_Project => + when Cmd_Instrument => if not Is_Project_Loaded then Fatal_Error ("instrumentation requires a project file;" & " please use the -P option"); @@ -1322,8 +1287,10 @@ begin -- Matcher for the source files to ignore Language_Version : Any_Language_Version; - pragma Unreferenced (Language_Version); + Mains : String_Vectors.Vector renames Args.Remaining_Args; + -- Treat remaining command line arguments as a list of source + -- files to be processed as mains. begin Create_Matcher (Ignored_Source_Files, Matcher, Has_Matcher); @@ -1355,62 +1322,30 @@ begin ("(selected runtime from " & (+Setup_Cfg.Project_File) & ")"); end if; + -- Even though instrumentation does not create any traces, the + -- structure of a SID file is basically a checkpoint, so it has a + -- Trace_Kind field in its header. Instead of leaving it to + -- Unknown (default value) mark it as Source_Trace_File so that + -- when the .sid file is loaded, it will set gnatcov in + -- "source trace mode" and it will be rejected if binary traces + -- have already been loaded. + + Update_Current_Trace_Kind (Source_Trace_File); + if Analyze_Entry_Barriers then Warn ("With source traces, entry barrier analysis (enabled" & " with --analyze-entry-barriers) is only supported when" & " when using a full runtime profile. In particular," - & " enabling this option with a ravenscar profile will" + & " enabeling this option with a ravenscar profile will" & " result in invalid code being emitted."); end if; - Instrument.Projects + Instrument.Instrument_Units_Of_Interest (Dump_Config => Dump_Config, + Language_Version => Language_Version, Ignored_Source_Files => (if Has_Matcher then Matcher'Access else null), - Mains => Args.Remaining_Args); - end; - - when Cmd_Instrument_Source => - -- For the instrument-source command, and for the instrument-main, - -- we do not check the command-line semantics as these commands are - -- internal and spawned by a gnatcov main process. They are thus by - -- default well-formed, and if they are not, it is a gnatcov bug. - -- - -- The unit to instrument is the trailing argument - - declare - Instrumenter : Language_Instrumenter'Class := Instrument.Config; - begin - Instrument.Source - (Instrumenter => Instrumenter, - Files_Of_Interest => Switches.Files_Of_Interest, - Prj => Instrument.Load_From_Command_Line, - Unit_Name => +Args.Remaining_Args.First_Element, - SID_Name => - +Args.String_List_Args (Opt_SID).First_Element); - end; - - when Cmd_Instrument_Main => - declare - -- The dump config is loaded from the command line. The - -- implementation of the main instrumentation process assumes that - -- it is fully explicited, i.e. that nothing is left as default. - - Dump_Config : constant Any_Dump_Config := - Load_Dump_Config (Any_Dump_Config'(others => <>)); - - -- Trailing argument is the main to instrument - - Main_Filename : constant String := - +Args.Remaining_Args.First_Element; - - Instrumenter : Language_Instrumenter'Class := Instrument.Config; - begin - Instrument.Main - (Instrumenter, - Dump_Config, - Main_Filename, - Instrument.Load_From_Command_Line); + Mains => Mains); end; when Cmd_Scan_Objects => @@ -1759,9 +1694,27 @@ begin Check_User_Provided_SCOs; - -- Build the list of units of interest from project files + -- Build the list of units of interest from project files option + + declare + procedure Add_Unit (Unit : Project_Unit; Is_Stub : Boolean); + -- Add Name to the list of names for units of interest. Do nothing + -- if this is a stub for a unit-based language, since such stubs + -- are implicitly part of another unit of interest. + + -------------- + -- Add_Unit -- + -------------- - Enumerate_Units_Of_Interest (Add_Unit'Access); + procedure Add_Unit (Unit : Project_Unit; Is_Stub : Boolean) is + begin + if not Is_Stub or else Unit.Language = File_Based_Language then + Add_Unit (Unit); + end if; + end Add_Unit; + begin + Enumerate_Units_Of_Interest (Add_Unit'Access); + end; -- Load routines from command line diff --git a/tools/gnatcov/inputs.adb b/tools/gnatcov/inputs.adb index 2b4072985..300aac1cd 100644 --- a/tools/gnatcov/inputs.adb +++ b/tools/gnatcov/inputs.adb @@ -262,22 +262,6 @@ package body Inputs is return Res; end To_String_Vector; - ------------------- - -- To_String_Set -- - ------------------- - - function To_String_Set - (Inputs : Inputs_Type) return String_Sets.Set - is - use String_Sets; - Res : Set; - begin - for IE of Inputs loop - Res.Include (+IE.Name.all); - end loop; - return Res; - end To_String_Set; - -------------------- -- Create_Matcher -- -------------------- diff --git a/tools/gnatcov/inputs.ads b/tools/gnatcov/inputs.ads index 3aa804365..b53251ec3 100644 --- a/tools/gnatcov/inputs.ads +++ b/tools/gnatcov/inputs.ads @@ -79,10 +79,6 @@ package Inputs is (Inputs : Inputs_Type) return String_Vectors.Vector; -- Convert an inputs list into a String_Vectors.Vector - function To_String_Set - (Inputs : Inputs_Type) return String_Sets.Set; - -- Convert an inputs list into a String_Sets.Set - procedure Create_Matcher (Pattern_List : String_Vectors.Vector; Matcher : out GNAT.Regexp.Regexp; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 6cdf086ca..39516a36d 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -18,14 +18,14 @@ with Ada.Characters.Conversions; use Ada.Characters.Conversions; with Ada.Characters.Handling; -with Ada.Directories; with Ada.Containers; use Ada.Containers; +with Ada.Directories; with Ada.Exceptions; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Wide_Wide_Fixed; pragma Warnings (Off, "* is an internal GNAT unit"); with Ada.Strings.Wide_Wide_Unbounded.Aux; pragma Warnings (On, "* is an internal GNAT unit"); -with Ada.Text_IO; use Ada.Text_IO; with Langkit_Support; with Langkit_Support.Slocs; use Langkit_Support.Slocs; @@ -39,14 +39,18 @@ use Libadalang.Generic_API.Introspection; with Libadalang.Sources; use Libadalang.Sources; with GNATCOLL.Utils; +with GNATCOLL.VFS; with ALI_Files; use ALI_Files; with Coverage_Options; use Coverage_Options; with Coverage; use Coverage; with Diagnostics; use Diagnostics; +with Files_Table; use Files_Table; +with Instrument.Ada_Unit_Provider; with Namet; use Namet; with Outputs; use Outputs; with Paths; use Paths; +with Project; with SCOs; with Slocs; with Snames; use Snames; @@ -100,14 +104,6 @@ package body Instrument.Ada_Unit is -- Import the low level SCO in UIC marked as non-instrumented in the high -- level non-instrumented SCO_Id sets. - procedure Find_Ada_Units - (Instrumenter : in out Ada_Instrumenter_Type; - Filename : String; - Process_Unit : access procedure (Filename : String)); - -- Consider that Filename is a source file to instrument (i.e. a unit of - -- interest) and call Process_Unit for all compilation units that must be - -- instrumented with it (i.e. related subunits, if present). - ----------------------- -- To_Qualified_Name -- ----------------------- @@ -923,7 +919,7 @@ package body Instrument.Ada_Unit is function Has_Matching_Pragma_For_Unit (Context : Analysis_Context; - Unit : LAL.Compilation_Unit; + Unit : Compilation_Unit; Filter : access function (Node : Pragma_Node) return Boolean) return Boolean; -- Return whether Filter return True on at least one configuration pragma @@ -934,18 +930,12 @@ package body Instrument.Ada_Unit is -- to get the analysis unit for System. Used to avoid emitting duplicate -- messages. - function Has_Unit - (Context : Analysis_Context; - Unit : String; - Part : Analysis_Unit_Kind) return Boolean; - -- Return whether the given unit exists - function Pragma_Restricts_Finalization (Prag_Node : Pragma_Node) return Boolean; -- Return True if Prag_Node imposes a restrictions on use of finalization function Finalization_Restricted_In_Unit - (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean; + (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean; -- Return True if Finalization is not available in this runtime, or if -- some control pragma restricts the usage of finalization in either Unit -- or the whole project. @@ -956,7 +946,7 @@ package body Instrument.Ada_Unit is -- Ada.Task_Termination and/or Ada.Task_Identification. function Task_Termination_Restricted - (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean; + (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean; -- Return True if tasking is not available in this runtime, or if some -- configuration pragma prevents the use of tasks and/or -- Ada.Task_Termination and/or Ada.Task_Identification in either the whole @@ -1043,8 +1033,7 @@ package body Instrument.Ada_Unit is -- to perform semantic analysis (so mandated by Ada), but which are not -- available. - procedure Create_LAL_Context - (Instrumenter : in out Ada_Instrumenter_Type'Class); + procedure Create_LAL_Context (Instrumenter : in out Ada_Instrumenter_Type); -- Create a new Libadalang analysis context for Instrumenter, assigning it -- to Instrumenter.Context. -- @@ -1054,7 +1043,7 @@ package body Instrument.Ada_Unit is -- used to instrument any source file yet. function Get_From_File - (Instrumenter : in out Ada_Instrumenter_Type'Class; + (Instrumenter : in out Ada_Instrumenter_Type; Filename : String) return Libadalang.Analysis.Analysis_Unit; -- Fetch the analysis unit for the given filename @@ -1076,8 +1065,8 @@ package body Instrument.Ada_Unit is procedure Start_Rewriting (Self : out Ada_Source_Rewriter'Class; - Instrumenter : in out Ada_Instrumenter_Type'Class; - Prj : Prj_Desc; + Instrumenter : in out Ada_Instrumenter_Type; + Info : in out Project_Info; Input_Filename : String); -- Start a rewriting session for the given Input_Filename. If the rewriting -- process is successful, the result will be written to a file in @@ -1124,17 +1113,22 @@ package body Instrument.Ada_Unit is -- the very beginning of each written source, these pragmas avoid this. procedure Initialize_Rewriting - (UIC : in out Ada_Unit_Inst_Context; - Instrumenter : Ada_Instrumenter_Type'Class); + (Instrumenter : Ada_Instrumenter_Type; + UIC : out Ada_Unit_Inst_Context; + Instrumented_Unit : Compilation_Unit_Name); -- Initialize a unit instrumentation context for the given unit to -- instrument. procedure Instrument_Source_File - (UIC : in out Ada_Unit_Inst_Context; - Filename : String; + (CU_Name : Compilation_Unit_Name; + Unit_Info : Instrumented_Unit_Info; + Prj_Info : in out Project_Info; Instrumenter : in out Ada_Instrumenter_Type; - Prj : Prj_Desc); - -- Generate the instrumented source corresponding to Filename + UIC : out Ada_Unit_Inst_Context); + -- Generate the instrumented source corresponding to CU_Name/Unit_Info. + -- + -- If the unit to instrument is also a main and the buffers dump trigger + -- is not manual, instrumented code will also dump the coverage buffers. ---------------------------------- -- Main instrumentation helpers -- @@ -1145,7 +1139,7 @@ package body Instrument.Ada_Unit is type Main_Instrumentation_Description (Synthetic : Boolean := False) is record - Main : Compilation_Unit_Part; + Main : Compilation_Unit_Name; -- Name of the compilation unit corresponding to the main body Controlled_Types_Available : Boolean; @@ -1184,8 +1178,8 @@ package body Instrument.Ada_Unit is -- subprogram instantiation (Synthetic => True). function Probe_Main - (Prj : Prj_Desc; - Dump_Config : Any_Dump_Config; + (Dump_Config : Any_Dump_Config; + Info : in out Project_Info; Rewriter : Ada_Source_Rewriter'Class) return Main_Instrumentation_Description; -- Given a rewriter for the main source, return a description of the main @@ -1201,7 +1195,7 @@ package body Instrument.Ada_Unit is procedure Expand_Main_Generic_Instantiation (Main : Generic_Subp_Instantiation; - Prj : Prj_Desc; + Info : in out Project_Info; Generic_Wrapper_Body_Filename : out Unbounded_String; Generic_Wrapper_Body : out Node_Rewriting_Handle; Prelude : out Node_Rewriting_Handle; @@ -1278,57 +1272,35 @@ package body Instrument.Ada_Unit is function Buffers_List_Unit (Project_Name : String) return Ada_Qualified_Name; -- Returns the name of the unit containing the array of coverage buffers. - -- It is named after the given project main name (e.g. if the - -- project p.gpr, its name is .). - - function Buffer_Unit - (Unit_Name : Ada_Qualified_Name) return Ada_Qualified_Name; - -- Given a file to instrument, return the name of the unit that holds - -- its coverage buffers (Coverage_Buffer_Type and - -- GNATcov_RTS_Coverage_Buffers records). + -- It is named after the root project name (e.g. if the root project is + -- p.gpr, its name is .). function Pure_Buffer_Unit - (Unit_Name : Ada_Qualified_Name) return Ada_Qualified_Name; + (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name; -- Given a unit to instrument, return the name of the unit that holds -- addresses to its coverage buffers. procedure Emit_Buffer_Unit - (Buffer_Unit : Compilation_Unit_Part; - Prj : Prj_Desc; - Unit : Files_Table.Compilation_Unit; - Unit_Bits : Allocated_Bits_Vectors.Vector; - CU_Names : CU_Name_Vectors.Vector; - CUs : CU_Id_Vectors.Vector); + (Info : in out Project_Info; UIC : Ada_Unit_Inst_Context'Class); -- Emit the unit to contain coverage buffers for the given instrumented -- unit. procedure Emit_Pure_Buffer_Unit - (PB_Unit : Compilation_Unit_Part; - Prj : Prj_Desc; - CU_Names : CU_Name_Vectors.Vector; - Language_Version : Unbounded_Wide_Wide_String; - Degenerate_Subprogram_Generics : Generic_Subp_Vectors.Vector); - -- Emit the unit to contain addresses for the coverage buffers of all of - -- the compilation unit parts in CU_Names. PB_Unit holds the name of - -- the pure buffer unit, which is generated in the output dir specified in - -- the project description Prj. - -- - -- See the documentation of the eponym fields of the Ada_Unit_Inst_Context - -- record for the Language_Version and Degenerate_Subprogram_Generics - -- parameters. + (Info : in out Project_Info; UIC : Ada_Unit_Inst_Context'Class); + -- Emit the unit to contain addresses for the coverage buffers procedure Emit_Dump_Helper_Unit (Dump_Config : Any_Dump_Config; - Instrumenter : Ada_Instrumenter_Type'Class; - Prj : Prj_Desc; - Main : Compilation_Unit_Part; + Info : in out Project_Info; + Main_Filename : String; + Main : Compilation_Unit_Name; Helper_Unit : out Ada_Qualified_Name; Override_Dump_Trigger : Any_Dump_Trigger := Manual; Has_Controlled : Boolean := False); -- Emit the unit to contain helpers to implement the automatic dump of - -- coverage buffers for the given Main unit. Prj must contain information - -- about the project that owns this main. Upon return, the name of this - -- helper unit is stored in Helper_Unit. + -- coverage buffers for the given Main unit implemented in Main_Filename. + -- Info must be the project that owns this main. Upon return, the name of + -- this helper unit is stored in Helper_Unit. -- -- If Override_Dump_Trigger is anything other than Manual, it will be used -- as a dump trigger instead of the one defined in IC.Dump_Config. @@ -4251,7 +4223,7 @@ package body Instrument.Ada_Unit is when Ada_Compilation_Unit => declare - CUN : constant LAL.Compilation_Unit := + CUN : constant Compilation_Unit := N.As_Compilation_Unit; CUN_Body : constant Ada_Node := CUN.F_Body; Is_Subunit : constant Boolean := @@ -4337,23 +4309,14 @@ package body Instrument.Ada_Unit is -- corresponding unit that contains coverage buffers. declare - Buffers_Unit : constant Node_Rewriting_Handle := - To_Nodes - (UIC.Rewriting_Context, UIC.Pure_Buffer_Unit.Unit); - With_Buffers_Clause : constant Node_Rewriting_Handle := - Create_From_Template - (UIC.Rewriting_Context, "with {};", - (1 => To_Nodes - (UIC.Rewriting_Context, Sys_Buffers)), - With_Clause_Rule); - With_PB_Clause : constant Node_Rewriting_Handle := + Buffers_Unit : constant Node_Rewriting_Handle := To_Nodes + (UIC.Rewriting_Context, UIC.Pure_Buffer_Unit.Unit); + With_Clause : constant Node_Rewriting_Handle := Create_From_Template (UIC.Rewriting_Context, "with {};", (1 => Buffers_Unit), With_Clause_Rule); begin - Append_Child (Handle (CUN.F_Prelude), - With_Buffers_Clause); - Append_Child (Handle (CUN.F_Prelude), With_PB_Clause); + Append_Child (Handle (CUN.F_Prelude), With_Clause); end; end; @@ -6505,14 +6468,14 @@ package body Instrument.Ada_Unit is procedure Start_Rewriting (Self : out Ada_Source_Rewriter'Class; - Instrumenter : in out Ada_Instrumenter_Type'Class; - Prj : Prj_Desc; + Instrumenter : in out Ada_Instrumenter_Type; + Info : in out Project_Info; Input_Filename : String) is Base_Filename : constant String := Ada.Directories.Simple_Name (Input_Filename); Output_Filename : constant String := - New_File (Prj, Base_Filename); + To_String (Info.Output_Dir) / Base_Filename; Unit : constant Analysis_Unit := Get_From_File (Instrumenter, Input_Filename); begin @@ -6583,23 +6546,22 @@ package body Instrument.Ada_Unit is declare Source_Name : constant String := To_String (N); begin - if not (GNATCOLL.Utils.Starts_With (Source_Name, "gnatcov_rts") - or else GNATCOLL.Utils.Starts_With (Source_Name, "gcvrt")) - then - -- If we have not done it yet, clarify which file we were - -- instrumenting when we noticed that the source file N was - -- missing. - - if Length (Self.Instrumented_File) > 0 then - Warn ("While instrumenting " - & To_String (Self.Instrumented_File) - & "..."); - Self.Instrumented_File := Null_Unbounded_String; - end if; - - Warn ("Cannot find required source file: " & Source_Name); + if GNATCOLL.Utils.Starts_With (Source_Name, "gnatcov_rts") then + return; end if; end; + + -- If we have not done it yet, clarify which file we were + -- instrumenting when we noticed that the source file N was missing. + + if Length (Self.Instrumented_File) > 0 then + Warn ("While instrumenting " + & To_String (Self.Instrumented_File) + & "..."); + Self.Instrumented_File := Null_Unbounded_String; + end if; + + Warn ("Cannot find required source file: " & To_String (N)); end; end Unit_Requested_Callback; @@ -6619,33 +6581,48 @@ package body Instrument.Ada_Unit is -- Create_LAL_Context -- ------------------------ - procedure Create_LAL_Context - (Instrumenter : in out Ada_Instrumenter_Type'Class) is + procedure Create_LAL_Context (Instrumenter : in out Ada_Instrumenter_Type) + is begin Instrumenter.Context := Create_Context - (Unit_Provider => - Create_Unit_Provider_Reference (Instrumenter.Provider), + (Unit_Provider => Instrumenter.Provider, Event_Handler => Instrumenter.Event_Handler); Instrumenter.Get_From_File_Count := 0; - -- Load configuration pragmas. TODO???: clarify what happens when there - -- is a local configuration pragma file. + -- Load configuration pragmas + -- TODO??? Remove the type convertion when the LAL API change for + -- VA07-037 makes it into stable-libadalang. - Libadalang.Config_Pragmas.Set_Mapping + Libadalang.Config_Pragmas.Import_From_Project (Instrumenter.Context, - Libadalang.Config_Pragmas.Config_Pragmas_Mapping' - (Global_Pragmas => - Instrumenter.Context.Get_From_File - (+Instrumenter.Config_Pragmas_Filename), - others => <>)); + GNATCOLL.Projects.Project_Tree (Project.Project.all)); end Create_LAL_Context; + ----------------------------- + -- Create_Ada_Instrumenter -- + ----------------------------- + + function Create_Ada_Instrumenter + (Language_Version : Any_Language_Version) return Ada_Instrumenter_Type + is + Provider : constant Unit_Provider_Reference := + Instrument.Ada_Unit_Provider.Create_Provider_From_Project; + + Instrumenter : Ada_Instrumenter_Type; + begin + Instrumenter.Provider := Provider; + Instrumenter.Event_Handler := Create_Missing_File_Reporter; + Create_LAL_Context (Instrumenter); + Instrumenter.Language_Version := Language_Version; + return Instrumenter; + end Create_Ada_Instrumenter; + ------------------- -- Get_From_File -- ------------------- function Get_From_File - (Instrumenter : in out Ada_Instrumenter_Type'Class; + (Instrumenter : in out Ada_Instrumenter_Type; Filename : String) return Libadalang.Analysis.Analysis_Unit is begin @@ -6677,50 +6654,33 @@ package body Instrument.Ada_Unit is -------------------------- procedure Initialize_Rewriting - (UIC : in out Ada_Unit_Inst_Context; - Instrumenter : Ada_Instrumenter_Type'Class) is + (Instrumenter : Ada_Instrumenter_Type; + UIC : out Ada_Unit_Inst_Context; + Instrumented_Unit : Compilation_Unit_Name) is begin + UIC.Instrumented_Unit := Instrumented_Unit; + UIC.Buffer_Unit := + CU_Name_For_Unit (Buffer_Unit (Instrumented_Unit), GPR.Unit_Spec); + UIC.Pure_Buffer_Unit := + CU_Name_For_Unit (Pure_Buffer_Unit (Instrumented_Unit), GPR.Unit_Spec); UIC.Rewriting_Context := Handle (Instrumenter.Context); declare RH : constant Rewriting_Handle := UIC.Rewriting_Context; E : Instrumentation_Entities renames UIC.Entities; - - function Indexed_Buffer - (Buffer_Kind : Ada_Qualified_Name) return Node_Rewriting_Handle; - -- Suffix Buffer_Kind with the buffer index for the currently - -- instrumented source file. See the comment for the package - -- Allocated_Bits_Vectors in Instrument.Common for more information. - - -------------------- - -- Indexed_Buffer -- - -------------------- - - function Indexed_Buffer - (Buffer_Kind : Ada_Qualified_Name) return Node_Rewriting_Handle - is - Buffer : constant Ada_Qualified_Name := - To_Qualified_Name ("Buffers_" & Img (E.Buffers_Index)) - & Buffer_Kind; - begin - return Create_From_Template - (Handle => RH, - Template => - To_Text (To_Ada (UIC.Pure_Buffer_Unit.Unit & Buffer)), - Arguments => (1 .. 0 => No_Node_Rewriting_Handle), - Rule => Expr_Rule); - end Indexed_Buffer; - begin E.Common_Buffers := To_Nodes (RH, Sys_Buffers); E.Unit_Buffers := To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit); - E.Statement_Buffer := Indexed_Buffer (Statement_Buffer_Name); + E.Statement_Buffer := + To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit & Statement_Buffer_Name); if Coverage.Enabled (Decision) or else MCDC_Coverage_Enabled then - E.Decision_Buffer := Indexed_Buffer (Decision_Buffer_Name); + E.Decision_Buffer := + To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit & Decision_Buffer_Name); if MCDC_Coverage_Enabled then - E.MCDC_Buffer := Indexed_Buffer (MCDC_Buffer_Name); + E.MCDC_Buffer := + To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit & MCDC_Buffer_Name); end if; end if; end; @@ -6731,8 +6691,8 @@ package body Instrument.Ada_Unit is ---------------- function Probe_Main - (Prj : Prj_Desc; - Dump_Config : Any_Dump_Config; + (Dump_Config : Any_Dump_Config; + Info : in out Project_Info; Rewriter : Ada_Source_Rewriter'Class) return Main_Instrumentation_Description is @@ -6743,7 +6703,7 @@ package body Instrument.Ada_Unit is Controlled_Types_Available : Boolean; Actual_Dump_Trigger : Auto_Dump_Trigger; - Main : Compilation_Unit_Part (Unit_Based_Language) := + Main : Compilation_Unit_Name (Unit_Based_Language) := (Language_Kind => Unit_Based_Language, Part => Unit_Body, others => <>); @@ -6818,7 +6778,7 @@ package body Instrument.Ada_Unit is begin Expand_Main_Generic_Instantiation (Tmp.As_Generic_Subp_Instantiation, - Prj, + Info, Generic_Wrapper_Body_Filename, Generic_Wrapper_Body, Prelude, @@ -6869,7 +6829,7 @@ package body Instrument.Ada_Unit is procedure Expand_Main_Generic_Instantiation (Main : Generic_Subp_Instantiation; - Prj : Prj_Desc; + Info : in out Project_Info; Generic_Wrapper_Body_Filename : out Unbounded_String; Generic_Wrapper_Body : out Node_Rewriting_Handle; Prelude : out Node_Rewriting_Handle; @@ -6891,7 +6851,7 @@ package body Instrument.Ada_Unit is -- Wrap_Name (, "Prefix") = -- Wrap_Name (, "Prefix") = - Output_Dir : constant String := +Prj.Output_Dir; + Output_Dir : constant String := To_String (Info.Output_Dir); function Filename (Unit_Name : Node_Rewriting_Handle; Extension : String) return String; @@ -6970,7 +6930,7 @@ package body Instrument.Ada_Unit is end case; end Visit; - -- Start of processing for Filename + -- Start of processing for Filenaem begin Visit (Unit_Name); @@ -7246,7 +7206,7 @@ package body Instrument.Ada_Unit is function Has_Matching_Pragma_For_Unit (Context : Analysis_Context; - Unit : LAL.Compilation_Unit; + Unit : Compilation_Unit; Filter : access function (Node : Pragma_Node) return Boolean) return Boolean is @@ -7284,19 +7244,6 @@ package body Instrument.Ada_Unit is end Has_Matching_Pragma_For_Unit; - -------------- - -- Has_Unit -- - -------------- - - function Has_Unit - (Context : Analysis_Context; - Unit : String; - Part : Analysis_Unit_Kind) return Boolean is - begin - return Context.Unit_Provider.Get.Get_Unit_Filename - (To_Text (Unit), Part) /= ""; - end Has_Unit; - ----------------------------------- -- Pragma_Restricts_Finalization -- ----------------------------------- @@ -7339,10 +7286,10 @@ package body Instrument.Ada_Unit is ------------------------------------- function Finalization_Restricted_In_Unit - (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean + (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean is begin - return not Has_Unit (Context, "Ada.Finalization", Unit_Specification) + return not Project.Runtime_Supports_Finalization or else Has_Matching_Pragma_For_Unit (Context, Unit, Pragma_Restricts_Finalization'Access); end Finalization_Restricted_In_Unit; @@ -7397,14 +7344,12 @@ package body Instrument.Ada_Unit is --------------------------------- function Task_Termination_Restricted - (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean + (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean is begin - return not Has_Unit (Context, "Ada.Task.Termination", Unit_Specification) - or else not Has_Unit - (Context, "Ada.Task.Identification", Unit_Specification) - or else Has_Matching_Pragma_For_Unit - (Context, Unit, Pragma_Prevents_Task_Termination'Access); + return not Project.Runtime_Supports_Task_Termination + or else Has_Matching_Pragma_For_Unit + (Context, Unit, Pragma_Prevents_Task_Termination'Access); end Task_Termination_Restricted; ----------- @@ -7563,10 +7508,11 @@ package body Instrument.Ada_Unit is ------------------------------- overriding procedure Auto_Dump_Buffers_In_Main - (Self : in out Ada_Instrumenter_Type; - Filename : String; - Dump_Config : Any_Dump_Config; - Prj : Prj_Desc) + (Self : in out Ada_Instrumenter_Type; + Filename : String; + Instr_Units : CU_Name_Vectors.Vector; + Dump_Config : Any_Dump_Config; + Info : in out Project_Info) is Rewriter : Ada_Source_Rewriter; RH : Rewriting_Handle renames Rewriter.Handle; @@ -7576,14 +7522,17 @@ package body Instrument.Ada_Unit is Desc : Main_Instrumentation_Description; begin - Start_Rewriting (Rewriter, Self, Prj, Filename); + if Instr_Units.Is_Empty then + return; + end if; + Start_Rewriting (Rewriter, Self, Info, Filename); -- Try to detect the structure of this main, to determine how to insert -- the dump of coverage buffers. In case of failure, let Probe_Main emit -- a warning and do nothing. begin - Desc := Probe_Main (Prj, Dump_Config, Rewriter); + Desc := Probe_Main (Dump_Config, Info, Rewriter); exception when Cannot_Instrument_Main_Error => return; @@ -7593,8 +7542,8 @@ package body Instrument.Ada_Unit is Emit_Dump_Helper_Unit (Dump_Config, - Self, - Prj, + Info, + Filename, Desc.Main, Helper_Unit, Override_Dump_Trigger => Desc.Actual_Dump_Trigger, @@ -7615,13 +7564,6 @@ package body Instrument.Ada_Unit is Arguments => (1 .. 0 => No_Node_Rewriting_Handle), Rule => With_Clause_Rule); - With_Buffers_Clause : constant Node_Rewriting_Handle := - Create_From_Template - (RH, - Template => "with GNATcov_RTS.Buffers;", - Arguments => (1 .. 0 => No_Node_Rewriting_Handle), - Rule => With_Clause_Rule); - Runtime_Version_Check_Node : constant Node_Rewriting_Handle := Create_From_Template (RH, @@ -7632,7 +7574,6 @@ package body Instrument.Ada_Unit is begin Append_Child (Desc.Prelude, With_Clause); Append_Child (Desc.Prelude, With_RTS_Clause); - Append_Child (Desc.Prelude, With_Buffers_Clause); Append_Child (Desc.Prelude, Runtime_Version_Check_Node); end; @@ -7730,13 +7671,14 @@ package body Instrument.Ada_Unit is ---------------------------- procedure Instrument_Source_File - (UIC : in out Ada_Unit_Inst_Context; - Filename : String; + (CU_Name : Compilation_Unit_Name; + Unit_Info : Instrumented_Unit_Info; + Prj_Info : in out Project_Info; Instrumenter : in out Ada_Instrumenter_Type; - Prj : Prj_Desc) + UIC : out Ada_Unit_Inst_Context) is - CU_Name : Compilation_Unit_Part (Language_Kind => Unit_Based_Language); Rewriter : Ada_Source_Rewriter; + Filename : constant String := To_String (Unit_Info.Filename); Dummy_Ctx : constant Context_Handle := Create_Context ("Instrumenting " & Filename); @@ -7754,7 +7696,7 @@ package body Instrument.Ada_Unit is -- Whether there is a pragma Short_Circuit_And_Or that applies to this -- unit. begin - Start_Rewriting (Rewriter, Instrumenter, Prj, Filename); + Start_Rewriting (Rewriter, Instrumenter, Prj_Info, Filename); Root_Analysis_Unit := Rewriter.Rewritten_Unit; @@ -7763,13 +7705,6 @@ package body Instrument.Ada_Unit is UIC.Root_Unit := Root_Analysis_Unit.Root.As_Compilation_Unit; - CU_Name.Part := - (case UIC.Root_Unit.P_Unit_Kind is - when Unit_Body => Unit_Body, - when Unit_Specification => Unit_Spec); - CU_Name.Unit := To_Qualified_Name - (UIC.Root_Unit.P_Decl.P_Fully_Qualified_Name_Array); - begin Preelab := (UIC.Root_Unit.P_Is_Preelaborable or else UIC.Root_Unit.P_Has_Restriction @@ -7788,22 +7723,7 @@ package body Instrument.Ada_Unit is Preelab := False; end; - -- Reset the unit inst context for the currently instrumented source - -- file. - - UIC.Annotations.Clear; - UIC.Current_Scope_Entity := null; - UIC.Degenerate_Subprogram_Index := 0; - UIC.Source_Decisions := Source_Decision_Vectors.Empty; - UIC.Source_Conditions := Source_Condition_Vectors.Empty; - UIC.Unit_Bits.Last_Statement_Bit := No_Bit_Id; - UIC.Unit_Bits.Last_Outcome_Bit := No_Bit_Id; - UIC.Unit_Bits.Last_Path_Bit := No_Bit_Id; - UIC.Unit_Bits.Decision_Bits := LL_Decision_SCO_Bit_Allocs.Empty; - UIC.Unit_Bits.Statement_Bits := LL_Statement_SCO_Bit_Allocs.Empty; - - Initialize_Rewriting (UIC, Instrumenter); - UIC.Instrumented_Unit := CU_Name; + Initialize_Rewriting (Instrumenter, UIC, CU_Name); begin Has_Pragma_SCAO := UIC.Root_Unit.P_Config_Pragmas @@ -7835,7 +7755,6 @@ package body Instrument.Ada_Unit is (Filename, Kind => Files_Table.Source_File, Indexed_Simple_Name => True); - UIC.Fullname := +Filename; UIC.Unit_Bits.SFI := UIC.SFI; -- Then run SCOs generation. This inserts calls to witness @@ -8010,19 +7929,6 @@ package body Instrument.Ada_Unit is -- Emit the instrumented source file Rewriter.Apply; - - -- Track which CU_Id maps to which instrumented unit - - Instrumented_Unit_CUs.Insert (CU_Name, UIC.CU); - - -- Update the Ignore_Status of the CU we instrumented - - Files_Table.Consolidate_Ignore_Status - (Index => Files_Table.Get_Index_From_Generic_Name - (Name => Filename, - Kind => Files_Table.Source_File, - Indexed_Simple_Name => True), - Status => Files_Table.Never); end Instrument_Source_File; ----------------------- @@ -8036,37 +7942,22 @@ package body Instrument.Ada_Unit is Qualified_Name_Slug (To_Qualified_Name (Project_Name)); begin return Ada_Identifier_Vectors."&" - (Sys_Prefix, Instrument.Ada_Identifier (+Project_Name_Slug)); + (Sys_Buffers_Lists, + Instrument.Ada_Identifier (+Project_Name_Slug)); end Buffers_List_Unit; - ----------------- - -- Buffer_Unit -- - ----------------- - - function Buffer_Unit - (Unit_Name : Ada_Qualified_Name) return Ada_Qualified_Name - is - Simple_Name : Ada_Identifier; - begin - Append (Simple_Name, "B"); - Append (Simple_Name, Ada_Identifier (+Qualified_Name_Slug (Unit_Name))); - return CU_Name : Ada_Qualified_Name := Sys_Prefix do - CU_Name.Append (Simple_Name); - end return; - end Buffer_Unit; - ---------------------- -- Pure_Buffer_Unit -- ---------------------- function Pure_Buffer_Unit - (Unit_Name : Ada_Qualified_Name) return Ada_Qualified_Name + (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name is Simple_Name : Instrument.Ada_Identifier; begin Append (Simple_Name, 'P'); - Append (Simple_Name, Ada_Identifier (+Qualified_Name_Slug (Unit_Name))); - return CU_Name : Ada_Qualified_Name := Sys_Prefix do + Append (Simple_Name, Instrumented_Unit_Slug (Instrumented_Unit)); + return CU_Name : Ada_Qualified_Name := Sys_Buffers do CU_Name.Append (Simple_Name); end return; end Pure_Buffer_Unit; @@ -8076,179 +7967,153 @@ package body Instrument.Ada_Unit is ---------------------- procedure Emit_Buffer_Unit - (Buffer_Unit : Compilation_Unit_Part; - Prj : Prj_Desc; - Unit : Files_Table.Compilation_Unit; - Unit_Bits : Allocated_Bits_Vectors.Vector; - CU_Names : CU_Name_Vectors.Vector; - CUs : CU_Id_Vectors.Vector) + (Info : in out Project_Info; UIC : Ada_Unit_Inst_Context'Class) is - Pkg_Name : constant String := To_Ada (Buffer_Unit.Unit); - -- Package name for the buffer unit - - File : Text_Files.File_Type; - Last_Buffer_Index : constant Natural := Natural (Unit_Bits.Length); + CU_Name : Compilation_Unit_Name renames UIC.Buffer_Unit; + File : Text_Files.File_Type; begin - Create_File (Prj, File, To_Filename (Prj, Ada_Language, Buffer_Unit)); + Create_File (Info, + File, + To_Filename (Info.Project, CU_Name, Switches.Ada_Language)); Put_Warnings_And_Style_Checks_Pragmas (File); File.Put_Line ("with Interfaces.C; use Interfaces.C;"); - File.Put_Line ("with System;"); - File.Put_Line ("with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers;"); File.Put_Line ("with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists;"); - File.Put_Line ("package " & Pkg_Name & " is"); - File.New_Line; - File.Put_Line (" pragma Preelaborate;"); - File.New_Line; + declare + Pkg_Name : constant String := To_Ada (CU_Name.Unit); + -- Package name for the buffer unit + + Fingerprint : Unbounded_String; + -- Fingerprint for the instrumented unit + + Unit_Name : constant String := Ada.Characters.Handling.To_Lower + (To_Ada (UIC.Instrumented_Unit.Unit)); + -- Lower-case name for the instrumented unit + + Unit_Part : constant String := + (case UIC.Instrumented_Unit.Part is + when GPR.Unit_Spec => "Unit_Spec", + when GPR.Unit_Body => "Unit_Body", + when GPR.Unit_Separate => "Unit_Separate"); + -- Do not use 'Image so that we use the original casing for the + -- enumerators, and thus avoid compilation warnings/errors. + + Statement_Last_Bit : constant String := Img + (UIC.Unit_Bits.Last_Statement_Bit); + Decision_Last_Bit : constant String := Img + (UIC.Unit_Bits.Last_Outcome_Bit); + MCDC_Last_Bit : constant String := Img + (UIC.Unit_Bits.Last_Path_Bit); - for I in 1 .. Last_Buffer_Index loop - declare - Unit_Bit : constant Allocated_Bits := Unit_Bits.Element (I); - CU_Name : constant Compilation_Unit_Part := CU_Names.Element (I); - CU : constant CU_Id := CUs.Element (I); - - Fingerprint : Unbounded_String; - -- Fingerprint for the instrumented unit - - Unit_Name : constant String := Ada.Characters.Handling.To_Lower - (To_Ada (CU_Name.Unit)); - -- Lower-case name for the instrumented unit - - Unit_Part : constant String := - (case CU_Name.Part is - when GPR.Unit_Spec => "Unit_Spec", - when GPR.Unit_Body => "Unit_Body", - when GPR.Unit_Separate => "Unit_Separate"); - -- Do not use 'Image so that we use the original casing for the - -- enumerators, and thus avoid compilation warnings/errors. - - Statement_Last_Bit : constant String := Img - (Unit_Bit.Last_Statement_Bit); - Decision_Last_Bit : constant String := Img - (Unit_Bit.Last_Outcome_Bit); - MCDC_Last_Bit : constant String := Img - (Unit_Bit.Last_Path_Bit); - - Suffix : constant String := "_" & Img (I); + begin + -- Turn the fingerprint value into the corresponding Ada literal + declare + First : Boolean := True; begin - -- Turn the fingerprint value into the corresponding Ada literal + Append (Fingerprint, "("); + for Byte of SC_Obligations.Fingerprint (UIC.CU) loop + if First then + First := False; + else + Append (Fingerprint, ", "); + end if; + Append (Fingerprint, Strings.Img (Integer (Byte))); + end loop; + Append (Fingerprint, ")"); + end; - declare - First : Boolean := True; - begin - Append (Fingerprint, "("); - for Byte of SC_Obligations.Fingerprint (CU) loop - if First then - First := False; - else - Append (Fingerprint, ", "); - end if; - Append (Fingerprint, Strings.Img (Integer (Byte))); - end loop; - Append (Fingerprint, ")"); - end; + File.Put_Line ("package " & Pkg_Name & " is"); + File.New_Line; + File.Put_Line (" pragma Preelaborate;"); + File.New_Line; - -- Create declarations for individual buffers (statement, decision - -- and MC/DC) as well as their exported addresses. Put this in - -- an individual package, to avoid having to suffix each - -- declaration - - File.Put_Line ("package Buffers" & Suffix & " is"); - - File.Put_Line (" Statement_Buffer" - & " : Coverage_Buffer_Type" - & " (0 .. " & Statement_Last_Bit & ") :=" - & " (others => False);"); - File.Put_Line (" Statement_Buffer_Address" - & " : constant System.Address" - & " := Statement_Buffer'Address;"); - File.Put_Line (" pragma Export (C, Statement_Buffer_Address, """ - & Statement_Buffer_Symbol (CU_Name) & Suffix - & """);"); - File.New_Line; + -- Create declarations for individual buffers (statement, decision + -- and MC/DC) as well as their exported addresses. + + File.Put_Line (" Statement_Buffer : Coverage_Buffer_Type" + & " (0 .. " & Statement_Last_Bit & ") :=" + & " (others => False);"); + File.Put_Line (" Statement_Buffer_Address : constant System.Address" + & " := Statement_Buffer'Address;"); + File.Put_Line (" pragma Export (C, Statement_Buffer_Address, """ + & Statement_Buffer_Symbol (UIC.Instrumented_Unit) + & """);"); + File.New_Line; - File.Put_Line (" Decision_Buffer : Coverage_Buffer_Type" - & " (0 .. " & Decision_Last_Bit & ") :=" - & " (others => False);"); - File.Put_Line (" Decision_Buffer_Address" - & " : constant System.Address" - & " := Decision_Buffer'Address;"); - File.Put_Line (" pragma Export (C, Decision_Buffer_Address, """ - & Decision_Buffer_Symbol (CU_Name) & Suffix - & """);"); - File.New_Line; + File.Put_Line (" Decision_Buffer : Coverage_Buffer_Type" + & " (0 .. " & Decision_Last_Bit & ") :=" + & " (others => False);"); + File.Put_Line (" Decision_Buffer_Address : constant System.Address" + & " := Decision_Buffer'Address;"); + File.Put_Line (" pragma Export (C, Decision_Buffer_Address, """ + & Decision_Buffer_Symbol (UIC.Instrumented_Unit) + & """);"); + File.New_Line; - File.Put_Line (" MCDC_Buffer : Coverage_Buffer_Type" - & " (0 .. " & MCDC_Last_Bit & ") :=" - & " (others => False);"); - File.Put_Line (" MCDC_Buffer_Address : constant System.Address" - & " := MCDC_Buffer'Address;"); - File.Put_Line (" pragma Export (C, MCDC_Buffer_Address, """ - & MCDC_Buffer_Symbol (CU_Name) - & Suffix & """);"); - File.New_Line; + File.Put_Line (" MCDC_Buffer : Coverage_Buffer_Type" + & " (0 .. " & MCDC_Last_Bit & ") :=" + & " (others => False);"); + File.Put_Line (" MCDC_Buffer_Address : constant System.Address" + & " := MCDC_Buffer'Address;"); + File.Put_Line (" pragma Export (C, MCDC_Buffer_Address, """ + & MCDC_Buffer_Symbol (UIC.Instrumented_Unit) + & """);"); + File.New_Line; - -- Create the GNATcov_RTS_Coverage_Buffers record + -- Create the GNATcov_RTS_Coverage_Buffers record - File.Put_Line (" Unit_Name : constant String := """ - & Unit_Name & """;"); - File.New_Line; + File.Put_Line (" Unit_Name : constant String := """ & Unit_Name + & """;"); + File.Put_Line (" Project_Name : constant String := """";"); + File.New_Line; - File.Put_Line (" Buffers : aliased constant" - & " GNATcov_RTS_Coverage_Buffers :="); - File.Put_Line (" (Fingerprint => " - & Format_Fingerprint - (SC_Obligations.Fingerprint (CU)) - & ","); - - File.Put_Line (" Language => Unit_Based_Language,"); - File.Put_Line (" Unit_Part => " & Unit_Part & ","); - File.Put_Line (" Unit_Name =>" - & " (Unit_Name'Address, Unit_Name'Length),"); - - File.Put_Line (" Bit_Maps_Fingerprint => " - & Format_Fingerprint - (SC_Obligations.Bit_Maps_Fingerprint (CU)) - & ","); - - File.Put_Line (" Statement => Statement_Buffer'Address,"); - File.Put_Line (" Decision => Decision_Buffer'Address,"); - File.Put_Line (" MCDC => MCDC_Buffer'Address,"); - - File.Put_Line (" Statement_Last_Bit => " & Statement_Last_Bit - & ","); - File.Put_Line (" Decision_Last_Bit => " & Decision_Last_Bit - & ","); - File.Put_Line (" MCDC_Last_Bit => " & MCDC_Last_Bit & ");"); - File.Put_Line ("end Buffers" & Suffix & ";"); - File.New_Line; - end; - end loop; + File.Put_Line (" Buffers : aliased constant" + & " GNATcov_RTS_Coverage_Buffers :="); + File.Put_Line + (" (Fingerprint => " + & Format_Fingerprint (SC_Obligations.Fingerprint (UIC.CU)) & ","); - -- Create the buffers group + File.Put_Line (" Language => Unit_Based_Language,"); + File.Put_Line (" Unit_Part => " & Unit_Part & ","); + File.Put_Line (" Unit_Name =>" + & " (Unit_Name'Address, Unit_Name'Length),"); - File.Put_Line - (" Buffers_Group : aliased constant Coverage_Buffers_Group :="); - File.Put (" ("); + File.Put_Line (" Project_Name =>" + & " (Project_Name'Address, Project_Name'Length),"); - for I in 1 .. Last_Buffer_Index loop - File.Put (Img (I) & " => Buffers_" & Img (I) & ".Buffers'Access"); - if I /= Last_Buffer_Index then - File.Put_Line (","); - end if; - end loop; - File.Put_Line (");"); - File.Put_Line - (" C_Buffers_Group : aliased constant" - & " GNATcov_RTS_Coverage_Buffers_Group :=" - & " (" & Last_Buffer_Index'Image & ", Buffers_Group'Address);"); - File.Put_Line (" pragma Export (C, C_Buffers_Group, """ - & Unit_Buffers_Name (Unit) & """);"); - File.New_Line; + File.Put_Line + (" Bit_Maps_Fingerprint => " + & Format_Fingerprint (SC_Obligations.Bit_Maps_Fingerprint (UIC.CU)) + & ","); + + File.Put_Line (" Statement => Statement_Buffer'Address,"); + File.Put_Line (" Decision => Decision_Buffer'Address,"); + File.Put_Line (" MCDC => MCDC_Buffer'Address,"); + + File.Put_Line (" Statement_Last_Bit => " & Statement_Last_Bit + & ","); + File.Put_Line (" Decision_Last_Bit => " & Decision_Last_Bit + & ","); + File.Put_Line (" MCDC_Last_Bit => " & MCDC_Last_Bit & ");"); + File.New_Line; - File.Put_Line ("end " & Pkg_Name & ";"); + -- Create the buffers group + + File.Put_Line + (" Buffers_Group : aliased constant Coverage_Buffers_Group :=" + & " (1 => Buffers'Access);"); + File.Put_Line + (" C_Buffers_Group : aliased constant" + & " GNATcov_RTS_Coverage_Buffers_Group :=" + & " (1, Buffers_Group'Address);"); + File.Put_Line (" pragma Export (C, C_Buffers_Group, """ + & Unit_Buffers_Name (UIC.Instrumented_Unit) & """);"); + File.New_Line; + + File.Put_Line ("end " & Pkg_Name & ";"); + end; end Emit_Buffer_Unit; --------------------------- @@ -8256,14 +8121,11 @@ package body Instrument.Ada_Unit is --------------------------- procedure Emit_Pure_Buffer_Unit - (PB_Unit : Compilation_Unit_Part; - Prj : Prj_Desc; - CU_Names : CU_Name_Vectors.Vector; - Language_Version : Unbounded_Wide_Wide_String; - Degenerate_Subprogram_Generics : Generic_Subp_Vectors.Vector) + (Info : in out Project_Info; UIC : Ada_Unit_Inst_Context'Class) is - Last_Buffer_Index : constant Natural := Natural (CU_Names.Length); - Pkg_Name : constant String := To_Ada (PB_Unit.Unit); + + CU_Name : Compilation_Unit_Name := UIC.Pure_Buffer_Unit; + Pkg_Name : constant String := To_Ada (CU_Name.Unit); File : Text_Files.File_Type; procedure Put_Language_Version_Pragma; @@ -8277,10 +8139,10 @@ package body Instrument.Ada_Unit is procedure Put_Language_Version_Pragma is begin - if Length (Language_Version) > 0 then + if Length (UIC.Language_Version_Pragma) > 0 then File.Put_Line ("pragma " - & To_String (To_Wide_Wide_String (Language_Version)) + & To_String (To_Wide_Wide_String (UIC.Language_Version_Pragma)) & ";"); File.New_Line; end if; @@ -8289,14 +8151,15 @@ package body Instrument.Ada_Unit is -- Start of processing for Emit_Pure_Buffer_Unit begin - Create_File (Prj, File, To_Filename (Prj, Ada_Language, PB_Unit)); + Create_File (Info, + File, + To_Filename (Info.Project, CU_Name, Switches.Ada_Language)); Put_Warnings_And_Style_Checks_Pragmas (File); Put_Language_Version_Pragma; File.Put_Line ("with System;"); File.Put_Line ("with GNATcov_RTS;"); - File.Put_Line ("with GNATcov_RTS.Buffers;"); File.Put_Line (Runtime_Version_Check); File.New_Line; @@ -8304,32 +8167,23 @@ package body Instrument.Ada_Unit is File.New_Line; File.Put_Line (" pragma Pure;"); File.New_Line; - for I in 1 .. Last_Buffer_Index loop - declare - Suffix : constant String := "_" & Img (I); - CU_Name : constant Compilation_Unit_Part := CU_Names.Element (I); - begin - File.Put_Line ("package Buffers" & Suffix & " is"); - File.Put_Line (" Statement_Buffer : constant System.Address;"); - File.Put_Line (" pragma Import (C, Statement_Buffer, """ - & Statement_Buffer_Symbol (CU_Name) & Suffix - & """);"); - File.New_Line; - File.Put_Line (" Decision_Buffer : constant System.Address;"); - File.Put_Line (" pragma Import (C, Decision_Buffer, """ - & Decision_Buffer_Symbol (CU_Name) & Suffix - & """);"); - File.New_Line; - File.Put_Line (" MCDC_Buffer : constant System.Address;"); - File.Put_Line (" pragma Import (C, MCDC_Buffer, """ - & MCDC_Buffer_Symbol (CU_Name) & Suffix & """);"); - File.New_Line; - File.Put_Line ("end Buffers" & Suffix & ";"); - File.New_Line; - end; - end loop; + File.Put_Line (" Statement_Buffer : constant System.Address;"); + File.Put_Line (" pragma Import (C, Statement_Buffer, """ + & Statement_Buffer_Symbol (UIC.Instrumented_Unit) + & """);"); + File.New_Line; + File.Put_Line (" Decision_Buffer : constant System.Address;"); + File.Put_Line (" pragma Import (C, Decision_Buffer, """ + & Decision_Buffer_Symbol (UIC.Instrumented_Unit) + & """);"); + File.New_Line; + File.Put_Line (" MCDC_Buffer : constant System.Address;"); + File.Put_Line (" pragma Import (C, MCDC_Buffer, """ + & MCDC_Buffer_Symbol (UIC.Instrumented_Unit) + & """);"); + File.New_Line; - for G of Degenerate_Subprogram_Generics loop + for G of UIC.Degenerate_Subprogram_Generics loop File.Put_Line (" " & To_String (To_Wide_Wide_String (G.Generic_Subp_Decl))); end loop; @@ -8340,31 +8194,28 @@ package body Instrument.Ada_Unit is Text_Files.Run_GNATpp (File); end if; - if not Degenerate_Subprogram_Generics.Is_Empty then - declare - PB_Unit_Body : Compilation_Unit_Part := PB_Unit; - begin - PB_Unit_Body.Part := GNATCOLL.Projects.Unit_Body; + if not UIC.Degenerate_Subprogram_Generics.Is_Empty then + CU_Name.Part := GNATCOLL.Projects.Unit_Body; - Create_File - (Prj, File, To_Filename (Prj, Ada_Language, PB_Unit_Body)); + Create_File + (Info, + File, + To_Filename (Info.Project, CU_Name, Switches.Ada_Language)); - Put_Warnings_And_Style_Checks_Pragmas (File); - Put_Language_Version_Pragma; - File.Put_Line ("package body " & Pkg_Name & " is"); - File.New_Line; - for G of Degenerate_Subprogram_Generics loop - File.Put_Line - (" " - & To_String (To_Wide_Wide_String (G.Generic_Subp_Body))); - end loop; - File.Put_Line ("end " & Pkg_Name & ";"); + Put_Warnings_And_Style_Checks_Pragmas (File); + Put_Language_Version_Pragma; + File.Put_Line ("package body " & Pkg_Name & " is"); + File.New_Line; + for G of UIC.Degenerate_Subprogram_Generics loop + File.Put_Line + (" " & To_String (To_Wide_Wide_String (G.Generic_Subp_Body))); + end loop; + File.Put_Line ("end " & Pkg_Name & ";"); - Text_Files.Close (File); - if Switches.Pretty_Print then - Text_Files.Run_GNATpp (File); - end if; - end; + Text_Files.Close (File); + if Switches.Pretty_Print then + Text_Files.Run_GNATpp (File); + end if; end if; end Emit_Pure_Buffer_Unit; @@ -8374,13 +8225,16 @@ package body Instrument.Ada_Unit is procedure Emit_Dump_Helper_Unit (Dump_Config : Any_Dump_Config; - Instrumenter : Ada_Instrumenter_Type'Class; - Prj : Prj_Desc; - Main : Compilation_Unit_Part; + Info : in out Project_Info; + Main_Filename : String; + Main : Compilation_Unit_Name; Helper_Unit : out Ada_Qualified_Name; Override_Dump_Trigger : Any_Dump_Trigger := Manual; Has_Controlled : Boolean := False) is + Root_Prj_Name : constant String := + Project.Project.Root_Project.Name; + File : Text_Files.File_Type; procedure Put_With (Unit : Ada_Qualified_Name); @@ -8410,7 +8264,7 @@ package body Instrument.Ada_Unit is begin -- Create the name of the helper unit - Helper_Unit := Sys_Prefix; + Helper_Unit := Sys_Buffers; Helper_Unit.Append (To_Unbounded_String ("D") & Instrumented_Unit_Slug (Main)); @@ -8440,13 +8294,13 @@ package body Instrument.Ada_Unit is -- trace file. Create_File - (Prj, + (Info, File, Name => To_Filename - (Prj, - Ada_Language, - CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Spec))); + (Info.Project, + CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Spec), + Switches.Ada_Language)); Put_Warnings_And_Style_Checks_Pragmas (File); Put_With (Sys_Buffers); @@ -8484,13 +8338,13 @@ package body Instrument.Ada_Unit is -- Emit the package body Create_File - (Prj, + (Info, File, Name => To_Filename - (Prj, - Ada_Language, - CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Body))); + (Info.Project, + CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Body), + Switches.Ada_Language)); Put_Warnings_And_Style_Checks_Pragmas (File); @@ -8506,7 +8360,7 @@ package body Instrument.Ada_Unit is end case; File.Put_Line - ("with " & To_Ada (Buffers_List_Unit (+Prj.Prj_Name)) & ";"); + ("with " & To_Ada (Buffers_List_Unit (Root_Prj_Name)) & ";"); File.Put_Line ("package body " & Helper_Unit_Name & " is"); File.New_Line; @@ -8521,10 +8375,12 @@ package body Instrument.Ada_Unit is File.Put (" ("); File.Put_Line - (To_Ada (Buffers_List_Unit (+Prj.Prj_Name)) & ".List,"); + (To_Ada (Buffers_List_Unit (Root_Prj_Name)) & ".List,"); case Dump_Config.Channel is when Binary_File => declare + use GNATCOLL.VFS; + U : constant String := To_Ada (Output_Unit); Indent1 : constant String := " "; Indent2 : constant String := Indent1 & " "; @@ -8535,8 +8391,14 @@ package body Instrument.Ada_Unit is else """" & To_String (Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := - """" & To_String (Dump_Config.Filename_Prefix) & """"; - Tag : constant String := """" & (+Instrumenter.Tag) & """"; + (if Length (Dump_Config.Filename_Prefix) = 0 + then """" & String'(+Info.Project.Executable_Name + (File => +Main_Filename, + Include_Suffix => True)) & """" + else """" & To_String (Dump_Config.Filename_Prefix) + & """"); + Tag : constant String := + """" & Trace_Filename_Tag & """"; Simple : constant String := (if Dump_Config.Filename_Simple then "True" @@ -8647,25 +8509,29 @@ package body Instrument.Ada_Unit is ---------------------------- overriding procedure Emit_Buffers_List_Unit - (Self : Ada_Instrumenter_Type; - Instr_Units : Unit_Sets.Set; - Prj : Prj_Desc) + (Self : Ada_Instrumenter_Type; + Root_Project_Info : in out Project_Info; + Instr_Units : CU_Name_Vectors.Vector) is - Buffers_CU_Name : constant Compilation_Unit_Part := + Prj_Name : constant String := Root_Project_Info.Project.Name; + CU_Name : constant Compilation_Unit_Name := CU_Name_For_Unit - (Buffers_List_Unit (+Prj.Prj_Name), GNATCOLL.Projects.Unit_Spec); - File : Text_Files.File_Type; + (Buffers_List_Unit (Prj_Name), GNATCOLL.Projects.Unit_Spec); + File : Text_Files.File_Type; begin -- Emit the unit to contain the list of buffers declare - Unit_Name : constant String := To_Ada (Buffers_CU_Name.Unit); + Unit_Name_Str : constant String := To_Ada (CU_Name.Unit); begin Create_File - (Prj, File, To_Filename (Prj, Ada_Language, Buffers_CU_Name)); + (Root_Project_Info, + File, + To_Filename + (Root_Project_Info.Project, + CU_Name, + Switches.Ada_Language)); Put_Warnings_And_Style_Checks_Pragmas (File); - File.Put_Line - ("with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists;"); for Instr_Unit of Instr_Units loop @@ -8676,16 +8542,13 @@ package body Instrument.Ada_Unit is -- would not include them in the link as they would not be in the -- dependency closure. - if Instr_Unit.Language = Unit_Based_Language then - File.Put_Line - ("with " - & To_Ada - (Buffer_Unit (To_Qualified_Name (+Instr_Unit.Unit_Name))) - & ";"); + if Instr_Unit.Language_Kind = Unit_Based_Language then + File.Put_Line ("with " & To_Ada (Buffer_Unit (Instr_Unit)) + & ";"); end if; end loop; File.New_Line; - File.Put_Line ("package " & Unit_Name & " is"); + File.Put_Line ("package " & Unit_Name_Str & " is"); File.New_Line; File.Put_Line (" pragma Preelaborate;"); File.New_Line; @@ -8708,197 +8571,93 @@ package body Instrument.Ada_Unit is File.Put_Line (" List : constant GNATcov_RTS.Buffers.Lists" & ".Coverage_Buffers_Group_Array := ("); - declare - Index : Positive := 1; - Last : constant Natural := Natural (Instr_Units.Length); - begin - for Instr_Unit of Instr_Units loop + for Cur in Instr_Units.Iterate loop + declare + use CU_Name_Vectors; + + Index : constant Positive := To_Index (Cur); + Index_Img : constant String := Img (To_Index (Cur)); + Buffer_Name : constant String := + Unit_Buffers_Name (Element (Cur)); + begin File.Put - (" " & Img (Index) & " => " - & Unit_Buffers_Name (Instr_Unit) & "'Access"); - if Index = Last then + (" " & Index_Img & " => " & Buffer_Name & "'Access"); + if Index = Instr_Units.Last_Index then File.Put_Line (");"); else File.Put_Line (","); end if; - Index := Index + 1; - end loop; - end; - + end; + end loop; File.Put_Line (" C_List : constant GNATcov_RTS.Buffers.Lists" & ".GNATcov_RTS_Coverage_Buffers_Group_Array :="); File.Put_Line (" (" & Instr_Units.Length'Image - & ", List'Address);"); + & " , List'Address);"); File.Put_Line (" pragma Export (C, C_List, """ - & Unit_Buffers_Array_Name (+Prj.Prj_Name) & """);"); + & Unit_Buffers_Array_Name (Prj_Name) + & """);"); File.New_Line; - File.Put_Line ("end " & Unit_Name & ";"); + File.Put_Line ("end " & Unit_Name_Str & ";"); end; end Emit_Buffers_List_Unit; - ----------------------------- - -- Create_Ada_Instrumenter -- - ----------------------------- - - function Create_Ada_Instrumenter - (Tag : Unbounded_String; - Config_Pragmas_Filename, - Mapping_Filename : String; - Predefined_Source_Dirs : String_Vectors.Vector) - return Ada_Instrumenter_Type - is - Instrumenter : Ada_Instrumenter_Type; - begin - Instrumenter.Tag := Tag; - - -- First create the context for Libadalang - - Instrumenter.Provider := - Instrument.Ada_Unit_Provider.Create_Provider - (Predefined_Source_Dirs, Mapping_Filename); - - -- Create the event handler, to report when Libadalang cannot read a - -- required source file. - - Instrumenter.Event_Handler := Create_Missing_File_Reporter; - - -- Save the location of the file holding the configuration pragmas - - Instrumenter.Config_Pragmas_Filename := +Config_Pragmas_Filename; - - -- Then, create the analysis context - - Create_LAL_Context (Instrumenter); - return Instrumenter; - end Create_Ada_Instrumenter; - --------------------- -- Instrument_Unit -- --------------------- - procedure Instrument_Unit - (Self : in out Ada_Instrumenter_Type; - Unit_Name : String; - Prj : Prj_Desc; - Files_Of_Interest : String_Sets.Set) + overriding procedure Instrument_Unit + (Self : in out Ada_Instrumenter_Type; + CU_Name : Compilation_Unit_Name; + Unit_Info : in out Instrumented_Unit_Info) is - Allocated_Bits : Allocated_Bits_Vectors.Vector; - Last_Buffer_Index : Natural := 0; - CU_Names : CU_Name_Vectors.Vector; - CUs : CU_Id_Vectors.Vector; - Unit : constant Files_Table.Compilation_Unit := - (Language => Unit_Based_Language, Unit_Name => +Unit_Name); - - UIC : Ada_Unit_Inst_Context; - - procedure Instrument_Source_File_Wrapper (Filename : String); - -- Wrapper around Instrument_Source_File. Instrument the given filename - -- if it is a file of interest. - - ------------------------------------ - -- Instrument_Source_File_Wrapper -- - ------------------------------------ - - procedure Instrument_Source_File_Wrapper (Filename : String) - is - Event_Handler : Missing_Src_Reporter renames - Missing_Src_Reporter_Access (Self.Event_Handler.Unchecked_Get).all; - -- Handle to the event handler we use to report missing source files; + Prj_Info : Project_Info renames Unit_Info.Prj_Info.all; + UIC : Ada_Unit_Inst_Context; - Basename : constant String := - Ada.Directories.Simple_Name (Filename); + Event_Handler : Missing_Src_Reporter renames + Missing_Src_Reporter_Access (Self.Event_Handler.Unchecked_Get).all; + -- Handle to the event handler we use to report missing source files - begin - -- Instrument the file only if it is a file of interest - - if Files_Of_Interest.Contains (+Filename) then - - -- In verbose mode, always print a notice for the source file - -- that we are about to instrument. In non-verbose mode, just get - -- prepared to print it in case we emit a "source file missing" - -- warning through Libadalang's event handler. - - if Verbose then - Put_Line ("Instrumenting " & Basename); - else - Event_Handler.Instrumented_File := - To_Unbounded_String (Basename); - end if; - - Last_Buffer_Index := Last_Buffer_Index + 1; - UIC.Entities.Buffers_Index := Last_Buffer_Index; - Instrument_Source_File - (UIC => UIC, - Filename => Filename, - Instrumenter => Self, - Prj => Prj); - CU_Names.Append (UIC.Instrumented_Unit); - CUs.Append (UIC.CU); - Allocated_Bits.Append (UIC.Unit_Bits); - end if; - end Instrument_Source_File_Wrapper; + Filename : constant String := To_String (Unit_Info.Filename); + Basename : constant String := Ada.Directories.Simple_Name (Filename); begin - -- Initialize the buffer unit to match the unit name. It will contain - -- coverage buffers for all parts of the unit: specification, body, - -- and separates. + -- If we are in verbose mode, we already printed the source file that + -- we are about to instrument. Otherwise, just get prepared to print it + -- in case we emit a "source file missing" warning through Libadalang's + -- event handler. - UIC.Buffer_Unit := - CU_Name_For_Unit - (Buffer_Unit (To_Qualified_Name (Unit_Name)), GPR.Unit_Spec); - UIC.Pure_Buffer_Unit := - CU_Name_For_Unit - (Pure_Buffer_Unit (To_Qualified_Name (Unit_Name)), GPR.Unit_Spec); + if not Verbose then + Event_Handler.Instrumented_File := To_Unbounded_String (Basename); + end if; - -- Try to find the spec and / or the body for this compilation unit - -- using the unit provider. Then retrieve the separate unit from the - -- spec / body / both. + -- Instrument the source file and create a unit to contain its coverage + -- buffers. - for Part in Analysis_Unit_Kind loop - declare - function Convert (Part : Analysis_Unit_Kind) return Unit_Parts is - (case Part is - when Unit_Body => Unit_Body, - when Unit_Specification => Unit_Spec); - begin - if Self.Provider.Has_Unit (Unit_Name, Convert (Part)) then - Find_Ada_Units - (Self, - Self.Provider.Get_Unit_Filename - (Langkit_Support.Text.From_UTF8 (Unit_Name), Part), - Instrument_Source_File_Wrapper'Access); - end if; - end; - end loop; + Instrument_Source_File + (CU_Name => CU_Name, + Unit_Info => Unit_Info, + Prj_Info => Prj_Info, + Instrumenter => Self, + UIC => UIC); + Emit_Buffer_Unit (Prj_Info, UIC); + Emit_Pure_Buffer_Unit (Prj_Info, UIC); - -- Once the unit was instrumented, emit the coverage buffer units - - Emit_Buffer_Unit - (Buffer_Unit => UIC.Buffer_Unit, - Prj => Prj, - Unit => Unit, - Unit_Bits => Allocated_Bits, - CU_Names => CU_Names, - CUs => CUs); - Emit_Pure_Buffer_Unit - (PB_Unit => UIC.Pure_Buffer_Unit, - Prj => Prj, - CU_Names => CU_Names, - Language_Version => UIC.Language_Version_Pragma, - Degenerate_Subprogram_Generics => UIC.Degenerate_Subprogram_Generics); - end Instrument_Unit; + -- Track which CU_Id maps to which instrumented unit - -------------------- - -- Find_Ada_Units -- - -------------------- + Instrumented_Unit_CUs.Insert (CU_Name, UIC.CU); + end Instrument_Unit; procedure Find_Ada_Units (Instrumenter : in out Ada_Instrumenter_Type; - Filename : String; - Process_Unit : access procedure (Filename : String)) + CU_Name : Compilation_Unit_Name; + Info : GNATCOLL.Projects.File_Info; + Process_Unit : access procedure + (CU_Name : Compilation_Unit_Name; + Info : GNATCOLL.Projects.File_Info)) is + use GNATCOLL.VFS; function Process_Node (N : LAL.Ada_Node'Class) return Visit_Status; @@ -8911,18 +8670,26 @@ package body Instrument.Ada_Unit is if N.Kind in Ada_Body_Stub then begin declare - Stub : constant LAL.Body_Stub := N.As_Body_Stub; - Subunit_FQN : constant Text_Type := - Stub.P_Fully_Qualified_Name; + Stub : constant LAL.Body_Stub := N.As_Body_Stub; + Subunit_FQN : constant LAL.Unbounded_Text_Type_Array := + Stub.P_Syntactic_Fully_Qualified_Name; + Subunit_Name : constant Compilation_Unit_Name := + CU_Name_For_Unit + (Unit => To_Qualified_Name (Subunit_FQN), + Part => GPR.Unit_Separate); + Subunit_Info : GPR.File_Info; begin if Subunit_FQN'Length = 0 then raise Property_Error; - else + elsif Unit_Info (Subunit_Name, Subunit_Info) then Find_Ada_Units (Instrumenter, - Instrumenter.Context.Unit_Provider.Get - .Get_Unit_Filename (Subunit_FQN, Unit_Body), - Process_Unit); + Subunit_Name, + Subunit_Info, + Process_Unit); + else + Warn ("cannot instrument " & Image (Subunit_Name) + & ": this unit does not belong to this project"); end if; end; exception @@ -8936,13 +8703,14 @@ package body Instrument.Ada_Unit is return Into; end Process_Node; - Unit : constant LAL.Analysis_Unit := - Get_From_File (Instrumenter, Filename); + Input_Filename : constant String := +Info.File.Full_Name; + Unit : constant LAL.Analysis_Unit := + Get_From_File (Instrumenter, Input_Filename); begin -- Abort if the input project is not compilable if Unit.Has_Diagnostics then - Outputs.Error ("instrumentation failed for " & Filename); + Outputs.Error ("instrumentation failed for " & Input_Filename); Outputs.Error ("please make sure the original project can be compiled"); for D of Unit.Diagnostics loop @@ -8962,7 +8730,7 @@ package body Instrument.Ada_Unit is -- unit. elsif Unit.Root.Kind = Ada_Compilation_Unit_List then - Outputs.Error ("instrumentation failed for " & Filename); + Outputs.Error ("instrumentation failed for " & Input_Filename); Outputs.Error ("source files containing multiple compilation units" & " are not supported"); raise Xcov_Exit_Exc; @@ -8972,7 +8740,7 @@ package body Instrument.Ada_Unit is declare CU : constant LAL.Compilation_Unit := Unit.Root.As_Compilation_Unit; begin - Process_Unit (Filename); + Process_Unit (CU_Name, Info); CU.Traverse (Process_Node'Access); end; end Find_Ada_Units; diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index a27d22e80..ae4bf0ed3 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -28,72 +28,74 @@ with Langkit_Support.Text; use Langkit_Support.Text; with Libadalang.Analysis; use Libadalang.Analysis; with Libadalang.Rewriting; use Libadalang.Rewriting; -with Files_Table; use Files_Table; -with Instrument.Ada_Unit_Provider; -with Instrument.Common; use Instrument.Common; +with Instrument.Common; use Instrument.Common; with Switches; package Instrument.Ada_Unit is - type Ada_Instrumenter_Type is new Language_Instrumenter with - record - Provider : Instrument.Ada_Unit_Provider.Provider_Type; - -- Unit provider to create an analysis context (Context member - -- below). We use a custom provider there, to be able to turn - -- a filename to our Compilation_Unit_Name internal representation, - -- and to not depend on project files in the unit instrumentation - -- process. + type Ada_Instrumenter_Type is new Language_Instrumenter + with record + Provider : Libadalang.Analysis.Unit_Provider_Reference; + -- Unit provider to create an analysis context (Context member below) - Event_Handler : Libadalang.Analysis.Event_Handler_Reference; - -- Event handler to warn about missing source files + Event_Handler : Libadalang.Analysis.Event_Handler_Reference; + -- Event handler to warn about missing source files - Config_Pragmas_Filename : Unbounded_String; - -- File holding the list of configuration pragmas + Context : Libadalang.Analysis.Analysis_Context; + -- Libadalang context to load all units to rewrite - Context : Libadalang.Analysis.Analysis_Context; - -- Libadalang context to load all units to rewrite + Get_From_File_Count : Natural; + -- Count how many times we called Context.Get_From_File. See the + -- Max_Get_From_File_Count constant. - Get_From_File_Count : Natural; - -- Count how many times we called Context.Get_From_File. See the - -- Max_Get_From_File_Count constant. + Language_Version : Any_Language_Version; + -- See the eponym arguments in Instrument.Intrument_Units_Of_Interest - end record; + end record; -- Instrumentation primitives for Ada + function Create_Ada_Instrumenter + (Language_Version : Any_Language_Version) return Ada_Instrumenter_Type; + -- Create an Ada instrumenter from the given provider, and the given + -- language version. + overriding function Language (Self : Ada_Instrumenter_Type) return Switches.Src_Supported_Language is (Switches.Ada_Language); overriding procedure Instrument_Unit - (Self : in out Ada_Instrumenter_Type; - Unit_Name : String; - Prj : Prj_Desc; - Files_Of_Interest : String_Sets.Set); + (Self : in out Ada_Instrumenter_Type; + CU_Name : Compilation_Unit_Name; + Unit_Info : in out Instrumented_Unit_Info); overriding procedure Auto_Dump_Buffers_In_Main - (Self : in out Ada_Instrumenter_Type; - Filename : String; - Dump_Config : Any_Dump_Config; - Prj : Prj_Desc); + (Self : in out Ada_Instrumenter_Type; + Filename : String; + Instr_Units : CU_Name_Vectors.Vector; + Dump_Config : Any_Dump_Config; + Info : in out Project_Info); overriding procedure Emit_Buffers_List_Unit - (Self : Ada_Instrumenter_Type; - Instr_Units : Unit_Sets.Set; - Prj : Prj_Desc); + (Self : Ada_Instrumenter_Type; + Root_Project_Info : in out Project_Info; + Instr_Units : CU_Name_Vectors.Vector); - function Create_Ada_Instrumenter - (Tag : Unbounded_String; - Config_Pragmas_Filename, - Mapping_Filename : String; - Predefined_Source_Dirs : String_Vectors.Vector) - return Ada_Instrumenter_Type; - -- Create an Ada instrumenter. Config_Pragmas_Filename is the fullname - -- to the configuration pragma file. Mapping_Filename is the fullname - -- to the mapping file, which maps unit names to file fullnames, and - -- Predefined_Source_Dirs is the list of directories hosting runtime - -- files. The two last parameters are used to instantiate our - -- custom unit provider, which does not rely on project files - -- (see Instrument.Ada_Unit_Provider). + overriding function Skip_Source_File + (Self : Ada_Instrumenter_Type; + Source_File : GNATCOLL.Projects.File_Info) return Boolean + is (False); + + procedure Find_Ada_Units + (Instrumenter : in out Ada_Instrumenter_Type; + CU_Name : Compilation_Unit_Name; + Info : GNATCOLL.Projects.File_Info; + Process_Unit : access procedure + (CU_Name : Compilation_Unit_Name; + Info : GNATCOLL.Projects.File_Info)); + -- Consider that Info is a source file to instrument (i.e. a unit of + -- interest, CU_Name being the name of its compilation unit) and call + -- Process_Unit for all compilation units that must be instrumented with + -- it (i.e. related subunits, if present). -- Private declarations relative to the AST traversal private @@ -214,10 +216,6 @@ private new Ada.Containers.Vectors (Natural, Source_Condition); type Instrumentation_Entities is record - Buffers_Index : Natural := 0; - -- Index into the set of this units' coverage buffers group for the - -- source file being instrumented. - Common_Buffers : Node_Rewriting_Handle := No_Node_Rewriting_Handle; -- Qualified name for the unit that contains coverage buffer types and -- witness subprograms. @@ -264,13 +262,10 @@ private type Ada_Unit_Inst_Context is new Instrument.Common.Unit_Inst_Context with record - Language_Version_Pragma : Unbounded_Wide_Wide_String; - -- Language version configuration pragma for unit, if any - CU : CU_Id := No_CU_Id; -- SCO identifier of the compilation unit being instrumented - Root_Unit : Libadalang.Analysis.Compilation_Unit; + Root_Unit : Compilation_Unit; -- Node of compilation unit Source_Decisions : Source_Decision_Vectors.Vector; @@ -283,7 +278,7 @@ private Entities : Instrumentation_Entities; -- Bank of nodes to use during instrumentation - Pure_Buffer_Unit : Compilation_Unit_Part; + Pure_Buffer_Unit : Compilation_Unit_Name; -- Name of the compilation unit that holds addresses for the coverage -- buffers of the unit being instrumented. diff --git a/tools/gnatcov/instrument-ada_unit__stub.adb b/tools/gnatcov/instrument-ada_unit__stub.adb index 523d98f83..c4fd7d0ac 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.adb +++ b/tools/gnatcov/instrument-ada_unit__stub.adb @@ -16,7 +16,4 @@ -- of the license. -- ------------------------------------------------------------------------------ -package body Instrument.Ada_Unit is -begin - Builtin_Support (Ada_Language) := False; -end Instrument.Ada_Unit; +pragma No_Body; diff --git a/tools/gnatcov/instrument-ada_unit__stub.ads b/tools/gnatcov/instrument-ada_unit__stub.ads index a1dddb09d..1caac4fe2 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.ads +++ b/tools/gnatcov/instrument-ada_unit__stub.ads @@ -24,21 +24,23 @@ with Instrument.Common; use Instrument.Common; package Instrument.Ada_Unit is - pragma Elaborate_Body; - type Ada_Instrumenter_Type is new Language_Instrumenter with null record; -- Common instrumentation primitives for Ada + function Create_Ada_Instrumenter + (Language_Version : Any_Language_Version) return Ada_Instrumenter_Type + is (Ada_Instrumenter_Type'(null record)); + overriding function Language (Self : Ada_Instrumenter_Type) return Src_Supported_Language is (Ada_Language); - function Create_Ada_Instrumenter - (Tag : Unbounded_String; - Config_Pragmas_Filename, - Mapping_Filename : String; - Predefined_Source_Dirs : String_Vectors.Vector) - return Ada_Instrumenter_Type - is (Ada_Instrumenter_Type'(others => <>)); + procedure Find_Ada_Units + (Instrumenter : in out Ada_Instrumenter_Type; + CU_Name : Compilation_Unit_Name; + Info : GNATCOLL.Projects.File_Info; + Process_Unit : access procedure + (CU_Name : Compilation_Unit_Name; + Info : GNATCOLL.Projects.File_Info)) is null; end Instrument.Ada_Unit; diff --git a/tools/gnatcov/instrument-ada_unit_provider.adb b/tools/gnatcov/instrument-ada_unit_provider.adb index 02bff2b50..cf0ad0b97 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.adb +++ b/tools/gnatcov/instrument-ada_unit_provider.adb @@ -63,8 +63,6 @@ package body Instrument.Ada_Unit_Provider is Get_Line (Dependencies_File); begin Provider.Unit_Map.Insert (To_Lower (Unit_Name), File_Fullname); - Provider.Filename_Map.Insert - (File_Fullname, To_Lower (Unit_Name)); end; end loop; exception @@ -198,22 +196,4 @@ package body Instrument.Ada_Unit_Provider is end if; end Get_Unit; - -------------- - -- Has_Unit -- - -------------- - - function Has_Unit - (Provider : Provider_Type; - Unit_Name : String; - Unit_Part : Unit_Parts) return Boolean - is - Unit_Name_And_Part : constant String := - To_Lower (Unit_Name) - & (case Unit_Part is - when Unit_Spec => "%s", - when others => "%b"); - begin - return Provider.Unit_Map.Contains (Unit_Name_And_Part); - end Has_Unit; - end Instrument.Ada_Unit_Provider; diff --git a/tools/gnatcov/instrument-ada_unit_provider.ads b/tools/gnatcov/instrument-ada_unit_provider.ads index fd851e9a3..3e2774b11 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.ads +++ b/tools/gnatcov/instrument-ada_unit_provider.ads @@ -65,14 +65,9 @@ package Instrument.Ada_Unit_Provider is overriding procedure Release (Provider : in out Provider_Type) is null; - function Has_Unit - (Provider : Provider_Type; - Unit_Name : String; - Unit_Part : Unit_Parts) return Boolean; - -- Returns whether given unit is in the provider unit closure - private + use US; use type GNATCOLL.VFS.Virtual_File; package String_Maps is new Ada.Containers.Indefinite_Hashed_Maps @@ -86,9 +81,6 @@ private Unit_Map : String_Maps.Map; -- Mapping from unit name to file fullnames - Filename_Map : String_Maps.Map; - -- Mapping from file fullnames to unit names - Runtime_Files : String_Maps.Map; -- Mapping from a runtime file basename to its fullname diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index cf64a2857..410348c38 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -26,6 +26,9 @@ with Clang.Extensions; use Clang.Extensions; with GNAT.OS_Lib; use GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; +with GNAT.Strings; + +with GNATCOLL.VFS; with Interfaces; use Interfaces; with Interfaces.C; use Interfaces.C; @@ -39,6 +42,7 @@ with Inputs; use Inputs; with Instrument.C_Utils; use Instrument.C_Utils; with Outputs; use Outputs; with Paths; use Paths; +with Project; use Project; with SCOs; with System; use System; with Table; @@ -46,6 +50,7 @@ with Text_Files; use Text_Files; package body Instrument.C is + package GPR renames GNATCOLL.Projects; package US renames Ada.Strings.Unbounded; function To_Chars_Ptr_Array @@ -56,6 +61,19 @@ package body Instrument.C is procedure Free (Self : in out chars_ptr_array); -- Free all strings in Self + function Compiler_Driver + (Project : GNATCOLL.Projects.Project_Type; + Language : C_Family_Language) return String; + -- Return the command name for the compiler for Language in the given + -- Project. + + function Source_Suffix + (Instrumenter : C_Family_Instrumenter_Type'Class; + Part : GNATCOLL.Projects.Unit_Parts; + Project : GNATCOLL.Projects.Project_Type) return String; + -- Return the filename suffix corresponding for Part files and the language + -- that Instrumenter handles in the given project. + procedure Filter_Annotations; -- Remove any exemption annotations from the map that intersects a -- statement SCO. This is not part of Import_Annotations as this is only @@ -72,8 +90,66 @@ package body Instrument.C is -- Preprocessing utilities -- ------------------------------ + Macro_Cmdline_Regexp : constant Pattern_Matcher := Compile ( + "([a-zA-Z_]\w*)" + -- The name of the macro + + & "(\(.*\))?" + -- The optional list of macro arguments + + & "([^ =]+)?" + -- Then, there can be any character before the assignment: they will be + -- part of the macro value (e.g. A(b)b will yield #define A b 1) + + & "(?:=(.*))?" + -- The macro value itself + ); + + Macro_Def_Regexp : constant Pattern_Matcher := Compile ( + "#define" + & "(?: |\t)+" + -- "#define", then a non-empty blank + + & "([a-zA-Z_]\w*)" + -- The name of the macro + + & "(\(.*\))?" + -- The optional list of macro arguments + + & "(.*)" + -- The macro value itself + ); + -- Regular expression to analyze definitions for builtin macros (see + -- Builtin_Macros) + type Macro_Set_Access is access Macro_Set; type Macro_Set_Cst_Access is access constant Macro_Set; + package Compiler_Macros_Maps is new Ada.Containers.Hashed_Maps + (Key_Type => Unbounded_String, + Element_Type => Macro_Set_Access, + Equivalent_Keys => "=", + Hash => Ada.Strings.Unbounded.Hash); + Compiler_Macros : Compiler_Macros_Maps.Map; + -- Cache for computed compiler builtin macros, to avoid relaunching the + -- compiler command every time a file is instrumented. Used in the + -- Builtin_Macros function only. + + -- The three following functions are not used, but could be in the future, + -- when we will refine what is done with macros. + + procedure Parse_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean); + -- Parse a macro definition. If the parsing failed, set Success to False. + -- Otherwise, set Parsed_Def to the parsed definition and set Success to + -- True. + + procedure Parse_Cmdline_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean); + -- Same as above, but with a command-line macro definition function Builtin_Macros (Lang, Compiler, Std, Output_Dir : String) return Macro_Set_Cst_Access; @@ -89,8 +165,8 @@ package body Instrument.C is procedure Preprocess_Source (Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc; PP_Filename : out Unbounded_String; + Info : in out Project_Info; Options : in out Analysis_Options); -- Preprocess the source at Filename and extend Options using the -- preprocessor output. @@ -277,30 +353,40 @@ package body Instrument.C is ---------------------------- procedure Record_PP_Info - (Orig_Filename : String; - UIC : in out C_Unit_Inst_Context; - Instrumenter : C_Family_Instrumenter_Type'Class); + (Unit_Info : Instrumented_Unit_Info; + UIC : in out C_Unit_Inst_Context); -- Emit the low-level SCOs for the given unit. Do not process them: this is -- left to the other (instrumentation) pass. + procedure Instrument_Source_File + (CU_Name : Compilation_Unit_Name; + Unit_Info : Instrumented_Unit_Info; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj_Info : in out Project_Info; + UIC : out C_Unit_Inst_Context); + -- Generate the instrumented source corresponding to CU_Name/Unit_Info. + -- Record instrumentation information in IC. + -- + -- If the unit to instrument is also a main and the buffers dump trigger + -- is not manual, instrumented code will also dump the coverage buffers. + ---------------------------- -- Source instrumentation -- ---------------------------- procedure Emit_Buffer_Unit - (UIC : C_Unit_Inst_Context'Class; - Unit : Compilation_Unit; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc); + (Info : in out Project_Info; + UIC : C_Unit_Inst_Context'Class; + Instrumenter : C_Family_Instrumenter_Type'Class); -- Emit the unit to contain coverage buffers for the given instrumented -- unit, for the given instrumenter. procedure Emit_Dump_Helper_Unit - (Dump_Config : Any_Dump_Config; - Main : Compilation_Unit_Part; - Helper_Unit : out US.Unbounded_String; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc); + (Dump_Config : Any_Dump_Config; + Info : in out Project_Info; + Main : Compilation_Unit_Name; + Helper_Unit : out US.Unbounded_String; + Instrumenter : C_Family_Instrumenter_Type'Class); -- Emit the unit to contain helpers to implement the automatic dump of -- coverage buffers for the given Main unit. Info must be the project that -- owns this main. Upon return, the name of this helper unit is stored in @@ -311,9 +397,9 @@ package body Instrument.C is procedure Start_Rewriting (Self : out C_Source_Rewriter; + Info : in out Project_Info; Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc; Preprocessed : Boolean := False); -- Start a rewriting session for the given file identified by its full -- name. @@ -437,6 +523,24 @@ package body Instrument.C is end loop; end Free; + --------------------- + -- Compiler_Driver -- + --------------------- + + function Compiler_Driver + (Project : GNATCOLL.Projects.Project_Type; + Language : C_Family_Language) return String is + begin + return Result : constant String := + GNATCOLL.Projects.Attribute_Value + (Project, GPR.Compiler_Driver_Attribute, Image (Language)) + do + if Result = "" then + Fatal_Error ("could not find a compiler for " & Image (Language)); + end if; + end return; + end Compiler_Driver; + ------------------------ -- Filter_Annotations -- ------------------------ @@ -478,6 +582,47 @@ package body Instrument.C is end loop; end Filter_Annotations; + ------------------- + -- Source_Suffix -- + ------------------- + + function Source_Suffix + (Instrumenter : C_Family_Instrumenter_Type'Class; + Part : GNATCOLL.Projects.Unit_Parts; + Project : GNATCOLL.Projects.Project_Type) return String + is + L : constant C_Family_Language := Instrumenter.Language; + Attr : constant GPR.Attribute_Pkg_String := + GPR.Build + (Package_Name => "Naming", + Attribute_Name => + (case Part is + when GPR.Unit_Body => "Body_Suffix", + when GPR.Unit_Spec => "Spec_Suffix", + when GPR.Unit_Separate => raise Program_Error)); + begin + case Part is + when GPR.Unit_Body => + return Project.Attribute_Value + (Attribute => Attr, + Index => Image (L), + Default => (case L is + when C_Language => ".c", + when CPP_Language => ".cpp")); + + when GPR.Unit_Spec => + return Project.Attribute_Value + (Attribute => Attr, + Index => Image (L), + Default => (case L is + when C_Language => ".h", + when CPP_Language => ".hh")); + + when GPR.Unit_Separate => + return (raise Program_Error); + end case; + end Source_Suffix; + ----------------- -- Enter_Scope -- ----------------- @@ -2391,6 +2536,71 @@ package body Instrument.C is UIC.MCDC_State_Declaration_Node := Saved_MCDC_State_Declaration_Node; end Traverse_Declarations; + ---------------------------- + -- Parse_Macro_Definition -- + ---------------------------- + + procedure Parse_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean) + is + Matches : Match_Array (0 .. 3); + begin + Match (Macro_Def_Regexp, Str, Matches); + if Matches (0) = No_Match then + Success := False; + else + Success := True; + Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); + if Matches (2) /= No_Match then + Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); + end if; + Parsed_Def.Value := +Str (Matches (3).First .. Matches (3).Last); + end if; + end Parse_Macro_Definition; + + ------------------------------------ + -- Parse_Cmdline_Macro_Definition -- + ------------------------------------ + + procedure Parse_Cmdline_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean) + is + Matches : Match_Array (0 .. 4); + begin + Match (Macro_Cmdline_Regexp, Str, Matches); + if Matches (0) = No_Match then + Success := False; + else + Success := True; + Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); + if Matches (2) /= No_Match then + Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); + end if; + + -- Command line macros can have part of their value before the + -- assignment, e.g. "-DA(b)b" is equivalent to "#define A(b) b 1". + + if Matches (3) /= No_Match then + Append + (Parsed_Def.Value, + Str (Matches (3).First .. Matches (3).Last) & " "); + end if; + + -- If no value is given, then it is implicitly 1 + + if Matches (4) /= No_Match then + Append + (Parsed_Def.Value, Str (Matches (4).First .. Matches (4).Last)); + else + Append (Parsed_Def.Value, " 1"); + end if; + end if; + end Parse_Cmdline_Macro_Definition; + -------------------- -- Builtin_Macros -- -------------------- @@ -2399,68 +2609,82 @@ package body Instrument.C is (Lang, Compiler, Std, Output_Dir : String) return Macro_Set_Cst_Access is use Ada.Characters.Handling; - - PID : constant Unsigned_64 := - Unsigned_64 (Pid_To_Integer (Current_Process_Id)); + use Compiler_Macros_Maps; L : constant String := To_Lower (Lang); Key : constant Unbounded_String := +Compiler & " -x " & L & " " & Std; - Result : constant Macro_Set_Access := new Macro_Set; - - Args : String_Vectors.Vector; - Basename : constant String := - Ada.Directories.Simple_Name (Compiler) - & "_builtins_" - & Hex_Image (PID); - Filename : constant String := Output_Dir / Basename; - File : Ada.Text_IO.File_Type; + Cur : constant Cursor := Compiler_Macros.Find (Key); + Result : Macro_Set_Access; begin - -- Run the preprocessor on an empty file and write the - -- preprocessed sources to Filename. + -- If we already computed builtin macros for Compiler, return the cached + -- result. Compute it now otherwise. - Args.Append (+"-x"); - Args.Append (+L); - if Std'Length /= 0 then - Args.Append (+Std); - end if; - Args.Append (+"-E"); - Args.Append (+"-dM"); - Args.Append (+"-"); - - Run_Command - (Command => Compiler, - Arguments => Args, - Origin_Command_Name => - "getting built-in macros for " & (+Key), - Output_File => Filename, - In_To_Null => True); - - -- Decode all macro definitions in Filename and store them in Result - - Open (File, In_File, Filename); - while not End_Of_File (File) loop + if Has_Element (Cur) then + Result := Element (Cur); + + else + Result := new Macro_Set; declare - Line : constant String := Get_Line (File); - Macro_Def : Macro_Definition (Define => True); - Success : Boolean; + Args : String_Vectors.Vector; + Basename : constant String := + Ada.Directories.Simple_Name (Compiler) & "_builtins"; + Filename : constant String := Output_Dir / Basename; + File : Ada.Text_IO.File_Type; begin - Parse_Macro_Definition - (Line, - Macro_Def, - Success); - if Success then - Result.Include (Macro_Def); - else - Warn - ("Cannot parse a built-in macro definition for " - & Compiler & ", ignoring it:" & ASCII.LF & " " - & Line); + -- Run the preprocessor on an empty file and write the + -- preprocessed sources to Filename. + + Args.Append (+"-x"); + Args.Append (+L); + if Std'Length /= 0 then + Args.Append (+Std); end if; + Args.Append (+"-E"); + Args.Append (+"-dM"); + Args.Append (+"-"); + + Run_Command + (Command => Compiler, + Arguments => Args, + Origin_Command_Name => + "getting built-in macros for " & (+Key), + Output_File => Filename, + In_To_Null => True); + + -- Decode all macro definitions in Filename and store them in + -- Result. + + Open (File, In_File, Filename); + while not End_Of_File (File) loop + declare + Line : constant String := Get_Line (File); + Macro_Def : Macro_Definition (Define => True); + Success : Boolean; + begin + Parse_Macro_Definition + (Line, + Macro_Def, + Success); + if Success then + Result.Include (Macro_Def); + else + Warn + ("Cannot parse a built-in macro definition for " + & Compiler & ", ignoring it:" & ASCII.LF & " " + & Line); + end if; + end; + end loop; + Close (File); + Delete_File (Filename); + + -- Save Result in the cache for later use + + Compiler_Macros.Insert (Key, Result); end; - end loop; - Close (File); - Delete_File (Filename); + end if; + return Macro_Set_Cst_Access (Result); end Builtin_Macros; @@ -2471,8 +2695,8 @@ package body Instrument.C is procedure Preprocess_Source (Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc; PP_Filename : out Unbounded_String; + Info : in out Project_Info; Options : in out Analysis_Options) is Cmd : Command_Type; @@ -2485,26 +2709,31 @@ package body Instrument.C is Unsigned_64 (Pid_To_Integer (Current_Process_Id)); Preprocessed_Filename : constant String := - (+Prj.Output_Dir) / ("pp-" & Strip_Zero_Padding (Hex_Image (PID))); + (+Info.Output_Dir) / ("pp-" & Strip_Zero_Padding (Hex_Image (PID))); -- Preprocessed file. We then postprocess it to remove redundant line -- markers inserted by the preprocessor. Preprocessor_Output_Filename : constant String := - (+Prj.Output_Dir) / + (+Info.Output_Dir) / ("pp-output-" & Strip_Zero_Padding (Hex_Image (PID))); Preprocessor_Output_File : Ada.Text_IO.File_Type; -- File containing the preprocessor output (used to get include search -- paths). begin - PP_Filename := +New_File (Prj, Filename); + PP_Filename := +New_File (Info, Filename); + + -- The file may have been preprocessed already, if we are instrumenting + -- it as a main after having instrumented it as a source. In this case, + -- we should not preprocess it again (as it will fail). HACK: if the + -- original filename is an instrumented file (in which case it is + -- equal to PP_Filename), skip the preprocessing step. - -- HACK: consider that the file was already preprocessed in that case if +PP_Filename = Filename then return; end if; Cmd := - (Command => Prj.Compiler_Driver (Instrumenter.Language), + (Command => +Compiler_Driver (Info.Project, Instrumenter.Language), others => <>); -- Add the preprocessing flag @@ -2649,9 +2878,9 @@ package body Instrument.C is procedure Start_Rewriting (Self : out C_Source_Rewriter; + Info : in out Project_Info; Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc; Preprocessed : Boolean := False) is PP_Filename : Unbounded_String := +Filename; @@ -2659,10 +2888,10 @@ package body Instrument.C is Options : Analysis_Options; Args : String_Vectors.Vector; begin - Import_Options (Options, Instrumenter, Prj, Filename); + Import_Options (Options, Instrumenter.Language, Info, Filename); if not Preprocessed then Preprocess_Source - (Filename, Instrumenter, Prj, PP_Filename, Options); + (Filename, Instrumenter, PP_Filename, Info, Options); end if; Self.CIdx := @@ -2752,11 +2981,11 @@ package body Instrument.C is -------------------- procedure Record_PP_Info - (Orig_Filename : String; - UIC : in out C_Unit_Inst_Context; - Instrumenter : C_Family_Instrumenter_Type'Class) + (Unit_Info : Instrumented_Unit_Info; + UIC : in out C_Unit_Inst_Context) is - Args : String_Vectors.Vector; + Orig_Filename : constant String := +Unit_Info.Filename; + Args : String_Vectors.Vector; begin UIC.Pass := Record_PP_Info_Pass'Access; UIC.CIdx := @@ -2768,8 +2997,7 @@ package body Instrument.C is -- the user's preprocessor. Add_Options (Args, UIC.Options); - String_Vectors.Append - (Args, Common_Parse_TU_Args (Instrumenter.Language)); + String_Vectors.Append (Args, Common_Parse_TU_Args (Unit_Info.Language)); -- TODO??? We should also inhibit the use of clang predefined macros, -- with the -undef option, but doing this yields parsing errors, and a @@ -2809,31 +3037,24 @@ package body Instrument.C is end Record_PP_Info; - --------------------- - -- Instrument_Unit -- - --------------------- + ---------------------------- + -- Instrument_Source_File -- + ---------------------------- - procedure Instrument_Unit - (Self : in out C_Family_Instrumenter_Type; - Unit_Name : String; - Prj : Prj_Desc; - Files_Of_Interest : String_Sets.Set) + procedure Instrument_Source_File + (CU_Name : Compilation_Unit_Name; + Unit_Info : Instrumented_Unit_Info; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj_Info : in out Project_Info; + UIC : out C_Unit_Inst_Context) is - UIC : C_Unit_Inst_Context; - CU_Name : constant Compilation_Unit_Part := - CU_Name_For_File (+Unit_Name); - - Orig_Filename : constant String := Unit_Name; + Orig_Filename : constant String := +Unit_Info.Filename; PP_Filename : Unbounded_String; -- Respectively original, and preprocessed filename Buffer_Filename : constant String := - New_File - (Prj, - To_Symbol_Name (Sys_Prefix) & "_b_" - & Instrumented_Unit_Slug (CU_Name) - & (+Prj.Body_Suffix - (C_Family_Instrumenter_Type'Class (Self).Language))); + To_Symbol_Name (Sys_Buffers) & "_b_" & Instrumented_Unit_Slug (CU_Name) + & Source_Suffix (Instrumenter, GPR.Unit_Body, Prj_Info.Project); -- Name of the generated source file holding the coverage buffers Rewriter : C_Source_Rewriter; @@ -2871,7 +3092,7 @@ package body Instrument.C is Put_Extern_Decl (UIC.Rewriter, Insert_Extern_Location, - Self, + Instrumenter, C_Type, Name, Array_Size, @@ -2881,46 +3102,30 @@ package body Instrument.C is -- Start of processing for Instrument_Source_File begin - -- Exit early if there is no compiler driver found to preprocess the - -- source. - - declare - Compiler_Driver : constant Unbounded_String := - Prj.Compiler_Driver - (C_Family_Instrumenter_Type'Class (Self).Language); - begin - if Compiler_Driver = Null_Unbounded_String then - Outputs.Fatal_Error - ("could not find a compiler for " - & Image - (C_Family_Instrumenter_Type'Class (Self).Language)); - end if; - end; - SCOs.Initialize; UIC.SFI := Get_Index_From_Generic_Name (Orig_Filename, Kind => Files_Table.Source_File, Indexed_Simple_Name => True); - UIC.Fullname := +Orig_Filename; -- Initialize the C instrumentation context UIC.Instrumented_Unit := CU_Name; - UIC.Buffer_Unit := CU_Name_For_File (+Buffer_Filename); - UIC.Files_Of_Interest := Files_Of_Interest; + UIC.Buffer_Unit := + CU_Name_For_File (+Buffer_Filename, CU_Name.Project_Name); -- Import analysis options for the file to preprocess, then run the -- preprocessor. - Import_Options (UIC.Options, Self, Prj, Unit_Name); + Import_Options + (UIC.Options, Instrumenter.Language, Prj_Info, Orig_Filename); Preprocess_Source - (Orig_Filename, Self, Prj, PP_Filename, UIC.Options); + (Orig_Filename, Instrumenter, PP_Filename, Prj_Info, UIC.Options); -- Start by recording preprocessing information - Record_PP_Info (Orig_Filename, UIC, Self); + Record_PP_Info (Unit_Info, UIC); -- Then record exemption annotations in the comments. Reuse the TU from -- the preprocessing information recording pass as we want the @@ -2986,12 +3191,11 @@ package body Instrument.C is UIC.Pass := Instrument_Pass'Access; - Start_Rewriting - (Self => Rewriter, - Filename => +PP_Filename, - Instrumenter => Self, - Prj => Prj, - Preprocessed => True); + Start_Rewriting (Self => Rewriter, + Info => Prj_Info, + Filename => +PP_Filename, + Instrumenter => Instrumenter, + Preprocessed => True); UIC.TU := Rewriter.TU; UIC.Rewriter := Rewriter.Rewriter; Insert_Extern_Location := @@ -3113,7 +3317,7 @@ package body Instrument.C is end if; end if; - -- Create mappings from allocated bits to the corresponding SCO + -- Create mappings from alloacted bits to the corresponding SCO -- discharging information (Bit_Maps). Bit_Maps := @@ -3243,29 +3447,7 @@ package body Instrument.C is & " unsigned value"); Rewriter.Apply; - - -- Generate a buffer compilation unit defining coverage buffers that - -- will store execution witnesses. This CU is a C file rather than an - -- Ada file exporting the defined symboled to C. Indeed, we want it to - -- be compatible with a C-only compiler. - - Emit_Buffer_Unit - (UIC, - Compilation_Unit' - (Language => File_Based_Language, - Unit_Name => UIC.Fullname), - Self, - Prj); - - -- Update the Ignore_Status of the CU we instrumented - - Files_Table.Consolidate_Ignore_Status - (Index => Files_Table.Get_Index_From_Generic_Name - (Name => Orig_Filename, - Kind => Files_Table.Source_File, - Indexed_Simple_Name => True), - Status => Files_Table.Never); - end Instrument_Unit; + end Instrument_Source_File; ---------------------------- -- Format_Array_Init_Expr -- @@ -3306,12 +3488,11 @@ package body Instrument.C is ---------------------- procedure Emit_Buffer_Unit - (UIC : C_Unit_Inst_Context'Class; - Unit : Compilation_Unit; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc) + (Info : in out Project_Info; + UIC : C_Unit_Inst_Context'Class; + Instrumenter : C_Family_Instrumenter_Type'Class) is - CU_Name : Compilation_Unit_Part renames UIC.Buffer_Unit; + CU_Name : Compilation_Unit_Name renames UIC.Buffer_Unit; File : Text_Files.File_Type; Buffers_Count : constant Natural := Natural (UIC.Allocated_Bits.Length); @@ -3354,12 +3535,12 @@ package body Instrument.C is begin -- Compute Buffers_Filenames and Buffers_Projects - for Cur in UIC.Sources_Of_Interest_Info.Iterate loop + for Cur in UIC.Sources_Of_Interest.Iterate loop declare use Created_Unit_Maps; SOI : Source_Of_Interest renames - UIC.Sources_Of_Interest_Info.Constant_Reference (Cur); + UIC.Sources_Of_Interest.Constant_Reference (Cur); Cur : Cursor; Index : Natural; begin @@ -3383,7 +3564,7 @@ package body Instrument.C is -- Start to emit the buffer unit - Create_File (Prj, File, +CU_Name.Filename); + Create_File (Info, File, +CU_Name.Filename); File.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); File.New_Line; @@ -3413,7 +3594,7 @@ package body Instrument.C is UIC.Allocated_Bits.Constant_Reference (Buffers_Index); CU : constant CU_Id := Buffers_CUs (Buffers_Index); - CU_Name : Compilation_Unit_Part renames + CU_Name : Compilation_Unit_Name renames Buffers_CU_Names.Constant_Reference (Buffers_Index); -- Symbol name for each kind of static buffer @@ -3474,6 +3655,9 @@ package body Instrument.C is & " .unit_name = " & Format_Str_Constant (+CU_Name.Filename) & "," & ASCII.LF + & " .project_name = " + & Format_Str_Constant (+CU_Name.Project_Name) & "," + & ASCII.LF & " .bit_maps_fingerprint = " & Format_Fingerprint (SC_Obligations.Bit_Maps_Fingerprint (CU)) @@ -3558,7 +3742,7 @@ package body Instrument.C is (File, Instrumenter, "const struct gnatcov_rts_coverage_buffers_group", - Unit_Buffers_Name (Unit), + Unit_Buffers_Name (UIC.Instrumented_Unit), Init_Expr => "{" & Img (Buffers_Count) & ", &" & Buffers_Array & "[0]}"); end; @@ -3569,11 +3753,11 @@ package body Instrument.C is --------------------------- procedure Emit_Dump_Helper_Unit - (Dump_Config : Any_Dump_Config; - Main : Compilation_Unit_Part; - Helper_Unit : out US.Unbounded_String; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc) + (Dump_Config : Any_Dump_Config; + Info : in out Project_Info; + Main : Compilation_Unit_Name; + Helper_Unit : out US.Unbounded_String; + Instrumenter : C_Family_Instrumenter_Type'Class) is File : Text_Files.File_Type; @@ -3593,7 +3777,8 @@ package body Instrument.C is To_Symbol_Name (Sys_Buffers) & "_d_" & Instrumented_Unit_Slug (Main) - & Prj.Body_Suffix (Instrumenter.Language); + & US.To_Unbounded_String + (Source_Suffix (Instrumenter, GPR.Unit_Body, Info.Project)); -- Compute the qualified names we need for instrumentation @@ -3604,7 +3789,7 @@ package body Instrument.C is begin -- Emit the package body - Create_File (Prj, File, Filename); + Create_File (Info, File, Filename); File.Put_Line ("#include ""gnatcov_rts_c-strings.h"""); @@ -3625,7 +3810,7 @@ package body Instrument.C is (File, Instrumenter, "const struct gnatcov_rts_coverage_buffers_group_array", - Unit_Buffers_Array_Name (+Prj.Prj_Name)); + Unit_Buffers_Array_Name (Project.Project.Root_Project.Name)); -- Emit the procedure to write the trace file @@ -3635,18 +3820,26 @@ package body Instrument.C is File.Put_Line (Indent1 & Output_Proc & " ("); File.Put_Line - (Indent2 & "&" - & Unit_Buffers_Array_Name (+Prj.Prj_Name) & ","); + (Indent2 & "&" + & Unit_Buffers_Array_Name (Project.Project.Root_Project.Name) + & ","); case Dump_Config.Channel is when Binary_File => declare + use GNATCOLL.VFS; + Env_Var : constant String := (if US.Length (Dump_Config.Filename_Env_Var) = 0 then "GNATCOV_RTS_DEFAULT_TRACE_FILENAME_ENV_VAR" else """" & (+Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := - """" & (+Dump_Config.Filename_Prefix) & """"; - Tag : constant String := """" & (+Instrumenter.Tag) & """"; + (if US.Length (Dump_Config.Filename_Prefix) = 0 + then """" & String'(+Info.Project.Executable_Name + (+(+Main.Filename), + Include_Suffix => True)) & """" + else """" & (+Dump_Config.Filename_Prefix) & """"); + Tag : constant String := + """" & Trace_Filename_Tag & """"; Simple : constant String := (if Dump_Config.Filename_Simple then "1" else "0"); begin @@ -3688,18 +3881,21 @@ package body Instrument.C is ------------------------------- overriding procedure Auto_Dump_Buffers_In_Main - (Self : in out C_Family_Instrumenter_Type; - Filename : String; - Dump_Config : Any_Dump_Config; - Prj : Prj_Desc) + (Self : in out C_Family_Instrumenter_Type; + Filename : String; + Instr_Units : CU_Name_Vectors.Vector; + Dump_Config : Any_Dump_Config; + Info : in out Project_Info) is + Helper_Filename : US.Unbounded_String; -- Name of file to contain helpers implementing the buffers dump Rew : C_Source_Rewriter; - Main : constant Compilation_Unit_Part := + Main : constant Compilation_Unit_Name := (Language_Kind => File_Based_Language, - Filename => +Ada.Directories.Full_Name (Filename)); + Filename => +Ada.Directories.Simple_Name (Filename), + Project_Name => +Info.Project.Name); Insert_Extern_Location : Source_Location_T; -- Where to insert extern declarations @@ -3707,19 +3903,18 @@ package body Instrument.C is Main_Cursor : Cursor_T; -- Cursor of the main declaration begin - Rew.Start_Rewriting (Filename, Self, Prj); + Rew.Start_Rewriting (Info, Filename, Self); Insert_Extern_Location := Start_Sloc (Get_Translation_Unit_Cursor (Rew.TU)); Main_Cursor := Get_Main (Rew.TU); if Main_Cursor = Get_Null_Cursor then - Outputs.Fatal_Error - ("Could not find main function in " - & (Ada.Directories.Simple_Name (+Main.Filename))); + Outputs.Fatal_Error ("Could not find main function in " + & (+Main.Filename)); end if; Emit_Dump_Helper_Unit - (Dump_Config, Main, Helper_Filename, Self, Prj); + (Dump_Config, Info, Main, Helper_Filename, Self); Put_Extern_Decl (Rew.Rewriter, @@ -4006,34 +4201,30 @@ package body Instrument.C is (Format_Extern_Decl (Instrumenter, C_Type, Name, Func_Args)); end Put_Extern_Decl; + ---------------------------- + -- Emit_Buffers_List_Unit -- + ---------------------------- + overriding procedure Emit_Buffers_List_Unit - (Self : C_Family_Instrumenter_Type; - Instr_Units : Unit_Sets.Set; - Prj : Prj_Desc) + (Self : C_Family_Instrumenter_Type; + Root_Project_Info : in out Project_Info; + Instr_Units : CU_Name_Vectors.Vector) is - Base_Filename : constant String := - "gnatcov_rts_c-buffers-lists-" & (+Prj.Prj_Name); - CU_Name_Body : constant String := - Base_Filename - & (+Prj.Body_Suffix - (C_Family_Instrumenter_Type'Class (Self).Language)); - CU_Name_Header : constant String := - Base_Filename - & (+Prj.Spec_Suffix - (C_Family_Instrumenter_Type'Class (Self).Language)); - - File_Body : Text_Files.File_Type; - File_Header : Text_Files.File_Type; + Project_Name : String renames Root_Project_Info.Project.Name; + CU_Name_Body : constant String := + "gnatcov_rts_c-buffers-lists-" & Project_Name + & Source_Suffix (Self, GPR.Unit_Body, Root_Project_Info.Project); + File_Body : Text_Files.File_Type; Buffer_Array_Decl : constant String := "const struct gnatcov_rts_coverage_buffers_group_array " - & Unit_Buffers_Array_Name (+Prj.Prj_Name); + & Unit_Buffers_Array_Name (Project_Name); Buffer_Unit_Length : constant String := Count_Type'Image (Instr_Units.Length); begin -- Emit the body to contain the list of buffers - Create_File (Prj, File_Body, CU_Name_Body); + Create_File (Root_Project_Info, File_Body, CU_Name_Body); File_Body.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); @@ -4047,33 +4238,308 @@ package body Instrument.C is Unit_Buffers_Name (Instr_Unit)); end loop; - -- Then create an extern declaration for the buffer array (necessary in - -- C++ to set the C linkage), and finally the definition for that array. + -- Then create an extern declaration for the buffer array (necessary + -- in C++ to set the C linkage), and finally the definition for that + -- array. File_Body.Put_Line (Self.Extern_Prefix & Buffer_Array_Decl & ";"); File_Body.Put_Line (Buffer_Array_Decl & " = {"); File_Body.Put_Line (" " & Buffer_Unit_Length & ","); File_Body.Put_Line (" (const struct gnatcov_rts_coverage_buffers_group *[]) {"); - for Instr_Unit of Instr_Units loop - File_Body.Put (" &" & Unit_Buffers_Name (Instr_Unit)); - if Instr_Unit = Instr_Units.Last_Element then - File_Body.Put_Line ("}};"); - else - File_Body.Put_Line (","); - end if; + for Cur in Instr_Units.Iterate loop + declare + use CU_Name_Vectors; + begin + File_Body.Put (" &" & Unit_Buffers_Name (Element (Cur))); + if To_Index (Cur) = Instr_Units.Last_Index then + File_Body.Put_Line ("}};"); + else + File_Body.Put_Line (","); + end if; + end; end loop; + end Emit_Buffers_List_Unit; - -- Emit the extern declaration of the buffers array in the header file + --------------------- + -- Instrument_Unit -- + --------------------- - Create_File (Prj, File_Header, CU_Name_Header); + overriding procedure Instrument_Unit + (Self : in out C_Family_Instrumenter_Type; + CU_Name : Compilation_Unit_Name; + Unit_Info : in out Instrumented_Unit_Info) + is + Prj_Info : Project_Info renames Unit_Info.Prj_Info.all; + UIC : C_Unit_Inst_Context; + begin + Instrument_Source_File + (CU_Name => CU_Name, + Unit_Info => Unit_Info, + Instrumenter => Self, + Prj_Info => Prj_Info, + UIC => UIC); - Put_Extern_Decl - (File_Header, - Self, - "const struct gnatcov_rts_coverage_buffers_group_array", - Unit_Buffers_Array_Name (+Prj.Prj_Name)); - end Emit_Buffers_List_Unit; + -- Generate a buffer compilation unit defining coverage buffers that + -- will store execution witnesses. This CU is a C file rather than an + -- Ada file exporting the defined symboled to C. Indeed, we want it to + -- be compatible with a C-only compiler. + + Emit_Buffer_Unit (Prj_Info, UIC, Self); + end Instrument_Unit; + + ---------------------- + -- Skip_Source_File -- + ---------------------- + + overriding function Skip_Source_File + (Self : C_Family_Instrumenter_Type; + Source_File : GNATCOLL.Projects.File_Info) return Boolean is + begin + -- Do not instrument C headers: code in C header is meant to be + -- instrumented at the time it is included in a ".c" source. + + return Source_File.Unit_Part = Unit_Spec; + end Skip_Source_File; + + ----------------- + -- Add_Options -- + ----------------- + + procedure Add_Options + (Args : in out String_Vectors.Vector; + Options : Analysis_Options; + Pass_Builtins : Boolean := True; + Preprocessed : Boolean := False) is + + procedure Add_Macro_Switches (Macros : Macro_Set); + -- Add the given macro switches to Args + + ------------------------ + -- Add_Macro_Switches -- + ------------------------ + + procedure Add_Macro_Switches (Macros : Macro_Set) is + begin + for M of Macros loop + if M.Define then + Args.Append ("-D" & M.Name & M.Args & "=" & M.Value); + else + Args.Append ("-U" & M.Name); + end if; + end loop; + end Add_Macro_Switches; + + begin + for Dir of Options.PP_Search_Path loop + Args.Append (+"-I"); + Args.Append (Dir); + end loop; + + -- If the file was already pre-processed, do not pass macro command + -- line switches. Since preprocessed code can contain names of defined + -- macros, passing macro arguments for the parsing step could trigger + -- other expansions, and thus feed the parser with unexpected code. + + if not Preprocessed then + + -- Add builtin macros before macros from command line switches, as + -- the latter should have precedence over builtins and thus must + -- come last in Args. + + if Pass_Builtins then + Add_Macro_Switches (Options.Builtin_Macros); + end if; + Add_Macro_Switches (Options.PP_Macros); + end if; + + -- The -std switch also indicates the C/C++ version used, and + -- influences both the configuration of the preprocessor, and the + -- parsing of the file. + + if Length (Options.Std) /= 0 then + Args.Append (Options.Std); + end if; + + end Add_Options; + + ------------------------- + -- Import_From_Project -- + ------------------------- + + procedure Import_From_Project + (Self : out Analysis_Options; + Language : C_Family_Language; + Info : Project_Info; + Filename : String) + is + procedure Register_Source_Dirs (P : GNATCOLL.Projects.Project_Type); + -- Add the source directories of P's project file to the search paths + -- to be passed as -I arguments later. The order in which the paths are + -- added to the search paths vector is the same order in which GNATCOLL + -- retrieves the files in the project tree. gprbuild also depends on + -- GNATCOLL which ensures we have the same behavior here. + + -------------------------- + -- Register_Source_Dirs -- + -------------------------- + + procedure Register_Source_Dirs (P : GNATCOLL.Projects.Project_Type) is + begin + for Dir of P.Source_Dirs loop + Self.PP_Search_Path.Append + (+GNATCOLL.VFS."+" (GNATCOLL.VFS.Dir_Name (Dir))); + end loop; + end Register_Source_Dirs; + + Switches : GNAT.Strings.String_List_Access; + + begin + + -- Pass the source directories of the project file as -I options. Note + -- that this will duplicate with the project tree traversal below, but + -- we need this project source directories to be picked first. We thus + -- make sure to add them first to the PP_Search_Path list. + + Register_Source_Dirs (Info.Project); + + -- Pass the source directories of included projects as -I options + + Project.Iterate_Projects + (Info.Project, Register_Source_Dirs'Access, + Recursive => True, Include_Extended => True); + + -- Now get actual compiler switches from the project file for Filename. + -- First try to get the switches specifically for Filename, then if + -- there are none fall back to default switches for C. + + Switches := + Info.Project.Attribute_Value + (Attribute => GPR.Build ("compiler", "switches"), + Index => Simple_Name (Filename)); + + if Switches = null then + Switches := + Info.Project.Attribute_Value + (Attribute => GPR.Compiler_Default_Switches_Attribute, + Index => Image (Language)); + end if; + + -- If we manage to find appropriate switches, convert them to a string + -- vector import the switches. + + if Switches /= null then + declare + Args : String_Vectors.Vector; + begin + for S of Switches.all loop + Args.Append (To_Unbounded_String (S.all)); + end loop; + GNAT.Strings.Free (Switches); + Import_From_Args (Self, Args); + end; + end if; + end Import_From_Project; + + ---------------------- + -- Import_From_Args -- + ---------------------- + + procedure Import_From_Args + (Self : in out Analysis_Options; Args : String_Vectors.Vector) + is + I : Natural := Args.First_Index; + Last : constant Integer := Args.Last_Index; + + function Read_With_Argument + (Arg : String; + Option_Name : Character; + Value : out Unbounded_String) return Boolean; + -- Assuming that Arg starts with "-X" where X is Option_Name, try to + -- fetch the value for this option. If we managed to get one, return + -- True and set Value to it. Return False otherwise. + + ------------------------ + -- Read_With_Argument -- + ------------------------ + + function Read_With_Argument + (Arg : String; + Option_Name : Character; + Value : out Unbounded_String) return Boolean + is + Prefix : constant String := "-" & Option_Name; + begin + if Arg = Prefix then + + -- Option and value are two separate arguments (-O VALUE) + + I := I + 1; + if I <= Last then + Value := Args (I); + return True; + end if; + + elsif Has_Prefix (Arg, Prefix) then + + -- Option and value are combined in a single argument (-OVALUE) + + Value := +Arg (Arg'First + Prefix'Length .. Arg'Last); + return True; + end if; + + return False; + end Read_With_Argument; + + -- Start of processing for Import_From_Args + + begin + while I <= Last loop + declare + A : constant String := +Args (I); + Value : Unbounded_String; + begin + + -- Process arguments we manage to handle, silently discard unknown + -- ones. + -- + -- TODO??? In order to avoid surprising situations for users (for + -- instance typos in command line arguments), maybe we should emit + -- a warning for unknown arguments. However, given that this + -- procedure is called at least once per instrumented source file, + -- we would need to avoid emitting duplicate warnings. + + if Read_With_Argument (A, 'I', Value) then + Self.PP_Search_Path.Append (Value); + + elsif Read_With_Argument (A, 'D', Value) then + declare + Macro_Def : Macro_Definition (Define => True); + Success : Boolean; + begin + Parse_Cmdline_Macro_Definition + (Str => +Value, + Parsed_Def => Macro_Def, + Success => Success); + if Success then + Self.PP_Macros.Include (Macro_Def); + else + Warn ("Failed to parse command-line macro definition: " + & (+Value)); + end if; + end; + + elsif Read_With_Argument (A, 'U', Value) then + Self.PP_Macros.Include ((Define => False, Name => Value)); + + elsif Has_Prefix (A, "-std=") then + Self.Std := +A; + end if; + + I := I + 1; + end; + end loop; + end Import_From_Args; ---------------- -- Split_Args -- @@ -4145,31 +4611,18 @@ package body Instrument.C is -------------------- procedure Import_Options - (Self : out Analysis_Options; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc; - Filename : String) + (Self : out Analysis_Options; + Language : C_Family_Language; + Info : Project_Info; + Filename : String) is Cmdline_Opts : constant String_Vectors.Vector := To_String_Vector - (case C_Family_Language (Instrumenter.Language) is + (case Language is when C_Language => C_Opts, when CPP_Language => CPP_Opts); - Prj_Options : String_Vectors.Vector; begin - -- Grab the options from the project description. Note that the project - -- description is filled with compiler options in the -j1 - -- implementation. Otherwise, the compiler switches in the project files - -- are passed through the command line directly. - - if Prj.Compiler_Options_Unit.Contains (+Filename) then - Prj_Options.Append (Prj.Compiler_Options_Unit.Element (+Filename)); - else - Prj_Options.Append (Prj.Compiler_Options (Instrumenter.Language)); - end if; - Prj_Options.Append (Prj.Search_Paths); - - Import_From_Args (Self, Prj_Options); + Import_From_Project (Self, Language, Info, Filename); for Args of Cmdline_Opts loop Import_From_Args (Self, Split_Args (Args)); end loop; @@ -4179,10 +4632,10 @@ package body Instrument.C is Self.Builtin_Macros := Builtin_Macros - (Image (C_Family_Language (Instrumenter.Language)), - +Prj.Compiler_Driver (Instrumenter.Language), + (Image (Language), + Compiler_Driver (Info.Project, Language), +Self.Std, - +Prj.Output_Dir).all; + +Info.Output_Dir).all; end Import_Options; --------------------------- @@ -4210,29 +4663,34 @@ package body Instrument.C is -- if it is missing. declare + use GNATCOLL.VFS; use Source_Of_Interest_Maps; - Cur : constant Cursor := UIC.Sources_Of_Interest_Info.Find (File); + Cur : constant Cursor := UIC.Sources_Of_Interest.Find (File); SOI : Source_Of_Interest; + FI : GNATCOLL.Projects.File_Info; begin if Has_Element (Cur) then - return UIC.Sources_Of_Interest_Info.Reference (Cur).Of_Interest; + return UIC.Sources_Of_Interest.Reference (Cur).Of_Interest; end if; -- Consider that File is of interest iff it belongs to a loaded - -- project. TODO???: this should also consider units of interest - -- switches. + -- project. - if UIC.Files_Of_Interest.Contains (File) then + FI := Project.Project.Info (Create (+To_String (File))); + if FI.Project /= No_Project then SOI := (Of_Interest => True, SFI => Get_Index_From_Generic_Name (+File, Source_File), - CU_Name => CU_Name_For_File (File)); + CU_Name => + CU_Name_For_File + (Filename => +Simple_Name (+File), + Project_Name => UIC.Instrumented_Unit.Project_Name)); else SOI := (Of_Interest => False); end if; - UIC.Sources_Of_Interest_Info.Insert (File, SOI); + UIC.Sources_Of_Interest.Insert (File, SOI); return SOI.Of_Interest; end; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index f9d89c4c5..af0be0c00 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -20,10 +20,14 @@ with Ada.Containers.Hashed_Maps; with Ada.Containers.Ordered_Maps; +with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; with Ada.Finalization; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Hash; +with GNATCOLL.Projects; + with Namet; use Namet; with Clang.Index; use Clang.Index; @@ -39,22 +43,26 @@ package Instrument.C is abstract new Language_Instrumenter with null record; -- Common instrumentation primitives for C/C++ + overriding function Skip_Source_File + (Self : C_Family_Instrumenter_Type; + Source_File : GNATCOLL.Projects.File_Info) return Boolean; + overriding procedure Instrument_Unit - (Self : in out C_Family_Instrumenter_Type; - Unit_Name : String; - Prj : Prj_Desc; - Files_Of_Interest : String_Sets.Set); + (Self : in out C_Family_Instrumenter_Type; + CU_Name : Compilation_Unit_Name; + Unit_Info : in out Instrumented_Unit_Info); overriding procedure Auto_Dump_Buffers_In_Main (Self : in out C_Family_Instrumenter_Type; Filename : String; + Instr_Units : CU_Name_Vectors.Vector; Dump_Config : Any_Dump_Config; - Prj : Prj_Desc); + Info : in out Project_Info); overriding procedure Emit_Buffers_List_Unit - (Self : C_Family_Instrumenter_Type; - Instr_Units : Unit_Sets.Set; - Prj : Prj_Desc); + (Self : C_Family_Instrumenter_Type; + Root_Project_Info : in out Project_Info; + Instr_Units : CU_Name_Vectors.Vector); function Extern_Prefix (Self : C_Family_Instrumenter_Type) return String @@ -69,12 +77,6 @@ package Instrument.C is (Self : C_Instrumenter_Type) return Src_Supported_Language is (C_Language); - function Create_C_Instrumenter - (Tag : Unbounded_String) return C_Instrumenter_Type - is (C_Instrumenter_Type'(Tag => Tag)); - -- Create a C instrumenter. See the definition of the - -- Language_Instrumenter type for the arguments semantic. - type CPP_Instrumenter_Type is new C_Family_Instrumenter_Type with null record; -- Instrumentation primitives for C++ @@ -87,12 +89,6 @@ package Instrument.C is (Self : CPP_Instrumenter_Type) return String is ("extern ""C"" "); - function Create_CPP_Instrumenter - (Tag : Unbounded_String) return CPP_Instrumenter_Type - is (CPP_Instrumenter_Type'(Tag => Tag)); - -- Create a C++ instrumenter. See the definition of the - -- Language_Instrumenter type for the arguments semantic. - type Instr_Scheme_Type is (Instr_Stmt, Instr_Expr); -- Depending on the statement construct, we can instrument it either with -- another statement right before (Instr_Stmt), which is the case for most @@ -236,14 +232,81 @@ package Instrument.C is (Key_Type => Nat, Element_Type => PP_Info); + type Macro_Definition (Define : Boolean := True) is record + Name : Unbounded_String; + -- Name of the macro + + case Define is + when True => + Args : Unbounded_String; + -- String representation of the macro arguments, e.g. (x, y) + + Value : Unbounded_String; + -- Value for the macro definition + + when False => + null; + end case; + end record; + -- Whether a macro should be defined, its name, and when it must be + -- defined, its optional arguments and value. + + function "<" (L, R : Macro_Definition) return Boolean is (L.Name < R.Name); + -- As we store Macro_Definition in sets, we do not want two conflicting + -- definitions of the same macro to coexist. Thus, we compare only the + -- name, meaning that when we insert a new definition, it will replace + -- the previous one. + + package Macro_Sets is new Ada.Containers.Ordered_Sets (Macro_Definition); + subtype Macro_Set is Macro_Sets.Set; + + type Analysis_Options is record + PP_Search_Path : String_Vectors.Vector; + -- List of directories to search when looking for an included file + + Builtin_Macros : Macro_Set; + -- Set of predefined macros for the project compiler driver + + PP_Macros : Macro_Set; + -- Set of macros for the preprocessor + + Std : Unbounded_String; + -- -std=X argument to pass to the preprocessor and the parser, or the + -- empty string. + end record; + -- Options to analyze (preprocess and/or parse) a compilation unit + + procedure Add_Options + (Args : in out String_Vectors.Vector; + Options : Analysis_Options; + Pass_Builtins : Boolean := True; + Preprocessed : Boolean := False); + -- Append to Args the command line options corresponding to Options. If + -- Pass_Builtins is True, pass builtin macros in Options to Args. If + -- Preprocessed is True, consider that we will use these options on a + -- file that was already preprocessed. + + procedure Import_From_Project + (Self : out Analysis_Options; + Language : C_Family_Language; + Info : Project_Info; + Filename : String); + -- Initialize Self from compiler switches corresponding to the Filename + -- source file in the Info project. + + procedure Import_From_Args + (Self : in out Analysis_Options; Args : String_Vectors.Vector); + -- Extract analysis options from the Args command line arguments and update + -- Self accordingly. + function Split_Args (Args : Unbounded_String) return String_Vectors.Vector; -- Split a comma-separated list of arguments procedure Import_Options - (Self : out Analysis_Options; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc; - Filename : String); + (Self : out Analysis_Options; + Language : C_Family_Language; + Info : Project_Info; + Filename : String); -- Shortcut to call Import_From_Project, and Import_From_Args on the -- --c-opts/--c++-opts option. @@ -253,7 +316,7 @@ package Instrument.C is null; when True => SFI : Valid_Source_File_Index; - CU_Name : Compilation_Unit_Part; + CU_Name : Compilation_Unit_Name; end case; end record; -- Descriptor for a source file: Of_Interest determines if we should @@ -298,8 +361,7 @@ package Instrument.C is LL_PP_Info_Map : LL_SCO_PP_Info_Maps.Map; -- Preprocessing information for low level SCOs - Files_Of_Interest : String_Sets.Set; - Sources_Of_Interest_Info : Source_Of_Interest_Maps.Map; + Sources_Of_Interest : Source_Of_Interest_Maps.Map; -- Records for each source file processed during the instrumentation -- whether it is a source of interest, and some properties if it is. diff --git a/tools/gnatcov/instrument-c__stub.adb b/tools/gnatcov/instrument-c__stub.adb index 1b0c5d7f1..98400eb4d 100644 --- a/tools/gnatcov/instrument-c__stub.adb +++ b/tools/gnatcov/instrument-c__stub.adb @@ -16,8 +16,4 @@ -- of the license. -- ------------------------------------------------------------------------------ -package body Instrument.C is -begin - Builtin_Support (C_Language) := False; - Builtin_Support (CPP_Language) := False; -end Instrument.C; +pragma No_Body; diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index 287fd99b9..3d30db5f9 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -23,8 +23,6 @@ with Instrument.Common; use Instrument.Common; package Instrument.C is - pragma Elaborate_Body; - type C_Family_Instrumenter_Type is abstract new Language_Instrumenter with null record; -- Common instrumentation primitives for C/C++ @@ -37,10 +35,6 @@ package Instrument.C is (Self : C_Instrumenter_Type) return Src_Supported_Language is (C_Language); - function Create_C_Instrumenter - (Tag : Unbounded_String) return C_Instrumenter_Type - is (C_Instrumenter_Type'(others => <>)); - type CPP_Instrumenter_Type is new C_Family_Instrumenter_Type with null record; -- Instrumentation primitives for C++ @@ -49,9 +43,8 @@ package Instrument.C is (Self : CPP_Instrumenter_Type) return Src_Supported_Language is (CPP_Language); - function Create_CPP_Instrumenter - (Tag : Unbounded_String) return CPP_Instrumenter_Type - is (CPP_Instrumenter_Type'(others => <>)); + C_Instrumenter : aliased C_Instrumenter_Type := (null record); + CPP_Instrumenter : aliased CPP_Instrumenter_Type := (null record); procedure Postprocess_Source (Preprocessed_Filename : String; diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 58155939e..6b3fda8ea 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -16,14 +16,15 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Containers; use Ada.Containers; +with Ada.Containers; use Ada.Containers; with Ada.Containers.Vectors; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Clang.Index; use Clang.Index; with Clang.Rewrite; use Clang.Rewrite; -with Instrument.Common; use Instrument.Common; -with Slocs; use Slocs; +with Instrument.C; use Instrument.C; +with Slocs; use Slocs; package Instrument.C_Utils is diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index 62c3e77ba..abdc8c7e2 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -59,7 +59,7 @@ package body Instrument.Checkpoints is for Cur in CP_IU_Map.Iterate loop declare - CP_Unit_Name : constant Compilation_Unit_Part := Key (Cur); + CP_Unit_Name : constant Compilation_Unit_Name := Key (Cur); Existing_Cur : constant Cursor := Instrumented_Unit_CUs.Find (CP_Unit_Name); CU_Ignored : constant Boolean := @@ -128,7 +128,7 @@ package body Instrument.Checkpoints is /= PP_Cmds.Reference (Cur) then Warn ("inconsistent information for instrumented file " - & Get_Full_Name (SFI)); + & Get_Unique_Name (SFI)); end if; end; end if; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index f31c7ed72..e12d83a29 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -18,19 +18,23 @@ with Ada.Containers; use Ada.Containers; with Ada.Directories; +with Ada.Unchecked_Deallocation; -with GNATCOLL.VFS; +with GNAT.OS_Lib; + +with Interfaces; with Coverage; with Diagnostics; -with Outputs; use Outputs; +with Hex_Images; with Paths; use Paths; +with Project; use Project; with SCOs; package body Instrument.Common is function Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Part; + (Instrumented_Unit : Compilation_Unit_Name; Buffer_Name : String) return String; -- Helper for Statement_Buffer_Symbol and Decision_Buffer_Symbol. Return -- the name of the symbol for the entity that contains the address of a @@ -45,7 +49,7 @@ package body Instrument.Common is ------------------- function Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Part; + (Instrumented_Unit : Compilation_Unit_Name; Buffer_Name : String) return String is Slug : constant String := Instrumented_Unit_Slug (Instrumented_Unit); @@ -58,7 +62,7 @@ package body Instrument.Common is ----------------------------- function Statement_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Part) return String is + (Instrumented_Unit : Compilation_Unit_Name) return String is begin return Buffer_Symbol (Instrumented_Unit, "stmt"); end Statement_Buffer_Symbol; @@ -68,7 +72,7 @@ package body Instrument.Common is ---------------------------- function Decision_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Part) return String is + (Instrumented_Unit : Compilation_Unit_Name) return String is begin return Buffer_Symbol (Instrumented_Unit, "dc"); end Decision_Buffer_Symbol; @@ -78,23 +82,35 @@ package body Instrument.Common is ------------------------ function MCDC_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Part) return String is + (Instrumented_Unit : Compilation_Unit_Name) return String is begin return Buffer_Symbol (Instrumented_Unit, "mcdc"); end MCDC_Buffer_Symbol; + ----------------- + -- Buffer_Unit -- + ----------------- + + function Buffer_Unit + (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name + is + Simple_Name : Ada_Identifier; + begin + Append (Simple_Name, 'B'); + Append (Simple_Name, Instrumented_Unit_Slug (Instrumented_Unit)); + return CU_Name : Ada_Qualified_Name := Sys_Buffers do + CU_Name.Append (Simple_Name); + end return; + end Buffer_Unit; + ----------------------- -- Unit_Buffers_Name -- ----------------------- - function Unit_Buffers_Name (Unit : Compilation_Unit) return String is - Slug : constant String := - (case Unit.Language is - when Unit_Based_Language => - Qualified_Name_Slug (To_Qualified_Name (+Unit.Unit_Name)), - when File_Based_Language => Filename_Slug (+Unit.Unit_Name)); + function Unit_Buffers_Name (Unit : Compilation_Unit_Name) return String is begin - return To_Symbol_Name (Sys_Buffers) & "_" & Slug & "_buffers"; + return To_Symbol_Name (Sys_Buffers) & "_" & Instrumented_Unit_Slug (Unit) + & "_buffers"; end Unit_Buffers_Name; ------------------------ @@ -141,6 +157,255 @@ package body Instrument.Common is return To_String (Result); end Format_Fingerprint; + ------------------------ + -- Trace_Filename_Tag -- + ------------------------ + + function Trace_Filename_Tag return String + is + -- Compute the tag for default source trace filenames. Use the current + -- time as a mostly unique identifier. Put it in hexadecimal form + -- without leading zeros to avoid too long names. + + use Interfaces; + Time : constant Unsigned_64 := + Unsigned_64 (GNAT.OS_Lib.To_C (GNAT.OS_Lib.Current_Time)); + Tag : constant String := + Hex_Images.Strip_Zero_Padding + (Hex_Images.Hex_Image (Time)); + begin + return Tag; + end Trace_Filename_Tag; + + -------------------- + -- Create_Context -- + -------------------- + + function Create_Context + (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context is + begin + return IC : Inst_Context do + IC.Project_Name := +Ada.Directories.Base_Name + (Project.Root_Project_Filename); + -- TODO??? Get the original casing for the project name + + IC.Ignored_Source_Files_Present := Ignored_Source_Files /= null; + if Ignored_Source_Files /= null then + IC.Ignored_Source_Files := Ignored_Source_Files.all; + end if; + end return; + end Create_Context; + + --------------------- + -- Destroy_Context -- + --------------------- + + procedure Destroy_Context (Context : in out Inst_Context) is + procedure Free is new Ada.Unchecked_Deallocation + (Instrumented_Unit_Info, Instrumented_Unit_Info_Access); + procedure Free is new Ada.Unchecked_Deallocation + (Project_Info, Project_Info_Access); + begin + -- Deallocate all Insrtrumented_Unit_Info in Context, and then clear the + -- hashed map, both to avoid dangling pointers and to make + -- Destroy_Context callable more than once, like conventional + -- deallocation procedures in Ada. + + for Cur in Context.Instrumented_Units.Iterate loop + declare + IU : Instrumented_Unit_Info_Access := + Instrumented_Unit_Maps.Element (Cur); + begin + Free (IU); + end; + end loop; + Context.Instrumented_Units := Instrumented_Unit_Maps.Empty_Map; + + -- Likewise for Project_Info records + + for Cur in Context.Project_Info_Map.Iterate loop + declare + PI : Project_Info_Access := Project_Info_Maps.Element (Cur); + begin + Free (PI); + end; + end loop; + Context.Project_Info_Map := Project_Info_Maps.Empty_Map; + end Destroy_Context; + + ---------------------------- + -- Is_Ignored_Source_File -- + ---------------------------- + + function Is_Ignored_Source_File + (Context : Inst_Context; Filename : String) return Boolean is + begin + return + Context.Ignored_Source_Files_Present + and then GNAT.Regexp.Match + (S => Fold_Filename_Casing (Filename), + R => Context.Ignored_Source_Files); + end Is_Ignored_Source_File; + + -------------------------------- + -- Get_Or_Create_Project_Info -- + -------------------------------- + + function Get_Or_Create_Project_Info + (Context : in out Inst_Context; + Project : Project_Type) return Project_Info_Access + is + use Project_Info_Maps; + + -- Look for an existing Project_Info record corresponding to Project + + Project_Name : constant Unbounded_String := +Project.Name; + Position : constant Cursor := Context.Project_Info_Map.Find + (Project_Name); + begin + if Has_Element (Position) then + return Element (Position); + + else + -- The requested Project_Info record does not exist yet. Create it, + -- register it and return it. + + declare + Storage_Project : constant Project_Type := + Project.Extending_Project (Recurse => True); + -- Actual project that will host instrumented sources: even when + -- we instrument an extended project, the resulting instrumented + -- sources must go to the ultimate extending project's object + -- directory. This is similar to the object directory that hosts + -- object files when GPRbuild processes a project that is + -- extended. + + Result : constant Project_Info_Access := new Project_Info' + (Project => Project, + Externally_Built => Project.Externally_Built, + Output_Dir => +Project_Output_Dir (Storage_Project)); + begin + Context.Project_Info_Map.Insert (Project_Name, Result); + return Result; + end; + end if; + end Get_Or_Create_Project_Info; + + --------------- + -- Unit_Info -- + --------------- + + function Unit_Info + (CU_Name : Compilation_Unit_Name; + Info : out GNATCOLL.Projects.File_Info) return Boolean + is + Prj : Project_Type renames Project.Project.Root_Project; + File : constant GNATCOLL.VFS.Filesystem_String := Prj.File_From_Unit + (Unit_Name => To_Ada (CU_Name.Unit), + Part => CU_Name.Part, + Language => "Ada"); + begin + if File'Length = 0 then + return False; + end if; + + Info := Prj.Create_From_Project (File); + return True; + end Unit_Info; + + --------------------------------- + -- Register_Main_To_Instrument -- + --------------------------------- + + procedure Register_Main_To_Instrument + (Context : in out Inst_Context; + Mains : in out Main_To_Instrument_Vectors.Vector; + File : GNATCOLL.VFS.Virtual_File; + Project : Project_Type) + is + File_Info : constant GNATCOLL.Projects.File_Info := + Standard.Project.Project.Info (File); + CU_Name : constant Compilation_Unit_Name := + To_Compilation_Unit_Name (File_Info); + Prj_Info : constant Project_Info_Access := + Get_Or_Create_Project_Info (Context, Project); + begin + Mains.Append + (Main_To_Instrument' + (CU_Name => CU_Name, + File => File, + Prj_Info => Prj_Info)); + end Register_Main_To_Instrument; + + --------------------------- + -- Add_Instrumented_Unit -- + --------------------------- + + procedure Add_Instrumented_Unit + (Context : in out Inst_Context; + Project : GNATCOLL.Projects.Project_Type; + Source_File : GNATCOLL.Projects.File_Info) + is + use GNATCOLL.VFS; + + SF_Basename : constant Filesystem_String := Source_File.File.Base_Name; + begin + pragma Assert (not (Is_Ignored_Source_File (Context, +SF_Basename))); + + declare + CU_Name : constant Compilation_Unit_Name := + To_Compilation_Unit_Name (Source_File); + begin + -- If we already planned to instrument this unit, do nothing more + + if Context.Instrumented_Units.Contains (CU_Name) then + return; + end if; + + -- Otherwise, add it to the list of instrumented units + + declare + Unit_Info : constant Instrumented_Unit_Info_Access := + new Instrumented_Unit_Info' + (Filename => To_Unbounded_String + (+Source_File.File.Full_Name), + Prj_Info => Get_Or_Create_Project_Info (Context, Project), + Language => To_Language (Source_File.Language)); + begin + Context.Instrumented_Units.Insert (CU_Name, Unit_Info); + end; + end; + end Add_Instrumented_Unit; + + -------------- + -- New_File -- + -------------- + + function New_File + (Info : Project_Info; Name : String) return String + is + Base_Filename : constant String := + Ada.Directories.Simple_Name (Name); + Output_Filename : constant String := + To_String (Info.Output_Dir) / Base_Filename; + begin + return Output_Filename; + end New_File; + + ----------------- + -- Create_File -- + ----------------- + + procedure Create_File + (Info : in out Project_Info; + File : in out Text_Files.File_Type; + Name : String) + is + Filename : constant String := New_File (Info, Name); + begin + File.Create (Filename); + end Create_File; + -------------- -- Next_Bit -- -------------- @@ -317,299 +582,46 @@ package body Instrument.Common is end loop; end Remap_Scope_Entity; - -------------- - -- New_File -- - -------------- - - function New_File - (Prj : Prj_Desc; Name : String) return String - is - Base_Filename : constant String := - Ada.Directories.Simple_Name (Name); - Output_Filename : constant String := - To_String (Prj.Output_Dir) / Base_Filename; - begin - return Output_Filename; - end New_File; - - ----------------- - -- Create_File -- - ----------------- + ------------------------------ + -- Buffer_Units_For_Closure -- + ------------------------------ - procedure Create_File - (Prj : Prj_Desc; - File : in out Text_Files.File_Type; - Name : String) + function Instr_Units_For_Closure + (IC : Inst_Context; + Main : Compilation_Unit_Name) + return CU_Name_Vectors.Vector is - Filename : constant String := New_File (Prj, Name); + pragma Unreferenced (Main); + Result : CU_Name_Vectors.Vector; begin - File.Create (Filename); - end Create_File; - - ----------------- - -- To_Filename -- - ----------------- - - function To_Filename - (Prj : Prj_Desc; - Lang : Src_Supported_Language; - CU_Name : Compilation_Unit_Part) return String - is - Filename : Unbounded_String; - begin - case CU_Name.Language_Kind is - when Unit_Based_Language => - for Id of CU_Name.Unit loop - if Length (Filename) > 0 then - Append (Filename, Prj.Dot_Replacement); - end if; - Append (Filename, To_Lower (To_String (Id))); - end loop; - - case CU_Name.Part is - when Unit_Body | Unit_Separate => - Append (Filename, Prj.Body_Suffix (Lang)); - when Unit_Spec => - Append (Filename, Prj.Spec_Suffix (Lang)); - end case; - when File_Based_Language => - Filename := CU_Name.Filename; - end case; - return +Filename; - end To_Filename; - - ----------------- - -- Add_Options -- - ----------------- - - procedure Add_Options - (Args : in out String_Vectors.Vector; - Options : Analysis_Options; - Pass_Builtins : Boolean := True; - Preprocessed : Boolean := False) is - - procedure Add_Macro_Switches (Macros : Macro_Set); - -- Add the given macro switches to Args - - ------------------------ - -- Add_Macro_Switches -- - ------------------------ - - procedure Add_Macro_Switches (Macros : Macro_Set) is - begin - for M of Macros loop - if M.Define then - Args.Append ("-D" & M.Name & M.Args & "=" & M.Value); - else - Args.Append ("-U" & M.Name); - end if; - end loop; - end Add_Macro_Switches; - - begin - for Dir of Options.PP_Search_Path loop - Args.Append (+"-I"); - Args.Append (Dir); - end loop; - - -- If the file was already pre-processed, do not pass macro command - -- line switches. Since preprocessed code can contain names of defined - -- macros, passing macro arguments for the parsing step could trigger - -- other expansions, and thus feed the parser with unexpected code. - - if not Preprocessed then - - -- Add builtin macros before macros from command line switches, as - -- the latter should have precedence over builtins and thus must - -- come last in Args. - - if Pass_Builtins then - Add_Macro_Switches (Options.Builtin_Macros); - end if; - Add_Macro_Switches (Options.PP_Macros); - end if; - - -- The -std switch also indicates the C/C++ version used, and - -- influences both the configuration of the preprocessor, and the - -- parsing of the file. - - if Length (Options.Std) /= 0 then - Args.Append (Options.Std); - end if; - - end Add_Options; - - ---------------------------- - -- Parse_Macro_Definition -- - ---------------------------- - - procedure Parse_Macro_Definition - (Str : String; - Parsed_Def : out Macro_Definition; - Success : out Boolean) - is - Matches : Match_Array (0 .. 3); - begin - Match (Macro_Def_Regexp, Str, Matches); - if Matches (0) = No_Match then - Success := False; - else - Success := True; - Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); - if Matches (2) /= No_Match then - Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); - end if; - Parsed_Def.Value := +Str (Matches (3).First .. Matches (3).Last); - end if; - end Parse_Macro_Definition; - - ------------------------------------ - -- Parse_Cmdline_Macro_Definition -- - ------------------------------------ - - procedure Parse_Cmdline_Macro_Definition - (Str : String; - Parsed_Def : out Macro_Definition; - Success : out Boolean) - is - Matches : Match_Array (0 .. 4); - begin - Match (Macro_Cmdline_Regexp, Str, Matches); - if Matches (0) = No_Match then - Success := False; - else - Success := True; - Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); - if Matches (2) /= No_Match then - Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); - end if; - - -- Command line macros can have part of their value before the - -- assignment, e.g. "-DA(b)b" is equivalent to "#define A(b) b 1". - - if Matches (3) /= No_Match then - Append - (Parsed_Def.Value, - Str (Matches (3).First .. Matches (3).Last) & " "); - end if; - - -- If no value is given, then it is implicitly 1 - - if Matches (4) /= No_Match then - Append - (Parsed_Def.Value, Str (Matches (4).First .. Matches (4).Last)); - else - Append (Parsed_Def.Value, " 1"); - end if; - end if; - end Parse_Cmdline_Macro_Definition; - - ---------------------- - -- Import_From_Args -- - ---------------------- - - procedure Import_From_Args - (Self : in out Analysis_Options; Args : String_Vectors.Vector) - is - I : Natural := Args.First_Index; - Last : constant Integer := Args.Last_Index; - - function Read_With_Argument - (Arg : String; - Option_Name : Character; - Value : out Unbounded_String) return Boolean; - -- Assuming that Arg starts with "-X" where X is Option_Name, try to - -- fetch the value for this option. If we managed to get one, return - -- True and set Value to it. Return False otherwise. - - ------------------------ - -- Read_With_Argument -- - ------------------------ - - function Read_With_Argument - (Arg : String; - Option_Name : Character; - Value : out Unbounded_String) return Boolean - is - Prefix : constant String := "-" & Option_Name; - begin - if Arg = Prefix then - - -- Option and value are two separate arguments (-O VALUE) - - I := I + 1; - if I <= Last then - Value := Args (I); - return True; - end if; - - elsif Has_Prefix (Arg, Prefix) then - - -- Option and value are combined in a single argument (-OVALUE) - - Value := +Arg (Arg'First + Prefix'Length .. Arg'Last); - return True; - end if; - - return False; - end Read_With_Argument; - - -- Start of processing for Import_From_Args - - begin - while I <= Last loop + -- TODO??? Here, we need the list of files needed to build Main: specs + -- for units WITHed by main, their bodies, the separates, etc. It's + -- unclear what GNATCOLL.Projects.Get_Closure does, but experimentations + -- show that it's not what we want. So for now, return an approximation: + -- buffer units for all instrumented units. In the future, we should + -- either get this service from GNATCOLL.Projects, either re-implement + -- it on top of Libadalang. + + for Cur in IC.Instrumented_Units.Iterate loop declare - A : constant String := +Args (I); - Value : Unbounded_String; + Instr_Unit : constant Compilation_Unit_Name := + Instrumented_Unit_Maps.Key (Cur); begin - - -- Process arguments we manage to handle, silently discard unknown - -- ones. - -- - -- TODO??? In order to avoid surprising situations for users (for - -- instance typos in command line arguments), maybe we should emit - -- a warning for unknown arguments. However, given that this - -- procedure is called at least once per instrumented source file, - -- we would need to avoid emitting duplicate warnings. - - if Read_With_Argument (A, 'I', Value) then - Self.PP_Search_Path.Append (Value); - - elsif Read_With_Argument (A, 'D', Value) then - declare - Macro_Def : Macro_Definition (Define => True); - Success : Boolean; - begin - Parse_Cmdline_Macro_Definition - (Str => +Value, - Parsed_Def => Macro_Def, - Success => Success); - if Success then - Self.PP_Macros.Include (Macro_Def); - else - Warn ("Failed to parse command-line macro definition: " - & (+Value)); - end if; - end; - - elsif Read_With_Argument (A, 'U', Value) then - Self.PP_Macros.Include ((Define => False, Name => Value)); - - elsif Has_Prefix (A, "-std=") then - Self.Std := +A; - end if; - - I := I + 1; + Result.Append (Instr_Unit); end; end loop; - end Import_From_Args; + return Result; + end Instr_Units_For_Closure; begin - Sys_Prefix.Append (To_Unbounded_String ("GCVRT")); + Sys_Prefix.Append (To_Unbounded_String ("GNATcov_RTS")); - Sys_Buffers.Append (To_Unbounded_String ("GNATcov_RTS")); + Sys_Buffers := Sys_Prefix; Sys_Buffers.Append (To_Unbounded_String ("Buffers")); + Sys_Buffers_Lists := Sys_Buffers; + Sys_Buffers_Lists.Append (To_Unbounded_String ("Lists")); + Statement_Buffer_Name.Append (To_Unbounded_String ("Statement_Buffer")); Decision_Buffer_Name.Append (To_Unbounded_String ("Decision_Buffer")); MCDC_Buffer_Name.Append (To_Unbounded_String ("MCDC_Buffer")); diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index dc050968d..7293a2f1d 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -50,21 +50,21 @@ -- buffers for the unit. with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Containers.Hashed_Maps; with Ada.Containers.Hashed_Sets; with Ada.Containers.Ordered_Maps; -with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Hash; +with Ada.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; -with GNAT.Regpat; use GNAT.Regpat; +with GNATCOLL.VFS; -with GNATCOLL.JSON; use GNATCOLL.JSON; - -with ALI_Files; use ALI_Files; -with Files_Table; use Files_Table; +with ALI_Files; use ALI_Files; +with Files_Table; use Files_Table; with GNATcov_RTS; -with Namet; use Namet; -with Slocs; use Slocs; +with Namet; use Namet; +with Slocs; use Slocs; with Text_Files; package Instrument.Common is @@ -76,7 +76,11 @@ package Instrument.Common is -- sources. Sys_Buffers : Ada_Qualified_Name; - -- Runtime package containing coverage buffer type definitions + -- Scope in Sys_Prefix for all packages to contain coverage buffers + + Sys_Buffers_Lists : Ada_Qualified_Name; + -- Scope in Sys_Prefix for all packages to contain generic procedures for + -- iterations on coverage buffers. Statement_Buffer_Name : Ada_Qualified_Name; -- Qualified name (relative to the unit buffer package) of the buffer to @@ -106,30 +110,36 @@ package Instrument.Common is -- handler. function Dump_Procedure_Symbol - (Main : Compilation_Unit_Part) return String + (Main : Compilation_Unit_Name) return String is ("gnatcov_rts_" & Instrumented_Unit_Slug (Main) & "_" & To_Lower (To_String (Dump_Procedure_Name))); -- Return the name of the exported symbol for the Dump_Buffers function function Statement_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Part) return String; + (Instrumented_Unit : Compilation_Unit_Name) return String; -- Given a unit to instrument, return the name of the symbol to use for the -- entity that contains address of the statement coverage buffer. function Decision_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Part) return String; + (Instrumented_Unit : Compilation_Unit_Name) return String; -- Given a unit to instrument, return the name of the symbol to use for the -- entity that contains address of the decision coverage buffer. function MCDC_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Part) return String; + (Instrumented_Unit : Compilation_Unit_Name) return String; -- Given a unit to instrument, return the name of the symbol to use for the -- entity that contains address of the decision coverage buffer. - function Unit_Buffers_Name (Unit : Compilation_Unit) return String; + function Buffer_Unit + (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name; + -- Given a unit to instrument, return the name of the unit that holds + -- its coverage buffers (Coverage_Buffer_Type and + -- GNATcov_RTS_Coverage_Buffers records). + + function Unit_Buffers_Name (Unit : Compilation_Unit_Name) return String; -- Name of the symbol that references the - -- gnatcov_rts_coverage_buffers_group struct for this file. + -- gnatcov_rts_coverage_buffers_group struct for this unit. function Unit_Buffers_Array_Name (Prj_Name : String) return String is ("gnatcov_rts_buffers_array_" & Prj_Name); @@ -156,16 +166,64 @@ package Instrument.Common is -- returned literal expression (aggregate in Ada, compound expression in -- C/C++). + function Trace_Filename_Tag return String; + -- Tag for the source trace filename. This allows differentiating trace + -- files produced by a specific program instrumentation from the ones + -- produced by other instrumentations. + package File_Sets is new Ada.Containers.Hashed_Sets (Element_Type => Ada.Strings.Unbounded.Unbounded_String, "=" => Ada.Strings.Unbounded."=", Equivalent_Elements => Ada.Strings.Unbounded."=", Hash => Ada.Strings.Unbounded.Hash); + type Project_Info is record + Project : Project_Type; + -- Project that this record describes + + Externally_Built : Boolean; + -- Whether this project is externally built. In that case, we assume its + -- units of interest have already been instrumented. + + Output_Dir : Ada.Strings.Unbounded.Unbounded_String; + -- Subdirectory in the project file's object directory. All we generate + -- for this project must land in it. + end record; + + type Project_Info_Access is access all Project_Info; + + package Project_Info_Maps is new Ada.Containers.Hashed_Maps + (Key_Type => Ada.Strings.Unbounded.Unbounded_String, + Element_Type => Project_Info_Access, + Equivalent_Keys => Ada.Strings.Unbounded."=", + Hash => Ada.Strings.Unbounded.Hash); + -- Mapping from project name (as returned by GNATCOLL.Projects.Name) to + -- Project_Info records. Project_Info records are owned by this map, and + -- thus must be deallocated when maps are deallocated. + + type Main_To_Instrument is record + CU_Name : Compilation_Unit_Name; + -- Compilation unit of the main to instrument + + File : GNATCOLL.VFS.Virtual_File; + -- Source file to instrument + + Prj_Info : Project_Info_Access; + -- Reference to the Project_Info record corresponding to the project + -- that owns the main to instrument. + end record; + + package Main_To_Instrument_Vectors is new Ada.Containers.Vectors + (Positive, Main_To_Instrument); + type Instrumented_Unit_Info is record Filename : Ada.Strings.Unbounded.Unbounded_String; -- Name of the source file for this unit + Prj_Info : Project_Info_Access; + -- Reference to the Project_Info record corresponding to the project + -- that owns the source file for this unit. + Language : Some_Language; -- Language for this unit end record; @@ -173,9 +231,81 @@ package Instrument.Common is type Instrumented_Unit_Info_Access is access all Instrumented_Unit_Info; package Instrumented_Unit_Maps is new Ada.Containers.Ordered_Maps - (Key_Type => Compilation_Unit_Part, + (Key_Type => Compilation_Unit_Name, Element_Type => Instrumented_Unit_Info_Access); + type Inst_Context is limited record + Project_Name : Ada.Strings.Unbounded.Unbounded_String; + -- Name of the root project. It is also used to name the list of buffers + + Ignored_Source_Files_Present : Boolean; + Ignored_Source_Files : GNAT.Regexp.Regexp; + -- If present, instrumentation will ignore files whose names match the + -- accessed pattern. + + Instrumented_Units : Instrumented_Unit_Maps.Map; + -- Mapping from instrumented unit names to information used during + -- instrumentation. + + Project_Info_Map : Project_Info_Maps.Map; + -- For each project that contains units of interest, this tracks a + -- Project_Info record. + end record; + + function Create_Context + (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context; + -- Create an instrumentation context for the currently loaded project + + procedure Destroy_Context (Context : in out Inst_Context); + -- Free dynamically allocated resources in Context + + function Is_Ignored_Source_File + (Context : Inst_Context; Filename : String) return Boolean; + -- Return whether the instrumentation process must ignore the Filename + -- source file. + + function Get_Or_Create_Project_Info + (Context : in out Inst_Context; + Project : Project_Type) return Project_Info_Access; + -- Return the Project_Info record corresponding to Project. Create it if it + -- does not exist. + + function Unit_Info + (CU_Name : Compilation_Unit_Name; + Info : out GNATCOLL.Projects.File_Info) return Boolean; + -- Look for a compilation unit in the loaded project. If found, put its + -- file info in Info and return True. Return False otherwise. + + procedure Register_Main_To_Instrument + (Context : in out Inst_Context; + Mains : in out Main_To_Instrument_Vectors.Vector; + File : GNATCOLL.VFS.Virtual_File; + Project : Project_Type); + -- Register in Mains a main to be instrumented so that it dumps coverage + -- buffers. File is the source file for this main, and Project is the + -- project that owns this main. If File is actually a unit of interest in + -- Context, do nothing. + + procedure Add_Instrumented_Unit + (Context : in out Inst_Context; + Project : GNATCOLL.Projects.Project_Type; + Source_File : GNATCOLL.Projects.File_Info); + -- Add the given source file to the list of units to instrument + + function New_File + (Info : Project_Info; Name : String) return String; + -- Compute the path to the file to create in Info.Output_Dir + + procedure Create_File + (Info : in out Project_Info; + File : in out Text_Files.File_Type; + Name : String); + -- Shortcut to Text_Files.Create: create a text file with the given name in + -- Info.Output_Dir. + -- + -- Name can be a basename, a relative name or an absolute one: in all + -- cases, the basename is taken and the file is created in Info.Output_Dir. + ------------------------------------------------------ -- Common declarations for Ada / C instrumentation -- ------------------------------------------------------ @@ -265,12 +395,9 @@ package Instrument.Common is package Allocated_Bits_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Allocated_Bits); -- Allocated bits in coverage buffers for low-level SCOs (one per source - -- file). A single compilation unit may yield multiple sets of coverage - -- buffers: one for each part of the unit in the case of unit-based - -- language units (the spec, the body, and the separates). It may also be - -- the case for unit of file-based languages: one for the compiled source - -- file and one for each included source (e.g. through inclusion directives - -- for C and C++). + -- file). Because of #include directives in C/C++, a single compilation + -- unit may yield multiple sets of coverage buffers: one for the compiled + -- source file, one for each included source. function Create_Unit_Bits (Allocated_Bits : in out Allocated_Bits_Vectors.Vector; @@ -306,16 +433,16 @@ package Instrument.Common is (Index_Type => Positive, Element_Type => Annotation_Couple); type Unit_Inst_Context is tagged record - Instrumented_Unit : Compilation_Unit_Part; + Instrumented_Unit : Compilation_Unit_Name; -- Name of the compilation unit being instrumented + Language_Version_Pragma : Unbounded_Wide_Wide_String; + -- Language version configuration pragma for unit, if any + SFI : Source_File_Index := No_Source_File; -- Source file index of the compilation unit being instrumented - Fullname : Unbounded_String; - -- Fullname of the compilation unit being instrumented - - Buffer_Unit : Compilation_Unit_Part; + Buffer_Unit : Compilation_Unit_Name; -- Name of the compilation unit that holds coverage buffers for the -- unit currently being instrumented (see Common.Buffer_Unit). @@ -365,18 +492,19 @@ package Instrument.Common is package CU_Name_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, - Element_Type => Compilation_Unit_Part); + Element_Type => Compilation_Unit_Name); package Ada_Qualified_Name_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Ada_Qualified_Name, "=" => Ada_Identifier_Vectors."="); - type Language_Instrumenter is abstract tagged record - Tag : Unbounded_String; - -- Tag specific to an instrumentation run + function Instr_Units_For_Closure + (IC : Inst_Context; + Main : Compilation_Unit_Name) return CU_Name_Vectors.Vector; + -- Return the list of instrumented units in Main's closure - end record; + type Language_Instrumenter is abstract tagged null record; -- Set of operations to allow the instrumentation of sources files for a -- given language. @@ -384,166 +512,44 @@ package Instrument.Common is (Self : Language_Instrumenter) return Src_Supported_Language is abstract; -- Return the language that this instrumenter is designed to process + function Skip_Source_File + (Self : Language_Instrumenter; + Source_File : GNATCOLL.Projects.File_Info) return Boolean + is (True); + -- Whether the instrumenter skips the given source file. The default + -- (undefined) instrumenter skips every source file. + procedure Instrument_Unit - (Self : in out Language_Instrumenter; - Unit_Name : String; - Prj : Prj_Desc; - Files_Of_Interest : String_Sets.Set) is null; + (Self : in out Language_Instrumenter; + CU_Name : Compilation_Unit_Name; + Unit_Info : in out Instrumented_Unit_Info) is null; -- Instrument a single source file for the language that Self supports. -- - -- Unit_Name identifies this compilation unit (either through a unit name, - -- for Unit_Based_Language, or through a full name, for file-based). Prj - -- describes information coming from the project, and relevant to the - -- instrumentation of the unit. Files_Of_Interest provides the list of - -- files of interest, to ignore e.g. part of the unit (e.g. a separate) - -- when instrumenting it. + -- CU_Name must be the name of the compilation unit for this source file, + -- and Unit_Info must be the Instrumented_Unit_Info record corresponding to + -- this source file. procedure Auto_Dump_Buffers_In_Main - (Self : in out Language_Instrumenter; - Filename : String; - Dump_Config : Any_Dump_Config; - Prj : Prj_Desc) is null; + (Self : in out Language_Instrumenter; + Filename : String; + Instr_Units : CU_Name_Vectors.Vector; + Dump_Config : Any_Dump_Config; + Info : in out Project_Info) is null; -- Try to instrument the Filename source file (whose language is assumed - -- to be Self's) to insert a call to dump the list of coverage buffers, - -- assumed to be named after Prj.Prj_Name. Do nothing if not successful. + -- to be Self's) to insert a call to dump the list of coverage buffers for + -- all Instr_Units, according to the Dump_Config options. Do nothing if not + -- successful. + -- + -- Info must be the Project_Info record corresponding to the project that + -- owns Filename's compilation unit. procedure Emit_Buffers_List_Unit - (Self : Language_Instrumenter; - Instr_Units : Unit_Sets.Set; - Prj : Prj_Desc) is null; - -- Emit in the root project a unit (in Self's language) to contain the list - -- of coverage buffers for the given instrumented files. - -- + (Self : Language_Instrumenter; + Root_Project_Info : in out Project_Info; + Instr_Units : CU_Name_Vectors.Vector) is null; -- The variable holding the list of coverage buffers is exported to a -- unique C symbol whose name is defined by the Unit_Buffers_Array_Name -- function. This procedure should thus be called only once, for one of -- the supported languages of the project. - function New_File - (Prj : Prj_Desc; Name : String) return String; - -- Compute the path to the file to create in Self.Output_Dir - - procedure Create_File - (Prj : Prj_Desc; - File : in out Text_Files.File_Type; - Name : String); - -- Shortcut to Text_Files.Create: create a text file with the given name in - -- Prj.Output_Dir. - -- - -- Name can be a basename, a relative name or an absolute one: in all - -- cases, the basename is taken and the file is created in Prj.Output_Dir. - - function To_Filename - (Prj : Prj_Desc; - Lang : Src_Supported_Language; - CU_Name : Compilation_Unit_Part) return String; - -- Convert a Compilation_Unit_Name to a file basename, using the body / - -- spec suffix and dot replacement (for unit based languages) defined in - -- Prj. - - type Macro_Definition (Define : Boolean := True) is record - Name : Unbounded_String; - -- Name of the macro - - case Define is - when True => - Args : Unbounded_String; - -- String representation of the macro arguments, e.g. (x, y) - - Value : Unbounded_String; - -- Value for the macro definition - - when False => - null; - end case; - end record; - -- Whether a macro should be defined, its name, and when it must be - -- defined, its optional arguments and value. - - function "<" (L, R : Macro_Definition) return Boolean is (L.Name < R.Name); - -- As we store Macro_Definition in sets, we do not want two conflicting - -- definitions of the same macro to coexist. Thus, we compare only the - -- name, meaning that when we insert a new definition, it will replace - -- the previous one. - - package Macro_Sets is new Ada.Containers.Ordered_Sets (Macro_Definition); - subtype Macro_Set is Macro_Sets.Set; - - type Analysis_Options is record - PP_Search_Path : String_Vectors.Vector; - -- List of directories to search when looking for an included file - - Builtin_Macros : Macro_Set; - -- Set of predefined macros for the project compiler driver - - PP_Macros : Macro_Set; - -- Set of macros for the preprocessor - - Std : Unbounded_String; - -- -std=X argument to pass to the preprocessor and the parser, or the - -- empty string. - end record; - -- Options to analyze (preprocess and/or parse) a compilation unit - - Macro_Cmdline_Regexp : constant Pattern_Matcher := Compile ( - "([a-zA-Z_]\w*)" - -- The name of the macro - - & "(\(.*\))?" - -- The optional list of macro arguments - - & "([^ =]+)?" - -- Then, there can be any character before the assignment: they will be - -- part of the macro value (e.g. A(b)b will yield #define A b 1) - - & "(?:=(.*))?" - -- The macro value itself - ); - - Macro_Def_Regexp : constant Pattern_Matcher := Compile ( - "#define" - & "(?: |\t)+" - -- "#define", then a non-empty blank - - & "([a-zA-Z_]\w*)" - -- The name of the macro - - & "(\(.*\))?" - -- The optional list of macro arguments - - & "(.*)" - -- The macro value itself - ); - -- Regular expression to analyze definitions for builtin macros (see - -- Builtin_Macros) - - procedure Parse_Macro_Definition - (Str : String; - Parsed_Def : out Macro_Definition; - Success : out Boolean); - -- Parse a macro definition. If the parsing failed, set Success to False. - -- Otherwise, set Parsed_Def to the parsed definition and set Success to - -- True. - - procedure Parse_Cmdline_Macro_Definition - (Str : String; - Parsed_Def : out Macro_Definition; - Success : out Boolean); - -- Same as above, but with a command-line macro definition - - procedure Add_Options - (Args : in out String_Vectors.Vector; - Options : Analysis_Options; - Pass_Builtins : Boolean := True; - Preprocessed : Boolean := False); - -- Append to Args the command line options corresponding to Options. If - -- Pass_Builtins is True, pass builtin macros in Options to Args. If - -- Preprocessed is True, consider that we will use these options on a - -- file that was already preprocessed. - - procedure Import_From_Args - (Self : in out Analysis_Options; Args : String_Vectors.Vector); - -- Extract analysis options from the Args command line arguments and update - -- Self accordingly. - end Instrument.Common; diff --git a/tools/gnatcov/instrument-config.adb b/tools/gnatcov/instrument-config.adb deleted file mode 100644 index 52c04a534..000000000 --- a/tools/gnatcov/instrument-config.adb +++ /dev/null @@ -1,50 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2023, 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 Command_Line; use Command_Line; -with Instrument.Ada_Unit; use Instrument.Ada_Unit; -with Instrument.C; use Instrument.C; -with Instrument.Common; use Instrument.Common; -with Strings; use Strings; - --- Return the instrumenter configuration generated from the command line - -function Instrument.Config return Language_Instrumenter'Class -is - use Command_Line.Parser; - Language : constant Some_Language := - To_Language (+Args.String_Args (Opt_Lang).Value); - Tag : constant Unbounded_String := - Value_Or_Null (Args.String_Args (Opt_Dump_Filename_Tag)); -begin - case Language is - when Ada_Language => - return Create_Ada_Instrumenter - (Tag => Tag, - Config_Pragmas_Filename => - +Args.String_Args (Opt_Gnatec).Value, - Mapping_Filename => - +Args.String_Args (Opt_Gnatem).Value, - Predefined_Source_Dirs => - Args.String_List_Args (Opt_Runtime_Dir)); - when C_Language => - return Create_C_Instrumenter (Tag => Tag); - when CPP_Language => - return Create_CPP_Instrumenter (Tag => Tag); - end case; -end Instrument.Config; diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 18da8e0a4..397c4fa76 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -136,6 +136,7 @@ package body Instrument.Input_Traces is type Trace_Entry_Elements is record Unit_Name : System.Address; + Project_Name : System.Address; Statement_Buffer : System.Address; Decision_Buffer : System.Address; MCDC_Buffer : System.Address; @@ -163,7 +164,7 @@ package body Instrument.Input_Traces is (Stream : in out Binary_Stream; File_Header : Trace_File_Header; Kind : out Supported_Info_Kind; - Data : out GNAT.OS_Lib.String_Access; + Data : out String_Access; Result : in out Read_Result) with Pre => Result.Success; -- Read a trace info entry from Stream. Return an error if something wrong @@ -394,7 +395,7 @@ package body Instrument.Input_Traces is (Stream : in out Binary_Stream; File_Header : Trace_File_Header; Kind : out Supported_Info_Kind; - Data : out GNAT.OS_Lib.String_Access; + Data : out String_Access; Result : in out Read_Result) is Ignored_EOF : Boolean; @@ -492,6 +493,7 @@ package body Instrument.Input_Traces is if File_Header.Endianity /= Native_Endianity then Swap4 (Raw_Header.Unit_Name_Length'Address); + Swap4 (Raw_Header.Project_Name_Length'Address); Swap4 (Raw_Header.Statement_Bit_Count'Address); Swap4 (Raw_Header.Decision_Bit_Count'Address); Swap4 (Raw_Header.MCDC_Bit_Count'Address); @@ -523,7 +525,7 @@ package body Instrument.Input_Traces is Create_Error (Result, "invalid bit buffer encoding"); return False; - elsif Raw_Header.Padding /= (1 .. 5 => ASCII.NUL) then + elsif Raw_Header.Padding /= (1 => ASCII.NUL) then Create_Error (Result, "invalid entry header padding"); return False; end if; @@ -538,9 +540,12 @@ package body Instrument.Input_Traces is Unit_Name_Range : constant Buffer_Range := Range_For (File_Header.Alignment, 0, Natural (Entry_Header.Unit_Name_Length)); + Project_Name_Range : constant Buffer_Range := + Range_For (File_Header.Alignment, Offset_After (Unit_Name_Range), + Natural (Entry_Header.Project_Name_Length)); Statement_Buffer_Range : constant Buffer_Range := Range_For (File_Header.Alignment, - Offset_After (Unit_Name_Range), + Offset_After (Project_Name_Range), Buffer_Size (Entry_Header.Bit_Buffer_Encoding, Entry_Header.Statement_Bit_Count)); Decision_Buffer_Range : constant Buffer_Range := @@ -573,6 +578,7 @@ package body Instrument.Input_Traces is Base_Address := Buffer_Address (Stream); Trace_Entry := (Base_Address + Unit_Name_Range.Offset, + Base_Address + Project_Name_Range.Offset, Base_Address + Statement_Buffer_Range.Offset, Base_Address + Decision_Buffer_Range.Offset, Base_Address + MCDC_Buffer_Range.Offset); @@ -655,7 +661,7 @@ package body Instrument.Input_Traces is loop declare Kind : Supported_Info_Kind; - Data : GNAT.OS_Lib.String_Access; + Data : String_Access; begin Read_Trace_Info (Stream, File_Header, Kind, Data, Result); if not Result.Success then @@ -683,6 +689,10 @@ package body Instrument.Input_Traces is (1 .. Natural (Entry_Header.Unit_Name_Length)) with Import, Address => Trace_Entry.Unit_Name; + Project_Name : constant String + (1 .. Natural (Entry_Header.Project_Name_Length)) + with Import, Address => Trace_Entry.Project_Name; + function Convert is new Ada.Unchecked_Conversion (GNATcov_RTS.Buffers.Fingerprint_Type, SC_Obligations.Fingerprint_Type); @@ -715,7 +725,7 @@ package body Instrument.Input_Traces is function Last_Bit (Bit_Count : Any_Bit_Count) return Any_Bit_Id is (Any_Bit_Id (Bit_Count) - 1); - CU_Name : Compilation_Unit_Part; + CU_Name : Compilation_Unit_Name; begin Reserve (Statement_Buffer, Entry_Header.Statement_Bit_Count); @@ -757,7 +767,7 @@ package body Instrument.Input_Traces is (Unit => To_Qualified_Name (Unit_Name), Part => Unit_Part_Map (Entry_Header.Unit_Part)); when GNATcov_RTS.Buffers.File_Based_Language => - CU_Name := CU_Name_For_File (+Unit_Name); + CU_Name := CU_Name_For_File (+Unit_Name, +Project_Name); end case; On_Trace_Entry @@ -793,7 +803,7 @@ package body Instrument.Input_Traces is procedure On_Trace_Entry (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Part; + CU_Name : Compilation_Unit_Name; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; @@ -833,7 +843,7 @@ package body Instrument.Input_Traces is procedure On_Trace_Entry (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Part; + CU_Name : Compilation_Unit_Name; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/instrument-input_traces.ads b/tools/gnatcov/instrument-input_traces.ads index 43ed20190..7c8d7137c 100644 --- a/tools/gnatcov/instrument-input_traces.ads +++ b/tools/gnatcov/instrument-input_traces.ads @@ -34,7 +34,7 @@ package Instrument.Input_Traces is with procedure On_Trace_Entry (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Part; + CU_Name : Compilation_Unit_Name; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/instrument-main.adb b/tools/gnatcov/instrument-main.adb deleted file mode 100644 index 134475d8b..000000000 --- a/tools/gnatcov/instrument-main.adb +++ /dev/null @@ -1,41 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2023, 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 Instrument.Common; use Instrument.Common; - --- Implementation of the gnatcov instrument-main, which inserts a call to --- dump coverage buffers according to the various dump options passed --- on the command line. - -procedure Instrument.Main - (Instrumenter : in out Language_Instrumenter'Class; - Dump_Config : Any_Dump_Config; - Main_Filename : String; - Prj : Prj_Desc) is -begin - -- If the dump-trigger is manual, there is nothing to do - - if Dump_Config.Trigger = Manual then - return; - end if; - - Instrumenter.Auto_Dump_Buffers_In_Main - (Filename => Main_Filename, - Dump_Config => Dump_Config, - Prj => Prj); -end Instrument.Main; diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb deleted file mode 100644 index 98c1b9139..000000000 --- a/tools/gnatcov/instrument-projects.adb +++ /dev/null @@ -1,1225 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2023, 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.Characters.Handling; use Ada.Characters.Handling; -with Ada.Containers.Hashed_Maps; -with Ada.Containers.Indefinite_Ordered_Maps; -with Ada.Containers.Indefinite_Ordered_Sets; -with Ada.Directories; -with Ada.Exceptions; -with Ada.Strings; -with Ada.Strings.Fixed; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; -with Ada.Strings.Unbounded.Hash; -with Ada.Unchecked_Deallocation; - -with Interfaces; use Interfaces; - -with GNAT.OS_Lib; -with GNAT.Regexp; -with GNAT.Strings; - -with GNATCOLL.JSON; use GNATCOLL.JSON; -with GNATCOLL.VFS; -with GNATCOLL.Projects.Aux; use GNATCOLL.Projects.Aux; - -with Command_Line; use Command_Line; -with Files_Table; -with Hex_Images; use Hex_Images; -with Instrument.Ada_Unit; use Instrument.Ada_Unit; -with Instrument.C; use Instrument.C; -with Instrument.Clean_Objdirs; -with Instrument.Common; use Instrument.Common; -with Instrument.Main; -with Instrument.Source; -with JSON; use JSON; -with Outputs; -with Paths; use Paths; -with Project; use Project; -with Strings; use Strings; -with Support_Files; -with Text_Files; use Text_Files; - --- Generate instrumented sources for the source files of all units of --- interest. Also save mappings between coverage buffers and SCOs for each --- library units to SID files (one per library unit). --- --- Depending on Dump_Config, instrument mains to schedule a call to the --- dump procedure for the list of coverage buffers in all mains in the --- project. --- --- Language_Version restricts what source constructs the instrumenter is --- allowed to use. For instance, if Ada_2005 (or a lower version) is --- passed, it will not be allowed to introduce expression functions, and --- thus will emit a warning when it needed to do so. --- --- If Ignored_Source_File is non-null, ignore files whose names match the --- accessed pattern. --- --- Mains is the list of source files that were listed on the command line: --- if non-empty, they replace the mains specified in project files. - -procedure Instrument.Projects - (Dump_Config : Any_Dump_Config; - Ignored_Source_Files : access GNAT.Regexp.Regexp; - Mains : String_Vectors.Vector) -is - type Project_Info is record - Project : Project_Type; - -- Project that this record describes - - Externally_Built : Boolean; - -- Whether this project is externally built. In that case, we assume its - -- units of interest have already been instrumented. - - Output_Dir : Ada.Strings.Unbounded.Unbounded_String; - -- Subdirectory in the project file's object directory. All we generate - -- for this project must land in it. - - Desc : Prj_Desc; - - end record; - - type Project_Info_Access is access all Project_Info; - - package Project_Info_Maps is new Ada.Containers.Hashed_Maps - (Key_Type => Ada.Strings.Unbounded.Unbounded_String, - Element_Type => Project_Info_Access, - Equivalent_Keys => Ada.Strings.Unbounded."=", - Hash => Ada.Strings.Unbounded.Hash); - -- Mapping from project name (as returned by GNATCOLL.Projects.Name) to - -- Project_Info records. Project_Info records are owned by this map, and - -- thus must be deallocated when maps are deallocated. - - type Main_To_Instrument is record - CU_Name : Compilation_Unit_Part; - -- Compilation unit of the main to instrument - - File : GNATCOLL.VFS.Virtual_File; - -- Source file to instrument - - Prj_Info : Project_Info_Access; - -- Reference to the Project_Info record corresponding to the project - -- that owns the main to instrument. - end record; - - package Main_To_Instrument_Vectors is new Ada.Containers.Vectors - (Positive, Main_To_Instrument); - - use type GNATCOLL.VFS.Filesystem_String; - function Less (L, R : File_Info) return Boolean is - (L.File.Full_Name < R.File.Full_Name); - function Equal (L, R : File_Info) return Boolean is - (L.File.Full_Name = R.File.Full_Name); - - package File_Info_Sets is new Ada.Containers.Indefinite_Ordered_Sets - (Element_Type => File_Info, "<" => Less, "=" => Equal); - - type Library_Unit_Info is record - Unit_Name : Unbounded_String; - -- Name of this unit: unit name for unit-based languages, simple name - -- for file-based languages. - - Instr_Project : GPR.Project_Type; - -- Project in which instrumentation artifacts for this unit are - -- generated. - - Language_Kind : Any_Language_Kind; - -- Higher level representation of a language (unit-based or file-based) - - Language : Any_Language; - -- Actual language representation - - All_Externally_Built : Boolean; - -- Whether all of the parts of this unit belongs to an externally-built - -- project. If it is the case, the unit won't be instrumented; - -- otherwise, every unit part will. - - end record; - - package Unit_Maps is new - Ada.Containers.Indefinite_Ordered_Maps (String, Library_Unit_Info); - -- Map to unit names to unit info of files implementing this unit. For - -- file- based languages, the unit name is the full name (to simplify - -- dealing with homonym in different projects). - - type Inst_Context is limited record - Mapping_File, Config_Pragmas_File : Unbounded_String; - - Predefined_Source_Dirs : String_Vectors.Vector; - - Sources_Of_Interest_Response_File : Unbounded_String; - -- File containing the list of units of interest, identified by their - -- fullname. This is passed on to gnatcov instrument-source invokations - -- (for Ada), to know which part of a unit (spec / body / separate) must - -- be instrumented. - - Ignored_Source_Files_Present : Boolean; - Ignored_Source_Files : GNAT.Regexp.Regexp; - -- If present, instrumentation will ignore files whose names match the - -- accessed pattern. - - Project_Info_Map : Project_Info_Maps.Map; - -- For each project that contains units of interest, this tracks a - -- Project_Info record. - - Tag : Unbounded_String; - -- Tag relative to the current instrumentation run - - end record; - - function Create_Context - (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context; - -- Create an instrumentation context for the currently loaded project - - procedure Destroy_Context (Context : in out Inst_Context); - -- Free dynamically allocated resources in Context - - function Is_Ignored_Source_File - (Context : Inst_Context; Filename : String) return Boolean; - -- Return whether the instrumentation process must ignore the Filename - -- source file. - - function Get_Or_Create_Project_Info - (Context : in out Inst_Context; - Project : Project_Type) return Project_Info_Access; - -- Return the Project_Info record corresponding to Project. Create it if it - -- does not exist. - - procedure Register_Main_To_Instrument - (Context : in out Inst_Context; - Mains : in out Main_To_Instrument_Vectors.Vector; - File : GNATCOLL.VFS.Virtual_File; - Project : Project_Type); - -- Register in Mains a main to be instrumented so that it dumps coverage - -- buffers. File is the source file for this main, and Project is the - -- project that owns this main. - - procedure Prepare_Output_Dirs (IC : Inst_Context); - -- Make sure we have the expected tree of directories for the - -- instrumentation output. - - function SID_Filename - (LU_Info : Library_Unit_Info; In_Library_Dir : Boolean) return String; - -- Return the filename of the SID file to create for the given library - -- unit. If In_Library_Dir is true, then return a filename located in the - -- project library directory. Otherwise, the filename is located in the - -- object directory. - - function Load_From_Project (Prj : Project_Type) return Prj_Desc; - -- Load the project description from the given project - - function Compilation_Unit_Options - (IC : Inst_Context; - Prj : Prj_Desc; - LU_Info : Library_Unit_Info) return String_Vectors.Vector; - -- Return the list of options to pass to a gnatcov instrument-source / - -- instrument-main (depending on Purpose) for the given compilation unit - -- LU_Info, belonging to the project Prj. - - procedure Add_Instrumented_Unit - (Project : GPR.Project_Type; Source_File : GPR.File_Info); - -- Add this source file to the list of units to instrument - - ----------------------- - -- Load_From_Project -- - ----------------------- - - function Load_From_Project (Prj : Project_Type) return Prj_Desc - is - Dot_Replacement : constant String := - Prj.Attribute_Value - (Attribute => Build ("Naming", "Dot_Replacement")); - Result : Prj_Desc; - begin - for Lang in Some_Language loop - if Builtin_Support (Lang) then - declare - Body_Suffix : constant String := - Project.Source_Suffix (Lang, GPR.Unit_Body, Prj); - Spec_Suffix : constant String := - Project.Source_Suffix (Lang, GPR.Unit_Spec, Prj); - begin - Result.Body_Suffix (Lang) := +Body_Suffix; - Result.Spec_Suffix (Lang) := +Spec_Suffix; - end; - end if; - end loop; - - Result.Prj_Name := +Prj.Name; - Result.Dot_Replacement := +Dot_Replacement; - - -- Load the set of compiler switches for languages requiring it - - for Lang in C_Family_Language loop - declare - use type GNAT.Strings.String_List_Access; - Options : Analysis_Options; - Compiler_Opts : String_Vectors.Vector; - Switches : GNAT.Strings.String_List_Access; - Compiler_Driver : constant String := - GNATCOLL.Projects.Attribute_Value - (Prj, - GPR.Compiler_Driver_Attribute, - Image (Lang)); - - procedure Register_Source_Dirs - (P : GNATCOLL.Projects.Project_Type); - -- Add the source directories of P's project file to the search - -- paths to be passed as -I arguments later. The order in which - -- the paths are added to the search paths vector is the same - -- order in which GNATCOLL retrieves the files in the project - -- tree. gprbuild also depends on GNATCOLL which ensures we - -- have the same behavior here. - - -------------------------- - -- Register_Source_Dirs -- - -------------------------- - - procedure Register_Source_Dirs - (P : GNATCOLL.Projects.Project_Type) is - begin - for Dir of P.Source_Dirs loop - Result.Search_Paths.Append - ("-I" & (+GNATCOLL.VFS."+" (GNATCOLL.VFS.Dir_Name (Dir)))); - end loop; - end Register_Source_Dirs; - begin - -- Pass the source directories of the project file as -I options. - -- Note that this will duplicate with the project tree traversal - -- below, but we need this project source directories to be - -- picked first. We thus make sure to add them first to the - -- PP_Search_Path list. - - Register_Source_Dirs (Prj); - - -- Pass the source directories of included projects as -I options - - Project.Iterate_Projects - (Prj, Register_Source_Dirs'Access, - Recursive => True, Include_Extended => True); - - -- Get the compiler switches from the project file. When - -- registering a compilation unit for instrumentation, we also - -- fill the compilation unit specific switches that will override - -- the project defaults, if there are any (see - -- Add_Instrumented_Unit). - - Switches := - Prj.Attribute_Value - (Attribute => GPR.Compiler_Default_Switches_Attribute, - Index => Image (Lang)); - - -- If we manage to find appropriate switches, convert them to a - -- string vector import the switches. - - if Switches /= null then - declare - Args : String_Vectors.Vector; - begin - for S of Switches.all loop - Args.Append (To_Unbounded_String (S.all)); - end loop; - GNAT.Strings.Free (Switches); - Import_From_Args (Options, Args); - end; - end if; - - Add_Options (Compiler_Opts, Options, Pass_Builtins => False); - - Result.Compiler_Options (Lang) := Compiler_Opts; - Result.Compiler_Driver (Lang) := +Compiler_Driver; - end; - end loop; - - return Result; - end Load_From_Project; - - -------------------- - -- Create_Context -- - -------------------- - - function Create_Context - (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context is - begin - return IC : Inst_Context do - IC.Ignored_Source_Files_Present := Ignored_Source_Files /= null; - if Ignored_Source_Files /= null then - IC.Ignored_Source_Files := Ignored_Source_Files.all; - end if; - end return; - end Create_Context; - - --------------------- - -- Destroy_Context -- - --------------------- - - procedure Destroy_Context (Context : in out Inst_Context) is - procedure Free is new Ada.Unchecked_Deallocation - (Project_Info, Project_Info_Access); - begin - -- Deallocate all Project_Info in Context, and then clear the hashed - -- map, both to avoid dangling pointers and to make Destroy_Context - -- callable more than once, like conventional deallocation procedures - -- in Ada. - - for Cur in Context.Project_Info_Map.Iterate loop - declare - PI : Project_Info_Access := Project_Info_Maps.Element (Cur); - begin - Free (PI); - end; - end loop; - Context.Project_Info_Map := Project_Info_Maps.Empty_Map; - end Destroy_Context; - - ---------------------------- - -- Is_Ignored_Source_File -- - ---------------------------- - - function Is_Ignored_Source_File - (Context : Inst_Context; Filename : String) return Boolean - is - begin - return - Context.Ignored_Source_Files_Present - and then GNAT.Regexp.Match - (S => Fold_Filename_Casing (Filename), - R => Context.Ignored_Source_Files); - end Is_Ignored_Source_File; - - -------------------------------- - -- Get_Or_Create_Project_Info -- - -------------------------------- - - function Get_Or_Create_Project_Info - (Context : in out Inst_Context; - Project : Project_Type) return Project_Info_Access - is - use Project_Info_Maps; - - -- Look for an existing Project_Info record corresponding to Project - - Project_Name : constant Unbounded_String := +Project.Name; - Position : constant Cursor := Context.Project_Info_Map.Find - (Project_Name); - begin - if Has_Element (Position) then - return Element (Position); - - else - -- The requested Project_Info record does not exist yet. Create it, - -- register it and return it. - - declare - Storage_Project : constant Project_Type := - Project.Extending_Project (Recurse => True); - -- Actual project that will host instrumented sources: even when - -- we instrument an extended project, the resulting instrumented - -- sources must go to the ultimate extending project's object - -- directory. This is similar to the object directory that hosts - -- object files when GPRbuild processes a project that is - -- extended. - - Result : constant Project_Info_Access := new Project_Info' - (Project => Project, - Externally_Built => Project.Externally_Built, - Output_Dir => +Project_Output_Dir (Storage_Project), - Desc => Load_From_Project (Project)); - begin - Result.Desc.Output_Dir := Result.Output_Dir; - Context.Project_Info_Map.Insert (Project_Name, Result); - return Result; - end; - end if; - end Get_Or_Create_Project_Info; - - ------------------------- - -- Prepare_Output_Dirs -- - ------------------------- - - procedure Prepare_Output_Dirs (IC : Inst_Context) is - use Project_Info_Maps; - begin - for Cur in IC.Project_Info_Map.Iterate loop - declare - Prj_Info : Project_Info renames Element (Cur).all; - Output_Dir : constant String := +(Element (Cur).Output_Dir); - begin - -- Do not create output directories for externally built projects: - -- we don't instrument them and we may not have filesystem - -- permissions to create directories there. - - if not Prj_Info.Externally_Built - and then not Ada.Directories.Exists (Output_Dir) - then - Ada.Directories.Create_Path (Output_Dir); - end if; - end; - end loop; - end Prepare_Output_Dirs; - - --------------------------------- - -- Register_Main_To_Instrument -- - --------------------------------- - - procedure Register_Main_To_Instrument - (Context : in out Inst_Context; - Mains : in out Main_To_Instrument_Vectors.Vector; - File : GNATCOLL.VFS.Virtual_File; - Project : Project_Type) - is - File_Info : constant GNATCOLL.Projects.File_Info := - Standard.Project.Project.Info (File); - CU_Name : constant Compilation_Unit_Part := - To_Compilation_Unit_Name (File_Info); - Prj_Info : constant Project_Info_Access := - Get_Or_Create_Project_Info (Context, Project); - begin - Mains.Append - (Main_To_Instrument' - (CU_Name => CU_Name, - File => File, - Prj_Info => Prj_Info)); - end Register_Main_To_Instrument; - - ------------------ - -- SID_Filename -- - ------------------ - - function SID_Filename - (LU_Info : Library_Unit_Info; - In_Library_Dir : Boolean) return String - is - use GNATCOLL.VFS; - - -- Determine in which project we will put this SID file, and the - -- basename for the SID file to create. Mimic how GNAT creates ALI - -- files: use the project of the main source of the library unit, start - -- from the basename of that source file, replace the last extension - -- with ".sid". Also make sure to use the most extending project in the - -- hierarchy, which is where GPRbuild puts ALI/object files. - - SID_Basename : US.Unbounded_String; - - Project : constant GPR.Project_Type := - GPR.Extending_Project - (Project => LU_Info.Instr_Project, - Recurse => True); - pragma Assert (Project /= GPR.No_Project); - - Output_Directory : constant Virtual_File := - (if In_Library_Dir - then Project.Library_Ali_Directory - else Project.Object_Dir); - begin - case Language_Kind (LU_Info.Language) is - when Unit_Based_Language => - declare - Src_Body_Basename : constant String := +Project.File_From_Unit - (Unit_Name => +LU_Info.Unit_Name, - Part => Unit_Body, - Language => Image (LU_Info.Language), - File_Must_Exist => True); - Src_Spec_Basename : constant String := +Project.File_From_Unit - (Unit_Name => +LU_Info.Unit_Name, - Part => Unit_Spec, - Language => Image (LU_Info.Language), - File_Must_Exist => True); - Src_Basename : constant String := - (if Src_Body_Basename = "" - then Src_Spec_Basename - else Src_Body_Basename); - Src_Ext_Index : constant Positive := - Ada.Strings.Fixed.Index - (Src_Basename, ".", Ada.Strings.Backward); - begin - SID_Basename := - +(Src_Basename (Src_Basename'First .. Src_Ext_Index) - & "sid"); - end; - when File_Based_Language => - SID_Basename := - +Ada.Directories.Simple_Name (+LU_Info.Unit_Name) & ".sid"; - end case; - - return String'(+Output_Directory.Full_Name) / (+SID_Basename); - end SID_Filename; - - ------------------------------ - -- Compilation_Unit_Options -- - ------------------------------ - - function Compilation_Unit_Options - (IC : Inst_Context; - Prj : Prj_Desc; - LU_Info : Library_Unit_Info) return String_Vectors.Vector - is - Result : String_Vectors.Vector; - - procedure Compilation_Unit_Options_Ada; - - ---------------------------------- - -- Compilation_Unit_Options_Ada -- - ---------------------------------- - - procedure Compilation_Unit_Options_Ada is - begin - Result.Append ("--gnatem=" & IC.Mapping_File); - Result.Append ("--gnatec=" & IC.Config_Pragmas_File); - - -- Load the predefined source directories - - for Dir of IC.Predefined_Source_Dirs loop - Result.Append ("--runtime-dir=" & Dir); - end loop; - end Compilation_Unit_Options_Ada; - - begin - -- Depending on the language, pass the right set of options - - case LU_Info.Language is - when Ada_Language => - Compilation_Unit_Options_Ada; - when others => - null; - end case; - - -- Pass the list of sources of interest, to e.g. skip the - -- instrumentation of the spec / body / subunit for an Ada unit if - -- it was requested through a --ignored-source-files switch. - - Result.Append ("--files=@" & IC.Sources_Of_Interest_Response_File); - - -- Pass the right language - - Result.Append (+"--lang=" & Image (LU_Info.Language)); - - -- Pass the project description options - - Result.Append - (String_Vectors.Vector' - (Unparse (Prj, LU_Info.Unit_Name, LU_Info.Language))); - - return Result; - end Compilation_Unit_Options; - - -- Create the instrumenter context - - IC : Inst_Context := Create_Context (Ignored_Source_Files); - - Root_Project_Info : constant Project_Info_Access := - Get_Or_Create_Project_Info (IC, Project.Project.Root_Project); - - -- Create a map from library units to lists of compilation units to - -- instrument for them. - - Instrumented_Sources : Unit_Maps.Map; - -- List of units that should be instrumented - - Files_Of_Interest_Str_Set : String_Sets.Set; - Files_Of_Interest : File_Info_Sets.Set; - -- List of files of interest. - -- - -- This is passed on to instrument-source invocations when instrumenting - -- an Ada file (to know which part of a compilation unit must be - -- instrumented, i.e. spec / body / separates). - - --------------------------- - -- Add_Instrumented_Unit -- - --------------------------- - - procedure Add_Instrumented_Unit - (Project : GPR.Project_Type; Source_File : GPR.File_Info) - is - Language : constant Src_Supported_Language := - To_Language (Source_File.Language); - Lang_Kind : constant Any_Language_Kind := Language_Kind (Language); - - use Unit_Maps; - Unit_Name : constant String := - (case Lang_Kind is - when Unit_Based_Language => Owning_Unit_Name (Source_File), - when File_Based_Language => - GNATCOLL.VFS."+" (Source_File.File.Full_Name)); - - Prj_Info : constant Project_Info_Access := - Get_Or_Create_Project_Info (IC, Source_File.Project); - - LU_Info : constant Library_Unit_Info := - (Unit_Name => +Unit_Name, - Instr_Project => Project, - Language_Kind => Lang_Kind, - Language => Language, - All_Externally_Built => Prj_Info.Externally_Built); - - begin - -- Check if this is an ignored source file - - if Is_Ignored_Source_File (IC, +Source_File.File.Base_Name) then - return; - end if; - - -- Check if gnatcov was built with support for this language. If not, - -- exit early. - - if not Builtin_Support (Language) then - return; - end if; - - -- Otherwise, this is a source of interest - - Files_Of_Interest.Insert (Source_File); - Files_Of_Interest_Str_Set.Insert (+(+Source_File.File.Full_Name)); - - -- Headers are not instrumented by themselves, so exit early as soon - -- as they have been added to the sources of interest. - - if Language in C_Family_Language - and then Source_File.Unit_Part = Unit_Spec - then - return; - end if; - - if not Instrumented_Sources.Contains (Unit_Name) then - Instrumented_Sources.Insert (Unit_Name, LU_Info); - end if; - declare - Cur_Ref : constant Unit_Maps.Reference_Type := - Instrumented_Sources.Reference (Unit_Name); - begin - if not Prj_Info.Externally_Built then - Cur_Ref.Instr_Project := Project; - Cur_Ref.All_Externally_Built := False; - end if; - end; - - -- If the unit belongs to an externally built project, exit after it - -- was added it to the instrumented sources. We won't instrument it - -- in the current instrumentation run, so there is no need to grab - -- information useful for instrumentation purposes. - - if Source_File.Project.Externally_Built - then - return; - end if; - - -- Also get compiler switches that are file-specific and register them - -- in the project description. - - if Language in C_Family_Language then - declare - use type GNAT.Strings.String_List_Access; - Options : Analysis_Options; - Compiler_Opts : String_Vectors.Vector; - Switches : GNAT.Strings.String_List_Access; - Basename : constant String := +Source_File.File.Base_Name; - begin - Switches := - Project.Attribute_Value - (Attribute => GPR.Build ("compiler", "switches"), - Index => Basename); - if Switches /= null then - declare - Args : String_Vectors.Vector; - begin - for S of Switches.all loop - Args.Append (To_Unbounded_String (S.all)); - end loop; - GNAT.Strings.Free (Switches); - Import_From_Args (Options, Args); - end; - Add_Options (Compiler_Opts, Options, Pass_Builtins => False); - Prj_Info.Desc.Compiler_Options_Unit.Insert - (LU_Info.Unit_Name, Compiler_Opts); - end if; - end; - end if; - end Add_Instrumented_Unit; - - Mains_To_Instrument : array (Src_Supported_Language) - of Main_To_Instrument_Vectors.Vector; - -- For each supported language, list of mains to instrument. Note that - -- this is filled even when dump-trigger is manual: in that case the - -- instrumentation of the main will do nothing. - - Exec_Filename : constant String := Ada.Directories.Compose - (Support_Files.Libexec_Dir, - "gnatcov64" & GNAT.OS_Lib.Get_Executable_Suffix.all); - -- Launch gnatcov64 for gnatcov subprocesses (when instrumenting sources - -- and mains), to bypass the wrapper and save some execution time. - - Ada_Instrumenter : aliased Instrument.Ada_Unit.Ada_Instrumenter_Type; - C_Instrumenter : aliased Instrument.C.C_Instrumenter_Type; - CPP_Instrumenter : aliased Instrument.C.CPP_Instrumenter_Type; - Instrumenters : constant array (Src_Supported_Language) - of access Language_Instrumenter'Class := - (Ada_Language => Ada_Instrumenter'Access, - C_Language => C_Instrumenter'Access, - CPP_Language => CPP_Instrumenter'Access); - - -- Start of processing for Instrument_Units_Of_Interest - -begin - -- Set the instrumentation tag - - declare - Time : constant Unsigned_64 := - Unsigned_64 - (GNAT.OS_Lib.To_C (GNAT.OS_Lib.Current_Time)); - Tag : constant String := - Hex_Images.Strip_Zero_Padding - (Hex_Images.Hex_Image (Time)); - -- Tag for the current instrumentation run. Passed on to instrument-main - -- invocations, to have the same tag for mains instrumented at the - -- same time. - - begin - IC.Tag := +Tag; - end; - - -- Delete output directories from previous instrumentations - - Clean_Objdirs; - - -- First get the list of all units of interest - - for Lang in Src_Supported_Language loop - if Src_Enabled_Languages (Lang) - and then Root_Project_Info.Project.Has_Language (Image (Lang)) - then - Project.Enumerate_Sources - (Add_Instrumented_Unit'Access, Lang, Include_Stubs => True); - end if; - end loop; - - -- Remove all of the separate whose parent unit was not instrumented, as - -- this is not supported. TODO???: we should probably issue a warning - -- there. - - for Source of Files_Of_Interest.Copy loop - if Source.Unit_Part = Unit_Separate then - declare - Parent_Unit : constant GNATCOLL.Projects.File_Info := - Project.Project.Info - (Project.Project.Other_File (Source.File)); - begin - if not Files_Of_Interest.Contains (Parent_Unit) then - Files_Of_Interest.Delete (Source); - end if; - end; - end if; - end loop; - - -- If we need to instrument all the mains, also go through them now, so - -- that we can prepare output directories for their projects later on. - -- Note that for user convenience, we want to do this for all the - -- languages that gnatcov supports, even those that are not considered - -- for coverage analysis. - -- - -- If no source file was specified on the command line to be a main, - -- use the list of mains specified in project files. - - if Mains.Is_Empty then - for Lang in Src_Supported_Language loop - for Main of Project.Enumerate_Mains (Lang) loop - Register_Main_To_Instrument - (IC, Mains_To_Instrument (Lang), Main.File, Main.Project); - end loop; - end loop; - - -- Otherwise, make sure we can find the source file of each main in - -- the project tree and that we can instrument them (supported - -- language). - - else - for Filename of Mains loop - declare - use GNATCOLL.VFS; - - F : constant String := +Filename; - Info : constant File_Info := - Project.Project.Root_Project.Create_From_Project (+F); - File : constant Virtual_File := Info.File; - Project : constant Project_Type := Info.Project; - Lang : Any_Language; - begin - if File = No_File or else Project = No_Project then - Outputs.Fatal_Error ("No such source file: " & F); - end if; - - Lang := To_Language_Or_All (Info.Language); - if Lang not in Src_Supported_Language - or else not Builtin_Support (Lang) - then - Outputs.Fatal_Error - ("Cannot instrument main source file (unsupported" - & " language): " & F); - end if; - - Register_Main_To_Instrument - (IC, Mains_To_Instrument (Lang), File, Project); - end; - end loop; - end if; - - -- Check early if there are no sources of interest - - if Files_Of_Interest.Length = 0 then - Outputs.Fatal_Error ("No unit to instrument."); - end if; - - -- Now that we know all the sources we need to instrument, prepare - -- output directories. - - Prepare_Output_Dirs (IC); - - -- Record in a file all of the files and headers of interest. We separate - -- both as we do not expect to have coverage buffers for header files (the - -- coverage data is in including bodies' coverage buffers). - - IC.Mapping_File := - +Create_Ada_Mapping_File (Project.Project.Root_Project); - IC.Config_Pragmas_File := - +Create_Config_Pragmas_File (Project.Project.Root_Project); - IC.Sources_Of_Interest_Response_File := - +To_String (Root_Project_Info.all.Output_Dir) / ".sources_of_interest"; - - -- Set the runtime directories - - declare - use GNATCOLL.VFS; - begin - for Dir of - Project.Project.Root_Project.Get_Environment.Predefined_Source_Path - loop - IC.Predefined_Source_Dirs.Append (+(+Full_Name (Dir))); - end loop; - end; - - -- Initialize the instrumenters: we will use them when parallelization is - -- disabled, but also to generate the unit holding the list of buffers, - -- in one of the supported languages. - - Ada_Instrumenter := - Create_Ada_Instrumenter - (IC.Tag, - +IC.Config_Pragmas_File, - +IC.Mapping_File, - IC.Predefined_Source_Dirs); - C_Instrumenter := Create_C_Instrumenter (IC.Tag); - CPP_Instrumenter := Create_CPP_Instrumenter (IC.Tag); - - -- Write the files of interest to temporary files in the instrumentation - -- directory. - - declare - Sources_Of_Interest_File : Text_Files.File_Type; - -- File containing the list of sources of interest - - begin - Sources_Of_Interest_File.Create - (+IC.Sources_Of_Interest_Response_File); - for Source of Files_Of_Interest loop - Sources_Of_Interest_File.Put_Line (+Source.File.Full_Name); - end loop; - Sources_Of_Interest_File.Close; - end; - - -- Instrument every unit of interest asynchronously - - declare - Instrument_Source_Pool : Process_Pool (Parallelism_Level); - - Instrument_Source_Args : String_Vectors.Vector; - -- Common arguments for all of the gnatcov instrument-source - -- invocations. - - begin - Instrument_Source_Args.Append (+"instrument-source"); - Instrument_Source_Args.Append - (Common_Switches (Cmd_Instrument_Source)); - for Cur in Instrumented_Sources.Iterate loop - declare - Unit_Args : String_Vectors.Vector := - Instrument_Source_Args.Copy; - -- Args specific to a gnatcov instrument-source invocation - -- (e.g. the common arguments + the sources that must be - -- instrumented for a specific unit). - - Unit_Name : constant String := Unit_Maps.Key (Cur); - LU_Info : constant Library_Unit_Info := Unit_Maps.Element (Cur); - - Obj_SID : constant String := - SID_Filename (LU_Info, In_Library_Dir => False); - - Prj : constant Project_Type := LU_Info.Instr_Project; - Desc : constant Prj_Desc := - IC.Project_Info_Map.Element (+Prj.Name).Desc; - begin - -- Skip instrumentation of the unit if it was already - -- instrumented. - - if LU_Info.All_Externally_Built then - goto Continue; - end if; - - -- Add the arguments that are specific to the compilation unit - - Unit_Args.Append - (Compilation_Unit_Options - (IC, - Desc, - LU_Info)); - - Unit_Args.Append (+"--sid=" & Obj_SID); - - -- We instrument the body, spec and separates as a whole - - Unit_Args.Append (+Unit_Name); - - -- According to the set parallelism level, instrument in - -- the same process (thus reusing the libadalang context, which - -- is a big gain of time), or spawn another instrmentation - -- process. - - if Parallelism_Level = 1 then - Instrument.Source - (Unit_Name => Unit_Name, - SID_Name => Obj_SID, - Instrumenter => Instrumenters (LU_Info.Language).all, - Files_Of_Interest => Files_Of_Interest_Str_Set, - Prj => Desc); - else - -- Asynchronously instrument - - Instrument_Source_Pool.Run_Command - (Command => Exec_Filename, - Arguments => Unit_Args, - Origin_Command_Name => "gnatcov instrument", - Ignore_Error => False); - end if; - end; - <> - end loop; - end; - - -- Copy SID files into the library directory - - for LU_Info of Instrumented_Sources loop - declare - Obj_SID : constant String := - SID_Filename (LU_Info, In_Library_Dir => False); - Lib_SID : constant String := - SID_Filename (LU_Info, In_Library_Dir => True); - Success : Boolean; - begin - if not LU_Info.All_Externally_Built and then Obj_SID /= Lib_SID then - - -- Unlike the object directory, which GNATCOLL.Project - -- creates automatically, the library directory may not - -- exist: create it if needed. - - declare - use GNATCOLL.VFS; - begin - Create (Create (+Lib_SID).Dir_Name).Make_Dir; - exception - when Exc : VFS_Directory_Error => - Outputs.Fatal_Error - (Ada.Exceptions.Exception_Message (Exc)); - end; - - GNAT.OS_Lib.Copy_File - (Name => Obj_SID, - Pathname => Lib_SID, - Success => Success, - Mode => GNAT.OS_Lib.Overwrite); - if not Success then - Outputs.Fatal_Error - ("Error while copying " & Obj_SID - & " to the library directory: " & Lib_SID); - end if; - end if; - end; - end loop; - - -- Then, instrument asynchronously every main - - declare - Instrument_Main_Pool : Process_Pool (Parallelism_Level); - Instrument_Main_Args : String_Vectors.Vector; - - Main_Filename : Unbounded_String; - -- Fullname for the main. It can either be an instrumented version of - -- the main (if it also was instrumented as a source), or the original - -- version. - - Explicit_Dump_Config : Any_Dump_Config := Dump_Config; - -- Dump config with explicited defaults. The only interesting thing - -- is the dump-filename-prefix that is computed after the name of - -- the main in the project file, if not specified explicitly on the - -- command line. - - begin - Instrument_Main_Args.Append (+"instrument-main"); - - -- Add the root project name, as the symbol holding the list of - -- coverage buffers is defined accordingly. - - Instrument_Main_Args.Append - (+"--project-name=" & Root_Project_Info.Project.Name); - - Instrument_Main_Args.Append (Common_Switches (Cmd_Instrument_Main)); - - for Language in Src_Supported_Language loop - for Main of Mains_To_Instrument (Language) loop - declare - Unit_Name : constant Unbounded_String := - +(case Main.CU_Name.Language_Kind is - when Unit_Based_Language => - To_Ada (Main.CU_Name.Unit), - when File_Based_Language => (+Main.File.Full_Name)); - Unit_Args : String_Vectors.Vector := - Instrument_Main_Args.Copy; - begin - Unit_Args.Append - (Compilation_Unit_Options - (IC, - Main.Prj_Info.Desc, - Library_Unit_Info' - (Unit_Name => Unit_Name, - Instr_Project => Main.Prj_Info.Project, - Language_Kind => Language_Kind (Language), - Language => Language, - All_Externally_Built => False))); - - -- Pass main-specific dump-config options - - if Dump_Config.Channel = Binary_File then - - -- If no dump filename prefix was specified, compute it - -- here: we use the executable name, that is retrieved from - -- the project. - - if Length (Dump_Config.Filename_Prefix) = 0 then - Explicit_Dump_Config.Filename_Prefix := - +(+Root_Project_Info.Project.Executable_Name - (Main.File.Full_Name)); - end if; - end if; - - Unit_Args.Append (Unparse_Config (Explicit_Dump_Config)); - - -- Then append the main filename. If the main was instrumented - -- as a unit of interest before, then pass the instrumented - -- version. - - if Instrumented_Sources.Contains (+Unit_Name) then - Main_Filename := - +(+Root_Project_Info.Output_Dir) / (+Main.File.Base_Name); - else - Main_Filename := +(+Main.File.Full_Name); - end if; - - Unit_Args.Append (Main_Filename); - - if Parallelism_Level = 1 then - declare - Instr_Units : String_Sets.Set; - begin - for Source of Files_Of_Interest loop - Instr_Units.Insert (+(+Source.File.Full_Name)); - end loop; - Instrument.Main - (Instrumenter => Instrumenters (Language).all, - Dump_Config => Explicit_Dump_Config, - Main_Filename => +Main_Filename, - Prj => Main.Prj_Info.Desc); - end; - else - Instrument_Main_Pool.Run_Command - (Command => Exec_Filename, - Arguments => Unit_Args, - Origin_Command_Name => "gnatcov instrument", - Ignore_Error => False); - end if; - end; - end loop; - end loop; - end; - - if not Args.Bool_Args (Opt_Save_Temps) then - Ada.Directories.Delete_File (+IC.Sources_Of_Interest_Response_File); - end if; - - -- Emit the unit to contain the list of coverage buffers, exported to a - -- C symbol, in one of the language supported by the project. - -- - -- Note that this has an implicit hack to it: if Ada is a language of - -- the project, it will pick it over the others (as it is the first - -- enumeration member of the Src_Supported_Language type). This matters - -- as we make the assumption in the Emit_Dump_Helper_Unit implementation - -- in instrument-ada_unit.adb (when instrumenting for an Ada main) that - -- the Ada package for buffers list units always exists: we need to - -- include it in the main closure, as it puts buffer units in scope - -- by importing them (otherwise they aren't as they are used through - -- C symbol importations). - - declare - use Files_Table; - Instr_Units : Unit_Sets.Set; - begin - for LU_Info of Instrumented_Sources loop - Instr_Units.Insert - (Compilation_Unit'(LU_Info.Language_Kind, LU_Info.Unit_Name)); - end loop; - for Lang in Src_Supported_Language loop - if Builtin_Support (Lang) - and then Root_Project_Info.Project.Has_Language (Image (Lang)) - then - Instrumenters (Lang).Emit_Buffers_List_Unit - (Instr_Units, Root_Project_Info.Desc); - exit; - end if; - end loop; - end; - - Destroy_Context (IC); - - -- Save the dump trigger+channel information in the root project's - -- object directory. This allows user scripts to automatically know - -- where to expect source trace files (dump channel) without inspecting - -- all inputs (command-line arguments, project file, instrumentation - -- runtime, etc.) and whether that info is reliable (it is not if the - -- dump trigger is manual). - -- - -- TODO: this should go at some point in Instrument_Main (in which case - -- one would be generated per main). - - declare - J : constant GNATCOLL.JSON.JSON_Value := Create_Object; - Filename : constant String := - Project.Output_Dir & "/gnatcov-instr.json"; - begin - J.Set_Field ("dump-trigger", Image (Dump_Config.Trigger)); - J.Set_Field ("dump-channel", Image (Dump_Config.Channel)); - Write (Filename, J, Compact => False); - end; - -end Instrument.Projects; diff --git a/tools/gnatcov/instrument-source.adb b/tools/gnatcov/instrument-source.adb deleted file mode 100644 index 1749140fe..000000000 --- a/tools/gnatcov/instrument-source.adb +++ /dev/null @@ -1,66 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2023, 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 Checkpoints; use Checkpoints; -with Coverage; -with Instrument.Common; use Instrument.Common; -with Strings; use Strings; -with Traces_Files; use Traces_Files; - --- Implementation of the gnatcov instrument-source command, which instrument --- the given command-line unit. If the unit is of a unit based language, the --- unit name is the name of the unit, otherwise, it is the (full) filename. - -procedure Instrument.Source - (Unit_Name : String; - SID_Name : String; - Instrumenter : in out Language_Instrumenter'Class; - Files_Of_Interest : String_Sets.Set; - Prj : Prj_Desc) -is - Context : aliased Coverage.Context := Coverage.Get_Context; -begin - -- Even though instrumentation does not create any traces, the structure - -- of a SID file is basically a checkpoint, so it has a Trace_Kind field - -- in its header. Instead of leaving it to Unknown (default value) mark it - -- as Source_Trace_File so that when the .sid file is loaded, it will set - -- gnatcov in "source trace mode" and it will be rejected if binary traces - -- have already been loaded. - - Update_Current_Trace_Kind (Source_Trace_File); - - -- Instrument all of the source files implementing the compilation unit. - -- For Ada, this means instrumenting the body / spec / separates, and for - -- C/C++, this means instrumenting the .c file and the included headers. - - Instrumenter.Instrument_Unit (Unit_Name, Prj, Files_Of_Interest); - - -- Save the SCOs for the unit in the SID file - - Checkpoints.Checkpoint_Save - (SID_Name, - Context'Access, - Purpose => Checkpoints.Instrumentation); - - if Switches.Verbose then - SC_Obligations.Dump_All_SCOs; - end if; - - Checkpoints.Checkpoint_Clear; - -end Instrument.Source; diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 27fb6e360..0ef2f2eec 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -19,18 +19,35 @@ -- Source instrumentation with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Containers; use Ada.Containers; +with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Directories; -with Ada.Strings; -with Ada.Strings.Hash; +with Ada.Exceptions; +with Ada.Strings.Fixed; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Text_IO; use Ada.Text_IO; with Ada.Strings.Unbounded.Equal_Case_Insensitive; with Ada.Strings.Unbounded.Less_Case_Insensitive; +with Ada.Unchecked_Deallocation; with Interfaces; use Interfaces; - -with GNATCOLL.VFS; use GNATCOLL.VFS; - -with Command_Line; use Command_Line; -with Hex_Images; use Hex_Images; +with GNAT.OS_Lib; + +with GNATCOLL.JSON; use GNATCOLL.JSON; +with GNATCOLL.VFS; use GNATCOLL.VFS; + +with Checkpoints; +with Coverage; +with Files_Table; +with Hex_Images; use Hex_Images; +with Instrument.Ada_Unit; +with Instrument.Clean_Objdirs; +with Instrument.C; +with Instrument.Common; use Instrument.Common; +with JSON; use JSON; +with Outputs; +with Paths; use Paths; +with Project; package body Instrument is @@ -68,7 +85,7 @@ package body Instrument is -- "<" -- --------- - function "<" (Left, Right : Compilation_Unit_Part) return Boolean is + function "<" (Left, Right : Compilation_Unit_Name) return Boolean is begin if Left.Language_Kind = Right.Language_Kind then case Left.Language_Kind is @@ -99,7 +116,14 @@ package body Instrument is return Left.Part < Right.Part; end if; when File_Based_Language => - return Left.Filename < Right.Filename; + if Equal_Case_Insensitive + (Left.Project_Name, Right.Project_Name) + then + return Left.Filename < Right.Filename; + else + return Less_Case_Insensitive + (Left.Project_Name, Right.Project_Name); + end if; end case; else return Left.Language_Kind < Right.Language_Kind; @@ -110,7 +134,7 @@ package body Instrument is -- "=" -- --------- - function "=" (Left, Right : Compilation_Unit_Part) return Boolean + function "=" (Left, Right : Compilation_Unit_Name) return Boolean is use Ada_Identifier_Vectors; begin @@ -118,10 +142,10 @@ package body Instrument is case Left.Language_Kind is when Unit_Based_Language => if Left.Part = Right.Part - and then Length (Left.Unit) = Length (Right.Unit) + and then Left.Unit.Length = Right.Unit.Length then - for I in 1 .. Integer (Length (Left.Unit)) loop - if not Ada.Strings.Unbounded.Equal_Case_Insensitive + for I in 1 .. Integer (Left.Unit.Length) loop + if not Equal_Case_Insensitive (Unbounded_String (Left.Unit.Element (I)), Unbounded_String (Right.Unit.Element (I))) then @@ -135,12 +159,15 @@ package body Instrument is end if; return False; when File_Based_Language => - return Left.Filename = Right.Filename; + return Left.Filename = Right.Filename + and then Equal_Case_Insensitive + (Left.Project_Name, Right.Project_Name); end case; else return False; end if; end "="; + ------------------------- -- Qualified_Name_Slug -- ------------------------- @@ -179,7 +206,7 @@ package body Instrument is ---------------------------- function Instrumented_Unit_Slug - (Instrumented_Unit : Compilation_Unit_Part) return String + (Instrumented_Unit : Compilation_Unit_Name) return String is begin case Instrumented_Unit.Language_Kind is @@ -200,59 +227,51 @@ package body Instrument is end; when File_Based_Language => - return Filename_Slug (+Instrumented_Unit.Filename); + declare + Result : Ada_Identifier; + begin + -- For a compilation unit in a file-based language, relying on + -- the filename only is not enough, as there can be multiple + -- sources with the same name belonging to different projects + -- in a project tree. To avoid name clashes, prepend the name + -- of the owning project to the computed slug. + + Append + (Result, + Qualified_Name_Slug + (To_Qualified_Name (+Instrumented_Unit.Project_Name))); + + -- Add an unambiguous separator between the project name and + -- the rest of the slug. + + Append (Result, "_z_z"); + + -- File names can contain characters that cannot appear in + -- identifiers. Furthermore, unlike for the identifier to + -- return, file names may be case sensitive. In order to + -- produce valid identifiers, encode everything that isn't a + -- lower case letter or a digit. + + for C of "+" (Instrumented_Unit.Filename) loop + if C in 'a' .. 'z' | '0' .. '9' then + Append (Result, C); + else + Append + (Result, + "_" & Hex_Image (Unsigned_8'(Character'Pos (C)))); + end if; + end loop; + + return To_String (Result); + end; end case; end Instrumented_Unit_Slug; - ------------------- - -- Filename_Slug -- - ------------------- - - function Filename_Slug (Fullname : String) return String is - use Ada.Directories; - Result : Ada_Identifier; - begin - -- We use the basename slug, followed by a hash of the fullname, which - -- makes us confident that homonym files will be correctly handled. - - -- File names can contain characters that cannot appear in identifiers. - -- Furthermore, unlike for the identifier to return, file names may - -- be case sensitive. In order to produce valid identifiers, encode - -- everything that isn't a lower case letter or a digit. - - -- To avoid a leading underscore, add a prefix - - Append (Result, "z"); - - for C of Base_Name (Fullname) loop - if C in 'a' .. 'z' | '0' .. '9' then - Append (Result, C); - else - Append - (Result, - "_" & Hex_Image - (Interfaces.Unsigned_8'(Character'Pos (C)))); - end if; - end loop; - - -- Then, suffix with the hash - - declare - Hash_Str : constant String := - Hex_Image (Unsigned_32 (Ada.Strings.Hash (Fullname))); - begin - -- Do not forget to remove the leading whitespace... - - Append (Result, Hash_Str (2 .. Hash_Str'Last)); - end; - return To_String (Result); - end Filename_Slug; - ----------- -- Image -- ----------- - function Image (CU_Name : Compilation_Unit_Part) return String is + function Image (CU_Name : Compilation_Unit_Name) return String is begin case CU_Name.Language_Kind is when Unit_Based_Language => @@ -323,7 +342,7 @@ package body Instrument is function CU_Name_For_Unit (Unit : Ada_Qualified_Name; - Part : Unit_Parts) return Compilation_Unit_Part + Part : Unit_Parts) return Compilation_Unit_Name is begin return (Unit_Based_Language, Unit, Part); @@ -334,10 +353,11 @@ package body Instrument is ----------------------------- function CU_Name_For_File - (Filename : US.Unbounded_String) return Compilation_Unit_Part + (Filename : Unbounded_String; + Project_Name : Unbounded_String) return Compilation_Unit_Name is begin - return (File_Based_Language, Filename); + return (File_Based_Language, Filename, Project_Name); end CU_Name_For_File; ------------------------------ @@ -345,7 +365,7 @@ package body Instrument is ------------------------------ function To_Compilation_Unit_Name - (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Part + (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Name is begin case Language_Kind (To_Language (Source_File.Language)) is @@ -355,7 +375,8 @@ package body Instrument is Part => Source_File.Unit_Part); when File_Based_Language => return CU_Name_For_File - (Filename => +(+Source_File.File.Full_Name)); + (Filename => +GNATCOLL.VFS."+" (Source_File.File.Base_Name), + Project_Name => +Source_File.Project.Name); end case; end To_Compilation_Unit_Name; @@ -365,7 +386,7 @@ package body Instrument is function To_Filename (Project : Project_Type; - CU_Name : Compilation_Unit_Part; + CU_Name : Compilation_Unit_Name; Language : Any_Language) return String is begin case CU_Name.Language_Kind is @@ -385,7 +406,7 @@ package body Instrument is ---------------------------- function Find_Instrumented_Unit - (CU_Name : Compilation_Unit_Part) return CU_Id + (CU_Name : Compilation_Unit_Name) return CU_Id is use Instrumented_Unit_To_CU_Maps; @@ -398,118 +419,629 @@ package body Instrument is end if; end Find_Instrumented_Unit; - ---------------------------- - -- Load_From_Command_Line -- - ---------------------------- + package GPR renames GNATCOLL.Projects; + + type CU_Name_With_Ignore is record + Name : Compilation_Unit_Name; + Ignored : Boolean; + end record; + + function "<" (Left, Right : CU_Name_With_Ignore) return Boolean + is (if Left.Name = Right.Name + then Left.Ignored < Right.Ignored + else Left.Name < Right.Name); + + package CU_Name_Vectors is new Ada.Containers.Vectors + (Positive, CU_Name_With_Ignore); + + type Library_Unit_Info is record + CU_Names : CU_Name_Vectors.Vector; + -- List of compilation units implementing this library unit + + Body_Project, Spec_Project : GPR.Project_Type; + -- Projects that own the body/spec for this library unit + + Language_Kind : Any_Language_Kind; + -- Higher level representation of a language (unit-based or file-based) + + Language : Any_Language; + -- Actual language representation + end record; + type Library_Unit_Info_Access is access Library_Unit_Info; + + type Ignored_Unit_Info is record + Filename : Unbounded_String; + -- Name of the source file for this unit + + Prj_Info : Project_Info_Access; + -- Reference to the Project_Info record corresponding to the project + -- that owns the source file for this unit. + end record; + + type Ignored_Unit_Info_Access is access all Ignored_Unit_Info; + + package Ignored_Units_Maps is new Ada.Containers.Ordered_Maps + (Compilation_Unit_Name, Ignored_Unit_Info_Access); + + procedure Free is new Ada.Unchecked_Deallocation + (Ignored_Unit_Info, Ignored_Unit_Info_Access); + + package Library_Unit_Maps is new Ada.Containers.Indefinite_Ordered_Maps + (String, Library_Unit_Info_Access); + -- Map to associate a list of compilation units to instrument to a library + -- unit (indexed by the library unit name, i.e. the unit name or the + -- full name depending on the language kind for the library unit). + -- + -- For file-based languages, the library unit only has one compilation + -- unit associated to it (that is the library unit itself, for which the + -- name is the actual base filename). + + procedure Get_Or_Create + (Map : in out Library_Unit_Maps.Map; + Library_Unit : String; + Info : out Library_Unit_Info_Access); + -- Look for the info corresponding to Library_Unit in Map. Create it if + -- it does not exist yet and put it in Info. + + function SID_Filename + (Cur : Library_Unit_Maps.Cursor; + In_Library_Dir : Boolean) return String; + -- Return the filename of the SID file to create for the given library + -- unit. If In_Library_Dir is true, then return a filename located in the + -- project library directory. Otherwise, the filename is located in the + -- object directory. + + procedure Prepare_Output_Dirs (IC : Inst_Context); + -- Make sure we have the expected tree of directories for the + -- instrumentation output. + + ------------------- + -- Get_Or_Create -- + ------------------- + + procedure Get_Or_Create + (Map : in out Library_Unit_Maps.Map; + Library_Unit : String; + Info : out Library_Unit_Info_Access) + is + use Library_Unit_Maps; + Cur : constant Cursor := Map.Find (Library_Unit); + begin + if Has_Element (Cur) then + Info := Element (Cur); + else + Info := new Library_Unit_Info; + Info.Body_Project := GPR.No_Project; + Info.Spec_Project := GPR.No_Project; + Map.Insert (Library_Unit, Info); + end if; + end Get_Or_Create; + + ------------------ + -- SID_Filename -- + ------------------ + + function SID_Filename + (Cur : Library_Unit_Maps.Cursor; + In_Library_Dir : Boolean) return String + is + use Library_Unit_Maps; + + LU_Name : constant String := Key (Cur); + Info : Library_Unit_Info renames Element (Cur).all; + + -- Determine in which project we will put this SID file, and the + -- basename for the SID file to create. Mimic how GNAT creates ALI + -- files: use the project of the main source of the library unit, start + -- from the basename of that source file, replace the last extension + -- with ".sid". Also make sure to use the most extending project in the + -- hierarchy, which is where GPRbuild puts ALI/object files. + + SID_Basename : US.Unbounded_String; + + Use_Spec : constant Boolean := + Info.Body_Project = GPR.No_Project; + Project : constant GPR.Project_Type := + GPR.Extending_Project + (Project => (if Use_Spec + then Info.Spec_Project + else Info.Body_Project), + Recurse => True); + pragma Assert (Project /= GPR.No_Project); + + Output_Directory : constant Virtual_File := + (if In_Library_Dir + then Project.Library_Ali_Directory + else Project.Object_Dir); + begin + case Info.Language_Kind is + when Unit_Based_Language => + declare + Src_Basename : constant String := +Project.File_From_Unit + (Unit_Name => LU_Name, + Part => (if Use_Spec + then Unit_Spec + else Unit_Body), + Language => Image (Info.Language), + File_Must_Exist => False); + Src_Ext_Index : constant Positive := + Ada.Strings.Fixed.Index + (Src_Basename, ".", Ada.Strings.Backward); + begin + SID_Basename := + +(Src_Basename (Src_Basename'First .. Src_Ext_Index) + & "sid"); + end; + when File_Based_Language => + SID_Basename := +(Ada.Directories.Simple_Name (LU_Name & ".sid")); + end case; + + return String'(+Output_Directory.Full_Name) / (+SID_Basename); + end SID_Filename; + + ------------------------- + -- Prepare_Output_Dirs -- + ------------------------- + + procedure Prepare_Output_Dirs (IC : Inst_Context) is + use Project_Info_Maps; + begin + for Cur in IC.Project_Info_Map.Iterate loop + declare + Prj_Info : Project_Info renames Element (Cur).all; + Output_Dir : constant String := + +(Element (Cur).Output_Dir); + begin + -- Do not create output directories for externally built projects: + -- we don't instrument them and we may not have filesystem + -- permissions to create directories there. + + if not Prj_Info.Externally_Built + and then not Ada.Directories.Exists (Output_Dir) + then + Ada.Directories.Create_Path (Output_Dir); + end if; + end; + end loop; + end Prepare_Output_Dirs; + + ---------------------------------- + -- Instrument_Units_Of_Interest -- + ---------------------------------- + + procedure Instrument_Units_Of_Interest + (Dump_Config : Any_Dump_Config; + Language_Version : Any_Language_Version; + Ignored_Source_Files : access GNAT.Regexp.Regexp; + Mains : String_Vectors.Vector) + is + use String_Vectors; + + -- Initialize all the instrumenters + + Ada_Instrumenter : aliased Instrument.Ada_Unit.Ada_Instrumenter_Type := + Instrument.Ada_Unit.Create_Ada_Instrumenter (Language_Version); + C_Instrumenter : aliased Instrument.C.C_Instrumenter_Type := + (null record); + CPP_Instrumenter : aliased Instrument.C.CPP_Instrumenter_Type := + (null record); + + Instrumenters : constant array (Src_Supported_Language) + of access Language_Instrumenter'Class := + (Ada_Language => Ada_Instrumenter'Access, + C_Language => C_Instrumenter'Access, + CPP_Language => CPP_Instrumenter'Access); + + -- Create a map from library units to lists of compilation units to + -- instrument for them. + + LU_Map : Library_Unit_Maps.Map; + Current_LU_Info : Library_Unit_Info_Access; + Ignored_Units : Ignored_Units_Maps.Map; + + Mains_To_Instrument : array (Src_Supported_Language) + of Main_To_Instrument_Vectors.Vector; + -- For each supported language, list of mains to instrument. Always + -- empty when Dump_Config.Trigger is Manual. - function Load_From_Command_Line return Prj_Desc is - use Command_Line.Parser; - Language : constant Some_Language := - To_Language (+Args.String_Args (Opt_Lang).Value); - Result : Prj_Desc; + -- Create the instrumenter context - procedure Fill_If_Present - (Opt : String_Options; Field : out Unbounded_String); + IC : Inst_Context := Create_Context (Ignored_Source_Files); - --------------------- - -- Fill_If_Present -- - --------------------- + Root_Project_Info : constant Project_Info_Access := + Get_Or_Create_Project_Info (IC, Project.Project.Root_Project); - procedure Fill_If_Present - (Opt : String_Options; Field : out Unbounded_String) + procedure Add_Instrumented_Unit_Wrapper + (Project : GPR.Project_Type; Source_File : GPR.File_Info); + -- Add this source file to the list of units to instrument. For unit- + -- based languages, also add subunits that depend on this source file. + + ----------------------------------- + -- Add_Instrumented_Unit_Wrapper -- + ----------------------------------- + + procedure Add_Instrumented_Unit_Wrapper + (Project : GPR.Project_Type; Source_File : GPR.File_Info) is - Opt_Ref : constant Option_Reference := (String_Opt, Opt); + procedure Add_Instrumented_Unit + (CU_Name : Compilation_Unit_Name; Info : GPR.File_Info); + -- Wrapper for Instrument.Common.Add_Instrumented_Unit + + --------------------------- + -- Add_Instrumented_Unit -- + --------------------------- + + procedure Add_Instrumented_Unit + (CU_Name : Compilation_Unit_Name; Info : GPR.File_Info) + is + Should_Ignore : constant Boolean := + Is_Ignored_Source_File (IC, +Info.File.Base_Name); + begin + Current_LU_Info.CU_Names.Append + (CU_Name_With_Ignore'(Name => CU_Name, + Ignored => Should_Ignore)); + if Should_Ignore then + Ignored_Units.Insert + (CU_Name, + new Ignored_Unit_Info' + (Filename => To_Unbounded_String (+Info.File.Base_Name), + Prj_Info => Get_Or_Create_Project_Info + (IC, Info.Project))); + else + Add_Instrumented_Unit (IC, Info.Project, Info); + end if; + end Add_Instrumented_Unit; + + Language : constant Src_Supported_Language := + To_Language (Source_File.Language); + + -- Start of processing for Add_Instrumented_Unit_Wrapper + begin - if Is_Present (Args, Opt_Ref) then - Field := +Value (Args, Opt); + -- Skip this source file if the instrumenter requires it + + if Instrumenters (Language).Skip_Source_File (Source_File) then + return; end if; - end Fill_If_Present; - begin - if Language in C_Family_Language then - Fill_If_Present - (Opt_Compiler_Driver, Result.Compiler_Driver (Language)); - end if; - Fill_If_Present (Opt_Output_Directory, Result.Output_Dir); - Fill_If_Present (Opt_Spec_Suffix, Result.Spec_Suffix (Language)); - Fill_If_Present (Opt_Body_Suffix, Result.Body_Suffix (Language)); - Fill_If_Present (Opt_Project_Name, Result.Prj_Name); - Fill_If_Present (Opt_Dot_Replacement, Result.Dot_Replacement); - -- Compiler options are loaded through the --c/c++-opts switch + declare + CU_Name : constant Compilation_Unit_Name := + To_Compilation_Unit_Name (Source_File); - return Result; - end Load_From_Command_Line; + Unit_Name : constant String := + (case CU_Name.Language_Kind is + when Unit_Based_Language => To_Ada (CU_Name.Unit), - ------------- - -- Unparse -- - ------------- + -- For file-based languages, we need to use the full + -- name to account for homonyms. + + when File_Based_Language => +Source_File.File.Full_Name); + + begin + -- Get the vector in which we will record the compilation units + -- that the following call to Find_Units will list. + + Get_Or_Create (LU_Map, Unit_Name, Current_LU_Info); + + -- Keep track of projects that own this library unit's source + -- files for its spec/body. + + case Source_File.Unit_Part is + when GPR.Unit_Body => Current_LU_Info.Body_Project := Project; + when GPR.Unit_Spec => Current_LU_Info.Spec_Project := Project; + + -- Subunits cannot be units of interest, so Enumerate_Sources + -- should not be able to call Find_Units_Wrapper with a + -- subunit. Hence, the following should be unreachable. + + when GPR.Unit_Separate => + raise Program_Error with "unreachable code"; + end case; + + Current_LU_Info.Language_Kind := CU_Name.Language_Kind; + Current_LU_Info.Language := To_Language (Source_File.Language); + + case CU_Name.Language_Kind is + when Unit_Based_Language => + Instrument.Ada_Unit.Find_Ada_Units + (Ada_Instrumenter, + CU_Name, + Source_File, + Add_Instrumented_Unit'Access); + when File_Based_Language => + Add_Instrumented_Unit (CU_Name, Source_File); + end case; + end; + end Add_Instrumented_Unit_Wrapper; + + -- Start of processing for Instrument_Units_Of_Interest - function Unparse - (Desc : Prj_Desc; - Unit_Name : Unbounded_String; - Lang : Src_Supported_Language) return String_Vectors.Vector - is - Result : String_Vectors.Vector; - Compiler_Opts : String_Vectors.Vector; begin - -- Pass the right body / spec suffixes + -- Delete output directories from previous instrumentations - if Desc.Body_Suffix (Lang) /= Null_Unbounded_String then - Result.Append (+"--body-suffix"); - Result.Append (Desc.Body_Suffix (Lang)); - end if; + Clean_Objdirs; - if Desc.Spec_Suffix (Lang) /= Null_Unbounded_String then - Result.Append (+"--spec-suffix"); - Result.Append (Desc.Spec_Suffix (Lang)); - end if; + -- First get the list of all units of interest - if Desc.Dot_Replacement /= Null_Unbounded_String then - Result.Append (+"--dot-replacement"); - Result.Append (Desc.Dot_Replacement); - end if; + for Lang in Src_Supported_Language loop + if Src_Enabled_Languages (Lang) then + Project.Enumerate_Sources + (Add_Instrumented_Unit_Wrapper'Access, Lang); + end if; + end loop; + + -- If we need to instrument all the mains, also go through them now, so + -- that we can prepare output directories for their projects later on. + -- Note that for user convenience, we want to do this for all the + -- languages that gnatcov supports, even those that are not considered + -- for coverage analysis. + + if Dump_Config.Trigger /= Manual then + + -- If no source file was specified on the command line to be a main, + -- use the list of mains specified in project files. + + if Mains.Is_Empty then + for Lang in Src_Supported_Language loop + for Main of Project.Enumerate_Mains (Lang) loop + Register_Main_To_Instrument + (IC, Mains_To_Instrument (Lang), Main.File, Main.Project); + end loop; + end loop; + + -- Otherwise, make sure we can find the source file of each main in + -- the project tree and that we can instrument them (supported + -- language). - if Lang in C_Family_Language then - Compiler_Opts.Append (Desc.Search_Paths); - if Desc.Compiler_Options_Unit.Contains (Unit_Name) then - Compiler_Opts.Append - (Desc.Compiler_Options_Unit.Element (Unit_Name)); else - Compiler_Opts.Append (Desc.Compiler_Options (Lang)); - end if; - if not Compiler_Opts.Is_Empty then - case C_Family_Language (Lang) is - when CPP_Language => - Result.Append (+"--c++-opts"); - when C_Language => - Result.Append (+"--c-opts"); - end case; + for Filename of Mains loop + declare + F : constant String := +Filename; + Info : constant File_Info := + Project.Project.Root_Project.Create_From_Project (+F); + File : constant Virtual_File := Info.File; + Project : constant Project_Type := Info.Project; + Lang : Any_Language; + begin + if File = No_File or else Project = No_Project then + Outputs.Fatal_Error ("No such source file: " & F); + end if; + + Lang := To_Language_Or_All (Info.Language); + if Lang not in Src_Supported_Language then + Outputs.Fatal_Error + ("Cannot instrument main source file (unsupported" + & " language): " & F); + end if; + + Register_Main_To_Instrument + (IC, Mains_To_Instrument (Lang), File, Project); + end; + end loop; end if; + end if; + + -- Know that we know all the sources we need to instrument, prepare + -- output directories. + + Prepare_Output_Dirs (IC); + + -- For each library unit... + + for Cur in LU_Map.Iterate loop + + -- Instrument compilation units (only the ones this library unit + -- owns). Sort them first, so that the instrumentation order is + -- deterministic. + declare - First : Boolean := True; - Compiler_Opts_Str : Unbounded_String; + package Sorting is new CU_Name_Vectors.Generic_Sorting; + + LU_Info : constant Library_Unit_Info_Access := + Library_Unit_Maps.Element (Cur); + All_Externally_Built : Boolean := True; begin - for Compiler_Opt of Compiler_Opts loop - if First then - First := False; + Sorting.Sort (LU_Info.CU_Names); + for CU of LU_Info.CU_Names loop + if CU.Ignored then + declare + Unit_Info : Ignored_Unit_Info renames + Ignored_Units.Element (CU.Name).all; + Filename : constant String := To_String + (Unit_Info.Filename); + begin + -- Simply add the unit to the file table if it is not + -- externally built. + + if not Unit_Info.Prj_Info.Externally_Built then + All_Externally_Built := False; + Files_Table.Consolidate_Ignore_Status + (Index => Files_Table.Get_Index_From_Generic_Name + (Name => Filename, + Kind => Files_Table.Source_File), + Status => Files_Table.Always); + end if; + end; else - Append (Compiler_Opts_Str, ","); + declare + Unit_Info : Instrumented_Unit_Info renames + IC.Instrumented_Units.Element (CU.Name).all; + Filename : constant String := + To_String (Unit_Info.Filename); + Basename : constant String := + Ada.Directories.Simple_Name (Filename); + begin + -- Do not process units from externally built projects + + if not Unit_Info.Prj_Info.Externally_Built then + + -- Keep a note that we are processing at least one + -- source file from a non-externally built project. + + All_Externally_Built := False; + + -- Run the instrumentation for this file + + if Verbose then + Put_Line ("Instrumenting " & Basename); + end if; + Instrumenters (Unit_Info.Language).Instrument_Unit + (CU.Name, Unit_Info); + + -- Update the Ignore_Status of the CU we instrumented + + Files_Table.Consolidate_Ignore_Status + (Index => Files_Table.Get_Index_From_Generic_Name + (Name => Filename, + Kind => Files_Table.Source_File, + Indexed_Simple_Name => True), + Status => Files_Table.Never); + end if; + end; end if; - Append (Compiler_Opts_Str, Compiler_Opt); end loop; - Result.Append (Compiler_Opts_Str); + + -- Except for units entirely externally built (the spec, the body, + -- and potential subunits all belong to externally built + -- projects), emit a SID file to contain mappings between bits in + -- coverage buffers and SCOs. + + if not All_Externally_Built then + declare + Context : aliased Coverage.Context := Coverage.Get_Context; + Obj_SID : constant String := + SID_Filename (Cur, In_Library_Dir => False); + Lib_SID : constant String := + SID_Filename (Cur, In_Library_Dir => True); + Success : Boolean; + begin + Checkpoints.Checkpoint_Save + (Obj_SID, + Context'Access, + Purpose => Checkpoints.Instrumentation); + + -- If the object directory is different from the library + -- directory, copy the SID file to the library directory. + -- This allows "gnatcov coverage" to automatically pick it + -- up if the project is later made externally built. + + if Obj_SID /= Lib_SID then + + -- Unlike the object directory, which GNATCOLL.Project + -- creates automatically, the library directory may not + -- exist: create it if needed. + + begin + Create (Create (+Lib_SID).Dir_Name).Make_Dir; + exception + when Exc : VFS_Directory_Error => + Outputs.Fatal_Error + (Ada.Exceptions.Exception_Message (Exc)); + end; + + GNAT.OS_Lib.Copy_File + (Name => Obj_SID, + Pathname => Lib_SID, + Success => Success, + Mode => GNAT.OS_Lib.Overwrite); + if not Success then + Outputs.Fatal_Error + ("Error while copying " & Obj_SID + & " to the library directory: " & Lib_SID); + end if; + end if; + end; + + if Switches.Verbose then + SC_Obligations.Dump_All_SCOs; + end if; + end if; end; - if Desc.Compiler_Driver (Lang) /= Null_Unbounded_String then - Result.Append (+"--compiler-driver"); - Result.Append (Desc.Compiler_Driver (Lang)); - end if; + Checkpoints.Checkpoint_Clear; + end loop; + + if IC.Instrumented_Units.Length = 0 then + Outputs.Fatal_Error ("No unit to instrument."); end if; - Result.Append (+"--output-dir"); - Result.Append (Desc.Output_Dir); + declare + Instrumented_Units : Instrument.Common.CU_Name_Vectors.Vector; + -- List of instrumented units + + begin + for Cur in IC.Instrumented_Units.Iterate loop + Instrumented_Units.Append (Instrumented_Unit_Maps.Key (Cur)); + end loop; + + -- Emit the unit to contain the list of coverage buffers, exported to + -- a C symbol, in one of the language supported by the project. + -- + -- Note that this has an implicit hack to it: if Ada is a language of + -- the project, it will pick it over the others (as it is the first + -- enumeration member of the Src_Supported_Language type). This + -- matters as we make the assumption in the Emit_Dump_Helper_Unit + -- implementation in instrument-ada_unit.adb (when instrumenting for + -- an Ada main) that the Ada package for buffers list units always + -- exists: we need to include it in the main closure, as it puts + -- buffer units in scope by importing them (otherwise they aren't + -- as they are used through C symbol importations). + + for Language in Src_Supported_Language loop + if Project.Project.Root_Project.Has_Language (Image (Language)) + then + Instrumenters (Language).Emit_Buffers_List_Unit + (Root_Project_Info.all, Instrumented_Units); + exit; + end if; + end loop; + + -- Instrument all the mains to add the dump of coverage buffers. + -- Make sure to pass the instrumented version if the main is a unit + -- of interest. + + for Language in Src_Supported_Language loop + + for Main of Mains_To_Instrument (Language) loop + declare + Filename : constant String := + (if IC.Instrumented_Units.Contains (Main.CU_Name) + then (+Main.Prj_Info.Output_Dir) / (+Main.File.Base_Name) + else +Main.File.Full_Name); + begin + Instrumenters (Language).Auto_Dump_Buffers_In_Main + (Filename, + Instrumented_Units, + Dump_Config, + Main.Prj_Info.all); + end; + end loop; + end loop; + end; + + -- Deallocate Ignored_Unit_Infos + + for IU of Ignored_Units loop + Free (IU); + end loop; + Ignored_Units := Ignored_Units_Maps.Empty_Map; - return Result; - end Unparse; + -- Save the dump trigger+channel information in the root project's + -- object directory. This allows user scripts to automatically know + -- where to expect source trace files (dump channel) without inspecting + -- all inputs (command-line arguments, project file, instrumentation + -- runtime, etc.) and whether that info is reliable (it is not if the + -- dump trigger is manual). + + declare + J : constant JSON_Value := Create_Object; + Filename : constant String := + Project.Output_Dir & "/gnatcov-instr.json"; + begin + J.Set_Field ("dump-trigger", Image (Dump_Config.Trigger)); + J.Set_Field ("dump-channel", Image (Dump_Config.Channel)); + Write (Filename, J, Compact => False); + end; + end Instrument_Units_Of_Interest; end Instrument; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 46c5eb4b3..8596dfb96 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -18,11 +18,11 @@ -- Support for source instrumentation -with Ada.Containers.Hashed_Maps; with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; -with Ada.Strings.Unbounded.Hash; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Strings.Unbounded; + +with GNAT.Regexp; with GNATCOLL.Projects; use GNATCOLL.Projects; @@ -38,12 +38,6 @@ package Instrument is package US renames Ada.Strings.Unbounded; - package GPR renames GNATCOLL.Projects; - - use type Ada.Containers.Count_Type; - - Parallelism_Level : Natural := 1; - function Language_Kind (Language : Some_Language) return Any_Language_Kind; -- Returns the language kind (unit-based or file-based) for the given @@ -66,7 +60,7 @@ package Instrument is with Pre => not Name.Is_Empty; -- Turn the given qualified name into Ada syntax - type Compilation_Unit_Part + type Compilation_Unit_Name (Language_Kind : Any_Language_Kind := Unit_Based_Language) is record @@ -81,22 +75,26 @@ package Instrument is -- Fallback for file-based languages (like C). We will use the -- simple filename for now. + Project_Name : US.Unbounded_String; + -- We also need the project name as different projects can have + -- the same file. + end case; end record; - -- Unique identifier for an instrumented unit part + -- Unique identifier for an instrumented unit Part_Tags : constant array (Unit_Parts) of Character := (Unit_Spec => 'S', Unit_Body => 'B', Unit_Separate => 'U'); - function "=" (Left, Right : Compilation_Unit_Part) return Boolean; + function "=" (Left, Right : Compilation_Unit_Name) return Boolean; - function "<" (Left, Right : Compilation_Unit_Part) return Boolean; + function "<" (Left, Right : Compilation_Unit_Name) return Boolean; -- Compare the result of a call to Instrumented_Unit_Slug (which gives -- unique identifiers for each compilation unit name) for both operands. - function Image (CU_Name : Compilation_Unit_Part) return String; + function Image (CU_Name : Compilation_Unit_Name) return String; -- Return a string representation of CU_Name for use in diagnostics function Qualified_Name_Slug (Name : Ada_Qualified_Name) return String; @@ -105,18 +103,12 @@ package Instrument is -- not contain any '-'. function Instrumented_Unit_Slug - (Instrumented_Unit : Compilation_Unit_Part) return String; + (Instrumented_Unit : Compilation_Unit_Name) return String; -- Given a unit to instrument, return a unique identifier to describe it -- (the so called slug). -- -- One can use this slug to generate unique names for this unit. - function Filename_Slug (Fullname : String) return String; - -- Given a filename to instrument, return a unique identifier to describe - -- it (the so called slug). - -- - -- One can use this slug to generate unique names for this unit. - function To_Qualified_Name (Name : String) return Ada_Qualified_Name; -- Convert a String qualified name into our format @@ -133,29 +125,30 @@ package Instrument is function CU_Name_For_Unit (Unit : Ada_Qualified_Name; - Part : Unit_Parts) return Compilation_Unit_Part; + Part : Unit_Parts) return Compilation_Unit_Name; -- Return the compilation unit name for the Ada compilation unit -- corresponding to the unit name and the unit part parameters. function CU_Name_For_File - (Filename : US.Unbounded_String) return Compilation_Unit_Part; + (Filename : US.Unbounded_String; + Project_Name : US.Unbounded_String) return Compilation_Unit_Name; -- Return the compilation unit name for the C translation unit -- corresponding to the filename parameter. function To_Compilation_Unit_Name - (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Part; + (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Name; -- Return the compilation unit name corresponding to the unit in -- Source_File. function To_Filename (Project : Project_Type; - CU_Name : Compilation_Unit_Part; + CU_Name : Compilation_Unit_Name; Language : Any_Language) return String; -- Return the name of the file to contain the given compilation unit, -- according to Project's naming scheme. package Instrumented_Unit_To_CU_Maps is new Ada.Containers.Ordered_Maps - (Key_Type => Compilation_Unit_Part, + (Key_Type => Compilation_Unit_Name, Element_Type => CU_Id); Instrumented_Unit_CUs : Instrumented_Unit_To_CU_Maps.Map; @@ -172,62 +165,31 @@ package Instrument is -- Save the preprocessing command for each unit that supports it function Find_Instrumented_Unit - (CU_Name : Compilation_Unit_Part) return CU_Id; + (CU_Name : Compilation_Unit_Name) return CU_Id; -- Return the CU_Id corresponding to the given instrumented unit, or -- No_CU_Id if not found. - type Lang_Array is array (Src_Supported_Language range <>) - of Unbounded_String; - type C_Lang_Array_Vec is array (C_Family_Language) of String_Vectors.Vector; - - package String_Vectors_Maps is new Ada.Containers.Hashed_Maps - (Key_Type => Unbounded_String, - Element_Type => String_Vectors.Vector, - Equivalent_Keys => Ada.Strings.Unbounded."=", - Hash => Ada.Strings.Unbounded.Hash, - "=" => String_Vectors."="); - - type Prj_Desc is record - Prj_Name : Unbounded_String; - -- Name for the project - - Output_Dir : Unbounded_String; - -- Where the instrumented sources and coverage buffer units are - -- generated. - - Spec_Suffix, Body_Suffix : Lang_Array (Src_Supported_Language); - -- Suffixes for the body and the spec - - Dot_Replacement : Unbounded_String; - -- Character to use as identifier separator for file naming (used for - -- unit-based languages). - - Compiler_Driver : Lang_Array (C_Family_Language); - -- Compiler used to compile the sources - - Compiler_Options : C_Lang_Array_Vec; - -- For languages resorting to the compiler to preprocess sources, list - -- of compiler switches to pass to the preprocessor invocation. - - Compiler_Options_Unit : String_Vectors_Maps.Map; - -- Compiler switches applying to a specific unit - - Search_Paths : String_Vectors.Vector; - -- List of compiler switches to look up the project source directories - - end record; - -- This record stores the information that is required from the project - -- for instrumentation purposes. - - type Prj_Desc_Access is access Prj_Desc; - - function Load_From_Command_Line return Prj_Desc; - - function Unparse - (Desc : Prj_Desc; - Unit_Name : Unbounded_String; - Lang : Src_Supported_Language) return String_Vectors.Vector; - -- Return a list of command line switches holding all the project - -- information for the given Unit_Name of the language Lang. - + procedure Instrument_Units_Of_Interest + (Dump_Config : Any_Dump_Config; + Language_Version : Any_Language_Version; + Ignored_Source_Files : access GNAT.Regexp.Regexp; + Mains : String_Vectors.Vector); + -- Generate instrumented sources for the source files of all units of + -- interest. Also save mappings between coverage buffers and SCOs for each + -- library units to SID files (one per library unit). + -- + -- Depending on Dump_Config, instrument mains to schedule a call to the + -- dump procedure for the list of coverage buffers in all mains in the + -- project. + -- + -- Language_Version restricts what source constructs the instrumenter is + -- allowed to use. For instance, if Ada_2005 (or a lower version) is + -- passed, it will not be allowed to introduce expression functions, and + -- thus will emit a warning when it needed to do so. + -- + -- If Ignored_Source_File is non-null, ignore files whose names match the + -- accessed pattern. + -- + -- Mains is the list of source files that were listed on the command line: + -- if non-empty, they replace the mains specified in project files. end Instrument; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index dda567487..39e6d4fb1 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -16,11 +16,14 @@ -- of the license. -- ------------------------------------------------------------------------------ +with Ada.Containers.Hashed_Maps; with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Containers.Indefinite_Ordered_Sets; +with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; with Ada.Directories; use Ada.Directories; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Strings.Unbounded.Hash; with Ada.Tags; with Ada.Text_IO; use Ada.Text_IO; @@ -31,17 +34,16 @@ with GNATCOLL.Traces; with GNATCOLL.Projects.Aux; with GNATCOLL.VFS; use GNATCOLL.VFS; -with Command_Line; use Command_Line; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -with Inputs; use Inputs; with Instrument; use Instrument; +with Inputs; use Inputs; with Outputs; use Outputs; with Paths; use Paths; package body Project is - subtype Compilation_Unit is Files_Table.Compilation_Unit; - use type Compilation_Unit; + subtype Project_Unit is Files_Table.Project_Unit; + use type Project_Unit; Coverage_Package : aliased String := "coverage"; Coverage_Package_List : aliased String_List := @@ -137,6 +139,14 @@ package body Project is -- Whether we found at least one source file in the projects of interest -- that matches this unit. + Is_Stub : Boolean; + -- Whether this record describes a source file that is not a bona fide + -- unit of interest: a subunit (Ada) or a header file (C/C++). + -- + -- Such source files are not units of their own (in particular they + -- don't have their own LI file), but we still need them to appear in + -- unit lists, for reporting purposes. + Language : Some_Language; -- Language for this unit @@ -148,7 +158,7 @@ package body Project is end record; package Unit_Maps is new Ada.Containers.Indefinite_Ordered_Maps - (Key_Type => Compilation_Unit, + (Key_Type => Project_Unit, Element_Type => Unit_Info); procedure Add_Unit @@ -158,7 +168,7 @@ package body Project is Info : File_Info; Language : Some_Language); -- Add a Unit_Info entry to Units. The key for this new entry (which is a - -- Compilation_Unit) is computed using the Original_Name, and the + -- Project_Unit) is computed using the Original_Name, and the -- Info.Project_Name if the unit is of a file-based language. procedure Warn_Missing_Info (What_Info : String; Unit : in out Unit_Info); @@ -166,9 +176,7 @@ package body Project is -- Unit. Unit_Map : Unit_Maps.Map; - -- Map lower-case unit names to Unit_Info records for all units of - -- interest. This map contains header files (C/C++) but does not contain - -- separate (Ada) units. + -- Map lower-case unit names to Unit_Info records for all units of interest procedure Initialize (Target, Runtime, CGPR_File : GNAT.Strings.String_Access) @@ -226,38 +234,27 @@ package body Project is -- Note that this also returns source files for mains that are not units of -- interest. - ---------------------- - -- Owning_Unit_Name -- - ---------------------- + function Runtime_Has_File (Filename : Filesystem_String) return Boolean; + -- Return whether Filename can be found among the sources of the + -- configured Ada runtime. - function Owning_Unit_Name (Info : File_Info) return String is - begin - if Info.Unit_Part = Unit_Separate then - return Prj_Tree.Info (Prj_Tree.Other_File (Info.File)).Unit_Name; - else - return Info.Unit_Name; - end if; - end Owning_Unit_Name; - - ------------------------- - -- To_Compilation_Unit -- - ------------------------- + --------------------- + -- To_Project_Unit -- + --------------------- - function To_Compilation_Unit - (Info : File_Info) return Files_Table.Compilation_Unit + function To_Project_Unit + (Unit_Name : String; + Project : Project_Type; + Language : Some_Language) return Files_Table.Project_Unit is - Language : constant Some_Language := To_Language (Info.Language); - U : Compilation_Unit; + U : Project_Unit (Language_Kind (Language)); begin - U.Language := Language_Kind (Language); - case U.Language is - when File_Based_Language => - U.Unit_Name := +(+Info.File.Full_Name); - when Unit_Based_Language => - U.Unit_Name := +Owning_Unit_Name (Info); - end case; + U.Unit_Name := +Unit_Name; + if U.Language = File_Based_Language then + U.Project_Name := +Project.Name; + end if; return U; - end To_Compilation_Unit; + end To_Project_Unit; --------- -- "+" -- @@ -289,27 +286,30 @@ package body Project is Info : File_Info; Language : Some_Language) is + Unit_Part : constant Unit_Parts := Info.Unit_Part; + Is_Stub : constant Boolean := + (case Language is + when C_Family_Language => Unit_Part = Unit_Spec, + when Ada_Language => Unit_Part = Unit_Separate); + Orig_Name : constant Unbounded_String := +Fold_Filename_Casing (Original_Name); - Unit_Name : constant Compilation_Unit := To_Compilation_Unit (Info); + Unit_Name : constant Project_Unit := + To_Project_Unit (Original_Name, Info.Project, Language); Ignored_Inserted : Boolean; - Is_Header : Boolean := False; begin - -- Disable warnings for header files as they do not have a corresponding + -- Disable warnings for stub units as they do not have a corresponding -- library file. - if Language in C_Family_Language and then Info.Unit_Part = Unit_Spec then - Is_Header := True; - end if; - Units.Insert (Key => Unit_Name, New_Item => (Original_Name => Orig_Name, Present_In_Projects => False, + Is_Stub => Is_Stub, Language => Language, - LI_Seen => Is_Header, - Warned_About_Missing_Info => Is_Header), + LI_Seen => Is_Stub, + Warned_About_Missing_Info => Is_Stub), Position => Cur, Inserted => Ignored_Inserted); end Add_Unit; @@ -467,15 +467,51 @@ package body Project is --------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Files_Table.Compilation_Unit)) + (Callback : access procedure (Name : Files_Table.Project_Unit; + Is_Stub : Boolean)) is use Unit_Maps; begin for Cur in Unit_Map.Iterate loop - Callback (Key (Cur)); + declare + Info : Unit_Info renames Reference (Unit_Map, Cur); + begin + Callback (Key (Cur), Info.Is_Stub); + end; end loop; end Enumerate_Units_Of_Interest; + ------------------------- + -- Is_Unit_Of_Interest -- + ------------------------- + + function Is_Unit_Of_Interest + (Project : Project_Type; + Unit_Name : String; + Language : Some_Language) return Boolean + is + U : constant Project_Unit := + To_Project_Unit (Unit_Name, Project, Language); + begin + return Unit_Map.Contains (U); + end Is_Unit_Of_Interest; + + ------------------------- + -- Is_Unit_Of_Interest -- + ------------------------- + + function Is_Unit_Of_Interest (Full_Name : String) return Boolean is + FI : constant File_Info := + Prj_Tree.Info (Create (+Full_Name)); + Unit_Name : constant String := + (case Language_Kind (To_Language (FI.Language)) is + when Unit_Based_Language => FI.Unit_Name, + when File_Based_Language => +FI.File.Base_Name); + begin + return Is_Unit_Of_Interest + (FI.Project, Unit_Name, To_Language (FI.Language)); + end Is_Unit_Of_Interest; + ------------------------- -- Enumerate_SCO_Files -- ------------------------- @@ -503,8 +539,23 @@ package body Project is declare use Unit_Maps; + LI_Source_Unit : constant String := LI.Source.Unit_Name; + LI_Source_File : constant String := +LI.Source.File.Base_Name; + + U : constant String := + (if LI_Source_Unit'Length > 0 + then LI_Source_Unit + else LI_Source_File); + -- For unit-based languages (Ada), retrieve unit name from + -- SCOs file. For file-based languages (C), fall back to + -- translation unit source file name instead. + Cur : constant Cursor := - Unit_Map.Find (To_Compilation_Unit (LI.Source.all)); + Unit_Map.Find + (To_Project_Unit + (U, + Project_Type (LI.LI_Project.all), + To_Language (LI.Source.Language))); begin if Has_Element (Cur) then Callback.all (+LI.Library_File.Full_Name); @@ -548,30 +599,17 @@ package body Project is -- Process_Source_File -- ------------------------- - procedure Process_Source_File (Info : File_Info; Unit_Name : String) - is - pragma Unreferenced (Unit_Name); - Info_Lang : constant Some_Language := To_Language (Info.Language); + procedure Process_Source_File (Info : File_Info; Unit_Name : String) is begin - if Language = All_Languages or else Language = Info_Lang then - - -- If this is a header, consider it a unit of interest. For now, - -- they can only be ignored through the --ignore-source-files - -- switch. - - if (Language_Kind (Info_Lang) = File_Based_Language - and then Info.Unit_Part = Unit_Spec) - - -- Otherwise, check if the unit is in the units of interest - -- map - - or else - (Unit_Map.Contains (To_Compilation_Unit (Info)) - and then (Info.Unit_Part /= Unit_Separate - or else Include_Stubs)) - then - Callback (Info.Project, Info); - end if; + if (Language = All_Languages + or else + Language = To_Language (Info.Language)) + and then + (Include_Stubs + or else Is_Unit_Of_Interest + (Info.Project, Unit_Name, To_Language (Info.Language))) + then + Callback (Info.Project, Info); end if; end Process_Source_File; @@ -613,6 +651,51 @@ package body Project is end; end Find_Source_File; + ---------------------- + -- Runtime_Has_File -- + ---------------------- + + function Runtime_Has_File (Filename : Filesystem_String) return Boolean is + Result_File : Virtual_File; + -- Virtual_File for Ada.Finalization. Only search predefined sources. + Ambiguous : Boolean; + -- Required in the call for GNATCOLL.Projects.Create + begin + GNATCOLL.Projects.Create + (Self => Prj_Tree.all, + Name => Filename, + Use_Object_Path => False, + Ambiguous => Ambiguous, + File => Result_File, + Predefined_Only => True); + + -- We don't expect there to be multiple homonyms for the runtime files + + pragma Assert (not Ambiguous); + return Result_File /= No_File; + end Runtime_Has_File; + + ------------------------------ + -- Runtime_Has_Finalization -- + ------------------------------ + + function Runtime_Supports_Finalization return Boolean is + (Runtime_Has_File ("a-finali.ads")); + + --------------------------------------- + -- Runtime_Supports_Task_Termination -- + --------------------------------------- + + function Runtime_Supports_Task_Termination return Boolean is + begin + -- We need both Ada.Task_Identification (a-taside.ads) and + -- Ada.Task_Termination (a-taster.ads) to be able to use task + -- termination. + + return Runtime_Has_File ("a-taster.ads") + and then Runtime_Has_File ("a-taside.ads"); + end Runtime_Supports_Task_Termination; + ---------------- -- Initialize -- ---------------- @@ -911,26 +994,20 @@ package body Project is procedure Process_Source_File (Info : File_Info; Unit_Name : String) is - Cur : Unit_Maps.Cursor; - Actual_Unit_Name : constant String := - (if Info.Unit_Part = Unit_Separate - then Owning_Unit_Name (Info) - else Unit_Name); + Cur : Unit_Maps.Cursor; begin -- Never try to perform coverage on our coverage runtime -- library (in one of the gnatcov_rts*.gpr projects) or on -- our coverage buffer units (in user projects). - if Strings.Has_Prefix (Actual_Unit_Name, "gnatcov_rts.") - or else Strings.Has_Prefix (Actual_Unit_Name, "gcvrt") - then + if Strings.Has_Prefix (Unit_Name, "gnatcov_rts.") then return; end if; if not Units_Specified or else (Has_Matcher and then GNAT.Regexp.Match - (To_Lower (Actual_Unit_Name), + (To_Lower (Unit_Name), Units_Specified_Matcher)) then Add_Unit @@ -947,9 +1024,7 @@ package body Project is -- Units attributes only apply to the project itself. Iterate_Source_Files - (Project, Process_Source_File'Access, - Recursive => False, - Include_Stubs => True); + (Project, Process_Source_File'Access, Recursive => False); Inc_Units_Defined := True; end; end if; @@ -960,7 +1035,7 @@ package body Project is for Cur in Inc_Units.Iterate loop declare use Unit_Maps; - K : constant Compilation_Unit := Key (Cur); + K : constant Project_Unit := Key (Cur); begin if not Exc_Units.Contains (K) then declare @@ -1014,8 +1089,7 @@ package body Project is Units_Present : String_Vectors.Vector; -- All units that were included - Patterns_Not_Covered : String_Sets.Set := - To_String_Set (Unit_Patterns); + Patterns_Not_Covered : String_Vectors.Vector; -- Patterns that do not match any of the present units procedure Add_To_Unit_Presents (C : Unit_Maps.Cursor); @@ -1024,16 +1098,9 @@ package body Project is -- Add_To_Unit_Presents -- -------------------------- - procedure Add_To_Unit_Presents (C : Unit_Maps.Cursor) - is - P_Unit : constant Compilation_Unit := Unit_Maps.Key (C); - Unit_Name : constant Unbounded_String := - (case P_Unit.Language is - when File_Based_Language => - +Ada.Directories.Simple_Name (+P_Unit.Unit_Name), - when Unit_Based_Language => P_Unit.Unit_Name); + procedure Add_To_Unit_Presents (C : Unit_Maps.Cursor) is begin - Units_Present.Append (Unit_Name); + Units_Present.Append (Unit_Maps.Key (C).Unit_Name); end Add_To_Unit_Presents; begin @@ -1144,15 +1211,39 @@ package body Project is Units : out Unit_Maps.Map; Defined : out Boolean) is + package FI_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, Element_Type => File_Info); + + use type FI_Vectors.Vector; + + package Unit_Name_FI_Vector_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Unbounded_String, + Element_Type => FI_Vectors.Vector); + + Units_Present : String_Vectors.Vector; + -- List of all units in Prj + + Unit_Present_To_FI : Unit_Name_FI_Vector_Maps.Map; + -- Map a unit name to a file information vector. A unit name can be + -- be mapped to multiple file info if there are homonym source files. + + package Unit_Language_Maps is new Ada.Containers.Hashed_Maps + (Key_Type => Unbounded_String, + Element_Type => Some_Language, + Equivalent_Keys => "=", + Hash => Hash); + Unit_Languages : Unit_Language_Maps.Map; + -- Language for each unit in Units_Present + Unit_Patterns : String_Vectors.Vector; Attr_For_Pattern : String_Maps.Map; -- Patterns identifying unit names and project attribute from which we -- got the pattern. We use Attr_For_Pattern for reporting purposes. - Patterns_Not_Covered : String_Sets.Set; + Patterns_Not_Covered : String_Vectors.Vector; -- Patterns that do not match any of the present unit - Cur : Unit_Maps.Cursor; + Ignored_Cur : Unit_Maps.Cursor; procedure Add_Pattern (Attr, Item : String); -- Add Item to Unit_Patterns. Also save from which project attribute @@ -1176,33 +1267,18 @@ package body Project is ------------------------- procedure Process_Source_File (Info : File_Info; Unit_Name : String) is - use type Ada.Containers.Count_Type; - use String_Vectors; - Actual_Unit_Name : Vector := - To_Vector - (+(if Info.Unit_Part = Unit_Separate - then Owning_Unit_Name (Info) - else Unit_Name), - 1); - begin - Match_Pattern_List - (Patterns_List => Unit_Patterns, - Strings_List => Actual_Unit_Name, - Patterns_Not_Covered => Patterns_Not_Covered); - -- Add it only if it matches one of the patterns + use Unit_Name_FI_Vector_Maps; - if not Actual_Unit_Name.Is_Empty then - declare - Lang : constant Some_Language := To_Language (Info.Language); - begin - Add_Unit - (Units, - Cur, - Unit_Name, - Info, - Lang); - end; + Key : constant Unbounded_String := +Unit_Name; + Cur : constant Cursor := Unit_Present_To_FI.Find (Key); + begin + Units_Present.Append (Key); + Unit_Languages.Include (Key, To_Language (Info.Language)); + if Has_Element (Cur) then + Unit_Present_To_FI.Reference (Cur).Append (Info); + else + Unit_Present_To_FI.Insert (Key, FI_Vectors.To_Vector (Info, 1)); end if; end Process_Source_File; @@ -1215,7 +1291,6 @@ package body Project is List_From_Project (Prj, List_Attr, List_File_Attr, Add_Pattern'Access, Defined); - Patterns_Not_Covered := To_String_Set (Unit_Patterns); if not Defined then return; @@ -1226,13 +1301,28 @@ package body Project is -- source file name. Iterate_Source_Files - (Prj, Process_Source_File'Access, - Recursive => False, Include_Stubs => True); + (Prj, Process_Source_File'Access, Recursive => False); + + Match_Pattern_List (Patterns_List => Unit_Patterns, + Strings_List => Units_Present, + Patterns_Not_Covered => Patterns_Not_Covered); for Pattern of Patterns_Not_Covered loop Warn ("no unit " & (+Pattern) & " in project " & Prj.Name & " (" & (+Attr_For_Pattern.Element (Pattern)) & " attribute)"); end loop; + + for Unit_Name of Units_Present loop + for Info of Unit_Present_To_FI (Unit_Name) loop + Add_Unit + (Units, + Ignored_Cur, + +Unit_Name, + Info, + Unit_Languages.Element (Unit_Name)); + end loop; + end loop; + end Units_From_Project; ----------------------- @@ -1579,7 +1669,7 @@ package body Project is procedure Finalize is begin - if Prj_Tree /= null and then not Args.Bool_Args (Opt_Save_Temps) then + if Prj_Tree /= null then GNATCOLL.Projects.Aux.Delete_All_Temp_Files (Prj_Tree.Root_Project); end if; end Finalize; @@ -1593,46 +1683,4 @@ package body Project is return Prj_Tree; end Project; - ------------------- - -- Source_Suffix -- - ------------------- - - function Source_Suffix - (Lang : Src_Supported_Language; - Part : GNATCOLL.Projects.Unit_Parts; - Project : GNATCOLL.Projects.Project_Type) return String - is - Attr : constant Attribute_Pkg_String := - Build - (Package_Name => "Naming", - Attribute_Name => - (case Part is - when Unit_Body => "Body_Suffix", - when Unit_Spec => "Spec_Suffix", - when Unit_Separate => raise Program_Error)); - begin - case Part is - when Unit_Body => - return Project.Attribute_Value - (Attribute => Attr, - Index => Image (Lang), - Default => (case Lang is - when Ada_Language => ".adb", - when C_Language => ".c", - when CPP_Language => ".cc")); - - when Unit_Spec => - return Project.Attribute_Value - (Attribute => Attr, - Index => Image (Lang), - Default => (case Lang is - when Ada_Language => ".ads", - when C_Language => ".h", - when CPP_Language => ".hh")); - - when Unit_Separate => - return (raise Program_Error); - end case; - end Source_Suffix; - end Project; diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 981ab4c6a..fb8b60812 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -114,22 +114,33 @@ package Project is -- path of its main executable (including its suffix, for instance ".exe"). -- Otherwise, return an empty string. - function Owning_Unit_Name (Info : File_Info) return String - with Pre => Is_Project_Loaded; - -- Return the owning unit name meaning the unit name if this is a body / - -- specification, and the top parent unit name if this is a separate. - - function To_Compilation_Unit - (Info : File_Info) return Files_Table.Compilation_Unit; - -- Return the Compilation_Unit for Info + function To_Project_Unit + (Unit_Name : String; + Project : Project_Type; + Language : Some_Language) return Files_Table.Project_Unit; + -- Return the Project_Unit value that designates the same unit as + -- Unit_Name/Project/Language. -------------------------------------- -- Accessors for project properties -- -------------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Files_Table.Compilation_Unit)); - -- Call Callback once for every unit of interest. Name is the unit name + (Callback : access procedure (Name : Files_Table.Project_Unit; + Is_Stub : Boolean)); + -- Call Callback once for every unit of interest. Name is the unit name, + -- and Is_Stub corresponds to the Unit_Info.Is_Stub field (see + -- project.adb). + + function Is_Unit_Of_Interest + (Project : Project_Type; + Unit_Name : String; + Language : Some_Language) return Boolean; + -- Return whether the unit Unit_Name that belongs to the project Project + -- is a unit of interest. + + function Is_Unit_Of_Interest (Full_Name : String) return Boolean; + -- Same as above, but given a full name procedure Enumerate_SCOs_Files (Callback : access procedure (Lib_Name : String); @@ -181,6 +192,15 @@ package Project is -- -- If no project is loaded, just return null. + function Runtime_Supports_Finalization return Boolean with + Pre => Is_Project_Loaded; + -- Return whether the configured runtime includes the Ada.Finalization unit + + function Runtime_Supports_Task_Termination return Boolean with + Pre => Is_Project_Loaded; + -- Return whether the configured runtime has necessary units to implement + -- the ravenscar-task-termination dump trigger. + function Switches (Op : String) return String_List_Access with Pre => Is_Project_Loaded; -- Return a list of gnatcov switches defined by the root project. Caller @@ -234,10 +254,4 @@ package Project is -- Unless Include_Extended is True, only process ultimate extending -- projects. - function Source_Suffix - (Lang : Src_Supported_Language; - Part : GNATCOLL.Projects.Unit_Parts; - Project : GNATCOLL.Projects.Project_Type) return String; - -- Return the filename suffix corresponding for Part files and Lang - end Project; diff --git a/tools/gnatcov/rts/gcvrt.ads b/tools/gnatcov/rts/gcvrt.ads deleted file mode 100644 index 44de3e1a7..000000000 --- a/tools/gnatcov/rts/gcvrt.ads +++ /dev/null @@ -1,23 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2023, 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. -- ------------------------------------------------------------------------------- - --- Namespace for units generated for instrumentation purposes - -package GCVRT is - pragma Pure; -end GCVRT; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index 158e8cdec..0a95db446 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -78,6 +78,7 @@ package GNATcov_RTS.Buffers is Language : Any_Language_Kind; Unit_Part : Any_Unit_Part; Unit_Name : GNATcov_RTS_String; + Project_Name : GNATcov_RTS_String; Bit_Maps_Fingerprint : Fingerprint_Type; Statement, Decision, MCDC : System.Address; Statement_Last_Bit, Decision_Last_Bit, diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index e1ef95be9..21cd45eac 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -93,6 +93,10 @@ extern "C" enum gnatcov_rts_unit_part unit_part; struct gnatcov_rts_string unit_name; + /* Project name for this compilation unit. This is only initialized for + file-based languages (otherwise, it is an empty string). */ + struct gnatcov_rts_string project_name; + /* Hash of buffer bit mappings for this unit, as gnatcov computes it (see SC_Obligations). Used as a fast way to check that gnatcov will be able to interpret buffer bits from a source traces using buffer bit mappings diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index fe2d272ba..b2a96c101 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -118,13 +118,14 @@ write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, { struct trace_entry_header header; header.unit_name_length = (uint32_t) buffers->unit_name.length; + header.project_name_length = (uint32_t) buffers->project_name.length; header.statement_bit_count = (uint32_t) buffers->statement_last_bit + 1; header.decision_bit_count = (uint32_t) buffers->decision_last_bit + 1; header.mcdc_bit_count = (uint32_t) buffers->mcdc_last_bit + 1; header.language_kind = (uint8_t) buffers->language_kind; header.unit_part = (uint8_t) buffers->unit_part; header.bit_buffer_encoding = GNATCOV_RTS_LSB_FIRST_BYTES; - memset (header.padding, 0, 5); + memset (header.padding, 0, 1); memcpy (&header.fingerprint, buffers->fingerprint, FINGERPRINT_SIZE); memcpy (&header.bit_maps_fingerprint, buffers->bit_maps_fingerprint, FINGERPRINT_SIZE); @@ -132,6 +133,9 @@ write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, write_bytes (output, (char *) &header, sizeof (header)); write_bytes (output, buffers->unit_name.str, buffers->unit_name.length); write_padding (write_bytes, output, buffers->unit_name.length); + write_bytes (output, buffers->project_name.str, + buffers->project_name.length); + write_padding (write_bytes, output, buffers->project_name.length); write_buffer (write_bytes, output, buffers->statement, buffers->statement_last_bit + 1); write_buffer (write_bytes, output, buffers->decision, diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces.h b/tools/gnatcov/rts/gnatcov_rts_c-traces.h index 33664a30d..6e3288395 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces.h @@ -115,6 +115,11 @@ extern "C" describes. */ uint32_t unit_name_length; + /* For file-based languages, length of the project name this file belongs + to. For unit-based languages, the unit name is unique so this piece of + information is not needed (and thus will be 0). */ + uint32_t project_name_length; + /* Number of bits in the statement, decision and MC/DC coverage buffers. */ uint32_t statement_bit_count; uint32_t decision_bit_count; @@ -143,7 +148,7 @@ extern "C" /* Padding used only to make the size of this trace entry header a multiple of 8 bytes. Must be zero. */ - uint8_t padding[5]; + uint8_t padding[1]; }; #ifdef __cplusplus diff --git a/tools/gnatcov/strings.adb b/tools/gnatcov/strings.adb index b7c343fc2..3ee5ea3b0 100644 --- a/tools/gnatcov/strings.adb +++ b/tools/gnatcov/strings.adb @@ -92,20 +92,6 @@ package body Strings is and then S (S'Last - Length + 1 .. S'Last) = Suffix; end Has_Suffix; - -------------------- - -- To_String_Sets -- - -------------------- - - function To_String_Set (V : String_Vectors.Vector) return String_Sets.Set - is - Result : String_Sets.Set; - begin - for Elem of V loop - Result.Include (Elem); - end loop; - return Result; - end To_String_Set; - -------------------- -- Vector_To_List -- -------------------- @@ -177,7 +163,7 @@ package body Strings is procedure Match_Pattern_List (Patterns_List : String_Vectors.Vector; Strings_List : in out String_Vectors.Vector; - Patterns_Not_Covered : in out String_Sets.Set) + Patterns_Not_Covered : out String_Vectors.Vector) is use Ada.Characters.Handling; use Ada.Strings.Unbounded; @@ -187,6 +173,10 @@ package body Strings is Regexps : array (0 .. Pattern_Length - 1) of GNAT.Regexp.Regexp; -- List of regexps, one for each pattern in Patterns_List + Regexps_Covered : array (0 .. Pattern_Length - 1) of Boolean := + (others => False); + -- Record which Regexp of Regexps matched at least once + Matching_Strings : String_Vectors.Vector; -- Result holder for Strings_List @@ -212,18 +202,9 @@ package body Strings is end if; -- A unit matching this pattern was found; the pattern is - -- covered. Remove it from Patterns_Not_Covered. - - declare - Pattern : constant Unbounded_String := - Patterns_List.Element (I); - Cur : String_Sets.Cursor := - Patterns_Not_Covered.Find (Pattern); - begin - if String_Sets.Has_Element (Cur) then - Patterns_Not_Covered.Delete (Cur); - end if; - end; + -- covered. + + Regexps_Covered (I) := True; -- Continue the search in case other patterns match Str so that -- we can mark them as covered as well. @@ -247,6 +228,12 @@ package body Strings is Strings_List := Matching_Strings; + for I in Regexps_Covered'Range loop + if not Regexps_Covered (I) then + Patterns_Not_Covered.Append (Patterns_List.Element (I)); + end if; + end loop; + end Match_Pattern_List; end Strings; diff --git a/tools/gnatcov/strings.ads b/tools/gnatcov/strings.ads index a1c5df035..8d58d1e6f 100644 --- a/tools/gnatcov/strings.ads +++ b/tools/gnatcov/strings.ads @@ -77,11 +77,9 @@ package Strings is "=" => Ada.Strings.Unbounded.Equal_Case_Insensitive); -- Case insensitive string set - function To_String_Set (V : String_Vectors.Vector) return String_Sets.Set; - -- Convert the given strings vector to a strings set - function Vector_To_List - (V : String_Vectors.Vector) return String_List_Access; + (V : String_Vectors.Vector) + return String_List_Access; -- The stream type below allows arbitrary objects to be streamed -- from/to an unbounded string, which is used as a buffer of bytes. @@ -89,11 +87,11 @@ package Strings is procedure Match_Pattern_List (Patterns_List : String_Vectors.Vector; Strings_List : in out String_Vectors.Vector; - Patterns_Not_Covered : in out String_Sets.Set); + Patterns_Not_Covered : out String_Vectors.Vector); -- Try matching each pattern of Patterns_List against each item of -- Strings_List (case-insensitively). Every item not matched is removed - -- from Strings_List. Also, each pattern that matched at least once is - -- removed from Patterns_Not_Covered. + -- from Strings_List. Also, each pattern that did not match at least once + -- is returned in Patterns_Not_Covered. type Unbounded_String_Stream (S : access Ada.Strings.Unbounded.Unbounded_String) diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 25edace20..33c2b5901 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -361,24 +361,21 @@ package body Subprocesses is Output_File : Mapped_File; Region : Mapped_Region; Str : Str_Access; - Str_Last : Natural; + Str_Last : Natural := Last (Region); begin Output_File := Open_Read (+Self.Process_Infos (Id).Output_File); Region := Read (Output_File); Str := Data (Region); - Str_Last := Last (Region); -- The finalization of Ada.Text_IO always emits a newline after a -- call to Put. To avoid redundant line breaks in this situation, -- do not pass that newline to Put and call New_Line instead. - if Str_Last > 0 then - if Str (Str_Last) = ASCII.LF then - Str_Last := Str_Last - 1; - end if; - Put (Str (1 .. Str_Last)); - New_Line; + if Str_Last > 0 and then Str (Str_Last) = ASCII.LF then + Str_Last := Str_Last - 1; end if; + Put (Str (1 .. Str_Last)); + New_Line; Free (Region); Close (Output_File); @@ -433,31 +430,22 @@ package body Subprocesses is Pool.Process_Infos (Id).Output_File := +Output_File; Pool.Process_Infos (Id).Origin_Command_Name := +Origin_Command_Name; Pool.Process_Infos (Id).Command := +Command; - if Output_File = "" then - - -- Redirect the output to a temporary file to avoid mangling - -- on the standard output. The dump of the output is done in - -- Wait_And_Finalize, through a later call to Run_Command, or - -- through the finalization of the process pool. - - Pool.Process_Infos (Id).Output_File := - +(Pool.Output_Dir.Directory_Name / "job-" - & Strings.Img (Id) & ".txt"); - Pool.Process_Infos (Id).Output_To_Stdout := True; - else - Pool.Process_Infos (Id).Output_To_Stdout := False; - end if; Pool.Handles (Id) := Run_Command (Command, Arguments, Origin_Command_Name, Environment, - +Pool.Process_Infos (Id).Output_File, - -- TODO???: there will be mangling on the stderr if stdout was - -- redirected to an output file. + -- Redirect the output to a temporary file to avoid mangling on the + -- standard output. The dump of the output is done in + -- Wait_And_Finalize, through a later call to Run_Command, or + -- through the finalization of the process pool. + (if Output_File = "" + then Pool.Output_Dir.Directory_Name / "job-" + & Strings.Img (Id) & ".txt" + else Output_File), Err_To_Out => Output_File = "", Out_To_Null => Out_To_Null, In_To_Null => In_To_Null, diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 6d6d5b325..6a81218ff 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -186,47 +186,6 @@ package body Switches is end return; end Load_Dump_Config; - -------------------- - -- Unparse_Config -- - -------------------- - - function Unparse_Config - (Dump_Config : Any_Dump_Config) return String_Vectors.Vector - is - use Ada.Strings.Unbounded; - Result : String_Vectors.Vector; - begin - Result.Append (+"--dump-trigger"); - case Dump_Config.Trigger is - when Manual => - Result.Append (+"manual"); - when At_Exit => - Result.Append (+"atexit"); - when Ravenscar_Task_Termination => - Result.Append (+"ravenscar-task-termination"); - when Main_End => - Result.Append (+"main-end"); - end case; - case Dump_Config.Channel is - when Binary_File => - Result.Append (+"--dump-channel=bin-file"); - if Dump_Config.Filename_Simple then - Result.Append (+"--dump-filename-simple"); - end if; - if Length (Dump_Config.Filename_Env_Var) /= 0 then - Result.Append - ("--dump-filename-env-var=" & Dump_Config.Filename_Env_Var); - end if; - if Length (Dump_Config.Filename_Prefix) /= 0 then - Result.Append - (+"--dump-filename-prefix=" & Dump_Config.Filename_Prefix); - end if; - when Base64_Standard_Output => - Result.Append (+"--dump-channel=base64-stdout"); - end case; - return Result; - end Unparse_Config; - ----------------- -- To_Language -- ----------------- diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 67817c1f8..2c259b2af 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -119,10 +119,6 @@ package Switches is SPARK_Compat : Boolean := False; -- When True, tune the instrumenter for maximum SPARK compatibility - Files_Of_Interest : String_Sets.Set; - -- Lower abstraction for files of interest, when the --files switch is - -- used. - type Separated_Source_Coverage_Type is (None, Routines, Instances); Separated_Source_Coverage : Separated_Source_Coverage_Type := None; @@ -162,11 +158,6 @@ package Switches is -- List of languages for which source files should be instrumented. -- Initialized during command line arguments parsing. - Builtin_Support : array (Src_Supported_Language) of Boolean := - (others => True); - -- Whether gnatcov supports the given language. Used when building gnatcov - -- without C instrumentation support. - ------------------------ -- Target information -- ------------------------ @@ -282,11 +273,6 @@ package Switches is -- Create the Any_Dump_Config value corresponding to Default_Dump_Config -- and the given --dump-* arguments for source trace dumping. - function Unparse_Config - (Dump_Config : Any_Dump_Config) return String_Vectors.Vector; - -- Return a suitable set of gnatcov command line switches that represent - -- the given dump config. - function Common_Switches (Cmd : Command_Line.Command_Type) return String_Vectors.Vector; -- Return the unparsed command line arguments supported by the given diff --git a/tools/gnatcov/traces_source.ads b/tools/gnatcov/traces_source.ads index ad7fb5fd8..230867cd4 100644 --- a/tools/gnatcov/traces_source.ads +++ b/tools/gnatcov/traces_source.ads @@ -225,6 +225,11 @@ package Traces_Source is -- Length of the unit name / filename for the unit this trace entry -- describes. + Project_Name_Length : Unsigned_32; + -- For file-based languages, length of the project name this file + -- belongs to. For unit-based languages, the unit name is unique so this + -- piece of information is not needed (thus will be 0). + Statement_Bit_Count : Any_Bit_Count; Decision_Bit_Count : Any_Bit_Count; MCDC_Bit_Count : Any_Bit_Count; @@ -251,22 +256,23 @@ package Traces_Source is -- be able to interpret buffer bits from a source traces using buffer -- bit mappings from SID files. - Padding : String (1 .. 5); + Padding : String (1 .. 1); -- Padding used only to make the size of this trace entry header a -- multiple of 8 bytes. Must be zero. end record; for Trace_Entry_Header use record Unit_Name_Length at 0 range 0 .. 31; - Statement_Bit_Count at 4 range 0 .. 31; - Decision_Bit_Count at 8 range 0 .. 31; - MCDC_Bit_Count at 12 range 0 .. 31; - Language_Kind at 16 range 0 .. 7; - Unit_Part at 17 range 0 .. 7; - Bit_Buffer_Encoding at 18 range 0 .. 7; - Fingerprint at 19 range 0 .. 20 * 8 - 1; - Bit_Maps_Fingerprint at 39 range 0 .. 20 * 8 - 1; - Padding at 59 range 0 .. 5 * 8 - 1; + Project_Name_Length at 4 range 0 .. 31; + Statement_Bit_Count at 8 range 0 .. 31; + Decision_Bit_Count at 12 range 0 .. 31; + MCDC_Bit_Count at 16 range 0 .. 31; + Language_Kind at 20 range 0 .. 7; + Unit_Part at 21 range 0 .. 7; + Bit_Buffer_Encoding at 22 range 0 .. 7; + Fingerprint at 23 range 0 .. 20 * 8 - 1; + Bit_Maps_Fingerprint at 43 range 0 .. 20 * 8 - 1; + Padding at 63 range 0 .. 7; end record; for Trace_Entry_Header'Size use 64 * 8; From 48d397f97313c937edcc849de85e12f03797b3d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 23 Jun 2023 15:53:03 +0200 Subject: [PATCH 0332/1483] Instrument Ada: Convert elsif expressions to Standard.Boolean When instrumenting elsif expressions, we insert the statement witness call as a function call in an OR ELSE expression with the original expression. This may create a type mismatch as the Witness function returns a Standard.Boolean, whereas the original expression may be a derived type from Boolean. This change fixes this by always converting the original expression to Standard.Boolean. --- .../Robustness/ElsifDerivedBool/src/pkg.adb | 15 ++++++++++++ .../Robustness/ElsifDerivedBool/src/pkg.ads | 7 ++++++ .../ElsifDerivedBool/src/test_else.adb | 16 +++++++++++++ .../ElsifDerivedBool/src/test_elsif.adb | 16 +++++++++++++ .../ElsifDerivedBool/src/test_if.adb | 16 +++++++++++++ .../ElsifDerivedBool/src/test_no.adb | 13 ++++++++++ .../stmt/Robustness/ElsifDerivedBool/tc.rst | 4 ++++ .../stmt/Robustness/ElsifDerivedBool/test.py | 12 ++++++++++ tools/gnatcov/instrument-ada_unit.adb | 24 +++++++++++++++---- 9 files changed, 119 insertions(+), 4 deletions(-) create mode 100644 testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.adb create mode 100644 testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.ads create mode 100644 testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_else.adb create mode 100644 testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_elsif.adb create mode 100644 testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_if.adb create mode 100644 testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_no.adb create mode 100644 testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/tc.rst create mode 100644 testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/test.py diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.adb b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.adb new file mode 100644 index 000000000..784ff7331 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.adb @@ -0,0 +1,15 @@ +package body Pkg is + + function Or_Else (L, R : New_Bool) return Boolean is + use type New_Bool; + begin + if L then -- # if-stmt + return True; -- # ret-if + elsif R then -- # elsif-stmt + return True; -- # ret-elsif + else + return False; -- # ret-else + end if; + end Or_Else; + +end Pkg; diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.ads b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.ads new file mode 100644 index 000000000..ee3026e42 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + type New_Bool is new Boolean; + + function Or_Else (L, R : New_Bool) return Boolean; + +end Pkg; diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_else.adb b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_else.adb new file mode 100644 index 000000000..1971dc325 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_else.adb @@ -0,0 +1,16 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Else is +begin + Support.Assert (not Or_Else (False, False)); +end Test_Else; + +--# pkg.adb +-- +-- /if-stmt/ l+ ## 0 +-- /ret-if/ l- ## s- +-- /elsif-stmt/ l+ ## 0 +-- /ret-elsif/ l- ## s- +-- /ret-else/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_elsif.adb b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_elsif.adb new file mode 100644 index 000000000..87ea64162 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_elsif.adb @@ -0,0 +1,16 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Elsif is +begin + Support.Assert (Or_Else (False, True)); +end Test_Elsif; + +--# pkg.adb +-- +-- /if-stmt/ l+ ## 0 +-- /ret-if/ l- ## s- +-- /elsif-stmt/ l+ ## 0 +-- /ret-elsif/ l+ ## 0 +-- /ret-else/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_if.adb b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_if.adb new file mode 100644 index 000000000..1caac11f8 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_if.adb @@ -0,0 +1,16 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_If is +begin + Support.Assert (Or_Else (True, False)); +end Test_If; + +--# pkg.adb +-- +-- /if-stmt/ l+ ## 0 +-- /ret-if/ l+ ## 0 +-- /elsif-stmt/ l- ## s- +-- /ret-elsif/ l- ## s- +-- /ret-else/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_no.adb b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_no.adb new file mode 100644 index 000000000..c606e05b9 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/src/test_no.adb @@ -0,0 +1,13 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_No is +begin + null; +end Test_No; + +--# pkg.adb +-- +-- /.*-stmt/ l- ## s- +-- /ret-.*/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/tc.rst b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/tc.rst new file mode 100644 index 000000000..7b3c56a0c --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/tc.rst @@ -0,0 +1,4 @@ +**Exercise SC on ELSIF stmt with derived boolean types** + +Check that statement coverage of elsif statements for which +the decision is of a type derived from boolean works as intended. diff --git a/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/test.py b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/test.py new file mode 100644 index 000000000..74a224f6c --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/ElsifDerivedBool/test.py @@ -0,0 +1,12 @@ +""" +Check that statement coverage of ELSIF statements works as intended +when the decision is of a type derived from Standard.Boolean +(and not a subtype of Standard.Boolean). Gnatcov used to produce +illegal code in this case. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 39516a36d..ea66d01b5 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3338,11 +3338,27 @@ package body Instrument.Ada_Unit is -- Now reattach old condition in the new OR ELSE node. We -- will wrap it in parens to preserve the semantics of -- the condition. - - Old_Cond := Create_Regular_Node + -- + -- The two operands of the OR ELSE may not have the same + -- type (Standard.Boolean for the Witness return type). + -- We could convert the result of the witness call to the + -- actual type of the expression, but this requires + -- "withing" the package in which the derived boolean + -- type is defined in case it is not visible. Instead, as + -- this is a top-level boolean expression, we can simply + -- convert the original expression to Standard.Boolean. + + Old_Cond := Create_Call_Expr (RC, - Ada_Paren_Expr, - Children => (1 => Old_Cond)); + F_Name => Create_Identifier + (RC, To_Text (To_Ada (Sys_Prefix) & ".Std.Boolean")), + F_Suffix => Create_Regular_Node + (RC, + Ada_Assoc_List, + (1 => Create_Param_Assoc + (RC, + F_Designator => No_Node_Rewriting_Handle, + F_R_Expr => Old_Cond)))); Set_Child (New_Cond, 3, Old_Cond); end; From db9b67c039a0e27d4cd1b3e6a273caf9e5540a71 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 3 Jul 2023 17:14:13 +0200 Subject: [PATCH 0333/1483] Ignore subsequent files in case of homonyms in a project The implementation of the Ada unit provider used to crash when there are duplicated sources (which is allowed) in the runtime directories. Make sure we are not inserting any already-inserted file. --- tools/gnatcov/instrument-ada_unit_provider.adb | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit_provider.adb b/tools/gnatcov/instrument-ada_unit_provider.adb index cf0ad0b97..110cf326f 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.adb +++ b/tools/gnatcov/instrument-ada_unit_provider.adb @@ -85,8 +85,16 @@ package body Instrument.Ada_Unit_Provider is if Runtime_Dir.Is_Directory then Files := Runtime_Dir.Read_Dir; for File of Files.all loop - Provider.Runtime_Files.Insert - (+File.Base_Name, +File.Full_Name); + + -- It is allowed to have multiple version of the same file + -- in a project: the builder will pick the first one found. + -- Apply the same semantics here, and ignore all later + -- occurrences of a file already encountered. + + if not Provider.Runtime_Files.Contains (+File.Base_Name) then + Provider.Runtime_Files.Insert + (+File.Base_Name, +File.Full_Name); + end if; end loop; Unchecked_Free (Files); end if; @@ -116,7 +124,7 @@ package body Instrument.Ada_Unit_Provider is return Create_Unit_Provider_Reference (Create_Provider - (Runtime_Directories => Project.Runtime_Dirs, + (Runtime_Directories => Project.Runtime_Dirs, Dependencies_Filename => Mapping_File)); end Create_Provider_From_Project; From c82d453eef58e79b9f47f8252c4725838968ce29 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 15 Jun 2023 08:48:29 +0000 Subject: [PATCH 0334/1483] Merge branch 'eyraud/squashed_parallelized' into 'master' Implementation of the parallelized instrumentation See merge request eng/cov/gnatcoverage!178 Ref: eng/cov/gnatcoverage#18 --- .gitignore | 1 + .../GPR/ByCmdLine/ProjectSets/test.py | 4 +- testsuite/SUITE/srctracelib.py | 23 +- .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 0 -> 644 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 0 -> 2020 bytes ...uffers-bb_main_1.ads => gcvrt-bmain_1.ads} | 23 +- ...uffers-bb_main_2.ads => gcvrt-bmain_2.ads} | 23 +- .../gen/arm-elf-linux/gcvrt-bpkg.ads | 74 + ...fers-db_main_1.adb => gcvrt-db_main_1.adb} | 8 +- ...fers-db_main_1.ads => gcvrt-db_main_1.ads} | 6 +- ...fers-db_main_2.adb => gcvrt-db_main_2.adb} | 8 +- ...fers-db_main_2.ads => gcvrt-db_main_2.ads} | 6 +- .../gen/arm-elf-linux/gcvrt-foo.ads | 25 + .../gcvrt-pmain_1.ads} | 42 +- .../gcvrt-pmain_2.ads} | 42 +- .../gen/arm-elf-linux/gcvrt-ppkg.ads | 35 + .../gnatcov_rts-buffers-bb_pkg.ads | 41 - .../gnatcov_rts-buffers-bs_pkg.ads | 41 - .../gnatcov_rts-buffers-lists-foo.ads | 25 - .../gnatcov_rts-buffers-pb_pkg.ads | 19 - .../gnatcov_rts-buffers-ps_pkg.ads | 19 - .../gen/arm-elf-linux/main_1.adb | 7 +- .../gen/arm-elf-linux/main_1.sid | Bin 387 -> 387 bytes .../gen/arm-elf-linux/main_2.adb | 7 +- .../gen/arm-elf-linux/main_2.sid | Bin 387 -> 387 bytes .../gen/arm-elf-linux/pkg.adb | 10 +- .../gen/arm-elf-linux/pkg.ads | 2 +- .../gen/arm-elf-linux/pkg.sid | Bin 1046 -> 1046 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1878 -> 1906 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1888 -> 1916 bytes .../U204-026-arch-mix/gen/main_1.srctrace | Bin 416 -> 416 bytes .../U204-026-arch-mix/gen/main_2.srctrace | Bin 388 -> 388 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 1942 -> 1943 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 1851 -> 1879 bytes ...uffers-bb_main_1.ads => gcvrt-bmain_1.ads} | 23 +- ...uffers-bb_main_2.ads => gcvrt-bmain_2.ads} | 23 +- .../gen/x86_64-windows/gcvrt-bpkg.ads | 74 + ...fers-db_main_1.adb => gcvrt-db_main_1.adb} | 13 +- .../gen/x86_64-windows/gcvrt-db_main_1.ads | 13 + ...fers-db_main_2.adb => gcvrt-db_main_2.adb} | 13 +- .../gen/x86_64-windows/gcvrt-db_main_2.ads | 13 + .../gen/x86_64-windows/gcvrt-foo.ads | 25 + .../gcvrt-pmain_1.ads} | 42 +- .../gcvrt-pmain_2.ads} | 42 +- .../gen/x86_64-windows/gcvrt-ppkg.ads | 35 + .../gnatcov_rts-buffers-bb_pkg.ads | 41 - .../gnatcov_rts-buffers-bs_pkg.ads | 41 - .../gnatcov_rts-buffers-db_main_1.ads | 6 - .../gnatcov_rts-buffers-db_main_2.ads | 6 - .../gnatcov_rts-buffers-lists-foo.ads | 25 - .../gnatcov_rts-buffers-pb_pkg.ads | 19 - .../gnatcov_rts-buffers-ps_pkg.ads | 19 - .../gen/x86_64-windows/main_1.adb | 13 +- .../gen/x86_64-windows/main_1.sid | Bin 389 -> 389 bytes .../gen/x86_64-windows/main_2.adb | 13 +- .../gen/x86_64-windows/main_2.sid | Bin 389 -> 389 bytes .../gen/x86_64-windows/pkg.adb | 10 +- .../gen/x86_64-windows/pkg.ads | 2 +- .../gen/x86_64-windows/pkg.sid | Bin 1050 -> 1050 bytes .../tests/U204-026-arch-mix/main_2-out.txt | 11 + .../tests/excluded_unit_imported_prj/test.py | 2 +- testsuite/tests/instr-cov/ext_gpr/test.py | 14 +- .../tests/instr-cov/gpr-complex/main_body.gpr | 5 + .../tests/instr-cov/gpr-complex/main_sep.gpr | 5 + .../instr-cov/gpr-complex/main_simple.gpr | 6 + .../tests/instr-cov/gpr-complex/main_spec.gpr | 5 + .../instr-cov/gpr-complex/src-lib/lib.gpr | 4 + .../instr-cov/gpr-complex/src-lib/pkg-bar.adb | 4 + .../instr-cov/gpr-complex/src-lib/pkg.adb | 9 + .../instr-cov/gpr-complex/src-lib/pkg.ads | 4 + .../gpr-complex/src-main_body/main.adb | 7 + .../gpr-complex/src-main_body/pkg.adb | 11 + .../gpr-complex/src-main_sep/main.adb | 7 + .../gpr-complex/src-main_sep/pkg-bar.adb | 6 + .../gpr-complex/src-main_simple/main.adb | 7 + .../gpr-complex/src-main_spec/main.adb | 8 + .../gpr-complex/src-main_spec/pkg.ads | 5 + .../tests/instr-cov/gpr-complex/test.opt | 1 + testsuite/tests/instr-cov/gpr-complex/test.py | 121 ++ .../instr-cov/manual-dump/covdump__cov.adb | 4 +- testsuite/tests/instr-cov/orphan-unit/test.py | 2 +- tools/gnatcov/Makefile | 6 +- tools/gnatcov/command_line.ads | 235 +++- tools/gnatcov/coverage-source.adb | 116 +- tools/gnatcov/coverage-source.ads | 7 +- tools/gnatcov/files_table.adb | 8 +- tools/gnatcov/files_table.ads | 37 +- tools/gnatcov/gnatcov_bits_specific.adb | 127 +- tools/gnatcov/inputs.adb | 16 + tools/gnatcov/inputs.ads | 4 + tools/gnatcov/instrument-ada_unit.adb | 1096 +++++++++------ tools/gnatcov/instrument-ada_unit.ads | 103 +- tools/gnatcov/instrument-ada_unit__stub.adb | 5 +- tools/gnatcov/instrument-ada_unit__stub.ads | 20 +- .../gnatcov/instrument-ada_unit_provider.adb | 20 + .../gnatcov/instrument-ada_unit_provider.ads | 10 +- tools/gnatcov/instrument-c.adb | 958 ++++--------- tools/gnatcov/instrument-c.ads | 116 +- tools/gnatcov/instrument-c__stub.adb | 6 +- tools/gnatcov/instrument-c__stub.ads | 11 +- tools/gnatcov/instrument-c_utils.ads | 7 +- tools/gnatcov/instrument-checkpoints.adb | 4 +- tools/gnatcov/instrument-common.adb | 602 ++++---- tools/gnatcov/instrument-common.ads | 368 +++-- tools/gnatcov/instrument-config.adb | 50 + tools/gnatcov/instrument-input_traces.adb | 28 +- tools/gnatcov/instrument-input_traces.ads | 2 +- tools/gnatcov/instrument-main.adb | 41 + tools/gnatcov/instrument-projects.adb | 1225 +++++++++++++++++ tools/gnatcov/instrument-source.adb | 66 + tools/gnatcov/instrument.adb | 838 ++--------- tools/gnatcov/instrument.ads | 124 +- tools/gnatcov/project.adb | 384 +++--- tools/gnatcov/project.ads | 46 +- tools/gnatcov/rts/gcvrt.ads | 23 + tools/gnatcov/rts/gnatcov_rts-buffers.ads | 1 - tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 4 - .../gnatcov/rts/gnatcov_rts_c-traces-output.c | 6 +- tools/gnatcov/rts/gnatcov_rts_c-traces.h | 7 +- tools/gnatcov/strings.adb | 41 +- tools/gnatcov/strings.ads | 12 +- tools/gnatcov/subprocesses.adb | 38 +- tools/gnatcov/switches.adb | 41 + tools/gnatcov/switches.ads | 14 + tools/gnatcov/traces_source.ads | 26 +- 125 files changed, 4605 insertions(+), 3544 deletions(-) create mode 100644 testsuite/tests/U204-026-arch-mix/bin-main_1.trace create mode 100644 testsuite/tests/U204-026-arch-mix/bin-main_2.trace rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gnatcov_rts-buffers-bb_main_1.ads => gcvrt-bmain_1.ads} (79%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gnatcov_rts-buffers-bb_main_2.ads => gcvrt-bmain_2.ads} (79%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bpkg.ads rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gnatcov_rts-buffers-db_main_1.adb => gcvrt-db_main_1.adb} (64%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gnatcov_rts-buffers-db_main_1.ads => gcvrt-db_main_1.ads} (60%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gnatcov_rts-buffers-db_main_2.adb => gcvrt-db_main_2.adb} (64%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gnatcov_rts-buffers-db_main_2.ads => gcvrt-db_main_2.ads} (60%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads rename testsuite/tests/U204-026-arch-mix/gen/{x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads => arm-elf-linux/gcvrt-pmain_1.ads} (66%) rename testsuite/tests/U204-026-arch-mix/gen/{x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads => arm-elf-linux/gcvrt-pmain_2.ads} (66%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gnatcov_rts-buffers-bb_main_1.ads => gcvrt-bmain_1.ads} (77%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gnatcov_rts-buffers-bb_main_2.ads => gcvrt-bmain_2.ads} (77%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bpkg.ads rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gnatcov_rts-buffers-db_main_1.adb => gcvrt-db_main_1.adb} (55%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gnatcov_rts-buffers-db_main_2.adb => gcvrt-db_main_2.adb} (55%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads rename testsuite/tests/U204-026-arch-mix/gen/{arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads => x86_64-windows/gcvrt-pmain_1.ads} (63%) rename testsuite/tests/U204-026-arch-mix/gen/{arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads => x86_64-windows/gcvrt-pmain_2.ads} (63%) create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads delete mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads create mode 100644 testsuite/tests/U204-026-arch-mix/main_2-out.txt create mode 100644 testsuite/tests/instr-cov/gpr-complex/main_body.gpr create mode 100644 testsuite/tests/instr-cov/gpr-complex/main_sep.gpr create mode 100644 testsuite/tests/instr-cov/gpr-complex/main_simple.gpr create mode 100644 testsuite/tests/instr-cov/gpr-complex/main_spec.gpr create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-lib/lib.gpr create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-lib/pkg-bar.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-lib/pkg.ads create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_body/main.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_body/pkg.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_sep/main.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_simple/main.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_spec/main.adb create mode 100644 testsuite/tests/instr-cov/gpr-complex/src-main_spec/pkg.ads create mode 100644 testsuite/tests/instr-cov/gpr-complex/test.opt create mode 100644 testsuite/tests/instr-cov/gpr-complex/test.py create mode 100644 tools/gnatcov/instrument-config.adb create mode 100644 tools/gnatcov/instrument-main.adb create mode 100644 tools/gnatcov/instrument-projects.adb create mode 100644 tools/gnatcov/instrument-source.adb create mode 100644 tools/gnatcov/rts/gcvrt.ads diff --git a/.gitignore b/.gitignore index 1ddf255c3..f65e4e605 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ obj +obj-* lib *.pyc *.pkl diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py index 2ec633226..729910a2c 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py @@ -19,7 +19,7 @@ recurse=False, xreports=['boolops']) -# -Pgen --projects=boolops.gpr --projects=intops.gpr, not recusrive +# -Pgen --projects=boolops.gpr --projects=intops.gpr, not recursive # expect boolops & intops related reports check( @@ -28,7 +28,7 @@ recurse=False, xreports=['boolops', 'intops']) -# -Pgen --projects=boolops.gpr --projects=counters.gpr, not recusrive +# -Pgen --projects=boolops.gpr --projects=counters.gpr, not recursive # expect boolops & counters related reports check( diff --git a/testsuite/SUITE/srctracelib.py b/testsuite/SUITE/srctracelib.py index a43943212..195fe36de 100755 --- a/testsuite/SUITE/srctracelib.py +++ b/testsuite/SUITE/srctracelib.py @@ -32,7 +32,6 @@ trace_entry_header_struct = Struct( 'trace entry header', ('unit_name_length', 'I'), - ('project_name_length', 'I'), ('stmt_bit_count', 'I'), ('dc_bit_count', 'I'), ('mcdc_bit_count', 'I'), @@ -41,7 +40,7 @@ ('bit_buffer_encoding', 'B'), ('fingerprint', '20B'), ('bit_maps_fingerprint', '20B'), - ('padding', 'B'), + ('padding', '5B'), ) @@ -196,7 +195,6 @@ def format_buffer(b): ''.join('{:02x}'.format(b) for b in e.fingerprint), ''.join('{:02x}'.format(b) for b in e.bit_maps_fingerprint) )) - print(' Project: {}'.format(e.project_name)) print(' Stmt buffer: {}'.format(format_buffer(e.stmt_buffer))) print(' Dc buffer: {}'.format(format_buffer(e.dc_buffer))) print(' MCDC buffer: {}'.format(format_buffer(e.mcdc_buffer))) @@ -276,13 +274,11 @@ class TraceEntry(object): BIT_BUFFER_ENCODING_CODES = { value: key for key, value in BIT_BUFFER_ENCODING_NAMES.items()} - def __init__(self, language, unit_part, unit_name, project_name, - fingerprint, bit_maps_fingerprint, stmt_buffer, dc_buffer, - mcdc_buffer): + def __init__(self, language, unit_part, unit_name, fingerprint, + bit_maps_fingerprint, stmt_buffer, dc_buffer, mcdc_buffer): self.language = language self.unit_part = unit_part self.unit_name = unit_name - self.project_name = project_name self.fingerprint = fingerprint self.bit_maps_fingerprint = bit_maps_fingerprint self.stmt_buffer = stmt_buffer @@ -303,7 +299,7 @@ def read(cls, fp, trace_file, big_endian): language = cls.LANGUAGE_NAMES[header['language']] - if header['padding'] != 0: + if header['padding'] != (0, 0, 0, 0, 0): raise ValueError('Invalid padding: {}' .format(header['padding'])) @@ -314,11 +310,6 @@ def read(cls, fp, trace_file, big_endian): unit_name = read_aligned( fp, header['unit_name_length'], trace_file.alignment) - with fp.label_context('project name'): - project_name = (read_aligned(fp, header['project_name_length'], - trace_file.alignment) - or "") - with fp.label_context('stmt buffer'): stmt_buffer = TraceBuffer.read( fp, trace_file, bit_buffer_encoding, @@ -332,7 +323,7 @@ def read(cls, fp, trace_file, big_endian): fp, trace_file, bit_buffer_encoding, header['mcdc_bit_count']) - return cls(language, unit_part, unit_name, project_name, + return cls(language, unit_part, unit_name, header['fingerprint'], header['bit_maps_fingerprint'], stmt_buffer, dc_buffer, mcdc_buffer) @@ -340,7 +331,6 @@ def write(self, fp, big_endian, alignment): """Write this trace info entry to the `fp` file.""" trace_entry_header_struct.write(fp, { 'unit_name_length': len(self.unit_name), - 'project_name_length': len(self.project_name), 'stmt_bit_count': len(self.stmt_buffer.bits), 'dc_bit_count': len(self.dc_buffer.bits), 'mcdc_bit_count': len(self.mcdc_buffer.bits), @@ -350,11 +340,10 @@ def write(self, fp, big_endian, alignment): self.BIT_BUFFER_ENCODING_CODES['lsb_first_bytes'], 'fingerprint': self.fingerprint, 'bit_maps_fingerprint': self.bit_maps_fingerprint, - 'padding': 0, + 'padding': (0, 0, 0, 0, 0), }, big_endian=big_endian) write_aligned(fp, self.unit_name, alignment) - write_aligned(fp, self.project_name, alignment) self.stmt_buffer.write(fp, alignment) self.dc_buffer.write(fp, alignment) diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace new file mode 100644 index 0000000000000000000000000000000000000000..1b7f06c4baf411743211d5529cc59e75e7336f5e GIT binary patch literal 644 zcmYk&y-LGS6u|M5TH8ylVq=vKQi7HuLa|Ac7CT9)P6{ejocvZ){6ZIT6h|j<=;Yu7 z_y|6MgM*{H-~)(*ga4CcuyFg!IrrXkk~6+EyRcH}Tx{*^U0R8x$b<<0VpyN)RR3__ zv{*c6SZCWuQzu)8ryH(FiddK92EONuqo$W%SgTLZ*1Seg z_5GR~5JkW7|NXTy{ofK|l9H2ZTFjW(vW$7$M?*eq#3b;Yb0g%xFiRY1%XgU1NufuK z&Hg0ny+~U;Vy%CGUG`~f=B=ExsjGG7d&M~9k5TL2;5GiD-s{Bu8Gu3VC*)C9$!b(z6aiJ9zZMePdN?S^T7zqNBl0Z^N2SGsiY1qUBqGDoV zq5^@KsF*-jEMWpMfj~@DA`v7Y5C{YU!M**S?;LVY(&RpS-|y#q=iIx}y<2x5)b79D zc>H8@=~Q6M2V*kEnB>WPUs*nX>0H+=CC_J*->XN@uD;lK`to6H%rc&^*@&V}D_Ti- zHTlI++^9vZTD=j*^=`f1U289LrSV}azSdgnH0#X-Sf&5#r_Q9lu8g^`c-%QHe;LDJ zD4aJJ7Y|K1fP0oD{^n)z7ff#PFn|Mi29=l=s|>1S|7^GiP?I3(W$)_g~> z)<5?2PjH*~zt%7N2})8gp#BeZorlw*n2-lnJL zA^Q*D9{zP$=hwC@ey0ofy?g_>!g)uq)_1zZkI{4bzQASraq+VM(GBT8kALLFyMD#* z@=Lu5{;J+bSnuaYtBc>UAchiq+vI_KHfwjMR`f*N{-lwmy#+x&u zS2^!0yiUG0`TFn_*7yL{dCg$G|0i&k{9mjt`-|vDzc07pGW90(qx*Y~uHWx1Sob%> zul False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1_1"); Unit_Name : constant String := "main_1"; - Project_Name : constant String := ""; Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := (Fingerprint => (125, 27, 0, 113, 188, 140, 235, 155, 190, 125, 180, 238, 139, 95, 108, 198, 229, 72, 222, 11), Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, @@ -33,9 +34,11 @@ package GNATcov_RTS.Buffers.BB_main_1 is Statement_Last_Bit => 0, Decision_Last_Bit => -1, MCDC_Last_Bit => -1); +end Buffers_1; - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_1_buffers"); + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_1_buffers"); -end GNATcov_RTS.Buffers.BB_main_1; +end GCVRT.Bmain_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_2.ads similarity index 79% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_2.ads index 4f546cde7..db6822381 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_main_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_2.ads @@ -1,31 +1,32 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Interfaces.C; use Interfaces.C; +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GNATcov_RTS.Buffers.BB_main_2 is +package GCVRT.Bmain_2 is pragma Preelaborate; +package Buffers_1 is Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2_1"); Unit_Name : constant String := "main_2"; - Project_Name : constant String := ""; Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := (Fingerprint => (242, 237, 33, 15, 121, 175, 106, 160, 145, 225, 226, 10, 175, 16, 207, 223, 26, 27, 27, 148), Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, @@ -33,9 +34,11 @@ package GNATcov_RTS.Buffers.BB_main_2 is Statement_Last_Bit => 0, Decision_Last_Bit => -1, MCDC_Last_Bit => -1); +end Buffers_1; - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_2_buffers"); + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_2_buffers"); -end GNATcov_RTS.Buffers.BB_main_2; +end GCVRT.Bmain_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bpkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bpkg.ads new file mode 100644 index 000000000..16884c68b --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bpkg.ads @@ -0,0 +1,74 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GCVRT.Bpkg is + + pragma Preelaborate; + +package Buffers_1 is + Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg_1"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg_1"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg_1"); + + Unit_Name : constant String := "pkg"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), + Language => Unit_Based_Language, + Unit_Part => Unit_Spec, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => -1, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); +end Buffers_1; + +package Buffers_2 is + Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg_2"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg_2"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg_2"); + + Unit_Name : constant String := "pkg"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 2, + Decision_Last_Bit => 1, + MCDC_Last_Bit => 2); +end Buffers_2; + + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access, +2 => Buffers_2.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 2, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_pkg_buffers"); + +end GCVRT.Bpkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.adb similarity index 64% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.adb rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.adb index 1923cd7da..b57053032 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.adb @@ -1,15 +1,15 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; -with GNATcov_RTS.Buffers.Lists.foo; -package body GNATcov_RTS.Buffers.DB_main_1 is +with GCVRT.Foo; +package body GCVRT.DB_main_1 is procedure Dump_Buffers is begin GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GNATcov_RTS.Buffers.Lists.foo.List, + (GCVRT.Foo.List, Program_Name => "main_1", Exec_Date => 0); end Dump_Buffers; -end GNATcov_RTS.Buffers.DB_main_1; +end GCVRT.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.ads similarity index 60% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.ads index e8975f8ba..8a501b2da 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.ads @@ -1,6 +1,8 @@ pragma Style_Checks (Off); pragma Warnings (Off); -package GNATcov_RTS.Buffers.DB_main_1 is +with GNATcov_RTS.Buffers; +package GCVRT.DB_main_1 is procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); -end GNATcov_RTS.Buffers.DB_main_1; + +end GCVRT.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.adb similarity index 64% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.adb rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.adb index c868d1f17..ccab2ae8d 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.adb @@ -1,15 +1,15 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; -with GNATcov_RTS.Buffers.Lists.foo; -package body GNATcov_RTS.Buffers.DB_main_2 is +with GCVRT.Foo; +package body GCVRT.DB_main_2 is procedure Dump_Buffers is begin GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GNATcov_RTS.Buffers.Lists.foo.List, + (GCVRT.Foo.List, Program_Name => "main_2", Exec_Date => 0); end Dump_Buffers; -end GNATcov_RTS.Buffers.DB_main_2; +end GCVRT.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.ads similarity index 60% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.ads index 5a1450133..0f4078092 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-db_main_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.ads @@ -1,6 +1,8 @@ pragma Style_Checks (Off); pragma Warnings (Off); -package GNATcov_RTS.Buffers.DB_main_2 is +with GNATcov_RTS.Buffers; +package GCVRT.DB_main_2 is procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); -end GNATcov_RTS.Buffers.DB_main_2; + +end GCVRT.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads new file mode 100644 index 000000000..8a33e62aa --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads @@ -0,0 +1,25 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +with GCVRT.Bmain_1; +with GCVRT.Bmain_2; +with GCVRT.Bpkg; + +package GCVRT.Foo is + + pragma Preelaborate; + + gnatcov_rts_buffers_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_main_1_buffers,"gnatcov_rts_buffers_main_1_buffers"); + gnatcov_rts_buffers_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_main_2_buffers,"gnatcov_rts_buffers_main_2_buffers"); + gnatcov_rts_buffers_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_pkg_buffers,"gnatcov_rts_buffers_pkg_buffers"); + List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( + 1 => gnatcov_rts_buffers_main_1_buffers'Access, + 2 => gnatcov_rts_buffers_main_2_buffers'Access, + 3 => gnatcov_rts_buffers_pkg_buffers'Access); + C_List : constant GNATcov_RTS.Buffers.Lists.GNATcov_RTS_Coverage_Buffers_Group_Array := + ( 3, List'Address); + pragma Export (C, C_List, "gnatcov_rts_buffers_array_Foo"); + +end GCVRT.Foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_1.ads similarity index 66% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_1.ads index baf5c0f4c..adbaa4d71 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_1.ads @@ -1,19 +1,23 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PB_main_1 is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1"); - -end GNATcov_RTS.Buffers.PB_main_1; +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pmain_1 is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1_1"); + +end Buffers_1; + +end GCVRT.Pmain_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_2.ads similarity index 66% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_2.ads index f40226dce..504bd5e24 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_main_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_2.ads @@ -1,19 +1,23 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PB_main_2 is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2"); - -end GNATcov_RTS.Buffers.PB_main_2; +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pmain_2 is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2_1"); + +end Buffers_1; + +end GCVRT.Pmain_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads new file mode 100644 index 000000000..d057902c9 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads @@ -0,0 +1,35 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Ppkg is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg_1"); + +end Buffers_1; + +package Buffers_2 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg_2"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg_2"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg_2"); + +end Buffers_2; + +end GCVRT.Ppkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads deleted file mode 100644 index 39a532e60..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bb_pkg.ads +++ /dev/null @@ -1,41 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; -with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GNATcov_RTS.Buffers.BB_pkg is - - pragma Preelaborate; - - Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); - Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg"); - - Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); - Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg"); - - MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); - MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg"); - - Unit_Name : constant String := "pkg"; - Project_Name : constant String := ""; - - Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := - (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), - Language => Unit_Based_Language, - Unit_Part => Unit_Body, - Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), - Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), - Statement => Statement_Buffer'Address, - Decision => Decision_Buffer'Address, - MCDC => MCDC_Buffer'Address, - Statement_Last_Bit => 2, - Decision_Last_Bit => 1, - MCDC_Last_Bit => 2); - - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_pkg_buffers"); - -end GNATcov_RTS.Buffers.BB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads deleted file mode 100644 index f041e06e8..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-bs_pkg.ads +++ /dev/null @@ -1,41 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; -with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GNATcov_RTS.Buffers.BS_pkg is - - pragma Preelaborate; - - Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg"); - - Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg"); - - MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg"); - - Unit_Name : constant String := "pkg"; - Project_Name : constant String := ""; - - Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := - (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), - Language => Unit_Based_Language, - Unit_Part => Unit_Spec, - Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), - Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), - Statement => Statement_Buffer'Address, - Decision => Decision_Buffer'Address, - MCDC => MCDC_Buffer'Address, - Statement_Last_Bit => -1, - Decision_Last_Bit => -1, - MCDC_Last_Bit => -1); - - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_S_pkg_buffers"); - -end GNATcov_RTS.Buffers.BS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads deleted file mode 100644 index 63f03b9f4..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-lists-foo.ads +++ /dev/null @@ -1,25 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers.BB_main_1; -with GNATcov_RTS.Buffers.BB_main_2; -with GNATcov_RTS.Buffers.BB_pkg; -with GNATcov_RTS.Buffers.BS_pkg; - -package GNATcov_RTS.Buffers.Lists.foo is - - pragma Preelaborate; - - gnatcov_rts_buffers_B_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_B_main_1_buffers,"gnatcov_rts_buffers_B_main_1_buffers"); - gnatcov_rts_buffers_B_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_B_main_2_buffers,"gnatcov_rts_buffers_B_main_2_buffers"); - gnatcov_rts_buffers_B_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_B_pkg_buffers,"gnatcov_rts_buffers_B_pkg_buffers"); - gnatcov_rts_buffers_S_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_S_pkg_buffers,"gnatcov_rts_buffers_S_pkg_buffers"); - List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( - 1 => gnatcov_rts_buffers_B_main_1_buffers'Access, - 2 => gnatcov_rts_buffers_B_main_2_buffers'Access, - 3 => gnatcov_rts_buffers_B_pkg_buffers'Access, - 4 => gnatcov_rts_buffers_S_pkg_buffers'Access); - -end GNATcov_RTS.Buffers.Lists.foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads deleted file mode 100644 index 2f84e5165..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_pkg.ads +++ /dev/null @@ -1,19 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PB_pkg is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg"); - -end GNATcov_RTS.Buffers.PB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads deleted file mode 100644 index 71406c7f1..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-ps_pkg.ads +++ /dev/null @@ -1,19 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PS_pkg is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg"); - -end GNATcov_RTS.Buffers.PS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb index 7a94497f7..cfb135284 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb @@ -1,8 +1,9 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Pkg; -with GNATcov_RTS.Buffers.PB_main_1;with GNATcov_RTS.Buffers.DB_main_1;with GNATcov_RTS;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +with GNATcov_RTS.Buffers;with GCVRT.Pmain_1;with GCVRT.DB_main_1;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is begin - GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_main_1.Statement_Buffer,0);Pkg.Compute (True, False); -GNATcov_RTS.Buffers.DB_main_1.Dump_Buffers;end Main_1; + GNATcov_RTS.Buffers.Witness(GCVRT.Pmain_1.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); +GCVRT.DB_main_1.Dump_Buffers;end Main_1; + diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index 255ad5bef91d788cd2cd950cee8283d653c7128c..a136b1e8d13a1557ad20f0640ee748747697bde7 100644 GIT binary patch delta 35 qcmZo>Ze|v7_j3$M&M#9)&PYwpF38W!D`DW>D5Am0_; delta 35 qcmZo>Ze|v7_j3$M&M#9)&PYwpF38W!D`DW?D5Am0_;a!?qZZe|v7_j3$M&M#9)&PYwpF38W!D`DW>D5Am0_; delta 35 qcmZo>Ze|v7_j3$M&M#9)&PYwpF38W!D`DW?D5Am0_;a!?qZ TiZV=AW=!KTf|$w$ zc4qv&`4qDxBarii z1<0AK!3rXCSd}MFW)++KpOtU&Qr0j-kf~tjfM^us!BQw9Mj$nl_1JXS3yRD$9bQeI loXB=g-B{PaOxMs@!N}Ok(9p`%TtVBw$jZO~q!R>SGyp5ZLInT- delta 316 zcmeywca2ZP-On*3IloLHIU_YWyC6R^uY`enqKJc+kzQg>CKCe_0|OZI0%KYj;7@AobnOhkcDrg%RSQ!|AjfEKxqyfRhL|Om< diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index 6d8d58fee919991e9661b3c759ba00fa266c61f2..4f6f771d824294e26979c7bbf23af408470bbe67 100644 GIT binary patch delta 299 zcmaFB_lHl!-On*3IloLHIU_YWyC6R^uY`ejqKL!f1&r*hObiSROq16zN(uoP42(d` z2E@6EnR)Ss6X%JufJ7&5Z3WYltr*jIjPw$7GMN~-fZ|*e6AUo58BM;-XgK)7eP`(#$;2FBl$+nAjhe{Vj;tjGxDykP-yCL6GV$P!j%W}u0aSFmQk;!IkI_v`JHG3RhO`e>|c0t`(*T78I&{)C9*vin*%G5$Z Q+rY@mzyNFo)J%{*0FXdEApigX delta 282 zcmeyv_kd5t-On*3IloLHIU_YWyC6R^uY`enqKE^JkzQg>CKCe_0|Nuou7=KQl#_Y`abMq}`MMfa!4-1ep*?|>Awy-Ks7G@Kg z{GL^8@Q3fE$P0Y-TH)LR71aW|XZQ@#MUJwH;VFYAM4rG*=oXe;U7A?q5 S2T3w8PyB1m43acwR0II4?+=^+ delta 82 zcmZ3$ynuN^3?swDNNdsD#LT>SLk0#$1_)pSQ4?1}C5)h=K#Cc}ob1SGJ-LBVVd4+L P$*hd}90l3wAYldoq!ABY diff --git a/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace b/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace index ef244cfe7684d3d525848372a52cb172a6761f00..f9310f2c01f1f50fa8eb8d28c7a4d558556fa316 100644 GIT binary patch delta 86 zcmZo+ZegAfGcmzJkO2sC6EpMT4M8jh2DXVStr3Do3=E7wLFUP>jMkhW>4NNZ2Ih%h PtwrD*AcF~rS%4S-@dysG delta 84 zcmZo+ZegAf!^ki((poS#F*7gTkO2(XK;*=wP(dRG21X#C86-H_l+jwWAUhq*V*(1W Nz+@(Vv}OTG006GK4wC=? diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 1ddccc5b96d894fca0916193751ec3b474e86839..2ea341c6bba732d35d81f98a0fb29faaeff9b510 100644 GIT binary patch delta 376 zcmbQnKb>F1-On*3IloLHIU_YWyC6R^uY`ejqKG>S0}xD%c7)J#EGG*vvO?Im%s7)6 z8JQVD3MPv(USMRJ9LMCs#t4#SnS772X!0Va4#wY;wV9pSe?vt}nQhsBGeK1BWR~Fs z=>>zy_n0-n=CVxYW>JQ+j9FBntXMd!odswD)U?wqwm|baS;H7vCMU3pGcr%EU|p>N zG7sb^HXzPT%*=~7#1Jt8iA=U<(~dd|WZdAHcK+tu$tOUX1b{dtwJbF!zaTd?uSB<` zC^Z!%J_U%Ktzt6rb5mndD~l3KQ)1Hd5=(#qmRgjUo*Gk^; delta 394 zcmbQvKaF3+-On*3IloLHIU_YWyC6R^uY`enqKNy%c*luLELoEn8JQU;J~Lx21~De9 zGG3VM&Xmo^$il$D0K!~A%sKfRqswFiW{%0bm>L*=PPS%tX8*~^43uG>+{$dr{*wv9 zKFKV@31V>rG5h3q%o?l^acLH1D9f2e70Swmv!=5EO@Nwqo5dDrz9efHBlF|}R&hp_ z$sMe#Wf+0xu>o;zVrE{vAqvlEax|NE{R^PvyB$26H`s)p07(k~v5|?MLAip4k%5ts zp`nq1CP;ie5IbANWaQ_j#-yYc<)We(O8I;R(2vHK{SMz6k;W$v#|)rbmB*7 zE!g-0mRf~0HvU2y=k4WUqQedIX6DV#yW4w7ekAkzhr37B=1s18d0wrznzgHIC*e2_ zStmyUM3DGB&wtl50&UZk*s5PBzqkIk=KA>+zY|Y|)Tn^QS?%hy6!G)M`&TZaVs`{v zg9Q$EX)mFq1xF{wMtM3wCn_^Qw0Nl%Mo$PQ4Lg{m+^Rwg&xa;&cc{OqPO7{bOeLs4Tih~6p4^%#Nx%Rsj6YkGOtAm} literal 1851 zcmb7FJ!lkB5Z-qe6{93kvB_!JU>WvqZxMr{La;~*f1(&{0&(4Yxtz(~o_Cug7O5;O zv=OxMr%($)5n>_ONJ_C2yI^5Zuo5j|qm4S>?9OIS6VD7cH*e?7H$UJ0yy25WXT6|l zdQ;k)t_789XlyeKL$N9&gGEQ;FpPd$7ec>Q7<26XmhBv{+`2bq`IWhX?^dc4#k^a( zpj1`?xS2HaX5tj>;Le(GCmX~2$gWepHeDucLrMcdE@{0jFzGo45QXaBfv;nQA0$neChALym0aUjSn9?7kb_- z_vUgpu_*uqCwUWg5TQ^+R9MFbL_NJacjffZlXv&d-RavmeEw0_gZZUsEBa42A$|o8 zp~$+GG##WKk9aR0c8{;*-+mi>c4o)XpT}?86w?w6;OKN223Tl1*A}`y7WlQjQQUjz(MhN zpi$V}q!4~&+V_!3=je=a$N@6ZTT1~9EdU_^G4z7KuyjZOI@lgNVc<6uXl7Eg={Ttj zi>ll>1L&e961~ZsNhB70QzR$qA{T6q6tYoPy9k3Eup7KHgkX^gxHs}(_~_fk?IPx{ zEhl+;WDDHVXD1>s1&RF$_lO6zB|YiR&V=$>!EIz&Xemj>qt@~89f(i_=Pxg&fm False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1_1"); Unit_Name : constant String := "main_1"; - Project_Name : constant String := ""; Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := (Fingerprint => (125, 27, 0, 113, 188, 140, 235, 155, 190, 125, 180, 238, 139, 95, 108, 198, 229, 72, 222, 11), Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, @@ -33,9 +34,11 @@ package GNATcov_RTS.Buffers.BB_main_1 is Statement_Last_Bit => 0, Decision_Last_Bit => -1, MCDC_Last_Bit => -1); +end Buffers_1; - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_1_buffers"); + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_1_buffers"); -end GNATcov_RTS.Buffers.BB_main_1; +end GCVRT.Bmain_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_2.ads similarity index 77% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_2.ads index fb7e669bc..d68593c7f 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_main_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_2.ads @@ -1,31 +1,32 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Interfaces.C; use Interfaces.C; +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GNATcov_RTS.Buffers.BB_main_2 is +package GCVRT.Bmain_2 is pragma Preelaborate; +package Buffers_1 is Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2_1"); Unit_Name : constant String := "main_2"; - Project_Name : constant String := ""; Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := (Fingerprint => (242, 237, 33, 15, 121, 175, 106, 160, 145, 225, 226, 10, 175, 16, 207, 223, 26, 27, 27, 148), Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, @@ -33,9 +34,11 @@ package GNATcov_RTS.Buffers.BB_main_2 is Statement_Last_Bit => 0, Decision_Last_Bit => -1, MCDC_Last_Bit => -1); +end Buffers_1; - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_main_2_buffers"); + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_2_buffers"); -end GNATcov_RTS.Buffers.BB_main_2; +end GCVRT.Bmain_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bpkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bpkg.ads new file mode 100644 index 000000000..46d0ddbc6 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bpkg.ads @@ -0,0 +1,74 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with Interfaces.C; use Interfaces.C; +with System; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +package GCVRT.Bpkg is + + pragma Preelaborate; + +package Buffers_1 is + Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg_1"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg_1"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg_1"); + + Unit_Name : constant String := "pkg"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), + Language => Unit_Based_Language, + Unit_Part => Unit_Spec, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => -1, + Decision_Last_Bit => -1, + MCDC_Last_Bit => -1); +end Buffers_1; + +package Buffers_2 is + Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg_2"); + + Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); + Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg_2"); + + MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); + MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg_2"); + + Unit_Name : constant String := "pkg"; + + Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := + (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), + Language => Unit_Based_Language, + Unit_Part => Unit_Body, + Unit_Name => (Unit_Name'Address, Unit_Name'Length), + Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), + Statement => Statement_Buffer'Address, + Decision => Decision_Buffer'Address, + MCDC => MCDC_Buffer'Address, + Statement_Last_Bit => 2, + Decision_Last_Bit => 1, + MCDC_Last_Bit => 2); +end Buffers_2; + + Buffers_Group : aliased constant Coverage_Buffers_Group := + (1 => Buffers_1.Buffers'Access, +2 => Buffers_2.Buffers'Access); + C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 2, Buffers_Group'Address); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_pkg_buffers"); + +end GCVRT.Bpkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.adb similarity index 55% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.adb rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.adb index 18ea1e0ed..79e3fa3de 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.adb @@ -1,15 +1,20 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; -with GNATcov_RTS.Buffers.Lists.foo; -package body GNATcov_RTS.Buffers.DB_main_1 is +with GCVRT.Foo; +package body GCVRT.DB_main_1 is procedure Dump_Buffers is begin GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GNATcov_RTS.Buffers.Lists.foo.List, + (GCVRT.Foo.List, Program_Name => "main_1", Exec_Date => 0); end Dump_Buffers; -end GNATcov_RTS.Buffers.DB_main_1; + overriding procedure Finalize (Self : in out Dump_Controlled_Type) is + begin + Dump_Buffers; + end Finalize; + +end GCVRT.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads new file mode 100644 index 000000000..fb6f2406e --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads @@ -0,0 +1,13 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers; +with Ada.Finalization; +package GCVRT.DB_main_1 is + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); + + type Dump_Controlled_Type is new Ada.Finalization.Controlled with + null record; + overriding procedure Finalize (Self : in out Dump_Controlled_Type); + +end GCVRT.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.adb similarity index 55% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.adb rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.adb index 02b84cc6a..d684712eb 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.adb @@ -1,15 +1,20 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; -with GNATcov_RTS.Buffers.Lists.foo; -package body GNATcov_RTS.Buffers.DB_main_2 is +with GCVRT.Foo; +package body GCVRT.DB_main_2 is procedure Dump_Buffers is begin GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GNATcov_RTS.Buffers.Lists.foo.List, + (GCVRT.Foo.List, Program_Name => "main_2", Exec_Date => 0); end Dump_Buffers; -end GNATcov_RTS.Buffers.DB_main_2; + overriding procedure Finalize (Self : in out Dump_Controlled_Type) is + begin + Dump_Buffers; + end Finalize; + +end GCVRT.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads new file mode 100644 index 000000000..691c4c538 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads @@ -0,0 +1,13 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers; +with Ada.Finalization; +package GCVRT.DB_main_2 is + + procedure Dump_Buffers; + pragma Convention (C, Dump_Buffers); + + type Dump_Controlled_Type is new Ada.Finalization.Controlled with + null record; + overriding procedure Finalize (Self : in out Dump_Controlled_Type); + +end GCVRT.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads new file mode 100644 index 000000000..c9aac77d4 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads @@ -0,0 +1,25 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +with GCVRT.Bmain_1; +with GCVRT.Bmain_2; +with GCVRT.Bpkg; + +package GCVRT.Foo is + + pragma Preelaborate; + + gnatcov_rts_buffers_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_main_1_buffers,"gnatcov_rts_buffers_main_1_buffers"); + gnatcov_rts_buffers_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_main_2_buffers,"gnatcov_rts_buffers_main_2_buffers"); + gnatcov_rts_buffers_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_pkg_buffers,"gnatcov_rts_buffers_pkg_buffers"); + List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( + 1 => gnatcov_rts_buffers_main_1_buffers'Access, + 2 => gnatcov_rts_buffers_main_2_buffers'Access, + 3 => gnatcov_rts_buffers_pkg_buffers'Access); + C_List : constant GNATcov_RTS.Buffers.Lists.GNATcov_RTS_Coverage_Buffers_Group_Array := + ( 3, List'Address); + pragma Export (C, C_List, "gnatcov_rts_buffers_array_Foo"); + +end GCVRT.Foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_1.ads similarity index 63% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_1.ads index 1d0b35bd8..c5a253048 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_1.ads @@ -1,19 +1,23 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PB_main_1 is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1"); - -end GNATcov_RTS.Buffers.PB_main_1; +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pmain_1 is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1_1"); + +end Buffers_1; + +end GCVRT.Pmain_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_2.ads similarity index 63% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_2.ads index f9f18da05..8bbd8b5ce 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gnatcov_rts-buffers-pb_main_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_2.ads @@ -1,19 +1,23 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PB_main_2 is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2"); - -end GNATcov_RTS.Buffers.PB_main_2; +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Pmain_2 is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2_1"); + +end Buffers_1; + +end GCVRT.Pmain_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads new file mode 100644 index 000000000..91152a7b1 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads @@ -0,0 +1,35 @@ +pragma Style_Checks (Off); pragma Warnings (Off); +with System; +with GNATcov_RTS; +with GNATcov_RTS.Buffers; +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); + +package GCVRT.Ppkg is + + pragma Pure; + +package Buffers_1 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg_1"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg_1"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg_1"); + +end Buffers_1; + +package Buffers_2 is + Statement_Buffer : constant System.Address; + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg_2"); + + Decision_Buffer : constant System.Address; + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg_2"); + + MCDC_Buffer : constant System.Address; + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg_2"); + +end Buffers_2; + +end GCVRT.Ppkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads deleted file mode 100644 index 8d1bde3aa..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bb_pkg.ads +++ /dev/null @@ -1,41 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; -with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GNATcov_RTS.Buffers.BB_pkg is - - pragma Preelaborate; - - Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); - Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg"); - - Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); - Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg"); - - MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); - MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg"); - - Unit_Name : constant String := "pkg"; - Project_Name : constant String := ""; - - Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := - (Fingerprint => (169, 72, 99, 183, 162, 15, 92, 242, 46, 209, 243, 55, 176, 82, 17, 62, 254, 76, 153, 48), - Language => Unit_Based_Language, - Unit_Part => Unit_Body, - Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), - Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), - Statement => Statement_Buffer'Address, - Decision => Decision_Buffer'Address, - MCDC => MCDC_Buffer'Address, - Statement_Last_Bit => 2, - Decision_Last_Bit => 1, - MCDC_Last_Bit => 2); - - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_B_pkg_buffers"); - -end GNATcov_RTS.Buffers.BB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads deleted file mode 100644 index 4c9260685..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-bs_pkg.ads +++ /dev/null @@ -1,41 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; -with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GNATcov_RTS.Buffers.BS_pkg is - - pragma Preelaborate; - - Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg"); - - Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg"); - - MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); - MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg"); - - Unit_Name : constant String := "pkg"; - Project_Name : constant String := ""; - - Buffers : aliased constant GNATcov_RTS_Coverage_Buffers := - (Fingerprint => (172, 135, 120, 131, 81, 65, 170, 218, 156, 87, 154, 30, 35, 71, 96, 166, 14, 161, 125, 216), - Language => Unit_Based_Language, - Unit_Part => Unit_Spec, - Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Project_Name => (Project_Name'Address, Project_Name'Length), - Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), - Statement => Statement_Buffer'Address, - Decision => Decision_Buffer'Address, - MCDC => MCDC_Buffer'Address, - Statement_Last_Bit => -1, - Decision_Last_Bit => -1, - MCDC_Last_Bit => -1); - - Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers'Access); - C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := (1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_S_pkg_buffers"); - -end GNATcov_RTS.Buffers.BS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads deleted file mode 100644 index ca5c6b54d..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_1.ads +++ /dev/null @@ -1,6 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -package GNATcov_RTS.Buffers.DB_main_1 is - - procedure Dump_Buffers; - pragma Convention (C, Dump_Buffers); -end GNATcov_RTS.Buffers.DB_main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads deleted file mode 100644 index 06f972268..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-db_main_2.ads +++ /dev/null @@ -1,6 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -package GNATcov_RTS.Buffers.DB_main_2 is - - procedure Dump_Buffers; - pragma Convention (C, Dump_Buffers); -end GNATcov_RTS.Buffers.DB_main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads deleted file mode 100644 index dfb98dbbb..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-lists-foo.ads +++ /dev/null @@ -1,25 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers.BB_main_1; -with GNATcov_RTS.Buffers.BB_main_2; -with GNATcov_RTS.Buffers.BB_pkg; -with GNATcov_RTS.Buffers.BS_pkg; - -package GNATcov_RTS.Buffers.Lists.foo is - - pragma Preelaborate; - - gnatcov_rts_buffers_B_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_B_main_1_buffers,"gnatcov_rts_buffers_B_main_1_buffers"); - gnatcov_rts_buffers_B_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_B_main_2_buffers,"gnatcov_rts_buffers_B_main_2_buffers"); - gnatcov_rts_buffers_B_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_B_pkg_buffers,"gnatcov_rts_buffers_B_pkg_buffers"); - gnatcov_rts_buffers_S_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_S_pkg_buffers,"gnatcov_rts_buffers_S_pkg_buffers"); - List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( - 1 => gnatcov_rts_buffers_B_main_1_buffers'Access, - 2 => gnatcov_rts_buffers_B_main_2_buffers'Access, - 3 => gnatcov_rts_buffers_B_pkg_buffers'Access, - 4 => gnatcov_rts_buffers_S_pkg_buffers'Access); - -end GNATcov_RTS.Buffers.Lists.foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads deleted file mode 100644 index 638a84ec2..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-pb_pkg.ads +++ /dev/null @@ -1,19 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PB_pkg is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg"); - -end GNATcov_RTS.Buffers.PB_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads deleted file mode 100644 index c8f18f74f..000000000 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gnatcov_rts-buffers-ps_pkg.ads +++ /dev/null @@ -1,19 +0,0 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with System; -with GNATcov_RTS; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); - -package GNATcov_RTS.Buffers.PS_pkg is - - pragma Pure; - - Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg"); - - Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg"); - - MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg"); - -end GNATcov_RTS.Buffers.PS_pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb index 61decca75..c9267341a 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb @@ -1,8 +1,9 @@ pragma Style_Checks (Off); pragma Warnings (Off); -with Pkg; - -with GNATcov_RTS.Buffers.PB_main_1;with GNATcov_RTS.Buffers.DB_main_1;with GNATcov_RTS;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is -begin - GNATcov_RTS.Buffers.Witness(GNATcov_RTS.Buffers.PB_main_1.Statement_Buffer,0);Pkg.Compute (True, False); -GNATcov_RTS.Buffers.DB_main_1.Dump_Buffers;end Main_1; +with Pkg; + +with GNATcov_RTS.Buffers;with GCVRT.Pmain_1;with GCVRT.DB_main_1;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +GNATcov_Dump_Object:GCVRT.DB_main_1.Dump_Controlled_Type;begin + GNATcov_RTS.Buffers.Witness(GCVRT.Pmain_1.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); +end Main_1; + diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid index b5f7a753eb7df7f191cc68d5518e5a7abea5f66d..6095ca35ca556f6bbca09c4f490391ed56311f51 100644 GIT binary patch delta 35 qcmZo=ZeD5Ay4_D5Ay4_)s;RLFHfXP#sG@xn@GATn@FPT)K mEMaCC%a$2v0>tRajm)-;zbEf!R$yeB{D4`Uk#X`5W+ebZej#Z9 delta 189 zcmbQmF^faQ-On*3IloLHIU_YWyC6R^uY`enqKG|P5+frs1JguJeLe;tU;<)BMi4Ps zgz*d?BZv>e96-!IabCgX1SXEjFBt7uA!@XlY}tP@LD>0BGMpe5H%RH^DNGtrH3ylL rp{$oos!*0NGmK@+3^W01V GNATcov_RTS.Buffers.Lists.P.List, + (Buffers_Groups => GCVRT.P.List, Filename => Ada.Command_Line.Command_Name & ".srctrace"); end Covdump; diff --git a/testsuite/tests/instr-cov/orphan-unit/test.py b/testsuite/tests/instr-cov/orphan-unit/test.py index 60d3db495..1880b8f65 100644 --- a/testsuite/tests/instr-cov/orphan-unit/test.py +++ b/testsuite/tests/instr-cov/orphan-unit/test.py @@ -27,7 +27,7 @@ thistest.fail_if_not_equal( '"gnatcov instrument" output', ( - "warning: While instrumenting pkg-child.adb...\n" + "warning: While instrumenting pkg-child.ads...\n" "warning: Cannot find required source file: pkg.ads" ), contents_of("instrument.log").strip(), diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index 7ed129754..d7a00b0af 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -176,15 +176,15 @@ ifdef INSTRUMENTED # instrumented as a main to compile gnatcov32, running gnatcov32 will not # dump execution traces. - gnatcov instrument -P gnatcov.gpr -XPART=gnatcov64 + gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov64 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 \ --src-subdirs=gnatcov-instr - gnatcov instrument -P gnatcov.gpr -XPART=gnatcov32 + gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov32 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov32 \ --src-subdirs=gnatcov-instr - gnatcov instrument -P gnatcov.gpr -XPART=driver + gnatcov instrument -j0 -P gnatcov.gpr -XPART=driver $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver \ --src-subdirs=gnatcov-instr else diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 1a355b49e..56bdafe4b 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -59,7 +59,9 @@ package Command_Line is Cmd_Scan_Objects, Cmd_Setup, - Cmd_Instrument); + Cmd_Instrument_Project, + Cmd_Instrument_Source, + Cmd_Instrument_Main); -- Set of commands we support. More complete descriptions below. type Bool_Options is @@ -113,6 +115,7 @@ package Command_Line is Opt_Dump_Channel, Opt_Dump_Filename_Env_Var, Opt_Dump_Filename_Prefix, + Opt_Dump_Filename_Tag, Opt_Ada, Opt_Dump_Units_To, Opt_Timezone, @@ -121,6 +124,15 @@ package Command_Line is Opt_Path_Count_Limit, Opt_Install_Name, Opt_Runtime_Project, + Opt_Lang, + Opt_Parallelism_Level, + Opt_Compiler_Driver, + Opt_Spec_Suffix, + Opt_Body_Suffix, + Opt_Dot_Replacement, + Opt_Gnatem, + Opt_Gnatec, + Opt_Project_Name, Opt_Source_Root); -- Set of string options we support. More complete descriptions below. @@ -145,9 +157,14 @@ package Command_Line is Opt_Restricted_To_Languages, Opt_Annotation_Format, Opt_C_Opts, - Opt_CPP_Opts); + Opt_CPP_Opts, + Opt_Files, + Opt_Runtime_Dir); -- Set of string list options we support. More complete descriptions below. + subtype Cmd_Instrument is Command_Type + range Cmd_Instrument_Project .. Cmd_Instrument_Main; + package Parser is new Argparse (Command_Type, Bool_Options, String_Options, String_List_Options); use Parser; @@ -338,11 +355,24 @@ package Command_Line is & " instrumentation and set up default arguments" & " for future ""gnatcov instrument"" invocations.", Internal => False), - Cmd_Instrument => Create + Cmd_Instrument_Project => Create (Name => "instrument", Description => ("Instrument the given project and produce the" & " associated Source Instrumentation Data files."), - Internal => False)); + Internal => False), + Cmd_Instrument_Source => Create + (Name => "instrument-source", + Description => "Instrument the given files, all belonging to the" + & " same unit.", + Pattern => "[FILES]", + Internal => True), + Cmd_Instrument_Main => Create + (Name => "instrument-main", + Description => "Insert dump trigger code in the the given main file," + & " dumping coverage buffers of all of the specified" + & " files (through the --files switch).", + Pattern => "--files= [MAIN]", + Internal => True)); Bool_Infos : constant Bool_Option_Info_Array := (Opt_Verbose => Create @@ -356,7 +386,7 @@ package Command_Line is & " transitively imported project.", Commands => (Cmd_Run | Cmd_Coverage - | Cmd_Instrument + | Cmd_Instrument_Project | Cmd_Dump_CFG => True, others => False), Internal => False), @@ -367,7 +397,7 @@ package Command_Line is & " transitively imported projects are not considered.", Commands => (Cmd_Run | Cmd_Coverage - | Cmd_Instrument + | Cmd_Instrument_Project | Cmd_Dump_CFG => True, others => False), Internal => False), @@ -465,7 +495,10 @@ package Command_Line is Help => "Valid only when --dump-channel=bin-file. Create simple" & " filenames for source trace files (no PID/timestamp" & " variations).", - Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), + Commands => (Cmd_Setup + | Cmd_Instrument_Project + | Cmd_Instrument_Main => True, + others => False), Internal => False), Opt_Allow_Mix_Trace_Kind => Create @@ -526,10 +559,13 @@ package Command_Line is Pattern => "[GPR]", Help => "Use GPR as root project to locate SCOs, select" & " units to analyze and find default options.", - Commands => (Cmd_Setup => False, others => True), + Commands => (Cmd_Setup + | Cmd_Instrument_Source + | Cmd_Instrument_Main => False, + others => True), At_Most_Once => True, Internal => False), - Opt_Subdirs => Create + Opt_Subdirs => Create (Long_Name => "--subdirs", Pattern => "[SUBDIR]", Help => "When using project files, look for ALI/SID files in" @@ -588,7 +624,9 @@ package Command_Line is Pattern => "[SUBDIR]", Help => "Subdirectory where XCOV or HTML report files should" & " be produced.", - Commands => (Cmd_Coverage => True, others => False), + Commands => (Cmd_Coverage + | Cmd_Instrument_Source + | Cmd_Instrument_Main => True, others => False), At_Most_Once => False, Internal => False), Opt_Tag => Create @@ -753,7 +791,10 @@ package Command_Line is & " to dump a base64 trace on the standard output" & " using Ada.Text_IO. This is the preferred channel" & " for non-native programs.", - Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), + Commands => (Cmd_Setup + | Cmd_Instrument_Project + | Cmd_Instrument_Main => True, + others => False), At_Most_Once => False, Internal => False, Pattern => "bin-file|base64-stdout"), @@ -762,14 +803,31 @@ package Command_Line is Help => "Valid only when --dump-channel=bin-file. Name of the" & " environment variable which, if set, contains the" & " filename for created source traces.", - Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), + Commands => (Cmd_Setup + | Cmd_Instrument_Project + | Cmd_Instrument_Main => True, + others => False), At_Most_Once => False, Internal => False), Opt_Dump_Filename_Prefix => Create (Long_Name => "--dump-filename-prefix", Help => "Valid only when --dump-channel=bin-file. Select a" & " filename prefix for created source traces.", - Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), + Commands => (Cmd_Setup + | Cmd_Instrument_Project + | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => False), + + Opt_Dump_Filename_Tag => Create + (Long_Name => "--dump-filename-tag", + Help => "Valid only when --dump-channel=bin-file. Select a" + & " filename tag for created source traces.", + Commands => (Cmd_Setup + | Cmd_Instrument_Project + | Cmd_Instrument_Main => True, + others => False), At_Most_Once => False, Internal => False), @@ -878,6 +936,107 @@ package Command_Line is At_Most_Once => False, Internal => False), + Opt_Lang => Create + (Long_Name => "--lang", + Pattern => "[C|C++|Ada]", + Help => "Language for the given compilation unit", + Commands => (Cmd_Instrument_Main | Cmd_Instrument_Source => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Parallelism_Level => Create + (Short_Name => "-j", + Long_Name => "--jobs", + Pattern => "POSITIVE", + Help => + "Maximal number of concurrently running tasks. Number of processors" + & " of the machine if set to 0. Defaults to 1.", + Commands => (Cmd_Instrument_Project => True, others => False), + At_Most_Once => False, + Internal => False), + + Opt_Compiler_Driver => Create + (Long_Name => "--compiler-driver", + Pattern => "NAME", + Help => + "Compiler driver used to compile the source (e.g. gcc). This is" + & " used when instrumenting a C/C++ source, to retrieve builtin" + & " macros that may modify the file preprocessing.", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Body_Suffix => Create + (Long_Name => "--body-suffix", + Pattern => "NAME", + Help => + "Body suffix for source files created by the instrumenter for the" + & " instrumentation of a source", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Spec_Suffix => Create + (Long_Name => "--spec-suffix", + Pattern => "NAME", + Help => + "Spec suffix for source files created by the instrumenter for the" + & " instrumentation of a source", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Dot_Replacement => Create + (Long_Name => "--dot-replacement", + Pattern => "NAME", + Help => + "Dot replacement for source files created by the instrumenter for" + & " the instrumentation of a source", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Gnatem => Create + (Long_Name => "--gnatem", + Pattern => "NAME", + Help => + "Name of the file containing unit dependencies in the GNAT format.", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Gnatec => Create + (Long_Name => "--gnatec", + Pattern => "NAME", + Help => + "Name of the file containing configuration pragmas.", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + + Opt_Project_Name => Create + (Long_Name => "--project-name", + Pattern => "NAME", + Help => + "Name of the root project, without its gpr extension.", + Commands => + (Cmd_Instrument_Main => True, others => False), + At_Most_Once => False, + Internal => True), + Opt_Source_Root => Create (Long_Name => "--source-root", Pattern => "PATH", @@ -900,7 +1059,10 @@ package Command_Line is Pattern => "[GPR|@LISTFILE]", Help => "Focus on specific projects within the transitive" & " closure reachable from the root designated by -P.", - Commands => (Cmd_Setup => False, others => True), + Commands => (Cmd_Setup + | Cmd_Instrument_Source + | Cmd_Instrument_Main => False, + others => True), Internal => False), Opt_Scenario_Var => Create (Short_Name => "-X", @@ -951,8 +1113,8 @@ package Command_Line is | Cmd_Coverage | Cmd_Scan_Decisions | Cmd_Map_Routines - | Cmd_Instrument => True, - others => False), + | Cmd_Instrument_Project => True, + others => False), Internal => False), Opt_SID => Create (Long_Name => "--sid", @@ -960,7 +1122,8 @@ package Command_Line is Help => "Load Source Instrumentation Data from FILE for this" & " operation; or do that for each file listed in" & " LISTFILE.", - Commands => (Cmd_Coverage => True, others => False), + Commands => (Cmd_Coverage | Cmd_Instrument_Source => True, + others => False), Internal => False), Opt_Routines => Create (Long_Name => "--routines", @@ -1042,10 +1205,19 @@ package Command_Line is & " Supports globbing patterns.", Commands => (Cmd_Coverage | Cmd_Map_Routines - | Cmd_Instrument => True, - others => False), + | Cmd_Instrument_Project => True, + others => False), Internal => False), + Opt_Files => Create + (Long_Name => "--files", + Pattern => "[FILE|@LISTFILE]", + Help => "Specify a list of source files of interest by their" + & " full name.", + Commands => (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + Internal => True), + Opt_Shared_Object => Create (Long_Name => "--shared-object", Short_Name => "-L", @@ -1070,12 +1242,13 @@ package Command_Line is (Long_Name => "--restricted-to-languages", Pattern => "[LANGUAGE|LIST|@LISTFILE]", Help => - "Restrict the set of languages for instrumentation. Supports Ada" - & " and C. As C support is still in beta state, the default is" - & " --restricted-to-languages=Ada. To enable both, pass" - & " --restricted-to-languages=Ada,C.", - Commands => (Cmd_Setup | Cmd_Instrument => True, - others => False), + "Restrict the set of languages for instrumentation. Supports Ada, C" + & " and C++. As C++ support is still in beta state, the default is" + & " --restricted-to-languages=Ada,C. To enable C++, pass" + & " --restricted-to-languages=Ada,C,C++.", + Commands => (Cmd_Setup + | Cmd_Instrument_Project => True, + others => False), Internal => False, Accepts_Comma_Separator => True), Opt_Annotation_Format => Create @@ -1109,7 +1282,17 @@ package Command_Line is "List of additional compiler switches to analayze C++ source" & " files.", Commands => (Cmd_Instrument => True, others => False), - Internal => False) + Internal => False), + + Opt_Runtime_Dir => Create + (Long_Name => "--runtime-dir", + Pattern => "NAME", + Help => + "Directories containing the compiler runtime sources.", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + Internal => True) ); procedure Bool_Callback diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 58527f599..1d1383175 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -20,8 +20,8 @@ with Ada.Characters.Latin_1; 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.Strings.Fixed; with Ada.Strings.Unbounded; with Ada.Tags; with Ada.Unchecked_Deallocation; @@ -221,26 +221,11 @@ package body Coverage.Source is -- 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 => Project_Unit, Element_Type => Ignored_Sources_Vector_Access); - -- Map units of interest to the list of associated ignored source files + (Key_Type => Compilation_Unit, + Element_Type => Ignored_Sources_Vector_Access); Ignored_SF_Map : Unit_To_Ignored_Maps.Map; - - function Unit_Name_For_Subunit (Qualified_Name : String) return String; - -- Return the unit name for the subunit whose name is Qualified_Name. - -- For instance, if foo-test.adb is a subunit for package Foo, - -- GNATCOLL.Projects should give us Foo.Test as a unit name, and this - -- function will return Foo. - -- - -- As a safeguard, this checks that the result is the name of a unit of - -- interest: subunits cannot be units of interest. - -- - -- If it can't be determined that the source file belongs to a unit of - -- interest, the empty string will be returned, and a warning will be - -- emitted. - -- - -- Note that the Ada language rules guarantee that the name of the owning - -- unit is a prefix of the name of its subunits. + -- Map units of interest to the list of associated ignored source files -------------------------- -- Basic_Block_Has_Code -- @@ -283,54 +268,13 @@ package body Coverage.Source is -- Add_Unit -- -------------- - procedure Add_Unit (Unit : Project_Unit) is + procedure Add_Unit (Unit : Compilation_Unit) is begin if not Unit_List_Invalidated then Unit_List.Include (Unit); end if; end Add_Unit; - --------------------------- - -- Unit_Name_For_Subunit -- - --------------------------- - - function Unit_Name_For_Subunit (Qualified_Name : String) return String - is - use Ada.Strings.Fixed; - First : constant Natural := Qualified_Name'First; - Sep : Natural := Qualified_Name'Last; - begin - loop - Sep := Index (Source => Qualified_Name, - Pattern => ".", - From => Sep, - Going => Ada.Strings.Backward); - - if Unit_List.Contains - (Project_Unit' - (Language => Unit_Based_Language, - Unit_Name => - US.To_Unbounded_String - (Qualified_Name (First .. Sep - 1)))) - then - return Qualified_Name (First .. Sep - 1); - end if; - exit when Sep = 0; - - -- Move past '.' character to start searching again - - Sep := Sep - 1; - end loop; - - -- If we got here, then there is no unit of interest whose name is a - -- prefix of the name of the subunit we are processing. - - Report (Msg => "Could not find the name of the owning unit of subunit " - & Qualified_Name & " among the units of interest", - Kind => Warning); - return ""; - end Unit_Name_For_Subunit; - ------------------------------------------- -- Compute_Unit_Name_For_Ignored_Sources -- ------------------------------------------- @@ -353,6 +297,7 @@ package body Coverage.Source is (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); @@ -362,26 +307,8 @@ package body Coverage.Source is begin if FI /= null and then not FI.Unit.Known then declare - use type GNATCOLL.Projects.Unit_Parts; - - Language : constant Some_Language := - To_Language (File.Language); - - -- For Ada, get the unit name for the compilation unit (no - -- subunit names). For file-based languages, - -- GNATCOLL.Projects.Unit_Name returns an empty string: we need - -- to get the file base name instead. - - Unit_Name : constant String := - (case Language is - when Ada_Language => - (if File.Unit_Part = GNATCOLL.Projects.Unit_Separate - then Unit_Name_For_Subunit (File.Unit_Name) - else File.Unit_Name), - when others => Get_Simple_Name (SFI)); - - Unit : constant Project_Unit := - To_Project_Unit (Unit_Name, Project, Language); + Unit : constant Compilation_Unit := + To_Compilation_Unit (File); begin Consolidate_Source_File_Unit (SFI, Unit); end; @@ -421,13 +348,6 @@ package body Coverage.Source is if FI.Kind = Source_File and then FI.Ignore_Status in Always .. Sometimes then - -- If FI is a separate (Ada) or a header file (C/C++), it is not a - -- unit of interest itself: only the compilation unit is, so - -- Is_Unit_Of_Interest (FI.Full_Name.all) return False. Still, the - -- unit that owns this file is supposed to be known by now, so it - -- should be valid to access FI.Unit.Name (i.e. FI.Unit.Known - -- should be True). - if not Ignored_SF_Map.Contains (FI.Unit.Name) then Vec := new Ignored_Sources_Vector.Vector; Ignored_SF_Map.Insert (FI.Unit.Name, Vec); @@ -449,7 +369,8 @@ package body Coverage.Source is -------------------------- procedure Iterate_On_Unit_List - (Process_Unit : not null access procedure (Name : Project_Unit); + (Process_Unit : not null access procedure + (Name : Compilation_Unit); Process_Source_File : not null access procedure (FI : File_Info)) is begin @@ -472,7 +393,7 @@ package body Coverage.Source 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 : Project_Unit); + procedure Print_Unit_Name (Unit : Compilation_Unit); -- Print the unit name ------------------------ @@ -492,9 +413,14 @@ package body Coverage.Source is -- Print_Unit_Name -- --------------------- - procedure Print_Unit_Name (Unit : Project_Unit) is + procedure Print_Unit_Name (Unit : Compilation_Unit) is begin - Put_Line (File, +Unit.Unit_Name); + 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 @@ -520,7 +446,7 @@ package body Coverage.Source is if not Unit_List_Invalidated then Ada.Containers.Count_Type'Output (CSS, Unit_List.Length); for N of Unit_List loop - Project_Unit'Output (CSS, N); + Compilation_Unit'Output (CSS, N); end loop; end if; end if; @@ -674,7 +600,7 @@ package body Coverage.Source is end if; US.Unbounded_String'Read (CLS, Dummy); else - Unit_List.Include (Project_Unit'Input (CLS)); + Unit_List.Include (Compilation_Unit'Input (CLS)); end if; end loop; end if; @@ -1781,7 +1707,7 @@ package body Coverage.Source is procedure Compute_Source_Coverage (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 1f0968fa2..38c2b903e 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -52,7 +52,7 @@ package Coverage.Source is procedure Compute_Source_Coverage (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; @@ -104,7 +104,7 @@ package Coverage.Source is -- message is used for logging purposes, so that users can find out why we -- cannot dump the list of units of interest. - procedure Add_Unit (Unit : Project_Unit); + procedure Add_Unit (Unit : Compilation_Unit); -- Add Unit to the list of units of interest. For convenience, do nothing -- if it is invalid. @@ -117,7 +117,8 @@ package Coverage.Source is -- unit names, linking them to the list of ignored source files. procedure Iterate_On_Unit_List - (Process_Unit : not null access procedure (Name : Project_Unit); + (Process_Unit : not null access procedure + (Name : Compilation_Unit); Process_Source_File : not null access procedure (FI : File_Info)) with Pre => Unit_List_Is_Valid; -- Call Process_Unit for each unit of interest, passing to it the name of diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 050504b88..4bd99d7a8 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -621,7 +621,7 @@ package body Files_Table is ---------------------------------- procedure Consolidate_Source_File_Unit - (Index : Valid_Source_File_Index; New_Unit : Project_Unit) + (Index : Valid_Source_File_Index; New_Unit : Compilation_Unit) is use Ada.Strings.Unbounded; FI : File_Info renames Files_Table.Element (Index).all; @@ -1890,7 +1890,7 @@ package body Files_Table is Any_Ignore_Status'Write (S, FI.Ignore_Status); Boolean'Write (S, FI.Unit.Known); if FI.Unit.Known then - Project_Unit'Output (S, FI.Unit.Name); + Compilation_Unit'Output (S, FI.Unit.Name); end if; end if; end; @@ -2042,7 +2042,7 @@ package body Files_Table is if Unit_Known then -- Starting with the version 13 of checkpoints, - -- owning units are represented as Project_Unit + -- owning units are represented as Compilation_Unit -- values (they were mere strings before). Consider -- the owning unit unknown if we do not have recent -- formats. @@ -2055,7 +2055,7 @@ package body Files_Table is end; else FE.Unit := (Known => True, - Name => Project_Unit'Input (S)); + Name => Compilation_Unit'Input (S)); end if; end if; end; diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 729aea7ee..9a9aafb29 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -305,46 +305,37 @@ package Files_Table is -- option --ignore-source-files. Consolidation rules are described in -- procedure Consolidate_Ignore_Status. - type Project_Unit (Language : Any_Language_Kind := Unit_Based_Language) - is record + type Compilation_Unit is record + Language : Any_Language_Kind; Unit_Name : Ada.Strings.Unbounded.Unbounded_String; - - case Language is - when File_Based_Language => - Project_Name : Ada.Strings.Unbounded.Unbounded_String; - when others => - null; - end case; end record; - -- To uniquely identify a unit in a project tree, we need its unit name (or - -- base name for a C unit). For file-based languages such as C or C++, we - -- might have homonym base file names in different projects so we keep - -- track of the project name in addition. + -- This record is used to uniquely identify a unit of any language + -- supported by gnatcov. The unique identifier, stored as Unit_Name is + -- the unit name for unit-based language, and the file fullname for + -- file-based languages. use type Ada.Strings.Unbounded.Unbounded_String; - function Image (U : Project_Unit) return String is + function Image (U : Compilation_Unit) return String is (case U.Language is when Unit_Based_Language => To_Lower (Ada.Strings.Unbounded.To_String (U.Unit_Name)), when File_Based_Language => - Ada.Strings.Unbounded.To_String (U.Project_Name) - & ":" - & Fold_Filename_Casing - (Ada.Strings.Unbounded.To_String (U.Unit_Name))); + Fold_Filename_Casing + (Ada.Strings.Unbounded.To_String (U.Unit_Name))); - function "<" (L, R : Project_Unit) return Boolean is + function "<" (L, R : Compilation_Unit) return Boolean is (Image (L) < Image (R)); - function "=" (L, R : Project_Unit) return Boolean is + function "=" (L, R : Compilation_Unit) return Boolean is (Image (L) = Image (R)); package Unit_Sets is new Ada.Containers.Ordered_Sets - (Element_Type => Project_Unit); + (Element_Type => Compilation_Unit); type Owning_Unit (Known : Boolean := False) is record case Known is - when True => Name : Project_Unit; + when True => Name : Compilation_Unit; when False => null; end case; end record; @@ -466,7 +457,7 @@ package Files_Table is (Index : Source_File_Index) return File_Info_Access; procedure Consolidate_Source_File_Unit - (Index : Valid_Source_File_Index; New_Unit : Project_Unit) + (Index : Valid_Source_File_Index; New_Unit : Compilation_Unit) with Pre => Get_File (Index).Kind = Source_File; -- Update the unit name info for the source file represented by Index. -- Does nothing if the new unit name is the empty string. diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 2d85786dc..4953f453c 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -27,6 +27,8 @@ with GNAT.OS_Lib; with GNAT.Regexp; with GNAT.Strings; use GNAT.Strings; +with System.Multiprocessors; + with Snames; with ALI_Files; @@ -54,10 +56,14 @@ with Decision_Map; use Decision_Map; with Disassemble_Insn_Properties; with Execs_Dbase; use Execs_Dbase; with Files_Table; use Files_Table; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Inputs; use Inputs; +with Instrument; +with Instrument.Common; use Instrument.Common; +with Instrument.Config; +with Instrument.Main; +with Instrument.Projects; +with Instrument.Source; with Instrument.Input_Traces; -with Instrument; use Instrument; with Object_Locations; with Outputs; use Outputs; with Perf_Counters; @@ -98,6 +104,7 @@ procedure GNATcov_Bits_Specific is Checkpoints_Inputs : Inputs.Inputs_Type; SID_Inputs : Inputs.Inputs_Type; Ignored_Source_Files : Inputs.Inputs_Type; + Files_Of_Interest : Inputs.Inputs_Type; Source_Rebase_Inputs : Inputs.Inputs_Type; Source_Search_Inputs : Inputs.Inputs_Type; Text_Start : Pc_Type := 0; @@ -481,6 +488,8 @@ procedure GNATcov_Bits_Specific is Copy_Arg_List (Opt_Checkpoint, Checkpoints_Inputs); Copy_Arg_List (Opt_Ignore_Source_Files, Ignored_Source_Files); + Copy_Arg_List (Opt_Files, Files_Of_Interest); + Switches.Files_Of_Interest := To_String_Set (Files_Of_Interest); -- Compute the languages for which we want coverage analysis, or enable -- just the default ones. @@ -1029,6 +1038,32 @@ procedure GNATcov_Bits_Specific is Copy_Arg_List (Opt_C_Opts, C_Opts); Copy_Arg_List (Opt_CPP_Opts, CPP_Opts); + if Args.String_Args (Opt_Parallelism_Level).Present then + declare + Parallelism_Level : Natural; + begin + begin + Parallelism_Level := + Natural'Value + (+Args.String_Args (Opt_Parallelism_Level).Value); + exception + when Constraint_Error => + Fatal_Error ("Parallelism level (-j or --jobs)" + & " must be a natural integer value"); + end; + + -- Limit the number of spawned subprocesses to the number + -- of cores. + + if Parallelism_Level = 0 then + Instrument.Parallelism_Level := + Positive (System.Multiprocessors.Number_Of_CPUs); + else + Instrument.Parallelism_Level := Parallelism_Level; + end if; + end; + end if; + when others => null; end case; @@ -1260,7 +1295,7 @@ begin Gargs => Args.String_List_Args (Opt_Gargs)); end; - when Cmd_Instrument => + when Cmd_Instrument_Project => if not Is_Project_Loaded then Fatal_Error ("instrumentation requires a project file;" & " please use the -P option"); @@ -1287,10 +1322,8 @@ begin -- Matcher for the source files to ignore Language_Version : Any_Language_Version; + pragma Unreferenced (Language_Version); - Mains : String_Vectors.Vector renames Args.Remaining_Args; - -- Treat remaining command line arguments as a list of source - -- files to be processed as mains. begin Create_Matcher (Ignored_Source_Files, Matcher, Has_Matcher); @@ -1322,30 +1355,62 @@ begin ("(selected runtime from " & (+Setup_Cfg.Project_File) & ")"); end if; - -- Even though instrumentation does not create any traces, the - -- structure of a SID file is basically a checkpoint, so it has a - -- Trace_Kind field in its header. Instead of leaving it to - -- Unknown (default value) mark it as Source_Trace_File so that - -- when the .sid file is loaded, it will set gnatcov in - -- "source trace mode" and it will be rejected if binary traces - -- have already been loaded. - - Update_Current_Trace_Kind (Source_Trace_File); - if Analyze_Entry_Barriers then Warn ("With source traces, entry barrier analysis (enabled" & " with --analyze-entry-barriers) is only supported when" & " when using a full runtime profile. In particular," - & " enabeling this option with a ravenscar profile will" + & " enabling this option with a ravenscar profile will" & " result in invalid code being emitted."); end if; - Instrument.Instrument_Units_Of_Interest + Instrument.Projects (Dump_Config => Dump_Config, - Language_Version => Language_Version, Ignored_Source_Files => (if Has_Matcher then Matcher'Access else null), - Mains => Mains); + Mains => Args.Remaining_Args); + end; + + when Cmd_Instrument_Source => + -- For the instrument-source command, and for the instrument-main, + -- we do not check the command-line semantics as these commands are + -- internal and spawned by a gnatcov main process. They are thus by + -- default well-formed, and if they are not, it is a gnatcov bug. + -- + -- The unit to instrument is the trailing argument + + declare + Instrumenter : Language_Instrumenter'Class := Instrument.Config; + begin + Instrument.Source + (Instrumenter => Instrumenter, + Files_Of_Interest => Switches.Files_Of_Interest, + Prj => Instrument.Load_From_Command_Line, + Unit_Name => +Args.Remaining_Args.First_Element, + SID_Name => + +Args.String_List_Args (Opt_SID).First_Element); + end; + + when Cmd_Instrument_Main => + declare + -- The dump config is loaded from the command line. The + -- implementation of the main instrumentation process assumes that + -- it is fully explicited, i.e. that nothing is left as default. + + Dump_Config : constant Any_Dump_Config := + Load_Dump_Config (Any_Dump_Config'(others => <>)); + + -- Trailing argument is the main to instrument + + Main_Filename : constant String := + +Args.Remaining_Args.First_Element; + + Instrumenter : Language_Instrumenter'Class := Instrument.Config; + begin + Instrument.Main + (Instrumenter, + Dump_Config, + Main_Filename, + Instrument.Load_From_Command_Line); end; when Cmd_Scan_Objects => @@ -1694,27 +1759,9 @@ begin Check_User_Provided_SCOs; - -- Build the list of units of interest from project files option - - declare - procedure Add_Unit (Unit : Project_Unit; Is_Stub : Boolean); - -- Add Name to the list of names for units of interest. Do nothing - -- if this is a stub for a unit-based language, since such stubs - -- are implicitly part of another unit of interest. - - -------------- - -- Add_Unit -- - -------------- + -- Build the list of units of interest from project files - procedure Add_Unit (Unit : Project_Unit; Is_Stub : Boolean) is - begin - if not Is_Stub or else Unit.Language = File_Based_Language then - Add_Unit (Unit); - end if; - end Add_Unit; - begin - Enumerate_Units_Of_Interest (Add_Unit'Access); - end; + Enumerate_Units_Of_Interest (Add_Unit'Access); -- Load routines from command line diff --git a/tools/gnatcov/inputs.adb b/tools/gnatcov/inputs.adb index 300aac1cd..2b4072985 100644 --- a/tools/gnatcov/inputs.adb +++ b/tools/gnatcov/inputs.adb @@ -262,6 +262,22 @@ package body Inputs is return Res; end To_String_Vector; + ------------------- + -- To_String_Set -- + ------------------- + + function To_String_Set + (Inputs : Inputs_Type) return String_Sets.Set + is + use String_Sets; + Res : Set; + begin + for IE of Inputs loop + Res.Include (+IE.Name.all); + end loop; + return Res; + end To_String_Set; + -------------------- -- Create_Matcher -- -------------------- diff --git a/tools/gnatcov/inputs.ads b/tools/gnatcov/inputs.ads index b53251ec3..3aa804365 100644 --- a/tools/gnatcov/inputs.ads +++ b/tools/gnatcov/inputs.ads @@ -79,6 +79,10 @@ package Inputs is (Inputs : Inputs_Type) return String_Vectors.Vector; -- Convert an inputs list into a String_Vectors.Vector + function To_String_Set + (Inputs : Inputs_Type) return String_Sets.Set; + -- Convert an inputs list into a String_Sets.Set + procedure Create_Matcher (Pattern_List : String_Vectors.Vector; Matcher : out GNAT.Regexp.Regexp; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index ea66d01b5..e465b3721 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -18,14 +18,14 @@ with Ada.Characters.Conversions; use Ada.Characters.Conversions; with Ada.Characters.Handling; -with Ada.Containers; use Ada.Containers; with Ada.Directories; +with Ada.Containers; use Ada.Containers; with Ada.Exceptions; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Wide_Wide_Fixed; pragma Warnings (Off, "* is an internal GNAT unit"); with Ada.Strings.Wide_Wide_Unbounded.Aux; pragma Warnings (On, "* is an internal GNAT unit"); +with Ada.Text_IO; use Ada.Text_IO; with Langkit_Support; with Langkit_Support.Slocs; use Langkit_Support.Slocs; @@ -39,18 +39,14 @@ use Libadalang.Generic_API.Introspection; with Libadalang.Sources; use Libadalang.Sources; with GNATCOLL.Utils; -with GNATCOLL.VFS; with ALI_Files; use ALI_Files; with Coverage_Options; use Coverage_Options; with Coverage; use Coverage; with Diagnostics; use Diagnostics; -with Files_Table; use Files_Table; -with Instrument.Ada_Unit_Provider; with Namet; use Namet; with Outputs; use Outputs; with Paths; use Paths; -with Project; with SCOs; with Slocs; with Snames; use Snames; @@ -104,6 +100,14 @@ package body Instrument.Ada_Unit is -- Import the low level SCO in UIC marked as non-instrumented in the high -- level non-instrumented SCO_Id sets. + procedure Find_Ada_Units + (Instrumenter : in out Ada_Instrumenter_Type; + Filename : String; + Process_Unit : access procedure (Filename : String)); + -- Consider that Filename is a source file to instrument (i.e. a unit of + -- interest) and call Process_Unit for all compilation units that must be + -- instrumented with it (i.e. related subunits, if present). + ----------------------- -- To_Qualified_Name -- ----------------------- @@ -919,7 +923,7 @@ package body Instrument.Ada_Unit is function Has_Matching_Pragma_For_Unit (Context : Analysis_Context; - Unit : Compilation_Unit; + Unit : LAL.Compilation_Unit; Filter : access function (Node : Pragma_Node) return Boolean) return Boolean; -- Return whether Filter return True on at least one configuration pragma @@ -930,12 +934,18 @@ package body Instrument.Ada_Unit is -- to get the analysis unit for System. Used to avoid emitting duplicate -- messages. + function Has_Unit + (Context : Analysis_Context; + Unit : String; + Part : Analysis_Unit_Kind) return Boolean; + -- Return whether the given unit exists + function Pragma_Restricts_Finalization (Prag_Node : Pragma_Node) return Boolean; -- Return True if Prag_Node imposes a restrictions on use of finalization function Finalization_Restricted_In_Unit - (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean; + (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean; -- Return True if Finalization is not available in this runtime, or if -- some control pragma restricts the usage of finalization in either Unit -- or the whole project. @@ -946,7 +956,7 @@ package body Instrument.Ada_Unit is -- Ada.Task_Termination and/or Ada.Task_Identification. function Task_Termination_Restricted - (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean; + (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean; -- Return True if tasking is not available in this runtime, or if some -- configuration pragma prevents the use of tasks and/or -- Ada.Task_Termination and/or Ada.Task_Identification in either the whole @@ -1033,7 +1043,8 @@ package body Instrument.Ada_Unit is -- to perform semantic analysis (so mandated by Ada), but which are not -- available. - procedure Create_LAL_Context (Instrumenter : in out Ada_Instrumenter_Type); + procedure Create_LAL_Context + (Instrumenter : in out Ada_Instrumenter_Type'Class); -- Create a new Libadalang analysis context for Instrumenter, assigning it -- to Instrumenter.Context. -- @@ -1043,7 +1054,7 @@ package body Instrument.Ada_Unit is -- used to instrument any source file yet. function Get_From_File - (Instrumenter : in out Ada_Instrumenter_Type; + (Instrumenter : in out Ada_Instrumenter_Type'Class; Filename : String) return Libadalang.Analysis.Analysis_Unit; -- Fetch the analysis unit for the given filename @@ -1065,8 +1076,8 @@ package body Instrument.Ada_Unit is procedure Start_Rewriting (Self : out Ada_Source_Rewriter'Class; - Instrumenter : in out Ada_Instrumenter_Type; - Info : in out Project_Info; + Instrumenter : in out Ada_Instrumenter_Type'Class; + Prj : Prj_Desc; Input_Filename : String); -- Start a rewriting session for the given Input_Filename. If the rewriting -- process is successful, the result will be written to a file in @@ -1113,22 +1124,17 @@ package body Instrument.Ada_Unit is -- the very beginning of each written source, these pragmas avoid this. procedure Initialize_Rewriting - (Instrumenter : Ada_Instrumenter_Type; - UIC : out Ada_Unit_Inst_Context; - Instrumented_Unit : Compilation_Unit_Name); + (UIC : in out Ada_Unit_Inst_Context; + Instrumenter : Ada_Instrumenter_Type'Class); -- Initialize a unit instrumentation context for the given unit to -- instrument. procedure Instrument_Source_File - (CU_Name : Compilation_Unit_Name; - Unit_Info : Instrumented_Unit_Info; - Prj_Info : in out Project_Info; + (UIC : in out Ada_Unit_Inst_Context; + Filename : String; Instrumenter : in out Ada_Instrumenter_Type; - UIC : out Ada_Unit_Inst_Context); - -- Generate the instrumented source corresponding to CU_Name/Unit_Info. - -- - -- If the unit to instrument is also a main and the buffers dump trigger - -- is not manual, instrumented code will also dump the coverage buffers. + Prj : Prj_Desc); + -- Generate the instrumented source corresponding to Filename ---------------------------------- -- Main instrumentation helpers -- @@ -1139,7 +1145,7 @@ package body Instrument.Ada_Unit is type Main_Instrumentation_Description (Synthetic : Boolean := False) is record - Main : Compilation_Unit_Name; + Main : Compilation_Unit_Part; -- Name of the compilation unit corresponding to the main body Controlled_Types_Available : Boolean; @@ -1178,8 +1184,8 @@ package body Instrument.Ada_Unit is -- subprogram instantiation (Synthetic => True). function Probe_Main - (Dump_Config : Any_Dump_Config; - Info : in out Project_Info; + (Prj : Prj_Desc; + Dump_Config : Any_Dump_Config; Rewriter : Ada_Source_Rewriter'Class) return Main_Instrumentation_Description; -- Given a rewriter for the main source, return a description of the main @@ -1195,7 +1201,7 @@ package body Instrument.Ada_Unit is procedure Expand_Main_Generic_Instantiation (Main : Generic_Subp_Instantiation; - Info : in out Project_Info; + Prj : Prj_Desc; Generic_Wrapper_Body_Filename : out Unbounded_String; Generic_Wrapper_Body : out Node_Rewriting_Handle; Prelude : out Node_Rewriting_Handle; @@ -1272,35 +1278,57 @@ package body Instrument.Ada_Unit is function Buffers_List_Unit (Project_Name : String) return Ada_Qualified_Name; -- Returns the name of the unit containing the array of coverage buffers. - -- It is named after the root project name (e.g. if the root project is - -- p.gpr, its name is .). + -- It is named after the given project main name (e.g. if the + -- project p.gpr, its name is .). + + function Buffer_Unit + (Unit_Name : Ada_Qualified_Name) return Ada_Qualified_Name; + -- Given a file to instrument, return the name of the unit that holds + -- its coverage buffers (Coverage_Buffer_Type and + -- GNATcov_RTS_Coverage_Buffers records). function Pure_Buffer_Unit - (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name; + (Unit_Name : Ada_Qualified_Name) return Ada_Qualified_Name; -- Given a unit to instrument, return the name of the unit that holds -- addresses to its coverage buffers. procedure Emit_Buffer_Unit - (Info : in out Project_Info; UIC : Ada_Unit_Inst_Context'Class); + (Buffer_Unit : Compilation_Unit_Part; + Prj : Prj_Desc; + Unit : Files_Table.Compilation_Unit; + Unit_Bits : Allocated_Bits_Vectors.Vector; + CU_Names : CU_Name_Vectors.Vector; + CUs : CU_Id_Vectors.Vector); -- Emit the unit to contain coverage buffers for the given instrumented -- unit. procedure Emit_Pure_Buffer_Unit - (Info : in out Project_Info; UIC : Ada_Unit_Inst_Context'Class); - -- Emit the unit to contain addresses for the coverage buffers + (PB_Unit : Compilation_Unit_Part; + Prj : Prj_Desc; + CU_Names : CU_Name_Vectors.Vector; + Language_Version : Unbounded_Wide_Wide_String; + Degenerate_Subprogram_Generics : Generic_Subp_Vectors.Vector); + -- Emit the unit to contain addresses for the coverage buffers of all of + -- the compilation unit parts in CU_Names. PB_Unit holds the name of + -- the pure buffer unit, which is generated in the output dir specified in + -- the project description Prj. + -- + -- See the documentation of the eponym fields of the Ada_Unit_Inst_Context + -- record for the Language_Version and Degenerate_Subprogram_Generics + -- parameters. procedure Emit_Dump_Helper_Unit (Dump_Config : Any_Dump_Config; - Info : in out Project_Info; - Main_Filename : String; - Main : Compilation_Unit_Name; + Instrumenter : Ada_Instrumenter_Type'Class; + Prj : Prj_Desc; + Main : Compilation_Unit_Part; Helper_Unit : out Ada_Qualified_Name; Override_Dump_Trigger : Any_Dump_Trigger := Manual; Has_Controlled : Boolean := False); -- Emit the unit to contain helpers to implement the automatic dump of - -- coverage buffers for the given Main unit implemented in Main_Filename. - -- Info must be the project that owns this main. Upon return, the name of - -- this helper unit is stored in Helper_Unit. + -- coverage buffers for the given Main unit. Prj must contain information + -- about the project that owns this main. Upon return, the name of this + -- helper unit is stored in Helper_Unit. -- -- If Override_Dump_Trigger is anything other than Manual, it will be used -- as a dump trigger instead of the one defined in IC.Dump_Config. @@ -4239,7 +4267,7 @@ package body Instrument.Ada_Unit is when Ada_Compilation_Unit => declare - CUN : constant Compilation_Unit := + CUN : constant LAL.Compilation_Unit := N.As_Compilation_Unit; CUN_Body : constant Ada_Node := CUN.F_Body; Is_Subunit : constant Boolean := @@ -4325,14 +4353,23 @@ package body Instrument.Ada_Unit is -- corresponding unit that contains coverage buffers. declare - Buffers_Unit : constant Node_Rewriting_Handle := To_Nodes - (UIC.Rewriting_Context, UIC.Pure_Buffer_Unit.Unit); - With_Clause : constant Node_Rewriting_Handle := + Buffers_Unit : constant Node_Rewriting_Handle := + To_Nodes + (UIC.Rewriting_Context, UIC.Pure_Buffer_Unit.Unit); + With_Buffers_Clause : constant Node_Rewriting_Handle := + Create_From_Template + (UIC.Rewriting_Context, "with {};", + (1 => To_Nodes + (UIC.Rewriting_Context, Sys_Buffers)), + With_Clause_Rule); + With_PB_Clause : constant Node_Rewriting_Handle := Create_From_Template (UIC.Rewriting_Context, "with {};", (1 => Buffers_Unit), With_Clause_Rule); begin - Append_Child (Handle (CUN.F_Prelude), With_Clause); + Append_Child (Handle (CUN.F_Prelude), + With_Buffers_Clause); + Append_Child (Handle (CUN.F_Prelude), With_PB_Clause); end; end; @@ -6484,14 +6521,14 @@ package body Instrument.Ada_Unit is procedure Start_Rewriting (Self : out Ada_Source_Rewriter'Class; - Instrumenter : in out Ada_Instrumenter_Type; - Info : in out Project_Info; + Instrumenter : in out Ada_Instrumenter_Type'Class; + Prj : Prj_Desc; Input_Filename : String) is Base_Filename : constant String := Ada.Directories.Simple_Name (Input_Filename); Output_Filename : constant String := - To_String (Info.Output_Dir) / Base_Filename; + New_File (Prj, Base_Filename); Unit : constant Analysis_Unit := Get_From_File (Instrumenter, Input_Filename); begin @@ -6562,22 +6599,23 @@ package body Instrument.Ada_Unit is declare Source_Name : constant String := To_String (N); begin - if GNATCOLL.Utils.Starts_With (Source_Name, "gnatcov_rts") then - return; + if not (GNATCOLL.Utils.Starts_With (Source_Name, "gnatcov_rts") + or else GNATCOLL.Utils.Starts_With (Source_Name, "gcvrt")) + then + -- If we have not done it yet, clarify which file we were + -- instrumenting when we noticed that the source file N was + -- missing. + + if Length (Self.Instrumented_File) > 0 then + Warn ("While instrumenting " + & To_String (Self.Instrumented_File) + & "..."); + Self.Instrumented_File := Null_Unbounded_String; + end if; + + Warn ("Cannot find required source file: " & Source_Name); end if; end; - - -- If we have not done it yet, clarify which file we were - -- instrumenting when we noticed that the source file N was missing. - - if Length (Self.Instrumented_File) > 0 then - Warn ("While instrumenting " - & To_String (Self.Instrumented_File) - & "..."); - Self.Instrumented_File := Null_Unbounded_String; - end if; - - Warn ("Cannot find required source file: " & To_String (N)); end; end Unit_Requested_Callback; @@ -6597,48 +6635,33 @@ package body Instrument.Ada_Unit is -- Create_LAL_Context -- ------------------------ - procedure Create_LAL_Context (Instrumenter : in out Ada_Instrumenter_Type) - is + procedure Create_LAL_Context + (Instrumenter : in out Ada_Instrumenter_Type'Class) is begin Instrumenter.Context := Create_Context - (Unit_Provider => Instrumenter.Provider, + (Unit_Provider => + Create_Unit_Provider_Reference (Instrumenter.Provider), Event_Handler => Instrumenter.Event_Handler); Instrumenter.Get_From_File_Count := 0; - -- Load configuration pragmas - -- TODO??? Remove the type convertion when the LAL API change for - -- VA07-037 makes it into stable-libadalang. + -- Load configuration pragmas. TODO???: clarify what happens when there + -- is a local configuration pragma file. - Libadalang.Config_Pragmas.Import_From_Project + Libadalang.Config_Pragmas.Set_Mapping (Instrumenter.Context, - GNATCOLL.Projects.Project_Tree (Project.Project.all)); + Libadalang.Config_Pragmas.Config_Pragmas_Mapping' + (Global_Pragmas => + Instrumenter.Context.Get_From_File + (+Instrumenter.Config_Pragmas_Filename), + others => <>)); end Create_LAL_Context; - ----------------------------- - -- Create_Ada_Instrumenter -- - ----------------------------- - - function Create_Ada_Instrumenter - (Language_Version : Any_Language_Version) return Ada_Instrumenter_Type - is - Provider : constant Unit_Provider_Reference := - Instrument.Ada_Unit_Provider.Create_Provider_From_Project; - - Instrumenter : Ada_Instrumenter_Type; - begin - Instrumenter.Provider := Provider; - Instrumenter.Event_Handler := Create_Missing_File_Reporter; - Create_LAL_Context (Instrumenter); - Instrumenter.Language_Version := Language_Version; - return Instrumenter; - end Create_Ada_Instrumenter; - ------------------- -- Get_From_File -- ------------------- function Get_From_File - (Instrumenter : in out Ada_Instrumenter_Type; + (Instrumenter : in out Ada_Instrumenter_Type'Class; Filename : String) return Libadalang.Analysis.Analysis_Unit is begin @@ -6670,33 +6693,50 @@ package body Instrument.Ada_Unit is -------------------------- procedure Initialize_Rewriting - (Instrumenter : Ada_Instrumenter_Type; - UIC : out Ada_Unit_Inst_Context; - Instrumented_Unit : Compilation_Unit_Name) is + (UIC : in out Ada_Unit_Inst_Context; + Instrumenter : Ada_Instrumenter_Type'Class) is begin - UIC.Instrumented_Unit := Instrumented_Unit; - UIC.Buffer_Unit := - CU_Name_For_Unit (Buffer_Unit (Instrumented_Unit), GPR.Unit_Spec); - UIC.Pure_Buffer_Unit := - CU_Name_For_Unit (Pure_Buffer_Unit (Instrumented_Unit), GPR.Unit_Spec); UIC.Rewriting_Context := Handle (Instrumenter.Context); declare RH : constant Rewriting_Handle := UIC.Rewriting_Context; E : Instrumentation_Entities renames UIC.Entities; + + function Indexed_Buffer + (Buffer_Kind : Ada_Qualified_Name) return Node_Rewriting_Handle; + -- Suffix Buffer_Kind with the buffer index for the currently + -- instrumented source file. See the comment for the package + -- Allocated_Bits_Vectors in Instrument.Common for more information. + + -------------------- + -- Indexed_Buffer -- + -------------------- + + function Indexed_Buffer + (Buffer_Kind : Ada_Qualified_Name) return Node_Rewriting_Handle + is + Buffer : constant Ada_Qualified_Name := + To_Qualified_Name ("Buffers_" & Img (E.Buffers_Index)) + & Buffer_Kind; + begin + return Create_From_Template + (Handle => RH, + Template => + To_Text (To_Ada (UIC.Pure_Buffer_Unit.Unit & Buffer)), + Arguments => (1 .. 0 => No_Node_Rewriting_Handle), + Rule => Expr_Rule); + end Indexed_Buffer; + begin E.Common_Buffers := To_Nodes (RH, Sys_Buffers); E.Unit_Buffers := To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit); - E.Statement_Buffer := - To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit & Statement_Buffer_Name); + E.Statement_Buffer := Indexed_Buffer (Statement_Buffer_Name); if Coverage.Enabled (Decision) or else MCDC_Coverage_Enabled then - E.Decision_Buffer := - To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit & Decision_Buffer_Name); + E.Decision_Buffer := Indexed_Buffer (Decision_Buffer_Name); if MCDC_Coverage_Enabled then - E.MCDC_Buffer := - To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit & MCDC_Buffer_Name); + E.MCDC_Buffer := Indexed_Buffer (MCDC_Buffer_Name); end if; end if; end; @@ -6707,8 +6747,8 @@ package body Instrument.Ada_Unit is ---------------- function Probe_Main - (Dump_Config : Any_Dump_Config; - Info : in out Project_Info; + (Prj : Prj_Desc; + Dump_Config : Any_Dump_Config; Rewriter : Ada_Source_Rewriter'Class) return Main_Instrumentation_Description is @@ -6719,7 +6759,7 @@ package body Instrument.Ada_Unit is Controlled_Types_Available : Boolean; Actual_Dump_Trigger : Auto_Dump_Trigger; - Main : Compilation_Unit_Name (Unit_Based_Language) := + Main : Compilation_Unit_Part (Unit_Based_Language) := (Language_Kind => Unit_Based_Language, Part => Unit_Body, others => <>); @@ -6794,7 +6834,7 @@ package body Instrument.Ada_Unit is begin Expand_Main_Generic_Instantiation (Tmp.As_Generic_Subp_Instantiation, - Info, + Prj, Generic_Wrapper_Body_Filename, Generic_Wrapper_Body, Prelude, @@ -6845,7 +6885,7 @@ package body Instrument.Ada_Unit is procedure Expand_Main_Generic_Instantiation (Main : Generic_Subp_Instantiation; - Info : in out Project_Info; + Prj : Prj_Desc; Generic_Wrapper_Body_Filename : out Unbounded_String; Generic_Wrapper_Body : out Node_Rewriting_Handle; Prelude : out Node_Rewriting_Handle; @@ -6867,7 +6907,7 @@ package body Instrument.Ada_Unit is -- Wrap_Name (, "Prefix") = -- Wrap_Name (, "Prefix") = - Output_Dir : constant String := To_String (Info.Output_Dir); + Output_Dir : constant String := +Prj.Output_Dir; function Filename (Unit_Name : Node_Rewriting_Handle; Extension : String) return String; @@ -6946,7 +6986,7 @@ package body Instrument.Ada_Unit is end case; end Visit; - -- Start of processing for Filenaem + -- Start of processing for Filename begin Visit (Unit_Name); @@ -7222,7 +7262,7 @@ package body Instrument.Ada_Unit is function Has_Matching_Pragma_For_Unit (Context : Analysis_Context; - Unit : Compilation_Unit; + Unit : LAL.Compilation_Unit; Filter : access function (Node : Pragma_Node) return Boolean) return Boolean is @@ -7260,6 +7300,19 @@ package body Instrument.Ada_Unit is end Has_Matching_Pragma_For_Unit; + -------------- + -- Has_Unit -- + -------------- + + function Has_Unit + (Context : Analysis_Context; + Unit : String; + Part : Analysis_Unit_Kind) return Boolean is + begin + return Context.Unit_Provider.Get.Get_Unit_Filename + (To_Text (Unit), Part) /= ""; + end Has_Unit; + ----------------------------------- -- Pragma_Restricts_Finalization -- ----------------------------------- @@ -7302,10 +7355,10 @@ package body Instrument.Ada_Unit is ------------------------------------- function Finalization_Restricted_In_Unit - (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean + (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean is begin - return not Project.Runtime_Supports_Finalization + return not Has_Unit (Context, "Ada.Finalization", Unit_Specification) or else Has_Matching_Pragma_For_Unit (Context, Unit, Pragma_Restricts_Finalization'Access); end Finalization_Restricted_In_Unit; @@ -7360,12 +7413,14 @@ package body Instrument.Ada_Unit is --------------------------------- function Task_Termination_Restricted - (Context : Analysis_Context; Unit : Compilation_Unit) return Boolean + (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean is begin - return not Project.Runtime_Supports_Task_Termination - or else Has_Matching_Pragma_For_Unit - (Context, Unit, Pragma_Prevents_Task_Termination'Access); + return not Has_Unit (Context, "Ada.Task.Termination", Unit_Specification) + or else not Has_Unit + (Context, "Ada.Task.Identification", Unit_Specification) + or else Has_Matching_Pragma_For_Unit + (Context, Unit, Pragma_Prevents_Task_Termination'Access); end Task_Termination_Restricted; ----------- @@ -7524,11 +7579,10 @@ package body Instrument.Ada_Unit is ------------------------------- overriding procedure Auto_Dump_Buffers_In_Main - (Self : in out Ada_Instrumenter_Type; - Filename : String; - Instr_Units : CU_Name_Vectors.Vector; - Dump_Config : Any_Dump_Config; - Info : in out Project_Info) + (Self : in out Ada_Instrumenter_Type; + Filename : String; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc) is Rewriter : Ada_Source_Rewriter; RH : Rewriting_Handle renames Rewriter.Handle; @@ -7538,17 +7592,14 @@ package body Instrument.Ada_Unit is Desc : Main_Instrumentation_Description; begin - if Instr_Units.Is_Empty then - return; - end if; - Start_Rewriting (Rewriter, Self, Info, Filename); + Start_Rewriting (Rewriter, Self, Prj, Filename); -- Try to detect the structure of this main, to determine how to insert -- the dump of coverage buffers. In case of failure, let Probe_Main emit -- a warning and do nothing. begin - Desc := Probe_Main (Dump_Config, Info, Rewriter); + Desc := Probe_Main (Prj, Dump_Config, Rewriter); exception when Cannot_Instrument_Main_Error => return; @@ -7558,8 +7609,8 @@ package body Instrument.Ada_Unit is Emit_Dump_Helper_Unit (Dump_Config, - Info, - Filename, + Self, + Prj, Desc.Main, Helper_Unit, Override_Dump_Trigger => Desc.Actual_Dump_Trigger, @@ -7580,6 +7631,13 @@ package body Instrument.Ada_Unit is Arguments => (1 .. 0 => No_Node_Rewriting_Handle), Rule => With_Clause_Rule); + With_Buffers_Clause : constant Node_Rewriting_Handle := + Create_From_Template + (RH, + Template => "with GNATcov_RTS.Buffers;", + Arguments => (1 .. 0 => No_Node_Rewriting_Handle), + Rule => With_Clause_Rule); + Runtime_Version_Check_Node : constant Node_Rewriting_Handle := Create_From_Template (RH, @@ -7590,6 +7648,7 @@ package body Instrument.Ada_Unit is begin Append_Child (Desc.Prelude, With_Clause); Append_Child (Desc.Prelude, With_RTS_Clause); + Append_Child (Desc.Prelude, With_Buffers_Clause); Append_Child (Desc.Prelude, Runtime_Version_Check_Node); end; @@ -7687,14 +7746,13 @@ package body Instrument.Ada_Unit is ---------------------------- procedure Instrument_Source_File - (CU_Name : Compilation_Unit_Name; - Unit_Info : Instrumented_Unit_Info; - Prj_Info : in out Project_Info; + (UIC : in out Ada_Unit_Inst_Context; + Filename : String; Instrumenter : in out Ada_Instrumenter_Type; - UIC : out Ada_Unit_Inst_Context) + Prj : Prj_Desc) is + CU_Name : Compilation_Unit_Part (Language_Kind => Unit_Based_Language); Rewriter : Ada_Source_Rewriter; - Filename : constant String := To_String (Unit_Info.Filename); Dummy_Ctx : constant Context_Handle := Create_Context ("Instrumenting " & Filename); @@ -7712,7 +7770,7 @@ package body Instrument.Ada_Unit is -- Whether there is a pragma Short_Circuit_And_Or that applies to this -- unit. begin - Start_Rewriting (Rewriter, Instrumenter, Prj_Info, Filename); + Start_Rewriting (Rewriter, Instrumenter, Prj, Filename); Root_Analysis_Unit := Rewriter.Rewritten_Unit; @@ -7721,6 +7779,13 @@ package body Instrument.Ada_Unit is UIC.Root_Unit := Root_Analysis_Unit.Root.As_Compilation_Unit; + CU_Name.Part := + (case UIC.Root_Unit.P_Unit_Kind is + when Unit_Body => Unit_Body, + when Unit_Specification => Unit_Spec); + CU_Name.Unit := To_Qualified_Name + (UIC.Root_Unit.P_Decl.P_Fully_Qualified_Name_Array); + begin Preelab := (UIC.Root_Unit.P_Is_Preelaborable or else UIC.Root_Unit.P_Has_Restriction @@ -7739,7 +7804,22 @@ package body Instrument.Ada_Unit is Preelab := False; end; - Initialize_Rewriting (Instrumenter, UIC, CU_Name); + -- Reset the unit inst context for the currently instrumented source + -- file. + + UIC.Annotations.Clear; + UIC.Current_Scope_Entity := null; + UIC.Degenerate_Subprogram_Index := 0; + UIC.Source_Decisions := Source_Decision_Vectors.Empty; + UIC.Source_Conditions := Source_Condition_Vectors.Empty; + UIC.Unit_Bits.Last_Statement_Bit := No_Bit_Id; + UIC.Unit_Bits.Last_Outcome_Bit := No_Bit_Id; + UIC.Unit_Bits.Last_Path_Bit := No_Bit_Id; + UIC.Unit_Bits.Decision_Bits := LL_Decision_SCO_Bit_Allocs.Empty; + UIC.Unit_Bits.Statement_Bits := LL_Statement_SCO_Bit_Allocs.Empty; + + Initialize_Rewriting (UIC, Instrumenter); + UIC.Instrumented_Unit := CU_Name; begin Has_Pragma_SCAO := UIC.Root_Unit.P_Config_Pragmas @@ -7771,6 +7851,7 @@ package body Instrument.Ada_Unit is (Filename, Kind => Files_Table.Source_File, Indexed_Simple_Name => True); + UIC.Fullname := +Filename; UIC.Unit_Bits.SFI := UIC.SFI; -- Then run SCOs generation. This inserts calls to witness @@ -7945,6 +8026,19 @@ package body Instrument.Ada_Unit is -- Emit the instrumented source file Rewriter.Apply; + + -- Track which CU_Id maps to which instrumented unit + + Instrumented_Unit_CUs.Insert (CU_Name, UIC.CU); + + -- Update the Ignore_Status of the CU we instrumented + + Files_Table.Consolidate_Ignore_Status + (Index => Files_Table.Get_Index_From_Generic_Name + (Name => Filename, + Kind => Files_Table.Source_File, + Indexed_Simple_Name => True), + Status => Files_Table.Never); end Instrument_Source_File; ----------------------- @@ -7958,22 +8052,37 @@ package body Instrument.Ada_Unit is Qualified_Name_Slug (To_Qualified_Name (Project_Name)); begin return Ada_Identifier_Vectors."&" - (Sys_Buffers_Lists, - Instrument.Ada_Identifier (+Project_Name_Slug)); + (Sys_Prefix, Instrument.Ada_Identifier (+Project_Name_Slug)); end Buffers_List_Unit; + ----------------- + -- Buffer_Unit -- + ----------------- + + function Buffer_Unit + (Unit_Name : Ada_Qualified_Name) return Ada_Qualified_Name + is + Simple_Name : Ada_Identifier; + begin + Append (Simple_Name, "B"); + Append (Simple_Name, Ada_Identifier (+Qualified_Name_Slug (Unit_Name))); + return CU_Name : Ada_Qualified_Name := Sys_Prefix do + CU_Name.Append (Simple_Name); + end return; + end Buffer_Unit; + ---------------------- -- Pure_Buffer_Unit -- ---------------------- function Pure_Buffer_Unit - (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name + (Unit_Name : Ada_Qualified_Name) return Ada_Qualified_Name is Simple_Name : Instrument.Ada_Identifier; begin Append (Simple_Name, 'P'); - Append (Simple_Name, Instrumented_Unit_Slug (Instrumented_Unit)); - return CU_Name : Ada_Qualified_Name := Sys_Buffers do + Append (Simple_Name, Ada_Identifier (+Qualified_Name_Slug (Unit_Name))); + return CU_Name : Ada_Qualified_Name := Sys_Prefix do CU_Name.Append (Simple_Name); end return; end Pure_Buffer_Unit; @@ -7983,153 +8092,179 @@ package body Instrument.Ada_Unit is ---------------------- procedure Emit_Buffer_Unit - (Info : in out Project_Info; UIC : Ada_Unit_Inst_Context'Class) + (Buffer_Unit : Compilation_Unit_Part; + Prj : Prj_Desc; + Unit : Files_Table.Compilation_Unit; + Unit_Bits : Allocated_Bits_Vectors.Vector; + CU_Names : CU_Name_Vectors.Vector; + CUs : CU_Id_Vectors.Vector) is - CU_Name : Compilation_Unit_Name renames UIC.Buffer_Unit; - File : Text_Files.File_Type; + Pkg_Name : constant String := To_Ada (Buffer_Unit.Unit); + -- Package name for the buffer unit + + File : Text_Files.File_Type; + Last_Buffer_Index : constant Natural := Natural (Unit_Bits.Length); begin - Create_File (Info, - File, - To_Filename (Info.Project, CU_Name, Switches.Ada_Language)); + Create_File (Prj, File, To_Filename (Prj, Ada_Language, Buffer_Unit)); Put_Warnings_And_Style_Checks_Pragmas (File); File.Put_Line ("with Interfaces.C; use Interfaces.C;"); + File.Put_Line ("with System;"); + File.Put_Line ("with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers;"); File.Put_Line ("with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists;"); - declare - Pkg_Name : constant String := To_Ada (CU_Name.Unit); - -- Package name for the buffer unit - - Fingerprint : Unbounded_String; - -- Fingerprint for the instrumented unit - - Unit_Name : constant String := Ada.Characters.Handling.To_Lower - (To_Ada (UIC.Instrumented_Unit.Unit)); - -- Lower-case name for the instrumented unit - - Unit_Part : constant String := - (case UIC.Instrumented_Unit.Part is - when GPR.Unit_Spec => "Unit_Spec", - when GPR.Unit_Body => "Unit_Body", - when GPR.Unit_Separate => "Unit_Separate"); - -- Do not use 'Image so that we use the original casing for the - -- enumerators, and thus avoid compilation warnings/errors. - - Statement_Last_Bit : constant String := Img - (UIC.Unit_Bits.Last_Statement_Bit); - Decision_Last_Bit : constant String := Img - (UIC.Unit_Bits.Last_Outcome_Bit); - MCDC_Last_Bit : constant String := Img - (UIC.Unit_Bits.Last_Path_Bit); - - begin - -- Turn the fingerprint value into the corresponding Ada literal + File.Put_Line ("package " & Pkg_Name & " is"); + File.New_Line; + File.Put_Line (" pragma Preelaborate;"); + File.New_Line; + for I in 1 .. Last_Buffer_Index loop declare - First : Boolean := True; - begin - Append (Fingerprint, "("); - for Byte of SC_Obligations.Fingerprint (UIC.CU) loop - if First then - First := False; - else - Append (Fingerprint, ", "); - end if; - Append (Fingerprint, Strings.Img (Integer (Byte))); - end loop; - Append (Fingerprint, ")"); - end; + Unit_Bit : constant Allocated_Bits := Unit_Bits.Element (I); + CU_Name : constant Compilation_Unit_Part := CU_Names.Element (I); + CU : constant CU_Id := CUs.Element (I); + + Fingerprint : Unbounded_String; + -- Fingerprint for the instrumented unit + + Unit_Name : constant String := Ada.Characters.Handling.To_Lower + (To_Ada (CU_Name.Unit)); + -- Lower-case name for the instrumented unit + + Unit_Part : constant String := + (case CU_Name.Part is + when GPR.Unit_Spec => "Unit_Spec", + when GPR.Unit_Body => "Unit_Body", + when GPR.Unit_Separate => "Unit_Separate"); + -- Do not use 'Image so that we use the original casing for the + -- enumerators, and thus avoid compilation warnings/errors. + + Statement_Last_Bit : constant String := Img + (Unit_Bit.Last_Statement_Bit); + Decision_Last_Bit : constant String := Img + (Unit_Bit.Last_Outcome_Bit); + MCDC_Last_Bit : constant String := Img + (Unit_Bit.Last_Path_Bit); + + Suffix : constant String := "_" & Img (I); - File.Put_Line ("package " & Pkg_Name & " is"); - File.New_Line; - File.Put_Line (" pragma Preelaborate;"); - File.New_Line; - - -- Create declarations for individual buffers (statement, decision - -- and MC/DC) as well as their exported addresses. - - File.Put_Line (" Statement_Buffer : Coverage_Buffer_Type" - & " (0 .. " & Statement_Last_Bit & ") :=" - & " (others => False);"); - File.Put_Line (" Statement_Buffer_Address : constant System.Address" - & " := Statement_Buffer'Address;"); - File.Put_Line (" pragma Export (C, Statement_Buffer_Address, """ - & Statement_Buffer_Symbol (UIC.Instrumented_Unit) - & """);"); - File.New_Line; + begin + -- Turn the fingerprint value into the corresponding Ada literal - File.Put_Line (" Decision_Buffer : Coverage_Buffer_Type" - & " (0 .. " & Decision_Last_Bit & ") :=" - & " (others => False);"); - File.Put_Line (" Decision_Buffer_Address : constant System.Address" - & " := Decision_Buffer'Address;"); - File.Put_Line (" pragma Export (C, Decision_Buffer_Address, """ - & Decision_Buffer_Symbol (UIC.Instrumented_Unit) - & """);"); - File.New_Line; + declare + First : Boolean := True; + begin + Append (Fingerprint, "("); + for Byte of SC_Obligations.Fingerprint (CU) loop + if First then + First := False; + else + Append (Fingerprint, ", "); + end if; + Append (Fingerprint, Strings.Img (Integer (Byte))); + end loop; + Append (Fingerprint, ")"); + end; - File.Put_Line (" MCDC_Buffer : Coverage_Buffer_Type" - & " (0 .. " & MCDC_Last_Bit & ") :=" - & " (others => False);"); - File.Put_Line (" MCDC_Buffer_Address : constant System.Address" - & " := MCDC_Buffer'Address;"); - File.Put_Line (" pragma Export (C, MCDC_Buffer_Address, """ - & MCDC_Buffer_Symbol (UIC.Instrumented_Unit) - & """);"); - File.New_Line; + -- Create declarations for individual buffers (statement, decision + -- and MC/DC) as well as their exported addresses. Put this in + -- an individual package, to avoid having to suffix each + -- declaration + + File.Put_Line ("package Buffers" & Suffix & " is"); + + File.Put_Line (" Statement_Buffer" + & " : Coverage_Buffer_Type" + & " (0 .. " & Statement_Last_Bit & ") :=" + & " (others => False);"); + File.Put_Line (" Statement_Buffer_Address" + & " : constant System.Address" + & " := Statement_Buffer'Address;"); + File.Put_Line (" pragma Export (C, Statement_Buffer_Address, """ + & Statement_Buffer_Symbol (CU_Name) & Suffix + & """);"); + File.New_Line; - -- Create the GNATcov_RTS_Coverage_Buffers record + File.Put_Line (" Decision_Buffer : Coverage_Buffer_Type" + & " (0 .. " & Decision_Last_Bit & ") :=" + & " (others => False);"); + File.Put_Line (" Decision_Buffer_Address" + & " : constant System.Address" + & " := Decision_Buffer'Address;"); + File.Put_Line (" pragma Export (C, Decision_Buffer_Address, """ + & Decision_Buffer_Symbol (CU_Name) & Suffix + & """);"); + File.New_Line; - File.Put_Line (" Unit_Name : constant String := """ & Unit_Name - & """;"); - File.Put_Line (" Project_Name : constant String := """";"); - File.New_Line; + File.Put_Line (" MCDC_Buffer : Coverage_Buffer_Type" + & " (0 .. " & MCDC_Last_Bit & ") :=" + & " (others => False);"); + File.Put_Line (" MCDC_Buffer_Address : constant System.Address" + & " := MCDC_Buffer'Address;"); + File.Put_Line (" pragma Export (C, MCDC_Buffer_Address, """ + & MCDC_Buffer_Symbol (CU_Name) + & Suffix & """);"); + File.New_Line; - File.Put_Line (" Buffers : aliased constant" - & " GNATcov_RTS_Coverage_Buffers :="); - File.Put_Line - (" (Fingerprint => " - & Format_Fingerprint (SC_Obligations.Fingerprint (UIC.CU)) & ","); + -- Create the GNATcov_RTS_Coverage_Buffers record - File.Put_Line (" Language => Unit_Based_Language,"); - File.Put_Line (" Unit_Part => " & Unit_Part & ","); - File.Put_Line (" Unit_Name =>" - & " (Unit_Name'Address, Unit_Name'Length),"); + File.Put_Line (" Unit_Name : constant String := """ + & Unit_Name & """;"); + File.New_Line; - File.Put_Line (" Project_Name =>" - & " (Project_Name'Address, Project_Name'Length),"); + File.Put_Line (" Buffers : aliased constant" + & " GNATcov_RTS_Coverage_Buffers :="); + File.Put_Line (" (Fingerprint => " + & Format_Fingerprint + (SC_Obligations.Fingerprint (CU)) + & ","); + + File.Put_Line (" Language => Unit_Based_Language,"); + File.Put_Line (" Unit_Part => " & Unit_Part & ","); + File.Put_Line (" Unit_Name =>" + & " (Unit_Name'Address, Unit_Name'Length),"); + + File.Put_Line (" Bit_Maps_Fingerprint => " + & Format_Fingerprint + (SC_Obligations.Bit_Maps_Fingerprint (CU)) + & ","); + + File.Put_Line (" Statement => Statement_Buffer'Address,"); + File.Put_Line (" Decision => Decision_Buffer'Address,"); + File.Put_Line (" MCDC => MCDC_Buffer'Address,"); + + File.Put_Line (" Statement_Last_Bit => " & Statement_Last_Bit + & ","); + File.Put_Line (" Decision_Last_Bit => " & Decision_Last_Bit + & ","); + File.Put_Line (" MCDC_Last_Bit => " & MCDC_Last_Bit & ");"); + File.Put_Line ("end Buffers" & Suffix & ";"); + File.New_Line; + end; + end loop; - File.Put_Line - (" Bit_Maps_Fingerprint => " - & Format_Fingerprint (SC_Obligations.Bit_Maps_Fingerprint (UIC.CU)) - & ","); - - File.Put_Line (" Statement => Statement_Buffer'Address,"); - File.Put_Line (" Decision => Decision_Buffer'Address,"); - File.Put_Line (" MCDC => MCDC_Buffer'Address,"); - - File.Put_Line (" Statement_Last_Bit => " & Statement_Last_Bit - & ","); - File.Put_Line (" Decision_Last_Bit => " & Decision_Last_Bit - & ","); - File.Put_Line (" MCDC_Last_Bit => " & MCDC_Last_Bit & ");"); - File.New_Line; + -- Create the buffers group - -- Create the buffers group + File.Put_Line + (" Buffers_Group : aliased constant Coverage_Buffers_Group :="); + File.Put (" ("); - File.Put_Line - (" Buffers_Group : aliased constant Coverage_Buffers_Group :=" - & " (1 => Buffers'Access);"); - File.Put_Line - (" C_Buffers_Group : aliased constant" - & " GNATcov_RTS_Coverage_Buffers_Group :=" - & " (1, Buffers_Group'Address);"); - File.Put_Line (" pragma Export (C, C_Buffers_Group, """ - & Unit_Buffers_Name (UIC.Instrumented_Unit) & """);"); - File.New_Line; + for I in 1 .. Last_Buffer_Index loop + File.Put (Img (I) & " => Buffers_" & Img (I) & ".Buffers'Access"); + if I /= Last_Buffer_Index then + File.Put_Line (","); + end if; + end loop; + File.Put_Line (");"); + File.Put_Line + (" C_Buffers_Group : aliased constant" + & " GNATcov_RTS_Coverage_Buffers_Group :=" + & " (" & Last_Buffer_Index'Image & ", Buffers_Group'Address);"); + File.Put_Line (" pragma Export (C, C_Buffers_Group, """ + & Unit_Buffers_Name (Unit) & """);"); + File.New_Line; - File.Put_Line ("end " & Pkg_Name & ";"); - end; + File.Put_Line ("end " & Pkg_Name & ";"); end Emit_Buffer_Unit; --------------------------- @@ -8137,11 +8272,14 @@ package body Instrument.Ada_Unit is --------------------------- procedure Emit_Pure_Buffer_Unit - (Info : in out Project_Info; UIC : Ada_Unit_Inst_Context'Class) + (PB_Unit : Compilation_Unit_Part; + Prj : Prj_Desc; + CU_Names : CU_Name_Vectors.Vector; + Language_Version : Unbounded_Wide_Wide_String; + Degenerate_Subprogram_Generics : Generic_Subp_Vectors.Vector) is - - CU_Name : Compilation_Unit_Name := UIC.Pure_Buffer_Unit; - Pkg_Name : constant String := To_Ada (CU_Name.Unit); + Last_Buffer_Index : constant Natural := Natural (CU_Names.Length); + Pkg_Name : constant String := To_Ada (PB_Unit.Unit); File : Text_Files.File_Type; procedure Put_Language_Version_Pragma; @@ -8155,10 +8293,10 @@ package body Instrument.Ada_Unit is procedure Put_Language_Version_Pragma is begin - if Length (UIC.Language_Version_Pragma) > 0 then + if Length (Language_Version) > 0 then File.Put_Line ("pragma " - & To_String (To_Wide_Wide_String (UIC.Language_Version_Pragma)) + & To_String (To_Wide_Wide_String (Language_Version)) & ";"); File.New_Line; end if; @@ -8167,15 +8305,14 @@ package body Instrument.Ada_Unit is -- Start of processing for Emit_Pure_Buffer_Unit begin - Create_File (Info, - File, - To_Filename (Info.Project, CU_Name, Switches.Ada_Language)); + Create_File (Prj, File, To_Filename (Prj, Ada_Language, PB_Unit)); Put_Warnings_And_Style_Checks_Pragmas (File); Put_Language_Version_Pragma; File.Put_Line ("with System;"); File.Put_Line ("with GNATcov_RTS;"); + File.Put_Line ("with GNATcov_RTS.Buffers;"); File.Put_Line (Runtime_Version_Check); File.New_Line; @@ -8183,23 +8320,32 @@ package body Instrument.Ada_Unit is File.New_Line; File.Put_Line (" pragma Pure;"); File.New_Line; - File.Put_Line (" Statement_Buffer : constant System.Address;"); - File.Put_Line (" pragma Import (C, Statement_Buffer, """ - & Statement_Buffer_Symbol (UIC.Instrumented_Unit) - & """);"); - File.New_Line; - File.Put_Line (" Decision_Buffer : constant System.Address;"); - File.Put_Line (" pragma Import (C, Decision_Buffer, """ - & Decision_Buffer_Symbol (UIC.Instrumented_Unit) - & """);"); - File.New_Line; - File.Put_Line (" MCDC_Buffer : constant System.Address;"); - File.Put_Line (" pragma Import (C, MCDC_Buffer, """ - & MCDC_Buffer_Symbol (UIC.Instrumented_Unit) - & """);"); - File.New_Line; + for I in 1 .. Last_Buffer_Index loop + declare + Suffix : constant String := "_" & Img (I); + CU_Name : constant Compilation_Unit_Part := CU_Names.Element (I); + begin + File.Put_Line ("package Buffers" & Suffix & " is"); + File.Put_Line (" Statement_Buffer : constant System.Address;"); + File.Put_Line (" pragma Import (C, Statement_Buffer, """ + & Statement_Buffer_Symbol (CU_Name) & Suffix + & """);"); + File.New_Line; + File.Put_Line (" Decision_Buffer : constant System.Address;"); + File.Put_Line (" pragma Import (C, Decision_Buffer, """ + & Decision_Buffer_Symbol (CU_Name) & Suffix + & """);"); + File.New_Line; + File.Put_Line (" MCDC_Buffer : constant System.Address;"); + File.Put_Line (" pragma Import (C, MCDC_Buffer, """ + & MCDC_Buffer_Symbol (CU_Name) & Suffix & """);"); + File.New_Line; + File.Put_Line ("end Buffers" & Suffix & ";"); + File.New_Line; + end; + end loop; - for G of UIC.Degenerate_Subprogram_Generics loop + for G of Degenerate_Subprogram_Generics loop File.Put_Line (" " & To_String (To_Wide_Wide_String (G.Generic_Subp_Decl))); end loop; @@ -8210,28 +8356,31 @@ package body Instrument.Ada_Unit is Text_Files.Run_GNATpp (File); end if; - if not UIC.Degenerate_Subprogram_Generics.Is_Empty then - CU_Name.Part := GNATCOLL.Projects.Unit_Body; + if not Degenerate_Subprogram_Generics.Is_Empty then + declare + PB_Unit_Body : Compilation_Unit_Part := PB_Unit; + begin + PB_Unit_Body.Part := GNATCOLL.Projects.Unit_Body; - Create_File - (Info, - File, - To_Filename (Info.Project, CU_Name, Switches.Ada_Language)); + Create_File + (Prj, File, To_Filename (Prj, Ada_Language, PB_Unit_Body)); - Put_Warnings_And_Style_Checks_Pragmas (File); - Put_Language_Version_Pragma; - File.Put_Line ("package body " & Pkg_Name & " is"); - File.New_Line; - for G of UIC.Degenerate_Subprogram_Generics loop - File.Put_Line - (" " & To_String (To_Wide_Wide_String (G.Generic_Subp_Body))); - end loop; - File.Put_Line ("end " & Pkg_Name & ";"); + Put_Warnings_And_Style_Checks_Pragmas (File); + Put_Language_Version_Pragma; + File.Put_Line ("package body " & Pkg_Name & " is"); + File.New_Line; + for G of Degenerate_Subprogram_Generics loop + File.Put_Line + (" " + & To_String (To_Wide_Wide_String (G.Generic_Subp_Body))); + end loop; + File.Put_Line ("end " & Pkg_Name & ";"); - Text_Files.Close (File); - if Switches.Pretty_Print then - Text_Files.Run_GNATpp (File); - end if; + Text_Files.Close (File); + if Switches.Pretty_Print then + Text_Files.Run_GNATpp (File); + end if; + end; end if; end Emit_Pure_Buffer_Unit; @@ -8241,16 +8390,13 @@ package body Instrument.Ada_Unit is procedure Emit_Dump_Helper_Unit (Dump_Config : Any_Dump_Config; - Info : in out Project_Info; - Main_Filename : String; - Main : Compilation_Unit_Name; + Instrumenter : Ada_Instrumenter_Type'Class; + Prj : Prj_Desc; + Main : Compilation_Unit_Part; Helper_Unit : out Ada_Qualified_Name; Override_Dump_Trigger : Any_Dump_Trigger := Manual; Has_Controlled : Boolean := False) is - Root_Prj_Name : constant String := - Project.Project.Root_Project.Name; - File : Text_Files.File_Type; procedure Put_With (Unit : Ada_Qualified_Name); @@ -8280,7 +8426,7 @@ package body Instrument.Ada_Unit is begin -- Create the name of the helper unit - Helper_Unit := Sys_Buffers; + Helper_Unit := Sys_Prefix; Helper_Unit.Append (To_Unbounded_String ("D") & Instrumented_Unit_Slug (Main)); @@ -8310,13 +8456,13 @@ package body Instrument.Ada_Unit is -- trace file. Create_File - (Info, + (Prj, File, Name => To_Filename - (Info.Project, - CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Spec), - Switches.Ada_Language)); + (Prj, + Ada_Language, + CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Spec))); Put_Warnings_And_Style_Checks_Pragmas (File); Put_With (Sys_Buffers); @@ -8354,13 +8500,13 @@ package body Instrument.Ada_Unit is -- Emit the package body Create_File - (Info, + (Prj, File, Name => To_Filename - (Info.Project, - CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Body), - Switches.Ada_Language)); + (Prj, + Ada_Language, + CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Body))); Put_Warnings_And_Style_Checks_Pragmas (File); @@ -8376,7 +8522,7 @@ package body Instrument.Ada_Unit is end case; File.Put_Line - ("with " & To_Ada (Buffers_List_Unit (Root_Prj_Name)) & ";"); + ("with " & To_Ada (Buffers_List_Unit (+Prj.Prj_Name)) & ";"); File.Put_Line ("package body " & Helper_Unit_Name & " is"); File.New_Line; @@ -8391,12 +8537,10 @@ package body Instrument.Ada_Unit is File.Put (" ("); File.Put_Line - (To_Ada (Buffers_List_Unit (Root_Prj_Name)) & ".List,"); + (To_Ada (Buffers_List_Unit (+Prj.Prj_Name)) & ".List,"); case Dump_Config.Channel is when Binary_File => declare - use GNATCOLL.VFS; - U : constant String := To_Ada (Output_Unit); Indent1 : constant String := " "; Indent2 : constant String := Indent1 & " "; @@ -8407,14 +8551,8 @@ package body Instrument.Ada_Unit is else """" & To_String (Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := - (if Length (Dump_Config.Filename_Prefix) = 0 - then """" & String'(+Info.Project.Executable_Name - (File => +Main_Filename, - Include_Suffix => True)) & """" - else """" & To_String (Dump_Config.Filename_Prefix) - & """"); - Tag : constant String := - """" & Trace_Filename_Tag & """"; + """" & To_String (Dump_Config.Filename_Prefix) & """"; + Tag : constant String := """" & (+Instrumenter.Tag) & """"; Simple : constant String := (if Dump_Config.Filename_Simple then "True" @@ -8525,29 +8663,25 @@ package body Instrument.Ada_Unit is ---------------------------- overriding procedure Emit_Buffers_List_Unit - (Self : Ada_Instrumenter_Type; - Root_Project_Info : in out Project_Info; - Instr_Units : CU_Name_Vectors.Vector) + (Self : Ada_Instrumenter_Type; + Instr_Units : Unit_Sets.Set; + Prj : Prj_Desc) is - Prj_Name : constant String := Root_Project_Info.Project.Name; - CU_Name : constant Compilation_Unit_Name := + Buffers_CU_Name : constant Compilation_Unit_Part := CU_Name_For_Unit - (Buffers_List_Unit (Prj_Name), GNATCOLL.Projects.Unit_Spec); - File : Text_Files.File_Type; + (Buffers_List_Unit (+Prj.Prj_Name), GNATCOLL.Projects.Unit_Spec); + File : Text_Files.File_Type; begin -- Emit the unit to contain the list of buffers declare - Unit_Name_Str : constant String := To_Ada (CU_Name.Unit); + Unit_Name : constant String := To_Ada (Buffers_CU_Name.Unit); begin Create_File - (Root_Project_Info, - File, - To_Filename - (Root_Project_Info.Project, - CU_Name, - Switches.Ada_Language)); + (Prj, File, To_Filename (Prj, Ada_Language, Buffers_CU_Name)); Put_Warnings_And_Style_Checks_Pragmas (File); + File.Put_Line + ("with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists;"); for Instr_Unit of Instr_Units loop @@ -8558,13 +8692,16 @@ package body Instrument.Ada_Unit is -- would not include them in the link as they would not be in the -- dependency closure. - if Instr_Unit.Language_Kind = Unit_Based_Language then - File.Put_Line ("with " & To_Ada (Buffer_Unit (Instr_Unit)) - & ";"); + if Instr_Unit.Language = Unit_Based_Language then + File.Put_Line + ("with " + & To_Ada + (Buffer_Unit (To_Qualified_Name (+Instr_Unit.Unit_Name))) + & ";"); end if; end loop; File.New_Line; - File.Put_Line ("package " & Unit_Name_Str & " is"); + File.Put_Line ("package " & Unit_Name & " is"); File.New_Line; File.Put_Line (" pragma Preelaborate;"); File.New_Line; @@ -8587,93 +8724,197 @@ package body Instrument.Ada_Unit is File.Put_Line (" List : constant GNATcov_RTS.Buffers.Lists" & ".Coverage_Buffers_Group_Array := ("); - for Cur in Instr_Units.Iterate loop - declare - use CU_Name_Vectors; - - Index : constant Positive := To_Index (Cur); - Index_Img : constant String := Img (To_Index (Cur)); - Buffer_Name : constant String := - Unit_Buffers_Name (Element (Cur)); - begin + declare + Index : Positive := 1; + Last : constant Natural := Natural (Instr_Units.Length); + begin + for Instr_Unit of Instr_Units loop File.Put - (" " & Index_Img & " => " & Buffer_Name & "'Access"); - if Index = Instr_Units.Last_Index then + (" " & Img (Index) & " => " + & Unit_Buffers_Name (Instr_Unit) & "'Access"); + if Index = Last then File.Put_Line (");"); else File.Put_Line (","); end if; - end; - end loop; + Index := Index + 1; + end loop; + end; + File.Put_Line (" C_List : constant GNATcov_RTS.Buffers.Lists" & ".GNATcov_RTS_Coverage_Buffers_Group_Array :="); File.Put_Line (" (" & Instr_Units.Length'Image - & " , List'Address);"); + & ", List'Address);"); File.Put_Line (" pragma Export (C, C_List, """ - & Unit_Buffers_Array_Name (Prj_Name) - & """);"); + & Unit_Buffers_Array_Name (+Prj.Prj_Name) & """);"); File.New_Line; - File.Put_Line ("end " & Unit_Name_Str & ";"); + File.Put_Line ("end " & Unit_Name & ";"); end; end Emit_Buffers_List_Unit; + ----------------------------- + -- Create_Ada_Instrumenter -- + ----------------------------- + + function Create_Ada_Instrumenter + (Tag : Unbounded_String; + Config_Pragmas_Filename, + Mapping_Filename : String; + Predefined_Source_Dirs : String_Vectors.Vector) + return Ada_Instrumenter_Type + is + Instrumenter : Ada_Instrumenter_Type; + begin + Instrumenter.Tag := Tag; + + -- First create the context for Libadalang + + Instrumenter.Provider := + Instrument.Ada_Unit_Provider.Create_Provider + (Predefined_Source_Dirs, Mapping_Filename); + + -- Create the event handler, to report when Libadalang cannot read a + -- required source file. + + Instrumenter.Event_Handler := Create_Missing_File_Reporter; + + -- Save the location of the file holding the configuration pragmas + + Instrumenter.Config_Pragmas_Filename := +Config_Pragmas_Filename; + + -- Then, create the analysis context + + Create_LAL_Context (Instrumenter); + return Instrumenter; + end Create_Ada_Instrumenter; + --------------------- -- Instrument_Unit -- --------------------- - overriding procedure Instrument_Unit - (Self : in out Ada_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Unit_Info : in out Instrumented_Unit_Info) + procedure Instrument_Unit + (Self : in out Ada_Instrumenter_Type; + Unit_Name : String; + Prj : Prj_Desc; + Files_Of_Interest : String_Sets.Set) is - Prj_Info : Project_Info renames Unit_Info.Prj_Info.all; - UIC : Ada_Unit_Inst_Context; + Allocated_Bits : Allocated_Bits_Vectors.Vector; + Last_Buffer_Index : Natural := 0; + CU_Names : CU_Name_Vectors.Vector; + CUs : CU_Id_Vectors.Vector; + Unit : constant Files_Table.Compilation_Unit := + (Language => Unit_Based_Language, Unit_Name => +Unit_Name); - Event_Handler : Missing_Src_Reporter renames - Missing_Src_Reporter_Access (Self.Event_Handler.Unchecked_Get).all; - -- Handle to the event handler we use to report missing source files + UIC : Ada_Unit_Inst_Context; - Filename : constant String := To_String (Unit_Info.Filename); - Basename : constant String := Ada.Directories.Simple_Name (Filename); - begin - -- If we are in verbose mode, we already printed the source file that - -- we are about to instrument. Otherwise, just get prepared to print it - -- in case we emit a "source file missing" warning through Libadalang's - -- event handler. + procedure Instrument_Source_File_Wrapper (Filename : String); + -- Wrapper around Instrument_Source_File. Instrument the given filename + -- if it is a file of interest. - if not Verbose then - Event_Handler.Instrumented_File := To_Unbounded_String (Basename); - end if; + ------------------------------------ + -- Instrument_Source_File_Wrapper -- + ------------------------------------ - -- Instrument the source file and create a unit to contain its coverage - -- buffers. + procedure Instrument_Source_File_Wrapper (Filename : String) + is + Event_Handler : Missing_Src_Reporter renames + Missing_Src_Reporter_Access (Self.Event_Handler.Unchecked_Get).all; + -- Handle to the event handler we use to report missing source files; - Instrument_Source_File - (CU_Name => CU_Name, - Unit_Info => Unit_Info, - Prj_Info => Prj_Info, - Instrumenter => Self, - UIC => UIC); - Emit_Buffer_Unit (Prj_Info, UIC); - Emit_Pure_Buffer_Unit (Prj_Info, UIC); + Basename : constant String := + Ada.Directories.Simple_Name (Filename); - -- Track which CU_Id maps to which instrumented unit + begin + -- Instrument the file only if it is a file of interest - Instrumented_Unit_CUs.Insert (CU_Name, UIC.CU); + if Files_Of_Interest.Contains (+Filename) then + + -- In verbose mode, always print a notice for the source file + -- that we are about to instrument. In non-verbose mode, just get + -- prepared to print it in case we emit a "source file missing" + -- warning through Libadalang's event handler. + + if Verbose then + Put_Line ("Instrumenting " & Basename); + else + Event_Handler.Instrumented_File := + To_Unbounded_String (Basename); + end if; + + Last_Buffer_Index := Last_Buffer_Index + 1; + UIC.Entities.Buffers_Index := Last_Buffer_Index; + Instrument_Source_File + (UIC => UIC, + Filename => Filename, + Instrumenter => Self, + Prj => Prj); + CU_Names.Append (UIC.Instrumented_Unit); + CUs.Append (UIC.CU); + Allocated_Bits.Append (UIC.Unit_Bits); + end if; + end Instrument_Source_File_Wrapper; + begin + -- Initialize the buffer unit to match the unit name. It will contain + -- coverage buffers for all parts of the unit: specification, body, + -- and separates. + + UIC.Buffer_Unit := + CU_Name_For_Unit + (Buffer_Unit (To_Qualified_Name (Unit_Name)), GPR.Unit_Spec); + UIC.Pure_Buffer_Unit := + CU_Name_For_Unit + (Pure_Buffer_Unit (To_Qualified_Name (Unit_Name)), GPR.Unit_Spec); + + -- Try to find the spec and / or the body for this compilation unit + -- using the unit provider. Then retrieve the separate unit from the + -- spec / body / both. + + for Part in Analysis_Unit_Kind loop + declare + function Convert (Part : Analysis_Unit_Kind) return Unit_Parts is + (case Part is + when Unit_Body => Unit_Body, + when Unit_Specification => Unit_Spec); + begin + if Self.Provider.Has_Unit (Unit_Name, Convert (Part)) then + Find_Ada_Units + (Self, + Self.Provider.Get_Unit_Filename + (Langkit_Support.Text.From_UTF8 (Unit_Name), Part), + Instrument_Source_File_Wrapper'Access); + end if; + end; + end loop; + + -- Once the unit was instrumented, emit the coverage buffer units + + Emit_Buffer_Unit + (Buffer_Unit => UIC.Buffer_Unit, + Prj => Prj, + Unit => Unit, + Unit_Bits => Allocated_Bits, + CU_Names => CU_Names, + CUs => CUs); + Emit_Pure_Buffer_Unit + (PB_Unit => UIC.Pure_Buffer_Unit, + Prj => Prj, + CU_Names => CU_Names, + Language_Version => UIC.Language_Version_Pragma, + Degenerate_Subprogram_Generics => UIC.Degenerate_Subprogram_Generics); end Instrument_Unit; + -------------------- + -- Find_Ada_Units -- + -------------------- + procedure Find_Ada_Units (Instrumenter : in out Ada_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info; - Process_Unit : access procedure - (CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info)) + Filename : String; + Process_Unit : access procedure (Filename : String)) is - use GNATCOLL.VFS; function Process_Node (N : LAL.Ada_Node'Class) return Visit_Status; @@ -8686,26 +8927,18 @@ package body Instrument.Ada_Unit is if N.Kind in Ada_Body_Stub then begin declare - Stub : constant LAL.Body_Stub := N.As_Body_Stub; - Subunit_FQN : constant LAL.Unbounded_Text_Type_Array := - Stub.P_Syntactic_Fully_Qualified_Name; - Subunit_Name : constant Compilation_Unit_Name := - CU_Name_For_Unit - (Unit => To_Qualified_Name (Subunit_FQN), - Part => GPR.Unit_Separate); - Subunit_Info : GPR.File_Info; + Stub : constant LAL.Body_Stub := N.As_Body_Stub; + Subunit_FQN : constant Text_Type := + Stub.P_Fully_Qualified_Name; begin if Subunit_FQN'Length = 0 then raise Property_Error; - elsif Unit_Info (Subunit_Name, Subunit_Info) then + else Find_Ada_Units (Instrumenter, - Subunit_Name, - Subunit_Info, - Process_Unit); - else - Warn ("cannot instrument " & Image (Subunit_Name) - & ": this unit does not belong to this project"); + Instrumenter.Context.Unit_Provider.Get + .Get_Unit_Filename (Subunit_FQN, Unit_Body), + Process_Unit); end if; end; exception @@ -8719,14 +8952,13 @@ package body Instrument.Ada_Unit is return Into; end Process_Node; - Input_Filename : constant String := +Info.File.Full_Name; - Unit : constant LAL.Analysis_Unit := - Get_From_File (Instrumenter, Input_Filename); + Unit : constant LAL.Analysis_Unit := + Get_From_File (Instrumenter, Filename); begin -- Abort if the input project is not compilable if Unit.Has_Diagnostics then - Outputs.Error ("instrumentation failed for " & Input_Filename); + Outputs.Error ("instrumentation failed for " & Filename); Outputs.Error ("please make sure the original project can be compiled"); for D of Unit.Diagnostics loop @@ -8746,7 +8978,7 @@ package body Instrument.Ada_Unit is -- unit. elsif Unit.Root.Kind = Ada_Compilation_Unit_List then - Outputs.Error ("instrumentation failed for " & Input_Filename); + Outputs.Error ("instrumentation failed for " & Filename); Outputs.Error ("source files containing multiple compilation units" & " are not supported"); raise Xcov_Exit_Exc; @@ -8756,7 +8988,7 @@ package body Instrument.Ada_Unit is declare CU : constant LAL.Compilation_Unit := Unit.Root.As_Compilation_Unit; begin - Process_Unit (CU_Name, Info); + Process_Unit (Filename); CU.Traverse (Process_Node'Access); end; end Find_Ada_Units; diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index ae4bf0ed3..a27d22e80 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -28,74 +28,72 @@ with Langkit_Support.Text; use Langkit_Support.Text; with Libadalang.Analysis; use Libadalang.Analysis; with Libadalang.Rewriting; use Libadalang.Rewriting; -with Instrument.Common; use Instrument.Common; +with Files_Table; use Files_Table; +with Instrument.Ada_Unit_Provider; +with Instrument.Common; use Instrument.Common; with Switches; package Instrument.Ada_Unit is - type Ada_Instrumenter_Type is new Language_Instrumenter - with record - Provider : Libadalang.Analysis.Unit_Provider_Reference; - -- Unit provider to create an analysis context (Context member below) + type Ada_Instrumenter_Type is new Language_Instrumenter with + record + Provider : Instrument.Ada_Unit_Provider.Provider_Type; + -- Unit provider to create an analysis context (Context member + -- below). We use a custom provider there, to be able to turn + -- a filename to our Compilation_Unit_Name internal representation, + -- and to not depend on project files in the unit instrumentation + -- process. - Event_Handler : Libadalang.Analysis.Event_Handler_Reference; - -- Event handler to warn about missing source files + Event_Handler : Libadalang.Analysis.Event_Handler_Reference; + -- Event handler to warn about missing source files - Context : Libadalang.Analysis.Analysis_Context; - -- Libadalang context to load all units to rewrite + Config_Pragmas_Filename : Unbounded_String; + -- File holding the list of configuration pragmas - Get_From_File_Count : Natural; - -- Count how many times we called Context.Get_From_File. See the - -- Max_Get_From_File_Count constant. + Context : Libadalang.Analysis.Analysis_Context; + -- Libadalang context to load all units to rewrite - Language_Version : Any_Language_Version; - -- See the eponym arguments in Instrument.Intrument_Units_Of_Interest + Get_From_File_Count : Natural; + -- Count how many times we called Context.Get_From_File. See the + -- Max_Get_From_File_Count constant. - end record; + end record; -- Instrumentation primitives for Ada - function Create_Ada_Instrumenter - (Language_Version : Any_Language_Version) return Ada_Instrumenter_Type; - -- Create an Ada instrumenter from the given provider, and the given - -- language version. - overriding function Language (Self : Ada_Instrumenter_Type) return Switches.Src_Supported_Language is (Switches.Ada_Language); overriding procedure Instrument_Unit - (Self : in out Ada_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Unit_Info : in out Instrumented_Unit_Info); + (Self : in out Ada_Instrumenter_Type; + Unit_Name : String; + Prj : Prj_Desc; + Files_Of_Interest : String_Sets.Set); overriding procedure Auto_Dump_Buffers_In_Main - (Self : in out Ada_Instrumenter_Type; - Filename : String; - Instr_Units : CU_Name_Vectors.Vector; - Dump_Config : Any_Dump_Config; - Info : in out Project_Info); + (Self : in out Ada_Instrumenter_Type; + Filename : String; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc); overriding procedure Emit_Buffers_List_Unit - (Self : Ada_Instrumenter_Type; - Root_Project_Info : in out Project_Info; - Instr_Units : CU_Name_Vectors.Vector); - - overriding function Skip_Source_File (Self : Ada_Instrumenter_Type; - Source_File : GNATCOLL.Projects.File_Info) return Boolean - is (False); - - procedure Find_Ada_Units - (Instrumenter : in out Ada_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info; - Process_Unit : access procedure - (CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info)); - -- Consider that Info is a source file to instrument (i.e. a unit of - -- interest, CU_Name being the name of its compilation unit) and call - -- Process_Unit for all compilation units that must be instrumented with - -- it (i.e. related subunits, if present). + Instr_Units : Unit_Sets.Set; + Prj : Prj_Desc); + + function Create_Ada_Instrumenter + (Tag : Unbounded_String; + Config_Pragmas_Filename, + Mapping_Filename : String; + Predefined_Source_Dirs : String_Vectors.Vector) + return Ada_Instrumenter_Type; + -- Create an Ada instrumenter. Config_Pragmas_Filename is the fullname + -- to the configuration pragma file. Mapping_Filename is the fullname + -- to the mapping file, which maps unit names to file fullnames, and + -- Predefined_Source_Dirs is the list of directories hosting runtime + -- files. The two last parameters are used to instantiate our + -- custom unit provider, which does not rely on project files + -- (see Instrument.Ada_Unit_Provider). -- Private declarations relative to the AST traversal private @@ -216,6 +214,10 @@ private new Ada.Containers.Vectors (Natural, Source_Condition); type Instrumentation_Entities is record + Buffers_Index : Natural := 0; + -- Index into the set of this units' coverage buffers group for the + -- source file being instrumented. + Common_Buffers : Node_Rewriting_Handle := No_Node_Rewriting_Handle; -- Qualified name for the unit that contains coverage buffer types and -- witness subprograms. @@ -262,10 +264,13 @@ private type Ada_Unit_Inst_Context is new Instrument.Common.Unit_Inst_Context with record + Language_Version_Pragma : Unbounded_Wide_Wide_String; + -- Language version configuration pragma for unit, if any + CU : CU_Id := No_CU_Id; -- SCO identifier of the compilation unit being instrumented - Root_Unit : Compilation_Unit; + Root_Unit : Libadalang.Analysis.Compilation_Unit; -- Node of compilation unit Source_Decisions : Source_Decision_Vectors.Vector; @@ -278,7 +283,7 @@ private Entities : Instrumentation_Entities; -- Bank of nodes to use during instrumentation - Pure_Buffer_Unit : Compilation_Unit_Name; + Pure_Buffer_Unit : Compilation_Unit_Part; -- Name of the compilation unit that holds addresses for the coverage -- buffers of the unit being instrumented. diff --git a/tools/gnatcov/instrument-ada_unit__stub.adb b/tools/gnatcov/instrument-ada_unit__stub.adb index c4fd7d0ac..523d98f83 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.adb +++ b/tools/gnatcov/instrument-ada_unit__stub.adb @@ -16,4 +16,7 @@ -- of the license. -- ------------------------------------------------------------------------------ -pragma No_Body; +package body Instrument.Ada_Unit is +begin + Builtin_Support (Ada_Language) := False; +end Instrument.Ada_Unit; diff --git a/tools/gnatcov/instrument-ada_unit__stub.ads b/tools/gnatcov/instrument-ada_unit__stub.ads index 1caac4fe2..a1dddb09d 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.ads +++ b/tools/gnatcov/instrument-ada_unit__stub.ads @@ -24,23 +24,21 @@ with Instrument.Common; use Instrument.Common; package Instrument.Ada_Unit is + pragma Elaborate_Body; + type Ada_Instrumenter_Type is new Language_Instrumenter with null record; -- Common instrumentation primitives for Ada - function Create_Ada_Instrumenter - (Language_Version : Any_Language_Version) return Ada_Instrumenter_Type - is (Ada_Instrumenter_Type'(null record)); - overriding function Language (Self : Ada_Instrumenter_Type) return Src_Supported_Language is (Ada_Language); - procedure Find_Ada_Units - (Instrumenter : in out Ada_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info; - Process_Unit : access procedure - (CU_Name : Compilation_Unit_Name; - Info : GNATCOLL.Projects.File_Info)) is null; + function Create_Ada_Instrumenter + (Tag : Unbounded_String; + Config_Pragmas_Filename, + Mapping_Filename : String; + Predefined_Source_Dirs : String_Vectors.Vector) + return Ada_Instrumenter_Type + is (Ada_Instrumenter_Type'(others => <>)); end Instrument.Ada_Unit; diff --git a/tools/gnatcov/instrument-ada_unit_provider.adb b/tools/gnatcov/instrument-ada_unit_provider.adb index 110cf326f..493e5444c 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.adb +++ b/tools/gnatcov/instrument-ada_unit_provider.adb @@ -63,6 +63,8 @@ package body Instrument.Ada_Unit_Provider is Get_Line (Dependencies_File); begin Provider.Unit_Map.Insert (To_Lower (Unit_Name), File_Fullname); + Provider.Filename_Map.Insert + (File_Fullname, To_Lower (Unit_Name)); end; end loop; exception @@ -204,4 +206,22 @@ package body Instrument.Ada_Unit_Provider is end if; end Get_Unit; + -------------- + -- Has_Unit -- + -------------- + + function Has_Unit + (Provider : Provider_Type; + Unit_Name : String; + Unit_Part : Unit_Parts) return Boolean + is + Unit_Name_And_Part : constant String := + To_Lower (Unit_Name) + & (case Unit_Part is + when Unit_Spec => "%s", + when others => "%b"); + begin + return Provider.Unit_Map.Contains (Unit_Name_And_Part); + end Has_Unit; + end Instrument.Ada_Unit_Provider; diff --git a/tools/gnatcov/instrument-ada_unit_provider.ads b/tools/gnatcov/instrument-ada_unit_provider.ads index 3e2774b11..fd851e9a3 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.ads +++ b/tools/gnatcov/instrument-ada_unit_provider.ads @@ -65,9 +65,14 @@ package Instrument.Ada_Unit_Provider is overriding procedure Release (Provider : in out Provider_Type) is null; + function Has_Unit + (Provider : Provider_Type; + Unit_Name : String; + Unit_Part : Unit_Parts) return Boolean; + -- Returns whether given unit is in the provider unit closure + private - use US; use type GNATCOLL.VFS.Virtual_File; package String_Maps is new Ada.Containers.Indefinite_Hashed_Maps @@ -81,6 +86,9 @@ private Unit_Map : String_Maps.Map; -- Mapping from unit name to file fullnames + Filename_Map : String_Maps.Map; + -- Mapping from file fullnames to unit names + Runtime_Files : String_Maps.Map; -- Mapping from a runtime file basename to its fullname diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 410348c38..cf64a2857 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -26,9 +26,6 @@ with Clang.Extensions; use Clang.Extensions; with GNAT.OS_Lib; use GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; -with GNAT.Strings; - -with GNATCOLL.VFS; with Interfaces; use Interfaces; with Interfaces.C; use Interfaces.C; @@ -42,7 +39,6 @@ with Inputs; use Inputs; with Instrument.C_Utils; use Instrument.C_Utils; with Outputs; use Outputs; with Paths; use Paths; -with Project; use Project; with SCOs; with System; use System; with Table; @@ -50,7 +46,6 @@ with Text_Files; use Text_Files; package body Instrument.C is - package GPR renames GNATCOLL.Projects; package US renames Ada.Strings.Unbounded; function To_Chars_Ptr_Array @@ -61,19 +56,6 @@ package body Instrument.C is procedure Free (Self : in out chars_ptr_array); -- Free all strings in Self - function Compiler_Driver - (Project : GNATCOLL.Projects.Project_Type; - Language : C_Family_Language) return String; - -- Return the command name for the compiler for Language in the given - -- Project. - - function Source_Suffix - (Instrumenter : C_Family_Instrumenter_Type'Class; - Part : GNATCOLL.Projects.Unit_Parts; - Project : GNATCOLL.Projects.Project_Type) return String; - -- Return the filename suffix corresponding for Part files and the language - -- that Instrumenter handles in the given project. - procedure Filter_Annotations; -- Remove any exemption annotations from the map that intersects a -- statement SCO. This is not part of Import_Annotations as this is only @@ -90,66 +72,8 @@ package body Instrument.C is -- Preprocessing utilities -- ------------------------------ - Macro_Cmdline_Regexp : constant Pattern_Matcher := Compile ( - "([a-zA-Z_]\w*)" - -- The name of the macro - - & "(\(.*\))?" - -- The optional list of macro arguments - - & "([^ =]+)?" - -- Then, there can be any character before the assignment: they will be - -- part of the macro value (e.g. A(b)b will yield #define A b 1) - - & "(?:=(.*))?" - -- The macro value itself - ); - - Macro_Def_Regexp : constant Pattern_Matcher := Compile ( - "#define" - & "(?: |\t)+" - -- "#define", then a non-empty blank - - & "([a-zA-Z_]\w*)" - -- The name of the macro - - & "(\(.*\))?" - -- The optional list of macro arguments - - & "(.*)" - -- The macro value itself - ); - -- Regular expression to analyze definitions for builtin macros (see - -- Builtin_Macros) - type Macro_Set_Access is access Macro_Set; type Macro_Set_Cst_Access is access constant Macro_Set; - package Compiler_Macros_Maps is new Ada.Containers.Hashed_Maps - (Key_Type => Unbounded_String, - Element_Type => Macro_Set_Access, - Equivalent_Keys => "=", - Hash => Ada.Strings.Unbounded.Hash); - Compiler_Macros : Compiler_Macros_Maps.Map; - -- Cache for computed compiler builtin macros, to avoid relaunching the - -- compiler command every time a file is instrumented. Used in the - -- Builtin_Macros function only. - - -- The three following functions are not used, but could be in the future, - -- when we will refine what is done with macros. - - procedure Parse_Macro_Definition - (Str : String; - Parsed_Def : out Macro_Definition; - Success : out Boolean); - -- Parse a macro definition. If the parsing failed, set Success to False. - -- Otherwise, set Parsed_Def to the parsed definition and set Success to - -- True. - - procedure Parse_Cmdline_Macro_Definition - (Str : String; - Parsed_Def : out Macro_Definition; - Success : out Boolean); - -- Same as above, but with a command-line macro definition function Builtin_Macros (Lang, Compiler, Std, Output_Dir : String) return Macro_Set_Cst_Access; @@ -165,8 +89,8 @@ package body Instrument.C is procedure Preprocess_Source (Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; PP_Filename : out Unbounded_String; - Info : in out Project_Info; Options : in out Analysis_Options); -- Preprocess the source at Filename and extend Options using the -- preprocessor output. @@ -353,40 +277,30 @@ package body Instrument.C is ---------------------------- procedure Record_PP_Info - (Unit_Info : Instrumented_Unit_Info; - UIC : in out C_Unit_Inst_Context); + (Orig_Filename : String; + UIC : in out C_Unit_Inst_Context; + Instrumenter : C_Family_Instrumenter_Type'Class); -- Emit the low-level SCOs for the given unit. Do not process them: this is -- left to the other (instrumentation) pass. - procedure Instrument_Source_File - (CU_Name : Compilation_Unit_Name; - Unit_Info : Instrumented_Unit_Info; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj_Info : in out Project_Info; - UIC : out C_Unit_Inst_Context); - -- Generate the instrumented source corresponding to CU_Name/Unit_Info. - -- Record instrumentation information in IC. - -- - -- If the unit to instrument is also a main and the buffers dump trigger - -- is not manual, instrumented code will also dump the coverage buffers. - ---------------------------- -- Source instrumentation -- ---------------------------- procedure Emit_Buffer_Unit - (Info : in out Project_Info; - UIC : C_Unit_Inst_Context'Class; - Instrumenter : C_Family_Instrumenter_Type'Class); + (UIC : C_Unit_Inst_Context'Class; + Unit : Compilation_Unit; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc); -- Emit the unit to contain coverage buffers for the given instrumented -- unit, for the given instrumenter. procedure Emit_Dump_Helper_Unit - (Dump_Config : Any_Dump_Config; - Info : in out Project_Info; - Main : Compilation_Unit_Name; - Helper_Unit : out US.Unbounded_String; - Instrumenter : C_Family_Instrumenter_Type'Class); + (Dump_Config : Any_Dump_Config; + Main : Compilation_Unit_Part; + Helper_Unit : out US.Unbounded_String; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc); -- Emit the unit to contain helpers to implement the automatic dump of -- coverage buffers for the given Main unit. Info must be the project that -- owns this main. Upon return, the name of this helper unit is stored in @@ -397,9 +311,9 @@ package body Instrument.C is procedure Start_Rewriting (Self : out C_Source_Rewriter; - Info : in out Project_Info; Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; Preprocessed : Boolean := False); -- Start a rewriting session for the given file identified by its full -- name. @@ -523,24 +437,6 @@ package body Instrument.C is end loop; end Free; - --------------------- - -- Compiler_Driver -- - --------------------- - - function Compiler_Driver - (Project : GNATCOLL.Projects.Project_Type; - Language : C_Family_Language) return String is - begin - return Result : constant String := - GNATCOLL.Projects.Attribute_Value - (Project, GPR.Compiler_Driver_Attribute, Image (Language)) - do - if Result = "" then - Fatal_Error ("could not find a compiler for " & Image (Language)); - end if; - end return; - end Compiler_Driver; - ------------------------ -- Filter_Annotations -- ------------------------ @@ -582,47 +478,6 @@ package body Instrument.C is end loop; end Filter_Annotations; - ------------------- - -- Source_Suffix -- - ------------------- - - function Source_Suffix - (Instrumenter : C_Family_Instrumenter_Type'Class; - Part : GNATCOLL.Projects.Unit_Parts; - Project : GNATCOLL.Projects.Project_Type) return String - is - L : constant C_Family_Language := Instrumenter.Language; - Attr : constant GPR.Attribute_Pkg_String := - GPR.Build - (Package_Name => "Naming", - Attribute_Name => - (case Part is - when GPR.Unit_Body => "Body_Suffix", - when GPR.Unit_Spec => "Spec_Suffix", - when GPR.Unit_Separate => raise Program_Error)); - begin - case Part is - when GPR.Unit_Body => - return Project.Attribute_Value - (Attribute => Attr, - Index => Image (L), - Default => (case L is - when C_Language => ".c", - when CPP_Language => ".cpp")); - - when GPR.Unit_Spec => - return Project.Attribute_Value - (Attribute => Attr, - Index => Image (L), - Default => (case L is - when C_Language => ".h", - when CPP_Language => ".hh")); - - when GPR.Unit_Separate => - return (raise Program_Error); - end case; - end Source_Suffix; - ----------------- -- Enter_Scope -- ----------------- @@ -2536,71 +2391,6 @@ package body Instrument.C is UIC.MCDC_State_Declaration_Node := Saved_MCDC_State_Declaration_Node; end Traverse_Declarations; - ---------------------------- - -- Parse_Macro_Definition -- - ---------------------------- - - procedure Parse_Macro_Definition - (Str : String; - Parsed_Def : out Macro_Definition; - Success : out Boolean) - is - Matches : Match_Array (0 .. 3); - begin - Match (Macro_Def_Regexp, Str, Matches); - if Matches (0) = No_Match then - Success := False; - else - Success := True; - Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); - if Matches (2) /= No_Match then - Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); - end if; - Parsed_Def.Value := +Str (Matches (3).First .. Matches (3).Last); - end if; - end Parse_Macro_Definition; - - ------------------------------------ - -- Parse_Cmdline_Macro_Definition -- - ------------------------------------ - - procedure Parse_Cmdline_Macro_Definition - (Str : String; - Parsed_Def : out Macro_Definition; - Success : out Boolean) - is - Matches : Match_Array (0 .. 4); - begin - Match (Macro_Cmdline_Regexp, Str, Matches); - if Matches (0) = No_Match then - Success := False; - else - Success := True; - Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); - if Matches (2) /= No_Match then - Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); - end if; - - -- Command line macros can have part of their value before the - -- assignment, e.g. "-DA(b)b" is equivalent to "#define A(b) b 1". - - if Matches (3) /= No_Match then - Append - (Parsed_Def.Value, - Str (Matches (3).First .. Matches (3).Last) & " "); - end if; - - -- If no value is given, then it is implicitly 1 - - if Matches (4) /= No_Match then - Append - (Parsed_Def.Value, Str (Matches (4).First .. Matches (4).Last)); - else - Append (Parsed_Def.Value, " 1"); - end if; - end if; - end Parse_Cmdline_Macro_Definition; - -------------------- -- Builtin_Macros -- -------------------- @@ -2609,82 +2399,68 @@ package body Instrument.C is (Lang, Compiler, Std, Output_Dir : String) return Macro_Set_Cst_Access is use Ada.Characters.Handling; - use Compiler_Macros_Maps; + + PID : constant Unsigned_64 := + Unsigned_64 (Pid_To_Integer (Current_Process_Id)); L : constant String := To_Lower (Lang); Key : constant Unbounded_String := +Compiler & " -x " & L & " " & Std; - Cur : constant Cursor := Compiler_Macros.Find (Key); - Result : Macro_Set_Access; + Result : constant Macro_Set_Access := new Macro_Set; + + Args : String_Vectors.Vector; + Basename : constant String := + Ada.Directories.Simple_Name (Compiler) + & "_builtins_" + & Hex_Image (PID); + Filename : constant String := Output_Dir / Basename; + File : Ada.Text_IO.File_Type; begin - -- If we already computed builtin macros for Compiler, return the cached - -- result. Compute it now otherwise. - - if Has_Element (Cur) then - Result := Element (Cur); + -- Run the preprocessor on an empty file and write the + -- preprocessed sources to Filename. - else - Result := new Macro_Set; + Args.Append (+"-x"); + Args.Append (+L); + if Std'Length /= 0 then + Args.Append (+Std); + end if; + Args.Append (+"-E"); + Args.Append (+"-dM"); + Args.Append (+"-"); + + Run_Command + (Command => Compiler, + Arguments => Args, + Origin_Command_Name => + "getting built-in macros for " & (+Key), + Output_File => Filename, + In_To_Null => True); + + -- Decode all macro definitions in Filename and store them in Result + + Open (File, In_File, Filename); + while not End_Of_File (File) loop declare - Args : String_Vectors.Vector; - Basename : constant String := - Ada.Directories.Simple_Name (Compiler) & "_builtins"; - Filename : constant String := Output_Dir / Basename; - File : Ada.Text_IO.File_Type; + Line : constant String := Get_Line (File); + Macro_Def : Macro_Definition (Define => True); + Success : Boolean; begin - -- Run the preprocessor on an empty file and write the - -- preprocessed sources to Filename. - - Args.Append (+"-x"); - Args.Append (+L); - if Std'Length /= 0 then - Args.Append (+Std); + Parse_Macro_Definition + (Line, + Macro_Def, + Success); + if Success then + Result.Include (Macro_Def); + else + Warn + ("Cannot parse a built-in macro definition for " + & Compiler & ", ignoring it:" & ASCII.LF & " " + & Line); end if; - Args.Append (+"-E"); - Args.Append (+"-dM"); - Args.Append (+"-"); - - Run_Command - (Command => Compiler, - Arguments => Args, - Origin_Command_Name => - "getting built-in macros for " & (+Key), - Output_File => Filename, - In_To_Null => True); - - -- Decode all macro definitions in Filename and store them in - -- Result. - - Open (File, In_File, Filename); - while not End_Of_File (File) loop - declare - Line : constant String := Get_Line (File); - Macro_Def : Macro_Definition (Define => True); - Success : Boolean; - begin - Parse_Macro_Definition - (Line, - Macro_Def, - Success); - if Success then - Result.Include (Macro_Def); - else - Warn - ("Cannot parse a built-in macro definition for " - & Compiler & ", ignoring it:" & ASCII.LF & " " - & Line); - end if; - end; - end loop; - Close (File); - Delete_File (Filename); - - -- Save Result in the cache for later use - - Compiler_Macros.Insert (Key, Result); end; - end if; - + end loop; + Close (File); + Delete_File (Filename); return Macro_Set_Cst_Access (Result); end Builtin_Macros; @@ -2695,8 +2471,8 @@ package body Instrument.C is procedure Preprocess_Source (Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; PP_Filename : out Unbounded_String; - Info : in out Project_Info; Options : in out Analysis_Options) is Cmd : Command_Type; @@ -2709,31 +2485,26 @@ package body Instrument.C is Unsigned_64 (Pid_To_Integer (Current_Process_Id)); Preprocessed_Filename : constant String := - (+Info.Output_Dir) / ("pp-" & Strip_Zero_Padding (Hex_Image (PID))); + (+Prj.Output_Dir) / ("pp-" & Strip_Zero_Padding (Hex_Image (PID))); -- Preprocessed file. We then postprocess it to remove redundant line -- markers inserted by the preprocessor. Preprocessor_Output_Filename : constant String := - (+Info.Output_Dir) / + (+Prj.Output_Dir) / ("pp-output-" & Strip_Zero_Padding (Hex_Image (PID))); Preprocessor_Output_File : Ada.Text_IO.File_Type; -- File containing the preprocessor output (used to get include search -- paths). begin - PP_Filename := +New_File (Info, Filename); - - -- The file may have been preprocessed already, if we are instrumenting - -- it as a main after having instrumented it as a source. In this case, - -- we should not preprocess it again (as it will fail). HACK: if the - -- original filename is an instrumented file (in which case it is - -- equal to PP_Filename), skip the preprocessing step. + PP_Filename := +New_File (Prj, Filename); + -- HACK: consider that the file was already preprocessed in that case if +PP_Filename = Filename then return; end if; Cmd := - (Command => +Compiler_Driver (Info.Project, Instrumenter.Language), + (Command => Prj.Compiler_Driver (Instrumenter.Language), others => <>); -- Add the preprocessing flag @@ -2878,9 +2649,9 @@ package body Instrument.C is procedure Start_Rewriting (Self : out C_Source_Rewriter; - Info : in out Project_Info; Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; Preprocessed : Boolean := False) is PP_Filename : Unbounded_String := +Filename; @@ -2888,10 +2659,10 @@ package body Instrument.C is Options : Analysis_Options; Args : String_Vectors.Vector; begin - Import_Options (Options, Instrumenter.Language, Info, Filename); + Import_Options (Options, Instrumenter, Prj, Filename); if not Preprocessed then Preprocess_Source - (Filename, Instrumenter, PP_Filename, Info, Options); + (Filename, Instrumenter, Prj, PP_Filename, Options); end if; Self.CIdx := @@ -2981,11 +2752,11 @@ package body Instrument.C is -------------------- procedure Record_PP_Info - (Unit_Info : Instrumented_Unit_Info; - UIC : in out C_Unit_Inst_Context) + (Orig_Filename : String; + UIC : in out C_Unit_Inst_Context; + Instrumenter : C_Family_Instrumenter_Type'Class) is - Orig_Filename : constant String := +Unit_Info.Filename; - Args : String_Vectors.Vector; + Args : String_Vectors.Vector; begin UIC.Pass := Record_PP_Info_Pass'Access; UIC.CIdx := @@ -2997,7 +2768,8 @@ package body Instrument.C is -- the user's preprocessor. Add_Options (Args, UIC.Options); - String_Vectors.Append (Args, Common_Parse_TU_Args (Unit_Info.Language)); + String_Vectors.Append + (Args, Common_Parse_TU_Args (Instrumenter.Language)); -- TODO??? We should also inhibit the use of clang predefined macros, -- with the -undef option, but doing this yields parsing errors, and a @@ -3037,24 +2809,31 @@ package body Instrument.C is end Record_PP_Info; - ---------------------------- - -- Instrument_Source_File -- - ---------------------------- + --------------------- + -- Instrument_Unit -- + --------------------- - procedure Instrument_Source_File - (CU_Name : Compilation_Unit_Name; - Unit_Info : Instrumented_Unit_Info; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj_Info : in out Project_Info; - UIC : out C_Unit_Inst_Context) + procedure Instrument_Unit + (Self : in out C_Family_Instrumenter_Type; + Unit_Name : String; + Prj : Prj_Desc; + Files_Of_Interest : String_Sets.Set) is - Orig_Filename : constant String := +Unit_Info.Filename; + UIC : C_Unit_Inst_Context; + CU_Name : constant Compilation_Unit_Part := + CU_Name_For_File (+Unit_Name); + + Orig_Filename : constant String := Unit_Name; PP_Filename : Unbounded_String; -- Respectively original, and preprocessed filename Buffer_Filename : constant String := - To_Symbol_Name (Sys_Buffers) & "_b_" & Instrumented_Unit_Slug (CU_Name) - & Source_Suffix (Instrumenter, GPR.Unit_Body, Prj_Info.Project); + New_File + (Prj, + To_Symbol_Name (Sys_Prefix) & "_b_" + & Instrumented_Unit_Slug (CU_Name) + & (+Prj.Body_Suffix + (C_Family_Instrumenter_Type'Class (Self).Language))); -- Name of the generated source file holding the coverage buffers Rewriter : C_Source_Rewriter; @@ -3092,7 +2871,7 @@ package body Instrument.C is Put_Extern_Decl (UIC.Rewriter, Insert_Extern_Location, - Instrumenter, + Self, C_Type, Name, Array_Size, @@ -3102,30 +2881,46 @@ package body Instrument.C is -- Start of processing for Instrument_Source_File begin + -- Exit early if there is no compiler driver found to preprocess the + -- source. + + declare + Compiler_Driver : constant Unbounded_String := + Prj.Compiler_Driver + (C_Family_Instrumenter_Type'Class (Self).Language); + begin + if Compiler_Driver = Null_Unbounded_String then + Outputs.Fatal_Error + ("could not find a compiler for " + & Image + (C_Family_Instrumenter_Type'Class (Self).Language)); + end if; + end; + SCOs.Initialize; UIC.SFI := Get_Index_From_Generic_Name (Orig_Filename, Kind => Files_Table.Source_File, Indexed_Simple_Name => True); + UIC.Fullname := +Orig_Filename; -- Initialize the C instrumentation context UIC.Instrumented_Unit := CU_Name; - UIC.Buffer_Unit := - CU_Name_For_File (+Buffer_Filename, CU_Name.Project_Name); + UIC.Buffer_Unit := CU_Name_For_File (+Buffer_Filename); + UIC.Files_Of_Interest := Files_Of_Interest; -- Import analysis options for the file to preprocess, then run the -- preprocessor. - Import_Options - (UIC.Options, Instrumenter.Language, Prj_Info, Orig_Filename); + Import_Options (UIC.Options, Self, Prj, Unit_Name); Preprocess_Source - (Orig_Filename, Instrumenter, PP_Filename, Prj_Info, UIC.Options); + (Orig_Filename, Self, Prj, PP_Filename, UIC.Options); -- Start by recording preprocessing information - Record_PP_Info (Unit_Info, UIC); + Record_PP_Info (Orig_Filename, UIC, Self); -- Then record exemption annotations in the comments. Reuse the TU from -- the preprocessing information recording pass as we want the @@ -3191,11 +2986,12 @@ package body Instrument.C is UIC.Pass := Instrument_Pass'Access; - Start_Rewriting (Self => Rewriter, - Info => Prj_Info, - Filename => +PP_Filename, - Instrumenter => Instrumenter, - Preprocessed => True); + Start_Rewriting + (Self => Rewriter, + Filename => +PP_Filename, + Instrumenter => Self, + Prj => Prj, + Preprocessed => True); UIC.TU := Rewriter.TU; UIC.Rewriter := Rewriter.Rewriter; Insert_Extern_Location := @@ -3317,7 +3113,7 @@ package body Instrument.C is end if; end if; - -- Create mappings from alloacted bits to the corresponding SCO + -- Create mappings from allocated bits to the corresponding SCO -- discharging information (Bit_Maps). Bit_Maps := @@ -3447,7 +3243,29 @@ package body Instrument.C is & " unsigned value"); Rewriter.Apply; - end Instrument_Source_File; + + -- Generate a buffer compilation unit defining coverage buffers that + -- will store execution witnesses. This CU is a C file rather than an + -- Ada file exporting the defined symboled to C. Indeed, we want it to + -- be compatible with a C-only compiler. + + Emit_Buffer_Unit + (UIC, + Compilation_Unit' + (Language => File_Based_Language, + Unit_Name => UIC.Fullname), + Self, + Prj); + + -- Update the Ignore_Status of the CU we instrumented + + Files_Table.Consolidate_Ignore_Status + (Index => Files_Table.Get_Index_From_Generic_Name + (Name => Orig_Filename, + Kind => Files_Table.Source_File, + Indexed_Simple_Name => True), + Status => Files_Table.Never); + end Instrument_Unit; ---------------------------- -- Format_Array_Init_Expr -- @@ -3488,11 +3306,12 @@ package body Instrument.C is ---------------------- procedure Emit_Buffer_Unit - (Info : in out Project_Info; - UIC : C_Unit_Inst_Context'Class; - Instrumenter : C_Family_Instrumenter_Type'Class) + (UIC : C_Unit_Inst_Context'Class; + Unit : Compilation_Unit; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc) is - CU_Name : Compilation_Unit_Name renames UIC.Buffer_Unit; + CU_Name : Compilation_Unit_Part renames UIC.Buffer_Unit; File : Text_Files.File_Type; Buffers_Count : constant Natural := Natural (UIC.Allocated_Bits.Length); @@ -3535,12 +3354,12 @@ package body Instrument.C is begin -- Compute Buffers_Filenames and Buffers_Projects - for Cur in UIC.Sources_Of_Interest.Iterate loop + for Cur in UIC.Sources_Of_Interest_Info.Iterate loop declare use Created_Unit_Maps; SOI : Source_Of_Interest renames - UIC.Sources_Of_Interest.Constant_Reference (Cur); + UIC.Sources_Of_Interest_Info.Constant_Reference (Cur); Cur : Cursor; Index : Natural; begin @@ -3564,7 +3383,7 @@ package body Instrument.C is -- Start to emit the buffer unit - Create_File (Info, File, +CU_Name.Filename); + Create_File (Prj, File, +CU_Name.Filename); File.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); File.New_Line; @@ -3594,7 +3413,7 @@ package body Instrument.C is UIC.Allocated_Bits.Constant_Reference (Buffers_Index); CU : constant CU_Id := Buffers_CUs (Buffers_Index); - CU_Name : Compilation_Unit_Name renames + CU_Name : Compilation_Unit_Part renames Buffers_CU_Names.Constant_Reference (Buffers_Index); -- Symbol name for each kind of static buffer @@ -3655,9 +3474,6 @@ package body Instrument.C is & " .unit_name = " & Format_Str_Constant (+CU_Name.Filename) & "," & ASCII.LF - & " .project_name = " - & Format_Str_Constant (+CU_Name.Project_Name) & "," - & ASCII.LF & " .bit_maps_fingerprint = " & Format_Fingerprint (SC_Obligations.Bit_Maps_Fingerprint (CU)) @@ -3742,7 +3558,7 @@ package body Instrument.C is (File, Instrumenter, "const struct gnatcov_rts_coverage_buffers_group", - Unit_Buffers_Name (UIC.Instrumented_Unit), + Unit_Buffers_Name (Unit), Init_Expr => "{" & Img (Buffers_Count) & ", &" & Buffers_Array & "[0]}"); end; @@ -3753,11 +3569,11 @@ package body Instrument.C is --------------------------- procedure Emit_Dump_Helper_Unit - (Dump_Config : Any_Dump_Config; - Info : in out Project_Info; - Main : Compilation_Unit_Name; - Helper_Unit : out US.Unbounded_String; - Instrumenter : C_Family_Instrumenter_Type'Class) + (Dump_Config : Any_Dump_Config; + Main : Compilation_Unit_Part; + Helper_Unit : out US.Unbounded_String; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc) is File : Text_Files.File_Type; @@ -3777,8 +3593,7 @@ package body Instrument.C is To_Symbol_Name (Sys_Buffers) & "_d_" & Instrumented_Unit_Slug (Main) - & US.To_Unbounded_String - (Source_Suffix (Instrumenter, GPR.Unit_Body, Info.Project)); + & Prj.Body_Suffix (Instrumenter.Language); -- Compute the qualified names we need for instrumentation @@ -3789,7 +3604,7 @@ package body Instrument.C is begin -- Emit the package body - Create_File (Info, File, Filename); + Create_File (Prj, File, Filename); File.Put_Line ("#include ""gnatcov_rts_c-strings.h"""); @@ -3810,7 +3625,7 @@ package body Instrument.C is (File, Instrumenter, "const struct gnatcov_rts_coverage_buffers_group_array", - Unit_Buffers_Array_Name (Project.Project.Root_Project.Name)); + Unit_Buffers_Array_Name (+Prj.Prj_Name)); -- Emit the procedure to write the trace file @@ -3820,26 +3635,18 @@ package body Instrument.C is File.Put_Line (Indent1 & Output_Proc & " ("); File.Put_Line - (Indent2 & "&" - & Unit_Buffers_Array_Name (Project.Project.Root_Project.Name) - & ","); + (Indent2 & "&" + & Unit_Buffers_Array_Name (+Prj.Prj_Name) & ","); case Dump_Config.Channel is when Binary_File => declare - use GNATCOLL.VFS; - Env_Var : constant String := (if US.Length (Dump_Config.Filename_Env_Var) = 0 then "GNATCOV_RTS_DEFAULT_TRACE_FILENAME_ENV_VAR" else """" & (+Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := - (if US.Length (Dump_Config.Filename_Prefix) = 0 - then """" & String'(+Info.Project.Executable_Name - (+(+Main.Filename), - Include_Suffix => True)) & """" - else """" & (+Dump_Config.Filename_Prefix) & """"); - Tag : constant String := - """" & Trace_Filename_Tag & """"; + """" & (+Dump_Config.Filename_Prefix) & """"; + Tag : constant String := """" & (+Instrumenter.Tag) & """"; Simple : constant String := (if Dump_Config.Filename_Simple then "1" else "0"); begin @@ -3881,21 +3688,18 @@ package body Instrument.C is ------------------------------- overriding procedure Auto_Dump_Buffers_In_Main - (Self : in out C_Family_Instrumenter_Type; - Filename : String; - Instr_Units : CU_Name_Vectors.Vector; - Dump_Config : Any_Dump_Config; - Info : in out Project_Info) + (Self : in out C_Family_Instrumenter_Type; + Filename : String; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc) is - Helper_Filename : US.Unbounded_String; -- Name of file to contain helpers implementing the buffers dump Rew : C_Source_Rewriter; - Main : constant Compilation_Unit_Name := + Main : constant Compilation_Unit_Part := (Language_Kind => File_Based_Language, - Filename => +Ada.Directories.Simple_Name (Filename), - Project_Name => +Info.Project.Name); + Filename => +Ada.Directories.Full_Name (Filename)); Insert_Extern_Location : Source_Location_T; -- Where to insert extern declarations @@ -3903,18 +3707,19 @@ package body Instrument.C is Main_Cursor : Cursor_T; -- Cursor of the main declaration begin - Rew.Start_Rewriting (Info, Filename, Self); + Rew.Start_Rewriting (Filename, Self, Prj); Insert_Extern_Location := Start_Sloc (Get_Translation_Unit_Cursor (Rew.TU)); Main_Cursor := Get_Main (Rew.TU); if Main_Cursor = Get_Null_Cursor then - Outputs.Fatal_Error ("Could not find main function in " - & (+Main.Filename)); + Outputs.Fatal_Error + ("Could not find main function in " + & (Ada.Directories.Simple_Name (+Main.Filename))); end if; Emit_Dump_Helper_Unit - (Dump_Config, Info, Main, Helper_Filename, Self); + (Dump_Config, Main, Helper_Filename, Self, Prj); Put_Extern_Decl (Rew.Rewriter, @@ -4201,30 +4006,34 @@ package body Instrument.C is (Format_Extern_Decl (Instrumenter, C_Type, Name, Func_Args)); end Put_Extern_Decl; - ---------------------------- - -- Emit_Buffers_List_Unit -- - ---------------------------- - overriding procedure Emit_Buffers_List_Unit - (Self : C_Family_Instrumenter_Type; - Root_Project_Info : in out Project_Info; - Instr_Units : CU_Name_Vectors.Vector) + (Self : C_Family_Instrumenter_Type; + Instr_Units : Unit_Sets.Set; + Prj : Prj_Desc) is - Project_Name : String renames Root_Project_Info.Project.Name; - CU_Name_Body : constant String := - "gnatcov_rts_c-buffers-lists-" & Project_Name - & Source_Suffix (Self, GPR.Unit_Body, Root_Project_Info.Project); - File_Body : Text_Files.File_Type; + Base_Filename : constant String := + "gnatcov_rts_c-buffers-lists-" & (+Prj.Prj_Name); + CU_Name_Body : constant String := + Base_Filename + & (+Prj.Body_Suffix + (C_Family_Instrumenter_Type'Class (Self).Language)); + CU_Name_Header : constant String := + Base_Filename + & (+Prj.Spec_Suffix + (C_Family_Instrumenter_Type'Class (Self).Language)); + + File_Body : Text_Files.File_Type; + File_Header : Text_Files.File_Type; Buffer_Array_Decl : constant String := "const struct gnatcov_rts_coverage_buffers_group_array " - & Unit_Buffers_Array_Name (Project_Name); + & Unit_Buffers_Array_Name (+Prj.Prj_Name); Buffer_Unit_Length : constant String := Count_Type'Image (Instr_Units.Length); begin -- Emit the body to contain the list of buffers - Create_File (Root_Project_Info, File_Body, CU_Name_Body); + Create_File (Prj, File_Body, CU_Name_Body); File_Body.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); @@ -4238,308 +4047,33 @@ package body Instrument.C is Unit_Buffers_Name (Instr_Unit)); end loop; - -- Then create an extern declaration for the buffer array (necessary - -- in C++ to set the C linkage), and finally the definition for that - -- array. + -- Then create an extern declaration for the buffer array (necessary in + -- C++ to set the C linkage), and finally the definition for that array. File_Body.Put_Line (Self.Extern_Prefix & Buffer_Array_Decl & ";"); File_Body.Put_Line (Buffer_Array_Decl & " = {"); File_Body.Put_Line (" " & Buffer_Unit_Length & ","); File_Body.Put_Line (" (const struct gnatcov_rts_coverage_buffers_group *[]) {"); - for Cur in Instr_Units.Iterate loop - declare - use CU_Name_Vectors; - begin - File_Body.Put (" &" & Unit_Buffers_Name (Element (Cur))); - if To_Index (Cur) = Instr_Units.Last_Index then - File_Body.Put_Line ("}};"); - else - File_Body.Put_Line (","); - end if; - end; - end loop; - end Emit_Buffers_List_Unit; - - --------------------- - -- Instrument_Unit -- - --------------------- - - overriding procedure Instrument_Unit - (Self : in out C_Family_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Unit_Info : in out Instrumented_Unit_Info) - is - Prj_Info : Project_Info renames Unit_Info.Prj_Info.all; - UIC : C_Unit_Inst_Context; - begin - Instrument_Source_File - (CU_Name => CU_Name, - Unit_Info => Unit_Info, - Instrumenter => Self, - Prj_Info => Prj_Info, - UIC => UIC); - - -- Generate a buffer compilation unit defining coverage buffers that - -- will store execution witnesses. This CU is a C file rather than an - -- Ada file exporting the defined symboled to C. Indeed, we want it to - -- be compatible with a C-only compiler. - - Emit_Buffer_Unit (Prj_Info, UIC, Self); - end Instrument_Unit; - - ---------------------- - -- Skip_Source_File -- - ---------------------- - - overriding function Skip_Source_File - (Self : C_Family_Instrumenter_Type; - Source_File : GNATCOLL.Projects.File_Info) return Boolean is - begin - -- Do not instrument C headers: code in C header is meant to be - -- instrumented at the time it is included in a ".c" source. - - return Source_File.Unit_Part = Unit_Spec; - end Skip_Source_File; - - ----------------- - -- Add_Options -- - ----------------- - - procedure Add_Options - (Args : in out String_Vectors.Vector; - Options : Analysis_Options; - Pass_Builtins : Boolean := True; - Preprocessed : Boolean := False) is - - procedure Add_Macro_Switches (Macros : Macro_Set); - -- Add the given macro switches to Args - - ------------------------ - -- Add_Macro_Switches -- - ------------------------ - - procedure Add_Macro_Switches (Macros : Macro_Set) is - begin - for M of Macros loop - if M.Define then - Args.Append ("-D" & M.Name & M.Args & "=" & M.Value); - else - Args.Append ("-U" & M.Name); - end if; - end loop; - end Add_Macro_Switches; - - begin - for Dir of Options.PP_Search_Path loop - Args.Append (+"-I"); - Args.Append (Dir); - end loop; - - -- If the file was already pre-processed, do not pass macro command - -- line switches. Since preprocessed code can contain names of defined - -- macros, passing macro arguments for the parsing step could trigger - -- other expansions, and thus feed the parser with unexpected code. - - if not Preprocessed then - - -- Add builtin macros before macros from command line switches, as - -- the latter should have precedence over builtins and thus must - -- come last in Args. - - if Pass_Builtins then - Add_Macro_Switches (Options.Builtin_Macros); - end if; - Add_Macro_Switches (Options.PP_Macros); - end if; - - -- The -std switch also indicates the C/C++ version used, and - -- influences both the configuration of the preprocessor, and the - -- parsing of the file. - - if Length (Options.Std) /= 0 then - Args.Append (Options.Std); - end if; - - end Add_Options; - - ------------------------- - -- Import_From_Project -- - ------------------------- - - procedure Import_From_Project - (Self : out Analysis_Options; - Language : C_Family_Language; - Info : Project_Info; - Filename : String) - is - procedure Register_Source_Dirs (P : GNATCOLL.Projects.Project_Type); - -- Add the source directories of P's project file to the search paths - -- to be passed as -I arguments later. The order in which the paths are - -- added to the search paths vector is the same order in which GNATCOLL - -- retrieves the files in the project tree. gprbuild also depends on - -- GNATCOLL which ensures we have the same behavior here. - - -------------------------- - -- Register_Source_Dirs -- - -------------------------- - - procedure Register_Source_Dirs (P : GNATCOLL.Projects.Project_Type) is - begin - for Dir of P.Source_Dirs loop - Self.PP_Search_Path.Append - (+GNATCOLL.VFS."+" (GNATCOLL.VFS.Dir_Name (Dir))); - end loop; - end Register_Source_Dirs; - - Switches : GNAT.Strings.String_List_Access; - - begin - - -- Pass the source directories of the project file as -I options. Note - -- that this will duplicate with the project tree traversal below, but - -- we need this project source directories to be picked first. We thus - -- make sure to add them first to the PP_Search_Path list. - - Register_Source_Dirs (Info.Project); - - -- Pass the source directories of included projects as -I options - - Project.Iterate_Projects - (Info.Project, Register_Source_Dirs'Access, - Recursive => True, Include_Extended => True); - - -- Now get actual compiler switches from the project file for Filename. - -- First try to get the switches specifically for Filename, then if - -- there are none fall back to default switches for C. - - Switches := - Info.Project.Attribute_Value - (Attribute => GPR.Build ("compiler", "switches"), - Index => Simple_Name (Filename)); - - if Switches = null then - Switches := - Info.Project.Attribute_Value - (Attribute => GPR.Compiler_Default_Switches_Attribute, - Index => Image (Language)); - end if; - - -- If we manage to find appropriate switches, convert them to a string - -- vector import the switches. - - if Switches /= null then - declare - Args : String_Vectors.Vector; - begin - for S of Switches.all loop - Args.Append (To_Unbounded_String (S.all)); - end loop; - GNAT.Strings.Free (Switches); - Import_From_Args (Self, Args); - end; - end if; - end Import_From_Project; - - ---------------------- - -- Import_From_Args -- - ---------------------- - - procedure Import_From_Args - (Self : in out Analysis_Options; Args : String_Vectors.Vector) - is - I : Natural := Args.First_Index; - Last : constant Integer := Args.Last_Index; - - function Read_With_Argument - (Arg : String; - Option_Name : Character; - Value : out Unbounded_String) return Boolean; - -- Assuming that Arg starts with "-X" where X is Option_Name, try to - -- fetch the value for this option. If we managed to get one, return - -- True and set Value to it. Return False otherwise. - - ------------------------ - -- Read_With_Argument -- - ------------------------ - - function Read_With_Argument - (Arg : String; - Option_Name : Character; - Value : out Unbounded_String) return Boolean - is - Prefix : constant String := "-" & Option_Name; - begin - if Arg = Prefix then - - -- Option and value are two separate arguments (-O VALUE) - - I := I + 1; - if I <= Last then - Value := Args (I); - return True; - end if; - - elsif Has_Prefix (Arg, Prefix) then - - -- Option and value are combined in a single argument (-OVALUE) - - Value := +Arg (Arg'First + Prefix'Length .. Arg'Last); - return True; + for Instr_Unit of Instr_Units loop + File_Body.Put (" &" & Unit_Buffers_Name (Instr_Unit)); + if Instr_Unit = Instr_Units.Last_Element then + File_Body.Put_Line ("}};"); + else + File_Body.Put_Line (","); end if; + end loop; - return False; - end Read_With_Argument; - - -- Start of processing for Import_From_Args - - begin - while I <= Last loop - declare - A : constant String := +Args (I); - Value : Unbounded_String; - begin - - -- Process arguments we manage to handle, silently discard unknown - -- ones. - -- - -- TODO??? In order to avoid surprising situations for users (for - -- instance typos in command line arguments), maybe we should emit - -- a warning for unknown arguments. However, given that this - -- procedure is called at least once per instrumented source file, - -- we would need to avoid emitting duplicate warnings. - - if Read_With_Argument (A, 'I', Value) then - Self.PP_Search_Path.Append (Value); - - elsif Read_With_Argument (A, 'D', Value) then - declare - Macro_Def : Macro_Definition (Define => True); - Success : Boolean; - begin - Parse_Cmdline_Macro_Definition - (Str => +Value, - Parsed_Def => Macro_Def, - Success => Success); - if Success then - Self.PP_Macros.Include (Macro_Def); - else - Warn ("Failed to parse command-line macro definition: " - & (+Value)); - end if; - end; - - elsif Read_With_Argument (A, 'U', Value) then - Self.PP_Macros.Include ((Define => False, Name => Value)); + -- Emit the extern declaration of the buffers array in the header file - elsif Has_Prefix (A, "-std=") then - Self.Std := +A; - end if; + Create_File (Prj, File_Header, CU_Name_Header); - I := I + 1; - end; - end loop; - end Import_From_Args; + Put_Extern_Decl + (File_Header, + Self, + "const struct gnatcov_rts_coverage_buffers_group_array", + Unit_Buffers_Array_Name (+Prj.Prj_Name)); + end Emit_Buffers_List_Unit; ---------------- -- Split_Args -- @@ -4611,18 +4145,31 @@ package body Instrument.C is -------------------- procedure Import_Options - (Self : out Analysis_Options; - Language : C_Family_Language; - Info : Project_Info; - Filename : String) + (Self : out Analysis_Options; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; + Filename : String) is Cmdline_Opts : constant String_Vectors.Vector := To_String_Vector - (case Language is + (case C_Family_Language (Instrumenter.Language) is when C_Language => C_Opts, when CPP_Language => CPP_Opts); + Prj_Options : String_Vectors.Vector; begin - Import_From_Project (Self, Language, Info, Filename); + -- Grab the options from the project description. Note that the project + -- description is filled with compiler options in the -j1 + -- implementation. Otherwise, the compiler switches in the project files + -- are passed through the command line directly. + + if Prj.Compiler_Options_Unit.Contains (+Filename) then + Prj_Options.Append (Prj.Compiler_Options_Unit.Element (+Filename)); + else + Prj_Options.Append (Prj.Compiler_Options (Instrumenter.Language)); + end if; + Prj_Options.Append (Prj.Search_Paths); + + Import_From_Args (Self, Prj_Options); for Args of Cmdline_Opts loop Import_From_Args (Self, Split_Args (Args)); end loop; @@ -4632,10 +4179,10 @@ package body Instrument.C is Self.Builtin_Macros := Builtin_Macros - (Image (Language), - Compiler_Driver (Info.Project, Language), + (Image (C_Family_Language (Instrumenter.Language)), + +Prj.Compiler_Driver (Instrumenter.Language), +Self.Std, - +Info.Output_Dir).all; + +Prj.Output_Dir).all; end Import_Options; --------------------------- @@ -4663,34 +4210,29 @@ package body Instrument.C is -- if it is missing. declare - use GNATCOLL.VFS; use Source_Of_Interest_Maps; - Cur : constant Cursor := UIC.Sources_Of_Interest.Find (File); + Cur : constant Cursor := UIC.Sources_Of_Interest_Info.Find (File); SOI : Source_Of_Interest; - FI : GNATCOLL.Projects.File_Info; begin if Has_Element (Cur) then - return UIC.Sources_Of_Interest.Reference (Cur).Of_Interest; + return UIC.Sources_Of_Interest_Info.Reference (Cur).Of_Interest; end if; -- Consider that File is of interest iff it belongs to a loaded - -- project. + -- project. TODO???: this should also consider units of interest + -- switches. - FI := Project.Project.Info (Create (+To_String (File))); - if FI.Project /= No_Project then + if UIC.Files_Of_Interest.Contains (File) then SOI := (Of_Interest => True, SFI => Get_Index_From_Generic_Name (+File, Source_File), - CU_Name => - CU_Name_For_File - (Filename => +Simple_Name (+File), - Project_Name => UIC.Instrumented_Unit.Project_Name)); + CU_Name => CU_Name_For_File (File)); else SOI := (Of_Interest => False); end if; - UIC.Sources_Of_Interest.Insert (File, SOI); + UIC.Sources_Of_Interest_Info.Insert (File, SOI); return SOI.Of_Interest; end; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index af0be0c00..f9d89c4c5 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -20,14 +20,10 @@ with Ada.Containers.Hashed_Maps; with Ada.Containers.Ordered_Maps; -with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; with Ada.Finalization; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Hash; -with GNATCOLL.Projects; - with Namet; use Namet; with Clang.Index; use Clang.Index; @@ -43,26 +39,22 @@ package Instrument.C is abstract new Language_Instrumenter with null record; -- Common instrumentation primitives for C/C++ - overriding function Skip_Source_File - (Self : C_Family_Instrumenter_Type; - Source_File : GNATCOLL.Projects.File_Info) return Boolean; - overriding procedure Instrument_Unit - (Self : in out C_Family_Instrumenter_Type; - CU_Name : Compilation_Unit_Name; - Unit_Info : in out Instrumented_Unit_Info); + (Self : in out C_Family_Instrumenter_Type; + Unit_Name : String; + Prj : Prj_Desc; + Files_Of_Interest : String_Sets.Set); overriding procedure Auto_Dump_Buffers_In_Main (Self : in out C_Family_Instrumenter_Type; Filename : String; - Instr_Units : CU_Name_Vectors.Vector; Dump_Config : Any_Dump_Config; - Info : in out Project_Info); + Prj : Prj_Desc); overriding procedure Emit_Buffers_List_Unit - (Self : C_Family_Instrumenter_Type; - Root_Project_Info : in out Project_Info; - Instr_Units : CU_Name_Vectors.Vector); + (Self : C_Family_Instrumenter_Type; + Instr_Units : Unit_Sets.Set; + Prj : Prj_Desc); function Extern_Prefix (Self : C_Family_Instrumenter_Type) return String @@ -77,6 +69,12 @@ package Instrument.C is (Self : C_Instrumenter_Type) return Src_Supported_Language is (C_Language); + function Create_C_Instrumenter + (Tag : Unbounded_String) return C_Instrumenter_Type + is (C_Instrumenter_Type'(Tag => Tag)); + -- Create a C instrumenter. See the definition of the + -- Language_Instrumenter type for the arguments semantic. + type CPP_Instrumenter_Type is new C_Family_Instrumenter_Type with null record; -- Instrumentation primitives for C++ @@ -89,6 +87,12 @@ package Instrument.C is (Self : CPP_Instrumenter_Type) return String is ("extern ""C"" "); + function Create_CPP_Instrumenter + (Tag : Unbounded_String) return CPP_Instrumenter_Type + is (CPP_Instrumenter_Type'(Tag => Tag)); + -- Create a C++ instrumenter. See the definition of the + -- Language_Instrumenter type for the arguments semantic. + type Instr_Scheme_Type is (Instr_Stmt, Instr_Expr); -- Depending on the statement construct, we can instrument it either with -- another statement right before (Instr_Stmt), which is the case for most @@ -232,81 +236,14 @@ package Instrument.C is (Key_Type => Nat, Element_Type => PP_Info); - type Macro_Definition (Define : Boolean := True) is record - Name : Unbounded_String; - -- Name of the macro - - case Define is - when True => - Args : Unbounded_String; - -- String representation of the macro arguments, e.g. (x, y) - - Value : Unbounded_String; - -- Value for the macro definition - - when False => - null; - end case; - end record; - -- Whether a macro should be defined, its name, and when it must be - -- defined, its optional arguments and value. - - function "<" (L, R : Macro_Definition) return Boolean is (L.Name < R.Name); - -- As we store Macro_Definition in sets, we do not want two conflicting - -- definitions of the same macro to coexist. Thus, we compare only the - -- name, meaning that when we insert a new definition, it will replace - -- the previous one. - - package Macro_Sets is new Ada.Containers.Ordered_Sets (Macro_Definition); - subtype Macro_Set is Macro_Sets.Set; - - type Analysis_Options is record - PP_Search_Path : String_Vectors.Vector; - -- List of directories to search when looking for an included file - - Builtin_Macros : Macro_Set; - -- Set of predefined macros for the project compiler driver - - PP_Macros : Macro_Set; - -- Set of macros for the preprocessor - - Std : Unbounded_String; - -- -std=X argument to pass to the preprocessor and the parser, or the - -- empty string. - end record; - -- Options to analyze (preprocess and/or parse) a compilation unit - - procedure Add_Options - (Args : in out String_Vectors.Vector; - Options : Analysis_Options; - Pass_Builtins : Boolean := True; - Preprocessed : Boolean := False); - -- Append to Args the command line options corresponding to Options. If - -- Pass_Builtins is True, pass builtin macros in Options to Args. If - -- Preprocessed is True, consider that we will use these options on a - -- file that was already preprocessed. - - procedure Import_From_Project - (Self : out Analysis_Options; - Language : C_Family_Language; - Info : Project_Info; - Filename : String); - -- Initialize Self from compiler switches corresponding to the Filename - -- source file in the Info project. - - procedure Import_From_Args - (Self : in out Analysis_Options; Args : String_Vectors.Vector); - -- Extract analysis options from the Args command line arguments and update - -- Self accordingly. - function Split_Args (Args : Unbounded_String) return String_Vectors.Vector; -- Split a comma-separated list of arguments procedure Import_Options - (Self : out Analysis_Options; - Language : C_Family_Language; - Info : Project_Info; - Filename : String); + (Self : out Analysis_Options; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; + Filename : String); -- Shortcut to call Import_From_Project, and Import_From_Args on the -- --c-opts/--c++-opts option. @@ -316,7 +253,7 @@ package Instrument.C is null; when True => SFI : Valid_Source_File_Index; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; end case; end record; -- Descriptor for a source file: Of_Interest determines if we should @@ -361,7 +298,8 @@ package Instrument.C is LL_PP_Info_Map : LL_SCO_PP_Info_Maps.Map; -- Preprocessing information for low level SCOs - Sources_Of_Interest : Source_Of_Interest_Maps.Map; + Files_Of_Interest : String_Sets.Set; + Sources_Of_Interest_Info : Source_Of_Interest_Maps.Map; -- Records for each source file processed during the instrumentation -- whether it is a source of interest, and some properties if it is. diff --git a/tools/gnatcov/instrument-c__stub.adb b/tools/gnatcov/instrument-c__stub.adb index 98400eb4d..1b0c5d7f1 100644 --- a/tools/gnatcov/instrument-c__stub.adb +++ b/tools/gnatcov/instrument-c__stub.adb @@ -16,4 +16,8 @@ -- of the license. -- ------------------------------------------------------------------------------ -pragma No_Body; +package body Instrument.C is +begin + Builtin_Support (C_Language) := False; + Builtin_Support (CPP_Language) := False; +end Instrument.C; diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index 3d30db5f9..287fd99b9 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -23,6 +23,8 @@ with Instrument.Common; use Instrument.Common; package Instrument.C is + pragma Elaborate_Body; + type C_Family_Instrumenter_Type is abstract new Language_Instrumenter with null record; -- Common instrumentation primitives for C/C++ @@ -35,6 +37,10 @@ package Instrument.C is (Self : C_Instrumenter_Type) return Src_Supported_Language is (C_Language); + function Create_C_Instrumenter + (Tag : Unbounded_String) return C_Instrumenter_Type + is (C_Instrumenter_Type'(others => <>)); + type CPP_Instrumenter_Type is new C_Family_Instrumenter_Type with null record; -- Instrumentation primitives for C++ @@ -43,8 +49,9 @@ package Instrument.C is (Self : CPP_Instrumenter_Type) return Src_Supported_Language is (CPP_Language); - C_Instrumenter : aliased C_Instrumenter_Type := (null record); - CPP_Instrumenter : aliased CPP_Instrumenter_Type := (null record); + function Create_CPP_Instrumenter + (Tag : Unbounded_String) return CPP_Instrumenter_Type + is (CPP_Instrumenter_Type'(others => <>)); procedure Postprocess_Source (Preprocessed_Filename : String; diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 6b3fda8ea..58155939e 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -16,15 +16,14 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Containers; use Ada.Containers; +with Ada.Containers; use Ada.Containers; with Ada.Containers.Vectors; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Clang.Index; use Clang.Index; with Clang.Rewrite; use Clang.Rewrite; -with Instrument.C; use Instrument.C; -with Slocs; use Slocs; +with Instrument.Common; use Instrument.Common; +with Slocs; use Slocs; package Instrument.C_Utils is diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index abdc8c7e2..62c3e77ba 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -59,7 +59,7 @@ package body Instrument.Checkpoints is for Cur in CP_IU_Map.Iterate loop declare - CP_Unit_Name : constant Compilation_Unit_Name := Key (Cur); + CP_Unit_Name : constant Compilation_Unit_Part := Key (Cur); Existing_Cur : constant Cursor := Instrumented_Unit_CUs.Find (CP_Unit_Name); CU_Ignored : constant Boolean := @@ -128,7 +128,7 @@ package body Instrument.Checkpoints is /= PP_Cmds.Reference (Cur) then Warn ("inconsistent information for instrumented file " - & Get_Unique_Name (SFI)); + & Get_Full_Name (SFI)); end if; end; end if; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index e12d83a29..f31c7ed72 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -18,23 +18,19 @@ with Ada.Containers; use Ada.Containers; with Ada.Directories; -with Ada.Unchecked_Deallocation; -with GNAT.OS_Lib; - -with Interfaces; +with GNATCOLL.VFS; with Coverage; with Diagnostics; -with Hex_Images; +with Outputs; use Outputs; with Paths; use Paths; -with Project; use Project; with SCOs; package body Instrument.Common is function Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name; + (Instrumented_Unit : Compilation_Unit_Part; Buffer_Name : String) return String; -- Helper for Statement_Buffer_Symbol and Decision_Buffer_Symbol. Return -- the name of the symbol for the entity that contains the address of a @@ -49,7 +45,7 @@ package body Instrument.Common is ------------------- function Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name; + (Instrumented_Unit : Compilation_Unit_Part; Buffer_Name : String) return String is Slug : constant String := Instrumented_Unit_Slug (Instrumented_Unit); @@ -62,7 +58,7 @@ package body Instrument.Common is ----------------------------- function Statement_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name) return String is + (Instrumented_Unit : Compilation_Unit_Part) return String is begin return Buffer_Symbol (Instrumented_Unit, "stmt"); end Statement_Buffer_Symbol; @@ -72,7 +68,7 @@ package body Instrument.Common is ---------------------------- function Decision_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name) return String is + (Instrumented_Unit : Compilation_Unit_Part) return String is begin return Buffer_Symbol (Instrumented_Unit, "dc"); end Decision_Buffer_Symbol; @@ -82,35 +78,23 @@ package body Instrument.Common is ------------------------ function MCDC_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name) return String is + (Instrumented_Unit : Compilation_Unit_Part) return String is begin return Buffer_Symbol (Instrumented_Unit, "mcdc"); end MCDC_Buffer_Symbol; - ----------------- - -- Buffer_Unit -- - ----------------- - - function Buffer_Unit - (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name - is - Simple_Name : Ada_Identifier; - begin - Append (Simple_Name, 'B'); - Append (Simple_Name, Instrumented_Unit_Slug (Instrumented_Unit)); - return CU_Name : Ada_Qualified_Name := Sys_Buffers do - CU_Name.Append (Simple_Name); - end return; - end Buffer_Unit; - ----------------------- -- Unit_Buffers_Name -- ----------------------- - function Unit_Buffers_Name (Unit : Compilation_Unit_Name) return String is + function Unit_Buffers_Name (Unit : Compilation_Unit) return String is + Slug : constant String := + (case Unit.Language is + when Unit_Based_Language => + Qualified_Name_Slug (To_Qualified_Name (+Unit.Unit_Name)), + when File_Based_Language => Filename_Slug (+Unit.Unit_Name)); begin - return To_Symbol_Name (Sys_Buffers) & "_" & Instrumented_Unit_Slug (Unit) - & "_buffers"; + return To_Symbol_Name (Sys_Buffers) & "_" & Slug & "_buffers"; end Unit_Buffers_Name; ------------------------ @@ -157,255 +141,6 @@ package body Instrument.Common is return To_String (Result); end Format_Fingerprint; - ------------------------ - -- Trace_Filename_Tag -- - ------------------------ - - function Trace_Filename_Tag return String - is - -- Compute the tag for default source trace filenames. Use the current - -- time as a mostly unique identifier. Put it in hexadecimal form - -- without leading zeros to avoid too long names. - - use Interfaces; - Time : constant Unsigned_64 := - Unsigned_64 (GNAT.OS_Lib.To_C (GNAT.OS_Lib.Current_Time)); - Tag : constant String := - Hex_Images.Strip_Zero_Padding - (Hex_Images.Hex_Image (Time)); - begin - return Tag; - end Trace_Filename_Tag; - - -------------------- - -- Create_Context -- - -------------------- - - function Create_Context - (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context is - begin - return IC : Inst_Context do - IC.Project_Name := +Ada.Directories.Base_Name - (Project.Root_Project_Filename); - -- TODO??? Get the original casing for the project name - - IC.Ignored_Source_Files_Present := Ignored_Source_Files /= null; - if Ignored_Source_Files /= null then - IC.Ignored_Source_Files := Ignored_Source_Files.all; - end if; - end return; - end Create_Context; - - --------------------- - -- Destroy_Context -- - --------------------- - - procedure Destroy_Context (Context : in out Inst_Context) is - procedure Free is new Ada.Unchecked_Deallocation - (Instrumented_Unit_Info, Instrumented_Unit_Info_Access); - procedure Free is new Ada.Unchecked_Deallocation - (Project_Info, Project_Info_Access); - begin - -- Deallocate all Insrtrumented_Unit_Info in Context, and then clear the - -- hashed map, both to avoid dangling pointers and to make - -- Destroy_Context callable more than once, like conventional - -- deallocation procedures in Ada. - - for Cur in Context.Instrumented_Units.Iterate loop - declare - IU : Instrumented_Unit_Info_Access := - Instrumented_Unit_Maps.Element (Cur); - begin - Free (IU); - end; - end loop; - Context.Instrumented_Units := Instrumented_Unit_Maps.Empty_Map; - - -- Likewise for Project_Info records - - for Cur in Context.Project_Info_Map.Iterate loop - declare - PI : Project_Info_Access := Project_Info_Maps.Element (Cur); - begin - Free (PI); - end; - end loop; - Context.Project_Info_Map := Project_Info_Maps.Empty_Map; - end Destroy_Context; - - ---------------------------- - -- Is_Ignored_Source_File -- - ---------------------------- - - function Is_Ignored_Source_File - (Context : Inst_Context; Filename : String) return Boolean is - begin - return - Context.Ignored_Source_Files_Present - and then GNAT.Regexp.Match - (S => Fold_Filename_Casing (Filename), - R => Context.Ignored_Source_Files); - end Is_Ignored_Source_File; - - -------------------------------- - -- Get_Or_Create_Project_Info -- - -------------------------------- - - function Get_Or_Create_Project_Info - (Context : in out Inst_Context; - Project : Project_Type) return Project_Info_Access - is - use Project_Info_Maps; - - -- Look for an existing Project_Info record corresponding to Project - - Project_Name : constant Unbounded_String := +Project.Name; - Position : constant Cursor := Context.Project_Info_Map.Find - (Project_Name); - begin - if Has_Element (Position) then - return Element (Position); - - else - -- The requested Project_Info record does not exist yet. Create it, - -- register it and return it. - - declare - Storage_Project : constant Project_Type := - Project.Extending_Project (Recurse => True); - -- Actual project that will host instrumented sources: even when - -- we instrument an extended project, the resulting instrumented - -- sources must go to the ultimate extending project's object - -- directory. This is similar to the object directory that hosts - -- object files when GPRbuild processes a project that is - -- extended. - - Result : constant Project_Info_Access := new Project_Info' - (Project => Project, - Externally_Built => Project.Externally_Built, - Output_Dir => +Project_Output_Dir (Storage_Project)); - begin - Context.Project_Info_Map.Insert (Project_Name, Result); - return Result; - end; - end if; - end Get_Or_Create_Project_Info; - - --------------- - -- Unit_Info -- - --------------- - - function Unit_Info - (CU_Name : Compilation_Unit_Name; - Info : out GNATCOLL.Projects.File_Info) return Boolean - is - Prj : Project_Type renames Project.Project.Root_Project; - File : constant GNATCOLL.VFS.Filesystem_String := Prj.File_From_Unit - (Unit_Name => To_Ada (CU_Name.Unit), - Part => CU_Name.Part, - Language => "Ada"); - begin - if File'Length = 0 then - return False; - end if; - - Info := Prj.Create_From_Project (File); - return True; - end Unit_Info; - - --------------------------------- - -- Register_Main_To_Instrument -- - --------------------------------- - - procedure Register_Main_To_Instrument - (Context : in out Inst_Context; - Mains : in out Main_To_Instrument_Vectors.Vector; - File : GNATCOLL.VFS.Virtual_File; - Project : Project_Type) - is - File_Info : constant GNATCOLL.Projects.File_Info := - Standard.Project.Project.Info (File); - CU_Name : constant Compilation_Unit_Name := - To_Compilation_Unit_Name (File_Info); - Prj_Info : constant Project_Info_Access := - Get_Or_Create_Project_Info (Context, Project); - begin - Mains.Append - (Main_To_Instrument' - (CU_Name => CU_Name, - File => File, - Prj_Info => Prj_Info)); - end Register_Main_To_Instrument; - - --------------------------- - -- Add_Instrumented_Unit -- - --------------------------- - - procedure Add_Instrumented_Unit - (Context : in out Inst_Context; - Project : GNATCOLL.Projects.Project_Type; - Source_File : GNATCOLL.Projects.File_Info) - is - use GNATCOLL.VFS; - - SF_Basename : constant Filesystem_String := Source_File.File.Base_Name; - begin - pragma Assert (not (Is_Ignored_Source_File (Context, +SF_Basename))); - - declare - CU_Name : constant Compilation_Unit_Name := - To_Compilation_Unit_Name (Source_File); - begin - -- If we already planned to instrument this unit, do nothing more - - if Context.Instrumented_Units.Contains (CU_Name) then - return; - end if; - - -- Otherwise, add it to the list of instrumented units - - declare - Unit_Info : constant Instrumented_Unit_Info_Access := - new Instrumented_Unit_Info' - (Filename => To_Unbounded_String - (+Source_File.File.Full_Name), - Prj_Info => Get_Or_Create_Project_Info (Context, Project), - Language => To_Language (Source_File.Language)); - begin - Context.Instrumented_Units.Insert (CU_Name, Unit_Info); - end; - end; - end Add_Instrumented_Unit; - - -------------- - -- New_File -- - -------------- - - function New_File - (Info : Project_Info; Name : String) return String - is - Base_Filename : constant String := - Ada.Directories.Simple_Name (Name); - Output_Filename : constant String := - To_String (Info.Output_Dir) / Base_Filename; - begin - return Output_Filename; - end New_File; - - ----------------- - -- Create_File -- - ----------------- - - procedure Create_File - (Info : in out Project_Info; - File : in out Text_Files.File_Type; - Name : String) - is - Filename : constant String := New_File (Info, Name); - begin - File.Create (Filename); - end Create_File; - -------------- -- Next_Bit -- -------------- @@ -582,46 +317,299 @@ package body Instrument.Common is end loop; end Remap_Scope_Entity; - ------------------------------ - -- Buffer_Units_For_Closure -- - ------------------------------ + -------------- + -- New_File -- + -------------- + + function New_File + (Prj : Prj_Desc; Name : String) return String + is + Base_Filename : constant String := + Ada.Directories.Simple_Name (Name); + Output_Filename : constant String := + To_String (Prj.Output_Dir) / Base_Filename; + begin + return Output_Filename; + end New_File; + + ----------------- + -- Create_File -- + ----------------- - function Instr_Units_For_Closure - (IC : Inst_Context; - Main : Compilation_Unit_Name) - return CU_Name_Vectors.Vector + procedure Create_File + (Prj : Prj_Desc; + File : in out Text_Files.File_Type; + Name : String) is - pragma Unreferenced (Main); - Result : CU_Name_Vectors.Vector; + Filename : constant String := New_File (Prj, Name); begin - -- TODO??? Here, we need the list of files needed to build Main: specs - -- for units WITHed by main, their bodies, the separates, etc. It's - -- unclear what GNATCOLL.Projects.Get_Closure does, but experimentations - -- show that it's not what we want. So for now, return an approximation: - -- buffer units for all instrumented units. In the future, we should - -- either get this service from GNATCOLL.Projects, either re-implement - -- it on top of Libadalang. - - for Cur in IC.Instrumented_Units.Iterate loop + File.Create (Filename); + end Create_File; + + ----------------- + -- To_Filename -- + ----------------- + + function To_Filename + (Prj : Prj_Desc; + Lang : Src_Supported_Language; + CU_Name : Compilation_Unit_Part) return String + is + Filename : Unbounded_String; + begin + case CU_Name.Language_Kind is + when Unit_Based_Language => + for Id of CU_Name.Unit loop + if Length (Filename) > 0 then + Append (Filename, Prj.Dot_Replacement); + end if; + Append (Filename, To_Lower (To_String (Id))); + end loop; + + case CU_Name.Part is + when Unit_Body | Unit_Separate => + Append (Filename, Prj.Body_Suffix (Lang)); + when Unit_Spec => + Append (Filename, Prj.Spec_Suffix (Lang)); + end case; + when File_Based_Language => + Filename := CU_Name.Filename; + end case; + return +Filename; + end To_Filename; + + ----------------- + -- Add_Options -- + ----------------- + + procedure Add_Options + (Args : in out String_Vectors.Vector; + Options : Analysis_Options; + Pass_Builtins : Boolean := True; + Preprocessed : Boolean := False) is + + procedure Add_Macro_Switches (Macros : Macro_Set); + -- Add the given macro switches to Args + + ------------------------ + -- Add_Macro_Switches -- + ------------------------ + + procedure Add_Macro_Switches (Macros : Macro_Set) is + begin + for M of Macros loop + if M.Define then + Args.Append ("-D" & M.Name & M.Args & "=" & M.Value); + else + Args.Append ("-U" & M.Name); + end if; + end loop; + end Add_Macro_Switches; + + begin + for Dir of Options.PP_Search_Path loop + Args.Append (+"-I"); + Args.Append (Dir); + end loop; + + -- If the file was already pre-processed, do not pass macro command + -- line switches. Since preprocessed code can contain names of defined + -- macros, passing macro arguments for the parsing step could trigger + -- other expansions, and thus feed the parser with unexpected code. + + if not Preprocessed then + + -- Add builtin macros before macros from command line switches, as + -- the latter should have precedence over builtins and thus must + -- come last in Args. + + if Pass_Builtins then + Add_Macro_Switches (Options.Builtin_Macros); + end if; + Add_Macro_Switches (Options.PP_Macros); + end if; + + -- The -std switch also indicates the C/C++ version used, and + -- influences both the configuration of the preprocessor, and the + -- parsing of the file. + + if Length (Options.Std) /= 0 then + Args.Append (Options.Std); + end if; + + end Add_Options; + + ---------------------------- + -- Parse_Macro_Definition -- + ---------------------------- + + procedure Parse_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean) + is + Matches : Match_Array (0 .. 3); + begin + Match (Macro_Def_Regexp, Str, Matches); + if Matches (0) = No_Match then + Success := False; + else + Success := True; + Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); + if Matches (2) /= No_Match then + Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); + end if; + Parsed_Def.Value := +Str (Matches (3).First .. Matches (3).Last); + end if; + end Parse_Macro_Definition; + + ------------------------------------ + -- Parse_Cmdline_Macro_Definition -- + ------------------------------------ + + procedure Parse_Cmdline_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean) + is + Matches : Match_Array (0 .. 4); + begin + Match (Macro_Cmdline_Regexp, Str, Matches); + if Matches (0) = No_Match then + Success := False; + else + Success := True; + Parsed_Def.Name := +Str (Matches (1).First .. Matches (1).Last); + if Matches (2) /= No_Match then + Parsed_Def.Args := +Str (Matches (2).First .. Matches (2).Last); + end if; + + -- Command line macros can have part of their value before the + -- assignment, e.g. "-DA(b)b" is equivalent to "#define A(b) b 1". + + if Matches (3) /= No_Match then + Append + (Parsed_Def.Value, + Str (Matches (3).First .. Matches (3).Last) & " "); + end if; + + -- If no value is given, then it is implicitly 1 + + if Matches (4) /= No_Match then + Append + (Parsed_Def.Value, Str (Matches (4).First .. Matches (4).Last)); + else + Append (Parsed_Def.Value, " 1"); + end if; + end if; + end Parse_Cmdline_Macro_Definition; + + ---------------------- + -- Import_From_Args -- + ---------------------- + + procedure Import_From_Args + (Self : in out Analysis_Options; Args : String_Vectors.Vector) + is + I : Natural := Args.First_Index; + Last : constant Integer := Args.Last_Index; + + function Read_With_Argument + (Arg : String; + Option_Name : Character; + Value : out Unbounded_String) return Boolean; + -- Assuming that Arg starts with "-X" where X is Option_Name, try to + -- fetch the value for this option. If we managed to get one, return + -- True and set Value to it. Return False otherwise. + + ------------------------ + -- Read_With_Argument -- + ------------------------ + + function Read_With_Argument + (Arg : String; + Option_Name : Character; + Value : out Unbounded_String) return Boolean + is + Prefix : constant String := "-" & Option_Name; + begin + if Arg = Prefix then + + -- Option and value are two separate arguments (-O VALUE) + + I := I + 1; + if I <= Last then + Value := Args (I); + return True; + end if; + + elsif Has_Prefix (Arg, Prefix) then + + -- Option and value are combined in a single argument (-OVALUE) + + Value := +Arg (Arg'First + Prefix'Length .. Arg'Last); + return True; + end if; + + return False; + end Read_With_Argument; + + -- Start of processing for Import_From_Args + + begin + while I <= Last loop declare - Instr_Unit : constant Compilation_Unit_Name := - Instrumented_Unit_Maps.Key (Cur); + A : constant String := +Args (I); + Value : Unbounded_String; begin - Result.Append (Instr_Unit); + + -- Process arguments we manage to handle, silently discard unknown + -- ones. + -- + -- TODO??? In order to avoid surprising situations for users (for + -- instance typos in command line arguments), maybe we should emit + -- a warning for unknown arguments. However, given that this + -- procedure is called at least once per instrumented source file, + -- we would need to avoid emitting duplicate warnings. + + if Read_With_Argument (A, 'I', Value) then + Self.PP_Search_Path.Append (Value); + + elsif Read_With_Argument (A, 'D', Value) then + declare + Macro_Def : Macro_Definition (Define => True); + Success : Boolean; + begin + Parse_Cmdline_Macro_Definition + (Str => +Value, + Parsed_Def => Macro_Def, + Success => Success); + if Success then + Self.PP_Macros.Include (Macro_Def); + else + Warn ("Failed to parse command-line macro definition: " + & (+Value)); + end if; + end; + + elsif Read_With_Argument (A, 'U', Value) then + Self.PP_Macros.Include ((Define => False, Name => Value)); + + elsif Has_Prefix (A, "-std=") then + Self.Std := +A; + end if; + + I := I + 1; end; end loop; - return Result; - end Instr_Units_For_Closure; + end Import_From_Args; begin - Sys_Prefix.Append (To_Unbounded_String ("GNATcov_RTS")); + Sys_Prefix.Append (To_Unbounded_String ("GCVRT")); - Sys_Buffers := Sys_Prefix; + Sys_Buffers.Append (To_Unbounded_String ("GNATcov_RTS")); Sys_Buffers.Append (To_Unbounded_String ("Buffers")); - Sys_Buffers_Lists := Sys_Buffers; - Sys_Buffers_Lists.Append (To_Unbounded_String ("Lists")); - Statement_Buffer_Name.Append (To_Unbounded_String ("Statement_Buffer")); Decision_Buffer_Name.Append (To_Unbounded_String ("Decision_Buffer")); MCDC_Buffer_Name.Append (To_Unbounded_String ("MCDC_Buffer")); diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 7293a2f1d..dc050968d 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -50,21 +50,21 @@ -- buffers for the unit. with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Containers.Hashed_Maps; with Ada.Containers.Hashed_Sets; with Ada.Containers.Ordered_Maps; +with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Hash; -with Ada.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; -with GNATCOLL.VFS; +with GNAT.Regpat; use GNAT.Regpat; -with ALI_Files; use ALI_Files; -with Files_Table; use Files_Table; +with GNATCOLL.JSON; use GNATCOLL.JSON; + +with ALI_Files; use ALI_Files; +with Files_Table; use Files_Table; with GNATcov_RTS; -with Namet; use Namet; -with Slocs; use Slocs; +with Namet; use Namet; +with Slocs; use Slocs; with Text_Files; package Instrument.Common is @@ -76,11 +76,7 @@ package Instrument.Common is -- sources. Sys_Buffers : Ada_Qualified_Name; - -- Scope in Sys_Prefix for all packages to contain coverage buffers - - Sys_Buffers_Lists : Ada_Qualified_Name; - -- Scope in Sys_Prefix for all packages to contain generic procedures for - -- iterations on coverage buffers. + -- Runtime package containing coverage buffer type definitions Statement_Buffer_Name : Ada_Qualified_Name; -- Qualified name (relative to the unit buffer package) of the buffer to @@ -110,36 +106,30 @@ package Instrument.Common is -- handler. function Dump_Procedure_Symbol - (Main : Compilation_Unit_Name) return String + (Main : Compilation_Unit_Part) return String is ("gnatcov_rts_" & Instrumented_Unit_Slug (Main) & "_" & To_Lower (To_String (Dump_Procedure_Name))); -- Return the name of the exported symbol for the Dump_Buffers function function Statement_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name) return String; + (Instrumented_Unit : Compilation_Unit_Part) return String; -- Given a unit to instrument, return the name of the symbol to use for the -- entity that contains address of the statement coverage buffer. function Decision_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name) return String; + (Instrumented_Unit : Compilation_Unit_Part) return String; -- Given a unit to instrument, return the name of the symbol to use for the -- entity that contains address of the decision coverage buffer. function MCDC_Buffer_Symbol - (Instrumented_Unit : Compilation_Unit_Name) return String; + (Instrumented_Unit : Compilation_Unit_Part) return String; -- Given a unit to instrument, return the name of the symbol to use for the -- entity that contains address of the decision coverage buffer. - function Buffer_Unit - (Instrumented_Unit : Compilation_Unit_Name) return Ada_Qualified_Name; - -- Given a unit to instrument, return the name of the unit that holds - -- its coverage buffers (Coverage_Buffer_Type and - -- GNATcov_RTS_Coverage_Buffers records). - - function Unit_Buffers_Name (Unit : Compilation_Unit_Name) return String; + function Unit_Buffers_Name (Unit : Compilation_Unit) return String; -- Name of the symbol that references the - -- gnatcov_rts_coverage_buffers_group struct for this unit. + -- gnatcov_rts_coverage_buffers_group struct for this file. function Unit_Buffers_Array_Name (Prj_Name : String) return String is ("gnatcov_rts_buffers_array_" & Prj_Name); @@ -166,64 +156,16 @@ package Instrument.Common is -- returned literal expression (aggregate in Ada, compound expression in -- C/C++). - function Trace_Filename_Tag return String; - -- Tag for the source trace filename. This allows differentiating trace - -- files produced by a specific program instrumentation from the ones - -- produced by other instrumentations. - package File_Sets is new Ada.Containers.Hashed_Sets (Element_Type => Ada.Strings.Unbounded.Unbounded_String, "=" => Ada.Strings.Unbounded."=", Equivalent_Elements => Ada.Strings.Unbounded."=", Hash => Ada.Strings.Unbounded.Hash); - type Project_Info is record - Project : Project_Type; - -- Project that this record describes - - Externally_Built : Boolean; - -- Whether this project is externally built. In that case, we assume its - -- units of interest have already been instrumented. - - Output_Dir : Ada.Strings.Unbounded.Unbounded_String; - -- Subdirectory in the project file's object directory. All we generate - -- for this project must land in it. - end record; - - type Project_Info_Access is access all Project_Info; - - package Project_Info_Maps is new Ada.Containers.Hashed_Maps - (Key_Type => Ada.Strings.Unbounded.Unbounded_String, - Element_Type => Project_Info_Access, - Equivalent_Keys => Ada.Strings.Unbounded."=", - Hash => Ada.Strings.Unbounded.Hash); - -- Mapping from project name (as returned by GNATCOLL.Projects.Name) to - -- Project_Info records. Project_Info records are owned by this map, and - -- thus must be deallocated when maps are deallocated. - - type Main_To_Instrument is record - CU_Name : Compilation_Unit_Name; - -- Compilation unit of the main to instrument - - File : GNATCOLL.VFS.Virtual_File; - -- Source file to instrument - - Prj_Info : Project_Info_Access; - -- Reference to the Project_Info record corresponding to the project - -- that owns the main to instrument. - end record; - - package Main_To_Instrument_Vectors is new Ada.Containers.Vectors - (Positive, Main_To_Instrument); - type Instrumented_Unit_Info is record Filename : Ada.Strings.Unbounded.Unbounded_String; -- Name of the source file for this unit - Prj_Info : Project_Info_Access; - -- Reference to the Project_Info record corresponding to the project - -- that owns the source file for this unit. - Language : Some_Language; -- Language for this unit end record; @@ -231,81 +173,9 @@ package Instrument.Common is type Instrumented_Unit_Info_Access is access all Instrumented_Unit_Info; package Instrumented_Unit_Maps is new Ada.Containers.Ordered_Maps - (Key_Type => Compilation_Unit_Name, + (Key_Type => Compilation_Unit_Part, Element_Type => Instrumented_Unit_Info_Access); - type Inst_Context is limited record - Project_Name : Ada.Strings.Unbounded.Unbounded_String; - -- Name of the root project. It is also used to name the list of buffers - - Ignored_Source_Files_Present : Boolean; - Ignored_Source_Files : GNAT.Regexp.Regexp; - -- If present, instrumentation will ignore files whose names match the - -- accessed pattern. - - Instrumented_Units : Instrumented_Unit_Maps.Map; - -- Mapping from instrumented unit names to information used during - -- instrumentation. - - Project_Info_Map : Project_Info_Maps.Map; - -- For each project that contains units of interest, this tracks a - -- Project_Info record. - end record; - - function Create_Context - (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context; - -- Create an instrumentation context for the currently loaded project - - procedure Destroy_Context (Context : in out Inst_Context); - -- Free dynamically allocated resources in Context - - function Is_Ignored_Source_File - (Context : Inst_Context; Filename : String) return Boolean; - -- Return whether the instrumentation process must ignore the Filename - -- source file. - - function Get_Or_Create_Project_Info - (Context : in out Inst_Context; - Project : Project_Type) return Project_Info_Access; - -- Return the Project_Info record corresponding to Project. Create it if it - -- does not exist. - - function Unit_Info - (CU_Name : Compilation_Unit_Name; - Info : out GNATCOLL.Projects.File_Info) return Boolean; - -- Look for a compilation unit in the loaded project. If found, put its - -- file info in Info and return True. Return False otherwise. - - procedure Register_Main_To_Instrument - (Context : in out Inst_Context; - Mains : in out Main_To_Instrument_Vectors.Vector; - File : GNATCOLL.VFS.Virtual_File; - Project : Project_Type); - -- Register in Mains a main to be instrumented so that it dumps coverage - -- buffers. File is the source file for this main, and Project is the - -- project that owns this main. If File is actually a unit of interest in - -- Context, do nothing. - - procedure Add_Instrumented_Unit - (Context : in out Inst_Context; - Project : GNATCOLL.Projects.Project_Type; - Source_File : GNATCOLL.Projects.File_Info); - -- Add the given source file to the list of units to instrument - - function New_File - (Info : Project_Info; Name : String) return String; - -- Compute the path to the file to create in Info.Output_Dir - - procedure Create_File - (Info : in out Project_Info; - File : in out Text_Files.File_Type; - Name : String); - -- Shortcut to Text_Files.Create: create a text file with the given name in - -- Info.Output_Dir. - -- - -- Name can be a basename, a relative name or an absolute one: in all - -- cases, the basename is taken and the file is created in Info.Output_Dir. - ------------------------------------------------------ -- Common declarations for Ada / C instrumentation -- ------------------------------------------------------ @@ -395,9 +265,12 @@ package Instrument.Common is package Allocated_Bits_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Allocated_Bits); -- Allocated bits in coverage buffers for low-level SCOs (one per source - -- file). Because of #include directives in C/C++, a single compilation - -- unit may yield multiple sets of coverage buffers: one for the compiled - -- source file, one for each included source. + -- file). A single compilation unit may yield multiple sets of coverage + -- buffers: one for each part of the unit in the case of unit-based + -- language units (the spec, the body, and the separates). It may also be + -- the case for unit of file-based languages: one for the compiled source + -- file and one for each included source (e.g. through inclusion directives + -- for C and C++). function Create_Unit_Bits (Allocated_Bits : in out Allocated_Bits_Vectors.Vector; @@ -433,16 +306,16 @@ package Instrument.Common is (Index_Type => Positive, Element_Type => Annotation_Couple); type Unit_Inst_Context is tagged record - Instrumented_Unit : Compilation_Unit_Name; + Instrumented_Unit : Compilation_Unit_Part; -- Name of the compilation unit being instrumented - Language_Version_Pragma : Unbounded_Wide_Wide_String; - -- Language version configuration pragma for unit, if any - SFI : Source_File_Index := No_Source_File; -- Source file index of the compilation unit being instrumented - Buffer_Unit : Compilation_Unit_Name; + Fullname : Unbounded_String; + -- Fullname of the compilation unit being instrumented + + Buffer_Unit : Compilation_Unit_Part; -- Name of the compilation unit that holds coverage buffers for the -- unit currently being instrumented (see Common.Buffer_Unit). @@ -492,19 +365,18 @@ package Instrument.Common is package CU_Name_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, - Element_Type => Compilation_Unit_Name); + Element_Type => Compilation_Unit_Part); package Ada_Qualified_Name_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Ada_Qualified_Name, "=" => Ada_Identifier_Vectors."="); - function Instr_Units_For_Closure - (IC : Inst_Context; - Main : Compilation_Unit_Name) return CU_Name_Vectors.Vector; - -- Return the list of instrumented units in Main's closure + type Language_Instrumenter is abstract tagged record + Tag : Unbounded_String; + -- Tag specific to an instrumentation run - type Language_Instrumenter is abstract tagged null record; + end record; -- Set of operations to allow the instrumentation of sources files for a -- given language. @@ -512,44 +384,166 @@ package Instrument.Common is (Self : Language_Instrumenter) return Src_Supported_Language is abstract; -- Return the language that this instrumenter is designed to process - function Skip_Source_File - (Self : Language_Instrumenter; - Source_File : GNATCOLL.Projects.File_Info) return Boolean - is (True); - -- Whether the instrumenter skips the given source file. The default - -- (undefined) instrumenter skips every source file. - procedure Instrument_Unit - (Self : in out Language_Instrumenter; - CU_Name : Compilation_Unit_Name; - Unit_Info : in out Instrumented_Unit_Info) is null; + (Self : in out Language_Instrumenter; + Unit_Name : String; + Prj : Prj_Desc; + Files_Of_Interest : String_Sets.Set) is null; -- Instrument a single source file for the language that Self supports. -- - -- CU_Name must be the name of the compilation unit for this source file, - -- and Unit_Info must be the Instrumented_Unit_Info record corresponding to - -- this source file. + -- Unit_Name identifies this compilation unit (either through a unit name, + -- for Unit_Based_Language, or through a full name, for file-based). Prj + -- describes information coming from the project, and relevant to the + -- instrumentation of the unit. Files_Of_Interest provides the list of + -- files of interest, to ignore e.g. part of the unit (e.g. a separate) + -- when instrumenting it. procedure Auto_Dump_Buffers_In_Main - (Self : in out Language_Instrumenter; - Filename : String; - Instr_Units : CU_Name_Vectors.Vector; - Dump_Config : Any_Dump_Config; - Info : in out Project_Info) is null; + (Self : in out Language_Instrumenter; + Filename : String; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc) is null; -- Try to instrument the Filename source file (whose language is assumed - -- to be Self's) to insert a call to dump the list of coverage buffers for - -- all Instr_Units, according to the Dump_Config options. Do nothing if not - -- successful. - -- - -- Info must be the Project_Info record corresponding to the project that - -- owns Filename's compilation unit. + -- to be Self's) to insert a call to dump the list of coverage buffers, + -- assumed to be named after Prj.Prj_Name. Do nothing if not successful. procedure Emit_Buffers_List_Unit - (Self : Language_Instrumenter; - Root_Project_Info : in out Project_Info; - Instr_Units : CU_Name_Vectors.Vector) is null; + (Self : Language_Instrumenter; + Instr_Units : Unit_Sets.Set; + Prj : Prj_Desc) is null; + -- Emit in the root project a unit (in Self's language) to contain the list + -- of coverage buffers for the given instrumented files. + -- -- The variable holding the list of coverage buffers is exported to a -- unique C symbol whose name is defined by the Unit_Buffers_Array_Name -- function. This procedure should thus be called only once, for one of -- the supported languages of the project. + function New_File + (Prj : Prj_Desc; Name : String) return String; + -- Compute the path to the file to create in Self.Output_Dir + + procedure Create_File + (Prj : Prj_Desc; + File : in out Text_Files.File_Type; + Name : String); + -- Shortcut to Text_Files.Create: create a text file with the given name in + -- Prj.Output_Dir. + -- + -- Name can be a basename, a relative name or an absolute one: in all + -- cases, the basename is taken and the file is created in Prj.Output_Dir. + + function To_Filename + (Prj : Prj_Desc; + Lang : Src_Supported_Language; + CU_Name : Compilation_Unit_Part) return String; + -- Convert a Compilation_Unit_Name to a file basename, using the body / + -- spec suffix and dot replacement (for unit based languages) defined in + -- Prj. + + type Macro_Definition (Define : Boolean := True) is record + Name : Unbounded_String; + -- Name of the macro + + case Define is + when True => + Args : Unbounded_String; + -- String representation of the macro arguments, e.g. (x, y) + + Value : Unbounded_String; + -- Value for the macro definition + + when False => + null; + end case; + end record; + -- Whether a macro should be defined, its name, and when it must be + -- defined, its optional arguments and value. + + function "<" (L, R : Macro_Definition) return Boolean is (L.Name < R.Name); + -- As we store Macro_Definition in sets, we do not want two conflicting + -- definitions of the same macro to coexist. Thus, we compare only the + -- name, meaning that when we insert a new definition, it will replace + -- the previous one. + + package Macro_Sets is new Ada.Containers.Ordered_Sets (Macro_Definition); + subtype Macro_Set is Macro_Sets.Set; + + type Analysis_Options is record + PP_Search_Path : String_Vectors.Vector; + -- List of directories to search when looking for an included file + + Builtin_Macros : Macro_Set; + -- Set of predefined macros for the project compiler driver + + PP_Macros : Macro_Set; + -- Set of macros for the preprocessor + + Std : Unbounded_String; + -- -std=X argument to pass to the preprocessor and the parser, or the + -- empty string. + end record; + -- Options to analyze (preprocess and/or parse) a compilation unit + + Macro_Cmdline_Regexp : constant Pattern_Matcher := Compile ( + "([a-zA-Z_]\w*)" + -- The name of the macro + + & "(\(.*\))?" + -- The optional list of macro arguments + + & "([^ =]+)?" + -- Then, there can be any character before the assignment: they will be + -- part of the macro value (e.g. A(b)b will yield #define A b 1) + + & "(?:=(.*))?" + -- The macro value itself + ); + + Macro_Def_Regexp : constant Pattern_Matcher := Compile ( + "#define" + & "(?: |\t)+" + -- "#define", then a non-empty blank + + & "([a-zA-Z_]\w*)" + -- The name of the macro + + & "(\(.*\))?" + -- The optional list of macro arguments + + & "(.*)" + -- The macro value itself + ); + -- Regular expression to analyze definitions for builtin macros (see + -- Builtin_Macros) + + procedure Parse_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean); + -- Parse a macro definition. If the parsing failed, set Success to False. + -- Otherwise, set Parsed_Def to the parsed definition and set Success to + -- True. + + procedure Parse_Cmdline_Macro_Definition + (Str : String; + Parsed_Def : out Macro_Definition; + Success : out Boolean); + -- Same as above, but with a command-line macro definition + + procedure Add_Options + (Args : in out String_Vectors.Vector; + Options : Analysis_Options; + Pass_Builtins : Boolean := True; + Preprocessed : Boolean := False); + -- Append to Args the command line options corresponding to Options. If + -- Pass_Builtins is True, pass builtin macros in Options to Args. If + -- Preprocessed is True, consider that we will use these options on a + -- file that was already preprocessed. + + procedure Import_From_Args + (Self : in out Analysis_Options; Args : String_Vectors.Vector); + -- Extract analysis options from the Args command line arguments and update + -- Self accordingly. + end Instrument.Common; diff --git a/tools/gnatcov/instrument-config.adb b/tools/gnatcov/instrument-config.adb new file mode 100644 index 000000000..52c04a534 --- /dev/null +++ b/tools/gnatcov/instrument-config.adb @@ -0,0 +1,50 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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 Command_Line; use Command_Line; +with Instrument.Ada_Unit; use Instrument.Ada_Unit; +with Instrument.C; use Instrument.C; +with Instrument.Common; use Instrument.Common; +with Strings; use Strings; + +-- Return the instrumenter configuration generated from the command line + +function Instrument.Config return Language_Instrumenter'Class +is + use Command_Line.Parser; + Language : constant Some_Language := + To_Language (+Args.String_Args (Opt_Lang).Value); + Tag : constant Unbounded_String := + Value_Or_Null (Args.String_Args (Opt_Dump_Filename_Tag)); +begin + case Language is + when Ada_Language => + return Create_Ada_Instrumenter + (Tag => Tag, + Config_Pragmas_Filename => + +Args.String_Args (Opt_Gnatec).Value, + Mapping_Filename => + +Args.String_Args (Opt_Gnatem).Value, + Predefined_Source_Dirs => + Args.String_List_Args (Opt_Runtime_Dir)); + when C_Language => + return Create_C_Instrumenter (Tag => Tag); + when CPP_Language => + return Create_CPP_Instrumenter (Tag => Tag); + end case; +end Instrument.Config; diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 397c4fa76..18da8e0a4 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -136,7 +136,6 @@ package body Instrument.Input_Traces is type Trace_Entry_Elements is record Unit_Name : System.Address; - Project_Name : System.Address; Statement_Buffer : System.Address; Decision_Buffer : System.Address; MCDC_Buffer : System.Address; @@ -164,7 +163,7 @@ package body Instrument.Input_Traces is (Stream : in out Binary_Stream; File_Header : Trace_File_Header; Kind : out Supported_Info_Kind; - Data : out String_Access; + Data : out GNAT.OS_Lib.String_Access; Result : in out Read_Result) with Pre => Result.Success; -- Read a trace info entry from Stream. Return an error if something wrong @@ -395,7 +394,7 @@ package body Instrument.Input_Traces is (Stream : in out Binary_Stream; File_Header : Trace_File_Header; Kind : out Supported_Info_Kind; - Data : out String_Access; + Data : out GNAT.OS_Lib.String_Access; Result : in out Read_Result) is Ignored_EOF : Boolean; @@ -493,7 +492,6 @@ package body Instrument.Input_Traces is if File_Header.Endianity /= Native_Endianity then Swap4 (Raw_Header.Unit_Name_Length'Address); - Swap4 (Raw_Header.Project_Name_Length'Address); Swap4 (Raw_Header.Statement_Bit_Count'Address); Swap4 (Raw_Header.Decision_Bit_Count'Address); Swap4 (Raw_Header.MCDC_Bit_Count'Address); @@ -525,7 +523,7 @@ package body Instrument.Input_Traces is Create_Error (Result, "invalid bit buffer encoding"); return False; - elsif Raw_Header.Padding /= (1 => ASCII.NUL) then + elsif Raw_Header.Padding /= (1 .. 5 => ASCII.NUL) then Create_Error (Result, "invalid entry header padding"); return False; end if; @@ -540,12 +538,9 @@ package body Instrument.Input_Traces is Unit_Name_Range : constant Buffer_Range := Range_For (File_Header.Alignment, 0, Natural (Entry_Header.Unit_Name_Length)); - Project_Name_Range : constant Buffer_Range := - Range_For (File_Header.Alignment, Offset_After (Unit_Name_Range), - Natural (Entry_Header.Project_Name_Length)); Statement_Buffer_Range : constant Buffer_Range := Range_For (File_Header.Alignment, - Offset_After (Project_Name_Range), + Offset_After (Unit_Name_Range), Buffer_Size (Entry_Header.Bit_Buffer_Encoding, Entry_Header.Statement_Bit_Count)); Decision_Buffer_Range : constant Buffer_Range := @@ -578,7 +573,6 @@ package body Instrument.Input_Traces is Base_Address := Buffer_Address (Stream); Trace_Entry := (Base_Address + Unit_Name_Range.Offset, - Base_Address + Project_Name_Range.Offset, Base_Address + Statement_Buffer_Range.Offset, Base_Address + Decision_Buffer_Range.Offset, Base_Address + MCDC_Buffer_Range.Offset); @@ -661,7 +655,7 @@ package body Instrument.Input_Traces is loop declare Kind : Supported_Info_Kind; - Data : String_Access; + Data : GNAT.OS_Lib.String_Access; begin Read_Trace_Info (Stream, File_Header, Kind, Data, Result); if not Result.Success then @@ -689,10 +683,6 @@ package body Instrument.Input_Traces is (1 .. Natural (Entry_Header.Unit_Name_Length)) with Import, Address => Trace_Entry.Unit_Name; - Project_Name : constant String - (1 .. Natural (Entry_Header.Project_Name_Length)) - with Import, Address => Trace_Entry.Project_Name; - function Convert is new Ada.Unchecked_Conversion (GNATcov_RTS.Buffers.Fingerprint_Type, SC_Obligations.Fingerprint_Type); @@ -725,7 +715,7 @@ package body Instrument.Input_Traces is function Last_Bit (Bit_Count : Any_Bit_Count) return Any_Bit_Id is (Any_Bit_Id (Bit_Count) - 1); - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; begin Reserve (Statement_Buffer, Entry_Header.Statement_Bit_Count); @@ -767,7 +757,7 @@ package body Instrument.Input_Traces is (Unit => To_Qualified_Name (Unit_Name), Part => Unit_Part_Map (Entry_Header.Unit_Part)); when GNATcov_RTS.Buffers.File_Based_Language => - CU_Name := CU_Name_For_File (+Unit_Name, +Project_Name); + CU_Name := CU_Name_For_File (+Unit_Name); end case; On_Trace_Entry @@ -803,7 +793,7 @@ package body Instrument.Input_Traces is procedure On_Trace_Entry (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; @@ -843,7 +833,7 @@ package body Instrument.Input_Traces is procedure On_Trace_Entry (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/instrument-input_traces.ads b/tools/gnatcov/instrument-input_traces.ads index 7c8d7137c..43ed20190 100644 --- a/tools/gnatcov/instrument-input_traces.ads +++ b/tools/gnatcov/instrument-input_traces.ads @@ -34,7 +34,7 @@ package Instrument.Input_Traces is with procedure On_Trace_Entry (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; Stmt_Buffer : Coverage_Buffer; Decision_Buffer : Coverage_Buffer; diff --git a/tools/gnatcov/instrument-main.adb b/tools/gnatcov/instrument-main.adb new file mode 100644 index 000000000..134475d8b --- /dev/null +++ b/tools/gnatcov/instrument-main.adb @@ -0,0 +1,41 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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 Instrument.Common; use Instrument.Common; + +-- Implementation of the gnatcov instrument-main, which inserts a call to +-- dump coverage buffers according to the various dump options passed +-- on the command line. + +procedure Instrument.Main + (Instrumenter : in out Language_Instrumenter'Class; + Dump_Config : Any_Dump_Config; + Main_Filename : String; + Prj : Prj_Desc) is +begin + -- If the dump-trigger is manual, there is nothing to do + + if Dump_Config.Trigger = Manual then + return; + end if; + + Instrumenter.Auto_Dump_Buffers_In_Main + (Filename => Main_Filename, + Dump_Config => Dump_Config, + Prj => Prj); +end Instrument.Main; diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb new file mode 100644 index 000000000..98c1b9139 --- /dev/null +++ b/tools/gnatcov/instrument-projects.adb @@ -0,0 +1,1225 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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.Characters.Handling; use Ada.Characters.Handling; +with Ada.Containers.Hashed_Maps; +with Ada.Containers.Indefinite_Ordered_Maps; +with Ada.Containers.Indefinite_Ordered_Sets; +with Ada.Directories; +with Ada.Exceptions; +with Ada.Strings; +with Ada.Strings.Fixed; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Strings.Unbounded.Hash; +with Ada.Unchecked_Deallocation; + +with Interfaces; use Interfaces; + +with GNAT.OS_Lib; +with GNAT.Regexp; +with GNAT.Strings; + +with GNATCOLL.JSON; use GNATCOLL.JSON; +with GNATCOLL.VFS; +with GNATCOLL.Projects.Aux; use GNATCOLL.Projects.Aux; + +with Command_Line; use Command_Line; +with Files_Table; +with Hex_Images; use Hex_Images; +with Instrument.Ada_Unit; use Instrument.Ada_Unit; +with Instrument.C; use Instrument.C; +with Instrument.Clean_Objdirs; +with Instrument.Common; use Instrument.Common; +with Instrument.Main; +with Instrument.Source; +with JSON; use JSON; +with Outputs; +with Paths; use Paths; +with Project; use Project; +with Strings; use Strings; +with Support_Files; +with Text_Files; use Text_Files; + +-- Generate instrumented sources for the source files of all units of +-- interest. Also save mappings between coverage buffers and SCOs for each +-- library units to SID files (one per library unit). +-- +-- Depending on Dump_Config, instrument mains to schedule a call to the +-- dump procedure for the list of coverage buffers in all mains in the +-- project. +-- +-- Language_Version restricts what source constructs the instrumenter is +-- allowed to use. For instance, if Ada_2005 (or a lower version) is +-- passed, it will not be allowed to introduce expression functions, and +-- thus will emit a warning when it needed to do so. +-- +-- If Ignored_Source_File is non-null, ignore files whose names match the +-- accessed pattern. +-- +-- Mains is the list of source files that were listed on the command line: +-- if non-empty, they replace the mains specified in project files. + +procedure Instrument.Projects + (Dump_Config : Any_Dump_Config; + Ignored_Source_Files : access GNAT.Regexp.Regexp; + Mains : String_Vectors.Vector) +is + type Project_Info is record + Project : Project_Type; + -- Project that this record describes + + Externally_Built : Boolean; + -- Whether this project is externally built. In that case, we assume its + -- units of interest have already been instrumented. + + Output_Dir : Ada.Strings.Unbounded.Unbounded_String; + -- Subdirectory in the project file's object directory. All we generate + -- for this project must land in it. + + Desc : Prj_Desc; + + end record; + + type Project_Info_Access is access all Project_Info; + + package Project_Info_Maps is new Ada.Containers.Hashed_Maps + (Key_Type => Ada.Strings.Unbounded.Unbounded_String, + Element_Type => Project_Info_Access, + Equivalent_Keys => Ada.Strings.Unbounded."=", + Hash => Ada.Strings.Unbounded.Hash); + -- Mapping from project name (as returned by GNATCOLL.Projects.Name) to + -- Project_Info records. Project_Info records are owned by this map, and + -- thus must be deallocated when maps are deallocated. + + type Main_To_Instrument is record + CU_Name : Compilation_Unit_Part; + -- Compilation unit of the main to instrument + + File : GNATCOLL.VFS.Virtual_File; + -- Source file to instrument + + Prj_Info : Project_Info_Access; + -- Reference to the Project_Info record corresponding to the project + -- that owns the main to instrument. + end record; + + package Main_To_Instrument_Vectors is new Ada.Containers.Vectors + (Positive, Main_To_Instrument); + + use type GNATCOLL.VFS.Filesystem_String; + function Less (L, R : File_Info) return Boolean is + (L.File.Full_Name < R.File.Full_Name); + function Equal (L, R : File_Info) return Boolean is + (L.File.Full_Name = R.File.Full_Name); + + package File_Info_Sets is new Ada.Containers.Indefinite_Ordered_Sets + (Element_Type => File_Info, "<" => Less, "=" => Equal); + + type Library_Unit_Info is record + Unit_Name : Unbounded_String; + -- Name of this unit: unit name for unit-based languages, simple name + -- for file-based languages. + + Instr_Project : GPR.Project_Type; + -- Project in which instrumentation artifacts for this unit are + -- generated. + + Language_Kind : Any_Language_Kind; + -- Higher level representation of a language (unit-based or file-based) + + Language : Any_Language; + -- Actual language representation + + All_Externally_Built : Boolean; + -- Whether all of the parts of this unit belongs to an externally-built + -- project. If it is the case, the unit won't be instrumented; + -- otherwise, every unit part will. + + end record; + + package Unit_Maps is new + Ada.Containers.Indefinite_Ordered_Maps (String, Library_Unit_Info); + -- Map to unit names to unit info of files implementing this unit. For + -- file- based languages, the unit name is the full name (to simplify + -- dealing with homonym in different projects). + + type Inst_Context is limited record + Mapping_File, Config_Pragmas_File : Unbounded_String; + + Predefined_Source_Dirs : String_Vectors.Vector; + + Sources_Of_Interest_Response_File : Unbounded_String; + -- File containing the list of units of interest, identified by their + -- fullname. This is passed on to gnatcov instrument-source invokations + -- (for Ada), to know which part of a unit (spec / body / separate) must + -- be instrumented. + + Ignored_Source_Files_Present : Boolean; + Ignored_Source_Files : GNAT.Regexp.Regexp; + -- If present, instrumentation will ignore files whose names match the + -- accessed pattern. + + Project_Info_Map : Project_Info_Maps.Map; + -- For each project that contains units of interest, this tracks a + -- Project_Info record. + + Tag : Unbounded_String; + -- Tag relative to the current instrumentation run + + end record; + + function Create_Context + (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context; + -- Create an instrumentation context for the currently loaded project + + procedure Destroy_Context (Context : in out Inst_Context); + -- Free dynamically allocated resources in Context + + function Is_Ignored_Source_File + (Context : Inst_Context; Filename : String) return Boolean; + -- Return whether the instrumentation process must ignore the Filename + -- source file. + + function Get_Or_Create_Project_Info + (Context : in out Inst_Context; + Project : Project_Type) return Project_Info_Access; + -- Return the Project_Info record corresponding to Project. Create it if it + -- does not exist. + + procedure Register_Main_To_Instrument + (Context : in out Inst_Context; + Mains : in out Main_To_Instrument_Vectors.Vector; + File : GNATCOLL.VFS.Virtual_File; + Project : Project_Type); + -- Register in Mains a main to be instrumented so that it dumps coverage + -- buffers. File is the source file for this main, and Project is the + -- project that owns this main. + + procedure Prepare_Output_Dirs (IC : Inst_Context); + -- Make sure we have the expected tree of directories for the + -- instrumentation output. + + function SID_Filename + (LU_Info : Library_Unit_Info; In_Library_Dir : Boolean) return String; + -- Return the filename of the SID file to create for the given library + -- unit. If In_Library_Dir is true, then return a filename located in the + -- project library directory. Otherwise, the filename is located in the + -- object directory. + + function Load_From_Project (Prj : Project_Type) return Prj_Desc; + -- Load the project description from the given project + + function Compilation_Unit_Options + (IC : Inst_Context; + Prj : Prj_Desc; + LU_Info : Library_Unit_Info) return String_Vectors.Vector; + -- Return the list of options to pass to a gnatcov instrument-source / + -- instrument-main (depending on Purpose) for the given compilation unit + -- LU_Info, belonging to the project Prj. + + procedure Add_Instrumented_Unit + (Project : GPR.Project_Type; Source_File : GPR.File_Info); + -- Add this source file to the list of units to instrument + + ----------------------- + -- Load_From_Project -- + ----------------------- + + function Load_From_Project (Prj : Project_Type) return Prj_Desc + is + Dot_Replacement : constant String := + Prj.Attribute_Value + (Attribute => Build ("Naming", "Dot_Replacement")); + Result : Prj_Desc; + begin + for Lang in Some_Language loop + if Builtin_Support (Lang) then + declare + Body_Suffix : constant String := + Project.Source_Suffix (Lang, GPR.Unit_Body, Prj); + Spec_Suffix : constant String := + Project.Source_Suffix (Lang, GPR.Unit_Spec, Prj); + begin + Result.Body_Suffix (Lang) := +Body_Suffix; + Result.Spec_Suffix (Lang) := +Spec_Suffix; + end; + end if; + end loop; + + Result.Prj_Name := +Prj.Name; + Result.Dot_Replacement := +Dot_Replacement; + + -- Load the set of compiler switches for languages requiring it + + for Lang in C_Family_Language loop + declare + use type GNAT.Strings.String_List_Access; + Options : Analysis_Options; + Compiler_Opts : String_Vectors.Vector; + Switches : GNAT.Strings.String_List_Access; + Compiler_Driver : constant String := + GNATCOLL.Projects.Attribute_Value + (Prj, + GPR.Compiler_Driver_Attribute, + Image (Lang)); + + procedure Register_Source_Dirs + (P : GNATCOLL.Projects.Project_Type); + -- Add the source directories of P's project file to the search + -- paths to be passed as -I arguments later. The order in which + -- the paths are added to the search paths vector is the same + -- order in which GNATCOLL retrieves the files in the project + -- tree. gprbuild also depends on GNATCOLL which ensures we + -- have the same behavior here. + + -------------------------- + -- Register_Source_Dirs -- + -------------------------- + + procedure Register_Source_Dirs + (P : GNATCOLL.Projects.Project_Type) is + begin + for Dir of P.Source_Dirs loop + Result.Search_Paths.Append + ("-I" & (+GNATCOLL.VFS."+" (GNATCOLL.VFS.Dir_Name (Dir)))); + end loop; + end Register_Source_Dirs; + begin + -- Pass the source directories of the project file as -I options. + -- Note that this will duplicate with the project tree traversal + -- below, but we need this project source directories to be + -- picked first. We thus make sure to add them first to the + -- PP_Search_Path list. + + Register_Source_Dirs (Prj); + + -- Pass the source directories of included projects as -I options + + Project.Iterate_Projects + (Prj, Register_Source_Dirs'Access, + Recursive => True, Include_Extended => True); + + -- Get the compiler switches from the project file. When + -- registering a compilation unit for instrumentation, we also + -- fill the compilation unit specific switches that will override + -- the project defaults, if there are any (see + -- Add_Instrumented_Unit). + + Switches := + Prj.Attribute_Value + (Attribute => GPR.Compiler_Default_Switches_Attribute, + Index => Image (Lang)); + + -- If we manage to find appropriate switches, convert them to a + -- string vector import the switches. + + if Switches /= null then + declare + Args : String_Vectors.Vector; + begin + for S of Switches.all loop + Args.Append (To_Unbounded_String (S.all)); + end loop; + GNAT.Strings.Free (Switches); + Import_From_Args (Options, Args); + end; + end if; + + Add_Options (Compiler_Opts, Options, Pass_Builtins => False); + + Result.Compiler_Options (Lang) := Compiler_Opts; + Result.Compiler_Driver (Lang) := +Compiler_Driver; + end; + end loop; + + return Result; + end Load_From_Project; + + -------------------- + -- Create_Context -- + -------------------- + + function Create_Context + (Ignored_Source_Files : access GNAT.Regexp.Regexp) return Inst_Context is + begin + return IC : Inst_Context do + IC.Ignored_Source_Files_Present := Ignored_Source_Files /= null; + if Ignored_Source_Files /= null then + IC.Ignored_Source_Files := Ignored_Source_Files.all; + end if; + end return; + end Create_Context; + + --------------------- + -- Destroy_Context -- + --------------------- + + procedure Destroy_Context (Context : in out Inst_Context) is + procedure Free is new Ada.Unchecked_Deallocation + (Project_Info, Project_Info_Access); + begin + -- Deallocate all Project_Info in Context, and then clear the hashed + -- map, both to avoid dangling pointers and to make Destroy_Context + -- callable more than once, like conventional deallocation procedures + -- in Ada. + + for Cur in Context.Project_Info_Map.Iterate loop + declare + PI : Project_Info_Access := Project_Info_Maps.Element (Cur); + begin + Free (PI); + end; + end loop; + Context.Project_Info_Map := Project_Info_Maps.Empty_Map; + end Destroy_Context; + + ---------------------------- + -- Is_Ignored_Source_File -- + ---------------------------- + + function Is_Ignored_Source_File + (Context : Inst_Context; Filename : String) return Boolean + is + begin + return + Context.Ignored_Source_Files_Present + and then GNAT.Regexp.Match + (S => Fold_Filename_Casing (Filename), + R => Context.Ignored_Source_Files); + end Is_Ignored_Source_File; + + -------------------------------- + -- Get_Or_Create_Project_Info -- + -------------------------------- + + function Get_Or_Create_Project_Info + (Context : in out Inst_Context; + Project : Project_Type) return Project_Info_Access + is + use Project_Info_Maps; + + -- Look for an existing Project_Info record corresponding to Project + + Project_Name : constant Unbounded_String := +Project.Name; + Position : constant Cursor := Context.Project_Info_Map.Find + (Project_Name); + begin + if Has_Element (Position) then + return Element (Position); + + else + -- The requested Project_Info record does not exist yet. Create it, + -- register it and return it. + + declare + Storage_Project : constant Project_Type := + Project.Extending_Project (Recurse => True); + -- Actual project that will host instrumented sources: even when + -- we instrument an extended project, the resulting instrumented + -- sources must go to the ultimate extending project's object + -- directory. This is similar to the object directory that hosts + -- object files when GPRbuild processes a project that is + -- extended. + + Result : constant Project_Info_Access := new Project_Info' + (Project => Project, + Externally_Built => Project.Externally_Built, + Output_Dir => +Project_Output_Dir (Storage_Project), + Desc => Load_From_Project (Project)); + begin + Result.Desc.Output_Dir := Result.Output_Dir; + Context.Project_Info_Map.Insert (Project_Name, Result); + return Result; + end; + end if; + end Get_Or_Create_Project_Info; + + ------------------------- + -- Prepare_Output_Dirs -- + ------------------------- + + procedure Prepare_Output_Dirs (IC : Inst_Context) is + use Project_Info_Maps; + begin + for Cur in IC.Project_Info_Map.Iterate loop + declare + Prj_Info : Project_Info renames Element (Cur).all; + Output_Dir : constant String := +(Element (Cur).Output_Dir); + begin + -- Do not create output directories for externally built projects: + -- we don't instrument them and we may not have filesystem + -- permissions to create directories there. + + if not Prj_Info.Externally_Built + and then not Ada.Directories.Exists (Output_Dir) + then + Ada.Directories.Create_Path (Output_Dir); + end if; + end; + end loop; + end Prepare_Output_Dirs; + + --------------------------------- + -- Register_Main_To_Instrument -- + --------------------------------- + + procedure Register_Main_To_Instrument + (Context : in out Inst_Context; + Mains : in out Main_To_Instrument_Vectors.Vector; + File : GNATCOLL.VFS.Virtual_File; + Project : Project_Type) + is + File_Info : constant GNATCOLL.Projects.File_Info := + Standard.Project.Project.Info (File); + CU_Name : constant Compilation_Unit_Part := + To_Compilation_Unit_Name (File_Info); + Prj_Info : constant Project_Info_Access := + Get_Or_Create_Project_Info (Context, Project); + begin + Mains.Append + (Main_To_Instrument' + (CU_Name => CU_Name, + File => File, + Prj_Info => Prj_Info)); + end Register_Main_To_Instrument; + + ------------------ + -- SID_Filename -- + ------------------ + + function SID_Filename + (LU_Info : Library_Unit_Info; + In_Library_Dir : Boolean) return String + is + use GNATCOLL.VFS; + + -- Determine in which project we will put this SID file, and the + -- basename for the SID file to create. Mimic how GNAT creates ALI + -- files: use the project of the main source of the library unit, start + -- from the basename of that source file, replace the last extension + -- with ".sid". Also make sure to use the most extending project in the + -- hierarchy, which is where GPRbuild puts ALI/object files. + + SID_Basename : US.Unbounded_String; + + Project : constant GPR.Project_Type := + GPR.Extending_Project + (Project => LU_Info.Instr_Project, + Recurse => True); + pragma Assert (Project /= GPR.No_Project); + + Output_Directory : constant Virtual_File := + (if In_Library_Dir + then Project.Library_Ali_Directory + else Project.Object_Dir); + begin + case Language_Kind (LU_Info.Language) is + when Unit_Based_Language => + declare + Src_Body_Basename : constant String := +Project.File_From_Unit + (Unit_Name => +LU_Info.Unit_Name, + Part => Unit_Body, + Language => Image (LU_Info.Language), + File_Must_Exist => True); + Src_Spec_Basename : constant String := +Project.File_From_Unit + (Unit_Name => +LU_Info.Unit_Name, + Part => Unit_Spec, + Language => Image (LU_Info.Language), + File_Must_Exist => True); + Src_Basename : constant String := + (if Src_Body_Basename = "" + then Src_Spec_Basename + else Src_Body_Basename); + Src_Ext_Index : constant Positive := + Ada.Strings.Fixed.Index + (Src_Basename, ".", Ada.Strings.Backward); + begin + SID_Basename := + +(Src_Basename (Src_Basename'First .. Src_Ext_Index) + & "sid"); + end; + when File_Based_Language => + SID_Basename := + +Ada.Directories.Simple_Name (+LU_Info.Unit_Name) & ".sid"; + end case; + + return String'(+Output_Directory.Full_Name) / (+SID_Basename); + end SID_Filename; + + ------------------------------ + -- Compilation_Unit_Options -- + ------------------------------ + + function Compilation_Unit_Options + (IC : Inst_Context; + Prj : Prj_Desc; + LU_Info : Library_Unit_Info) return String_Vectors.Vector + is + Result : String_Vectors.Vector; + + procedure Compilation_Unit_Options_Ada; + + ---------------------------------- + -- Compilation_Unit_Options_Ada -- + ---------------------------------- + + procedure Compilation_Unit_Options_Ada is + begin + Result.Append ("--gnatem=" & IC.Mapping_File); + Result.Append ("--gnatec=" & IC.Config_Pragmas_File); + + -- Load the predefined source directories + + for Dir of IC.Predefined_Source_Dirs loop + Result.Append ("--runtime-dir=" & Dir); + end loop; + end Compilation_Unit_Options_Ada; + + begin + -- Depending on the language, pass the right set of options + + case LU_Info.Language is + when Ada_Language => + Compilation_Unit_Options_Ada; + when others => + null; + end case; + + -- Pass the list of sources of interest, to e.g. skip the + -- instrumentation of the spec / body / subunit for an Ada unit if + -- it was requested through a --ignored-source-files switch. + + Result.Append ("--files=@" & IC.Sources_Of_Interest_Response_File); + + -- Pass the right language + + Result.Append (+"--lang=" & Image (LU_Info.Language)); + + -- Pass the project description options + + Result.Append + (String_Vectors.Vector' + (Unparse (Prj, LU_Info.Unit_Name, LU_Info.Language))); + + return Result; + end Compilation_Unit_Options; + + -- Create the instrumenter context + + IC : Inst_Context := Create_Context (Ignored_Source_Files); + + Root_Project_Info : constant Project_Info_Access := + Get_Or_Create_Project_Info (IC, Project.Project.Root_Project); + + -- Create a map from library units to lists of compilation units to + -- instrument for them. + + Instrumented_Sources : Unit_Maps.Map; + -- List of units that should be instrumented + + Files_Of_Interest_Str_Set : String_Sets.Set; + Files_Of_Interest : File_Info_Sets.Set; + -- List of files of interest. + -- + -- This is passed on to instrument-source invocations when instrumenting + -- an Ada file (to know which part of a compilation unit must be + -- instrumented, i.e. spec / body / separates). + + --------------------------- + -- Add_Instrumented_Unit -- + --------------------------- + + procedure Add_Instrumented_Unit + (Project : GPR.Project_Type; Source_File : GPR.File_Info) + is + Language : constant Src_Supported_Language := + To_Language (Source_File.Language); + Lang_Kind : constant Any_Language_Kind := Language_Kind (Language); + + use Unit_Maps; + Unit_Name : constant String := + (case Lang_Kind is + when Unit_Based_Language => Owning_Unit_Name (Source_File), + when File_Based_Language => + GNATCOLL.VFS."+" (Source_File.File.Full_Name)); + + Prj_Info : constant Project_Info_Access := + Get_Or_Create_Project_Info (IC, Source_File.Project); + + LU_Info : constant Library_Unit_Info := + (Unit_Name => +Unit_Name, + Instr_Project => Project, + Language_Kind => Lang_Kind, + Language => Language, + All_Externally_Built => Prj_Info.Externally_Built); + + begin + -- Check if this is an ignored source file + + if Is_Ignored_Source_File (IC, +Source_File.File.Base_Name) then + return; + end if; + + -- Check if gnatcov was built with support for this language. If not, + -- exit early. + + if not Builtin_Support (Language) then + return; + end if; + + -- Otherwise, this is a source of interest + + Files_Of_Interest.Insert (Source_File); + Files_Of_Interest_Str_Set.Insert (+(+Source_File.File.Full_Name)); + + -- Headers are not instrumented by themselves, so exit early as soon + -- as they have been added to the sources of interest. + + if Language in C_Family_Language + and then Source_File.Unit_Part = Unit_Spec + then + return; + end if; + + if not Instrumented_Sources.Contains (Unit_Name) then + Instrumented_Sources.Insert (Unit_Name, LU_Info); + end if; + declare + Cur_Ref : constant Unit_Maps.Reference_Type := + Instrumented_Sources.Reference (Unit_Name); + begin + if not Prj_Info.Externally_Built then + Cur_Ref.Instr_Project := Project; + Cur_Ref.All_Externally_Built := False; + end if; + end; + + -- If the unit belongs to an externally built project, exit after it + -- was added it to the instrumented sources. We won't instrument it + -- in the current instrumentation run, so there is no need to grab + -- information useful for instrumentation purposes. + + if Source_File.Project.Externally_Built + then + return; + end if; + + -- Also get compiler switches that are file-specific and register them + -- in the project description. + + if Language in C_Family_Language then + declare + use type GNAT.Strings.String_List_Access; + Options : Analysis_Options; + Compiler_Opts : String_Vectors.Vector; + Switches : GNAT.Strings.String_List_Access; + Basename : constant String := +Source_File.File.Base_Name; + begin + Switches := + Project.Attribute_Value + (Attribute => GPR.Build ("compiler", "switches"), + Index => Basename); + if Switches /= null then + declare + Args : String_Vectors.Vector; + begin + for S of Switches.all loop + Args.Append (To_Unbounded_String (S.all)); + end loop; + GNAT.Strings.Free (Switches); + Import_From_Args (Options, Args); + end; + Add_Options (Compiler_Opts, Options, Pass_Builtins => False); + Prj_Info.Desc.Compiler_Options_Unit.Insert + (LU_Info.Unit_Name, Compiler_Opts); + end if; + end; + end if; + end Add_Instrumented_Unit; + + Mains_To_Instrument : array (Src_Supported_Language) + of Main_To_Instrument_Vectors.Vector; + -- For each supported language, list of mains to instrument. Note that + -- this is filled even when dump-trigger is manual: in that case the + -- instrumentation of the main will do nothing. + + Exec_Filename : constant String := Ada.Directories.Compose + (Support_Files.Libexec_Dir, + "gnatcov64" & GNAT.OS_Lib.Get_Executable_Suffix.all); + -- Launch gnatcov64 for gnatcov subprocesses (when instrumenting sources + -- and mains), to bypass the wrapper and save some execution time. + + Ada_Instrumenter : aliased Instrument.Ada_Unit.Ada_Instrumenter_Type; + C_Instrumenter : aliased Instrument.C.C_Instrumenter_Type; + CPP_Instrumenter : aliased Instrument.C.CPP_Instrumenter_Type; + Instrumenters : constant array (Src_Supported_Language) + of access Language_Instrumenter'Class := + (Ada_Language => Ada_Instrumenter'Access, + C_Language => C_Instrumenter'Access, + CPP_Language => CPP_Instrumenter'Access); + + -- Start of processing for Instrument_Units_Of_Interest + +begin + -- Set the instrumentation tag + + declare + Time : constant Unsigned_64 := + Unsigned_64 + (GNAT.OS_Lib.To_C (GNAT.OS_Lib.Current_Time)); + Tag : constant String := + Hex_Images.Strip_Zero_Padding + (Hex_Images.Hex_Image (Time)); + -- Tag for the current instrumentation run. Passed on to instrument-main + -- invocations, to have the same tag for mains instrumented at the + -- same time. + + begin + IC.Tag := +Tag; + end; + + -- Delete output directories from previous instrumentations + + Clean_Objdirs; + + -- First get the list of all units of interest + + for Lang in Src_Supported_Language loop + if Src_Enabled_Languages (Lang) + and then Root_Project_Info.Project.Has_Language (Image (Lang)) + then + Project.Enumerate_Sources + (Add_Instrumented_Unit'Access, Lang, Include_Stubs => True); + end if; + end loop; + + -- Remove all of the separate whose parent unit was not instrumented, as + -- this is not supported. TODO???: we should probably issue a warning + -- there. + + for Source of Files_Of_Interest.Copy loop + if Source.Unit_Part = Unit_Separate then + declare + Parent_Unit : constant GNATCOLL.Projects.File_Info := + Project.Project.Info + (Project.Project.Other_File (Source.File)); + begin + if not Files_Of_Interest.Contains (Parent_Unit) then + Files_Of_Interest.Delete (Source); + end if; + end; + end if; + end loop; + + -- If we need to instrument all the mains, also go through them now, so + -- that we can prepare output directories for their projects later on. + -- Note that for user convenience, we want to do this for all the + -- languages that gnatcov supports, even those that are not considered + -- for coverage analysis. + -- + -- If no source file was specified on the command line to be a main, + -- use the list of mains specified in project files. + + if Mains.Is_Empty then + for Lang in Src_Supported_Language loop + for Main of Project.Enumerate_Mains (Lang) loop + Register_Main_To_Instrument + (IC, Mains_To_Instrument (Lang), Main.File, Main.Project); + end loop; + end loop; + + -- Otherwise, make sure we can find the source file of each main in + -- the project tree and that we can instrument them (supported + -- language). + + else + for Filename of Mains loop + declare + use GNATCOLL.VFS; + + F : constant String := +Filename; + Info : constant File_Info := + Project.Project.Root_Project.Create_From_Project (+F); + File : constant Virtual_File := Info.File; + Project : constant Project_Type := Info.Project; + Lang : Any_Language; + begin + if File = No_File or else Project = No_Project then + Outputs.Fatal_Error ("No such source file: " & F); + end if; + + Lang := To_Language_Or_All (Info.Language); + if Lang not in Src_Supported_Language + or else not Builtin_Support (Lang) + then + Outputs.Fatal_Error + ("Cannot instrument main source file (unsupported" + & " language): " & F); + end if; + + Register_Main_To_Instrument + (IC, Mains_To_Instrument (Lang), File, Project); + end; + end loop; + end if; + + -- Check early if there are no sources of interest + + if Files_Of_Interest.Length = 0 then + Outputs.Fatal_Error ("No unit to instrument."); + end if; + + -- Now that we know all the sources we need to instrument, prepare + -- output directories. + + Prepare_Output_Dirs (IC); + + -- Record in a file all of the files and headers of interest. We separate + -- both as we do not expect to have coverage buffers for header files (the + -- coverage data is in including bodies' coverage buffers). + + IC.Mapping_File := + +Create_Ada_Mapping_File (Project.Project.Root_Project); + IC.Config_Pragmas_File := + +Create_Config_Pragmas_File (Project.Project.Root_Project); + IC.Sources_Of_Interest_Response_File := + +To_String (Root_Project_Info.all.Output_Dir) / ".sources_of_interest"; + + -- Set the runtime directories + + declare + use GNATCOLL.VFS; + begin + for Dir of + Project.Project.Root_Project.Get_Environment.Predefined_Source_Path + loop + IC.Predefined_Source_Dirs.Append (+(+Full_Name (Dir))); + end loop; + end; + + -- Initialize the instrumenters: we will use them when parallelization is + -- disabled, but also to generate the unit holding the list of buffers, + -- in one of the supported languages. + + Ada_Instrumenter := + Create_Ada_Instrumenter + (IC.Tag, + +IC.Config_Pragmas_File, + +IC.Mapping_File, + IC.Predefined_Source_Dirs); + C_Instrumenter := Create_C_Instrumenter (IC.Tag); + CPP_Instrumenter := Create_CPP_Instrumenter (IC.Tag); + + -- Write the files of interest to temporary files in the instrumentation + -- directory. + + declare + Sources_Of_Interest_File : Text_Files.File_Type; + -- File containing the list of sources of interest + + begin + Sources_Of_Interest_File.Create + (+IC.Sources_Of_Interest_Response_File); + for Source of Files_Of_Interest loop + Sources_Of_Interest_File.Put_Line (+Source.File.Full_Name); + end loop; + Sources_Of_Interest_File.Close; + end; + + -- Instrument every unit of interest asynchronously + + declare + Instrument_Source_Pool : Process_Pool (Parallelism_Level); + + Instrument_Source_Args : String_Vectors.Vector; + -- Common arguments for all of the gnatcov instrument-source + -- invocations. + + begin + Instrument_Source_Args.Append (+"instrument-source"); + Instrument_Source_Args.Append + (Common_Switches (Cmd_Instrument_Source)); + for Cur in Instrumented_Sources.Iterate loop + declare + Unit_Args : String_Vectors.Vector := + Instrument_Source_Args.Copy; + -- Args specific to a gnatcov instrument-source invocation + -- (e.g. the common arguments + the sources that must be + -- instrumented for a specific unit). + + Unit_Name : constant String := Unit_Maps.Key (Cur); + LU_Info : constant Library_Unit_Info := Unit_Maps.Element (Cur); + + Obj_SID : constant String := + SID_Filename (LU_Info, In_Library_Dir => False); + + Prj : constant Project_Type := LU_Info.Instr_Project; + Desc : constant Prj_Desc := + IC.Project_Info_Map.Element (+Prj.Name).Desc; + begin + -- Skip instrumentation of the unit if it was already + -- instrumented. + + if LU_Info.All_Externally_Built then + goto Continue; + end if; + + -- Add the arguments that are specific to the compilation unit + + Unit_Args.Append + (Compilation_Unit_Options + (IC, + Desc, + LU_Info)); + + Unit_Args.Append (+"--sid=" & Obj_SID); + + -- We instrument the body, spec and separates as a whole + + Unit_Args.Append (+Unit_Name); + + -- According to the set parallelism level, instrument in + -- the same process (thus reusing the libadalang context, which + -- is a big gain of time), or spawn another instrmentation + -- process. + + if Parallelism_Level = 1 then + Instrument.Source + (Unit_Name => Unit_Name, + SID_Name => Obj_SID, + Instrumenter => Instrumenters (LU_Info.Language).all, + Files_Of_Interest => Files_Of_Interest_Str_Set, + Prj => Desc); + else + -- Asynchronously instrument + + Instrument_Source_Pool.Run_Command + (Command => Exec_Filename, + Arguments => Unit_Args, + Origin_Command_Name => "gnatcov instrument", + Ignore_Error => False); + end if; + end; + <> + end loop; + end; + + -- Copy SID files into the library directory + + for LU_Info of Instrumented_Sources loop + declare + Obj_SID : constant String := + SID_Filename (LU_Info, In_Library_Dir => False); + Lib_SID : constant String := + SID_Filename (LU_Info, In_Library_Dir => True); + Success : Boolean; + begin + if not LU_Info.All_Externally_Built and then Obj_SID /= Lib_SID then + + -- Unlike the object directory, which GNATCOLL.Project + -- creates automatically, the library directory may not + -- exist: create it if needed. + + declare + use GNATCOLL.VFS; + begin + Create (Create (+Lib_SID).Dir_Name).Make_Dir; + exception + when Exc : VFS_Directory_Error => + Outputs.Fatal_Error + (Ada.Exceptions.Exception_Message (Exc)); + end; + + GNAT.OS_Lib.Copy_File + (Name => Obj_SID, + Pathname => Lib_SID, + Success => Success, + Mode => GNAT.OS_Lib.Overwrite); + if not Success then + Outputs.Fatal_Error + ("Error while copying " & Obj_SID + & " to the library directory: " & Lib_SID); + end if; + end if; + end; + end loop; + + -- Then, instrument asynchronously every main + + declare + Instrument_Main_Pool : Process_Pool (Parallelism_Level); + Instrument_Main_Args : String_Vectors.Vector; + + Main_Filename : Unbounded_String; + -- Fullname for the main. It can either be an instrumented version of + -- the main (if it also was instrumented as a source), or the original + -- version. + + Explicit_Dump_Config : Any_Dump_Config := Dump_Config; + -- Dump config with explicited defaults. The only interesting thing + -- is the dump-filename-prefix that is computed after the name of + -- the main in the project file, if not specified explicitly on the + -- command line. + + begin + Instrument_Main_Args.Append (+"instrument-main"); + + -- Add the root project name, as the symbol holding the list of + -- coverage buffers is defined accordingly. + + Instrument_Main_Args.Append + (+"--project-name=" & Root_Project_Info.Project.Name); + + Instrument_Main_Args.Append (Common_Switches (Cmd_Instrument_Main)); + + for Language in Src_Supported_Language loop + for Main of Mains_To_Instrument (Language) loop + declare + Unit_Name : constant Unbounded_String := + +(case Main.CU_Name.Language_Kind is + when Unit_Based_Language => + To_Ada (Main.CU_Name.Unit), + when File_Based_Language => (+Main.File.Full_Name)); + Unit_Args : String_Vectors.Vector := + Instrument_Main_Args.Copy; + begin + Unit_Args.Append + (Compilation_Unit_Options + (IC, + Main.Prj_Info.Desc, + Library_Unit_Info' + (Unit_Name => Unit_Name, + Instr_Project => Main.Prj_Info.Project, + Language_Kind => Language_Kind (Language), + Language => Language, + All_Externally_Built => False))); + + -- Pass main-specific dump-config options + + if Dump_Config.Channel = Binary_File then + + -- If no dump filename prefix was specified, compute it + -- here: we use the executable name, that is retrieved from + -- the project. + + if Length (Dump_Config.Filename_Prefix) = 0 then + Explicit_Dump_Config.Filename_Prefix := + +(+Root_Project_Info.Project.Executable_Name + (Main.File.Full_Name)); + end if; + end if; + + Unit_Args.Append (Unparse_Config (Explicit_Dump_Config)); + + -- Then append the main filename. If the main was instrumented + -- as a unit of interest before, then pass the instrumented + -- version. + + if Instrumented_Sources.Contains (+Unit_Name) then + Main_Filename := + +(+Root_Project_Info.Output_Dir) / (+Main.File.Base_Name); + else + Main_Filename := +(+Main.File.Full_Name); + end if; + + Unit_Args.Append (Main_Filename); + + if Parallelism_Level = 1 then + declare + Instr_Units : String_Sets.Set; + begin + for Source of Files_Of_Interest loop + Instr_Units.Insert (+(+Source.File.Full_Name)); + end loop; + Instrument.Main + (Instrumenter => Instrumenters (Language).all, + Dump_Config => Explicit_Dump_Config, + Main_Filename => +Main_Filename, + Prj => Main.Prj_Info.Desc); + end; + else + Instrument_Main_Pool.Run_Command + (Command => Exec_Filename, + Arguments => Unit_Args, + Origin_Command_Name => "gnatcov instrument", + Ignore_Error => False); + end if; + end; + end loop; + end loop; + end; + + if not Args.Bool_Args (Opt_Save_Temps) then + Ada.Directories.Delete_File (+IC.Sources_Of_Interest_Response_File); + end if; + + -- Emit the unit to contain the list of coverage buffers, exported to a + -- C symbol, in one of the language supported by the project. + -- + -- Note that this has an implicit hack to it: if Ada is a language of + -- the project, it will pick it over the others (as it is the first + -- enumeration member of the Src_Supported_Language type). This matters + -- as we make the assumption in the Emit_Dump_Helper_Unit implementation + -- in instrument-ada_unit.adb (when instrumenting for an Ada main) that + -- the Ada package for buffers list units always exists: we need to + -- include it in the main closure, as it puts buffer units in scope + -- by importing them (otherwise they aren't as they are used through + -- C symbol importations). + + declare + use Files_Table; + Instr_Units : Unit_Sets.Set; + begin + for LU_Info of Instrumented_Sources loop + Instr_Units.Insert + (Compilation_Unit'(LU_Info.Language_Kind, LU_Info.Unit_Name)); + end loop; + for Lang in Src_Supported_Language loop + if Builtin_Support (Lang) + and then Root_Project_Info.Project.Has_Language (Image (Lang)) + then + Instrumenters (Lang).Emit_Buffers_List_Unit + (Instr_Units, Root_Project_Info.Desc); + exit; + end if; + end loop; + end; + + Destroy_Context (IC); + + -- Save the dump trigger+channel information in the root project's + -- object directory. This allows user scripts to automatically know + -- where to expect source trace files (dump channel) without inspecting + -- all inputs (command-line arguments, project file, instrumentation + -- runtime, etc.) and whether that info is reliable (it is not if the + -- dump trigger is manual). + -- + -- TODO: this should go at some point in Instrument_Main (in which case + -- one would be generated per main). + + declare + J : constant GNATCOLL.JSON.JSON_Value := Create_Object; + Filename : constant String := + Project.Output_Dir & "/gnatcov-instr.json"; + begin + J.Set_Field ("dump-trigger", Image (Dump_Config.Trigger)); + J.Set_Field ("dump-channel", Image (Dump_Config.Channel)); + Write (Filename, J, Compact => False); + end; + +end Instrument.Projects; diff --git a/tools/gnatcov/instrument-source.adb b/tools/gnatcov/instrument-source.adb new file mode 100644 index 000000000..1749140fe --- /dev/null +++ b/tools/gnatcov/instrument-source.adb @@ -0,0 +1,66 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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 Checkpoints; use Checkpoints; +with Coverage; +with Instrument.Common; use Instrument.Common; +with Strings; use Strings; +with Traces_Files; use Traces_Files; + +-- Implementation of the gnatcov instrument-source command, which instrument +-- the given command-line unit. If the unit is of a unit based language, the +-- unit name is the name of the unit, otherwise, it is the (full) filename. + +procedure Instrument.Source + (Unit_Name : String; + SID_Name : String; + Instrumenter : in out Language_Instrumenter'Class; + Files_Of_Interest : String_Sets.Set; + Prj : Prj_Desc) +is + Context : aliased Coverage.Context := Coverage.Get_Context; +begin + -- Even though instrumentation does not create any traces, the structure + -- of a SID file is basically a checkpoint, so it has a Trace_Kind field + -- in its header. Instead of leaving it to Unknown (default value) mark it + -- as Source_Trace_File so that when the .sid file is loaded, it will set + -- gnatcov in "source trace mode" and it will be rejected if binary traces + -- have already been loaded. + + Update_Current_Trace_Kind (Source_Trace_File); + + -- Instrument all of the source files implementing the compilation unit. + -- For Ada, this means instrumenting the body / spec / separates, and for + -- C/C++, this means instrumenting the .c file and the included headers. + + Instrumenter.Instrument_Unit (Unit_Name, Prj, Files_Of_Interest); + + -- Save the SCOs for the unit in the SID file + + Checkpoints.Checkpoint_Save + (SID_Name, + Context'Access, + Purpose => Checkpoints.Instrumentation); + + if Switches.Verbose then + SC_Obligations.Dump_All_SCOs; + end if; + + Checkpoints.Checkpoint_Clear; + +end Instrument.Source; diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 0ef2f2eec..27fb6e360 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -19,35 +19,18 @@ -- Source instrumentation with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Containers; use Ada.Containers; -with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Directories; -with Ada.Exceptions; -with Ada.Strings.Fixed; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; -with Ada.Text_IO; use Ada.Text_IO; +with Ada.Strings; +with Ada.Strings.Hash; with Ada.Strings.Unbounded.Equal_Case_Insensitive; with Ada.Strings.Unbounded.Less_Case_Insensitive; -with Ada.Unchecked_Deallocation; with Interfaces; use Interfaces; -with GNAT.OS_Lib; - -with GNATCOLL.JSON; use GNATCOLL.JSON; -with GNATCOLL.VFS; use GNATCOLL.VFS; - -with Checkpoints; -with Coverage; -with Files_Table; -with Hex_Images; use Hex_Images; -with Instrument.Ada_Unit; -with Instrument.Clean_Objdirs; -with Instrument.C; -with Instrument.Common; use Instrument.Common; -with JSON; use JSON; -with Outputs; -with Paths; use Paths; -with Project; + +with GNATCOLL.VFS; use GNATCOLL.VFS; + +with Command_Line; use Command_Line; +with Hex_Images; use Hex_Images; package body Instrument is @@ -85,7 +68,7 @@ package body Instrument is -- "<" -- --------- - function "<" (Left, Right : Compilation_Unit_Name) return Boolean is + function "<" (Left, Right : Compilation_Unit_Part) return Boolean is begin if Left.Language_Kind = Right.Language_Kind then case Left.Language_Kind is @@ -116,14 +99,7 @@ package body Instrument is return Left.Part < Right.Part; end if; when File_Based_Language => - if Equal_Case_Insensitive - (Left.Project_Name, Right.Project_Name) - then - return Left.Filename < Right.Filename; - else - return Less_Case_Insensitive - (Left.Project_Name, Right.Project_Name); - end if; + return Left.Filename < Right.Filename; end case; else return Left.Language_Kind < Right.Language_Kind; @@ -134,7 +110,7 @@ package body Instrument is -- "=" -- --------- - function "=" (Left, Right : Compilation_Unit_Name) return Boolean + function "=" (Left, Right : Compilation_Unit_Part) return Boolean is use Ada_Identifier_Vectors; begin @@ -142,10 +118,10 @@ package body Instrument is case Left.Language_Kind is when Unit_Based_Language => if Left.Part = Right.Part - and then Left.Unit.Length = Right.Unit.Length + and then Length (Left.Unit) = Length (Right.Unit) then - for I in 1 .. Integer (Left.Unit.Length) loop - if not Equal_Case_Insensitive + for I in 1 .. Integer (Length (Left.Unit)) loop + if not Ada.Strings.Unbounded.Equal_Case_Insensitive (Unbounded_String (Left.Unit.Element (I)), Unbounded_String (Right.Unit.Element (I))) then @@ -159,15 +135,12 @@ package body Instrument is end if; return False; when File_Based_Language => - return Left.Filename = Right.Filename - and then Equal_Case_Insensitive - (Left.Project_Name, Right.Project_Name); + return Left.Filename = Right.Filename; end case; else return False; end if; end "="; - ------------------------- -- Qualified_Name_Slug -- ------------------------- @@ -206,7 +179,7 @@ package body Instrument is ---------------------------- function Instrumented_Unit_Slug - (Instrumented_Unit : Compilation_Unit_Name) return String + (Instrumented_Unit : Compilation_Unit_Part) return String is begin case Instrumented_Unit.Language_Kind is @@ -227,51 +200,59 @@ package body Instrument is end; when File_Based_Language => - declare - Result : Ada_Identifier; - begin - -- For a compilation unit in a file-based language, relying on - -- the filename only is not enough, as there can be multiple - -- sources with the same name belonging to different projects - -- in a project tree. To avoid name clashes, prepend the name - -- of the owning project to the computed slug. - - Append - (Result, - Qualified_Name_Slug - (To_Qualified_Name (+Instrumented_Unit.Project_Name))); - - -- Add an unambiguous separator between the project name and - -- the rest of the slug. - - Append (Result, "_z_z"); - - -- File names can contain characters that cannot appear in - -- identifiers. Furthermore, unlike for the identifier to - -- return, file names may be case sensitive. In order to - -- produce valid identifiers, encode everything that isn't a - -- lower case letter or a digit. - - for C of "+" (Instrumented_Unit.Filename) loop - if C in 'a' .. 'z' | '0' .. '9' then - Append (Result, C); - else - Append - (Result, - "_" & Hex_Image (Unsigned_8'(Character'Pos (C)))); - end if; - end loop; - - return To_String (Result); - end; + return Filename_Slug (+Instrumented_Unit.Filename); end case; end Instrumented_Unit_Slug; + ------------------- + -- Filename_Slug -- + ------------------- + + function Filename_Slug (Fullname : String) return String is + use Ada.Directories; + Result : Ada_Identifier; + begin + -- We use the basename slug, followed by a hash of the fullname, which + -- makes us confident that homonym files will be correctly handled. + + -- File names can contain characters that cannot appear in identifiers. + -- Furthermore, unlike for the identifier to return, file names may + -- be case sensitive. In order to produce valid identifiers, encode + -- everything that isn't a lower case letter or a digit. + + -- To avoid a leading underscore, add a prefix + + Append (Result, "z"); + + for C of Base_Name (Fullname) loop + if C in 'a' .. 'z' | '0' .. '9' then + Append (Result, C); + else + Append + (Result, + "_" & Hex_Image + (Interfaces.Unsigned_8'(Character'Pos (C)))); + end if; + end loop; + + -- Then, suffix with the hash + + declare + Hash_Str : constant String := + Hex_Image (Unsigned_32 (Ada.Strings.Hash (Fullname))); + begin + -- Do not forget to remove the leading whitespace... + + Append (Result, Hash_Str (2 .. Hash_Str'Last)); + end; + return To_String (Result); + end Filename_Slug; + ----------- -- Image -- ----------- - function Image (CU_Name : Compilation_Unit_Name) return String is + function Image (CU_Name : Compilation_Unit_Part) return String is begin case CU_Name.Language_Kind is when Unit_Based_Language => @@ -342,7 +323,7 @@ package body Instrument is function CU_Name_For_Unit (Unit : Ada_Qualified_Name; - Part : Unit_Parts) return Compilation_Unit_Name + Part : Unit_Parts) return Compilation_Unit_Part is begin return (Unit_Based_Language, Unit, Part); @@ -353,11 +334,10 @@ package body Instrument is ----------------------------- function CU_Name_For_File - (Filename : Unbounded_String; - Project_Name : Unbounded_String) return Compilation_Unit_Name + (Filename : US.Unbounded_String) return Compilation_Unit_Part is begin - return (File_Based_Language, Filename, Project_Name); + return (File_Based_Language, Filename); end CU_Name_For_File; ------------------------------ @@ -365,7 +345,7 @@ package body Instrument is ------------------------------ function To_Compilation_Unit_Name - (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Name + (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Part is begin case Language_Kind (To_Language (Source_File.Language)) is @@ -375,8 +355,7 @@ package body Instrument is Part => Source_File.Unit_Part); when File_Based_Language => return CU_Name_For_File - (Filename => +GNATCOLL.VFS."+" (Source_File.File.Base_Name), - Project_Name => +Source_File.Project.Name); + (Filename => +(+Source_File.File.Full_Name)); end case; end To_Compilation_Unit_Name; @@ -386,7 +365,7 @@ package body Instrument is function To_Filename (Project : Project_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Language : Any_Language) return String is begin case CU_Name.Language_Kind is @@ -406,7 +385,7 @@ package body Instrument is ---------------------------- function Find_Instrumented_Unit - (CU_Name : Compilation_Unit_Name) return CU_Id + (CU_Name : Compilation_Unit_Part) return CU_Id is use Instrumented_Unit_To_CU_Maps; @@ -419,629 +398,118 @@ package body Instrument is end if; end Find_Instrumented_Unit; - package GPR renames GNATCOLL.Projects; - - type CU_Name_With_Ignore is record - Name : Compilation_Unit_Name; - Ignored : Boolean; - end record; - - function "<" (Left, Right : CU_Name_With_Ignore) return Boolean - is (if Left.Name = Right.Name - then Left.Ignored < Right.Ignored - else Left.Name < Right.Name); - - package CU_Name_Vectors is new Ada.Containers.Vectors - (Positive, CU_Name_With_Ignore); - - type Library_Unit_Info is record - CU_Names : CU_Name_Vectors.Vector; - -- List of compilation units implementing this library unit - - Body_Project, Spec_Project : GPR.Project_Type; - -- Projects that own the body/spec for this library unit - - Language_Kind : Any_Language_Kind; - -- Higher level representation of a language (unit-based or file-based) - - Language : Any_Language; - -- Actual language representation - end record; - type Library_Unit_Info_Access is access Library_Unit_Info; - - type Ignored_Unit_Info is record - Filename : Unbounded_String; - -- Name of the source file for this unit - - Prj_Info : Project_Info_Access; - -- Reference to the Project_Info record corresponding to the project - -- that owns the source file for this unit. - end record; - - type Ignored_Unit_Info_Access is access all Ignored_Unit_Info; - - package Ignored_Units_Maps is new Ada.Containers.Ordered_Maps - (Compilation_Unit_Name, Ignored_Unit_Info_Access); - - procedure Free is new Ada.Unchecked_Deallocation - (Ignored_Unit_Info, Ignored_Unit_Info_Access); - - package Library_Unit_Maps is new Ada.Containers.Indefinite_Ordered_Maps - (String, Library_Unit_Info_Access); - -- Map to associate a list of compilation units to instrument to a library - -- unit (indexed by the library unit name, i.e. the unit name or the - -- full name depending on the language kind for the library unit). - -- - -- For file-based languages, the library unit only has one compilation - -- unit associated to it (that is the library unit itself, for which the - -- name is the actual base filename). - - procedure Get_Or_Create - (Map : in out Library_Unit_Maps.Map; - Library_Unit : String; - Info : out Library_Unit_Info_Access); - -- Look for the info corresponding to Library_Unit in Map. Create it if - -- it does not exist yet and put it in Info. - - function SID_Filename - (Cur : Library_Unit_Maps.Cursor; - In_Library_Dir : Boolean) return String; - -- Return the filename of the SID file to create for the given library - -- unit. If In_Library_Dir is true, then return a filename located in the - -- project library directory. Otherwise, the filename is located in the - -- object directory. - - procedure Prepare_Output_Dirs (IC : Inst_Context); - -- Make sure we have the expected tree of directories for the - -- instrumentation output. - - ------------------- - -- Get_Or_Create -- - ------------------- - - procedure Get_Or_Create - (Map : in out Library_Unit_Maps.Map; - Library_Unit : String; - Info : out Library_Unit_Info_Access) - is - use Library_Unit_Maps; - Cur : constant Cursor := Map.Find (Library_Unit); - begin - if Has_Element (Cur) then - Info := Element (Cur); - else - Info := new Library_Unit_Info; - Info.Body_Project := GPR.No_Project; - Info.Spec_Project := GPR.No_Project; - Map.Insert (Library_Unit, Info); - end if; - end Get_Or_Create; - - ------------------ - -- SID_Filename -- - ------------------ - - function SID_Filename - (Cur : Library_Unit_Maps.Cursor; - In_Library_Dir : Boolean) return String - is - use Library_Unit_Maps; - - LU_Name : constant String := Key (Cur); - Info : Library_Unit_Info renames Element (Cur).all; - - -- Determine in which project we will put this SID file, and the - -- basename for the SID file to create. Mimic how GNAT creates ALI - -- files: use the project of the main source of the library unit, start - -- from the basename of that source file, replace the last extension - -- with ".sid". Also make sure to use the most extending project in the - -- hierarchy, which is where GPRbuild puts ALI/object files. - - SID_Basename : US.Unbounded_String; - - Use_Spec : constant Boolean := - Info.Body_Project = GPR.No_Project; - Project : constant GPR.Project_Type := - GPR.Extending_Project - (Project => (if Use_Spec - then Info.Spec_Project - else Info.Body_Project), - Recurse => True); - pragma Assert (Project /= GPR.No_Project); - - Output_Directory : constant Virtual_File := - (if In_Library_Dir - then Project.Library_Ali_Directory - else Project.Object_Dir); - begin - case Info.Language_Kind is - when Unit_Based_Language => - declare - Src_Basename : constant String := +Project.File_From_Unit - (Unit_Name => LU_Name, - Part => (if Use_Spec - then Unit_Spec - else Unit_Body), - Language => Image (Info.Language), - File_Must_Exist => False); - Src_Ext_Index : constant Positive := - Ada.Strings.Fixed.Index - (Src_Basename, ".", Ada.Strings.Backward); - begin - SID_Basename := - +(Src_Basename (Src_Basename'First .. Src_Ext_Index) - & "sid"); - end; - when File_Based_Language => - SID_Basename := +(Ada.Directories.Simple_Name (LU_Name & ".sid")); - end case; - - return String'(+Output_Directory.Full_Name) / (+SID_Basename); - end SID_Filename; - - ------------------------- - -- Prepare_Output_Dirs -- - ------------------------- - - procedure Prepare_Output_Dirs (IC : Inst_Context) is - use Project_Info_Maps; - begin - for Cur in IC.Project_Info_Map.Iterate loop - declare - Prj_Info : Project_Info renames Element (Cur).all; - Output_Dir : constant String := - +(Element (Cur).Output_Dir); - begin - -- Do not create output directories for externally built projects: - -- we don't instrument them and we may not have filesystem - -- permissions to create directories there. - - if not Prj_Info.Externally_Built - and then not Ada.Directories.Exists (Output_Dir) - then - Ada.Directories.Create_Path (Output_Dir); - end if; - end; - end loop; - end Prepare_Output_Dirs; - - ---------------------------------- - -- Instrument_Units_Of_Interest -- - ---------------------------------- - - procedure Instrument_Units_Of_Interest - (Dump_Config : Any_Dump_Config; - Language_Version : Any_Language_Version; - Ignored_Source_Files : access GNAT.Regexp.Regexp; - Mains : String_Vectors.Vector) - is - use String_Vectors; - - -- Initialize all the instrumenters - - Ada_Instrumenter : aliased Instrument.Ada_Unit.Ada_Instrumenter_Type := - Instrument.Ada_Unit.Create_Ada_Instrumenter (Language_Version); - C_Instrumenter : aliased Instrument.C.C_Instrumenter_Type := - (null record); - CPP_Instrumenter : aliased Instrument.C.CPP_Instrumenter_Type := - (null record); - - Instrumenters : constant array (Src_Supported_Language) - of access Language_Instrumenter'Class := - (Ada_Language => Ada_Instrumenter'Access, - C_Language => C_Instrumenter'Access, - CPP_Language => CPP_Instrumenter'Access); - - -- Create a map from library units to lists of compilation units to - -- instrument for them. - - LU_Map : Library_Unit_Maps.Map; - Current_LU_Info : Library_Unit_Info_Access; - Ignored_Units : Ignored_Units_Maps.Map; - - Mains_To_Instrument : array (Src_Supported_Language) - of Main_To_Instrument_Vectors.Vector; - -- For each supported language, list of mains to instrument. Always - -- empty when Dump_Config.Trigger is Manual. - - -- Create the instrumenter context - - IC : Inst_Context := Create_Context (Ignored_Source_Files); + ---------------------------- + -- Load_From_Command_Line -- + ---------------------------- - Root_Project_Info : constant Project_Info_Access := - Get_Or_Create_Project_Info (IC, Project.Project.Root_Project); + function Load_From_Command_Line return Prj_Desc is + use Command_Line.Parser; + Language : constant Some_Language := + To_Language (+Args.String_Args (Opt_Lang).Value); + Result : Prj_Desc; - procedure Add_Instrumented_Unit_Wrapper - (Project : GPR.Project_Type; Source_File : GPR.File_Info); - -- Add this source file to the list of units to instrument. For unit- - -- based languages, also add subunits that depend on this source file. + procedure Fill_If_Present + (Opt : String_Options; Field : out Unbounded_String); - ----------------------------------- - -- Add_Instrumented_Unit_Wrapper -- - ----------------------------------- + --------------------- + -- Fill_If_Present -- + --------------------- - procedure Add_Instrumented_Unit_Wrapper - (Project : GPR.Project_Type; Source_File : GPR.File_Info) + procedure Fill_If_Present + (Opt : String_Options; Field : out Unbounded_String) is - procedure Add_Instrumented_Unit - (CU_Name : Compilation_Unit_Name; Info : GPR.File_Info); - -- Wrapper for Instrument.Common.Add_Instrumented_Unit - - --------------------------- - -- Add_Instrumented_Unit -- - --------------------------- - - procedure Add_Instrumented_Unit - (CU_Name : Compilation_Unit_Name; Info : GPR.File_Info) - is - Should_Ignore : constant Boolean := - Is_Ignored_Source_File (IC, +Info.File.Base_Name); - begin - Current_LU_Info.CU_Names.Append - (CU_Name_With_Ignore'(Name => CU_Name, - Ignored => Should_Ignore)); - if Should_Ignore then - Ignored_Units.Insert - (CU_Name, - new Ignored_Unit_Info' - (Filename => To_Unbounded_String (+Info.File.Base_Name), - Prj_Info => Get_Or_Create_Project_Info - (IC, Info.Project))); - else - Add_Instrumented_Unit (IC, Info.Project, Info); - end if; - end Add_Instrumented_Unit; - - Language : constant Src_Supported_Language := - To_Language (Source_File.Language); - - -- Start of processing for Add_Instrumented_Unit_Wrapper - + Opt_Ref : constant Option_Reference := (String_Opt, Opt); begin - -- Skip this source file if the instrumenter requires it - - if Instrumenters (Language).Skip_Source_File (Source_File) then - return; + if Is_Present (Args, Opt_Ref) then + Field := +Value (Args, Opt); end if; - - declare - CU_Name : constant Compilation_Unit_Name := - To_Compilation_Unit_Name (Source_File); - - Unit_Name : constant String := - (case CU_Name.Language_Kind is - when Unit_Based_Language => To_Ada (CU_Name.Unit), - - -- For file-based languages, we need to use the full - -- name to account for homonyms. - - when File_Based_Language => +Source_File.File.Full_Name); - - begin - -- Get the vector in which we will record the compilation units - -- that the following call to Find_Units will list. - - Get_Or_Create (LU_Map, Unit_Name, Current_LU_Info); - - -- Keep track of projects that own this library unit's source - -- files for its spec/body. - - case Source_File.Unit_Part is - when GPR.Unit_Body => Current_LU_Info.Body_Project := Project; - when GPR.Unit_Spec => Current_LU_Info.Spec_Project := Project; - - -- Subunits cannot be units of interest, so Enumerate_Sources - -- should not be able to call Find_Units_Wrapper with a - -- subunit. Hence, the following should be unreachable. - - when GPR.Unit_Separate => - raise Program_Error with "unreachable code"; - end case; - - Current_LU_Info.Language_Kind := CU_Name.Language_Kind; - Current_LU_Info.Language := To_Language (Source_File.Language); - - case CU_Name.Language_Kind is - when Unit_Based_Language => - Instrument.Ada_Unit.Find_Ada_Units - (Ada_Instrumenter, - CU_Name, - Source_File, - Add_Instrumented_Unit'Access); - when File_Based_Language => - Add_Instrumented_Unit (CU_Name, Source_File); - end case; - end; - end Add_Instrumented_Unit_Wrapper; - - -- Start of processing for Instrument_Units_Of_Interest - + end Fill_If_Present; begin - -- Delete output directories from previous instrumentations - - Clean_Objdirs; + if Language in C_Family_Language then + Fill_If_Present + (Opt_Compiler_Driver, Result.Compiler_Driver (Language)); + end if; + Fill_If_Present (Opt_Output_Directory, Result.Output_Dir); + Fill_If_Present (Opt_Spec_Suffix, Result.Spec_Suffix (Language)); + Fill_If_Present (Opt_Body_Suffix, Result.Body_Suffix (Language)); + Fill_If_Present (Opt_Project_Name, Result.Prj_Name); + Fill_If_Present (Opt_Dot_Replacement, Result.Dot_Replacement); - -- First get the list of all units of interest + -- Compiler options are loaded through the --c/c++-opts switch - for Lang in Src_Supported_Language loop - if Src_Enabled_Languages (Lang) then - Project.Enumerate_Sources - (Add_Instrumented_Unit_Wrapper'Access, Lang); - end if; - end loop; + return Result; + end Load_From_Command_Line; - -- If we need to instrument all the mains, also go through them now, so - -- that we can prepare output directories for their projects later on. - -- Note that for user convenience, we want to do this for all the - -- languages that gnatcov supports, even those that are not considered - -- for coverage analysis. + ------------- + -- Unparse -- + ------------- - if Dump_Config.Trigger /= Manual then + function Unparse + (Desc : Prj_Desc; + Unit_Name : Unbounded_String; + Lang : Src_Supported_Language) return String_Vectors.Vector + is + Result : String_Vectors.Vector; + Compiler_Opts : String_Vectors.Vector; + begin + -- Pass the right body / spec suffixes - -- If no source file was specified on the command line to be a main, - -- use the list of mains specified in project files. + if Desc.Body_Suffix (Lang) /= Null_Unbounded_String then + Result.Append (+"--body-suffix"); + Result.Append (Desc.Body_Suffix (Lang)); + end if; - if Mains.Is_Empty then - for Lang in Src_Supported_Language loop - for Main of Project.Enumerate_Mains (Lang) loop - Register_Main_To_Instrument - (IC, Mains_To_Instrument (Lang), Main.File, Main.Project); - end loop; - end loop; + if Desc.Spec_Suffix (Lang) /= Null_Unbounded_String then + Result.Append (+"--spec-suffix"); + Result.Append (Desc.Spec_Suffix (Lang)); + end if; - -- Otherwise, make sure we can find the source file of each main in - -- the project tree and that we can instrument them (supported - -- language). + if Desc.Dot_Replacement /= Null_Unbounded_String then + Result.Append (+"--dot-replacement"); + Result.Append (Desc.Dot_Replacement); + end if; + if Lang in C_Family_Language then + Compiler_Opts.Append (Desc.Search_Paths); + if Desc.Compiler_Options_Unit.Contains (Unit_Name) then + Compiler_Opts.Append + (Desc.Compiler_Options_Unit.Element (Unit_Name)); else - for Filename of Mains loop - declare - F : constant String := +Filename; - Info : constant File_Info := - Project.Project.Root_Project.Create_From_Project (+F); - File : constant Virtual_File := Info.File; - Project : constant Project_Type := Info.Project; - Lang : Any_Language; - begin - if File = No_File or else Project = No_Project then - Outputs.Fatal_Error ("No such source file: " & F); - end if; - - Lang := To_Language_Or_All (Info.Language); - if Lang not in Src_Supported_Language then - Outputs.Fatal_Error - ("Cannot instrument main source file (unsupported" - & " language): " & F); - end if; - - Register_Main_To_Instrument - (IC, Mains_To_Instrument (Lang), File, Project); - end; - end loop; + Compiler_Opts.Append (Desc.Compiler_Options (Lang)); + end if; + if not Compiler_Opts.Is_Empty then + case C_Family_Language (Lang) is + when CPP_Language => + Result.Append (+"--c++-opts"); + when C_Language => + Result.Append (+"--c-opts"); + end case; end if; - end if; - - -- Know that we know all the sources we need to instrument, prepare - -- output directories. - - Prepare_Output_Dirs (IC); - - -- For each library unit... - - for Cur in LU_Map.Iterate loop - - -- Instrument compilation units (only the ones this library unit - -- owns). Sort them first, so that the instrumentation order is - -- deterministic. - declare - package Sorting is new CU_Name_Vectors.Generic_Sorting; - - LU_Info : constant Library_Unit_Info_Access := - Library_Unit_Maps.Element (Cur); - All_Externally_Built : Boolean := True; + First : Boolean := True; + Compiler_Opts_Str : Unbounded_String; begin - Sorting.Sort (LU_Info.CU_Names); - for CU of LU_Info.CU_Names loop - if CU.Ignored then - declare - Unit_Info : Ignored_Unit_Info renames - Ignored_Units.Element (CU.Name).all; - Filename : constant String := To_String - (Unit_Info.Filename); - begin - -- Simply add the unit to the file table if it is not - -- externally built. - - if not Unit_Info.Prj_Info.Externally_Built then - All_Externally_Built := False; - Files_Table.Consolidate_Ignore_Status - (Index => Files_Table.Get_Index_From_Generic_Name - (Name => Filename, - Kind => Files_Table.Source_File), - Status => Files_Table.Always); - end if; - end; + for Compiler_Opt of Compiler_Opts loop + if First then + First := False; else - declare - Unit_Info : Instrumented_Unit_Info renames - IC.Instrumented_Units.Element (CU.Name).all; - Filename : constant String := - To_String (Unit_Info.Filename); - Basename : constant String := - Ada.Directories.Simple_Name (Filename); - begin - -- Do not process units from externally built projects - - if not Unit_Info.Prj_Info.Externally_Built then - - -- Keep a note that we are processing at least one - -- source file from a non-externally built project. - - All_Externally_Built := False; - - -- Run the instrumentation for this file - - if Verbose then - Put_Line ("Instrumenting " & Basename); - end if; - Instrumenters (Unit_Info.Language).Instrument_Unit - (CU.Name, Unit_Info); - - -- Update the Ignore_Status of the CU we instrumented - - Files_Table.Consolidate_Ignore_Status - (Index => Files_Table.Get_Index_From_Generic_Name - (Name => Filename, - Kind => Files_Table.Source_File, - Indexed_Simple_Name => True), - Status => Files_Table.Never); - end if; - end; + Append (Compiler_Opts_Str, ","); end if; + Append (Compiler_Opts_Str, Compiler_Opt); end loop; - - -- Except for units entirely externally built (the spec, the body, - -- and potential subunits all belong to externally built - -- projects), emit a SID file to contain mappings between bits in - -- coverage buffers and SCOs. - - if not All_Externally_Built then - declare - Context : aliased Coverage.Context := Coverage.Get_Context; - Obj_SID : constant String := - SID_Filename (Cur, In_Library_Dir => False); - Lib_SID : constant String := - SID_Filename (Cur, In_Library_Dir => True); - Success : Boolean; - begin - Checkpoints.Checkpoint_Save - (Obj_SID, - Context'Access, - Purpose => Checkpoints.Instrumentation); - - -- If the object directory is different from the library - -- directory, copy the SID file to the library directory. - -- This allows "gnatcov coverage" to automatically pick it - -- up if the project is later made externally built. - - if Obj_SID /= Lib_SID then - - -- Unlike the object directory, which GNATCOLL.Project - -- creates automatically, the library directory may not - -- exist: create it if needed. - - begin - Create (Create (+Lib_SID).Dir_Name).Make_Dir; - exception - when Exc : VFS_Directory_Error => - Outputs.Fatal_Error - (Ada.Exceptions.Exception_Message (Exc)); - end; - - GNAT.OS_Lib.Copy_File - (Name => Obj_SID, - Pathname => Lib_SID, - Success => Success, - Mode => GNAT.OS_Lib.Overwrite); - if not Success then - Outputs.Fatal_Error - ("Error while copying " & Obj_SID - & " to the library directory: " & Lib_SID); - end if; - end if; - end; - - if Switches.Verbose then - SC_Obligations.Dump_All_SCOs; - end if; - end if; + Result.Append (Compiler_Opts_Str); end; - Checkpoints.Checkpoint_Clear; - end loop; - - if IC.Instrumented_Units.Length = 0 then - Outputs.Fatal_Error ("No unit to instrument."); + if Desc.Compiler_Driver (Lang) /= Null_Unbounded_String then + Result.Append (+"--compiler-driver"); + Result.Append (Desc.Compiler_Driver (Lang)); + end if; end if; - declare - Instrumented_Units : Instrument.Common.CU_Name_Vectors.Vector; - -- List of instrumented units - - begin - for Cur in IC.Instrumented_Units.Iterate loop - Instrumented_Units.Append (Instrumented_Unit_Maps.Key (Cur)); - end loop; - - -- Emit the unit to contain the list of coverage buffers, exported to - -- a C symbol, in one of the language supported by the project. - -- - -- Note that this has an implicit hack to it: if Ada is a language of - -- the project, it will pick it over the others (as it is the first - -- enumeration member of the Src_Supported_Language type). This - -- matters as we make the assumption in the Emit_Dump_Helper_Unit - -- implementation in instrument-ada_unit.adb (when instrumenting for - -- an Ada main) that the Ada package for buffers list units always - -- exists: we need to include it in the main closure, as it puts - -- buffer units in scope by importing them (otherwise they aren't - -- as they are used through C symbol importations). - - for Language in Src_Supported_Language loop - if Project.Project.Root_Project.Has_Language (Image (Language)) - then - Instrumenters (Language).Emit_Buffers_List_Unit - (Root_Project_Info.all, Instrumented_Units); - exit; - end if; - end loop; - - -- Instrument all the mains to add the dump of coverage buffers. - -- Make sure to pass the instrumented version if the main is a unit - -- of interest. - - for Language in Src_Supported_Language loop - - for Main of Mains_To_Instrument (Language) loop - declare - Filename : constant String := - (if IC.Instrumented_Units.Contains (Main.CU_Name) - then (+Main.Prj_Info.Output_Dir) / (+Main.File.Base_Name) - else +Main.File.Full_Name); - begin - Instrumenters (Language).Auto_Dump_Buffers_In_Main - (Filename, - Instrumented_Units, - Dump_Config, - Main.Prj_Info.all); - end; - end loop; - end loop; - end; - - -- Deallocate Ignored_Unit_Infos - - for IU of Ignored_Units loop - Free (IU); - end loop; - Ignored_Units := Ignored_Units_Maps.Empty_Map; + Result.Append (+"--output-dir"); + Result.Append (Desc.Output_Dir); - -- Save the dump trigger+channel information in the root project's - -- object directory. This allows user scripts to automatically know - -- where to expect source trace files (dump channel) without inspecting - -- all inputs (command-line arguments, project file, instrumentation - -- runtime, etc.) and whether that info is reliable (it is not if the - -- dump trigger is manual). - - declare - J : constant JSON_Value := Create_Object; - Filename : constant String := - Project.Output_Dir & "/gnatcov-instr.json"; - begin - J.Set_Field ("dump-trigger", Image (Dump_Config.Trigger)); - J.Set_Field ("dump-channel", Image (Dump_Config.Channel)); - Write (Filename, J, Compact => False); - end; - end Instrument_Units_Of_Interest; + return Result; + end Unparse; end Instrument; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 8596dfb96..46c5eb4b3 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -18,11 +18,11 @@ -- Support for source instrumentation +with Ada.Containers.Hashed_Maps; with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; -with Ada.Strings.Unbounded; - -with GNAT.Regexp; +with Ada.Strings.Unbounded.Hash; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with GNATCOLL.Projects; use GNATCOLL.Projects; @@ -38,6 +38,12 @@ package Instrument is package US renames Ada.Strings.Unbounded; + package GPR renames GNATCOLL.Projects; + + use type Ada.Containers.Count_Type; + + Parallelism_Level : Natural := 1; + function Language_Kind (Language : Some_Language) return Any_Language_Kind; -- Returns the language kind (unit-based or file-based) for the given @@ -60,7 +66,7 @@ package Instrument is with Pre => not Name.Is_Empty; -- Turn the given qualified name into Ada syntax - type Compilation_Unit_Name + type Compilation_Unit_Part (Language_Kind : Any_Language_Kind := Unit_Based_Language) is record @@ -75,26 +81,22 @@ package Instrument is -- Fallback for file-based languages (like C). We will use the -- simple filename for now. - Project_Name : US.Unbounded_String; - -- We also need the project name as different projects can have - -- the same file. - end case; end record; - -- Unique identifier for an instrumented unit + -- Unique identifier for an instrumented unit part Part_Tags : constant array (Unit_Parts) of Character := (Unit_Spec => 'S', Unit_Body => 'B', Unit_Separate => 'U'); - function "=" (Left, Right : Compilation_Unit_Name) return Boolean; + function "=" (Left, Right : Compilation_Unit_Part) return Boolean; - function "<" (Left, Right : Compilation_Unit_Name) return Boolean; + function "<" (Left, Right : Compilation_Unit_Part) return Boolean; -- Compare the result of a call to Instrumented_Unit_Slug (which gives -- unique identifiers for each compilation unit name) for both operands. - function Image (CU_Name : Compilation_Unit_Name) return String; + function Image (CU_Name : Compilation_Unit_Part) return String; -- Return a string representation of CU_Name for use in diagnostics function Qualified_Name_Slug (Name : Ada_Qualified_Name) return String; @@ -103,12 +105,18 @@ package Instrument is -- not contain any '-'. function Instrumented_Unit_Slug - (Instrumented_Unit : Compilation_Unit_Name) return String; + (Instrumented_Unit : Compilation_Unit_Part) return String; -- Given a unit to instrument, return a unique identifier to describe it -- (the so called slug). -- -- One can use this slug to generate unique names for this unit. + function Filename_Slug (Fullname : String) return String; + -- Given a filename to instrument, return a unique identifier to describe + -- it (the so called slug). + -- + -- One can use this slug to generate unique names for this unit. + function To_Qualified_Name (Name : String) return Ada_Qualified_Name; -- Convert a String qualified name into our format @@ -125,30 +133,29 @@ package Instrument is function CU_Name_For_Unit (Unit : Ada_Qualified_Name; - Part : Unit_Parts) return Compilation_Unit_Name; + Part : Unit_Parts) return Compilation_Unit_Part; -- Return the compilation unit name for the Ada compilation unit -- corresponding to the unit name and the unit part parameters. function CU_Name_For_File - (Filename : US.Unbounded_String; - Project_Name : US.Unbounded_String) return Compilation_Unit_Name; + (Filename : US.Unbounded_String) return Compilation_Unit_Part; -- Return the compilation unit name for the C translation unit -- corresponding to the filename parameter. function To_Compilation_Unit_Name - (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Name; + (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Part; -- Return the compilation unit name corresponding to the unit in -- Source_File. function To_Filename (Project : Project_Type; - CU_Name : Compilation_Unit_Name; + CU_Name : Compilation_Unit_Part; Language : Any_Language) return String; -- Return the name of the file to contain the given compilation unit, -- according to Project's naming scheme. package Instrumented_Unit_To_CU_Maps is new Ada.Containers.Ordered_Maps - (Key_Type => Compilation_Unit_Name, + (Key_Type => Compilation_Unit_Part, Element_Type => CU_Id); Instrumented_Unit_CUs : Instrumented_Unit_To_CU_Maps.Map; @@ -165,31 +172,62 @@ package Instrument is -- Save the preprocessing command for each unit that supports it function Find_Instrumented_Unit - (CU_Name : Compilation_Unit_Name) return CU_Id; + (CU_Name : Compilation_Unit_Part) return CU_Id; -- Return the CU_Id corresponding to the given instrumented unit, or -- No_CU_Id if not found. - procedure Instrument_Units_Of_Interest - (Dump_Config : Any_Dump_Config; - Language_Version : Any_Language_Version; - Ignored_Source_Files : access GNAT.Regexp.Regexp; - Mains : String_Vectors.Vector); - -- Generate instrumented sources for the source files of all units of - -- interest. Also save mappings between coverage buffers and SCOs for each - -- library units to SID files (one per library unit). - -- - -- Depending on Dump_Config, instrument mains to schedule a call to the - -- dump procedure for the list of coverage buffers in all mains in the - -- project. - -- - -- Language_Version restricts what source constructs the instrumenter is - -- allowed to use. For instance, if Ada_2005 (or a lower version) is - -- passed, it will not be allowed to introduce expression functions, and - -- thus will emit a warning when it needed to do so. - -- - -- If Ignored_Source_File is non-null, ignore files whose names match the - -- accessed pattern. - -- - -- Mains is the list of source files that were listed on the command line: - -- if non-empty, they replace the mains specified in project files. + type Lang_Array is array (Src_Supported_Language range <>) + of Unbounded_String; + type C_Lang_Array_Vec is array (C_Family_Language) of String_Vectors.Vector; + + package String_Vectors_Maps is new Ada.Containers.Hashed_Maps + (Key_Type => Unbounded_String, + Element_Type => String_Vectors.Vector, + Equivalent_Keys => Ada.Strings.Unbounded."=", + Hash => Ada.Strings.Unbounded.Hash, + "=" => String_Vectors."="); + + type Prj_Desc is record + Prj_Name : Unbounded_String; + -- Name for the project + + Output_Dir : Unbounded_String; + -- Where the instrumented sources and coverage buffer units are + -- generated. + + Spec_Suffix, Body_Suffix : Lang_Array (Src_Supported_Language); + -- Suffixes for the body and the spec + + Dot_Replacement : Unbounded_String; + -- Character to use as identifier separator for file naming (used for + -- unit-based languages). + + Compiler_Driver : Lang_Array (C_Family_Language); + -- Compiler used to compile the sources + + Compiler_Options : C_Lang_Array_Vec; + -- For languages resorting to the compiler to preprocess sources, list + -- of compiler switches to pass to the preprocessor invocation. + + Compiler_Options_Unit : String_Vectors_Maps.Map; + -- Compiler switches applying to a specific unit + + Search_Paths : String_Vectors.Vector; + -- List of compiler switches to look up the project source directories + + end record; + -- This record stores the information that is required from the project + -- for instrumentation purposes. + + type Prj_Desc_Access is access Prj_Desc; + + function Load_From_Command_Line return Prj_Desc; + + function Unparse + (Desc : Prj_Desc; + Unit_Name : Unbounded_String; + Lang : Src_Supported_Language) return String_Vectors.Vector; + -- Return a list of command line switches holding all the project + -- information for the given Unit_Name of the language Lang. + end Instrument; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 39e6d4fb1..dda567487 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -16,14 +16,11 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Containers.Hashed_Maps; with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Containers.Indefinite_Ordered_Sets; -with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; with Ada.Directories; use Ada.Directories; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; -with Ada.Strings.Unbounded.Hash; with Ada.Tags; with Ada.Text_IO; use Ada.Text_IO; @@ -34,16 +31,17 @@ with GNATCOLL.Traces; with GNATCOLL.Projects.Aux; with GNATCOLL.VFS; use GNATCOLL.VFS; +with Command_Line; use Command_Line; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -with Instrument; use Instrument; with Inputs; use Inputs; +with Instrument; use Instrument; with Outputs; use Outputs; with Paths; use Paths; package body Project is - subtype Project_Unit is Files_Table.Project_Unit; - use type Project_Unit; + subtype Compilation_Unit is Files_Table.Compilation_Unit; + use type Compilation_Unit; Coverage_Package : aliased String := "coverage"; Coverage_Package_List : aliased String_List := @@ -139,14 +137,6 @@ package body Project is -- Whether we found at least one source file in the projects of interest -- that matches this unit. - Is_Stub : Boolean; - -- Whether this record describes a source file that is not a bona fide - -- unit of interest: a subunit (Ada) or a header file (C/C++). - -- - -- Such source files are not units of their own (in particular they - -- don't have their own LI file), but we still need them to appear in - -- unit lists, for reporting purposes. - Language : Some_Language; -- Language for this unit @@ -158,7 +148,7 @@ package body Project is end record; package Unit_Maps is new Ada.Containers.Indefinite_Ordered_Maps - (Key_Type => Project_Unit, + (Key_Type => Compilation_Unit, Element_Type => Unit_Info); procedure Add_Unit @@ -168,7 +158,7 @@ package body Project is Info : File_Info; Language : Some_Language); -- Add a Unit_Info entry to Units. The key for this new entry (which is a - -- Project_Unit) is computed using the Original_Name, and the + -- Compilation_Unit) is computed using the Original_Name, and the -- Info.Project_Name if the unit is of a file-based language. procedure Warn_Missing_Info (What_Info : String; Unit : in out Unit_Info); @@ -176,7 +166,9 @@ package body Project is -- Unit. Unit_Map : Unit_Maps.Map; - -- Map lower-case unit names to Unit_Info records for all units of interest + -- Map lower-case unit names to Unit_Info records for all units of + -- interest. This map contains header files (C/C++) but does not contain + -- separate (Ada) units. procedure Initialize (Target, Runtime, CGPR_File : GNAT.Strings.String_Access) @@ -234,27 +226,38 @@ package body Project is -- Note that this also returns source files for mains that are not units of -- interest. - function Runtime_Has_File (Filename : Filesystem_String) return Boolean; - -- Return whether Filename can be found among the sources of the - -- configured Ada runtime. + ---------------------- + -- Owning_Unit_Name -- + ---------------------- - --------------------- - -- To_Project_Unit -- - --------------------- + function Owning_Unit_Name (Info : File_Info) return String is + begin + if Info.Unit_Part = Unit_Separate then + return Prj_Tree.Info (Prj_Tree.Other_File (Info.File)).Unit_Name; + else + return Info.Unit_Name; + end if; + end Owning_Unit_Name; - function To_Project_Unit - (Unit_Name : String; - Project : Project_Type; - Language : Some_Language) return Files_Table.Project_Unit + ------------------------- + -- To_Compilation_Unit -- + ------------------------- + + function To_Compilation_Unit + (Info : File_Info) return Files_Table.Compilation_Unit is - U : Project_Unit (Language_Kind (Language)); + Language : constant Some_Language := To_Language (Info.Language); + U : Compilation_Unit; begin - U.Unit_Name := +Unit_Name; - if U.Language = File_Based_Language then - U.Project_Name := +Project.Name; - end if; + U.Language := Language_Kind (Language); + case U.Language is + when File_Based_Language => + U.Unit_Name := +(+Info.File.Full_Name); + when Unit_Based_Language => + U.Unit_Name := +Owning_Unit_Name (Info); + end case; return U; - end To_Project_Unit; + end To_Compilation_Unit; --------- -- "+" -- @@ -286,30 +289,27 @@ package body Project is Info : File_Info; Language : Some_Language) is - Unit_Part : constant Unit_Parts := Info.Unit_Part; - Is_Stub : constant Boolean := - (case Language is - when C_Family_Language => Unit_Part = Unit_Spec, - when Ada_Language => Unit_Part = Unit_Separate); - Orig_Name : constant Unbounded_String := +Fold_Filename_Casing (Original_Name); - Unit_Name : constant Project_Unit := - To_Project_Unit (Original_Name, Info.Project, Language); + Unit_Name : constant Compilation_Unit := To_Compilation_Unit (Info); Ignored_Inserted : Boolean; + Is_Header : Boolean := False; begin - -- Disable warnings for stub units as they do not have a corresponding + -- Disable warnings for header files as they do not have a corresponding -- library file. + if Language in C_Family_Language and then Info.Unit_Part = Unit_Spec then + Is_Header := True; + end if; + Units.Insert (Key => Unit_Name, New_Item => (Original_Name => Orig_Name, Present_In_Projects => False, - Is_Stub => Is_Stub, Language => Language, - LI_Seen => Is_Stub, - Warned_About_Missing_Info => Is_Stub), + LI_Seen => Is_Header, + Warned_About_Missing_Info => Is_Header), Position => Cur, Inserted => Ignored_Inserted); end Add_Unit; @@ -467,51 +467,15 @@ package body Project is --------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Files_Table.Project_Unit; - Is_Stub : Boolean)) + (Callback : access procedure (Name : Files_Table.Compilation_Unit)) is use Unit_Maps; begin for Cur in Unit_Map.Iterate loop - declare - Info : Unit_Info renames Reference (Unit_Map, Cur); - begin - Callback (Key (Cur), Info.Is_Stub); - end; + Callback (Key (Cur)); end loop; end Enumerate_Units_Of_Interest; - ------------------------- - -- Is_Unit_Of_Interest -- - ------------------------- - - function Is_Unit_Of_Interest - (Project : Project_Type; - Unit_Name : String; - Language : Some_Language) return Boolean - is - U : constant Project_Unit := - To_Project_Unit (Unit_Name, Project, Language); - begin - return Unit_Map.Contains (U); - end Is_Unit_Of_Interest; - - ------------------------- - -- Is_Unit_Of_Interest -- - ------------------------- - - function Is_Unit_Of_Interest (Full_Name : String) return Boolean is - FI : constant File_Info := - Prj_Tree.Info (Create (+Full_Name)); - Unit_Name : constant String := - (case Language_Kind (To_Language (FI.Language)) is - when Unit_Based_Language => FI.Unit_Name, - when File_Based_Language => +FI.File.Base_Name); - begin - return Is_Unit_Of_Interest - (FI.Project, Unit_Name, To_Language (FI.Language)); - end Is_Unit_Of_Interest; - ------------------------- -- Enumerate_SCO_Files -- ------------------------- @@ -539,23 +503,8 @@ package body Project is declare use Unit_Maps; - LI_Source_Unit : constant String := LI.Source.Unit_Name; - LI_Source_File : constant String := +LI.Source.File.Base_Name; - - U : constant String := - (if LI_Source_Unit'Length > 0 - then LI_Source_Unit - else LI_Source_File); - -- For unit-based languages (Ada), retrieve unit name from - -- SCOs file. For file-based languages (C), fall back to - -- translation unit source file name instead. - Cur : constant Cursor := - Unit_Map.Find - (To_Project_Unit - (U, - Project_Type (LI.LI_Project.all), - To_Language (LI.Source.Language))); + Unit_Map.Find (To_Compilation_Unit (LI.Source.all)); begin if Has_Element (Cur) then Callback.all (+LI.Library_File.Full_Name); @@ -599,17 +548,30 @@ package body Project is -- Process_Source_File -- ------------------------- - procedure Process_Source_File (Info : File_Info; Unit_Name : String) is + procedure Process_Source_File (Info : File_Info; Unit_Name : String) + is + pragma Unreferenced (Unit_Name); + Info_Lang : constant Some_Language := To_Language (Info.Language); begin - if (Language = All_Languages - or else - Language = To_Language (Info.Language)) - and then - (Include_Stubs - or else Is_Unit_Of_Interest - (Info.Project, Unit_Name, To_Language (Info.Language))) - then - Callback (Info.Project, Info); + if Language = All_Languages or else Language = Info_Lang then + + -- If this is a header, consider it a unit of interest. For now, + -- they can only be ignored through the --ignore-source-files + -- switch. + + if (Language_Kind (Info_Lang) = File_Based_Language + and then Info.Unit_Part = Unit_Spec) + + -- Otherwise, check if the unit is in the units of interest + -- map + + or else + (Unit_Map.Contains (To_Compilation_Unit (Info)) + and then (Info.Unit_Part /= Unit_Separate + or else Include_Stubs)) + then + Callback (Info.Project, Info); + end if; end if; end Process_Source_File; @@ -651,51 +613,6 @@ package body Project is end; end Find_Source_File; - ---------------------- - -- Runtime_Has_File -- - ---------------------- - - function Runtime_Has_File (Filename : Filesystem_String) return Boolean is - Result_File : Virtual_File; - -- Virtual_File for Ada.Finalization. Only search predefined sources. - Ambiguous : Boolean; - -- Required in the call for GNATCOLL.Projects.Create - begin - GNATCOLL.Projects.Create - (Self => Prj_Tree.all, - Name => Filename, - Use_Object_Path => False, - Ambiguous => Ambiguous, - File => Result_File, - Predefined_Only => True); - - -- We don't expect there to be multiple homonyms for the runtime files - - pragma Assert (not Ambiguous); - return Result_File /= No_File; - end Runtime_Has_File; - - ------------------------------ - -- Runtime_Has_Finalization -- - ------------------------------ - - function Runtime_Supports_Finalization return Boolean is - (Runtime_Has_File ("a-finali.ads")); - - --------------------------------------- - -- Runtime_Supports_Task_Termination -- - --------------------------------------- - - function Runtime_Supports_Task_Termination return Boolean is - begin - -- We need both Ada.Task_Identification (a-taside.ads) and - -- Ada.Task_Termination (a-taster.ads) to be able to use task - -- termination. - - return Runtime_Has_File ("a-taster.ads") - and then Runtime_Has_File ("a-taside.ads"); - end Runtime_Supports_Task_Termination; - ---------------- -- Initialize -- ---------------- @@ -994,20 +911,26 @@ package body Project is procedure Process_Source_File (Info : File_Info; Unit_Name : String) is - Cur : Unit_Maps.Cursor; + Cur : Unit_Maps.Cursor; + Actual_Unit_Name : constant String := + (if Info.Unit_Part = Unit_Separate + then Owning_Unit_Name (Info) + else Unit_Name); begin -- Never try to perform coverage on our coverage runtime -- library (in one of the gnatcov_rts*.gpr projects) or on -- our coverage buffer units (in user projects). - if Strings.Has_Prefix (Unit_Name, "gnatcov_rts.") then + if Strings.Has_Prefix (Actual_Unit_Name, "gnatcov_rts.") + or else Strings.Has_Prefix (Actual_Unit_Name, "gcvrt") + then return; end if; if not Units_Specified or else (Has_Matcher and then GNAT.Regexp.Match - (To_Lower (Unit_Name), + (To_Lower (Actual_Unit_Name), Units_Specified_Matcher)) then Add_Unit @@ -1024,7 +947,9 @@ package body Project is -- Units attributes only apply to the project itself. Iterate_Source_Files - (Project, Process_Source_File'Access, Recursive => False); + (Project, Process_Source_File'Access, + Recursive => False, + Include_Stubs => True); Inc_Units_Defined := True; end; end if; @@ -1035,7 +960,7 @@ package body Project is for Cur in Inc_Units.Iterate loop declare use Unit_Maps; - K : constant Project_Unit := Key (Cur); + K : constant Compilation_Unit := Key (Cur); begin if not Exc_Units.Contains (K) then declare @@ -1089,7 +1014,8 @@ package body Project is Units_Present : String_Vectors.Vector; -- All units that were included - Patterns_Not_Covered : String_Vectors.Vector; + Patterns_Not_Covered : String_Sets.Set := + To_String_Set (Unit_Patterns); -- Patterns that do not match any of the present units procedure Add_To_Unit_Presents (C : Unit_Maps.Cursor); @@ -1098,9 +1024,16 @@ package body Project is -- Add_To_Unit_Presents -- -------------------------- - procedure Add_To_Unit_Presents (C : Unit_Maps.Cursor) is + procedure Add_To_Unit_Presents (C : Unit_Maps.Cursor) + is + P_Unit : constant Compilation_Unit := Unit_Maps.Key (C); + Unit_Name : constant Unbounded_String := + (case P_Unit.Language is + when File_Based_Language => + +Ada.Directories.Simple_Name (+P_Unit.Unit_Name), + when Unit_Based_Language => P_Unit.Unit_Name); begin - Units_Present.Append (Unit_Maps.Key (C).Unit_Name); + Units_Present.Append (Unit_Name); end Add_To_Unit_Presents; begin @@ -1211,39 +1144,15 @@ package body Project is Units : out Unit_Maps.Map; Defined : out Boolean) is - package FI_Vectors is new Ada.Containers.Vectors - (Index_Type => Positive, Element_Type => File_Info); - - use type FI_Vectors.Vector; - - package Unit_Name_FI_Vector_Maps is new Ada.Containers.Ordered_Maps - (Key_Type => Unbounded_String, - Element_Type => FI_Vectors.Vector); - - Units_Present : String_Vectors.Vector; - -- List of all units in Prj - - Unit_Present_To_FI : Unit_Name_FI_Vector_Maps.Map; - -- Map a unit name to a file information vector. A unit name can be - -- be mapped to multiple file info if there are homonym source files. - - package Unit_Language_Maps is new Ada.Containers.Hashed_Maps - (Key_Type => Unbounded_String, - Element_Type => Some_Language, - Equivalent_Keys => "=", - Hash => Hash); - Unit_Languages : Unit_Language_Maps.Map; - -- Language for each unit in Units_Present - Unit_Patterns : String_Vectors.Vector; Attr_For_Pattern : String_Maps.Map; -- Patterns identifying unit names and project attribute from which we -- got the pattern. We use Attr_For_Pattern for reporting purposes. - Patterns_Not_Covered : String_Vectors.Vector; + Patterns_Not_Covered : String_Sets.Set; -- Patterns that do not match any of the present unit - Ignored_Cur : Unit_Maps.Cursor; + Cur : Unit_Maps.Cursor; procedure Add_Pattern (Attr, Item : String); -- Add Item to Unit_Patterns. Also save from which project attribute @@ -1267,18 +1176,33 @@ package body Project is ------------------------- procedure Process_Source_File (Info : File_Info; Unit_Name : String) is + use type Ada.Containers.Count_Type; + use String_Vectors; + Actual_Unit_Name : Vector := + To_Vector + (+(if Info.Unit_Part = Unit_Separate + then Owning_Unit_Name (Info) + else Unit_Name), + 1); + begin + Match_Pattern_List + (Patterns_List => Unit_Patterns, + Strings_List => Actual_Unit_Name, + Patterns_Not_Covered => Patterns_Not_Covered); - use Unit_Name_FI_Vector_Maps; + -- Add it only if it matches one of the patterns - Key : constant Unbounded_String := +Unit_Name; - Cur : constant Cursor := Unit_Present_To_FI.Find (Key); - begin - Units_Present.Append (Key); - Unit_Languages.Include (Key, To_Language (Info.Language)); - if Has_Element (Cur) then - Unit_Present_To_FI.Reference (Cur).Append (Info); - else - Unit_Present_To_FI.Insert (Key, FI_Vectors.To_Vector (Info, 1)); + if not Actual_Unit_Name.Is_Empty then + declare + Lang : constant Some_Language := To_Language (Info.Language); + begin + Add_Unit + (Units, + Cur, + Unit_Name, + Info, + Lang); + end; end if; end Process_Source_File; @@ -1291,6 +1215,7 @@ package body Project is List_From_Project (Prj, List_Attr, List_File_Attr, Add_Pattern'Access, Defined); + Patterns_Not_Covered := To_String_Set (Unit_Patterns); if not Defined then return; @@ -1301,28 +1226,13 @@ package body Project is -- source file name. Iterate_Source_Files - (Prj, Process_Source_File'Access, Recursive => False); - - Match_Pattern_List (Patterns_List => Unit_Patterns, - Strings_List => Units_Present, - Patterns_Not_Covered => Patterns_Not_Covered); + (Prj, Process_Source_File'Access, + Recursive => False, Include_Stubs => True); for Pattern of Patterns_Not_Covered loop Warn ("no unit " & (+Pattern) & " in project " & Prj.Name & " (" & (+Attr_For_Pattern.Element (Pattern)) & " attribute)"); end loop; - - for Unit_Name of Units_Present loop - for Info of Unit_Present_To_FI (Unit_Name) loop - Add_Unit - (Units, - Ignored_Cur, - +Unit_Name, - Info, - Unit_Languages.Element (Unit_Name)); - end loop; - end loop; - end Units_From_Project; ----------------------- @@ -1669,7 +1579,7 @@ package body Project is procedure Finalize is begin - if Prj_Tree /= null then + if Prj_Tree /= null and then not Args.Bool_Args (Opt_Save_Temps) then GNATCOLL.Projects.Aux.Delete_All_Temp_Files (Prj_Tree.Root_Project); end if; end Finalize; @@ -1683,4 +1593,46 @@ package body Project is return Prj_Tree; end Project; + ------------------- + -- Source_Suffix -- + ------------------- + + function Source_Suffix + (Lang : Src_Supported_Language; + Part : GNATCOLL.Projects.Unit_Parts; + Project : GNATCOLL.Projects.Project_Type) return String + is + Attr : constant Attribute_Pkg_String := + Build + (Package_Name => "Naming", + Attribute_Name => + (case Part is + when Unit_Body => "Body_Suffix", + when Unit_Spec => "Spec_Suffix", + when Unit_Separate => raise Program_Error)); + begin + case Part is + when Unit_Body => + return Project.Attribute_Value + (Attribute => Attr, + Index => Image (Lang), + Default => (case Lang is + when Ada_Language => ".adb", + when C_Language => ".c", + when CPP_Language => ".cc")); + + when Unit_Spec => + return Project.Attribute_Value + (Attribute => Attr, + Index => Image (Lang), + Default => (case Lang is + when Ada_Language => ".ads", + when C_Language => ".h", + when CPP_Language => ".hh")); + + when Unit_Separate => + return (raise Program_Error); + end case; + end Source_Suffix; + end Project; diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index fb8b60812..981ab4c6a 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -114,33 +114,22 @@ package Project is -- path of its main executable (including its suffix, for instance ".exe"). -- Otherwise, return an empty string. - function To_Project_Unit - (Unit_Name : String; - Project : Project_Type; - Language : Some_Language) return Files_Table.Project_Unit; - -- Return the Project_Unit value that designates the same unit as - -- Unit_Name/Project/Language. + function Owning_Unit_Name (Info : File_Info) return String + with Pre => Is_Project_Loaded; + -- Return the owning unit name meaning the unit name if this is a body / + -- specification, and the top parent unit name if this is a separate. + + function To_Compilation_Unit + (Info : File_Info) return Files_Table.Compilation_Unit; + -- Return the Compilation_Unit for Info -------------------------------------- -- Accessors for project properties -- -------------------------------------- procedure Enumerate_Units_Of_Interest - (Callback : access procedure (Name : Files_Table.Project_Unit; - Is_Stub : Boolean)); - -- Call Callback once for every unit of interest. Name is the unit name, - -- and Is_Stub corresponds to the Unit_Info.Is_Stub field (see - -- project.adb). - - function Is_Unit_Of_Interest - (Project : Project_Type; - Unit_Name : String; - Language : Some_Language) return Boolean; - -- Return whether the unit Unit_Name that belongs to the project Project - -- is a unit of interest. - - function Is_Unit_Of_Interest (Full_Name : String) return Boolean; - -- Same as above, but given a full name + (Callback : access procedure (Name : Files_Table.Compilation_Unit)); + -- Call Callback once for every unit of interest. Name is the unit name procedure Enumerate_SCOs_Files (Callback : access procedure (Lib_Name : String); @@ -192,15 +181,6 @@ package Project is -- -- If no project is loaded, just return null. - function Runtime_Supports_Finalization return Boolean with - Pre => Is_Project_Loaded; - -- Return whether the configured runtime includes the Ada.Finalization unit - - function Runtime_Supports_Task_Termination return Boolean with - Pre => Is_Project_Loaded; - -- Return whether the configured runtime has necessary units to implement - -- the ravenscar-task-termination dump trigger. - function Switches (Op : String) return String_List_Access with Pre => Is_Project_Loaded; -- Return a list of gnatcov switches defined by the root project. Caller @@ -254,4 +234,10 @@ package Project is -- Unless Include_Extended is True, only process ultimate extending -- projects. + function Source_Suffix + (Lang : Src_Supported_Language; + Part : GNATCOLL.Projects.Unit_Parts; + Project : GNATCOLL.Projects.Project_Type) return String; + -- Return the filename suffix corresponding for Part files and Lang + end Project; diff --git a/tools/gnatcov/rts/gcvrt.ads b/tools/gnatcov/rts/gcvrt.ads new file mode 100644 index 000000000..44de3e1a7 --- /dev/null +++ b/tools/gnatcov/rts/gcvrt.ads @@ -0,0 +1,23 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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. -- +------------------------------------------------------------------------------ + +-- Namespace for units generated for instrumentation purposes + +package GCVRT is + pragma Pure; +end GCVRT; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index 0a95db446..158e8cdec 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -78,7 +78,6 @@ package GNATcov_RTS.Buffers is Language : Any_Language_Kind; Unit_Part : Any_Unit_Part; Unit_Name : GNATcov_RTS_String; - Project_Name : GNATcov_RTS_String; Bit_Maps_Fingerprint : Fingerprint_Type; Statement, Decision, MCDC : System.Address; Statement_Last_Bit, Decision_Last_Bit, diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index 21cd45eac..e1ef95be9 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -93,10 +93,6 @@ extern "C" enum gnatcov_rts_unit_part unit_part; struct gnatcov_rts_string unit_name; - /* Project name for this compilation unit. This is only initialized for - file-based languages (otherwise, it is an empty string). */ - struct gnatcov_rts_string project_name; - /* Hash of buffer bit mappings for this unit, as gnatcov computes it (see SC_Obligations). Used as a fast way to check that gnatcov will be able to interpret buffer bits from a source traces using buffer bit mappings diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index b2a96c101..fe2d272ba 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -118,14 +118,13 @@ write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, { struct trace_entry_header header; header.unit_name_length = (uint32_t) buffers->unit_name.length; - header.project_name_length = (uint32_t) buffers->project_name.length; header.statement_bit_count = (uint32_t) buffers->statement_last_bit + 1; header.decision_bit_count = (uint32_t) buffers->decision_last_bit + 1; header.mcdc_bit_count = (uint32_t) buffers->mcdc_last_bit + 1; header.language_kind = (uint8_t) buffers->language_kind; header.unit_part = (uint8_t) buffers->unit_part; header.bit_buffer_encoding = GNATCOV_RTS_LSB_FIRST_BYTES; - memset (header.padding, 0, 1); + memset (header.padding, 0, 5); memcpy (&header.fingerprint, buffers->fingerprint, FINGERPRINT_SIZE); memcpy (&header.bit_maps_fingerprint, buffers->bit_maps_fingerprint, FINGERPRINT_SIZE); @@ -133,9 +132,6 @@ write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, write_bytes (output, (char *) &header, sizeof (header)); write_bytes (output, buffers->unit_name.str, buffers->unit_name.length); write_padding (write_bytes, output, buffers->unit_name.length); - write_bytes (output, buffers->project_name.str, - buffers->project_name.length); - write_padding (write_bytes, output, buffers->project_name.length); write_buffer (write_bytes, output, buffers->statement, buffers->statement_last_bit + 1); write_buffer (write_bytes, output, buffers->decision, diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces.h b/tools/gnatcov/rts/gnatcov_rts_c-traces.h index 6e3288395..33664a30d 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces.h @@ -115,11 +115,6 @@ extern "C" describes. */ uint32_t unit_name_length; - /* For file-based languages, length of the project name this file belongs - to. For unit-based languages, the unit name is unique so this piece of - information is not needed (and thus will be 0). */ - uint32_t project_name_length; - /* Number of bits in the statement, decision and MC/DC coverage buffers. */ uint32_t statement_bit_count; uint32_t decision_bit_count; @@ -148,7 +143,7 @@ extern "C" /* Padding used only to make the size of this trace entry header a multiple of 8 bytes. Must be zero. */ - uint8_t padding[1]; + uint8_t padding[5]; }; #ifdef __cplusplus diff --git a/tools/gnatcov/strings.adb b/tools/gnatcov/strings.adb index 3ee5ea3b0..b7c343fc2 100644 --- a/tools/gnatcov/strings.adb +++ b/tools/gnatcov/strings.adb @@ -92,6 +92,20 @@ package body Strings is and then S (S'Last - Length + 1 .. S'Last) = Suffix; end Has_Suffix; + -------------------- + -- To_String_Sets -- + -------------------- + + function To_String_Set (V : String_Vectors.Vector) return String_Sets.Set + is + Result : String_Sets.Set; + begin + for Elem of V loop + Result.Include (Elem); + end loop; + return Result; + end To_String_Set; + -------------------- -- Vector_To_List -- -------------------- @@ -163,7 +177,7 @@ package body Strings is procedure Match_Pattern_List (Patterns_List : String_Vectors.Vector; Strings_List : in out String_Vectors.Vector; - Patterns_Not_Covered : out String_Vectors.Vector) + Patterns_Not_Covered : in out String_Sets.Set) is use Ada.Characters.Handling; use Ada.Strings.Unbounded; @@ -173,10 +187,6 @@ package body Strings is Regexps : array (0 .. Pattern_Length - 1) of GNAT.Regexp.Regexp; -- List of regexps, one for each pattern in Patterns_List - Regexps_Covered : array (0 .. Pattern_Length - 1) of Boolean := - (others => False); - -- Record which Regexp of Regexps matched at least once - Matching_Strings : String_Vectors.Vector; -- Result holder for Strings_List @@ -202,9 +212,18 @@ package body Strings is end if; -- A unit matching this pattern was found; the pattern is - -- covered. - - Regexps_Covered (I) := True; + -- covered. Remove it from Patterns_Not_Covered. + + declare + Pattern : constant Unbounded_String := + Patterns_List.Element (I); + Cur : String_Sets.Cursor := + Patterns_Not_Covered.Find (Pattern); + begin + if String_Sets.Has_Element (Cur) then + Patterns_Not_Covered.Delete (Cur); + end if; + end; -- Continue the search in case other patterns match Str so that -- we can mark them as covered as well. @@ -228,12 +247,6 @@ package body Strings is Strings_List := Matching_Strings; - for I in Regexps_Covered'Range loop - if not Regexps_Covered (I) then - Patterns_Not_Covered.Append (Patterns_List.Element (I)); - end if; - end loop; - end Match_Pattern_List; end Strings; diff --git a/tools/gnatcov/strings.ads b/tools/gnatcov/strings.ads index 8d58d1e6f..a1c5df035 100644 --- a/tools/gnatcov/strings.ads +++ b/tools/gnatcov/strings.ads @@ -77,9 +77,11 @@ package Strings is "=" => Ada.Strings.Unbounded.Equal_Case_Insensitive); -- Case insensitive string set + function To_String_Set (V : String_Vectors.Vector) return String_Sets.Set; + -- Convert the given strings vector to a strings set + function Vector_To_List - (V : String_Vectors.Vector) - return String_List_Access; + (V : String_Vectors.Vector) return String_List_Access; -- The stream type below allows arbitrary objects to be streamed -- from/to an unbounded string, which is used as a buffer of bytes. @@ -87,11 +89,11 @@ package Strings is procedure Match_Pattern_List (Patterns_List : String_Vectors.Vector; Strings_List : in out String_Vectors.Vector; - Patterns_Not_Covered : out String_Vectors.Vector); + Patterns_Not_Covered : in out String_Sets.Set); -- Try matching each pattern of Patterns_List against each item of -- Strings_List (case-insensitively). Every item not matched is removed - -- from Strings_List. Also, each pattern that did not match at least once - -- is returned in Patterns_Not_Covered. + -- from Strings_List. Also, each pattern that matched at least once is + -- removed from Patterns_Not_Covered. type Unbounded_String_Stream (S : access Ada.Strings.Unbounded.Unbounded_String) diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 33c2b5901..25edace20 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -361,21 +361,24 @@ package body Subprocesses is Output_File : Mapped_File; Region : Mapped_Region; Str : Str_Access; - Str_Last : Natural := Last (Region); + Str_Last : Natural; begin Output_File := Open_Read (+Self.Process_Infos (Id).Output_File); Region := Read (Output_File); Str := Data (Region); + Str_Last := Last (Region); -- The finalization of Ada.Text_IO always emits a newline after a -- call to Put. To avoid redundant line breaks in this situation, -- do not pass that newline to Put and call New_Line instead. - if Str_Last > 0 and then Str (Str_Last) = ASCII.LF then - Str_Last := Str_Last - 1; + if Str_Last > 0 then + if Str (Str_Last) = ASCII.LF then + Str_Last := Str_Last - 1; + end if; + Put (Str (1 .. Str_Last)); + New_Line; end if; - Put (Str (1 .. Str_Last)); - New_Line; Free (Region); Close (Output_File); @@ -430,22 +433,31 @@ package body Subprocesses is Pool.Process_Infos (Id).Output_File := +Output_File; Pool.Process_Infos (Id).Origin_Command_Name := +Origin_Command_Name; Pool.Process_Infos (Id).Command := +Command; + if Output_File = "" then + + -- Redirect the output to a temporary file to avoid mangling + -- on the standard output. The dump of the output is done in + -- Wait_And_Finalize, through a later call to Run_Command, or + -- through the finalization of the process pool. + + Pool.Process_Infos (Id).Output_File := + +(Pool.Output_Dir.Directory_Name / "job-" + & Strings.Img (Id) & ".txt"); + Pool.Process_Infos (Id).Output_To_Stdout := True; + else + Pool.Process_Infos (Id).Output_To_Stdout := False; + end if; Pool.Handles (Id) := Run_Command (Command, Arguments, Origin_Command_Name, Environment, + +Pool.Process_Infos (Id).Output_File, - -- Redirect the output to a temporary file to avoid mangling on the - -- standard output. The dump of the output is done in - -- Wait_And_Finalize, through a later call to Run_Command, or - -- through the finalization of the process pool. + -- TODO???: there will be mangling on the stderr if stdout was + -- redirected to an output file. - (if Output_File = "" - then Pool.Output_Dir.Directory_Name / "job-" - & Strings.Img (Id) & ".txt" - else Output_File), Err_To_Out => Output_File = "", Out_To_Null => Out_To_Null, In_To_Null => In_To_Null, diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 6a81218ff..6d6d5b325 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -186,6 +186,47 @@ package body Switches is end return; end Load_Dump_Config; + -------------------- + -- Unparse_Config -- + -------------------- + + function Unparse_Config + (Dump_Config : Any_Dump_Config) return String_Vectors.Vector + is + use Ada.Strings.Unbounded; + Result : String_Vectors.Vector; + begin + Result.Append (+"--dump-trigger"); + case Dump_Config.Trigger is + when Manual => + Result.Append (+"manual"); + when At_Exit => + Result.Append (+"atexit"); + when Ravenscar_Task_Termination => + Result.Append (+"ravenscar-task-termination"); + when Main_End => + Result.Append (+"main-end"); + end case; + case Dump_Config.Channel is + when Binary_File => + Result.Append (+"--dump-channel=bin-file"); + if Dump_Config.Filename_Simple then + Result.Append (+"--dump-filename-simple"); + end if; + if Length (Dump_Config.Filename_Env_Var) /= 0 then + Result.Append + ("--dump-filename-env-var=" & Dump_Config.Filename_Env_Var); + end if; + if Length (Dump_Config.Filename_Prefix) /= 0 then + Result.Append + (+"--dump-filename-prefix=" & Dump_Config.Filename_Prefix); + end if; + when Base64_Standard_Output => + Result.Append (+"--dump-channel=base64-stdout"); + end case; + return Result; + end Unparse_Config; + ----------------- -- To_Language -- ----------------- diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 2c259b2af..67817c1f8 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -119,6 +119,10 @@ package Switches is SPARK_Compat : Boolean := False; -- When True, tune the instrumenter for maximum SPARK compatibility + Files_Of_Interest : String_Sets.Set; + -- Lower abstraction for files of interest, when the --files switch is + -- used. + type Separated_Source_Coverage_Type is (None, Routines, Instances); Separated_Source_Coverage : Separated_Source_Coverage_Type := None; @@ -158,6 +162,11 @@ package Switches is -- List of languages for which source files should be instrumented. -- Initialized during command line arguments parsing. + Builtin_Support : array (Src_Supported_Language) of Boolean := + (others => True); + -- Whether gnatcov supports the given language. Used when building gnatcov + -- without C instrumentation support. + ------------------------ -- Target information -- ------------------------ @@ -273,6 +282,11 @@ package Switches is -- Create the Any_Dump_Config value corresponding to Default_Dump_Config -- and the given --dump-* arguments for source trace dumping. + function Unparse_Config + (Dump_Config : Any_Dump_Config) return String_Vectors.Vector; + -- Return a suitable set of gnatcov command line switches that represent + -- the given dump config. + function Common_Switches (Cmd : Command_Line.Command_Type) return String_Vectors.Vector; -- Return the unparsed command line arguments supported by the given diff --git a/tools/gnatcov/traces_source.ads b/tools/gnatcov/traces_source.ads index 230867cd4..ad7fb5fd8 100644 --- a/tools/gnatcov/traces_source.ads +++ b/tools/gnatcov/traces_source.ads @@ -225,11 +225,6 @@ package Traces_Source is -- Length of the unit name / filename for the unit this trace entry -- describes. - Project_Name_Length : Unsigned_32; - -- For file-based languages, length of the project name this file - -- belongs to. For unit-based languages, the unit name is unique so this - -- piece of information is not needed (thus will be 0). - Statement_Bit_Count : Any_Bit_Count; Decision_Bit_Count : Any_Bit_Count; MCDC_Bit_Count : Any_Bit_Count; @@ -256,23 +251,22 @@ package Traces_Source is -- be able to interpret buffer bits from a source traces using buffer -- bit mappings from SID files. - Padding : String (1 .. 1); + Padding : String (1 .. 5); -- Padding used only to make the size of this trace entry header a -- multiple of 8 bytes. Must be zero. end record; for Trace_Entry_Header use record Unit_Name_Length at 0 range 0 .. 31; - Project_Name_Length at 4 range 0 .. 31; - Statement_Bit_Count at 8 range 0 .. 31; - Decision_Bit_Count at 12 range 0 .. 31; - MCDC_Bit_Count at 16 range 0 .. 31; - Language_Kind at 20 range 0 .. 7; - Unit_Part at 21 range 0 .. 7; - Bit_Buffer_Encoding at 22 range 0 .. 7; - Fingerprint at 23 range 0 .. 20 * 8 - 1; - Bit_Maps_Fingerprint at 43 range 0 .. 20 * 8 - 1; - Padding at 63 range 0 .. 7; + Statement_Bit_Count at 4 range 0 .. 31; + Decision_Bit_Count at 8 range 0 .. 31; + MCDC_Bit_Count at 12 range 0 .. 31; + Language_Kind at 16 range 0 .. 7; + Unit_Part at 17 range 0 .. 7; + Bit_Buffer_Encoding at 18 range 0 .. 7; + Fingerprint at 19 range 0 .. 20 * 8 - 1; + Bit_Maps_Fingerprint at 39 range 0 .. 20 * 8 - 1; + Padding at 59 range 0 .. 5 * 8 - 1; end record; for Trace_Entry_Header'Size use 64 * 8; From 9fbafdda73a5618dca1f93c5cd9d637f68c8ca77 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 19 Jun 2023 14:40:02 +0200 Subject: [PATCH 0335/1483] Escape backslashes in C strings Backslashes in C strings are escape characters, so they need to be escaped as they appear in e.g. full path of windows filename. --- tools/gnatcov/instrument-c.adb | 31 ++++++++++++++----------------- tools/gnatcov/instrument.adb | 4 ++-- tools/gnatcov/instrument.ads | 4 ++-- tools/gnatcov/paths.adb | 21 +++++++++++++++++++++ tools/gnatcov/paths.ads | 4 ++++ 5 files changed, 43 insertions(+), 21 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index cf64a2857..540d6e318 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -325,9 +325,6 @@ package body Instrument.C is procedure Run_Diagnostics (TU : Translation_Unit_T); -- Output clang diagnostics on the given translation unit - function Format_Str_Constant (Value : String) return String; - -- Return a gnatcov_rts_string literal corresponding to Value - function Format_Array_Init_Expr (Exprs : String_Vectors.Vector; Multiline : Boolean := False) return String; @@ -3412,9 +3409,10 @@ package body Instrument.C is Unit_Bits : Allocated_Bits renames UIC.Allocated_Bits.Constant_Reference (Buffers_Index); - CU : constant CU_Id := Buffers_CUs (Buffers_Index); - CU_Name : Compilation_Unit_Part renames + CU : constant CU_Id := Buffers_CUs (Buffers_Index); + CU_Name : Compilation_Unit_Part renames Buffers_CU_Names.Constant_Reference (Buffers_Index); + CU_Filename : constant String := +CU_Name.Filename; -- Symbol name for each kind of static buffer @@ -3470,8 +3468,14 @@ package body Instrument.C is -- refuse using STR to initialize a global data structure. To -- workaround this, emit a gnatcov_rtr_string literal -- ourselves. + -- + -- We also have to be careful to escape the backslashes inside + -- the string, which can appear e.g. in in windows full + -- filenames. - & " .unit_name = " & Format_Str_Constant (+CU_Name.Filename) + & " .unit_name = " + & " {""" & Escape_Backslashes (CU_Filename) & """, " + & CU_Filename'Length'Image & "}" & "," & ASCII.LF @@ -3657,7 +3661,8 @@ package body Instrument.C is File.Put_Line (Indent2 & Tag & ","); File.Put_Line (Indent2 & Simple & "),"); - File.Put_Line (Indent2 & "STR (""" & (+Main.Filename) + File.Put_Line (Indent2 & "STR (""" + & Escape_Backslashes (+Main.Filename) & """),"); File.Put_Line (Indent2 & "gnatcov_rts_time_to_uint64()" & ","); File.Put_Line (Indent2 & "STR ("""")"); @@ -3670,7 +3675,8 @@ package body Instrument.C is -- program name is the name of the main, and there is no way to -- get the current execution time. - File.Put_Line (Indent2 & "STR (""" & (+Main.Filename) & """),"); + File.Put_Line (Indent2 & "STR (""" + & Escape_Backslashes (+Main.Filename) & """),"); File.Put_Line (Indent2 & "0,"); File.Put_Line (Indent2 & "STR ("""")"); @@ -3869,15 +3875,6 @@ package body Instrument.C is Rew.Apply; end Auto_Dump_Buffers_In_Main; - ------------------------- - -- Format_Str_Constant -- - ------------------------- - - function Format_Str_Constant (Value : String) return String is - begin - return "{""" & Value & """," & Value'Length'Image & "}"; - end Format_Str_Constant; - ---------------- -- Format_Def -- ---------------- diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 27fb6e360..8b8836b00 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -29,8 +29,8 @@ with Interfaces; use Interfaces; with GNATCOLL.VFS; use GNATCOLL.VFS; -with Command_Line; use Command_Line; -with Hex_Images; use Hex_Images; +with Command_Line; use Command_Line; +with Hex_Images; use Hex_Images; package body Instrument is diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 46c5eb4b3..3485d2ae5 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -78,8 +78,8 @@ package Instrument is when File_Based_Language => Filename : US.Unbounded_String; - -- Fallback for file-based languages (like C). We will use the - -- simple filename for now. + -- Fallback for file-based languages (like C). We use the full + -- filename, for homonym resiliency. end case; end record; diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index b25ebaee1..77b4de80a 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -22,6 +22,8 @@ with Ada.Strings.Unbounded; with GNAT.OS_Lib; with GNAT.Regpat; +with Strings; use Strings; + package body Paths is On_Windows : constant Boolean := GNAT.OS_Lib.Directory_Separator = '\'; @@ -317,4 +319,23 @@ package body Paths is and then Path (Path'First + 1) = ':'; end Starts_With_Drive_Pattern; + ------------------------- + -- Escape_Windows_Path -- + ------------------------- + + function Escape_Backslashes (Str : String) return String + is + use Ada.Strings.Unbounded; + Result : Unbounded_String; + begin + for C of Str loop + if C = '\' then + Append (Result, "\\"); + else + Append (Result, C); + end if; + end loop; + return +Result; + end Escape_Backslashes; + end Paths; diff --git a/tools/gnatcov/paths.ads b/tools/gnatcov/paths.ads index a7bc5dc55..e66e7cdf1 100644 --- a/tools/gnatcov/paths.ads +++ b/tools/gnatcov/paths.ads @@ -64,6 +64,10 @@ package Paths is -- of the service, this one always matches both Windows or Unix file path -- flavors. + function Escape_Backslashes (Str : String) return String; + -- Escape every backslash in the given Str, to turn it into a C-compatible + -- string. + -- TODO??? Handle Unicode file names end Paths; From 106030307d8f71115df2b374505b63da26244865 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 19 Jun 2023 15:40:19 +0200 Subject: [PATCH 0336/1483] Fix typo --- tools/gnatcov/paths.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index 77b4de80a..36916a14b 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -139,7 +139,7 @@ package body Paths is case Pat (I) is - -- '*' cannot be directly transalted as '.*' as you do not expect + -- '*' cannot be directly translated as '.*' as you do not expect -- '*' to match on more than one directory level: -- you would expect 'src_*/' to match 'src_1/' and 'src_2/', but -- not 'src_1/subdir/'. From 3afa8fdbb3c8398fdd3d035c198115a9cde4a10d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 19 Jun 2023 15:40:30 +0200 Subject: [PATCH 0337/1483] Shorten filename for generated files We must now generate filenames under the gcvrt hierarchy instead of gnatcov_rts_buffers, as we now include the hash of the fullname in the compilation unit slugs. --- tools/gnatcov/instrument-ada_unit.adb | 2 +- tools/gnatcov/instrument-c.adb | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index e465b3721..9f735a29f 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3379,7 +3379,7 @@ package body Instrument.Ada_Unit is Old_Cond := Create_Call_Expr (RC, F_Name => Create_Identifier - (RC, To_Text (To_Ada (Sys_Prefix) & ".Std.Boolean")), + (RC, To_Text ("GNATcov_RTS.Std.Boolean")), F_Suffix => Create_Regular_Node (RC, Ada_Assoc_List, diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 540d6e318..1ab44ade9 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3594,7 +3594,7 @@ package body Instrument.C is -- Create the name of the helper unit Helper_Unit := - To_Symbol_Name (Sys_Buffers) + To_Symbol_Name (Sys_Prefix) & "_d_" & Instrumented_Unit_Slug (Main) & Prj.Body_Suffix (Instrumenter.Language); @@ -4009,7 +4009,7 @@ package body Instrument.C is Prj : Prj_Desc) is Base_Filename : constant String := - "gnatcov_rts_c-buffers-lists-" & (+Prj.Prj_Name); + "gcvrtc-" & (+Prj.Prj_Name); CU_Name_Body : constant String := Base_Filename & (+Prj.Body_Suffix From d379de6bf7c0577b05c5b6c537c79410f67b6ada Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 26 Jun 2023 16:35:08 +0200 Subject: [PATCH 0338/1483] Instrument: Consider all languages when enumerating sources A project that is not the root project may have more languages than those defined in the root project. As such, gnatcov should always check for sources of all the enabled languages when enumerating sources of interest. --- .../tests/86-subproj_lang/src_root/main.adb | 7 +++ .../86-subproj_lang/src_sub/calculations.c | 24 +++++++++ .../86-subproj_lang/src_sub/calculations.h | 3 ++ .../src_sub/procedure_under_test.adb | 25 ++++++++++ .../src_sub/procedure_under_test.ads | 20 ++++++++ testsuite/tests/86-subproj_lang/test.py | 49 +++++++++++++++++++ tools/gnatcov/instrument-projects.adb | 4 +- 7 files changed, 129 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/86-subproj_lang/src_root/main.adb create mode 100644 testsuite/tests/86-subproj_lang/src_sub/calculations.c create mode 100644 testsuite/tests/86-subproj_lang/src_sub/calculations.h create mode 100644 testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.adb create mode 100644 testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.ads create mode 100644 testsuite/tests/86-subproj_lang/test.py diff --git a/testsuite/tests/86-subproj_lang/src_root/main.adb b/testsuite/tests/86-subproj_lang/src_root/main.adb new file mode 100644 index 000000000..f70f97420 --- /dev/null +++ b/testsuite/tests/86-subproj_lang/src_root/main.adb @@ -0,0 +1,7 @@ +with Procedure_Under_Test; use Procedure_Under_Test; + +procedure Main is +begin + Test (Control => 1, In_A => 1, In_B => 2); + Test (Control => -11, In_A => 1, In_B => 2); +end Main; diff --git a/testsuite/tests/86-subproj_lang/src_sub/calculations.c b/testsuite/tests/86-subproj_lang/src_sub/calculations.c new file mode 100644 index 000000000..b9b039b8a --- /dev/null +++ b/testsuite/tests/86-subproj_lang/src_sub/calculations.c @@ -0,0 +1,24 @@ +#include "calculations.h" + +// simple function performing some basic math operations +// which allows a division by 0 +int +calculations_problematic (int a, int b) +{ + int temp = 0; + temp = a * b; + temp = temp + a / b; + return temp; +} + +// same as previous function but prohibits the division +// by zero +int +calculations (int a, int b) +{ + int temp = 0; + temp = a * b; + if (b != 0) + temp = temp + a / b; + return temp; +} diff --git a/testsuite/tests/86-subproj_lang/src_sub/calculations.h b/testsuite/tests/86-subproj_lang/src_sub/calculations.h new file mode 100644 index 000000000..fe6f07dff --- /dev/null +++ b/testsuite/tests/86-subproj_lang/src_sub/calculations.h @@ -0,0 +1,3 @@ +int calculations (int a, int b); + +int calculations_problematic (int a, int b); diff --git a/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.adb b/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.adb new file mode 100644 index 000000000..043744514 --- /dev/null +++ b/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.adb @@ -0,0 +1,25 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; + +package body Procedure_Under_Test is + + procedure Test + (Control : Integer; + In_A : Integer; + In_B : Integer) + is + Result : Integer := 0; + begin + + if Control < 0 then + Result := Calculations_Problematic (In_A, In_B); + else + Result := Calculations (In_A, In_B); + end if; + + Put_Line (Result'Image); + + end Test; + +end Procedure_Under_Test; diff --git a/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.ads b/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.ads new file mode 100644 index 000000000..f37366170 --- /dev/null +++ b/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.ads @@ -0,0 +1,20 @@ +pragma Ada_2012; + +package Procedure_Under_Test is + + function Calculations (A : Integer; B : Integer) return Integer + with Import => True, + Convention => C, + External_Name => "calculations"; + + function Calculations_Problematic (A : Integer; B : Integer) return Integer + with Import => True, + Convention => C, + External_Name => "calculations_problematic"; + + procedure Test + (Control : Integer; + In_A : Integer; + In_B : Integer); + +end Procedure_Under_Test; diff --git a/testsuite/tests/86-subproj_lang/test.py b/testsuite/tests/86-subproj_lang/test.py new file mode 100644 index 000000000..89709c9ed --- /dev/null +++ b/testsuite/tests/86-subproj_lang/test.py @@ -0,0 +1,49 @@ +""" +Test that sources of another language not present in the root project are still +considered as sources of interest. This was not the case with the first version +of the parallelized instrumentation. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Sub has both Ada and C as languages, whereas Root only declares Ada sources. +# Gnatcov should nevertheless instrument C sources in Sub, as long as the +# instrumentation languages are not explicitly restricted. +prj_sub = gprfor( + prjid="sub", + srcdirs=["../src_sub"], + langs=["Ada", "C"], + mains=None, +) +prj_root = gprfor( + prjid="root", + srcdirs=["../src_root"], + langs=["Ada"], + mains=["main.adb"], + deps=["sub.gpr"], +) + +# Build and produce a coverage report for the test project. Only compute +# coverage for the C unit as this is the one that may not be instrumented. +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj_root, units=["calculations.c"]), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "*.xcov", + {"calculations.c.xcov": {"+": {8, 9, 10, 11, 19, 20, 21, 22, 23}}}, + "xcov", +) + +thistest.result() diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 98c1b9139..3531b9ca5 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -800,9 +800,7 @@ begin -- First get the list of all units of interest for Lang in Src_Supported_Language loop - if Src_Enabled_Languages (Lang) - and then Root_Project_Info.Project.Has_Language (Image (Lang)) - then + if Src_Enabled_Languages (Lang) then Project.Enumerate_Sources (Add_Instrumented_Unit'Access, Lang, Include_Stubs => True); end if; From 9dc536d853a403f738ae0845e8610ba46a7d885d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 16 Jun 2023 16:56:06 +0200 Subject: [PATCH 0339/1483] Fix dependency in generated last chance handler To have shorter filenames for files generated by the instrumentation process (as we now include the hash of the fullname, for buffer files of file-based languages), we now generate them as child units of the GCVRT unit. --- testsuite/SCOV/instr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 63c2269a8..e19e2ab05 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -205,7 +205,7 @@ def add_dumper_lch_hook(project, obj_dir, subdirs, main_unit): # such unit per main. See instrument-common.ads to know more about the slug # computation. main_unit_slug = main_unit.replace('z', 'zz') - auto_dump_unit = 'GNATcov_RTS.Buffers.DB_{}'.format(main_unit_slug) + auto_dump_unit = 'GCVRT.DB_{}'.format(main_unit_slug) handler_unit = "Last_Chance_Dumper"; def filename(prefix, ext): From 2d396a4106007785d5b565bd4d088cab33817b61 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 16 Jun 2023 15:52:48 +0200 Subject: [PATCH 0340/1483] Fix use after free The UIC.Current_Scope_Entity is freed in Exit_Scope, meaning that references (through a prior renaming declaration) to UIC.Current_Scope_Entity.Parent will become invalid. --- tools/gnatcov/instrument-ada_unit.adb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 9f735a29f..20cfd0801 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6490,8 +6490,10 @@ package body Instrument.Ada_Unit is procedure Exit_Scope (UIC : in out Ada_Unit_Inst_Context) is - Parent : Scope_Entity_Acc renames UIC.Current_Scope_Entity.Parent; - Scope : Scope_Entity_Acc renames UIC.Current_Scope_Entity; + Parent : constant Scope_Entity_Acc := UIC.Current_Scope_Entity.Parent; + -- Latch the parent value before UIC.Current_Scope_Entity is freed + + Scope : Scope_Entity_Acc renames UIC.Current_Scope_Entity; begin -- Update the last SCO for this scope entity From ef12d745cc41de3a8d820d962e8649591dca303c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 16 Jun 2023 15:54:48 +0200 Subject: [PATCH 0341/1483] Fix trace name prefix under windows With the recent introduction of the parallelized instrumentation support, trace names lost their executable extension part. Reinstantiate. --- tools/gnatcov/instrument-projects.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 3531b9ca5..6fa2afc9c 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -1118,7 +1118,7 @@ begin if Length (Dump_Config.Filename_Prefix) = 0 then Explicit_Dump_Config.Filename_Prefix := +(+Root_Project_Info.Project.Executable_Name - (Main.File.Full_Name)); + (Main.File.Full_Name, Include_Suffix => True)); end if; end if; From e469383aef27fc8bfdfcae60f3c206a2b2834679 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 26 Jun 2023 12:23:17 +0200 Subject: [PATCH 0342/1483] Remove dead code The dead code was responsible for a gnatcov crash when there was a multi-unit source in the project closure. Add a test for this as this was noticed in the gpr2 testsuite. --- .../instr-cov/multi_unit_source/src/code.ada | 28 +++++++++ .../instr-cov/multi_unit_source/src/main.adb | 6 ++ .../instr-cov/multi_unit_source/src/pck.adb | 14 +++++ .../instr-cov/multi_unit_source/src/pck.ads | 3 + .../tests/instr-cov/multi_unit_source/test.py | 61 +++++++++++++++++++ .../gnatcov/instrument-ada_unit_provider.adb | 2 - .../gnatcov/instrument-ada_unit_provider.ads | 3 - 7 files changed, 112 insertions(+), 5 deletions(-) create mode 100644 testsuite/tests/instr-cov/multi_unit_source/src/code.ada create mode 100644 testsuite/tests/instr-cov/multi_unit_source/src/main.adb create mode 100644 testsuite/tests/instr-cov/multi_unit_source/src/pck.adb create mode 100644 testsuite/tests/instr-cov/multi_unit_source/src/pck.ads create mode 100644 testsuite/tests/instr-cov/multi_unit_source/test.py diff --git a/testsuite/tests/instr-cov/multi_unit_source/src/code.ada b/testsuite/tests/instr-cov/multi_unit_source/src/code.ada new file mode 100644 index 000000000..e419b4817 --- /dev/null +++ b/testsuite/tests/instr-cov/multi_unit_source/src/code.ada @@ -0,0 +1,28 @@ +package U1 is + A : Integer := 1; +end U1; + +package U2 is + B : Integer := 2; + procedure Increment; + procedure Decrement; +end U2; + +package body U2 is + procedure Increment is + begin + B := B + 1; + end Increment; + procedure Decrement is + begin + B := B - 1; + end Decrement; +end U2; + +with U1, U2; +procedure U3 is +begin + U2.Increment; + U1.A := U1.A + U2.B; + U2.Decrement; +end U3; diff --git a/testsuite/tests/instr-cov/multi_unit_source/src/main.adb b/testsuite/tests/instr-cov/multi_unit_source/src/main.adb new file mode 100644 index 000000000..a3dacf4ab --- /dev/null +++ b/testsuite/tests/instr-cov/multi_unit_source/src/main.adb @@ -0,0 +1,6 @@ +with Pck; + +procedure Main is +begin + Pck.Call; +end Main; diff --git a/testsuite/tests/instr-cov/multi_unit_source/src/pck.adb b/testsuite/tests/instr-cov/multi_unit_source/src/pck.adb new file mode 100644 index 000000000..c0e8e6ac1 --- /dev/null +++ b/testsuite/tests/instr-cov/multi_unit_source/src/pck.adb @@ -0,0 +1,14 @@ +with U1; +with U2; +with U3; + +package body Pck is + + procedure Call is + begin + U2.Increment; + U1.A := U1.A + U2.B; + U3; + end Call; + +end Pck; diff --git a/testsuite/tests/instr-cov/multi_unit_source/src/pck.ads b/testsuite/tests/instr-cov/multi_unit_source/src/pck.ads new file mode 100644 index 000000000..9616e13ad --- /dev/null +++ b/testsuite/tests/instr-cov/multi_unit_source/src/pck.ads @@ -0,0 +1,3 @@ +package Pck is + procedure Call; +end Pck; diff --git a/testsuite/tests/instr-cov/multi_unit_source/test.py b/testsuite/tests/instr-cov/multi_unit_source/test.py new file mode 100644 index 000000000..180dc04bf --- /dev/null +++ b/testsuite/tests/instr-cov/multi_unit_source/test.py @@ -0,0 +1,61 @@ +""" +Check that the instrumentation of a project containing a multi-unit source does +not crash. +""" + +import os +import os.path + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +extra = """ + package Naming is + for Spec ("U1") use "code.ada" at 1; + for Spec ("U2") use "code.ada" at 2; + for Body ("U2") use "code.ada" at 3; + for Body ("U3") use "code.ada" at 4; + end Naming; +""" + +mkdir("obj") +prj = gprfor(srcdirs=[os.path.join("..", "src")], mains=["main.adb"], extra=extra) + +# Check that the instrumentation crashes and does not leave stale +# instrumentation artefacts when trying to instrument the multi-unit source. +xcov_instrument(gprsw=GPRswitches(prj), covlevel="stmt", register_failure=False) +thistest.fail_if_no_match( + "gnatcov instrument output", + ( + ".*gnatcov.*: instrumentation failed for .*code.ada\n" + ".*gnatcov.*: source files containing multiple compilation units are not" + " supported" + ), + contents_of("instrument.log"), +) +thistest.fail_if( + os.path.exists(os.path.join("obj", "gen-gnatcov-instr", "main.adb")), + "unexpected instrumented files", +) + +# Now check that everything runs fine when we exclude the culprit multi-unit +# source from the coverage analysis. +build_run_and_coverage( + gprsw=GPRswitches(prj), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--units=pck"], + extra_coverage_args=["--units=pck", "-axcov"], +) + +check_xcov_reports("*.xcov", {"pck.adb.xcov": {"+": {9, 10, 11}}}, "obj") + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit_provider.adb b/tools/gnatcov/instrument-ada_unit_provider.adb index 493e5444c..283ecb323 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.adb +++ b/tools/gnatcov/instrument-ada_unit_provider.adb @@ -63,8 +63,6 @@ package body Instrument.Ada_Unit_Provider is Get_Line (Dependencies_File); begin Provider.Unit_Map.Insert (To_Lower (Unit_Name), File_Fullname); - Provider.Filename_Map.Insert - (File_Fullname, To_Lower (Unit_Name)); end; end loop; exception diff --git a/tools/gnatcov/instrument-ada_unit_provider.ads b/tools/gnatcov/instrument-ada_unit_provider.ads index fd851e9a3..e320e105a 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.ads +++ b/tools/gnatcov/instrument-ada_unit_provider.ads @@ -86,9 +86,6 @@ private Unit_Map : String_Maps.Map; -- Mapping from unit name to file fullnames - Filename_Map : String_Maps.Map; - -- Mapping from file fullnames to unit names - Runtime_Files : String_Maps.Map; -- Mapping from a runtime file basename to its fullname From e41bb7b818c5fdf736c47349b65de66cb25b327c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 29 Jun 2023 12:38:09 +0200 Subject: [PATCH 0343/1483] Clean the instrumentation directories if exception arose We can't leave the instrumentation directories in a partial instrumentation state, as there is no guarantee the build will work in that case. If an exception was raised in the instrumentation process, remove all of the generated instrumentation artifacts. --- tools/gnatcov/instrument-projects.adb | 38 ++++++++++++++++++++++++++- tools/gnatcov/outputs.adb | 5 ---- tools/gnatcov/outputs.ads | 6 ++++- 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 6fa2afc9c..c80b179ea 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -22,12 +22,15 @@ with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Containers.Indefinite_Ordered_Sets; with Ada.Directories; with Ada.Exceptions; +with Ada.IO_Exceptions; with Ada.Strings; with Ada.Strings.Fixed; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Hash; with Ada.Unchecked_Deallocation; +with GNAT.Exception_Actions; + with Interfaces; use Interfaces; with GNAT.OS_Lib; @@ -38,6 +41,7 @@ with GNATCOLL.JSON; use GNATCOLL.JSON; with GNATCOLL.VFS; with GNATCOLL.Projects.Aux; use GNATCOLL.Projects.Aux; +with Binary_Files; with Command_Line; use Command_Line; with Files_Table; with Hex_Images; use Hex_Images; @@ -236,6 +240,10 @@ is (Project : GPR.Project_Type; Source_File : GPR.File_Info); -- Add this source file to the list of units to instrument + procedure Clean_And_Print (Exc : Ada.Exceptions.Exception_Occurrence); + -- Clean the instrumentation directories and print any relevant information + -- regarding the instrumentation context. + ----------------------- -- Load_From_Project -- ----------------------- @@ -752,6 +760,16 @@ is end if; end Add_Instrumented_Unit; + --------------------- + -- Clean_And_Print -- + --------------------- + + procedure Clean_And_Print (Exc : Ada.Exceptions.Exception_Occurrence) is + begin + Clean_Objdirs; + Outputs.Print_Internal_Error (Exc); + end Clean_And_Print; + Mains_To_Instrument : array (Src_Supported_Language) of Main_To_Instrument_Vectors.Vector; -- For each supported language, list of mains to instrument. Note that @@ -887,6 +905,16 @@ begin Prepare_Output_Dirs (IC); + -- Clean the instrumentation directories if the process terminated with + -- an exception. Note that we can't do this with a handler, as the + -- Clean_And_Print hook must be executed before local context objects at + -- the raise point are finalized. Using the + -- Register_Global_Unhandled_Action, the hook will be triggered before + -- local controlled objects are finalized. + + GNAT.Exception_Actions.Register_Global_Unhandled_Action + (Clean_And_Print'Unrestricted_Access); + -- Record in a file all of the files and headers of interest. We separate -- both as we do not expect to have coverage buffers for header files (the -- coverage data is in including bodies' coverage buffers). @@ -1219,5 +1247,13 @@ begin J.Set_Field ("dump-channel", Image (Dump_Config.Channel)); Write (Filename, J, Compact => False); end; - +exception + -- We need to clear the object directories in case an exception (caught by + -- a global handler and not dealt with by the registered hook) was raised. + + when Binary_Files.Error + | Ada.IO_Exceptions.Name_Error + | Outputs.Xcov_Exit_Exc => + Clean_Objdirs; + raise; end Instrument.Projects; diff --git a/tools/gnatcov/outputs.adb b/tools/gnatcov/outputs.adb index db6e2c7b6..f6de07687 100644 --- a/tools/gnatcov/outputs.adb +++ b/tools/gnatcov/outputs.adb @@ -20,7 +20,6 @@ with Ada.Characters.Handling; with Ada.Command_Line; use Ada.Command_Line; with Ada.Directories; with Ada.Environment_Variables; use Ada.Environment_Variables; -with Ada.Exceptions; use Ada.Exceptions; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with GNAT.Exception_Actions; @@ -73,10 +72,6 @@ package body Outputs is -- Linked list (through Context_Entry.Next) of already allocated and -- available Context_Entry records. - procedure Print_Internal_Error (Exc : Ada.Exceptions.Exception_Occurrence); - -- Display the given internal error along with the known context (see the - -- previous procedures). - ------------------------- -- Create_Output_File -- ------------------------- diff --git a/tools/gnatcov/outputs.ads b/tools/gnatcov/outputs.ads index 967c3073f..8fd9c654c 100644 --- a/tools/gnatcov/outputs.ads +++ b/tools/gnatcov/outputs.ads @@ -20,7 +20,8 @@ -- (error messages and annotated reports). private with Ada.Finalization; -with Ada.Text_IO; use Ada.Text_IO; +with Ada.Exceptions; use Ada.Exceptions; +with Ada.Text_IO; use Ada.Text_IO; with Types; use Types; @@ -90,6 +91,9 @@ package Outputs is -- ... process foobar... -- end; + procedure Print_Internal_Error (Exc : Ada.Exceptions.Exception_Occurrence); + -- Display the given internal error along with the known context (see the + -- previous procedures). type Any_Internal_Error_Trigger is ( None, -- Do not create an artificial internal error From 55d09d1544463200e43cba517f663cf59e6058b4 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 5 Jul 2023 11:01:33 +0200 Subject: [PATCH 0344/1483] Fix regressions for 5.04a1 --- .../src_sub/procedure_under_test.adb | 4 +--- .../src_sub/procedure_under_test.ads | 20 +++++++++---------- testsuite/tests/instr-cov/gpr-complex/test.py | 8 +++++--- .../instr-cov/multi_unit_source/test.opt | 1 + 4 files changed, 17 insertions(+), 16 deletions(-) create mode 100644 testsuite/tests/instr-cov/multi_unit_source/test.opt diff --git a/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.adb b/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.adb index 043744514..0621c07be 100644 --- a/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.adb +++ b/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.adb @@ -1,5 +1,3 @@ -pragma Ada_2012; - with Ada.Text_IO; use Ada.Text_IO; package body Procedure_Under_Test is @@ -18,7 +16,7 @@ package body Procedure_Under_Test is Result := Calculations (In_A, In_B); end if; - Put_Line (Result'Image); + Put_Line (Integer'Image (Result)); end Test; diff --git a/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.ads b/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.ads index f37366170..5595de1a6 100644 --- a/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.ads +++ b/testsuite/tests/86-subproj_lang/src_sub/procedure_under_test.ads @@ -1,16 +1,16 @@ -pragma Ada_2012; - package Procedure_Under_Test is - function Calculations (A : Integer; B : Integer) return Integer - with Import => True, - Convention => C, - External_Name => "calculations"; + function Calculations (A : Integer; B : Integer) return Integer; + pragma Import + (Convention => C, + Entity => Calculations, + External_Name => "calculations"); - function Calculations_Problematic (A : Integer; B : Integer) return Integer - with Import => True, - Convention => C, - External_Name => "calculations_problematic"; + function Calculations_Problematic (A : Integer; B : Integer) return Integer; + pragma Import + (Convention => C, + Entity => Calculations_Problematic, + External_Name => "calculations_problematic"); procedure Test (Control : Integer; diff --git a/testsuite/tests/instr-cov/gpr-complex/test.py b/testsuite/tests/instr-cov/gpr-complex/test.py index 235241be6..1dd1f488c 100644 --- a/testsuite/tests/instr-cov/gpr-complex/test.py +++ b/testsuite/tests/instr-cov/gpr-complex/test.py @@ -37,14 +37,16 @@ ], ) -# Add the newly installed library to gprbuild's project lookup path +# Add the newly installed library to gprbuild's project lookup path. Use the +# ADA_PROJECT_PATH environment variable to be compatible with the 5.04 +# toolchain. gpr_install_dir = os.path.join(install_dir, "share", "gpr") -old_path = os.environ.get("GPR_PROJECT_PATH", "") +old_path = os.environ.get("ADA_PROJECT_PATH", "") if old_path: new_path = "{}{}{}".format(gpr_install_dir, os.path.pathsep, old_path) else: new_path = gpr_install_dir -os.environ["GPR_PROJECT_PATH"] = new_path +os.environ["ADA_PROJECT_PATH"] = new_path def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): diff --git a/testsuite/tests/instr-cov/multi_unit_source/test.opt b/testsuite/tests/instr-cov/multi_unit_source/test.opt new file mode 100644 index 000000000..e9bca8553 --- /dev/null +++ b/testsuite/tests/instr-cov/multi_unit_source/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD multi-unit sources not supported with GNAT 5.04 From 834fb95077c893bede8ecc24ef6c322b468f46f2 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 16 Mar 2023 17:34:21 +0100 Subject: [PATCH 0345/1483] Instrument.C: output clang diagnostics If the parsing failed because of an error in the user code, we should emit the diagnostics reported by clang to let the user know that coverage analysis may be incomplete. As we preprocess code with another compiler configuration than the clang one, we may have compiler-specific code, notably in system-headers, so we also need to filter out a lot of messages to avoid issuing spurious warning messages. The heuristic picked is to only keep diagnostics whose presumed location file is a file of interest (belonging to the project). This could be revisited if there are still too many false positives (as we will have false positives raised on compiler-specific user code). --- testsuite/tests/C++/28-default-values/foo.c | 9 +++ .../tests/C++/28-default-values/test.cpp | 11 ++++ testsuite/tests/C++/28-default-values/test.py | 31 ++++++++++ tools/gnatcov/instrument-c.adb | 56 +++++++++++-------- tools/gnatcov/instrument-c.ads | 5 +- 5 files changed, 87 insertions(+), 25 deletions(-) create mode 100644 testsuite/tests/C++/28-default-values/foo.c create mode 100644 testsuite/tests/C++/28-default-values/test.cpp create mode 100644 testsuite/tests/C++/28-default-values/test.py diff --git a/testsuite/tests/C++/28-default-values/foo.c b/testsuite/tests/C++/28-default-values/foo.c new file mode 100644 index 000000000..60d82ec5e --- /dev/null +++ b/testsuite/tests/C++/28-default-values/foo.c @@ -0,0 +1,9 @@ +// stdlib comes with a bunch of compiler specific code, when included in a +// GNU source context. Check that its inclusion does not result in gnatcov +// instrument emitting spurious diagnostics. +#define _GNU_SOURCE 1 +#include + +int bar(){ + return 0; +} diff --git a/testsuite/tests/C++/28-default-values/test.cpp b/testsuite/tests/C++/28-default-values/test.cpp new file mode 100644 index 000000000..8dd25d04b --- /dev/null +++ b/testsuite/tests/C++/28-default-values/test.cpp @@ -0,0 +1,11 @@ +namespace bar { + bool b = true; + bool foo (bool b = b) { + return b; + } +} + +int main(){ + bar::foo(); + return 0; +} diff --git a/testsuite/tests/C++/28-default-values/test.py b/testsuite/tests/C++/28-default-values/test.py new file mode 100644 index 000000000..8a35f136b --- /dev/null +++ b/testsuite/tests/C++/28-default-values/test.py @@ -0,0 +1,31 @@ +""" +Check that we output clang diagnostics on source of interests only. +""" + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import thistest, gprfor +from SUITE.gprutils import GPRswitches + +Wdir("tmp_") + +mkdir("obj") + +output = "instr.log" +xcov_instrument( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], + mains=["test.cpp"])), + covlevel="stmt", + out=output, +) + +thistest.fail_if_no_match( + "'gnatcov instrument' output", + ".* error: default argument references parameter 'b'", + contents_of(output).strip(), +) + + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 1ab44ade9..3775daaaa 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -322,8 +322,15 @@ package body Instrument.C is -- beforehand. Otherwise, generate a preprocessed version of it in -- Info.Output_Dir and start a rewriting session on the latter. - procedure Run_Diagnostics (TU : Translation_Unit_T); - -- Output clang diagnostics on the given translation unit + procedure Run_Diagnostics (UIC : in out C_Unit_Inst_Context); + -- Output clang diagnostics on the given translation unit UIC.TU. Note + -- that we aggressively filter out diagnostics whose presumed location + -- file is not a file of interest. Indeed, system headers have a lot + -- of compiler-specific code, which means that some type / symbol names + -- will not be resolved by clang, as we preprocess the code with another + -- compiler configuration (e.g. gcc). This also means that compiler- + -- specific user code will issue false positives. TODO???: is it that + -- uncommon of an occurrence? function Format_Array_Init_Expr (Exprs : String_Vectors.Vector; @@ -1776,27 +1783,30 @@ package body Instrument.C is -- Run_Diagnostics -- --------------------- - procedure Run_Diagnostics (TU : Translation_Unit_T) is - Num_Diag : constant unsigned := Get_Num_Diagnostics (TU); + procedure Run_Diagnostics (UIC : in out C_Unit_Inst_Context) + is + Num_Diag : constant unsigned := Get_Num_Diagnostics (UIC.TU); begin for I in 1 .. Num_Diag loop declare Diag : constant Diagnostic_T := - Get_Diagnostic (Unit => TU, Index => I - 1); + Get_Diagnostic (Unit => UIC.TU, Index => I - 1); Severity : constant Diagnostic_Severity_T := Get_Diagnostic_Severity (Diag); - Str : constant String := - Format_Diagnostic - (Diagnostic => Diag, - Options => Default_Diagnostic_Display_Options); begin - case Severity is - when Diagnostic_Error | Diagnostic_Fatal => - Outputs.Warning_Or_Error - ("Error when parsing the file " & Str); - when others => - null; - end case; + if Is_Source_Of_Interest (UIC, Get_Diagnostic_Location (Diag)) + then + case Severity is + when Diagnostic_Error | Diagnostic_Fatal => + Outputs.Warning_Or_Error + ("Error when parsing the file " + & Format_Diagnostic + (Diagnostic => Diag, + Options => Default_Diagnostic_Display_Options)); + when others => + null; + end case; + end if; end; end loop; end Run_Diagnostics; @@ -2126,7 +2136,9 @@ package body Instrument.C is -- statement source location range. begin - if Is_Null (N) or else not Is_Source_Of_Interest (UIC, N) then + if Is_Null (N) + or else not Is_Source_Of_Interest (UIC, Get_Cursor_Location (N)) + then return; end if; @@ -2319,7 +2331,7 @@ package body Instrument.C is -- Only traverse the function declarations that belong to a unit of -- interest. - if Is_Source_Of_Interest (UIC, N) then + if Is_Source_Of_Interest (UIC, Get_Cursor_Location (N)) then case Kind (N) is @@ -2692,9 +2704,6 @@ package body Instrument.C is & " options is passed to gnatcov instrument"); raise Xcov_Exit_Exc; end if; - if Verbose then - Run_Diagnostics (Self.TU); - end if; Free (C_Args); end; Self.Rewriter := CX_Rewriter_Create (Self.TU); @@ -2800,6 +2809,7 @@ package body Instrument.C is Options => Translation_Unit_Keep_Going); Free (C_Args); end; + Run_Diagnostics (UIC); Traverse_Declarations (UIC => UIC, L => Get_Children (Get_Translation_Unit_Cursor (UIC.TU))); @@ -4187,14 +4197,14 @@ package body Instrument.C is --------------------------- function Is_Source_Of_Interest - (UIC : in out C_Unit_Inst_Context; N : Cursor_T) return Boolean + (UIC : in out C_Unit_Inst_Context; + Loc : Source_Location_T) return Boolean is -- Determine the file from which N originates C_File : aliased String_T; Line : aliased unsigned; Column : aliased unsigned; - Loc : constant Source_Location_T := Get_Cursor_Location (N); File : Unbounded_String; begin Get_Presumed_Location (Location => Loc, diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index f9d89c4c5..e32946071 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -328,8 +328,9 @@ package Instrument.C is -- Helper object to instrument a source file function Is_Source_Of_Interest - (UIC : in out C_Unit_Inst_Context; N : Cursor_T) return Boolean; - -- Track the source file from which N originates in + (UIC : in out C_Unit_Inst_Context; + Loc : Source_Location_T) return Boolean; + -- Track the source file from which Locs originates in -- UIC.Sources_Of_Interest. Return whether this source file is a source of -- interest. From 9a439731b44d2cbc796c6a61289129b0817984e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 5 Jul 2023 12:01:20 +0200 Subject: [PATCH 0346/1483] Instrument: Use hashes instead of slugs for buffer unit names This helps reduce the overall length of the buffer unit names, which could previously be up to three times the length of the original unit name. This was a problem under Windows where the length of the paths is usually limited to 250 characters. --- ..._TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.c | 7 ++ ..._TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.h | 6 ++ testsuite/tests/92-long_slugs/main.c | 9 +++ testsuite/tests/92-long_slugs/test.py | 79 +++++++++++++++++++ testsuite/tests/instr-cov/ext_gpr/test.py | 22 +++--- tools/gnatcov/command_line.ads | 11 ++- tools/gnatcov/gnatcov_bits_specific.adb | 1 + tools/gnatcov/instrument-ada_unit.adb | 3 +- tools/gnatcov/instrument.adb | 44 ++++++++--- tools/gnatcov/instrument.ads | 19 +++-- tools/gnatcov/switches.ads | 4 + 11 files changed, 175 insertions(+), 30 deletions(-) create mode 100644 testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.c create mode 100644 testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.h create mode 100644 testsuite/tests/92-long_slugs/main.c create mode 100644 testsuite/tests/92-long_slugs/test.py diff --git a/testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.c b/testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.c new file mode 100644 index 000000000..0e161b489 --- /dev/null +++ b/testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.c @@ -0,0 +1,7 @@ +#include "OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.h" + +int +ident (int x) +{ + return x; +} diff --git a/testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.h b/testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.h new file mode 100644 index 000000000..bfb193971 --- /dev/null +++ b/testsuite/tests/92-long_slugs/OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.h @@ -0,0 +1,6 @@ +#ifndef __OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT__ +#define __OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT__ + +int ident (int x); + +#endif diff --git a/testsuite/tests/92-long_slugs/main.c b/testsuite/tests/92-long_slugs/main.c new file mode 100644 index 000000000..792aaec55 --- /dev/null +++ b/testsuite/tests/92-long_slugs/main.c @@ -0,0 +1,9 @@ +#include "OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.h" + +#include + +int +main () +{ + assert (ident (3) == 3); +} diff --git a/testsuite/tests/92-long_slugs/test.py b/testsuite/tests/92-long_slugs/test.py new file mode 100644 index 000000000..6c1734732 --- /dev/null +++ b/testsuite/tests/92-long_slugs/test.py @@ -0,0 +1,79 @@ +""" +Check that gnatcov-generated units have reasonably short filenames. +Gnatcov used to generate slugs that could take up to three characters to +represent a single one for the original unit name, thus generating overly long +unit names. +""" + +from e3.fs import mkdir + +from SCOV.minicheck import ( + build_run_and_coverage, + check_xcov_reports, + xcov_instrument, +) +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor + +Wdir("tmp_") + +prj_switches = GPRswitches(gprfor(srcdirs=[".."], mains=["main.c"])) + +# Suppress "creating output path ..." messages from the log +mkdir("obj") + +# First, check that using the legacy slugs produces paths that exceed the path +# limit. + +log = "slug_instr.log" +p = xcov_instrument( + gprsw=prj_switches, + covlevel="stmt", + extra_args=["--full-slugs"], + register_failure=False, + out=log, +) +thistest.fail_if(p.status == 0) + +# The error message for exceeding the path limit isn't the same on Windows +# and on linux. + +thistest.fail_if_no_match( + what="Missing or unexpected error message", + regexp=( + r'.*/gnatcov\.exe: invalid path name "gcvrt_b_z.*' + if "windows" in thistest.env.host.platform + else r".*/gnatcov: cannot open .*/tests" + r"/92-long_slugs/tmp_/obj/gen-gnatcov-instr/gcvrt_b_z.*\.c" + ), + actual=contents_of(log).replace("\\", "/"), +) + +# Now check that the buffer units with hashes in their names work ok +build_run_and_coverage( + gprsw=prj_switches, + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], +) + +unit_name = ( + "OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE" + "_TO_AVOID_PATH_NAME_LIMIT" +) + +# We normalize the case of files on Windows, as such the report files won't +# have the same case as the original filename. + +check_xcov_reports( + "*.xcov", + { + "main.c.xcov": {"+": {8}}, + (unit_name.lower() if "windows" in thistest.env.host.platform else unit_name) + + ".c.xcov": {"+": {6}}, + }, + "obj", +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/ext_gpr/test.py b/testsuite/tests/instr-cov/ext_gpr/test.py index b76c9b08c..183296675 100644 --- a/testsuite/tests/instr-cov/ext_gpr/test.py +++ b/testsuite/tests/instr-cov/ext_gpr/test.py @@ -22,19 +22,19 @@ # Check that directories for instrumented sources are all empty except for the # ultimate extending project, which should contain all instrumented sources. -thistest.fail_if_not_equal( +thistest.fail_if_no_match( "instrumented directories", "\n".join([ - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bpkg.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bpkg1.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bpkg2.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-p_ext2.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-ppkg.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-ppkg1.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-ppkg2.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/pkg.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/pkg1.ads", - "obj-p_ext2/p_ext2-gnatcov-instr/pkg2.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-p_ext2\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/pkg\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/pkg1\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/pkg2\.ads", ]), "\n".join( f.replace("\\", "/") diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 56bdafe4b..2891f554d 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -87,7 +87,8 @@ package Command_Line is Opt_Cancel_Annotate, Opt_All_Warnings, Opt_Save_Temps, - Opt_SPARK_Compat); + Opt_SPARK_Compat, + Opt_Full_Slugs); -- Set of boolean options we support. More complete descriptions below. type String_Options is @@ -551,7 +552,13 @@ package Command_Line is Help => "Enable the SPARK compatibility mode. This ensures" & " instrumented code will be ghost compliant.", Commands => (Cmd_Instrument => True, others => False), - Internal => False)); + Internal => False), + + Opt_Full_Slugs => Create + (Long_Name => "--full-slugs", + Help => "Use full unit slugs instead of hashes for buffer units", + Commands => (Cmd_Instrument => True, others => False), + Internal => True)); String_Infos : constant String_Option_Info_Array := (Opt_Project => Create diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 4953f453c..a90898653 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -451,6 +451,7 @@ procedure GNATcov_Bits_Specific is Emit_Report := not Args.Bool_Args (Opt_Cancel_Annotate); Save_Temps := Args.Bool_Args (Opt_Save_Temps); SPARK_Compat := Args.Bool_Args (Opt_SPARK_Compat); + Use_Full_Slugs := Args.Bool_Args (Opt_Full_Slugs); if Args.Bool_Args (Opt_Recursive) then Warn ("--recursive is deprecated. Recursive is now the default" diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 20cfd0801..543b80da8 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8051,7 +8051,8 @@ package body Instrument.Ada_Unit is (Project_Name : String) return Ada_Qualified_Name is Project_Name_Slug : constant String := - Qualified_Name_Slug (To_Qualified_Name (Project_Name)); + Qualified_Name_Slug + (To_Qualified_Name (Project_Name), Use_Hash => False); begin return Ada_Identifier_Vectors."&" (Sys_Prefix, Instrument.Ada_Identifier (+Project_Name_Slug)); diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 8b8836b00..521db3fcb 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -145,12 +145,26 @@ package body Instrument is -- Qualified_Name_Slug -- ------------------------- - function Qualified_Name_Slug (Name : Ada_Qualified_Name) return String + function Qualified_Name_Slug + (Name : Ada_Qualified_Name; + Use_Hash : Boolean := not Switches.Use_Full_Slugs) return String is First : Boolean := True; Result : Ada_Identifier; begin - -- Create a unique slug from the qualified name: replace occurences of + if Use_Hash then + + -- Prefix the hash with "z_" to ensure the unit name slug doesn't + -- start with a digit. + + return + "z" & Strip_Zero_Padding + (Hex_Image + (Unsigned_32 + (Ada.Strings.Hash (To_Symbol_Name (Name))))); + end if; + + -- Create a unique slug from the qualified name: replace occurrences of -- 'z' with 'zz' and insert '_z_' between identifiers. for Id of Name loop @@ -208,10 +222,25 @@ package body Instrument is -- Filename_Slug -- ------------------- - function Filename_Slug (Fullname : String) return String is + function Filename_Slug + (Fullname : String; + Use_Hash : Boolean := not Switches.Use_Full_Slugs) return String + is use Ada.Directories; Result : Ada_Identifier; + + Full_Name_Hash : constant String := + Strip_Zero_Padding + (Hex_Image (Unsigned_32 (Ada.Strings.Hash (Fullname)))); begin + if Use_Hash then + + -- Prefix the hash with "z_" to ensure the filename slug doesn't + -- start with a digit. + + return "z" & Full_Name_Hash; + end if; + -- We use the basename slug, followed by a hash of the fullname, which -- makes us confident that homonym files will be correctly handled. @@ -237,14 +266,7 @@ package body Instrument is -- Then, suffix with the hash - declare - Hash_Str : constant String := - Hex_Image (Unsigned_32 (Ada.Strings.Hash (Fullname))); - begin - -- Do not forget to remove the leading whitespace... - - Append (Result, Hash_Str (2 .. Hash_Str'Last)); - end; + Append (Result, Full_Name_Hash); return To_String (Result); end Filename_Slug; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 3485d2ae5..cf174b0dd 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -99,9 +99,14 @@ package Instrument is function Image (CU_Name : Compilation_Unit_Part) return String; -- Return a string representation of CU_Name for use in diagnostics - function Qualified_Name_Slug (Name : Ada_Qualified_Name) return String; - -- Given a qualified name, return a unique identifier to describe it. This - -- identifier can be used as a filename suffix / unit name, as it does + function Qualified_Name_Slug + (Name : Ada_Qualified_Name; + Use_Hash : Boolean := not Switches.Use_Full_Slugs) return String; + -- Given a qualified name, return a unique identifier to describe it. + -- This identifier is an 32bit hash of the identifiers in Name, if Use_Hash + -- is True, otherwise, it remains human readable. + -- + -- This identifier can be used as a filename suffix / unit name, as it does -- not contain any '-'. function Instrumented_Unit_Slug @@ -111,9 +116,13 @@ package Instrument is -- -- One can use this slug to generate unique names for this unit. - function Filename_Slug (Fullname : String) return String; + function Filename_Slug + (Fullname : String; + Use_Hash : Boolean := not Switches.Use_Full_Slugs) return String; -- Given a filename to instrument, return a unique identifier to describe - -- it (the so called slug). + -- it (the so called slug). This is a hash of the filename if Use_Hash is + -- True, otherwise a human-readable slug of the base name with the same + -- hash concatenated at the end, to distinguish slugs from homonym files. -- -- One can use this slug to generate unique names for this unit. diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 67817c1f8..7ec854415 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -123,6 +123,10 @@ package Switches is -- Lower abstraction for files of interest, when the --files switch is -- used. + Use_Full_Slugs : Boolean := False; + -- When True, use full unit/filename slugs for generated buffer units + -- instead of hashes. + type Separated_Source_Coverage_Type is (None, Routines, Instances); Separated_Source_Coverage : Separated_Source_Coverage_Type := None; From b6f3809664ff43cc103f38fc3d67ff63c205ac09 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 7 Jul 2023 14:21:01 +0200 Subject: [PATCH 0347/1483] Revert "Merge branch 'eyraud/diagnostics' into 'master'" This reverts commit dc22acfae3d70e3c2b315ebdaa6ee0e733a36536, reversing changes made to 9330e907665b0296f699466bc1dd8e22a4d8e00a. --- testsuite/tests/C++/28-default-values/foo.c | 9 --- .../tests/C++/28-default-values/test.cpp | 11 ---- testsuite/tests/C++/28-default-values/test.py | 31 ---------- tools/gnatcov/instrument-c.adb | 56 ++++++++----------- tools/gnatcov/instrument-c.ads | 5 +- 5 files changed, 25 insertions(+), 87 deletions(-) delete mode 100644 testsuite/tests/C++/28-default-values/foo.c delete mode 100644 testsuite/tests/C++/28-default-values/test.cpp delete mode 100644 testsuite/tests/C++/28-default-values/test.py diff --git a/testsuite/tests/C++/28-default-values/foo.c b/testsuite/tests/C++/28-default-values/foo.c deleted file mode 100644 index 60d82ec5e..000000000 --- a/testsuite/tests/C++/28-default-values/foo.c +++ /dev/null @@ -1,9 +0,0 @@ -// stdlib comes with a bunch of compiler specific code, when included in a -// GNU source context. Check that its inclusion does not result in gnatcov -// instrument emitting spurious diagnostics. -#define _GNU_SOURCE 1 -#include - -int bar(){ - return 0; -} diff --git a/testsuite/tests/C++/28-default-values/test.cpp b/testsuite/tests/C++/28-default-values/test.cpp deleted file mode 100644 index 8dd25d04b..000000000 --- a/testsuite/tests/C++/28-default-values/test.cpp +++ /dev/null @@ -1,11 +0,0 @@ -namespace bar { - bool b = true; - bool foo (bool b = b) { - return b; - } -} - -int main(){ - bar::foo(); - return 0; -} diff --git a/testsuite/tests/C++/28-default-values/test.py b/testsuite/tests/C++/28-default-values/test.py deleted file mode 100644 index 8a35f136b..000000000 --- a/testsuite/tests/C++/28-default-values/test.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Check that we output clang diagnostics on source of interests only. -""" - -from e3.fs import mkdir - -from SCOV.instr import xcov_instrument -from SUITE.cutils import contents_of, Wdir -from SUITE.tutils import thistest, gprfor -from SUITE.gprutils import GPRswitches - -Wdir("tmp_") - -mkdir("obj") - -output = "instr.log" -xcov_instrument( - gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], - mains=["test.cpp"])), - covlevel="stmt", - out=output, -) - -thistest.fail_if_no_match( - "'gnatcov instrument' output", - ".* error: default argument references parameter 'b'", - contents_of(output).strip(), -) - - -thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 3775daaaa..1ab44ade9 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -322,15 +322,8 @@ package body Instrument.C is -- beforehand. Otherwise, generate a preprocessed version of it in -- Info.Output_Dir and start a rewriting session on the latter. - procedure Run_Diagnostics (UIC : in out C_Unit_Inst_Context); - -- Output clang diagnostics on the given translation unit UIC.TU. Note - -- that we aggressively filter out diagnostics whose presumed location - -- file is not a file of interest. Indeed, system headers have a lot - -- of compiler-specific code, which means that some type / symbol names - -- will not be resolved by clang, as we preprocess the code with another - -- compiler configuration (e.g. gcc). This also means that compiler- - -- specific user code will issue false positives. TODO???: is it that - -- uncommon of an occurrence? + procedure Run_Diagnostics (TU : Translation_Unit_T); + -- Output clang diagnostics on the given translation unit function Format_Array_Init_Expr (Exprs : String_Vectors.Vector; @@ -1783,30 +1776,27 @@ package body Instrument.C is -- Run_Diagnostics -- --------------------- - procedure Run_Diagnostics (UIC : in out C_Unit_Inst_Context) - is - Num_Diag : constant unsigned := Get_Num_Diagnostics (UIC.TU); + procedure Run_Diagnostics (TU : Translation_Unit_T) is + Num_Diag : constant unsigned := Get_Num_Diagnostics (TU); begin for I in 1 .. Num_Diag loop declare Diag : constant Diagnostic_T := - Get_Diagnostic (Unit => UIC.TU, Index => I - 1); + Get_Diagnostic (Unit => TU, Index => I - 1); Severity : constant Diagnostic_Severity_T := Get_Diagnostic_Severity (Diag); + Str : constant String := + Format_Diagnostic + (Diagnostic => Diag, + Options => Default_Diagnostic_Display_Options); begin - if Is_Source_Of_Interest (UIC, Get_Diagnostic_Location (Diag)) - then - case Severity is - when Diagnostic_Error | Diagnostic_Fatal => - Outputs.Warning_Or_Error - ("Error when parsing the file " - & Format_Diagnostic - (Diagnostic => Diag, - Options => Default_Diagnostic_Display_Options)); - when others => - null; - end case; - end if; + case Severity is + when Diagnostic_Error | Diagnostic_Fatal => + Outputs.Warning_Or_Error + ("Error when parsing the file " & Str); + when others => + null; + end case; end; end loop; end Run_Diagnostics; @@ -2136,9 +2126,7 @@ package body Instrument.C is -- statement source location range. begin - if Is_Null (N) - or else not Is_Source_Of_Interest (UIC, Get_Cursor_Location (N)) - then + if Is_Null (N) or else not Is_Source_Of_Interest (UIC, N) then return; end if; @@ -2331,7 +2319,7 @@ package body Instrument.C is -- Only traverse the function declarations that belong to a unit of -- interest. - if Is_Source_Of_Interest (UIC, Get_Cursor_Location (N)) then + if Is_Source_Of_Interest (UIC, N) then case Kind (N) is @@ -2704,6 +2692,9 @@ package body Instrument.C is & " options is passed to gnatcov instrument"); raise Xcov_Exit_Exc; end if; + if Verbose then + Run_Diagnostics (Self.TU); + end if; Free (C_Args); end; Self.Rewriter := CX_Rewriter_Create (Self.TU); @@ -2809,7 +2800,6 @@ package body Instrument.C is Options => Translation_Unit_Keep_Going); Free (C_Args); end; - Run_Diagnostics (UIC); Traverse_Declarations (UIC => UIC, L => Get_Children (Get_Translation_Unit_Cursor (UIC.TU))); @@ -4197,14 +4187,14 @@ package body Instrument.C is --------------------------- function Is_Source_Of_Interest - (UIC : in out C_Unit_Inst_Context; - Loc : Source_Location_T) return Boolean + (UIC : in out C_Unit_Inst_Context; N : Cursor_T) return Boolean is -- Determine the file from which N originates C_File : aliased String_T; Line : aliased unsigned; Column : aliased unsigned; + Loc : constant Source_Location_T := Get_Cursor_Location (N); File : Unbounded_String; begin Get_Presumed_Location (Location => Loc, diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index e32946071..f9d89c4c5 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -328,9 +328,8 @@ package Instrument.C is -- Helper object to instrument a source file function Is_Source_Of_Interest - (UIC : in out C_Unit_Inst_Context; - Loc : Source_Location_T) return Boolean; - -- Track the source file from which Locs originates in + (UIC : in out C_Unit_Inst_Context; N : Cursor_T) return Boolean; + -- Track the source file from which N originates in -- UIC.Sources_Of_Interest. Return whether this source file is a source of -- interest. From be6aede381fe336b957b49ac3085891a91016ddc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 7 Jul 2023 13:56:51 +0200 Subject: [PATCH 0348/1483] instr.py: Adapt lch hook generation for buffer units with hashes --- testsuite/SCOV/instr.py | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index e19e2ab05..0e54da693 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -201,12 +201,26 @@ def add_dumper_lch_hook(project, obj_dir, subdirs, main_unit): if project.endswith('.gpr'): project = project[:-4] - # Unit that contain helper routines to dump coverage bufers. There is one - # such unit per main. See instrument-common.ads to know more about the slug - # computation. - main_unit_slug = main_unit.replace('z', 'zz') - auto_dump_unit = 'GCVRT.DB_{}'.format(main_unit_slug) - handler_unit = "Last_Chance_Dumper"; + # Unit that contain helper routines to dump coverage buffers. There is one + # such unit per main. The only differences between two such units of the + # same project is the name of the main unit which is encoded in the trace (in + # place of the actual executable name). This is not checked by the testsuite + # so there should be no problem using the helper unit of a different main. + + auto_dump_hash = None + for _,_, files in os.walk (os.path.join(obj_dir, f"{project}-gnatcov-instr")): + for file in files: + res = re.match(pattern="gcvrt-db_z([0-9a-f]+).adb",string=file) + if res: + auto_dump_hash = res.group(1) + break + if auto_dump_hash: + break + + assert(auto_dump_hash is not None) + + auto_dump_unit = 'GCVRT.DB_z{}'.format(auto_dump_hash) + handler_unit = "Last_Chance_Dumper" def filename(prefix, ext): return os.path.join(obj_dir, '{}-gnatcov-instr'.format(project), From 9ec673736f7cf47ed494b9807e80f513af103b64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 7 Jul 2023 13:59:53 +0200 Subject: [PATCH 0349/1483] Adapt test do work in bareboard scenario The test used to depend in asser.h, this dependency has been removed so that the test can run without a libc. Also disable test for bin traces, as this test a behavior specific to the insturmenter. --- testsuite/tests/92-long_slugs/main.c | 4 +--- testsuite/tests/92-long_slugs/test.opt | 1 + testsuite/tests/92-long_slugs/test.py | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) create mode 100644 testsuite/tests/92-long_slugs/test.opt diff --git a/testsuite/tests/92-long_slugs/main.c b/testsuite/tests/92-long_slugs/main.c index 792aaec55..c0a951db2 100644 --- a/testsuite/tests/92-long_slugs/main.c +++ b/testsuite/tests/92-long_slugs/main.c @@ -1,9 +1,7 @@ #include "OVERLY_LONG_CAPITALIZED_C_UNIT_THAT_SHOULD_NOT_TRIPLE_IN_SIZE_TO_AVOID_PATH_NAME_LIMIT.h" -#include - int main () { - assert (ident (3) == 3); + return ident (0); } diff --git a/testsuite/tests/92-long_slugs/test.opt b/testsuite/tests/92-long_slugs/test.opt new file mode 100644 index 000000000..f9701e94a --- /dev/null +++ b/testsuite/tests/92-long_slugs/test.opt @@ -0,0 +1 @@ +bin-traces DEAD test specific to instrumentation diff --git a/testsuite/tests/92-long_slugs/test.py b/testsuite/tests/92-long_slugs/test.py index 6c1734732..2beba8384 100644 --- a/testsuite/tests/92-long_slugs/test.py +++ b/testsuite/tests/92-long_slugs/test.py @@ -69,7 +69,7 @@ check_xcov_reports( "*.xcov", { - "main.c.xcov": {"+": {8}}, + "main.c.xcov": {"+": {6}}, (unit_name.lower() if "windows" in thistest.env.host.platform else unit_name) + ".c.xcov": {"+": {6}}, }, From bbefb7d17bb94b5e5bddb8eb31c1e5ee1213b3f3 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 5 Jul 2023 11:33:57 +0000 Subject: [PATCH 0350/1483] Ada instrumenter: decide to skip instr. a decision in Process_Decisions Before this patch, the decision of whether to instrument an identifier decision is taken after the low-level to high-level SCOs conversion in `Instrument_Source_File`. Upcoming work will require this decision to be aware of the expression context (in entry guard?), and it is more natural to express this in a place where the context is available: in `Process_Decisions`. This is just a refactoring: no change of behavior expected. --- tools/gnatcov/instrument-ada_unit.adb | 47 +++++++++++++++------------ tools/gnatcov/instrument-ada_unit.ads | 6 ++-- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 543b80da8..4af201370 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -5737,12 +5737,24 @@ package body Instrument.Ada_Unit is end if; end if; + -- Instrumenting static decisions would make them non-static by + -- wrapping them in a Witness call. This transformation would + -- trigger legality checks on the originally non-evaluated branch, + -- which could result in compilation errors specific to the + -- instrumented code, e.g. on: + -- + -- X := (if + -- then + -- else ); + -- + -- For this reason, refrain from instrumenting static decisions. + UIC.Source_Decisions.Append (Source_Decision' - (LL_SCO => Current_Decision, - Decision => N.As_Expr, - State => MCDC_State, - Is_Static => Is_Static_Expr (N.As_Expr))); + (LL_SCO => Current_Decision, + Decision => N.As_Expr, + State => MCDC_State, + Do_Not_Instrument => Is_Static_Expr (N.As_Expr))); end if; -- For an aspect specification, which will be rewritten into a @@ -7907,25 +7919,18 @@ package body Instrument.Ada_Unit is if Coverage.Enabled (Decision) or else MCDC_Coverage_Enabled then for SD of UIC.Source_Decisions loop - -- Instrumenting a static decision would make it non-static by - -- wrapping it in a Witness call. This transformation would - -- trigger legality checks on the originally non-evaluated - -- branch, which could result in compilation errors specific to - -- the instrumented code, e.g. on: - -- - -- X := (if - -- then - -- else ); - -- - -- Mark these decisions as non-instrumented so they are + -- Mark non-instrumented decisions as such so that they are -- properly reported. - if not SD.Is_Static then - Insert_Decision_Witness - (UIC, SD, Path_Count (SCO_Map (SD.LL_SCO))); - else - Set_Decision_SCO_Non_Instr (SCO_Map (SD.LL_SCO)); - end if; + declare + HL_SCO : constant SCO_Id := SCO_Map (SD.LL_SCO); + begin + if SD.Do_Not_Instrument then + Set_Decision_SCO_Non_Instr (HL_SCO); + else + Insert_Decision_Witness (UIC, SD, Path_Count (HL_SCO)); + end if; + end; end loop; if MCDC_Coverage_Enabled then diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index a27d22e80..7dd57a16c 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -185,9 +185,9 @@ private State : Ada.Strings.Unbounded.Unbounded_String; -- Name of MC/DC state local variable - Is_Static : Boolean := False; - -- Whether the decision expression is static (according to the RM - -- definition of static). + Do_Not_Instrument : Boolean; + -- Whether this decision should not be instrumented. This is set to True + -- when instrumenting the decision could create invalid Ada code. end record; type Source_Condition is record From dc08071bf0f6267f72e58312145d823acef23116 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 5 Jul 2023 12:21:25 +0000 Subject: [PATCH 0351/1483] Remove the --analyze-entry-guards option Never ignore 'G' decisions in the low-level to high-level SCO conversion, and in the instrumenter, detect restrictions in order to decide whether entry guards should be instrumented as decisions. When they are not instrumented, flag these decisions as non-instrumented instead of just ignoring them. As a side effect, this fixes the instrumentation of decisions for select alternative barriers (`select ... when X =>`), which used to crash the Ada instrumenter. On configurations that support non-pure/simple barriers, this creates new coverage obligations for entry barriers in user code: adjust existing tests accordingly. --- .../FullRuntime/Barrier/src/test_pop.adb | 6 +- .../Barrier/src/test_pop_push_pop.adb | 4 +- .../FullRuntime/Barrier/src/test_push.adb | 6 +- .../Barrier/src/test_push_push_pop.adb | 4 +- .../main.adb.xml.expected | 56 +++++---- .../example0/decision/src/test_1.adb | 2 +- .../tests/instr-cov/entry_guards/extra.opt | 4 + .../instr-cov/entry_guards/full/src/pkg.adb | 28 +++++ .../instr-cov/entry_guards/full/src/pkg.ads | 8 ++ .../entry_guards/full/src/test_0.adb | 27 +++++ .../entry_guards/full/src/test_a.adb | 32 +++++ .../entry_guards/full/src/test_a_ab.adb | 35 ++++++ .../entry_guards/full/src/test_a_b_ab.adb | 42 +++++++ .../entry_guards/full/src/test_ab.adb | 28 +++++ .../entry_guards/full/src/test_b_ab.adb | 35 ++++++ .../tests/instr-cov/entry_guards/full/test.py | 10 ++ .../entry_guards/restricted/src/pkg.adb | 28 +++++ .../entry_guards/restricted/src/pkg.ads | 10 ++ .../entry_guards/restricted/src/test_true.adb | 8 ++ .../instr-cov/entry_guards/restricted/test.py | 35 ++++++ .../tests/instr-cov/select_when/src/pkg.adb | 27 +++++ .../tests/instr-cov/select_when/src/pkg.ads | 8 ++ .../instr-cov/select_when/src/test_0.adb | 30 +++++ .../instr-cov/select_when/src/test_a_ab.adb | 39 ++++++ .../instr-cov/select_when/src/test_a_b_ab.adb | 48 ++++++++ .../instr-cov/select_when/src/test_b_ab.adb | 39 ++++++ .../instr-cov/select_when/src/test_false.adb | 36 ++++++ .../tests/instr-cov/select_when/test.opt | 2 + testsuite/tests/instr-cov/select_when/test.py | 8 ++ tools/gnatcov/command_line.ads | 10 -- tools/gnatcov/gnatcov_bits_specific.adb | 9 -- tools/gnatcov/instrument-ada_unit.adb | 114 +++++++++++++++--- tools/gnatcov/sc_obligations.adb | 78 +++++------- tools/gnatcov/switches.ads | 3 - 34 files changed, 738 insertions(+), 121 deletions(-) create mode 100644 testsuite/tests/instr-cov/entry_guards/extra.opt create mode 100644 testsuite/tests/instr-cov/entry_guards/full/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/entry_guards/full/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/entry_guards/full/src/test_0.adb create mode 100644 testsuite/tests/instr-cov/entry_guards/full/src/test_a.adb create mode 100644 testsuite/tests/instr-cov/entry_guards/full/src/test_a_ab.adb create mode 100644 testsuite/tests/instr-cov/entry_guards/full/src/test_a_b_ab.adb create mode 100644 testsuite/tests/instr-cov/entry_guards/full/src/test_ab.adb create mode 100644 testsuite/tests/instr-cov/entry_guards/full/src/test_b_ab.adb create mode 100644 testsuite/tests/instr-cov/entry_guards/full/test.py create mode 100644 testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/entry_guards/restricted/src/test_true.adb create mode 100644 testsuite/tests/instr-cov/entry_guards/restricted/test.py create mode 100644 testsuite/tests/instr-cov/select_when/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/select_when/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/select_when/src/test_0.adb create mode 100644 testsuite/tests/instr-cov/select_when/src/test_a_ab.adb create mode 100644 testsuite/tests/instr-cov/select_when/src/test_a_b_ab.adb create mode 100644 testsuite/tests/instr-cov/select_when/src/test_b_ab.adb create mode 100644 testsuite/tests/instr-cov/select_when/src/test_false.adb create mode 100644 testsuite/tests/instr-cov/select_when/test.opt create mode 100644 testsuite/tests/instr-cov/select_when/test.py diff --git a/testsuite/tests/FullRuntime/Barrier/src/test_pop.adb b/testsuite/tests/FullRuntime/Barrier/src/test_pop.adb index 73cc0b288..c5826104d 100644 --- a/testsuite/tests/FullRuntime/Barrier/src/test_pop.adb +++ b/testsuite/tests/FullRuntime/Barrier/src/test_pop.adb @@ -24,15 +24,15 @@ end Test_Pop; -- =/pop_test_tell/ l- ## s- --%cov: --level=stmt\+decision --- =/push_guard/ l. ## 0 +-- =/push_guard/ l- ## d- -- =/push_do/ l- ## s- -- =/push_test_tell/ l- ## s- -- =/push_tell/ l- ## s- --- =/pop_guard/ l. ## 0 +-- =/pop_guard/ l! ## dT- -- =/pop_do/ l- ## s- -- =/pop_tell/ l- ## s- -- =/pop_test_tell/ l- ## s- --# buffer.ads --- =/component_decl/ l+ ## 0 \ No newline at end of file +-- =/component_decl/ l+ ## 0 diff --git a/testsuite/tests/FullRuntime/Barrier/src/test_pop_push_pop.adb b/testsuite/tests/FullRuntime/Barrier/src/test_pop_push_pop.adb index c77cc03bc..7e0248e85 100644 --- a/testsuite/tests/FullRuntime/Barrier/src/test_pop_push_pop.adb +++ b/testsuite/tests/FullRuntime/Barrier/src/test_pop_push_pop.adb @@ -31,11 +31,11 @@ end Test_Pop_Push_Pop; -- =/pop_test_tell/ l+ ## 0 --%cov: --level=stmt\+decision --- =/push_guard/ l. ## 0 +-- =/push_guard/ l! ## dF- -- =/push_do/ l+ ## 0 -- =/push_test_tell/ l! ## dF- -- =/push_tell/ l+ ## 0 --- =/pop_guard/ l. ## 0 +-- =/pop_guard/ l+ ## 0 -- =/pop_do/ l+ ## 0 -- =/pop_tell/ l- ## s- -- =/pop_test_tell/ l! ## dT- diff --git a/testsuite/tests/FullRuntime/Barrier/src/test_push.adb b/testsuite/tests/FullRuntime/Barrier/src/test_push.adb index 3c119ddc4..59959554d 100644 --- a/testsuite/tests/FullRuntime/Barrier/src/test_push.adb +++ b/testsuite/tests/FullRuntime/Barrier/src/test_push.adb @@ -19,14 +19,14 @@ end Test_Push; -- =/pop_test_tell/ l- ## s- --%cov: --level=stmt\+decision --- =/push_guard/ l. ## 0 +-- =/push_guard/ l! ## dF- -- =/push_do/ l+ ## 0 -- =/push_test_tell/ l! ## dT- -- =/push_tell/ l- ## s- --- =/pop_guard/ l. ## 0 +-- =/pop_guard/ l- ## d- -- =/pop_do/ l- ## s- -- =/pop_test_tell/ l- ## s- --# buffer.ads --- =/component_decl/ l+ ## 0 \ No newline at end of file +-- =/component_decl/ l+ ## 0 diff --git a/testsuite/tests/FullRuntime/Barrier/src/test_push_push_pop.adb b/testsuite/tests/FullRuntime/Barrier/src/test_push_push_pop.adb index b18c85b9d..b2b6f40d2 100644 --- a/testsuite/tests/FullRuntime/Barrier/src/test_push_push_pop.adb +++ b/testsuite/tests/FullRuntime/Barrier/src/test_push_push_pop.adb @@ -31,11 +31,11 @@ end Test_Push_Push_Pop; -- =/pop_test_tell/ l+ ## 0 --%cov: --level=stmt\+decision --- =/push_guard/ l. ## 0 +-- =/push_guard/ l+ ## 0 -- =/push_do/ l+ ## 0 -- =/push_test_tell/ l! ## dT- -- =/push_tell/ l- ## s- --- =/pop_guard/ l. ## 0 +-- =/pop_guard/ l! ## dF- -- =/pop_do/ l+ ## 0 -- =/pop_tell/ l+ ## 0 -- =/pop_test_tell/ l! ## dF- diff --git a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected index 37b70b71f..20a7d60d6 100644 --- a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected +++ b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected @@ -1,10 +1,10 @@ - - + + - + @@ -21,10 +21,10 @@ - - + + - + @@ -32,10 +32,10 @@ - - + + - + @@ -777,11 +777,25 @@ - + + + + + + + + + + + + + + + @@ -887,7 +901,7 @@ - + @@ -908,7 +922,7 @@ - + @@ -943,7 +957,7 @@ - + @@ -957,7 +971,7 @@ - + @@ -971,7 +985,7 @@ - + @@ -985,7 +999,7 @@ - + @@ -999,7 +1013,7 @@ - + @@ -1027,7 +1041,7 @@ - + @@ -1041,7 +1055,7 @@ - + @@ -1055,7 +1069,7 @@ - + @@ -1069,7 +1083,7 @@ - + diff --git a/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb b/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb index eab3a20c3..22ea84bb2 100644 --- a/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb +++ b/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb @@ -15,5 +15,5 @@ end; -- /pop_ttell/ l! ## dF- -- /pop_tell/ l+ ## 0 -- /rch_do/ l+ ## 0 --- /wat_guard/ l. ## 0 +-- /wat_guard/ l+ ## 0 -- /wat_do/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/entry_guards/extra.opt b/testsuite/tests/instr-cov/entry_guards/extra.opt new file mode 100644 index 000000000..e1ca6aae1 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/extra.opt @@ -0,0 +1,4 @@ +-- These tests use protected bodies, which not available with light or +-- embedded runtimes. +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/pkg.adb b/testsuite/tests/instr-cov/entry_guards/full/src/pkg.adb new file mode 100644 index 000000000..510602245 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/pkg.adb @@ -0,0 +1,28 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + protected body PT is + + ---------- + -- Init -- + ---------- + + procedure Init (A, B : Boolean) is + begin + PT.A := A; -- # init + PT.B := B; -- # init + end Init; + + --------------- + -- Wait_Cond -- + --------------- + + entry Wait_Cond + when A and then B -- # guard + is + begin + Put_Line ("OK"); -- # stmt + end Wait_Cond; + + end PT; +end Pkg; diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/pkg.ads b/testsuite/tests/instr-cov/entry_guards/full/src/pkg.ads new file mode 100644 index 000000000..9c557c2b9 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/pkg.ads @@ -0,0 +1,8 @@ +package Pkg is + protected type PT is + procedure Init (A, B : Boolean); + entry Wait_Cond; + private + A, B : Boolean := False; -- # init + end PT; +end Pkg; diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/test_0.adb b/testsuite/tests/instr-cov/entry_guards/full/src/test_0.adb new file mode 100644 index 000000000..42b6e3096 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/test_0.adb @@ -0,0 +1,27 @@ +with Pkg; +with Support; use Support; + +procedure Test_0 is +begin + Assert (True); +end Test_0; + +--# pkg.ads +-- /init/ l- ## s- +-- +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l- ## s- +-- =/guard/ l. ## 0 +-- =/stmt/ l- ## s- +-- +-- %cov: --level=stmt\+decision +-- =/init/ l- ## s- +-- =/guard/ l- ## d- +-- =/stmt/ l- ## s- +-- +-- %cov: --level=.*mcdc +-- =/init/ l- ## s- +-- =/guard/ l- ## d- +-- =/stmt/ l- ## s- diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/test_a.adb b/testsuite/tests/instr-cov/entry_guards/full/src/test_a.adb new file mode 100644 index 000000000..f3dac33bd --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/test_a.adb @@ -0,0 +1,32 @@ +with Pkg; + +procedure Test_A is + T : Pkg.PT; +begin + T.Init (A => True, B => False); + select + T.Wait_Cond; + else + null; + end select; +end Test_A; + +--# pkg.ads +-- /init/ l+ ## 0 +-- +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/guard/ l. ## 0 +-- =/stmt/ l- ## s- +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/guard/ l! ## dT- +-- =/stmt/ l- ## s- +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/guard/ l! ## dT- +-- =/stmt/ l- ## s- diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/test_a_ab.adb b/testsuite/tests/instr-cov/entry_guards/full/src/test_a_ab.adb new file mode 100644 index 000000000..b830cf349 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/test_a_ab.adb @@ -0,0 +1,35 @@ +with Pkg; + +procedure Test_A_AB is + T : Pkg.PT; +begin + T.Init (A => True, B => False); + select + T.Wait_Cond; + else + null; + end select; + + T.Init (A => True, B => True); + T.Wait_Cond; +end Test_A_AB; + +--# pkg.ads +-- /init/ l+ ## 0 +-- +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/guard/ l. ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/guard/ l+ ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/guard/ l! ## c!:"A" +-- =/stmt/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/test_a_b_ab.adb b/testsuite/tests/instr-cov/entry_guards/full/src/test_a_b_ab.adb new file mode 100644 index 000000000..9f3b3a93a --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/test_a_b_ab.adb @@ -0,0 +1,42 @@ +with Pkg; + +procedure Test_A_B_AB is + T : Pkg.PT; +begin + T.Init (A => True, B => False); + select + T.Wait_Cond; + else + null; + end select; + + T.Init (A => False, B => True); + select + T.Wait_Cond; + else + null; + end select; + + T.Init (A => True, B => True); + T.Wait_Cond; +end Test_A_B_AB; + +--# pkg.ads +-- /init/ l+ ## 0 +-- +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/guard/ l. ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/guard/ l+ ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/guard/ l+ ## 0 +-- =/stmt/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/test_ab.adb b/testsuite/tests/instr-cov/entry_guards/full/src/test_ab.adb new file mode 100644 index 000000000..780cae54f --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/test_ab.adb @@ -0,0 +1,28 @@ +with Pkg; + +procedure Test_AB is + T : Pkg.PT; +begin + T.Init (A => True, B => True); + T.Wait_Cond; +end Test_AB; + +--# pkg.ads +-- /init/ l+ ## 0 +-- +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/guard/ l. ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/guard/ l! ## dF- +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/guard/ l! ## dF- +-- =/stmt/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/entry_guards/full/src/test_b_ab.adb b/testsuite/tests/instr-cov/entry_guards/full/src/test_b_ab.adb new file mode 100644 index 000000000..dd5e9a222 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/src/test_b_ab.adb @@ -0,0 +1,35 @@ +with Pkg; + +procedure Test_B_AB is + T : Pkg.PT; +begin + T.Init (A => False, B => True); + select + T.Wait_Cond; + else + null; + end select; + + T.Init (A => True, B => True); + T.Wait_Cond; +end Test_B_AB; + +--# pkg.ads +-- /init/ l+ ## 0 +-- +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/guard/ l. ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/guard/ l+ ## 0 +-- =/stmt/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/guard/ l! ## c!:"B" +-- =/stmt/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/entry_guards/full/test.py b/testsuite/tests/instr-cov/entry_guards/full/test.py new file mode 100644 index 000000000..27271256e --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/full/test.py @@ -0,0 +1,10 @@ +"""Check the coverage for protected bodies entry guards.""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.adb b/testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.adb new file mode 100644 index 000000000..4bf754be0 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.adb @@ -0,0 +1,28 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + protected body PT is + + ---------- + -- Init -- + ---------- + + procedure Init (A, B : Boolean) is + begin + PT.A := A; + PT.B := B; + end Init; + + --------------- + -- Wait_Cond -- + --------------- + + entry Wait_Cond + when A and then B + is + begin + Put_Line ("OK"); + end Wait_Cond; + + end PT; +end Pkg; diff --git a/testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.ads b/testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.ads new file mode 100644 index 000000000..75781f03a --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/restricted/src/pkg.ads @@ -0,0 +1,10 @@ +pragma Restrictions (Pure_Barriers); + +package Pkg is + protected type PT is + procedure Init (A, B : Boolean); + entry Wait_Cond; + private + A, B : Boolean := False; + end PT; +end Pkg; diff --git a/testsuite/tests/instr-cov/entry_guards/restricted/src/test_true.adb b/testsuite/tests/instr-cov/entry_guards/restricted/src/test_true.adb new file mode 100644 index 000000000..4d0059e11 --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/restricted/src/test_true.adb @@ -0,0 +1,8 @@ +with Pkg; + +procedure Test_True is + T : Pkg.PT; +begin + T.Init (A => True, B => True); + T.Wait_Cond; +end Test_True; diff --git a/testsuite/tests/instr-cov/entry_guards/restricted/test.py b/testsuite/tests/instr-cov/entry_guards/restricted/test.py new file mode 100644 index 000000000..a29d2aa7f --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/restricted/test.py @@ -0,0 +1,35 @@ +""" +Check that protected bodies' entry guard decisions are not instrumented in the +presence of Pure_Barriers restrictions. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +for covlevel, slug, expected_coverage in [ + ("stmt", "st", {"+": {12, 13, 24}}), + ("stmt+decision", "dc", {"+": {12, 13, 24}, "?": {21}}), +]: + thistest.log(f"== {covlevel} ==") + tmp = Wdir(f"tmp_{slug}") + + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["test_true.adb"]), + units=["pkg"], + ), + covlevel=covlevel, + mains=["test_true"], + extra_coverage_args=["-axcov", "--output-dir=."], + ) + check_xcov_reports( + "*.xcov", {"pkg.adb.xcov": expected_coverage, "pkg.ads.xcov": {}} + ) + + tmp.to_homedir() + +thistest.result() diff --git a/testsuite/tests/instr-cov/select_when/src/pkg.adb b/testsuite/tests/instr-cov/select_when/src/pkg.adb new file mode 100644 index 000000000..1d9deb7f9 --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/pkg.adb @@ -0,0 +1,27 @@ +package body Pkg is + task body T is + A, B : Boolean; -- # init + begin + accept Init (A, B : Boolean) do -- # init + T.A := A; -- # init + T.B := B; -- # init + end; + + loop + select -- # init + accept Set_A (Value : Boolean) do -- # set-a-stmts + A := Value; -- # set-a-stmts + end; + or + accept Set_B (Value : Boolean) do -- # set-b-stmts + B := Value; -- # set-b-stmts + end; + or + when A and then B => -- # wait-guard + accept Wait_Cond; -- # wait-stmts + or + terminate; + end select; + end loop; + end T; +end Pkg; diff --git a/testsuite/tests/instr-cov/select_when/src/pkg.ads b/testsuite/tests/instr-cov/select_when/src/pkg.ads new file mode 100644 index 000000000..df4066f9f --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/pkg.ads @@ -0,0 +1,8 @@ +package Pkg is + task type T is + entry Init (A, B : Boolean); + entry Set_A (Value : Boolean); + entry Set_B (Value : Boolean); + entry Wait_Cond; + end T; +end Pkg; diff --git a/testsuite/tests/instr-cov/select_when/src/test_0.adb b/testsuite/tests/instr-cov/select_when/src/test_0.adb new file mode 100644 index 000000000..20099974f --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/test_0.adb @@ -0,0 +1,30 @@ +with Pkg; +with Support; use Support; + +procedure Test_0 is +begin + Assert (True); +end Test_0; + +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l- ## s- +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l. ## 0 +-- =/wait-stmts/ l- ## s- +-- +-- %cov: --level=stmt\+decision +-- =/init/ l- ## s- +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l- ## d- +-- =/wait-stmts/ l- ## s- +-- +-- %cov: --level=.*mcdc +-- =/init/ l- ## s- +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l- ## d- +-- =/wait-stmts/ l- ## s- diff --git a/testsuite/tests/instr-cov/select_when/src/test_a_ab.adb b/testsuite/tests/instr-cov/select_when/src/test_a_ab.adb new file mode 100644 index 000000000..51501be39 --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/test_a_ab.adb @@ -0,0 +1,39 @@ +with Pkg; + +procedure Test_A_AB is + T : Pkg.T; +begin + T.Init (A => True, B => False); + + select + T.Wait_Cond; -- Guard: True and False => False + else + null; + end select; + + T.Set_B (True); + T.Wait_Cond; -- Guard: True and True => True +end Test_A_AB; + +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l+ ## 0 +-- =/wait-guard/ l. ## 0 +-- =/wait-stmts/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l+ ## 0 +-- =/wait-guard/ l+ ## 0 +-- =/wait-stmts/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l+ ## 0 +-- =/wait-guard/ l! ## c!:"A" +-- =/wait-stmts/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/select_when/src/test_a_b_ab.adb b/testsuite/tests/instr-cov/select_when/src/test_a_b_ab.adb new file mode 100644 index 000000000..246c24e47 --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/test_a_b_ab.adb @@ -0,0 +1,48 @@ +with Pkg; + +procedure Test_A_B_AB is + T : Pkg.T; +begin + T.Init (A => False, B => False); + + T.Set_A (True); + select + T.Wait_Cond; -- Guard: True and False => False + else + null; + end select; + + T.Set_A (False); + T.Set_B (True); + select + T.Wait_Cond; -- Guard: False and True => False + else + null; + end select; + + T.Set_A (True); + T.Wait_Cond; -- Guard: True and True => True +end Test_A_B_AB; + +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l+ ## 0 +-- =/set-b-stmts/ l+ ## 0 +-- =/wait-guard/ l. ## 0 +-- =/wait-stmts/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l+ ## 0 +-- =/set-b-stmts/ l+ ## 0 +-- =/wait-guard/ l+ ## 0 +-- =/wait-stmts/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l+ ## 0 +-- =/set-b-stmts/ l+ ## 0 +-- =/wait-guard/ l+ ## 0 +-- =/wait-stmts/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/select_when/src/test_b_ab.adb b/testsuite/tests/instr-cov/select_when/src/test_b_ab.adb new file mode 100644 index 000000000..1c6b249ff --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/test_b_ab.adb @@ -0,0 +1,39 @@ +with Pkg; + +procedure Test_B_AB is + T : Pkg.T; +begin + T.Init (A => False, B => True); + + select + T.Wait_Cond; -- Guard: False and True => False + else + null; + end select; + + T.Set_A (True); + T.Wait_Cond; -- Guard: True and True => True +end Test_B_AB; + +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l+ ## 0 +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l. ## 0 +-- =/wait-stmts/ l+ ## 0 +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l+ ## 0 +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l+ ## 0 +-- =/wait-stmts/ l+ ## 0 +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l+ ## 0 +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l! ## c!:"B" +-- =/wait-stmts/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/select_when/src/test_false.adb b/testsuite/tests/instr-cov/select_when/src/test_false.adb new file mode 100644 index 000000000..2994fe364 --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/src/test_false.adb @@ -0,0 +1,36 @@ +with Pkg; + +procedure Test_False is + T : Pkg.T; +begin + T.Init (A => False, B => False); + + select + T.Wait_Cond; -- Guard: False and False => False + else + null; + end select; +end Test_False; + +--# pkg.adb +-- +-- %cov: --level=stmt +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l. ## 0 +-- =/wait-stmts/ l- ## s- +-- +-- %cov: --level=stmt\+decision +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l! ## dT- +-- =/wait-stmts/ l- ## s- +-- +-- %cov: --level=.*mcdc +-- =/init/ l+ ## 0 +-- =/set-a-stmts/ l- ## s- +-- =/set-b-stmts/ l- ## s- +-- =/wait-guard/ l! ## dT- +-- =/wait-stmts/ l- ## s- diff --git a/testsuite/tests/instr-cov/select_when/test.opt b/testsuite/tests/instr-cov/select_when/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/instr-cov/select_when/test.py b/testsuite/tests/instr-cov/select_when/test.py new file mode 100644 index 000000000..5fb3bd4ed --- /dev/null +++ b/testsuite/tests/instr-cov/select_when/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +for cat in CAT.critcats: + TestCase(category=cat).run() +thistest.result() diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 2891f554d..4c1a0d67c 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -82,7 +82,6 @@ package Command_Line is Opt_Show_MCDC_Vectors, Opt_Dump_Filename_Simple, Opt_Allow_Mix_Trace_Kind, - Opt_Analyze_Entry_Barriers, Opt_Boolean_Short_Circuit_And_Or, Opt_Cancel_Annotate, Opt_All_Warnings, @@ -509,15 +508,6 @@ package Command_Line is Commands => (Cmd_Coverage => True, others => False), Internal => True), - Opt_Analyze_Entry_Barriers => Create - (Long_Name => "--analyze-entry-barriers", - Help => "Activate coverage analysis for entry barriers." - & ASCII.LF & "Warning, this option should not be used" - & " in source trace mode and with a ravenscar profile," - & " as the instrumenter will generate invalid code.", - Commands => (Cmd_Instrument | Cmd_Coverage => True, others => False), - Internal => True), - Opt_Boolean_Short_Circuit_And_Or => Create (Long_Name => "--short-circuit-and-or", Help => "For Ada sources, consider that boolean operators" diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index a90898653..defcab5a2 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -445,7 +445,6 @@ procedure GNATcov_Bits_Specific is or else All_Messages or else Verbose); Allow_Mixing_Trace_Kinds := Args.Bool_Args (Opt_Allow_Mix_Trace_Kind); - Analyze_Entry_Barriers := Args.Bool_Args (Opt_Analyze_Entry_Barriers); Short_Circuit_And_Or := Args.Bool_Args (Opt_Boolean_Short_Circuit_And_Or); Emit_Report := not Args.Bool_Args (Opt_Cancel_Annotate); @@ -1356,14 +1355,6 @@ begin ("(selected runtime from " & (+Setup_Cfg.Project_File) & ")"); end if; - if Analyze_Entry_Barriers then - Warn ("With source traces, entry barrier analysis (enabled" - & " with --analyze-entry-barriers) is only supported when" - & " when using a full runtime profile. In particular," - & " enabling this option with a ravenscar profile will" - & " result in invalid code being emitted."); - end if; - Instrument.Projects (Dump_Config => Dump_Config, Ignored_Source_Files => diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 4af201370..5d4b0ec46 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -962,6 +962,16 @@ package body Instrument.Ada_Unit is -- Ada.Task_Termination and/or Ada.Task_Identification in either the whole -- project or in Unit. + function Pragma_Restricts_Entry_Guards + (Prag_Node : Pragma_Node) return Boolean; + -- Return True if Node restricts entry guards so that we cannot instrument + -- them as decisions. + + function Entry_Guards_Restricted + (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean; + -- Return if entry guards are restricted in this unit so that we cannot + -- instrument them as decisions. + function Return_From_Subp_Body (Ret_Node : Return_Stmt; Subp : Subp_Body) return Boolean; -- Return whether Ret_Node is returning from Subp @@ -2843,15 +2853,20 @@ package body Instrument.Ada_Unit is -- which aren't valid for a pragma. procedure Process_Decisions - (UIC : in out Ada_Unit_Inst_Context; - N : Ada_Node'Class; - T : Character); + (UIC : in out Ada_Unit_Inst_Context; + N : Ada_Node'Class; + T : Character; + Do_Not_Instrument : Boolean := False); -- If N is Empty, has no effect. Otherwise scans the tree for the node N, -- to output any decisions it contains. T is one of IEGPWX (for context of -- expression: if/exit when/entry guard/pragma/while/expression). If T is -- other than X, the node N is the if expression involved, and a decision -- is always present (at the very least a simple decision is present at the -- top level). + -- + -- If Do_Not_Instrument, this creates SCOs for the decisions/conditions, + -- but plan not to instrument them, so that the decision can be reported as + -- such. -------------------------- -- Internal Subprograms -- @@ -2968,8 +2983,9 @@ package body Instrument.Ada_Unit is -- output intermediate entries such as decision entries. type SD_Entry is record - Nod : Ada_Node; - Typ : Character; + Nod : Ada_Node; + Typ : Character; + Do_Not_Instrument : Boolean; end record; -- Used to store a single entry in the following table. Nod is the node to -- be searched for decisions. @@ -3034,7 +3050,10 @@ package body Instrument.Ada_Unit is -- probably refactor this so the logic for determining it is -- more localized. - procedure Process_Decisions_Defer (N : Ada_Node'Class; T : Character); + procedure Process_Decisions_Defer + (N : Ada_Node'Class; + T : Character; + Do_Not_Instrument : Boolean := False); -- This routine is logically the same as Process_Decisions, except that -- the arguments are saved in the SD table for later processing when -- Set_Statement_Entry is called, which goes through the saved entries @@ -3225,7 +3244,11 @@ package body Instrument.Ada_Unit is -- Process_Decisions_Defer -- ----------------------------- - procedure Process_Decisions_Defer (N : Ada_Node'Class; T : Character) is + procedure Process_Decisions_Defer + (N : Ada_Node'Class; + T : Character; + Do_Not_Instrument : Boolean := False) + is function Process_Decl_Expr (N : Ada_Node'Class) return Visit_Status; -- Helper to Libadalang's Traverse. Only operates on Decl_Exprs, -- instrument each declaration as a statement and process the nested @@ -3270,7 +3293,7 @@ package body Instrument.Ada_Unit is end Process_Decl_Expr; begin - SD.Append ((N.As_Ada_Node, T)); + SD.Append ((N.As_Ada_Node, T, Do_Not_Instrument)); if not N.Is_Null then N.Traverse (Process_Decl_Expr'Access); end if; @@ -3626,7 +3649,8 @@ package body Instrument.Ada_Unit is SDE : SD_Entry renames SD.Table (J); begin - Process_Decisions (UIC, SDE.Nod, SDE.Typ); + Process_Decisions + (UIC, SDE.Nod, SDE.Typ, SDE.Do_Not_Instrument); end; end loop; @@ -4443,13 +4467,18 @@ package body Instrument.Ada_Unit is when Ada_Entry_Body => declare Cond : constant Expr := As_Entry_Body (N).F_Barrier; - + Unit : LAL.Analysis_Unit; begin Set_Statement_Entry; - if Switches.Analyze_Entry_Barriers and then not Cond.Is_Null - then - Process_Decisions_Defer (Cond, 'G'); + if not Cond.Is_Null then + Unit := Cond.Unit; + Process_Decisions_Defer + (N => Cond, + T => 'G', + Do_Not_Instrument => + Entry_Guards_Restricted + (Unit.Context, Unit.Root.As_Compilation_Unit)); end if; Traverse_Subprogram_Or_Task_Body (UIC, N); @@ -5427,9 +5456,10 @@ package body Instrument.Ada_Unit is ----------------------- procedure Process_Decisions - (UIC : in out Ada_Unit_Inst_Context; - N : Ada_Node'Class; - T : Character) + (UIC : in out Ada_Unit_Inst_Context; + N : Ada_Node'Class; + T : Character; + Do_Not_Instrument : Boolean := False) is Mark : Nat; -- This is used to mark the location of a decision sequence in the SCO @@ -5737,6 +5767,10 @@ package body Instrument.Ada_Unit is end if; end if; + -- Do not instrument this decision if we have already determined + -- from the context that instrumenting it could produce invalid + -- code. + -- -- Instrumenting static decisions would make them non-static by -- wrapping them in a Witness call. This transformation would -- trigger legality checks on the originally non-evaluated branch, @@ -5747,14 +5781,16 @@ package body Instrument.Ada_Unit is -- then -- else ); -- - -- For this reason, refrain from instrumenting static decisions. + -- For this reason, also refrain from instrumenting static + -- decisions. UIC.Source_Decisions.Append (Source_Decision' (LL_SCO => Current_Decision, Decision => N.As_Expr, State => MCDC_State, - Do_Not_Instrument => Is_Static_Expr (N.As_Expr))); + Do_Not_Instrument => Do_Not_Instrument + or else Is_Static_Expr (N.As_Expr))); end if; -- For an aspect specification, which will be rewritten into a @@ -7437,6 +7473,48 @@ package body Instrument.Ada_Unit is (Context, Unit, Pragma_Prevents_Task_Termination'Access); end Task_Termination_Restricted; + ----------------------------------- + -- Pragma_Restricts_Entry_Guards -- + ----------------------------------- + + function Pragma_Restricts_Entry_Guards + (Prag_Node : Pragma_Node) return Boolean is + begin + -- We are looking for Restrictions pragmas with Pure_Barriers or + -- Simple_Barriers restrictions. + + if Canonically_Equal (Prag_Node.F_Id.Text, "Restrictions") then + for Assoc of Prag_Node.F_Args loop + declare + Prag_Assoc : constant Pragma_Argument_Assoc := + Assoc.As_Pragma_Argument_Assoc; + Expr_Text : constant Text_Type := Prag_Assoc.F_Expr.Text; + begin + if Prag_Assoc.F_Name.Is_Null + and then (Canonically_Equal (Expr_Text, "Pure_Barriers") + or else + Canonically_Equal (Expr_Text, "Simple_Barriers")) + then + return True; + end if; + end; + end loop; + end if; + return False; + end Pragma_Restricts_Entry_Guards; + + ----------------------------- + -- Entry_Guards_Restricted -- + ----------------------------- + + function Entry_Guards_Restricted + (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean + is + begin + return Has_Matching_Pragma_For_Unit + (Context, Unit, Pragma_Restricts_Entry_Guards'Access); + end Entry_Guards_Restricted; + ----------- -- Apply -- ----------- diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index d2dc7ed1b..658d97c3a 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -3264,55 +3264,35 @@ package body SC_Obligations is when 'E' | 'G' | 'I' | 'P' | 'W' | 'X' | 'A' => -- Decision - if SCOE.C1 = 'G' and then not Analyze_Entry_Barriers then - - -- entry barrier, ignore it as the instrumenter cannot - -- instrument it in the Ravenscar profile, and we should keep - -- the two coverage modes as coherent as possible. - - State.Current_Decision_Ignored := True; - State.Current_Decision := No_SCO_Id; - State.Current_Condition_Index := No_Condition_Index; - Ignored_Slocs.Insert - (Slocs.To_Sloc (Unit.Main_Source, From_Sloc)); - - if Verbose then - Put_Line - ("Ignoring SCO entry: ENTRY BARRIER at " - & Image (Slocs.To_Sloc (Unit.Main_Source, From_Sloc))); - end if; - - else - pragma Assert (State.Current_Decision = No_SCO_Id); - State.Current_Decision_Ignored := False; - State.Current_Decision := Add_SCO - (SCO_Descriptor' - (Kind => Decision, - Origin => CU, - Control_Location => - - -- Control locations are only useful for dominance - -- markers, which are only used with binary traces. As - -- it is impractical to get the correct location with - -- the C/C++ instrumenter, and as using incorrect slocs - -- can create conflicts, ignore those in the - -- instrumentation case. - - (if Provider = Compiler - then Slocs.To_Sloc (Unit.Main_Source, From_Sloc) - else No_Location), - - D_Kind => To_Decision_Kind (SCOE.C1), - Last_Cond_Index => 0, - Aspect_Name => - Get_Aspect_Id (SCOE.Pragma_Aspect_Name), - others => <>)); - pragma Assert (not SCOE.Last); - - State.Current_BDD := - BDD.Create (BDD_Vector, State.Current_Decision); - State.Current_Condition_Index := No_Condition_Index; - end if; + pragma Assert (State.Current_Decision = No_SCO_Id); + State.Current_Decision_Ignored := False; + State.Current_Decision := Add_SCO + (SCO_Descriptor' + (Kind => Decision, + Origin => CU, + Control_Location => + + -- Control locations are only useful for dominance + -- markers, which are only used with binary traces. As + -- it is impractical to get the correct location with + -- the C/C++ instrumenter, and as using incorrect slocs + -- can create conflicts, ignore those in the + -- instrumentation case. + + (if Provider = Compiler + then Slocs.To_Sloc (Unit.Main_Source, From_Sloc) + else No_Location), + + D_Kind => To_Decision_Kind (SCOE.C1), + Last_Cond_Index => 0, + Aspect_Name => + Get_Aspect_Id (SCOE.Pragma_Aspect_Name), + others => <>)); + pragma Assert (not SCOE.Last); + + State.Current_BDD := + BDD.Create (BDD_Vector, State.Current_Decision); + State.Current_Condition_Index := No_Condition_Index; when ' ' => -- Condition diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 7ec854415..662454d7d 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -105,9 +105,6 @@ package Switches is -- If true, mixing trace kinds (binary and source) will not result in an -- error but only output a warning. - Analyze_Entry_Barriers : Boolean := False; - -- If True, instrument and do not discard SCOs from entry barriers - Short_Circuit_And_Or : Boolean := False; -- If True, consider that standard boolean operators "and" and "or" have -- short-circuit semantics and instrument the operands of these operators From 2db6d5bc5cb31e7a204027f5279cf8cb4f15b2b8 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 5 Jul 2023 12:41:27 +0000 Subject: [PATCH 0352/1483] sc_obligations.adb: remove dead code The previous commit made the `CU_Load_State.Current_Decision_Ignored` component useless (always set to False): remove it. --- tools/gnatcov/sc_obligations.adb | 39 +++++++------------------------- 1 file changed, 8 insertions(+), 31 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 658d97c3a..03917c4a4 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -293,15 +293,6 @@ package body SC_Obligations is Current_Decision : SCO_Id := No_SCO_Id; -- Decision whose conditions are being processed - Current_Decision_Ignored : Boolean := False; - -- Whether the current decision is ignored or not. - -- Used to determine if we should load subsequent low-level entries. - -- - -- Currently, only decision scos from entry barriers are ignored because - -- the instrumenter cannot instrument entry barriers for ravenscar - -- profiles, and we want to keep some consistency between the two - -- coverage modes. - Current_Condition_Index : Any_Condition_Index; -- Index of current condition within the current decision (0-based, set -- to No_Condition_Index, i.e. -1, before the first condition of the @@ -3265,7 +3256,6 @@ package body SC_Obligations is -- Decision pragma Assert (State.Current_Decision = No_SCO_Id); - State.Current_Decision_Ignored := False; State.Current_Decision := Add_SCO (SCO_Descriptor' (Kind => Decision, @@ -3297,14 +3287,7 @@ package body SC_Obligations is when ' ' => -- Condition - pragma Assert (State.Current_Decision /= No_SCO_Id - or else State.Current_Decision_Ignored); - - -- Do not process this entry if the current decision is ignored - - if State.Current_Decision_Ignored then - return; - end if; + pragma Assert (State.Current_Decision /= No_SCO_Id); SCO_Vector.Update_Element (Index => State.Current_Decision, @@ -3333,22 +3316,16 @@ package body SC_Obligations is end if; when '!' => - if not State.Current_Decision_Ignored then - BDD.Process_Not (New_Operator_SCO (Op_Not), State.Current_BDD); - end if; + BDD.Process_Not (New_Operator_SCO (Op_Not), State.Current_BDD); when '&' => - if not State.Current_Decision_Ignored then - BDD.Process_And_Then (BDD_Vector, - New_Operator_SCO (Op_And_Then), - State.Current_BDD); - end if; + BDD.Process_And_Then (BDD_Vector, + New_Operator_SCO (Op_And_Then), + State.Current_BDD); when '|' => - if not State.Current_Decision_Ignored then - BDD.Process_Or_Else (BDD_Vector, - New_Operator_SCO (Op_Or_Else), - State.Current_BDD); - end if; + BDD.Process_Or_Else (BDD_Vector, + New_Operator_SCO (Op_Or_Else), + State.Current_BDD); when 'H' => -- Chaining indicator: not used yet From 88feed6e68f4a99b44097591270b860b7de4cd18 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 7 Jul 2023 10:58:32 +0000 Subject: [PATCH 0353/1483] Document the instrumenter limitation for protected bodies entry guards --- doc/gnatcov/src_traces.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index c55edce69..5e7c91446 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -365,6 +365,8 @@ The list of unsupported constructs is as follows: * Recursive expression functions which are primitives of some tagged type, * Expression functions which are primitives of their return type, when it is a tagged type. +* Protected bodies entry guards when the ``Simple_Barriers`` restriction or + the ``Pure_Barriers`` one apply. The simplest way to work around the limitation concerning expression functions is to turn them into regular functions, by giving them a proper body, From 173d0048a3f32ba6e0fd253a23a9107f881f4f89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 6 Jul 2023 17:33:14 +0200 Subject: [PATCH 0354/1483] Cobertura: do no require sources to produce a report --- .../cobertura_validation/{ => src}/lib.c | 0 .../cobertura_validation/{ => src}/pkg.adb | 0 .../cobertura_validation/{ => src}/pkg.ads | 0 .../cobertura_validation/{ => src}/test.adb | 0 testsuite/tests/cobertura_validation/test.py | 79 ++++++++++++++----- tools/gnatcov/annotations-cobertura.adb | 6 +- 6 files changed, 62 insertions(+), 23 deletions(-) rename testsuite/tests/cobertura_validation/{ => src}/lib.c (100%) rename testsuite/tests/cobertura_validation/{ => src}/pkg.adb (100%) rename testsuite/tests/cobertura_validation/{ => src}/pkg.ads (100%) rename testsuite/tests/cobertura_validation/{ => src}/test.adb (100%) diff --git a/testsuite/tests/cobertura_validation/lib.c b/testsuite/tests/cobertura_validation/src/lib.c similarity index 100% rename from testsuite/tests/cobertura_validation/lib.c rename to testsuite/tests/cobertura_validation/src/lib.c diff --git a/testsuite/tests/cobertura_validation/pkg.adb b/testsuite/tests/cobertura_validation/src/pkg.adb similarity index 100% rename from testsuite/tests/cobertura_validation/pkg.adb rename to testsuite/tests/cobertura_validation/src/pkg.adb diff --git a/testsuite/tests/cobertura_validation/pkg.ads b/testsuite/tests/cobertura_validation/src/pkg.ads similarity index 100% rename from testsuite/tests/cobertura_validation/pkg.ads rename to testsuite/tests/cobertura_validation/src/pkg.ads diff --git a/testsuite/tests/cobertura_validation/test.adb b/testsuite/tests/cobertura_validation/src/test.adb similarity index 100% rename from testsuite/tests/cobertura_validation/test.adb rename to testsuite/tests/cobertura_validation/src/test.adb diff --git a/testsuite/tests/cobertura_validation/test.py b/testsuite/tests/cobertura_validation/test.py index cc0b15d76..d6da3af7b 100644 --- a/testsuite/tests/cobertura_validation/test.py +++ b/testsuite/tests/cobertura_validation/test.py @@ -4,9 +4,11 @@ import os +from e3.fs import sync_tree, mv + from lxml import etree -from SCOV.minicheck import build_run_and_coverage +from SCOV.minicheck import build_and_run, xcov from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor, thistest @@ -14,12 +16,23 @@ tmp = Wdir("tmp_") -gprsw = gprsw=GPRswitches( - root_project=gprfor(srcdirs=[".."], mains=["test.adb"]) -) +sync_tree(os.path.join("..", "src"), "src") + +gprsw = gprsw = GPRswitches(root_project=gprfor(srcdirs=["src"], mains=["test.adb"])) + +scos_list = ["obj/lib.c", "obj/pkg", "obj/test"] -def build_run_coverage_and_check(covlevel, output_opt=None, source_root=None): +def build_run_coverage_and_check( + covlevel, output_opt=None, source_root=None, hide_src=False, expected_filenames=None +): + # We need to use manually designated SCOs if we are to remove the sources + # from the project. + # + # Passing explicit SCOs does not work in bin traces for C files, so do not + # run cases with explicit SCOs if this is a bin-traces run. + if thistest.options.trace_mode == "bin" and hide_src: + return extra_args = ["--annotate=cobertura"] if source_root: extra_args += ["--source-root", source_root] @@ -27,15 +40,36 @@ def build_run_coverage_and_check(covlevel, output_opt=None, source_root=None): filename = output_opt if output_opt else "cobertura.xml" if output_opt: extra_args += ["-o", output_opt] + # Using explicit SCOs instead of a project changes the default output dir, + # so set it manually to keep everything consistent. + if hide_src: + extra_args += ["--output-dir=obj"] - build_run_and_coverage( + xcov_args = build_and_run( gprsw=gprsw, covlevel=covlevel, + scos=scos_list if hide_src else None, mains=["test"], extra_coverage_args=extra_args, ) + if hide_src: + mv("src", "src_hidden") + xcov(xcov_args, out="coverage.log") + if hide_src: + mv("src_hidden", "src") parser = etree.XMLParser(dtd_validation=True) - return etree.parse(os.path.join("obj", filename), parser) + report = etree.parse(os.path.join("obj", filename), parser) + if expected_filenames: + filenames = set() + for elt in report.getroot().iter(): + if elt.tag == "class": + filenames.add(elt.get("filename")) + + thistest.fail_if_not_equal( + "list of filenames in cobertura.xml", + "\n".join(sorted(expected_filenames)), + "\n".join(sorted(filenames)), + ) # For both source and object coverage, check that the output "cobertura.xml" @@ -47,20 +81,27 @@ def build_run_coverage_and_check(covlevel, output_opt=None, source_root=None): # Check that the --source-root option works as expected -for prefix in [tmp.homedir, tmp.homedir + "/"]: +expected_filenames = {"lib.c", "pkg.adb", "pkg.ads", "test.adb"} +for prefix in ["src", "src/"]: thistest.log(f"== Prefix: {prefix} ==") - report = build_run_coverage_and_check("stmt", source_root=prefix) - filenames = set() - for elt in report.getroot().iter(): - if elt.tag == "class": - filenames.add(elt.get("filename")) - - expected_filenames = {"lib.c", "pkg.adb", "pkg.ads", "test.adb"} - thistest.fail_if_not_equal( - "list of filenames in cobertura.xml", - "\n".join(sorted(expected_filenames)), - "\n".join(sorted(filenames)), + build_run_coverage_and_check( + "stmt", source_root=os.path.join(os.getcwd(), prefix), expected_filenames=expected_filenames ) +# Check that the report can be emitted in the absence of the project sources. We +# have to rely on sid files to convey the coverage obligations +thistest.log("== Report with no sources ==") +# No pkg.ads in the report as there are no coverage obligations for it +expected_filenames = { + os.path.join(os.getcwd(), "src", filename) + for filename in {"lib.c", "pkg.adb", "test.adb"} +} +build_run_coverage_and_check( + "stmt", + "cobertura-no_src.xml", + hide_src=True, + expected_filenames=expected_filenames +) + thistest.result() diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb index 0de7213cc..172d80a38 100644 --- a/tools/gnatcov/annotations-cobertura.adb +++ b/tools/gnatcov/annotations-cobertura.adb @@ -251,6 +251,8 @@ package body Annotations.Cobertura is Pp.Report_Filename := +"cobertura.xml"; end if; + Pp.Need_Sources := False; + Annotations.Generate_Report (Pp, True, Subdir => "cobertura"); Free (Pp.Source_Prefix_Pattern); end Generate_Report; @@ -425,10 +427,6 @@ package body Annotations.Cobertura is -- Filename to mention in the coverage report. Use the full name, unless -- we can remove the prefix according to the --source-root option. begin - if not Info.Has_Source then - Skip := True; - return; - end if; Skip := False; -- Compute line and branch statistics From 7365c12bfb847e2abf5e28d1011d53397dbfc982 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 7 Jul 2023 11:01:34 +0000 Subject: [PATCH 0355/1483] Fix stmt+mcdc line coverage of uninstrumented decisions For uninstrumented decisions that are not compile-time known, gnatcov used to produce `-` lines in xcov reports for `stmt+mcdc`, whereas `?` is expected instead. --- testsuite/tests/instr-cov/entry_guards/restricted/test.py | 1 + tools/gnatcov/coverage-source.adb | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/instr-cov/entry_guards/restricted/test.py b/testsuite/tests/instr-cov/entry_guards/restricted/test.py index a29d2aa7f..ca8a3387c 100644 --- a/testsuite/tests/instr-cov/entry_guards/restricted/test.py +++ b/testsuite/tests/instr-cov/entry_guards/restricted/test.py @@ -13,6 +13,7 @@ for covlevel, slug, expected_coverage in [ ("stmt", "st", {"+": {12, 13, 24}}), ("stmt+decision", "dc", {"+": {12, 13, 24}, "?": {21}}), + ("stmt+mcdc", "mc", {"+": {12, 13, 24}, "?": {21}}), ]: thistest.log(f"== {covlevel} ==") tmp = Wdir(f"tmp_{slug}") diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 1d1383175..67f1deab7 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -968,7 +968,8 @@ package body Coverage.Source is Compute_MCDC_State (SCO, SCI.all)); end if; - elsif SCO_State /= No_Code then + elsif SCO_State not in No_Code | Undetermined_Coverage + then -- Case of MC/DC enabled, and decision is coverable -- but at least one outcome was never taken: do not From 9654e7f835ee9b74182c41e147aa5e5819983024 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 11 Jul 2023 17:06:43 +0200 Subject: [PATCH 0356/1483] test/cobertura_validation: adjust path comparison Shortening the paths to be compared avoids having to deal with case issues under Windows. --- testsuite/tests/cobertura_validation/test.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/testsuite/tests/cobertura_validation/test.py b/testsuite/tests/cobertura_validation/test.py index d6da3af7b..26138fe78 100644 --- a/testsuite/tests/cobertura_validation/test.py +++ b/testsuite/tests/cobertura_validation/test.py @@ -93,13 +93,12 @@ def build_run_coverage_and_check( # have to rely on sid files to convey the coverage obligations thistest.log("== Report with no sources ==") # No pkg.ads in the report as there are no coverage obligations for it -expected_filenames = { - os.path.join(os.getcwd(), "src", filename) - for filename in {"lib.c", "pkg.adb", "test.adb"} -} +expected_filenames = {"lib.c", "pkg.adb", "test.adb"} + build_run_coverage_and_check( "stmt", "cobertura-no_src.xml", + source_root=os.path.join(os.getcwd(), "src"), hide_src=True, expected_filenames=expected_filenames ) From ea1822fb34769730e919b85cca5d8aea3b4423cd Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 11 Jul 2023 15:13:28 +0000 Subject: [PATCH 0357/1483] Ada instrumenter: rework pragma matching code To avoid code duplication and improve code readability, turn code that accepts/rejects pragmas into matcher data tables. --- tools/gnatcov/instrument-ada_unit.adb | 333 ++++++++++++++------------ 1 file changed, 184 insertions(+), 149 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 5d4b0ec46..337a12c32 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -201,6 +201,18 @@ package body Instrument.Ada_Unit is Static_Predicate, Type_Invariant, + -- Pragmas + + Restrictions, + + -- Pragma Restrictions arguments + + No_Dependence, + No_Finalization, + No_Tasking, + Pure_Barriers, + Simple_Barriers, + -- Annotations Xcov); @@ -221,6 +233,12 @@ package body Instrument.Ada_Unit is Predicate => Precompute_Symbol (Predicate), Static_Predicate => Precompute_Symbol (Static_Predicate), Type_Invariant => Precompute_Symbol (Type_Invariant), + Restrictions => Precompute_Symbol (Restrictions), + No_Dependence => Precompute_Symbol (No_Dependence), + No_Finalization => Precompute_Symbol (No_Finalization), + No_Tasking => Precompute_Symbol (No_Tasking), + Pure_Barriers => Precompute_Symbol (Pure_Barriers), + Simple_Barriers => Precompute_Symbol (Simple_Barriers), Xcov => Precompute_Symbol (Xcov)); function As_Symbol (S : All_Symbols) return Symbol_Type is @@ -230,13 +248,63 @@ package body Instrument.Ada_Unit is function As_Name (Id : Identifier) return Name_Id; -- Canonicalize Id and return a corresponding Name_Id/Symbol_Type + function As_Symbol (Id : Text_Type) return Symbol_Type is + (Find (Symbols, Id)); + -- Return a symbol for the given identifier Id. Note that Id is supposed + -- to be already canonicalized. + function Pragma_Name (P : Pragma_Node) return Symbol_Type; function Pragma_Name (P : Pragma_Node) return Name_Id; -- Return a symbol from Symbols corresponding to the name of the given -- P pragma. - function Canonically_Equal (Left, Right : Text_Type) return Boolean; - -- Returns whether Left and Right are equal after canonicalization + type Pragma_Matcher is record + Pragma_Name : Symbol_Type; + Assoc_Name : Symbol_Type; + Expr_Name : Symbol_Type; + end record; + -- Matcher for a pragma: Pragma_Name is the name of the pragmas that can + -- match, while Assoc_Name and Expr_Name are the name/expression of at + -- least one of the pragma's arguments (Assoc_Name can be null). + -- + -- For example, the following matcher: + -- + -- (As_Symbol ("foo"), null, As_Symbol ("bar")) + -- + -- can match: + -- + -- pragma foo (bar); + -- pragma Foo (Bar); + -- pragma Foo (name, Bar); + -- + -- but not: + -- + -- pragma name (bar); -- unexpected pragma name ("name") + -- pragma foo (bar => 1); -- unexpected argument expr ("1") + -- pragma foo (name => bar); -- unexpected argument name ("name") + -- + -- And the following matcher: + -- + -- (As_Symbol ("foo"), As_Symbol ("bar"), As_Symbol ("x.y")) + -- + -- can match: + -- + -- pragma foo (bar => x.y); + -- pragma Foo (Bar => X.Y); + -- pragma Foo (name, Bar => X.Y); + -- + -- but not: + -- + -- pragma foo (bar); -- unexpected argument name (none) + -- pragma foo (bar => 1); -- unexpected argument expr ("1") + -- pragma foo (name => x); -- unexpected argument name ("name") + + type Pragma_Matcher_Array is array (Positive range <>) of Pragma_Matcher; + + function Matches + (P : Pragma_Node; Matchers : Pragma_Matcher_Array) return Boolean; + -- Return whether pragam P matches at least one of the given pragam + -- matchers. function Aspect_Assoc_Name (A : Aspect_Assoc) return Identifier; function Aspect_Assoc_Name (A : Aspect_Assoc) return Symbol_Type; @@ -922,12 +990,11 @@ package body Instrument.Ada_Unit is -- the return type of the expression function. function Has_Matching_Pragma_For_Unit - (Context : Analysis_Context; - Unit : LAL.Compilation_Unit; - Filter : access function (Node : Pragma_Node) return Boolean) - return Boolean; - -- Return whether Filter return True on at least one configuration pragma - -- that applies to Unit or system.ads. + (Context : Analysis_Context; + Unit : LAL.Compilation_Unit; + Matchers : Pragma_Matcher_Array) return Boolean; + -- Return whether at least one matcher in Matchers accepts at least one + -- configuration pragma that applies to Unit or system.ads. Unusable_System_Reported : Boolean := False; -- Global variable set to True once gnatcov emits a warning about a failure @@ -940,9 +1007,12 @@ package body Instrument.Ada_Unit is Part : Analysis_Unit_Kind) return Boolean; -- Return whether the given unit exists - function Pragma_Restricts_Finalization - (Prag_Node : Pragma_Node) return Boolean; - -- Return True if Prag_Node imposes a restrictions on use of finalization + Pragma_Restricts_Finalization_Matchers : constant Pragma_Matcher_Array := + ((As_Symbol (Restrictions), null, As_Symbol (No_Finalization)), + (As_Symbol (Restrictions), + As_Symbol (No_Dependence), + As_Symbol ("ada.finalization"))); + -- Matchers for pragmas that impose a restrictions on use of finalization function Finalization_Restricted_In_Unit (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean; @@ -950,9 +1020,16 @@ package body Instrument.Ada_Unit is -- some control pragma restricts the usage of finalization in either Unit -- or the whole project. - function Pragma_Prevents_Task_Termination - (Prag_Node : Pragma_Node) return Boolean; - -- Return True if Node prevents the use of tasks and/or + Pragma_Prevents_Task_Termination_Matchers : constant Pragma_Matcher_Array := + ((As_Symbol (Restrictions), null, As_Symbol (No_Finalization)), + (As_Symbol (Restrictions), null, As_Symbol (No_Tasking)), + (As_Symbol (Restrictions), + As_Symbol (No_Dependence), + As_Symbol ("ada.task_termination")), + (As_Symbol (Restrictions), + As_Symbol (No_Dependence), + As_Symbol ("ada.identification"))); + -- Matchers for pragmas that prevent the use of tasks and/or -- Ada.Task_Termination and/or Ada.Task_Identification. function Task_Termination_Restricted @@ -962,10 +1039,11 @@ package body Instrument.Ada_Unit is -- Ada.Task_Termination and/or Ada.Task_Identification in either the whole -- project or in Unit. - function Pragma_Restricts_Entry_Guards - (Prag_Node : Pragma_Node) return Boolean; - -- Return True if Node restricts entry guards so that we cannot instrument - -- them as decisions. + Pragma_Restricts_Entry_Guards_Matchers : constant Pragma_Matcher_Array := + ((As_Symbol (Restrictions), null, As_Symbol (Pure_Barriers)), + (As_Symbol (Restrictions), null, As_Symbol (Simple_Barriers))); + -- Matchers for Restrictions pragmas that restrict entry guards so that we + -- cannot instrument them as decisions (Pure_Barriers and Simple_Barriers). function Entry_Guards_Restricted (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean; @@ -6264,20 +6342,90 @@ package body Instrument.Ada_Unit is end Safe_Is_Ghost; - ----------------------- - -- Canonically_Equal -- - ----------------------- + ------------- + -- Matches -- + ------------- + + function Matches + (P : Pragma_Node; Matchers : Pragma_Matcher_Array) return Boolean + is + function As_Symbol (E : Expr) return Symbol_Type; + -- If E is an identifier or a dotted name involving identifiers only, + -- return a symbol that represents it. Return null otherwise. + + --------------- + -- As_Symbol -- + --------------- + + function As_Symbol (E : Expr) return Symbol_Type is + begin + if E.Is_Null then + return null; + end if; + + case Ada_Expr (E.Kind) is + when Libadalang.Common.Ada_Identifier => + return As_Symbol (E.As_Identifier); + + when Ada_Dotted_Name => + declare + DN : constant Dotted_Name := E.As_Dotted_Name; + Prefix : constant Symbol_Type := + As_Symbol (DN.F_Prefix.As_Expr); + begin + return (if Prefix = null + then null + else Find + (Symbols, + Image (Prefix) + & "." + & Image (As_Symbol (DN.F_Suffix.As_Expr)))); + end; + + when others => + return null; + end case; + end As_Symbol; + + Pragma_Name : constant Symbol_Type := As_Symbol (P.F_Id); + + -- Start of processing for Matches - function Canonically_Equal (Left, Right : Text_Type) return Boolean is - Canonical_Left : constant Symbolization_Result := Canonicalize (Left); - Canonical_Right : constant Symbolization_Result := Canonicalize (Right); begin - -- If canonicalization failed for one of the two text types, assume they - -- are different. + for Matcher of Matchers loop + + -- If this matcher accepts the pragma name, inspect its arguments + + if Matcher.Pragma_Name = Pragma_Name then + for Assoc of P.F_Args loop + declare + A : constant Pragma_Argument_Assoc := + Assoc.As_Pragma_Argument_Assoc; + begin + if Matcher.Assoc_Name = null then - return Canonical_Left.Success - and then Canonical_Left = Canonical_Right; - end Canonically_Equal; + -- We expect an "Expr_Name" expression + + if A.F_Name.Is_Null + and then As_Symbol (A.F_Expr) = Matcher.Expr_Name + then + return True; + end if; + + -- We expect a "Assoc_Name => Expr_Name" association + + elsif As_Symbol (A.F_Name.As_Expr) = Matcher.Assoc_Name + and then As_Symbol (A.F_Expr) = Matcher.Expr_Name + then + return True; + end if; + end; + end loop; + end if; + end loop; + + return False; + end Matches; ----------------------- -- Aspect_Assoc_Name -- @@ -7311,10 +7459,9 @@ package body Instrument.Ada_Unit is ---------------------------------- function Has_Matching_Pragma_For_Unit - (Context : Analysis_Context; - Unit : LAL.Compilation_Unit; - Filter : access function (Node : Pragma_Node) return Boolean) - return Boolean + (Context : Analysis_Context; + Unit : LAL.Compilation_Unit; + Matchers : Pragma_Matcher_Array) return Boolean is System_Unit : constant Analysis_Unit := Context.Get_From_Provider ("System", Unit_Specification); @@ -7342,7 +7489,7 @@ package body Instrument.Ada_Unit is Unusable_System_Reported := True; end if; for Prag_Node of Unit_Pragmas loop - if Filter.all (Prag_Node) then + if Matches (Prag_Node, Matchers) then return True; end if; end loop; @@ -7363,43 +7510,6 @@ package body Instrument.Ada_Unit is (To_Text (Unit), Part) /= ""; end Has_Unit; - ----------------------------------- - -- Pragma_Restricts_Finalization -- - ----------------------------------- - - function Pragma_Restricts_Finalization - (Prag_Node : Pragma_Node) return Boolean - is - begin - -- We are looking for pragmas of the form: - -- pragma Restrictions (No_Finalization); - -- or - -- pragma Restriction (No_Dependence => Ada.Finalization); - - if Canonically_Equal (Prag_Node.F_Id.Text, "Restrictions") then - for Assoc of Prag_Node.F_Args loop - declare - Prag_Assoc : constant Pragma_Argument_Assoc := - Assoc.As_Pragma_Argument_Assoc; - begin - if not Prag_Assoc.F_Name.Is_Null - and then - (Canonically_Equal - (Prag_Assoc.F_Name.Text, "No_Finalization") - or else - (Canonically_Equal - (Prag_Assoc.F_Name.Text, "No_Dependence") - and then Canonically_Equal (Prag_Assoc.F_Expr.Text, - "Ada.Finalization"))) - then - return True; - end if; - end; - end loop; - end if; - return False; - end Pragma_Restricts_Finalization; - ------------------------------------- -- Finalization_Restricted_In_Unit -- ------------------------------------- @@ -7410,54 +7520,9 @@ package body Instrument.Ada_Unit is begin return not Has_Unit (Context, "Ada.Finalization", Unit_Specification) or else Has_Matching_Pragma_For_Unit - (Context, Unit, Pragma_Restricts_Finalization'Access); + (Context, Unit, Pragma_Restricts_Finalization_Matchers); end Finalization_Restricted_In_Unit; - -------------------------------------- - -- Pragma_Prevents_Task_Termination -- - -------------------------------------- - - function Pragma_Prevents_Task_Termination - (Prag_Node : Pragma_Node) return Boolean - is - begin - -- We are looking for pragmas of the form: - -- pragma Restrictions (No_Tasking); - -- or - -- pragma Restriction (No_Dependence => Ada.Task_Termination); - -- or - -- pragma Restriction (No_Depenence => Ada.Task_Identification); - - if Canonically_Equal (Prag_Node.F_Id.Text, "Restrictions") then - for Assoc of Prag_Node.F_Args loop - declare - Prag_Assoc : constant Pragma_Argument_Assoc := - Assoc.As_Pragma_Argument_Assoc; - begin - if not Prag_Assoc.F_Name.Is_Null - and then - (Canonically_Equal - (Prag_Assoc.F_Name.Text, "No_Finalization") - or else Canonically_Equal - (Prag_Assoc.F_Name.Text, "No_Tasking") - or else - (Canonically_Equal - (Prag_Assoc.F_Name.Text, "No_Dependence") - and then - (Canonically_Equal (Prag_Assoc.F_Expr.Text, - "Ada.Task_Termination") - or else - Canonically_Equal (Prag_Assoc.F_Expr.Text, - "Ada.Task_Identification")))) - then - return True; - end if; - end; - end loop; - end if; - return False; - end Pragma_Prevents_Task_Termination; - --------------------------------- -- Task_Termination_Restricted -- --------------------------------- @@ -7470,39 +7535,9 @@ package body Instrument.Ada_Unit is or else not Has_Unit (Context, "Ada.Task.Identification", Unit_Specification) or else Has_Matching_Pragma_For_Unit - (Context, Unit, Pragma_Prevents_Task_Termination'Access); + (Context, Unit, Pragma_Prevents_Task_Termination_Matchers); end Task_Termination_Restricted; - ----------------------------------- - -- Pragma_Restricts_Entry_Guards -- - ----------------------------------- - - function Pragma_Restricts_Entry_Guards - (Prag_Node : Pragma_Node) return Boolean is - begin - -- We are looking for Restrictions pragmas with Pure_Barriers or - -- Simple_Barriers restrictions. - - if Canonically_Equal (Prag_Node.F_Id.Text, "Restrictions") then - for Assoc of Prag_Node.F_Args loop - declare - Prag_Assoc : constant Pragma_Argument_Assoc := - Assoc.As_Pragma_Argument_Assoc; - Expr_Text : constant Text_Type := Prag_Assoc.F_Expr.Text; - begin - if Prag_Assoc.F_Name.Is_Null - and then (Canonically_Equal (Expr_Text, "Pure_Barriers") - or else - Canonically_Equal (Expr_Text, "Simple_Barriers")) - then - return True; - end if; - end; - end loop; - end if; - return False; - end Pragma_Restricts_Entry_Guards; - ----------------------------- -- Entry_Guards_Restricted -- ----------------------------- @@ -7512,7 +7547,7 @@ package body Instrument.Ada_Unit is is begin return Has_Matching_Pragma_For_Unit - (Context, Unit, Pragma_Restricts_Entry_Guards'Access); + (Context, Unit, Pragma_Restricts_Entry_Guards_Matchers); end Entry_Guards_Restricted; ----------- From 1a6828faa35e5897ed539598a7e04557cb66e8e8 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 12 Jul 2023 08:30:16 +0000 Subject: [PATCH 0358/1483] SCOV.internals.rnexpanders: minor reformatting --- testsuite/SCOV/internals/rnexpanders.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index 204f8462a..fe3f82eb4 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -426,7 +426,7 @@ def re_summary(self): return r"(No|\d+) coverage exclusion[s]*\.$" -class UCIchapter (Nchapter): +class UCIchapter(Nchapter): """Undetermined Coverage Items chapter.""" def __init__(self, re_start, re_notes): Nchapter.__init__(self, re_start=re_start, From a5555e1ddef895f421a56ba4e80648c382efcf7d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 12 Jul 2023 08:30:32 +0000 Subject: [PATCH 0359/1483] SCOV.internals.rnexpanders: fix singular handling in regular expression This regexp should accept "1 undetermined coverage item.", so it should have "item[s]*", whereas it currently has "items[s]*". This bug prevented testcases with exactly one uninstrumented item from passing. --- testsuite/SCOV/internals/rnexpanders.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index fe3f82eb4..9f59d580d 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -434,7 +434,7 @@ def __init__(self, re_start, re_notes): re_notes=re_notes) def re_summary(self): - return r"(\d+) undetermined coverage items[s]*\.$" + return r"(\d+) undetermined coverage item[s]*\.$" class SMRchapter(Rchapter): From df94a71252836d0d4a56480b5f26303a270d5fa4 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 12 Jul 2023 08:37:10 +0000 Subject: [PATCH 0360/1483] Ada instrumenter: fix entry guards handling for various profiles Some Ada runtime profiles, like Ravenscar or Jorvik, restrict what entry barriers can contain, and thus prevent decision instrumentation for them. Adapt the existing mechanism so that we do not try to instrument such decisions when these profiles are used. Also update the relevant testcases accordingly. --- .../ProtectedOps/decision/src/test_driver.adb | 1 + .../ProtectedOps/src/synchronization.adb | 2 +- .../example0/decision/src/test_1.adb | 3 +- .../tests/Ravenscar/example0/src/sync.adb | 4 +- tools/gnatcov/instrument-ada_unit.adb | 57 +++++++++++++------ 5 files changed, 46 insertions(+), 21 deletions(-) diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb index 97f44f284..55b6cd2ef 100644 --- a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb @@ -13,5 +13,6 @@ end; -- /exception/ l- ## s- -- /put_element/ l+ ## 0 -- /open_barrier/ l+ ## 0 +-- /entry_guard/ l? ## d? -- /get_element/ l+ ## 0 -- /close_barrier/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.adb b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.adb index 4f0f7d511..760a4b17c 100644 --- a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.adb +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/src/synchronization.adb @@ -21,7 +21,7 @@ package body Synchronization is Barrier := True; -- # open_barrier end Put; - entry Get (Item : out Integer) when Barrier is + entry Get (Item : out Integer) when Barrier is -- # entry_guard begin Item := Element; -- # get_element Barrier := False; -- # close_barrier diff --git a/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb b/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb index 22ea84bb2..0876fde3b 100644 --- a/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb +++ b/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb @@ -11,9 +11,10 @@ end; -- /psh_do/ l+ ## 0 -- /psh_ttell/ l! ## dT- -- /psh_tell/ l- ## s- +-- /pop_guard/ l? ## d? -- /pop_do/ l+ ## 0 -- /pop_ttell/ l! ## dF- -- /pop_tell/ l+ ## 0 -- /rch_do/ l+ ## 0 --- /wat_guard/ l+ ## 0 +-- /wat_guard/ l? ## d? -- /wat_do/ l+ ## 0 diff --git a/testsuite/tests/Ravenscar/example0/src/sync.adb b/testsuite/tests/Ravenscar/example0/src/sync.adb index 37e0f873a..ba96f00f6 100644 --- a/testsuite/tests/Ravenscar/example0/src/sync.adb +++ b/testsuite/tests/Ravenscar/example0/src/sync.adb @@ -11,7 +11,9 @@ package body Sync is Has_Value := True; -- # psh_do end; - entry Pop (V : out Integer; Tell : Boolean) when Has_Value is + entry Pop (V : out Integer; Tell : Boolean) + when Has_Value -- # pop_guard + is begin V := Value; -- # pop_do if Tell then -- # pop_ttell diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 337a12c32..2312e1602 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -203,6 +203,7 @@ package body Instrument.Ada_Unit is -- Pragmas + Profile, Restrictions, -- Pragma Restrictions arguments @@ -213,6 +214,14 @@ package body Instrument.Ada_Unit is Pure_Barriers, Simple_Barriers, + -- Pragma Profile arguments + + GNAT_Extended_Ravenscar, + GNAT_Ravenscar_EDF, + Jorvik, + Ravenscar, + Restricted, + -- Annotations Xcov); @@ -224,22 +233,28 @@ package body Instrument.Ada_Unit is (Find (Symbols, Canonicalize (To_Wide_Wide_String (S'Image)).Symbol)); Precomputed_Symbols : constant array (All_Symbols) of Symbol_Type := - (Dynamic_Predicate => Precompute_Symbol (Dynamic_Predicate), - Invariant => Precompute_Symbol (Invariant), - Post => Precompute_Symbol (Post), - Postcondition => Precompute_Symbol (Postcondition), - Pre => Precompute_Symbol (Pre), - Precondition => Precompute_Symbol (Precondition), - Predicate => Precompute_Symbol (Predicate), - Static_Predicate => Precompute_Symbol (Static_Predicate), - Type_Invariant => Precompute_Symbol (Type_Invariant), - Restrictions => Precompute_Symbol (Restrictions), - No_Dependence => Precompute_Symbol (No_Dependence), - No_Finalization => Precompute_Symbol (No_Finalization), - No_Tasking => Precompute_Symbol (No_Tasking), - Pure_Barriers => Precompute_Symbol (Pure_Barriers), - Simple_Barriers => Precompute_Symbol (Simple_Barriers), - Xcov => Precompute_Symbol (Xcov)); + (Dynamic_Predicate => Precompute_Symbol (Dynamic_Predicate), + Invariant => Precompute_Symbol (Invariant), + Post => Precompute_Symbol (Post), + Postcondition => Precompute_Symbol (Postcondition), + Pre => Precompute_Symbol (Pre), + Precondition => Precompute_Symbol (Precondition), + Predicate => Precompute_Symbol (Predicate), + Static_Predicate => Precompute_Symbol (Static_Predicate), + Type_Invariant => Precompute_Symbol (Type_Invariant), + Profile => Precompute_Symbol (Profile), + Restrictions => Precompute_Symbol (Restrictions), + No_Dependence => Precompute_Symbol (No_Dependence), + No_Finalization => Precompute_Symbol (No_Finalization), + No_Tasking => Precompute_Symbol (No_Tasking), + Pure_Barriers => Precompute_Symbol (Pure_Barriers), + Simple_Barriers => Precompute_Symbol (Simple_Barriers), + GNAT_Extended_Ravenscar => Precompute_Symbol (GNAT_Extended_Ravenscar), + GNAT_Ravenscar_EDF => Precompute_Symbol (Dynamic_Predicate), + Jorvik => Precompute_Symbol (Jorvik), + Ravenscar => Precompute_Symbol (Ravenscar), + Restricted => Precompute_Symbol (Restricted), + Xcov => Precompute_Symbol (Xcov)); function As_Symbol (S : All_Symbols) return Symbol_Type is (Precomputed_Symbols (S)); @@ -1041,9 +1056,15 @@ package body Instrument.Ada_Unit is Pragma_Restricts_Entry_Guards_Matchers : constant Pragma_Matcher_Array := ((As_Symbol (Restrictions), null, As_Symbol (Pure_Barriers)), - (As_Symbol (Restrictions), null, As_Symbol (Simple_Barriers))); + (As_Symbol (Restrictions), null, As_Symbol (Simple_Barriers)), + (As_Symbol (Profile), null, As_Symbol (GNAT_Extended_Ravenscar)), + (As_Symbol (Profile), null, As_Symbol (GNAT_Ravenscar_EDF)), + (As_Symbol (Profile), null, As_Symbol (Jorvik)), + (As_Symbol (Profile), null, As_Symbol (Ravenscar)), + (As_Symbol (Profile), null, As_Symbol (Restricted))); -- Matchers for Restrictions pragmas that restrict entry guards so that we - -- cannot instrument them as decisions (Pure_Barriers and Simple_Barriers). + -- cannot instrument them as decisions (Pure_Barriers and Simple_Barriers, + -- plus various Ada runtime profiles). function Entry_Guards_Restricted (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean; From e24ee9eb366eaf615ef38c99c42bf530f6283338 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 12 Jul 2023 13:54:14 +0000 Subject: [PATCH 0361/1483] instr-cov/entry_guards/restricted: kill with old compilers --- testsuite/tests/instr-cov/entry_guards/restricted/test.opt | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 testsuite/tests/instr-cov/entry_guards/restricted/test.opt diff --git a/testsuite/tests/instr-cov/entry_guards/restricted/test.opt b/testsuite/tests/instr-cov/entry_guards/restricted/test.opt new file mode 100644 index 000000000..9355892fe --- /dev/null +++ b/testsuite/tests/instr-cov/entry_guards/restricted/test.opt @@ -0,0 +1,3 @@ +-- Support for the Pure_Barriers pragma is recent in GNAT +5.04a1 DEAD +7.1.2 DEAD From 0f666e9f5d5c71cb4743b556de7f0472b246c9e5 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 13 Jul 2023 13:58:02 +0000 Subject: [PATCH 0362/1483] Ravenscar: adjust coverage expectations for binary traces Recent changes for these tests assumed coverage for source traces, and so created regresions for runs in binary traces mode. Adjust expectations to accomodate both: the discrepancy between the two modes is expected. --- .../Tasking/ProtectedOps/decision/src/test_driver.adb | 4 +++- testsuite/tests/Ravenscar/example0/decision/src/test_1.adb | 6 ++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb index 55b6cd2ef..44aa5b867 100644 --- a/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb +++ b/testsuite/tests/Ravenscar/Tasking/ProtectedOps/decision/src/test_driver.adb @@ -13,6 +13,8 @@ end; -- /exception/ l- ## s- -- /put_element/ l+ ## 0 -- /open_barrier/ l+ ## 0 --- /entry_guard/ l? ## d? -- /get_element/ l+ ## 0 -- /close_barrier/ l+ ## 0 +-- +-- %opts: --trace-mode=src +-- =/entry_guard/ l? ## d? diff --git a/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb b/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb index 0876fde3b..ff0714f14 100644 --- a/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb +++ b/testsuite/tests/Ravenscar/example0/decision/src/test_1.adb @@ -11,10 +11,12 @@ end; -- /psh_do/ l+ ## 0 -- /psh_ttell/ l! ## dT- -- /psh_tell/ l- ## s- --- /pop_guard/ l? ## d? -- /pop_do/ l+ ## 0 -- /pop_ttell/ l! ## dF- -- /pop_tell/ l+ ## 0 -- /rch_do/ l+ ## 0 --- /wat_guard/ l? ## d? -- /wat_do/ l+ ## 0 +-- +-- %opts: --trace-mode=src +-- /pop_guard/ l? ## d? +-- /wat_guard/ l? ## d? From 41f99d38e4f511311ee33080dd92d231d63f069f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 11 Jul 2023 15:33:23 +0200 Subject: [PATCH 0363/1483] Correctly process quant. expr. as decisions The predicate Has_Decision in Instrument.Ada_Unit did not properly consider that quantified expressions contained a decision. This meant that in some contexts, such as in object declarations, quantified expressions were not instrumented, and SCOs would not be emitted for them. --- .../tests/97-quant_expr_in_decl/src/pkg.adb | 25 +++++++++++++++++++ .../tests/97-quant_expr_in_decl/src/pkg.ads | 9 +++++++ .../97-quant_expr_in_decl/src/test_0.adb | 12 +++++++++ .../97-quant_expr_in_decl/src/test_f.adb | 19 ++++++++++++++ .../97-quant_expr_in_decl/src/test_t.adb | 19 ++++++++++++++ .../97-quant_expr_in_decl/src/test_tf.adb | 17 +++++++++++++ .../tests/97-quant_expr_in_decl/test.opt | 1 + testsuite/tests/97-quant_expr_in_decl/test.py | 12 +++++++++ tools/gnatcov/instrument-ada_unit.adb | 8 +++--- 9 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/97-quant_expr_in_decl/src/pkg.adb create mode 100644 testsuite/tests/97-quant_expr_in_decl/src/pkg.ads create mode 100644 testsuite/tests/97-quant_expr_in_decl/src/test_0.adb create mode 100644 testsuite/tests/97-quant_expr_in_decl/src/test_f.adb create mode 100644 testsuite/tests/97-quant_expr_in_decl/src/test_t.adb create mode 100644 testsuite/tests/97-quant_expr_in_decl/src/test_tf.adb create mode 100644 testsuite/tests/97-quant_expr_in_decl/test.opt create mode 100644 testsuite/tests/97-quant_expr_in_decl/test.py diff --git a/testsuite/tests/97-quant_expr_in_decl/src/pkg.adb b/testsuite/tests/97-quant_expr_in_decl/src/pkg.adb new file mode 100644 index 000000000..39342ff6c --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/src/pkg.adb @@ -0,0 +1,25 @@ +pragma Ada_2012; + +package body Pkg is + + -------------- + -- All_True -- + -------------- + + function All_True (Arr : My_Arr) return Boolean is + Res : constant Boolean := (for all Elt of Arr => Elt); -- # decl + begin + return Res; -- # ret + end All_True; + + --------------- + -- Some_True -- + --------------- + + function Some_True (Arr : My_Arr) return Boolean is + Res : constant Boolean := (for some Elt of Arr => Elt); -- # decl + begin + return Res; -- # ret + end Some_True; + +end Pkg; diff --git a/testsuite/tests/97-quant_expr_in_decl/src/pkg.ads b/testsuite/tests/97-quant_expr_in_decl/src/pkg.ads new file mode 100644 index 000000000..c22a6f4d8 --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/src/pkg.ads @@ -0,0 +1,9 @@ +package Pkg is + + type My_Arr is Array (Positive range <>) of Boolean; + + function All_True (Arr : My_Arr) return Boolean; + + function Some_True (Arr : My_Arr) return Boolean; + +end Pkg; diff --git a/testsuite/tests/97-quant_expr_in_decl/src/test_0.adb b/testsuite/tests/97-quant_expr_in_decl/src/test_0.adb new file mode 100644 index 000000000..203d38250 --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/src/test_0.adb @@ -0,0 +1,12 @@ +with Support; use Support; +with Pkg; + +procedure Test_No is +begin + null; +end Test_No; + +--# pkg.adb +-- +-- /decl/ l- ## s- +-- /ret/ l- ## s- diff --git a/testsuite/tests/97-quant_expr_in_decl/src/test_f.adb b/testsuite/tests/97-quant_expr_in_decl/src/test_f.adb new file mode 100644 index 000000000..59ec55857 --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/src/test_f.adb @@ -0,0 +1,19 @@ +with Support; use Support; +with Pkg; + +procedure Test_F is + All_F : Pkg.My_Arr := (False, False, False); +begin + Assert (not Pkg.All_True (All_F)); + Assert (not Pkg.Some_True (All_F)); +end Test_F; + +--# pkg.adb +-- +-- /decl/ l! ## dT- +-- /ret/ l+ ## 0 +-- +-- Decision coverage with bin traces is imprecise on simple expressions +-- +-- %opts: --trace-mode=bin +-- =/decl/ l! ## d! diff --git a/testsuite/tests/97-quant_expr_in_decl/src/test_t.adb b/testsuite/tests/97-quant_expr_in_decl/src/test_t.adb new file mode 100644 index 000000000..6428f0cdd --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/src/test_t.adb @@ -0,0 +1,19 @@ +with Support; use Support; +with Pkg; + +procedure Test_T is + All_T : Pkg.My_Arr := (True, True, True); +begin + Assert (Pkg.All_True (All_T)); + Assert (Pkg.Some_True (All_T)); +end Test_T; + +--# pkg.adb +-- +-- /decl/ l! ## dF- +-- /ret/ l+ ## 0 +-- +-- Decision coverage with bin traces is imprecise on simple expressions +-- +-- %opts: --trace-mode=bin +-- =/decl/ l! ## d! diff --git a/testsuite/tests/97-quant_expr_in_decl/src/test_tf.adb b/testsuite/tests/97-quant_expr_in_decl/src/test_tf.adb new file mode 100644 index 000000000..2136c72e4 --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/src/test_tf.adb @@ -0,0 +1,17 @@ +with Support; use Support; +with Pkg; + +procedure Test_T is + All_T : Pkg.My_Arr := (True, True, True); + All_F : Pkg.My_Arr := (False, False, False); +begin + Assert (Pkg.All_True (All_T)); + Assert (Pkg.Some_True (All_T)); + Assert (not Pkg.All_True (All_F)); + Assert (not Pkg.Some_True (All_F)); +end Test_T; + +--# pkg.adb +-- +-- /decl/ l+ ## 0 +-- /ret/ l+ ## 0 diff --git a/testsuite/tests/97-quant_expr_in_decl/test.opt b/testsuite/tests/97-quant_expr_in_decl/test.opt new file mode 100644 index 000000000..bbf61ccd4 --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Quantified expressions not supported by gnat 5.04a1 diff --git a/testsuite/tests/97-quant_expr_in_decl/test.py b/testsuite/tests/97-quant_expr_in_decl/test.py new file mode 100644 index 000000000..851fc0e58 --- /dev/null +++ b/testsuite/tests/97-quant_expr_in_decl/test.py @@ -0,0 +1,12 @@ +""" +Check that quantified expressions are correctly instrumented in object +declaration initialization expressions. This used not to be the case. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 2312e1602..879ff1f43 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6094,7 +6094,8 @@ package body Instrument.Ada_Unit is -- otherwise return Into. -- -- We know have a decision as soon as we have a logical operator (by - -- definition) or an IF-expression (its condition is a decision). + -- definition), an IF-expression (its condition is a decision), or a + -- quantified expression. -- -- Do not recurse into the declarations of declare expressions as those -- are handled separately. @@ -6111,8 +6112,9 @@ package body Instrument.Ada_Unit is then return Over; elsif N.Kind in Ada_Expr - and then (Is_Complex_Decision (UIC, N.As_Expr) - or else N.Kind = Ada_If_Expr) + and then + (Is_Complex_Decision (UIC, N.As_Expr) + or else N.Kind in Ada_If_Expr | Ada_Quantified_Expr_Range) then return Stop; else From aadf594b8ffcd9111354d19c4feeb9f15d754ea4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 17 Jul 2023 11:50:35 +0200 Subject: [PATCH 0364/1483] XFAIL quant expr test until next stable bump The changes made to the compiler won't be available for wavefront gnatcov testing until the next stable bump, XFAIL the test 97-quant_expr_in_decl for bin traces in the meantime. --- testsuite/tests/97-quant_expr_in_decl/test.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/97-quant_expr_in_decl/test.opt b/testsuite/tests/97-quant_expr_in_decl/test.opt index bbf61ccd4..0f47b1b0c 100644 --- a/testsuite/tests/97-quant_expr_in_decl/test.opt +++ b/testsuite/tests/97-quant_expr_in_decl/test.opt @@ -1 +1,2 @@ 5.04a1 DEAD Quantified expressions not supported by gnat 5.04a1 +bin-traces XFAIL Requires compiler change, will be fixed by next stable bump From 0c0ab9615c426a77bc79497e9bcd0b830d633bad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 18 Jul 2023 11:24:10 +0200 Subject: [PATCH 0365/1483] Process nested decisions in quant. expr. loop specs The Process_Decisions tree traversal skipped the processing of the loop specification of quantified expressions nodes, thus potentially missing on some nested decisions. This change fixes that by fully traversing the syntactic children of quantified expressions nodes. Fixes eng/cov/gnatcoverage#98 --- .../tests/98-quant_expr_nested/src/pkg.ads | 13 +++++++++++++ .../tests/98-quant_expr_nested/src/test_0.adb | 14 ++++++++++++++ .../tests/98-quant_expr_nested/src/test_f_f.adb | 16 ++++++++++++++++ .../tests/98-quant_expr_nested/src/test_f_t.adb | 16 ++++++++++++++++ .../98-quant_expr_nested/src/test_full.adb | 17 +++++++++++++++++ .../tests/98-quant_expr_nested/src/test_t_f.adb | 16 ++++++++++++++++ .../tests/98-quant_expr_nested/src/test_t_t.adb | 16 ++++++++++++++++ testsuite/tests/98-quant_expr_nested/test.opt | 2 ++ testsuite/tests/98-quant_expr_nested/test.py | 15 +++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 2 ++ 10 files changed, 127 insertions(+) create mode 100644 testsuite/tests/98-quant_expr_nested/src/pkg.ads create mode 100644 testsuite/tests/98-quant_expr_nested/src/test_0.adb create mode 100644 testsuite/tests/98-quant_expr_nested/src/test_f_f.adb create mode 100644 testsuite/tests/98-quant_expr_nested/src/test_f_t.adb create mode 100644 testsuite/tests/98-quant_expr_nested/src/test_full.adb create mode 100644 testsuite/tests/98-quant_expr_nested/src/test_t_f.adb create mode 100644 testsuite/tests/98-quant_expr_nested/src/test_t_t.adb create mode 100644 testsuite/tests/98-quant_expr_nested/test.opt create mode 100644 testsuite/tests/98-quant_expr_nested/test.py diff --git a/testsuite/tests/98-quant_expr_nested/src/pkg.ads b/testsuite/tests/98-quant_expr_nested/src/pkg.ads new file mode 100644 index 000000000..1e4b5f3cc --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/pkg.ads @@ -0,0 +1,13 @@ +pragma Ada_2012; + +package Pkg is + + type My_Arr is array (Positive range <>) of Integer; + + function All_Positive + (Arr_Main, Arr_Backup : My_Arr; Use_Backup : Boolean) return Boolean is + (for all Element of -- # stmt + My_Arr'(if Use_Backup then Arr_Backup else Arr_Main) => -- # if_expr + Element >= 0); -- # predicate + +end Pkg; diff --git a/testsuite/tests/98-quant_expr_nested/src/test_0.adb b/testsuite/tests/98-quant_expr_nested/src/test_0.adb new file mode 100644 index 000000000..904cef813 --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/test_0.adb @@ -0,0 +1,14 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_F_F is +begin + null; +end Test_F_F; + +--# pkg.ads +-- +-- /stmt/ l- ## s- +-- /if_expr/ l- ## 0 +-- /predicate/ l- ## 0 diff --git a/testsuite/tests/98-quant_expr_nested/src/test_f_f.adb b/testsuite/tests/98-quant_expr_nested/src/test_f_f.adb new file mode 100644 index 000000000..853bc290e --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/test_f_f.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_F_F is + Arr_Main : My_Arr := (1 .. 10 => -18); + Arr_Backup : My_Arr := (1 .. 4 => 4); +begin + Assert (not All_Positive (Arr_Main, Arr_Backup, False)); +end Test_F_F; + +--# pkg.ads +-- +-- /stmt/ l+ ## 0 +-- /if_expr/ l! ## dT- +-- /predicate/ l! ## dT- diff --git a/testsuite/tests/98-quant_expr_nested/src/test_f_t.adb b/testsuite/tests/98-quant_expr_nested/src/test_f_t.adb new file mode 100644 index 000000000..ab84edee4 --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/test_f_t.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_F_T is + Arr_Main : My_Arr := (1 .. 10 => 18); + Arr_Backup : My_Arr := (1 .. 4 => -4); +begin + Assert (All_Positive (Arr_Main, Arr_Backup, False)); +end Test_F_T; + +--# pkg.ads +-- +-- /stmt/ l+ ## 0 +-- /if_expr/ l! ## dT- +-- /predicate/ l! ## dF- diff --git a/testsuite/tests/98-quant_expr_nested/src/test_full.adb b/testsuite/tests/98-quant_expr_nested/src/test_full.adb new file mode 100644 index 000000000..478a0c152 --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/test_full.adb @@ -0,0 +1,17 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_T_T is + Arr_Main : My_Arr := (1 .. 10 => -18); + Arr_Backup : My_Arr := (1 .. 4 => 4); +begin + Assert (All_Positive (Arr_Main, Arr_Backup, True)); + Assert (not All_Positive (Arr_Main, Arr_Backup, False)); +end Test_T_T; + +--# pkg.ads +-- +-- /stmt/ l+ ## 0 +-- /if_expr/ l+ ## 0 +-- /predicate/ l+ ## 0 diff --git a/testsuite/tests/98-quant_expr_nested/src/test_t_f.adb b/testsuite/tests/98-quant_expr_nested/src/test_t_f.adb new file mode 100644 index 000000000..e288bec71 --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/test_t_f.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_T_F is + Arr_Main : My_Arr := (1 .. 10 => 18); + Arr_Backup : My_Arr := (1 .. 4 => -4); +begin + Assert (All_Positive (Arr_Main, Arr_Backup, False)); +end Test_T_F; + +--# pkg.ads +-- +-- /stmt/ l+ ## 0 +-- /if_expr/ l! ## dT- +-- /predicate/ l! ## dF- diff --git a/testsuite/tests/98-quant_expr_nested/src/test_t_t.adb b/testsuite/tests/98-quant_expr_nested/src/test_t_t.adb new file mode 100644 index 000000000..704b9946e --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/src/test_t_t.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_T_T is + Arr_Main : My_Arr := (1 .. 10 => -18); + Arr_Backup : My_Arr := (1 .. 4 => 4); +begin + Assert (All_Positive (Arr_Main, Arr_Backup, True)); +end Test_T_T; + +--# pkg.ads +-- +-- /stmt/ l+ ## 0 +-- /if_expr/ l! ## dF- +-- /predicate/ l! ## dF- diff --git a/testsuite/tests/98-quant_expr_nested/test.opt b/testsuite/tests/98-quant_expr_nested/test.opt new file mode 100644 index 000000000..0f47b1b0c --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Quantified expressions not supported by gnat 5.04a1 +bin-traces XFAIL Requires compiler change, will be fixed by next stable bump diff --git a/testsuite/tests/98-quant_expr_nested/test.py b/testsuite/tests/98-quant_expr_nested/test.py new file mode 100644 index 000000000..7b05164ca --- /dev/null +++ b/testsuite/tests/98-quant_expr_nested/test.py @@ -0,0 +1,15 @@ +""" +Check that decisions nested in a quantified expression but not in the predicate +are correctly instrumented. These used to be silently ignored by gnatcov. + +The naming convention for the test drivers is as follows: +test__.adb +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 879ff1f43..e28c19ac8 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6032,6 +6032,8 @@ package body Instrument.Ada_Unit is end; when Ada_Quantified_Expr => + Process_Decisions + (UIC, N.As_Quantified_Expr.F_Loop_Spec, 'X'); Process_Decisions (UIC, N.As_Quantified_Expr.F_Expr, 'W'); return Over; From ad3f23d16585c82508f4aca260fe8cef3baffb97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 19 Jul 2023 17:57:13 +0200 Subject: [PATCH 0366/1483] Test/98-quant_expr_nested: Kill for gnat 7.1.2 run Ada 2012 support is not perfect in gnat 7.1.2, so do not run the test when using that compiler. --- testsuite/tests/98-quant_expr_nested/test.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/98-quant_expr_nested/test.opt b/testsuite/tests/98-quant_expr_nested/test.opt index 0f47b1b0c..2f812c360 100644 --- a/testsuite/tests/98-quant_expr_nested/test.opt +++ b/testsuite/tests/98-quant_expr_nested/test.opt @@ -1,2 +1,3 @@ 5.04a1 DEAD Quantified expressions not supported by gnat 5.04a1 +7.1.2 DEAD Ada 2012 support weak on 7.1.2 bin-traces XFAIL Requires compiler change, will be fixed by next stable bump From 2eb45955230de23a499c1d08742e0ea15999f947 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 19 Jul 2023 12:22:03 +0200 Subject: [PATCH 0367/1483] Add support for iterator filters in the Ada instrumenter This change modifies the instrumenter to always consider iterator filters as decisions (both for decision coverage and MC/DC coverage) and adds corresponding tests in the Ada2022 testsuite directory. --- .../iter_filter/array_aggr/src/pkg.adb | 18 ++++++++++++++ .../Ada2022/iter_filter/array_aggr/test.py | 12 ++++++++++ .../Ada2022/iter_filter/cont_aggr/src/pkg.adb | 24 +++++++++++++++++++ .../Ada2022/iter_filter/cont_aggr/test.opt | 2 ++ .../Ada2022/iter_filter/cont_aggr/test.py | 12 ++++++++++ .../Ada2022/iter_filter/for_loop/src/pkg.adb | 16 +++++++++++++ .../Ada2022/iter_filter/for_loop/test.py | 12 ++++++++++ .../iter_filter/quant_expr/src/foo.ads | 12 ++++++++++ .../iter_filter/quant_expr/src/test_0.adb | 13 ++++++++++ .../iter_filter/quant_expr/src/test_f_x.adb | 16 +++++++++++++ .../iter_filter/quant_expr/src/test_full.adb | 14 +++++++++++ .../iter_filter/quant_expr/src/test_t_t.adb | 14 +++++++++++ .../iter_filter/quant_expr/src/test_tf_f.adb | 14 +++++++++++ .../iter_filter/quant_expr/src/test_tf_t.adb | 14 +++++++++++ .../iter_filter/quant_expr/src/test_x_x.adb | 16 +++++++++++++ .../Ada2022/iter_filter/quant_expr/test.py | 15 ++++++++++++ .../tests/Ada2022/iter_filter/src/pkg.ads | 8 +++++++ .../Ada2022/iter_filter/src/test_pkg_0.adb | 15 ++++++++++++ .../Ada2022/iter_filter/src/test_pkg_p.adb | 16 +++++++++++++ .../Ada2022/iter_filter/src/test_pkg_z.adb | 16 +++++++++++++ .../Ada2022/iter_filter/src/test_pkg_zn.adb | 16 +++++++++++++ .../Ada2022/iter_filter/src/test_pkg_zp.adb | 16 +++++++++++++ .../Ada2022/iter_filter/src/test_pkg_zpn.adb | 16 +++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 21 ++++++++++++---- 24 files changed, 344 insertions(+), 4 deletions(-) create mode 100644 testsuite/tests/Ada2022/iter_filter/array_aggr/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/array_aggr/test.py create mode 100644 testsuite/tests/Ada2022/iter_filter/cont_aggr/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt create mode 100644 testsuite/tests/Ada2022/iter_filter/cont_aggr/test.py create mode 100644 testsuite/tests/Ada2022/iter_filter/for_loop/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/for_loop/test.py create mode 100644 testsuite/tests/Ada2022/iter_filter/quant_expr/src/foo.ads create mode 100644 testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_0.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_f_x.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_full.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_t_t.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_f.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_t.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_x_x.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/quant_expr/test.py create mode 100644 testsuite/tests/Ada2022/iter_filter/src/pkg.ads create mode 100644 testsuite/tests/Ada2022/iter_filter/src/test_pkg_0.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/src/test_pkg_p.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/src/test_pkg_z.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/src/test_pkg_zn.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/src/test_pkg_zp.adb create mode 100644 testsuite/tests/Ada2022/iter_filter/src/test_pkg_zpn.adb diff --git a/testsuite/tests/Ada2022/iter_filter/array_aggr/src/pkg.adb b/testsuite/tests/Ada2022/iter_filter/array_aggr/src/pkg.adb new file mode 100644 index 000000000..65b5b3492 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/array_aggr/src/pkg.adb @@ -0,0 +1,18 @@ +pragma Ada_2022; + +package body Pkg is + + function Non_Zero_Mult (Arr : Arr_T) return Integer is + Res : Integer := 1; -- # other_stmt + Filtered_Arr : Arr_T := -- # other_stmt + [for Element of Arr -- # other_cont + when Element < 0 or else Element > 0 -- # filter + => Element]; -- # other_cont + begin + for Element of Filtered_Arr loop -- # other_stmt + Res := Res * Element; -- # loop_body + end loop; + return Res; -- # other_stmt + end Non_Zero_Mult; + +end Pkg; diff --git a/testsuite/tests/Ada2022/iter_filter/array_aggr/test.py b/testsuite/tests/Ada2022/iter_filter/array_aggr/test.py new file mode 100644 index 000000000..ede968ea4 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/array_aggr/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of iterator filters, present +within an array aggregate. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/iter_filter/cont_aggr/src/pkg.adb b/testsuite/tests/Ada2022/iter_filter/cont_aggr/src/pkg.adb new file mode 100644 index 000000000..ad2f2fcf8 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/cont_aggr/src/pkg.adb @@ -0,0 +1,24 @@ +pragma Ada_2022; + +with Ada.Containers.Ordered_Sets; + +package body Pkg is + + package Int_Sets is new Ada.Containers.Ordered_Sets + (Element_Type => Integer); + subtype Set is Int_Sets.Set; + + function Non_Zero_Mult (Arr : Arr_T) return Integer is + Res : Integer := 1; -- # other_stmt + Filtered_Set : Set := -- # other_stmt + [for Element of Arr -- # other_cont + when Element < 0 or else Element > 0 -- # filter + => Element]; -- # other_cont + begin + for Element of Filtered_Set loop -- # other_stmt + Res := Res * Element; -- # loop_body + end loop; + return Res; -- # other_stmt + end Non_Zero_Mult; + +end Pkg; diff --git a/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt b/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt new file mode 100644 index 000000000..ab5cc641a --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt @@ -0,0 +1,2 @@ +RTS_ZFP DEAD Test uses Ada.Containers, not available in that profile +ALL XFAIL Instrument warnings due to LAL property error, see libadalang#1046 diff --git a/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.py b/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.py new file mode 100644 index 000000000..ef7b2f4be --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of iterator filters, present +within a container aggregate. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/iter_filter/for_loop/src/pkg.adb b/testsuite/tests/Ada2022/iter_filter/for_loop/src/pkg.adb new file mode 100644 index 000000000..750c18f2c --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/for_loop/src/pkg.adb @@ -0,0 +1,16 @@ +pragma Ada_2022; + +package body Pkg is + + function Non_Zero_Mult (Arr : Arr_T) return Integer is + Res : Integer := 1; -- # other_stmt + begin + for Element of Arr -- # other_stmt + when Element < 0 or else Element > 0 -- # filter + loop + Res := Res * Element; -- # loop_body + end loop; + return Res; -- # other_stmt + end Non_Zero_Mult; + +end Pkg; diff --git a/testsuite/tests/Ada2022/iter_filter/for_loop/test.py b/testsuite/tests/Ada2022/iter_filter/for_loop/test.py new file mode 100644 index 000000000..3a5aca4a9 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/for_loop/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of iterator filters, present +within a for-loop specification. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/foo.ads b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/foo.ads new file mode 100644 index 000000000..24e0eb21e --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/foo.ads @@ -0,0 +1,12 @@ +pragma Ada_2022; + +package Foo is + + type Arr_T is array (Positive range <>) of Integer; + + function All_Naturals_Are_Non_Zero (Arr : Arr_T) return Boolean is + (for all Element of Arr -- # stmt + when Element >= 0 -- # filter + => Element /= 0); -- # pred + +end Foo; diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_0.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_0.adb new file mode 100644 index 000000000..3dce55cf0 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_0.adb @@ -0,0 +1,13 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_0 is +begin + null; +end Test_0; + +--# foo.ads +-- +-- /stmt/ l- ## s- +-- /filter/ l- ## 0 +-- /pred/ l- ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_f_x.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_f_x.adb new file mode 100644 index 000000000..22ad3b942 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_f_x.adb @@ -0,0 +1,16 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_F_X is + Arr : constant Arr_T := (-1, -2, -3); +begin + -- A for all with no element passing the filter is True + + Assert (All_Naturals_Are_Non_Zero (Arr)); +end Test_F_X; + +--# foo.ads +-- +-- /stmt/ l+ ## 0 +-- /filter/ l! ## dT- +-- /pred/ l! ## d- diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_full.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_full.adb new file mode 100644 index 000000000..e93155c0f --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_full.adb @@ -0,0 +1,14 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_Full is + Arr : constant Arr_T := (1, -2, 3, 0, 9); +begin + Assert (not All_Naturals_Are_Non_Zero (Arr)); +end Test_Full; + +--# foo.ads +-- +-- /stmt/ l+ ## 0 +-- /filter/ l+ ## 0 +-- /pred/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_t_t.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_t_t.adb new file mode 100644 index 000000000..ee975106b --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_t_t.adb @@ -0,0 +1,14 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_T_T is + Arr : constant Arr_T := (1, 2, 3); +begin + Assert (All_Naturals_Are_Non_Zero (Arr)); +end Test_T_T; + +--# foo.ads +-- +-- /stmt/ l+ ## 0 +-- /filter/ l! ## dF- +-- /pred/ l! ## dF- diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_f.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_f.adb new file mode 100644 index 000000000..0a8421722 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_f.adb @@ -0,0 +1,14 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_TF_F is + Arr : constant Arr_T := (-1, -2, 0); +begin + Assert (not All_Naturals_Are_Non_Zero (Arr)); +end Test_TF_F; + +--# foo.ads +-- +-- /stmt/ l+ ## 0 +-- /filter/ l+ ## 0 +-- /pred/ l! ## dT- diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_t.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_t.adb new file mode 100644 index 000000000..34ca27a5c --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_tf_t.adb @@ -0,0 +1,14 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_TF_T is + Arr : constant Arr_T := (1, -2, 3); +begin + Assert (All_Naturals_Are_Non_Zero (Arr)); +end Test_TF_T; + +--# foo.ads +-- +-- /stmt/ l+ ## 0 +-- /filter/ l+ ## 0 +-- /pred/ l! ## dF- diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_x_x.adb b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_x_x.adb new file mode 100644 index 000000000..f8b0fcc06 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/src/test_x_x.adb @@ -0,0 +1,16 @@ +with Support; use Support; +with Foo; use Foo; + +procedure Test_X_X is + Arr : constant Arr_T := (1 .. 0 => 0); +begin + -- A for all with not elements is True + + Assert (All_Naturals_Are_Non_Zero (Arr)); +end Test_X_X; + +--# foo.ads +-- +-- /stmt/ l+ ## 0 +-- /filter/ l! ## d- +-- /pred/ l! ## d- diff --git a/testsuite/tests/Ada2022/iter_filter/quant_expr/test.py b/testsuite/tests/Ada2022/iter_filter/quant_expr/test.py new file mode 100644 index 000000000..c8f8356e4 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/quant_expr/test.py @@ -0,0 +1,15 @@ +""" +Test the correct handling and instrumentation of iterator filters, present +within a quantified expression. + +The naming convention of the test drivers is +test__.adb +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/iter_filter/src/pkg.ads b/testsuite/tests/Ada2022/iter_filter/src/pkg.ads new file mode 100644 index 000000000..0d336a916 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/pkg.ads @@ -0,0 +1,8 @@ +package pkg is + + type Arr_T is array (Positive range <>) of Integer; + + function Non_Zero_Mult (Arr : Arr_T) return Integer; + -- Returns the product of all the non-zero elements in Arr + +end pkg; diff --git a/testsuite/tests/Ada2022/iter_filter/src/test_pkg_0.adb b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_0.adb new file mode 100644 index 000000000..111b8ad78 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_0.adb @@ -0,0 +1,15 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_0 is +begin + null; +end Test_Pkg_0; + +--# pkg.adb +-- +-- /filter/ l- ## 0 +-- /loop_body/ l- ## s- +-- /other_stmt/ l- ## s- +-- /other_cont/ l- ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/src/test_pkg_p.adb b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_p.adb new file mode 100644 index 000000000..131699ab9 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_p.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_P is + Input_Arr : Arr_T := (1 => 1); +begin + Assert (Non_Zero_Mult (Input_Arr) = 1); +end Test_Pkg_P; + +--# pkg.adb +-- +-- /filter/ l! ## dF- +-- /loop_body/ l+ ## 0 +-- /other_stmt/ l+ ## 0 +-- /other_cont/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/src/test_pkg_z.adb b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_z.adb new file mode 100644 index 000000000..e6557535b --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_z.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_Z is + Input_Arr : Arr_T := (1 => 0); +begin + Assert (Non_Zero_Mult (Input_Arr) = 1); +end Test_Pkg_Z; + +--# pkg.adb +-- +-- /filter/ l! ## dT- +-- /loop_body/ l- ## s- +-- /other_stmt/ l+ ## 0 +-- /other_cont/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zn.adb b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zn.adb new file mode 100644 index 000000000..b1994c2fe --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zn.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_ZN is + Input_Arr : Arr_T := (0, -1); +begin + Assert (Non_Zero_Mult (Input_Arr) = -1); +end Test_Pkg_ZN; + +--# pkg.adb +-- +-- /filter/ l! ## c!:"Element > 0" +-- /loop_body/ l+ ## 0 +-- /other_stmt/ l+ ## 0 +-- /other_cont/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zp.adb b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zp.adb new file mode 100644 index 000000000..440f47d7c --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zp.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_ZP is + Input_Arr : Arr_T := (0, 1); +begin + Assert (Non_Zero_Mult (Input_Arr) = 1); +end Test_Pkg_ZP; + +--# pkg.adb +-- +-- /filter/ l! ## c!:"Element < 0" +-- /loop_body/ l+ ## 0 +-- /other_stmt/ l+ ## 0 +-- /other_cont/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zpn.adb b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zpn.adb new file mode 100644 index 000000000..573029470 --- /dev/null +++ b/testsuite/tests/Ada2022/iter_filter/src/test_pkg_zpn.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_ZPN is + Input_Arr : Arr_T := (0, 1, -1); +begin + Assert (Non_Zero_Mult (Input_Arr) = -1); +end Test_Pkg_ZPN; + +--# pkg.adb +-- +-- /filter/ l+ ## 0 +-- /loop_body/ l+ ## 0 +-- /other_stmt/ l+ ## 0 +-- /other_cont/ l+ ## 0 diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index e28c19ac8..bd95e4b38 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -4854,7 +4854,12 @@ package body Instrument.Ada_Unit is Extend_Statement_Sequence (UIC, N, 'F'); Process_Decisions_Defer - (ISC.As_For_Loop_Spec, 'X'); + (ISC.As_For_Loop_Spec.F_Var_Decl, 'X'); + Process_Decisions_Defer + (ISC.As_For_Loop_Spec.F_Iter_Expr, 'X'); + Process_Decisions_Defer + (ISC.As_For_Loop_Spec.F_Iter_Filter, 'W'); + end if; end if; @@ -6037,6 +6042,12 @@ package body Instrument.Ada_Unit is Process_Decisions (UIC, N.As_Quantified_Expr.F_Expr, 'W'); return Over; + when Ada_For_Loop_Spec => + Process_Decisions (UIC, N.As_For_Loop_Spec.F_Var_Decl, 'X'); + Process_Decisions (UIC, N.As_For_Loop_Spec.F_Iter_Expr, 'X'); + Process_Decisions (UIC, N.As_For_Loop_Spec.F_Iter_Filter, 'W'); + return Over; + -- Aspects for which we don't want to instrument the decision when Ada_Aspect_Assoc => @@ -6096,8 +6107,8 @@ package body Instrument.Ada_Unit is -- otherwise return Into. -- -- We know have a decision as soon as we have a logical operator (by - -- definition), an IF-expression (its condition is a decision), or a - -- quantified expression. + -- definition), an IF-expression (its condition is a decision), a + -- quantified expression or an iterator filter in a For_Loop_Spec. -- -- Do not recurse into the declarations of declare expressions as those -- are handled separately. @@ -6116,7 +6127,9 @@ package body Instrument.Ada_Unit is elsif N.Kind in Ada_Expr and then (Is_Complex_Decision (UIC, N.As_Expr) - or else N.Kind in Ada_If_Expr | Ada_Quantified_Expr_Range) + or else N.Kind in Ada_If_Expr | Ada_Quantified_Expr_Range + or else (N.Kind in Ada_For_Loop_Spec_Range + and then not N.As_For_Loop_Spec.F_Iter_Filter.Is_Null)) then return Stop; else From 99abfc34fa92cc5726e08937a2ab8dc4abb967e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 19 Jul 2023 16:02:01 +0200 Subject: [PATCH 0368/1483] Add tests for reduce attribute There is nothing special to be done to add support for the reduce attribute, so only add tests to ensure gnatcov handles this attribute with no issues, and that nested decisions in the initial value expression and in the value sequence are correctly instrumented. --- .../Ada2022/reduce_attr/shorthand/src/pkg.adb | 25 +++++++++++++++++ .../Ada2022/reduce_attr/shorthand/src/pkg.ads | 11 ++++++++ .../reduce_attr/shorthand/src/test_0.adb | 13 +++++++++ .../reduce_attr/shorthand/src/test_empty.adb | 16 +++++++++++ .../reduce_attr/shorthand/src/test_full.adb | 18 +++++++++++++ .../reduce_attr/shorthand/src/test_max.adb | 16 +++++++++++ .../reduce_attr/shorthand/src/test_sum.adb | 16 +++++++++++ .../Ada2022/reduce_attr/shorthand/test.py | 12 +++++++++ .../Ada2022/reduce_attr/value_seq/src/pkg.adb | 27 +++++++++++++++++++ .../Ada2022/reduce_attr/value_seq/src/pkg.ads | 11 ++++++++ .../reduce_attr/value_seq/src/test_0.adb | 15 +++++++++++ .../reduce_attr/value_seq/src/test_empty.adb | 18 +++++++++++++ .../reduce_attr/value_seq/src/test_full.adb | 18 +++++++++++++ .../reduce_attr/value_seq/src/test_mult.adb | 18 +++++++++++++ .../reduce_attr/value_seq/src/test_mult_z.adb | 18 +++++++++++++ .../reduce_attr/value_seq/src/test_sum.adb | 18 +++++++++++++ .../reduce_attr/value_seq/src/test_sum_z.adb | 18 +++++++++++++ .../Ada2022/reduce_attr/value_seq/test.py | 12 +++++++++ 18 files changed, 300 insertions(+) create mode 100644 testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.ads create mode 100644 testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_0.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_empty.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_full.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_max.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_sum.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/shorthand/test.py create mode 100644 testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.ads create mode 100644 testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_0.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_empty.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_full.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult_z.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum_z.adb create mode 100644 testsuite/tests/Ada2022/reduce_attr/value_seq/test.py diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.adb b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.adb new file mode 100644 index 000000000..086f373fd --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.adb @@ -0,0 +1,25 @@ +pragma Ada_2022; + +package body Pkg is + + ------------- + -- Compute -- + ------------- + + function Compute (Inp : Arr_T; Op : Op_T) return Integer is + function Reducer (Accum : Integer; Value : Integer) return Integer; + + ------------- + -- Reducer -- + ------------- + + function Reducer (Accum : Integer; Value : Integer) return Integer is + (if Op = Sum -- # reducer_main + then Accum + Value -- # reducer_cont + else Integer'Max (Accum, Value)); -- # reducer_cont + begin + return Inp'Reduce -- # reduce_st + (Reducer, (if Op = Sum then 0 else Integer'First)); -- # reduce_dc + end Compute; + +end Pkg; diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.ads b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.ads new file mode 100644 index 000000000..09c18584c --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/pkg.ads @@ -0,0 +1,11 @@ +package Pkg is + + type Arr_T is array (Positive range <>) of Integer; + + type Op_T is (Sum, Max); + + function Compute (Inp : Arr_T; Op : Op_T) return Integer; + -- Compute either the sum or the maximum of the Element in Inp based on the + -- value of Op. + +end Pkg; diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_0.adb b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_0.adb new file mode 100644 index 000000000..5d61a4327 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_0.adb @@ -0,0 +1,13 @@ +with Pkg; use Pkg; + +procedure Test_0 is +begin + null; +end Test_0; + +--# pkg.adb +-- +-- /reducer_main/ l- ## s- +-- /reducer_cont/ l- ## 0 +-- /reduce_st/ l- ## s- +-- /reduce_dc/ l- ## 0 diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_empty.adb b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_empty.adb new file mode 100644 index 000000000..cffc279da --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_empty.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Empty is + Inp : Arr_T := (1 .. 0 => 0); +begin + Assert (Compute (Inp, Sum) = 0); +end Test_Empty; + +--# pkg.adb +-- +-- /reducer_main/ l- ## s- +-- /reducer_cont/ l- ## 0 +-- /reduce_st/ l+ ## 0 +-- /reduce_dc/ l! ## dF- diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_full.adb b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_full.adb new file mode 100644 index 000000000..5925f3eb5 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_full.adb @@ -0,0 +1,18 @@ +pragma Ada_2022; + +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Full is + Inp : Arr_T := [for I in 1 .. 3 => I]; +begin + Assert (Compute (Inp, Sum) / 2 = Compute (Inp, Max)); +end Test_Full; + +--# pkg.adb +-- +-- /reducer_main/ l+ ## 0 +-- /reducer_cont/ l+ ## 0 +-- /reduce_st/ l+ ## 0 +-- /reduce_dc/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_max.adb b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_max.adb new file mode 100644 index 000000000..06711a1d0 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_max.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Max is + Inp : Arr_T := (1, 3, 2, 5, 4); +begin + Assert (Compute (Inp, Max) = 5); +end Test_Max; + +--# pkg.adb +-- +-- /reducer_main/ l! ## dT- +-- /reducer_cont/ l+ ## 0 +-- /reduce_st/ l+ ## 0 +-- /reduce_dc/ l! ## dT- diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_sum.adb b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_sum.adb new file mode 100644 index 000000000..029665404 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/src/test_sum.adb @@ -0,0 +1,16 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Sum is + Inp : Arr_T := (1, 3, 2, 5, 4); +begin + Assert (Compute (Inp, Sum) = 15); +end Test_Sum; + +--# pkg.adb +-- +-- /reducer_main/ l! ## dF- +-- /reducer_cont/ l+ ## 0 +-- /reduce_st/ l+ ## 0 +-- /reduce_dc/ l! ## dF- diff --git a/testsuite/tests/Ada2022/reduce_attr/shorthand/test.py b/testsuite/tests/Ada2022/reduce_attr/shorthand/test.py new file mode 100644 index 000000000..ae9947b1d --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/shorthand/test.py @@ -0,0 +1,12 @@ +""" +Check that gnatcov correctly processes sources containing reduce attributes, in +their shorthand form (no value sequence), and that nested decisions in the +initial value are correctly instrumented. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.adb new file mode 100644 index 000000000..5c45d1d54 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.adb @@ -0,0 +1,27 @@ +pragma Ada_2022; + +package body Pkg is + + ------------- + -- Compute -- + ------------- + + function Compute (Inp : Arr_T; Op : Op_T) return Integer is + function Reducer (Accum : Integer; Value : Integer) return Integer; + + ------------- + -- Reducer -- + ------------- + + function Reducer (Accum : Integer; Value : Integer) return Integer is + (if Op = Sum -- # reducer_main + then Accum + Value -- # reducer_cont + else Accum * Value); -- # reducer_cont + begin + return [for Elt of Inp -- # reduce_stmt + when Elt /= 0 => -- # filter + (if Op = Sum then Elt else abs Elt)]'Reduce -- # map + (Reducer, (if Op = Sum then 0 else 1)); -- # reduce_dc + end Compute; + +end Pkg; diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.ads b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.ads new file mode 100644 index 000000000..3f839aa2b --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/pkg.ads @@ -0,0 +1,11 @@ +package Pkg is + + type Arr_T is array (Positive range <>) of Integer; + + type Op_T is (Sum, Abs_Mult); + + function Compute (Inp : Arr_T; Op : Op_T) return Integer; + -- If Op is Sum, return the sum of the elements in Inp. otherwise, if Op + -- is Abs_Mult, return the product of the absolute value of the non-zero + -- elements in Inp. +end Pkg; diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_0.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_0.adb new file mode 100644 index 000000000..cd52a87b5 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_0.adb @@ -0,0 +1,15 @@ +with Pkg; use Pkg; + +procedure Test_0 is +begin + null; +end Test_0; + +--# pkg.adb +-- +-- /reducer_main/ l- ## s- +-- /reducer_cont/ l- ## 0 +-- /reduce_stmt/ l- ## s- +-- /filter/ l- ## 0 +-- /map/ l- ## 0 +-- /reduce_dc/ l- ## 0 diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_empty.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_empty.adb new file mode 100644 index 000000000..4d31520cb --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_empty.adb @@ -0,0 +1,18 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Empty is + Inp : Arr_T := (1 .. 0 => 0); +begin + Assert (Compute (Inp, Sum) = 0); +end Test_Empty; + +--# pkg.adb +-- +-- /reducer_main/ l- ## s- +-- /reducer_cont/ l- ## 0 +-- /reduce_stmt/ l+ ## 0 +-- /filter/ l! ## d- +-- /map/ l! ## d- +-- /reduce_dc/ l! ## dF- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_full.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_full.adb new file mode 100644 index 000000000..afe54634f --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_full.adb @@ -0,0 +1,18 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Empty is + Inp : Arr_T := (1, 2, 0, 3); +begin + Assert (Compute (Inp, Sum) = Compute (Inp, Abs_Mult)); +end Test_Empty; + +--# pkg.adb +-- +-- /reducer_main/ l+ ## 0 +-- /reducer_cont/ l+ ## 0 +-- /reduce_stmt/ l+ ## 0 +-- /filter/ l+ ## 0 +-- /map/ l+ ## 0 +-- /reduce_dc/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult.adb new file mode 100644 index 000000000..e7cee35db --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult.adb @@ -0,0 +1,18 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Empty is + Inp : Arr_T := (1, 2, 3); +begin + Assert (Compute (Inp, Abs_Mult) = 6); +end Test_Empty; + +--# pkg.adb +-- +-- /reducer_main/ l! ## dT- +-- /reducer_cont/ l+ ## 0 +-- /reduce_stmt/ l+ ## 0 +-- /filter/ l! ## dF- +-- /map/ l! ## dT- +-- /reduce_dc/ l! ## dT- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult_z.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult_z.adb new file mode 100644 index 000000000..a064bb905 --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult_z.adb @@ -0,0 +1,18 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Empty is + Inp : Arr_T := (1, 2, 0, 3); +begin + Assert (Compute (Inp, Abs_Mult) = 6); +end Test_Empty; + +--# pkg.adb +-- +-- /reducer_main/ l! ## dT- +-- /reducer_cont/ l+ ## 0 +-- /reduce_stmt/ l+ ## 0 +-- /filter/ l+ ## 0 +-- /map/ l! ## dT- +-- /reduce_dc/ l! ## dT- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum.adb new file mode 100644 index 000000000..86d167b1b --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum.adb @@ -0,0 +1,18 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Empty is + Inp : Arr_T := (1, 2, 3); +begin + Assert (Compute (Inp, Sum) = 6); +end Test_Empty; + +--# pkg.adb +-- +-- /reducer_main/ l! ## dF- +-- /reducer_cont/ l+ ## 0 +-- /reduce_stmt/ l+ ## 0 +-- /filter/ l! ## dF- +-- /map/ l! ## dF- +-- /reduce_dc/ l! ## dF- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum_z.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum_z.adb new file mode 100644 index 000000000..6f6dba7df --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum_z.adb @@ -0,0 +1,18 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_Empty is + Inp : Arr_T := (1, 2, 0, 3); +begin + Assert (Compute (Inp, Sum) = 6); +end Test_Empty; + +--# pkg.adb +-- +-- /reducer_main/ l! ## dF- +-- /reducer_cont/ l+ ## 0 +-- /reduce_stmt/ l+ ## 0 +-- /filter/ l+ ## 0 +-- /map/ l! ## dF- +-- /reduce_dc/ l! ## dF- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/test.py b/testsuite/tests/Ada2022/reduce_attr/value_seq/test.py new file mode 100644 index 000000000..4d9959a5c --- /dev/null +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/test.py @@ -0,0 +1,12 @@ +""" +Test checking that gnatcov correctly processes sources containing reduce +attributes, with a value sequence prefix, and that decisions withing the value +sequence are correctly instrumented. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.decision).run() +thistest.result() From e722d865a3df615dc5c1b51fd9cbf5fd4719e2c6 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 7 Aug 2023 11:10:13 +0200 Subject: [PATCH 0369/1483] Simplify the preprocessing process If there is already an instrumented version of the file being instrumented (e.g. instrumenting a main after having instrumented it as a source), pick this one rather than the original source, and consider that it has been preprocessed. --- tools/gnatcov/instrument-c.adb | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 1ab44ade9..0d41b35d6 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -313,8 +313,7 @@ package body Instrument.C is (Self : out C_Source_Rewriter; Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc; - Preprocessed : Boolean := False); + Prj : Prj_Desc); -- Start a rewriting session for the given file identified by its full -- name. -- @@ -2495,8 +2494,10 @@ package body Instrument.C is begin PP_Filename := +New_File (Prj, Filename); - -- HACK: consider that the file was already preprocessed in that case - if +PP_Filename = Filename then + -- If the preprocessed output file already exists, consider that it was + -- already preprocessed and do nothing. + + if Ada.Directories.Exists (+PP_Filename) then return; end if; @@ -2648,8 +2649,7 @@ package body Instrument.C is (Self : out C_Source_Rewriter; Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc; - Preprocessed : Boolean := False) + Prj : Prj_Desc) is PP_Filename : Unbounded_String := +Filename; @@ -2657,10 +2657,13 @@ package body Instrument.C is Args : String_Vectors.Vector; begin Import_Options (Options, Instrumenter, Prj, Filename); - if not Preprocessed then - Preprocess_Source - (Filename, Instrumenter, Prj, PP_Filename, Options); - end if; + + Preprocess_Source + (Filename, + Instrumenter, + Prj, + PP_Filename, + Options); Self.CIdx := Create_Index @@ -2987,8 +2990,7 @@ package body Instrument.C is (Self => Rewriter, Filename => +PP_Filename, Instrumenter => Self, - Prj => Prj, - Preprocessed => True); + Prj => Prj); UIC.TU := Rewriter.TU; UIC.Rewriter := Rewriter.Rewriter; Insert_Extern_Location := From 6df3cebf260964fa694faa601ef8fca3019ea910 Mon Sep 17 00:00:00 2001 From: Jerome Lambourg Date: Fri, 5 May 2023 10:27:05 +0200 Subject: [PATCH 0370/1483] Add support for out of tree instrumentation This patch adds proper handling of --relocate-build-tree and --root_dir so that it behaves similarly to gprbuild and allows generation of instrumentation out of the source tree. Fixes eng/cov/coverage#63 (cherry picked from commit bdf3852e569d86c3de8138c76894a7b5ce7fbba2) --- testsuite/SUITE/gprutils.py | 10 +++ .../modified-root-dir/opslib/src/ops.adb | 9 +++ .../modified-root-dir/opslib/src/ops.ads | 5 ++ .../modified-root-dir/test.py | 49 ++++++++++++++ .../modified-root-dir/tests/src/test_inc.adb | 7 ++ .../unmodified-root-dir/opslib/src/ops.adb | 9 +++ .../unmodified-root-dir/opslib/src/ops.ads | 5 ++ .../unmodified-root-dir/src/test_inc.adb | 7 ++ .../unmodified-root-dir/test.py | 67 +++++++++++++++++++ tools/gnatcov/command_line.ads | 25 ++++++- tools/gnatcov/project.adb | 48 +++++++++++++ tools/gnatcov/project.ads | 10 +++ tools/gnatcov/switches.adb | 15 ++++- 13 files changed, 262 insertions(+), 4 deletions(-) create mode 100644 testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.adb create mode 100644 testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.ads create mode 100644 testsuite/tests/relocate-build-tree/modified-root-dir/test.py create mode 100644 testsuite/tests/relocate-build-tree/modified-root-dir/tests/src/test_inc.adb create mode 100644 testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.adb create mode 100644 testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.ads create mode 100644 testsuite/tests/relocate-build-tree/unmodified-root-dir/src/test_inc.adb create mode 100644 testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py diff --git a/testsuite/SUITE/gprutils.py b/testsuite/SUITE/gprutils.py index d63be9ab2..97721b106 100644 --- a/testsuite/SUITE/gprutils.py +++ b/testsuite/SUITE/gprutils.py @@ -143,6 +143,8 @@ def __init__(self, units=None, no_subprojects=False, externally_built_projects=False, + relocate_build_tree=False, + root_dir=None, xvars=None, subdirs=None): """ @@ -165,6 +167,8 @@ def __init__(self, self.units = units or [] self.no_subprojects = no_subprojects self.externally_built_projects = externally_built_projects + self.relocate_build_tree = relocate_build_tree + self.root_dir = root_dir self.xvars = xvars or [] self.subdirs = subdirs @@ -182,6 +186,12 @@ def build_switches(self): if self.subdirs: switches.append('--subdirs={}'.format(self.subdirs)) + if self.relocate_build_tree: + switches.append('--relocate-build-tree') + + if self.root_dir: + switches.append('--root-dir={}'.format(self.root_dir)) + return switches @property diff --git a/testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.adb b/testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.adb new file mode 100644 index 000000000..201838d3a --- /dev/null +++ b/testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.adb @@ -0,0 +1,9 @@ +package body Ops is + procedure Apply (Op : Op_Kind; X : in out Integer) is + begin + case Op is + when Increment => X := X + 1; + when Decrement => X := X - 1; + end case; + end; +end; diff --git a/testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.ads b/testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.ads new file mode 100644 index 000000000..ec1a7e9ed --- /dev/null +++ b/testsuite/tests/relocate-build-tree/modified-root-dir/opslib/src/ops.ads @@ -0,0 +1,5 @@ +package Ops is + type Op_Kind is (Increment, Decrement); + + procedure Apply (Op : Op_Kind; X : in out Integer); +end; diff --git a/testsuite/tests/relocate-build-tree/modified-root-dir/test.py b/testsuite/tests/relocate-build-tree/modified-root-dir/test.py new file mode 100644 index 000000000..4ad78ce9a --- /dev/null +++ b/testsuite/tests/relocate-build-tree/modified-root-dir/test.py @@ -0,0 +1,49 @@ +""" +Test the behaviour of the --relocate-build-tree and -root-dir option. +""" + +import os + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.gprutils import GPRswitches + +expected_reports = { + "ops.adb.xcov": {'+': {4, 5}, '-': {6}}, + "ops.ads.xcov": {}, + } + +project_root = os.path.abspath(os.getcwd())+os.sep + +# Create ops project file +os.chdir("opslib") +extra="for Library_Dir use \"lib-opslib\";\n\ +for Library_Name use \"opslib\";" +ops_gpr = gprfor([], prjid="ops", extra=extra) + +# Create tests project file +os.chdir(os.path.join("..", "tests")) +tests_gpr = gprfor(["test_inc.adb"], prjid="tests", deps=["../opslib/ops.gpr"]) +abs_test_gpr = os.path.abspath(tests_gpr) + +os.chdir("..") + +# Build directory is relocated in tmp +wd = Wdir("tmp") +build_run_and_coverage( + gprsw=GPRswitches( + abs_test_gpr, + units=["ops"], + root_dir=project_root, + relocate_build_tree=True), + covlevel="stmt", + gpr_exe_dir=os.path.join(project_root, "tmp", "tests"), + mains=["test_inc"], + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"]) + +check_xcov_reports("*.xcov", expected_reports, "out-instr") + +wd.to_homedir() +thistest.result() diff --git a/testsuite/tests/relocate-build-tree/modified-root-dir/tests/src/test_inc.adb b/testsuite/tests/relocate-build-tree/modified-root-dir/tests/src/test_inc.adb new file mode 100644 index 000000000..d3c3ce1f2 --- /dev/null +++ b/testsuite/tests/relocate-build-tree/modified-root-dir/tests/src/test_inc.adb @@ -0,0 +1,7 @@ +with Ops; +procedure Test_Inc is + X : Integer := 4; +begin + Ops.Apply (Ops.Increment, X); + pragma Assert (X = 5); +end; diff --git a/testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.adb b/testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.adb new file mode 100644 index 000000000..201838d3a --- /dev/null +++ b/testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.adb @@ -0,0 +1,9 @@ +package body Ops is + procedure Apply (Op : Op_Kind; X : in out Integer) is + begin + case Op is + when Increment => X := X + 1; + when Decrement => X := X - 1; + end case; + end; +end; diff --git a/testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.ads b/testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.ads new file mode 100644 index 000000000..ec1a7e9ed --- /dev/null +++ b/testsuite/tests/relocate-build-tree/unmodified-root-dir/opslib/src/ops.ads @@ -0,0 +1,5 @@ +package Ops is + type Op_Kind is (Increment, Decrement); + + procedure Apply (Op : Op_Kind; X : in out Integer); +end; diff --git a/testsuite/tests/relocate-build-tree/unmodified-root-dir/src/test_inc.adb b/testsuite/tests/relocate-build-tree/unmodified-root-dir/src/test_inc.adb new file mode 100644 index 000000000..d3c3ce1f2 --- /dev/null +++ b/testsuite/tests/relocate-build-tree/unmodified-root-dir/src/test_inc.adb @@ -0,0 +1,7 @@ +with Ops; +procedure Test_Inc is + X : Integer := 4; +begin + Ops.Apply (Ops.Increment, X); + pragma Assert (X = 5); +end; diff --git a/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py new file mode 100644 index 000000000..257ef7ae0 --- /dev/null +++ b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py @@ -0,0 +1,67 @@ +""" +Test the behaviour of the --relocate-build-tree option. +""" + +import os + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.gprutils import GPRswitches + +expected_reports = { + "ops.adb.xcov": {'+': {4, 5}, '-': {6}}, + "ops.ads.xcov": {}, + } + +# Create ops project file +os.chdir("opslib") +extra="for Library_Dir use \"lib-opslib\";\n\ +for Library_Name use \"opslib\";" +ops_gpr = gprfor([], prjid="ops", extra=extra) +os.chdir("..") + +# Create tests project file +tests_gpr = gprfor(["test_inc.adb"], prjid="tests", deps=["opslib/ops.gpr"]) +abs_test_gpr = os.path.abspath(tests_gpr) + +# Build directory is relocated in tmp +wd = Wdir("tmp") +build_run_and_coverage( + gprsw=GPRswitches( + abs_test_gpr, + units=["ops"], + relocate_build_tree=True), + covlevel="stmt", + mains=["test_inc"], + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"]) + +check_xcov_reports("*.xcov", expected_reports, "out-instr") + +# Check if relative path for GPR works correctly +build_run_and_coverage( + gprsw=GPRswitches( + os.path.join("..", tests_gpr), + units=["ops"], + relocate_build_tree=True), + covlevel="stmt", + mains=["test_inc"], + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"]) + +check_xcov_reports("*.xcov", expected_reports, "out-instr") + +os.environ["GPR_PROJECT_PATH"] += os.pathsep + os.path.dirname(abs_test_gpr) +build_run_and_coverage( + gprsw=GPRswitches( + tests_gpr, + units=["ops"], + relocate_build_tree=True), + covlevel="stmt", + mains=["test_inc"], + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"]) + +check_xcov_reports("*.xcov", expected_reports, "out-instr") + +wd.to_homedir() +thistest.result() diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 4c1a0d67c..586f4c1d0 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -87,11 +87,13 @@ package Command_Line is Opt_All_Warnings, Opt_Save_Temps, Opt_SPARK_Compat, - Opt_Full_Slugs); + Opt_Full_Slugs, + Opt_Relocate_Build_Tree); -- Set of boolean options we support. More complete descriptions below. type String_Options is (Opt_Project, + Opt_Root_Dir, Opt_Subdirs, Opt_Target, Opt_Runtime, @@ -548,7 +550,14 @@ package Command_Line is (Long_Name => "--full-slugs", Help => "Use full unit slugs instead of hashes for buffer units", Commands => (Cmd_Instrument => True, others => False), - Internal => True)); + Internal => True), + + Opt_Relocate_Build_Tree => Create + (Long_Name => "--relocate-build-tree", + Help => "Relocate object, library and exec directories in the" + & " current directory.", + Commands => (Cmd_Setup => False, others => True), + Internal => False)); String_Infos : constant String_Option_Info_Array := (Opt_Project => Create @@ -562,7 +571,17 @@ package Command_Line is others => True), At_Most_Once => True, Internal => False), - Opt_Subdirs => Create + Opt_Root_Dir => Create + (Long_Name => "--root-dir", + Pattern => "[DIR]", + Help => "When --relocate-build-tree is active, this" + & " designates the topmost directory of the tree of" + & " projects. By default the root project's directory" + & " is used.", + Commands => (Cmd_Setup => False, others => True), + At_Most_Once => True, + Internal => False), + Opt_Subdirs => Create (Long_Name => "--subdirs", Pattern => "[SUBDIR]", Help => "When using project files, look for ALI/SID files in" diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index dda567487..4515b18af 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -96,6 +96,13 @@ package body Project is -- Hold the object subdirectory to use (if any) for all loaded projects. -- Should be processed each time we load a project tree. + Build_Tree_Dir : Virtual_File; + -- The root of the build tree for the loaded projects + + Root_Dir : Virtual_File; + -- The root dir of the project tree, to consider when Build_Root_Dir is + -- set. + Externally_Built_Projects_Processing_Enabled : Boolean := False; -- Whether to include projects marked as externally built to processings @@ -1262,6 +1269,18 @@ package body Project is Env.Set_Object_Subdir (+To_String (Obj_Subdir)); end if; + if Build_Tree_Dir /= No_File then + Env.Set_Build_Tree_Dir (Build_Tree_Dir.Full_Name); + + -- When the build tree directory is set, the root directory may be + -- specified explicitly from the command line. Otherwise, the project + -- file directory is used. + + if Root_Dir /= No_File then + Env.Set_Root_Dir (Root_Dir.Full_Name); + end if; + end if; + Prj_Tree := new Project_Tree; begin Prj_Tree.Load @@ -1478,6 +1497,35 @@ package body Project is Externally_Built_Projects_Processing_Enabled := True; end Enable_Externally_Built_Projects_Processing; + ----------------------------------- + -- Set_Build_Tree_Dir_To_Current -- + ----------------------------------- + + procedure Set_Build_Tree_Dir_To_Current is + begin + Build_Tree_Dir := Get_Current_Dir; + Build_Tree_Dir.Normalize_Path; + + if Env /= null then + Env.Set_Build_Tree_Dir + (Build_Tree_Dir.Full_Name); + end if; + end Set_Build_Tree_Dir_To_Current; + + ------------------ + -- Set_Root_Dir -- + ------------------ + + procedure Set_Root_Dir (Dir : String) is + begin + Root_Dir := Create (+Dir); + Root_Dir.Normalize_Path; + + if Env /= null then + Env.Set_Root_Dir (Root_Dir.Full_Name); + end if; + end Set_Root_Dir; + ------------------ -- Project_Name -- ------------------ diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 981ab4c6a..f1717c3b3 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -71,6 +71,16 @@ package Project is -- If Prj_Name maps to no loaded project, Compute_Units_Of_Interest will -- later emit an error. + procedure Set_Build_Tree_Dir_To_Current + with Pre => not Is_Project_Loaded; + -- Set the root build directory to current directory, for out of tree + -- builds. + + procedure Set_Root_Dir (Dir : String) + with Pre => not Is_Project_Loaded; + -- Set the directory to consider as topmost directory when relocating + -- the build tree. + procedure Load_Root_Project (Prj_Name : String; Target, Runtime, CGPR_File : String_Access; diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 6d6d5b325..fe1ed97f4 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -349,7 +349,8 @@ package body Switches is case Ref.Kind is when String_Opt => Complain := Ref.String_Option in - Opt_Project | Opt_Target | Opt_Runtime | Opt_Subdirs; + Opt_Project | Opt_Target | Opt_Runtime | Opt_Subdirs | + Opt_Root_Dir; when others => null; end case; @@ -409,6 +410,18 @@ package body Switches is Enable_Externally_Built_Projects_Processing; end if; + if Args.Bool_Args (Opt_Relocate_Build_Tree) then + Set_Build_Tree_Dir_To_Current; + + if Args.String_Args (Opt_Root_Dir).Present then + Set_Root_Dir (+Args.String_Args (Opt_Root_Dir).Value); + end if; + + elsif Args.String_Args (Opt_Root_Dir).Present then + Fatal_Error + ("--root-dir cannot be used without --relocate-build-tree"); + end if; + -- If the project file does not define a target, loading it needs the -- target information: load it here. Likewise for the runtime system. From e862a54acdbf02b6097132fc7568bbcec372526d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 18 Jul 2023 10:10:28 +0200 Subject: [PATCH 0371/1483] tests/97-quant_expr_in_decl: remove xfail for bin traces (cherry picked from commit 00de688a6ae58197fd830d002339b5b6e4be9e11) --- testsuite/tests/97-quant_expr_in_decl/test.opt | 1 - 1 file changed, 1 deletion(-) diff --git a/testsuite/tests/97-quant_expr_in_decl/test.opt b/testsuite/tests/97-quant_expr_in_decl/test.opt index 0f47b1b0c..bbf61ccd4 100644 --- a/testsuite/tests/97-quant_expr_in_decl/test.opt +++ b/testsuite/tests/97-quant_expr_in_decl/test.opt @@ -1,2 +1 @@ 5.04a1 DEAD Quantified expressions not supported by gnat 5.04a1 -bin-traces XFAIL Requires compiler change, will be fixed by next stable bump From 250ba640be138e1c5f9cb6d01ea6b070f8f2356c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 1 Jun 2023 16:08:30 +0000 Subject: [PATCH 0372/1483] Prepare update to LLVM 16 There were minor API refactorings, so few adaptations are required in gnatcov. (cherry picked from commit 05cef7f4db692e1ecb0e8dff1f14b214cba4b522) --- tools/gnatcov/clang-extensions.adb | 1 + tools/gnatcov/clang-extensions.ads | 5 +++-- tools/gnatcov/instrument-c.adb | 5 +++-- tools/gnatcov/instrument-c.ads | 5 +++-- tools/gnatcov/instrument-c_utils.ads | 5 +++-- 5 files changed, 13 insertions(+), 8 deletions(-) diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index c010c4b0f..c262a5440 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -20,6 +20,7 @@ -- is done for the libclang Ada bindings themselves (to avoid having to use -- the String_T type that must be memory managed by the user for instance). +with Clang.CX_File; use Clang.CX_File; with Clang.CX_String; use Clang.CX_String; with Files_Table; use Files_Table; diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index 0dc07d97f..7d652d7d4 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -22,8 +22,9 @@ with Interfaces.C; use Interfaces.C; -with Clang.Index; use Clang.Index; -with Clang.Rewrite; use Clang.Rewrite; +with Clang.CX_Source_Location; use Clang.CX_Source_Location; +with Clang.Index; use Clang.Index; +with Clang.Rewrite; use Clang.Rewrite; with Slocs; use Slocs; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 0d41b35d6..3cef48e04 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -21,8 +21,9 @@ with Ada.Containers; use Ada.Containers; with Ada.Directories; use Ada.Directories; with Ada.Text_IO; use Ada.Text_IO; -with Clang.CX_String; use Clang.CX_String; -with Clang.Extensions; use Clang.Extensions; +with Clang.CX_Diagnostic; use Clang.CX_Diagnostic; +with Clang.CX_String; use Clang.CX_String; +with Clang.Extensions; use Clang.Extensions; with GNAT.OS_Lib; use GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index f9d89c4c5..5d088faf0 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -26,8 +26,9 @@ with Ada.Strings.Unbounded.Hash; with Namet; use Namet; -with Clang.Index; use Clang.Index; -with Clang.Rewrite; use Clang.Rewrite; +with Clang.CX_Source_Location; use Clang.CX_Source_Location; +with Clang.Index; use Clang.Index; +with Clang.Rewrite; use Clang.Rewrite; with Files_Table; use Files_Table; with Instrument.Common; use Instrument.Common; diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 58155939e..616874546 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -19,8 +19,9 @@ with Ada.Containers; use Ada.Containers; with Ada.Containers.Vectors; -with Clang.Index; use Clang.Index; -with Clang.Rewrite; use Clang.Rewrite; +with Clang.CX_Source_Location; use Clang.CX_Source_Location; +with Clang.Index; use Clang.Index; +with Clang.Rewrite; use Clang.Rewrite; with Instrument.Common; use Instrument.Common; with Slocs; use Slocs; From ceafe2ee31769333104c3dc537c39cb0c3660ba5 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 16 Aug 2023 17:57:49 +0200 Subject: [PATCH 0373/1483] C++ instr: consider struct member functions --- .../stmt/StructMemberFun/src/test_struct.cpp | 20 +++++++++++++++++++ .../tests/C++/stmt/StructMemberFun/test.py | 5 +++++ tools/gnatcov/instrument-c.adb | 3 ++- 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/C++/stmt/StructMemberFun/src/test_struct.cpp create mode 100644 testsuite/tests/C++/stmt/StructMemberFun/test.py diff --git a/testsuite/tests/C++/stmt/StructMemberFun/src/test_struct.cpp b/testsuite/tests/C++/stmt/StructMemberFun/src/test_struct.cpp new file mode 100644 index 000000000..b59865918 --- /dev/null +++ b/testsuite/tests/C++/stmt/StructMemberFun/src/test_struct.cpp @@ -0,0 +1,20 @@ +struct Foo { + void bar (){ + return; // # member-fun + } +}; + +int +main (void) +{ + struct Foo foo; // # decl + foo.bar(); // # call + return 0; // # return +} + +//# test_struct.cpp +// +// /decl/ l+ ## 0 +// /member-fun/ l+ ## 0 +// /call/ l+ ## 0 +// /return/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/StructMemberFun/test.py b/testsuite/tests/C++/stmt/StructMemberFun/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/tests/C++/stmt/StructMemberFun/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 3cef48e04..9779b3783 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2363,7 +2363,8 @@ package body Instrument.C is when Cursor_Namespace | Cursor_Class_Template - | Cursor_Class_Decl => + | Cursor_Class_Decl + | Cursor_Struct_Decl => UIC.Pass.Enter_Scope (UIC, N); From 193040b9389cf85b9c3517b3743657964cdb37ef Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 17 Aug 2023 11:40:58 +0200 Subject: [PATCH 0374/1483] C instr: fix postprocessing wrt. pragma directives As a reminder, we postprocess the preprocessed code to avoid nesting in the SCOs source location (as we rely on the preprocessor line directives), e.g. when we have occurrences of the following: ``` # 1 main.c int a = foo(); // SCO #1 span is [1:14] # 1 main.c bool b = bar(); // SCO #2 span is [1:15], CONFLICT ``` we rewrite them to ``` # 1 main.c int a = foo(); bool b = bar(); // SCO #1 span is [1:14] and SCO #2 is [16:30], no conflict ``` This is proven to be an issue when there are pragma directives, e.g. ``` # 1 main.c #pragma GCC diagnostic push # 1 main.c #pragma GCC diagnostic ignored "-Wnon-null" ``` as we rewrite them to ``` # 1 main.c #pragma GCC diagnostic push#pragma GCC diagnostic ignored "-Wnon-null" ``` which is invalid code. We thus make an exception for preprocessing directives as they can't yield coverage obligations, and thus won't trigger the issue mentionned above. --- .../tests/104-pragma-directives/src/test_pragma.c | 15 +++++++++++++++ testsuite/tests/104-pragma-directives/test.py | 11 +++++++++++ tools/gnatcov/files_table.adb | 9 +++++++++ tools/gnatcov/files_table.ads | 13 +++++++++++++ 4 files changed, 48 insertions(+) create mode 100644 testsuite/tests/104-pragma-directives/src/test_pragma.c create mode 100644 testsuite/tests/104-pragma-directives/test.py diff --git a/testsuite/tests/104-pragma-directives/src/test_pragma.c b/testsuite/tests/104-pragma-directives/src/test_pragma.c new file mode 100644 index 000000000..148fde6a9 --- /dev/null +++ b/testsuite/tests/104-pragma-directives/src/test_pragma.c @@ -0,0 +1,15 @@ +#define DISABLE_WARNINGS \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") + +DISABLE_WARNINGS + +int +main () +{ + return 0; // # return +} + +//# test_pragma.c +// +// /return/ l+ ## 0 diff --git a/testsuite/tests/104-pragma-directives/test.py b/testsuite/tests/104-pragma-directives/test.py new file mode 100644 index 000000000..5bcbaf871 --- /dev/null +++ b/testsuite/tests/104-pragma-directives/test.py @@ -0,0 +1,11 @@ +""" +Check that the instrumentation of a test with pragma preprocessing directives +works fine. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 4bd99d7a8..95eabe7d1 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -2231,6 +2231,9 @@ package body Files_Table is ); + PP_Directive_Pattern : constant GNAT.Regpat.Pattern_Matcher := + Compile ("\s*#"); + Add_New_Line : Boolean := True; Line_Marker_Line : Integer; @@ -2241,6 +2244,10 @@ package body Files_Table is Current_Line : Integer := 0; -- Line and file of the currently-active line marker + PP_Directive_Matched : Boolean; + -- Whether the last line was a preprocessing directive, other than + -- a line directive. + Matches : Match_Array (0 .. 3); begin while not End_Of_File (Preprocessed_File) loop @@ -2256,6 +2263,7 @@ package body Files_Table is +Line (Matches (2).First .. Matches (2).Last); if Line_Marker_Line = Current_Line - 1 and then Line_Marker_File = Current_File + and then not PP_Directive_Matched then -- We have a spurious line marker. Remove it, and write -- the next line in continuation of the previous line. @@ -2277,6 +2285,7 @@ package body Files_Table is Put (Postprocessed_File, Line); end if; else + PP_Directive_Matched := Match (PP_Directive_Pattern, Line); if Add_New_Line then New_Line (Postprocessed_File); end if; diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 9a9aafb29..07e708bde 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -591,6 +591,19 @@ package Files_Table is -- Note that this will remove the "system header "flag (the "3" at the -- end of the line marker). We expect that this won't be a problem in -- practice. + -- + -- Important: do not do that in case the code lines are pragma directives, + -- which are preprocessor directives that are preserved by a preprocessing + -- pass, e.g. + -- # 1 main.c + -- #pragma GCC diagnostic push + -- # 1 main.c + -- #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" + -- + -- as we would otherwise produce the following (invalid) code: + -- # 1 main.c + -- #pragma GCC diagnostic push#pragma GCC diagnostic ignored \ + -- "-Wimplicit-fallthrough" private -- Describe a source file - one element per line From cbb990230ed8c3a91864c3b0bd0752ec64daa558 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 17 Aug 2023 15:14:12 +0200 Subject: [PATCH 0375/1483] CI: Remove hardcoded build space names Use the `anod eval` command to programmatically determine build space names and avoid future issues should they change again. --- .gitlab-ci.yml | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 009b482ea..1a1b5ecb5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,11 +25,9 @@ variables: then EDGE_QUALIFIER="-Qedge" EDGE_REPO_SUFFIX="-edge" - EDGE_BUILD_SPACE_SUFFIX="_edge" else EDGE_QUALIFIER="" EDGE_REPO_SUFFIX="" - EDGE_BUILD_SPACE_SUFFIX="" fi .common_anod_bits: &common_anod_bits @@ -38,6 +36,7 @@ variables: - cd /it/wave - anod tune --anod-dir /tmp/anod - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR + - GCV_INSTR_BSN=$(anod eval gnatcov -Qinstr $EDGE_QUALIFIER build_space_name) stages: - build @@ -61,8 +60,7 @@ build: - anod build --minimal gnatcov -Qinstr $EDGE_QUALIFIER # Create the package - - tar czf $PACKAGE_ABSOLUTE_NAME -C / - it/wave/x86_64-linux/gnatcov-instr$EDGE_BUILD_SPACE_SUFFIX/ + - tar czf $PACKAGE_ABSOLUTE_NAME -C / it/wave/x86_64-linux/$GCV_INSTR_BSN - cd $CI_PROJECT_DIR - ls -l $PACKAGE_BASE_NAME @@ -122,7 +120,7 @@ build_community: # download the nightly one, which may not even exist (case of an edge build # failure that was fixed on that day). - mkdir -p fingerprints - - touch fingerprints/x86_64-linux.gnatcov-instr$EDGE_BUILD_SPACE_SUFFIX.build.json.assume-unchanged + - touch fingerprints/x86_64-linux.$GCV_INSTR_BSN.build.json.assume-unchanged # Setup the CI directory to host coverage results - mkdir $CI_PROJECT_DIR/coverage @@ -150,12 +148,13 @@ test_bin_traces: # Test using anod - anod test gnatcov --target=leon3-elf -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER - - mv leon3-elf-linux64/gnatcov-O0-embedded-leon3-instr$EDGE_BUILD_SPACE_SUFFIX-test/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - TEST_BSN=$(anod eval --primitive=test gnatcov --target=leon3-elf -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER build_space_name) + - mv leon3-elf-linux64/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name bin-traces - leon3-elf-linux64/gnatcov-O0-embedded-leon3-instr$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ + leon3-elf-linux64/$TEST_BSN/results/new/ <<: *artifacts @@ -170,12 +169,13 @@ test_src_traces: # Test using anod - anod test gnatcov -Qsrc-traces,instr $EDGE_QUALIFIER - - mv x86_64-linux/gnatcov-instr-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - TEST_BSN=$(anod eval --primitive=test gnatcov -Qsrc-traces,instr $EDGE_QUALIFIER build_space_name) + - mv x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name src-traces - x86_64-linux/gnatcov-instr-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ + x86_64-linux/$TEST_BSN/results/new/ <<: *artifacts @@ -190,11 +190,12 @@ test_spark: # Test using anod - anod test gnatcov -Qspark-tests,src-traces,instr $EDGE_QUALIFIER - - mv x86_64-linux/gnatcov-instr-spark-tests-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - TEST_BSN=$(anod eval --primitive=test gnatcov -Qspark-tests,src-traces,instr $EDGE_QUALIFIER build_space_name) + - mv x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name spark - x86_64-linux/gnatcov-instr-spark-tests-src-traces$EDGE_BUILD_SPACE_SUFFIX-test/results/new/ + x86_64-linux/$TEST_BSN/results/new/ <<: *artifacts From 875c17b21969eb91b396c2374a1d08e1cee10385 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 3 Jul 2023 11:52:22 +0200 Subject: [PATCH 0376/1483] Ada 2022: add tests for raise expressions We don't have enough hindsight on the future uses of raise expressions to implement some custom handling for them in decisions. They thus currently constitute conditions which can't ever be evaluated, and will thus always trigger decision or MC/DC violations. This change adds tests to ensure gnatcov correctly handles raise expressions and checks the behavior above. This involves no modifications on the tool itself. --- testsuite/tests/Ada2022/raise_expr/extra.opt | 1 + .../raise_expr/in_expr_func/src/pkg.adb | 12 +++++++++ .../Ada2022/raise_expr/in_expr_func/test.py | 12 +++++++++ .../Ada2022/raise_expr/in_if_stmt/src/pkg.adb | 16 ++++++++++++ .../Ada2022/raise_expr/in_if_stmt/test.py | 12 +++++++++ .../raise_expr/in_ret_stmt/src/pkg.adb | 11 ++++++++ .../Ada2022/raise_expr/in_ret_stmt/test.py | 12 +++++++++ .../tests/Ada2022/raise_expr/src/pkg.ads | 9 +++++++ .../Ada2022/raise_expr/src/test_pkg_0.adb | 14 +++++++++++ .../Ada2022/raise_expr/src/test_pkg_f.adb | 15 +++++++++++ .../Ada2022/raise_expr/src/test_pkg_raise.adb | 18 +++++++++++++ .../Ada2022/raise_expr/src/test_pkg_t.adb | 15 +++++++++++ .../Ada2022/raise_expr/src/test_pkg_tf.adb | 16 ++++++++++++ .../Ada2022/raise_expr/src/test_pkg_tfr.adb | 25 +++++++++++++++++++ 14 files changed, 188 insertions(+) create mode 100644 testsuite/tests/Ada2022/raise_expr/extra.opt create mode 100644 testsuite/tests/Ada2022/raise_expr/in_expr_func/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/raise_expr/in_expr_func/test.py create mode 100644 testsuite/tests/Ada2022/raise_expr/in_if_stmt/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/raise_expr/in_if_stmt/test.py create mode 100644 testsuite/tests/Ada2022/raise_expr/in_ret_stmt/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/raise_expr/in_ret_stmt/test.py create mode 100644 testsuite/tests/Ada2022/raise_expr/src/pkg.ads create mode 100644 testsuite/tests/Ada2022/raise_expr/src/test_pkg_0.adb create mode 100644 testsuite/tests/Ada2022/raise_expr/src/test_pkg_f.adb create mode 100644 testsuite/tests/Ada2022/raise_expr/src/test_pkg_raise.adb create mode 100644 testsuite/tests/Ada2022/raise_expr/src/test_pkg_t.adb create mode 100644 testsuite/tests/Ada2022/raise_expr/src/test_pkg_tf.adb create mode 100644 testsuite/tests/Ada2022/raise_expr/src/test_pkg_tfr.adb diff --git a/testsuite/tests/Ada2022/raise_expr/extra.opt b/testsuite/tests/Ada2022/raise_expr/extra.opt new file mode 100644 index 000000000..df0cb1cfc --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/extra.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD Tests propagate exceptions diff --git a/testsuite/tests/Ada2022/raise_expr/in_expr_func/src/pkg.adb b/testsuite/tests/Ada2022/raise_expr/in_expr_func/src/pkg.adb new file mode 100644 index 000000000..98fe3f0aa --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/in_expr_func/src/pkg.adb @@ -0,0 +1,12 @@ +pragma Ada_2022; + +package body Pkg is + + -- Note: the lone parenthesis is used here to dissociate the statement from + -- the decision in the coverage reports. It is not a formatting glitch. + + function Identity (A : Boolean; Do_Raise : Boolean) return Boolean is + ( -- # stmt + (not Do_Raise or else raise Custom_Error) and then A); -- # expr :o/e: + +end Pkg; diff --git a/testsuite/tests/Ada2022/raise_expr/in_expr_func/test.py b/testsuite/tests/Ada2022/raise_expr/in_expr_func/test.py new file mode 100644 index 000000000..bce78cfc0 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/in_expr_func/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of raise expressions, +within a return statement, as part of a decision. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/raise_expr/in_if_stmt/src/pkg.adb b/testsuite/tests/Ada2022/raise_expr/in_if_stmt/src/pkg.adb new file mode 100644 index 000000000..54f79c1c6 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/in_if_stmt/src/pkg.adb @@ -0,0 +1,16 @@ +pragma Ada_2022; + +package body Pkg is + + function Identity (A : Boolean; Do_Raise : Boolean) return Boolean is + begin + if -- # stmt + (not Do_Raise or else raise Custom_Error) and then A -- # expr :o/d: + then + return True; -- # ret_true + else + return False; -- # ret_false + end if; + end Identity; + +end Pkg; diff --git a/testsuite/tests/Ada2022/raise_expr/in_if_stmt/test.py b/testsuite/tests/Ada2022/raise_expr/in_if_stmt/test.py new file mode 100644 index 000000000..aa836cd69 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/in_if_stmt/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of raise expressions, +within an expression function, as part of a decision. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/raise_expr/in_ret_stmt/src/pkg.adb b/testsuite/tests/Ada2022/raise_expr/in_ret_stmt/src/pkg.adb new file mode 100644 index 000000000..e7111ceaa --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/in_ret_stmt/src/pkg.adb @@ -0,0 +1,11 @@ +pragma Ada_2022; + +package body Pkg is + + function Identity (A : Boolean; Do_Raise : Boolean) return Boolean is + begin + return -- # stmt + (not Do_Raise or else raise Custom_Error) and then A; -- # expr :o/e: + end Identity; + +end Pkg; diff --git a/testsuite/tests/Ada2022/raise_expr/in_ret_stmt/test.py b/testsuite/tests/Ada2022/raise_expr/in_ret_stmt/test.py new file mode 100644 index 000000000..bce78cfc0 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/in_ret_stmt/test.py @@ -0,0 +1,12 @@ +""" +Test the correct handling and instrumentation of raise expressions, +within a return statement, as part of a decision. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/raise_expr/src/pkg.ads b/testsuite/tests/Ada2022/raise_expr/src/pkg.ads new file mode 100644 index 000000000..c82a842a3 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/pkg.ads @@ -0,0 +1,9 @@ +package Pkg is + + Custom_Error : Exception; + + function Identity (A : Boolean; Do_Raise : Boolean) return Boolean; + -- Returns the value of A if Do_Raise is False, raises Custom_Error + -- otherwise. + +end Pkg; diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_0.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_0.adb new file mode 100644 index 000000000..523a532f7 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_0.adb @@ -0,0 +1,14 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_0 is +begin + null; +end Test_Pkg_0; + +--# pkg.adb +-- +-- /stmt/ l- ## s- +-- /expr/ l- ## 0 +-- /ret/ l- ## s- diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_f.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_f.adb new file mode 100644 index 000000000..421e3e629 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_f.adb @@ -0,0 +1,15 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_T is +begin + Support.Assert (not Identity (A => False, Do_Raise => False)); +end Test_Pkg_T; + +--# pkg.adb +-- +-- /stmt/ l+ ## 0 +-- /expr/ l! ## oT- +-- /ret_false/ l+ ## 0 +-- /ret_true/ l- ## s- diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_raise.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_raise.adb new file mode 100644 index 000000000..1aa8769bc --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_raise.adb @@ -0,0 +1,18 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_T is +begin + Support.Assert (Identity (A => True, Do_Raise => True)); +exception + when Custom_Error => + null; +end Test_Pkg_T; + +--# pkg.adb +-- +-- /stmt/ l+ ## 0 +-- /expr/ l! ## o- +-- /ret_false/ l- ## s- +-- /ret_true/ l- ## s- diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_t.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_t.adb new file mode 100644 index 000000000..aa006f7a9 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_t.adb @@ -0,0 +1,15 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_T is +begin + Support.Assert (Identity (A => True, Do_Raise => False)); +end Test_Pkg_T; + +--# pkg.adb +-- +-- /stmt/ l+ ## 0 +-- /expr/ l! ## oF- +-- /ret_false/ l- ## s- +-- /ret_true/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tf.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tf.adb new file mode 100644 index 000000000..838d01cbe --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tf.adb @@ -0,0 +1,16 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_TF is +begin + Support.Assert (Identity (A => True, Do_Raise => False)); + Support.Assert (not Identity (A => False, Do_Raise => False)); +end Test_Pkg_TF; + +--# pkg.adb +-- +-- /stmt/ l+ ## 0 +-- /expr/ l! ## c!:"Do_Raise", c!:"raise Custom_Error" +-- /ret_false/ l+ ## 0 +-- /ret_true/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tfr.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tfr.adb new file mode 100644 index 000000000..b70147a79 --- /dev/null +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tfr.adb @@ -0,0 +1,25 @@ +with Support; + +with Pkg; use Pkg; + +procedure Test_Pkg_TF is +begin + Support.Assert (Identity (A => True, Do_Raise => False)); + Support.Assert (not Identity (A => False, Do_Raise => False)); + Support.Assert (not Identity (A => True, Do_Raise => True)); +exception + when Custom_Error => + null; +end Test_Pkg_TF; + +-- This specific test shows that, despite having a T/F pair for Do_Raise, the +-- raise expression evaluation prevents the last evaluation of the decision +-- from completing and thus we can't find a pair to show the independent +-- influence of Do_Raise. + +--# pkg.adb +-- +-- /stmt/ l+ ## 0 +-- /expr/ l! ## c!:"Do_Raise", c!:"raise Custom_Error" +-- /ret_false/ l+ ## 0 +-- /ret_true/ l+ ## 0 From 4358b97ad01867d8900570d41531e173f603850b Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 21 Aug 2023 12:12:10 +0200 Subject: [PATCH 0377/1483] Remove XFAIL + minor refactoring The gprinstall bug was probably fixed as the test is no longer failing in the src-traces configuration. --- testsuite/tests/S603-009-externally-built/test.opt | 1 - testsuite/tests/S603-009-externally-built/test.py | 9 ++------- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/testsuite/tests/S603-009-externally-built/test.opt b/testsuite/tests/S603-009-externally-built/test.opt index 4bb4b05b9..bdc588b7f 100644 --- a/testsuite/tests/S603-009-externally-built/test.opt +++ b/testsuite/tests/S603-009-externally-built/test.opt @@ -5,4 +5,3 @@ ALL DEAD -- GNAT5.04a1), and GNATcoll.projects uses it to compute environment -- information. This should be fixed when transitioning to libgpr2. 5.04a1 XFAIL Incompatibility between gnatls and GNATCOLL.Projects -src-traces XFAIL Pending resolution of gprinstall bug in V923-009 \ No newline at end of file diff --git a/testsuite/tests/S603-009-externally-built/test.py b/testsuite/tests/S603-009-externally-built/test.py index 0489d950c..30b9070d6 100644 --- a/testsuite/tests/S603-009-externally-built/test.py +++ b/testsuite/tests/S603-009-externally-built/test.py @@ -10,6 +10,7 @@ from SCOV.instr import xcov_instrument from SCOV.minicheck import build_and_run, check_xcov_reports from SUITE.context import thistest +from SUITE.control import env from SUITE.cutils import Wdir, contents_of, indent from SUITE.gprutils import GPRswitches from SUITE.tutils import gprbuild, gprinstall, xcov @@ -28,13 +29,7 @@ gpr_install_dir = os.path.join(install_dir, 'share', 'gpr') installed_mylib_gpr = os.path.join(gpr_install_dir, 'mylib.gpr') os.mkdir(install_dir) - -old_path = os.environ.get('GPR_PROJECT_PATH', '') -if old_path: - new_path = '{}{}{}'.format(gpr_install_dir, os.path.pathsep, old_path) -else: - new_path = gpr_install_dir -os.environ['GPR_PROJECT_PATH'] = new_path +env.add_search_path("GPR_PROJECT_PATH", gpr_install_dir) # Build and install the library project if thistest.options.trace_mode == 'src': From ae1ab60f7bcba12a376106737901336c84347311 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 11 Jul 2023 18:00:57 +0200 Subject: [PATCH 0378/1483] gnatcov setup: do not install sources in multiple directories Whether the gnatcov_rts is built as a static, static-pic or relocatable library does not change the set of sources. Always install it in the same directory. --- tools/gnatcov/setup_rts.adb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 2af89144e..ce005d66c 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -541,6 +541,7 @@ package body Setup_RTS is -- is installed (without the ".gpr" extension). Args.Append (+To_Lower (Project_Name)); + Args.Append (+"--sources-subdir=" & ("include" / "gnatcov_rts")); -- The project may not have been installed there yet, so ignore errors @@ -745,6 +746,11 @@ package body Setup_RTS is Install_Args.Append (+("--prefix=" & Prefix)); end if; + -- Avoid installing several time the same set of sources + + Install_Args.Append + (+"--sources-subdir=" & ("include" / Install_Name)); + -- Let the project know about its installation name Common_Args.Append From 24199f82a3ab414cc8dbcf88901ee73f2be1c8cb Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 11 Jul 2023 18:04:56 +0200 Subject: [PATCH 0379/1483] Fix outdated comment --- tools/gnatcov/instrument-c.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 9779b3783..b50a77613 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3353,7 +3353,7 @@ package body Instrument.C is I : Positive := 1; begin - -- Compute Buffers_Filenames and Buffers_Projects + -- Compute Buffers_CUs and Buffers_CU_Names for Cur in UIC.Sources_Of_Interest_Info.Iterate loop declare From 7556ee2cf90e1e227ca63a022d3b0ec860e9877e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 11 Jul 2023 17:17:23 +0200 Subject: [PATCH 0380/1483] Initial version for integrated instrumentation This commit features an initial implementation for the integrated instrumentation approach. It has a lot of limitations that are documented in the code. The major one is that it only works on native linux, with gcc. --- .../integrated_instrumentation/C++/Makefile | 11 + .../integrated_instrumentation/C++/test.cpp | 8 + .../integrated_instrumentation/C++/test.py | 55 + .../basic_lib/Makefile | 12 + .../basic_lib/lib/Makefile | 8 + .../basic_lib/lib/bar.c | 5 + .../basic_lib/lib/foo.c | 5 + .../basic_lib/main.c | 10 + .../basic_lib/test.py | 66 ++ .../basic_stmt/Makefile | 11 + .../basic_stmt/pkg.c | 5 + .../basic_stmt/test.c | 8 + .../basic_stmt/test.py | 73 ++ .../compile_and_link/pkg.c | 5 + .../compile_and_link/test.c | 8 + .../compile_and_link/test.py | 56 ++ .../integrated_instrumentation/extra.opt | 2 + tools/gnatcov/Makefile | 7 + tools/gnatcov/command_line.ads | 45 +- tools/gnatcov/compiler_wrappers-gcc.adb | 952 ++++++++++++++++++ tools/gnatcov/compiler_wrappers.ads | 22 + tools/gnatcov/files_table.adb | 1 - tools/gnatcov/files_table.ads | 4 + tools/gnatcov/gnatcov.gpr | 18 +- tools/gnatcov/gnatcov_bits_specific.adb | 35 + tools/gnatcov/instrument-c.adb | 185 ++-- tools/gnatcov/instrument-c.ads | 20 + tools/gnatcov/instrument-common.ads | 29 + tools/gnatcov/instrument-projects.adb | 18 +- tools/gnatcov/instrument-setup_config.adb | 440 ++++++++ tools/gnatcov/instrument-setup_config.ads | 62 ++ tools/gnatcov/instrument.adb | 21 + tools/gnatcov/instrument.ads | 13 +- tools/gnatcov/strings.ads | 9 + 34 files changed, 2130 insertions(+), 99 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/C++/Makefile create mode 100644 testsuite/tests/integrated_instrumentation/C++/test.cpp create mode 100644 testsuite/tests/integrated_instrumentation/C++/test.py create mode 100644 testsuite/tests/integrated_instrumentation/basic_lib/Makefile create mode 100644 testsuite/tests/integrated_instrumentation/basic_lib/lib/Makefile create mode 100644 testsuite/tests/integrated_instrumentation/basic_lib/lib/bar.c create mode 100644 testsuite/tests/integrated_instrumentation/basic_lib/lib/foo.c create mode 100644 testsuite/tests/integrated_instrumentation/basic_lib/main.c create mode 100644 testsuite/tests/integrated_instrumentation/basic_lib/test.py create mode 100644 testsuite/tests/integrated_instrumentation/basic_stmt/Makefile create mode 100644 testsuite/tests/integrated_instrumentation/basic_stmt/pkg.c create mode 100644 testsuite/tests/integrated_instrumentation/basic_stmt/test.c create mode 100644 testsuite/tests/integrated_instrumentation/basic_stmt/test.py create mode 100644 testsuite/tests/integrated_instrumentation/compile_and_link/pkg.c create mode 100644 testsuite/tests/integrated_instrumentation/compile_and_link/test.c create mode 100644 testsuite/tests/integrated_instrumentation/compile_and_link/test.py create mode 100644 testsuite/tests/integrated_instrumentation/extra.opt create mode 100644 tools/gnatcov/compiler_wrappers-gcc.adb create mode 100644 tools/gnatcov/compiler_wrappers.ads create mode 100644 tools/gnatcov/instrument-setup_config.adb create mode 100644 tools/gnatcov/instrument-setup_config.ads diff --git a/testsuite/tests/integrated_instrumentation/C++/Makefile b/testsuite/tests/integrated_instrumentation/C++/Makefile new file mode 100644 index 000000000..08f3a54de --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/C++/Makefile @@ -0,0 +1,11 @@ +CC=g++ +OBJ = test.o + +%.o: %.cpp + $(CC) -c -o $@ $< + +test: $(OBJ) + $(CC) -o $@ $^ + +clean: + rm -f *.o test diff --git a/testsuite/tests/integrated_instrumentation/C++/test.cpp b/testsuite/tests/integrated_instrumentation/C++/test.cpp new file mode 100644 index 000000000..0097946c9 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/C++/test.cpp @@ -0,0 +1,8 @@ +#include + +int +main () +{ + std::cout << "Hello, World!" << std::endl; + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/C++/test.py b/testsuite/tests/integrated_instrumentation/C++/test.py new file mode 100644 index 000000000..be75c01e7 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/C++/test.py @@ -0,0 +1,55 @@ +""" +Check the integrated instrumentation on a C++ source. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "test.cpp"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'test.cpp')}", + "--compilers=g++", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make", "test"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=test.cpp.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports("*.xcov", {"test.cpp.xcov": {"+": {6, 7}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/basic_lib/Makefile b/testsuite/tests/integrated_instrumentation/basic_lib/Makefile new file mode 100644 index 000000000..eacae9bab --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_lib/Makefile @@ -0,0 +1,12 @@ +main: main.o lib/libfoobar.a + gcc -o main main.o -Llib/ -lfoobar + +lib/libfoobar.a: + $(MAKE) -C lib + +%.o: %.c + gcc -c $< -o $@ + +clean: + rm -rf main.o + $(MAKE) -C lib clean diff --git a/testsuite/tests/integrated_instrumentation/basic_lib/lib/Makefile b/testsuite/tests/integrated_instrumentation/basic_lib/lib/Makefile new file mode 100644 index 000000000..258da872a --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_lib/lib/Makefile @@ -0,0 +1,8 @@ +libfoobar.a: foo.o bar.o + ar -rc $@ $^ + +%.o: %.c + gcc -c $< -o $@ + +clean: + rm -f foo.o bar.o libfoobar.a diff --git a/testsuite/tests/integrated_instrumentation/basic_lib/lib/bar.c b/testsuite/tests/integrated_instrumentation/basic_lib/lib/bar.c new file mode 100644 index 000000000..291781351 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_lib/lib/bar.c @@ -0,0 +1,5 @@ +int +bar () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/basic_lib/lib/foo.c b/testsuite/tests/integrated_instrumentation/basic_lib/lib/foo.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_lib/lib/foo.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/basic_lib/main.c b/testsuite/tests/integrated_instrumentation/basic_lib/main.c new file mode 100644 index 000000000..2286f6957 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_lib/main.c @@ -0,0 +1,10 @@ +extern int foo (); +extern int bar (); + +int +main () +{ + foo (); + bar (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/basic_lib/test.py b/testsuite/tests/integrated_instrumentation/basic_lib/test.py new file mode 100644 index 000000000..d782a8b39 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_lib/test.py @@ -0,0 +1,66 @@ +""" +Basic test for the integrated instrumentation approach. This test checks that +we integrate smoothly in a Makefile build process with: + * A library compiled with its own Makefile in the lib directory, producing + libfoobar.a and with foo.c and bar.c sources of interest. + * A main linked with the library (holding instrumented version of the + sources). The main is not a source of interest itself. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "main.c"), ".") +cp(os.path.join("..", "lib"), ".", recursive=True) + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'lib', 'foo.c')}", + f"--files={os.path.join(cwd, 'lib', 'bar.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make"], for_pgm=False) + +# Run the executable +cmdrun(["main"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=foo.c.sid", + "--sid=bar.c.sid", + "-axcov", + srctracename_for("main"), + ] +) +check_xcov_reports( + "*.xcov", + {"bar.c.xcov": {"+": {4}}, "foo.c.xcov": {"+": {4}}}, +) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/basic_stmt/Makefile b/testsuite/tests/integrated_instrumentation/basic_stmt/Makefile new file mode 100644 index 000000000..303dc65f8 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_stmt/Makefile @@ -0,0 +1,11 @@ +CC=gcc +OBJ = pkg.o test.o + +%.o: %.c + $(CC) -c -o $@ $< + +test: $(OBJ) + $(CC) -o $@ $^ + +clean: + rm -f *.o test diff --git a/testsuite/tests/integrated_instrumentation/basic_stmt/pkg.c b/testsuite/tests/integrated_instrumentation/basic_stmt/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_stmt/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/basic_stmt/test.c b/testsuite/tests/integrated_instrumentation/basic_stmt/test.c new file mode 100644 index 000000000..84fcd4703 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_stmt/test.c @@ -0,0 +1,8 @@ +extern int foo (); + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/basic_stmt/test.py b/testsuite/tests/integrated_instrumentation/basic_stmt/test.py new file mode 100644 index 000000000..34a22a418 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_stmt/test.py @@ -0,0 +1,73 @@ +""" +Basic test for the integrated instrumentation approach. This test checks that +we integrate smoothly in a standard (and very easy) Makefile build process, +that compiles the sources of the project, and then links. + +The integrated instrumentation process is as followed: + * The user sets up the instrumentation runtime + * The user sets up the instrumentation using the instrument-setup command. He + must indicate the list of sources of interest (through the --files switch), + the install location of the instrumentation runtime (through the + --runtime-install-dir) switch, and the list of compiler wrappers that he + wants gnatcov to generate (through the --compilers switch). + * This setup command produces compiler wrappers _and_ an instrumentation + configuration file. The user must then set his PATH to have the compiler + wrapper appear _before_ the actual compiler. + * Then, he can launch the build process unchanged. It will call the compiler + wrapper instead of the actual compiler, which will instrument on the fly. + * Running the executable should then produce a trace prefixed with the main + simple name. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "pkg.c"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'pkg.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make", "test"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=pkg.c.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports("*.xcov", {"pkg.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/compile_and_link/pkg.c b/testsuite/tests/integrated_instrumentation/compile_and_link/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/compile_and_link/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/compile_and_link/test.c b/testsuite/tests/integrated_instrumentation/compile_and_link/test.c new file mode 100644 index 000000000..84fcd4703 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/compile_and_link/test.c @@ -0,0 +1,8 @@ +extern int foo (); + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/compile_and_link/test.py b/testsuite/tests/integrated_instrumentation/compile_and_link/test.py new file mode 100644 index 000000000..7ffbdc52f --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/compile_and_link/test.py @@ -0,0 +1,56 @@ +""" +Test for the integrated instrumentation approach, where we do not split the +compilation process from the link process: both are done through one command. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources in the temporary directory +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "pkg.c"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'pkg.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the compile + link command +cmdrun(["gcc", "-o", "test", "test.c", "pkg.c"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=pkg.c.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports("*.xcov", {"pkg.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/extra.opt b/testsuite/tests/integrated_instrumentation/extra.opt new file mode 100644 index 000000000..4ce8274d5 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/extra.opt @@ -0,0 +1,2 @@ +native,linux,src-traces,!5.04a1,!7.1.2 +ALL DEAD Prototype for integrated instrumentation functional for native linux diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index d7a00b0af..d2a1918b6 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -54,6 +54,7 @@ PGMNAME=gnatcov PGMPATH=obj32/$(BUILD_MODE)/$(PGMNAME) PGM32PATH=obj32/$(BUILD_MODE)/gnatcov32 PGM64PATH=obj64/$(BUILD_MODE)/gnatcov64 +COMPILERPATH=obj64/$(BUILD_MODE)/compiler_wrappers-gcc # Directory name in the install tree DIRNAME=gnatcoverage @@ -187,11 +188,16 @@ ifdef INSTRUMENTED gnatcov instrument -j0 -P gnatcov.gpr -XPART=driver $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver \ --src-subdirs=gnatcov-instr + + gnatcov instrument -j0 -P gnatcov.gpr -XPART=compiler + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=compiler \ + --src-subdirs=gnatcov-instr else # Start with the 64-bit gnatcov, which has the largest closure $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov32 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver + $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=compiler endif ADAPTER_TARGETS=$(foreach a, $(ADAPTERS_LIST), adapter-$(a)) @@ -251,6 +257,7 @@ install-bin: $(CP) \ $(PGM32PATH)$(exeext) \ $(PGM64PATH)$(exeext) \ + $(COMPILERPATH)$(exeext) \ $(PREFIX)/libexec/gnatcoverage install-examples: diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 586f4c1d0..4519a3ed8 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -61,7 +61,8 @@ package Command_Line is Cmd_Setup, Cmd_Instrument_Project, Cmd_Instrument_Source, - Cmd_Instrument_Main); + Cmd_Instrument_Main, + Cmd_Setup_Integration); -- Set of commands we support. More complete descriptions below. type Bool_Options is @@ -161,11 +162,12 @@ package Command_Line is Opt_C_Opts, Opt_CPP_Opts, Opt_Files, - Opt_Runtime_Dir); + Opt_Runtime_Dir, + Opt_Compiler_Wrappers); -- Set of string list options we support. More complete descriptions below. subtype Cmd_Instrument is Command_Type - range Cmd_Instrument_Project .. Cmd_Instrument_Main; + range Cmd_Instrument_Project .. Cmd_Setup_Integration; package Parser is new Argparse (Command_Type, Bool_Options, String_Options, String_List_Options); @@ -374,6 +376,20 @@ package Command_Line is & " dumping coverage buffers of all of the specified" & " files (through the --files switch).", Pattern => "--files= [MAIN]", + Internal => True), + Cmd_Setup_Integration => Create + (Name => "setup-integration", + Description => + "Generate the adequate configuration to use gnatcov in integrated" + & " instrumentation mode. The files of interest must be passed" + & " through the --files switch, the compiler driver in used through" + & " the --compilers switch, the runtime installation directory" + & " through the --runtime-install-dir switch, and the configuration" + & " and compiler driver wrappers are generated in the subdirectory" + & " pointed by the --output-dir switch.", + Pattern => + "--files= --compilers=" + & " --runtime-install-dir=

[--output-dir=]", Internal => True)); Bool_Infos : constant Bool_Option_Info_Array := @@ -638,11 +654,11 @@ package Command_Line is Opt_Output_Directory => Create (Long_Name => "--output-dir", Pattern => "[SUBDIR]", - Help => "Subdirectory where XCOV or HTML report files should" - & " be produced.", + Help => "Place the output files into SUBDIR.", Commands => (Cmd_Coverage | Cmd_Instrument_Source - | Cmd_Instrument_Main => True, others => False), + | Cmd_Instrument_Main + | Cmd_Setup_Integration => True, others => False), At_Most_Once => False, Internal => False), Opt_Tag => Create @@ -1230,8 +1246,10 @@ package Command_Line is Pattern => "[FILE|@LISTFILE]", Help => "Specify a list of source files of interest by their" & " full name.", - Commands => (Cmd_Instrument_Source | Cmd_Instrument_Main => True, - others => False), + Commands => (Cmd_Instrument_Source + | Cmd_Instrument_Main + | Cmd_Setup_Integration => True, + others => False), Internal => True), Opt_Shared_Object => Create @@ -1308,7 +1326,16 @@ package Command_Line is Commands => (Cmd_Instrument_Source | Cmd_Instrument_Main => True, others => False), - Internal => True) + Internal => True), + + Opt_Compiler_Wrappers => Create + (Long_Name => "--compilers", + Pattern => "NAME", + Help => + "List of compiler drivers for which we should generate wrappers." + & " Supported compilers are: gcc.", + Commands => (others => True), + Internal => True) ); procedure Bool_Callback diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb new file mode 100644 index 000000000..98940e39f --- /dev/null +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -0,0 +1,952 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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.Command_Line; use Ada.Command_Line; +with Ada.Containers; use Ada.Containers; +with Ada.Containers.Vectors; +with Ada.Directories; use Ada.Directories; +with Ada.Environment_Variables; +with Ada.Strings; use Ada.Strings; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Text_IO; use Ada.Text_IO; + +with GNAT.OS_Lib; + +with Coverage.Tags; use Coverage.Tags; +with Files_Table; use Files_Table; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with Instrument; use Instrument; +with Instrument.C; use Instrument.C; +with Instrument.Common; use Instrument.Common; +with Instrument.Setup_Config; use Instrument.Setup_Config; +with Instrument.Source; +with Outputs; +with Paths; use Paths; +with Strings; use Strings; +with Subprocesses; use Subprocesses; +with Switches; use Switches; +with Temp_Dirs; use Temp_Dirs; +with Traces_Files; + +procedure Compiler_Wrappers.Gcc +is + type Compilation_Command_Type is record + Language : Any_Language; + -- Language of the file that is compiled + + Filename : Unbounded_String; + -- Full name of the file that is compiled + + Target : Unbounded_String; + -- Name of the output assembly file (passed through the -o switch) + + Instrumentation_Sources : String_Vectors.Vector; + -- List of sources produced by the instrumentation process. It does not + -- include the instrumented version of the source. + + end record; + -- Information relative to a compilation command launched by the compiler + -- driver. + + No_Compilation_Command : constant Compilation_Command_Type := + (Language => All_Languages, + Filename => +"", + Target => +"", + Instrumentation_Sources => String_Vectors.Empty_Vector); + + package Compilation_Command_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, Element_Type => Compilation_Command_Type); + + type Assembly_Command_Type is record + Filename : Unbounded_String; + -- Name of the assembly file (positional argument) + + Target : Unbounded_String; + -- Output object file (passed through the -o switch) + + end record; + -- Information relative to an assembly command launched by the compiler + -- driver. + + No_Assembly_Command : constant Assembly_Command_Type := + (Filename => +"", + Target => +""); + + package Assembly_Command_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, Element_Type => Assembly_Command_Type); + + type Link_Command_Type is record + Library_Dirs : String_Vectors.Vector; + -- List of library directories arguments (passed through -L switches) + + Libraries : String_Vectors.Vector; + -- List of libraries (passed through -l switches) + + Object_Files : String_Vectors.Vector; + -- List of object files (positional arguments) + + Source_Files : String_Vectors.Vector; + -- When the compiler driver command compiles and links, this contains + -- the list of files that are compiled by the compiler driver command. + + Target : Unbounded_String; + -- Output executable file (passed through the -o switch) + + end record; + -- Information relative to a link command launched by the compiler driver + + No_Link_Command : constant Link_Command_Type := + (Library_Dirs => String_Vectors.Empty_Vector, + Libraries => String_Vectors.Empty_Vector, + Object_Files => String_Vectors.Empty_Vector, + Source_Files => String_Vectors.Empty_Vector, + Target => +""); + + type Compilation_Database is record + Compilation_Commands : Compilation_Command_Vectors.Vector; + -- List of compilation commands launched by this compiler driver + -- invocation. + + Assembly_Commands : Assembly_Command_Vectors.Vector; + -- List of assembly commands launched by this compiler driver invocation + + Link_Command : Link_Command_Type := No_Link_Command; + -- List of link commands launched by this compiler driver invocation + + end record; + -- Track all of the commands launched by a compiler driver invocation + + type Parsing_Context is record + Orig_Compiler_Driver : Unbounded_String; + -- Full path to the original compiler driver + + Source_Mapping : String_Maps.Map; + -- We rely on object file symbols to know what coverage buffers we + -- should dump at link time. Nevertheless, an object file referenced in + -- a link command (which we get through the -### verbose switch) does + -- not necessarily exists yet: it can be a temporary file created by a + -- previous compilation command that belongs to the same compiler driver + -- invocation (e.g. when compiling and linking at the same time). + -- + -- To support this case, we thus need to keep track of the temporary + -- files created along the compilation process, to know to which source + -- they ultimately refer, and derive the coverage buffer symbol from it. + -- + -- The Source_Mapping thus maps the temporary object files to the + -- original source. + + Instrumentation_Objects : String_Vectors_Maps.Map; + -- Maps the original source name to the instrumentation artifact objects + -- (e.g. coverage buffers unit, dump helper unit). + + end record; + + function Starts_With + (Str : Unbounded_String; Pattern : String) return Boolean + is (Index (Str, Pattern, 1) = 1); + -- Returns whether the given Str starts with the given Pattern + + function Ends_With + (Str : Unbounded_String; Pattern : String) return Boolean + is (Length (Str) >= Pattern'Length + and then + Index + (Str, Pattern, From => Positive (Length (Str)), Going => Backward) + = + Length (Str) - Pattern'Length + 1); + -- Returns whether the given Str ends with the given Pattern + + function Split_Args (Command : String) return String_Vectors.Vector; + + function Img (Command : String_Vectors.Vector) return String; + + function Parse_Compiler_Driver_Command + (Context : in out Parsing_Context; + Tmp_Dir : Temporary_Directory; + Command : String_Vectors.Vector) return Compilation_Database; + -- Parse a compiler driver command + + function Parse_Compilation_Command + (Context : in out Parsing_Context; + Command : String_Vectors.Vector) return Compilation_Command_Type; + -- Parse a compilation command + + function Parse_Assembly_Command + (Context : in out Parsing_Context; + Command : String_Vectors.Vector) return Assembly_Command_Type; + -- Parse an assembly command + + function Parse_Link_Command + (Context : Parsing_Context; + Command : String_Vectors.Vector) return Link_Command_Type; + -- Parse a link command + + function Coverage_Buffer_Symbols + (Tmp_Dir : String; + Command : Link_Command_Type; + Compiler_Driver : String; + Config : Instrumentation_Config) return String_Sets.Set; + -- Return the list of coverage buffer symbols in the link closure + + ---------------- + -- Split_Args -- + ---------------- + + function Split_Args (Command : String) return String_Vectors.Vector + is + Arg : Unbounded_String; + Result : String_Vectors.Vector; + begin + for C of Command loop + if C = ' ' and then Arg /= "" then + Result.Append (Arg); + Arg := +""; + else + Append (Arg, C); + end if; + end loop; + if Arg /= "" then + Result.Append (Arg); + end if; + return Result; + end Split_Args; + + --------- + -- Img -- + --------- + + function Img (Command : String_Vectors.Vector) return String is + Result : Unbounded_String; + begin + for Arg of Command loop + Append (Result, Arg); + Append (Result, " "); + end loop; + return +Result; + end Img; + + ----------------------------------- + -- Parse_Compiler_Driver_Command -- + ----------------------------------- + + function Parse_Compiler_Driver_Command + (Context : in out Parsing_Context; + Tmp_Dir : Temporary_Directory; + Command : String_Vectors.Vector) return Compilation_Database + is + Result : Compilation_Database; + Parsed_Link_Command : Boolean := False; + Commands_Filename : constant String := + Tmp_Dir.Directory_Name / "commands"; + begin + -- Expand the command line using gcc's -### option. TODO??? check if + -- the command we are intercepting is a compile / link target and not + -- a preprocessing / -### action. + + declare + Arguments : String_Vectors.Vector; + begin + Arguments.Append_Vector (Command); + Arguments.Delete_First; + Arguments.Prepend (+"-###"); + Run_Command + (+Context.Orig_Compiler_Driver, + Arguments, + "gnatcov", + Output_File => Commands_Filename); + end; + + -- Then, parse the files containing the list of launched commands, using + -- the following heuristics: + -- * If the command is a cc1 invocation (first argument end with cc1), + -- assume compilation command. + -- * If the command is an as invocation, assume assembly command. + -- * If the command is a collect2 invocation, assume link command + + declare + Commands_File : File_Type; + begin + Open (Commands_File, In_File, Commands_Filename); + while not End_Of_File (Commands_File) loop + declare + Line : constant String := Get_Line (Commands_File); + Command : constant String_Vectors.Vector := Split_Args (Line); + begin + if Ends_With (Command.First_Element, "cc1") + or else Ends_With (Command.First_Element, "cc1plus") + then + declare + CC_Command : constant Compilation_Command_Type := + Parse_Compilation_Command (Context, Command); + begin + if CC_Command /= No_Compilation_Command then + Result.Compilation_Commands.Append (CC_Command); + end if; + end; + elsif Ends_With (Command.First_Element, "as") then + declare + As_Command : constant Assembly_Command_Type := + Parse_Assembly_Command (Context, Command); + begin + if As_Command /= No_Assembly_Command then + Result.Assembly_Commands.Append (As_Command); + end if; + end; + elsif Ends_With (Command.First_Element, "collect2") then + + -- Assume that we can only have a single link command. If + -- that's not the case, error out. + + if Parsed_Link_Command then + Outputs.Fatal_Error + ("The compiler driver invocation yielded several link" + & " commands, which is not supported"); + end if; + Result.Link_Command := + (Parse_Link_Command (Context, Command)); + Parsed_Link_Command := True; + end if; + end; + end loop; + end; + return Result; + end Parse_Compiler_Driver_Command; + + ------------------------------- + -- Parse_Compilation_Command -- + ------------------------------- + + function Parse_Compilation_Command + (Context : in out Parsing_Context; + Command : String_Vectors.Vector) return Compilation_Command_Type + is + use String_Vectors; + Result : Compilation_Command_Type; + Cur : Cursor := First (Command); + begin + if Ends_With (Command.First_Element, "cc1plus") then + Result.Language := CPP_Language; + elsif Ends_With (Command.First_Element, "cc1") then + Result.Language := C_Language; + end if; + + while Has_Element (Cur) loop + declare + Arg : constant Unbounded_String := + String_Vectors.Element (Cur); + begin + -- Skip switches arguments that look like filenames. Ideally, + -- we would find the positional argument but it is not + -- straightforward. + + if Arg = +"-dumpbase" or else Arg = +"-dumpbase-ext" then + Cur := Next (Cur); + end if; + + if Ends_With (Arg, ".c") + or else Ends_With (Arg, ".cc") + or else Ends_With (Arg, ".cpp") + then + if Length (Result.Filename) = 0 then + Result.Filename := +Ada.Directories.Full_Name (+Arg); + else + Outputs.Warn + ("Found multiple filenames in the compiler invocation: " + & (+Result.Filename) & " and " & (+Arg) + & ". Keeping the former, which was parsed before."); + end if; + elsif Arg = "-o" then + Result.Target := + String_Vectors.Element (String_Vectors.Next (Cur)); + end if; + end; + Cur := Next (Cur); + end loop; + + -- Error out if the parsing failed + + if Length (Result.Filename) = 0 then + Outputs.Fatal_Error + ("Could not find source file in compilation command: " + & Img (Command)); + elsif Length (Result.Target) = 0 then + Outputs.Fatal_Error + ("Could not find output file in compilation command: " + & Img (Command)); + end if; + Context.Source_Mapping.Include (Result.Target, Result.Filename); + return Result; + end Parse_Compilation_Command; + + ---------------------------- + -- Parse_Assembly_Command -- + ---------------------------- + + function Parse_Assembly_Command + (Context : in out Parsing_Context; + Command : String_Vectors.Vector) return Assembly_Command_Type + is + Result : Assembly_Command_Type; + begin + for Cur in Command.Iterate loop + declare + Arg : constant Unbounded_String := + String_Vectors.Element (Cur); + begin + if Arg = "-o" then + Result.Target := + String_Vectors.Element (String_Vectors.Next (Cur)); + elsif Ends_With (Arg, ".s") then + Result.Filename := Arg; + end if; + end; + end loop; + + -- Error out if the parsing failed + + if Length (Result.Filename) = 0 then + Outputs.Fatal_Error + ("Could not find assembly file in assembly command: " + & Img (Command)); + elsif Length (Result.Target) = 0 then + Outputs.Fatal_Error + ("Could not find output file in assembly command: " + & Img (Command)); + end if; + + -- If we do not find the original source in the mapping, assume that + -- this is not a file of interest. + + if not Context.Source_Mapping.Contains (Result.Filename) then + return No_Assembly_Command; + end if; + + Context.Source_Mapping.Insert + (Result.Target, Context.Source_Mapping.Element (Result.Filename)); + return Result; + end Parse_Assembly_Command; + + ------------------------ + -- Parse_Link_Command -- + ------------------------ + + function Parse_Link_Command + (Context : Parsing_Context; + Command : String_Vectors.Vector) return Link_Command_Type + is + use String_Vectors; + Result : Link_Command_Type; + begin + -- Find the libraries and library directories in the link command + + for Cur in Command.Iterate loop + declare + Arg : constant Unbounded_String := Element (Cur); + begin + if Arg = +"-L" then + Result.Library_Dirs.Append (Element (Next (Cur))); + elsif Starts_With (Arg, "-L") then + Result.Library_Dirs.Append + (Unbounded_Slice (Arg, 3, Length (Arg))); + elsif Arg = +"-l" then + Result.Libraries.Append (Element (Next (Cur))); + elsif Starts_With (Arg, "-l") then + Result.Libraries.Append + (Unbounded_Slice (Arg, 3, Length (Arg))); + elsif Arg = +"-o" then + Result.Target := Element (Next (Cur)); + elsif Ends_With (Arg, ".o") then + if Context.Source_Mapping.Contains (Arg) then + Result.Source_Files.Append + (Context.Source_Mapping.Element (Arg)); + else + Result.Object_Files.Append (Arg); + end if; + end if; + end; + end loop; + + if Length (Result.Target) = 0 then + Result.Target := +"a.out"; + end if; + + return Result; + end Parse_Link_Command; + + ----------------------------- + -- Coverage_Buffer_Symbols -- + ----------------------------- + + function Coverage_Buffer_Symbols + (Tmp_Dir : String; + Command : Link_Command_Type; + Compiler_Driver : String; + Config : Instrumentation_Config) return String_Sets.Set + is + function Coverage_Buffer_Symbols + (Symbol_File : String) return String_Sets.Set; + -- Return the list of coverage buffer symbols in the given symbol file + -- (object or library file). + + ----------------------------- + -- Coverage_Buffer_Symbols -- + ----------------------------- + + function Coverage_Buffer_Symbols + (Symbol_File : String) return String_Sets.Set + is + Args : String_Vectors.Vector; + Output_Filename : constant String := + Tmp_Dir / ("nm_" & Filename_Slug (Symbol_File)); + Output_File : File_Type; + + Result : String_Sets.Set; + Ignore_Success : Boolean; + + begin + -- Use the compiler nm to dump the list of symbols + + Args.Append (+"--format=just-symbol"); + Args.Append (+Symbol_File); + + -- The command can fail with e.g. "file format not recognized" for + -- system libraries. TODO???: investigate why. We should also avoid + -- invoking nm on system libraries altogether. + + Ignore_Success := + Run_Command + (Command => + +Config.Nms.Element (+Base_Name (Compiler_Driver)), + Arguments => Args, + Origin_Command_Name => "compiler wrapper", + Output_File => Output_Filename, + Ignore_Error => True); + + -- Each line of the output is a symbol + + Open (Output_File, In_File, Output_Filename); + + while not End_Of_File (Output_File) loop + declare + Line_Str : constant String := Get_Line (Output_File); + Line : constant Unbounded_String := +Line_Str; + begin + if Starts_With (Line, "gnatcov_rts_buffers") + + -- The buffer list symbols is also referenced in the link + -- closure: make sure not to pick it as it is named + -- gnatcov_rts_buffers_array_, so + -- gnatcov_rts_buffers_array_main in our case. + + and then Ends_With (Line, "_buffers") + then + Result.Insert (Line); + end if; + end; + end loop; + Close (Output_File); + return Result; + end Coverage_Buffer_Symbols; + + Result : String_Sets.Set; + + begin + -- Search through object files and libraries the list of coverage buffer + -- symbols. + + -- Start by dealing with object files + + for Object_File of Command.Object_Files loop + Result.Union (Coverage_Buffer_Symbols (+Object_File)); + end loop; + + -- Then, deal with library files + + declare + Library_Path : Unbounded_String; + begin + for Library_Dir of Command.Library_Dirs loop + Append (Library_Path, Library_Dir); + Append (Library_Path, GNAT.OS_Lib.Path_Separator); + end loop; + Append + (Library_Path, + Ada.Environment_Variables.Value ("LIBRARY_PATH", "")); + + for Library of Command.Libraries loop + declare + use type GNAT.OS_Lib.String_Access; + Library_File : GNAT.OS_Lib.String_Access := + GNAT.OS_Lib.Locate_Regular_File + ("lib" & (+Library) & ".a", +Library_Path); + begin + if Library_File /= null then + Result.Union (Coverage_Buffer_Symbols (Library_File.all)); + GNAT.OS_Lib.Free (Library_File); + end if; + end; + end loop; + end; + + -- Deal with sources that were compiled _and_ linked by the same driver + -- command. + + for Source of Command.Source_Files loop + if Switches.Files_Of_Interest.Contains (Source) then + declare + Unit : constant Compilation_Unit := + (Language => File_Based_Language, + Unit_Name => Source); + begin + Result.Insert (+Unit_Buffers_Name (Unit)); + end; + end if; + end loop; + + return Result; + end Coverage_Buffer_Symbols; + + Compiler_Wrapper_Dir : constant String := Containing_Directory + (GNAT.OS_Lib.Locate_Exec_On_Path (Command_Name).all); + -- Directory that contains the current program + + Instr_Config_File : constant String := + Compiler_Wrapper_Dir / Instrumentation_Config_Filename; + Instr_Config : Instrumentation_Config := + Load_Config (Instr_Config_File); + -- Instrumentation configuration previously generated by the setup step + + Instr_Dir : Temporary_Directory; + -- Directory holding instrumentation artefacts + + Command : String_Vectors.Vector; + -- Original compiler driver invocation + + Comp_DB : Compilation_Database; + + Prj : Prj_Desc; + -- Artificial project description to pass to the various instrumentation + -- workflows. + + Buffers_List_Unit : Compilation_Unit; + -- Name of the unit holding the buffer list definitions, if this compiler + -- driver invocation expands to a link command. + + Context : Parsing_Context; + + Compiler_Driver_Opts : String_Vectors.Vector; + -- List of options passed to the compiler driver + + Instrumented_Files : String_Sets.Set; + -- List of instrumented files (files of interest / main files / both) + +begin + Create_Temporary_Directory + (Instr_Dir, "gnatcov_instr", Auto_Delete => not Switches.Save_Temps); + + -- Set things that must be set as we don't go through gnatcov_bits_specific + + Tag_Provider := Tag_Providers.Create (Default_Tag_Provider_Name); + Traces_Files.Update_Current_Trace_Kind (Traces_Files.Source_Trace_File); + + -- Load the command line + + Command.Append (+Command_Name); + for I in 1 .. Argument_Count loop + Compiler_Driver_Opts.Append (+Argument (I)); + end loop; + Command.Append_Vector (Compiler_Driver_Opts); + + Context.Orig_Compiler_Driver := + Instr_Config.Compiler_Drivers.Element + (+Ada.Directories.Simple_Name (Command_Name)); + + -- Parse the compiler driver invocation + + Comp_DB := Parse_Compiler_Driver_Command (Context, Instr_Dir, Command); + + -- Generate an artificial project description to pass compiler + -- switches and default spec / body suffixes. + + Prj.Prj_Name := +"main"; + Prj.Output_Dir := +Instr_Dir.Directory_Name; + Prj.Spec_Suffix := + (C_Language => +".h", CPP_Language => +".hh", others => <>); + Prj.Body_Suffix := + (C_Language => +".c", CPP_Language => +".cc", others => <>); + Prj.Compiler_Driver := (others => Context.Orig_Compiler_Driver); + Prj.Compiler_Options := (others => Compiler_Driver_Opts); + + -- Then, invoke the right set of gnatcov commands + + -- Start by the compilation command: for each compilation command, we + -- must instrument its source and substitute on the command line the + -- original file with its instrumented version. + + for Cur in Comp_DB.Compilation_Commands.Iterate loop + declare + use Compilation_Command_Vectors; + Comp_Command : constant Compilation_Command_Type := Element (Cur); + Comp_Command_Ref : constant Reference_Type := + Comp_DB.Compilation_Commands.Reference (Cur); + Instrumenter : Language_Instrumenter'Class := + (case Comp_Command.Language is + when C_Language => Create_C_Instrumenter (Instr_Config.Tag), + when CPP_Language => Create_CPP_Instrumenter (Instr_Config.Tag), + when others => + raise Program_Error + with "Unsupported language for integrated" + & " instrumentation"); + + Fullname : constant String := + Ada.Directories.Full_Name (+Comp_Command.Filename); + Simple_Name : constant String := + Ada.Directories.Simple_Name (+Comp_Command.Filename); + Instr_Name : constant String := (+Prj.Output_Dir) / Simple_Name; + + begin + -- Start by instrumenting the file as a source, if it is a unit of + -- interest. + + if Files_Of_Interest.Contains (+Fullname) then + + -- Pass the compiler switches through the project description + + Instrument.Source + (Instrumenter => Instrumenter, + Files_Of_Interest => Switches.Files_Of_Interest, + Prj => Prj, + Unit_Name => Fullname, + + -- Generate all the SID files under the same directory as the + -- compiler wrapper as they must persist. TODO???: deal with + -- homonym files in SID names. + + SID_Name => Compiler_Wrapper_Dir / (Simple_Name & ".sid")); + + Comp_Command_Ref.Instrumentation_Sources.Append + (Instrumenter.Buffer_Unit + (Compilation_Unit' + (File_Based_Language, Comp_Command.Filename), + Prj) + .Unit_Name); + Instrumented_Files.Include (+Fullname); + end if; + + -- Then, instrument it as a main if it is one + + if Instrumenter.Has_Main (Fullname, Prj) then + + -- Pick as the trace name prefix the base name of the main + -- filename + + if Instr_Config.Dump_Config.Channel = Binary_File then + Instr_Config.Dump_Config.Filename_Prefix := + +Ada.Directories.Base_Name (Fullname); + end if; + + Instrumenter.Auto_Dump_Buffers_In_Main + (Instr_Name, Instr_Config.Dump_Config, Prj); + Comp_Command_Ref.Instrumentation_Sources.Append + (Instrumenter.Dump_Helper_Unit + (Compilation_Unit' + (File_Based_Language, +Instr_Name), + Prj) + .Unit_Name); + Instrumented_Files.Include (+Fullname); + end if; + end; + end loop; + + -- Then, deal with the link command + + if Comp_DB.Link_Command /= No_Link_Command then + declare + Instrumenter : constant Language_Instrumenter'Class := + Create_C_Instrumenter (Instr_Config.Tag); + -- Emit the buffers list unit as a C compilation unit as it is + -- compilable by a C / C++ compiler, which are the languages + -- supported by the integrated instrumentation scheme. + + Buffer_Symbols : constant String_Sets.Set := + Coverage_Buffer_Symbols + (Tmp_Dir => +Prj.Output_Dir, + Command => Comp_DB.Link_Command, + Compiler_Driver => Command_Name, + Config => Instr_Config); + begin + Buffers_List_Unit := + Instrumenter.Emit_Buffers_List_Unit + (Buffer_Symbols, + Prj); + end; + end if; + + -- Now that we have all of the instrumentation artifacts, launch the + -- original compiler driver command. + + declare + Output_Dir : constant String := +Prj.Output_Dir; + New_Args : String_Vectors.Vector := Command.Copy; + begin + New_Args.Delete_First; + + New_Args.Prepend ("-I" & Instr_Config.GNATcov_RTS_Include_Dir); + + if Comp_DB.Link_Command /= No_Link_Command then + New_Args.Append (+"-lgnatcov_rts"); + New_Args.Prepend ("-L" & Instr_Config.GNATcov_RTS_Object_Dir); + end if; + + -- Start with adding the buffer list unit (if it was emitted) to the + -- compilation closure. + + if Length (Buffers_List_Unit.Unit_Name) /= 0 then + New_Args.Prepend (Buffers_List_Unit.Unit_Name); + end if; + + -- Then, substitute files of interest with their instrumented version, + -- which were generated in Prj.Output_Dir. + + for I in 0 .. Natural (String_Vectors.Length (New_Args) - 1) loop + declare + Arg : constant Unbounded_String := New_Args.Element (I); + begin + if Ada.Directories.Exists (+Arg) then + declare + Base : constant String := Simple_Name (+Arg); + Fullname : constant String := Full_Name (+Arg); + begin + if Instrumented_Files.Contains (+Fullname) then + New_Args.Replace_Element (I, +(Output_Dir / Base)); + end if; + end; + end if; + end; + end loop; + + -- Deal with the instrumentation artifacts + + for Cur in Comp_DB.Compilation_Commands.Iterate loop + declare + use Compilation_Command_Vectors; + Comp_Command : constant Compilation_Command_Type := Element (Cur); + begin + -- If this is a link command, add the instrumentation artifacts + -- to the compiler driver command + + if Comp_DB.Link_Command /= No_Link_Command then + for Instr_Artifact of Comp_Command.Instrumentation_Sources loop + New_Args.Prepend (Instr_Artifact); + end loop; + + -- Otherwise, compile the instrumentation artifacts and package + -- them later with the instrumented source object file once we + -- assemble it. + + else + Context.Instrumentation_Objects.Insert + (Comp_Command.Filename, String_Vectors.Empty); + + for Instr_Artifact of Comp_Command.Instrumentation_Sources loop + declare + Args_Compilation : String_Vectors.Vector; + Instr_Artifact_Object_Name : constant String := + New_File + (Prj, + Ada.Directories.Base_Name (+Instr_Artifact) & ".o"); + begin + Args_Compilation.Append (+"-c"); + Args_Compilation.Append + ("-I" & Instr_Config.GNATcov_RTS_Include_Dir); + Args_Compilation.Append (Instr_Artifact); + Args_Compilation.Append (+"-o"); + Args_Compilation.Append (+Instr_Artifact_Object_Name); + Run_Command + (Command => +Context.Orig_Compiler_Driver, + Arguments => Args_Compilation, + Origin_Command_Name => "compiler wrapper"); + + Context.Instrumentation_Objects + .Reference (Comp_Command.Filename) + .Append (+Instr_Artifact_Object_Name); + end; + end loop; + end if; + end; + end loop; + + -- Finally, run the alternate compiler driver invocation + + Run_Command + (Command => +Context.Orig_Compiler_Driver, + Arguments => New_Args, + Origin_Command_Name => "compiler"); + + if Comp_DB.Link_Command = No_Link_Command then + + -- Merge coverage buffer object files with instrumented files for + -- each assembly command. + + for Assembly_Command of Comp_DB.Assembly_Commands loop + if Context.Source_Mapping.Contains (Assembly_Command.Filename) then + declare + Orig_Source : constant Unbounded_String := + Context.Source_Mapping.Element (Assembly_Command.Filename); + Instr_Objects : constant String_Vectors.Vector := + Context.Instrumentation_Objects.Element (Orig_Source); + Packaged_Name : constant String := + New_File + (Prj, "instr_" & Filename_Slug (+Orig_Source) & ".a"); + Success : Boolean; + begin + if not Instr_Objects.Is_Empty then + declare + Args_Ld : String_Vectors.Vector; + begin + Args_Ld.Append (+"-r"); + Args_Ld.Append_Vector (Instr_Objects); + Args_Ld.Append (Assembly_Command.Target); + Args_Ld.Append (+"-o"); + Args_Ld.Append (+Packaged_Name); + Run_Command + (Command => + +Instr_Config.Linkers.Element + (+Base_Name (Command_Name)), + Arguments => Args_Ld, + Origin_Command_Name => "compiler wrapper"); + + -- Finally, replace the original object file with + -- the newly created library file, packaging both + -- the instrumented source and its coverage buffer. + + GNAT.OS_Lib.Copy_File + (Packaged_Name, + +Assembly_Command.Target, + Success, + Mode => GNAT.OS_Lib.Overwrite, + Preserve => GNAT.OS_Lib.Full); + end; + end if; + end; + end if; + end loop; + end if; + end; + +end Compiler_Wrappers.Gcc; diff --git a/tools/gnatcov/compiler_wrappers.ads b/tools/gnatcov/compiler_wrappers.ads new file mode 100644 index 000000000..92258e3a9 --- /dev/null +++ b/tools/gnatcov/compiler_wrappers.ads @@ -0,0 +1,22 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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. -- +------------------------------------------------------------------------------ + +-- This package contains common declaration for compiler wrappers + +package Compiler_Wrappers is +end Compiler_Wrappers; diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 95eabe7d1..3e5b8b95a 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -36,7 +36,6 @@ with Coverage; use Coverage; with Outputs; with Perf_Counters; use Perf_Counters; with Project; -with Strings; with Switches; package body Files_Table is diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 07e708bde..aa361f075 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -32,6 +32,7 @@ with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Paths; use Paths; with SC_Obligations; use SC_Obligations; with Slocs; use Slocs; +with Strings; with Traces_Elf; use Traces_Elf; with Traces_Dbase; use Traces_Dbase; with Traces_Stats; use Traces_Stats; @@ -330,6 +331,9 @@ package Files_Table is function "=" (L, R : Compilation_Unit) return Boolean is (Image (L) = Image (R)); + No_Compilation_Unit : constant Compilation_Unit := + (Language => File_Based_Language, Unit_Name => Strings."+" ("")); + package Unit_Sets is new Ada.Containers.Ordered_Sets (Element_Type => Compilation_Unit); diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 3a79dda86..001d3cba3 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -24,7 +24,8 @@ project Gnatcov is -- Mandatory externals -- ------------------------- - type Part_Type is ("lib32", "lib64", "driver", "gnatcov32", "gnatcov64"); + type Part_Type is + ("lib32", "lib64", "driver", "gnatcov32", "gnatcov64", "compiler"); Part : Part_Type := external ("PART"); -- Which program this project should build: -- @@ -37,6 +38,9 @@ project Gnatcov is -- * "gnatcov32": the homonym program, for everything that needs to deal -- with binary traces of 32-bit programs. -- + -- * "compiler": a compiler wrapper executable, used to implement the + -- integrated instrumentation approach. + -- -- * "gnatcov64": the homonym program, for everything else. Binutils_Src_Dir := external ("BINUTILS_SRC_DIR"); @@ -59,7 +63,7 @@ project Gnatcov is -- "gnatcov64" configuration. case Part is - when "gnatcov64" => null; + when "gnatcov64" | "compiler" => null; when others => C_Support := "False"; end case; @@ -84,8 +88,8 @@ project Gnatcov is type Bits_Type is ("32", "64"); Bits : Bits_Type := "32"; case Part is - when "lib64" | "gnatcov64" => Bits := "64"; - when "driver" | "lib32" | "gnatcov32" => Bits := "32"; + when "lib64" | "gnatcov64" | "compiler" => Bits := "64"; + when "driver" | "lib32" | "gnatcov32" => Bits := "32"; end case; ------------------------------------------- @@ -111,7 +115,7 @@ project Gnatcov is use "instrument-ada_unit__stub.adb"; for Body ("Instrument.C") use "instrument-c__stub.adb"; for Specification ("Instrument.C") use "instrument-c__stub.ads"; - when "gnatcov64" => + when "gnatcov64" | "compiler" => null; end case; @@ -175,6 +179,8 @@ project Gnatcov is for Main use ("gnatcov.adb"); when "gnatcov32" | "gnatcov64" => for Main use ("gnatcov_bits_specific.adb"); + when "compiler" => + for Main use ("compiler_wrappers-gcc.adb"); end case; package Builder is @@ -274,7 +280,7 @@ project Gnatcov is Object_Dir := ""; case Part is when "driver" | "lib32" | "gnatcov32" => Object_Dir := "obj32"; - when "gnatcov64" => Object_Dir := "obj64"; + when "gnatcov64" | "compiler" => Object_Dir := "obj64"; -- gnatcov64 uses the real instrumenter.adb while lib64 uses the stub -- one, so they cannot use the same object directory. diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index defcab5a2..5a1ec80a3 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -62,6 +62,7 @@ with Instrument.Common; use Instrument.Common; with Instrument.Config; with Instrument.Main; with Instrument.Projects; +with Instrument.Setup_Config; with Instrument.Source; with Instrument.Input_Traces; with Object_Locations; @@ -105,6 +106,7 @@ procedure GNATcov_Bits_Specific is SID_Inputs : Inputs.Inputs_Type; Ignored_Source_Files : Inputs.Inputs_Type; Files_Of_Interest : Inputs.Inputs_Type; + Compiler_Drivers : Inputs.Inputs_Type; Source_Rebase_Inputs : Inputs.Inputs_Type; Source_Search_Inputs : Inputs.Inputs_Type; Text_Start : Pc_Type := 0; @@ -489,6 +491,7 @@ procedure GNATcov_Bits_Specific is Copy_Arg_List (Opt_Ignore_Source_Files, Ignored_Source_Files); Copy_Arg_List (Opt_Files, Files_Of_Interest); + Copy_Arg_List (Opt_Compiler_Wrappers, Compiler_Drivers); Switches.Files_Of_Interest := To_String_Set (Files_Of_Interest); -- Compute the languages for which we want coverage analysis, or enable @@ -1362,6 +1365,38 @@ begin Mains => Args.Remaining_Args); end; + when Cmd_Setup_Integration => + declare + -- Try to load the setup config from metadata installed with + -- instrumentation runtime, and from there, decode the --dump-* + -- options. + + Runtime_Project : constant String := + Value (Args, Opt_Runtime_Project, "gnatcov_rts"); + + Setup_Cfg : constant Setup_Config := Load + ("", + "", + Value (Args, Opt_Config), + Runtime_Project); + -- TODO???: we should not leave the target and runtime empty, but + -- we have no project to load here. + + Dump_Config : constant Any_Dump_Config := + Load_Dump_Config (Setup_Cfg.Default_Dump_Config); + + Compiler_Drivers_Set : constant String_Sets.Set := + To_String_Set (Compiler_Drivers); + + begin + Instrument.Setup_Config.Generate_Config + (Files_Of_Interest => Switches.Files_Of_Interest, + Coverage_Level => Coverage_Option_Value, + Dump_Config => Dump_Config, + Compiler_Drivers => Compiler_Drivers_Set, + Output_Dir => Get_Output_Dir); + end; + when Cmd_Instrument_Source => -- For the instrument-source command, and for the instrument-main, -- we do not check the command-line semantics as these commands are diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index b50a77613..b01edbb64 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -316,11 +316,7 @@ package body Instrument.C is Instrumenter : C_Family_Instrumenter_Type'Class; Prj : Prj_Desc); -- Start a rewriting session for the given file identified by its full - -- name. - -- - -- If Preprocessed is set to True, consider that the file was preprocessed - -- beforehand. Otherwise, generate a preprocessed version of it in - -- Info.Output_Dir and start a rewriting session on the latter. + -- name. If not already done, preprocess it beforehand. procedure Run_Diagnostics (TU : Translation_Unit_T); -- Output clang diagnostics on the given translation unit @@ -2653,7 +2649,7 @@ package body Instrument.C is Instrumenter : C_Family_Instrumenter_Type'Class; Prj : Prj_Desc) is - PP_Filename : Unbounded_String := +Filename; + PP_Filename : Unbounded_String; Options : Analysis_Options; Args : String_Vectors.Vector; @@ -2821,7 +2817,7 @@ package body Instrument.C is Prj : Prj_Desc; Files_Of_Interest : String_Sets.Set) is - UIC : C_Unit_Inst_Context; + UIC : C_Unit_Inst_Context; CU_Name : constant Compilation_Unit_Part := CU_Name_For_File (+Unit_Name); @@ -2830,12 +2826,8 @@ package body Instrument.C is -- Respectively original, and preprocessed filename Buffer_Filename : constant String := - New_File - (Prj, - To_Symbol_Name (Sys_Prefix) & "_b_" - & Instrumented_Unit_Slug (CU_Name) - & (+Prj.Body_Suffix - (C_Family_Instrumenter_Type'Class (Self).Language))); + +Self.Buffer_Unit + (Compilation_Unit'(File_Based_Language, +Unit_Name), Prj).Unit_Name; -- Name of the generated source file holding the coverage buffers Rewriter : C_Source_Rewriter; @@ -2918,7 +2910,11 @@ package body Instrument.C is Import_Options (UIC.Options, Self, Prj, Unit_Name); Preprocess_Source - (Orig_Filename, Self, Prj, PP_Filename, UIC.Options); + (Orig_Filename, + Self, + Prj, + PP_Filename, + UIC.Options); -- Start by recording preprocessing information @@ -3597,11 +3593,9 @@ package body Instrument.C is begin -- Create the name of the helper unit - Helper_Unit := - To_Symbol_Name (Sys_Prefix) - & "_d_" - & Instrumented_Unit_Slug (Main) - & Prj.Body_Suffix (Instrumenter.Language); + Helper_Unit := Instrumenter.Dump_Helper_Unit + (Compilation_Unit'(File_Based_Language, Main.Filename), + Prj).Unit_Name; -- Compute the qualified names we need for instrumentation @@ -3879,6 +3873,75 @@ package body Instrument.C is Rew.Apply; end Auto_Dump_Buffers_In_Main; + ----------------- + -- Buffer_Unit -- + ----------------- + + function Buffer_Unit + (Self : C_Family_Instrumenter_Type; + CU : Compilation_Unit; + Prj : Prj_Desc) return Compilation_Unit + is + Filename : constant String := + New_File + (Prj, + To_Symbol_Name (Sys_Prefix) & "_b_" + & Filename_Slug (+CU.Unit_Name) + & (+Prj.Body_Suffix + (C_Family_Instrumenter_Type'Class (Self).Language))); + begin + return Compilation_Unit' + (Language => File_Based_Language, + Unit_Name => +Filename); + end Buffer_Unit; + + ---------------------- + -- Dump_Helper_Unit -- + ---------------------- + + overriding function Dump_Helper_Unit + (Self : C_Family_Instrumenter_Type; + CU : Compilation_Unit; + Prj : Prj_Desc) return Compilation_Unit + is + Filename : constant String := + New_File + (Prj, + To_Symbol_Name (Sys_Prefix) + & "_d_" + & Filename_Slug (+CU.Unit_Name) + & (+Prj.Body_Suffix + (C_Family_Instrumenter_Type'Class (Self).Language))); + begin + return Compilation_Unit' + (Language => File_Based_Language, + Unit_Name => +Filename); + end Dump_Helper_Unit; + + -------------- + -- Has_Main -- + -------------- + + overriding function Has_Main + (Self : in out C_Family_Instrumenter_Type; + Filename : String; + Prj : Prj_Desc) return Boolean + is + Rew : C_Source_Rewriter; + + Main_Cursor : Cursor_T; + -- Cursor of the main declaration + + begin + Rew.Start_Rewriting (Filename, Self, Prj); + Main_Cursor := Get_Main (Rew.TU); + if Main_Cursor = Get_Null_Cursor then + return False; + else + return True; + end if; + end Has_Main; + ---------------- -- Format_Def -- ---------------- @@ -4007,73 +4070,81 @@ package body Instrument.C is (Format_Extern_Decl (Instrumenter, C_Type, Name, Func_Args)); end Put_Extern_Decl; + ---------------------------- + -- Emit_Buffers_List_Unit -- + ---------------------------- + overriding procedure Emit_Buffers_List_Unit (Self : C_Family_Instrumenter_Type; Instr_Units : Unit_Sets.Set; Prj : Prj_Desc) is - Base_Filename : constant String := - "gcvrtc-" & (+Prj.Prj_Name); - CU_Name_Body : constant String := - Base_Filename - & (+Prj.Body_Suffix - (C_Family_Instrumenter_Type'Class (Self).Language)); - CU_Name_Header : constant String := - Base_Filename - & (+Prj.Spec_Suffix - (C_Family_Instrumenter_Type'Class (Self).Language)); - - File_Body : Text_Files.File_Type; - File_Header : Text_Files.File_Type; + Buffer_Symbols : String_Sets.Set; + Ignore_CU : Compilation_Unit; + begin + for Instr_Unit of Instr_Units loop + Buffer_Symbols.Insert (+Unit_Buffers_Name (Instr_Unit)); + end loop; + Ignore_CU := + C_Family_Instrumenter_Type'Class (Self).Emit_Buffers_List_Unit + (Buffer_Symbols => Buffer_Symbols, Prj => Prj); + end Emit_Buffers_List_Unit; + + overriding function Emit_Buffers_List_Unit + (Self : C_Family_Instrumenter_Type; + Buffer_Symbols : String_Sets.Set; + Prj : Prj_Desc) return Compilation_Unit + is + CU_Name : constant Compilation_Unit := + (Language => File_Based_Language, + Unit_Name => + +New_File + (Prj, + "gcvrtc-" & (+Prj.Prj_Name) + & (+Prj.Body_Suffix + (C_Family_Instrumenter_Type'Class (Self).Language)))); + + CU_File : Text_Files.File_Type; Buffer_Array_Decl : constant String := "const struct gnatcov_rts_coverage_buffers_group_array " & Unit_Buffers_Array_Name (+Prj.Prj_Name); Buffer_Unit_Length : constant String := - Count_Type'Image (Instr_Units.Length); + Count_Type'Image (Buffer_Symbols.Length); begin -- Emit the body to contain the list of buffers - Create_File (Prj, File_Body, CU_Name_Body); + CU_File.Create (+CU_Name.Unit_Name); - File_Body.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); + CU_File.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); -- First create extern declarations for the buffers group of each unit - for Instr_Unit of Instr_Units loop + for BS of Buffer_Symbols loop Put_Extern_Decl - (File_Body, + (CU_File, Self, "const struct gnatcov_rts_coverage_buffers_group", - Unit_Buffers_Name (Instr_Unit)); + +BS); end loop; -- Then create an extern declaration for the buffer array (necessary in -- C++ to set the C linkage), and finally the definition for that array. - File_Body.Put_Line (Self.Extern_Prefix & Buffer_Array_Decl & ";"); - File_Body.Put_Line (Buffer_Array_Decl & " = {"); - File_Body.Put_Line (" " & Buffer_Unit_Length & ","); - File_Body.Put_Line + CU_File.Put_Line (Self.Extern_Prefix & Buffer_Array_Decl & ";"); + CU_File.Put_Line (Buffer_Array_Decl & " = {"); + CU_File.Put_Line (" " & Buffer_Unit_Length & ","); + CU_File.Put_Line (" (const struct gnatcov_rts_coverage_buffers_group *[]) {"); - for Instr_Unit of Instr_Units loop - File_Body.Put (" &" & Unit_Buffers_Name (Instr_Unit)); - if Instr_Unit = Instr_Units.Last_Element then - File_Body.Put_Line ("}};"); + for BS of Buffer_Symbols loop + CU_File.Put (" &" & (+BS)); + if BS = Buffer_Symbols.Last_Element then + CU_File.Put_Line ("}};"); else - File_Body.Put_Line (","); + CU_File.Put_Line (","); end if; end loop; - - -- Emit the extern declaration of the buffers array in the header file - - Create_File (Prj, File_Header, CU_Name_Header); - - Put_Extern_Decl - (File_Header, - Self, - "const struct gnatcov_rts_coverage_buffers_group_array", - Unit_Buffers_Array_Name (+Prj.Prj_Name)); + return CU_Name; end Emit_Buffers_List_Unit; ---------------- diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 5d088faf0..7358dc367 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -57,6 +57,26 @@ package Instrument.C is Instr_Units : Unit_Sets.Set; Prj : Prj_Desc); + overriding function Emit_Buffers_List_Unit + (Self : C_Family_Instrumenter_Type; + Buffer_Symbols : String_Sets.Set; + Prj : Prj_Desc) return Compilation_Unit; + + overriding function Buffer_Unit + (Self : C_Family_Instrumenter_Type; + CU : Compilation_Unit; + Prj : Prj_Desc) return Compilation_Unit; + + overriding function Dump_Helper_Unit + (Self : C_Family_Instrumenter_Type; + CU : Compilation_Unit; + Prj : Prj_Desc) return Compilation_Unit; + + overriding function Has_Main + (Self : in out C_Family_Instrumenter_Type; + Filename : String; + Prj : Prj_Desc) return Boolean; + function Extern_Prefix (Self : C_Family_Instrumenter_Type) return String is ("extern "); diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index dc050968d..7f9b556fa 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -419,6 +419,35 @@ package Instrument.Common is -- function. This procedure should thus be called only once, for one of -- the supported languages of the project. + function Emit_Buffers_List_Unit + (Self : Language_Instrumenter; + Buffer_Symbols : String_Sets.Set; + Prj : Prj_Desc) return Compilation_Unit + is (No_Compilation_Unit); + -- Same as above except Buffer_Symbols contains the list of C symbols + -- holding coverage buffers for units of interest. Return the buffers list + -- compilation unit. + + function Buffer_Unit + (Self : Language_Instrumenter; + CU : Compilation_Unit; + Prj : Prj_Desc) return Compilation_Unit + is (No_Compilation_Unit); + -- Return the compilation unit holding coverage buffers + + function Dump_Helper_Unit + (Self : Language_Instrumenter; + CU : Compilation_Unit; + Prj : Prj_Desc) return Compilation_Unit + is (No_Compilation_Unit); + -- Return the compilation unit holding the dump helper subprogram + + function Has_Main + (Self : in out Language_Instrumenter; + Filename : String; + Prj : Prj_Desc) return Boolean is (False); + -- Return whether the given file is a main or not + function New_File (Prj : Prj_Desc; Name : String) return String; -- Compute the path to the file to create in Self.Output_Dir diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index c80b179ea..620b2906d 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -31,8 +31,6 @@ with Ada.Unchecked_Deallocation; with GNAT.Exception_Actions; -with Interfaces; use Interfaces; - with GNAT.OS_Lib; with GNAT.Regexp; with GNAT.Strings; @@ -44,7 +42,6 @@ with GNATCOLL.Projects.Aux; use GNATCOLL.Projects.Aux; with Binary_Files; with Command_Line; use Command_Line; with Files_Table; -with Hex_Images; use Hex_Images; with Instrument.Ada_Unit; use Instrument.Ada_Unit; with Instrument.C; use Instrument.C; with Instrument.Clean_Objdirs; @@ -796,20 +793,7 @@ is begin -- Set the instrumentation tag - declare - Time : constant Unsigned_64 := - Unsigned_64 - (GNAT.OS_Lib.To_C (GNAT.OS_Lib.Current_Time)); - Tag : constant String := - Hex_Images.Strip_Zero_Padding - (Hex_Images.Hex_Image (Time)); - -- Tag for the current instrumentation run. Passed on to instrument-main - -- invocations, to have the same tag for mains instrumented at the - -- same time. - - begin - IC.Tag := +Tag; - end; + IC.Tag := +Instrumentation_Tag; -- Delete output directories from previous instrumentations diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb new file mode 100644 index 000000000..744b72cac --- /dev/null +++ b/tools/gnatcov/instrument-setup_config.adb @@ -0,0 +1,440 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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.Directories; +with Ada.Strings; use Ada.Strings; +with Ada.Strings.Fixed; +with Ada.Text_IO; use Ada.Text_IO; + +with GNAT.OS_Lib; +with GNAT.Regexp; use GNAT.Regexp; +with GNAT.Strings; + +with Coverage; +with JSON; use JSON; +with Outputs; use Outputs; +with Paths; use Paths; +with Support_Files; use Support_Files; + +package body Instrument.Setup_Config is + + GCC_Regexp : constant Regexp := Compile (".*gcc.*"); + GXX_Regexp : constant Regexp := Compile (".*g\+\+.*"); + + function Find_Compiler_Prog + (Compiler_Driver : String; + Program_Names : String_Vectors.Vector; + Output_Dir : String; + Fallback_To_System : Boolean := True) return String; + -- Locate the program whose name is one of Program_Names elements in the + -- Compiler_Driver installation directory. Output_Dir is the directory + -- where temporary output files are generated. If the program is not + -- found under the compiler driver installation, assume there is a + -- system installation if Fallback_To_System is True (and so return the + -- first name of Program_Names), otherwise error out. + + function Find_Compiler_Prog + (Compiler_Driver : String; + Program_Names : String_Vectors.Vector; + Output_Dir : String; + Fallback_To_System : Boolean := True) return String + is + Driver_Arguments : String_Vectors.Vector; + Output_Filename : constant String := + Output_Dir / "which-compiler-prog"; + Output_File : File_Type; + begin + for Program_Name of Program_Names loop + Driver_Arguments.Clear; + Driver_Arguments.Append (+"--print-prog-name"); + Driver_Arguments.Append (Program_Name); + + Run_Command + (Compiler_Driver, + Arguments => Driver_Arguments, + Origin_Command_Name => "gnatcov instrument-setup", + Output_File => Output_Filename); + + -- Check if the output is a full path to an existing file. If this is + -- the case, then store the program path. + + Open (Output_File, In_File, Output_Filename); + declare + Output : constant String := Get_Line (Output_File); + begin + Close (Output_File); + if Ada.Directories.Exists (Output) then + Ada.Directories.Delete_File (Output_Filename); + return Output; + end if; + end; + end loop; + Ada.Directories.Delete_File (Output_Filename); + if Fallback_To_System then + return +Program_Names.First_Element; + else + Outputs.Fatal_Error + ("Could not locate program " & (+Program_Names.First_Element) + & " in compiler driver installation."); + end if; + end Find_Compiler_Prog; + + --------------------- + -- Generate_Config -- + --------------------- + + procedure Generate_Config + (Files_Of_Interest : String_Sets.Set; + Coverage_Level : String; + Dump_Config : Any_Dump_Config; + Compiler_Drivers : String_Sets.Set; + Output_Dir : String) + is + Config : constant JSON_Value := Create_Object; + Compilers : constant JSON_Value := Create_Object; + Linkers : constant JSON_Value := Create_Object; + -- For each compiler driver, location of the ld executable + + Nms : constant JSON_Value := Create_Object; + -- For each compiler driver, location of the nm executable + + begin + -- Find the installed gnatcov_rts, using gprls. TODO???: deal with non + -- native cases. + -- + -- We are looking for the following lines: + -- Source Search Path: + -- some/path/to/include/ + -- [...] + -- Object Search Path: + -- some/path/to/lib/gnatcov_rts.static + + declare + use Ada.Strings.Fixed; + + Args : String_Vectors.Vector; + Output_Filename : constant String := + Output_Dir / "gprls_output"; + Output_File : File_Type; + begin + Args.Append (+"-P"); + Args.Append (+"gnatcov_rts"); + Args.Append (+"-vP1"); + Run_Command + (Command => "gprls", + Arguments => Args, + Origin_Command_Name => "gnatcov setup-integration", + Output_File => Output_Filename); + Open (Output_File, In_File, Output_Filename); + while not End_Of_File (Output_File) loop + declare + Line : constant String := Get_Line (Output_File); + begin + if Line = "Source Search Path:" then + Config.Set_Field + ("gnatcov_rts_include_dir", + Trim (Get_Line (Output_File), Left)); + elsif Line = "Object Search Path:" then + Config.Set_Field + ("gnatcov_rts_object_dir", + Trim (Get_Line (Output_File), Left)); + end if; + end; + end loop; + Close (Output_File); + end; + + -- Generate the compiler driver wrappers, checking that they are + -- supported. + + for Compiler_Driver of Compiler_Drivers loop + + -- Locate the compiler driver, and if it is not found, terminate + -- with an exception. + + declare + use type GNAT.Strings.String_Access; + Compiler_Fullname : constant GNAT.OS_Lib.String_Access := + GNAT.OS_Lib.Locate_Exec_On_Path (+Compiler_Driver); + begin + -- Check if the compiler executable is on the PATH + + if Compiler_Fullname = null then + Outputs.Fatal_Error + ("Could not locate compiler " & (+Compiler_Driver) + & " on the PATH."); + end if; + + -- Check if this is a supported compiler and instantiate the + -- compiler wrapper accordingly. + + declare + Actual_Compiler_Driver : constant String := + GNAT.OS_Lib.Normalize_Pathname (Compiler_Fullname.all); + Actual_CD_Basename : constant String := + Ada.Directories.Simple_Name (Actual_Compiler_Driver); + Success : Boolean; + Matched : Boolean := True; + Compiler_Identifier : Unbounded_String; + begin + if GNAT.Regexp.Match (Actual_Compiler_Driver, GCC_Regexp) + or else GNAT.Regexp.Match + (Actual_Compiler_Driver, GXX_Regexp) + then + Compiler_Identifier := +"gcc"; + else + Matched := False; + end if; + + if Matched then + Compilers.Set_Field + (+Compiler_Driver, Compiler_Fullname.all); + + -- Then, find the linker associated to this compiler. Look + -- for ld / ld.bfd. TODO???: this may need reworking when + -- we want to support toolchain other than ours, not + -- necessarily packaging ld. + + declare + Linker_Programs : String_Vectors.Vector; + begin + Linker_Programs.Append (+"ld"); + Linker_Programs.Append (+"ld.bfd"); + + Linkers.Set_Field + (+Compiler_Driver, + Find_Compiler_Prog + (Compiler_Driver => Actual_Compiler_Driver, + Program_Names => Linker_Programs, + Output_Dir => Output_Dir)); + end; + + -- Do the same with nm, as we need to be able to inspect the + -- object / library file contents. TODO???: this may need + -- reworking when we want to support toolchain other than + -- ours, not necessarily packaging nm. + + declare + Nm_Program : String_Vectors.Vector; + begin + Nm_Program.Append (+"nm"); + + Nms.Set_Field + (+Compiler_Driver, + Find_Compiler_Prog + (Compiler_Driver => Actual_Compiler_Driver, + Program_Names => Nm_Program, + Output_Dir => Output_Dir)); + end; + + GNAT.OS_Lib.Copy_File + (Support_Files.Libexec_Dir + / ("compiler_wrappers-" & (+Compiler_Identifier)), + Pathname => Output_Dir / (+Compiler_Driver), + Success => Success, + Mode => GNAT.OS_Lib.Overwrite, + Preserve => GNAT.OS_Lib.Full); + if not Success then + Outputs.Fatal_Error + ("Could not generate a compiler wrapper in the given" + & " directory " & Output_Dir); + end if; + else + Outputs.Fatal_Error + ("Unsupported compiler driver: " & Actual_CD_Basename); + end if; + end; + + end; + end loop; + Config.Set_Field ("compilers", Compilers); + Config.Set_Field ("linkers", Linkers); + Config.Set_Field ("nms", Nms); + + -- Then, register the files of interest + + declare + Files_Of_Interest_JSON : JSON_Array; + begin + for F of Files_Of_Interest loop + Append (Files_Of_Interest_JSON, Create (+F)); + end loop; + Config.Set_Field ("files-of-interest", Files_Of_Interest_JSON); + end; + + -- Then, register the dump config that we will pass explicitly on the + -- command line. + + declare + Dump_Config_JSON : constant JSON_Value := Create_Object; + begin + case Dump_Config.Trigger is + when Manual => + Dump_Config_JSON.Set_Field ("dump-trigger", "manual"); + when At_Exit => + Dump_Config_JSON.Set_Field ("dump-trigger", "atexit"); + when Ravenscar_Task_Termination => + Dump_Config_JSON.Set_Field + ("dump-trigger", "ravenscar-task-termination"); + when Main_End => + Dump_Config_JSON.Set_Field ("dump-trigger", "main-end"); + end case; + + case Dump_Config.Channel is + when Binary_File => + Dump_Config_JSON.Set_Field ("dump-channel", "bin-file"); + if Dump_Config.Filename_Simple then + Dump_Config_JSON.Set_Field ("dump-filename-simple", True); + end if; + if Length (Dump_Config.Filename_Env_Var) /= 0 then + Dump_Config_JSON.Set_Field + ("dump-filename-env-var", Dump_Config.Filename_Env_Var); + end if; + if Length (Dump_Config.Filename_Prefix) /= 0 then + Dump_Config_JSON.Set_Field + ("dump-filename-prefix", Dump_Config.Filename_Prefix); + end if; + when Base64_Standard_Output => + Dump_Config_JSON.Set_Field ("dump-channel", "base64-stdout"); + end case; + Config.Set_Field ("dump-config", Dump_Config_JSON); + end; + + Config.Set_Field ("coverage_level", Coverage_Level); + Config.Set_Field ("tag", Instrumentation_Tag); + Config.Set_Field ("save_temps", Switches.Save_Temps); + Config.Set_Field ("verbose", Switches.Verbose); + + -- Dump the instrumentation configuration in a JSON file. Do not write + -- the compact representation of the JSON as we may reach the character + -- limit. + + Write + (Filename => Output_Dir / Instrumentation_Config_Filename, + Value => Config, + Compact => False); + end Generate_Config; + + ----------------- + -- Load_Config -- + ----------------- + + function Load_Config (Config_File : String) return Instrumentation_Config + is + Result : Instrumentation_Config; + Channel : Any_Dump_Channel; + Config_JSON : JSON_Value; + Parsed_JSON : constant Read_Result := JSON.Read (Config_File); + begin + if not Parsed_JSON.Success then + Outputs.Fatal_Error + ("Parsing errror while reading the instrumentation configuration" + & " file."); + end if; + Config_JSON := Parsed_JSON.Value; + + Switches.Save_Temps := Config_JSON.Get ("save_temps"); + Switches.Verbose := Config_JSON.Get ("verbose"); + Coverage.Set_Coverage_Levels (Config_JSON.Get ("coverage_level")); + + declare + FOI_JSON : constant JSON_Array := + Config_JSON.Get ("files-of-interest"); + begin + for FOI of FOI_JSON loop + Switches.Files_Of_Interest.Include (Get (FOI)); + end loop; + end; + + -- Read the dump config + + declare + Dump_Config_JSON : constant JSON_Value := + Config_JSON.Get ("dump-config"); + Dump_Trigger_Str : constant String := + Dump_Config_JSON.Get ("dump-trigger"); + Dump_Channel_Str : constant String := + Dump_Config_JSON.Get ("dump-channel"); + begin + if Dump_Channel_Str = "bin-file" then + Channel := Binary_File; + elsif Dump_Channel_Str = "base64-stdout" then + Channel := Base64_Standard_Output; + else + Outputs.Fatal_Error ("unsupported dump channel"); + end if; + + declare + Dump_Config : Any_Dump_Config (Channel); + begin + + if Dump_Trigger_Str = "atexit" then + Dump_Config.Trigger := At_Exit; + elsif Dump_Trigger_Str = "main-end" then + Dump_Config.Trigger := Main_End; + elsif Dump_Trigger_Str = "ravenscar-task-termination" then + Dump_Config.Trigger := Ravenscar_Task_Termination; + elsif Dump_Trigger_Str = "manual" then + Dump_Config.Trigger := Manual; + else + Outputs.Fatal_Error ("unsupported dump trigger"); + end if; + Result.Dump_Config := Dump_Config; + end; + end; + + declare + + procedure Fill_String_Map + (Result : out String_Maps.Map; + JSON_Object : JSON_Value); + -- Fill the Result string map with the contents of the given JSON + -- object + + procedure Fill_String_Map + (Result : out String_Maps.Map; + JSON_Object : JSON_Value) + is + procedure Insert_Element + (Key : UTF8_String; Value : JSON_Value); + + procedure Insert_Element + (Key : UTF8_String; Value : JSON_Value) is + begin + Result.Insert (+Key, Get (Value)); + end Insert_Element; + begin + Map_JSON_Object (JSON_Object, Insert_Element'Access); + end Fill_String_Map; + + begin + Fill_String_Map + (Result.Compiler_Drivers, Config_JSON.Get ("compilers")); + Fill_String_Map (Result.Linkers, Config_JSON.Get ("linkers")); + Fill_String_Map (Result.Nms, Config_JSON.Get ("nms")); + end; + + Result.Tag := Config_JSON.Get ("tag"); + Result.GNATcov_RTS_Include_Dir := + Config_JSON.Get ("gnatcov_rts_include_dir"); + Result.GNATcov_RTS_Object_Dir := + Config_JSON.Get ("gnatcov_rts_object_dir"); + return Result; + end Load_Config; + +end Instrument.Setup_Config; diff --git a/tools/gnatcov/instrument-setup_config.ads b/tools/gnatcov/instrument-setup_config.ads new file mode 100644 index 000000000..4c4982aa4 --- /dev/null +++ b/tools/gnatcov/instrument-setup_config.ads @@ -0,0 +1,62 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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 GNATCOLL.JSON; use GNATCOLL.JSON; + +package Instrument.Setup_Config is + + type Instrumentation_Config is record + Dump_Config : Any_Dump_Config; + + Compiler_Drivers : String_Maps.Map; + -- Mapping from compiler driver simple names to full names + + Linkers : String_Maps.Map; + -- Mapping from compiler driver simple names to associated linker + -- executable + + Nms : String_Maps.Map; + -- Mapping from compiler driver simple names to associated nm + -- executable + + Tag : Unbounded_String; + -- Tag for this instrumentation run + + GNATcov_RTS_Include_Dir : Unbounded_String; + GNATcov_RTS_Object_Dir : Unbounded_String; + -- Location of the include / object directories of the installed + -- gnatcov_rts. This is used by compiler wrappers to compile / link + -- instrumented sources in the instrumented main executable. For now, + -- we always link it statically. + + end record; + + Instrumentation_Config_Filename : constant String := "gnatcov_config.json"; + -- Simple name of the file containing the instrumentation configuration + + procedure Generate_Config + (Files_Of_Interest : String_Sets.Set; + Coverage_Level : String; + Dump_Config : Any_Dump_Config; + Compiler_Drivers : String_Sets.Set; + Output_Dir : String); + -- Setup the configuration to use the integrated-mode of gnatcov + + function Load_Config (Config_File : String) return Instrumentation_Config; + +end Instrument.Setup_Config; diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 521db3fcb..482207402 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -25,6 +25,8 @@ with Ada.Strings.Hash; with Ada.Strings.Unbounded.Equal_Case_Insensitive; with Ada.Strings.Unbounded.Less_Case_Insensitive; +with GNAT.OS_Lib; + with Interfaces; use Interfaces; with GNATCOLL.VFS; use GNATCOLL.VFS; @@ -534,4 +536,23 @@ package body Instrument is return Result; end Unparse; + ------------------------- + -- Instrumentation_Tag -- + ------------------------- + + function Instrumentation_Tag return String + is + Time : constant Unsigned_64 := + Unsigned_64 + (GNAT.OS_Lib.To_C (GNAT.OS_Lib.Current_Time)); + Tag : constant String := + Hex_Images.Strip_Zero_Padding + (Hex_Images.Hex_Image (Time)); + -- Tag for the current instrumentation run. Passed on to instrument-main + -- invocations, to have the same tag for mains instrumented at the + -- same time. + begin + return Tag; + end Instrumentation_Tag; + end Instrument; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index cf174b0dd..7bbc8372b 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -18,10 +18,8 @@ -- Support for source instrumentation -with Ada.Containers.Hashed_Maps; with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; -with Ada.Strings.Unbounded.Hash; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with GNATCOLL.Projects; use GNATCOLL.Projects; @@ -189,13 +187,6 @@ package Instrument is of Unbounded_String; type C_Lang_Array_Vec is array (C_Family_Language) of String_Vectors.Vector; - package String_Vectors_Maps is new Ada.Containers.Hashed_Maps - (Key_Type => Unbounded_String, - Element_Type => String_Vectors.Vector, - Equivalent_Keys => Ada.Strings.Unbounded."=", - Hash => Ada.Strings.Unbounded.Hash, - "=" => String_Vectors."="); - type Prj_Desc is record Prj_Name : Unbounded_String; -- Name for the project @@ -239,4 +230,8 @@ package Instrument is -- Return a list of command line switches holding all the project -- information for the given Unit_Name of the language Lang. + function Instrumentation_Tag return String; + -- Generate a unique identifier that can be used to tag the current + -- instrumentation run. + end Instrument; diff --git a/tools/gnatcov/strings.ads b/tools/gnatcov/strings.ads index a1c5df035..b3c683adf 100644 --- a/tools/gnatcov/strings.ads +++ b/tools/gnatcov/strings.ads @@ -17,12 +17,14 @@ ------------------------------------------------------------------------------ with Ada.Containers; +with Ada.Containers.Hashed_Maps; with Ada.Containers.Ordered_Maps; with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; with Ada.Streams; with Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Equal_Case_Insensitive; +with Ada.Strings.Unbounded.Hash; with Ada.Strings.Unbounded.Less_Case_Insensitive; with GNAT.Strings; use GNAT.Strings; @@ -77,6 +79,13 @@ package Strings is "=" => Ada.Strings.Unbounded.Equal_Case_Insensitive); -- Case insensitive string set + package String_Vectors_Maps is new Ada.Containers.Hashed_Maps + (Key_Type => Ada.Strings.Unbounded.Unbounded_String, + Element_Type => String_Vectors.Vector, + Equivalent_Keys => Ada.Strings.Unbounded."=", + Hash => Ada.Strings.Unbounded.Hash, + "=" => String_Vectors."="); + function To_String_Set (V : String_Vectors.Vector) return String_Sets.Set; -- Convert the given strings vector to a strings set From 8ff57c64ce2fbda932bc6c37c6c4e54cb074addb Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 12 Jul 2023 17:23:21 +0200 Subject: [PATCH 0381/1483] Always emit a valid buffers list unit Even if the buffers list is empty, emit a valid buffers list compilation unit. --- tools/gnatcov/instrument-c.adb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index b01edbb64..527d0adcf 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -4138,12 +4138,11 @@ package body Instrument.C is (" (const struct gnatcov_rts_coverage_buffers_group *[]) {"); for BS of Buffer_Symbols loop CU_File.Put (" &" & (+BS)); - if BS = Buffer_Symbols.Last_Element then - CU_File.Put_Line ("}};"); - else + if BS /= Buffer_Symbols.Last_Element then CU_File.Put_Line (","); end if; end loop; + CU_File.Put_Line ("}};"); return CU_Name; end Emit_Buffers_List_Unit; From 943cc1b1c29b461049f9f62dd69642bd9a3dffaf Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 2 Aug 2023 14:43:56 +0200 Subject: [PATCH 0382/1483] Enable use of a custom timeout in test.opt --- testsuite/testsuite.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 6b544e523..44a42efe0 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -44,13 +44,6 @@ from SUITE.control import altrun_opt_for, altrun_attr_for from SUITE.control import cargs_opt_for, cargs_attr_for - -DEFAULT_TIMEOUT = 600 -""" -Default timeout to use (in seconds) to run testcases. Users can override this -using gnatpython.main's --timeout command-line option. -""" - VALGRIND_TIMEOUT_FACTOR = 2 """ When the testsuite runs with Valgrind (--enable-valgrind), the default timeout @@ -595,7 +588,7 @@ def set_up(self): # Compute the testcase timeout, whose default vary depending on whether # we use Valgrind. - timeout = DEFAULT_TIMEOUT + timeout = int(self.test_control.opt_results["RLIMIT"]) if mopt.enable_valgrind: timeout = VALGRIND_TIMEOUT_FACTOR * timeout From 563d6187e2a3c1c8cc097a2a20b717a1c31c3b00 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 2 Aug 2023 14:44:50 +0200 Subject: [PATCH 0383/1483] Always get the full name for file locations --- tools/gnatcov/instrument-c_utils.adb | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index f11b86b89..361b6f220 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -85,6 +85,7 @@ package body Instrument.C_Utils is Sloc := To_Sloc (0, 0); else Sloc := To_Sloc (Line, Column); + Filename := +Full_Name (+Filename); end if; Dispose_String (C_Filename); From e3fa902ca3394a4bcc8a273a8e98c7b524aff8da Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 17 Aug 2023 12:28:48 +0200 Subject: [PATCH 0384/1483] Minor formatting / fixes --- tools/gnatcov/clang-wrapper.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index c4929e506..13adba792 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -333,7 +333,6 @@ clang_getWhileLoc (CXCursor C) return clang_getNullLocation (); } - extern "C" CXCursor clang_getSubExpr (CXCursor C) { @@ -601,7 +600,6 @@ clang_CXRewriter_insertTextBeforeToken (CXRewriter Rew, CXSourceLocation Loc, { assert (Rew); Rewriter &R = *reinterpret_cast (Rew); - const SourceManager &SM = R.getSourceMgr (); // Get the previous location, and insert after it From 9f8e0c0b9abf4fc7c267b0f14515be27de2c6f92 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 18 Aug 2023 11:50:04 +0200 Subject: [PATCH 0385/1483] Fix debug print when running subprocesses --- testsuite/tests/KB30-011-eargs-gnatemu/test.py | 8 +++++--- testsuite/tests/N630-009-forward_p_x/test.py | 2 +- testsuite/tests/duplicate_postprocess/test.py | 2 +- tools/gnatcov/subprocesses.adb | 9 +++++++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/testsuite/tests/KB30-011-eargs-gnatemu/test.py b/testsuite/tests/KB30-011-eargs-gnatemu/test.py index 3f6278df3..c3326f737 100644 --- a/testsuite/tests/KB30-011-eargs-gnatemu/test.py +++ b/testsuite/tests/KB30-011-eargs-gnatemu/test.py @@ -26,11 +26,13 @@ gprbuild(gprfor(mains=[unit], srcdirs=['..'])) -def check_eargs(output, eargs, exe): +def check_eargs(output, eargs, exe, protect_eargs=False): m = re.search('exec:\n .*gnatemu.*', output) e = m.group(0) + if protect_eargs: + eargs = ' '.join ([f"'{arg}'" for arg in eargs.split(" ")]) thistest.fail_if( - not re.search('--eargs .*%(eargs)s.* --eargs-end.*%(exe)s' + not re.search("'--eargs' .*%(eargs)s.* '--eargs-end'.*%(exe)s" % {'eargs': eargs, 'exe': exe}, e), "failed to match eargs='%s' and exe='%s' in output: <<\n%s\n>>" % (eargs, exe, output)) @@ -98,7 +100,7 @@ def gnatemulator(args, exe): extra = '--level=stmt' thistest.log(extra + ' eargs for qemu') output = gnatcovrun(extra=extra, exe=exe, eargs=eargs) -check_eargs(output, eargs=eargs, exe=exe) +check_eargs(output, eargs=eargs, exe=exe, protect_eargs=True) eargs1 = '-m 512' eargs2 = '-version' diff --git a/testsuite/tests/N630-009-forward_p_x/test.py b/testsuite/tests/N630-009-forward_p_x/test.py index 1df8eec7b..5a6eaba3d 100644 --- a/testsuite/tests/N630-009-forward_p_x/test.py +++ b/testsuite/tests/N630-009-forward_p_x/test.py @@ -24,7 +24,7 @@ xcovargs = ['-P', gpr, '-v', program_path] + xargs p = xrun(xcovargs) -for arg in xargs + ['-P *%s' % gpr]: +for arg in xargs + ["'-P' '*%s'" % gpr]: thistest.fail_if( not re.search('gnatemu.*%s' % arg, p.out), 'couldn\'t find "%s" on the gnatemu command line out of %s' % diff --git a/testsuite/tests/duplicate_postprocess/test.py b/testsuite/tests/duplicate_postprocess/test.py index 9ca45b0b0..64d033e78 100644 --- a/testsuite/tests/duplicate_postprocess/test.py +++ b/testsuite/tests/duplicate_postprocess/test.py @@ -25,7 +25,7 @@ thistest.fail_if( len( re.findall( - f"gcc{env.build.os.exeext} -E", contents_of("coverage.log") + f"gcc{env.build.os.exeext}' '-E'", contents_of("coverage.log") ) ) != 1, diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 25edace20..5ea2465a1 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -261,15 +261,20 @@ package body Subprocesses is Process_Types.Add_Argument (Args, Program.all); if Verbose then Put_Line ("exec:"); - Put (" " & Program.all); + Put (" '" & Program.all & "'"); end if; Free (Program); for A of Arguments loop Process_Types.Add_Argument (Args, +A); if Verbose then - Put (' '); + + -- Quote the arguments to print empty strings and correctly + -- escape quoted strings. + + Put (" '"); Put (+A); + Put ("'"); end if; end loop; if Verbose then From 8092a7bb5e408305d7143783eba1a38f9a4454c5 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 18 Aug 2023 12:37:27 +0200 Subject: [PATCH 0386/1483] Instrument.Projects: avoid spurious project tree traversals --- tools/gnatcov/instrument-projects.adb | 75 ++++++++++++++------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 620b2906d..7288ad63f 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -269,6 +269,46 @@ is Result.Prj_Name := +Prj.Name; Result.Dot_Replacement := +Dot_Replacement; + -- Register the source directories of the project tree + + declare + procedure Register_Source_Dirs + (P : GNATCOLL.Projects.Project_Type); + -- Add the source directories of P's project file to the search + -- paths to be passed as -I arguments later. The order in which + -- the paths are added to the search paths vector is the same + -- order in which GNATCOLL retrieves the files in the project + -- tree. gprbuild also depends on GNATCOLL which ensures we + -- have the same behavior here. + + -------------------------- + -- Register_Source_Dirs -- + -------------------------- + + procedure Register_Source_Dirs + (P : GNATCOLL.Projects.Project_Type) is + begin + for Dir of P.Source_Dirs loop + Result.Search_Paths.Append + ("-I" & (+GNATCOLL.VFS."+" (GNATCOLL.VFS.Dir_Name (Dir)))); + end loop; + end Register_Source_Dirs; + begin + -- Pass the source directories of the project file as -I options. + -- Note that this will duplicate with the project tree traversal + -- below, but we need this project source directories to be + -- picked first. We thus make sure to add them first to the + -- PP_Search_Path list. + + Register_Source_Dirs (Prj); + + -- Pass the source directories of included projects as -I options + + Project.Iterate_Projects + (Prj, Register_Source_Dirs'Access, + Recursive => True, Include_Extended => True); + end; + -- Load the set of compiler switches for languages requiring it for Lang in C_Family_Language loop @@ -283,42 +323,7 @@ is GPR.Compiler_Driver_Attribute, Image (Lang)); - procedure Register_Source_Dirs - (P : GNATCOLL.Projects.Project_Type); - -- Add the source directories of P's project file to the search - -- paths to be passed as -I arguments later. The order in which - -- the paths are added to the search paths vector is the same - -- order in which GNATCOLL retrieves the files in the project - -- tree. gprbuild also depends on GNATCOLL which ensures we - -- have the same behavior here. - - -------------------------- - -- Register_Source_Dirs -- - -------------------------- - - procedure Register_Source_Dirs - (P : GNATCOLL.Projects.Project_Type) is - begin - for Dir of P.Source_Dirs loop - Result.Search_Paths.Append - ("-I" & (+GNATCOLL.VFS."+" (GNATCOLL.VFS.Dir_Name (Dir)))); - end loop; - end Register_Source_Dirs; begin - -- Pass the source directories of the project file as -I options. - -- Note that this will duplicate with the project tree traversal - -- below, but we need this project source directories to be - -- picked first. We thus make sure to add them first to the - -- PP_Search_Path list. - - Register_Source_Dirs (Prj); - - -- Pass the source directories of included projects as -I options - - Project.Iterate_Projects - (Prj, Register_Source_Dirs'Access, - Recursive => True, Include_Extended => True); - -- Get the compiler switches from the project file. When -- registering a compilation unit for instrumentation, we also -- fill the compilation unit specific switches that will override From 72a3e56af46e2a47c7c3182255eb0d15892369c7 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 18 Aug 2023 14:44:39 +0200 Subject: [PATCH 0387/1483] C/C++ instrumentation: include externally built project source dirs To preprocess a C/C++ source file, we need to locate the source directories that will be ultimately pass down through -I switches to the compiler driver command line. In a GPR context, a source can reference a header in any of the project dependencies source directories. We thus do a full traversal of the project tree and register every source directory. Nevertheless, we were not traversing externally built projects, as it depended on the setting of the Externally_Built_Projects_Processing_Enabled variable. Refactor the code to be able to traverse through externally built project in that case. --- .../106-externally-built-header/main/main.c | 8 +++ .../106-externally-built-header/mylib/mylib.c | 5 ++ .../mylib/mylib.gpr | 6 +++ .../106-externally-built-header/mylib/mylib.h | 1 + .../tests/106-externally-built-header/test.py | 49 +++++++++++++++++++ tools/gnatcov/instrument-projects.adb | 7 ++- tools/gnatcov/project.adb | 17 +++---- tools/gnatcov/project.ads | 20 +++++--- 8 files changed, 95 insertions(+), 18 deletions(-) create mode 100644 testsuite/tests/106-externally-built-header/main/main.c create mode 100644 testsuite/tests/106-externally-built-header/mylib/mylib.c create mode 100644 testsuite/tests/106-externally-built-header/mylib/mylib.gpr create mode 100644 testsuite/tests/106-externally-built-header/mylib/mylib.h create mode 100644 testsuite/tests/106-externally-built-header/test.py diff --git a/testsuite/tests/106-externally-built-header/main/main.c b/testsuite/tests/106-externally-built-header/main/main.c new file mode 100644 index 000000000..1eff0311b --- /dev/null +++ b/testsuite/tests/106-externally-built-header/main/main.c @@ -0,0 +1,8 @@ +#include "mylib.h" + +int +main() +{ + foo(); + return 0; +} diff --git a/testsuite/tests/106-externally-built-header/mylib/mylib.c b/testsuite/tests/106-externally-built-header/mylib/mylib.c new file mode 100644 index 000000000..c0d2890e2 --- /dev/null +++ b/testsuite/tests/106-externally-built-header/mylib/mylib.c @@ -0,0 +1,5 @@ +int +foo() +{ + return 0; +} diff --git a/testsuite/tests/106-externally-built-header/mylib/mylib.gpr b/testsuite/tests/106-externally-built-header/mylib/mylib.gpr new file mode 100644 index 000000000..afc15b221 --- /dev/null +++ b/testsuite/tests/106-externally-built-header/mylib/mylib.gpr @@ -0,0 +1,6 @@ +library project Mylib is + for Library_Name use "mylib"; + for Library_Dir use "lib"; + for Object_Dir use "obj"; + for Languages use ("C"); +end Mylib; diff --git a/testsuite/tests/106-externally-built-header/mylib/mylib.h b/testsuite/tests/106-externally-built-header/mylib/mylib.h new file mode 100644 index 000000000..cf790ac3e --- /dev/null +++ b/testsuite/tests/106-externally-built-header/mylib/mylib.h @@ -0,0 +1 @@ +extern int foo(); diff --git a/testsuite/tests/106-externally-built-header/test.py b/testsuite/tests/106-externally-built-header/test.py new file mode 100644 index 000000000..0645d0d60 --- /dev/null +++ b/testsuite/tests/106-externally-built-header/test.py @@ -0,0 +1,49 @@ +""" +Check that GNATcoverage passes the right source directories to the +preprocessing command, including externally built projects source directories. + +It used to skip externally built projects when the --externally-built-project +switch was not passed to the gnatcov command line. +""" + +import os.path +import re +import shutil + +from e3.fs import cp, rm + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of, indent +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, gprbuild, gprinstall, xcov + +tmp = Wdir("tmp_") + +# Create the installation directory and add it to gprbuild's project lookup +# path. +install_dir = os.path.abspath("install") +gpr_install_dir = os.path.join(install_dir, "share", "gpr") +os.mkdir(install_dir) +env.add_search_path("GPR_PROJECT_PATH", gpr_install_dir) + +# Build and install the library project +cp(os.path.join("..", "mylib"), ".", recursive=True) +mylib_gpr = os.path.join("mylib", "mylib.gpr") +gprbuild(mylib_gpr) +gprinstall(mylib_gpr, f"--prefix={install_dir}") + +# Build the main project using this and run it to produce a trace file +main_gpr = gprfor(mains=["main.c"], srcdirs=os.path.join("..", "main"), deps=["mylib"]) +xcov_args = build_run_and_coverage( + gprsw=GPRswitches(root_project=main_gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=."], +) + +check_xcov_reports("*.xcov", {"main.c.xcov": {"+": {6, 7}}}) + +thistest.result() diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 7288ad63f..bec050ced 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -305,8 +305,11 @@ is -- Pass the source directories of included projects as -I options Project.Iterate_Projects - (Prj, Register_Source_Dirs'Access, - Recursive => True, Include_Extended => True); + (Prj, + Register_Source_Dirs'Access, + Recursive => True, + Include_Extended => True, + Include_Externally_Built => True); end; -- Load the set of compiler switches for languages requiring it diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 4515b18af..40bce594c 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -103,9 +103,6 @@ package body Project is -- The root dir of the project tree, to consider when Build_Root_Dir is -- set. - Externally_Built_Projects_Processing_Enabled : Boolean := False; - -- Whether to include projects marked as externally built to processings - type Project_Info is record Project : Project_Type; -- The project this info relates to @@ -348,11 +345,13 @@ package body Project is ---------------------- procedure Iterate_Projects - (Root_Project : GNATCOLL.Projects.Project_Type; - Process : access procedure - (Prj : GNATCOLL.Projects.Project_Type); - Recursive : Boolean; - Include_Extended : Boolean := False) + (Root_Project : GNATCOLL.Projects.Project_Type; + Process : access procedure + (Prj : GNATCOLL.Projects.Project_Type); + Recursive : Boolean; + Include_Extended : Boolean := False; + Include_Externally_Built : Boolean := + Externally_Built_Projects_Processing_Enabled) is Iter : Project_Iterator := Start (Root_Project => Root_Project, @@ -380,7 +379,7 @@ package body Project is -- Skip externally built projects unless they are explicitly -- requested. - if (Externally_Built_Projects_Processing_Enabled + if (Include_Externally_Built or else not Project.Externally_Built) and then not Visited_Projects.Contains (Name) then diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index f1717c3b3..f2d4ba202 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -33,6 +33,9 @@ with Traces_Files; use Traces_Files; package Project is + Externally_Built_Projects_Processing_Enabled : Boolean := False; + -- Whether to include projects marked as externally built to processings + ----------------------- -- Lifetime handling -- ----------------------- @@ -232,17 +235,20 @@ package Project is with Pre => Is_Project_Loaded; procedure Iterate_Projects - (Root_Project : GNATCOLL.Projects.Project_Type; - Process : access procedure - (Prj : GNATCOLL.Projects.Project_Type); - Recursive : Boolean; - Include_Extended : Boolean := False) + (Root_Project : GNATCOLL.Projects.Project_Type; + Process : access procedure + (Prj : GNATCOLL.Projects.Project_Type); + Recursive : Boolean; + Include_Extended : Boolean := False; + Include_Externally_Built : Boolean := + Externally_Built_Projects_Processing_Enabled) with Pre => Is_Project_Loaded; -- Call Process on Root_Project if Recursive is False, or on the whole -- project tree otherwise. -- - -- Unless Include_Extended is True, only process ultimate extending - -- projects. + -- Set Include_Extended to True to process extended projects (otherwise, + -- only process ultimate extending projects). Set Include_Externally_Built + -- to True to process externally built projects. function Source_Suffix (Lang : Src_Supported_Language; From 84febdd63166e26d1371a5f654733b46ec00636e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 29 Aug 2023 13:52:44 +0200 Subject: [PATCH 0388/1483] Kill test in 5.04a1 config --- testsuite/tests/106-externally-built-header/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/106-externally-built-header/test.opt diff --git a/testsuite/tests/106-externally-built-header/test.opt b/testsuite/tests/106-externally-built-header/test.opt new file mode 100644 index 000000000..4f2a3ffe1 --- /dev/null +++ b/testsuite/tests/106-externally-built-header/test.opt @@ -0,0 +1 @@ +5.04a1 XFAIL Incompatibility between gnatls and GNATCOLL.Projects From 47e2f82de43771cfec574d82a0190a6366fa0953 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 31 Aug 2023 13:48:25 +0000 Subject: [PATCH 0389/1483] Display which SID/checkpoint is being loaded in case of internal error --- testsuite/tests/TC11-052-internal-error/test.py | 17 +++++++++++++++++ tools/gnatcov/checkpoints.adb | 7 +++++++ tools/gnatcov/outputs.ads | 3 +++ 3 files changed, 27 insertions(+) diff --git a/testsuite/tests/TC11-052-internal-error/test.py b/testsuite/tests/TC11-052-internal-error/test.py index 1789f93d4..385d6abf2 100644 --- a/testsuite/tests/TC11-052-internal-error/test.py +++ b/testsuite/tests/TC11-052-internal-error/test.py @@ -5,8 +5,10 @@ import re import os +from SCOV.minicheck import build_and_run from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor, xcov @@ -81,4 +83,19 @@ def check(args, trigger, info): trigger="ada-instrument-insert-stmt-witness", info=r"Instrumenting ConcreteTypeDecl at [^\n]*main\.adb:6:4-6:26") +# Instrument the example project, run its main to produce a source trace and +# then trigger an internal error while loading the SID file. +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], + trace_mode="src", +) +check( + args=xcov_args, + trigger="load-checkpoint", + info="Loading [^\n]*main\.sid", +) + thistest.result() diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index 6a1803a78..8a99ee384 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -548,12 +548,19 @@ package body Checkpoints is Purpose : Checkpoint_Purpose; Ignored_Source_Files : access GNAT.Regexp.Regexp) is + Dummy : constant Context_Handle := + Create_Context ("Loading " & Filename); SF : Ada.Streams.Stream_IO.File_Type; CP_Header : Checkpoint_Header; Levels : Levels_Type; begin Open (SF, In_File, Filename); + -- If requested, create an artificial internal error when loading + -- checkpoints. + + Raise_Stub_Internal_Error_For (Load_Checkpoint); + declare CLS : aliased Checkpoint_Load_State := (Root_Stream_Type with diff --git a/tools/gnatcov/outputs.ads b/tools/gnatcov/outputs.ads index 8fd9c654c..724d30f37 100644 --- a/tools/gnatcov/outputs.ads +++ b/tools/gnatcov/outputs.ads @@ -101,6 +101,9 @@ package Outputs is Arguments_Loading, -- Raise an error after Argparse's work and before loading arguments + Load_Checkpoint, + -- Raise an error when loading a checkpoint + Ada_Instrument_Start_File, -- Raise an error when starting the instrumentation of a source file From b5bda0eb153560b85aa47e3214661c3a9d2510e4 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 31 Aug 2023 14:04:50 +0000 Subject: [PATCH 0390/1483] Minor reformattings --- tools/gnatcov/Makefile | 28 ++++++++++++++-------------- tools/gnatcov/gnatcov.gpr | 2 +- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index d2a1918b6..af148d462 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -168,32 +168,32 @@ bin: fi ifdef INSTRUMENTED - # We need to instrument and build at the same time: the driver and gnatcov32 - # builds share the same object directory, meaning that gnatcov will remove - # files resulting from the instrumentation of gnatcov32 when instrumenting - # the driver. This will be a problem: in the former case, - # gnatcov_bits_specific.adb is instrumented as a main but not in the latter - # case (gnatcov.adb is). This means that if we use the version that was not - # instrumented as a main to compile gnatcov32, running gnatcov32 will not - # dump execution traces. + # We need to instrument and build at the same time: the driver and + # gnatcov32 builds share the same object directory, meaning that + # gnatcov will remove files resulting from the instrumentation of + # gnatcov32 when instrumenting the driver. This will be a problem: in + # the former case, gnatcov_bits_specific.adb is instrumented as a main + # but not in the latter case (gnatcov.adb is). This means that if we + # use the version that was not instrumented as a main to compile + # gnatcov32, running gnatcov32 will not dump execution traces. gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov64 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 \ - --src-subdirs=gnatcov-instr + --src-subdirs=gnatcov-instr gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov32 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov32 \ - --src-subdirs=gnatcov-instr + --src-subdirs=gnatcov-instr gnatcov instrument -j0 -P gnatcov.gpr -XPART=driver $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver \ - --src-subdirs=gnatcov-instr + --src-subdirs=gnatcov-instr gnatcov instrument -j0 -P gnatcov.gpr -XPART=compiler $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=compiler \ - --src-subdirs=gnatcov-instr + --src-subdirs=gnatcov-instr else - # Start with the 64-bit gnatcov, which has the largest closure + # Start with the 64-bit gnatcov, which has the largest closure $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov32 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver @@ -257,7 +257,7 @@ install-bin: $(CP) \ $(PGM32PATH)$(exeext) \ $(PGM64PATH)$(exeext) \ - $(COMPILERPATH)$(exeext) \ + $(COMPILERPATH)$(exeext) \ $(PREFIX)/libexec/gnatcoverage install-examples: diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 001d3cba3..64a75df6f 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -64,7 +64,7 @@ project Gnatcov is case Part is when "gnatcov64" | "compiler" => null; - when others => C_Support := "False"; + when others => C_Support := "False"; end case; type Build_Mode_Type is ("dev", "prod", "boot"); From e598f402333a1f00cf59d97c55c635d1d8242836 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 10 Aug 2023 15:55:34 +0200 Subject: [PATCH 0391/1483] Add test for container aggregates and generalized array aggregates The test for container aggregates does nothing useful, in a convoluted way simply for the sake of introducing decisions in the expressions of the keys of the aggregates. The test also fails as Libadalang doesn't support the `[use Key_Expression]` syntax as of yet, so gnatcov fails to instrument the source file. --- .../Ada2022/aggregates/arrays/src/pkg.adb | 20 ++++++++++++++++ .../Ada2022/aggregates/arrays/src/pkg.ads | 7 ++++++ .../Ada2022/aggregates/arrays/src/test_0.adb | 16 +++++++++++++ .../aggregates/arrays/src/test_empty.adb | 20 ++++++++++++++++ .../aggregates/arrays/src/test_full.adb | 23 ++++++++++++++++++ .../aggregates/arrays/src/test_multi.adb | 20 ++++++++++++++++ .../aggregates/arrays/src/test_single.adb | 20 ++++++++++++++++ .../tests/Ada2022/aggregates/arrays/tc.rst | 17 +++++++++++++ .../tests/Ada2022/aggregates/arrays/test.py | 13 ++++++++++ .../aggregates/containers/src/check.adb | 19 +++++++++++++++ .../Ada2022/aggregates/containers/src/pkg.adb | 24 +++++++++++++++++++ .../Ada2022/aggregates/containers/src/pkg.ads | 17 +++++++++++++ .../aggregates/containers/src/test_0.adb | 17 +++++++++++++ .../aggregates/containers/src/test_empty.adb | 20 ++++++++++++++++ .../aggregates/containers/src/test_full.adb | 23 ++++++++++++++++++ .../aggregates/containers/src/test_multi.adb | 20 ++++++++++++++++ .../aggregates/containers/src/test_single.adb | 20 ++++++++++++++++ .../Ada2022/aggregates/containers/tc.rst | 17 +++++++++++++ .../Ada2022/aggregates/containers/test.opt | 2 ++ .../Ada2022/aggregates/containers/test.py | 12 ++++++++++ 20 files changed, 347 insertions(+) create mode 100644 testsuite/tests/Ada2022/aggregates/arrays/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/aggregates/arrays/src/pkg.ads create mode 100644 testsuite/tests/Ada2022/aggregates/arrays/src/test_0.adb create mode 100644 testsuite/tests/Ada2022/aggregates/arrays/src/test_empty.adb create mode 100644 testsuite/tests/Ada2022/aggregates/arrays/src/test_full.adb create mode 100644 testsuite/tests/Ada2022/aggregates/arrays/src/test_multi.adb create mode 100644 testsuite/tests/Ada2022/aggregates/arrays/src/test_single.adb create mode 100644 testsuite/tests/Ada2022/aggregates/arrays/tc.rst create mode 100644 testsuite/tests/Ada2022/aggregates/arrays/test.py create mode 100644 testsuite/tests/Ada2022/aggregates/containers/src/check.adb create mode 100644 testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/aggregates/containers/src/pkg.ads create mode 100644 testsuite/tests/Ada2022/aggregates/containers/src/test_0.adb create mode 100644 testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb create mode 100644 testsuite/tests/Ada2022/aggregates/containers/src/test_full.adb create mode 100644 testsuite/tests/Ada2022/aggregates/containers/src/test_multi.adb create mode 100644 testsuite/tests/Ada2022/aggregates/containers/src/test_single.adb create mode 100644 testsuite/tests/Ada2022/aggregates/containers/tc.rst create mode 100644 testsuite/tests/Ada2022/aggregates/containers/test.opt create mode 100644 testsuite/tests/Ada2022/aggregates/containers/test.py diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/pkg.adb b/testsuite/tests/Ada2022/aggregates/arrays/src/pkg.adb new file mode 100644 index 000000000..dd9bfedd8 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/pkg.adb @@ -0,0 +1,20 @@ +pragma Ada_2022; + +package body Pkg is + + function Absolute (Input : Int_Arr) return Int_Arr is + begin + if Input = [] then -- # empty_aggr_guard + return []; -- # empty_aggr_st + elsif Input'Length = 1 then -- # single_elt_guard + return -- # single_elt_st + [(declare Elt : Integer renames Input (Input'First); -- # single_elt_st + begin (if Elt > 0 then Elt else -Elt))]; -- # single_elt_dc + else + return [for Idx in Input'Range => -- # multi_elt_st + (declare Elt : Integer renames Input (Idx) ; -- # multi_elt_st + begin (if Elt > 0 then Elt else -Elt))]; -- # multi_elt_dc + end if; + end Absolute; + +end Pkg; diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/pkg.ads b/testsuite/tests/Ada2022/aggregates/arrays/src/pkg.ads new file mode 100644 index 000000000..17b7dc446 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + type Int_Arr is array (Positive range <>) of Integer; + + function Absolute (Input : Int_Arr) return Int_Arr; + +end Pkg; diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/test_0.adb b/testsuite/tests/Ada2022/aggregates/arrays/src/test_0.adb new file mode 100644 index 000000000..092bf29fb --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/test_0.adb @@ -0,0 +1,16 @@ +with Pkg; use Pkg; + +procedure Test_0 is +begin + null; +end Test_0; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l- ## s- +-- /empty_aggr_st/ l- ## s- +-- /single_elt_guard/ l- ## s- +-- /single_elt_st/ l- ## s- +-- /single_elt_dc/ l- ## 0 +-- /multi_elt_st/ l- ## s- +-- /multi_elt_dc/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/test_empty.adb b/testsuite/tests/Ada2022/aggregates/arrays/src/test_empty.adb new file mode 100644 index 000000000..f9720cad3 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/test_empty.adb @@ -0,0 +1,20 @@ +pragma Ada_2022; + +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Empty is +begin + Assert (Absolute ([]) = []); +end Test_Empty; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l! ## dF- +-- /empty_aggr_st/ l+ ## 0 +-- /single_elt_guard/ l- ## s- +-- /single_elt_st/ l- ## s- +-- /single_elt_dc/ l- ## 0 +-- /multi_elt_st/ l- ## s- +-- /multi_elt_dc/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/test_full.adb b/testsuite/tests/Ada2022/aggregates/arrays/src/test_full.adb new file mode 100644 index 000000000..4fb707887 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/test_full.adb @@ -0,0 +1,23 @@ +pragma Ada_2022; + +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Full is +begin + Assert (Absolute ([]) = []); + Assert (Absolute ([9]) = [9]); + Assert (Absolute ([-8]) = [8]); + Assert (Absolute ([-3, 2]) = [3, 2]); +end Test_Full; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l+ ## 0 +-- /empty_aggr_st/ l+ ## 0 +-- /single_elt_guard/ l+ ## 0 +-- /single_elt_st/ l+ ## 0 +-- /single_elt_dc/ l+ ## 0 +-- /multi_elt_st/ l+ ## 0 +-- /multi_elt_dc/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/test_multi.adb b/testsuite/tests/Ada2022/aggregates/arrays/src/test_multi.adb new file mode 100644 index 000000000..d775bd38e --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/test_multi.adb @@ -0,0 +1,20 @@ +pragma Ada_2022; + +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Multi is +begin + Assert (Absolute ([9, 4]) = [9, 4]); +end Test_Multi; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l! ## dT- +-- /empty_aggr_st/ l- ## s- +-- /single_elt_guard/ l! ## dT- +-- /single_elt_st/ l- ## s- +-- /single_elt_dc/ l- ## 0 +-- /multi_elt_st/ l+ ## 0 +-- /multi_elt_dc/ l! ## dF- diff --git a/testsuite/tests/Ada2022/aggregates/arrays/src/test_single.adb b/testsuite/tests/Ada2022/aggregates/arrays/src/test_single.adb new file mode 100644 index 000000000..ab3aade30 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/src/test_single.adb @@ -0,0 +1,20 @@ +pragma Ada_2022; + +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Single is +begin + Assert (Absolute ([9]) = [9]); +end Test_Single; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l! ## dT- +-- /empty_aggr_st/ l- ## s- +-- /single_elt_guard/ l! ## dF- +-- /single_elt_st/ l+ ## 0 +-- /single_elt_dc/ l! ## dF- +-- /multi_elt_st/ l- ## s- +-- /multi_elt_dc/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/arrays/tc.rst b/testsuite/tests/Ada2022/aggregates/arrays/tc.rst new file mode 100644 index 000000000..83cdb6db6 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/tc.rst @@ -0,0 +1,17 @@ +** DC for decisions nested in generalized array aggregates ** + +Check proper handling and decision coverage computing for decisions nested in +generalized array aggregates. Pkg implements a function presenting three forms +of generalized array aggregates, i.e. a positional empty aggregate, a single +element positional aggregate and a iterated component association aggregate. + +The test drivers are articulated as follows: + - Test_0 ensures only statement violations are reported when the + function is not called, + - Test_Empty ensures that decision coverage can be computed on a decision + containing an empty generalized array aggregate, + - Test_Single ensures that decisions nested within a single element positional + aggregate are correctly processed, + - Test_Multi ensures that decisions nested within iterated component + associations in a generalized array aggregate are properly processed. + - Test_Full ensures all the above can be covered simultaneously. diff --git a/testsuite/tests/Ada2022/aggregates/arrays/test.py b/testsuite/tests/Ada2022/aggregates/arrays/test.py new file mode 100644 index 000000000..e1cd5e58c --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/arrays/test.py @@ -0,0 +1,13 @@ +""" +Test correct support for generalized array aggregates, including iterated +component associations. +""" + + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/check.adb b/testsuite/tests/Ada2022/aggregates/containers/src/check.adb new file mode 100644 index 000000000..149c78d62 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/check.adb @@ -0,0 +1,19 @@ +pragma Ada_2022; + +with Ada.Containers; use Ada.Containers; + +with Pkg; use Pkg; + +with Support; use Support; + +procedure Check (Input : Int_Set) is + use Int_Maps; + Res : constant Int_Map := Overly_Complex_Identity_Build (Input); +begin + Assert (Input.Length = Res.Length); + Assert ((for all Val of Input => + (declare Cur : constant Cursor := Res.Find (Val); + begin Has_Element (Cur) + and then Key (Cur) = Val + and then Element (Cur) = Val))); +end Check; diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb new file mode 100644 index 000000000..d923cb57c --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb @@ -0,0 +1,24 @@ +pragma Ada_2022; + +with Ada.Containers; use Ada.Containers; + +package body Pkg is + + function Overly_Complex_Identity_Build (Input : Int_Set) return Int_Map is + use Int_Sets; + use Int_Maps; + begin + if Input = [] then -- # empty_aggr_guard + return []; -- # empty_aggr_st + elsif Input.Length = 1 then -- # single_elt_guard + return -- # single_elt_st + (declare Elt : Integer renames Input.First_Element; -- # single_elt_st + begin [(If Elt > 0 then Elt else Elt)]); -- # single_elt_dc + else + return [for Elt of Input use -- # multi_elt_st + (if Elt > 0 then Elt else Elt) => -- # multi_elt_dc + (if Elt > 0 then Elt else Elt)]; -- # multi_elt_dc + end if; + end Overly_Complex_Identity_Build; + +end Pkg; diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/pkg.ads b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.ads new file mode 100644 index 000000000..d7f3a50c0 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.ads @@ -0,0 +1,17 @@ +with Ada.Containers.Ordered_Maps; +with Ada.Containers.Ordered_Sets; + +package Pkg is + + package Int_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Positive, Element_Type => Integer); + subtype Int_Map is Int_Maps.Map; + + package Int_Sets is new Ada.Containers.Ordered_Sets + (Element_Type => Integer); + subtype Int_Set is Int_Sets.Set; + + function Overly_Complex_Identity_Build (Input : Int_Set) return Int_Map; + -- Build an identity map for the elements of Input + +end Pkg; diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_0.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_0.adb new file mode 100644 index 000000000..a6a31f605 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_0.adb @@ -0,0 +1,17 @@ +with Pkg; use Pkg; +with Check; + +procedure Test_0 is +begin + null; +end Test_0; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l- ## s- +-- /empty_aggr_st/ l- ## s- +-- /single_elt_guard/ l- ## s- +-- /single_elt_st/ l- ## s- +-- /single_elt_dc/ l- ## 0 +-- /multi_elt_st/ l- ## s- +-- /multi_elt_dc/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb new file mode 100644 index 000000000..39c73ae6a --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb @@ -0,0 +1,20 @@ +pragma Ada_2022; + +with Pkg; use Pkg; +with Check; + +procedure Test_Single is + use Int_Sets; +begin + Check ([]); +end Test_Single; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l! ## dF- +-- /empty_aggr_st/ l+ ## 0 +-- /single_elt_guard/ l- ## s- +-- /single_elt_st/ l- ## s- +-- /single_elt_dc/ l- ## 0 +-- /multi_elt_st/ l- ## s- +-- /multi_elt_dc/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_full.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_full.adb new file mode 100644 index 000000000..32c7bafb0 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_full.adb @@ -0,0 +1,23 @@ +pragma Ada_2022; + +with Pkg; use Pkg; +with Check; + +procedure Test_Full is + use Int_Sets; +begin + Check ([]); + Check ([9]); + Check ([-8]); + Check ([-3, 2]); +end Test_Full; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l+ ## 0 +-- /empty_aggr_st/ l+ ## 0 +-- /single_elt_guard/ l+ ## 0 +-- /single_elt_st/ l+ ## 0 +-- /single_elt_dc/ l+ ## 0 +-- /multi_elt_st/ l+ ## 0 +-- /multi_elt_dc/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_multi.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_multi.adb new file mode 100644 index 000000000..8295232c9 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_multi.adb @@ -0,0 +1,20 @@ +pragma Ada_2022; + +with Pkg; use Pkg; +with Check; + +procedure Test_Multi is + use Int_Sets; +begin + Check ([-3, 9]); +end Test_Multi; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l! ## dT- +-- /empty_aggr_st/ l- ## s- +-- /single_elt_guard/ l! ## dT- +-- /single_elt_st/ l- ## s- +-- /single_elt_dc/ l- ## 0 +-- /multi_elt_st/ l+ ## 0 +-- /multi_elt_dc/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_single.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_single.adb new file mode 100644 index 000000000..e19d5bf80 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_single.adb @@ -0,0 +1,20 @@ +pragma Ada_2022; + +with Pkg; use Pkg; +with Check; + +procedure Test_Single is + use Int_Sets; +begin + Check ([9]); +end Test_Single; + +--# pkg.adb +-- +-- /empty_aggr_guard/ l! ## dT- +-- /empty_aggr_st/ l- ## s- +-- /single_elt_guard/ l! ## dF- +-- /single_elt_st/ l+ ## 0 +-- /single_elt_dc/ l! ## dF- +-- /multi_elt_st/ l- ## s- +-- /multi_elt_dc/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/tc.rst b/testsuite/tests/Ada2022/aggregates/containers/tc.rst new file mode 100644 index 000000000..8b904c6cc --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/tc.rst @@ -0,0 +1,17 @@ +** DC for decisions nested in container aggregates ** + +Check proper handling and decision coverage computing for decisions nested in +container aggregates. Pkg implements a function presenting three forms of +container aggregates, i.e. a positional empty aggregate, a single element +positional aggregate and a iterated component association aggregate. + +The test drivers are articulated as follows: + - Test_0 ensures only statement violations are reported when the + function is not called, + - Test_Empty ensures that decision coverage can be computed on a decision + containing an empty container aggregate, + - Test_Single ensures that decisions nested within a single element positional + aggregate are correctly processed, + - Test_Multi ensures that decisions nested within iterated component + associations in a container aggregate are properly processed. + - Test_Full ensures all the above can be covered simultaneously. diff --git a/testsuite/tests/Ada2022/aggregates/containers/test.opt b/testsuite/tests/Ada2022/aggregates/containers/test.opt new file mode 100644 index 000000000..9009419d6 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/test.opt @@ -0,0 +1,2 @@ +RTS_ZFP DEAD Test instantiates containers +all XFAIL Support for [use key_expression] not yet available in LAL (libadalang#1062) diff --git a/testsuite/tests/Ada2022/aggregates/containers/test.py b/testsuite/tests/Ada2022/aggregates/containers/test.py new file mode 100644 index 000000000..e755dd8c5 --- /dev/null +++ b/testsuite/tests/Ada2022/aggregates/containers/test.py @@ -0,0 +1,12 @@ +""" +Test correct handling and instrumentation of container aggregates, and decisions +nested within. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() From 9789e7b8a97e24518b1781fba7576fe5d5a2ea2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 17 Aug 2023 12:25:14 +0200 Subject: [PATCH 0392/1483] Add test verifying delta aggregate support --- .../Ada2022/delta_aggr/array/src/pkg.adb | 22 ++++++++++ .../Ada2022/delta_aggr/array/src/pkg.ads | 40 +++++++++++++++++ .../tests/Ada2022/delta_aggr/array/test.py | 11 +++++ .../Ada2022/delta_aggr/record/src/pkg.adb | 30 +++++++++++++ .../Ada2022/delta_aggr/record/src/pkg.ads | 43 +++++++++++++++++++ .../tests/Ada2022/delta_aggr/record/test.py | 11 +++++ .../Ada2022/delta_aggr/src/test_pkg_0.adb | 13 ++++++ .../Ada2022/delta_aggr/src/test_pkg_base.adb | 19 ++++++++ .../Ada2022/delta_aggr/src/test_pkg_comp.adb | 17 ++++++++ .../Ada2022/delta_aggr/src/test_pkg_full.adb | 24 +++++++++++ .../Ada2022/delta_aggr/src/test_pkg_value.adb | 20 +++++++++ testsuite/tests/Ada2022/delta_aggr/tc_set.rst | 18 ++++++++ 12 files changed, 268 insertions(+) create mode 100644 testsuite/tests/Ada2022/delta_aggr/array/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/delta_aggr/array/src/pkg.ads create mode 100644 testsuite/tests/Ada2022/delta_aggr/array/test.py create mode 100644 testsuite/tests/Ada2022/delta_aggr/record/src/pkg.adb create mode 100644 testsuite/tests/Ada2022/delta_aggr/record/src/pkg.ads create mode 100644 testsuite/tests/Ada2022/delta_aggr/record/test.py create mode 100644 testsuite/tests/Ada2022/delta_aggr/src/test_pkg_0.adb create mode 100644 testsuite/tests/Ada2022/delta_aggr/src/test_pkg_base.adb create mode 100644 testsuite/tests/Ada2022/delta_aggr/src/test_pkg_comp.adb create mode 100644 testsuite/tests/Ada2022/delta_aggr/src/test_pkg_full.adb create mode 100644 testsuite/tests/Ada2022/delta_aggr/src/test_pkg_value.adb create mode 100644 testsuite/tests/Ada2022/delta_aggr/tc_set.rst diff --git a/testsuite/tests/Ada2022/delta_aggr/array/src/pkg.adb b/testsuite/tests/Ada2022/delta_aggr/array/src/pkg.adb new file mode 100644 index 000000000..6acf27889 --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/array/src/pkg.adb @@ -0,0 +1,22 @@ +pragma Ada_2022; + +package body Pkg is + + -------------------------- + -- Copy_With_Abs_Update -- + -------------------------- + + function Copy_With_Abs_Update + (Input : Composite; + Item : Item_Type; + Use_Cache : Boolean := False) return Composite + is + Elem : integer renames -- # st + Input (if Item = First then 1 else 2); -- # comp_expr + begin + return -- # st + [(if Use_Cache then Cached_Comp else Input) with delta -- # base_expr_first + (if Item = First then 1 else 2) => -- # comp_expr + (if Elem >= 0 then Elem else -Elem)]; -- # value_expr_first + end Copy_With_Abs_Update; +end Pkg; diff --git a/testsuite/tests/Ada2022/delta_aggr/array/src/pkg.ads b/testsuite/tests/Ada2022/delta_aggr/array/src/pkg.ads new file mode 100644 index 000000000..c149b8ec6 --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/array/src/pkg.ads @@ -0,0 +1,40 @@ +pragma Ada_2012; + +package Pkg is + + type Item_Type is (First, Last); + + type Composite is private; + + Cached_Comp : constant Composite; + + function Make (First, Last : Integer) return Composite; + + function Eq (Comp : Composite; First, Last : Integer) return Boolean; + + function Copy_With_Abs_Update + (Input : Composite; + Item : Item_Type; + Use_Cache : Boolean := False) return Composite; + -- Return a copy of Input or Cached_Comp depending on the value of + -- Use_Cache, with either the "First" or "Last" component being updated to + -- its absolute value. +private + type Composite is array (1 .. 2) of Integer; + + Cached_Comp : constant Composite := (0, 0); + + ---------- + -- Make -- + ---------- + + function Make (First, Last : Integer) return Composite is ((First, Last)); + + -------- + -- Eq -- + -------- + + function Eq (Comp : Composite; First, Last : Integer) return Boolean is + (Comp (1) = First and then Comp (2) = Last); + +end Pkg; diff --git a/testsuite/tests/Ada2022/delta_aggr/array/test.py b/testsuite/tests/Ada2022/delta_aggr/array/test.py new file mode 100644 index 000000000..8a18bd4d2 --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/array/test.py @@ -0,0 +1,11 @@ +""" +Test the correct handling and instrumentation of array delta aggregates +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/delta_aggr/record/src/pkg.adb b/testsuite/tests/Ada2022/delta_aggr/record/src/pkg.adb new file mode 100644 index 000000000..570270d4e --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/record/src/pkg.adb @@ -0,0 +1,30 @@ +pragma Ada_2022; + +package body Pkg is + + -------------------------- + -- Copy_With_Abs_Update -- + -------------------------- + + function Copy_With_Abs_Update + (Input : Composite; + Item : Item_Type; + Use_Cache : Boolean := False) return Composite + is + Elem : constant integer := -- # st + (if Item = First then Input.First else Input.Last); -- # comp_expr + begin + -- We can't dynamically condition which component is used in a record + -- delta aggregate, so in order to emulate the behavior we need to + -- resort to two separate aggregates. This duplicates some decisions, + -- only one will be covered by the driver meant to exercise the + -- specific part of the aggregate. + + return -- # st + ((if Item = First -- # comp_expr + then ((if Use_Cache then Cached_Comp else Input) with delta -- # base_expr_first + First => (if Elem >= 0 then Elem else -Elem)) -- # value_expr_first + else ((if Use_Cache then Cached_Comp else Input) with delta -- # base_expr_last + Last => (if Elem >= 0 then Elem else -Elem)))); -- # value_expr_last + end Copy_With_Abs_Update; +end Pkg; diff --git a/testsuite/tests/Ada2022/delta_aggr/record/src/pkg.ads b/testsuite/tests/Ada2022/delta_aggr/record/src/pkg.ads new file mode 100644 index 000000000..38b60f16a --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/record/src/pkg.ads @@ -0,0 +1,43 @@ +pragma Ada_2012; + +package Pkg is + + type Item_Type is (First, Last); + + type Composite is private; + + Cached_Comp : constant Composite; + + function Make (First, Last : Integer) return Composite; + + function Eq (Comp : Composite; First, Last : Integer) return Boolean; + + function Copy_With_Abs_Update + (Input : Composite; + Item : Item_Type; + Use_Cache : Boolean := False) return Composite; + -- Return a copy of Input or Cached_Comp depending on the value of + -- Use_Cache, with either the "First" or "Last" component being updated to + -- its absolute value. +private + type Composite is record + First : Integer; + Last : Integer; + end record; + + Cached_Comp : constant Composite := (0, 0); + + ---------- + -- Make -- + ---------- + + function Make (First, Last : Integer) return Composite is ((First, Last)); + + -------- + -- Eq -- + -------- + + function Eq (Comp : Composite; First, Last : Integer) return Boolean is + (Comp.First = First and then Comp.Last = Last); + +end Pkg; diff --git a/testsuite/tests/Ada2022/delta_aggr/record/test.py b/testsuite/tests/Ada2022/delta_aggr/record/test.py new file mode 100644 index 000000000..461f85bfb --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/record/test.py @@ -0,0 +1,11 @@ +""" +Test the correct handling and instrumentation of record delta aggregates +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() +thistest.result() diff --git a/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_0.adb b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_0.adb new file mode 100644 index 000000000..4d2bbca3c --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_0.adb @@ -0,0 +1,13 @@ +with Pkg; use Pkg; + +procedure Test_Pkg_0 is +begin + null; +end Test_Pkg_0; + +--# pkg.adb +-- +-- /st/ l- ## s- +-- /base_expr/ l- ## 0 +-- /comp_expr/ l- ## 0 +-- /value_expr/ l- ## 0 diff --git a/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_base.adb b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_base.adb new file mode 100644 index 000000000..4781ded38 --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_base.adb @@ -0,0 +1,19 @@ +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Pkg_Base is + Comp : Composite := Cached_Comp; +begin + Assert (Eq (Copy_With_Abs_Update (Comp, First, True), 0, 0)); + Assert (Eq (Copy_With_Abs_Update (Comp, First, False), 0, 0)); +end Test_Pkg_Base; + +--# pkg.adb +-- +-- /st/ l+ ## 0 +-- /base_expr_last/ l! ## d- +-- /base_expr_first/ l+ ## 0 +-- /comp_expr/ l! ## dF- +-- /value_expr_last/ l! ## d- +-- /value_expr_first/ l! ## dF- diff --git a/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_comp.adb b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_comp.adb new file mode 100644 index 000000000..d99fd7fd0 --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_comp.adb @@ -0,0 +1,17 @@ +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Pkg_Comp is + Comp : Composite := Cached_Comp; +begin + Assert (Eq (Copy_With_Abs_Update (Comp, First, False), 0, 0)); + Assert (Eq (Copy_With_Abs_Update (Comp, Last, False), 0, 0)); +end Test_Pkg_Comp; + +--# pkg.adb +-- +-- /st/ l+ ## 0 +-- /base_expr/ l! ## dT- +-- /comp_expr/ l+ ## 0 +-- /value_expr/ l! ## dF- diff --git a/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_full.adb b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_full.adb new file mode 100644 index 000000000..9efe82a1c --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_full.adb @@ -0,0 +1,24 @@ +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Pkg_Full is + Comp : Composite := Cached_Comp; +begin + Assert (Eq (Copy_With_Abs_Update (Comp, First, True), 0, 0)); + Assert (Eq (Copy_With_Abs_Update (Comp, Last, True), 0, 0)); + Assert (Eq (Copy_With_Abs_Update (Comp, First, False), 0, 0)); + Assert (Eq (Copy_With_Abs_Update (Comp, Last, False), 0, 0)); + Comp := Make (-1, 0); + Assert (Eq (Copy_With_Abs_Update (Comp, First, False), 1, 0)); + Comp := Make (0, -1); + Assert (Eq (Copy_With_Abs_Update (Comp, Last, False), 0, 1)); + +end Test_Pkg_Full; + +--# pkg.adb +-- +-- /st/ l+ ## 0 +-- /base_expr/ l+ ## 0 +-- /comp_expr/ l+ ## 0 +-- /value_expr/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_value.adb b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_value.adb new file mode 100644 index 000000000..228f1fe4e --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/src/test_pkg_value.adb @@ -0,0 +1,20 @@ +with Pkg; use Pkg; + +with Support; use Support; + +procedure Test_Pkg_Value is + Comp : Composite := Cached_Comp; +begin + Assert (Eq (Copy_With_Abs_Update (Comp, First, False), 0, 0)); + Comp := Make (-1, 0); + Assert (Eq (Copy_With_Abs_Update (Comp, First, False), 1, 0)); +end Test_Pkg_Value; + +--# pkg.adb +-- +-- /st/ l+ ## 0 +-- /base_expr_last/ l! ## d- +-- /base_expr_first/ l! ## dT- +-- /comp_expr/ l! ## dF- +-- /value_expr_last/ l! ## d- +-- /value_expr_first/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/delta_aggr/tc_set.rst b/testsuite/tests/Ada2022/delta_aggr/tc_set.rst new file mode 100644 index 000000000..ededabf8b --- /dev/null +++ b/testsuite/tests/Ada2022/delta_aggr/tc_set.rst @@ -0,0 +1,18 @@ +DC on various decisions nested in delta aggregates +================================================== + +Exercise decision coverage on decisions nested within both array and record +delta aggregates. Check for correct handling of nested decisions within the +base expression, in the index expression as well as in the component value +expression. The tests are organized such that each test exercises all three +possible decisions in a delta aggregate for the construct corresponding to the +test directory name. + +The Test_Pkg_0 driver tests ensures only SC violations are reported when the +code in the unit of interest is not executed, Test_Pkg_Base verifies proper DC +of decisions present in the base expression of the delta aggregate, +Test_Pkg_Comp ensures proper DC computation for decisions nested in the +component index expression of the delta aggregate, Test_Pkg_Value ensures that +decisions within the component value expression are properly processed, and +Test_Pkg_Full demonstrates decision coverage being exercised for all three +possible nested decisions at the same time. From 842cfe8877627e8a19a22e643d5e4aa6685abb7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 4 Sep 2023 11:46:02 +0200 Subject: [PATCH 0393/1483] Instrument.Common: Do not warn for big BDD in stmt+decision gnatcov emits a warning when encountering a decision with too many paths to keep track of. This warning is not relevant for decision coverage as the non instrumentation of the individual conditions does not affect the accuracy of the coverage report for level stmt+decision. This change removes the warning when MC/DC coverage is not enabled. --- testsuite/tests/U416-006-big-bdd/test.py | 94 +++++++++++++++--------- tools/gnatcov/instrument-common.adb | 2 +- 2 files changed, 60 insertions(+), 36 deletions(-) diff --git a/testsuite/tests/U416-006-big-bdd/test.py b/testsuite/tests/U416-006-big-bdd/test.py index 84dd20643..a64b37deb 100644 --- a/testsuite/tests/U416-006-big-bdd/test.py +++ b/testsuite/tests/U416-006-big-bdd/test.py @@ -14,30 +14,7 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir("tmp_") - -gpr = gprfor(mains=["test_eval.adb"], srcdirs=["../src"], langs=["Ada", "C"]) - -build_run_and_coverage( - gprsw=GPRswitches(root_project=gpr), - extra_coverage_args=["--annotate=xcov"], - covlevel="stmt+mcdc", - mains=["test_eval"], - trace_mode="src", - tolerate_instrument_messages=\ - "Number of distinct paths .* exceeds the limit", -) - -check_xcov_reports( - "*.xcov", - expected_cov={ - "test_eval.adb.xcov": {"+": {11, 13, 19, 20}}, - "testconditions.adb.xcov": {"?": {17}, "+": {22, 23, 24, 25, 26, 27}}, - "compute.c.xcov": {"?": {4}, "+": {5, 6}}, - }, - cwd="obj", -) - +tmp = Wdir() def warning_re_for(filename, sloc): """ @@ -53,17 +30,64 @@ def warning_re_for(filename, sloc): ).format(filename=re.escape(filename), sloc=re.escape(sloc)) -# The order in which sources are instrumented is not specified, so sort lines -# in the output of "gnatcov instrument" to get deterministic test execution. -log = "\n".join(sorted(contents_of("instrument.log").splitlines())) +def do_one_level(level): + tmp.to_subdir(f"tmp_{level}") + thistest.log(f"===== {level} =====") + + gpr = gprfor(mains=["test_eval.adb"], srcdirs=["../src"], langs=["Ada", "C"]) + + build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + extra_coverage_args=["--annotate=xcov"], + covlevel=level, + mains=["test_eval"], + trace_mode="src", + tolerate_instrument_messages=( + "Number of distinct paths .* exceeds the limit" + if level == "stmt+mcdc" + else None + ), + ) + + expected_cov = { + "test_eval.adb.xcov": {"+": {11, 13, 19, 20}}, + "testconditions.adb.xcov": {"+": {22, 23, 24, 25, 26, 27}}, + "compute.c.xcov": {"+": {5, 6}}, + } + + # For stmt+decision, the BDD is still computed, but the non-instrumentation + # of the conditions has no impact on stmt+decision coverage reports. + # As such, we expect no warnings or errors in the log and no undetermined + # coverage items in the report. + + if level == "stmt+mcdc": + expected_cov["testconditions.adb.xcov"]['?'] = {17} + expected_cov["compute.c.xcov"]['?'] = {4} + else: + expected_cov["testconditions.adb.xcov"]['+'].add(17) + expected_cov["compute.c.xcov"]['+'].add(4) + + check_xcov_reports("*.xcov", expected_cov, cwd="obj") + + if level == "stmt+mcdc": + # The order in which sources are instrumented is not specified, so sort + # lines in the output of "gnatcov instrument" to get deterministic test + # execution. + log = "\n".join(sorted(contents_of("instrument.log").splitlines())) + + thistest.fail_if_no_match( + what="Unexpected/missing warnings for MC/DC path limit", + regexp="^" + "\n".join([ + warning_re_for("compute.c", "4:11"), + warning_re_for("testconditions.adb", "17:9"), + ]), + actual=log, + ) + +# Run the mcdc case +do_one_level("stmt+mcdc") -thistest.fail_if_no_match( - what="Unexpected/missing warnings for MC/DC path limit", - regexp="^" + "\n".join([ - warning_re_for("compute.c", "4:11"), - warning_re_for("testconditions.adb", "17:9"), - ]), - actual=log, -) +# Then the decision case +do_one_level("stmt+decision") thistest.result() diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index f31c7ed72..acd3b2841 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -201,7 +201,7 @@ package body Instrument.Common is -- Warn if the number of paths exceeded the limit - if Path_Count = 0 then + if Path_Count = 0 and then Coverage.MCDC_Coverage_Enabled then Diagnostics.Report (Decision_Sloc, "Number of distinct paths in the decision exceeds the limit" From d567eeaae87e1237a4dd17a9df07ef707a838062 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 6 Sep 2023 09:41:59 +0000 Subject: [PATCH 0394/1483] strings.adb: fix Has_Prefix/Suffix for equal strings "X" is a valid prefix/suffix substrings for the "X" string. Adjust Has_Prefix and Has_Suffix accordingly. --- tools/gnatcov/strings.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/strings.adb b/tools/gnatcov/strings.adb index b7c343fc2..93c48a729 100644 --- a/tools/gnatcov/strings.adb +++ b/tools/gnatcov/strings.adb @@ -77,7 +77,7 @@ package body Strings is function Has_Prefix (S : String; Prefix : String) return Boolean is Length : constant Integer := Prefix'Length; begin - return S'Length > Length + return S'Length >= Length and then S (S'First .. S'First + Length - 1) = Prefix; end Has_Prefix; @@ -88,7 +88,7 @@ package body Strings is function Has_Suffix (S : String; Suffix : String) return Boolean is Length : constant Integer := Suffix'Length; begin - return S'Length > Length + return S'Length >= Length and then S (S'Last - Length + 1 .. S'Last) = Suffix; end Has_Suffix; From e5b1033294e7dfb6872f678517e1c8003964b969 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 6 Sep 2023 09:43:10 +0000 Subject: [PATCH 0395/1483] gnatcov extract-base64-trace: add support for arbitrary line prefixes Enhance the extract-base64-trace command so that it can handle base64 trace data with arbitrary line prefixes: PREFIX> == GNATcoverage source trace file == PREFIX> ... PREFIX> == End == --- .../tests/instr-cov/base64_prefix/main1.adb | 6 + .../tests/instr-cov/base64_prefix/main2.adb | 6 + .../tests/instr-cov/base64_prefix/pkg.adb | 18 ++ .../tests/instr-cov/base64_prefix/pkg.ads | 3 + .../tests/instr-cov/base64_prefix/test.py | 100 +++++++++ tools/gnatcov/instrument-input_traces.adb | 209 +++++++++++++----- 6 files changed, 283 insertions(+), 59 deletions(-) create mode 100644 testsuite/tests/instr-cov/base64_prefix/main1.adb create mode 100644 testsuite/tests/instr-cov/base64_prefix/main2.adb create mode 100644 testsuite/tests/instr-cov/base64_prefix/pkg.adb create mode 100644 testsuite/tests/instr-cov/base64_prefix/pkg.ads create mode 100644 testsuite/tests/instr-cov/base64_prefix/test.py diff --git a/testsuite/tests/instr-cov/base64_prefix/main1.adb b/testsuite/tests/instr-cov/base64_prefix/main1.adb new file mode 100644 index 000000000..ad381071c --- /dev/null +++ b/testsuite/tests/instr-cov/base64_prefix/main1.adb @@ -0,0 +1,6 @@ +with Pkg; use Pkg; + +procedure Main1 is +begin + Print_Message (Goodbye => False); +end Main1; diff --git a/testsuite/tests/instr-cov/base64_prefix/main2.adb b/testsuite/tests/instr-cov/base64_prefix/main2.adb new file mode 100644 index 000000000..fca526d77 --- /dev/null +++ b/testsuite/tests/instr-cov/base64_prefix/main2.adb @@ -0,0 +1,6 @@ +with Pkg; use Pkg; + +procedure Main2 is +begin + Print_Message (Goodbye => True); +end Main2; diff --git a/testsuite/tests/instr-cov/base64_prefix/pkg.adb b/testsuite/tests/instr-cov/base64_prefix/pkg.adb new file mode 100644 index 000000000..6db039d88 --- /dev/null +++ b/testsuite/tests/instr-cov/base64_prefix/pkg.adb @@ -0,0 +1,18 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + ------------------- + -- Print_Message -- + ------------------- + + procedure Print_Message (Goodbye : Boolean) is + begin + if Goodbye then + Put_Line ("Goodbye!"); + else + Put_Line ("Hello!"); + end if; + end Print_Message; + +end Pkg; diff --git a/testsuite/tests/instr-cov/base64_prefix/pkg.ads b/testsuite/tests/instr-cov/base64_prefix/pkg.ads new file mode 100644 index 000000000..127352e3c --- /dev/null +++ b/testsuite/tests/instr-cov/base64_prefix/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Print_Message (Goodbye : Boolean); +end Pkg; diff --git a/testsuite/tests/instr-cov/base64_prefix/test.py b/testsuite/tests/instr-cov/base64_prefix/test.py new file mode 100644 index 000000000..9d01c567a --- /dev/null +++ b/testsuite/tests/instr-cov/base64_prefix/test.py @@ -0,0 +1,100 @@ +""" +Check that "gnatcov extract-base64-trace" can extract trace data from outputs +with arbitrary line prefixes. +""" + +import itertools + +from SCOV.instr import xcov_convert_base64, xcov_instrument +from SCOV.minicheck import check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import exepath_to, gprbuild, gprfor, run_cov_program, xcov + +tmp = Wdir("tmp_") + +# Instrument and build the test project +p = GPRswitches( + root_project=gprfor(srcdirs="..", mains=["main1.adb", "main2.adb"]), + units=["pkg"], +) +xcov_instrument( + gprsw=p, + covlevel="stmt", + dump_trigger="main-end", + dump_channel="base64-stdout", +) +gprbuild(p.root_project, trace_mode="src") + +# Run the two programs, saving their output +mains = ["main1", "main2"] +out_files = [f"{m}_output.txt" for m in mains] + +for main, out_file in zip(mains, out_files): + run_cov_program(exepath_to(main), out=out_file) + +# Expected coverage report for both program executions: +main1_cov = {"pkg.adb.xcov": {"+": {11, 14}, "-": {12}}} +main2_cov = {"pkg.adb.xcov": {"+": {11, 12}, "-": {14}}} + +# Now combine them with different prefixes and check that "gnatcov +# extract-base64-trace" correctly loads the last one. +for label, interleaved_outputs, trailing_output, cov in [ + ("main1_first", out_files, None, main1_cov), + ("main2_first", [out_files[1], out_files[0]], None, main2_cov), + ("main2_trail", [out_files[0]], out_files[1], main2_cov), +]: + thistest.log(f"== {label} ==") + + tracedata_filename = f"{label}_trace_data.txt" + trace_filename = f"{label}.srctrace" + + traces_lines = [] + for i, filename in enumerate(interleaved_outputs): + with open(filename) as f: + traces_lines.append((f"DATA{i}> ", f.readlines())) + + if trailing_output is None: + trailing_lines = [] + else: + with open(trailing_output) as f: + trailing_lines = f.readlines() + + # Interleave all lines to make sure that once gnatcov detects a source + # trace with some prefix, it filters that prefix only until the end of the + # source trace. + with open(tracedata_filename, "w") as f: + for i in itertools.count(0): + had_line = False + for prefix, lines in traces_lines: + if i >= len(lines): + continue + had_line = True + f.write(prefix) + f.write(lines[i]) + if not had_line: + break + + for line in trailing_lines: + f.write("TRAILING> ") + f.write(line) + + # Now run the source trace conversion and create a coverage report from it + xcov_convert_base64(tracedata_filename, trace_filename) + xcov_dir = f"xcov-{label}" + xcov( + [ + "coverage", + "-P", + p.root_project, + "--level=stmt", + "--annotate=xcov", + "--output-dir", + xcov_dir, + trace_filename, + ] + ) + check_xcov_reports("*.xcov", cov, cwd=xcov_dir) + +thistest.result() diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 18da8e0a4..a6f5483f5 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -998,6 +998,14 @@ package body Instrument.Input_Traces is Start_Marker : constant String := "== GNATcoverage source trace file =="; End_Marker : constant String := "== End =="; + Started_Trace : Boolean := False; + -- Whether we are in the middle of reading a source trace + + Prefix : String (1 .. 200) := (others => ASCII.NUL); + Prefix_Last : Natural := 0; + -- If Started_Trace is True, line prefix for the base64 dump for that + -- source trace. + -- Start of processing for Extract_Base64_Trace begin @@ -1005,12 +1013,49 @@ package body Instrument.Input_Traces is -- way to "continue" the loop (i.e. skip to the next iteration), which -- simplifies the loop body. -- - -- Each time we come across a Start_Marker line, create the output trace - -- file, so that if there are several start/end couples in the input - -- file, we consider only the last one. This is convenient when running - -- GNATcoverage's testsuite, as we may have one trace per task - -- termination and this also makes sense in real life: the last trace - -- should be the one with the final coverage state. + -- Each time we come across a line that ends with Start_Marker, create + -- the output source trace file, take note of the rest of the line as + -- "the prefix" and ignore the next lines that do not have the same + -- prefix, then process all lines until finding a line with the + -- End_Marker. Then repeat with the remaining lines if another line ends + -- with Start_Marker. + -- + -- For instance: + -- + -- A> == GNATcoverage source trace file == + -- B> == GNATcoverage source trace file == + -- A> ... + -- A> == End == + -- B> ... + -- B> == End == + -- + -- will create a source trace file for all lines with the "A> " prefix, + -- whereas: + -- + -- A> == GNATcoverage source trace file == + -- B> == GNATcoverage source trace file == + -- A> ... + -- A> == End == + -- B> ... + -- C> == GNATcoverage source trace file == + -- B> == End == + -- C> ... + -- C> == End == + -- + -- will first create a source trace file for all lines with the "A> " + -- prefix, then overwrite it with a file for all lines with the "C> " + -- prefix. + -- + -- The prefix-related rules allow the processing of source traces for a + -- program with several concurrent traces dumps, as long as lines are + -- printed atomically and as long as each tasks writes a dedicated line + -- prefix. + -- + -- The overwriting rules ensures that if there are several start/end + -- marker couples in the input file, we consider only the last one. This + -- is convenient when running GNATcoverage's testsuite, as we may have + -- one trace per task termination and this also makes sense in real + -- life: the last trace should be the one with the final coverage state. TIO.Open (Input, TIO.In_File, Input_File); <> @@ -1018,10 +1063,10 @@ package body Instrument.Input_Traces is declare use type TIO.Count; - Reading_Trace : constant Boolean := BIO.Is_Open (Output); - Buffer : String (1 .. 100); - First : Positive := 1; - Last : Natural; + Buffer : String (1 .. 200); + Ignore_Line : Boolean; + First : Positive := 1; + Last : Natural; begin -- Try to read a line, abort if we reached the end of file @@ -1032,11 +1077,25 @@ package body Instrument.Input_Traces is exit; end; + -- Remove leading/trailing whitespaces, which copy/pasting may + -- insert. + + Trim (Buffer, First, Last); + + -- If we are in the middle of reading a source trace, ignore lines + -- that do not have the same prefix. + + Ignore_Line := + Started_Trace + and then not Has_Prefix (Buffer (First .. Last), + Prefix (Prefix'First .. Prefix_Last)); + -- If the line is too long for our buffer: -- - -- * If we are in the middle of reading a source trace, stop with - -- an error: this is not supposed to happen as we dump source - -- traces with at most 80-columns wide lines. + -- * If that line has the current prefix and we are in the middle + -- of reading a source trace, stop with an error: this is not + -- supposed to happen as we dump source traces with at most + -- 80-columns wide lines. -- -- * Otherwise, just skip that line. -- @@ -1047,7 +1106,7 @@ package body Instrument.Input_Traces is -- previous line in one go). if not TIO.End_Of_Line (Input) and then TIO.Col (Input) > 1 then - if Reading_Trace then + if Started_Trace and then not Ignore_Line then Outputs.Fatal_Error ("Unexpected long line in Base64 trace"); else @@ -1056,64 +1115,95 @@ package body Instrument.Input_Traces is end if; end if; - -- Remove leading/trailing whitespaces, which copy/pasting may - -- insert. + -- If this line does not have the expected prefix, ignore it - Trim (Buffer, First, Last); + if Ignore_Line then + goto Read_Next_Line; - if Reading_Trace then - if Buffer (First .. Last) = End_Marker then - BIO.Close (Output); - goto Read_Next_Line; - end if; + -- If we have not started reading a trace, check if the current + -- line is the beginning of a trace. - -- Expect groups of 4 characters + elsif not Started_Trace then - if Buffer (First .. Last)'Length mod 4 /= 0 then - Outputs.Fatal_Error - ("Invalid Base64 trace: incomplete group of 4 characters"); + -- If this is the beginning of a trace, keep track of the + -- current line prefix and open the source trace file to write. + + if Has_Suffix (Buffer (First .. Last), Start_Marker) then + Had_One_Trace := True; + Started_Trace := True; + declare + Prefix_Length : constant Natural := + Last - First + 1 - Start_Marker'Length; + begin + Prefix_Last := Prefix_Length + Prefix'First - 1; + Prefix (Prefix'First .. Prefix_Last) := + Buffer (First .. First + Prefix_Length - 1); + end; + BIO.Create (Output, BIO.Out_File, Output_File); end if; - -- Now process each group + goto Read_Next_Line; + end if; - declare - Next : Positive := First; + -- If execution reaches this point, we know that we are in the + -- middle of processing a source trace. Adjust First to strip the + -- line prefix. - function D (Index : Natural) return Unsigned_8 - is (Base64_Digit (Buffer (Next + Index))); + pragma Assert (Started_Trace); + First := First + Prefix_Last - Prefix'First + 1; - begin - while Next <= Last loop - -- Here, process the Base64 digits in the slice: - -- - -- Buffer (Next .. Next + 3) - -- - -- This slice contains 4 Base64 digits, and each digit - -- encodes 6 bits (total: 24 bits), so we can decode 3 - -- bytes (3 * 8 bits). The actual number of bytes to - -- decode depends on the amount of padding characters - -- ('=' character). + -- If we reached the end of this source trace, close the file and + -- go to the next line. + + if Buffer (First .. Last) = End_Marker then + BIO.Close (Output); + Started_Trace := False; + goto Read_Next_Line; + end if; + + -- Otherwise, expect the rest of the line to be a groups of 4 + -- base64 characters. + + if Buffer (First .. Last)'Length mod 4 /= 0 then + Outputs.Fatal_Error + ("Invalid Base64 trace: incomplete group of 4 characters"); + end if; + + -- Now process each group + + declare + Next : Positive := First; + function D (Index : Natural) return Unsigned_8 + is (Base64_Digit (Buffer (Next + Index))); + + begin + while Next <= Last loop + -- Here, process the Base64 digits in the slice: + -- + -- Buffer (Next .. Next + 3) + -- + -- This slice contains 4 Base64 digits, and each digit + -- encodes 6 bits (total: 24 bits), so we can decode 3 + -- bytes (3 * 8 bits). The actual number of bytes to + -- decode depends on the amount of padding characters + -- ('=' character). + + BIO.Write + (Output, + Shift_Left (D (0), 2) or Shift_Right (D (1), 4)); + if Buffer (Next + 2) /= '=' then BIO.Write (Output, - Shift_Left (D (0), 2) or Shift_Right (D (1), 4)); - if Buffer (Next + 2) /= '=' then - BIO.Write - (Output, - Shift_Left (D (1), 4) or Shift_Right (D (2), 2)); - if Buffer (Next + 3) /= '=' then - BIO.Write (Output, Shift_Left (D (2), 6) or D (3)); - end if; + Shift_Left (D (1), 4) or Shift_Right (D (2), 2)); + if Buffer (Next + 3) /= '=' then + BIO.Write (Output, Shift_Left (D (2), 6) or D (3)); end if; + end if; - Next := Next + 4; - end loop; - end; - - elsif Buffer (First .. Last) = Start_Marker then - Had_One_Trace := True; - BIO.Create (Output, BIO.Out_File, Output_File); - end if; + Next := Next + 4; + end loop; + end; end; end loop; TIO.Close (Input); @@ -1123,7 +1213,8 @@ package body Instrument.Input_Traces is if not Had_One_Trace then Outputs.Fatal_Error ("No Base64 trace found"); - elsif BIO.Is_Open (Output) then + elsif Started_Trace then + BIO.Close (Output); Outputs.Fatal_Error ("Incomplete Base64 trace"); end if; end Extract_Base64_Trace; From e1ba25695551ad8f3e3386853a0fca7dfaa8a3e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 7 Sep 2023 17:57:57 +0200 Subject: [PATCH 0396/1483] Document iterator filters are considered as decisions Iterator filters, introduced with Ada 2022, can control the flow of the program. As such when adding support for this construct, the tool now considers their predicate as decisions for decision level coverage. This change documents this in the user guide. --- doc/gnatcov/cov_source.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index 97dd8166a..edf87ac0d 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -777,6 +777,10 @@ performs Statement and Decision Coverage assessments combined together. * The iteration predicate of Ada quantified expressions, in the same contexts as for if-expressions. +* The iterator filter predicate optionally present in a loop parameter + specification or in an iterator specification, in the same context as + if-expressions. + The expression may be of essentially any type in C. In Ada, this may be the standard Boolean type, or subtypes of it, or derived types thereof. Here are a few examples show-casing decisions in a variety of @@ -793,6 +797,9 @@ contexts:: Z := (for all X of Container => P(X)); -- "P(X)", quantified-expression predicate T := (for some X of Container => P(X)); + for I in 1 .. 10 when (I mod 2) = 0 loop ... -- "(I mod 2) = 0", iterator filter predicate + F := (for Elt of Container when Pred (Elt) => Elt); -- "Pred (Elt)", iterator filter predicate + The coverage status of a decision obligation is determined as follows: From 3ffa0224b49e9b44af39b1bc43a6792a67ced9c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 21 Jun 2023 13:47:08 +0200 Subject: [PATCH 0397/1483] Improve the usability of manual dump trigger When using the manual dump trigger option, one dump helper unit per project is generated containing everything needed to perform a call to its buffers dumping procedure anywhere in the code. gnatcov will look for the pragma statement 'pragma Annotate (Xcov, Dump_Buffers)' (for Ada) or the comment '/* GNATCOV_DUMP_BUFFERS */ (for C) in all sources and replace it with the actual call. --- doc/gnatcov/src_traces.rst | 16 +- testsuite/SCOV/minicheck.py | 24 +- testsuite/SUITE/tutils.py | 19 +- .../ada_manual_dump/src-lib1/lib1.adb | 9 + .../ada_manual_dump/src-lib1/lib1.ads | 3 + .../ada_manual_dump/src-lib2/lib2.adb | 9 + .../ada_manual_dump/src-lib2/lib2.ads | 3 + .../instr-cov/ada_manual_dump/src/main.adb | 30 ++ .../ada_manual_dump/src/manual_dump.adb | 6 + .../ada_manual_dump/src/manual_dump.ads | 3 + .../tests/instr-cov/ada_manual_dump/test.opt | 1 + .../tests/instr-cov/ada_manual_dump/test.py | 66 ++++ .../src-lib1/lib1.adb | 12 + .../src-lib1/lib1.ads | 3 + .../src-lib1/src-lib3/lib3.adb | 8 + .../src-lib1/src-lib3/lib3.ads | 3 + .../src-lib2/lib2.adb | 9 + .../src-lib2/lib2.ads | 3 + .../ada_manual_no_dump_in_root/src/main.adb | 27 ++ .../ada_manual_no_dump_in_root/test.opt | 1 + .../ada_manual_no_dump_in_root/test.py | 73 +++++ .../instr-cov/c_manual_dump/src-lib/foo.c | 9 + .../instr-cov/c_manual_dump/src-lib/foo.h | 1 + .../tests/instr-cov/c_manual_dump/src/main.c | 27 ++ .../tests/instr-cov/c_manual_dump/test.opt | 1 + .../tests/instr-cov/c_manual_dump/test.py | 57 ++++ testsuite/tests/instr-cov/manual-dump/test.py | 4 + tools/gnatcov/ali_files.ads | 2 +- tools/gnatcov/clang-extensions.adb | 18 ++ tools/gnatcov/clang-extensions.ads | 2 + tools/gnatcov/clang-wrapper.cc | 38 ++- tools/gnatcov/coverage-source.adb | 3 +- tools/gnatcov/instrument-ada_unit.adb | 228 ++++++++++++- tools/gnatcov/instrument-ada_unit.ads | 21 ++ tools/gnatcov/instrument-c.adb | 236 +++++++++++--- tools/gnatcov/instrument-c.ads | 26 ++ tools/gnatcov/instrument-common.adb | 15 + tools/gnatcov/instrument-common.ads | 43 ++- tools/gnatcov/instrument-projects.adb | 301 +++++++++++++++--- tools/gnatcov/project.adb | 17 +- tools/gnatcov/project.ads | 8 +- 41 files changed, 1261 insertions(+), 124 deletions(-) create mode 100644 testsuite/tests/instr-cov/ada_manual_dump/src-lib1/lib1.adb create mode 100644 testsuite/tests/instr-cov/ada_manual_dump/src-lib1/lib1.ads create mode 100644 testsuite/tests/instr-cov/ada_manual_dump/src-lib2/lib2.adb create mode 100644 testsuite/tests/instr-cov/ada_manual_dump/src-lib2/lib2.ads create mode 100644 testsuite/tests/instr-cov/ada_manual_dump/src/main.adb create mode 100644 testsuite/tests/instr-cov/ada_manual_dump/src/manual_dump.adb create mode 100644 testsuite/tests/instr-cov/ada_manual_dump/src/manual_dump.ads create mode 100644 testsuite/tests/instr-cov/ada_manual_dump/test.opt create mode 100644 testsuite/tests/instr-cov/ada_manual_dump/test.py create mode 100644 testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.adb create mode 100644 testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.ads create mode 100644 testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.adb create mode 100644 testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.ads create mode 100644 testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib2/lib2.adb create mode 100644 testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib2/lib2.ads create mode 100644 testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src/main.adb create mode 100644 testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.opt create mode 100644 testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.py create mode 100644 testsuite/tests/instr-cov/c_manual_dump/src-lib/foo.c create mode 100644 testsuite/tests/instr-cov/c_manual_dump/src-lib/foo.h create mode 100644 testsuite/tests/instr-cov/c_manual_dump/src/main.c create mode 100644 testsuite/tests/instr-cov/c_manual_dump/test.opt create mode 100644 testsuite/tests/instr-cov/c_manual_dump/test.py diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 5e7c91446..0234cdbd2 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -273,12 +273,20 @@ For more restricted environments where, say, there is limited file IO available to the program, a ``--dump-channel=base64-stdout`` kind of output is needed in association with the restricted coverage runtime. -If none of the available automatic triggering option works out well, full +If none of the available automatic triggering option work out well, full control is offered by the ``--dump-trigger=manual`` policy where the instrumenter doesn't actually add any code to main units for emitting the -collected coverage data. You will have to emit this data somehow to allow -analysing coverage afterwards, still, and can of course experiment with other -possibilities just to get examples of possible ways to proceed. +collected coverage data. You will have to indicate the point at which you wish +to emit this data by inserting: + +- a ``pragma Annotate (Xcov, Dump_Buffers);`` pragma statement in Ada code; +- a ``/* GNATCOV_DUMP_BUFFERS */`` comment on its own line in C code + +where necessary in your code. During instrumentation, |gcv| will replace them +with a call to the procedure responsible for dumping the coverage buffers, +at which point the source traces will be created during the execution of the +program. Therefore, the pragma or comment should be placed at a location at +which such a function call would be appropriate. .. _instr-tracename: diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 7a325cf3e..79241fa94 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -37,7 +37,7 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, gprsw_for_coverage=None, scos_for_run=True, register_failure=True, program_env=None, tolerate_instrument_messages=None, exec_args=None, - auto_languages=True): + auto_languages=True, manual_prj_name=None): """ Prepare a project to run a coverage analysis on it. @@ -108,6 +108,10 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, :param None|list[str] exec_args: List of arguments to pass to the executable. This will only work for native configurations. :param bool auto_languages: See SUITE.tutils.xcov. + :param None|str manual_proj_name: when the dump trigger is manual, several + traces files (one per project) can be emitted if there are dump buffers + procedure calls in at least two distinct projects. This is the name of + the project which trace we want to consider. :rtype: list[str] :return: Incomplete list of arguments to pass to `xcov` in order to run @@ -283,7 +287,9 @@ def gprbuild_wrapper(root_project): # Remove potential existing source trace files: the name is # non-deterministic by default, so we want to avoid getting # multiple traces in the current directory. - rm(srctrace_pattern_for(m)) + rm(srctrace_pattern_for(m, + dump_trigger == "manual", + manual_prj_name)) out_file = out_file_.format(m) run_cov_program(exepath(m), out=out_file, env=program_env, @@ -307,14 +313,20 @@ def gprbuild_wrapper(root_project): trace_file = None if known_channel in [None, "bin-file"]: - trace_file = srctracename_for(m, register_failure=False) + trace_file = srctracename_for(m, + register_failure=False, + manual=dump_trigger == "manual", + manual_prj_name=manual_prj_name) if (not trace_file and (known_channel == "base64-stdout" - or "source trace file ==" in contents_of(out_file)) - ): + or "source trace file ==" in contents_of(out_file))): + # Pick a trace name that is compatible with srctracename_for - trace_file = srctrace_pattern_for(m).replace("*", "unique") + src_pattern = srctrace_pattern_for(m, + dump_trigger == "manual", + manual_prj_name) + trace_file = src_pattern.replace("*", "unique") # Here we're really supposed to have a trace in the output # so we can be a tad stricter on the conversion outcome. diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 0e37468d1..7f1e6594d 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -453,12 +453,21 @@ def tracename_for(pgmname): return exename_for(pgmname) + ".trace" -def srctrace_pattern_for(pgmname): - """Glob pattern for the source trace file for the given program name""" - return exename_for(pgmname) + "*.srctrace" +def srctrace_pattern_for(pgmname, manual=False, manual_prj_name=None): + """ + Glob pattern for the source trace file for the given program name. + + :param bool manual: Indicates if the trace file was created as a result of + a manual dump buffers procedure call. + :param None|str manual_prj_name: Trace files emitted in manual dump trigger + mode contain the name of the relevant project in their name. + manual_prj_name is the name of the project which trace we want to find. + """ + return (manual_prj_name if manual else exename_for(pgmname)) + "*.srctrace" -def srctracename_for(pgmname, register_failure=True): +def srctracename_for(pgmname, register_failure=True, manual=False, + manual_prj_name=None): """ Name for the source trace file for the given program name. @@ -470,7 +479,7 @@ def srctracename_for(pgmname, register_failure=True): stops the testcase. If "register_failure" is False, we just return None in that case. """ - pattern = srctrace_pattern_for(pgmname) + pattern = srctrace_pattern_for(pgmname, manual, manual_prj_name) trace_files = glob.glob(pattern) if len(trace_files) == 1: diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src-lib1/lib1.adb b/testsuite/tests/instr-cov/ada_manual_dump/src-lib1/lib1.adb new file mode 100644 index 000000000..3db35b9fd --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_dump/src-lib1/lib1.adb @@ -0,0 +1,9 @@ +package body Lib1 is + function Foo return Integer + is + Res : constant Integer := 1; + begin + pragma Annotate (Xcov, Dump_Buffers); + return Res; + end Foo; +end Lib1; diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src-lib1/lib1.ads b/testsuite/tests/instr-cov/ada_manual_dump/src-lib1/lib1.ads new file mode 100644 index 000000000..aaa69a16f --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_dump/src-lib1/lib1.ads @@ -0,0 +1,3 @@ +package Lib1 is + function Foo return Integer; +end Lib1; diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src-lib2/lib2.adb b/testsuite/tests/instr-cov/ada_manual_dump/src-lib2/lib2.adb new file mode 100644 index 000000000..326f4aa54 --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_dump/src-lib2/lib2.adb @@ -0,0 +1,9 @@ +package body Lib2 is + function Bar return Integer + is + Res : constant Integer := 1; + begin + pragma Annotate (Xcov, Dump_Buffers); + return Res; + end Bar; +end Lib2; diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src-lib2/lib2.ads b/testsuite/tests/instr-cov/ada_manual_dump/src-lib2/lib2.ads new file mode 100644 index 000000000..7968b33bf --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_dump/src-lib2/lib2.ads @@ -0,0 +1,3 @@ +package Lib2 is + function Bar return Integer; +end Lib2; diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src/main.adb b/testsuite/tests/instr-cov/ada_manual_dump/src/main.adb new file mode 100644 index 000000000..6242717d5 --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_dump/src/main.adb @@ -0,0 +1,30 @@ +pragma Ada_2012; + +with Lib1; +with Lib2; +with Manual_Dump; + +procedure Main is + + procedure Increment (J : in out Integer) + is + begin + J := J + 1; + end Increment; + + I : Integer := 1; +begin + -- The only call that should not count as a violation when never executed + -- is that of the dump buffers procedure. + if 1 = I + 1 then + pragma Annotate (Xcov, Dump_Buffers); + I := I+ 1; + end if; + + Increment (I); + pragma Annotate (Xcov, Dump_Buffers); + I := I + Lib1.Foo; + I := I + Lib2.Bar; + Manual_Dump.Dump; + Increment (I); +end Main; diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src/manual_dump.adb b/testsuite/tests/instr-cov/ada_manual_dump/src/manual_dump.adb new file mode 100644 index 000000000..16b06f89c --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_dump/src/manual_dump.adb @@ -0,0 +1,6 @@ +package body Manual_Dump is + procedure Dump is + begin + pragma Annotate (Xcov, Dump_Buffers); + end Dump; +end Manual_Dump; diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src/manual_dump.ads b/testsuite/tests/instr-cov/ada_manual_dump/src/manual_dump.ads new file mode 100644 index 000000000..898439fa6 --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_dump/src/manual_dump.ads @@ -0,0 +1,3 @@ +package Manual_Dump is + procedure Dump; +end Manual_Dump; diff --git a/testsuite/tests/instr-cov/ada_manual_dump/test.opt b/testsuite/tests/instr-cov/ada_manual_dump/test.opt new file mode 100644 index 000000000..a322c0d34 --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_dump/test.opt @@ -0,0 +1 @@ +!src-traces DEAD Checks a feature specific the instrumenter diff --git a/testsuite/tests/instr-cov/ada_manual_dump/test.py b/testsuite/tests/instr-cov/ada_manual_dump/test.py new file mode 100644 index 000000000..7f098af4e --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_dump/test.py @@ -0,0 +1,66 @@ +""" +Test that when using manual dump trigger in Ada with a specific pragma +indicating where to dump the coverage buffers, gnatcov is able to replace it +with a call to the dump buffers procedure and output correct traces. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir('tmp_') + +lib1_p = gprfor(mains=[], + prjid="lib1", + srcdirs="../src-lib1", + objdir="obj-lib1", + langs=["Ada"], + ) + +lib2_p = gprfor(mains=[], + prjid="lib2", + srcdirs="../src-lib2", + objdir="obj-lib2", + langs=["Ada"], + ) + +p = gprfor(mains=["main.adb"], + srcdirs=["../src"], + objdir="obj", + deps=["lib1", "lib2"]) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p, units=["lib1", "main"]), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src', + dump_trigger="manual", + manual_prj_name="gen") + +# Check that gnatcov inserted the call to the dump buffers procedure in the +# lib2.adb which is not a unit of interest + + +def check_call(file): + thistest.fail_if_no_match("missing dump buffers procedure call", + "(\n|.)*GCVRT.DB_manual_lib2.Dump_Buffers;" + "(\n|.)*", + contents_of(file)) + + +check_call('obj-lib2/lib2-gnatcov-instr/lib2.adb') + +# Check that we get the expected coverage reports + +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'+': {12, 15, 19, 24, 26, 27, 28}, + '-': {21, 29}}, + 'xcov/lib1.adb.xcov': {'+': {4, 7}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.adb b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.adb new file mode 100644 index 000000000..b9ef383b4 --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.adb @@ -0,0 +1,12 @@ +with Lib3; + +package body Lib1 is + function Foo return Integer + is + Res : Integer := 1; + begin + Res := Res + Lib3.Baz; + pragma Annotate (Xcov, Dump_Buffers); + return Res; + end Foo; +end Lib1; diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.ads b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.ads new file mode 100644 index 000000000..aaa69a16f --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.ads @@ -0,0 +1,3 @@ +package Lib1 is + function Foo return Integer; +end Lib1; diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.adb b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.adb new file mode 100644 index 000000000..57507a918 --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.adb @@ -0,0 +1,8 @@ +package body Lib3 is + function Baz return Integer + is + Res : constant Integer := 1; + begin + return Res; + end Baz; +end Lib3; diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.ads b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.ads new file mode 100644 index 000000000..3ce3ffa95 --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.ads @@ -0,0 +1,3 @@ +package Lib3 is + function Baz return Integer; +end Lib3; diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib2/lib2.adb b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib2/lib2.adb new file mode 100644 index 000000000..326f4aa54 --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib2/lib2.adb @@ -0,0 +1,9 @@ +package body Lib2 is + function Bar return Integer + is + Res : constant Integer := 1; + begin + pragma Annotate (Xcov, Dump_Buffers); + return Res; + end Bar; +end Lib2; diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib2/lib2.ads b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib2/lib2.ads new file mode 100644 index 000000000..7968b33bf --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib2/lib2.ads @@ -0,0 +1,3 @@ +package Lib2 is + function Bar return Integer; +end Lib2; diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src/main.adb b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src/main.adb new file mode 100644 index 000000000..4c6e6543a --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src/main.adb @@ -0,0 +1,27 @@ +pragma Ada_2012; + +with Lib1; +with Lib2; + +procedure Main is + + procedure Increment (J : in out Integer) + is + begin + J := J + 1; + end Increment; + + I : Integer := 1; +begin + -- The only call that should not count as a violation when never executed + -- is that of the dump buffers procedure. + if 1 = I + 1 then + pragma Annotate (Xcov, Dump_Buffers); + I := I+ 1; + end if; + + Increment (I); + I := I + Lib1.Foo; + I := I + Lib2.Bar; + Increment (I); +end Main; diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.opt b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.opt new file mode 100644 index 000000000..a322c0d34 --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.opt @@ -0,0 +1 @@ +!src-traces DEAD Checks a feature specific the instrumenter diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.py b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.py new file mode 100644 index 000000000..0a7ebb9e5 --- /dev/null +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.py @@ -0,0 +1,73 @@ +""" +Test that when using manual dump trigger in Ada with the appropriate buffers +dump pragma only in a subproject itself dependent on another subproject +gnatcov is able to provide the correct coverage analysis. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir('tmp_') + +lib1_p = gprfor(mains=[], + prjid="lib1", + srcdirs="../src-lib1", + objdir="obj-lib1", + langs=["Ada"], + deps=["lib3"] + ) + +lib2_p = gprfor(mains=[], + prjid="lib2", + srcdirs="../src-lib2", + objdir="obj-lib2", + langs=["Ada"], + ) + +lib2_p = gprfor(mains=[], + prjid="lib3", + srcdirs="../src-lib1/src-lib3", + objdir="obj-lib3", + langs=["Ada"], + ) + +p = gprfor(mains=["main.adb"], + srcdirs=["../src"], + objdir="obj", + deps=["lib1", "lib2", "lib3"]) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=p, units=["lib1", "lib3"]), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src', + dump_trigger="manual", + manual_prj_name="lib1") + +# Check that gnatcov inserted the call to the dump buffers procedure in the +# lib2.adb which is not a unit of interest + + +def check_call(file): + thistest.fail_if_no_match("missing dump buffers procedure call", + "(\n|.)*GCVRT.DB_manual_lib2.Dump_Buffers;" + "(\n|.)*", + contents_of(file)) + + +check_call('obj-lib2/lib2-gnatcov-instr/lib2.adb') + +# Check that we get the expected coverage reports + +check_xcov_reports('xcov/*.xcov', { + 'xcov/lib1.adb.xcov': {'+': {6, 8}, '-': {10}}, + 'xcov/lib3.adb.xcov': {'+': {4, 6}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_manual_dump/src-lib/foo.c b/testsuite/tests/instr-cov/c_manual_dump/src-lib/foo.c new file mode 100644 index 000000000..690bc85c0 --- /dev/null +++ b/testsuite/tests/instr-cov/c_manual_dump/src-lib/foo.c @@ -0,0 +1,9 @@ +int +foo () +{ + int res = 1; + // This is a comment + /* GNATCOV_DUMP_BUFFERS */ + // This is another comment + return res; +} diff --git a/testsuite/tests/instr-cov/c_manual_dump/src-lib/foo.h b/testsuite/tests/instr-cov/c_manual_dump/src-lib/foo.h new file mode 100644 index 000000000..a4536647c --- /dev/null +++ b/testsuite/tests/instr-cov/c_manual_dump/src-lib/foo.h @@ -0,0 +1 @@ +int foo (); diff --git a/testsuite/tests/instr-cov/c_manual_dump/src/main.c b/testsuite/tests/instr-cov/c_manual_dump/src/main.c new file mode 100644 index 000000000..151547cf5 --- /dev/null +++ b/testsuite/tests/instr-cov/c_manual_dump/src/main.c @@ -0,0 +1,27 @@ +#include "foo.h" + +void +increment (int *x) +{ + (*x)++; +} + +int +main () +{ + int x = 1; + // The only call that should not count as a violation when never executed + // is that of the dump buffers procedure. + if (1 == 2) + { + /* GNATCOV_DUMP_BUFFERS */ + return 0; + } + increment (&x); + + x += foo (); + + /* GNATCOV_DUMP_BUFFERS */ + + return 0; +} diff --git a/testsuite/tests/instr-cov/c_manual_dump/test.opt b/testsuite/tests/instr-cov/c_manual_dump/test.opt new file mode 100644 index 000000000..a322c0d34 --- /dev/null +++ b/testsuite/tests/instr-cov/c_manual_dump/test.opt @@ -0,0 +1 @@ +!src-traces DEAD Checks a feature specific the instrumenter diff --git a/testsuite/tests/instr-cov/c_manual_dump/test.py b/testsuite/tests/instr-cov/c_manual_dump/test.py new file mode 100644 index 000000000..7d01918d3 --- /dev/null +++ b/testsuite/tests/instr-cov/c_manual_dump/test.py @@ -0,0 +1,57 @@ +""" +Test that when using manual dump trigger in C with a specific comment +indicating where to dump the coverage buffers, gnatcov is able to replace it +with a call to the dump buffers procedure and output correct traces. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +# Create the GPR file for the root project +src_gpr = gprfor(mains=["main.c"], + prjid="main", + srcdirs="../src", + objdir="obj", + langs=["C"], + deps=["lib"] + ) + +# Create the GPR files for the library +lib_gpr = gprfor(mains=[], + prjid="lib", + srcdirs="../src-lib", + langs=["C"], + extra=""" + for Library_Name use "lib"; + for Library_Dir use "lib"; + """ + ) + +gprsw = GPRswitches(root_project=src_gpr) + +build_run_and_coverage(gprsw=gprsw, covlevel="stmt", mains=["main"], + extra_coverage_args=["-axcov"], dump_trigger="manual", + manual_prj_name="main") + +# Check that that the dump call indication was correctly replaced in the sub +# project + +lib_file = 'obj/lib-gnatcov-instr/foo.c' +thistest.fail_if_no_match +("missing Dump_Buffers call", + "(\n|.)*gnatcov_rts_manual_dump_buffers_lib ();(\n|.)*", + contents_of(lib_file)) + +# Check that we got the expected coverage report + +check_xcov_reports("obj/*.xcov", + {"obj/main.c.xcov": {"+": {6, 12, 15, 20, 22}, + "-": {18, 26}}, + "obj/foo.c.xcov": {"+": {4, 8}}}) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/test.py b/testsuite/tests/instr-cov/manual-dump/test.py index a4ebf93c7..b3f0abd78 100644 --- a/testsuite/tests/instr-cov/manual-dump/test.py +++ b/testsuite/tests/instr-cov/manual-dump/test.py @@ -45,6 +45,10 @@ extra_instr_args=["--dump-trigger=manual"], extra_gprbuild_args=["-XCOV_BUILD=True"], extra_coverage_args=["--annotate=xcov", "-XCOV_BUILD=True"], + tolerate_instrument_messages="warning: no indication for dump location was" + " found, this might be caused by a" + " misspelling in the expected pragma" + " statement." ) check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {5}}}, "obj") diff --git a/tools/gnatcov/ali_files.ads b/tools/gnatcov/ali_files.ads index daa60d041..0bc0d5829 100644 --- a/tools/gnatcov/ali_files.ads +++ b/tools/gnatcov/ali_files.ads @@ -36,7 +36,7 @@ package ALI_Files is pragma Suppress (Tampering_Check); - type ALI_Annotation_Kind is (Exempt_On, Exempt_Off); + type ALI_Annotation_Kind is (Exempt_On, Exempt_Off, Dump_Buffers); type ALI_Annotation is record CU : CU_Id; diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index c262a5440..4a2211ced 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -54,6 +54,24 @@ package body Clang.Extensions is return DeclName; end Get_Decl_Name_Str; + ------------------------- + -- Get_Callee_Name_Str -- + ------------------------- + + function Get_Callee_Name_Str (C : Cursor_T) return String is + + function Get_Callee_Name_Str_C (C : Cursor_T) return String_T + with + Import, Convention => C, + External_Name => "clang_getCalleeName"; + + CalleeName_Str_C : constant String_T := Get_Callee_Name_Str_C (C); + CalleeName : constant String := Get_C_String (CalleeName_Str_C); + begin + Dispose_String (CalleeName_Str_C); + return CalleeName; + end Get_Callee_Name_Str; + -------------------- -- Get_Opcode_Str -- -------------------- diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index 7d652d7d4..a5c08e463 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -86,6 +86,8 @@ package Clang.Extensions is function Get_Decl_Name_Str (C : Cursor_T) return String with Inline; + function Get_Callee_Name_Str (C : Cursor_T) return String with Inline; + function Unwrap (C : Cursor_T) return Cursor_T with Import, Convention => C, External_Name => "clang_unwrap"; diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 13adba792..1528580da 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -311,7 +311,8 @@ clang_getElseLoc (CXCursor C) switch (S->getStmtClass ()) { case Stmt::IfStmtClass: - return translateSLoc (getCursorTU (C), cast (S)->getElseLoc ()); + return translateSLoc (getCursorTU (C), + cast (S)->getElseLoc ()); default: return clang_getNullLocation (); } @@ -326,7 +327,8 @@ clang_getWhileLoc (CXCursor C) switch (S->getStmtClass ()) { case Stmt::DoStmtClass: - return translateSLoc (getCursorTU (C), cast (S)->getWhileLoc ()); + return translateSLoc (getCursorTU (C), + cast (S)->getWhileLoc ()); default: return clang_getNullLocation (); } @@ -466,6 +468,36 @@ clang_getDeclName (CXCursor C) return createEmpty (); } +/* Return the name of the callee. */ + +extern "C" const CXString +clang_getCalleeName (CXCursor C) +{ + if (clang_isExpression (C.kind)) + { + const Expr *E = getCursorExpr (C); + + if (E->getStmtClass () == Stmt::CallExprClass) + { + const clang::CallExpr *CE = cast (E); + const Decl *D = CE->getCalleeDecl (); + + auto getFunctionDeclName = [] (const FunctionDecl *FD) { + const DeclarationName FunctionName = FD->getNameInfo ().getName (); + return createDup (FunctionName.getAsString ().c_str ()); + }; + + const clang::FunctionDecl *FD; + if (D->getKind () == Decl::FunctionTemplate) + FD = (cast (D))->getTemplatedDecl (); + else + FD = cast (D); + return getFunctionDeclName (FD); + } + } + return createEmpty (); +} + /* Return the string representative of the operator for a binary or unary operator node. */ @@ -596,7 +628,7 @@ clang_CXRewriter_insertTextAfterToken (CXRewriter Rew, CXSourceLocation Loc, extern "C" void clang_CXRewriter_insertTextBeforeToken (CXRewriter Rew, CXSourceLocation Loc, - const char *Insert) + const char *Insert) { assert (Rew); Rewriter &R = *reinterpret_cast (Rew); diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 67f1deab7..8408b895d 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -321,7 +321,8 @@ package body Coverage.Source is Enumerate_Sources (Callback'Access, Include_Stubs => True, - Language => All_Languages); + Language => All_Languages, + Only_UOIs => True); end Compute_Unit_Name_For_Ignored_Sources; ------------------------- diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index bd95e4b38..123771c90 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -39,6 +39,7 @@ use Libadalang.Generic_API.Introspection; with Libadalang.Sources; use Libadalang.Sources; with GNATCOLL.Utils; +with GNATCOLL.VFS; with ALI_Files; use ALI_Files; with Coverage_Options; use Coverage_Options; @@ -224,7 +225,8 @@ package body Instrument.Ada_Unit is -- Annotations - Xcov); + Xcov, + Dump_Buffers); Symbols : constant Symbol_Table := Create_Symbol_Table; -- Holder for name singletons @@ -254,7 +256,8 @@ package body Instrument.Ada_Unit is Jorvik => Precompute_Symbol (Jorvik), Ravenscar => Precompute_Symbol (Ravenscar), Restricted => Precompute_Symbol (Restricted), - Xcov => Precompute_Symbol (Xcov)); + Xcov => Precompute_Symbol (Xcov), + Dump_Buffers => Precompute_Symbol (Dump_Buffers)); function As_Symbol (S : All_Symbols) return Symbol_Type is (Precomputed_Symbols (S)); @@ -1426,6 +1429,11 @@ package body Instrument.Ada_Unit is -- record for the Language_Version and Degenerate_Subprogram_Generics -- parameters. + function Create_Manual_Helper_Unit_Name + (Prj : Prj_Desc) + return Ada_Qualified_Name; + -- Return the name for the dump helper unit for manual dump trigger + procedure Emit_Dump_Helper_Unit (Dump_Config : Any_Dump_Config; Instrumenter : Ada_Instrumenter_Type'Class; @@ -7906,6 +7914,137 @@ package body Instrument.Ada_Unit is Rewriter.Apply; end Auto_Dump_Buffers_In_Main; + ------------------------------------ + -- Replace_Manual_Dump_Indication -- + ------------------------------------ + + overriding procedure Replace_Manual_Dump_Indication + (Self : in out Ada_Instrumenter_Type; + Done : in out Boolean; + Prj : Prj_Desc; + Source : GNATCOLL.Projects.File_Info) + is + Instrumented_Filename : constant String := + +(Prj.Output_Dir & "/" & GNATCOLL.VFS."+" (Source.File.Base_Name)); + Source_Filename : constant String := + GNATCOLL.VFS."+" (Source.File.Full_Name); + Instrumented_Exists : constant Boolean := + Ada.Directories.Exists (Instrumented_Filename); + File_To_Search : constant String := (if Instrumented_Exists + then Instrumented_Filename + else Source_Filename); + Unit : constant Libadalang.Analysis.Analysis_Unit := + Self.Context.Get_From_File (File_To_Search); + + Rewriter : Ada_Source_Rewriter; + + function Find_And_Replace_Pragma + (N : Ada_Node'Class) + return Visit_Status; + -- If N is the expected pragma statement, replace it with the actual + -- call. + + procedure Create_Directory_If_Not_Exists (Name : String); + -- Create the directory of name Name if it does not exist yet + + function Find_And_Replace_Pragma (N : Ada_Node'Class) return Visit_Status + is + function Is_Expected_Argument + (Args : Base_Assoc_List; + Idx : Positive; + Arg : All_Symbols) + return Boolean + is ((As_Symbol + (Args.Child (Idx).As_Pragma_Argument_Assoc.F_Expr.As_Identifier) + = As_Symbol (Arg))); + -- Check if the argument of Prag_N at Index matches Arg + + begin + if N.Kind = Ada_Pragma_Node then + declare + Prag_N : constant Pragma_Node := N.As_Pragma_Node; + Prag_Args : constant Base_Assoc_List := Prag_N.F_Args; + begin + if Pragma_Name (Prag_N) = Name_Annotate + and then Prag_Args.Children_Count = 2 + and then Is_Expected_Argument (Prag_Args, 1, Xcov) + and then Is_Expected_Argument (Prag_Args, 2, Dump_Buffers) + then + -- The pragma statement to be replaced by the actual call + -- to Dump_Buffers has been found. + + if not Done then + Start_Rewriting (Rewriter, Self, Prj, File_To_Search); + end if; + + declare + RH : constant Rewriting_Handle := Rewriter.Handle; + With_Unit : constant Node_Rewriting_Handle := + To_Nodes + (RH, + Create_Manual_Helper_Unit_Name (Prj)); + Dump_Call : constant Node_Rewriting_Handle := + To_Nodes + (RH, + To_Qualified_Name (To_String (Dump_Procedure_Name))); + begin + -- Add the with clause only once in the file + + if not Done then + Append_Child + (Handle (Unit.Root.As_Compilation_Unit.F_Prelude), + Create_From_Template + (RH, + Template => "with {};", + Arguments => (1 => With_Unit), + Rule => With_Clause_Rule)); + end if; + + -- Insert the call to the dump procedure + + Replace + (Handle (N), + Create_From_Template + (RH, + "{}.{};", + Arguments => (1 => With_Unit, 2 => Dump_Call), + Rule => Call_Stmt_Rule)); + end; + + Done := True; + return Over; + end if; + end; + end if; + return Into; + end Find_And_Replace_Pragma; + + procedure Create_Directory_If_Not_Exists (Name : String) + is + begin + if not Ada.Directories.Exists (Name) then + Ada.Directories.Create_Directory (Name); + end if; + end Create_Directory_If_Not_Exists; + + begin + -- If no pragma is found in this file then Start_Rewriting will not be + -- called. In this case, Rewriter.Handle will not be properly + -- initialized which will lead to finalization issues. To avoid this, + -- make sure it is set to No_Rewriting_Handle. + + Rewriter.Handle := No_Rewriting_Handle; + + Unit.Root.Traverse (Find_And_Replace_Pragma'Access); + + if Done then + Create_Directory_If_Not_Exists + (GNATCOLL.VFS."+" (Source.Project.Object_Dir.Base_Dir_Name)); + Create_Directory_If_Not_Exists (+Prj.Output_Dir); + Rewriter.Apply; + end if; + end Replace_Manual_Dump_Indication; + ---------------------------- -- Instrument_Source_File -- ---------------------------- @@ -8543,6 +8682,22 @@ package body Instrument.Ada_Unit is end if; end Emit_Pure_Buffer_Unit; + ------------------------------------ + -- Create_Manual_Helper_Unit_Name -- + ------------------------------------ + + function Create_Manual_Helper_Unit_Name + (Prj : Prj_Desc) + return Ada_Qualified_Name + is + Helper_Unit : Ada_Qualified_Name; + begin + Helper_Unit := Sys_Prefix; + Helper_Unit.Append + (To_Unbounded_String ("D") & "B_manual_" & To_String (Prj.Prj_Name)); + return Helper_Unit; + end Create_Manual_Helper_Unit_Name; + --------------------------- -- Emit_Dump_Helper_Unit -- --------------------------- @@ -8574,7 +8729,7 @@ package body Instrument.Ada_Unit is -- Qualified names for the unit that contains the buffer output -- procedure, and for the procedure itself. - Dump_Trigger : constant Auto_Dump_Trigger := + Dump_Trigger : constant Any_Dump_Trigger := (if Override_Dump_Trigger = Manual then Dump_Config.Trigger else Override_Dump_Trigger); @@ -8585,9 +8740,13 @@ package body Instrument.Ada_Unit is begin -- Create the name of the helper unit - Helper_Unit := Sys_Prefix; - Helper_Unit.Append - (To_Unbounded_String ("D") & Instrumented_Unit_Slug (Main)); + if Dump_Config.Trigger = Manual then + Helper_Unit := Create_Manual_Helper_Unit_Name (Prj); + else + Helper_Unit := Sys_Prefix; + Helper_Unit.Append + (To_Unbounded_String ("D") & Instrumented_Unit_Slug (Main)); + end if; -- Compute the qualified names we need for instrumentation @@ -8651,6 +8810,8 @@ package body Instrument.Ada_Unit is & " out Dump_Controlled_Type);"); File.New_Line; end if; + when others => + null; end case; File.Put_Line ("end " & Helper_Unit_Name & ";"); @@ -8710,7 +8871,9 @@ package body Instrument.Ada_Unit is else """" & To_String (Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := - """" & To_String (Dump_Config.Filename_Prefix) & """"; + """" & To_String ((if Dump_Config.Trigger = Manual + then Prj.Prj_Name + else Dump_Config.Filename_Prefix)) & """"; Tag : constant String := """" & (+Instrumenter.Tag) & """"; Simple : constant String := (if Dump_Config.Filename_Simple @@ -8733,7 +8896,9 @@ package body Instrument.Ada_Unit is -- get the current execution time. File.Put_Line (" Program_Name => """ - & To_Ada (Main.Unit) & ""","); + & (if Dump_Trigger = Manual + then "manual_dump""," + else To_Ada (Main.Unit) & """,")); File.Put (" Exec_Date => 0"); end case; File.Put_Line (");"); @@ -8755,11 +8920,14 @@ package body Instrument.Ada_Unit is File.Put_Line (" type Callback is access procedure;"); File.Put_Line (" pragma Convention (C, Callback);"); File.New_Line; + File.Put_Line (" function atexit (Func : Callback)" & " return Interfaces.C.int;"); File.Put_Line (" pragma Import (C, atexit);"); File.Put_Line (" Dummy : constant Interfaces.C.int :="); - File.Put_Line (" atexit (" & Dump_Procedure & "'Access);"); + File.Put_Line + (" atexit (" & Dump_Procedure & "'Access);"); + File.Put_Line ("begin"); File.Put_Line (" return (Data => False);"); File.Put_Line @@ -8810,6 +8978,9 @@ package body Instrument.Ada_Unit is File.Put_Line (" end Finalize;"); File.New_Line; end if; + + when others => + null; end case; File.Put_Line ("end " & Helper_Unit_Name & ";"); @@ -8817,6 +8988,35 @@ package body Instrument.Ada_Unit is end; end Emit_Dump_Helper_Unit; + ---------------------------------- + -- Emit_Dump_Helper_Unit_Manual -- + ---------------------------------- + + procedure Emit_Dump_Helper_Unit_Manual + (Self : in out Ada_Instrumenter_Type; + Helper_Unit : out Unbounded_String; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc) + is + Main : Compilation_Unit_Part; + -- Since the dump trigger is "manual" and there is no main to be given, + -- the Main argument in the following call to Emit_Dump_Helper_Unit will + -- not be used. + + Ada_Helper_Unit : Ada_Qualified_Name; + begin + Emit_Dump_Helper_Unit + (Dump_Config => Dump_Config, + Instrumenter => Self, + Prj => Prj, + Main => Main, + Helper_Unit => Ada_Helper_Unit, + Override_Dump_Trigger => Manual, + Has_Controlled => False); + + Helper_Unit := To_Unbounded_String (To_Ada (Ada_Helper_Unit)); + end Emit_Dump_Helper_Unit_Manual; + ---------------------------- -- Emit_Buffers_List_Unit -- ---------------------------- @@ -8879,6 +9079,11 @@ package body Instrument.Ada_Unit is end; end loop; + if Instr_Units.Is_Empty then + File.Put_Line + (" Dummy : aliased GNATcov_RTS_Coverage_Buffers_Group;"); + end if; + -- Create the list of coverage buffers File.Put_Line (" List : constant GNATcov_RTS.Buffers.Lists" @@ -8900,6 +9105,10 @@ package body Instrument.Ada_Unit is end loop; end; + if Instr_Units.Is_Empty then + File.Put (" 1 => Dummy'Access);"); + end if; + File.Put_Line (" C_List : constant GNATcov_RTS.Buffers.Lists" & ".GNATcov_RTS_Coverage_Buffers_Group_Array :="); File.Put_Line (" (" & Instr_Units.Length'Image @@ -8990,7 +9199,6 @@ package body Instrument.Ada_Unit is -- Instrument the file only if it is a file of interest if Files_Of_Interest.Contains (+Filename) then - -- In verbose mode, always print a notice for the source file -- that we are about to instrument. In non-verbose mode, just get -- prepared to print it in case we emit a "source file missing" diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 7dd57a16c..1635b2208 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -76,6 +76,27 @@ package Instrument.Ada_Unit is Dump_Config : Any_Dump_Config; Prj : Prj_Desc); + overriding procedure Emit_Dump_Helper_Unit_Manual + (Self : in out Ada_Instrumenter_Type; + Helper_Unit : out Unbounded_String; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc); + + overriding procedure Replace_Manual_Dump_Indication + (Self : in out Ada_Instrumenter_Type; + Done : in out Boolean; + Prj : Prj_Desc; + Source : GNATCOLL.Projects.File_Info); + -- Once the instrumentation has finished, if the dump trigger is "manual" + -- we expect the user to have indicated the place where a call to the + -- manual dump buffers procedure should be inserted by the pragma + -- statement: + -- + -- pragma Annotate (Xcov, Dump_Buffers); + -- + -- This pragma must be found and replaced by the actual call to the dump + -- procedure defined in the dump helper unit. + overriding procedure Emit_Buffers_List_Unit (Self : Ada_Instrumenter_Type; Instr_Units : Unit_Sets.Set; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 527d0adcf..0b4a742bf 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -17,6 +17,7 @@ ------------------------------------------------------------------------------ with Ada.Characters.Handling; +with Ada.Characters.Latin_1; with Ada.Containers; use Ada.Containers; with Ada.Directories; use Ada.Directories; with Ada.Text_IO; use Ada.Text_IO; @@ -28,6 +29,8 @@ with Clang.Extensions; use Clang.Extensions; with GNAT.OS_Lib; use GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; +with GNATCOLL.VFS; + with Interfaces; use Interfaces; with Interfaces.C; use Interfaces.C; with Interfaces.C.Strings; use Interfaces.C.Strings; @@ -88,11 +91,12 @@ package body Instrument.C is -- language and standard only. procedure Preprocess_Source - (Filename : String; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc; - PP_Filename : out Unbounded_String; - Options : in out Analysis_Options); + (Filename : String; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; + PP_Filename : out Unbounded_String; + Options : in out Analysis_Options; + Keep_Comments : Boolean := False); -- Preprocess the source at Filename and extend Options using the -- preprocessor output. -- @@ -307,6 +311,11 @@ package body Instrument.C is -- owns this main. Upon return, the name of this helper unit is stored in -- Helper_Unit. + procedure Check_Compiler_Driver + (Prj : Prj_Desc; + Instrumenter : C_Family_Instrumenter_Type'Class); + -- Check that a compiler driver exists for Instrumenter's language + procedure Apply (Self : in out C_Source_Rewriter); -- Overwrite the file with the rewritter modifications @@ -2072,6 +2081,19 @@ package body Instrument.C is -- TODO??? there are probably missing special statements, such as -- ternary operator etc. Do that in a later step. + when Cursor_Call_Expr => + -- Check the name of the callee. If the callee is the manual + -- dump buffers procedure, do nothing. It should not be + -- considered for coverage analysis. + + if not Is_Manual_Dump_Procedure_Symbol (Get_Callee_Name_Str (N)) + then + Extend_Statement_Sequence (N, ' '); + if Has_Decision (N) then + Process_Decisions_Defer (N, 'X'); + end if; + end if; + when others => -- Determine required type character code, or ASCII.NUL if @@ -2463,11 +2485,12 @@ package body Instrument.C is ----------------------- procedure Preprocess_Source - (Filename : String; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc; - PP_Filename : out Unbounded_String; - Options : in out Analysis_Options) + (Filename : String; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; + PP_Filename : out Unbounded_String; + Options : in out Analysis_Options; + Keep_Comments : Boolean := False) is Cmd : Command_Type; -- The command to preprocess the file @@ -2505,6 +2528,10 @@ package body Instrument.C is -- Add the preprocessing flag + if Keep_Comments then + Append_Arg (Cmd, "-C"); + end if; + Append_Arg (Cmd, "-E"); Add_Options (Cmd.Arguments, Options, Pass_Builtins => False); @@ -2878,18 +2905,7 @@ package body Instrument.C is -- Exit early if there is no compiler driver found to preprocess the -- source. - declare - Compiler_Driver : constant Unbounded_String := - Prj.Compiler_Driver - (C_Family_Instrumenter_Type'Class (Self).Language); - begin - if Compiler_Driver = Null_Unbounded_String then - Outputs.Fatal_Error - ("could not find a compiler for " - & Image - (C_Family_Instrumenter_Type'Class (Self).Language)); - end if; - end; + Check_Compiler_Driver (Prj, Self); SCOs.Initialize; @@ -2909,12 +2925,7 @@ package body Instrument.C is -- preprocessor. Import_Options (UIC.Options, Self, Prj, Unit_Name); - Preprocess_Source - (Orig_Filename, - Self, - Prj, - PP_Filename, - UIC.Options); + Preprocess_Source (Orig_Filename, Self, Prj, PP_Filename, UIC.Options); -- Start by recording preprocessing information @@ -3591,18 +3602,22 @@ package body Instrument.C is Indent2 : constant String := Indent1 & " "; begin - -- Create the name of the helper unit + -- Create the dump helper unit - Helper_Unit := Instrumenter.Dump_Helper_Unit - (Compilation_Unit'(File_Based_Language, Main.Filename), - Prj).Unit_Name; + Helper_Unit := (if Dump_Config.Trigger = Manual + then + Instrumenter.Dump_Manual_Helper_Unit (Prj).Unit_Name + else Instrumenter.Dump_Helper_Unit + (Compilation_Unit'(File_Based_Language, Main.Filename), + Prj).Unit_Name); -- Compute the qualified names we need for instrumentation declare Filename : constant String := +Helper_Unit; - Dump_Procedure : constant String := Dump_Procedure_Symbol (Main); - + Dump_Procedure : constant String := + Dump_Procedure_Symbol + (Main, Dump_Config.Trigger = Manual, Prj_Name => +Prj.Prj_Name); begin -- Emit the package body @@ -3647,7 +3662,9 @@ package body Instrument.C is then "GNATCOV_RTS_DEFAULT_TRACE_FILENAME_ENV_VAR" else """" & (+Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := - """" & (+Dump_Config.Filename_Prefix) & """"; + (if Dump_Config.Trigger = Manual + then """" & (+Prj.Prj_Name) & """" + else """" & (+Dump_Config.Filename_Prefix) & """"); Tag : constant String := """" & (+Instrumenter.Tag) & """"; Simple : constant String := (if Dump_Config.Filename_Simple then "1" else "0"); @@ -3659,8 +3676,11 @@ package body Instrument.C is File.Put_Line (Indent2 & Tag & ","); File.Put_Line (Indent2 & Simple & "),"); - File.Put_Line (Indent2 & "STR (""" - & Escape_Backslashes (+Main.Filename) + File.Put_Line (Indent2 + & "STR (""" + & (if Dump_Config.Trigger = Manual + then +Prj.Prj_Name + else Escape_Backslashes (+Main.Filename)) & """),"); File.Put_Line (Indent2 & "gnatcov_rts_time_to_uint64()" & ","); File.Put_Line (Indent2 & "STR ("""")"); @@ -3687,6 +3707,110 @@ package body Instrument.C is end; end Emit_Dump_Helper_Unit; + ---------------------------------- + -- Emit_Dump_Helper_Unit_Manual -- + ---------------------------------- + + procedure Emit_Dump_Helper_Unit_Manual + (Self : in out C_Family_Instrumenter_Type; + Helper_Unit : out US.Unbounded_String; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc) + is + Main : Compilation_Unit_Part; + -- Since the dump trigger is "manual" and there is no main to be given, + -- the Main argument in the following call to Emit_Dump_Helper_Unit will + -- not be used. + + begin + Emit_Dump_Helper_Unit + (Dump_Config => Dump_Config, + Main => Main, + Helper_Unit => Helper_Unit, + Instrumenter => Self, + Prj => Prj); + end Emit_Dump_Helper_Unit_Manual; + + ------------------------------------ + -- Replace_Manual_Dump_Indication -- + ------------------------------------ + + procedure Replace_Manual_Dump_Indication + (Self : in out C_Family_Instrumenter_Type; + Done : in out Boolean; + Prj : Prj_Desc; + Source : GNATCOLL.Projects.File_Info) + is + Orig_Filename : constant String := + GNATCOLL.VFS."+" (Source.File.Full_Name); + begin + Check_Compiler_Driver (Prj, Self); + + declare + Options : Analysis_Options; + PP_Filename : Unbounded_String; + File : Ada.Text_IO.File_Type; + Dummy_Main : Compilation_Unit_Part; + Dump_Pat : constant Pattern_Matcher := + Compile ("^[\t ]*\/\* GNATCOV_DUMP_BUFFERS \*\/[ \t]*"); + Matches : Match_Array (0 .. 1); + Dump_Procedure : constant String := + Dump_Procedure_Symbol + (Main => Dummy_Main, Manual => True, Prj_Name => +Prj.Prj_Name); + Contents : Unbounded_String := + "extern void " & To_Unbounded_String (Dump_Procedure) & " (void);"; + begin + -- Preprocess the source, keeping the comment to look for the manual + -- dump indication later. + + Import_Options (Options, Self, Prj, To_String (PP_Filename)); + Preprocess_Source + (Orig_Filename, Self, Prj, PP_Filename, Options, True); + + -- Look for the manual dump indication in the preprocessed file + + Ada.Text_IO.Open + (File => File, + Mode => In_File, + Name => To_String (PP_Filename)); + + while not Ada.Text_IO.End_Of_File (File) loop + declare + Line : constant String := Get_Line (File); + begin + Match (Dump_Pat, Line, Matches); + + if Matches (0) /= No_Match then + Contents := Contents & Dump_Procedure & "();"; + Done := True; + else + Contents := Contents & Line; + end if; + + Contents := Contents & Ada.Characters.Latin_1.LF; + end; + end loop; + + Ada.Text_IO.Close (File); + + if Done then + -- Content now holds the text of the original file with calls to + -- the manual dump procedure where the indications and its extern + -- declaration were. Replace the original content of the file with + -- Content. + + Ada.Text_IO.Open + (File => File, + Mode => Out_File, + Name => To_String (PP_Filename)); + + Ada.Text_IO.Put_Line (File, To_String (Contents)); + + Ada.Text_IO.Close (File); + end if; + end; + end Replace_Manual_Dump_Indication; + ------------------------------- -- Auto_Dump_Buffers_In_Main -- ------------------------------- @@ -3895,6 +4019,27 @@ package body Instrument.C is Unit_Name => +Filename); end Buffer_Unit; + ----------------------------- + -- Dump_Manual_Helper_Unit -- + ----------------------------- + + overriding function Dump_Manual_Helper_Unit + (Self : C_Family_Instrumenter_Type; + Prj : Prj_Desc) return Compilation_Unit + is + Filename : constant String := + New_File + (Prj, + To_Symbol_Name (Sys_Prefix) + & "_d_b_" & To_String (Prj.Prj_Name) + & (+Prj.Body_Suffix + (C_Family_Instrumenter_Type'Class (Self).Language))); + begin + return Compilation_Unit' + (Language => File_Based_Language, + Unit_Name => +Filename); + end Dump_Manual_Helper_Unit; + ---------------------- -- Dump_Helper_Unit -- ---------------------- @@ -3942,6 +4087,23 @@ package body Instrument.C is end if; end Has_Main; + --------------------------- + -- Check_Compiler_Driver -- + --------------------------- + + procedure Check_Compiler_Driver + (Prj : Prj_Desc; + Instrumenter : C_Family_Instrumenter_Type'Class) + is + Compiler_Driver : constant Unbounded_String := + Prj.Compiler_Driver (Instrumenter.Language); + begin + if Compiler_Driver = Null_Unbounded_String then + Outputs.Fatal_Error + ("could not find a compiler for " & Image (Instrumenter.Language)); + end if; + end Check_Compiler_Driver; + ---------------- -- Format_Def -- ---------------- diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 7358dc367..10003c672 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -52,6 +52,28 @@ package Instrument.C is Dump_Config : Any_Dump_Config; Prj : Prj_Desc); + procedure Replace_Manual_Dump_Indication + (Self : in out C_Family_Instrumenter_Type; + Done : in out Boolean; + Prj : Prj_Desc; + Source : GNATCOLL.Projects.File_Info); + -- Preprocess Source and look through the text content of the preprocessed + -- file looking for manual dump indications. The C-like languages, the + -- expected indication is the comment alone on its line: + -- + -- /* GNATCOV_DUMP_BUFFERS */ + -- + -- When one is found the text of the file is modified: the line is replaced + -- by a call to the manual dump procedure and an extern declaration for the + -- procedure is put at the beginning of the file. + + procedure Emit_Dump_Helper_Unit_Manual + (Self : in out C_Family_Instrumenter_Type; + Helper_Unit : out US.Unbounded_String; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc); + -- Emit the dump helper unit + overriding procedure Emit_Buffers_List_Unit (Self : C_Family_Instrumenter_Type; Instr_Units : Unit_Sets.Set; @@ -67,6 +89,10 @@ package Instrument.C is CU : Compilation_Unit; Prj : Prj_Desc) return Compilation_Unit; + overriding function Dump_Manual_Helper_Unit + (Self : C_Family_Instrumenter_Type; + Prj : Prj_Desc) return Compilation_Unit; + overriding function Dump_Helper_Unit (Self : C_Family_Instrumenter_Type; CU : Compilation_Unit; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index acd3b2841..dbe66dc63 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -83,6 +83,21 @@ package body Instrument.Common is return Buffer_Symbol (Instrumented_Unit, "mcdc"); end MCDC_Buffer_Symbol; + ------------------------------------- + -- Is_Manual_Dump_Procedure_Symbol -- + ------------------------------------- + + function Is_Manual_Dump_Procedure_Symbol (Symbol : String) return Boolean + is + Dummy_Main : Compilation_Unit_Part; + Pattern : constant Pattern_Matcher := + Compile (Dump_Procedure_Symbol (Dummy_Main, Manual => True)); + Matches : Match_Array (0 .. 0); + begin + Match (Pattern, Symbol, Matches); + return Matches (0) /= No_Match; + end Is_Manual_Dump_Procedure_Symbol; + ----------------------- -- Unit_Buffers_Name -- ----------------------- diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 7f9b556fa..6419614d5 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -106,12 +106,25 @@ package Instrument.Common is -- handler. function Dump_Procedure_Symbol - (Main : Compilation_Unit_Part) return String + (Main : Compilation_Unit_Part; + Manual : Boolean := False; + Prj_Name : String := "") return String is - ("gnatcov_rts_" & Instrumented_Unit_Slug (Main) & "_" - & To_Lower (To_String (Dump_Procedure_Name))); + ("gnatcov_rts_" + & (if Manual + then "manual" + else Instrumented_Unit_Slug (Main)) + & "_" + & To_Lower (To_String (Dump_Procedure_Name)) + & (if Manual + then "_" & Prj_Name + else "")); -- Return the name of the exported symbol for the Dump_Buffers function + function Is_Manual_Dump_Procedure_Symbol (Symbol : String) return Boolean; + -- For C, manual dump procedures are suffixed by the project's name. Check + -- that Symbol corresponds to the name of one such procedure. + function Statement_Buffer_Symbol (Instrumented_Unit : Compilation_Unit_Part) return String; -- Given a unit to instrument, return the name of the symbol to use for the @@ -435,6 +448,11 @@ package Instrument.Common is is (No_Compilation_Unit); -- Return the compilation unit holding coverage buffers + function Dump_Manual_Helper_Unit + (Self : Language_Instrumenter; + Prj : Prj_Desc) return Compilation_Unit + is (No_Compilation_Unit); + function Dump_Helper_Unit (Self : Language_Instrumenter; CU : Compilation_Unit; @@ -448,6 +466,25 @@ package Instrument.Common is Prj : Prj_Desc) return Boolean is (False); -- Return whether the given file is a main or not + procedure Emit_Dump_Helper_Unit_Manual + (Self : in out Language_Instrumenter; + Helper_Unit : out Unbounded_String; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc) is null; + -- Emit the dump helper unit with the appropriate content to allow for a + -- simple call to a procedure dumping the coverage buffers to be made in + -- the instrumented source files. + + procedure Replace_Manual_Dump_Indication + (Self : in out Language_Instrumenter; + Done : in out Boolean; + Prj : Prj_Desc; + Source : GNATCOLL.Projects.File_Info) is null; + -- Look for the pragma (for Ada) or comment (for C family languages) + -- indicating where the user wishes to the buffers to be dumped in Source. + -- When found, replace it with a call to the buffers dump procedure defined + -- in the dump helper unit. + function New_File (Prj : Prj_Desc; Name : String) return String; -- Compute the path to the file to create in Self.Output_Dir diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index bec050ced..95200727c 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -131,6 +131,9 @@ is package File_Info_Sets is new Ada.Containers.Indefinite_Ordered_Sets (Element_Type => File_Info, "<" => Less, "=" => Equal); + package Prj_Has_Manual_Helper_Sets is new + Ada.Containers.Indefinite_Ordered_Sets (Element_Type => Unbounded_String); + type Library_Unit_Info is record Unit_Name : Unbounded_String; -- Name of this unit: unit name for unit-based languages, simple name @@ -233,6 +236,22 @@ is -- instrument-main (depending on Purpose) for the given compilation unit -- LU_Info, belonging to the project Prj. + procedure Add_Project_Source + (Project : GPR.Project_Type; Source_File : GPR.File_Info); + -- Add Source_File to the C or Ada list of all project sources depending on + -- its language. + + procedure Insert_Manual_Dump_Trigger + (Language : Src_Supported_Language; + Project_Sources : in out File_Info_Sets.Set; + Instrumenter : in out Language_Instrumenter'Class; + Manual_Dump_Inserted : in out Boolean); + -- For all sources in Project_Sources of language Language, call + -- Replace_Manual_Dump_Indication. If a dump procedure call was inserted + -- and id there is not one already, also emit a dump helper unit for the + -- project the source belongs to. Set Manual_Dump_Inserted to True if at + -- least one manual dump indication was found. + procedure Add_Instrumented_Unit (Project : GPR.Project_Type; Source_File : GPR.File_Info); -- Add this source file to the list of units to instrument @@ -653,6 +672,35 @@ is -- an Ada file (to know which part of a compilation unit must be -- instrumented, i.e. spec / body / separates). + Project_Sources : File_Info_Sets.Set; + -- Sets of all Ada and C family source files of all projects. If the dump + -- trigger is "manual", traversing all these project sources will be + -- necessary to find the indication marking the location where the user + -- wishes the Dump_Buffers call to be inserted. + + Prj_Has_Manual_Helper : Prj_Has_Manual_Helper_Sets.Set; + -- In the case of a manual dump config, set of names of projects for which + -- a manual dump helper unit has already been emitted. + + ------------------------ + -- Add_Project_Source -- + ------------------------ + + procedure Add_Project_Source + (Project : GPR.Project_Type; Source_File : GPR.File_Info) + is + pragma Unreferenced (Project); + begin + -- Check if gnatcov was built with support for this language. If not, + -- exit early. + + if not Builtin_Support (To_Language (Source_File.Language)) then + return; + end if; + + Project_Sources.Insert (Source_File); + end Add_Project_Source; + --------------------------- -- Add_Instrumented_Unit -- --------------------------- @@ -765,6 +813,100 @@ is end if; end Add_Instrumented_Unit; + -------------------------------- + -- Insert_Manual_Dump_Trigger -- + -------------------------------- + + procedure Insert_Manual_Dump_Trigger + (Language : Src_Supported_Language; + Project_Sources : in out File_Info_Sets.Set; + Instrumenter : in out Language_Instrumenter'Class; + Manual_Dump_Inserted : in out Boolean) + is + begin + for Source_C in Project_Sources.Iterate loop + declare + Source : constant File_Info := File_Info_Sets.Element (Source_C); + begin + if To_Language (Source.Language) = Language then + declare + use Prj_Has_Manual_Helper_Sets; + + Prj : constant Prj_Desc := + Get_Or_Create_Project_Info (IC, Source.Project).Desc; + Helper_Unit : Unbounded_String; + Contained_Indication : Boolean := False; + begin + + Instrumenter.Replace_Manual_Dump_Indication + (Contained_Indication, + Prj, + Source); + + if Contained_Indication + and then + Prj_Has_Manual_Helper.Find (Prj.Prj_Name) = No_Element + then + -- Only generate one manual dump helper unit per project + + Instrumenter.Emit_Dump_Helper_Unit_Manual + (Helper_Unit, Dump_Config, Prj); + + declare + use Files_Table; + Instr_Units : Unit_Sets.Set; + Source_Files : GNATCOLL.VFS.File_Array_Access + := Source.Project.Source_Files (Recursive => True); + begin + for S of Source_Files.all loop + declare + use Unit_Maps; + Unit_C : constant Unit_Maps.Cursor := + Instrumented_Sources.Find + (+To_Compilation_Unit + (Project.Project.Info (S)).Unit_Name); + begin + if Unit_C /= Unit_Maps.No_Element then + declare + Unit : constant Library_Unit_Info := + Element (Unit_C); + Instr_Unit : constant Compilation_Unit := + Compilation_Unit' + (Unit.Language_Kind, + Unit.Unit_Name); + begin + if not Instr_Units.Contains (Instr_Unit) + then + Instr_Units.Insert (Instr_Unit); + end if; + end; + end if; + end; + end loop; + + -- The creation of the root project's buffers list + -- unit is already taken care of by the regular + -- instrumentation process, so skip it. + + if Prj.Prj_Name /= Root_Project_Info.Project.Name then + Instrumenter.Emit_Buffers_List_Unit + (Instr_Units, Prj); + end if; + + GNATCOLL.VFS.Unchecked_Free (Source_Files); + end; + + Prj_Has_Manual_Helper.Insert (Prj.Prj_Name); + end if; + + Manual_Dump_Inserted := + Manual_Dump_Inserted or else Contained_Indication; + end; + end if; + end; + end loop; + end Insert_Manual_Dump_Trigger; + --------------------- -- Clean_And_Print -- --------------------- @@ -781,6 +923,9 @@ is -- this is filled even when dump-trigger is manual: in that case the -- instrumentation of the main will do nothing. + Manual_Dump_Inserted : Boolean := False; + -- Whether or not a dump procedure was inserted in any source file + Exec_Filename : constant String := Ada.Directories.Compose (Support_Files.Libexec_Dir, "gnatcov64" & GNAT.OS_Lib.Get_Executable_Suffix.all); @@ -812,7 +957,18 @@ begin for Lang in Src_Supported_Language loop if Src_Enabled_Languages (Lang) then Project.Enumerate_Sources - (Add_Instrumented_Unit'Access, Lang, Include_Stubs => True); + (Add_Instrumented_Unit'Access, + Lang, + Include_Stubs => True, + Only_UOIs => True); + + if Dump_Config.Trigger = Manual then + -- The expected manual dump indication can be located in any + -- source file, not only in sources of interest. + + Project.Enumerate_Sources + (Add_Project_Source'Access, Lang, Include_Stubs => True); + end if; end if; end loop; @@ -943,6 +1099,18 @@ begin C_Instrumenter := Create_C_Instrumenter (IC.Tag); CPP_Instrumenter := Create_CPP_Instrumenter (IC.Tag); + if Dump_Config.Trigger = Manual then + -- Replace manual dump indications for C-like languages + + for Lang in C_Family_Language loop + Insert_Manual_Dump_Trigger + (Lang, + Project_Sources, + Instrumenters (Lang).all, + Manual_Dump_Inserted); + end loop; + end if; + -- Write the files of interest to temporary files in the instrumentation -- directory. @@ -973,6 +1141,7 @@ begin Instrument_Source_Args.Append (Common_Switches (Cmd_Instrument_Source)); for Cur in Instrumented_Sources.Iterate loop + declare Unit_Args : String_Vectors.Vector := Instrument_Source_Args.Copy; @@ -981,13 +1150,12 @@ begin -- instrumented for a specific unit). Unit_Name : constant String := Unit_Maps.Key (Cur); - LU_Info : constant Library_Unit_Info := Unit_Maps.Element (Cur); - - Obj_SID : constant String := + LU_Info : constant Library_Unit_Info := Unit_Maps.Element (Cur); + Obj_SID : constant String := SID_Filename (LU_Info, In_Library_Dir => False); - Prj : constant Project_Type := LU_Info.Instr_Project; - Desc : constant Prj_Desc := + Prj : constant Project_Type := LU_Info.Instr_Project; + Desc : constant Prj_Desc := IC.Project_Info_Map.Element (+Prj.Name).Desc; begin -- Skip instrumentation of the unit if it was already @@ -1141,43 +1309,67 @@ begin (Main.File.Full_Name, Include_Suffix => True)); end if; end if; - - Unit_Args.Append (Unparse_Config (Explicit_Dump_Config)); - - -- Then append the main filename. If the main was instrumented - -- as a unit of interest before, then pass the instrumented - -- version. - - if Instrumented_Sources.Contains (+Unit_Name) then - Main_Filename := - +(+Root_Project_Info.Output_Dir) / (+Main.File.Base_Name); - else - Main_Filename := +(+Main.File.Full_Name); - end if; - - Unit_Args.Append (Main_Filename); - - if Parallelism_Level = 1 then - declare - Instr_Units : String_Sets.Set; - begin - for Source of Files_Of_Interest loop - Instr_Units.Insert (+(+Source.File.Full_Name)); - end loop; - Instrument.Main - (Instrumenter => Instrumenters (Language).all, - Dump_Config => Explicit_Dump_Config, - Main_Filename => +Main_Filename, - Prj => Main.Prj_Info.Desc); - end; - else - Instrument_Main_Pool.Run_Command - (Command => Exec_Filename, - Arguments => Unit_Args, - Origin_Command_Name => "gnatcov instrument", - Ignore_Error => False); - end if; end; + + if Dump_Config.Trigger /= Manual then + declare + Unit_Name : constant Unbounded_String := + +(case Main.CU_Name.Language_Kind is + when Unit_Based_Language => + To_Ada (Main.CU_Name.Unit), + when File_Based_Language => (+Main.File.Full_Name)); + Unit_Args : String_Vectors.Vector := + Instrument_Main_Args.Copy; + begin + Unit_Args.Append + (Compilation_Unit_Options + (IC, + Main.Prj_Info.Desc, + Library_Unit_Info' + (Unit_Name => Unit_Name, + Instr_Project => Main.Prj_Info.Project, + Language_Kind => Language_Kind (Language), + Language => Language, + All_Externally_Built => False))); + + Unit_Args.Append (Unparse_Config (Explicit_Dump_Config)); + + -- Then append the main filename. If the main was + -- instrumented as a unit of interest before, then pass the + -- instrumented version. + + if Instrumented_Sources.Contains (+Unit_Name) then + Main_Filename := + +(+Root_Project_Info.Output_Dir) + / (+Main.File.Base_Name); + else + Main_Filename := +(+Main.File.Full_Name); + end if; + + Unit_Args.Append (Main_Filename); + + if Parallelism_Level = 1 then + declare + Instr_Units : String_Sets.Set; + begin + for Source of Files_Of_Interest loop + Instr_Units.Insert (+(+Source.File.Full_Name)); + end loop; + Instrument.Main + (Instrumenter => Instrumenters (Language).all, + Dump_Config => Explicit_Dump_Config, + Main_Filename => +Main_Filename, + Prj => Main.Prj_Info.Desc); + end; + else + Instrument_Main_Pool.Run_Command + (Command => Exec_Filename, + Arguments => Unit_Args, + Origin_Command_Name => "gnatcov instrument", + Ignore_Error => False); + end if; + end; + end if; end loop; end loop; end; @@ -1218,6 +1410,25 @@ begin end loop; end; + if Dump_Config.Trigger = Manual then + Insert_Manual_Dump_Trigger + (Ada_Language, + Project_Sources, + Ada_Instrumenter, + Manual_Dump_Inserted); + + -- At this point, all source files for all languages have been looked + -- through to insert a call to the manual dump procedure. If no call + -- has been inserted (i.e. no manual dump location indication was + -- found), warn the user. + if not Manual_Dump_Inserted then + Outputs.Warn + ("no indication for dump location was found, this might be" + & " caused by a misspelling in the expected pragma" + & " statement or comment."); + end if; + end if; + Destroy_Context (IC); -- Save the dump trigger+channel information in the root project's @@ -1239,9 +1450,11 @@ begin J.Set_Field ("dump-channel", Image (Dump_Config.Channel)); Write (Filename, J, Compact => False); end; + exception - -- We need to clear the object directories in case an exception (caught by - -- a global handler and not dealt with by the registered hook) was raised. + -- We need to clear the object directories in case an exception (caught + -- by a global handler and not dealt with by the registered hook) was + -- raised. when Binary_Files.Error | Ada.IO_Exceptions.Name_Error diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 40bce594c..a65654b46 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -544,11 +544,13 @@ package body Project is (Project : GNATCOLL.Projects.Project_Type; File : GNATCOLL.Projects.File_Info); Language : Any_Language; - Include_Stubs : Boolean := False) + Include_Stubs : Boolean := False; + Only_UOIs : Boolean := False) is procedure Process_Source_File (Info : File_Info; Unit_Name : String); - -- Callback for Iterate_Source_File. If Unit_Name is a unit of interest, - -- call "Callback" on this file. + -- Callback for Iterate_Source_File. If Only_UOIs is set to true, call + -- Callback the Unit_Name file is it a unit of interest. If Only_UOIs is + -- set to False, call Callback on all sources. ------------------------- -- Process_Source_File -- @@ -571,10 +573,11 @@ package body Project is -- Otherwise, check if the unit is in the units of interest -- map - or else - (Unit_Map.Contains (To_Compilation_Unit (Info)) - and then (Info.Unit_Part /= Unit_Separate - or else Include_Stubs)) + or else (Only_UOIs + and then (Unit_Map.Contains (To_Compilation_Unit (Info)) + and then (Info.Unit_Part /= Unit_Separate + or else Include_Stubs))) + or else not Only_UOIs then Callback (Info.Project, Info); end if; diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index f2d4ba202..17bf9a84b 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -157,11 +157,13 @@ package Project is (Project : GNATCOLL.Projects.Project_Type; File : GNATCOLL.Projects.File_Info); Language : Any_Language; - Include_Stubs : Boolean := False) + Include_Stubs : Boolean := False; + Only_UOIs : Boolean := False) with Pre => Is_Project_Loaded; -- Call Callback once for every source file of the given language - -- mentionned in a previous Add_Project call. Override_Units has the same - -- semantics as in Enumerate_LIs. + -- mentionned in a previous Add_Project call. If Only_UOIs is set to True, + -- only call Callback on sources that are units of interest. Override_Units + -- has the same semantics as in Enumerate_LIs. -- -- If Include_Stubs is false (the default) then Callback will skip -- sources files that are subunits (Ada) or headers (C/C++). From 2ff0f8fe391a384fc02d229dc32113c422c46e9d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 22 Aug 2023 11:51:42 +0200 Subject: [PATCH 0398/1483] Reformat clang-wrapper.cc --- .pre-commit-config.yaml | 1 - tools/gnatcov/clang-wrapper.cc | 566 ++++++++++++++++++--------------- 2 files changed, 312 insertions(+), 255 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aa805a5f1..c65082fd2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -13,7 +13,6 @@ repos: IndentExternBlock: NoIndent, SpaceAfterCStyleCast: true, - UseTab: ForContinuationAndIndentation, SpacesInLineCommentPrefix: { Minimum: 0, Maximum: -1 diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 1528580da..8b207f2da 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -114,23 +114,23 @@ clang_getCond (CXCursor C) if (clang_isStatement (C.kind) || clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::IfStmtClass: - return MakeCXCursorWithNull (cast (S)->getCond (), C); - case Stmt::WhileStmtClass: - return MakeCXCursorWithNull (cast (S)->getCond (), C); - case Stmt::ForStmtClass: - return MakeCXCursorWithNull (cast (S)->getCond (), C); - case Stmt::SwitchStmtClass: - return MakeCXCursorWithNull (cast (S)->getCond (), C); - case Stmt::DoStmtClass: - return MakeCXCursorWithNull (cast (S)->getCond (), C); - case Stmt::ConditionalOperatorClass: - return MakeCXCursorWithNull ( - cast (S)->getCond (), C); - default: - return clang_getNullCursor (); - } + { + case Stmt::IfStmtClass: + return MakeCXCursorWithNull (cast (S)->getCond (), C); + case Stmt::WhileStmtClass: + return MakeCXCursorWithNull (cast (S)->getCond (), C); + case Stmt::ForStmtClass: + return MakeCXCursorWithNull (cast (S)->getCond (), C); + case Stmt::SwitchStmtClass: + return MakeCXCursorWithNull (cast (S)->getCond (), C); + case Stmt::DoStmtClass: + return MakeCXCursorWithNull (cast (S)->getCond (), C); + case Stmt::ConditionalOperatorClass: + return MakeCXCursorWithNull ( + cast (S)->getCond (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -140,56 +140,56 @@ clang_getBody (CXCursor C) if (clang_isDeclaration (C.kind)) { if (const Decl *D = getCursorDecl (C)) - switch (D->getKind ()) - { - case Decl::FunctionTemplate: - return MakeCXCursorWithNull ( - cast (D)->getTemplatedDecl ()->getBody (), - C); - case Decl::Function: - case Decl::CXXMethod: - case Decl::CXXConstructor: - case Decl::CXXDestructor: - case Decl::CXXConversion: - { - const FunctionDecl *FD = cast (D); - if (FD->doesThisDeclarationHaveABody ()) - return MakeCXCursorWithNull (FD->getBody (), C); - break; - } - default: - return MakeCXCursorWithNull (D->getBody (), C); - } + switch (D->getKind ()) + { + case Decl::FunctionTemplate: + return MakeCXCursorWithNull ( + cast (D)->getTemplatedDecl ()->getBody (), + C); + case Decl::Function: + case Decl::CXXMethod: + case Decl::CXXConstructor: + case Decl::CXXDestructor: + case Decl::CXXConversion: + { + const FunctionDecl *FD = cast (D); + if (FD->doesThisDeclarationHaveABody ()) + return MakeCXCursorWithNull (FD->getBody (), C); + break; + } + default: + return MakeCXCursorWithNull (D->getBody (), C); + } } else if (clang_isStatement (C.kind)) { if (const Stmt *S = getCursorStmt (C)) - switch (S->getStmtClass ()) - { - case Stmt::WhileStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), C); - case Stmt::ForStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), C); - case Stmt::CXXForRangeStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), - C); - case Stmt::DoStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), C); - case Stmt::SwitchStmtClass: - return MakeCXCursorWithNull (cast (S)->getBody (), C); - default: - return clang_getNullCursor (); - } + switch (S->getStmtClass ()) + { + case Stmt::WhileStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), C); + case Stmt::ForStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), C); + case Stmt::CXXForRangeStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), + C); + case Stmt::DoStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), C); + case Stmt::SwitchStmtClass: + return MakeCXCursorWithNull (cast (S)->getBody (), C); + default: + return clang_getNullCursor (); + } } else if (clang_isExpression (C.kind)) if (const Expr *E = getCursorExpr (C)) switch (E->getStmtClass ()) - { - case Expr::LambdaExprClass: - return MakeCXCursorWithNull (cast (E)->getBody (), C); - default: - return clang_getNullCursor (); - } + { + case Expr::LambdaExprClass: + return MakeCXCursorWithNull (cast (E)->getBody (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -199,15 +199,15 @@ clang_getForInit (CXCursor C) if (clang_isStatement (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::ForStmtClass: - return MakeCXCursorWithNull (cast (S)->getInit (), C); - case Stmt::CXXForRangeStmtClass: - return MakeCXCursorWithNull (cast (S)->getInit (), - C); - default: - return clang_getNullCursor (); - } + { + case Stmt::ForStmtClass: + return MakeCXCursorWithNull (cast (S)->getInit (), C); + case Stmt::CXXForRangeStmtClass: + return MakeCXCursorWithNull (cast (S)->getInit (), + C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -232,12 +232,12 @@ clang_getForInc (CXCursor C) if (clang_isStatement (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::ForStmtClass: - return MakeCXCursorWithNull (cast (S)->getInc (), C); - default: - return clang_getNullCursor (); - } + { + case Stmt::ForStmtClass: + return MakeCXCursorWithNull (cast (S)->getInc (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -253,7 +253,7 @@ clang_getCondVar (CXCursor C) { while_stmt = cast (stmt); if (decl = while_stmt->getConditionVariable ()) - return MakeCXCursorWithNull (decl, C); + return MakeCXCursorWithNull (decl, C); } return clang_getNullCursor (); } @@ -279,12 +279,12 @@ clang_getThen (CXCursor C) if (clang_isStatement (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::IfStmtClass: - return MakeCXCursorWithNull (cast (S)->getThen (), C); - default: - return clang_getNullCursor (); - } + { + case Stmt::IfStmtClass: + return MakeCXCursorWithNull (cast (S)->getThen (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -294,12 +294,12 @@ clang_getElse (CXCursor C) if (clang_isStatement (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::IfStmtClass: - return MakeCXCursorWithNull (cast (S)->getElse (), C); - default: - return clang_getNullCursor (); - } + { + case Stmt::IfStmtClass: + return MakeCXCursorWithNull (cast (S)->getElse (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -309,13 +309,13 @@ clang_getElseLoc (CXCursor C) if (clang_isStatement (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::IfStmtClass: - return translateSLoc (getCursorTU (C), - cast (S)->getElseLoc ()); - default: - return clang_getNullLocation (); - } + { + case Stmt::IfStmtClass: + return translateSLoc (getCursorTU (C), + cast (S)->getElseLoc ()); + default: + return clang_getNullLocation (); + } return clang_getNullLocation (); } @@ -325,13 +325,13 @@ clang_getWhileLoc (CXCursor C) if (clang_isStatement (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::DoStmtClass: - return translateSLoc (getCursorTU (C), - cast (S)->getWhileLoc ()); - default: - return clang_getNullLocation (); - } + { + case Stmt::DoStmtClass: + return translateSLoc (getCursorTU (C), + cast (S)->getWhileLoc ()); + default: + return clang_getNullLocation (); + } return clang_getNullLocation (); } @@ -341,13 +341,13 @@ clang_getSubExpr (CXCursor C) if (clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::UnaryOperatorClass: - return MakeCXCursorWithNull (cast (S)->getSubExpr (), - C); - default: - return clang_getNullCursor (); - } + { + case Stmt::UnaryOperatorClass: + return MakeCXCursorWithNull (cast (S)->getSubExpr (), + C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -357,15 +357,15 @@ clang_getSubStmt (CXCursor C) if (clang_isStatement (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::CaseStmtClass: - return MakeCXCursorWithNull (cast (S)->getSubStmt (), C); - case Stmt::DefaultStmtClass: - return MakeCXCursorWithNull (cast (S)->getSubStmt (), - C); - default: - return clang_getNullCursor (); - } + { + case Stmt::CaseStmtClass: + return MakeCXCursorWithNull (cast (S)->getSubStmt (), C); + case Stmt::DefaultStmtClass: + return MakeCXCursorWithNull (cast (S)->getSubStmt (), + C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -375,15 +375,15 @@ clang_getRHS (CXCursor C) if (clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::BinaryOperatorClass: - return MakeCXCursorWithNull (cast (S)->getRHS (), C); - case Stmt::ConditionalOperatorClass: - return MakeCXCursorWithNull ( - cast (S)->getRHS (), C); - default: - return clang_getNullCursor (); - } + { + case Stmt::BinaryOperatorClass: + return MakeCXCursorWithNull (cast (S)->getRHS (), C); + case Stmt::ConditionalOperatorClass: + return MakeCXCursorWithNull ( + cast (S)->getRHS (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -393,15 +393,15 @@ clang_getLHS (CXCursor C) if (clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::BinaryOperatorClass: - return MakeCXCursorWithNull (cast (S)->getLHS (), C); - case Stmt::ConditionalOperatorClass: - return MakeCXCursorWithNull ( - cast (S)->getLHS (), C); - default: - return clang_getNullCursor (); - } + { + case Stmt::BinaryOperatorClass: + return MakeCXCursorWithNull (cast (S)->getLHS (), C); + case Stmt::ConditionalOperatorClass: + return MakeCXCursorWithNull ( + cast (S)->getLHS (), C); + default: + return clang_getNullCursor (); + } return clang_getNullCursor (); } @@ -413,56 +413,56 @@ clang_getDeclName (CXCursor C) if (clang_isDeclaration (C.kind)) { auto getFunctionDeclName = [] (const FunctionDecl *FD) { - const DeclarationName FunctionName = FD->getNameInfo ().getName (); - return createDup (FunctionName.getAsString ().c_str ()); + const DeclarationName FunctionName = FD->getNameInfo ().getName (); + return createDup (FunctionName.getAsString ().c_str ()); }; const Decl *D = getCursorDecl (C); switch (D->getKind ()) - { - case Decl::Function: - case Decl::CXXMethod: - case Decl::CXXConstructor: - case Decl::CXXDestructor: - { - const clang::FunctionDecl *FD = cast (D); - return getFunctionDeclName (FD); - } - case Decl::FunctionTemplate: - { - const clang::FunctionDecl *FD - = (cast (D))->getTemplatedDecl (); - return getFunctionDeclName (FD); - } - - case Decl::Namespace: - { - const NamespaceDecl *ND - = (cast (D))->getCanonicalDecl (); - - if (ND->isAnonymousNamespace ()) - return createDup ("Anonymous namespace"); - - return createDup (ND->getName ()); - } - case Decl::ClassTemplate: - - { - const clang::ClassTemplateDecl *CD - = (cast (D))->getCanonicalDecl (); - return createDup (CD->getName ()); - } - case Decl::CXXRecord: - { - const clang::CXXRecordDecl *RD - = (cast (D))->getCanonicalDecl (); - return createDup (RD->getName ()); - } - - default: - return createEmpty (); - } + { + case Decl::Function: + case Decl::CXXMethod: + case Decl::CXXConstructor: + case Decl::CXXDestructor: + { + const clang::FunctionDecl *FD = cast (D); + return getFunctionDeclName (FD); + } + case Decl::FunctionTemplate: + { + const clang::FunctionDecl *FD + = (cast (D))->getTemplatedDecl (); + return getFunctionDeclName (FD); + } + + case Decl::Namespace: + { + const NamespaceDecl *ND + = (cast (D))->getCanonicalDecl (); + + if (ND->isAnonymousNamespace ()) + return createDup ("Anonymous namespace"); + + return createDup (ND->getName ()); + } + case Decl::ClassTemplate: + + { + const clang::ClassTemplateDecl *CD + = (cast (D))->getCanonicalDecl (); + return createDup (CD->getName ()); + } + case Decl::CXXRecord: + { + const clang::CXXRecordDecl *RD + = (cast (D))->getCanonicalDecl (); + return createDup (RD->getName ()); + } + + default: + return createEmpty (); + } } return createEmpty (); @@ -478,28 +478,82 @@ clang_getCalleeName (CXCursor C) const Expr *E = getCursorExpr (C); if (E->getStmtClass () == Stmt::CallExprClass) - { - const clang::CallExpr *CE = cast (E); - const Decl *D = CE->getCalleeDecl (); - - auto getFunctionDeclName = [] (const FunctionDecl *FD) { - const DeclarationName FunctionName = FD->getNameInfo ().getName (); - return createDup (FunctionName.getAsString ().c_str ()); - }; - - const clang::FunctionDecl *FD; - if (D->getKind () == Decl::FunctionTemplate) - FD = (cast (D))->getTemplatedDecl (); - else - FD = cast (D); - return getFunctionDeclName (FD); - } + { + const clang::CallExpr *CE = cast (E); + const Decl *D = CE->getCalleeDecl (); + + auto getFunctionDeclName = [] (const FunctionDecl *FD) { + const DeclarationName FunctionName = FD->getNameInfo ().getName (); + return createDup (FunctionName.getAsString ().c_str ()); + }; + + const clang::FunctionDecl *FD; + if (D->getKind () == Decl::FunctionTemplate) + FD = (cast (D))->getTemplatedDecl (); + else + FD = cast (D); + return getFunctionDeclName (FD); + } } return createEmpty (); } -/* Return the string representative of the operator for a binary or unary - operator node. */ +extern "C" unsigned +clang_isConstexpr (CXCursor C) +{ + if (clang_isDeclaration (C.kind)) + { + if (const Decl *D = getCursorDecl (C)) + { + switch (D->getKind ()) + { + case Decl::FunctionTemplate: + { + const clang::FunctionDecl *FD + = (cast (D)) + ->getTemplatedDecl (); + return FD->isConstexpr () ? 1 : 0; + } + case Decl::Function: + case Decl::CXXMethod: + case Decl::CXXConstructor: + case Decl::CXXDestructor: + { + const FunctionDecl *FD = cast (D); + return FD->isConstexpr () ? 1 : 0; + } + case Decl::Kind::Var: + const VarDecl *VD = cast (D); + return VD->isConstexpr () ? 1 : 0; + } + } + } + else if (clang_isStatement (C.kind)) + if (const Stmt *S = getCursorStmt (C)) + switch (S->getStmtClass ()) + { + case Stmt::IfStmtClass: + { + const IfStmt *ifStmt = cast (S); + return ifStmt->isConstexpr () ? 1 : 0; + } + case Stmt::DeclStmtClass: + { + // For DeclStmt, consider it a constexpr if any of the its + // variable declaration is. This avoids spurious checking on the + // C instrumentation side. + + const DeclStmt *declStmt = cast (S); + for (const auto *innerDecl : declStmt->decls ()) + if (const auto *varDecl = dyn_cast (innerDecl)) + return varDecl->isConstexpr () ? 1 : 0; + } + } + return 0; +} + +/* Return the string representative of the operator for a binary + or unary operator node. */ extern "C" CXString clang_getOpcodeStr (CXCursor C) @@ -507,20 +561,21 @@ clang_getOpcodeStr (CXCursor C) if (clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::BinaryOperatorClass: - return createRef (BinaryOperator::getOpcodeStr ( - cast (S)->getOpcode ())); - case Stmt::UnaryOperatorClass: - return createRef (UnaryOperator::getOpcodeStr ( - cast (S)->getOpcode ())); - default: - return createEmpty (); - } + { + case Stmt::BinaryOperatorClass: + return createRef (BinaryOperator::getOpcodeStr ( + cast (S)->getOpcode ())); + case Stmt::UnaryOperatorClass: + return createRef (UnaryOperator::getOpcodeStr ( + cast (S)->getOpcode ())); + default: + return createEmpty (); + } return createEmpty (); } -/* Return the location of the operator for a binary / unary operator node. */ +/* Return the location of the operator for a binary / unary + * operator node. */ extern "C" CXSourceLocation clang_getOperatorLoc (CXCursor C) @@ -530,22 +585,23 @@ clang_getOperatorLoc (CXCursor C) if (clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::BinaryOperatorClass: - sloc = cast (S)->getOperatorLoc (); - break; - case Stmt::UnaryOperatorClass: - sloc = cast (S)->getOperatorLoc (); - break; - default: - return clang_getNullLocation (); - } + { + case Stmt::BinaryOperatorClass: + sloc = cast (S)->getOperatorLoc (); + break; + case Stmt::UnaryOperatorClass: + sloc = cast (S)->getOperatorLoc (); + break; + default: + return clang_getNullLocation (); + } return translateSLoc (TU, sloc); } -/* If the given expression is a wrapping expression (i.e. a parenthesized - expression, a cast expression etc.), return the outermost expression inside - that is not a wrapping expression. */ +/* If the given expression is a wrapping expression (i.e. a + parenthesized expression, a cast expression etc.), return the + outermost expression inside that is not a wrapping expression. + */ extern "C" CXCursor clang_unwrap (CXCursor C) @@ -553,42 +609,44 @@ clang_unwrap (CXCursor C) if (clang_isExpression (C.kind)) if (const Stmt *S = getCursorStmt (C)) switch (S->getStmtClass ()) - { - case Stmt::ParenExprClass: - return clang_unwrap ( - MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); - case Expr::ConstantExprClass: - case Expr::ExprWithCleanupsClass: - return clang_unwrap ( - MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); - case Expr::ImplicitCastExprClass: - case Expr::CStyleCastExprClass: - case Expr::CXXFunctionalCastExprClass: - case Expr::CXXStaticCastExprClass: - case Expr::CXXDynamicCastExprClass: - case Expr::CXXReinterpretCastExprClass: - case Expr::CXXConstCastExprClass: - case Expr::CXXAddrspaceCastExprClass: - return clang_unwrap ( - MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); - } + { + case Stmt::ParenExprClass: + return clang_unwrap ( + MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); + case Expr::ConstantExprClass: + case Expr::ExprWithCleanupsClass: + return clang_unwrap ( + MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); + case Expr::ImplicitCastExprClass: + case Expr::CStyleCastExprClass: + case Expr::CXXFunctionalCastExprClass: + case Expr::CXXStaticCastExprClass: + case Expr::CXXDynamicCastExprClass: + case Expr::CXXReinterpretCastExprClass: + case Expr::CXXConstCastExprClass: + case Expr::CXXAddrspaceCastExprClass: + return clang_unwrap ( + MakeCXCursorWithNull (cast (S)->getSubExpr (), C)); + } return C; } -/* Visit a node, starting by itself (in contrary to clang_visitChildren that - immediately starts with the children of the node). */ +/* Visit a node, starting by itself (in contrary to + clang_visitChildren that immediately starts with the children + of the node). */ extern "C" unsigned clang_visit (CXCursor parent, CXCursorVisitor visitor, - CXClientData client_data) + CXClientData client_data) { CursorVisitor CursorVis (getCursorTU (parent), visitor, client_data, - /*VisitPreprocessorLast=*/false); + /*VisitPreprocessorLast=*/false); return CursorVis.Visit (parent); } -/* Returns the parent node of the given node. This accepts statements and - expressions, unlike clang_getLexicalParent and clang_getCursorParent. */ +/* Returns the parent node of the given node. This accepts + statements and expressions, unlike clang_getLexicalParent and + clang_getCursorParent. */ extern "C" CXCursor clang_getParent (CXCursor C) @@ -598,10 +656,10 @@ clang_getParent (CXCursor C) { const auto Parents = getContext (C).getParents (*S); if (Parents.empty ()) - return clang_getNullCursor (); + return clang_getNullCursor (); const auto &SParent = Parents[0]; if (const auto *Res = SParent.get ()) - return MakeCXCursorWithNull (Res, C); + return MakeCXCursorWithNull (Res, C); } return clang_getNullCursor (); } @@ -610,7 +668,7 @@ clang_getParent (CXCursor C) extern "C" void clang_CXRewriter_insertTextAfter (CXRewriter Rew, CXSourceLocation Loc, - const char *Insert) + const char *Insert) { assert (Rew); Rewriter &R = *reinterpret_cast (Rew); @@ -619,7 +677,7 @@ clang_CXRewriter_insertTextAfter (CXRewriter Rew, CXSourceLocation Loc, extern "C" void clang_CXRewriter_insertTextAfterToken (CXRewriter Rew, CXSourceLocation Loc, - const char *Insert) + const char *Insert) { assert (Rew); Rewriter &R = *reinterpret_cast (Rew); @@ -628,7 +686,7 @@ clang_CXRewriter_insertTextAfterToken (CXRewriter Rew, CXSourceLocation Loc, extern "C" void clang_CXRewriter_insertTextBeforeToken (CXRewriter Rew, CXSourceLocation Loc, - const char *Insert) + const char *Insert) { assert (Rew); Rewriter &R = *reinterpret_cast (Rew); @@ -651,7 +709,7 @@ clang_isMacroLocation (CXSourceLocation Loc) extern "C" unsigned clang_isMacroArgExpansion (CXSourceLocation Loc, CXSourceLocation *StartLoc, - CXTranslationUnit TU) + CXTranslationUnit TU) { const SourceManager &SM = getSourceManager (TU); const SourceLocation SLoc = translateSourceLocation (Loc); @@ -684,7 +742,7 @@ clang_getImmediateExpansionLoc (CXSourceLocation Loc, CXTranslationUnit TU) extern "C" CXString clang_getImmediateMacroNameForDiagnostics (CXSourceLocation Loc, - CXTranslationUnit TU) + CXTranslationUnit TU) { SourceLocation SLoc = translateSourceLocation (Loc); const SourceManager &SM = getSourceManager (TU); From 6897c90dce691c83459d27cb48b9d948879d1c20 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 22 Aug 2023 11:38:51 +0200 Subject: [PATCH 0399/1483] Pass down the value of Do_Not_Instrument to recursive calls To avoid picking the default value for Do_Not_Instrument, we should pass down its actual value to recursive calls. We have very little testing for not instrumented source code constructs, so this does not originate from a regression / unvalid instrumented code but it is safer. --- tools/gnatcov/instrument-ada_unit.adb | 40 +++++++++++++++++++-------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 123771c90..5636a0dd0 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -5932,7 +5932,7 @@ package body Instrument.Ada_Unit is end if; else - Process_Decisions (UIC, N, 'X'); + Process_Decisions (UIC, N, 'X', Do_Not_Instrument); end if; end Find_Nested_Decisions; @@ -6027,33 +6027,48 @@ package body Instrument.Ada_Unit is Alt : constant Elsif_Expr_Part_List := IEN.F_Alternatives; begin - Process_Decisions (UIC, IEN.F_Cond_Expr, 'I'); - Process_Decisions (UIC, IEN.F_Then_Expr, 'X'); + Process_Decisions + (UIC, IEN.F_Cond_Expr, 'I', Do_Not_Instrument); + Process_Decisions + (UIC, IEN.F_Then_Expr, 'X', Do_Not_Instrument); for J in 1 .. Alt.Children_Count loop declare EIN : constant Elsif_Expr_Part := Alt.Child (J).As_Elsif_Expr_Part; begin - Process_Decisions (UIC, EIN.F_Cond_Expr, 'I'); - Process_Decisions (UIC, EIN.F_Then_Expr, 'X'); + Process_Decisions + (UIC, EIN.F_Cond_Expr, 'I', Do_Not_Instrument); + Process_Decisions + (UIC, EIN.F_Then_Expr, 'X', Do_Not_Instrument); end; end loop; - Process_Decisions (UIC, IEN.F_Else_Expr, 'X'); + Process_Decisions + (UIC, IEN.F_Else_Expr, 'X', Do_Not_Instrument); return Over; end; when Ada_Quantified_Expr => Process_Decisions - (UIC, N.As_Quantified_Expr.F_Loop_Spec, 'X'); - Process_Decisions (UIC, N.As_Quantified_Expr.F_Expr, 'W'); + (UIC, + N.As_Quantified_Expr.F_Loop_Spec, + 'X', + Do_Not_Instrument); + Process_Decisions + (UIC, N.As_Quantified_Expr.F_Expr, 'W', Do_Not_Instrument); return Over; when Ada_For_Loop_Spec => - Process_Decisions (UIC, N.As_For_Loop_Spec.F_Var_Decl, 'X'); - Process_Decisions (UIC, N.As_For_Loop_Spec.F_Iter_Expr, 'X'); - Process_Decisions (UIC, N.As_For_Loop_Spec.F_Iter_Filter, 'W'); + Process_Decisions + (UIC, N.As_For_Loop_Spec.F_Var_Decl, 'X', Do_Not_Instrument); + Process_Decisions + (UIC, N.As_For_Loop_Spec.F_Iter_Expr, 'X', Do_Not_Instrument); + Process_Decisions + (UIC, + N.As_For_Loop_Spec.F_Iter_Filter, + 'W', + Do_Not_Instrument); return Over; -- Aspects for which we don't want to instrument the decision @@ -6082,7 +6097,8 @@ package body Instrument.Ada_Unit is -- them, but do process the final expression. when Ada_Decl_Expr => - Process_Decisions (UIC, N.As_Decl_Expr.F_Expr, 'X'); + Process_Decisions + (UIC, N.As_Decl_Expr.F_Expr, 'X', Do_Not_Instrument); return Over; -- All other cases, continue scan From 62e7d461baf49dd8ddef1ed05c25be24f4e34039 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 25 Aug 2023 12:30:52 +0200 Subject: [PATCH 0400/1483] Refactor logic when exceeding the path count limit Return Path_Count_Limit + 1 rather than 0 as a special value to indicate that the number of paths in a decision binary diagram exceeds the path count limit, to be able to distinguish such cases from static decisions. --- tools/gnatcov/instrument-ada_unit.adb | 11 +++++++---- tools/gnatcov/instrument-c.adb | 3 ++- tools/gnatcov/instrument-common.adb | 4 +++- tools/gnatcov/sc_obligations-bdd.adb | 2 +- tools/gnatcov/sc_obligations.ads | 4 +--- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 5636a0dd0..f7019c92a 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8264,13 +8264,16 @@ package body Instrument.Ada_Unit is Decision : constant SCO_Id := Enclosing_Decision (Condition); begin - if Path_Count (Decision) /= 0 - and then not SC.Decision_Static + -- If the number of paths in the decision binary diagram + -- exceeds the path count limit, we do not instrument it. + + if Path_Count (Decision) > Get_Path_Count_Limit + and then not SC.Decision_Static then + Set_Decision_SCO_Non_Instr_For_MCDC (Decision); + else Insert_Condition_Witness (UIC, SC, Offset_For_True (Condition)); - else - Set_Decision_SCO_Non_Instr_For_MCDC (Decision); end if; end; end loop; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 0b4a742bf..2be39fda3 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3110,7 +3110,8 @@ package body Instrument.C is Decision : constant SCO_Id := Enclosing_Decision (Condition); begin - if Path_Count (Decision) = 0 then + if Path_Count (Decision) > Get_Path_Count_Limit + then Set_Decision_SCO_Non_Instr_For_MCDC (Decision); else Insert_Condition_Witness diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index dbe66dc63..3c54cbfb0 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -216,7 +216,9 @@ package body Instrument.Common is -- Warn if the number of paths exceeded the limit - if Path_Count = 0 and then Coverage.MCDC_Coverage_Enabled then + if Path_Count > Get_Path_Count_Limit + and then Coverage.MCDC_Coverage_Enabled + then Diagnostics.Report (Decision_Sloc, "Number of distinct paths in the decision exceeds the limit" diff --git a/tools/gnatcov/sc_obligations-bdd.adb b/tools/gnatcov/sc_obligations-bdd.adb index a2da013a7..9ffc1e79b 100644 --- a/tools/gnatcov/sc_obligations-bdd.adb +++ b/tools/gnatcov/sc_obligations-bdd.adb @@ -301,7 +301,7 @@ package body SC_Obligations.BDD is BDD.Path_Count := Path_Count (BDD.Root_Condition); exception when Path_Limit_Error => - BDD.Path_Count := 0; + BDD.Path_Count := Path_Count_Limit + 1; end Enumerate_Paths; --------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 07ffe8ec6..9ce5851ce 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -538,9 +538,7 @@ package SC_Obligations is function Path_Count (SCO : SCO_Id) return Natural; -- Return count of paths through decision's BDD from root condition to -- any outcome. This should be a positive number for any decision - -- (at least 2, one for the True outcome, and one for the False outcome), - -- but this function can also return 0 when the number of paths exceeds - -- the limit set with Set_Path_Count_Limit. + -- (at least 2, one for the True outcome, and one for the False outcome). procedure Set_Path_Count_Limit (Limit : Natural); -- Set the path count limit beyond which BDD path enumeration is aborted From ed88172a47b4da97388992d24c0beda56b0eedf5 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 22 Aug 2023 11:38:07 +0200 Subject: [PATCH 0401/1483] Refactor handling of not instrumented obligations We had different ways of dealing with not instrumented statements, and decisions / conditions. Unify both for clarity purposes. Also move parts of the not instrumented obligations handling to Instrument.Common, to be able to use it in Instrument.C, as we will need it for constexpr code constructs. --- tools/gnatcov/decision_map.adb | 2 - tools/gnatcov/instrument-ada_unit.adb | 146 +++++++++----------------- tools/gnatcov/instrument-ada_unit.ads | 18 ---- tools/gnatcov/instrument-common.adb | 23 ++++ tools/gnatcov/instrument-common.ads | 8 ++ tools/gnatcov/sc_obligations.adb | 18 ++-- tools/gnatcov/sc_obligations.ads | 2 +- 7 files changed, 91 insertions(+), 126 deletions(-) diff --git a/tools/gnatcov/decision_map.adb b/tools/gnatcov/decision_map.adb index 04f6eb8a9..955560070 100644 --- a/tools/gnatcov/decision_map.adb +++ b/tools/gnatcov/decision_map.adb @@ -80,8 +80,6 @@ package body Decision_Map is -- Return the PC of the first conditional branch instruction in D_Occ. -- Used as unique identifier for occurrences. - package SCO_Sets is new Ada.Containers.Ordered_Sets (SCO_Id); - type Call_Kind is (Normal, Raise_Exception, Finalizer); -- Classification of calls within a decision: -- - normal calls to subprograms diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index f7019c92a..8a1838036 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -96,11 +96,6 @@ package body Instrument.Ada_Unit is return Ada_Qualified_Name; -- Convert a Libadalang fully qualified name into our format - procedure Import_Non_Instrumented_LL_SCOs - (UIC : Ada_Unit_Inst_Context; SCO_Map : LL_HL_SCO_Map); - -- Import the low level SCO in UIC marked as non-instrumented in the high - -- level non-instrumented SCO_Id sets. - procedure Find_Ada_Units (Instrumenter : in out Ada_Instrumenter_Type; Filename : String; @@ -165,29 +160,6 @@ package body Instrument.Ada_Unit is end return; end To_Qualified_Name; - ------------------------------------- - -- Import_Non_Instrumented_LL_SCOs -- - ------------------------------------- - - procedure Import_Non_Instrumented_LL_SCOs - (UIC : Ada_Unit_Inst_Context; SCO_Map : LL_HL_SCO_Map) is - begin - for LL_SCO of UIC.Non_Instr_LL_SCOs loop - declare - Remapped_SCO : constant SCO_Id := SCO_Map (Nat (LL_SCO)); - begin - case Kind (Remapped_SCO) is - when Statement => Set_Stmt_SCO_Non_Instr (Remapped_SCO); - when Decision => Set_Decision_SCO_Non_Instr (Remapped_SCO); - when Condition => Set_Decision_SCO_Non_Instr_For_MCDC - (Enclosing_Decision (Remapped_SCO)); - when others => - null; - end case; - end; - end loop; - end Import_Non_Instrumented_LL_SCOs; - type All_Symbols is ( -- Aspects @@ -2972,8 +2944,8 @@ package body Instrument.Ada_Unit is -- top level). -- -- If Do_Not_Instrument, this creates SCOs for the decisions/conditions, - -- but plan not to instrument them, so that the decision can be reported as - -- such. + -- but plans not to instrument them, so that the decision can be reported + -- as such. -------------------------- -- Internal Subprograms -- @@ -3067,6 +3039,10 @@ package body Instrument.Ada_Unit is In_Generic : Boolean := False; -- Wether this statment is generic code. + + Do_Not_Instrument : Boolean; + -- Whether this statement should not be instrumented. This is set to + -- True when instrumenting the statement could create invalid Ada code. end record; package SC is new Table.Table @@ -3126,8 +3102,7 @@ package body Instrument.Ada_Unit is SD_First : constant Nat := SD.Last + 1; -- Record first entries used in SC/SD at this recursive level - Current_Insertion_Info : aliased Insertion_Info := - (Method => None, Unsupported => False); + Current_Insertion_Info : aliased Insertion_Info := (Method => None); procedure Extend_Statement_Sequence (UIC : Ada_Unit_Inst_Context; @@ -3135,7 +3110,8 @@ package body Instrument.Ada_Unit is Typ : Character; Insertion_N : Node_Rewriting_Handle := No_Node_Rewriting_Handle; - Instrument_Location : Instrument_Location_Type := Before); + Instrument_Location : Instrument_Location_Type := Before; + Do_Not_Instrument : Boolean := False); -- Extend the current statement sequence to encompass the node N. -- -- Typ is the letter that identifies the type of statement/declaration @@ -3206,7 +3182,8 @@ package body Instrument.Ada_Unit is Typ : Character; Insertion_N : Node_Rewriting_Handle := No_Node_Rewriting_Handle; - Instrument_Location : Instrument_Location_Type := Before) + Instrument_Location : Instrument_Location_Type := Before; + Do_Not_Instrument : Boolean := False) is SR : constant Source_Location_Range := N.Sloc_Range; @@ -3344,7 +3321,8 @@ package body Instrument.Ada_Unit is when others => After) else Instrument_Location), - In_Generic => UIC.In_Generic)); + In_Generic => UIC.In_Generic, + Do_Not_Instrument => Do_Not_Instrument)); end Extend_Statement_Sequence; ----------------------------- @@ -3442,12 +3420,7 @@ package body Instrument.Ada_Unit is Raise_Stub_Internal_Error_For (Ada_Instrument_Insert_Stmt_Witness); - -- If the current code pattern is actually unsupported, do not - -- even try to insert the witness call or allocate bits for it in - -- the buffers. Mark the corresponding SCO as non-instrumented - -- instead. - - if Insert_Info.Unsupported then + if SCE.Do_Not_Instrument then UIC.Non_Instr_LL_SCOs.Include (SCO_Id (LL_SCO_Id)); return; end if; @@ -3863,7 +3836,6 @@ package body Instrument.Ada_Unit is begin II.RH_List := Stmt_list_RH; - II.Unsupported := False; II.Index := 1; II.Rewriting_Offset := 0; II.Preelab := False; @@ -3951,8 +3923,7 @@ package body Instrument.Ada_Unit is -- Witness insertion info for statements (for both null procedures -- and expression functions). - Unsupported : Boolean := False; - -- Temporary to compute New_Insertion_Info.Unsupported + Do_Not_Instrument : Boolean := False; EF_Inserter : aliased Expr_Func_MCDC_State_Inserter := (N_Spec => N_Spec, @@ -3989,7 +3960,7 @@ package body Instrument.Ada_Unit is if Is_Generic (UIC, N.As_Basic_Decl) then if Is_Expr_Function then - Unsupported := True; + Do_Not_Instrument := True; Report (UIC, N, "gnatcov limitation: " & "cannot instrument generic expression functions." @@ -4000,7 +3971,7 @@ package body Instrument.Ada_Unit is -- functions and null procedures, we are in the case of a -- generic null procedure here. - Unsupported := True; + Do_Not_Instrument := True; Report (UIC, N, "gnatcov limitation:" & " cannot instrument generic null procedures." @@ -4036,7 +4007,7 @@ package body Instrument.Ada_Unit is -- so that the augmented EF is no longer a primitive of its -- return type. Need to check for potential freezing issues. - Unsupported := True; + Do_Not_Instrument := True; Report (UIC, N, "gnatcov limitation:" & " cannot instrument an expression function which is" @@ -4047,7 +4018,7 @@ package body Instrument.Ada_Unit is elsif Is_Self_Referencing (UIC, N.As_Expr_Function) and then not Common_Nodes.Ctrl_Type.Is_Null then - Unsupported := True; + Do_Not_Instrument := True; Report (UIC, N, "gnatcov limitation:" & " instrumenting a self referencing (i.e. recursive)" @@ -4086,11 +4057,10 @@ package body Instrument.Ada_Unit is New_Insertion_Info := (Method => Expression_Function, - Unsupported => Unsupported, Witness_Actual => No_Node_Rewriting_Handle, Witness_Formal => No_Node_Rewriting_Handle); - if not New_Insertion_Info.Unsupported then + if not Do_Not_Instrument then -- Pass all expression function parameters to the augmented -- expression function call. @@ -4124,7 +4094,6 @@ package body Instrument.Ada_Unit is New_Insertion_Info := (Method => Statement, - Unsupported => Unsupported, RH_List => NP_Nodes.Stmt_List, Index => 1, Rewriting_Offset => 0, @@ -4153,18 +4122,9 @@ package body Instrument.Ada_Unit is declare N_Expr : constant Expr := N.As_Expr_Function.F_Expr; begin - Extend_Statement_Sequence (UIC, N_Expr, 'X'); - - -- For unsupported expression functions, creating a statement - -- obligation is enough: it will never be satisfied and thus - -- violations regarding conditions/decisions will not be - -- displayed, so no need to bother creating them and adding - -- special cases in decision processings for unsupported - -- expression functions. - - if not New_Insertion_Info.Unsupported then - Process_Decisions_Defer (N_Expr, 'X'); - end if; + Extend_Statement_Sequence + (UIC, N_Expr, 'X', Do_Not_Instrument => Do_Not_Instrument); + Process_Decisions_Defer (N_Expr, 'X', Do_Not_Instrument); end; else -- Even though there is a "null" keyword in the null procedure, @@ -4172,10 +4132,11 @@ package body Instrument.Ada_Unit is -- the whole null procedure declaration to provide a sloc. Extend_Statement_Sequence - (UIC => UIC, - N => N, - Typ => 'X', - Insertion_N => NP_Nodes.Null_Stmt); + (UIC => UIC, + N => N, + Typ => 'X', + Insertion_N => NP_Nodes.Null_Stmt, + Do_Not_Instrument => Do_Not_Instrument); end if; Set_Statement_Entry; @@ -4187,7 +4148,7 @@ package body Instrument.Ada_Unit is -- There is nothing else to do if we gave up instrumenting this -- subprogram. - if New_Insertion_Info.Unsupported then + if Do_Not_Instrument then return; end if; @@ -5171,7 +5132,6 @@ package body Instrument.Ada_Unit is else Declaration); II : Insertion_Info (Method); begin - II.Unsupported := False; II.RH_List := Handle (L); II.Index := 0; II.Rewriting_Offset := 0; @@ -5686,7 +5646,6 @@ package body Instrument.Ada_Unit is Op_NK : Ada_Node_Kind_Type; begin - -- Logical operator if Is_Logical_Operator (UIC, N) then @@ -5733,14 +5692,16 @@ package body Instrument.Ada_Unit is else Output_Element (N.As_Ada_Node); + if Decision_Static or else Do_Not_Instrument then + return; + end if; if MCDC_Coverage_Enabled then UIC.Source_Conditions.Append (Source_Condition' (LL_SCO => SCOs.SCO_Table.Last, Condition => N.As_Expr, State => MCDC_State, - First => Condition_Count = 0, - Decision_Static => Decision_Static)); + First => Condition_Count = 0)); Condition_Count := Condition_Count + 1; end if; @@ -5778,6 +5739,9 @@ package body Instrument.Ada_Unit is SFI => UIC.SFI, Last => False); Hash_Entries.Append ((Start_Sloc (N_SR), SCOs.SCO_Table.Last)); + if Do_Not_Instrument then + UIC.Non_Instr_LL_SCOs.Include (SCO_Id (SCOs.SCO_Table.Last)); + end if; end Output_Element; ------------------- @@ -5858,6 +5822,9 @@ package body Instrument.Ada_Unit is SFI => UIC.SFI, Last => False, Pragma_Aspect_Name => Nam); + if Do_Not_Instrument then + UIC.Non_Instr_LL_SCOs.Include (SCO_Id (SCOs.SCO_Table.Last)); + end if; Current_Decision := SCOs.SCO_Table.Last; @@ -5896,13 +5863,15 @@ package body Instrument.Ada_Unit is -- For this reason, also refrain from instrumenting static -- decisions. - UIC.Source_Decisions.Append - (Source_Decision' - (LL_SCO => Current_Decision, - Decision => N.As_Expr, - State => MCDC_State, - Do_Not_Instrument => Do_Not_Instrument - or else Is_Static_Expr (N.As_Expr))); + if not (Do_Not_Instrument + or else Is_Static_Expr (N.As_Expr)) + then + UIC.Source_Decisions.Append + (Source_Decision' + (LL_SCO => Current_Decision, + Decision => N.As_Expr, + State => MCDC_State)); + end if; end if; -- For an aspect specification, which will be rewritten into a @@ -8224,18 +8193,10 @@ package body Instrument.Ada_Unit is if Coverage.Enabled (Decision) or else MCDC_Coverage_Enabled then for SD of UIC.Source_Decisions loop - - -- Mark non-instrumented decisions as such so that they are - -- properly reported. - declare HL_SCO : constant SCO_Id := SCO_Map (SD.LL_SCO); begin - if SD.Do_Not_Instrument then - Set_Decision_SCO_Non_Instr (HL_SCO); - else - Insert_Decision_Witness (UIC, SD, Path_Count (HL_SCO)); - end if; + Insert_Decision_Witness (UIC, SD, Path_Count (HL_SCO)); end; end loop; @@ -8249,11 +8210,6 @@ package body Instrument.Ada_Unit is -- in a decision with a path count exceeding the limit to avoid -- generating overly large traces / run out of memory. -- - -- We also do not include witness calls for conditions of - -- static decision, as this would make the instrumented - -- expression non-static. Mark the enclosing decision as not - -- instrumented for MCDC instead. - -- -- As we go through each condition, mark their enclosing -- decision as not instrumented if their number of paths -- exceeds our limit. @@ -8267,9 +8223,7 @@ package body Instrument.Ada_Unit is -- If the number of paths in the decision binary diagram -- exceeds the path count limit, we do not instrument it. - if Path_Count (Decision) > Get_Path_Count_Limit - and then not SC.Decision_Static - then + if Path_Count (Decision) > Get_Path_Count_Limit then Set_Decision_SCO_Non_Instr_For_MCDC (Decision); else Insert_Condition_Witness diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 1635b2208..d11d41d7b 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -139,13 +139,6 @@ private -- in a case expression whose controlling expr is a witness call. type Insertion_Info (Method : Insertion_Method := None) is record - - Unsupported : Boolean; - -- Whether we gave up on inserting witness calls. This is True when - -- processing a code pattern that we do not know how to instrument. Note - -- that we still processes such patterns to create the corresponding - -- coverage obligations. - case Method is when Statement | Declaration => RH_List : Node_Rewriting_Handle := No_Node_Rewriting_Handle; @@ -205,10 +198,6 @@ private State : Ada.Strings.Unbounded.Unbounded_String; -- Name of MC/DC state local variable - - Do_Not_Instrument : Boolean; - -- Whether this decision should not be instrumented. This is set to True - -- when instrumenting the decision could create invalid Ada code. end record; type Source_Condition is record @@ -223,10 +212,6 @@ private First : Boolean; -- True if this condition is the first one in its decision - - Decision_Static : Boolean := False; - -- True if the expression of the enclosing decision is static - -- (according to the RM definition of static). end record; package Source_Decision_Vectors is @@ -345,9 +330,6 @@ private -- Used when the SPARK compatibility mode is enabled, to insert -- non-volatile witness result variables to be ghost compliant. - Non_Instr_LL_SCOs : Non_Instrumented_SCO_Sets.Set; - -- Set of low level SCO ids that were not instrumented - Current_Scope_Entity : Scope_Entity_Acc := null; -- Information about the name, sloc, SCO range and children scopes of -- the current scope entity. This is modified when entering a scope diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 3c54cbfb0..7fcf21fda 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -260,6 +260,29 @@ package body Instrument.Common is end loop; end Import_Annotations; + ------------------------------------- + -- Import_Non_Instrumented_LL_SCOs -- + ------------------------------------- + + procedure Import_Non_Instrumented_LL_SCOs + (UIC : Unit_Inst_Context; SCO_Map : LL_HL_SCO_Map) is + begin + for LL_SCO of UIC.Non_Instr_LL_SCOs loop + declare + Remapped_SCO : constant SCO_Id := SCO_Map (Nat (LL_SCO)); + begin + case Kind (Remapped_SCO) is + when Statement => Set_Stmt_SCO_Non_Instr (Remapped_SCO); + when Decision => Set_Decision_SCO_Non_Instr (Remapped_SCO); + when Condition => Set_Decision_SCO_Non_Instr_For_MCDC + (Enclosing_Decision (Remapped_SCO)); + when others => + null; + end case; + end; + end loop; + end Import_Non_Instrumented_LL_SCOs; + ----------------- -- Append_Unit -- ----------------- diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 6419614d5..a93756893 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -336,6 +336,9 @@ package Instrument.Common is -- Annotations created during the instrumentation process, to insert in -- ALI_Files.ALI_Annotations afterwards, when the compilation unit -- (SC_Obligations.CU_Info) for this annotation is ready. + + Non_Instr_LL_SCOs : SCO_Sets.Set; + -- Set of low level SCO ids that were not instrumented end record; procedure Import_Annotations @@ -344,6 +347,11 @@ package Instrument.Common is -- This should be called once the unit was instrumented and its low level -- SCOS have been transformed into high-level ones. + procedure Import_Non_Instrumented_LL_SCOs + (UIC : Unit_Inst_Context; SCO_Map : LL_HL_SCO_Map); + -- Import the low level SCO in UIC marked as non-instrumented in the high + -- level non-instrumented SCO_Id sets. + function Img (Bit : Any_Bit_Id) return String is (Strings.Img (Integer (Bit))); diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 03917c4a4..d7c013bb8 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -532,8 +532,8 @@ package body SC_Obligations is Inst_Vector : Inst_Info_Vectors.Vector; BDD_Vector : BDD.BDD_Vectors.Vector; SCO_Vector : SCO_Vectors.Vector; - Non_Instr_SCOs : Non_Instrumented_SCO_Sets.Set; - Non_Instr_MCDC_SCOs : Non_Instrumented_SCO_Sets.Set; + Non_Instr_SCOs : SCO_Sets.Set; + Non_Instr_MCDC_SCOs : SCO_Sets.Set; end record; ----------------------------------------- @@ -592,7 +592,7 @@ package body SC_Obligations is SCO_Vector : SCO_Vectors.Vector renames SC_Vectors.SCO_Vector; -- Vector of high-level Source Coverage Obligations (for all units) - Non_Instr_SCOs : Non_Instrumented_SCO_Sets.Set renames + Non_Instr_SCOs : SCO_Sets.Set renames SC_Vectors.Non_Instr_SCOs; -- Set of SCOs that were not instrumented, either for stmt or decision. -- @@ -601,7 +601,7 @@ package body SC_Obligations is -- be removed once manual serialization of checkpoints/SID files is -- implemented. - Non_Instr_MCDC_SCOs : Non_Instrumented_SCO_Sets.Set renames + Non_Instr_MCDC_SCOs : SCO_Sets.Set renames SC_Vectors.Non_Instr_MCDC_SCOs; -- Set of decsion SCOs that were not instrumented for MCDC. -- @@ -740,7 +740,7 @@ package body SC_Obligations is end if; declare - use Non_Instrumented_SCO_Sets; + use SCO_Sets; CU_CP_Set : Set; CU_Set : Set; Cur : Cursor; @@ -1522,8 +1522,8 @@ package body SC_Obligations is -- Load non-instrumented information if not Version_Less (S, Than => 9) then - Non_Instrumented_SCO_Sets.Set'Read (S, CP_Vectors.Non_Instr_SCOs); - Non_Instrumented_SCO_Sets.Set'Read + SCO_Sets.Set'Read (S, CP_Vectors.Non_Instr_SCOs); + SCO_Sets.Set'Read (S, CP_Vectors.Non_Instr_MCDC_SCOs); end if; @@ -1660,8 +1660,8 @@ package body SC_Obligations is Inst_Info_Vectors.Vector'Write (S, Inst_Vector); BDD.BDD_Vectors.Vector'Write (S, BDD_Vector); SCO_Vectors.Vector'Write (S, SCO_Vector); - Non_Instrumented_SCO_Sets.Set'Write (S, Non_Instr_SCOs); - Non_Instrumented_SCO_Sets.Set'Write (S, Non_Instr_MCDC_SCOs); + SCO_Sets.Set'Write (S, Non_Instr_SCOs); + SCO_Sets.Set'Write (S, Non_Instr_MCDC_SCOs); end Checkpoint_Save; --------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 9ce5851ce..2b7de7331 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -428,7 +428,7 @@ package SC_Obligations is -- item in the source. The input SCO argument is expected to designate a -- statement SCO. - package Non_Instrumented_SCO_Sets is + package SCO_Sets is new Ada.Containers.Ordered_Sets (Element_Type => SCO_Id); procedure Set_Stmt_SCO_Non_Instr (SCO : SCO_Id) with From c233f9a05ed60517a91e82e7699f0dc2cf82031f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 16 Aug 2023 17:17:53 +0200 Subject: [PATCH 0402/1483] C++ instr: do not instrument constexpr Instrumenting constexpr functions violates the constexpr semantics and there is no straightforward valid way of instrumenting such code constructs. Skip their instrumentation altogether for the moment, as their use is quite limited (they are only allowed to return literal values). --- .../C++/mcdc/ConstExpr/src/test_constexpr.cpp | 28 +++ testsuite/tests/C++/mcdc/ConstExpr/test.py | 5 + tools/gnatcov/clang-extensions.adb | 14 ++ tools/gnatcov/clang-extensions.ads | 2 + tools/gnatcov/instrument-c.adb | 211 +++++++++++++----- tools/gnatcov/instrument-c.ads | 19 +- 6 files changed, 215 insertions(+), 64 deletions(-) create mode 100644 testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp create mode 100644 testsuite/tests/C++/mcdc/ConstExpr/test.py diff --git a/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp b/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp new file mode 100644 index 000000000..e6d8a31a6 --- /dev/null +++ b/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp @@ -0,0 +1,28 @@ +constexpr int +foo () +{ + if (true && false) // # ce-body + return 1; // # ce-body + constexpr bool a = true; // # ce-body + if constexpr (false) // # ce-body + return 1; // # ce-body + return 0; // # ce-body +} + +int +main(){ + constexpr bool a = true || false; // # single-ce-decl + constexpr bool b = true || false, c = true || false; // # double-ce-decl + if constexpr (false) // # if-ce + return 1; // # if-rt + return 0; // # rt +} + +//# test_constexpr.cpp +// +// /ce-body/ l? ## s? +// /single-ce-decl/ l? ## d? +// /double-ce-decl/ l? ## d?, d? +// /if-ce/ l? ## d? +// /if-rt/ l- ## s- +// /rt/ l+ ## 0 diff --git a/testsuite/tests/C++/mcdc/ConstExpr/test.py b/testsuite/tests/C++/mcdc/ConstExpr/test.py new file mode 100644 index 000000000..6f496a80c --- /dev/null +++ b/testsuite/tests/C++/mcdc/ConstExpr/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(tolerate_messages=r".* cannot instrument constexpr").run() +thistest.result() diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index 4a2211ced..2dae8f683 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -90,6 +90,20 @@ package body Clang.Extensions is return Opcode_Str; end Get_Opcode_Str; + ------------------ + -- Is_Constexpr -- + ------------------ + + function Is_Constexpr (C : Cursor_T) return Boolean + is + function Is_Constexpr_C (C : Cursor_T) return unsigned + with + Import, Convention => C, + External_Name => "clang_isConstexpr"; + begin + return Is_Constexpr_C (C) /= 0; + end Is_Constexpr; + ----------------------------------- -- CX_Rewriter_Insert_Text_After -- ----------------------------------- diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index a5c08e463..2689b9fdd 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -88,6 +88,8 @@ package Clang.Extensions is function Get_Callee_Name_Str (C : Cursor_T) return String with Inline; + function Is_Constexpr (C : Cursor_T) return Boolean with Inline; + function Unwrap (C : Cursor_T) return Cursor_T with Import, Convention => C, External_Name => "clang_unwrap"; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 2be39fda3..a34be6058 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -192,6 +192,13 @@ package body Instrument.C is First : Boolean); -- Add an entry to UIC.Source_Conditions + procedure Report + (Pass : Instrument_Pass_Kind; + Node : Cursor_T; + Msg : String; + Kind : Report_Kind := Diagnostics.Warning); + -- Report an instrumentation warning + overriding procedure Insert_MCDC_State (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; @@ -201,19 +208,19 @@ package body Instrument.C is overriding procedure Insert_Text_Before_Token (Pass : Instrument_Pass_Kind; - Rew : Rewriter_T; + UIC : C_Unit_Inst_Context'Class; Loc : Source_Location_T; Text : String); overriding procedure Insert_Text_Before (Pass : Instrument_Pass_Kind; - Rew : Rewriter_T; + UIC : C_Unit_Inst_Context'Class; Loc : Source_Location_T; Text : String); overriding procedure Insert_Text_After (Pass : Instrument_Pass_Kind; - Rew : Rewriter_T; + UIC : C_Unit_Inst_Context'Class; Loc : Source_Location_T; Text : String); @@ -944,7 +951,9 @@ package body Instrument.C is Name : String; MCDC_State : out US.Unbounded_String) is begin - MCDC_State := +Insert_MCDC_State (UIC, Name); + if not UIC.Disable_Instrumentation then + MCDC_State := +Insert_MCDC_State (UIC, Name); + end if; end Insert_MCDC_State; ------------------------------ @@ -953,11 +962,13 @@ package body Instrument.C is overriding procedure Insert_Text_Before_Token (Pass : Instrument_Pass_Kind; - Rew : Rewriter_T; + UIC : C_Unit_Inst_Context'Class; Loc : Source_Location_T; Text : String) is begin - CX_Rewriter_Insert_Text_Before_Token (Rew, Loc, Text); + if not UIC.Disable_Instrumentation then + CX_Rewriter_Insert_Text_Before_Token (UIC.Rewriter, Loc, Text); + end if; end Insert_Text_Before_Token; ------------------------ @@ -966,11 +977,13 @@ package body Instrument.C is overriding procedure Insert_Text_Before (Pass : Instrument_Pass_Kind; - Rew : Rewriter_T; + UIC : C_Unit_Inst_Context'Class; Loc : Source_Location_T; Text : String) is begin - CX_Rewriter_Insert_Text_Before (Rew, Loc, Text); + if not UIC.Disable_Instrumentation then + CX_Rewriter_Insert_Text_Before (UIC.Rewriter, Loc, Text); + end if; end Insert_Text_Before; ----------------------- @@ -979,11 +992,13 @@ package body Instrument.C is overriding procedure Insert_Text_After (Pass : Instrument_Pass_Kind; - Rew : Rewriter_T; + UIC : C_Unit_Inst_Context'Class; Loc : Source_Location_T; Text : String) is begin - CX_Rewriter_Insert_Text_After (Rew, Loc, Text); + if not UIC.Disable_Instrumentation then + CX_Rewriter_Insert_Text_After (UIC.Rewriter, Loc, Text); + end if; end Insert_Text_After; -------------------------- @@ -997,11 +1012,15 @@ package body Instrument.C is Insertion_N : Cursor_T; Instr_Scheme : Instr_Scheme_Type) is begin - UIC.Find_Instrumented_Entities (Last_File).Statements.Append - (C_Source_Statement' - (LL_SCO => SCOs.SCO_Table.Last, - Instr_Scheme => Instr_Scheme, - Statement => Insertion_N)); + if UIC.Disable_Instrumentation then + UIC.Non_Instr_LL_SCOs.Include (SCO_Id (LL_SCO)); + else + UIC.Find_Instrumented_Entities (Last_File).Statements.Append + (C_Source_Statement' + (LL_SCO => LL_SCO, + Instr_Scheme => Instr_Scheme, + Statement => Insertion_N)); + end if; end Instrument_Statement; ------------------------- @@ -1015,11 +1034,15 @@ package body Instrument.C is Decision : Cursor_T; State : US.Unbounded_String) is begin - UIC.Find_Instrumented_Entities (Last_File).Decisions.Append - (C_Source_Decision' - (LL_SCO => LL_SCO, - Decision => Decision, - State => State)); + if UIC.Disable_Instrumentation then + UIC.Non_Instr_LL_SCOs.Include (SCO_Id (LL_SCO)); + else + UIC.Find_Instrumented_Entities (Last_File).Decisions.Append + (C_Source_Decision' + (LL_SCO => LL_SCO, + Decision => Decision, + State => State)); + end if; end Instrument_Decision; -------------------------- @@ -1034,14 +1057,37 @@ package body Instrument.C is State : US.Unbounded_String; First : Boolean) is begin - UIC.Find_Instrumented_Entities (Last_File).Conditions.Append - (C_Source_Condition' - (LL_SCO => SCOs.SCO_Table.Last, - Condition => Condition, - State => State, - First => First)); + if UIC.Disable_Instrumentation then + UIC.Non_Instr_LL_SCOs.Include (SCO_Id (LL_SCO)); + else + UIC.Find_Instrumented_Entities (Last_File).Conditions.Append + (C_Source_Condition' + (LL_SCO => LL_SCO, + Condition => Condition, + State => State, + First => First)); + end if; end Instrument_Condition; + ------------ + -- Report -- + ------------ + + procedure Report + (Pass : Instrument_Pass_Kind; + Node : Cursor_T; + Msg : String; + Kind : Report_Kind := Diagnostics.Warning) + is + Sloc : constant Source_Location := Start_Sloc (Node); + begin + Diagnostics.Report ((Source_File => Sloc.Source_File, + L => (Line => Sloc.L.Line, + Column => Sloc.L.Column)), + Msg, + Kind); + end Report; + ----------------------- -- Make_Expr_Witness -- ----------------------- @@ -1312,7 +1358,9 @@ package body Instrument.C is -- Traverse a translation unit (top level declarations) procedure Process_Decisions - (UIC : in out C_Unit_Inst_Context; N : Cursor_T; T : Character); + (UIC : in out C_Unit_Inst_Context; + N : Cursor_T; + T : Character); -- If N is Empty, has no effect. Otherwise scans the tree for the node N, -- to output any decisions it contains. @@ -1356,7 +1404,9 @@ package body Instrument.C is ----------------------- procedure Process_Decisions - (UIC : in out C_Unit_Inst_Context; N : Cursor_T; T : Character) + (UIC : in out C_Unit_Inst_Context; + N : Cursor_T; + T : Character) is Mark : Nat; -- This is used to mark the location of a decision sequence in the SCO @@ -1869,6 +1919,8 @@ package body Instrument.C is -- being done with the instrumentation of the function (see the body -- of Traverse_Declarations). + Save_Disable_Instrumentation : constant Boolean := + UIC.Disable_Instrumentation; begin if Curlify (N) then Append (Trailing_Braces, '}'); @@ -1899,15 +1951,22 @@ package body Instrument.C is when Cursor_If_Stmt => Extend_Statement_Sequence (N, 'I'); + Set_Statement_Entry; declare Then_Part : constant Cursor_T := Get_Then (N); Else_Part : constant Cursor_T := Get_Else (N); begin - Process_Decisions_Defer (Get_Cond (N), 'I'); - Set_Statement_Entry; - Traverse_Statements - (UIC, To_Vector (Then_Part), TB); + if Is_Constexpr (N) then + UIC.Pass.Report + (N, + "gnatcov limitation: cannot instrument constexpr if" + & " statement."); + UIC.Disable_Instrumentation := True; + end if; + Process_Decisions (UIC, Get_Cond (N), 'I'); + UIC.Disable_Instrumentation := Save_Disable_Instrumentation; + Traverse_Statements (UIC, To_Vector (Then_Part), TB); -- Traverse the ELSE statements if present @@ -1916,11 +1975,9 @@ package body Instrument.C is -- Insert the trailing braces resulting from the -- traversal of the then part before the else. - UIC.Pass.Insert_Text_Before - (UIC.Rewriter, Get_Else_Loc (N), +TB); + UIC.Pass.Insert_Text_Before (UIC, Get_Else_Loc (N), +TB); TB := +""; - Traverse_Statements - (UIC, To_Vector (Else_Part), TB); + Traverse_Statements (UIC, To_Vector (Else_Part), TB); end if; end; @@ -1990,8 +2047,7 @@ package body Instrument.C is -- Insert the trailing braces resulting from the body -- traversal before the while. - UIC.Pass.Insert_Text_After - (UIC.Rewriter, Get_While_Loc (N), +TB); + UIC.Pass.Insert_Text_After (UIC, Get_While_Loc (N), +TB); TB := +""; -- Process the while decision @@ -2104,7 +2160,30 @@ package body Instrument.C is -- Process any embedded decisions if Has_Decision (N) then - Process_Decisions_Defer (N, 'X'); + if Is_Constexpr (N) then + + -- HACK: as we rely on the value of + -- UIC.Disable_Instrumentation to know if we should + -- instrument a source coverage obligation, we + -- have to process the decision before reenabling + -- instrumentation. Call Process_Decisions instead of + -- Process_Decisions_Defer, and Set_Statement_Entry + -- before to flush the statement SCOs. TODO???: rework + -- when eng/cov/gnatcoverage#107 is dealt with. + + UIC.Pass.Report + (N, + "gnatcov limitation: cannot instrument constexpr" + & " variable declarations."); + + Set_Statement_Entry; + UIC.Disable_Instrumentation := True; + Process_Decisions (UIC, N, 'X'); + UIC.Disable_Instrumentation := + Save_Disable_Instrumentation; + else + Process_Decisions_Defer (N, 'X'); + end if; end if; end case; @@ -2167,8 +2246,8 @@ package body Instrument.C is end if; SC.Append - ((N => Insert_Cursor, - Insertion_N => + ((N => Insert_Cursor, + Insertion_N => (if Is_Null (Insertion_N) then N else Insertion_N), @@ -2232,9 +2311,7 @@ package body Instrument.C is -- Curlify -- ------------- - function Curlify (N : Cursor_T) return Boolean - is - Rew : Rewriter_T renames UIC.Rewriter; + function Curlify (N : Cursor_T) return Boolean is begin case Kind (N) is when Cursor_If_Stmt => @@ -2244,13 +2321,13 @@ package body Instrument.C is begin if Kind (Then_Part) /= Cursor_Compound_Stmt then UIC.Pass.Insert_Text_Before - (Rew, Start_Sloc (Then_Part), "{"); + (UIC, Start_Sloc (Then_Part), "{"); if not Is_Null (Else_Part) then -- Close the brace introduced to wrap the then part -- if possible. UIC.Pass.Insert_Text_Before - (Rew, Get_Else_Loc (N), "}"); + (UIC, Get_Else_Loc (N), "}"); else -- Otherwise, we need to insert a trailing brace @@ -2264,7 +2341,7 @@ package body Instrument.C is and then Kind (Else_Part) /= Cursor_Compound_Stmt then UIC.Pass.Insert_Text_Before - (Rew, Start_Sloc (Else_Part), "{"); + (UIC, Start_Sloc (Else_Part), "{"); return True; end if; return False; @@ -2276,9 +2353,9 @@ package body Instrument.C is begin if Kind (Do_Body) /= Cursor_Compound_Stmt then UIC.Pass.Insert_Text_Before - (Rew, Start_Sloc (Do_Body), "{"); + (UIC, Start_Sloc (Do_Body), "{"); UIC.Pass.Insert_Text_Before - (Rew, Get_While_Loc (N), "}"); + (UIC, Get_While_Loc (N), "}"); end if; return False; end; @@ -2289,7 +2366,7 @@ package body Instrument.C is B : constant Cursor_T := Get_Body (N); begin if Kind (B) /= Cursor_Compound_Stmt then - UIC.Pass.Insert_Text_Before (Rew, Start_Sloc (B), "{"); + UIC.Pass.Insert_Text_Before (UIC, Start_Sloc (B), "{"); return True; end if; return False; @@ -2309,7 +2386,7 @@ package body Instrument.C is for N of L loop if Length (Trailing_Braces) /= 0 then UIC.Pass.Insert_Text_Before - (UIC.Rewriter, Start_Sloc (N), +Trailing_Braces); + (UIC, Start_Sloc (N), +Trailing_Braces); Trailing_Braces := +""; end if; Traverse_One (N, Trailing_Braces); @@ -2332,6 +2409,8 @@ package body Instrument.C is use Cursor_Vectors; Saved_MCDC_State_Declaration_Node : constant Cursor_T := UIC.MCDC_State_Declaration_Node; + Save_Disable_Instrumentation : constant Boolean := + UIC.Disable_Instrumentation; begin for N of L loop @@ -2350,32 +2429,43 @@ package body Instrument.C is | Cursor_Destructor | Cursor_Lambda_Expr => - UIC.Pass.Enter_Scope (UIC, N); - declare - -- Get_Body returns a Compound_Stmt, convert it to - -- a list of statements using the Get_Children - -- utility. - Fun_Body : constant Cursor_T := Get_Body (N); Stmts : constant Cursor_Vectors.Vector := Get_Children (Fun_Body); + -- Get_Body returns a Compound_Stmt, convert it to a list + -- of statements using the Get_Children utility. TB : Unbounded_String; -- Trailing braces that should be inserted at the end -- of the function body. + begin + UIC.Pass.Enter_Scope (UIC, N); + + -- Do not instrument constexpr function as it would + -- violate the constexpr restrictions. + + if Is_Constexpr (N) then + UIC.Pass.Report + (N, + "gnatcov limitation: cannot instrument constexpr" + & " functions."); + UIC.Disable_Instrumentation := True; + end if; + if Stmts.Length > 0 then UIC.MCDC_State_Declaration_Node := Stmts.First_Element; Traverse_Statements (UIC, Stmts, TB); UIC.Pass.Insert_Text_Before_Token - (UIC.Rewriter, End_Sloc (Fun_Body), +TB); + (UIC, End_Sloc (Fun_Body), +TB); end if; + UIC.Pass.Exit_Scope (UIC); + UIC.Disable_Instrumentation := + Save_Disable_Instrumentation; end; - UIC.Pass.Exit_Scope (UIC); - -- Traverse the declarations of a namespace / linkage -- specification etc. @@ -3068,6 +3158,7 @@ package body Instrument.C is UIC.Import_Annotations (UIC.CUs); Filter_Annotations; + Import_Non_Instrumented_LL_SCOs (UIC, SCO_Map); for Cur in UIC.Instrumented_Entities.Iterate loop declare diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 10003c672..946e5948c 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -30,6 +30,7 @@ with Clang.CX_Source_Location; use Clang.CX_Source_Location; with Clang.Index; use Clang.Index; with Clang.Rewrite; use Clang.Rewrite; +with Diagnostics; use Diagnostics; with Files_Table; use Files_Table; with Instrument.Common; use Instrument.Common; with Slocs; use Slocs; @@ -368,7 +369,11 @@ package Instrument.C is -- which scope was originally opened in which file. Current_File_Scope : Source_File_Index; - -- Source file in wich the last scope encountered was opened. + -- Source file in which the last scope encountered was opened + + Disable_Instrumentation : Boolean := False; + -- Set to True to deactivate instrumentation and prevent any code + -- rewriting. end record; type C_Source_Rewriter is tagged limited private; @@ -438,22 +443,28 @@ private procedure Insert_Text_Before_Token (Pass : Pass_Kind; - Rew : Rewriter_T; + UIC : C_Unit_Inst_Context'Class; Loc : Source_Location_T; Text : String) is null; procedure Insert_Text_Before (Pass : Pass_Kind; - Rew : Rewriter_T; + UIC : C_Unit_Inst_Context'Class; Loc : Source_Location_T; Text : String) is null; procedure Insert_Text_After (Pass : Pass_Kind; - Rew : Rewriter_T; + UIC : C_Unit_Inst_Context'Class; Loc : Source_Location_T; Text : String) is null; + procedure Report + (Pass : Pass_Kind; + Node : Cursor_T; + Msg : String; + Kind : Report_Kind := Diagnostics.Warning) is null; + type C_Source_Rewriter is limited new Ada.Finalization.Limited_Controlled with record CIdx : Index_T; From b7b713dd971cca1de143292715e8fd8de5beb699 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 22 Aug 2023 16:02:23 +0200 Subject: [PATCH 0403/1483] Enable use of the TestCase driver infr with instr warnings We do that by adding an optional tolerate_messages parameter to the TestCase constructor and passing it down to gnatcov instrument invocations. --- testsuite/SCOV/internals/driver.py | 14 ++++++++------ testsuite/SCOV/tc.py | 7 ++++++- 2 files changed, 14 insertions(+), 7 deletions(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 09a20fc7b..137910f0f 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -1301,7 +1301,8 @@ def mode_build(self): dump_trigger=self.dump_trigger, gprsw=instrument_gprsw, gpr_obj_dir=self.gpr_obj_dir, - out=out) + out=out, + tolerate_messages=self.testcase.tolerate_messages) # When exception propagation is not available, a test ending with an # unhandled exception goes straight to the last_chance_handler from @@ -1328,11 +1329,12 @@ def mode_build(self): # Standard output might contain warnings indicating instrumentation # issues. This should not happen, so simply fail as soon as the output # file is not empty. - thistest.fail_if( - os.path.getsize(out) > 0, - 'xcov instrument standard output not empty ({}):' - '\n--' - '\n{}'.format(out, contents_of(out))) + if not self.testcase.tolerate_messages: + thistest.fail_if( + os.path.getsize(out) > 0, + 'xcov instrument standard output not empty ({}):' + '\n--' + '\n{}'.format(out, contents_of(out))) # Now we can build, instructing gprbuild to fetch the instrumented # sources in their dedicated subdir: diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index ec3a7ea04..f8ece4bd4 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -123,11 +123,16 @@ def __drivers_from(self, cspec): # match this expression return [drv for drv in self.all_drivers if re.search(drv_expr, drv)] - def __init__(self, extradrivers="", extracargs="", category=CAT.auto): + def __init__(self, extradrivers="", extracargs="", category=CAT.auto, + tolerate_messages=None): # By default, these test cases expect no error from subprocesses (xrun, # xcov, etc.) self.expect_failures = False + # Pass tolerate_messages to gnatcov instrument invocations (see the doc + # for xcov_instrument). + self.tolerate_messages = tolerate_messages + # Step 1: Compute the list of drivers and consolidation specs # to exercise # ------------------------------------------------------------ From 84a94d1402320e1db424a933276c1c3557ff9b3b Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 11 Sep 2023 15:03:47 +0200 Subject: [PATCH 0404/1483] Do not allocate MC/DC bits for decision uninstrumented for MC/DC --- tools/gnatcov/instrument-common.adb | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 7fcf21fda..3e6212a55 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -206,6 +206,7 @@ package body Instrument.Common is if Coverage.MCDC_Coverage_Enabled and then Length (State_Variable) > 0 and then Path_Count > 0 + and then Path_Count < Get_Path_Count_Limit then Result.Path_Bits_Base := Unit_Bits.Last_Path_Bit + 1; Unit_Bits.Last_Path_Bit := From b652204f1f9493d8220c51af89cca5689ce9b5c9 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 11 Sep 2023 16:01:49 +0200 Subject: [PATCH 0405/1483] Enable C++ instrumentation by default --- testsuite/SUITE/tutils.py | 9 --------- tools/gnatcov/Makefile | 8 ++++---- tools/gnatcov/command_line.ads | 4 +--- tools/gnatcov/gnatcov_bits_specific.adb | 7 +------ 4 files changed, 6 insertions(+), 22 deletions(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 7f1e6594d..d76385f0b 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -735,15 +735,6 @@ def xcov(args, out=None, err=None, inp=None, env=None, register_failure=True, covcmd = args[0] covargs = args[1:] - # gnatcov testsuite exercises C/C++ instrumentation, which are not - # activated by default. - if ( - auto_languages - and not thistest.options.qualif_level - and covcmd == "instrument" - ): - covargs = ['--restricted-to-languages=Ada,C,C++'] + covargs - if thistest.options.all_warnings: covargs = ['--all-warnings'] + covargs diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index af148d462..6860289e2 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -177,19 +177,19 @@ ifdef INSTRUMENTED # use the version that was not instrumented as a main to compile # gnatcov32, running gnatcov32 will not dump execution traces. - gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov64 + gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov64 --c++-opts=$(CXXFLAGS) $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 \ --src-subdirs=gnatcov-instr - gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov32 + gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov32 --c++-opts=$(CXXFLAGS) $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov32 \ --src-subdirs=gnatcov-instr - gnatcov instrument -j0 -P gnatcov.gpr -XPART=driver + gnatcov instrument -j0 -P gnatcov.gpr -XPART=driver --c++-opts=$(CXXFLAGS) $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver \ --src-subdirs=gnatcov-instr - gnatcov instrument -j0 -P gnatcov.gpr -XPART=compiler + gnatcov instrument -j0 -P gnatcov.gpr -XPART=compiler --c++-opts=$(CXXFLAGS) $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=compiler \ --src-subdirs=gnatcov-instr else diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 4519a3ed8..57e3558c2 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -1277,9 +1277,7 @@ package Command_Line is Pattern => "[LANGUAGE|LIST|@LISTFILE]", Help => "Restrict the set of languages for instrumentation. Supports Ada, C" - & " and C++. As C++ support is still in beta state, the default is" - & " --restricted-to-languages=Ada,C. To enable C++, pass" - & " --restricted-to-languages=Ada,C,C++.", + & " and C++.", Commands => (Cmd_Setup | Cmd_Instrument_Project => True, others => False), diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 5a1ec80a3..c17e3ebe9 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -498,15 +498,10 @@ procedure GNATcov_Bits_Specific is -- just the default ones. if Args.String_List_Args (Opt_Restricted_To_Languages).Is_Empty then - - -- C++ instrumentation is a beta feature and not yet fully - -- functional. It will thus not be part of the languages enabled by - -- default. - Src_Enabled_Languages := (Ada_Language => True, C_Language => True, - CPP_Language => False); + CPP_Language => True); else for Arg of Args.String_List_Args (Opt_Restricted_To_Languages) loop Src_Enabled_Languages (To_Language (+Arg)) := True; From d3c532982b62038a397ed5d6b920eb06e706db04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Mon, 11 Sep 2023 15:17:59 +0200 Subject: [PATCH 0406/1483] Fix regressions for improved manual dump and add warning * Fix range-check failed regression in ada_manual_dump cause by accessing Main.Filename while creating the manual dump helper unit * Modify ada_manual_no_dump_in_root to account for more cases and different expectations while running gnatcov natively or cross-platform * Fix typo in test.opt of manual dump tests * Don't prevent creation of manual dump helper unit when no dump procedure call was found * Update documentation to highlight difference in source trace files creation between bin-file and base64-stdout dump config * Add warning for dump buffers indications in subproject stating they will only produce an accurate coverage analysis for the subprojects and the projects it depends on --- doc/gnatcov/src_traces.rst | 12 +++ testsuite/SCOV/minicheck.py | 2 +- .../tests/instr-cov/ada_manual_dump/test.opt | 2 +- .../tests/instr-cov/ada_manual_dump/test.py | 5 +- .../src-lib1/lib1.adb | 4 +- .../{ => src-lib1}/src-lib2/lib2.adb | 1 - .../{ => src-lib1}/src-lib2/lib2.ads | 0 .../src-lib1/src-lib3/lib3.adb | 8 -- .../src-lib1/src-lib3/lib3.ads | 3 - .../ada_manual_no_dump_in_root/src/main.adb | 9 --- .../ada_manual_no_dump_in_root/test.opt | 2 +- .../ada_manual_no_dump_in_root/test.py | 59 ++++++--------- .../tests/instr-cov/c_manual_dump/test.opt | 2 +- .../tests/instr-cov/c_manual_dump/test.py | 5 +- tools/gnatcov/instrument-c.adb | 5 +- tools/gnatcov/instrument-projects.adb | 73 +++++++++++++++++-- 16 files changed, 119 insertions(+), 73 deletions(-) rename testsuite/tests/instr-cov/ada_manual_no_dump_in_root/{ => src-lib1}/src-lib2/lib2.adb (76%) rename testsuite/tests/instr-cov/ada_manual_no_dump_in_root/{ => src-lib1}/src-lib2/lib2.ads (100%) delete mode 100644 testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.adb delete mode 100644 testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.ads diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 0234cdbd2..2cb74667b 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -288,6 +288,18 @@ at which point the source traces will be created during the execution of the program. Therefore, the pragma or comment should be placed at a location at which such a function call would be appropriate. +A dump procedure is only able to dump the buffers of the project tree which +root is the project it is called from. A dump procedure call done in a +subproject will result in a trace containing all code of projects higher in the +project tree marked as not covered. + +One source trace is dumped per call to the dump buffers procedure. For the +``bin-file`` dump configuration, each trace is written in a file which name +depends on the selected trace file naming scheme. For the ``base64-stdout`` +dump configuration the traces are sequentially dumped in the same output file, +from which the |gcv| command ``extrace-base64-trace`` will be able to produce a +source trace file. + .. _instr-tracename: Controlling trace file names diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 79241fa94..d7a1ae6b5 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -108,7 +108,7 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, :param None|list[str] exec_args: List of arguments to pass to the executable. This will only work for native configurations. :param bool auto_languages: See SUITE.tutils.xcov. - :param None|str manual_proj_name: when the dump trigger is manual, several + :param None|str manual_prj_name: when the dump trigger is manual, several traces files (one per project) can be emitted if there are dump buffers procedure calls in at least two distinct projects. This is the name of the project which trace we want to consider. diff --git a/testsuite/tests/instr-cov/ada_manual_dump/test.opt b/testsuite/tests/instr-cov/ada_manual_dump/test.opt index a322c0d34..da626d559 100644 --- a/testsuite/tests/instr-cov/ada_manual_dump/test.opt +++ b/testsuite/tests/instr-cov/ada_manual_dump/test.opt @@ -1 +1 @@ -!src-traces DEAD Checks a feature specific the instrumenter +!src-traces DEAD Checks a feature specific to the instrumenter diff --git a/testsuite/tests/instr-cov/ada_manual_dump/test.py b/testsuite/tests/instr-cov/ada_manual_dump/test.py index 7f098af4e..86eae8ef3 100644 --- a/testsuite/tests/instr-cov/ada_manual_dump/test.py +++ b/testsuite/tests/instr-cov/ada_manual_dump/test.py @@ -34,6 +34,8 @@ objdir="obj", deps=["lib1", "lib2"]) +instr_warning = (r"warning: Manual dump trigger indications were found in.*") + build_run_and_coverage( gprsw=GPRswitches(root_project=p, units=["lib1", "main"]), covlevel='stmt', @@ -41,7 +43,8 @@ extra_coverage_args=['-axcov', '--output-dir=xcov'], trace_mode='src', dump_trigger="manual", - manual_prj_name="gen") + manual_prj_name="gen", + tolerate_instrument_messages=instr_warning) # Check that gnatcov inserted the call to the dump buffers procedure in the # lib2.adb which is not a unit of interest diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.adb b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.adb index b9ef383b4..83adfaee4 100644 --- a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.adb +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.adb @@ -1,11 +1,11 @@ -with Lib3; +with Lib2; package body Lib1 is function Foo return Integer is Res : Integer := 1; begin - Res := Res + Lib3.Baz; + Res := Res + Lib2.Bar; pragma Annotate (Xcov, Dump_Buffers); return Res; end Foo; diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib2/lib2.adb b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib2/lib2.adb similarity index 76% rename from testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib2/lib2.adb rename to testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib2/lib2.adb index 326f4aa54..dac52ea6c 100644 --- a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib2/lib2.adb +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib2/lib2.adb @@ -3,7 +3,6 @@ package body Lib2 is is Res : constant Integer := 1; begin - pragma Annotate (Xcov, Dump_Buffers); return Res; end Bar; end Lib2; diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib2/lib2.ads b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib2/lib2.ads similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib2/lib2.ads rename to testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib2/lib2.ads diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.adb b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.adb deleted file mode 100644 index 57507a918..000000000 --- a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.adb +++ /dev/null @@ -1,8 +0,0 @@ -package body Lib3 is - function Baz return Integer - is - Res : constant Integer := 1; - begin - return Res; - end Baz; -end Lib3; diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.ads b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.ads deleted file mode 100644 index 3ce3ffa95..000000000 --- a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib3/lib3.ads +++ /dev/null @@ -1,3 +0,0 @@ -package Lib3 is - function Baz return Integer; -end Lib3; diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src/main.adb b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src/main.adb index 4c6e6543a..d52e99f7a 100644 --- a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src/main.adb +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src/main.adb @@ -1,7 +1,6 @@ pragma Ada_2012; with Lib1; -with Lib2; procedure Main is @@ -13,15 +12,7 @@ procedure Main is I : Integer := 1; begin - -- The only call that should not count as a violation when never executed - -- is that of the dump buffers procedure. - if 1 = I + 1 then - pragma Annotate (Xcov, Dump_Buffers); - I := I+ 1; - end if; - Increment (I); I := I + Lib1.Foo; - I := I + Lib2.Bar; Increment (I); end Main; diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.opt b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.opt index a322c0d34..da626d559 100644 --- a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.opt +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.opt @@ -1 +1 @@ -!src-traces DEAD Checks a feature specific the instrumenter +!src-traces DEAD Checks a feature specific to the instrumenter diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.py b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.py index 0a7ebb9e5..b400e7a85 100644 --- a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.py +++ b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.py @@ -15,59 +15,42 @@ tmp = Wdir('tmp_') -lib1_p = gprfor(mains=[], - prjid="lib1", - srcdirs="../src-lib1", - objdir="obj-lib1", - langs=["Ada"], - deps=["lib3"] - ) -lib2_p = gprfor(mains=[], - prjid="lib2", - srcdirs="../src-lib2", - objdir="obj-lib2", - langs=["Ada"], - ) +def make_lib_gpr(name, srcdirs, deps): + return gprfor(mains=[], + prjid=name, + srcdirs=srcdirs, + objdir="obj-" + name, + langs=["Ada"], + deps=deps) -lib2_p = gprfor(mains=[], - prjid="lib3", - srcdirs="../src-lib1/src-lib3", - objdir="obj-lib3", - langs=["Ada"], - ) + +lib1_p = make_lib_gpr("lib1", "../src-lib1", ["lib2"]) +lib2_p = make_lib_gpr("lib2", "../src-lib1/src-lib2", None) p = gprfor(mains=["main.adb"], srcdirs=["../src"], objdir="obj", - deps=["lib1", "lib2", "lib3"]) + deps=["lib1", "lib2"]) + +# Check that we get the expected coverage reports + +# Running gnatcov natively allows to have one source trace file per +# project. +instr_warning = (r"warning: Manual dump trigger indications were found in.*") build_run_and_coverage( - gprsw=GPRswitches(root_project=p, units=["lib1", "lib3"]), + gprsw=GPRswitches(root_project=p, units=["lib1", "lib2"]), covlevel='stmt', mains=['main'], extra_coverage_args=['-axcov', '--output-dir=xcov'], trace_mode='src', dump_trigger="manual", - manual_prj_name="lib1") - -# Check that gnatcov inserted the call to the dump buffers procedure in the -# lib2.adb which is not a unit of interest - - -def check_call(file): - thistest.fail_if_no_match("missing dump buffers procedure call", - "(\n|.)*GCVRT.DB_manual_lib2.Dump_Buffers;" - "(\n|.)*", - contents_of(file)) - - -check_call('obj-lib2/lib2-gnatcov-instr/lib2.adb') - -# Check that we get the expected coverage reports + manual_prj_name="lib1", + tolerate_instrument_messages=instr_warning) check_xcov_reports('xcov/*.xcov', { 'xcov/lib1.adb.xcov': {'+': {6, 8}, '-': {10}}, - 'xcov/lib3.adb.xcov': {'+': {4, 6}}}) + 'xcov/lib2.adb.xcov': {'+': {4, 6}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/c_manual_dump/test.opt b/testsuite/tests/instr-cov/c_manual_dump/test.opt index a322c0d34..da626d559 100644 --- a/testsuite/tests/instr-cov/c_manual_dump/test.opt +++ b/testsuite/tests/instr-cov/c_manual_dump/test.opt @@ -1 +1 @@ -!src-traces DEAD Checks a feature specific the instrumenter +!src-traces DEAD Checks a feature specific to the instrumenter diff --git a/testsuite/tests/instr-cov/c_manual_dump/test.py b/testsuite/tests/instr-cov/c_manual_dump/test.py index 7d01918d3..69dabfec3 100644 --- a/testsuite/tests/instr-cov/c_manual_dump/test.py +++ b/testsuite/tests/instr-cov/c_manual_dump/test.py @@ -34,9 +34,12 @@ gprsw = GPRswitches(root_project=src_gpr) +instr_warning = (r"warning: Manual dump trigger indications were found in.*") + build_run_and_coverage(gprsw=gprsw, covlevel="stmt", mains=["main"], extra_coverage_args=["-axcov"], dump_trigger="manual", - manual_prj_name="main") + manual_prj_name="main", + tolerate_instrument_messages=instr_warning) # Check that that the dump call indication was correctly replaced in the sub # project diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index a34be6058..e1c606e45 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3786,7 +3786,10 @@ package body Instrument.C is -- get the current execution time. File.Put_Line (Indent2 & "STR (""" - & Escape_Backslashes (+Main.Filename) & """),"); + & (if Dump_Config.Trigger = Manual + then +Prj.Prj_Name + else Escape_Backslashes (+Main.Filename)) + & """),"); File.Put_Line (Indent2 & "0,"); File.Put_Line (Indent2 & "STR ("""")"); diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 95200727c..f8b292f00 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -17,6 +17,7 @@ ------------------------------------------------------------------------------ with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Characters.Latin_1; use Ada.Characters.Latin_1; with Ada.Containers.Hashed_Maps; with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Containers.Indefinite_Ordered_Sets; @@ -823,6 +824,22 @@ is Instrumenter : in out Language_Instrumenter'Class; Manual_Dump_Inserted : in out Boolean) is + function Dump_Helper_Output_Dir_Exists + (Source : File_Info; Prj : Prj_Desc) + return Boolean + is (Ada.Directories.Exists + (GNATCOLL.VFS."+" (Source.Project.Object_Dir.Base_Dir_Name)) + and then Ada.Directories.Exists (+Prj.Output_Dir)); + -- True if the project's object directory and the instrumented sources + -- directory exist, False otherwise. + + package Non_Root_Src_Calls_Sets is new + Ada.Containers.Indefinite_Ordered_Sets (Element_Type => String); + + Non_Root_Src_Calls : Non_Root_Src_Calls_Sets.Set; + -- Set of names of source files containing a dump buffers indication + -- that belong to a non-root project. + begin for Source_C in Project_Sources.Iterate loop declare @@ -834,8 +851,13 @@ is Prj : constant Prj_Desc := Get_Or_Create_Project_Info (IC, Source.Project).Desc; + Is_Root_Prj : constant Boolean := + Prj.Prj_Name = Root_Project_Info.Project.Name; + Source_Name : constant String := + GNATCOLL.VFS."+" (Source.File.Full_Name); Helper_Unit : Unbounded_String; Contained_Indication : Boolean := False; + begin Instrumenter.Replace_Manual_Dump_Indication @@ -843,12 +865,27 @@ is Prj, Source); - if Contained_Indication - and then - Prj_Has_Manual_Helper.Find (Prj.Prj_Name) = No_Element + if Contained_Indication and then not Is_Root_Prj then - -- Only generate one manual dump helper unit per project + -- A call to the dump buffers procedure is only able to + -- dump the buffers of the project it is in and its + -- subprojects, meaning coverage data for all projects + -- higher in the project tree will be missing. Record + -- what file this call was in to warn the user later. + + Non_Root_Src_Calls.Include (Source_Name); + end if; + -- Only generate one manual dump helper unit per project. + -- At this point, if the project's object directory and the + -- instrumented sources directory do not exist there is no + -- need to emit the dump helper unit. There are no units of + -- interest or call to a manual dump procedure for this + -- project. + + if Prj_Has_Manual_Helper.Find (Prj.Prj_Name) = No_Element + and then Dump_Helper_Output_Dir_Exists (Source, Prj) + then Instrumenter.Emit_Dump_Helper_Unit_Manual (Helper_Unit, Dump_Config, Prj); @@ -888,7 +925,7 @@ is -- unit is already taken care of by the regular -- instrumentation process, so skip it. - if Prj.Prj_Name /= Root_Project_Info.Project.Name then + if not Is_Root_Prj then Instrumenter.Emit_Buffers_List_Unit (Instr_Units, Prj); end if; @@ -905,6 +942,32 @@ is end if; end; end loop; + + if not Non_Root_Src_Calls.Is_Empty then + -- For each manual dump call inserted in a file belonging to a + -- non-root project, warn the user the coverage data it will produce + -- will not cover the whole project tree. + + declare + All_File_Names : Unbounded_String := +""; + begin + for File_Name of Non_Root_Src_Calls loop + All_File_Names := + All_File_Names & (+File_Name) & Ada.Characters.Latin_1.LF; + end loop; + + Outputs.Warn ("Manual dump trigger indications were found in" + & " subprojects in the following files:" + & Ada.Characters.Latin_1.LF + & (+All_File_Names) + & "The coverage report built from the source traces" + & " they will produce will show all code from" + & " projects higher in the project tree as not" + & " covered. To get a full coverage analysis," + & " consider placing the manual dump buffers" + & " indication in the root project."); + end; + end if; end Insert_Manual_Dump_Trigger; --------------------- From c69b7343b62fd2417d03c5c36f885d62833daa35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 5 Sep 2023 15:04:55 +0200 Subject: [PATCH 0407/1483] Instrument expr. functions using declare expressions in Ada 2022 Until this change, all methods used to instrument expression functions had limitations that made them unsuitable for use in all scenarios, and some expression functions had no viable instrumentation scheme at all. Ada 2022 introduces declare expressions, which can be used to declare local objects inside an expression, which was precisely what was missing in order to fully support expression functions. This change adds a new instrumentation strategy for expression functions in Ada 2022 sources. --- doc/gnatcov/src_traces.rst | 46 +++--- .../instr-cov/expr_func/ada_2022/src/gen.ads | 21 +++ .../instr-cov/expr_func/ada_2022/src/prim.adb | 11 ++ .../instr-cov/expr_func/ada_2022/src/prim.ads | 25 +++ .../instr-cov/expr_func/ada_2022/src/rec.ads | 12 ++ .../expr_func/ada_2022/src/test_all.adb | 41 +++++ .../expr_func/ada_2022/src/test_true.adb | 33 ++++ .../instr-cov/expr_func/ada_2022/test.opt | 3 + .../instr-cov/expr_func/ada_2022/test.py | 22 +++ tools/gnatcov/gnatcov_bits_specific.adb | 16 +- tools/gnatcov/instrument-ada_unit.adb | 147 +++++++++++++++++- tools/gnatcov/instrument-ada_unit.ads | 7 + tools/gnatcov/switches.adb | 25 +++ tools/gnatcov/switches.ads | 13 +- 14 files changed, 382 insertions(+), 40 deletions(-) create mode 100644 testsuite/tests/instr-cov/expr_func/ada_2022/src/gen.ads create mode 100644 testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.adb create mode 100644 testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.ads create mode 100644 testsuite/tests/instr-cov/expr_func/ada_2022/src/rec.ads create mode 100644 testsuite/tests/instr-cov/expr_func/ada_2022/src/test_all.adb create mode 100644 testsuite/tests/instr-cov/expr_func/ada_2022/src/test_true.adb create mode 100644 testsuite/tests/instr-cov/expr_func/ada_2022/test.opt create mode 100644 testsuite/tests/instr-cov/expr_func/ada_2022/test.py diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 2cb74667b..5b3bf5634 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -374,19 +374,25 @@ Unsupported source constructs There are a few language constructs that |gcvins| doesn't support. The tool emits a warning when it encounters such cases and the corresponding code is not instrumented. Source coverage obligations are still emitted, and -the unsupported constructs will be reported in a separate +the unsupported constructs will be reported in a separate ``Undetermined_Coverage`` category, to differentiate them from actual coverage violations. The list of unsupported constructs is as follows: -* Generic expression functions, * Generic null procedures, +* Protected bodies entry guards when the ``Simple_Barriers`` restriction or + the ``Pure_Barriers`` one apply. + +Additionally, if the Ada language version in use, indicated to the tool by +either a ``pragma Ada_nnnn`` pragma in the sources or through the ``--ada`` +command line switch, is less or equal to Ada 2012, the following constructs are +also unsupported: + +* Generic expression functions, * Recursive expression functions which are primitives of some tagged type, * Expression functions which are primitives of their return type, when it is a tagged type. -* Protected bodies entry guards when the ``Simple_Barriers`` restriction or - the ``Pure_Barriers`` one apply. The simplest way to work around the limitation concerning expression functions is to turn them into regular functions, by giving them a proper body, @@ -394,31 +400,27 @@ containing a single return statement with the original expression. Otherwise it is possible to exempt those constructs (see :ref:`exemptions`) and/or perform a manual coverage analysis for these special cases. -Additionally, the MC/DC instrumentation of decisions with many conditions -may require more memory than available (during instrumentation and/or at -run-time) to enumerate the possible paths through the decision. To avoid this, -|gcv| will not instrument such decisions for MC/DC, emitting a warning in the -process, and the MC/DC coverage for each decision will be reported as -``Undetermined_Coverage`` state. Should the default limit not be satisfactory, -it can be tuned with the option :cmd-option:`--path-count-limit`. +The MC/DC instrumentation of decisions with many conditions may require more +memory than available (during instrumentation and/or at run-time) to enumerate +the possible paths through the decision. To avoid this, |gcv| will not +instrument such decisions for MC/DC, emitting a warning in the process, and the +MC/DC coverage for each decision will be reported as ``Undetermined_Coverage`` +state. Should the default limit not be satisfactory, it can be tuned with the +option :cmd-option:`--path-count-limit`. -Source-coverage obligations limitations +Other source-traces limitations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In Ada, variable or type declarations at the package level can yield elaboration code. Such code constructs are thus considered to have corresponding coverage obligations -In the case where a `pragma Preelaborate` or the `No_Elaboration_Code` -restriction affects the instrumented unit, variable / type declarations at the -package level are not considered as coverage obligations. In the former case, -elaboration code can still be emitted (in rare occurrences), but the pragma is -too restrictive to instrument such code constructs. In the latter case, no -elaboration code can be emitted so it is valid not to produce any coverage -obligation. - -Global source traces limitations -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In the case where a `pragma Preelaborate` restriction affects the instrumented +unit, variable and type declarations at the package level are not considered as +coverage obligations, although some elaboration code may still be emitted in +rare instances. Note that declarations within a unit constrained by a +``No_Elaboration_Code`` pragma don't produce coverage obligation either, which +is always correct as no executable code can be emitted by the compiler for them. There are also a few limitations concerning the source trace workflow as a whole: diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/src/gen.ads b/testsuite/tests/instr-cov/expr_func/ada_2022/src/gen.ads new file mode 100644 index 000000000..db5b17d1f --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/src/gen.ads @@ -0,0 +1,21 @@ +pragma Ada_2022; + +package Gen is + + generic + type Value_Type is private; + with function Weight (Self : Value_Type) return Natural; + function Weight_Sum (Left, Right : Value_Type) return Natural; + + generic + type Value_Type is private; + with function Weight (Self : Value_Type) return Natural; + function Both_Weights_Null (Left, Right : Value_Type) return Boolean; + + function Weight_Sum (Left, Right : Value_Type) return Natural is + (Weight (Left) + Weight (Right)); -- # expr_st + + function Both_Weights_Null (Left, Right : Value_Type) return Boolean is + (Weight (Left) = 0 and then Weight (Right) = 0); -- # expr_dc :o/e: + +end Gen; diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.adb b/testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.adb new file mode 100644 index 000000000..1a9b12bb1 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.adb @@ -0,0 +1,11 @@ +pragma Ada_2022; + +package body Prim is + + function Make_Internal (Cond : Boolean) return T is + (T'(X => (if Cond then 1 else 2))); -- # expr_dc :o/d: + + function Make_Internal (Cond : Boolean) return TT is + (TT'(X => 3, Y => 4)); -- # expr_st + +end Prim; diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.ads b/testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.ads new file mode 100644 index 000000000..f05ef1e10 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/src/prim.ads @@ -0,0 +1,25 @@ +pragma Ada_2022; + +package Prim is + type T is tagged record + X : Integer; + end record; + function And_Then (X : T; A, B : Boolean) return Boolean is + (A and then B); -- # expr_dc :o/e: + function Or_Else (X : T; A, B : Boolean) return Boolean is + (A or else B); -- # expr_dc :o/e: + + function Make_Internal (Cond : Boolean) return T; + + function Make (Cond : Boolean) return T is (Make_Internal (Cond)); -- # expr_st + + type TT is new T with record + Y : Integer; + end record; + + overriding function Make_Internal (Cond : Boolean) return TT; + + overriding function Make (Cond : Boolean) return TT is + (Make_Internal (Cond)); -- # expr_st + +end Prim; diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/src/rec.ads b/testsuite/tests/instr-cov/expr_func/ada_2022/src/rec.ads new file mode 100644 index 000000000..dce3ea8df --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/src/rec.ads @@ -0,0 +1,12 @@ +pragma Ada_2022; + +package Rec is + + type T is tagged record + X : Positive; + end record; + + function Fact (Input : T) return Positive is + (if Input.X = 1 then 1 else Input.X * Fact ((X => Input.X - 1))); -- # expr_dc :o/d: + +end Rec; diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/src/test_all.adb b/testsuite/tests/instr-cov/expr_func/ada_2022/src/test_all.adb new file mode 100644 index 000000000..78c2b7854 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/src/test_all.adb @@ -0,0 +1,41 @@ +pragma Ada_2012; + +with Gen; use Gen; +with Prim; use Prim; +with Rec; use Rec; + +with Support; use Support; + +procedure Test_All is + function Identity (X : Natural) return Natural is (X); + function Nat_Sum is new Gen.Weight_Sum + (Value_Type => Natural, Weight => Identity); + function Nat_Both_Null is new Gen.Both_Weights_Null + (Value_Type => Natural, Weight => Identity); + Val : Prim.T := (X => 0); + Res_T : Prim.T; + Res_TT : Prim.TT; +begin + -- Ensure we get full coverage + Assert (Nat_Sum (1, 1) = 2); + Assert (Nat_Both_Null (0, 0)); + Assert (not Nat_Both_Null (0, 1)); + Assert (not Nat_Both_Null (1, 0)); + Assert (Fact ((X => 3)) = 6); + Assert (And_Then (Val, True, True)); + Assert (not And_Then (Val, True, False)); + Assert (not And_Then (Val, False, True)); + Assert (not Or_Else (Val, False, False)); + Assert (Or_Else (Val, True, False)); + Assert (Or_Else (Val, False, True)); + Res_T := Make (True); + Assert (Res_T.X = 1); + Res_T := Make (False); + Assert (Res_T.X = 2); + Res_TT := Make (False); + Assert (Res_TT.X = 3 and then Res_TT.Y = 4); +end Test_All; + +--# rec.ads prim.ads prim.adb gen.ads +-- +-- /expr/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/src/test_true.adb b/testsuite/tests/instr-cov/expr_func/ada_2022/src/test_true.adb new file mode 100644 index 000000000..b5db57d44 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/src/test_true.adb @@ -0,0 +1,33 @@ +pragma Ada_2012; + +with Gen; use Gen; +with Prim; use Prim; +with Rec; use Rec; + +with Support; use Support; + +procedure Test_True is + function Identity (X : Natural) return Natural is (X); + function Nat_Sum is new Gen.Weight_Sum + (Value_Type => Natural, Weight => Identity); + function Nat_Both_Null is new Gen.Both_Weights_Null + (Value_Type => Natural, Weight => Identity); + Val : Prim.T := (X => 0); + Res_T : Prim.T; + Res_TT : Prim.TT; +begin + Assert (Nat_Sum (1, 1) = 2); + Assert (Nat_Both_Null (0, 0)); + Assert (Fact ((X => 1)) = 1); + Assert (Or_Else (Val, False, True)); + Assert (And_Then (Val, True, True)); + Res_T := Make (True); + Assert (Res_T.X = 1); + Res_TT := Make (False); + Assert (Res_TT.X = 3 and then Res_TT.Y = 4); +end Test_True; + +--# rec.ads prim.ads prim.adb gen.ads +-- +-- /expr_st/ l+ ## 0 +-- /expr_dc/ l! ## oF- diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/test.opt b/testsuite/tests/instr-cov/expr_func/ada_2022/test.opt new file mode 100644 index 000000000..087421040 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/test.opt @@ -0,0 +1,3 @@ +7.1.2 DEAD Ada 2022 not supported on old toolchains +5.04a1 DEAD Ada 2022 not supported on old toolchains +bin-traces DEAD Ada 2022 not supported on bin traces diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/test.py b/testsuite/tests/instr-cov/expr_func/ada_2022/test.py new file mode 100644 index 000000000..eda23b557 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/test.py @@ -0,0 +1,22 @@ +""" +Check that limitations concerning expression function instrumentation are lifted +when Ada 2022, and thus declare expressions are available. + +This test reflects the various limitations that are documented in the user +manual: +- generic expression functions (gen.ads) +- expression functions which are primitives of a tagged type, when that type is + the return type of the expression function. (prim.ads) +- Recursive expression functions which are a primitive of some type (rec.ads) + +The above constructs used to not be instrumented by gnatcov and resulted in +warnings and undetermined coverage items in the reports. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index c17e3ebe9..49ae7ca18 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1319,26 +1319,14 @@ begin Has_Matcher : Boolean; -- Matcher for the source files to ignore - Language_Version : Any_Language_Version; - pragma Unreferenced (Language_Version); - begin Create_Matcher (Ignored_Source_Files, Matcher, Has_Matcher); declare V : constant String := Value (Args, Opt_Ada, "2012"); begin - if V in "83" | "1983" then - Language_Version := Ada_83; - elsif V in "95" | "1995" then - Language_Version := Ada_95; - elsif V in "05" | "2005" then - Language_Version := Ada_2005; - elsif V in "12" | "2012" then - Language_Version := Ada_2012; - elsif V in "22" | "2022" then - Language_Version := Ada_2022; - else + if not Set_Language_Version (Global_Language_Version, From => V) + then Fatal_Error ("Bad Ada language version: " & V); end if; end; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 8a1838036..15c0a1a55 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -572,8 +572,9 @@ package body Instrument.Ada_Unit is -- instantiation of that generic subprogram. The statement witness and -- MC/DC state variable declarations are inserted in the generic body. -- - -- For expression functions, there are three instrumentation strategies, - -- depending on its spec and the context in which it is declared. + -- For expression functions, there are four instrumentation strategies, + -- depending on its spec, the context in which it is declared and the + -- language version used. -- -- In the first strategy (the "default" and most common one, which applies -- if not in one of the cases described bellow), we create a new augmented @@ -601,6 +602,11 @@ package body Instrument.Ada_Unit is -- for the second strategy. To circumvent this, all expression functions -- declared in a protected body are transformed into regular functions. -- + -- The last strategy only applies to Ada 2022 sources. In that case, a + -- declare expression is used to prepend a list of declarations prior to + -- the expression of the expression function, and is used to host the + -- statement witness call, and MC/DC state holders. + -- -- Also note that we wrap the generic instantiation in a nested package, -- so that it does not introduce unwanted additional primitive operations. -- We use a renaming-as-body of the instantiation to associate it with @@ -764,6 +770,24 @@ package body Instrument.Ada_Unit is -- return ([origin expression plus witness call using MCDC_State_2]); -- end Foo; -- + -- Expression function in Ada 2022 sources example (4th strategy) + -- ============================================================== + -- + -- In the following expression function, located in an Ada 2022 source: + -- + -- function Foo (Arg : Arg_Type) return Boolean is (Arg.X or else Arg.Y); + -- + -- the expression part is wrapped in a declare expression, in order to host + -- declarations for the stmt witness call and MC/DC state variable + -- declarations: + -- + -- function Foo (Arg : Arg_Type) return Boolean is + -- (declare + -- + -- + -- begin + -- [origin expression plus decision & MC/DC witness calls]); + -- -- -- The following record tracks several parse and rewriting nodes that are -- useful for both the instrumentation of null subprograms and expression @@ -3938,6 +3962,11 @@ package body Instrument.Ada_Unit is -- the expression function, the aspects need to be attached to the -- declaration and not the augmented expression function. + subtype Decl_Expr_Supported_Versions is Any_Language_Version range + Ada_2022 .. Any_Language_Version'Last; + -- Set of versions of the Ada language that support declare + -- expressions. + -- Start of processing for Traverse_Degenerate_Subprogram begin @@ -3958,6 +3987,102 @@ package body Instrument.Ada_Unit is UIC.Degenerate_Subprogram_Index := UIC.Degenerate_Subprogram_Index + 1; + -- Deal with the "easy" Ada 2022 and onwards case for expression + -- functions: + -- Simply nest the expression in a declare expression, and use that + -- to host the statement witness call, and local declarations. + + if UIC.Language_Version in Decl_Expr_Supported_Versions + and then Is_Expr_Function + then + declare + Expr_Func : constant Expr_Function := N.As_Expr_Function; + Decl_List : constant Node_Rewriting_Handle := + Create_Node (UIC.Rewriting_Context, Ada_Basic_Decl_List); + -- List of declarations to hold the statement witness call and + -- local MC/DC state holder variables. + + Decl_Expr : constant Node_Rewriting_Handle := + Create_Decl_Expr + (Handle => UIC.Rewriting_Context, + F_Decls => Decl_List, + F_Expr => Detach (Expr_Func.F_Expr)); + -- Declare expression to hold the above list + + Dummy_Decl : constant Node_Rewriting_Handle := + Create_From_Template + (UIC.Rewriting_Context, + "Dummy_Gnatcov_Decl : constant Boolean := False;", + (1 .. 0 => No_Node_Rewriting_Handle), + Rule => Object_Decl_Rule); + -- Dummy declaration to provide a node before which the + -- statement witness will be inserted. + + Local_Insertion_Info : aliased Insertion_Info := + (Method => Declaration, + RH_List => Decl_List, + Preelab => False, + Parent => null, + Index => 1, + others => <>); + -- Insertion info points to the newly created declaration list. + -- Index is 1 as we want to insert a witness call at the + -- beginning of the list. + + Local_Inserter : aliased Default_MCDC_State_Inserter := + (Local_Decls => Decl_List); + -- MC/DC state inserter points to the new decl list as well + + Saved_In_Decl_Expr : constant Boolean := UIC.In_Decl_Expr; + -- We are going to be inserting things as if we were + -- instrumenting a declare expression, save the flag to restore + -- it later. + + begin + -- Add the dummy declaration to the declaration list + + Append_Child (Decl_List, Dummy_Decl); + + -- Tie the declare expression to the expression function's + -- F_Expr field, taking care to wrap it in parentheses. + + Set_Child + (Handle (Expr_Func), + Member_Refs.Expr_Function_F_Expr, + Create_Paren_Expr (UIC.Rewriting_Context, Decl_Expr)); + + UIC.Current_Insertion_Info := + Local_Insertion_Info'Unchecked_Access; + UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; + + -- Flag that we are in a declare expression, in order to force + -- the MC/DC state holder to be declared constant + + UIC.In_Decl_Expr := True; + + -- The declaration list above does not exist in the analysis + -- tree as we just created it, so letting Set_Statement_Entry + -- decide where to insert the statement witness does not work. + -- Instead, force the witness to go in the newly declared list + -- using the Insertion_N param. + + Extend_Statement_Sequence + (UIC, + Expr_Func.F_Expr, + 'X', + Insertion_N => Dummy_Decl); + Process_Decisions_Defer (Expr_Func.F_Expr, 'X'); + Set_Statement_Entry; + + -- Restore context + + UIC.Current_Insertion_Info := Saved_Insertion_Info; + UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; + UIC.In_Decl_Expr := Saved_In_Decl_Expr; + return; + end; + end if; + if Is_Generic (UIC, N.As_Basic_Decl) then if Is_Expr_Function then Do_Not_Instrument := True; @@ -3992,7 +4117,7 @@ package body Instrument.Ada_Unit is -- override the original EF (because T2 may have different -- components compared to T). The instrumenter generates all -- the required functions, but since the names of the augmented - -- EFs are not necessarly consistent between the augmented EFs + -- EFs are not necessarily consistent between the augmented EFs -- for T and T2, we end up with missing some primitive -- overrides. -- @@ -5244,6 +5369,22 @@ package body Instrument.Ada_Unit is if Index (Pragma_Name, "ada_") = Pragma_Name'First then UIC.Language_Version_Pragma := To_Unbounded_Wide_Wide_String (Pragma_Name); + declare + Pragma_Str : constant String := + Image (N.As_Pragma_Node.F_Id.Text); + begin + if not + Set_Language_Version + (UIC.Language_Version, From => Pragma_Str) + then + Report + (UIC, + N, + "Unknown language pragma version: " + & Pragma_Str, + Kind => Warning); + end if; + end; end if; end; end if; diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index d11d41d7b..30abff00a 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -273,6 +273,13 @@ private Language_Version_Pragma : Unbounded_Wide_Wide_String; -- Language version configuration pragma for unit, if any + Language_Version : Any_Language_Version := + Switches.Global_Language_Version; + -- Most recent version of the language that can be used during + -- instrumentation of the unit. It is determined by the language + -- version pragma if present, otherwise it defaults to the value + -- obtained from the --ada switch. + CU : CU_Id := No_CU_Id; -- SCO identifier of the compilation unit being instrumented diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index fe1ed97f4..b738ae08a 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -19,6 +19,7 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Command_Line; with Ada.Exceptions; +with Ada.Strings.Fixed; with Outputs; use Outputs; with Project; use Project; @@ -656,4 +657,28 @@ package body Switches is return Result; end Common_Switches; + -------------------------- + -- Set_Language_Version -- + -------------------------- + + function Set_Language_Version + (V : in out Any_Language_Version; From : String) return Boolean + is + use Ada.Strings.Fixed; + begin + for Ada_Version in Any_Language_Version loop + declare + Year : constant String := Ada_Version'Image (5 .. 8); + begin + if Index (From, Year) /= 0 + or else Index (From, Year (7 .. 8)) /= 0 + then + V := Ada_Version; + return True; + end if; + end; + end loop; + return False; + end Set_Language_Version; + end Switches; diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 662454d7d..a5b5cda3f 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -225,7 +225,14 @@ package Switches is -- Instrumentation-related switches -- --------------------------------------- - type Any_Language_Version is (Ada_83, Ada_95, Ada_2005, Ada_2012, Ada_2022); + type Any_Language_Version is + (Ada_1983, Ada_1995, Ada_2005, Ada_2012, Ada_2022); + + function Set_Language_Version + (V : in out Any_Language_Version; From : String) return Boolean; + -- Try to find a language version substring in From. This will search for + -- the presence of any of the years defined in Any_Language_Version. If one + -- is found, update V accordingly and return True; return False otherwise. type Any_Dump_Trigger is (Manual, At_Exit, Ravenscar_Task_Termination, Main_End); @@ -294,4 +301,8 @@ package Switches is -- Cmd. This is used to propagate a set of switches to a gnatcov -- subprocess. + Global_Language_Version : Any_Language_Version; + -- Language version to be used in case no language version pragma is + -- present in the source being instrumented. + end Switches; From 9d359e5a24117c87612896436dbf0a1f19739f4f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 29 Jun 2023 18:01:39 +0200 Subject: [PATCH 0408/1483] Introduce subprograms of interest With this change, users now have the ability for finer-grained filtering - on a subprogram of interest basis. This changes actually provides more than that: filtering per scopes, which are identified by the : of their specification declaration point for Ada, if they have any (otherwise it is the body declaration point), and by the body declaration point for C / C++. The subprograms of interest filtering is applied after all of the units of interest filtering has been applied. This means that if the users passes --subprograms=:, it won't be in the coverage report. To implement this, we use the logic implemented to support scope metrics, and refactor it to use trees instead of ad-hoc data structures. --- testsuite/tests/subp_of_interest/src/main.adb | 7 + testsuite/tests/subp_of_interest/src/pkg.adb | 14 ++ testsuite/tests/subp_of_interest/src/pkg.ads | 6 + testsuite/tests/subp_of_interest/test.py | 117 +++++++++++ tools/gnatcov/annotations-cobertura.adb | 3 +- tools/gnatcov/annotations-dynamic_html.adb | 61 +++--- tools/gnatcov/annotations-html.adb | 1 + tools/gnatcov/annotations-report.adb | 2 +- tools/gnatcov/annotations-xcov.adb | 1 + tools/gnatcov/annotations-xml.adb | 82 +++++--- tools/gnatcov/annotations.adb | 39 ++-- tools/gnatcov/annotations.ads | 31 +-- tools/gnatcov/command_line.ads | 10 + tools/gnatcov/coverage-source.adb | 31 ++- tools/gnatcov/coverage-source.ads | 1 - tools/gnatcov/coverage.adb | 14 +- tools/gnatcov/coverage.ads | 14 +- tools/gnatcov/gnatcov_bits_specific.adb | 57 +++++ tools/gnatcov/instrument-ada_unit.adb | 135 ++++++------ tools/gnatcov/instrument-ada_unit.ads | 3 +- tools/gnatcov/instrument-c.adb | 157 ++++++++------ tools/gnatcov/instrument-c.ads | 11 +- tools/gnatcov/instrument-common.adb | 21 +- tools/gnatcov/instrument-common.ads | 7 +- tools/gnatcov/sc_obligations-bdd.adb | 2 - tools/gnatcov/sc_obligations-bdd.ads | 2 + tools/gnatcov/sc_obligations.adb | 196 +++++++++--------- tools/gnatcov/sc_obligations.ads | 151 ++++++++++---- tools/gnatcov/switches.ads | 4 + 29 files changed, 788 insertions(+), 392 deletions(-) create mode 100644 testsuite/tests/subp_of_interest/src/main.adb create mode 100644 testsuite/tests/subp_of_interest/src/pkg.adb create mode 100644 testsuite/tests/subp_of_interest/src/pkg.ads create mode 100644 testsuite/tests/subp_of_interest/test.py diff --git a/testsuite/tests/subp_of_interest/src/main.adb b/testsuite/tests/subp_of_interest/src/main.adb new file mode 100644 index 000000000..d83413451 --- /dev/null +++ b/testsuite/tests/subp_of_interest/src/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo (1); + Pkg.Bar; +end Main; diff --git a/testsuite/tests/subp_of_interest/src/pkg.adb b/testsuite/tests/subp_of_interest/src/pkg.adb new file mode 100644 index 000000000..d4971528c --- /dev/null +++ b/testsuite/tests/subp_of_interest/src/pkg.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + procedure Foo (I : Integer) is + begin + Put_Line ("Hello from Foo!"); + end Foo; + + procedure Bar is + begin + Put_Line ("Hello from Bar!"); + end Bar; + +end Pkg; diff --git a/testsuite/tests/subp_of_interest/src/pkg.ads b/testsuite/tests/subp_of_interest/src/pkg.ads new file mode 100644 index 000000000..fd7058eb9 --- /dev/null +++ b/testsuite/tests/subp_of_interest/src/pkg.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pkg is + procedure Foo (I : Integer) with Pre => I > 0; + procedure Bar; +end Pkg; diff --git a/testsuite/tests/subp_of_interest/test.py b/testsuite/tests/subp_of_interest/test.py new file mode 100644 index 000000000..235595cd1 --- /dev/null +++ b/testsuite/tests/subp_of_interest/test.py @@ -0,0 +1,117 @@ +""" +Check that the subprograms of interest mechanism works as expected, i.e. +produces the right coverage expectations for source traces, and the right error +message for binary traces. +""" + +import os +import os.path + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor(srcdirs=os.path.join("..", "src"), mains=["main.adb"]) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) + +# Produce a coverage report and a checkpoint with the subprogram switch. Check +# that the coverage report contains only coverage data for the specific +# subprogram for source traces. For binary traces, simply check that the +# gnatcov coverage invocation yields the expected warning. +os.mkdir("xcov_subp") +xcov( + cov_args + + [ + "--save-checkpoint", + "trace.ckpt", + "--subprograms", + f"{os.path.join('..', 'src', 'pkg.ads')}:4", + "--output-dir=xcov_subp", + ], + out="coverage.log", +) +if thistest.options.trace_mode == "bin": + thistest.fail_if_no_match( + "gnatcov coverage output", + "warning: Ignoring --subprograms switches as this is not supported with" + " binary traces.", + contents_of("coverage.log"), + ) +else: + check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": {}, + "pkg.adb.xcov": {"+": {6}}, + }, + "xcov_subp", + ) + + # Then check that the checkpoint contains only coverage data for the specific + # subprogram. To do this, produce a new coverage report from the checkpoint + # without using the --subprograms switch. + xcov( + cov_args[:-1] + + ["--checkpoint", "trace.ckpt", "--output-dir=xcov_no_subp"] + ) + check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": {"-": {5, 6}}, + "pkg.adb.xcov": {"+": {6}, "-": {11}}, + }, + "xcov_no_subp", + ) + + # Also check the warnings when the subprogram switch is ill-formed + + # Case 1: missing colon in the argument + xcov( + cov_args + ["--subprograms", "no-colon"], + out="xcov-wrong1.txt", + register_failure=False, + ) + thistest.fail_if_no_match( + what="unexpected coverage output", + regexp=r".*Wrong argument passed to --subprograms: .*", + actual=contents_of("xcov-wrong1.txt"), + ) + + # Case 2: line number is not a number + xcov( + cov_args + ["--subprograms", f"{os.path.join('..', 'src', 'pkg.ads')}:b",], + out="xcov-wrong2.txt", + register_failure=False, + ) + thistest.fail_if_no_match( + what="unexpected coverage output", + regexp=r".*Wrong argument passed to --subprograms: .*", + actual=contents_of("xcov-wrong2.txt"), + ) + + # Case 3: file does not exist + xcov( + cov_args + ["--subprograms", "dumb-file-name:4"], + out="xcov-wrong3.txt", + register_failure=False, + ) + thistest.fail_if_no_match( + what="unexpected coverage output", + regexp=r".*Error when parsing --subprograms argument dumb-file-name:4:" + r".*dumb-file-name does not exist", + actual=contents_of("xcov-wrong3.txt"), + ) + + + +thistest.result() diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb index 172d80a38..32d63bae6 100644 --- a/tools/gnatcov/annotations-cobertura.adb +++ b/tools/gnatcov/annotations-cobertura.adb @@ -253,7 +253,8 @@ package body Annotations.Cobertura is Pp.Need_Sources := False; - Annotations.Generate_Report (Pp, True, Subdir => "cobertura"); + Annotations.Generate_Report + (Pp, True, Context.Subps_Of_Interest, Subdir => "cobertura"); Free (Pp.Source_Prefix_Pattern); end Generate_Report; diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 3f30f6955..8c16aebf8 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -150,9 +150,10 @@ package body Annotations.Dynamic_Html is procedure Pretty_Print_End_File (Pp : in out Dynamic_Html); - procedure Pretty_Print_Scope_Entity - (Pp : in out Dynamic_Html; - Scope_Ent : Scope_Entity); + procedure Pretty_Print_Scope_Entities + (Pp : in out Dynamic_Html; + File : Source_File_Index; + Scope_Entities : Scope_Entities_Tree); procedure Pretty_Print_Start_Line (Pp : in out Dynamic_Html; @@ -294,8 +295,9 @@ package body Annotations.Dynamic_Html is begin Annotations.Generate_Report (Pp, - Show_Details => True, - Subdir => "html"); + Show_Details => True, + Subp_Of_Interest => Context.Subps_Of_Interest, + Subdir => "html"); end Generate_Report; ------------------------ @@ -516,15 +518,18 @@ package body Annotations.Dynamic_Html is Append (Pp.Source_List, Simplified); end Pretty_Print_End_File; - ------------------------------- - -- Pretty_Print_Scope_Entity -- - ------------------------------- + --------------------------------- + -- Pretty_Print_Scope_Entities -- + --------------------------------- - procedure Pretty_Print_Scope_Entity - (Pp : in out Dynamic_Html; - Scope_Ent : Scope_Entity) + procedure Pretty_Print_Scope_Entities + (Pp : in out Dynamic_Html; + File : Source_File_Index; + Scope_Entities : Scope_Entities_Tree) is - function To_JSON (Scope_Ent : Scope_Entity) return JSON_Value; + use Scope_Entities_Trees; + + function To_JSON (Cur : Cursor) return JSON_Value; -- Convert a scope entity to a JSON scoped metric: compute line and -- obligation statistics for the given scope and recursively for -- child scopes. Store the result as a JSON object, with the name and @@ -534,37 +539,41 @@ package body Annotations.Dynamic_Html is -- To_JSON -- ------------- - function To_JSON (Scope_Ent : Scope_Entity) return JSON_Value is + function To_JSON (Cur : Cursor) return JSON_Value + is + Scope_Ent : constant Scope_Entity := Element (Cur); + Child : Cursor := First_Child (Cur); + Scope_Metrics_JSON : constant JSON_Value := Create_Object; Children_Scope_Metrics_JSON : JSON_Array; - FI : constant File_Info_Access := - Get_File (First_Sloc (Scope_Ent.From).Source_File); - Line_Stats : constant Li_Stat_Array := + -- Representation of the scope metrics for the html format + + Line_Stats : constant Li_Stat_Array := Line_Metrics - (FI, + (Get_File (File), First_Sloc (Scope_Ent.From).L.Line, Last_Sloc (Scope_Ent.To).L.Line); - Ob_Stats : constant Ob_Stat_Array := + Ob_Stats : constant Ob_Stat_Array := Obligation_Metrics (Scope_Ent.From, Scope_Ent.To); begin Scope_Metrics_JSON.Set_Field ("scopeName", Scope_Ent.Name); Scope_Metrics_JSON.Set_Field ("scopeLine", Scope_Ent.Sloc.Line); Scope_Metrics_JSON.Set_Field ("stats", To_JSON (Line_Stats)); Scope_Metrics_JSON.Set_Field ("enAllStats", To_JSON (Ob_Stats)); - for Child_Scope_Ent of Scope_Ent.Children loop - Append - (Children_Scope_Metrics_JSON, - To_JSON (Child_Scope_Ent.all)); + while Has_Element (Child) loop + Append (Children_Scope_Metrics_JSON, To_JSON (Child)); + Child := Next_Sibling (Child); end loop; Scope_Metrics_JSON.Set_Field - ("children", - Create (Children_Scope_Metrics_JSON)); + ("children", Create (Children_Scope_Metrics_JSON)); return Scope_Metrics_JSON; end To_JSON; begin - Pp.Scope_Metrics := To_JSON (Scope_Ent); - end Pretty_Print_Scope_Entity; + for Cur in Scope_Entities.Iterate_Children (Scope_Entities.Root) loop + Pp.Scope_Metrics := To_JSON (Cur); + end loop; + end Pretty_Print_Scope_Entities; ----------------------------- -- Pretty_Print_Start_Line -- diff --git a/tools/gnatcov/annotations-html.adb b/tools/gnatcov/annotations-html.adb index 2eb037afc..b3c75182d 100644 --- a/tools/gnatcov/annotations-html.adb +++ b/tools/gnatcov/annotations-html.adb @@ -224,6 +224,7 @@ package body Annotations.Html is Annotations.Generate_Report (Pp, Show_Details, + Context.Subps_Of_Interest, Subdir => (if Show_Details then "shtml+" else "shtml")); end Generate_Report; diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index ad64771f2..6ac88d171 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -242,7 +242,7 @@ package body Annotations.Report is Open_Report_File (Final_Report_Name.all); end if; - Annotations.Generate_Report (Pp, True); + Annotations.Generate_Report (Pp, True, Context.Subps_Of_Interest); Close_Report_File; end Generate_Report; diff --git a/tools/gnatcov/annotations-xcov.adb b/tools/gnatcov/annotations-xcov.adb index 92700a6c1..6398929a5 100644 --- a/tools/gnatcov/annotations-xcov.adb +++ b/tools/gnatcov/annotations-xcov.adb @@ -88,6 +88,7 @@ package body Annotations.Xcov is Annotations.Generate_Report (Pp, Show_Details, + Context.Subps_Of_Interest, Subdir => (if Pp.Show_Details then "xcov+" else "xcov"), Clean_Pattern => "*.xcov"); end Generate_Report; diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index 12c1eff1d..7540daf1a 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -138,9 +138,10 @@ package body Annotations.Xml is procedure Pretty_Print_End_File (Pp : in out Xml_Pretty_Printer); - procedure Pretty_Print_Scope_Entity - (Pp : in out Xml_Pretty_Printer; - Scope_Ent : Scope_Entity); + procedure Pretty_Print_Scope_Entities + (Pp : in out Xml_Pretty_Printer; + File : Source_File_Index; + Scope_Entities : Scope_Entities_Tree); procedure Pretty_Print_Start_Line (Pp : in out Xml_Pretty_Printer; @@ -293,7 +294,8 @@ package body Annotations.Xml is Context => Context, others => <>); begin - Annotations.Generate_Report (Pp, True, Subdir => "xml"); + Annotations.Generate_Report + (Pp, True, Context.Subps_Of_Interest, Subdir => "xml"); end Generate_Report; ------- @@ -565,36 +567,54 @@ package body Annotations.Xml is Dest_Index); end Pretty_Print_Start_File; - ------------------------------- - -- Pretty_Print_Scope_Entity -- - ------------------------------- + --------------------------------- + -- Pretty_Print_Scope_Entities -- + --------------------------------- - procedure Pretty_Print_Scope_Entity - (Pp : in out Xml_Pretty_Printer; - Scope_Ent : Scope_Entity) + procedure Pretty_Print_Scope_Entities + (Pp : in out Xml_Pretty_Printer; + File : Source_File_Index; + Scope_Entities : Scope_Entities_Tree) is - FI : constant File_Info_Access := - Get_File (First_Sloc (Scope_Ent.From).Source_File); - begin - Pp.ST ("scope_metric", - A ("scope_name", Scope_Ent.Name) - & A ("scope_line", Img (Scope_Ent.Sloc.Line))); - Print_Coverage_Li_Stats - (Pp, - Line_Metrics - (FI, - First_Sloc (Scope_Ent.From).L.Line, - Last_Sloc (Scope_Ent.To).L.Line), - Dest_Compilation_Unit); - Print_Coverage_Ob_Stats - (Pp, - Obligation_Metrics (Scope_Ent.From, Scope_Ent.To), - Dest_Compilation_Unit); - for Child of Scope_Ent.Children loop - Pp.Pretty_Print_Scope_Entity (Child.all); + use Scope_Entities_Trees; + + procedure Pp_Scope_Entity (Cur : Cursor); + + --------------------- + -- Pp_Scope_Entity -- + --------------------- + + procedure Pp_Scope_Entity (Cur : Cursor) + is + Scope_Ent : constant Scope_Entity := Element (Cur); + Child : Cursor := First_Child (Cur); + begin + Pp.ST ("scope_metric", + A ("scope_name", Scope_Ent.Name) + & A ("scope_line", Img (Scope_Ent.Sloc.Line))); + Print_Coverage_Li_Stats + (Pp, + Line_Metrics + (Get_File (File), + First_Sloc (Scope_Ent.From).L.Line, + Last_Sloc (Scope_Ent.To).L.Line), + Dest_Compilation_Unit); + Print_Coverage_Ob_Stats + (Pp, + Obligation_Metrics (Scope_Ent.From, Scope_Ent.To), + Dest_Compilation_Unit); + while Has_Element (Child) loop + Pp_Scope_Entity (Child); + Child := Next_Sibling (Child); + end loop; + Pp.ET ("scope_metric"); + end Pp_Scope_Entity; + + begin + for Cur in Scope_Entities.Iterate_Children (Scope_Entities.Root) loop + Pp_Scope_Entity (Cur); end loop; - Pp.ET ("scope_metric"); - end Pretty_Print_Scope_Entity; + end Pretty_Print_Scope_Entities; ---------------------------------------- -- Pretty_Print_Start_Instruction_Set -- diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index cadb8641c..5790d883b 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -181,14 +181,8 @@ package body Annotations is return; end if; - declare - Scope_Ent : constant Scope_Entity_Acc := - Get_Scope_Entity (Comp_Unit (File_Index)); - begin - if Scope_Ent /= null and then Scope_Ent.all /= No_Scope_Entity then - Pretty_Print_Scope_Entity (Pp, Scope_Ent.all); - end if; - end; + Pretty_Print_Scope_Entities + (Pp, File_Index, Get_Scope_Entities (Comp_Unit (File_Index))); Iterate_On_Lines (FI, Process_One_Line'Access); Pretty_Print_End_File (Pp); end Disp_File_Line_State; @@ -384,10 +378,11 @@ package body Annotations is --------------------- procedure Generate_Report - (Pp : in out Pretty_Printer'Class; - Show_Details : Boolean; - Subdir : String := ""; - Clean_Pattern : String := No_Cleaning) + (Pp : in out Pretty_Printer'Class; + Show_Details : Boolean; + Subp_Of_Interest : Scope_Id_Set; + Subdir : String := ""; + Clean_Pattern : String := No_Cleaning) is use Coverage; @@ -406,9 +401,11 @@ package body Annotations is -- Compute_File_State -- ------------------------ - procedure Compute_File_State (File_Index : Source_File_Index) is - - FI : constant File_Info_Access := Get_File (File_Index); + procedure Compute_File_State (File_Index : Source_File_Index) + is + ST : Scope_Traversal_Type; + FI : constant File_Info_Access := + Get_File (File_Index); procedure Compute_Line_State (L : Positive); -- Given a source line located in FI's source file, at line L, @@ -422,6 +419,17 @@ package body Annotations is LI : constant Line_Info_Access := Get_Line (FI, L); S : Line_State; begin + -- Check that this is a SCO for a subprogram of interest + + if not Subp_Of_Interest.Is_Empty and then LI.SCOs /= null then + for SCO of LI.SCOs.all loop + Traverse_SCO (ST, SCO); + end loop; + if not Is_Active (ST, Subps_Of_Interest) then + return; + end if; + end if; + -- Compute state for each coverage objective if Object_Coverage_Enabled then @@ -457,6 +465,7 @@ package body Annotations is end if; Populate_Exemptions (File_Index); + ST := Scope_Traversal (Comp_Unit (File_Index)); Iterate_On_Lines (FI, Compute_Line_State'Access); -- Update file statistics for line L. Note that this can be done diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 7454f0180..9832e8745 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -193,9 +193,10 @@ private State : Line_State) is null; -- Let Pp print the condition whose id is SCO - procedure Pretty_Print_Scope_Entity - (Pp : in out Pretty_Printer; - Scope_Ent : Scope_Entity) is null; + procedure Pretty_Print_Scope_Entities + (Pp : in out Pretty_Printer; + File : Source_File_Index; + Scope_Entities : Scope_Entities_Tree) is null; -- Let Pp print the given body entity No_Cleaning : constant String := "DO NOT CLEAN"; @@ -206,17 +207,19 @@ private -- never need to clean a report dir with the above string as a pattern. procedure Generate_Report - (Pp : in out Pretty_Printer'Class; - Show_Details : Boolean; - Subdir : String := ""; - Clean_Pattern : String := No_Cleaning); - -- Let Pp generate the annotated sources. If Show_Details is False, only - -- a line state will be displayed. If Show_Details is True, a justification - -- is associated to this line state. If Subdir is not empty, this will be - -- subdirectory in which the report will be created if multiple reports are - -- requested. If Clean_Pattern is not No_Cleaning, all the files matching - -- Clean_Pattern in Output_Dir as well as in Output_Dir/Subdir will be - -- removed. + (Pp : in out Pretty_Printer'Class; + Show_Details : Boolean; + Subp_Of_Interest : Scope_Id_Set; + Subdir : String := ""; + Clean_Pattern : String := No_Cleaning); + -- Let Pp generate the annotated sources. If Show_Details is False, only a + -- line state will be displayed. If Show_Details is True, a justification + -- is associated to this line state. Subp_Of_Interest contains the list + -- of subprograms of interest, empty if no subprogram of interest was + -- specified. If Subdir is not empty, this will be subdirectory in which + -- the report will be created if multiple reports are requested. If + -- Clean_Pattern is not No_Cleaning, all the files matching Clean_Pattern + -- in Output_Dir as well as in Output_Dir/Subdir will be removed. function Aggregated_State (Info : Line_Info; diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 57e3558c2..94efd8da9 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -148,6 +148,7 @@ package Command_Line is Opt_Scos, Opt_Units, Opt_SID, + Opt_Subp_Of_Interest, Opt_Routines, Opt_Routines_List, Opt_Exec, @@ -1096,6 +1097,15 @@ package Command_Line is | Cmd_Instrument_Main => False, others => True), Internal => False), + Opt_Subp_Of_Interest => Create + (Long_Name => "--subprograms", + Pattern => ":", + Help => + "Restrict coverage analysis to specific subprograms designated by" + & " the specification source line for Ada, and by the body source" + & " for C/C++.", + Commands => (Cmd_Coverage => True, others => False), + Internal => False), Opt_Scenario_Var => Create (Short_Name => "-X", Pattern => "[NAME]=[VALUE]", diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 8408b895d..1448f1b65 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -1754,6 +1754,26 @@ package body Coverage.Source is when Unit_Separate => "separate"); end Part_Image; + ST : Scope_Traversal_Type; + + procedure Update_SCI_Wrapper + (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 + + procedure Update_SCI_Wrapper + (SCO : SCO_Id; + Tag : SC_Tag; + Process : access procedure (SCI : in out Source_Coverage_Info)) + is + begin + Traverse_SCO (ST, SCO); + if Is_Active (ST, Subps_Of_Interest) then + Update_SCI (SCO, Tag, Process); + end if; + end Update_SCI_Wrapper; + -- Start of processing for Compute_Source_Coverage begin @@ -1806,15 +1826,18 @@ package body Coverage.Source is BM := Bit_Maps (CU); + ST := Scope_Traversal (CU); for J in Stmt_Buffer'Range loop -- If bit is set, statement has been executed if Stmt_Buffer (J) then - Update_SCI (BM.Statement_Bits (J), No_SC_Tag, Set_Executed'Access); + Update_SCI_Wrapper + (BM.Statement_Bits (J), No_SC_Tag, Set_Executed'Access); end if; end loop; + ST := Scope_Traversal (CU); for J in Decision_Buffer'Range loop if Decision_Buffer (J) then declare @@ -1835,7 +1858,7 @@ package body Coverage.Source is end Set_Known_Outcome_Taken; begin - Update_SCI + Update_SCI_Wrapper (Outcome_Info.D_SCO, No_SC_Tag, Set_Known_Outcome_Taken'Access); @@ -1845,6 +1868,7 @@ package body Coverage.Source is end if; end loop; + ST := Scope_Traversal (CU); for J in MCDC_Buffer'Range loop if MCDC_Buffer (J) then declare @@ -1871,7 +1895,8 @@ package body Coverage.Source is end Add_Evaluation; begin - Update_SCI (MCDC_Info.D_SCO, No_SC_Tag, Add_Evaluation'Access); + Update_SCI_Wrapper + (MCDC_Info.D_SCO, No_SC_Tag, Add_Evaluation'Access); end; end if; end loop; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 38c2b903e..1bf7e7c21 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -25,7 +25,6 @@ with Instrument.Input_Traces; use Instrument.Input_Traces; with Traces; use Traces; with Traces_Names; use Traces_Names; with Traces_Lines; use Traces_Lines; -with SC_Obligations; use SC_Obligations; package Coverage.Source is diff --git a/tools/gnatcov/coverage.adb b/tools/gnatcov/coverage.adb index 533461c14..9c76eccb3 100644 --- a/tools/gnatcov/coverage.adb +++ b/tools/gnatcov/coverage.adb @@ -17,9 +17,11 @@ ------------------------------------------------------------------------------ with Ada.Command_Line; +with Ada.Containers; with Strings; use Strings; with Support_Files; use Support_Files; +with Switches; use Switches; with Version; use Version; package body Coverage is @@ -232,17 +234,19 @@ package body Coverage is use Ada.Command_Line; Command : Unbounded_String := - To_Unbounded_String (Support_Files.Gnatcov_Command_Name); + To_Unbounded_String (Support_Files.Gnatcov_Command_Name); + begin for J in 1 .. Argument_Count loop Append (Command, ' ' & Argument (J)); end loop; return Context' - (Timestamp => Clock, - Version => To_Unbounded_String (Xcov_Version), - Command => Command, - Levels => To_Unbounded_String (Coverage_Option_Value)); + (Timestamp => Clock, + Version => To_Unbounded_String (Xcov_Version), + Command => Command, + Levels => To_Unbounded_String (Coverage_Option_Value), + Subps_Of_Interest => Subps_Of_Interest); end Get_Context; --------------- diff --git a/tools/gnatcov/coverage.ads b/tools/gnatcov/coverage.ads index 1f08100b9..27ad8065c 100644 --- a/tools/gnatcov/coverage.ads +++ b/tools/gnatcov/coverage.ads @@ -28,6 +28,7 @@ with Ada.Containers.Ordered_Sets; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Coverage_Options; use Coverage_Options; +with SC_Obligations; use SC_Obligations; package Coverage is @@ -108,19 +109,24 @@ package Coverage is Timestamp : Time; -- Timestamp of report generation - Version : Unbounded_String; + Version : Unbounded_String; -- Gnatcov version - Command : Unbounded_String; + Command : Unbounded_String; -- Gnatcov command line - Levels : Unbounded_String; + Levels : Unbounded_String; -- Coverage option for enabled coverage levels + + Subps_Of_Interest : Scope_Id_Set; + -- List of subprogram of interest. If empty, consider that all of + -- the subprograms are of interest. end record; type Context_Access is access all Context; function Get_Context return Context; - -- Return the description of the current coverage assessment context + -- Return the description of the current coverage assessment context. + -- Note: this must be called after the files table has been filled. function To_String (C : Context) return String; function From_String (S : String) return Context; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 49ae7ca18..745082afa 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -20,6 +20,8 @@ with Ada.Containers; use Ada.Containers; with Ada.Directories; use Ada.Directories; with Ada.Exceptions; with Ada.IO_Exceptions; +with Ada.Strings.Fixed; +with Ada.Strings.Maps; with Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; @@ -109,6 +111,7 @@ procedure GNATcov_Bits_Specific is Compiler_Drivers : Inputs.Inputs_Type; Source_Rebase_Inputs : Inputs.Inputs_Type; Source_Search_Inputs : Inputs.Inputs_Type; + Subprograms_Inputs : Inputs.Inputs_Type; Text_Start : Pc_Type := 0; Output : String_Access := null; Tag : String_Access := null; @@ -312,6 +315,15 @@ procedure GNATcov_Bits_Specific is Inputs.Iterate (ALIs_Inputs, ALI_Files.Load_ALI'Access); end if; + + -- If subprograms of interest were passed warn the user that they will + -- be ignored + + if not Args.String_List_Args (Opt_Subp_Of_Interest).Is_Empty then + Warn + ("Ignoring --subprograms switches as this is not supported with" + & " binary traces."); + end if; end Load_All_ALIs; ------------------- @@ -329,6 +341,9 @@ procedure GNATcov_Bits_Specific is procedure SID_Load_Wrapper (Filename : String); -- Wrapper for SID_Load to include the ignored source file regexp + procedure Process_Subp_Input (Subp_Input : String); + -- Parse a value passed to --subprograms + ------------------ -- Add_SID_File -- ------------------ @@ -348,6 +363,43 @@ procedure GNATcov_Bits_Specific is (Filename, (if Has_Matcher then Matcher'Access else null)); end SID_Load_Wrapper; + ------------------------ + -- Process_Subp_Input -- + ------------------------ + + procedure Process_Subp_Input (Subp_Input : String) + is + Colon_Index : constant Natural := + Ada.Strings.Fixed.Index (Subp_Input, Ada.Strings.Maps.To_Set (':')); + Filename : constant String := + Subp_Input (Subp_Input'First .. Colon_Index - 1); + begin + if Colon_Index = 0 then + raise Constraint_Error; + end if; + if not Exists (Filename) then + Outputs.Fatal_Error + ("Error when parsing --subprograms argument " + & Subp_Input & ": file " & Filename & " does not exist"); + end if; + Subps_Of_Interest.Include + (Scope_Entity_Identifier' + (Decl_SFI => + Get_Index_From_Full_Name + (Full_Name (Filename), Source_File), + Decl_Line => + Natural'Value + (Subp_Input (Colon_Index + 1 .. Subp_Input'Last)))); + + exception + -- Deal gracefully with parsing errors + + when Constraint_Error => + Outputs.Fatal_Error + ("Wrong argument passed to --subprograms: " + & "expecting : but got " & Subp_Input); + end Process_Subp_Input; + -- Start of processing for Load_All_SIDs begin @@ -368,6 +420,11 @@ procedure GNATcov_Bits_Specific is Create_Matcher (Ignored_Source_Files, Matcher, Has_Matcher); Inputs.Iterate (SID_Inputs, SID_Load_Wrapper'Access); + + -- Parse the listed subprograms of interest + + Copy_Arg_List (Opt_Subp_Of_Interest, Subprograms_Inputs); + Iterate (Subprograms_Inputs, Process_Subp_Input'Access); end Load_All_SIDs; ----------------------- diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 15c0a1a55..f7279aabc 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1082,17 +1082,16 @@ package body Instrument.Ada_Unit is -------------------------------- procedure Enter_Scope - (UIC : in out Ada_Unit_Inst_Context; - Scope_Name : Text_Type; - Sloc : Source_Location); + (UIC : in out Ada_Unit_Inst_Context; + Sloc : Source_Location; + Decl : Basic_Decl); -- Enter a scope. This must be completed with a call to the function -- Exit_Scope, defined below. Scope_Name is the name of the scope, which -- is defined at location Sloc. Assume that the scope first SCO is the next -- generated SCO (SCOs.SCO_Table.Last + 1). Update UIC.Current_Scope_Entity -- to the created entity. - procedure Exit_Scope (UIC : in out Ada_Unit_Inst_Context) - with Pre => UIC.Current_Scope_Entity /= null; + procedure Exit_Scope (UIC : in out Ada_Unit_Inst_Context); -- Exit the current scope, updating UIC.Current_Scope_Entity to -- UIC.Current_Scope_Entity.Parent, if any. Assume that the last generated -- SCO (SCOs.SCO_Table.Last) is the last SCO for the current scope. @@ -2825,7 +2824,7 @@ package body Instrument.Ada_Unit is | Ada_Accept_Stmt_With_Stmts | Ada_Entry_Body => - -- A return statment may only appear within a callable + -- A return statement may only appear within a callable -- construct (RM 6.5 (4/2)), which are either subprogram -- bodies, entry bodies or accept statements (RM 6.2)). As -- Subp is a Subp_Body if we encounter an accept statement @@ -4450,19 +4449,20 @@ package body Instrument.Ada_Unit is Process_Decisions_Defer (N_Spec.F_Subp_Params, 'X'); + Enter_Scope + (UIC => UIC, + Sloc => Sloc (N), + Decl => N); + -- Nothing else to do except for the case of degenerate subprograms -- (null procedures and expression functions). if N.Kind in Ada_Null_Subp_Decl then Traverse_Degenerate_Subprogram (N, N_Spec); elsif N.Kind in Ada_Expr_Function then - Enter_Scope - (UIC => UIC, - Scope_Name => N.As_Expr_Function.F_Subp_Spec.F_Subp_Name.Text, - Sloc => Sloc (N)); Traverse_Degenerate_Subprogram (N, N_Spec); - Exit_Scope (UIC); end if; + Exit_Scope (UIC); end Traverse_Subp_Decl_Or_Stub; ------------------ @@ -5151,10 +5151,9 @@ package body Instrument.Ada_Unit is => Set_Statement_Entry; Enter_Scope - (UIC => UIC, - Scope_Name => - N.As_Basic_Decl.P_Defining_Name.F_Name.Text, - Sloc => Sloc (N)); + (UIC => UIC, + Sloc => Sloc (N), + Decl => N.As_Basic_Decl); Extend_Statement_Sequence (UIC, N, (if N.Kind in Ada_Generic_Instantiation then 'i' else 'r')); @@ -5474,9 +5473,9 @@ package body Instrument.Ada_Unit is begin UIC.Ghost_Code := Safe_Is_Ghost (N); Enter_Scope - (UIC => UIC, - Scope_Name => N.As_Package_Body.F_Package_Name.Text, - Sloc => Sloc (N)); + (UIC => UIC, + Sloc => Sloc (N), + Decl => N.P_Previous_Part_For_Decl); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; Traverse_Declarations_Or_Statements @@ -5504,9 +5503,9 @@ package body Instrument.Ada_Unit is begin UIC.Ghost_Code := Safe_Is_Ghost (N); Enter_Scope - (UIC => UIC, - Scope_Name => N.F_Package_Name.Text, - Sloc => Sloc (N)); + (UIC => UIC, + Sloc => Sloc (N), + Decl => N.As_Basic_Decl); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; Traverse_Declarations_Or_Statements @@ -5604,14 +5603,12 @@ package body Instrument.Ada_Unit is (UIC : in out Ada_Unit_Inst_Context; N : Ada_Node) is - Decls : Declarative_Part; - HSS : Handled_Stmts; + Decls : Declarative_Part; + HSS : Handled_Stmts; Saved_MCDC_State_Inserter : constant Any_MCDC_State_Inserter := UIC.MCDC_State_Inserter; Local_Inserter : aliased Default_MCDC_State_Inserter; - - Body_Name : Defining_Name; begin case Kind (N) is when Ada_Subp_Body => @@ -5620,7 +5617,6 @@ package body Instrument.Ada_Unit is begin Decls := SBN.F_Decls; HSS := SBN.F_Stmts; - Body_Name := N.As_Subp_Body.F_Subp_Spec.F_Subp_Name; end; when Ada_Task_Body => @@ -5629,7 +5625,6 @@ package body Instrument.Ada_Unit is begin Decls := TBN.F_Decls; HSS := TBN.F_Stmts; - Body_Name := N.As_Task_Body.F_Name; end; when Ada_Entry_Body => @@ -5638,17 +5633,24 @@ package body Instrument.Ada_Unit is begin Decls := EBN.F_Decls; HSS := EBN.F_Stmts; - Body_Name := N.As_Entry_Body.F_Entry_Name; end; when others => raise Program_Error; end case; - Enter_Scope - (UIC => UIC, - Scope_Name => Body_Name.Text, - Sloc => Sloc (N)); + declare + Previous_Part : constant Basic_Decl := N.As_Body_Node.P_Previous_Part; + Decl : constant Basic_Decl := + (if Previous_Part.Is_Null + then N.As_Body_Node.P_Subp_Spec_Or_Null.P_Parent_Basic_Decl + else Previous_Part); + begin + Enter_Scope + (UIC => UIC, + Sloc => Sloc (N), + Decl => Decl); + end; Local_Inserter.Local_Decls := Handle (Decls.F_Decls); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; @@ -6833,23 +6835,34 @@ package body Instrument.Ada_Unit is ----------------- procedure Enter_Scope - (UIC : in out Ada_Unit_Inst_Context; - Scope_Name : Text_Type; - Sloc : Source_Location) + (UIC : in out Ada_Unit_Inst_Context; + Sloc : Source_Location; + Decl : Basic_Decl) is - New_Scope_Ent : constant Scope_Entity_Acc := new Scope_Entity' - (From => SCO_Id (SCOs.SCO_Table.Last + 1), - To => No_SCO_Id, - Name => +Langkit_Support.Text.To_UTF8 (Scope_Name), - Sloc => (Line => Natural (Sloc.Line), - Column => Natural (Sloc.Column)), - Children => Scope_Entities_Vectors.Empty_Vector, - Parent => UIC.Current_Scope_Entity); + Decl_SFI : constant Source_File_Index := + Get_Index_From_Generic_Name + (Decl.Unit.Get_Filename, + Kind => Files_Table.Source_File, + Indexed_Simple_Name => True); + New_Scope_Ent : constant Scope_Entity := + (From => SCO_Id (SCOs.SCO_Table.Last + 1), + To => No_SCO_Id, + Name => + +Langkit_Support.Text.To_UTF8 (Decl.P_Defining_Name.F_Name.Text), + Sloc => + (Line => Natural (Sloc.Line), + Column => Natural (Sloc.Column)), + Identifier => + (Decl_SFI => Decl_SFI, + Decl_Line => Natural (Decl.Sloc_Range.Start_Line))); + Inserted : Scope_Entities_Trees.Cursor; begin - if UIC.Current_Scope_Entity /= null then - UIC.Current_Scope_Entity.Children.Append (New_Scope_Ent); - end if; - UIC.Current_Scope_Entity := New_Scope_Ent; + UIC.Scope_Entities.Insert_Child + (Parent => UIC.Current_Scope_Entity, + Before => Scope_Entities_Trees.No_Element, + New_Item => New_Scope_Ent, + Position => Inserted); + UIC.Current_Scope_Entity := Inserted; end Enter_Scope; ---------------- @@ -6858,10 +6871,12 @@ package body Instrument.Ada_Unit is procedure Exit_Scope (UIC : in out Ada_Unit_Inst_Context) is - Parent : constant Scope_Entity_Acc := UIC.Current_Scope_Entity.Parent; + use Scope_Entities_Trees; + Parent_Scope : constant Cursor := Parent (UIC.Current_Scope_Entity); -- Latch the parent value before UIC.Current_Scope_Entity is freed - Scope : Scope_Entity_Acc renames UIC.Current_Scope_Entity; + Scope : constant Reference_Type := + UIC.Scope_Entities.Reference (UIC.Current_Scope_Entity); begin -- Update the last SCO for this scope entity @@ -6871,18 +6886,13 @@ package body Instrument.Ada_Unit is -- only subprogram declarations for instance), discard it. if Scope.To < Scope.From then - if Parent /= null then - Parent.Children.Delete_Last; - end if; - Free (Scope); + UIC.Scope_Entities.Delete_Leaf (UIC.Current_Scope_Entity); end if; -- If this is not the top-level scope (we want to keep its reference -- after having traversed the AST), go up the scope tree. - if Parent /= null then - Scope := Parent; - end if; + UIC.Current_Scope_Entity := Parent_Scope; end Exit_Scope; --------------------- @@ -8208,6 +8218,7 @@ package body Instrument.Ada_Unit is -- we can insert witness calls (which are not preelaborable). UIC.Root_Unit := Root_Analysis_Unit.Root.As_Compilation_Unit; + UIC.Current_Scope_Entity := UIC.Scope_Entities.Root; CU_Name.Part := (case UIC.Root_Unit.P_Unit_Kind is @@ -8238,7 +8249,8 @@ package body Instrument.Ada_Unit is -- file. UIC.Annotations.Clear; - UIC.Current_Scope_Entity := null; + UIC.Scope_Entities := Scope_Entities_Trees.Empty_Tree; + UIC.Current_Scope_Entity := UIC.Scope_Entities.Root; UIC.Degenerate_Subprogram_Index := 0; UIC.Source_Decisions := Source_Decision_Vectors.Empty; UIC.Source_Conditions := Source_Condition_Vectors.Empty; @@ -8425,13 +8437,8 @@ package body Instrument.Ada_Unit is -- Remap low level SCOS in Scope_Entity records to high-level SCOs. -- See the comment for Scope_Entity.From/To. - if UIC.Current_Scope_Entity /= null then - - -- Iterate through the package level body entities - - Remap_Scope_Entity (UIC.Current_Scope_Entity, SCO_Map); - Set_Scope_Entity (UIC.CU, UIC.Current_Scope_Entity); - end if; + Remap_Scope_Entities (UIC.Scope_Entities, SCO_Map); + Set_Scope_Entities (UIC.CU, UIC.Scope_Entities); end; -- Emit the instrumented source file diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 30abff00a..4c7a72a6a 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -337,7 +337,8 @@ private -- Used when the SPARK compatibility mode is enabled, to insert -- non-volatile witness result variables to be ghost compliant. - Current_Scope_Entity : Scope_Entity_Acc := null; + Scope_Entities : Scope_Entities_Tree; + Current_Scope_Entity : Scope_Entities_Trees.Cursor; -- Information about the name, sloc, SCO range and children scopes of -- the current scope entity. This is modified when entering a scope -- (updated to the current scope), and when leaving it (updated to diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index e1c606e45..b85b0df07 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -142,15 +142,14 @@ package body Instrument.C is overriding procedure Exit_Scope (Pass : Instrument_Pass_Kind; - UIC : in out C_Unit_Inst_Context'Class) - with Pre => UIC.Scopes.Contains (UIC.Current_File_Scope); + UIC : in out C_Unit_Inst_Context'Class); -- Close the current scope, removing the current scope of the current file -- from UIC.Scopes if it does not contain SCOs. Assume that the last -- generated SCO (SCOs.SCO_Table.Last) is the last SCO for the current -- scope. procedure Remap_Scopes - (Scopes : Scopes_In_Files_Map.Map; + (Scopes : in out Scopes_In_Files_Map.Map; SCO_Map : LL_HL_SCO_Map); -- Convert low level SCOs in each scope for each file to high-level SCOs -- using the mapping in SCO_Map. Set the file's SCO range to cover all of @@ -496,6 +495,10 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context'Class; N : Cursor_T) is + Inserted : Boolean; + + File_Scope_Position : Scopes_In_Files_Map.Cursor; + procedure Enter_File_Scope (UIC : in out C_Unit_Inst_Context'Class; SFI : Source_File_Index) @@ -512,20 +515,40 @@ package body Instrument.C is SFI : Source_File_Index) is begin if not UIC.Scopes.Contains (SFI) then + + -- Add a new entry to the file scopes map + + UIC.Scopes.Insert + (SFI, + File_Scope_Type'(others => <>), + Position => File_Scope_Position, + Inserted => Inserted); + declare - New_Scope_Ent : constant Scope_Entity_Acc := new Scope_Entity' - (From => SCO_Id (SCOs.SCO_Table.Last + 1), - To => No_SCO_Id, - Name => +Get_Simple_Name (SFI), - Sloc => (Line => 0, Column => 0), - Children => Scope_Entities_Vectors.Empty_Vector, - Parent => null); + File_Scope : constant Scopes_In_Files_Map.Reference_Type := + UIC.Scopes.Reference (File_Scope_Position); + New_Scope_Ent : constant Scope_Entity := + (From => SCO_Id (SCOs.SCO_Table.Last + 1), + To => No_SCO_Id, + Name => +Get_Simple_Name (SFI), + Sloc => (Line => 0, Column => 0), + Identifier => (Decl_SFI => SFI, Decl_Line => 0)); + + Scope_Entity_Position : Scope_Entities_Trees.Cursor; begin - UIC.Scopes.Insert (SFI, New_Scope_Ent); + File_Scope.Scope_Entities.Insert_Child + (Parent => File_Scope.Scope_Entities.Root, + Before => Scope_Entities_Trees.No_Element, + New_Item => New_Scope_Ent, + Position => Scope_Entity_Position); + File_Scope.Current_Scope_Entity := Scope_Entity_Position; + File_Scope.File_Scope_Entity := Scope_Entity_Position; end; + else + File_Scope_Position := UIC.Scopes.Find (SFI); end if; - UIC.Current_File_Scope := SFI; + UIC.Current_File_Scope := File_Scope_Position; end Enter_File_Scope; Sloc : constant Source_Location := Start_Sloc (N); @@ -544,22 +567,28 @@ package body Instrument.C is declare C : constant Scopes_In_Files_Map.Cursor := UIC.Scopes.Find (File); - Current_Scope : constant Scope_Entity_Acc := - Scopes_In_Files_Map.Element (C); - New_Scope_Ent : constant Scope_Entity_Acc := new Scope_Entity' - (From => SCO_Id (SCOs.SCO_Table.Last + 1), - To => No_SCO_Id, - Name => +Get_Decl_Name_Str (N), - Sloc => Sloc.L, - Children => Scope_Entities_Vectors.Empty_Vector, - Parent => Current_Scope); + File_Scope : constant Scopes_In_Files_Map.Reference_Type := + UIC.Scopes.Reference (C); + New_Scope_Ent : constant Scope_Entity := + (From => SCO_Id (SCOs.SCO_Table.Last + 1), + To => No_SCO_Id, + Name => +Get_Decl_Name_Str (N), + Sloc => Sloc.L, + Identifier => (Decl_SFI => File, Decl_Line => Sloc.L.Line)); + Inserted : Scope_Entities_Trees.Cursor; begin -- Add New_Scope_Ent to the children of the last open scope in the -- file. - Current_Scope.Children.Append (New_Scope_Ent); - -- Set New_Scope_Ent as the current open scope for the file. - UIC.Scopes.Replace_Element (C, New_Scope_Ent); + File_Scope.Scope_Entities.Insert_Child + (Parent => File_Scope.Current_Scope_Entity, + Before => Scope_Entities_Trees.No_Element, + New_Item => New_Scope_Ent, + Position => Inserted); + + -- Make the current scope entity point to the right one + + File_Scope.Current_Scope_Entity := Inserted; end; end Enter_Scope; @@ -571,44 +600,31 @@ package body Instrument.C is (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class) is - C : Scopes_In_Files_Map.Cursor := - UIC.Scopes.Find (UIC.Current_File_Scope); - Scope : Scope_Entity_Acc := Scopes_In_Files_Map.Element (C); + File_Scope_Ref : constant Scopes_In_Files_Map.Reference_Type := + UIC.Scopes.Reference (UIC.Current_File_Scope); + Scope_Entity_Ref : constant Scope_Entities_Trees.Reference_Type := + File_Scope_Ref.Scope_Entities.Reference + (File_Scope_Ref.Current_Scope_Entity); + Parent : constant Scope_Entities_Trees.Cursor := + Scope_Entities_Trees.Parent (File_Scope_Ref.Current_Scope_Entity); begin - -- If the scope associated to the current file is that of the file (no - -- parent), no scope is currently open in it. Then the scope that needs - -- closing is the current one of the file being instrumented. - - if Scope.Parent = null then - UIC.Current_File_Scope := UIC.SFI; - C := UIC.Scopes.Find (UIC.SFI); - Scope := Scopes_In_Files_Map.Element (C); - end if; - - declare - Parent : constant Scope_Entity_Acc := Scope.Parent; - begin - -- Update the last SCO for this scope entity + Scope_Entity_Ref.To := SCO_Id (SCOs.SCO_Table.Last); - Scope.To := SCO_Id (SCOs.SCO_Table.Last); + -- Discard the scope entity if it has no associated SCOs - -- If the scope has no SCO, discard it + if Scope_Entity_Ref.To < Scope_Entity_Ref.From then + File_Scope_Ref.Scope_Entities.Delete_Leaf + (File_Scope_Ref.Current_Scope_Entity); + else + -- Update the last SCO for the file scope - if Scope.To < Scope.From then - if Parent /= null then - Parent.Children.Delete_Last; - end if; - Free (Scope); - end if; + File_Scope_Ref.Scope_Entities.Reference + (File_Scope_Ref.File_Scope_Entity).To := Scope_Entity_Ref.To; + end if; - -- If this is not a top-level file scope (we want to keep its - -- reference after having traversed the AST), go up the scope tree - -- of the current file. + -- Go back to the parent scope entity - if Parent /= null then - UIC.Scopes.Replace_Element (C, Parent); - end if; - end; + File_Scope_Ref.Current_Scope_Entity := Parent; end Exit_Scope; ------------------ @@ -616,18 +632,24 @@ package body Instrument.C is ------------------ procedure Remap_Scopes - (Scopes : Scopes_In_Files_Map.Map; + (Scopes : in out Scopes_In_Files_Map.Map; SCO_Map : LL_HL_SCO_Map) is begin - for S of Scopes loop - if not S.Children.Is_Empty then - for Child of S.Children loop - Remap_Scope_Entity (Child, SCO_Map); - end loop; + for Cur in Scopes.Iterate loop + declare + Ref : constant Scopes_In_Files_Map.Reference_Type := + Scopes.Reference (Cur); + File_Scope : Scope_Entity renames + Scope_Entities_Trees.Element (Ref.File_Scope_Entity); + begin + -- If the file scope is empty, remove it - S.From := S.Children.First_Element.From; - S.To := S.Children.Last_Element.To; - end if; + if File_Scope.To < File_Scope.From then + Ref.Scope_Entities.Delete_Subtree (Ref.File_Scope_Entity); + else + Remap_Scope_Entities (Ref.Scope_Entities, SCO_Map); + end if; + end; end loop; end Remap_Scopes; @@ -3273,8 +3295,9 @@ package body Instrument.C is UIC.CUs.Find (Scopes_In_Files_Map.Key (C)); begin if Created_Unit_Maps.Has_Element (CU) then - Set_Scope_Entity (Created_Unit_Maps.Element (CU), - Scopes_In_Files_Map.Element (C)); + Set_Scope_Entities + (Created_Unit_Maps.Element (CU), + Scopes_In_Files_Map.Element (C).Scope_Entities); end if; end; end loop; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 946e5948c..339d094a7 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -315,9 +315,16 @@ package Instrument.C is Hash => Hash, Equivalent_Keys => "="); + type File_Scope_Type is record + Scope_Entities : Scope_Entities_Tree; + File_Scope_Entity : Scope_Entities_Trees.Cursor; + Current_Scope_Entity : Scope_Entities_Trees.Cursor; + end record; + -- Store scope entities and the currently traversed scope + package Scopes_In_Files_Map is new Ada.Containers.Ordered_Maps (Key_Type => Source_File_Index, - Element_Type => Scope_Entity_Acc); + Element_Type => File_Scope_Type); -- Mapping from a source file to the tree of scopes opened within it. The -- root of each tree is the scope corresponding to the file itself in which -- all its scopes are stored. @@ -368,7 +375,7 @@ package Instrument.C is -- after preprocessing. This is needed in order to keep track of -- which scope was originally opened in which file. - Current_File_Scope : Source_File_Index; + Current_File_Scope : Scopes_In_Files_Map.Cursor; -- Source file in which the last scope encountered was opened Disable_Instrumentation : Boolean := False; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 3e6212a55..bec71c658 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -346,17 +346,20 @@ package body Instrument.Common is -- Remap_Scope_Entity -- ------------------------ - procedure Remap_Scope_Entity - (Scope_Entity : Scope_Entity_Acc; - SCO_Map : LL_HL_SCO_Map) is + procedure Remap_Scope_Entities + (Scope_Entities : in out Scope_Entities_Tree; + SCO_Map : LL_HL_SCO_Map) is begin - Scope_Entity.From := SCO_Map (Nat (Scope_Entity.From)); - Scope_Entity.To := SCO_Map (Nat (Scope_Entity.To)); - - for Child of Scope_Entity.Children loop - Remap_Scope_Entity (Child, SCO_Map); + for Scope_Entity in Scope_Entities.Iterate loop + declare + Ref : constant Scope_Entities_Trees.Reference_Type := + Scope_Entities.Reference (Scope_Entity); + begin + Ref.From := SCO_Map (Nat (Ref.From)); + Ref.To := SCO_Map (Nat (Ref.To)); + end; end loop; - end Remap_Scope_Entity; + end Remap_Scope_Entities; -------------- -- New_File -- diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index a93756893..d40bc56fb 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -378,9 +378,9 @@ package Instrument.Common is -- source file, also append a new entry to the SCO_Unit_Table, otherwise -- complete its last entry. - procedure Remap_Scope_Entity - (Scope_Entity : Scope_Entity_Acc; - SCO_Map : LL_HL_SCO_Map); + procedure Remap_Scope_Entities + (Scope_Entities : in out Scope_Entities_Tree; + SCO_Map : LL_HL_SCO_Map); -- Convert low level SCOs in Scope_Entity to high-level SCOs using the -- mapping in SCO_Map. @@ -396,7 +396,6 @@ package Instrument.Common is type Language_Instrumenter is abstract tagged record Tag : Unbounded_String; -- Tag specific to an instrumentation run - end record; -- Set of operations to allow the instrumentation of sources files for a -- given language. diff --git a/tools/gnatcov/sc_obligations-bdd.adb b/tools/gnatcov/sc_obligations-bdd.adb index 9ffc1e79b..6e9350832 100644 --- a/tools/gnatcov/sc_obligations-bdd.adb +++ b/tools/gnatcov/sc_obligations-bdd.adb @@ -331,8 +331,6 @@ package body SC_Obligations.BDD is pragma Assert (BDD_Vector.Element (Dest).Kind /= Jump); end Patch_Jump; - use type Ada.Containers.Count_Type; - -- Start of processing for Completed begin diff --git a/tools/gnatcov/sc_obligations-bdd.ads b/tools/gnatcov/sc_obligations-bdd.ads index 15479f6f8..0e5c17bea 100644 --- a/tools/gnatcov/sc_obligations-bdd.ads +++ b/tools/gnatcov/sc_obligations-bdd.ads @@ -18,6 +18,8 @@ -- Binary Decision Diagrams +with Ada.Streams; use Ada.Streams; + private package SC_Obligations.BDD is Path_Count_Limit : Natural := 1024; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index d7c013bb8..3bc48f31c 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -20,6 +20,7 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Strings.Fixed; use Ada.Strings.Fixed; +with Ada.Streams; use Ada.Streams; with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Deallocation; @@ -102,8 +103,8 @@ package body SC_Obligations is PP_Info_Map : SCO_PP_Info_Maps.Map; -- Information about preprocessing - Scope_Ent : Scope_Entity_Acc := null; - -- Top-level scope, used to output e.g. subprogram metrics + Scope_Entities : Scope_Entities_Tree := Scope_Entities_Trees.Empty_Tree; + -- Scope tree, used to output e.g. subprogram metrics case Provider is when Compiler => @@ -607,6 +608,77 @@ package body SC_Obligations is -- -- ??? Same comment as above. + --------------------- + -- Scope_Traversal -- + --------------------- + + function Scope_Traversal (CU : CU_Id) return Scope_Traversal_Type + is + Result : Scope_Traversal_Type; + begin + if CU = No_CU_Id then + return No_Scope_Traversal; + end if; + Result.It := + new Tree_Iterator' + (Scope_Entities_Trees.Iterate + (CU_Vector.Reference (CU).Element.Scope_Entities)); + Result.Next_Scope_Ent := Result.It.First; + Result.Scope_Stack := Scope_Stacks.Empty_List; + Result.Active_Scopes := Scope_Id_Sets.Empty; + Result.Active_Scope_Ent := Scope_Entities_Trees.No_Element; + return Result; + end Scope_Traversal; + + ------------------ + -- Traverse_SCO -- + ------------------ + + procedure Traverse_SCO + (ST : in out Scope_Traversal_Type; + SCO : SCO_Id) + is + use Scope_Entities_Trees; + begin + -- Find the innermost scope featuring this SCO and update the list of + -- active scopes as we go. + + while ST.Next_Scope_Ent /= No_Element + and then SCO >= Element (ST.Next_Scope_Ent).From + loop + ST.Active_Scope_Ent := ST.Next_Scope_Ent; + + -- Update the scope stack + + if not ST.Scope_Stack.Is_Empty then + while ST.Scope_Stack.Last_Element /= Parent (ST.Active_Scope_Ent) + loop + ST.Active_Scopes.Delete + (Element (ST.Scope_Stack.Last_Element).Identifier); + ST.Scope_Stack.Delete_Last; + exit when ST.Scope_Stack.Is_Empty; + end loop; + end if; + ST.Scope_Stack.Append (ST.Active_Scope_Ent); + ST.Active_Scopes.Insert + (Element (ST.Active_Scope_Ent).Identifier); + ST.Next_Scope_Ent := ST.It.Next (ST.Next_Scope_Ent); + end loop; + end Traverse_SCO; + + --------------- + -- Is_Active -- + --------------- + + function Is_Active + (ST : Scope_Traversal_Type; + Subps_Of_Interest : Scope_Id_Set) return Boolean is + begin + return Subps_Of_Interest.Is_Empty + or else not Scope_Id_Sets.Is_Empty + (ST.Active_Scopes.Intersection (Subps_Of_Interest)); + end Is_Active; + ----------------- -- Add_Address -- ----------------- @@ -662,22 +734,6 @@ package body SC_Obligations is return CU_Vector.Reference (CU).Element.PP_Info_Map.Element (SCO); end Get_PP_Info; - ---------------------- - -- Get_Scope_Entity -- - ---------------------- - - function Get_Scope_Entity (CU : CU_Id) return Scope_Entity_Acc is - begin - if CU /= No_CU_Id then - declare - Info : constant CU_Info := CU_Vector.Reference (CU).Element.all; - begin - return Info.Scope_Ent; - end; - end if; - return null; - end Get_Scope_Entity; - -------------------------------- -- Checkpoint_Load_Merge_Unit -- -------------------------------- @@ -833,9 +889,6 @@ package body SC_Obligations is -- Remap a SCO_Id. Note: this assumes possible forward references, and -- does not rely on SCO_Map. - procedure Remap_Scope_Entity (Scope_Ent : Scope_Entity_Acc); - -- Remap a Scope_Entity, including all of its children (recursively) - --------------- -- Remap_BDD -- --------------- @@ -928,23 +981,6 @@ package body SC_Obligations is end if; end Remap_SCO_Id; - ------------------------ - -- Remap_Scope_Entity -- - ------------------------ - - procedure Remap_Scope_Entity (Scope_Ent : Scope_Entity_Acc) is - begin - if Scope_Ent = null then - return; - end if; - Remap_SCO_Id (Scope_Ent.From); - Remap_SCO_Id (Scope_Ent.To); - - for Child of Scope_Ent.Children loop - Remap_Scope_Entity (Child); - end loop; - end Remap_Scope_Entity; - -- Start of processing for Checkpoint_Load_New_Unit begin @@ -1129,7 +1165,11 @@ package body SC_Obligations is -- Remap SCOs span for scope entities - Remap_Scope_Entity (CP_CU.Scope_Ent); + for Scope_Ent of CP_CU.Scope_Entities loop + Remap_SCO_Id (Scope_Ent.From); + Remap_SCO_Id (Scope_Ent.To); + Remap_SFI (Relocs, Scope_Ent.Identifier.Decl_SFI); + end loop; end if; @@ -1313,20 +1353,6 @@ package body SC_Obligations is end if; end Checkpoint_Load_Unit; - ---------- - -- Free -- - ---------- - - procedure Free (Scope_Ent : in out Scope_Entity_Acc) is - procedure Deallocate is new Ada.Unchecked_Deallocation - (Scope_Entity, Scope_Entity_Acc); - begin - for Child of Scope_Ent.Children loop - Free (Child); - end loop; - Deallocate (Scope_Ent); - end Free; - procedure Free (CU : in out CU_Info) is procedure Free is new Ada.Unchecked_Deallocation (Statement_Bit_Map, Statement_Bit_Map_Access); @@ -1342,9 +1368,6 @@ package body SC_Obligations is Free (CU.Bit_Maps.Decision_Bits); Free (CU.Bit_Maps.MCDC_Bits); end if; - if CU.Scope_Ent /= null then - Free (CU.Scope_Ent); - end if; end Free; -- Procedures below use comparisons on checkpoint format versions @@ -1424,25 +1447,10 @@ package body SC_Obligations is -- Checkpoint version 8 data (scoped metrics support) if not Version_Less (S, Than => 8) then - Scope_Entity_Acc'Read (S, V.Scope_Ent); + Scope_Entities_Tree'Read (S, V.Scope_Entities); end if; end Read; - procedure Read (S : access Root_Stream_Type'Class; V : out Scope_Entity_Acc) - is - begin - V := new Scope_Entity; - SCO_Id'Read (S, V.From); - SCO_Id'Read (S, V.To); - Unbounded_String'Read (S, V.Name); - Local_Source_Location'Read (S, V.Sloc); - Scope_Entities_Vector'Read (S, V.Children); - - -- Note that we don't stream Scope_Ent.Parent. We only need it at - -- instrumentation time, to help creating the scope tree. - - end Read; - ----------- -- Write -- ----------- @@ -1482,23 +1490,7 @@ package body SC_Obligations is Fingerprint_Type'Write (S, V.Bit_Maps_Fingerprint); end if; end case; - - Scope_Entity_Acc'Write (S, V.Scope_Ent); - end Write; - - ----------- - -- Write -- - ----------- - - procedure Write (S : access Root_Stream_Type'Class; V : Scope_Entity_Acc) is - Scope_Ent : constant Scope_Entity := - (if V = null then No_Scope_Entity else V.all); - begin - SCO_Id'Write (S, Scope_Ent.From); - SCO_Id'Write (S, Scope_Ent.To); - Unbounded_String'Write (S, Scope_Ent.Name); - Local_Source_Location'Write (S, Scope_Ent.Sloc); - Scope_Entities_Vector'Write (S, Scope_Ent.Children); + Scope_Entities_Tree'Write (S, V.Scope_Entities); end Write; --------------------- @@ -4058,7 +4050,6 @@ package body SC_Obligations is -- associated conditional branch instruction. declare - use type Ada.Containers.Count_Type; SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); D_SCO : SCO_Id; begin @@ -4197,14 +4188,27 @@ package body SC_Obligations is (GNAT.SHA1.Binary_Message_Digest'(GNAT.SHA1.Digest (Ctx))); end Set_Bit_Maps; - ---------------------- - -- Set_Scope_Entity -- - ---------------------- + ------------------------ + -- Get_Scope_Entities -- + ------------------------ + + function Get_Scope_Entities (CU : CU_Id) return Scope_Entities_Tree is + begin + if CU /= No_CU_Id then + return CU_Vector.Reference (CU).Element.Scope_Entities; + end if; + return Scope_Entities_Trees.Empty_Tree; + end Get_Scope_Entities; + + ------------------------ + -- Set_Scope_Entities -- + ------------------------ - procedure Set_Scope_Entity (CU : CU_Id; Scope_Ent : Scope_Entity_Acc) is + procedure Set_Scope_Entities + (CU : CU_Id; Scope_Entities : Scope_Entities_Trees.Tree) is begin - CU_Vector.Reference (CU).Scope_Ent := Scope_Ent; - end Set_Scope_Entity; + CU_Vector.Reference (CU).Scope_Entities := Scope_Entities; + end Set_Scope_Entities; ------------------------------- -- Set_Operand_Or_Expression -- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 2b7de7331..2c12c5006 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -18,12 +18,13 @@ -- Source Coverage Obligations +with Ada.Containers; use Ada.Containers; with Ada.Containers.Doubly_Linked_Lists; with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Containers.Ordered_Maps; with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; -with Ada.Streams; use Ada.Streams; +with Ada.Containers.Multiway_Trees; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with GNAT.Regexp; @@ -148,35 +149,18 @@ package SC_Obligations is No_SCO_Id : constant SCO_Id := 0; subtype Valid_SCO_Id is SCO_Id range No_SCO_Id + 1 .. SCO_Id'Last; - type Scope_Entity; - type Scope_Entity_Acc is access Scope_Entity; - -- Scope_Entity (SE) stores the SCO range, the name, the sloc and the - -- child scopes of a SE. Note that we assume that the SCOs of a SE can - -- be designated by a range. We thus include SCOs belonging to children - -- SEs. - -- - -- For Ada, we support a granularity of package / subprogram / task / - -- entry scopes. - -- - -- TODO??? implementation for C. - -- - -- This information is computed by the instrumenters (that know what is - -- a scope, and what is not). - - procedure Read - (S : access Root_Stream_Type'Class; - V : out Scope_Entity_Acc); - procedure Write (S : access Root_Stream_Type'Class; V : Scope_Entity_Acc); - - for Scope_Entity_Acc'Read use Read; - for Scope_Entity_Acc'Write use Write; - - procedure Free (Scope_Ent : in out Scope_Entity_Acc); + type Scope_Entity_Identifier is record + Decl_SFI : Source_File_Index; + Decl_Line : Natural; + end record; + -- To have a unique identifier for the scope, we use the source file index + -- and line for the original declaration (which is the body declaration for + -- C/C++ and the specification declaration for Ada). - package Scope_Entities_Vectors is new Ada.Containers.Vectors - (Index_Type => Pos, - Element_Type => Scope_Entity_Acc); - subtype Scope_Entities_Vector is Scope_Entities_Vectors.Vector; + function "<" (L, R : Scope_Entity_Identifier) return Boolean is + (if L.Decl_SFI = R.Decl_SFI + then L.Decl_Line < R.Decl_Line + else L.Decl_SFI < R.Decl_SFI); type Scope_Entity is record From, To : SCO_Id; @@ -188,21 +172,70 @@ package SC_Obligations is Sloc : Local_Source_Location; -- Name (as it appears in the source) and sloc of this scope definition - Children : Scope_Entities_Vector; - -- Children scopes - - Parent : Scope_Entity_Acc; - -- Reference to parent scope, null if this is a top-level scope - + Identifier : Scope_Entity_Identifier; + -- Identifier for this scope entity end record; + -- Scope_Entity (SE) stores the SCO range, the name and the sloc of a SE. + -- Note that we assume that the SCOs of a SE can be designated by a range. + -- + -- For Ada, we support a granularity of package / subprogram / task / + -- entry scopes. + -- + -- For C/C++, we support a granularity of function declaration (including + -- template, constructor, destructor and lambda expressions) / namespace / + -- class (including template) scopes. + -- + -- This information is computed by the instrumenters (that know what is + -- a scope, and what is not). + + package Scope_Id_Sets is new Ada.Containers.Ordered_Sets + (Element_Type => Scope_Entity_Identifier); + subtype Scope_Id_Set is Scope_Id_Sets.Set; + + package Scope_Entities_Trees is new Ada.Containers.Multiway_Trees + (Element_Type => Scope_Entity); + subtype Scope_Entities_Tree is Scope_Entities_Trees.Tree; + + subtype Tree_Iterator is + Scope_Entities_Trees.Tree_Iterator_Interfaces.Forward_Iterator'Class; + type Iterator_Acc is access Tree_Iterator; + package Scope_Stacks is new Ada.Containers.Doubly_Linked_Lists + (Element_Type => Scope_Entities_Trees.Cursor, + "=" => Scope_Entities_Trees."="); + + type Scope_Traversal_Type is private; + -- Utilities type to efficiently traverse the scopes in a compilation unit. + -- This is a tree-like data structure, with an iterator pointing to the + -- currently traversed inner scope. + -- + -- The intended use is to create a Scope_Traversal_Type using the + -- Scope_Traversal function, and then call Traverse_SCO every time + -- we traverse a SCO to update the scope traversal iterator, and call + -- Is_Active to know whether a given scope is active in the given + -- traversal. + + function Scope_Traversal (CU : CU_Id) return Scope_Traversal_Type; + -- Return a scope traversal for the given compilation unit + + procedure Traverse_SCO + (ST : in out Scope_Traversal_Type; + SCO : SCO_Id); + -- Traverse the given SCO and update the Scope_Traversal accordingly. Note + -- that the scope traversal must be done on increasing SCOs identifiers. + + function Is_Active + (ST : Scope_Traversal_Type; + Subps_Of_Interest : Scope_Id_Set) return Boolean; + -- Return whether any of the scopes in Subps_Of_Interest is currently + -- active. Return True if Subps_Of_Interest is empty (i.e. consider all + -- subprograms of interest in that case). No_Scope_Entity : constant Scope_Entity := - (From => No_SCO_Id, - To => No_SCO_Id, - Name => +"", - Sloc => No_Local_Location, - Children => Scope_Entities_Vectors.Empty_Vector, - Parent => null); + (From => No_SCO_Id, + To => No_SCO_Id, + Name => +"", + Sloc => No_Local_Location, + Identifier => (Decl_SFI => 0, Decl_Line => 0)); type Any_SCO_Kind is (Removed, Statement, Decision, Condition, Operator); subtype SCO_Kind is Any_SCO_Kind range Statement .. Operator; @@ -679,12 +712,12 @@ package SC_Obligations is with Pre => Has_PP_Info (SCO); -- Return the preprocessing information (if any) for the given SCO - function Get_Scope_Entity (CU : CU_Id) return Scope_Entity_Acc; - -- Return description for top-level scope, if available. Return null - -- otherwise. + function Get_Scope_Entities (CU : CU_Id) return Scope_Entities_Trees.Tree; + -- Return the scope entities for the given compilation unit - procedure Set_Scope_Entity (CU : CU_Id; Scope_Ent : Scope_Entity_Acc); - -- Set the top level scope for the given unit + procedure Set_Scope_Entities + (CU : CU_Id; Scope_Entities : Scope_Entities_Trees.Tree); + -- Set the scope entities for the given unit ----------------- -- Checkpoints -- @@ -1288,4 +1321,30 @@ private procedure Set_BDD_Node (C_SCO : SCO_Id; BDD_Node : BDD_Node_Id); -- Set the BDD node for the given condition SCO + type Scope_Traversal_Type is record + Scope_Entities : Scope_Entities_Tree; + -- Currently traversed scope entities + + Scope_Stack : Scope_Stacks.List; + Active_Scopes : Scope_Id_Set; + -- List of currently active scopes + + Active_Scope_Ent : Scope_Entities_Trees.Cursor; + -- Innermost currently active scope + + Next_Scope_Ent : Scope_Entities_Trees.Cursor; + -- Next active scope + + It : Iterator_Acc; + -- Iterator to traverse the scope tree + end record; + + No_Scope_Traversal : Scope_Traversal_Type := + (Scope_Entities => Scope_Entities_Trees.Empty_Tree, + Scope_Stack => Scope_Stacks.Empty_List, + Active_Scopes => Scope_Id_Sets.Empty_Set, + Active_Scope_Ent => Scope_Entities_Trees.No_Element, + Next_Scope_Ent => Scope_Entities_Trees.No_Element, + It => null); + end SC_Obligations; diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index a5b5cda3f..9483aa805 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -25,6 +25,7 @@ with Calendar_Utils; use Calendar_Utils; with Command_Line; use Command_Line; with Command_Line_Support; use Command_Line_Support; with Inputs; +with SC_Obligations; with Strings; use Strings; package Switches is @@ -124,6 +125,9 @@ package Switches is -- When True, use full unit/filename slugs for generated buffer units -- instead of hashes. + Subps_Of_Interest : SC_Obligations.Scope_Id_Set; + -- List of subprograms of interest + type Separated_Source_Coverage_Type is (None, Routines, Instances); Separated_Source_Coverage : Separated_Source_Coverage_Type := None; From 3fbdddc6ba22c1ae84ae23e351c4383bfd94f140 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 12 Sep 2023 12:37:26 +0200 Subject: [PATCH 0409/1483] U204-026-arch-mix: update test --- .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 644 -> 668 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2020 -> 2020 bytes .../{gcvrt-bpkg.ads => gcvrt-bz3791e32c.ads} | 18 ++++++------- ...gcvrt-bmain_1.ads => gcvrt-bz794ac68b.ads} | 12 ++++----- ...gcvrt-bmain_2.ads => gcvrt-bz794ac68c.ads} | 12 ++++----- ...t-db_main_1.adb => gcvrt-db_z794ac68b.adb} | 4 +-- ...t-db_main_1.ads => gcvrt-db_z794ac68b.ads} | 4 +-- ...t-db_main_2.adb => gcvrt-db_z794ac68c.adb} | 4 +-- ...t-db_main_2.ads => gcvrt-db_z794ac68c.ads} | 4 +-- .../gen/arm-elf-linux/gcvrt-foo.ads | 24 +++++++++--------- .../{gcvrt-ppkg.ads => gcvrt-pz3791e32c.ads} | 16 ++++++------ ...gcvrt-pmain_1.ads => gcvrt-pz794ac68b.ads} | 10 ++++---- ...gcvrt-pmain_2.ads => gcvrt-pz794ac68c.ads} | 10 ++++---- .../gen/arm-elf-linux/main_1.adb | 6 ++--- .../gen/arm-elf-linux/main_1.sid | Bin 387 -> 403 bytes .../gen/arm-elf-linux/main_2.adb | 6 ++--- .../gen/arm-elf-linux/main_2.sid | Bin 387 -> 403 bytes .../gen/arm-elf-linux/pkg.adb | 8 +++--- .../gen/arm-elf-linux/pkg.ads | 2 +- .../gen/arm-elf-linux/pkg.sid | Bin 1046 -> 1046 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1906 -> 1838 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1916 -> 1848 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 1943 -> 1979 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 1879 -> 1915 bytes .../{gcvrt-bpkg.ads => gcvrt-bz3791e32c.ads} | 18 ++++++------- ...gcvrt-bmain_1.ads => gcvrt-bz794ac68b.ads} | 12 ++++----- ...gcvrt-bmain_2.ads => gcvrt-bz794ac68c.ads} | 12 ++++----- ...t-db_main_1.adb => gcvrt-db_z794ac68b.adb} | 4 +-- ...t-db_main_1.ads => gcvrt-db_z794ac68b.ads} | 4 +-- ...t-db_main_2.adb => gcvrt-db_z794ac68c.adb} | 4 +-- ...t-db_main_2.ads => gcvrt-db_z794ac68c.ads} | 4 +-- .../gen/x86_64-windows/gcvrt-foo.ads | 24 +++++++++--------- .../{gcvrt-ppkg.ads => gcvrt-pz3791e32c.ads} | 16 ++++++------ ...gcvrt-pmain_2.ads => gcvrt-pz794ac68b.ads} | 10 ++++---- ...gcvrt-pmain_1.ads => gcvrt-pz794ac68c.ads} | 10 ++++---- .../gen/x86_64-windows/main_1.adb | 6 ++--- .../gen/x86_64-windows/main_1.sid | Bin 389 -> 405 bytes .../gen/x86_64-windows/main_2.adb | 6 ++--- .../gen/x86_64-windows/main_2.sid | Bin 389 -> 405 bytes .../gen/x86_64-windows/pkg.adb | 8 +++--- .../gen/x86_64-windows/pkg.ads | 2 +- .../gen/x86_64-windows/pkg.sid | Bin 1050 -> 1050 bytes 42 files changed, 140 insertions(+), 140 deletions(-) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-bpkg.ads => gcvrt-bz3791e32c.ads} (86%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-bmain_1.ads => gcvrt-bz794ac68b.ads} (84%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-bmain_2.ads => gcvrt-bz794ac68c.ads} (84%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-db_main_1.adb => gcvrt-db_z794ac68b.adb} (85%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-db_main_1.ads => gcvrt-db_z794ac68b.ads} (72%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-db_main_2.adb => gcvrt-db_z794ac68c.adb} (85%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-db_main_2.ads => gcvrt-db_z794ac68c.ads} (72%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-ppkg.ads => gcvrt-pz3791e32c.ads} (57%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-pmain_1.ads => gcvrt-pz794ac68b.ads} (65%) rename testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/{gcvrt-pmain_2.ads => gcvrt-pz794ac68c.ads} (65%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-bpkg.ads => gcvrt-bz3791e32c.ads} (84%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-bmain_1.ads => gcvrt-bz794ac68b.ads} (82%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-bmain_2.ads => gcvrt-bz794ac68c.ads} (82%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-db_main_1.adb => gcvrt-db_z794ac68b.adb} (85%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-db_main_1.ads => gcvrt-db_z794ac68b.ads} (82%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-db_main_2.adb => gcvrt-db_z794ac68c.adb} (85%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-db_main_2.ads => gcvrt-db_z794ac68c.ads} (82%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-ppkg.ads => gcvrt-pz3791e32c.ads} (56%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-pmain_2.ads => gcvrt-pz794ac68b.ads} (63%) rename testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/{gcvrt-pmain_1.ads => gcvrt-pz794ac68c.ads} (63%) diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index 1b7f06c4baf411743211d5529cc59e75e7336f5e..edde38ac124f89f4b3eb758e41abd30945d393e3 100644 GIT binary patch literal 668 zcmYk2y)Q#i7{=dwReLohdWncMazi7QM(?eUG8hDdM1mj&iSL2^bZg*nM?-E1~C}?-rFP5o$W%SgTLZ*1Seg z_5GR~5JkW7|NXTy{ofK|l9H2ZTFjW(vW$7$M?*eq#3b;Yb0g%xFiRY1%XgU1NufuK z&Hg0ny+~U;Vy%CGUG`~f=B=ExsjGG7d&M~9k5TL2;5GiD-s{Bu8Gun94jXe53kfjWn)E4T|*-ULnA9gV=E&w1`Y-W25ul$Ffz9=H#9UdFf-d& Hp34pZB>4(W delta 53 zcmaFD|Ac>n94i~ID7V!_Wn)D%T|;99BSR}gLn~7Y1`Y-W1}-30Ff%eYGqp4^G-23S Hp34pZDo6@O diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bpkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads similarity index 86% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bpkg.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads index 16884c68b..04a1130a6 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bpkg.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads @@ -3,22 +3,22 @@ with Interfaces.C; use Interfaces.C; with System; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GCVRT.Bpkg is +package GCVRT.Bz3791e32c is pragma Preelaborate; package Buffers_1 is Statement_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_z3791e32c_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_z3791e32c_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_z3791e32c_1"); Unit_Name : constant String := "pkg"; @@ -39,15 +39,15 @@ end Buffers_1; package Buffers_2 is Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg_2"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_z3791e32c_2"); Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg_2"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_z3791e32c_2"); MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg_2"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_z3791e32c_2"); Unit_Name : constant String := "pkg"; @@ -69,6 +69,6 @@ end Buffers_2; (1 => Buffers_1.Buffers'Access, 2 => Buffers_2.Buffers'Access); C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 2, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_pkg_buffers"); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_z3791e32c_buffers"); -end GCVRT.Bpkg; +end GCVRT.Bz3791e32c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_1.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads similarity index 84% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads index abd0f2006..15d7322a1 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads @@ -3,22 +3,22 @@ with Interfaces.C; use Interfaces.C; with System; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GCVRT.Bmain_1 is +package GCVRT.Bz794ac68b is pragma Preelaborate; package Buffers_1 is Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_z794ac68b_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_z794ac68b_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_z794ac68b_1"); Unit_Name : constant String := "main_1"; @@ -39,6 +39,6 @@ end Buffers_1; Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers_1.Buffers'Access); C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_1_buffers"); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_z794ac68b_buffers"); -end GCVRT.Bmain_1; +end GCVRT.Bz794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads similarity index 84% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads index db6822381..bf5286f05 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bmain_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads @@ -3,22 +3,22 @@ with Interfaces.C; use Interfaces.C; with System; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GCVRT.Bmain_2 is +package GCVRT.Bz794ac68c is pragma Preelaborate; package Buffers_1 is Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_z794ac68c_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_z794ac68c_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_z794ac68c_1"); Unit_Name : constant String := "main_2"; @@ -39,6 +39,6 @@ end Buffers_1; Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers_1.Buffers'Access); C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_2_buffers"); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_z794ac68c_buffers"); -end GCVRT.Bmain_2; +end GCVRT.Bz794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb similarity index 85% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.adb rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb index b57053032..f287bda84 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; with GCVRT.Foo; -package body GCVRT.DB_main_1 is +package body GCVRT.DB_z794ac68b is procedure Dump_Buffers is begin @@ -12,4 +12,4 @@ package body GCVRT.DB_main_1 is Exec_Date => 0); end Dump_Buffers; -end GCVRT.DB_main_1; +end GCVRT.DB_z794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads similarity index 72% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads index 8a501b2da..f401c6be8 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads @@ -1,8 +1,8 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Buffers; -package GCVRT.DB_main_1 is +package GCVRT.DB_z794ac68b is procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); -end GCVRT.DB_main_1; +end GCVRT.DB_z794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb similarity index 85% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.adb rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb index ccab2ae8d..b8d2caccb 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; with GCVRT.Foo; -package body GCVRT.DB_main_2 is +package body GCVRT.DB_z794ac68c is procedure Dump_Buffers is begin @@ -12,4 +12,4 @@ package body GCVRT.DB_main_2 is Exec_Date => 0); end Dump_Buffers; -end GCVRT.DB_main_2; +end GCVRT.DB_z794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads similarity index 72% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads index 0f4078092..f2304e341 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_main_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads @@ -1,8 +1,8 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Buffers; -package GCVRT.DB_main_2 is +package GCVRT.DB_z794ac68c is procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); -end GCVRT.DB_main_2; +end GCVRT.DB_z794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads index 8a33e62aa..718d038b9 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads @@ -1,23 +1,23 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -with GCVRT.Bmain_1; -with GCVRT.Bmain_2; -with GCVRT.Bpkg; +with GCVRT.Bz794ac68b; +with GCVRT.Bz794ac68c; +with GCVRT.Bz3791e32c; package GCVRT.Foo is pragma Preelaborate; - gnatcov_rts_buffers_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_main_1_buffers,"gnatcov_rts_buffers_main_1_buffers"); - gnatcov_rts_buffers_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_main_2_buffers,"gnatcov_rts_buffers_main_2_buffers"); - gnatcov_rts_buffers_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_pkg_buffers,"gnatcov_rts_buffers_pkg_buffers"); + gnatcov_rts_buffers_z794ac68b_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_z794ac68b_buffers,"gnatcov_rts_buffers_z794ac68b_buffers"); + gnatcov_rts_buffers_z794ac68c_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_z794ac68c_buffers,"gnatcov_rts_buffers_z794ac68c_buffers"); + gnatcov_rts_buffers_z3791e32c_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_z3791e32c_buffers,"gnatcov_rts_buffers_z3791e32c_buffers"); List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( - 1 => gnatcov_rts_buffers_main_1_buffers'Access, - 2 => gnatcov_rts_buffers_main_2_buffers'Access, - 3 => gnatcov_rts_buffers_pkg_buffers'Access); + 1 => gnatcov_rts_buffers_z794ac68b_buffers'Access, + 2 => gnatcov_rts_buffers_z794ac68c_buffers'Access, + 3 => gnatcov_rts_buffers_z3791e32c_buffers'Access); C_List : constant GNATcov_RTS.Buffers.Lists.GNATcov_RTS_Coverage_Buffers_Group_Array := ( 3, List'Address); pragma Export (C, C_List, "gnatcov_rts_buffers_array_Foo"); diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads similarity index 57% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads index d057902c9..75674fce3 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-ppkg.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads @@ -4,32 +4,32 @@ with GNATcov_RTS; with GNATcov_RTS.Buffers; pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); -package GCVRT.Ppkg is +package GCVRT.Pz3791e32c is pragma Pure; package Buffers_1 is Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg_1"); + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_z3791e32c_1"); Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg_1"); + pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_z3791e32c_1"); MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg_1"); + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_z3791e32c_1"); end Buffers_1; package Buffers_2 is Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg_2"); + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_z3791e32c_2"); Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg_2"); + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_z3791e32c_2"); MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg_2"); + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_z3791e32c_2"); end Buffers_2; -end GCVRT.Ppkg; +end GCVRT.Pz3791e32c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_1.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads similarity index 65% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads index adbaa4d71..5830af68f 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads @@ -4,20 +4,20 @@ with GNATcov_RTS; with GNATcov_RTS.Buffers; pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); -package GCVRT.Pmain_1 is +package GCVRT.Pz794ac68b is pragma Pure; package Buffers_1 is Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1_1"); + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_z794ac68b_1"); Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1_1"); + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_z794ac68b_1"); MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1_1"); + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_z794ac68b_1"); end Buffers_1; -end GCVRT.Pmain_1; +end GCVRT.Pz794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_2.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads similarity index 65% rename from testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads index 504bd5e24..3e9adb3e0 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pmain_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads @@ -4,20 +4,20 @@ with GNATcov_RTS; with GNATcov_RTS.Buffers; pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); -package GCVRT.Pmain_2 is +package GCVRT.Pz794ac68c is pragma Pure; package Buffers_1 is Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2_1"); + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_z794ac68c_1"); Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2_1"); + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_z794ac68c_1"); MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2_1"); + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_z794ac68c_1"); end Buffers_1; -end GCVRT.Pmain_2; +end GCVRT.Pz794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb index cfb135284..172458ad0 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb @@ -1,9 +1,9 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pmain_1;with GCVRT.DB_main_1;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is begin - GNATcov_RTS.Buffers.Witness(GCVRT.Pmain_1.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); -GCVRT.DB_main_1.Dump_Buffers;end Main_1; + GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); +GCVRT.DB_z794ac68b.Dump_Buffers;end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index a136b1e8d13a1557ad20f0640ee748747697bde7..0d9fe3bf75ee9c5fbffcf4c0175b4eb43eee6996 100644 GIT binary patch delta 22 ecmZo>p3FSq^2F0ptc(l{49t@i8HFc)?E?T$dp3FSq^2F0ptc(l{49t@i8HFc)?E?T$dZPOKmelw)@l+O delta 101 zcmZ3-_la+V5fcjo0|Vn^LuQf5MofMPP6LxCBS=_!^I4`?X6_w8RRu-nnGUZePc~)S kIQbQuf{K~0p|OIIv6Z2rm8rRcwt9SFc^0J2^bxc~qF diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index 4f6f771d824294e26979c7bbf23af408470bbe67..7fe2851caf3ae1126587120f8e2732a0b84aad3d 100644 GIT binary patch delta 82 zcmeyvw}Wqk5z}NZCcnuWm^?QNGG{V#?_*$KP|$PLS-X4v4)#!;FfoOklBxjEu%%a+8~x zv{{*fa!i|7Gu>w9z6fN_(OpsVd-wXu6WLU_LyJ?3ieoZMa?^_@A7Go#0+eQ$9M0|l E0EyHbQvd(} delta 86 zcmdnZKb?O=731V4Mxn`b7_BDXW0afB!eqzF00fMa9hrqEJ29C}ZeWt0yqHOO^Esv) q%-m;zQa5;}oxk~Z^5l(dD%=_Qxv4R!l|_lADU%1_lPk$y*uKCSPV$W@QBOm?nQ_v<0&mC+jjPvN8k3m?wKP o!NgjDVk{uB&5N0CGjq=bGIuQ9m$PQ~`pKPaeIOZz$>Qt|0Bb!Kp8x;= delta 74 zcmey(cb#uT79%SI5HL;-WD%a6#b`Ep1*7uhHH;jSZ!-!{{>ErE*@8)KavYP@ False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_pkg_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__S_z3791e32c_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_pkg_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__S_z3791e32c_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_pkg_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__S_z3791e32c_1"); Unit_Name : constant String := "pkg"; @@ -39,15 +39,15 @@ end Buffers_1; package Buffers_2 is Statement_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_pkg_2"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_z3791e32c_2"); Decision_Buffer : Coverage_Buffer_Type (0 .. 1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_pkg_2"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_z3791e32c_2"); MCDC_Buffer : Coverage_Buffer_Type (0 .. 2) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_pkg_2"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_z3791e32c_2"); Unit_Name : constant String := "pkg"; @@ -69,6 +69,6 @@ end Buffers_2; (1 => Buffers_1.Buffers'Access, 2 => Buffers_2.Buffers'Access); C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 2, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_pkg_buffers"); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_z3791e32c_buffers"); -end GCVRT.Bpkg; +end GCVRT.Bz3791e32c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads similarity index 82% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads index f21637825..621358f4b 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads @@ -3,22 +3,22 @@ with Interfaces.C; use Interfaces.C; with System; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GCVRT.Bmain_1 is +package GCVRT.Bz794ac68b is pragma Preelaborate; package Buffers_1 is Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_1_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_z794ac68b_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_1_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_z794ac68b_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_1_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_z794ac68b_1"); Unit_Name : constant String := "main_1"; @@ -39,6 +39,6 @@ end Buffers_1; Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers_1.Buffers'Access); C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_1_buffers"); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_z794ac68b_buffers"); -end GCVRT.Bmain_1; +end GCVRT.Bz794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads similarity index 82% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads index d68593c7f..02173f249 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bmain_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads @@ -3,22 +3,22 @@ with Interfaces.C; use Interfaces.C; with System; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -package GCVRT.Bmain_2 is +package GCVRT.Bz794ac68c is pragma Preelaborate; package Buffers_1 is Statement_Buffer : Coverage_Buffer_Type (0 .. 0) := (others => False); Statement_Buffer_Address : constant System.Address := Statement_Buffer'Address; - pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_main_2_1"); + pragma Export (C, Statement_Buffer_Address, "xcov__buf_stmt__B_z794ac68c_1"); Decision_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); Decision_Buffer_Address : constant System.Address := Decision_Buffer'Address; - pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_main_2_1"); + pragma Export (C, Decision_Buffer_Address, "xcov__buf_dc__B_z794ac68c_1"); MCDC_Buffer : Coverage_Buffer_Type (0 .. -1) := (others => False); MCDC_Buffer_Address : constant System.Address := MCDC_Buffer'Address; - pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_main_2_1"); + pragma Export (C, MCDC_Buffer_Address, "xcov__buf_mcdc__B_z794ac68c_1"); Unit_Name : constant String := "main_2"; @@ -39,6 +39,6 @@ end Buffers_1; Buffers_Group : aliased constant Coverage_Buffers_Group := (1 => Buffers_1.Buffers'Access); C_Buffers_Group : aliased constant GNATcov_RTS_Coverage_Buffers_Group := ( 1, Buffers_Group'Address); - pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_main_2_buffers"); + pragma Export (C, C_Buffers_Group, "gnatcov_rts_buffers_z794ac68c_buffers"); -end GCVRT.Bmain_2; +end GCVRT.Bz794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.adb similarity index 85% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.adb rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.adb index 79e3fa3de..b2179bab2 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.adb @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; with GCVRT.Foo; -package body GCVRT.DB_main_1 is +package body GCVRT.DB_z794ac68b is procedure Dump_Buffers is begin @@ -17,4 +17,4 @@ package body GCVRT.DB_main_1 is Dump_Buffers; end Finalize; -end GCVRT.DB_main_1; +end GCVRT.DB_z794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.ads similarity index 82% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.ads index fb6f2406e..ae6165f07 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.ads @@ -1,7 +1,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Buffers; with Ada.Finalization; -package GCVRT.DB_main_1 is +package GCVRT.DB_z794ac68b is procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); @@ -10,4 +10,4 @@ package GCVRT.DB_main_1 is null record; overriding procedure Finalize (Self : in out Dump_Controlled_Type); -end GCVRT.DB_main_1; +end GCVRT.DB_z794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.adb similarity index 85% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.adb rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.adb index d684712eb..53e73cfed 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.adb @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with Interfaces.C; with GCVRT.Foo; -package body GCVRT.DB_main_2 is +package body GCVRT.DB_z794ac68c is procedure Dump_Buffers is begin @@ -17,4 +17,4 @@ package body GCVRT.DB_main_2 is Dump_Buffers; end Finalize; -end GCVRT.DB_main_2; +end GCVRT.DB_z794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.ads similarity index 82% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.ads index 691c4c538..2fd733d04 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_main_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.ads @@ -1,7 +1,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Buffers; with Ada.Finalization; -package GCVRT.DB_main_2 is +package GCVRT.DB_z794ac68c is procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); @@ -10,4 +10,4 @@ package GCVRT.DB_main_2 is null record; overriding procedure Finalize (Self : in out Dump_Controlled_Type); -end GCVRT.DB_main_2; +end GCVRT.DB_z794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads index c9aac77d4..4d6b4219d 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads @@ -1,23 +1,23 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; -with GCVRT.Bmain_1; -with GCVRT.Bmain_2; -with GCVRT.Bpkg; +with GCVRT.Bz794ac68b; +with GCVRT.Bz794ac68c; +with GCVRT.Bz3791e32c; package GCVRT.Foo is pragma Preelaborate; - gnatcov_rts_buffers_main_1_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_main_1_buffers,"gnatcov_rts_buffers_main_1_buffers"); - gnatcov_rts_buffers_main_2_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_main_2_buffers,"gnatcov_rts_buffers_main_2_buffers"); - gnatcov_rts_buffers_pkg_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; - pragma Import (C, gnatcov_rts_buffers_pkg_buffers,"gnatcov_rts_buffers_pkg_buffers"); + gnatcov_rts_buffers_z794ac68b_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_z794ac68b_buffers,"gnatcov_rts_buffers_z794ac68b_buffers"); + gnatcov_rts_buffers_z794ac68c_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_z794ac68c_buffers,"gnatcov_rts_buffers_z794ac68c_buffers"); + gnatcov_rts_buffers_z3791e32c_buffers : aliased constant GNATcov_RTS_Coverage_Buffers_Group; + pragma Import (C, gnatcov_rts_buffers_z3791e32c_buffers,"gnatcov_rts_buffers_z3791e32c_buffers"); List : constant GNATcov_RTS.Buffers.Lists.Coverage_Buffers_Group_Array := ( - 1 => gnatcov_rts_buffers_main_1_buffers'Access, - 2 => gnatcov_rts_buffers_main_2_buffers'Access, - 3 => gnatcov_rts_buffers_pkg_buffers'Access); + 1 => gnatcov_rts_buffers_z794ac68b_buffers'Access, + 2 => gnatcov_rts_buffers_z794ac68c_buffers'Access, + 3 => gnatcov_rts_buffers_z3791e32c_buffers'Access); C_List : constant GNATcov_RTS.Buffers.Lists.GNATcov_RTS_Coverage_Buffers_Group_Array := ( 3, List'Address); pragma Export (C, C_List, "gnatcov_rts_buffers_array_Foo"); diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads similarity index 56% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads index 91152a7b1..fa1db1f43 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-ppkg.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads @@ -4,32 +4,32 @@ with GNATcov_RTS; with GNATcov_RTS.Buffers; pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); -package GCVRT.Ppkg is +package GCVRT.Pz3791e32c is pragma Pure; package Buffers_1 is Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_pkg_1"); + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__S_z3791e32c_1"); Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_pkg_1"); + pragma Import (C, Decision_Buffer, "xcov__buf_dc__S_z3791e32c_1"); MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_pkg_1"); + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__S_z3791e32c_1"); end Buffers_1; package Buffers_2 is Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_pkg_2"); + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_z3791e32c_2"); Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_pkg_2"); + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_z3791e32c_2"); MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_pkg_2"); + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_z3791e32c_2"); end Buffers_2; -end GCVRT.Ppkg; +end GCVRT.Pz3791e32c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_2.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads similarity index 63% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_2.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads index 8bbd8b5ce..cdb290eef 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_2.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads @@ -4,20 +4,20 @@ with GNATcov_RTS; with GNATcov_RTS.Buffers; pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); -package GCVRT.Pmain_2 is +package GCVRT.Pz794ac68b is pragma Pure; package Buffers_1 is Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_2_1"); + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_z794ac68b_1"); Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_2_1"); + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_z794ac68b_1"); MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_2_1"); + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_z794ac68b_1"); end Buffers_1; -end GCVRT.Pmain_2; +end GCVRT.Pz794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_1.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads similarity index 63% rename from testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_1.ads rename to testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads index c5a253048..3b64b8361 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pmain_1.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads @@ -4,20 +4,20 @@ with GNATcov_RTS; with GNATcov_RTS.Buffers; pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); -package GCVRT.Pmain_1 is +package GCVRT.Pz794ac68c is pragma Pure; package Buffers_1 is Statement_Buffer : constant System.Address; - pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_main_1_1"); + pragma Import (C, Statement_Buffer, "xcov__buf_stmt__B_z794ac68c_1"); Decision_Buffer : constant System.Address; - pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_main_1_1"); + pragma Import (C, Decision_Buffer, "xcov__buf_dc__B_z794ac68c_1"); MCDC_Buffer : constant System.Address; - pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_main_1_1"); + pragma Import (C, MCDC_Buffer, "xcov__buf_mcdc__B_z794ac68c_1"); end Buffers_1; -end GCVRT.Pmain_1; +end GCVRT.Pz794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb index c9267341a..d61044bda 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb @@ -1,9 +1,9 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pmain_1;with GCVRT.DB_main_1;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is -GNATcov_Dump_Object:GCVRT.DB_main_1.Dump_Controlled_Type;begin - GNATcov_RTS.Buffers.Witness(GCVRT.Pmain_1.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +GNATcov_Dump_Object:GCVRT.DB_z794ac68b.Dump_Controlled_Type;begin + GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid index 6095ca35ca556f6bbca09c4f490391ed56311f51..8c3a9cf461021af24641eb3efee0b2b8f2eaadff 100644 GIT binary patch delta 22 ecmZo=p2|Go>cq2Btc(l{49t@i8HFc)?*jl(6b9u0 delta 17 ZcmbQr+{!%R>cqQ3lT8=}CbKj40RTKP1_uBD diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb index 12cb696d4..36fee4ed0 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb @@ -1,9 +1,9 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pmain_2;with GCVRT.DB_main_2;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is -GNATcov_Dump_Object:GCVRT.DB_main_2.Dump_Controlled_Type;begin - GNATcov_RTS.Buffers.Witness(GCVRT.Pmain_2.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +GNATcov_Dump_Object:GCVRT.DB_z794ac68c.Dump_Controlled_Type;begin + GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid index 3fcfcade62e7c565dc22596e2c23edea73af3b15..ed362aae294d95988646601009487ef72c0eaa1e 100644 GIT binary patch delta 22 ecmZo=p2|Go>cq2Btc(l{49t@i8HFc)?*jl(6b9u0 delta 17 ZcmbQr+{!%R>cqQ3lT8=}CbKj40RTKP1_uBD diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.adb index 189459c09..f8bb5f57d 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.adb @@ -1,7 +1,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with Ada.Text_IO; use Ada.Text_IO; -with GNATcov_RTS.Buffers;with GCVRT.Ppkg;package body Pkg is +with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package body Pkg is ------------- -- Compute -- @@ -9,10 +9,10 @@ with GNATcov_RTS.Buffers;with GCVRT.Ppkg;package body Pkg is procedure Compute (A, B : Boolean) is MCDC_State_2_Var:GNATcov_RTS.Buffers.MCDC_State_Type:=0;MCDC_State_2:constant GNATCov_RTS.Sys.Address:=MCDC_State_2_Var'Address;begin - GNATcov_RTS.Buffers.Witness(GCVRT.Ppkg.Buffers_2.Statement_Buffer,0);if GNATcov_RTS.Buffers.Witness(GCVRT.Ppkg.Buffers_2.Decision_Buffer,0,1,GCVRT.Ppkg.Buffers_2.MCDC_Buffer,0,MCDC_State_2,GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,TRUE,A )and then GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,FALSE,B ))then - GNATcov_RTS.Buffers.Witness(GCVRT.Ppkg.Buffers_2.Statement_Buffer,1);Put_Line ("true"); + GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,0);if GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Decision_Buffer,0,1,GCVRT.Pz3791e32c.Buffers_2.MCDC_Buffer,0,MCDC_State_2,GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,TRUE,A )and then GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,FALSE,B ))then + GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,1);Put_Line ("true"); else - GNATcov_RTS.Buffers.Witness(GCVRT.Ppkg.Buffers_2.Statement_Buffer,2);Put_Line ("false"); + GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,2);Put_Line ("false"); end if; end Compute; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.ads index d21f49719..aef8a67c2 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.ads @@ -1,5 +1,5 @@ pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers;with GCVRT.Ppkg;package Pkg is +with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package Pkg is procedure Compute (A, B : Boolean); end Pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid index e4e596b22bd020afd704982c155dc2f06629eb22..a394a807e0c4550387cbb6d036b8b7577d3177ae 100644 GIT binary patch delta 38 qcmbQmF^glux5<2r6F8U{7#J9Vc=9|(<;go4m03X?rp-4Q9hm^T)(E8l delta 32 ncmbQmF^gluH&zB9V4NJtBs}rkgvou3%9D38N^icyXvYKqrfCXZ From 1e381f69bec1ec8f4d97b60f466c4cc9c8a41fc8 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 25 Aug 2023 14:44:51 +0200 Subject: [PATCH 0410/1483] Add cxx as a C++ recognized prefix C++ files generated for the CMake configuration are actually suffixed with cxx. Add this as a recognized source file suffix. --- tools/gnatcov/compiler_wrappers-gcc.adb | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 98940e39f..c8d1fb374 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -361,6 +361,7 @@ is if Ends_With (Arg, ".c") or else Ends_With (Arg, ".cc") or else Ends_With (Arg, ".cpp") + or else Ends_With (Arg, ".cxx") then if Length (Result.Filename) = 0 then Result.Filename := +Ada.Directories.Full_Name (+Arg); From f1ab880708f7f39ad7ae448e4efdfcca97d539de Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 25 Aug 2023 15:10:50 +0200 Subject: [PATCH 0411/1483] C/C++ instr: consider other compiler switches for preprocessing We must launch the preprocessing command with all of the switches that can influence the preprocessing of the file. We used to consider macro definition / undefinition and the C/C++ standard set by the -std switch but there are more switches than that (the list is unfortunately probably not exhaustive): -fno-rtti (do not include runtime type information) and all of the warnings switches which can influence the preprocessing through the __has_warning macro. --- .../instr-cov/C++/109-pp-switches/main.cpp | 7 ++++ .../instr-cov/C++/109-pp-switches/test.py | 33 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 30 +++++++---------- tools/gnatcov/instrument-common.adb | 28 +++++++++++----- tools/gnatcov/instrument-common.ads | 7 ++-- 5 files changed, 74 insertions(+), 31 deletions(-) create mode 100644 testsuite/tests/instr-cov/C++/109-pp-switches/main.cpp create mode 100644 testsuite/tests/instr-cov/C++/109-pp-switches/test.py diff --git a/testsuite/tests/instr-cov/C++/109-pp-switches/main.cpp b/testsuite/tests/instr-cov/C++/109-pp-switches/main.cpp new file mode 100644 index 000000000..f9a6743f8 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/109-pp-switches/main.cpp @@ -0,0 +1,7 @@ +#include + +int +main (int argc, char **argv) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/C++/109-pp-switches/test.py b/testsuite/tests/instr-cov/C++/109-pp-switches/test.py new file mode 100644 index 000000000..abf95b554 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/109-pp-switches/test.py @@ -0,0 +1,33 @@ +""" +Check that the instrumenter considers the -fno-rtti switch for preprocessing. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprbuild, gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.cpp"])), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--c++-opts=-fno-rtti"], + extra_gprbuild_cargs=["-fno-rtti"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "*.xcov", + { + "main.cpp.xcov": {"+": {6}}, + }, + "xcov", +) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index b85b0df07..cf697fc10 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -80,15 +80,11 @@ package body Instrument.C is type Macro_Set_Cst_Access is access constant Macro_Set; function Builtin_Macros - (Lang, Compiler, Std, Output_Dir : String) return Macro_Set_Cst_Access; - -- Return the list of built-in macros for the given compiler, standard and - -- language. Output_Dir is used to store a temporary file. - -- - -- Note that we could generate a fully-fledged preprocessor configuration - -- (the standard macros + the command-line defined macros with an - -- additional argument there), but it is more convenient to cache the - -- "light" preprocessor configuration that is determined by the compiler, - -- language and standard only. + (Lang, Compiler, Output_Dir : String; + Compiler_Switches : String_Vectors.Vector) return Macro_Set_Cst_Access; + -- Return the list of built-in macros for the given compiler, language and + -- according to the compiler switches. Output_Dir is used to store a + -- temporary file. procedure Preprocess_Source (Filename : String; @@ -2524,7 +2520,8 @@ package body Instrument.C is -------------------- function Builtin_Macros - (Lang, Compiler, Std, Output_Dir : String) return Macro_Set_Cst_Access + (Lang, Compiler, Output_Dir : String; + Compiler_Switches : String_Vectors.Vector) return Macro_Set_Cst_Access is use Ada.Characters.Handling; @@ -2532,8 +2529,6 @@ package body Instrument.C is Unsigned_64 (Pid_To_Integer (Current_Process_Id)); L : constant String := To_Lower (Lang); - Key : constant Unbounded_String := - +Compiler & " -x " & L & " " & Std; Result : constant Macro_Set_Access := new Macro_Set; Args : String_Vectors.Vector; @@ -2549,9 +2544,7 @@ package body Instrument.C is Args.Append (+"-x"); Args.Append (+L); - if Std'Length /= 0 then - Args.Append (+Std); - end if; + Args.Append (Compiler_Switches); Args.Append (+"-E"); Args.Append (+"-dM"); Args.Append (+"-"); @@ -2559,8 +2552,7 @@ package body Instrument.C is Run_Command (Command => Compiler, Arguments => Args, - Origin_Command_Name => - "getting built-in macros for " & (+Key), + Origin_Command_Name => "gnatcov instrument", Output_File => Filename, In_To_Null => True); @@ -4532,8 +4524,8 @@ package body Instrument.C is Builtin_Macros (Image (C_Family_Language (Instrumenter.Language)), +Prj.Compiler_Driver (Instrumenter.Language), - +Self.Std, - +Prj.Output_Dir).all; + +Prj.Output_Dir, + Self.Compiler_Switches).all; end Import_Options; --------------------------- diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index bec71c658..67c487389 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -473,13 +473,13 @@ package body Instrument.Common is Add_Macro_Switches (Options.PP_Macros); end if; - -- The -std switch also indicates the C/C++ version used, and - -- influences both the configuration of the preprocessor, and the - -- parsing of the file. + -- Add other compiler switches as they may also influence both the + -- configuration of the preprocessor, and the parsing of the file. A + -- non-exhaustive list includes undefining macros through -U switches, + -- using -std to change the C++ standard in use, -fno-rtti to prevent + -- inclusion of runtime type information etc. - if Length (Options.Std) /= 0 then - Args.Append (Options.Std); - end if; + Args.Append (Options.Compiler_Switches); end Add_Options; @@ -638,11 +638,21 @@ package body Instrument.Common is elsif Read_With_Argument (A, 'U', Value) then Self.PP_Macros.Include ((Define => False, Name => Value)); + -- Account for all the switches that can influence the file + -- preprocessing. - elsif Has_Prefix (A, "-std=") then - Self.Std := +A; - end if; + elsif Has_Prefix (A, "-std") + or else Has_Prefix (A, "-fno-rtti") + or else Has_Prefix (A, "-fno-exceptions") + -- All the warning switches can influence the preprocessing + -- through the use of the __has_warning macro, e.g. + -- #if __has_warning("-Wimplicit-fallthrough") + + or else Has_Prefix (A, "-W") + then + Self.Compiler_Switches.Append (+A); + end if; I := I + 1; end; end loop; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index d40bc56fb..e618965d4 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -552,9 +552,10 @@ package Instrument.Common is PP_Macros : Macro_Set; -- Set of macros for the preprocessor - Std : Unbounded_String; - -- -std=X argument to pass to the preprocessor and the parser, or the - -- empty string. + Compiler_Switches : String_Vectors.Vector; + -- List of compiler switches that can influence the file preprocessing. + -- The list should be amended alongside our discoveries. It is + -- currently: -std, -fno-exceptions, -fno-rtti, -W* switches. end record; -- Options to analyze (preprocess and/or parse) a compilation unit From 21f5650694974e955875b77c95285d5af5c9a159 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 14 Sep 2023 12:27:53 +0200 Subject: [PATCH 0412/1483] Instrument.C: fix instrumentation when no SCO can be instrumented gnatcov used to crash when instrumenting source code that consisted solely of non-instrumentable constructs. This was due to an implicit assumption that every source of interest should be present in the UIC.Instrumented_Entities map, which wasn't the case in this scenario. Fix the code to ensure the assumption's validity. --- testsuite/tests/C++/mcdc/ConstExpr/src/pkg.hh | 5 +++ .../C++/mcdc/ConstExpr/src/test_constexpr.cpp | 2 ++ tools/gnatcov/instrument-c.adb | 33 ++++++++++++------- tools/gnatcov/instrument-c.ads | 6 ++-- 4 files changed, 32 insertions(+), 14 deletions(-) create mode 100644 testsuite/tests/C++/mcdc/ConstExpr/src/pkg.hh diff --git a/testsuite/tests/C++/mcdc/ConstExpr/src/pkg.hh b/testsuite/tests/C++/mcdc/ConstExpr/src/pkg.hh new file mode 100644 index 000000000..57a467c98 --- /dev/null +++ b/testsuite/tests/C++/mcdc/ConstExpr/src/pkg.hh @@ -0,0 +1,5 @@ +constexpr int +bar () +{ + return 0; // # ce-header +} diff --git a/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp b/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp index e6d8a31a6..0d670ddf7 100644 --- a/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp +++ b/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp @@ -1,3 +1,5 @@ +#include "pkg.hh" + constexpr int foo () { diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index cf697fc10..d23e14f33 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -896,6 +896,17 @@ package body Instrument.C is Pragma_Aspect_Name : Name_Id := Namet.No_Name) is begin + -- Insert a new entry to the UIC.Instrumented_Entities maps: even if + -- this SOI does not possess instrumented SCOs (it can be the case if + -- all of the code constructs are not instrumentable), we want an empty + -- Instrumented_Entities entry rather than no entry at all, to have + -- proper initialization of checkpoints structures (e.g. Statement_Bits) + -- later on. + + if not UIC.Instrumented_Entities.Contains (From.Source_File) then + UIC.Instrumented_Entities.Insert (From.Source_File, (others => <>)); + end if; + Append_SCO (C1, C2, From.L, To.L, From.Source_File, Last, Pragma_Aspect_Name); @@ -950,13 +961,9 @@ package body Instrument.C is SFI : Valid_Source_File_Index) return C_Instrumented_Entities_Maps.Reference_Type is - use C_Instrumented_Entities_Maps; - Cur : Cursor; Dummy : Boolean; begin - UIC.Instrumented_Entities.Insert - (SFI, (others => <>), Cur, Dummy); - return UIC.Instrumented_Entities.Reference (Cur); + return UIC.Instrumented_Entities.Reference (SFI); end Find_Instrumented_Entities; ----------------------- @@ -3185,7 +3192,7 @@ package body Instrument.C is UIC.Allocated_Bits.Reference (Ent.Buffers_Index); Bit_Maps : CU_Bit_Maps; begin - -- Allocate bits in covearge buffers and insert the + -- Allocate bits in coverage buffers and insert the -- corresponding witness calls. for SS of Ent.Statements loop @@ -4567,11 +4574,15 @@ package body Instrument.C is -- switches. if UIC.Files_Of_Interest.Contains (File) then - SOI := - (Of_Interest => True, - SFI => Get_Index_From_Generic_Name - (+File, Source_File), - CU_Name => CU_Name_For_File (File)); + declare + SFI : constant Source_File_Index := + Get_Index_From_Generic_Name (+File, Source_File); + begin + SOI := + (Of_Interest => True, + SFI => SFI, + CU_Name => CU_Name_For_File (File)); + end; else SOI := (Of_Interest => False); end if; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 339d094a7..58253690f 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -397,10 +397,10 @@ private function Find_Instrumented_Entities (UIC : in out C_Unit_Inst_Context'Class; SFI : Valid_Source_File_Index) - return C_Instrumented_Entities_Maps.Reference_Type; + return C_Instrumented_Entities_Maps.Reference_Type + with Pre => UIC.Instrumented_Entities.Contains (SFI); -- Return a reference to the UIC.Instrumented_Entities entry - -- corresponding to the source file that SFI designates. If there is no - -- such entry yet, create it. + -- corresponding to the source file that SFI designates. type Pass_Kind is abstract tagged null record; From 6b6bc30ad4d70de4db24129ba7acc0706139b876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 21 Dec 2022 09:58:06 +0100 Subject: [PATCH 0413/1483] Implement first two levels of assertion coverage This change adds the possibility of computing the coverage of assertions and contracts for levels: * ATC (Assertion True Coverage): an assertion is covered if its whole decision has been evaluated to True at least once. * ATCC (Assertion True Condition Coverage): and assertion is covered if every condition of the decision has been evaluated at least once in the context of an evaluation to True of the whole decision. The relevant assertions and contracts are Assert, Assert_And_Cut, Assume, Check, Loop_Invariant, Type_Invariant, Precondition, Postcondition. The only unsupported cases are Pre/Postcondition and Type_Invariant as pragma statements which are not instrumented. A warning is issued stating as much, and the rest of the code is instrumented as normal. Issue: #7 TN: O212-062 --- testsuite/SCOV/internals/cnotes.py | 15 +- testsuite/SCOV/internals/driver.py | 44 ++ testsuite/SCOV/internals/rnexpanders.py | 25 +- testsuite/SCOV/internals/xnexpanders.py | 30 +- testsuite/SCOV/internals/xnotep.py | 4 +- testsuite/SCOV/report.py | 14 +- testsuite/SCOV/tc.py | 32 +- .../O212-062-assertions/src/assertions.adb | 59 +++ .../O212-062-assertions/src/assertions.ads | 17 + .../O212-062-assertions/src/assertions_0.adb | 39 ++ .../O212-062-assertions/src/assertions_1.adb | 18 + .../O212-062-assertions/src/assertions_2.adb | 16 + .../O212-062-assertions/src/assertions_3.adb | 18 + .../O212-062-assertions/src/expr_func.adb | 29 ++ .../src/pack_type_invariant.ads | 22 + .../tests/O212-062-assertions/src/pragmas.adb | 27 + .../src/test_assertions_0.adb | 34 ++ .../src/test_assertions_1.adb | 31 ++ .../src/test_assertions_2.adb | 30 ++ .../src/test_assertions_3.adb | 13 + .../src/test_expr_func.adb | 18 + .../O212-062-assertions/src/test_pragmas.adb | 18 + .../src/test_type_inv_false.adb | 25 + .../src/test_type_inv_null.adb | 11 + .../src/test_type_inv_true.adb | 18 + testsuite/tests/O212-062-assertions/test.opt | 1 + testsuite/tests/O212-062-assertions/test.py | 8 + .../gen/arm-elf-linux/main_1.sid | Bin 403 -> 405 bytes .../gen/arm-elf-linux/main_2.sid | Bin 403 -> 405 bytes .../gen/arm-elf-linux/pkg.sid | Bin 1046 -> 1048 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1838 -> 1850 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1848 -> 1860 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 1979 -> 1993 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 1915 -> 1929 bytes .../gen/x86_64-windows/main_1.sid | Bin 405 -> 407 bytes .../gen/x86_64-windows/main_2.sid | Bin 405 -> 407 bytes .../gen/x86_64-windows/pkg.sid | Bin 1050 -> 1052 bytes .../O212-062-unsupported-pragmas/main.adb | 13 + .../pkg_type_invariant.ads | 24 + .../O212-062-unsupported-pragmas/test.opt | 1 + .../O212-062-unsupported-pragmas/test.py | 43 ++ tools/gnatcov/annotations-report.adb | 75 ++- tools/gnatcov/annotations.adb | 104 ++-- tools/gnatcov/annotations.ads | 6 + tools/gnatcov/command_line.ads | 16 +- tools/gnatcov/coverage-source.adb | 460 ++++++++++++++---- tools/gnatcov/coverage-source.ads | 5 + tools/gnatcov/coverage.adb | 23 + tools/gnatcov/coverage.ads | 11 +- tools/gnatcov/coverage_options.adb | 74 ++- tools/gnatcov/coverage_options.ads | 18 +- tools/gnatcov/files_table.ads | 22 +- tools/gnatcov/gnatcov_bits_specific.adb | 7 +- tools/gnatcov/instrument-ada_unit.adb | 297 ++++++++--- tools/gnatcov/instrument-ada_unit.ads | 8 + tools/gnatcov/instrument-common.adb | 3 +- tools/gnatcov/sc_obligations.adb | 115 +++-- tools/gnatcov/sc_obligations.ads | 27 +- tools/gnatcov/switches.ads | 10 +- tools/gnatcov/traces_stats.adb | 2 + 60 files changed, 1669 insertions(+), 311 deletions(-) create mode 100644 testsuite/tests/O212-062-assertions/src/assertions.adb create mode 100644 testsuite/tests/O212-062-assertions/src/assertions.ads create mode 100644 testsuite/tests/O212-062-assertions/src/assertions_0.adb create mode 100644 testsuite/tests/O212-062-assertions/src/assertions_1.adb create mode 100644 testsuite/tests/O212-062-assertions/src/assertions_2.adb create mode 100644 testsuite/tests/O212-062-assertions/src/assertions_3.adb create mode 100644 testsuite/tests/O212-062-assertions/src/expr_func.adb create mode 100644 testsuite/tests/O212-062-assertions/src/pack_type_invariant.ads create mode 100644 testsuite/tests/O212-062-assertions/src/pragmas.adb create mode 100644 testsuite/tests/O212-062-assertions/src/test_assertions_0.adb create mode 100644 testsuite/tests/O212-062-assertions/src/test_assertions_1.adb create mode 100644 testsuite/tests/O212-062-assertions/src/test_assertions_2.adb create mode 100644 testsuite/tests/O212-062-assertions/src/test_assertions_3.adb create mode 100644 testsuite/tests/O212-062-assertions/src/test_expr_func.adb create mode 100644 testsuite/tests/O212-062-assertions/src/test_pragmas.adb create mode 100644 testsuite/tests/O212-062-assertions/src/test_type_inv_false.adb create mode 100644 testsuite/tests/O212-062-assertions/src/test_type_inv_null.adb create mode 100644 testsuite/tests/O212-062-assertions/src/test_type_inv_true.adb create mode 100644 testsuite/tests/O212-062-assertions/test.opt create mode 100644 testsuite/tests/O212-062-assertions/test.py create mode 100644 testsuite/tests/instr-cov/O212-062-unsupported-pragmas/main.adb create mode 100644 testsuite/tests/instr-cov/O212-062-unsupported-pragmas/pkg_type_invariant.ads create mode 100644 testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt create mode 100644 testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py diff --git a/testsuite/SCOV/internals/cnotes.py b/testsuite/SCOV/internals/cnotes.py index 4b15733cb..12abf372c 100644 --- a/testsuite/SCOV/internals/cnotes.py +++ b/testsuite/SCOV/internals/cnotes.py @@ -126,6 +126,11 @@ # cPartCov : independent effect of condition not demonstrated (=report) +# aNoCov : assertion never evaluated (=report) +# atNoCov : assertion expression outcome TRUE never evaluated (=report) +# acPartCov : assertion condition was never evaluated during an evaluation of +# the decision to True (=report) + # xBlock0 : exempted block, 0 deviations (=report) # xBlock1 : exempted block, >0 deviations (=report) # xBlock2 : exempted block, >0 undetermined coverage items (=report) @@ -168,8 +173,9 @@ XotNoCov, XofNoCov, XoPartCov, XoNoCov, XcPartCov, Xr0, Xr0c, + aNoCov, atNoCov, acPartCov, blockNote, - xBlock0, xBlock1, xBlock2) = range(50) + xBlock0, xBlock1, xBlock2) = range(53) NK_image = {None: "None", lNoCode: "lNoCode", lNotCoverable: "lNotCoverable", @@ -192,7 +198,8 @@ XotNoCov: "XotNoCov", XofNoCov: "XofNoCov", XoPartCov: "XoPartCov", XoNoCov: "XoNoCov", XcPartCov: "XcPartCov", - Xr0: "Xr0", Xr0c: "Xr0c"} + Xr0: "Xr0", Xr0c: "Xr0c", + aNoCov: "aNoCov", atNoCov: "atNoCov", acPartCov: "acPartCov"} # =============================== @@ -221,6 +228,9 @@ # MCDC violations cNoteKinds = (etNoCov, efNoCov, ePartCov, eNoCov, cPartCov, eUndetCov) +# Assertion violations +aNoteKinds = (aNoCov, atNoCov, acPartCov) + # Exemption regions xNoteKinds = (xBlock0, xBlock1, xBlock2) @@ -247,6 +257,7 @@ # if they could be emitted and report them as unmatched. erNoteKinds = sNoteKinds+dNoteKinds+cNoteKinds+xNoteKinds+tNoteKinds+XNoteKinds +erNoteKinds += aNoteKinds xrNoteKinds = erNoteKinds+rAntiKinds+XrAntiKinds diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 137910f0f..782e37400 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -936,6 +936,13 @@ def check_expectations(self): "stmt+decision": 2, "stmt+mcdc": 3, "stmt+uc_mcdc": 3, + "stmt+atc": 1, + "stmt+decision+atc": 2, + "stmt+decision+atcc": 2, + "stmt+mcdc+atc": 3, + "stmt+mcdc+atcc": 3, + "stmt+uc_mcdc+atc": 3, + "stmt+uc_mcdc+atcc": 3, } stricter_level = ( @@ -1164,6 +1171,43 @@ def _scofiles_list(self): for soi in self.sources_of_interest()) if scof} + def wdbase_for(self, covlevel): + """ + Compute a short base prefix for the working directory that will + contain the output of coverage analysis for level covlevel. + + Uses the first letter of the highest level ('s' for "stmt" or 'u' for + "stmt+uc_mcdc") and the full name of the assertion level if assertion + coverage is enabled. + """ + levels = covlevel.split("+") + + if len(levels) == 1: + return "s_" + + wdbase = levels[1][0] + wdbase += levels[-1] if self.assert_lvl else "" + + return wdbase + "_" + + def xcovlevel_for(self, wdname): + """ + Compute the source coverage level from the working directory prefix + by matching the first letter of the highest coverage level plus the + full name of the assertion level is enabled. + """ + res = "stmt" + wdbase = wdname.split('_')[0] + + for lvl in ["decision", "mcdc", "uc_mcdc"]: + if wdbase[0] == lvl[0]: + res += "+" + lvl + + if len(wdbase) > 1: + res += "+" + wdbase[1:] + + return res + class SCOV_helper_bin_traces(SCOV_helper): """SCOV_helper specialization for the binary execution trace based mode.""" diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index 9f59d580d..99f82a18b 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -11,9 +11,10 @@ from .cnotes import ( xBlock0, xBlock1, sNoCov, sPartCov, sNotCoverable, dfAlways, dtAlways, dfNoCov, dtNoCov, dNoCov, dPartCov, efNoCov, etNoCov, eNoCov, ePartCov, - cPartCov, Enote, KnoteDict, erNoteKinds, sUndetCov, dUndetCov, eUndetCov, - xBlock2, XsNoCov, XsPartCov, XsNotCoverable, XsUndetCov, XotNoCov, - XofNoCov, XoPartCov, XoNoCov, XcPartCov + cPartCov, aNoCov, atNoCov, acPartCov, Enote, KnoteDict, erNoteKinds, + sUndetCov, dUndetCov, eUndetCov, xBlock2, XsNoCov, XsPartCov, + XsNotCoverable, XsUndetCov, XotNoCov, XofNoCov, XoPartCov, XoNoCov, + XcPartCov ) from .segments import Sloc, Sloc_from_match from .stags import Stag_from @@ -79,7 +80,6 @@ def __init__(self, sloc, diag): def Rdiagline_from(text): - p = re.match(Rdiagline.re, text) return Rdiagline(sloc=Sloc_from_match(p), @@ -207,7 +207,6 @@ def __init__(self, re_notes): self.enotes = [] def try_parse_enote(self, rline): - dline = Rdiagline_from(rline) # If no match at all, punt. @@ -570,6 +569,22 @@ def __init__(self): self.noteblocks.append( VIOsection(re_start="MCDC COVERAGE", re_notes=mcdc_notes)) + # Assertion coverage + + atc_notes = { + "contract expression outcome TRUE never": atNoCov, + "contract expression never evaluated": aNoCov, + } + self.noteblocks.append( + VIOsection(re_start="ATC COVERAGE", re_notes=atc_notes)) + + atcc_notes = { + "condition was never evaluated during an evaluation of the " + "decision to True": acPartCov + } + self.noteblocks.append( + VIOsection(re_start="ATCC COVERAGE", re_notes=atcc_notes)) + # Non coverable items nc_notes = { diff --git a/testsuite/SCOV/internals/xnexpanders.py b/testsuite/SCOV/internals/xnexpanders.py index 68c576cb7..b60ccac69 100644 --- a/testsuite/SCOV/internals/xnexpanders.py +++ b/testsuite/SCOV/internals/xnexpanders.py @@ -1203,10 +1203,25 @@ def __decode_note_choice(self, text): or [('stmt', 'l+'), ('stmt+decision', 'l+')] """ - level_from_char = {"s": "stmt", - "d": "stmt+decision", - "m": "stmt+mcdc", - "u": "stmt+uc_mcdc"} + level_from_char = {"s": ["stmt"], + "d": ["stmt+decision"], + "m": ["stmt+mcdc"], + "u": ["stmt+uc_mcdc"]} + + def make_assert_lvl_combinaison(assert_lvl): + """ + Add the assertion coverage level assert_lvl to other regular + coverage level combinaisons defined in level_from_char. Return the + list of combinaisons. + """ + return [level_from_char[c][0] + "+" + assert_lvl + for c in level_from_char] + + assert_level_from_char = {"a": make_assert_lvl_combinaison("atc"), + "c": make_assert_lvl_combinaison("atcc")} + + level_from_char.update(assert_level_from_char) + result = text.split("=>") if len(result) == 1: @@ -1220,7 +1235,12 @@ def __decode_note_choice(self, text): note = result[1].lstrip(' ') lev_list = result[0].rstrip(' ') - return [(level_from_char[lchar], note) for lchar in lev_list] + res = [] + for lchar in lev_list: + for combinaison in level_from_char[lchar]: + res.append((combinaison, note)) + + return res def __select_lnote(self, text): """Decode text to return the line note for the current diff --git a/testsuite/SCOV/internals/xnotep.py b/testsuite/SCOV/internals/xnotep.py index 6ce7343b5..78da96485 100644 --- a/testsuite/SCOV/internals/xnotep.py +++ b/testsuite/SCOV/internals/xnotep.py @@ -18,7 +18,8 @@ oPartCov, ofNoCov, otNoCov, r0, r0c, sNoCov, sNotCoverable, sPartCov, xBlock0, xBlock1, xBlock2, xNoteKinds, lUndetCov, sUndetCov, dUndetCov, eUndetCov, XsNoCov, XsPartCov, XsNotCoverable, XsUndetCov, XotNoCov, - XofNoCov, XoPartCov, XoNoCov, XcPartCov, Xr0, Xr0c + XofNoCov, XoPartCov, XoNoCov, XcPartCov, Xr0, Xr0c, aNoCov, atNoCov, + acPartCov ) from .segments import Line, Section, Segment from .stags import Stag_from @@ -181,6 +182,7 @@ class XnoteP: 'e?': eUndetCov, 'oT-': otNoCov, 'oF-': ofNoCov, 'o!': oPartCov, 'o-': oNoCov, 'c!': cPartCov, + 'a-': aNoCov, 'aT-': atNoCov, 'ac!': acPartCov, 'x0': xBlock0, 'x+': xBlock1, 'x?': xBlock2, '0': r0, '0c': r0c, # Exempted notes diff --git a/testsuite/SCOV/report.py b/testsuite/SCOV/report.py index 4e2716c0a..fff84aa5a 100644 --- a/testsuite/SCOV/report.py +++ b/testsuite/SCOV/report.py @@ -16,6 +16,7 @@ from e3.fs import ls +from SCOV.internals.driver import SCOV_helper from SCOV.internals.cnotes import xNoteKinds from SCOV.internals.tfiles import Tfile from SUITE.tutils import XCOV, thistest, frame @@ -139,15 +140,6 @@ def check(self): "stmt+uc_mcdc": ["STMT", "DECISION", "MCDC"] } -# Base prefix of the working subdirectory for each xcovlevel. ??? This is -# relying too much on knowledge about how the testuite driver works ... -xcovlevel_from = { - "sc_": "stmt", - "dc_": "stmt+decision", - "mc_": "stmt+mcdc", - "uc_": "stmt+uc_mcdc" -} - class ReportChecker: """Whole report checker""" @@ -301,7 +293,9 @@ def __process_one_test(self, qde): # applicable xcov-level self.__setup_expectations( ntraces=len(qde.drivers), - xcovlevel=xcovlevel_from[os.path.basename(qde.wdir)[0:3]], + xcovlevel=SCOV_helper.xcovlevel_for(self.tc, + os.path.basename + (qde.wdir)), xregions=xregions) reports = ls(os.path.join(qde.wdir, "test.rep")) diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index f8ece4bd4..1c8a7b375 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -124,7 +124,7 @@ def __drivers_from(self, cspec): return [drv for drv in self.all_drivers if re.search(drv_expr, drv)] def __init__(self, extradrivers="", extracargs="", category=CAT.auto, - tolerate_messages=None): + tolerate_messages=None, assert_lvl=None): # By default, these test cases expect no error from subprocesses (xrun, # xcov, etc.) self.expect_failures = False @@ -171,6 +171,8 @@ def __init__(self, extradrivers="", extracargs="", category=CAT.auto, if category == CAT.auto else category) + self.assert_lvl = assert_lvl + # - extra compilation arguments, added to what --cargs was provided to # the testsuite command line: self.extracargs = extracargs @@ -191,19 +193,24 @@ def __xcovlevels(self): if thistest.options.xcov_level: return [thistest.options.xcov_level] + assert not thistest.options.qualif_level + default_xcovlevels_for = { # Tests without categories should be ready for anything. # Exercise with the strictest possible mode: - None: ["stmt+mcdc"], + None: ["stmt+mcdc"], - CAT.stmt: ["stmt"], + CAT.stmt: ["stmt"], CAT.decision: ["stmt+decision"], - CAT.mcdc: ["stmt+mcdc", "stmt+uc_mcdc"]} + CAT.mcdc: ["stmt+mcdc", "stmt+uc_mcdc"], + } - defaults = default_xcovlevels_for[self.category] - return ([defaults[0]] - if thistest.options.qualif_level else - defaults) + # Add a "+" before the name of the assertion coverage level in order + # to append it at the end of the the other specified coverage levels + # passed to gnatcov. + alvl = ("+" + self.assert_lvl) if self.assert_lvl else "" + + return [d + alvl for d in default_xcovlevels_for[self.category]] def __register_qde_for(self, drvo): """ @@ -215,13 +222,6 @@ def __register_qde_for(self, drvo): drivers=drvo.drivers, xrnotes=drvo.xrnotes, wdir=os.path.normpath(drvo.awdir()))) - # Base prefix for Working directories, per --level. Shared across - # runs for multiples levels. - _wdbase_for = {"stmt": "st_", - "stmt+decision": "dc_", - "stmt+mcdc": "mc_", - "stmt+uc_mcdc": "uc_"} - def __run_one_covlevel(self, covlevel, covcontrol, subdirhint): """ Run this testcase individual drivers and consolidation tests with @@ -236,7 +236,7 @@ def __run_one_covlevel(self, covlevel, covcontrol, subdirhint): # Compute the Working directory base for this level, then run the test # for each indivdual driver. - this_wdbase = self._wdbase_for[covlevel] + this_wdbase = this_scov_helper.wdbase_for(self, covlevel) wdctl = WdirControl(wdbase=this_wdbase, bdbase=self._available_bdbase, subdirhint=subdirhint) diff --git a/testsuite/tests/O212-062-assertions/src/assertions.adb b/testsuite/tests/O212-062-assertions/src/assertions.adb new file mode 100644 index 000000000..c9d7d43c5 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/assertions.adb @@ -0,0 +1,59 @@ +pragma Assertion_Policy (Check); +pragma Ada_2012; + +package body Assertions is + + --------- + -- Foo -- + --------- + + function Foo (I : Integer) return Integer + is + High : Integer := 3; -- # foo_hi_decl + begin + for J in 1 .. High loop -- # foo_loop_1 + pragma Loop_Invariant (J = J + 1 - 1 and then J < 4); -- # foo_inv_1 + end loop; + + for J in 1 .. High loop -- # foo_loop_2 + pragma Loop_Invariant (J = J + 1 - 1 or else J < 4); -- # foo_inv_2 + end loop; + return I; -- # foo_return + end Foo; + + ---------- + -- Same -- + ---------- + + function Same (A, B : Boolean) return Boolean + is + -- Subprogram body with aspect without prior declaration + + function Id (C : Boolean) return Boolean + with Pre => C or else (C or else not C), -- # id_pre + Post => Id'Result = C -- # id_post + is + begin + return C; -- # id_ret + end Id; + + begin + -- Decision nested as parameter of a function call within an assertion. + -- The function parameter should not be seen as a condition for the + -- assertion decision. + + -- Last two conditions are not evaluated + + pragma Assert (Id (A or else B) or else A or else B); -- # nested_1 + + -- Last condition is not evaluated + + pragma Assert (B or else A or else Id (A or else B)); -- # nested_2 + + -- All conditions are evaluated + + pragma Assert (B or else Id (A or else B)); -- # nested_3 + return B; -- # same_ret + end Same; + +end Assertions; diff --git a/testsuite/tests/O212-062-assertions/src/assertions.ads b/testsuite/tests/O212-062-assertions/src/assertions.ads new file mode 100644 index 000000000..db579b9d6 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/assertions.ads @@ -0,0 +1,17 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Assertions is + + function Foo (I : Integer) return Integer + with Pre => (I >= 0 and then False) or else I >= 0, -- # foo_pre + Post => (I = Foo'Result or else Foo'Result /= 42); -- # foo_post + + function Bar (I : Integer) return Integer is (I) -- # bar_expr + with Pre => (I < 0 or else I >= 0) or else (I = 42); -- # bar_pre + + function Baz (I : Integer) return Integer is (I); -- # baz_expr + + function Same (A, B : Boolean) return Boolean; + +end Assertions; diff --git a/testsuite/tests/O212-062-assertions/src/assertions_0.adb b/testsuite/tests/O212-062-assertions/src/assertions_0.adb new file mode 100644 index 000000000..9e1643f4c --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/assertions_0.adb @@ -0,0 +1,39 @@ +pragma Assertion_Policy (Check); + +with Assertions; use Assertions; + +procedure Assertions_0 +is + X : Integer := 0; + Y : Integer := X; + A : Boolean := True; + B : Boolean := False; +begin + -- The last condition is not evaluated + + pragma Assert ((X = 0 or else A) or else X = 0); -- # assert_1 + + -- Call a function. Evaluate all conditions of the precondition; + -- evaluate only the first condition of the postcondition. The first + -- loop invariant is entirely covered while the last condition of the + -- second loop invariant is not evaluated. + + Y := Foo (0); -- # foo_0 + + -- The if's decision is False, so the statement contained is not executed + + if X /= 0 then -- # if_false + pragma Assert (X /= 0 or else False); -- # assert_2 + null; -- # null + end if; + + -- Call an expression function with a precondition of which the last + -- condition is not evaluated. + + Y := Bar (0); -- # bar_0 + + -- Call to function with an aspect defined with the function body. + + A := Same (A, B); + +end Assertions_0; diff --git a/testsuite/tests/O212-062-assertions/src/assertions_1.adb b/testsuite/tests/O212-062-assertions/src/assertions_1.adb new file mode 100644 index 000000000..11a1d585b --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/assertions_1.adb @@ -0,0 +1,18 @@ +pragma Assertion_Policy (Check); + +with Ada.Assertions; +with Assertions; use Assertions; + +procedure Assertions_1 +is + X : Integer := 1; +begin + begin + -- This assertion fails, all conditions are evaluated + + pragma Assert (Baz (X) = 1 or else X /= 0); -- # assert_3 + null; -- # null + exception + when Ada.Assertions.Assertion_Error => null; -- # catch_1 + end; +end Assertions_1; diff --git a/testsuite/tests/O212-062-assertions/src/assertions_2.adb b/testsuite/tests/O212-062-assertions/src/assertions_2.adb new file mode 100644 index 000000000..3402f6b39 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/assertions_2.adb @@ -0,0 +1,16 @@ +with Ada.Assertions; +with Assertions; use Assertions; + +procedure Assertions_2 +is + Y : Integer := 2; +begin + begin + -- Call to Foo with a parameter that does not satisfy the + -- precondition. + + Y := Foo (-2); -- # foo_2 + exception + when Ada.Assertions.Assertion_Error => null; -- # catch_2 + end; +end Assertions_2; diff --git a/testsuite/tests/O212-062-assertions/src/assertions_3.adb b/testsuite/tests/O212-062-assertions/src/assertions_3.adb new file mode 100644 index 000000000..116b78d19 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/assertions_3.adb @@ -0,0 +1,18 @@ +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +procedure Assertions_3 is +begin + declare + High : Integer := 3; -- # high_decl + begin + -- Failed loop invariant + + for J in 1 .. High loop -- # loop_3 + pragma Loop_Invariant (High < 0); -- # loop_inv + end loop; + exception + when Ada.Assertions.Assertion_Error => null; -- # catch_3 + end; +end Assertions_3; diff --git a/testsuite/tests/O212-062-assertions/src/expr_func.adb b/testsuite/tests/O212-062-assertions/src/expr_func.adb new file mode 100644 index 000000000..c0a4674ba --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/expr_func.adb @@ -0,0 +1,29 @@ +pragma Assertion_Policy (Check); +pragma Ada_2012; + +with Ada.Assertions; + +procedure Expr_Func +is + -- Expression function without a prior declaration. + function Foo (X : Integer) return Integer is (X) -- # foo_decl + with Pre => X >= 0, -- # foo_pre + Post => Foo'Result = X; -- # foo_post + + -- Expression function with aspects on prior declaration + function Bar (X : Integer) return Integer + with Pre => X > 0, -- # bar_pre + Post => Bar'Result = X and then X = 0; -- # bar_post + + function Bar (X : Integer) return Integer is (X); -- # bar_def + + Dummy : Integer; -- # dummy_decl +begin + Dummy := Foo (0); -- # foo_call + + begin + Dummy := Bar (42); -- # bar_call + exception + when Ada.Assertions.Assertion_Error => null; -- # catch + end; +end Expr_Func; diff --git a/testsuite/tests/O212-062-assertions/src/pack_type_invariant.ads b/testsuite/tests/O212-062-assertions/src/pack_type_invariant.ads new file mode 100644 index 000000000..e9430ebf3 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/pack_type_invariant.ads @@ -0,0 +1,22 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Pack_Type_Invariant is + + type Bool_Record_1 is private; -- # type_dec_1 + + function Make_Bool_Record_1 (B : Boolean) return Bool_Record_1; +private + + -- Type invariant as aspect + type Bool_Record_1 is -- # type_def_1 + record -- # rec_1 + B : Boolean := True; -- # rec_1 + end record -- # rec_1 + with Type_Invariant => B; -- # type_inv_1 + + function Make_Bool_Record_1 (B : Boolean) return Bool_Record_1 is + ((B => B)); -- # func_ret_1 + +end Pack_Type_Invariant; + diff --git a/testsuite/tests/O212-062-assertions/src/pragmas.adb b/testsuite/tests/O212-062-assertions/src/pragmas.adb new file mode 100644 index 000000000..128144cf2 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/pragmas.adb @@ -0,0 +1,27 @@ +pragma Assertion_Policy (Check); +pragma Ada_2012; + +with Ada.Assertions; + +procedure Pragmas (T : Boolean := True; F : Boolean := False) +is + function Id (B : Boolean) return Boolean is (B); -- # id +begin + begin + -- Pass + pragma Assume (T and then (F or else T)); -- # assume + + pragma Check (Precondition, F or else not T or else T); -- # c_pre + pragma Check (Postcondition, not Id (F)); -- # c_post + pragma Check (Type_Invariant, T or else Id (T)); -- # c_ti + pragma Check (Invariant, T); -- # c_inv + pragma Check (Assertion, T or else T); -- # c_assert + + pragma Assert_And_Cut (T or else (F or else T)); -- # cut + + -- Fail + pragma Assume (Id (F) or else F); -- # fail + exception + when Ada.Assertions.Assertion_Error => null; -- # catch + end; +end Pragmas; diff --git a/testsuite/tests/O212-062-assertions/src/test_assertions_0.adb b/testsuite/tests/O212-062-assertions/src/test_assertions_0.adb new file mode 100644 index 000000000..c5e94b29b --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/test_assertions_0.adb @@ -0,0 +1,34 @@ +with Assertions_0; + +procedure Test_Assertions_0 is +begin + Assertions_0; +end Test_Assertions_0; + +--# assertions.ads +-- /foo_pre/ l+ ## 0 +-- /foo_post/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /bar_expr/ l+ ## 0 +-- /bar_pre/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /baz_expr/ l- ## s- +--# assertions.adb +-- /foo_hi_decl/ l+ ## 0 +-- /foo_loop_1/ l+ ## 0 +-- /foo_inv_1/ l+ ## 0 +-- /foo_loop_2/ l+ ## 0 +-- /foo_inv_2/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /foo_return/ l+ ## 0 +-- /id_pre/ a=>l+, c=>l! ## a=>0, c=> ac! +-- /id_post/ l+ ## 0 +-- /id_ret/ l+ ## 0 +-- /nested_1/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /nested_2/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /nested_3/ l+ ## 0 +-- /same_ret/ l+ ## 0 +-- # assertions_0.adb +-- /assert_1/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /foo_0/ l+ ## 0 +-- /if_false/ l! ## dT- +-- /assert_2/ l- ## s- +-- /null/ l- ## s- +-- /bar_0/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/test_assertions_1.adb b/testsuite/tests/O212-062-assertions/src/test_assertions_1.adb new file mode 100644 index 000000000..fcc020584 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/test_assertions_1.adb @@ -0,0 +1,31 @@ +with Assertions_1; + +procedure Test_Assertions_1 is +begin + Assertions_1; +end Test_Assertions_1; + +--# assertions.ads +-- /foo_pre/ l- ## a- +-- /foo_post/ l- ## a- +-- /bar_expr/ l- ## s- +-- /bar_pre/ l- ## a- +-- /baz_expr/ l+ ## 0 +--# assertions.adb +-- /foo_hi_decl/ l- ## s- +-- /foo_loop_1/ l- ## s- +-- /foo_inv_1/ l- ## s- +-- /foo_loop_2/ l- ## s- +-- /foo_inv_2/ l- ## s- +-- /foo_return/ l- ## s- +-- /id_pre/ l- ## a- +-- /id_post/ l- ## a- +-- /id_ret/ l- ## s- +-- /nested_1/ l- ## s- +-- /nested_2/ l- ## s- +-- /nested_3/ l- ## s- +-- /same_ret/ l- ## s- +-- # assertions_1.adb +-- /assert_3/ a=>l+, c=>l! ## a=>0, c=>aT- +-- /null/ l+ ## 0 +-- /catch_1/ l- ## s- diff --git a/testsuite/tests/O212-062-assertions/src/test_assertions_2.adb b/testsuite/tests/O212-062-assertions/src/test_assertions_2.adb new file mode 100644 index 000000000..8af1b7f80 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/test_assertions_2.adb @@ -0,0 +1,30 @@ +with Assertions_2; + +procedure Test_Assertions_2 is +begin + Assertions_2; +end Test_Assertions_2; + +--# assertions.ads +-- /foo_pre/ l- ## a- +-- /foo_post/ l- ## a- +-- /bar_expr/ l- ## s- +-- /bar_pre/ l- ## aT- +-- /baz_expr/ l- ## s- +--# assertions.adb +-- /foo_hi_decl/ l- ## s- +-- /foo_loop_1/ l- ## s- +-- /foo_inv_1/ l- ## s- +-- /foo_loop_2/ l- ## s- +-- /foo_inv_2/ l- ## s- +-- /foo_return/ l- ## s- +-- /id_pre/ l- ## a- +-- /id_post/ l- ## a- +-- /id_ret/ l- ## s- +-- /nested_1/ l- ## s- +-- /nested_2/ l- ## s- +-- /nested_3/ l- ## s- +-- /same_ret/ l- ## s- +--# assertions_2.adb +-- /foo_2/ l+ ## c! +-- /catch_2/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/test_assertions_3.adb b/testsuite/tests/O212-062-assertions/src/test_assertions_3.adb new file mode 100644 index 000000000..ea53dbaf0 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/test_assertions_3.adb @@ -0,0 +1,13 @@ +with Assertions_3; + +procedure Test_Assertions_3 is +begin + Assertions_3; +end Test_Assertions_3; + +--# assertions_3.adb +-- /high_decl/ l+ ## 0 +-- /loop_3/ l+ ## 0 +-- /loop_inv/ l! ## 0 +-- /null/ l+ ## 0 +-- /catch_3/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/test_expr_func.adb b/testsuite/tests/O212-062-assertions/src/test_expr_func.adb new file mode 100644 index 000000000..1eb1d538d --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/test_expr_func.adb @@ -0,0 +1,18 @@ +with Expr_Func; + +procedure Test_Expr_Func is +begin + Expr_Func; +end Test_Expr_Func; + +--# expr_func.adb +-- /foo_decl/ l+ ## 0 +-- /foo_pre/ l+ ## 0 +-- /foo_post/ l+ ## 0 +-- /bar_pre/ l+ ## 0 +-- /bar_post/ l- ## aT- +-- /bar_def/ l+ ## 0 +-- /dummy_decl/ l+ ## 0 +-- /foo_call/ l+ ## 0 +-- /bar_call/ l+ ## 0 +-- /catch/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/test_pragmas.adb b/testsuite/tests/O212-062-assertions/src/test_pragmas.adb new file mode 100644 index 000000000..4b6015b8f --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/test_pragmas.adb @@ -0,0 +1,18 @@ +with Pragmas; + +procedure Test_Pragmas is +begin + Pragmas; +end Test_Pragmas; + +--# pragmas.adb +-- /id/ l+ ## 0 +-- /assume/ l+ ## 0 +-- /c_pre/ l+ ## 0 +-- /c_post/ l+ ## 0 +-- /c_ti/ a=>l+, c=>l! ## a=>0, a=>ac! +-- /c_inv/ l+ ## 0 +-- /c_assert/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /cut/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /fail/ l! ## aT- +-- /catch/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/test_type_inv_false.adb b/testsuite/tests/O212-062-assertions/src/test_type_inv_false.adb new file mode 100644 index 000000000..86eec5709 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/test_type_inv_false.adb @@ -0,0 +1,25 @@ +with Pack_Type_Invariant; + +with Ada.Assertions; + +procedure Test_False +is + use Pack_Type_Invariant; + +begin + begin + declare + Dummy_1 : constant Bool_Record_1 := Make_Bool_Record_1 (False); + begin + null; + end; + exception + when Ada.Assertions.Assertion_Error => null; + end; +end Test_False; + +--# pack_type_invariant.ads +-- /type_dec_1/ l+ ## 0 +-- /type_def_1/ l+ ## 0 +-- /type_inv_1/ l! ## aT- +-- /func_ret_1/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/test_type_inv_null.adb b/testsuite/tests/O212-062-assertions/src/test_type_inv_null.adb new file mode 100644 index 000000000..d684f6eef --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/test_type_inv_null.adb @@ -0,0 +1,11 @@ +procedure Test_Null is +begin + null; +end Test_Null; + +--# pack_type_invariant.ads +-- /type_dec_1/ l- ## s- +-- /type_def_1/ l- ## s- +-- /rec_1/ l- ## 0 +-- /type_inv_1/ l- ## 0 +-- /func_ret_1/ l- ## s- diff --git a/testsuite/tests/O212-062-assertions/src/test_type_inv_true.adb b/testsuite/tests/O212-062-assertions/src/test_type_inv_true.adb new file mode 100644 index 000000000..bba14630e --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/test_type_inv_true.adb @@ -0,0 +1,18 @@ +with Pack_Type_Invariant; + +procedure Test_Type_Invariant +is + use Pack_Type_Invariant; + + Dummy_1 : Bool_Record_1 := Make_Bool_Record_1 (True); +begin + + null; +end Test_Type_Invariant; + +--# pack_type_invariant.ads +-- /type_dec_1/ l+ ## 0 +-- /type_def_1/ l+ ## 0 +-- /rec_1/ l+ ## 0 +-- /type_inv_1/ l+ ## 0 +-- /func_ret_1/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/test.opt b/testsuite/tests/O212-062-assertions/test.opt new file mode 100644 index 000000000..74b2fb73e --- /dev/null +++ b/testsuite/tests/O212-062-assertions/test.opt @@ -0,0 +1 @@ +bin-traces XFAIL Assertion coverage not yet supported for binary traces diff --git a/testsuite/tests/O212-062-assertions/test.py b/testsuite/tests/O212-062-assertions/test.py new file mode 100644 index 000000000..651d5af35 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision, assert_lvl="atc").run() +TestCase(category=CAT.decision, assert_lvl="atcc").run() +thistest.result() diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index 0d9fe3bf75ee9c5fbffcf4c0175b4eb43eee6996..4e1a258f439cab1c76dc5baea7ec39022f4de1a3 100644 GIT binary patch delta 13 UcmbQtJe7HZJQD-MM)?v(02oaJB>(^b delta 10 RcmbQrJehfd{6@tRMgS7810?_e diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid index a66641535543cbcfbbb162c2dbe1bc82ede36e06..6349dac17ad6b663845ab009c755b75840509b21 100644 GIT binary patch delta 13 UcmbQtJe7HZJQD-MM)?v(02oaJB>(^b delta 10 RcmbQrJehfd{6@tRMgS7810?_e diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid index d5d4c20fcdbaa9d74393da691b6ca0da69006e9f..33f7bd2aa00568400ab2349c18ecfda35d9e24c5 100644 GIT binary patch delta 13 UcmbQnF@s}*JQD-MM)~i|02&Jex&QzG delta 10 RcmbQiF^yw_{6@v^%m5TU1G)eJ diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt index d30eeff7fde4e9bc745aa8fb712c933fcf7ba324..1d9a4296a7f5c6884cb3783254bcba1010649362 100644 GIT binary patch delta 642 zcmY*WyG{Z@6rIQJ@(>9aNeG3oQ3^xE1u;Y{Fn)u*V4xsTEI@;aiTDR@?l)MOXl(86 zEG%tFENT1$?-_Os-sI-aoO|x$%si*x(htRy5K;;ulI${^?XD_5zyWTAwE{I|A))!Q z!k!JE%0~%4bbH-uw>J{f1mMVh$8`G&OYq?VgI>b?I)o3|g(3Dbi|?dYNb2BN}x`Ui1E- z!~U_cgk9#3eambJN}@DUF?8~t`8!3Qj=yOq;%_hsah)BuX4W%27sohdben#htD@H2 z&6Wxs86X1^x!W1$EZzkWbExCy>BBvX<%i$%m-#F0dtd%Rsn%@mHCjQVR0-;>ATVU+ G+xQEe>N@@a delta 598 zcmYjOJxc>Y5WU^o-FQ)g1Vkl*IWUF9=;cgx5&Wnu{0V}d#KKC!C>BD%#x8iwUl6pA z2v(xKzd`&PHj0h&Hn$-IbMx-)?7TO3Z>2%$Zm}qY=Xpg=L4k<1WF%=z>;yg|WRTt0 zvY%<8v-+AgOqlFoBPzI4u4yM-O*`kFn8?Wz$VT`0s(W%eJPCMsod#lW9&$(o#zPQQ zQ7XfRW&{nenC3dcL((arM^QzFbR(C9q6gWYMGyK>5klc%=vOY#pK2R{p@z!-X3rvi zo8-jqs56}4am#uD2~Etj4s$%3@60i;#wSiO;Q|*ufh({qeA~Cra9kP|AS*HPlDD)T z7!TVSID@W^y05w0EuJs9qUH=_dG)@k@$)Pvc=^5x>04dUhb~w6&qEK6Jl_TgyDi=7 pWqQ$N`qGDm$D`fXr}t;tHlJZ!ZMKr;dJ?y)^(aoF$bAD>{{d7WHZlMJ diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index 7fe2851caf3ae1126587120f8e2732a0b84aad3d..e21e64110d2d13f610d926582767d59b0d3df6c2 100644 GIT binary patch delta 625 zcmY*VyGjF55WSDw-MmHLhS7I10*2M+2qD#VD{WQGw0kn``|r#ms4pWq!dCVIc4}VXA~b)_`8wNd`NL- z!mE;(;6u;|DnX+yq@itDC^%fg3@eCsr+sp8-0Qk@B+Kb)C1^F3h;uU@?w6@4FMO9T zcne`TV||1Qo^@zX`6Wz6v_4t}rcehulu#2rM0$Q?#S& z3$_JQunWv#gcG6>4@JADq9U1-2~ zW5y~*t+SpRE?^Oe1GAinacm^$(RUyHY2ceLqzB-e`7mD=J`ZGM@2H~$B# C-Z^vt delta 663 zcmYjPJxc>Y5WU&Gy_gSzL?wu#31}hlE?g9gM9{{%W#!K>*f?*KJ#Jub=HAYGGdp+h)z|97W{Jr2yplNakXn^EN`?dFDFGB8Q>&;Y zgBR1s?euq%OxkLjK!6}UJ8T!+sl=q8L`nbFqlGzG1sIMl?nZ;_*$H3KWEBnJFesxJ zqR)wHhDI{T1BH;Q1deV_95p_#sV3j6E%NzE_3EfWJtB;JJOZAob=IaA5JUs6>7%jD zUUX@>BRIWIJ#lilaH7d{QXOPxl%-;MXWodXUF F^?y3aG+zJ! diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 512ee6f1aeb3ddf25df2389987f3660578e018e7..30379d59a3d747a3b94189e3249878dbc7d266ab 100644 GIT binary patch delta 62 zcmdnZf0BQKJR`$Kxy`Hs%*>3842%p6V9dbGJozrG#N^McB9mF!OeQ}B(w=OI>@G~X O_v_wl+`N&EixB{=)DQ6h delta 56 zcmX@fzng!8{6@u1tdp;@3Qcxp6XIcHWME`qU|<4bhRNJ)79hdNk!k`~e$h)|)dHF1(%DnfGR9cfS^ImhM+GV=NeB97C*NEo^tgOAl;h0~3m-Mqx657ekRb~!ZwjD&*lI~iAkmaApg4>kpHz4>JQ0E%B^4`Iep;Oy zY!61K>wXs~$0q2=8#}M0Qh|tj) zW`J~!y~|nN0_Su|+<-KXEpe8o^~CDX(GkrbrgYTKHM71E*R%#{qaJ+dO8RtH{2624 zp^@)cu=MEj9YnsQJ|VaGSyfD~RL9tj?}7C0^Ywppzu&<+>L-K7Lu>Ln{dlIQSQYdDqPzsz}Vm zTmNSPD{LlO?1A{D#1ITc{#J%%{elBi`nh9M^2pRU(;a>@XB)VI2p@{`X}|mPjlSo3 wBEE|AMWX6KxTz%|lkexxI4^u3gzvjDj0jBSAsXIEj???=$CJ^+E#D=RFD>aXo&W#< diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid index 8c3a9cf461021af24641eb3efee0b2b8f2eaadff..2d84552ef934580944ebcb45e4d38683677c0a45 100644 GIT binary patch delta 13 UcmbQrJe_%hJQD-MM)@*E02qM-D*ylh delta 10 RcmbQvJe7HZ{6@txMgS7m11kUk diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid index ed362aae294d95988646601009487ef72c0eaa1e..1134e529a7f6e7fe86c05a6a22689f2fc7805b39 100644 GIT binary patch delta 13 UcmbQrJe_%hJQD-MM)@*E02qM-D*ylh delta 10 RcmbQvJe7HZ{6@txMgS7m11kUk diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid index a394a807e0c4550387cbb6d036b8b7577d3177ae..9f9c03d18e3240f12df704f4b831e9751b806cfa 100644 GIT binary patch delta 13 UcmbQmF^6M B); + + function Make_Bool_Record (B : Boolean) return Bool_Record is + ((B => B)); + + function Get_Value (R : Bool_Record) return Boolean is (R.B); +end Pkg_Type_Invariant; + diff --git a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt new file mode 100644 index 000000000..74b2fb73e --- /dev/null +++ b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt @@ -0,0 +1 @@ +bin-traces XFAIL Assertion coverage not yet supported for binary traces diff --git a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py new file mode 100644 index 000000000..eb2dad649 --- /dev/null +++ b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py @@ -0,0 +1,43 @@ +""" +Check that gnatcov behaves properly in the cases where gnatcov cannot +instrument contracts expressed in pragmas: a warning is emitted, the statement +is not instrumented but the rest is. This concerns pre and postconditions and +type invariants. +""" + +from SCOV.minicheck import (check_xcov_reports, build_and_run, xcov) +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + + +xcov_args = build_and_run( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../"], + mains=["main.adb"])), + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + covlevel="stmt+decision+atcc", + register_failure=False, + ) + +thistest.fail_if_no_match( + "'gnatcov instrument' output", + r".*gnatcov limitation: pragma Precondition ignored.*\n" + + r".*gnatcov limitation: pragma Postcondition ignored.*\n" + + r".*gnatcov limitation: pragma Type_Invariant ignored.*", + contents_of("instrument.log").strip()) + +xcov(xcov_args) + +check_xcov_reports('xcov/*.xcov', { + 'xcov/pkg_type_invariant.ads.xcov': {'+': {6, 13, 14, 15, 16, 20}, + '-': {22}}, + 'xcov/main.adb.xcov': {'+': {6, 8, 12}}, +}) + +thistest.result() diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 6ac88d171..1526ae4f3 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -415,7 +415,8 @@ package body Annotations.Report is Put (Output.all, To_Lower (SCO_Kind'Image (Kind (M.SCO))) - & (if Switches.Show_MCDC_Vectors + & (if (Switches.Show_MCDC_Vectors + or else Switches.Show_Condition_Vectors) and then Kind (M.SCO) = Condition then Index (M.SCO)'Image & " (" & SCO_Image (M.SCO) & ") " @@ -533,6 +534,9 @@ package body Annotations.Report is Title : String; Item : String) is + procedure Output_Message (C : Message_Vectors.Cursor); + -- Display the SCO violations messages stored at C + Item_Count : Natural := 0; -- Count of the number of violation / error messages for the current -- section. @@ -541,6 +545,58 @@ package body Annotations.Report is -- Count of the number of messages (including info messages) for the -- current section. + -------------------- + -- Output_Message -- + -------------------- + + procedure Output_Message (C : Message_Vectors.Cursor) is + M : Message renames Message_Vectors.Element (C); + Msg : constant String := To_String (M.Msg); + First : Natural := Msg'First; + Show_Vectors : constant Boolean := + (Switches.Show_MCDC_Vectors + and then not Is_Assertion_To_Cover (M.SCO)) + or else Switches.Show_Condition_Vectors; + begin + -- For info messages (such as the messages displayed with + -- --show-mcdc-vectors and --show-condition vectors), do not + -- display the SCO, as it is only used to attach the message to + -- the right report location. + + if M.Kind /= Info and then M.SCO /= No_SCO_Id then + Put + (Output.all, Image (First_Sloc (M.SCO), Unique_Name => True)); + Put (Output.all, ": "); + if Msg (First) = '^' then + First := First + 1; + else + Put + (Output.all, + SCO_Kind_Image (M.SCO) + & (if Show_Vectors and then Kind (M.SCO) = Condition + then Index (M.SCO)'Image + & " (" & SCO_Image (M.SCO) & ") " + else " ")); + end if; + + else + Put (Output.all, Image (M.Sloc, Unique_Name => True)); + Put (Output.all, ": "); + end if; + + Output_Multiline_Msg + (Output => Output.all, + Text => Msg (First .. Msg'Last)); + + if M.SCO /= No_SCO_Id and then M.Tag /= No_SC_Tag then + Put (Output.all, + " (from " & Tag_Provider.Tag_Name (M.Tag) & ")"); + end if; + + New_Line (Output.all); + Output_Annotations (Output.all, SCO_Annotations (M.SCO)); + end Output_Message; + -- Start of processing for Messages_For_Section begin @@ -609,6 +665,7 @@ package body Annotations.Report is for L in Coverage_Level loop if Enabled (L) or else (L = Decision and then MCDC_Coverage_Enabled) + or else (L in ATC | ATCC and then Assertion_Coverage_Enabled) then Messages_For_Section (Coverage_Level'Pos (L), @@ -617,7 +674,6 @@ package body Annotations.Report is else pragma Assert (Pp.Nonexempted_Messages (Coverage_Level'Pos (L)).Is_Empty); - null; end if; end loop; @@ -935,15 +991,24 @@ package body Annotations.Report is return Coverage_Level'Pos (Stmt); when Decision => - if Is_Expression (SCO) then + if Is_Expression (SCO) + and then not Decision_Requires_Assertion_Coverage (SCO) + then return MCDC_Section; - + elsif Decision_Requires_Assertion_Coverage (SCO) then + return Coverage_Level'Pos (ATC); else return Coverage_Level'Pos (Decision); end if; when Condition => - return MCDC_Section; + if Enabled (ATCC) + and then Decision_Requires_Assertion_Coverage (SCO) + then + return Coverage_Level'Pos (ATCC); + else + return MCDC_Section; + end if; when others => return Other_Errors; diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 5790d883b..6095407fb 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -27,6 +27,7 @@ with Interfaces; with ALI_Files; use ALI_Files; with Calendar_Utils; +with Coverage; with Coverage_Options; use Coverage_Options; with Coverage.Object; with Coverage.Source; use Coverage.Source; @@ -645,15 +646,19 @@ package body Annotations is use Ada.Strings.Unbounded; begin if M.SCO /= No_SCO_Id then - return To_Lower (SCO_Kind'Image (Kind (M.SCO))) - & (if Switches.Show_MCDC_Vectors and then Kind (M.SCO) = Condition + return SCO_Kind_Image (M.SCO) + & (if (Switches.Show_MCDC_Vectors + or else Switches.Show_Condition_Vectors) + and then Kind (M.SCO) = Condition then Index (M.SCO)'Image & " (" else " ") & SCO_Image (M.SCO) & " at " & Img (First_Sloc (M.SCO).L.Line) & ":" & Img (First_Sloc (M.SCO).L.Column) - & (if Switches.Show_MCDC_Vectors and then Kind (M.SCO) = Condition + & (if (Switches.Show_MCDC_Vectors + or else Switches.Show_Condition_Vectors) + and then Kind (M.SCO) = Condition then ")" else "") & (if M.Tag = No_SC_Tag @@ -1035,42 +1040,49 @@ package body Annotations is when Statement => Update_Level_Stats (SCO, Get_Line_State (SCO, Stmt), Stmt); when Decision => - Update_Level_Stats - (SCO, Get_Line_State (SCO, Decision), Decision); - - -- Conditions in that decision - - if Coverage.MCDC_Coverage_Enabled then - for J in - Condition_Index'First .. Last_Cond_Index (SCO) - loop - declare - Condition_SCO : constant SCO_Id := - Condition (SCO, J); - - MCDC_State : constant SCO_State := - Get_Line_State (SCO, MCDC); - -- If the parent decision is partially covered, then - -- the SCO_State for each condition will be No_Code, - -- and the SCO_State for the MCDC Coverage_Level - -- associated to the parent decision SCO will be - -- Not_Covered. - - Condition_State : SCO_State; - - begin - if MCDC_State = Not_Covered then - Condition_State := Not_Covered; - else - Condition_State := - Get_Line_State - (Condition_SCO, Coverage.MCDC_Level); - end if; - - Update_Level_Stats - (SCO, Condition_State, Coverage.MCDC_Level); - end; - end loop; + if Coverage.Assertion_Coverage_Enabled + and then Decision_Type (SCO) in Pragma_Decision | Aspect + then + Update_Level_Stats + (SCO, Get_Line_State (SCO, ATC), ATC); + else + Update_Level_Stats + (SCO, Get_Line_State (SCO, Decision), Decision); + + -- Conditions in that decision + + if Coverage.MCDC_Coverage_Enabled then + for J in + Condition_Index'First .. Last_Cond_Index (SCO) + loop + declare + Condition_SCO : constant SCO_Id := + Condition (SCO, J); + + MCDC_State : constant SCO_State := + Get_Line_State (SCO, MCDC); + -- If the parent decision is partially covered, + -- then the SCO_State for each condition will be + -- No_Code, and the SCO_State for the MCDC + -- Coverage_Level associated to the parent decision + -- SCO will be Not_Covered. + + Condition_State : SCO_State; + + begin + if MCDC_State = Not_Covered then + Condition_State := Not_Covered; + else + Condition_State := + Get_Line_State + (Condition_SCO, Coverage.MCDC_Level); + end if; + + Update_Level_Stats + (SCO, Condition_State, Coverage.MCDC_Level); + end; + end loop; + end if; end if; when others => null; @@ -1079,4 +1091,18 @@ package body Annotations is return Result; end Obligation_Metrics; + -------------------- + -- SCO_Kind_Image -- + -------------------- + + function SCO_Kind_Image (SCO : SCO_Id) return String is + K : constant SCO_Kind := Kind (SCO); + begin + return (if Kind (SCO) in Decision + and then Decision_Type (SCO) in Pragma_Decision | Aspect + and then Coverage.Assertion_Coverage_Enabled + then "contract expression" + else To_Lower (SCO_Kind'Image (K))); + end SCO_Kind_Image; + end Annotations; diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 9832e8745..7ca320e6f 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -279,4 +279,10 @@ private function Obligation_Metrics (From, To : SCO_Id) return Ob_Stat_Array; -- Return obligation metrics for the given SCO range + function SCO_Kind_Image (SCO : SCO_Id) return String; + -- Get the string representation of the SCO_Kind of SCO. A special + -- treatment is needed for assertions. There is no assertion SCO_Kind but + -- some decision SCOs correspond to assertion decisions. The difference + -- needs to be made clear in the reports by not calling them the same. + end Annotations; diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 94efd8da9..906b862e7 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -81,6 +81,7 @@ package Command_Line is Opt_Externally_Built_Projects, Opt_GNAT_Pragmas, Opt_Show_MCDC_Vectors, + Opt_Show_Condition_Vectors, Opt_Dump_Filename_Simple, Opt_Allow_Mix_Trace_Kind, Opt_Boolean_Short_Circuit_And_Or, @@ -503,9 +504,18 @@ package Command_Line is Opt_Show_MCDC_Vectors => Create (Long_Name => "--show-mcdc-vectors", - Help => "If set, show MCDC evaluation vectors encountered for" - & " decisions where there is at least a MCDC" - & " violation on one of the conditions.", + Help => "DEPRECATED: If set, show MCDC evaluation vectors" + & " encountered for decisions where there is at least a" + & " MCDC violation on one of the conditions. Prefer" + & " using --show-condition-vectors.", + Commands => (Cmd_Coverage => True, others => False), + Internal => False), + + Opt_Show_Condition_Vectors => Create + (Long_Name => "--show-condition-vectors", + Help => "If set, show MCDC and ATCC evaluation vectors" + & " encountered for decisions where there is at least a" + & " MCDC or ATCC violation on one of the conditions.", Commands => (Cmd_Coverage => True, others => False), Internal => False), diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 1448f1b65..906ba7c2f 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -179,10 +179,16 @@ package body Coverage.Source is 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. Note: this can be True even for decisions + -- 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 @@ -618,6 +624,105 @@ package body Coverage.Source is (Line_Num : Positive; Line_Info : Line_Info_Access) 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 @@ -672,15 +777,13 @@ package body Coverage.Source is -- 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) + and then not Basic_Block_Has_Code (SCO, SCI.Tag) then -- If a unit has any code at all, then a SCO is marked @@ -783,25 +886,41 @@ package body Coverage.Source is -- computed for the first line, and then cached in the SCI -- and reused for subsequent lines. - if Enabled (Decision) then - SCO_State := SCI.State (Decision); - Update_Line_State - (Line_Info, SCO, SCI.Tag, Decision, SCO_State); - end if; + if Decision_Requires_Assertion_Coverage (SCO) then - if MCDC_Coverage_Enabled then - SCO_State := SCI.State (MCDC_Level); + SCO_State := SCI.State (ATC); Update_Line_State - (Line_Info, SCO, SCI.Tag, MCDC_Level, SCO_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 (Enabled (Decision) or else MCDC_Coverage_Enabled) - and then Decision_Requires_Coverage (SCO) + 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 -- that the decision coverage information is also included - -- in MC/DC coverage. + -- in MC/DC coverage. The same goes for ATC and ATCC + -- information. if Decision_Outcome (SCO) /= Unknown then -- Case of a compile time known decision: exclude from @@ -832,49 +951,75 @@ package body Coverage.Source is or else SCI.Known_Outcome_Taken /= No_Outcome_Taken then - -- Here if at least one outcome has been exercised, - -- determined either by conditional branch instructions - -- (Outcome_Taken) or dominance (Known_Outcome_Taken). + -- Assertion coverage - SCO_State := Partially_Covered; + if Decision_Requires_Assertion_Coverage (SCO) then + -- Contract coverage level "Assertion True + -- Coverage" - declare - Missing_Outcome : Tristate := Unknown; - begin - -- Indicate which outcome has never been taken: if - -- FALSE has been taken then this is outcome TRUE, - -- else FALSE. + -- Assertions are never supposed to be evaluated + -- to False. Therefore once they have been + -- exercised and found to be True, they are + -- covered. - if SCI.Known_Outcome_Taken (False) - /= SCI.Known_Outcome_Taken (True) + if SCI.Outcome_Taken (True) + or else SCI.Known_Outcome_Taken (True) then - Missing_Outcome := - To_Tristate (SCI.Known_Outcome_Taken (False)); - - elsif not Degraded_Origins (SCO) then - Missing_Outcome := - To_Tristate (SCI.Outcome_Taken (False)); - end if; - - if Missing_Outcome = Unknown then - Report_Violation - (SCO, SCI.Tag, - "not exercised in both directions"); - + SCO_State := Covered; else + SCO_State := Not_Covered; Report_Violation (SCO, SCI.Tag, - "outcome " - & Missing_Outcome'Img & " never exercised"); + "outcome TRUE never exercised"); end if; - end; + + else + -- Here if at least one outcome has been exercised, + -- determined either by conditional branch + -- instructions (Outcome_Taken) or dominance + -- (Known_Outcome_Taken). + + SCO_State := Partially_Covered; + + declare + Missing_Outcome : Tristate := Unknown; + begin + -- Indicate which outcome has never been taken: if + -- FALSE has been taken then this is outcome TRUE, + -- else FALSE. + + if SCI.Known_Outcome_Taken (False) + /= SCI.Known_Outcome_Taken (True) + then + Missing_Outcome := + To_Tristate (SCI.Known_Outcome_Taken (False)); + + elsif not Degraded_Origins (SCO) then + Missing_Outcome := + To_Tristate (SCI.Outcome_Taken (False)); + end if; + + if Missing_Outcome = Unknown then + Report_Violation + (SCO, SCI.Tag, + "not exercised in both directions"); + + else + Report_Violation + (SCO, + SCI.Tag, + "outcome " + & Missing_Outcome'Img & " never exercised"); + end if; + end; + end if; elsif Enclosing_Statement (SCO) = No_SCO_Id or else (Basic_Block_Has_Code - (Enclosing_Statement (SCO), SCI.Tag) + (Enclosing_Statement (SCO), SCI.Tag) and then Stmt_SCO_Instrumented - (Enclosing_Statement (SCO))) + (Enclosing_Statement (SCO))) then -- Similar to the above for statement coverage: a -- decision that cannot ever be executed is reported @@ -915,7 +1060,6 @@ package body Coverage.Source is SCI.Tag, "was not instrumented for decision coverage", Kind => Undetermined_Cov); - SCO_State := Undetermined_Coverage; else Report_Violation (SCO, SCI.Tag, "never evaluated"); @@ -924,61 +1068,37 @@ package body Coverage.Source is end; end if; - Update_Line_State - (Line_Info, SCO, SCI.Tag, Decision, SCO_State); + -- Update the state of the line for all enabled source + -- coverage levels. - if MCDC_Coverage_Enabled then - if SCO_State = Covered then + if Decision_Requires_Assertion_Coverage (SCO) then + -- If the SCO is in an assertion, update its state for + -- the relevant assertion coverage levels... - -- Complete computation of MC/DC coverage state if SCO - -- is covered for decision coverage. + Update_Line_State + (Line_Info, SCO, SCI.Tag, ATC, SCO_State); - if not Decision_SCO_Instrumented_For_MCDC (SCO) then + if Enabled (ATCC) then + Compute_Condition_Level_Line_State + (SCO, SCO_State, Line_Info, SCI, ATCC); + end if; - -- This decision was not instrumented for MCDC, - -- so report only once for the whole decision, but - -- still mark each condition as not instrumented. + else + -- ...otherwise update the SCO state for the regular + -- source coverage levels. - for Cond_Index in 0 .. Last_Cond_Index (SCO) loop - Update_Line_State - (Line_Info, - Condition (SCO, Cond_Index), - SCI.Tag, - MCDC_Level, - Undetermined_Coverage); - end loop; + -- Update the SCO state for decision level - Update_Line_State - (Line_Info, - SCO, - SCI.Tag, - MCDC_Level, - Covered); + Update_Line_State + (Line_Info, SCO, SCI.Tag, Decision, SCO_State); - Report_Coverage - (SCO, - SCI.Tag, - "was not instrumented for MC/DC", - Kind => Undetermined_Cov); - else - Update_Line_State - (Line_Info, - SCO, - SCI.Tag, - MCDC_Level, - Compute_MCDC_State (SCO, SCI.all)); - end if; + -- Compute and update the SCO state for MCDC level - elsif SCO_State not in No_Code | Undetermined_Coverage + if MCDC_Coverage_Enabled + and then not Decision_Requires_Assertion_Coverage (SCO) then - - -- Case of MC/DC enabled, and decision is coverable - -- but at least one outcome was never taken: do not - -- report details regarding MC/DC coverage, just - -- record that MC/DC is not achieved. - - Update_Line_State - (Line_Info, SCO, SCI.Tag, MCDC_Level, Not_Covered); + Compute_Condition_Level_Line_State + (SCO, SCO_State, Line_Info, SCI, MCDC_Level); end if; end if; end if; @@ -987,7 +1107,6 @@ package body Coverage.Source is <> null; end loop; - -- Record that this line has been processed Line_Info.Coverage_Processed := True; @@ -1095,7 +1214,8 @@ package body Coverage.Source is -- Record and report the first eval pair that shows independent -- influence of Influent_Condition. - if Switches.Show_MCDC_Vectors + if (Switches.Show_MCDC_Vectors + or else Switches.Show_Condition_Vectors) and then Influent_Condition /= No_Condition_Index then Eval_Cond_Set_Map.Element @@ -1125,7 +1245,8 @@ package body Coverage.Source is -- Find the last condition which has a violation - if Switches.Show_MCDC_Vectors then + if Switches.Show_MCDC_Vectors or else Switches.Show_Condition_Vectors + then for J in reverse Indep'Range loop if not Indep (J) then Last_Cond_No_Pair := J; @@ -1147,7 +1268,10 @@ package body Coverage.Source is Tag => SCI.Tag, Msg => "has no independent influence pair, MC/DC not achieved"); - if Switches.Show_MCDC_Vectors and then J = Last_Cond_No_Pair then + if (Switches.Show_MCDC_Vectors + or else Switches.Show_Condition_Vectors) + and then J = Last_Cond_No_Pair + then -- We want the MC/DC vector to be displayed with the MC/DC -- violations, after the last MC/DC violation of the decision. @@ -1188,6 +1312,114 @@ package body Coverage.Source is return SCO_State; end Compute_MCDC_State; + ------------------------ + -- Compute_ATCC_State -- + ------------------------ + + function Compute_ATCC_State + (SCO : SCO_Id; + SCI : Source_Coverage_Info) return Line_State + is + + function Emit_Evaluation_Vector_Message return String; + -- List all the evaluation vectors + + ------------------------------------ + -- Emit_Evaluation_Vector_Message -- + ------------------------------------ + + function Emit_Evaluation_Vector_Message return String is + Msg : Unbounded_String; + EOL : constant String := "" & Ada.Characters.Latin_1.LF; + begin + Msg := To_Unbounded_String ("Decision of the form ") + & Expression_Image (SCO) & EOL; + Append (Msg, "Evaluation vectors found:" & EOL); + + for Eval of SCI.Evaluations loop + Append (Msg, " " & Image (Eval) & EOL); + end loop; + + return To_String (Msg); + + end Emit_Evaluation_Vector_Message; + + SCO_State : Line_State := No_Code; + + Last_Cond_Not_Evaluated : Condition_Index; + -- Condition index for which to dump the message. As the DHTML output + -- only displays the last registered violation for a line, we must + -- emit the evaluation vectors of the last reported violation. + + Last_Cond_Idx : constant Condition_Index := Last_Cond_Index (SCO); + -- Index of last condition in decision + + type Condition_Evaluated_Array is array + (Condition_Index'First .. Last_Cond_Idx) of Boolean; + + Condition_Evaluated : Condition_Evaluated_Array := (others => False); + + begin + + -- Record if a condition has been evaluated during the overall + -- evaluation to true of its corresponding decision. + + for Eval of SCI.Evaluations loop + if Eval.Outcome = True then + for I in Condition_Evaluated_Array'Range loop + Condition_Evaluated (I) := + Condition_Evaluated (I) or else Eval.Values (I) /= Unknown; + end loop; + end if; + end loop; + + -- Find the last condition which has a violation + + for I in reverse Condition_Evaluated'Range loop + if not Condition_Evaluated (I) then + Last_Cond_Not_Evaluated := I; + exit; + end if; + end loop; + + -- Iterate over conditions and report + + for I in Condition_Evaluated_Array'Range loop + if not Condition_Evaluated (I) then + Update_State + (SCO_State, Condition (SCO, I), SCI.Tag, ATCC, Not_Covered); + Report_Violation + (SCO => Condition (SCO, I), + Tag => SCI.Tag, + Msg => "was never evaluated during an evaluation of the " & + "decision to True, ATCC not achieved"); + + if Switches.Show_Condition_Vectors + and then I = Last_Cond_Not_Evaluated + then + -- In much the same way is in Compute_MCDC_State, display the + -- vector with ATCC violations and after the last ATCC + -- violation of the decision. + + Report_Coverage (SCO => Condition (SCO, I), + Tag => SCI.Tag, + Msg => Emit_Evaluation_Vector_Message, + Kind => Info); + end if; + else + Update_State + (SCO_State, Condition (SCO, I), SCI.Tag, ATCC, Covered); + end if; + end loop; + + -- If we have degraded origins for SCO but we computed ATCC coverage + -- state then this means that ATC is achieved, and so ATCC must be + -- achieved as well (because this is a single condition decision). + + pragma Assert (SCO_State = Covered or else not Degraded_Origins (SCO)); + return SCO_State; + end Compute_ATCC_State; + ----------------------------- -- Compute_Source_Coverage -- ----------------------------- @@ -1317,19 +1549,18 @@ package body Coverage.Source is or else (not Precise and then Multistatement_Line); if not (Propagating and No_Propagation) then + -- Mark S_SCO as executed - -- Mark S_SCO as executed - - Report - ((if Line_Executed then "line " else "") - & "executed" & Tag_Suffix - & (if Propagating then " (propagating)" else ""), - SCO => S_SCO, - Exe => Exe, - PC => PC, - Kind => Notice); + Report + ((if Line_Executed then "line " else "") + & "executed" & Tag_Suffix + & (if Propagating then " (propagating)" else ""), + SCO => S_SCO, + Exe => Exe, + PC => PC, + Kind => Notice); - Update_SCI (S_SCO, Tag, Set_Executed'Access); + Update_SCI (S_SCO, Tag, Set_Executed'Access); end if; exit when not Propagating and No_Propagation; @@ -2006,9 +2237,22 @@ package body Coverage.Source is return Switches.All_Decisions or else not Is_Expression (SCO) - or else (MCDC_Coverage_Enabled and then Last_Cond_Index (SCO) > 0); + or else (MCDC_Coverage_Enabled + and then Last_Cond_Index (SCO) > 0); end Decision_Requires_Coverage; + ------------------------------------------ + -- Decision_Requires_Assertion_Coverage -- + ------------------------------------------ + + function Decision_Requires_Assertion_Coverage (SCO : SCO_Id) return Boolean + is + begin + pragma Assert (Kind (SCO) in Decision | Condition); + + return Assertion_Coverage_Enabled and then Is_Assertion_To_Cover (SCO); + end Decision_Requires_Assertion_Coverage; + -------------------- -- Get_Line_State -- -------------------- diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 1bf7e7c21..e696d29c6 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -41,6 +41,11 @@ package Coverage.Source is -- which have an allocated bit in trace buffers (see -- SC_Obligations.Statement_Bit_Map) as having code. + function Decision_Requires_Assertion_Coverage (SCO : SCO_Id) return Boolean; + -- True if SCO is for a decision in a pragma/aspect whose coverage can be + -- checked by assertion coverage levels, and if any assertion coverage + -- level is enabled. + procedure Compute_Source_Coverage (Subp_Key : Subprogram_Key; Subp_Info : Subprogram_Info; diff --git a/tools/gnatcov/coverage.adb b/tools/gnatcov/coverage.adb index 9c76eccb3..9708f35ee 100644 --- a/tools/gnatcov/coverage.adb +++ b/tools/gnatcov/coverage.adb @@ -95,6 +95,23 @@ package body Coverage is return MCDC_Coverage_Enabled_Cached; end MCDC_Coverage_Enabled; + -------------------------------- + -- Assertion_Coverage_Enabled -- + -------------------------------- + + function Assertion_Coverage_Enabled return Boolean is + begin + return Source_Coverage_Enabled + and then (Enabled (ATC) or else Enabled (ATCC)); + end Assertion_Coverage_Enabled; + + ------------------------------------------ + -- Assertion_Condition_Coverage_Enabled -- + ------------------------------------------ + + function Assertion_Condition_Coverage_Enabled return Boolean is + (Enabled (ATCC)); + ---------------- -- MCDC_Level -- ---------------- @@ -191,6 +208,12 @@ package body Coverage is Res.Include (MCDC_Level); end if; end if; + if Enabled (ATC) then + Res.Include (ATC); + if Enabled (ATCC) then + Res.Include (ATCC); + end if; + end if; end if; return Res; end Source_Levels_Enabled; diff --git a/tools/gnatcov/coverage.ads b/tools/gnatcov/coverage.ads index 27ad8065c..f97c6972d 100644 --- a/tools/gnatcov/coverage.ads +++ b/tools/gnatcov/coverage.ads @@ -39,7 +39,9 @@ package Coverage is when Stmt => "Stmt", when Decision => "Decision", when MCDC => "MCDC", - when UC_MCDC => "UC_MCDC"); + when UC_MCDC => "UC_MCDC", + when ATC => "ATC", + when ATCC => "ATCC"); -- Case sensitive version of Coverage_Level'Image procedure Set_Coverage_Levels (Opt : String); @@ -60,6 +62,13 @@ package Coverage is function MCDC_Coverage_Enabled return Boolean; -- True if any MCDC_Coverage_Level is enabled + function Assertion_Condition_Coverage_Enabled return Boolean; + -- True if any level of assertion coverage requiring to compute the + -- coverage of separate conditions is enabled; + + function Assertion_Coverage_Enabled return Boolean; + -- True if any Assertion_Coverage_Level is enabled + function Object_Level return Object_Coverage_Level; -- If Object_Coverage_Enabled, return Insn or Branch, depending on which -- one is enabled (it is illegal to have both enabled). diff --git a/tools/gnatcov/coverage_options.adb b/tools/gnatcov/coverage_options.adb index 5dffd8f20..a6b7c0acc 100644 --- a/tools/gnatcov/coverage_options.adb +++ b/tools/gnatcov/coverage_options.adb @@ -32,6 +32,9 @@ package body Coverage_Options is procedure Add_Object_Level_Option (L : Levels_Type); -- Register L as a valid combination of object coverage levels + procedure Add_Source_Coverage_Level_Combinaisons; + -- Register the possible source coverage level combinaisons + --------------------------- -- Coverage_Option_Value -- --------------------------- @@ -121,6 +124,65 @@ package body Coverage_Options is return Level_Options (Source_Levels_Option_Map, Separator); end Source_Level_Options; + ------------------------------------- + -- Add_Coverage_Level_Combinaisons -- + ------------------------------------- + + procedure Add_Source_Coverage_Level_Combinaisons is + procedure Add_Assert_Coverage_Levels (Combinaison : Levels_Type); + -- Register the coverage level Combinaison combined plus each level + -- of assertion coverage. + + -------------------------------- + -- Add_Assert_Coverage_Levels -- + -------------------------------- + + procedure Add_Assert_Coverage_Levels (Combinaison : Levels_Type) is + Assert_Levels : constant array (1 .. 2) of Coverage_Level := + (ATC, ATCC); + Comb : Levels_Type := Combinaison; + begin + for Lvl of Assert_Levels loop + + -- Activate Lvl to combine it with the levels in Comb + Comb (Lvl) := True; + + Add_Source_Level_Option (Comb); + + -- Deactivate Lvl to add the next assertion level to the + -- combinaison Comb + Comb (Lvl) := False; + + end loop; + end Add_Assert_Coverage_Levels; + + Decision_Levels : constant array (1 .. 3) of Coverage_Level := + (Decision, MCDC, UC_MCDC); + + Combinaison : Levels_Type := (Stmt => True, others => False); + begin + + -- Add "stmt" only and combine it with all possible assertion levels + + Add_Source_Level_Option (Combinaison); + Add_Assert_Coverage_Levels (Combinaison); + + -- Do the same for all other regular source coverage options + + for Lvl of Decision_Levels loop + + -- Activate Lvl to combine it with "stmt" + Combinaison (Lvl) := True; + + Add_Source_Level_Option (Combinaison); + Add_Assert_Coverage_Levels (Combinaison); + + -- Deactivate Lvl to combine the next level with "stmt" + Combinaison (Lvl) := False; + + end loop; + end Add_Source_Coverage_Level_Combinaisons; + begin -- Register command line options for valid combinations of coverage levels @@ -133,15 +195,5 @@ begin -- Source coverage levels - Add_Source_Level_Option ((Stmt => True, - others => False)); - Add_Source_Level_Option ((Stmt => True, - Decision => True, - others => False)); - Add_Source_Level_Option ((Stmt => True, - MCDC => True, - others => False)); - Add_Source_Level_Option ((Stmt => True, - UC_MCDC => True, - others => False)); + Add_Source_Coverage_Level_Combinaisons; end Coverage_Options; diff --git a/tools/gnatcov/coverage_options.ads b/tools/gnatcov/coverage_options.ads index f8dd829db..2107e59a7 100644 --- a/tools/gnatcov/coverage_options.ads +++ b/tools/gnatcov/coverage_options.ads @@ -24,7 +24,8 @@ with Strings; use Strings; package Coverage_Options is - type Coverage_Level is (Insn, Branch, Stmt, Decision, MCDC, UC_MCDC); + type Coverage_Level is + (Insn, Branch, Stmt, Decision, MCDC, UC_MCDC, ATC, ATCC); -- Coverage objectives supported by xcov. The following values are -- supported: @@ -33,14 +34,25 @@ package Coverage_Options is -- * source coverage at statement level (Stmt); -- * source coverage at decision level (Decision); -- * source coverage at masking MC/DC level (MCDC); - -- * source coverage at unique cause MC/DC level (UC_MCDC). + -- * source coverage at unique cause MC/DC level (UC_MCDC); + -- * source coverage at ATC level (ATC); + -- * source coverage at ATCC level (ATCC). -- The terms "instruction", "branch", "statement", "decision" and "MCDC" -- should be understood here as they are defined in the DO-178B standard; -- their meaning is also documented in Couverture's documentation. + -- + -- The meaning of the assertion coverage level "ATC" should be understood + -- as follows: + -- + -- * "ATC" : the whole expression has been evaluated to True at least + -- once; + -- * "ATCC" : all the conditions of the decision have been evaluated at + -- least once as part of an evaluation to True of the whole + -- decision. subtype Object_Coverage_Level is Coverage_Level range Insn .. Branch; - subtype Source_Coverage_Level is Coverage_Level range Stmt .. UC_MCDC; + subtype Source_Coverage_Level is Coverage_Level range Stmt .. ATCC; subtype MCDC_Coverage_Level is Coverage_Level range MCDC .. UC_MCDC; type Levels_Type is array (Coverage_Level) of Boolean; diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index aa361f075..b37a043c3 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -215,18 +215,22 @@ package Files_Table is package SCO_Id_Vectors is new Ada.Containers.Vectors (Index_Type => Natural, Element_Type => SCO_Id); - type Line_State_Cell is (Cell_1, Cell_2); + type Line_State_Cell is (Cell_1, Cell_2, Cell_3); Coverage_Level_To_Cell : constant array (Coverage_Level) of Line_State_Cell := - (Insn => Cell_1, - Branch => Cell_2, - Stmt => Cell_1, - Decision => Cell_2, - MCDC => Cell_2, - UC_MCDC => Cell_2); + (Insn => Cell_1, + Branch => Cell_2, + Stmt => Cell_1, + Decision => Cell_2, + MCDC => Cell_2, + UC_MCDC => Cell_2, + ATC => Cell_3, + ATCC => Cell_3); -- For one specific execution of GNATcov, we know that each line needs at - -- most only two states (insn, branch, stmt, stmt+decision, stmt+mcdc or - -- stmt+uc_mcdc). Thus, there is no need to store the state for all + -- most only three states (insn, branch, stmt, stmt+decision, stmt+mcdc, + -- stmt+uc_mcdc, stmt+atc, stmt+decision+atc, stmt+mcdc+atc, + -- stmt+uc_mcdc+atc, stmt+atcc, stmt+decision+atcc, stmt+mcdc+atcc, + -- stmt+uc_mcdc_atcc). Thus, there is no need to store the state for all -- coverage levels at the same time. This table is thus used to convert the -- coverage level to the appropriate state "storage cell". diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 745082afa..9e9c11af1 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -501,8 +501,11 @@ procedure GNATcov_Bits_Specific is Keep_Reading_Traces := Args.Bool_Args (Opt_Keep_Reading_Traces); Dump_Units := Args.String_Args (Opt_Dump_Units_To).Present; Show_MCDC_Vectors := (Args.Bool_Args (Opt_Show_MCDC_Vectors) - or else All_Messages - or else Verbose); + or else All_Messages + or else Verbose); + Show_Condition_Vectors := (Args.Bool_Args (Opt_Show_Condition_Vectors) + or else All_Messages + or else Verbose); Allow_Mixing_Trace_Kinds := Args.Bool_Args (Opt_Allow_Mix_Trace_Kind); Short_Circuit_And_Or := Args.Bool_Args (Opt_Boolean_Short_Circuit_And_Or); diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index f7279aabc..069604e73 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -946,7 +946,6 @@ package body Instrument.Ada_Unit is Common_Nodes : Degenerate_Subp_Common_Nodes; Formal_Params : Node_Rewriting_Handle; Call_Params : Node_Rewriting_Handle; - Keep_Aspects : Boolean; Augmented_Expr_Function : out Node_Rewriting_Handle; Augmented_Expr_Function_Decl : out Node_Rewriting_Handle; New_Expr_Function : out Node_Rewriting_Handle); @@ -979,7 +978,7 @@ package body Instrument.Ada_Unit is -- right before the original expression function's declaration. -- -- If the original expression function is not defined in the same - -- declarative region as its prefious declaration, then there is no need to + -- declarative region as its previous declaration, then there is no need to -- insert a declaration for the augmented expression function, beause in -- that case it isn't a primitive. @@ -2435,7 +2434,6 @@ package body Instrument.Ada_Unit is Common_Nodes : Degenerate_Subp_Common_Nodes; Formal_Params : Node_Rewriting_Handle; Call_Params : Node_Rewriting_Handle; - Keep_Aspects : Boolean; Augmented_Expr_Function : out Node_Rewriting_Handle; Augmented_Expr_Function_Decl : out Node_Rewriting_Handle; New_Expr_Function : out Node_Rewriting_Handle) @@ -2484,10 +2482,8 @@ package body Instrument.Ada_Unit is and then Augmented_Expr_Function_Needs_Decl (Common_Nodes.N.As_Expr_Function); + Orig_Aspects : constant Aspect_Spec := Common_Nodes.N.F_Aspects; begin - -- Create New_Expr_Function, which will go right after the augmented - -- expression function. Move all aspects from the original function to - -- the new one. New_Expr_Function := Create_Expr_Function @@ -2495,9 +2491,7 @@ package body Instrument.Ada_Unit is F_Overriding => Clone (Common_Nodes.N_Overriding), F_Subp_Spec => Clone (Common_Nodes.N_Spec), F_Expr => Create_Paren_Expr (RC, Call_Expr), - F_Aspects => (if Keep_Aspects - then Detach (Common_Nodes.N.F_Aspects) - else No_Node_Rewriting_Handle)); + F_Aspects => No_Node_Rewriting_Handle); -- The original expression function becomes the augmented one: @@ -2537,10 +2531,12 @@ package body Instrument.Ada_Unit is Previous_Spec : constant Subp_Spec := Common_Nodes.N.P_Previous_Part_For_Decl.As_Subp_Decl.F_Subp_Spec; - New_Spec : constant Node_Rewriting_Handle := Clone (Previous_Spec); -- Clone the spec of the original declaration + New_Spec : constant Node_Rewriting_Handle := Clone (Previous_Spec); + begin + -- Replace the original EF name by the augmented EF name Set_Child (New_Spec, @@ -2570,6 +2566,55 @@ package body Instrument.Ada_Unit is end; else Augmented_Expr_Function_Decl := No_Node_Rewriting_Handle; + + if not Orig_Aspects.Is_Null then + declare + function Replace_Attr_Subp_Name + (N : Ada_Node'Class) return Visit_Status; + -- Replace all uses of the name of the original expression + -- function in an attribute reference in N with the name of the + -- new augmented expr function. + + function Replace_Attr_Subp_Name + (N : Ada_Node'Class) return Visit_Status is + begin + if N.Kind = Ada_Attribute_Ref + and then N.As_Attribute_Ref.F_Prefix.Text = Orig_Name_Text + then + Replace + (Handle (N.As_Attribute_Ref.F_Prefix), + Make_Identifier (UIC, Augmented_Expr_Func_Name)); + end if; + return Into; + end Replace_Attr_Subp_Name; + + Assocs : constant Aspect_Assoc_List := + Orig_Aspects.F_Aspect_Assocs; + Idx : Positive := 1; + Has_Elt : Boolean := Assocs.Aspect_Assoc_List_Has_Element (Idx); + begin + while Has_Elt loop + declare + Aspect_Expr : constant Expr := + Assocs.Aspect_Assoc_List_Element (Idx).F_Expr; + begin + if Aspect_Expr /= No_Expr then + Traverse (Aspect_Expr, Replace_Attr_Subp_Name'Access); + end if; + + Idx := Idx + 1; + Has_Elt := Assocs.Aspect_Assoc_List_Has_Element (Idx); + end; + end loop; + end; + end if; + + -- Attach the aspect specifications of the original expression + -- function to the augmented one. + + Set_Child (Augmented_Expr_Function, + Member_Refs.Basic_Decl_F_Aspects, + Detach (Orig_Aspects)); end if; -- If the original expression function is ghost, so must be the @@ -3120,7 +3165,6 @@ package body Instrument.Ada_Unit is Is_Select_Stmt_Alternative : Boolean := False; Priv_Part : Private_Part := No_Private_Part) is - SC_First : constant Nat := SC.Last + 1; SD_First : constant Nat := SD.Last + 1; -- Record first entries used in SC/SD at this recursive level @@ -3170,6 +3214,10 @@ package body Instrument.Ada_Unit is -- -- This also processes any nested declare expressions. + procedure Process_Contract (D : Basic_Decl'Class; Name : Text_Type) + with Pre => Assertion_Coverage_Enabled; + -- Register decision of contrat of name Name of declaration node D + procedure Set_Statement_Entry; -- Output CS entries for all statements saved in table SC, and end the -- current CS sequence. Then output entries for all decisions nested in @@ -3407,6 +3455,16 @@ package body Instrument.Ada_Unit is end if; end Process_Decisions_Defer; + ---------------------- + -- Process_Contract -- + ---------------------- + + procedure Process_Contract (D : Basic_Decl'Class; Name : Text_Type) is + begin + Process_Decisions_Defer + (P_Get_Aspect_Spec_Expr (D, To_Unbounded_Text (Name)), 'A'); + end Process_Contract; + ------------------------- -- Set_Statement_Entry -- ------------------------- @@ -3955,12 +4013,6 @@ package body Instrument.Ada_Unit is -- MC/DC state inserter for this expression function (unused if -- instrumenting a null procedure). - Keep_Aspects : Boolean := True; - -- Whether to keep the aspects of the expression in the augmented - -- expression function or not. If we emit a forward declaration for - -- the expression function, the aspects need to be attached to the - -- declaration and not the augmented expression function. - subtype Decl_Expr_Supported_Versions is Any_Language_Version range Ada_2022 .. Any_Language_Version'Last; -- Set of versions of the Ada language that support declare @@ -4328,8 +4380,6 @@ package body Instrument.Ada_Unit is -- For expression functions, the aspects of the subprogram were -- moved to the newly created declaration, so they should not be -- added to the augmented function later on. - - Keep_Aspects := False; end if; if Is_Expr_Function then @@ -4347,7 +4397,6 @@ package body Instrument.Ada_Unit is Common_Nodes, Formal_Params, Call_Params, - Keep_Aspects, Augmented_Expr_Function, Augmented_Expr_Function_Decl, New_Expr_Function); @@ -4438,6 +4487,22 @@ package body Instrument.Ada_Unit is -------------------------------- procedure Traverse_Subp_Decl_Or_Stub (N : Basic_Decl) is + + procedure Process_Contracts (D : Basic_Decl'Class); + -- Register decisions of pre/postconditions for processing + + ----------------------- + -- Process_Contracts -- + ----------------------- + + procedure Process_Contracts (D : Basic_Decl'Class) is + begin + if Assertion_Coverage_Enabled then + Process_Contract (D, "Pre"); + Process_Contract (D, "Post"); + end if; + end Process_Contracts; + Dummy_Ctx : constant Context_Handle := Create_Context_Instrument (N); N_Spec : constant Subp_Spec := N.P_Subp_Spec_Or_Null.As_Subp_Spec; @@ -4459,7 +4524,13 @@ package body Instrument.Ada_Unit is if N.Kind in Ada_Null_Subp_Decl then Traverse_Degenerate_Subprogram (N, N_Spec); + + elsif N.Kind in Ada_Subp_Decl then + Process_Contracts (N.As_Subp_Decl); + elsif N.Kind in Ada_Expr_Function then + Process_Contracts (N.As_Expr_Function); + Traverse_Degenerate_Subprogram (N, N_Spec); end if; Exit_Scope (UIC); @@ -4984,14 +5055,40 @@ package body Instrument.Ada_Unit is begin case Nam is + when Name_Type_Invariant + | Name_Precondition + | Name_Postcondition + => + Typ := 'p'; + + if Assertion_Coverage_Enabled then + declare + Pragma_Name : constant String := + (case Nam is + when Name_Type_Invariant => + "Type_Invariant", + when Name_Precondition => + "Precondition", + when Name_Postcondition => + "Postcondition", + when others => ""); + Location : constant String := + Ada.Directories.Simple_Name + (N.Unit.Get_Filename) + & ":" & Image (Sloc (N)); + begin + Warn ("gnatcov limitation: pragma " & Pragma_Name + & " ignored during instrumentation at " + & Location & ". Consider expressing it as" + & " an aspect instead."); + end; + end if; + when Name_Assert | Name_Assert_And_Cut | Name_Assume | Name_Check | Name_Loop_Invariant - | Name_Type_Invariant - | Name_Postcondition - | Name_Precondition => -- For Assert-like pragmas, we insert a statement -- witness and instrument the decision if the pragma @@ -5008,14 +5105,31 @@ package body Instrument.Ada_Unit is end if; -- We consider that the assertion policy is - -- "disabled". + -- "disabled", except if any level of assertion + -- coverage is enabled. -- -- In the compiler, we initially set the type to 'p' -- (disabled pragma), and then switch it to 'P' -- if/when the policy is determined to be enabled -- later on. - Typ := 'p'; + if Assertion_Coverage_Enabled then + Typ := 'P'; + declare + Index : Positive := + (case Nam is + when Name_Check => 2, + when others => 1); + begin + while not Is_Null (Prag_Args.Child (Index)) loop + Process_Decisions_Defer + (Prag_Arg_Expr (Index), 'P'); + Index := Index + 1; + end loop; + end; + else + Typ := 'p'; + end if; -- Pre/postconditions can be inherited so SCO should -- never be deactivated??? @@ -5174,6 +5288,10 @@ package body Instrument.Ada_Unit is Typ := 's'; else Typ := 't'; + if Assertion_Coverage_Enabled then + Process_Contract + (N.As_Concrete_Type_Decl, "Type_Invariant"); + end if; end if; -- Entity declaration nodes that may also be used @@ -5603,22 +5721,24 @@ package body Instrument.Ada_Unit is (UIC : in out Ada_Unit_Inst_Context; N : Ada_Node) is - Decls : Declarative_Part; - HSS : Handled_Stmts; + Decls : Declarative_Part; + HSS : Handled_Stmts; + Aspects : Aspect_Spec := No_Aspect_Spec; Saved_MCDC_State_Inserter : constant Any_MCDC_State_Inserter := UIC.MCDC_State_Inserter; Local_Inserter : aliased Default_MCDC_State_Inserter; + begin case Kind (N) is when Ada_Subp_Body => declare SBN : constant Subp_Body := N.As_Subp_Body; begin - Decls := SBN.F_Decls; - HSS := SBN.F_Stmts; + Decls := SBN.F_Decls; + HSS := SBN.F_Stmts; + Aspects := SBN.F_Aspects; end; - when Ada_Task_Body => declare TBN : constant Task_Body := N.As_Task_Body; @@ -5655,6 +5775,30 @@ package body Instrument.Ada_Unit is Local_Inserter.Local_Decls := Handle (Decls.F_Decls); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; + -- If assertion coverage is enabled, process the decisions in the + -- contracts. This is needed in the case of a subprogram body with + -- aspect with no prior declaration. + + if Aspects /= No_Aspect_Spec and then Assertion_Coverage_Enabled then + declare + Assocs : constant Aspect_Assoc_List := Aspects.F_Aspect_Assocs; + Idx : Positive := 1; + Has_Elt : Boolean := Assocs.Aspect_Assoc_List_Has_Element (Idx); + begin + while Has_Elt loop + -- Defer the treatment of this decision + SD.Append + ((As_Ada_Node + (Assocs.Aspect_Assoc_List_Element (Idx).F_Expr), + 'A', + False)); + + Idx := Idx + 1; + Has_Elt := Assocs.Aspect_Assoc_List_Has_Element (Idx); + end loop; + end; + end if; + Traverse_Declarations_Or_Statements (UIC, L => Decls.F_Decls); Traverse_Handled_Statement_Sequence (UIC, N => HSS); @@ -5728,8 +5872,9 @@ package body Instrument.Ada_Unit is Condition_Count : Natural := 0; -- Count of conditions for current decision (MC/DC only) - MCDC_State : Unbounded_String; - -- Name of MC/DC state local variable for current decision (MC/DC only) + Conditions_State : Unbounded_String; + -- Name of MC/DC and ATCC state local variable for current decision + -- (MC/DC and ATCC only). procedure Output_Decision_Operand (Operand : Expr; @@ -5753,9 +5898,9 @@ package body Instrument.Ada_Unit is -- False, and an entry is made in the condition hash table. procedure Output_Header (T : Character; N : Ada_Node'Class); - -- Outputs a decision header node. T is I/W/E/P for IF/WHILE/EXIT WHEN/ - -- PRAGMA, and 'X' for the expression case. Resets Condition_Count to 0, - -- and initializes MCDC_State. + -- Outputs a decision header node. T is I/W/E/P/G/a or A for IF/WHILE/ + -- EXIT WHEN/PRAGMA/ENTRY GUARD/ASPECT, and 'X' for the expression case. + -- Resets Condition_Count to 0, and initializes MCDC_State. procedure Find_Nested_Decisions (Operand : Expr); -- This is called on node Operand, the top level node of a decision, @@ -5838,13 +5983,16 @@ package body Instrument.Ada_Unit is if Decision_Static or else Do_Not_Instrument then return; end if; - if MCDC_Coverage_Enabled then + + if MCDC_Coverage_Enabled + or else Assertion_Condition_Coverage_Enabled + then UIC.Source_Conditions.Append (Source_Condition' - (LL_SCO => SCOs.SCO_Table.Last, - Condition => N.As_Expr, - State => MCDC_State, - First => Condition_Count = 0)); + (LL_SCO => SCOs.SCO_Table.Last, + Condition => N.As_Expr, + State => Conditions_State, + First => Condition_Count = 0)); Condition_Count := Condition_Count + 1; end if; @@ -5897,6 +6045,9 @@ package body Instrument.Ada_Unit is Nam : Name_Id := Namet.No_Name; -- For the case of an aspect, aspect name + + Is_Contract : constant Boolean := T in 'a' | 'A' | 'P'; + -- Is the decision that of a contract begin case T is when 'I' | 'E' | 'W' | 'a' | 'A' => @@ -5906,7 +6057,7 @@ package body Instrument.Ada_Unit is Loc := Sloc (Parent (N)); - if T = 'a' or else T = 'A' then + if T in 'a' | 'A' then Nam := Aspect_Assoc_Name (N.Parent.As_Aspect_Assoc); end if; @@ -5972,9 +6123,14 @@ package body Instrument.Ada_Unit is Current_Decision := SCOs.SCO_Table.Last; if Coverage.Enabled (Decision) - or else MCDC_Coverage_Enabled + or else MCDC_Coverage_Enabled + or else Assertion_Condition_Coverage_Enabled then - if MCDC_Coverage_Enabled then + + if MCDC_Coverage_Enabled + or else (Is_Contract + and then Assertion_Condition_Coverage_Enabled) + then Condition_Count := 0; if UIC.MCDC_State_Inserter = null then @@ -5983,7 +6139,7 @@ package body Instrument.Ada_Unit is & "cannot find local declarative part for MC/DC", Kind => Diagnostics.Error); else - MCDC_State := To_Unbounded_String + Conditions_State := To_Unbounded_String (UIC.MCDC_State_Inserter.Insert_MCDC_State (UIC, Make_MCDC_State_Name (SCOs.SCO_Table.Last))); end if; @@ -6011,16 +6167,19 @@ package body Instrument.Ada_Unit is then UIC.Source_Decisions.Append (Source_Decision' - (LL_SCO => Current_Decision, - Decision => N.As_Expr, - State => MCDC_State)); + (LL_SCO => Current_Decision, + Decision => N.As_Expr, + State => Conditions_State, + Do_Not_Instrument => + Do_Not_Instrument or else Is_Static_Expr (N.As_Expr), + Is_Contract => Is_Contract)); end if; end if; -- For an aspect specification, which will be rewritten into a -- pragma, enter a hash table entry now. - if T = 'a' then + if T in 'a' | 'A' then Hash_Entries.Append ((Loc, Current_Decision)); end if; @@ -6113,9 +6272,15 @@ package body Instrument.Ada_Unit is SCOs.SCO_Table.Table (SCOs.SCO_Table.Last).Last := True; end if; - -- Process any embedded decisions + -- Process any embedded decisions. + -- For the sake of simplicity the coverage of nested decisions + -- in contract decisions should not be checked. Therefore they + -- should be instrumented. + + if T /= 'P' then + Find_Nested_Decisions (EN); + end if; - Find_Nested_Decisions (EN); return Over; end; end if; @@ -7112,10 +7277,15 @@ package body Instrument.Ada_Unit is E.Unit_Buffers := To_Nodes (RH, UIC.Pure_Buffer_Unit.Unit); E.Statement_Buffer := Indexed_Buffer (Statement_Buffer_Name); - if Coverage.Enabled (Decision) or else MCDC_Coverage_Enabled then + if Coverage.Enabled (Decision) + or else MCDC_Coverage_Enabled + or else Assertion_Condition_Coverage_Enabled + then E.Decision_Buffer := Indexed_Buffer (Decision_Buffer_Name); - if MCDC_Coverage_Enabled then + if MCDC_Coverage_Enabled + or else Assertion_Condition_Coverage_Enabled + then E.MCDC_Buffer := Indexed_Buffer (MCDC_Buffer_Name); end if; end if; @@ -8344,16 +8514,30 @@ package body Instrument.Ada_Unit is -- Insert calls to condition/decision witnesses - if Coverage.Enabled (Decision) or else MCDC_Coverage_Enabled then + if Coverage.Enabled (Decision) or else MCDC_Coverage_Enabled + or else Assertion_Condition_Coverage_Enabled + then for SD of UIC.Source_Decisions loop declare HL_SCO : constant SCO_Id := SCO_Map (SD.LL_SCO); + Should_Instrument : constant Boolean := + ((not SD.Is_Contract + and then (Coverage.Enabled (Decision) + or else MCDC_Coverage_Enabled)) + or else (SD.Is_Contract + and then Assertion_Coverage_Enabled)); begin - Insert_Decision_Witness (UIC, SD, Path_Count (HL_SCO)); + if SD.Do_Not_Instrument then + Set_Decision_SCO_Non_Instr (HL_SCO); + elsif Should_Instrument then + Insert_Decision_Witness (UIC, SD, Path_Count (HL_SCO)); + end if; end; end loop; - if MCDC_Coverage_Enabled then + if MCDC_Coverage_Enabled + or else Assertion_Condition_Coverage_Enabled + then -- As high-level SCO tables have been populated, we have built -- BDDs for each decision, and we can now set the correct MC/DC @@ -8415,7 +8599,8 @@ package body Instrument.Ada_Unit is (D_SCO, Outcome); end loop; - if MCDC_Coverage_Enabled + if (MCDC_Coverage_Enabled + or else Assertion_Condition_Coverage_Enabled) and then D_Bit_Alloc.Path_Bits_Base /= No_Bit_Id then declare diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 4c7a72a6a..20f343bbe 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -198,6 +198,14 @@ private State : Ada.Strings.Unbounded.Unbounded_String; -- Name of MC/DC state local variable + + Do_Not_Instrument : Boolean; + -- Whether this decision should not be instrumented. This is set to True + -- when instrumenting the decision could create invalid Ada code. + + Is_Contract : Boolean := False; + -- Whether the decision belongs to an assert-like pragma statement or an + -- equivalent aspect. end record; type Source_Condition is record diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 67c487389..60433ca33 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -203,7 +203,8 @@ package body Instrument.Common is -- If appropriate, allocate path bits for MC/DC: one bit per path in -- the decision. - if Coverage.MCDC_Coverage_Enabled + if (Coverage.MCDC_Coverage_Enabled + or else Coverage.Assertion_Condition_Coverage_Enabled) and then Length (State_Variable) > 0 and then Path_Count > 0 and then Path_Count < Get_Path_Count_Limit diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 3bc48f31c..8b4d12dcb 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -334,17 +334,6 @@ package body SC_Obligations is function To_Statement_Kind (C : Character) return Statement_Kind; -- Convert character code for statement kind to corresponding enum value - -- Decision_Kind denotes the various decision kinds identified in SCOs - - type Decision_Kind is - (If_Statement, - Exit_Statement, - Entry_Guard, - Pragma_Decision, - While_Loop, - Expression, - Aspect); - function To_Decision_Kind (C : Character) return Decision_Kind; -- Convert character code for decision kind to corresponding enum value @@ -1806,6 +1795,19 @@ package body SC_Obligations is else Unknown); end Decision_Outcome; + ------------------- + -- Decision_Type -- + ------------------- + + function Decision_Type (SCO : SCO_Id) return Decision_Kind + is + D : constant SCO_Descriptor := SCO_Vector.Reference (SCO); + begin + pragma Assert (D.Kind = Decision); + + return D.D_Kind; + end Decision_Type; + ---------------------- -- Degraded_Origins -- ---------------------- @@ -2202,6 +2204,7 @@ package body SC_Obligations is -- Disabled pragma? SCOD.S_Kind = Disabled_Pragma_Statement; + end Ignore_SCO; ---------------------------- @@ -2390,7 +2393,7 @@ package body SC_Obligations is ------------------ function Is_Assertion (SCO : SCO_Id) return Boolean is - SCOD : SCO_Descriptor renames SCO_Vector (SCO); + SCOD : SCO_Descriptor renames SCO_Vector (SCO); begin pragma Assert (SCOD.Kind = Decision); case SCOD.D_Kind is @@ -2400,7 +2403,7 @@ package body SC_Obligations is -- in the enclosing statement SCO. return SCO_Vector (Enclosing_Statement (SCO)).Pragma_Name - /= Pragma_Debug; + /= Pragma_Debug; when Aspect => -- Always True for aspects (Pre/Post/Predicate/Invariant) @@ -2410,8 +2413,65 @@ package body SC_Obligations is when others => return False; end case; + end Is_Assertion; + --------------------------- + -- Is_Assertion_To_Cover -- + --------------------------- + + function Is_Assertion_To_Cover (SCO : SCO_Id) return Boolean + is + function Is_Pragma_Stmt_To_Cover (SCOD : SCO_Descriptor) return Boolean; + -- True if the pragma statement of SCOD belongs to the list of pragmas + -- supported by assertion coverage. + + function Is_Pragma_Stmt_To_Cover (SCOD : SCO_Descriptor) return Boolean + is + begin + pragma Assert + (SCOD.Kind = Statement and then SCOD.S_Kind = Pragma_Statement); + + return SCOD.Pragma_Name in + Pragma_Assert + | Pragma_Assert_And_Cut + | Pragma_Assume + | Pragma_Check + | Pragma_Loop_Invariant + | Pragma_Type_Invariant + | Pragma_Precondition + | Pragma_Postcondition; + end Is_Pragma_Stmt_To_Cover; + + SCOD : SCO_Descriptor renames SCO_Vector (SCO); + begin + if SCOD.Kind = Statement and then SCOD.S_Kind = Pragma_Statement then + return Is_Pragma_Stmt_To_Cover (SCOD); + + elsif SCOD.Kind = Decision then + case SCOD.D_Kind is + when Pragma_Decision => + return + Is_Pragma_Stmt_To_Cover (SCO_Vector (Enclosing_Statement (SCO))); + + when Aspect => + return SCOD.Aspect_Name in + Aspect_Type_Invariant + | Aspect_Pre + | Aspect_Post; + + when others => + return False; + end case; + + elsif SCOD.Kind = Condition then + return Is_Assertion_To_Cover (Enclosing_Decision (SCO)); + + else + return False; + end if; + end Is_Assertion_To_Cover; + ------------------- -- Is_Expression -- ------------------- @@ -2445,18 +2505,14 @@ package body SC_Obligations is begin -- Return whether S_SCOD is a pragma Assert/Check/Pre/Post - return (S_SCOD.S_Kind = Pragma_Statement - or else - S_SCOD.S_Kind = Disabled_Pragma_Statement) - and then (S_SCOD.Pragma_Name = Pragma_Assert - or else - S_SCOD.Pragma_Name = Pragma_Check - or else - S_SCOD.Pragma_Name = Pragma_Precondition - or else - S_SCOD.Pragma_Name = Pragma_Postcondition - or else - S_SCOD.Pragma_Name = Pragma_Loop_Invariant); + return (S_SCOD.S_Kind = Disabled_Pragma_Statement + or else S_SCOD.S_Kind = Pragma_Statement) + and then S_SCOD.Pragma_Name in + Pragma_Assert + | Pragma_Check + | Pragma_Precondition + | Pragma_Postcondition + | Pragma_Loop_Invariant; end; end Is_Expression; @@ -2533,12 +2589,9 @@ package body SC_Obligations is SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); pragma Assert (SCOD.Kind = Statement); begin - return (SCOD.S_Kind = Pragma_Statement - or else - SCOD.S_Kind = Disabled_Pragma_Statement) - and then (SCOD.Pragma_Name = Pragma_Precondition - or else - SCOD.Pragma_Name = Pragma_Postcondition); + return SCOD.S_Kind in Pragma_Statement | Disabled_Pragma_Statement + and then + SCOD.Pragma_Name in Pragma_Precondition | Pragma_Postcondition; end Is_Pragma_Pre_Post_Condition; ------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 2c12c5006..193e95c10 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -59,6 +59,21 @@ package SC_Obligations is subtype SFI_Vector is SFI_Vectors.Vector; + ------------------------ + -- Types of decisions -- + ------------------------ + + -- Decision_Kind denotes the various decision kinds identified in SCOs + + type Decision_Kind is + (If_Statement, + Exit_Statement, + Entry_Guard, + Pragma_Decision, + While_Loop, + Expression, + Aspect); + ----------------------- -- Compilation units -- ----------------------- @@ -546,6 +561,9 @@ package SC_Obligations is -- For a decision whose outcome is compile time known, return that outcome; -- otherwise return Unknown. + function Decision_Type (SCO : SCO_Id) return Decision_Kind; + -- Get the type of decision for SCO + function Has_Multipath_Condition (SCO : SCO_Id) return Boolean; -- True if decison's BDD has a node reachable through more than one path @@ -559,8 +577,13 @@ package SC_Obligations is -- expression appearing outside of a control structure. function Is_Assertion (SCO : SCO_Id) return Boolean; - -- True if SCO is for a pragma Assert/Pre/Postcondition/Check, or an - -- equivalent aspect. + -- True if SCO is for all pragmas except Debug and all aspects + + function Is_Assertion_To_Cover (SCO : SCO_Id) return Boolean; + -- True if the SCO is an assertion SCO that should be covered by any level + -- of assertion coverage (ATC, ATCC), i.e. Assert, Assert_And_Cut, Assume, + -- Check, Loop_Invariant, Type_Invariant, Precondition, Postcondition + -- pragmas and Type_Invariant, Precondition and Postcondition aspects. function Is_If_Expression (SCO : SCO_Id) return Boolean; -- True if SCO is the decision of an IF expression diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 9483aa805..e0ee59de6 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -94,7 +94,15 @@ package Switches is Show_MCDC_Vectors : Boolean := False; -- If True, show the evaluation vectors for each decision where there is - -- an MCDC violation. + -- an MCDC violation. The "--show-mcdc-vectors" switch is now deprecated. + -- Displaying the evaluation vectors is possible for assertion coverage, + -- in which case keeping "mcdc" in the name can be missleading. This switch + -- is replaced by "--show-condition-vectors" that behaves the same way for + -- both MCDC and ATCC. + + Show_Condition_Vectors : Boolean := False; + -- If True, show the evaluation vectors for each decision where there is + -- an MCDC or ATCC violation. Timezone : Any_Timezone := Local_Time; -- Control the date display format (either in local time, or UTC time) diff --git a/tools/gnatcov/traces_stats.adb b/tools/gnatcov/traces_stats.adb index a6bacaa17..0cb9a4411 100644 --- a/tools/gnatcov/traces_stats.adb +++ b/tools/gnatcov/traces_stats.adb @@ -70,6 +70,8 @@ package body Traces_Stats is Decision => +"decision", MCDC => +"MC/DC", UC_MCDC => +"UC MC/DC", + ATC => +"ATC", + ATCC => +"ATCC", others => +""); Res : Unbounded_String := +""; From e42a69d8d5be3b7a41ef0da8d0893672c1afa043 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 18 Sep 2023 17:14:05 +0200 Subject: [PATCH 0414/1483] Generate an empty buffers unit list that is -pedantic compliant --- .../no_uoi/Makefile | 11 +++++ .../integrated_instrumentation/no_uoi/pkg.c | 5 +++ .../integrated_instrumentation/no_uoi/test.c | 8 ++++ .../integrated_instrumentation/no_uoi/test.py | 42 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 27 ++++++++---- 5 files changed, 84 insertions(+), 9 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/no_uoi/Makefile create mode 100644 testsuite/tests/integrated_instrumentation/no_uoi/pkg.c create mode 100644 testsuite/tests/integrated_instrumentation/no_uoi/test.c create mode 100644 testsuite/tests/integrated_instrumentation/no_uoi/test.py diff --git a/testsuite/tests/integrated_instrumentation/no_uoi/Makefile b/testsuite/tests/integrated_instrumentation/no_uoi/Makefile new file mode 100644 index 000000000..922360d92 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/no_uoi/Makefile @@ -0,0 +1,11 @@ +CC=g++ +OBJ = pkg.o test.o + +%.o: %.c + $(CC) -c -pedantic -Wall -o $@ $< + +test: $(OBJ) + $(CC) -pedantic -o $@ $^ + +clean: + rm -f *.o test diff --git a/testsuite/tests/integrated_instrumentation/no_uoi/pkg.c b/testsuite/tests/integrated_instrumentation/no_uoi/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/no_uoi/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/no_uoi/test.c b/testsuite/tests/integrated_instrumentation/no_uoi/test.c new file mode 100644 index 000000000..84fcd4703 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/no_uoi/test.c @@ -0,0 +1,8 @@ +extern int foo (); + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/no_uoi/test.py b/testsuite/tests/integrated_instrumentation/no_uoi/test.py new file mode 100644 index 000000000..85249f472 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/no_uoi/test.py @@ -0,0 +1,42 @@ +""" +Check that gnatcov does not break compilation with the -pedantic switch. The +code generated for an empty buffers list used to be uncompilable with +-pedantic. Note that -pedantic should only diagnose warnings and not errors, +so this is not expected, but we can work around the issue easily so fix the +wrong code. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + "--compilers=g++", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make", "-C", "..", "test"], for_pgm=False) + +# Run the executable +cmdrun(["../test"], for_pgm=False) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index d23e14f33..d661caa96 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -4413,15 +4413,24 @@ package body Instrument.C is CU_File.Put_Line (Self.Extern_Prefix & Buffer_Array_Decl & ";"); CU_File.Put_Line (Buffer_Array_Decl & " = {"); CU_File.Put_Line (" " & Buffer_Unit_Length & ","); - CU_File.Put_Line - (" (const struct gnatcov_rts_coverage_buffers_group *[]) {"); - for BS of Buffer_Symbols loop - CU_File.Put (" &" & (+BS)); - if BS /= Buffer_Symbols.Last_Element then - CU_File.Put_Line (","); - end if; - end loop; - CU_File.Put_Line ("}};"); + if String_Sets.Length (Buffer_Symbols) = 0 then + + -- If there are no units of interest, create a NULL pointer to avoid + -- having an empty array. + + CU_File.Put_Line ("NULL"); + else + CU_File.Put_Line + (" (const struct gnatcov_rts_coverage_buffers_group *[]) {"); + for BS of Buffer_Symbols loop + CU_File.Put (" &" & (+BS)); + if BS /= Buffer_Symbols.Last_Element then + CU_File.Put_Line (","); + end if; + end loop; + CU_File.Put_Line ("}"); + end if; + CU_File.Put_Line ("};"); return CU_Name; end Emit_Buffers_List_Unit; From 8f433cdf9b7e74afdba04efe71745ff1a3dc365c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 19 Sep 2023 17:44:10 +0200 Subject: [PATCH 0415/1483] document subprograms of interest --- doc/gnatcov/units_of_interest.rst | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/doc/gnatcov/units_of_interest.rst b/doc/gnatcov/units_of_interest.rst index b46112e49..10cf8180a 100644 --- a/doc/gnatcov/units_of_interest.rst +++ b/doc/gnatcov/units_of_interest.rst @@ -203,6 +203,23 @@ and then executing:: gnatcov --units=@units.list +Conveying *subprograms* of interest +********************************* + +|gcv| enables even finer grain control through the use of ``--subprograms`` +switch, which restricts coverage analysis to the specified list of subprograms +of interest. + +The ``--subprograms`` switch expects a ``:`` argument, +where ```` is the full path to the subprogram source, and +``line`` is the specification line for Ada subprograms, and the body line for +C/C++ functions. + +Every coverage obligation from non subprograms of interest is discarded and +reported as *no code* in the various output formats, and the associated coverage +data is ignored. This means that checkpoints will hold coverage data for +subprograms of interest only. + .. _gpr_context: Other switches or attributes of importance From 6f835aece76dde10c146f98446cd9ce139459493 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 18 Sep 2023 18:03:31 +0200 Subject: [PATCH 0416/1483] Instrument.C: fix issue related to metaprogramming instances Do not instrument decisions in sources of interest whose parent statement does not belong to a source of interest. This can happen with metaprogramming instances in C/C++. --- testsuite/tests/instr-cov/c_metaprog/main.c | 8 ++++++ .../instr-cov/c_metaprog/meta_print_msg.h | 6 +++++ testsuite/tests/instr-cov/c_metaprog/test.opt | 2 ++ testsuite/tests/instr-cov/c_metaprog/test.py | 27 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 9 ++++++- 5 files changed, 51 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/instr-cov/c_metaprog/main.c create mode 100644 testsuite/tests/instr-cov/c_metaprog/meta_print_msg.h create mode 100644 testsuite/tests/instr-cov/c_metaprog/test.opt create mode 100644 testsuite/tests/instr-cov/c_metaprog/test.py diff --git a/testsuite/tests/instr-cov/c_metaprog/main.c b/testsuite/tests/instr-cov/c_metaprog/main.c new file mode 100644 index 000000000..b745967e0 --- /dev/null +++ b/testsuite/tests/instr-cov/c_metaprog/main.c @@ -0,0 +1,8 @@ +int +main () +{ + int a = 0; +#define DECISION a +#include "meta_print_msg.h" + return 0; +} diff --git a/testsuite/tests/instr-cov/c_metaprog/meta_print_msg.h b/testsuite/tests/instr-cov/c_metaprog/meta_print_msg.h new file mode 100644 index 000000000..4bc402f05 --- /dev/null +++ b/testsuite/tests/instr-cov/c_metaprog/meta_print_msg.h @@ -0,0 +1,6 @@ +#include + +#ifdef DECISION +if (DECISION) + printf("Hello world!\n"); +#endif diff --git a/testsuite/tests/instr-cov/c_metaprog/test.opt b/testsuite/tests/instr-cov/c_metaprog/test.opt new file mode 100644 index 000000000..eb40c018e --- /dev/null +++ b/testsuite/tests/instr-cov/c_metaprog/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD Check instrumentation-specific behavior + diff --git a/testsuite/tests/instr-cov/c_metaprog/test.py b/testsuite/tests/instr-cov/c_metaprog/test.py new file mode 100644 index 000000000..4d3a59348 --- /dev/null +++ b/testsuite/tests/instr-cov/c_metaprog/test.py @@ -0,0 +1,27 @@ +""" +Checks that gnatcov does not instrument decisions in sources of interest whose +parent statement does not belong to a source of interest. This can happen with +metaprogramming instances in C/C++. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt+decision", + mains=["main"], + extra_instr_args=["--ignore-source-files=meta_print_msg.h"], + extra_coverage_args=["-axcov"], + trace_mode="src", +) + +check_xcov_reports("obj/*.xcov", {"obj/main.c.xcov": {"+": {4, 7}}}) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index d661caa96..973136031 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -1951,6 +1951,13 @@ package body Instrument.C is Append (Trailing_Braces, '}'); end if; + -- If this statement does not belong to a source of interest, skip + -- it altogether. + + if Is_Null (N) or not Is_Source_Of_Interest (UIC, N) then + return; + end if; + -- Initialize or extend current statement sequence. Note that for -- special cases such as IF and SWITCH statements we will modify -- the range to exclude internal statements that should not be @@ -2248,7 +2255,7 @@ package body Instrument.C is -- statement source location range. begin - if Is_Null (N) or else not Is_Source_Of_Interest (UIC, N) then + if Is_Null (N) then return; end if; From 609d952575b7f446c3cdff21ac4a3375c2b37fd1 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 21 Sep 2023 11:22:26 +0200 Subject: [PATCH 0417/1483] tests/instr-cov/c_metaprog: avoid dependency to printf Modify the test to avoid using printf as it does not compile on some cross targets (e.g. arm-elf with a light-stm32f4 RTS). --- testsuite/tests/instr-cov/c_metaprog/main.c | 4 ++-- testsuite/tests/instr-cov/c_metaprog/meta_inc.h | 4 ++++ testsuite/tests/instr-cov/c_metaprog/meta_print_msg.h | 6 ------ testsuite/tests/instr-cov/c_metaprog/test.py | 2 +- 4 files changed, 7 insertions(+), 9 deletions(-) create mode 100644 testsuite/tests/instr-cov/c_metaprog/meta_inc.h delete mode 100644 testsuite/tests/instr-cov/c_metaprog/meta_print_msg.h diff --git a/testsuite/tests/instr-cov/c_metaprog/main.c b/testsuite/tests/instr-cov/c_metaprog/main.c index b745967e0..3792c88b9 100644 --- a/testsuite/tests/instr-cov/c_metaprog/main.c +++ b/testsuite/tests/instr-cov/c_metaprog/main.c @@ -2,7 +2,7 @@ int main () { int a = 0; -#define DECISION a -#include "meta_print_msg.h" +#define DECISION 1 +#include "meta_inc.h" return 0; } diff --git a/testsuite/tests/instr-cov/c_metaprog/meta_inc.h b/testsuite/tests/instr-cov/c_metaprog/meta_inc.h new file mode 100644 index 000000000..06588cca4 --- /dev/null +++ b/testsuite/tests/instr-cov/c_metaprog/meta_inc.h @@ -0,0 +1,4 @@ +#ifdef DECISION +if (DECISION) + a++; +#endif diff --git a/testsuite/tests/instr-cov/c_metaprog/meta_print_msg.h b/testsuite/tests/instr-cov/c_metaprog/meta_print_msg.h deleted file mode 100644 index 4bc402f05..000000000 --- a/testsuite/tests/instr-cov/c_metaprog/meta_print_msg.h +++ /dev/null @@ -1,6 +0,0 @@ -#include - -#ifdef DECISION -if (DECISION) - printf("Hello world!\n"); -#endif diff --git a/testsuite/tests/instr-cov/c_metaprog/test.py b/testsuite/tests/instr-cov/c_metaprog/test.py index 4d3a59348..673ffd875 100644 --- a/testsuite/tests/instr-cov/c_metaprog/test.py +++ b/testsuite/tests/instr-cov/c_metaprog/test.py @@ -17,7 +17,7 @@ gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), covlevel="stmt+decision", mains=["main"], - extra_instr_args=["--ignore-source-files=meta_print_msg.h"], + extra_instr_args=["--ignore-source-files=meta_inc.h"], extra_coverage_args=["-axcov"], trace_mode="src", ) From 571e9c14b5a8f0f57026ed218278d15175afce3d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 21 Sep 2023 11:26:12 +0200 Subject: [PATCH 0418/1483] tests/subp_of_interest: kill test under 5.04 This test uses aspects, which are not available in older Ada versions. --- testsuite/tests/subp_of_interest/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/subp_of_interest/test.opt diff --git a/testsuite/tests/subp_of_interest/test.opt b/testsuite/tests/subp_of_interest/test.opt new file mode 100644 index 000000000..fc0b26792 --- /dev/null +++ b/testsuite/tests/subp_of_interest/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Uses Ada_2012 code constructs (aspects) From 7953975290de1484d317b34982dbbc26a4d4180e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 20 Sep 2023 17:45:00 +0200 Subject: [PATCH 0419/1483] clang-wrapper.cc: fix clang_getCalleeName The callee declaration can be, e.g. a parameter declaration if the call expression is a parameter callback, which is not a derived type of FunctionDecl, and thus can't be casted to it. Only deal with FunctionDecl (and FunctionTemplateDecl) type derivations and return an empty strings for the other cases. --- tools/gnatcov/clang-wrapper.cc | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 8b207f2da..4554dcc9c 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -487,12 +487,19 @@ clang_getCalleeName (CXCursor C) return createDup (FunctionName.getAsString ().c_str ()); }; - const clang::FunctionDecl *FD; - if (D->getKind () == Decl::FunctionTemplate) - FD = (cast (D))->getTemplatedDecl (); - else - FD = cast (D); - return getFunctionDeclName (FD); + switch (D->getKind ()) + { + case Decl::FunctionTemplate: + return getFunctionDeclName ((cast (D))->getTemplatedDecl ()); + case Decl::Function: + case Decl::CXXMethod: + case Decl::CXXConstructor: + case Decl::CXXDestructor: + case Decl::CXXConversion: + return getFunctionDeclName (cast (D)); + default: + return createEmpty (); + } } } return createEmpty (); From 5c838af3f32f8351e2d4ec862902db56a2ac6081 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 20 Sep 2023 16:11:38 +0200 Subject: [PATCH 0420/1483] Instrument.C: avoid clobbering the Scopes_In_Files_Map We were leaving erased file scopes in the Scopes_In_Files_Map which resulted in a crash when calling multiple times Remap_Scopes on this clobbered map. Fix this to leave it in a consistent state and properly remove empty file scopes. --- testsuite/tests/subp_of_interest_c/src/bar.h | 5 +++ testsuite/tests/subp_of_interest_c/src/main.c | 10 +++++ testsuite/tests/subp_of_interest_c/src/pkg.c | 5 +++ testsuite/tests/subp_of_interest_c/src/pkg.h | 1 + testsuite/tests/subp_of_interest_c/test.py | 41 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 34 ++++++++------- 6 files changed, 81 insertions(+), 15 deletions(-) create mode 100644 testsuite/tests/subp_of_interest_c/src/bar.h create mode 100644 testsuite/tests/subp_of_interest_c/src/main.c create mode 100644 testsuite/tests/subp_of_interest_c/src/pkg.c create mode 100644 testsuite/tests/subp_of_interest_c/src/pkg.h create mode 100644 testsuite/tests/subp_of_interest_c/test.py diff --git a/testsuite/tests/subp_of_interest_c/src/bar.h b/testsuite/tests/subp_of_interest_c/src/bar.h new file mode 100644 index 000000000..291781351 --- /dev/null +++ b/testsuite/tests/subp_of_interest_c/src/bar.h @@ -0,0 +1,5 @@ +int +bar () +{ + return 0; +} diff --git a/testsuite/tests/subp_of_interest_c/src/main.c b/testsuite/tests/subp_of_interest_c/src/main.c new file mode 100644 index 000000000..18f907090 --- /dev/null +++ b/testsuite/tests/subp_of_interest_c/src/main.c @@ -0,0 +1,10 @@ +#include "bar.h" +#include "pkg.h" + +int +main () +{ + foo (); + bar (); + return 0; +} diff --git a/testsuite/tests/subp_of_interest_c/src/pkg.c b/testsuite/tests/subp_of_interest_c/src/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/subp_of_interest_c/src/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/subp_of_interest_c/src/pkg.h b/testsuite/tests/subp_of_interest_c/src/pkg.h new file mode 100644 index 000000000..f8f1dde0b --- /dev/null +++ b/testsuite/tests/subp_of_interest_c/src/pkg.h @@ -0,0 +1 @@ +extern int foo (); diff --git a/testsuite/tests/subp_of_interest_c/test.py b/testsuite/tests/subp_of_interest_c/test.py new file mode 100644 index 000000000..2f4db72d4 --- /dev/null +++ b/testsuite/tests/subp_of_interest_c/test.py @@ -0,0 +1,41 @@ +""" +Check that the subprograms of interest mechanism works as expected on a C +example. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +cov_args = build_run_and_coverage( + gprsw=GPRswitches( + gprfor(srcdirs=os.path.join("..", "src"), mains=["main.c"]) + ), + covlevel="stmt", + mains=["main"], + trace_mode='src', + extra_coverage_args=[ + "-axcov", + "--subprograms", + f"{os.path.join('..', 'src', 'pkg.c')}:1", + ], +) + +check_xcov_reports( + "*.xcov", + { + "main.c.xcov": {}, + "bar.h.xcov": {}, + "pkg.c.xcov": {"+": {4}}, + }, + "obj", +) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 973136031..aa7354b96 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -150,6 +150,8 @@ package body Instrument.C is -- Convert low level SCOs in each scope for each file to high-level SCOs -- using the mapping in SCO_Map. Set the file's SCO range to cover all of -- its scopes' SCO ranges. + -- + -- Also remove from the Scopes map empty file scopes. overriding procedure Append_SCO (Pass : Instrument_Pass_Kind; @@ -491,10 +493,6 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context'Class; N : Cursor_T) is - Inserted : Boolean; - - File_Scope_Position : Scopes_In_Files_Map.Cursor; - procedure Enter_File_Scope (UIC : in out C_Unit_Inst_Context'Class; SFI : Source_File_Index) @@ -508,7 +506,11 @@ package body Instrument.C is procedure Enter_File_Scope (UIC : in out C_Unit_Inst_Context'Class; - SFI : Source_File_Index) is + SFI : Source_File_Index) + is + File_Scope_Position : Scopes_In_Files_Map.Cursor; + + Inserted : Boolean; begin if not UIC.Scopes.Contains (SFI) then @@ -629,24 +631,26 @@ package body Instrument.C is procedure Remap_Scopes (Scopes : in out Scopes_In_Files_Map.Map; - SCO_Map : LL_HL_SCO_Map) is + SCO_Map : LL_HL_SCO_Map) + is + Res : Scopes_In_Files_Map.Map; begin for Cur in Scopes.Iterate loop declare - Ref : constant Scopes_In_Files_Map.Reference_Type := - Scopes.Reference (Cur); - File_Scope : Scope_Entity renames - Scope_Entities_Trees.Element (Ref.File_Scope_Entity); + File_Scope : File_Scope_Type := + Scopes_In_Files_Map.Element (Cur); + File_Scope_Entity : Scope_Entity renames + Scope_Entities_Trees.Element (File_Scope.File_Scope_Entity); begin - -- If the file scope is empty, remove it + -- If the file scope is empty, do not add it to the resulting map - if File_Scope.To < File_Scope.From then - Ref.Scope_Entities.Delete_Subtree (Ref.File_Scope_Entity); - else - Remap_Scope_Entities (Ref.Scope_Entities, SCO_Map); + if File_Scope_Entity.To >= File_Scope_Entity.From then + Remap_Scope_Entities (File_Scope.Scope_Entities, SCO_Map); + Res.Insert (Scopes_In_Files_Map.Key (Cur), File_Scope); end if; end; end loop; + Scopes := Res; end Remap_Scopes; ---------------- From ab5faa70804359a6c3ec3dc44a32c5c5f20f4b3d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 20 Sep 2023 16:14:54 +0200 Subject: [PATCH 0421/1483] Instrument.C: Remap_Scopes only once The scope remapping was implemented in a loop over UIC.Instrumented_Entities, meaning that we were remapping them several time. One time is enough, so extract this code of the loop. --- testsuite/tests/subp_of_interest_c/test.py | 4 +++- tools/gnatcov/instrument-c.adb | 28 +++++++++++----------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/testsuite/tests/subp_of_interest_c/test.py b/testsuite/tests/subp_of_interest_c/test.py index 2f4db72d4..c2c209bf0 100644 --- a/testsuite/tests/subp_of_interest_c/test.py +++ b/testsuite/tests/subp_of_interest_c/test.py @@ -1,6 +1,8 @@ """ Check that the subprograms of interest mechanism works as expected on a C -example. +example. It also acts as a regression testcase as gnatcov used to crash when +instrumenting a source including multiple headers, with at last one of them +not having any coverage obligation. """ import os diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index aa7354b96..525533b27 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3294,23 +3294,23 @@ package body Instrument.C is -- Associate these bit maps to the corresponding CU Set_Bit_Maps (UIC.CUs.Element (SFI), Bit_Maps); + end; + end loop; - -- Iterate through the package level body entities + -- Iterate through the package level body entities - Remap_Scopes (UIC.Scopes, SCO_Map); + Remap_Scopes (UIC.Scopes, SCO_Map); - for C in UIC.Scopes.Iterate loop - declare - CU : constant Created_Unit_Maps.Cursor := - UIC.CUs.Find (Scopes_In_Files_Map.Key (C)); - begin - if Created_Unit_Maps.Has_Element (CU) then - Set_Scope_Entities - (Created_Unit_Maps.Element (CU), - Scopes_In_Files_Map.Element (C).Scope_Entities); - end if; - end; - end loop; + for C in UIC.Scopes.Iterate loop + declare + CU : constant Created_Unit_Maps.Cursor := + UIC.CUs.Find (Scopes_In_Files_Map.Key (C)); + begin + if Created_Unit_Maps.Has_Element (CU) then + Set_Scope_Entities + (Created_Unit_Maps.Element (CU), + Scopes_In_Files_Map.Element (C).Scope_Entities); + end if; end; end loop; end; From 3b4dd7a3cf61c9b4eb4f6ba98e9a53c700cd08d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Thu, 21 Sep 2023 12:08:19 +0200 Subject: [PATCH 0422/1483] Fix unhandled exceptions in assertion test For light runtimes the exception raised by unsatisfied assertions can only be caught by Silent_Last_Chance, rendering the exception catcher in the tests uncovered. Only rely on Silent_Last_Chance for the needed cases. --- .../tests/O212-062-assertions/src/assertions_2.adb | 12 ++++-------- .../O212-062-assertions/src/catch_assertions_2.adb | 11 +++++++++++ .../O212-062-assertions/src/catch_expr_func.adb | 11 +++++++++++ .../tests/O212-062-assertions/src/expr_func.adb | 8 ++------ .../O212-062-assertions/src/test_assertions_2.adb | 5 ++--- .../tests/O212-062-assertions/src/test_expr_func.adb | 5 ++--- .../O212-062-assertions/src/test_type_inv_false.adb | 1 + 7 files changed, 33 insertions(+), 20 deletions(-) create mode 100644 testsuite/tests/O212-062-assertions/src/catch_assertions_2.adb create mode 100644 testsuite/tests/O212-062-assertions/src/catch_expr_func.adb diff --git a/testsuite/tests/O212-062-assertions/src/assertions_2.adb b/testsuite/tests/O212-062-assertions/src/assertions_2.adb index 3402f6b39..45f0b01d2 100644 --- a/testsuite/tests/O212-062-assertions/src/assertions_2.adb +++ b/testsuite/tests/O212-062-assertions/src/assertions_2.adb @@ -1,16 +1,12 @@ -with Ada.Assertions; with Assertions; use Assertions; +with Silent_Last_Chance; procedure Assertions_2 is Y : Integer := 2; begin - begin - -- Call to Foo with a parameter that does not satisfy the - -- precondition. + -- Call to Foo with a parameter that does not satisfy the + -- precondition. - Y := Foo (-2); -- # foo_2 - exception - when Ada.Assertions.Assertion_Error => null; -- # catch_2 - end; + Y := Foo (-2); -- # foo_2 end Assertions_2; diff --git a/testsuite/tests/O212-062-assertions/src/catch_assertions_2.adb b/testsuite/tests/O212-062-assertions/src/catch_assertions_2.adb new file mode 100644 index 000000000..af280df14 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/catch_assertions_2.adb @@ -0,0 +1,11 @@ +with Ada.Assertions; +with Assertions_2; + +procedure Catch_Assertions_2 is +begin + begin + Assertions_2; + exception + when Ada.Assertions.Assertion_Error => null; + end; +end Catch_Assertions_2; diff --git a/testsuite/tests/O212-062-assertions/src/catch_expr_func.adb b/testsuite/tests/O212-062-assertions/src/catch_expr_func.adb new file mode 100644 index 000000000..0807c7ac7 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/src/catch_expr_func.adb @@ -0,0 +1,11 @@ +with Ada.Assertions; +with Expr_Func; + +procedure Catch_Expr_Func is +begin + begin + Expr_Func; + exception + when Ada.Assertions.Assertion_Error => null; + end; +end Catch_Expr_Func; diff --git a/testsuite/tests/O212-062-assertions/src/expr_func.adb b/testsuite/tests/O212-062-assertions/src/expr_func.adb index c0a4674ba..adfd417e4 100644 --- a/testsuite/tests/O212-062-assertions/src/expr_func.adb +++ b/testsuite/tests/O212-062-assertions/src/expr_func.adb @@ -1,7 +1,7 @@ pragma Assertion_Policy (Check); pragma Ada_2012; -with Ada.Assertions; +with Silent_Last_Chance; procedure Expr_Func is @@ -21,9 +21,5 @@ is begin Dummy := Foo (0); -- # foo_call - begin - Dummy := Bar (42); -- # bar_call - exception - when Ada.Assertions.Assertion_Error => null; -- # catch - end; + Dummy := Bar (42); -- # bar_call end Expr_Func; diff --git a/testsuite/tests/O212-062-assertions/src/test_assertions_2.adb b/testsuite/tests/O212-062-assertions/src/test_assertions_2.adb index 8af1b7f80..f271f4ae9 100644 --- a/testsuite/tests/O212-062-assertions/src/test_assertions_2.adb +++ b/testsuite/tests/O212-062-assertions/src/test_assertions_2.adb @@ -1,8 +1,8 @@ -with Assertions_2; +with Catch_Assertions_2; procedure Test_Assertions_2 is begin - Assertions_2; + Catch_Assertions_2; end Test_Assertions_2; --# assertions.ads @@ -27,4 +27,3 @@ end Test_Assertions_2; -- /same_ret/ l- ## s- --# assertions_2.adb -- /foo_2/ l+ ## c! --- /catch_2/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/test_expr_func.adb b/testsuite/tests/O212-062-assertions/src/test_expr_func.adb index 1eb1d538d..b3b9663d9 100644 --- a/testsuite/tests/O212-062-assertions/src/test_expr_func.adb +++ b/testsuite/tests/O212-062-assertions/src/test_expr_func.adb @@ -1,8 +1,8 @@ -with Expr_Func; +with Catch_Expr_Func; procedure Test_Expr_Func is begin - Expr_Func; + Catch_Expr_Func; end Test_Expr_Func; --# expr_func.adb @@ -15,4 +15,3 @@ end Test_Expr_Func; -- /dummy_decl/ l+ ## 0 -- /foo_call/ l+ ## 0 -- /bar_call/ l+ ## 0 --- /catch/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/test_type_inv_false.adb b/testsuite/tests/O212-062-assertions/src/test_type_inv_false.adb index 86eec5709..9460d9bcb 100644 --- a/testsuite/tests/O212-062-assertions/src/test_type_inv_false.adb +++ b/testsuite/tests/O212-062-assertions/src/test_type_inv_false.adb @@ -1,3 +1,4 @@ +with Silent_Last_Chance; with Pack_Type_Invariant; with Ada.Assertions; From 6c0ff34cec170d370762a2104611b50136277c88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Thu, 21 Sep 2023 12:37:06 +0200 Subject: [PATCH 0423/1483] Deactivate assertion tests for 5.04a1 and 7.1.2 These tests make use of unsupported features for both of the versions --- testsuite/tests/O212-062-assertions/test.opt | 1 + testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt | 1 + 2 files changed, 2 insertions(+) diff --git a/testsuite/tests/O212-062-assertions/test.opt b/testsuite/tests/O212-062-assertions/test.opt index 74b2fb73e..0cfac7221 100644 --- a/testsuite/tests/O212-062-assertions/test.opt +++ b/testsuite/tests/O212-062-assertions/test.opt @@ -1 +1,2 @@ bin-traces XFAIL Assertion coverage not yet supported for binary traces +5.04a1|7.1.2 DEAD Test contains expression functions and Ada_2012 features diff --git a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt index 74b2fb73e..f1baab314 100644 --- a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt +++ b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt @@ -1 +1,2 @@ bin-traces XFAIL Assertion coverage not yet supported for binary traces +5.04a1|7.1.2 DEAD Test contains expression function and Ada_2012 features From 771168e139f59890f7588a40df911d0fbeb3703f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 21 Sep 2023 18:39:50 +0200 Subject: [PATCH 0424/1483] Follow pattern convention in the --subprograms help message --- tools/gnatcov/command_line.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 906b862e7..abccb9aae 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -1109,7 +1109,7 @@ package Command_Line is Internal => False), Opt_Subp_Of_Interest => Create (Long_Name => "--subprograms", - Pattern => ":", + Pattern => "FILE:LINE", Help => "Restrict coverage analysis to specific subprograms designated by" & " the specification source line for Ada, and by the body source" From d9558a7ee48c8ef466d126e81f378b8819c68b00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Thu, 21 Sep 2023 17:21:52 +0200 Subject: [PATCH 0425/1483] Simplify missing source cov levels on cmd line warning Instead of listing all possible source coverage combinations, express them as a regular expression. --- tools/gnatcov/command_line.ads | 2 +- tools/gnatcov/coverage_options.adb | 14 ++++++++++++-- tools/gnatcov/coverage_options.ads | 6 +++--- tools/gnatcov/gnatcov_bits_specific.adb | 8 ++++---- 4 files changed, 20 insertions(+), 10 deletions(-) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index abccb9aae..14d854347 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -699,7 +699,7 @@ package Command_Line is & " " & Object_Level_Options (Separator => ", ") & " (object coverage)" & ASCII.LF - & " " & Source_Level_Options (Separator => ", ") + & " " & Source_Level_Options & " (source coverage)" & ASCII.LF & "For the ""instrument"" command, " diff --git a/tools/gnatcov/coverage_options.adb b/tools/gnatcov/coverage_options.adb index a6b7c0acc..4b88eb86e 100644 --- a/tools/gnatcov/coverage_options.adb +++ b/tools/gnatcov/coverage_options.adb @@ -119,9 +119,19 @@ package body Coverage_Options is -- Source_Level_Options -- -------------------------- - function Source_Level_Options (Separator : String) return String is + function Source_Level_Options return String is + function Level_Str (L : Source_Coverage_Level) return String; + -- Return the lowercase string representation of L + + function Level_Str (L : Source_Coverage_Level) return String + is (To_Lower (L'Img)); begin - return Level_Options (Source_Levels_Option_Map, Separator); + return Level_Str (Stmt) + & "(+" & Level_Str (Decision) & "|" + & "+" & Level_Str (MCDC) & "|" + & "+" & Level_Str (UC_MCDC) & ")?" + & "(+" & Level_Str (ATC) & "|" + & "+" & Level_Str (ATCC) & ")?"; end Source_Level_Options; ------------------------------------- diff --git a/tools/gnatcov/coverage_options.ads b/tools/gnatcov/coverage_options.ads index 2107e59a7..db2e06d0f 100644 --- a/tools/gnatcov/coverage_options.ads +++ b/tools/gnatcov/coverage_options.ads @@ -69,9 +69,9 @@ package Coverage_Options is function Coverage_Option_Value (L : Levels_Type) return String; -- Return the coverage option value corresponding to L - function Source_Level_Options (Separator : String) return String; - -- Return a string expression listing the valid --level alternatives - -- for source coverage, separated by Separator. + function Source_Level_Options return String; + -- Return a regular expression string describing the valid --level + -- combinations of source coverage levels. function Object_Level_Options (Separator : String) return String; -- Return a string expression describing valid --level alternatives diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 9e9c11af1..181e8cc41 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1067,12 +1067,12 @@ procedure GNATcov_Bits_Specific is Fatal_Error ("Instrumentation requires a source coverage level" & ASCII.LF - & " (--level=" & Source_Level_Options ("|") & ")"); + & " (--level=" & Source_Level_Options & ")"); elsif not Source_Coverage_Enabled then Warn ("Coverage level not specified on the command" & " line or in the project file (--level=" - & Source_Level_Options ("|") & "), defaulting to ""stmt""."); + & Source_Level_Options & "), defaulting to ""stmt""."); Set_Coverage_Levels ("stmt"); end if; @@ -1774,7 +1774,7 @@ begin if not (Source_Coverage_Enabled or else Object_Coverage_Enabled) then Warn ("Coverage level not specified on the command line or in the" - & " project file (--level=" & Source_Level_Options ("|") + & " project file (--level=" & Source_Level_Options & "|" & Object_Level_Options ("|") & "), defaulting to" & " ""stmt""."); Set_Coverage_Levels ("stmt"); @@ -1789,7 +1789,7 @@ begin ("""report"" output format (from --annotate) is" & " only for source coverage criteria" & ASCII.LF - & " (--level=" & Source_Level_Options ("|") + & " (--level=" & Source_Level_Options & ", not --level=" & Coverage_Option_Value (Current_Levels) & ")"); From 08df966253660b8055e50fe119414da622e6c8fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Fri, 22 Sep 2023 09:31:18 +0200 Subject: [PATCH 0426/1483] Fix list of disabled configs for assertion tests --- testsuite/tests/O212-062-assertions/test.opt | 2 +- testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/O212-062-assertions/test.opt b/testsuite/tests/O212-062-assertions/test.opt index 0cfac7221..a7e5600b6 100644 --- a/testsuite/tests/O212-062-assertions/test.opt +++ b/testsuite/tests/O212-062-assertions/test.opt @@ -1,2 +1,2 @@ bin-traces XFAIL Assertion coverage not yet supported for binary traces -5.04a1|7.1.2 DEAD Test contains expression functions and Ada_2012 features +5.04a1,7.1.2 DEAD Test contains expression functions and Ada_2012 features diff --git a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt index f1baab314..168d3ae58 100644 --- a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt +++ b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt @@ -1,2 +1,2 @@ bin-traces XFAIL Assertion coverage not yet supported for binary traces -5.04a1|7.1.2 DEAD Test contains expression function and Ada_2012 features +5.04a1,7.1.2 DEAD Test contains expression function and Ada_2012 features From 9796cb5cbfdae1ce81880cc48f7f665a6fb05ee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 12 Sep 2023 17:41:42 +0200 Subject: [PATCH 0427/1483] Doc: Document basic integration between gnattest and gnatfuzz Although the features are not mature, document them so as not to confuse users when seeing new command line options with no matching documentation in the users' guide. --- doc/gnattest/gnattest_part.rst | 80 ++++++++++++++++++++++++--- doc/integration/gs_menu.png | Bin 0 -> 131154 bytes doc/integration/integration_part.rst | 69 +++++++++++++++++++++++ 3 files changed, 140 insertions(+), 9 deletions(-) create mode 100644 doc/integration/gs_menu.png diff --git a/doc/gnattest/gnattest_part.rst b/doc/gnattest/gnattest_part.rst index 734b58d5d..c30127ab7 100644 --- a/doc/gnattest/gnattest_part.rst +++ b/doc/gnattest/gnattest_part.rst @@ -926,10 +926,54 @@ The tool currently has the following limitations: .. _Automatic_testcase_generation: -Automatically generating test cases (alpha) -------------------------------------------- +Automatically generating test cases (experimental) +-------------------------------------------------- -``gnattest`` provides a switch ``--gen-test-vectors`` that can be used to +Please note that all the features described bellow are experimental, and the +interface is subject to change. + +GNATtest has the capability to generate test inputs for subprograms under test. + +.. _Tgen_Env: + +Setting up the test generation runtime +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Generation of values for Ada cannot be fully done statically, as the bounds of +some types may only be defined at runtime. As such, the test generation feature +requires the compilation and installation of a runtime project. + +The sources for that project are located at +``/share/tgen/tgen_rts /tmp/tgen_rts_src + + # Build the project + cd /tmp/tgen_rts_src + gprbuild -P tgen_rts.gpr + + # Install the project (removing the previous one if needed) + gprinstall --uninstall -P tgen_rts.gpr --prefix=/tmp/tgen_rts_install + gprinstall -p -P tgen_rts.gpr --prefix=/tmp/tgen_rts_install + + # Make it available to other tools + export GPR_PROJECT_PATH=/tmp/tgen_rts_install/share/gpr:$GPR_PROJECT_PATH + +Generating test inputs +^^^^^^^^^^^^^^^^^^^^^^ + +``gnattest`` provides a ``--gen-test-vectors`` switch that can be used to automatically generate test cases for all of the supported subprogram profiles. The number of generated test cases can be configured through the ``--gen-test-num`` switch. @@ -946,12 +990,23 @@ are true: 5. Any of the subprogram's "in" or "out" mode parameters is a private type of a nested package. -.. - TODO: document a bit the value generation (mostly random, except for - unconstrained arrays and discriminated record). +Input value generation currently follows a simple strategy for each input +parameter of the subprogram under test. Parameters of scalar types, and scalar +components of composite types have their values uniformly generated. For +unconstrained array types, a length is randomly chosen between 0 and 10 +elements, then the low bound is randomly chosen and the high bound computed +accordingly to those two first points. + +For record discriminants, different strategies are chosen depending on the use +of the discriminant within the record: If the discriminant constraints a array +component, then the array strategy described above is used. If the discriminant +is used in a variant part, generation will be biased in order to generated all +possible shapes of the record (i.e. explore all variants). Otherwise, these are +generated as any other scalar component. + The generated test cases are then stored in a ad-hoc (and yet to be specified) -JSON format, in files under the /gnattest/tests/JSON_Tests directory. +JSON format, in files under the ``/gnattest/tests/JSON_Tests`` directory. The generated JSON files are preserved through a ``gnattest`` rerun. The user is thus free to modify them, to e.g. fill in expected return values, though backward compatibility of the format is not guaranteed at this stage. @@ -959,8 +1014,15 @@ backward compatibility of the format is not guaranteed at this stage. ``gnattest`` also generates Ada files to actually execute the test cases. Each test vector has its own AUnit test case, and all test cases for a specific subprogram are all stored in a dedicated file, namely --test_data-test__.ad[bs]. The content of these -files is not preserved through a ``gnattest`` rerun. +``-test_data-test__.ad[bs]``, where +```` is the name of the unit in which the subprogram is declared, +```` is the name of the subprogram, and is a hash based +on the profile of the subprogram, in order to differentiate overloads. + +The content of these files are re-generated each time ``gnattest`` is invoked, +independently of the presence of the ``--gen-test-vectors`` switch on the +command line. It is thus not necessary to re-invoke ``gnattest`` with that +switch more than once, unless the goal is to generate additional test inputs. .. TODO: document the --unparse switch diff --git a/doc/integration/gs_menu.png b/doc/integration/gs_menu.png new file mode 100644 index 0000000000000000000000000000000000000000..c261b4fefd7e5bb72b119f0873cc103ab76667f8 GIT binary patch literal 131154 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%0DFO+zyPnj%9~L2 z2B00QiKb7g78h9_3;3(=THEE+uOUIg;1m#1S7ws!*&&jL#md?TW}ok{@^tc4mu8)Z zKXSf^yxX^Bw|%eBc)i=7Z?eOlTvn=Xl3f*{?|w9YS;og(8h1H*AbSS&v)?r6Sd%RN z2nhdjYF>7IQzZ+?ZT1A9tw`pz8@5L;a@Ynx1K0uZjXMf9QMxT@Ca1r@-=;#*|K}n3 zJq{WplnU|fk}T*vgpqmy>24M-&COI+3(((ffW8AKyw^*K=`?@NZxm~|Fn4F^(!r$U z0eWKbqwMLP5UUG_duDVD=49VZl`1Fom7nuXECTHekoEZ5D>Udd7$3TRnGL3*ihpe-q5(D1-KdSuACmUHkyomyhQ2_&>r*rr3ikUw%g zC#o0{p#;_lY}V9!Uz6mgT=l`PFHQyVV54 zKX7!zV}H{r`I-%qh>{9402Qh>-v_zm{t=vnAFhB41Jcx{5N=D{GwqJR=9(LAS~uDX zFhHh&=PUmT66<#OHYsmvih#{R2=cZWbur}GGI+J&3)ggR*iUIm8TWPD)|DDDYN6&dpAaC z87%eb5&v~!d8%%AQ;Wbv=2lGe8Hvy%uRM?kY zJ@hv1j0KX}bT=~Y61ISTrS{x!u`57Vm6`0AVtZw-fFD%^XHdJU)dayV@2+%6E?gZb%q^knGB0Rj*|b zDLQpIjUA2wnh(1g^KwT~8T5*;+jG7+!f?6Jc>5kieSMWd@?}avXLJCgI?G_YaC=vZ zU>k=|*qv1*Qsyh(`1s0a5Mh;`^%J2wdaPoz(UZ|s zG30{mhU1YDKV_*lHZqS*Um=&j3)68}IOH#)JhW;B%0HVUM--k8l7^5blF&B83u)+4 zqu?>Nkv#=*C7>+BpmmJ+V|`|TDPM-JC`qQ4X2%8juf3&2kVa#SH`9O&li~t7;?_vH zZcQgYjL^;5gBd>@1$vw<6kVU~Oj$G}SbW&|rq73Rwr;XzK9TjxBD^2%$%}v}VudfV z?pcRw_exUiuhunR15KGpXOg%d;rIb-aBB%XV4J%BLmr#M&*=1@k|u2Ix)6P|k~m*z zqtdJ|l+RubvXc_)@cU*knXP`wMowKx>+agQ9=CBaT~Ob+1bWoBq10=B#~tsq6^rM2K?gQH zzXm)$)XL(w-9YhU4o^=$~4^a`VI98is7$MT-r1KxuaJ(-ij#k9Zq|* zO#~DllKE0~Pf^#Cn7FscJ^mB3%#lPeZ~lD4q^S6jL2G8`YfK&byZ#-10?bf&E^oP} z@!W5S_j(7r?lT{SWr2A6N?qOlnNIg(Kqpko8PX9^sK(6tg9SjBB)Q<=O5{x`5g(D& z8_89mokeI8Qm-HSZnT05fEAb0^Aq9OBsvn%zJGd3c=E|k^*r}t*1J6FdRU1sx7)SD z=lq#8*t>S}OVqdzcE(d6${OZ>;$1!2hH$+Fxh^(@qS=P&yUvRyT34jZwjmTQa?Mw(cz#!dup&*>-l+ zLk5PqBWG0PW9-2IgH=0ocl$T}I?(DAKR;JF*gq)>N(UkigO2WQ1a)=wv7H84Xm$WP zT_~0rZP;m3m)C0G?8q{PfYHg$o?K%X9JGm+*BLweZ~xU7@yZ$>qHKuh)ttX_#L!&p-5qgiwf(%v+fH`L zibZ=D$I%nn$`2=UAE~dQjACY7ycBsPc{5}LSIiess6467igROqKcsW5Ui)F%gYa3s zrm!c;Cd#gEn^Mfjhe2uFF;ehI6OIiqR@hwzNTJZp<-iyJAS1ATjLJ#l=dSTNMe&L z8Js^sKYUaQZg-{4;mWR4(Hzi4UW?_v90p9xi}1gQJ*-NkIVu*vQKkI0h!(k$wpDc<%>u4pa9!29ng~9*43bvI5Mu5gVKJV z9*%+dCaygnNn(mAGcF1P1H*0V^J@A?ppE%r466!YQedG}vsIN<*{@;EY{S;N1_zTT z^|lP>C3=;v*21+`kfd;?_{yu#*f6y^TzgkLj)xu`iSZy)4iil##?h4C(j<5dCt5lt+J!{~_LRI%(o4p)<)kl=C&{~E6 z3~ZIc?X91}BOy+`6HH~P{}r}aXfQg_2*#k-9H`K89t!Q1imTSM`?IC2Y7}EJ<5)~) zPBhb7s>7*MmaObIcWGNW1Z%$MD}H3fex95AXkAy#Go~&xoEIaun(9`S>mG(AO zs@84R3%jY`ce7>iTo4*aMG5WvF(EfH_P4Q8jJ9Meo}(G$eTM?n)Lk2UN%L~L2!RIp z;(me3RlO+>^3REKY6(i-*3=b-=NG!92(5SopADFwZa}dEm=T&kNjoQg==UnuhZU(f zP<^jO5@S~iU_Ljy+8;L-i8d}CF)$o1SMm1t+B-RIrFrb@SLI+36U$mzSw$F`rZdQR zOc!d#EV#_}?AcX%jFLjjUE_M)f`j@1q7}%^=Z5gV5bN!}brT}mM2rrvHs5(G6Q{G7 zsoAjx3`fCylC>7UxKJGuPF`t{gbXZrus`of)Y9(|6B~O0_LRNSbuF0KEU8G^SOp`Q zo0GvgJE6UJGiqp(MF)p5`x21-uy&#sM&_;YBQFq15AZ1W>;7W@l9|hFSl-1$&FT1o zx-+l^?Y*olbJjBPur2U0Ei17BS`*6k8vyvlg?hXE9BD&R^0Sa?8GQ7)Cyz83ZvR%S&G&=m}dGXdJ9T9ek9#y^Nw4Xm$Bn z&Qu}f`c=a$AVGNer-9(SL1Ev;e7HsQNK~Eo8*z=D9_rB%3y#k8jF{w2QR1iv-h4+d zQx;IniiNROhV-;siHs9r!gbGLl&r?wM{n&b6g?6d3KvL(DMps0Q>*J_0s$3d^;_Cb zRE5VE?%&51=@!?^AC(-0?`Ud^mm;|sXW{>znI$z97--)?llzX3e=ND=cjXLEHz8rA z*~)Z&OCA`pfM(H}LRHx3^z8GS@^-mViTt;`PsFjw|lb)@g2f zRRMaXY$iq}74a9P$bC#92r3xNtmyddF&X1A^MU60>8AR?dG_TO-w>kLJBR!?-k@)rlF$R!2Rg# zPwnFm{SJ5~R~tyIxA7_59Mp&d!^&FP9mv4fRIlw~rHO!uSm_EzH~ICkc-)+EX(W7q zJ_|`xQ*$VZD*@U+8V1@kxVM*V)MV8M!W#?Y49z_y;BuF%%9&4v5^Df{q9B%Ezs~h4 zB2Te?`;%y}9TXTm>XPYvk2ZI>qN16n#!<^nz||L6zM=*`E^Qv{<}l0DaHZWZ6uY)X zrYl!>yt7{FU_>eMn6=Rh40zL8-Ebxh30UW8I06wNzvB-P zKa)CgRqvAk>?p$TWYZ=|150+m$XD%y?ExuV217SA(HfmKsrq7(QID=P_{2n4CaNp4 z@gstArx!iMNzLC^Lei62NCAlj2#c;4qi^4`ESz0qK@u#-b`R}<&|4+}O_g)9ZY$SV z1nzFHcA303Ckq9pNv!)tT*3-Mse)KWoEK(`dk?67>}}@JTn=^l^mFW>=qcs_W6$ z<}6v}0x4e|E+?wle3Cz&>n%#=77{MxeuO`gVW&IP&Oi}Oh9g}Wj+j%{eh?_NFW>ya{c+2v z%F!VxI5_KrueYR3#dTP41eZ^YtcR`f`OjkKSU9AMcU_AS>Fs!nCa*<;v+4U-4w;a+!U7>FE zKq9bo`qzg?narel719gKlb(!lMXQi04#=gzH6KL zu^byjg&|0SYl`cx|FY*8Qykrl@o(MfSBN~`b(lnf1{Y{Loqjs*3`Kl&Uvue@-s1A5W=XwM=Xo#N_X$fmoGJ-j;{*N}b= z%Bx;!|07OasZ>-{F$sEZHHDq!`?az#9?r>X(-hD0)e-XJ(UIw49`blUk!>-aaP@e1 zxdoM76*Y}G)9w%vrk0V|Se36+`MSAARaKRYEsvD~0Ep0s@35{O9x*8?s6JIyT;IP# zpuE7$!jF0%pDxZvZ*E-28=Wj+pxw`JuNF^ArcxxNDXUxZSh}dA?cPP)z_m5ea(}Zi z7hG0=hY2S^Y{3$UE|>`5=Q3f$Cksn*|3WYXz~%GqJ$_7Z(7b zs*|(s5 z?V*UB%vX~9qv~2!8q2walf1v!=lDO*uK1U8B^guGDT6-_`qw{#IHXoPUThC7jI8Qj z5(rhlQEuU;_DeT7j+B^7E&Oux88+~`7yAj+*N|#Zd^8z_+gi?s_WLJG@+gM7(BzB~ z%db1`2Hq*RgIPR9@+O;(1jbu3tT7;$V4Z<2-cE+u?YugI6=(kjH@N&RpsHaIWaY zK9dU*XS#VPGx9TTrXZVGXi)WNgtWU-jjB@#&X8=F*CJDchZi&gP#Nd{%8@|d0QWdz z>{@eai;FaHmgkA22W*8?Nj2x1%R)682sYEE_&Ks5wkJfgi}sJ|5q;o=_TK={BrDt5 z*_FF%+t{#jnYPM&3Wytj;_bIig29DqsxFYlst@eN{ z*TjAPHz?|H)A_ntO8fHC(#(!##AFHR<&`GyujMa)kttMI(KM{E<@H&sHQp_5ThlH+Hh{KJ4%}m+1fAUUmkBdkP z+33hVSg`#7;Kyz{1}}6_FMFvsOr?Ox`7@{@E4urL&I4OIk<-LOdGjGXe^v zP;fDsQPxCFbct7~N*_}y^ODisRZDFw<)NpwbEq@$J5CR=T6W)u zlm=xO$+N`eD}Rp#WjTUp$!#KB^UQwQ@qeRwWub;h0vbE7@d>q1hlDfB_ET&X{;^RF zGc%=9Nh1df9(mOsEa|a>;H19UqHJSrQi6}I%RavHt-6@c<_KfmnG%?R^8Al@J7?z} zP-i&c>I7K0G&zZd5gc&=y97^Uz|2Pi4bV^Hl*qN`1elxopD=Pj+Z4Y@N zKhw`|X(*&}=7(>(E8fDJr-GfhqV==H5)$MyYEsThFr1>`-JJH87rsw7ox{X6rwE;u z(~Z6;o%L$#6S0iM;%(uNq)F%#n48JAB_iRGmWdy>P*gEBLWywN-2kMNZ7?JJcF@rk zW(n+C!p{Y^q<5Oq9;Pllvc)(*g_cwy`KEdMxZKl@@8E4*LM;-WM!7(&e^I2W6aJRk z&$KRdLAJAp&n|F2Dvlxt(}duWjnd*fJ7Ko;S);C)S0_%r1zn7l>LPGMQ{Rb5d|w|z zIv$3GIJ=|LBq{^3rnxb!;XdadZ%Hb-v;Kxbn>w8ll^u8QbAC5+V{EKg3%Eqx+~b~$ z!y}NHU)a5a0N^Z4l+|kV!KFq;shzfR^Pbqwylq#`{SmS<)p*! zo}Sk)eV=oO_Tr9G&Ww~k=`1R(sj*b*Id3d%jOP^=dltML(G%7S)k$K3XjquUVV|<>);Fd0 zXG(hKI7ZK8?UinnF!@+YP$x%W#uQsj%zo7~;j1DT4R~LrsDB7ISV6;EsP*^>`7%cD zPaSwfL2*VM=&-oH;h1?*Xq(${&a4qNwBCMw-gt!pBv#lmEdAjkr?=0q@7<%hui3f; z^5YlQCT}o*m#RD{uw)jpJ?sM6S{V#R7QBl%8q7Ls(LD92^xx7tml~WH&;P|Dj)#lW z{i$3CYJX8fHim)g!Aw)Dds^YSR|SWxrCB~aYV17L_{YC~b zL@%Z*lqHE7+0#%L;BngAA!#u8+CP_cB%1qjQ94sbK_+z6oy#^;mC?11A3rciBk(Ky z7M;EDUQ^yiUQAuYFGCI|^p(C`I3aY`HPuEl_zW8_P-$;u>DOGrvM29H^rj`Y4#g~I zspVN_-C%L*XaD+^H@1$Bj$0+XdGU=ezUk_co(#DrgoRal1JvB8VVR-d3DU|`9gNqm z$FOxK*!&buxcvBPwX2JhObZ8yt;@vC9cR5*r{_&V26*#P5ueK)TP#3mr1nTqTJ!Ao zi)PAv#mu31@NKYx)sx_1<5^!zvZSnZd)335I%Qm<^&)=KbXbM(LglHwL<+}GSBj|N zLEduesUN2VQ<8UkK;igI#8aL(@!ohqBC-WMiB*3t<8Jgu& z#3rN{snVoAAZt(^3=pik*$X{7)qr+vufx*i`J{vut=Z&2)?}Y`Qtsi_-HX=!o9=i@ zYWa)u+rYy+_d@TP77QFG2^s+G*;yah25O0Fdsc=Kjcm}&Iyw_?JdDBbF`*|q@8U-Ax_`!rkX5{&&*xNHY5nfcO+d87<*{SMO%!ApR~t#ml_XS#H2h7iN5`<)6*QDEw0UG^?x{d-s~C;J0p*v&!`6 z5QyCYXH6j$Llq1rzR`p4jGs|k07%*qm(f>JwNww|6j>t8_0gc`W;5E$0#VWmUtv^4 z&O-0C2LeF@ulnGMl>UaPp(}}ohqzeumxo54V*Wyk2F|j)m|(j7j`R$|N+u2eyvX2t zIF%G^oG|1-1q=Q(^%3bqxr_X~^`rb~LW9n`O{IYna{|LvU5_!n{XAk8phSK(o0;&; zjVhNxaw&zHUd5<73g?7Y(OU0I1ghVBN%%A3COZ^IIdScby{~okfD4~UFMVI%*QD@> zmbibqQ&rZel29HI2C4|ua4N0frd0n_e#!BM$4Z_d=aJ~p%u0pS%3{+&KpIw}B!Jt4 z+a#st^C#X1$LxtJ-zXorG5A8=wN*_PI+=TZMzbcMWPJr^e{qA-b+GKZJBjL~x$%y@A2T#f^@M@hvK1dNy`=dY-Clt|=)x1K7U& zPWw}9vwGg5ip79o3wC_h&GGgW5kULCeLU2;8qak)P+C+}jq`niXk}2_Sv>wsPWH{p zQf@e4DS%#DVr*=TNubFuDEK9-kTLkxtGA?TU=OjE_SXcHB7O)(!x60*>J=t!e&4I- z?vPH1n=~!k?%Cbs1t&ywhku;&76fbc1hlfDZnuw_gsr%t02o^KyfjpIXiDQ6O}?lG zl0Pd1d-Z~_lZIncPWT%{6}qI8*R~tdJpOaPKWr&FVI93PslU>3z_wHdqTG6{AuqFy z76$OpF1Rr~5b0b@{LC;=FO8D-W@KU&Jy>Aep{$Neen9A(JiXSWx7FR`OqH%9j}w!q z5y$=!F5jI+$+2xY=Suu_mUrwo^OhPzia?2p*4?zpR#`8no*quGHe-spRM;fO%7El4 z0#U@KSQa@}5(f|Tnf^q;*7sjYr@%gw42+kD3>)5hvr2PLeE~YlpL%W?9z3-jFKab% zm&`?sK5MwF4rH9=^(x zTKil$0PoE>$hMT?2E*$~GANTKqq^Q59CLbhw%+#L7kclDhkY*^Mu}9O>aQc-)v|X z8W@Pf6pQI1e15@xItG6Ri*-gOm|+xNe6`IyZT``t*uAJ`AWJG+L z3V`#cZfgjLl4z#r#pRrAYkz$h&CML@k9a9p?EpLd0%4x8R)RiTZS5MDHI23rseq6E z_o&jGgPK@j;l!ABiaagii-LNA0`miWFn4=5AItxu>#O6M{{DZ5C@86-AT3f#hs0oj zf`YWt-Q6&Hlp>%=NH<7#$LN+CjdXW60|wi;!_VjYyZ1is_ntp^ydT?}op{yr73ZAm z;3y#uKEjZru_IUu#qM{d%=T1`04dD*`3fKFy45=LA7poX!b&-R#%271^BCF#a-9R@ z)IZM2g%Etagx895{1QxZub?Rs%1HN`b=LgWT^@N=cb8ItUU&WpKNUx!i>oSv~l_h|BunN5uKgr^qM7&BFv;U&ZP88%wFBi91Avl8AWKjoGnmVE&mj8QzX3 z%X{^qjaBoW6#4aqGAq@vrI;%Q&JKd!1#|>R(pY9cj>&nLkmbP9U_qMBt=nl)x)T3Us}Np;@L{wy{Xew~y>n z_`lvt&|e_hXpe&f1o?`Dhz9&a1tqPfAp`XdS2l#*k2o6a`l7 zS-4<`?e~^W%Qz#7v-3C0CC-<`daX&HOamD*2gM(V)|B@wz}Vh z3fGOuBRy3|hZsdSHwlUA@GP}rO3V(2PHL>1#Cnx$EzC0l39~3)ruaXYB%nlx;Jh}- zKFU=BuNm z+*Dnj#4H9uyFDJ(pT<}<`#<#(%s zqf*4}mf^hsU$-8f_`HLxWoPml{C*+(4s(He=+6R&a>3mgRe*vkiviuIbQUU6yADnB znCEUWq@nVEz7Ln-_6Yb{eHX-7{OzZ}6R=E1N_U+wRt?JfK z*`CeqCCH4pNBKv7LBWqpmp*JXmR9?avj5v#8ccruv%c5(+# zY~!=NBefw}dRl4U@-vIId&@!gs-X2f^VZqLcPRvfEejKqZ`))pys|+3Tb#J$*`oso4%Z zLp>JuQ%Uz&@bXyR-+X$*oi3QLrK)Twn-_>5n9-yFu`Vg-QzD63x$-QLPSp|m6)njA z=}Fn7_~&$sKt0PdrV@r)yOJzf(9#s35_r$T2>f;w@>F=cy-W zl`94-Xsfc-57TBN>WNNiaqVK=!RLVH{@?8=&HQ~*Rh!H=KAIQ5_~W->HiWzFPh}`+ zz}df9U-$9d+t`WQR0>Fw{l~?+b)7L!2Q(+uM}+aEs2^K<_!+*R+^tb z-IV!WKwzV~Q=4yr^(1d2BQh5n`E2A%iXPo>z)O~Dky25f(uc|WB{x;sCnxnKsXBzm z=PWMH?~f;szkHRuR~;<~mwbxLE5Wu`Ku$hB^8rp7_NP(X$D8vL-R?}kUb?tOm`u3V z!vu}1=K80OtEi&KO6rV!O0v$tJ4F>f&9T|nm0!j+cNAZ<(D47%`Pdd*`FwEt1Ah0) zq*e?CqtK8}0}$sa*=$D3b-l_-52**ozf$!No7BqoPPPgx{Tz*VoSAeVIpYl-{~-60 zN+q$30m2o9DjX@5phiCkXMWWrj-RZ@%&pqS{pL6Ni@4~+hbHZ;njKv$JMNqmTLNAKzTBBLK>}02oOL}X_gh&7dioCUrz=KPHj3qXdU}(SnPt~S;ul?# zi7X%Ei_6wu{L;c?@$@9dFwm2)H9(LZG8){cyZ z$JjxBFjdjKuU$7@PGF{&h2391UcnluHKOUB(N|5tZ2;~H#E#+RSgP4npM9h5AFFR{ zzfY5OQ|;3{O~KE{s@oI#gD=7P$Nj< zhF;8-B8G!b@(Te*rPac}2j0kuE#gr;ReFtN?bW9{aOdaekC&6I((;hRqeDaR;GX1i zFTU2Uzt$q;*P8vuoN4_f!Z84`rvki(YbI9TijrY;Mcl9U1fBNjB}-t`y;%+{LImp-=|%mNROpI^)QoQNkqo#5Xvfv}!}tD0(%gZ4{nv6sO(+QPy%`+Igy z?*t@ORVyk@u$^wlG>4#~PAL$&`*(cDv`*Sge#%g}!dtqF-!}}1s+9fL5Bbjo+6gqD zYyYD-3-|8t@neotyJ_3d6`rm>CiY1b`2Myn^#oS+P}KlgOI9HCwc!muQ|V18w@aZ= z*z6}`rV_2TOD0w7pxY^8x=@+31!Dirq`6fD5~R(>)mqY)qfUZ5@roq}G6zPa*#s@j z6xB;zK_VFnSF^W`}nNrU>PpuvR&q{jo%f=4fpm!TFOuHJS~L$D@8Xt2Dabd zdD9%L%F9%o@)^Azlt8Pe z>G-c&e>W}tPqH$GEu!-src`rD#;pGy@etc%k^u%^ET!{fl+^Wo8t!mc=*zy*Y2}6v zRBdX@=euPqiiAAqOR-3X->?#+{hulFwoAJ z6U_YPsfgojv!Ry89fYfkJ96BSAlNhDcX#j?7aO66wretH0?#%GM_df{E@QtAK|&H( zAOFCwe6V;z9aY2f(oeS)Th86~^*kj+qVEB}k4O?C$>`Yo3gTmjBoWb{|3Cx4V`na2 z6Io}!8U)@+WhV!E+`-nmx0Fl^TgV2-SHBKn)8g_#QBI*6u@`Bm9}H6)bQv!i2)k0O zUh`q@=B8skf9Ttv@;gJq5->GM-Lq>iBC+|LIzPzQ^!*NiMi$~9Br1&M*JY$FK9_LN z$WZp>=GU~B@L)g;t(@6J>NC8iq|;$p<;xu~aTlo4k3{vVtO3hy=6Q_Ls{H0wVl|ZO z`M+Y7=N0)kU-OPpmYI7bVuA)Q70!IDw>j1yPa2#n^+prraa8MXuAsCk1Yvk>;K_ZzP{Y0B2y*C>(F* z;oN*;muTun7Z02=rDk+**wS$MO3S7c_}~lszOKs~jx7qVBP@|03$Tt3S@i{)JW%Li zb}{Ue==ypm=C2JZIE-?1tOf=$TAqE@CSR7!pj~6}Kz!5MiTOFKBDxP4vsQ z&0j=iqQ&b;lu{J)rq_qb;rx(&H$Roq^Tw-b8@*ufknIM*ow}Cwdy*jD=vwi6_tdo{ zi_NaSO#+h)CHB$wC+pXo5BUw4t_eaBi$SYLnxbLomSl;^6`&|0ivp=cm8%rBOgh`w ziZ@YQ?MX$ZpggaCPy46AL1c^JM2L`^ETEnkSZyAiaF zNlP6pGdA*?Q|Z)tOSzCqorH53?etf7YV`Kke+BhQ(Sq8VL~&l! z_~@;;tIudsIUCvi>?5Ulne7cLZy0ku)0XqhA|H4Dr5L)D3q^OYaLKMuroR87bTy#U zNbA_&zConfV4<4dPjYuYFqc_m$WQI9yH(}48T38Qp{X|=>gL?TW7IAO zc%G!~$E8vySBZGVG5;|JPhZT&-fEeQ$b1H-?3LwhNrPX3we5f}$)Mvu43T+NMq3ZX z&b^MYc+CgbP9@Nwk(Ninzw4d9f`k$wN3~^!oh~B#&Ru6LlGSgF8b$p#ehYcHk3C|wc%Bf-Eoz^C3d?sGvgv1 z%Vj#PvGtfc87krS!Qd&??g2t5k|ENGt#Pr8tVu-R6fPk3ft8H`egySu8c7jtqLe`5 zOr+SzmR{>%4cBb{#zrJ*xakC3p`NLj z`7lPqtt+)ver9wK&P6GZt)rWIL%i#@Hd?RCS_QZ}%qJLmkxJcrlpdwAd+qCWq_Ur3 zewp1yMb=_w)1r4q)9~$!l=-O=GiEFFo$XPE;0q~{-laCq@}_f!t_z3q$13tyXMf7q zd{K42!>`-FFvkh%y``;A+@{BISVR%?F1xuSd-%RR|4%Idip;{z1EetWJVtYfU_HH! z7MxdgUi^E({h9JrE|@#=u*ls@w1sifsO@y#>--0 zh*e%wy_U73^&JnZ1FHI5PD5me$oA-_r5W<+ThTJ(iNYc|d6Vg^plz`wLuoYLKfGxN z{3m6WG0Moyv~n;K{ruuX4Rtx=%TAK;wRe$L0@>e{3F|?aW4XIqTB9z6(%nv4PbSB( zURy@?E!d8{hcP7ad~b;-9Jf|xMm!6Ol>cSsxaPp%vU4{b0Mwk$n+C3#nMSDoln5Kd z%5{QTe~xh-PB{{1~?_8?yGE=a#e3AVy-``m+B3A@>_OZ}48n4bp3?FyaZGJ=Lz z2I5EHh^1#LVXR;iwiWqQR;io&+%ECg?!!~bxV>_1B$Wl3cZ*+{v z-W+l_z0|1rs=NJ*aBm<}6r$m=#~+`P81Xi+iC9#Dbm8K-OL+Umah&-S`S+He-@?O* zfA(LwbX!dBit3c7dzac}m0l-B0epNer(KuE^?i*I6&W|)BK<9$-U%{JGQD++u77r~ zAD@!mbQSOwURsaa;9S)%ALvm@INf;=7qxzmfgxIBvEfh6*V@XbTlg|!c?ES1tFdX~ z6$#y1PD(tOGpL@3WP_*AcXu+(gSk^1Bwfzrv(M+PwiaV>ng5NG~e)MQ_^;9Sh!TG|U;=}Ny;)pr?Zo!mq z>rVKaM&*nBzpZVL6r?9sN*05H?m&+b-Lv0%`7(CKfZmsE6)BbfK+6@^=dy2ZlcpJ? zPnnq7ng$;909zLy)l@aNh$?&+?)}BoX=~huoR3G<>ovKS8$W%|T?wej(C{i|Vaa2X zW68_=W${C@QPUb)R8(cH;A-^vNWdBlXpRLBl^jSG)qdX=v}VZ)!D6S=V;O8jtpGbqg#qKASDaFiC=?|wr^<8rJ45=^3dL`k1KS=!n# zV9a|R8CeRNJUuyeaBgyLq=sLG8P6@b{yDCZGFEXoDL41O&dw~Q&iVq!s1BbiDZLvT z0%N_)=#jT9o36;VTw2cMvh0)B{bi%}8!K>(47@tHY7=(x^82A4R!IsifL3`A&&~znxo%!rS>tU|?vEqTH7}u6C60=s=4*p|mjV4z3=WKcQ&P zW=;eoqw+*bBc9B*;cf=@N2=pv*RS}G-nrwBjmlyN^A1Q@VT!J8Jxb@4X81V68$r0q zDYD3Vl?7MDeY2nvdT;I8Osv=Z{FD8G>}ykl4ir_kA$O((@N*`Pvm4>(uNPAJL-T)} zuaH0f5;Wac>`*LmibM0B9`yur2OHHRBhRUTP6Tp}O2f`OX9-&qw5l6}gNi=2G&`yeunu2aZY{*Z>3m&pyiE#&h7%6%!p*epFFI$q4SZz;q@q> zekqwT$!XGyrf0h;7o|^46KB4Mm!W>rF{rX-MVFc^p*G8>sJM0R?d-G0$8^E5w6}PQ zpzjxNh>g!cShp<_kPCgkz)k8Ik~Tb?AzX7Z)iocR)}`ugOk1$9d_4Da>nN@EbwZCb zQ*spF0duDd{VXqRngzU4>0XRV6(fY zYL{qiiSL*6)$X4OQQ=A-slH0w_fLZWe1#Q3NR_U}KLj1qEeX(qWYnrJt^WbMoerg$ z1Lb6qnd3T9sTI>(-aa#TN9PM5&Y#jcd-T4eUF@%J{hg5kgF-09V#3X25*eHeQ!`HeifU>+;oRT-vFIz}ol|uLK18laCYn4?X zBwu=tS%^xQf@;eM-B%vNU(`8^)tK0hI=rzVGLDiz*}Yri&k39 zl-oLAdM=njxP7H}p!d1R(6=^=cgnf`(@v*FXGy?Z{xVTGt7N#=K(Bqr$3#)x*Y4(f z4}QH(SXp?~94lr_dOFuR_|CT`NH7y0o_O`s{gQw@Dt5&ErBpD0McW$O z{+CzF_g~#K=?T^}=1>lUnIP-$uV~1#;5LJ0-#NMRY*Pwxz-*Vfq*0SCZ?8`MH9vwD zawqa=HB|PMY20u85;U};of^qfm!W*GJow z{+4@(!IEjxbLs2--WRyy*ntV`VovkM#Z?$N<=nahIa;yK^!Vj?yp$49d1>NJ;7P&j zI1YKH4~a)CPh5ehi-$x)JQ4Sun|RCLEc-;Coq?N(a z^LY55;MUx-^IPu(?p^jq8&#*Mc1?kGYIO8k=|l18q?J!`Gj_)|GI={6ZUb$%FlFVR zupK7yN6lfjz6+|TD9FU5!i06AHZ{8m(!O$PmWg#=rMrf@pWJ924|R)ywe)4G6+)jK z_0u~ax#36Wa`JUJn#raylN>voRp^~%+~#cn~>5+R9wq4h9XMZVZUP)%{)btV2;vAVO1c% zIl3N=DVn90O6g9e7jz+!BC#Gl{QY?iB^af6bHBs8^_frMh6F56oU*!FrDB z53?2F7S_F+CpAgiMwrtwL66&^m1b}p{(aDA^~K|=!MV|Kd&Po#f7fPo71#m+|9OQ4joP3!mcBPt;^aFNcHqKL)Pxtn! z{9-t9tnZRUxa7s^K?L+twqVQj z2d@il!;3pS&{sv{1rU}v}pt#9iH+tZ7%p;MU~NjcOu15c^K{|JWow*tloe_`w#Ls)GcWl!Jh=$H7v zq@z^Mo5|#{{9Z*}{$Lb~l9tTDwX=Jp`MA{;>x^dX#~0JIGFIw5qTqr^h&y>DJ@`YR zDp{~{WNaU67S(>D2#p`OC>|linzGAf&~G3#j%RB6H6hd+%Yl($%D*h8{HGCvoLJz) z8`F0le{x)%U#6L2C$BrW^J4+x9qcY2cFat+>Zz6=JG6^-P;|zg_@B3 z{2kE|5pthMd^%Cf*?EKeJnf}|4%yC#fQ1Z6F2$4x3Zx6Lp&G$lQ+cO{;qS!$oohkt zKbyK7qn;?`LE9#3OcH`KG-MlRjLdVHXO(EG82(R(>9^+ine*t}yd&p_7c5wfNez)H z5uZnt>Z-3qgpZM(G%C0}=Nv|Zi`?t>7_G$^kEyVy&N=C8s@5cTobh5Cr2BezdPNv% zOHpXByYk+yjFWZs4POFBT2QYFD5+kOICVe&WOXkb7*(j0d6*P3enUs6 zyOM^7@59z7vJO^$Ko>R!pbO2BNOt>%*szPd_t^T7Cx8?&+r+Dg1FOF4R%affN2f2{Izz)FXat_YZLMdi+XHe&EZiN`XKHCd09ar1SE1C1-xSeO1A z>Z~}Qr4FG&`At^&NsAz#&rxrqWnsqn8cDU`19KypI=laqBa#&I7t12>b_i|#)h(kl#6oZ? z_3Lic-3tHm+Md(+Zt@-*zLe+K>3S}g&&8u8*`)Cw^!wTKxVeM^{%Nk66rt14GsPLnla^^!Nw=v8&K9HVj0-0E?uT3G6L< zZw{ALuF`At9$vBTG9XwFUb4qGq6NDCG%4?}>mGGJMFLA4j|;oxbgI7`%iDQV35<;}~?-_Tjsi{(a`;S3C zre*$DXQ>3%`tN~~l&?Mql<&=wyhRTXOMi2!pf8)%F!R2_O>)~end}m~v|M1oxd&O0 zY>`_mdbT=!1sAXRt*#VrIvOHveb}5;$w(*BHHPe=1Wgs=4&AtxpAlm)U4t-g>YTFx zC_byv||@XsdLxFQQZ#_vex!0=<%Di+OrDAatlbmc|qR?jLpbDN1s=SK7duQSnTgy*HYS{Bh#d6j_sRwap< z&}2$Y=AzLk{Xkw0wzt(?u_n0Ki|YZSU%A3Nb5GCMzOL$rufh44WY4`6Yu?i4;MyPS?sAbY4-S>Vqh>B}H>mgZP zRH=RvtY$Z?Y4+7!g2avs63{e{FR5{E@(WRkABvd}cZU!9Li+@!xga@vbPrFqWSBO$z?L}Hib}3Ig04#&UmW2Ski!Oc{sOsxPan7ip0f{ zWr(jkb2$##jsU#bj@n-W~IwmIx9iC2t@nA&;q|*8g zRra`=LE3TUV7;uXonwN_Wdb7GuG4L)afAG9q6b;BQ7=;|;6SnmMt=kr^?>TO#^{S> zL9f{G%p1c~L!r_(mB^QEdQQi)g2Nm^StgX~mnp}9ny>lFv8w=xAY;%3OvS9h*AC`9c zrdEjwnyv%)NXVWv#O7F9)_tM)j^D@Qhu_X+K8P}Yc+U*0ROkwh@Vew0>PL7FT_CeO zo|g_Cx;1;sr6!O69B+0I=MaRqf+|oK;Gwy}bNI5tf^qg(wZP&M!VA9JusQ7!qp~BG z>>sz0?Ba}8oMD{5nu~elJI9Nwf8zvU7U`Xt_POpwtcPZvp48|MZq|s2nhzk&T}2K@ z0x}0GZer=1-K=W#*T<3YMhT~>rzAYNo4HOaKq-@5tZ_M1_r6D7g*?%eVE~cdt_#d` zT(x06&9{+Gphb`wbz|GGSKCWN&bPLXoQ(5L{VpQV2OSb+(}vsk{t2=lGA2wL5+K#R zh@wAjilEHxRyGFz9>0;pl*8;IuURz9-6Dy#00-rt&V?;dAg2iq1bWL7zZtasSsOfp z4drm3L$`j|^e0N8z20~mn3k`$CTGe7aLtDh)Hle9)tp~*ZPRJ)I^v+~?k52SUJ zP;lS>w&&GGvh8KD8rl}s;+wwT)HpqQ=w=zHXvT4}Fe7?S7GC9x7O(*O?sB#Pg*ckf zn+F8Q{_Zi~1eyd?>pE~fBC-X9n0`*nvEJk~k2X6P!hwKaHfq@_tm$CKFA*Wnewyr51I=1Uz1X`4-bO{{7u(@BY-psetsDu0gJIyra?9(03 zLU*L~95qX$0%uKj(b74(NyZmIx9G^pqz37B zJ@b^UvP)9yHKR?6|8(ueuD^il2_biK_c@9gSJK?`0P~z@={ik_^y&}I^6F2af9W9R zkZn=E$mb3Aye}XjS5l&`E9B&L=erja`e&08kcq+bS>k@Nu8_f|Q0$ZP{qP~pYhRON z?Pbnud*BN4caUPU%iyDF&lI$W3$n@H@^URMPA8QzEf1EMv={Ly_aI?Bat*#5RgJqg z&Ws*iKI$!tI~;gQrk}`aUoWN{n;_&YIPLaIeId=PAl`(wbXg2fyJoY{FdCFdBnE+G+U(i3g2-C>l3V={I_5ut7; z%r+UOe^$SgJ+=DlGr1sqT25~mS&)E4MiXdxf84#$i;v$V^|E(Og_L9p9xItOeaho? zJD58=nB5JXOgJxXtX)#+ANavJsO9`wK(6*hcXEsVx$x24o^VlY?m;8dW~#Rbjm4>2 z-+bjp4et7{dH((#Y)DRtRxgjg=f;GOY;7sgqOrNPfZ5EMK)~KVd|c&Xy;mdGyN1A5 zVOAWBW`GesOKyYrQpN#@dxq1c^_qnR7C?q=F>BtqgfdVD4^JZ|wI~xcCNx;GVtFY{ zzrqk<<2dzc+PpB_eBDQ6;fdE(wr`6-@pY;1M%p+-LIQJIVk)xx=e;4Dy3M|1Ub`kL z&b^tD3s+gY#8Jc$S5GzXfTz9GG2V$^Ha;}6qi2~!qNT;h_;M`*H+8URlU7FCzD|DJH4Nn- zwVCUm=1-lNBBtZgflQ;00;BBFKPAGacnbBL9GP5Qw=isZc(d2mpU32}G^!)$8b>8; zG_S)Ys)@v~e(NxsP!*HkTr z=96?)L}{=27-IrywmsmdtdDio>7*og)BcC3+kVXH%2G_F6Ld}A*2iMC3VCo@$-9*I3Fvl6?{s7u z&h84?Vw_q1W0}BjfhhWz2GW&}yecYNS&~Z;;!6->AG^B1>?I#!l%^QA>uHxRE+F)cSj`6bAWTC8(nEX` zJu=cf-ZD9C&UA;$EdXoemlNH&YD8zRf z=}ZY?kcjM;87kt+T5N~$i^UX%qm@cD%@9S+6FZ20b;X{yl=i8mc2G~d%k3!HV>CXO zwVD~6D)wztRKG%`CAl|Juddh-?u8l!SJ;F*gSaBq$CiId9dvkBVVEXG+%NLaY+y6M%XpyV}PY9){nB5tK7O6~7iX`z`h zzQl0ALg`%t0Kj5st^vG^Al`@zN=Y%cHeXkF6Nz{QzBZ{=4C|S^F_uw4w}Gi?Z#qNk zt`M?LJ#D^y$7G91=1CapZ5?@4U0lu~w&HaJw#g7(hDmGNr-y@;G)xNQ}t=8HRoiJd#I|C8Sl0>ppme>aE8KK) zz>}?UFE^}b9G9SP5iQEi*)OL?JI5<6Yu2xGrE}SQvE^NN7_(ow9*fQ6d3MGy-pFt5 zsV95WZz&xsFGTaK_b6;q|BEphg~^t~QM&0dT?o;n{vT@(TZIefUG&we%+>kz#}h5{ z?&|E&zjk=~@G)^3TTV(_%%a=&$0TQ{dPDb}%iyMgH9^xTxY^uTY!uG^jJuDisb zzUo_()u1TWaHOjpZLQm2!$B<4anGghtU=g3MO4}<$_W7t>$@SMN=TdI;&%(HV`H{~ zT9HayjiFuO zc`b$78AYDW@q+(!r}gV9vTrvFd4$V0oR6kfh7I04hOo6<^`?!PqZG}muU>h$pXCEj z+NCO{@T#}TFPb{QgDB4INl$w40kK(RmC3gy(eg*d8$fmzGM`NQM?-APZg(u96$TUCWyr=MPHFrbru1X8CA_#sx%L zj$SCI^?%JVoOW-RuN*?_4@#n#H&Yi=BX7|2KV**=@VPHabS_tePL4Z<2FrzgUKA2) z@;7;2z*uN+E{dkjeL^5BT{a7sGq%d*N$0L$g4imqpvS6iTKuo(sCD@;<(Ou-^Sx&EjLjD(_3S6Q>%ym?AP zm!rb;3g?Z5L1MPW4Gf!kbV+;Fiu@WSqHyoYp=OAEqO@^$wXbr30Hv?Boh4G|oVw2E zitn{a9lT{i$ld95lpvL%lsGNfXEeWV?W?WOGg07+?#0(Yc;P`buTPb|=qRscotvCp zYO2Z6AP^P#34yL7+Zc8YR8#=2XL)VYpDw~PI+$l`_`D)bwm5+3uchm(xM6*7Z3)wK z&i%d2TR6?e2t{M7MSD7!0RS%p)d?*~iq`0rdR$=@x_D-8ZkiX%kE2R1jhOxHa$Ftx znZmwBt2p)*XLG!2AdxKCMNg~1ZuSyA$~&9t0+E~pzQEPJP*S(w@V2T<_8hXDE)Dtpuk#;Z-aXuc3JkW%L z^Y|oQbAt;l$YiqDN?e83X_Xvg`7>y^ zO1H)X{nx>i4s<)wn;0<6l*+zJp$0Ex+8&yIlC4}!YdS$BL-y=6-PTQ&C(o2pQL~3m z8@@L@#La&Y*5k!csfKP>XP+4@H|fDo>lL#+Hj^o*Bc}SWC^wzxC?7$ls2Swk<&_sY zq=9E8Tzh?KSKC){!gxy!cqV*p_QU0xd8~W0=7%CI+%6$Hhkx*9W#MufjJP-)5`r8i zFQfDZzBFJ4EgvKUj*t@Br>il}u zQhLZ!PB2QgVXbUGXf1&C0&`k|ShR`5dA-dUvVqtp-nff#yT;QMwET7NVtRbkcw?;Y zCQ&TcXKi7+Xj2T_Rsvaz^kt;gvJa>7-8-0e$gXcZg6{H~P55ps?W@VH-gxn9r=g)H zp`06kGH+NrCN=0#vH7rM@}Z3g$GFW9u$|o|J=ub$3*5yr?=Ute=l8)f765Sg4C@&{ z!|D##Ar96h%Dm?&l-FRi$-`N)0+~zPTbEm$Q0R)5^tmAIV6;~REUZ9`PpS`AohG9= zvxn-n&4T0ubGpy8!JTmm{VBA`=xdt$tz}uU45Q6a1Zj;axA>s`%Miwy0W6S;1llGY zrnnm6I2W3p|B(WpI_9nk9YbOAJ~m!E=TkxuyHQ?wUj3f0vz!B*K28W+7WAFNX2Njv zetQRV$8OX%bVC4oy^M_+^lQwZ0q)vz_2~FLFK_k342GK|WBxg=ZlsvH$5~%TWp|7{ zED#VIzf1xEYzf(65dzrwpne2Wy1ZoVN`yWS1X?{`s`lao`jaOVh1C0{l2PrWB4Mz~w=w*ml-xdYZ# zGJoZkUAO7!l6R3d)Goj9Pd1}ZEZ{IzMwhWV5kLTFZGhbdHvlj7s_PQ#>#zPyj=RCt z{D{9@VV=jwbG3?H;c5WDrJv)y+hP2+&ackWD$Z$6r;CZLud1r*wAK9VCdugH5_9hu z3g0BebPTy&X@Ka%g7J+%R_yturHT>~-jOou_77evv16L0T`DvB4q%w^?|Z@O>iThk zS9Ts|qhsVClMgIUkI4W4KOO|Z?XO^(pZM)`K8Cn}r?#xYM^g2kw6`BSKfPU{89uga zT^GfJmc!IJ-$h-->Xh}#>7g%h_hNs?o3U34ycYl7_;78`arrl*W36NcLjnLmSN_(c zRX`p}rw!!t&w{J6jCI#2|yj zz`rDF+^nw3(z5M?MI8*P8mILiB$dWsS@tbJsge%V7ZT{Sy_pKnYB?8Y;YFaTK2qQs zMv!4HxJ+ZTuqk}SArGiXR1U$=Cn!~%-VN9d$7f@8yG1U%-)HG0*{N&5!%S}%_6NTB zTwi$Sr_GIhVb)Nx`N^h!TEv(S>Vw|k5mj}MwXW|CDZ=Q+CqKo*wk9e>+{a}F3-Oy?7m|pfINx&z@G~~bTKA!e%xE>W;!h{Eq zW8hBShK)6`>SL{H?J?iV!|ZMC;&SLXp8Z~RCOqdbVzrq|L~P3Y-9c)^ncgwIW*tIT zB(~--yWG+n*`M;lj8k~u^qRK+|BtYvcv+*L}aec(X4sJIw@tp zm}|u3j?EZ#vAV4Sc<8gHadFHTRGY6d&G#iqPUC(qhUWo(97}ix81e4Z_vPVXo=0ox zK`>@#2mmO!C^{6aS)*?Yc~R_zDaL(^c*^plD$fq`sL^kl_iY$eaeM)!tT`hNpP>-y3se?2mGa8Dbh z>AD_V+B^JAe_wgpxyfh0aVq3BKSvw}m5rT4g*8g;;GrjJwEA>SyHOscgMIyz1(qdh zQO+<=eGr2_;;a?%!}C+fblvpf26k$p(cQ^-GvKssA#dxsq(->t&!Pg`$$ z!?b{h7)k%z@J5EmF*d@FI1m?n#oyopXS)6PWispkyg-NHp}*~k_^qwHZ7;vxS_+6- zwvu#lp#avCbfrRu{A{Is=UdYNSfXac{L4}5`0()0KUzxa$FpinH@Qmc(#2}lsQ8fWnlAC zzeob3Z%y3Zs-;V>O#;gOYHJILdUfg2rAa#sO*Xh_tz5lYr(-{`E_r!%b$EC_7f{!| zKu|sT-ZTH-oO4-QEw@H_zk2=p@`Zr;N75^pycbOa0u%G|v+Zpz{n~u=ImnLzM!@s| zw8m@cS7Yn!t<(1WI;B0+xZH2n?AgJqcQQ%5hynW7+1a`3+l!fTd#i!|6|M({qQ*RM zU_@oFSqU8coaVXy-rnc+Tg7-KUU+0bUwh{N^Va{s3XH)^4IC)ne@#7*e`K~-iA+Lf z$9|xAO#rxd*6%O}au_b`Bv|Q#Ye}F|NIeMBgdCl?VhgM;fCF1AV${IVFdR)bpfmt3 z*G6*+au;K?a2PEdMhl10!eO-K07?T6ilgP>Xn9Db@-Tz=}744LbSa z;^N|?qT#@yy0Wig;I7{T+oc;fZalmG`}_OPyhe` literal 0 HcmV?d00001 diff --git a/doc/integration/integration_part.rst b/doc/integration/integration_part.rst index 723d99ce0..0fdf92c79 100644 --- a/doc/integration/integration_part.rst +++ b/doc/integration/integration_part.rst @@ -461,3 +461,72 @@ created in the same directory as each ``test_driver.gpr`` file. This file contains the name of the unit tested by the driver, and can be used to specify to |gcv| to only process the unit under test, by adding the switch :cmd-option:`--units=@units.list`. + +########################################### +Using GNATtest with GNATfuzz (experimental) +########################################### + +This section presents how a pre-existing GNATtest test harness can be used as +a starting corpus for a GNATfuzz fuzzing campaign, and how inputs of interest +found by GNATfuzz can be imported back into a GNATtest harness. These features +are still experimental; the workflow and command line interface may change in +the future. + +************************** +Setting up the environment +************************** + +To ensure the entire workflow functions properly, it's crucial to configure +the various tools by setting specific environment variables. + +The first step is to setup the value generation runtime library. For detailed +instructions on how to do so, see :ref:`Tgen_Env`. + +Then in order to activate the import and export of tests between GNATfuzz +and GNATtest, the ``GNATFUZZ_TGEN`` environment variable must be set: + +.. code-block::bash + export GNATFUZZ_TGEN=1 + +******************************************* +Using GNATStudio to perform the integration +******************************************* + +The simplest way to sequence the invocations of the two tools is to use the +GNATstudio integration plugin. + +First, create a GNATtest harness project if it doesn't already exist, using the +``Analyze -> GNATtest -> Generate harness project`` entries in the menu bar. +Note that in the dialog box opening there is an option to generate tests inputs +if needed. + +Then, exporting tests inputs from GNATtest to GNATfuzz and running a fuzzing +campaign on a specific subprogram can be done by right-clicking on the +declaration of the target subprogram, then selecting +``GNATtest -> Start/Stop fuzzing subprogram``, as illustrated bellow. + +.. Image:: gs_menu.png + +This will first instrument sources and re-generate the GNATtest harness in order +to be able to intercept the inputs passed to the subprogram, then run the test +harness, dumping the inputs in a binary format that can be used by GNATfuzz. +GNATstudio will then setup a fuzzing session on the subprogram, for which the +parameters can be controlled through the various pop-up windows that will be +displayed during the process. + +``gnatfuzz`` will periodically export newly found inputs in a human readable +JSON format under ``/gnattest/test/JSON_Tests``, where ```` designates +the object directory of the project. + +The fuzzing session will stop once all the stopping criteria have been met. The +fuzzing session can also be stopped early by right clicking on the subprogram +declaration, then selecting ``GNATtest => Start/Stop fuzzing subprogram``. + +After the fuzzing sessions has ended, a new GNATtest harness will be +regenerated, including the tests exported by the GNATfuzz session. These will +appear in +``/gnattest/tests/-test_data-test__.adb``, +where ```` is the name of the unit in which the subprogram is +declared, ```` is the name of the subprogram, and is a +hash based on the profile of the subprogram, in order to differentiate +overloads. From 9ff7e57562231d88de39a68b2e4a655cd0c0b336 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 19 Sep 2023 15:49:32 +0200 Subject: [PATCH 0428/1483] command_line.ads: minor documentation fixes --- tools/gnatcov/command_line.ads | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 14d854347..cc3c3bd80 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -385,13 +385,12 @@ package Command_Line is "Generate the adequate configuration to use gnatcov in integrated" & " instrumentation mode. The files of interest must be passed" & " through the --files switch, the compiler driver in used through" - & " the --compilers switch, the runtime installation directory" - & " through the --runtime-install-dir switch, and the configuration" - & " and compiler driver wrappers are generated in the subdirectory" - & " pointed by the --output-dir switch.", + & " the --compilers switch, and the configuration and compiler" + & " driver wrappers are generated in the subdirectory pointed by" + & " the --output-dir switch.", Pattern => "--files= --compilers=" - & " --runtime-install-dir= [--output-dir=]", + & " [--output-dir=]", Internal => True)); Bool_Infos : constant Bool_Option_Info_Array := @@ -1351,7 +1350,7 @@ package Command_Line is Pattern => "NAME", Help => "List of compiler drivers for which we should generate wrappers." - & " Supported compilers are: gcc.", + & " Supported compilers are: gcc, g++.", Commands => (others => True), Internal => True) ); From d5ced4576440c639c4227530475d4f081e1c8bc7 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 19 Sep 2023 15:51:08 +0200 Subject: [PATCH 0429/1483] setup-integration: support dump configuration options The setup-integration command should readily support these options as they are taken into account when loading the configuration file generated by `gnatcov setup` (which `gnatcov setup-integration` uses to determine dump configuration options). --- tools/gnatcov/command_line.ads | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index cc3c3bd80..b6640d1b0 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -525,6 +525,7 @@ package Command_Line is & " variations).", Commands => (Cmd_Setup | Cmd_Instrument_Project + | Cmd_Setup_Integration | Cmd_Instrument_Main => True, others => False), Internal => False), @@ -835,6 +836,7 @@ package Command_Line is & " for non-native programs.", Commands => (Cmd_Setup | Cmd_Instrument_Project + | Cmd_Setup_Integration | Cmd_Instrument_Main => True, others => False), At_Most_Once => False, @@ -847,6 +849,7 @@ package Command_Line is & " filename for created source traces.", Commands => (Cmd_Setup | Cmd_Instrument_Project + | Cmd_Setup_Integration | Cmd_Instrument_Main => True, others => False), At_Most_Once => False, @@ -857,6 +860,7 @@ package Command_Line is & " filename prefix for created source traces.", Commands => (Cmd_Setup | Cmd_Instrument_Project + | Cmd_Setup_Integration | Cmd_Instrument_Main => True, others => False), At_Most_Once => False, @@ -868,6 +872,7 @@ package Command_Line is & " filename tag for created source traces.", Commands => (Cmd_Setup | Cmd_Instrument_Project + | Cmd_Setup_Integration | Cmd_Instrument_Main => True, others => False), At_Most_Once => False, From 095e59f88809ccf380660d8bd51760428d4ca388 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 19 Sep 2023 15:55:13 +0200 Subject: [PATCH 0430/1483] Document the integrated instrumentation workflow --- doc/gnatcov/fig_flow_integrated_instr.dot | 61 +++++++++ doc/gnatcov/fig_flow_integrated_instr.pdf | Bin 0 -> 24275 bytes doc/gnatcov/fig_flow_integrated_instr.png | Bin 0 -> 37948 bytes doc/gnatcov/getting_started.rst | 12 ++ doc/gnatcov/gnatcov_part.rst | 1 + doc/gnatcov/integrated_instr.rst | 154 ++++++++++++++++++++++ 6 files changed, 228 insertions(+) create mode 100644 doc/gnatcov/fig_flow_integrated_instr.dot create mode 100644 doc/gnatcov/fig_flow_integrated_instr.pdf create mode 100644 doc/gnatcov/fig_flow_integrated_instr.png create mode 100644 doc/gnatcov/integrated_instr.rst diff --git a/doc/gnatcov/fig_flow_integrated_instr.dot b/doc/gnatcov/fig_flow_integrated_instr.dot new file mode 100644 index 000000000..45f81b2be --- /dev/null +++ b/doc/gnatcov/fig_flow_integrated_instr.dot @@ -0,0 +1,61 @@ +digraph { + node [fontsize = 9] + + edge [fontsize = 9, arrowsize=0.7] + + setup [shape=box, label="gnatcov setup"] + + /*------------------- + Using Source traces + -------------------*/ + subgraph "cluster_src_traces" { + label = "Setup / Build / Execute / Analyze"; + fontsize = 10; + labeljust = l; + + /* processes */ + node [shape = box]; + + node [color = green]; + instrument [label = "Setup integrated instrumentation\n(gnatcov setup-integration -P)"]; + build_instr [label = "Regular build\n(using the generated compiler wrapper)"]; + regular_execution [label = "Regular Execution\n(instrumented executable)"]; + + node [color = blue]; + srct_coverage [label = "Analyze/Consolidate\n(gnatcov coverage -P...)"]; + + /* products or inputs */ + node [shape = ellipse, color = green]; + st1 [label = "strace1"]; + stdots [label = "..."]; + st2 [label = "strace2"]; + + node [shape = ellipse, color = blue]; + srct_report [label = "Report"]; + srct_checkpoint [label = "Checkpoint"]; + + src [shape = ellipse, label = "Original Sources"]; + + /* Links */ + src -> instrument; + instrument -> build_instr; + build_instr -> regular_execution; + + {rank = same; + st1; stdots; st2; + } + + regular_execution -> st1 [style = dotted]; + regular_execution -> stdots [style = dotted]; + regular_execution -> st2 [style = dotted]; + + st1 -> srct_coverage; + stdots -> srct_coverage; + st2 -> srct_coverage; + + srct_coverage -> srct_report [style = dotted]; + srct_coverage -> srct_checkpoint [style = dotted]; + srct_checkpoint -> srct_coverage; + + } +} diff --git a/doc/gnatcov/fig_flow_integrated_instr.pdf b/doc/gnatcov/fig_flow_integrated_instr.pdf new file mode 100644 index 0000000000000000000000000000000000000000..e3ad7645793b1d18606a677c207efc13563da03c GIT binary patch literal 24275 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%0D|~UjO{2-tVzcccLb;a0hu4d@ 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

eB`gx-+Nu@>>1Y~wWn6X=Zy`t4M&n`_ALmz z&F!4n>NS1@)@iR-O}x7$>!s!@*^9YiH&R;?Hy%=4due5Vp~EV--|v5xykQz0O>RHs z^7WIiyVO(l)mN=A=H%GtC%-uG)XFFK#epaJ_vlK8=m*+$6Ku0GX?vbB&y7p>QS{;m z&g<5TC=Pd)cZ)o%tlVO1Y8sU#v@*;LWqaxVKX<$W`u&fOY+!nPE_Huz<*n^kuUc;k z)8PJ?ZrE2J7waCnAKBacuu>6} zR<6Z#!zWT3hG%RJb3ZL?Nu9Xlv$-g^Wkl7+hDTIPtZ`xc#(kw!#vgaOY&NiLHuqQR z7JK4)yg80TtmiJrhAEfb><&L}zIq|3L?5A>J*@N{3=cIc}r#=kHwNFTHK-6izmMCOp8{&f@mMy`ja)H22ws}{mn zmVe0l`Pa~PiNAbHw@dnc+tFiF7kzyfmns#1?%sPgP+)7ox$k#bx|!)2jt!~Njg6l+TYXU1u~1=RpWn)ydsL`?iqqE7A74B- zK6^s(KQC+%q#__7c%R`#nDlNV*53I`*4<4lBT+&DJZ*!u$v5XmxA)1cEKX~&Kn<{L z?ebIW#>-|0P4+buPMf-ktPi(t$KrhQ$`@1ZlzeUpTyt#X5?tOQte-q!GHfugmUgbt z*=IqC#^C%O&9ry-BK-tK)6@7fzW%xXu_FBG=g-1N%S(0tg!A(|aIfNEWi7gPB|J3L zLgN6a=i(V@7;|~s&;YEASHjs~6&+ zRn15bW7*+~x2wy})qs2~Z@2To|J^syi~b+|@Np_` to be used by the instrumented code needs to be +setup as a required prerequisite. Refer to the :ref:`instr-rts` section of this +manual for a description of this step. The installed instrumentation runtime +must be visible on the ``GPR_PROJECT_PATH``. + +Then the process essentially goes like: + +#. Setup the integrated instrumentation process, specifying the instrumentation + parameters (units of interest, coverage level etc.) and the compilers of use. +#. Build the instrumented code using the generated compiler wrapper(s); +#. Execute the program to produce a trace. + + +Specifying instrumentation switches +=================================== + +The user specifies the switches through the ``gnatcov setup-integration`` +command, which accepts any option accepted by ``gnatcov instrument``, except the +ones using project mechanisms to filter out units of interest: ``--units`` and +``--projects``. Refer to :ref:`src_traces` for more information regarding the +source instrumentation specific switches. + +As there is no project acting as a units of interest provider, the user must +explicitly pass files of interest through the ``--files`` switch, which expects +a list of full filenames that can be passed through the command line, or using a +response file. + +To generate a compiler wrapper, use the ``--compilers`` switch. The list of +supported compilers is ``gcc`` and ``g++``. + +This will generate in the current directory, or in the directory specified by +the ``--output-dir`` switch an executable compiler wrapper and a +``gnatcov_config.json`` file along. Note that this configuration file is used to +configure various instrumentation options: it is thus very important that it +resides in the same directory as the compiler wrapper. + + +Building an instrumented executable +=================================== + +The build process can be run unchanged after it has been configured to use the +generated compiler wrapper instead of the original compiler. + + +A simple Makefile example +========================= + +The following considers that the instrumentation runtime was previously +installed with ``gnatcov setup``, and that the ``GPR_PROJECT_PATH`` variable +contains its installed location. See :ref:`instr-rts`. + +Let's consider a simple ``main.cpp`` file: + +.. code-block:: c++ + + #include + + int main(int argc, char **argv){ + std::cout << "Hello World" << std::endl; + return 0; + } + +and the following Makefile: + +.. code-block:: makefile + + CC=g++ + OBJ = main.o + + %.o: %.c + $(CC) -c -o $@ $< + + test: $(OBJ) + $(CC) -o $@ $^ + +We start by configuring the instrumentation process: + +.. code-block:: sh + + cd + gnatcov setup-integration --files=/main.cpp --compilers=g++ + +Then, we launch the build processed unchanged, with the compiler wrapper first +on the path: + +.. code-block:: sh + + export PATH=:$PATH + make + +This will produce an instrumented executable, that will produce a source trace +when run, that can be analyzed with ``gnatcov coverage``. + +A simple CMake example +====================== + +The following considers that the instrumentation runtime was installed through +the use of ``gnatcov setup``. + +Let's consider a simple ``main.cpp`` file + +.. code-block:: c++ + + #include + + int main(int argc, char **argv){ + std::cout << "Hello World" << std::endl; + return 0; + } + +The CMakeLists.txt file to be used to compile the main.cpp file is : + +.. code-block:: cmake + + project(HelloWorld) + cmake_minimum_required(VERSION 3.0) + + add_executable(hello_world main.cpp) + +We start by creating the build directory, and configuring the instrumentation +process there: + +.. code-block:: sh + + cd + mkdir build + cd build + gnatcov setup-integration --files=/main.cpp --compilers=g++ + +This creates a ``g++`` compiler wrapper in the build directory, along with a +``gnatcov_config.json`` file that we intend to use as a proxy for compilation. +To do that, we have to configure the CMake build process accordingly, using the +``CMAKE_CXX_COMPILER`` variable. We run the configuration command in the build +directory: + +.. code-block:: sh + + cmake .. -CMAKE_CXX_COMPILER=/build/g++ + +The default generator for CMake is "Unix Makefiles", so we can then run the +build process with ``make``, and our executable which will produce a source trace +that can be analyzed by ``gnatcov coverage``. From 933bb26df03e2424fbb012067b773fd0b052ca6c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 21 Sep 2023 12:58:54 +0200 Subject: [PATCH 0431/1483] Expose the setup-integration subcommand --- tools/gnatcov/command_line.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index b6640d1b0..f1dcdafd4 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -391,7 +391,7 @@ package Command_Line is Pattern => "--files= --compilers=" & " [--output-dir=

]", - Internal => True)); + Internal => False)); Bool_Infos : constant Bool_Option_Info_Array := (Opt_Verbose => Create From 78ecbf944d3c1d594543eafc28bfdbf726cd65ae Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 22 Sep 2023 12:19:04 +0200 Subject: [PATCH 0432/1483] Reject older checkpoint versions We actually document that we reject older checkpoint versions but this was not reflected in the code. Fix this. --- tools/gnatcov/checkpoints.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index 8a99ee384..c8256787d 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -573,7 +573,7 @@ package body Checkpoints is if CP_Header.Magic /= Checkpoint_Magic then Fatal_Error ("invalid checkpoint file " & Filename); - elsif CP_Header.Version not in Checkpoint_Version then + elsif CP_Header.Version /= Checkpoint_Version'Last then Fatal_Error ("invalid checkpoint version" & CP_Header.Version'Img); From 2a72ad9d50c98e9f2068ac72c3e2f0f8bbcb4b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 22 Sep 2023 11:44:12 +0200 Subject: [PATCH 0433/1483] Doc: Add reference to gnatfuzz integration in the test generation part This gives a more comprehensive view of all the Tagada items that are currently supported in a single location. --- doc/gnattest/gnattest_part.rst | 5 +++++ doc/integration/integration_part.rst | 2 ++ 2 files changed, 7 insertions(+) diff --git a/doc/gnattest/gnattest_part.rst b/doc/gnattest/gnattest_part.rst index c30127ab7..b93c0e463 100644 --- a/doc/gnattest/gnattest_part.rst +++ b/doc/gnattest/gnattest_part.rst @@ -933,6 +933,11 @@ Please note that all the features described bellow are experimental, and the interface is subject to change. GNATtest has the capability to generate test inputs for subprograms under test. +This test generation feature is also useable in conjunction with GNATfuzz, in +order to use GNATtest harnesses (generated or manually written) as a starting +corpus for a fuzzing session, and to integrate inputs of interest found by +GNATfuzz back into the test harness. For more details, see section +:ref:`Gnattest_Gnatfuzz`. .. _Tgen_Env: diff --git a/doc/integration/integration_part.rst b/doc/integration/integration_part.rst index 0fdf92c79..42f399916 100644 --- a/doc/integration/integration_part.rst +++ b/doc/integration/integration_part.rst @@ -462,6 +462,8 @@ contains the name of the unit tested by the driver, and can be used to specify to |gcv| to only process the unit under test, by adding the switch :cmd-option:`--units=@units.list`. +.. _Gnattest_Gnatfuzz: + ########################################### Using GNATtest with GNATfuzz (experimental) ########################################### From e73ce9454d4ca5450c0b8da362db99409b8c6add Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 22 Sep 2023 15:53:43 +0200 Subject: [PATCH 0434/1483] instrumentation: do not instrument main from project dependencies This is consistent with gprbuild behavior. --- .../src-main-dep/main.adb | 4 +++ .../126-main-in-dependency/src/main_root.adb | 6 ++++ .../instr-cov/126-main-in-dependency/test.py | 30 +++++++++++++++++++ tools/gnatcov/project.adb | 3 +- 4 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/instr-cov/126-main-in-dependency/src-main-dep/main.adb create mode 100644 testsuite/tests/instr-cov/126-main-in-dependency/src/main_root.adb create mode 100644 testsuite/tests/instr-cov/126-main-in-dependency/test.py diff --git a/testsuite/tests/instr-cov/126-main-in-dependency/src-main-dep/main.adb b/testsuite/tests/instr-cov/126-main-in-dependency/src-main-dep/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/instr-cov/126-main-in-dependency/src-main-dep/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/126-main-in-dependency/src/main_root.adb b/testsuite/tests/instr-cov/126-main-in-dependency/src/main_root.adb new file mode 100644 index 000000000..9a0c41ad1 --- /dev/null +++ b/testsuite/tests/instr-cov/126-main-in-dependency/src/main_root.adb @@ -0,0 +1,6 @@ +with Main; + +procedure Main_Root is +begin + Main; +end Main_Root; diff --git a/testsuite/tests/instr-cov/126-main-in-dependency/test.py b/testsuite/tests/instr-cov/126-main-in-dependency/test.py new file mode 100644 index 000000000..798bf3d39 --- /dev/null +++ b/testsuite/tests/instr-cov/126-main-in-dependency/test.py @@ -0,0 +1,30 @@ +""" +Regression testcase: checks that gnatcov correctly deals with mains in +dependency projects. It used to crash when there was a main in one of the +dependencies. The correct behavior should be not instrumenting them as a main. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir('tmp_') + +main_prj = gprfor(srcdirs=[os.path.join("..", "src-main-dep")], + prjid="main_dep", mains=["main.adb"], objdir="obj-main") +root_prj = gprfor(srcdirs=[os.path.join("..", "src")], deps=[main_prj], + mains=["main_root.adb"], objdir="obj") + +# This also checks that we do not produce multiple traces +build_run_and_coverage( + gprsw=GPRswitches(root_project=root_prj), + covlevel='stmt', + mains=["main_root"], + extra_coverage_args=["-axcov"], +) + +thistest.result() diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index a65654b46..3e832cb47 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -1431,7 +1431,8 @@ package body Project is -- Start of processing for Enumerate_Mains begin - Iterate_Projects (Root_Project, Enumerate_Mains'Access, True); + Iterate_Projects + (Root_Project, Enumerate_Mains'Access, Recursive => False); return Result : Main_Source_File_Array (Mains.First_Index .. Mains.Last_Index) do From 21ffcec720a6588b61afd4a38fdc1e444fef362e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 22 Sep 2023 17:45:11 +0200 Subject: [PATCH 0435/1483] PC09-022-auto-exename: update test to be consistent with gprbuild --- .../src-sub/sub_main.adb | 4 ---- testsuite/tests/PC09-022-auto-exename/test.py | 20 ------------------- 2 files changed, 24 deletions(-) delete mode 100644 testsuite/tests/PC09-022-auto-exename/src-sub/sub_main.adb diff --git a/testsuite/tests/PC09-022-auto-exename/src-sub/sub_main.adb b/testsuite/tests/PC09-022-auto-exename/src-sub/sub_main.adb deleted file mode 100644 index 379623393..000000000 --- a/testsuite/tests/PC09-022-auto-exename/src-sub/sub_main.adb +++ /dev/null @@ -1,4 +0,0 @@ -procedure Sub_Main is -begin - null; -end Sub_Main; diff --git a/testsuite/tests/PC09-022-auto-exename/test.py b/testsuite/tests/PC09-022-auto-exename/test.py index 15d0fe9f4..f679431a4 100644 --- a/testsuite/tests/PC09-022-auto-exename/test.py +++ b/testsuite/tests/PC09-022-auto-exename/test.py @@ -136,26 +136,6 @@ def run(self): mains=('main_proc.adb', ), build=False, should_succeed=False), - - # Check success when there is one single main in the whole project closure: - # once when the main is in the root project... - Project(project_files, 'sub', 'src-sub', - mains=('sub_main.adb', ), - deps=('nomain', ), - should_succeed=True), - - # ... and once when it is in a dep project - Project(project_files, 'sub_main_in_dep', 'src-sub', - mains=(), - deps=('single', ), - should_succeed=True), - - # Check that we have an error when there is at most one main per project - # and multiple projects with a main. - Project(project_files, 'sub_double', 'src-sub', - mains=('sub_main.adb', ), - deps=('single', ), - should_succeed=False), ): assert p.name not in project_files project_files[p.name] = p From 4a4af26a354d5fbb1f473ee8f956bde946b2d097 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Sat, 23 Sep 2023 12:07:37 +0200 Subject: [PATCH 0436/1483] Fix test.opt --- testsuite/tests/O212-062-assertions/test.opt | 3 ++- .../tests/instr-cov/O212-062-unsupported-pragmas/test.opt | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/O212-062-assertions/test.opt b/testsuite/tests/O212-062-assertions/test.opt index a7e5600b6..c102bbe0c 100644 --- a/testsuite/tests/O212-062-assertions/test.opt +++ b/testsuite/tests/O212-062-assertions/test.opt @@ -1,2 +1,3 @@ bin-traces XFAIL Assertion coverage not yet supported for binary traces -5.04a1,7.1.2 DEAD Test contains expression functions and Ada_2012 features +5.04a1 DEAD Test contains expression functions and Ada_2012 features +7.1.2 DEAD Test contains expression functions and Ada_2012 features diff --git a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt index 168d3ae58..edd652267 100644 --- a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt +++ b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.opt @@ -1,2 +1,3 @@ bin-traces XFAIL Assertion coverage not yet supported for binary traces -5.04a1,7.1.2 DEAD Test contains expression function and Ada_2012 features +5.04a1 DEAD Test contains expression function and Ada_2012 features +7.1.2 DEAD Test contains expression function and Ada_2012 features From e0c80ad871147330f990fa953e95dcdf7b0aa5e3 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 16 Aug 2023 16:27:03 +0200 Subject: [PATCH 0437/1483] C++ instrumentation: fix for ranges support The instrumentation scheme for C++ for ranges resulted in incorrect code when initializer lists were involved, e.g.: ``` for (auto i : {1, 2) { } ``` being instrumented as ``` for (auto i : (witness(), {1, 2}) { } ``` which is invalid C++ code. To fix this, we now instrument such expressions as followed: ``` witness(); for (auto i : {1, 2}) { } ``` We can't execute the loop statement without executing the witness with a goto as it is forbidden to bypass initialization statements in C++. When there is an initialization statement, e.g.: ``` for (int j = 0; auto i : {1, 2}){} ``` we actually introduce an outer scope and instrument as followed: ``` { witness_j(); int j = 0; witness_i(); for (auto i : {1, 2}){} } ``` (cherry picked from commit c29e1be8bf3ab223654eda810b4a50d97f9b2ddb) --- .../src/test_for_range.cpp | 18 +++ .../ForRange/WithInitializerRange/test.py | 13 ++ tools/gnatcov/clang-extensions.adb | 23 +++ tools/gnatcov/clang-extensions.ads | 6 + tools/gnatcov/clang-wrapper.cc | 15 +- tools/gnatcov/instrument-c.adb | 132 +++++++++++++++++- tools/gnatcov/instrument-c.ads | 12 ++ 7 files changed, 210 insertions(+), 9 deletions(-) create mode 100644 testsuite/tests/C++/stmt/ForRange/WithInitializerRange/src/test_for_range.cpp create mode 100644 testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.py diff --git a/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/src/test_for_range.cpp b/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/src/test_for_range.cpp new file mode 100644 index 000000000..736210b0c --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/src/test_for_range.cpp @@ -0,0 +1,18 @@ +#include + +int +main (void) +{ + int sum = 0; // # init + for (auto i : { 1, 2, 3 }) // # for-range + { + sum += i; // # for-body + } + return 0; +} + +//# test_for_range.cpp +// +// /init/ l+ ## 0 +// /for-range/ l+ ## 0 +// /for-body/ l+ ## 0 diff --git a/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.py b/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.py new file mode 100644 index 000000000..c34f08074 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.py @@ -0,0 +1,13 @@ +""" +Test that gnatcov correctly instruments a for range with an initializer as the +range expression and an initialization statement, e.g. +``` +for (int i = 0; auto j : {1, 2}){} +``` +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index 2dae8f683..f29eeef17 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -164,6 +164,29 @@ package body Clang.Extensions is CX_Rewriter_Insert_Text_Before_Token_C (Rew, Loc, Insert & ASCII.NUL); end CX_Rewriter_Insert_Text_Before_Token; + ------------------------------------ + -- CX_Rewriter_Get_Rewritten_Text -- + ------------------------------------ + + function CX_Rewriter_Get_Rewritten_Text + (Rew : Rewriter_T; + R : Source_Range_T) return String + is + function CX_Rewriter_Get_Rewritten_Text + (Rew : Rewriter_T; + R : Source_Range_T) return String_T + with + Import, Convention => C, + External_Name => "clang_CXRewriter_getRewrittenText"; + + Rewritten_Text_C : constant String_T := + CX_Rewriter_Get_Rewritten_Text (Rew, R); + Rewritten_Text : constant String := Get_C_String (Rewritten_Text_C); + begin + Dispose_String (Rewritten_Text_C); + return Rewritten_Text; + end CX_Rewriter_Get_Rewritten_Text; + ----------------------- -- Spelling_Location -- ----------------------- diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index 2689b9fdd..b516cd84e 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -128,6 +128,12 @@ package Clang.Extensions is -- Insert the text Insert before the token at the given location, and after -- any previously inserted string (at the same location). + function CX_Rewriter_Get_Rewritten_Text + (Rew : Rewriter_T; + R : Source_Range_T) return String + with Inline; + -- Return the rewritten text for the given source range. + function Get_Cursor_TU (C : Cursor_T) return Translation_Unit_T with Import, Convention => C, diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 4554dcc9c..945646bfa 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -705,10 +705,19 @@ clang_CXRewriter_insertTextBeforeToken (CXRewriter Rew, CXSourceLocation Loc, R.InsertTextAfter (Prv, Insert); } -/* Wrappers around source location analysis functions. */ +extern "C" CXString +clang_CXRewriter_getRewrittenText (CXRewriter Rew, CXSourceRange Rng) +{ + assert (Rew); + Rewriter &R = *reinterpret_cast (Rew); + SourceRange SR = translateCXSourceRange (Rng); + return createDup (R.getRewrittenText (SR).c_str ()); +} -extern "C" unsigned -clang_isMacroLocation (CXSourceLocation Loc) + /* Wrappers around source location analysis functions. */ + + extern "C" unsigned + clang_isMacroLocation (CXSourceLocation Loc) { const SourceLocation SLoc = translateSourceLocation (Loc); return SLoc.isMacroID () ? 1 : 0; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 525533b27..b848dcfef 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -40,7 +40,6 @@ with Coverage; use Coverage; with Coverage_Options; with Hex_Images; use Hex_Images; with Inputs; use Inputs; -with Instrument.C_Utils; use Instrument.C_Utils; with Outputs; use Outputs; with Paths; use Paths; with SCOs; @@ -221,6 +220,11 @@ package body Instrument.C is Loc : Source_Location_T; Text : String); + overriding procedure Register_CXX_For_Range + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class; + N : Cursor_T); + Record_PP_Info_Pass : aliased Record_PP_Info_Pass_Kind; Instrument_Pass : aliased Instrument_Pass_Kind; @@ -281,6 +285,54 @@ package body Instrument.C is function Insert_MCDC_State (UIC : in out C_Unit_Inst_Context'Class; Name : String) return String; + procedure Fix_CXX_For_Ranges (UIC : in out C_Unit_Inst_Context); + -- This procedure fixes C++ for ranges that were purposefully instrumented + -- wrongly. To instrument a C++ for range, we actually need to turn + -- + -- for (int i = 0; auto j : {1, 2}) {} + -- + -- into + -- + -- { + -- witness_i(); int i = 0; + -- witness_j(); + -- for (auto j : {1, 2}) {} + -- } + -- + -- We introduce an outer scope to leave the initializer declaration + -- lifetime unchanged, and to be able to easily instrument both the + -- initializer declaration and the range expression. + -- + -- Note that this is valid because you can't goto inside the loop + -- (and thus skip the execution of witness_j) as it is + -- forbidden to bypass declarations with initialization in C++, + -- which "auto j : {1, 2}" is. + -- + -- Though we can't do that all at once, as this changes the shape as the + -- AST. As we rely on the AST node location to instrument statements and + -- decisions, we would be instrumenting the decision at the wrong place, + -- as we would instrument the initialization statement by moving it. + -- + -- Thus, we do the normal instrumentation process, which will yield an + -- unvalid C++ sequence, that we can easily fix in this procedure, by + -- moving around the rewritten code. + -- + -- The for ranges at the entry of this procedure will have been + -- instrumented as followed (the added code is identified by <>): + -- + -- for ( int i = 0; auto j : {1, 2}) {}<}> + -- + -- Two things to note here: the witness_j is executed before "int i = 0;" + -- (which is wrong), and there is an unmatched closing brace. + -- + -- To fix this, we actually need to move both the added code, _and_ the + -- initializer statement before the , and insert an opening + -- brace before: + -- + -- <{> int i = 0; for (auto j : {1, 2}) {}<}> + -- + -- and now we have valid, and correctly instrumented code. + ---------------------------- -- Source level rewriting -- ---------------------------- @@ -1030,6 +1082,18 @@ package body Instrument.C is end if; end Insert_Text_After; + ---------------------------- + -- Register_CXX_For_Range -- + ---------------------------- + + overriding procedure Register_CXX_For_Range + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class; + N : Cursor_T) is + begin + UIC.Instrumented_CXX_For_Ranges.Append (N); + end Register_CXX_For_Range; + -------------------------- -- Instrument_Statement -- -------------------------- @@ -1306,6 +1370,43 @@ package body Instrument.C is return Name; end Insert_MCDC_State; + ------------------------ + -- Fix_CXX_For_Ranges -- + ------------------------ + + procedure Fix_CXX_For_Ranges (UIC : in out C_Unit_Inst_Context) is + begin + for N of UIC.Instrumented_CXX_For_Ranges loop + declare + Loc : constant Source_Location_T := Start_Sloc (N); + For_Init_Stmt : constant Cursor_T := Get_For_Init (N); + For_Init_Rng : constant Source_Range_T := + Get_Cursor_Extent (For_Init_Stmt); + begin + -- Get the rewritten text for the initializing statement and + -- move it before any rewritten text before the for statement. + + CX_Rewriter_Insert_Text_Before + (UIC.Rewriter, + Loc, + CX_Rewriter_Get_Rewritten_Text (UIC.Rewriter, For_Init_Rng)); + + -- Open the outer scope. It was closed during the instrumentation + -- process, so we do not need to take care of that. + + CX_Rewriter_Insert_Text_Before (UIC.Rewriter, Loc, "{"); + CX_Rewriter_Remove_Text (UIC.Rewriter, For_Init_Rng); + + -- for (; auto i : {1, 2}) is invalid C++ code so insert a dummy + -- initializing expression to avoid the null statement here, as + -- it is easier than trying to move around the comma. + + CX_Rewriter_Insert_Text_Before + (UIC.Rewriter, Start_Sloc (For_Init_Stmt), "true"); + end; + end loop; + end Fix_CXX_For_Ranges; + type SC_Entry is record N : Cursor_T; -- Original statement node, used to compute macro expansion information @@ -2134,14 +2235,28 @@ package body Instrument.C is -- the range declaration initialization expression. Like all -- statements, they can contain nested decisions. - Extend_Statement_Sequence - (For_Init_Stmt, ' ', Insertion_N => N); - Process_Decisions_Defer (For_Init_Stmt, 'X'); + if not Is_Null (For_Init_Stmt) then + + -- See Fix_CXX_For_Ranges for an explanation of the + -- below code. + + Extend_Statement_Sequence + (For_Init_Stmt, ' ', Insertion_N => For_Init_Stmt); + Process_Decisions_Defer (For_Init_Stmt, 'X'); + + -- Preemptively end the introduced outer scope as it is + -- easier done when traversing the AST. + + Append (Trailing_Braces, '}'); + UIC.Pass.Register_CXX_For_Range (UIC, N); + end if; + + -- Instrument the range as mentioned above Extend_Statement_Sequence (For_Range_Decl, ' ', - Insertion_N => For_Range_Decl, - Instr_Scheme => Instr_Expr); + Insertion_N => N, + Instr_Scheme => Instr_Stmt); Process_Decisions_Defer (For_Range_Decl, 'X'); Set_Statement_Entry; @@ -3315,6 +3430,11 @@ package body Instrument.C is end loop; end; + -- Once everything has been instrumented, fixup the for ranges. See the + -- documentation of Fix_CXX_For_Ranges. + + Fix_CXX_For_Ranges (UIC); + -- We import the extern declaration of symbols instead of including the -- header where they are defined. -- diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 58253690f..2e6dbfcc7 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -32,6 +32,7 @@ with Clang.Rewrite; use Clang.Rewrite; with Diagnostics; use Diagnostics; with Files_Table; use Files_Table; +with Instrument.C_Utils; use Instrument.C_Utils; with Instrument.Common; use Instrument.Common; with Slocs; use Slocs; @@ -381,6 +382,11 @@ package Instrument.C is Disable_Instrumentation : Boolean := False; -- Set to True to deactivate instrumentation and prevent any code -- rewriting. + + Instrumented_CXX_For_Ranges : Cursor_Vectors.Vector; + -- List of instrumented for ranges. For an explanation of why we need + -- to store these, see the documentation of the Fix_CXX_For_Ranges + -- subprogram. end record; type C_Source_Rewriter is tagged limited private; @@ -472,6 +478,12 @@ private Msg : String; Kind : Report_Kind := Diagnostics.Warning) is null; + procedure Register_CXX_For_Range + (Pass : Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class; + N : Cursor_T) is null; + -- See the documentation of Fix_CXX_For_Ranges + type C_Source_Rewriter is limited new Ada.Finalization.Limited_Controlled with record CIdx : Index_T; From ee233210744b185d148e9ad36484a3bc9d712cbc Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 2 Oct 2023 13:25:07 +0000 Subject: [PATCH 0438/1483] Instrument Ada: fix handling of Compile_Time_* pragmas The boolean expressions for the Compile_Time_Error and Compile_Time_Warning pragmas are expected to be time known. This means that we cannot instrument them as decision/conditions, as doing so would make them non compile time known. Emitting coverage obligations for compile time known expressions would not make much sense anyway. --- .../instr-cov/compile_time_pragma/main.adb | 9 +++++++ .../instr-cov/compile_time_pragma/test.py | 25 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 10 ++++++++ 3 files changed, 44 insertions(+) create mode 100644 testsuite/tests/instr-cov/compile_time_pragma/main.adb create mode 100644 testsuite/tests/instr-cov/compile_time_pragma/test.py diff --git a/testsuite/tests/instr-cov/compile_time_pragma/main.adb b/testsuite/tests/instr-cov/compile_time_pragma/main.adb new file mode 100644 index 000000000..1b7eed195 --- /dev/null +++ b/testsuite/tests/instr-cov/compile_time_pragma/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + pragma Compile_Time_Error + (Boolean'Size /= 1 or else Integer'Size < 2, "Dummy error check"); + pragma Compile_Time_Warning (Character'Size /= 8, "Dummy warning check"); + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/instr-cov/compile_time_pragma/test.py b/testsuite/tests/instr-cov/compile_time_pragma/test.py new file mode 100644 index 000000000..99f84f9f4 --- /dev/null +++ b/testsuite/tests/instr-cov/compile_time_pragma/test.py @@ -0,0 +1,25 @@ +""" +Check that the decision/conditions of Compile_Time_Error pragmas are not +instrumented. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {8}}}, "xcov") + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 069604e73..a04b5215e 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -5193,6 +5193,16 @@ package body Instrument.Ada_Unit is end if; Typ := 'P'; + -- Even though Compile_Time_* pragmas do contain + -- decisions, we cannot instrument them, as they would + -- not be known at compile time anymore (this is a + -- requirements for this pragma), so just generate a + -- statement obligation for them. + + when Name_Compile_Time_Error | Name_Compile_Time_Warning + => + Typ := 'P'; + -- For all other pragmas, we generate decision entries -- for any embedded expressions, and the pragma is -- never disabled. From d502622b6fe43a1eed293c931bc3320a64bb9609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 20 Sep 2023 14:53:44 +0200 Subject: [PATCH 0439/1483] Add ATC and ATCC documentation without examples --- doc/gnatcov/cov_source.rst | 107 +++++++++++++++++++++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index edf87ac0d..b90df8bb7 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -1404,6 +1404,113 @@ condition expressions are such that running vector 4 is not possible, however, since we can't have V both < X1 (condition 1 False) and V > X2 (condition 2 False) at the same time when X1 < X2. +.. _scov-atc: + +Assertion True Coverage (ATC) analysis +====================================== + +Along with the previous coverage levels, |gcv| can provide different strictness +levels of assertion coverage for source traces for Ada. + +Assertion coverage warrants defining separate criteria to perform coverage +analysis since contrary to all other regular decisions, those contained in +assertions are expected to never be evaluated to False. Assertion decisions and +conditions are defined the same way as for Decision and MCDC but, the coverage +is computed differently. + +If such coverage analysis is needed, it should always be activated along one of +the previously described coverage levels, as an "addition". In the following +sections on assertion coverage, their associated command line options will be +written as `--level=...+` where `...` is one of +`stmt`, `stmt+decision`, `stmt+mcdc` and `stmt+uc_mcdc`. + +Using assertion coverage levels allows to compute the coverage of the pragma +statements `Assert`, `Assert_And_Cut`, `Assume`, `Check`, `Loop_Invariant`, and +the aspects `Type_Invariant`, `Precondition` and `Postcondition`. + +Core notions and Reporting (:cmd-option:`--level=...+atc`) +---------------------------------------------------------- + +|gcv| performs Assertion True Coverage assessments with the +:cmd-option:`--level=...+atc` command line option. The assessment determines +the status of assertion true coverage obligations out of the tests execution, +considering that: + +* An assertion is :dfn:`covered`, and the obligation :dfn:`discharged`, + as soon as the assertion's decision has been evaluated once to True. + +* An assertion is :dfn:`uncovered` otherwise. + +In synthetic :cmd-option:`=report` outputs, uncovered source assertions are +listed as ATC Coverage violations in the report section dedicated to these. + +In annotated source outputs, the coverage annotations convey the following +indications: + +.. tabularcolumns:: cl +.. csv-table:: + :delim: | + :widths: 10, 80 + :header: Annotation, Meaning + + ``-`` | At least one assertion on the line, none covered + ``!`` | More than one assertion on the line, some covered + ``?`` | At least one assertion on this line, some with undetermined coverage state (*) + ``+`` | At least one assertion on the line, all covered + +(*) The Undetermined Coverage state (``?``) is only shown on the line in the +absence of other known violations for that same line. + +.. _scov-atcc: + +Assertion True Condition Coverage analysis (ATCC) +================================================= + +Core notions and Reporting (:cmd-option:`--level=...+atcc`) +----------------------------------------------------------- + +The coverage status of an "ATCC" obligation is determined as follows: + +* An assertion is said :dfn:`fully covered`, or just :dfn:`covered`, and the + obligation discharged, as soon as all conditions have been evaluated to True + or False at least once accross all evaluations to True of the whole decision. + +* An assertion is said :dfn:`uncovered` when the decision was never + evaluated to True, either because the enclosing assertion statement was not + executed at all or when all the attempted evaluations were interrupted e.g. + because of exceptions. + +* An assertion is said :dfn:`partially covered` when at least one of the + conditions of the assertion's decision was never evaluated to either True or + False in the context of an evaluation to True of the whole decision. In this + case, the obligation is partially discharged. + +The :cmd-option:`=report` synthetic output lists the ATC and ATCC coverage +violations in the ``ATC`` and ``ATCC`` coverage report section respectively. +For the :cmd-option:`=xcov` and :cmd-option:`=html` annotated-source oriented +formats, the single annotation produced on each source line combines the +statement and ATC coverage indications. The following table summarizes the +meaning of the possible annotations: + +.. tabularcolumns:: cl +.. csv-table:: + :delim: | + :widths: 10, 80 + :header: Annotation, Meaning + + ``-`` | At least one statement on the line, none executed. + ``!`` | Unless multiple statements are involved, assertion partially covered on the line. + ``?`` | At least one statement or assertion on the line with undetermined coverage state. (*) + ``+`` | All the statements and assertions on the line are covered. + +(*) The Undetermined Coverage state (``?``) is only shown on the line in the +absence of other known violations for that same line. + +When a trailing `+` is added to the format passed to :cmd-option:`--annotate` +(:cmd-option:`=xcov+`), a precise description of the actual violations is +available for each line in addition to the annotation. The :cmd-option:`=html` +provides it by default. + .. _synthetic-metrics: Synthetic metrics From 1a877a0d234a38037a520c5f77fbe0837f2bac7f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 21 Sep 2023 18:29:57 +0200 Subject: [PATCH 0440/1483] Fix wrong logic in scope traversal The logic implemented to traverse the scopes tree was actually wrong, which resulted in gnatcov not reporting coverage result on the parent subprogram when specifying a nested subprogram to `--subprograms`. --- testsuite/tests/subp_of_interest/src/pkg.adb | 5 ++ testsuite/tests/subp_of_interest/test.py | 12 ++-- tools/gnatcov/sc_obligations.adb | 70 +++++++++++++++----- 3 files changed, 65 insertions(+), 22 deletions(-) diff --git a/testsuite/tests/subp_of_interest/src/pkg.adb b/testsuite/tests/subp_of_interest/src/pkg.adb index d4971528c..6607b0f9f 100644 --- a/testsuite/tests/subp_of_interest/src/pkg.adb +++ b/testsuite/tests/subp_of_interest/src/pkg.adb @@ -7,7 +7,12 @@ package body Pkg is end Foo; procedure Bar is + procedure Nested_Bar_1 is null; + Dummy_Decl : Boolean; + procedure Nested_Bar_2 is null; begin + Nested_Bar_1; + Nested_Bar_2; Put_Line ("Hello from Bar!"); end Bar; diff --git a/testsuite/tests/subp_of_interest/test.py b/testsuite/tests/subp_of_interest/test.py index 235595cd1..cb4f971cb 100644 --- a/testsuite/tests/subp_of_interest/test.py +++ b/testsuite/tests/subp_of_interest/test.py @@ -25,8 +25,8 @@ ) # Produce a coverage report and a checkpoint with the subprogram switch. Check -# that the coverage report contains only coverage data for the specific -# subprogram for source traces. For binary traces, simply check that the +# that the coverage report contains only coverage data for the specified +# subprograms for source traces. For binary traces, simply check that the # gnatcov coverage invocation yields the expected warning. os.mkdir("xcov_subp") xcov( @@ -36,6 +36,10 @@ "trace.ckpt", "--subprograms", f"{os.path.join('..', 'src', 'pkg.ads')}:4", + "--subprograms", + f"{os.path.join('..', 'src', 'pkg.adb')}:10", + "--subprograms", + f"{os.path.join('..', 'src', 'pkg.adb')}:12", "--output-dir=xcov_subp", ], out="coverage.log", @@ -52,7 +56,7 @@ "*.xcov", { "main.adb.xcov": {}, - "pkg.adb.xcov": {"+": {6}}, + "pkg.adb.xcov": {"+": {6, 10, 12}}, }, "xcov_subp", ) @@ -68,7 +72,7 @@ "*.xcov", { "main.adb.xcov": {"-": {5, 6}}, - "pkg.adb.xcov": {"+": {6}, "-": {11}}, + "pkg.adb.xcov": {"+": {6, 10, 12}, "-": {11, 14, 15, 16}}, }, "xcov_no_subp", ) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 8b4d12dcb..64501e614 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -612,10 +612,10 @@ package body SC_Obligations is new Tree_Iterator' (Scope_Entities_Trees.Iterate (CU_Vector.Reference (CU).Element.Scope_Entities)); - Result.Next_Scope_Ent := Result.It.First; Result.Scope_Stack := Scope_Stacks.Empty_List; Result.Active_Scopes := Scope_Id_Sets.Empty; - Result.Active_Scope_Ent := Scope_Entities_Trees.No_Element; + Result.Active_Scope_Ent := Result.It.First; + Result.Next_Scope_Ent := Result.It.Next (Result.Active_Scope_Ent); return Result; end Scope_Traversal; @@ -629,29 +629,63 @@ package body SC_Obligations is is use Scope_Entities_Trees; begin + -- In some cases (C metaprogramming instances), e.g. + -- + -- foo.h: + -- TYPE ret = 0; + -- return (TYPE) ret + 1; + -- + -- foo.c: + -- int + -- one_int (void) + -- { + -- #define TYPE int + -- #include "foo.h" + -- #undef TYPE + -- } + -- + -- Active_Scope_Ent is null in the aforementionned case, as the inner + -- scope for the statements in foo.h is the `one_int` function defined + -- in foo.c. The scope implementation assumes that scopes do not cross + -- sources, which does not hold here. + -- + -- TODO???: This should be fixed by dealing with metaprogramming + -- instances in a more appropriate way, which should be done under + -- eng/cov/gnatcoverage#103. For now, return early in that case. + + if ST.Active_Scope_Ent = No_Element then + return; + end if; + -- Find the innermost scope featuring this SCO and update the list of -- active scopes as we go. - while ST.Next_Scope_Ent /= No_Element - and then SCO >= Element (ST.Next_Scope_Ent).From + while SCO > Element (ST.Active_Scope_Ent).To + or else (ST.Next_Scope_Ent /= No_Element + and then SCO >= Element (ST.Next_Scope_Ent).From) loop - ST.Active_Scope_Ent := ST.Next_Scope_Ent; + -- We can enter the next scope only when we have reached its + -- parent scope. If the next scope is null, this means that we + -- are in the last scope of the unit. - -- Update the scope stack + if ST.Next_Scope_Ent /= No_Element + and then ST.Active_Scope_Ent = Parent (ST.Next_Scope_Ent) + and then SCO >= Element (ST.Next_Scope_Ent).From + then + ST.Active_Scope_Ent := ST.Next_Scope_Ent; + ST.Next_Scope_Ent := ST.It.Next (ST.Next_Scope_Ent); + ST.Scope_Stack.Append (ST.Active_Scope_Ent); + ST.Active_Scopes.Insert + (Element (ST.Active_Scope_Ent).Identifier); + else + -- Otherwise, go up the parent chain and pop the last entry from + -- the active scopes. - if not ST.Scope_Stack.Is_Empty then - while ST.Scope_Stack.Last_Element /= Parent (ST.Active_Scope_Ent) - loop - ST.Active_Scopes.Delete - (Element (ST.Scope_Stack.Last_Element).Identifier); - ST.Scope_Stack.Delete_Last; - exit when ST.Scope_Stack.Is_Empty; - end loop; + ST.Active_Scope_Ent := Parent (ST.Active_Scope_Ent); + ST.Active_Scopes.Delete + (Element (ST.Scope_Stack.Last_Element).Identifier); + ST.Scope_Stack.Delete_Last; end if; - ST.Scope_Stack.Append (ST.Active_Scope_Ent); - ST.Active_Scopes.Insert - (Element (ST.Active_Scope_Ent).Identifier); - ST.Next_Scope_Ent := ST.It.Next (ST.Next_Scope_Ent); end loop; end Traverse_SCO; From 37acd23476c56363690f17c9f13fd2fef2cbe67f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 27 Sep 2023 10:44:32 +0200 Subject: [PATCH 0441/1483] Fix the documentation of the gnattest <-> gnatfuzz integration --- doc/integration/integration_part.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/doc/integration/integration_part.rst b/doc/integration/integration_part.rst index 42f399916..2e5b2247b 100644 --- a/doc/integration/integration_part.rst +++ b/doc/integration/integration_part.rst @@ -484,12 +484,6 @@ the various tools by setting specific environment variables. The first step is to setup the value generation runtime library. For detailed instructions on how to do so, see :ref:`Tgen_Env`. -Then in order to activate the import and export of tests between GNATfuzz -and GNATtest, the ``GNATFUZZ_TGEN`` environment variable must be set: - -.. code-block::bash - export GNATFUZZ_TGEN=1 - ******************************************* Using GNATStudio to perform the integration ******************************************* From 9065fb4990199795bc69ad346b455302684e9e3e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 22 Sep 2023 11:01:53 +0200 Subject: [PATCH 0442/1483] Fix typo --- doc/gnatcov/src_traces.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 5b3bf5634..63052d973 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -209,7 +209,7 @@ kinds of operations: --------------------- As for other commands, help on the command line interface is displayed -by ``gnatcov instrument --help``. The general sysopsis is as follows:: +by ``gnatcov instrument --help``. The general synopsis is as follows:: gnatcov instrument --level=<> [OPTIONS] From 07e2a4b228baa7921eed7cd6503e4f59a5978024 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 22 Sep 2023 11:01:59 +0200 Subject: [PATCH 0443/1483] Add a documentation entry for parallelized instrumentation --- doc/gnatcov/src_traces.rst | 4 ++++ tools/gnatcov/command_line.ads | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 63052d973..74b993f48 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -245,6 +245,10 @@ dump-channel, the ``--dump-filename-<>`` family of switches provides control over the name of trace files. See :ref:`instr-tracename` for more details on the default behavior and possibilities to alter it. +The instrumentation process can be parallelized using the ``-j`` (shorthand for +``--jobs``) switch. ``-j0`` can be used for maximal parallelism, and ``-jN`` +with N > 0 to specify the desired level of concurrency. + Output strategies for main units -------------------------------- diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index f1dcdafd4..b3f1803b9 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -995,7 +995,7 @@ package Command_Line is Opt_Parallelism_Level => Create (Short_Name => "-j", Long_Name => "--jobs", - Pattern => "POSITIVE", + Pattern => "NATURAL", Help => "Maximal number of concurrently running tasks. Number of processors" & " of the machine if set to 0. Defaults to 1.", From 657d1019a2c8a0b9e6aab5e536995ef9a4806256 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 22 Sep 2023 11:18:54 +0200 Subject: [PATCH 0444/1483] doc: remove outdated references to `gnatcov_rts_full` We no longer have two versions of the runtime, but one version with various build configuration, and a `gnatcov setup` command picking the right configuration according to the target switches. Also document the build + install of the coverage runtime using `gnatcov setup` (which is the standard process) rather than manually building and installing the runtime. --- doc/gnatcov/src_traces.rst | 39 +++++++--------------------- doc/integration/integration_part.rst | 6 ++--- 2 files changed, 12 insertions(+), 33 deletions(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 74b993f48..98394bd07 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -685,24 +685,13 @@ of trace data to standard output. Setting up the coverage runtime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -We just "build" the runtime library project as we would build a regular -program for our target configuration, specifying the target name and the -intended base Ada runtime library. +As seen in the :ref:`instr-rts` section, we use the ``gnatcov setup`` command to +build and install the :term:`coverage runtime `:: For our intended target environment, this would be something like:: - # Copy the sources into a fresh local place for the build: - cp -rp /share/gnatcoverage/gnatcov_rts - - # Build and install the library to a place of our choice. Pick gnatcov_rts.gpr as - # we won't be emitting source trace files directly: - - cd - gprbuild -Pgnatcov_rts.gpr --target=powerpc-wrs-vxworks7r2 --RTS=rtp -f -p - - rm -rf - gprinstall -Pgnatcov_rts.gpr --target=powerpc-wrs-vxworks7r2 --RTS=rtp \ - -p --prefix= + gnatcov setup --target=powerpc-wrs-vxworks7r2 --RTS=rtp \ + --prefix= # Allow references to the coverage runtime project from other project files: export GPR_PROJECT_PATH=/share/gpr @@ -793,20 +782,10 @@ For the sake of the example, we will consider that Setting up the coverage runtime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -On a native system such as Linux or Windows, the simplest is to pick a -*gnatcov_rts_full.gpr* variant, thanks to which we will be able to produce -trace files directly. We go for a straightforward setup assuming we will use -the default full Ada runtime (no specific :cmd-option:`--RTS` option):: - - # Copy the sources into a fresh local place for the build: - cp -rp /share/gnatcoverage/gnatcov_rts +As seen in the :ref:`instr-rts` section, we use the ``gnatcov setup`` command to +build and install the :term:`coverage runtime `:: - # Build and install the library to a place of our choice. - cd - gprbuild -Pgnatcov_rts_full.gpr -f -p - - rm -rf - gprinstall -Pgnatcov_rts_full.gpr -p --prefix= + gnatcov setup --prefix= # Allow references to the coverage runtime project from other project files: export GPR_PROJECT_PATH=/share/gpr @@ -888,7 +867,7 @@ such as:: gnatcov instrument -Pcode.gpr -XCODE_LIBMODE=instrument --level=stmt+decision gprbuild -f -Pcode.gpr -XCODE_LIBMODE=build -p - --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts_full.gpr + --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts.gpr Both commands proceed with ``Externally_Built`` ``"False"``. There is no main unit attached to the library per se, so no need for @@ -916,7 +895,7 @@ the trace file. The build of instrumented tests then proceeds as follows:: gprbuild -Ptests.gpr -p - --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts_full.gpr + --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts.gpr And a regular execution in the host environment would produce a source trace in addition to performing the original functional operations. diff --git a/doc/integration/integration_part.rst b/doc/integration/integration_part.rst index 2e5b2247b..99aee92fe 100644 --- a/doc/integration/integration_part.rst +++ b/doc/integration/integration_part.rst @@ -210,7 +210,7 @@ example, this would be like: gnatcov instrument -PPkg1.Test_Data.Tests/test_driver.gpr --dump-trigger=main-end --level=stmt --projects=Prj --units=@Pkg1.Test_Data.Tests/units.list Building Pkg1.Test_Data.Tests/test_driver.gpr: - gprbuild -PPkg1.Test_Data.Tests/test_driver.gpr -o test_driver --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts_full + gprbuild -PPkg1.Test_Data.Tests/test_driver.gpr -o test_driver --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts ... Running Pkg1.Test_Data.Tests/test_driver.gpr: @@ -226,7 +226,7 @@ example, this would be like: gnatcov instrument -PPkg2.Test_Data.Tests/test_driver.gpr --dump-trigger=main-end --level=stmt --projects=Prj --units=@Pkg2.Test_Data.Tests/units.list Building Pkg2.Test_Data.Tests/test_driver.gpr: - gprbuild -PPkg2.Test_Data.Tests/test_driver.gpr -o test_driver --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts_full + gprbuild -PPkg2.Test_Data.Tests/test_driver.gpr -o test_driver --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts ... Running Pkg2.Test_Data.Tests/test_driver.gpr: @@ -313,7 +313,7 @@ which outputs: gnatcov instrument -Ptest_driver.gpr --dump-trigger=main-end --level=stmt --projects=Prj Building test_driver.gpr: - gprbuild -Ptest_driver.gpr -o test_driver --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts_full + gprbuild -Ptest_driver.gpr -o test_driver --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts ... Running test_driver.gpr: GNATCOV_TRACE_FILE=test_driver-gnattest_td.srctrace ./test_driver From 22037ec422ff36a5ac7dd4be92ffbe22635d727f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 27 Sep 2023 18:17:01 +0200 Subject: [PATCH 0445/1483] Fix line endings for instrumented sources under windows We need to open and write the instrumented source as a binary file, to be consistent with Libadalang which retrieves the tokens from a file opened in binary mode. It provides us with line terminators when unparsing the user-defined tokens and we must be careful to output these unaltered. On Windows for example, we get CRLF line terminators in the LAL tokens, as CR is not automatically stripped when opening a file in binary mode. If these line terminators (CRLF) were written in a text file, calls to fwrite would replace LF with CRLF, resulting in CRCRLF, which is incorrect. --- .../tests/127-check-line-endings/main.adb | 6 +++ .../tests/127-check-line-endings/test.py | 37 +++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 45 +++++++++++++------ tools/gnatcov/text_files.adb | 9 ++-- tools/gnatcov/text_files.ads | 3 +- 5 files changed, 79 insertions(+), 21 deletions(-) create mode 100644 testsuite/tests/127-check-line-endings/main.adb create mode 100644 testsuite/tests/127-check-line-endings/test.py diff --git a/testsuite/tests/127-check-line-endings/main.adb b/testsuite/tests/127-check-line-endings/main.adb new file mode 100644 index 000000000..0cbd4a8d5 --- /dev/null +++ b/testsuite/tests/127-check-line-endings/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/127-check-line-endings/test.py b/testsuite/tests/127-check-line-endings/test.py new file mode 100644 index 000000000..4ec472ffd --- /dev/null +++ b/testsuite/tests/127-check-line-endings/test.py @@ -0,0 +1,37 @@ +""" +Check that we do not have CRCRLF line endings in instrumented files. This used +to be the case on windows, as we were opening the instrumented file as a text +file, and not as a binary file when writing it. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir('tmp_') + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel='stmt', + mains=['main'], + extra_coverage_args=['-axcov', '--output-dir=xcov'], + trace_mode='src') + +# Check line endings +with open(os.path.join("obj", "gen-gnatcov-instr", "main.adb"), "rb") as f: + content = f.read() + thistest.fail_if( + b'\r\r\n' in content, + comment="wrong line ending in instrumented source", + ) + +check_xcov_reports('xcov/*.xcov', { + 'xcov/main.adb.xcov': {'+': {5}}, +}) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index a04b5215e..81002f2ed 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -26,6 +26,7 @@ pragma Warnings (Off, "* is an internal GNAT unit"); with Ada.Strings.Wide_Wide_Unbounded.Aux; pragma Warnings (On, "* is an internal GNAT unit"); with Ada.Text_IO; use Ada.Text_IO; +with Ada.Streams.Stream_IO; with Langkit_Support; with Langkit_Support.Slocs; use Langkit_Support.Slocs; @@ -8016,7 +8017,18 @@ package body Instrument.Ada_Unit is Remove_Warnings_And_Style_Checks_Pragmas (Unit); + -- Note: we need to open and write the instrumented source as a binary + -- file, to be consistent with Libadalang which retrieves the tokens + -- from a file opened in binary mode. It provides us with line + -- terminators when unparsing the user-defined tokens and we must be + -- careful to output these unaltered. On Windows for example, we get + -- CRLF line terminators in the LAL tokens, as CR is not automatically + -- stripped when opening a file in binary mode. If these line + -- terminators (CRLF) were written in a text file, calls to fwrite + -- would replace LF with CRLF, resulting in CRCRLF, which is incorrect. + declare + use Ada.Streams.Stream_IO; use Ada.Strings.Wide_Wide_Unbounded.Aux; Source : constant Unbounded_Wide_Wide_String := Unparse (Unit); @@ -8032,10 +8044,12 @@ package body Instrument.Ada_Unit is Chunk_Size : constant := 4096; Position : Natural; - Out_File : Text_Files.File_Type; + File : Ada.Streams.Stream_IO.File_Type; + S : Stream_Access; begin - Out_File.Create (Filename); - Put_Warnings_And_Style_Checks_Pragmas (Out_File); + Ada.Streams.Stream_IO.Create (File, Out_File, Filename); + S := Stream (File); + String'Write (S, "pragma Style_Checks (Off); pragma Warnings (Off);"); Get_Wide_Wide_String (Source, Source_Access, Length); Position := Source_Access.all'First; @@ -8051,14 +8065,14 @@ package body Instrument.Ada_Unit is Encoded_Chunk : constant String := Ada.Characters.Conversions.To_String (Chunk); begin - Out_File.Put (Encoded_Chunk); + String'Write (S, Encoded_Chunk); Position := Chunk_Last + 1; end; end loop; - Out_File.Close; + Close (File); if Switches.Pretty_Print then - Text_Files.Run_GNATpp (Out_File); + Text_Files.Run_GNATpp (Filename); end if; end; end Write_To_File; @@ -8894,6 +8908,7 @@ package body Instrument.Ada_Unit is is Last_Buffer_Index : constant Natural := Natural (CU_Names.Length); Pkg_Name : constant String := To_Ada (PB_Unit.Unit); + Filename : constant String := To_Filename (Prj, Ada_Language, PB_Unit); File : Text_Files.File_Type; procedure Put_Language_Version_Pragma; @@ -8919,7 +8934,7 @@ package body Instrument.Ada_Unit is -- Start of processing for Emit_Pure_Buffer_Unit begin - Create_File (Prj, File, To_Filename (Prj, Ada_Language, PB_Unit)); + Create_File (Prj, File, Filename); Put_Warnings_And_Style_Checks_Pragmas (File); Put_Language_Version_Pragma; @@ -8967,17 +8982,19 @@ package body Instrument.Ada_Unit is Text_Files.Close (File); if Switches.Pretty_Print then - Text_Files.Run_GNATpp (File); + Text_Files.Run_GNATpp (Filename); end if; if not Degenerate_Subprogram_Generics.Is_Empty then declare - PB_Unit_Body : Compilation_Unit_Part := PB_Unit; + PB_Unit_Body : constant Compilation_Unit_Part := + (Language_Kind => Unit_Based_Language, + Unit => PB_Unit.Unit, + Part => GNATCOLL.Projects.Unit_Body); + PB_Filename : constant String := + To_Filename (Prj, Ada_Language, PB_Unit_Body); begin - PB_Unit_Body.Part := GNATCOLL.Projects.Unit_Body; - - Create_File - (Prj, File, To_Filename (Prj, Ada_Language, PB_Unit_Body)); + Create_File (Prj, File, PB_Filename); Put_Warnings_And_Style_Checks_Pragmas (File); Put_Language_Version_Pragma; @@ -8992,7 +9009,7 @@ package body Instrument.Ada_Unit is Text_Files.Close (File); if Switches.Pretty_Print then - Text_Files.Run_GNATpp (File); + Text_Files.Run_GNATpp (PB_Filename); end if; end; end if; diff --git a/tools/gnatcov/text_files.adb b/tools/gnatcov/text_files.adb index facb0d5dd..020e57645 100644 --- a/tools/gnatcov/text_files.adb +++ b/tools/gnatcov/text_files.adb @@ -155,13 +155,12 @@ package body Text_Files is -- Run_GNATpp -- ---------------- - procedure Run_GNATpp (Self : Text_Files.File_Type) is + procedure Run_GNATpp (Filename : String) is use GNAT.OS_Lib; - Filename : constant String := US.To_String (Self.Filename); - Args : constant Argument_List := (1 => Filename'Unrestricted_Access); - GNATpp : String_Access := Locate_Exec_On_Path ("gnatpp"); - Success : Boolean; + Args : constant Argument_List := (1 => Filename'Unrestricted_Access); + GNATpp : String_Access := Locate_Exec_On_Path ("gnatpp"); + Success : Boolean; begin if GNATpp = null then Put_Line ("gnatpp not available"); diff --git a/tools/gnatcov/text_files.ads b/tools/gnatcov/text_files.ads index 4785a3fc6..f06b1393a 100644 --- a/tools/gnatcov/text_files.ads +++ b/tools/gnatcov/text_files.ads @@ -96,8 +96,7 @@ package Text_Files is Inline; -- Close the text file that Self references - procedure Run_GNATpp (Self : File_Type) - with Pre => not Self.Is_Open; + procedure Run_GNATpp (Filename : String); -- Run "gnatpp" on the given file (i.e. reformat/pretty-print it) procedure Run_Clang_Format (Filename : String); From 32eba72f006d7c110654eb9f5939982351a70558 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Sat, 9 Sep 2023 18:25:48 +0200 Subject: [PATCH 0446/1483] Instrument.Ada_Unit: refactor instrumentation process We no longer process statement by sequences and defer the processing of decisions. This was a leftover from the computation of dominance information, which is not needed in instrumentation mode, and it simplifies the instrumentation process a bit. We also use this as an opportunity to refactor the way we deal with non instrumented source code constructs, and make it similar to what is done in the C instrumentation process. --- tools/gnatcov/instrument-ada_unit.adb | 2071 +++++++++++-------------- tools/gnatcov/instrument-ada_unit.ads | 4 - tools/gnatcov/instrument-c.ads | 5 +- tools/gnatcov/instrument-common.ads | 4 + 4 files changed, 878 insertions(+), 1206 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 81002f2ed..c2853121a 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3000,11 +3000,10 @@ package body Instrument.Ada_Unit is -- the regular alternative processing typically involves attribute queries -- which aren't valid for a pragma. - procedure Process_Decisions - (UIC : in out Ada_Unit_Inst_Context; - N : Ada_Node'Class; - T : Character; - Do_Not_Instrument : Boolean := False); + procedure Process_Expression + (UIC : in out Ada_Unit_Inst_Context; + N : Ada_Node'Class; + T : Character); -- If N is Empty, has no effect. Otherwise scans the tree for the node N, -- to output any decisions it contains. T is one of IEGPWX (for context of -- expression: if/exit when/entry guard/pragma/while/expression). If T is @@ -3012,20 +3011,12 @@ package body Instrument.Ada_Unit is -- is always present (at the very least a simple decision is present at the -- top level). -- - -- If Do_Not_Instrument, this creates SCOs for the decisions/conditions, - -- but plans not to instrument them, so that the decision can be reported - -- as such. + -- This also processes any nested declare expressions. -------------------------- -- Internal Subprograms -- -------------------------- - function Has_Decision - (UIC : Ada_Unit_Inst_Context; T : Ada_Node'Class) return Boolean; - -- T is the node for a subtree. Returns True if any (sub)expression in T - -- contains a nested decision (i.e. either is a logical operator, or - -- contains a logical operator in its subtree). - function Operator (N : Expr'Class) return Op; -- Return the operator node of an unary or binary expression, or No_Op if -- not an operator. @@ -3051,12 +3042,6 @@ package body Instrument.Ada_Unit is -- Traverse_Declarations_Or_Statements -- ----------------------------------------- - -- Tables used by Traverse_Declarations_Or_Statements for temporarily - -- holding statement and decision entries. These are declared globally - -- since they are shared by recursive calls to this procedure. - -- - -- ??? Clarify terminology (CS, SC, SD) - type Instrument_Location_Type is (Before, After, Before_Parent, Inside_Expr); -- Where to insert the witness call for a statement: @@ -3080,83 +3065,6 @@ package body Instrument.Ada_Unit is -- statement, or as a declaration (before or after). Such occurrences are -- elsif statements. In this case, we will insert the witness call inside -- the underlying boolean expression. - -- - -- SC_Entry is a single entry in the following table, From:To represents - -- the range of entries in the CS line entry, and typ is the type, with - -- space meaning that no type letter will accompany the entry. - - type SC_Entry is record - N : Ada_Node; - -- Original statement node, providing the source location associated - -- with the statement SCO. - - Insertion_N : Node_Rewriting_Handle; - -- Rewriting handle of the node indicating where the witness call for - -- the statement is to be inserted. - - From : Source_Location; - To : Source_Location; - Typ : Character; - - Index : Natural := 0; - -- 1-based index of N in enclosing list, if any - - Instrument_Location : Instrument_Location_Type := Before; - -- Position where to insert the witness call relative to Insertion_N - -- (see declaration of Instrument_Location_Type for the meaning of - -- the various values). - - In_Generic : Boolean := False; - -- Wether this statment is generic code. - - Do_Not_Instrument : Boolean; - -- Whether this statement should not be instrumented. This is set to - -- True when instrumenting the statement could create invalid Ada code. - end record; - - package SC is new Table.Table - (Table_Component_Type => SC_Entry, - Table_Index_Type => Nat, - Table_Low_Bound => 1, - Table_Initial => 1000, - Table_Increment => 200, - Table_Name => "SCO_SC"); - -- Used to store statement components for a CS entry to be output as a - -- result of the call to this procedure. SC.Last is the last entry stored, - -- so the current statement sequence is represented by SC_Array (SC_First - -- .. SC.Last), where SC_First is saved on entry to each recursive call to - -- the routine. - -- - -- Extend_Statement_Sequence adds an entry to this array, and then - -- Set_Statement_Entry clears the entries starting with SC_First, copying - -- these entries to the main SCO output table. The reason that we do the - -- temporary caching of results in this array is that we want the SCO table - -- entries for a given CS line to be contiguous, and the processing may - -- output intermediate entries such as decision entries. - - type SD_Entry is record - Nod : Ada_Node; - Typ : Character; - Do_Not_Instrument : Boolean; - end record; - -- Used to store a single entry in the following table. Nod is the node to - -- be searched for decisions. - - package SD is new Table.Table - (Table_Component_Type => SD_Entry, - Table_Index_Type => Nat, - Table_Low_Bound => 1, - Table_Initial => 1000, - Table_Increment => 200, - Table_Name => "SCO_SD"); - -- Used to store possible decision information. Instead of calling the - -- Process_Decisions procedures directly, we call Process_Decisions_Defer, - -- which simply stores the arguments in this table. Then when we clear - -- out a statement sequence using Set_Statement_Entry, after generating - -- the CS lines for the statements, the entries in this table result in - -- calls to Process_Decision. The reason for doing things this way is to - -- ensure that decisions are output after the CS line for the statements - -- in which the decisions occur. procedure Traverse_Declarations_Or_Statements (UIC : in out Ada_Unit_Inst_Context; @@ -3166,24 +3074,17 @@ package body Instrument.Ada_Unit is Is_Select_Stmt_Alternative : Boolean := False; Priv_Part : Private_Part := No_Private_Part) is - SC_First : constant Nat := SC.Last + 1; - SD_First : constant Nat := SD.Last + 1; - -- Record first entries used in SC/SD at this recursive level - Current_Insertion_Info : aliased Insertion_Info := (Method => None); - procedure Extend_Statement_Sequence - (UIC : Ada_Unit_Inst_Context; - N : Ada_Node'Class; - Typ : Character; - Insertion_N : Node_Rewriting_Handle := - No_Node_Rewriting_Handle; - Instrument_Location : Instrument_Location_Type := Before; - Do_Not_Instrument : Boolean := False); - -- Extend the current statement sequence to encompass the node N. + procedure Instrument_Statement + (UIC : in out Ada_Unit_Inst_Context; + N : Ada_Node'Class; + Typ : Character; + Insertion_N : Node_Rewriting_Handle := No_Node_Rewriting_Handle); + -- Instrument the statement N. -- -- Typ is the letter that identifies the type of statement/declaration - -- that is being added to the sequence. + -- that is being instrumented. -- -- N is the original node from user code, and controls the source -- location assigned to the statement SCO. @@ -3193,37 +3094,14 @@ package body Instrument.Ada_Unit is -- (case of a degenerated subprogram, which gets rewritten into a -- generic). In that case, Insertion_N indicates where to insert the -- witness. - -- - -- Instrument_Location gives further information on how the witness call - -- should be inserted. - -- - -- ??? Instrument_Location is sometimes ignored, we should - -- probably refactor this so the logic for determining it is - -- more localized. - - procedure Process_Decisions_Defer - (N : Ada_Node'Class; - T : Character; - Do_Not_Instrument : Boolean := False); - -- This routine is logically the same as Process_Decisions, except that - -- the arguments are saved in the SD table for later processing when - -- Set_Statement_Entry is called, which goes through the saved entries - -- making the corresponding calls to Process_Decision. Note: the - -- enclosing statement must have already been added to the current - -- statement sequence, so that nested decisions are properly - -- identified as such. - -- - -- This also processes any nested declare expressions. - procedure Process_Contract (D : Basic_Decl'Class; Name : Text_Type) + procedure Process_Contract + (UIC : in out Ada_Unit_Inst_Context; + D : Basic_Decl'Class; + Name : Text_Type) with Pre => Assertion_Coverage_Enabled; -- Register decision of contrat of name Name of declaration node D - procedure Set_Statement_Entry; - -- Output CS entries for all statements saved in table SC, and end the - -- current CS sequence. Then output entries for all decisions nested in - -- these statements, which have been deferred so far. - procedure Traverse_One (N : Ada_Node); -- Traverse one declaration or statement @@ -3244,27 +3122,35 @@ package body Instrument.Ada_Unit is RC : Rewriting_Handle renames UIC.Rewriting_Context; - ------------------------------- - -- Extend_Statement_Sequence -- - ------------------------------- + -------------------------- + -- Instrument_Statement -- + -------------------------- - procedure Extend_Statement_Sequence - (UIC : Ada_Unit_Inst_Context; - N : Ada_Node'Class; - Typ : Character; - Insertion_N : Node_Rewriting_Handle := - No_Node_Rewriting_Handle; - Instrument_Location : Instrument_Location_Type := Before; - Do_Not_Instrument : Boolean := False) + procedure Instrument_Statement + (UIC : in out Ada_Unit_Inst_Context; + N : Ada_Node'Class; + Typ : Character; + Insertion_N : Node_Rewriting_Handle := No_Node_Rewriting_Handle) is - SR : constant Source_Location_Range := N.Sloc_Range; + Instrument_Location : Instrument_Location_Type := Before; + -- See the documentation of Instrument_Location_Type for more + -- information. + + Dummy_Ctx : constant Context_Handle := Create_Context_Instrument (N); - F : Source_Location := Start_Sloc (SR); - T : Source_Location := Inclusive_End_Sloc (SR); + Is_Pragma : constant Boolean := N.Kind = Ada_Pragma_Node; + Pragma_Aspect_Name : constant Name_Id := + (if Is_Pragma + then Pragma_Name (N.As_Pragma_Node) + else Namet.No_Name); + + SR : constant Source_Location_Range := N.Sloc_Range; + From : Source_Location := Start_Sloc (SR); + To : Source_Location := Inclusive_End_Sloc (SR); -- Source location bounds used to produre a SCO statement. By -- default, this should cover the same source location range as N, -- however for nodes that can contain themselves other statements - -- (for instance IN statements), we select an end bound that appears + -- (for instance IF statements), we select an end bound that appears -- before the first nested statement (see To_Node below). To_Node : Ada_Node := No_Ada_Node; @@ -3272,6 +3158,17 @@ package body Instrument.Ada_Unit is -- Otherwise, use F and this node's end sloc for the emitted -- statement source location range. + Actual_Insertion_N : constant Node_Rewriting_Handle := + (if Insertion_N = No_Node_Rewriting_Handle + then Handle (N) + else Insertion_N); + + Index : constant Natural := + (case UIC.Current_Insertion_Info.Method is + when Statement | Declaration => + UIC.Current_Insertion_Info.Index, + when others => 0); + begin case Kind (N) is when Ada_Accept_Stmt | Ada_Accept_Stmt_With_Stmts => @@ -3300,6 +3197,7 @@ package body Instrument.Ada_Unit is when Ada_Elsif_Stmt_Part => To_Node := N.As_Elsif_Stmt_Part.F_Cond_Expr.As_Ada_Node; + Instrument_Location := Inside_Expr; when Ada_If_Stmt => To_Node := N.As_If_Stmt.F_Cond_Expr.As_Ada_Node; @@ -3314,7 +3212,7 @@ package body Instrument.Ada_Unit is | Ada_Single_Protected_Decl | Ada_Single_Task_Decl => - T := F; + To := From; when Ada_Protected_Type_Decl | Ada_Task_Type_Decl @@ -3357,7 +3255,7 @@ package body Instrument.Ada_Unit is Null_Token : constant Token_Reference := NNT (NNT (N.As_Null_Subp_Decl.F_Subp_Spec.Token_End)); begin - F := Start_Sloc (Sloc_Range (Data (Null_Token))); + From := Start_Sloc (Sloc_Range (Data (Null_Token))); end; when others => @@ -3365,461 +3263,335 @@ package body Instrument.Ada_Unit is end case; if not To_Node.Is_Null then - T := Inclusive_End_Sloc (To_Node.Sloc_Range); + To := Inclusive_End_Sloc (To_Node.Sloc_Range); end if; - SC.Append - ((N => N.As_Ada_Node, - Insertion_N => - (if Insertion_N = No_Node_Rewriting_Handle - then Handle (N) - else Insertion_N), - From => F, - To => T, - Typ => Typ, - Index => (case UIC.Current_Insertion_Info.Method is - when Statement | Declaration => - UIC.Current_Insertion_Info.Index, - when others => 0), - Instrument_Location => - -- See the comment attached to the declaration of the - -- Instrument_Location_Type. - - (if Is_Select_Stmt_Alternative - and then N = L.Children (L.Children'First) - then (case N.Kind is - when Ada_Delay_Stmt - | Ada_Call_Stmt => Before_Parent, - when others => After) - else Instrument_Location), - - In_Generic => UIC.In_Generic, - Do_Not_Instrument => Do_Not_Instrument)); - end Extend_Statement_Sequence; - - ----------------------------- - -- Process_Decisions_Defer -- - ----------------------------- - - procedure Process_Decisions_Defer - (N : Ada_Node'Class; - T : Character; - Do_Not_Instrument : Boolean := False) - is - function Process_Decl_Expr (N : Ada_Node'Class) return Visit_Status; - -- Helper to Libadalang's Traverse. Only operates on Decl_Exprs, - -- instrument each declaration as a statement and process the nested - -- expressions. + Instrument_Location := + -- See the comment attached to the declaration of the + -- Instrument_Location_Type. - ----------------------- - -- Process_Decl_Expr -- - ----------------------- + (if Is_Select_Stmt_Alternative + and then N = L.Children (L.Children'First) + then (case N.Kind is + when Ada_Delay_Stmt + | Ada_Call_Stmt => Before_Parent, + when others => After) + else Instrument_Location); - function Process_Decl_Expr (N : Ada_Node'Class) return Visit_Status is - begin - if N.Kind in Ada_Decl_Expr then - declare - Saved_Inserter : constant Any_MCDC_State_Inserter := - UIC.MCDC_State_Inserter; - Saved_In_Decl_Expr : constant Boolean := UIC.In_Decl_Expr; - Local_Inserter : aliased Default_MCDC_State_Inserter := - (Local_Decls => Handle (N.As_Decl_Expr.F_Decls)); - begin - Set_Statement_Entry; - UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; - UIC.In_Decl_Expr := True; - - -- Traverse_declarations_And_Statements will instrument the - -- declarations as statements, as well as instrument the - -- nested decisions within those declarations. - - Traverse_Declarations_Or_Statements - (UIC, N.As_Decl_Expr.F_Decls); - UIC.MCDC_State_Inserter := Saved_Inserter; - UIC.In_Decl_Expr := Saved_In_Decl_Expr; - - -- End the statement sequence right away as there isn't - -- going to be any more statements that follow. - - Set_Statement_Entry; - return Over; - end; - else - return Into; - end if; - end Process_Decl_Expr; - - begin - SD.Append ((N.As_Ada_Node, T, Do_Not_Instrument)); - if not N.Is_Null then - N.Traverse (Process_Decl_Expr'Access); - end if; - end Process_Decisions_Defer; - - ---------------------- - -- Process_Contract -- - ---------------------- - - procedure Process_Contract (D : Basic_Decl'Class; Name : Text_Type) is - begin - Process_Decisions_Defer - (P_Get_Aspect_Spec_Expr (D, To_Unbounded_Text (Name)), 'A'); - end Process_Contract; + Append_SCO + (C1 => 'S', + C2 => Typ, + From => +From, + To => +To, + SFI => UIC.SFI, + Last => True, + Pragma_Aspect_Name => Pragma_Aspect_Name); - ------------------------- - -- Set_Statement_Entry -- - ------------------------- - - procedure Set_Statement_Entry is - SC_Last : constant Int := SC.Last; - SD_Last : constant Int := SD.Last; - - procedure Insert_Statement_Witness (SCE : SC_Entry; LL_SCO_Id : Nat) - with Pre => - (case UIC.Current_Insertion_Info.Method is - when Statement | Declaration => - not UIC.Current_Insertion_Info.Preelab - and then - UIC.Current_Insertion_Info.RH_List /= No_Node_Rewriting_Handle, - when Expression_Function => True, - when None => False); - -- Insert statement witness call for the given SCE - - ------------------------------ - -- Insert_Statement_Witness -- - ------------------------------ - - procedure Insert_Statement_Witness - (SCE : SC_Entry; LL_SCO_Id : Nat) - is - Insert_List : Node_Rewriting_Handle; - Insert_Pos : Natural; - Insert_Info : Insertion_Info_Access := UIC.Current_Insertion_Info; + -- Insert a witness call for this statement obligation + -- unless... - Bit : Any_Bit_Id; - begin - -- Create an artificial internal error, if requested + if + -- ... there is no enclosing list to which a witness call + -- can be attached. - Raise_Stub_Internal_Error_For (Ada_Instrument_Insert_Stmt_Witness); + UIC.Current_Insertion_Info.Method /= None - if SCE.Do_Not_Instrument then - UIC.Non_Instr_LL_SCOs.Include (SCO_Id (LL_SCO_Id)); - return; - end if; + -- ... this is a top-level declaration in a Preelaborate + -- package. - -- Allocate a bit in the statement coverage buffer + and then (UIC.Current_Insertion_Info.Method + not in Statement | Declaration + or else not UIC.Current_Insertion_Info.Preelab) - Bit := Allocate_Statement_Bit (UIC.Unit_Bits, LL_SCO_Id); + -- ... this is a pragma that we know for certain will not + -- generate code (such as Annotate or elaboration control + -- pragmas). - case Insert_Info.Method is + and then (not Is_Pragma + or else + Pragma_Might_Generate_Code + (Case_Insensitive_Get_Pragma_Id + (Pragma_Aspect_Name))) - when Statement | Declaration => + -- ... this is a disabled pragma that we assume will not + -- generate code. - if SCE.Instrument_Location = Inside_Expr then - declare - Old_Cond : Node_Rewriting_Handle := SCE.Insertion_N; - New_Cond : constant Node_Rewriting_Handle := - Create_Regular_Node - (RC, - Ada_Bin_Op, - Children => - (1 => Make_Statement_Witness - (UIC, - Bit => Bit, - Flavor => Function_Call, - In_Generic => SCE.In_Generic), + and then Typ /= 'p' + then + declare + Insert_List : Node_Rewriting_Handle; + Insert_Pos : Natural; + Insert_Info : Insertion_Info_Access := + UIC.Current_Insertion_Info; - 2 => Make (UIC, Ada_Op_Or_Else), + Bit : Any_Bit_Id; - -- Placeholder for relocation of old condition - -- after it is detached from the tree. + LL_SCO_Id : constant Nat := SCOs.SCO_Table.Last; + begin + -- Create an artificial internal error, if requested - 3 => No_Node_Rewriting_Handle)); + Raise_Stub_Internal_Error_For + (Ada_Instrument_Insert_Stmt_Witness); - begin - -- Detach old condition from tree and replace it with - -- OR ELSE node. - - Replace (Old_Cond, New_Cond); - - -- Now reattach old condition in new OR ELSE node. If it - -- is AND, OR, XOR, AND THEN binary operation or an IF - -- expression, or a quantified expression (FOR ALL, FOR - -- SOME), we need to wrap it in parens to generate valid - -- code. - - -- Now reattach old condition in the new OR ELSE node. We - -- will wrap it in parens to preserve the semantics of - -- the condition. - -- - -- The two operands of the OR ELSE may not have the same - -- type (Standard.Boolean for the Witness return type). - -- We could convert the result of the witness call to the - -- actual type of the expression, but this requires - -- "withing" the package in which the derived boolean - -- type is defined in case it is not visible. Instead, as - -- this is a top-level boolean expression, we can simply - -- convert the original expression to Standard.Boolean. - - Old_Cond := Create_Call_Expr - (RC, - F_Name => Create_Identifier - (RC, To_Text ("GNATcov_RTS.Std.Boolean")), - F_Suffix => Create_Regular_Node - (RC, - Ada_Assoc_List, - (1 => Create_Param_Assoc - (RC, - F_Designator => No_Node_Rewriting_Handle, - F_R_Expr => Old_Cond)))); + -- If the current code pattern is actually unsupported, do + -- not even try to insert the witness call or allocate bits + -- for it in the buffers. Mark the corresponding SCO as + -- non-instrumented instead. - Set_Child (New_Cond, 3, Old_Cond); - end; + if UIC.Disable_Instrumentation then + UIC.Non_Instr_LL_SCOs.Include (SCO_Id (LL_SCO_Id)); + return; + end if; - else - if Kind (SCE.Insertion_N) = Ada_Accept_Stmt_With_Stmts - and then SCE.Instrument_Location = After - then - -- In the case of an accept_statement containing a - -- sequence of statements, if Instrument_Location is - -- After, we want to call the witness after the entry has - -- been accepted, but before the enclosed statements are - -- executed, so insert the witness call in the inner - -- statement list at first position. - - Insert_List := - Child (SCE.Insertion_N, - (Member_Refs.Accept_Stmt_With_Stmts_F_Stmts, - Member_Refs.Handled_Stmts_F_Stmts)); - Insert_Pos := 1; + -- Allocate a bit in the statement coverage buffer - else - if SCE.Instrument_Location = Before_Parent then - Insert_Info := Insert_Info.Parent; - Insert_Pos := Insert_Info.Index; - else - Insert_Pos := SCE.Index; - end if; + Bit := Allocate_Statement_Bit (UIC.Unit_Bits, LL_SCO_Id); - Insert_List := Insert_Info.RH_List; + case Insert_Info.Method is - -- Adjust insertion to account for any insertion - -- performed outside of the processing of the current - -- list (case of the above special processing for accept - -- statements). Note that SCE.N might not be a direct - -- element of the enclosing list (e.g. in the case where - -- it is a named statement), so we must first go up to - -- the parent of SCE.N that *is* an element of that list, - -- and *then* scan forward to determine the current - -- position of that parent note within the list. + when Statement | Declaration => + if Instrument_Location = Inside_Expr then declare - RH_Element_Node : Node_Rewriting_Handle := - SCE.Insertion_N; - RH_Children_Count : constant Natural := - Children_Count (Insert_Info.RH_List); - begin - -- Find the parent of SCE.N that is an element of the - -- enclosing list. + Old_Cond : Node_Rewriting_Handle := Actual_Insertion_N; + New_Cond : constant Node_Rewriting_Handle := + Create_Regular_Node + (RC, + Ada_Bin_Op, + Children => + (1 => Make_Statement_Witness + (UIC, + Bit => Bit, + Flavor => Function_Call, + In_Generic => UIC.In_Generic), - while Parent (RH_Element_Node) - /= Insert_Info.RH_List - loop - RH_Element_Node := Parent (RH_Element_Node); - end loop; + 2 => Make (UIC, Ada_Op_Or_Else), - -- Scan forward in enclosing list for adjusted - -- position of the element node. - - while Child - (Insert_Info.RH_List, - Integer (Insert_Pos - + Insert_Info.Rewriting_Offset)) - /= RH_Element_Node - loop - Insert_Info.Rewriting_Offset := - Insert_Info.Rewriting_Offset + 1; - pragma Assert - (Insert_Pos + Insert_Info.Rewriting_Offset - <= RH_Children_Count); - end loop; - end; - - -- The witness is inserted at the current location of the - -- statement, so that it will occur immediately *before* - -- it in the instrumented sources. This is necessary - -- because we want to mark a statement as executed - -- anytime it has commenced execution (including in cases - -- it raises an exception or otherwise transfers - -- control). However in some special cases we have to - -- insert after the statement, see comment for - -- Instrument_Location_Type. - -- - -- The cases where we need to instrument inside an - -- expression are handled before, as they do not trigger - -- the insertion of a new statement in a statement list. - - Insert_Pos := Insert_Pos - + Insert_Info.Rewriting_Offset - + (case SCE.Instrument_Location is - when Before | Before_Parent => 0, - when After => 1, - when Inside_Expr => - raise Program_Error); - end if; + -- Placeholder for relocation of old condition + -- after it is detached from the tree. - -- Insert witness statement or declaration - - Insert_Child - (Handle => Insert_List, - Index => Insert_Pos, - Child => - Make_Statement_Witness - (UIC, - Bit => Bit, - Flavor => - (case Insert_Info.Method is - when Statement => Procedure_Call, - when Declaration => Declaration, - when Expression_Function | None => - raise Program_Error), - In_Generic => SCE.In_Generic)); - - -- Update the rewriting offset iff we inserted an element in - -- the current rewriting list: that offset specifically - -- refers to that list, whereas we may have inserted an item - -- in a nested list, in which case we will adjust - -- automatically the rewriting offset accordingly when - -- processing that list. - - if Insert_Info.RH_List = Insert_List then - Insert_Info.Rewriting_Offset := - Insert_Info.Rewriting_Offset + 1; - end if; - end if; + 3 => No_Node_Rewriting_Handle)); - when Expression_Function => - - -- Create both the witness call and a formal parameter to - -- accept it as an actual. - - declare - RC : constant Rewriting_Handle := UIC.Rewriting_Context; - - Formal_Name : constant Node_Rewriting_Handle := - Make_Identifier (UIC, "Dummy_Witness_Result"); - Formal_Def_Id : constant Node_Rewriting_Handle := - Create_Regular_Node - (RC, - Ada_Defining_Name_List, - Children => (1 => Create_Defining_Name - (RC, Formal_Name))); - begin - Insert_Info.Witness_Actual := Make_Statement_Witness - (UIC, - Bit => Bit, - Flavor => Function_Call, - In_Generic => SCE.In_Generic); - - Insert_Info.Witness_Formal := Create_Param_Spec - (RC, - F_Ids => Formal_Def_Id, - F_Has_Aliased => No_Node_Rewriting_Handle, - F_Mode => No_Node_Rewriting_Handle, - F_Type_Expr => Make_Identifier (UIC, "Boolean"), - F_Default_Expr => No_Node_Rewriting_Handle, - F_Aspects => No_Node_Rewriting_Handle); - end; - - when None => - raise Program_Error; - end case; - end Insert_Statement_Witness; - - -- Start of processing for Set_Statement_Entry - - begin - -- Output statement entries from saved entries in SC table + begin + -- Detach old condition from tree and replace it with + -- OR ELSE node. - for J in SC_First .. SC_Last loop - declare - SCE : SC_Entry renames SC.Table (J); - Dummy_Ctx : constant Context_Handle := - Create_Context_Instrument (SCE.N); + Replace (Old_Cond, New_Cond); - Is_Pragma : constant Boolean := - SCE.N.Kind = Ada_Pragma_Node; - Pragma_Aspect_Name : constant Name_Id := - (if Is_Pragma - then Pragma_Name (SCE.N.As_Pragma_Node) - else Namet.No_Name); + -- Now reattach old condition in new OR ELSE node. If + -- it is AND, OR, XOR, AND THEN binary operation or an + -- IF expression, or a quantified expression (FOR ALL, + -- FOR SOME), we need to wrap it in parens to generate + -- valid code. - begin - Append_SCO - (C1 => 'S', - C2 => SCE.Typ, - From => +SCE.From, - To => +SCE.To, - SFI => UIC.SFI, - Last => (J = SC_Last), - Pragma_Aspect_Name => Pragma_Aspect_Name); - - -- Insert a witness call for this statement obligation - -- unless... + -- Now reattach old condition in the new OR ELSE node. + -- We will wrap it in parens to preserve the semantics + -- of the condition. + -- + -- The two operands of the OR ELSE may not have the + -- same type (Standard.Boolean for the Witness return + -- type). We could convert the result of the witness + -- call to the actual type of the expression, but this + -- requires "withing" the package in which the derived + -- boolean type is defined in case it is not visible. + -- Instead, as this is a top-level boolean expression, + -- we can simply convert the original expression to + -- Standard.Boolean. + + Old_Cond := Create_Call_Expr + (RC, + F_Name => Create_Identifier + (RC, To_Text ("GNATcov_RTS.Std.Boolean")), + F_Suffix => Create_Regular_Node + (RC, + Ada_Assoc_List, + (1 => Create_Param_Assoc + (RC, + F_Designator => No_Node_Rewriting_Handle, + F_R_Expr => Old_Cond)))); + + Set_Child (New_Cond, 3, Old_Cond); + end; - if - -- ... there is no enclosing list to which a witness call - -- can be attached. + else + if Kind (Actual_Insertion_N) = Ada_Accept_Stmt_With_Stmts + and then Instrument_Location = After + then + -- In the case of an accept_statement containing a + -- sequence of statements, if Instrument_Location + -- is After, we want to call the witness after the + -- entry has been accepted, but before the enclosed + -- statements are executed, so insert the witness + -- call in the inner statement list at first position. + + Insert_List := + Child (Actual_Insertion_N, + (Member_Refs.Accept_Stmt_With_Stmts_F_Stmts, + Member_Refs.Handled_Stmts_F_Stmts)); + Insert_Pos := 1; - UIC.Current_Insertion_Info.Method /= None + else + if Instrument_Location = Before_Parent then + Insert_Info := Insert_Info.Parent; + Insert_Pos := Insert_Info.Index; + else + Insert_Pos := Index; + end if; - -- ... this is a top-level declaration in a Preelaborate - -- package. + Insert_List := Insert_Info.RH_List; - and then (UIC.Current_Insertion_Info.Method - not in Statement | Declaration - or else not UIC.Current_Insertion_Info.Preelab) + -- Adjust insertion to account for any insertion + -- performed outside of the processing of the current + -- list (case of the above special processing for + -- accept statements). Note that SCE.N might not be a + -- direct element of the enclosing list (e.g. in the + -- case where it is a named statement), so we must + -- first go up to the parent of SCE.N that *is* an + -- element of that list, and *then* scan forward to + -- determine the current position of that parent note + -- within the list. - -- ... this is a pragma that we know for certain will not - -- generate code (such as Annotate or elaboration control - -- pragmas). + declare + RH_Element_Node : Node_Rewriting_Handle := + Actual_Insertion_N; + RH_Children_Count : constant Natural := + Children_Count (Insert_Info.RH_List); + begin + -- Find the parent of N that is an element of the + -- enclosing list. + + while Parent (RH_Element_Node) + /= Insert_Info.RH_List + loop + RH_Element_Node := Parent (RH_Element_Node); + end loop; + + -- Scan forward in enclosing list for adjusted + -- position of the element node. + + while Child + (Insert_Info.RH_List, + Integer (Insert_Pos + + Insert_Info.Rewriting_Offset)) + /= RH_Element_Node + loop + Insert_Info.Rewriting_Offset := + Insert_Info.Rewriting_Offset + 1; + pragma Assert + (Insert_Pos + Insert_Info.Rewriting_Offset + <= RH_Children_Count); + end loop; + end; - and then (not Is_Pragma - or else - Pragma_Might_Generate_Code - (Case_Insensitive_Get_Pragma_Id - (Pragma_Aspect_Name))) + -- The witness is inserted at the current location of + -- the statement, so that it will occur immediately + -- *before* it in the instrumented sources. This + -- is necessary because we want to mark a statement + -- as executed anytime it has commenced execution + -- (including in cases it raises an exception or + -- otherwise transfers control). However in some + -- special cases we have to insert after the + -- statement, see the comment for + -- Instrument_Location_Type. + -- + -- The cases where we need to instrument inside an + -- expression are handled before, as they do not + -- trigger the insertion of a new statement in a + -- statement list. + + Insert_Pos := Insert_Pos + + Insert_Info.Rewriting_Offset + + (case Instrument_Location is + when Before | Before_Parent => 0, + when After => 1, + when Inside_Expr => + raise Program_Error); + end if; - -- ... this is a disabled pragma that we assume will not - -- generate code. + -- Insert witness statement or declaration + + Insert_Child + (Handle => Insert_List, + Index => Insert_Pos, + Child => + Make_Statement_Witness + (UIC, + Bit => Bit, + Flavor => + (case Insert_Info.Method is + when Statement => Procedure_Call, + when Declaration => Declaration, + when Expression_Function | None => + raise Program_Error), + In_Generic => UIC.In_Generic)); + + -- Update the rewriting offset iff we inserted an + -- element in the current rewriting list: that offset + -- specifically refers to that list, whereas we may + -- have inserted an item in a nested list, in which case + -- we will adjust automatically the rewriting offset + -- accordingly when processing that list. + + if Insert_Info.RH_List = Insert_List then + Insert_Info.Rewriting_Offset := + Insert_Info.Rewriting_Offset + 1; + end if; + end if; - and then SCE.Typ /= 'p' - then - Insert_Statement_Witness (SCE, SCOs.SCO_Table.Last); - end if; - end; - end loop; + when Expression_Function => - -- Clear out used section of SC table + -- Create both the witness call and a formal parameter to + -- accept it as an actual. - SC.Set_Last (SC_First - 1); + declare + RC : constant Rewriting_Handle := UIC.Rewriting_Context; - -- Output any embedded decisions + Formal_Name : constant Node_Rewriting_Handle := + Make_Identifier (UIC, "Dummy_Witness_Result"); + Formal_Def_Id : constant Node_Rewriting_Handle := + Create_Regular_Node + (RC, + Ada_Defining_Name_List, + Children => (1 => Create_Defining_Name + (RC, Formal_Name))); + begin + Insert_Info.Witness_Actual := Make_Statement_Witness + (UIC, + Bit => Bit, + Flavor => Function_Call, + In_Generic => UIC.In_Generic); - for J in SD_First .. SD_Last loop - declare - SDE : SD_Entry renames SD.Table (J); + Insert_Info.Witness_Formal := Create_Param_Spec + (RC, + F_Ids => Formal_Def_Id, + F_Has_Aliased => No_Node_Rewriting_Handle, + F_Mode => No_Node_Rewriting_Handle, + F_Type_Expr => Make_Identifier (UIC, "Boolean"), + F_Default_Expr => No_Node_Rewriting_Handle, + F_Aspects => No_Node_Rewriting_Handle); + end; - begin - Process_Decisions - (UIC, SDE.Nod, SDE.Typ, SDE.Do_Not_Instrument); + when None => + raise Program_Error; + end case; end; - end loop; + end if; + end Instrument_Statement; - -- Clear out used section of SD table + ---------------------- + -- Process_Contract -- + ---------------------- - SD.Set_Last (SD_First - 1); - end Set_Statement_Entry; + procedure Process_Contract + (UIC : in out Ada_Unit_Inst_Context; + D : Basic_Decl'Class; + Name : Text_Type) is + begin + Process_Expression + (UIC, + P_Get_Aspect_Spec_Expr (D, To_Unbounded_Text (Name)), + 'A'); + end Process_Contract; ------------------------------------ -- Traverse_Degenerate_Subprogram -- @@ -3929,7 +3701,7 @@ package body Instrument.Ada_Unit is -- Add witness statement for the single statement - Extend_Statement_Sequence + Instrument_Statement (UIC => UIC, N => N, Typ => ' ', @@ -3939,7 +3711,7 @@ package body Instrument.Ada_Unit is -- dealing with an expression function if N.Kind = Ada_Expr_Function then - Process_Decisions_Defer (N.As_Expr_Function.F_Expr, 'X'); + Process_Expression (UIC, N.As_Expr_Function.F_Expr, 'X'); end if; -- Insert the new regular function in place of the old subprogram @@ -3954,8 +3726,6 @@ package body Instrument.Ada_Unit is F_Stmts => Stmts_RH, F_End_Name => Proc_Name)); - Set_Statement_Entry; - UIC.Current_Insertion_Info := Saved_Insertion_Info; UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; end To_Regular_Subprogram; @@ -4005,7 +3775,8 @@ package body Instrument.Ada_Unit is -- Witness insertion info for statements (for both null procedures -- and expression functions). - Do_Not_Instrument : Boolean := False; + Save_Disable_Instrumentation : constant Boolean := + UIC.Disable_Instrumentation; EF_Inserter : aliased Expr_Func_MCDC_State_Inserter := (N_Spec => N_Spec, @@ -4118,13 +3889,8 @@ package body Instrument.Ada_Unit is -- Instead, force the witness to go in the newly declared list -- using the Insertion_N param. - Extend_Statement_Sequence - (UIC, - Expr_Func.F_Expr, - 'X', - Insertion_N => Dummy_Decl); - Process_Decisions_Defer (Expr_Func.F_Expr, 'X'); - Set_Statement_Entry; + Instrument_Statement (UIC, Expr_Func.F_Expr, 'X', Dummy_Decl); + Process_Expression (UIC, Expr_Func.F_Expr, 'X'); -- Restore context @@ -4137,7 +3903,7 @@ package body Instrument.Ada_Unit is if Is_Generic (UIC, N.As_Basic_Decl) then if Is_Expr_Function then - Do_Not_Instrument := True; + UIC.Disable_Instrumentation := True; Report (UIC, N, "gnatcov limitation: " & "cannot instrument generic expression functions." @@ -4148,7 +3914,7 @@ package body Instrument.Ada_Unit is -- functions and null procedures, we are in the case of a -- generic null procedure here. - Do_Not_Instrument := True; + UIC.Disable_Instrumentation := True; Report (UIC, N, "gnatcov limitation:" & " cannot instrument generic null procedures." @@ -4184,7 +3950,7 @@ package body Instrument.Ada_Unit is -- so that the augmented EF is no longer a primitive of its -- return type. Need to check for potential freezing issues. - Do_Not_Instrument := True; + UIC.Disable_Instrumentation := True; Report (UIC, N, "gnatcov limitation:" & " cannot instrument an expression function which is" @@ -4195,7 +3961,7 @@ package body Instrument.Ada_Unit is elsif Is_Self_Referencing (UIC, N.As_Expr_Function) and then not Common_Nodes.Ctrl_Type.Is_Null then - Do_Not_Instrument := True; + UIC.Disable_Instrumentation := True; Report (UIC, N, "gnatcov limitation:" & " instrumenting a self referencing (i.e. recursive)" @@ -4237,7 +4003,7 @@ package body Instrument.Ada_Unit is Witness_Actual => No_Node_Rewriting_Handle, Witness_Formal => No_Node_Rewriting_Handle); - if not Do_Not_Instrument then + if not UIC.Disable_Instrumentation then -- Pass all expression function parameters to the augmented -- expression function call. @@ -4270,19 +4036,19 @@ package body Instrument.Ada_Unit is -- procedure (NP_Nodes.Null_Stmt). New_Insertion_Info := - (Method => Statement, - RH_List => NP_Nodes.Stmt_List, - Index => 1, - Rewriting_Offset => 0, + (Method => Statement, + RH_List => NP_Nodes.Stmt_List, + Index => 1, + Rewriting_Offset => 0, -- Even if the current package has elaboration restrictions, -- this Insertion_Info is used to insert a witness call in the -- procedure in the generic body: the elaboration restriction -- does not apply there. - Preelab => False, + Preelab => False, - Parent => null); + Parent => null); end if; ---------------------------------- @@ -4299,23 +4065,20 @@ package body Instrument.Ada_Unit is declare N_Expr : constant Expr := N.As_Expr_Function.F_Expr; begin - Extend_Statement_Sequence - (UIC, N_Expr, 'X', Do_Not_Instrument => Do_Not_Instrument); - Process_Decisions_Defer (N_Expr, 'X', Do_Not_Instrument); + Instrument_Statement (UIC, N_Expr, 'X'); + Process_Expression (UIC, N_Expr, 'X'); end; else -- Even though there is a "null" keyword in the null procedure, -- is no dedicated node for it in the Libadalang parse tree: use -- the whole null procedure declaration to provide a sloc. - Extend_Statement_Sequence - (UIC => UIC, - N => N, - Typ => 'X', - Insertion_N => NP_Nodes.Null_Stmt, - Do_Not_Instrument => Do_Not_Instrument); + Instrument_Statement + (UIC => UIC, + N => N, + Typ => 'X', + Insertion_N => NP_Nodes.Null_Stmt); end if; - Set_Statement_Entry; -- Restore saved insertion context @@ -4325,7 +4088,8 @@ package body Instrument.Ada_Unit is -- There is nothing else to do if we gave up instrumenting this -- subprogram. - if Do_Not_Instrument then + if UIC.Disable_Instrumentation then + UIC.Disable_Instrumentation := Save_Disable_Instrumentation; return; end if; @@ -4499,8 +4263,8 @@ package body Instrument.Ada_Unit is procedure Process_Contracts (D : Basic_Decl'Class) is begin if Assertion_Coverage_Enabled then - Process_Contract (D, "Pre"); - Process_Contract (D, "Post"); + Process_Contract (UIC, D, "Pre"); + Process_Contract (UIC, D, "Post"); end if; end Process_Contracts; @@ -4509,11 +4273,9 @@ package body Instrument.Ada_Unit is N_Spec : constant Subp_Spec := N.P_Subp_Spec_Or_Null.As_Subp_Spec; begin - Set_Statement_Entry; - -- Process decisions nested in formal parameters - Process_Decisions_Defer (N_Spec.F_Subp_Params, 'X'); + Process_Expression (UIC, N_Spec.F_Subp_Params, 'X'); Enter_Scope (UIC => UIC, @@ -4546,11 +4308,6 @@ package body Instrument.Ada_Unit is Saved_In_Generic : constant Boolean := UIC.In_Generic; 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. - case N.Kind is -- Top of the tree: Compilation unit @@ -4665,7 +4422,6 @@ package body Instrument.Ada_Unit is -- Package declaration when Ada_Package_Decl => - Set_Statement_Entry; Traverse_Package_Declaration (UIC, N.As_Base_Package_Decl, Preelab); @@ -4673,7 +4429,6 @@ package body Instrument.Ada_Unit is when Ada_Generic_Package_Decl => UIC.In_Generic := True; - Set_Statement_Entry; Traverse_Generic_Package_Declaration (UIC, N.As_Generic_Package_Decl, Preelab); UIC.In_Generic := Saved_In_Generic; @@ -4682,7 +4437,6 @@ package body Instrument.Ada_Unit is when Ada_Package_Body => UIC.In_Generic := Is_Generic (UIC, N.As_Basic_Decl); - Set_Statement_Entry; Traverse_Package_Body (UIC, N.As_Package_Body, Preelab); UIC.In_Generic := Saved_In_Generic; @@ -4698,8 +4452,8 @@ package body Instrument.Ada_Unit is -- Entry declaration when Ada_Entry_Decl => - Process_Decisions_Defer - (As_Entry_Decl (N).F_Spec.F_Entry_Params, 'X'); + Process_Expression + (UIC, As_Entry_Decl (N).F_Spec.F_Entry_Params, 'X'); -- Generic subprogram declaration @@ -4708,10 +4462,10 @@ package body Instrument.Ada_Unit is GSD : constant Generic_Subp_Decl := As_Generic_Subp_Decl (N); begin UIC.In_Generic := True; - Process_Decisions_Defer - (GSD.F_Formal_Part.F_Decls, 'X'); - Process_Decisions_Defer - (GSD.F_Subp_Decl.F_Subp_Spec.F_Subp_Params, 'X'); + Process_Expression + (UIC, GSD.F_Formal_Part.F_Decls, 'X'); + Process_Expression + (UIC, GSD.F_Subp_Decl.F_Subp_Spec.F_Subp_Params, 'X'); UIC.In_Generic := Saved_In_Generic; end; @@ -4723,7 +4477,6 @@ package body Instrument.Ada_Unit is if Is_Generic (UIC, N.As_Basic_Decl) then UIC.In_Generic := True; end if; - Set_Statement_Entry; Traverse_Subprogram_Or_Task_Body (UIC, N); UIC.In_Generic := Saved_In_Generic; @@ -4733,17 +4486,18 @@ package body Instrument.Ada_Unit is declare Cond : constant Expr := As_Entry_Body (N).F_Barrier; Unit : LAL.Analysis_Unit; - begin - Set_Statement_Entry; + Save_Disable_Instrumentation : constant Boolean := + UIC.Disable_Instrumentation; + begin if not Cond.Is_Null then Unit := Cond.Unit; - Process_Decisions_Defer - (N => Cond, - T => 'G', - Do_Not_Instrument => - Entry_Guards_Restricted - (Unit.Context, Unit.Root.As_Compilation_Unit)); + UIC.Disable_Instrumentation := + Entry_Guards_Restricted + (Unit.Context, Unit.Root.As_Compilation_Unit); + Process_Expression (UIC, Cond, 'G'); + UIC.Disable_Instrumentation := + Save_Disable_Instrumentation; end if; Traverse_Subprogram_Or_Task_Body (UIC, N); @@ -4752,35 +4506,14 @@ package body Instrument.Ada_Unit is -- Protected body when Ada_Protected_Body => - Set_Statement_Entry; Traverse_Declarations_Or_Statements (UIC, L => As_Protected_Body (N).F_Decls.F_Decls); - -- 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 Ada_Exit_Stmt => - Extend_Statement_Sequence (UIC, N, 'E'); - declare - Cond : constant Expr := As_Exit_Stmt (N).F_Cond_Expr; - begin - Process_Decisions_Defer (Cond, 'E'); - Set_Statement_Entry; - end; - - -- 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 Ada_Label => - Set_Statement_Entry; - - -- Block statement, which breaks the current statement sequence + Instrument_Statement (UIC, N, 'E'); + Process_Expression (UIC, As_Exit_Stmt (N).F_Cond_Expr, 'E'); when Ada_Decl_Block | Ada_Begin_Block => - Set_Statement_Entry; if N.Kind = Ada_Decl_Block then Traverse_Declarations_Or_Statements @@ -4794,18 +4527,14 @@ package body Instrument.Ada_Unit is when Ada_Begin_Block => As_Begin_Block (N).F_Stmts, when others => raise Program_Error)); - -- If statement, which breaks the current statement sequence, - -- but we include the condition in the current sequence. - when Ada_If_Stmt => - Extend_Statement_Sequence (UIC, N, 'I'); + Instrument_Statement (UIC, N, 'I'); declare If_N : constant If_Stmt := N.As_If_Stmt; Alt : constant Elsif_Stmt_Part_List := If_N.F_Alternatives; begin - Process_Decisions_Defer (If_N.F_Cond_Expr, 'I'); - Set_Statement_Entry; + Process_Expression (UIC, If_N.F_Cond_Expr, 'I'); -- Now we traverse the statements in the THEN part @@ -4820,23 +4549,16 @@ package body Instrument.Ada_Unit is Elif : constant Elsif_Stmt_Part := Alt.Child (J).As_Elsif_Stmt_Part; begin - -- We generate a statement sequence for the construct - -- "ELSIF condition", so that we have a statement for - -- the resulting decisions. - - Extend_Statement_Sequence + Instrument_Statement (UIC, Ada_Node (Elif), 'I', - Insertion_N => Handle (Elif.F_Cond_Expr), - Instrument_Location => Inside_Expr); - Process_Decisions_Defer (Elif.F_Cond_Expr, 'I'); - Set_Statement_Entry; + Insertion_N => Handle (Elif.F_Cond_Expr)); + Process_Expression (UIC, Elif.F_Cond_Expr, 'I'); -- Traverse the statements in the ELSIF Traverse_Declarations_Or_Statements - (UIC, - L => Elif.F_Stmts.As_Ada_Node_List); + (UIC, L => Elif.F_Stmts.As_Ada_Node_List); end; end loop; @@ -4847,18 +4569,14 @@ package body Instrument.Ada_Unit is L => If_N.F_Else_Stmts.As_Ada_Node_List); end; - -- CASE statement, which breaks the current statement sequence, - -- but we include the expression in the current sequence. - when Ada_Case_Stmt => - Extend_Statement_Sequence (UIC, N, 'C'); + Instrument_Statement (UIC, N, 'C'); declare Case_N : constant Case_Stmt := N.As_Case_Stmt; Alt_L : constant Case_Stmt_Alternative_List := Case_N.F_Alternatives; begin - Process_Decisions_Defer (Case_N.F_Expr, 'X'); - Set_Statement_Entry; + Process_Expression (UIC, Case_N.F_Expr, 'X'); -- Process case branches @@ -4877,8 +4595,7 @@ package body Instrument.Ada_Unit is -- ACCEPT statement when Ada_Accept_Stmt | Ada_Accept_Stmt_With_Stmts => - Extend_Statement_Sequence (UIC, N, 'A'); - Set_Statement_Entry; + Instrument_Statement (UIC, N, 'A'); if N.Kind = Ada_Accept_Stmt_With_Stmts then -- Process sequence of statements @@ -4893,8 +4610,7 @@ package body Instrument.Ada_Unit is -- conditional_entry_call, and asynchronous_select). when Ada_Select_Stmt => - Extend_Statement_Sequence (UIC, N, 'S'); - Set_Statement_Entry; + Instrument_Statement (UIC, N, 'S'); declare Sel_N : constant Select_Stmt := As_Select_Stmt (N); @@ -4908,7 +4624,7 @@ package body Instrument.Ada_Unit is Guard := Alt.F_Cond_Expr; if not Guard.Is_Null then - Process_Decisions (UIC, Guard, 'G'); + Process_Expression (UIC, Guard, 'G'); end if; -- Traverse the select_alternative, @@ -4940,46 +4656,34 @@ package body Instrument.Ada_Unit is when Ada_Terminate_Alternative => null; - -- Unconditional exit points, which are included in the current - -- statement sequence, but then terminate it. - when Ada_Goto_Stmt | Ada_Raise_Stmt | Ada_Requeue_Stmt => - Extend_Statement_Sequence (UIC, N, ' '); - Set_Statement_Entry; + Instrument_Statement (UIC, N, ' '); -- Simple return statement. which is an exit point, but we -- have to process the return expression for decisions. when Ada_Return_Stmt => - Extend_Statement_Sequence (UIC, N, ' '); - Process_Decisions_Defer - (N.As_Return_Stmt.F_Return_Expr, 'X'); - Set_Statement_Entry; + Instrument_Statement (UIC, N, ' '); + Process_Expression + (UIC, N.As_Return_Stmt.F_Return_Expr, 'X'); -- Extended return statement when Ada_Extended_Return_Stmt => - Extend_Statement_Sequence (UIC, N, 'R'); + Instrument_Statement (UIC, N, 'R'); declare ER_N : constant Extended_Return_Stmt := N.As_Extended_Return_Stmt; begin - Process_Decisions_Defer (ER_N.F_Decl, 'X'); - Set_Statement_Entry; + Process_Expression (UIC, ER_N.F_Decl, 'X'); Traverse_Handled_Statement_Sequence - (UIC, - N => ER_N.F_Stmts); + (UIC, N => ER_N.F_Stmts); end; - -- 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. - when Ada_Base_Loop_Stmt => declare Loop_S : constant Base_Loop_Stmt := N.As_Base_Loop_Stmt; @@ -4988,16 +4692,12 @@ package body Instrument.Ada_Unit is begin if not ISC.Is_Null then - -- If iteration scheme present, extend the current - -- statement sequence to include the iteration scheme - -- and process any decisions it contains. - -- WHILE loop if ISC.Kind = Ada_While_Loop_Spec then - Extend_Statement_Sequence (UIC, N, 'W'); - Process_Decisions_Defer - (ISC.As_While_Loop_Spec.F_Expr, 'W'); + Instrument_Statement (UIC, N, 'W'); + Process_Expression + (UIC, ISC.As_While_Loop_Spec.F_Expr, 'W'); -- FOR loop @@ -5018,19 +4718,17 @@ package body Instrument.Ada_Unit is -- Still go through them to generate SCOs, for the -- sake of completeness. - Extend_Statement_Sequence (UIC, N, 'F'); - Process_Decisions_Defer - (ISC.As_For_Loop_Spec.F_Var_Decl, 'X'); - Process_Decisions_Defer - (ISC.As_For_Loop_Spec.F_Iter_Expr, 'X'); - Process_Decisions_Defer - (ISC.As_For_Loop_Spec.F_Iter_Filter, 'W'); + Instrument_Statement (UIC, N, 'F'); + Process_Expression + (UIC, ISC.As_For_Loop_Spec.F_Var_Decl, 'X'); + Process_Expression + (UIC, ISC.As_For_Loop_Spec.F_Iter_Expr, 'X'); + Process_Expression + (UIC, ISC.As_For_Loop_Spec.F_Iter_Filter, 'W'); end if; end if; - Set_Statement_Entry; - Traverse_Declarations_Or_Statements (UIC, L => Loop_S.F_Stmts.As_Ada_Node_List); @@ -5123,8 +4821,8 @@ package body Instrument.Ada_Unit is when others => 1); begin while not Is_Null (Prag_Args.Child (Index)) loop - Process_Decisions_Defer - (Prag_Arg_Expr (Index), 'P'); + Process_Expression + (UIC, Prag_Arg_Expr (Index), 'P'); Index := Index + 1; end loop; end; @@ -5142,11 +4840,11 @@ package body Instrument.Ada_Unit is -- is a P decision, any nested decision in the -- second argument is an X decision. - Process_Decisions_Defer (Prag_Arg_Expr (Arg), 'P'); + Process_Expression (UIC, Prag_Arg_Expr (Arg), 'P'); Arg := 2; end if; - Process_Decisions_Defer (Prag_Arg_Expr (Arg), 'X'); + Process_Expression (UIC, Prag_Arg_Expr (Arg), 'X'); -- Note: conservatively assume that the check policy -- for all pragmas is enabled (see comment above for @@ -5212,14 +4910,14 @@ package body Instrument.Ada_Unit is -- related pragmas: [{Static,Dynamic}_]Predicate??? when others => - Process_Decisions_Defer (N, 'X'); + Process_Expression (UIC, N, 'X'); Typ := 'P'; end case; -- Add statement SCO - Extend_Statement_Sequence (UIC, N, Typ); + Instrument_Statement (UIC, N, Typ); end; -- Object or named number declaration @@ -5229,19 +4927,13 @@ package body Instrument.Ada_Unit is when Ada_Number_Decl | Ada_Object_Decl => - Extend_Statement_Sequence (UIC, N, 'o'); - - if Has_Decision (UIC, N) then - Process_Decisions_Defer (N, 'X'); - end if; - - -- All other cases, which extend the current statement sequence - -- but do not terminate it, even if they have nested decisions. + Instrument_Statement (UIC, N, 'o'); + Process_Expression (UIC, N, 'X'); when Ada_Protected_Type_Decl | Ada_Task_Type_Decl => - Extend_Statement_Sequence (UIC, N, 't'); + Instrument_Statement (UIC, N, 't'); declare Disc_N : constant Discriminant_Part := (case N.Kind is @@ -5252,17 +4944,15 @@ package body Instrument.Ada_Unit is when others => raise Program_Error); begin - Process_Decisions_Defer (Disc_N, 'X'); + Process_Expression (UIC, Disc_N, 'X'); end; - Set_Statement_Entry; Traverse_Sync_Definition (UIC, N); when Ada_Single_Protected_Decl | Ada_Single_Task_Decl => - Extend_Statement_Sequence (UIC, N, 'o'); - Set_Statement_Entry; + Instrument_Statement (UIC, N, 'o'); Traverse_Sync_Definition (UIC, N); @@ -5274,15 +4964,13 @@ package body Instrument.Ada_Unit is | Ada_Generic_Renaming_Decl | Ada_Generic_Instantiation => - Set_Statement_Entry; Enter_Scope (UIC => UIC, Sloc => Sloc (N), Decl => N.As_Basic_Decl); - Extend_Statement_Sequence + Instrument_Statement (UIC, N, (if N.Kind in Ada_Generic_Instantiation then 'i' else 'r')); - Set_Statement_Entry; Exit_Scope (UIC); when others => @@ -5301,7 +4989,9 @@ package body Instrument.Ada_Unit is Typ := 't'; if Assertion_Coverage_Enabled then Process_Contract - (N.As_Concrete_Type_Decl, "Type_Invariant"); + (UIC, + N.As_Concrete_Type_Decl, + "Type_Invariant"); end if; end if; @@ -5332,6 +5022,7 @@ package body Instrument.Ada_Unit is | Ada_Task_Body_Stub | Ada_Use_Package_Clause | Ada_Use_Type_Clause + | Ada_Label => Typ := ASCII.NUL; @@ -5344,15 +5035,13 @@ package body Instrument.Ada_Unit is end case; if Typ /= ASCII.NUL then - Extend_Statement_Sequence (UIC, N, Typ); + Instrument_Statement (UIC, N, Typ); end if; end; -- Process any embedded decisions - if Has_Decision (UIC, N) then - Process_Decisions_Defer (N, 'X'); - end if; + Process_Expression (UIC, N, 'X'); end case; end Traverse_One; @@ -5426,12 +5115,6 @@ package body Instrument.Ada_Unit is end; end loop; - -- End sequence of statements and flush deferred decisions - - if not P.Is_Null or else Items_Count > 0 then - Set_Statement_Entry; - end if; - -- Pop insertion info UIC.Current_Insertion_Info := Saved_Insertion_Info; @@ -5550,7 +5233,7 @@ package body Instrument.Ada_Unit is Preelab : Boolean) is begin - Process_Decisions (UIC, N.F_Formal_Part, 'X'); + Process_Expression (UIC, N.F_Formal_Part, 'X'); Traverse_Package_Declaration (UIC, N.F_Package_Decl.As_Base_Package_Decl, Preelab); end Traverse_Generic_Package_Declaration; @@ -5783,9 +5466,6 @@ package body Instrument.Ada_Unit is Decl => Decl); end; - Local_Inserter.Local_Decls := Handle (Decls.F_Decls); - UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; - -- If assertion coverage is enabled, process the decisions in the -- contracts. This is needed in the case of a subprogram body with -- aspect with no prior declaration. @@ -5797,19 +5477,19 @@ package body Instrument.Ada_Unit is Has_Elt : Boolean := Assocs.Aspect_Assoc_List_Has_Element (Idx); begin while Has_Elt loop - -- Defer the treatment of this decision - SD.Append - ((As_Ada_Node + Process_Expression + (UIC, + As_Ada_Node (Assocs.Aspect_Assoc_List_Element (Idx).F_Expr), - 'A', - False)); - + 'A'); Idx := Idx + 1; Has_Elt := Assocs.Aspect_Assoc_List_Has_Element (Idx); end loop; end; end if; + Local_Inserter.Local_Decls := Handle (Decls.F_Decls); + UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; Traverse_Declarations_Or_Statements (UIC, L => Decls.F_Decls); Traverse_Handled_Statement_Sequence (UIC, N => HSS); @@ -5821,246 +5501,301 @@ package body Instrument.Ada_Unit is UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; end Traverse_Subprogram_Or_Task_Body; - ----------------------- - -- Process_Decisions -- - ----------------------- + ------------------------ + -- Process_Expression -- + ------------------------ - procedure Process_Decisions - (UIC : in out Ada_Unit_Inst_Context; - N : Ada_Node'Class; - T : Character; - Do_Not_Instrument : Boolean := False) + procedure Process_Expression + (UIC : in out Ada_Unit_Inst_Context; + N : Ada_Node'Class; + T : Character) is - Mark : Nat; - -- This is used to mark the location of a decision sequence in the SCO - -- table. We use it for backing out a simple decision in an expression - -- context that contains only NOT operators. + function Process_Decl_Expr (N : Ada_Node'Class) return Visit_Status; + -- Helper to Libadalang's Traverse. Only operates on Decl_Exprs, + -- instrument each declaration as a statement and process the nested + -- expressions. - Mark_Hash : Nat; - -- Likewise for the putative SCO_Raw_Hash_Table entries: see below + procedure Process_Decisions + (UIC : in out Ada_Unit_Inst_Context; + N : Ada_Node'Class; + T : Character); - type Hash_Entry is record - Sloc : Source_Location; - SCO_Index : Nat; - end record; - -- We must register all conditions/pragmas in SCO_Raw_Hash_Table. - -- However we cannot register them in the same time we are adding the - -- corresponding SCO entries to the raw table since we may discard them - -- later on. So instead we put all putative conditions into Hash_Entries - -- (see below) and register them once we are sure we keep them. - -- - -- This data structure holds the conditions/pragmas to register in - -- SCO_Raw_Hash_Table. - - package Hash_Entries is new Table.Table - (Table_Component_Type => Hash_Entry, - Table_Index_Type => Nat, - Table_Low_Bound => 1, - Table_Initial => 10, - Table_Increment => 10, - Table_Name => "Hash_Entries"); - -- Hold temporarily (i.e. free'd before returning) the Hash_Entry before - -- they are registered in SCO_Raw_Hash_Table. + ----------------------- + -- Process_Decl_Expr -- + ----------------------- - --------------------------------- - -- Decision-specific variables -- - --------------------------------- + function Process_Decl_Expr (N : Ada_Node'Class) return Visit_Status is + begin + if N.Kind in Ada_Decl_Expr then + declare + Saved_Inserter : constant Any_MCDC_State_Inserter := + UIC.MCDC_State_Inserter; + Saved_In_Decl_Expr : constant Boolean := UIC.In_Decl_Expr; + Local_Inserter : aliased Default_MCDC_State_Inserter := + (Local_Decls => Handle (N.As_Decl_Expr.F_Decls)); + begin + UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; + UIC.In_Decl_Expr := True; - -- The following variables are related to the current decision being - -- processed by this call to Process_Decisions. Note that in the case - -- of nested decisions, this subprogram recurses, so we do not have to - -- worry about overwriting them. - - Current_Decision : Nat; - -- Low level SCO id of current decision - - X_Not_Decision : Boolean; - -- This flag keeps track of whether a decision sequence in the SCO table - -- contains only NOT operators, and is for an expression context (T=X). - -- The flag will be set False if T is other than X, or if an operator - -- other than NOT is in the sequence. - - Condition_Count : Natural := 0; - -- Count of conditions for current decision (MC/DC only) - - Conditions_State : Unbounded_String; - -- Name of MC/DC and ATCC state local variable for current decision - -- (MC/DC and ATCC only). - - procedure Output_Decision_Operand - (Operand : Expr; - Decision_Static : Boolean); - -- The node Operand is the top level logical operator of a decision, or - -- it is one of the operands of a logical operator belonging to a single - -- complex decision. This (recursive) routine outputs the sequence of - -- table entries corresponding to the node. Note that we do not process - -- the sub- operands to look for further decisions, that processing is - -- done in Find_Nested_Decisions, because we can't get decisions mixed - -- up in the global table. Call has no effect if Operand is Empty. - -- Increments Condition_Count (recursively) for each condition. - -- - -- Decision_Static indicates whether the expression of the whole - -- decision is static, and should thus not be instrumented. - - procedure Output_Element (N : Ada_Node); - -- Node N is an operand of a logical operator that is not itself a - -- logical operator, or it is a simple decision. This routine outputs - -- the table entry for the element, with C1 set to ' '. Last is set - -- False, and an entry is made in the condition hash table. - - procedure Output_Header (T : Character; N : Ada_Node'Class); - -- Outputs a decision header node. T is I/W/E/P/G/a or A for IF/WHILE/ - -- EXIT WHEN/PRAGMA/ENTRY GUARD/ASPECT, and 'X' for the expression case. - -- Resets Condition_Count to 0, and initializes MCDC_State. - - procedure Find_Nested_Decisions (Operand : Expr); - -- This is called on node Operand, the top level node of a decision, - -- or on one of its operands or suboperands after generating the full - -- output for the complex decision. It process the suboperands of the - -- decision looking for nested decisions. + -- Traverse_Declarations_Or_Statements will instrument the + -- declarations as statements, as well as instrument the + -- nested decisions within those declarations. - function Process_Node (N : Ada_Node'Class) return Visit_Status; - -- Processes one node in the traversal, looking for logical operators, - -- and if one is found, outputs the appropriate table entries. + Traverse_Declarations_Or_Statements + (UIC, N.As_Decl_Expr.F_Decls); + UIC.MCDC_State_Inserter := Saved_Inserter; + UIC.In_Decl_Expr := Saved_In_Decl_Expr; + + return Over; + end; + else + return Into; + end if; + end Process_Decl_Expr; - ----------------------------- - -- Output_Decision_Operand -- - ----------------------------- + ----------------------- + -- Process_Decisions -- + ----------------------- - procedure Output_Decision_Operand - (Operand : Expr; Decision_Static : Boolean) + procedure Process_Decisions + (UIC : in out Ada_Unit_Inst_Context; + N : Ada_Node'Class; + T : Character) is - C1 : Character; - C2 : Character; - -- C1 holds a character that identifies the operation while C2 - -- indicates whether we are sure (' ') or not ('?') this operation - -- belongs to the decision. '?' entries will be filtered out in the - -- second (SCO_Record_Filtered) pass. + Mark : Nat; + -- This is used to mark the location of a decision sequence in the + -- SCO table. We use it for backing out a simple decision in an + -- expression context that contains only NOT operators. + + Mark_Hash : Nat; + -- Likewise for the putative SCO_Raw_Hash_Table entries: see below + + type Hash_Entry is record + Sloc : Source_Location; + SCO_Index : Nat; + end record; + -- We must register all conditions/pragmas in SCO_Raw_Hash_Table. + -- However we cannot register them in the same time we are adding the + -- corresponding SCO entries to the raw table since we may discard + -- them later on. So instead we put all putative conditions into + -- Hash_Entries (see below) and register them once we are sure we + -- keep them. + -- + -- This data structure holds the conditions/pragmas to register in + -- SCO_Raw_Hash_Table. + + package Hash_Entries is new Table.Table + (Table_Component_Type => Hash_Entry, + Table_Index_Type => Nat, + Table_Low_Bound => 1, + Table_Initial => 10, + Table_Increment => 10, + Table_Name => "Hash_Entries"); + -- Hold temporarily (i.e. free'd before returning) the Hash_Entry + -- before they are registered in SCO_Raw_Hash_Table. + + --------------------------------- + -- Decision-specific variables -- + --------------------------------- + + -- The following variables are related to the current decision being + -- processed by this call to Process_Decisions. Note that in the case + -- of nested decisions, this subprogram recurses, so we do not have + -- to worry about overwriting them. + + Current_Decision : Nat; + -- Low level SCO id of current decision + + X_Not_Decision : Boolean; + -- This flag keeps track of whether a decision sequence in the + -- SCO table contains only NOT operators, and is for an expression + -- context (T=X). The flag will be set False if T is other than X, + -- or if an operator other than NOT is in the sequence. + + Condition_Count : Natural := 0; + -- Count of conditions for current decision (MC/DC only) + + Conditions_State : Unbounded_String; + -- Name of MC/DC and ATCC state local variable for current + -- decision (MC/DC and ATCC only). + + procedure Output_Decision_Operand + (Operand : Expr; + Decision_Static : Boolean); + -- The node Operand is the top level logical operator of a decision, + -- or it is one of the operands of a logical operator belonging to + -- a single complex decision. This (recursive) routine outputs the + -- sequence of table entries corresponding to the node. Note that we + -- do not process the sub- operands to look for further decisions, + -- that processing is done in Find_Nested_Decisions, because we can't + -- get decisions mixed up in the global table. Call has no effect + -- if Operand is Empty. Increments Condition_Count (recursively) + -- for each condition. + -- + -- Decision_Static indicates whether the expression of the whole + -- decision is static, and should thus not be instrumented. + + procedure Output_Element (N : Ada_Node); + -- Node N is an operand of a logical operator that is not itself a + -- logical operator, or it is a simple decision. This routine outputs + -- the table entry for the element, with C1 set to ' '. Last is set + -- False, and an entry is made in the condition hash table. + + procedure Output_Header (T : Character; N : Ada_Node'Class); + -- Outputs a decision header node. T is I/W/E/P for IF/WHILE/EXIT + -- WHEN/ PRAGMA, and 'X' for the expression case. Resets + -- Condition_Count to 0, and initializes Conditions_State. + + procedure Find_Nested_Decisions (Operand : Expr); + -- This is called on node Operand, the top level node of a decision, + -- or on one of its operands or suboperands after generating the full + -- output for the complex decision. It process the suboperands of the + -- decision looking for nested decisions. + + function Process_Node (N : Ada_Node'Class) return Visit_Status; + -- Processes one node in the traversal, looking for logical + -- operators, and if one is found, outputs the appropriate + -- table entries. + + ----------------------------- + -- Output_Decision_Operand -- + ----------------------------- + + procedure Output_Decision_Operand + (Operand : Expr; Decision_Static : Boolean) + is + C1 : Character; + C2 : Character; + -- C1 holds a character that identifies the operation while C2 + -- indicates whether we are sure (' ') or not ('?') this operation + -- belongs to the decision. '?' entries will be filtered out in + -- the second (SCO_Record_Filtered) pass. - N : constant Expr := Unwrap (Operand); + N : constant Expr := Unwrap (Operand); - L, R : Expr; + L, R : Expr; - Op_N : Op; - Op_NK : Ada_Node_Kind_Type; + Op_N : Op; + Op_NK : Ada_Node_Kind_Type; - begin - -- Logical operator + begin + -- Logical operator - if Is_Logical_Operator (UIC, N) then - Op_N := Operator (N); - Op_NK := Op_N.Kind; + if Is_Logical_Operator (UIC, N) then + Op_N := Operator (N); + Op_NK := Op_N.Kind; - if Op_NK = Ada_Op_Not then - C1 := '!'; - L := No_Expr; - R := N.As_Un_Op.F_Expr; + if Op_NK = Ada_Op_Not then + C1 := '!'; + L := No_Expr; + R := N.As_Un_Op.F_Expr; - else - declare - BN : constant Bin_Op := N.As_Bin_Op; - begin - L := BN.F_Left; - R := BN.F_Right; - if Op_NK in Ada_Op_Or | Ada_Op_Or_Else then - C1 := '|'; - else pragma Assert (Op_NK in Ada_Op_And | Ada_Op_And_Then); - C1 := '&'; - end if; - end; - end if; + else + declare + BN : constant Bin_Op := N.As_Bin_Op; + begin + L := BN.F_Left; + R := BN.F_Right; + if Op_NK in Ada_Op_Or | Ada_Op_Or_Else then + C1 := '|'; + else + pragma Assert (Op_NK in Ada_Op_And | Ada_Op_And_Then); + C1 := '&'; + end if; + end; + end if; - C2 := ' '; - Append_SCO - (C1 => C1, - C2 => C2, - From => +Sloc (Op_N), - To => Slocs.No_Local_Location, - SFI => UIC.SFI, - Last => False); + C2 := ' '; + Append_SCO + (C1 => C1, + C2 => C2, + From => +Sloc (Op_N), + To => Slocs.No_Local_Location, + SFI => UIC.SFI, + Last => False); - Hash_Entries.Append ((Sloc (N), SCOs.SCO_Table.Last)); + Hash_Entries.Append ((Sloc (N), SCOs.SCO_Table.Last)); - if not L.Is_Null then - Output_Decision_Operand (L, Decision_Static); - end if; - Output_Decision_Operand (R, Decision_Static); + if not L.Is_Null then + Output_Decision_Operand (L, Decision_Static); + end if; + Output_Decision_Operand (R, Decision_Static); - -- Not a logical operator -> condition + -- Not a logical operator -> condition - else - Output_Element (N.As_Ada_Node); + else + Output_Element (N.As_Ada_Node); - if Decision_Static or else Do_Not_Instrument then - return; + if Decision_Static or else UIC.Disable_Instrumentation then + return; + end if; + if MCDC_Coverage_Enabled + or else Assertion_Condition_Coverage_Enabled + then + UIC.Source_Conditions.Append + (Source_Condition' + (LL_SCO => SCOs.SCO_Table.Last, + Condition => N.As_Expr, + State => Conditions_State, + First => Condition_Count = 0)); + + Condition_Count := Condition_Count + 1; + end if; end if; + end Output_Decision_Operand; - if MCDC_Coverage_Enabled - or else Assertion_Condition_Coverage_Enabled - then - UIC.Source_Conditions.Append - (Source_Condition' - (LL_SCO => SCOs.SCO_Table.Last, - Condition => N.As_Expr, - State => Conditions_State, - First => Condition_Count = 0)); - - Condition_Count := Condition_Count + 1; - end if; - end if; - end Output_Decision_Operand; + -------------------- + -- Output_Element -- + -------------------- - -------------------- - -- Output_Element -- - -------------------- + procedure Output_Element (N : Ada_Node) is + N_SR : constant Source_Location_Range := N.Sloc_Range; + C2 : Character := 'c'; + begin + if Is_Static_Expr (N.As_Expr) then - procedure Output_Element (N : Ada_Node) is - N_SR : constant Source_Location_Range := N.Sloc_Range; - C2 : Character := 'c'; - begin - if Is_Static_Expr (N.As_Expr) then + -- This condition is static: record its value in the SCO - -- This condition is static: record its value in the SCO + declare + Eval : constant String := Bool_Expr_Eval (N.As_Expr); + begin + if Eval = "True" then + C2 := 't'; + elsif Eval = "False" then + C2 := 'f'; + end if; + end; + end if; - declare - Eval : constant String := Bool_Expr_Eval (N.As_Expr); - begin - if Eval = "True" then - C2 := 't'; - elsif Eval = "False" then - C2 := 'f'; - end if; - end; - end if; + Append_SCO + (C1 => ' ', + C2 => C2, + From => +Start_Sloc (N_SR), + To => +Inclusive_End_Sloc (N_SR), + SFI => UIC.SFI, + Last => False); + Hash_Entries.Append ((Start_Sloc (N_SR), SCOs.SCO_Table.Last)); + if UIC.Disable_Instrumentation then + UIC.Non_Instr_LL_SCOs.Include (SCO_Id (SCOs.SCO_Table.Last)); + end if; + end Output_Element; - Append_SCO - (C1 => ' ', - C2 => C2, - From => +Start_Sloc (N_SR), - To => +Inclusive_End_Sloc (N_SR), - SFI => UIC.SFI, - Last => False); - Hash_Entries.Append ((Start_Sloc (N_SR), SCOs.SCO_Table.Last)); - if Do_Not_Instrument then - UIC.Non_Instr_LL_SCOs.Include (SCO_Id (SCOs.SCO_Table.Last)); - end if; - end Output_Element; + ------------------- + -- Output_Header -- + ------------------- - ------------------- - -- Output_Header -- - ------------------- + procedure Output_Header (T : Character; N : Ada_Node'Class) is + Loc : Source_Location := No_Source_Location; + -- Node whose Sloc is used for the decision - procedure Output_Header (T : Character; N : Ada_Node'Class) is - Loc : Source_Location := No_Source_Location; - -- Node whose Sloc is used for the decision + Nam : Name_Id := Namet.No_Name; + -- For the case of an aspect, aspect name - Nam : Name_Id := Namet.No_Name; - -- For the case of an aspect, aspect name + Is_Contract : constant Boolean := T in 'a' | 'A' | 'P'; + -- Is the decision that of a contract - Is_Contract : constant Boolean := T in 'a' | 'A' | 'P'; - -- Is the decision that of a contract - begin - case T is + begin + case T is when 'I' | 'E' | 'W' | 'a' | 'A' => -- For IF, EXIT, WHILE, or aspects, the token SLOC is that of @@ -6113,201 +5848,199 @@ package body Instrument.Ada_Unit is null; - -- No other possibilities + -- No other possibilities when others => raise Program_Error; - end case; + end case; - Append_SCO - (C1 => T, - C2 => ' ', - From => +Loc, - To => Slocs.No_Local_Location, - SFI => UIC.SFI, - Last => False, - Pragma_Aspect_Name => Nam); - if Do_Not_Instrument then - UIC.Non_Instr_LL_SCOs.Include (SCO_Id (SCOs.SCO_Table.Last)); - end if; + Append_SCO + (C1 => T, + C2 => ' ', + From => +Loc, + To => Slocs.No_Local_Location, + SFI => UIC.SFI, + Last => False, + Pragma_Aspect_Name => Nam); + if UIC.Disable_Instrumentation then + UIC.Non_Instr_LL_SCOs.Include (SCO_Id (SCOs.SCO_Table.Last)); + end if; - Current_Decision := SCOs.SCO_Table.Last; + Current_Decision := SCOs.SCO_Table.Last; - if Coverage.Enabled (Decision) - or else MCDC_Coverage_Enabled - or else Assertion_Condition_Coverage_Enabled - then - - if MCDC_Coverage_Enabled - or else (Is_Contract - and then Assertion_Condition_Coverage_Enabled) + if Coverage.Enabled (Decision) + or else MCDC_Coverage_Enabled + or else Assertion_Condition_Coverage_Enabled then - Condition_Count := 0; + if MCDC_Coverage_Enabled + or else (Is_Contract + and then Assertion_Condition_Coverage_Enabled) + then + Condition_Count := 0; - if UIC.MCDC_State_Inserter = null then - Report (UIC, N, - "gnatcov limitation: " - & "cannot find local declarative part for MC/DC", - Kind => Diagnostics.Error); - else - Conditions_State := To_Unbounded_String - (UIC.MCDC_State_Inserter.Insert_MCDC_State - (UIC, Make_MCDC_State_Name (SCOs.SCO_Table.Last))); + if UIC.MCDC_State_Inserter = null then + Report (UIC, N, + "gnatcov limitation: " + & "cannot find local declarative part for MC/DC", + Kind => Diagnostics.Error); + else + Conditions_State := To_Unbounded_String + (UIC.MCDC_State_Inserter.Insert_MCDC_State + (UIC, Make_MCDC_State_Name (SCOs.SCO_Table.Last))); + end if; end if; - end if; - -- Do not instrument this decision if we have already determined - -- from the context that instrumenting it could produce invalid - -- code. - -- - -- Instrumenting static decisions would make them non-static by - -- wrapping them in a Witness call. This transformation would - -- trigger legality checks on the originally non-evaluated branch, - -- which could result in compilation errors specific to the - -- instrumented code, e.g. on: - -- - -- X := (if - -- then - -- else ); - -- - -- For this reason, also refrain from instrumenting static - -- decisions. + -- Do not instrument this decision if we have already + -- determined from the context that instrumenting it + -- could produce invalid code. + -- + -- Instrumenting static decisions would make them non-static by + -- wrapping them in a Witness call. This transformation would + -- trigger legality checks on the originally non-evaluated + -- branch, which could result in compilation errors specific + -- to the instrumented code, e.g. on: + -- + -- X := (if + -- then + -- else ); + -- + -- For this reason, also refrain from instrumenting static + -- decisions. - if not (Do_Not_Instrument - or else Is_Static_Expr (N.As_Expr)) - then - UIC.Source_Decisions.Append - (Source_Decision' - (LL_SCO => Current_Decision, - Decision => N.As_Expr, - State => Conditions_State, - Do_Not_Instrument => - Do_Not_Instrument or else Is_Static_Expr (N.As_Expr), - Is_Contract => Is_Contract)); + if not (UIC.Disable_Instrumentation + or else Is_Static_Expr (N.As_Expr)) + then + UIC.Source_Decisions.Append + (Source_Decision' + (LL_SCO => Current_Decision, + Decision => N.As_Expr, + State => Conditions_State, + Is_Contract => Is_Contract)); + end if; end if; - end if; - -- For an aspect specification, which will be rewritten into a - -- pragma, enter a hash table entry now. + -- For an aspect specification, which will be rewritten into a + -- pragma, enter a hash table entry now. - if T in 'a' | 'A' then - Hash_Entries.Append ((Loc, Current_Decision)); - end if; + if T in 'a' | 'A' then + Hash_Entries.Append ((Loc, Current_Decision)); + end if; - end Output_Header; + end Output_Header; - --------------------------- - -- Find_Nested_Decisions -- - --------------------------- + --------------------------- + -- Find_Nested_Decisions -- + --------------------------- - procedure Find_Nested_Decisions (Operand : Expr) is - N : constant Expr := Unwrap (Operand); - begin - if Is_Logical_Operator (UIC, N) then - if N.Kind = Ada_Un_Op then - Find_Nested_Decisions (N.As_Un_Op.F_Expr); + procedure Find_Nested_Decisions (Operand : Expr) is + N : constant Expr := Unwrap (Operand); + begin + if Is_Logical_Operator (UIC, N) then + if N.Kind = Ada_Un_Op then + Find_Nested_Decisions (N.As_Un_Op.F_Expr); + + else + Find_Nested_Decisions (N.As_Bin_Op.F_Left); + Find_Nested_Decisions (N.As_Bin_Op.F_Right); + X_Not_Decision := False; + end if; else - Find_Nested_Decisions (N.As_Bin_Op.F_Left); - Find_Nested_Decisions (N.As_Bin_Op.F_Right); - X_Not_Decision := False; + Process_Decisions (UIC, N, 'X'); end if; + end Find_Nested_Decisions; - else - Process_Decisions (UIC, N, 'X', Do_Not_Instrument); - end if; - end Find_Nested_Decisions; - - ------------------ - -- Process_Node -- - ------------------ + ------------------ + -- Process_Node -- + ------------------ - function Process_Node (N : Ada_Node'Class) return Visit_Status is - -- Test for the two cases where N is the root node of some decision: + function Process_Node (N : Ada_Node'Class) return Visit_Status is + -- Test for the two cases where N is the root node of some + -- decision: - Decision_Root : constant Boolean := + Decision_Root : constant Boolean := - -- Simple decision at outer level: a boolean expression (which is - -- not a logical operator or short circuit form) appearing as the - -- operand of an IF, WHILE, EXIT WHEN, or special PRAGMA construct. + -- Simple decision at outer level: a boolean expression (which + -- is not a logical operator or short circuit form) appearing + -- as the operand of an IF, WHILE, EXIT WHEN, or special PRAGMA + -- construct. - (N = Process_Decisions.N and then T /= 'X') - or else + (N = Process_Decisions.N and then T /= 'X') + or else - -- Complex decision, whether at outer level or nested: a boolean - -- expression involving a logical operator. + -- Complex decision, whether at outer level or nested: a boolean + -- expression involving a logical operator. - (N.Kind in Ada_Expr - and then Is_Complex_Decision (UIC, N.As_Expr)); + (N.Kind in Ada_Expr + and then Is_Complex_Decision (UIC, N.As_Expr)); - begin - if Decision_Root then - declare - EN : constant Expr := N.As_Expr; - T : Character; - - begin - -- If outer level, then type comes from call, otherwise it - -- is more deeply nested and counts as X for expression. + begin + if Decision_Root then + declare + EN : constant Expr := N.As_Expr; + T : Character; - if N = Process_Decisions.N then - T := Process_Decisions.T; - else - T := 'X'; - end if; + begin + -- If outer level, then type comes from call, otherwise it + -- is more deeply nested and counts as X for expression. - -- Output header for sequence + if N = Process_Decisions.N then + T := Process_Decisions.T; + else + T := 'X'; + end if; - X_Not_Decision := T = 'X' and then N.Kind = Ada_Op_Not; - Mark := SCOs.SCO_Table.Last; - Mark_Hash := Hash_Entries.Last; - Output_Header (T, N); + -- Output header for sequence - -- Output the decision (recursively traversing operands) + X_Not_Decision := T = 'X' and then N.Kind = Ada_Op_Not; + Mark := SCOs.SCO_Table.Last; + Mark_Hash := Hash_Entries.Last; + Output_Header (T, N); - Output_Decision_Operand - (EN, Is_Static_Expr (N.As_Expr)); + -- Output the decision (recursively traversing operands) - -- If the decision was in an expression context (T = 'X') - -- and contained only NOT operators, then we don't output - -- it, so delete the associated SCO entries. As a consequence, - -- no instrumentation will be emitted. + Output_Decision_Operand + (EN, Is_Static_Expr (N.As_Expr)); - if X_Not_Decision then - SCOs.SCO_Table.Set_Last (Mark); - Hash_Entries.Set_Last (Mark_Hash); + -- If the decision was in an expression context (T = + -- 'X') and contained only NOT operators, then we don't + -- output it, so delete the associated SCO entries. As a + -- consequence, no instrumentation will be emitted. - -- Otherwise, set Last in last table entry to mark end + if X_Not_Decision then + SCOs.SCO_Table.Set_Last (Mark); + Hash_Entries.Set_Last (Mark_Hash); - else - SCOs.SCO_Table.Table (SCOs.SCO_Table.Last).Last := True; - end if; + -- Otherwise, set Last in last table entry to mark end - -- Process any embedded decisions. - -- For the sake of simplicity the coverage of nested decisions - -- in contract decisions should not be checked. Therefore they - -- should be instrumented. + else + SCOs.SCO_Table.Table (SCOs.SCO_Table.Last).Last := True; + end if; - if T /= 'P' then - Find_Nested_Decisions (EN); - end if; + -- Process any embedded decisions. For the sake of simplicity + -- the coverage of nested decisions in contract decisions + -- should not be checked. Therefore they should be + -- instrumented. - return Over; - end; - end if; + if T /= 'P' then + Find_Nested_Decisions (EN); + end if; + return Over; + end; + end if; - -- Here for cases that are known to not be logical operators + -- Here for cases that are known to not be logical operators - case N.Kind is - -- CASE expression + case N.Kind is + -- CASE expression - -- Really hard to believe this is correct given the special - -- handling for if expressions below ??? + -- Really hard to believe this is correct given the special + -- handling for if expressions below ??? when Ada_Case_Expr => return Into; -- ??? - -- IF expression: processed like an if statement + -- IF expression: processed like an if statement when Ada_If_Expr => declare @@ -6315,51 +6048,36 @@ package body Instrument.Ada_Unit is Alt : constant Elsif_Expr_Part_List := IEN.F_Alternatives; begin - Process_Decisions - (UIC, IEN.F_Cond_Expr, 'I', Do_Not_Instrument); - Process_Decisions - (UIC, IEN.F_Then_Expr, 'X', Do_Not_Instrument); + Process_Decisions (UIC, IEN.F_Cond_Expr, 'I'); + Process_Decisions (UIC, IEN.F_Then_Expr, 'X'); for J in 1 .. Alt.Children_Count loop declare EIN : constant Elsif_Expr_Part := Alt.Child (J).As_Elsif_Expr_Part; begin - Process_Decisions - (UIC, EIN.F_Cond_Expr, 'I', Do_Not_Instrument); - Process_Decisions - (UIC, EIN.F_Then_Expr, 'X', Do_Not_Instrument); + Process_Decisions (UIC, EIN.F_Cond_Expr, 'I'); + Process_Decisions (UIC, EIN.F_Then_Expr, 'X'); end; end loop; - Process_Decisions - (UIC, IEN.F_Else_Expr, 'X', Do_Not_Instrument); + Process_Decisions (UIC, IEN.F_Else_Expr, 'X'); return Over; end; when Ada_Quantified_Expr => Process_Decisions - (UIC, - N.As_Quantified_Expr.F_Loop_Spec, - 'X', - Do_Not_Instrument); - Process_Decisions - (UIC, N.As_Quantified_Expr.F_Expr, 'W', Do_Not_Instrument); + (UIC, N.As_Quantified_Expr.F_Loop_Spec, 'X'); + Process_Decisions (UIC, N.As_Quantified_Expr.F_Expr, 'W'); return Over; when Ada_For_Loop_Spec => - Process_Decisions - (UIC, N.As_For_Loop_Spec.F_Var_Decl, 'X', Do_Not_Instrument); - Process_Decisions - (UIC, N.As_For_Loop_Spec.F_Iter_Expr, 'X', Do_Not_Instrument); - Process_Decisions - (UIC, - N.As_For_Loop_Spec.F_Iter_Filter, - 'W', - Do_Not_Instrument); + Process_Decisions (UIC, N.As_For_Loop_Spec.F_Var_Decl, 'X'); + Process_Decisions (UIC, N.As_For_Loop_Spec.F_Iter_Expr, 'X'); + Process_Decisions (UIC, N.As_For_Loop_Spec.F_Iter_Filter, 'W'); return Over; - -- Aspects for which we don't want to instrument the decision + -- Aspects for which we don't want to instrument the decision when Ada_Aspect_Assoc => declare @@ -6380,80 +6098,39 @@ package body Instrument.Ada_Unit is return Into; end; - -- Declare expressions: do not process the nested decisions in the - -- declarations, as those will be processed when instrumenting - -- them, but do process the final expression. + -- Declare expressions: do not process the nested decisions + -- in the declarations, as those will be processed when + -- instrumenting them, but do process the final expression. when Ada_Decl_Expr => - Process_Decisions - (UIC, N.As_Decl_Expr.F_Expr, 'X', Do_Not_Instrument); + Process_Decisions (UIC, N.As_Decl_Expr.F_Expr, 'X'); return Over; - -- All other cases, continue scan + -- All other cases, continue scan when others => return Into; - end case; - end Process_Node; - - -- Start of processing for Process_Decisions - - begin - if N.Is_Null then - return; - end if; - Hash_Entries.Init; - N.Traverse (Process_Node'Access); - Hash_Entries.Free; - end Process_Decisions; - - ------------------ - -- Has_Decision -- - ------------------ - - function Has_Decision - (UIC : Ada_Unit_Inst_Context; T : Ada_Node'Class) return Boolean - is - function Visit (N : Ada_Node'Class) return Visit_Status; - -- If N's kind indicates the presence of a decision, return Stop, - -- otherwise return Into. - -- - -- We know have a decision as soon as we have a logical operator (by - -- definition), an IF-expression (its condition is a decision), a - -- quantified expression or an iterator filter in a For_Loop_Spec. - -- - -- Do not recurse into the declarations of declare expressions as those - -- are handled separately. + end case; + end Process_Node; - ----------- - -- Visit -- - ----------- + -- Start of processing for Process_Decisions - function Visit (N : Ada_Node'Class) return Visit_Status is begin - if N.Kind in Ada_Decl_List_Range - and then N.Parent /= No_Ada_Node - and then N.Parent.Kind in Ada_Decl_Expr - then - return Over; - elsif N.Kind in Ada_Expr - and then - (Is_Complex_Decision (UIC, N.As_Expr) - or else N.Kind in Ada_If_Expr | Ada_Quantified_Expr_Range - or else (N.Kind in Ada_For_Loop_Spec_Range - and then not N.As_For_Loop_Spec.F_Iter_Filter.Is_Null)) - then - return Stop; - else - return Into; + if N.Is_Null then + return; end if; - end Visit; - - -- Start of processing for Has_Decision + Hash_Entries.Init; + N.Traverse (Process_Node'Access); + Hash_Entries.Free; + end Process_Decisions; begin - return T.Traverse (Visit'Access) = Stop; - end Has_Decision; + if N.Is_Null then + return; + end if; + Process_Decisions (UIC, N, T); + N.Traverse (Process_Decl_Expr'Access); + end Process_Expression; ------------------------- -- Is_Logical_Operator -- @@ -8551,9 +8228,7 @@ package body Instrument.Ada_Unit is or else (SD.Is_Contract and then Assertion_Coverage_Enabled)); begin - if SD.Do_Not_Instrument then - Set_Decision_SCO_Non_Instr (HL_SCO); - elsif Should_Instrument then + if Should_Instrument then Insert_Decision_Witness (UIC, SD, Path_Count (HL_SCO)); end if; end; diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 20f343bbe..9465f8474 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -199,10 +199,6 @@ private State : Ada.Strings.Unbounded.Unbounded_String; -- Name of MC/DC state local variable - Do_Not_Instrument : Boolean; - -- Whether this decision should not be instrumented. This is set to True - -- when instrumenting the decision could create invalid Ada code. - Is_Contract : Boolean := False; -- Whether the decision belongs to an assert-like pragma statement or an -- equivalent aspect. diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 2e6dbfcc7..a50fb5bc9 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -379,14 +379,11 @@ package Instrument.C is Current_File_Scope : Scopes_In_Files_Map.Cursor; -- Source file in which the last scope encountered was opened - Disable_Instrumentation : Boolean := False; - -- Set to True to deactivate instrumentation and prevent any code - -- rewriting. - Instrumented_CXX_For_Ranges : Cursor_Vectors.Vector; -- List of instrumented for ranges. For an explanation of why we need -- to store these, see the documentation of the Fix_CXX_For_Ranges -- subprogram. + end record; type C_Source_Rewriter is tagged limited private; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index e618965d4..336f8b249 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -337,6 +337,10 @@ package Instrument.Common is -- ALI_Files.ALI_Annotations afterwards, when the compilation unit -- (SC_Obligations.CU_Info) for this annotation is ready. + Disable_Instrumentation : Boolean := False; + -- Set to True to deactivate instrumentation and prevent any code + -- rewriting. + Non_Instr_LL_SCOs : SCO_Sets.Set; -- Set of low level SCO ids that were not instrumented end record; From c609cef03a474d59de7e32f0f7248db355f91797 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 13 Sep 2023 11:02:45 +0200 Subject: [PATCH 0447/1483] Refactor instrumentation of pragmas Fix various wrong comments + make sure we are instrumenting the statement SCO before instrumenting any nested decision. --- tools/gnatcov/instrument-ada_unit.adb | 47 +++++++-------------------- 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index c2853121a..9b3120ecf 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -4745,7 +4745,6 @@ package body Instrument.Ada_Unit is Prag_Args : constant Base_Assoc_List := Prag_N.F_Args; Nam : constant Name_Id := Pragma_Name (Prag_N); Arg : Positive := 1; - Typ : Character; function Prag_Arg_Expr (Index : Positive) return Expr is (Prag_Args.Child (Index).As_Pragma_Argument_Assoc.F_Expr); @@ -4758,7 +4757,7 @@ package body Instrument.Ada_Unit is | Name_Precondition | Name_Postcondition => - Typ := 'p'; + Instrument_Statement (UIC, N, 'p'); if Assertion_Coverage_Enabled then declare @@ -4789,20 +4788,6 @@ package body Instrument.Ada_Unit is | Name_Check | Name_Loop_Invariant => - -- For Assert-like pragmas, we insert a statement - -- witness and instrument the decision if the pragma - -- is not disabled. - -- - -- This is in line with what is done for pre/post - -- aspects. - - if Nam = Name_Check then - - -- Skip check name - - Arg := 2; - end if; - -- We consider that the assertion policy is -- "disabled", except if any level of assertion -- coverage is enabled. @@ -4813,7 +4798,7 @@ package body Instrument.Ada_Unit is -- later on. if Assertion_Coverage_Enabled then - Typ := 'P'; + Instrument_Statement (UIC, N, 'P'); declare Index : Positive := (case Nam is @@ -4827,13 +4812,15 @@ package body Instrument.Ada_Unit is end loop; end; else - Typ := 'p'; + Instrument_Statement (UIC, N, 'p'); end if; - -- Pre/postconditions can be inherited so SCO should - -- never be deactivated??? - when Name_Debug => + + -- Note: conservatively assume that the check policy + -- for pragma debug is enabled. + + Instrument_Statement (UIC, N, 'P'); if Prag_Args.Children_Count = 2 then -- Case of a dyadic pragma Debug: first argument @@ -4846,13 +4833,8 @@ package body Instrument.Ada_Unit is Process_Expression (UIC, Prag_Arg_Expr (Arg), 'X'); - -- Note: conservatively assume that the check policy - -- for all pragmas is enabled (see comment above for - -- Assert case). - - Typ := 'P'; - when Name_Annotate => + -- If this is a coverage exemption, record it if Prag_Args.Children_Count >= 2 @@ -4890,7 +4872,7 @@ package body Instrument.Ada_Unit is null; end; end if; - Typ := 'P'; + Instrument_Statement (UIC, N, 'P'); -- Even though Compile_Time_* pragmas do contain -- decisions, we cannot instrument them, as they would @@ -4900,7 +4882,7 @@ package body Instrument.Ada_Unit is when Name_Compile_Time_Error | Name_Compile_Time_Warning => - Typ := 'P'; + Instrument_Statement (UIC, N, 'P'); -- For all other pragmas, we generate decision entries -- for any embedded expressions, and the pragma is @@ -4910,14 +4892,9 @@ package body Instrument.Ada_Unit is -- related pragmas: [{Static,Dynamic}_]Predicate??? when others => + Instrument_Statement (UIC, N, 'P'); Process_Expression (UIC, N, 'X'); - Typ := 'P'; - end case; - - -- Add statement SCO - - Instrument_Statement (UIC, N, Typ); end; -- Object or named number declaration From 988d8fab074a7bbe2c6f37463908e8ecc0a20f07 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 13 Sep 2023 11:03:30 +0200 Subject: [PATCH 0448/1483] R417-010-scope-metrics: rewrite test baseline Following minor changes in the order of SCOs. --- .../tests/R417-010-scope-metrics/main.adb.xml.expected | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected index 20a7d60d6..da608bc35 100644 --- a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected +++ b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected @@ -782,12 +782,12 @@ - + - + @@ -852,7 +852,7 @@ - + @@ -866,7 +866,7 @@ - + From a6a70bcebd99720ac5f6ee380eaf8bae8e9aaaeb Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 4 Oct 2023 17:33:00 +0200 Subject: [PATCH 0449/1483] Instrument.c: refactor the instrumentation process We no longer process statement by sequences and defer the processing of decisions. This was a leftover from the computation of dominance information, which is not needed in instrumentation mode, and it simplifies the instrumentation process a bit. --- tools/gnatcov/instrument-c.adb | 292 ++++++--------------------------- 1 file changed, 52 insertions(+), 240 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index b848dcfef..fc5f4cbeb 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -1407,69 +1407,6 @@ package body Instrument.C is end loop; end Fix_CXX_For_Ranges; - type SC_Entry is record - N : Cursor_T; - -- Original statement node, used to compute macro expansion information - -- related to this SCO. - - Insertion_N : Cursor_T; - -- If not null, node where the witness call should be inserted. - -- Otherwise, the insertion node will be N. - - From : Source_Location; - To : Source_Location; - Typ : Character; - - Instr_Scheme : Instr_Scheme_Type := Instr_Stmt; - end record; - - package SC is new Table.Table - (Table_Component_Type => SC_Entry, - Table_Index_Type => Nat, - Table_Low_Bound => 1, - Table_Initial => 1000, - Table_Increment => 200, - Table_Name => "SCO_SC"); - -- Used to store statement components for a CS entry to be output as a - -- result of the call to this procedure. SC.Last is the last entry stored, - -- so the current statement sequence is represented by SC_Array (SC_First - -- .. SC.Last), where SC_First is saved on entry to each recursive call to - -- the routine. - -- - -- Extend_Statement_Sequence adds an entry to this array, and then - -- Set_Statement_Entry clears the entries starting with SC_First, copying - -- these entries to the main SCO output table. The reason that we do the - -- temporary caching of results in this array is that we want the SCO table - -- entries for a given CS line to be contiguous, and the processing may - -- output intermediate entries such as decision entries. - - type SD_Entry is record - Nod : Cursor_T; - Typ : Character; - end record; - -- Used to store a single entry in the following table. Nod is the node to - -- be searched for decisions for the case of Process_Decisions_Defer with a - -- node argument (with Lst set to No_Ada_Node. Lst is the list to be - -- searched for decisions for the case of Process_Decisions_Defer with a - -- List argument (in which case Nod is set to No_Ada_Node). - - package SD is new Table.Table - (Table_Component_Type => SD_Entry, - Table_Index_Type => Nat, - Table_Low_Bound => 1, - Table_Initial => 1000, - Table_Increment => 200, - Table_Name => "SCO_SD"); - -- Used to store possible decision information. Instead of calling the - -- Process_Decisions procedures directly, we call Process_Decisions_Defer, - -- which simply stores the arguments in this table. Then when we clear - -- out a statement sequence using Set_Statement_Entry, after generating - -- the CS lines for the statements, the entries in this table result in - -- calls to Process_Decision. The reason for doing things this way is to - -- ensure that decisions are output after the CS line for the statements - -- in which the decisions occur. - -- - ------------------------- -- Traverse_Statements -- ------------------------- @@ -1884,24 +1821,6 @@ package body Instrument.C is Hash_Entries.Free; end Process_Decisions; - procedure Process_Decisions_Defer (N : Cursor_T; T : Character) - with Inline; - -- This routine is logically the same as Process_Decisions, except that the - -- arguments are saved in the SD table for later processing when - -- Set_Statement_Entry is called, which goes through the saved entries - -- making the corresponding calls to Process_Decision. Note: the enclosing - -- statement must have already been added to the current statement - -- sequence, so that nested decisions are properly identified as such. - - ----------------------------- - -- Process_Decisions_Defer -- - ----------------------------- - - procedure Process_Decisions_Defer (N : Cursor_T; T : Character) is - begin - SD.Append ((N, T)); - end Process_Decisions_Defer; - ------------------ -- Has_Decision -- ------------------ @@ -1995,25 +1914,28 @@ package body Instrument.C is L : Cursor_Vectors.Vector; Trailing_Braces : out Unbounded_String) is - SC_First : constant Nat := SC.Last + 1; - SD_First : constant Nat := SD.Last + 1; - procedure Traverse_One (N : Cursor_T; Trailing_Braces : out Unbounded_String); -- Traverse a statement. Set Trailing_Braces to the list of braces that -- should be inserted after this statement. - procedure Extend_Statement_Sequence + procedure Instrument_Statement (N : Cursor_T; Typ : Character; Insertion_N : Cursor_T := Get_Null_Cursor; Instr_Scheme : Instr_Scheme_Type := Instr_Stmt); - -- Add an entry to the SC table - - procedure Set_Statement_Entry; - -- Output CS entries for all statements saved in table SC, and end the - -- current CS sequence. Then output entries for all decisions nested in - -- these statements, which have been deferred so far. + -- Instrument the statement N. + -- + -- Typ is the letter that identifies the type of statement/declaration + -- that is being instrumented. + -- + -- N is the original node from user code, and controls the source + -- location assigned to the statement SCO. + -- + -- In general, this is also where the witness statement is inserted, but + -- in some rare cases, it needs to be inserted at a different place, + -- or in a different manner: this is configured by the Insertion_N and + -- Instr_Scheme formals. function Curlify (N : Cursor_T) return Boolean; -- Rewrite control flow statements (if else, for, while etc.) with @@ -2063,32 +1985,13 @@ package body Instrument.C is return; end if; - -- Initialize or extend current statement sequence. Note that for - -- special cases such as IF and SWITCH statements we will modify - -- the range to exclude internal statements that should not be - -- counted as part of the current statement sequence. case Kind (N) is - -- 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 Cursor_Label_Ref => - Set_Statement_Entry; - - -- Compound statement, which breaks the current statement sequence - when Cursor_Compound_Stmt => - Set_Statement_Entry; - Traverse_Statements (UIC, Get_Children (N), TB); - -- If statement, which breaks the current statement sequence, but - -- we include the condition in the current sequence. - when Cursor_If_Stmt => - Extend_Statement_Sequence (N, 'I'); - Set_Statement_Entry; + Instrument_Statement (N, 'I'); declare Then_Part : constant Cursor_T := Get_Then (N); @@ -2118,17 +2021,13 @@ package body Instrument.C is end if; end; - -- Switch statement, which breaks the current statement sequence, - -- but we include the expression in the current sequence. - when Cursor_Switch_Stmt => - Extend_Statement_Sequence (N, 'C'); + Instrument_Statement (N, 'C'); declare Switch_Cond : constant Cursor_T := Get_Cond (N); Alt : constant Cursor_T := Get_Body (N); begin - Process_Decisions_Defer (Switch_Cond, 'X'); - Set_Statement_Entry; + Process_Decisions (UIC, Switch_Cond, 'X'); -- Process case branches @@ -2144,11 +2043,6 @@ package body Instrument.C is Traverse_Statements (UIC, To_Vector (Case_Body), TB); end; - -- 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. - when Cursor_While_Stmt => declare While_Body : constant Cursor_T := Get_Body (N); @@ -2159,20 +2053,17 @@ package body Instrument.C is -- If the loop condition is a declaration, instrument its -- initialization expression. - Extend_Statement_Sequence + Instrument_Statement (N, 'W', Insertion_N => (if Is_Null (Cond_Var) then Cond else Get_Var_Init_Expr (Cond_Var)), Instr_Scheme => Instr_Expr); - Process_Decisions_Defer (Cond, 'W'); - Set_Statement_Entry; + Process_Decisions (UIC, Cond, 'W'); Traverse_Statements (UIC, To_Vector (While_Body), TB); end; - -- Do while statement. Ends the current statement sequence. - when Cursor_Do_Stmt => declare Do_Body : constant Cursor_T := Get_Body (N); @@ -2189,15 +2080,12 @@ package body Instrument.C is -- Process the while decision - Extend_Statement_Sequence + Instrument_Statement (Do_While, 'W', Instr_Scheme => Instr_Expr); - Process_Decisions_Defer (Do_While, 'W'); - Set_Statement_Entry; + Process_Decisions (UIC, Do_While, 'W'); end; - -- For statement. Ends the current statement sequence - when Cursor_For_Stmt => declare For_Init : constant Cursor_T := Get_For_Init (N); @@ -2205,24 +2093,20 @@ package body Instrument.C is For_Inc : constant Cursor_T := Get_For_Inc (N); For_Body : constant Cursor_T := Get_Body (N); begin - Extend_Statement_Sequence + Instrument_Statement (For_Init, ' ', Insertion_N => N); - Extend_Statement_Sequence + Instrument_Statement (For_Cond, 'F', Instr_Scheme => Instr_Expr); -- The guard expression for the FOR loop is a decision. The -- closest match for this kind of decision is a while loop. - Process_Decisions_Defer (For_Cond, 'W'); - - Set_Statement_Entry; + Process_Decisions (UIC, For_Cond, 'W'); Traverse_Statements (UIC, To_Vector (For_Body), TB); - Extend_Statement_Sequence + Instrument_Statement (For_Inc, ' ', Instr_Scheme => Instr_Expr); - - Set_Statement_Entry; end; when Cursor_CXX_For_Range_Stmt => @@ -2240,9 +2124,9 @@ package body Instrument.C is -- See Fix_CXX_For_Ranges for an explanation of the -- below code. - Extend_Statement_Sequence + Instrument_Statement (For_Init_Stmt, ' ', Insertion_N => For_Init_Stmt); - Process_Decisions_Defer (For_Init_Stmt, 'X'); + Process_Decisions (UIC, For_Init_Stmt, 'X'); -- Preemptively end the introduced outer scope as it is -- easier done when traversing the AST. @@ -2253,28 +2137,21 @@ package body Instrument.C is -- Instrument the range as mentioned above - Extend_Statement_Sequence + Instrument_Statement (For_Range_Decl, ' ', Insertion_N => N, Instr_Scheme => Instr_Stmt); - Process_Decisions_Defer (For_Range_Decl, 'X'); - - Set_Statement_Entry; + Process_Decisions (UIC, For_Range_Decl, 'X'); -- Generate obligations for body statements Traverse_Statements (UIC, To_Vector (For_Body), TB); end; - -- Unconditional goto, which is included in the current statement - -- sequence, but then terminates it. - when Cursor_Goto_Stmt | Cursor_Indirect_Goto_Stmt => - Extend_Statement_Sequence (N, ' '); - Set_Statement_Entry; + Instrument_Statement (N, ' '); when Cursor_Label_Stmt => - Set_Statement_Entry; Traverse_Statements (UIC, Get_Children (N), TB); when Cursor_Stmt_Expr => @@ -2295,9 +2172,9 @@ package body Instrument.C is if not Is_Manual_Dump_Procedure_Symbol (Get_Callee_Name_Str (N)) then - Extend_Statement_Sequence (N, ' '); + Instrument_Statement (N, ' '); if Has_Decision (N) then - Process_Decisions_Defer (N, 'X'); + Process_Decisions (UIC, N, 'X'); end if; end if; @@ -2306,34 +2183,22 @@ package body Instrument.C is -- Determine required type character code, or ASCII.NUL if -- no SCO should be generated for this node. - Extend_Statement_Sequence (N, ' '); + Instrument_Statement (N, ' '); -- Process any embedded decisions if Has_Decision (N) then if Is_Constexpr (N) then - - -- HACK: as we rely on the value of - -- UIC.Disable_Instrumentation to know if we should - -- instrument a source coverage obligation, we - -- have to process the decision before reenabling - -- instrumentation. Call Process_Decisions instead of - -- Process_Decisions_Defer, and Set_Statement_Entry - -- before to flush the statement SCOs. TODO???: rework - -- when eng/cov/gnatcoverage#107 is dealt with. - UIC.Pass.Report (N, "gnatcov limitation: cannot instrument constexpr" & " variable declarations."); - - Set_Statement_Entry; UIC.Disable_Instrumentation := True; Process_Decisions (UIC, N, 'X'); UIC.Disable_Instrumentation := Save_Disable_Instrumentation; else - Process_Decisions_Defer (N, 'X'); + Process_Decisions (UIC, N, 'X'); end if; end if; end case; @@ -2348,11 +2213,11 @@ package body Instrument.C is L => Get_Lambda_Exprs (N)); end Traverse_One; - ------------------------------- - -- Extend_Statement_Sequence -- - ------------------------------- + -------------------------- + -- Instrument_Statement -- + -------------------------- - procedure Extend_Statement_Sequence + procedure Instrument_Statement (N : Cursor_T; Typ : Character; Insertion_N : Cursor_T := Get_Null_Cursor; @@ -2396,67 +2261,21 @@ package body Instrument.C is T := End_Sloc (To_Node); end if; - SC.Append - ((N => Insert_Cursor, - Insertion_N => - (if Is_Null (Insertion_N) - then N - else Insertion_N), - From => F, - To => T, - Typ => Typ, - Instr_Scheme => Instr_Scheme)); - end Extend_Statement_Sequence; - - ------------------------- - -- Set_Statement_Entry -- - ------------------------- - - procedure Set_Statement_Entry is - SC_Last : constant Types.Int := SC.Last; - SD_Last : constant Types.Int := SD.Last; - begin - for J in SC_First .. SC_Last loop - declare - SCE : SC_Entry renames SC.Table (J); - begin - UIC.Pass.Append_SCO - (UIC => UIC, - N => SCE.N, - C1 => 'S', - C2 => SCE.Typ, - From => SCE.From, - To => SCE.To, - Last => (J = SC_Last)); - - UIC.Pass.Instrument_Statement - (UIC => UIC, - LL_SCO => SCOs.SCO_Table.Last, - Insertion_N => SCE.Insertion_N, - Instr_Scheme => SCE.Instr_Scheme); - end; - end loop; - - -- Clear out used section of SC table - - SC.Set_Last (SC_First - 1); - - -- Output any embedded decisions - - for J in SD_First .. SD_Last loop - declare - SDE : SD_Entry renames SD.Table (J); - - begin - Process_Decisions (UIC, SDE.Nod, SDE.Typ); - end; - end loop; - - -- Clear out used section of SD table - - SD.Set_Last (SD_First - 1); - - end Set_Statement_Entry; + UIC.Pass.Append_SCO + (UIC => UIC, + N => N, + C1 => 'S', + C2 => Typ, + From => F, + To => T, + Last => True); + + UIC.Pass.Instrument_Statement + (UIC => UIC, + LL_SCO => SCOs.SCO_Table.Last, + Insertion_N => (if Is_Null (Insertion_N) then N else Insertion_N), + Instr_Scheme => Instr_Scheme); + end Instrument_Statement; ------------- -- Curlify -- @@ -2529,8 +2348,6 @@ package body Instrument.C is use Cursor_Vectors; - Emit_SCOs : Boolean := False; - -- Start of processing for Traverse_Statements begin @@ -2541,12 +2358,7 @@ package body Instrument.C is Trailing_Braces := +""; end if; Traverse_One (N, Trailing_Braces); - Emit_SCOs := True; end loop; - - if Emit_SCOs then - Set_Statement_Entry; - end if; end Traverse_Statements; --------------------------- From 3fbab64fe5a196f7fcdb11ec5de4a7085a21a7ef Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 5 Oct 2023 10:20:55 +0200 Subject: [PATCH 0450/1483] gpr-complex: update coverage expectations for the test This test checks coverage expectations over instrumented sources. We used to introduce a new line in instrumented sources when writing warnings and style check pragmas, but this is no longer the case, so adjust the expectations accordingly. --- testsuite/tests/instr-cov/gpr-complex/test.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/testsuite/tests/instr-cov/gpr-complex/test.py b/testsuite/tests/instr-cov/gpr-complex/test.py index 1dd1f488c..2d0c98065 100644 --- a/testsuite/tests/instr-cov/gpr-complex/test.py +++ b/testsuite/tests/instr-cov/gpr-complex/test.py @@ -83,8 +83,7 @@ def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): # belonging to the library. We should fix this (and adjust coverage # expectations) if possible. thistest.log("== Redefining Pkg body ==") -expected_xcov = {"pkg.adb.xcov": {"+": {7}}, "pkg-bar.adb.xcov": {"+": {4}}} -# Should be: {"pkg.adb.xcov": {"+": {7}}, "pkg-bar.adb.xcov": {"+": {5}}} +expected_xcov = {"pkg.adb.xcov": {"+": {7}}, "pkg-bar.adb.xcov": {"+": {3}}} build_run_cov_and_check( "main_body.gpr", main_prj_obj_dir="obj-main_body", @@ -94,8 +93,7 @@ def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): # Now the main project defines an alternate separate. thistest.log("== Redefining Pkg.Bar separate ==") -expected_xcov = {"pkg.adb.xcov": {"+": {6}}, "pkg-bar.adb.xcov": {"+": {5}}} -# Should be: {"pkg.adb.xcov": {"+": {5}}, "pkg-bar.adb.xcov": {"+": {5}}} +expected_xcov = {"pkg.adb.xcov": {"+": {5}}, "pkg-bar.adb.xcov": {"+": {5}}} build_run_cov_and_check( "main_sep.gpr", main_prj_obj_dir="obj-main_sep", @@ -105,15 +103,10 @@ def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): # Now the main project defines an alternate spec. thistest.log("== Redefining Pkg spec ==") expected_xcov = { - "pkg.adb.xcov": {"+": {6}}, - "pkg-bar.adb.xcov": {"+": {4}}, + "pkg.adb.xcov": {"+": {5}}, + "pkg-bar.adb.xcov": {"+": {3}}, "pkg.ads.xcov": {"+": {4}}, } -# Should be: { -# "pkg.adb.xcov": {"+": {5}}, -# "pkg-bar.adb.xcov": {"+": {3}}, -# "pkg.ads.xcov": {"+": {4}}, -# } build_run_cov_and_check( "main_spec.gpr", main_prj_obj_dir="obj-main_spec", From 5cc7811b45ca47bd9e7c449952932e422f25d7b8 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 5 Oct 2023 11:10:47 +0200 Subject: [PATCH 0451/1483] Pass the right filename to gnatpp Also make the pretty printing failure a gnatcov warning, to be able to detect it in the testsuite. --- .../tests/instr-cov/pretty_print/main.adb | 9 ++++++ .../tests/instr-cov/pretty_print/pkg.adb | 12 ++++++++ .../tests/instr-cov/pretty_print/pkg.ads | 5 ++++ .../tests/instr-cov/pretty_print/test.py | 30 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 9 +++--- tools/gnatcov/text_files.adb | 2 +- 6 files changed, 62 insertions(+), 5 deletions(-) create mode 100644 testsuite/tests/instr-cov/pretty_print/main.adb create mode 100644 testsuite/tests/instr-cov/pretty_print/pkg.adb create mode 100644 testsuite/tests/instr-cov/pretty_print/pkg.ads create mode 100644 testsuite/tests/instr-cov/pretty_print/test.py diff --git a/testsuite/tests/instr-cov/pretty_print/main.adb b/testsuite/tests/instr-cov/pretty_print/main.adb new file mode 100644 index 000000000..4937d0976 --- /dev/null +++ b/testsuite/tests/instr-cov/pretty_print/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Main is + Who : constant String := "world"; +begin + Put_Line ("Hello, " & Who & "!"); + Put_Line ("Fact (6) = " & Integer'Image (Pkg.Fact (6))); +end Main; diff --git a/testsuite/tests/instr-cov/pretty_print/pkg.adb b/testsuite/tests/instr-cov/pretty_print/pkg.adb new file mode 100644 index 000000000..d7c0c4843 --- /dev/null +++ b/testsuite/tests/instr-cov/pretty_print/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/pretty_print/pkg.ads b/testsuite/tests/instr-cov/pretty_print/pkg.ads new file mode 100644 index 000000000..3e3dfbeb4 --- /dev/null +++ b/testsuite/tests/instr-cov/pretty_print/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/pretty_print/test.py b/testsuite/tests/instr-cov/pretty_print/test.py new file mode 100644 index 000000000..55f53bc87 --- /dev/null +++ b/testsuite/tests/instr-cov/pretty_print/test.py @@ -0,0 +1,30 @@ +""" +Test that running gnatcov instrument with the --pretty-print switch does not +yield any warning. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs="..", mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--pretty-print"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports( + "xcov/*.xcov", + { + "xcov/main.adb.xcov": {"+": {5, 7, 8}}, + "xcov/pkg.adb.xcov": {"+": {5, 6, 8}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 9b3120ecf..a783d55ef 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8560,7 +8560,8 @@ package body Instrument.Ada_Unit is is Last_Buffer_Index : constant Natural := Natural (CU_Names.Length); Pkg_Name : constant String := To_Ada (PB_Unit.Unit); - Filename : constant String := To_Filename (Prj, Ada_Language, PB_Unit); + Filename : constant String := + New_File (Prj, To_Filename (Prj, Ada_Language, PB_Unit)); File : Text_Files.File_Type; procedure Put_Language_Version_Pragma; @@ -8586,7 +8587,7 @@ package body Instrument.Ada_Unit is -- Start of processing for Emit_Pure_Buffer_Unit begin - Create_File (Prj, File, Filename); + File.Create (Filename); Put_Warnings_And_Style_Checks_Pragmas (File); Put_Language_Version_Pragma; @@ -8644,9 +8645,9 @@ package body Instrument.Ada_Unit is Unit => PB_Unit.Unit, Part => GNATCOLL.Projects.Unit_Body); PB_Filename : constant String := - To_Filename (Prj, Ada_Language, PB_Unit_Body); + New_File (Prj, To_Filename (Prj, Ada_Language, PB_Unit_Body)); begin - Create_File (Prj, File, PB_Filename); + File.Create (PB_Filename); Put_Warnings_And_Style_Checks_Pragmas (File); Put_Language_Version_Pragma; diff --git a/tools/gnatcov/text_files.adb b/tools/gnatcov/text_files.adb index 020e57645..0f7f238a9 100644 --- a/tools/gnatcov/text_files.adb +++ b/tools/gnatcov/text_files.adb @@ -169,7 +169,7 @@ package body Text_Files is Spawn (GNATpp.all, Args, Success); Free (GNATpp); if not Success then - Put_Line ("pretty-printing " & Filename & " failed!"); + Outputs.Warn ("pretty-printing " & Filename & " failed!"); end if; end Run_GNATpp; From a95388ceaa0edae4205fe1623bd1a937c11e2e9e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 5 Oct 2023 13:25:49 +0000 Subject: [PATCH 0452/1483] .gitignore: update tempdir prefixes after changes for assertion coverage --- testsuite/.gitignore | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/testsuite/.gitignore b/testsuite/.gitignore index f2233cff7..0184a825b 100644 --- a/testsuite/.gitignore +++ b/testsuite/.gitignore @@ -1,7 +1,9 @@ -mc_* -uc_* -dc_* -st_* +d_* +datc_* +datcc_* +m_* +s_* +u_* tmp_* tmp bin From dc33f6375f9ac2a932605b25abe89a0fd8fa0364 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 5 Oct 2023 13:20:42 +0000 Subject: [PATCH 0453/1483] Instrument Ada: fix the handling of "Boolean" hiding with expr functions The instrumentation of expression functions in contexts where the "Boolean" standard entity is hidden by user-defined entities produces incorrect code. This commit fixes this, leveraging our GNATcov_RTS.Std renaming of the Standard package. --- .../131-hidden-bool-exprfunc/src/pkg.ads | 6 ++++++ .../131-hidden-bool-exprfunc/src/test_0.adb | 10 ++++++++++ .../src/test_full.adb | 12 +++++++++++ .../tests/131-hidden-bool-exprfunc/test.opt | 2 ++ .../tests/131-hidden-bool-exprfunc/test.py | 13 ++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 20 ++++++++++++++----- 6 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 testsuite/tests/131-hidden-bool-exprfunc/src/pkg.ads create mode 100644 testsuite/tests/131-hidden-bool-exprfunc/src/test_0.adb create mode 100644 testsuite/tests/131-hidden-bool-exprfunc/src/test_full.adb create mode 100644 testsuite/tests/131-hidden-bool-exprfunc/test.opt create mode 100644 testsuite/tests/131-hidden-bool-exprfunc/test.py diff --git a/testsuite/tests/131-hidden-bool-exprfunc/src/pkg.ads b/testsuite/tests/131-hidden-bool-exprfunc/src/pkg.ads new file mode 100644 index 000000000..c3dcb2f41 --- /dev/null +++ b/testsuite/tests/131-hidden-bool-exprfunc/src/pkg.ads @@ -0,0 +1,6 @@ +pragma Ada_2012; + +package Pkg is + type T is (Boolean, String); + function F (I : Integer) return Integer is (I + 1); -- # stmt +end Pkg; diff --git a/testsuite/tests/131-hidden-bool-exprfunc/src/test_0.adb b/testsuite/tests/131-hidden-bool-exprfunc/src/test_0.adb new file mode 100644 index 000000000..cc00ec17a --- /dev/null +++ b/testsuite/tests/131-hidden-bool-exprfunc/src/test_0.adb @@ -0,0 +1,10 @@ +with Pkg; use Pkg; + +procedure Test_0 is +begin + null; +end Test_0; + +--# pkg.ads +-- +-- /stmt/ l- ## s- diff --git a/testsuite/tests/131-hidden-bool-exprfunc/src/test_full.adb b/testsuite/tests/131-hidden-bool-exprfunc/src/test_full.adb new file mode 100644 index 000000000..8eaaf10a9 --- /dev/null +++ b/testsuite/tests/131-hidden-bool-exprfunc/src/test_full.adb @@ -0,0 +1,12 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Test_0 is +begin + Assert (F (0) = 1); +end Test_0; + +--# pkg.ads +-- +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/131-hidden-bool-exprfunc/test.opt b/testsuite/tests/131-hidden-bool-exprfunc/test.opt new file mode 100644 index 000000000..4102be8d5 --- /dev/null +++ b/testsuite/tests/131-hidden-bool-exprfunc/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Expr functions not supported by 5.04a1 +7.1.2 DEAD Expr functions not supported by 5.04a1 diff --git a/testsuite/tests/131-hidden-bool-exprfunc/test.py b/testsuite/tests/131-hidden-bool-exprfunc/test.py new file mode 100644 index 000000000..a4211aff7 --- /dev/null +++ b/testsuite/tests/131-hidden-bool-exprfunc/test.py @@ -0,0 +1,13 @@ +""" +Regression test: when the "Boolean" standard entity is hidden by a user-defined +entity, the stmt instrumentation of expression functions used to generate +invalid code. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index a783d55ef..8cd23981e 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -412,6 +412,19 @@ package body Instrument.Ada_Unit is Make_Identifier (UIC, D_Name))); -- Shortcut to create a defining identifier tree + function Make_Std_Ref + (UIC : Ada_Unit_Inst_Context'Class; + Entity : Text_Type) return Node_Rewriting_Handle + is (Create_From_Template + (UIC.Rewriting_Context, + "GNATcov_RTS.Std." & Entity, (1 .. 0 => <>), + Rule => Expr_Rule)); + -- Language-defined entities such as "Standard" or "Boolean" may be hidden + -- by entities defined in the code to instrument. To avoid compilation + -- issues, we have an accessible package that renames Standard in + -- GNATcov_RTS: this function allows to refer to standard entities from + -- this renaming. + --------------------- -- Unbounded texts -- --------------------- @@ -1481,10 +1494,7 @@ package body Instrument.Ada_Unit is -- very well be). To avoid issues, we have an accessible package -- that renames Standard in GNATcov_RTS. - To_Type_Indentifier := - Create_Identifier - (IC.Rewriting_Context, - To_Text ("GNATcov_RTS.Std.Boolean")); + To_Type_Indentifier := Make_Std_Ref (IC, "Boolean"); end if; return Create_Call_Expr @@ -3566,7 +3576,7 @@ package body Instrument.Ada_Unit is F_Ids => Formal_Def_Id, F_Has_Aliased => No_Node_Rewriting_Handle, F_Mode => No_Node_Rewriting_Handle, - F_Type_Expr => Make_Identifier (UIC, "Boolean"), + F_Type_Expr => Make_Std_Ref (UIC, "Boolean"), F_Default_Expr => No_Node_Rewriting_Handle, F_Aspects => No_Node_Rewriting_Handle); end; From e02c8dff8db3d73c89b9779821c0ec13245658e9 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 6 Oct 2023 10:27:05 +0200 Subject: [PATCH 0454/1483] pretty_print: kill test under older GNAT versions GNAT-based gnatpp can't pretty print the instrumented sources because of missing dependencies to the instrumentation runtime. --- testsuite/tests/instr-cov/pretty_print/test.opt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 testsuite/tests/instr-cov/pretty_print/test.opt diff --git a/testsuite/tests/instr-cov/pretty_print/test.opt b/testsuite/tests/instr-cov/pretty_print/test.opt new file mode 100644 index 000000000..87a62fc19 --- /dev/null +++ b/testsuite/tests/instr-cov/pretty_print/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD GNAT-based gnatpp does not work on a source with missing dependencies +7.1.2 DEAD GNAT-based gnatpp does not work on a source with missing dependencies From 5a44a5099438d289e679ac11a242b0b926067996 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 5 Oct 2023 13:39:53 +0000 Subject: [PATCH 0455/1483] relocate-build-tree: minor reformatting --- .../modified-root-dir/test.py | 29 ++++++++------- .../unmodified-root-dir/test.py | 35 ++++++++++++------- 2 files changed, 39 insertions(+), 25 deletions(-) diff --git a/testsuite/tests/relocate-build-tree/modified-root-dir/test.py b/testsuite/tests/relocate-build-tree/modified-root-dir/test.py index 4ad78ce9a..4d3dab9c0 100644 --- a/testsuite/tests/relocate-build-tree/modified-root-dir/test.py +++ b/testsuite/tests/relocate-build-tree/modified-root-dir/test.py @@ -1,26 +1,29 @@ """ -Test the behaviour of the --relocate-build-tree and -root-dir option. +Test the behaviour of the --relocate-build-tree and --root-dir option. """ import os +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir -from SUITE.tutils import gprfor -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + expected_reports = { - "ops.adb.xcov": {'+': {4, 5}, '-': {6}}, - "ops.ads.xcov": {}, - } + "ops.adb.xcov": {"+": {4, 5}, "-": {6}}, + "ops.ads.xcov": {}, +} -project_root = os.path.abspath(os.getcwd())+os.sep +project_root = os.path.abspath(".") # Create ops project file os.chdir("opslib") -extra="for Library_Dir use \"lib-opslib\";\n\ -for Library_Name use \"opslib\";" +extra = """ + for Library_Dir use "lib-opslib"; + for Library_Name use "opslib"; +""" ops_gpr = gprfor([], prjid="ops", extra=extra) # Create tests project file @@ -36,12 +39,14 @@ gprsw=GPRswitches( abs_test_gpr, units=["ops"], - root_dir=project_root, - relocate_build_tree=True), + root_dir=project_root + os.sep, + relocate_build_tree=True, + ), covlevel="stmt", gpr_exe_dir=os.path.join(project_root, "tmp", "tests"), mains=["test_inc"], - extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"]) + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], +) check_xcov_reports("*.xcov", expected_reports, "out-instr") diff --git a/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py index 257ef7ae0..4033917d4 100644 --- a/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py +++ b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py @@ -4,21 +4,24 @@ import os +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir -from SUITE.tutils import gprfor -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + expected_reports = { - "ops.adb.xcov": {'+': {4, 5}, '-': {6}}, - "ops.ads.xcov": {}, - } + "ops.adb.xcov": {'+': {4, 5}, '-': {6}}, + "ops.ads.xcov": {}, +} # Create ops project file os.chdir("opslib") -extra="for Library_Dir use \"lib-opslib\";\n\ -for Library_Name use \"opslib\";" +extra = """ + for Library_Dir use "lib-opslib"; + for Library_Name use "opslib"; +""" ops_gpr = gprfor([], prjid="ops", extra=extra) os.chdir("..") @@ -32,10 +35,12 @@ gprsw=GPRswitches( abs_test_gpr, units=["ops"], - relocate_build_tree=True), + relocate_build_tree=True, + ), covlevel="stmt", mains=["test_inc"], - extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"]) + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], +) check_xcov_reports("*.xcov", expected_reports, "out-instr") @@ -44,10 +49,12 @@ gprsw=GPRswitches( os.path.join("..", tests_gpr), units=["ops"], - relocate_build_tree=True), + relocate_build_tree=True, + ), covlevel="stmt", mains=["test_inc"], - extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"]) + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], +) check_xcov_reports("*.xcov", expected_reports, "out-instr") @@ -56,10 +63,12 @@ gprsw=GPRswitches( tests_gpr, units=["ops"], - relocate_build_tree=True), + relocate_build_tree=True, + ), covlevel="stmt", mains=["test_inc"], - extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"]) + extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], +) check_xcov_reports("*.xcov", expected_reports, "out-instr") From 06eab2666876463343ed5b92362bbe0c8248c6e9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 5 Oct 2023 14:06:40 +0000 Subject: [PATCH 0456/1483] SUITE.tutils.gprfor: add a CWD optional argument This new argument allows tests to generate a project file in a designated directory without requiring the caller to call Python's current working directory. This allows less convoluted testing code. --- testsuite/SUITE/tutils.py | 18 ++++++++++++++---- .../tests/homonym-units-of-interest/test.py | 4 +++- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index d76385f0b..7c2dde6d9 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -335,7 +335,7 @@ def gpr_emulator_package(): def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", main_cargs=None, langs=None, deps=None, scenario_extra="", - compiler_extra="", extra=""): + compiler_extra="", extra="", cwd=None): """ Generate a simple PRJID.gpr project file to build executables for each main source file in the MAINS list, sources in SRCDIRS. Inexistant directories @@ -345,8 +345,12 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", COMPILER_EXTRA, if any, at the end of the Compiler package contents. Add EXTRA, if any, at the end of the project file contents. Return the gpr file name. + + If CWD is None, generate the project file in the current directory. + Generate it in the CWD directory otherwise. """ + cwd = cwd or os.getcwd() mains = to_list(mains) srcdirs = to_list(srcdirs) langs = to_list(langs) @@ -365,14 +369,18 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", # Likewise for source dirs. Filter on existence, to allow widening the set # of tentative dirs while preventing complaints from gprbuild about # inexistent ones. - srcdirs_list = [d for d in srcdirs if os.path.exists(d)] + srcdirs_list = [ + d + for d in srcdirs + if os.path.exists(os.path.join(cwd, d)) + ] # Determine the language(s) from the sources if they are not explicitly # passed as parameters. if not langs: lang_infos = [language_info(src) for srcdir in srcdirs_list - for src in os.listdir(srcdir)] + for src in os.listdir(os.path.join(cwd, srcdir))] langs = set(li.name for li in lang_infos if li) srcdirs = ', '.join('"%s"' % d for d in srcdirs_list) @@ -434,7 +442,9 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", 'pkg_emulator': gpr_emulator_package(), 'extra': extra} - return text_to_file(text=gprtext, filename=prjid + ".gpr") + return text_to_file( + text=gprtext, filename=os.path.join(cwd, prjid + ".gpr") + ) # The following functions abstract away the possible presence of extensions at diff --git a/testsuite/tests/homonym-units-of-interest/test.py b/testsuite/tests/homonym-units-of-interest/test.py index 6931c25bc..8633124f8 100644 --- a/testsuite/tests/homonym-units-of-interest/test.py +++ b/testsuite/tests/homonym-units-of-interest/test.py @@ -23,7 +23,9 @@ p = gprfor(mains=['test.c'], deps=['prj1', 'prj2'], srcdirs=['..']) xcov_args = build_and_run( - gprsw=GPRswitches(root_project=p), + # TODO: The test fails if we pass an absolute path to root_project, which + # is unexpected. + gprsw=GPRswitches(root_project=os.path.basename(p)), covlevel='stmt+mcdc', mains=['test'], extra_coverage_args=['--annotate=xcov', '--output-dir=xcov'], From 35e6fd1f8ea79bbdf7b5935d3e69e18d52e43bb7 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 5 Oct 2023 14:07:45 +0000 Subject: [PATCH 0457/1483] relocate-build-tree: rework to avoid source repository pollution --- .../modified-root-dir/test.py | 30 ++++++++----- .../unmodified-root-dir/test.py | 43 +++++++++---------- 2 files changed, 39 insertions(+), 34 deletions(-) diff --git a/testsuite/tests/relocate-build-tree/modified-root-dir/test.py b/testsuite/tests/relocate-build-tree/modified-root-dir/test.py index 4d3dab9c0..68ad4003f 100644 --- a/testsuite/tests/relocate-build-tree/modified-root-dir/test.py +++ b/testsuite/tests/relocate-build-tree/modified-root-dir/test.py @@ -4,6 +4,8 @@ import os +from e3.fs import sync_tree + from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir @@ -16,39 +18,45 @@ "ops.ads.xcov": {}, } +# To avoid source repository pollution, copy source material to a temporary +# directory. +Wdir("tmp_") +for filename in ["opslib", "tests"]: + sync_tree(os.path.join("..", filename), filename) + project_root = os.path.abspath(".") # Create ops project file -os.chdir("opslib") extra = """ for Library_Dir use "lib-opslib"; for Library_Name use "opslib"; """ -ops_gpr = gprfor([], prjid="ops", extra=extra) +gprfor([], prjid="ops", extra=extra, cwd="opslib") # Create tests project file -os.chdir(os.path.join("..", "tests")) -tests_gpr = gprfor(["test_inc.adb"], prjid="tests", deps=["../opslib/ops.gpr"]) -abs_test_gpr = os.path.abspath(tests_gpr) - -os.chdir("..") +tests_gpr = os.path.abspath( + gprfor( + ["test_inc.adb"], + prjid="tests", + deps=["../opslib/ops.gpr"], + cwd="tests", + ) +) # Build directory is relocated in tmp -wd = Wdir("tmp") build_run_and_coverage( gprsw=GPRswitches( - abs_test_gpr, + tests_gpr, units=["ops"], root_dir=project_root + os.sep, relocate_build_tree=True, ), covlevel="stmt", - gpr_exe_dir=os.path.join(project_root, "tmp", "tests"), + gpr_exe_dir=os.path.join(project_root, "tests"), mains=["test_inc"], extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], ) check_xcov_reports("*.xcov", expected_reports, "out-instr") -wd.to_homedir() thistest.result() diff --git a/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py index 4033917d4..ed46226fe 100644 --- a/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py +++ b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py @@ -4,6 +4,8 @@ import os +from e3.fs import sync_tree + from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir @@ -16,27 +18,31 @@ "ops.ads.xcov": {}, } +# To avoid source repository pollution, copy source material to a temporary +# directory. +Wdir("tmp_") +for filename in ["opslib", "src"]: + sync_tree(os.path.join("..", filename), filename) + # Create ops project file -os.chdir("opslib") extra = """ for Library_Dir use "lib-opslib"; for Library_Name use "opslib"; """ -ops_gpr = gprfor([], prjid="ops", extra=extra) -os.chdir("..") +ops_gpr = gprfor([], prjid="ops", extra=extra, cwd="opslib") # Create tests project file -tests_gpr = gprfor(["test_inc.adb"], prjid="tests", deps=["opslib/ops.gpr"]) -abs_test_gpr = os.path.abspath(tests_gpr) +tests_gpr = os.path.abspath( + gprfor( + ["test_inc.adb"], + prjid="tests", + deps=["opslib/ops.gpr"], + ) +) # Build directory is relocated in tmp -wd = Wdir("tmp") build_run_and_coverage( - gprsw=GPRswitches( - abs_test_gpr, - units=["ops"], - relocate_build_tree=True, - ), + gprsw=GPRswitches(tests_gpr, units=["ops"], relocate_build_tree=True), covlevel="stmt", mains=["test_inc"], extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], @@ -46,11 +52,7 @@ # Check if relative path for GPR works correctly build_run_and_coverage( - gprsw=GPRswitches( - os.path.join("..", tests_gpr), - units=["ops"], - relocate_build_tree=True, - ), + gprsw=GPRswitches(tests_gpr, units=["ops"], relocate_build_tree=True), covlevel="stmt", mains=["test_inc"], extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], @@ -58,13 +60,9 @@ check_xcov_reports("*.xcov", expected_reports, "out-instr") -os.environ["GPR_PROJECT_PATH"] += os.pathsep + os.path.dirname(abs_test_gpr) +os.environ["GPR_PROJECT_PATH"] += os.pathsep + os.path.dirname(tests_gpr) build_run_and_coverage( - gprsw=GPRswitches( - tests_gpr, - units=["ops"], - relocate_build_tree=True, - ), + gprsw=GPRswitches(tests_gpr, units=["ops"], relocate_build_tree=True), covlevel="stmt", mains=["test_inc"], extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], @@ -72,5 +70,4 @@ check_xcov_reports("*.xcov", expected_reports, "out-instr") -wd.to_homedir() thistest.result() From 26dce09caa57061e18c1700303279ef843c60860 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 9 Oct 2023 15:31:32 +0000 Subject: [PATCH 0458/1483] clang-wrapper.cc: minor reformatting This fixes a sync issue with the edge branch. --- tools/gnatcov/clang-wrapper.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 945646bfa..c4aa9d4be 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -714,10 +714,10 @@ clang_CXRewriter_getRewrittenText (CXRewriter Rew, CXSourceRange Rng) return createDup (R.getRewrittenText (SR).c_str ()); } - /* Wrappers around source location analysis functions. */ +/* Wrappers around source location analysis functions. */ - extern "C" unsigned - clang_isMacroLocation (CXSourceLocation Loc) +extern "C" unsigned +clang_isMacroLocation (CXSourceLocation Loc) { const SourceLocation SLoc = translateSourceLocation (Loc); return SLoc.isMacroID () ? 1 : 0; From 975f3c96395efde1b851b187d37c09c2d98f36ad Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 5 Oct 2023 13:36:57 +0000 Subject: [PATCH 0459/1483] integrated_instrumentation/no_uoi: avoid source repository pollution --- .../integrated_instrumentation/no_uoi/test.py | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/testsuite/tests/integrated_instrumentation/no_uoi/test.py b/testsuite/tests/integrated_instrumentation/no_uoi/test.py index 85249f472..4e6ad8e9c 100644 --- a/testsuite/tests/integrated_instrumentation/no_uoi/test.py +++ b/testsuite/tests/integrated_instrumentation/no_uoi/test.py @@ -16,9 +16,20 @@ from SCOV.minicheck import check_xcov_reports from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +# To avoid source repository pollution and interference between successive test +# runs, copy source material to a temporary directory and run the test there, +# which is common practice in the gnatcov testsuite. Doing so is however +# absolutely not a requirement to use the integrated instrumentation scheme. Wdir("tmp_") -cwd = os.getcwd() +src_dir = os.path.abspath("src") +run_dir = os.path.abspath("run") +os.mkdir(src_dir) +os.mkdir(run_dir) + +for filename in ["Makefile", "pkg.c", "test.c"]: + cp(os.path.join("..", filename), os.path.join(src_dir, filename)) # Then, setup the instrumentation process xcov( @@ -26,17 +37,17 @@ "setup-integration", "--level=stmt", "--compilers=g++", - f"--output-dir={cwd}", + f"--output-dir={run_dir}", ] ) # Shadow the compiler driver with the generated wrapper -env.add_search_path(env_var="PATH", path=cwd) +env.add_search_path(env_var="PATH", path=run_dir) # Then, run the build process unchanged -cmdrun(["make", "-C", "..", "test"], for_pgm=False) +cmdrun(["make", "-C", src_dir, "test"], for_pgm=False) # Run the executable -cmdrun(["../test"], for_pgm=False) +cmdrun([os.path.join(src_dir, "test")], for_pgm=False) thistest.result() From 3cb91dc73804fefacee73fbb1704b012e794f5ba Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 10 Oct 2023 10:15:25 +0200 Subject: [PATCH 0460/1483] .gitlab-ci.yml: check for issues in merge requests descriptions --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1a1b5ecb5..a5539a4e1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -49,6 +49,8 @@ build: - mem:16 stage: build script: + - (unset GITLAB_TOKEN; require_issue) + - export PATH=/it/e3/bin:$PATH - *edge_vars From 74dd26bd676e055141d3ed799a2678a28bbc424e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 6 Oct 2023 11:28:48 +0200 Subject: [PATCH 0461/1483] last_chance_handler: fix insertion of with clause To insert the 'with' clause for the last chance dump unit, we picked the first line that was not a pragma. This relied on the implicit assumption that we did not have code where a line was composed both of a pragma and the start of a package / procedure, e.g. pragma Style_Checks (Off); procedure Foo is ... As we can now have such code occurrences in instrumented sources, because we no longer introduce new lines for inserted Style_Checks and Warnings pragmas, we drop this heuristic and use LAL syntax tree to know where to insert the with clause. --- testsuite/SCOV/instr.py | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 0e54da693..2fddc29f2 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -5,6 +5,8 @@ from e3.fs import mkdir +import libadalang as lal + from SUITE.context import thistest from SUITE.cutils import contents_of, ext, indent from SUITE.tutils import RUNTIME_INFO, GNATCOV_INFO, locate_gpr_file, xcov @@ -251,19 +253,31 @@ def filename(prefix, ext): # included in the build. Insert the "with" clause after all pragmas # to keep the code valid. - main_file = filename(main_unit, 'adb') - with open(main_file, 'r') as f: - lines = f.read().splitlines() - - for i, line in enumerate(lines): - if not line.strip().lower().startswith('pragma'): - break - else: - assert False, 'Could not find a non-pragma line' - lines.insert(i, 'with {};'.format(handler_unit)) - - with open(main_file, 'w') as f: - f.write('\n'.join(lines)) + main_file = filename(main_unit, "adb") + + context = lal.AnalysisContext() + unit = context.get_from_file(main_file) + + # Assume that the root node is a CompilationUnit. Then look for the token + # right before the start of the body node: this is where we will insert the + # with_handler clause. + assert not unit.diagnostics + assert isinstance(unit.root, lal.CompilationUnit) + after_body_token = unit.lookup_token(unit.root.f_body.sloc_range.start) + before_body_token = after_body_token.previous + + # build the new source + new_source = "".join( + [ + "" + if before_body_token is None + else lal.Token.text_range(unit.first_token, before_body_token), + "with {};".format(handler_unit), + lal.Token.text_range(after_body_token, unit.last_token), + ] + ) + with open(main_file, "w") as f: + f.write(new_source) def available_ada_dump_triggers(): From d907c881af3911444aa238a1f230d5397627bbe1 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 12 Oct 2023 08:18:19 +0000 Subject: [PATCH 0462/1483] N630-009-forward_p_x: fix regexp formatting Escape file paths, as they may contain special regexp sequences, like backslashes on Windows. --- testsuite/tests/N630-009-forward_p_x/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/N630-009-forward_p_x/test.py b/testsuite/tests/N630-009-forward_p_x/test.py index 5a6eaba3d..bf2ae976e 100644 --- a/testsuite/tests/N630-009-forward_p_x/test.py +++ b/testsuite/tests/N630-009-forward_p_x/test.py @@ -24,7 +24,7 @@ xcovargs = ['-P', gpr, '-v', program_path] + xargs p = xrun(xcovargs) -for arg in xargs + ["'-P' '*%s'" % gpr]: +for arg in xargs + ["'-P' '*%s'" % re.escape(gpr)]: thistest.fail_if( not re.search('gnatemu.*%s' % arg, p.out), 'couldn\'t find "%s" on the gnatemu command line out of %s' % From f65d3c01b6fa00c4499648786429aee36f97716a Mon Sep 17 00:00:00 2001 From: bortolussi Date: Fri, 13 Oct 2023 17:02:12 +0200 Subject: [PATCH 0463/1483] Update the logo in the docs Update the logo and the background color in top left corner of the docs. eng/cov/gnatcoverage#139 --- doc/adacore-logo-white.png | Bin 0 -> 39317 bytes doc/conf.py | 6 ++++-- 2 files changed, 4 insertions(+), 2 deletions(-) create mode 100644 doc/adacore-logo-white.png diff --git a/doc/adacore-logo-white.png b/doc/adacore-logo-white.png new file mode 100644 index 0000000000000000000000000000000000000000..115c90f74bd0be37469a8d4395018c0feb28d3ad GIT binary patch literal 39317 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 Date: Thu, 19 Oct 2023 16:59:01 +0200 Subject: [PATCH 0464/1483] clang-wrapper.cc: add a safety net for clang_getCalleeName If the declaration returned by getCalleeDecl is NULL, return an empty string conservatively to avoid any NULL dereferencing. --- tools/gnatcov/clang-wrapper.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index c4aa9d4be..f464c32a7 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -481,6 +481,8 @@ clang_getCalleeName (CXCursor C) { const clang::CallExpr *CE = cast (E); const Decl *D = CE->getCalleeDecl (); + if (!D) + return createEmpty (); auto getFunctionDeclName = [] (const FunctionDecl *FD) { const DeclarationName FunctionName = FD->getNameInfo ().getName (); From a80b81d75b1d4d397c43782a2864b1c68681c6b9 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 19 Oct 2023 17:23:31 +0200 Subject: [PATCH 0465/1483] Instrument.C: fix call to Import_Options The Analysis_Options record stores the list of options useful for preprocessing purposes, among them being a mapping of units to compiler switches (that can alter the preprocessing). This mapping maps the original source filename to its list of compiler switches, and not the preprocessed filename. Fix it to pass the former instead of the latter. --- .../main.c | 9 +++++ .../test.py | 38 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 2 +- 3 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/main.c create mode 100644 testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py diff --git a/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/main.c b/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/main.c new file mode 100644 index 000000000..10db6f9ee --- /dev/null +++ b/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/main.c @@ -0,0 +1,9 @@ +#ifdef MAIN +int +main (int argc, char **argv) +{ + int a = 0; + /* GNATCOV_DUMP_BUFFERS */ + return a; +} +#endif diff --git a/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py b/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py new file mode 100644 index 000000000..f39a6c277 --- /dev/null +++ b/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py @@ -0,0 +1,38 @@ +""" +Check that we consider unit-specific compiler switches (that have an effect on +the preprocessing) when using the manual dump-trigger. We used to ignore them. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +prj = gprfor( + prjid="main", + srcdirs=[".."], + mains=["main.c"], + main_cargs=["-DMAIN=1"], +) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--dump-trigger=manual"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "*.xcov", + { + "main.c.xcov": {"+": {5}, "-": {7}}, + }, + "xcov", +) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index fc5f4cbeb..3363e7af5 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3823,7 +3823,7 @@ package body Instrument.C is -- Preprocess the source, keeping the comment to look for the manual -- dump indication later. - Import_Options (Options, Self, Prj, To_String (PP_Filename)); + Import_Options (Options, Self, Prj, Orig_Filename); Preprocess_Source (Orig_Filename, Self, Prj, PP_Filename, Options, True); From 875e370b16514bbadd03834ef3dfbeafdbc0cdae Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 19 Oct 2023 17:38:14 +0200 Subject: [PATCH 0466/1483] Instrument.C: fix manual dump-trigger we used to have mismatching coverage obligations between the step recording preprocessing information and the step instrumenting because we were missing standard preprocessor search paths when parsing the source file in the former step. For recall, to record preprocessing information, we parse the unpreprocessed file with clang, and we inhibit builtin macros, as well as standard compiler headers to fully mimick the behavior of the preprocessor _in use_ (e.g. gcc). This means that if we are missing part of that configuration, which was the case there, we end up with an ill-formed AST. This results in wrong coverage obligations for the step recording preprocessing information. --- .../141-trigger-manual-pp-search-path/main.c | 9 ++++ .../141-trigger-manual-pp-search-path/test.py | 47 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 8 ++-- tools/gnatcov/instrument-ada_unit.ads | 8 ++-- tools/gnatcov/instrument-c.adb | 35 ++++++++++---- tools/gnatcov/instrument-c.ads | 12 ++--- tools/gnatcov/instrument-common.ads | 8 ++-- tools/gnatcov/instrument-projects.adb | 10 ++-- 8 files changed, 106 insertions(+), 31 deletions(-) create mode 100644 testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/main.c create mode 100644 testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py diff --git a/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/main.c b/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/main.c new file mode 100644 index 000000000..77d01c9d7 --- /dev/null +++ b/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/main.c @@ -0,0 +1,9 @@ +#include + +int +main (int argc, char **argv) +{ + size_t a = (size_t) 0; + /* GNATCOV_DUMP_BUFFERS */ + return a; +} diff --git a/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py b/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py new file mode 100644 index 000000000..7aaba2456 --- /dev/null +++ b/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py @@ -0,0 +1,47 @@ +""" +Regression testcase: when using the manual dump-trigger, we used to have +mismatching coverage obligations between the step recording preprocessing +information and the step instrumenting. That was because we were missing +standard preprocessor search paths when parsing the source file in the former +step + +As a reminder, to record preprocessing information, we parse the unpreprocessed +file with clang, and we inhibit builtin macros, as well as standard compiler +headers to fully mimick the behavior of the preprocessor _in use_ (e.g. gcc). +This means that if we are missing part of that configuration, which was the +case there, we end up with an ill-formed AST. This results in wrong coverage +obligations for the step recording preprocessing information. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +prj = gprfor( + prjid="main", + srcdirs=[".."], + mains=["main.c"], +) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--dump-trigger=manual"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "*.xcov", + { + "main.c.xcov": {"+": {6}, "-": {8}}, + }, + "xcov", +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 8cd23981e..a00ae5296 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -7913,10 +7913,10 @@ package body Instrument.Ada_Unit is ------------------------------------ overriding procedure Replace_Manual_Dump_Indication - (Self : in out Ada_Instrumenter_Type; - Done : in out Boolean; - Prj : Prj_Desc; - Source : GNATCOLL.Projects.File_Info) + (Self : in out Ada_Instrumenter_Type; + Done : in out Boolean; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info) is Instrumented_Filename : constant String := +(Prj.Output_Dir & "/" & GNATCOLL.VFS."+" (Source.File.Base_Name)); diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 9465f8474..c6267a7e0 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -83,10 +83,10 @@ package Instrument.Ada_Unit is Prj : Prj_Desc); overriding procedure Replace_Manual_Dump_Indication - (Self : in out Ada_Instrumenter_Type; - Done : in out Boolean; - Prj : Prj_Desc; - Source : GNATCOLL.Projects.File_Info); + (Self : in out Ada_Instrumenter_Type; + Done : in out Boolean; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info); -- Once the instrumentation has finished, if the dump trigger is "manual" -- we expect the user to have indicated the place where a call to the -- manual dump buffers procedure should be inserted by the pragma diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 3363e7af5..76e6ee5fb 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3771,7 +3771,7 @@ package body Instrument.C is -- Emit_Dump_Helper_Unit_Manual -- ---------------------------------- - procedure Emit_Dump_Helper_Unit_Manual + overriding procedure Emit_Dump_Helper_Unit_Manual (Self : in out C_Family_Instrumenter_Type; Helper_Unit : out US.Unbounded_String; Dump_Config : Any_Dump_Config; @@ -3795,14 +3795,14 @@ package body Instrument.C is -- Replace_Manual_Dump_Indication -- ------------------------------------ - procedure Replace_Manual_Dump_Indication - (Self : in out C_Family_Instrumenter_Type; - Done : in out Boolean; - Prj : Prj_Desc; - Source : GNATCOLL.Projects.File_Info) + overriding procedure Replace_Manual_Dump_Indication + (Self : in out C_Family_Instrumenter_Type; + Done : in out Boolean; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info) is - Orig_Filename : constant String := - GNATCOLL.VFS."+" (Source.File.Full_Name); + use GNATCOLL.VFS; + Orig_Filename : constant String := +Source.File.Full_Name; begin Check_Compiler_Driver (Prj, Self); @@ -3826,6 +3826,25 @@ package body Instrument.C is Import_Options (Options, Self, Prj, Orig_Filename); Preprocess_Source (Orig_Filename, Self, Prj, PP_Filename, Options, True); + declare + use String_Vectors_Maps; + Cur : Cursor; + Inserted : Boolean; + begin + -- We need to save the search paths that were used to preprocess + -- the file, as they must be passed on to clang parsing + -- invocations (especially when we are parsing the original file + -- to record preprocessing information). + + for Path of Options.PP_Search_Path loop + Prj.Compiler_Options_Unit.Insert + (Key => +(+Source.File.Full_Name), + New_Item => String_Vectors.Empty_Vector, + Position => Cur, + Inserted => Inserted); + Prj.Compiler_Options_Unit.Reference (Cur).Append ("-I" & Path); + end loop; + end; -- Look for the manual dump indication in the preprocessed file diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index a50fb5bc9..fda70e1c4 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -54,11 +54,11 @@ package Instrument.C is Dump_Config : Any_Dump_Config; Prj : Prj_Desc); - procedure Replace_Manual_Dump_Indication - (Self : in out C_Family_Instrumenter_Type; - Done : in out Boolean; - Prj : Prj_Desc; - Source : GNATCOLL.Projects.File_Info); + overriding procedure Replace_Manual_Dump_Indication + (Self : in out C_Family_Instrumenter_Type; + Done : in out Boolean; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info); -- Preprocess Source and look through the text content of the preprocessed -- file looking for manual dump indications. The C-like languages, the -- expected indication is the comment alone on its line: @@ -69,7 +69,7 @@ package Instrument.C is -- by a call to the manual dump procedure and an extern declaration for the -- procedure is put at the beginning of the file. - procedure Emit_Dump_Helper_Unit_Manual + overriding procedure Emit_Dump_Helper_Unit_Manual (Self : in out C_Family_Instrumenter_Type; Helper_Unit : out US.Unbounded_String; Dump_Config : Any_Dump_Config; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 336f8b249..2c4a53a43 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -487,10 +487,10 @@ package Instrument.Common is -- the instrumented source files. procedure Replace_Manual_Dump_Indication - (Self : in out Language_Instrumenter; - Done : in out Boolean; - Prj : Prj_Desc; - Source : GNATCOLL.Projects.File_Info) is null; + (Self : in out Language_Instrumenter; + Done : in out Boolean; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info) is null; -- Look for the pragma (for Ada) or comment (for C family languages) -- indicating where the user wishes to the buffers to be dumped in Source. -- When found, replace it with a call to the buffers dump procedure defined diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index f8b292f00..626a4783b 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -849,8 +849,9 @@ is declare use Prj_Has_Manual_Helper_Sets; - Prj : constant Prj_Desc := - Get_Or_Create_Project_Info (IC, Source.Project).Desc; + Prj_Info : constant Project_Info_Access := + Get_Or_Create_Project_Info (IC, Source.Project); + Prj : Prj_Desc renames Prj_Info.Desc; Is_Root_Prj : constant Boolean := Prj.Prj_Name = Root_Project_Info.Project.Name; Source_Name : constant String := @@ -859,10 +860,9 @@ is Contained_Indication : Boolean := False; begin - Instrumenter.Replace_Manual_Dump_Indication (Contained_Indication, - Prj, + Prj_Info.Desc, Source); if Contained_Indication and then not Is_Root_Prj @@ -1244,7 +1244,7 @@ begin -- According to the set parallelism level, instrument in -- the same process (thus reusing the libadalang context, which - -- is a big gain of time), or spawn another instrmentation + -- is a big gain of time), or spawn another instrumentation -- process. if Parallelism_Level = 1 then From 1952ae72d7f891fc13944b646de6ecc8f48c02a7 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 19 Oct 2023 17:44:06 +0200 Subject: [PATCH 0467/1483] minor refactoring --- tools/gnatcov/instrument-c.adb | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 76e6ee5fb..48e456044 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -92,8 +92,8 @@ package body Instrument.C is PP_Filename : out Unbounded_String; Options : in out Analysis_Options; Keep_Comments : Boolean := False); - -- Preprocess the source at Filename and extend Options using the - -- preprocessor output. + -- Preprocess the source at Filename and extend Options using the Prj and + -- the preprocessor output to retrieve standard search paths. -- -- This uses the compiler in the Compiler_Driver project attribute to -- preprocess the file, assuming that it accepts the -E flag, to preprocess @@ -2562,6 +2562,7 @@ package body Instrument.C is -- File containing the preprocessor output (used to get include search -- paths). begin + Import_Options (Options, Instrumenter, Prj, Filename); PP_Filename := +New_File (Prj, Filename); -- If the preprocessed output file already exists, consider that it was @@ -2730,8 +2731,6 @@ package body Instrument.C is Options : Analysis_Options; Args : String_Vectors.Vector; begin - Import_Options (Options, Instrumenter, Prj, Filename); - Preprocess_Source (Filename, Instrumenter, @@ -2970,10 +2969,9 @@ package body Instrument.C is UIC.Buffer_Unit := CU_Name_For_File (+Buffer_Filename); UIC.Files_Of_Interest := Files_Of_Interest; - -- Import analysis options for the file to preprocess, then run the - -- preprocessor. + -- Run the preprocessor (this also takes care of importing the + -- preprocessor options into UIC.Options). - Import_Options (UIC.Options, Self, Prj, Unit_Name); Preprocess_Source (Orig_Filename, Self, Prj, PP_Filename, UIC.Options); -- Start by recording preprocessing information @@ -3823,7 +3821,6 @@ package body Instrument.C is -- Preprocess the source, keeping the comment to look for the manual -- dump indication later. - Import_Options (Options, Self, Prj, Orig_Filename); Preprocess_Source (Orig_Filename, Self, Prj, PP_Filename, Options, True); declare From 7de24b5c691c0adcfa2906be4089c1b1d3622791 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 5 Oct 2023 12:57:51 +0200 Subject: [PATCH 0468/1483] Fix handling of lambda expressions When retrieving the lambda expressions inside a clang cursor, we were traversing recursively all the nodes in the cursor subtree. In addition to being very inefficient, this resulted in lambda expressions being processed multiple times. To fix this, we integrate the processing of lambda expression to the processing of decisions, similarly to what is done to process declare expressions in Ada. --- .../AandB/Lambda_Robustness/src/tryme.cpp | 37 + .../mcdc/AandB/Lambda_Robustness/src/tryme.hh | 2 + .../C++/mcdc/AandB/Lambda_Robustness/test.py | 11 + tools/gnatcov/instrument-c.adb | 647 +++++++++--------- tools/gnatcov/instrument-c_utils.adb | 31 - tools/gnatcov/instrument-c_utils.ads | 4 - 6 files changed, 392 insertions(+), 340 deletions(-) create mode 100644 testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp create mode 100644 testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.hh create mode 100644 testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/test.py diff --git a/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp new file mode 100644 index 000000000..8ec878d79 --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp @@ -0,0 +1,37 @@ +void +tryme (bool aa, bool bb, bool skip) +{ + if (skip) // # test_skip + return; // # skip + + // A lambda function in a compound statement + { + auto InCompound = [] (int aa, int bb) { // # other + if (aa > 0 && bb > 0) // # eval :o/d: + return true; // # lambda_true + else // # lambda_other + return false; // # lambda_false + }; // # lambda_other + volatile bool a = InCompound (aa, bb); // # other + } + + // A lambda function in a for statement + int i = 0; // # other + for (; i++ < 1;) // # other + [] (int aa, int bb) { // # other + if (aa > 0 && bb > 0) // # eval :o/d: + return true; // # lambda_true + else // # lambda_other + return false; // # lambda_false + } (aa, bb); // # lambda_other + + // A nested lambda + [] (int aa, int bb) { // # other + [] (int aa, int bb) { // # other + if (aa > 0 && bb > 0) // # eval :o/d: + return true; // # lambda_true + else // # lambda_other + return false; // # lambda_false + } (aa, bb); // # lambda_other + } (aa, bb); // # lambda_other +} diff --git a/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.hh b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.hh new file mode 100644 index 000000000..c3be505cd --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.hh @@ -0,0 +1,2 @@ +// No need of anything here. File needed to allow reference +// from expectations, still. diff --git a/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/test.py b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/test.py new file mode 100644 index 000000000..6723f353a --- /dev/null +++ b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/test.py @@ -0,0 +1,11 @@ +""" +Regression / robustness test case: we use to implement spuriously source +coverage obligations inside lambda expressions. Check that we correctly +instrument lambda expressions in various contexts. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 48e456044..7e9781a3f 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -1424,12 +1424,11 @@ package body Instrument.C is L : Cursor_Vectors.Vector); -- Traverse a translation unit (top level declarations) - procedure Process_Decisions + procedure Process_Expression (UIC : in out C_Unit_Inst_Context; N : Cursor_T; T : Character); - -- If N is Empty, has no effect. Otherwise scans the tree for the node N, - -- to output any decisions it contains. + -- Process the decisions, and the lambda expressions in N -------------------------- -- Internal Subprograms -- @@ -1466,325 +1465,367 @@ package body Instrument.C is end if; end Is_Complex_Decision; - ----------------------- - -- Process_Decisions -- - ----------------------- + ------------------------ + -- Process_Expression -- + ------------------------ - procedure Process_Decisions + procedure Process_Expression (UIC : in out C_Unit_Inst_Context; N : Cursor_T; T : Character) is - Mark : Nat; - -- This is used to mark the location of a decision sequence in the SCO - -- table. We use it for backing out a simple decision in an expression - -- context that contains only NOT operators. - - Mark_Hash : Nat; - -- Likewise for the putative SCO_Raw_Hash_Table entries: see below - - type Hash_Entry is record - Sloc : Source_Location; - SCO_Index : Nat; - end record; - -- We must register all conditions/pragmas in SCO_Raw_Hash_Table. - -- However we cannot register them at the same time we are adding the - -- corresponding SCO entries to the raw table since we may discard them - -- later on. So instead we put all putative conditions into Hash_Entries - -- (see below) and register them once we are sure we keep them. - -- - -- This data structure holds the conditions/pragmas to register in - -- SCO_Raw_Hash_Table. - - package Hash_Entries is new Table.Table - (Table_Component_Type => Hash_Entry, - Table_Index_Type => Nat, - Table_Low_Bound => 1, - Table_Initial => 10, - Table_Increment => 10, - Table_Name => "Hash_Entries"); - -- Hold temporarily (i.e. free'd before returning) the Hash_Entry before - -- they are registered in SCO_Raw_Hash_Table. - - --------------------------------- - -- Decision-specific variables -- - --------------------------------- - - -- The following variables are related to the current decision being - -- processed by this call to Process_Decisions. Note that in the case - -- of nested decisions, this subprogram recurses, so we do not have to - -- worry about overwriting them. - - Current_Decision : Nat; - -- Low level SCO id of current decision - - X_Not_Decision : Boolean; - -- This flag keeps track of whether a decision sequence in the SCO table - -- contains only NOT operators, and is for an expression context (T=X). - -- The flag will be set False if T is other than X, or if an operator - -- other than NOT is in the sequence. - - Condition_Count : Natural := 0; - -- Count of conditions for current decision (MC/DC only) - - MCDC_State : US.Unbounded_String; - -- Name of MC/DC state local variable for current decision (MC/DC only) - - procedure Output_Decision_Operand (Operand : Cursor_T); - -- The node Operand is the top level logical operator of a decision, or - -- it is one of the operands of a logical operator belonging to a single - -- complex decision. This (recursive) routine outputs the sequence of - -- table entries corresponding to the node. Note that we do not process - -- the sub- operands to look for further decisions, that processing is - -- done in Find_Nested_Decisions, because we can't get decisions mixed - -- up in the global table. Call has no effect if Operand is Empty. - -- Increments Condition_Count (recursively) for each condition. - - procedure Output_Element (N : Cursor_T); - -- Node N is an operand of a logical operator that is not itself a - -- logical operator, or it is a simple decision. This routine outputs - -- the table entry for the element, with C1 set to ' '. Last is set - -- False, and an entry is made in the condition hash table. - - procedure Output_Header (T : Character; N : Cursor_T); - -- Outputs a decision header node. T is I/W/E/P for IF/WHILE/EXIT WHEN/ - -- PRAGMA, and 'X' for the expression case. Resets Condition_Count to 0, - -- and initializes MCDC_State. - - procedure Find_Nested_Decisions (Operand : Cursor_T); - -- This is called on node Operand, the top level node of a decision, - -- or on one of its operands or suboperands after generating the full - -- output for the complex decision. It process the suboperands of the - -- decision looking for nested decisions. - - function Process_Node (N : Cursor_T) return Child_Visit_Result_T; - -- Processes one node in the traversal, looking for logical operators, - -- and if one is found, outputs the appropriate table entries. - - ----------------------------- - -- Output_Decision_Operand -- - ----------------------------- - - procedure Output_Decision_Operand (Operand : Cursor_T) is - C1 : Character; - C2 : Character; - -- C1 holds a character that identifies the operation while C2 - -- indicates whether we are sure (' ') or not ('?') this operation - -- belongs to the decision. '?' entries will be filtered out in the - -- second (SCO_Record_Filtered) pass. - - N : constant Cursor_T := Unwrap (Operand); - - L, R : Cursor_T; - - Op_N : constant String := Get_Opcode_Str (N); - + function Process_Lambda_Expr + (Cursor : Cursor_T) return Child_Visit_Result_T; + -- Helper for Visit_Children. Process every lambda expr under Cursor, + -- _but_ the lambda expressions nested in other lambda expressions. + + procedure Process_Decisions + (UIC : in out C_Unit_Inst_Context; + N : Cursor_T; + T : Character); + + ------------------------- + -- Process_Lambda_Expr -- + ------------------------- + + function Process_Lambda_Expr + (Cursor : Cursor_T) return Child_Visit_Result_T is begin + if Kind (Cursor) = Cursor_Lambda_Expr then + Traverse_Declarations + (UIC => UIC, + L => Cursor_Vectors.To_Vector (Cursor, 1)); + return Child_Visit_Continue; + end if; + return Child_Visit_Recurse; + end Process_Lambda_Expr; - -- Logical operator + ----------------------- + -- Process_Decisions -- + ----------------------- - if Is_Logical_Operator (N) then - if Op_N = "!" then - C1 := '!'; - L := Get_Null_Cursor; - R := Get_Sub_Expr (N); + procedure Process_Decisions + (UIC : in out C_Unit_Inst_Context; + N : Cursor_T; + T : Character) + is + Mark : Nat; + -- This is used to mark the location of a decision sequence in the + -- SCO table. We use it for backing out a simple decision in an + -- expression context that contains only NOT operators. + + Mark_Hash : Nat; + -- Likewise for the putative SCO_Raw_Hash_Table entries: see below + + type Hash_Entry is record + Sloc : Source_Location; + SCO_Index : Nat; + end record; + -- We must register all conditions/pragmas in SCO_Raw_Hash_Table. + -- However we cannot register them at the same time we are adding the + -- corresponding SCO entries to the raw table since we may discard + -- them later on. So instead we put all putative conditions into + -- Hash_Entries (see below) and register them once we are sure we + -- keep them. + -- + -- This data structure holds the conditions/pragmas to register in + -- SCO_Raw_Hash_Table. + + package Hash_Entries is new Table.Table + (Table_Component_Type => Hash_Entry, + Table_Index_Type => Nat, + Table_Low_Bound => 1, + Table_Initial => 10, + Table_Increment => 10, + Table_Name => "Hash_Entries"); + -- Hold temporarily (i.e. free'd before returning) the Hash_Entry + -- before they are registered in SCO_Raw_Hash_Table. + + --------------------------------- + -- Decision-specific variables -- + --------------------------------- + + -- The following variables are related to the current decision being + -- processed by this call to Process_Decisions. Note that in the case + -- of nested decisions, this subprogram recurses, so we do not have + -- to worry about overwriting them. + + Current_Decision : Nat; + -- Low level SCO id of current decision + + X_Not_Decision : Boolean; + -- This flag keeps track of whether a decision sequence in the + -- SCO table contains only NOT operators, and is for an expression + -- context (T=X). The flag will be set False if T is other than X, + -- or if an operator other than NOT is in the sequence. + + Condition_Count : Natural := 0; + -- Count of conditions for current decision (MC/DC only) + + MCDC_State : US.Unbounded_String; + -- Name of MC/DC state local variable for current decision (MC/DC + -- only). + + procedure Output_Decision_Operand (Operand : Cursor_T); + -- The node Operand is the top level logical operator of a decision, + -- or it is one of the operands of a logical operator belonging to + -- a single complex decision. This (recursive) routine outputs the + -- sequence of table entries corresponding to the node. Note that we + -- do not process the sub- operands to look for further decisions, + -- that processing is done in Find_Nested_Decisions, because we can't + -- get decisions mixed up in the global table. Call has no effect + -- if Operand is Empty. Increments Condition_Count (recursively) + -- for each condition. + + procedure Output_Element (N : Cursor_T); + -- Node N is an operand of a logical operator that is not itself a + -- logical operator, or it is a simple decision. This routine outputs + -- the table entry for the element, with C1 set to ' '. Last is set + -- False, and an entry is made in the condition hash table. + + procedure Output_Header (T : Character; N : Cursor_T); + -- Outputs a decision header node. T is I/W/E/P for IF/WHILE/EXIT + -- WHEN/ PRAGMA, and 'X' for the expression case. Resets + -- Condition_Count to 0, and initializes MCDC_State. + + procedure Find_Nested_Decisions (Operand : Cursor_T); + -- This is called on node Operand, the top level node of a decision, + -- or on one of its operands or suboperands after generating the full + -- output for the complex decision. It process the suboperands of the + -- decision looking for nested decisions. + + function Process_Node (N : Cursor_T) return Child_Visit_Result_T; + -- Processes one node in the traversal, looking for logical + -- operators, and if one is found, outputs the appropriate + -- table entries. + + ----------------------------- + -- Output_Decision_Operand -- + ----------------------------- + + procedure Output_Decision_Operand (Operand : Cursor_T) is + C1 : Character; + C2 : Character; + -- C1 holds a character that identifies the operation while C2 + -- indicates whether we are sure (' ') or not ('?') this operation + -- belongs to the decision. '?' entries will be filtered out in + -- the second (SCO_Record_Filtered) pass. + + N : constant Cursor_T := Unwrap (Operand); + + L, R : Cursor_T; + + Op_N : constant String := Get_Opcode_Str (N); - else - -- N is a binary logical operator + begin + + -- Logical operator + + if Is_Logical_Operator (N) then + if Op_N = "!" then + C1 := '!'; + L := Get_Null_Cursor; + R := Get_Sub_Expr (N); - L := Get_LHS (N); - R := Get_RHS (N); - if Op_N = "||" then - C1 := '|'; else - pragma Assert (Op_N = "&&"); - C1 := '&'; + -- N is a binary logical operator + + L := Get_LHS (N); + R := Get_RHS (N); + if Op_N = "||" then + C1 := '|'; + else + pragma Assert (Op_N = "&&"); + C1 := '&'; + end if; end if; - end if; - C2 := ' '; + C2 := ' '; - UIC.Pass.Append_SCO - (UIC => UIC, - N => N, - C1 => C1, - C2 => C2, - From => Sloc (Get_Operator_Loc (N)), - To => Slocs.No_Location, - Last => False); + UIC.Pass.Append_SCO + (UIC => UIC, + N => N, + C1 => C1, + C2 => C2, + From => Sloc (Get_Operator_Loc (N)), + To => Slocs.No_Location, + Last => False); - Hash_Entries.Append ((Sloc => Start_Sloc (N), - SCO_Index => SCOs.SCO_Table.Last)); + Hash_Entries.Append ((Sloc => Start_Sloc (N), + SCO_Index => SCOs.SCO_Table.Last)); - if not Is_Null (L) then - Output_Decision_Operand (L); - end if; - Output_Decision_Operand (R); + if not Is_Null (L) then + Output_Decision_Operand (L); + end if; + Output_Decision_Operand (R); - -- Not a logical operator -> condition + -- Not a logical operator -> condition - else - Output_Element (N); + else + Output_Element (N); - if MCDC_Coverage_Enabled then - UIC.Pass.Instrument_Condition - (UIC => UIC, - LL_SCO => SCOs.SCO_Table.Last, - Condition => N, - State => MCDC_State, - First => Condition_Count = 0); + if MCDC_Coverage_Enabled then + UIC.Pass.Instrument_Condition + (UIC => UIC, + LL_SCO => SCOs.SCO_Table.Last, + Condition => N, + State => MCDC_State, + First => Condition_Count = 0); - Condition_Count := Condition_Count + 1; + Condition_Count := Condition_Count + 1; + end if; end if; - end if; - end Output_Decision_Operand; + end Output_Decision_Operand; - -------------------- - -- Output_Element -- - -------------------- + -------------------- + -- Output_Element -- + -------------------- - procedure Output_Element (N : Cursor_T) is - begin - UIC.Pass.Append_SCO - (UIC => UIC, - N => N, - C1 => ' ', - C2 => 'c', - From => Start_Sloc (N), - To => End_Sloc (N), - Last => False); - Hash_Entries.Append ((Start_Sloc (N), SCOs.SCO_Table.Last)); - end Output_Element; - - ------------------- - -- Output_Header -- - ------------------- - - procedure Output_Header (T : Character; N : Cursor_T) is - begin - UIC.Pass.Append_SCO - (UIC => UIC, - N => N, - C1 => T, - C2 => ' ', - From => Start_Sloc (N), - To => End_Sloc (N), - Last => False); + procedure Output_Element (N : Cursor_T) is + begin + UIC.Pass.Append_SCO + (UIC => UIC, + N => N, + C1 => ' ', + C2 => 'c', + From => Start_Sloc (N), + To => End_Sloc (N), + Last => False); + Hash_Entries.Append ((Start_Sloc (N), SCOs.SCO_Table.Last)); + end Output_Element; - Current_Decision := SCOs.SCO_Table.Last; + ------------------- + -- Output_Header -- + ------------------- - if Coverage.Enabled (Coverage_Options.Decision) - or else MCDC_Coverage_Enabled - then - if MCDC_Coverage_Enabled then - Condition_Count := 0; + procedure Output_Header (T : Character; N : Cursor_T) is + begin + UIC.Pass.Append_SCO + (UIC => UIC, + N => N, + C1 => T, + C2 => ' ', + From => Start_Sloc (N), + To => End_Sloc (N), + Last => False); + + Current_Decision := SCOs.SCO_Table.Last; - UIC.Pass.Insert_MCDC_State - (UIC, Make_MCDC_State_Name (SCOs.SCO_Table.Last), MCDC_State); + if Coverage.Enabled (Coverage_Options.Decision) + or else MCDC_Coverage_Enabled + then + if MCDC_Coverage_Enabled then + Condition_Count := 0; + + UIC.Pass.Insert_MCDC_State + (UIC, + Make_MCDC_State_Name (SCOs.SCO_Table.Last), + MCDC_State); + end if; + + UIC.Pass.Instrument_Decision + (UIC => UIC, + LL_SCO => Current_Decision, + Decision => N, + State => MCDC_State); end if; - UIC.Pass.Instrument_Decision - (UIC => UIC, - LL_SCO => Current_Decision, - Decision => N, - State => MCDC_State); - end if; + end Output_Header; - end Output_Header; + --------------------------- + -- Find_Nested_Decisions -- + --------------------------- - --------------------------- - -- Find_Nested_Decisions -- - --------------------------- + procedure Find_Nested_Decisions (Operand : Cursor_T) is + N : constant Cursor_T := Unwrap (Operand); + begin + if Is_Logical_Operator (N) then - procedure Find_Nested_Decisions (Operand : Cursor_T) is - N : constant Cursor_T := Unwrap (Operand); - begin - if Is_Logical_Operator (N) then + if Kind (N) = Cursor_Unary_Operator then + Find_Nested_Decisions (Get_Sub_Expr (N)); - if Kind (N) = Cursor_Unary_Operator then - Find_Nested_Decisions (Get_Sub_Expr (N)); + else + Find_Nested_Decisions (Get_LHS (N)); + Find_Nested_Decisions (Get_RHS (N)); + X_Not_Decision := False; + end if; else - Find_Nested_Decisions (Get_LHS (N)); - Find_Nested_Decisions (Get_RHS (N)); - X_Not_Decision := False; + Process_Decisions (UIC, N, 'X'); end if; + end Find_Nested_Decisions; - else - Process_Decisions (UIC, N, 'X'); - end if; - end Find_Nested_Decisions; - - ------------------ - -- Process_Node -- - ------------------ + ------------------ + -- Process_Node -- + ------------------ - function Process_Node (N : Cursor_T) return Child_Visit_Result_T is - -- Test for the two cases where N is the root node of some decision: + function Process_Node (N : Cursor_T) return Child_Visit_Result_T is + -- Test for the two cases where N is the root node of some + -- decision: - Decision_Root : constant Boolean := + Decision_Root : constant Boolean := - -- Simple decision at outer level: a boolean expression (which is - -- not a logical operator) appearing as the operand of an IF, - -- WHILE, FOR construct. + -- Simple decision at outer level: a boolean expression (which + -- is not a logical operator) appearing as the operand of an + -- IF, WHILE, FOR construct. - (N = Process_Decisions.N and then T /= 'X') - or else + (N = Process_Decisions.N and then T /= 'X') + or else - -- Complex decision, whether at outer level or nested: a boolean - -- expression involving a logical operator. + -- Complex decision, whether at outer level or nested: a + -- boolean expression involving a logical operator. - Is_Complex_Decision (N); + Is_Complex_Decision (N); - begin - if Decision_Root then - declare - T : Character; + begin + if Decision_Root then + declare + T : Character; - begin - -- If outer level, then type comes from call, otherwise it - -- is more deeply nested and counts as X for expression. + begin + -- If outer level, then type comes from call, otherwise it + -- is more deeply nested and counts as X for expression. - if N = Process_Decisions.N then - T := Process_Decisions.T; - else - T := 'X'; - end if; + if N = Process_Decisions.N then + T := Process_Decisions.T; + else + T := 'X'; + end if; - -- Output header for sequence + -- Output header for sequence - X_Not_Decision := T = 'X' and then Get_Opcode_Str (N) = "!"; - Mark := SCOs.SCO_Table.Last; - Mark_Hash := Hash_Entries.Last; - Output_Header (T, N); + X_Not_Decision := T = 'X' and then Get_Opcode_Str (N) = "!"; + Mark := SCOs.SCO_Table.Last; + Mark_Hash := Hash_Entries.Last; + Output_Header (T, N); - -- Output the decision (recursively traversing operands) + -- Output the decision (recursively traversing operands) - Output_Decision_Operand (N); + Output_Decision_Operand (N); - -- If the decision was in an expression context (T = 'X') - -- and contained only NOT operators, then we do not output - -- it, so delete the associated SCO entries. As a consequence, - -- no instrumentation will be emitted. + -- If the decision was in an expression context (T = + -- 'X') and contained only NOT operators, then we do not + -- output it, so delete the associated SCO entries. As a + -- consequence, no instrumentation will be emitted. - if X_Not_Decision then - SCOs.SCO_Table.Set_Last (Mark); - Hash_Entries.Set_Last (Mark_Hash); + if X_Not_Decision then + SCOs.SCO_Table.Set_Last (Mark); + Hash_Entries.Set_Last (Mark_Hash); - -- Otherwise, set Last in last table entry to mark end + -- Otherwise, set Last in last table entry to mark end - else - SCOs.SCO_Table.Table (SCOs.SCO_Table.Last).Last := True; - end if; + else + SCOs.SCO_Table.Table (SCOs.SCO_Table.Last).Last := True; + end if; - -- Process any embedded decisions + -- Process any embedded decisions - Find_Nested_Decisions (N); - return Child_Visit_Continue; - end; - end if; + Find_Nested_Decisions (N); + return Child_Visit_Continue; + end; + end if; - case Kind (N) is + case Kind (N) is when Cursor_Conditional_Operator => declare Cond : constant Cursor_T := Get_Cond (N); @@ -1805,21 +1846,26 @@ package body Instrument.C is return Child_Visit_Continue; when others => null; - end case; + end case; - return Child_Visit_Recurse; - end Process_Node; + return Child_Visit_Recurse; + end Process_Node; + + -- Start of processing for Process_Decisions - -- Start of processing for Process_Decisions + begin + if Is_Null (N) then + return; + end if; + Hash_Entries.Init; + Visit (N, Process_Node'Access); + Hash_Entries.Free; + end Process_Decisions; begin - if Is_Null (N) then - return; - end if; - Hash_Entries.Init; - Visit (N, Process_Node'Access); - Hash_Entries.Free; - end Process_Decisions; + Process_Decisions (UIC, N, T); + Visit (N, Process_Lambda_Expr'Access); + end Process_Expression; ------------------ -- Has_Decision -- @@ -2004,7 +2050,7 @@ package body Instrument.C is & " statement."); UIC.Disable_Instrumentation := True; end if; - Process_Decisions (UIC, Get_Cond (N), 'I'); + Process_Expression (UIC, Get_Cond (N), 'I'); UIC.Disable_Instrumentation := Save_Disable_Instrumentation; Traverse_Statements (UIC, To_Vector (Then_Part), TB); @@ -2027,7 +2073,7 @@ package body Instrument.C is Switch_Cond : constant Cursor_T := Get_Cond (N); Alt : constant Cursor_T := Get_Body (N); begin - Process_Decisions (UIC, Switch_Cond, 'X'); + Process_Expression (UIC, Switch_Cond, 'X'); -- Process case branches @@ -2060,7 +2106,7 @@ package body Instrument.C is else Get_Var_Init_Expr (Cond_Var)), Instr_Scheme => Instr_Expr); - Process_Decisions (UIC, Cond, 'W'); + Process_Expression (UIC, Cond, 'W'); Traverse_Statements (UIC, To_Vector (While_Body), TB); end; @@ -2082,7 +2128,7 @@ package body Instrument.C is Instrument_Statement (Do_While, 'W', Instr_Scheme => Instr_Expr); - Process_Decisions (UIC, Do_While, 'W'); + Process_Expression (UIC, Do_While, 'W'); end; @@ -2101,7 +2147,7 @@ package body Instrument.C is -- The guard expression for the FOR loop is a decision. The -- closest match for this kind of decision is a while loop. - Process_Decisions (UIC, For_Cond, 'W'); + Process_Expression (UIC, For_Cond, 'W'); Traverse_Statements (UIC, To_Vector (For_Body), TB); @@ -2126,7 +2172,7 @@ package body Instrument.C is Instrument_Statement (For_Init_Stmt, ' ', Insertion_N => For_Init_Stmt); - Process_Decisions (UIC, For_Init_Stmt, 'X'); + Process_Expression (UIC, For_Init_Stmt, 'X'); -- Preemptively end the introduced outer scope as it is -- easier done when traversing the AST. @@ -2141,7 +2187,7 @@ package body Instrument.C is (For_Range_Decl, ' ', Insertion_N => N, Instr_Scheme => Instr_Stmt); - Process_Decisions (UIC, For_Range_Decl, 'X'); + Process_Expression (UIC, For_Range_Decl, 'X'); -- Generate obligations for body statements @@ -2174,7 +2220,7 @@ package body Instrument.C is then Instrument_Statement (N, ' '); if Has_Decision (N) then - Process_Decisions (UIC, N, 'X'); + Process_Expression (UIC, N, 'X'); end if; end if; @@ -2187,30 +2233,21 @@ package body Instrument.C is -- Process any embedded decisions - if Has_Decision (N) then - if Is_Constexpr (N) then - UIC.Pass.Report - (N, - "gnatcov limitation: cannot instrument constexpr" - & " variable declarations."); - UIC.Disable_Instrumentation := True; - Process_Decisions (UIC, N, 'X'); - UIC.Disable_Instrumentation := - Save_Disable_Instrumentation; - else - Process_Decisions (UIC, N, 'X'); - end if; + if Is_Constexpr (N) then + UIC.Pass.Report + (N, + "gnatcov limitation: cannot instrument constexpr" + & " variable declarations."); + UIC.Disable_Instrumentation := True; + Process_Expression (UIC, N, 'X'); + UIC.Disable_Instrumentation := + Save_Disable_Instrumentation; + else + Process_Expression (UIC, N, 'X'); end if; end case; Append (Trailing_Braces, TB); - - -- Traverse lambda expressions, if any. Do not register them as - -- scopes. - - Traverse_Declarations - (UIC => UIC, - L => Get_Lambda_Exprs (N)); end Traverse_One; -------------------------- diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index 361b6f220..88c72a30c 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -245,37 +245,6 @@ package body Instrument.C_Utils is return Res; end Get_Children; - ---------------------- - -- Get_Lambda_Exprs -- - ---------------------- - - function Get_Lambda_Exprs (N : Cursor_T) return Cursor_Vectors.Vector is - Res : Vector; - - function Process (Cursor : Cursor_T) return Child_Visit_Result_T; - -- Helper for Visit_Children. Add every lambda expr under Cursor to Res, - -- _but_ the lambda expressions nested in other lambda expressions. - - ------------- - -- Process -- - ------------- - - function Process (Cursor : Cursor_T) return Child_Visit_Result_T is - begin - if Kind (Cursor) = Cursor_Lambda_Expr then - Res.Append (Cursor); - return Child_Visit_Continue; - end if; - return Child_Visit_Recurse; - end Process; - - -- Start of processing for Get_Lambda_Exprs - - begin - Visit_Children (N, Process'Access); - return Res; - end Get_Lambda_Exprs; - --------------- -- To_Vector -- --------------- diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 616874546..af3f30e81 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -91,10 +91,6 @@ package Instrument.C_Utils is -- functions in clang-wrapper.cc and the associated ada bindings in the -- package clang-extensions. - function Get_Lambda_Exprs (N : Cursor_T) return Cursor_Vectors.Vector; - -- Return the lambda expressions in a node and its descendents if any, - -- except the lambda expressions nested in other lambda expressions. - function To_Vector (N : Cursor_T) return Cursor_Vectors.Vector; -- Turn the node N into a single element node vector From f637b9c0cd3fe136981b9de79bd72a6141f16232 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 23 Oct 2023 12:43:43 +0200 Subject: [PATCH 0469/1483] Fix regressions We have to pass the dump-trigger to the dump_trigger argument of the build_and_run function, instead of passing it as an extra instrumentation args through extra_instr_args, to have the right source trace name expectation. --- .../141-trigger-manual-pp-search-path/test.py | 11 +++-------- .../141-trigger-manual-pp-switch-in-prj/test.py | 16 +++++++--------- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py b/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py index 7aaba2456..1dfb57e36 100644 --- a/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py +++ b/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py @@ -21,17 +21,12 @@ tmp = Wdir("tmp_") -prj = gprfor( - prjid="main", - srcdirs=[".."], - mains=["main.c"], -) - build_run_and_coverage( - gprsw=GPRswitches(root_project=prj), + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), covlevel="stmt", mains=["main"], - extra_instr_args=["--dump-trigger=manual"], + dump_trigger="manual", + manual_prj_name="gen", extra_coverage_args=["-axcov", "--output-dir=xcov"], trace_mode="src", ) diff --git a/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py b/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py index f39a6c277..5cc76f804 100644 --- a/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py +++ b/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py @@ -11,18 +11,16 @@ tmp = Wdir("tmp_") -prj = gprfor( - prjid="main", - srcdirs=[".."], - mains=["main.c"], - main_cargs=["-DMAIN=1"], -) - build_run_and_coverage( - gprsw=GPRswitches(root_project=prj), + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=[".."], mains=["main.c"], main_cargs=["-DMAIN=1"] + ) + ), covlevel="stmt", mains=["main"], - extra_instr_args=["--dump-trigger=manual"], + dump_trigger="manual", + manual_prj_name="gen", extra_coverage_args=["-axcov", "--output-dir=xcov"], trace_mode="src", ) From 03df9745303771fc4d774f3c7d9bb2706066d9cc Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 23 Oct 2023 15:17:15 +0200 Subject: [PATCH 0470/1483] Instrument.C: do not yield "unknown warning" warnings gnatcov used to yield "unknown warning" warnings on warning switches not recognized by clang. Fix this by passing the "-Wno-unknown-warning-option" when parsing with clang. --- .../instr-cov/144-no-unknown-warning/main.c | 5 ++++ .../instr-cov/144-no-unknown-warning/test.py | 28 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 7 +++++ 3 files changed, 40 insertions(+) create mode 100644 testsuite/tests/instr-cov/144-no-unknown-warning/main.c create mode 100644 testsuite/tests/instr-cov/144-no-unknown-warning/test.py diff --git a/testsuite/tests/instr-cov/144-no-unknown-warning/main.c b/testsuite/tests/instr-cov/144-no-unknown-warning/main.c new file mode 100644 index 000000000..f3836d7ba --- /dev/null +++ b/testsuite/tests/instr-cov/144-no-unknown-warning/main.c @@ -0,0 +1,5 @@ +int +main (int argc, char **argv) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/144-no-unknown-warning/test.py b/testsuite/tests/instr-cov/144-no-unknown-warning/test.py new file mode 100644 index 000000000..424428270 --- /dev/null +++ b/testsuite/tests/instr-cov/144-no-unknown-warning/test.py @@ -0,0 +1,28 @@ +""" +Check that gnatcov does not yield "unknown warning warnings" when parsing a +file with warnings not recognized by clang. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=[".."], mains=["main.c"], main_cargs=["-Wtrampolines"] + ) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports("xcov/*.xcov", {"xcov/main.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 7e9781a3f..d8ceccc73 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2750,6 +2750,13 @@ package body Instrument.C is Append (Command_Line_Args, +"-x"); Append (Command_Line_Args, +To_Lower (Image (Lang))); + -- As we also pass compiler warning switches, as they can influence the + -- preprocessing through the use of the __has_warning macro, we make + -- sure to disable warnings on unknown warnings (as some warnings are + -- e.g. gcc-specific and won't be recognized by clang). + + Append (Command_Line_Args, +"-Wno-unknown-warning-option"); + return Command_Line_Args; end Common_Parse_TU_Args; From 3d6827c94c834f23c4711301b9456da83bc539f9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 25 Oct 2023 08:32:59 +0000 Subject: [PATCH 0471/1483] Various CI cleanups --- .gitlab-ci.yml | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a5539a4e1..392c96dd4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,11 +1,7 @@ -# This bit is used to make sure we don't run too many pipelines: -# don't run the branch CI when a merge request is already open for the -# branch. workflow: rules: - - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push" - when: never - - when: always + # Run the CI on merge requests only + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' variables: PACKAGE_BASE_NAME: gnatcoverage.tar.gz @@ -43,13 +39,14 @@ stages: - test build: + interruptible: true services: - image:gnatcov - cpu:8 - mem:16 stage: build script: - - (unset GITLAB_TOKEN; require_issue) + - require_issue - export PATH=/it/e3/bin:$PATH - *edge_vars @@ -72,6 +69,7 @@ build: - $PACKAGE_BASE_NAME build_community: + interruptible: true services: - image:gnatcov - cpu:8 @@ -140,6 +138,7 @@ build_community: path: coverage/cobertura.xml test_bin_traces: + interruptible: true services: - image:gnatcov - cpu:8 @@ -161,6 +160,7 @@ test_bin_traces: <<: *artifacts test_src_traces: + interruptible: true services: - image:gnatcov - cpu:8 @@ -182,6 +182,7 @@ test_src_traces: <<: *artifacts test_spark: + interruptible: true services: - image:gnatcov - cpu:8 From d9466d34626c130e4db6db258fea81963fc17498 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 25 Oct 2023 14:34:33 +0200 Subject: [PATCH 0472/1483] no-unknown-warning: kill test under 5.04a1 --- testsuite/tests/instr-cov/144-no-unknown-warning/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/instr-cov/144-no-unknown-warning/test.opt diff --git a/testsuite/tests/instr-cov/144-no-unknown-warning/test.opt b/testsuite/tests/instr-cov/144-no-unknown-warning/test.opt new file mode 100644 index 000000000..b4cb46ef9 --- /dev/null +++ b/testsuite/tests/instr-cov/144-no-unknown-warning/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Compilation option (-Wtrampolines) unsupported by GNAT 5.04 From 354689d8be83b460261f12478871e1f7989640f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 3 Nov 2023 14:18:14 +0100 Subject: [PATCH 0473/1483] gcvrt.ads: remove trailing space --- tools/gnatcov/rts/gcvrt.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/rts/gcvrt.ads b/tools/gnatcov/rts/gcvrt.ads index 44de3e1a7..38efdf1c7 100644 --- a/tools/gnatcov/rts/gcvrt.ads +++ b/tools/gnatcov/rts/gcvrt.ads @@ -18,6 +18,6 @@ -- Namespace for units generated for instrumentation purposes -package GCVRT is +package GCVRT is pragma Pure; end GCVRT; From 52cd85ef86cfe00ce41e22bb48e4b9a09a89b3f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 3 Nov 2023 13:28:15 +0100 Subject: [PATCH 0474/1483] Instrument.adb: Disambiguate hash-based slugs for Ada units Change the string from which the hash is computed when generating a slug for an Ada unit to avoid collisions. The hash was computed from the symbol string of the unit name, but this transformation can result in the same symbol name being produced for two units: Foo.Bar and Foo_Bar will both be turned into foo_bar. Instead, use the human readable slug as a basis to compute the hash. --- .../147-slug_collision/src/pkg-child.adb | 8 ++++++ .../147-slug_collision/src/pkg-child.ads | 3 +++ .../tests/147-slug_collision/src/pkg.ads | 2 ++ .../147-slug_collision/src/pkg_child.adb | 8 ++++++ .../147-slug_collision/src/pkg_child.ads | 3 +++ .../147-slug_collision/src/test_collision.adb | 13 +++++++++ testsuite/tests/147-slug_collision/test.py | 14 ++++++++++ tools/gnatcov/instrument.adb | 27 ++++++++++--------- 8 files changed, 65 insertions(+), 13 deletions(-) create mode 100644 testsuite/tests/147-slug_collision/src/pkg-child.adb create mode 100644 testsuite/tests/147-slug_collision/src/pkg-child.ads create mode 100644 testsuite/tests/147-slug_collision/src/pkg.ads create mode 100644 testsuite/tests/147-slug_collision/src/pkg_child.adb create mode 100644 testsuite/tests/147-slug_collision/src/pkg_child.ads create mode 100644 testsuite/tests/147-slug_collision/src/test_collision.adb create mode 100644 testsuite/tests/147-slug_collision/test.py diff --git a/testsuite/tests/147-slug_collision/src/pkg-child.adb b/testsuite/tests/147-slug_collision/src/pkg-child.adb new file mode 100644 index 000000000..c3d877af2 --- /dev/null +++ b/testsuite/tests/147-slug_collision/src/pkg-child.adb @@ -0,0 +1,8 @@ +package body Pkg.Child is + + function Foo (X : Integer) return Integer is + begin + return X; -- # stmt + end Foo; + +end Pkg.Child; diff --git a/testsuite/tests/147-slug_collision/src/pkg-child.ads b/testsuite/tests/147-slug_collision/src/pkg-child.ads new file mode 100644 index 000000000..fc63faf53 --- /dev/null +++ b/testsuite/tests/147-slug_collision/src/pkg-child.ads @@ -0,0 +1,3 @@ +package Pkg.Child is + function Foo (X : Integer) return Integer; +end Pkg.Child; diff --git a/testsuite/tests/147-slug_collision/src/pkg.ads b/testsuite/tests/147-slug_collision/src/pkg.ads new file mode 100644 index 000000000..2db1f1de6 --- /dev/null +++ b/testsuite/tests/147-slug_collision/src/pkg.ads @@ -0,0 +1,2 @@ +package Pkg is +end Pkg; diff --git a/testsuite/tests/147-slug_collision/src/pkg_child.adb b/testsuite/tests/147-slug_collision/src/pkg_child.adb new file mode 100644 index 000000000..a47ded692 --- /dev/null +++ b/testsuite/tests/147-slug_collision/src/pkg_child.adb @@ -0,0 +1,8 @@ +package body Pkg_Child is + + function Bar (X : Integer) return Integer is + begin + return X; -- # stmt + end Bar; + +end Pkg_Child; diff --git a/testsuite/tests/147-slug_collision/src/pkg_child.ads b/testsuite/tests/147-slug_collision/src/pkg_child.ads new file mode 100644 index 000000000..899b28c78 --- /dev/null +++ b/testsuite/tests/147-slug_collision/src/pkg_child.ads @@ -0,0 +1,3 @@ +package Pkg_Child is + function Bar (X : Integer) return Integer; +end Pkg_Child; diff --git a/testsuite/tests/147-slug_collision/src/test_collision.adb b/testsuite/tests/147-slug_collision/src/test_collision.adb new file mode 100644 index 000000000..4996fd17d --- /dev/null +++ b/testsuite/tests/147-slug_collision/src/test_collision.adb @@ -0,0 +1,13 @@ +with Support; use Support; + +with Pkg.Child; +with Pkg_Child; + +procedure Test_Collision is +begin + Assert (Pkg.Child.Foo (3) = Pkg_Child.Bar (3)); +end Test_Collision; + +--# pkg-child.adb pkg_child.adb +-- +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/147-slug_collision/test.py b/testsuite/tests/147-slug_collision/test.py new file mode 100644 index 000000000..e571a41e8 --- /dev/null +++ b/testsuite/tests/147-slug_collision/test.py @@ -0,0 +1,14 @@ +""" +Regression test: gnatcov used to generated homonym buffer units for a +"Pkg.Child" unit and a "Pkg_Child" unit, as well as duplicate constant +declarations in some generated units, which prevented the build of the +instrumented sources. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 482207402..56572cdf7 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -154,18 +154,6 @@ package body Instrument is First : Boolean := True; Result : Ada_Identifier; begin - if Use_Hash then - - -- Prefix the hash with "z_" to ensure the unit name slug doesn't - -- start with a digit. - - return - "z" & Strip_Zero_Padding - (Hex_Image - (Unsigned_32 - (Ada.Strings.Hash (To_Symbol_Name (Name))))); - end if; - -- Create a unique slug from the qualified name: replace occurrences of -- 'z' with 'zz' and insert '_z_' between identifiers. @@ -187,7 +175,20 @@ package body Instrument is end; end loop; end loop; - return To_String (Result); + + if Use_Hash then + + -- Prefix the hash with "z" to ensure the unit name slug doesn't + -- start with a digit. + + return + "z" & Strip_Zero_Padding + (Hex_Image + (Unsigned_32 + (Ada.Strings.Hash (To_String (Result))))); + else + return To_String (Result); + end if; end Qualified_Name_Slug; ---------------------------- From 748babae1418416d82c2708402e1dc9bbf788aa2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 9 Nov 2023 13:46:30 +0000 Subject: [PATCH 0475/1483] command_line.ads: mark --subprograms as experimental Also reword the help message a bit. --- tools/gnatcov/command_line.ads | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index b3f1803b9..15f05db27 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -1115,9 +1115,10 @@ package Command_Line is (Long_Name => "--subprograms", Pattern => "FILE:LINE", Help => - "Restrict coverage analysis to specific subprograms designated by" - & " the specification source line for Ada, and by the body source" - & " for C/C++.", + "Experimental feature: restrict coverage analysis to specific" + & " subprograms designated by the specification source line for" + & " Ada, or to specific functions designated by the definition" + & " source line for C/C++.", Commands => (Cmd_Coverage => True, others => False), Internal => False), Opt_Scenario_Var => Create From 794ca823e2db1fcd9b95381eb741dfa50adbfbd9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 10 Oct 2023 07:42:55 +0000 Subject: [PATCH 0476/1483] Sc_Obligations: add support for the new Side_Effects pragma (cherry picked from commit f82c5ee9c00f7f66b692c887ddd7a8de1b987e31) --- tools/gnatcov/sc_obligations.ads | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 193e95c10..e241f4f06 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -973,6 +973,7 @@ package SC_Obligations is Pragma_Shared_Passive, Pragma_Short_Circuit_And_Or, Pragma_Short_Descriptors, + Pragma_Side_Effects, Pragma_Simple_Storage_Pool_Type, Pragma_Source_File_Name, Pragma_Source_File_Name_Project, @@ -1239,6 +1240,7 @@ package SC_Obligations is Pragma_Share_Generic => False, Pragma_Shared => False, Pragma_Shared_Passive => False, + Pragma_Side_Effects => False, Pragma_Simple_Storage_Pool_Type => False, Pragma_Source_Reference => False, Pragma_Static_Elaboration_Desired => False, From 1cf1efcc2b34d87d977095a7cf84c683bcd987fb Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 13 Oct 2023 09:20:42 +0000 Subject: [PATCH 0477/1483] Sc_Obligations: add support for the new User_Aspect_Definition pragma (cherry picked from commit a523efc6bfa5877e3d0d1a100f2f697547bc4c5d) --- tools/gnatcov/sc_obligations.ads | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index e241f4f06..9cebfd9fa 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -1013,6 +1013,7 @@ package SC_Obligations is Pragma_Unsuppress, Pragma_Unused, Pragma_Use_VADS_Size, + Pragma_User_Aspect_Definition, Pragma_Validity_Checks, Pragma_Volatile, Pragma_Volatile_Components, @@ -1124,6 +1125,7 @@ package SC_Obligations is Pragma_Universal_Data => False, Pragma_Unsuppress => False, Pragma_Use_VADS_Size => False, + Pragma_User_Aspect_Definition => False, Pragma_Validity_Checks => False, Pragma_Warning_As_Error => False, Pragma_Warnings => False, From 6ee0c8b0a2774dcede2b8b3bcb9d250d0d1d1721 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 24 Oct 2023 09:49:07 +0000 Subject: [PATCH 0478/1483] instrument-ada_unit.adb: update after recent API changes in Langkit (cherry picked from commit cafc66b7cd7ae18f224318b83590b266b7fa323c) --- tools/gnatcov/instrument-ada_unit.adb | 444 ++++++++++---------------- tools/gnatcov/instrument-ada_unit.ads | 6 - 2 files changed, 165 insertions(+), 285 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index a00ae5296..6ee3dfb77 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -551,10 +551,6 @@ package body Instrument.Ada_Unit is -- Unit, which must be specified in the normalized form expected for -- FQN_Sets (lower case, period separated, fully qualified). - function Index_In_Rewriting_Tree (N : Ada_Node'Class) return Positive; - -- Assuming that the rewriting node for N has a parent, return its index in - -- that parent's list of children. - function Make_MCDC_State_Name (LL_SCO_Id : Nat) return String is ("MCDC_State_" & Img (Integer (LL_SCO_Id))); -- Return the name of the MC/DC state local variable for the given @@ -1564,7 +1560,7 @@ package body Instrument.Ada_Unit is -- The second child of RH_Call is its list of actual parameters - Append_Child (Child (RH_Call, 2), D); + Insert_Last (Child (RH_Call, Member_Refs.Call_Expr_F_Suffix), D); return Convert_To (IC, B_Type, D_Type, RH_Call); end Make_Decision_Witness; @@ -1612,8 +1608,9 @@ package body Instrument.Ada_Unit is -- The second child of RH_Call is its list of actual parameters - Append_Child - (Child (RH_Call, 2), Convert_To (IC, C_Type, B_Type, RH_Cond)); + Insert_Last + (Child (RH_Call, Member_Refs.Call_Expr_F_Suffix), + Convert_To (IC, C_Type, B_Type, RH_Cond)); return Convert_To (IC, B_Type, C_Type, RH_Call); end Make_Condition_Witness; @@ -1765,7 +1762,7 @@ package body Instrument.Ada_Unit is return; end if; - Append_Child + Insert_Last (Handle (UIC.Root_Unit.F_Prelude), Create_From_Template (RH, @@ -1776,27 +1773,6 @@ package body Instrument.Ada_Unit is UIC.Withed_Units.Include (Unit); end Ensure_With; - ----------------------------- - -- Index_In_Rewriting_Tree -- - ----------------------------- - - function Index_In_Rewriting_Tree (N : Ada_Node'Class) return Positive is - RH : constant Node_Rewriting_Handle := Handle (N); - P : constant Node_Rewriting_Handle := Parent (RH); - begin - pragma Assert (P /= No_Node_Rewriting_Handle); - for I in 1 .. Children_Count (P) loop - if Child (P, I) = RH then - return I; - end if; - end loop; - - -- If we reach this point, this means the rewriting tree is corrupted (a - -- node does not belong to its parent's children). - - return (raise Program_Error with "corrupted rewriting tree"); - end Index_In_Rewriting_Tree; - ----------------------- -- Insert_MCDC_State -- ----------------------- @@ -1814,35 +1790,21 @@ package body Instrument.Ada_Unit is Name & " : constant GNATCov_RTS.Sys.Address := " & Name & "_Var'Address;"; + Decl : constant Node_Rewriting_Handle := + Create_From_Template + (UIC.Rewriting_Context, + Template => To_Wide_Wide_String (Var_Decl_Img), + Arguments => (1 => E.Common_Buffers), + Rule => Object_Decl_Rule); + Rep_Clause : constant Node_Rewriting_Handle := + Create_From_Template + (UIC.Rewriting_Context, + Template => To_Wide_Wide_String (Addr_Decl_Img), + Arguments => (1 .. 0 => No_Node_Rewriting_Handle), + Rule => Object_Decl_Rule); begin - Insert_Child - (Inserter.Local_Decls, 1, - Create_From_Template - (UIC.Rewriting_Context, - Template => To_Wide_Wide_String (Var_Decl_Img), - Arguments => (1 => E.Common_Buffers), - Rule => Object_Decl_Rule)); - Insert_Child - (Inserter.Local_Decls, 2, - Create_From_Template - (UIC.Rewriting_Context, - Template => To_Wide_Wide_String (Addr_Decl_Img), - Arguments => (1 .. 0 => No_Node_Rewriting_Handle), - Rule => Object_Decl_Rule)); - - -- If we are adding MCDC state variables to the decls currently being - -- instrumented, we need to indicate that we just added two extra - -- elements in the list of declarations, so that following insertions - -- are made at the correct index in this list. - - if UIC.Current_Insertion_Info /= null - and then UIC.Current_Insertion_Info.Method = Declaration - and then UIC.Current_Insertion_Info.RH_List = Inserter.Local_Decls - then - UIC.Current_Insertion_Info.Rewriting_Offset := - UIC.Current_Insertion_Info.Rewriting_Offset + 2; - end if; - + Insert_First (Inserter.Local_Decls, Rep_Clause); + Insert_First (Inserter.Local_Decls, Decl); return Name; end Insert_MCDC_State; @@ -2203,7 +2165,7 @@ package body Instrument.Ada_Unit is -- Create the generic formal type node and add it to the list of -- generic formals. - Append_Child + Insert_Last (NP_Nodes.Formals, Create_Generic_Formal_Type_Decl (RC, @@ -2250,7 +2212,7 @@ package body Instrument.Ada_Unit is if Actual.Kind = Ada_Subtype_Indication then Actual := TE.As_Subtype_Indication.F_Name.As_Ada_Node; end if; - Append_Child (NP_Nodes.Inst_Params, Clone (Actual)); + Insert_Last (NP_Nodes.Inst_Params, Clone (Actual)); end; -- Return a reference to this formal @@ -2267,7 +2229,7 @@ package body Instrument.Ada_Unit is return; end if; for J in 1 .. Common_Nodes.N_Params.Children_Count loop - Append_Child + Insert_Last (NP_Nodes.Param_Specs, Gen_Proc_Param_For (Common_Nodes.N_Params.Child (J).As_Param_Spec)); @@ -2430,8 +2392,8 @@ package body Instrument.Ada_Unit is end; end if; - Append_Child (Inserter.Formal_Params, State_Param_Spec); - Append_Child (Inserter.Call_Params, State_Actual); + Insert_Last (Inserter.Formal_Params, State_Param_Spec); + Insert_Last (Inserter.Call_Params, State_Actual); return Name & ".State'Address"; end Insert_MCDC_State; @@ -2663,8 +2625,8 @@ package body Instrument.Ada_Unit is -- Put the augmented expression function in the wrapper package, and -- return its handle instead of the one of the expression function. - Append_Child (Common_Nodes.Wrapper_Pkg_Decls, - Child => Augmented_Expr_Function); + Insert_Last + (Common_Nodes.Wrapper_Pkg_Decls, Augmented_Expr_Function); Augmented_Expr_Function := Common_Nodes.Wrapper_Pkg; end if; @@ -3173,12 +3135,6 @@ package body Instrument.Ada_Unit is then Handle (N) else Insertion_N); - Index : constant Natural := - (case UIC.Current_Insertion_Info.Method is - when Statement | Declaration => - UIC.Current_Insertion_Info.Index, - when others => 0); - begin case Kind (N) is when Ada_Accept_Stmt | Ada_Accept_Stmt_With_Stmts => @@ -3329,13 +3285,11 @@ package body Instrument.Ada_Unit is and then Typ /= 'p' then declare - Insert_List : Node_Rewriting_Handle; - Insert_Pos : Natural; - Insert_Info : Insertion_Info_Access := - UIC.Current_Insertion_Info; - Bit : Any_Bit_Id; + Insert_Info : constant Insertion_Info_Access := + UIC.Current_Insertion_Info; + LL_SCO_Id : constant Nat := SCOs.SCO_Table.Last; begin -- Create an artificial internal error, if requested @@ -3420,13 +3374,17 @@ package body Instrument.Ada_Unit is F_Designator => No_Node_Rewriting_Handle, F_R_Expr => Old_Cond)))); - Set_Child (New_Cond, 3, Old_Cond); + Set_Child + (New_Cond, Member_Refs.Bin_Op_F_Right, Old_Cond); end; else - if Kind (Actual_Insertion_N) = Ada_Accept_Stmt_With_Stmts - and then Instrument_Location = After - then + declare + Ref_Node : Node_Rewriting_Handle; + Insert_Sibling : Boolean; + Is_Before : Boolean; + Witness_Call : Node_Rewriting_Handle; + begin -- In the case of an accept_statement containing a -- sequence of statements, if Instrument_Location -- is After, we want to call the witness after the @@ -3434,96 +3392,73 @@ package body Instrument.Ada_Unit is -- statements are executed, so insert the witness -- call in the inner statement list at first position. - Insert_List := - Child (Actual_Insertion_N, - (Member_Refs.Accept_Stmt_With_Stmts_F_Stmts, - Member_Refs.Handled_Stmts_F_Stmts)); - Insert_Pos := 1; + if Kind (Actual_Insertion_N) + = Ada_Accept_Stmt_With_Stmts + and then Instrument_Location = After + then + Ref_Node := Child + (Actual_Insertion_N, + (Member_Refs.Accept_Stmt_With_Stmts_F_Stmts, + Member_Refs.Handled_Stmts_F_Stmts)); + Insert_Sibling := False; - else - if Instrument_Location = Before_Parent then - Insert_Info := Insert_Info.Parent; - Insert_Pos := Insert_Info.Index; else - Insert_Pos := Index; - end if; - - Insert_List := Insert_Info.RH_List; - - -- Adjust insertion to account for any insertion - -- performed outside of the processing of the current - -- list (case of the above special processing for - -- accept statements). Note that SCE.N might not be a - -- direct element of the enclosing list (e.g. in the - -- case where it is a named statement), so we must - -- first go up to the parent of SCE.N that *is* an - -- element of that list, and *then* scan forward to - -- determine the current position of that parent note - -- within the list. - - declare - RH_Element_Node : Node_Rewriting_Handle := - Actual_Insertion_N; - RH_Children_Count : constant Natural := - Children_Count (Insert_Info.RH_List); - begin - -- Find the parent of N that is an element of the - -- enclosing list. - - while Parent (RH_Element_Node) - /= Insert_Info.RH_List - loop - RH_Element_Node := Parent (RH_Element_Node); - end loop; - - -- Scan forward in enclosing list for adjusted - -- position of the element node. - - while Child - (Insert_Info.RH_List, - Integer (Insert_Pos - + Insert_Info.Rewriting_Offset)) - /= RH_Element_Node - loop - Insert_Info.Rewriting_Offset := - Insert_Info.Rewriting_Offset + 1; - pragma Assert - (Insert_Pos + Insert_Info.Rewriting_Offset - <= RH_Children_Count); - end loop; - end; + Ref_Node := Actual_Insertion_N; + Insert_Sibling := True; + + -- Set Is_Before according to the requested + -- insertion mode. + -- + -- Also update Ref_Node so that it is the + -- "reference" node to use for insertion, i.e. the + -- sibling in the target insertion list (Ref_List, + -- below). + -- + -- Note that the witness is inserted at the current + -- location of the statement, so that it will occur + -- immediately *before* it in the instrumented + -- sources. This is necessary because we want to + -- mark a statement as executed anytime it has + -- commenced execution (including in cases it + -- raises an exception or otherwise transfers + -- control). However in some special cases we have + -- to insert after the statement, see the comment + -- for Instrument_Location_Type. - -- The witness is inserted at the current location of - -- the statement, so that it will occur immediately - -- *before* it in the instrumented sources. This - -- is necessary because we want to mark a statement - -- as executed anytime it has commenced execution - -- (including in cases it raises an exception or - -- otherwise transfers control). However in some - -- special cases we have to insert after the - -- statement, see the comment for - -- Instrument_Location_Type. - -- - -- The cases where we need to instrument inside an - -- expression are handled before, as they do not - -- trigger the insertion of a new statement in a - -- statement list. - - Insert_Pos := Insert_Pos - + Insert_Info.Rewriting_Offset - + (case Instrument_Location is - when Before | Before_Parent => 0, - when After => 1, - when Inside_Expr => - raise Program_Error); - end if; + declare + Ref_List : Node_Rewriting_Handle; + begin + case Instrument_Location is + when Before => + Is_Before := True; + Ref_List := Insert_Info.RH_List; + + when Before_Parent => + Is_Before := True; + Ref_List := Insert_Info.Parent.RH_List; + + when After => + Is_Before := False; + Ref_List := Insert_Info.RH_List; + + -- The cases where we need to instrument + -- inside an expression are handled before, + -- as they do not trigger the insertion of a + -- new statement in a statement list. + + when Inside_Expr => + raise Program_Error; + end case; + + while Parent (Ref_Node) /= Ref_List loop + Ref_Node := Parent (Ref_Node); + end loop; + end; + end if; - -- Insert witness statement or declaration + -- Insert witness statement or declaration - Insert_Child - (Handle => Insert_List, - Index => Insert_Pos, - Child => + Witness_Call := Make_Statement_Witness (UIC, Bit => Bit, @@ -3533,19 +3468,18 @@ package body Instrument.Ada_Unit is when Declaration => Declaration, when Expression_Function | None => raise Program_Error), - In_Generic => UIC.In_Generic)); - - -- Update the rewriting offset iff we inserted an - -- element in the current rewriting list: that offset - -- specifically refers to that list, whereas we may - -- have inserted an item in a nested list, in which case - -- we will adjust automatically the rewriting offset - -- accordingly when processing that list. - - if Insert_Info.RH_List = Insert_List then - Insert_Info.Rewriting_Offset := - Insert_Info.Rewriting_Offset + 1; - end if; + In_Generic => UIC.In_Generic); + + if Insert_Sibling then + if Is_Before then + Insert_Before (Ref_Node, Witness_Call); + else + Insert_After (Ref_Node, Witness_Call); + end if; + else + Insert_First (Ref_Node, Witness_Call); + end if; + end; end if; when Expression_Function => @@ -3611,6 +3545,11 @@ package body Instrument.Ada_Unit is (N : Basic_Decl; N_Spec : Subp_Spec) is + Stub : constant Node_Rewriting_Handle := + Make_Identifier (UIC, "Stub"); + -- Placeholder for the the degenerate subprogram node while it is + -- rewritten. + -- See the "Degenerate subprograms" comment section above for a -- description of the of transformation we implement in this -- procedure. @@ -3625,10 +3564,6 @@ package body Instrument.Ada_Unit is UIC.MCDC_State_Inserter; -- Likewise for MC/DC state inserter - procedure Insert (New_Node : Node_Rewriting_Handle); - -- Insert New_Node in sequence at original location of the degenerate - -- subprogram. - procedure To_Regular_Subprogram (N : Base_Subp_Body); -- Turns N into an instrumented regular function, by creating a -- function with the same subp_spec as the original expression @@ -3639,22 +3574,6 @@ package body Instrument.Ada_Unit is -- The SCO associated with the new single statement has the -- sloc of the whole original subprogram. - ------------ - -- Insert -- - ------------ - - procedure Insert (New_Node : Node_Rewriting_Handle) is - begin - Insert_Child - (Handle => Saved_Insertion_Info.RH_List, - Index => Saved_Insertion_Info.Index - + Saved_Insertion_Info.Rewriting_Offset - + 1, - Child => New_Node); - Saved_Insertion_Info.Rewriting_Offset := - Saved_Insertion_Info.Rewriting_Offset + 1; - end Insert; - --------------------------- -- To_Regular_Subprogram -- --------------------------- @@ -3700,8 +3619,6 @@ package body Instrument.Ada_Unit is begin II.RH_List := Stmt_list_RH; - II.Index := 1; - II.Rewriting_Offset := 0; II.Preelab := False; II.Parent := Saved_Insertion_Info; @@ -3856,7 +3773,6 @@ package body Instrument.Ada_Unit is RH_List => Decl_List, Preelab => False, Parent => null, - Index => 1, others => <>); -- Insertion info points to the newly created declaration list. -- Index is 1 as we want to insert a witness call at the @@ -3874,7 +3790,7 @@ package body Instrument.Ada_Unit is begin -- Add the dummy declaration to the declaration list - Append_Child (Decl_List, Dummy_Decl); + Insert_Last (Decl_List, Dummy_Decl); -- Tie the declare expression to the expression function's -- F_Expr field, taking care to wrap it in parentheses. @@ -4025,7 +3941,7 @@ package body Instrument.Ada_Unit is for Id of Common_Nodes.N_Params.Child (J) .As_Param_Spec.F_Ids.Children loop - Append_Child + Insert_Last (Call_Params, Make_Identifier (UIC, Id.Text)); end loop; end loop; @@ -4046,19 +3962,17 @@ package body Instrument.Ada_Unit is -- procedure (NP_Nodes.Null_Stmt). New_Insertion_Info := - (Method => Statement, - RH_List => NP_Nodes.Stmt_List, - Index => 1, - Rewriting_Offset => 0, + (Method => Statement, + RH_List => NP_Nodes.Stmt_List, -- Even if the current package has elaboration restrictions, -- this Insertion_Info is used to insert a witness call in the -- procedure in the generic body: the elaboration restriction -- does not apply there. - Preelab => False, + Preelab => False, - Parent => null); + Parent => null); end if; ---------------------------------- @@ -4107,23 +4021,15 @@ package body Instrument.Ada_Unit is -- Pass the witness call to the augmented expression function - Append_Child (Call_Params, New_Insertion_Info.Witness_Actual); - Append_Child (Formal_Params, New_Insertion_Info.Witness_Formal); + Insert_Last (Call_Params, New_Insertion_Info.Witness_Actual); + Insert_Last (Formal_Params, New_Insertion_Info.Witness_Formal); end if; ---------------------------- -- 3. Rework declarations -- ---------------------------- - -- Remove the original declaration (N) from the tree. Note that since - -- .RH_List (the instrumented list of declarations from which N must - -- be removed) may contain more elements than before instrumenting. - -- So in order to remove it, we must recompute N's index in .RH_List. - - Remove_Child - (Saved_Insertion_Info.RH_List, Index_In_Rewriting_Tree (N)); - Saved_Insertion_Info.Rewriting_Offset := - Saved_Insertion_Info.Rewriting_Offset - 1; + Replace (Handle (N), Stub); -- For null procedures, if there is no previous declaration, generate -- one, keeping the original aspects and default parameters. Then @@ -4146,11 +4052,13 @@ package body Instrument.Ada_Unit is and then (not Is_Expr_Function or else Is_Self_Referencing (UIC, N.As_Expr_Function)) then - Insert (Create_Subp_Decl - (RC, - F_Overriding => Detach (Common_Nodes.N_Overriding), - F_Subp_Spec => Clone (N_Spec), - F_Aspects => Detach (N.F_Aspects))); + Insert_Before + (Stub, + Create_Subp_Decl + (RC, + F_Overriding => Detach (Common_Nodes.N_Overriding), + F_Subp_Spec => Clone (N_Spec), + F_Aspects => Detach (N.F_Aspects))); -- For expression functions, the aspects of the subprogram were -- moved to the newly created declaration, so they should not be @@ -4179,8 +4087,8 @@ package body Instrument.Ada_Unit is -- First comes the augmented expression function, then the new -- expression function. - Insert (Augmented_Expr_Function); - Insert (New_Expr_Function); + Insert_Before (Stub, Augmented_Expr_Function); + Insert_Before (Stub, New_Expr_Function); -- If we need to insert a declaration for the new expression -- function, find the correct spot to add it, and keep track @@ -4194,22 +4102,11 @@ package body Instrument.Ada_Unit is -- This property cannot fail because to reach this point -- we will already have succesfully queried the previous -- part of N in Augmented_Expr_Function_Needs_Decl. - - Insert_List : constant Node_Rewriting_Handle := - Handle (Previous_Decl.Parent); - Insert_Index : constant Positive := - Index_In_Rewriting_Tree (Previous_Decl); begin - Insert_Child (Insert_List, - Insert_Index, - Augmented_Expr_Function_Decl); - if Insert_List = Saved_Insertion_Info.RH_List then - Saved_Insertion_Info.Rewriting_Offset := - Saved_Insertion_Info.Rewriting_Offset + 1; - end if; + Insert_Before + (Handle (Previous_Decl), Augmented_Expr_Function_Decl); end; end if; - end; else @@ -4233,14 +4130,14 @@ package body Instrument.Ada_Unit is -- Insert the renaming in the wrapper package - Append_Child (Common_Nodes.Wrapper_Pkg_Decls, Instance); + Insert_Last (Common_Nodes.Wrapper_Pkg_Decls, Instance); -- Push the wrapper package and the renaming down to the end of -- the current list of declarations. - Append_Child + Insert_Last (Common_Nodes.Append_List, Common_Nodes.Wrapper_Pkg); - Append_Child (Common_Nodes.Append_List, Renaming_Decl); + Insert_Last (Common_Nodes.Append_List, Renaming_Decl); -- Unparse the generic subprogram now, for later insertion in -- the pure buffers unit (at which time the rewriting context @@ -4255,6 +4152,11 @@ package body Instrument.Ada_Unit is To_Unbounded_Wide_Wide_String (Unparse (Subp_Body)))); end; end if; + + -- Now that we have inserted the replacement declarations, remove the + -- stub. + + Remove_Child (Stub); end Traverse_Degenerate_Subprogram; -------------------------------- @@ -4423,9 +4325,8 @@ package body Instrument.Ada_Unit is (UIC.Rewriting_Context, "with {};", (1 => Buffers_Unit), With_Clause_Rule); begin - Append_Child (Handle (CUN.F_Prelude), - With_Buffers_Clause); - Append_Child (Handle (CUN.F_Prelude), With_PB_Clause); + Insert_Last (Handle (CUN.F_Prelude), With_Buffers_Clause); + Insert_Last (Handle (CUN.F_Prelude), With_PB_Clause); end; end; @@ -5062,8 +4963,6 @@ package body Instrument.Ada_Unit is II : Insertion_Info (Method); begin II.RH_List := Handle (L); - II.Index := 0; - II.Rewriting_Offset := 0; II.Preelab := Preelab; II.Parent := Saved_Insertion_Info; @@ -5084,10 +4983,6 @@ package body Instrument.Ada_Unit is declare N : constant Ada_Node := L.Child (J); begin - if Current_Insertion_Info.Method in Statement | Declaration then - Current_Insertion_Info.Index := J; - end if; - -- Only traverse the nodes if they are not ghost entities if not (UIC.Ghost_Code @@ -7406,10 +7301,7 @@ package body Instrument.Ada_Unit is then -- Child_Index is 0 based whereas Insert_Child is 1 based - Insert_Child - (Handle (Node.Parent), - Node.Child_Index + 1, - Clone (Call_Stmt)); + Insert_Before (Handle (Node), Clone (Call_Stmt)); return Over; else return Into; @@ -7424,7 +7316,7 @@ package body Instrument.Ada_Unit is begin -- Add a Dump_Buffer call at the end of the main's handeled statements - Append_Child (Handled_Stmt_List, Call_Stmt); + Insert_Last (Handled_Stmt_List, Call_Stmt); -- Add a Dump_Buffer call before any return statement that returns from -- the main. @@ -7446,7 +7338,7 @@ package body Instrument.Ada_Unit is Exn_Stmt_List : constant Node_Rewriting_Handle := Handle (Exn_Handler.F_Stmts); begin - Append_Child (Exn_Stmt_List, Clone (Call_Stmt)); + Insert_Last (Exn_Stmt_List, Clone (Call_Stmt)); end; end if; end loop; @@ -7478,7 +7370,7 @@ package body Instrument.Ada_Unit is -- Insert the declaration as the first declaration in the -- list to ensure it is finalized last. - Insert_Child (Decls, 1, Dump_Object_Decl); + Insert_First (Decls, Dump_Object_Decl); end Insert_Controlled_Dump_Object_Decl; ---------------------------------- @@ -7627,7 +7519,7 @@ package body Instrument.Ada_Unit is declare Symbol : constant Symbolization_Result := - Canonicalize (Text (Child (Node, 1))); + Canonicalize (Text (Child (Node, Member_Refs.Pragma_Node_F_Id))); begin return (Symbol.Success and then Symbol.Symbol in "warnings" | "style_checks"); @@ -7647,19 +7539,13 @@ package body Instrument.Ada_Unit is -- Go through all children in reverse order so that we can remove -- pragmas in one pass. - for I in reverse 1 .. Children_Count (Node) loop - declare - Child : constant Node_Rewriting_Handle := - Libadalang.Rewriting.Child (Node, I); - begin - if Child /= No_Node_Rewriting_Handle - and then Should_Remove (Child) - then - Remove_Child (Node, I); - else - Process (Child); - end if; - end; + for Child of Children (Node) loop + if Child /= No_Node_Rewriting_Handle and then Should_Remove (Child) + then + Remove_Child (Child); + else + Process (Child); + end if; end loop; end Process; @@ -7813,10 +7699,10 @@ package body Instrument.Ada_Unit is Rule => Pragma_Rule); begin - Append_Child (Desc.Prelude, With_Clause); - Append_Child (Desc.Prelude, With_RTS_Clause); - Append_Child (Desc.Prelude, With_Buffers_Clause); - Append_Child (Desc.Prelude, Runtime_Version_Check_Node); + Insert_Last (Desc.Prelude, With_Clause); + Insert_Last (Desc.Prelude, With_RTS_Clause); + Insert_Last (Desc.Prelude, With_Buffers_Clause); + Insert_Last (Desc.Prelude, Runtime_Version_Check_Node); end; -- Depending on the chosen coverage buffers dump trigger, insert the @@ -7846,7 +7732,7 @@ package body Instrument.Ada_Unit is "Autodump_Dummy : {} := {};", (1 => To_Nodes (RH, Witness_Dummy_Type_Name), 2 => Call_Expr), Object_Decl_Rule); - Insert_Child (Desc.Main_Decls, 1, Call_Decl); + Insert_First (Desc.Main_Decls, Call_Decl); end; when Main_End => @@ -7882,7 +7768,7 @@ package body Instrument.Ada_Unit is -- place where we want to dump coverage buffers: at the end of the -- wrapper procedure body. - Append_Child + Insert_Last (Desc.Main_Stmts, Simple_Dump_Proc_Call (RH, Helper_Unit)); else @@ -7985,7 +7871,7 @@ package body Instrument.Ada_Unit is -- Add the with clause only once in the file if not Done then - Append_Child + Insert_Last (Handle (Unit.Root.As_Compilation_Unit.F_Prelude), Create_From_Template (RH, diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index c6267a7e0..54b4facdb 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -144,12 +144,6 @@ private RH_List : Node_Rewriting_Handle := No_Node_Rewriting_Handle; -- Rewriting handle for the statement/declaration list - Index : Natural := 0; - -- Index of the element in RH_List being traversed - - Rewriting_Offset : Integer := 0; - -- Count of nodes inserted/removed in current list so far - Preelab : Boolean := False; -- Whether we are traversing a list of top-level declarations in a -- preelaborate package. In this context, we cannot insert witness From 13175e240f6cb4b49228cb42a1954d82abc2c3e9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 25 Oct 2023 21:12:07 +0000 Subject: [PATCH 0479/1483] Instrument Ada: add support for preprocessing Extract preprocessor configuration data from project files and pass it to Libadalang, so that instrumentation works on preprocessed code. Naturally, this allows gnatcov to compute the code coverage only for code that is left "enabled" by preprocessing directives: disabled code (i.e. equivalent to `#if false`) is ignored and thus creates no coverage obligation. Note that consolidation will not help including code from all "preprocessing branches" in coverage reports, as gnatcov requires (and checks) that coverage obligations are the same for two units to consolidate. Similarly, the coverage obligations for code that comes from symbol expansion (`$Foo` expanded into `Bar` with `-Dfoo=Bar`) designates expanded code. Even though line numbers are preserved during preprocessing, column numbers may be different between original code and preprocessed code and thus coverage reports. This is a limitation from Libadalang's preprocessing facilities, so not something we could fix at the gnatcov level, but this limitation is not considered problematic at this point for the known use cases of coverage on code with preprocessing directives. (cherry picked from commit 8a69f32dafd90d0db36a764944b80674c6c19109) --- .../errors/bad_syntax.txt | 1 + .../errors/eval_error.txt | 1 + .../138-ada-preprocessing/errors/main.adb | 6 + .../138-ada-preprocessing/errors/pkg.ads | 5 + .../138-ada-preprocessing/errors/test.py | 67 ++++ .../138-ada-preprocessing/example/prep.txt | 1 + .../138-ada-preprocessing/example/test.py | 83 +++++ .../example/test_eval.adb | 15 + .../138-ada-preprocessing/example/vm.adb | 130 ++++++++ .../138-ada-preprocessing/example/vm.ads | 30 ++ .../prep_data/def_empty/defs.txt | 1 + .../prep_data/def_empty/pkg.adb | 10 + .../prep_data/def_empty/prep.txt | 1 + .../prep_data/def_string/pkg.adb | 13 + .../prep_data/def_string/prep.txt | 1 + .../prep_data/def_symbol/pkg.adb | 13 + .../prep_data/def_symbol/prep.txt | 1 + .../prep_data/default_config/pkg.adb | 10 + .../prep_data/default_config/prep.txt | 2 + .../prep_data/file_config/pkg.adb | 10 + .../prep_data/file_config/prep.txt | 2 + .../138-ada-preprocessing/prep_data/main.adb | 6 + .../prep_data/no_undef_is_false/pkg.adb | 14 + .../prep_data/no_undef_is_false/prep.txt | 1 + .../138-ada-preprocessing/prep_data/pkg.ads | 3 + .../138-ada-preprocessing/prep_data/test.py | 117 +++++++ .../prep_data/undef_is_false/pkg.adb | 20 ++ .../prep_data/undef_is_false/prep.txt | 1 + tools/gnatcov/command_line.ads | 13 + .../gnatcov/instrument-ada_preprocessing.adb | 314 ++++++++++++++++++ .../gnatcov/instrument-ada_preprocessing.ads | 41 +++ tools/gnatcov/instrument-ada_unit.adb | 18 +- tools/gnatcov/instrument-ada_unit.ads | 34 +- tools/gnatcov/instrument-ada_unit__stub.ads | 7 +- tools/gnatcov/instrument-config.adb | 12 +- tools/gnatcov/instrument-projects.adb | 22 +- 36 files changed, 1000 insertions(+), 26 deletions(-) create mode 100644 testsuite/tests/138-ada-preprocessing/errors/bad_syntax.txt create mode 100644 testsuite/tests/138-ada-preprocessing/errors/eval_error.txt create mode 100644 testsuite/tests/138-ada-preprocessing/errors/main.adb create mode 100644 testsuite/tests/138-ada-preprocessing/errors/pkg.ads create mode 100644 testsuite/tests/138-ada-preprocessing/errors/test.py create mode 100644 testsuite/tests/138-ada-preprocessing/example/prep.txt create mode 100644 testsuite/tests/138-ada-preprocessing/example/test.py create mode 100644 testsuite/tests/138-ada-preprocessing/example/test_eval.adb create mode 100644 testsuite/tests/138-ada-preprocessing/example/vm.adb create mode 100644 testsuite/tests/138-ada-preprocessing/example/vm.ads create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/def_empty/defs.txt create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/def_empty/pkg.adb create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/def_empty/prep.txt create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/def_string/pkg.adb create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/def_string/prep.txt create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/pkg.adb create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/prep.txt create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/default_config/pkg.adb create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/default_config/prep.txt create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/file_config/pkg.adb create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/file_config/prep.txt create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/main.adb create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/pkg.adb create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/prep.txt create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/pkg.ads create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/test.py create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/pkg.adb create mode 100644 testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/prep.txt create mode 100644 tools/gnatcov/instrument-ada_preprocessing.adb create mode 100644 tools/gnatcov/instrument-ada_preprocessing.ads diff --git a/testsuite/tests/138-ada-preprocessing/errors/bad_syntax.txt b/testsuite/tests/138-ada-preprocessing/errors/bad_syntax.txt new file mode 100644 index 000000000..36bea91e6 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/errors/bad_syntax.txt @@ -0,0 +1 @@ +:= diff --git a/testsuite/tests/138-ada-preprocessing/errors/eval_error.txt b/testsuite/tests/138-ada-preprocessing/errors/eval_error.txt new file mode 100644 index 000000000..4fc5f1c9d --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/errors/eval_error.txt @@ -0,0 +1 @@ +* -c diff --git a/testsuite/tests/138-ada-preprocessing/errors/main.adb b/testsuite/tests/138-ada-preprocessing/errors/main.adb new file mode 100644 index 000000000..5db011f19 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/errors/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/138-ada-preprocessing/errors/pkg.ads b/testsuite/tests/138-ada-preprocessing/errors/pkg.ads new file mode 100644 index 000000000..6444959e9 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/errors/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is +# if Log then + procedure Log; +# end if ; +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/errors/test.py b/testsuite/tests/138-ada-preprocessing/errors/test.py new file mode 100644 index 000000000..2433e87ad --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/errors/test.py @@ -0,0 +1,67 @@ +""" +Check various error cases related to the use of preprocessing in Ada. +""" + +import os +import os.path + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Avoid "creating output path" info messages +os.mkdir("obj") + +for basename, expected_msg in [ + ( + "no_such_file", + ".*gnatcov.*: error while loading preprocessor data from project" + "\n.*gnatcov.*: no such file: .*no_such_file\\.txt", + ), + ( + "bad_syntax", + ".*gnatcov.*: error while loading preprocessor data from project" + "\n.*gnatcov.*: .*bad_syntax\\.txt:1:1: Ada source filename expected", + ), + ( + "eval_error", + ".*gnatcov.*: instrumentation failed for .*pkg\\.ads" + "\n.*gnatcov.*: please make sure the original project can be" + " compiled" + '\n.*gnatcov.*: pkg\\.ads:2:6: unknown symbol "Log"', + ), +]: + thistest.log(f"== {basename} ==") + log_filename = f"{basename}-out.txt" + p = xcov_instrument( + gprsw=GPRswitches( + root_project=gprfor( + prjid=basename, + mains=["main.adb"], + srcdirs=[".."], + compiler_extra=( + 'for Default_Switches ("Ada")' + ' use ("-gnatep="' + " & Project'Project_Dir" + f' & "/../{basename}.txt");' + ), + ) + ), + covlevel="stmt", + register_failure=False, + out=log_filename, + ) + thistest.fail_if(p.status == 0, "'gnatcov instrument' is supposed to fail") + output = contents_of(log_filename) + thistest.fail_if_no_match( + "'gnatcov instrument' output", + expected_msg, + contents_of(log_filename).strip(), + ) + +thistest.result() diff --git a/testsuite/tests/138-ada-preprocessing/example/prep.txt b/testsuite/tests/138-ada-preprocessing/example/prep.txt new file mode 100644 index 000000000..b5e172856 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/example/prep.txt @@ -0,0 +1 @@ +* -Dlog=false -c diff --git a/testsuite/tests/138-ada-preprocessing/example/test.py b/testsuite/tests/138-ada-preprocessing/example/test.py new file mode 100644 index 000000000..649a7b064 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/example/test.py @@ -0,0 +1,83 @@ +""" +Check that the instrumentation of Ada sources with preprocessing enabled works +as expected on an example project. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Avoid "creating output path" info messages +os.mkdir("obj") + +# Test the working case. The "log" preprocessing symbol is set to "false" in +# "prep.txt", so all logging lines are supposed to be disabled and thus not +# create coverage obligations. Yet the line numbers for the code remaining are +# supposed to be preserved. +thistest.log("== Up to the coverage report ==") +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + mains=["test_eval.adb"], + srcdirs=[".."], + compiler_extra=( + 'for Default_Switches ("Ada")' + ' use ("-gnatep=" & Project\'Project_Dir & "/../prep.txt");' + ), + ) + ), + covlevel="stmt+decision", + mains=["test_eval"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports( + "*.xcov", + { + "test_eval.adb.xcov": {"+": {4}, "!": {12}, "-": {13}}, + "vm.ads.xcov": {"+": {3, 4, 6, 7, 16, 17}}, + "vm.adb.xcov": { + "+": { + # Eval header + 13, + + # Pop + 27, 31, + + # Push + 43, 44, + + # Eval loop + 61, 62, 70, 72, 87, 89, 90, 96, + + # Eval wrapper + 117, 118, 121, 122, 123, 125, 126, 127, + }, + "!": { + # Branch condition evaluation + 78 + }, + "-": { + # Jump + 75, + + # Branch jump + 79, + + # Push_Lit, Add + 83, 94, + }, + }, + }, + cwd="xcov", +) + +thistest.result() diff --git a/testsuite/tests/138-ada-preprocessing/example/test_eval.adb b/testsuite/tests/138-ada-preprocessing/example/test_eval.adb new file mode 100644 index 000000000..7af26d072 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/example/test_eval.adb @@ -0,0 +1,15 @@ +with VM; use VM; + +procedure Test_Eval is + Program : constant Program_Type := + (1 => (Kind => Clone), + 2 => (Kind => Branch, Jump_Dest => 4), + 3 => (Kind => Halt), + 4 => (Kind => Push_Lit, Push_Value => -1), + 5 => (Kind => Add), + 6 => (Kind => Jump, Jump_Dest => 1)); +begin + if Eval (Program, 5, (1 => 0)) /= 0 then + raise Program_Error; + end if; +end Test_Eval; diff --git a/testsuite/tests/138-ada-preprocessing/example/vm.adb b/testsuite/tests/138-ada-preprocessing/example/vm.adb new file mode 100644 index 000000000..7f1f393a8 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/example/vm.adb @@ -0,0 +1,130 @@ +#if Log then +with Ada.Text_IO; use Ada.Text_IO; +#end if; + +package body VM is + + procedure Eval + (Program : Program_Type; + PC : in out PC_Type; + Stack : in out Stack_type; + SP : in out SP_Type) + is + Continue : Boolean := True; + + function Pop return Integer; + procedure Push (Value : Integer); + + --------- + -- Pop -- + --------- + + function Pop return Integer is + begin +#if Log then + Put_Line ("Popping the stack"); +#end if; + SP := SP - 1; +#if Log then + Put_Line ("SP:" & SP_Type'Image (SP)); +#end if; + return Stack (SP); + end Pop; + + ---------- + -- Push -- + ---------- + + procedure Push (Value : Integer) is + begin +#if Log then + Put_Line ("Pushing the stack"); +#end if; + Stack (SP) := Value; + SP := SP + 1; +#if Log then + Put_Line ("SP:" & SP_Type'Image (SP)); +#end if; + end Push; + + begin + +#if Log then + Put_Line ("Program starting:"); + Put_Line ("PC:" & PC_Type'Image (PC)); + Put_Line ("SP:" & SP_Type'Image (SP)); + New_Line; +#end if; + + while Continue loop + declare + Inst : Instruction_Type renames Program (PC); + Next_PC : PC_Type := PC + 1; + begin +#if Log then + Put_Line + ("Execute: " + & Opcode'Image (Inst.Kind) + & " at" & PC_Type'Image (PC)); +#end if; + case Inst.Kind is + when Halt => + Continue := False; + + when Jump => + Next_PC := Inst.Jump_Dest; + + when Branch => + if Pop /= 0 then + Next_PC := Inst.Jump_Dest; + end if; + + when Push_Lit => + Push (Inst.Push_Value); + + when Clone => + declare + Value : constant Integer := Pop; + begin + Push (Value); + Push (Value); + end; + + when Add => + Push (Pop + Pop); + end case; + PC := Next_PC; + end; + end loop; + +#if Log then + New_Line; + Put_Line ("Program stopped"); + Put_Line ("PC:" & PC_Type'Image (PC)); + Put_Line ("SP:" & SP_Type'Image (SP)); +#end if; + end Eval; + + ---------- + -- Eval -- + ---------- + + function Eval + (Program : Program_Type; + Stack_Size : Natural; + Initial_Values : Stack_Type) return Integer + is + SP_First : constant SP_Type := Initial_Values'First; + SP_Last : constant SP_Type := + Initial_Values'First + SP_Type (Stack_Size) - 1; + + Stack : Stack_Type (SP_First .. SP_Last); + PC : PC_Type := Program'First; + SP : SP_Type := Initial_Values'Last + 1; + begin + Stack (Initial_Values'Range) := Initial_Values; + Eval (Program, PC, Stack, SP); + return Stack (SP - 1); + end Eval; + +end VM; diff --git a/testsuite/tests/138-ada-preprocessing/example/vm.ads b/testsuite/tests/138-ada-preprocessing/example/vm.ads new file mode 100644 index 000000000..ab54260c6 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/example/vm.ads @@ -0,0 +1,30 @@ +package VM is + + type PC_Type is new Positive; + type SP_Type is new Positive; + + type Opcode is (Halt, Jump, Branch, Push_Lit, Clone, Add); + type Instruction_Type (Kind : Opcode := Opcode'First) is record + case Kind is + when Halt => null; + when Jump | Branch => Jump_Dest : PC_Type; + when Push_Lit => Push_Value : Integer; + when Clone | Add => null; + end case; + end record; + + type Stack_Type is array (SP_Type range <>) of Integer; + type Program_Type is array (PC_Type range <>) of Instruction_Type; + + procedure Eval + (Program : Program_Type; + PC : in out PC_Type; + Stack : in out Stack_type; + SP : in out SP_Type); + + function Eval + (Program : Program_Type; + Stack_Size : Natural; + Initial_Values : Stack_Type) return Integer; + +end VM; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/defs.txt b/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/defs.txt new file mode 100644 index 000000000..c986293b6 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/defs.txt @@ -0,0 +1 @@ +X := diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/pkg.adb new file mode 100644 index 000000000..05d1a6622 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/pkg.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + begin + $X Put_Line ("Hello, world!"); + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/prep.txt new file mode 100644 index 000000000..bd2ce2cfd --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_empty/prep.txt @@ -0,0 +1 @@ +* "defs.txt" diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_string/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/def_string/pkg.adb new file mode 100644 index 000000000..ad434c260 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_string/pkg.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + Word : constant String := $X; + begin + if Word = "world" then + Put_Line ("Hello, " & Word & "!"); + end if; + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_string/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/def_string/prep.txt new file mode 100644 index 000000000..c25e3de83 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_string/prep.txt @@ -0,0 +1 @@ +* -DX="world" diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/pkg.adb new file mode 100644 index 000000000..ebc61abec --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/pkg.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + Word : constant String := "world"; + begin + if $X = "world" then + Put_Line ("Hello, " & $X & "!"); + end if; + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/prep.txt new file mode 100644 index 000000000..f1fb4c0bf --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/def_symbol/prep.txt @@ -0,0 +1 @@ +* -DX=Word diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/default_config/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/default_config/pkg.adb new file mode 100644 index 000000000..10c58c803 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/default_config/pkg.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + begin + Put_Line ("Hello, " & $X & "!"); + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/default_config/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/default_config/prep.txt new file mode 100644 index 000000000..25f403e0f --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/default_config/prep.txt @@ -0,0 +1,2 @@ +"pkg.ads" -DY=foo +* -DX="world" diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/file_config/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/file_config/pkg.adb new file mode 100644 index 000000000..10c58c803 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/file_config/pkg.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + begin + Put_Line ("Hello, " & $X & "!"); + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/file_config/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/file_config/prep.txt new file mode 100644 index 000000000..90f0fd6b0 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/file_config/prep.txt @@ -0,0 +1,2 @@ +"pkg.adb" -DX="world" +* -DY=foo diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/main.adb b/testsuite/tests/138-ada-preprocessing/prep_data/main.adb new file mode 100644 index 000000000..c6304b2e7 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Run; +end Main; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/pkg.adb new file mode 100644 index 000000000..10d313e2f --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/pkg.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + begin +#if $X then + Put_Line ("X"); +#else + Put_Line ("not X"); +#end if; + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/prep.txt new file mode 100644 index 000000000..28d0582d1 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/prep.txt @@ -0,0 +1 @@ +* -DY=foo diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/pkg.ads b/testsuite/tests/138-ada-preprocessing/prep_data/pkg.ads new file mode 100644 index 000000000..28fc6b094 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Run; +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/test.py b/testsuite/tests/138-ada-preprocessing/prep_data/test.py new file mode 100644 index 000000000..e35269f52 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/test.py @@ -0,0 +1,117 @@ +""" +Exhaustively check that the features of preprocessing configuration are +correctly used. +""" + +from dataclasses import dataclass +import os +import os.path + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +@dataclass +class BaseTestcase: + label: str + + +@dataclass +class InstrErrorTestcase(BaseTestcase): + """Testcase that expects an instrumentation error.""" + expected_msg: str + """Regexp for the expected instrumentation error message.""" + + +@dataclass +class ReportTestcase(BaseTestcase): + """Testcase that expects successful instrumentation+build+coverage.""" + + expected_cov: dict[str, set[int]] + """Expected coverage report for "pkg.adb".""" + + +# Run a full instrument+build+coverage cycle on test projects that have their +# own "pkg.adb" implementation and "prep.txt" preprocesor configuration data. +# Both exercise a particular preprocessor configuration feature: the +# compilation would fail with a misimplementation for that feature. +for t in [ + ReportTestcase("def_empty", {"+": {7}}), + ReportTestcase("def_string", {"+": {6, 8, 9}}), + ReportTestcase("def_symbol", {"+": {6, 8, 9}}), + ReportTestcase("undef_is_false", {"+": {10, 14}}), + InstrErrorTestcase( + "no_undef_is_false", + ".*gnatcov.*: instrumentation failed for .*pkg\\.adb" + "\n.*gnatcov.*: please make sure the original project can be" + " compiled" + '\n.*gnatcov.*: pkg\\.adb:7:5: unknown symbol "\\$X"', + ), + ReportTestcase("default_config", {"+": {7}}), + ReportTestcase("file_config", {"+": {7}}), +]: + thistest.log(f"== {t.label} ==") + tmp = Wdir(f"tmp_{t.label}") + + # Avoid "creating output path" info messages + os.mkdir("obj") + + gprsw = GPRswitches( + root_project=gprfor( + mains=["main.adb"], + srcdirs=["..", f"../{t.label}"], + compiler_extra=( + 'for Default_Switches ("Ada")' + ' use ("-gnatep=" & Project\'Project_Dir' + f' & "/../{t.label}/prep.txt", ' + f' "-I" & Project\'Project_Dir & "../{t.label}");' + ), + ), + units=["pkg"], + ) + + if isinstance(t, InstrErrorTestcase): + # We expect an instrumentation error: check its message + log_filename = f"{t.label}-out.txt" + p = xcov_instrument( + gprsw=gprsw, + covlevel="stmt", + register_failure=False, + out=log_filename, + extra_args=["--save-temps"], + ) + thistest.fail_if( + p.status == 0, + "'gnatcov instrument' is supposed to fail", + ) + output = contents_of(log_filename) + thistest.fail_if_no_match( + "'gnatcov instrument' output", + t.expected_msg, + contents_of(log_filename).strip(), + ) + + else: + assert isinstance(t, ReportTestcase) + # If we expect a coverage report, compute it and check its contents + + build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_args=["--save-temps"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + ) + check_xcov_reports( + "*.xcov", {"pkg.adb.xcov": t.expected_cov}, cwd="xcov" + ) + + tmp.to_homedir() + thistest.log("") + +thistest.result() diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/pkg.adb new file mode 100644 index 000000000..966f0bfd3 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/pkg.adb @@ -0,0 +1,20 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Run is + begin +#if $X then + Invalid Statement +#else + Put_Line ("Hello, world!"); +#end if; + +#if not $X then + Put_Line ("Hello, world!"); +#else + Invalid Statement +#end if; + end Run; + +end Pkg; diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/prep.txt b/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/prep.txt new file mode 100644 index 000000000..97dd10651 --- /dev/null +++ b/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/prep.txt @@ -0,0 +1 @@ +* -DY=foo -u diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 15f05db27..fe1b15c93 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -136,6 +136,7 @@ package Command_Line is Opt_Dot_Replacement, Opt_Gnatem, Opt_Gnatec, + Opt_Ada_Preprocessor_Data, Opt_Project_Name, Opt_Source_Root); -- Set of string options we support. More complete descriptions below. @@ -1074,6 +1075,18 @@ package Command_Line is At_Most_Once => False, Internal => True), + Opt_Ada_Preprocessor_Data => Create + (Long_Name => "--ada-preprocessor-data", + Pattern => "NAME", + Help => + "Name of the file containing preprocessor configuration data for" + & " Ada.", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + Opt_Project_Name => Create (Long_Name => "--project-name", Pattern => "NAME", diff --git a/tools/gnatcov/instrument-ada_preprocessing.adb b/tools/gnatcov/instrument-ada_preprocessing.adb new file mode 100644 index 000000000..24fe4274f --- /dev/null +++ b/tools/gnatcov/instrument-ada_preprocessing.adb @@ -0,0 +1,314 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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.Exceptions; use Ada.Exceptions; +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO; + +with GNATCOLL.JSON; use GNATCOLL.JSON; + +with Langkit_Support.Errors; +with Libadalang.Preprocessing; use Libadalang.Preprocessing; + +with JSON; +with Outputs; use Outputs; +with Project; + +package body Instrument.Ada_Preprocessing is + + ----------------------------------- + -- Create_Preprocessor_Data_File -- + ----------------------------------- + + procedure Create_Preprocessor_Data_File (Filename : String) is + + function Serialize (Value : Value_Type) return JSON_Value; + -- Serialize Value to JSON + + function Serialize (Map : Definition_Maps.Map) return JSON_Value; + -- Serialize Map to JSON + + function Serialize (Config : File_Config) return JSON_Value; + -- Serialize Config to JSON + + --------------- + -- Serialize -- + --------------- + + function Serialize (Value : Value_Type) return JSON_Value is + begin + case Value.Kind is + when Libadalang.Preprocessing.Empty => + return Create; + when String_Literal => + return Result : constant JSON_Value := Create_Object do + Result.Set_Field ("kind", "string"); + Result.Set_Field ("value", Value.String_Value); + end return; + when Symbol => + return Result : constant JSON_Value := Create_Object do + Result.Set_Field ("kind", "symbol"); + Result.Set_Field ("value", Value.Symbol_Value); + end return; + end case; + end Serialize; + + function Serialize (Map : Definition_Maps.Map) return JSON_Value is + Result : constant JSON_Value := Create_Object; + begin + for Cur in Map.Iterate loop + declare + Name : constant US.Unbounded_String := + Definition_Maps.Key (Cur); + Value : Value_Type renames Map.Constant_Reference (Cur); + begin + Result.Set_Field (US.To_String (Name), Serialize (Value)); + end; + end loop; + return Result; + end Serialize; + + function Serialize (Config : File_Config) return JSON_Value is + begin + if not Config.Enabled then + return Create; + end if; + + return Result : constant JSON_Value := Create_Object do + Result.Set_Field ("definitions", Serialize (Config.Definitions)); + Result.Set_Field ("line_mode", Config.Line_Mode'Image); + Result.Set_Field ("print_symbols", Config.Print_Symbols); + Result.Set_Field ("undefined_is_false", Config.Undefined_Is_False); + end return; + end Serialize; + + Default_Config : File_Config; + File_Configs : File_Config_Maps.Map; + + Result : constant JSON_Value := Create_Object; + + -- Start of processing for Create_Preprocessor_Data_File + + begin + -- Extract preprocessor data from the loaded project + + begin + Extract_Preprocessor_Data_From_Project + (Tree => Project.Project.all, + Default_Config => Default_Config, + File_Configs => File_Configs); + exception + when Exc : Langkit_Support.Errors.File_Read_Error + | Langkit_Support.Errors.Syntax_Error + => + Outputs.Error + ("error while loading preprocessor data from project"); + Fatal_Error (Exception_Message (Exc)); + end; + + -- Refine it to make sure line number are preserved in the preprocessor + -- output. + + declare + procedure Process (Config : in out File_Config); + -- If Config enables preprocessing, set its line mode to Blank_Lines + + ------------- + -- Process -- + ------------- + + procedure Process (Config : in out File_Config) is + begin + if Config.Enabled then + Config.Line_Mode := Blank_Lines; + end if; + end Process; + begin + Iterate (Default_Config, File_Configs, Process'Access); + end; + + -- Serialize this data to JSON + + Result.Set_Field ("default_config", Serialize (Default_Config)); + declare + Map : constant JSON_Value := Create_Object; + begin + for Cur in File_Configs.Iterate loop + declare + Filename : constant US.Unbounded_String := + File_Config_Maps.Key (Cur); + begin + Map.Set_Field + (US.To_String (Filename), + Serialize (File_Configs.Constant_Reference (Cur))); + end; + end loop; + Result.Set_Field ("file_configs", Map); + end; + + -- Create the requested file + + declare + File : Ada.Text_IO.File_Type; + Doc : constant US.Unbounded_String := + Result.Write (Compact => False); + begin + Create (File, Out_File, Filename); + Put_Line (File, Doc); + Close (File); + end; + end Create_Preprocessor_Data_File; + + ------------------------- + -- Create_Preprocessor -- + ------------------------- + + function Create_Preprocessor + (Filename : String) + return Langkit_Support.File_Readers.File_Reader_Reference + is + Dummy : constant Context_Handle := + Create_Context + ("Loading preprocessor data from temporary file " & Filename); + + function Deserialize (Desc : JSON_Value) return Value_Type; + -- Deserialize Value from JSON + + function Deserialize (Desc : JSON_Value) return Definition_Maps.Map; + -- Deserialize Map from JSON + + function Deserialize (Desc : JSON_Value) return File_Config; + -- Deserialize Config from JSON + + ----------------- + -- Deserialize -- + ----------------- + + function Deserialize (Desc : JSON_Value) return Value_Type is + begin + if Desc.Kind = JSON_Null_Type then + return (Kind => Libadalang.Preprocessing.Empty); + end if; + + declare + Kind : constant String := Desc.Get ("kind"); + begin + if Kind = "string" then + return (Kind => String_Literal, + String_Value => Desc.Get ("value")); + elsif Kind = "symbol" then + return (Kind => Symbol, + Symbol_Value => Desc.Get ("value")); + else + Fatal_Error ("invalid value kind: " & Kind); + end if; + end; + end Deserialize; + + function Deserialize (Desc : JSON_Value) return Definition_Maps.Map is + begin + return Result : Definition_Maps.Map do + declare + procedure Process (Name : UTF8_String; Value : JSON_Value); + -- Deserialize a definition map from Value and add it under the + -- given Name to Result. + + ------------- + -- Process -- + ------------- + + procedure Process (Name : UTF8_String; Value : JSON_Value) is + begin + Result.Insert + (US.To_Unbounded_String (Name), Deserialize (Value)); + end Process; + begin + Desc.Map_JSON_Object (Process'Access); + end; + end return; + end Deserialize; + + function Deserialize (Desc : JSON_Value) return File_Config is + begin + if Desc.Kind = JSON_Null_Type then + return (Enabled => False); + end if; + + return Result : File_Config (Enabled => True) do + Result.Definitions := Deserialize (Desc.Get ("definitions")); + Result.Line_Mode := Any_Line_Mode'Value (Desc.Get ("line_mode")); + Result.Print_Symbols := Desc.Get ("print_symbols"); + Result.Undefined_Is_False := Desc.Get ("undefined_is_false"); + end return; + end Deserialize; + + Default_Config : File_Config; + File_Configs : File_Config_Maps.Map; + + Parsed_JSON : Read_Result; + + -- Start of processing for Create_Preprocessor + + begin + -- Parse the preprocessor data from the given filename + + Parsed_JSON := JSON.Read (Filename); + if not Parsed_JSON.Success then + Fatal_Error + ("Parsing error: " & Format_Parsing_Error (Parsed_JSON.Error)); + end if; + + declare + Dummy : constant Context_Handle := + Create_Context + ("Loading preprocessor data from temporary file " & Filename + & " for the default config"); + begin + Default_Config := + Deserialize (Parsed_JSON.Value.Get ("default_config")); + end; + + declare + File_Configs_Desc : constant JSON_Value := + Parsed_JSON.Value.Get ("file_configs"); + + procedure Process (Name : UTF8_String; Value : JSON_Value); + -- Deserialize a file config from Value and add it under the given + -- Name to File_Configs. + + ------------- + -- Process -- + ------------- + + procedure Process (Name : UTF8_String; Value : JSON_Value) is + Dummy : constant Context_Handle := + Create_Context + ("Loading preprocessor data from temporary file " & Filename + & " for " & Name); + begin + File_Configs.Insert + (US.To_Unbounded_String (Name), Deserialize (Value)); + end Process; + begin + File_Configs_Desc.Map_JSON_Object (Process'Access); + end; + + return Create_Preprocessor (Default_Config, File_Configs); + end Create_Preprocessor; + +end Instrument.Ada_Preprocessing; diff --git a/tools/gnatcov/instrument-ada_preprocessing.ads b/tools/gnatcov/instrument-ada_preprocessing.ads new file mode 100644 index 000000000..ec0e3fcf6 --- /dev/null +++ b/tools/gnatcov/instrument-ada_preprocessing.ads @@ -0,0 +1,41 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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 Langkit_Support.File_Readers; use Langkit_Support.File_Readers; + +-- Helpers to implement support for the Ada sources. +-- +-- Just like for the Ada unit provider (Instrument.Ada_Unit_Provider), we need +-- the Ada instrumenter to work without loading the GPR tree. To achieve this, +-- preprocessor configuration data is first extracted from project files, then +-- stored in a JSON file (Create_Preprocessor_Data_File below), which the Ada +-- instrumenter can then load (Create_Preprocessor below). + +package Instrument.Ada_Preprocessing is + + procedure Create_Preprocessor_Data_File (Filename : String); + -- Write in Filename a JSON representation of the preprocessor data + -- extracted from the root project + + function Create_Preprocessor + (Filename : String) return File_Reader_Reference; + -- Load preprocessor data from a file written by + -- Create_Preprocessor_Data_File and create a file reader to preprocess Ada + -- sources according to this data. + +end Instrument.Ada_Preprocessing; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 6ee3dfb77..1a15acefc 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -46,6 +46,7 @@ with ALI_Files; use ALI_Files; with Coverage_Options; use Coverage_Options; with Coverage; use Coverage; with Diagnostics; use Diagnostics; +with Instrument.Ada_Preprocessing; with Namet; use Namet; with Outputs; use Outputs; with Paths; use Paths; @@ -6756,7 +6757,8 @@ package body Instrument.Ada_Unit is Instrumenter.Context := Create_Context (Unit_Provider => Create_Unit_Provider_Reference (Instrumenter.Provider), - Event_Handler => Instrumenter.Event_Handler); + Event_Handler => Instrumenter.Event_Handler, + File_Reader => Instrumenter.File_Reader); Instrumenter.Get_From_File_Count := 0; -- Load configuration pragmas. TODO???: clarify what happens when there @@ -9010,10 +9012,11 @@ package body Instrument.Ada_Unit is ----------------------------- function Create_Ada_Instrumenter - (Tag : Unbounded_String; + (Tag : Unbounded_String; Config_Pragmas_Filename, - Mapping_Filename : String; - Predefined_Source_Dirs : String_Vectors.Vector) + Mapping_Filename : String; + Predefined_Source_Dirs : String_Vectors.Vector; + Preprocessor_Data_Filename : String) return Ada_Instrumenter_Type is Instrumenter : Ada_Instrumenter_Type; @@ -9026,6 +9029,13 @@ package body Instrument.Ada_Unit is Instrument.Ada_Unit_Provider.Create_Provider (Predefined_Source_Dirs, Mapping_Filename); + -- Create a file reader, to let Libadalang preprocess source files that + -- need it. + + Instrumenter.File_Reader := + Instrument.Ada_Preprocessing.Create_Preprocessor + (Preprocessor_Data_Filename); + -- Create the event handler, to report when Libadalang cannot read a -- required source file. diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 54b4facdb..9410ca1d4 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -24,6 +24,7 @@ with Ada.Strings.Unbounded; with Ada.Strings.Wide_Wide_Hash; with Ada.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; +with Langkit_Support.File_Readers; with Langkit_Support.Text; use Langkit_Support.Text; with Libadalang.Analysis; use Libadalang.Analysis; with Libadalang.Rewriting; use Libadalang.Rewriting; @@ -44,6 +45,9 @@ package Instrument.Ada_Unit is -- and to not depend on project files in the unit instrumentation -- process. + File_Reader : Langkit_Support.File_Readers.File_Reader_Reference; + -- File reader to preprocess source files when needed + Event_Handler : Libadalang.Analysis.Event_Handler_Reference; -- Event handler to warn about missing source files @@ -103,18 +107,28 @@ package Instrument.Ada_Unit is Prj : Prj_Desc); function Create_Ada_Instrumenter - (Tag : Unbounded_String; + (Tag : Unbounded_String; Config_Pragmas_Filename, - Mapping_Filename : String; - Predefined_Source_Dirs : String_Vectors.Vector) + Mapping_Filename : String; + Predefined_Source_Dirs : String_Vectors.Vector; + Preprocessor_Data_Filename : String) return Ada_Instrumenter_Type; - -- Create an Ada instrumenter. Config_Pragmas_Filename is the fullname - -- to the configuration pragma file. Mapping_Filename is the fullname - -- to the mapping file, which maps unit names to file fullnames, and - -- Predefined_Source_Dirs is the list of directories hosting runtime - -- files. The two last parameters are used to instantiate our - -- custom unit provider, which does not rely on project files - -- (see Instrument.Ada_Unit_Provider). + -- Create an Ada instrumenter. + -- + -- Config_Pragmas_Filename is the fullname to the configuration pragma + -- file. + -- + -- Mapping_Filename is the fullname to the mapping file, which maps unit + -- names to file fullnames. + -- + -- Predefined_Source_Dirs is the list of directories hosting runtime files. + -- + -- Both Mapping_Filename and Predefined_Source_Dirs are used to instantiate + -- our custom unit provider, which does not rely on project files (see + -- Instrument.Ada_Unit_Provider). + -- + -- Preprocessor_Data_Filename is the name of the file that contains + -- preprocessor configuration data (see Instrument.Ada_Preprocessing). -- Private declarations relative to the AST traversal private diff --git a/tools/gnatcov/instrument-ada_unit__stub.ads b/tools/gnatcov/instrument-ada_unit__stub.ads index a1dddb09d..1eb4e78f8 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.ads +++ b/tools/gnatcov/instrument-ada_unit__stub.ads @@ -34,10 +34,11 @@ package Instrument.Ada_Unit is is (Ada_Language); function Create_Ada_Instrumenter - (Tag : Unbounded_String; + (Tag : Unbounded_String; Config_Pragmas_Filename, - Mapping_Filename : String; - Predefined_Source_Dirs : String_Vectors.Vector) + Mapping_Filename : String; + Predefined_Source_Dirs : String_Vectors.Vector; + Preprocessor_Data_Filename : String) return Ada_Instrumenter_Type is (Ada_Instrumenter_Type'(others => <>)); diff --git a/tools/gnatcov/instrument-config.adb b/tools/gnatcov/instrument-config.adb index 52c04a534..9d5bff6df 100644 --- a/tools/gnatcov/instrument-config.adb +++ b/tools/gnatcov/instrument-config.adb @@ -35,13 +35,15 @@ begin case Language is when Ada_Language => return Create_Ada_Instrumenter - (Tag => Tag, - Config_Pragmas_Filename => + (Tag => Tag, + Config_Pragmas_Filename => +Args.String_Args (Opt_Gnatec).Value, - Mapping_Filename => + Mapping_Filename => +Args.String_Args (Opt_Gnatem).Value, - Predefined_Source_Dirs => - Args.String_List_Args (Opt_Runtime_Dir)); + Predefined_Source_Dirs => + Args.String_List_Args (Opt_Runtime_Dir), + Preprocessor_Data_Filename => + +Args.String_Args (Opt_Ada_Preprocessor_Data).Value); when C_Language => return Create_C_Instrumenter (Tag => Tag); when CPP_Language => diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 626a4783b..b53a40d03 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -44,6 +44,7 @@ with Binary_Files; with Command_Line; use Command_Line; with Files_Table; with Instrument.Ada_Unit; use Instrument.Ada_Unit; +with Instrument.Ada_Preprocessing; with Instrument.C; use Instrument.C; with Instrument.Clean_Objdirs; with Instrument.Common; use Instrument.Common; @@ -174,6 +175,10 @@ is -- (for Ada), to know which part of a unit (spec / body / separate) must -- be instrumented. + Ada_Preprocessor_Data_File : Unbounded_String; + -- JSON file that contains the preprocessor data necessary to analyze + -- Ada sources (see Instrument.Ada_Unit.Create_Preprocessor_Data_File). + Ignored_Source_Files_Present : Boolean; Ignored_Source_Files : GNAT.Regexp.Regexp; -- If present, instrumentation will ignore files whose names match the @@ -615,6 +620,8 @@ is begin Result.Append ("--gnatem=" & IC.Mapping_File); Result.Append ("--gnatec=" & IC.Config_Pragmas_File); + Result.Append + ("--ada-preprocessor-data=" & IC.Ada_Preprocessor_Data_File); -- Load the predefined source directories @@ -1136,6 +1143,11 @@ begin +Create_Config_Pragmas_File (Project.Project.Root_Project); IC.Sources_Of_Interest_Response_File := +To_String (Root_Project_Info.all.Output_Dir) / ".sources_of_interest"; + IC.Ada_Preprocessor_Data_File := + +To_String (Root_Project_Info.all.Output_Dir) / "prep-data.json"; + + Instrument.Ada_Preprocessing.Create_Preprocessor_Data_File + (+IC.Ada_Preprocessor_Data_File); -- Set the runtime directories @@ -1155,10 +1167,11 @@ begin Ada_Instrumenter := Create_Ada_Instrumenter - (IC.Tag, - +IC.Config_Pragmas_File, - +IC.Mapping_File, - IC.Predefined_Source_Dirs); + (Tag => IC.Tag, + Config_Pragmas_Filename => +IC.Config_Pragmas_File, + Mapping_Filename => +IC.Mapping_File, + Predefined_Source_Dirs => IC.Predefined_Source_Dirs, + Preprocessor_Data_Filename => +IC.Ada_Preprocessor_Data_File); C_Instrumenter := Create_C_Instrumenter (IC.Tag); CPP_Instrumenter := Create_CPP_Instrumenter (IC.Tag); @@ -1439,6 +1452,7 @@ begin if not Args.Bool_Args (Opt_Save_Temps) then Ada.Directories.Delete_File (+IC.Sources_Of_Interest_Response_File); + Ada.Directories.Delete_File (+IC.Ada_Preprocessor_Data_File); end if; -- Emit the unit to contain the list of coverage buffers, exported to a From e601d594e44aa49066a01911be9c7ecfb1ec9eb9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 6 Nov 2023 09:05:15 +0000 Subject: [PATCH 0480/1483] src_traces.rst: fix minor formatting issues --- doc/gnatcov/src_traces.rst | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 98394bd07..818d0f813 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -413,18 +413,19 @@ state. Should the default limit not be satisfactory, it can be tuned with the option :cmd-option:`--path-count-limit`. Other source-traces limitations -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ In Ada, variable or type declarations at the package level can yield elaboration code. Such code constructs are thus considered to have corresponding coverage obligations -In the case where a `pragma Preelaborate` restriction affects the instrumented -unit, variable and type declarations at the package level are not considered as -coverage obligations, although some elaboration code may still be emitted in -rare instances. Note that declarations within a unit constrained by a -``No_Elaboration_Code`` pragma don't produce coverage obligation either, which -is always correct as no executable code can be emitted by the compiler for them. +In the case where a ``pragma Preelaborate`` restriction affects the +instrumented unit, variable and type declarations at the package level are not +considered as coverage obligations, although some elaboration code may still be +emitted in rare instances. Note that declarations within a unit constrained by +a ``No_Elaboration_Code`` pragma don't produce coverage obligation either, +which is always correct as no executable code can be emitted by the compiler +for them. There are also a few limitations concerning the source trace workflow as a whole: @@ -686,7 +687,7 @@ Setting up the coverage runtime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ As seen in the :ref:`instr-rts` section, we use the ``gnatcov setup`` command to -build and install the :term:`coverage runtime `:: +build and install the :term:`coverage runtime `. For our intended target environment, this would be something like:: From dce3c3fcdf9012f0aba9ac1aad7e787acb7dba33 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 8 Nov 2023 09:55:49 +0100 Subject: [PATCH 0481/1483] unit_of_interest.rst: fix minor formatting issues --- doc/gnatcov/units_of_interest.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gnatcov/units_of_interest.rst b/doc/gnatcov/units_of_interest.rst index 10cf8180a..57a830dc8 100644 --- a/doc/gnatcov/units_of_interest.rst +++ b/doc/gnatcov/units_of_interest.rst @@ -204,7 +204,7 @@ and then executing:: gnatcov --units=@units.list Conveying *subprograms* of interest -********************************* +*********************************** |gcv| enables even finer grain control through the use of ``--subprograms`` switch, which restricts coverage analysis to the specified list of subprograms From 39fe37257f58c06994c809d6443367e7e8693de2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 6 Nov 2023 09:22:47 +0000 Subject: [PATCH 0482/1483] Document the support for preprocessing in Ada --- doc/gnatcov/src_traces.rst | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 818d0f813..4f183aff7 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -362,6 +362,31 @@ within the same environment, the variable name for a program can actually be tailored by passing a :cmd-option:`--dump-filename-env-var` switch to |gcvins|, providing the variable name to use. +Support for preprocessing +------------------------- + +|gcvins| automatically detects preprocessor configuration from the compiler +switches present in project files (``-gnatep`` and ``-gnateD`` for Ada sources, +``-D`` and the like for C/C++ sources). It then runs preprocessing on the +source code *before* the instrumentation itself happens. This allows gnatcov +to compute the code coverage only for code that is left "enabled" by +preprocessing directives: disabled code (for instance what follows ``#if Debug +then`` in Ada when the preprocessing symbol ``Debug`` is set to ``False``) is +ignored and thus creates no coverage obligation. Note that consolidation will +not help including code from all "preprocessing branches" in coverage reports, +as gnatcov requires (and checks) that coverage obligations are the same for two +units to consolidate. + +Ada pecularities +^^^^^^^^^^^^^^^^ + +The coverage obligations for code that comes from symbol expansion (for +example, ``$Foo = 42`` expanded into ``My_Variable = 42`` with +``-Dfoo=My_Variable``) designate expanded code. Even though line numbers are +preserved during preprocessing, column numbers may be different between the +original code and the preprocessed code and thus the coverage report. + + .. _instr-limitations: |gcvins| limitations @@ -417,7 +442,7 @@ Other source-traces limitations In Ada, variable or type declarations at the package level can yield elaboration code. Such code constructs are thus considered to have corresponding coverage -obligations +obligations. In the case where a ``pragma Preelaborate`` restriction affects the instrumented unit, variable and type declarations at the package level are not @@ -430,8 +455,7 @@ for them. There are also a few limitations concerning the source trace workflow as a whole: -- Separate analysis of generic package instances is not supported, -- Preprocessing directives are ignored by the source instrumenter. +- Separate analysis of generic package instances is not supported. Toolchain-specific limitations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From ec63dd9d96417767790c8c18fd01aa14cc4055e2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 6 Nov 2023 16:03:03 +0000 Subject: [PATCH 0483/1483] Minor refactorings/reformattings/typo fixes --- testsuite/tests/subp_of_interest/test.py | 25 +++++++------- testsuite/tests/subp_of_interest_c/test.py | 4 +-- tools/gnatcov/coverage-source.adb | 17 ++++++---- tools/gnatcov/gnatcov_bits_specific.adb | 26 +++++++-------- tools/gnatcov/sc_obligations.adb | 38 ++++++++++++++-------- tools/gnatcov/sc_obligations.ads | 12 ++++--- 6 files changed, 69 insertions(+), 53 deletions(-) diff --git a/testsuite/tests/subp_of_interest/test.py b/testsuite/tests/subp_of_interest/test.py index cb4f971cb..e2bec5696 100644 --- a/testsuite/tests/subp_of_interest/test.py +++ b/testsuite/tests/subp_of_interest/test.py @@ -47,8 +47,8 @@ if thistest.options.trace_mode == "bin": thistest.fail_if_no_match( "gnatcov coverage output", - "warning: Ignoring --subprograms switches as this is not supported with" - " binary traces.", + "warning: Ignoring --subprograms switches as this is not supported" + " with binary traces.", contents_of("coverage.log"), ) else: @@ -61,9 +61,9 @@ "xcov_subp", ) - # Then check that the checkpoint contains only coverage data for the specific - # subprogram. To do this, produce a new coverage report from the checkpoint - # without using the --subprograms switch. + # Then check that the checkpoint contains only coverage data for the + # specific subprogram. To do this, produce a new coverage report from the + # checkpoint without using the --subprograms switch. xcov( cov_args[:-1] + ["--checkpoint", "trace.ckpt", "--output-dir=xcov_no_subp"] @@ -90,10 +90,12 @@ regexp=r".*Wrong argument passed to --subprograms: .*", actual=contents_of("xcov-wrong1.txt"), ) - + # Case 2: line number is not a number xcov( - cov_args + ["--subprograms", f"{os.path.join('..', 'src', 'pkg.ads')}:b",], + cov_args + [ + "--subprograms", f"{os.path.join('..', 'src', 'pkg.ads')}:b", + ], out="xcov-wrong2.txt", register_failure=False, ) @@ -102,7 +104,7 @@ regexp=r".*Wrong argument passed to --subprograms: .*", actual=contents_of("xcov-wrong2.txt"), ) - + # Case 3: file does not exist xcov( cov_args + ["--subprograms", "dumb-file-name:4"], @@ -111,11 +113,12 @@ ) thistest.fail_if_no_match( what="unexpected coverage output", - regexp=r".*Error when parsing --subprograms argument dumb-file-name:4:" - r".*dumb-file-name does not exist", + regexp=( + r".*Error when parsing --subprograms argument dumb-file-name:4:" + r".*dumb-file-name does not exist" + ), actual=contents_of("xcov-wrong3.txt"), ) - thistest.result() diff --git a/testsuite/tests/subp_of_interest_c/test.py b/testsuite/tests/subp_of_interest_c/test.py index c2c209bf0..d58f1e4ab 100644 --- a/testsuite/tests/subp_of_interest_c/test.py +++ b/testsuite/tests/subp_of_interest_c/test.py @@ -10,8 +10,8 @@ from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest -from SUITE.cutils import contents_of, Wdir -from SUITE.tutils import gprfor, xcov +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor from SUITE.gprutils import GPRswitches tmp = Wdir("tmp_") diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 906ba7c2f..451aa69a7 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -1948,6 +1948,7 @@ package body Coverage.Source is is CU : CU_Id; BM : CU_Bit_Maps; + ST : Scope_Traversal_Type; procedure Set_Executed (SCI : in out Source_Coverage_Info); -- Mark SCI as executed @@ -1962,6 +1963,12 @@ package body Coverage.Source is when File_Based_Language => +CU_Name.Filename); -- Helper to refer to the instrumented unit in an error message + procedure Update_SCI_Wrapper + (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 + ------------------ -- Set_Executed -- ------------------ @@ -1985,13 +1992,9 @@ package body Coverage.Source is when Unit_Separate => "separate"); end Part_Image; - ST : Scope_Traversal_Type; - - procedure Update_SCI_Wrapper - (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 + ------------------------ + -- Update_SCI_Wrapper -- + ------------------------ procedure Update_SCI_Wrapper (SCO : SCO_Id; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 181e8cc41..3c56c6622 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -367,14 +367,15 @@ procedure GNATcov_Bits_Specific is -- Process_Subp_Input -- ------------------------ - procedure Process_Subp_Input (Subp_Input : String) - is - Colon_Index : constant Natural := + procedure Process_Subp_Input (Subp_Input : String) is + Column_Index : constant Natural := Ada.Strings.Fixed.Index (Subp_Input, Ada.Strings.Maps.To_Set (':')); - Filename : constant String := - Subp_Input (Subp_Input'First .. Colon_Index - 1); + Filename : String renames + Subp_Input (Subp_Input'First .. Column_Index - 1); + Column : String renames + Subp_Input (Column_Index + 1 .. Subp_Input'Last); begin - if Colon_Index = 0 then + if Column_Index = 0 then raise Constraint_Error; end if; if not Exists (Filename) then @@ -385,14 +386,10 @@ procedure GNATcov_Bits_Specific is Subps_Of_Interest.Include (Scope_Entity_Identifier' (Decl_SFI => - Get_Index_From_Full_Name - (Full_Name (Filename), Source_File), - Decl_Line => - Natural'Value - (Subp_Input (Colon_Index + 1 .. Subp_Input'Last)))); - + Get_Index_From_Full_Name (Full_Name (Filename), Source_File), + Decl_Line => Natural'Value (Column))); exception - -- Deal gracefully with parsing errors + -- Deal gracefully with parsing errors when Constraint_Error => Outputs.Fatal_Error @@ -1771,8 +1768,7 @@ begin -- Warn when the user hasn't explicitly set a coverage level and -- default to stmt. - if not (Source_Coverage_Enabled or else Object_Coverage_Enabled) - then + if not (Source_Coverage_Enabled or else Object_Coverage_Enabled) then Warn ("Coverage level not specified on the command line or in the" & " project file (--level=" & Source_Level_Options & "|" & Object_Level_Options ("|") & "), defaulting to" diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 64501e614..0d790df06 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -601,8 +601,7 @@ package body SC_Obligations is -- Scope_Traversal -- --------------------- - function Scope_Traversal (CU : CU_Id) return Scope_Traversal_Type - is + function Scope_Traversal (CU : CU_Id) return Scope_Traversal_Type is Result : Scope_Traversal_Type; begin if CU = No_CU_Id then @@ -614,8 +613,7 @@ package body SC_Obligations is (CU_Vector.Reference (CU).Element.Scope_Entities)); Result.Scope_Stack := Scope_Stacks.Empty_List; Result.Active_Scopes := Scope_Id_Sets.Empty; - Result.Active_Scope_Ent := Result.It.First; - Result.Next_Scope_Ent := Result.It.Next (Result.Active_Scope_Ent); + Set_Active_Scope_Ent (Result, Result.It.First); return Result; end Scope_Traversal; @@ -623,10 +621,7 @@ package body SC_Obligations is -- Traverse_SCO -- ------------------ - procedure Traverse_SCO - (ST : in out Scope_Traversal_Type; - SCO : SCO_Id) - is + procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) is use Scope_Entities_Trees; begin -- In some cases (C metaprogramming instances), e.g. @@ -662,18 +657,17 @@ package body SC_Obligations is while SCO > Element (ST.Active_Scope_Ent).To or else (ST.Next_Scope_Ent /= No_Element - and then SCO >= Element (ST.Next_Scope_Ent).From) + and then SCO >= Element (ST.Next_Scope_Ent).From) loop - -- We can enter the next scope only when we have reached its - -- parent scope. If the next scope is null, this means that we - -- are in the last scope of the unit. + -- We can enter the next scope only when we have reached its parent + -- scope. If the next scope is null, this means that we are in the + -- last scope of the unit. if ST.Next_Scope_Ent /= No_Element and then ST.Active_Scope_Ent = Parent (ST.Next_Scope_Ent) and then SCO >= Element (ST.Next_Scope_Ent).From then - ST.Active_Scope_Ent := ST.Next_Scope_Ent; - ST.Next_Scope_Ent := ST.It.Next (ST.Next_Scope_Ent); + Set_Active_Scope_Ent (ST, ST.Next_Scope_Ent); ST.Scope_Stack.Append (ST.Active_Scope_Ent); ST.Active_Scopes.Insert (Element (ST.Active_Scope_Ent).Identifier); @@ -689,6 +683,18 @@ package body SC_Obligations is end loop; end Traverse_SCO; + -------------------------- + -- Set_Active_Scope_Ent -- + -------------------------- + + procedure Set_Active_Scope_Ent + (ST : in out Scope_Traversal_Type; + Scope_Ent : Scope_Entities_Trees.Cursor) is + begin + ST.Active_Scope_Ent := Scope_Ent; + ST.Next_Scope_Ent := ST.It.Next (Scope_Ent); + end Set_Active_Scope_Ent; + --------------- -- Is_Active -- --------------- @@ -1376,6 +1382,10 @@ package body SC_Obligations is end if; end Checkpoint_Load_Unit; + ---------- + -- Free -- + ---------- + procedure Free (CU : in out CU_Info) is procedure Free is new Ada.Unchecked_Deallocation (Statement_Bit_Map, Statement_Bit_Map_Access); diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 9cebfd9fa..8b59f728b 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -180,7 +180,7 @@ package SC_Obligations is type Scope_Entity is record From, To : SCO_Id; -- SCO range for this scope. As scope entities are computed during - -- instrumentation, From and To designates low level SCOs that are then + -- instrumentation, From and To designate low level SCOs that are then -- converted to high level SCOs after processing the low level SCOs. Name : Unbounded_String; @@ -232,9 +232,7 @@ package SC_Obligations is function Scope_Traversal (CU : CU_Id) return Scope_Traversal_Type; -- Return a scope traversal for the given compilation unit - procedure Traverse_SCO - (ST : in out Scope_Traversal_Type; - SCO : SCO_Id); + procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id); -- Traverse the given SCO and update the Scope_Traversal accordingly. Note -- that the scope traversal must be done on increasing SCOs identifiers. @@ -1366,6 +1364,12 @@ private -- Iterator to traverse the scope tree end record; + procedure Set_Active_Scope_Ent + (ST : in out Scope_Traversal_Type; + Scope_Ent : Scope_Entities_Trees.Cursor); + -- Set ST.Active_Scope_Ent to Scope_Ent and set ST.Next_Scope_Ent to the + -- next one according to ST's iterator. + No_Scope_Traversal : Scope_Traversal_Type := (Scope_Entities => Scope_Entities_Trees.Empty_Tree, Scope_Stack => Scope_Stacks.Empty_List, From 434d99fae909cdf0784184bd80ffe504350d3609 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 7 Nov 2023 09:13:35 +0000 Subject: [PATCH 0484/1483] subp_of_interest: check that coverage logs are empty --- testsuite/tests/subp_of_interest/test.py | 51 +++++++++++++++++------- 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/testsuite/tests/subp_of_interest/test.py b/testsuite/tests/subp_of_interest/test.py index e2bec5696..d2e9e3813 100644 --- a/testsuite/tests/subp_of_interest/test.py +++ b/testsuite/tests/subp_of_interest/test.py @@ -13,8 +13,29 @@ from SUITE.tutils import gprfor, xcov from SUITE.gprutils import GPRswitches + +src_traces = thistest.options.trace_mode == "src" + + +def check_xcov(label, args, expected_output=""): + """ + Run xcov with the given aruments and check its output. + + Also pass it --output-dir={label}, and create that directory beforehand. + """ + log = f"{label}.log" + os.mkdir(label) + xcov(args + [f"--output-dir={label}"], out=log) + thistest.fail_if_not_equal( + "'gnatcov coverage' output", + expected_output, + contents_of(log).strip(), + ) + + tmp = Wdir("tmp_") +thistest.log("== Checkpoint creation ==") cov_args = build_and_run( gprsw=GPRswitches( gprfor(srcdirs=os.path.join("..", "src"), mains=["main.adb"]) @@ -28,8 +49,8 @@ # that the coverage report contains only coverage data for the specified # subprograms for source traces. For binary traces, simply check that the # gnatcov coverage invocation yields the expected warning. -os.mkdir("xcov_subp") -xcov( +check_xcov( + "xcov_subp", cov_args + [ "--save-checkpoint", @@ -40,18 +61,15 @@ f"{os.path.join('..', 'src', 'pkg.adb')}:10", "--subprograms", f"{os.path.join('..', 'src', 'pkg.adb')}:12", - "--output-dir=xcov_subp", ], - out="coverage.log", -) -if thistest.options.trace_mode == "bin": - thistest.fail_if_no_match( - "gnatcov coverage output", + expected_output=( + "" + if src_traces else "warning: Ignoring --subprograms switches as this is not supported" - " with binary traces.", - contents_of("coverage.log"), - ) -else: + " with binary traces." + ), +) +if src_traces: check_xcov_reports( "*.xcov", { @@ -64,9 +82,11 @@ # Then check that the checkpoint contains only coverage data for the # specific subprogram. To do this, produce a new coverage report from the # checkpoint without using the --subprograms switch. - xcov( + thistest.log("== xcov_no_subp ==") + check_xcov( + "xcov_no_subp", cov_args[:-1] - + ["--checkpoint", "trace.ckpt", "--output-dir=xcov_no_subp"] + + ["--checkpoint", "trace.ckpt"], ) check_xcov_reports( "*.xcov", @@ -80,6 +100,7 @@ # Also check the warnings when the subprogram switch is ill-formed # Case 1: missing colon in the argument + thistest.log("== Missing colon ==") xcov( cov_args + ["--subprograms", "no-colon"], out="xcov-wrong1.txt", @@ -92,6 +113,7 @@ ) # Case 2: line number is not a number + thistest.log("== Bad line number ==") xcov( cov_args + [ "--subprograms", f"{os.path.join('..', 'src', 'pkg.ads')}:b", @@ -106,6 +128,7 @@ ) # Case 3: file does not exist + thistest.log("== No such file ==") xcov( cov_args + ["--subprograms", "dumb-file-name:4"], out="xcov-wrong3.txt", From fd2d2a78af206ce6b0e8f1f7b4e62c0dbd5ef2e0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 7 Nov 2023 09:53:01 +0000 Subject: [PATCH 0485/1483] Add verbose output to show the scope entities structure This will help understand what scope entities are created for input sources, for debugging purposes. --- tools/gnatcov/gnatcov_bits_specific.adb | 10 +++++ tools/gnatcov/sc_obligations.adb | 60 +++++++++++++++++++++++++ tools/gnatcov/sc_obligations.ads | 12 +++++ tools/gnatcov/slocs.adb | 5 +++ tools/gnatcov/slocs.ads | 2 + 5 files changed, 89 insertions(+) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 3c56c6622..ad1ccc478 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -418,6 +418,16 @@ procedure GNATcov_Bits_Specific is Create_Matcher (Ignored_Source_Files, Matcher, Has_Matcher); Inputs.Iterate (SID_Inputs, SID_Load_Wrapper'Access); + -- Now that all the scope entities that can be referenced by + -- --subprograms are known, dump them in verbose mode. + + if Verbose then + for CU in 1 .. Last_CU loop + Put_Line ("Scopes for " & Image (CU) & ":"); + Dump (Get_Scope_Entities (CU), Line_Prefix => "| "); + end loop; + end if; + -- Parse the listed subprograms of interest Copy_Arg_List (Opt_Subp_Of_Interest, Subprograms_Inputs); diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 0d790df06..266f99ab6 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -597,6 +597,44 @@ package body SC_Obligations is -- -- ??? Same comment as above. + ----------- + -- Image -- + ----------- + + function Image (SE : Scope_Entity) return String is + begin + return + "Scope for " + & Ada.Strings.Unbounded.To_String (SE.Name) + & "[" & Slocs.Image (SE.Sloc) + & "], identifier at " + & Get_Simple_Name (SE.Identifier.Decl_SFI) + & ":" & Img (SE.Identifier.Decl_Line); + end Image; + + ---------- + -- Dump -- + ---------- + + procedure Dump + (Scope_Entities : Scope_Entities_Trees.Tree; Line_Prefix : String := "") + is + use Scope_Entities_Trees; + begin + for Cur in Scope_Entities.Iterate loop + declare + Prefix : constant String := + Line_Prefix & (1 .. 2 * (Natural (Depth (Cur)) - 2) => ' '); + SE : Scope_Entity renames + Scope_Entities.Constant_Reference (Cur); + begin + Put_Line (Prefix & Image (SE)); + Put_Line (Prefix & "... from " & Image (SE.From)); + Put_Line (Prefix & " to " & Image (SE.To)); + end; + end loop; + end Dump; + --------------------- -- Scope_Traversal -- --------------------- @@ -2699,6 +2737,28 @@ package body SC_Obligations is return Sloc; end Last_Sloc; + ----------- + -- Image -- + ----------- + + function Image (CU : CU_Id) return String is + begin + return + (if CU = No_CU_Id + then "No CU" + else "CU " + & Get_Full_Name (CU_Vector.Constant_Reference (CU).Main_Source)); + end Image; + + ------------- + -- Last_CU -- + ------------- + + function Last_CU return CU_Id is + begin + return CU_Vector.Last_Index; + end Last_CU; + -------------- -- Provider -- -------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 8b59f728b..0361188a8 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -108,6 +108,11 @@ package SC_Obligations is No_CU_Id : constant CU_Id := 0; subtype Valid_CU_Id is CU_Id range No_CU_Id + 1 .. CU_Id'Last; + function Image (CU : CU_Id) return String; + + function Last_CU return CU_Id; + -- Return the last compilation unit that was created so far + package CU_Id_Vectors is new Ada.Containers.Vectors (Positive, CU_Id); function Provider (CU : CU_Id) return SCO_Provider; @@ -203,6 +208,8 @@ package SC_Obligations is -- This information is computed by the instrumenters (that know what is -- a scope, and what is not). + function Image (SE : Scope_Entity) return String; + package Scope_Id_Sets is new Ada.Containers.Ordered_Sets (Element_Type => Scope_Entity_Identifier); subtype Scope_Id_Set is Scope_Id_Sets.Set; @@ -211,6 +218,11 @@ package SC_Obligations is (Element_Type => Scope_Entity); subtype Scope_Entities_Tree is Scope_Entities_Trees.Tree; + procedure Dump + (Scope_Entities : Scope_Entities_Trees.Tree; Line_Prefix : String := ""); + -- Debug helper: print a representation of Scope_Entities on the standard + -- output. Each line that is printed has the given Line_Prefix. + subtype Tree_Iterator is Scope_Entities_Trees.Tree_Iterator_Interfaces.Forward_Iterator'Class; type Iterator_Acc is access Tree_Iterator; diff --git a/tools/gnatcov/slocs.adb b/tools/gnatcov/slocs.adb index 5167e2bc5..080e9a222 100644 --- a/tools/gnatcov/slocs.adb +++ b/tools/gnatcov/slocs.adb @@ -143,6 +143,11 @@ package body Slocs is -- Image -- ----------- + function Image (Sloc : Local_Source_Location) return String is + begin + return Img (Sloc.Line) & ":" & Img (Sloc.Column); + end Image; + function Image (Sloc : Source_Location; Unique_Name : Boolean := False) return String is diff --git a/tools/gnatcov/slocs.ads b/tools/gnatcov/slocs.ads index 03a9ad246..0c1ab727b 100644 --- a/tools/gnatcov/slocs.ads +++ b/tools/gnatcov/slocs.ads @@ -37,6 +37,8 @@ package Slocs is function "<" (L, R : Local_Source_Location) return Boolean; function "<=" (L, R : Local_Source_Location) return Boolean; + function Image (Sloc : Local_Source_Location) return String; + No_Local_Location : constant Local_Source_Location := (0, 0); type Local_Source_Location_Range is record From 941429230568fef24b267c1aeeec56653e906c3c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 7 Nov 2023 10:33:50 +0000 Subject: [PATCH 0486/1483] SC_Obligations: assert that scope entities are set only once per CU Instrumenters are not supposed to set scope entities once, and then override them later for the same CU: ensure this with an assertion. --- tools/gnatcov/sc_obligations.adb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 266f99ab6..bd31be826 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -4362,9 +4362,15 @@ package body SC_Obligations is ------------------------ procedure Set_Scope_Entities - (CU : CU_Id; Scope_Entities : Scope_Entities_Trees.Tree) is + (CU : CU_Id; Scope_Entities : Scope_Entities_Trees.Tree) + is + SE : Scope_Entities_Trees.Tree renames + CU_Vector.Reference (CU).Scope_Entities; begin - CU_Vector.Reference (CU).Scope_Entities := Scope_Entities; + -- Scopes are supposed to be set only once per compilation unit + + pragma Assert (SE.Is_Empty); + SE := Scope_Entities; end Set_Scope_Entities; ------------------------------- From b26c4b90617c07bbcf90c078de087aa41d96c0ee Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 7 Nov 2023 16:28:13 +0000 Subject: [PATCH 0487/1483] SC_Obligations.Scope_Traversal_Type: remove useless component --- tools/gnatcov/sc_obligations.ads | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 0361188a8..3977d7932 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -1359,9 +1359,6 @@ private -- Set the BDD node for the given condition SCO type Scope_Traversal_Type is record - Scope_Entities : Scope_Entities_Tree; - -- Currently traversed scope entities - Scope_Stack : Scope_Stacks.List; Active_Scopes : Scope_Id_Set; -- List of currently active scopes @@ -1383,8 +1380,7 @@ private -- next one according to ST's iterator. No_Scope_Traversal : Scope_Traversal_Type := - (Scope_Entities => Scope_Entities_Trees.Empty_Tree, - Scope_Stack => Scope_Stacks.Empty_List, + (Scope_Stack => Scope_Stacks.Empty_List, Active_Scopes => Scope_Id_Sets.Empty_Set, Active_Scope_Ent => Scope_Entities_Trees.No_Element, Next_Scope_Ent => Scope_Entities_Trees.No_Element, From fb6f7b6fa6e8707d45d9bc9af37445d783de0650 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 7 Nov 2023 15:31:06 +0000 Subject: [PATCH 0488/1483] Reject --subprograms arguments that designate no known subprogram --- testsuite/tests/subp_of_interest/test.py | 34 +++++++++++++++++------- tools/gnatcov/gnatcov_bits_specific.adb | 25 ++++++++++++----- tools/gnatcov/sc_obligations.adb | 5 ++++ tools/gnatcov/sc_obligations.ads | 5 ++++ tools/gnatcov/switches.ads | 2 +- 5 files changed, 53 insertions(+), 18 deletions(-) diff --git a/testsuite/tests/subp_of_interest/test.py b/testsuite/tests/subp_of_interest/test.py index d2e9e3813..3fdf6c923 100644 --- a/testsuite/tests/subp_of_interest/test.py +++ b/testsuite/tests/subp_of_interest/test.py @@ -35,6 +35,9 @@ def check_xcov(label, args, expected_output=""): tmp = Wdir("tmp_") +pkg_spec = os.path.join("..", "src", "pkg.ads") +pkg_body = os.path.join("..", "src", "pkg.adb") + thistest.log("== Checkpoint creation ==") cov_args = build_and_run( gprsw=GPRswitches( @@ -55,12 +58,9 @@ def check_xcov(label, args, expected_output=""): + [ "--save-checkpoint", "trace.ckpt", - "--subprograms", - f"{os.path.join('..', 'src', 'pkg.ads')}:4", - "--subprograms", - f"{os.path.join('..', 'src', 'pkg.adb')}:10", - "--subprograms", - f"{os.path.join('..', 'src', 'pkg.adb')}:12", + f"--subprograms={pkg_spec}:4", + f"--subprograms={pkg_body}:10", + f"--subprograms={pkg_body}:12", ], expected_output=( "" @@ -115,9 +115,7 @@ def check_xcov(label, args, expected_output=""): # Case 2: line number is not a number thistest.log("== Bad line number ==") xcov( - cov_args + [ - "--subprograms", f"{os.path.join('..', 'src', 'pkg.ads')}:b", - ], + cov_args + ["--subprograms", f"{pkg_spec}:b"], out="xcov-wrong2.txt", register_failure=False, ) @@ -138,7 +136,23 @@ def check_xcov(label, args, expected_output=""): what="unexpected coverage output", regexp=( r".*Error when parsing --subprograms argument dumb-file-name:4:" - r".*dumb-file-name does not exist" + r" unknown source file" + ), + actual=contents_of("xcov-wrong3.txt"), + ) + + # Case 4: scope does not exist + thistest.log("== No such scope ==") + xcov( + cov_args + [f"--subprograms={pkg_body}:14"], + out="xcov-wrong3.txt", + register_failure=False, + ) + thistest.fail_if_no_match( + what="unexpected coverage output", + regexp=( + f".*Error when parsing --subprograms argument {pkg_body}:14:" + " unknown subprogram" ), actual=contents_of("xcov-wrong3.txt"), ) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index ad1ccc478..e4d944d08 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -87,6 +87,7 @@ with Traces_Files; use Traces_Files; with Traces_Files_Registry; use Traces_Files_Registry; with Traces_Names; use Traces_Names; with Traces_Source; +with Types; use Types; with Version; procedure GNATcov_Bits_Specific is @@ -374,20 +375,30 @@ procedure GNATcov_Bits_Specific is Subp_Input (Subp_Input'First .. Column_Index - 1); Column : String renames Subp_Input (Column_Index + 1 .. Subp_Input'Last); + + Identifier : Scope_Entity_Identifier; begin if Column_Index = 0 then raise Constraint_Error; end if; - if not Exists (Filename) then + Identifier.Decl_SFI := + Get_Index_From_Full_Name + (Full_Name => Full_Name (Filename), + Kind => Source_File, + Insert => False); + if Identifier.Decl_SFI = No_Source_File then + Outputs.Fatal_Error + ("Error when parsing --subprograms argument " + & Subp_Input & ": unknown source file"); + end if; + Identifier.Decl_Line := Natural'Value (Column); + + if not Available_Subps_Of_Interest.Contains (Identifier) then Outputs.Fatal_Error ("Error when parsing --subprograms argument " - & Subp_Input & ": file " & Filename & " does not exist"); + & Subp_Input & ": unknown subprogram"); end if; - Subps_Of_Interest.Include - (Scope_Entity_Identifier' - (Decl_SFI => - Get_Index_From_Full_Name (Full_Name (Filename), Source_File), - Decl_Line => Natural'Value (Column))); + Subps_Of_Interest.Include (Identifier); exception -- Deal gracefully with parsing errors diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index bd31be826..562e5a594 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -1236,6 +1236,11 @@ package body SC_Obligations is Remap_SCO_Id (Scope_Ent.From); Remap_SCO_Id (Scope_Ent.To); Remap_SFI (Relocs, Scope_Ent.Identifier.Decl_SFI); + + -- Register each scope identifiers to make them available to users + -- on the command line. + + Available_Subps_Of_Interest.Include (Scope_Ent.Identifier); end loop; end if; diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 3977d7932..d86811a49 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -214,6 +214,11 @@ package SC_Obligations is (Element_Type => Scope_Entity_Identifier); subtype Scope_Id_Set is Scope_Id_Sets.Set; + Available_Subps_Of_Interest : SC_Obligations.Scope_Id_Set; + -- Set of subprograms of interest known so far. This is used to validate + -- that entries added to Switches.Subp_Of_Interest do exist, i.e. raise + -- errors when a requested subprogram of interest is unknown. + package Scope_Entities_Trees is new Ada.Containers.Multiway_Trees (Element_Type => Scope_Entity); subtype Scope_Entities_Tree is Scope_Entities_Trees.Tree; diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index e0ee59de6..b2429cb6d 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -134,7 +134,7 @@ package Switches is -- instead of hashes. Subps_Of_Interest : SC_Obligations.Scope_Id_Set; - -- List of subprograms of interest + -- List of subprograms of interest requested by users on the command line type Separated_Source_Coverage_Type is (None, Routines, Instances); Separated_Source_Coverage : Separated_Source_Coverage_Type := None; From 4e666173f7d7295e5c5b560994690f2ca3638159 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 15 Nov 2023 14:48:20 +0000 Subject: [PATCH 0489/1483] instrument-c.adb: avoid uninitialized record component Make sure that the record component PP_Info.PP_Source_Range is always initialized, at least so that we do not stream absurd sloc range information to SID/checkpoint files. That went unnoticed so far because Natural'Write will happily write a negative number, and Natural'Read will happily read and assign it, without raising a Constraint_Error. This fixes no known gnatcov issue as of today, but is necessary for the upcoming work to make SID/checkpoint reading manual. --- tools/gnatcov/instrument-c.adb | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index d8ceccc73..081b4d1c8 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -735,6 +735,7 @@ package body Instrument.C is -- a Local_Source_Location as it can refer to #included files. Info.Actual_Source_Range := (From.L, To.L); + Info.PP_Source_Range := No_Local_Range; -- Check if this is comes from a macro expansion, in which case we need -- to record some information, for reporting purposes. From 5d7c541d994c0e96989ab58f9ce55e85da516161 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 17 Nov 2023 09:31:29 +0000 Subject: [PATCH 0490/1483] files_table.adb: fix a GNAT warning --- tools/gnatcov/files_table.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 3e5b8b95a..a8c75aae4 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -2243,7 +2243,7 @@ package body Files_Table is Current_Line : Integer := 0; -- Line and file of the currently-active line marker - PP_Directive_Matched : Boolean; + PP_Directive_Matched : Boolean := False; -- Whether the last line was a preprocessing directive, other than -- a line directive. From 0a8c387dd93c0c63eeb119edc496e368544390de Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 17 Nov 2023 08:50:55 +0000 Subject: [PATCH 0491/1483] subp_of_interest: fix regexp escaping Escape filenames before including them in regexps: on Windows, these contain backslashes, which have special interpretations. In the general case, these filenames also contain dots, which mean "any character" whereas in this context we meant "a dot". --- testsuite/tests/subp_of_interest/test.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/subp_of_interest/test.py b/testsuite/tests/subp_of_interest/test.py index 3fdf6c923..646979ea2 100644 --- a/testsuite/tests/subp_of_interest/test.py +++ b/testsuite/tests/subp_of_interest/test.py @@ -6,6 +6,7 @@ import os import os.path +import re from SCOV.minicheck import build_and_run, check_xcov_reports from SUITE.context import thistest @@ -151,8 +152,8 @@ def check_xcov(label, args, expected_output=""): thistest.fail_if_no_match( what="unexpected coverage output", regexp=( - f".*Error when parsing --subprograms argument {pkg_body}:14:" - " unknown subprogram" + ".*Error when parsing --subprograms argument" + f" {re.escape(pkg_body)}:14: unknown subprogram" ), actual=contents_of("xcov-wrong3.txt"), ) From 3daaa1202154f1fe7849d225485cbb6804f6aced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 10 Nov 2023 10:08:32 +0100 Subject: [PATCH 0492/1483] subprocesses.adb: Do not set the exit status when ignoring subcommand failure Change the verbose reporting mechanism for Run_Command when ignoring subprocess failures to not set the exit status of gnatcov to Failure, as it otherwise defeats the point of ignoring the failures. --- tools/gnatcov/subprocesses.adb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 5ea2465a1..f38a4dfb0 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -106,7 +106,11 @@ package body Subprocesses is if Success then Put_Line (Command & " finished"); else - Error (Origin_Command_Name & " failed"); + -- Do not use Error as this sets the exit status to Failure, but + -- here we are precisely ignoring the fact that the subprocess + -- failed. + + Warning_Or_Error (Origin_Command_Name & " failed"); end if; end if; end Check_Status; From b4b1651d1932f3addb6c22b5d0e8084a7301e1c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 10 Nov 2023 10:22:32 +0100 Subject: [PATCH 0493/1483] Setup_RTS: Check for existence of shared Ada RTS Add a check for the existence of a shared Ada runtime library before atempting to build the shared version of the coverage runtime. --- testsuite/tests/152-shared_setup/main.adb | 6 ++ testsuite/tests/152-shared_setup/test.opt | 1 + testsuite/tests/152-shared_setup/test.py | 125 ++++++++++++++++++++++ tools/gnatcov/setup_rts.adb | 106 +++++++++++++++--- 4 files changed, 224 insertions(+), 14 deletions(-) create mode 100644 testsuite/tests/152-shared_setup/main.adb create mode 100644 testsuite/tests/152-shared_setup/test.opt create mode 100644 testsuite/tests/152-shared_setup/test.py diff --git a/testsuite/tests/152-shared_setup/main.adb b/testsuite/tests/152-shared_setup/main.adb new file mode 100644 index 000000000..57d139b4a --- /dev/null +++ b/testsuite/tests/152-shared_setup/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello world!"); +end Main; diff --git a/testsuite/tests/152-shared_setup/test.opt b/testsuite/tests/152-shared_setup/test.opt new file mode 100644 index 000000000..1842ee84d --- /dev/null +++ b/testsuite/tests/152-shared_setup/test.opt @@ -0,0 +1 @@ +!native DEAD Test requires both shared lib support and available light runtime diff --git a/testsuite/tests/152-shared_setup/test.py b/testsuite/tests/152-shared_setup/test.py new file mode 100644 index 000000000..c038e74d2 --- /dev/null +++ b/testsuite/tests/152-shared_setup/test.py @@ -0,0 +1,125 @@ +""" +Check that "gnatcov setup" does not try to build a shared version of the +coverage runtime when the Ada runtime is not available as a shared library. + +This is the case for all of our light runtimes: even though the platform might +support them, we generally don't build the shared version of the runtime. +""" + +import os + +from SCOV.instr import xcov_convert_base64, xcov_instrument +from SCOV.minicheck import check_xcov_reports +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import ( + exepath_to, + gprfor, + run_and_log, + run_cov_program, + xcov, +) +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +# Name of the installed runtime project, to avoid conflict with the one setup +# by the testing infrastructure. +rt_prj = "rt_prj" + +# Installation directory for the instrumentation runtime project and directory +# for the project path. +rt_install_dir = os.path.abspath("install") +rt_path_dir = os.path.join(rt_install_dir, "share", "gpr") + +prj = gprfor( + mains=["main.adb"], + objdir="obj", + srcdirs=[".."], + extra=' for Runtime ("Ada") use "light";', +) + +gprsw = GPRswitches(root_project=prj) + +light_log = "setup_light.log" + +# Setup the coverage runtime for a light Ada runtime. Disable the automatic +# passing of --config / --target / --rts as we are doing something custom. +xcov( + [ + "setup", + "--RTS=light", + f"--install-name={rt_prj}", + f"--prefix={rt_install_dir}", + "-v", + ], + out=light_log, + auto_target_args=False, + auto_config_args=False, +) + +thistest.fail_if( + "Library support: STATIC_ONLY" not in contents_of(light_log), + "Incorrect library support for light runtime", +) + +# Make this install available to GPR tools +env.add_search_path("GPR_PROJECT_PATH", rt_path_dir) + +# As we want to override the config generated for the testsuite, we have to +# manually re-do all the coverage workflow to ensure no "--config" argument is +# used in the process. + +xcov_instrument( + gprsw, + covlevel="stmt", + dump_channel="base64-stdout", + dump_trigger="main-end", + runtime_project=rt_prj, + auto_config_args=False, + auto_target_args=False, +) + +build_log = "gprbuild.log" + +p = run_and_log( + cmds=[ + "gprbuild", + f"-P{prj}", + f"--implicit-with={rt_prj}", + "--src-subdirs=gnatcov-instr", + ], + output=build_log, + env=env.environ, +) + +thistest.fail_if(p.status != 0, "GPRbuild exit in error") + +run_log = "run.log" + +# Ignore exit status as there's no way with a light runtime to set the exit +# status to 0. +run_cov_program( + exepath_to ("main"), + out=run_log, + register_failure=False, +) + +main_srctrace = "main.srctrace" + +xcov_convert_base64(run_log, main_srctrace) + +xcov( + [ + "coverage", + f"-P{prj}", + "-cstmt", + "-axcov", + main_srctrace, + ] +) + +check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {5}}}, cwd="obj") + +thistest.result() diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index ce005d66c..de89c7c35 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -32,6 +32,7 @@ with GPR2.Containers; with GPR2.Log; with GPR2.Path_Name; with GPR2.Project.Attribute; +with GPR2.Project.Attribute_Index; with GPR2.Project.Configuration; with GPR2.Project.Registry.Attribute; with GPR2.Project.Tree; @@ -169,6 +170,11 @@ package body Setup_RTS is -- project to install. Use a filename that will match the Install'Artifacts -- attribute in the runtime project file. + function Has_Shared_Lib + (RTS_Dir : String; Shared_Lib_Ext : String) return Boolean; + -- Return whether there is any file with extension Shared_Lib_Ext in the + -- directory RTS_Dir/adalib. + ------------------ -- Load_Project -- ------------------ @@ -491,23 +497,64 @@ package body Setup_RTS is end; end if; - -- Query the support for libraries in this configuration. When GPRconfig - -- fails to find the toolchain for the requested target/RTS, it only - -- emits warnings (no Invalid_Project exception raised in the call to - -- Load above). In this case, we reach this point and have an empty - -- string for the Library_Support attribute. + -- First, determine what kind of library is supported by the current + -- target / RTS configuration. If we have full library support, still + -- try to determine if we have access to a shared Ada runtime as it is + -- not always available. + -- + -- To do this, we search in the /adalib directory any file + -- with a extension. If we can't find anything + -- then assume only static libraries are supported. + -- + -- If GPRconfig fails to find a toolchain, it only emits warnings (no + -- Invalid_Project exception raise in the call to Load above), so when + -- reaching this point, assume empty strings for all the attributes, + -- (and thus no library support). declare - Attr_Id : constant GPR2.Q_Attribute_Id := - GPR2.Project.Registry.Attribute.Library_Support; - Attr : constant GPR2.Project.Attribute.Object := - Prj.Configuration.Corresponding_View.Attribute (Attr_Id); - LS : constant String := - (if Attr.Is_Defined - then String (Attr.Value.Text) - else ""); + function Config_Attribute + (Id : GPR2.Q_Attribute_Id; + Index : GPR2.Project.Attribute_Index.Object := + GPR2.Project.Attribute_Index.Undefined) return String; + -- Return the string value for the attribute denoted by Id, at Index. + -- If the attribute value is not defined, return the empty string. + + ---------------------- + -- Config_Attribute -- + ---------------------- + + function Config_Attribute + (Id : GPR2.Q_Attribute_Id; + Index : GPR2.Project.Attribute_Index.Object := + GPR2.Project.Attribute_Index.Undefined) return String + is + Attr : constant GPR2.Project.Attribute.Object := + Prj.Configuration.Corresponding_View.Attribute (Id, Index); + begin + return (if Attr.Is_Defined then String (Attr.Value.Text) else ""); + end Config_Attribute; + + Lib_Support_Str : constant String := + Config_Attribute (GPR2.Project.Registry.Attribute.Library_Support); + + RTS_Dir : constant String := + Config_Attribute + (GPR2.Project.Registry.Attribute.Runtime_Dir, + Index => + GPR2.Project.Attribute_Index.Create (GPR2.Ada_Language)); + + Shared_Lib_Ext : constant String := + Config_Attribute + (GPR2.Project.Registry.Attribute.Shared_Library_Suffix); begin - Lib_Support := Library_Support'Value (LS); + Lib_Support := Library_Support'Value (Lib_Support_Str); + + if Lib_Support = Full + and then not Has_Shared_Lib (RTS_Dir, Shared_Lib_Ext) + then + Lib_Support := Static_Only; + end if; + exception when Constraint_Error => Fatal_Error ("Cannot get library support for this configuration"); @@ -1114,4 +1161,35 @@ package body Setup_RTS is return Had_Warnings; end Check_RTS_Profile; + -------------------- + -- Has_Shared_Lib -- + -------------------- + + function Has_Shared_Lib + (RTS_Dir : String; Shared_Lib_Ext : String) return Boolean + is + Lib_Dir_Search : Search_Type; + begin + if not Exists (RTS_Dir) then + return False; + end if; + + Start_Search + (Lib_Dir_Search, + Directory => + RTS_Dir & GNAT.OS_Lib.Directory_Separator & "adalib", + Pattern => "*" & Shared_Lib_Ext, + Filter => + (Ordinary_File => True, others => False)); + + return Res : constant Boolean := More_Entries (Lib_Dir_Search) do + End_Search (Lib_Dir_Search); + end return; + + exception + when Ada.Directories.Name_Error => + End_Search (Lib_Dir_Search); + return False; + end Has_Shared_Lib; + end Setup_RTS; From 7be8d525399adaf2d373048cc135a549e1de6cd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 22 Nov 2023 14:13:35 +0100 Subject: [PATCH 0494/1483] Tests/152-shared_setup: kill test for older toolchains The 7.1.2 and 5.04a1 toolchains are not shipped with either a light nor a ZFP runtime so do not run the test when using them. --- testsuite/tests/152-shared_setup/test.opt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/tests/152-shared_setup/test.opt b/testsuite/tests/152-shared_setup/test.opt index 1842ee84d..86eb0c85f 100644 --- a/testsuite/tests/152-shared_setup/test.opt +++ b/testsuite/tests/152-shared_setup/test.opt @@ -1 +1,3 @@ !native DEAD Test requires both shared lib support and available light runtime +7.1.2 DEAD Light runtime not provided by this toolchain +5.04a1 DEAD Light runtime not provided by this toolchain From e80b41ad50ef53ce493bb0b6a0f1de47f6658984 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 24 Nov 2023 08:06:50 +0000 Subject: [PATCH 0495/1483] GNATcov_RTS: add missing pragma Pure/Ada 95 notices --- tools/gnatcov/rts/gcvrt.ads | 2 ++ tools/gnatcov/rts/gnatcov_rts-strings.ads | 2 ++ tools/gnatcov/rts/gnatcov_rts-traces-output.ads | 4 ++++ tools/gnatcov/rts/gnatcov_rts-traces.ads | 2 ++ 4 files changed, 10 insertions(+) diff --git a/tools/gnatcov/rts/gcvrt.ads b/tools/gnatcov/rts/gcvrt.ads index 38efdf1c7..047875429 100644 --- a/tools/gnatcov/rts/gcvrt.ads +++ b/tools/gnatcov/rts/gcvrt.ads @@ -17,6 +17,8 @@ ------------------------------------------------------------------------------ -- Namespace for units generated for instrumentation purposes +-- +-- This unit needs to be compilable with Ada 95 compilers package GCVRT is pragma Pure; diff --git a/tools/gnatcov/rts/gnatcov_rts-strings.ads b/tools/gnatcov/rts/gnatcov_rts-strings.ads index 15720bddb..aed404d02 100644 --- a/tools/gnatcov/rts/gnatcov_rts-strings.ads +++ b/tools/gnatcov/rts/gnatcov_rts-strings.ads @@ -23,6 +23,8 @@ ------------------------------------------------------------------------------ -- Ada bindings for gnatcov_rts_c-strings.h +-- +-- This unit needs to be compilable with Ada 95 compilers with Interfaces.C; use Interfaces.C; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output.ads index 379457bf2..832176101 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output.ads @@ -23,7 +23,11 @@ ------------------------------------------------------------------------------ -- Namespace for all support packages required to dump traces +-- +-- This unit needs to be compilable with Ada 95 compilers package GNATcov_RTS.Traces.Output is + pragma Pure; + end GNATcov_RTS.Traces.Output; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces.ads b/tools/gnatcov/rts/gnatcov_rts-traces.ads index 94c2b3a0e..a0181e476 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces.ads @@ -22,6 +22,8 @@ -- -- ------------------------------------------------------------------------------ +-- This unit needs to be compilable with Ada 95 compilers + package GNATcov_RTS.Traces is pragma Pure; From 2525333de686a5717bb9ed39c5b245571503812f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 24 Nov 2023 08:53:35 +0000 Subject: [PATCH 0496/1483] GNATcov_RTS: remove dependencies on Interfaces/Interfaces.C --- tools/gnatcov/rts/gnatcov_rts-buffers.ads | 11 ++--- tools/gnatcov/rts/gnatcov_rts-strings.ads | 2 +- .../rts/gnatcov_rts-traces-output-base64.ads | 3 +- tools/gnatcov/rts/gnatcov_rts-types.ads | 47 +++++++++++++++++++ 4 files changed, 54 insertions(+), 9 deletions(-) create mode 100644 tools/gnatcov/rts/gnatcov_rts-types.ads diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index 158e8cdec..f0483cb46 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -28,12 +28,9 @@ -- -- This unit needs to be compilable with Ada 95 compilers. -with Interfaces; -with Interfaces.C; use Interfaces.C; - with System; -with System.Storage_Elements; +with GNATcov_RTS.Types; use GNATcov_RTS.Types; with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; package GNATcov_RTS.Buffers is @@ -68,8 +65,10 @@ package GNATcov_RTS.Buffers is type Any_Language_Kind is (Unit_Based_Language, File_Based_Language); pragma Convention (C, Any_Language_Kind); - type Fingerprint_Type is - new System.Storage_Elements.Storage_Array (1 .. 20); + type Fingerprint_Type is array (1 .. 20) of Unsigned_8; + for Fingerprint_Type'Component_Size use 8; + for Fingerprint_Type'Size use 20 * 8; + -- Hash type to perform consistency checks over Source Coverage -- Obligations. 20-byte to hold a SHA-1. diff --git a/tools/gnatcov/rts/gnatcov_rts-strings.ads b/tools/gnatcov/rts/gnatcov_rts-strings.ads index aed404d02..e0f9f85e4 100644 --- a/tools/gnatcov/rts/gnatcov_rts-strings.ads +++ b/tools/gnatcov/rts/gnatcov_rts-strings.ads @@ -26,7 +26,7 @@ -- -- This unit needs to be compilable with Ada 95 compilers -with Interfaces.C; use Interfaces.C; +with GNATcov_RTS.Types; use GNATcov_RTS.Types; package GNATcov_RTS.Strings is diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads index 39690b204..4f60936b7 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads @@ -24,9 +24,8 @@ -- This unit needs to be compilable with Ada 95 compilers -with Interfaces; use Interfaces; - with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; +with GNATcov_RTS.Types; use GNATcov_RTS.Types; package GNATcov_RTS.Traces.Output.Base64 is diff --git a/tools/gnatcov/rts/gnatcov_rts-types.ads b/tools/gnatcov/rts/gnatcov_rts-types.ads new file mode 100644 index 000000000..9ce1379ae --- /dev/null +++ b/tools/gnatcov/rts/gnatcov_rts-types.ads @@ -0,0 +1,47 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2021-2023, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- Basic types to use in source trace buffers. We try to avoid using types +-- from Interfaces and Interfaces.C, and in general to minimize the set of +-- dependencies of GNATcov_RTS on the Ada runtime, so that we can compute code +-- coverage for these runtime units. +-- +-- This unit needs to be compilable with Ada 95 compilers + +with System; + +package GNATcov_RTS.Types is + + pragma Pure; + + type Unsigned_8 is mod 2 ** 8; + type Unsigned_64 is mod 2 ** 64; + + -- We assume here that Integer (Ada) is a correct mapping for int (C) + + type int is new Integer; + type unsigned is mod 2 ** int'Size; + type size_t is mod System.Memory_Size; + +end GNATcov_RTS.Types; From b458dab7b55da6072c795a5cadc5fd07fe4f6466 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 8 Nov 2023 12:46:27 +0000 Subject: [PATCH 0497/1483] SC_Obligations: assert SCOs nesting/ordering invariants for scopes The scope entities traversal code assumes that SCOs ranges in scope entities (Scope_Entity.From/.To) are correctly nested/ordered in scope entities trees. Add code to check that this invariant is respected each time we create/modify these trees. These invariants are supposed to hold no matter how gnatcov is used and checking them is not trivial, so check them only when assertions are enabled. --- tools/gnatcov/sc_obligations.adb | 120 +++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 562e5a594..22780cda9 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -19,6 +19,7 @@ -- Source Coverage Obligations with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Exceptions; with Ada.Strings.Fixed; use Ada.Strings.Fixed; with Ada.Streams; use Ada.Streams; with Ada.Text_IO; use Ada.Text_IO; @@ -50,6 +51,17 @@ package body SC_Obligations is No_Location : Source_Location renames Slocs.No_Location; -- (not SCOs.Source_Location) + function SCOs_Nested_And_Ordered + (Tree : Scope_Entities_Trees.Tree) return Boolean; + -- Return whether nodes in Tree are: + -- + -- * properly nested: SCO ranges (Element.From .. Element.To) are disjoint + -- for two sibling elements, and all nodes' SCO ranges are included in + -- its parents'; + -- + -- * properly ordered: if E1 and E2 are consecutive siblings, E1.To must be + -- smaller than E2.From. + --------------- -- Instances -- --------------- @@ -1242,6 +1254,7 @@ package body SC_Obligations is Available_Subps_Of_Interest.Include (Scope_Ent.Identifier); end loop; + pragma Assert (SCOs_Nested_And_Ordered (CP_CU.Scope_Entities)); end if; @@ -4362,6 +4375,106 @@ package body SC_Obligations is return Scope_Entities_Trees.Empty_Tree; end Get_Scope_Entities; + ----------------------------- + -- SCOs_Nested_And_Ordered -- + ----------------------------- + + function SCOs_Nested_And_Ordered + (Tree : Scope_Entities_Trees.Tree) return Boolean + is + use Scope_Entities_Trees; + + Failure : exception; + -- Exception raised when the nesting/ordering invariant is found to be + -- broken. + + Lower_Bound : SCO_Id := No_SCO_Id; + -- At every step of the check, this designates the minimum possible SCO + -- value for the .From component for the next element to inspect. + + procedure Check_Element (Cur : Cursor); + -- Check that Cur's From/To SCOs range is not empty and + -- Parent_From .. Parent_To range and that they are correctly ordered. + + ------------------- + -- Check_Element -- + ------------------- + + procedure Check_Element (Cur : Cursor) is + SE : Scope_Entity renames Tree.Constant_Reference (Cur); + Child : Cursor := First_Child (Cur); + + Last : SCO_Id; + -- SCO range upper bound for Cur's last child, or SE.From if there is + -- no child. + begin + -- Check that SCO ranges are never empty + + if SE.From > SE.To then + raise Failure with "empty SCO range for " & Image (SE); + end if; + + -- Check that the SCO range lower bound is both: + -- + -- * greater or equal to the parent's lower bound (this is the first + -- half of the nesting check; + -- + -- * greater than the previous sibling (if any: this checks the + -- ordering). + + if SE.From < Lower_Bound then + raise Failure with "SCO lower bound too low for " & Image (SE); + end if; + Lower_Bound := SE.From; + Last := SE.From; + + while Has_Element (Child) loop + Check_Element (Child); + Child := Next_Sibling (Child); + Last := Lower_Bound; + + -- The next sibling's SCO range cannot overlap with the current's + + Lower_Bound := Lower_Bound + 1; + end loop; + + -- Check that the SCO range upper bound is greater or equal to + -- the upper bound of the last child's upper bound (this is the + -- second half of the nesting check). + + if SE.To < Last then + raise Failure with "SCO higher bound too low for " & Image (SE); + end if; + Lower_Bound := SE.To; + end Check_Element; + + Cur : Cursor := First_Child (Tree.Root); + + -- Start of processing for SCOs_Nested_And_Ordered + + begin + while Has_Element (Cur) loop + Check_Element (Cur); + Cur := Next_Sibling (Cur); + end loop; + return True; + + exception + when Exc : Failure => + + -- In case of failure, be helpful and print the offending tree for + -- the verbose mode. + + if Verbose then + Put_Line + ("The following tree of scopes breaks the nesting/ordering" + & " invariant:"); + Put_Line (Ada.Exceptions.Exception_Message (Exc)); + Dump (Tree, "| "); + end if; + return False; + end SCOs_Nested_And_Ordered; + ------------------------ -- Set_Scope_Entities -- ------------------------ @@ -4375,7 +4488,14 @@ package body SC_Obligations is -- Scopes are supposed to be set only once per compilation unit pragma Assert (SE.Is_Empty); + + pragma Assert (SCOs_Nested_And_Ordered (Scope_Entities)); SE := Scope_Entities; + + if Verbose then + Put_Line ("Setting scopes for " & Image (CU) & ":"); + Dump (SE, Line_Prefix => "| "); + end if; end Set_Scope_Entities; ------------------------------- From d1ffb4fe8a9b05747c4838db24afcb36f1f7dca4 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 8 Nov 2023 14:14:53 +0000 Subject: [PATCH 0498/1483] SC_Obligations: ensure that Traverse_SCO is called with increasing SCOs --- tools/gnatcov/sc_obligations.adb | 12 ++++++++++++ tools/gnatcov/sc_obligations.ads | 19 ++++++++++++++++--- 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 22780cda9..b39f2c35e 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -664,6 +664,7 @@ package body SC_Obligations is Result.Scope_Stack := Scope_Stacks.Empty_List; Result.Active_Scopes := Scope_Id_Sets.Empty; Set_Active_Scope_Ent (Result, Result.It.First); + Result.Last_SCO := No_SCO_Id; return Result; end Scope_Traversal; @@ -674,6 +675,8 @@ package body SC_Obligations is procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) is use Scope_Entities_Trees; begin + ST.Last_SCO := SCO; + -- In some cases (C metaprogramming instances), e.g. -- -- foo.h: @@ -733,6 +736,15 @@ package body SC_Obligations is end loop; end Traverse_SCO; + -------------- + -- Last_SCO -- + -------------- + + function Last_SCO (ST : Scope_Traversal_Type) return SCO_Id is + begin + return ST.Last_SCO; + end Last_SCO; + -------------------------- -- Set_Active_Scope_Ent -- -------------------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index d86811a49..477f09a63 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -246,13 +246,20 @@ package SC_Obligations is -- Is_Active to know whether a given scope is active in the given -- traversal. - function Scope_Traversal (CU : CU_Id) return Scope_Traversal_Type; + function Scope_Traversal (CU : CU_Id) return Scope_Traversal_Type + with Post => Last_SCO (Scope_Traversal'Result) = No_SCO_Id; -- Return a scope traversal for the given compilation unit - procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id); + procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) + with Pre => Last_SCO (ST) <= SCO, + Post => Last_SCO (ST) = SCO; -- Traverse the given SCO and update the Scope_Traversal accordingly. Note -- that the scope traversal must be done on increasing SCOs identifiers. + function Last_SCO (ST : Scope_Traversal_Type) return SCO_Id; + -- Return the last SCO that was passed to Traverse_SCO, or No_SCO_Id if + -- Traverse_SCO has not been called yet on ST. + function Is_Active (ST : Scope_Traversal_Type; Subps_Of_Interest : Scope_Id_Set) return Boolean; @@ -1376,6 +1383,11 @@ private It : Iterator_Acc; -- Iterator to traverse the scope tree + + Last_SCO : SCO_Id; + -- Keep track of the last SCO requested with Traverse_SCO. We use this + -- to check that SCOs are requested in the right order (lower Ids to + -- higher ones). end record; procedure Set_Active_Scope_Ent @@ -1389,6 +1401,7 @@ private Active_Scopes => Scope_Id_Sets.Empty_Set, Active_Scope_Ent => Scope_Entities_Trees.No_Element, Next_Scope_Ent => Scope_Entities_Trees.No_Element, - It => null); + It => null, + Last_SCO => No_SCO_Id); end SC_Obligations; From d4144a18153ef166050b190426e7981aca409a98 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 8 Nov 2023 15:45:54 +0000 Subject: [PATCH 0499/1483] SC_Obligations: rework the scopes querying API Exactly one set of subprograms of interest is ever used: the set for --subprograms command line arguments. Remove Is_Active's corresponding argument and always use the set at Switches.Subps_Of_Interest instead. This also opens the way to more efficient ways to check whether the current SCO is covered by a scope that matches --subprograms. Also rename Is_Active to avoid the confusion with the Active_Scopes/Active_Scope_Ent components (which can contain scopes that are *not* active according to --subprograms arguments). --- tools/gnatcov/annotations.adb | 2 +- tools/gnatcov/coverage-source.adb | 2 +- tools/gnatcov/sc_obligations.adb | 12 +++++------- tools/gnatcov/sc_obligations.ads | 11 +++++------ 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 6095407fb..bc30f5c6b 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -426,7 +426,7 @@ package body Annotations is for SCO of LI.SCOs.all loop Traverse_SCO (ST, SCO); end loop; - if not Is_Active (ST, Subps_Of_Interest) then + if not In_Scope_Of_Interest (ST) then return; end if; end if; diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 451aa69a7..3abf69745 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -2003,7 +2003,7 @@ package body Coverage.Source is is begin Traverse_SCO (ST, SCO); - if Is_Active (ST, Subps_Of_Interest) then + if In_Scope_Of_Interest (ST) then Update_SCI (SCO, Tag, Process); end if; end Update_SCI_Wrapper; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index b39f2c35e..c778591f6 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -757,18 +757,16 @@ package body SC_Obligations is ST.Next_Scope_Ent := ST.It.Next (Scope_Ent); end Set_Active_Scope_Ent; - --------------- - -- Is_Active -- - --------------- + -------------------------- + -- In_Scope_Of_Interest -- + -------------------------- - function Is_Active - (ST : Scope_Traversal_Type; - Subps_Of_Interest : Scope_Id_Set) return Boolean is + function In_Scope_Of_Interest (ST : Scope_Traversal_Type) return Boolean is begin return Subps_Of_Interest.Is_Empty or else not Scope_Id_Sets.Is_Empty (ST.Active_Scopes.Intersection (Subps_Of_Interest)); - end Is_Active; + end In_Scope_Of_Interest; ----------------- -- Add_Address -- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 477f09a63..c59d25f6d 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -260,12 +260,11 @@ package SC_Obligations is -- Return the last SCO that was passed to Traverse_SCO, or No_SCO_Id if -- Traverse_SCO has not been called yet on ST. - function Is_Active - (ST : Scope_Traversal_Type; - Subps_Of_Interest : Scope_Id_Set) return Boolean; - -- Return whether any of the scopes in Subps_Of_Interest is currently - -- active. Return True if Subps_Of_Interest is empty (i.e. consider all - -- subprograms of interest in that case). + function In_Scope_Of_Interest (ST : Scope_Traversal_Type) return Boolean; + -- Return whether at least one scope in Switches.Subps_Of_Interest contains + -- Last_SCO (ST). Note that this also returns True if + -- Switches.Subps_Of_Interest is empty (i.e. consider that all subprograms + -- are of interest in that case). No_Scope_Entity : constant Scope_Entity := (From => No_SCO_Id, From 792d43bbc28441be3f0033c0bcb64d8696ce255f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 9 Nov 2023 11:52:06 +0000 Subject: [PATCH 0500/1483] SC_Obligations: simplify Scope_Traversal_Type/Traverse_SCO Remove the traversal stack and set of scope identifiers for that stack and simplify Traverse_SCO accordingly. This simplified traversal algoritm makes it work on hypothetical cases when some SCOs are not covered by any scope (this never happens right now, but candidate-then-discarded work used to introduce such cases). --- tools/gnatcov/sc_obligations.adb | 125 +++++++++++++------------------ tools/gnatcov/sc_obligations.ads | 32 +++----- 2 files changed, 60 insertions(+), 97 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index c778591f6..ffd1e08a9 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -62,6 +62,15 @@ package body SC_Obligations is -- * properly ordered: if E1 and E2 are consecutive siblings, E1.To must be -- smaller than E2.From. + function Covers_SCO (SE : Scope_Entity; SCO : SCO_Id) return Boolean + is (SCO in SE.From .. SE.To); + -- Return whether SCO is covered by SE's SCO range + + function Covers_SCO + (Cur : Scope_Entities_Trees.Cursor; SCO : SCO_Id) return Boolean + is (Covers_SCO (Scope_Entities_Trees.Element (Cur), SCO)); + -- Return whether SCO is covered by that element's SCO range + --------------- -- Instances -- --------------- @@ -658,13 +667,10 @@ package body SC_Obligations is return No_Scope_Traversal; end if; Result.It := - new Tree_Iterator' - (Scope_Entities_Trees.Iterate - (CU_Vector.Reference (CU).Element.Scope_Entities)); - Result.Scope_Stack := Scope_Stacks.Empty_List; - Result.Active_Scopes := Scope_Id_Sets.Empty; - Set_Active_Scope_Ent (Result, Result.It.First); + new Tree_Iterator'(CU_Vector.Reference (CU).Scope_Entities.Iterate); Result.Last_SCO := No_SCO_Id; + Result.Current_SE := Scope_Entities_Trees.No_Element; + Result.Next_SE := Result.It.First; return Result; end Scope_Traversal; @@ -674,66 +680,30 @@ package body SC_Obligations is procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) is use Scope_Entities_Trees; + Progressed : Boolean := False; begin ST.Last_SCO := SCO; - -- In some cases (C metaprogramming instances), e.g. - -- - -- foo.h: - -- TYPE ret = 0; - -- return (TYPE) ret + 1; - -- - -- foo.c: - -- int - -- one_int (void) - -- { - -- #define TYPE int - -- #include "foo.h" - -- #undef TYPE - -- } - -- - -- Active_Scope_Ent is null in the aforementionned case, as the inner - -- scope for the statements in foo.h is the `one_int` function defined - -- in foo.c. The scope implementation assumes that scopes do not cross - -- sources, which does not hold here. - -- - -- TODO???: This should be fixed by dealing with metaprogramming - -- instances in a more appropriate way, which should be done under - -- eng/cov/gnatcoverage#103. For now, return early in that case. - - if ST.Active_Scope_Ent = No_Element then - return; - end if; - - -- Find the innermost scope featuring this SCO and update the list of - -- active scopes as we go. + -- Move Next_SE forward in the iterator until we go past the deepest + -- scope that covers SCO. Update Current_SE along the way. - while SCO > Element (ST.Active_Scope_Ent).To - or else (ST.Next_Scope_Ent /= No_Element - and then SCO >= Element (ST.Next_Scope_Ent).From) - loop - -- We can enter the next scope only when we have reached its parent - -- scope. If the next scope is null, this means that we are in the - -- last scope of the unit. + while Has_Element (ST.Next_SE) and then Covers_SCO (ST.Next_SE, SCO) loop + ST.Current_SE := ST.Next_SE; + ST.Next_SE := ST.It.Next (ST.Next_SE); + Progressed := True; + end loop; - if ST.Next_Scope_Ent /= No_Element - and then ST.Active_Scope_Ent = Parent (ST.Next_Scope_Ent) - and then SCO >= Element (ST.Next_Scope_Ent).From - then - Set_Active_Scope_Ent (ST, ST.Next_Scope_Ent); - ST.Scope_Stack.Append (ST.Active_Scope_Ent); - ST.Active_Scopes.Insert - (Element (ST.Active_Scope_Ent).Identifier); - else - -- Otherwise, go up the parent chain and pop the last entry from - -- the active scopes. + -- If we have not found a more specific scope for SCO, we still may need + -- to update Current_SE in case the requested SCO is not covered anymore + -- by Current_SE. - ST.Active_Scope_Ent := Parent (ST.Active_Scope_Ent); - ST.Active_Scopes.Delete - (Element (ST.Scope_Stack.Last_Element).Identifier); - ST.Scope_Stack.Delete_Last; - end if; - end loop; + if not Progressed then + while Has_Element (ST.Current_SE) + and then not Covers_SCO (ST.Current_SE, SCO) + loop + ST.Current_SE := Parent (ST.Current_SE); + end loop; + end if; end Traverse_SCO; -------------- @@ -745,27 +715,32 @@ package body SC_Obligations is return ST.Last_SCO; end Last_SCO; - -------------------------- - -- Set_Active_Scope_Ent -- - -------------------------- - - procedure Set_Active_Scope_Ent - (ST : in out Scope_Traversal_Type; - Scope_Ent : Scope_Entities_Trees.Cursor) is - begin - ST.Active_Scope_Ent := Scope_Ent; - ST.Next_Scope_Ent := ST.It.Next (Scope_Ent); - end Set_Active_Scope_Ent; - -------------------------- -- In_Scope_Of_Interest -- -------------------------- function In_Scope_Of_Interest (ST : Scope_Traversal_Type) return Boolean is + use Scope_Entities_Trees; + Cur : Cursor; begin - return Subps_Of_Interest.Is_Empty - or else not Scope_Id_Sets.Is_Empty - (ST.Active_Scopes.Intersection (Subps_Of_Interest)); + -- If no subprogram of interest was requested, consider that they are + -- all of interest. + + if Subps_Of_Interest.Is_Empty then + return True; + end if; + + -- Otherwise, find at least one scope that covers SCO and that is a + -- subprogram of interest. + + Cur := ST.Current_SE; + while Has_Element (Cur) loop + if Subps_Of_Interest.Contains (Element (Cur).Identifier) then + return True; + end if; + Cur := Parent (Cur); + end loop; + return False; end In_Scope_Of_Interest; ----------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index c59d25f6d..a7bca6ea5 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -1370,16 +1370,6 @@ private -- Set the BDD node for the given condition SCO type Scope_Traversal_Type is record - Scope_Stack : Scope_Stacks.List; - Active_Scopes : Scope_Id_Set; - -- List of currently active scopes - - Active_Scope_Ent : Scope_Entities_Trees.Cursor; - -- Innermost currently active scope - - Next_Scope_Ent : Scope_Entities_Trees.Cursor; - -- Next active scope - It : Iterator_Acc; -- Iterator to traverse the scope tree @@ -1387,20 +1377,18 @@ private -- Keep track of the last SCO requested with Traverse_SCO. We use this -- to check that SCOs are requested in the right order (lower Ids to -- higher ones). - end record; - procedure Set_Active_Scope_Ent - (ST : in out Scope_Traversal_Type; - Scope_Ent : Scope_Entities_Trees.Cursor); - -- Set ST.Active_Scope_Ent to Scope_Ent and set ST.Next_Scope_Ent to the - -- next one according to ST's iterator. + Current_SE : Scope_Entities_Trees.Cursor; + -- Scope that is the deepest in the scope tree and that covers Last_SCO + + Next_SE : Scope_Entities_Trees.Cursor; + -- Next scope that Traverse_SCO needs to consider + end record; No_Scope_Traversal : Scope_Traversal_Type := - (Scope_Stack => Scope_Stacks.Empty_List, - Active_Scopes => Scope_Id_Sets.Empty_Set, - Active_Scope_Ent => Scope_Entities_Trees.No_Element, - Next_Scope_Ent => Scope_Entities_Trees.No_Element, - It => null, - Last_SCO => No_SCO_Id); + (It => null, + Last_SCO => No_SCO_Id, + Current_SE => Scope_Entities_Trees.No_Element, + Next_SE => Scope_Entities_Trees.No_Element); end SC_Obligations; From 07b55fcf74616ad9c682bbcfa9b93a6028e3e017 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 9 Nov 2023 13:17:33 +0000 Subject: [PATCH 0501/1483] SC_Obligations: fix loading of scopes for ignored source files This fixes an assertion failure: when remapping source files from the scopes loaded from a SID/checkpoint, scopes whose identifier references ignored source files will lose their identifier. Such scopes will remain, but users will not be able to mark them of interest. --- testsuite/tests/subp_of_interest/src/pkg.adb | 21 +++++++++- testsuite/tests/subp_of_interest/src/pkg.ads | 2 + testsuite/tests/subp_of_interest/test.py | 40 +++++++++++++++----- tools/gnatcov/sc_obligations.adb | 12 +++++- tools/gnatcov/sc_obligations.ads | 5 ++- 5 files changed, 66 insertions(+), 14 deletions(-) diff --git a/testsuite/tests/subp_of_interest/src/pkg.adb b/testsuite/tests/subp_of_interest/src/pkg.adb index 6607b0f9f..bbe2ebc38 100644 --- a/testsuite/tests/subp_of_interest/src/pkg.adb +++ b/testsuite/tests/subp_of_interest/src/pkg.adb @@ -1,15 +1,34 @@ with Ada.Text_IO; use Ada.Text_IO; package body Pkg is + + --------- + -- Foo -- + --------- + procedure Foo (I : Integer) is begin Put_Line ("Hello from Foo!"); end Foo; + --------- + -- Bar -- + --------- + procedure Bar is procedure Nested_Bar_1 is null; + procedure Nested_Bar_2; + Dummy_Decl : Boolean; - procedure Nested_Bar_2 is null; + + ------------------ + -- Nested_Bar_2 -- + ------------------ + + procedure Nested_Bar_2 is + begin + Put_Line ("Hello from Nested_Bar_2!"); + end Nested_Bar_2; begin Nested_Bar_1; Nested_Bar_2; diff --git a/testsuite/tests/subp_of_interest/src/pkg.ads b/testsuite/tests/subp_of_interest/src/pkg.ads index fd7058eb9..0845bfade 100644 --- a/testsuite/tests/subp_of_interest/src/pkg.ads +++ b/testsuite/tests/subp_of_interest/src/pkg.ads @@ -3,4 +3,6 @@ pragma Ada_2012; package Pkg is procedure Foo (I : Integer) with Pre => I > 0; procedure Bar; + + I : Integer; end Pkg; diff --git a/testsuite/tests/subp_of_interest/test.py b/testsuite/tests/subp_of_interest/test.py index 646979ea2..f385d7864 100644 --- a/testsuite/tests/subp_of_interest/test.py +++ b/testsuite/tests/subp_of_interest/test.py @@ -53,15 +53,16 @@ def check_xcov(label, args, expected_output=""): # that the coverage report contains only coverage data for the specified # subprograms for source traces. For binary traces, simply check that the # gnatcov coverage invocation yields the expected warning. +ckpt_filename = "trace.ckpt" check_xcov( "xcov_subp", cov_args + [ "--save-checkpoint", - "trace.ckpt", + ckpt_filename, f"--subprograms={pkg_spec}:4", - f"--subprograms={pkg_body}:10", - f"--subprograms={pkg_body}:12", + f"--subprograms={pkg_body}:19", + f"--subprograms={pkg_body}:20", ], expected_output=( "" @@ -70,12 +71,14 @@ def check_xcov(label, args, expected_output=""): " with binary traces." ), ) +cov_ckpt_args = cov_args[:-1] + ["--checkpoint", ckpt_filename] if src_traces: check_xcov_reports( "*.xcov", { "main.adb.xcov": {}, - "pkg.adb.xcov": {"+": {6, 10, 12}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {11, 19, 30}}, }, "xcov_subp", ) @@ -84,20 +87,37 @@ def check_xcov(label, args, expected_output=""): # specific subprogram. To do this, produce a new coverage report from the # checkpoint without using the --subprograms switch. thistest.log("== xcov_no_subp ==") - check_xcov( - "xcov_no_subp", - cov_args[:-1] - + ["--checkpoint", "trace.ckpt"], - ) + check_xcov("xcov_no_subp", cov_ckpt_args) check_xcov_reports( "*.xcov", { "main.adb.xcov": {"-": {5, 6}}, - "pkg.adb.xcov": {"+": {6, 10, 12}, "-": {11, 14, 15, 16}}, + "pkg.ads.xcov": {"-": {7}}, + "pkg.adb.xcov": {"+": {11, 19, 30}, "-": {22, 33, 34, 35}}, }, "xcov_no_subp", ) + # Check that we can still select subprograms of interest declared in the + # package body, when the package specification is ignored through + # --ignored-source-files. + thistest.log("== xcov_ignore ==") + check_xcov( + "xcov_ignore", + cov_args + [ + f"--subprograms={pkg_body}:20", + "--ignore-source-files=pkg.ads", + ], + ) + check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": {}, + "pkg.adb.xcov": {"+": {30}}, + }, + "xcov_ignore", + ) + # Also check the warnings when the subprogram switch is ill-formed # Case 1: missing colon in the argument diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index ffd1e08a9..561975187 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -1232,7 +1232,16 @@ package body SC_Obligations is for Scope_Ent of CP_CU.Scope_Entities loop Remap_SCO_Id (Scope_Ent.From); Remap_SCO_Id (Scope_Ent.To); - Remap_SFI (Relocs, Scope_Ent.Identifier.Decl_SFI); + + -- Scopes whose identifier references ignored source files will + -- lose their identifier: such scopes will remain, but users will + -- not be able to mark them of interest. + + if SFI_Ignored (Relocs, Scope_Ent.Identifier.Decl_SFI) then + Scope_Ent.Identifier := No_Scope_Entity_Identifier; + else + Remap_SFI (Relocs, Scope_Ent.Identifier.Decl_SFI); + end if; -- Register each scope identifiers to make them available to users -- on the command line. @@ -1240,7 +1249,6 @@ package body SC_Obligations is Available_Subps_Of_Interest.Include (Scope_Ent.Identifier); end loop; pragma Assert (SCOs_Nested_And_Ordered (CP_CU.Scope_Entities)); - end if; -- Preallocate line table entries for last file diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index a7bca6ea5..eaa5d187f 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -177,6 +177,9 @@ package SC_Obligations is -- and line for the original declaration (which is the body declaration for -- C/C++ and the specification declaration for Ada). + No_Scope_Entity_Identifier : constant Scope_Entity_Identifier := + (Decl_SFI => No_Source_File, Decl_Line => 0); + function "<" (L, R : Scope_Entity_Identifier) return Boolean is (if L.Decl_SFI = R.Decl_SFI then L.Decl_Line < R.Decl_Line @@ -271,7 +274,7 @@ package SC_Obligations is To => No_SCO_Id, Name => +"", Sloc => No_Local_Location, - Identifier => (Decl_SFI => 0, Decl_Line => 0)); + Identifier => No_Scope_Entity_Identifier); type Any_SCO_Kind is (Removed, Statement, Decision, Condition, Operator); subtype SCO_Kind is Any_SCO_Kind range Statement .. Operator; From 254f439726eefc4bdebc591061906807b9a0edee Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 24 Nov 2023 15:47:46 +0000 Subject: [PATCH 0502/1483] sc_obligations.adb: fix scope entities dump code for ignored src. files Fix a crash when dumping scope entities that have identifiers whose source file is cleared because of the --ignore-source-files option. --- tools/gnatcov/sc_obligations.adb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 561975187..83a183173 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -623,14 +623,17 @@ package body SC_Obligations is ----------- function Image (SE : Scope_Entity) return String is + Identifier_Image : constant String := + (if SE.Identifier.Decl_SFI = No_Source_File + then "ignored" + else "at " & Get_Simple_Name (SE.Identifier.Decl_SFI) + & ":" & Img (SE.Identifier.Decl_Line)); begin return "Scope for " & Ada.Strings.Unbounded.To_String (SE.Name) & "[" & Slocs.Image (SE.Sloc) - & "], identifier at " - & Get_Simple_Name (SE.Identifier.Decl_SFI) - & ":" & Img (SE.Identifier.Decl_Line); + & "], identifier " & Identifier_Image; end Image; ---------- From 0cca65b8680d1218a725039bd80df041fa0e2c87 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 27 Nov 2023 09:01:50 +0000 Subject: [PATCH 0503/1483] Ada2022/aggregates/containers: workaround the compiler hang When compiling the instrumented code for this testcase, GNAT is currently stuck in an infinite loop. This is highly inconvenient for the GNATcov team, as this means that this testcase always hits the timeout, making affected testuite runs take ~13 minutes more than needed. Temporarily make the testcase fail instantly while the GNAT bug is being investigated. --- testsuite/tests/Ada2022/aggregates/containers/test.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/testsuite/tests/Ada2022/aggregates/containers/test.py b/testsuite/tests/Ada2022/aggregates/containers/test.py index e755dd8c5..087505dcc 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/test.py +++ b/testsuite/tests/Ada2022/aggregates/containers/test.py @@ -8,5 +8,9 @@ from SUITE.context import thistest +# GNAT hangs on instrumented code (eng/toolchain/gnat#502): to avoid +# systematically hitting timeouts (wasting precious minutes in a testsuite +# run), abort the testcase early until this is fixed. +thistest.stop(RuntimeError) TestCase(category=CAT.decision).run() thistest.result() From 44dce831ff6fd7034cfb875f03ff078f6c66fa25 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 14 Nov 2023 16:00:24 +0000 Subject: [PATCH 0504/1483] Checkpoints: rework Version_Less and Purpose_Of primitives Let them take Checkpoint_Load_State'Class values instead of accesses to Root_Stream_Type'Class ones. This does not complicates the current (de)serialization code, and will allow simplifiaction of manual code from upcoming work. --- tools/gnatcov/checkpoints.adb | 8 ++--- tools/gnatcov/checkpoints.ads | 8 ++--- tools/gnatcov/coverage-source.adb | 8 ++--- tools/gnatcov/files_table.adb | 4 +-- tools/gnatcov/instrument-checkpoints.adb | 2 +- tools/gnatcov/sc_obligations-bdd.adb | 16 ++++------ tools/gnatcov/sc_obligations-bdd.ads | 7 ++--- tools/gnatcov/sc_obligations.adb | 37 +++++++++++------------- tools/gnatcov/traces_files_registry.adb | 2 +- 9 files changed, 40 insertions(+), 52 deletions(-) diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index c8256787d..16691eff5 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -583,7 +583,7 @@ package body Checkpoints is -- Check that we are loading the kind of checkpoint we are -- expecting (Purpose). - if not Version_Less (CLS'Access, Than => 2) then + if not CLS.Version_Less (Than => 2) then declare CP_Purpose : constant Checkpoint_Purpose := Checkpoint_Purpose'Input (CLS.Stream); @@ -600,7 +600,7 @@ package body Checkpoints is -- Check the kind of binary traces that were used to create this -- checkpoint. - if not Version_Less (CLS'Access, Than => 7) then + if not CLS.Version_Less (Than => 7) then declare Bits : constant Binary_Traces_Bits := Binary_Traces_Bits'Input (CLS.Stream); @@ -624,7 +624,7 @@ package body Checkpoints is end if; end; - if not Version_Less (CLS'Access, Than => 6) then + if not CLS.Version_Less (Than => 6) then declare CP_Trace_Kind : Any_Accepted_Trace_Kind; begin @@ -635,7 +635,7 @@ package body Checkpoints is Files_Table.Checkpoint_Load (CLS'Access, Ignored_Source_Files); SC_Obligations.Checkpoint_Load (CLS'Access); - if not Version_Less (CLS'Access, Than => 2) then + if not CLS.Version_Less (Than => 2) then Instrument.Checkpoints.Checkpoint_Load (CLS'Access); end if; Coverage.Source.Checkpoint_Load (CLS'Access); diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 81df6a963..48ff0fd66 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -253,15 +253,15 @@ package Checkpoints is use type Interfaces.Unsigned_32; function Version_Less - (CS : access Root_Stream_Type'Class; Than : Checkpoint_Version) - return Boolean is (Stateful_Stream (CS.all).Version < Than) + (SS : Stateful_Stream'Class; Than : Checkpoint_Version) return Boolean + is (SS.Version < Than) with Inline; -- This is provided as a function to prevent the compiler from generating -- "can never be greater than" warnings. function Purpose_Of - (CS : access Root_Stream_Type'Class) return Checkpoint_Purpose - is (Stateful_Stream (CS.all).Purpose) + (SS : Stateful_Stream'Class) return Checkpoint_Purpose + is (SS.Purpose) with Inline; -- Shortcut to get the purpose of a stream that is known to be an instance -- of Stateful_Stream. diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 3abf69745..06f810f4c 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -477,8 +477,7 @@ package body Coverage.Source is procedure Checkpoint_Load (CLS : access Checkpoint_Load_State) is use SCI_Vector_Vectors; - Stream_Tags : constant Boolean := - not Checkpoints.Version_Less (CLS, Than => 2); + Stream_Tags : constant Boolean := not CLS.Version_Less (Than => 2); -- Before version 2, we streamed mere tags in the checkpoint. We stream -- tag provider names since then. @@ -573,7 +572,7 @@ package body Coverage.Source is -- Before version 3, this list was not streamed. In this case, be -- conservative and consider that we don't have a valid list. - if Checkpoints.Version_Less (CLS, Than => 3) then + if CLS.Version_Less (Than => 3) then Invalidate_Unit_List (US.To_String (CLS.Filename) & " does not contain the list of units (obsolete format)"); @@ -581,8 +580,7 @@ package body Coverage.Source is else declare Invalidated : constant Boolean := Boolean'Input (CLS); - Obsolete : constant Boolean := - Checkpoints.Version_Less (CLS, Than => 12); + Obsolete : constant Boolean := CLS.Version_Less (Than => 12); Dummy : US.Unbounded_String; begin if Invalidated then diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index a8c75aae4..b0cee38b1 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -2033,7 +2033,7 @@ package body Files_Table is FE.Ignore_Status := Unknown; FE.Unit := (Known => False); - if not Checkpoints.Version_Less (CLS, Than => 5) then + if not CLS.Version_Less (Than => 5) then FE.Ignore_Status := Any_Ignore_Status'Input (S); declare Unit_Known : constant Boolean := Boolean'Input (S); @@ -2046,7 +2046,7 @@ package body Files_Table is -- the owning unit unknown if we do not have recent -- formats. - if Checkpoints.Version_Less (CLS, Than => 13) then + if CLS.Version_Less (Than => 13) then declare Dummy : constant String := String'Input (S); begin diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index 62c3e77ba..e22bdb235 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -95,7 +95,7 @@ package body Instrument.Checkpoints is -- Load the mappings for preprocessing commands - if not Version_Less (CLS, Than => 8) then + if not CLS.Version_Less (Than => 8) then declare CP_PP_Cmds : SFI_To_PP_Cmd_Maps.Map; CP_SFI : Source_File_Index; diff --git a/tools/gnatcov/sc_obligations-bdd.adb b/tools/gnatcov/sc_obligations-bdd.adb index 6e9350832..7227103dd 100644 --- a/tools/gnatcov/sc_obligations-bdd.adb +++ b/tools/gnatcov/sc_obligations-bdd.adb @@ -81,10 +81,8 @@ package body SC_Obligations.BDD is -- Read -- ---------- - procedure Read - (S : access Root_Stream_Type'Class; - V : out BDD_Type) - is + procedure Read (S : access Root_Stream_Type'Class; V : out BDD_Type) is + CLS : Stateful_Stream renames Stateful_Stream (S.all); begin SCO_Id'Read (S, V.Decision); BDD_Node_Id'Read (S, V.Root_Condition); @@ -93,15 +91,13 @@ package body SC_Obligations.BDD is BDD_Node_Id'Read (S, V.First_Multipath_Condition); Reachability'Read (S, V.Reachable_Outcomes); - if not Version_Less (S, Than => 2) then + if not CLS.Version_Less (Than => 2) then Natural'Read (S, V.Path_Count); end if; end Read; - procedure Read - (S : access Root_Stream_Type'Class; - V : out BDD_Node) - is + procedure Read (S : access Root_Stream_Type'Class; V : out BDD_Node) is + CLS : Stateful_Stream renames Stateful_Stream (S.all); New_BDDN : BDD_Node (BDD_Node_Kind'Input (S)); pragma Warnings (Off, New_BDDN); @@ -122,7 +118,7 @@ package body SC_Obligations.BDD is -- Checkpoint version 2 data (instrumentation support) - if not Version_Less (S, 2) then + if not CLS.Version_Less (2) then Natural'Read (S, V.Path_Offset); end if; diff --git a/tools/gnatcov/sc_obligations-bdd.ads b/tools/gnatcov/sc_obligations-bdd.ads index 0e5c17bea..9f397b8dc 100644 --- a/tools/gnatcov/sc_obligations-bdd.ads +++ b/tools/gnatcov/sc_obligations-bdd.ads @@ -78,8 +78,7 @@ private package SC_Obligations.BDD is -- Work around compiler bug: bogus warning??? procedure Read - (S : access Root_Stream_Type'Class; - V : out BDD_Node); + (S : access Root_Stream_Type'Class; V : out BDD_Node); procedure Write (S : access Root_Stream_Type'Class; V : BDD_Node); @@ -118,9 +117,7 @@ private package SC_Obligations.BDD is end record; pragma Warnings (Off, "* is not referenced"); - procedure Read - (S : access Root_Stream_Type'Class; - V : out BDD_Type); + procedure Read (S : access Root_Stream_Type'Class; V : out BDD_Type); procedure Write (S : access Root_Stream_Type'Class; V : BDD_Type); diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 83a183173..10b328a7a 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -147,9 +147,7 @@ package body SC_Obligations is procedure Read (S : access Root_Stream_Type'Class; V : out CU_Info); - procedure Write - (S : access Root_Stream_Type'Class; - V : CU_Info); + procedure Write (S : access Root_Stream_Type'Class; V : CU_Info); pragma Warnings (On, "* is not referenced"); for CU_Info'Read use Read; @@ -813,7 +811,6 @@ package body SC_Obligations is is Relocs : Checkpoint_Relocations renames CLS.Relocations; Real_CU : CU_Info renames CU_Vector.Reference (Real_CU_Id).Element.all; - S : constant access Root_Stream_Type'Class := CLS.all'Access; begin -- Here we already have loaded full SCO information for this CU, so -- all we need to do is to populate the tables mapping the SCO and @@ -856,7 +853,7 @@ package body SC_Obligations is -- Non-Instrumented SCO sets - if Version_Less (S, Than => 9) then + if CLS.Version_Less (Than => 9) then -- Nothing to do return; @@ -938,7 +935,6 @@ package body SC_Obligations is New_CU_Id : out CU_Id) is Relocs : Checkpoint_Relocations renames CLS.Relocations; - S : constant access Root_Stream_Type'Class := CLS.all'Access; New_First_Instance : Inst_Id; New_First_SCO : SCO_Id; @@ -1275,7 +1271,7 @@ package body SC_Obligations is -- belong to a CU already present in the current execution, and which -- would not be simply imported as is. - if not Version_Less (S, Than => 9) then + if not CLS.Version_Less (Than => 9) then for SCO of CP_Vectors.Non_Instr_SCOs loop if SCO in CP_CU.First_SCO .. CP_CU.Last_SCO then Non_Instr_SCOs.Insert (Remap_SCO_Id (Relocs, SCO)); @@ -1465,8 +1461,10 @@ package body SC_Obligations is (S : access Root_Stream_Type'Class; V : out CU_Info) is + CLS : Stateful_Stream renames Stateful_Stream (S.all); + Provider : constant SCO_Provider := - (if Version_Less (S, Than => 2) + (if CLS.Version_Less (Than => 2) then Compiler else SCO_Provider'Input (S)); -- Discriminant for v2 data @@ -1493,7 +1491,7 @@ package body SC_Obligations is -- Checkpoint version 8 preprocessing information - if not Version_Less (S, Than => 8) then + if not CLS.Version_Less (Than => 8) then SCO_PP_Info_Maps.Map'Read (S, V.PP_Info_Map); end if; @@ -1514,8 +1512,8 @@ package body SC_Obligations is V.Bit_Maps_Fingerprint := No_Fingerprint; - if not Version_Less (S, Than => 2) - and then Purpose_Of (S) = Instrumentation + if not CLS.Version_Less (Than => 2) + and then CLS.Purpose_Of = Instrumentation then V.Bit_Maps.Statement_Bits := new Statement_Bit_Map'(Statement_Bit_Map'Input (S)); @@ -1523,7 +1521,7 @@ package body SC_Obligations is new Decision_Bit_Map'(Decision_Bit_Map'Input (S)); V.Bit_Maps.MCDC_Bits := new MCDC_Bit_Map'(MCDC_Bit_Map'Input (S)); - if not Version_Less (S, Than => 11) then + if not CLS.Version_Less (Than => 11) then Fingerprint_Type'Read (S, V.Bit_Maps_Fingerprint); end if; end if; @@ -1531,7 +1529,7 @@ package body SC_Obligations is -- Checkpoint version 8 data (scoped metrics support) - if not Version_Less (S, Than => 8) then + if not CLS.Version_Less (Than => 8) then Scope_Entities_Tree'Read (S, V.Scope_Entities); end if; end Read; @@ -1540,10 +1538,8 @@ package body SC_Obligations is -- Write -- ----------- - procedure Write - (S : access Root_Stream_Type'Class; - V : CU_Info) - is + procedure Write (S : access Root_Stream_Type'Class; V : CU_Info) is + CLS : Stateful_Stream renames Stateful_Stream (S.all); begin SCO_Provider'Write (S, V.Provider); @@ -1565,7 +1561,7 @@ package body SC_Obligations is when Compiler => null; when Instrumenter => - if Purpose_Of (S) = Instrumentation then + if CLS.Purpose_Of = Instrumentation then Statement_Bit_Map'Output (S, V.Bit_Maps.Statement_Bits.all); Decision_Bit_Map'Output @@ -1598,7 +1594,7 @@ package body SC_Obligations is -- Load non-instrumented information - if not Version_Less (S, Than => 9) then + if not CLS.Version_Less (Than => 9) then SCO_Sets.Set'Read (S, CP_Vectors.Non_Instr_SCOs); SCO_Sets.Set'Read (S, CP_Vectors.Non_Instr_MCDC_SCOs); @@ -3898,6 +3894,7 @@ package body SC_Obligations is procedure Read (S : access Root_Stream_Type'Class; V : out SCO_Descriptor) is + CLS : Stateful_Stream renames Stateful_Stream (S.all); SCOD : SCO_Descriptor (SCO_Kind'Input (S)); begin if SCOD.Kind = Removed then @@ -3932,7 +3929,7 @@ package body SC_Obligations is -- Before version 2, decisions shared Operations's Operand member, -- and stored the expression as its Right array item. - if Version_Less (S, Than => 2) then + if CLS.Version_Less (Than => 2) then declare Operands : constant Operand_Pair := Operand_Pair'Input (S); begin diff --git a/tools/gnatcov/traces_files_registry.adb b/tools/gnatcov/traces_files_registry.adb index 854e56bc9..c987a7f57 100644 --- a/tools/gnatcov/traces_files_registry.adb +++ b/tools/gnatcov/traces_files_registry.adb @@ -382,7 +382,7 @@ package body Traces_Files_Registry is CP_File := new Trace_File_Element; CP_File.Filename := Name; - if Checkpoints.Version_Less (CLS, Than => 2) then + if CLS.Version_Less (Than => 2) then -- Before version 2, there were only binary traces and we -- streamed metadata as trace infos. From d9875176f992e51f96dad81b37c3c612d71a7f98 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 17 Nov 2023 09:13:35 +0000 Subject: [PATCH 0505/1483] Checkpoint_Load: remove dead code Now that gnatcov reject all checkpoint versions except the last one, all the code that handles previous versions is dead: clean it up. --- tools/gnatcov/checkpoints.adb | 66 ++++++------ tools/gnatcov/coverage-source.adb | 80 +++------------ tools/gnatcov/files_table.adb | 35 ++----- tools/gnatcov/instrument-checkpoints.adb | 74 +++++++------- tools/gnatcov/sc_obligations-bdd.adb | 15 +-- tools/gnatcov/sc_obligations.adb | 122 +++++++---------------- tools/gnatcov/traces_files_registry.adb | 56 +---------- 7 files changed, 132 insertions(+), 316 deletions(-) diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index 16691eff5..394ec36e0 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -583,36 +583,32 @@ package body Checkpoints is -- Check that we are loading the kind of checkpoint we are -- expecting (Purpose). - if not CLS.Version_Less (Than => 2) then - declare - CP_Purpose : constant Checkpoint_Purpose := - Checkpoint_Purpose'Input (CLS.Stream); - begin - if CP_Purpose /= Purpose then - Fatal_Error - (Filename & " is a " & Purpose_Name (CP_Purpose) - & " while a " & Purpose_Name (Purpose) - & " was expected"); - end if; - end; - end if; + declare + CP_Purpose : constant Checkpoint_Purpose := + Checkpoint_Purpose'Input (CLS.Stream); + begin + if CP_Purpose /= Purpose then + Fatal_Error + (Filename & " is a " & Purpose_Name (CP_Purpose) + & " while a " & Purpose_Name (Purpose) + & " was expected"); + end if; + end; -- Check the kind of binary traces that were used to create this -- checkpoint. - if not CLS.Version_Less (Than => 7) then - declare - Bits : constant Binary_Traces_Bits := - Binary_Traces_Bits'Input (CLS.Stream); - begin - if Bits not in Undetermined | Supported_Bits then - Fatal_Error - (Filename & " was created with " & Image (Bits) - & " whereas the selected target requires " - & Image (Supported_Bits)); - end if; - end; - end if; + declare + Bits : constant Binary_Traces_Bits := + Binary_Traces_Bits'Input (CLS.Stream); + begin + if Bits not in Undetermined | Supported_Bits then + Fatal_Error + (Filename & " was created with " & Image (Bits) + & " whereas the selected target requires " + & Image (Supported_Bits)); + end if; + end; Levels_Type'Read (CLS.Stream, Levels); declare @@ -624,20 +620,16 @@ package body Checkpoints is end if; end; - if not CLS.Version_Less (Than => 6) then - declare - CP_Trace_Kind : Any_Accepted_Trace_Kind; - begin - Any_Accepted_Trace_Kind'Read (CLS.Stream, CP_Trace_Kind); - Update_Current_Trace_Kind (CP_Trace_Kind); - end; - end if; + declare + CP_Trace_Kind : Any_Accepted_Trace_Kind; + begin + Any_Accepted_Trace_Kind'Read (CLS.Stream, CP_Trace_Kind); + Update_Current_Trace_Kind (CP_Trace_Kind); + end; Files_Table.Checkpoint_Load (CLS'Access, Ignored_Source_Files); SC_Obligations.Checkpoint_Load (CLS'Access); - if not CLS.Version_Less (Than => 2) then - Instrument.Checkpoints.Checkpoint_Load (CLS'Access); - end if; + Instrument.Checkpoints.Checkpoint_Load (CLS'Access); Coverage.Source.Checkpoint_Load (CLS'Access); Traces_Files_Registry.Checkpoint_Load (CLS'Access); diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 06f810f4c..2e4f00c08 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -23,7 +23,6 @@ with Ada.Containers.Ordered_Maps; with Ada.Directories; with Ada.Streams; use Ada.Streams; with Ada.Strings.Unbounded; -with Ada.Tags; with Ada.Unchecked_Deallocation; with Interfaces; @@ -477,10 +476,6 @@ package body Coverage.Source is procedure Checkpoint_Load (CLS : access Checkpoint_Load_State) is use SCI_Vector_Vectors; - Stream_Tags : constant Boolean := not CLS.Version_Less (Than => 2); - -- Before version 2, we streamed mere tags in the checkpoint. We stream - -- tag provider names since then. - CP_Tag_Provider : Unbounded_String; CP_SCI_Vector : SCI_Vector_Vectors.Vector; Relocs : Checkpoint_Relocations renames CLS.Relocations; @@ -491,23 +486,7 @@ package body Coverage.Source is -- tag provider is the default (i.e. no coverage separation), or same -- as checkpoint. - if Stream_Tags then - CP_Tag_Provider := To_Unbounded_String (String'Input (CLS)); - else - declare - Tag : Ada.Tags.Tag; - begin - Ada.Tags.Tag'Read (CLS, Tag); - CP_Tag_Provider := To_Unbounded_String (Tag_Providers.Name (Tag)); - exception - when Constraint_Error => - Warn ("cannot read " & To_String (CLS.Filename) - & ", it was produced with an incompatible version of " - & "gnatcov"); - CP_Tag_Provider := To_Unbounded_String (""); - end; - end if; - + CP_Tag_Provider := To_Unbounded_String (String'Input (CLS)); if Tag_Provider.all not in Default_Tag_Provider_Type and then Tag_Provider_Name /= To_String (CP_Tag_Provider) then @@ -569,48 +548,21 @@ package body Coverage.Source is if CLS.Purpose = Consolidation then - -- Before version 3, this list was not streamed. In this case, be - -- conservative and consider that we don't have a valid list. - - if CLS.Version_Less (Than => 3) then - Invalidate_Unit_List - (US.To_String (CLS.Filename) - & " does not contain the list of units (obsolete format)"); - - else - declare - Invalidated : constant Boolean := Boolean'Input (CLS); - Obsolete : constant Boolean := CLS.Version_Less (Than => 12); - Dummy : US.Unbounded_String; - begin - if Invalidated then - Invalidate_Unit_List - (US.To_String (CLS.Filename) - & " does not contain the list of units (produced with" - & " --scos or --sid)"); - else - for I in 1 .. Ada.Containers.Count_Type'Input (CLS) loop - - -- From version 3 up to version 11, Unit_List used to - -- be a set of unbounded strings, and did not support - -- homonym source files. If we are in that case, read the - -- old Unit_List from the checkpoint and then discard it. - - if Obsolete then - if I = 1 then - Invalidate_Unit_List - (US.To_String (CLS.Filename) - & " does not contain the list of units (obsolete" - & " format)"); - end if; - US.Unbounded_String'Read (CLS, Dummy); - else - Unit_List.Include (Compilation_Unit'Input (CLS)); - end if; - end loop; - end if; - end; - end if; + declare + Invalidated : constant Boolean := Boolean'Input (CLS); + Dummy : US.Unbounded_String; + begin + if Invalidated then + Invalidate_Unit_List + (US.To_String (CLS.Filename) + & " does not contain the list of units (produced with --scos" + & " or --sid)"); + else + for I in 1 .. Ada.Containers.Count_Type'Input (CLS) loop + Unit_List.Include (Compilation_Unit'Input (CLS)); + end loop; + end if; + end; end if; end Checkpoint_Load; diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index b0cee38b1..e95bb2d65 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -2033,32 +2033,15 @@ package body Files_Table is FE.Ignore_Status := Unknown; FE.Unit := (Known => False); - if not CLS.Version_Less (Than => 5) then - FE.Ignore_Status := Any_Ignore_Status'Input (S); - declare - Unit_Known : constant Boolean := Boolean'Input (S); - begin - if Unit_Known then - - -- Starting with the version 13 of checkpoints, - -- owning units are represented as Compilation_Unit - -- values (they were mere strings before). Consider - -- the owning unit unknown if we do not have recent - -- formats. - - if CLS.Version_Less (Than => 13) then - declare - Dummy : constant String := String'Input (S); - begin - null; - end; - else - FE.Unit := (Known => True, - Name => Compilation_Unit'Input (S)); - end if; - end if; - end; - end if; + FE.Ignore_Status := Any_Ignore_Status'Input (S); + declare + Unit_Known : constant Boolean := Boolean'Input (S); + begin + if Unit_Known then + FE.Unit := (Known => True, + Name => Compilation_Unit'Input (S)); + end if; + end; when Library_File => FE := (Kind => Library_File, others => <>); FE.Main_Source := Source_File_Index'Input (S); diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index e22bdb235..17bce2971 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -95,46 +95,44 @@ package body Instrument.Checkpoints is -- Load the mappings for preprocessing commands - if not CLS.Version_Less (Than => 8) then - declare - CP_PP_Cmds : SFI_To_PP_Cmd_Maps.Map; - CP_SFI : Source_File_Index; - begin - SFI_To_PP_Cmd_Maps.Map'Read (CLS.Stream, CP_PP_Cmds); - - for CP_Cur in CP_PP_Cmds.Iterate loop - - -- If this source file is now ignored, just discard its - -- preprocessing commands. - - CP_SFI := SFI_To_PP_Cmd_Maps.Key (CP_Cur); - if not SFI_Ignored (Relocs, CP_SFI) then - declare - SFI : constant Source_File_Index := - Remap_SFI (Relocs, CP_SFI); - Cur : constant SFI_To_PP_Cmd_Maps.Cursor := - PP_Cmds.Find (SFI); - begin - -- If there was no known preprocessing command for SFI so - -- far, just register the loaded one. - - if not SFI_To_PP_Cmd_Maps.Has_Element (Cur) then - PP_Cmds.Insert (SFI, CP_PP_Cmds.Reference (CP_Cur)); - - -- Otherwise, warn if the already known command and the + declare + CP_PP_Cmds : SFI_To_PP_Cmd_Maps.Map; + CP_SFI : Source_File_Index; + begin + SFI_To_PP_Cmd_Maps.Map'Read (CLS.Stream, CP_PP_Cmds); + + for CP_Cur in CP_PP_Cmds.Iterate loop + + -- If this source file is now ignored, just discard its + -- preprocessing commands. + + CP_SFI := SFI_To_PP_Cmd_Maps.Key (CP_Cur); + if not SFI_Ignored (Relocs, CP_SFI) then + declare + SFI : constant Source_File_Index := + Remap_SFI (Relocs, CP_SFI); + Cur : constant SFI_To_PP_Cmd_Maps.Cursor := + PP_Cmds.Find (SFI); + begin + -- If there was no known preprocessing command for SFI so + -- far, just register the loaded one. + + if not SFI_To_PP_Cmd_Maps.Has_Element (Cur) then + PP_Cmds.Insert (SFI, CP_PP_Cmds.Reference (CP_Cur)); + + -- Otherwise, warn if the already known command and the -- loaded one are different. - elsif CP_PP_Cmds.Reference (CP_Cur) - /= PP_Cmds.Reference (Cur) - then - Warn ("inconsistent information for instrumented file " - & Get_Full_Name (SFI)); - end if; - end; - end if; - end loop; - end; - end if; + elsif CP_PP_Cmds.Reference (CP_Cur) + /= PP_Cmds.Reference (Cur) + then + Warn ("inconsistent information for instrumented file " + & Get_Full_Name (SFI)); + end if; + end; + end if; + end loop; + end; end Checkpoint_Load; end Instrument.Checkpoints; diff --git a/tools/gnatcov/sc_obligations-bdd.adb b/tools/gnatcov/sc_obligations-bdd.adb index 7227103dd..87c25c86f 100644 --- a/tools/gnatcov/sc_obligations-bdd.adb +++ b/tools/gnatcov/sc_obligations-bdd.adb @@ -82,7 +82,6 @@ package body SC_Obligations.BDD is ---------- procedure Read (S : access Root_Stream_Type'Class; V : out BDD_Type) is - CLS : Stateful_Stream renames Stateful_Stream (S.all); begin SCO_Id'Read (S, V.Decision); BDD_Node_Id'Read (S, V.Root_Condition); @@ -90,17 +89,12 @@ package body SC_Obligations.BDD is BDD_Node_Id'Read (S, V.Last_Node); BDD_Node_Id'Read (S, V.First_Multipath_Condition); Reachability'Read (S, V.Reachable_Outcomes); - - if not CLS.Version_Less (Than => 2) then - Natural'Read (S, V.Path_Count); - end if; + Natural'Read (S, V.Path_Count); end Read; procedure Read (S : access Root_Stream_Type'Class; V : out BDD_Node) is - CLS : Stateful_Stream renames Stateful_Stream (S.all); New_BDDN : BDD_Node (BDD_Node_Kind'Input (S)); pragma Warnings (Off, New_BDDN); - begin -- Set discriminant @@ -115,12 +109,7 @@ package body SC_Obligations.BDD is Boolean'Read (S, V.Parent_Value); SCO_Id'Read (S, V.C_SCO); Destinations'Read (S, V.Dests); - - -- Checkpoint version 2 data (instrumentation support) - - if not CLS.Version_Less (2) then - Natural'Read (S, V.Path_Offset); - end if; + Natural'Read (S, V.Path_Offset); when Jump => BDD_Node_Id'Read (S, V.Dest); diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 10b328a7a..8da527dfe 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -853,12 +853,6 @@ package body SC_Obligations is -- Non-Instrumented SCO sets - if CLS.Version_Less (Than => 9) then - - -- Nothing to do - return; - end if; - declare use SCO_Sets; CU_CP_Set : Set; @@ -1266,24 +1260,22 @@ package body SC_Obligations is end; end loop; - -- If we have information about non instrumented units, import them as - -- is. Only import SCOs that belong to this CU, as others SCOs might - -- belong to a CU already present in the current execution, and which - -- would not be simply imported as is. + -- Import information about non instrumented units. Only import SCOs + -- that belong to this CU, as others SCOs might belong to a CU already + -- present in the current execution, and which would not be simply + -- imported as is. - if not CLS.Version_Less (Than => 9) then - for SCO of CP_Vectors.Non_Instr_SCOs loop - if SCO in CP_CU.First_SCO .. CP_CU.Last_SCO then - Non_Instr_SCOs.Insert (Remap_SCO_Id (Relocs, SCO)); - end if; - end loop; + for SCO of CP_Vectors.Non_Instr_SCOs loop + if SCO in CP_CU.First_SCO .. CP_CU.Last_SCO then + Non_Instr_SCOs.Insert (Remap_SCO_Id (Relocs, SCO)); + end if; + end loop; - for SCO of CP_Vectors.Non_Instr_MCDC_SCOs loop - if SCO in CP_CU.First_SCO .. CP_CU.Last_SCO then - Non_Instr_MCDC_SCOs.Insert (Remap_SCO_Id (Relocs, SCO)); - end if; - end loop; - end if; + for SCO of CP_Vectors.Non_Instr_MCDC_SCOs loop + if SCO in CP_CU.First_SCO .. CP_CU.Last_SCO then + Non_Instr_MCDC_SCOs.Insert (Remap_SCO_Id (Relocs, SCO)); + end if; + end loop; -- Perform final fixups and insert CU @@ -1463,12 +1455,7 @@ package body SC_Obligations is is CLS : Stateful_Stream renames Stateful_Stream (S.all); - Provider : constant SCO_Provider := - (if CLS.Version_Less (Than => 2) - then Compiler else SCO_Provider'Input (S)); - -- Discriminant for v2 data - - New_CUI : CU_Info (Provider); + New_CUI : CU_Info (SCO_Provider'Input (S)); pragma Warnings (Off, New_CUI); -- Used only for discriminant and default initialization @@ -1477,61 +1464,42 @@ package body SC_Obligations is V := New_CUI; - -- Checkpoint version 1 data - - Source_File_Index'Read (S, V.Origin); - Source_File_Index'Read (S, V.Main_Source); - SCO_Id'Read (S, V.First_SCO); - SCO_Id'Read (S, V.Last_SCO); - Inst_Id'Read (S, V.First_Instance); - Inst_Id'Read (S, V.Last_Instance); - SFI_Vector'Read (S, V.Deps); - Boolean'Read (S, V.Has_Code); - Fingerprint_Type'Read (S, V.Fingerprint); - - -- Checkpoint version 8 preprocessing information - - if not CLS.Version_Less (Than => 8) then - SCO_PP_Info_Maps.Map'Read (S, V.PP_Info_Map); - end if; + Source_File_Index'Read (S, V.Origin); + Source_File_Index'Read (S, V.Main_Source); + SCO_Id'Read (S, V.First_SCO); + SCO_Id'Read (S, V.Last_SCO); + Inst_Id'Read (S, V.First_Instance); + Inst_Id'Read (S, V.Last_Instance); + SFI_Vector'Read (S, V.Deps); + Boolean'Read (S, V.Has_Code); + Fingerprint_Type'Read (S, V.Fingerprint); + SCO_PP_Info_Maps.Map'Read (S, V.PP_Info_Map); case V.Provider is when Compiler => null; when Instrumenter => - -- Checkpoint version 2 data (instrumentation support) - -- By default, use "no fingerprint" for buffer bit maps - -- fingerprints: either the SID file we load is too old to have - -- such fingerprints, either we are loading a checkpoint, and by - -- design checkpoints contains neither bit maps nor their - -- fingerprints (all source traces are processed before loading - -- checkpoints, and bit maps are needed only to interpret source - -- traces). + -- fingerprints: by design checkpoints contains neither bit maps + -- nor their fingerprints (all source traces are processed before + -- loading checkpoints, and bit maps are needed only to interpret + -- source traces). V.Bit_Maps_Fingerprint := No_Fingerprint; - if not CLS.Version_Less (Than => 2) - and then CLS.Purpose_Of = Instrumentation - then + if CLS.Purpose_Of = Instrumentation then V.Bit_Maps.Statement_Bits := new Statement_Bit_Map'(Statement_Bit_Map'Input (S)); V.Bit_Maps.Decision_Bits := new Decision_Bit_Map'(Decision_Bit_Map'Input (S)); V.Bit_Maps.MCDC_Bits := new MCDC_Bit_Map'(MCDC_Bit_Map'Input (S)); - if not CLS.Version_Less (Than => 11) then - Fingerprint_Type'Read (S, V.Bit_Maps_Fingerprint); - end if; + Fingerprint_Type'Read (S, V.Bit_Maps_Fingerprint); end if; end case; - -- Checkpoint version 8 data (scoped metrics support) - - if not CLS.Version_Less (Than => 8) then - Scope_Entities_Tree'Read (S, V.Scope_Entities); - end if; + Scope_Entities_Tree'Read (S, V.Scope_Entities); end Read; ----------- @@ -1542,9 +1510,6 @@ package body SC_Obligations is CLS : Stateful_Stream renames Stateful_Stream (S.all); begin SCO_Provider'Write (S, V.Provider); - - -- Checkpoint version 1 data - Source_File_Index'Write (S, V.Origin); Source_File_Index'Write (S, V.Main_Source); SCO_Id'Write (S, V.First_SCO); @@ -1594,11 +1559,8 @@ package body SC_Obligations is -- Load non-instrumented information - if not CLS.Version_Less (Than => 9) then - SCO_Sets.Set'Read (S, CP_Vectors.Non_Instr_SCOs); - SCO_Sets.Set'Read - (S, CP_Vectors.Non_Instr_MCDC_SCOs); - end if; + SCO_Sets.Set'Read (S, CP_Vectors.Non_Instr_SCOs); + SCO_Sets.Set'Read (S, CP_Vectors.Non_Instr_MCDC_SCOs); -- Allocate mapping tables for SCOs, instance identifiers and BDD nodes @@ -3894,7 +3856,6 @@ package body SC_Obligations is procedure Read (S : access Root_Stream_Type'Class; V : out SCO_Descriptor) is - CLS : Stateful_Stream renames Stateful_Stream (S.all); SCOD : SCO_Descriptor (SCO_Kind'Input (S)); begin if SCOD.Kind = Removed then @@ -3925,20 +3886,7 @@ package body SC_Obligations is SCOD.Index := Condition_Index'Input (S); when Decision => - - -- Before version 2, decisions shared Operations's Operand member, - -- and stored the expression as its Right array item. - - if CLS.Version_Less (Than => 2) then - declare - Operands : constant Operand_Pair := Operand_Pair'Input (S); - begin - SCOD.Expression := Operands (Right); - end; - else - SCOD.Expression := SCO_Id'Input (S); - end if; - + SCOD.Expression := SCO_Id'Input (S); SCOD.D_Kind := Decision_Kind'Input (S); SCOD.Control_Location := Source_Location'Input (S); SCOD.Last_Cond_Index := Any_Condition_Index'Input (S); diff --git a/tools/gnatcov/traces_files_registry.adb b/tools/gnatcov/traces_files_registry.adb index c987a7f57..3d1136b71 100644 --- a/tools/gnatcov/traces_files_registry.adb +++ b/tools/gnatcov/traces_files_registry.adb @@ -381,57 +381,11 @@ package body Traces_Files_Registry is exit when Length (Name) = 0; CP_File := new Trace_File_Element; CP_File.Filename := Name; - - if CLS.Version_Less (Than => 2) then - - -- Before version 2, there were only binary traces and we - -- streamed metadata as trace infos. - - CP_File.Kind := Binary_Trace_File; - CP_File.Context := Null_Unbounded_String; - CP_File.Program_Name := Null_Unbounded_String; - CP_File.Time := Null_Unbounded_String; - CP_File.User_Data := Null_Unbounded_String; - - declare - Kind : Info_Kind_Type; - Data : Unbounded_String; - begin - loop - Info_Kind_Type'Read (CLS, Kind); - exit when Kind = Info_End; - - Unbounded_String'Read (CLS, Data); - case Kind is - when Exec_File_Name => - CP_File.Program_Name := Data; - when Date_Time => - CP_File.Time := To_Unbounded_String - (Format_Date_Info (To_String (Data))); - when User_Data => - CP_File.User_Data := Data; - when Coverage_Context => - CP_File.Context := Data; - when others => - null; - end case; - end loop; - end; - - -- All traces in checkpoints are supposed to have a coverage - -- context. - - if Length (CP_File.Context) = 0 then - raise Program_Error; - end if; - - else - Trace_File_Kind'Read (CLS, CP_File.Kind); - Unbounded_String'Read (CLS, CP_File.Context); - Unbounded_String'Read (CLS, CP_File.Program_Name); - Unbounded_String'Read (CLS, CP_File.Time); - Unbounded_String'Read (CLS, CP_File.User_Data); - end if; + Trace_File_Kind'Read (CLS, CP_File.Kind); + Unbounded_String'Read (CLS, CP_File.Context); + Unbounded_String'Read (CLS, CP_File.Program_Name); + Unbounded_String'Read (CLS, CP_File.Time); + Unbounded_String'Read (CLS, CP_File.User_Data); Add_Traces_File (CP_File); end; From 142a8e4bb8184bead6262487a056a654e0b71624 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 27 Nov 2023 10:43:39 +0000 Subject: [PATCH 0506/1483] U204-026-arch-mix: comment typo fix --- testsuite/tests/U204-026-arch-mix/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/U204-026-arch-mix/test.py b/testsuite/tests/U204-026-arch-mix/test.py index 1d48d7a72..6f3fed02d 100644 --- a/testsuite/tests/U204-026-arch-mix/test.py +++ b/testsuite/tests/U204-026-arch-mix/test.py @@ -165,7 +165,7 @@ def check_reports(xcov_dir): # 4. Check that we can use source traces produced on a different host # -thistest.log("== 3. src-traces mix ==") +thistest.log("== 4. src-traces mix ==") mkdir("4-xcov") sid_list = "sids.txt" with open(sid_list, "w") as f: From c38e1e93258777b0e899a6d39473b14046bc5572 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 27 Nov 2023 14:35:11 +0000 Subject: [PATCH 0507/1483] instrument-setup_config.adb: minor reformattings --- tools/gnatcov/instrument-setup_config.adb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index 744b72cac..3a952ac7c 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -48,6 +48,10 @@ package body Instrument.Setup_Config is -- system installation if Fallback_To_System is True (and so return the -- first name of Program_Names), otherwise error out. + ------------------------ + -- Find_Compiler_Prog -- + ------------------------ + function Find_Compiler_Prog (Compiler_Driver : String; Program_Names : String_Vectors.Vector; @@ -334,8 +338,7 @@ package body Instrument.Setup_Config is -- Load_Config -- ----------------- - function Load_Config (Config_File : String) return Instrumentation_Config - is + function Load_Config (Config_File : String) return Instrumentation_Config is Result : Instrumentation_Config; Channel : Any_Dump_Channel; Config_JSON : JSON_Value; From 804341e17b6659e1e2f249030e5e510fa4ba9b65 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 27 Nov 2023 16:24:42 +0000 Subject: [PATCH 0508/1483] SCOV.map: do not pass "-v" to "gnatcov map-routines" The goal of this test driver is to detect the presence of decision map issue ("!!!" and "***" messages), which are emitted regardless of whether "-v" is passed. Upcoming work will trigger the emission of "branch stats" when "-v" is passed (it is currently enabled only when --branch-stats is passed), and logging code for --branch-stats currently crashes or create spurious test failures. As a workaround, do not pass "-v" anymore. --- testsuite/SCOV/map.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/SCOV/map.py b/testsuite/SCOV/map.py index 4e7ca155d..9675fac8c 100644 --- a/testsuite/SCOV/map.py +++ b/testsuite/SCOV/map.py @@ -54,7 +54,7 @@ def run(self): # Run xcov map-routines and check absence of errors mapoutput = do(maybe_valgrind([ - XCOV, 'map-routines', '-v', f'--target={env.target.triplet}', + XCOV, 'map-routines', f'--target={env.target.triplet}', '--scos=@{}'.format(list_to_file(self.alis)), ] + self.execs)) From 681a6fd401196fb95dcbcb8d9a81b632c1aeb8aa Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 27 Nov 2023 08:51:15 +0000 Subject: [PATCH 0509/1483] Rework the verbose mode towards GNATCOLL.Traces-based logs Use the GNATCOLL.Traces package to create different categories for logs, so that we can enable only the traces relevant for what is being debugged (see the `*_Trace : Logging.GNATCOLL_Trace` constants declared where appropriate). In addition to GNATCOLL.Traces's traditional way of configuring which logs are enabled (i.e. the .gnatdebug file in the current directory), also add a `--log ` command line option (internal, just like --verbose) to enable the GNATCOLL trace called GNATCOV.. Still keep --verbose/-v as a convenient way to activate all GNATCOV.* traces so that we still have a way to print all information when we do not know what we are looking for exactly. Also introduce --quiet/-q switches (public, this time) to instruct gnatcov not to print logs it normally emits by default, for instance gprbuild/gprinstall logs for "gnatcov setup". Remove "debug switches" (-dX for various X letters) as they are now obsolete: each one now has a GNATCOLL trace that controls the corresponding on/off setting. --- .../tests/KB30-011-eargs-gnatemu/test.py | 2 +- .../tests/MB15-041-verbose-open-crc32/test.py | 2 +- testsuite/tests/S529-038-isi-ckpt/test.py | 4 +- .../tests/instr-cov/file-context/test.py | 11 +- .../tests/instr-cov/unknown_unit/test.py | 3 +- tools/gnatcov/ali_files.adb | 5 +- tools/gnatcov/annotations.adb | 2 +- tools/gnatcov/cfg_dump.adb | 67 +++----- tools/gnatcov/cfg_dump.ads | 4 + tools/gnatcov/command_line.adb | 18 +++ tools/gnatcov/command_line.ads | 34 ++-- tools/gnatcov/command_line_support.adb | 76 --------- tools/gnatcov/command_line_support.ads | 62 -------- tools/gnatcov/coverage-source.adb | 17 +- tools/gnatcov/coverage-source.ads | 6 + tools/gnatcov/decision_map.adb | 17 +- tools/gnatcov/diagnostics.adb | 2 +- tools/gnatcov/diagnostics.ads | 4 + tools/gnatcov/files_table.adb | 55 ++++--- tools/gnatcov/files_table.ads | 8 +- tools/gnatcov/gnatcov.adb | 13 +- tools/gnatcov/gnatcov_bits_specific.adb | 50 ++---- tools/gnatcov/inputs.adb | 7 +- tools/gnatcov/instrument-ada_unit.adb | 7 +- tools/gnatcov/instrument-c.adb | 2 +- tools/gnatcov/instrument-setup_config.adb | 29 +++- tools/gnatcov/instrument-source.adb | 2 +- tools/gnatcov/logging.adb | 146 ++++++++++++++++++ tools/gnatcov/logging.ads | 50 ++++++ tools/gnatcov/object_locations.adb | 4 +- tools/gnatcov/project.adb | 7 +- tools/gnatcov/rundrv-handlers.adb | 4 +- tools/gnatcov/rundrv.ads | 4 + tools/gnatcov/sc_obligations-bdd.adb | 3 +- tools/gnatcov/sc_obligations.adb | 68 ++++---- tools/gnatcov/sc_obligations.ads | 7 + tools/gnatcov/setup_rts.adb | 79 +++++----- tools/gnatcov/setup_rts.ads | 4 + tools/gnatcov/subprocesses.adb | 50 +++--- tools/gnatcov/subprocesses.ads | 4 + tools/gnatcov/switches.adb | 12 +- tools/gnatcov/switches.ads | 46 ++---- tools/gnatcov/temp_dirs.adb | 7 +- tools/gnatcov/traces.ads | 12 ++ tools/gnatcov/traces_disa.adb | 3 +- tools/gnatcov/traces_disa.ads | 6 + tools/gnatcov/traces_names.adb | 5 +- 47 files changed, 555 insertions(+), 475 deletions(-) delete mode 100644 tools/gnatcov/command_line_support.adb delete mode 100644 tools/gnatcov/command_line_support.ads create mode 100644 tools/gnatcov/logging.adb create mode 100644 tools/gnatcov/logging.ads diff --git a/testsuite/tests/KB30-011-eargs-gnatemu/test.py b/testsuite/tests/KB30-011-eargs-gnatemu/test.py index c3326f737..f30b9f09f 100644 --- a/testsuite/tests/KB30-011-eargs-gnatemu/test.py +++ b/testsuite/tests/KB30-011-eargs-gnatemu/test.py @@ -27,7 +27,7 @@ def check_eargs(output, eargs, exe, protect_eargs=False): - m = re.search('exec:\n .*gnatemu.*', output) + m = re.search('exec: .*gnatemu.*', output) e = m.group(0) if protect_eargs: eargs = ' '.join ([f"'{arg}'" for arg in eargs.split(" ")]) diff --git a/testsuite/tests/MB15-041-verbose-open-crc32/test.py b/testsuite/tests/MB15-041-verbose-open-crc32/test.py index feefe57a9..159ad3e9f 100644 --- a/testsuite/tests/MB15-041-verbose-open-crc32/test.py +++ b/testsuite/tests/MB15-041-verbose-open-crc32/test.py @@ -19,7 +19,7 @@ CWD_LINE_PREFIX = 'CWD = ' LOG_OPEN_RE = re.compile( - r'--- notice: open "(?P[^"]+)"' + r'\[GNATCOV\.MISC\] --- notice: open "(?P[^"]+)"' r' \(CRC32 = 0x(?P[0-9a-f]{8})\)' ) diff --git a/testsuite/tests/S529-038-isi-ckpt/test.py b/testsuite/tests/S529-038-isi-ckpt/test.py index 1cf8c73df..c233cc1f0 100644 --- a/testsuite/tests/S529-038-isi-ckpt/test.py +++ b/testsuite/tests/S529-038-isi-ckpt/test.py @@ -106,7 +106,7 @@ def check_error(argv, log_name, expected_error): '--checkpoint', ckpt(1), trace(1)], out='leak.log') thistest.fail_if( - 'discarding source trace entry for unknown instrumented unit: body of' - ' main1' not in lines_of('leak.log')) + '[GNATCOV.MISC] discarding source trace entry for unknown instrumented' + ' unit: body of main1' not in lines_of('leak.log')) thistest.result() diff --git a/testsuite/tests/instr-cov/file-context/test.py b/testsuite/tests/instr-cov/file-context/test.py index 24a8d3186..1a519f6fe 100644 --- a/testsuite/tests/instr-cov/file-context/test.py +++ b/testsuite/tests/instr-cov/file-context/test.py @@ -52,17 +52,20 @@ def do_instr(label, args): actual_lines = [ line for line in lines_of(log) - if line.startswith("Instrumenting ") or line.startswith("warning: ") + if ( + line.startswith("[GNATCOV.MISC] Instrumenting ") + or line.startswith("warning: ") + ) ] thistest.fail_if_not_equal( f'"gnatcov instrument" output', - "\n".join(actual_lines), "\n".join([ - "Instrumenting main.adb", + "[GNATCOV.MISC] Instrumenting main.adb", "warning: Cannot find required source file: missing_a.ads", "warning: Cannot find required source file: missing_b.ads", - "Instrumenting pkg.ads", + "[GNATCOV.MISC] Instrumenting pkg.ads", ]), + "\n".join(actual_lines), ) thistest.result() diff --git a/testsuite/tests/instr-cov/unknown_unit/test.py b/testsuite/tests/instr-cov/unknown_unit/test.py index bcd174a0f..4fb028703 100644 --- a/testsuite/tests/instr-cov/unknown_unit/test.py +++ b/testsuite/tests/instr-cov/unknown_unit/test.py @@ -48,7 +48,8 @@ '--sid', unrelated_sid, trace_file], out='coverage.log') thistest.fail_if( - 'discarding source trace entry for unknown instrumented unit: body of pkg' + '[GNATCOV.MISC] discarding source trace entry for unknown instrumented' + ' unit: body of pkg' not in lines_of('coverage.log')) thistest.result() diff --git a/tools/gnatcov/ali_files.adb b/tools/gnatcov/ali_files.adb index 9e3a9e511..8d9c223cd 100644 --- a/tools/gnatcov/ali_files.adb +++ b/tools/gnatcov/ali_files.adb @@ -28,7 +28,6 @@ with Files_Table; use Files_Table; with Get_SCOs; with Inputs; use Inputs; with Outputs; use Outputs; -with Switches; use Switches; package body ALI_Files is @@ -386,9 +385,7 @@ package body ALI_Files is -- Here once the ALI file has been succesfully opened - if Verbose then - Put_Line ("Loading SCOs from " & ALI_Filename); - end if; + SCOs_Trace.Trace ("Loading SCOs from " & ALI_Filename); Expected_Annotation_Kind := Exempt_On; Expected_Annotation_Msg := null; diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index bc30f5c6b..6b958b0be 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -562,7 +562,7 @@ package body Annotations is Cur : constant Cursor := ALI_Annotations.Floor (Sloc); begin - if not Debug_Ignore_Exemptions + if not Ignore_Exemptions_Trace.Is_Active and then Cur /= No_Element and then Key (Cur).Source_File = Sloc.Source_File then diff --git a/tools/gnatcov/cfg_dump.adb b/tools/gnatcov/cfg_dump.adb index 3aa9be786..5e93263e4 100644 --- a/tools/gnatcov/cfg_dump.adb +++ b/tools/gnatcov/cfg_dump.adb @@ -45,7 +45,6 @@ with Qemu_Traces; with SC_Obligations; with Strings; with Support_Files; -with Switches; with Traces; use Traces; with Traces_Dbase; with Traces_Elf; use Traces_Elf; @@ -1750,29 +1749,16 @@ package body CFG_Dump is Context.Keep_Edges := Keep_Edges; Context.Tag_Executed := Inputs.Length (Traces_Files_List) > 0; - if Switches.Verbose then - Report - (Msg => "Hello, this is the dumper!", - Kind => Notice); - Report - (Msg => "Dumping code from: " & Exec_Path, - Kind => Notice); - Report - (Msg => - (if Output = null - then "To standard output" - else "To " & Output.all), - Kind => Notice); - Report - (Msg => "Format: " & Output_Format'Image (Format), - Kind => Notice); - Report - (Msg => - (if Keep_Edges - then "Keep edges that follow exception raises" - else "Strip edges that follow exception raises"), - Kind => Notice); - end if; + CFG_Dump_Trace.Trace ("Dumping code from: " & Exec_Path); + CFG_Dump_Trace.Trace + (if Output = null + then "To standard output" + else "To " & Output.all); + CFG_Dump_Trace.Trace ("Format: " & Output_Format'Image (Format)); + CFG_Dump_Trace.Trace + (if Keep_Edges + then "Keep edges that follow exception raises" + else "Strip edges that follow exception raises"); begin Execs_Dbase.Open_Exec (Exec_Path, 0, Context.Exec); @@ -1781,38 +1767,26 @@ package body CFG_Dump is Fatal_Error ("Could not open " & Exec_Path); end; - if Switches.Verbose then - Report (Msg => "Reading symbols...", Kind => Notice); - end if; + CFG_Dump_Trace.Trace ("Reading symbols..."); Build_Symbols (Context.Exec.all); Translate_Locations (Ctx.Exec, Locations, Context.Locs); if Context.Group_By_Condition then Coverage.Set_Coverage_Levels ("stmt+mcdc"); - if Switches.Verbose then - Report (Msg => "Loading ALI files...", Kind => Notice); - end if; + CFG_Dump_Trace.Trace ("Loading ALI files..."); Inputs.Iterate (SCO_Files_List, Load_SCOs'Access); Coverage.Source.Initialize_SCI; - if Switches.Verbose then - Report (Msg => "Reading routine names...", Kind => Notice); - end if; + CFG_Dump_Trace.Trace ("Reading routine names..."); Read_Routine_Names (Context.Exec.all, Exclude => False); end if; - if Switches.Verbose then - Report (Msg => "Reading debug line info...", Kind => Notice); - end if; + CFG_Dump_Trace.Trace ("Reading debug line info..."); Build_Debug_Lines (Context.Exec.all); if Context.Group_By_Condition then - if Switches.Verbose then - Report - (Msg => "Performing static analysis for decisions...", - Kind => Notice); - end if; + CFG_Dump_Trace.Trace ("Performing static analysis for decisions..."); Decision_Map.Analyze (Context.Exec); end if; @@ -1826,13 +1800,10 @@ package body CFG_Dump is exit when Section = null; if Section.Section_Name.all = ".text" then - if Switches.Verbose then - Report - (Msg => "ELF section #" - & Strings.Img (Integer (Section.Section_Sec_Idx)) - & " looks interesting: loading its instructions...", - Kind => Notice); - end if; + CFG_Dump_Trace.Trace + ("ELF section #" + & Strings.Img (Integer (Section.Section_Sec_Idx)) + & " looks interesting: loading its instructions..."); Load_Section_Content (Context.Exec.all, Section); Collect_Instructions (Ctx, Section); end if; diff --git a/tools/gnatcov/cfg_dump.ads b/tools/gnatcov/cfg_dump.ads index e61a81921..79bd1e2e2 100644 --- a/tools/gnatcov/cfg_dump.ads +++ b/tools/gnatcov/cfg_dump.ads @@ -19,11 +19,15 @@ with GNAT.Strings; use GNAT.Strings; with Inputs; +with Logging; with Object_Locations; use Object_Locations; with Slocs; use Slocs; package CFG_Dump is + CFG_Dump_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("CFG_DUMP"); + type Output_Format is (None, Dot, SVG, PDF, PNG); -- Format used to output the CFG. None stands for "output the Dot graph -- without passing it to dot(1)". diff --git a/tools/gnatcov/command_line.adb b/tools/gnatcov/command_line.adb index d90a065e2..c41901de4 100644 --- a/tools/gnatcov/command_line.adb +++ b/tools/gnatcov/command_line.adb @@ -34,8 +34,26 @@ package body Command_Line is case Option is when Opt_Include => Result.Remaining_Args.Append (+"--include"); + when Opt_Exclude => Result.Remaining_Args.Append (+"--exclude"); + + when Opt_Quiet => + + -- "--quiet" cancels all the previous requests to enable logs + -- ("--log") and cancels any previuos request for full verbosity + -- ("--verbose"). + + Result.Bool_Args (Opt_Verbose) := False; + Result.String_List_Args (Opt_Log).Clear; + + when Opt_Verbose => + + -- "--verbose" cancels any previous request for quiet verbosity + -- ("--quiet"). + + Result.Bool_Args (Opt_Quiet) := False; + when others => null; end case; diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index fe1b15c93..382461ab1 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -17,8 +17,7 @@ ------------------------------------------------------------------------------ with Argparse; -with Command_Line_Support; use Command_Line_Support; -with Coverage_Options; use Coverage_Options; +with Coverage_Options; use Coverage_Options; package Command_Line is @@ -29,6 +28,8 @@ package Command_Line is Cmd_Help_Internal, Cmd_Version, + Cmd_List_Logs, + Cmd_Run, Cmd_Convert, Cmd_Coverage, @@ -67,13 +68,13 @@ package Command_Line is type Bool_Options is (Opt_Verbose, + Opt_Quiet, Opt_Recursive, Opt_No_Subprojects, Opt_All_Decisions, Opt_All_Messages, Opt_Include, Opt_Exclude, - Opt_Branch_Stats, Opt_Excluded_SCOs, Opt_Keep_Edges, Opt_Pretty_Print, @@ -142,7 +143,7 @@ package Command_Line is -- Set of string options we support. More complete descriptions below. type String_List_Options is - (Opt_Debug, + (Opt_Log, Opt_Projects, Opt_Scenario_Var, Opt_Eargs, @@ -192,6 +193,13 @@ package Command_Line is Description => "Display the version.", Internal => False), + Cmd_List_Logs => Create + (Name => "list-logs", + Pattern => "", + Description => + "Dump the list of GNATcov available logs (GNATCOLL traces).", + Internal => True), + Cmd_Run => Create (Name => "run", Pattern => "[OPTIONS] [EXE] [-eargs [EXE] EARGS...]", @@ -399,6 +407,10 @@ package Command_Line is (Long_Name => "--verbose", Short_Name => "-v", Help => "Print lots of debugging information.", Internal => True), + Opt_Quiet => Create + (Long_Name => "--quiet", Short_Name => "-q", + Help => "Print nothing but errors/warnings.", + Internal => False), Opt_Recursive => Create (Long_Name => "--recursive", Help => "DEPRECATED: In addition to those designated by" @@ -445,12 +457,6 @@ package Command_Line is & " the command line to the list of routines", Commands => (Cmd_Disp_Routines => True, others => False), Internal => False), - Opt_Branch_Stats => Create - (Long_Name => "--stats", - Help => "Dump statistics about branch instructions after the" - & " static analysis pass.", - Commands => (Cmd_Map_Routines => True, others => False), - Internal => True), Opt_Excluded_SCOs => Create (Long_Name => "--non-coverable", Help => "Report SCOs whose coverage cannot be established due to" @@ -1109,10 +1115,10 @@ package Command_Line is ); String_List_Infos : constant String_List_Option_Info_Array := - (Opt_Debug => Create - (Short_Name => "-d", - Pattern => Debug_Command_Line_Pattern, - Help => Debug_Command_Line_Help, + (Opt_Log => Create + (Long_Name => "--log", + Pattern => "[GNATCOLL_TRACE_NAME]", + Help => "Enable logging for the given GNATCOLL trace name.", Internal => True), Opt_Projects => Create (Long_Name => "--projects", diff --git a/tools/gnatcov/command_line_support.adb b/tools/gnatcov/command_line_support.adb deleted file mode 100644 index b4e9b5504..000000000 --- a/tools/gnatcov/command_line_support.adb +++ /dev/null @@ -1,76 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2009-2022, 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.Strings.Unbounded; use Ada.Strings.Unbounded; - -with Strings; use Strings; - -package body Command_Line_Support is - - Debug_Switches_Help : constant array (Valid_Debug_Type) - of Ada.Strings.Unbounded.Unbounded_String := - (Break_Long_Instructions => - +"Break long instructions in disassemblies, a la objdump", - Full_History => - +("Keep full historical traces for MC/DC even for decisions that do" - & " not require it (decisions without multi-path conditions)."), - Ignore_Exemptions => - +"Exemption pragmas have no effect.", - File_Table => - +"Print debugging messages for files table management."); - - -------------------------------- - -- Debug_Command_Line_Pattern -- - -------------------------------- - - function Debug_Command_Line_Pattern return String is - Result : Unbounded_String; - begin - for C in Debug_Switches_Map'Range loop - if Debug_Switches_Map (C) /= None then - if Length (Result) >= 1 then - Append (Result, '|'); - end if; - Append (Result, C); - end if; - end loop; - return To_String (Result); - end Debug_Command_Line_Pattern; - - ----------------------------- - -- Debug_Command_Line_Help -- - ----------------------------- - - function Debug_Command_Line_Help return String is - Result : Unbounded_String; - begin - Append (Result, "Debug switch: change various behaviors."); - for C in Debug_Switches_Map'Range loop - declare - S : constant Debug_Type := Debug_Switches_Map (C); - begin - if S /= None then - Append (Result, ASCII.LF & ASCII.LF); - Append (Result, " -d" & C & ": " & Debug_Switches_Help (S)); - end if; - end; - end loop; - return To_String (Result); - end Debug_Command_Line_Help; - -end Command_Line_Support; diff --git a/tools/gnatcov/command_line_support.ads b/tools/gnatcov/command_line_support.ads deleted file mode 100644 index 74dc43c55..000000000 --- a/tools/gnatcov/command_line_support.ads +++ /dev/null @@ -1,62 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2009-2022, 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. -- ------------------------------------------------------------------------------- - -package Command_Line_Support is - - ------------------------------ - -- Debugging switches (-d?) -- - ------------------------------ - - -- Set of debug switches to expose on command-line - - type Debug_Type is - (None, - - Break_Long_Instructions, - -- Break long instructions in disassemblies, a la objdump - - Full_History, - -- Keep full historical traces for MC/DC even for decisions that do not - -- require it (decisions without multi-path conditions). - - Ignore_Exemptions, - -- Exemption pragmas have no effect. - - File_Table); - -- Show debugging output for files table management - - subtype Valid_Debug_Type is Debug_Type range - Break_Long_Instructions .. File_Table; - -- Set of debug switches to expose on command-line - - Debug_Switches_Map : constant array (Character) of Debug_Type := - ('b' => Break_Long_Instructions, - 'h' => Full_History, - 'i' => Ignore_Exemptions, - 'f' => File_Table, - others => None); - -- Map characters to switches. Update this map to make a debug flags - -- available through the -d command-line argument (see command_line.ads). - - function Debug_Command_Line_Pattern return String; - -- Return a pattern string for the usage of the command-line -d option - - function Debug_Command_Line_Help return String; - -- Return a help string for the usage of the command-line -d option - -end Command_Line_Support; diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 2e4f00c08..0353192cc 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -1651,7 +1651,7 @@ package body Coverage.Source is Inferred_Values := Infer_Values (SCO); Inferred_Values.Append (CBE.Origin); - if Debug_Full_History then + if Full_History_Trace.Is_Active then -- In full history debugging mode, we record the -- evaluation history and check it against the -- inferred vector. @@ -1713,7 +1713,7 @@ package body Coverage.Source is & "abandoning evaluation", Kind => Notice); if Has_Multipath_Condition (D_SCO) - or else Debug_Full_History + or else Full_History_Trace.Is_Active then Evaluation_Stack.Delete_Last; end if; @@ -1765,7 +1765,7 @@ package body Coverage.Source is when 3 => if MCDC_Coverage_Enabled and then (Has_Multipath_Condition (D_SCO) - or else Debug_Full_History) + or else Full_History_Trace.Is_Active) then -- For MC/DC we need full historical traces, not just -- accumulated traces. @@ -1972,10 +1972,9 @@ package body Coverage.Source is -- just log the fact that we skip this trace entry in the verbose -- about, just in case. - if Verbose then - Put_Line ("discarding source trace entry for unknown instrumented" - & " unit: " & Unit_Image); - end if; + Misc_Trace.Trace + ("discarding source trace entry for unknown instrumented unit: " + & Unit_Image); return; elsif Provider (CU) /= Instrumenter then @@ -2131,7 +2130,9 @@ package body Coverage.Source is -- No-op if decision has no multi-path condition and not debugging - if not (Has_Multipath_Condition (D_SCO) or else Debug_Full_History) then + if not (Has_Multipath_Condition (D_SCO) + or else Full_History_Trace.Is_Active) + then return; end if; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index e696d29c6..3b0e4c0e8 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -22,12 +22,18 @@ with Checkpoints; use Checkpoints; with Files_Table; use Files_Table; with Instrument; use Instrument; with Instrument.Input_Traces; use Instrument.Input_Traces; +with Logging; with Traces; use Traces; with Traces_Names; use Traces_Names; with Traces_Lines; use Traces_Lines; package Coverage.Source is + Ignore_Exemptions_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("IGNORE_EXEMPTIONS"); + -- Note that enabling this trace will make gnatcov ignore source coverage + -- exemptions (exemption pragmas will have no effect). + procedure Initialize_SCI; -- Initialize source coverage information vector once SCOs have been loaded -- This can be called multiple times if SCO information is loaded in chunks diff --git a/tools/gnatcov/decision_map.adb b/tools/gnatcov/decision_map.adb index 955560070..be396a9e9 100644 --- a/tools/gnatcov/decision_map.adb +++ b/tools/gnatcov/decision_map.adb @@ -1891,11 +1891,11 @@ package body Decision_Map is -- Mark instruction address for full (historical) traces collection -- (for MC/DC source coverage analysis) if required by decision - -- structure (presence of multiple paths) or if Debug_Full_History - -- is set. + -- structure (presence of multiple paths) or if Full_History_Trace is + -- enabled. if Has_Multipath_Condition (Enclosing_Decision (CBI.Condition)) - or else Debug_Full_History + or else Full_History_Trace.Is_Active then Add_Entry (Base => Decision_Map_Base, @@ -2485,11 +2485,10 @@ package body Decision_Map is -- Start of processing for Analyze_Routine begin - if Branch_Stats then + if Branch_Stats_Trace.Is_Active then Put_Line ("Branch statistics for " & Subp_Name, '^'); - - elsif Verbose then - Put_Line ("building decision map for " & Subp_Name); + else + Misc_Trace.Trace ("building decision map for " & Subp_Name); end if; Context.Subprg := @@ -2769,7 +2768,7 @@ package body Decision_Map is -- All done if doing only statement coverage - if not (Branch_Stats + if not (Branch_Stats_Trace.Is_Active or else Enabled (Decision) or else MCDC_Coverage_Enabled) then @@ -2873,7 +2872,7 @@ package body Decision_Map is -- Statistics processing - if Branch_Stats then + if Branch_Stats_Trace.Is_Active then -- Update statistics diff --git a/tools/gnatcov/diagnostics.adb b/tools/gnatcov/diagnostics.adb index 8b4ebed3d..bf431acbf 100644 --- a/tools/gnatcov/diagnostics.adb +++ b/tools/gnatcov/diagnostics.adb @@ -282,7 +282,7 @@ package body Diagnostics is -- always reported in the annotated sources or report output, so it's -- fine to omit them here. - if Verbose + if Diagnostics_Trace.Is_Active or else (M.Kind < Violation and then not Suppress_Message (M)) then Put_Line (Image (M)); diff --git a/tools/gnatcov/diagnostics.ads b/tools/gnatcov/diagnostics.ads index b50e31b3b..8f9011ffa 100644 --- a/tools/gnatcov/diagnostics.ads +++ b/tools/gnatcov/diagnostics.ads @@ -37,6 +37,7 @@ with Ada.Containers.Vectors; with Ada.Strings.Unbounded; with Coverage; use Coverage; +with Logging; with SC_Obligations; use SC_Obligations; with Slocs; use Slocs; with Traces; use Traces; @@ -44,6 +45,9 @@ with Traces_Elf; use Traces_Elf; package Diagnostics is + Diagnostics_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("DIAGNOSTICS"); + type Report_Kind is (Notice, Low_Warning, diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index e95bb2d65..ab508cf78 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -36,7 +36,6 @@ with Coverage; use Coverage; with Outputs; with Perf_Counters; use Perf_Counters; with Project; -with Switches; package body Files_Table is @@ -316,12 +315,10 @@ package body Files_Table is -- are canonicalized. begin - if Switches.Verbose then - Put_Line ("Adding source rebase:"); - Put_Line (" Glob -> " & Old_Prefix); - Put_Line (" Regexp -> " & Regexp); - Put_Line (" Will become: " & New_Prefix); - end if; + Files_Table_Trace.Trace ("Adding source rebase:"); + Files_Table_Trace.Trace (" Glob -> " & Old_Prefix); + Files_Table_Trace.Trace (" Regexp -> " & Regexp); + Files_Table_Trace.Trace (" Will become: " & New_Prefix); E := new Source_Rebase_Entry' (Old_Prefix => new Pattern_Matcher'(Compile (Regexp, Flags)), @@ -735,9 +732,10 @@ package body Files_Table is Info_Simple : File_Info_Access; begin - if Switches.Debug_File_Table then - Put_Line ("GIFN: <<" & Full_Name & ">> ISN=" & Indexed_Simple_Name'Img - & " Insert=" & Insert'Img); + if Files_Table_Trace.Is_Active then + Files_Table_Trace.Trace + ("GIFN: <<" & Full_Name & ">> ISN=" & Indexed_Simple_Name'Img + & " Insert=" & Insert'Img); end if; -- First lookup the full path in the Renaming_Map as this file can @@ -840,8 +838,8 @@ package body Files_Table is end; <> - if Switches.Debug_File_Table then - Put_Line (" ->" & Res'Img); + if Files_Table_Trace.Is_Active then + Files_Table_Trace.Trace (" ->" & Res'Img); end if; if Res in Valid_Source_File_Index then Consolidate_File_Kind (Res, Kind); @@ -867,8 +865,9 @@ package body Files_Table is Simple_Name_Map.Find (Simple_Path); Res : Source_File_Index; begin - if Switches.Debug_File_Table then - Put ("GISN: <<" & Simple_Name & ">> Insert=" & Insert'Img); + if Files_Table_Trace.Is_Active then + Files_Table_Trace.Trace + ("GISN: <<" & Simple_Name & ">> Insert=" & Insert'Img); end if; if Cur /= Simple_Name_Maps.No_Element then @@ -891,8 +890,8 @@ package body Files_Table is Simple_Name_Map.Insert (Simple_Path, Res); end if; - if Switches.Debug_File_Table then - Put_Line (" ->" & Res'Img); + if Files_Table_Trace.Is_Active then + Files_Table_Trace.Trace (" ->" & Res'Img); end if; if Res in Valid_Source_File_Index then @@ -914,9 +913,9 @@ package body Files_Table is is Result : Source_File_Index; begin - if Switches.Debug_File_Table then - Put ("GIGN: <<" & Name - & ">> ISN=" & Indexed_Simple_Name'Img & " -> "); + if Files_Table_Trace.Is_Active then + Files_Table_Trace.Trace + ("GIGN: <<" & Name & ">> ISN=" & Indexed_Simple_Name'Img & " -> "); end if; if Is_Absolute_Path (Name) then @@ -1360,14 +1359,14 @@ package body Files_Table is pragma Assert (not Files_Table_Frozen); - if Switches.Debug_File_Table then + if Files_Table_Trace.Is_Active then declare Name : constant String_Access := (if FI.Full_Name = null then FI.Simple_Name else FI.Full_Name); begin - Put_Line + Files_Table_Trace.Trace ("Promoting " & Name.all & " from stub to source file"); end; end if; @@ -2066,10 +2065,9 @@ package body Files_Table is and then GNAT.Regexp.Match (+Create (+FE.Name.all).Base_Name, Ignored_Source_Files.all) then - if Switches.Verbose then - Put_Line ("Ignored SFI from SID file:" & CP_SFI'Image - & " (" & FE.Name.all & ")"); - end if; + Files_Table_Trace.Trace + ("Ignored SFI from SID file:" & CP_SFI'Image + & " (" & FE.Name.all & ")"); Ignore_SFI (Relocs, CP_SFI); -- Still insert this source file in the files table to keep @@ -2140,10 +2138,9 @@ package body Files_Table is end if; Set_SFI_Map (Relocs, CP_SFI, SFI); - if Switches.Verbose then - Put_Line ("Remap " & FE.Name.all & ":" & CP_SFI'Img - & " ->" & Remap_SFI (Relocs, CP_SFI)'Img); - end if; + Files_Table_Trace.Trace + ("Remap " & FE.Name.all & ":" & CP_SFI'Img + & " ->" & Remap_SFI (Relocs, CP_SFI)'Img); end if; end; end loop; diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index b37a043c3..8c32c02d7 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -29,18 +29,22 @@ limited with Checkpoints; with Coverage_Options; use Coverage_Options; with Diagnostics; use Diagnostics; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with Logging; with Paths; use Paths; with SC_Obligations; use SC_Obligations; with Slocs; use Slocs; with Strings; -with Traces_Elf; use Traces_Elf; with Traces_Dbase; use Traces_Dbase; -with Traces_Stats; use Traces_Stats; +with Traces_Elf; use Traces_Elf; with Traces_Lines; use Traces_Lines; +with Traces_Stats; use Traces_Stats; with Types; use Types; package Files_Table is + Files_Table_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("FILE_TABLE"); + -- This package manages a source file table and, for each file, a table of -- its source lines. Coverage information can be associated with each -- file/line. Only object coverage is supported. diff --git a/tools/gnatcov/gnatcov.adb b/tools/gnatcov/gnatcov.adb index 57eb6b280..c84d34db6 100644 --- a/tools/gnatcov/gnatcov.adb +++ b/tools/gnatcov/gnatcov.adb @@ -20,8 +20,6 @@ with Ada.Command_Line; use Ada.Command_Line; with Ada.Directories; with Ada.Environment_Variables; use Ada.Environment_Variables; with Ada.Strings.Fixed; use Ada.Strings.Fixed; -with Ada.Text_IO; use Ada.Text_IO; - with GNAT.OS_Lib; with GNAT.Strings; use GNAT.Strings; @@ -39,7 +37,6 @@ begin -- forwarding all arguments as-is. Parse_Arguments (From_Driver => True); - Verbose := Args.Bool_Args (Opt_Verbose); -- Determine if the target is 32-bit or 64-bit: consider it's 32-bit unless -- we can find the "64" substring before the first dash. @@ -85,9 +82,7 @@ begin Success : Boolean; begin - if Verbose then - Put_Line ("Running: " & Exec_Filename); - end if; + Misc_Trace.Trace ("Running: " & Exec_Filename); -- Make sure that the arch-specific entry point knows what the prefix is -- so that it can locale support files. Also make sure that the name of @@ -114,11 +109,9 @@ begin -- exitted with an error". To avoid overly verbose output in the -- latter case (the bits-specific entry point is already supposed to -- print an explicit error message), restrict the following message - -- to the verbose mode. + -- to a trace. - if Verbose then - Put_Line ("Could not spawn " & Exec_Filename & ": aborting"); - end if; + Misc_Trace.Trace ("Could not spawn " & Exec_Filename & ": aborting"); end if; end; exception diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index e4d944d08..98fbda502 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -48,7 +48,6 @@ with Check_SCOs; with Checkpoints; with Command_Line; use Command_Line; use Command_Line.Parser; -with Command_Line_Support; with Convert; with Coverage.Source; use Coverage.Source; with Coverage.Tags; use Coverage.Tags; @@ -67,6 +66,7 @@ with Instrument.Projects; with Instrument.Setup_Config; with Instrument.Source; with Instrument.Input_Traces; +with Logging; with Object_Locations; with Outputs; use Outputs; with Perf_Counters; @@ -430,11 +430,11 @@ procedure GNATcov_Bits_Specific is Inputs.Iterate (SID_Inputs, SID_Load_Wrapper'Access); -- Now that all the scope entities that can be referenced by - -- --subprograms are known, dump them in verbose mode. + -- --subprograms are known, dump them if requested. - if Verbose then + if Scope_Entities_Trace.Is_Active then for CU in 1 .. Last_CU loop - Put_Line ("Scopes for " & Image (CU) & ":"); + Scope_Entities_Trace.Trace ("Scopes for " & Image (CU) & ":"); Dump (Get_Scope_Entities (CU), Line_Prefix => "| "); end loop; end if; @@ -509,21 +509,17 @@ procedure GNATcov_Bits_Specific is begin -- First, handle all options... - Verbose := Args.Bool_Args (Opt_Verbose); Switches.All_Decisions := Args.Bool_Args (Opt_All_Decisions); Switches.All_Messages := Args.Bool_Args (Opt_All_Messages); - Branch_Stats := Args.Bool_Args (Opt_Branch_Stats); Excluded_SCOs := Args.Bool_Args (Opt_Excluded_SCOs); Keep_Edges := Args.Bool_Args (Opt_Keep_Edges); Pretty_Print := Args.Bool_Args (Opt_Pretty_Print); Keep_Reading_Traces := Args.Bool_Args (Opt_Keep_Reading_Traces); Dump_Units := Args.String_Args (Opt_Dump_Units_To).Present; Show_MCDC_Vectors := (Args.Bool_Args (Opt_Show_MCDC_Vectors) - or else All_Messages - or else Verbose); + or else All_Messages); Show_Condition_Vectors := (Args.Bool_Args (Opt_Show_Condition_Vectors) - or else All_Messages - or else Verbose); + or else All_Messages); Allow_Mixing_Trace_Kinds := Args.Bool_Args (Opt_Allow_Mix_Trace_Kind); Short_Circuit_And_Or := Args.Bool_Args (Opt_Boolean_Short_Circuit_And_Or); @@ -735,22 +731,6 @@ procedure GNATcov_Bits_Specific is end; end if; - for Arg of Args.String_List_Args (Opt_Debug) loop - for Char of Ada.Strings.Unbounded.To_String (Arg) loop - declare - use Command_Line_Support; - - Switch : constant Debug_Type := Debug_Switches_Map (Char); - begin - if Switch = None then - Fatal_Error ("Invalid debug switch: -d" & Char); - else - Debug_Switches (Switch) := True; - end if; - end; - end loop; - end loop; - for Arg of Args.String_List_Args (Opt_Shared_Object) loop declare @@ -1252,7 +1232,7 @@ begin Raise_Stub_Internal_Error_For (Arguments_Loading); Process_Arguments; - if Verbose then + if Misc_Trace.Is_Active then Show_Version; Show_CWD; Perf_Counters.Enable; @@ -1275,10 +1255,13 @@ begin Print_Usage (Arg_Parser, True, False); when Cmd_Version => - if not Verbose then + if not Misc_Trace.Is_Active then Show_Version; end if; + when Cmd_List_Logs => + Logging.Print_List; + when Cmd_Disp_Routines => declare Mode_Exclude : Boolean := False; @@ -1545,7 +1528,7 @@ begin begin Load_All_ALIs (Check_SCOs => True); Inputs.Iterate (Exe_Inputs, Build_Decision_Map'Access); - if Verbose then + if SCOs_Trace.Is_Active then SC_Obligations.Report_SCOs_Without_Code; end if; SC_Obligations.Report_Units_Without_Code; @@ -2166,8 +2149,9 @@ begin Build_Debug_Compile_Units (Exe_File.all); - if Verbose and then Trace_File /= null then - Put_Line ("Processing traces from " & Trace_Filename); + if Trace_File /= null then + Misc_Trace.Trace + ("Processing traces from " & Trace_Filename); end if; Load_Code_And_Traces (Exe_File, Base'Access); @@ -2377,7 +2361,7 @@ begin end if; end if; - if Source_Coverage_Enabled and then Verbose then + if Source_Coverage_Enabled and then SCOs_Trace.Is_Active then SC_Obligations.Report_Units_Without_Code; end if; @@ -2611,7 +2595,7 @@ begin end case; - if Verbose then + if Misc_Trace.Is_Active then Perf_Counters.Display; end if; diff --git a/tools/gnatcov/inputs.adb b/tools/gnatcov/inputs.adb index 2b4072985..5329532ed 100644 --- a/tools/gnatcov/inputs.adb +++ b/tools/gnatcov/inputs.adb @@ -239,9 +239,10 @@ package body Inputs is end Get_CRC32; begin - if Switches.Verbose then - Put_Line ("--- notice: open """ & File_Name & """ (CRC32 = " - & Get_CRC32 & ")"); + if Switches.Misc_Trace.Is_Active then + Switches.Misc_Trace.Trace + ("--- notice: open """ & File_Name + & """ (CRC32 = " & Get_CRC32 & ")"); end if; end Log_File_Open; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 1a15acefc..52b6b7fe5 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -25,7 +25,6 @@ with Ada.Strings.Wide_Wide_Fixed; pragma Warnings (Off, "* is an internal GNAT unit"); with Ada.Strings.Wide_Wide_Unbounded.Aux; pragma Warnings (On, "* is an internal GNAT unit"); -with Ada.Text_IO; use Ada.Text_IO; with Ada.Streams.Stream_IO; with Langkit_Support; @@ -2805,7 +2804,7 @@ package body Instrument.Ada_Unit is Report (UIC, Common_Nodes.N, "failed to determine return type of expression function: " - & (if Switches.Verbose + & (if Switches.Misc_Trace.Is_Active then Ada.Exceptions.Exception_Message (Exc) else Ada.Exceptions.Exception_Information (Exc)), Low_Warning); @@ -9096,8 +9095,8 @@ package body Instrument.Ada_Unit is -- prepared to print it in case we emit a "source file missing" -- warning through Libadalang's event handler. - if Verbose then - Put_Line ("Instrumenting " & Basename); + if Switches.Misc_Trace.Is_Active then + Switches.Misc_Trace.Trace ("Instrumenting " & Basename); else Event_Handler.Instrumented_File := To_Unbounded_String (Basename); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 081b4d1c8..3dff09ff8 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2813,7 +2813,7 @@ package body Instrument.C is & " options is passed to gnatcov instrument"); raise Xcov_Exit_Exc; end if; - if Verbose then + if Misc_Trace.Is_Active then Run_Diagnostics (Self.TU); end if; Free (C_Args); diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index 3a952ac7c..26a58c580 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -27,6 +27,7 @@ with GNAT.Strings; with Coverage; with JSON; use JSON; +with Logging; with Outputs; use Outputs; with Paths; use Paths; with Support_Files; use Support_Files; @@ -322,7 +323,20 @@ package body Instrument.Setup_Config is Config.Set_Field ("coverage_level", Coverage_Level); Config.Set_Field ("tag", Instrumentation_Tag); Config.Set_Field ("save_temps", Switches.Save_Temps); - Config.Set_Field ("verbose", Switches.Verbose); + + Config.Set_Field ("quiet", Switches.Quiet); + declare + Verbose : Boolean; + To_Enable : String_Vectors.Vector; + Names : JSON_Array; + begin + Logging.Get_Configuration (Verbose, To_Enable); + for N of To_Enable loop + Append (Names, Create (+N)); + end loop; + Config.Set_Field ("verbose", Verbose); + Config.Set_Field ("logs", Names); + end; -- Dump the instrumentation configuration in a JSON file. Do not write -- the compact representation of the JSON as we may reach the character @@ -352,9 +366,20 @@ package body Instrument.Setup_Config is Config_JSON := Parsed_JSON.Value; Switches.Save_Temps := Config_JSON.Get ("save_temps"); - Switches.Verbose := Config_JSON.Get ("verbose"); Coverage.Set_Coverage_Levels (Config_JSON.Get ("coverage_level")); + declare + Verbose : Boolean; + To_Enable : String_Vectors.Vector; + begin + Switches.Quiet := Config_JSON.Get ("quiet"); + Verbose := Config_JSON.Get ("verbose"); + for N of JSON_Array'(Config_JSON.Get ("logs")) loop + To_Enable.Append (+N.Get); + end loop; + Logging.Initialize (Verbose, To_Enable); + end; + declare FOI_JSON : constant JSON_Array := Config_JSON.Get ("files-of-interest"); diff --git a/tools/gnatcov/instrument-source.adb b/tools/gnatcov/instrument-source.adb index 1749140fe..2e3b2638b 100644 --- a/tools/gnatcov/instrument-source.adb +++ b/tools/gnatcov/instrument-source.adb @@ -57,7 +57,7 @@ begin Context'Access, Purpose => Checkpoints.Instrumentation); - if Switches.Verbose then + if SC_Obligations.SCOs_Trace.Is_Active then SC_Obligations.Dump_All_SCOs; end if; diff --git a/tools/gnatcov/logging.adb b/tools/gnatcov/logging.adb new file mode 100644 index 000000000..3514505dd --- /dev/null +++ b/tools/gnatcov/logging.adb @@ -0,0 +1,146 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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.Characters.Handling; use Ada.Characters.Handling; +with Ada.Text_IO; use Ada.Text_IO; + +package body Logging is + + Verbose : Boolean := False; + -- Whether the "--verbose" command line flag is active + + Enabled_Traces : String_Sets.Set; + -- Set of names for all GNATCOLL traces requested to be enabled on the + -- command line ("--log"). + + Explicitly_Enabled : String_Vectors.Vector; + -- Copy of the To_Enable argument passed to Initialize + + function Unprefixed_Name (Handle : GNATCOLL_Trace) return String; + -- If Handle's name starts with GNATCOLL_Trace_Prefix (i.e. if it is a + -- GNATcov trace), return its normalized unprefixed name. Return an empty + -- string otherwise. + + procedure Try_Enabling (Handle : GNATCOLL_Trace); + -- If the verbose mode is enabled, enable Handle if its name starts with + -- GNATCOLL_Trace_Prefix. Otherwise, enable it if its name starts with + -- GNATCOLL_Trace_Prefix *and* is in Enabled_Traces. + + GNATcov_Traces : String_Sets.Set; + -- Temporary for Print_List: set of names for GNATcov traces + + procedure Add_Trace (Handle : GNATCOLL_Trace); + -- If Handle's name starts with GNATCOLL_Trace_Prefix, add the name to + -- GNATcov_Traces. + + ------------------ + -- Create_Trace -- + ------------------ + + function Create_Trace (Unit_Name : String) return GNATCOLL_Trace is + begin + return GNATCOLL.Traces.Create (GNATCOLL_Trace_Prefix & Unit_Name); + end Create_Trace; + + --------------------- + -- Unprefixed_Name -- + --------------------- + + function Unprefixed_Name (Handle : GNATCOLL_Trace) return String is + Name : constant String := To_Lower (Handle.Unit_Name); + begin + if Has_Prefix (Name, GNATCOLL_Trace_Prefix) then + return Name (Name'First + GNATCOLL_Trace_Prefix'Length .. Name'Last); + else + return ""; + end if; + end Unprefixed_Name; + + ------------------ + -- Try_Enabling -- + ------------------ + + procedure Try_Enabling (Handle : GNATCOLL_Trace) is + Name : constant String := Unprefixed_Name (Handle); + begin + if Name /= "" + and then (Verbose + or else Enabled_Traces.Contains (+Name)) + then + Handle.Set_Active (Active => True); + end if; + end Try_Enabling; + + ---------------- + -- Initialize -- + ---------------- + + procedure Initialize (Verbose : Boolean; To_Enable : String_Vectors.Vector) + is + begin + Logging.Verbose := Verbose; + Explicitly_Enabled := To_Enable; + for Name of To_Enable loop + Enabled_Traces.Include (+To_Lower (+Name)); + end loop; + + GNATCOLL.Traces.Parse_Config_File; + GNATCOLL.Traces.For_Each_Handle (Try_Enabling'Access); + end Initialize; + + ----------------------- + -- Get_Configuration -- + ----------------------- + + procedure Get_Configuration + (Verbose : out Boolean; + To_Enable : out String_Vectors.Vector) is + begin + Verbose := Logging.Verbose; + To_Enable := Explicitly_Enabled; + end Get_Configuration; + + --------------- + -- Add_Trace -- + --------------- + + procedure Add_Trace (Handle : GNATCOLL_Trace) is + Name : constant String := Unprefixed_Name (Handle); + begin + if Name /= "" then + GNATcov_Traces.Include (+Name); + end if; + end Add_Trace; + + ---------------- + -- Print_List -- + ---------------- + + procedure Print_List is + begin + -- To get deterministic (and convenient) output, first build an ordered + -- set of names, then print it in order. + + GNATcov_Traces.Clear; + GNATCOLL.Traces.For_Each_Handle (Add_Trace'Access); + for Name of GNATcov_Traces loop + Put_Line (+Name); + end loop; + end Print_List; + +end Logging; diff --git a/tools/gnatcov/logging.ads b/tools/gnatcov/logging.ads new file mode 100644 index 000000000..83e334592 --- /dev/null +++ b/tools/gnatcov/logging.ads @@ -0,0 +1,50 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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 GNATCOLL.Traces; + +with Strings; use Strings; + +package Logging is + + subtype GNATCOLL_Trace is GNATCOLL.Traces.Logger; + -- Convenience subtype so that trace creation requires "with Switches;" + -- only instead of also "with GNATCOLL.Traces;". + + GNATCOLL_Trace_Prefix : constant String := "gnatcov."; + -- Prefix to use for all GNATCOLL traces defined in GNATcov + + function Create_Trace (Unit_Name : String) return GNATCOLL_Trace; + -- Wrapper around GNATCOLL.Traces.Create to create GNATcov-specific traces + -- (with GNATCOLL_Trace_Prefix and standard settings). + + procedure Initialize (Verbose : Boolean; To_Enable : String_Vectors.Vector); + -- Initialize GNATCOLL traces from the ".gnatdebug" config file, if any. + -- + -- Then, if Verbose is True, make all GNATcov traces active. Otherwise, + -- enable GNATcov traces whose name is included in To_Enable. + + procedure Get_Configuration + (Verbose : out Boolean; + To_Enable : out String_Vectors.Vector); + -- Get the arguments that were passed to Initialize + + procedure Print_List; + -- Print the list of GNATcov traces on the standard output + +end Logging; diff --git a/tools/gnatcov/object_locations.adb b/tools/gnatcov/object_locations.adb index c0762ca8a..b99a0e572 100644 --- a/tools/gnatcov/object_locations.adb +++ b/tools/gnatcov/object_locations.adb @@ -171,7 +171,7 @@ package body Object_Locations is begin if Loc /= No_Proc_Location then Proc_Locs.Append (Loc); - if Switches.Verbose then + if Switches.Misc_Trace.Is_Active then Report (Msg => ("Location: " & Image (Loc) @@ -179,7 +179,7 @@ package body Object_Locations is Kind => Notice); end if; - elsif Switches.Verbose then + elsif Switches.Misc_Trace.Is_Active then Report (Msg => "Ignore location: " & Image (User_Loc), Kind => Notice); diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 3e832cb47..7e64fa506 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -22,7 +22,6 @@ with Ada.Containers.Vectors; with Ada.Directories; use Ada.Directories; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Tags; -with Ada.Text_IO; use Ada.Text_IO; with GNAT.OS_Lib; with GNAT.Regexp; @@ -688,11 +687,11 @@ package body Project is & "gnatls", GNAT_Version => Gnatls_Version, Errors => null); - if Verbose and then Gnatls_Version /= null then - Put_Line + if Gnatls_Version /= null then + Misc_Trace.Trace ("default paths set from GNATLS " & Gnatls_Version.all); - Free (Gnatls_Version); end if; + Free (Gnatls_Version); end; -- Set scenario variables diff --git a/tools/gnatcov/rundrv-handlers.adb b/tools/gnatcov/rundrv-handlers.adb index c9d708a06..950800209 100644 --- a/tools/gnatcov/rundrv-handlers.adb +++ b/tools/gnatcov/rundrv-handlers.adb @@ -106,7 +106,7 @@ package body Rundrv.Handlers is begin Native := True; Cmd := (Command => +Cmd_Name, others => <>); - if not Verbose then + if not Rundrv_Trace.Is_Active then Append_Arg (Cmd, "--quiet"); end if; Append_Arg (Cmd, "--tool=coverage"); @@ -146,7 +146,7 @@ package body Rundrv.Handlers is -- -quiet silences the warnings emitted by DynamoRIO on the assumption -- that it is invoked from an official release install tree. - if not Verbose then + if not Rundrv_Trace.Is_Active then Append_Arg (Cmd, "-quiet"); end if; Append_Arg (Cmd, "-no_follow_children"); diff --git a/tools/gnatcov/rundrv.ads b/tools/gnatcov/rundrv.ads index fabff7d71..320731888 100644 --- a/tools/gnatcov/rundrv.ads +++ b/tools/gnatcov/rundrv.ads @@ -19,9 +19,13 @@ with GNAT.Strings; use GNAT.Strings; with Inputs; +with Logging; package Rundrv is + Rundrv_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("RUNDRV"); + type SO_Set_Kind is (None, Some_SO, All_SO); type SO_Set_Type (Kind : SO_Set_Kind := Some_SO) is record case Kind is diff --git a/tools/gnatcov/sc_obligations-bdd.adb b/tools/gnatcov/sc_obligations-bdd.adb index 87c25c86f..a793d63e1 100644 --- a/tools/gnatcov/sc_obligations-bdd.adb +++ b/tools/gnatcov/sc_obligations-bdd.adb @@ -26,7 +26,6 @@ with Checkpoints; use Checkpoints; with Diagnostics; use Diagnostics; with Outputs; with Slocs; -with Switches; use Switches; package body SC_Obligations.BDD is @@ -356,7 +355,7 @@ package body SC_Obligations.BDD is Enumerate_Paths (BDD_Vector, BDD, Count_Paths); - if Verbose then + if SCOs_Trace.Is_Active then Dump_BDD (BDD_Vector, BDD); end if; end Completed; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 8da527dfe..d119f98bc 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -249,8 +249,8 @@ package body SC_Obligations is -- nonsensical. Fingerprint_Buffer : Unbounded_String; - -- In verbose mode, buffer to hold the bytes used to compute the - -- fingerprint. + -- When SCOs_Trace is active, buffer to hold the bytes used to compute + -- the fingerprint. end record; -- Information about a compilation unit to load, i.e. to create a CU_Info -- record and the associated information. @@ -1156,8 +1156,8 @@ package body SC_Obligations is SCO_Vector.Append (New_SCOD); Set_SCO_Id_Map (Relocs, Old_SCO_Id, SCO_Vector.Last_Index); - if Verbose then - Put_Line + if SCOs_Trace.Is_Active then + SCOs_Trace.Trace ("Loaded from checkpoint: " & Image (SCO_Vector.Last_Index) & " (was #" & Trim (Old_SCO_Id'Img, Side => Ada.Strings.Both) @@ -1341,11 +1341,10 @@ package body SC_Obligations is New_CU_Id := Comp_Unit (CP_CU.Main_Source); - if Verbose then - Put_Line ("Remapped CU: id " & New_CU_Id'Img - & ", main source" & CP_CU.Main_Source'Img - & " " & Get_Full_Name (CP_CU.Main_Source)); - end if; + SCOs_Trace.Trace + ("Remapped CU: id " & New_CU_Id'Img + & ", main source" & CP_CU.Main_Source'Img + & " " & Get_Full_Name (CP_CU.Main_Source, Or_Simple => True)); -- Case 1: CU not already present. Load all SCO information -- from checkpoint. @@ -1600,9 +1599,8 @@ package body SC_Obligations is SFI_Ignored (Relocs, CP_CU.Main_Source); begin if Origin_Ignored or else Main_Source_Ignored then - if Switches.Verbose then - Put_Line ("Ignoring CU from SID file: Id" & CP_CU_Id'Img); - end if; + SCOs_Trace.Trace + ("Ignoring CU from SID file: Id" & CP_CU_Id'Img); -- If we cannot load this CU *not* because its main source -- is ignored, but rather because the origin is ignored, @@ -2944,7 +2942,7 @@ package body SC_Obligations is is begin GNAT.SHA1.Update (Unit_Info.Fingerprint_Context, S); - if Verbose then + if SCOs_Trace.Is_Active then Append (Unit_Info.Fingerprint_Buffer, S); end if; end Append_For_Fingerprint; @@ -3054,13 +3052,14 @@ package body SC_Obligations is -- If requested, show the string used to compute fingerprint for each -- unit. - if Verbose then + if SCOs_Trace.Is_Active then for Unit_Info of Infos loop - Put_Line ("Computing fingerprint for " - & Unit_Info.File_Name_Ptr.all & " SCOs from:"); - Put_Line ("BEGIN ..."); - Put_Line (To_String (Unit_Info.Fingerprint_Buffer)); - Put_Line ("... END"); + SCOs_Trace.Trace + ("Computing fingerprint for " + & Unit_Info.File_Name_Ptr.all & " SCOs from:"); + SCOs_Trace.Trace ("BEGIN ..."); + SCOs_Trace.Trace (To_String (Unit_Info.Fingerprint_Buffer)); + SCOs_Trace.Trace ("... END"); end loop; end if; end Build_CU_Load_Info; @@ -3430,7 +3429,7 @@ package body SC_Obligations is SCO_Vector.Update_Element (State.Current_BDD.Decision, Update_Decision_BDD'Access); - if Verbose then + if SCOs_Trace.Is_Active then Dump_Decision (State.Current_Decision); end if; State.Current_Decision := No_SCO_Id; @@ -3644,17 +3643,13 @@ package body SC_Obligations is -- SCO containing First begin - if Verbose then - Put ("Processing: " & Image (SCO)); - if SCOD.Kind = Decision then - if SCOD.Last_Cond_Index > 0 then - Put (" (complex)"); - else - Put (" (simple)"); - end if; - end if; - New_Line; - end if; + SCOs_Trace.Trace + ("Processing: " & Image (SCO) + & (if SCOD.Kind = Decision + then (if SCOD.Last_Cond_Index > 0 + then " (complex)" + else " (simple)") + else "")); case SCOD.Kind is when Removed => @@ -4406,11 +4401,12 @@ package body SC_Obligations is -- In case of failure, be helpful and print the offending tree for -- the verbose mode. - if Verbose then - Put_Line + if Scope_Entities_Trace.Is_Active then + Scope_Entities_Trace.Trace ("The following tree of scopes breaks the nesting/ordering" & " invariant:"); - Put_Line (Ada.Exceptions.Exception_Message (Exc)); + Scope_Entities_Trace.Trace + (Ada.Exceptions.Exception_Message (Exc)); Dump (Tree, "| "); end if; return False; @@ -4433,8 +4429,8 @@ package body SC_Obligations is pragma Assert (SCOs_Nested_And_Ordered (Scope_Entities)); SE := Scope_Entities; - if Verbose then - Put_Line ("Setting scopes for " & Image (CU) & ":"); + if Scope_Entities_Trace.Is_Active then + Scope_Entities_Trace.Trace ("Setting scopes for " & Image (CU) & ":"); Dump (SE, Line_Prefix => "| "); end if; end Set_Scope_Entities; diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index eaa5d187f..710f40bdf 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -35,6 +35,7 @@ with Types; use Types; limited with Checkpoints; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with Logging; with Slocs; use Slocs; with Strings; use Strings; with Traces; use Traces; @@ -47,6 +48,12 @@ package SC_Obligations is pragma Suppress (Tampering_Check); + SCOs_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("SCOS"); + + Scope_Entities_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("SCOPE_ENTITIES"); + ------------------ -- Source files -- ------------------ diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index de89c7c35..e40902541 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -20,7 +20,6 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Directories; use Ada.Directories; with Ada.Environment_Variables; with Ada.Exceptions; use Ada.Exceptions; -with Ada.Text_IO; use Ada.Text_IO; with GNAT.OS_Lib; with GNAT.Regexp; @@ -442,7 +441,7 @@ package body Setup_RTS is Logs.Has_Error or else (Has_Ada and then not Prj.Has_Runtime_Project); begin - Logs.Output_Messages (Information => Verbose); + Logs.Output_Messages (Information => Setup_RTS_Trace.Is_Active); if Has_Error then Fatal_Error ("Could not load the coverage runtime project file"); end if; @@ -453,15 +452,12 @@ package body Setup_RTS is then To_Unbounded_String (String (Prj.Runtime (Main_Language))) else Null_Unbounded_String); - -- In verbose mode, show the actual names for the target and the runtime - -- that GPR2 uses. They can be slightly different from the names users - -- passed. + -- Show the actual names for the target and the runtime that GPR2 uses. + -- They can be slightly different from the names users passed. - if Verbose then - Put_Line - ("Actual target: " & String (Prj.Target (Canonical => True))); - Put_Line ("Actual RTS: " & To_String (Actual_RTS)); - end if; + Setup_RTS_Trace.Trace + ("Actual target: " & String (Prj.Target (Canonical => True))); + Setup_RTS_Trace.Trace ("Actual RTS: " & To_String (Actual_RTS)); -- The best heuristic we have to determine if the actual runtime is -- "full" is to look for an Ada source file that is typically found in @@ -560,9 +556,7 @@ package body Setup_RTS is Fatal_Error ("Cannot get library support for this configuration"); end; - if Verbose then - Put_Line ("Library support: " & Lib_Support'Image); - end if; + Setup_RTS_Trace.Trace ("Library support: " & Lib_Support'Image); end Load_Project_Parameters; --------------- @@ -573,8 +567,11 @@ package body Setup_RTS is Dummy : Boolean; Args : String_Vectors.Vector; begin - if Verbose then - Put_Line ("Trying to uninstall " & Project_Name & " from " & Prefix); + Setup_RTS_Trace.Trace + ("Trying to uninstall " & Project_Name & " from " & Prefix); + + if Quiet then + Args.Append (+"-q"); end if; Args.Append (+"--uninstall"); @@ -596,7 +593,7 @@ package body Setup_RTS is (Command => "gprinstall", Arguments => Args, Origin_Command_Name => "gprinstall", - Out_To_Null => not Verbose, + Out_To_Null => not Setup_RTS_Trace.Is_Active, Ignore_Error => True); end Uninstall; @@ -715,9 +712,8 @@ package body Setup_RTS is then Auto_RTS_Profile else RTS_Profile); - if Verbose then - Put_Line ("Actual RTS profile: " & Actual_RTS_Profile'Image); - end if; + Setup_RTS_Trace.Trace + ("Actual RTS profile: " & Actual_RTS_Profile'Image); -- Create the temporary directory to host the build of the -- instrumentation runtime and other temporary files. @@ -793,6 +789,10 @@ package body Setup_RTS is Install_Args.Append (+("--prefix=" & Prefix)); end if; + if Quiet then + Common_Args.Append (+"-q"); + end if; + -- Avoid installing several time the same set of sources Install_Args.Append @@ -888,8 +888,8 @@ package body Setup_RTS is Load_Project (Prj, Prj_Filename, Target, RTS, Config_File); if Prj.Log_Messages.Has_Error then - if Verbose then - Put_Line + if Setup_RTS_Trace.Is_Active then + Setup_RTS_Trace.Trace ("Could not load the coverage runtime project to get dump" & " options defaults: " & Runtime_Project); Prj.Log_Messages.Output_Messages; @@ -901,11 +901,9 @@ package body Setup_RTS is -- then look for the config file under it. Project_File := Create (+Prj.Root_Project.Path_Name.Value); - if Verbose then - Put_Line - ("Loaded the coverage runtime project at: " - & (+Project_File.Full_Name)); - end if; + Setup_RTS_Trace.Trace + ("Loaded the coverage runtime project at: " + & (+Project_File.Full_Name)); declare Prefix : constant Virtual_File := @@ -919,19 +917,19 @@ package body Setup_RTS is if Setup_Config_File.Is_Regular_File then Result := Load (+Project_File.Full_Name, Setup_Config_File); - elsif Verbose then - Put_Line ("Could not find the setup config file: " - & (+Setup_Config_File.Full_Name)); + elsif Setup_RTS_Trace.Is_Active then + Setup_RTS_Trace.Trace + ("Could not find the setup config file: " + & (+Setup_Config_File.Full_Name)); raise Load_Setup_Config_Error; end if; -- At that point, setup config file was loaded successfully. Otherwise, -- we will return through the below exception handler. - if Verbose then - Put_Line ("Successfully loaded the setup configuration file " - & (+Setup_Config_File.Full_Name) & "."); - end if; + Setup_RTS_Trace.Trace + ("Successfully loaded the setup configuration file " + & (+Setup_Config_File.Full_Name) & "."); return Result; exception @@ -958,9 +956,10 @@ package body Setup_RTS is end return; end if; - elsif Verbose then - Put_Line ("Parsing error while reading the setup config file:"); - Put_Line (Format_Parsing_Error (Parsed_JSON.Error)); + elsif Setup_RTS_Trace.Is_Active then + Setup_RTS_Trace.Trace + ("Parsing error while reading the setup config file:"); + Setup_RTS_Trace.Trace (Format_Parsing_Error (Parsed_JSON.Error)); end if; raise Load_Setup_Config_Error; @@ -1063,11 +1062,9 @@ package body Setup_RTS is exception when Exc : Format_Error => - if Verbose then - Put_Line - ("Setup config file decoding error: " - & Exception_Information (Exc)); - end if; + Setup_RTS_Trace.Trace + ("Setup config file decoding error: " + & Exception_Information (Exc)); raise Load_Setup_Config_Error; end Load; diff --git a/tools/gnatcov/setup_rts.ads b/tools/gnatcov/setup_rts.ads index c583afdf0..327b79542 100644 --- a/tools/gnatcov/setup_rts.ads +++ b/tools/gnatcov/setup_rts.ads @@ -20,11 +20,15 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Logging; with Strings; use Strings; with Switches; use Switches; package Setup_RTS is + Setup_RTS_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("SETUP_RTS"); + type Any_RTS_Profile is (Auto, Full, Embedded); -- See documentation for the --rts-profile option diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index f38a4dfb0..8f0d3dc32 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -26,9 +26,8 @@ with GNATCOLL.Mmap; use GNATCOLL.Mmap; with GNATCOLL.OS.FS; use GNATCOLL.OS.FS; with GNATCOLL.OS.Process_Types; -with Outputs; use Outputs; -with Paths; use Paths; -with Switches; use Switches; +with Outputs; use Outputs; +with Paths; use Paths; package body Subprocesses is @@ -102,9 +101,9 @@ package body Subprocesses is if not Ignore_Error and then not Success then Fatal_Error (Origin_Command_Name & " failed: aborting"); - elsif Verbose then + elsif Subprocesses_Trace.Is_Active then if Success then - Put_Line (Command & " finished"); + Subprocesses_Trace.Trace (Command & " finished"); else -- Do not use Error as this sets the exit status to Failure, but -- here we are precisely ignoring the fact that the subprocess @@ -245,45 +244,42 @@ package body Subprocesses is -- Instantiate environment variables Process_Types.Import (Env); - if Verbose and then not Environment.Is_Empty then - Put_Line ("env:"); + if not Environment.Is_Empty then + Subprocesses_Trace.Trace ("env:"); end if; for Env_Var in Environment.Iterate loop declare Name : constant String := +String_Maps.Key (Env_Var); Value : constant String := +String_Maps.Element (Env_Var); begin - if Verbose then - Put_Line (" " & Name & "='" & Value & "'"); - end if; + Subprocesses_Trace.Trace (" " & Name & "='" & Value & "'"); Process_Types.Set_Variable (Env, Name, Value); end; end loop; -- Instantiate the argument list - Process_Types.Add_Argument (Args, Program.all); - if Verbose then - Put_Line ("exec:"); - Put (" '" & Program.all & "'"); - end if; - Free (Program); + declare + use Ada.Strings.Unbounded; + Log : Unbounded_String; + begin + Process_Types.Add_Argument (Args, Program.all); + Append (Log, "exec:"); + Append (Log, " '" & Program.all & "'"); + Free (Program); - for A of Arguments loop - Process_Types.Add_Argument (Args, +A); - if Verbose then + for A of Arguments loop + Process_Types.Add_Argument (Args, +A); -- Quote the arguments to print empty strings and correctly -- escape quoted strings. - Put (" '"); - Put (+A); - Put ("'"); - end if; - end loop; - if Verbose then - New_Line; - end if; + Append (Log, " '"); + Append (Log, A); + Append (Log, "'"); + end loop; + Subprocesses_Trace.Trace (+Log); + end; -- Actually run the subprocess diff --git a/tools/gnatcov/subprocesses.ads b/tools/gnatcov/subprocesses.ads index 2bca5f15e..34216a4a3 100644 --- a/tools/gnatcov/subprocesses.ads +++ b/tools/gnatcov/subprocesses.ads @@ -27,11 +27,15 @@ with Ada.Strings.Unbounded; with GNATCOLL.OS.Process; use GNATCOLL.OS.Process; +with Logging; with Strings; use Strings; with Temp_Dirs; use Temp_Dirs; package Subprocesses is + Subprocesses_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("SUBPROCESSES"); + type Command_Type is record Command : Ada.Strings.Unbounded.Unbounded_String; -- Command (executable file) to run diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index b738ae08a..f644a0d17 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -21,9 +21,8 @@ with Ada.Command_Line; with Ada.Exceptions; with Ada.Strings.Fixed; -with Outputs; use Outputs; -with Project; use Project; -with Switches; use Switches; +with Outputs; use Outputs; +with Project; use Project; package body Switches is @@ -543,6 +542,13 @@ package body Switches is Args := Parse (Command_Line_Args); Load_Project_Arguments (From_Driver); + -- Enable logs according to the logs/verbosity options + + Logging.Initialize + (Verbose => Args.Bool_Args (Opt_Verbose), + To_Enable => Args.String_List_Args (Opt_Log)); + Quiet := Args.Bool_Args (Opt_Quiet); + -- Loading the project may have set a new target/RTS: update our -- internal state accordingly. diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index b2429cb6d..d4d24a29f 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -21,15 +21,20 @@ with Ada.Strings.Unbounded; with GNAT.Strings; use GNAT.Strings; -with Calendar_Utils; use Calendar_Utils; -with Command_Line; use Command_Line; -with Command_Line_Support; use Command_Line_Support; +with Calendar_Utils; use Calendar_Utils; +with Command_Line; use Command_Line; with Inputs; +with Logging; with SC_Obligations; -with Strings; use Strings; +with Strings; use Strings; package Switches is + Misc_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("MISC"); + -- Trace to log all messages for which creating a dedicated trace was not + -- worth it. + procedure Parse_Arguments (From_Driver : Boolean); -- Load arguments from command-line and from the project file (if any) into -- Args (see below). Print usage and exit if there is no argument. @@ -64,8 +69,12 @@ package Switches is -- Miscellaneous switches -- ---------------------------- - Verbose : Boolean := False; - -- Verbose informational output + Quiet : Boolean := False; + -- Whenther the "--quiet/-q" command line switch is active. + -- + -- When it is, do not display information about progress on the standard + -- output. Intended output, such as the "report" coverage output when no + -- "--output/-o" argument is passed is still emitted in this case. All_Decisions : Boolean := False; -- If True, perform decision coverage in stmt+decision mode even for @@ -80,10 +89,6 @@ package Switches is -- When a project file is specified using -P, also consider all imported -- projects for coverage. - Branch_Stats : Boolean := False; - -- If True, dump statistics about branch instructions after the static - -- analysis pass. - Excluded_SCOs : Boolean := False; -- If True, report SCOs whose coverage cannot be established due to -- absence of executable code. @@ -212,27 +217,6 @@ package Switches is -- All defined scenario variables, as provided through -X options on -- the command line. - ------------------------------ - -- Debugging switches (-d?) -- - ------------------------------ - - Debug_Switches : array (Valid_Debug_Type) of Boolean := (others => False); - -- For each debug switches, tell whether it's enabled - - -- Convenience shortcuts: - - Debug_Break_Long_Instructions : Boolean renames - Debug_Switches (Break_Long_Instructions); - - Debug_Full_History : Boolean renames - Debug_Switches (Full_History); - - Debug_Ignore_Exemptions : Boolean renames - Debug_Switches (Ignore_Exemptions); - - Debug_File_Table : Boolean renames - Debug_Switches (File_Table); - --------------------------------------- -- Instrumentation-related switches -- --------------------------------------- diff --git a/tools/gnatcov/temp_dirs.adb b/tools/gnatcov/temp_dirs.adb index f6700b42d..a93509bfc 100644 --- a/tools/gnatcov/temp_dirs.adb +++ b/tools/gnatcov/temp_dirs.adb @@ -17,8 +17,6 @@ ------------------------------------------------------------------------------ with Ada.Directories; use Ada.Directories; -with Ada.Text_IO; use Ada.Text_IO; - with Interfaces; use Interfaces; with GNAT.OS_Lib; use GNAT.OS_Lib; @@ -47,10 +45,7 @@ package body Temp_Dirs is then Unique_Name else Current_Directory / Unique_Name); begin - if Verbose then - Put_Line - ("Creating temporary directory: " & Name); - end if; + Misc_Trace.Trace ("Creating temporary directory: " & Name); -- In directory creation fails and we raise an exception, make sure to -- leave a null directory name so that finalization does not try to diff --git a/tools/gnatcov/traces.ads b/tools/gnatcov/traces.ads index ff30fadd4..b803b697e 100644 --- a/tools/gnatcov/traces.ads +++ b/tools/gnatcov/traces.ads @@ -24,9 +24,21 @@ with System; use System; with Arch; use Arch; with Elf_Common; use Elf_Common; +with Logging; package Traces is + Full_History_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("FULL_HISTORY"); + -- Note that enabling this trace will keep full historical traces for MC/DC + -- even for decisions that do not require it (decisions without multi-path + -- conditions). + + Branch_Stats_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("BRANCH_STATS"); + -- Trace to dump statistics about branch instructions after the static + -- analysis pass. + Big_Endian_Host : constant Boolean := Default_Bit_Order = High_Order_First; -- Host order is determined by System.Default_Bit_Order diff --git a/tools/gnatcov/traces_disa.adb b/tools/gnatcov/traces_disa.adb index b82c1b3de..ff4ec5ffb 100644 --- a/tools/gnatcov/traces_disa.adb +++ b/tools/gnatcov/traces_disa.adb @@ -25,7 +25,6 @@ with Disassemblers; use Disassemblers; with Execs_Dbase; with Hex_Images; use Hex_Images; with Highlighting; use Highlighting; -with Switches; with Traces_Files; package body Traces_Disa is @@ -86,7 +85,7 @@ package body Traces_Disa is Off : Pc_Type := Addr; I : Pc_Type; begin - if Switches.Debug_Break_Long_Instructions then + if Break_Long_Instructions_Trace.Is_Active then while -- Make sure we process each byte of the given instruction. Off <= Insn.Last diff --git a/tools/gnatcov/traces_disa.ads b/tools/gnatcov/traces_disa.ads index 47cfe6175..683883377 100644 --- a/tools/gnatcov/traces_disa.ads +++ b/tools/gnatcov/traces_disa.ads @@ -19,12 +19,18 @@ with Binary_Files; use Binary_Files; with Disa_Symbolize; use Disa_Symbolize; with Elf_Disassemblers; use Elf_Disassemblers; +with Logging; with Traces; use Traces; with Traces_Dbase; use Traces_Dbase; with Traces_Elf; use Traces_Elf; package Traces_Disa is + Break_Long_Instructions_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("BREAK_LONG_INSTRUCTIONS"); + -- Note that enabling this trace will break long instructions in + -- disassemblies, a la objdump. + function Get_Label (Sym : Symbolizer'Class; Info : Address_Info_Acc) return String; -- Return the symbol corresponding to Info, if any, or return an empty diff --git a/tools/gnatcov/traces_names.adb b/tools/gnatcov/traces_names.adb index 9a62881cc..fc7c947e9 100644 --- a/tools/gnatcov/traces_names.adb +++ b/tools/gnatcov/traces_names.adb @@ -226,8 +226,9 @@ package body Traces_Names is Tag := Element (Cur).Routine_Tag; end if; - if Verbose and then Tag /= No_SC_Tag then - Put_Line ("Routine tag" & Tag'Img & ": " & Key_To_Name (Key).all); + if Tag /= No_SC_Tag then + Misc_Trace.Trace + ("Routine tag" & Tag'Img & ": " & Key_To_Name (Key).all); end if; end Add_Routine; From 71584934b27db3a4308cf1e23d84a44a79a1d2b3 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 28 Nov 2023 11:12:39 +0000 Subject: [PATCH 0510/1483] Makefile: make "gnatcov instrument" honnor the PARALLEL_BUILD setting --- tools/gnatcov/Makefile | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index 6860289e2..e15bf3128 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -156,6 +156,10 @@ BIN_COMMON_BUILD_ARGS=\ -largs $(LD_FLAGS) \ -cargs:c++ $(CXXFLAGS) \ -gargs +INSTR_COMMON_ARGS=\ + -j$(PARALLEL_BUILD) \ + -P gnatcov.gpr \ + --c++-opts=$(CXXFLAGS) bin: # Unlike BINUTILS_BUILD_DIR for which we have a default fallback, @@ -177,19 +181,19 @@ ifdef INSTRUMENTED # use the version that was not instrumented as a main to compile # gnatcov32, running gnatcov32 will not dump execution traces. - gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov64 --c++-opts=$(CXXFLAGS) + gnatcov instrument $(INSTR_COMMON_ARGS) -XPART=gnatcov64 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 \ --src-subdirs=gnatcov-instr - gnatcov instrument -j0 -P gnatcov.gpr -XPART=gnatcov32 --c++-opts=$(CXXFLAGS) + gnatcov instrument $(INSTR_COMMON_ARGS) -XPART=gnatcov32 $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov32 \ --src-subdirs=gnatcov-instr - gnatcov instrument -j0 -P gnatcov.gpr -XPART=driver --c++-opts=$(CXXFLAGS) + gnatcov instrument $(INSTR_COMMON_ARGS) -XPART=driver $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver \ --src-subdirs=gnatcov-instr - gnatcov instrument -j0 -P gnatcov.gpr -XPART=compiler --c++-opts=$(CXXFLAGS) + gnatcov instrument $(INSTR_COMMON_ARGS) -XPART=compiler $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=compiler \ --src-subdirs=gnatcov-instr else From 44afbd9caea2ad1933cb250a2ff17a0228532577 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 28 Nov 2023 16:04:08 +0000 Subject: [PATCH 0511/1483] Makefile: rename PARALLEL_BUILD to PROCESSORS This is to harmonize with similar variables in other Makefiles at AdaCore. --- tools/gnatcov/Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index e15bf3128..2c5e911d2 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -124,7 +124,7 @@ endif ADAPTERS_LIST=$(DEFAULT_ADAPTERS) -PARALLEL_BUILD=0 +PROCESSORS=0 BUILD_MODE=dev # ================================================================ @@ -147,7 +147,7 @@ all: bin adapters # "instrument" support is needed. BIN_COMMON_BUILD_ARGS=\ - -Pgnatcov.gpr -p -j$(PARALLEL_BUILD) \ + -Pgnatcov.gpr -p -j$(PROCESSORS) \ -XBUILD_MODE=$(BUILD_MODE) \ -XBINUTILS_SRC_DIR="$(BINUTILS_SRC_DIR)" \ -XBINUTILS_BUILD_DIR="$(BINUTILS_BUILD_DIR)" \ @@ -157,7 +157,7 @@ BIN_COMMON_BUILD_ARGS=\ -cargs:c++ $(CXXFLAGS) \ -gargs INSTR_COMMON_ARGS=\ - -j$(PARALLEL_BUILD) \ + -j$(PROCESSORS) \ -P gnatcov.gpr \ --c++-opts=$(CXXFLAGS) @@ -222,7 +222,7 @@ adapters: $(ADAPTER_TARGETS) ####################### ppc_genopc: - $(GPRBUILD) -j$(PARALLEL_BUILD) -Pgnatcov $(EXTRA_ADAFLAGS) $@ + $(GPRBUILD) -j$(PROCESSORS) -Pgnatcov $(EXTRA_ADAFLAGS) $@ ppc_disopc.ads: ppc_genopc ppc_disopc.tmpl ./ppc_genopc > $@ From b059712357f67351fa7f52ddb2956af0802fa6c9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 29 Nov 2023 12:29:06 +0000 Subject: [PATCH 0512/1483] Accept comma-separated log names in the internal --log option In other words, interpret for instance "--log L1,L2" the say way as "--log L1 --log L2". --- tools/gnatcov/command_line.ads | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 382461ab1..2ecc28800 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -1116,10 +1116,12 @@ package Command_Line is String_List_Infos : constant String_List_Option_Info_Array := (Opt_Log => Create - (Long_Name => "--log", - Pattern => "[GNATCOLL_TRACE_NAME]", - Help => "Enable logging for the given GNATCOLL trace name.", - Internal => True), + (Long_Name => "--log", + Pattern => "[GNATCOLL_TRACE_NAME]", + Help => + "Enable logging for the given GNATCOLL trace name.", + Internal => True, + Accepts_Comma_Separator => True), Opt_Projects => Create (Long_Name => "--projects", Pattern => "[GPR|@LISTFILE]", From 6dbf39e79a73950220374e3d7963a59b0d2ecbcc Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 28 Nov 2023 09:52:43 +0000 Subject: [PATCH 0513/1483] instrument-projects.adb: show progress for coverage instrumentation --- testsuite/SCOV/instr.py | 7 +- testsuite/SCOV/minicheck.py | 45 ++++++++----- testsuite/tests/129-instr-progress/c_unit.c | 10 +++ .../tests/129-instr-progress/cpp_unit.cpp | 11 ++++ testsuite/tests/129-instr-progress/main.adb | 9 +++ testsuite/tests/129-instr-progress/test.opt | 1 + testsuite/tests/129-instr-progress/test.py | 66 +++++++++++++++++++ .../tests/TC11-052-internal-error/test.py | 2 +- tools/gnatcov/instrument-projects.adb | 42 ++++++++++++ 9 files changed, 172 insertions(+), 21 deletions(-) create mode 100644 testsuite/tests/129-instr-progress/c_unit.c create mode 100644 testsuite/tests/129-instr-progress/cpp_unit.cpp create mode 100644 testsuite/tests/129-instr-progress/main.adb create mode 100644 testsuite/tests/129-instr-progress/test.opt create mode 100644 testsuite/tests/129-instr-progress/test.py diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 2fddc29f2..b8f01c583 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -38,8 +38,8 @@ def default_dump_channel(): return 'base64-stdout' -def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", - dump_channel="auto", gpr_obj_dir=None, +def xcov_instrument(gprsw, covlevel, quiet=True, extra_args=[], + dump_trigger="auto", dump_channel="auto", gpr_obj_dir=None, runtime_project=None, out=None, err=None, tolerate_messages=None, register_failure=True, auto_config_args=True, auto_target_args=True, @@ -50,6 +50,7 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", :param GPRswitches gprsw: Project file command line switches to honor. :param None|str covlevel: Coverage level for the instrumentation (--level argument). Not passed if None. + :param bool quiet: Whether to pass the "--quiet" flag. :param list[str] extra_args: Extra arguments to append to the command line. :param None|str dump_trigger: If None, do not pass the --dump-trigger argument. If "auto", pass the result of default_dump_trigger(). @@ -97,6 +98,8 @@ def xcov_instrument(gprsw, covlevel, extra_args=[], dump_trigger="auto", mains = [main.strip(' "') for main in mains] args = ['instrument'] + covlevel_args + if quiet: + args.append("--quiet") if dump_trigger: if dump_trigger == "auto": diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index d7a1ae6b5..04a55bed2 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -26,16 +26,16 @@ COV_RE = re.compile(r'^ *(\d+) (.):.*$') -def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, - gpr_obj_dir=None, gpr_exe_dir=None, ignored_source_files=[], - separate_coverage=None, extra_args=[], extra_run_args=None, - extra_instr_args=None, extra_gprbuild_args=[], - extra_gprbuild_cargs=[], extra_gprbuild_largs=[], - absolute_paths=False, dump_trigger="auto", - dump_channel="auto", check_gprbuild_output=False, - trace_mode=None, runtime_project=None, - gprsw_for_coverage=None, scos_for_run=True, - register_failure=True, program_env=None, +def build_and_run(gprsw, covlevel, mains, extra_coverage_args, quiet=True, + scos=None, gpr_obj_dir=None, gpr_exe_dir=None, + ignored_source_files=[], separate_coverage=None, + extra_args=[], extra_run_args=None, extra_instr_args=None, + extra_gprbuild_args=[], extra_gprbuild_cargs=[], + extra_gprbuild_largs=[], absolute_paths=False, + dump_trigger="auto", dump_channel="auto", + check_gprbuild_output=False, trace_mode=None, + runtime_project=None, gprsw_for_coverage=None, + scos_for_run=True, register_failure=True, program_env=None, tolerate_instrument_messages=None, exec_args=None, auto_languages=True, manual_prj_name=None): """ @@ -56,6 +56,7 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, scos=None, "gnatcov coverage" command-line returned. This is just for convenience: one can pass an empty list here and manually append extra arguments to the result. + :param bool quiet: Whether to pass "--quiet" to "gnatcov. :param None|list[str] scos: Optional list of SCOs files (ALI or SID) must be passed to gnatcov. These files must have no extension (for instance: 'obj/foo' instead of 'obj/foo.ali'. If absent, we pass "-P" to "gnatcov @@ -170,6 +171,8 @@ def gprbuild_wrapper(root_project): for pattern in ignored_source_files]) if separate_coverage: cov_or_instr_args.extend(['-S', separate_coverage]) + if quiet: + cov_or_instr_args.append("--quiet") # Compute arguments to specify units of interest. if trace_mode == 'bin': @@ -213,14 +216,20 @@ def gprbuild_wrapper(root_project): # Instrument the project and build the result extra_instr_args = cov_or_instr_args + list(extra_instr_args or []) - xcov_instrument(gprsw, covlevel, extra_args=extra_instr_args, - gpr_obj_dir=gpr_obj_dir, dump_trigger=dump_trigger, - dump_channel=dump_channel, - runtime_project=runtime_project, - out='instrument.log', - register_failure=register_failure, - tolerate_messages=tolerate_instrument_messages, - auto_languages=auto_languages) + xcov_instrument( + gprsw, + covlevel, + quiet=False, + extra_args=extra_instr_args, + gpr_obj_dir=gpr_obj_dir, + dump_trigger=dump_trigger, + dump_channel=dump_channel, + runtime_project=runtime_project, + out='instrument.log', + register_failure=register_failure, + tolerate_messages=tolerate_instrument_messages, + auto_languages=auto_languages, + ) gprbuild_wrapper(gprsw.root_project) # Retrieve the dump_channel that "gnatcov instrument" actually used, diff --git a/testsuite/tests/129-instr-progress/c_unit.c b/testsuite/tests/129-instr-progress/c_unit.c new file mode 100644 index 000000000..c3737dc54 --- /dev/null +++ b/testsuite/tests/129-instr-progress/c_unit.c @@ -0,0 +1,10 @@ +#include + +extern void cpp_func (void); + +void +c_func (void) +{ + puts ("c:c_func"); + cpp_func (); +} diff --git a/testsuite/tests/129-instr-progress/cpp_unit.cpp b/testsuite/tests/129-instr-progress/cpp_unit.cpp new file mode 100644 index 000000000..bbe5360ff --- /dev/null +++ b/testsuite/tests/129-instr-progress/cpp_unit.cpp @@ -0,0 +1,11 @@ +#include + +extern "C" { + extern void cpp_func (void); +} + +void +cpp_func (void) +{ + std::cout << "cpp:cpp_func" << std::endl; +} diff --git a/testsuite/tests/129-instr-progress/main.adb b/testsuite/tests/129-instr-progress/main.adb new file mode 100644 index 000000000..d418c7650 --- /dev/null +++ b/testsuite/tests/129-instr-progress/main.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + procedure C_Func; + pragma Import (C, C_Func, "c_func"); +begin + Put_Line ("Ada:main"); + C_Func; +end Main; diff --git a/testsuite/tests/129-instr-progress/test.opt b/testsuite/tests/129-instr-progress/test.opt new file mode 100644 index 000000000..183279b61 --- /dev/null +++ b/testsuite/tests/129-instr-progress/test.opt @@ -0,0 +1 @@ +!C++ DEAD Testcase uses a Ada/C/C++ mixed project diff --git a/testsuite/tests/129-instr-progress/test.py b/testsuite/tests/129-instr-progress/test.py new file mode 100644 index 000000000..0b220960f --- /dev/null +++ b/testsuite/tests/129-instr-progress/test.py @@ -0,0 +1,66 @@ +""" +Check that "gnatcov instrument" correctly reports progress about the +instrumented units. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, lines_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Avoid "creating output path" info messages +os.mkdir("obj") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + langs=["Ada", "C", "C++"], + mains=["main.adb"], + srcdirs=[".."], + ) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + quiet=False, + trace_mode="src", +) + +# Sanity check: the insrument-build-coverage process completed with the +# expected results. +check_xcov_reports( + "*xcov", + { + "main.adb.xcov": {"+": {7, 8}}, + "c_unit.c.xcov": {"+": {8}}, + "cpp_unit.cpp.xcov": {"+": {10}}, + }, + cwd="xcov", +) + +# Units are not instrumented in a particular order: we only want to check that +# all of them are listed with the expected formatting. +output = lines_of("instrument.log") +thistest.fail_if_not_equal( + "First line of 'gnatcov instrument' output", + "".join(output[:1]), + "Coverage instrumentation", +) +thistest.fail_if_not_equal( + "'gnatcov instrument' output", + "\n".join([ + " [Ada] main", + " [C++] cpp_unit.cpp", + " [C] c_unit.c", + ]), + "\n".join(sorted(output[1:])), +) + +thistest.result() diff --git a/testsuite/tests/TC11-052-internal-error/test.py b/testsuite/tests/TC11-052-internal-error/test.py index 385d6abf2..125526d57 100644 --- a/testsuite/tests/TC11-052-internal-error/test.py +++ b/testsuite/tests/TC11-052-internal-error/test.py @@ -17,7 +17,7 @@ def check(args, trigger, info): out = f"{trigger}.log" env = dict(os.environ) env["GNATCOV_INTERNAL_ERROR_TRIGGER"] = trigger - p = xcov(args, out=out, env=env, register_failure=False) + p = xcov(args + ["-q"], out=out, env=env, register_failure=False) thistest.fail_if( p.status == 0, "gnatcov returned success exit code, error expected" diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index b53a40d03..bc5599e1f 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -28,6 +28,7 @@ with Ada.Strings; with Ada.Strings.Fixed; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Hash; +with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Deallocation; with GNAT.Exception_Actions; @@ -266,6 +267,10 @@ is -- Clean the instrumentation directories and print any relevant information -- regarding the instrumentation context. + procedure Show_Progress (Language : Some_Language; Unit_Name : String); + -- If quiet mode is not enabled, show instrumentation progress by printing + -- the language/unit name that are being instrumented. + ----------------------- -- Load_From_Project -- ----------------------- @@ -987,6 +992,37 @@ is Outputs.Print_Internal_Error (Exc); end Clean_And_Print; + ------------------- + -- Show_Progress -- + ------------------- + + procedure Show_Progress (Language : Some_Language; Unit_Name : String) is + begin + if Quiet then + return; + end if; + + declare + Language_Name : constant String := + "[" & Image (Language) & "]"; + Filename_Indentation : constant String := + (1 .. 16 - Language_Name'Length => ' '); + begin + Put (" "); + Put (Language_Name); + Put (Filename_Indentation); + + -- To keep progress logs readable, use source basenames for + -- file-based languages. + + if Language_Kind (Language) = File_Based_Language then + Put_Line (Ada.Directories.Simple_Name (Unit_Name)); + else + Put_Line (Unit_Name); + end if; + end; + end Show_Progress; + Mains_To_Instrument : array (Src_Supported_Language) of Main_To_Instrument_Vectors.Vector; -- For each supported language, list of mains to instrument. Note that @@ -1203,6 +1239,10 @@ begin Sources_Of_Interest_File.Close; end; + if not Quiet then + Put_Line ("Coverage instrumentation"); + end if; + -- Instrument every unit of interest asynchronously declare @@ -1255,6 +1295,8 @@ begin Unit_Args.Append (+Unit_Name); + Show_Progress (LU_Info.Language, Unit_Name); + -- According to the set parallelism level, instrument in -- the same process (thus reusing the libadalang context, which -- is a big gain of time), or spawn another instrumentation From e200232b9b2aa1ea116695a9616b1fe660cb7f81 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 28 Nov 2023 08:33:55 +0000 Subject: [PATCH 0514/1483] instrument-projects.adb: remove useless use of container cursor In a container iteration through a "for Cur in Container.Iterate" loop, the cursor is used only once, to get access to the container element. Switch to the "for Item of Container" loop instead to simplify the code (no need for a declare block anymore: less nesting involved). --- tools/gnatcov/instrument-projects.adb | 178 ++++++++++++-------------- 1 file changed, 85 insertions(+), 93 deletions(-) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index bc5599e1f..b9c08e910 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -853,106 +853,98 @@ is -- that belong to a non-root project. begin - for Source_C in Project_Sources.Iterate loop - declare - Source : constant File_Info := File_Info_Sets.Element (Source_C); - begin - if To_Language (Source.Language) = Language then - declare - use Prj_Has_Manual_Helper_Sets; - - Prj_Info : constant Project_Info_Access := - Get_Or_Create_Project_Info (IC, Source.Project); - Prj : Prj_Desc renames Prj_Info.Desc; - Is_Root_Prj : constant Boolean := - Prj.Prj_Name = Root_Project_Info.Project.Name; - Source_Name : constant String := - GNATCOLL.VFS."+" (Source.File.Full_Name); - Helper_Unit : Unbounded_String; - Contained_Indication : Boolean := False; - - begin - Instrumenter.Replace_Manual_Dump_Indication - (Contained_Indication, - Prj_Info.Desc, - Source); - - if Contained_Indication and then not Is_Root_Prj - then - -- A call to the dump buffers procedure is only able to - -- dump the buffers of the project it is in and its - -- subprojects, meaning coverage data for all projects - -- higher in the project tree will be missing. Record - -- what file this call was in to warn the user later. - - Non_Root_Src_Calls.Include (Source_Name); - end if; - - -- Only generate one manual dump helper unit per project. - -- At this point, if the project's object directory and the - -- instrumented sources directory do not exist there is no - -- need to emit the dump helper unit. There are no units of - -- interest or call to a manual dump procedure for this - -- project. + for Source of Project_Sources loop + if To_Language (Source.Language) = Language then + declare + use Prj_Has_Manual_Helper_Sets; + + Prj_Info : constant Project_Info_Access := + Get_Or_Create_Project_Info (IC, Source.Project); + Prj : Prj_Desc renames Prj_Info.Desc; + Is_Root_Prj : constant Boolean := + Prj.Prj_Name = Root_Project_Info.Project.Name; + Source_Name : constant String := + GNATCOLL.VFS."+" (Source.File.Full_Name); + Helper_Unit : Unbounded_String; + Contained_Indication : Boolean := False; + begin + Instrumenter.Replace_Manual_Dump_Indication + (Contained_Indication, + Prj_Info.Desc, + Source); - if Prj_Has_Manual_Helper.Find (Prj.Prj_Name) = No_Element - and then Dump_Helper_Output_Dir_Exists (Source, Prj) - then - Instrumenter.Emit_Dump_Helper_Unit_Manual - (Helper_Unit, Dump_Config, Prj); + if Contained_Indication and then not Is_Root_Prj then - declare - use Files_Table; - Instr_Units : Unit_Sets.Set; - Source_Files : GNATCOLL.VFS.File_Array_Access - := Source.Project.Source_Files (Recursive => True); - begin - for S of Source_Files.all loop - declare - use Unit_Maps; - Unit_C : constant Unit_Maps.Cursor := - Instrumented_Sources.Find - (+To_Compilation_Unit - (Project.Project.Info (S)).Unit_Name); - begin - if Unit_C /= Unit_Maps.No_Element then - declare - Unit : constant Library_Unit_Info := - Element (Unit_C); - Instr_Unit : constant Compilation_Unit := - Compilation_Unit' - (Unit.Language_Kind, - Unit.Unit_Name); - begin - if not Instr_Units.Contains (Instr_Unit) - then - Instr_Units.Insert (Instr_Unit); - end if; - end; - end if; - end; - end loop; + -- A call to the dump buffers procedure is only able to dump + -- the buffers of the project it is in and its subprojects, + -- meaning coverage data for all projects higher in the + -- project tree will be missing. Record what file this call + -- was in to warn the user later. - -- The creation of the root project's buffers list - -- unit is already taken care of by the regular - -- instrumentation process, so skip it. + Non_Root_Src_Calls.Include (Source_Name); + end if; - if not Is_Root_Prj then - Instrumenter.Emit_Buffers_List_Unit - (Instr_Units, Prj); - end if; + -- Only generate one manual dump helper unit per project. At + -- this point, if the project's object directory and the + -- instrumented sources directory do not exist there is no need + -- to emit the dump helper unit. There are no units of interest + -- or call to a manual dump procedure for this project. + + if Prj_Has_Manual_Helper.Find (Prj.Prj_Name) = No_Element + and then Dump_Helper_Output_Dir_Exists (Source, Prj) + then + Instrumenter.Emit_Dump_Helper_Unit_Manual + (Helper_Unit, Dump_Config, Prj); + + declare + use Files_Table; + Instr_Units : Unit_Sets.Set; + Source_Files : GNATCOLL.VFS.File_Array_Access := + Source.Project.Source_Files (Recursive => True); + begin + for S of Source_Files.all loop + declare + use Unit_Maps; + Unit_C : constant Unit_Maps.Cursor := + Instrumented_Sources.Find + (+To_Compilation_Unit + (Project.Project.Info (S)).Unit_Name); + begin + if Unit_C /= Unit_Maps.No_Element then + declare + Unit : constant Library_Unit_Info := + Element (Unit_C); + Instr_Unit : constant Compilation_Unit := + Compilation_Unit' + (Unit.Language_Kind, + Unit.Unit_Name); + begin + if not Instr_Units.Contains (Instr_Unit) then + Instr_Units.Insert (Instr_Unit); + end if; + end; + end if; + end; + end loop; + + -- The creation of the root project's buffers list unit + -- is already taken care of by the regular + -- instrumentation process, so skip it. + + if not Is_Root_Prj then + Instrumenter.Emit_Buffers_List_Unit (Instr_Units, Prj); + end if; - GNATCOLL.VFS.Unchecked_Free (Source_Files); - end; + GNATCOLL.VFS.Unchecked_Free (Source_Files); + end; - Prj_Has_Manual_Helper.Insert (Prj.Prj_Name); - end if; + Prj_Has_Manual_Helper.Insert (Prj.Prj_Name); + end if; - Manual_Dump_Inserted := - Manual_Dump_Inserted or else Contained_Indication; - end; - end if; - end; + Manual_Dump_Inserted := + Manual_Dump_Inserted or else Contained_Indication; + end; + end if; end loop; if not Non_Root_Src_Calls.Is_Empty then From c174f5786279513c07a6e7a60b21b9b57fa90697 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 28 Nov 2023 08:35:49 +0000 Subject: [PATCH 0515/1483] instrument-projects.adb: minor coding style fix --- tools/gnatcov/instrument-projects.adb | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index b9c08e910..90ae1f78a 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -948,6 +948,7 @@ is end loop; if not Non_Root_Src_Calls.Is_Empty then + -- For each manual dump call inserted in a file belonging to a -- non-root project, warn the user the coverage data it will produce -- will not cover the whole project tree. From ef912e74eb47ec961e39c6e404311349e4dcd918 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 28 Nov 2023 08:36:03 +0000 Subject: [PATCH 0516/1483] instrument-projects.adb: simplify warning message formatting code --- tools/gnatcov/instrument-projects.adb | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 90ae1f78a..541da47a3 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -17,7 +17,6 @@ ------------------------------------------------------------------------------ with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Characters.Latin_1; use Ada.Characters.Latin_1; with Ada.Containers.Hashed_Maps; with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Containers.Indefinite_Ordered_Sets; @@ -954,23 +953,22 @@ is -- will not cover the whole project tree. declare - All_File_Names : Unbounded_String := +""; + All_File_Names : Unbounded_String; begin for File_Name of Non_Root_Src_Calls loop - All_File_Names := - All_File_Names & (+File_Name) & Ada.Characters.Latin_1.LF; + Append (All_File_Names, File_Name); + Append (All_File_Names, ASCII.LF); end loop; - Outputs.Warn ("Manual dump trigger indications were found in" - & " subprojects in the following files:" - & Ada.Characters.Latin_1.LF - & (+All_File_Names) - & "The coverage report built from the source traces" - & " they will produce will show all code from" - & " projects higher in the project tree as not" - & " covered. To get a full coverage analysis," - & " consider placing the manual dump buffers" - & " indication in the root project."); + Outputs.Warn + ("Manual dump trigger indications were found in subprojects in" + & " the following files:" & ASCII.LF + & (+All_File_Names) + & "The coverage report built from the source traces they will" + & " produce will show all code from projects higher in the" + & " project tree as not covered. To get a full coverage" + & " analysis, consider placing the manual dump buffers" + & " indication in the root project."); end; end if; end Insert_Manual_Dump_Trigger; From 167e4bc419dbd12d2487833a4460b138847af5e8 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 28 Nov 2023 09:51:00 +0000 Subject: [PATCH 0517/1483] instrument-projects.adb: minor reformattings --- tools/gnatcov/instrument-projects.adb | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 541da47a3..f2cb89dac 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -1038,7 +1038,7 @@ is C_Language => C_Instrumenter'Access, CPP_Language => CPP_Instrumenter'Access); - -- Start of processing for Instrument_Units_Of_Interest +-- Start of processing for Instrument_Units_Of_Interest begin -- Set the instrumentation tag @@ -1203,6 +1203,7 @@ begin CPP_Instrumenter := Create_CPP_Instrumenter (IC.Tag); if Dump_Config.Trigger = Manual then + -- Replace manual dump indications for C-like languages for Lang in C_Family_Language loop @@ -1248,7 +1249,6 @@ begin Instrument_Source_Args.Append (Common_Switches (Cmd_Instrument_Source)); for Cur in Instrumented_Sources.Iterate loop - declare Unit_Args : String_Vectors.Vector := Instrument_Source_Args.Copy; @@ -1274,12 +1274,7 @@ begin -- Add the arguments that are specific to the compilation unit - Unit_Args.Append - (Compilation_Unit_Options - (IC, - Desc, - LU_Info)); - + Unit_Args.Append (Compilation_Unit_Options (IC, Desc, LU_Info)); Unit_Args.Append (+"--sid=" & Obj_SID); -- We instrument the body, spec and separates as a whole From ef2f8af79a4cd5c864c9f026e7535546800f8191 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 13 Nov 2023 17:24:32 +0100 Subject: [PATCH 0518/1483] Mark the --subprograms switch as experimental As we are still discussing some aspects of what the switch should do and want to preserve our ability to evolve the behavior if need be. --- doc/gnatcov/units_of_interest.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/doc/gnatcov/units_of_interest.rst b/doc/gnatcov/units_of_interest.rst index 57a830dc8..472f291b2 100644 --- a/doc/gnatcov/units_of_interest.rst +++ b/doc/gnatcov/units_of_interest.rst @@ -203,8 +203,9 @@ and then executing:: gnatcov --units=@units.list -Conveying *subprograms* of interest -*********************************** +Conveying *subprograms* of interest (experimental) +************************************************** +>>>>>>> 9544dc8f5 (Mark the --subprograms switch as experimental) |gcv| enables even finer grain control through the use of ``--subprograms`` switch, which restricts coverage analysis to the specified list of subprograms From e50613fb02ff65f14b72b72b21c67f98954e1abc Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 13 Nov 2023 17:28:12 +0100 Subject: [PATCH 0519/1483] gnatcov doc: improve the documentation for --subprograms Specify its behavior when it refers to subprograms declared in units that are not of interest. --- doc/gnatcov/units_of_interest.rst | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/doc/gnatcov/units_of_interest.rst b/doc/gnatcov/units_of_interest.rst index 472f291b2..a596ff89e 100644 --- a/doc/gnatcov/units_of_interest.rst +++ b/doc/gnatcov/units_of_interest.rst @@ -205,22 +205,27 @@ and then executing:: Conveying *subprograms* of interest (experimental) ************************************************** ->>>>>>> 9544dc8f5 (Mark the --subprograms switch as experimental) |gcv| enables even finer grain control through the use of ``--subprograms`` switch, which restricts coverage analysis to the specified list of subprograms of interest. -The ``--subprograms`` switch expects a ``:`` argument, -where ```` is the full path to the subprogram source, and -``line`` is the specification line for Ada subprograms, and the body line for -C/C++ functions. +The ``--subprograms`` switch expects a ``:`` argument, where +```` is a source file name path, absolute or relative to the current +directory, pointing to the subprogram source and ``line`` is the first line of +the subprogram specification in Ada, and the first line of the function +definition in C/C++. Every coverage obligation from non subprograms of interest is discarded and reported as *no code* in the various output formats, and the associated coverage data is ignored. This means that checkpoints will hold coverage data for subprograms of interest only. +The ``--subprograms`` switch acts only on subprograms within units of interest. +If a unit was ignored for coverage analysis through a project attribute (e.g. +``Excluded_Units``) or through a command line switch (e.g. ``--units``), the +designated subprogram will be ignored for coverage analysis as well. + .. _gpr_context: Other switches or attributes of importance From 0a38844cba9719ed84a37f860286ef1282563e43 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 29 Nov 2023 14:34:14 +0000 Subject: [PATCH 0520/1483] testsuite/README.md: update the obsolete gnatpython prerequisites --- testsuite/README.md | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/testsuite/README.md b/testsuite/README.md index ccb8fdce4..be4e0caa1 100644 --- a/testsuite/README.md +++ b/testsuite/README.md @@ -25,16 +25,8 @@ You need, on your `PATH`: * gprbuild >= 1.3.0 -* GNATpython and rlimit. If you don't have a binary package at hand, you may - install the necessary subset with: - - ```shell - git clone https://forge.open-do.org/anonscm/git/gnatpython/gnatpython.git - ``` - - Add the extracted directory to your `PYTHONPATH`, then compile rlimit and add - it to your `PATH`. Or run `./setup.py` install to install the GNATpython - package in your Python distribution. +* The [e3-core](https://github.com/AdaCore/e3-core/) and + [e3-testsuite](https://github.com/adacore/e3-testsuite/) Python packages. * The GNAT toolchain that you wish be used to compile the tests (recent enough wrt `-fpreserve-control-flow`). From 2458823217d05d0458b0e26c2152ed1cb571dc78 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 17 Nov 2023 08:40:36 +0000 Subject: [PATCH 0521/1483] Checkpoint_Load: stop using streaming attributes for non-trivial types Use streaming attributes only for atomic data types with specific size (Unsigned_8, Integer_32, ...). Create explicit checkpoint reading procedures for the rest (records, containers, scalars with implicit size, ...). --- tools/gnatcov/ali_files.adb | 64 ++- tools/gnatcov/ali_files.ads | 8 +- tools/gnatcov/checkpoints.adb | 626 +++++++++++++++++++++-- tools/gnatcov/checkpoints.ads | 186 ++++++- tools/gnatcov/coverage-source.adb | 103 +++- tools/gnatcov/files_table.adb | 28 +- tools/gnatcov/instrument-checkpoints.adb | 6 +- tools/gnatcov/instrument-checkpoints.ads | 2 - tools/gnatcov/instrument.adb | 29 ++ tools/gnatcov/instrument.ads | 35 ++ tools/gnatcov/mc_dc.adb | 13 + tools/gnatcov/mc_dc.ads | 10 + tools/gnatcov/sc_obligations-bdd.adb | 101 ++-- tools/gnatcov/sc_obligations-bdd.ads | 14 +- tools/gnatcov/sc_obligations.adb | 401 ++++++++++----- tools/gnatcov/strings.adb | 35 ++ tools/gnatcov/strings.ads | 12 + tools/gnatcov/subprocesses.adb | 13 + tools/gnatcov/subprocesses.ads | 6 + tools/gnatcov/traces_files_registry.adb | 14 +- 20 files changed, 1409 insertions(+), 297 deletions(-) diff --git a/tools/gnatcov/ali_files.adb b/tools/gnatcov/ali_files.adb index 8d9c223cd..5695f61ec 100644 --- a/tools/gnatcov/ali_files.adb +++ b/tools/gnatcov/ali_files.adb @@ -23,6 +23,7 @@ with Ada.Text_IO; use Ada.Text_IO; with GNAT.Regpat; use GNAT.Regpat; with SCOs; +with Checkpoints; use Checkpoints; with Diagnostics; use Diagnostics; with Files_Table; use Files_Table; with Get_SCOs; @@ -31,6 +32,10 @@ with Outputs; use Outputs; package body ALI_Files is + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out ALI_Annotation); + -- Read a ALI_Annotation from CLS + ----------------------------------------------- -- Regular expressions for ALI files parsing -- ----------------------------------------------- @@ -622,42 +627,57 @@ package body ALI_Files is return ALI_Index; end Load_ALI; + ----------- + -- Write -- + ----------- + + procedure Write (S : access Root_Stream_Type'Class; V : ALI_Annotation) is + begin + CU_Id'Write (S, V.CU); + ALI_Annotation_Kind'Write (S, V.Kind); + if V.Message /= null then + String'Output (S, V.Message.all); + else + String'Output (S, ""); + end if; + end Write; + ---------- -- Read -- ---------- procedure Read - (S : access Root_Stream_Type'Class; - V : out ALI_Annotation) - is + (CLS : in out Checkpoint_Load_State; Value : out ALI_Annotation) is begin - CU_Id'Read (S, V.CU); - ALI_Annotation_Kind'Read (S, V.Kind); + Value.CU := CLS.Read_CU; + Value.Kind := ALI_Annotation_Kind'Val (CLS.Read_U8); declare - Msg : constant String := String'Input (S); + Msg : constant String := CLS.Read_String; begin if Msg'Length > 0 then - V.Message := new String'(Msg); + Value.Message := new String'(Msg); end if; end; - V.Violation_Count := 0; - V.Undetermined_Cov_Count := 0; - end Read; - ----------- - -- Write -- - ----------- + Value.Violation_Count := 0; + Value.Undetermined_Cov_Count := 0; + end Read; - procedure Write (S : access Root_Stream_Type'Class; V : ALI_Annotation) is + procedure Read + (CLS : access Checkpoints.Checkpoint_Load_State; + Value : out ALI_Annotation_Maps.Map) + is + procedure Read_Map is new Checkpoints.Read_Map + (Key_Type => Source_Location, + Element_Type => ALI_Annotation, + Map_Type => ALI_Annotation_Maps.Map, + Clear => ALI_Annotation_Maps.Clear, + Insert => ALI_Annotation_Maps.Insert, + Read_Key => Read, + Read_Element => Read); begin - CU_Id'Write (S, V.CU); - ALI_Annotation_Kind'Write (S, V.Kind); - if V.Message /= null then - String'Output (S, V.Message.all); - else - String'Output (S, ""); - end if; - end Write; + Read_Map (CLS.all, Value); + end Read; end ALI_Files; diff --git a/tools/gnatcov/ali_files.ads b/tools/gnatcov/ali_files.ads index 0bc0d5829..872e5e087 100644 --- a/tools/gnatcov/ali_files.ads +++ b/tools/gnatcov/ali_files.ads @@ -24,6 +24,7 @@ with Ada.Streams; use Ada.Streams; with GNAT.Regexp; with GNAT.Strings; use GNAT.Strings; +limited with Checkpoints; with SC_Obligations; use SC_Obligations; with Slocs; use Slocs; with Types; use Types; @@ -67,9 +68,7 @@ package ALI_Files is -- This is relevant only for source trace based coverage analysis. end record; - procedure Read (S : access Root_Stream_Type'Class; V : out ALI_Annotation); procedure Write (S : access Root_Stream_Type'Class; V : ALI_Annotation); - for ALI_Annotation'Read use Read; for ALI_Annotation'Write use Write; package ALI_Annotation_Maps is @@ -77,6 +76,11 @@ package ALI_Files is (Key_Type => Source_Location, Element_Type => ALI_Annotation); + procedure Read + (CLS : access Checkpoints.Checkpoint_Load_State; + Value : out ALI_Annotation_Maps.Map); + -- Read a ALI_Annotation_Maps.Map from CLS + ALI_Annotations : ALI_Annotation_Maps.Map; function Load_ALI diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index 394ec36e0..a979d5733 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -19,13 +19,16 @@ with Ada.Streams.Stream_IO; use Ada.Streams.Stream_IO; with Ada.Unchecked_Deallocation; +pragma Warnings (Off, "* is an internal GNAT unit"); +with Ada.Strings.Unbounded.Aux; use Ada.Strings.Unbounded.Aux; +pragma Warnings (On, "* is an internal GNAT unit"); + with Interfaces; use Interfaces; with Coverage.Source; with Coverage_Options; use Coverage_Options; with Instrument.Checkpoints; with Outputs; use Outputs; -with Traces; use Traces; with Traces_Files; use Traces_Files; with Traces_Files_Registry; @@ -548,11 +551,9 @@ package body Checkpoints is Purpose : Checkpoint_Purpose; Ignored_Source_Files : access GNAT.Regexp.Regexp) is - Dummy : constant Context_Handle := + Dummy : constant Context_Handle := Create_Context ("Loading " & Filename); - SF : Ada.Streams.Stream_IO.File_Type; - CP_Header : Checkpoint_Header; - Levels : Levels_Type; + SF : Ada.Streams.Stream_IO.File_Type; begin Open (SF, In_File, Filename); @@ -568,49 +569,69 @@ package body Checkpoints is Filename => To_Unbounded_String (Filename), Purpose => Purpose, others => <>); + + Magic : String (Checkpoint_Magic'Range); begin - Checkpoint_Header'Read (CLS.Stream, CP_Header); - if CP_Header.Magic /= Checkpoint_Magic then + CLS.Read (Magic); + if Magic /= Checkpoint_Magic then Fatal_Error ("invalid checkpoint file " & Filename); + end if; - elsif CP_Header.Version /= Checkpoint_Version'Last then - Fatal_Error - ("invalid checkpoint version" & CP_Header.Version'Img); + CLS.Version := CLS.Read_U32; + if CLS.Version /= Checkpoint_Version'Last then + Fatal_Error ("invalid checkpoint version" & CLS.Version'Img); + end if; - else - CLS.Version := CP_Header.Version; + -- Check that we are loading the kind of checkpoint we are + -- expecting (Purpose). - -- Check that we are loading the kind of checkpoint we are - -- expecting (Purpose). + declare + CP_Purpose : constant Checkpoint_Purpose := + Checkpoint_Purpose'Val (CLS.Read_U8); + begin + if CP_Purpose /= Purpose then + Fatal_Error + (Filename & " is a " & Purpose_Name (CP_Purpose) + & " while a " & Purpose_Name (Purpose) + & " was expected"); + end if; + end; - declare - CP_Purpose : constant Checkpoint_Purpose := - Checkpoint_Purpose'Input (CLS.Stream); - begin - if CP_Purpose /= Purpose then - Fatal_Error - (Filename & " is a " & Purpose_Name (CP_Purpose) - & " while a " & Purpose_Name (Purpose) - & " was expected"); - end if; - end; + -- Check the kind of binary traces that were used to create this + -- checkpoint. - -- Check the kind of binary traces that were used to create this - -- checkpoint. + declare + Bits : constant Binary_Traces_Bits := + Binary_Traces_Bits'Val (CLS.Read_U8); + begin + if Bits not in Undetermined | Supported_Bits then + Fatal_Error + (Filename & " was created with " & Image (Bits) + & " whereas the selected target requires " + & Image (Supported_Bits)); + end if; + end; - declare - Bits : constant Binary_Traces_Bits := - Binary_Traces_Bits'Input (CLS.Stream); - begin - if Bits not in Undetermined | Supported_Bits then - Fatal_Error - (Filename & " was created with " & Image (Bits) - & " whereas the selected target requires " - & Image (Supported_Bits)); - end if; - end; + -- Check that the checkpoint to load covers all the coverage levels + -- that are selected for this run. + -- + -- See the note on checkpoint version compatibility for the tedious + -- reading code. - Levels_Type'Read (CLS.Stream, Levels); + declare + CP_Levels : U8_Array (1 .. 8); + Levels : Levels_Type; + begin + CLS.Read (CP_Levels); + Levels := + (Insn => Boolean'Val (CP_Levels (1)), + Branch => Boolean'Val (CP_Levels (2)), + Stmt => Boolean'Val (CP_Levels (3)), + Decision => Boolean'Val (CP_Levels (4)), + MCDC => Boolean'Val (CP_Levels (5)), + UC_MCDC => Boolean'Val (CP_Levels (6)), + ATC => Boolean'Val (CP_Levels (7)), + ATCC => Boolean'Val (CP_Levels (8))); declare Error_Msg : constant String := Coverage.Is_Load_Allowed (Filename, Levels); @@ -619,22 +640,18 @@ package body Checkpoints is Fatal_Error (Error_Msg); end if; end; + end; - declare - CP_Trace_Kind : Any_Accepted_Trace_Kind; - begin - Any_Accepted_Trace_Kind'Read (CLS.Stream, CP_Trace_Kind); - Update_Current_Trace_Kind (CP_Trace_Kind); - end; + Update_Current_Trace_Kind + (Any_Accepted_Trace_Kind'Val (CLS.Read_U8)); - Files_Table.Checkpoint_Load (CLS'Access, Ignored_Source_Files); - SC_Obligations.Checkpoint_Load (CLS'Access); - Instrument.Checkpoints.Checkpoint_Load (CLS'Access); - Coverage.Source.Checkpoint_Load (CLS'Access); - Traces_Files_Registry.Checkpoint_Load (CLS'Access); + Files_Table.Checkpoint_Load (CLS'Access, Ignored_Source_Files); + SC_Obligations.Checkpoint_Load (CLS'Access); + Instrument.Checkpoints.Checkpoint_Load (CLS'Access); + Coverage.Source.Checkpoint_Load (CLS'Access); + Traces_Files_Registry.Checkpoint_Load (CLS'Access); - Free (CLS.Relocations); - end if; + Free (CLS.Relocations); end; Close (SF); @@ -681,4 +698,509 @@ package body Checkpoints is Stream.Stream.Write (Item); end Write; + -- Note for the Read* procedures below: using stream attributes for + -- well-defined elementary data types (String, Unsigned_*) can be + -- considered stable enough that it will preserve backwards and platform + -- compatibility, except maybe for endianity. For now, gnatcov is supported + -- on little-endian platforms only, so we should be fine. + + ------------------- + -- Read_BDD_Node -- + ------------------- + + function Read_BDD_Node + (Self : in out Checkpoint_Load_State) return BDD_Node_Id is + begin + return BDD_Node_Id (Self.Read_I32); + end Read_BDD_Node; + + ----------------- + -- Read_Bit_Id -- + ----------------- + + function Read_Bit_Id + (Self : in out Checkpoint_Load_State) return Any_Bit_Id + is + begin + return Any_Bit_Id (Self.Read_I32); + end Read_Bit_Id; + + ------------------ + -- Read_Boolean -- + ------------------ + + function Read_Boolean (Self : in out Checkpoint_Load_State) return Boolean + is + begin + return Boolean'Val (Self.Read_U8); + end Read_Boolean; + + ------------- + -- Read_CU -- + ------------- + + function Read_CU (Self : in out Checkpoint_Load_State) return CU_Id is + begin + return CU_Id (Self.Read_I32); + end Read_CU; + + --------------------------- + -- Read_Compilation_Unit -- + --------------------------- + + function Read_Compilation_Unit + (Self : in out Checkpoint_Load_State) return Compilation_Unit + is + Language : constant Any_Language_Kind := Self.Read_Language_Kind; + begin + return (Language => Language, Unit_Name => Self.Read_Unbounded_String); + end Read_Compilation_Unit; + + -------------------- + -- Read_Condition -- + -------------------- + + function Read_Condition + (Self : in out Checkpoint_Load_State) return Any_Condition_Index is + begin + return Any_Condition_Index (Self.Read_I32); + end Read_Condition; + + ---------------------- + -- Read_Fingerprint -- + ---------------------- + + function Read_Fingerprint + (Self : in out Checkpoint_Load_State) + return SC_Obligations.Fingerprint_Type + is + Buffer : String (1 .. SC_Obligations.Fingerprint_Type'Length); + I : Positive := 1; + begin + Self.Read (Buffer); + return Result : SC_Obligations.Fingerprint_Type do + for Digit of Result loop + Digit := Character'Pos (Buffer (I)); + I := I + 1; + end loop; + end return; + end Read_Fingerprint; + + -------------- + -- Read_I32 -- + -------------- + + function Read_I32 + (Self : in out Checkpoint_Load_State) return Interfaces.Integer_32 is + begin + return Interfaces.Integer_32'Input (Self.Stream); + end Read_I32; + + ------------------ + -- Read_Integer -- + ------------------ + + function Read_Integer (Self : in out Checkpoint_Load_State) return Integer + is + begin + return Integer (Self.Read_I32); + end Read_Integer; + + --------------- + -- Read_Inst -- + --------------- + + function Read_Inst (Self : in out Checkpoint_Load_State) return Inst_Id is + begin + return Inst_Id (Self.Read_I32); + end Read_Inst; + + ------------------------ + -- Read_Language_Kind -- + ------------------------ + + function Read_Language_Kind + (Self : in out Checkpoint_Load_State) return Any_Language_Kind is + begin + return Any_Language_Kind'Val (Self.Read_U32); + end Read_Language_Kind; + + --------------------- + -- Read_Line_State -- + --------------------- + + function Read_Line_State + (Self : in out Checkpoint_Load_State) return Any_Line_State is + begin + return Any_Line_State'Val (Self.Read_U8); + end Read_Line_State; + + -------------------------------- + -- Read_Local_Source_Location -- + -------------------------------- + + function Read_Local_Source_Location + (Self : in out Checkpoint_Load_State) return Local_Source_Location + is + Line : constant Natural := Self.Read_Integer; + Column : constant Integer := Self.Read_Integer; + begin + return (Line, Column); + end Read_Local_Source_Location; + + -------------------------------------- + -- Read_Local_Source_Location_Range -- + -------------------------------------- + + function Read_Local_Source_Location_Range + (Self : in out Checkpoint_Load_State) return Local_Source_Location_Range + is + First : constant Local_Source_Location := + Self.Read_Local_Source_Location; + Last : constant Local_Source_Location := + Self.Read_Local_Source_Location; + begin + return (First, Last); + end Read_Local_Source_Location_Range; + + ------------- + -- Read_PC -- + ------------- + + function Read_PC (Self : in out Checkpoint_Load_State) return Pc_Type is + begin + case Pc_Type'Size is + when 32 => + return Pc_Type (Self.Read_U32); + when 64 => + return Pc_Type (Self.Read_U64); + when others => + raise Program_Error; + end case; + end Read_PC; + + -------------- + -- Read_SCO -- + -------------- + + function Read_SCO (Self : in out Checkpoint_Load_State) return SCO_Id is + begin + return SCO_Id (Self.Read_I32); + end Read_SCO; + + -------------- + -- Read_SFI -- + -------------- + + function Read_SFI + (Self : in out Checkpoint_Load_State) return Source_File_Index is + begin + return Source_File_Index (Self.Read_I32); + end Read_SFI; + + -------------------------- + -- Read_Source_Location -- + -------------------------- + + function Read_Source_Location + (Self : in out Checkpoint_Load_State) return Source_Location + is + begin + return Result : Source_Location do + Self.Read (Result); + end return; + end Read_Source_Location; + + -------------------------------- + -- Read_Source_Location_Range -- + -------------------------------- + + function Read_Source_Location_Range + (Self : in out Checkpoint_Load_State) return Source_Location_Range is + begin + return Result : Source_Location_Range do + Result.Source_File := Self.Read_SFI; + Result.L := Self.Read_Local_Source_Location_Range; + end return; + end Read_Source_Location_Range; + + ----------------- + -- Read_String -- + ----------------- + + function Read_String (Self : in out Checkpoint_Load_State) return String is + First : constant Positive := Self.Read_Integer; + Last : constant Natural := Self.Read_Integer; + begin + return Result : String (First .. Last) do + Self.Read (Result); + end return; + end Read_String; + + ------------------- + -- Read_Tristate -- + ------------------- + + function Read_Tristate + (Self : in out Checkpoint_Load_State) return Tristate is + begin + return Tristate'Val (Self.Read_U8); + end Read_Tristate; + + ------------- + -- Read_U8 -- + ------------- + + function Read_U8 + (Self : in out Checkpoint_Load_State) return Interfaces.Unsigned_8 is + begin + return Interfaces.Unsigned_8'Input (Self.Stream); + end Read_U8; + + -------------- + -- Read_U16 -- + -------------- + + function Read_U16 + (Self : in out Checkpoint_Load_State) return Interfaces.Unsigned_16 is + begin + return Interfaces.Unsigned_16'Input (Self.Stream); + end Read_U16; + + -------------- + -- Read_U32 -- + -------------- + + function Read_U32 + (Self : in out Checkpoint_Load_State) return Interfaces.Unsigned_32 is + begin + return Interfaces.Unsigned_32'Input (Self.Stream); + end Read_U32; + + -------------- + -- Read_U64 -- + -------------- + + function Read_U64 + (Self : in out Checkpoint_Load_State) return Interfaces.Unsigned_64 is + begin + return Interfaces.Unsigned_64'Input (Self.Stream); + end Read_U64; + + --------------------------- + -- Read_Unbounded_String -- + --------------------------- + + function Read_Unbounded_String + (Self : in out Checkpoint_Load_State) return Unbounded_String + is + begin + return Result : Unbounded_String do + Read (Self, Result); + end return; + end Read_Unbounded_String; + + -------------- + -- Read_Map -- + -------------- + + procedure Read_Map + (Self : in out Checkpoint_Load_State; Map : out Map_Type) + is + Count : constant Interfaces.Integer_32 := Self.Read_I32; + begin + Clear (Map); + for I in 1 .. Count loop + declare + Key : Key_Type; + Element : Element_Type; + begin + Read_Key (Self, Key); + Read_Element (Self, Element); + Insert (Map, Key, Element); + end; + end loop; + end Read_Map; + + -------------- + -- Read_Set -- + -------------- + + procedure Read_Set + (Self : in out Checkpoint_Load_State; Set : out Set_Type) + is + Count : constant Interfaces.Integer_32 := Self.Read_I32; + begin + Clear (Set); + for I in 1 .. Count loop + declare + Element : Element_Type; + begin + Read_Element (Self, Element); + Insert (Set, Element); + end; + end loop; + end Read_Set; + + --------------- + -- Read_Tree -- + --------------- + + procedure Read_Tree + (Self : in out Checkpoint_Load_State; Tree : out Multiway_Trees.Tree) + is + procedure Read_Children (Parent : Multiway_Trees.Cursor); + -- Read a list of child subtrees and append them to Parent + + procedure Read_Subtree (Parent : Multiway_Trees.Cursor); + -- Read a subtree and append it to Parent + + ------------------- + -- Read_Children -- + ------------------- + + procedure Read_Children (Parent : Multiway_Trees.Cursor) is + Count : constant Natural := Self.Read_Integer; + begin + for I in 1 .. Count loop + Read_Subtree (Parent); + end loop; + end Read_Children; + + ------------------ + -- Read_Subtree -- + ------------------ + + procedure Read_Subtree (Parent : Multiway_Trees.Cursor) is + Element : Element_Type; + begin + Read_Element (Self, Element); + Tree.Append_Child (Parent, Element); + Read_Children (Multiway_Trees.Last_Child (Parent)); + end Read_Subtree; + + Count : constant Natural := Self.Read_Integer; + + -- Start of processing for Read + + begin + Tree.Clear; + if Count > 0 then + Read_Children (Tree.Root); + end if; + end Read_Tree; + + ----------------- + -- Read_Vector -- + ----------------- + + procedure Read_Vector + (Self : in out Checkpoint_Load_State; Vector : out Vectors.Vector) + is + procedure Process (Element : in out Element_Type); + -- Call Read_Element on Element + + ------------- + -- Process -- + ------------- + + procedure Process (Element : in out Element_Type) is + begin + Read_Element (Self, Element); + end Process; + + Length : constant Interfaces.Integer_32 := Self.Read_I32; + + -- Start of processing for Read_Vector + + begin + Vector.Clear; + Vector.Set_Length (Ada.Containers.Count_Type (Length)); + for Cur in Vector.Iterate loop + Vector.Update_Element (Cur, Process'Access); + end loop; + end Read_Vector; + + ---------- + -- Read -- + ---------- + + procedure Read (Self : in out Checkpoint_Load_State; Value : out U8_Array) + is + begin + U8_Array'Read (Self.Stream, Value); + end Read; + + procedure Read + (Self : in out Checkpoint_Load_State; Value : out CU_Id) is + begin + Value := Self.Read_CU; + end Read; + + procedure Read + (Self : in out Checkpoint_Load_State; Value : out Pc_Type) is + begin + Value := Self.Read_PC; + end Read; + + procedure Read + (Self : in out Checkpoint_Load_State; Value : out SCO_Id) is + begin + Value := Self.Read_SCO; + end Read; + + procedure Read + (Self : in out Checkpoint_Load_State; Value : out Source_File_Index) is + begin + Value := Self.Read_SFI; + end Read; + + procedure Read + (Self : in out Checkpoint_Load_State; Value : out Source_Location) is + begin + Value.Source_File := Self.Read_SFI; + Value.L := Self.Read_Local_Source_Location; + end Read; + + procedure Read (Self : in out Checkpoint_Load_State; Value : out String) is + begin + String'Read (Self.Stream, Value); + end Read; + + procedure Read + (Self : in out Checkpoint_Load_State; Value : out Tristate) is + begin + Value := Self.Read_Tristate; + end Read; + + procedure Read + (Self : in out Checkpoint_Load_State; Value : out Unbounded_String) + is + procedure Set (S : out String); + -- Callback for Set_String: set S with bytes read from Self + + --------- + -- Set -- + --------- + + procedure Set (S : out String) is + begin + Self.Read (S); + end Set; + + First : constant Positive := Self.Read_Integer; + Last : constant Natural := Self.Read_Integer; + subtype Fixed_String is String (First .. Last); + Length : constant Natural := Fixed_String'Length; + + -- Start of processing for Read + + begin + if Length = 0 then + Value := Null_Unbounded_String; + else + Set_String (Value, Length, Set'Access); + end if; + end Read; + end Checkpoints; diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 48ff0fd66..52f86952d 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -19,6 +19,8 @@ -- This unit controls the generation and processing of coverage state -- checkpoint files for incremental coverage. +with Ada.Containers.Multiway_Trees; +with Ada.Containers.Vectors; with Ada.Streams; use Ada.Streams; with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Interfaces; @@ -27,8 +29,12 @@ with GNAT.Regexp; with Types; use Types; with Coverage; -with Files_Table; use Files_Table; -with SC_Obligations; use SC_Obligations; +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with Files_Table; use Files_Table; +with Slocs; use Slocs; +with SC_Obligations; use SC_Obligations; +with Traces; use Traces; +with Traces_Lines; use Traces_Lines; package Checkpoints is @@ -294,6 +300,182 @@ package Checkpoints is procedure Checkpoint_Load (Filename : String); -- Load a checkpoint file into internal data structures + -- Note on checkpoint version compatibility: our goal for (de)serialization + -- code is to avoid unintentional unintentional changes to the + -- checkpoint/SID file format. Consider for instance the following + -- hypothetical deserialization code: + -- + -- Levels : Coverage_Options.Levels_Type; + -- + -- Levels := + -- (for Level in Coverage_Options.Coverage_Level => + -- CLS.Read_Boolean); + -- + -- This reads N booleans from the checkpoints, N being the number of + -- enumeration values defined for Coverage_Levels. If a patch adds a new + -- enumeration value (creation of a new coverage level), then this code + -- will suddenly read one more boolean from the checkpoint, silently + -- breaking the checkpoint file format, whereas such changes mandate the + -- creation of a new checkpoint version number (see above). + -- + -- To avoid this kind of problem, we deserialize code like the above with + -- more "manual" code: + -- + -- CP_Levels : U8_Array (1 .. 8); + -- Levels : Levels_Type; + -- + -- CLS.Read (CP_Levels); + -- Levels := + -- (Insn => Boolean'Val (CP_Levels (1)), + -- Branch => Boolean'Val (CP_Levels (2)), + -- [...] + -- + -- The above will not compile when adding a new coverage level, since the + -- aggregate and Levels will not have the same length. + + ---------------------------------------------- + -- Helpers to implement checkpoints loading -- + ---------------------------------------------- + + -- All the Read_* functions below read bytes from the checkpoint and decode + -- specific data types. There is no overload (functions have different + -- names) to avoid ambiguities when writing for instance: + -- + -- My_Type'Val (CLS.Read_U8) + -- + -- Also define generic procedures to read and decode containers (maps, + -- multiway trees, sets, vectors). For these, we prefer procedures with OUT + -- parameters rather than functions to avoid unecessary copies for the + -- decoded values (functions are more convenient, so we keep them for small + -- data types). Yet, in order to be able to instantiate Read procedures for + -- containers, we also define several Read procedure that wrap the Read_* + -- functions. + + type U8_Array is array (Positive range <>) of Interfaces.Unsigned_8; + + function Read_BDD_Node + (Self : in out Checkpoint_Load_State) return BDD_Node_Id; + function Read_Bit_Id + (Self : in out Checkpoint_Load_State) return Any_Bit_Id; + function Read_Boolean (Self : in out Checkpoint_Load_State) return Boolean; + function Read_CU (Self : in out Checkpoint_Load_State) return CU_Id; + function Read_Compilation_Unit + (Self : in out Checkpoint_Load_State) return Compilation_Unit; + function Read_Condition + (Self : in out Checkpoint_Load_State) return Any_Condition_Index; + function Read_Fingerprint + (Self : in out Checkpoint_Load_State) + return SC_Obligations.Fingerprint_Type; + function Read_I32 + (Self : in out Checkpoint_Load_State) return Interfaces.Integer_32; + function Read_Inst (Self : in out Checkpoint_Load_State) return Inst_Id; + function Read_Integer (Self : in out Checkpoint_Load_State) return Integer; + function Read_Language_Kind + (Self : in out Checkpoint_Load_State) return Any_Language_Kind; + function Read_Line_State + (Self : in out Checkpoint_Load_State) return Any_Line_State; + function Read_Local_Source_Location + (Self : in out Checkpoint_Load_State) return Local_Source_Location; + function Read_Local_Source_Location_Range + (Self : in out Checkpoint_Load_State) return Local_Source_Location_Range; + function Read_PC (Self : in out Checkpoint_Load_State) return Pc_Type; + function Read_SCO (Self : in out Checkpoint_Load_State) return SCO_Id; + function Read_SFI + (Self : in out Checkpoint_Load_State) return Source_File_Index; + function Read_Source_Location + (Self : in out Checkpoint_Load_State) return Source_Location; + function Read_Source_Location_Range + (Self : in out Checkpoint_Load_State) return Source_Location_Range; + function Read_String (Self : in out Checkpoint_Load_State) return String; + function Read_Tristate + (Self : in out Checkpoint_Load_State) return Tristate; + function Read_U8 + (Self : in out Checkpoint_Load_State) return Interfaces.Unsigned_8; + function Read_U16 + (Self : in out Checkpoint_Load_State) return Interfaces.Unsigned_16; + function Read_U32 + (Self : in out Checkpoint_Load_State) return Interfaces.Unsigned_32; + function Read_U64 + (Self : in out Checkpoint_Load_State) return Interfaces.Unsigned_64; + function Read_Unbounded_String + (Self : in out Checkpoint_Load_State) return Unbounded_String; + + generic + type Key_Type is private; + type Element_Type is private; + type Map_Type is private; + + with procedure Clear (Self : in out Map_Type); + with procedure Insert + (Self : in out Map_Type; Key : Key_Type; Element : Element_Type); + + with procedure Read_Key + (Self : in out Checkpoint_Load_State; Key : out Key_Type); + with procedure Read_Element + (Self : in out Checkpoint_Load_State; Element : out Element_Type); + procedure Read_Map + (Self : in out Checkpoint_Load_State; Map : out Map_Type); + -- Generic implementation to read a map from a checkpoint. Since there are + -- two flavors for maps (ordered and hashed), do not take a instantiated + -- formal package, but rather the only two map primitives that we need: + -- Clear and Insert. + + generic + type Element_Type is private; + type Set_Type is private; + + with procedure Clear (Self : in out Set_Type); + with procedure Insert (Self : in out Set_Type; Element : Element_Type); + + with procedure Read_Element + (Self : in out Checkpoint_Load_State; Element : out Element_Type); + procedure Read_Set + (Self : in out Checkpoint_Load_State; Set : out Set_Type); + -- Generic implementation to read a set from a checkpoint. Since there are + -- two flavors for sets (ordered and hashed), do not take a instantiated + -- formal package, but rather the only two set primitives that we need: + -- Clear and Insert. + + generic + type Element_Type is private; + with function "=" (Left, Right : Element_Type) return Boolean is <>; + with package Multiway_Trees is new Ada.Containers.Multiway_Trees + (Element_Type, "="); + with procedure Read_Element + (Self : in out Checkpoint_Load_State; Element : out Element_Type); + procedure Read_Tree + (Self : in out Checkpoint_Load_State; Tree : out Multiway_Trees.Tree); + -- Generic implementation to read a multiway tree from a checkpoint + + generic + type Index_Type is range <>; + type Element_Type is private; + with function "=" (Left, Right : Element_Type) return Boolean is <>; + with package Vectors is new Ada.Containers.Vectors + (Index_Type, Element_Type, "="); + with procedure Read_Element + (Self : in out Checkpoint_Load_State; Element : out Element_Type); + procedure Read_Vector + (Self : in out Checkpoint_Load_State; Vector : out Vectors.Vector); + -- Generic implementation to read a vector tree from a checkpoint + + procedure Read (Self : in out Checkpoint_Load_State; Value : out U8_Array); + procedure Read + (Self : in out Checkpoint_Load_State; Value : out CU_Id); + procedure Read + (Self : in out Checkpoint_Load_State; Value : out Pc_Type); + procedure Read + (Self : in out Checkpoint_Load_State; Value : out SCO_Id); + procedure Read + (Self : in out Checkpoint_Load_State; Value : out Source_File_Index); + procedure Read + (Self : in out Checkpoint_Load_State; Value : out Source_Location); + procedure Read (Self : in out Checkpoint_Load_State; Value : out String); + procedure Read + (Self : in out Checkpoint_Load_State; Value : out Tristate); + procedure Read + (Self : in out Checkpoint_Load_State; Value : out Unbounded_String); + private type SFI_Map_Array is diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 0353192cc..488ffd403 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -69,6 +69,13 @@ package body Coverage.Source is 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); + 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); @@ -119,17 +126,12 @@ package body Coverage.Source is 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 Read_SCI - (S : access Root_Stream_Type'Class; - SCI : out RW_Source_Coverage_Info_Access); - -- Allocate a new SCI initialized from S 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'Read use Read_SCI; for RW_Source_Coverage_Info_Access'Write use Write_SCI; procedure Free is @@ -145,6 +147,24 @@ package body Coverage.Source is 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 Read is new Read_Vector + (Index_Type => Natural, + Element_Type => RW_Source_Coverage_Info_Access, + Vectors => SCI_Vectors, + Read_Element => Read); + + 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); + SCI_Vector : SCI_Vector_Vectors.Vector; Default_SCIs : array (SCO_Kind) of Source_Coverage_Info_Access; @@ -486,7 +506,7 @@ package body Coverage.Source is -- tag provider is the default (i.e. no coverage separation), or same -- as checkpoint. - CP_Tag_Provider := To_Unbounded_String (String'Input (CLS)); + CP_Tag_Provider := CLS.Read_Unbounded_String; if Tag_Provider.all not in Default_Tag_Provider_Type and then Tag_Provider_Name /= To_String (CP_Tag_Provider) then @@ -504,7 +524,7 @@ package body Coverage.Source is -- Even if we cannot merge coverage information, we must read it in -- order to be able to decode the rest of the checkpoint. - SCI_Vector_Vectors.Vector'Read (CLS, CP_SCI_Vector); + Read (CLS.all, CP_SCI_Vector); if not Do_Merge then return; @@ -547,19 +567,18 @@ package body Coverage.Source is -- units of interest. if CLS.Purpose = Consolidation then - declare - Invalidated : constant Boolean := Boolean'Input (CLS); + Invalidated : constant Boolean := CLS.Read_Boolean; Dummy : US.Unbounded_String; begin if Invalidated then Invalidate_Unit_List (US.To_String (CLS.Filename) - & " does not contain the list of units (produced with --scos" - & " or --sid)"); + & " does not contain the list of units (produced with" + & " --scos or --sid)"); else - for I in 1 .. Ada.Containers.Count_Type'Input (CLS) loop - Unit_List.Include (Compilation_Unit'Input (CLS)); + for I in 1 .. CLS.Read_Integer loop + Unit_List.Include (CLS.Read_Compilation_Unit); end loop; end if; end; @@ -2395,23 +2414,59 @@ package body Coverage.Source is Update_SCI (SCO, Tag, Merge_SCI'Access); end Merge_Checkpoint_SCI; - -------------- - -- Read_SCI -- - -------------- + ---------- + -- Read -- + ---------- - procedure Read_SCI - (S : access Root_Stream_Type'Class; - SCI : out RW_Source_Coverage_Info_Access) + procedure Read + (CLS : in out Checkpoint_Load_State; + Value : out RW_Source_Coverage_Info_Access) is - CP_SCI : constant Source_Coverage_Info := - Source_Coverage_Info'Input (S); + CP_SCI : Source_Coverage_Info (SCO_Kind'Val (CLS.Read_U8)); begin + CP_SCI.Tag := SC_Tag (CLS.Read_I32); + + declare + States : array (1 .. 8) of Line_State; + begin + for I in States'Range loop + States (I) := CLS.Read_Line_State; + end loop; + CP_SCI.State (Insn) := States (1); + CP_SCI.State (Branch) := States (2); + CP_SCI.State (Stmt) := States (3); + CP_SCI.State (Decision) := States (4); + CP_SCI.State (MCDC) := States (5); + CP_SCI.State (UC_MCDC) := States (6); + CP_SCI.State (ATC) := States (7); + CP_SCI.State (ATCC) := States (8); + end; + + case CP_SCI.Kind is + when Statement => + CP_SCI.Basic_Block_Has_Code := CLS.Read_Boolean; + CP_SCI.Executed := CLS.Read_Boolean; + CP_SCI.Line_Executed := CLS.Read_Boolean; + + when Decision => + CP_SCI.Outcome_Taken (False) := CLS.Read_Boolean; + CP_SCI.Outcome_Taken (True) := CLS.Read_Boolean; + + CP_SCI.Known_Outcome_Taken (False) := CLS.Read_Boolean; + CP_SCI.Known_Outcome_Taken (True) := CLS.Read_Boolean; + + Read (CLS, CP_SCI.Evaluations); + + when others => + null; + end case; + if CP_SCI = Default_SCIs (CP_SCI.Kind).all then - SCI := null; + Value := null; else - SCI := new Source_Coverage_Info'(CP_SCI); + Value := new Source_Coverage_Info'(CP_SCI); end if; - end Read_SCI; + end Read; ------------------------ -- Report_If_Excluded -- diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index ab508cf78..4a1877777 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -1956,13 +1956,12 @@ package body Files_Table is is pragma Assert (CLS.Purpose = Instrumentation or else Ignored_Source_Files = null); - S : access Ada.Streams.Root_Stream_Type'Class renames CLS.Stream; Relocs : Checkpoint_Relocations renames CLS.Relocations; -- 1) Read header - CP_First_SFI : constant Source_File_Index := Source_File_Index'Input (S); - CP_Last_SFI : constant Source_File_Index := Source_File_Index'Input (S); + CP_First_SFI : constant Source_File_Index := CLS.Read_SFI; + CP_Last_SFI : constant Source_File_Index := CLS.Read_SFI; CP_SFI : Source_File_Index; -- 2) Read file table entries @@ -1999,14 +1998,15 @@ package body Files_Table is -- Pass 1: load all file entries from checkpoint loop - Source_File_Index'Read (S, CP_SFI); + CP_SFI := CLS.Read_SFI; exit when CP_SFI = No_Source_File; declare FE : File_Entry renames CP_Entries (CP_SFI); - Name : constant String := String'Input (S); - Kind : constant File_Kind := File_Kind'Input (S); - Indexed_Simple_Name : constant Boolean := Boolean'Input (S); + Name : constant String := CLS.Read_String; + Kind : constant File_Kind := + File_Kind'Val (CLS.Read_U8); + Indexed_Simple_Name : constant Boolean := CLS.Read_Boolean; -- Do not call Ada.Directories.Simple_Name on artificial file -- names: such names are known to make Simple_Name raise a @@ -2027,23 +2027,21 @@ package body Files_Table is when Source_File => FE := (Kind => Source_File, others => <>); - -- Dumping ignored source files requires information that is - -- not available before checkpoint version 13. - FE.Ignore_Status := Unknown; FE.Unit := (Known => False); - FE.Ignore_Status := Any_Ignore_Status'Input (S); + FE.Ignore_Status := Any_Ignore_Status'Val (CLS.Read_U8); declare - Unit_Known : constant Boolean := Boolean'Input (S); + Unit_Known : constant Boolean := CLS.Read_Boolean; begin if Unit_Known then - FE.Unit := (Known => True, - Name => Compilation_Unit'Input (S)); + FE.Unit := + (Known => True, + Name => CLS.Read_Compilation_Unit); end if; end; when Library_File => FE := (Kind => Library_File, others => <>); - FE.Main_Source := Source_File_Index'Input (S); + FE.Main_Source := CLS.Read_SFI; pragma Assert (FE.Main_Source /= No_Source_File); end case; FE.Name := new String'(Name); diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index 17bce2971..877f421a9 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -55,7 +55,7 @@ package body Instrument.Checkpoints is use Instrumented_Unit_To_CU_Maps; CP_IU_Map : Map; begin - Map'Read (CLS.Stream, CP_IU_Map); + Read (CLS.all, CP_IU_Map); for Cur in CP_IU_Map.Iterate loop declare @@ -99,7 +99,7 @@ package body Instrument.Checkpoints is CP_PP_Cmds : SFI_To_PP_Cmd_Maps.Map; CP_SFI : Source_File_Index; begin - SFI_To_PP_Cmd_Maps.Map'Read (CLS.Stream, CP_PP_Cmds); + Read (CLS.all, CP_PP_Cmds); for CP_Cur in CP_PP_Cmds.Iterate loop @@ -121,7 +121,7 @@ package body Instrument.Checkpoints is PP_Cmds.Insert (SFI, CP_PP_Cmds.Reference (CP_Cur)); -- Otherwise, warn if the already known command and the - -- loaded one are different. + -- loaded one are different. elsif CP_PP_Cmds.Reference (CP_Cur) /= PP_Cmds.Reference (Cur) diff --git a/tools/gnatcov/instrument-checkpoints.ads b/tools/gnatcov/instrument-checkpoints.ads index 71fd2ef23..96a596364 100644 --- a/tools/gnatcov/instrument-checkpoints.ads +++ b/tools/gnatcov/instrument-checkpoints.ads @@ -16,8 +16,6 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Checkpoints; use Checkpoints; - package Instrument.Checkpoints is -- Note: the following procedures must be called after the SCO units diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 56572cdf7..188e04924 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -66,6 +66,35 @@ package body Instrument is return +Result; end To_Ada; + ---------- + -- Read -- + ---------- + + procedure Read + (CLS : in out Checkpoints.Checkpoint_Load_State; + Value : out Ada_Identifier) is + begin + Value := Ada_Identifier (CLS.Read_Unbounded_String); + end Read; + + procedure Read + (CLS : in out Checkpoints.Checkpoint_Load_State; + Value : out Compilation_Unit_Part) + is + CUP : Compilation_Unit_Part (CLS.Read_Language_Kind); + begin + case CUP.Language_Kind is + when Unit_Based_Language => + Read (CLS, CUP.Unit); + CUP.Part := Unit_Parts'Val (CLS.Read_U8); + + when File_Based_Language => + CUP.Filename := CLS.Read_Unbounded_String; + end case; + + Value := CUP; + end Read; + --------- -- "<" -- --------- diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 7bbc8372b..b540d6ebd 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -26,6 +26,7 @@ with GNATCOLL.Projects; use GNATCOLL.Projects; with Types; use Types; +with Checkpoints; use Checkpoints; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with SC_Obligations; use SC_Obligations; with Subprocesses; use Subprocesses; @@ -50,6 +51,11 @@ package Instrument is type Ada_Identifier is new Ada.Strings.Unbounded.Unbounded_String; -- Simple Ada identifier + procedure Read + (CLS : in out Checkpoints.Checkpoint_Load_State; + Value : out Ada_Identifier); + -- Read an Ada_Identifier from CLS + package Ada_Identifier_Vectors is new Ada.Containers.Vectors (Positive, Ada_Identifier); @@ -64,6 +70,12 @@ package Instrument is with Pre => not Name.Is_Empty; -- Turn the given qualified name into Ada syntax + procedure Read is new Read_Vector + (Index_Type => Positive, + Element_Type => Ada_Identifier, + Vectors => Ada_Identifier_Vectors, + Read_Element => Read); + type Compilation_Unit_Part (Language_Kind : Any_Language_Kind := Unit_Based_Language) is record @@ -83,6 +95,11 @@ package Instrument is end record; -- Unique identifier for an instrumented unit part + procedure Read + (CLS : in out Checkpoints.Checkpoint_Load_State; + Value : out Compilation_Unit_Part); + -- Read a Compilation_Unit_Part from CLS + Part_Tags : constant array (Unit_Parts) of Character := (Unit_Spec => 'S', Unit_Body => 'B', @@ -165,6 +182,15 @@ package Instrument is (Key_Type => Compilation_Unit_Part, Element_Type => CU_Id); + procedure Read is new Read_Map + (Key_Type => Compilation_Unit_Part, + Element_Type => CU_Id, + Map_Type => Instrumented_Unit_To_CU_Maps.Map, + Clear => Instrumented_Unit_To_CU_Maps.Clear, + Insert => Instrumented_Unit_To_CU_Maps.Insert, + Read_Key => Read, + Read_Element => Read); + Instrumented_Unit_CUs : Instrumented_Unit_To_CU_Maps.Map; -- Associate a CU id for all instrumented units. Updated each time we -- instrument a unit (or load a checkpoint) and used each time we read a @@ -175,6 +201,15 @@ package Instrument is (Key_Type => Source_File_Index, Element_Type => Command_Type); + procedure Read is new Read_Map + (Key_Type => Source_File_Index, + Element_Type => Command_Type, + Map_Type => SFI_To_PP_Cmd_Maps.Map, + Clear => SFI_To_PP_Cmd_Maps.Clear, + Insert => SFI_To_PP_Cmd_Maps.Insert, + Read_Key => Read, + Read_Element => Read); + PP_Cmds : SFI_To_PP_Cmd_Maps.Map; -- Save the preprocessing command for each unit that supports it diff --git a/tools/gnatcov/mc_dc.adb b/tools/gnatcov/mc_dc.adb index 468ec6e6d..667eaa618 100644 --- a/tools/gnatcov/mc_dc.adb +++ b/tools/gnatcov/mc_dc.adb @@ -215,4 +215,17 @@ package body MC_DC is return Result; end To_Vector; + ---------- + -- Read -- + ---------- + + procedure Read (CLS : in out Checkpoint_Load_State; Value : out Evaluation) + is + begin + Value.Decision := CLS.Read_SCO; + Read (CLS, Value.Values); + Value.Outcome := CLS.Read_Tristate; + Value.Next_Condition := CLS.Read_Condition; + end Read; + end MC_DC; diff --git a/tools/gnatcov/mc_dc.ads b/tools/gnatcov/mc_dc.ads index f84153e7c..5d3ae53d2 100644 --- a/tools/gnatcov/mc_dc.ads +++ b/tools/gnatcov/mc_dc.ads @@ -20,6 +20,7 @@ with Ada.Containers.Vectors; +with Checkpoints; use Checkpoints; with SC_Obligations; use SC_Obligations; package MC_DC is @@ -80,4 +81,13 @@ package MC_DC is function Image (EV : Condition_Evaluation_Vectors.Vector) return String; -- Image of EV, for reporting purposes + procedure Read is new Read_Vector + (Index_Type => Condition_Index, + Element_Type => Tristate, + Vectors => Condition_Evaluation_Vectors, + Read_Element => Read); + + procedure Read (CLS : in out Checkpoint_Load_State; Value : out Evaluation); + -- Read an Evaluation from CLS + end MC_DC; diff --git a/tools/gnatcov/sc_obligations-bdd.adb b/tools/gnatcov/sc_obligations-bdd.adb index a793d63e1..461307dcf 100644 --- a/tools/gnatcov/sc_obligations-bdd.adb +++ b/tools/gnatcov/sc_obligations-bdd.adb @@ -29,6 +29,16 @@ with Slocs; package body SC_Obligations.BDD is + procedure Read (CLS : in out Checkpoint_Load_State; Value : out BDD_Node); + -- Read a BDD_Node from CLS + + procedure Read is new Read_Vector + (Index_Type => Valid_BDD_Node_Id, + Element_Type => BDD_Node, + "=" => "=", + Vectors => BDD_Vectors, + Read_Element => Read); + package Arcs_Stacks is new Ada.Containers.Vectors (Index_Type => Natural, @@ -76,45 +86,6 @@ package body SC_Obligations.BDD is end if; end Allocate; - ---------- - -- Read -- - ---------- - - procedure Read (S : access Root_Stream_Type'Class; V : out BDD_Type) is - begin - SCO_Id'Read (S, V.Decision); - BDD_Node_Id'Read (S, V.Root_Condition); - BDD_Node_Id'Read (S, V.First_Node); - BDD_Node_Id'Read (S, V.Last_Node); - BDD_Node_Id'Read (S, V.First_Multipath_Condition); - Reachability'Read (S, V.Reachable_Outcomes); - Natural'Read (S, V.Path_Count); - end Read; - - procedure Read (S : access Root_Stream_Type'Class; V : out BDD_Node) is - New_BDDN : BDD_Node (BDD_Node_Kind'Input (S)); - pragma Warnings (Off, New_BDDN); - begin - -- Set discriminant - - V := New_BDDN; - - case V.Kind is - when Outcome => - Boolean'Read (S, V.Decision_Outcome); - - when Condition => - BDD_Node_Id'Read (S, V.Parent); - Boolean'Read (S, V.Parent_Value); - SCO_Id'Read (S, V.C_SCO); - Destinations'Read (S, V.Dests); - Natural'Read (S, V.Path_Offset); - - when Jump => - BDD_Node_Id'Read (S, V.Dest); - end case; - end Read; - ----------- -- Write -- ----------- @@ -156,6 +127,58 @@ package body SC_Obligations.BDD is end case; end Write; + ---------- + -- Read -- + ---------- + + procedure Read + (CLS : access Checkpoints.Checkpoint_Load_State; Value : out BDD_Type) is + begin + Value.Decision := CLS.Read_SCO; + Value.Root_Condition := CLS.Read_BDD_Node; + Value.First_Node := CLS.Read_BDD_Node; + Value.Last_Node := CLS.Read_BDD_Node; + Value.First_Multipath_Condition := CLS.Read_BDD_Node; + + Value.Reachable_Outcomes (False) := CLS.Read_Boolean; + Value.Reachable_Outcomes (True) := CLS.Read_Boolean; + + Value.Path_Count := CLS.Read_Integer; + end Read; + + procedure Read (CLS : in out Checkpoint_Load_State; Value : out BDD_Node) is + New_BDDN : BDD_Node (BDD_Node_Kind'Val (CLS.Read_U8)); + pragma Warnings (Off, New_BDDN); + + begin + -- Set discriminant + + Value := New_BDDN; + + case Value.Kind is + when Outcome => + Value.Decision_Outcome := CLS.Read_Boolean; + + when Condition => + Value.Parent := CLS.Read_BDD_Node; + Value.Parent_Value := CLS.Read_Boolean; + Value.C_SCO := CLS.Read_SCO; + Value.Dests (False) := CLS.Read_BDD_Node; + Value.Dests (True) := CLS.Read_BDD_Node; + Value.Path_Offset := CLS.Read_Integer; + + when Jump => + Value.Dest := CLS.Read_BDD_Node; + end case; + end Read; + + procedure Read + (CLS : access Checkpoints.Checkpoint_Load_State; + Vector : out BDD_Vectors.Vector) is + begin + Read (CLS.all, Vector); + end Read; + --------------------- -- Enumerate_Paths -- --------------------- diff --git a/tools/gnatcov/sc_obligations-bdd.ads b/tools/gnatcov/sc_obligations-bdd.ads index 9f397b8dc..3a902aabc 100644 --- a/tools/gnatcov/sc_obligations-bdd.ads +++ b/tools/gnatcov/sc_obligations-bdd.ads @@ -77,14 +77,11 @@ private package SC_Obligations.BDD is pragma Warnings (Off, "* is not referenced"); -- Work around compiler bug: bogus warning??? - procedure Read - (S : access Root_Stream_Type'Class; V : out BDD_Node); procedure Write (S : access Root_Stream_Type'Class; V : BDD_Node); pragma Warnings (On, "* is not referenced"); - for BDD_Node'Read use Read; for BDD_Node'Write use Write; package BDD_Vectors is @@ -92,6 +89,11 @@ private package SC_Obligations.BDD is (Index_Type => Valid_BDD_Node_Id, Element_Type => BDD_Node); + procedure Read + (CLS : access Checkpoints.Checkpoint_Load_State; + Vector : out BDD_Vectors.Vector); + -- Read a BDD_Vectors.Vector from CLS + type Reachability is array (Boolean) of Boolean; type BDD_Type is record @@ -117,15 +119,17 @@ private package SC_Obligations.BDD is end record; pragma Warnings (Off, "* is not referenced"); - procedure Read (S : access Root_Stream_Type'Class; V : out BDD_Type); procedure Write (S : access Root_Stream_Type'Class; V : BDD_Type); pragma Warnings (On, "* is not referenced"); - for BDD_Type'Read use Read; for BDD_Type'Write use Write; + procedure Read + (CLS : access Checkpoints.Checkpoint_Load_State; Value : out BDD_Type); + -- Read a BDD_Type from CLS + procedure Allocate (BDD_Vector : in out BDD_Vectors.Vector; BDD : in out BDD_Type; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index d119f98bc..74d6c5a8e 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -144,13 +144,9 @@ package body SC_Obligations is procedure Free (CU : in out CU_Info); pragma Warnings (Off, "* is not referenced"); - procedure Read - (S : access Root_Stream_Type'Class; - V : out CU_Info); procedure Write (S : access Root_Stream_Type'Class; V : CU_Info); pragma Warnings (On, "* is not referenced"); - for CU_Info'Read use Read; for CU_Info'Write use Write; function Has_SCOs (CUI : CU_Info) return Boolean is @@ -461,11 +457,9 @@ package body SC_Obligations is end record; pragma Warnings (Off, "* is not referenced"); - procedure Read (S : access Root_Stream_Type'Class; V : out SCO_Descriptor); procedure Write (S : access Root_Stream_Type'Class; V : SCO_Descriptor); pragma Warnings (On, "* is not referenced"); - for SCO_Descriptor'Read use Read; for SCO_Descriptor'Write use Write; Removed_SCO_Descriptor : constant SCO_Descriptor := (Kind => Removed); @@ -549,6 +543,82 @@ package body SC_Obligations is -- Helper routines for Checkpoint_Load -- ----------------------------------------- + procedure Read is new Read_Vector + (Index_Type => Pos, + Element_Type => Source_File_Index, + "=" => "=", + Vectors => SFI_Vectors, + Read_Element => Read); + + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out Expansion_Info); + -- Read an Expansion_Info from CLS + + procedure Read (CLS : in out Checkpoint_Load_State; Value : out PP_Info); + -- Read a PP_Info from CLS + + procedure Read is new Read_Map + (Key_Type => SCO_Id, + Element_Type => PP_Info, + Map_Type => SCO_PP_Info_Maps.Map, + Clear => SCO_PP_Info_Maps.Clear, + Insert => SCO_PP_Info_Maps.Insert, + Read_Key => Read, + Read_element => Read); + + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out Scope_Entity); + -- Read a Scope_Entity from CLS + + procedure Read is new Read_Tree + (Element_Type => Scope_Entity, + "=" => "=", + Multiway_Trees => Scope_Entities_Trees, + Read_Element => Read); + + procedure Read (CLS : in out Checkpoint_Load_State; Value : out CU_Info); + -- Read a CU_Info from CLS + + procedure Read is new Read_Vector + (Valid_CU_Id, CU_Info, "=", CU_Info_Vectors, Read); + -- Read a vector of CU_Info records from CLS and append them to CU_Vector + + procedure Read + (CLS : in out Checkpoint_Load_State; Element : out Inst_Info); + -- Read an Inst_Info from CLS + + procedure Read is new Read_Vector + (Index_Type => Valid_Inst_Id, + Element_Type => Inst_Info, + "=" => "=", + Vectors => Inst_Info_Vectors, + Read_Element => Read); + + procedure Read is new Read_Set + (Element_Type => Pc_Type, + Set_Type => PC_Sets.Set, + Clear => PC_Sets.Clear, + Insert => PC_Sets.Insert, + Read_Element => Read); + + procedure Read + (CLS : in out Checkpoint_Load_State; Element : out SCO_Descriptor); + -- Read a SCO_Descriptor from CLS + + procedure Read is new Read_Set + (Element_Type => SCO_Id, + Set_Type => SCO_Sets.Set, + Clear => SCO_Sets.Clear, + Insert => SCO_Sets.Insert, + Read_Element => Read); + + procedure Read is new Read_Vector + (Index_Type => Valid_SCO_Id, + Element_Type => SCO_Descriptor, + "=" => "=", + Vectors => SCO_Vectors, + Read_Element => Read); + procedure Checkpoint_Load_Merge_Unit (CLS : access Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; @@ -799,6 +869,200 @@ package body SC_Obligations is return CU_Vector.Reference (CU).Element.PP_Info_Map.Element (SCO); end Get_PP_Info; + ---------- + -- Read -- + ---------- + + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out Expansion_Info) + is + begin + Value.Macro_Name := CLS.Read_Unbounded_String; + Value.Sloc := CLS.Read_Source_Location; + end Read; + + procedure Read (CLS : in out Checkpoint_Load_State; Value : out PP_Info) is + Result : PP_Info (SCO_PP_Kind'Val (CLS.Read_U8)); + Count : Interfaces.Integer_32; + begin + Result.Actual_Source_Range := CLS.Read_Local_Source_Location_Range; + Result.PP_Source_Range := CLS.Read_Local_Source_Location_Range; + + Result.Expansion_Stack.Clear; + Count := CLS.Read_I32; + for I in 1 .. Count loop + declare + EI : Expansion_Info; + begin + Read (CLS, EI); + Result.Expansion_Stack.Append (EI); + end; + end loop; + + case Result.Kind is + when In_Expansion => + Read (CLS, Result.Definition_Loc); + + when others => + null; + end case; + + Value := Result; + end Read; + + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out Scope_Entity) + is + begin + Value.From := CLS.Read_SCO; + Value.To := CLS.Read_SCO; + + Value.Name := CLS.Read_Unbounded_String; + Value.Sloc := CLS.Read_Local_Source_Location; + + Value.Identifier.Decl_SFI := CLS.Read_SFI; + Value.Identifier.Decl_Line := CLS.Read_Integer; + end Read; + + procedure Read (CLS : in out Checkpoint_Load_State; Value : out CU_Info) + is + Element_Template : CU_Info (SCO_Provider'Val (CLS.Read_U8)); + begin + Value := Element_Template; + + -- Checkpoint version 1 data + + Value.Origin := CLS.Read_SFI; + Value.Main_Source := CLS.Read_SFI; + Value.First_SCO := CLS.Read_SCO; + Value.Last_SCO := CLS.Read_SCO; + Value.First_Instance := CLS.Read_Inst; + Value.Last_Instance := CLS.Read_Inst; + Read (CLS, Value.Deps); + Value.Has_Code := CLS.Read_Boolean; + Value.Fingerprint := CLS.Read_Fingerprint; + Read (CLS, Value.PP_Info_Map); + + case Value.Provider is + when Compiler => + null; + when Instrumenter => + + -- By default, use "no fingerprint" for buffer bit maps + -- fingerprints: by design checkpoints contains neither bit maps + -- nor their fingerprints (all source traces are processed before + -- loading checkpoints, and bit maps are needed only to interpret + -- source traces). + + Value.Bit_Maps_Fingerprint := No_Fingerprint; + + if Purpose_Of (CLS) = Instrumentation then + declare + Stmt_First, DC_First, MCDC_First : Bit_Id; + Stmt_Last, DC_Last, MCDC_Last : Any_Bit_Id; + begin + Stmt_First := CLS.Read_Bit_Id; + Stmt_Last := CLS.Read_Bit_Id; + Value.Bit_Maps.Statement_Bits := + new Statement_Bit_Map (Stmt_First .. Stmt_Last); + for SCO of Value.Bit_Maps.Statement_Bits.all loop + SCO := CLS.Read_SCO; + end loop; + + DC_First := CLS.Read_Bit_Id; + DC_Last := CLS.Read_Bit_Id; + Value.Bit_Maps.Decision_Bits := + new Decision_Bit_Map (DC_First .. DC_Last); + for Info of Value.Bit_Maps.Decision_Bits.all loop + Info.D_SCO := CLS.Read_SCO; + Info.Outcome := CLS.Read_Boolean; + end loop; + + MCDC_First := CLS.Read_Bit_Id; + MCDC_Last := CLS.Read_Bit_Id; + Value.Bit_Maps.MCDC_Bits := + new MCDC_Bit_Map (MCDC_First .. MCDC_Last); + for Info of Value.Bit_Maps.MCDC_Bits.all loop + Info.D_SCO := CLS.Read_SCO; + Info.Path_Index := CLS.Read_Integer; + end loop; + end; + Value.Bit_Maps_Fingerprint := CLS.Read_Fingerprint; + end if; + end case; + + Read (CLS, Value.Scope_Entities); + end Read; + + procedure Read (CLS : in out Checkpoint_Load_State; Element : out Inst_Info) + is + begin + Element.Sloc := CLS.Read_Source_Location; + Element.Enclosing_Instance := CLS.Read_Inst; + Element.Comp_Unit := CLS.Read_CU; + end Read; + + procedure Read + (CLS : in out Checkpoint_Load_State; Element : out SCO_Descriptor) + is + SCOD : SCO_Descriptor (SCO_Kind'Val (CLS.Read_U8)); + begin + if SCOD.Kind = Removed then + Element := Removed_SCO_Descriptor; + return; + end if; + + SCOD.Origin := CLS.Read_CU; + SCOD.Sloc_Range := CLS.Read_Source_Location_Range; + SCOD.Parent := CLS.Read_SCO; + + case SCOD.Kind is + when Removed => + raise Program_Error with "unreachable code"; + + when Statement => + SCOD.S_Kind := Statement_Kind'Val (CLS.Read_U8); + SCOD.Dominant := CLS.Read_SCO; + SCOD.Dominant_Value := CLS.Read_Tristate; + SCOD.Dominant_Sloc := CLS.Read_Source_Location; + SCOD.Handler_Range := CLS.Read_Source_Location_Range; + SCOD.Pragma_Name := Pragma_Id'Val (CLS.Read_U8); + + when Condition => + SCOD.Value := CLS.Read_Tristate; + Read (CLS, SCOD.PC_Set); + SCOD.BDD_Node := CLS.Read_BDD_Node; + SCOD.Index := CLS.Read_Condition; + + when Decision => + SCOD.Expression := CLS.Read_SCO; + SCOD.D_Kind := Decision_Kind'Val (CLS.Read_U8); + SCOD.Control_Location := CLS.Read_Source_Location; + SCOD.Last_Cond_Index := CLS.Read_Condition; + SC_Obligations.BDD.Read (CLS'Access, SCOD.Decision_BDD); + SCOD.Degraded_Origins := CLS.Read_Boolean; + SCOD.Aspect_Name := Aspect_Id'Val (CLS.Read_U8); + SCOD.Path_Count := CLS.Read_Integer; + + when Operator => + declare + First : constant Operand_Position := + Operand_Position'Val (CLS.Read_U8); + Last : constant Operand_Position := + Operand_Position'Val (CLS.Read_U8); + begin + pragma Assert (First = Left); + pragma Assert (Last = Right); + + SCOD.Operands (Left) := CLS.Read_SCO; + SCOD.Operands (Right) := CLS.Read_SCO; + end; + SCOD.Op_Kind := Operator_Kind'Val (CLS.Read_U8); + end case; + + Element := SCOD; + end Read; + -------------------------------- -- Checkpoint_Load_Merge_Unit -- -------------------------------- @@ -1444,63 +1708,6 @@ package body SC_Obligations is -- Procedures below use comparisons on checkpoint format versions - ---------- - -- Read -- - ---------- - - procedure Read - (S : access Root_Stream_Type'Class; - V : out CU_Info) - is - CLS : Stateful_Stream renames Stateful_Stream (S.all); - - New_CUI : CU_Info (SCO_Provider'Input (S)); - pragma Warnings (Off, New_CUI); - -- Used only for discriminant and default initialization - - begin - -- Set CUI's discriminant - - V := New_CUI; - - Source_File_Index'Read (S, V.Origin); - Source_File_Index'Read (S, V.Main_Source); - SCO_Id'Read (S, V.First_SCO); - SCO_Id'Read (S, V.Last_SCO); - Inst_Id'Read (S, V.First_Instance); - Inst_Id'Read (S, V.Last_Instance); - SFI_Vector'Read (S, V.Deps); - Boolean'Read (S, V.Has_Code); - Fingerprint_Type'Read (S, V.Fingerprint); - SCO_PP_Info_Maps.Map'Read (S, V.PP_Info_Map); - - case V.Provider is - when Compiler => - null; - when Instrumenter => - - -- By default, use "no fingerprint" for buffer bit maps - -- fingerprints: by design checkpoints contains neither bit maps - -- nor their fingerprints (all source traces are processed before - -- loading checkpoints, and bit maps are needed only to interpret - -- source traces). - - V.Bit_Maps_Fingerprint := No_Fingerprint; - - if CLS.Purpose_Of = Instrumentation then - V.Bit_Maps.Statement_Bits := - new Statement_Bit_Map'(Statement_Bit_Map'Input (S)); - V.Bit_Maps.Decision_Bits := - new Decision_Bit_Map'(Decision_Bit_Map'Input (S)); - V.Bit_Maps.MCDC_Bits := - new MCDC_Bit_Map'(MCDC_Bit_Map'Input (S)); - Fingerprint_Type'Read (S, V.Bit_Maps_Fingerprint); - end if; - end case; - - Scope_Entities_Tree'Read (S, V.Scope_Entities); - end Read; - ----------- -- Write -- ----------- @@ -1544,22 +1751,21 @@ package body SC_Obligations is procedure Checkpoint_Load (CLS : access Checkpoint_Load_State) is CP_Vectors : Source_Coverage_Vectors; - S : constant access Root_Stream_Type'Class := CLS.all'Access; Relocs : Checkpoint_Relocations renames CLS.Relocations; begin -- Load data from stream -- This part must be kept consistent with Checkpoint_Save - CU_Info_Vectors.Vector'Read (S, CP_Vectors.CU_Vector); - ALI_Annotation_Maps.Map'Read (S, CP_Vectors.ALI_Annotations); - Inst_Info_Vectors.Vector'Read (S, CP_Vectors.Inst_Vector); - BDD.BDD_Vectors.Vector'Read (S, CP_Vectors.BDD_Vector); - SCO_Vectors.Vector'Read (S, CP_Vectors.SCO_Vector); + Read (CLS.all, CP_Vectors.CU_Vector); + Read (CLS, CP_Vectors.ALI_Annotations); + Read (CLS.all, CP_Vectors.Inst_Vector); + SC_Obligations.BDD.Read (CLS, CP_Vectors.BDD_Vector); + Read (CLS.all, CP_Vectors.SCO_Vector); -- Load non-instrumented information - SCO_Sets.Set'Read (S, CP_Vectors.Non_Instr_SCOs); - SCO_Sets.Set'Read (S, CP_Vectors.Non_Instr_MCDC_SCOs); + Read (CLS.all, CP_Vectors.Non_Instr_SCOs); + Read (CLS.all, CP_Vectors.Non_Instr_MCDC_SCOs); -- Allocate mapping tables for SCOs, instance identifiers and BDD nodes @@ -3845,59 +4051,6 @@ package body SC_Obligations is end if; end Map_Tag; - ---------- - -- Read -- - ---------- - - procedure Read (S : access Root_Stream_Type'Class; V : out SCO_Descriptor) - is - SCOD : SCO_Descriptor (SCO_Kind'Input (S)); - begin - if SCOD.Kind = Removed then - V := Removed_SCO_Descriptor; - return; - end if; - - SCOD.Origin := CU_Id'Input (S); - SCOD.Sloc_Range := Source_Location_Range'Input (S); - SCOD.Parent := SCO_Id'Input (S); - - case SCOD.Kind is - when Removed => - raise Program_Error with "unreachable code"; - - when Statement => - SCOD.S_Kind := Statement_Kind'Input (S); - SCOD.Dominant := SCO_Id'Input (S); - SCOD.Dominant_Value := Tristate'Input (S); - SCOD.Dominant_Sloc := Source_Location'Input (S); - SCOD.Handler_Range := Source_Location_Range'Input (S); - SCOD.Pragma_Name := Pragma_Id'Input (S); - - when Condition => - SCOD.Value := Tristate'Input (S); - SCOD.PC_Set := PC_Sets.Set'Input (S); - SCOD.BDD_Node := BDD_Node_Id'Input (S); - SCOD.Index := Condition_Index'Input (S); - - when Decision => - SCOD.Expression := SCO_Id'Input (S); - SCOD.D_Kind := Decision_Kind'Input (S); - SCOD.Control_Location := Source_Location'Input (S); - SCOD.Last_Cond_Index := Any_Condition_Index'Input (S); - SCOD.Decision_BDD := BDD.BDD_Type'Input (S); - SCOD.Degraded_Origins := Boolean'Input (S); - SCOD.Aspect_Name := Aspect_Id'Input (S); - SCOD.Path_Count := Natural'Input (S); - - when Operator => - SCOD.Operands := Operand_Pair'Input (S); - SCOD.Op_Kind := Operator_Kind'Input (S); - end case; - - V := SCOD; - end Read; - ----------- -- Write -- ----------- diff --git a/tools/gnatcov/strings.adb b/tools/gnatcov/strings.adb index 93c48a729..1a12f594a 100644 --- a/tools/gnatcov/strings.adb +++ b/tools/gnatcov/strings.adb @@ -21,6 +21,7 @@ with Ada.Strings.Hash; with GNAT.Regexp; +with Checkpoints; use Checkpoints; with Paths; package body Strings is @@ -92,6 +93,40 @@ package body Strings is and then S (S'Last - Length + 1 .. S'Last) = Suffix; end Has_Suffix; + ---------- + -- Read -- + ---------- + + procedure Read + (CLS : access Checkpoints.Checkpoint_Load_State; + Value : out String_Vectors.Vector) + is + procedure Read is new Read_Vector + (Index_Type => Natural, + Element_Type => Ada.Strings.Unbounded.Unbounded_String, + "=" => Ada.Strings.Unbounded."=", + Vectors => String_Vectors, + Read_Element => Read); + begin + Read (CLS.all, Value); + end Read; + + procedure Read + (CLS : access Checkpoints.Checkpoint_Load_State; + Value : out String_Maps.Map) + is + procedure Read is new Read_Map + (Key_Type => Ada.Strings.Unbounded.Unbounded_String, + Element_Type => Ada.Strings.Unbounded.Unbounded_String, + Map_Type => String_Maps.Map, + Clear => String_Maps.Clear, + Insert => String_Maps.Insert, + Read_Key => Read, + Read_Element => Read); + begin + Read (CLS.all, Value); + end Read; + -------------------- -- To_String_Sets -- -------------------- diff --git a/tools/gnatcov/strings.ads b/tools/gnatcov/strings.ads index b3c683adf..3552126ff 100644 --- a/tools/gnatcov/strings.ads +++ b/tools/gnatcov/strings.ads @@ -29,6 +29,8 @@ with Ada.Strings.Unbounded.Less_Case_Insensitive; with GNAT.Strings; use GNAT.Strings; +limited with Checkpoints; + package Strings is function Hash (El : String_Access) return Ada.Containers.Hash_Type; @@ -67,12 +69,22 @@ package Strings is Element_Type => Ada.Strings.Unbounded.Unbounded_String, "=" => Ada.Strings.Unbounded."="); + procedure Read + (CLS : access Checkpoints.Checkpoint_Load_State; + Value : out String_Vectors.Vector); + -- Read a String_Vectors.Vector from CLS + package String_Maps is new Ada.Containers.Ordered_Maps (Key_Type => Ada.Strings.Unbounded.Unbounded_String, Element_Type => Ada.Strings.Unbounded.Unbounded_String, "<" => Ada.Strings.Unbounded."<", "=" => Ada.Strings.Unbounded."="); + procedure Read + (CLS : access Checkpoints.Checkpoint_Load_State; + Value : out String_Maps.Map); + -- Read a String_Maps.Map from CLS + package String_Sets is new Ada.Containers.Ordered_Sets (Element_Type => Ada.Strings.Unbounded.Unbounded_String, "<" => Ada.Strings.Unbounded.Less_Case_Insensitive, diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 8f0d3dc32..e0f25ff1c 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -67,6 +67,19 @@ package body Subprocesses is and then L.Arguments = R.Arguments; end "="; + ---------- + -- Read -- + ---------- + + procedure Read + (CLS : in out Checkpoints.Checkpoint_Load_State; + Value : out Command_Type) is + begin + Value.Command := CLS.Read_Unbounded_String; + Read (CLS'Access, Value.Arguments); + Read (CLS'Access, Value.Environment); + end Read; + ---------------- -- Append_Arg -- ---------------- diff --git a/tools/gnatcov/subprocesses.ads b/tools/gnatcov/subprocesses.ads index 34216a4a3..292525e8f 100644 --- a/tools/gnatcov/subprocesses.ads +++ b/tools/gnatcov/subprocesses.ads @@ -27,6 +27,7 @@ with Ada.Strings.Unbounded; with GNATCOLL.OS.Process; use GNATCOLL.OS.Process; +with Checkpoints; with Logging; with Strings; use Strings; with Temp_Dirs; use Temp_Dirs; @@ -54,6 +55,11 @@ package Subprocesses is -- Note: the equality comparison does not consider the commands' -- environment. + procedure Read + (CLS : in out Checkpoints.Checkpoint_Load_State; + Value : out Command_Type); + -- Read a Command_Type from CLS + Null_Command : constant Command_Type := (others => <>); procedure Append_Arg (Cmd : in out Command_Type; Arg : String); diff --git a/tools/gnatcov/traces_files_registry.adb b/tools/gnatcov/traces_files_registry.adb index 3d1136b71..5a1100e96 100644 --- a/tools/gnatcov/traces_files_registry.adb +++ b/tools/gnatcov/traces_files_registry.adb @@ -24,6 +24,7 @@ with Ada.Strings.Unbounded.Hash; with Interfaces.C; +with Checkpoints; use Checkpoints; with Outputs; with Qemu_Traces; use Qemu_Traces; @@ -374,18 +375,17 @@ package body Traces_Files_Registry is begin loop declare - Name : constant Unbounded_String := - Unbounded_String'Input (CLS); + Name : constant Unbounded_String := CLS.Read_Unbounded_String; CP_File : Trace_File_Element_Acc; begin exit when Length (Name) = 0; CP_File := new Trace_File_Element; CP_File.Filename := Name; - Trace_File_Kind'Read (CLS, CP_File.Kind); - Unbounded_String'Read (CLS, CP_File.Context); - Unbounded_String'Read (CLS, CP_File.Program_Name); - Unbounded_String'Read (CLS, CP_File.Time); - Unbounded_String'Read (CLS, CP_File.User_Data); + CP_File.Kind := Trace_File_Kind'Val (CLS.Read_U8); + CLS.Read (CP_File.Context); + CLS.Read (CP_File.Program_Name); + CLS.Read (CP_File.Time); + CLS.Read (CP_File.User_Data); Add_Traces_File (CP_File); end; From c1972f93572556550b77b970789f6b635a6af33e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 20 Nov 2023 12:34:23 +0000 Subject: [PATCH 0522/1483] Checkpoint_Load: replace access argument types with IN OUT modes Now that we do not use streaming attributes anymore, it makes more sense to use IN OUT modes for the Checkpoint_Load_State argument rather than access types: no need to take 'Access or dereference once in a while. --- tools/gnatcov/ali_files.adb | 4 ++-- tools/gnatcov/ali_files.ads | 2 +- tools/gnatcov/checkpoints.adb | 12 +++++------ tools/gnatcov/coverage-source.adb | 4 ++-- tools/gnatcov/coverage-source.ads | 2 +- tools/gnatcov/files_table.adb | 2 +- tools/gnatcov/files_table.ads | 2 +- tools/gnatcov/instrument-checkpoints.adb | 6 +++--- tools/gnatcov/instrument-checkpoints.ads | 2 +- tools/gnatcov/sc_obligations-bdd.adb | 8 ++++---- tools/gnatcov/sc_obligations-bdd.ads | 4 ++-- tools/gnatcov/sc_obligations.adb | 26 ++++++++++++------------ tools/gnatcov/sc_obligations.ads | 2 +- tools/gnatcov/strings.adb | 8 ++++---- tools/gnatcov/strings.ads | 4 ++-- tools/gnatcov/subprocesses.adb | 4 ++-- tools/gnatcov/traces_files_registry.adb | 2 +- tools/gnatcov/traces_files_registry.ads | 2 +- 18 files changed, 48 insertions(+), 48 deletions(-) diff --git a/tools/gnatcov/ali_files.adb b/tools/gnatcov/ali_files.adb index 5695f61ec..5685fe806 100644 --- a/tools/gnatcov/ali_files.adb +++ b/tools/gnatcov/ali_files.adb @@ -665,7 +665,7 @@ package body ALI_Files is end Read; procedure Read - (CLS : access Checkpoints.Checkpoint_Load_State; + (CLS : in out Checkpoints.Checkpoint_Load_State; Value : out ALI_Annotation_Maps.Map) is procedure Read_Map is new Checkpoints.Read_Map @@ -677,7 +677,7 @@ package body ALI_Files is Read_Key => Read, Read_Element => Read); begin - Read_Map (CLS.all, Value); + Read_Map (CLS, Value); end Read; end ALI_Files; diff --git a/tools/gnatcov/ali_files.ads b/tools/gnatcov/ali_files.ads index 872e5e087..bc1a9082a 100644 --- a/tools/gnatcov/ali_files.ads +++ b/tools/gnatcov/ali_files.ads @@ -77,7 +77,7 @@ package ALI_Files is Element_Type => ALI_Annotation); procedure Read - (CLS : access Checkpoints.Checkpoint_Load_State; + (CLS : in out Checkpoints.Checkpoint_Load_State; Value : out ALI_Annotation_Maps.Map); -- Read a ALI_Annotation_Maps.Map from CLS diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index a979d5733..3a5e78de4 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -563,7 +563,7 @@ package body Checkpoints is Raise_Stub_Internal_Error_For (Load_Checkpoint); declare - CLS : aliased Checkpoint_Load_State := + CLS : Checkpoint_Load_State := (Root_Stream_Type with Stream => Stream (SF), Filename => To_Unbounded_String (Filename), @@ -645,11 +645,11 @@ package body Checkpoints is Update_Current_Trace_Kind (Any_Accepted_Trace_Kind'Val (CLS.Read_U8)); - Files_Table.Checkpoint_Load (CLS'Access, Ignored_Source_Files); - SC_Obligations.Checkpoint_Load (CLS'Access); - Instrument.Checkpoints.Checkpoint_Load (CLS'Access); - Coverage.Source.Checkpoint_Load (CLS'Access); - Traces_Files_Registry.Checkpoint_Load (CLS'Access); + Files_Table.Checkpoint_Load (CLS, Ignored_Source_Files); + SC_Obligations.Checkpoint_Load (CLS); + Instrument.Checkpoints.Checkpoint_Load (CLS); + Coverage.Source.Checkpoint_Load (CLS); + Traces_Files_Registry.Checkpoint_Load (CLS); Free (CLS.Relocations); end; diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 488ffd403..c956cc7e3 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -493,7 +493,7 @@ package body Coverage.Source is -- Checkpoint_Load -- --------------------- - procedure Checkpoint_Load (CLS : access Checkpoint_Load_State) is + procedure Checkpoint_Load (CLS : in out Checkpoint_Load_State) is use SCI_Vector_Vectors; CP_Tag_Provider : Unbounded_String; @@ -524,7 +524,7 @@ package body Coverage.Source is -- 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.all, CP_SCI_Vector); + Read (CLS, CP_SCI_Vector); if not Do_Merge then return; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 3b0e4c0e8..3d8f49b54 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -152,7 +152,7 @@ package Coverage.Source is procedure Checkpoint_Clear; -- Clear the internal data structures used to create checkpoints - procedure Checkpoint_Load (CLS : access Checkpoint_Load_State); + procedure Checkpoint_Load (CLS : in out Checkpoint_Load_State); -- Load checkpointed coverage state from S and merge into current state end Coverage.Source; diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 4a1877777..61e6b3bba 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -1951,7 +1951,7 @@ package body Files_Table is --------------------- procedure Checkpoint_Load - (CLS : access Checkpoint_Load_State; + (CLS : in out Checkpoint_Load_State; Ignored_Source_Files : access GNAT.Regexp.Regexp) is pragma Assert diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 8c32c02d7..833c58fe9 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -573,7 +573,7 @@ package Files_Table is -- Clear the internal data structures used to create checkpoints procedure Checkpoint_Load - (CLS : access Checkpoints.Checkpoint_Load_State; + (CLS : in out Checkpoints.Checkpoint_Load_State; Ignored_Source_Files : access GNAT.Regexp.Regexp); -- Load checkpointed files table from S and merge in current state. -- Ignore_Source_Files should be null if the checkpoint purpose is diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index 877f421a9..6788bc77c 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -48,14 +48,14 @@ package body Instrument.Checkpoints is -- Checkpoint_Load -- --------------------- - procedure Checkpoint_Load (CLS : access Checkpoint_Load_State) is + procedure Checkpoint_Load (CLS : in out Checkpoint_Load_State) is Relocs : Checkpoint_Relocations renames CLS.Relocations; begin declare use Instrumented_Unit_To_CU_Maps; CP_IU_Map : Map; begin - Read (CLS.all, CP_IU_Map); + Read (CLS, CP_IU_Map); for Cur in CP_IU_Map.Iterate loop declare @@ -99,7 +99,7 @@ package body Instrument.Checkpoints is CP_PP_Cmds : SFI_To_PP_Cmd_Maps.Map; CP_SFI : Source_File_Index; begin - Read (CLS.all, CP_PP_Cmds); + Read (CLS, CP_PP_Cmds); for CP_Cur in CP_PP_Cmds.Iterate loop diff --git a/tools/gnatcov/instrument-checkpoints.ads b/tools/gnatcov/instrument-checkpoints.ads index 96a596364..2c6a0b99b 100644 --- a/tools/gnatcov/instrument-checkpoints.ads +++ b/tools/gnatcov/instrument-checkpoints.ads @@ -27,7 +27,7 @@ package Instrument.Checkpoints is procedure Checkpoint_Clear; -- Clear the internal data structures used to create checkpoints - procedure Checkpoint_Load (CLS : access Checkpoint_Load_State); + procedure Checkpoint_Load (CLS : in out Checkpoint_Load_State); -- Load instrumentation-specific data from stream and merge them in the -- current state. diff --git a/tools/gnatcov/sc_obligations-bdd.adb b/tools/gnatcov/sc_obligations-bdd.adb index 461307dcf..f298b566f 100644 --- a/tools/gnatcov/sc_obligations-bdd.adb +++ b/tools/gnatcov/sc_obligations-bdd.adb @@ -32,7 +32,7 @@ package body SC_Obligations.BDD is procedure Read (CLS : in out Checkpoint_Load_State; Value : out BDD_Node); -- Read a BDD_Node from CLS - procedure Read is new Read_Vector + procedure Read_BDD_Vector is new Read_Vector (Index_Type => Valid_BDD_Node_Id, Element_Type => BDD_Node, "=" => "=", @@ -132,7 +132,7 @@ package body SC_Obligations.BDD is ---------- procedure Read - (CLS : access Checkpoints.Checkpoint_Load_State; Value : out BDD_Type) is + (CLS : in out Checkpoints.Checkpoint_Load_State; Value : out BDD_Type) is begin Value.Decision := CLS.Read_SCO; Value.Root_Condition := CLS.Read_BDD_Node; @@ -173,10 +173,10 @@ package body SC_Obligations.BDD is end Read; procedure Read - (CLS : access Checkpoints.Checkpoint_Load_State; + (CLS : in out Checkpoints.Checkpoint_Load_State; Vector : out BDD_Vectors.Vector) is begin - Read (CLS.all, Vector); + Read_BDD_Vector (CLS, Vector); end Read; --------------------- diff --git a/tools/gnatcov/sc_obligations-bdd.ads b/tools/gnatcov/sc_obligations-bdd.ads index 3a902aabc..559d9259f 100644 --- a/tools/gnatcov/sc_obligations-bdd.ads +++ b/tools/gnatcov/sc_obligations-bdd.ads @@ -90,7 +90,7 @@ private package SC_Obligations.BDD is Element_Type => BDD_Node); procedure Read - (CLS : access Checkpoints.Checkpoint_Load_State; + (CLS : in out Checkpoints.Checkpoint_Load_State; Vector : out BDD_Vectors.Vector); -- Read a BDD_Vectors.Vector from CLS @@ -127,7 +127,7 @@ private package SC_Obligations.BDD is for BDD_Type'Write use Write; procedure Read - (CLS : access Checkpoints.Checkpoint_Load_State; Value : out BDD_Type); + (CLS : in out Checkpoints.Checkpoint_Load_State; Value : out BDD_Type); -- Read a BDD_Type from CLS procedure Allocate diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 74d6c5a8e..b6f287785 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -620,7 +620,7 @@ package body SC_Obligations is Read_Element => Read); procedure Checkpoint_Load_Merge_Unit - (CLS : access Checkpoint_Load_State; + (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : CU_Info; Real_CU_Id : CU_Id); @@ -628,7 +628,7 @@ package body SC_Obligations is -- whose ID is Real_CU_Id. procedure Checkpoint_Load_New_Unit - (CLS : access Checkpoint_Load_State; + (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; CP_CU_Id : CU_Id; @@ -637,7 +637,7 @@ package body SC_Obligations is -- interest. The newly assigned CU_Id is returned in New_CU_Id. procedure Checkpoint_Load_Unit - (CLS : access Checkpoint_Load_State; + (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; CP_CU_Id : CU_Id; @@ -1039,7 +1039,7 @@ package body SC_Obligations is SCOD.D_Kind := Decision_Kind'Val (CLS.Read_U8); SCOD.Control_Location := CLS.Read_Source_Location; SCOD.Last_Cond_Index := CLS.Read_Condition; - SC_Obligations.BDD.Read (CLS'Access, SCOD.Decision_BDD); + SC_Obligations.BDD.Read (CLS, SCOD.Decision_BDD); SCOD.Degraded_Origins := CLS.Read_Boolean; SCOD.Aspect_Name := Aspect_Id'Val (CLS.Read_U8); SCOD.Path_Count := CLS.Read_Integer; @@ -1068,7 +1068,7 @@ package body SC_Obligations is -------------------------------- procedure Checkpoint_Load_Merge_Unit - (CLS : access Checkpoint_Load_State; + (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : CU_Info; Real_CU_Id : CU_Id) @@ -1186,7 +1186,7 @@ package body SC_Obligations is ------------------------------ procedure Checkpoint_Load_New_Unit - (CLS : access Checkpoint_Load_State; + (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; CP_CU_Id : CU_Id; @@ -1573,7 +1573,7 @@ package body SC_Obligations is -------------------------- procedure Checkpoint_Load_Unit - (CLS : access Checkpoint_Load_State; + (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; CP_CU_Id : CU_Id; @@ -1749,23 +1749,23 @@ package body SC_Obligations is -- Checkpoint_Load -- --------------------- - procedure Checkpoint_Load (CLS : access Checkpoint_Load_State) is + procedure Checkpoint_Load (CLS : in out Checkpoint_Load_State) is CP_Vectors : Source_Coverage_Vectors; Relocs : Checkpoint_Relocations renames CLS.Relocations; begin -- Load data from stream -- This part must be kept consistent with Checkpoint_Save - Read (CLS.all, CP_Vectors.CU_Vector); + Read (CLS, CP_Vectors.CU_Vector); Read (CLS, CP_Vectors.ALI_Annotations); - Read (CLS.all, CP_Vectors.Inst_Vector); + Read (CLS, CP_Vectors.Inst_Vector); SC_Obligations.BDD.Read (CLS, CP_Vectors.BDD_Vector); - Read (CLS.all, CP_Vectors.SCO_Vector); + Read (CLS, CP_Vectors.SCO_Vector); -- Load non-instrumented information - Read (CLS.all, CP_Vectors.Non_Instr_SCOs); - Read (CLS.all, CP_Vectors.Non_Instr_MCDC_SCOs); + Read (CLS, CP_Vectors.Non_Instr_SCOs); + Read (CLS, CP_Vectors.Non_Instr_MCDC_SCOs); -- Allocate mapping tables for SCOs, instance identifiers and BDD nodes diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 710f40bdf..97bff1754 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -783,7 +783,7 @@ package SC_Obligations is procedure Checkpoint_Clear; -- Clear the internal data structures used to create checkpoints - procedure Checkpoint_Load (CLS : access Checkpoints.Checkpoint_Load_State); + procedure Checkpoint_Load (CLS : in out Checkpoints.Checkpoint_Load_State); -- Load checkpointed SCOs from stream and merge them in current state --------------------------- diff --git a/tools/gnatcov/strings.adb b/tools/gnatcov/strings.adb index 1a12f594a..97bde28b4 100644 --- a/tools/gnatcov/strings.adb +++ b/tools/gnatcov/strings.adb @@ -98,7 +98,7 @@ package body Strings is ---------- procedure Read - (CLS : access Checkpoints.Checkpoint_Load_State; + (CLS : in out Checkpoints.Checkpoint_Load_State; Value : out String_Vectors.Vector) is procedure Read is new Read_Vector @@ -108,11 +108,11 @@ package body Strings is Vectors => String_Vectors, Read_Element => Read); begin - Read (CLS.all, Value); + Read (CLS, Value); end Read; procedure Read - (CLS : access Checkpoints.Checkpoint_Load_State; + (CLS : in out Checkpoints.Checkpoint_Load_State; Value : out String_Maps.Map) is procedure Read is new Read_Map @@ -124,7 +124,7 @@ package body Strings is Read_Key => Read, Read_Element => Read); begin - Read (CLS.all, Value); + Read (CLS, Value); end Read; -------------------- diff --git a/tools/gnatcov/strings.ads b/tools/gnatcov/strings.ads index 3552126ff..812b7b2db 100644 --- a/tools/gnatcov/strings.ads +++ b/tools/gnatcov/strings.ads @@ -70,7 +70,7 @@ package Strings is "=" => Ada.Strings.Unbounded."="); procedure Read - (CLS : access Checkpoints.Checkpoint_Load_State; + (CLS : in out Checkpoints.Checkpoint_Load_State; Value : out String_Vectors.Vector); -- Read a String_Vectors.Vector from CLS @@ -81,7 +81,7 @@ package Strings is "=" => Ada.Strings.Unbounded."="); procedure Read - (CLS : access Checkpoints.Checkpoint_Load_State; + (CLS : in out Checkpoints.Checkpoint_Load_State; Value : out String_Maps.Map); -- Read a String_Maps.Map from CLS diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index e0f25ff1c..cfbbea374 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -76,8 +76,8 @@ package body Subprocesses is Value : out Command_Type) is begin Value.Command := CLS.Read_Unbounded_String; - Read (CLS'Access, Value.Arguments); - Read (CLS'Access, Value.Environment); + Read (CLS, Value.Arguments); + Read (CLS, Value.Environment); end Read; ---------------- diff --git a/tools/gnatcov/traces_files_registry.adb b/tools/gnatcov/traces_files_registry.adb index 5a1100e96..15a29d4cf 100644 --- a/tools/gnatcov/traces_files_registry.adb +++ b/tools/gnatcov/traces_files_registry.adb @@ -370,7 +370,7 @@ package body Traces_Files_Registry is -- Checkpoint_Load -- --------------------- - procedure Checkpoint_Load (CLS : access Checkpoints.Checkpoint_Load_State) + procedure Checkpoint_Load (CLS : in out Checkpoints.Checkpoint_Load_State) is begin loop diff --git a/tools/gnatcov/traces_files_registry.ads b/tools/gnatcov/traces_files_registry.ads index 12fc694b6..ee2d6f79d 100644 --- a/tools/gnatcov/traces_files_registry.ads +++ b/tools/gnatcov/traces_files_registry.ads @@ -106,7 +106,7 @@ package Traces_Files_Registry is procedure Checkpoint_Clear; -- Clear the internal data structures used to create checkpoints - procedure Checkpoint_Load (CLS : access Checkpoints.Checkpoint_Load_State); + procedure Checkpoint_Load (CLS : in out Checkpoints.Checkpoint_Load_State); -- Load list of trace files from S end Traces_Files_Registry; From 457233f38df436a90e85d5d005388b0a2b626e16 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 20 Nov 2023 08:58:03 +0000 Subject: [PATCH 0523/1483] Checkpoints: rework use of last checkpoint format version when writing gnatcov always use the version of the checkpoint file format when writing a SID/checkpoint. Using this fact, move the "Version" information from read/write common code to read-specific code. --- tools/gnatcov/checkpoints.adb | 6 ++---- tools/gnatcov/checkpoints.ads | 22 +++++++++++----------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index 3a5e78de4..a8faa0282 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -443,8 +443,7 @@ package body Checkpoints is Context : access Coverage.Context; Purpose : Checkpoint_Purpose) is - Version : constant Checkpoint_Version := Checkpoint_Version'Last; - SF : Ada.Streams.Stream_IO.File_Type; + SF : Ada.Streams.Stream_IO.File_Type; begin Create (SF, Out_File, Filename); @@ -455,12 +454,11 @@ package body Checkpoints is (Root_Stream_Type with Stream => Stream (SF), Filename => To_Unbounded_String (Filename), - Version => Version, Purpose => Purpose); Supported_Levels : Levels_Type := Current_Levels; begin Checkpoint_Header'Write - (CSS.Stream, (Version => Version, others => <>)); + (CSS.Stream, (Version => Checkpoint_Version'Last, others => <>)); Checkpoint_Purpose'Write (CSS.Stream, Purpose); diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 52f86952d..1cc964394 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -241,9 +241,6 @@ package Checkpoints is Filename : Unbounded_String; -- Name of the checkpoint being written/read - Version : Checkpoint_Version; - -- Format version for the checkpoint being written/read - Purpose : Checkpoint_Purpose; -- Purpose for the checkpoint being written/read end record; @@ -257,14 +254,6 @@ package Checkpoints is Item : Stream_Element_Array); -- Read/write from/to underlying stream - use type Interfaces.Unsigned_32; - function Version_Less - (SS : Stateful_Stream'Class; Than : Checkpoint_Version) return Boolean - is (SS.Version < Than) - with Inline; - -- This is provided as a function to prevent the compiler from generating - -- "can never be greater than" warnings. - function Purpose_Of (SS : Stateful_Stream'Class) return Checkpoint_Purpose is (SS.Purpose) @@ -279,9 +268,20 @@ package Checkpoints is -- Global state shared across phases of a checkpoint load type Checkpoint_Load_State is new Stateful_Stream with record + Version : Checkpoint_Version; + -- Format version for the checkpoint being read + Relocations : Checkpoint_Relocations; end record; + use type Interfaces.Unsigned_32; + function Version_Less + (CLS : Checkpoint_Load_State; Than : Checkpoint_Version) return Boolean + is (CLS.Version < Than) + with Inline; + -- This is provided as a function to prevent the compiler from generating + -- "can never be greater than" warnings. + procedure Checkpoint_Save (Filename : String; Context : access Coverage.Context; From 1070f9d25b060027028f99b502485a83b5a34509 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 21 Nov 2023 10:01:00 +0000 Subject: [PATCH 0524/1483] Checkpoint_Save: stop using streaming attributes for non-trivial types Use streaming attributes only for atomic data types with specific size (Unsigned_8, Integer_32, ...). Create explicit checkpoint writing procedures for the rest (records, containers, scalars with implicit size, ...). --- tools/gnatcov/ali_files.adb | 51 ++- tools/gnatcov/ali_files.ads | 9 +- tools/gnatcov/checkpoints.adb | 407 ++++++++++++++++++++++- tools/gnatcov/checkpoints.ads | 140 ++++++++ tools/gnatcov/coverage-source.adb | 71 +++- tools/gnatcov/files_table.adb | 30 +- tools/gnatcov/instrument-checkpoints.adb | 6 +- tools/gnatcov/instrument.adb | 26 ++ tools/gnatcov/instrument.ads | 37 +++ tools/gnatcov/mc_dc.adb | 12 + tools/gnatcov/mc_dc.ads | 9 + tools/gnatcov/sc_obligations-bdd.adb | 99 +++--- tools/gnatcov/sc_obligations-bdd.ads | 26 +- tools/gnatcov/sc_obligations.adb | 360 +++++++++++++------- tools/gnatcov/strings.adb | 35 ++ tools/gnatcov/strings.ads | 9 + tools/gnatcov/subprocesses.adb | 12 + tools/gnatcov/subprocesses.ads | 4 + tools/gnatcov/traces_files_registry.adb | 14 +- 19 files changed, 1119 insertions(+), 238 deletions(-) diff --git a/tools/gnatcov/ali_files.adb b/tools/gnatcov/ali_files.adb index 5685fe806..338e05c0f 100644 --- a/tools/gnatcov/ali_files.adb +++ b/tools/gnatcov/ali_files.adb @@ -36,6 +36,10 @@ package body ALI_Files is (CLS : in out Checkpoint_Load_State; Value : out ALI_Annotation); -- Read a ALI_Annotation from CLS + procedure Write + (CSS : in out Checkpoint_Save_State; Value : ALI_Annotation); + -- Write a ALI_Annotation to CSS + ----------------------------------------------- -- Regular expressions for ALI files parsing -- ----------------------------------------------- @@ -627,21 +631,6 @@ package body ALI_Files is return ALI_Index; end Load_ALI; - ----------- - -- Write -- - ----------- - - procedure Write (S : access Root_Stream_Type'Class; V : ALI_Annotation) is - begin - CU_Id'Write (S, V.CU); - ALI_Annotation_Kind'Write (S, V.Kind); - if V.Message /= null then - String'Output (S, V.Message.all); - else - String'Output (S, ""); - end if; - end Write; - ---------- -- Read -- ---------- @@ -680,4 +669,36 @@ package body ALI_Files is Read_Map (CLS, Value); end Read; + ----------- + -- Write -- + ----------- + + procedure Write (CSS : in out Checkpoint_Save_State; Value : ALI_Annotation) + is + begin + CSS.Write_CU (Value.CU); + CSS.Write_U8 (ALI_Annotation_Kind'Pos (Value.Kind)); + CSS.Write_Unbounded (if Value.Message = null + then "" + else Value.Message.all); + end Write; + + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; + Value : ALI_Annotation_Maps.Map) + is + procedure Write_Map is new Checkpoints.Write_Map + (Key_Type => Source_Location, + Element_Type => ALI_Annotation, + Map_Type => ALI_Annotation_Maps.Map, + Cursor_Type => ALI_Annotation_Maps.Cursor, + Length => ALI_Annotation_Maps.Length, + Iterate => ALI_Annotation_Maps.Iterate, + Query_Element => ALI_Annotation_Maps.Query_Element, + Write_Key => Write, + Write_Element => Write); + begin + Write_Map (CSS, Value); + end Write; + end ALI_Files; diff --git a/tools/gnatcov/ali_files.ads b/tools/gnatcov/ali_files.ads index bc1a9082a..c58e4de55 100644 --- a/tools/gnatcov/ali_files.ads +++ b/tools/gnatcov/ali_files.ads @@ -19,7 +19,6 @@ -- ALI files reader with Ada.Containers.Ordered_Maps; -with Ada.Streams; use Ada.Streams; with GNAT.Regexp; with GNAT.Strings; use GNAT.Strings; @@ -68,9 +67,6 @@ package ALI_Files is -- This is relevant only for source trace based coverage analysis. end record; - procedure Write (S : access Root_Stream_Type'Class; V : ALI_Annotation); - for ALI_Annotation'Write use Write; - package ALI_Annotation_Maps is new Ada.Containers.Ordered_Maps (Key_Type => Source_Location, @@ -81,6 +77,11 @@ package ALI_Files is Value : out ALI_Annotation_Maps.Map); -- Read a ALI_Annotation_Maps.Map from CLS + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; + Value : ALI_Annotation_Maps.Map); + -- Write a ALI_Annotation_Maps.Map to CSS + ALI_Annotations : ALI_Annotation_Maps.Map; function Load_ALI diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index a8faa0282..d3e6e5e50 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -36,11 +36,6 @@ package body Checkpoints is Checkpoint_Magic : constant String := "GNATcov checkpoint" & ASCII.NUL; - type Checkpoint_Header is record - Magic : String (1 .. Checkpoint_Magic'Length) := Checkpoint_Magic; - Version : Interfaces.Unsigned_32; - end record; - procedure Free is new Ada.Unchecked_Deallocation (SFI_Map_Array, SFI_Map_Acc); procedure Free is new Ada.Unchecked_Deallocation @@ -457,10 +452,11 @@ package body Checkpoints is Purpose => Purpose); Supported_Levels : Levels_Type := Current_Levels; begin - Checkpoint_Header'Write - (CSS.Stream, (Version => Checkpoint_Version'Last, others => <>)); + -- Write the checkpoint header: magic, version and purpose - Checkpoint_Purpose'Write (CSS.Stream, Purpose); + CSS.Write (Checkpoint_Magic); + CSS.Write_U32 (Checkpoint_Version'Last); + CSS.Write_U8 (Checkpoint_Purpose'Pos (Purpose)); -- Describe the binary traces (if any) that contributed to the -- creation of this checkpoint. @@ -471,7 +467,7 @@ package body Checkpoints is when Unknown | Source_Trace_File => Undetermined, when Binary_Trace_File | All_Trace_Files => Supported_Bits); begin - Binary_Traces_Bits'Write (CSS.Stream, Bits); + CSS.Write_U8 (Binary_Traces_Bits'Pos (Bits)); end; -- Instrumentation is the same for all MC/DC variants, so a @@ -483,9 +479,13 @@ package body Checkpoints is Supported_Levels (MCDC_Coverage_Level'Range) := (others => True); Supported_Levels (Decision) := True; end if; - Levels_Type'Write (CSS.Stream, Supported_Levels); - Traces_Files.Any_Accepted_Trace_Kind'Write - (CSS.Stream, Traces_Files.Currently_Accepted_Trace_Kind); + for Level in Insn .. ATCC loop + CSS.Write (Supported_Levels (Level)); + end loop; + + CSS.Write_U8 + (Traces_Files.Any_Accepted_Trace_Kind'Pos + (Traces_Files.Currently_Accepted_Trace_Kind)); Files_Table.Checkpoint_Save (CSS'Access); SC_Obligations.Checkpoint_Save (CSS'Access); @@ -1201,4 +1201,387 @@ package body Checkpoints is end if; end Read; + -------------------- + -- Write_BDD_Node -- + -------------------- + + procedure Write_BDD_Node + (Self : in out Checkpoint_Save_State; Value : BDD_Node_Id) is + begin + Self.Write_I32 (Interfaces.Integer_32 (Value)); + end Write_BDD_Node; + + ------------------ + -- Write_Bit_Id -- + ------------------ + + procedure Write_Bit_Id + (Self : in out Checkpoint_Save_State; Value : Any_Bit_Id) is + begin + Self.Write_I32 (Interfaces.Integer_32 (Value)); + end Write_Bit_Id; + + -------------- + -- Write_CU -- + -------------- + + procedure Write_CU (Self : in out Checkpoint_Save_State; Value : CU_Id) is + begin + Self.Write_I32 (Interfaces.Integer_32 (Value)); + end Write_CU; + + --------------------- + -- Write_Condition -- + --------------------- + + procedure Write_Condition + (Self : in out Checkpoint_Save_State; Value : Any_Condition_Index) is + begin + Self.Write_I32 (Interfaces.Integer_32 (Value)); + end Write_Condition; + + ----------------- + -- Write_Count -- + ----------------- + + procedure Write_Count + (Self : in out Checkpoint_Save_State; Value : Count_Type) is + begin + Self.Write_I32 (Interfaces.Integer_32 (Value)); + end Write_Count; + + --------------- + -- Write_I32 -- + --------------- + + procedure Write_I32 + (Self : in out Checkpoint_Save_State; Value : Interfaces.Integer_32) is + begin + Interfaces.Integer_32'Write (Self.Stream, Value); + end Write_I32; + + ---------------- + -- Write_Inst -- + ---------------- + + procedure Write_Inst (Self : in out Checkpoint_Save_State; Value : Inst_Id) + is + begin + Self.Write_I32 (Interfaces.Integer_32 (Value)); + end Write_Inst; + + ------------------- + -- Write_Integer -- + ------------------- + + procedure Write_Integer + (Self : in out Checkpoint_Save_State; Value : Integer) is + begin + Self.Write_I32 (Interfaces.Integer_32 (Value)); + end Write_Integer; + + -------------- + -- Write_PC -- + -------------- + + procedure Write_PC (Self : in out Checkpoint_Save_State; Value : Pc_Type) is + begin + case Pc_Type'Size is + when 32 => + Self.Write_U32 (Interfaces.Unsigned_32 (Value)); + when 64 => + Self.Write_U64 (Interfaces.Unsigned_64 (Value)); + when others => + raise Program_Error; + end case; + end Write_PC; + + --------------- + -- Write_SCO -- + --------------- + + procedure Write_SCO (Self : in out Checkpoint_Save_State; Value : SCO_Id) is + begin + Self.Write_I32 (Interfaces.Integer_32 (Value)); + end Write_SCO; + + --------------- + -- Write_SFI -- + --------------- + + procedure Write_SFI + (Self : in out Checkpoint_Save_State; Value : Source_File_Index) is + begin + Self.Write_I32 (Interfaces.Integer_32 (Value)); + end Write_SFI; + + -------------- + -- Write_U8 -- + -------------- + + procedure Write_U8 + (Self : in out Checkpoint_Save_State; Value : Interfaces.Unsigned_8) is + begin + Interfaces.Unsigned_8'Write (Self.Stream, Value); + end Write_U8; + + --------------- + -- Write_U16 -- + --------------- + + procedure Write_U16 + (Self : in out Checkpoint_Save_State; Value : Interfaces.Unsigned_16) is + begin + Interfaces.Unsigned_16'Write (Self.Stream, Value); + end Write_U16; + + --------------- + -- Write_U32 -- + --------------- + + procedure Write_U32 + (Self : in out Checkpoint_Save_State; Value : Interfaces.Unsigned_32) is + begin + Interfaces.Unsigned_32'Write (Self.Stream, Value); + end Write_U32; + + --------------- + -- Write_U64 -- + --------------- + + procedure Write_U64 + (Self : in out Checkpoint_Save_State; Value : Interfaces.Unsigned_64) is + begin + Interfaces.Unsigned_64'Write (Self.Stream, Value); + end Write_U64; + + ----------- + -- Write -- + ----------- + + procedure Write (Self : in out Checkpoint_Save_State; Value : Boolean) is + begin + Self.Write_U8 (Boolean'Pos (Value)); + end Write; + + procedure Write + (Self : in out Checkpoint_Save_State; Value : Compilation_Unit) is + begin + Self.Write (Value.Language); + Self.Write (Value.Unit_Name); + end Write; + + procedure Write + (Self : in out Checkpoint_Save_State; + Value : SC_Obligations.Fingerprint_Type) + is + Buffer : String (1 .. SC_Obligations.Fingerprint_Type'Length); + I : Positive := 1; + begin + for Digit of Value loop + Buffer (I) := Character'Val (Digit); + I := I + 1; + end loop; + Self.Write (Buffer); + end Write; + + procedure Write + (Self : in out Checkpoint_Save_State; Value : Any_Language_Kind) is + begin + Self.Write_U32 (Any_Language_Kind'Pos (Value)); + end Write; + + procedure Write + (Self : in out Checkpoint_Save_State; Value : Any_Line_State) is + begin + Self.Write_U8 (Any_Line_State'Pos (Value)); + end Write; + + procedure Write + (Self : in out Checkpoint_Save_State; Value : Local_Source_Location) is + begin + Self.Write_Integer (Value.Line); + Self.Write_Integer (Value.Column); + end Write; + + procedure Write + (Self : in out Checkpoint_Save_State; + Value : Local_Source_Location_Range) is + begin + Self.Write (Value.First_Sloc); + Self.Write (Value.Last_Sloc); + end Write; + + procedure Write + (Self : in out Checkpoint_Save_State; Value : Source_Location) is + begin + Self.Write_SFI (Value.Source_File); + Self.Write (Value.L); + end Write; + + procedure Write + (Self : in out Checkpoint_Save_State; Value : Source_Location_Range) is + begin + Self.Write_SFI (Value.Source_File); + Self.Write (Value.L); + end Write; + + procedure Write (Self : in out Checkpoint_Save_State; Value : String) is + begin + String'Write (Self.Stream, Value); + end Write; + + procedure Write (Self : in out Checkpoint_Save_State; Value : Tristate) is + begin + Self.Write_U8 (Tristate'Pos (Value)); + end Write; + + procedure Write + (Self : in out Checkpoint_Save_State; Value : Unbounded_String) + is + S : Big_String_Access; + L : Natural; + begin + Get_String (Value, S, L); + Self.Write_Unbounded (S.all (1 .. L)); + end Write; + + --------------------- + -- Write_Unbounded -- + --------------------- + + procedure Write_Unbounded + (Self : in out Checkpoint_Save_State; Value : String) is + begin + Self.Write_Integer (Value'First); + Self.Write_Integer (Value'Last); + Self.Write (Value); + end Write_Unbounded; + + --------------- + -- Write_Map -- + --------------- + + procedure Write_Map + (Self : in out Checkpoint_Save_State; Map : Map_Type) + is + procedure Process (Position : Cursor_Type); + -- Write the key/element couple designated by Position to the checkpoint + + procedure Process (Key : Key_Type; Element : Element_Type); + -- Write the Key/Element couple to the checkpoint + + ------------- + -- Process -- + ------------- + + procedure Process (Position : Cursor_Type) is + begin + Query_Element (Position, Process'Access); + end Process; + + procedure Process (Key : Key_Type; Element : Element_Type) is + begin + Write_Key (Self, Key); + Write_Element (Self, Element); + end Process; + + -- Start of processing for Write_Map + + begin + Self.Write_Count (Length (Map)); + Iterate (Map, Process'Access); + end Write_Map; + + --------------- + -- Write_Set -- + --------------- + + procedure Write_Set + (Self : in out Checkpoint_Save_State; Set : Set_Type) + is + procedure Process (Position : Cursor_Type); + -- Write the element designated by Position to the checkpoint + + procedure Process (Element : Element_Type); + -- Write Element to the checkpoint + + ------------- + -- Process -- + ------------- + + procedure Process (Position : Cursor_Type) is + begin + Query_Element (Position, Process'Access); + end Process; + + procedure Process (Element : Element_Type) is + begin + Write_Element (Self, Element); + end Process; + + -- Start of processing for Write_Set + + begin + Self.Write_Count (Length (Set)); + Iterate (Set, Process'Access); + end Write_Set; + + ---------------- + -- Write_Tree -- + ---------------- + + procedure Write_Tree + (Self : in out Checkpoint_Save_State; Tree : Multiway_Trees.Tree) + is + procedure Write_Children (Parent : Multiway_Trees.Cursor); + -- Write the list of Parent's child subtrees + + procedure Write_Subtree (Parent : Multiway_Trees.Cursor); + -- Write the subtree rooted at Parent + + -------------------- + -- Write_Children -- + -------------------- + + procedure Write_Children (Parent : Multiway_Trees.Cursor) is + begin + Self.Write_Count (Multiway_Trees.Child_Count (Parent)); + for Child in Tree.Iterate_Children (Parent) loop + Write_Subtree (Child); + end loop; + end Write_Children; + + ------------------- + -- Write_Subtree -- + ------------------- + + procedure Write_Subtree (Parent : Multiway_Trees.Cursor) is + begin + Write_Element (Self, Tree.Constant_Reference (Parent)); + Write_Children (Parent); + end Write_Subtree; + + -- Start of processing for Write_Tree + + begin + Self.Write_Count (Tree.Node_Count - 1); + if not Tree.Is_Empty then + Write_Children (Tree.Root); + end if; + end Write_Tree; + + ------------------ + -- Write_Vector -- + ------------------ + + procedure Write_Vector + (Self : in out Checkpoint_Save_State; Vector : Vectors.Vector) is + begin + Self.Write_I32 (Interfaces.Integer_32 (Vector.Length)); + for Element of Vector loop + Write_Element (Self, Element); + end loop; + end Write_Vector; + end Checkpoints; diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 1cc964394..347332710 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -19,6 +19,7 @@ -- This unit controls the generation and processing of coverage state -- checkpoint files for incremental coverage. +with Ada.Containers; use Ada.Containers; with Ada.Containers.Multiway_Trees; with Ada.Containers.Vectors; with Ada.Streams; use Ada.Streams; @@ -476,6 +477,145 @@ package Checkpoints is procedure Read (Self : in out Checkpoint_Load_State; Value : out Unbounded_String); + --------------------------------------------- + -- Helpers to implement checkpoints saving -- + --------------------------------------------- + + -- All the Write* procedures below serialize specific data types to + -- checkpoints. There is no overload (functions have different names) for + -- numeric data types in order to avoid ambiguities when writing for + -- instance: + -- + -- CSS.Write_U8 (My_Type'Pos (Numeric_Data)); + -- + -- Also define generic procedures to write containers (maps, multiway + -- trees, sets, vectors). + + procedure Write_BDD_Node + (Self : in out Checkpoint_Save_State; Value : BDD_Node_Id); + procedure Write_Bit_Id + (Self : in out Checkpoint_Save_State; Value : Any_Bit_Id); + procedure Write_CU (Self : in out Checkpoint_Save_State; Value : CU_Id); + procedure Write_Condition + (Self : in out Checkpoint_Save_State; Value : Any_Condition_Index); + procedure Write_Count + (Self : in out Checkpoint_Save_State; Value : Count_Type); + procedure Write_I32 + (Self : in out Checkpoint_Save_State; Value : Interfaces.Integer_32); + procedure Write_Inst (Self : in out Checkpoint_Save_State; Value : Inst_Id); + procedure Write_Integer + (Self : in out Checkpoint_Save_State; Value : Integer); + procedure Write_PC (Self : in out Checkpoint_Save_State; Value : Pc_Type); + procedure Write_SCO (Self : in out Checkpoint_Save_State; Value : SCO_Id); + procedure Write_SFI + (Self : in out Checkpoint_Save_State; Value : Source_File_Index); + procedure Write_U8 + (Self : in out Checkpoint_Save_State; Value : Interfaces.Unsigned_8); + procedure Write_U16 + (Self : in out Checkpoint_Save_State; Value : Interfaces.Unsigned_16); + procedure Write_U32 + (Self : in out Checkpoint_Save_State; Value : Interfaces.Unsigned_32); + procedure Write_U64 + (Self : in out Checkpoint_Save_State; Value : Interfaces.Unsigned_64); + + procedure Write (Self : in out Checkpoint_Save_State; Value : Boolean); + procedure Write + (Self : in out Checkpoint_Save_State; Value : Compilation_Unit); + procedure Write + (Self : in out Checkpoint_Save_State; + Value : SC_Obligations.Fingerprint_Type); + procedure Write + (Self : in out Checkpoint_Save_State; Value : Any_Language_Kind); + procedure Write + (Self : in out Checkpoint_Save_State; Value : Any_Line_State); + procedure Write + (Self : in out Checkpoint_Save_State; Value : Local_Source_Location); + procedure Write + (Self : in out Checkpoint_Save_State; + Value : Local_Source_Location_Range); + procedure Write + (Self : in out Checkpoint_Save_State; Value : Source_Location); + procedure Write + (Self : in out Checkpoint_Save_State; Value : Source_Location_Range); + procedure Write (Self : in out Checkpoint_Save_State; Value : String); + procedure Write (Self : in out Checkpoint_Save_State; Value : Tristate); + procedure Write + (Self : in out Checkpoint_Save_State; Value : Unbounded_String); + + procedure Write_Unbounded + (Self : in out Checkpoint_Save_State; Value : String); + + generic + type Key_Type is private; + type Element_Type is private; + type Map_Type is private; + type Cursor_Type is private; + + with function Length (Self : Map_Type) return Count_Type is <>; + with procedure Iterate + (Self : Map_Type; + Process : not null access procedure (Position : Cursor_Type)); + with procedure Query_Element + (Position : Cursor_Type; + Process : not null access + procedure (Key : Key_Type; Element : Element_Type)); + + with procedure Write_Key + (Self : in out Checkpoint_Save_State; Key : Key_Type); + with procedure Write_Element + (Self : in out Checkpoint_Save_State; Element : Element_Type); + procedure Write_Map + (Self : in out Checkpoint_Save_State; Map : Map_Type); + -- Generic implementation to write a map to a checkpoint. Since there are + -- two flavors for maps (ordered and hashed), do not take a instantiated + -- formal package, but rather the only three map primitives that we need: + -- Length, Iterate and Query_Element. + + generic + type Element_Type is private; + type Set_Type is private; + type Cursor_Type is private; + + with function Length (Self : Set_Type) return Count_Type is <>; + with procedure Iterate + (Self : Set_Type; + Process : not null access procedure (Position : Cursor_Type)); + with procedure Query_Element + (Position : Cursor_Type; + Process : not null access procedure (Element : Element_Type)); + + with procedure Write_Element + (Self : in out Checkpoint_Save_State; Element : Element_Type); + procedure Write_Set + (Self : in out Checkpoint_Save_State; Set : Set_Type); + -- Generic implementation to write a set to a checkpoint. Since there are + -- two flavors for sets (ordered and hashed), do not take a instantiated + -- formal package, but rather the only three set primitives that we need: + -- Length, Iterate and Query_Element. + + generic + type Element_Type is private; + with function "=" (Left, Right : Element_Type) return Boolean is <>; + with package Multiway_Trees is new Ada.Containers.Multiway_Trees + (Element_Type, "="); + with procedure Write_Element + (Self : in out Checkpoint_Save_State; Element : Element_Type); + procedure Write_Tree + (Self : in out Checkpoint_Save_State; Tree : Multiway_Trees.Tree); + -- Generic implementation to write a multiway tree from a checkpoint + + generic + type Index_Type is range <>; + type Element_Type is private; + with function "=" (Left, Right : Element_Type) return Boolean is <>; + with package Vectors is new Ada.Containers.Vectors + (Index_Type, Element_Type, "="); + with procedure Write_Element + (Self : in out Checkpoint_Save_State; Element : Element_Type); + procedure Write_Vector + (Self : in out Checkpoint_Save_State; Vector : Vectors.Vector); + -- Generic implementation to write a vector tree to a checkpoint + private type SFI_Map_Array is diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index c956cc7e3..65f23055d 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -76,6 +76,15 @@ package body Coverage.Source is 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); @@ -152,12 +161,23 @@ package body Coverage.Source is 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, @@ -165,6 +185,13 @@ package body Coverage.Source is 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; @@ -462,17 +489,17 @@ package body Coverage.Source is procedure Checkpoint_Save (CSS : access Checkpoint_Save_State) is begin - String'Output (CSS, Tag_Provider_Name); - SCI_Vector_Vectors.Vector'Write (CSS.Stream, SCI_Vector); + 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 - Boolean'Output (CSS, Unit_List_Invalidated); + CSS.Write (Unit_List_Invalidated); if not Unit_List_Invalidated then - Ada.Containers.Count_Type'Output (CSS, Unit_List.Length); + CSS.Write_Count (Unit_List.Length); for N of Unit_List loop - Compilation_Unit'Output (CSS, N); + Write (CSS.all, N); end loop; end if; end if; @@ -2468,6 +2495,40 @@ package body Coverage.Source is end if; end Read; + ----------- + -- Write -- + ----------- + + procedure Write + (CSS : in out Checkpoint_Save_State; + Value : RW_Source_Coverage_Info_Access) is + begin + CSS.Write_U8 (SCO_Kind'Pos (Value.Kind)); + CSS.Write_I32 (Interfaces.Integer_32 (Value.Tag)); + for S of Value.State loop + CSS.Write (S); + end loop; + + case Value.Kind is + when Statement => + CSS.Write (Value.Basic_Block_Has_Code); + CSS.Write (Value.Executed); + CSS.Write (Value.Line_Executed); + + when Decision => + CSS.Write (Value.Outcome_Taken (False)); + CSS.Write (Value.Outcome_Taken (True)); + + CSS.Write (Value.Known_Outcome_Taken (False)); + CSS.Write (Value.Known_Outcome_Taken (True)); + + Write (CSS, Value.Evaluations); + + when others => + null; + end case; + end Write; + ------------------------ -- Report_If_Excluded -- ------------------------ diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 61e6b3bba..2c1fdfc97 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -18,7 +18,6 @@ with Ada.Containers.Hashed_Maps; with Ada.Directories; -with Ada.Streams; with Ada.Unchecked_Deallocation; with System; @@ -1860,12 +1859,11 @@ package body Files_Table is --------------------- procedure Checkpoint_Save (CSS : access Checkpoint_Save_State) is - S : access Ada.Streams.Root_Stream_Type'Class renames CSS.Stream; begin -- 1) Output first and last SFIs - Source_File_Index'Write (S, Files_Table.First_Index); - Source_File_Index'Write (S, Files_Table.Last_Index); + CSS.Write_SFI (Files_Table.First_Index); + CSS.Write_SFI (Files_Table.Last_Index); -- 2) Output file table info for each file -- Note that we need LI files there, not just source files with @@ -1875,20 +1873,22 @@ package body Files_Table is declare FI : File_Info_Access renames File_Vectors.Element (FI_C); begin - Source_File_Index'Write (S, File_Vectors.To_Index (FI_C)); - String'Output (S, (if FI.Full_Name /= null - then FI.Full_Name.all - else FI.Simple_Name.all)); - File_Kind'Write (S, FI.Kind); - Boolean'Write (S, FI.Indexed_Simple_Name); + CSS.Write_SFI (File_Vectors.To_Index (FI_C)); + CSS.Write_Unbounded + (String_Access' + (if FI.Full_Name /= null + then FI.Full_Name + else FI.Simple_Name).all); + CSS.Write_U8 (File_Kind'Pos (FI.Kind)); + CSS.Write (FI.Indexed_Simple_Name); if FI.Kind = Library_File then pragma Assert (FI.Main_Source /= No_Source_File); - Source_File_Index'Write (S, FI.Main_Source); + CSS.Write_SFI (FI.Main_Source); elsif FI.Kind = Source_File then - Any_Ignore_Status'Write (S, FI.Ignore_Status); - Boolean'Write (S, FI.Unit.Known); + CSS.Write_U8 (Any_Ignore_Status'Pos (FI.Ignore_Status)); + CSS.Write (FI.Unit.Known); if FI.Unit.Known then - Compilation_Unit'Output (S, FI.Unit.Name); + CSS.Write (FI.Unit.Name); end if; end if; end; @@ -1896,7 +1896,7 @@ package body Files_Table is -- No_Source_File marks end of file table info - Source_File_Index'Write (S, No_Source_File); + CSS.Write_SFI (No_Source_File); end Checkpoint_Save; ---------------------- diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index 6788bc77c..0f6ef0e22 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -28,10 +28,8 @@ package body Instrument.Checkpoints is procedure Checkpoint_Save (CSS : access Checkpoint_Save_State) is begin - Instrumented_Unit_To_CU_Maps.Map'Write - (CSS.Stream, Instrumented_Unit_CUs); - SFI_To_PP_Cmd_Maps.Map'Write - (CSS.Stream, PP_Cmds); + Write (CSS.all, Instrumented_Unit_CUs); + Write (CSS.all, PP_Cmds); end Checkpoint_Save; ---------------------- diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 188e04924..0aafedd31 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -95,6 +95,32 @@ package body Instrument is Value := CUP; end Read; + ----------- + -- Write -- + ----------- + + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; Value : Ada_Identifier) + is + begin + CSS.Write (Unbounded_String (Value)); + end Write; + + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; + Value : Compilation_Unit_Part) is + begin + CSS.Write (Value.Language_Kind); + case Value.Language_Kind is + when Unit_Based_Language => + Write (CSS, Value.Unit); + CSS.Write_U8 (Unit_Parts'Pos (Value.Part)); + + when File_Based_Language => + CSS.Write (Value.Filename); + end case; + end Write; + --------- -- "<" -- --------- diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index b540d6ebd..19c3c8bfa 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -56,6 +56,10 @@ package Instrument is Value : out Ada_Identifier); -- Read an Ada_Identifier from CLS + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; Value : Ada_Identifier); + -- Write an Ada_Identifier to CSS + package Ada_Identifier_Vectors is new Ada.Containers.Vectors (Positive, Ada_Identifier); @@ -76,6 +80,12 @@ package Instrument is Vectors => Ada_Identifier_Vectors, Read_Element => Read); + procedure Write is new Write_Vector + (Index_Type => Positive, + Element_Type => Ada_Identifier, + Vectors => Ada_Identifier_Vectors, + Write_Element => Write); + type Compilation_Unit_Part (Language_Kind : Any_Language_Kind := Unit_Based_Language) is record @@ -100,6 +110,11 @@ package Instrument is Value : out Compilation_Unit_Part); -- Read a Compilation_Unit_Part from CLS + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; + Value : Compilation_Unit_Part); + -- Write a Compilation_Unit_Part to CSS + Part_Tags : constant array (Unit_Parts) of Character := (Unit_Spec => 'S', Unit_Body => 'B', @@ -191,6 +206,17 @@ package Instrument is Read_Key => Read, Read_Element => Read); + procedure Write is new Write_Map + (Key_Type => Compilation_Unit_Part, + Element_Type => CU_Id, + Map_Type => Instrumented_Unit_To_CU_Maps.Map, + Cursor_Type => Instrumented_Unit_To_CU_Maps.Cursor, + Length => Instrumented_Unit_To_CU_Maps.Length, + Iterate => Instrumented_Unit_To_CU_Maps.Iterate, + Query_Element => Instrumented_Unit_To_CU_Maps.Query_Element, + Write_Key => Write, + Write_Element => Write_CU); + Instrumented_Unit_CUs : Instrumented_Unit_To_CU_Maps.Map; -- Associate a CU id for all instrumented units. Updated each time we -- instrument a unit (or load a checkpoint) and used each time we read a @@ -210,6 +236,17 @@ package Instrument is Read_Key => Read, Read_Element => Read); + procedure Write is new Write_Map + (Key_Type => Source_File_Index, + Element_Type => Command_Type, + Map_Type => SFI_To_PP_Cmd_Maps.Map, + Cursor_Type => SFI_To_PP_Cmd_Maps.Cursor, + Length => SFI_To_PP_Cmd_Maps.Length, + Iterate => SFI_To_PP_Cmd_Maps.Iterate, + Query_Element => SFI_To_PP_Cmd_Maps.Query_Element, + Write_Key => Write_SFI, + Write_Element => Write); + PP_Cmds : SFI_To_PP_Cmd_Maps.Map; -- Save the preprocessing command for each unit that supports it diff --git a/tools/gnatcov/mc_dc.adb b/tools/gnatcov/mc_dc.adb index 667eaa618..a798c7948 100644 --- a/tools/gnatcov/mc_dc.adb +++ b/tools/gnatcov/mc_dc.adb @@ -228,4 +228,16 @@ package body MC_DC is Value.Next_Condition := CLS.Read_Condition; end Read; + ----------- + -- Write -- + ----------- + + procedure Write (CSS : in out Checkpoint_Save_State; Value : Evaluation) is + begin + CSS.Write_SCO (Value.Decision); + Write (CSS, Value.Values); + CSS.Write (Value.Outcome); + CSS.Write_Condition (Value.Next_Condition); + end Write; + end MC_DC; diff --git a/tools/gnatcov/mc_dc.ads b/tools/gnatcov/mc_dc.ads index 5d3ae53d2..435f889dd 100644 --- a/tools/gnatcov/mc_dc.ads +++ b/tools/gnatcov/mc_dc.ads @@ -87,7 +87,16 @@ package MC_DC is Vectors => Condition_Evaluation_Vectors, Read_Element => Read); + procedure Write is new Write_Vector + (Index_Type => Condition_Index, + Element_Type => Tristate, + Vectors => Condition_Evaluation_Vectors, + Write_Element => Write); + procedure Read (CLS : in out Checkpoint_Load_State; Value : out Evaluation); -- Read an Evaluation from CLS + procedure Write (CSS : in out Checkpoint_Save_State; Value : Evaluation); + -- Write an Evalution to CSS + end MC_DC; diff --git a/tools/gnatcov/sc_obligations-bdd.adb b/tools/gnatcov/sc_obligations-bdd.adb index f298b566f..93a55365f 100644 --- a/tools/gnatcov/sc_obligations-bdd.adb +++ b/tools/gnatcov/sc_obligations-bdd.adb @@ -32,6 +32,9 @@ package body SC_Obligations.BDD is procedure Read (CLS : in out Checkpoint_Load_State; Value : out BDD_Node); -- Read a BDD_Node from CLS + procedure Write (CSS : in out Checkpoint_Save_State; Value : BDD_Node); + -- Write a BDD_Node to CSS + procedure Read_BDD_Vector is new Read_Vector (Index_Type => Valid_BDD_Node_Id, Element_Type => BDD_Node, @@ -39,6 +42,13 @@ package body SC_Obligations.BDD is Vectors => BDD_Vectors, Read_Element => Read); + procedure Write_BDD_Vector is new Write_Vector + (Index_Type => Valid_BDD_Node_Id, + Element_Type => BDD_Node, + "=" => "=", + Vectors => BDD_Vectors, + Write_Element => Write); + package Arcs_Stacks is new Ada.Containers.Vectors (Index_Type => Natural, @@ -86,47 +96,6 @@ package body SC_Obligations.BDD is end if; end Allocate; - ----------- - -- Write -- - ----------- - - procedure Write - (S : access Root_Stream_Type'Class; - V : BDD_Type) - is - begin - SCO_Id'Write (S, V.Decision); - BDD_Node_Id'Write (S, V.Root_Condition); - BDD_Node_Id'Write (S, V.First_Node); - BDD_Node_Id'Write (S, V.Last_Node); - BDD_Node_Id'Write (S, V.First_Multipath_Condition); - Reachability'Write (S, V.Reachable_Outcomes); - Natural'Write (S, V.Path_Count); - end Write; - - procedure Write - (S : access Root_Stream_Type'Class; - V : BDD_Node) - is - begin - BDD_Node_Kind'Write (S, V.Kind); - - case V.Kind is - when Outcome => - Boolean'Write (S, V.Decision_Outcome); - - when Condition => - BDD_Node_Id'Write (S, V.Parent); - Boolean'Write (S, V.Parent_Value); - SCO_Id'Write (S, V.C_SCO); - Destinations'Write (S, V.Dests); - Natural'Write (S, V.Path_Offset); - - when Jump => - BDD_Node_Id'Write (S, V.Dest); - end case; - end Write; - ---------- -- Read -- ---------- @@ -179,6 +148,54 @@ package body SC_Obligations.BDD is Read_BDD_Vector (CLS, Vector); end Read; + ----------- + -- Write -- + ----------- + + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; Value : BDD_Type) is + begin + CSS.Write_SCO (Value.Decision); + CSS.Write_BDD_Node (Value.Root_Condition); + CSS.Write_BDD_Node (Value.First_Node); + CSS.Write_BDD_Node (Value.Last_Node); + CSS.Write_BDD_Node (Value.First_Multipath_Condition); + + CSS.Write (Value.Reachable_Outcomes (False)); + CSS.Write (Value.Reachable_Outcomes (True)); + + CSS.Write_Integer (Value.Path_Count); + end Write; + + procedure Write (CSS : in out Checkpoint_Save_State; Value : BDD_Node) is + begin + CSS.Write_U8 (BDD_Node_Kind'Pos (Value.Kind)); + + case Value.Kind is + when Outcome => + CSS.Write (Value.Decision_Outcome); + + when Condition => + CSS.Write_BDD_Node (Value.Parent); + CSS.Write (Value.Parent_Value); + CSS.Write_SCO (Value.C_SCO); + CSS.Write_BDD_Node (Value.Dests (False)); + CSS.Write_BDD_Node (Value.Dests (True)); + CSS.Write_Integer (Value.Path_Offset); + + when Jump => + CSS.Write_BDD_Node (Value.Dest); + end case; + end Write; + + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; + Vector : BDD_Vectors.Vector) + is + begin + Write_BDD_Vector (CSS, Vector); + end Write; + --------------------- -- Enumerate_Paths -- --------------------- diff --git a/tools/gnatcov/sc_obligations-bdd.ads b/tools/gnatcov/sc_obligations-bdd.ads index 559d9259f..1b0cdae5d 100644 --- a/tools/gnatcov/sc_obligations-bdd.ads +++ b/tools/gnatcov/sc_obligations-bdd.ads @@ -18,8 +18,6 @@ -- Binary Decision Diagrams -with Ada.Streams; use Ada.Streams; - private package SC_Obligations.BDD is Path_Count_Limit : Natural := 1024; @@ -77,13 +75,6 @@ private package SC_Obligations.BDD is pragma Warnings (Off, "* is not referenced"); -- Work around compiler bug: bogus warning??? - procedure Write - (S : access Root_Stream_Type'Class; - V : BDD_Node); - pragma Warnings (On, "* is not referenced"); - - for BDD_Node'Write use Write; - package BDD_Vectors is new Ada.Containers.Vectors (Index_Type => Valid_BDD_Node_Id, @@ -94,6 +85,11 @@ private package SC_Obligations.BDD is Vector : out BDD_Vectors.Vector); -- Read a BDD_Vectors.Vector from CLS + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; + Vector : BDD_Vectors.Vector); + -- Write a BDD_Vectors.Vector to CSS + type Reachability is array (Boolean) of Boolean; type BDD_Type is record @@ -118,18 +114,14 @@ private package SC_Obligations.BDD is -- Count of paths from root condition to any outcome end record; - pragma Warnings (Off, "* is not referenced"); - procedure Write - (S : access Root_Stream_Type'Class; - V : BDD_Type); - pragma Warnings (On, "* is not referenced"); - - for BDD_Type'Write use Write; - procedure Read (CLS : in out Checkpoints.Checkpoint_Load_State; Value : out BDD_Type); -- Read a BDD_Type from CLS + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; Value : BDD_Type); + -- Write a BDD_Type to CSS + procedure Allocate (BDD_Vector : in out BDD_Vectors.Vector; BDD : in out BDD_Type; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index b6f287785..0310f01e0 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -18,11 +18,10 @@ -- Source Coverage Obligations -with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Exceptions; -with Ada.Strings.Fixed; use Ada.Strings.Fixed; -with Ada.Streams; use Ada.Streams; -with Ada.Text_IO; use Ada.Text_IO; +with Ada.Strings.Fixed; use Ada.Strings.Fixed; +with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Deallocation; with Interfaces; @@ -143,12 +142,6 @@ package body SC_Obligations is procedure Free (CU : in out CU_Info); - pragma Warnings (Off, "* is not referenced"); - procedure Write (S : access Root_Stream_Type'Class; V : CU_Info); - pragma Warnings (On, "* is not referenced"); - - for CU_Info'Write use Write; - function Has_SCOs (CUI : CU_Info) return Boolean is (CUI.First_SCO <= CUI.Last_SCO); @@ -456,12 +449,6 @@ package body SC_Obligations is end case; end record; - pragma Warnings (Off, "* is not referenced"); - procedure Write (S : access Root_Stream_Type'Class; V : SCO_Descriptor); - pragma Warnings (On, "* is not referenced"); - - for SCO_Descriptor'Write use Write; - Removed_SCO_Descriptor : constant SCO_Descriptor := (Kind => Removed); package SCO_Vectors is @@ -648,6 +635,90 @@ package body SC_Obligations is -- either an already existing CU_Id (if the unit was already known), -- or a newly assigned one (if not). + ----------------------------------------- + -- Helper routines for Checkpoint_Save -- + ----------------------------------------- + + procedure Write is new Write_Vector + (Index_Type => Pos, + Element_Type => Source_File_Index, + "=" => "=", + Vectors => SFI_Vectors, + Write_Element => Write_SFI); + + procedure Write + (CSS : in out Checkpoint_Save_State; Value : Expansion_Info); + -- Write an Expansion_Info to CSS + + procedure Write (CSS : in out Checkpoint_Save_State; Value : PP_Info); + -- Write a PP_Info to CSS + + procedure Write is new Write_Map + (Key_Type => SCO_Id, + Element_Type => PP_Info, + Map_Type => SCO_PP_Info_Maps.Map, + Cursor_Type => SCO_PP_Info_Maps.Cursor, + Length => SCO_PP_Info_Maps.Length, + Iterate => SCO_PP_Info_Maps.Iterate, + Query_Element => SCO_PP_Info_Maps.Query_Element, + Write_Key => Write_SCO, + Write_Element => Write); + + procedure Write (CSS : in out Checkpoint_Save_State; Value : Scope_Entity); + -- Write a Scope_Entity to CSS + + procedure Write is new Write_Tree + (Element_Type => Scope_Entity, + "=" => "=", + Multiway_Trees => Scope_Entities_Trees, + Write_Element => Write); + + procedure Write (CSS : in out Checkpoint_Save_State; Value : CU_Info); + -- Write a CU_Info to CSS + + procedure Write is new Write_Vector + (Valid_CU_Id, CU_Info, "=", CU_Info_Vectors, Write); + -- Write a vector of CU_Info records to CSS + + procedure Write (CSS : in out Checkpoint_Save_State; Value : Inst_Info); + -- Write an Inst_Info to CSS + + procedure Write is new Write_Vector + (Index_Type => Valid_Inst_Id, + Element_Type => Inst_Info, + "=" => "=", + Vectors => Inst_Info_Vectors, + Write_Element => Write); + + procedure Write is new Write_Set + (Element_Type => Pc_Type, + Set_Type => PC_Sets.Set, + Cursor_Type => PC_Sets.Cursor, + Length => PC_Sets.Length, + Iterate => PC_Sets.Iterate, + Query_Element => PC_Sets.Query_Element, + Write_Element => Write_PC); + + procedure Write + (CSS : in out Checkpoint_Save_State; Value : SCO_Descriptor); + -- Write a SCO_Descriptor to CSS + + procedure Write is new Write_Set + (Element_Type => SCO_Id, + Set_Type => SCO_Sets.Set, + Cursor_Type => SCO_Sets.Cursor, + Length => SCO_Sets.Length, + Iterate => SCO_Sets.Iterate, + Query_Element => SCO_Sets.Query_Element, + Write_Element => Write_SCO); + + procedure Write is new Write_Vector + (Index_Type => Valid_SCO_Id, + Element_Type => SCO_Descriptor, + "=" => "=", + Vectors => SCO_Vectors, + Write_Element => Write); + ------------------ -- Local tables -- ------------------ @@ -1685,6 +1756,154 @@ package body SC_Obligations is end if; end Checkpoint_Load_Unit; + ----------- + -- Write -- + ----------- + + procedure Write (CSS : in out Checkpoint_Save_State; Value : Expansion_Info) + is + begin + CSS.Write (Value.Macro_Name); + CSS.Write (Value.Sloc); + end Write; + + procedure Write (CSS : in out Checkpoint_Save_State; Value : PP_Info) is + begin + CSS.Write_U8 (SCO_PP_Kind'Pos (Value.Kind)); + CSS.Write (Value.Actual_Source_Range); + CSS.Write (Value.PP_Source_Range); + + CSS.Write_Count (Value.Expansion_Stack.Length); + for EI of Value.Expansion_Stack loop + Write (CSS, EI); + end loop; + + case Value.Kind is + when In_Expansion => + Write (CSS, Value.Definition_Loc); + + when others => + null; + end case; + end Write; + + procedure Write (CSS : in out Checkpoint_Save_State; Value : Scope_Entity) + is + begin + CSS.Write_SCO (Value.From); + CSS.Write_SCO (Value.To); + + CSS.Write (Value.Name); + CSS.Write (Value.Sloc); + + CSS.Write_SFI (Value.Identifier.Decl_SFI); + CSS.Write_Integer (Value.Identifier.Decl_Line); + end Write; + + procedure Write (CSS : in out Checkpoint_Save_State; Value : CU_Info) is + begin + CSS.Write_U8 (SCO_Provider'Pos (Value.Provider)); + CSS.Write_SFI (Value.Origin); + CSS.Write_SFI (Value.Main_Source); + CSS.Write_SCO (Value.First_SCO); + CSS.Write_SCO (Value.Last_SCO); + CSS.Write_Inst (Value.First_Instance); + CSS.Write_Inst (Value.Last_Instance); + Write (CSS, Value.Deps); + CSS.Write (Value.Has_Code); + CSS.Write (Value.Fingerprint); + Write (CSS, Value.PP_Info_Map); + + case Value.Provider is + when Compiler => + null; + + when Instrumenter => + if CSS.Purpose_Of = Instrumentation then + CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'First); + CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'Last); + for SCO of Value.Bit_Maps.Statement_Bits.all loop + CSS.Write_SCO (SCO); + end loop; + + CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'First); + CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'Last); + for Info of Value.Bit_Maps.Decision_Bits.all loop + CSS.Write_SCO (Info.D_SCO); + CSS.Write (Info.Outcome); + end loop; + + CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'First); + CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'Last); + for Info of Value.Bit_Maps.MCDC_Bits.all loop + CSS.Write_SCO (Info.D_SCO); + CSS.Write_Integer (Info.Path_Index); + end loop; + + CSS.Write (Value.Bit_Maps_Fingerprint); + end if; + end case; + + Write (CSS, Value.Scope_Entities); + end Write; + + procedure Write + (CSS : in out Checkpoint_Save_State; Value : Inst_Info) is + begin + CSS.Write (Value.Sloc); + CSS.Write_Inst (Value.Enclosing_Instance); + CSS.Write_CU (Value.Comp_Unit); + end Write; + + procedure Write + (CSS : in out Checkpoint_Save_State; Value : SCO_Descriptor) is + begin + CSS.Write_U8 (SCO_Kind'Pos (Value.Kind)); + if Value.Kind = Removed then + return; + end if; + + CSS.Write_CU (Value.Origin); + CSS.Write (Value.Sloc_Range); + CSS.Write_SCO (Value.Parent); + + case Value.Kind is + when Removed => + raise Program_Error with "unreachable code"; + + when Statement => + CSS.Write_U8 (Statement_Kind'Pos (Value.S_Kind)); + CSS.Write_SCO (Value.Dominant); + CSS.Write (Value.Dominant_Value); + CSS.Write (Value.Dominant_Sloc); + CSS.Write (Value.Handler_Range); + CSS.Write_U8 (Pragma_Id'Pos (Value.Pragma_Name)); + + when Condition => + CSS.Write (Value.Value); + Write (CSS, Value.PC_Set); + CSS.Write_BDD_Node (Value.BDD_Node); + CSS.Write_Condition (Value.Index); + + when Decision => + CSS.Write_SCO (Value.Expression); + CSS.Write_U8 (Decision_Kind'Pos (Value.D_Kind)); + CSS.Write (Value.Control_Location); + CSS.Write_Condition (Value.Last_Cond_Index); + BDD.Write (CSS, Value.Decision_BDD); + CSS.Write (Value.Degraded_Origins); + CSS.Write_U8 (Aspect_Id'Pos (Value.Aspect_Name)); + CSS.Write_Integer (Value.Path_Count); + + when Operator => + CSS.Write_U8 (Operand_Position'Pos (Left)); + CSS.Write_U8 (Operand_Position'Pos (Right)); + CSS.Write_SCO (Value.Operands (Left)); + CSS.Write_SCO (Value.Operands (Right)); + CSS.Write_U8 (Operator_Kind'Pos (Value.Op_Kind)); + end case; + end Write; + ---------- -- Free -- ---------- @@ -1706,45 +1925,6 @@ package body SC_Obligations is end if; end Free; - -- Procedures below use comparisons on checkpoint format versions - - ----------- - -- Write -- - ----------- - - procedure Write (S : access Root_Stream_Type'Class; V : CU_Info) is - CLS : Stateful_Stream renames Stateful_Stream (S.all); - begin - SCO_Provider'Write (S, V.Provider); - Source_File_Index'Write (S, V.Origin); - Source_File_Index'Write (S, V.Main_Source); - SCO_Id'Write (S, V.First_SCO); - SCO_Id'Write (S, V.Last_SCO); - Inst_Id'Write (S, V.First_Instance); - Inst_Id'Write (S, V.Last_Instance); - SFI_Vector'Write (S, V.Deps); - Boolean'Write (S, V.Has_Code); - Fingerprint_Type'Write (S, V.Fingerprint); - - SCO_PP_Info_Maps.Map'Write (S, V.PP_Info_Map); - - case V.Provider is - when Compiler => - null; - when Instrumenter => - if CLS.Purpose_Of = Instrumentation then - Statement_Bit_Map'Output - (S, V.Bit_Maps.Statement_Bits.all); - Decision_Bit_Map'Output - (S, V.Bit_Maps.Decision_Bits.all); - MCDC_Bit_Map'Output - (S, V.Bit_Maps.MCDC_Bits.all); - Fingerprint_Type'Write (S, V.Bit_Maps_Fingerprint); - end if; - end case; - Scope_Entities_Tree'Write (S, V.Scope_Entities); - end Write; - --------------------- -- Checkpoint_Load -- --------------------- @@ -1892,15 +2072,14 @@ package body SC_Obligations is --------------------- procedure Checkpoint_Save (CSS : access Checkpoint_Save_State) is - S : constant access Root_Stream_Type'Class := CSS.all'Access; begin - CU_Info_Vectors.Vector'Write (S, CU_Vector); - ALI_Annotation_Maps.Map'Write (S, ALI_Annotations); - Inst_Info_Vectors.Vector'Write (S, Inst_Vector); - BDD.BDD_Vectors.Vector'Write (S, BDD_Vector); - SCO_Vectors.Vector'Write (S, SCO_Vector); - SCO_Sets.Set'Write (S, Non_Instr_SCOs); - SCO_Sets.Set'Write (S, Non_Instr_MCDC_SCOs); + Write (CSS.all, CU_Vector); + Write (CSS.all, ALI_Annotations); + Write (CSS.all, Inst_Vector); + BDD.Write (CSS.all, BDD_Vector); + Write (CSS.all, SCO_Vector); + Write (CSS.all, Non_Instr_SCOs); + Write (CSS.all, Non_Instr_MCDC_SCOs); end Checkpoint_Save; --------------- @@ -4051,61 +4230,6 @@ package body SC_Obligations is end if; end Map_Tag; - ----------- - -- Write -- - ----------- - - procedure Write (S : access Root_Stream_Type'Class; V : SCO_Descriptor) is - begin - SCO_Kind'Output (S, V.Kind); - if V.Kind = Removed then - return; - end if; - - CU_Id'Output (S, V.Origin); - Source_Location_Range'Output (S, V.Sloc_Range); - SCO_Id'Output (S, V.Parent); - - case V.Kind is - when Removed => - raise Program_Error with "unreachable code"; - - when Statement => - Statement_Kind'Output (S, V.S_Kind); - SCO_Id'Output (S, V.Dominant); - Tristate'Output (S, V.Dominant_Value); - Source_Location'Output (S, V.Dominant_Sloc); - Source_Location_Range'Output (S, V.Handler_Range); - Pragma_Id'Output (S, V.Pragma_Name); - - when Condition => - Tristate'Output (S, V.Value); - PC_Sets.Set'Output (S, V.PC_Set); - BDD_Node_Id'Output (S, V.BDD_Node); - Condition_Index'Output (S, V.Index); - - when Decision | Operator => - case V.Kind is - when Decision => - SCO_Id'Output (S, V.Expression); - Decision_Kind'Output (S, V.D_Kind); - Source_Location'Output (S, V.Control_Location); - Any_Condition_Index'Output (S, V.Last_Cond_Index); - BDD.BDD_Type'Output (S, V.Decision_BDD); - Boolean'Output (S, V.Degraded_Origins); - Aspect_Id'Output (S, V.Aspect_Name); - Natural'Output (S, V.Path_Count); - - when Operator => - Operand_Pair'Output (S, V.Operands); - Operator_Kind'Output (S, V.Op_Kind); - - when others => - null; - end case; - end case; - end Write; - ------------------- -- Next_BDD_Node -- ------------------- diff --git a/tools/gnatcov/strings.adb b/tools/gnatcov/strings.adb index 97bde28b4..6a45c47da 100644 --- a/tools/gnatcov/strings.adb +++ b/tools/gnatcov/strings.adb @@ -127,6 +127,41 @@ package body Strings is Read (CLS, Value); end Read; + ----------- + -- Write -- + ----------- + + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; + Value : String_Vectors.Vector) + is + procedure Write is new Write_Vector + (Index_Type => Natural, + Element_Type => Ada.Strings.Unbounded.Unbounded_String, + "=" => Ada.Strings.Unbounded."=", + Vectors => String_Vectors, + Write_Element => Write); + begin + Write (CSS, Value); + end Write; + + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; Value : String_Maps.Map) + is + procedure Write is new Write_Map + (Key_Type => Ada.Strings.Unbounded.Unbounded_String, + Element_Type => Ada.Strings.Unbounded.Unbounded_String, + Map_Type => String_Maps.Map, + Cursor_Type => String_Maps.Cursor, + Length => String_Maps.Length, + Iterate => String_Maps.Iterate, + Query_Element => String_Maps.Query_Element, + Write_Key => Write, + Write_Element => Write); + begin + Write (CSS, Value); + end Write; + -------------------- -- To_String_Sets -- -------------------- diff --git a/tools/gnatcov/strings.ads b/tools/gnatcov/strings.ads index 812b7b2db..1ec365475 100644 --- a/tools/gnatcov/strings.ads +++ b/tools/gnatcov/strings.ads @@ -74,6 +74,11 @@ package Strings is Value : out String_Vectors.Vector); -- Read a String_Vectors.Vector from CLS + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; + Value : String_Vectors.Vector); + -- Write a String_Vectors.Vector to CSS + package String_Maps is new Ada.Containers.Ordered_Maps (Key_Type => Ada.Strings.Unbounded.Unbounded_String, Element_Type => Ada.Strings.Unbounded.Unbounded_String, @@ -85,6 +90,10 @@ package Strings is Value : out String_Maps.Map); -- Read a String_Maps.Map from CLS + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; Value : String_Maps.Map); + -- Write a String_Maps.Map to CSS + package String_Sets is new Ada.Containers.Ordered_Sets (Element_Type => Ada.Strings.Unbounded.Unbounded_String, "<" => Ada.Strings.Unbounded.Less_Case_Insensitive, diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index cfbbea374..45947577d 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -80,6 +80,18 @@ package body Subprocesses is Read (CLS, Value.Environment); end Read; + ----------- + -- Write -- + ----------- + + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; Value : Command_Type) is + begin + CSS.Write (Value.Command); + Write (CSS, Value.Arguments); + Write (CSS, Value.Environment); + end Write; + ---------------- -- Append_Arg -- ---------------- diff --git a/tools/gnatcov/subprocesses.ads b/tools/gnatcov/subprocesses.ads index 292525e8f..ae91ccaf4 100644 --- a/tools/gnatcov/subprocesses.ads +++ b/tools/gnatcov/subprocesses.ads @@ -60,6 +60,10 @@ package Subprocesses is Value : out Command_Type); -- Read a Command_Type from CLS + procedure Write + (CSS : in out Checkpoints.Checkpoint_Save_State; Value : Command_Type); + -- Write a Command_Type to CSS + Null_Command : constant Command_Type := (others => <>); procedure Append_Arg (Cmd : in out Command_Type; Arg : String); diff --git a/tools/gnatcov/traces_files_registry.adb b/tools/gnatcov/traces_files_registry.adb index 15a29d4cf..4a6f5d97b 100644 --- a/tools/gnatcov/traces_files_registry.adb +++ b/tools/gnatcov/traces_files_registry.adb @@ -332,7 +332,7 @@ package body Traces_Files_Registry is (Coverage.To_String (Context.all)); begin for TF of Files loop - Unbounded_String'Output (CSS, TF.Filename); + CSS.Write (TF.Filename); declare -- If this trace file does not come from a checkpoint (TF.Context @@ -344,17 +344,17 @@ package body Traces_Files_Registry is then This_Context else TF.Context); begin - Trace_File_Kind'Write (CSS, TF.Kind); - Unbounded_String'Write (CSS, TF_Context); - Unbounded_String'Write (CSS, TF.Program_Name); - Unbounded_String'Write (CSS, TF.Time); - Unbounded_String'Write (CSS, TF.User_Data); + CSS.Write_U8 (Trace_File_Kind'Pos (TF.Kind)); + CSS.Write (TF_Context); + CSS.Write (TF.Program_Name); + CSS.Write (TF.Time); + CSS.Write (TF.User_Data); end; end loop; -- Mark end of list with empty string - String'Output (CSS, ""); + CSS.Write_Unbounded (""); end Checkpoint_Save; ---------------------- From ccbfaacbedeac0c120de8dc0d4b75fded5c357c1 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 30 Nov 2023 14:02:07 +0000 Subject: [PATCH 0525/1483] files_table.adb: remove useless assignment --- tools/gnatcov/files_table.adb | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 2c1fdfc97..c282007ba 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -2027,7 +2027,6 @@ package body Files_Table is when Source_File => FE := (Kind => Source_File, others => <>); - FE.Ignore_Status := Unknown; FE.Unit := (Known => False); FE.Ignore_Status := Any_Ignore_Status'Val (CLS.Read_U8); declare From 0e3eb6a0838c4afd229701f6c1209fcb842a4e61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Fri, 3 Nov 2023 16:47:25 +0100 Subject: [PATCH 0526/1483] Fix assertion coverage reporting Fix assertion level enabling, coverage obligation stats computing for ATCC, and adapt SCO kind image for better xml reporting --- testsuite/tests/O212-062-xml/main.adb | 28 ++++ .../src-traces-index.xml.expected | 147 ++++++++++++++++++ testsuite/tests/O212-062-xml/test.opt | 1 + testsuite/tests/O212-062-xml/test.py | 26 ++++ tools/gnatcov/annotations-xml.ads | 4 +- tools/gnatcov/annotations.adb | 89 ++++++----- tools/gnatcov/coverage.adb | 13 +- tools/gnatcov/coverage.ads | 5 +- tools/gnatcov/coverage_options.ads | 7 +- tools/gnatcov/sc_obligations.adb | 14 +- 10 files changed, 291 insertions(+), 43 deletions(-) create mode 100644 testsuite/tests/O212-062-xml/main.adb create mode 100644 testsuite/tests/O212-062-xml/src-traces-index.xml.expected create mode 100644 testsuite/tests/O212-062-xml/test.opt create mode 100644 testsuite/tests/O212-062-xml/test.py diff --git a/testsuite/tests/O212-062-xml/main.adb b/testsuite/tests/O212-062-xml/main.adb new file mode 100644 index 000000000..b5a78882f --- /dev/null +++ b/testsuite/tests/O212-062-xml/main.adb @@ -0,0 +1,28 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +procedure Main +is + function ATCC_Violation (X : Boolean) return Boolean + with Pre => (X or else not X) + is + function Id (X : Boolean) return Boolean is + begin + if X or else X then + return X; + end if; + return X; + end Id; + + Dummy : Boolean := Id (True); + begin + return Id (False); + end ATCC_Violation; +begin + declare + Dummy : Boolean := ATCC_Violation (True); + begin + null; + end; + return; +end Main; diff --git a/testsuite/tests/O212-062-xml/src-traces-index.xml.expected b/testsuite/tests/O212-062-xml/src-traces-index.xml.expected new file mode 100644 index 000000000..4a38aef12 --- /dev/null +++ b/testsuite/tests/O212-062-xml/src-traces-index.xml.expected @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/tests/O212-062-xml/test.opt b/testsuite/tests/O212-062-xml/test.opt new file mode 100644 index 000000000..74b2fb73e --- /dev/null +++ b/testsuite/tests/O212-062-xml/test.opt @@ -0,0 +1 @@ +bin-traces XFAIL Assertion coverage not yet supported for binary traces diff --git a/testsuite/tests/O212-062-xml/test.py b/testsuite/tests/O212-062-xml/test.py new file mode 100644 index 000000000..0b9536db6 --- /dev/null +++ b/testsuite/tests/O212-062-xml/test.py @@ -0,0 +1,26 @@ +""" +Check the content of an XML summary for assertion coverage. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +wd = Wdir('tmp_') + +gpr = gprfor(['main.adb'], srcdirs='..') +xcov_args = build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + covlevel='stmt+mcdc+atcc', + mains=['main'], + extra_coverage_args=['-axml']) + +thistest.fail_if_diff( + os.path.join("..", "src-traces-index.xml.expected"), + os.path.join("obj", "index.xml") +) + +thistest.result() diff --git a/tools/gnatcov/annotations-xml.ads b/tools/gnatcov/annotations-xml.ads index 64f31e57e..d71aa243c 100644 --- a/tools/gnatcov/annotations-xml.ads +++ b/tools/gnatcov/annotations-xml.ads @@ -34,8 +34,8 @@ package Annotations.Xml is -- The following sections will describe each file type. The following -- convention will be used to denotate possible values for attributes: -- - -- * COVERAGE_KIND: can be either 'insn', 'branch', 'stmt', - -- 'stmt+decision', 'stmt+mcdc'. + -- * COVERAGE_KIND: can be either 'insn', 'branch', or one matching + -- 'stmt(\+(decision|mcdc|uc_mcdc))?(\+(atc|atcc)?)?' -- * COVERAGE: can be either '+' (total coverage for the chosen coverage -- criteria), '-' (null coverage), '!' (partial coverage) or -- '.' (no code for this line). diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 6b958b0be..db7d1d7a0 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -1041,49 +1041,68 @@ package body Annotations is Update_Level_Stats (SCO, Get_Line_State (SCO, Stmt), Stmt); when Decision => if Coverage.Assertion_Coverage_Enabled - and then Decision_Type (SCO) in Pragma_Decision | Aspect + and then Is_Assertion (SCO) then Update_Level_Stats (SCO, Get_Line_State (SCO, ATC), ATC); else Update_Level_Stats (SCO, Get_Line_State (SCO, Decision), Decision); + end if; + + declare + Assertion_Decision : constant Boolean := + Coverage.Assertion_Condition_Coverage_Enabled + and then Is_Assertion (SCO); + begin + if Coverage.MCDC_Coverage_Enabled or else Assertion_Decision + then + declare + Condition_Level : constant Coverage_Level := + (if Assertion_Decision + then Coverage.Assertion_Condition_Level + else Coverage.MCDC_Level); + begin - -- Conditions in that decision - - if Coverage.MCDC_Coverage_Enabled then - for J in - Condition_Index'First .. Last_Cond_Index (SCO) - loop - declare - Condition_SCO : constant SCO_Id := - Condition (SCO, J); - - MCDC_State : constant SCO_State := - Get_Line_State (SCO, MCDC); - -- If the parent decision is partially covered, - -- then the SCO_State for each condition will be - -- No_Code, and the SCO_State for the MCDC - -- Coverage_Level associated to the parent decision - -- SCO will be Not_Covered. - - Condition_State : SCO_State; - - begin - if MCDC_State = Not_Covered then - Condition_State := Not_Covered; - else - Condition_State := - Get_Line_State - (Condition_SCO, Coverage.MCDC_Level); - end if; - - Update_Level_Stats - (SCO, Condition_State, Coverage.MCDC_Level); - end; - end loop; + -- Conditions in that decision + + for J in + Condition_Index'First .. Last_Cond_Index (SCO) + loop + declare + Condition_SCO : constant SCO_Id := + Condition (SCO, J); + + Line_Condition_State : constant SCO_State := + Get_Line_State (SCO, + (if Assertion_Decision + then ATCC + else MCDC)); + -- If the parent decision is partially covered, + -- then the SCO_State for each condition will be + -- No_Code, and the SCO_State for the + -- MCDC/Assertion condition Coverage_Level + -- associated to the parent decision SCO will be + -- Not_Covered. + + Condition_State : SCO_State; + + begin + if Line_Condition_State = Not_Covered then + Condition_State := Not_Covered; + else + Condition_State := + Get_Line_State + (Condition_SCO, (Condition_Level)); + end if; + + Update_Level_Stats + (SCO, Condition_State, Condition_Level); + end; + end loop; + end; end if; - end if; + end; when others => null; end case; diff --git a/tools/gnatcov/coverage.adb b/tools/gnatcov/coverage.adb index 9708f35ee..d60fef2bd 100644 --- a/tools/gnatcov/coverage.adb +++ b/tools/gnatcov/coverage.adb @@ -128,6 +128,17 @@ package body Coverage is end if; end MCDC_Level; + ------------------------------- + -- Assertion_Condition_Level -- + ------------------------------- + + function Assertion_Condition_Level return Contract_Condition_Level is + begin + pragma Assert (Assertion_Condition_Coverage_Enabled); + pragma Assert (Enabled (ATCC)); + return ATCC; + end Assertion_Condition_Level; + ---------------- -- Object_Level -- ---------------- @@ -208,7 +219,7 @@ package body Coverage is Res.Include (MCDC_Level); end if; end if; - if Enabled (ATC) then + if Assertion_Coverage_Enabled then Res.Include (ATC); if Enabled (ATCC) then Res.Include (ATCC); diff --git a/tools/gnatcov/coverage.ads b/tools/gnatcov/coverage.ads index f97c6972d..7787ef207 100644 --- a/tools/gnatcov/coverage.ads +++ b/tools/gnatcov/coverage.ads @@ -74,9 +74,12 @@ package Coverage is -- one is enabled (it is illegal to have both enabled). function MCDC_Level return MCDC_Coverage_Level; - -- If MCDC_Coverage_Level_Enabled, return MCDC or UC_MCDC, depending on + -- If MCDC_Coverage_Enabled, return MCDC or UC_MCDC, depending on -- which one is enabled (it is illegal to have both enabled). + function Assertion_Condition_Level return Contract_Condition_Level; + -- If Assertion_Condition_Coverage_Enabled, return ATCC. + function Coverage_Option_Value return String; -- Return the coverage option value for the currently enabled levels diff --git a/tools/gnatcov/coverage_options.ads b/tools/gnatcov/coverage_options.ads index db2e06d0f..a9ba9334d 100644 --- a/tools/gnatcov/coverage_options.ads +++ b/tools/gnatcov/coverage_options.ads @@ -51,9 +51,10 @@ package Coverage_Options is -- least once as part of an evaluation to True of the whole -- decision. - subtype Object_Coverage_Level is Coverage_Level range Insn .. Branch; - subtype Source_Coverage_Level is Coverage_Level range Stmt .. ATCC; - subtype MCDC_Coverage_Level is Coverage_Level range MCDC .. UC_MCDC; + subtype Object_Coverage_Level is Coverage_Level range Insn .. Branch; + subtype Source_Coverage_Level is Coverage_Level range Stmt .. ATCC; + subtype MCDC_Coverage_Level is Coverage_Level range MCDC .. UC_MCDC; + subtype Contract_Condition_Level is Coverage_Level range ATCC .. ATCC; type Levels_Type is array (Coverage_Level) of Boolean; -- Set of Coverage_Levels diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 0310f01e0..3e89b5f8a 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -2741,9 +2741,21 @@ package body SC_Obligations is return ""; else declare - SCOD : constant SCO_Descriptor := SCO_Vector (SCO); + SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); + From_Assertion : constant Boolean := Assertion_Coverage_Enabled + and then + ((SCOD.Kind = Decision + and then SCOD.D_Kind in Pragma_Decision | Aspect) + or else + (SCOD.Kind = Condition + and then SCO_Vector.Reference + (Enclosing_Decision (SCO)).D_Kind in + Pragma_Decision | Aspect)); begin return "SCO #" & Trim (SCO'Img, Side => Ada.Strings.Both) & ": " + & (if From_Assertion + then "ASSERTION " + else "") & SCO_Kind'Image (SCOD.Kind) & Op_Kind_Image & Sloc_Image (SCOD.Sloc_Range); From 3369b70d662631f2597e0ac92edfbacfe02e0da3 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 4 Dec 2023 11:41:31 +0100 Subject: [PATCH 0527/1483] Make the Inputs_Type definition public This makes it easier to iterate over the Inputs_Type type. --- tools/gnatcov/inputs.ads | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/tools/gnatcov/inputs.ads b/tools/gnatcov/inputs.ads index 3aa804365..bd80f9c11 100644 --- a/tools/gnatcov/inputs.ads +++ b/tools/gnatcov/inputs.ads @@ -39,7 +39,17 @@ package Inputs is -- May raise Name_Error or Status_Error if the corresponding text file -- cannot be opened. - type Inputs_Type is private; + type Inputs_Entry is record + Name, Qualifier : String_Access; + end record; + + function Equal (L, R : Inputs_Entry) return Boolean; + + package Input_Lists is new Ada.Containers.Doubly_Linked_Lists + (Element_Type => Inputs_Entry, + "=" => Equal); + + type Inputs_Type is new Input_Lists.List with null record; -- Input lists. Can be used to accumulate the arguments given on -- a command line. @@ -68,7 +78,8 @@ package Inputs is -- Go through the input list and call Process on each entry (qualifiers are -- ignored in the first variant). - function Length (Inputs : Inputs_Type) return Ada.Containers.Count_Type; + function Length (Inputs : Inputs_Type) return Ada.Containers.Count_Type + with Inline; -- Return the number of elements in Inputs procedure Log_File_Open (File_Name : String); @@ -104,20 +115,4 @@ package Inputs is Case_Insensitive : Boolean := False); -- Overload to work on Inputs.Inputs_Type values -private - - type Inputs_Entry is record - Name, Qualifier : String_Access; - end record; - - function Equal (L, R : Inputs_Entry) return Boolean; - - package Input_Lists is new Ada.Containers.Doubly_Linked_Lists - (Element_Type => Inputs_Entry, - "=" => Equal); - - type Inputs_Type is new Input_Lists.List with null record; - - pragma Inline (Length); - end Inputs; From 3893436ff91a92f8110ac178e884d2c995efce65 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 4 Dec 2023 11:42:19 +0100 Subject: [PATCH 0528/1483] Do not clean object directories with --save-temps We generate some temporary files for instrumentation purposes in the instrumentation directory, which is cleaned by Instrument.Clean_Objdirs. As temporary files should be preserved when `--save-temps` is passed through the command line, avoid cleaning it altogether. --- tools/gnatcov/instrument-clean_objdirs.adb | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/instrument-clean_objdirs.adb b/tools/gnatcov/instrument-clean_objdirs.adb index 5051ad259..f2191f3e5 100644 --- a/tools/gnatcov/instrument-clean_objdirs.adb +++ b/tools/gnatcov/instrument-clean_objdirs.adb @@ -20,6 +20,7 @@ with Ada.Directories; use Ada.Directories; with GNATCOLL.Projects; use GNATCOLL.Projects; +with Command_Line; use Command_Line; with Instrument.Common; use Instrument.Common; with Project; @@ -62,9 +63,11 @@ begin -- through extended projects, as their object directories can interfere -- with the build of the extending project. - Project.Iterate_Projects - (Root_Project => Project.Project.Root_Project, - Process => Clean_Subdir'Access, - Recursive => True, - Include_Extended => True); + if not Args.Bool_Args (Opt_Save_Temps) then + Project.Iterate_Projects + (Root_Project => Project.Project.Root_Project, + Process => Clean_Subdir'Access, + Recursive => True, + Include_Extended => True); + end if; end Instrument.Clean_Objdirs; From 4f73a5831921d9e6a35a9f811878bea61ff20747 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 1 Dec 2023 15:57:02 +0100 Subject: [PATCH 0529/1483] [integrated-instrumentation] normalize paths for files of interest gnatcov used to leave paths passed to the --files switch un-normalized, which resulted in some units of interest being ignored at instrumentation time. --- .../basic_cmake/CMakeLists.txt | 4 ++ .../basic_cmake/main.c | 8 +++ .../basic_cmake/test.py | 51 +++++++++++++++++++ tools/gnatcov/gnatcov_bits_specific.adb | 15 +++++- 4 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/basic_cmake/CMakeLists.txt create mode 100644 testsuite/tests/integrated_instrumentation/basic_cmake/main.c create mode 100644 testsuite/tests/integrated_instrumentation/basic_cmake/test.py diff --git a/testsuite/tests/integrated_instrumentation/basic_cmake/CMakeLists.txt b/testsuite/tests/integrated_instrumentation/basic_cmake/CMakeLists.txt new file mode 100644 index 000000000..b5e617d04 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_cmake/CMakeLists.txt @@ -0,0 +1,4 @@ +project(HelloWorld) +cmake_minimum_required(VERSION 3.0) + +add_executable(hello_world main.c) diff --git a/testsuite/tests/integrated_instrumentation/basic_cmake/main.c b/testsuite/tests/integrated_instrumentation/basic_cmake/main.c new file mode 100644 index 000000000..5b6a74961 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_cmake/main.c @@ -0,0 +1,8 @@ +#include + +int +main() +{ + printf("Hello world!\n"); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/basic_cmake/test.py b/testsuite/tests/integrated_instrumentation/basic_cmake/test.py new file mode 100644 index 000000000..00f00f5eb --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_cmake/test.py @@ -0,0 +1,51 @@ +""" +Regression test: gnatcov used to leave paths passed to the --files switch +un-normalized, which resulted in some units of interest being ignored at +instrumentation time. +""" + +import os +import os.path + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Setup the instrumentation process +xcov( + [ + "setup-integration", + f"--files={os.path.join(cwd, '..', 'main.c')}", + "--compilers=gcc", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +compiler_wrapper = os.path.join(cwd, 'gcc') +cmdrun(["cmake", "..", f"-DCMAKE_C_COMPILER={compiler_wrapper}"], for_pgm=False) +cmdrun(["make"], for_pgm=False) + +# Run the executable +cmdrun(["hello_world"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=main.c.sid", + "-axcov", + srctracename_for("main"), + ] +) +check_xcov_reports("*.xcov", {"main.c.xcov": {"+": {6, 7}}}) + +thistest.result() diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 98fbda502..8eb82c02f 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -29,6 +29,8 @@ with GNAT.OS_Lib; with GNAT.Regexp; with GNAT.Strings; use GNAT.Strings; +with GNATCOLL.VFS; + with System.Multiprocessors; with Snames; @@ -112,7 +114,7 @@ procedure GNATcov_Bits_Specific is Compiler_Drivers : Inputs.Inputs_Type; Source_Rebase_Inputs : Inputs.Inputs_Type; Source_Search_Inputs : Inputs.Inputs_Type; - Subprograms_Inputs : Inputs.Inputs_Type; + Subprograms_Inputs : Inputs.Inputs_Type; Text_Start : Pc_Type := 0; Output : String_Access := null; Tag : String_Access := null; @@ -566,7 +568,16 @@ procedure GNATcov_Bits_Specific is Copy_Arg_List (Opt_Ignore_Source_Files, Ignored_Source_Files); Copy_Arg_List (Opt_Files, Files_Of_Interest); Copy_Arg_List (Opt_Compiler_Wrappers, Compiler_Drivers); - Switches.Files_Of_Interest := To_String_Set (Files_Of_Interest); + + for File of Files_Of_Interest loop + declare + use GNATCOLL.VFS; + F : constant Virtual_File := Create (+File.Name.all); + begin + F.Normalize_Path; + Switches.Files_Of_Interest.Include (+(+Full_Name (F))); + end; + end loop; -- Compute the languages for which we want coverage analysis, or enable -- just the default ones. From 84460fb99dd1e58b80f8d5bf2f0b722d8a53bb32 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 1 Dec 2023 15:57:39 +0100 Subject: [PATCH 0530/1483] [integrated instrumentation] minor doc fix --- doc/gnatcov/integrated_instr.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/gnatcov/integrated_instr.rst b/doc/gnatcov/integrated_instr.rst index 10fac4ed4..aa0926298 100644 --- a/doc/gnatcov/integrated_instr.rst +++ b/doc/gnatcov/integrated_instr.rst @@ -147,7 +147,7 @@ directory: .. code-block:: sh - cmake .. -CMAKE_CXX_COMPILER=/build/g++ + cmake .. -DCMAKE_CXX_COMPILER=/build/g++ The default generator for CMake is "Unix Makefiles", so we can then run the build process with ``make``, and our executable which will produce a source trace From 5d9e7d5c9215d64bbfde66225bf667c73ef94fff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 5 Dec 2023 15:25:02 +0100 Subject: [PATCH 0531/1483] Setup-integration: improve error message when failing to load gnatcov_rts --- .../168-rts_error_msg/gnatcov_rts.gpr | 1 + .../168-rts_error_msg/main.c | 5 +++ .../168-rts_error_msg/test.py | 44 +++++++++++++++++++ tools/gnatcov/instrument-setup_config.adb | 16 ++++++- 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/168-rts_error_msg/gnatcov_rts.gpr create mode 100644 testsuite/tests/integrated_instrumentation/168-rts_error_msg/main.c create mode 100644 testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py diff --git a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/gnatcov_rts.gpr b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/gnatcov_rts.gpr new file mode 100644 index 000000000..481b201fb --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/gnatcov_rts.gpr @@ -0,0 +1 @@ +INVALID PROJECT FILE FOR TEST PURPOSES diff --git a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/main.c b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/main.c new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/main.c @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py new file mode 100644 index 000000000..7cdf7c550 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py @@ -0,0 +1,44 @@ +""" +Test that the error message emitted by the "gnatcov setup-integration" command +is helpful when failing to load the coverage runtime project. +""" + +import os + +from SUITE.cutils import Wdir +from SUITE.tutils import contents_of, thistest, xcov + +# Point gnatcov towards our invalid GNATcov_RTS project +env = os.environ +env["GPR_PROJECT_PATH"] = os.getcwd() + +tmp = Wdir("tmp_") + +# Try to setup for a simple main file +integration_log = "setup-integration.log" +p = xcov( + [ + "setup-integration", + "-cstmt+mcdc", + "--output-dir=.", + "--files=../main.c", + ], + env=env, + out=integration_log, + register_failure=False +) + +thistest.fail_if(p.status == 0, "gnatcov exit status shouldn't be success") + +# Check that the error message correctly reports an issue with the coverage +# runtime. +thistest.fail_if_no_match( + what="gnatcov error message", + regexp=r".*gnatcov(\.exe)?: Failed locating or loading gnatcov_rts\.gpr" + r"(\n|.)*Is the project available on the GPR_PROJECT_PATH\?" + r"(\n|.)*gprls output was:" + r"(\n|.)*", + actual=contents_of(integration_log), +) + +thistest.result() diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index 26a58c580..5213f4ee5 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -136,16 +136,28 @@ package body Instrument.Setup_Config is Output_Filename : constant String := Output_Dir / "gprls_output"; Output_File : File_Type; + GPRLS_Success : Boolean; begin Args.Append (+"-P"); Args.Append (+"gnatcov_rts"); Args.Append (+"-vP1"); - Run_Command + GPRLS_Success := Run_Command (Command => "gprls", Arguments => Args, Origin_Command_Name => "gnatcov setup-integration", - Output_File => Output_Filename); + Output_File => Output_Filename, + Ignore_Error => True); Open (Output_File, In_File, Output_Filename); + if not GPRLS_Success then + Outputs.Error ("Failed locating or loading gnatcov_rts.gpr"); + Warning_Or_Error ("Is the project available on the" + & " GPR_PROJECT_PATH?"); + Warning_Or_Error ("gprls output was:"); + while not End_Of_File (Output_File) loop + Warning_Or_Error (Get_Line (Output_File)); + end loop; + raise Xcov_Exit_Exc; + end if; while not End_Of_File (Output_File) loop declare Line : constant String := Get_Line (Output_File); From 742bbfdc6b474899c087833bf42a652d015d15d0 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 4 Dec 2023 15:57:08 +0100 Subject: [PATCH 0532/1483] [integrated instrumentation] fix forwarding of compiler invocation The compiler driver wrapper used to crash on invocation that did not involve a compilation / linking command, e.g. `gcc --version`. Properly forward to the original compiler the command line invocation in such cases. --- .../check_compiler_wrapper/pkg.c | 5 + .../check_compiler_wrapper/test.py | 49 ++++++++++ tools/gnatcov/compiler_wrappers-gcc.adb | 97 ++++++++++--------- 3 files changed, 107 insertions(+), 44 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/check_compiler_wrapper/pkg.c create mode 100644 testsuite/tests/integrated_instrumentation/check_compiler_wrapper/test.py diff --git a/testsuite/tests/integrated_instrumentation/check_compiler_wrapper/pkg.c b/testsuite/tests/integrated_instrumentation/check_compiler_wrapper/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/check_compiler_wrapper/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/check_compiler_wrapper/test.py b/testsuite/tests/integrated_instrumentation/check_compiler_wrapper/test.py new file mode 100644 index 000000000..0a79488d1 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/check_compiler_wrapper/test.py @@ -0,0 +1,49 @@ +""" +Regression test-case: checks that the use of the compiler wrapper is +transparent to the user, meaning that all adequate use of the compiler are +supported by the compiler wrapper, and not only compiling / linking commands. +gnatcov used to crash on e.g. `gcc --version`. Also check other special cases +for robustness. +""" + +import os +import os.path + +from SUITE.control import env +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import cmdrun, thistest, xcov + +Wdir("tmp_") + +# Setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join('..', 'pkg.c')}", + "--compilers=gcc", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=os.getcwd()) + +# Check that gcc --version do not crash +cmdrun(["gcc", "--version"], for_pgm=False) + +# Check that gcc -### -c pkg.c -o pkg.o does not crash and does not produce an +# object file. +cmdrun(["gcc", "-###", "-c", "../pkg.c", "-o", "pkg.o"], for_pgm=False) +thistest.fail_if( + os.path.exists("pkg.o"), + "unexpected pkg.o file", +) + +# Check that gcc -E pkg.c produces uninstrumented preprocessed code +cmdrun(["gcc", "-E", "../pkg.c", "-o", "pkg.pp"], for_pgm=False) +thistest.fail_if( + "witness" in contents_of("pkg.pp"), + "unexpected instrumented preprocessed file", +) + +thistest.result() diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index c8d1fb374..4a49c7fad 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -178,7 +178,7 @@ is function Parse_Compiler_Driver_Command (Context : in out Parsing_Context; Tmp_Dir : Temporary_Directory; - Command : String_Vectors.Vector) return Compilation_Database; + Args : String_Vectors.Vector) return Compilation_Database; -- Parse a compiler driver command function Parse_Compilation_Command @@ -203,6 +203,11 @@ is Config : Instrumentation_Config) return String_Sets.Set; -- Return the list of coverage buffer symbols in the link closure + procedure Run_Original_Compiler + (Context : Parsing_Context; + Args : String_Vectors.Vector); + -- Run the wrapped compiler with the given Args + ---------------- -- Split_Args -- ---------------- @@ -247,8 +252,9 @@ is function Parse_Compiler_Driver_Command (Context : in out Parsing_Context; Tmp_Dir : Temporary_Directory; - Command : String_Vectors.Vector) return Compilation_Database + Args : String_Vectors.Vector) return Compilation_Database is + use type String_Vectors.Vector; Result : Compilation_Database; Parsed_Link_Command : Boolean := False; Commands_Filename : constant String := @@ -258,18 +264,11 @@ is -- the command we are intercepting is a compile / link target and not -- a preprocessing / -### action. - declare - Arguments : String_Vectors.Vector; - begin - Arguments.Append_Vector (Command); - Arguments.Delete_First; - Arguments.Prepend (+"-###"); - Run_Command - (+Context.Orig_Compiler_Driver, - Arguments, - "gnatcov", - Output_File => Commands_Filename); - end; + Run_Command + (+Context.Orig_Compiler_Driver, + String_Vectors.To_Vector (+"-###", 1) & Args, + "gnatcov", + Output_File => Commands_Filename); -- Then, parse the files containing the list of launched commands, using -- the following heuristics: @@ -287,6 +286,9 @@ is Line : constant String := Get_Line (Commands_File); Command : constant String_Vectors.Vector := Split_Args (Line); begin + if Line = "" then + goto Continue; + end if; if Ends_With (Command.First_Element, "cc1") or else Ends_With (Command.First_Element, "cc1plus") then @@ -321,6 +323,7 @@ is (Parse_Link_Command (Context, Command)); Parsed_Link_Command := True; end if; + <> end; end loop; end; @@ -379,16 +382,10 @@ is Cur := Next (Cur); end loop; - -- Error out if the parsing failed - - if Length (Result.Filename) = 0 then - Outputs.Fatal_Error - ("Could not find source file in compilation command: " - & Img (Command)); - elsif Length (Result.Target) = 0 then - Outputs.Fatal_Error - ("Could not find output file in compilation command: " - & Img (Command)); + if Length (Result.Filename) = 0 + or else Length (Result.Target) = 0 + then + return No_Compilation_Command; end if; Context.Source_Mapping.Include (Result.Target, Result.Filename); return Result; @@ -622,6 +619,20 @@ is return Result; end Coverage_Buffer_Symbols; + --------------------------- + -- Run_Original_Compiler -- + --------------------------- + + procedure Run_Original_Compiler + (Context : Parsing_Context; + Args : String_Vectors.Vector) is + begin + Run_Command + (Command => +Context.Orig_Compiler_Driver, + Arguments => Args, + Origin_Command_Name => "compiler"); + end Run_Original_Compiler; + Compiler_Wrapper_Dir : constant String := Containing_Directory (GNAT.OS_Lib.Locate_Exec_On_Path (Command_Name).all); -- Directory that contains the current program @@ -635,9 +646,6 @@ is Instr_Dir : Temporary_Directory; -- Directory holding instrumentation artefacts - Command : String_Vectors.Vector; - -- Original compiler driver invocation - Comp_DB : Compilation_Database; Prj : Prj_Desc; @@ -665,21 +673,30 @@ begin Tag_Provider := Tag_Providers.Create (Default_Tag_Provider_Name); Traces_Files.Update_Current_Trace_Kind (Traces_Files.Source_Trace_File); + Context.Orig_Compiler_Driver := + Instr_Config.Compiler_Drivers.Element + (+Ada.Directories.Simple_Name (Command_Name)); + -- Load the command line - Command.Append (+Command_Name); for I in 1 .. Argument_Count loop Compiler_Driver_Opts.Append (+Argument (I)); end loop; - Command.Append_Vector (Compiler_Driver_Opts); - Context.Orig_Compiler_Driver := - Instr_Config.Compiler_Drivers.Element - (+Ada.Directories.Simple_Name (Command_Name)); + -- If this driver invocation is not meant to compile a source file, there + -- is no instrumentation to do: just run the original driver and exit. + + for Arg of Compiler_Driver_Opts loop + if +Arg in "-###" | "-E" then + Run_Original_Compiler (Context, Compiler_Driver_Opts); + return; + end if; + end loop; -- Parse the compiler driver invocation - Comp_DB := Parse_Compiler_Driver_Command (Context, Instr_Dir, Command); + Comp_DB := + Parse_Compiler_Driver_Command (Context, Instr_Dir, Compiler_Driver_Opts); -- Generate an artificial project description to pass compiler -- switches and default spec / body suffixes. @@ -803,10 +820,8 @@ begin declare Output_Dir : constant String := +Prj.Output_Dir; - New_Args : String_Vectors.Vector := Command.Copy; + New_Args : String_Vectors.Vector := Compiler_Driver_Opts; begin - New_Args.Delete_First; - New_Args.Prepend ("-I" & Instr_Config.GNATcov_RTS_Include_Dir); if Comp_DB.Link_Command /= No_Link_Command then @@ -878,10 +893,7 @@ begin Args_Compilation.Append (Instr_Artifact); Args_Compilation.Append (+"-o"); Args_Compilation.Append (+Instr_Artifact_Object_Name); - Run_Command - (Command => +Context.Orig_Compiler_Driver, - Arguments => Args_Compilation, - Origin_Command_Name => "compiler wrapper"); + Run_Original_Compiler (Context, Args_Compilation); Context.Instrumentation_Objects .Reference (Comp_Command.Filename) @@ -894,10 +906,7 @@ begin -- Finally, run the alternate compiler driver invocation - Run_Command - (Command => +Context.Orig_Compiler_Driver, - Arguments => New_Args, - Origin_Command_Name => "compiler"); + Run_Original_Compiler (Context, New_Args); if Comp_DB.Link_Command = No_Link_Command then From c26fe66d5a7c225767ac5b86a89f4f4ff6de9d12 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 5 Dec 2023 16:36:26 +0100 Subject: [PATCH 0533/1483] compiler_wrappers-gcc.adb: fix a comment typo --- tools/gnatcov/compiler_wrappers-gcc.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 4a49c7fad..45975fecb 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -139,7 +139,7 @@ is -- We rely on object file symbols to know what coverage buffers we -- should dump at link time. Nevertheless, an object file referenced in -- a link command (which we get through the -### verbose switch) does - -- not necessarily exists yet: it can be a temporary file created by a + -- not necessarily exist yet: it can be a temporary file created by a -- previous compilation command that belongs to the same compiler driver -- invocation (e.g. when compiling and linking at the same time). -- From 496832d8923862bb8c5382bcdadec9d17c49570e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 5 Dec 2023 16:13:21 +0000 Subject: [PATCH 0534/1483] compiler_wrappers-gcc.adb: use the Null_Unbounded_String constant --- tools/gnatcov/compiler_wrappers-gcc.adb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 45975fecb..10fb84fea 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -65,8 +65,8 @@ is No_Compilation_Command : constant Compilation_Command_Type := (Language => All_Languages, - Filename => +"", - Target => +"", + Filename => Null_Unbounded_String, + Target => Null_Unbounded_String, Instrumentation_Sources => String_Vectors.Empty_Vector); package Compilation_Command_Vectors is new Ada.Containers.Vectors @@ -84,8 +84,8 @@ is -- driver. No_Assembly_Command : constant Assembly_Command_Type := - (Filename => +"", - Target => +""); + (Filename => Null_Unbounded_String, + Target => Null_Unbounded_String); package Assembly_Command_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Assembly_Command_Type); @@ -115,7 +115,7 @@ is Libraries => String_Vectors.Empty_Vector, Object_Files => String_Vectors.Empty_Vector, Source_Files => String_Vectors.Empty_Vector, - Target => +""); + Target => Null_Unbounded_String); type Compilation_Database is record Compilation_Commands : Compilation_Command_Vectors.Vector; @@ -220,7 +220,7 @@ is for C of Command loop if C = ' ' and then Arg /= "" then Result.Append (Arg); - Arg := +""; + Arg := Null_Unbounded_String; else Append (Arg, C); end if; From 293758713633aecf6d377da69d4530737819aee1 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 5 Dec 2023 16:25:35 +0000 Subject: [PATCH 0535/1483] compiler_wrappers-gcc.adb: minor reformattings --- tools/gnatcov/compiler_wrappers-gcc.adb | 58 ++++++++++++------------- tools/gnatcov/subprocesses.adb | 2 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 10fb84fea..3b6d5a916 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -212,9 +212,8 @@ is -- Split_Args -- ---------------- - function Split_Args (Command : String) return String_Vectors.Vector - is - Arg : Unbounded_String; + function Split_Args (Command : String) return String_Vectors.Vector is + Arg : Unbounded_String; Result : String_Vectors.Vector; begin for C of Command loop @@ -260,9 +259,9 @@ is Commands_Filename : constant String := Tmp_Dir.Directory_Name / "commands"; begin - -- Expand the command line using gcc's -### option. TODO??? check if - -- the command we are intercepting is a compile / link target and not - -- a preprocessing / -### action. + -- Expand the command line using gcc's -### option. TODO??? check if the + -- command we are intercepting is a compile / link target and not a + -- preprocessing / -### action. Run_Command (+Context.Orig_Compiler_Driver, @@ -272,10 +271,11 @@ is -- Then, parse the files containing the list of launched commands, using -- the following heuristics: + -- -- * If the command is a cc1 invocation (first argument end with cc1), -- assume compilation command. -- * If the command is an as invocation, assume assembly command. - -- * If the command is a collect2 invocation, assume link command + -- * If the command is a collect2 invocation, assume link command. declare Commands_File : File_Type; @@ -283,7 +283,7 @@ is Open (Commands_File, In_File, Commands_Filename); while not End_Of_File (Commands_File) loop declare - Line : constant String := Get_Line (Commands_File); + Line : constant String := Get_Line (Commands_File); Command : constant String_Vectors.Vector := Split_Args (Line); begin if Line = "" then @@ -353,8 +353,8 @@ is Arg : constant Unbounded_String := String_Vectors.Element (Cur); begin - -- Skip switches arguments that look like filenames. Ideally, - -- we would find the positional argument but it is not + -- Skip switches arguments that look like filenames. Ideally, we + -- would find the positional argument but it is not -- straightforward. if Arg = +"-dumpbase" or else Arg = +"-dumpbase-ext" then @@ -523,7 +523,7 @@ is Args.Append (+Symbol_File); -- The command can fail with e.g. "file format not recognized" for - -- system libraries. TODO???: investigate why. We should also avoid + -- system libraries. TODO??? investigate why. We should also avoid -- invoking nm on system libraries altogether. Ignore_Success := @@ -542,7 +542,7 @@ is while not End_Of_File (Output_File) loop declare Line_Str : constant String := Get_Line (Output_File); - Line : constant Unbounded_String := +Line_Str; + Line : constant Unbounded_String := +Line_Str; begin if Starts_With (Line, "gnatcov_rts_buffers") @@ -639,7 +639,7 @@ is Instr_Config_File : constant String := Compiler_Wrapper_Dir / Instrumentation_Config_Filename; - Instr_Config : Instrumentation_Config := + Instr_Config : Instrumentation_Config := Load_Config (Instr_Config_File); -- Instrumentation configuration previously generated by the setup step @@ -664,6 +664,8 @@ is Instrumented_Files : String_Sets.Set; -- List of instrumented files (files of interest / main files / both) +-- Start of processing for Compiler_Wrappers.GCC + begin Create_Temporary_Directory (Instr_Dir, "gnatcov_instr", Auto_Delete => not Switches.Save_Temps); @@ -724,12 +726,12 @@ begin Comp_DB.Compilation_Commands.Reference (Cur); Instrumenter : Language_Instrumenter'Class := (case Comp_Command.Language is - when C_Language => Create_C_Instrumenter (Instr_Config.Tag), - when CPP_Language => Create_CPP_Instrumenter (Instr_Config.Tag), - when others => - raise Program_Error - with "Unsupported language for integrated" - & " instrumentation"); + when C_Language => Create_C_Instrumenter (Instr_Config.Tag), + when CPP_Language => Create_CPP_Instrumenter (Instr_Config.Tag), + when others => + raise Program_Error + with "Unsupported language for integrated" + & " instrumentation"); Fullname : constant String := Ada.Directories.Full_Name (+Comp_Command.Filename); @@ -752,7 +754,7 @@ begin Unit_Name => Fullname, -- Generate all the SID files under the same directory as the - -- compiler wrapper as they must persist. TODO???: deal with + -- compiler wrapper as they must persist. TODO??? deal with -- homonym files in SID names. SID_Name => Compiler_Wrapper_Dir / (Simple_Name & ".sid")); @@ -809,9 +811,7 @@ begin Config => Instr_Config); begin Buffers_List_Unit := - Instrumenter.Emit_Buffers_List_Unit - (Buffer_Symbols, - Prj); + Instrumenter.Emit_Buffers_List_Unit (Buffer_Symbols, Prj); end; end if; @@ -845,8 +845,8 @@ begin begin if Ada.Directories.Exists (+Arg) then declare - Base : constant String := Simple_Name (+Arg); - Fullname : constant String := Full_Name (+Arg); + Base : constant String := Simple_Name (+Arg); + Fullname : constant String := Full_Name (+Arg); begin if Instrumented_Files.Contains (+Fullname) then New_Args.Replace_Element (I, +(Output_Dir / Base)); @@ -923,7 +923,7 @@ begin Packaged_Name : constant String := New_File (Prj, "instr_" & Filename_Slug (+Orig_Source) & ".a"); - Success : Boolean; + Success : Boolean; begin if not Instr_Objects.Is_Empty then declare @@ -941,9 +941,9 @@ begin Arguments => Args_Ld, Origin_Command_Name => "compiler wrapper"); - -- Finally, replace the original object file with - -- the newly created library file, packaging both - -- the instrumented source and its coverage buffer. + -- Finally, replace the original object file with the + -- newly created library file, packaging both the + -- instrumented source and its coverage buffer. GNAT.OS_Lib.Copy_File (Packaged_Name, diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 45947577d..8b2925d6f 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -485,7 +485,7 @@ package body Subprocesses is Environment, +Pool.Process_Infos (Id).Output_File, - -- TODO???: there will be mangling on the stderr if stdout was + -- TODO??? there will be mangling on the stderr if stdout was -- redirected to an output file. Err_To_Out => Output_File = "", From 61bf0d02a1516a741c98e57c1652879c96a84d37 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 7 Dec 2023 09:12:03 +0000 Subject: [PATCH 0536/1483] Instrument.C: fix handling of double quotes in filenames --- .../tests/instr-cov/c_special_filenames/bar.c | 8 +++ .../{$foo@bar$.c => foo.c} | 0 .../instr-cov/c_special_filenames/main.c | 3 +- .../instr-cov/c_special_filenames/test.py | 54 +++++++++++++------ tools/gnatcov/instrument-c.adb | 45 ++++++++++++---- tools/gnatcov/instrument-c.ads | 8 +++ tools/gnatcov/paths.adb | 21 -------- tools/gnatcov/paths.ads | 4 -- 8 files changed, 91 insertions(+), 52 deletions(-) create mode 100644 testsuite/tests/instr-cov/c_special_filenames/bar.c rename testsuite/tests/instr-cov/c_special_filenames/{$foo@bar$.c => foo.c} (100%) diff --git a/testsuite/tests/instr-cov/c_special_filenames/bar.c b/testsuite/tests/instr-cov/c_special_filenames/bar.c new file mode 100644 index 000000000..088001447 --- /dev/null +++ b/testsuite/tests/instr-cov/c_special_filenames/bar.c @@ -0,0 +1,8 @@ +int +bar (int a, int b, int c) +{ + if (a) + return b; + else + return c; +} diff --git a/testsuite/tests/instr-cov/c_special_filenames/$foo@bar$.c b/testsuite/tests/instr-cov/c_special_filenames/foo.c similarity index 100% rename from testsuite/tests/instr-cov/c_special_filenames/$foo@bar$.c rename to testsuite/tests/instr-cov/c_special_filenames/foo.c diff --git a/testsuite/tests/instr-cov/c_special_filenames/main.c b/testsuite/tests/instr-cov/c_special_filenames/main.c index ec9915a9c..2c284257d 100644 --- a/testsuite/tests/instr-cov/c_special_filenames/main.c +++ b/testsuite/tests/instr-cov/c_special_filenames/main.c @@ -1,8 +1,9 @@ extern int foo (int i); +extern int bar (int a, int b, int c); int main (void) { - int result = foo (0); + int result = foo (0) + bar (1, 0, 2); return result; } diff --git a/testsuite/tests/instr-cov/c_special_filenames/test.py b/testsuite/tests/instr-cov/c_special_filenames/test.py index a82f2d837..e6848b74f 100644 --- a/testsuite/tests/instr-cov/c_special_filenames/test.py +++ b/testsuite/tests/instr-cov/c_special_filenames/test.py @@ -3,32 +3,56 @@ characters produces valid instrumented sources. """ +import os.path + +from e3.fs import cp + from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.control import env from SUITE.context import thistest from SUITE.cutils import Wdir from SUITE.tutils import gprfor from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") + +# Copy the sources in the temporary directory. Note that we cannot test the +# case of a filename containing a double quote or a backslash on Windows +# because of filename restrictions on that platform. +copy_map = { + "ada_main.adb": "ada_main.adb", + "bar.c": "src bar.c" if env.build.os.name == "windows" else 'src\\"bar.c', + "foo.c": "src foo$@.c", + "main.c": "main.c", +} +for src, dest in copy_map.items(): + cp(os.path.join("..", src), dest) + +# Compute the expected coverage report from the actual source filenames. Note +# that in xcov filenames, "gnatcov coverage" first turns '\' to '/' (during +# path separator canonicalization) and then the unique filename machinery turns +# '/' to '-'. +coverage_data = { + "ada_main.adb": {"+": {7, 9}}, + "bar.c": {"+": {4, 5}, "-": {7}}, + "foo.c": {"+": {4}}, + "main.c": {"+": {7, 8}}, +} +expected_report = { + "{}.xcov".format(copy_map[filename].replace("\\", "-")): report + for filename, report in coverage_data.items() +} build_run_and_coverage( gprsw=GPRswitches( - root_project=gprfor(srcdirs=['..'], mains=['main.c', 'ada_main.adb']) + root_project=gprfor(srcdirs=["."], mains=["main.c", "ada_main.adb"]) ), - covlevel='stmt', - mains=['main', 'ada_main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src', -) -check_xcov_reports( - '*.xcov', - { - 'main.c.xcov': {'+': {6}}, - '$foo@bar$.c.xcov': {'+': {4}}, - 'ada_main.adb.xcov': {'+': {9}}, - }, - 'xcov', + covlevel="stmt", + mains=["main", "ada_main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", ) +check_xcov_reports("*.xcov", expected_report, "xcov") thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 3dff09ff8..eb1ae15fd 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3585,7 +3585,7 @@ package body Instrument.C is -- filenames. & " .unit_name = " - & " {""" & Escape_Backslashes (CU_Filename) & """, " + & " {" & C_String_Literal (CU_Filename) & ", " & CU_Filename'Length'Image & "}" & "," & ASCII.LF @@ -3777,11 +3777,12 @@ package body Instrument.C is File.Put_Line (Indent2 & Simple & "),"); File.Put_Line (Indent2 - & "STR (""" - & (if Dump_Config.Trigger = Manual - then +Prj.Prj_Name - else Escape_Backslashes (+Main.Filename)) - & """),"); + & "STR (" + & C_String_Literal + (if Dump_Config.Trigger = Manual + then +Prj.Prj_Name + else +Main.Filename) + & "),"); File.Put_Line (Indent2 & "gnatcov_rts_time_to_uint64()" & ","); File.Put_Line (Indent2 & "STR ("""")"); end; @@ -3793,11 +3794,12 @@ package body Instrument.C is -- program name is the name of the main, and there is no way to -- get the current execution time. - File.Put_Line (Indent2 & "STR (""" - & (if Dump_Config.Trigger = Manual - then +Prj.Prj_Name - else Escape_Backslashes (+Main.Filename)) - & """),"); + File.Put_Line (Indent2 & "STR (" + & C_String_Literal + (if Dump_Config.Trigger = Manual + then +Prj.Prj_Name + else +Main.Filename) + & "),"); File.Put_Line (Indent2 & "0,"); File.Put_Line (Indent2 & "STR ("""")"); @@ -4605,4 +4607,25 @@ package body Instrument.C is end; end Is_Source_Of_Interest; + ---------------------- + -- C_String_Literal -- + ---------------------- + + function C_String_Literal (Str : String) return String is + Result : Unbounded_String; + begin + Append (Result, '"'); + for C of Str loop + if C = '\' then + Append (Result, "\\"); + elsif C = '"' then + Append (Result, "\"""); + else + Append (Result, C); + end if; + end loop; + Append (Result, '"'); + return +Result; + end C_String_Literal; + end Instrument.C; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index fda70e1c4..c6d455fe9 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -395,6 +395,14 @@ package Instrument.C is -- UIC.Sources_Of_Interest. Return whether this source file is a source of -- interest. + function C_String_Literal (Str : String) return String; + -- Turn Str into the corresponding C string literal. For instance: + -- + -- C_String_Literal ("foo") = """foo""" + -- C_String_Literal ("a\b") = """a\\b""" + -- C_String_Literal ("a\b") = """a\\b""" + -- C_String_Literal ("a""b") = """a\""b""" + private function Find_Instrumented_Entities diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index 36916a14b..fdd208c42 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -22,8 +22,6 @@ with Ada.Strings.Unbounded; with GNAT.OS_Lib; with GNAT.Regpat; -with Strings; use Strings; - package body Paths is On_Windows : constant Boolean := GNAT.OS_Lib.Directory_Separator = '\'; @@ -319,23 +317,4 @@ package body Paths is and then Path (Path'First + 1) = ':'; end Starts_With_Drive_Pattern; - ------------------------- - -- Escape_Windows_Path -- - ------------------------- - - function Escape_Backslashes (Str : String) return String - is - use Ada.Strings.Unbounded; - Result : Unbounded_String; - begin - for C of Str loop - if C = '\' then - Append (Result, "\\"); - else - Append (Result, C); - end if; - end loop; - return +Result; - end Escape_Backslashes; - end Paths; diff --git a/tools/gnatcov/paths.ads b/tools/gnatcov/paths.ads index e66e7cdf1..a7bc5dc55 100644 --- a/tools/gnatcov/paths.ads +++ b/tools/gnatcov/paths.ads @@ -64,10 +64,6 @@ package Paths is -- of the service, this one always matches both Windows or Unix file path -- flavors. - function Escape_Backslashes (Str : String) return String; - -- Escape every backslash in the given Str, to turn it into a C-compatible - -- string. - -- TODO??? Handle Unicode file names end Paths; From f87a62f968d6d828adbee044597933db25720616 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 7 Dec 2023 08:44:38 +0000 Subject: [PATCH 0537/1483] compiler_wrappers-gcc.adb: fix handling of special filenames --- .../special_filenames/bar.c | 5 ++ .../special_filenames/foo.c | 8 +++ .../special_filenames/test.c | 10 +++ .../special_filenames/test.py | 66 +++++++++++++++++++ tools/gnatcov/compiler_wrappers-gcc.adb | 61 ++++++++++++++--- tools/gnatcov/paths.adb | 18 +++++ tools/gnatcov/paths.ads | 5 ++ 7 files changed, 164 insertions(+), 9 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/special_filenames/bar.c create mode 100644 testsuite/tests/integrated_instrumentation/special_filenames/foo.c create mode 100644 testsuite/tests/integrated_instrumentation/special_filenames/test.c create mode 100644 testsuite/tests/integrated_instrumentation/special_filenames/test.py diff --git a/testsuite/tests/integrated_instrumentation/special_filenames/bar.c b/testsuite/tests/integrated_instrumentation/special_filenames/bar.c new file mode 100644 index 000000000..1b5f37c42 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/special_filenames/bar.c @@ -0,0 +1,5 @@ +int +bar (int c) +{ + return c + 1; +} diff --git a/testsuite/tests/integrated_instrumentation/special_filenames/foo.c b/testsuite/tests/integrated_instrumentation/special_filenames/foo.c new file mode 100644 index 000000000..069e4ecdb --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/special_filenames/foo.c @@ -0,0 +1,8 @@ +int +foo (int a, int b) +{ + if (a) + return a; + else + return b; +} diff --git a/testsuite/tests/integrated_instrumentation/special_filenames/test.c b/testsuite/tests/integrated_instrumentation/special_filenames/test.c new file mode 100644 index 000000000..5c8b273b5 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/special_filenames/test.c @@ -0,0 +1,10 @@ +extern int foo (int a, int b); +extern int bar (int c); + +int +main (void) +{ + foo (0, 1); + bar (0); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/special_filenames/test.py b/testsuite/tests/integrated_instrumentation/special_filenames/test.py new file mode 100644 index 000000000..b2647f3ae --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/special_filenames/test.py @@ -0,0 +1,66 @@ +""" +Check that the integration instrumentation handles correctly filenames that +contain spaces. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +# Copy the sources in the temporary directory. Note that we cannot test the +# case of a filename containing a double quote or a backslash on Windows +# because of filename restrictions on that platform. +copy_map = { + "bar.c": 'src bar.c' if env.build.os.name == "windows" else 'src\\"bar.c', + "foo.c": "src foo$@.c", + "test.c": "test.c", +} +for src, dest in copy_map.items(): + cp(os.path.join("..", src), dest) + +# Compute the expected coverage report from the actual source filenames. Note +# that in xcov filenames, "gnatcov coverage" first turns '\' to '/' (during +# path separator canonicalization) and then the unique filename machinery turns +# '/' to '-'. +coverage_data = { + "test.c": {"+": {7, 8, 9}}, + "foo.c": {"+": {4, 7}, "-": {5}}, + "bar.c": {"+": {4}}, +} +expected_report = { + "{}.xcov".format(copy_map[filename].replace("\\", "-")): report + for filename, report in coverage_data.items() +} + +# Setup the instrumentation process +sources = [os.path.abspath(filename) for filename in copy_map.values()] +files = [f"--files={filename}" for filename in sources] +xcov( + ["setup-integration", "--level=stmt", "--compilers=gcc", "--output-dir=."] + + files +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=os.getcwd()) + +# Build the test program and run it +cmdrun(["gcc", "-o", "test program"] + sources, for_pgm=False) +cmdrun(["test program"], for_pgm=False) + +# Check coverage expectations +sid_args = [f"--sid={filename}.sid" for filename in sources] +xcov( + ["coverage", "-cstmt", "-axcov", srctracename_for("test")] + + sid_args +) +check_xcov_reports("*.xcov", expected_report) + +thistest.result() diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 3b6d5a916..6bfde1c01 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -213,20 +213,63 @@ is ---------------- function Split_Args (Command : String) return String_Vectors.Vector is + type State_Kind is + (No_Argument, Simple_Argument, Quoted_Argument); + + State : State_Kind := No_Argument; Arg : Unbounded_String; Result : String_Vectors.Vector; - begin - for C of Command loop - if C = ' ' and then Arg /= "" then + + procedure Append_Arg; + + ---------------- + -- Append_Arg -- + ---------------- + + procedure Append_Arg is + begin + if State /= No_Argument then Result.Append (Arg); + State := No_Argument; Arg := Null_Unbounded_String; - else - Append (Arg, C); end if; + end Append_Arg; + + C : Character; + I : Natural := Command'First; + + begin + while I <= Command'Last loop + C := Command (I); + case State is + when No_Argument => + if C = '"' then + State := Quoted_Argument; + elsif C /= ' ' then + State := Simple_Argument; + Append (Arg, C); + end if; + + when Simple_Argument => + if C = ' ' then + Append_Arg; + else + Append (Arg, C); + end if; + + when Quoted_Argument => + if C = '\' then + I := I + 1; + Append (Arg, Command (I)); + elsif C = '"' then + Append_Arg; + else + Append (Arg, C); + end if; + end case; + I := I + 1; end loop; - if Arg /= "" then - Result.Append (Arg); - end if; + Append_Arg; return Result; end Split_Args; @@ -736,7 +779,7 @@ begin Fullname : constant String := Ada.Directories.Full_Name (+Comp_Command.Filename); Simple_Name : constant String := - Ada.Directories.Simple_Name (+Comp_Command.Filename); + Workaround_Simple_Name (+Comp_Command.Filename); Instr_Name : constant String := (+Prj.Output_Dir) / Simple_Name; begin diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index fdd208c42..3f11fb2c5 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -317,4 +317,22 @@ package body Paths is and then Path (Path'First + 1) = ':'; end Starts_With_Drive_Pattern; + ---------------------------- + -- Workaround_Simple_Name -- + ---------------------------- + + function Workaround_Simple_Name (Path : String) return String is + begin + -- Return the Path suffix that precedes the first directory separator + -- according to the current platform. Return the full string if there is + -- no separator. + + for I in reverse Path'Range loop + if Path (I) = '/' or else (On_Windows and then Path (I) = '\') then + return Path (I + 1 .. Path'Last); + end if; + end loop; + return Path; + end Workaround_Simple_Name; + end Paths; diff --git a/tools/gnatcov/paths.ads b/tools/gnatcov/paths.ads index a7bc5dc55..c67729e7f 100644 --- a/tools/gnatcov/paths.ads +++ b/tools/gnatcov/paths.ads @@ -66,4 +66,9 @@ package Paths is -- TODO??? Handle Unicode file names + function Workaround_Simple_Name (Path : String) return String; + -- TODO??? (eng/toolchain/gnat#603) The native GNAT runtime has a bug on + -- Unix systems: Ada.Directories.Simple_Name misbehaves in the presence of + -- backslashes. Provide our own implementation as a workaround. + end Paths; From 2b3f0eeda3221ac74e79877fccb6abcd5f945d23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 21 Nov 2023 14:29:03 +0100 Subject: [PATCH 0538/1483] Testsuite: various changes to allow native light runtime runs This commit brings various changes that allow the execution of the testsuite for a native target with a light runtime: - Fix light runtime detection pattern in RuntimeInfo; - Add missing RTS_ZFP filters for native only tests that use lagnuage features not available in the light runtime; - Remove exit code checking on native light runtime program execution, as the programs do not set the exit status code, often resulting in it being non-zero despite a normal termination of the program. This is in preparation of the introduction of CCG testing. --- .../Appendix/Testsuite/Selftest/assert-failure/test.opt | 1 + testsuite/SUITE/control.py | 5 ++++- testsuite/SUITE/tutils.py | 8 ++++++++ testsuite/tests/C/stmt/NA28-015-default-return/test.opt | 3 ++- testsuite/tests/M724-035-eh-warnings/test.opt | 2 +- testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt | 1 + testsuite/tests/U901-029-estamps/test.opt | 1 + testsuite/tests/V309-017-setup-config/test.opt | 4 +++- testsuite/tests/instr-cov/bin_file_tunings/test.opt | 1 + testsuite/tests/instr-cov/default_dump_channel/test.opt | 1 + .../tests/instr-cov/expr_func/program_error/test.opt | 1 + testsuite/tests/instr-cov/stmt_after_accept/test.opt | 1 + testsuite/tests/integrated_instrumentation/extra.opt | 2 +- testsuite/tests/shared-libs/extra.opt | 1 + testsuite/tests/trace_name/test.opt | 1 + 15 files changed, 28 insertions(+), 5 deletions(-) create mode 100644 testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.opt diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.opt b/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.opt new file mode 100644 index 000000000..916096d15 --- /dev/null +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.opt @@ -0,0 +1 @@ +native,RTS_ZFP DEAD Test assumes bin file available on native platform diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index 7c6e63206..930a96638 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -252,7 +252,10 @@ def __init__(self, runtime_name=None): elif self.runtime_name.startswith('zfp'): self.has_light_runtime = True self.has_exception_propagation = False - elif self.runtime_name.startswith('light-'): + elif ( + self.runtime_name == "light" + or self.runtime_name.startswith('light-') + ): self.has_light_runtime = True self.has_exception_propagation = False elif self.runtime_name == 'kernel': diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 7c2dde6d9..7c7800193 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -852,6 +852,14 @@ def run_cov_program(executable, out=None, env=None, exec_args=None, # failing. Redirecting the standard input to /dev/null works around # this issue. inp = DEVNULL + else: + # Native programs using a light runtime can't set the exit code, and + # will often terminate with a non-zero status code even though nothing + # went wrong. There is thus no point in checking the exit code in this + # configuration. + register_failure = ( + register_failure and not RUNTIME_INFO.has_light_runtime + ) args.append(executable) args.extend(exec_args) diff --git a/testsuite/tests/C/stmt/NA28-015-default-return/test.opt b/testsuite/tests/C/stmt/NA28-015-default-return/test.opt index 6d0b18e7b..cbce755aa 100644 --- a/testsuite/tests/C/stmt/NA28-015-default-return/test.opt +++ b/testsuite/tests/C/stmt/NA28-015-default-return/test.opt @@ -1 +1,2 @@ -!x86-linux,!x86_64-linux DEAD test relies on passing command line arguments \ No newline at end of file +!x86-linux,!x86_64-linux DEAD test relies on passing command line arguments +RTS_ZFP DEAD test relies on bin-file dump channel diff --git a/testsuite/tests/M724-035-eh-warnings/test.opt b/testsuite/tests/M724-035-eh-warnings/test.opt index b00e5f3be..e0e4e6687 100644 --- a/testsuite/tests/M724-035-eh-warnings/test.opt +++ b/testsuite/tests/M724-035-eh-warnings/test.opt @@ -1,2 +1,2 @@ ALL DEAD -native +native,!RTS_ZFP diff --git a/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt index a34c07f1d..843545d10 100644 --- a/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt +++ b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt @@ -1 +1,2 @@ !native DEAD Uses full runtime only constructs +RTS_ZFP DEAD Uses full runtime only constructs \ No newline at end of file diff --git a/testsuite/tests/U901-029-estamps/test.opt b/testsuite/tests/U901-029-estamps/test.opt index 6da46e6e4..2b60383b6 100644 --- a/testsuite/tests/U901-029-estamps/test.opt +++ b/testsuite/tests/U901-029-estamps/test.opt @@ -1 +1,2 @@ src-traces,!native DEAD checking trace stamp, no way to get from BB programs +native,RTS_ZFP DEAD checking trace stamp, no way to get it from light runtime diff --git a/testsuite/tests/V309-017-setup-config/test.opt b/testsuite/tests/V309-017-setup-config/test.opt index 11b852e4b..d39effadc 100644 --- a/testsuite/tests/V309-017-setup-config/test.opt +++ b/testsuite/tests/V309-017-setup-config/test.opt @@ -1,4 +1,6 @@ -- This test needs to check that --dump-channel is properly handled in a -- typical gnatcov usage workflow. To do this, it needs multiple dump channels --- to be supported, i.e. a native platform (bin-file and base64-stdout). +-- to be supported, i.e. a native platform (bin-file and base64-stdout), and +-- a full runtime. !native DEAD +RTS_ZFP DEAD diff --git a/testsuite/tests/instr-cov/bin_file_tunings/test.opt b/testsuite/tests/instr-cov/bin_file_tunings/test.opt index a78189307..57852c494 100644 --- a/testsuite/tests/instr-cov/bin_file_tunings/test.opt +++ b/testsuite/tests/instr-cov/bin_file_tunings/test.opt @@ -1 +1,2 @@ !native DEAD Test specific to source trace binary files directly produced by automatic main instrumentation +RTS_ZFP DEAD Test required bin-file dump channel to be available diff --git a/testsuite/tests/instr-cov/default_dump_channel/test.opt b/testsuite/tests/instr-cov/default_dump_channel/test.opt index cb7409573..856e8dc72 100644 --- a/testsuite/tests/instr-cov/default_dump_channel/test.opt +++ b/testsuite/tests/instr-cov/default_dump_channel/test.opt @@ -1,2 +1,3 @@ !src-traces DEAD Checks a feature specific to the instrumenter !native DEAD Checks the default dump channel (bin-file, native only) +RTS_ZFP DEAD requires bin-file available diff --git a/testsuite/tests/instr-cov/expr_func/program_error/test.opt b/testsuite/tests/instr-cov/expr_func/program_error/test.opt index a1aa0f330..832969ef5 100644 --- a/testsuite/tests/instr-cov/expr_func/program_error/test.opt +++ b/testsuite/tests/instr-cov/expr_func/program_error/test.opt @@ -1 +1,2 @@ !native DEAD Testcase requires standard Ada containers +RTS_ZFP DEAD Testcase requires standard Ada containers diff --git a/testsuite/tests/instr-cov/stmt_after_accept/test.opt b/testsuite/tests/instr-cov/stmt_after_accept/test.opt index a34c07f1d..caccd7ad3 100644 --- a/testsuite/tests/instr-cov/stmt_after_accept/test.opt +++ b/testsuite/tests/instr-cov/stmt_after_accept/test.opt @@ -1 +1,2 @@ !native DEAD Uses full runtime only constructs +RTS_ZFP DEAD Uses full runtime constructs diff --git a/testsuite/tests/integrated_instrumentation/extra.opt b/testsuite/tests/integrated_instrumentation/extra.opt index 4ce8274d5..f38570883 100644 --- a/testsuite/tests/integrated_instrumentation/extra.opt +++ b/testsuite/tests/integrated_instrumentation/extra.opt @@ -1,2 +1,2 @@ -native,linux,src-traces,!5.04a1,!7.1.2 +native,linux,src-traces,!5.04a1,!7.1.2,!RTS_ZFP ALL DEAD Prototype for integrated instrumentation functional for native linux diff --git a/testsuite/tests/shared-libs/extra.opt b/testsuite/tests/shared-libs/extra.opt index cd0601689..2057bb8c4 100644 --- a/testsuite/tests/shared-libs/extra.opt +++ b/testsuite/tests/shared-libs/extra.opt @@ -1,2 +1,3 @@ !native DEAD Shared libraries exist only for native platforms bin-traces XFAIL OA05-051: bin-traces and shared libs +RTS_ZFP DEAD can't build shared gnatcov_rts with light runtime diff --git a/testsuite/tests/trace_name/test.opt b/testsuite/tests/trace_name/test.opt index b07d3aea8..2eb62c7a9 100644 --- a/testsuite/tests/trace_name/test.opt +++ b/testsuite/tests/trace_name/test.opt @@ -1 +1,2 @@ !native,src-traces DEAD Check default trace file name (dump-channel=bin-file) +native,RTS_ZFP DEAD Check default trace file name (dump-channel=bin-file) From 11582b6ef3ef398f0c2f4c2cccc6d10779256f0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 21 Nov 2023 14:37:21 +0100 Subject: [PATCH 0539/1483] libsupport.gpr: minimize C language inclusion In preparation to the introduction of a CCG testsuite run, minimize the cases in which C is listed as a required language in libsupport.gpr. CCG does not support compiling projects with C sources. As such, only include the C language in a cross targeted scenario, when there actually are C files to be compiled. --- tools/gnatcov/examples/support/libsupport.gpr | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/examples/support/libsupport.gpr b/tools/gnatcov/examples/support/libsupport.gpr index 7c5bfb331..91fc3ad60 100644 --- a/tools/gnatcov/examples/support/libsupport.gpr +++ b/tools/gnatcov/examples/support/libsupport.gpr @@ -20,7 +20,8 @@ library project Libsupport is for Library_Kind use "static"; for Library_Auto_Init use "False"; - for Languages use ("Ada", "C"); + + Langs := ("Ada"); for Library_Dir use "lib/" & Conf.Target; for Object_Dir use "obj/" & Conf.Target; @@ -47,10 +48,12 @@ library project Libsupport is Source_Dirs := ("src", "src/helpers"); case Conf.Target is - when "" => null; + when "" | "c" => null; when others => + Langs := Langs & ("C"); + Source_Dirs := Source_Dirs & ("src/memory"); Source_Dirs := Source_Dirs & ("src/" & Conf.Target); @@ -71,7 +74,9 @@ library project Libsupport is ("src/last_chance_" & Conf.Board); end case; - end case; + end case; + + for Languages use Langs; for Source_Dirs use Source_Dirs; From d31efbf8af6430d92ae0d9bf7c16e92a81639274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 21 Nov 2023 14:42:36 +0100 Subject: [PATCH 0540/1483] Makefile.Libsupport: add more customization options This change allows the customization of the exit mechanism in the last chance handler, and to pass compilation flags when building the support library. This is in preparation of the introduction of a CCG testsuite run. The heuristics to choose which compilation flags need to be passed to gprbuild, and which exit mechanism needs to be used in the last chance handler do not work in a CCG context. Instead of adding corner cases for each configuration, allow configuring these features during the make invocation. --- tools/gnatcov/examples/support/Makefile.libsupport | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/examples/support/Makefile.libsupport b/tools/gnatcov/examples/support/Makefile.libsupport index 5ca39c4e8..c08b4d3e6 100644 --- a/tools/gnatcov/examples/support/Makefile.libsupport +++ b/tools/gnatcov/examples/support/Makefile.libsupport @@ -7,7 +7,7 @@ include Makefile.common # at this stage. ifneq ($(TARGET),) -LIBSUPPORT_CFLAGS=-fdump-scos -fpreserve-control-flow -g +LIBSUPPORT_CFLAGS:=-fdump-scos -fpreserve-control-flow -g $(LIBSUPPORT_CFLAGS) endif all: $(SUPPORT_TARGET_SRC_DIR) $(LIBSUPPORT_DIR) LIBSUPPORT LCH @@ -21,7 +21,7 @@ all: $(SUPPORT_TARGET_SRC_DIR) $(LIBSUPPORT_DIR) LIBSUPPORT LCH # Pick a default kind of silent last chance handler, that users of this # Makefile can override if needed, e.g. for VxWorks kinds of configurations # which are cross targets with "full" runtimes akin to native profiles. -SILENT_LCH = $(strip $(if $(TARGET), abort, exit)) +SILENT_LCH ?= $(strip $(if $(TARGET), abort, exit)) conf.gpr: force sed -e 's/%TARGET%/$(TARGET)/g' \ From 14ae4c9e9488ca3cd1f82ddaa48248d5b7a20dc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 21 Nov 2023 14:49:35 +0100 Subject: [PATCH 0541/1483] Testsuite: Allow altruns to specify an alternate builder The altrun mechanism allows to specify alternate programs for all the "gnatcov " commands. To be able to support CCG, we also need to be able to override which builder is used. This change adds the possibility to specify an overriding program for gprbuild. Note that gprbuild still needs to be present on path, as it will be used when dumping version information, and to build the support library, as this is done through a Makefile out of the testsuite's control. --- testsuite/SUITE/context.py | 6 ++++++ testsuite/SUITE/control.py | 19 +++++++++++++++---- testsuite/SUITE/tutils.py | 7 ++++++- testsuite/testsuite.py | 19 +++++++++++++++++-- 4 files changed, 44 insertions(+), 7 deletions(-) diff --git a/testsuite/SUITE/context.py b/testsuite/SUITE/context.py index 2a169511a..99b80e976 100644 --- a/testsuite/SUITE/context.py +++ b/testsuite/SUITE/context.py @@ -459,6 +459,12 @@ def suite_covpgm_for(self, cmd): """ return getattr(thistest.options, 'gnatcov_%s' % cmd, None) + def suite_gprpgm_for(self, pgm): + """ + Alternate program to launch in lieu of "gpr", + """ + return getattr(thistest.options, pgm, None) + def support_dir(self): return os.path.join(ROOT_DIR, 'support') diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index 930a96638..29d569a36 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -384,16 +384,19 @@ def gnatcov_info(): ('pre', 'testcase'), ('post', 'testcase')) +# Allowed alternatives for the --gpr family of command line options +ALTRUN_GPR = ('gprbuild', ) -def altrun_opt_for(p0, p1): + +def altrun_opt_for(p0, p1=None): """Name of the command line option controlling the ALTRUN (P0, P1) pair.""" - return "%s_%s" % (p0, p1) + return "%s_%s" % (p0, p1) if p1 else p0 -def altrun_attr_for(p0, p1): +def altrun_attr_for(p0, p1=None): """Name of our internal controlling options attribute for the ALTRUN (P0, P1) pair.""" - return "%s_%s" % (p0, p1) + return "%s_%s" % (p0, p1) if p1 else p0 def cargs_opt_for(lang): @@ -422,6 +425,14 @@ def add_shared_options_to(parser, toplevel): metavar="CMD", help='Use CMD instead of "%s %s"' % (pgm, cmd)) + # --gpr family + for pgm in ALTRUN_GPR: + parser.add_argument( + f'--{altrun_opt_for(pgm)}', dest=altrun_attr_for(pgm), + metavar="CMD", + help=f'use CMD instead of "{pgm}"' + ) + # Valgrind control parser.add_argument( '--enable-valgrind', dest='enable_valgrind', diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 7c7800193..f6f53cd90 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -291,7 +291,12 @@ def gprbuild(project, # Now cleanup, do build and check status thistest.cleanup(project) - args = (to_list(BUILDER.BASE_COMMAND) + + builder = thistest.suite_gprpgm_for(os.path.basename(BUILDER.BASE_COMMAND)) + + if builder is None: + builder = BUILDER.BASE_COMMAND + + args = (to_list(builder) + ['-P%s' % project] + all_gargs + all_cargs + all_largs) p = run_and_log(args, output=out, timeout=thistest.options.timeout) if register_failure: diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 44a42efe0..9f12fc48f 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -579,6 +579,15 @@ def set_up(self): 'opt': altrun_opt_for(pgm, cmd), 'val': getattr(mopt, altrun_attr_for(pgm, cmd))}) + # --gpr family + for pgm in control.ALTRUN_GPR: + if getattr(mopt, altrun_attr_for(pgm)) is None: + continue + testcase_cmd.append( + f"--{altrun_opt_for(pgm)}=" + f"{getattr(mopt, altrun_attr_for(pgm))}" + ) + # --cargs family for lang in [None] + control.KNOWN_LANGUAGES: @@ -1480,7 +1489,9 @@ def _resolve_paths(self): ["kernel", "altrun"] + [altrun_attr_for(p0, p1) for p0, p1 in (control.ALTRUN_HOOK_PAIRS - + control.ALTRUN_GNATCOV_PAIRS)]) + + control.ALTRUN_GNATCOV_PAIRS)] + + [altrun_attr_for(p0) for p0 in control.ALTRUN_GPR] + ) for attr in attributes_to_resolve: current_value = getattr(self.main.args, attr) @@ -1582,7 +1593,7 @@ def _setup_altrun_hooks(self): self.maybe_exec( bin=self._bin_for("setup", indir=ctldir), edir=ctldir) - def install_altrun_for(p0, p1, binbase): + def install_altrun_for(p0, p1=None, binbase=None): """Establish an implicit value for the --P0_P1 command line option if we find a matching binary program in the altrun subdir we are processing. BINBASE provides the binary base name to use.""" @@ -1614,6 +1625,10 @@ def install_altrun_for(p0, p1, binbase): for pgm, cmd in control.ALTRUN_GNATCOV_PAIRS: install_altrun_for(p0=pgm, p1=cmd, binbase="c%s" % cmd) + # For the gpr replacements, map on binaries called cgpr: + for pgm in control.ALTRUN_GPR: + install_altrun_for(p0=pgm, p1=None, binbase=f"c{pgm}") + if __name__ == "__main__": sys.exit(TestSuite().testsuite_main()) From 6864cab81cba5823e9aae32a64748efca654f902 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 22 Nov 2023 17:04:57 +0100 Subject: [PATCH 0542/1483] gnatcov_rts.gpr: Add configuration for use with CCG toolchain The CCG toolchain does not support compiling C code. As such, in order to be able to use GNATcov_RTS with this toolchain, there must be no C sources in the project, and no references to C files. This change introduces a new configuration variable, For_CCG, which when active removes C from the source languages, and removes C source exclusions. --- tools/gnatcov/rts/gnatcov_rts.gpr | 37 ++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts.gpr b/tools/gnatcov/rts/gnatcov_rts.gpr index b21b1f023..4e832e618 100644 --- a/tools/gnatcov/rts/gnatcov_rts.gpr +++ b/tools/gnatcov/rts/gnatcov_rts.gpr @@ -35,6 +35,11 @@ library project GNATcov_RTS is -- gnatcov_rts_c-base_io.c C unit instead (implemented on top of libc's -- stdout/fwrite/putchar). + For_CCG : Boolean := external ("GNATCOV_RTS_FOR_CCG", "false"); + -- Whether to configure the project for compilation with CCG. This means + -- excluding C from the source languages, as there is no C compiler for that + -- environment and C sources need to be managed manually. + RTS_Profile : RTS_Profile_Type := external ("GNATCOV_RTS_RTS_PROFILE", "full"); @@ -42,18 +47,24 @@ library project GNATcov_RTS is -- Configuration logic -- ------------------------- - Languages := ("C"); + Languages := (); Excluded_Source_Files := (); -- Compute the set of languages for this project. When Ada is enabled, -- exclude the C implementation for stdout output primitives. case With_Ada is - when "false" => null; + when "false" => + Languages := ("C"); when "true" => - Languages := Languages & ("Ada"); - Excluded_Source_Files := - Excluded_Source_Files & ("gnatcov_rts_c-base_io.c"); + Languages := ("Ada"); + case For_CCG is + when "true" => null; + when "false" => + Excluded_Source_Files := + Excluded_Source_Files & ("gnatcov_rts_c-base_io.c"); + Languages := Languages & ("C"); + end case; end case; -- If the runtime does not have support to create files, exclude units that @@ -64,11 +75,17 @@ library project GNATcov_RTS is Excluded_Source_Files := Excluded_Source_Files & ("gnatcov_rts-traces-output-files.adb", - "gnatcov_rts-traces-output-files.ads", - "gnatcov_rts_c-os_interface.c", - "gnatcov_rts_c-os_interface.h", - "gnatcov_rts_c-traces-output-files.c", - "gnatcov_rts_c-traces-output-files.h"); + "gnatcov_rts-traces-output-files.ads"); + case For_CCG is + when "true" => null; + when "false" => + Excluded_Source_Files := + Excluded_Source_Files + & ("gnatcov_rts_c-os_interface.c", + "gnatcov_rts_c-os_interface.h", + "gnatcov_rts_c-traces-output-files.c", + "gnatcov_rts_c-traces-output-files.h"); + end case; when "full" => null; end case; From f86f4a67166e0c742ac27727e3193fa9dbc45b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 21 Nov 2023 15:01:31 +0100 Subject: [PATCH 0543/1483] Testsuite: Add an altrun for CCG This altrun allows the testsuite to build test executables through CCG, for a native target. The altrun inlcudes: - a pre_testsuite.py script that prepares the coverage runtime, the support library and the Ada runtime; - a cgprbuild.py script that is meant to replace gprbuild. It invokes CCG through gprbuild, then collects all the generated C files and compiles them to generate an executable; - various other files used by the two above scripts as build helpers. Note that CCG does not support compiling projects that have C listed as a project language, the binder will thus not execute and no main will be generated. As such, it is best not to run the full testsuite with this altrun but only a subset of tests which only contains Ada sources, such as Qualif/Ada. --- .gitignore | 2 + .../MixedConstructs/If_ElsAbs/test.opt | 1 + .../MachineCode/Inserts_In_Cond/test.opt | 1 + .../Ada/stmt/Robustness/Multinops/test.opt | 1 + testsuite/SUITE/control.py | 19 +- testsuite/SUITE/tutils.py | 2 +- testsuite/altrun/ccg_native/cgprbuild.py | 175 ++++++++++++++ testsuite/altrun/ccg_native/libgnat.gpr | 6 + testsuite/altrun/ccg_native/pre_testsuite.py | 217 ++++++++++++++++++ testsuite/testsuite.py | 30 +-- 10 files changed, 425 insertions(+), 29 deletions(-) create mode 100644 testsuite/Qualif/Ada/decision/MixedConstructs/If_ElsAbs/test.opt create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/test.opt create mode 100644 testsuite/Qualif/Ada/stmt/Robustness/Multinops/test.opt create mode 100755 testsuite/altrun/ccg_native/cgprbuild.py create mode 100644 testsuite/altrun/ccg_native/libgnat.gpr create mode 100644 testsuite/altrun/ccg_native/pre_testsuite.py diff --git a/.gitignore b/.gitignore index f65e4e605..673b8675a 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,8 @@ lib /testsuite/suite.cgpr /testsuite/support /testsuite/tmp +/testsuite/altrun/ccg_native/ccg_gnatcov_rts +/testsuite/altrun/ccg_native/adainclude gnatcov-loc.xml gnatinspect.db README.html diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_ElsAbs/test.opt b/testsuite/Qualif/Ada/decision/MixedConstructs/If_ElsAbs/test.opt new file mode 100644 index 000000000..cccf1c20d --- /dev/null +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_ElsAbs/test.opt @@ -0,0 +1 @@ +c XFAIL Runtime check bug in CCG, see eng/toolchain/gnat-llvm#73 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/test.opt new file mode 100644 index 000000000..531c42810 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/test.opt @@ -0,0 +1 @@ +c DEAD ASM inlining not supported by CCG diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Multinops/test.opt b/testsuite/Qualif/Ada/stmt/Robustness/Multinops/test.opt new file mode 100644 index 000000000..531c42810 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/Robustness/Multinops/test.opt @@ -0,0 +1 @@ +c DEAD ASM inlining not supported by CCG diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index 29d569a36..e4ab2a038 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -241,23 +241,29 @@ def __init__(self, runtime_name=None): self.has_kernel_runtime = False self.has_light_runtime = False self.has_exception_propagation = True + self.discrs = [] if not self.runtime_name: self.has_full_runtime = True + self.discrs = ["RTS_FULL"] elif 'embedded' in self.runtime_name: self.has_ravenscar_runtime = True + self.discrs = ["RTS_RAVENSCAR", "RTS_EMBEDDED"] elif 'light-tasking' in self.runtime_name: self.has_ravenscar_runtime = True self.has_exception_propagation = False + self.discrs = ["RTS_RAVENSCAR", "RTS_LIGHT_TASKING"] elif self.runtime_name.startswith('zfp'): self.has_light_runtime = True self.has_exception_propagation = False + self.discrs = ["RTS_ZFP"] elif ( self.runtime_name == "light" or self.runtime_name.startswith('light-') ): self.has_light_runtime = True self.has_exception_propagation = False + self.discrs = ["RTS_ZFP"] elif self.runtime_name == 'kernel': self.has_kernel_runtime = True else: @@ -276,12 +282,19 @@ def gnatcov_rts_project(self): else 'gnatcov_rts' ) -def runtime_info(runtime=None): - if runtime is None: - runtime = env.main_options.RTS +def _runtime_info(runtime, target): + if target == "c": + assert not runtime + # CCG's runtime has no name, but it is for our purposes equivalent + # to a light runtime. + runtime = "light" return RuntimeInfo(runtime) +def runtime_info(): + return _runtime_info(env.main_options.RTS, env.target.platform) + + # Target specificities. We don't have many variants but need to match each # against a few possible triplets. diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index f6f53cd90..bb613e46a 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -841,7 +841,7 @@ def run_cov_program(executable, out=None, env=None, exec_args=None, inp = None # If we are in a cross configuration, run the program using GNATemulator - if thistest.options.target: + if thistest.options.target and thistest.env.target.platform != "c": kernel = thistest.options.kernel board = thistest.options.board or thistest.env.target.machine args.append('{}-gnatemu'.format(thistest.env.target.triplet)) diff --git a/testsuite/altrun/ccg_native/cgprbuild.py b/testsuite/altrun/ccg_native/cgprbuild.py new file mode 100755 index 000000000..0c5ba38cc --- /dev/null +++ b/testsuite/altrun/ccg_native/cgprbuild.py @@ -0,0 +1,175 @@ +#!/usr/bin/env python3 + +import argparse +import json +import os +import pathlib + +from e3.os.process import Run +from e3.platform import Platform + + +def parse_scenario(arg: str): + """ + Helper to parse -XVAR[=VAL] command line options. + If VAL is not specified in the argument, consider this an ill formed + argument and ignore it. + """ + return arg.split("=", maxsplit=1) if "=" in arg else None + + +def get_attr(obj, attr_name, idx=0): + """ + Get the value of the attribute named attr_name, at index idx if relevant. + If no such attribute exists, returns None. + """ + attrs = obj["projects"][0]["attributes"] + for attr_ob in attrs: + if attr_ob["name"] == attr_name: + if attr_ob["kind"] == "single": + return attr_ob["value"] + else: + return attr_ob["values"][idx] + return None + + +def run(cmd, what): + """ + Run the command represented by cmd in a subprocess. If the exit status is + not success and ignore_failure is True, print f"{what} failed" followed by + the command output on the standard output and exit with an error. + Otherwise, return the output of the command execution. + """ + p = Run(cmd) + if p.status != 0: + print(f"{what} failed:") + print(p.command_line_image()) + print(p.out) + exit(1) + return p.out + + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-P", dest="project") + parser.add_argument("--config", dest="config") + parser.add_argument("--target", dest="target") + parser.add_argument("--RTS", dest="rts") + parser.add_argument("--src-subdirs", dest="src_subdirs") + parser.add_argument("--implicit-with", dest="implicit_with") + parser.add_argument( + "-X", dest="scenario", action="append", type=parse_scenario, + ) + parser.add_argument("-v", dest="verbose", action="store_true") + + args, extra = parser.parse_known_args() + + altrun_dir = os.path.dirname(os.path.realpath(__file__)) + + # Substitute the "--implicit-with=gnatcov_rts.gpr" to point it toward our + # own custom RTS. + ccg_gnatcov_rts = os.path.join( + altrun_dir, "ccg_gnatcov_rts", "gnatcov_rts.gpr", + ) + custom_rts_dir = None + if args.implicit_with and "gnatcov_rts" in args.implicit_with: + custom_rts_dir = os.path.dirname(ccg_gnatcov_rts) + args.implicit_with = ccg_gnatcov_rts + + # Build common args for all gpr commands + common_args = ["--target=c"] + common_args += ["-P", args.project] + if args.src_subdirs: + common_args += [f"--src-subdirs={args.src_subdirs}"] + if args.implicit_with: + common_args += [f"--implicit-with={args.implicit_with}"] + for key, val in args.scenario: + common_args += [f"-X{key}={val}"] + + # Add specific scenario for our custom version of gnatcov rts: + common_args.append("-XGNATCOV_RTS_RTS_PROFILE=embedded") + common_args.append("-XGNATCOV_RTS_FOR_CCG=true") + + if "-cargs" in extra: + cargs_index = extra.index("-cargs") + extra.insert(cargs_index + 1, f"-mtriple={Platform.get().triplet}") + else: + extra += ["-cargs", f"-mtriple={Platform.get().triplet}"] + + # Generate C files + gprbuild_args = ["gprbuild"] + common_args + extra + run(gprbuild_args, "gprbuild invocation") + + # Gather information about the project structure, we need the name of the + # main (to generate an executable of the same name), the list of object + # directories, the root directory of the project (as all other directories + # are relatives to this), and the directory in which to place the + # executable. + gprinspect_args = ( + ["gprinspect"] + + common_args + + ["--attributes", "--display=json-compact"] + ) + prj_txt = run(gprinspect_args, "gprinspect invocation") + prj = json.loads(prj_txt) + + # Assume single main per project file + main_name = os.path.basename(get_attr(prj, "Main")).split(".")[0] + prj_dir = get_attr(prj, "Project_Dir") + exec_dir = os.path.join(prj_dir, get_attr(prj, "Exec_Dir")) + obj_dir = os.path.join(prj_dir, get_attr(prj, "Object_Dir")) + + # Get the list of all the generated C files that need to be compiled. gprls + # will return a list of ".o" files, so replace the extension to ".c" + gprls_args = ["gprls"] + common_args + ["-o", "-U"] + + c_files = run(gprls_args, "gprls invocation").splitlines() + c_files = [f for f in c_files if f[-2:] == ".c"] + # Add the generated binder file in order to be able to link the executable + c_files.append(os.path.join(obj_dir, "b__" + main_name + ".c")) + + # Hack: given the characteristics passed to the runtime (light runtime), + # it will always add a "last_chance_dumper" unit which defines the symbol + # __lch_enter. This symbol is also defined in the Libsupport unit, as part + # of the Libsupport library. This normally is a static library, and thus + # the object for __lch_enter should not be pulled during the link, but with + # ccg we don't build any libraries. as such we must exclude libsupport.c + # from the gcc invocation to avoid having multiple definitions of + # __lch_enter. + c_files = [ + filename + for filename in c_files + if os.path.basename(filename) != "libsupport.c" + ] + + gcc_args = ["gcc"] + + if "-g" in extra: + gcc_args += ["-g"] + + gcc_args += c_files + + # Add the list of native C files from gnatcov_rts: the project was modified + # to not include C as a language (to avoid gprbuild issues), but these are + # still required for a successful build. + if custom_rts_dir: + rts_dir = pathlib.Path(custom_rts_dir) + gcc_args += [ + str(pth.absolute()) for pth in rts_dir.glob("gnatcov_rts_c*") + ] + + # Add the runtime library in the mix. The pre-testsuite script compile the + # library and does not bother to create a separate adalib directory for the + # compilation results + gcc_args += [os.path.join(altrun_dir, "adainclude", "libgnat.a")] + + # Compile the executable + gcc_args += [ + "-o", + os.path.join(exec_dir, main_name + Platform.get().os.exeext), + ] + run(gcc_args, "gcc invocation") + + +if __name__ == "__main__": + main() diff --git a/testsuite/altrun/ccg_native/libgnat.gpr b/testsuite/altrun/ccg_native/libgnat.gpr new file mode 100644 index 000000000..c6de94576 --- /dev/null +++ b/testsuite/altrun/ccg_native/libgnat.gpr @@ -0,0 +1,6 @@ +project Libgnat is + + for Source_Dirs use ("adainclude"); + for Object_Dir use "adainclude"; + +end Libgnat; diff --git a/testsuite/altrun/ccg_native/pre_testsuite.py b/testsuite/altrun/ccg_native/pre_testsuite.py new file mode 100644 index 000000000..b70e10839 --- /dev/null +++ b/testsuite/altrun/ccg_native/pre_testsuite.py @@ -0,0 +1,217 @@ +""" +Setup everything needed to be able to compile an instrumented executable with +CCG. This includes as custom version of gnatcov_rts, building the Ada runtime +for the proper platform, and pre-building libsupport. +""" + +import json +import os +from pathlib import Path +from shutil import which + +from e3.fs import rm, cp, mkdir, mv +from e3.os.process import Run +from e3.platform import Platform + +altrun_dir = os.path.dirname(os.path.realpath(__file__)) + +custom_rts_dir = os.path.join(altrun_dir, "ccg_gnatcov_rts") +custom_rts_prj = os.path.join(custom_rts_dir, "gnatcov_rts.gpr") + +exeext = Platform.get().os.exeext + +gnatcov = which("gnatcov" + exeext) +base_rts_dir = os.path.join( + os.path.dirname(gnatcov), "..", "share", "gnatcoverage", "gnatcov_rts" +) + + +def run(cmd, what): + """ + Run the command represented by cmd in a subprocess. If the exit status is + not success and ignore_failure is True, print f"{what} failed" followed by + the command output on the standard output and exit with an error. + Otherwise, return the output of the command execution. + """ + p = Run(cmd) + if p.status != 0: + print(f"{what} failed:") + print(p.command_line_image()) + print(p.out) + exit(1) + return p.out + + +def amend_file(filename, substs): + """ + Given a list of (pattern, subst) tuple of strings, search for each line, if + some pattern is present in the line (string comparison), and replace the + whole line with the corresponding substitution string. Otherwise, leave the + line unchanged. + The substitution string corresponding to the first matching pattern is + applied, then processing moves on to the next line in the source file. + """ + source = filename + ".source" + mv(filename, source) + found = False + with open(source, "r") as src: + with open(filename, "w") as dest: + for line in src.readlines(): + found = False + for pat, sub in substs: + if pat in line: + found = True + dest.write(sub + "\n") + break + if not found: + dest.write(line) + rm(source) + + +def prepare_rts(): + rm(custom_rts_dir, recursive=True) + mkdir(custom_rts_dir) + + # Copy the runtime and remove obj and lib dirs if they exist + cp(os.path.join(base_rts_dir, "*"), custom_rts_dir, recursive=True) + rm(os.path.join(custom_rts_dir, "obj-*"), recursive=True) + rm(os.path.join(custom_rts_dir, "lib-*"), recursive=True) + + # Remove gnatcov_rts_c-base_io.c as it would interfere with the symbols + # defined in gnatcov_rts-base_io.adb, and the C files that should not + # be compiled when the RTS profile is "embedded". + rm(os.path.join(custom_rts_dir, "gnatcov_rts_c-base_io.c")) + rm(os.path.join(custom_rts_dir, "gnatcov_rts_c-os_interface*")) + rm(os.path.join(custom_rts_dir, "gnatcov_rts_c-traces-output-files*")) + + # Amend gnatcov_rts-base_io.adb to change the dependency on GNAT.IO to + # Ada.Text_IO, the former not being available in the CCG runtime. + amend_file( + os.path.join(custom_rts_dir, "gnatcov_rts-base_io.adb"), + substs=[ + ("with GNAT.IO;", "with Ada.Text_IO;"), + ("GNAT.IO.Put (Str);", " Ada.Text_IO.Put (Str);"), + ], + ) + + # Pre-build gnatcov_rts + run( + [ + "gprbuild", + "--target=c", + "-P", + custom_rts_prj, + "-XGNATCOV_RTS_FOR_CCG=true", + "-XGNATCOV_RTS_RTS_PROFILE=embedded", + "-cargs", + f"-mtriple={Platform.get().triplet}", + ], + what="Custom gnatcov rts build", + ) + + # Flag it as externally built + amend_file( + custom_rts_prj, + [( + "end GNATcov_RTS;", + 'for Externally_Built use "True"; end GNATcov_RTS;' + )], + ) + + +# Prepare custom rts +prepare_rts() + +# Re-build the lib support with the correct target: +# First, clean any previous libsupport build +libsupport_home = os.path.join("..", "..", "support") +run( + ["make", "-C", libsupport_home, "-f", "Makefile.libsupport", "clean"], + what="libsupport cleaning", +) + +rm(os.path.join(libsupport_home, "silent_last_chance-*")) + +# Then build the libsupport with the correct configuration and cflags +run( + [ + "make", + "--debug", + "-C", + libsupport_home, + "-f", + "Makefile.libsupport", + "TARGET=c", + f"LIBSUPPORT_CFLAGS=-mtriple={Platform.get().triplet}", + "SILENT_LCH=exit", + ], + what="build of libsupport", +) + +# Build the Ada runtime for the correct target + +# First, determine where the runtime sources are located +prj_str = run( + [ + "gprinspect", + "-P", + custom_rts_prj, + "-XGNATCOV_RTS_FOR_CCG=true", + "-XGNATCOV_RTS_RTS_PROFILE=embedded", + "--target=c", + "--display=json-compact", + ], + what="gprinspect invocation" +) +try: + prj_info = json.loads(prj_str) +except: + print("failed parsing project info:") + print(prj_str) + exit(1) + +adainclude_dir = None +for path in prj_info["tree"]["source-search-paths"]: + if "adainclude" in path: + adainclude_dir = path + break +if not adainclude_dir: + print("could no find adainclude directory from gprinspect output") + print(prj_str) + exit(1) + +# Copy the sources in the altrun directory, in order not to modify the CCG +# build space. +local_rt = os.path.join(altrun_dir, "adainclude") +rm(local_rt, recursive=True) +cp(adainclude_dir, local_rt, recursive=True) + +# Transpile the runtime to C +run( + [ + "gprbuild", + "-P", + os.path.join(altrun_dir, "libgnat.gpr"), + "--target=c", + "-cargs", + f"-mtriple={Platform.get().triplet}", + "-gnatpg", + ], + what="compilation of the Ada runtime", +) + +# Compile all the C files +all_rt_src = [str(pth.absolute()) for pth in Path(local_rt).glob("*.c")] +all_obj_files = [] +for f in all_rt_src: + all_obj_files.append(f[:-2] + ".o") + run( + ["gcc", "-c", f, "-o", all_obj_files[-1], "-I", adainclude_dir], + what=f"compilation of {f}", + ) + +# Create the library per se. +run( + ["ar", "rcs", os.path.join(adainclude_dir, "libgnat.a")] + all_obj_files, + what="archival of the Ada runtime", +) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 9f12fc48f..e363b346f 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -40,7 +40,7 @@ import SUITE.control as control -from SUITE.control import BUILDER +from SUITE.control import BUILDER, _runtime_info from SUITE.control import altrun_opt_for, altrun_attr_for from SUITE.control import cargs_opt_for, cargs_attr_for @@ -1382,31 +1382,11 @@ def _rts_discriminants(self): support library in use, as conveyed by the --RTS command-line option. """ + return _runtime_info( + self.main.args.RTS, + self.env.target.platform + ).discrs - # Match light-tasking before light otherwise the wrong discriminant - # will be selected. - - # ex --RTS=powerpc-elf/light-tasking or --RTS=light-tasking - - if "light-tasking" in self.main.args.RTS: - return ["RTS_RAVENSCAR", "RTS_LIGHT_TASKING"] - - # --RTS=light- or --RTS=light (e.g. for VxWorks) correspond to - # the former zfp- variants - - elif "light" in self.main.args.RTS or "zfp" in self.main.args.RTS: - return ["RTS_ZFP"] - - # ex --RTS=powerpc-elf/embedded or --RTS=embedded or --RTS=ravenscar - - elif ("embedded" in self.main.args.RTS - or "ravenscar" in self.main.args.RTS): - return ["RTS_RAVENSCAR", "RTS_EMBEDDED"] - - # ex --RTS=native or --RTS=kernel, or no --RTS at all - - else: - return ["RTS_FULL"] def _toolchain_discriminants(self): """ From 51644077c037d9e8bc5ab5bda588f14baa351af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 23 Nov 2023 14:23:17 +0100 Subject: [PATCH 0544/1483] Document setup and build steps when building insturmented code with CCG This includes the modifications to be done to the coverage runtime, as well as the additionnal switches to be passed to GPRbuild. --- doc/gnatcov/src_traces.rst | 69 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 4f183aff7..bd06241ff 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -972,6 +972,7 @@ the default coverage runtime library, in practice only one use case is supported currently: changing the behavior of the ``--dump-channel=base64-stdout`` instrumentation option. +.. _custom_base_64: Customize the ``base64-stdout`` dump channel -------------------------------------------- @@ -1037,3 +1038,71 @@ file so that it implements the interface described in the (unmodified) const char *str; size_t length; }; + +Building instrumented programs with CCG +======================================= + +Programs instrumented with |gcvins| can be built using the +`GNAT Pro Common Code Generator `_ +provided a few modifications are made to the coverage runtime, and +respecting some limitations in terms of dump-trigger and dump-channel choice. + +Customizing the runtime +----------------------- + +Given the workflow associated with CCG, it is not possible to use the |gcvstp| +command to setup the coverage runtime. Instead, it must be prepared manually. + +The coverage runtime contains both Ada and C sources. When using CCG through +GPRbuild, projects containing C sources are not well handled and some steps of +the build procedure won't be executed. There thus is an external variable to +remove all C sources from the project. This means that C sources must be +manually managed during the executable compilation later on. + +The first step is to copy the runtime sources in a dedicated directory. For the +remainder of this section, it will be denoted by ``ccg_gnatcov_rts``. + +.. code-block:: sh + + mkdir ccg_gnatcov_rts + cp -r /share/gnatcoverage/gnatcov_rts ccg_gnatcov_rts + +Then, C sources not relevant to the coverage runtime for the CCG configuration +must be deleted: + +.. code-block:: sh + + rm ccg_gnatcov_rts/gnatcov_rts_c-base-io.c + rm ccg_gnatcov_rts/gnatcov_rts_c-trace-output-files.* + rm ccg_gnatcov_rts/gnatcov_rts_c-os_interface.* + +Finally, it is necessary to modify the contents of +``ccg_gnatcov_rts/gnatcov_rts-base_io.adb`` to use an alternate medium on which +the execution trace will be output. By default this relies on ``GNAT.IO``, +which is not available in the CCG runtime. It is possible to replace occurrences +of this unit by ``Ada.Text_IO``, which is supported by CCG, but which relies on +the C standard function ``putchar``. Otherwise, see :ref:`custom_base_64` for +more details on the expected interface to dump the coverage trace information. + +Building an instrumented program with CCG +----------------------------------------- + +Building an instrumented program with CCG is done in the same manner as with +any other target, with the exception that GPRbuild must be instructed to use +the custom coverage runtime prepared in the previous step, and by setting an +external variable to configure the coverage runtime project for a build with +CCG: + +.. code-block:: sh + + gprbuild -P --src-subdirs=gnatcov-instr \ + --implicit-with=ccg_gnatcov_rts/gnatcov_rts.gpr \ + -XGNATCOV_RTS_FOR_CCG=true \ + + +After the generation of C sources is complete, all the coverage runtime C sources +must be included in the build process of the executable. These can be found +under ``ccg_gnatcov_rts/`` for the sources already present before the gprbuild +invocation, and under ``ccg_gnatcov_rts/obj-gnatcov_rts.static`` for the sources +generated by CCG. The C sources generated from the instrumented Ada sources will +be available in the object directory of their corresponding project. From 131d43f224bd0ba93a876f2e83cb739ef6fce2bf Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 8 Dec 2023 14:42:59 +0000 Subject: [PATCH 0545/1483] Consistently use Switches.Save_Temps instead of the raw cmdline argument --- tools/gnatcov/instrument-clean_objdirs.adb | 3 +-- tools/gnatcov/instrument-projects.adb | 2 +- tools/gnatcov/project.adb | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/instrument-clean_objdirs.adb b/tools/gnatcov/instrument-clean_objdirs.adb index f2191f3e5..bf43f1d45 100644 --- a/tools/gnatcov/instrument-clean_objdirs.adb +++ b/tools/gnatcov/instrument-clean_objdirs.adb @@ -20,7 +20,6 @@ with Ada.Directories; use Ada.Directories; with GNATCOLL.Projects; use GNATCOLL.Projects; -with Command_Line; use Command_Line; with Instrument.Common; use Instrument.Common; with Project; @@ -63,7 +62,7 @@ begin -- through extended projects, as their object directories can interfere -- with the build of the extending project. - if not Args.Bool_Args (Opt_Save_Temps) then + if not Save_Temps then Project.Iterate_Projects (Root_Project => Project.Project.Root_Project, Process => Clean_Subdir'Access, diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index f2cb89dac..d6cb9cb81 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -1478,7 +1478,7 @@ begin end loop; end; - if not Args.Bool_Args (Opt_Save_Temps) then + if not Save_Temps then Ada.Directories.Delete_File (+IC.Sources_Of_Interest_Response_File); Ada.Directories.Delete_File (+IC.Ada_Preprocessor_Data_File); end if; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 7e64fa506..e21c2e759 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -30,7 +30,6 @@ with GNATCOLL.Traces; with GNATCOLL.Projects.Aux; with GNATCOLL.VFS; use GNATCOLL.VFS; -with Command_Line; use Command_Line; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Inputs; use Inputs; with Instrument; use Instrument; @@ -1629,7 +1628,7 @@ package body Project is procedure Finalize is begin - if Prj_Tree /= null and then not Args.Bool_Args (Opt_Save_Temps) then + if Prj_Tree /= null and then not Save_Temps then GNATCOLL.Projects.Aux.Delete_All_Temp_Files (Prj_Tree.Root_Project); end if; end Finalize; From 1bfa3573d9cb49e0cfd6e291c759de01fbb019c6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 8 Dec 2023 14:46:42 +0000 Subject: [PATCH 0546/1483] integrated_instrumentation/basic_cmake: fix coding style issues --- testsuite/tests/integrated_instrumentation/basic_cmake/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/integrated_instrumentation/basic_cmake/main.c b/testsuite/tests/integrated_instrumentation/basic_cmake/main.c index 5b6a74961..8bfd10171 100644 --- a/testsuite/tests/integrated_instrumentation/basic_cmake/main.c +++ b/testsuite/tests/integrated_instrumentation/basic_cmake/main.c @@ -1,8 +1,8 @@ #include int -main() +main () { - printf("Hello world!\n"); + printf ("Hello world!\n"); return 0; } From 44aacfa7aa2172efa0180f2afe359a8704ceb6ac Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 8 Dec 2023 09:11:19 +0000 Subject: [PATCH 0547/1483] coverage-source.adb: add missing "Start of processing" comments --- tools/gnatcov/coverage-source.adb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 65f23055d..0380d59dc 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -1194,6 +1194,8 @@ package body Coverage.Source is return To_String (Msg & No_Pair_Msg); end Emit_Evaluation_Vector_Message; + -- Start of processing for Compute_MCDC_State + begin for Cur of SCI.Evaluations loop Eval_Cond_Set_Map.Include (Cur, new Condition_Set.Set); @@ -1355,6 +1357,8 @@ package body Coverage.Source is Condition_Evaluated : Condition_Evaluated_Array := (others => False); + -- Start of processing for Compute_ATCC_State + begin -- Record if a condition has been evaluated during the overall From 0ea4ac7ab2834d75eea22039547d5f4ac3172847 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 7 Dec 2023 15:21:48 +0000 Subject: [PATCH 0548/1483] Unify references to unbounded strings Put renamings for unbounded strings in "strings.ads" and consistently use them in the codebase. --- tools/gnatcov/ali_files.adb | 16 ++--- tools/gnatcov/annotations-cobertura.adb | 10 ++- tools/gnatcov/annotations-dynamic_html.adb | 17 +++-- tools/gnatcov/annotations-html.adb | 12 ++-- tools/gnatcov/annotations-html.ads | 5 +- tools/gnatcov/annotations-report.adb | 55 +++++++--------- tools/gnatcov/annotations-xml.adb | 54 ++++++---------- tools/gnatcov/annotations.adb | 27 +++----- tools/gnatcov/annotations.ads | 2 + tools/gnatcov/argparse.adb | 28 ++++---- tools/gnatcov/argparse.ads | 7 +- tools/gnatcov/cfg_dump.adb | 64 ++++++++----------- tools/gnatcov/checkpoints.adb | 4 +- tools/gnatcov/checkpoints.ads | 2 +- tools/gnatcov/command_line.adb | 2 - tools/gnatcov/compiler_wrappers-gcc.adb | 7 +- tools/gnatcov/coverage-source.adb | 43 +++++-------- tools/gnatcov/coverage.adb | 23 +++---- tools/gnatcov/coverage.ads | 4 +- tools/gnatcov/coverage_options.adb | 9 ++- tools/gnatcov/coverage_options.ads | 2 + tools/gnatcov/decision_map.adb | 11 ++-- tools/gnatcov/diagnostics.adb | 8 +-- tools/gnatcov/diagnostics.ads | 4 +- tools/gnatcov/disassemble_insn_properties.adb | 10 +-- tools/gnatcov/disassemblers.adb | 10 +-- tools/gnatcov/factory_registry.adb | 7 +- tools/gnatcov/files_table.adb | 10 +-- tools/gnatcov/files_table.ads | 16 ++--- tools/gnatcov/gnatcov_bits_specific.adb | 11 +--- tools/gnatcov/highlighting.adb | 14 ++-- tools/gnatcov/inputs.adb | 4 +- tools/gnatcov/inputs.ads | 3 + .../gnatcov/instrument-ada_preprocessing.adb | 18 ++---- tools/gnatcov/instrument-ada_unit.adb | 60 +++++++++-------- tools/gnatcov/instrument-ada_unit.ads | 5 +- tools/gnatcov/instrument-c.adb | 56 ++++++++-------- tools/gnatcov/instrument-c.ads | 17 +++-- tools/gnatcov/instrument-common.adb | 9 ++- tools/gnatcov/instrument-common.ads | 11 ++-- tools/gnatcov/instrument-input_traces.adb | 3 +- tools/gnatcov/instrument-projects.adb | 23 +++---- tools/gnatcov/instrument-setup_config.adb | 4 +- tools/gnatcov/instrument.adb | 25 ++++---- tools/gnatcov/instrument.ads | 10 ++- tools/gnatcov/json.adb | 11 ++-- tools/gnatcov/outputs.adb | 9 ++- tools/gnatcov/paths.adb | 14 ++-- tools/gnatcov/project.adb | 17 ++--- tools/gnatcov/rundrv-config.adb | 13 ++-- tools/gnatcov/rundrv.adb | 9 +-- tools/gnatcov/sc_obligations.adb | 25 ++++---- tools/gnatcov/sc_obligations.ads | 3 +- tools/gnatcov/setup_rts.adb | 22 +++---- tools/gnatcov/setup_rts.ads | 2 - tools/gnatcov/strings.adb | 20 +++--- tools/gnatcov/strings.ads | 51 ++++++++------- tools/gnatcov/subprocesses.adb | 3 - tools/gnatcov/subprocesses.ads | 9 +-- tools/gnatcov/switches.adb | 10 +-- tools/gnatcov/switches.ads | 5 +- tools/gnatcov/temp_dirs.adb | 8 +-- tools/gnatcov/temp_dirs.ads | 6 +- tools/gnatcov/text_files.adb | 4 +- tools/gnatcov/text_files.ads | 7 +- tools/gnatcov/traces_files.adb | 17 ++--- tools/gnatcov/traces_files.ads | 11 ++-- tools/gnatcov/traces_files_registry.adb | 42 ++++++------ tools/gnatcov/traces_files_registry.ads | 13 ++-- tools/gnatcov/traces_stats.adb | 7 +- 70 files changed, 481 insertions(+), 599 deletions(-) diff --git a/tools/gnatcov/ali_files.adb b/tools/gnatcov/ali_files.adb index 338e05c0f..fcdfe7261 100644 --- a/tools/gnatcov/ali_files.adb +++ b/tools/gnatcov/ali_files.adb @@ -17,7 +17,6 @@ ------------------------------------------------------------------------------ with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; with GNAT.Regpat; use GNAT.Regpat; @@ -29,9 +28,12 @@ with Files_Table; use Files_Table; with Get_SCOs; with Inputs; use Inputs; with Outputs; use Outputs; +with Strings; use Strings; package body ALI_Files is + use all type Unbounded_String; + procedure Read (CLS : in out Checkpoint_Load_State; Value : out ALI_Annotation); -- Read a ALI_Annotation from CLS @@ -72,8 +74,6 @@ package body ALI_Files is ------------- function Unquote (Filename : String) return String is - use Ada.Strings.Unbounded; - Result : Unbounded_String; In_Quote : Boolean := False; -- True when we just met a double quote inside a quoted filename. False @@ -96,7 +96,7 @@ package body ALI_Files is Append (Result, C); end if; end loop; - return To_String (Result); + return +Result; end if; end Unquote; @@ -366,17 +366,13 @@ package body ALI_Files is -- Check that the first line is a valid ALI V line. declare - use Ada.Strings.Unbounded; - V_Line : constant String := Get_Stripped_Line (ALI_File); - Error_Msg : Unbounded_String; begin Match (V_Matcher, V_Line, Matches); if Matches (0) = No_Match then Error_Msg := - To_Unbounded_String - ("malformed ALI file """ & ALI_Filename & """"); + +("malformed ALI file """ & ALI_Filename & """"); if V_Line'Length > 3 and then @@ -388,7 +384,7 @@ package body ALI_Files is & "to load ALIs from list use ""--scos=@" & ALI_Filename & """"); end if; - Fatal_Error (To_String (Error_Msg)); + Fatal_Error (+Error_Msg); end if; end; diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb index 32d63bae6..8331bc4cc 100644 --- a/tools/gnatcov/annotations-cobertura.adb +++ b/tools/gnatcov/annotations-cobertura.adb @@ -22,7 +22,6 @@ with Ada.Containers.Ordered_Maps; with Ada.Directories; with Ada.Text_IO; use Ada.Text_IO; with Ada.Strings.Fixed; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Unchecked_Deallocation; with GNAT.OS_Lib; @@ -424,7 +423,7 @@ package body Annotations.Cobertura is Branches_Valid, Branches_Covered : Natural; Branch_Rate : Rate_Type; - Filename : Unbounded_String := To_Unbounded_String (Info.Full_Name.all); + Filename : Unbounded_String := +Info.Full_Name.all; -- Filename to mention in the coverage report. Use the full name, unless -- we can remove the prefix according to the --source-root option. begin @@ -459,15 +458,14 @@ package body Annotations.Cobertura is Matches : GNAT.Regpat.Match_Array (0 .. 0); First, Last : Natural; Normalized_Filename : constant String := - Paths.Normalize_For_Regexp (To_String (Filename)); + Paths.Normalize_For_Regexp (+Filename); begin GNAT.Regpat.Match (Pp.Source_Prefix_Pattern.all, Normalized_Filename, Matches); if Matches (0) /= GNAT.Regpat.No_Match then First := Matches (0).Last + 1; Last := Normalized_Filename'Last; - Filename := - To_Unbounded_String (Normalized_Filename (First .. Last)); + Filename := +Normalized_Filename (First .. Last); end if; end; end if; @@ -480,7 +478,7 @@ package body Annotations.Cobertura is Pp.ST ("classes"); Pp.ST ("class", A ("name", Simple_Source_Filename) - & A ("filename", To_String (Filename)) + & A ("filename", +Filename) & A ("line-rate", Img (Line_Rate)) & A ("branch-rate", Img (Branch_Rate)) & A ("complexity", "-1")); diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 8c16aebf8..57a0f4767 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -19,7 +19,6 @@ with Ada.Characters.Handling; with Ada.Directories; use Ada.Directories; with Ada.Exceptions; use Ada.Exceptions; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Text_IO; pragma Warnings (Off, "* is an internal GNAT unit"); @@ -125,7 +124,7 @@ package body Annotations.Dynamic_Html is Source_List : JSON_Array; -- The sources array in the index, containing all source mappings - Title_Prefix : Ada.Strings.Unbounded.Unbounded_String; + Title_Prefix : Unbounded_String; -- Prefix to use for titles in generated HTML documents Scope_Metrics : JSON_Value; @@ -226,7 +225,7 @@ package body Annotations.Dynamic_Html is -- Write Item (String) into Output procedure W - (Item : Ada.Strings.Unbounded.Unbounded_String; + (Item : Unbounded_String; Output : Ada.Text_IO.File_Type; New_Line : Boolean := True) with Pre => Ada.Text_IO.Is_Open (Output); @@ -812,7 +811,7 @@ package body Annotations.Dynamic_Html is Message.Set_Field ("sco", Image (M.SCO, With_Sloc => False)); end if; - Message.Set_Field ("message", To_String (M.Msg)); + Message.Set_Field ("message", +M.Msg); Pp.Current_Mapping.Get ("messages").Append (Message); end Pretty_Print_Message; @@ -835,18 +834,18 @@ package body Annotations.Dynamic_Html is end W; procedure W - (Item : Ada.Strings.Unbounded.Unbounded_String; + (Item : Unbounded_String; Output : Ada.Text_IO.File_Type; New_Line : Boolean := True) is use Ada.Text_IO; - Buffer : Aux.Big_String_Access; + Buffer : US.Aux.Big_String_Access; Last : Natural; - First : constant Natural := Aux.Big_String'First; + First : constant Natural := US.Aux.Big_String'First; begin - Aux.Get_String (Item, Buffer, Last); + US.Aux.Get_String (Item, Buffer, Last); Put (File => Output, Item => Buffer (First .. Last)); if New_Line then @@ -1119,7 +1118,7 @@ package body Annotations.Dynamic_Html is (In_Filename => Source_Name, Out_Filename => Target_Name, Pattern => ".*", - Replacement => " " & To_String (Pp.Title_Prefix) + Replacement => " <title>" & (+Pp.Title_Prefix) & "GNATcoverage Report"); else Copy_File (Source_Name, Target_Name); diff --git a/tools/gnatcov/annotations-html.adb b/tools/gnatcov/annotations-html.adb index b3c75182d..bf592c06a 100644 --- a/tools/gnatcov/annotations-html.adb +++ b/tools/gnatcov/annotations-html.adb @@ -458,7 +458,7 @@ package body Annotations.Html is Pi (""); Pi (""); - Pi (" " & To_String (Pp.Title_Prefix) + Pi (" <title>" & (+Pp.Title_Prefix) & "Coverage results"); Pi (" "); Pi (""); @@ -484,11 +484,11 @@ package body Annotations.Html is for El of Sorted_Traces_Files loop Pi (" "); - Pi (" " & To_String (El.Filename) & ""); + Pi (" " & (+El.Filename) & ""); Pi (" " & Image (El.Kind) & ""); - Pi (" " & To_String (El.Program_Name) & ""); - Pi (" " & To_String (El.Time) & ""); - Pi (" " & To_String (El.User_Data) & ""); + Pi (" " & (+El.Program_Name) & ""); + Pi (" " & (+El.Time) & ""); + Pi (" " & (+El.User_Data) & ""); Pi (" "); end loop; @@ -598,7 +598,7 @@ package body Annotations.Html is Plh (Pp, ""); Plh (Pp, ""); - Plh (Pp, " " & To_String (Pp.Title_Prefix) & "Coverage of " + Plh (Pp, " <title>" & (+Pp.Title_Prefix) & "Coverage of " & To_Xml_String (Simple_Source_Filename) & ""); Plh (Pp, " "); diff --git a/tools/gnatcov/annotations-html.ads b/tools/gnatcov/annotations-html.ads index 4b607210e..e14e85df8 100644 --- a/tools/gnatcov/annotations-html.ads +++ b/tools/gnatcov/annotations-html.ads @@ -16,8 +16,6 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; - with Annotations.Xml; use Annotations.Xml; with Command_Line; with Coverage; @@ -37,8 +35,7 @@ package Annotations.Html is (Report_Title : Command_Line.Parser.String_Option) return Unbounded_String is ((if Report_Title.Present and then Length (Report_Title.Value) > 0 - then To_Unbounded_String - (To_Xml_String (To_String (Report_Title.Value & " - "))) + then +(To_Xml_String (+Report_Title.Value & " - ")) else Null_Unbounded_String)); -- If Report_Title is present and non-empty, return the corresponding -- report title prefix (for instance: "foo" -> "foo - "). Return an empty diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 1526ae4f3..5a9e1427e 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -19,7 +19,6 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Containers.Vectors; with Ada.Containers.Indefinite_Ordered_Maps; -with Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; with ALI_Files; @@ -104,10 +103,7 @@ package body Annotations.Report is "=" => Message_Vectors."="); package String_Vectors is - new Ada.Containers.Vectors - (Natural, - Ada.Strings.Unbounded.Unbounded_String, - Ada.Strings.Unbounded."="); + new Ada.Containers.Vectors (Natural, Unbounded_String, "="); type Report_Pretty_Printer is new Pretty_Printer with record Current_File_Index : Source_File_Index; @@ -302,7 +298,6 @@ package body Annotations.Report is procedure Pretty_Print_End (Pp : in out Report_Pretty_Printer) is use ALI_Files, ALI_Files.ALI_Annotation_Maps; - use Ada.Strings.Unbounded; Output : constant File_Access := Get_Output; @@ -397,7 +392,7 @@ package body Annotations.Report is procedure Output_Message (C : Message_Vectors.Cursor) is M : Message renames Message_Vectors.Element (C); - Msg : constant String := To_String (M.Msg); + Msg : constant String := +M.Msg; First : Natural := Msg'First; begin @@ -551,7 +546,7 @@ package body Annotations.Report is procedure Output_Message (C : Message_Vectors.Cursor) is M : Message renames Message_Vectors.Element (C); - Msg : constant String := To_String (M.Msg); + Msg : constant String := +M.Msg; First : Natural := Msg'First; Show_Vectors : constant Boolean := (Switches.Show_MCDC_Vectors @@ -625,19 +620,18 @@ package body Annotations.Report is -- Append summary line for general summary chapter Pp.Summary.Append - (To_Unbounded_String - (Pluralize - (Item_Count, - (case MC is - when Coverage_Violations => - Non_Exempted - & Coverage_Level'Val (MC)'Img & " " & Item, - when Other_Errors => - "other message", - when Coverage_Exclusions => - "coverage exclusion", - when Undetermined_Coverage => - "undetermined coverage item")) & ".")); + (+(Pluralize + (Item_Count, + (case MC is + when Coverage_Violations => + Non_Exempted + & Coverage_Level'Val (MC)'Img & " " & Item, + when Other_Errors => + "other message", + when Coverage_Exclusions => + "coverage exclusion", + when Undetermined_Coverage => + "undetermined coverage item")) & ".")); -- Count of total (coverable) and covered SCOs is displayed only -- if --all-messages is specified. @@ -725,7 +719,7 @@ package body Annotations.Report is New_Line (Output.all); for L of Pp.Summary loop - Put_Line (Output.all, To_String (L)); + Put_Line (Output.all, +L); end loop; if Has_Exempted_Region then @@ -835,8 +829,6 @@ package body Annotations.Report is ------------------------ procedure Pretty_Print_Start (Pp : in out Report_Pretty_Printer) is - use Ada.Strings.Unbounded; - Output : constant File_Access := Get_Output; procedure Process_One_Trace (TF : Trace_File_Element); @@ -850,11 +842,11 @@ package body Annotations.Report is Orig_Context : constant String := Original_Processing_Context (TF); begin New_Line (Output.all); - Put_Line (Output.all, To_String (TF.Filename)); + Put_Line (Output.all, +TF.Filename); Put_Line (Output.all, " kind : " & Image (TF.Kind)); - Put_Line (Output.all, " program : " & To_String (TF.Program_Name)); - Put_Line (Output.all, " date : " & To_String (TF.Time)); - Put_Line (Output.all, " tag : " & To_String (TF.User_Data)); + Put_Line (Output.all, " program : " & (+TF.Program_Name)); + Put_Line (Output.all, " date : " & (+TF.Time)); + Put_Line (Output.all, " tag : " & (+TF.User_Data)); -- For a trace that has been processed in an earlier run, provide -- information on original coverage assessment context. @@ -875,15 +867,14 @@ package body Annotations.Report is Put_Line (Output.all, "Date and time of execution: " & Image (Pp.Context.Timestamp)); Put_Line (Output.all, "Tool version: XCOV " - & To_String (Pp.Context.Version)); + & (+Pp.Context.Version)); New_Line (Output.all); Put_Line (Output.all, "Command line:"); - Put_Line (Output.all, To_String (Pp.Context.Command)); + Put_Line (Output.all, +Pp.Context.Command); New_Line (Output.all); - Put_Line (Output.all, "Coverage level: " - & To_String (Pp.Context.Levels)); + Put_Line (Output.all, "Coverage level: " & (+Pp.Context.Levels)); New_Line (Output.all); Put_Line (Output.all, "Trace files:"); diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index 7540daf1a..1a3eaa59a 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -19,7 +19,6 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Directories; with Ada.Text_IO; use Ada.Text_IO; -with Ada.Strings.Unbounded; with Interfaces; with GNAT.OS_Lib; @@ -33,8 +32,6 @@ with Traces_Files; use Traces_Files; package body Annotations.Xml is - package ASU renames Ada.Strings.Unbounded; - XSD_Basename : constant String := "gnatcov-xml-report.xsd"; XSD_Filename : constant String := Support_Files.In_Lib_Dir (XSD_Basename); @@ -80,9 +77,7 @@ package body Annotations.Xml is Trace_File_Name : constant String := "trace.xml"; function A (Name : String; Value : Character) return String; - function A - (Name : String; - Value : Ada.Strings.Unbounded.Unbounded_String) return String; + function A (Name : String; Value : Unbounded_String) return String; function A (Name : String; Value : String) return String; -- Return a string representing an xml attribute whose name -- and value are given in parameter. id est @@ -256,12 +251,9 @@ package body Annotations.Xml is return " " & Name & "=" & '"' & To_Xml_String (Value) & '"'; end A; - function A - (Name : String; - Value : Ada.Strings.Unbounded.Unbounded_String) return String - is + function A (Name : String; Value : Unbounded_String) return String is begin - return A (Name, Ada.Strings.Unbounded.To_String (Value)); + return A (Name, +Value); end A; function A (Name : String; Value : Character) return String is @@ -426,22 +418,18 @@ package body Annotations.Xml is M : Message) is use Interfaces; - use Ada.Strings.Unbounded; - - Attributes : Unbounded_String := - ASU.To_Unbounded_String (A ("kind", To_Lower (M.Kind'Img))); + Attributes : Unbounded_String := +A ("kind", To_Lower (M.Kind'Img)); begin if M.PC /= 0 then - Attributes := Attributes & A ("address", Hex_Image (M.PC)); + Append (Attributes, A ("address", Hex_Image (M.PC))); end if; if M.SCO /= No_SCO_Id then - Attributes := Attributes - & A ("SCO", Image (M.SCO, With_Sloc => False)); + Append (Attributes, A ("SCO", Image (M.SCO, With_Sloc => False))); end if; - Attributes := Attributes & A ("message", To_String (M.Msg)); - Pp.T ("message", To_String (Attributes)); + Append (Attributes, A ("message", +M.Msg)); + Pp.T ("message", +Attributes); end Pretty_Print_Message; ------------------------ @@ -706,8 +694,6 @@ package body Annotations.Xml is ----------------------- procedure Process_One_Trace (TF : Trace_File_Element) is - use Ada.Strings.Unbounded; - Attributes : Unbounded_String; begin Append (Attributes, @@ -716,7 +702,7 @@ package body Annotations.Xml is & A ("program", TF.Program_Name) & A ("date", TF.Time) & A ("tag", TF.User_Data)); - Pp.T ("trace", To_String (Attributes), Dest_Trace_Info); + Pp.T ("trace", +Attributes, Dest_Trace_Info); end Process_One_Trace; -- Start of processing for Print_Trace_Info @@ -739,8 +725,6 @@ package body Annotations.Xml is Sloc_Start : Source_Location; Sloc_End : Source_Location) is - use Ada.Strings.Unbounded; - Current_Line_Sloc : Source_Location := Sloc_Start; begin Pp.ST ("src"); @@ -750,22 +734,20 @@ package body Annotations.Xml is Current_Line_Sloc.L.Line := Line_Num; declare - Attributes : Unbounded_String := - To_Unbounded_String (A ("num", Img (Line_Num))); + Attributes : Unbounded_String := +A ("num", Img (Line_Num)); Line : constant String := Get_Line (Current_Line_Sloc); Src_Start : Natural := Line'First; Src_End : Natural := Line'Last; begin if Line_Num = Sloc_Start.L.Line then Src_Start := Natural'Min (Src_End, Sloc_Start.L.Column); - Attributes := Attributes - & A ("column_begin", Img (Sloc_Start.L.Column)); + Append + (Attributes, A ("column_begin", Img (Sloc_Start.L.Column))); end if; if Line_Num = Sloc_End.L.Line then Src_End := Natural'Min (Src_End, Sloc_End.L.Column); - Attributes := Attributes - & A ("column_end", Img (Sloc_End.L.Column)); + Append (Attributes, A ("column_end", Img (Sloc_End.L.Column))); end if; if Line'Length /= 0 then @@ -774,16 +756,16 @@ package body Annotations.Xml is Spaces : constant String (1 .. Src_Start - 1) := (others => ' '); begin - Attributes := Attributes - & A ("src", Spaces & Line (Src_Start .. Src_End)); + Append + (Attributes, + A ("src", Spaces & Line (Src_Start .. Src_End))); end; else - Attributes := Attributes - & A ("src", Line (Src_Start .. Src_End)); + Append (Attributes, A ("src", Line (Src_Start .. Src_End))); end if; end if; - Pp.T ("line", To_String (Attributes)); + Pp.T ("line", +Attributes); end; end loop; Pp.ET ("src"); diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index db7d1d7a0..a7362ca3a 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -19,7 +19,6 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Characters.Latin_1; with Ada.Strings.Fixed; -with Ada.Strings.Unbounded; with GNAT.OS_Lib; @@ -40,8 +39,6 @@ with Traces_Disa; package body Annotations is - package US renames Ada.Strings.Unbounded; - ------------------------- -- Get_Unique_Filename -- ------------------------- @@ -643,7 +640,6 @@ package body Annotations is function Message_Annotation (M : Message) return String is use Coverage, Coverage.Tags; - use Ada.Strings.Unbounded; begin if M.SCO /= No_SCO_Id then return SCO_Kind_Image (M.SCO) @@ -664,9 +660,9 @@ package body Annotations is & (if M.Tag = No_SC_Tag then "" else " (from " & Tag_Provider.Tag_Name (M.Tag) & ")") - & " " & To_String (M.Msg); + & " " & (+M.Msg); else - return Image (M.Sloc, Unique_Name => True) & ": " & To_String (M.Msg); + return Image (M.Sloc, Unique_Name => True) & ": " & (+M.Msg); end if; end Message_Annotation; @@ -677,18 +673,17 @@ package body Annotations is function Original_Processing_Context (TF : Trace_File_Element) return String is use Calendar_Utils; - use Ada.Strings.Unbounded; begin - if Length (TF.Context) = 0 then + if TF.Context = "" then return ""; else declare Orig_Context : constant Coverage.Context := - Coverage.From_String (To_String (TF.Context)); + Coverage.From_String (+TF.Context); begin - return To_String (Orig_Context.Command) - & " @ " & Image (Orig_Context.Timestamp); + return + +Orig_Context.Command & " @ " & Image (Orig_Context.Timestamp); end; end if; end Original_Processing_Context; @@ -702,11 +697,11 @@ package body Annotations is Sloc_Start : Source_Location := First_Sloc (SCO); Sloc_End : Source_Location := End_Lex_Element (Last_Sloc (SCO)); Sloc_Bound : Source_Location; - Line : US.Unbounded_String; + Line : Unbounded_String; Col_Start : Natural; Col_End : Natural; - Desc : US.Unbounded_String; + Desc : Unbounded_String; -- SCO description: shortened view of the SCO tokens, with a macro -- expansion annotation if the SCO comes from a macro expansion. @@ -793,11 +788,10 @@ package body Annotations is if Sloc_Bound <= Sloc_End then Col_End := Natural'Min (US.Length (Line), Sloc_Bound.L.Column); - US.Append (Desc, - +US.Unbounded_Slice (Line, Col_Start, Col_End) & "..."); + Append (Desc, +Unbounded_Slice (Line, Col_Start, Col_End) & "..."); else Col_End := Natural'Min (US.Length (Line), Sloc_End.L.Column); - US.Append (Desc, US.Unbounded_Slice (Line, Col_Start, Col_End)); + Append (Desc, Unbounded_Slice (Line, Col_Start, Col_End)); end if; return +Desc; end SCO_Text; @@ -807,7 +801,6 @@ package body Annotations is --------------------- function SCO_Annotations (SCO : SCO_Id) return String_Vectors.Vector is - use Ada.Strings.Unbounded; begin if Has_PP_Info (SCO) then declare diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 7ca320e6f..567077baf 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -38,6 +38,8 @@ with Types; use Types; package Annotations is + use all type Unbounded_String; + type Annotation_Format is (Annotate_Asm, Annotate_Xcov, diff --git a/tools/gnatcov/argparse.adb b/tools/gnatcov/argparse.adb index 70bed5848..d8702b3ef 100644 --- a/tools/gnatcov/argparse.adb +++ b/tools/gnatcov/argparse.adb @@ -21,7 +21,6 @@ with Ada.Containers.Generic_Array_Sort; with Ada.Containers.Hashed_Maps; with Ada.Containers.Vectors; with Ada.Exceptions; -with Ada.Strings.Unbounded.Hash; with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Deallocation; @@ -52,7 +51,7 @@ package body Argparse is package Long_Options_Index is new Ada.Containers.Hashed_Maps (Key_Type => Unbounded_String, - Hash => Ada.Strings.Unbounded.Hash, + Hash => Strings.Hash, Element_Type => Option_Reference_Vector, Equivalent_Keys => "="); @@ -139,8 +138,7 @@ package body Argparse is (Parser : Parser_Type; Command : Valid_Commands) return String - is - (To_String (Parser.Data.Command_Infos (Command).Name)); + is (+Parser.Data.Command_Infos (Command).Name); ----------------- -- Option_Name -- @@ -160,11 +158,11 @@ package body Argparse is function Option_Name (Option : Option_Info'Class) return String is Result : Unbounded_String; begin - if Length (Option.Long_Name) > 0 then + if Option.Long_Name /= "" then Append (Result, Option.Long_Name); end if; - if Length (Option.Short_Name) > 0 then - if Length (Result) > 0 then + if Option.Short_Name /= "" then + if Result /= "" then Append (Result, '|'); end if; Append (Result, Option.Short_Name); @@ -250,7 +248,7 @@ package body Argparse is Result : String_Vectors.Vector; function Name (Opt : Option_Info'Class) return Unbounded_String is - (if Length (Opt.Long_Name) = 0 + (if Opt.Long_Name = "" then Opt.Short_Name else Opt.Long_Name); -- Some options such as -P do not defined a long name. In this case, @@ -445,7 +443,7 @@ package body Argparse is return ""; end if; - return (if Length (Candidate) = 0 + return (if Candidate = "" then " [...]" else " " & (+Candidate)); end Get_Pattern; @@ -751,7 +749,7 @@ package body Argparse is begin if Callback /= null then Callback (Result, Ref); - return Length (Result.Error) > 0; + return Result.Error /= ""; end if; return False; end Invoke_Callback; @@ -1132,9 +1130,7 @@ package body Argparse is Opt : constant Option_Info_Access := Get_Option (Parser, Ref); begin for Name of Split_Option_Text (+Opt.Long_Name) loop - if Length (Name) < 2 - or else Element (Name, 1) /= '-' - then + if Length (Name) < 2 or else Element (Name, 1) /= '-' then raise Program_Error with "Invalid option long name: " & (+Name); end if; @@ -1305,11 +1301,11 @@ package body Argparse is function "<" (Left, Right : Option_Info_Access) return Boolean is Left_Str : constant Unbounded_String := - (if Length (Left.Long_Name) = 0 + (if Left.Long_Name = "" then Left.Short_Name else Left.Long_Name); Right_Str : constant Unbounded_String := - (if Length (Right.Long_Name) = 0 + (if Right.Long_Name = "" then Right.Short_Name else Right.Long_Name); begin @@ -1516,7 +1512,7 @@ package body Argparse is if Column /= 0 then Append (Result, ASCII.LF); end if; - return To_String (Result); + return +Result; end Wrap; end Argparse; diff --git a/tools/gnatcov/argparse.ads b/tools/gnatcov/argparse.ads index 98ca12eac..4c6e59760 100644 --- a/tools/gnatcov/argparse.ads +++ b/tools/gnatcov/argparse.ads @@ -17,7 +17,6 @@ ------------------------------------------------------------------------------ private with Ada.Finalization; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with GNAT.Strings; @@ -101,6 +100,8 @@ generic package Argparse is + use all type Unbounded_String; + ----------------------- -- Commands handling -- ----------------------- @@ -350,8 +351,8 @@ package Argparse is (Args : in out Parsed_Arguments; Other_Args : Parsed_Arguments) with Pre => - (Ada.Strings.Unbounded.Length (Args.Error) = 0 - and then Ada.Strings.Unbounded.Length (Other_Args.Error) = 0 + (Args.Error = "" + and then Other_Args.Error = "" and then (Args.Command = No_Command or else Args.Command = Other_Args.Command)); diff --git a/tools/gnatcov/cfg_dump.adb b/tools/gnatcov/cfg_dump.adb index 5e93263e4..1e9cf4ca6 100644 --- a/tools/gnatcov/cfg_dump.adb +++ b/tools/gnatcov/cfg_dump.adb @@ -22,7 +22,6 @@ with Ada.Containers.Ordered_Maps; with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; with Ada.Exceptions; use Ada.Exceptions; -with Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Conversion; with Ada.Unchecked_Deallocation; @@ -43,7 +42,7 @@ with Highlighting; with Outputs; use Outputs; with Qemu_Traces; with SC_Obligations; -with Strings; +with Strings; use Strings; with Support_Files; with Traces; use Traces; with Traces_Dbase; @@ -53,10 +52,7 @@ with Traces_Files; package body CFG_Dump is use type Pc_Type; - - function To_Unbounded_String - (S : String) return Ada.Strings.Unbounded.Unbounded_String - renames Ada.Strings.Unbounded.To_Unbounded_String; + use all type Unbounded_String; procedure Load_SCOs (ALI_Filename : String); -- Wrapper for SC_Obligations.Load_SCOs, assumes there is no source file to @@ -345,7 +341,7 @@ package body CFG_Dump is State : Disassembly_State; -- Disassembled instructions - Disas_Error : Ada.Strings.Unbounded.Unbounded_String; + Disas_Error : Unbounded_String; -- Hold the error message when disassembling failed PC : Pc_Type := Code.First; @@ -492,8 +488,7 @@ package body CFG_Dump is -- assume instructions are not supposed to do that. State := Invalid_Insn; - Disas_Error := To_Unbounded_String - ("Insn crosses a symbol's upper address"); + Disas_Error := +"Insn crosses a symbol's upper address"; end if; end if; @@ -624,8 +619,7 @@ package body CFG_Dump is when Invalid_Insn => Disassemblers.Abort_Disassembler_Error - (PC, Slice (Code, PC, Code.Last), - Ada.Strings.Unbounded.To_String (Disas_Error)); + (PC, Slice (Code, PC, Code.Last), +Disas_Error); when Skip_Padding => @@ -1007,7 +1001,6 @@ package body CFG_Dump is ---------------- procedure Output_CFG (Context : Context_Access) is - use Ada.Strings.Unbounded; use type SC_Obligations.SCO_Id; subtype SCO_Id is SC_Obligations.SCO_Id; @@ -1170,7 +1163,7 @@ package body CFG_Dump is Append (Prefix, ""); Insert (Suffix, 1, ""); end if; - return To_String (Prefix) & Text & To_String (Suffix); + return +Prefix & Text & (+Suffix); end Styled; ----------------------- @@ -1232,7 +1225,7 @@ package body CFG_Dump is Append (Result, C); end case; end loop; - return To_String (Result); + return +Result; end HTML_Escape; ------------------------- @@ -1259,7 +1252,7 @@ package body CFG_Dump is Append (Result, "
"); Previous (Sloc); end loop; - return To_String (Result); + return +Result; end Format_Slocs_For_PC; ------------------------- @@ -1386,7 +1379,7 @@ package body CFG_Dump is end; Append (Result, "
"); end loop; - return To_String (Result); + return +Result; end Format_Basic_Block_Label; ------------------------ @@ -1501,9 +1494,9 @@ package body CFG_Dump is else Edge_Unselected_Color); begin - Put (F, To_String (Edge.From_Id)); + Put (F, +Edge.From_Id); Put (F, " -> "); - Put (F, To_String (Edge.To_Id)); + Put (F, +Edge.To_Id); Put (F, " [color=""#" & Color & """,penwidth=3,style="); Put (F, (case Edge.Kind is when Fallthrough => "solid", @@ -1518,7 +1511,6 @@ package body CFG_Dump is use Decision_Map; use Decision_Map.Cond_Branch_Maps; use SC_Obligations; - use Strings; This_Branch : Decision_Map.Cond_Branch_Info renames Reference (Cond_Branch_Map, Edge.Info.Branch_Info); @@ -1614,15 +1606,15 @@ package body CFG_Dump is Get_Cond_Edge_Info (BB.Last_Element, Successor); begin Edges.Append - ((To_Unbounded_String (Node_Id (Address (BB.all))), - To_Unbounded_String (Id), - Successor.Kind, - Selected => - (not Successor.Known - or else not Context.Other_Outcome.Contains - (Successor_Key'Unchecked_Access)), - Executed => Element (Succ_Cur), - Info => Edge_Info)); + ((+Node_Id (Address (BB.all)), + +Id, + Successor.Kind, + Selected => + (not Successor.Known + or else not Context.Other_Outcome.Contains + (Successor_Key'Unchecked_Access)), + Executed => Element (Succ_Cur), + Info => Edge_Info)); if not Successor.Known then Put_Line (F, Id & " [shape=ellipse, label=];"); end if; @@ -1707,12 +1699,12 @@ package body CFG_Dump is Get_Cond_Edge_Info (Insn, Successor); begin Edges.Append - ((To_Unbounded_String (Node_Id (Address (Insn))), - To_Unbounded_String (Node_Id (Successor.Address)), - Successor.Kind, - Selected => False, - Executed => False, - Info => Edge_Info)); + ((+Node_Id (Address (Insn)), + +Node_Id (Successor.Address), + Successor.Kind, + Selected => False, + Executed => False, + Info => Edge_Info)); end; end if; end loop; @@ -1957,8 +1949,6 @@ package body CFG_Dump is ----------------- function Expand_Tabs (S : String; Start : Positive) return String is - use Ada.Strings.Unbounded; - Column : Positive := Start; Result : Unbounded_String; begin @@ -1976,7 +1966,7 @@ package body CFG_Dump is Column := Column + 1; end if; end loop; - return To_String (Result); + return +Result; end Expand_Tabs; end CFG_Dump; diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index d3e6e5e50..a4f39f5ff 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -448,7 +448,7 @@ package body Checkpoints is CSS : aliased Checkpoint_Save_State := (Root_Stream_Type with Stream => Stream (SF), - Filename => To_Unbounded_String (Filename), + Filename => +Filename, Purpose => Purpose); Supported_Levels : Levels_Type := Current_Levels; begin @@ -564,7 +564,7 @@ package body Checkpoints is CLS : Checkpoint_Load_State := (Root_Stream_Type with Stream => Stream (SF), - Filename => To_Unbounded_String (Filename), + Filename => +Filename, Purpose => Purpose, others => <>); diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 347332710..08ffef484 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -23,7 +23,6 @@ with Ada.Containers; use Ada.Containers; with Ada.Containers.Multiway_Trees; with Ada.Containers.Vectors; with Ada.Streams; use Ada.Streams; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Interfaces; with GNAT.Regexp; @@ -34,6 +33,7 @@ with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Files_Table; use Files_Table; with Slocs; use Slocs; with SC_Obligations; use SC_Obligations; +with Strings; use Strings; with Traces; use Traces; with Traces_Lines; use Traces_Lines; diff --git a/tools/gnatcov/command_line.adb b/tools/gnatcov/command_line.adb index c41901de4..5540c3643 100644 --- a/tools/gnatcov/command_line.adb +++ b/tools/gnatcov/command_line.adb @@ -16,8 +16,6 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; - with Strings; use Strings; package body Command_Line is diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 6bfde1c01..61ff38402 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -22,7 +22,6 @@ with Ada.Containers.Vectors; with Ada.Directories; use Ada.Directories; with Ada.Environment_Variables; with Ada.Strings; use Ada.Strings; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; with GNAT.OS_Lib; @@ -43,8 +42,10 @@ with Switches; use Switches; with Temp_Dirs; use Temp_Dirs; with Traces_Files; -procedure Compiler_Wrappers.Gcc -is +procedure Compiler_Wrappers.Gcc is + + use all type Unbounded_String; + type Compilation_Command_Type is record Language : Any_Language; -- Language of the file that is compiled diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 0380d59dc..f82edeaf4 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -16,13 +16,11 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Characters.Latin_1; 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.Strings.Unbounded; with Ada.Unchecked_Deallocation; with Interfaces; @@ -40,7 +38,6 @@ with MC_DC; use MC_DC; with Outputs; use Outputs; with Project; use Project; with Slocs; use Slocs; -with Strings; use Strings; with Switches; use Switches; with Traces_Elf; use Traces_Elf; with Types; @@ -266,8 +263,6 @@ package body Coverage.Source is Unit_List_Invalidated : Boolean := False; -- Keeps track of whether Invalidate_Unit_List was called - package US renames Ada.Strings.Unbounded; - 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. @@ -535,11 +530,11 @@ package body Coverage.Source is CP_Tag_Provider := CLS.Read_Unbounded_String; if Tag_Provider.all not in Default_Tag_Provider_Type - and then Tag_Provider_Name /= To_String (CP_Tag_Provider) + and then Tag_Provider_Name /= +CP_Tag_Provider then Warn ("cannot merge coverage information from " - & To_String (CLS.Filename) - & " as it is separated by " & To_String (CP_Tag_Provider)); + & (+CLS.Filename) + & " as it is separated by " & (+CP_Tag_Provider)); Do_Merge := False; end if; @@ -596,11 +591,11 @@ package body Coverage.Source is if CLS.Purpose = Consolidation then declare Invalidated : constant Boolean := CLS.Read_Boolean; - Dummy : US.Unbounded_String; + Dummy : Unbounded_String; begin if Invalidated then Invalidate_Unit_List - (US.To_String (CLS.Filename) + (+CLS.Filename & " does not contain the list of units (produced with" & " --scos or --sid)"); else @@ -1162,11 +1157,9 @@ package body Coverage.Source is function Emit_Evaluation_Vector_Message return String is Msg : Unbounded_String; No_Pair_Msg : Unbounded_String; - EOL : constant String := "" & Ada.Characters.Latin_1.LF; begin - Msg := To_Unbounded_String ("Decision of the form ") - & Expression_Image (SCO) & EOL; - Append (Msg, "Evaluation vectors found:" & EOL); + Msg := +"Decision of the form " & Expression_Image (SCO) & ASCII.LF; + Append (Msg, "Evaluation vectors found:" & ASCII.LF); for Eval of SCI.Evaluations loop declare @@ -1174,24 +1167,23 @@ package body Coverage.Source is Eval_Cond_Set_Map.Element (Eval).all; begin if not Cond_Set.Is_Empty then -- This evaluation is in a pair - Append (Msg, " " & Image (Eval) - & " In a pair for "); + Append (Msg, " " & Image (Eval) & " In a pair for "); for Cond of Cond_Set loop Append (Msg, 'C' & Img (Integer (Cond))); if Cond < Cond_Set.Last_Element then Append (Msg, ", "); end if; end loop; - Append (Msg, EOL); + Append (Msg, ASCII.LF); else Append - (No_Pair_Msg, - " " & Image (Eval) & " Not part of any pair" & EOL); + (No_Pair_Msg, " " & Image (Eval) + & " Not part of any pair" & ASCII.LF); end if; end; end loop; - return To_String (Msg & No_Pair_Msg); + return +(Msg & No_Pair_Msg); end Emit_Evaluation_Vector_Message; -- Start of processing for Compute_MCDC_State @@ -1328,18 +1320,15 @@ package body Coverage.Source is function Emit_Evaluation_Vector_Message return String is Msg : Unbounded_String; - EOL : constant String := "" & Ada.Characters.Latin_1.LF; begin - Msg := To_Unbounded_String ("Decision of the form ") - & Expression_Image (SCO) & EOL; - Append (Msg, "Evaluation vectors found:" & EOL); + Msg := +"Decision of the form " & Expression_Image (SCO) & ASCII.LF; + Append (Msg, "Evaluation vectors found:" & ASCII.LF); for Eval of SCI.Evaluations loop - Append (Msg, " " & Image (Eval) & EOL); + Append (Msg, " " & Image (Eval) & ASCII.LF); end loop; - return To_String (Msg); - + return +Msg; end Emit_Evaluation_Vector_Message; SCO_State : Line_State := No_Code; diff --git a/tools/gnatcov/coverage.adb b/tools/gnatcov/coverage.adb index d60fef2bd..a2ccd5574 100644 --- a/tools/gnatcov/coverage.adb +++ b/tools/gnatcov/coverage.adb @@ -19,7 +19,6 @@ with Ada.Command_Line; with Ada.Containers; -with Strings; use Strings; with Support_Files; use Support_Files; with Switches; use Switches; with Version; use Version; @@ -267,9 +266,7 @@ package body Coverage is function Get_Context return Context is use Ada.Command_Line; - Command : Unbounded_String := - To_Unbounded_String (Support_Files.Gnatcov_Command_Name); - + Command : Unbounded_String := +Support_Files.Gnatcov_Command_Name; begin for J in 1 .. Argument_Count loop Append (Command, ' ' & Argument (J)); @@ -277,9 +274,9 @@ package body Coverage is return Context' (Timestamp => Clock, - Version => To_Unbounded_String (Xcov_Version), + Version => +Xcov_Version, Command => Command, - Levels => To_Unbounded_String (Coverage_Option_Value), + Levels => +Coverage_Option_Value, Subps_Of_Interest => Subps_Of_Interest); end Get_Context; @@ -288,11 +285,11 @@ package body Coverage is --------------- function To_String (C : Context) return String is - US : aliased Unbounded_String; - USS : aliased Unbounded_String_Stream (US'Access); + S : aliased Unbounded_String; + SS : aliased Unbounded_String_Stream (S'Access); begin - Context'Output (USS'Access, C); - return To_String (US); + Context'Output (SS'Access, C); + return +S; end To_String; ----------------- @@ -300,10 +297,10 @@ package body Coverage is ----------------- function From_String (S : String) return Context is - US : aliased Unbounded_String := To_Unbounded_String (S); - USS : aliased Unbounded_String_Stream (US'Access); + Str : aliased Unbounded_String := +S; + SS : aliased Unbounded_String_Stream (Str'Access); begin - return Context'Input (USS'Access); + return Context'Input (SS'Access); end From_String; end Coverage; diff --git a/tools/gnatcov/coverage.ads b/tools/gnatcov/coverage.ads index 7787ef207..f75df24f7 100644 --- a/tools/gnatcov/coverage.ads +++ b/tools/gnatcov/coverage.ads @@ -25,13 +25,15 @@ with Ada.Calendar; use Ada.Calendar; with Ada.Containers.Ordered_Sets; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Coverage_Options; use Coverage_Options; with SC_Obligations; use SC_Obligations; +with Strings; use Strings; package Coverage is + use all type Unbounded_String; + function Image (Level : Coverage_Level) return String is (case Level is when Insn => "Insn", diff --git a/tools/gnatcov/coverage_options.adb b/tools/gnatcov/coverage_options.adb index 4b88eb86e..38ff21665 100644 --- a/tools/gnatcov/coverage_options.adb +++ b/tools/gnatcov/coverage_options.adb @@ -17,7 +17,6 @@ ------------------------------------------------------------------------------ with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; package body Coverage_Options is @@ -44,13 +43,13 @@ package body Coverage_Options is begin for J in L'Range loop if L (J) then - if Length (Option) /= 0 then + if Option /= "" then Append (Option, '+'); end if; Append (Option, To_Lower (J'Img)); end if; end loop; - return To_String (Option); + return +Option; end Coverage_Option_Value; ----------------------------- @@ -93,7 +92,7 @@ package body Coverage_Options is procedure Put_Option (Cur : Cursor) is begin - if Length (Options) /= 0 then + if Options /= "" then Append (Options, Separator); end if; Append (Options, Key (Cur).all); @@ -103,7 +102,7 @@ package body Coverage_Options is begin Map.Iterate (Put_Option'Access); - return To_String (Options); + return +Options; end Level_Options; -------------------------- diff --git a/tools/gnatcov/coverage_options.ads b/tools/gnatcov/coverage_options.ads index a9ba9334d..f36c644ed 100644 --- a/tools/gnatcov/coverage_options.ads +++ b/tools/gnatcov/coverage_options.ads @@ -24,6 +24,8 @@ with Strings; use Strings; package Coverage_Options is + use all type Unbounded_String; + type Coverage_Level is (Insn, Branch, Stmt, Decision, MCDC, UC_MCDC, ATC, ATCC); -- Coverage objectives supported by xcov. The following values are diff --git a/tools/gnatcov/decision_map.adb b/tools/gnatcov/decision_map.adb index be396a9e9..bb9dad27b 100644 --- a/tools/gnatcov/decision_map.adb +++ b/tools/gnatcov/decision_map.adb @@ -16,7 +16,6 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; with GNAT.Regexp; use GNAT.Regexp; @@ -56,6 +55,7 @@ package body Decision_Map is use Ada.Containers; use Coverage; + use all type Unbounded_String; Decision_Map_Base : Traces_Base; -- The decision map is a list of code addresses, so we manage it as a @@ -543,12 +543,11 @@ package body Decision_Map is if Report_If_Unexpected then declare - use Ada.Strings.Unbounded; Msg : Unbounded_String; begin - Msg := To_Unbounded_String - ("unexpected condition" & CI'Img - & " in decision " & Image (DS_Top.Decision)); + Msg := + +("unexpected condition" & CI'Img + & " in decision " & Image (DS_Top.Decision)); if Tag /= No_SC_Tag then Append (Msg, ", tag=" & Tag_Provider.Tag_Name (Tag)); @@ -559,7 +558,7 @@ package body Decision_Map is -- We will silence it unless explicitely requested with a -- verbose mode. - Report (Exec, Insn.First, To_String (Msg), Kind => Notice); + Report (Exec, Insn.First, +Msg, Kind => Notice); end; end if; return False; diff --git a/tools/gnatcov/diagnostics.adb b/tools/gnatcov/diagnostics.adb index bf431acbf..a3deea367 100644 --- a/tools/gnatcov/diagnostics.adb +++ b/tools/gnatcov/diagnostics.adb @@ -140,9 +140,7 @@ package body Diagnostics is end if; end Tag_Image; - use Ada.Strings.Unbounded; - - Msg : constant String := To_String (M.Msg); + Msg : constant String := +M.Msg; First : Natural := Msg'First; -- Start of processing for Image @@ -206,8 +204,6 @@ package body Diagnostics is Tag : SC_Tag := No_SC_Tag; Kind : Report_Kind := Error) is - use Ada.Strings.Unbounded; - M : constant Message := (Kind => Kind, Exe => Exe, @@ -215,7 +211,7 @@ package body Diagnostics is Sloc => Sloc, SCO => SCO, Tag => Tag, - Msg => To_Unbounded_String (Msg)); + Msg => +Msg); begin Output_Message (M); Store_Message (M); diff --git a/tools/gnatcov/diagnostics.ads b/tools/gnatcov/diagnostics.ads index 8f9011ffa..fbe251eab 100644 --- a/tools/gnatcov/diagnostics.ads +++ b/tools/gnatcov/diagnostics.ads @@ -34,12 +34,12 @@ -- output at the time the report procedure is called. with Ada.Containers.Vectors; -with Ada.Strings.Unbounded; with Coverage; use Coverage; with Logging; with SC_Obligations; use SC_Obligations; with Slocs; use Slocs; +with Strings; use Strings; with Traces; use Traces; with Traces_Elf; use Traces_Elf; @@ -66,7 +66,7 @@ package Diagnostics is Sloc : Source_Location; SCO : SCO_Id; Tag : SC_Tag; - Msg : Ada.Strings.Unbounded.Unbounded_String; + Msg : Unbounded_String; end record; package Message_Vectors is new Ada.Containers.Vectors diff --git a/tools/gnatcov/disassemble_insn_properties.adb b/tools/gnatcov/disassemble_insn_properties.adb index de17a4f64..439f0b70d 100644 --- a/tools/gnatcov/disassemble_insn_properties.adb +++ b/tools/gnatcov/disassemble_insn_properties.adb @@ -17,7 +17,6 @@ ------------------------------------------------------------------------------ with Ada.Characters.Handling; -with Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; with Interfaces; use Interfaces; @@ -28,24 +27,19 @@ with Disassemblers; with Elf_Disassemblers; with Hex_Images; with Highlighting; +with Strings; use Strings; with Traces_Elf; use Traces_Elf; with Traces; use Traces; package body Disassemble_Insn_Properties is - function "+" (S : String) return Ada.Strings.Unbounded.Unbounded_String - renames Ada.Strings.Unbounded.To_Unbounded_String; - -- Shortcut to To_Unbounded_String - function "+" (PC : Pc_Type) return JSON_Value is (Create ("0x" & Hex_Images.Hex_Image (PC))); -- Shortcut to convert addresses to GNATCOLL.JSON strings "0x...". We -- represent addresses as hexadecimal strings in order not to rely on JSON -- libraries implementation constraints about abritrarily sized integers. - Branch_Kind_Strings : constant - array (Branch_Kind) - of Ada.Strings.Unbounded.Unbounded_String := + Branch_Kind_Strings : constant array (Branch_Kind) of Unbounded_String := (Br_None => +"none", Br_Call => +"call", Br_Ret => +"return", diff --git a/tools/gnatcov/disassemblers.adb b/tools/gnatcov/disassemblers.adb index 7e8be86ee..3f1146c8c 100644 --- a/tools/gnatcov/disassemblers.adb +++ b/tools/gnatcov/disassemblers.adb @@ -16,17 +16,19 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; -with Ada.Text_IO; use Ada.Text_IO; +with Ada.Text_IO; use Ada.Text_IO; with Arch; with Interfaces; use Interfaces; with Hex_Images; use Hex_Images; +with Strings; use Strings; with Outputs; with Version; package body Disassemblers is + use all type Unbounded_String; + --------- -- "<" -- --------- @@ -62,10 +64,10 @@ package body Disassemblers is Append (Dump, Hex_Image (Get (Bin, I))); I := I + 1; end loop; - if Length (Dump) = 0 then + if Dump = "" then Append (Dump, ""); end if; - return To_String (Dump); + return +Dump; end Dump_Bin; ------------------------------ diff --git a/tools/gnatcov/factory_registry.adb b/tools/gnatcov/factory_registry.adb index 363ff0fee..264781c7f 100644 --- a/tools/gnatcov/factory_registry.adb +++ b/tools/gnatcov/factory_registry.adb @@ -16,11 +16,14 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with Ada.Containers.Indefinite_Ordered_Maps; +with Strings; use Strings; + package body Factory_Registry is + use all type Unbounded_String; + type Factory_Record is record Factory : Create_Function; Tag : Ada.Tags.Tag; @@ -106,7 +109,7 @@ package body Factory_Registry is Append (Result, Key (Cur)); end loop; - return To_String (Result); + return +Result; end Registered_Names; end Factory_Registry; diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index c282007ba..3a4d8f7b1 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -618,10 +618,9 @@ package body Files_Table is procedure Consolidate_Source_File_Unit (Index : Valid_Source_File_Index; New_Unit : Compilation_Unit) is - use Ada.Strings.Unbounded; FI : File_Info renames Files_Table.Element (Index).all; begin - pragma Assert (New_Unit.Unit_Name /= Null_Unbounded_String); + pragma Assert (New_Unit.Unit_Name /= ""); if FI.Kind /= Source_File then null; elsif not FI.Unit.Known then @@ -2017,10 +2016,7 @@ package body Files_Table is then Name else Ada.Directories.Simple_Name (Name)); begin - Set_SFI_Simple_Name - (Relocs, - CP_SFI, - Ada.Strings.Unbounded.To_Unbounded_String (Simple_Name)); + Set_SFI_Simple_Name (Relocs, CP_SFI, +Simple_Name); case Kind is when Stub_File => FE := (Kind => Stub_File, others => <>); @@ -2182,8 +2178,6 @@ package body Files_Table is (Preprocessed_Filename : String; Postprocessed_Filename : String) is - use Ada.Strings.Unbounded; - use Strings; Preprocessed_File : Ada.Text_IO.File_Type; Postprocessed_File : Ada.Text_IO.File_Type; begin diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 833c58fe9..653b48458 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -19,7 +19,6 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; -with Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; with GNAT.Strings; use GNAT.Strings; @@ -33,7 +32,7 @@ with Logging; with Paths; use Paths; with SC_Obligations; use SC_Obligations; with Slocs; use Slocs; -with Strings; +with Strings; use Strings; with Traces_Dbase; use Traces_Dbase; with Traces_Elf; use Traces_Elf; with Traces_Lines; use Traces_Lines; @@ -42,6 +41,8 @@ with Types; use Types; package Files_Table is + use all type Unbounded_String; + Files_Table_Trace : constant Logging.GNATCOLL_Trace := Logging.Create_Trace ("FILE_TABLE"); @@ -316,22 +317,17 @@ package Files_Table is type Compilation_Unit is record Language : Any_Language_Kind; - Unit_Name : Ada.Strings.Unbounded.Unbounded_String; + Unit_Name : Unbounded_String; end record; -- This record is used to uniquely identify a unit of any language -- supported by gnatcov. The unique identifier, stored as Unit_Name is -- the unit name for unit-based language, and the file fullname for -- file-based languages. - use type Ada.Strings.Unbounded.Unbounded_String; - function Image (U : Compilation_Unit) return String is (case U.Language is - when Unit_Based_Language => - To_Lower (Ada.Strings.Unbounded.To_String (U.Unit_Name)), - when File_Based_Language => - Fold_Filename_Casing - (Ada.Strings.Unbounded.To_String (U.Unit_Name))); + when Unit_Based_Language => To_Lower (+U.Unit_Name), + when File_Based_Language => Fold_Filename_Casing (+U.Unit_Name)); function "<" (L, R : Compilation_Unit) return Boolean is (Image (L) < Image (R)); diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 8eb82c02f..b39671d89 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -22,7 +22,6 @@ with Ada.Exceptions; with Ada.IO_Exceptions; with Ada.Strings.Fixed; with Ada.Strings.Maps; -with Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; with GNAT.OS_Lib; @@ -1199,9 +1198,7 @@ procedure GNATcov_Bits_Specific is procedure Report_Bad_Trace (Trace_Filename : String; Result : Read_Result) is - Message : constant String := - Trace_Filename & ": " - & Ada.Strings.Unbounded.To_String (Result.Error); + Message : constant String := Trace_Filename & ": " & (+Result.Error); begin if Keep_Reading_Traces then Outputs.Error (Message); @@ -1875,8 +1872,6 @@ begin -- Read and process traces declare - use Ada.Strings.Unbounded; - Bin_Traces_Present : Boolean := False; Src_Traces_Present : Boolean := False; @@ -2126,7 +2121,7 @@ begin Trace_Filename : constant String := (if Trace_File = null then "" - else To_String (Trace_File.Filename)); + else +Trace_File.Filename); Exe_File : Exe_File_Acc; begin Init_Base (Base); @@ -2182,7 +2177,7 @@ begin Trace_Filename : constant String := (if Trace_File = null then "" - else To_String (Trace_File.Filename)); + else +Trace_File.Filename); Current_Exec : Exe_File_Acc; Current_Sym : Address_Info_Acc; diff --git a/tools/gnatcov/highlighting.adb b/tools/gnatcov/highlighting.adb index 5f5c3bb5a..fc5b9b737 100644 --- a/tools/gnatcov/highlighting.adb +++ b/tools/gnatcov/highlighting.adb @@ -16,13 +16,14 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Strings.Unbounded; +with Strings; use Strings; package body Highlighting is + use all type Unbounded_String; + function Get_Token_Last - (Buffer : Buffer_Type; - First : Natural) return Natural; + (Buffer : Buffer_Type; First : Natural) return Natural; -- Return the last character index in Buffer of the token that starts at -- index First. @@ -31,8 +32,7 @@ package body Highlighting is -------------------- function Get_Token_Last - (Buffer : Buffer_Type; - First : Natural) return Natural + (Buffer : Buffer_Type; First : Natural) return Natural is Position : Natural := First + 1; begin @@ -173,8 +173,6 @@ package body Highlighting is function Format_Token (Text : String; Kind : Some_Token_Kind) return String is - use Ada.Strings.Unbounded; - Hex_Digits : constant array (0 .. 15) of Character := "0123456789abcdef"; Result : Unbounded_String; @@ -197,7 +195,7 @@ package body Highlighting is end if; end; end loop; - return To_String (Result); + return +Result; end Format_Token; end Highlighting; diff --git a/tools/gnatcov/inputs.adb b/tools/gnatcov/inputs.adb index 5329532ed..d277d092e 100644 --- a/tools/gnatcov/inputs.adb +++ b/tools/gnatcov/inputs.adb @@ -17,7 +17,6 @@ ------------------------------------------------------------------------------ with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Strings.Unbounded; with Ada.Text_IO; use Ada.Text_IO; with GNAT.CRC32; @@ -289,7 +288,6 @@ package body Inputs is Has_Matcher : out Boolean; Case_Insensitive : Boolean := False) is - use Ada.Strings.Unbounded; use String_Vectors; Pattern : Unbounded_String; @@ -337,7 +335,7 @@ package body Inputs is String_Vectors.Iterate (Pattern_List, Process'Access); Has_Matcher := not First; if Has_Matcher then - Matcher := GNAT.Regexp.Compile (Pattern => To_String (Pattern)); + Matcher := GNAT.Regexp.Compile (Pattern => +Pattern); end if; end Create_Matcher; diff --git a/tools/gnatcov/inputs.ads b/tools/gnatcov/inputs.ads index bd80f9c11..c2914b197 100644 --- a/tools/gnatcov/inputs.ads +++ b/tools/gnatcov/inputs.ads @@ -23,6 +23,9 @@ with GNAT.Strings; use GNAT.Strings; with Strings; use Strings; package Inputs is + + use all type Unbounded_String; + -- This package provides a simple way to accumulate a set of -- command line inputs into a container, plus basic support for -- reading such inputs from a list in a file. diff --git a/tools/gnatcov/instrument-ada_preprocessing.adb b/tools/gnatcov/instrument-ada_preprocessing.adb index 24fe4274f..b3e75fe16 100644 --- a/tools/gnatcov/instrument-ada_preprocessing.adb +++ b/tools/gnatcov/instrument-ada_preprocessing.adb @@ -73,11 +73,10 @@ package body Instrument.Ada_Preprocessing is begin for Cur in Map.Iterate loop declare - Name : constant US.Unbounded_String := - Definition_Maps.Key (Cur); + Name : constant Unbounded_String := Definition_Maps.Key (Cur); Value : Value_Type renames Map.Constant_Reference (Cur); begin - Result.Set_Field (US.To_String (Name), Serialize (Value)); + Result.Set_Field (+Name, Serialize (Value)); end; end loop; return Result; @@ -150,11 +149,11 @@ package body Instrument.Ada_Preprocessing is begin for Cur in File_Configs.Iterate loop declare - Filename : constant US.Unbounded_String := + Filename : constant Unbounded_String := File_Config_Maps.Key (Cur); begin Map.Set_Field - (US.To_String (Filename), + (+Filename, Serialize (File_Configs.Constant_Reference (Cur))); end; end loop; @@ -165,8 +164,7 @@ package body Instrument.Ada_Preprocessing is declare File : Ada.Text_IO.File_Type; - Doc : constant US.Unbounded_String := - Result.Write (Compact => False); + Doc : constant Unbounded_String := Result.Write (Compact => False); begin Create (File, Out_File, Filename); Put_Line (File, Doc); @@ -234,8 +232,7 @@ package body Instrument.Ada_Preprocessing is procedure Process (Name : UTF8_String; Value : JSON_Value) is begin - Result.Insert - (US.To_Unbounded_String (Name), Deserialize (Value)); + Result.Insert (+Name, Deserialize (Value)); end Process; begin Desc.Map_JSON_Object (Process'Access); @@ -301,8 +298,7 @@ package body Instrument.Ada_Preprocessing is ("Loading preprocessor data from temporary file " & Filename & " for " & Name); begin - File_Configs.Insert - (US.To_Unbounded_String (Name), Deserialize (Value)); + File_Configs.Insert (+Name, Deserialize (Value)); end Process; begin File_Configs_Desc.Map_JSON_Object (Process'Access); diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 52b6b7fe5..6a3f37000 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1181,8 +1181,8 @@ package body Instrument.Ada_Unit is type Ada_Source_Rewriter is limited new Ada.Finalization.Limited_Controlled with record - Input_Filename : Ada.Strings.Unbounded.Unbounded_String; - Output_Filename : Ada.Strings.Unbounded.Unbounded_String; + Input_Filename : Unbounded_String; + Output_Filename : Unbounded_String; Unit : Libadalang.Analysis.Analysis_Unit; Handle : Libadalang.Rewriting.Rewriting_Handle; @@ -1527,7 +1527,7 @@ package body Instrument.Ada_Unit is & (if Is_MCDC then ", {}" & ", " & Img (Bits.Path_Bits_Base) - & ", " & To_String (MCDC_State) + & ", " & (+MCDC_State) else "") & ")"; @@ -1577,7 +1577,7 @@ package body Instrument.Ada_Unit is is E : Instrumentation_Entities renames IC.Entities; Call_Img : constant String := - "{}.Witness (" & To_String (MCDC_State) & "," + "{}.Witness (" & (+MCDC_State) & "," & Img (Offset) & "," & First'Img & ")"; RH_Call : constant Node_Rewriting_Handle := @@ -1682,7 +1682,7 @@ package body Instrument.Ada_Unit is begin -- No instrumentation for condition if there is no local state variable - if Length (SC.State) = 0 then + if SC.State = "" then return; end if; @@ -3534,7 +3534,7 @@ package body Instrument.Ada_Unit is Process_Expression (UIC, P_Get_Aspect_Spec_Expr (D, To_Unbounded_Text (Name)), - 'A'); + 'A'); end Process_Contract; ------------------------------------ @@ -6657,8 +6657,8 @@ package body Instrument.Ada_Unit is raise Xcov_Exit_Exc; end if; - Self.Input_Filename := To_Unbounded_String (Input_Filename); - Self.Output_Filename := To_Unbounded_String (Output_Filename); + Self.Input_Filename := +Input_Filename; + Self.Output_Filename := +Output_Filename; Self.Unit := Unit; Self.Handle := Start_Rewriting (Instrumenter.Context); end Start_Rewriting; @@ -6699,8 +6699,8 @@ package body Instrument.Ada_Unit is -- which should be unique in Ada projects anyway. declare - N : constant Unbounded_String := To_Unbounded_String - (Ada.Directories.Simple_Name (Langkit_Support.Text.Image (Name))); + N : constant Unbounded_String := + +Ada.Directories.Simple_Name (Langkit_Support.Text.Image (Name)); begin if Self.Reported_Files.Contains (N) then return; @@ -6712,7 +6712,7 @@ package body Instrument.Ada_Unit is -- hierarchy. declare - Source_Name : constant String := To_String (N); + Source_Name : constant String := +N; begin if not (GNATCOLL.Utils.Starts_With (Source_Name, "gnatcov_rts") or else GNATCOLL.Utils.Starts_With (Source_Name, "gcvrt")) @@ -6721,9 +6721,9 @@ package body Instrument.Ada_Unit is -- instrumenting when we noticed that the source file N was -- missing. - if Length (Self.Instrumented_File) > 0 then + if Self.Instrumented_File /= "" then Warn ("While instrumenting " - & To_String (Self.Instrumented_File) + & (+Self.Instrumented_File) & "..."); Self.Instrumented_File := Null_Unbounded_String; end if; @@ -7112,8 +7112,7 @@ package body Instrument.Ada_Unit is begin Visit (Unit_Name); Append (Result, Extension); - return Output_Dir - / Ada.Characters.Handling.To_Lower (To_String (Result)); + return Output_Dir / Ada.Characters.Handling.To_Lower (+Result); end Filename; Wrapped_Prefix : constant String := "Xcov_Wrapped_"; @@ -7210,7 +7209,7 @@ package body Instrument.Ada_Unit is 4 => Generic_Wrapper_Name), Rule => Compilation_Unit_Rule); Generic_Wrapper_Body_Filename := - To_Unbounded_String (Filename (Generic_Wrapper_Name, ".adb")); + +Filename (Generic_Wrapper_Name, ".adb"); -- Code that is inserted to dump coverage buffers will land in this -- wrapper: set Prelude, Main_Decls and Main_Stmts accordingly. @@ -7476,7 +7475,7 @@ package body Instrument.Ada_Unit is procedure Apply (Self : in out Ada_Source_Rewriter'Class) is begin - Write_To_File (Handle (Self.Unit), To_String (Self.Output_Filename)); + Write_To_File (Handle (Self.Unit), +Self.Output_Filename); Abort_Rewriting (Self.Handle); Self.Finalize; end Apply; @@ -7787,7 +7786,7 @@ package body Instrument.Ada_Unit is Saved_Root : constant Node_Rewriting_Handle := Root (UH); begin Set_Root (UH, Desc.Generic_Wrapper_Body); - Write_To_File (UH, To_String (Desc.Generic_Wrapper_Body_Filename)); + Write_To_File (UH, +Desc.Generic_Wrapper_Body_Filename); Set_Root (UH, Saved_Root); end; end if; @@ -8577,7 +8576,7 @@ package body Instrument.Ada_Unit is begin Helper_Unit := Sys_Prefix; Helper_Unit.Append - (To_Unbounded_String ("D") & "B_manual_" & To_String (Prj.Prj_Name)); + (To_Unbounded_String ("D" & "B_manual_" & (+Prj.Prj_Name))); return Helper_Unit; end Create_Manual_Helper_Unit_Name; @@ -8628,7 +8627,7 @@ package body Instrument.Ada_Unit is else Helper_Unit := Sys_Prefix; Helper_Unit.Append - (To_Unbounded_String ("D") & Instrumented_Unit_Slug (Main)); + (To_Unbounded_String ("D" & Instrumented_Unit_Slug (Main))); end if; -- Compute the qualified names we need for instrumentation @@ -8749,14 +8748,14 @@ package body Instrument.Ada_Unit is Indent2 : constant String := Indent1 & " "; Env_Var : constant String := - (if Length (Dump_Config.Filename_Env_Var) = 0 + (if Dump_Config.Filename_Env_Var = "" then U & ".Default_Trace_Filename_Env_Var" - else """" & To_String (Dump_Config.Filename_Env_Var) + else """" & (+Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := - """" & To_String ((if Dump_Config.Trigger = Manual - then Prj.Prj_Name - else Dump_Config.Filename_Prefix)) & """"; + """" & (if Dump_Config.Trigger = Manual + then +Prj.Prj_Name + else +Dump_Config.Filename_Prefix) & """"; Tag : constant String := """" & (+Instrumenter.Tag) & """"; Simple : constant String := (if Dump_Config.Filename_Simple @@ -8779,9 +8778,9 @@ package body Instrument.Ada_Unit is -- get the current execution time. File.Put_Line (" Program_Name => """ - & (if Dump_Trigger = Manual - then "manual_dump""," - else To_Ada (Main.Unit) & """,")); + & (if Dump_Trigger = Manual + then "manual_dump""," + else To_Ada (Main.Unit) & """,")); File.Put (" Exec_Date => 0"); end case; File.Put_Line (");"); @@ -8897,7 +8896,7 @@ package body Instrument.Ada_Unit is Override_Dump_Trigger => Manual, Has_Controlled => False); - Helper_Unit := To_Unbounded_String (To_Ada (Ada_Helper_Unit)); + Helper_Unit := +To_Ada (Ada_Helper_Unit); end Emit_Dump_Helper_Unit_Manual; ---------------------------- @@ -9098,8 +9097,7 @@ package body Instrument.Ada_Unit is if Switches.Misc_Trace.Is_Active then Switches.Misc_Trace.Trace ("Instrumenting " & Basename); else - Event_Handler.Instrumented_File := - To_Unbounded_String (Basename); + Event_Handler.Instrumented_File := +Basename; end if; Last_Buffer_Index := Last_Buffer_Index + 1; diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 9410ca1d4..686b337af 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -20,7 +20,6 @@ with Ada.Containers.Indefinite_Hashed_Sets; with Ada.Containers.Vectors; -with Ada.Strings.Unbounded; with Ada.Strings.Wide_Wide_Hash; with Ada.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; @@ -204,7 +203,7 @@ private Decision : Expr; -- Decision expression - State : Ada.Strings.Unbounded.Unbounded_String; + State : Unbounded_String; -- Name of MC/DC state local variable Is_Contract : Boolean := False; @@ -219,7 +218,7 @@ private Condition : Expr; -- Condition expression - State : Ada.Strings.Unbounded.Unbounded_String; + State : Unbounded_String; -- Name of MC/DC state local variable First : Boolean; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index eb1ae15fd..9e31e8374 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -49,8 +49,6 @@ with Text_Files; use Text_Files; package body Instrument.C is - package US renames Ada.Strings.Unbounded; - function To_Chars_Ptr_Array (V : String_Vectors.Vector) return chars_ptr_array; -- Convert a string vector to a chars_ptr_array. Result must be freed by @@ -176,7 +174,7 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; Decision : Cursor_T; - State : US.Unbounded_String); + State : Unbounded_String); -- Add an entry to UIC.Source_Decisions overriding procedure Instrument_Condition @@ -184,7 +182,7 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; Condition : Cursor_T; - State : US.Unbounded_String; + State : Unbounded_String; First : Boolean); -- Add an entry to UIC.Source_Conditions @@ -199,7 +197,7 @@ package body Instrument.C is (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; Name : String; - MCDC_State : out US.Unbounded_String); + MCDC_State : out Unbounded_String); -- Wrapper around Insert_MCDC_State overload overriding procedure Insert_Text_Before_Token @@ -359,7 +357,7 @@ package body Instrument.C is procedure Emit_Dump_Helper_Unit (Dump_Config : Any_Dump_Config; Main : Compilation_Unit_Part; - Helper_Unit : out US.Unbounded_String; + Helper_Unit : out Unbounded_String; Instrumenter : C_Family_Instrumenter_Type'Class; Prj : Prj_Desc); -- Emit the unit to contain helpers to implement the automatic dump of @@ -745,7 +743,7 @@ package body Instrument.C is Expansion_Stack : Expansion_Lists.List; Definition_Info : Expansion_Info; - Macro_Expansion_Name : US.Unbounded_String; + Macro_Expansion_Name : Unbounded_String; Immediate_Expansion_Loc : Source_Location_T; Macro_Arg_Expanded_Loc : Source_Location_T; begin @@ -919,7 +917,7 @@ package body Instrument.C is -- then it means the location refers to a token paste, or -- stringization and not a macro at all. Let's walk past it. - if Length (Macro_Expansion_Name) /= 0 then + if Macro_Expansion_Name /= "" then Expansion_Stack.Append ((Macro_Name => Macro_Expansion_Name, Sloc => @@ -1031,7 +1029,7 @@ package body Instrument.C is (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; Name : String; - MCDC_State : out US.Unbounded_String) is + MCDC_State : out Unbounded_String) is begin if not UIC.Disable_Instrumentation then MCDC_State := +Insert_MCDC_State (UIC, Name); @@ -1126,7 +1124,7 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; Decision : Cursor_T; - State : US.Unbounded_String) is + State : Unbounded_String) is begin if UIC.Disable_Instrumentation then UIC.Non_Instr_LL_SCOs.Include (SCO_Id (LL_SCO)); @@ -1148,7 +1146,7 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; Condition : Cursor_T; - State : US.Unbounded_String; + State : Unbounded_String; First : Boolean) is begin if UIC.Disable_Instrumentation then @@ -1260,7 +1258,7 @@ package body Instrument.C is begin -- No instrumentation for condition if there is no local state variable - if US.Length (SC.State) = 0 then + if SC.State = "" then return; end if; @@ -1276,7 +1274,7 @@ package body Instrument.C is (N => SC.Condition, Text => "gnatcov_rts_witness_condition (" - & US.To_String (SC.State) & ", " + & (+SC.State) & ", " & Img (Offset) & ", " & First_Image & ", " & "(", @@ -1335,7 +1333,7 @@ package body Instrument.C is Text => ", " & MCDC_Buffer_Symbol (UIC.Instrumented_Unit) & Buffers_Subscript (Buffers_Index) & ", " & Img (Bits.Path_Bits_Base) & ", " - & US.To_String (SD.State), + & (+SD.State), Rew => UIC.Rewriter); end if; Insert_Text_After_Start_Of (N => N, @@ -1563,7 +1561,7 @@ package body Instrument.C is Condition_Count : Natural := 0; -- Count of conditions for current decision (MC/DC only) - MCDC_State : US.Unbounded_String; + MCDC_State : Unbounded_String; -- Name of MC/DC state local variable for current decision (MC/DC -- only). @@ -2390,7 +2388,7 @@ package body Instrument.C is begin for N of L loop - if Length (Trailing_Braces) /= 0 then + if Trailing_Braces /= "" then UIC.Pass.Insert_Text_Before (UIC, Start_Sloc (N), +Trailing_Braces); Trailing_Braces := +""; @@ -3400,13 +3398,13 @@ package body Instrument.C is if Multiline then Append (Result, " "); end if; - Append (Result, To_String (Exprs.Element (I))); + Append (Result, (+Exprs.Element (I))); end loop; if Multiline then Append (Result, ASCII.LF); end if; Append (Result, "}"); - return To_String (Result); + return (+Result); end Format_Array_Init_Expr; ---------------------- @@ -3686,7 +3684,7 @@ package body Instrument.C is procedure Emit_Dump_Helper_Unit (Dump_Config : Any_Dump_Config; Main : Compilation_Unit_Part; - Helper_Unit : out US.Unbounded_String; + Helper_Unit : out Unbounded_String; Instrumenter : C_Family_Instrumenter_Type'Class; Prj : Prj_Desc) is @@ -3758,7 +3756,7 @@ package body Instrument.C is when Binary_File => declare Env_Var : constant String := - (if US.Length (Dump_Config.Filename_Env_Var) = 0 + (if Dump_Config.Filename_Env_Var = "" then "GNATCOV_RTS_DEFAULT_TRACE_FILENAME_ENV_VAR" else """" & (+Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := @@ -3818,7 +3816,7 @@ package body Instrument.C is overriding procedure Emit_Dump_Helper_Unit_Manual (Self : in out C_Family_Instrumenter_Type; - Helper_Unit : out US.Unbounded_String; + Helper_Unit : out Unbounded_String; Dump_Config : Any_Dump_Config; Prj : Prj_Desc) is @@ -3863,7 +3861,7 @@ package body Instrument.C is Dump_Procedure_Symbol (Main => Dummy_Main, Manual => True, Prj_Name => +Prj.Prj_Name); Contents : Unbounded_String := - "extern void " & To_Unbounded_String (Dump_Procedure) & " (void);"; + +("extern void " & Dump_Procedure & " (void);"); begin -- Preprocess the source, keeping the comment to look for the manual -- dump indication later. @@ -3895,7 +3893,7 @@ package body Instrument.C is Ada.Text_IO.Open (File => File, Mode => In_File, - Name => To_String (PP_Filename)); + Name => (+PP_Filename)); while not Ada.Text_IO.End_Of_File (File) loop declare @@ -3925,9 +3923,9 @@ package body Instrument.C is Ada.Text_IO.Open (File => File, Mode => Out_File, - Name => To_String (PP_Filename)); + Name => (+PP_Filename)); - Ada.Text_IO.Put_Line (File, To_String (Contents)); + Ada.Text_IO.Put_Line (File, (+Contents)); Ada.Text_IO.Close (File); end if; @@ -3944,7 +3942,7 @@ package body Instrument.C is Dump_Config : Any_Dump_Config; Prj : Prj_Desc) is - Helper_Filename : US.Unbounded_String; + Helper_Filename : Unbounded_String; -- Name of file to contain helpers implementing the buffers dump Rew : C_Source_Rewriter; @@ -4154,7 +4152,7 @@ package body Instrument.C is New_File (Prj, To_Symbol_Name (Sys_Prefix) - & "_d_b_" & To_String (Prj.Prj_Name) + & "_d_b_" & (+Prj.Prj_Name) & (+Prj.Body_Suffix (C_Family_Instrumenter_Type'Class (Self).Language))); begin @@ -4221,7 +4219,7 @@ package body Instrument.C is Compiler_Driver : constant Unbounded_String := Prj.Compiler_Driver (Instrumenter.Language); begin - if Compiler_Driver = Null_Unbounded_String then + if Compiler_Driver = "" then Outputs.Fatal_Error ("could not find a compiler for " & Image (Instrumenter.Language)); end if; @@ -4279,7 +4277,7 @@ package body Instrument.C is Append (Result, Init_Expr); end if; Append (Result, ';'); - return To_String (Result); + return +Result; end Format_Def; -------------------- diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index c6d455fe9..ee8a78dc9 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -22,7 +22,6 @@ with Ada.Containers.Hashed_Maps; with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; with Ada.Finalization; -with Ada.Strings.Unbounded.Hash; with Namet; use Namet; @@ -71,7 +70,7 @@ package Instrument.C is overriding procedure Emit_Dump_Helper_Unit_Manual (Self : in out C_Family_Instrumenter_Type; - Helper_Unit : out US.Unbounded_String; + Helper_Unit : out Unbounded_String; Dump_Config : Any_Dump_Config; Prj : Prj_Desc); -- Emit the dump helper unit @@ -187,7 +186,7 @@ package Instrument.C is Decision : Cursor_T; -- Decision expression - State : Ada.Strings.Unbounded.Unbounded_String; + State : Unbounded_String; -- Name of MC/DC state local variable end record; @@ -198,7 +197,7 @@ package Instrument.C is Condition : Cursor_T; -- Condition expression - State : Ada.Strings.Unbounded.Unbounded_String; + State : Unbounded_String; -- Name of MC/DC state local variable First : Boolean; @@ -313,7 +312,7 @@ package Instrument.C is package Source_Of_Interest_Maps is new Ada.Containers.Hashed_Maps (Key_Type => Unbounded_String, Element_Type => Source_Of_Interest, - Hash => Hash, + Hash => Strings.Hash, Equivalent_Keys => "="); type File_Scope_Type is record @@ -443,21 +442,21 @@ private UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; Decision : Cursor_T; - State : US.Unbounded_String) is null; + State : Unbounded_String) is null; procedure Instrument_Condition (Pass : Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; Condition : Cursor_T; - State : US.Unbounded_String; + State : Unbounded_String; First : Boolean) is null; procedure Insert_MCDC_State (Pass : Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; Name : String; - MCDC_State : out US.Unbounded_String) is null; + MCDC_State : out Unbounded_String) is null; procedure Insert_Text_Before_Token (Pass : Pass_Kind; @@ -501,7 +500,7 @@ private -- Such declarations must go before being used, so this should -- correspond to the first rewritable location. - Output_Filename : Ada.Strings.Unbounded.Unbounded_String; + Output_Filename : Unbounded_String; end record; overriding procedure Initialize (Self : in out C_Source_Rewriter); diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 60433ca33..18a44011f 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -153,7 +153,7 @@ package body Instrument.Common is Append (Result, Strings.Img (Integer (Byte))); end loop; Append (Result, Closing); - return To_String (Result); + return +Result; end Format_Fingerprint; -------------- @@ -205,7 +205,7 @@ package body Instrument.Common is if (Coverage.MCDC_Coverage_Enabled or else Coverage.Assertion_Condition_Coverage_Enabled) - and then Length (State_Variable) > 0 + and then State_Variable /= "" and then Path_Count > 0 and then Path_Count < Get_Path_Count_Limit then @@ -371,8 +371,7 @@ package body Instrument.Common is is Base_Filename : constant String := Ada.Directories.Simple_Name (Name); - Output_Filename : constant String := - To_String (Prj.Output_Dir) / Base_Filename; + Output_Filename : constant String := (+Prj.Output_Dir) / Base_Filename; begin return Output_Filename; end New_File; @@ -405,7 +404,7 @@ package body Instrument.Common is case CU_Name.Language_Kind is when Unit_Based_Language => for Id of CU_Name.Unit loop - if Length (Filename) > 0 then + if Filename /= "" then Append (Filename, Prj.Dot_Replacement); end if; Append (Filename, To_Lower (To_String (Id))); diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 2c4a53a43..eca9c9f0a 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -54,7 +54,6 @@ with Ada.Containers.Hashed_Sets; with Ada.Containers.Ordered_Maps; with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; -with Ada.Strings.Unbounded.Hash; with GNAT.Regpat; use GNAT.Regpat; @@ -170,13 +169,13 @@ package Instrument.Common is -- C/C++). package File_Sets is new Ada.Containers.Hashed_Sets - (Element_Type => Ada.Strings.Unbounded.Unbounded_String, - "=" => Ada.Strings.Unbounded."=", - Equivalent_Elements => Ada.Strings.Unbounded."=", - Hash => Ada.Strings.Unbounded.Hash); + (Element_Type => Unbounded_String, + "=" => "=", + Equivalent_Elements => "=", + Hash => Strings.Hash); type Instrumented_Unit_Info is record - Filename : Ada.Strings.Unbounded.Unbounded_String; + Filename : Unbounded_String; -- Name of the source file for this unit Language : Some_Language; diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index a6f5483f5..22f06c04c 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -17,7 +17,6 @@ ------------------------------------------------------------------------------ with Ada.Direct_IO; -with Ada.Strings.Unbounded; with Ada.Text_IO; with Ada.Unchecked_Conversion; with Ada.Unchecked_Deallocation; @@ -911,7 +910,7 @@ package body Instrument.Input_Traces is begin Read_Source_Trace_File (Filename, Result); if not Result.Success then - Outputs.Fatal_Error (Ada.Strings.Unbounded.To_String (Result.Error)); + Outputs.Fatal_Error (+Result.Error); end if; end Dump_Source_Trace_File; diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index d6cb9cb81..59d6e7680 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -25,8 +25,6 @@ with Ada.Exceptions; with Ada.IO_Exceptions; with Ada.Strings; with Ada.Strings.Fixed; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; -with Ada.Strings.Unbounded.Hash; with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Deallocation; @@ -54,7 +52,6 @@ with JSON; use JSON; with Outputs; with Paths; use Paths; with Project; use Project; -with Strings; use Strings; with Support_Files; with Text_Files; use Text_Files; @@ -90,7 +87,7 @@ is -- Whether this project is externally built. In that case, we assume its -- units of interest have already been instrumented. - Output_Dir : Ada.Strings.Unbounded.Unbounded_String; + Output_Dir : Unbounded_String; -- Subdirectory in the project file's object directory. All we generate -- for this project must land in it. @@ -101,10 +98,10 @@ is type Project_Info_Access is access all Project_Info; package Project_Info_Maps is new Ada.Containers.Hashed_Maps - (Key_Type => Ada.Strings.Unbounded.Unbounded_String, + (Key_Type => Unbounded_String, Element_Type => Project_Info_Access, - Equivalent_Keys => Ada.Strings.Unbounded."=", - Hash => Ada.Strings.Unbounded.Hash); + Equivalent_Keys => "=", + Hash => Strings.Hash); -- Mapping from project name (as returned by GNATCOLL.Projects.Name) to -- Project_Info records. Project_Info records are owned by this map, and -- thus must be deallocated when maps are deallocated. @@ -375,7 +372,7 @@ is Args : String_Vectors.Vector; begin for S of Switches.all loop - Args.Append (To_Unbounded_String (S.all)); + Args.Append (+S.all); end loop; GNAT.Strings.Free (Switches); Import_From_Args (Options, Args); @@ -557,7 +554,7 @@ is -- with ".sid". Also make sure to use the most extending project in the -- hierarchy, which is where GPRbuild puts ALI/object files. - SID_Basename : US.Unbounded_String; + SID_Basename : Unbounded_String; Project : constant GPR.Project_Type := GPR.Extending_Project @@ -812,7 +809,7 @@ is Args : String_Vectors.Vector; begin for S of Switches.all loop - Args.Append (To_Unbounded_String (S.all)); + Args.Append (+S.all); end loop; GNAT.Strings.Free (Switches); Import_From_Args (Options, Args); @@ -1169,9 +1166,9 @@ begin IC.Config_Pragmas_File := +Create_Config_Pragmas_File (Project.Project.Root_Project); IC.Sources_Of_Interest_Response_File := - +To_String (Root_Project_Info.all.Output_Dir) / ".sources_of_interest"; + +(+Root_Project_Info.all.Output_Dir) / ".sources_of_interest"; IC.Ada_Preprocessor_Data_File := - +To_String (Root_Project_Info.all.Output_Dir) / "prep-data.json"; + +(+Root_Project_Info.all.Output_Dir) / "prep-data.json"; Instrument.Ada_Preprocessing.Create_Preprocessor_Data_File (+IC.Ada_Preprocessor_Data_File); @@ -1407,7 +1404,7 @@ begin -- here: we use the executable name, that is retrieved from -- the project. - if Length (Dump_Config.Filename_Prefix) = 0 then + if Dump_Config.Filename_Prefix = "" then Explicit_Dump_Config.Filename_Prefix := +(+Root_Project_Info.Project.Executable_Name (Main.File.Full_Name, Include_Suffix => True)); diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index 5213f4ee5..cae99a724 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -318,11 +318,11 @@ package body Instrument.Setup_Config is if Dump_Config.Filename_Simple then Dump_Config_JSON.Set_Field ("dump-filename-simple", True); end if; - if Length (Dump_Config.Filename_Env_Var) /= 0 then + if Dump_Config.Filename_Env_Var /= "" then Dump_Config_JSON.Set_Field ("dump-filename-env-var", Dump_Config.Filename_Env_Var); end if; - if Length (Dump_Config.Filename_Prefix) /= 0 then + if Dump_Config.Filename_Prefix /= "" then Dump_Config_JSON.Set_Field ("dump-filename-prefix", Dump_Config.Filename_Prefix); end if; diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 0aafedd31..c001b01cf 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -22,8 +22,6 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Directories; with Ada.Strings; with Ada.Strings.Hash; -with Ada.Strings.Unbounded.Equal_Case_Insensitive; -with Ada.Strings.Unbounded.Less_Case_Insensitive; with GNAT.OS_Lib; @@ -57,7 +55,7 @@ package body Instrument is Result : Unbounded_String; begin for Id of Name loop - if Length (Result) > 0 then + if Result /= "" then Append (Result, "."); end if; Append (Result, To_String (Id)); @@ -139,9 +137,11 @@ package body Instrument is Right_Id : constant Unbounded_String := Unbounded_String (Right.Unit.Element (I)); begin - if not Equal_Case_Insensitive (Left_Id, Right_Id) + if not Strings.Equal_Case_Insensitive + (Left_Id, Right_Id) then - return Less_Case_Insensitive (Left_Id, Right_Id); + return Strings.Less_Case_Insensitive + (Left_Id, Right_Id); end if; end; end loop; @@ -178,7 +178,7 @@ package body Instrument is and then Length (Left.Unit) = Length (Right.Unit) then for I in 1 .. Integer (Length (Left.Unit)) loop - if not Ada.Strings.Unbounded.Equal_Case_Insensitive + if not Strings.Equal_Case_Insensitive (Unbounded_String (Left.Unit.Element (I)), Unbounded_String (Right.Unit.Element (I))) then @@ -388,7 +388,7 @@ package body Instrument is Result : Unbounded_String; begin for Id of Name loop - if Length (Result) > 0 then + if Result /= "" then Append (Result, "_"); end if; Append (Result, To_Lower (To_String (Id))); @@ -414,8 +414,7 @@ package body Instrument is ----------------------------- function CU_Name_For_File - (Filename : US.Unbounded_String) return Compilation_Unit_Part - is + (Filename : Unbounded_String) return Compilation_Unit_Part is begin return (File_Based_Language, Filename); end CU_Name_For_File; @@ -534,17 +533,17 @@ package body Instrument is begin -- Pass the right body / spec suffixes - if Desc.Body_Suffix (Lang) /= Null_Unbounded_String then + if Desc.Body_Suffix (Lang) /= "" then Result.Append (+"--body-suffix"); Result.Append (Desc.Body_Suffix (Lang)); end if; - if Desc.Spec_Suffix (Lang) /= Null_Unbounded_String then + if Desc.Spec_Suffix (Lang) /= "" then Result.Append (+"--spec-suffix"); Result.Append (Desc.Spec_Suffix (Lang)); end if; - if Desc.Dot_Replacement /= Null_Unbounded_String then + if Desc.Dot_Replacement /= "" then Result.Append (+"--dot-replacement"); Result.Append (Desc.Dot_Replacement); end if; @@ -580,7 +579,7 @@ package body Instrument is Result.Append (Compiler_Opts_Str); end; - if Desc.Compiler_Driver (Lang) /= Null_Unbounded_String then + if Desc.Compiler_Driver (Lang) /= "" then Result.Append (+"--compiler-driver"); Result.Append (Desc.Compiler_Driver (Lang)); end if; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 19c3c8bfa..c36e2934d 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -20,7 +20,6 @@ with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with GNATCOLL.Projects; use GNATCOLL.Projects; @@ -35,11 +34,10 @@ with Switches; use Switches; package Instrument is - package US renames Ada.Strings.Unbounded; - package GPR renames GNATCOLL.Projects; use type Ada.Containers.Count_Type; + use all type Unbounded_String; Parallelism_Level : Natural := 1; @@ -48,7 +46,7 @@ package Instrument is -- Returns the language kind (unit-based or file-based) for the given -- language. - type Ada_Identifier is new Ada.Strings.Unbounded.Unbounded_String; + type Ada_Identifier is new Unbounded_String; -- Simple Ada identifier procedure Read @@ -97,7 +95,7 @@ package Instrument is -- Identifies an Ada compilation unit (unit-based) when File_Based_Language => - Filename : US.Unbounded_String; + Filename : Unbounded_String; -- Fallback for file-based languages (like C). We use the full -- filename, for homonym resiliency. @@ -177,7 +175,7 @@ package Instrument is -- corresponding to the unit name and the unit part parameters. function CU_Name_For_File - (Filename : US.Unbounded_String) return Compilation_Unit_Part; + (Filename : Unbounded_String) return Compilation_Unit_Part; -- Return the compilation unit name for the C translation unit -- corresponding to the filename parameter. diff --git a/tools/gnatcov/json.adb b/tools/gnatcov/json.adb index 58bfeddf5..07ea07eee 100644 --- a/tools/gnatcov/json.adb +++ b/tools/gnatcov/json.adb @@ -16,14 +16,13 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; - pragma Warnings (Off, "* is an internal GNAT unit"); with Ada.Strings.Unbounded.Aux; pragma Warnings (On, "* is an internal GNAT unit"); with GNAT.Strings; use GNAT.Strings; +with Strings; use Strings; with Text_Files; package body JSON is @@ -38,8 +37,8 @@ package body JSON is File : Text_Files.File_Type; Content : constant Unbounded_String := Value.Write (Compact => Compact); - Buffer : Aux.Big_String_Access; - First : constant Natural := Aux.Big_String'First; + Buffer : US.Aux.Big_String_Access; + First : constant Natural := US.Aux.Big_String'First; Last : Natural; begin File.Create (Filename); @@ -49,7 +48,7 @@ package body JSON is -- copying the whole string. This is not just for performance: using -- To_String could for instance make GNAT's secondary stack overflow. - Aux.Get_String (Content, Buffer, Last); + US.Aux.Get_String (Content, Buffer, Last); File.Put (Buffer (First .. Last)); end Write; @@ -63,7 +62,7 @@ package body JSON is end Read; function Read (File : Virtual_File) return Read_Result is - Content : GNAT.Strings.String_Access := File.Read_File; + Content : String_Access := File.Read_File; begin return Parsed_JSON : constant Read_Result := GNATCOLL.JSON.Read (Content.all) diff --git a/tools/gnatcov/outputs.adb b/tools/gnatcov/outputs.adb index f6de07687..b8093ec66 100644 --- a/tools/gnatcov/outputs.adb +++ b/tools/gnatcov/outputs.adb @@ -20,7 +20,6 @@ with Ada.Characters.Handling; with Ada.Command_Line; use Ada.Command_Line; with Ada.Directories; with Ada.Environment_Variables; use Ada.Environment_Variables; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with GNAT.Exception_Actions; with GNAT.OS_Lib; use GNAT.OS_Lib; @@ -32,7 +31,7 @@ with Version; package body Outputs is - Report_Output_Dir : GNAT.OS_Lib.String_Access := null; + Report_Output_Dir : String_Access := null; -- Name of the output directory. The reports will be generated -- in this directory. @@ -130,7 +129,7 @@ package body Outputs is declare Name : constant String := Simple_Name (Dir_Entry); Full_Name : constant Unbounded_String := - To_Unbounded_String (Dir / Name); + +(Dir / Name); begin if not Ignored_Files.Contains (Full_Name) then To_Delete.Append (Full_Name); @@ -142,7 +141,7 @@ package body Outputs is -- Do the deletion for Name of To_Delete loop - Delete_File (To_String (Name)); + Delete_File (+Name); end loop; end Clean_Dir; @@ -220,7 +219,7 @@ package body Outputs is -- Properly fill it and put it on the current contexts stack - Set_Unbounded_String (Ctx.Info, Message); + Ctx.Info := +Message; Ctx.Next := Current_Context; Current_Context := Ctx; diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index 3f11fb2c5..073ba4720 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -17,13 +17,16 @@ ------------------------------------------------------------------------------ with Ada.Characters.Handling; -with Ada.Strings.Unbounded; with GNAT.OS_Lib; with GNAT.Regpat; +with Strings; use Strings; + package body Paths is + use all type Unbounded_String; + On_Windows : constant Boolean := GNAT.OS_Lib.Directory_Separator = '\'; function Likely_Windows_Path (Path : String) return Boolean; @@ -107,7 +110,6 @@ package body Paths is -------------------- function Glob_To_Regexp (Pattern : String) return String is - use Ada.Strings.Unbounded; use GNAT.Regpat; Pat : constant String := @@ -185,8 +187,7 @@ package body Paths is -- De-duplicate directory separators so that "a//b" can match -- "a/b". - if Length (Res) = 0 or else Element (Res, Length (Res)) /= '/' - then + if Res = "" or else Element (Res, Length (Res)) /= '/' then Append (Res, '/'); end if; @@ -195,7 +196,7 @@ package body Paths is end case; I := I + 1; end loop; - return To_String (Res); + return +Res; end Glob_To_Regexp; -------------------------- @@ -280,7 +281,6 @@ package body Paths is -- -- At least for dirsep purposes, we craft the new value incrementally. - use Ada.Strings.Unbounded; use Ada.Characters.Handling; Res : Unbounded_String; @@ -303,7 +303,7 @@ package body Paths is end if; end loop; - return To_String (Res); + return +Res; end Normalize_Windows_Pattern; ------------------------------- diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index e21c2e759..1ae587c53 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -19,8 +19,7 @@ with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Containers.Indefinite_Ordered_Sets; with Ada.Containers.Vectors; -with Ada.Directories; use Ada.Directories; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Directories; use Ada.Directories; with Ada.Tags; with GNAT.OS_Lib; @@ -38,6 +37,8 @@ with Paths; use Paths; package body Project is + use type Unbounded_String; + subtype Compilation_Unit is Files_Table.Compilation_Unit; use type Compilation_Unit; @@ -334,7 +335,7 @@ package body Project is end if; Warn ("no " & What_Info & " file found for unit " - & To_String (Unit.Original_Name)); + & (+Unit.Original_Name)); Unit.Warned_About_Missing_Info := True; end Warn_Missing_Info; @@ -1265,8 +1266,8 @@ package body Project is Initialize (Target, Runtime, CGPR_File); pragma Assert (Env /= null); - if Obj_Subdir /= Null_Unbounded_String then - Env.Set_Object_Subdir (+To_String (Obj_Subdir)); + if Obj_Subdir /= "" then + Env.Set_Object_Subdir (+(+Obj_Subdir)); end if; if Build_Tree_Dir /= No_File then @@ -1295,8 +1296,8 @@ package body Project is Fatal_Error ("Could not load the project file, aborting."); end; - if Obj_Subdir /= Null_Unbounded_String then - Env.Set_Object_Subdir (+To_String (Obj_Subdir)); + if Obj_Subdir /= "" then + Env.Set_Object_Subdir (+(+Obj_Subdir)); end if; -- If we were asked only to load the project file, stop there (i.e. @@ -1478,7 +1479,7 @@ package body Project is procedure Set_Subdirs (Subdir : String) is begin - Obj_Subdir := To_Unbounded_String (Subdir); + Obj_Subdir := +Subdir; -- The --subdirs switch is relevant only if projects are used, otherwise -- it can safely be ignored. If projects are not loaded yet, the diff --git a/tools/gnatcov/rundrv-config.adb b/tools/gnatcov/rundrv-config.adb index b434e3be2..f4bf26f57 100644 --- a/tools/gnatcov/rundrv-config.adb +++ b/tools/gnatcov/rundrv-config.adb @@ -16,8 +16,6 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; - with GNAT.Regpat; use GNAT.Regpat; with Rundrv.Handlers; use Rundrv.Handlers; @@ -25,6 +23,8 @@ with Strings; use Strings; package body Rundrv.Config is + use all type Unbounded_String; + procedure Get_Builtin_Driver (Context : Context_Type; Found : out Boolean; @@ -57,7 +57,7 @@ package body Rundrv.Config is -- arguments list. type Builtin_Target_Type is record - Pattern : Ada.Strings.Unbounded.Unbounded_String; + Pattern : Unbounded_String; -- Pattern used to match a target family string Driver_Creator : Driver_Creator_Type; @@ -139,8 +139,7 @@ package body Rundrv.Config is -- Available_Targets -- ----------------------- - function Available_Targets return String - is + function Available_Targets return String is Result : Unbounded_String; First : Boolean := True; begin @@ -150,9 +149,9 @@ package body Rundrv.Config is end if; First := False; - Append (Result, +T.Pattern); + Append (Result, T.Pattern); end loop; - return To_String (Result); + return +Result; end Available_Targets; end Rundrv.Config; diff --git a/tools/gnatcov/rundrv.adb b/tools/gnatcov/rundrv.adb index b923a1d1f..7c74c3241 100644 --- a/tools/gnatcov/rundrv.adb +++ b/tools/gnatcov/rundrv.adb @@ -18,7 +18,6 @@ with Ada.Directories; use Ada.Directories; with Ada.Environment_Variables; -with Ada.Strings.Unbounded; with Ada.Unchecked_Conversion; with Interfaces; @@ -29,15 +28,17 @@ with Binary_Files; with Execs_Dbase; with Outputs; with Qemu_Traces; -with Subprocesses; use Subprocesses; with Rundrv.Config; use Rundrv.Config; +with Strings; use Strings; +with Subprocesses; use Subprocesses; with Traces_Elf; with Traces_Files; use Traces_Files; package body Rundrv is + use all type Unbounded_String; + package Env renames Ada.Environment_Variables; - package US renames Ada.Strings.Unbounded; Native_Warning : constant String := "Support for coverage of non-instrumented native programs is deprecated" @@ -172,7 +173,7 @@ package body Rundrv is -- command to run, as we just need to create the trace file header: do -- not call Run_Command in this case. - if US.Length (Run_Cmd.Command) > 0 then + if Run_Cmd.Command /= "" then Dummy := Run_Command (Run_Cmd, "gnatcov run", Ignore_Error => True); end if; end Driver; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 3e89b5f8a..49fff7540 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -770,7 +770,7 @@ package body SC_Obligations is begin return "Scope for " - & Ada.Strings.Unbounded.To_String (SE.Name) + & (+SE.Name) & "[" & Slocs.Image (SE.Sloc) & "], identifier " & Identifier_Image; end Image; @@ -1709,7 +1709,7 @@ package body SC_Obligations is function CU_Image return String is (Get_Simple_Name (CP_CU.Origin) - & " (from " & To_String (CLS.Filename) & ")"); + & " (from " & (+CLS.Filename) & ")"); -- Helper to refer to the compilation unit in an error message begin @@ -1999,9 +1999,9 @@ package body SC_Obligations is ("gnatcov limitation: ignoring unit " & Get_Simple_Name (Remap_SFI (Relocs, CP_CU.Main_Source)) - & " from " & To_String (CLS.Filename) + & " from " & (+CLS.Filename) & " because " - & To_String (Get_Simple_Name (Relocs, CP_CU.Origin)) + & (+Get_Simple_Name (Relocs, CP_CU.Origin)) & " is ignored"); end if; @@ -2282,14 +2282,14 @@ package body SC_Obligations is begin case Kind (Op_SCO) is when Condition => - return To_Unbounded_String ('C' & Img (Integer (Index (Op_SCO)))); + return +('C' & Img (Integer (Index (Op_SCO)))); when Decision => return Expression_Image (SCO_Vector.Reference (Op_SCO).Expression); when Operator => declare - Result : Unbounded_String := To_Unbounded_String ("("); + Result : Unbounded_String := +"("; Binary : constant Boolean := Op_Kind (Op_SCO) /= Op_Not; begin for J in Operand_Position'Range loop @@ -2314,13 +2314,14 @@ package body SC_Obligations is end; end loop; - return Result & ')'; + Append (Result, ')'); + return Result; end; when others => - return To_Unbounded_String - ("Expected expression SCO kind (Decision, Condition or Operator)" - & ", but got " & SCO_Kind'Image (Kind (Op_SCO))); + return + +("Expected expression SCO kind (Decision, Condition or" + & " Operator), but got " & SCO_Kind'Image (Kind (Op_SCO))); end case; end Expression_Image; @@ -2331,7 +2332,7 @@ package body SC_Obligations is procedure Dump_Decision (SCO : SCO_Id) is begin Put_Line ("Reconstructed expression for " & Image (SCO)); - Put_Line (To_String (Expression_Image (SCO))); + Put_Line (+Expression_Image (SCO)); end Dump_Decision; --------------- @@ -3455,7 +3456,7 @@ package body SC_Obligations is ("Computing fingerprint for " & Unit_Info.File_Name_Ptr.all & " SCOs from:"); SCOs_Trace.Trace ("BEGIN ..."); - SCOs_Trace.Trace (To_String (Unit_Info.Fingerprint_Buffer)); + SCOs_Trace.Trace (+Unit_Info.Fingerprint_Buffer); SCOs_Trace.Trace ("... END"); end loop; end if; diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 97bff1754..1a3ff3bfa 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -25,7 +25,6 @@ with Ada.Containers.Ordered_Maps; with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; with Ada.Containers.Multiway_Trees; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with GNAT.Regexp; with GNAT.SHA1; @@ -48,6 +47,8 @@ package SC_Obligations is pragma Suppress (Tampering_Check); + use all type Unbounded_String; + SCOs_Trace : constant Logging.GNATCOLL_Trace := Logging.Create_Trace ("SCOS"); diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index e40902541..0341e15e0 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -449,7 +449,7 @@ package body Setup_RTS is Actual_RTS := (if Prj.Has_Runtime_Project - then To_Unbounded_String (String (Prj.Runtime (Main_Language))) + then +String (Prj.Runtime (Main_Language)) else Null_Unbounded_String); -- Show the actual names for the target and the runtime that GPR2 uses. @@ -457,7 +457,7 @@ package body Setup_RTS is Setup_RTS_Trace.Trace ("Actual target: " & String (Prj.Target (Canonical => True))); - Setup_RTS_Trace.Trace ("Actual RTS: " & To_String (Actual_RTS)); + Setup_RTS_Trace.Trace ("Actual RTS: " & (+Actual_RTS)); -- The best heuristic we have to determine if the actual runtime is -- "full" is to look for an Ada source file that is typically found in @@ -585,7 +585,7 @@ package body Setup_RTS is -- is installed (without the ".gpr" extension). Args.Append (+To_Lower (Project_Name)); - Args.Append (+"--sources-subdir=" & ("include" / "gnatcov_rts")); + Args.Append (+("--sources-subdir=" & ("include" / "gnatcov_rts"))); -- The project may not have been installed there yet, so ignore errors @@ -647,8 +647,7 @@ package body Setup_RTS is then Dir else Dir & GNAT.OS_Lib.Path_Separator & Path); begin - Env.Insert - (To_Unbounded_String (Var_Name), To_Unbounded_String (New_Path)); + Env.Insert (+Var_Name, +New_Path); end; -- Now run gprbuild and gprinstall @@ -736,8 +735,7 @@ package body Setup_RTS is Dump_Config : constant Any_Dump_Config := Load_Dump_Config - (Default_Dump_Config - (Actual_RTS_Profile, To_String (Actual_RTS))); + (Default_Dump_Config (Actual_RTS_Profile, +Actual_RTS)); begin -- Try to uninstall a previous installation of the instrumentation -- runtime in the requested prefix. This is to avoid installation @@ -796,7 +794,7 @@ package body Setup_RTS is -- Avoid installing several time the same set of sources Install_Args.Append - (+"--sources-subdir=" & ("include" / Install_Name)); + (+("--sources-subdir=" & ("include" / Install_Name))); -- Let the project know about its installation name @@ -952,7 +950,7 @@ package body Setup_RTS is if Parsed_JSON.Success then if Parsed_JSON.Value.Kind = JSON_Object_Type then return Result : Setup_Config := Load (Parsed_JSON.Value) do - Result.Project_File := To_Unbounded_String (Project_File); + Result.Project_File := +Project_File; end return; end if; @@ -1020,7 +1018,7 @@ package body Setup_RTS is begin declare - RTS_Profile : constant String := To_String (Get ("rts-profile")); + RTS_Profile : constant String := +Get ("rts-profile"); begin Result.RTS_Profile := Value (RTS_Profile); Result.RTS_Profile_Present := True; @@ -1030,14 +1028,14 @@ package body Setup_RTS is end; begin - Channel := Value (To_String (Get ("dump-channel"))); + Channel := Value (+Get ("dump-channel")); exception when Constraint_Error => raise Format_Error with "invalid dump-channel field"; end; begin - Trigger := Value (To_String (Get ("dump-trigger"))); + Trigger := Value (+Get ("dump-trigger")); exception when Constraint_Error => raise Format_Error with "invalid dump-trigger field"; diff --git a/tools/gnatcov/setup_rts.ads b/tools/gnatcov/setup_rts.ads index 327b79542..4f6d61cef 100644 --- a/tools/gnatcov/setup_rts.ads +++ b/tools/gnatcov/setup_rts.ads @@ -18,8 +18,6 @@ -- This package implements the "setup" gnatcov command. -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; - with Logging; with Strings; use Strings; with Switches; use Switches; diff --git a/tools/gnatcov/strings.adb b/tools/gnatcov/strings.adb index 6a45c47da..047d1dc69 100644 --- a/tools/gnatcov/strings.adb +++ b/tools/gnatcov/strings.adb @@ -103,8 +103,8 @@ package body Strings is is procedure Read is new Read_Vector (Index_Type => Natural, - Element_Type => Ada.Strings.Unbounded.Unbounded_String, - "=" => Ada.Strings.Unbounded."=", + Element_Type => Unbounded_String, + "=" => "=", Vectors => String_Vectors, Read_Element => Read); begin @@ -116,8 +116,8 @@ package body Strings is Value : out String_Maps.Map) is procedure Read is new Read_Map - (Key_Type => Ada.Strings.Unbounded.Unbounded_String, - Element_Type => Ada.Strings.Unbounded.Unbounded_String, + (Key_Type => Unbounded_String, + Element_Type => Unbounded_String, Map_Type => String_Maps.Map, Clear => String_Maps.Clear, Insert => String_Maps.Insert, @@ -137,8 +137,8 @@ package body Strings is is procedure Write is new Write_Vector (Index_Type => Natural, - Element_Type => Ada.Strings.Unbounded.Unbounded_String, - "=" => Ada.Strings.Unbounded."=", + Element_Type => Unbounded_String, + "=" => "=", Vectors => String_Vectors, Write_Element => Write); begin @@ -149,8 +149,8 @@ package body Strings is (CSS : in out Checkpoints.Checkpoint_Save_State; Value : String_Maps.Map) is procedure Write is new Write_Map - (Key_Type => Ada.Strings.Unbounded.Unbounded_String, - Element_Type => Ada.Strings.Unbounded.Unbounded_String, + (Key_Type => Unbounded_String, + Element_Type => Unbounded_String, Map_Type => String_Maps.Map, Cursor_Type => String_Maps.Cursor, Length => String_Maps.Length, @@ -205,7 +205,6 @@ package body Strings is Last : out Ada.Streams.Stream_Element_Offset) is use Ada.Streams; - use Ada.Strings.Unbounded; Last_Index : constant Natural := Natural'Min (Length (Stream.S.all), @@ -231,8 +230,6 @@ package body Strings is (Stream : in out Unbounded_String_Stream; Item : Ada.Streams.Stream_Element_Array) is - use Ada.Strings.Unbounded; - Item_S : String (1 .. Item'Length); for Item_S'Address use Item'Address; pragma Import (Ada, Item_S); @@ -250,7 +247,6 @@ package body Strings is Patterns_Not_Covered : in out String_Sets.Set) is use Ada.Characters.Handling; - use Ada.Strings.Unbounded; use String_Vectors; Pattern_Length : constant Natural := Natural (Patterns_List.Length); diff --git a/tools/gnatcov/strings.ads b/tools/gnatcov/strings.ads index 1ec365475..9b322479d 100644 --- a/tools/gnatcov/strings.ads +++ b/tools/gnatcov/strings.ads @@ -33,6 +33,19 @@ limited with Checkpoints; package Strings is + package US renames Ada.Strings.Unbounded; + subtype Unbounded_String is US.Unbounded_String; + use all type Unbounded_String; + Null_Unbounded_String : Unbounded_String renames US.Null_Unbounded_String; + function Hash (S : Unbounded_String) return Ada.Containers.Hash_Type + renames US.Hash; + function Equal_Case_Insensitive + (Left, Right : Unbounded_String) return Boolean + renames US.Equal_Case_Insensitive; + function Less_Case_Insensitive + (Left, Right : Unbounded_String) return Boolean + renames US.Less_Case_Insensitive; + function Hash (El : String_Access) return Ada.Containers.Hash_Type; -- Compute a hash from El.all @@ -54,20 +67,15 @@ package Strings is function Has_Suffix (S : String; Suffix : String) return Boolean; -- True if S ends with Suffix - function "+" - (S : String) - return Ada.Strings.Unbounded.Unbounded_String - renames Ada.Strings.Unbounded.To_Unbounded_String; + function "+" (S : String) return Unbounded_String + renames To_Unbounded_String; - function "+" - (S : Ada.Strings.Unbounded.Unbounded_String) - return String - renames Ada.Strings.Unbounded.To_String; + function "+" (S : Unbounded_String) return String renames To_String; package String_Vectors is new Ada.Containers.Vectors (Index_Type => Natural, - Element_Type => Ada.Strings.Unbounded.Unbounded_String, - "=" => Ada.Strings.Unbounded."="); + Element_Type => Unbounded_String, + "=" => "="); procedure Read (CLS : in out Checkpoints.Checkpoint_Load_State; @@ -80,10 +88,10 @@ package Strings is -- Write a String_Vectors.Vector to CSS package String_Maps is new Ada.Containers.Ordered_Maps - (Key_Type => Ada.Strings.Unbounded.Unbounded_String, - Element_Type => Ada.Strings.Unbounded.Unbounded_String, - "<" => Ada.Strings.Unbounded."<", - "=" => Ada.Strings.Unbounded."="); + (Key_Type => Unbounded_String, + Element_Type => Unbounded_String, + "<" => "<", + "=" => "="); procedure Read (CLS : in out Checkpoints.Checkpoint_Load_State; @@ -95,16 +103,16 @@ package Strings is -- Write a String_Maps.Map to CSS package String_Sets is new Ada.Containers.Ordered_Sets - (Element_Type => Ada.Strings.Unbounded.Unbounded_String, - "<" => Ada.Strings.Unbounded.Less_Case_Insensitive, - "=" => Ada.Strings.Unbounded.Equal_Case_Insensitive); + (Element_Type => Unbounded_String, + "<" => Less_Case_Insensitive, + "=" => Equal_Case_Insensitive); -- Case insensitive string set package String_Vectors_Maps is new Ada.Containers.Hashed_Maps - (Key_Type => Ada.Strings.Unbounded.Unbounded_String, + (Key_Type => Unbounded_String, Element_Type => String_Vectors.Vector, - Equivalent_Keys => Ada.Strings.Unbounded."=", - Hash => Ada.Strings.Unbounded.Hash, + Equivalent_Keys => "=", + Hash => Hash, "=" => String_Vectors."="); function To_String_Set (V : String_Vectors.Vector) return String_Sets.Set; @@ -125,8 +133,7 @@ package Strings is -- from Strings_List. Also, each pattern that matched at least once is -- removed from Patterns_Not_Covered. - type Unbounded_String_Stream - (S : access Ada.Strings.Unbounded.Unbounded_String) + type Unbounded_String_Stream (S : access Unbounded_String) is new Ada.Streams.Root_Stream_Type with record Read_Index : Positive := 1; end record; diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 8b2925d6f..4fdda92ad 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -16,7 +16,6 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Strings; with Ada.Text_IO; use Ada.Text_IO; with GNAT.OS_Lib; @@ -60,7 +59,6 @@ package body Subprocesses is function "=" (L, R : Command_Type) return Boolean is - use Ada.Strings.Unbounded; use String_Vectors; begin return L.Command = R.Command @@ -285,7 +283,6 @@ package body Subprocesses is -- Instantiate the argument list declare - use Ada.Strings.Unbounded; Log : Unbounded_String; begin Process_Types.Add_Argument (Args, Program.all); diff --git a/tools/gnatcov/subprocesses.ads b/tools/gnatcov/subprocesses.ads index ae91ccaf4..1e9da6c36 100644 --- a/tools/gnatcov/subprocesses.ads +++ b/tools/gnatcov/subprocesses.ads @@ -23,7 +23,6 @@ -- abort gnatcov in case of subprocess failure. with Ada.Finalization; -with Ada.Strings.Unbounded; with GNATCOLL.OS.Process; use GNATCOLL.OS.Process; @@ -34,11 +33,13 @@ with Temp_Dirs; use Temp_Dirs; package Subprocesses is + use all type Unbounded_String; + Subprocesses_Trace : constant Logging.GNATCOLL_Trace := Logging.Create_Trace ("SUBPROCESSES"); type Command_Type is record - Command : Ada.Strings.Unbounded.Unbounded_String; + Command : Unbounded_String; -- Command (executable file) to run Arguments : String_Vectors.Vector; @@ -169,8 +170,8 @@ package Subprocesses is private type Process_Info is record - Command, Origin_Command_Name : Ada.Strings.Unbounded.Unbounded_String; - Output_File : Ada.Strings.Unbounded.Unbounded_String; + Command, Origin_Command_Name : Unbounded_String; + Output_File : Unbounded_String; Ignore_Error : Boolean; -- Information specific to a subprocess, filled when calling the -- Run_Command overload running a subprocess in a process pool. See the diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index f644a0d17..93fe284b7 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -26,6 +26,7 @@ with Project; use Project; package body Switches is + use type Unbounded_String; use Command_Line.Parser; function Command_Line_Args return String_List_Access; @@ -113,8 +114,8 @@ package body Switches is Dump_Channel : Any_Dump_Channel; Dump_Trigger : Any_Dump_Trigger; Dump_Filename_Simple : Boolean := False; - Dump_Filename_Env_Var : Ada.Strings.Unbounded.Unbounded_String; - Dump_Filename_Prefix : Ada.Strings.Unbounded.Unbounded_String; + Dump_Filename_Env_Var : Unbounded_String; + Dump_Filename_Prefix : Unbounded_String; begin -- First, load the config from Default_Dump_Config, then override it -- using command-line arguments. @@ -193,7 +194,6 @@ package body Switches is function Unparse_Config (Dump_Config : Any_Dump_Config) return String_Vectors.Vector is - use Ada.Strings.Unbounded; Result : String_Vectors.Vector; begin Result.Append (+"--dump-trigger"); @@ -213,11 +213,11 @@ package body Switches is if Dump_Config.Filename_Simple then Result.Append (+"--dump-filename-simple"); end if; - if Length (Dump_Config.Filename_Env_Var) /= 0 then + if Dump_Config.Filename_Env_Var /= "" then Result.Append ("--dump-filename-env-var=" & Dump_Config.Filename_Env_Var); end if; - if Length (Dump_Config.Filename_Prefix) /= 0 then + if Dump_Config.Filename_Prefix /= "" then Result.Append (+"--dump-filename-prefix=" & Dump_Config.Filename_Prefix); end if; diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index d4d24a29f..240a41966 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -17,7 +17,6 @@ ------------------------------------------------------------------------------ with Ada.Containers.Indefinite_Ordered_Maps; -with Ada.Strings.Unbounded; with GNAT.Strings; use GNAT.Strings; @@ -261,7 +260,7 @@ package Switches is -- -- Controlled by --dump-filename-simple. - Filename_Env_Var : Ada.Strings.Unbounded.Unbounded_String; + Filename_Env_Var : Unbounded_String; -- Name of the environment variable which, if set, contains the -- default filename for created source traces. If empty, use the -- default one (see Default_Trace_Filename_Env_Var in @@ -269,7 +268,7 @@ package Switches is -- -- Controlled by --dump-filename-env-var. - Filename_Prefix : Ada.Strings.Unbounded.Unbounded_String; + Filename_Prefix : Unbounded_String; -- Prefix for the source trace filename. If empty, use the -- program's basename (see Default_Trace_Filename_Prefix in -- GNATcov_RTS.Traces.Output.Files). diff --git a/tools/gnatcov/temp_dirs.adb b/tools/gnatcov/temp_dirs.adb index a93509bfc..1f2ff0361 100644 --- a/tools/gnatcov/temp_dirs.adb +++ b/tools/gnatcov/temp_dirs.adb @@ -52,7 +52,7 @@ package body Temp_Dirs is -- remove it. Create_Directory (Name); - Self.Name := To_Unbounded_String (Name); + Self.Name := +Name; Self.Auto_Delete := Auto_Delete; end Create_Temporary_Directory; @@ -62,7 +62,7 @@ package body Temp_Dirs is function Directory_Name (Self : Temporary_Directory) return String is begin - return To_String (Self.Name); + return +Self.Name; end Directory_Name; -------------- @@ -71,8 +71,8 @@ package body Temp_Dirs is overriding procedure Finalize (Self : in out Temporary_Directory) is begin - if Self.Name /= Null_Unbounded_String and then Self.Auto_Delete then - Delete_Tree (To_String (Self.Name)); + if Self.Name /= "" and then Self.Auto_Delete then + Delete_Tree (+Self.Name); Self.Name := Null_Unbounded_String; end if; end Finalize; diff --git a/tools/gnatcov/temp_dirs.ads b/tools/gnatcov/temp_dirs.ads index 17587c092..fb93eb1f6 100644 --- a/tools/gnatcov/temp_dirs.ads +++ b/tools/gnatcov/temp_dirs.ads @@ -24,7 +24,8 @@ -- directory. private with Ada.Finalization; -private with Ada.Strings.Unbounded; + +private with Strings; package Temp_Dirs is @@ -44,7 +45,8 @@ package Temp_Dirs is private - use Ada.Strings.Unbounded; + use Strings; + use type Unbounded_String; type Temporary_Directory is new Ada.Finalization.Limited_Controlled with record diff --git a/tools/gnatcov/text_files.adb b/tools/gnatcov/text_files.adb index 0f7f238a9..f506c9dd5 100644 --- a/tools/gnatcov/text_files.adb +++ b/tools/gnatcov/text_files.adb @@ -51,7 +51,7 @@ package body Text_Files is return Boolean is begin Open (Self.File, Mode, Name); - Self.Filename := US.To_Unbounded_String (Name); + Self.Filename := +Name; return True; exception when Use_Error | Name_Error => @@ -69,7 +69,7 @@ package body Text_Files is return Boolean is begin Create (Self.File, Mode, Name); - Self.Filename := US.To_Unbounded_String (Name); + Self.Filename := +Name; return True; exception when Use_Error | Name_Error => diff --git a/tools/gnatcov/text_files.ads b/tools/gnatcov/text_files.ads index f06b1393a..2a45b687f 100644 --- a/tools/gnatcov/text_files.ads +++ b/tools/gnatcov/text_files.ads @@ -19,9 +19,10 @@ -- Convenience wrapper around Ada.Text_IO. private with Ada.Finalization; -private with Ada.Strings.Unbounded; with Ada.Text_IO; +private with Strings; + package Text_Files is subtype File_Mode is Ada.Text_IO.File_Mode; @@ -105,11 +106,11 @@ package Text_Files is private use Ada.Text_IO; - package US renames Ada.Strings.Unbounded; + use Strings; type File_Type is new Ada.Finalization.Limited_Controlled with record File : Ada.Text_IO.File_Type; - Filename : US.Unbounded_String; + Filename : Unbounded_String; end record; overriding procedure Finalize (Self : in out File_Type); diff --git a/tools/gnatcov/traces_files.adb b/tools/gnatcov/traces_files.adb index 29aec6ea9..3b3009d11 100644 --- a/tools/gnatcov/traces_files.adb +++ b/tools/gnatcov/traces_files.adb @@ -288,8 +288,7 @@ package body Traces_Files is is begin if not Result.Success then - Fatal_Error - (Filename & ": " & US.To_String (Result.Error)); + Fatal_Error (Filename & ": " & (+Result.Error)); end if; end Success_Or_Fatal_Error; @@ -568,7 +567,7 @@ package body Traces_Files is begin return Desc : Trace_File_Descriptor (Writeable => Mode /= Read_File) do - Desc.Filename := US.To_Unbounded_String (Filename); + Desc.Filename := +Filename; case Mode is when Read_File => Log_File_Open (Filename); @@ -926,7 +925,7 @@ package body Traces_Files is Raw_Entry : Trace_Entry_IO.Ref; begin Open_Trace_File (Filename, Desc, Trace_File); - Trace_File.Filename := US.To_Unbounded_String (Filename); + Trace_File.Filename := +Filename; Process_Info_Entries (Trace_File, Result); if not Result.Success then return; @@ -1179,7 +1178,7 @@ package body Traces_Files is Mmap.Free (Desc.Region); Mmap.Close (Desc.File); end if; - Desc.Filename := US.Null_Unbounded_String; + Desc.Filename := Null_Unbounded_String; end Close_Trace_File; -------------------------------- @@ -1325,7 +1324,6 @@ package body Traces_Files is --------------------- procedure Dump_Trace_File (Filename : String; Raw : Boolean) is - use Ada.Strings.Unbounded; procedure Process_Info_Entries (Trace_File : Trace_File_Type; @@ -1399,7 +1397,7 @@ package body Traces_Files is begin Put_Line ("Loading shared object " & Filename); Put_Line (" at " & Hex_Image (First) & " .. " & Hex_Image (Last)); - return To_Unbounded_String (Filename); + return +Filename; end Load_Shared_Object; ------------------------- @@ -1760,7 +1758,7 @@ package body Traces_Files is is begin Trace_File := Trace_File_Type' - (Filename => US.To_Unbounded_String (Filename), + (Filename => +Filename, Header => (Kind, Pc_Type_Size, Big_Endian_Host, 0), First_Infos => null, Last_Infos => null); @@ -1772,8 +1770,7 @@ package body Traces_Files is procedure Create_Error (Result : out Read_Result; Error : String) is begin - Result := (Success => False, - Error => Ada.Strings.Unbounded.To_Unbounded_String (Error)); + Result := (Success => False, Error => +Error); end Create_Error; end Traces_Files; diff --git a/tools/gnatcov/traces_files.ads b/tools/gnatcov/traces_files.ads index ead350c6c..59d272b9a 100644 --- a/tools/gnatcov/traces_files.ads +++ b/tools/gnatcov/traces_files.ads @@ -16,7 +16,6 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Strings.Unbounded; with Interfaces; use Interfaces; private with System.Storage_Elements; @@ -26,6 +25,7 @@ with GNATCOLL.Mmap; with Binary_Files; use Binary_Files; with Qemu_Traces; use Qemu_Traces; +with Strings; use Strings; with Traces_Dbase; use Traces_Dbase; with Traces; @@ -34,7 +34,7 @@ package Traces_Files is type Read_Result (Success : Boolean := True) is record case Success is when False => - Error : Ada.Strings.Unbounded.Unbounded_String; + Error : Unbounded_String; when True => null; end case; @@ -257,7 +257,6 @@ package Traces_Files is private - package US renames Ada.Strings.Unbounded; package SSE renames System.Storage_Elements; package Mmap renames GNATCOLL.Mmap; @@ -285,7 +284,7 @@ private end record; type Trace_File_Type is record - Filename : US.Unbounded_String; + Filename : Unbounded_String; Header : Trace_File_Header; -- Linked list of infos @@ -295,7 +294,7 @@ private end record; type Trace_File_Descriptor (Writeable : Boolean := False) is record - Filename : US.Unbounded_String; + Filename : Unbounded_String; Header : Trace_File_Header; -- Use memory mapping to read trace files (for efficiency), and @@ -355,6 +354,6 @@ private (Trace_File.Header.Kind); function Filename (Trace_File : Trace_File_Type) return String is - (US.To_String (Trace_File.Filename)); + (+Trace_File.Filename); end Traces_Files; diff --git a/tools/gnatcov/traces_files_registry.adb b/tools/gnatcov/traces_files_registry.adb index 4a6f5d97b..e2d42eb47 100644 --- a/tools/gnatcov/traces_files_registry.adb +++ b/tools/gnatcov/traces_files_registry.adb @@ -20,7 +20,6 @@ with Ada.Calendar; with Ada.Calendar.Conversions; with Ada.Containers.Generic_Sort; with Ada.Containers.Hashed_Sets; -with Ada.Strings.Unbounded.Hash; with Interfaces.C; @@ -30,7 +29,7 @@ with Qemu_Traces; use Qemu_Traces; package body Traces_Files_Registry is - use Ada.Strings.Unbounded; + use type Unbounded_String; package Traces_Files_Sets is new Ada.Containers.Hashed_Sets (Element_Type => Trace_File_Element_Acc, @@ -112,12 +111,12 @@ package body Traces_Files_Registry is use type Ada.Containers.Hash_Type; begin return - Hash (Element.Filename) + Strings.Hash (Element.Filename) + Trace_File_Kind'Pos (Element.Kind) - + Hash (Element.Context) - + Hash (Element.Program_Name) - + Hash (Element.Time) - + Hash (Element.User_Data); + + Strings.Hash (Element.Context) + + Strings.Hash (Element.Program_Name) + + Strings.Hash (Element.Time) + + Strings.Hash (Element.User_Data); end Hash; ------------------------------- @@ -131,7 +130,7 @@ package body Traces_Files_Registry is begin return Result : constant Trace_File_Element_Acc := new Trace_File_Element do - Result.Filename := To_Unbounded_String (Filename); + Result.Filename := +Filename; Result.Kind := Kind; Result.Context := Null_Unbounded_String; end return; @@ -146,12 +145,9 @@ package body Traces_Files_Registry is File : Trace_File_Type) is begin - Element.Program_Name := To_Unbounded_String - (Get_Info (File, Exec_File_Name)); - Element.Time := To_Unbounded_String - (Format_Date_Info (Get_Info (File, Date_Time))); - Element.User_Data := To_Unbounded_String - (Get_Info (File, User_Data)); + Element.Program_Name := +Get_Info (File, Exec_File_Name); + Element.Time := +Format_Date_Info (Get_Info (File, Date_Time)); + Element.User_Data := +Get_Info (File, User_Data); end Update_From_Binary_Trace; ------------------------------ @@ -174,7 +170,7 @@ package body Traces_Files_Registry is raise Program_Error; when Info_Program_Name => - Element.Program_Name := To_Unbounded_String (Data); + Element.Program_Name := +Data; when Info_Exec_Date => declare @@ -196,8 +192,7 @@ package body Traces_Files_Registry is if Data'Length /= 8 then Outputs.Fatal_Error - (To_String (Element.Filename) - & "invalid execution date format"); + (+Element.Filename & "invalid execution date format"); end if; for I in reverse Data'Range loop Timestamp := 2 ** 8 * Timestamp + Character'Pos (Data (I)); @@ -237,13 +232,12 @@ package body Traces_Files_Registry is Info_Date.Hour := Unsigned_8 (Hour); Info_Date.Min := Unsigned_8 (Minute); Info_Date.Sec := Unsigned_8 (int'Min (Second, 59)); - Element.Time := To_Unbounded_String - (Format_Date_Info (Info_Date_As_String)); + Element.Time := +Format_Date_Info (Info_Date_As_String); end; end; when Info_User_Data => - Element.User_Data := To_Unbounded_String (Data); + Element.User_Data := +Data; end case; end Update_From_Source_Trace; @@ -328,8 +322,8 @@ package body Traces_Files_Registry is (CSS : access Checkpoints.Checkpoint_Save_State; Context : access Coverage.Context) is - This_Context : constant Unbounded_String := To_Unbounded_String - (Coverage.To_String (Context.all)); + This_Context : constant Unbounded_String := + +Coverage.To_String (Context.all); begin for TF of Files loop CSS.Write (TF.Filename); @@ -340,7 +334,7 @@ package body Traces_Files_Registry is -- actually been processed: record in in its infos. TF_Context : constant Unbounded_String := - (if Length (TF.Context) = 0 + (if TF.Context = "" then This_Context else TF.Context); begin @@ -378,7 +372,7 @@ package body Traces_Files_Registry is Name : constant Unbounded_String := CLS.Read_Unbounded_String; CP_File : Trace_File_Element_Acc; begin - exit when Length (Name) = 0; + exit when Name = ""; CP_File := new Trace_File_Element; CP_File.Filename := Name; CP_File.Kind := Trace_File_Kind'Val (CLS.Read_U8); diff --git a/tools/gnatcov/traces_files_registry.ads b/tools/gnatcov/traces_files_registry.ads index ee2d6f79d..85f306f8b 100644 --- a/tools/gnatcov/traces_files_registry.ads +++ b/tools/gnatcov/traces_files_registry.ads @@ -17,13 +17,12 @@ ------------------------------------------------------------------------------ with Ada.Containers.Vectors; -with Ada.Strings.Unbounded; with Ada.Unchecked_Deallocation; with Checkpoints; with Coverage; +with Strings; use Strings; with Traces_Files; use Traces_Files; - with Traces_Source; -- This package keeps track of all processed trace files @@ -31,26 +30,26 @@ with Traces_Source; package Traces_Files_Registry is type Trace_File_Element is limited record - Filename : Ada.Strings.Unbounded.Unbounded_String; + Filename : Unbounded_String; -- File name for the trace file, as passed to "gnatcov coverage" Kind : Trace_File_Kind; -- Kind of trace file this describes - Context : Ada.Strings.Unbounded.Unbounded_String; + Context : Unbounded_String; -- Empty string if this trace file was loaded by this instance of -- gnatcov. Otherwise, string to be decoded with Coverage.From_String, -- that describes the context where this trace file has actually been -- processed. - Program_Name : Ada.Strings.Unbounded.Unbounded_String; + Program_Name : Unbounded_String; -- Name of the program that was executed to produce this trace - Time : Ada.Strings.Unbounded.Unbounded_String; + Time : Unbounded_String; -- Production time for this trace file. The date format is the one -- returned by Traces_Files.Format_Date_Info. - User_Data : Ada.Strings.Unbounded.Unbounded_String; + User_Data : Unbounded_String; -- Custom user data attached to this trace file end record; diff --git a/tools/gnatcov/traces_stats.adb b/tools/gnatcov/traces_stats.adb index 0cb9a4411..6907f2b24 100644 --- a/tools/gnatcov/traces_stats.adb +++ b/tools/gnatcov/traces_stats.adb @@ -16,13 +16,14 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Strings.Fixed; use Ada.Strings.Fixed; -with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; +with Ada.Strings.Fixed; use Ada.Strings.Fixed; with Strings; use Strings; package body Traces_Stats is + use all type Unbounded_String; + --------------- -- Get_Total -- --------------- @@ -73,7 +74,7 @@ package body Traces_Stats is ATC => +"ATC", ATCC => +"ATCC", others => +""); - Res : Unbounded_String := +""; + Res : Unbounded_String := Null_Unbounded_String; function Trimmed_Image (N : Natural) return String is (Trim (Natural'Image (N), Ada.Strings.Left)); From 94341730c30e9c27f8bb3b663ec2775a6e4e8ab8 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 8 Dec 2023 13:32:48 +0000 Subject: [PATCH 0549/1483] Remove the Inputs.Inputs_Type type and associated primitives At this point, this type is just an awkward layer around a container, making iteration complicated. Just use a mere string vector instead, and use a dedicated container for the only use case that needs it (Trace_Inputs, responsible for the "qualifier" feature of Inputs.Inputs_Type). --- tools/gnatcov/cfg_dump.adb | 25 +- tools/gnatcov/cfg_dump.ads | 7 +- tools/gnatcov/gnatcov_bits_specific.adb | 626 ++++++++++-------------- tools/gnatcov/inputs.adb | 178 ------- tools/gnatcov/inputs.ads | 60 --- tools/gnatcov/instrument-c.adb | 8 +- tools/gnatcov/project.adb | 27 +- tools/gnatcov/project.ads | 4 +- tools/gnatcov/rundrv-config.adb | 3 - tools/gnatcov/rundrv-handlers.adb | 1 - tools/gnatcov/rundrv.adb | 3 - tools/gnatcov/rundrv.ads | 6 +- tools/gnatcov/switches.adb | 70 ++- tools/gnatcov/switches.ads | 34 +- tools/gnatcov/traces_files.ads | 12 + 15 files changed, 386 insertions(+), 678 deletions(-) diff --git a/tools/gnatcov/cfg_dump.adb b/tools/gnatcov/cfg_dump.adb index 1e9cf4ca6..ad8ad1f77 100644 --- a/tools/gnatcov/cfg_dump.adb +++ b/tools/gnatcov/cfg_dump.adb @@ -42,12 +42,10 @@ with Highlighting; with Outputs; use Outputs; with Qemu_Traces; with SC_Obligations; -with Strings; use Strings; with Support_Files; with Traces; use Traces; with Traces_Dbase; with Traces_Elf; use Traces_Elf; -with Traces_Files; package body CFG_Dump is @@ -266,7 +264,7 @@ package body CFG_Dump is procedure Tag_Executed_Instructions (Context : Context_Access; Exec_Path : String; - Traces_Files_List : Inputs.Inputs_Type); + Traces_Files_List : Requested_Trace_Vectors.Vector); -- Extract traces from each file and use them to tag instructions if they -- have been executed. This pass works on the CFG. @@ -799,11 +797,10 @@ package body CFG_Dump is procedure Tag_Executed_Instructions (Context : Context_Access; Exec_Path : String; - Traces_Files_List : Inputs.Inputs_Type) + Traces_Files_List : Requested_Trace_Vectors.Vector) is use type Interfaces.Unsigned_8; use Traces_Dbase; - use Traces_Files; Base : Traces_Base; @@ -984,7 +981,9 @@ package body CFG_Dump is -- Import all trace entries to the database, so that they are sorted by -- address - Inputs.Iterate (Traces_Files_List, Import_Traces'Access); + for RT of Traces_Files_List loop + Import_Traces (+RT.Filename); + end loop; -- And then, use them to tag instructions @@ -1726,20 +1725,18 @@ package body CFG_Dump is Locations : User_Locations; Output : String_Access; Format : Output_Format; - SCO_Files_List : Inputs.Inputs_Type; - Traces_Files_List : Inputs.Inputs_Type; + SCO_Files_List : String_Vectors.Vector; + Traces_Files_List : Requested_Trace_Vectors.Vector; Keep_Edges : Boolean) is - use Ada.Containers; - Context : aliased Context_Type; Ctx : constant Context_Access := Context'Unrestricted_Access; Output_File : aliased File_Type; begin - Context.Group_By_Condition := Inputs.Length (SCO_Files_List) > 0; + Context.Group_By_Condition := not SCO_Files_List.Is_Empty; Context.Keep_Edges := Keep_Edges; - Context.Tag_Executed := Inputs.Length (Traces_Files_List) > 0; + Context.Tag_Executed := not Traces_Files_List.Is_Empty; CFG_Dump_Trace.Trace ("Dumping code from: " & Exec_Path); CFG_Dump_Trace.Trace @@ -1767,7 +1764,9 @@ package body CFG_Dump is if Context.Group_By_Condition then Coverage.Set_Coverage_Levels ("stmt+mcdc"); CFG_Dump_Trace.Trace ("Loading ALI files..."); - Inputs.Iterate (SCO_Files_List, Load_SCOs'Access); + for SCO_File of SCO_Files_List loop + Load_SCOs (+SCO_File); + end loop; Coverage.Source.Initialize_SCI; CFG_Dump_Trace.Trace ("Reading routine names..."); diff --git a/tools/gnatcov/cfg_dump.ads b/tools/gnatcov/cfg_dump.ads index 79bd1e2e2..7f1b9ee31 100644 --- a/tools/gnatcov/cfg_dump.ads +++ b/tools/gnatcov/cfg_dump.ads @@ -18,10 +18,11 @@ with GNAT.Strings; use GNAT.Strings; -with Inputs; with Logging; with Object_Locations; use Object_Locations; with Slocs; use Slocs; +with Strings; use Strings; +with Traces_Files; use Traces_Files; package CFG_Dump is @@ -36,8 +37,8 @@ package CFG_Dump is Locations : User_Locations; Output : String_Access; Format : Output_Format; - SCO_Files_List : Inputs.Inputs_Type; - Traces_Files_List : Inputs.Inputs_Type; + SCO_Files_List : String_Vectors.Vector; + Traces_Files_List : Requested_Trace_Vectors.Vector; Keep_Edges : Boolean); end CFG_Dump; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index b39671d89..340840c7f 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -96,24 +96,26 @@ procedure GNATcov_Bits_Specific is -- This is the main of the bits-specific gnatcov program. Only the gnatcov -- driver (see gnatcov.adb) is supposed to run this main. + use all type Unbounded_String; + -- Results of the command line processing. It is filled by -- Process_Arguments once Switches.Args reached its final state. Annotation : Annotation_Formats_Arr renames Annotations.Annotation; - Trace_Inputs : Inputs.Inputs_Type; - Exe_Inputs : Inputs.Inputs_Type; - Obj_Inputs : Inputs.Inputs_Type; - ALIs_Inputs : Inputs.Inputs_Type; - Routines_Inputs : Inputs.Inputs_Type; - Checkpoints_Inputs : Inputs.Inputs_Type; - SID_Inputs : Inputs.Inputs_Type; - Ignored_Source_Files : Inputs.Inputs_Type; - Files_Of_Interest : Inputs.Inputs_Type; - Compiler_Drivers : Inputs.Inputs_Type; - Source_Rebase_Inputs : Inputs.Inputs_Type; - Source_Search_Inputs : Inputs.Inputs_Type; - Subprograms_Inputs : Inputs.Inputs_Type; + Trace_Inputs : Requested_Trace_Vectors.Vector; + Exe_Inputs : String_Vectors.Vector; + Obj_Inputs : String_Vectors.Vector; + ALIs_Inputs : String_Vectors.Vector; + Routines_Inputs : String_Vectors.Vector; + Checkpoints_Inputs : String_Vectors.Vector; + SID_Inputs : String_Vectors.Vector; + Ignored_Source_Files : String_Vectors.Vector; + Files_Of_Interest : String_Vectors.Vector; + Compiler_Drivers : String_Vectors.Vector; + Source_Rebase_Inputs : String_Vectors.Vector; + Source_Search_Inputs : String_Vectors.Vector; + Subprograms_Inputs : String_Vectors.Vector; Text_Start : Pc_Type := 0; Output : String_Access := null; Tag : String_Access := null; @@ -161,11 +163,14 @@ procedure GNATcov_Bits_Specific is -- Report a fatal error telling the user that an argument is missing. procedure Check_Argument_Available - (Input_Args : Inputs.Inputs_Type; + (Input_Args : String_Vectors.Vector; What : String; Additional_Info : String := ""); -- Invoke Report_Missing_Argument if Input_Args is empty + procedure Check_Traces_Available; + -- Invoke Report_Missing_Argument if Trace_Inputs is empty + procedure Check_User_Provided_SCOs; -- If source coverage is enabled, report an error if no SCOs are provided. -- Do nothing in object coverage mode. @@ -205,16 +210,27 @@ procedure GNATcov_Bits_Specific is ------------------------------ procedure Check_Argument_Available - (Input_Args : Inputs.Inputs_Type; + (Input_Args : String_Vectors.Vector; What : String; Additional_Info : String := "") is begin - if Inputs.Length (Input_Args) = 0 then + if Input_Args.Is_Empty then Report_Missing_Argument (What, Additional_Info); end if; end Check_Argument_Available; + ---------------------------- + -- Check_Traces_Available -- + ---------------------------- + + procedure Check_Traces_Available is + begin + if Trace_Inputs.Is_Empty then + Report_Missing_Argument ("TRACE_FILEs"); + end if; + end Check_Traces_Available; + ------------------------------ -- Check_User_Provided_SCOs -- ------------------------------ @@ -228,9 +244,9 @@ procedure GNATcov_Bits_Specific is -- anything useful, so we need to ask for that and stop. if Source_Coverage_Enabled - and then Inputs.Length (Checkpoints_Inputs) = 0 - and then Inputs.Length (SID_Inputs) = 0 - and then Inputs.Length (ALIs_Inputs) = 0 + and then Checkpoints_Inputs.Is_Empty + and then SID_Inputs.Is_Empty + and then ALIs_Inputs.Is_Empty and then not Args.String_Args (Opt_Project).Present then Report_Missing_Argument @@ -251,30 +267,15 @@ procedure GNATcov_Bits_Specific is procedure Add_LI (S : String); -- Callback to add items to ALIs_Inputs - procedure Load_SCOs_Wrapper (ALI_Filename : String); - -- Wrapper for SC_Obligations.Load_SCOs that uses Ignored to ignore - -- source files. - ------------ -- Add_LI -- ------------ procedure Add_LI (S : String) is begin - Inputs.Add_Input (ALIs_Inputs, S); + Append_Expanded_Argument (S, ALIs_Inputs); end Add_LI; - ----------------------- - -- Load_SCOs_Wrapper -- - ----------------------- - - procedure Load_SCOs_Wrapper (ALI_Filename : String) is - begin - Load_SCOs (ALI_Filename, (if Has_Matcher - then Matcher'Access - else null)); - end Load_SCOs_Wrapper; - -- Start of processing for Load_All_ALIs begin @@ -297,7 +298,7 @@ procedure GNATcov_Bits_Specific is -- command line options, so if it is empty at that point, it means SCOs -- have to be enumerated from a project file. - if Inputs.Length (ALIs_Inputs) = 0 and then Is_Project_Loaded then + if ALIs_Inputs.Is_Empty and then Is_Project_Loaded then Enumerate_SCOs_Files (Add_LI'Access, Binary_Trace_File); end if; @@ -307,7 +308,10 @@ procedure GNATcov_Bits_Specific is -- structures. Create_Matcher (Ignored_Source_Files, Matcher, Has_Matcher); - Inputs.Iterate (ALIs_Inputs, Load_SCOs_Wrapper'Access); + for Filename of ALIs_Inputs loop + Load_SCOs + (+Filename, (if Has_Matcher then Matcher'Access else null)); + end loop; Coverage.Source.Initialize_SCI; elsif Object_Coverage_Enabled then @@ -315,7 +319,9 @@ procedure GNATcov_Bits_Specific is -- For object coverage, just load ALIs (not SCOs inside them) just to -- get exemptions as they apply to instruction/branch coverage. - Inputs.Iterate (ALIs_Inputs, ALI_Files.Load_ALI'Access); + for Filename of ALIs_Inputs loop + ALI_Files.Load_ALI (+Filename); + end loop; end if; -- If subprograms of interest were passed warn the user that they will @@ -340,75 +346,15 @@ procedure GNATcov_Bits_Specific is procedure Add_SID_File (SID_Name : String); -- Callback for Enumerate_SIDs. Add SID_Name to SID_Inputs - procedure SID_Load_Wrapper (Filename : String); - -- Wrapper for SID_Load to include the ignored source file regexp - - procedure Process_Subp_Input (Subp_Input : String); - -- Parse a value passed to --subprograms - ------------------ -- Add_SID_File -- ------------------ procedure Add_SID_File (SID_Name : String) is begin - Inputs.Add_Input (SID_Inputs, SID_Name); + Append_Expanded_Argument (SID_Name, SID_Inputs); end Add_SID_File; - ---------------------- - -- SID_Load_Wrapper -- - ---------------------- - - procedure SID_Load_Wrapper (Filename : String) is - begin - Checkpoints.SID_Load - (Filename, (if Has_Matcher then Matcher'Access else null)); - end SID_Load_Wrapper; - - ------------------------ - -- Process_Subp_Input -- - ------------------------ - - procedure Process_Subp_Input (Subp_Input : String) is - Column_Index : constant Natural := - Ada.Strings.Fixed.Index (Subp_Input, Ada.Strings.Maps.To_Set (':')); - Filename : String renames - Subp_Input (Subp_Input'First .. Column_Index - 1); - Column : String renames - Subp_Input (Column_Index + 1 .. Subp_Input'Last); - - Identifier : Scope_Entity_Identifier; - begin - if Column_Index = 0 then - raise Constraint_Error; - end if; - Identifier.Decl_SFI := - Get_Index_From_Full_Name - (Full_Name => Full_Name (Filename), - Kind => Source_File, - Insert => False); - if Identifier.Decl_SFI = No_Source_File then - Outputs.Fatal_Error - ("Error when parsing --subprograms argument " - & Subp_Input & ": unknown source file"); - end if; - Identifier.Decl_Line := Natural'Value (Column); - - if not Available_Subps_Of_Interest.Contains (Identifier) then - Outputs.Fatal_Error - ("Error when parsing --subprograms argument " - & Subp_Input & ": unknown subprogram"); - end if; - Subps_Of_Interest.Include (Identifier); - exception - -- Deal gracefully with parsing errors - - when Constraint_Error => - Outputs.Fatal_Error - ("Wrong argument passed to --subprograms: " - & "expecting : but got " & Subp_Input); - end Process_Subp_Input; - -- Start of processing for Load_All_SIDs begin @@ -420,7 +366,7 @@ procedure GNATcov_Bits_Specific is -- If no --sid option is present, enumerate all available SID for units -- of interest. This requires a project file. - if Is_Project_Loaded and then Inputs.Length (SID_Inputs) = 0 then + if Is_Project_Loaded and then SID_Inputs.Is_Empty then Enumerate_SCOs_Files (Add_SID_File'Access, Source_Trace_File); end if; @@ -428,7 +374,10 @@ procedure GNATcov_Bits_Specific is -- if present. Create_Matcher (Ignored_Source_Files, Matcher, Has_Matcher); - Inputs.Iterate (SID_Inputs, SID_Load_Wrapper'Access); + for Filename of SID_Inputs loop + Checkpoints.SID_Load + (+Filename, (if Has_Matcher then Matcher'Access else null)); + end loop; -- Now that all the scope entities that can be referenced by -- --subprograms are known, dump them if requested. @@ -443,7 +392,46 @@ procedure GNATcov_Bits_Specific is -- Parse the listed subprograms of interest Copy_Arg_List (Opt_Subp_Of_Interest, Subprograms_Inputs); - Iterate (Subprograms_Inputs, Process_Subp_Input'Access); + for Name of Subprograms_Inputs loop + declare + N : constant String := +Name; + Column_Index : constant Natural := + Ada.Strings.Fixed.Index (N, Ada.Strings.Maps.To_Set (':')); + Filename : String renames N (N'First .. Column_Index - 1); + Column : String renames N (Column_Index + 1 .. N'Last); + + Identifier : Scope_Entity_Identifier; + begin + if Column_Index = 0 then + raise Constraint_Error; + end if; + Identifier.Decl_SFI := + Get_Index_From_Full_Name + (Full_Name => Full_Name (Filename), + Kind => Source_File, + Insert => False); + if Identifier.Decl_SFI = No_Source_File then + Outputs.Fatal_Error + ("Error when parsing --subprograms argument " + & N & ": unknown source file"); + end if; + Identifier.Decl_Line := Natural'Value (Column); + + if not Available_Subps_Of_Interest.Contains (Identifier) then + Outputs.Fatal_Error + ("Error when parsing --subprograms argument " + & N & ": unknown subprogram"); + end if; + Subps_Of_Interest.Include (Identifier); + exception + -- Deal gracefully with parsing errors + + when Constraint_Error => + Outputs.Fatal_Error + ("Wrong argument passed to --subprograms: " + & "expecting : but got " & N); + end; + end loop; end Load_All_SIDs; ----------------------- @@ -456,14 +444,13 @@ procedure GNATcov_Bits_Specific is -- Parse S to get an hexadecimal number (form : 0x[0-9a-f]+) and -- return the value. If the parsing fails, fatal error. - Current_Exec : GNAT.Strings.String_Access := null; + Current_Exec : Unbounded_String; -- Some arguments specify what executable the next traces will have to -- refer to: this holds the current executable for the next traces. procedure Handle_Trace_List_Element (Element : String); -- If Element starts with ASCII.NUL, consider it comes from --exec and - -- assign it to Current_Exec. Otherwise, add it to the Trace_Inputs - -- input-list. + -- assign it to Current_Exec. Otherwise, add it to Trace_Inputs. --------------- -- Parse_Hex -- @@ -494,14 +481,10 @@ procedure GNATcov_Bits_Specific is procedure Handle_Trace_List_Element (Element : String) is begin - if Element'Length > 0 - and then Element (Element'First) = ASCII.NUL - then - Current_Exec := - new String'(Element (Element'First + 1 .. Element'Last)); + if Has_Prefix (Element, (1 => ASCII.NUL)) then + Current_Exec := +Element (Element'First + 1 .. Element'Last); else - Inputs.Add_Input - (Trace_Inputs, Element, Qualifier => Current_Exec); + Trace_Inputs.Append ((+Element, Current_Exec)); end if; end Handle_Trace_List_Element; @@ -543,12 +526,12 @@ procedure GNATcov_Bits_Specific is Copy_Arg (Opt_Save_Checkpoint, Save_Checkpoint); Copy_Arg_List (Opt_Scos, ALIs_Inputs); - if Inputs.Length (ALIs_Inputs) /= 0 then + if not ALIs_Inputs.Is_Empty then Invalidate_Unit_List ("--scos is present"); end if; Copy_Arg_List (Opt_SID, SID_Inputs); - if Inputs.Length (SID_Inputs) /= 0 then + if not SID_Inputs.Is_Empty then Invalidate_Unit_List ("--sid is present"); end if; @@ -568,10 +551,10 @@ procedure GNATcov_Bits_Specific is Copy_Arg_List (Opt_Files, Files_Of_Interest); Copy_Arg_List (Opt_Compiler_Wrappers, Compiler_Drivers); - for File of Files_Of_Interest loop + for Filename of Files_Of_Interest loop declare use GNATCOLL.VFS; - F : constant Virtual_File := Create (+File.Name.all); + F : constant Virtual_File := Create (+(+Filename)); begin F.Normalize_Path; Switches.Files_Of_Interest.Include (+(+Full_Name (F))); @@ -636,7 +619,7 @@ procedure GNATcov_Bits_Specific is end if; for Arg of Args.String_List_Args (Opt_Routines_List) loop - Inputs.Add_Input (Routines_Inputs, '@' & (+Arg)); + Routines_Inputs.Append (+"@" & Arg); end loop; if Args.String_Args (Opt_Text_Start).Present then @@ -661,23 +644,17 @@ procedure GNATcov_Bits_Specific is Calendar_Utils.To_Timezone (+Args.String_Args (Opt_Timezone).Value); end if; - -- Parse --source-rebase options - - declare - procedure Process_One_Entry (Arg : String); - -- Parse source-rebase's argument. This option's form should be: - -- - -- "=" - - ----------------------- - -- Process_One_Entry -- - ----------------------- + -- Parse --source-rebase options. This option's form should be: + -- + -- "=". - procedure Process_One_Entry (Arg : String) is + Copy_Arg_List (Opt_Source_Rebase, Source_Rebase_Inputs); + for Arg of Source_Rebase_Inputs loop + declare Pos : Natural := 0; begin - for I in Arg'First .. Arg'Last loop - if Arg (I) = '=' then + for I in 1 .. Length (Arg) loop + if Element (Arg, I) = '=' then Pos := I; exit; end if; @@ -685,19 +662,18 @@ procedure GNATcov_Bits_Specific is if Pos = 0 then Fatal_Error ("Missing '=' in --source-rebase"); end if; - Add_Source_Rebase (Arg (Arg'First .. Pos - 1), - Arg (Pos + 1 .. Arg'Last)); - end Process_One_Entry; - - begin - Copy_Arg_List (Opt_Source_Rebase, Source_Rebase_Inputs); - Iterate (Source_Rebase_Inputs, Process_One_Entry'Access); - end; + Add_Source_Rebase + (Old_Prefix => Slice (Arg, 1, Pos - 1), + New_Prefix => Slice (Arg, Pos + 1, Length (Arg))); + end; + end loop; -- Parse --source-search options Copy_Arg_List (Opt_Source_Search, Source_Search_Inputs); - Iterate (Source_Search_Inputs, Add_Source_Search'Access); + for Dirname of Source_Search_Inputs loop + Add_Source_Search (+Dirname); + end loop; if Args.String_Args (Opt_Exec_Prefix).Present then Set_Exec_Prefix (+Args.String_Args (Opt_Exec_Prefix).Value); @@ -709,7 +685,9 @@ procedure GNATcov_Bits_Specific is end if; for Arg of Args.String_List_Args (Opt_Trace) loop - Handle_Trace_List_Element (+Arg); + for Exp_Arg of Expand_Argument (+Arg) loop + Handle_Trace_List_Element (+Exp_Arg); + end loop; end loop; if Args.String_Args (Opt_Trace_Source).Present then @@ -790,7 +768,7 @@ procedure GNATcov_Bits_Specific is procedure Set_Mode (SO_Set : SO_Set_Type) is begin - if Length (SO_Inputs.Set) /= 0 then + if not SO_Inputs.Set.Is_Empty then Invalid_SO_With (SO_Set.Kind); end if; SO_Inputs := SO_Set; @@ -833,7 +811,7 @@ procedure GNATcov_Bits_Specific is else case SO_Inputs.Kind is when None | All_SO => Invalid_SO_With (SO_Inputs.Kind); - when Some_SO => Add_Input (SO_Inputs.Set, +Arg); + when Some_SO => SO_Inputs.Set.Append (Arg); end case; end if; end; @@ -915,9 +893,7 @@ procedure GNATcov_Bits_Specific is when Cmd_Disp_Routines | Cmd_Scan_Objects => - for Arg of Args.Remaining_Args loop - Inputs.Add_Input (Obj_Inputs, +Arg); - end loop; + Copy_Arg_List (Args.Remaining_Args, Obj_Inputs); when Cmd_Dump_Sections | Cmd_Dump_Symbols @@ -927,9 +903,7 @@ procedure GNATcov_Bits_Specific is | Cmd_Dump_Lines | Cmd_Disassemble_Raw | Cmd_Disassemble => - for Arg of Args.Remaining_Args loop - Inputs.Add_Input (Exe_Inputs, +Arg); - end loop; + Copy_Arg_List (Args.Remaining_Args, Exe_Inputs); when Cmd_Disassemble_Insn_Properties | Cmd_Dump_CFG => -- The first argument is the executable. The other ones are @@ -971,9 +945,7 @@ procedure GNATcov_Bits_Specific is -- decision map. Set_Coverage_Levels ("stmt+mcdc"); - for Arg of Args.Remaining_Args loop - Inputs.Add_Input (Exe_Inputs, +Arg); - end loop; + Copy_Arg_List (Args.Remaining_Args, Exe_Inputs); when Cmd_Run => @@ -1019,7 +991,7 @@ procedure GNATcov_Bits_Specific is begin if Earg0_Executable then - Inputs.Add_Input (Exe_Inputs, Earg0); + Append_Expanded_Argument (Earg0, Exe_Inputs); loop Next (C); exit when not Has_Element (C); @@ -1027,7 +999,8 @@ procedure GNATcov_Bits_Specific is end loop; elsif Exe_From_Project /= "" then - Inputs.Add_Input (Exe_Inputs, Exe_From_Project); + Append_Expanded_Argument + (Exe_From_Project, Exe_Inputs); Eargs := Eargs_Arg; else Report_Missing_Argument ("an executable to run (EXE)"); @@ -1041,8 +1014,8 @@ procedure GNATcov_Bits_Specific is -- line (before eargs). Use it and forward all the EARGS -- options we have to the Eargs local. - Inputs.Add_Input - (Exe_Inputs, +Args.Remaining_Args.First_Element); + Append_Expanded_Argument + (+Args.Remaining_Args.First_Element, Exe_Inputs); Eargs := Args.String_List_Args (Opt_Eargs); when others => @@ -1054,9 +1027,7 @@ procedure GNATcov_Bits_Specific is end case; when Cmd_Check_SCOs => - for Arg of Args.Remaining_Args loop - Inputs.Add_Input (ALIs_Inputs, +Arg); - end loop; + Copy_Arg_List (Args.Remaining_Args, ALIs_Inputs); when Cmd_Convert => if Args.String_List_Args (Opt_Exec).Is_Empty then @@ -1162,8 +1133,7 @@ procedure GNATcov_Bits_Specific is end if; end if; - if Inputs.Length (Ignored_Source_Files) = 0 and then Is_Project_Loaded - then + if Ignored_Source_Files.Is_Empty and then Is_Project_Loaded then declare procedure Add_Source_File (S : String); -- Add S to the list of ignored source files @@ -1174,7 +1144,7 @@ procedure GNATcov_Bits_Specific is procedure Add_Source_File (S : String) is begin - Inputs.Add_Input (Ignored_Source_Files, S); + Append_Expanded_Argument (S, Ignored_Source_Files); end Add_Source_File; begin Enumerate_Ignored_Source_Files (Add_Source_File'Access); @@ -1273,35 +1243,20 @@ begin when Cmd_Disp_Routines => declare Mode_Exclude : Boolean := False; - - procedure Read_Routine_Name (Disp_Routine_Arg : String); - -- Process Disp_Routine_Arg: - -- * if it equals "--exclude", switch mode to exclude; - -- * if it equals "--include", switch mode to include; - -- * otherwise, consider Disp_Routine_Arg as a object file name - -- and exclude or include it according to the current mode. - - ----------------------- - -- Read_Routine_Name -- - ----------------------- - - procedure Read_Routine_Name (Disp_Routine_Arg : String) is - begin - if Disp_Routine_Arg = "--exclude" then + begin + Check_Argument_Available (Obj_Inputs, "FILEs"); + for Arg of Obj_Inputs loop + if Arg = "--exclude" then Mode_Exclude := True; - elsif Disp_Routine_Arg = "--include" then + elsif Arg = "--include" then Mode_Exclude := False; else Traces_Elf.Read_Routine_Names - (Disp_Routine_Arg, + (+Arg, Exclude => Mode_Exclude, Strict => False); end if; - end Read_Routine_Name; - - begin - Check_Argument_Available (Obj_Inputs, "FILEs"); - Inputs.Iterate (Obj_Inputs, Read_Routine_Name'Access); + end loop; Traces_Names.Disp_All_Routines_Of_Interest; end; @@ -1493,54 +1448,32 @@ begin end; when Cmd_Scan_Objects => - declare - procedure Scan_One_Elf (Elf_Name : String); - -- Process to Scan_Symbols_From ELF_NAME in strict mode, warning - -- about text section points of note wrt object coverage (empty - -- symbols, orphan regions, ...) - - ------------------ - -- Scan_One_Elf -- - ------------------ - - procedure Scan_One_Elf (Elf_Name : String) is - begin - Traces_Elf.Scan_Symbols_From - (Elf_Name, - Sym_Cb => null, - Strict => True); - end Scan_One_Elf; + -- Scan symbols from all given ELF files in strict mode, warning + -- about text section points of note wrt object coverage (empty + -- symbols, orphan regions, ...) - begin - Check_Argument_Available (Obj_Inputs, "FILEs"); - Inputs.Iterate (Obj_Inputs, Scan_One_Elf'Access); - end; + Check_Argument_Available (Obj_Inputs, "FILEs"); + for Filename of Obj_Inputs loop + Traces_Elf.Scan_Symbols_From + (+Filename, + Sym_Cb => null, + Strict => True); + end loop; when Cmd_Map_Routines => - declare - procedure Build_Decision_Map (Exec_Name : String); - -- Prepare decision map build for Exec_Name - - ------------------------ - -- Build_Decision_Map -- - ------------------------ - - procedure Build_Decision_Map (Exec_Name : String) is + Load_All_ALIs (Check_SCOs => True); + for Filename of Exe_Inputs loop + declare + F : constant String := +Filename; begin - -- Just set the filename - - Build_Decision_Map (Exec_Name, Text_Start, Exec_Name & ".dmap"); - end Build_Decision_Map; - - begin - Load_All_ALIs (Check_SCOs => True); - Inputs.Iterate (Exe_Inputs, Build_Decision_Map'Access); - if SCOs_Trace.Is_Active then - SC_Obligations.Report_SCOs_Without_Code; - end if; - SC_Obligations.Report_Units_Without_Code; - end; + Build_Decision_Map (F, Text_Start, F & ".dmap"); + end; + end loop; + if SCOs_Trace.Is_Active then + SC_Obligations.Report_SCOs_Without_Code; + end if; + SC_Obligations.Report_Units_Without_Code; when Cmd_Scan_Decisions => Set_Coverage_Levels ("stmt"); @@ -1549,16 +1482,22 @@ begin when Cmd_Check_SCOs => Set_Coverage_Levels ("stmt"); - Inputs.Iterate (ALIs_Inputs, Check_SCOs.Check_SCO_Syntax'Access); + for Filename of ALIs_Inputs loop + Check_SCOs.Check_SCO_Syntax (+Filename); + end loop; Load_All_ALIs (Check_SCOs => True); when Cmd_Dump_Trace => - Check_Argument_Available (Trace_Inputs, "TRACE_FILEs"); - Inputs.Iterate (Trace_Inputs, Dump_Trace_File'Access); + Check_Traces_Available; + for RT of Trace_Inputs loop + Dump_Trace_File (+RT.Filename); + end loop; when Cmd_Dump_Trace_Raw => - Check_Argument_Available (Trace_Inputs, "TRACE_FILEs"); - Inputs.Iterate (Trace_Inputs, Dump_Raw_Trace_File'Access); + Check_Traces_Available; + for RT of Trace_Inputs loop + Dump_Raw_Trace_File (+RT.Filename); + end loop; when Cmd_Dump_Trace_Base => declare @@ -1579,51 +1518,29 @@ begin end Dump_Trace_Base; begin - Check_Argument_Available (Trace_Inputs, "TRACE_FILEs"); - Inputs.Iterate (Trace_Inputs, Dump_Trace_Base'Access); + Check_Traces_Available; + for RT of Trace_Inputs loop + Dump_Trace_Base (+RT.Filename); + end loop; end; when Cmd_Dump_Trace_Asm => - declare - procedure Open_Exec (Exec_File_Name : String); - -- Open Exec_File_Name and build its sections and symbol - -- information. - - procedure Dump_Trace (Trace_File_Name : String); - -- Raw display of Trace_File_Name with assembly code - - ---------------- - -- Dump_Trace -- - ---------------- - - procedure Dump_Trace (Trace_File_Name : String) is - begin - Traces_Disa.Dump_Traces_With_Asm (Exec.all, Trace_File_Name); - end Dump_Trace; - - --------------- - -- Open_Exec -- - --------------- - - procedure Open_Exec (Exec_File_Name : String) is - begin - Exec := Open_File (Exec_File_Name, Text_Start); - Build_Sections (Exec.all); - Build_Symbols (Exec.all); - end Open_Exec; - - begin - Check_Argument_Available (Exe_Inputs, "EXE"); - Check_Argument_Available (Trace_Inputs, "TRACE_FILEs"); - Inputs.Iterate (Exe_Inputs, Open_Exec'Access); - Inputs.Iterate (Trace_Inputs, Dump_Trace'Access); - end; + Check_Argument_Available (Exe_Inputs, "EXE"); + Check_Traces_Available; + for Filename of Exe_Inputs loop + Exec := Open_File (+Filename, Text_Start); + Build_Sections (Exec.all); + Build_Symbols (Exec.all); + end loop; + for TF of Trace_Inputs loop + Traces_Disa.Dump_Traces_With_Asm (Exec.all, +TF.Filename); + end loop; when Cmd_Dump_Src_Trace => - Check_Argument_Available (Trace_Inputs, "TRACE_FILE"); - Inputs.Iterate - (Trace_Inputs, - Instrument.Input_Traces.Dump_Source_Trace_File'Access); + Check_Traces_Available; + for TF of Trace_Inputs loop + Instrument.Input_Traces.Dump_Source_Trace_File (+TF.Filename); + end loop; when Cmd_Dump_Sections | Cmd_Dump_Symbols @@ -1631,18 +1548,14 @@ begin | Cmd_Dump_Inlined_Subprograms | Cmd_Dump_Lines => declare - procedure Dump_Exec (Exec_File_Name : String); -- Dump Exec_File_Name's sections|symbols|subprograms|lines, -- depending on the current command. - --------------- - -- Dump_Exec -- - --------------- - - procedure Dump_Exec (Exec_File_Name : String) is - To_Display : Address_Info_Kind; - begin - Exec := Open_File (Exec_File_Name, Text_Start); + To_Display : Address_Info_Kind; + begin + Check_Argument_Available (Exe_Inputs, "EXEs"); + for Filename of Exe_Inputs loop + Exec := Open_File (+Filename, Text_Start); Build_Sections (Exec.all); case Args.Command is @@ -1673,79 +1586,36 @@ begin Disp_Addresses (Exec.all, To_Display); Close_File (Exec); - end Dump_Exec; - - begin - Check_Argument_Available (Exe_Inputs, "EXEs"); - Inputs.Iterate (Exe_Inputs, Dump_Exec'Access); + end loop; end; when Cmd_Dump_Compile_Units => - declare - procedure Dump_Compilation_Units (Exec_File_Name : String); - -- Dump Exec_File_Name's compilation units - - ---------------------------- - -- Dump_Compilation_Units -- - ---------------------------- - - procedure Dump_Compilation_Units (Exec_File_Name : String) is - begin - Exec := Open_File (Exec_File_Name, 0); - Build_Sections (Exec.all); - Build_Debug_Compile_Units (Exec.all); - Disp_Compilation_Units (Exec.all); - Close_File (Exec); - end Dump_Compilation_Units; - - begin - Check_Argument_Available (Exe_Inputs, "EXEs"); - Inputs.Iterate (Exe_Inputs, Dump_Compilation_Units'Access); - end; + Check_Argument_Available (Exe_Inputs, "EXEs"); + for Filename of Exe_Inputs loop + Exec := Open_File (+Filename, 0); + Build_Sections (Exec.all); + Build_Debug_Compile_Units (Exec.all); + Disp_Compilation_Units (Exec.all); + Close_File (Exec); + end loop; when Cmd_Disassemble_Raw => - declare - procedure Disassemble (Exec_File_Name : String); - -- Disassemble Exec_File_Name and display the raw result - - ----------------- - -- Disassemble -- - ----------------- - - procedure Disassemble (Exec_File_Name : String) is - begin - Exec := Open_File (Exec_File_Name, 0); - Disassemble_File_Raw (Exec.all); - Close_File (Exec); - end Disassemble; - - begin - Check_Argument_Available (Exe_Inputs, "EXEs"); - Inputs.Iterate (Exe_Inputs, Disassemble'Access); - end; + Check_Argument_Available (Exe_Inputs, "EXEs"); + for Filename of Exe_Inputs loop + Exec := Open_File (+Filename, 0); + Disassemble_File_Raw (Exec.all); + Close_File (Exec); + end loop; when Cmd_Disassemble => - declare - procedure Disassemble (Exec_File_Name : String); - -- Disassemble Exec_File_Name and display the raw result - - ----------------- - -- Disassemble -- - ----------------- - - procedure Disassemble (Exec_File_Name : String) is - begin - Exec := Open_File (Exec_File_Name, 0); - Build_Sections (Exec.all); - Build_Symbols (Exec.all); - Disassemble_File (Exec.all); - Close_File (Exec); - end Disassemble; - - begin - Check_Argument_Available (Exe_Inputs, "EXEs"); - Inputs.Iterate (Exe_Inputs, Disassemble'Access); - end; + Check_Argument_Available (Exe_Inputs, "EXEs"); + for Filename of Exe_Inputs loop + Exec := Open_File (+Filename, 0); + Build_Sections (Exec.all); + Build_Symbols (Exec.all); + Disassemble_File (Exec.all); + Close_File (Exec); + end loop; when Cmd_Disassemble_Insn_Properties | Cmd_Dump_CFG => if Executable_Path = null then @@ -1801,7 +1671,7 @@ begin & ", not --level=" & Coverage_Option_Value (Current_Levels) & ")"); - elsif Inputs.Length (Checkpoints_Inputs) > 0 + elsif not Checkpoints_Inputs.Is_Empty or else Save_Checkpoint /= null then Fatal_Error ("Incremental coverage is supported for source" @@ -1845,12 +1715,13 @@ begin if Object_Coverage_Enabled then - if Inputs.Length (Routines_Inputs) /= 0 then - Inputs.Iterate (Routines_Inputs, - Traces_Names.Add_Routine_Of_Interest'Access); + if not Routines_Inputs.Is_Empty then + for Name of Routines_Inputs loop + Traces_Names.Add_Routine_Of_Interest (+Name); + end loop; Routines_Of_Interest_Origin := From_Command_Line; - elsif Inputs.Length (Trace_Inputs) > 1 then + elsif Trace_Inputs.Length > 1 then Report_Missing_Argument ("a list of routines", "required when reading multiple trace files"); @@ -1864,7 +1735,7 @@ begin end if; else - if Inputs.Length (Routines_Inputs) /= 0 then + if not Routines_Inputs.Is_Empty then Fatal_Error ("Routine list not allowed for source coverage."); end if; end if; @@ -2149,7 +2020,7 @@ begin -- first executable. A test earlier allows this only if there -- is one trace file. - if Inputs.Length (Routines_Inputs) = 0 then + if Routines_Inputs.Is_Empty then Read_Routine_Names (Exe_File.all, Exclude => False); end if; @@ -2317,22 +2188,26 @@ begin end Process_Trace_For_Src_Coverage; begin - if Inputs.Length (Checkpoints_Inputs) = 0 then - Check_Argument_Available (Trace_Inputs, "TRACE_FILEs"); + if Checkpoints_Inputs.Is_Empty then + Check_Traces_Available; end if; - Inputs.Iterate (Exe_Inputs, Process_Exec'Access); - Inputs.Iterate (Trace_Inputs, Process_Trace'Access); + for Filename of Exe_Inputs loop + Process_Exec (+Filename); + end loop; + for RT of Trace_Inputs loop + Process_Trace (+RT.Filename, +RT.Executable); + end loop; -- Warn when using --scos with source traces or --sid with bin -- traces. - if Inputs.Length (SID_Inputs) > 0 and then Bin_Traces_Present then + if not SID_Inputs.Is_Empty and then Bin_Traces_Present then Warn ("Using option --sid with binary trace files has no" & " effect." & ASCII.LF & "Please consider using option" & " --scos or -P in conjunction with" & " --units to specify units of interest."); end if; - if Inputs.Length (ALIs_Inputs) > 0 and then Src_Traces_Present then + if not ALIs_Inputs.Is_Empty and then Src_Traces_Present then Warn ("Using option --scos with source trace files has no" & " effect." & ASCII.LF & "Please consider using option" & " --sid or -P in conjunction with --units" @@ -2352,8 +2227,9 @@ begin -- Read checkpointed coverage data from previous executions - Inputs.Iterate - (Checkpoints_Inputs, Checkpoints.Checkpoint_Load'Access); + for Filename of Checkpoints_Inputs loop + Checkpoints.Checkpoint_Load (+Filename); + end loop; -- Now determine coverage according to the requested metric (for -- source coverage, complete coverage information has been determined @@ -2495,16 +2371,8 @@ begin when Cmd_Run => Check_Argument_Available (Exe_Inputs, "EXE"); - - declare - procedure Run (Exe_File : String); - -- Run Exe_File in QEMU - - --------- - -- Run -- - --------- - - procedure Run (Exe_File : String) is + for Filename of Exe_Inputs loop + declare package OS renames GNAT.OS_Lib; use type OS.File_Descriptor; @@ -2515,7 +2383,7 @@ begin begin if MCDC_Coverage_Enabled then Load_All_ALIs (Check_SCOs => False); - if Length (ALIs_Inputs) = 0 then + if ALIs_Inputs.Is_Empty then Warn ("No SCOs specified for MC/DC level."); else @@ -2540,11 +2408,11 @@ begin Histmap := new String' (Dmap_Filename (1 .. OS.Temp_File_Len - 1)); - Build_Decision_Map (Exe_File, Text_Start, Histmap.all); + Build_Decision_Map (+Filename, Text_Start, Histmap.all); end if; end if; - Rundrv.Driver (Exe_File, Target_Family, Target_Board, Tag, + Rundrv.Driver (+Filename, Target_Family, Target_Board, Tag, Output, Histmap, Kernel, Vector_To_List (Eargs), SO_Inputs); @@ -2560,10 +2428,8 @@ begin end if; Free (Histmap); end if; - end Run; - begin - Inputs.Iterate (Exe_Inputs, Run'Access); - end; + end; + end loop; when Cmd_Convert => declare @@ -2574,7 +2440,7 @@ begin begin if MCDC_Coverage_Enabled then Load_All_ALIs (Check_SCOs => False); - if Length (ALIs_Inputs) = 0 then + if ALIs_Inputs.Is_Empty then Warn ("No SCOs specified for MC/DC level."); else diff --git a/tools/gnatcov/inputs.adb b/tools/gnatcov/inputs.adb index d277d092e..12289702f 100644 --- a/tools/gnatcov/inputs.adb +++ b/tools/gnatcov/inputs.adb @@ -23,143 +23,11 @@ with GNAT.CRC32; with GNATCOLL.Mmap; with Hex_Images; use Hex_Images; -with Outputs; use Outputs; with Paths; with Switches; package body Inputs is - --------------- - -- Add_Input -- - --------------- - - procedure Add_Input - (Inputs : in out Inputs_Type; - Name : String; - Qualifier : String_Access := null) - is - procedure Add_Input (Name : String); - -- Add_Input for this particular Inputs (the one given in parameter) - - --------------- - -- Add_Input -- - --------------- - - procedure Add_Input (Name : String) is - begin - Inputs.Add_Input (Name, Qualifier); - end Add_Input; - - -- Start of processing for Add_Input - - begin - if Name'Length = 0 then - return; - end if; - - if Name (Name'First) /= '@' then - Inputs.Append ((Name => new String'(Name), Qualifier => Qualifier)); - else - if Name'Length = 1 then - return; - end if; - - if Name (Name'First + 1) /= '@' then - declare - File_Name : constant String := - Name (Name'First + 1 .. Name'Last); - begin - Read_List_From_File (File_Name, Add_Input'Access); - exception - when Name_Error | Status_Error => - Fatal_Error ("cannot open input list: " & File_Name); - end; - else - Inputs.Append - ((Name => new String'(Name (Name'First + 1 .. Name'Last)), - Qualifier => Qualifier)); - end if; - end if; - end Add_Input; - - ----------- - -- Equal -- - ----------- - - function Equal (L, R : Inputs_Entry) return Boolean is - begin - return Equal (L.Name, R.Name) and then - (if L.Qualifier /= null and then R.Qualifier /= null - then Equal (L.Qualifier, R.Qualifier) - else L.Qualifier = R.Qualifier); - end Equal; - - ------------- - -- Iterate -- - ------------- - - procedure Iterate - (Inputs : Inputs_Type; - Process : not null access procedure (Input : String)) - is - use Input_Lists; - - procedure Input_Lists_Process (Position : Cursor); - -- Call Process with Input at Cursor - - ------------------------- - -- Input_Lists_Process -- - ------------------------- - - procedure Input_Lists_Process (Position : Cursor) is - IE : constant Inputs_Entry := Element (Position); - begin - Process (IE.Name.all); - end Input_Lists_Process; - - -- Start of processing for Iterate - - begin - Inputs.Iterate (Input_Lists_Process'Access); - end Iterate; - - procedure Iterate - (Inputs : Inputs_Type; - Process : not null access procedure - (Input : String; Qualifier : String)) - is - use Input_Lists; - - procedure Input_Lists_Process (Position : Cursor); - -- Call Process with Input at Cursor - - ------------------------- - -- Input_Lists_Process -- - ------------------------- - - procedure Input_Lists_Process (Position : Cursor) is - IE : constant Inputs_Entry := Element (Position); - begin - Process - (IE.Name.all, - (if IE.Qualifier = null then "" else IE.Qualifier.all)); - end Input_Lists_Process; - - -- Start of processing for Iterate - - begin - Inputs.Iterate (Input_Lists_Process'Access); - end Iterate; - - ------------ - -- Length -- - ------------ - - function Length (Inputs : Inputs_Type) return Ada.Containers.Count_Type is - begin - return Input_Lists.Length (Input_Lists.List (Inputs)); - end Length; - ------------------------- -- Read_List_From_File -- ------------------------- @@ -245,39 +113,6 @@ package body Inputs is end if; end Log_File_Open; - ---------------------- - -- To_String_Vector -- - ---------------------- - - function To_String_Vector - (Inputs : Inputs_Type) return String_Vectors.Vector - is - use String_Vectors; - - Res : Vector; - begin - for IE of Inputs loop - Res.Append (+IE.Name.all); - end loop; - return Res; - end To_String_Vector; - - ------------------- - -- To_String_Set -- - ------------------- - - function To_String_Set - (Inputs : Inputs_Type) return String_Sets.Set - is - use String_Sets; - Res : Set; - begin - for IE of Inputs loop - Res.Include (+IE.Name.all); - end loop; - return Res; - end To_String_Set; - -------------------- -- Create_Matcher -- -------------------- @@ -339,17 +174,4 @@ package body Inputs is end if; end Create_Matcher; - procedure Create_Matcher - (Pattern_List : Inputs.Inputs_Type; - Matcher : out GNAT.Regexp.Regexp; - Has_Matcher : out Boolean; - Case_Insensitive : Boolean := False) is - begin - Create_Matcher - (To_String_Vector (Pattern_List), - Matcher, - Has_Matcher, - Case_Insensitive); - end Create_Matcher; - end Inputs; diff --git a/tools/gnatcov/inputs.ads b/tools/gnatcov/inputs.ads index c2914b197..301f390b4 100644 --- a/tools/gnatcov/inputs.ads +++ b/tools/gnatcov/inputs.ads @@ -16,9 +16,7 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Containers.Doubly_Linked_Lists; with GNAT.Regexp; -with GNAT.Strings; use GNAT.Strings; with Strings; use Strings; @@ -42,61 +40,10 @@ package Inputs is -- May raise Name_Error or Status_Error if the corresponding text file -- cannot be opened. - type Inputs_Entry is record - Name, Qualifier : String_Access; - end record; - - function Equal (L, R : Inputs_Entry) return Boolean; - - package Input_Lists is new Ada.Containers.Doubly_Linked_Lists - (Element_Type => Inputs_Entry, - "=" => Equal); - - type Inputs_Type is new Input_Lists.List with null record; - -- Input lists. Can be used to accumulate the arguments given on - -- a command line. - - procedure Add_Input - (Inputs : in out Inputs_Type; - Name : String; - Qualifier : String_Access := null); - -- If Name does not begin with '@', it is an input: add it to Inputs. - -- - -- If Name begins with '@', it is a file name; this corresponding - -- file constains a list of inputs to append to Inputs, in the format - -- described by Read_List_From_File. - -- - -- If Name begins with '@@', it is an input ('@' is escaped): add - -- Name (Name'First + 1 .. Name'Last) to Inputs. - - -- An optional qualifier may be provided for each input - - procedure Iterate - (Inputs : Inputs_Type; - Process : not null access procedure (Input : String)); - procedure Iterate - (Inputs : Inputs_Type; - Process : not null access procedure - (Input : String; Qualifier : String)); - -- Go through the input list and call Process on each entry (qualifiers are - -- ignored in the first variant). - - function Length (Inputs : Inputs_Type) return Ada.Containers.Count_Type - with Inline; - -- Return the number of elements in Inputs - procedure Log_File_Open (File_Name : String); -- When in verbose mode, add a debug message indicating that File_Name is -- open. Try to include the CRC32 checksum. - function To_String_Vector - (Inputs : Inputs_Type) return String_Vectors.Vector; - -- Convert an inputs list into a String_Vectors.Vector - - function To_String_Set - (Inputs : Inputs_Type) return String_Sets.Set; - -- Convert an inputs list into a String_Sets.Set - procedure Create_Matcher (Pattern_List : String_Vectors.Vector; Matcher : out GNAT.Regexp.Regexp; @@ -111,11 +58,4 @@ package Inputs is -- Case_Insensitive is False (for instance on Windows, where all glob -- patterns are interpreted as case insensitive). - procedure Create_Matcher - (Pattern_List : Inputs.Inputs_Type; - Matcher : out GNAT.Regexp.Regexp; - Has_Matcher : out Boolean; - Case_Insensitive : Boolean := False); - -- Overload to work on Inputs.Inputs_Type values - end Inputs; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 9e31e8374..de1a18deb 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -39,7 +39,6 @@ with ALI_Files; use ALI_Files; with Coverage; use Coverage; with Coverage_Options; with Hex_Images; use Hex_Images; -with Inputs; use Inputs; with Outputs; use Outputs; with Paths; use Paths; with SCOs; @@ -4514,10 +4513,9 @@ package body Instrument.C is Filename : String) is Cmdline_Opts : constant String_Vectors.Vector := - To_String_Vector - (case C_Family_Language (Instrumenter.Language) is - when C_Language => C_Opts, - when CPP_Language => CPP_Opts); + (case C_Family_Language (Instrumenter.Language) is + when C_Language => C_Opts, + when CPP_Language => CPP_Opts); Prj_Options : String_Vectors.Vector; begin -- Grab the options from the project description. Note that the project diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 1ae587c53..0f719d39c 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -187,7 +187,7 @@ package body Project is procedure Build_Prj_Map with Pre => Is_Project_Loaded; -- Add entries in Prj_Map for all relevant projects - procedure Build_Unit_Map (Override_Units : Inputs.Inputs_Type); + procedure Build_Unit_Map (Override_Units : String_Vectors.Vector); -- Add entries in Unit_Map for all units of interest procedure List_From_Project @@ -826,10 +826,8 @@ package body Project is -- Build_Unit_Map -- -------------------- - procedure Build_Unit_Map (Override_Units : Inputs.Inputs_Type) is - use type Ada.Containers.Count_Type; - - Units_Specified : constant Boolean := Length (Override_Units) > 0; + procedure Build_Unit_Map (Override_Units : String_Vectors.Vector) is + Units_Specified : constant Boolean := not Override_Units.Is_Empty; -- Whether the user requested a specific set of units of interest -- through the --units command-line argument. @@ -840,22 +838,10 @@ package body Project is Has_Matcher : Boolean; -- Matcher for the list of units of interest - procedure Add_Pattern (Item : String); - -- Add the pattern Item lower-cased to Unit_Patterns - procedure Process_Project (Project : Project_Type); -- Compute the list of units of interest in Project and call -- Enumerate_In_Single_Projects for Project. - ----------------- - -- Add_Pattern -- - ----------------- - - procedure Add_Pattern (Item : String) is - begin - Unit_Patterns.Append (+To_Lower (Item)); - end Add_Pattern; - --------------------- -- Process_Project -- --------------------- @@ -997,7 +983,9 @@ package body Project is -- First, lower case all the units / patterns specified on the command -- line. - Iterate (Override_Units, Add_Pattern'Access); + for Pattern of Override_Units loop + Unit_Patterns.Append (+To_Lower (+Pattern)); + end loop; -- Then, create a regexp matching all the patterns specified. -- Regardless of the current platform, the casing of unit names is not @@ -1321,7 +1309,8 @@ package body Project is -- Compute_Units_Of_Interest -- ------------------------------- - procedure Compute_Units_Of_Interest (Override_Units : Inputs.Inputs_Type) is + procedure Compute_Units_Of_Interest (Override_Units : String_Vectors.Vector) + is begin Build_Prj_Map; Build_Unit_Map (Override_Units); diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 17bf9a84b..ea51b9f7c 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -25,7 +25,6 @@ with GNAT.Strings; use GNAT.Strings; with GNATCOLL.Projects; use GNATCOLL.Projects; with GNATCOLL.VFS; -with Inputs; with Files_Table; with Strings; use Strings; with Switches; use Switches; @@ -105,7 +104,8 @@ package Project is -- interest. This is meant to be used only in the gnatcov driver, where we -- just need to determine the target. - procedure Compute_Units_Of_Interest (Override_Units : Inputs.Inputs_Type); + procedure Compute_Units_Of_Interest + (Override_Units : String_Vectors.Vector); -- Compute the sets of projects and units of interest from Add_Project, -- Override_Units and project files data. -- diff --git a/tools/gnatcov/rundrv-config.adb b/tools/gnatcov/rundrv-config.adb index f4bf26f57..b4d4c4b6c 100644 --- a/tools/gnatcov/rundrv-config.adb +++ b/tools/gnatcov/rundrv-config.adb @@ -19,12 +19,9 @@ with GNAT.Regpat; use GNAT.Regpat; with Rundrv.Handlers; use Rundrv.Handlers; -with Strings; use Strings; package body Rundrv.Config is - use all type Unbounded_String; - procedure Get_Builtin_Driver (Context : Context_Type; Found : out Boolean; diff --git a/tools/gnatcov/rundrv-handlers.adb b/tools/gnatcov/rundrv-handlers.adb index 950800209..78add4f84 100644 --- a/tools/gnatcov/rundrv-handlers.adb +++ b/tools/gnatcov/rundrv-handlers.adb @@ -26,7 +26,6 @@ with Arch; with Coverage; use Coverage; with Paths; use Paths; with Support_Files; -with Strings; use Strings; with Switches; use Switches; package body Rundrv.Handlers is diff --git a/tools/gnatcov/rundrv.adb b/tools/gnatcov/rundrv.adb index 7c74c3241..b61afc2ef 100644 --- a/tools/gnatcov/rundrv.adb +++ b/tools/gnatcov/rundrv.adb @@ -29,15 +29,12 @@ with Execs_Dbase; with Outputs; with Qemu_Traces; with Rundrv.Config; use Rundrv.Config; -with Strings; use Strings; with Subprocesses; use Subprocesses; with Traces_Elf; with Traces_Files; use Traces_Files; package body Rundrv is - use all type Unbounded_String; - package Env renames Ada.Environment_Variables; Native_Warning : constant String := diff --git a/tools/gnatcov/rundrv.ads b/tools/gnatcov/rundrv.ads index 320731888..54b54afcd 100644 --- a/tools/gnatcov/rundrv.ads +++ b/tools/gnatcov/rundrv.ads @@ -18,11 +18,13 @@ with GNAT.Strings; use GNAT.Strings; -with Inputs; with Logging; +with Strings; use Strings; package Rundrv is + use all type Unbounded_String; + Rundrv_Trace : constant Logging.GNATCOLL_Trace := Logging.Create_Trace ("RUNDRV"); @@ -30,7 +32,7 @@ package Rundrv is type SO_Set_Type (Kind : SO_Set_Kind := Some_SO) is record case Kind is when None => null; - when Some_SO => Set : Inputs.Inputs_Type; + when Some_SO => Set : String_Vectors.Vector; when All_SO => null; end case; end record; diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 93fe284b7..925d2ae97 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -20,7 +20,9 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Command_Line; with Ada.Exceptions; with Ada.Strings.Fixed; +with Ada.Text_IO; use Ada.Text_IO; +with Inputs; with Outputs; use Outputs; with Project; use Project; @@ -81,16 +83,78 @@ package body Switches is end if; end Copy_Arg; + --------------------- + -- Expand_Argument -- + --------------------- + + function Expand_Argument (Argument : String) return String_Vectors.Vector is + Result : String_Vectors.Vector; + + procedure Process (Argument : String); + + ------------- + -- Process -- + ------------- + + procedure Process (Argument : String) is + begin + if Argument'Length = 0 then + return; + end if; + + if Argument (Argument'First) /= '@' then + Result.Append (+Argument); + elsif Argument'Length > 1 then + if Argument (Argument'First + 1) /= '@' then + declare + File_Name : constant String := + Argument (Argument'First + 1 .. Argument'Last); + begin + Inputs.Read_List_From_File (File_Name, Process'Access); + exception + when Name_Error | Status_Error => + Fatal_Error ("cannot open input list: " & File_Name); + end; + else + Result.Append (+Argument (Argument'First + 1 .. Argument'Last)); + end if; + end if; + end Process; + + -- Start of processing for Expand_Argument + + begin + Process (Argument); + return Result; + end Expand_Argument; + + ------------------------------ + -- Append_Expanded_Argument -- + ------------------------------ + + procedure Append_Expanded_Argument + (Argument : String; List : in out String_Vectors.Vector) is + begin + List.Append_Vector (Expand_Argument (Argument)); + end Append_Expanded_Argument; + ------------------- -- Copy_Arg_List -- ------------------- procedure Copy_Arg_List (Option : String_List_Options; - List : in out Inputs.Inputs_Type) is + List : in out String_Vectors.Vector) is + begin + Copy_Arg_List (Args.String_List_Args (Option), List); + end Copy_Arg_List; + + procedure Copy_Arg_List + (Args : String_Vectors.Vector; + List : in out String_Vectors.Vector) is begin - for Arg of Args.String_List_Args (Option) loop - Inputs.Add_Input (List, +Arg); + for Arg of Args loop + Append_Expanded_Argument (+Arg, List); end loop; end Copy_Arg_List; diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 240a41966..a7d179a99 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -22,7 +22,6 @@ with GNAT.Strings; use GNAT.Strings; with Calendar_Utils; use Calendar_Utils; with Command_Line; use Command_Line; -with Inputs; with Logging; with SC_Obligations; with Strings; use Strings; @@ -59,10 +58,33 @@ package Switches is -- Copy the string for Option into Variable. If the option is present, this -- allocates a new string in Variable. + function Expand_Argument (Argument : String) return String_Vectors.Vector; + -- If Argument starts with a '@' character, consider that it is a response + -- file: read it and return its contents as a vector, assuming the + -- following format: + -- + -- * lines starting with '#' are ignored, + -- * lines that start with '@@' are included with the leading '@' removed, + -- * the other lines that start with '@' are treated as filenames and + -- processed recursively, + -- * one item per line, + -- * no blanks allowed. + -- + -- Otherwise, just return a 1-element vector to contain Argument. + + procedure Append_Expanded_Argument + (Argument : String; List : in out String_Vectors.Vector); + -- Expand Argument and append the resulting arguments to List + procedure Copy_Arg_List (Option : String_List_Options; - List : in out Inputs.Inputs_Type); - -- Copy the list of strings referenced in Option to the List input list + List : in out String_Vectors.Vector); + procedure Copy_Arg_List + (Args : String_Vectors.Vector; + List : in out String_Vectors.Vector); + -- Copy the list of strings referenced in Option to the List input list, + -- expanding arguments that start with '@' according to rules described in + -- Inputs.Expand_Argument. ---------------------------- -- Miscellaneous switches -- @@ -143,11 +165,11 @@ package Switches is type Separated_Source_Coverage_Type is (None, Routines, Instances); Separated_Source_Coverage : Separated_Source_Coverage_Type := None; - Units_Inputs : Inputs.Inputs_Type; + Units_Inputs : String_Vectors.Vector; -- List of names for requested units of interest - C_Opts : Inputs.Inputs_Type; - CPP_Opts : Inputs.Inputs_Type; + C_Opts : String_Vectors.Vector; + CPP_Opts : String_Vectors.Vector; type Any_Language is (All_Languages, Ada_Language, C_Language, CPP_Language); diff --git a/tools/gnatcov/traces_files.ads b/tools/gnatcov/traces_files.ads index 59d272b9a..c0f20daae 100644 --- a/tools/gnatcov/traces_files.ads +++ b/tools/gnatcov/traces_files.ads @@ -16,6 +16,7 @@ -- of the license. -- ------------------------------------------------------------------------------ +with Ada.Containers.Vectors; with Interfaces; use Interfaces; private with System.Storage_Elements; @@ -255,6 +256,17 @@ package Traces_Files is procedure Dump_Raw_Trace_File (Filename : String); -- Raw dump of a trace file + type Requested_Trace is record + Filename : Unbounded_String; + Executable : Unbounded_String; + end record; + -- Trace file that is passed to gnatcov for analysis. Filename designates + -- the trace file, and, if non-empty, Executable overrides the binary used + -- for decision mapping when analyzing this trace file. + + package Requested_Trace_Vectors is new Ada.Containers.Vectors + (Positive, Requested_Trace); + private package SSE renames System.Storage_Elements; From d68f72206a6810d9be3e8188f6149b3e93f66470 Mon Sep 17 00:00:00 2001 From: Rowan Walshe Date: Mon, 11 Dec 2023 16:22:54 +0000 Subject: [PATCH 0550/1483] Insert the GNATfuzz documentation earlier This means it appears before the appendix, and before the section about integrating GNATtest with GNATfuzz. Fixes eng/das/fuzz/gnatfuzz#663 --- doc/Makefile | 8 ++++---- doc/index.rst | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/doc/Makefile b/doc/Makefile index 12fac6bd9..7a67f6cab 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -41,7 +41,7 @@ prepare-installdir.%: # expect to have a line like << master_doc = "bla" or 'bla' >> someplace. MASTER_DOC=$(shell sed -n -e \ - "s/master_doc.*=[^'\"]*['\"]\([^'\"]*\).*/\1/p" conf.py) + "s/master_doc.*=[^'\"]*['\"]\([^'\"]*\).*/\1/p" conf.py) # Make sure the PDF we install has a meaningful name and leave the html # alone so internal hyperlinks to the toplevel page remain functional. @@ -107,9 +107,9 @@ prepare-builddir.%: $(PREPARE_IMAGES) # bits to find it in index.rst. look_for_gnatfuzz: if [ -e "gnatfuzz/gnatfuzz_part.rst" ]; then \ - if [ "`grep "gnatfuzz" index.rst`" = "" ]; then \ - echo " gnatfuzz/gnatfuzz_part" >> index.rst; \ - fi; \ + if [ "`grep "gnatfuzz" index.rst`" = "" ]; then \ + sed -i -e 's/\.\. Optional GNATfuzz part/ gnatfuzz\/gnatfuzz_part/g' index.rst; \ + fi; \ fi build.pdf: look_for_gnatfuzz prepare-builddir.pdf diff --git a/doc/index.rst b/doc/index.rst index 91d33436c..552703095 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -8,6 +8,9 @@ gnatcov/gnatcov_part gnattest/gnattest_part + +.. Optional GNATfuzz part + integration/integration_part .. Appendix part - manual numbering From 5f8f76f13ae7cf30fb0082ce1e6341b1d11a6769 Mon Sep 17 00:00:00 2001 From: Rowan Walshe Date: Mon, 11 Dec 2023 16:36:16 +0000 Subject: [PATCH 0551/1483] Build docs during CI when updated --- .gitlab-ci.yml | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 392c96dd4..d59282f84 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -68,6 +68,28 @@ build: paths: - $PACKAGE_BASE_NAME +build_docs: + stage: build + services: + - image:e3 + rules: + - if: $CI_PIPELINE_SOURCE == "merge_request_event" || ($CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH) + changes: + - doc/**/* + when: always + script: + - unset GITLAB_TOKEN + - generic_anod_ci + - . /tmp/ci_env.sh + - anod build gnatdas-doc --latest + - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/gnatdas-doc/install/share/doc/gnatdas/ $CI_PROJECT_DIR + artifacts: + when: + always + paths: + - gnatdas/pdf/gnatdas.pdf + - gnatdas/html + build_community: interruptible: true services: From f0c7ac4a0fc4382924bf137b08c4121dfa31283d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 8 Dec 2023 16:26:43 +0100 Subject: [PATCH 0552/1483] command_line.ads: make the --files option public This option is meant to be user facing, and is even mentionned in the synopsis for the setup-integration command, so change it to not be an internal option. --- tools/gnatcov/command_line.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 2ecc28800..6cb46873b 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -1296,7 +1296,7 @@ package Command_Line is | Cmd_Instrument_Main | Cmd_Setup_Integration => True, others => False), - Internal => True), + Internal => False), Opt_Shared_Object => Create (Long_Name => "--shared-object", From d32136382f5623bf86e2e9b6cfc1d74df40ebcca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 8 Dec 2023 16:30:54 +0100 Subject: [PATCH 0553/1483] Integrated instr: Recognize positional static libs on command line gnatcov only used to recognize static libraries that were specified with the -l switch on link command lines. This change also makes it recognize *.a files that are passed as positional arguments on the command line. --- .../cmake_lib/CMakeLists.txt | 9 +++ .../cmake_lib/src/lib.c | 7 +++ .../cmake_lib/src/lib.h | 6 ++ .../cmake_lib/src/main.c | 10 ++++ .../cmake_lib/test.py | 60 +++++++++++++++++++ tools/gnatcov/compiler_wrappers-gcc.adb | 35 +++++++---- 6 files changed, 116 insertions(+), 11 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/cmake_lib/CMakeLists.txt create mode 100644 testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.c create mode 100644 testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.h create mode 100644 testsuite/tests/integrated_instrumentation/cmake_lib/src/main.c create mode 100644 testsuite/tests/integrated_instrumentation/cmake_lib/test.py diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/CMakeLists.txt b/testsuite/tests/integrated_instrumentation/cmake_lib/CMakeLists.txt new file mode 100644 index 000000000..f7753fa2e --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/CMakeLists.txt @@ -0,0 +1,9 @@ +project(HelloWorld) +cmake_minimum_required(VERSION 3.0) + +# Create a static library from the sources in src +add_library(my_lib STATIC src/lib.c) + +# Create an executable using the library previously declared +add_executable(hello_world src/main.c) +target_link_libraries(hello_world my_lib) diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.c b/testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.c new file mode 100644 index 000000000..184eb25dc --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.c @@ -0,0 +1,7 @@ +#include "lib.h" + +int +identity (int x) +{ + return x; +} diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.h b/testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.h new file mode 100644 index 000000000..5bc6dd5af --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/src/lib.h @@ -0,0 +1,6 @@ +#ifndef LIB_H_ +#define LIB_H_ + +int identity (int x); + +#endif // LIB_H_ diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/src/main.c b/testsuite/tests/integrated_instrumentation/cmake_lib/src/main.c new file mode 100644 index 000000000..d9036b833 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/src/main.c @@ -0,0 +1,10 @@ +#include + +#include "lib.h" + +int +main () +{ + printf ("Hello world!\n"); + return identity (0); +} diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/test.py b/testsuite/tests/integrated_instrumentation/cmake_lib/test.py new file mode 100644 index 000000000..e53833d69 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/test.py @@ -0,0 +1,60 @@ +""" +Test that gnatcov correctly takes into account instrumented units present +in a static library passed as a positional argument on the link command line. +This is what is done by CMake when defining a library, then using it in an +executable in the same CMakeLists.txt. +""" + +import os +import os.path + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Setup the instrumentation process +xcov( + [ + "setup-integration", + f"--files={os.path.join(cwd, '..', 'src', 'main.c')}", + f"--files={os.path.join(cwd, '..', 'src', 'lib.c')}", + "--compilers=gcc", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +compiler_wrapper = os.path.join(cwd, 'gcc') +cmdrun(["cmake", "..", f"-DCMAKE_C_COMPILER={compiler_wrapper}"], for_pgm=False) +cmdrun(["make"], for_pgm=False) + +# Run the executable +cmdrun(["hello_world"], for_pgm=True) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=main.c.sid", + "--sid=lib.c.sid", + "-axcov", + srctracename_for("main"), + ] +) +check_xcov_reports( + "*.xcov", + { + "main.c.xcov": {"+": {8, 9}}, + "lib.c.xcov": {"+": {6}}, + } +) + +thistest.result() diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 61ff38402..3d90c7be9 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -519,6 +519,8 @@ procedure Compiler_Wrappers.Gcc is else Result.Object_Files.Append (Arg); end if; + elsif Ends_With (Arg, ".a") then + Result.Libraries.Append (Arg); end if; end; end loop; @@ -631,17 +633,28 @@ procedure Compiler_Wrappers.Gcc is Ada.Environment_Variables.Value ("LIBRARY_PATH", "")); for Library of Command.Libraries loop - declare - use type GNAT.OS_Lib.String_Access; - Library_File : GNAT.OS_Lib.String_Access := - GNAT.OS_Lib.Locate_Regular_File - ("lib" & (+Library) & ".a", +Library_Path); - begin - if Library_File /= null then - Result.Union (Coverage_Buffer_Symbols (Library_File.all)); - GNAT.OS_Lib.Free (Library_File); - end if; - end; + + if Ends_With (Library, ".a") then + + -- Library filename on the command line, no need to look it up + + Result.Union (Coverage_Buffer_Symbols (+Library)); + else + -- Simple library name passed to the -l option, search the + -- actual file on the library path. + + declare + use type GNAT.OS_Lib.String_Access; + Library_File : GNAT.OS_Lib.String_Access := + GNAT.OS_Lib.Locate_Regular_File + ("lib" & (+Library) & ".a", +Library_Path); + begin + if Library_File /= null then + Result.Union (Coverage_Buffer_Symbols (Library_File.all)); + GNAT.OS_Lib.Free (Library_File); + end if; + end; + end if; end loop; end; From a2b52b0281cfd08921005aab59877afec249eb1c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 8 Dec 2023 09:46:50 +0100 Subject: [PATCH 0554/1483] CI: assign 16 cores to machines that run bottleneck jobs --- .gitlab-ci.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d59282f84..e8f521cd1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -42,7 +42,7 @@ build: interruptible: true services: - image:gnatcov - - cpu:8 + - cpu:16 - mem:16 stage: build script: @@ -163,7 +163,7 @@ test_bin_traces: interruptible: true services: - image:gnatcov - - cpu:8 + - cpu:16 - mem:16 stage: test script: @@ -185,7 +185,7 @@ test_src_traces: interruptible: true services: - image:gnatcov - - cpu:8 + - cpu:16 - mem:16 stage: test script: @@ -207,7 +207,7 @@ test_spark: interruptible: true services: - image:gnatcov - - cpu:8 + - cpu:16 - mem:16 stage: test script: From 2782834eb2b0f5b136c545f7e58d381e12c33bba Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 12 Dec 2023 14:01:53 +0100 Subject: [PATCH 0555/1483] gnatcov doc: state that GPR_PROJECT_PATH needs an update with --prefix --- doc/gnatcov/src_traces.rst | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index bd06241ff..bfbcf8855 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -83,7 +83,16 @@ another location, pass the :cmd-option:`--prefix` option: .. code-block:: sh - gnatcov setup --prefix=/usr/local + gnatcov setup --prefix=/usr/custom + +When installing the coverage runtime to a non-default location, tools that +process project files must be instructed how to find the coverage runtime +project file that is installed. To achieve this, update the +``GPR_PROJECT_PATH`` environment variable: + +.. code-block:: sh + + export GPR_PROJECT_PATH=$GPR_PROJECT_PATH:/usr/custom/share/gpr Multiple runtimes in the same prefix From 42c3745e7191fab68533997ff2e43ca877c05572 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 4 Dec 2023 17:44:15 +0100 Subject: [PATCH 0556/1483] manual dump: rename `Done` formal to `Has_Manual_Indication` And make it an `out` parameter, rather than an `in out`. --- tools/gnatcov/instrument-ada_unit.adb | 17 +++++++++-------- tools/gnatcov/instrument-ada_unit.ads | 8 ++++---- tools/gnatcov/instrument-c.adb | 12 ++++++------ tools/gnatcov/instrument-c.ads | 8 ++++---- tools/gnatcov/instrument-common.ads | 11 +++++++---- tools/gnatcov/instrument-projects.adb | 6 +++--- 6 files changed, 33 insertions(+), 29 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 6a3f37000..bd43a44cb 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -7799,10 +7799,10 @@ package body Instrument.Ada_Unit is ------------------------------------ overriding procedure Replace_Manual_Dump_Indication - (Self : in out Ada_Instrumenter_Type; - Done : in out Boolean; - Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info) + (Self : in out Ada_Instrumenter_Type; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info; + Has_Manual_Indication : out Boolean) is Instrumented_Filename : constant String := +(Prj.Output_Dir & "/" & GNATCOLL.VFS."+" (Source.File.Base_Name)); @@ -7853,7 +7853,7 @@ package body Instrument.Ada_Unit is -- The pragma statement to be replaced by the actual call -- to Dump_Buffers has been found. - if not Done then + if not Has_Manual_Indication then Start_Rewriting (Rewriter, Self, Prj, File_To_Search); end if; @@ -7870,7 +7870,7 @@ package body Instrument.Ada_Unit is begin -- Add the with clause only once in the file - if not Done then + if not Has_Manual_Indication then Insert_Last (Handle (Unit.Root.As_Compilation_Unit.F_Prelude), Create_From_Template @@ -7891,7 +7891,7 @@ package body Instrument.Ada_Unit is Rule => Call_Stmt_Rule)); end; - Done := True; + Has_Manual_Indication := True; return Over; end if; end; @@ -7913,11 +7913,12 @@ package body Instrument.Ada_Unit is -- initialized which will lead to finalization issues. To avoid this, -- make sure it is set to No_Rewriting_Handle. + Has_Manual_Indication := False; Rewriter.Handle := No_Rewriting_Handle; Unit.Root.Traverse (Find_And_Replace_Pragma'Access); - if Done then + if Has_Manual_Indication then Create_Directory_If_Not_Exists (GNATCOLL.VFS."+" (Source.Project.Object_Dir.Base_Dir_Name)); Create_Directory_If_Not_Exists (+Prj.Output_Dir); diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 686b337af..3f8edeb49 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -86,10 +86,10 @@ package Instrument.Ada_Unit is Prj : Prj_Desc); overriding procedure Replace_Manual_Dump_Indication - (Self : in out Ada_Instrumenter_Type; - Done : in out Boolean; - Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info); + (Self : in out Ada_Instrumenter_Type; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info; + Has_Manual_Indication : out Boolean); -- Once the instrumentation has finished, if the dump trigger is "manual" -- we expect the user to have indicated the place where a call to the -- manual dump buffers procedure should be inserted by the pragma diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index de1a18deb..f97c7548d 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3838,10 +3838,10 @@ package body Instrument.C is ------------------------------------ overriding procedure Replace_Manual_Dump_Indication - (Self : in out C_Family_Instrumenter_Type; - Done : in out Boolean; - Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info) + (Self : in out C_Family_Instrumenter_Type; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info; + Has_Manual_Indication : out Boolean) is use GNATCOLL.VFS; Orig_Filename : constant String := +Source.File.Full_Name; @@ -3902,7 +3902,7 @@ package body Instrument.C is if Matches (0) /= No_Match then Contents := Contents & Dump_Procedure & "();"; - Done := True; + Has_Manual_Indication := True; else Contents := Contents & Line; end if; @@ -3913,7 +3913,7 @@ package body Instrument.C is Ada.Text_IO.Close (File); - if Done then + if Has_Manual_Indication then -- Content now holds the text of the original file with calls to -- the manual dump procedure where the indications and its extern -- declaration were. Replace the original content of the file with diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index ee8a78dc9..cbf5164f0 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -54,10 +54,10 @@ package Instrument.C is Prj : Prj_Desc); overriding procedure Replace_Manual_Dump_Indication - (Self : in out C_Family_Instrumenter_Type; - Done : in out Boolean; - Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info); + (Self : in out C_Family_Instrumenter_Type; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info; + Has_Manual_Indication : out Boolean); -- Preprocess Source and look through the text content of the preprocessed -- file looking for manual dump indications. The C-like languages, the -- expected indication is the comment alone on its line: diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index eca9c9f0a..f184c16a7 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -486,14 +486,17 @@ package Instrument.Common is -- the instrumented source files. procedure Replace_Manual_Dump_Indication - (Self : in out Language_Instrumenter; - Done : in out Boolean; - Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info) is null; + (Self : in out Language_Instrumenter; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info; + Has_Manual_Indication : out Boolean) is null; -- Look for the pragma (for Ada) or comment (for C family languages) -- indicating where the user wishes to the buffers to be dumped in Source. -- When found, replace it with a call to the buffers dump procedure defined -- in the dump helper unit. + -- + -- Has_Manual_Indication indicates whether a manual dump indication was + -- found - and replaced with a call to dump buffers - in the given source. function New_File (Prj : Prj_Desc; Name : String) return String; diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 59d6e7680..69e897488 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -865,9 +865,9 @@ is Contained_Indication : Boolean := False; begin Instrumenter.Replace_Manual_Dump_Indication - (Contained_Indication, - Prj_Info.Desc, - Source); + (Prj_Info.Desc, + Source, + Contained_Indication); if Contained_Indication and then not Is_Root_Prj then From 547b3687af0e9e4ab71c77f35159df65e2c54ef5 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 4 Dec 2023 17:47:24 +0100 Subject: [PATCH 0557/1483] manual dump: fix performance issue When looking for dump trigger indications in a C/C++ source, we were so far reading the source file contents to an unbounded string, which is very inefficient for large files. Use the GNATCOLL.Mmap API instead to avoid the costly string copies/allocations. This was noticed when instrumenting gnatcov with the manual dump-trigger, and notably when trying to look for a manual dump indication in the `clang-wrapper.cc` file. The preprocessed version of a C++ file including parts of the standard library can be quite large, which incurred this performance slow down. --- tools/gnatcov/instrument-c.adb | 106 ++++++++++++++++++++++----------- 1 file changed, 71 insertions(+), 35 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index f97c7548d..9541e1308 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -17,7 +17,6 @@ ------------------------------------------------------------------------------ with Ada.Characters.Handling; -with Ada.Characters.Latin_1; with Ada.Containers; use Ada.Containers; with Ada.Directories; use Ada.Directories; with Ada.Text_IO; use Ada.Text_IO; @@ -30,6 +29,7 @@ with GNAT.OS_Lib; use GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; with GNATCOLL.VFS; +with GNATCOLL.Mmap; with Interfaces; use Interfaces; with Interfaces.C; use Interfaces.C; @@ -3851,16 +3851,15 @@ package body Instrument.C is declare Options : Analysis_Options; PP_Filename : Unbounded_String; - File : Ada.Text_IO.File_Type; Dummy_Main : Compilation_Unit_Part; Dump_Pat : constant Pattern_Matcher := - Compile ("^[\t ]*\/\* GNATCOV_DUMP_BUFFERS \*\/[ \t]*"); + Compile + ("^[\t ]*\/\* GNATCOV_DUMP_BUFFERS \*\/[ \t]*", + Flags => Multiple_Lines); Matches : Match_Array (0 .. 1); Dump_Procedure : constant String := Dump_Procedure_Symbol (Main => Dummy_Main, Manual => True, Prj_Name => +Prj.Prj_Name); - Contents : Unbounded_String := - +("extern void " & Dump_Procedure & " (void);"); begin -- Preprocess the source, keeping the comment to look for the manual -- dump indication later. @@ -3887,47 +3886,84 @@ package body Instrument.C is end loop; end; - -- Look for the manual dump indication in the preprocessed file + -- Look for the manual dump indication in the preprocessed file. Use + -- the GNATCOLL.Mmap API to map the file contents in memory, as we + -- may need to rewrite it to the source file, with the manual dump + -- indication replaced by an actual call to the dump buffers + -- function. - Ada.Text_IO.Open - (File => File, - Mode => In_File, - Name => (+PP_Filename)); + declare + use GNATCOLL.Mmap; + File : Mapped_File := Open_Read (To_String (PP_Filename)); + Region : Mapped_Region := Read (File); + Raw_Str : constant Str_Access := Data (Region); + Raw_Str_Last : constant Natural := Last (Region); + Str : String renames Raw_Str (1 .. Raw_Str_Last); + + Tmp_Filename : constant String := +PP_Filename & ".tmp"; + Output_File : Ada.Text_IO.File_Type; + -- Temporary file containing the new version of the original file, + -- with inserted calls to dump buffers. The original file is then + -- overwritten by this temporary file. + + Index : Positive := 1; + -- Starting index, or last index of the previous match in the + -- original file. - while not Ada.Text_IO.End_Of_File (File) loop - declare - Line : constant String := Get_Line (File); - begin - Match (Dump_Pat, Line, Matches); + begin + Has_Manual_Indication := False; + while Index in Str'Range loop + Match (Dump_Pat, Str (Index .. Str'Last), Matches); + exit when Matches (0) = No_Match; - if Matches (0) /= No_Match then - Contents := Contents & Dump_Procedure & "();"; + -- Open the output file if this is the first match we find, + -- then forward the source code that appear before the match + -- unchanged. + + if not Has_Manual_Indication then + Create (Output_File, Out_File, Tmp_Filename); Has_Manual_Indication := True; - else - Contents := Contents & Line; end if; + Put (Output_File, Str (Index .. Matches (0).First)); - Contents := Contents & Ada.Characters.Latin_1.LF; - end; - end loop; + -- Replace the match with the call to the dump procedure + + Put (Output_File, Dump_Procedure & "();"); + Index := Matches (0).Last + 1; + end loop; - Ada.Text_IO.Close (File); + -- If we had a manual indication, and thus wrote a modified source + -- file, overwrite the original source file with it. - if Has_Manual_Indication then - -- Content now holds the text of the original file with calls to - -- the manual dump procedure where the indications and its extern - -- declaration were. Replace the original content of the file with - -- Content. + if Has_Manual_Indication then + declare + Tmp_File : constant Virtual_File := Create (+Tmp_Filename); + Success : Boolean; + begin + -- Flush the rest of the file contents - Ada.Text_IO.Open - (File => File, - Mode => Out_File, - Name => (+PP_Filename)); + Ada.Text_IO.Put (Output_File, Str (Index .. Str'Last)); + Ada.Text_IO.Close (Output_File); - Ada.Text_IO.Put_Line (File, (+Contents)); + Free (Region); + Close (File); - Ada.Text_IO.Close (File); - end if; + -- Overwrite the original file with its newer version + + Tmp_File.Rename + (Full_Name => Create (+(+PP_Filename)), + Success => Success); + if not Success then + Outputs.Fatal_Error + ("Failed to replace manual dump indication for Source " + & (+Source.File.Full_Name)); + end if; + end; + else + Free (Region); + Close (File); + end if; + end; end; end Replace_Manual_Dump_Indication; From 1d4c2015317223eb680ab7d279ca323a3ee7ffe9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 13 Dec 2023 10:05:23 +0000 Subject: [PATCH 0558/1483] Setup: kill "object/library directory not found" warnings --- testsuite/tests/185-setup-warnings/test.py | 19 +++++++++++++++++++ tools/gnatcov/setup_rts.adb | 8 +++++--- 2 files changed, 24 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/185-setup-warnings/test.py diff --git a/testsuite/tests/185-setup-warnings/test.py b/testsuite/tests/185-setup-warnings/test.py new file mode 100644 index 000000000..6830b8cc0 --- /dev/null +++ b/testsuite/tests/185-setup-warnings/test.py @@ -0,0 +1,19 @@ +""" +Check that "gnatcov setup" does not emit warnings about missing object/library +directories when loading the "gnatcov_rts.gpr" project file. +""" + +import os +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import xcov + + +tmp = Wdir("tmp_") + +filename = "setup.log" +xcov(["setup", "-q"], out=filename, force_project_args=True) +thistest.fail_if_not_equal("gnatcov setup output", "", contents_of(filename)) +thistest.result() diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 0341e15e0..553626413 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -206,9 +206,10 @@ package body Setup_RTS is GPR2.Project.Configuration.Load (F); begin Project.Load - (Filename => PF, - Context => Context, - Config => Config); + (Filename => PF, + Context => Context, + Absent_Dir_Error => GPR2.Project.Tree.No_Error, + Config => Config); exception when GPR2.Project_Error => null; @@ -233,6 +234,7 @@ package body Setup_RTS is Project.Load_Autoconf (Filename => PF, Context => Context, + Absent_Dir_Error => GPR2.Project.Tree.No_Error, Target => Actual_Target, Language_Runtimes => RTS_Map); exception From 637977587524e40f783c70057a7e0f2d5ad198b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 12 Dec 2023 14:05:55 +0100 Subject: [PATCH 0559/1483] altrun/ccg_native: Fix incorrect Ada runtime library path The pre_testsuite.py script created the Ada runtime library file in the compiler installation tree, when it was meant to be created in the altrun directory. This change fixes this. --- testsuite/altrun/ccg_native/pre_testsuite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/altrun/ccg_native/pre_testsuite.py b/testsuite/altrun/ccg_native/pre_testsuite.py index b70e10839..24e694b5e 100644 --- a/testsuite/altrun/ccg_native/pre_testsuite.py +++ b/testsuite/altrun/ccg_native/pre_testsuite.py @@ -212,6 +212,6 @@ def prepare_rts(): # Create the library per se. run( - ["ar", "rcs", os.path.join(adainclude_dir, "libgnat.a")] + all_obj_files, + ["ar", "rcs", os.path.join(local_rt, "libgnat.a")] + all_obj_files, what="archival of the Ada runtime", ) From 4a3219916b606d927b0f2a6f523ccf8559e88241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 12 Dec 2023 14:10:37 +0100 Subject: [PATCH 0560/1483] altrun/ccg_native: Fix various issues related to executable extensions Namely, adding the correct extension to the executables invoked in Windows, and stripping the executable extension when looking for an altrun hook. --- testsuite/SUITE/tutils.py | 5 ++++- testsuite/altrun/ccg_native/cgprbuild.py | 10 ++++++---- testsuite/altrun/ccg_native/pre_testsuite.py | 10 ++++++---- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index bb613e46a..e8a366979 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -291,7 +291,10 @@ def gprbuild(project, # Now cleanup, do build and check status thistest.cleanup(project) - builder = thistest.suite_gprpgm_for(os.path.basename(BUILDER.BASE_COMMAND)) + # lookup the hook for the executable name without extension + builder = thistest.suite_gprpgm_for( + os.path.splitext(os.path.basename(BUILDER.BASE_COMMAND))[0] + ) if builder is None: builder = BUILDER.BASE_COMMAND diff --git a/testsuite/altrun/ccg_native/cgprbuild.py b/testsuite/altrun/ccg_native/cgprbuild.py index 0c5ba38cc..5fe0d8d97 100755 --- a/testsuite/altrun/ccg_native/cgprbuild.py +++ b/testsuite/altrun/ccg_native/cgprbuild.py @@ -35,11 +35,13 @@ def get_attr(obj, attr_name, idx=0): def run(cmd, what): """ - Run the command represented by cmd in a subprocess. If the exit status is - not success and ignore_failure is True, print f"{what} failed" followed by - the command output on the standard output and exit with an error. - Otherwise, return the output of the command execution. + Run the command represented by cmd in a subprocess, appending the + executable extension for the platform to the first element of cmd. If the + exit status is not success and ignore_failure is True, print + f"{what} failed" followed by the command output on the standard output and + exit with an error. Otherwise, return the output of the command execution. """ + cmd[0] = cmd[0] + Platform.get().os.exeext p = Run(cmd) if p.status != 0: print(f"{what} failed:") diff --git a/testsuite/altrun/ccg_native/pre_testsuite.py b/testsuite/altrun/ccg_native/pre_testsuite.py index 24e694b5e..0adbd930b 100644 --- a/testsuite/altrun/ccg_native/pre_testsuite.py +++ b/testsuite/altrun/ccg_native/pre_testsuite.py @@ -28,11 +28,13 @@ def run(cmd, what): """ - Run the command represented by cmd in a subprocess. If the exit status is - not success and ignore_failure is True, print f"{what} failed" followed by - the command output on the standard output and exit with an error. - Otherwise, return the output of the command execution. + Run the command represented by cmd in a subprocess, appending the + executable extension for the platform to the first element of cmd. If the + exit status is not success and ignore_failure is True, print + f"{what} failed" followed by the command output on the standard output and + exit with an error. Otherwise, return the output of the command execution. """ + cmd[0] = cmd[0] + exeext p = Run(cmd) if p.status != 0: print(f"{what} failed:") From 6f03d874dc58c555a7f22a4da82a445bdbf40750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 12 Dec 2023 16:47:11 +0100 Subject: [PATCH 0561/1483] tutils.py: run all python commands through a python interpreter... Instead of relying on the shebang to find it, as this is not supported on Windows. --- testsuite/SUITE/tutils.py | 12 +++++++++++- testsuite/altrun/ccg_native/cgprbuild.py | 2 +- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index e8a366979..4a5fe2f26 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -296,12 +296,22 @@ def gprbuild(project, os.path.splitext(os.path.basename(BUILDER.BASE_COMMAND))[0] ) + has_altrun = builder is not None + if builder is None: builder = BUILDER.BASE_COMMAND args = (to_list(builder) + ['-P%s' % project] + all_gargs + all_cargs + all_largs) - p = run_and_log(args, output=out, timeout=thistest.options.timeout) + # If there is an altrun hook for gprbuild, it may be a script. + # Instruct the Run primitive to parse the shebang to invoke the correct + # interpreter in that case. + p = run_and_log( + args, + output=out, + timeout=thistest.options.timeout, + parse_shebang=has_altrun, + ) if register_failure: thistest.stop_if(p.status != 0, FatalError("gprbuild exit in error", out)) diff --git a/testsuite/altrun/ccg_native/cgprbuild.py b/testsuite/altrun/ccg_native/cgprbuild.py index 5fe0d8d97..7db80a27e 100755 --- a/testsuite/altrun/ccg_native/cgprbuild.py +++ b/testsuite/altrun/ccg_native/cgprbuild.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python3 +#!/usr/bin/env python import argparse import json From 9d73e2e22fcdca25addbc43e706720db3fba4164 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 13 Dec 2023 13:09:40 +0100 Subject: [PATCH 0562/1483] Instrument.C: Delete target file before renaming It is not allowed to rename to an existing file on windows. We thus make sure to delete the target file before renaming to it. --- tools/gnatcov/instrument-c.adb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 9541e1308..01d605357 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3937,6 +3937,7 @@ package body Instrument.C is if Has_Manual_Indication then declare + PP_File : constant Virtual_File := Create (+(+PP_Filename)); Tmp_File : constant Virtual_File := Create (+Tmp_Filename); Success : Boolean; begin @@ -3950,8 +3951,9 @@ package body Instrument.C is -- Overwrite the original file with its newer version + PP_File.Delete (Success); Tmp_File.Rename - (Full_Name => Create (+(+PP_Filename)), + (Full_Name => PP_File, Success => Success); if not Success then Outputs.Fatal_Error From be3c0b95641350616ac96208d01725641315bc8d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 13 Dec 2023 13:10:51 +0100 Subject: [PATCH 0563/1483] Instrument.C: Fix inconsistency in files handling When using mmap, we read a file in binary mode, meaning that we read binary content: we thus need to be consistent when writing this content to another file, and open the latter in binary mode, otherwise it can result in spurious line endings on windows. --- tools/gnatcov/instrument-c.adb | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 01d605357..d0d3ecd9b 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -19,6 +19,7 @@ with Ada.Characters.Handling; with Ada.Containers; use Ada.Containers; with Ada.Directories; use Ada.Directories; +with Ada.Streams.Stream_IO; with Ada.Text_IO; use Ada.Text_IO; with Clang.CX_Diagnostic; use Clang.CX_Diagnostic; @@ -3893,6 +3894,7 @@ package body Instrument.C is -- function. declare + use Ada.Streams.Stream_IO; use GNATCOLL.Mmap; File : Mapped_File := Open_Read (To_String (PP_Filename)); Region : Mapped_Region := Read (File); @@ -3901,10 +3903,14 @@ package body Instrument.C is Str : String renames Raw_Str (1 .. Raw_Str_Last); Tmp_Filename : constant String := +PP_Filename & ".tmp"; - Output_File : Ada.Text_IO.File_Type; + + Output_File : Ada.Streams.Stream_IO.File_Type; + S : Ada.Streams.Stream_IO.Stream_Access; -- Temporary file containing the new version of the original file, -- with inserted calls to dump buffers. The original file is then - -- overwritten by this temporary file. + -- overwritten by this temporary file. This file is opened as a + -- binary file, as we are going to write contents retrieved + -- through mmap (thus binary content) to it. Index : Positive := 1; -- Starting index, or last index of the previous match in the @@ -3922,13 +3928,14 @@ package body Instrument.C is if not Has_Manual_Indication then Create (Output_File, Out_File, Tmp_Filename); + S := Stream (Output_File); Has_Manual_Indication := True; end if; - Put (Output_File, Str (Index .. Matches (0).First)); + String'Write (S, Str (Index .. Matches (0).First)); -- Replace the match with the call to the dump procedure - Put (Output_File, Dump_Procedure & "();"); + String'Write (S, Dump_Procedure & "();"); Index := Matches (0).Last + 1; end loop; @@ -3943,8 +3950,8 @@ package body Instrument.C is begin -- Flush the rest of the file contents - Ada.Text_IO.Put (Output_File, Str (Index .. Str'Last)); - Ada.Text_IO.Close (Output_File); + String'Write (S, Str (Index .. Str'Last)); + Close (Output_File); Free (Region); Close (File); From 7e245e5905cbfd5bc763ab6a98ab32302fe5ff89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 20 Sep 2023 11:51:43 +0200 Subject: [PATCH 0564/1483] Fix non-assertion coverage and add test for --show-condition-vectors Ensure that when the coverage of assertion decisions should not be reported it is also not computed as if it were a regular decision. Also, add a test checking evaluation vectors for levels stmt+mcdc+atcc and stmt+uc_mcdc+atcc. --- .../bin-mcdc-atcc.expected | 47 ++++++++++++ .../bin-ucmcdc-atcc.expected | 48 ++++++++++++ .../O212-062-show-condition-vectors/main.adb | 11 +++ .../O212-062-show-condition-vectors/pkg.adb | 45 +++++++++++ .../O212-062-show-condition-vectors/pkg.ads | 7 ++ .../src-mcdc-atcc.expected | 47 ++++++++++++ .../src-ucmcdc-atcc.expected | 47 ++++++++++++ .../O212-062-show-condition-vectors/test.py | 74 +++++++++++++++++++ tools/gnatcov/coverage-source.adb | 7 +- 9 files changed, 331 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/O212-062-show-condition-vectors/bin-mcdc-atcc.expected create mode 100644 testsuite/tests/O212-062-show-condition-vectors/bin-ucmcdc-atcc.expected create mode 100644 testsuite/tests/O212-062-show-condition-vectors/main.adb create mode 100644 testsuite/tests/O212-062-show-condition-vectors/pkg.adb create mode 100644 testsuite/tests/O212-062-show-condition-vectors/pkg.ads create mode 100644 testsuite/tests/O212-062-show-condition-vectors/src-mcdc-atcc.expected create mode 100644 testsuite/tests/O212-062-show-condition-vectors/src-ucmcdc-atcc.expected create mode 100644 testsuite/tests/O212-062-show-condition-vectors/test.py diff --git a/testsuite/tests/O212-062-show-condition-vectors/bin-mcdc-atcc.expected b/testsuite/tests/O212-062-show-condition-vectors/bin-mcdc-atcc.expected new file mode 100644 index 000000000..698e8f682 --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/bin-mcdc-atcc.expected @@ -0,0 +1,47 @@ +(.|\n)* + +2\.3\. MCDC COVERAGE +-+ + +pkg\.adb:13:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:13:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:13:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) +Evaluation vectors found: + F - - F -> FALSE In a pair for C0, C3 + T T F T -> TRUE In a pair for C3 + T T T - -> TRUE In a pair for C0 + +pkg\.adb:24:50: condition 1 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:24:60: condition 2 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:24:25: Decision of the form \(\(C0 or else C1\) or else C2\) +Evaluation vectors found: + F F F -> FALSE In a pair for C0 + T - - -> TRUE In a pair for C0 + +pkg\.adb:25:25: contract expression outcome FALSE never exercised +pkg\.adb:25:39: decision never evaluated +pkg\.adb:34:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:34:13: Decision of the form \(C0 and then C1\) +Evaluation vectors found: + F - -> FALSE In a pair for C0 + T T -> TRUE In a pair for C0 + +pkg\.adb:40:37: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:40:48: condition 2 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:40:26: Decision of the form \(\(C0 and then C1\) or else C2\) +Evaluation vectors found: + F - F -> FALSE In a pair for C0 + T T - -> TRUE In a pair for C0 + + +9 violations\. + +2\.4\. ATC COVERAGE +-+ + +No violation\. + +2\.5\. ATCC COVERAGE +-+ + +No violation\. diff --git a/testsuite/tests/O212-062-show-condition-vectors/bin-ucmcdc-atcc.expected b/testsuite/tests/O212-062-show-condition-vectors/bin-ucmcdc-atcc.expected new file mode 100644 index 000000000..4812d2f8b --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/bin-ucmcdc-atcc.expected @@ -0,0 +1,48 @@ +(.|\n)* + +2\.3\. UC_MCDC COVERAGE +-+ + +pkg\.adb:13:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:13:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:13:47: condition 3 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:13:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) +Evaluation vectors found: + F - - F -> FALSE In a pair for C0 + T T T - -> TRUE In a pair for C0 + T T F T -> TRUE Not part of any pair + +pkg\.adb:24:50: condition 1 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:24:60: condition 2 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:24:25: Decision of the form \(\(C0 or else C1\) or else C2\) +Evaluation vectors found: + F F F -> FALSE In a pair for C0 + T - - -> TRUE In a pair for C0 + +pkg\.adb:25:25: contract expression outcome FALSE never exercised +pkg\.adb:25:39: decision never evaluated +pkg\.adb:34:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:34:13: Decision of the form \(C0 and then C1\) +Evaluation vectors found: + F - -> FALSE In a pair for C0 + T T -> TRUE In a pair for C0 + +pkg\.adb:40:37: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:40:48: condition 2 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:40:26: Decision of the form \(\(C0 and then C1\) or else C2\) +Evaluation vectors found: + F - F -> FALSE In a pair for C0 + T T - -> TRUE In a pair for C0 + + +10 violations\. + +2\.4\. ATC COVERAGE +-+ + +No violation. + +2\.5\. ATCC COVERAGE +-+ + +No violation. diff --git a/testsuite/tests/O212-062-show-condition-vectors/main.adb b/testsuite/tests/O212-062-show-condition-vectors/main.adb new file mode 100644 index 000000000..9d9cb6287 --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/main.adb @@ -0,0 +1,11 @@ +with Pkg; use Pkg; +procedure Main is +begin + Mystery (False, True, True); + Mystery (False, False, False); + Mystery (True, True, True); + Mystery (True, True, False); + Other_Proc (True, True); + Other_Proc (False, True); +end Main; + diff --git a/testsuite/tests/O212-062-show-condition-vectors/pkg.adb b/testsuite/tests/O212-062-show-condition-vectors/pkg.adb new file mode 100644 index 000000000..056929256 --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/pkg.adb @@ -0,0 +1,45 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +with Ada.Text_IO; use Ada.Text_IO; +with Ada.Assertions; use Ada.Assertions; +package body Pkg is + + procedure Mystery (A, B, C : Boolean) + is + function Id (B : Boolean) return Boolean is (B); + begin + begin + if (A and then B and then C) or else A then + Put_Line ("Great success!"); + else + Put_Line ("Failed"); + end if; + if A then + Put_Line ("A is True"); + else + Put_Line ("A is False"); + end if; + + pragma Assert (Id (A or else B) or else A or else B); + pragma Assert (B or else Id (A or else B)); + exception + when Ada.Assertions.Assertion_Error => null; + end; + end Mystery; + + procedure Other_Proc (A, B : Boolean) is + begin + begin + if A and then B then + Put_Line ("Stuff"); + else + Put_Line ("not Stuff"); + end if; + + pragma Assert ((A and then B) or else A); + exception + when Ada.Assertions.Assertion_Error => null; + end; + end Other_Proc; +end Pkg; diff --git a/testsuite/tests/O212-062-show-condition-vectors/pkg.ads b/testsuite/tests/O212-062-show-condition-vectors/pkg.ads new file mode 100644 index 000000000..f20a1e22f --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + procedure Mystery (A, B, C : Boolean); + + procedure Other_Proc (A, B : Boolean); +end Pkg; + diff --git a/testsuite/tests/O212-062-show-condition-vectors/src-mcdc-atcc.expected b/testsuite/tests/O212-062-show-condition-vectors/src-mcdc-atcc.expected new file mode 100644 index 000000000..8b23cebd2 --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/src-mcdc-atcc.expected @@ -0,0 +1,47 @@ +(.|\n)* + +2\.3\. MCDC COVERAGE +-+ + +pkg\.adb:13:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:13:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:13:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) +Evaluation vectors found: + F - - F -> FALSE In a pair for C0, C3 + T T F T -> TRUE In a pair for C3 + T T T - -> TRUE In a pair for C0 + +pkg\.adb:34:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:34:13: Decision of the form \(C0 and then C1\) +Evaluation vectors found: + F - -> FALSE In a pair for C0 + T T -> TRUE In a pair for C0 + + +3 violations\. +(.|\n)* + +2\.5\. ATCC COVERAGE +-+ + +pkg\.adb:24:50: condition 1 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:24:60: condition 2 \("B"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:24:25: Decision of the form \(\(C0 or else C1\) or else C2\) +Evaluation vectors found: + F F F -> FALSE + T - - -> TRUE + +pkg\.adb:25:35: condition 1 \("Id \(A or ..."\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:25:25: Decision of the form \(C0 or else C1\) +Evaluation vectors found: + T - -> TRUE + +pkg\.adb:40:48: condition 2 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:40:26: Decision of the form \(\(C0 and then C1\) or else C2\) +Evaluation vectors found: + F - F -> FALSE + T T - -> TRUE + + +4 violations\. +(.|\n)* diff --git a/testsuite/tests/O212-062-show-condition-vectors/src-ucmcdc-atcc.expected b/testsuite/tests/O212-062-show-condition-vectors/src-ucmcdc-atcc.expected new file mode 100644 index 000000000..1d99cbd6c --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/src-ucmcdc-atcc.expected @@ -0,0 +1,47 @@ +(.|\n)* + +2\.3\. UC_MCDC COVERAGE +-+ + +pkg\.adb:13:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:13:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:13:47: condition 3 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:13:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) +Evaluation vectors found: + F - - F -> FALSE In a pair for C0 + T T T - -> TRUE In a pair for C0 + T T F T -> TRUE Not part of any pair + +pkg\.adb:34:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:34:13: Decision of the form \(C0 and then C1\) +Evaluation vectors found: + F - -> FALSE In a pair for C0 + T T -> TRUE In a pair for C0 + + +4 violations\. +(.|\n)* + +2\.5\. ATCC COVERAGE +-+ + +pkg\.adb:24:50: condition 1 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:24:60: condition 2 \("B"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:24:25: Decision of the form \(\(C0 or else C1\) or else C2\) +Evaluation vectors found: + F F F -> FALSE + T - - -> TRUE + +pkg\.adb:25:35: condition 1 \("Id \(A or ..."\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:25:25: Decision of the form \(C0 or else C1\) +Evaluation vectors found: + T - -> TRUE + +pkg\.adb:40:48: condition 2 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:40:26: Decision of the form \(\(C0 and then C1\) or else C2\) +Evaluation vectors found: + F - F -> FALSE + T T - -> TRUE + + +4 violations\. diff --git a/testsuite/tests/O212-062-show-condition-vectors/test.py b/testsuite/tests/O212-062-show-condition-vectors/test.py new file mode 100644 index 000000000..b2ddd7727 --- /dev/null +++ b/testsuite/tests/O212-062-show-condition-vectors/test.py @@ -0,0 +1,74 @@ +""" +Check that --show-condition-vectors works as expected for MCDC/UC_MCDC and +ATCC. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir('tmp_') + +# Generate a project, instrument it if necessary and run it, +p = gprfor(mains=['main.adb'], srcdirs=['..']) +xcov_args_mcdc = build_and_run( + gprsw=GPRswitches(root_project=p), + covlevel='stmt+mcdc+atcc', + mains=['main'], + extra_coverage_args=[] +) + + +def run_and_check(args, output_file, expected_file): + """ + Run gnatcov with the given arguments. + + :param str output_file: Name of the temporary file to store the content of + gnatcov's standard output. + :param str expected_file: File containing text we expected to find in the + coverage report. + """ + xcov(args, out=output_file) + + thistest.fail_if_no_match( + '"gnatcov coverage" output ({})'.format(output_file), + contents_of(expected_file).replace('\r\n', '\n'), + + # Canonicalize to Unix-style line endings to have cross-platform checks + contents_of(output_file).replace('\r\n', '\n')) + + +# For the following test, a different behavior is expected for source and bin +# traces as assertion coverage is currently not supported in binary traces. +# Assertion decisions are expected to be treated as any other decision. + +# Check that mcdc/atcc vectors are displayed under the corresponding +# condition violations, and show the conditions indexes in violation messages. + +mcdc_atcc_ref_file = ("../bin-mcdc-atcc.expected" + if thistest.options.trace_mode == "bin" + else "../src-mcdc-atcc.expected") + + +run_and_check(xcov_args_mcdc + ['-areport', '--show-condition-vectors'], + 'report-stdout-mcdc-atcc.txt', + mcdc_atcc_ref_file) + + +# Check that evaluation vectors not part of any pair are displayed below the +# other vectors. + +ucmcdc_atcc_ref_file = ("../bin-ucmcdc-atcc.expected" + if thistest.options.trace_mode == "bin" + else "../src-ucmcdc-atcc.expected") + +run_and_check(xcov_args_mcdc + ['--level=stmt+uc_mcdc+atcc', + '-areport', + '--show-condition-vectors'], + 'report-stdout-ucmcdc-atcc.txt', + ucmcdc_atcc_ref_file) + +thistest.result() diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index f82edeaf4..0b20f26ed 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -40,6 +40,7 @@ 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 Types; package body Coverage.Source is @@ -1074,7 +1075,7 @@ package body Coverage.Source is (SCO, SCO_State, Line_Info, SCI, ATCC); end if; - else + elsif Decision_Requires_Coverage (SCO) then -- ...otherwise update the SCO state for the regular -- source coverage levels. @@ -2243,7 +2244,9 @@ package body Coverage.Source is begin pragma Assert (Kind (SCO) in Decision | Condition); - return Assertion_Coverage_Enabled and then Is_Assertion_To_Cover (SCO); + return Currently_Accepted_Trace_Kind /= Binary_Trace_File + and then Assertion_Coverage_Enabled + and then Is_Assertion_To_Cover (SCO); end Decision_Requires_Assertion_Coverage; -------------------- From 1f3f6ecd26c19b0e73998c684b5d26f9dad23faf Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 6 Dec 2023 16:57:40 +0100 Subject: [PATCH 0565/1483] Instrument.Common: remove unused package --- tools/gnatcov/instrument-common.ads | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index f184c16a7..5912e62e7 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -49,8 +49,7 @@ -- units are replacements for the original units. They fill the coverage -- buffers for the unit. -with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Containers.Hashed_Sets; +with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Containers.Ordered_Maps; with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; @@ -168,12 +167,6 @@ package Instrument.Common is -- returned literal expression (aggregate in Ada, compound expression in -- C/C++). - package File_Sets is new Ada.Containers.Hashed_Sets - (Element_Type => Unbounded_String, - "=" => "=", - Equivalent_Elements => "=", - Hash => Strings.Hash); - type Instrumented_Unit_Info is record Filename : Unbounded_String; -- Name of the source file for this unit From fdceba034de0844edaf32a99fc566978a50bb865 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 6 Dec 2023 17:06:22 +0100 Subject: [PATCH 0566/1483] Compiler_Wrappers.Gcc: minor refactoring Use the "=" overload that takes an Unbounded_String, and a String as a parameter to avoid a spurious conversion from String to Unbounded_String. --- tools/gnatcov/compiler_wrappers-gcc.adb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 3d90c7be9..bc2b588ec 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -401,7 +401,7 @@ procedure Compiler_Wrappers.Gcc is -- would find the positional argument but it is not -- straightforward. - if Arg = +"-dumpbase" or else Arg = +"-dumpbase-ext" then + if Arg = "-dumpbase" or else Arg = "-dumpbase-ext" then Cur := Next (Cur); end if; @@ -500,17 +500,17 @@ procedure Compiler_Wrappers.Gcc is declare Arg : constant Unbounded_String := Element (Cur); begin - if Arg = +"-L" then + if Arg = "-L" then Result.Library_Dirs.Append (Element (Next (Cur))); elsif Starts_With (Arg, "-L") then Result.Library_Dirs.Append (Unbounded_Slice (Arg, 3, Length (Arg))); - elsif Arg = +"-l" then + elsif Arg = "-l" then Result.Libraries.Append (Element (Next (Cur))); elsif Starts_With (Arg, "-l") then Result.Libraries.Append (Unbounded_Slice (Arg, 3, Length (Arg))); - elsif Arg = +"-o" then + elsif Arg = "-o" then Result.Target := Element (Next (Cur)); elsif Ends_With (Arg, ".o") then if Context.Source_Mapping.Contains (Arg) then From df0e395aa4ea3ab76088df7c506d35488acdac2a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 6 Dec 2023 16:53:49 +0100 Subject: [PATCH 0567/1483] Refactoring: use Virtual_File instead of String / Unbounded_String This refactorings operate on instrumentation structure (mostly the ones that are used in the integrated instrumentation) and replace uses of strings / unbounded strings representing filenames with Virtual_File. There is no behavior change. --- tools/gnatcov/compiler_wrappers-gcc.adb | 132 ++++++++++++---------- tools/gnatcov/files_handling.adb | 41 +++++++ tools/gnatcov/files_handling.ads | 59 ++++++++++ tools/gnatcov/gnatcov_bits_specific.adb | 13 +-- tools/gnatcov/instrument-ada_unit.adb | 4 +- tools/gnatcov/instrument-ada_unit.ads | 3 +- tools/gnatcov/instrument-c.adb | 21 ++-- tools/gnatcov/instrument-c.ads | 26 +++-- tools/gnatcov/instrument-common.ads | 11 +- tools/gnatcov/instrument-projects.adb | 54 ++++----- tools/gnatcov/instrument-setup_config.adb | 8 +- tools/gnatcov/instrument-setup_config.ads | 4 +- tools/gnatcov/instrument-source.adb | 4 +- tools/gnatcov/instrument.adb | 21 ++-- tools/gnatcov/instrument.ads | 3 +- tools/gnatcov/switches.ads | 3 +- 16 files changed, 256 insertions(+), 151 deletions(-) create mode 100644 tools/gnatcov/files_handling.adb create mode 100644 tools/gnatcov/files_handling.ads diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index bc2b588ec..3b30500f2 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -24,9 +24,12 @@ with Ada.Environment_Variables; with Ada.Strings; use Ada.Strings; with Ada.Text_IO; use Ada.Text_IO; +with GNATCOLL.VFS; use GNATCOLL.VFS; + with GNAT.OS_Lib; with Coverage.Tags; use Coverage.Tags; +with Files_Handling; use Files_Handling; with Files_Table; use Files_Table; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Instrument; use Instrument; @@ -50,11 +53,11 @@ procedure Compiler_Wrappers.Gcc is Language : Any_Language; -- Language of the file that is compiled - Filename : Unbounded_String; - -- Full name of the file that is compiled + File : Virtual_File; + -- File that is compiled - Target : Unbounded_String; - -- Name of the output assembly file (passed through the -o switch) + Target : Virtual_File; + -- Output assembly file (passed through the -o switch) Instrumentation_Sources : String_Vectors.Vector; -- List of sources produced by the instrumentation process. It does not @@ -66,18 +69,18 @@ procedure Compiler_Wrappers.Gcc is No_Compilation_Command : constant Compilation_Command_Type := (Language => All_Languages, - Filename => Null_Unbounded_String, - Target => Null_Unbounded_String, + File => No_File, + Target => No_File, Instrumentation_Sources => String_Vectors.Empty_Vector); package Compilation_Command_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Compilation_Command_Type); type Assembly_Command_Type is record - Filename : Unbounded_String; - -- Name of the assembly file (positional argument) + Filename : Virtual_File; + -- Assembly file (positional argument) - Target : Unbounded_String; + Target : Virtual_File; -- Output object file (passed through the -o switch) end record; @@ -85,8 +88,7 @@ procedure Compiler_Wrappers.Gcc is -- driver. No_Assembly_Command : constant Assembly_Command_Type := - (Filename => Null_Unbounded_String, - Target => Null_Unbounded_String); + (Filename => No_File, Target => No_File); package Assembly_Command_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Assembly_Command_Type); @@ -98,14 +100,14 @@ procedure Compiler_Wrappers.Gcc is Libraries : String_Vectors.Vector; -- List of libraries (passed through -l switches) - Object_Files : String_Vectors.Vector; + Object_Files : File_Vectors.Vector; -- List of object files (positional arguments) - Source_Files : String_Vectors.Vector; + Source_Files : File_Vectors.Vector; -- When the compiler driver command compiles and links, this contains -- the list of files that are compiled by the compiler driver command. - Target : Unbounded_String; + Target : Virtual_File; -- Output executable file (passed through the -o switch) end record; @@ -114,9 +116,9 @@ procedure Compiler_Wrappers.Gcc is No_Link_Command : constant Link_Command_Type := (Library_Dirs => String_Vectors.Empty_Vector, Libraries => String_Vectors.Empty_Vector, - Object_Files => String_Vectors.Empty_Vector, - Source_Files => String_Vectors.Empty_Vector, - Target => Null_Unbounded_String); + Object_Files => File_Vectors.Empty_Vector, + Source_Files => File_Vectors.Empty_Vector, + Target => No_File); type Compilation_Database is record Compilation_Commands : Compilation_Command_Vectors.Vector; @@ -136,7 +138,7 @@ procedure Compiler_Wrappers.Gcc is Orig_Compiler_Driver : Unbounded_String; -- Full path to the original compiler driver - Source_Mapping : String_Maps.Map; + Source_Mapping : File_To_File_Maps.Map; -- We rely on object file symbols to know what coverage buffers we -- should dump at link time. Nevertheless, an object file referenced in -- a link command (which we get through the -### verbose switch) does @@ -151,7 +153,7 @@ procedure Compiler_Wrappers.Gcc is -- The Source_Mapping thus maps the temporary object files to the -- original source. - Instrumentation_Objects : String_Vectors_Maps.Map; + Instrumentation_Objects : File_To_String_Vectors_Maps.Map; -- Maps the original source name to the instrumentation artifact objects -- (e.g. coverage buffers unit, dump helper unit). @@ -410,28 +412,26 @@ procedure Compiler_Wrappers.Gcc is or else Ends_With (Arg, ".cpp") or else Ends_With (Arg, ".cxx") then - if Length (Result.Filename) = 0 then - Result.Filename := +Ada.Directories.Full_Name (+Arg); + if Result.File = No_File then + Result.File := Create_Normalized (+Arg); else Outputs.Warn ("Found multiple filenames in the compiler invocation: " - & (+Result.Filename) & " and " & (+Arg) + & (+Result.File.Base_Name) & " and " & (+Arg) & ". Keeping the former, which was parsed before."); end if; elsif Arg = "-o" then Result.Target := - String_Vectors.Element (String_Vectors.Next (Cur)); + Create_Normalized (+String_Vectors.Element (Cur)); end if; end; Cur := Next (Cur); end loop; - if Length (Result.Filename) = 0 - or else Length (Result.Target) = 0 - then + if Result.File = No_File or else Result.Target = No_File then return No_Compilation_Command; end if; - Context.Source_Mapping.Include (Result.Target, Result.Filename); + Context.Source_Mapping.Include (Result.Target, Result.File); return Result; end Parse_Compilation_Command; @@ -452,20 +452,21 @@ procedure Compiler_Wrappers.Gcc is begin if Arg = "-o" then Result.Target := - String_Vectors.Element (String_Vectors.Next (Cur)); + Create_Normalized + (+String_Vectors.Element (String_Vectors.Next (Cur))); elsif Ends_With (Arg, ".s") then - Result.Filename := Arg; + Result.Filename := Create_Normalized (+Arg); end if; end; end loop; -- Error out if the parsing failed - if Length (Result.Filename) = 0 then + if Result.Filename = No_File then Outputs.Fatal_Error ("Could not find assembly file in assembly command: " & Img (Command)); - elsif Length (Result.Target) = 0 then + elsif Result.Target = No_File then Outputs.Fatal_Error ("Could not find output file in assembly command: " & Img (Command)); @@ -511,22 +512,27 @@ procedure Compiler_Wrappers.Gcc is Result.Libraries.Append (Unbounded_Slice (Arg, 3, Length (Arg))); elsif Arg = "-o" then - Result.Target := Element (Next (Cur)); + Result.Target := Create_Normalized (+Element (Next (Cur))); elsif Ends_With (Arg, ".o") then - if Context.Source_Mapping.Contains (Arg) then - Result.Source_Files.Append - (Context.Source_Mapping.Element (Arg)); - else - Result.Object_Files.Append (Arg); - end if; + declare + Object_File : constant Virtual_File := + Create_Normalized (+Arg); + begin + if Context.Source_Mapping.Contains (Object_File) then + Result.Source_Files.Append + (Context.Source_Mapping.Element (Object_File)); + else + Result.Object_Files.Append (Create_Normalized (+Arg)); + end if; + end; elsif Ends_With (Arg, ".a") then Result.Libraries.Append (Arg); end if; end; end loop; - if Length (Result.Target) = 0 then - Result.Target := +"a.out"; + if Result.Target = No_File then + Result.Target := Create_Normalized ("a.out"); end if; return Result; @@ -543,7 +549,7 @@ procedure Compiler_Wrappers.Gcc is Config : Instrumentation_Config) return String_Sets.Set is function Coverage_Buffer_Symbols - (Symbol_File : String) return String_Sets.Set; + (Symbol_File : Virtual_File) return String_Sets.Set; -- Return the list of coverage buffer symbols in the given symbol file -- (object or library file). @@ -552,11 +558,11 @@ procedure Compiler_Wrappers.Gcc is ----------------------------- function Coverage_Buffer_Symbols - (Symbol_File : String) return String_Sets.Set + (Symbol_File : Virtual_File) return String_Sets.Set is Args : String_Vectors.Vector; Output_Filename : constant String := - Tmp_Dir / ("nm_" & Filename_Slug (Symbol_File)); + Tmp_Dir / ("nm_" & Filename_Slug (+Symbol_File.Full_Name)); Output_File : File_Type; Result : String_Sets.Set; @@ -566,7 +572,7 @@ procedure Compiler_Wrappers.Gcc is -- Use the compiler nm to dump the list of symbols Args.Append (+"--format=just-symbol"); - Args.Append (+Symbol_File); + Args.Append (Full_Name (Symbol_File)); -- The command can fail with e.g. "file format not recognized" for -- system libraries. TODO??? investigate why. We should also avoid @@ -616,7 +622,7 @@ procedure Compiler_Wrappers.Gcc is -- Start by dealing with object files for Object_File of Command.Object_Files loop - Result.Union (Coverage_Buffer_Symbols (+Object_File)); + Result.Union (Coverage_Buffer_Symbols (Object_File)); end loop; -- Then, deal with library files @@ -633,12 +639,12 @@ procedure Compiler_Wrappers.Gcc is Ada.Environment_Variables.Value ("LIBRARY_PATH", "")); for Library of Command.Libraries loop - if Ends_With (Library, ".a") then -- Library filename on the command line, no need to look it up - Result.Union (Coverage_Buffer_Symbols (+Library)); + Result.Union + (Coverage_Buffer_Symbols (Create_Normalized (+Library))); else -- Simple library name passed to the -l option, search the -- actual file on the library path. @@ -650,7 +656,9 @@ procedure Compiler_Wrappers.Gcc is ("lib" & (+Library) & ".a", +Library_Path); begin if Library_File /= null then - Result.Union (Coverage_Buffer_Symbols (Library_File.all)); + Result.Union + (Coverage_Buffer_Symbols + (Create_Normalized (Library_File.all))); GNAT.OS_Lib.Free (Library_File); end if; end; @@ -666,7 +674,7 @@ procedure Compiler_Wrappers.Gcc is declare Unit : constant Compilation_Unit := (Language => File_Based_Language, - Unit_Name => Source); + Unit_Name => Full_Name (Source)); begin Result.Insert (+Unit_Buffers_Name (Unit)); end; @@ -790,17 +798,15 @@ begin with "Unsupported language for integrated" & " instrumentation"); - Fullname : constant String := - Ada.Directories.Full_Name (+Comp_Command.Filename); - Simple_Name : constant String := - Workaround_Simple_Name (+Comp_Command.Filename); + Fullname : constant String := +Comp_Command.File.Full_Name; + Simple_Name : constant String := +Comp_Command.File.Base_Name; Instr_Name : constant String := (+Prj.Output_Dir) / Simple_Name; begin -- Start by instrumenting the file as a source, if it is a unit of -- interest. - if Files_Of_Interest.Contains (+Fullname) then + if Files_Of_Interest.Contains (Comp_Command.File) then -- Pass the compiler switches through the project description @@ -819,7 +825,7 @@ begin Comp_Command_Ref.Instrumentation_Sources.Append (Instrumenter.Buffer_Unit (Compilation_Unit' - (File_Based_Language, Comp_Command.Filename), + (File_Based_Language, Full_Name (Comp_Command.File)), Prj) .Unit_Name); Instrumented_Files.Include (+Fullname); @@ -934,7 +940,7 @@ begin else Context.Instrumentation_Objects.Insert - (Comp_Command.Filename, String_Vectors.Empty); + (Comp_Command.File, String_Vectors.Empty); for Instr_Artifact of Comp_Command.Instrumentation_Sources loop declare @@ -953,7 +959,7 @@ begin Run_Original_Compiler (Context, Args_Compilation); Context.Instrumentation_Objects - .Reference (Comp_Command.Filename) + .Reference (Comp_Command.File) .Append (+Instr_Artifact_Object_Name); end; end loop; @@ -973,14 +979,16 @@ begin for Assembly_Command of Comp_DB.Assembly_Commands loop if Context.Source_Mapping.Contains (Assembly_Command.Filename) then declare - Orig_Source : constant Unbounded_String := + Orig_Source : constant Virtual_File := Context.Source_Mapping.Element (Assembly_Command.Filename); Instr_Objects : constant String_Vectors.Vector := Context.Instrumentation_Objects.Element (Orig_Source); Packaged_Name : constant String := New_File - (Prj, "instr_" & Filename_Slug (+Orig_Source) & ".a"); - Success : Boolean; + (Prj, + "instr_" & Filename_Slug (+Orig_Source.Full_Name) + & ".a"); + Success : Boolean; begin if not Instr_Objects.Is_Empty then declare @@ -988,7 +996,7 @@ begin begin Args_Ld.Append (+"-r"); Args_Ld.Append_Vector (Instr_Objects); - Args_Ld.Append (Assembly_Command.Target); + Args_Ld.Append (Full_Name (Assembly_Command.Target)); Args_Ld.Append (+"-o"); Args_Ld.Append (+Packaged_Name); Run_Command @@ -1004,7 +1012,7 @@ begin GNAT.OS_Lib.Copy_File (Packaged_Name, - +Assembly_Command.Target, + +Assembly_Command.Target.Full_Name, Success, Mode => GNAT.OS_Lib.Overwrite, Preserve => GNAT.OS_Lib.Full); diff --git a/tools/gnatcov/files_handling.adb b/tools/gnatcov/files_handling.adb new file mode 100644 index 000000000..a94387b46 --- /dev/null +++ b/tools/gnatcov/files_handling.adb @@ -0,0 +1,41 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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. -- +------------------------------------------------------------------------------ + +package body Files_Handling is + + ----------------------- + -- Create_Normalized -- + ----------------------- + + function Create_Normalized (Filename : String) return Virtual_File is + Result : constant Virtual_File := Create_From_Base (+Filename); + begin + Result.Normalize_Path; + return Result; + end Create_Normalized; + + --------------- + -- Full_Name -- + --------------- + + function Full_Name (File : Virtual_File) return Unbounded_String is + begin + return +(+File.Full_Name); + end Full_Name; + +end Files_Handling; diff --git a/tools/gnatcov/files_handling.ads b/tools/gnatcov/files_handling.ads new file mode 100644 index 000000000..0f2685526 --- /dev/null +++ b/tools/gnatcov/files_handling.ads @@ -0,0 +1,59 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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.Ordered_Maps; +with Ada.Containers.Ordered_Sets; +with Ada.Containers.Vectors; + +with GNATCOLL.VFS; use GNATCOLL.VFS; + +with Strings; use Strings; + +package Files_Handling is + + function Create_Normalized (Filename : String) return Virtual_File; + -- Wrapper around GNATCOLL.VFS.Create_From_Base, that normalizes by + -- default the Virtual_File. + + function Full_Name (File : Virtual_File) return Unbounded_String; + -- Wrapper around GNATCOLL.VFS.Full_Name, converting the Filesystem_String + -- to an Unbounded_String. + + package File_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, + Element_Type => Virtual_File, + "=" => GNATCOLL.VFS."="); + + package File_Sets is new Ada.Containers.Ordered_Sets + (Element_Type => Virtual_File, + "<" => GNATCOLL.VFS."<", + "=" => GNATCOLL.VFS."="); + + package File_To_String_Vectors_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Virtual_File, + Element_Type => String_Vectors.Vector, + "<" => GNATCOLL.VFS."<", + "=" => String_Vectors."="); + + package File_To_File_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Virtual_File, + Element_Type => Virtual_File, + "<" => GNATCOLL.VFS."<", + "=" => GNATCOLL.VFS."="); + +end Files_Handling; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 340840c7f..8de0ca907 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -28,8 +28,6 @@ with GNAT.OS_Lib; with GNAT.Regexp; with GNAT.Strings; use GNAT.Strings; -with GNATCOLL.VFS; - with System.Multiprocessors; with Snames; @@ -57,6 +55,7 @@ with Coverage_Options; use Coverage_Options; with Decision_Map; use Decision_Map; with Disassemble_Insn_Properties; with Execs_Dbase; use Execs_Dbase; +with Files_Handling; use Files_Handling; with Files_Table; use Files_Table; with Inputs; use Inputs; with Instrument; @@ -551,14 +550,8 @@ procedure GNATcov_Bits_Specific is Copy_Arg_List (Opt_Files, Files_Of_Interest); Copy_Arg_List (Opt_Compiler_Wrappers, Compiler_Drivers); - for Filename of Files_Of_Interest loop - declare - use GNATCOLL.VFS; - F : constant Virtual_File := Create (+(+Filename)); - begin - F.Normalize_Path; - Switches.Files_Of_Interest.Include (+(+Full_Name (F))); - end; + for File of Files_Of_Interest loop + Switches.Files_Of_Interest.Include (Create_Normalized (+File)); end loop; -- Compute the languages for which we want coverage analysis, or enable diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index bd43a44cb..f5deca87c 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -9058,7 +9058,7 @@ package body Instrument.Ada_Unit is (Self : in out Ada_Instrumenter_Type; Unit_Name : String; Prj : Prj_Desc; - Files_Of_Interest : String_Sets.Set) + Files_Of_Interest : File_Sets.Set) is Allocated_Bits : Allocated_Bits_Vectors.Vector; Last_Buffer_Index : Natural := 0; @@ -9089,7 +9089,7 @@ package body Instrument.Ada_Unit is begin -- Instrument the file only if it is a file of interest - if Files_Of_Interest.Contains (+Filename) then + if Files_Of_Interest.Contains (Create_Normalized (Filename)) then -- In verbose mode, always print a notice for the source file -- that we are about to instrument. In non-verbose mode, just get -- prepared to print it in case we emit a "source file missing" diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 3f8edeb49..82ac5b1d3 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -28,6 +28,7 @@ with Langkit_Support.Text; use Langkit_Support.Text; with Libadalang.Analysis; use Libadalang.Analysis; with Libadalang.Rewriting; use Libadalang.Rewriting; +with Files_Handling; use Files_Handling; with Files_Table; use Files_Table; with Instrument.Ada_Unit_Provider; with Instrument.Common; use Instrument.Common; @@ -71,7 +72,7 @@ package Instrument.Ada_Unit is (Self : in out Ada_Instrumenter_Type; Unit_Name : String; Prj : Prj_Desc; - Files_Of_Interest : String_Sets.Set); + Files_Of_Interest : File_Sets.Set); overriding procedure Auto_Dump_Buffers_In_Main (Self : in out Ada_Instrumenter_Type; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index d0d3ecd9b..bc527a414 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -29,7 +29,6 @@ with Clang.Extensions; use Clang.Extensions; with GNAT.OS_Lib; use GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; -with GNATCOLL.VFS; with GNATCOLL.Mmap; with Interfaces; use Interfaces; @@ -2933,7 +2932,7 @@ package body Instrument.C is (Self : in out C_Family_Instrumenter_Type; Unit_Name : String; Prj : Prj_Desc; - Files_Of_Interest : String_Sets.Set) + Files_Of_Interest : File_Sets.Set) is UIC : C_Unit_Inst_Context; CU_Name : constant Compilation_Unit_Part := @@ -3844,7 +3843,6 @@ package body Instrument.C is Source : GNATCOLL.Projects.File_Info; Has_Manual_Indication : out Boolean) is - use GNATCOLL.VFS; Orig_Filename : constant String := +Source.File.Full_Name; begin Check_Compiler_Driver (Prj, Self); @@ -3868,7 +3866,7 @@ package body Instrument.C is Preprocess_Source (Orig_Filename, Self, Prj, PP_Filename, Options, True); declare - use String_Vectors_Maps; + use Files_Handling.File_To_String_Vectors_Maps; Cur : Cursor; Inserted : Boolean; begin @@ -3879,7 +3877,7 @@ package body Instrument.C is for Path of Options.PP_Search_Path loop Prj.Compiler_Options_Unit.Insert - (Key => +(+Source.File.Full_Name), + (Key => Source.File, New_Item => String_Vectors.Empty_Vector, Position => Cur, Inserted => Inserted); @@ -4557,6 +4555,7 @@ package body Instrument.C is Prj : Prj_Desc; Filename : String) is + File : constant Virtual_File := Create_Normalized (Filename); Cmdline_Opts : constant String_Vectors.Vector := (case C_Family_Language (Instrumenter.Language) is when C_Language => C_Opts, @@ -4568,8 +4567,8 @@ package body Instrument.C is -- implementation. Otherwise, the compiler switches in the project files -- are passed through the command line directly. - if Prj.Compiler_Options_Unit.Contains (+Filename) then - Prj_Options.Append (Prj.Compiler_Options_Unit.Element (+Filename)); + if Prj.Compiler_Options_Unit.Contains (File) then + Prj_Options.Append (Prj.Compiler_Options_Unit.Element (File)); else Prj_Options.Append (Prj.Compiler_Options (Instrumenter.Language)); end if; @@ -4604,13 +4603,13 @@ package body Instrument.C is Line : aliased unsigned; Column : aliased unsigned; Loc : constant Source_Location_T := Get_Cursor_Location (N); - File : Unbounded_String; + File : Virtual_File; begin Get_Presumed_Location (Location => Loc, Filename => C_File'Access, Line => Line'Access, Column => Column'Access); - File := +Ada.Directories.Full_Name (Get_C_String (C_File)); + File := Create_Normalized (Get_C_String (C_File)); -- Look for a corresponding entry in UIC.Sources_Of_Interest, create one -- if it is missing. @@ -4632,12 +4631,12 @@ package body Instrument.C is if UIC.Files_Of_Interest.Contains (File) then declare SFI : constant Source_File_Index := - Get_Index_From_Generic_Name (+File, Source_File); + Get_Index_From_Generic_Name (+File.Full_Name, Source_File); begin SOI := (Of_Interest => True, SFI => SFI, - CU_Name => CU_Name_For_File (File)); + CU_Name => CU_Name_For_File (Full_Name (File))); end; else SOI := (Of_Interest => False); diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index cbf5164f0..bb8aa761c 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -18,22 +18,24 @@ -- Instrumentation of a C source file -with Ada.Containers.Hashed_Maps; with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; with Ada.Finalization; with Namet; use Namet; +with GNATCOLL.VFS; use GNATCOLL.VFS; + with Clang.CX_Source_Location; use Clang.CX_Source_Location; with Clang.Index; use Clang.Index; with Clang.Rewrite; use Clang.Rewrite; -with Diagnostics; use Diagnostics; -with Files_Table; use Files_Table; +with Diagnostics; use Diagnostics; +with Files_Handling; use Files_Handling; +with Files_Table; use Files_Table; with Instrument.C_Utils; use Instrument.C_Utils; -with Instrument.Common; use Instrument.Common; -with Slocs; use Slocs; +with Instrument.Common; use Instrument.Common; +with Slocs; use Slocs; package Instrument.C is @@ -45,7 +47,7 @@ package Instrument.C is (Self : in out C_Family_Instrumenter_Type; Unit_Name : String; Prj : Prj_Desc; - Files_Of_Interest : String_Sets.Set); + Files_Of_Interest : File_Sets.Set); overriding procedure Auto_Dump_Buffers_In_Main (Self : in out C_Family_Instrumenter_Type; @@ -309,11 +311,11 @@ package Instrument.C is -- gnatcov's file table and Project_Name is the name of the project that -- owns this source file. - package Source_Of_Interest_Maps is new Ada.Containers.Hashed_Maps - (Key_Type => Unbounded_String, - Element_Type => Source_Of_Interest, - Hash => Strings.Hash, - Equivalent_Keys => "="); + package Source_Of_Interest_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Virtual_File, + Element_Type => Source_Of_Interest, + "<" => GNATCOLL.VFS."<", + "=" => "="); type File_Scope_Type is record Scope_Entities : Scope_Entities_Tree; @@ -353,7 +355,7 @@ package Instrument.C is LL_PP_Info_Map : LL_SCO_PP_Info_Maps.Map; -- Preprocessing information for low level SCOs - Files_Of_Interest : String_Sets.Set; + Files_Of_Interest : File_Sets.Set; Sources_Of_Interest_Info : Source_Of_Interest_Maps.Map; -- Records for each source file processed during the instrumentation -- whether it is a source of interest, and some properties if it is. diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 5912e62e7..913cdf367 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -58,11 +58,12 @@ with GNAT.Regpat; use GNAT.Regpat; with GNATCOLL.JSON; use GNATCOLL.JSON; -with ALI_Files; use ALI_Files; -with Files_Table; use Files_Table; +with ALI_Files; use ALI_Files; +with Files_Handling; use Files_Handling; +with Files_Table; use Files_Table; with GNATcov_RTS; -with Namet; use Namet; -with Slocs; use Slocs; +with Namet; use Namet; +with Slocs; use Slocs; with Text_Files; package Instrument.Common is @@ -404,7 +405,7 @@ package Instrument.Common is (Self : in out Language_Instrumenter; Unit_Name : String; Prj : Prj_Desc; - Files_Of_Interest : String_Sets.Set) is null; + Files_Of_Interest : File_Sets.Set) is null; -- Instrument a single source file for the language that Self supports. -- -- Unit_Name identifies this compilation unit (either through a unit name, diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 69e897488..2c0ae7bf9 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -35,11 +35,12 @@ with GNAT.Regexp; with GNAT.Strings; with GNATCOLL.JSON; use GNATCOLL.JSON; -with GNATCOLL.VFS; +with GNATCOLL.VFS; use GNATCOLL.VFS; with GNATCOLL.Projects.Aux; use GNATCOLL.Projects.Aux; with Binary_Files; with Command_Line; use Command_Line; +with Files_Handling; use Files_Handling; with Files_Table; with Instrument.Ada_Unit; use Instrument.Ada_Unit; with Instrument.Ada_Preprocessing; @@ -121,11 +122,10 @@ is package Main_To_Instrument_Vectors is new Ada.Containers.Vectors (Positive, Main_To_Instrument); - use type GNATCOLL.VFS.Filesystem_String; function Less (L, R : File_Info) return Boolean is (L.File.Full_Name < R.File.Full_Name); function Equal (L, R : File_Info) return Boolean is - (L.File.Full_Name = R.File.Full_Name); + (Equal (L.File.Full_Name, R.File.Full_Name)); package File_Info_Sets is new Ada.Containers.Indefinite_Ordered_Sets (Element_Type => File_Info, "<" => Less, "=" => Equal); @@ -545,8 +545,6 @@ is (LU_Info : Library_Unit_Info; In_Library_Dir : Boolean) return String is - use GNATCOLL.VFS; - -- Determine in which project we will put this SID file, and the -- basename for the SID file to create. Mimic how GNAT creates ALI -- files: use the project of the main source of the library unit, start @@ -673,8 +671,8 @@ is Instrumented_Sources : Unit_Maps.Map; -- List of units that should be instrumented - Files_Of_Interest_Str_Set : String_Sets.Set; - Files_Of_Interest : File_Info_Sets.Set; + Files_Of_Interest : File_Sets.Set; + Files_Of_Interest_Info : File_Info_Sets.Set; -- List of files of interest. -- -- This is passed on to instrument-source invocations when instrumenting @@ -754,8 +752,8 @@ is -- Otherwise, this is a source of interest - Files_Of_Interest.Insert (Source_File); - Files_Of_Interest_Str_Set.Insert (+(+Source_File.File.Full_Name)); + Files_Of_Interest_Info.Insert (Source_File); + Files_Of_Interest.Insert (Source_File.File); -- Headers are not instrumented by themselves, so exit early as soon -- as they have been added to the sources of interest. @@ -816,7 +814,7 @@ is end; Add_Options (Compiler_Opts, Options, Pass_Builtins => False); Prj_Info.Desc.Compiler_Options_Unit.Insert - (LU_Info.Unit_Name, Compiler_Opts); + (Create_Normalized (+LU_Info.Unit_Name), Compiler_Opts); end if; end; end if; @@ -1070,15 +1068,15 @@ begin -- this is not supported. TODO???: we should probably issue a warning -- there. - for Source of Files_Of_Interest.Copy loop + for Source of Files_Of_Interest_Info.Copy loop if Source.Unit_Part = Unit_Separate then declare Parent_Unit : constant GNATCOLL.Projects.File_Info := Project.Project.Info (Project.Project.Other_File (Source.File)); begin - if not Files_Of_Interest.Contains (Parent_Unit) then - Files_Of_Interest.Delete (Source); + if not Files_Of_Interest_Info.Contains (Parent_Unit) then + Files_Of_Interest_Info.Delete (Source); end if; end; end if; @@ -1108,8 +1106,6 @@ begin else for Filename of Mains loop declare - use GNATCOLL.VFS; - F : constant String := +Filename; Info : constant File_Info := Project.Project.Root_Project.Create_From_Project (+F); @@ -1138,7 +1134,7 @@ begin -- Check early if there are no sources of interest - if Files_Of_Interest.Length = 0 then + if Files_Of_Interest_Info.Length = 0 then Outputs.Fatal_Error ("No unit to instrument."); end if; @@ -1175,15 +1171,11 @@ begin -- Set the runtime directories - declare - use GNATCOLL.VFS; - begin - for Dir of - Project.Project.Root_Project.Get_Environment.Predefined_Source_Path - loop - IC.Predefined_Source_Dirs.Append (+(+Full_Name (Dir))); - end loop; - end; + for Dir of + Project.Project.Root_Project.Get_Environment.Predefined_Source_Path + loop + IC.Predefined_Source_Dirs.Append (Full_Name (Dir)); + end loop; -- Initialize the instrumenters: we will use them when parallelization is -- disabled, but also to generate the unit holding the list of buffers, @@ -1222,7 +1214,7 @@ begin begin Sources_Of_Interest_File.Create (+IC.Sources_Of_Interest_Response_File); - for Source of Files_Of_Interest loop + for Source of Files_Of_Interest_Info loop Sources_Of_Interest_File.Put_Line (+Source.File.Full_Name); end loop; Sources_Of_Interest_File.Close; @@ -1290,7 +1282,7 @@ begin (Unit_Name => Unit_Name, SID_Name => Obj_SID, Instrumenter => Instrumenters (LU_Info.Language).all, - Files_Of_Interest => Files_Of_Interest_Str_Set, + Files_Of_Interest => Files_Of_Interest, Prj => Desc); else -- Asynchronously instrument @@ -1322,8 +1314,6 @@ begin -- creates automatically, the library directory may not -- exist: create it if needed. - declare - use GNATCOLL.VFS; begin Create (Create (+Lib_SID).Dir_Name).Make_Dir; exception @@ -1444,7 +1434,7 @@ begin +(+Root_Project_Info.Output_Dir) / (+Main.File.Base_Name); else - Main_Filename := +(+Main.File.Full_Name); + Main_Filename := Full_Name (Main.File); end if; Unit_Args.Append (Main_Filename); @@ -1453,8 +1443,8 @@ begin declare Instr_Units : String_Sets.Set; begin - for Source of Files_Of_Interest loop - Instr_Units.Insert (+(+Source.File.Full_Name)); + for Source of Files_Of_Interest_Info loop + Instr_Units.Insert (Full_Name (Source.File)); end loop; Instrument.Main (Instrumenter => Instrumenters (Language).all, diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index cae99a724..9d06711ff 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -25,6 +25,8 @@ with GNAT.OS_Lib; with GNAT.Regexp; use GNAT.Regexp; with GNAT.Strings; +with GNATCOLL.VFS; use GNATCOLL.VFS; + with Coverage; with JSON; use JSON; with Logging; @@ -104,7 +106,7 @@ package body Instrument.Setup_Config is --------------------- procedure Generate_Config - (Files_Of_Interest : String_Sets.Set; + (Files_Of_Interest : File_Sets.Set; Coverage_Level : String; Dump_Config : Any_Dump_Config; Compiler_Drivers : String_Sets.Set; @@ -289,7 +291,7 @@ package body Instrument.Setup_Config is Files_Of_Interest_JSON : JSON_Array; begin for F of Files_Of_Interest loop - Append (Files_Of_Interest_JSON, Create (+F)); + Append (Files_Of_Interest_JSON, Create (+F.Full_Name)); end loop; Config.Set_Field ("files-of-interest", Files_Of_Interest_JSON); end; @@ -397,7 +399,7 @@ package body Instrument.Setup_Config is Config_JSON.Get ("files-of-interest"); begin for FOI of FOI_JSON loop - Switches.Files_Of_Interest.Include (Get (FOI)); + Switches.Files_Of_Interest.Include (Create_Normalized (Get (FOI))); end loop; end; diff --git a/tools/gnatcov/instrument-setup_config.ads b/tools/gnatcov/instrument-setup_config.ads index 4c4982aa4..ab302f54e 100644 --- a/tools/gnatcov/instrument-setup_config.ads +++ b/tools/gnatcov/instrument-setup_config.ads @@ -18,6 +18,8 @@ with GNATCOLL.JSON; use GNATCOLL.JSON; +with Files_Handling; use Files_Handling; + package Instrument.Setup_Config is type Instrumentation_Config is record @@ -50,7 +52,7 @@ package Instrument.Setup_Config is -- Simple name of the file containing the instrumentation configuration procedure Generate_Config - (Files_Of_Interest : String_Sets.Set; + (Files_Of_Interest : File_Sets.Set; Coverage_Level : String; Dump_Config : Any_Dump_Config; Compiler_Drivers : String_Sets.Set; diff --git a/tools/gnatcov/instrument-source.adb b/tools/gnatcov/instrument-source.adb index 2e3b2638b..7b3ab0b41 100644 --- a/tools/gnatcov/instrument-source.adb +++ b/tools/gnatcov/instrument-source.adb @@ -18,8 +18,8 @@ with Checkpoints; use Checkpoints; with Coverage; +with Files_Handling; use Files_Handling; with Instrument.Common; use Instrument.Common; -with Strings; use Strings; with Traces_Files; use Traces_Files; -- Implementation of the gnatcov instrument-source command, which instrument @@ -30,7 +30,7 @@ procedure Instrument.Source (Unit_Name : String; SID_Name : String; Instrumenter : in out Language_Instrumenter'Class; - Files_Of_Interest : String_Sets.Set; + Files_Of_Interest : File_Sets.Set; Prj : Prj_Desc) is Context : aliased Coverage.Context := Coverage.Get_Context; diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index c001b01cf..5ec5ae532 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -29,8 +29,9 @@ with Interfaces; use Interfaces; with GNATCOLL.VFS; use GNATCOLL.VFS; -with Command_Line; use Command_Line; -with Hex_Images; use Hex_Images; +with Command_Line; use Command_Line; +with Files_Handling; use Files_Handling; +with Hex_Images; use Hex_Images; package body Instrument is @@ -550,12 +551,16 @@ package body Instrument is if Lang in C_Family_Language then Compiler_Opts.Append (Desc.Search_Paths); - if Desc.Compiler_Options_Unit.Contains (Unit_Name) then - Compiler_Opts.Append - (Desc.Compiler_Options_Unit.Element (Unit_Name)); - else - Compiler_Opts.Append (Desc.Compiler_Options (Lang)); - end if; + declare + File : constant Virtual_File := Create_Normalized (+Unit_Name); + begin + if Desc.Compiler_Options_Unit.Contains (File) then + Compiler_Opts.Append + (Desc.Compiler_Options_Unit.Element (File)); + else + Compiler_Opts.Append (Desc.Compiler_Options (Lang)); + end if; + end; if not Compiler_Opts.Is_Empty then case C_Family_Language (Lang) is when CPP_Language => diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index c36e2934d..b57bc8348 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -26,6 +26,7 @@ with GNATCOLL.Projects; use GNATCOLL.Projects; with Types; use Types; with Checkpoints; use Checkpoints; +with Files_Handling; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with SC_Obligations; use SC_Obligations; with Subprocesses; use Subprocesses; @@ -279,7 +280,7 @@ package Instrument is -- For languages resorting to the compiler to preprocess sources, list -- of compiler switches to pass to the preprocessor invocation. - Compiler_Options_Unit : String_Vectors_Maps.Map; + Compiler_Options_Unit : Files_Handling.File_To_String_Vectors_Maps.Map; -- Compiler switches applying to a specific unit Search_Paths : String_Vectors.Vector; diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index a7d179a99..0b3f9cdd4 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -22,6 +22,7 @@ with GNAT.Strings; use GNAT.Strings; with Calendar_Utils; use Calendar_Utils; with Command_Line; use Command_Line; +with Files_Handling; use Files_Handling; with Logging; with SC_Obligations; with Strings; use Strings; @@ -151,7 +152,7 @@ package Switches is SPARK_Compat : Boolean := False; -- When True, tune the instrumenter for maximum SPARK compatibility - Files_Of_Interest : String_Sets.Set; + Files_Of_Interest : File_Sets.Set; -- Lower abstraction for files of interest, when the --files switch is -- used. From c526f79aa15fd0c4ff9f51fdc60035c20d8e5a9a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 6 Dec 2023 17:39:00 +0100 Subject: [PATCH 0568/1483] Minor cosmetic changes --- tools/gnatcov/compiler_wrappers-gcc.adb | 4 ++-- tools/gnatcov/gnatcov_bits_specific.adb | 1 + tools/gnatcov/instrument-common.adb | 4 ++-- tools/gnatcov/instrument.adb | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 3b30500f2..86664a2a8 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -765,8 +765,8 @@ begin Comp_DB := Parse_Compiler_Driver_Command (Context, Instr_Dir, Compiler_Driver_Opts); - -- Generate an artificial project description to pass compiler - -- switches and default spec / body suffixes. + -- Generate an artificial project description to pass compiler switches and + -- default spec / body suffixes. Prj.Prj_Name := +"main"; Prj.Output_Dir := +Instr_Dir.Directory_Name; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 8de0ca907..01c7de67b 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1398,6 +1398,7 @@ begin end; when Cmd_Instrument_Source => + -- For the instrument-source command, and for the instrument-main, -- we do not check the command-line semantics as these commands are -- internal and spawned by a gnatcov main process. They are thus by diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 18a44011f..891b2b8df 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -456,8 +456,8 @@ package body Instrument.Common is Args.Append (Dir); end loop; - -- If the file was already pre-processed, do not pass macro command - -- line switches. Since preprocessed code can contain names of defined + -- If the file was already preprocessed, do not pass macro command line + -- switches. Since preprocessed code can contain names of defined -- macros, passing macro arguments for the parsing step could trigger -- other expansions, and thus feed the parser with unexpected code. diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 5ec5ae532..36664d627 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -529,7 +529,7 @@ package body Instrument is Unit_Name : Unbounded_String; Lang : Src_Supported_Language) return String_Vectors.Vector is - Result : String_Vectors.Vector; + Result : String_Vectors.Vector; Compiler_Opts : String_Vectors.Vector; begin -- Pass the right body / spec suffixes From 235f4feec579eb306a904498ecd585d260c79a0f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 6 Dec 2023 17:41:25 +0100 Subject: [PATCH 0569/1483] C/C++ instr: use the raw list of switches to preprocess the sources We currently have a selective list of switches that are passed on to the preprocessing invocation, which has proven to not be a scalable solution (the number of switches that can influence the preprocessing, notably the source search paths is pretty huge). This patch opts for a slightly different approach. As a reminder, we need to preprocess both with (1) the original compiler driver, and (2) with clang. We will now pass on all of the switches when preprocessing with the original compiler driver, without applying any filtering. That way we are ensured that this preprocessing will be correct, and will not be missing part of the user configuration, which could be the case before. We will still keep the selective list of switches to have control over the switches that are passed on to the clang preprocessing invocation. We must do that as, e.g. some gcc switches are not accepted by clang. Note that we do not _only_ use user specified switches to, e.g. know the source search paths: we also use the preprocessing output of (1). We retrieve, e.g. the list of search paths from this preprocessing output, so we expect that in practice, improving (1) will also make (2) more robust. And in the worst case scenario, the preprocessing step will yield different results for (1) and (2), in which case we will simply discard preprocessing information, which is what (2) is for. --- .../isystem/include/pkg.h | 5 ++ .../integrated_instrumentation/isystem/test.c | 8 +++ .../isystem/test.py | 57 +++++++++++++++++++ tools/gnatcov/compiler_wrappers-gcc.adb | 53 ++++++++++++----- tools/gnatcov/instrument-c.adb | 57 +++++++++++-------- tools/gnatcov/instrument-c.ads | 15 +++-- tools/gnatcov/instrument-c__stub.ads | 6 +- tools/gnatcov/instrument-common.adb | 2 + tools/gnatcov/instrument-common.ads | 4 ++ tools/gnatcov/instrument-config.adb | 6 +- tools/gnatcov/instrument-projects.adb | 5 +- tools/gnatcov/instrument.ads | 3 + 12 files changed, 172 insertions(+), 49 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/isystem/include/pkg.h create mode 100644 testsuite/tests/integrated_instrumentation/isystem/test.c create mode 100644 testsuite/tests/integrated_instrumentation/isystem/test.py diff --git a/testsuite/tests/integrated_instrumentation/isystem/include/pkg.h b/testsuite/tests/integrated_instrumentation/isystem/include/pkg.h new file mode 100644 index 000000000..96dfea3e5 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/isystem/include/pkg.h @@ -0,0 +1,5 @@ +static int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/isystem/test.c b/testsuite/tests/integrated_instrumentation/isystem/test.c new file mode 100644 index 000000000..14eebbdb7 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/isystem/test.c @@ -0,0 +1,8 @@ +#include "pkg.h" + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/isystem/test.py b/testsuite/tests/integrated_instrumentation/isystem/test.py new file mode 100644 index 000000000..a1100b6dc --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/isystem/test.py @@ -0,0 +1,57 @@ +""" +Regression test: checks that gnatcov accounts for the isystem switch. It used +to plainly ignore it, which resulted in preprocessing failures. +""" + +import os +import os.path + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +# Setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + "--files=../test.c", + "--compilers=gcc", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=os.getcwd()) + +# Then, run the compile + link command +cmdrun( + [ + "gcc", + "-o", + "test", + os.path.join("..", "test.c"), + "-isystem", + os.path.join("..", "include"), + ], + for_pgm=False, +) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=test.c.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports("*.xcov", {"test.c.xcov": {"+": {6, 7}}}) + +thistest.result() diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 86664a2a8..95e7808e7 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -180,12 +180,14 @@ procedure Compiler_Wrappers.Gcc is function Parse_Compiler_Driver_Command (Context : in out Parsing_Context; + Prj : in out Prj_Desc; Tmp_Dir : Temporary_Directory; Args : String_Vectors.Vector) return Compilation_Database; -- Parse a compiler driver command function Parse_Compilation_Command (Context : in out Parsing_Context; + Prj : in out Prj_Desc; Command : String_Vectors.Vector) return Compilation_Command_Type; -- Parse a compilation command @@ -296,6 +298,7 @@ procedure Compiler_Wrappers.Gcc is function Parse_Compiler_Driver_Command (Context : in out Parsing_Context; + Prj : in out Prj_Desc; Tmp_Dir : Temporary_Directory; Args : String_Vectors.Vector) return Compilation_Database is @@ -340,7 +343,7 @@ procedure Compiler_Wrappers.Gcc is then declare CC_Command : constant Compilation_Command_Type := - Parse_Compilation_Command (Context, Command); + Parse_Compilation_Command (Context, Prj, Command); begin if CC_Command /= No_Compilation_Command then Result.Compilation_Commands.Append (CC_Command); @@ -382,9 +385,15 @@ procedure Compiler_Wrappers.Gcc is function Parse_Compilation_Command (Context : in out Parsing_Context; + Prj : in out Prj_Desc; Command : String_Vectors.Vector) return Compilation_Command_Type is use String_Vectors; + PP_Args : String_Vectors.Vector; + -- List of arguments that should be passed to the preprocessor + -- invocation: basically all of the arguments except the compiled source + -- and the -o switch. + Result : Compilation_Command_Type; Cur : Cursor := First (Command); begin @@ -394,6 +403,11 @@ procedure Compiler_Wrappers.Gcc is Result.Language := C_Language; end if; + -- Skip the first argument as it is the compiler executable, and not + -- a compiler argument. + + Cur := Next (Cur); + while Has_Element (Cur) loop declare Arg : constant Unbounded_String := @@ -403,11 +417,13 @@ procedure Compiler_Wrappers.Gcc is -- would find the positional argument but it is not -- straightforward. - if Arg = "-dumpbase" or else Arg = "-dumpbase-ext" then + if +Arg in "-dumpbase" | "-dumpbase-ext" then Cur := Next (Cur); - end if; - if Ends_With (Arg, ".c") + -- TODO??? the user can configure the file extension and the + -- implementation should be resilient to this. + + elsif Ends_With (Arg, ".c") or else Ends_With (Arg, ".cc") or else Ends_With (Arg, ".cpp") or else Ends_With (Arg, ".cxx") @@ -421,8 +437,11 @@ procedure Compiler_Wrappers.Gcc is & ". Keeping the former, which was parsed before."); end if; elsif Arg = "-o" then + Cur := Next (Cur); Result.Target := Create_Normalized (+String_Vectors.Element (Cur)); + else + PP_Args.Append (Arg); end if; end; Cur := Next (Cur); @@ -431,6 +450,8 @@ procedure Compiler_Wrappers.Gcc is if Result.File = No_File or else Result.Target = No_File then return No_Compilation_Command; end if; + Prj.Compiler_Driver (Result.Language) := Command.First_Element; + Prj.Compiler_Options_Unit.Insert (Result.File, PP_Args); Context.Source_Mapping.Include (Result.Target, Result.File); return Result; end Parse_Compilation_Command; @@ -762,8 +783,8 @@ begin -- Parse the compiler driver invocation - Comp_DB := - Parse_Compiler_Driver_Command (Context, Instr_Dir, Compiler_Driver_Opts); + Comp_DB := Parse_Compiler_Driver_Command + (Context, Prj, Instr_Dir, Compiler_Driver_Opts); -- Generate an artificial project description to pass compiler switches and -- default spec / body suffixes. @@ -774,8 +795,6 @@ begin (C_Language => +".h", CPP_Language => +".hh", others => <>); Prj.Body_Suffix := (C_Language => +".c", CPP_Language => +".cc", others => <>); - Prj.Compiler_Driver := (others => Context.Orig_Compiler_Driver); - Prj.Compiler_Options := (others => Compiler_Driver_Opts); -- Then, invoke the right set of gnatcov commands @@ -791,12 +810,15 @@ begin Comp_DB.Compilation_Commands.Reference (Cur); Instrumenter : Language_Instrumenter'Class := (case Comp_Command.Language is - when C_Language => Create_C_Instrumenter (Instr_Config.Tag), - when CPP_Language => Create_CPP_Instrumenter (Instr_Config.Tag), - when others => - raise Program_Error - with "Unsupported language for integrated" - & " instrumentation"); + when C_Language => + Create_C_Instrumenter + (Instr_Config.Tag, Integrated_Instrumentation), + when CPP_Language => + Create_CPP_Instrumenter + (Instr_Config.Tag, Integrated_Instrumentation), + when others => + raise Program_Error + with "Unsupported language for integrated instrumentation"); Fullname : constant String := +Comp_Command.File.Full_Name; Simple_Name : constant String := +Comp_Command.File.Base_Name; @@ -861,7 +883,8 @@ begin if Comp_DB.Link_Command /= No_Link_Command then declare Instrumenter : constant Language_Instrumenter'Class := - Create_C_Instrumenter (Instr_Config.Tag); + Create_C_Instrumenter + (Instr_Config.Tag, Integrated_Instrumentation); -- Emit the buffers list unit as a C compilation unit as it is -- compilable by a C / C++ compiler, which are the languages -- supported by the integrated instrumentation scheme. diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index bc527a414..4797d2c76 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -72,12 +72,11 @@ package body Instrument.C is -- Preprocessing utilities -- ------------------------------ - type Macro_Set_Access is access Macro_Set; - type Macro_Set_Cst_Access is access constant Macro_Set; - - function Builtin_Macros + procedure Get_Builtin_Macros (Lang, Compiler, Output_Dir : String; - Compiler_Switches : String_Vectors.Vector) return Macro_Set_Cst_Access; + Compiler_Switches : String_Vectors.Vector; + Instr_Mode : Instrumentation_Mode; + Result : out Macro_Set); -- Return the list of built-in macros for the given compiler, language and -- according to the compiler switches. Output_Dir is used to store a -- temporary file. @@ -2499,18 +2498,18 @@ package body Instrument.C is -- Builtin_Macros -- -------------------- - function Builtin_Macros + procedure Get_Builtin_Macros (Lang, Compiler, Output_Dir : String; - Compiler_Switches : String_Vectors.Vector) return Macro_Set_Cst_Access + Compiler_Switches : String_Vectors.Vector; + Instr_Mode : Instrumentation_Mode; + Result : out Macro_Set) is use Ada.Characters.Handling; PID : constant Unsigned_64 := Unsigned_64 (Pid_To_Integer (Current_Process_Id)); - L : constant String := To_Lower (Lang); - Result : constant Macro_Set_Access := new Macro_Set; - + L : constant String := To_Lower (Lang); Args : String_Vectors.Vector; Basename : constant String := Ada.Directories.Simple_Name (Compiler) @@ -2522,8 +2521,16 @@ package body Instrument.C is -- Run the preprocessor on an empty file and write the -- preprocessed sources to Filename. - Args.Append (+"-x"); - Args.Append (+L); + -- If we are in the integrated instrumentation mode, we use the compiler + -- (as opposed to the compiler driver) to preprocess the source file. + -- The compiler - which is specific to the language - does not accept + -- the -x switch, so do not pass it in this case. + + if Instr_Mode = Project_Instrumentation then + Args.Append (+"-x"); + Args.Append (+L); + end if; + Args.Append (Compiler_Switches); Args.Append (+"-E"); Args.Append (+"-dM"); @@ -2561,8 +2568,7 @@ package body Instrument.C is end loop; Close (File); Delete_File (Filename); - return Macro_Set_Cst_Access (Result); - end Builtin_Macros; + end Get_Builtin_Macros; ----------------------- -- Preprocess_Source -- @@ -2611,14 +2617,18 @@ package body Instrument.C is (Command => Prj.Compiler_Driver (Instrumenter.Language), others => <>); - -- Add the preprocessing flag - if Keep_Comments then Append_Arg (Cmd, "-C"); end if; + -- Add the preprocessing flag + Append_Arg (Cmd, "-E"); - Add_Options (Cmd.Arguments, Options, Pass_Builtins => False); + + -- Add all of the compiler / compiler driver options to the + -- preprocessing command line. + + Append_Args (Cmd, Options.Raw_Switches); Append_Arg (Cmd, Filename); @@ -4582,12 +4592,13 @@ package body Instrument.C is -- Now, we can generate the preprocessor configuration (i.e. the set -- of predefined macros). - Self.Builtin_Macros := - Builtin_Macros - (Image (C_Family_Language (Instrumenter.Language)), - +Prj.Compiler_Driver (Instrumenter.Language), - +Prj.Output_Dir, - Self.Compiler_Switches).all; + Get_Builtin_Macros + (Image (C_Family_Language (Instrumenter.Language)), + +Prj.Compiler_Driver (Instrumenter.Language), + +Prj.Output_Dir, + Self.Compiler_Switches, + Instrumenter.Instr_Mode, + Self.Builtin_Macros); end Import_Options; --------------------------- diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index bb8aa761c..66ccfc712 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -40,7 +40,10 @@ with Slocs; use Slocs; package Instrument.C is type C_Family_Instrumenter_Type is - abstract new Language_Instrumenter with null record; + abstract new Language_Instrumenter with + record + Instr_Mode : Instrumentation_Mode; + end record; -- Common instrumentation primitives for C/C++ overriding procedure Instrument_Unit @@ -120,8 +123,9 @@ package Instrument.C is is (C_Language); function Create_C_Instrumenter - (Tag : Unbounded_String) return C_Instrumenter_Type - is (C_Instrumenter_Type'(Tag => Tag)); + (Tag : Unbounded_String; + Instr_Mode : Instrumentation_Mode) return C_Instrumenter_Type + is (C_Instrumenter_Type'(Tag => Tag, Instr_Mode => Instr_Mode)); -- Create a C instrumenter. See the definition of the -- Language_Instrumenter type for the arguments semantic. @@ -138,8 +142,9 @@ package Instrument.C is is ("extern ""C"" "); function Create_CPP_Instrumenter - (Tag : Unbounded_String) return CPP_Instrumenter_Type - is (CPP_Instrumenter_Type'(Tag => Tag)); + (Tag : Unbounded_String; + Instr_Mode : Instrumentation_Mode) return CPP_Instrumenter_Type + is (CPP_Instrumenter_Type'(Tag => Tag, Instr_Mode => Instr_Mode)); -- Create a C++ instrumenter. See the definition of the -- Language_Instrumenter type for the arguments semantic. diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index 287fd99b9..16dc0445e 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -38,7 +38,8 @@ package Instrument.C is is (C_Language); function Create_C_Instrumenter - (Tag : Unbounded_String) return C_Instrumenter_Type + (Tag : Unbounded_String; + Instr_Mode : Instrumentation_Mode) return C_Instrumenter_Type is (C_Instrumenter_Type'(others => <>)); type CPP_Instrumenter_Type is @@ -50,7 +51,8 @@ package Instrument.C is is (CPP_Language); function Create_CPP_Instrumenter - (Tag : Unbounded_String) return CPP_Instrumenter_Type + (Tag : Unbounded_String; + Instr_Mode : Instrumentation_Mode) return CPP_Instrumenter_Type is (CPP_Instrumenter_Type'(others => <>)); procedure Postprocess_Source diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 891b2b8df..0528eaf14 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -601,6 +601,8 @@ package body Instrument.Common is -- Start of processing for Import_From_Args begin + Self.Raw_Switches.Append_Vector (Args); + while I <= Last loop declare A : constant String := +Args (I); diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 913cdf367..4c925d256 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -556,6 +556,10 @@ package Instrument.Common is -- List of compiler switches that can influence the file preprocessing. -- The list should be amended alongside our discoveries. It is -- currently: -std, -fno-exceptions, -fno-rtti, -W* switches. + + Raw_Switches : String_Vectors.Vector; + -- List of switches passed to the compiler driver without filtering + end record; -- Options to analyze (preprocess and/or parse) a compilation unit diff --git a/tools/gnatcov/instrument-config.adb b/tools/gnatcov/instrument-config.adb index 9d5bff6df..34ba19767 100644 --- a/tools/gnatcov/instrument-config.adb +++ b/tools/gnatcov/instrument-config.adb @@ -45,8 +45,10 @@ begin Preprocessor_Data_Filename => +Args.String_Args (Opt_Ada_Preprocessor_Data).Value); when C_Language => - return Create_C_Instrumenter (Tag => Tag); + return Create_C_Instrumenter + (Tag => Tag, Instr_Mode => Project_Instrumentation); when CPP_Language => - return Create_CPP_Instrumenter (Tag => Tag); + return Create_CPP_Instrumenter + (Tag => Tag, Instr_Mode => Project_Instrumentation); end case; end Instrument.Config; diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 2c0ae7bf9..52b433c62 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -1188,8 +1188,9 @@ begin Mapping_Filename => +IC.Mapping_File, Predefined_Source_Dirs => IC.Predefined_Source_Dirs, Preprocessor_Data_Filename => +IC.Ada_Preprocessor_Data_File); - C_Instrumenter := Create_C_Instrumenter (IC.Tag); - CPP_Instrumenter := Create_CPP_Instrumenter (IC.Tag); + C_Instrumenter := Create_C_Instrumenter (IC.Tag, Project_Instrumentation); + CPP_Instrumenter := + Create_CPP_Instrumenter (IC.Tag, Project_Instrumentation); if Dump_Config.Trigger = Manual then diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index b57bc8348..6b813a44a 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -42,6 +42,9 @@ package Instrument is Parallelism_Level : Natural := 1; + type Instrumentation_Mode is + (Project_Instrumentation, Integrated_Instrumentation); + function Language_Kind (Language : Some_Language) return Any_Language_Kind; -- Returns the language kind (unit-based or file-based) for the given From b0fa115e86ec32ec9e5c866b350fe99e950a32ef Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 27 Nov 2023 15:06:38 +0100 Subject: [PATCH 0570/1483] Minor cosmetic changes --- tools/gnatcov/traces_elf.adb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/traces_elf.adb b/tools/gnatcov/traces_elf.adb index b7b454e53..22932f55d 100644 --- a/tools/gnatcov/traces_elf.adb +++ b/tools/gnatcov/traces_elf.adb @@ -236,7 +236,7 @@ package body Traces_Elf is pragma Assert (L.Kind = R.Kind); function Names_Lt (LN, RN : String_Access) return Boolean; - -- Compare desginated strings, null is higher than any non-null string + -- Compare designated strings, null is higher than any non-null string -------------- -- Names_Lt -- @@ -775,7 +775,7 @@ package body Traces_Elf is -- of interest, or until we can conclude that there is no such -- Addres_Info. -- - -- We can conclude that PC is contained in an Addres_Info or not as soon + -- We can conclude that PC is contained in an Address_Info or not as soon -- as we reach a top level Info. If PC is not contained in that top -- level Address_Info, then PC isn't contained in any of those. @@ -3057,8 +3057,7 @@ package body Traces_Elf is Reset_Lines; when DW_LNE_set_address => - Read_Address - (Exec, Base, Off, Arch.Arch_Addr'Size / 8, Pc); + Read_Address (Exec, Base, Off, Arch.Arch_Addr'Size / 8, Pc); Base_Pc := Pc; when DW_LNE_define_file => @@ -3340,7 +3339,7 @@ package body Traces_Elf is function Get_Sloc (Set : Address_Info_Sets.Set; - PC : Pc_Type) return Source_Location + PC : Pc_Type) return Source_Location is SL : constant Source_Locations := Get_Slocs (Set, PC, Non_Empty_Only => True); From 162d2452b71c5670b8ea94f7b06bc07bd04ba7fd Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 13 Dec 2023 11:55:12 +0100 Subject: [PATCH 0571/1483] gnatcov testsuite: Isolate the LAL dependency --- testsuite/SCOV/instr.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index b8f01c583..de69eb739 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -5,8 +5,6 @@ from e3.fs import mkdir -import libadalang as lal - from SUITE.context import thistest from SUITE.cutils import contents_of, ext, indent from SUITE.tutils import RUNTIME_INFO, GNATCOV_INFO, locate_gpr_file, xcov @@ -197,6 +195,11 @@ def add_dumper_lch_hook(project, obj_dir, subdirs, main_unit): :param str main_unit: Name of the main unit for which the hook will call the coverage buffers dump routine. """ + # Isolate the dependency to the libadalang module. This means that a user + # testing natively (thus not needing the support for last chance handlers) + # will not need to install the libadalang python module. + import libadalang as lal + # Amend obj_dir according to subdirs, if applicable if subdirs: obj_dir = os.path.join(obj_dir, subdirs) From 1fccd8f5f5d55031ebbb43c12dddf4b5fcb630c5 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 14 Dec 2023 08:44:11 +0000 Subject: [PATCH 0572/1483] GNATcov_RTS: remove unused WITH clauses for GNATcov_RTS.Base_IO --- tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb | 1 - tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads | 1 - 2 files changed, 2 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb index 9dfc22f1c..3b5abdeb6 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb @@ -24,7 +24,6 @@ -- This unit needs to be compilable with Ada 95 compilers -with GNATcov_RTS.Base_IO; use GNATcov_RTS.Base_IO; with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; package body GNATcov_RTS.Traces.Output.Base64 is diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads index 0c3bbaf19..e92b08e20 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads @@ -28,7 +28,6 @@ with Ada.Command_Line; with Interfaces; use Interfaces; -with GNATcov_RTS.Base_IO; use GNATcov_RTS.Base_IO; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; package GNATcov_RTS.Traces.Output.Files is From fbdb6a5a0fc17818b5e7fa51eaff9e90d2cbf030 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 14 Dec 2023 08:45:29 +0000 Subject: [PATCH 0573/1483] GNATcov_RTS.Buffers.Witness: make constant and mark as unreferenced This fixes warnings with GNAT 5.04a1, which does not follow the convention not to warn about entities being unreferenced when they are called "Ignore". --- tools/gnatcov/rts/gnatcov_rts-buffers.adb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.adb b/tools/gnatcov/rts/gnatcov_rts-buffers.adb index 35356eab8..354483dd7 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.adb +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.adb @@ -77,8 +77,9 @@ package body GNATcov_RTS.Buffers is ------------- procedure Witness (Buffer_Address : System.Address; Bit : Bit_Id) is - Ignored : GNATcov_RTS_Bool := + Ignored : constant GNATcov_RTS_Bool := GNATcov_RTS_Witness (Buffer_Address, Bit); + pragma Unreferenced (Ignored); begin null; end Witness; From 98e2c73add9b5f6329321fa9ec0c09cc0cad5f9a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 14 Dec 2023 08:46:44 +0000 Subject: [PATCH 0574/1483] GNATcov_RTS: disable warnings for packages GNAT 5.04a1 warns that they are unused. These warnings are spurious: the imported "System" package is actually used in a package renaming, and the "Sys"/"Std" package renamings are part of the GNATcov_RTS API. --- tools/gnatcov/rts/gnatcov_rts.ads | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/gnatcov/rts/gnatcov_rts.ads b/tools/gnatcov/rts/gnatcov_rts.ads index 2a29747cb..ca9b500c1 100644 --- a/tools/gnatcov/rts/gnatcov_rts.ads +++ b/tools/gnatcov/rts/gnatcov_rts.ads @@ -28,6 +28,7 @@ -- This unit needs to be compilable with Ada 95 compilers with System; +pragma Warnings (Off, System); package GNATcov_RTS is @@ -35,6 +36,8 @@ package GNATcov_RTS is package Std renames Standard; package Sys renames System; + pragma Warnings (Off, Std); + pragma Warnings (Off, Sys); Version : constant := 5; -- For compatibility with the GNATcoverage in use, GNATcov_RTS is From 089177a245c819401d6e662c24abab123aedbdd0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 14 Dec 2023 08:56:16 +0000 Subject: [PATCH 0575/1483] GNATcov_RTS: disable warnings for No_Exception_Propagation mode --- tools/gnatcov/rts/gnatcov_rts.gpr | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts.gpr b/tools/gnatcov/rts/gnatcov_rts.gpr index 4e832e618..fc4245106 100644 --- a/tools/gnatcov/rts/gnatcov_rts.gpr +++ b/tools/gnatcov/rts/gnatcov_rts.gpr @@ -123,8 +123,23 @@ library project GNATcov_RTS is end case; for Default_Switches ("C") use - ("-O2", "-g", "-Wall", "-Wextra") & C_Extra_Switches; - for Default_Switches ("Ada") use ("-O2", "-g", "-gnatwa"); + ("-O2", "-g", "-Wall", "-Wextra") & C_Extra_Switches; + for Default_Switches ("Ada") use + ("-O2", "-g", + + -- Enable all warnings to raise awareness about issues, but do not + -- treat them as errors so that users are not blocked because of + -- warnings. + + "-gnatwa", + + -- Disable warnings for No_Exception_Propagation: this restriction is + -- common on restricted runtimes, but are not actionable in the + -- context of the coverage runtime: we have to convert size_t values + -- to Natural, we have to assume that addresses are correctly aligned + -- in "for X'Address use Y;" clauses. + + "-gnatw.X"); end Compiler; package Install is From eb8006822854d3d31303f3b1d3f0120592bde547 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 13 Dec 2023 20:39:18 +0000 Subject: [PATCH 0576/1483] Disable options that do not make sense for "gnatcov setup-integration" --- tools/gnatcov/command_line.ads | 27 +++++++++++++++++-------- tools/gnatcov/gnatcov_bits_specific.adb | 2 +- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 6cb46873b..928ab0902 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -171,7 +171,14 @@ package Command_Line is -- Set of string list options we support. More complete descriptions below. subtype Cmd_Instrument is Command_Type - range Cmd_Instrument_Project .. Cmd_Setup_Integration; + range Cmd_Instrument_Project .. Cmd_Instrument_Main; + + subtype Cmd_Instrument_With_Setup is Command_Type + range Cmd_Instrument_Project .. Cmd_Setup_Integration; + + subtype Cmd_All_Setups is Command_Type + with Static_Predicate => + Cmd_All_Setups in Cmd_Setup | Cmd_Setup_Integration; package Parser is new Argparse (Command_Type, Bool_Options, String_Options, String_List_Options); @@ -590,7 +597,7 @@ package Command_Line is (Long_Name => "--relocate-build-tree", Help => "Relocate object, library and exec directories in the" & " current directory.", - Commands => (Cmd_Setup => False, others => True), + Commands => (Cmd_All_Setups => False, others => True), Internal => False)); String_Infos : constant String_Option_Info_Array := @@ -600,6 +607,7 @@ package Command_Line is Help => "Use GPR as root project to locate SCOs, select" & " units to analyze and find default options.", Commands => (Cmd_Setup + | Cmd_Setup_Integration | Cmd_Instrument_Source | Cmd_Instrument_Main => False, others => True), @@ -612,7 +620,7 @@ package Command_Line is & " designates the topmost directory of the tree of" & " projects. By default the root project's directory" & " is used.", - Commands => (Cmd_Setup => False, others => True), + Commands => (Cmd_All_Setups => False, others => True), At_Most_Once => True, Internal => False), Opt_Subdirs => Create @@ -621,7 +629,7 @@ package Command_Line is Help => "When using project files, look for ALI/SID files in" & " the provided SUBDIR of the projects' build" & " directory.", - Commands => (Cmd_Setup => False, others => True), + Commands => (Cmd_All_Setups => False, others => True), At_Most_Once => False, Internal => False), Opt_Target => Create @@ -638,6 +646,7 @@ package Command_Line is & " ""Target""/""Runtime"" attributes. It is also" & " needed for ""run"" commands without a project" & " file.", + Commands => (Cmd_Setup_Integration => False, others => True), At_Most_Once => True, Internal => False), Opt_Runtime => Create @@ -647,6 +656,7 @@ package Command_Line is & " to build the analyzed programs. If project files" & " don't already set the runtime, this is required" & " for correct project files processing.", + Commands => (Cmd_Setup_Integration => False, others => True), At_Most_Once => True, Internal => False), Opt_Config => Create @@ -715,8 +725,8 @@ package Command_Line is Commands => (Cmd_Run | Cmd_Coverage | Cmd_Convert - | Cmd_Instrument => True, - others => False), + | Cmd_Instrument_With_Setup => True, + others => False), At_Most_Once => False, Internal => False), Opt_Text_Start => Create @@ -986,7 +996,7 @@ package Command_Line is "Name of the installed instrumentation runtime project (see" & " ""gnatcov setup""'s ""--install-name"" option). By default, use" & " ""gnatcov_rts"".", - Commands => (Cmd_Instrument => True, others => False), + Commands => (Cmd_Instrument_With_Setup => True, others => False), At_Most_Once => False, Internal => False), @@ -1128,6 +1138,7 @@ package Command_Line is Help => "Focus on specific projects within the transitive" & " closure reachable from the root designated by -P.", Commands => (Cmd_Setup + | Cmd_Setup_Integration | Cmd_Instrument_Source | Cmd_Instrument_Main => False, others => True), @@ -1146,7 +1157,7 @@ package Command_Line is (Short_Name => "-X", Pattern => "[NAME]=[VALUE]", Help => "Define a scenario variable for project files.", - Commands => (Cmd_Setup => False, others => True), + Commands => (Cmd_All_Setups => False, others => True), Internal => False), Opt_Eargs => Create (Long_Name => "-eargs", diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 01c7de67b..da9b044f8 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1029,7 +1029,7 @@ procedure GNATcov_Bits_Specific is & " is missing (required for ""convert"")"); end if; - when Cmd_Instrument => + when Cmd_Instrument_With_Setup => -- Ensure we have a source coverage level. If not, we might have -- either an object level specified, or possibly no --level at From 9a6fabfdd6c24f3cd73ab3808170d386ea13a5af Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 13 Dec 2023 20:57:52 +0000 Subject: [PATCH 0577/1483] 185-setup-warnings: do not install gnatcov_rts in gprbuild's prefix MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Nothing in the whole testsuite is supposed to modify gprbuild's installation prefix: in general the execution of tests must be self-contained, without side effect for the environment. This issue was found running the testsuite with the gnatcov_rts used by the whole testsuite installed in gnatcov_rts: during the execution of the 185-setup-warnings testcase, the installed project was temporarily unavailable, causing the failure of the other tests running in parallel. --- testsuite/SUITE/tutils.py | 9 +++++++++ testsuite/tests/185-setup-warnings/test.py | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 4a5fe2f26..060018f65 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -757,6 +757,15 @@ def xcov(args, out=None, err=None, inp=None, env=None, register_failure=True, arguments. """ + # Defensive code: running "gnatcov setup" with no prefix will install + # gnatcov_rts in gprbuild's prefix, i.e. the current test will try to + # modify a global resource. This is always an error, so reject it before it + # causes hard to trace damage elsewhere. + assert ( + args[0] != "setup" + or any(arg.startswith("--prefix") for arg in args) + ) + # Make ARGS a list from whatever it is, to allow unified processing. # Then fetch the requested command, always first: args = to_list(args) diff --git a/testsuite/tests/185-setup-warnings/test.py b/testsuite/tests/185-setup-warnings/test.py index 6830b8cc0..132b1c185 100644 --- a/testsuite/tests/185-setup-warnings/test.py +++ b/testsuite/tests/185-setup-warnings/test.py @@ -14,6 +14,6 @@ tmp = Wdir("tmp_") filename = "setup.log" -xcov(["setup", "-q"], out=filename, force_project_args=True) +xcov(["setup", "--prefix=.", "-q"], out=filename, force_project_args=True) thistest.fail_if_not_equal("gnatcov setup output", "", contents_of(filename)) thistest.result() From a70c7340accb03276237d08a5e620a24c1d7f1f8 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 14 Dec 2023 11:48:31 +0100 Subject: [PATCH 0578/1483] [integrated instr] Silence execution time statistics ... When retrieving the built-in macros using e.g. `cc1 -E -dM -`. By default, the compiler outputs execution time statistics in addition to macro definition, which results in gnatcov outputting warnings. Deactivate these using the -quiet switch. --- .../tests/integrated_instrumentation/isystem/test.py | 10 +++++++++- tools/gnatcov/instrument-c.adb | 7 +++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/integrated_instrumentation/isystem/test.py b/testsuite/tests/integrated_instrumentation/isystem/test.py index a1100b6dc..857b38d60 100644 --- a/testsuite/tests/integrated_instrumentation/isystem/test.py +++ b/testsuite/tests/integrated_instrumentation/isystem/test.py @@ -7,7 +7,7 @@ import os.path from SUITE.control import env -from SUITE.cutils import Wdir +from SUITE.cutils import contents_of, Wdir from SCOV.minicheck import check_xcov_reports from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov @@ -27,6 +27,7 @@ env.add_search_path(env_var="PATH", path=os.getcwd()) # Then, run the compile + link command +gcc_output = "gcc.out" cmdrun( [ "gcc", @@ -36,9 +37,16 @@ "-isystem", os.path.join("..", "include"), ], + out=gcc_output, for_pgm=False, ) +thistest.fail_if_not_equal( + "compiler output", + "", + contents_of(gcc_output), +) + # Run the executable cmdrun(["test"], for_pgm=False) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 4797d2c76..9a08c5db8 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2529,6 +2529,13 @@ package body Instrument.C is if Instr_Mode = Project_Instrumentation then Args.Append (+"-x"); Args.Append (+L); + else + -- Add the -quiet switch to prevent the compiler from outputting + -- execution time statistics. TODO??? check whether this is compiler + -- specific (cc1 / cc1plus) when implementing integrated + -- instrumentation support for other compilers. + + Args.Append (+"-quiet"); end if; Args.Append (Compiler_Switches); From bcd1fcd947f8d67eed0c4b66a4a25a6b8c9a2942 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 13 Dec 2023 20:38:27 +0000 Subject: [PATCH 0579/1483] instrument-setup_config.adb: minor reformatting --- tools/gnatcov/instrument-setup_config.adb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index 9d06711ff..1fb325013 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -472,10 +472,10 @@ package body Instrument.Setup_Config is end; Result.Tag := Config_JSON.Get ("tag"); - Result.GNATcov_RTS_Include_Dir := - Config_JSON.Get ("gnatcov_rts_include_dir"); - Result.GNATcov_RTS_Object_Dir := - Config_JSON.Get ("gnatcov_rts_object_dir"); + Result.GNATcov_RTS_Include_Dir := + Config_JSON.Get ("gnatcov_rts_include_dir"); + Result.GNATcov_RTS_Object_Dir := + Config_JSON.Get ("gnatcov_rts_object_dir"); return Result; end Load_Config; From ccdf421f28f6a3bfc1ab2b6a378bc473ee90e26d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 14 Dec 2023 14:53:20 +0000 Subject: [PATCH 0580/1483] traces_elf.adb: fix line length --- tools/gnatcov/traces_elf.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/traces_elf.adb b/tools/gnatcov/traces_elf.adb index 22932f55d..deaf1fa2a 100644 --- a/tools/gnatcov/traces_elf.adb +++ b/tools/gnatcov/traces_elf.adb @@ -775,8 +775,8 @@ package body Traces_Elf is -- of interest, or until we can conclude that there is no such -- Addres_Info. -- - -- We can conclude that PC is contained in an Address_Info or not as soon - -- as we reach a top level Info. If PC is not contained in that top + -- We can conclude that PC is contained in an Address_Info or not as + -- soon as we reach a top level Info. If PC is not contained in that top -- level Address_Info, then PC isn't contained in any of those. Candidate := Set.Floor (PC_Addr'Unchecked_Access); From 6f9cac69864a590dee8b39dfd93cd1308b17ddac Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 15 Dec 2023 10:17:42 +0000 Subject: [PATCH 0581/1483] SUITE.tutils.xcov_suite_args: pass --config/--target/--RTS to setup cmds The "gnatcov setup" and "gnatcov setup-integration" commands are sensible to toolchain configuration (target and runtime), so let the testuite pass them the corresponding arguments. This fixes the recent regressions for "gnatcov setup-integration" on 32-bit platforms: we need to pass this command the --config flag so that it uses the 32-bit toolchains instead of the 64-bit ones. --- testsuite/SUITE/tutils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 060018f65..c14564ec6 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -622,7 +622,9 @@ def xcov_suite_args(covcmd, covargs, are True. """ project_handling_enabled = ( - force_project_args or any(arg.startswith('-P') for arg in covargs) + force_project_args + or covcmd in ("setup", "setup-integration") + or any(arg.startswith('-P') for arg in covargs) ) # If --config is asked and project handling is involved, pass it and stop From ccd06d8a679c1ce5ced5aa84149df2fdfc1304ad Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 15 Dec 2023 12:49:48 +0000 Subject: [PATCH 0582/1483] gnatcov_rts.gpr: restore support for old toolchains --- tools/gnatcov/rts/gnatcov_rts-base_io.adb | 5 +++ .../rts/gnatcov_rts-traces-output-base64.adb | 4 +++ tools/gnatcov/rts/gnatcov_rts.gpr | 31 +++++++++++++------ 3 files changed, 30 insertions(+), 10 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts-base_io.adb b/tools/gnatcov/rts/gnatcov_rts-base_io.adb index 346cbfdae..ae46fa21a 100644 --- a/tools/gnatcov/rts/gnatcov_rts-base_io.adb +++ b/tools/gnatcov/rts/gnatcov_rts-base_io.adb @@ -33,8 +33,13 @@ package body GNATcov_RTS.Base_IO is --------- procedure Put (S : GNATcov_RTS_String) is + + -- See the note about -gnatw.X in gnatcov_rts.gpr + + pragma Warnings (Off); Str : String (1 .. Integer (S.Length)); for Str'Address use S.Str; + pragma Warnings (On); begin GNAT.IO.Put (Str); end Put; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb index 3b5abdeb6..b329d9ed1 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb @@ -46,11 +46,15 @@ package body GNATcov_RTS.Traces.Output.Base64 is Exec_Date : Unsigned_64; User_Data : String := "") is begin + -- See the note about -gnatw.X in gnatcov_rts.gpr + + pragma Warnings (Off); Write_Trace_File_C ((Buffers_Groups'Length, Buffers_Groups'Address), (Program_Name'Address, Program_Name'Length), Exec_Date, (User_Data'Address, User_Data'Length)); + pragma Warnings (On); end Write_Trace_File; end GNATcov_RTS.Traces.Output.Base64; diff --git a/tools/gnatcov/rts/gnatcov_rts.gpr b/tools/gnatcov/rts/gnatcov_rts.gpr index fc4245106..fa8ddca9d 100644 --- a/tools/gnatcov/rts/gnatcov_rts.gpr +++ b/tools/gnatcov/rts/gnatcov_rts.gpr @@ -130,16 +130,27 @@ library project GNATcov_RTS is -- Enable all warnings to raise awareness about issues, but do not -- treat them as errors so that users are not blocked because of -- warnings. - - "-gnatwa", - - -- Disable warnings for No_Exception_Propagation: this restriction is - -- common on restricted runtimes, but are not actionable in the - -- context of the coverage runtime: we have to convert size_t values - -- to Natural, we have to assume that addresses are correctly aligned - -- in "for X'Address use Y;" clauses. - - "-gnatw.X"); + -- + -- Note that we would like to use the -gnatw.X switch here to disable + -- warnings for No_Exception_Propagation. This restriction is common + -- on restricted runtimes, but these warnings are not actionable in + -- the context of the coverage runtime: + -- + -- * We have to convert size_t values to Natural in order to + -- convert C strings into Ada's String type. + -- * We have to assume that addresses are correctly aligned in "for + -- X'Address use Y;" clauses. + -- + -- These operations necessarily involve implicit checks; short of a + -- gnatcov bug, these checks are never supposed to trigger, and so + -- it is legitimate for them to trigger the last chance handler. + -- + -- Since -gnatw.X is not available with old GNAT toolchain and since + -- we need gnatcov_rts.gpr to build with these toolchains, we resort + -- to temporarily disable warnings with "pragma Warnings" on several + -- occasions in GNATcov_RTS's sources. + + "-gnatwa"); end Compiler; package Install is From 0329736a190f1442c2069fe2a85e6b4360aae7fe Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 18 Dec 2023 14:16:48 +0000 Subject: [PATCH 0583/1483] CI: switch to anod-copy-components to use builds from test machines Instead of copying the whole build space for instrumented gnatcov, use anod-copy-components to copy its component only (saves disk space, archive compression/decompression time and upload/download time for the artifact), then use anod to install the instrumented gnatcov from that component. As a bonus, this makes the fingerprint business obsolete. --- .gitlab-ci.yml | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e8f521cd1..fa246cd9a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -58,8 +58,9 @@ build: - anod build --minimal gnatcov $EDGE_QUALIFIER - anod build --minimal gnatcov -Qinstr $EDGE_QUALIFIER - # Create the package - - tar czf $PACKAGE_ABSOLUTE_NAME -C / it/wave/x86_64-linux/$GCV_INSTR_BSN + # Package all components created so far + - anod-copy-components --standalone-export /it/wave /it/wave/exp-comps + - tar czf $PACKAGE_ABSOLUTE_NAME -C / it/wave/exp-comps - cd $CI_PROJECT_DIR - ls -l $PACKAGE_BASE_NAME @@ -115,10 +116,6 @@ build_community: - export PATH=/it/e3/bin:$PATH - *edge_vars - # Unpack the artifact then delete it - - tar zxf $PACKAGE_ABSOLUTE_NAME -C / - - rm -f $PACKAGE_ABSOLUTE_NAME - # Get the gnatcoverage-extra repository. If we're testing a 'sync/' branch, # expect the same for that repo. @@ -137,12 +134,12 @@ build_community: - *common_anod_bits - anod vcs --add-repo gnatcoverage-extra$EDGE_REPO_SUFFIX /tmp/gnatcoverage-extra - # Setup fingerprints so anod doesn't do unnecessary rebuilds and does not - # try to download gnatcov/edge: we have rebuilt it so we do not need to - # download the nightly one, which may not even exist (case of an edge build - # failure that was fixed on that day). - - mkdir -p fingerprints - - touch fingerprints/x86_64-linux.$GCV_INSTR_BSN.build.json.assume-unchanged + # Import components from the artifact and install the instrumented gnatcov, + # then remove temporaries to save disk space. + - tar zxf $PACKAGE_ABSOLUTE_NAME -C / + - anod-copy-components /it/wave/exp-comps /it/wave + - anod install gnatcov -Qinstr $EDGE_QUALIFIER + - rm -rf $PACKAGE_ABSOLUTE_NAME /it/wave/exp-comps # Setup the CI directory to host coverage results - mkdir $CI_PROJECT_DIR/coverage @@ -170,7 +167,7 @@ test_bin_traces: - *retrieve_gnatcoverage_extras_and_setup_anod_repo # Test using anod - - anod test gnatcov --target=leon3-elf -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER + - anod test gnatcov --minimal --target=leon3-elf -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER - TEST_BSN=$(anod eval --primitive=test gnatcov --target=leon3-elf -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER build_space_name) - mv leon3-elf-linux64/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report @@ -192,7 +189,7 @@ test_src_traces: - *retrieve_gnatcoverage_extras_and_setup_anod_repo # Test using anod - - anod test gnatcov -Qsrc-traces,instr $EDGE_QUALIFIER + - anod test gnatcov --minimal -Qsrc-traces,instr $EDGE_QUALIFIER - TEST_BSN=$(anod eval --primitive=test gnatcov -Qsrc-traces,instr $EDGE_QUALIFIER build_space_name) - mv x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report @@ -214,7 +211,7 @@ test_spark: - *retrieve_gnatcoverage_extras_and_setup_anod_repo # Test using anod - - anod test gnatcov -Qspark-tests,src-traces,instr $EDGE_QUALIFIER + - anod test gnatcov --minimal -Qspark-tests,src-traces,instr $EDGE_QUALIFIER - TEST_BSN=$(anod eval --primitive=test gnatcov -Qspark-tests,src-traces,instr $EDGE_QUALIFIER build_space_name) - mv x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report From 2c05c85d30f3c88a051c22f1a7f26608dc189081 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 18 Dec 2023 14:01:56 +0000 Subject: [PATCH 0584/1483] Clean up source version tracking for examples/support/ Set an object directory for lch.gpr so that build artifacts do not pollute "git status", and ignore the automatically generated conf.gpr file. --- .gitignore | 1 + tools/gnatcov/examples/support/lch.gpr | 1 + 2 files changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 673b8675a..e05ca0b2e 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ lib /tools/gnatcov/obj64/ /tools/gnatcov/obj-gnatcov_rts/ /tools/gnatcov/objlib64/ +/tools/gnatcov/examples/support/conf.gpr /tools/gnatcov/examples/support/lib /tools/gnatcov/examples/support/obj /tools/gnatcov/rts-instr diff --git a/tools/gnatcov/examples/support/lch.gpr b/tools/gnatcov/examples/support/lch.gpr index e7978b816..ac8c87a82 100644 --- a/tools/gnatcov/examples/support/lch.gpr +++ b/tools/gnatcov/examples/support/lch.gpr @@ -13,6 +13,7 @@ project LCH is end case; for Source_Dirs use ("lch"); + for Object_Dir use "obj/lch"; -- Make sure recursive project file inclusions don't get -- to produce reports for parts of this support lib, never From 37ca9205cb4782fa190e83162c51ef943fc575b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 6 Dec 2023 16:31:03 +0100 Subject: [PATCH 0585/1483] Remove use of Ada_2012 in assertion xml test --- testsuite/tests/O212-062-xml/main.adb | 3 +-- .../tests/O212-062-xml/src-traces-index.xml.expected | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/testsuite/tests/O212-062-xml/main.adb b/testsuite/tests/O212-062-xml/main.adb index b5a78882f..dcb65ce75 100644 --- a/testsuite/tests/O212-062-xml/main.adb +++ b/testsuite/tests/O212-062-xml/main.adb @@ -1,10 +1,8 @@ -pragma Ada_2012; pragma Assertion_Policy (Check); procedure Main is function ATCC_Violation (X : Boolean) return Boolean - with Pre => (X or else not X) is function Id (X : Boolean) return Boolean is begin @@ -16,6 +14,7 @@ is Dummy : Boolean := Id (True); begin + pragma Assert (X or else not X); return Id (False); end ATCC_Violation; begin diff --git a/testsuite/tests/O212-062-xml/src-traces-index.xml.expected b/testsuite/tests/O212-062-xml/src-traces-index.xml.expected index 4a38aef12..d7e76c018 100644 --- a/testsuite/tests/O212-062-xml/src-traces-index.xml.expected +++ b/testsuite/tests/O212-062-xml/src-traces-index.xml.expected @@ -15,8 +15,8 @@ - - + + @@ -79,8 +79,8 @@ - - + + From a6f70118551f0ea46600f96ff1da5bd95ced8447 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 14 Dec 2023 15:18:37 +0000 Subject: [PATCH 0586/1483] gnatcov.gpr: remove the dependency on gnatcov_rts.gpr This dependency is used only to pull a few data types and the version number, but implies that the gnatcov codebase cannot be instrumented by a gnatcov build based on an different coverage runtime. As a consequence, all attempts to compute code coverage for gnatcov need to compile gnatcov twice: once to get the "bootstrap" gnatcov, and once for the instrumented gnatcov. Without this dependency, one can use any gnatcov build to instrument the gnatcov codebase. Also update the Makefile to add the "--implicit-with=gnatcov_rts" gprbuild switch as expected for instrumented builds. --- tools/gnatcov/Makefile | 16 +++--- tools/gnatcov/checkpoints.adb | 10 ++-- tools/gnatcov/checkpoints.ads | 18 +++---- tools/gnatcov/compiler_wrappers-gcc.adb | 2 +- tools/gnatcov/coverage-source.adb | 33 ++++++------ tools/gnatcov/files_table.ads | 26 +++++----- tools/gnatcov/gnatcov.gpr | 2 - tools/gnatcov/instrument-ada_unit.adb | 35 ++++++------- .../gnatcov/instrument-ada_unit_provider.adb | 8 +-- tools/gnatcov/instrument-common.adb | 6 ++- tools/gnatcov/instrument-common.ads | 10 ++-- tools/gnatcov/instrument-input_traces.adb | 27 +++------- tools/gnatcov/instrument-input_traces.ads | 2 +- tools/gnatcov/instrument-projects.adb | 14 ++--- tools/gnatcov/instrument.adb | 10 ++-- tools/gnatcov/instrument.ads | 24 ++++----- tools/gnatcov/project.adb | 24 +++++---- tools/gnatcov/sc_obligations.ads | 13 +++-- tools/gnatcov/traces_source.ads | 51 +++++++++---------- 19 files changed, 158 insertions(+), 173 deletions(-) diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index 2c5e911d2..978b24f34 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -160,6 +160,10 @@ INSTR_COMMON_ARGS=\ -j$(PROCESSORS) \ -P gnatcov.gpr \ --c++-opts=$(CXXFLAGS) +INSTR_BIN_BUILD_ARGS=\ + $(BIN_COMMON_BUILD_ARGS) \ + --src-subdirs=gnatcov-instr \ + --implicit-with=gnatcov_rts bin: # Unlike BINUTILS_BUILD_DIR for which we have a default fallback, @@ -182,20 +186,16 @@ ifdef INSTRUMENTED # gnatcov32, running gnatcov32 will not dump execution traces. gnatcov instrument $(INSTR_COMMON_ARGS) -XPART=gnatcov64 - $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 \ - --src-subdirs=gnatcov-instr + $(GPRBUILD) $(INSTR_BIN_BUILD_ARGS) -XPART=gnatcov64 gnatcov instrument $(INSTR_COMMON_ARGS) -XPART=gnatcov32 - $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov32 \ - --src-subdirs=gnatcov-instr + $(GPRBUILD) $(INSTR_BIN_BUILD_ARGS) -XPART=gnatcov32 gnatcov instrument $(INSTR_COMMON_ARGS) -XPART=driver - $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=driver \ - --src-subdirs=gnatcov-instr + $(GPRBUILD) $(INSTR_BIN_BUILD_ARGS) -XPART=driver gnatcov instrument $(INSTR_COMMON_ARGS) -XPART=compiler - $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=compiler \ - --src-subdirs=gnatcov-instr + $(GPRBUILD) $(INSTR_BIN_BUILD_ARGS) -XPART=compiler else # Start with the 64-bit gnatcov, which has the largest closure $(GPRBUILD) $(BIN_COMMON_BUILD_ARGS) -XPART=gnatcov64 diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index a4f39f5ff..eb2ea3515 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -749,7 +749,7 @@ package body Checkpoints is function Read_Compilation_Unit (Self : in out Checkpoint_Load_State) return Compilation_Unit is - Language : constant Any_Language_Kind := Self.Read_Language_Kind; + Language : constant Supported_Language_Kind := Self.Read_Language_Kind; begin return (Language => Language, Unit_Name => Self.Read_Unbounded_String); end Read_Compilation_Unit; @@ -818,9 +818,9 @@ package body Checkpoints is ------------------------ function Read_Language_Kind - (Self : in out Checkpoint_Load_State) return Any_Language_Kind is + (Self : in out Checkpoint_Load_State) return Supported_Language_Kind is begin - return Any_Language_Kind'Val (Self.Read_U32); + return Supported_Language_Kind'Val (Self.Read_U32); end Read_Language_Kind; --------------------- @@ -1386,9 +1386,9 @@ package body Checkpoints is end Write; procedure Write - (Self : in out Checkpoint_Save_State; Value : Any_Language_Kind) is + (Self : in out Checkpoint_Save_State; Value : Supported_Language_Kind) is begin - Self.Write_U32 (Any_Language_Kind'Pos (Value)); + Self.Write_U32 (Supported_Language_Kind'Pos (Value)); end Write; procedure Write diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 08ffef484..ecb96174b 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -29,13 +29,13 @@ with GNAT.Regexp; with Types; use Types; with Coverage; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -with Files_Table; use Files_Table; -with Slocs; use Slocs; -with SC_Obligations; use SC_Obligations; -with Strings; use Strings; -with Traces; use Traces; -with Traces_Lines; use Traces_Lines; +with Files_Table; use Files_Table; +with Slocs; use Slocs; +with SC_Obligations; use SC_Obligations; +with Strings; use Strings; +with Traces; use Traces; +with Traces_Lines; use Traces_Lines; +with Traces_Source; use Traces_Source; package Checkpoints is @@ -372,7 +372,7 @@ package Checkpoints is function Read_Inst (Self : in out Checkpoint_Load_State) return Inst_Id; function Read_Integer (Self : in out Checkpoint_Load_State) return Integer; function Read_Language_Kind - (Self : in out Checkpoint_Load_State) return Any_Language_Kind; + (Self : in out Checkpoint_Load_State) return Supported_Language_Kind; function Read_Line_State (Self : in out Checkpoint_Load_State) return Any_Line_State; function Read_Local_Source_Location @@ -525,7 +525,7 @@ package Checkpoints is (Self : in out Checkpoint_Save_State; Value : SC_Obligations.Fingerprint_Type); procedure Write - (Self : in out Checkpoint_Save_State; Value : Any_Language_Kind); + (Self : in out Checkpoint_Save_State; Value : Supported_Language_Kind); procedure Write (Self : in out Checkpoint_Save_State; Value : Any_Line_State); procedure Write diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 95e7808e7..c5a2ffe2e 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -31,7 +31,6 @@ with GNAT.OS_Lib; with Coverage.Tags; use Coverage.Tags; with Files_Handling; use Files_Handling; with Files_Table; use Files_Table; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Instrument; use Instrument; with Instrument.C; use Instrument.C; with Instrument.Common; use Instrument.Common; @@ -44,6 +43,7 @@ with Subprocesses; use Subprocesses; with Switches; use Switches; with Temp_Dirs; use Temp_Dirs; with Traces_Files; +with Traces_Source; use Traces_Source; procedure Compiler_Wrappers.Gcc is diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 0b20f26ed..38ca45cf1 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -28,19 +28,19 @@ 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 GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -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 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 @@ -1974,12 +1974,11 @@ package body Coverage.Source is function Part_Image (Part : GNATCOLL.Projects.Unit_Parts) return String is - use all type GNATCOLL.Projects.Unit_Parts; begin return (case Part is - when Unit_Body => "body of", - when Unit_Spec => "spec of", - when Unit_Separate => "separate"); + when GNATCOLL.Projects.Unit_Body => "body of", + when GNATCOLL.Projects.Unit_Spec => "spec of", + when GNATCOLL.Projects.Unit_Separate => "separate"); end Part_Image; ------------------------ diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 653b48458..87ef8765a 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -25,19 +25,19 @@ with GNAT.Strings; use GNAT.Strings; with GNAT.Regexp; limited with Checkpoints; -with Coverage_Options; use Coverage_Options; -with Diagnostics; use Diagnostics; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; +with Coverage_Options; use Coverage_Options; +with Diagnostics; use Diagnostics; with Logging; -with Paths; use Paths; -with SC_Obligations; use SC_Obligations; -with Slocs; use Slocs; -with Strings; use Strings; -with Traces_Dbase; use Traces_Dbase; -with Traces_Elf; use Traces_Elf; -with Traces_Lines; use Traces_Lines; -with Traces_Stats; use Traces_Stats; -with Types; use Types; +with Paths; use Paths; +with SC_Obligations; use SC_Obligations; +with Slocs; use Slocs; +with Strings; use Strings; +with Traces_Dbase; use Traces_Dbase; +with Traces_Elf; use Traces_Elf; +with Traces_Lines; use Traces_Lines; +with Traces_Source; use Traces_Source; +with Traces_Stats; use Traces_Stats; +with Types; use Types; package Files_Table is @@ -316,7 +316,7 @@ package Files_Table is -- procedure Consolidate_Ignore_Status. type Compilation_Unit is record - Language : Any_Language_Kind; + Language : Supported_Language_Kind; Unit_Name : Unbounded_String; end record; -- This record is used to uniquely identify a unit of any language diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 64a75df6f..e3a322de4 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -1,7 +1,5 @@ with "gnat_util", "gnatcoll", "gpr2", "libadalang", "libclang"; -with "rts/gnatcov_rts"; - project Gnatcov is type Boolean is ("False", "True"); diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index f5deca87c..4446474ab 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -75,6 +75,11 @@ package body Instrument.Ada_Unit is is (Instrument.Common.Format_Fingerprint (Fingerprint, "(", ")")); -- Helper to format a String literal for a fingerprint + function "+" (Part : Analysis_Unit_Kind) return GNATCOLL.Projects.Unit_Parts + is (case Part is + when LALCO.Unit_Body => GNATCOLL.Projects.Unit_Body, + when LALCO.Unit_Specification => GNATCOLL.Projects.Unit_Spec); + ------------------------------- -- Create_Context_Instrument -- ------------------------------- @@ -6882,7 +6887,7 @@ package body Instrument.Ada_Unit is Main : Compilation_Unit_Part (Unit_Based_Language) := (Language_Kind => Unit_Based_Language, - Part => Unit_Body, + Part => GNATCOLL.Projects.Unit_Body, others => <>); -- Note that we can't get the compilation unit name using the -- To_Compilation_Unit_Name overload taking a File_Info parameter, @@ -7965,10 +7970,7 @@ package body Instrument.Ada_Unit is UIC.Root_Unit := Root_Analysis_Unit.Root.As_Compilation_Unit; UIC.Current_Scope_Entity := UIC.Scope_Entities.Root; - CU_Name.Part := - (case UIC.Root_Unit.P_Unit_Kind is - when Unit_Body => Unit_Body, - when Unit_Specification => Unit_Spec); + CU_Name.Part := +UIC.Root_Unit.P_Unit_Kind; CU_Name.Unit := To_Qualified_Name (UIC.Root_Unit.P_Decl.P_Fully_Qualified_Name_Array); @@ -9130,20 +9132,13 @@ package body Instrument.Ada_Unit is -- spec / body / both. for Part in Analysis_Unit_Kind loop - declare - function Convert (Part : Analysis_Unit_Kind) return Unit_Parts is - (case Part is - when Unit_Body => Unit_Body, - when Unit_Specification => Unit_Spec); - begin - if Self.Provider.Has_Unit (Unit_Name, Convert (Part)) then - Find_Ada_Units - (Self, - Self.Provider.Get_Unit_Filename - (Langkit_Support.Text.From_UTF8 (Unit_Name), Part), - Instrument_Source_File_Wrapper'Access); - end if; - end; + if Self.Provider.Has_Unit (Unit_Name, +Part) then + Find_Ada_Units + (Self, + Self.Provider.Get_Unit_Filename + (Langkit_Support.Text.From_UTF8 (Unit_Name), Part), + Instrument_Source_File_Wrapper'Access); + end if; end loop; -- Once the unit was instrumented, emit the coverage buffer units @@ -9194,7 +9189,7 @@ package body Instrument.Ada_Unit is Find_Ada_Units (Instrumenter, Instrumenter.Context.Unit_Provider.Get - .Get_Unit_Filename (Subunit_FQN, Unit_Body), + .Get_Unit_Filename (Subunit_FQN, LALCO.Unit_Body), Process_Unit); end if; end; diff --git a/tools/gnatcov/instrument-ada_unit_provider.adb b/tools/gnatcov/instrument-ada_unit_provider.adb index 283ecb323..879a11c3c 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.adb +++ b/tools/gnatcov/instrument-ada_unit_provider.adb @@ -28,6 +28,8 @@ with Project; use Project; package body Instrument.Ada_Unit_Provider is + package LALCO renames Libadalang.Common; + --------------------- -- Create_Provider -- --------------------- @@ -192,8 +194,8 @@ package body Instrument.Ada_Unit_Provider is Libadalang.Unit_Files.File_From_Unit (Name, Kind); Kind_Name : constant Text_Type := (case Kind is - when Unit_Specification => "specification file", - when Unit_Body => "body file"); + when LALCO.Unit_Specification => "specification file", + when LALCO.Unit_Body => "body file"); Error : constant Text_Type := "Could not find source file for " & Name & " (" & Kind_Name & ")"; @@ -216,7 +218,7 @@ package body Instrument.Ada_Unit_Provider is Unit_Name_And_Part : constant String := To_Lower (Unit_Name) & (case Unit_Part is - when Unit_Spec => "%s", + when GNATCOLL.Projects.Unit_Spec => "%s", when others => "%b"); begin return Provider.Unit_Map.Contains (Unit_Name_And_Part); diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 0528eaf14..94014e27a 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -411,9 +411,11 @@ package body Instrument.Common is end loop; case CU_Name.Part is - when Unit_Body | Unit_Separate => + when GNATCOLL.Projects.Unit_Body + | GNATCOLL.Projects.Unit_Separate + => Append (Filename, Prj.Body_Suffix (Lang)); - when Unit_Spec => + when GNATCOLL.Projects.Unit_Spec => Append (Filename, Prj.Spec_Suffix (Lang)); end case; when File_Based_Language => diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 4c925d256..02e143819 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -61,7 +61,6 @@ with GNATCOLL.JSON; use GNATCOLL.JSON; with ALI_Files; use ALI_Files; with Files_Handling; use Files_Handling; with Files_Table; use Files_Table; -with GNATcov_RTS; with Namet; use Namet; with Slocs; use Slocs; with Text_Files; @@ -353,14 +352,17 @@ package Instrument.Common is (Strings.Img (Integer (Bit))); Runtime_Version_Check : constant String := - "pragma Compile_Time_Error (GNATcov_RTS.Version /=" - & GNATcov_RTS.Version'Image - & ",""Incompatible GNATcov_RTS version, please use" + "pragma Compile_Time_Error (GNATcov_RTS.Version /= 5, " + & """Incompatible GNATcov_RTS version, please use" & " the GNATcov_RTS project provided with your" & " GNATcoverage distribution."");"; -- Check to be inserted in Ada units generated by the instrumenter to -- verify that they are built with the version of GNATcov_RTS the -- instrumenter expects. + -- + -- The hardcoded version number must be updated in synchronization with the + -- Version constant in gnatcov_rts.ads. It is fine to forget one or the + -- other: the testsuite will not work without this. procedure Append_Unit (SFI : Source_File_Index); -- Append a new entry to the SCO_Unit_Table, with an empty SCO range diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 22f06c04c..212604511 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -29,24 +29,11 @@ with System.Storage_Elements; with GNAT.OS_Lib; use GNAT.OS_Lib; with GNAT.Byte_Swapping; use GNAT.Byte_Swapping; -with Traces_Source; use Traces_Source; with Hex_Images; with Outputs; package body Instrument.Input_Traces is - Unit_Part_Map : constant array (Supported_Unit_Part) of Unit_Parts := - (Traces_Source.Unit_Body => GNATCOLL.Projects.Unit_Body, - Traces_Source.Unit_Spec => GNATCOLL.Projects.Unit_Spec, - Traces_Source.Unit_Separate => GNATCOLL.Projects.Unit_Separate); - - Language_Map : constant array (Supported_Language_Kind) - of GNATcov_RTS.Buffers.Any_Language_Kind := - (Traces_Source.Unit_Based_Language => - GNATcov_RTS.Buffers.Unit_Based_Language, - Traces_Source.File_Based_Language => - GNATcov_RTS.Buffers.File_Based_Language); - Native_Endianity : constant Supported_Endianity := Traces_Source.Native_Endianity; @@ -683,7 +670,7 @@ package body Instrument.Input_Traces is with Import, Address => Trace_Entry.Unit_Name; function Convert is new Ada.Unchecked_Conversion - (GNATcov_RTS.Buffers.Fingerprint_Type, + (Traces_Source.Fingerprint_Type, SC_Obligations.Fingerprint_Type); Fingerprint : constant SC_Obligations.Fingerprint_Type := Convert (Entry_Header.Fingerprint); @@ -750,12 +737,12 @@ package body Instrument.Input_Traces is goto Cleanup_And_Exit; end if; - case Language_Map (Entry_Header.Language_Kind) is - when GNATcov_RTS.Buffers.Unit_Based_Language => + case Supported_Language_Kind (Entry_Header.Language_Kind) is + when Traces_Source.Unit_Based_Language => CU_Name := CU_Name_For_Unit (Unit => To_Qualified_Name (Unit_Name), - Part => Unit_Part_Map (Entry_Header.Unit_Part)); - when GNATcov_RTS.Buffers.File_Based_Language => + Part => +Entry_Header.Unit_Part); + when Traces_Source.File_Based_Language => CU_Name := CU_Name_For_File (+Unit_Name); end case; @@ -847,10 +834,10 @@ package body Instrument.Input_Traces is end if; case CU_Name.Language_Kind is - when GNATcov_RTS.Buffers.Unit_Based_Language => + when Traces_Source.Unit_Based_Language => Put ("Unit " & To_Ada (CU_Name.Unit) & " (" & CU_Name.Part'Image & ", "); - when GNATcov_RTS.Buffers.File_Based_Language => + when Traces_Source.File_Based_Language => Put ("Unit " & (+CU_Name.Filename) & " ("); end case; diff --git a/tools/gnatcov/instrument-input_traces.ads b/tools/gnatcov/instrument-input_traces.ads index 43ed20190..0dddce1b6 100644 --- a/tools/gnatcov/instrument-input_traces.ads +++ b/tools/gnatcov/instrument-input_traces.ads @@ -24,7 +24,7 @@ with Traces_Source; package Instrument.Input_Traces is - type Coverage_Buffer is array (Bit_Id range <>) of Boolean with Pack; + type Coverage_Buffer is array (Any_Bit_Id range <>) of Boolean with Pack; -- Content of a coverage buffer generic diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 52b433c62..2950d1076 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -570,13 +570,13 @@ is declare Src_Body_Basename : constant String := +Project.File_From_Unit (Unit_Name => +LU_Info.Unit_Name, - Part => Unit_Body, - Language => Image (LU_Info.Language), + Part => GNATCOLL.Projects.Unit_Body, + Language => Image (LU_Info.Language), File_Must_Exist => True); Src_Spec_Basename : constant String := +Project.File_From_Unit (Unit_Name => +LU_Info.Unit_Name, - Part => Unit_Spec, - Language => Image (LU_Info.Language), + Part => GNATCOLL.Projects.Unit_Spec, + Language => Image (LU_Info.Language), File_Must_Exist => True); Src_Basename : constant String := (if Src_Body_Basename = "" @@ -717,7 +717,7 @@ is is Language : constant Src_Supported_Language := To_Language (Source_File.Language); - Lang_Kind : constant Any_Language_Kind := Language_Kind (Language); + Lang_Kind : constant Supported_Language_Kind := Language_Kind (Language); use Unit_Maps; Unit_Name : constant String := @@ -759,7 +759,7 @@ is -- as they have been added to the sources of interest. if Language in C_Family_Language - and then Source_File.Unit_Part = Unit_Spec + and then Source_File.Unit_Part = GNATCOLL.Projects.Unit_Spec then return; end if; @@ -1069,7 +1069,7 @@ begin -- there. for Source of Files_Of_Interest_Info.Copy loop - if Source.Unit_Part = Unit_Separate then + if Source.Unit_Part = GNATCOLL.Projects.Unit_Separate then declare Parent_Unit : constant GNATCOLL.Projects.File_Info := Project.Project.Info diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 36664d627..2b78f087b 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -39,8 +39,8 @@ package body Instrument is -- Language_Kind -- ------------------- - function Language_Kind (Language : Some_Language) return Any_Language_Kind - is + function Language_Kind + (Language : Some_Language) return Supported_Language_Kind is begin return (case Language is when Ada_Language => Unit_Based_Language, @@ -340,9 +340,9 @@ package body Instrument is return To_Ada (CU_Name.Unit) & " " & (case CU_Name.Part is - when Unit_Spec => "spec", - when Unit_Body => "body", - when Unit_Separate => "subunit"); + when GNATCOLL.Projects.Unit_Spec => "spec", + when GNATCOLL.Projects.Unit_Body => "body", + when GNATCOLL.Projects.Unit_Separate => "subunit"); when File_Based_Language => return +CU_Name.Filename; end case; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 6b813a44a..eeb431366 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -25,13 +25,13 @@ with GNATCOLL.Projects; use GNATCOLL.Projects; with Types; use Types; -with Checkpoints; use Checkpoints; +with Checkpoints; use Checkpoints; with Files_Handling; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -with SC_Obligations; use SC_Obligations; -with Subprocesses; use Subprocesses; -with Strings; use Strings; -with Switches; use Switches; +with SC_Obligations; use SC_Obligations; +with Strings; use Strings; +with Subprocesses; use Subprocesses; +with Switches; use Switches; +with Traces_Source; use Traces_Source; package Instrument is @@ -46,7 +46,7 @@ package Instrument is (Project_Instrumentation, Integrated_Instrumentation); function Language_Kind - (Language : Some_Language) return Any_Language_Kind; + (Language : Some_Language) return Supported_Language_Kind; -- Returns the language kind (unit-based or file-based) for the given -- language. @@ -89,13 +89,13 @@ package Instrument is Write_Element => Write); type Compilation_Unit_Part - (Language_Kind : Any_Language_Kind := Unit_Based_Language) + (Language_Kind : Supported_Language_Kind := Unit_Based_Language) is record case Language_Kind is when Unit_Based_Language => Unit : Ada_Qualified_Name := Ada_Identifier_Vectors.Empty_Vector; - Part : Unit_Parts := Unit_Body; + Part : Unit_Parts := GNATCOLL.Projects.Unit_Body; -- Identifies an Ada compilation unit (unit-based) when File_Based_Language => @@ -118,9 +118,9 @@ package Instrument is -- Write a Compilation_Unit_Part to CSS Part_Tags : constant array (Unit_Parts) of Character := - (Unit_Spec => 'S', - Unit_Body => 'B', - Unit_Separate => 'U'); + (GNATCOLL.Projects.Unit_Spec => 'S', + GNATCOLL.Projects.Unit_Body => 'B', + GNATCOLL.Projects.Unit_Separate => 'U'); function "=" (Left, Right : Compilation_Unit_Part) return Boolean; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 0f719d39c..a35910cee 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -29,11 +29,11 @@ with GNATCOLL.Traces; with GNATCOLL.Projects.Aux; with GNATCOLL.VFS; use GNATCOLL.VFS; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; -with Inputs; use Inputs; -with Instrument; use Instrument; -with Outputs; use Outputs; -with Paths; use Paths; +with Inputs; use Inputs; +with Instrument; use Instrument; +with Outputs; use Outputs; +with Paths; use Paths; +with Traces_Source; package body Project is @@ -42,6 +42,8 @@ package body Project is subtype Compilation_Unit is Files_Table.Compilation_Unit; use type Compilation_Unit; + use type Traces_Source.Supported_Language_Kind; + Coverage_Package : aliased String := "coverage"; Coverage_Package_List : aliased String_List := (1 => Coverage_Package'Access); @@ -254,9 +256,9 @@ package body Project is begin U.Language := Language_Kind (Language); case U.Language is - when File_Based_Language => + when Traces_Source.File_Based_Language => U.Unit_Name := +(+Info.File.Full_Name); - when Unit_Based_Language => + when Traces_Source.Unit_Based_Language => U.Unit_Name := +Owning_Unit_Name (Info); end case; return U; @@ -566,7 +568,7 @@ package body Project is -- they can only be ignored through the --ignore-source-files -- switch. - if (Language_Kind (Info_Lang) = File_Based_Language + if (Language_Kind (Info_Lang) = Traces_Source.File_Based_Language and then Info.Unit_Part = Unit_Spec) -- Otherwise, check if the unit is in the units of interest @@ -1025,9 +1027,9 @@ package body Project is P_Unit : constant Compilation_Unit := Unit_Maps.Key (C); Unit_Name : constant Unbounded_String := (case P_Unit.Language is - when File_Based_Language => - +Ada.Directories.Simple_Name (+P_Unit.Unit_Name), - when Unit_Based_Language => P_Unit.Unit_Name); + when Traces_Source.File_Based_Language => + +Ada.Directories.Simple_Name (+P_Unit.Unit_Name), + when Traces_Source.Unit_Based_Language => P_Unit.Unit_Name); begin Units_Present.Append (Unit_Name); end Add_To_Unit_Presents; diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 1a3ff3bfa..8199f7173 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -18,7 +18,7 @@ -- Source Coverage Obligations -with Ada.Containers; use Ada.Containers; +with Ada.Containers; use Ada.Containers; with Ada.Containers.Doubly_Linked_Lists; with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Containers.Ordered_Maps; @@ -33,11 +33,10 @@ with Namet; with Types; use Types; limited with Checkpoints; -with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with Logging; -with Slocs; use Slocs; -with Strings; use Strings; -with Traces; use Traces; +with Slocs; use Slocs; +with Strings; use Strings; +with Traces; use Traces; package SC_Obligations is @@ -668,6 +667,10 @@ package SC_Obligations is -- For units whose SCOs come from source instrumentation, maintain -- mapping of coverage buffer bit indices to SCO info. + type Any_Bit_Id is new Integer; + No_Bit_Id : constant Any_Bit_Id := -1; + subtype Bit_Id is Any_Bit_Id range 0 .. Any_Bit_Id'Last; + type Statement_Bit_Map is array (Bit_Id range <>) of SCO_Id; type Statement_Bit_Map_Access is access all Statement_Bit_Map; -- Statement buffer: bit set True denotes that the statement was executed diff --git a/tools/gnatcov/traces_source.ads b/tools/gnatcov/traces_source.ads index ad7fb5fd8..ce7776bd5 100644 --- a/tools/gnatcov/traces_source.ads +++ b/tools/gnatcov/traces_source.ads @@ -24,7 +24,7 @@ with Interfaces; use Interfaces; -with GNATcov_RTS.Buffers; +with GNATCOLL.Projects; -- Describes the content of a source trace file. Should be kept up to date -- when the trace format is modified. It is notably used to parse source @@ -32,8 +32,6 @@ with GNATcov_RTS.Buffers; package Traces_Source is - package Buffers renames GNATcov_RTS.Buffers; - -- Execution of an instrumented program sets bits in its coverage buffers. -- These bits convey information that GNATcov will later on use to -- discharge coverage obligations. @@ -77,44 +75,39 @@ package Traces_Source is -- Hash type to perform consistency checks type Any_Unit_Part is new Unsigned_8; - Not_Applicable_Part : constant Any_Unit_Part := - Buffers.Any_Unit_Part'Pos (Buffers.Not_Applicable_Part); - Unit_Body : constant Any_Unit_Part := - Buffers.Any_Unit_Part'Pos (Buffers.Unit_Body); - Unit_Spec : constant Any_Unit_Part := - Buffers.Any_Unit_Part'Pos (Buffers.Unit_Spec); - Unit_Separate : constant Any_Unit_Part := - Buffers.Any_Unit_Part'Pos (Buffers.Unit_Separate); + Not_Applicable_Part : constant Any_Unit_Part := 0; + Unit_Body : constant Any_Unit_Part := 1; + Unit_Spec : constant Any_Unit_Part := 2; + Unit_Separate : constant Any_Unit_Part := 3; subtype All_Unit_Part is Any_Unit_Part range Not_Applicable_Part .. Unit_Separate; subtype Supported_Unit_Part is Any_Unit_Part range Unit_Body .. Unit_Separate; -- Describe the kind of unit referenced by a trace entry - Unit_Part_Map : constant - array (Buffers.Any_Unit_Part) of All_Unit_Part := - (Buffers.Not_Applicable_Part => Not_Applicable_Part, - Buffers.Unit_Body => Unit_Body, - Buffers.Unit_Spec => Unit_Spec, - Buffers.Unit_Separate => Unit_Separate); + function "+" + (Part : Supported_Unit_Part) return GNATCOLL.Projects.Unit_Parts + is (case Part is + when Unit_Body => GNATCOLL.Projects.Unit_Body, + when Unit_Spec => GNATCOLL.Projects.Unit_Spec, + when Unit_Separate => GNATCOLL.Projects.Unit_Separate); + function "+" + (Part : GNATCOLL.Projects.Unit_Parts) return Supported_Unit_Part + is (case Part is + when GNATCOLL.Projects.Unit_Body => Unit_Body, + when GNATCOLL.Projects.Unit_Spec => Unit_Spec, + when GNATCOLL.Projects.Unit_Separate => Unit_Separate); type Any_Bit_Count is new Unsigned_32; -- Number of bits contained in a coverage buffer type Any_Language_Kind is new Unsigned_8; - Unit_Based_Language : constant Any_Language_Kind := - Buffers.Any_Language_Kind'Pos (Buffers.Unit_Based_Language); - File_Based_Language : constant Any_Language_Kind := - Buffers.Any_Language_Kind'Pos (Buffers.File_Based_Language); + Unit_Based_Language : constant Any_Language_Kind := 0; + File_Based_Language : constant Any_Language_Kind := 1; subtype Supported_Language_Kind is Any_Language_Kind range Unit_Based_Language .. File_Based_Language; -- Language kind for a compilation unit - Any_Language_Kind_Map : constant - array (Buffers.Any_Language_Kind) of Supported_Language_Kind := - (Buffers.Unit_Based_Language => Unit_Based_Language, - Buffers.File_Based_Language => File_Based_Language); - ----------------------- -- Trace file header -- ----------------------- @@ -220,6 +213,8 @@ package Traces_Source is subtype Supported_Bit_Buffer_Encoding is Any_Bit_Buffer_Encoding range LSB_First_Bytes .. LSB_First_Bytes; + type Fingerprint_Type is new String (1 .. 20); + type Trace_Entry_Header is record Unit_Name_Length : Unsigned_32; -- Length of the unit name / filename for the unit this trace entry @@ -240,12 +235,12 @@ package Traces_Source is Bit_Buffer_Encoding : Any_Bit_Buffer_Encoding; -- Encoding used to represent statement and decision coverage buffers - Fingerprint : Buffers.Fingerprint_Type; + Fingerprint : Fingerprint_Type; -- Hash of SCO info for this unit. Useds a fast way to check that -- coverage obligations and coverage data are consistent. Specific hash -- values are computed during instrumentation. - Bit_Maps_Fingerprint : Buffers.Fingerprint_Type; + Bit_Maps_Fingerprint : Fingerprint_Type; -- Hash of buffer bit mappings for this unit, as gnatcov computes it -- (see SC_Obligations). Used as a fast way to check that gnatcov will -- be able to interpret buffer bits from a source traces using buffer From 80359b18d0bf319e73f74b066fba1708202d92db Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 18 Dec 2023 13:05:41 +0000 Subject: [PATCH 0587/1483] CI: install latest gnatcov wavefront instead of rebuilding it Now that gnatcov itself does not use gnatcov_rts, instrumenting gnatcov with another version of gnatcov should work in all cases, so there is no need to use a fresh build of gnatcov to run the bootstrap instrumentation. This should give a noticeable CI speed up. --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fa246cd9a..c69e4703c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -55,7 +55,7 @@ build: - *common_anod_bits # Build using anod - - anod build --minimal gnatcov $EDGE_QUALIFIER + - anod install gnatcov $EDGE_QUALIFIER --latest - anod build --minimal gnatcov -Qinstr $EDGE_QUALIFIER # Package all components created so far From 23a23daa907a64221dc95666ee9947aa54232dda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 13 Dec 2023 15:53:30 +0100 Subject: [PATCH 0588/1483] tutils.py: Use run-cross2 to run instrumented programs instead of gnatemu run-cross2 already has knowledge of all configuration needed to run cross or bareboard programs, so use it instead of re-developping our own solution. --- .../GPR/ByCmdLine/test_support.py | 4 +- .../GPR/GprsOfInterest/test.py | 7 +-- testsuite/SUITE/control.py | 23 ++++++++ testsuite/SUITE/tutils.py | 54 ++++++++++--------- testsuite/tests/RB13-019-win-paths/test.opt | 2 +- testsuite/testsuite.py | 7 ++- 6 files changed, 63 insertions(+), 34 deletions(-) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py index e7dae6a78..b1940779b 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py @@ -8,7 +8,7 @@ from SCOV.tc import TestCase from SCOV.tctl import CovControl -from SUITE.control import env +from SUITE.control import env, gnatemu_board_name from SUITE.cutils import to_list, Wdir from SUITE.gprutils import GPRswitches @@ -108,7 +108,7 @@ def check(root_project, recurse, projects=None, units=None, xreports=None): projects=projects, units=units, no_subprojects=no_subprojects, - xvars=[('BOARD', env.target.machine)], + xvars=[('BOARD', gnatemu_board_name(env.target.machine))], ), xreports=ctl_xreports, diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py index 252602aab..f1f9e94b6 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py @@ -5,7 +5,7 @@ from SCOV.minicheck import build_and_run from SUITE.context import thistest -from SUITE.control import env +from SUITE.control import env, gnatemu_board_name from SUITE.cutils import Wdir, lines_of from SUITE.gprutils import GPRswitches from SUITE.tutils import xcov @@ -15,7 +15,8 @@ root_project = os.path.abspath('root.gpr') -board_arg = '-XBOARD={}'.format(env.target.machine) +board = gnatemu_board_name(env.target.machine) +board_arg = '-XBOARD={}'.format(board) wd = Wdir('wd_') # Every project of interest is setup to feature a single unit named after the @@ -29,7 +30,7 @@ cov_cmdline = build_and_run( gprsw=GPRswitches( root_project=root_project, - xvars=[("BOARD", env.target.machine)], + xvars=[("BOARD", board)], ), mains=['root'], covlevel='stmt', diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index e4ab2a038..6201904e6 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -387,6 +387,29 @@ def major(self): def gnatcov_info(): return GnatcovInfo() + +# Mapping between run-cross2 board names and gnatemu board names +BOARD_INFO = { + # generic + "qemu" : "", + # aarch64-elf + "qemu-zynqmp" : "", + # arm-elf + "qemu-stm32" : "stm32f4", + "qemu-tms570" : "tms570", + # ppc-elf: + "qemu-8641d" : "", + None : "" +} + +def gnatemu_board_name(name): + """ + Return the gnatemu board name corresponding to the run-cross2 board name + passed as argument. If name is unknown in the mapping, return it + unchanged. + """ + return BOARD_INFO.get(name, name) + # Allowed pairs for the --gnatcov- family of command line options: ALTRUN_GNATCOV_PAIRS = (('gnatcov', 'run'), ) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index c14564ec6..9db67d8ff 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -11,18 +11,19 @@ import glob import os import re +import sys import time -from e3.os.fs import touch, unixpath +from e3.os.fs import touch, unixpath, which from e3.os.process import DEVNULL, Run # Expose a few other items as a test util facilities as well from SUITE import control -from SUITE.control import (BUILDER, KNOWN_LANGUAGES, env, language_info, - xcov_pgm) +from SUITE.control import (BUILDER, KNOWN_LANGUAGES, env, gnatemu_board_name, + language_info, xcov_pgm) from SUITE.context import ROOT_DIR, thistest @@ -345,10 +346,11 @@ def gpr_emulator_package(): If there is a board name, return a package Emulator to be included in a GPR file to provide this information to GNATemulator. """ + gnatemu_board = gnatemu_board_name(env.target.machine) return ('package Emulator is\n' ' for Board use "{}";\n' - 'end Emulator;'.format(env.target.machine) - if env.target.machine else '') + 'end Emulator;'.format(gnatemu_board) + if gnatemu_board else '') def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", @@ -652,8 +654,9 @@ def xcov_suite_args(covcmd, covargs, # --> gnatcov run --target=iSystem-5554 # # Such board indications are intended for probe based targets. - if thistest.options.board: - targetarg = thistest.options.board + gnatemu_board = gnatemu_board_name(thistest.options.board) + if gnatemu_board: + targetarg = gnatemu_board # Otherwise, pass the target triplet indication, completed by a board # extension if we also have a target "machine": @@ -670,8 +673,9 @@ def xcov_suite_args(covcmd, covargs, # --target argument to "gnatcov" as soon as we work with a 32bit target. elif thistest.options.target or env.target.cpu.bits != 64: targetarg = env.target.triplet - if env.target.machine and env.target.machine != "unknown": - targetarg += ",%s" % env.target.machine + board_name = gnatemu_board_name(env.target.machine) + if board_name and board_name != "unknown": + targetarg += ",%s" % board_name else: targetarg = None @@ -840,7 +844,7 @@ def xrun(args, out=None, env=None, register_failure=True, if ( thistest.options.trace_size_limit and thistest.options.target and - not thistest.options.board + not gnatemu_board_name(thistest.options.board) ): if '-eargs' not in runargs: runargs.append('-eargs') @@ -864,23 +868,21 @@ def run_cov_program(executable, out=None, env=None, exec_args=None, exec_args = exec_args or [] inp = None - # If we are in a cross configuration, run the program using GNATemulator + # If we are in a cross configuration, run the program using run-cross2 if thistest.options.target and thistest.env.target.platform != "c": - kernel = thistest.options.kernel - board = thistest.options.board or thistest.env.target.machine - args.append('{}-gnatemu'.format(thistest.env.target.triplet)) - if kernel: - args.append('--kernel=' + kernel) - if board: - args.append('--board=' + board) - - # If GNATemulator runs as a background process in an interactive shell, - # the Linux kernel will send a SIGTTIN when GNATemulator tries to read - # the standard input (which is the interactive shell by default). This - # will result in an abnormal GNATemulator termination, and the test - # failing. Redirecting the standard input to /dev/null works around - # this issue. - inp = DEVNULL + # We absolutely need a machine name to run programs with run-cross2 + assert thistest.options.board or thistest.env.target.machine + + # run-cross2 is a python script. As Windows does not parse shebangs, + # use the python executable as main program instead of the script. + args.append(sys.executable) + args.append(which("run-cross2")) + target = thistest.env.target.platform + if thistest.options.board: + target += f",,{thistest.options.board}" + else: + target += f",,{thistest.env.target.machine}" + args.append(f"--target={target}") else: # Native programs using a light runtime can't set the exit code, and # will often terminate with a non-zero status code even though nothing diff --git a/testsuite/tests/RB13-019-win-paths/test.opt b/testsuite/tests/RB13-019-win-paths/test.opt index 1df01ed06..b68b45768 100644 --- a/testsuite/tests/RB13-019-win-paths/test.opt +++ b/testsuite/tests/RB13-019-win-paths/test.opt @@ -1,2 +1,2 @@ -arm-elf,stm32f4,bin-traces +arm-elf,qemu-stm32,bin-traces ALL DEAD Test tailored for bin traces on arm-elf/stm32f4 diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index e363b346f..1f1241741 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1104,8 +1104,11 @@ def _build_libsupport(self): # (e.g. aarch64-elf,unknown). libsup_vars.append("TARGET={}".format(self.env.target.triplet)) - if args.board: - libsup_vars.append("BOARD={}".format(args.board)) + # The BOARD variable is used to fill the Emulator package Board + # attribute, so convert the argument to a gnatemu name. + board = control.gnatemu_board_name(args.board) + if board: + libsup_vars.append("BOARD={}".format(board)) if args.RTS: libsup_vars.append("RTS={}".format(args.RTS)) From c245e17425e8fb4e0b00654388cc1c91856b7005 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 18 Dec 2023 10:25:31 +0100 Subject: [PATCH 0589/1483] Testsuite: fix various test.opt filters Kill tests not relevant for light-tasking runtimes, and kill some gnatcov run specific tests on src-traces runs. --- testsuite/Qualif/Ada/decision/Robustness/Ustrings/test.opt | 1 + testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/test.opt | 1 + .../Ada/stmt/1_Core/11_Exceptions/Propagation/extra.opt | 1 + .../Ada/stmt/1_Core/13_Representation/OpAttributes/extra.opt | 1 + .../Qualif/Common/GprFacilities/ConfigAttr/Target/test.opt | 2 +- testsuite/Qualif/Common/GprFacilities/MainAttr/extra.opt | 2 +- testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.opt | 1 + testsuite/tests/Ada2022/declare_expr/extra.opt | 1 + testsuite/tests/Ada2022/raise_expr/extra.opt | 1 + testsuite/tests/HA16-013_cleanups/test.opt | 3 ++- testsuite/tests/KB30-011-eargs-gnatemu/test.opt | 1 + testsuite/tests/M502-040-default-prj-path/test.opt | 1 + testsuite/tests/M528-002-transient-finalize/extra.opt | 5 +++-- testsuite/tests/N630-009-forward_p_x/test.opt | 1 + testsuite/tests/NC08-027-target_attr/test.opt | 1 + testsuite/tests/T319-018-if-expr/test.opt | 1 + testsuite/tests/U204-026-arch-mix/test.opt | 1 + .../tests/instr-cov/main_autodump/nested_block/test.opt | 1 + testsuite/tests/instr-cov/main_autodump/stubs/test.opt | 1 + testsuite/tests/instr-cov/pragma_after_cu/test.opt | 3 ++- 20 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 testsuite/tests/instr-cov/main_autodump/stubs/test.opt diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/test.opt b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/test.opt index 468c8f45e..46096cdfa 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/test.opt +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/test.opt @@ -1,3 +1,4 @@ RTS_ZFP DEAD no support for unbounded strings in ZFP runtimes +RTS_LIGHT_TASKING DEAD no support for unbounded string in light-tasking runtimes CARGS_O1,7.1.2,bin-traces XFAIL Debug info issue fixed post 7.0, PB30-044 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/test.opt index 6e33ff527..4986592e9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/test.opt @@ -1 +1,2 @@ RTS_ZFP DEAD no support for unbounded strings in ZFP runtimes +RTS_LIGHT_TASKING DEAD no support for unbounded strings in light-tasking runtimes diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/extra.opt b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/extra.opt index d5aeaf6cb..3f9983d16 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/extra.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/extra.opt @@ -1 +1,2 @@ RTS_ZFP DEAD no support for exception propagation in ZFP runtimes +RTS_LIGHT_TASKING DEAD no support for exception propagation in light-tasking runtimes diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/extra.opt b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/extra.opt index 54fba5f43..9fa5daf30 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/extra.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/extra.opt @@ -1 +1,2 @@ RTS_ZFP DEAD +RTS_LIGHT_TASKING DEAD Ada.Streams not available diff --git a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.opt b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.opt index c0edc3122..9e5989f5a 100644 --- a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.opt +++ b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.opt @@ -1,2 +1,2 @@ -src-traces,native DEAD Binary traces specific testcase +src-traces DEAD Binary traces specific testcase 7.1.2 DEAD test GPR file attributes that were not supported in 7.1.2 \ No newline at end of file diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/extra.opt b/testsuite/Qualif/Common/GprFacilities/MainAttr/extra.opt index 1eff4a74a..4b804ae79 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/extra.opt +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/extra.opt @@ -1 +1 @@ -src-traces,native DEAD Binary traces specific testcase +src-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.opt b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.opt index 6c7b0a7ff..1f8985273 100644 --- a/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.opt +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/Freezing/test.opt @@ -1 +1,2 @@ RTS_ZFP DEAD Test relies on advanced use of tagged types +RTS_LIGHT_TASKING DEAD Requires language features not available in the runtime diff --git a/testsuite/tests/Ada2022/declare_expr/extra.opt b/testsuite/tests/Ada2022/declare_expr/extra.opt index 3abfb6047..77e633e36 100644 --- a/testsuite/tests/Ada2022/declare_expr/extra.opt +++ b/testsuite/tests/Ada2022/declare_expr/extra.opt @@ -1 +1,2 @@ RTS_ZFP DEAD tests propagate exceptions +RTS_LIGHT_TASKING DEAD Test propagates exceptions diff --git a/testsuite/tests/Ada2022/raise_expr/extra.opt b/testsuite/tests/Ada2022/raise_expr/extra.opt index df0cb1cfc..e414c7dda 100644 --- a/testsuite/tests/Ada2022/raise_expr/extra.opt +++ b/testsuite/tests/Ada2022/raise_expr/extra.opt @@ -1 +1,2 @@ RTS_ZFP DEAD Tests propagate exceptions +RTS_LIGHT_TASKING DEAD Tests propagate exceptions diff --git a/testsuite/tests/HA16-013_cleanups/test.opt b/testsuite/tests/HA16-013_cleanups/test.opt index 72097dd49..a413475c5 100644 --- a/testsuite/tests/HA16-013_cleanups/test.opt +++ b/testsuite/tests/HA16-013_cleanups/test.opt @@ -1 +1,2 @@ -!RTS_RAVENSCAR,!RTS_FULL DEAD test on exception propagation cleanups, zfp-irrelevant \ No newline at end of file +RTS_ZFP DEAD test on exception propagation cleanups, zfp-irrelevant +RTS_LIGHT_TASKING DEAD test on exception propagation cleanups, light-tasking irrelevant diff --git a/testsuite/tests/KB30-011-eargs-gnatemu/test.opt b/testsuite/tests/KB30-011-eargs-gnatemu/test.opt index 9815b3e57..83daf7326 100644 --- a/testsuite/tests/KB30-011-eargs-gnatemu/test.opt +++ b/testsuite/tests/KB30-011-eargs-gnatemu/test.opt @@ -2,3 +2,4 @@ native DEAD checking argument passing to qemu & gnatemu, NA on this platform visium-elf DEAD checking argument passing to qemu & gnatemu, NA on this platform lmp-elf DEAD checking argument passing to qemu & gnatemu, NA on this platform vxworks XFAIL mcdc without scos run on purpose, trace size limit overrun +src-traces DEAD test specific to gnatcov run diff --git a/testsuite/tests/M502-040-default-prj-path/test.opt b/testsuite/tests/M502-040-default-prj-path/test.opt index a24154dc9..d49846591 100644 --- a/testsuite/tests/M502-040-default-prj-path/test.opt +++ b/testsuite/tests/M502-040-default-prj-path/test.opt @@ -1 +1,2 @@ native DEAD test works by simulating a missing/non-working native gnatls +src-traces DEAD test specific to gnatcov run diff --git a/testsuite/tests/M528-002-transient-finalize/extra.opt b/testsuite/tests/M528-002-transient-finalize/extra.opt index 5367f0143..3f9ce77c1 100644 --- a/testsuite/tests/M528-002-transient-finalize/extra.opt +++ b/testsuite/tests/M528-002-transient-finalize/extra.opt @@ -1,3 +1,4 @@ -RTS_ZFP DEAD Involves controlled objects -7.0.3 DEAD testing transient controlled finalizers, requires post 7.0.3 +RTS_ZFP DEAD Involves controlled objects +RTS_LIGHT_TASKING DEAD Involes controlled objects +7.0.3 DEAD testing transient controlled finalizers, requires post 7.0.3 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/N630-009-forward_p_x/test.opt b/testsuite/tests/N630-009-forward_p_x/test.opt index ce433215b..5096f7b9b 100644 --- a/testsuite/tests/N630-009-forward_p_x/test.opt +++ b/testsuite/tests/N630-009-forward_p_x/test.opt @@ -1 +1,2 @@ native DEAD testing gnatcov/gnatemu interaction, no gnatemu on native +src-traces DEAD gnatcov/gnatemu interaction not relevant for the trace mode diff --git a/testsuite/tests/NC08-027-target_attr/test.opt b/testsuite/tests/NC08-027-target_attr/test.opt index 0c7704396..418d1af51 100644 --- a/testsuite/tests/NC08-027-target_attr/test.opt +++ b/testsuite/tests/NC08-027-target_attr/test.opt @@ -1 +1,2 @@ native DEAD testing --target interactions, no --target at all for native. +src-traces DEAD test specific to gnatcov run diff --git a/testsuite/tests/T319-018-if-expr/test.opt b/testsuite/tests/T319-018-if-expr/test.opt index 135a50b26..e0ed9ce5c 100644 --- a/testsuite/tests/T319-018-if-expr/test.opt +++ b/testsuite/tests/T319-018-if-expr/test.opt @@ -1,2 +1,3 @@ RTS_ZFP DEAD Test requires dynamic interface conversions +RTS_LIGHT_TASKING DEAD Test requires dynamic interface conversions 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/U204-026-arch-mix/test.opt b/testsuite/tests/U204-026-arch-mix/test.opt index fefea3e78..8c2fc9d10 100644 --- a/testsuite/tests/U204-026-arch-mix/test.opt +++ b/testsuite/tests/U204-026-arch-mix/test.opt @@ -1 +1,2 @@ RTS_ZFP DEAD Native instrumentation not compatible with cross light profiles +RTS_LIGHT_TASKING DEAD Native instr not compatible with cross light-tasking profiles diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/test.opt b/testsuite/tests/instr-cov/main_autodump/nested_block/test.opt index e239b0933..ddd35d955 100644 --- a/testsuite/tests/instr-cov/main_autodump/nested_block/test.opt +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/test.opt @@ -1 +1,2 @@ RTS_ZFP DEAD Test only makes sense with exception propagation +RTS_LIGHT_TASKING DEAD Test only makes sens with exception propagation diff --git a/testsuite/tests/instr-cov/main_autodump/stubs/test.opt b/testsuite/tests/instr-cov/main_autodump/stubs/test.opt new file mode 100644 index 000000000..32846ff56 --- /dev/null +++ b/testsuite/tests/instr-cov/main_autodump/stubs/test.opt @@ -0,0 +1 @@ +RTS_LIGHT_TASKING XFAIL Issue with task termination for these runtimes diff --git a/testsuite/tests/instr-cov/pragma_after_cu/test.opt b/testsuite/tests/instr-cov/pragma_after_cu/test.opt index a1ace576d..2b7d39df5 100644 --- a/testsuite/tests/instr-cov/pragma_after_cu/test.opt +++ b/testsuite/tests/instr-cov/pragma_after_cu/test.opt @@ -1 +1,2 @@ -src-traces,RTS_ZFP DEAD Cannot dump coverage buffers in this test without non-local execption propagation +src-traces,RTS_ZFP DEAD Cannot dump coverage buffers in this test without non-local exception propagation +src-traces,RTS_LIGHT_TASKING DEAD requires exception propagation From 4cc7af3b15ee6a109daddf960e9af8d2266c30a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 18 Dec 2023 12:58:25 +0100 Subject: [PATCH 0590/1483] instr.py: change default dump trigger for light-taskig runtimes There seems to be an issue with the dependent fallback handlers of Ada.Task_Termination in the light-tasking runtimes, resulting in the handler not being executed at the end of the main. This thus makes it impossible to use that dump trigger, so change the default dump trigger of light-tasking runtime to be main-end. --- testsuite/SCOV/instr.py | 11 +++++++++-- .../tests/instr-cov/main_autodump/stubs/test.opt | 1 - 2 files changed, 9 insertions(+), 3 deletions(-) delete mode 100644 testsuite/tests/instr-cov/main_autodump/stubs/test.opt diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index de69eb739..3d05da07b 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -20,7 +20,11 @@ def default_dump_trigger(mains): # It does not make sense to have a dump-trigger=ravenscar-task-termination # if the main is not an Ada program. elif (all([ext(main) == 'adb' for main in mains]) - and RUNTIME_INFO.has_ravenscar_runtime): + and RUNTIME_INFO.has_ravenscar_runtime + # TODO: There seems to be a problem with light-tasking runtimes and + # task-termination, so default back to main end in that case. + # See eng/cov/gnatcoverage#191 + and "light-tasking" not in RUNTIME_INFO.runtime_name): return 'ravenscar-task-termination' else: return 'main-end' @@ -292,7 +296,10 @@ def available_ada_dump_triggers(): """ if RUNTIME_INFO.has_full_runtime: return ["main-end", "atexit"] - elif RUNTIME_INFO.has_ravenscar_runtime: + elif (RUNTIME_INFO.has_ravenscar_runtime + # TODO: remove once --dump-trigger=ravenscar-task-termination is + # fixed, see eng/das/cov/gnatcoverage#191. + and "light-tasking" not in RUNTIME_INFO.runtime_name): return ["main-end", "ravenscar-task-termination"] else: return ["main-end"] diff --git a/testsuite/tests/instr-cov/main_autodump/stubs/test.opt b/testsuite/tests/instr-cov/main_autodump/stubs/test.opt deleted file mode 100644 index 32846ff56..000000000 --- a/testsuite/tests/instr-cov/main_autodump/stubs/test.opt +++ /dev/null @@ -1 +0,0 @@ -RTS_LIGHT_TASKING XFAIL Issue with task termination for these runtimes From 6e8f20adbe4ba43865c53e36468098421056a01b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 18 Dec 2023 10:27:00 +0100 Subject: [PATCH 0591/1483] testsuite.py: override default last chance handler for QNX QNX and run-cross2 register an abort as an abnormal termination, the silent last chance handler can't thus use this configuration. QNX does provide the exit function, use that instead. --- testsuite/testsuite.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 1f1241741..f8aaa51d5 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1113,6 +1113,13 @@ def _build_libsupport(self): if args.RTS: libsup_vars.append("RTS={}".format(args.RTS)) + # QNX + run-cross2 will report an abort as an abnormal program + # termination, which is not the point of the silent last chance + # handler. QNX however does provide the exit function, so use that + # instead. + if "qnx" in args.target: + libsup_vars.append("SILENT_LCH=exit") + logfile = os.path.join(self.output_dir, 'build_support.out') p = Run(['make', '--debug', '-C', 'support', '-f', 'Makefile.libsupport'] + From 15affc8bbb6df4ebb162e8ae144bab371a0b8994 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 18 Dec 2023 14:15:20 +0100 Subject: [PATCH 0592/1483] Kill Long line test for QNX The amount of IO needed for this test makes the emulator hang. --- testsuite/tests/instr-cov/W502-023-base64-long-lines/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/instr-cov/W502-023-base64-long-lines/test.opt diff --git a/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.opt b/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.opt new file mode 100644 index 000000000..b2e067acc --- /dev/null +++ b/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.opt @@ -0,0 +1 @@ +aarch64-qnx DEAD Slow IO prevents the test from finishing From 1ec11ab336327d94dc171e5961439e68d393cf3a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 20 Dec 2023 15:31:20 +0000 Subject: [PATCH 0593/1483] Testsuite: fix testsuite runs with default target "args.target" is None when "--target" is not passed to the "testsuite.py" script: fix the QNX target check to work in this case. --- testsuite/testsuite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index f8aaa51d5..4e0e8eddb 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1117,7 +1117,7 @@ def _build_libsupport(self): # termination, which is not the point of the silent last chance # handler. QNX however does provide the exit function, so use that # instead. - if "qnx" in args.target: + if args.target and "qnx" in args.target: libsup_vars.append("SILENT_LCH=exit") logfile = os.path.join(self.output_dir, 'build_support.out') From dca42bbc495a94f10b60fee889198979bf82eb57 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 20 Dec 2023 15:20:44 +0000 Subject: [PATCH 0594/1483] Ada: do not instrument decisions in Ghost_Predicate Expressions associated to these predicates are ghost code, so gnatcov should never instrument them. --- .../instr-cov/pragma_ghost_predicate/main.adb | 6 +++ .../instr-cov/pragma_ghost_predicate/pkg.ads | 15 ++++++++ .../instr-cov/pragma_ghost_predicate/test.out | 2 + .../instr-cov/pragma_ghost_predicate/test.py | 37 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 3 ++ 5 files changed, 63 insertions(+) create mode 100644 testsuite/tests/instr-cov/pragma_ghost_predicate/main.adb create mode 100644 testsuite/tests/instr-cov/pragma_ghost_predicate/pkg.ads create mode 100644 testsuite/tests/instr-cov/pragma_ghost_predicate/test.out create mode 100644 testsuite/tests/instr-cov/pragma_ghost_predicate/test.py diff --git a/testsuite/tests/instr-cov/pragma_ghost_predicate/main.adb b/testsuite/tests/instr-cov/pragma_ghost_predicate/main.adb new file mode 100644 index 000000000..f759cb8a0 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_ghost_predicate/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; +end Main; diff --git a/testsuite/tests/instr-cov/pragma_ghost_predicate/pkg.ads b/testsuite/tests/instr-cov/pragma_ghost_predicate/pkg.ads new file mode 100644 index 000000000..4136f2f74 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_ghost_predicate/pkg.ads @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package Pkg is + + type R1 is record + X, Y : Integer; + end record + with Ghost_Predicate => R1.X /= 0 and then R1.Y /= 0; + + subtype R2 is R1 + with Ghost_Predicate => R2.X mod 2 = 0 and then R2.Y mod 2 = 0; + + procedure Foo is null; + +end Pkg; diff --git a/testsuite/tests/instr-cov/pragma_ghost_predicate/test.out b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.out new file mode 100644 index 000000000..61483536e --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.out @@ -0,0 +1,2 @@ +5.04a1 DEAD Test support for an Ada 2012 feature +7.1.2 DEAD Test support for an Ada 2012 feature diff --git a/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py new file mode 100644 index 000000000..1d8c2b5b5 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py @@ -0,0 +1,37 @@ +""" +Check that decisions in Ghost_Predicate aspects are not instrumented. + +They used to be instrumented as decisions, and thus be reported as uncovered in +this example program. +""" + +import os.path + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.control import env +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": {"+": {5}}, + "pkg.ads.xcov": {"+": {5, 10, 13}}, + }, + "xcov", +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 4446474ab..43da2ec1b 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -172,6 +172,7 @@ package body Instrument.Ada_Unit is Dynamic_Predicate, Invariant, + Ghost_Predicate, Post, Postcondition, Pre, @@ -214,6 +215,7 @@ package body Instrument.Ada_Unit is Precomputed_Symbols : constant array (All_Symbols) of Symbol_Type := (Dynamic_Predicate => Precompute_Symbol (Dynamic_Predicate), + Ghost_Predicate => Precompute_Symbol (Ghost_Predicate), Invariant => Precompute_Symbol (Invariant), Post => Precompute_Symbol (Post), Postcondition => Precompute_Symbol (Postcondition), @@ -5972,6 +5974,7 @@ package body Instrument.Ada_Unit is begin if Aspect_Assoc_Name (AN) in As_Symbol (Dynamic_Predicate) | As_Symbol (Invariant) + | As_Symbol (Ghost_Predicate) | As_Symbol (Post) | As_Symbol (Postcondition) | As_Symbol (Pre) From c827acebe0e77c8a74aa09ca1a7dcc5e2722b624 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 20 Dec 2023 15:25:06 +0000 Subject: [PATCH 0595/1483] instrument-ada_unit.adb: minor reformatting --- tools/gnatcov/instrument-ada_unit.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 43da2ec1b..f189fc611 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -4688,7 +4688,7 @@ package body Instrument.Ada_Unit is when Name_Postcondition => "Postcondition", when others => ""); - Location : constant String := + Location : constant String := Ada.Directories.Simple_Name (N.Unit.Get_Filename) & ":" & Image (Sloc (N)); From e0bcc55367464b6942b6dd624354685653931c0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 20 Dec 2023 17:12:52 +0100 Subject: [PATCH 0596/1483] .gitlab-ci.yaml: Fix bin-traces board name --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c69e4703c..59a719616 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -167,7 +167,7 @@ test_bin_traces: - *retrieve_gnatcoverage_extras_and_setup_anod_repo # Test using anod - - anod test gnatcov --minimal --target=leon3-elf -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER + - anod test gnatcov --minimal --target=leon3-elf,,qemu -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER - TEST_BSN=$(anod eval --primitive=test gnatcov --target=leon3-elf -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER build_space_name) - mv leon3-elf-linux64/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report From ab32f7bbeec0c688a7175c3948f5f8b1c0b1d0b1 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 21 Dec 2023 10:49:39 +0100 Subject: [PATCH 0597/1483] CI: fix machine information to compute build spaces --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 59a719616..03b53efe3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -168,7 +168,7 @@ test_bin_traces: # Test using anod - anod test gnatcov --minimal --target=leon3-elf,,qemu -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER - - TEST_BSN=$(anod eval --primitive=test gnatcov --target=leon3-elf -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER build_space_name) + - TEST_BSN=$(anod eval --primitive=test gnatcov --target=leon3-elf,,qemu -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER build_space_name) - mv leon3-elf-linux64/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report --failure-exit-code 1 From 829a7b242e725ac81c573e7ce37824a917d83779 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 21 Dec 2023 11:36:47 +0000 Subject: [PATCH 0598/1483] instr-cov/pragma_ghost_predicate: adjust for binary traces To harmonize with source traces, do not generate code for assertions (so that we always get "no-code" for Ghost_Predicate) and remove expectations for type declarations (they are "no-code" with binary traces, "covered" with source traces). --- testsuite/tests/instr-cov/pragma_ghost_predicate/pkg.ads | 1 + testsuite/tests/instr-cov/pragma_ghost_predicate/test.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/instr-cov/pragma_ghost_predicate/pkg.ads b/testsuite/tests/instr-cov/pragma_ghost_predicate/pkg.ads index 4136f2f74..b85c4653a 100644 --- a/testsuite/tests/instr-cov/pragma_ghost_predicate/pkg.ads +++ b/testsuite/tests/instr-cov/pragma_ghost_predicate/pkg.ads @@ -1,4 +1,5 @@ pragma Ada_2012; +pragma Assertion_Policy (Disable); package Pkg is diff --git a/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py index 1d8c2b5b5..6f90cb1f9 100644 --- a/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py +++ b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py @@ -29,7 +29,7 @@ "*.xcov", { "main.adb.xcov": {"+": {5}}, - "pkg.ads.xcov": {"+": {5, 10, 13}}, + "pkg.ads.xcov": {"+": {14}}, }, "xcov", ) From 28485df984fa7b8efb3196dcfb81f5dee6ff6ec2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 20 Dec 2023 16:04:04 +0100 Subject: [PATCH 0599/1483] Remove Ada_2012 and use Silent_Last_Chance in test This makes it possible to run this test on the 5.04a1 toolchain that does not support Ada_2012 and the use of Ada.Assertions to catch assertion-related exceptions. --- .../bin-mcdc-atcc.expected | 26 ++++++++--------- .../bin-ucmcdc-atcc.expected | 28 +++++++++---------- .../O212-062-show-condition-vectors/pkg.adb | 15 ++++++---- .../src-mcdc-atcc.expected | 24 ++++++++-------- .../src-ucmcdc-atcc.expected | 26 ++++++++--------- 5 files changed, 62 insertions(+), 57 deletions(-) diff --git a/testsuite/tests/O212-062-show-condition-vectors/bin-mcdc-atcc.expected b/testsuite/tests/O212-062-show-condition-vectors/bin-mcdc-atcc.expected index 698e8f682..249a711bc 100644 --- a/testsuite/tests/O212-062-show-condition-vectors/bin-mcdc-atcc.expected +++ b/testsuite/tests/O212-062-show-condition-vectors/bin-mcdc-atcc.expected @@ -3,32 +3,32 @@ 2\.3\. MCDC COVERAGE -+ -pkg\.adb:13:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:13:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:13:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) +pkg\.adb:18:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) Evaluation vectors found: F - - F -> FALSE In a pair for C0, C3 T T F T -> TRUE In a pair for C3 T T T - -> TRUE In a pair for C0 -pkg\.adb:24:50: condition 1 \("A"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:24:60: condition 2 \("B"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:24:25: Decision of the form \(\(C0 or else C1\) or else C2\) +pkg\.adb:29:50: condition 1 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:29:60: condition 2 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:29:25: Decision of the form \(\(C0 or else C1\) or else C2\) Evaluation vectors found: F F F -> FALSE In a pair for C0 T - - -> TRUE In a pair for C0 -pkg\.adb:25:25: contract expression outcome FALSE never exercised -pkg\.adb:25:39: decision never evaluated -pkg\.adb:34:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:34:13: Decision of the form \(C0 and then C1\) +pkg\.adb:30:25: contract expression outcome FALSE never exercised +pkg\.adb:30:39: decision never evaluated +pkg\.adb:39:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:39:13: Decision of the form \(C0 and then C1\) Evaluation vectors found: F - -> FALSE In a pair for C0 T T -> TRUE In a pair for C0 -pkg\.adb:40:37: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:40:48: condition 2 \("A"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:40:26: Decision of the form \(\(C0 and then C1\) or else C2\) +pkg\.adb:45:37: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:45:48: condition 2 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:45:26: Decision of the form \(\(C0 and then C1\) or else C2\) Evaluation vectors found: F - F -> FALSE In a pair for C0 T T - -> TRUE In a pair for C0 diff --git a/testsuite/tests/O212-062-show-condition-vectors/bin-ucmcdc-atcc.expected b/testsuite/tests/O212-062-show-condition-vectors/bin-ucmcdc-atcc.expected index 4812d2f8b..97338c0af 100644 --- a/testsuite/tests/O212-062-show-condition-vectors/bin-ucmcdc-atcc.expected +++ b/testsuite/tests/O212-062-show-condition-vectors/bin-ucmcdc-atcc.expected @@ -3,33 +3,33 @@ 2\.3\. UC_MCDC COVERAGE -+ -pkg\.adb:13:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:13:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:13:47: condition 3 \("A"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:13:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) +pkg\.adb:18:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:47: condition 3 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) Evaluation vectors found: F - - F -> FALSE In a pair for C0 T T T - -> TRUE In a pair for C0 T T F T -> TRUE Not part of any pair -pkg\.adb:24:50: condition 1 \("A"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:24:60: condition 2 \("B"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:24:25: Decision of the form \(\(C0 or else C1\) or else C2\) +pkg\.adb:29:50: condition 1 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:29:60: condition 2 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:29:25: Decision of the form \(\(C0 or else C1\) or else C2\) Evaluation vectors found: F F F -> FALSE In a pair for C0 T - - -> TRUE In a pair for C0 -pkg\.adb:25:25: contract expression outcome FALSE never exercised -pkg\.adb:25:39: decision never evaluated -pkg\.adb:34:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:34:13: Decision of the form \(C0 and then C1\) +pkg\.adb:30:25: contract expression outcome FALSE never exercised +pkg\.adb:30:39: decision never evaluated +pkg\.adb:39:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:39:13: Decision of the form \(C0 and then C1\) Evaluation vectors found: F - -> FALSE In a pair for C0 T T -> TRUE In a pair for C0 -pkg\.adb:40:37: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:40:48: condition 2 \("A"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:40:26: Decision of the form \(\(C0 and then C1\) or else C2\) +pkg\.adb:45:37: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:45:48: condition 2 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:45:26: Decision of the form \(\(C0 and then C1\) or else C2\) Evaluation vectors found: F - F -> FALSE In a pair for C0 T T - -> TRUE In a pair for C0 diff --git a/testsuite/tests/O212-062-show-condition-vectors/pkg.adb b/testsuite/tests/O212-062-show-condition-vectors/pkg.adb index 056929256..f863e28d1 100644 --- a/testsuite/tests/O212-062-show-condition-vectors/pkg.adb +++ b/testsuite/tests/O212-062-show-condition-vectors/pkg.adb @@ -1,13 +1,18 @@ -pragma Ada_2012; pragma Assertion_Policy (Check); with Ada.Text_IO; use Ada.Text_IO; -with Ada.Assertions; use Ada.Assertions; +with Silent_Last_Chance; + package body Pkg is procedure Mystery (A, B, C : Boolean) is - function Id (B : Boolean) return Boolean is (B); + function Id (B : Boolean) return Boolean; + + function Id (B : Boolean) return Boolean is + begin + return B; + end Id; begin begin if (A and then B and then C) or else A then @@ -24,7 +29,7 @@ package body Pkg is pragma Assert (Id (A or else B) or else A or else B); pragma Assert (B or else Id (A or else B)); exception - when Ada.Assertions.Assertion_Error => null; + when others => null; end; end Mystery; @@ -39,7 +44,7 @@ package body Pkg is pragma Assert ((A and then B) or else A); exception - when Ada.Assertions.Assertion_Error => null; + when others => null; end; end Other_Proc; end Pkg; diff --git a/testsuite/tests/O212-062-show-condition-vectors/src-mcdc-atcc.expected b/testsuite/tests/O212-062-show-condition-vectors/src-mcdc-atcc.expected index 8b23cebd2..4a0d7dc35 100644 --- a/testsuite/tests/O212-062-show-condition-vectors/src-mcdc-atcc.expected +++ b/testsuite/tests/O212-062-show-condition-vectors/src-mcdc-atcc.expected @@ -3,16 +3,16 @@ 2\.3\. MCDC COVERAGE -+ -pkg\.adb:13:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:13:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:13:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) +pkg\.adb:18:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) Evaluation vectors found: F - - F -> FALSE In a pair for C0, C3 T T F T -> TRUE In a pair for C3 T T T - -> TRUE In a pair for C0 -pkg\.adb:34:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:34:13: Decision of the form \(C0 and then C1\) +pkg\.adb:39:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:39:13: Decision of the form \(C0 and then C1\) Evaluation vectors found: F - -> FALSE In a pair for C0 T T -> TRUE In a pair for C0 @@ -24,20 +24,20 @@ Evaluation vectors found: 2\.5\. ATCC COVERAGE -+ -pkg\.adb:24:50: condition 1 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved -pkg\.adb:24:60: condition 2 \("B"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved -pkg\.adb:24:25: Decision of the form \(\(C0 or else C1\) or else C2\) +pkg\.adb:29:50: condition 1 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:29:60: condition 2 \("B"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:29:25: Decision of the form \(\(C0 or else C1\) or else C2\) Evaluation vectors found: F F F -> FALSE T - - -> TRUE -pkg\.adb:25:35: condition 1 \("Id \(A or ..."\) was never evaluated during an evaluation of the decision to True, ATCC not achieved -pkg\.adb:25:25: Decision of the form \(C0 or else C1\) +pkg\.adb:30:35: condition 1 \("Id \(A or ..."\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:30:25: Decision of the form \(C0 or else C1\) Evaluation vectors found: T - -> TRUE -pkg\.adb:40:48: condition 2 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved -pkg\.adb:40:26: Decision of the form \(\(C0 and then C1\) or else C2\) +pkg\.adb:45:48: condition 2 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:45:26: Decision of the form \(\(C0 and then C1\) or else C2\) Evaluation vectors found: F - F -> FALSE T T - -> TRUE diff --git a/testsuite/tests/O212-062-show-condition-vectors/src-ucmcdc-atcc.expected b/testsuite/tests/O212-062-show-condition-vectors/src-ucmcdc-atcc.expected index 1d99cbd6c..91e97090c 100644 --- a/testsuite/tests/O212-062-show-condition-vectors/src-ucmcdc-atcc.expected +++ b/testsuite/tests/O212-062-show-condition-vectors/src-ucmcdc-atcc.expected @@ -3,17 +3,17 @@ 2\.3\. UC_MCDC COVERAGE -+ -pkg\.adb:13:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:13:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:13:47: condition 3 \("A"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:13:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) +pkg\.adb:18:25: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:36: condition 2 \("C"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:47: condition 3 \("A"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:18:14: Decision of the form \(\(\(C0 and then C1\) and then C2\) or else C3\) Evaluation vectors found: F - - F -> FALSE In a pair for C0 T T T - -> TRUE In a pair for C0 T T F T -> TRUE Not part of any pair -pkg\.adb:34:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved -pkg\.adb:34:13: Decision of the form \(C0 and then C1\) +pkg\.adb:39:24: condition 1 \("B"\) has no independent influence pair, MC/DC not achieved +pkg\.adb:39:13: Decision of the form \(C0 and then C1\) Evaluation vectors found: F - -> FALSE In a pair for C0 T T -> TRUE In a pair for C0 @@ -25,20 +25,20 @@ Evaluation vectors found: 2\.5\. ATCC COVERAGE -+ -pkg\.adb:24:50: condition 1 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved -pkg\.adb:24:60: condition 2 \("B"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved -pkg\.adb:24:25: Decision of the form \(\(C0 or else C1\) or else C2\) +pkg\.adb:29:50: condition 1 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:29:60: condition 2 \("B"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:29:25: Decision of the form \(\(C0 or else C1\) or else C2\) Evaluation vectors found: F F F -> FALSE T - - -> TRUE -pkg\.adb:25:35: condition 1 \("Id \(A or ..."\) was never evaluated during an evaluation of the decision to True, ATCC not achieved -pkg\.adb:25:25: Decision of the form \(C0 or else C1\) +pkg\.adb:30:35: condition 1 \("Id \(A or ..."\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:30:25: Decision of the form \(C0 or else C1\) Evaluation vectors found: T - -> TRUE -pkg\.adb:40:48: condition 2 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved -pkg\.adb:40:26: Decision of the form \(\(C0 and then C1\) or else C2\) +pkg\.adb:45:48: condition 2 \("A"\) was never evaluated during an evaluation of the decision to True, ATCC not achieved +pkg\.adb:45:26: Decision of the form \(\(C0 and then C1\) or else C2\) Evaluation vectors found: F - F -> FALSE T T - -> TRUE From bb601a4cc772721ea6f582c53c26a3eab0d45787 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 21 Dec 2023 16:33:08 +0100 Subject: [PATCH 0600/1483] instrument-c.adb: Ensure buffer dump decl is inserted for manual dump Ensure, when using --dump-trigger=manual, that there is an extern declaration for the function to dump buffers in order to avoid warnings at compile time. --- testsuite/tests/instr-cov/c_manual_dump/test.py | 6 ++++++ tools/gnatcov/instrument-c.adb | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/testsuite/tests/instr-cov/c_manual_dump/test.py b/testsuite/tests/instr-cov/c_manual_dump/test.py index 69dabfec3..7fdbee9eb 100644 --- a/testsuite/tests/instr-cov/c_manual_dump/test.py +++ b/testsuite/tests/instr-cov/c_manual_dump/test.py @@ -41,6 +41,12 @@ manual_prj_name="main", tolerate_instrument_messages=instr_warning) +thistest.fail_if_not_equal( + what="gprbuild output not empty", + expected="", + actual=contents_of("gprbuild.out").strip() +) + # Check that that the dump call indication was correctly replaced in the sub # project diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 9a08c5db8..4ca2d1337 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3945,6 +3945,11 @@ package body Instrument.C is Create (Output_File, Out_File, Tmp_Filename); S := Stream (Output_File); Has_Manual_Indication := True; + + -- Put an external decl for the buffers dump function + + String'Write + (S, "extern void " & Dump_Procedure & "(void);"); end if; String'Write (S, Str (Index .. Matches (0).First)); From 609d4bfa610715125bf3cb97c80437ad0129c91a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 22 Dec 2023 10:38:23 +0100 Subject: [PATCH 0601/1483] instr-cov/pragma_ghost_predicate: fix "test.opt" filename --- .../tests/instr-cov/pragma_ghost_predicate/{test.out => test.opt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename testsuite/tests/instr-cov/pragma_ghost_predicate/{test.out => test.opt} (100%) diff --git a/testsuite/tests/instr-cov/pragma_ghost_predicate/test.out b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.opt similarity index 100% rename from testsuite/tests/instr-cov/pragma_ghost_predicate/test.out rename to testsuite/tests/instr-cov/pragma_ghost_predicate/test.opt From be3ed2721253dd84196a1a6bf8f5cb9fee4fb95a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 22 Dec 2023 14:44:55 +0000 Subject: [PATCH 0602/1483] instrument-ada_unit.adb: minor reformatting --- tools/gnatcov/instrument-ada_unit.adb | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index f189fc611..306c77be9 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -9095,6 +9095,7 @@ package body Instrument.Ada_Unit is -- Instrument the file only if it is a file of interest if Files_Of_Interest.Contains (Create_Normalized (Filename)) then + -- In verbose mode, always print a notice for the source file -- that we are about to instrument. In non-verbose mode, just get -- prepared to print it in case we emit a "source file missing" From fadff443be47b86eaa4f7ab549f07cab5955625d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 22 Dec 2023 14:45:08 +0000 Subject: [PATCH 0603/1483] Ada instrumenter: clear the non-instrumented LL SCOs between src. files Data structures that track non-instrumented SCOs are based on low-level SCOs. Since the Ada instrumenter converts low-level SCOs to high-level SCOs for each source file separately, low-level SCOs are invalidated before each new source file, and so non-instrumented SCOs data structures must be reset at that time. --- .../instr-cov/198-non-instr-scos/main.adb | 7 ++++ .../instr-cov/198-non-instr-scos/pkg.adb | 14 +++++++ .../instr-cov/198-non-instr-scos/pkg.ads | 9 ++++ .../instr-cov/198-non-instr-scos/test.py | 42 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 8 ++++ 5 files changed, 80 insertions(+) create mode 100644 testsuite/tests/instr-cov/198-non-instr-scos/main.adb create mode 100644 testsuite/tests/instr-cov/198-non-instr-scos/pkg.adb create mode 100644 testsuite/tests/instr-cov/198-non-instr-scos/pkg.ads create mode 100644 testsuite/tests/instr-cov/198-non-instr-scos/test.py diff --git a/testsuite/tests/instr-cov/198-non-instr-scos/main.adb b/testsuite/tests/instr-cov/198-non-instr-scos/main.adb new file mode 100644 index 000000000..3fff114ee --- /dev/null +++ b/testsuite/tests/instr-cov/198-non-instr-scos/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is + V : Pkg.T := Pkg.Create; +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/198-non-instr-scos/pkg.adb b/testsuite/tests/instr-cov/198-non-instr-scos/pkg.adb new file mode 100644 index 000000000..3f25bad55 --- /dev/null +++ b/testsuite/tests/instr-cov/198-non-instr-scos/pkg.adb @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package body Pkg is + + ------------ + -- Length -- + ------------ + + function Length (Self : T) return Natural is + begin + return 0; + end Length; + +end Pkg; diff --git a/testsuite/tests/instr-cov/198-non-instr-scos/pkg.ads b/testsuite/tests/instr-cov/198-non-instr-scos/pkg.ads new file mode 100644 index 000000000..5e4ac24fd --- /dev/null +++ b/testsuite/tests/instr-cov/198-non-instr-scos/pkg.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; + +package Pkg is + type T is tagged null record; + + function Length (Self : T) return Natural; + + function Create return T is (null record); +end Pkg; diff --git a/testsuite/tests/instr-cov/198-non-instr-scos/test.py b/testsuite/tests/instr-cov/198-non-instr-scos/test.py new file mode 100644 index 000000000..5e6f7b59a --- /dev/null +++ b/testsuite/tests/instr-cov/198-non-instr-scos/test.py @@ -0,0 +1,42 @@ +""" +Regression testcase specific to the Ada instrumenter: check that a +non-instrumented SCO in one source file (pkg.ads) does not trigger a crash in +the next source file that is instrumented for the same unit (pkg.adb). +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Avoid "creating output path" info messages +os.mkdir("obj") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + tolerate_instrument_messages=( + ".*cannot instrument an expression function which.*" + ), +) +check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": {"+": {4, 6}}, + "pkg.ads.xcov": {"?": {8}}, + "pkg.adb.xcov": {"-": {11}}, + }, + cwd="xcov", +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 306c77be9..4bbf36cb4 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8010,6 +8010,14 @@ package body Instrument.Ada_Unit is UIC.Unit_Bits.Decision_Bits := LL_Decision_SCO_Bit_Allocs.Empty; UIC.Unit_Bits.Statement_Bits := LL_Statement_SCO_Bit_Allocs.Empty; + -- Instrumentation of another source file in the same unit may have + -- produced non-instrumented low-level SCOs in UIC.Non_Instr_LL_SCOs, + -- which were later converted to high-level SCOS, and the low-level SCO + -- table was since then cleared, so UIC.Non_Instr_LL_SCOs may contain + -- stale entries: clear it. + + UIC.Non_Instr_LL_SCOs.Clear; + Initialize_Rewriting (UIC, Instrumenter); UIC.Instrumented_Unit := CU_Name; From 3e37ef4d368d394a252371044ebea3b1fe0fd692 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 3 Jan 2024 14:55:55 +0100 Subject: [PATCH 0604/1483] Setup: Refine the heuristic for full runtime detection The QNX light-tasking runtime provides the Ada.Command_Line unit, but is not a full runtime (as it does not provide e.g. GNAT.OS_Lib). Check for the presence of GNAT.OS_Lib rather than Ada.Command_Line to determine whether the runtime is a full runtime or not. --- tools/gnatcov/setup_rts.adb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 553626413..8649f2313 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -463,8 +463,8 @@ package body Setup_RTS is -- The best heuristic we have to determine if the actual runtime is -- "full" is to look for an Ada source file that is typically found in - -- full runtime: "a-comlin.ads" for the Ada.Command_Line unit. If we do - -- not have it, consider that the runtime is embedded. + -- full runtime: "g-os_lib.ads" for the GNAT.OS_Lib unit. If we do not + -- have it, consider that the runtime is embedded. -- -- When only C is enabled and we do not have a runtime at hand to guess -- what is available, fall back to the full profile for native @@ -473,7 +473,7 @@ package body Setup_RTS is Auto_RTS_Profile := Embedded; if Has_Ada then for F of Prj.Runtime_Project.Sources loop - if F.Path_Name.Simple_Name = "a-comlin.ads" then + if F.Path_Name.Simple_Name = "g-os_lib.ads" then Auto_RTS_Profile := Full; exit; end if; From 867aa20cc24b02c1e4f3f64b533c6430cd2a9e0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 8 Jan 2024 10:04:22 +0100 Subject: [PATCH 0605/1483] instrument-ada_unit.adb: Add missing with clause The unit lacks a with clause for Ada.Finalization. While this is not detected by the current stable compiler and thus master builds fine, this prevents the unit from being built with the latest compiler on the edge branch. This change adds the missing with clause. --- tools/gnatcov/instrument-ada_unit.adb | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 4bbf36cb4..fa50015f6 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -21,6 +21,7 @@ with Ada.Characters.Handling; with Ada.Directories; with Ada.Containers; use Ada.Containers; with Ada.Exceptions; +with Ada.Finalization; with Ada.Strings.Wide_Wide_Fixed; pragma Warnings (Off, "* is an internal GNAT unit"); with Ada.Strings.Wide_Wide_Unbounded.Aux; From 221f260001d1ea5bd55c083876e121c19a256742 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 8 Jan 2024 10:45:39 +0000 Subject: [PATCH 0606/1483] instr-cov/198-non-instr-scos: kill with 5.04a1 toolchains This testcase relies on an Ada 2012 construct (expression function) in order to trigger a "uninstrumented" case in gnatcov: there is no pre-2012 construct that is known to have this effect. So just disable this testcase with toolchains that do not support Ada 2012. --- testsuite/tests/instr-cov/198-non-instr-scos/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/instr-cov/198-non-instr-scos/test.opt diff --git a/testsuite/tests/instr-cov/198-non-instr-scos/test.opt b/testsuite/tests/instr-cov/198-non-instr-scos/test.opt new file mode 100644 index 000000000..a2a0796ac --- /dev/null +++ b/testsuite/tests/instr-cov/198-non-instr-scos/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Ada 2012 support required From 04640cbcbf588a21a27ae2130d842ee70ba6754b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 8 Jan 2024 10:17:30 +0100 Subject: [PATCH 0607/1483] .gitlab-ci.yaml: Use the standard e3 image for all jobs The gnatcov image was used to get a pre-built binutils in the sandbox. This is no longer required now that binutils is a component and can thus be downloaded. This also brings all the generic_anod_ci capabilities to the gnatcov repo, including arbitrary depends-on, release branch support and so on. --- .gitlab-ci.yml | 137 +++++++++++++++---------------------------------- 1 file changed, 41 insertions(+), 96 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 03b53efe3..a824dd9cc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,32 +7,11 @@ variables: PACKAGE_BASE_NAME: gnatcoverage.tar.gz PACKAGE_ABSOLUTE_NAME: $CI_PROJECT_DIR/$PACKAGE_BASE_NAME - # These are not needed at the moment, but will be useful when we migrate - # to a multi-stage pipeline. - # PACKAGE_REPOSITORY_PROJECT: eng/cov/ci-packages - # CI_FRAGMENTS: ci-fragments - # CI_FRAGMENTS_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/it/$CI_FRAGMENTS - ANOD_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/it/anod - GNATCOVERAGE_EXTRA_GIT: https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/eng/cov/gnatcoverage-extra - -.edge_vars: &edge_vars - - | - if [ $CI_COMMIT_BRANCH = edge ] || [ $CI_MERGE_REQUEST_TARGET_BRANCH_NAME = edge ] - then - EDGE_QUALIFIER="-Qedge" - EDGE_REPO_SUFFIX="-edge" - else - EDGE_QUALIFIER="" - EDGE_REPO_SUFFIX="" - fi - -.common_anod_bits: &common_anod_bits - - cd /tmp - - git clone --depth 1 $ANOD_GIT - - cd /it/wave - - anod tune --anod-dir /tmp/anod - - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR - - GCV_INSTR_BSN=$(anod eval gnatcov -Qinstr $EDGE_QUALIFIER build_space_name) +.basic_setup: &basic_setup + - unset GITLAB_TOKEN + - generic_anod_ci --add-dep eng/das/cov/gnatcoverage-extra + - cat /tmp/ci_env.sh + - . /tmp/ci_env.sh stages: - build @@ -41,26 +20,20 @@ stages: build: interruptible: true services: - - image:gnatcov + - image:e3 - cpu:16 - mem:16 stage: build script: - require_issue - - - export PATH=/it/e3/bin:$PATH - - *edge_vars - - # Setup the repository - - *common_anod_bits - + - *basic_setup # Build using anod - - anod install gnatcov $EDGE_QUALIFIER --latest - - anod build --minimal gnatcov -Qinstr $EDGE_QUALIFIER + - anod install gnatcov $ACI_TRACK_QUALIFIER --latest + - anod build --minimal gnatcov -Qinstr $ACI_TRACK_QUALIFIER # Package all components created so far - - anod-copy-components --standalone-export /it/wave /it/wave/exp-comps - - tar czf $PACKAGE_ABSOLUTE_NAME -C / it/wave/exp-comps + - anod-copy-components --standalone-export $ANOD_DEFAULT_SANDBOX_DIR $ANOD_DEFAULT_SANDBOX_DIR/exp-comps + - tar czf $PACKAGE_ABSOLUTE_NAME -C / $ANOD_DEFAULT_SANDBOX_DIR/exp-comps - cd $CI_PROJECT_DIR - ls -l $PACKAGE_BASE_NAME @@ -79,9 +52,7 @@ build_docs: - doc/**/* when: always script: - - unset GITLAB_TOKEN - - generic_anod_ci - - . /tmp/ci_env.sh + - *basic_setup - anod build gnatdas-doc --latest - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/gnatdas-doc/install/share/doc/gnatdas/ $CI_PROJECT_DIR artifacts: @@ -94,56 +65,30 @@ build_docs: build_community: interruptible: true services: - - image:gnatcov + - image:e3 - cpu:8 - mem:16 stage: test script: - - export PATH=/it/e3/bin:$PATH - - *edge_vars - - # Setup the repository - - cd /tmp - - git clone --depth 1 $ANOD_GIT - - cd /it/wave - - anod tune --anod-dir /tmp/anod - - anod vcs --add-repo gnatcoverage$EDGE_REPO_SUFFIX $CI_PROJECT_DIR - + - *basic_setup # Build using anod - - anod build --minimal gnatcov -Qno-c $EDGE_QUALIFIER - -.common_test_bits: &retrieve_gnatcoverage_extras_and_setup_anod_repo - - export PATH=/it/e3/bin:$PATH - - *edge_vars - - # Get the gnatcoverage-extra repository. If we're testing a 'sync/' branch, - # expect the same for that repo. - - - cd /tmp - - EXTRA_BRANCH=master - - if [[ $CI_COMMIT_BRANCH =~ ^sync/ ]]; then - EXTRA_BRANCH=$CI_COMMIT_BRANCH; - elif [[ $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ ^sync/ ]]; then - EXTRA_BRANCH=$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME; - elif [ $CI_COMMIT_BRANCH = edge ] || [ $CI_MERGE_REQUEST_TARGET_BRANCH_NAME = edge ]; then - EXTRA_BRANCH=edge; - fi - - git clone $GNATCOVERAGE_EXTRA_GIT -b $EXTRA_BRANCH - - # Setup the anod sandbox repositories - - *common_anod_bits - - anod vcs --add-repo gnatcoverage-extra$EDGE_REPO_SUFFIX /tmp/gnatcoverage-extra + - anod build --minimal gnatcov -Qno-c $ACI_TRACK_QUALIFIER $ACI_TRACK_QUALIFIER + +.common_test_bits: &basic_test_setup + # Setup the sandbox + - *basic_setup # Import components from the artifact and install the instrumented gnatcov, # then remove temporaries to save disk space. - tar zxf $PACKAGE_ABSOLUTE_NAME -C / - - anod-copy-components /it/wave/exp-comps /it/wave - - anod install gnatcov -Qinstr $EDGE_QUALIFIER - - rm -rf $PACKAGE_ABSOLUTE_NAME /it/wave/exp-comps + - anod-copy-components $ANOD_DEFAULT_SANDBOX_DIR/exp-comps $ANOD_DEFAULT_SANDBOX_DIR + - anod install gnatcov -Qinstr $ACI_TRACK_QUALIFIER + - rm -rf $PACKAGE_ABSOLUTE_NAME $ANOD_DEFAULT_SANDBOX_DIR/exp-comps # Setup the CI directory to host coverage results - mkdir $CI_PROJECT_DIR/coverage + .common_artifacts_bits: &artifacts artifacts: paths: @@ -159,65 +104,65 @@ build_community: test_bin_traces: interruptible: true services: - - image:gnatcov + - image:e3 - cpu:16 - mem:16 stage: test script: - - *retrieve_gnatcoverage_extras_and_setup_anod_repo + - *basic_test_setup # Test using anod - - anod test gnatcov --minimal --target=leon3-elf,,qemu -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER - - TEST_BSN=$(anod eval --primitive=test gnatcov --target=leon3-elf,,qemu -QRTS=embedded-leon3,-O0,instr $EDGE_QUALIFIER build_space_name) - - mv leon3-elf-linux64/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - anod test gnatcov --minimal --target=leon3-elf,,qemu -QRTS=embedded-leon3,-O0,instr $ACI_TRACK_QUALIFIER + - TEST_BSN=$(anod eval --primitive=test gnatcov --target=leon3-elf,,qemu -QRTS=embedded-leon3,-O0,instr $ACI_TRACK_QUALIFIER build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/leon3-elf-linux64/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name bin-traces - leon3-elf-linux64/$TEST_BSN/results/new/ + $ANOD_DEFAULT_SANDBOX_DIR/leon3-elf-linux64/$TEST_BSN/results/new/ <<: *artifacts test_src_traces: interruptible: true services: - - image:gnatcov + - image:e3 - cpu:16 - mem:16 stage: test script: - - *retrieve_gnatcoverage_extras_and_setup_anod_repo + - *basic_test_setup # Test using anod - - anod test gnatcov --minimal -Qsrc-traces,instr $EDGE_QUALIFIER - - TEST_BSN=$(anod eval --primitive=test gnatcov -Qsrc-traces,instr $EDGE_QUALIFIER build_space_name) - - mv x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - anod test gnatcov --minimal -Qsrc-traces,instr $ACI_TRACK_QUALIFIER + - TEST_BSN=$(anod eval --primitive=test gnatcov -Qsrc-traces,instr $ACI_TRACK_QUALIFIER build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name src-traces - x86_64-linux/$TEST_BSN/results/new/ + $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/results/new/ <<: *artifacts test_spark: interruptible: true services: - - image:gnatcov + - image:e3 - cpu:16 - mem:16 stage: test script: - - *retrieve_gnatcoverage_extras_and_setup_anod_repo + - *basic_test_setup # Test using anod - - anod test gnatcov --minimal -Qspark-tests,src-traces,instr $EDGE_QUALIFIER - - TEST_BSN=$(anod eval --primitive=test gnatcov -Qspark-tests,src-traces,instr $EDGE_QUALIFIER build_space_name) - - mv x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - anod test gnatcov --minimal -Qspark-tests,src-traces,instr $ACI_TRACK_QUALIFIER + - TEST_BSN=$(anod eval --primitive=test gnatcov -Qspark-tests,src-traces,instr $ACI_TRACK_QUALIFIER build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - e3-testsuite-report --failure-exit-code 1 --xunit-output $CI_PROJECT_DIR/xunit_output.xml --xunit-name spark - x86_64-linux/$TEST_BSN/results/new/ + $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/results/new/ <<: *artifacts From 2d28dfa7069782f3c5cd66880e98c1db47ca163b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 9 Jan 2024 10:24:57 +0100 Subject: [PATCH 0608/1483] GNATcov_RTS: Inline binding of errno This removes the dependency on GNAT.OS_Lib, and thus allows the coverage runtime to be built on more Ada runtimes, that may provide a libc but that don't include the GNAT.OS_Lib unit. --- .../rts/gnatcov_rts-traces-output-files.adb | 14 +++++++------- tools/gnatcov/rts/gnatcov_rts_c-os_interface.c | 7 +++++++ tools/gnatcov/rts/gnatcov_rts_c-os_interface.h | 5 +++++ 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb index 2521059bb..31ebeebf8 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb @@ -26,8 +26,6 @@ with Ada.Text_IO; use Ada.Text_IO; -with GNAT.OS_Lib; - with Interfaces.C; use Interfaces.C; with Interfaces.C.Strings; use Interfaces.C.Strings; @@ -130,9 +128,12 @@ package body GNATcov_RTS.Traces.Output.Files is function C_Strerror (Errnum : C.int) return C.Strings.chars_ptr; pragma Import (C, C_Strerror, "strerror"); - -- GNAT.OS_Lib.Errno_Message is not available in GNAT 5.04a1. Use the - -- C function to get a descriptive error message from the value of - -- errno. + -- strerror is already a function, we can bind to its symbol directly + + function C_Errno return C.Int; + pragma Import (C, C_Errno, "gnatcov_rts_get_errno"); + -- Get the errno value through the wrapper declared in + -- gnatcov_rts_c-os_interface.h. begin Write_Trace_File @@ -140,8 +141,7 @@ package body GNATcov_RTS.Traces.Output.Files is exception when IO_Error => declare - C_Error_Msg : constant chars_ptr := - C_Strerror (C.int (GNAT.OS_Lib.Errno)); + C_Error_Msg : constant chars_ptr := C_Strerror (C_Errno); Error_Msg : constant String := Value (C_Error_Msg); begin Ada.Text_IO.Put_Line diff --git a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.c b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.c index db46c24c2..f0150f4c0 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.c @@ -17,6 +17,7 @@ * * ****************************************************************************/ +#include #include #include @@ -44,3 +45,9 @@ gnatcov_rts_getpid (void) return (uint64_t) getpid (); #endif } + +int +gnatcov_rts_get_errno (void) +{ + return errno; +} diff --git a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h index 8e9e7a057..c2d0cda5d 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h @@ -36,6 +36,11 @@ extern "C" /* Return the current process ID as an unsigned 64-bit integer. */ extern uint64_t gnatcov_rts_getpid (void); + /* Return the value of errno. This is used to provide a symbol for the Ada + part of GNATcov_RTS to be able to access the value of errno, without + relying on GNAT.OS_Lib. */ + extern int gnatcov_rts_get_errno (void); + #ifdef __cplusplus } #endif From be05d9aea8932fe6079fe34e8007db24017a3fbe Mon Sep 17 00:00:00 2001 From: Tonu Naks Date: Wed, 10 Jan 2024 09:36:34 +0000 Subject: [PATCH 0609/1483] Fix gnatcoverage-qualification repository location eng/das/cov/gnatcoverage#203 --- qualification/genbundle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 7caac139f..938a02349 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -329,7 +329,7 @@ def current_gitbranch_at (dirname): } # The master GIT repo where our source artifacts reside -GIT_MASTER = "ssh://git.adacore.com/gnatcoverage-qualification" +GIT_MASTER = "git@ssh.gitlab.adacore-it.com:eng/das/cov/gnatcoverage-qualification.git" # The subdir name for this clone, relative to --root GIT_CLONE_SUBDIR = "gnatcoverage-git-clone" From 0e420973dd40b26c6df3cb489c3ecab840600d14 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 15 Dec 2023 13:52:53 +0000 Subject: [PATCH 0610/1483] instrument-ada_unit__stub.ads: typo fix in a comment --- tools/gnatcov/instrument-ada_unit__stub.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-ada_unit__stub.ads b/tools/gnatcov/instrument-ada_unit__stub.ads index 1eb4e78f8..4dcdaa4f6 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.ads +++ b/tools/gnatcov/instrument-ada_unit__stub.ads @@ -18,7 +18,7 @@ -- Stub of Instrument.Ada_Unit, to avoid pulling a dependency to libadalang -- when gnatcov is not built with Ada instrumentation support (basically the --- gnatcov32 executable that have support for binary traces only). +-- gnatcov32 executable that has support for binary traces only). with Instrument.Common; use Instrument.Common; From 7c1b3fb6db85505ca40704fd08c8b8f39d1c93ce Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 18 Dec 2023 12:09:45 +0000 Subject: [PATCH 0611/1483] Add stubs for Instrument.Ada_Preprocessing These stubs are used for all gnatcov.gpr "parts" that do not perform Ada instrumentation (i.e. all but gnatcov64). --- tools/gnatcov/gnatcov.gpr | 8 ++++- .../instrument-ada_preprocessing__stub.adb | 33 +++++++++++++++++ .../instrument-ada_preprocessing__stub.ads | 35 +++++++++++++++++++ 3 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 tools/gnatcov/instrument-ada_preprocessing__stub.adb create mode 100644 tools/gnatcov/instrument-ada_preprocessing__stub.ads diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index e3a322de4..d8fdb7aa2 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -107,12 +107,18 @@ project Gnatcov is case Part is when "lib32" | "lib64" | "driver" | "gnatcov32" => + for Specification ("Instrument.Ada_Preprocessing") + use "instrument-ada_preprocessing__stub.ads"; + for Body ("Instrument.Ada_Preprocessing") + use "instrument-ada_preprocessing__stub.adb"; + for Specification ("Instrument.Ada_Unit") use "instrument-ada_unit__stub.ads"; for Body ("Instrument.Ada_Unit") use "instrument-ada_unit__stub.adb"; - for Body ("Instrument.C") use "instrument-c__stub.adb"; + for Specification ("Instrument.C") use "instrument-c__stub.ads"; + for Body ("Instrument.C") use "instrument-c__stub.adb"; when "gnatcov64" | "compiler" => null; end case; diff --git a/tools/gnatcov/instrument-ada_preprocessing__stub.adb b/tools/gnatcov/instrument-ada_preprocessing__stub.adb new file mode 100644 index 000000000..6e6e23cb5 --- /dev/null +++ b/tools/gnatcov/instrument-ada_preprocessing__stub.adb @@ -0,0 +1,33 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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. -- +------------------------------------------------------------------------------ + +package body Instrument.Ada_Preprocessing is + + ------------------------- + -- Create_Preprocessor -- + ------------------------- + + function Create_Preprocessor + (Filename : String) return File_Reader_Reference + is + pragma Unreferenced (Filename); + begin + return (raise Program_Error); + end Create_Preprocessor; + +end Instrument.Ada_Preprocessing; diff --git a/tools/gnatcov/instrument-ada_preprocessing__stub.ads b/tools/gnatcov/instrument-ada_preprocessing__stub.ads new file mode 100644 index 000000000..4914ae82a --- /dev/null +++ b/tools/gnatcov/instrument-ada_preprocessing__stub.ads @@ -0,0 +1,35 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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. -- +------------------------------------------------------------------------------ + +-- Stub of Instrument.Ada_Preprocessing, to avoid pulling a dependency to +-- libadalang when gnatcov is not built with Ada instrumentation support +-- (basically the gnatcov32 executable that has support for binary traces +-- only). + +package Instrument.Ada_Preprocessing is + + pragma Elaborate_Body; + + type File_Reader_Reference is null record; + + procedure Create_Preprocessor_Data_File (Filename : String) is null; + + function Create_Preprocessor + (Filename : String) return File_Reader_Reference; + +end Instrument.Ada_Preprocessing; From 294e757c886c085281097a424af8536bcb736608 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 18 Dec 2023 12:19:32 +0000 Subject: [PATCH 0612/1483] gnatcov_rts.gpr: tidy up naming clauses Remove duplicate clauses for the Instrument.C unit. --- tools/gnatcov/gnatcov.gpr | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index d8fdb7aa2..70a33acc3 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -99,14 +99,20 @@ project Gnatcov is for Specification ("Qemu_Traces_Entries") use"qemu_traces_entries__" & Bits & ".ads"; - -- Tools that don't need instrumentation support might nevertheless - -- rely on sources that drag dependencies on the "instrument" source - -- unit, even though the instrumentation feature is never actually - -- used. Provide a stub body for such tools, which significantly - -- reduces the size of executables: + -- In order to reduce the size of produced executables, whenever + -- possible, use stubs for units that pull big dependencies into the + -- link closure (Libadalang, Libclang). + -- + -- Removing such a dependency is possible when the associated feature is + -- not used in the selected part: for instance, the gnatcov driver does + -- not perform any source instrumentation itself (it delegates it to + -- gnatcov64), so it does not need to be linked with Libadalang nor + -- Libclang. case Part is - when "lib32" | "lib64" | "driver" | "gnatcov32" => + when "gnatcov64" => + null; + when others => for Specification ("Instrument.Ada_Preprocessing") use "instrument-ada_preprocessing__stub.ads"; for Body ("Instrument.Ada_Preprocessing") @@ -116,11 +122,6 @@ project Gnatcov is use "instrument-ada_unit__stub.ads"; for Body ("Instrument.Ada_Unit") use "instrument-ada_unit__stub.adb"; - - for Specification ("Instrument.C") use "instrument-c__stub.ads"; - for Body ("Instrument.C") use "instrument-c__stub.adb"; - when "gnatcov64" | "compiler" => - null; end case; case C_Support is From 4813b5799f417149d223a9fb1fce0305e50be8eb Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 18 Dec 2023 12:46:56 +0000 Subject: [PATCH 0613/1483] Add a stub for Setup_RTS This stub is used for all gnatcov "parts" except the one that really needs the implementation for this unit: gnatcov64. --- tools/gnatcov/gnatcov.gpr | 4 +- tools/gnatcov/setup_rts__stub.adb | 126 ++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 1 deletion(-) create mode 100644 tools/gnatcov/setup_rts__stub.adb diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 70a33acc3..461e38813 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -101,7 +101,7 @@ project Gnatcov is -- In order to reduce the size of produced executables, whenever -- possible, use stubs for units that pull big dependencies into the - -- link closure (Libadalang, Libclang). + -- link closure (GPR2, Libadalang, Libclang). -- -- Removing such a dependency is possible when the associated feature is -- not used in the selected part: for instance, the gnatcov driver does @@ -122,6 +122,8 @@ project Gnatcov is use "instrument-ada_unit__stub.ads"; for Body ("Instrument.Ada_Unit") use "instrument-ada_unit__stub.adb"; + + for Body ("Setup_RTS") use "setup_rts__stub.adb"; end case; case C_Support is diff --git a/tools/gnatcov/setup_rts__stub.adb b/tools/gnatcov/setup_rts__stub.adb new file mode 100644 index 000000000..69b2d7641 --- /dev/null +++ b/tools/gnatcov/setup_rts__stub.adb @@ -0,0 +1,126 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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. -- +------------------------------------------------------------------------------ + +package body Setup_RTS is + + ----------- + -- Image -- + ----------- + + function Image (Profile : Any_RTS_Profile) return String is + pragma Unreferenced (Profile); + begin + return (raise Program_Error); + end Image; + + ----------- + -- Value -- + ----------- + + function Value (Profile : String) return Any_RTS_Profile is + pragma Unreferenced (Profile); + begin + return (raise Program_Error); + end Value; + + ------------------------- + -- Default_Dump_Config -- + ------------------------- + + function Default_Dump_Config + (RTS_Profile : Resolved_RTS_Profile; RTS : String) return Any_Dump_Config + is + pragma Unreferenced (RTS_Profile, RTS); + begin + return (raise Program_Error); + end Default_Dump_Config; + + --------------------------- + --- Default_Project_File -- + --------------------------- + + function Default_Project_File return String is + begin + return (raise Program_Error); + end Default_Project_File; + + ------------------ + -- Project_Name -- + ------------------ + + function Project_Name (Project_File : String) return String is + pragma Unreferenced (Project_File); + begin + return (raise Program_Error); + end Project_Name; + + ----------- + -- Setup -- + ----------- + + procedure Setup + (Project_File : String; + Target : String; + RTS : String; + Config_File : String; + Prefix : String; + RTS_Profile : Any_RTS_Profile; + Install_Name : String; + Gargs : String_Vectors.Vector) + is + pragma Unreferenced (Project_File); + pragma Unreferenced (Target); + pragma Unreferenced (RTS); + pragma Unreferenced (Config_File); + pragma Unreferenced (Prefix); + pragma Unreferenced (RTS_Profile); + pragma Unreferenced (Install_Name); + pragma Unreferenced (Gargs); + begin + raise Program_Error; + end Setup; + + ---------- + -- Load -- + ---------- + + function Load + (Target : String; + RTS : String; + Config_File : String; + Runtime_Project : String) return Setup_Config + is + pragma Unreferenced (Target, RTS, Config_File, Runtime_Project); + begin + return (raise Program_Error); + end Load; + + ----------------------- + -- Check_RTS_Profile -- + ----------------------- + + function Check_RTS_Profile + (Profile : Resolved_RTS_Profile; + Dump_Config : Any_Dump_Config) return Boolean + is + pragma Unreferenced (Profile, Dump_Config); + begin + return (raise Program_Error); + end Check_RTS_Profile; + +end Setup_RTS; From 09aaf28a5811c9b3cf44a4899274205b68a0efdb Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 18 Dec 2023 15:22:54 +0000 Subject: [PATCH 0614/1483] instrument.adb: fix the coding style --- tools/gnatcov/instrument.adb | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 2b78f087b..eb7c06458 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -484,12 +484,14 @@ package body Instrument is function Load_From_Command_Line return Prj_Desc is use Command_Line.Parser; - Language : constant Some_Language := + Language : constant Some_Language := To_Language (+Args.String_Args (Opt_Lang).Value); - Result : Prj_Desc; + Result : Prj_Desc; procedure Fill_If_Present (Opt : String_Options; Field : out Unbounded_String); + -- If option Opt is present on the command line, copy its valaue to + -- Field. --------------------- -- Fill_If_Present -- @@ -504,6 +506,9 @@ package body Instrument is Field := +Value (Args, Opt); end if; end Fill_If_Present; + + -- Start of processing for Load_From_Command_Line + begin if Language in C_Family_Language then Fill_If_Present From b71b3746ba48cbca4f9f701316299949f61b8329 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 21 Dec 2023 16:17:17 +0000 Subject: [PATCH 0615/1483] gnatcov_bits_specific.adb: minor refactoring --- tools/gnatcov/gnatcov_bits_specific.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index da9b044f8..928b7fae4 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -61,11 +61,11 @@ with Inputs; use Inputs; with Instrument; with Instrument.Common; use Instrument.Common; with Instrument.Config; +with Instrument.Input_Traces; with Instrument.Main; with Instrument.Projects; with Instrument.Setup_Config; with Instrument.Source; -with Instrument.Input_Traces; with Logging; with Object_Locations; with Outputs; use Outputs; From 34f5ee454fb3155dd5f1372e24ff29e8632d62b5 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 21 Dec 2023 20:37:09 +0000 Subject: [PATCH 0616/1483] Introduce the "gcc-wrapper" internal subcommand Move the actual integrated instrumentation implementation to this new subcommand so that the compiler wrapper is just a thin wrapper around gnatcov itself. Thanks to this, the compiler_wrapper-gcc main does not need to pull the C instrumenter anymore: it is faster to compile/link and yields a smaller executable. --- tools/gnatcov/command_line.ads | 22 +- tools/gnatcov/compiler_wrappers-gcc.adb | 1033 +-------------------- tools/gnatcov/gnatcov.gpr | 4 +- tools/gnatcov/gnatcov_bits_specific.adb | 10 + tools/gnatcov/instrument-gcc_wrapper.adb | 1041 ++++++++++++++++++++++ 5 files changed, 1092 insertions(+), 1018 deletions(-) create mode 100644 tools/gnatcov/instrument-gcc_wrapper.adb diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 928ab0902..49cc3b501 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -63,7 +63,8 @@ package Command_Line is Cmd_Instrument_Project, Cmd_Instrument_Source, Cmd_Instrument_Main, - Cmd_Setup_Integration); + Cmd_Setup_Integration, + Cmd_Gcc_Wrapper); -- Set of commands we support. More complete descriptions below. type Bool_Options is @@ -146,6 +147,7 @@ package Command_Line is (Opt_Log, Opt_Projects, Opt_Scenario_Var, + Opt_Cargs, Opt_Eargs, Opt_Gargs, Opt_Scos, @@ -407,7 +409,13 @@ package Command_Line is Pattern => "--files= --compilers=" & " [--output-dir=]", - Internal => False)); + Internal => False), + Cmd_Gcc_Wrapper => Create + (Name => "gcc-wrapper", + Description => + "Implementation of the GCC wrapper for integrated instrumentation.", + Pattern => "[JSON-CONFIG-FILE]", + Internal => True)); Bool_Infos : constant Bool_Option_Info_Array := (Opt_Verbose => Create @@ -1109,7 +1117,8 @@ package Command_Line is Help => "Name of the root project, without its gpr extension.", Commands => - (Cmd_Instrument_Main => True, others => False), + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), At_Most_Once => False, Internal => True), @@ -1159,6 +1168,13 @@ package Command_Line is Help => "Define a scenario variable for project files.", Commands => (Cmd_All_Setups => False, others => True), Internal => False), + Opt_Cargs => Create + (Long_Name => "--cargs", + Pattern => "[CARGS ...]", + Help => "Pass CARGS arguments to the wrapped compiler.", + Commands => (Cmd_Gcc_Wrapper => True, others => False), + Internal => True, + Greedy => True), Opt_Eargs => Create (Long_Name => "-eargs", Pattern => "[EARGS ...]", diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index c5a2ffe2e..94d2b1151 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -16,1035 +16,42 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Command_Line; use Ada.Command_Line; -with Ada.Containers; use Ada.Containers; -with Ada.Containers.Vectors; -with Ada.Directories; use Ada.Directories; -with Ada.Environment_Variables; -with Ada.Strings; use Ada.Strings; -with Ada.Text_IO; use Ada.Text_IO; - -with GNATCOLL.VFS; use GNATCOLL.VFS; +with Ada.Command_Line; use Ada.Command_Line; +with Ada.Directories; use Ada.Directories; with GNAT.OS_Lib; -with Coverage.Tags; use Coverage.Tags; -with Files_Handling; use Files_Handling; -with Files_Table; use Files_Table; -with Instrument; use Instrument; -with Instrument.C; use Instrument.C; -with Instrument.Common; use Instrument.Common; with Instrument.Setup_Config; use Instrument.Setup_Config; -with Instrument.Source; -with Outputs; with Paths; use Paths; with Strings; use Strings; with Subprocesses; use Subprocesses; -with Switches; use Switches; -with Temp_Dirs; use Temp_Dirs; -with Traces_Files; -with Traces_Source; use Traces_Source; procedure Compiler_Wrappers.Gcc is - use all type Unbounded_String; - - type Compilation_Command_Type is record - Language : Any_Language; - -- Language of the file that is compiled - - File : Virtual_File; - -- File that is compiled - - Target : Virtual_File; - -- Output assembly file (passed through the -o switch) - - Instrumentation_Sources : String_Vectors.Vector; - -- List of sources produced by the instrumentation process. It does not - -- include the instrumented version of the source. - - end record; - -- Information relative to a compilation command launched by the compiler - -- driver. - - No_Compilation_Command : constant Compilation_Command_Type := - (Language => All_Languages, - File => No_File, - Target => No_File, - Instrumentation_Sources => String_Vectors.Empty_Vector); - - package Compilation_Command_Vectors is new Ada.Containers.Vectors - (Index_Type => Positive, Element_Type => Compilation_Command_Type); - - type Assembly_Command_Type is record - Filename : Virtual_File; - -- Assembly file (positional argument) - - Target : Virtual_File; - -- Output object file (passed through the -o switch) - - end record; - -- Information relative to an assembly command launched by the compiler - -- driver. - - No_Assembly_Command : constant Assembly_Command_Type := - (Filename => No_File, Target => No_File); - - package Assembly_Command_Vectors is new Ada.Containers.Vectors - (Index_Type => Positive, Element_Type => Assembly_Command_Type); - - type Link_Command_Type is record - Library_Dirs : String_Vectors.Vector; - -- List of library directories arguments (passed through -L switches) - - Libraries : String_Vectors.Vector; - -- List of libraries (passed through -l switches) - - Object_Files : File_Vectors.Vector; - -- List of object files (positional arguments) - - Source_Files : File_Vectors.Vector; - -- When the compiler driver command compiles and links, this contains - -- the list of files that are compiled by the compiler driver command. - - Target : Virtual_File; - -- Output executable file (passed through the -o switch) - - end record; - -- Information relative to a link command launched by the compiler driver - - No_Link_Command : constant Link_Command_Type := - (Library_Dirs => String_Vectors.Empty_Vector, - Libraries => String_Vectors.Empty_Vector, - Object_Files => File_Vectors.Empty_Vector, - Source_Files => File_Vectors.Empty_Vector, - Target => No_File); - - type Compilation_Database is record - Compilation_Commands : Compilation_Command_Vectors.Vector; - -- List of compilation commands launched by this compiler driver - -- invocation. - - Assembly_Commands : Assembly_Command_Vectors.Vector; - -- List of assembly commands launched by this compiler driver invocation - - Link_Command : Link_Command_Type := No_Link_Command; - -- List of link commands launched by this compiler driver invocation - - end record; - -- Track all of the commands launched by a compiler driver invocation - - type Parsing_Context is record - Orig_Compiler_Driver : Unbounded_String; - -- Full path to the original compiler driver - - Source_Mapping : File_To_File_Maps.Map; - -- We rely on object file symbols to know what coverage buffers we - -- should dump at link time. Nevertheless, an object file referenced in - -- a link command (which we get through the -### verbose switch) does - -- not necessarily exist yet: it can be a temporary file created by a - -- previous compilation command that belongs to the same compiler driver - -- invocation (e.g. when compiling and linking at the same time). - -- - -- To support this case, we thus need to keep track of the temporary - -- files created along the compilation process, to know to which source - -- they ultimately refer, and derive the coverage buffer symbol from it. - -- - -- The Source_Mapping thus maps the temporary object files to the - -- original source. - - Instrumentation_Objects : File_To_String_Vectors_Maps.Map; - -- Maps the original source name to the instrumentation artifact objects - -- (e.g. coverage buffers unit, dump helper unit). - - end record; - - function Starts_With - (Str : Unbounded_String; Pattern : String) return Boolean - is (Index (Str, Pattern, 1) = 1); - -- Returns whether the given Str starts with the given Pattern - - function Ends_With - (Str : Unbounded_String; Pattern : String) return Boolean - is (Length (Str) >= Pattern'Length - and then - Index - (Str, Pattern, From => Positive (Length (Str)), Going => Backward) - = - Length (Str) - Pattern'Length + 1); - -- Returns whether the given Str ends with the given Pattern - - function Split_Args (Command : String) return String_Vectors.Vector; - - function Img (Command : String_Vectors.Vector) return String; - - function Parse_Compiler_Driver_Command - (Context : in out Parsing_Context; - Prj : in out Prj_Desc; - Tmp_Dir : Temporary_Directory; - Args : String_Vectors.Vector) return Compilation_Database; - -- Parse a compiler driver command - - function Parse_Compilation_Command - (Context : in out Parsing_Context; - Prj : in out Prj_Desc; - Command : String_Vectors.Vector) return Compilation_Command_Type; - -- Parse a compilation command - - function Parse_Assembly_Command - (Context : in out Parsing_Context; - Command : String_Vectors.Vector) return Assembly_Command_Type; - -- Parse an assembly command - - function Parse_Link_Command - (Context : Parsing_Context; - Command : String_Vectors.Vector) return Link_Command_Type; - -- Parse a link command - - function Coverage_Buffer_Symbols - (Tmp_Dir : String; - Command : Link_Command_Type; - Compiler_Driver : String; - Config : Instrumentation_Config) return String_Sets.Set; - -- Return the list of coverage buffer symbols in the link closure - - procedure Run_Original_Compiler - (Context : Parsing_Context; - Args : String_Vectors.Vector); - -- Run the wrapped compiler with the given Args - - ---------------- - -- Split_Args -- - ---------------- - - function Split_Args (Command : String) return String_Vectors.Vector is - type State_Kind is - (No_Argument, Simple_Argument, Quoted_Argument); - - State : State_Kind := No_Argument; - Arg : Unbounded_String; - Result : String_Vectors.Vector; - - procedure Append_Arg; - - ---------------- - -- Append_Arg -- - ---------------- - - procedure Append_Arg is - begin - if State /= No_Argument then - Result.Append (Arg); - State := No_Argument; - Arg := Null_Unbounded_String; - end if; - end Append_Arg; - - C : Character; - I : Natural := Command'First; - - begin - while I <= Command'Last loop - C := Command (I); - case State is - when No_Argument => - if C = '"' then - State := Quoted_Argument; - elsif C /= ' ' then - State := Simple_Argument; - Append (Arg, C); - end if; - - when Simple_Argument => - if C = ' ' then - Append_Arg; - else - Append (Arg, C); - end if; - - when Quoted_Argument => - if C = '\' then - I := I + 1; - Append (Arg, Command (I)); - elsif C = '"' then - Append_Arg; - else - Append (Arg, C); - end if; - end case; - I := I + 1; - end loop; - Append_Arg; - return Result; - end Split_Args; - - --------- - -- Img -- - --------- - - function Img (Command : String_Vectors.Vector) return String is - Result : Unbounded_String; - begin - for Arg of Command loop - Append (Result, Arg); - Append (Result, " "); - end loop; - return +Result; - end Img; - - ----------------------------------- - -- Parse_Compiler_Driver_Command -- - ----------------------------------- - - function Parse_Compiler_Driver_Command - (Context : in out Parsing_Context; - Prj : in out Prj_Desc; - Tmp_Dir : Temporary_Directory; - Args : String_Vectors.Vector) return Compilation_Database - is - use type String_Vectors.Vector; - Result : Compilation_Database; - Parsed_Link_Command : Boolean := False; - Commands_Filename : constant String := - Tmp_Dir.Directory_Name / "commands"; - begin - -- Expand the command line using gcc's -### option. TODO??? check if the - -- command we are intercepting is a compile / link target and not a - -- preprocessing / -### action. - - Run_Command - (+Context.Orig_Compiler_Driver, - String_Vectors.To_Vector (+"-###", 1) & Args, - "gnatcov", - Output_File => Commands_Filename); - - -- Then, parse the files containing the list of launched commands, using - -- the following heuristics: - -- - -- * If the command is a cc1 invocation (first argument end with cc1), - -- assume compilation command. - -- * If the command is an as invocation, assume assembly command. - -- * If the command is a collect2 invocation, assume link command. - - declare - Commands_File : File_Type; - begin - Open (Commands_File, In_File, Commands_Filename); - while not End_Of_File (Commands_File) loop - declare - Line : constant String := Get_Line (Commands_File); - Command : constant String_Vectors.Vector := Split_Args (Line); - begin - if Line = "" then - goto Continue; - end if; - if Ends_With (Command.First_Element, "cc1") - or else Ends_With (Command.First_Element, "cc1plus") - then - declare - CC_Command : constant Compilation_Command_Type := - Parse_Compilation_Command (Context, Prj, Command); - begin - if CC_Command /= No_Compilation_Command then - Result.Compilation_Commands.Append (CC_Command); - end if; - end; - elsif Ends_With (Command.First_Element, "as") then - declare - As_Command : constant Assembly_Command_Type := - Parse_Assembly_Command (Context, Command); - begin - if As_Command /= No_Assembly_Command then - Result.Assembly_Commands.Append (As_Command); - end if; - end; - elsif Ends_With (Command.First_Element, "collect2") then - - -- Assume that we can only have a single link command. If - -- that's not the case, error out. - - if Parsed_Link_Command then - Outputs.Fatal_Error - ("The compiler driver invocation yielded several link" - & " commands, which is not supported"); - end if; - Result.Link_Command := - (Parse_Link_Command (Context, Command)); - Parsed_Link_Command := True; - end if; - <> - end; - end loop; - end; - return Result; - end Parse_Compiler_Driver_Command; - - ------------------------------- - -- Parse_Compilation_Command -- - ------------------------------- - - function Parse_Compilation_Command - (Context : in out Parsing_Context; - Prj : in out Prj_Desc; - Command : String_Vectors.Vector) return Compilation_Command_Type - is - use String_Vectors; - PP_Args : String_Vectors.Vector; - -- List of arguments that should be passed to the preprocessor - -- invocation: basically all of the arguments except the compiled source - -- and the -o switch. - - Result : Compilation_Command_Type; - Cur : Cursor := First (Command); - begin - if Ends_With (Command.First_Element, "cc1plus") then - Result.Language := CPP_Language; - elsif Ends_With (Command.First_Element, "cc1") then - Result.Language := C_Language; - end if; - - -- Skip the first argument as it is the compiler executable, and not - -- a compiler argument. - - Cur := Next (Cur); - - while Has_Element (Cur) loop - declare - Arg : constant Unbounded_String := - String_Vectors.Element (Cur); - begin - -- Skip switches arguments that look like filenames. Ideally, we - -- would find the positional argument but it is not - -- straightforward. - - if +Arg in "-dumpbase" | "-dumpbase-ext" then - Cur := Next (Cur); - - -- TODO??? the user can configure the file extension and the - -- implementation should be resilient to this. - - elsif Ends_With (Arg, ".c") - or else Ends_With (Arg, ".cc") - or else Ends_With (Arg, ".cpp") - or else Ends_With (Arg, ".cxx") - then - if Result.File = No_File then - Result.File := Create_Normalized (+Arg); - else - Outputs.Warn - ("Found multiple filenames in the compiler invocation: " - & (+Result.File.Base_Name) & " and " & (+Arg) - & ". Keeping the former, which was parsed before."); - end if; - elsif Arg = "-o" then - Cur := Next (Cur); - Result.Target := - Create_Normalized (+String_Vectors.Element (Cur)); - else - PP_Args.Append (Arg); - end if; - end; - Cur := Next (Cur); - end loop; - - if Result.File = No_File or else Result.Target = No_File then - return No_Compilation_Command; - end if; - Prj.Compiler_Driver (Result.Language) := Command.First_Element; - Prj.Compiler_Options_Unit.Insert (Result.File, PP_Args); - Context.Source_Mapping.Include (Result.Target, Result.File); - return Result; - end Parse_Compilation_Command; - - ---------------------------- - -- Parse_Assembly_Command -- - ---------------------------- - - function Parse_Assembly_Command - (Context : in out Parsing_Context; - Command : String_Vectors.Vector) return Assembly_Command_Type - is - Result : Assembly_Command_Type; - begin - for Cur in Command.Iterate loop - declare - Arg : constant Unbounded_String := - String_Vectors.Element (Cur); - begin - if Arg = "-o" then - Result.Target := - Create_Normalized - (+String_Vectors.Element (String_Vectors.Next (Cur))); - elsif Ends_With (Arg, ".s") then - Result.Filename := Create_Normalized (+Arg); - end if; - end; - end loop; - - -- Error out if the parsing failed - - if Result.Filename = No_File then - Outputs.Fatal_Error - ("Could not find assembly file in assembly command: " - & Img (Command)); - elsif Result.Target = No_File then - Outputs.Fatal_Error - ("Could not find output file in assembly command: " - & Img (Command)); - end if; - - -- If we do not find the original source in the mapping, assume that - -- this is not a file of interest. - - if not Context.Source_Mapping.Contains (Result.Filename) then - return No_Assembly_Command; - end if; - - Context.Source_Mapping.Insert - (Result.Target, Context.Source_Mapping.Element (Result.Filename)); - return Result; - end Parse_Assembly_Command; - - ------------------------ - -- Parse_Link_Command -- - ------------------------ - - function Parse_Link_Command - (Context : Parsing_Context; - Command : String_Vectors.Vector) return Link_Command_Type - is - use String_Vectors; - Result : Link_Command_Type; - begin - -- Find the libraries and library directories in the link command - - for Cur in Command.Iterate loop - declare - Arg : constant Unbounded_String := Element (Cur); - begin - if Arg = "-L" then - Result.Library_Dirs.Append (Element (Next (Cur))); - elsif Starts_With (Arg, "-L") then - Result.Library_Dirs.Append - (Unbounded_Slice (Arg, 3, Length (Arg))); - elsif Arg = "-l" then - Result.Libraries.Append (Element (Next (Cur))); - elsif Starts_With (Arg, "-l") then - Result.Libraries.Append - (Unbounded_Slice (Arg, 3, Length (Arg))); - elsif Arg = "-o" then - Result.Target := Create_Normalized (+Element (Next (Cur))); - elsif Ends_With (Arg, ".o") then - declare - Object_File : constant Virtual_File := - Create_Normalized (+Arg); - begin - if Context.Source_Mapping.Contains (Object_File) then - Result.Source_Files.Append - (Context.Source_Mapping.Element (Object_File)); - else - Result.Object_Files.Append (Create_Normalized (+Arg)); - end if; - end; - elsif Ends_With (Arg, ".a") then - Result.Libraries.Append (Arg); - end if; - end; - end loop; - - if Result.Target = No_File then - Result.Target := Create_Normalized ("a.out"); - end if; - - return Result; - end Parse_Link_Command; - - ----------------------------- - -- Coverage_Buffer_Symbols -- - ----------------------------- - - function Coverage_Buffer_Symbols - (Tmp_Dir : String; - Command : Link_Command_Type; - Compiler_Driver : String; - Config : Instrumentation_Config) return String_Sets.Set - is - function Coverage_Buffer_Symbols - (Symbol_File : Virtual_File) return String_Sets.Set; - -- Return the list of coverage buffer symbols in the given symbol file - -- (object or library file). - - ----------------------------- - -- Coverage_Buffer_Symbols -- - ----------------------------- - - function Coverage_Buffer_Symbols - (Symbol_File : Virtual_File) return String_Sets.Set - is - Args : String_Vectors.Vector; - Output_Filename : constant String := - Tmp_Dir / ("nm_" & Filename_Slug (+Symbol_File.Full_Name)); - Output_File : File_Type; - - Result : String_Sets.Set; - Ignore_Success : Boolean; - - begin - -- Use the compiler nm to dump the list of symbols + -- Find the the instrumentation configuration that "setup-integration" + -- generated along with this compiler wrapper in the Prefix directory. - Args.Append (+"--format=just-symbol"); - Args.Append (Full_Name (Symbol_File)); - - -- The command can fail with e.g. "file format not recognized" for - -- system libraries. TODO??? investigate why. We should also avoid - -- invoking nm on system libraries altogether. - - Ignore_Success := - Run_Command - (Command => - +Config.Nms.Element (+Base_Name (Compiler_Driver)), - Arguments => Args, - Origin_Command_Name => "compiler wrapper", - Output_File => Output_Filename, - Ignore_Error => True); - - -- Each line of the output is a symbol - - Open (Output_File, In_File, Output_Filename); - - while not End_Of_File (Output_File) loop - declare - Line_Str : constant String := Get_Line (Output_File); - Line : constant Unbounded_String := +Line_Str; - begin - if Starts_With (Line, "gnatcov_rts_buffers") - - -- The buffer list symbols is also referenced in the link - -- closure: make sure not to pick it as it is named - -- gnatcov_rts_buffers_array_, so - -- gnatcov_rts_buffers_array_main in our case. - - and then Ends_With (Line, "_buffers") - then - Result.Insert (Line); - end if; - end; - end loop; - Close (Output_File); - return Result; - end Coverage_Buffer_Symbols; - - Result : String_Sets.Set; - - begin - -- Search through object files and libraries the list of coverage buffer - -- symbols. - - -- Start by dealing with object files - - for Object_File of Command.Object_Files loop - Result.Union (Coverage_Buffer_Symbols (Object_File)); - end loop; - - -- Then, deal with library files - - declare - Library_Path : Unbounded_String; - begin - for Library_Dir of Command.Library_Dirs loop - Append (Library_Path, Library_Dir); - Append (Library_Path, GNAT.OS_Lib.Path_Separator); - end loop; - Append - (Library_Path, - Ada.Environment_Variables.Value ("LIBRARY_PATH", "")); - - for Library of Command.Libraries loop - if Ends_With (Library, ".a") then - - -- Library filename on the command line, no need to look it up - - Result.Union - (Coverage_Buffer_Symbols (Create_Normalized (+Library))); - else - -- Simple library name passed to the -l option, search the - -- actual file on the library path. - - declare - use type GNAT.OS_Lib.String_Access; - Library_File : GNAT.OS_Lib.String_Access := - GNAT.OS_Lib.Locate_Regular_File - ("lib" & (+Library) & ".a", +Library_Path); - begin - if Library_File /= null then - Result.Union - (Coverage_Buffer_Symbols - (Create_Normalized (Library_File.all))); - GNAT.OS_Lib.Free (Library_File); - end if; - end; - end if; - end loop; - end; - - -- Deal with sources that were compiled _and_ linked by the same driver - -- command. - - for Source of Command.Source_Files loop - if Switches.Files_Of_Interest.Contains (Source) then - declare - Unit : constant Compilation_Unit := - (Language => File_Based_Language, - Unit_Name => Full_Name (Source)); - begin - Result.Insert (+Unit_Buffers_Name (Unit)); - end; - end if; - end loop; - - return Result; - end Coverage_Buffer_Symbols; - - --------------------------- - -- Run_Original_Compiler -- - --------------------------- - - procedure Run_Original_Compiler - (Context : Parsing_Context; - Args : String_Vectors.Vector) is - begin - Run_Command - (Command => +Context.Orig_Compiler_Driver, - Arguments => Args, - Origin_Command_Name => "compiler"); - end Run_Original_Compiler; - - Compiler_Wrapper_Dir : constant String := Containing_Directory + Prefix : constant String := Containing_Directory (GNAT.OS_Lib.Locate_Exec_On_Path (Command_Name).all); - -- Directory that contains the current program - - Instr_Config_File : constant String := - Compiler_Wrapper_Dir / Instrumentation_Config_Filename; - Instr_Config : Instrumentation_Config := - Load_Config (Instr_Config_File); - -- Instrumentation configuration previously generated by the setup step - - Instr_Dir : Temporary_Directory; - -- Directory holding instrumentation artefacts - - Comp_DB : Compilation_Database; - - Prj : Prj_Desc; - -- Artificial project description to pass to the various instrumentation - -- workflows. + Config_Filename : constant String := + Prefix / Instrumentation_Config_Filename; - Buffers_List_Unit : Compilation_Unit; - -- Name of the unit holding the buffer list definitions, if this compiler - -- driver invocation expands to a link command. - - Context : Parsing_Context; - - Compiler_Driver_Opts : String_Vectors.Vector; - -- List of options passed to the compiler driver - - Instrumented_Files : String_Sets.Set; - -- List of instrumented files (files of interest / main files / both) - --- Start of processing for Compiler_Wrappers.GCC + -- Delegate the actual work to the "gnatcov gcc-wrapper" command + Gnatcov_Exec : constant String := + "gnatcov" & GNAT.OS_Lib.Get_Executable_Suffix.all; + Args : String_Vectors.Vector; begin - Create_Temporary_Directory - (Instr_Dir, "gnatcov_instr", Auto_Delete => not Switches.Save_Temps); - - -- Set things that must be set as we don't go through gnatcov_bits_specific - - Tag_Provider := Tag_Providers.Create (Default_Tag_Provider_Name); - Traces_Files.Update_Current_Trace_Kind (Traces_Files.Source_Trace_File); - - Context.Orig_Compiler_Driver := - Instr_Config.Compiler_Drivers.Element - (+Ada.Directories.Simple_Name (Command_Name)); - - -- Load the command line - + Args.Append (+"gcc-wrapper"); + Args.Append (+Config_Filename); + Args.Append (+Command_Name); + Args.Append (+"--cargs"); for I in 1 .. Argument_Count loop - Compiler_Driver_Opts.Append (+Argument (I)); - end loop; - - -- If this driver invocation is not meant to compile a source file, there - -- is no instrumentation to do: just run the original driver and exit. - - for Arg of Compiler_Driver_Opts loop - if +Arg in "-###" | "-E" then - Run_Original_Compiler (Context, Compiler_Driver_Opts); - return; - end if; - end loop; - - -- Parse the compiler driver invocation - - Comp_DB := Parse_Compiler_Driver_Command - (Context, Prj, Instr_Dir, Compiler_Driver_Opts); - - -- Generate an artificial project description to pass compiler switches and - -- default spec / body suffixes. - - Prj.Prj_Name := +"main"; - Prj.Output_Dir := +Instr_Dir.Directory_Name; - Prj.Spec_Suffix := - (C_Language => +".h", CPP_Language => +".hh", others => <>); - Prj.Body_Suffix := - (C_Language => +".c", CPP_Language => +".cc", others => <>); - - -- Then, invoke the right set of gnatcov commands - - -- Start by the compilation command: for each compilation command, we - -- must instrument its source and substitute on the command line the - -- original file with its instrumented version. - - for Cur in Comp_DB.Compilation_Commands.Iterate loop - declare - use Compilation_Command_Vectors; - Comp_Command : constant Compilation_Command_Type := Element (Cur); - Comp_Command_Ref : constant Reference_Type := - Comp_DB.Compilation_Commands.Reference (Cur); - Instrumenter : Language_Instrumenter'Class := - (case Comp_Command.Language is - when C_Language => - Create_C_Instrumenter - (Instr_Config.Tag, Integrated_Instrumentation), - when CPP_Language => - Create_CPP_Instrumenter - (Instr_Config.Tag, Integrated_Instrumentation), - when others => - raise Program_Error - with "Unsupported language for integrated instrumentation"); - - Fullname : constant String := +Comp_Command.File.Full_Name; - Simple_Name : constant String := +Comp_Command.File.Base_Name; - Instr_Name : constant String := (+Prj.Output_Dir) / Simple_Name; - - begin - -- Start by instrumenting the file as a source, if it is a unit of - -- interest. - - if Files_Of_Interest.Contains (Comp_Command.File) then - - -- Pass the compiler switches through the project description - - Instrument.Source - (Instrumenter => Instrumenter, - Files_Of_Interest => Switches.Files_Of_Interest, - Prj => Prj, - Unit_Name => Fullname, - - -- Generate all the SID files under the same directory as the - -- compiler wrapper as they must persist. TODO??? deal with - -- homonym files in SID names. - - SID_Name => Compiler_Wrapper_Dir / (Simple_Name & ".sid")); - - Comp_Command_Ref.Instrumentation_Sources.Append - (Instrumenter.Buffer_Unit - (Compilation_Unit' - (File_Based_Language, Full_Name (Comp_Command.File)), - Prj) - .Unit_Name); - Instrumented_Files.Include (+Fullname); - end if; - - -- Then, instrument it as a main if it is one - - if Instrumenter.Has_Main (Fullname, Prj) then - - -- Pick as the trace name prefix the base name of the main - -- filename - - if Instr_Config.Dump_Config.Channel = Binary_File then - Instr_Config.Dump_Config.Filename_Prefix := - +Ada.Directories.Base_Name (Fullname); - end if; - - Instrumenter.Auto_Dump_Buffers_In_Main - (Instr_Name, Instr_Config.Dump_Config, Prj); - Comp_Command_Ref.Instrumentation_Sources.Append - (Instrumenter.Dump_Helper_Unit - (Compilation_Unit' - (File_Based_Language, +Instr_Name), - Prj) - .Unit_Name); - Instrumented_Files.Include (+Fullname); - end if; - end; + Args.Append (+Argument (I)); end loop; - -- Then, deal with the link command - - if Comp_DB.Link_Command /= No_Link_Command then - declare - Instrumenter : constant Language_Instrumenter'Class := - Create_C_Instrumenter - (Instr_Config.Tag, Integrated_Instrumentation); - -- Emit the buffers list unit as a C compilation unit as it is - -- compilable by a C / C++ compiler, which are the languages - -- supported by the integrated instrumentation scheme. - - Buffer_Symbols : constant String_Sets.Set := - Coverage_Buffer_Symbols - (Tmp_Dir => +Prj.Output_Dir, - Command => Comp_DB.Link_Command, - Compiler_Driver => Command_Name, - Config => Instr_Config); - begin - Buffers_List_Unit := - Instrumenter.Emit_Buffers_List_Unit (Buffer_Symbols, Prj); - end; - end if; - - -- Now that we have all of the instrumentation artifacts, launch the - -- original compiler driver command. - - declare - Output_Dir : constant String := +Prj.Output_Dir; - New_Args : String_Vectors.Vector := Compiler_Driver_Opts; - begin - New_Args.Prepend ("-I" & Instr_Config.GNATcov_RTS_Include_Dir); - - if Comp_DB.Link_Command /= No_Link_Command then - New_Args.Append (+"-lgnatcov_rts"); - New_Args.Prepend ("-L" & Instr_Config.GNATcov_RTS_Object_Dir); - end if; - - -- Start with adding the buffer list unit (if it was emitted) to the - -- compilation closure. - - if Length (Buffers_List_Unit.Unit_Name) /= 0 then - New_Args.Prepend (Buffers_List_Unit.Unit_Name); - end if; - - -- Then, substitute files of interest with their instrumented version, - -- which were generated in Prj.Output_Dir. - - for I in 0 .. Natural (String_Vectors.Length (New_Args) - 1) loop - declare - Arg : constant Unbounded_String := New_Args.Element (I); - begin - if Ada.Directories.Exists (+Arg) then - declare - Base : constant String := Simple_Name (+Arg); - Fullname : constant String := Full_Name (+Arg); - begin - if Instrumented_Files.Contains (+Fullname) then - New_Args.Replace_Element (I, +(Output_Dir / Base)); - end if; - end; - end if; - end; - end loop; - - -- Deal with the instrumentation artifacts - - for Cur in Comp_DB.Compilation_Commands.Iterate loop - declare - use Compilation_Command_Vectors; - Comp_Command : constant Compilation_Command_Type := Element (Cur); - begin - -- If this is a link command, add the instrumentation artifacts - -- to the compiler driver command - - if Comp_DB.Link_Command /= No_Link_Command then - for Instr_Artifact of Comp_Command.Instrumentation_Sources loop - New_Args.Prepend (Instr_Artifact); - end loop; - - -- Otherwise, compile the instrumentation artifacts and package - -- them later with the instrumented source object file once we - -- assemble it. - - else - Context.Instrumentation_Objects.Insert - (Comp_Command.File, String_Vectors.Empty); - - for Instr_Artifact of Comp_Command.Instrumentation_Sources loop - declare - Args_Compilation : String_Vectors.Vector; - Instr_Artifact_Object_Name : constant String := - New_File - (Prj, - Ada.Directories.Base_Name (+Instr_Artifact) & ".o"); - begin - Args_Compilation.Append (+"-c"); - Args_Compilation.Append - ("-I" & Instr_Config.GNATcov_RTS_Include_Dir); - Args_Compilation.Append (Instr_Artifact); - Args_Compilation.Append (+"-o"); - Args_Compilation.Append (+Instr_Artifact_Object_Name); - Run_Original_Compiler (Context, Args_Compilation); - - Context.Instrumentation_Objects - .Reference (Comp_Command.File) - .Append (+Instr_Artifact_Object_Name); - end; - end loop; - end if; - end; - end loop; - - -- Finally, run the alternate compiler driver invocation - - Run_Original_Compiler (Context, New_Args); - - if Comp_DB.Link_Command = No_Link_Command then - - -- Merge coverage buffer object files with instrumented files for - -- each assembly command. - - for Assembly_Command of Comp_DB.Assembly_Commands loop - if Context.Source_Mapping.Contains (Assembly_Command.Filename) then - declare - Orig_Source : constant Virtual_File := - Context.Source_Mapping.Element (Assembly_Command.Filename); - Instr_Objects : constant String_Vectors.Vector := - Context.Instrumentation_Objects.Element (Orig_Source); - Packaged_Name : constant String := - New_File - (Prj, - "instr_" & Filename_Slug (+Orig_Source.Full_Name) - & ".a"); - Success : Boolean; - begin - if not Instr_Objects.Is_Empty then - declare - Args_Ld : String_Vectors.Vector; - begin - Args_Ld.Append (+"-r"); - Args_Ld.Append_Vector (Instr_Objects); - Args_Ld.Append (Full_Name (Assembly_Command.Target)); - Args_Ld.Append (+"-o"); - Args_Ld.Append (+Packaged_Name); - Run_Command - (Command => - +Instr_Config.Linkers.Element - (+Base_Name (Command_Name)), - Arguments => Args_Ld, - Origin_Command_Name => "compiler wrapper"); - - -- Finally, replace the original object file with the - -- newly created library file, packaging both the - -- instrumented source and its coverage buffer. - - GNAT.OS_Lib.Copy_File - (Packaged_Name, - +Assembly_Command.Target.Full_Name, - Success, - Mode => GNAT.OS_Lib.Overwrite, - Preserve => GNAT.OS_Lib.Full); - end; - end if; - end; - end if; - end loop; - end if; - end; - + Run_Command + (Command => Gnatcov_Exec, + Arguments => Args, + Origin_Command_Name => "gnatcov gcc-wrapper"); end Compiler_Wrappers.Gcc; diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 461e38813..1121eecfa 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -61,8 +61,8 @@ project Gnatcov is -- "gnatcov64" configuration. case Part is - when "gnatcov64" | "compiler" => null; - when others => C_Support := "False"; + when "gnatcov64" => null; + when others => C_Support := "False"; end case; type Build_Mode_Type is ("dev", "prod", "boot"); diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 928b7fae4..4a05c8914 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -61,6 +61,7 @@ with Inputs; use Inputs; with Instrument; with Instrument.Common; use Instrument.Common; with Instrument.Config; +with Instrument.Gcc_Wrapper; with Instrument.Input_Traces; with Instrument.Main; with Instrument.Projects; @@ -1397,6 +1398,15 @@ begin Output_Dir => Get_Output_Dir); end; + when Cmd_Gcc_Wrapper => + if Args.Remaining_Args.Length /= 2 then + Fatal_Error ("exactly two positional arguments expected"); + end if; + Instrument.Gcc_Wrapper + (Config_File => +Args.Remaining_Args.Element (0), + Compiler_Exec => +Args.Remaining_Args.Element (1), + Cargs => Args.String_List_Args (Opt_Cargs)); + when Cmd_Instrument_Source => -- For the instrument-source command, and for the instrument-main, diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb new file mode 100644 index 000000000..95ac49818 --- /dev/null +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -0,0 +1,1041 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023, 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; use Ada.Containers; +with Ada.Containers.Vectors; +with Ada.Directories; use Ada.Directories; +with Ada.Environment_Variables; +with Ada.Strings; use Ada.Strings; +with Ada.Text_IO; use Ada.Text_IO; + +with GNATCOLL.VFS; use GNATCOLL.VFS; + +with GNAT.OS_Lib; + +with Coverage.Tags; use Coverage.Tags; +with Files_Handling; use Files_Handling; +with Files_Table; use Files_Table; +with Instrument.C; use Instrument.C; +with Instrument.Common; use Instrument.Common; +with Instrument.Setup_Config; use Instrument.Setup_Config; +with Instrument.Source; +with Outputs; +with Paths; use Paths; +with Strings; use Strings; +with Subprocesses; use Subprocesses; +with Switches; use Switches; +with Temp_Dirs; use Temp_Dirs; +with Traces_Files; +with Traces_Source; use Traces_Source; + +-- Implementation for the "gcc-wrapper" command + +procedure Instrument.Gcc_Wrapper + (Config_File : String; + Compiler_Exec : String; + Cargs : String_Vectors.Vector) +is + Compiler_Exec_Basename : constant Unbounded_String := + +Simple_Name (Compiler_Exec); + + type Compilation_Command_Type is record + Language : Any_Language; + -- Language of the file that is compiled + + File : Virtual_File; + -- File that is compiled + + Target : Virtual_File; + -- Output assembly file (passed through the -o switch) + + Instrumentation_Sources : String_Vectors.Vector; + -- List of sources produced by the instrumentation process. It does not + -- include the instrumented version of the source. + + end record; + -- Information relative to a compilation command launched by the compiler + -- driver. + + No_Compilation_Command : constant Compilation_Command_Type := + (Language => All_Languages, + File => No_File, + Target => No_File, + Instrumentation_Sources => String_Vectors.Empty_Vector); + + package Compilation_Command_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, Element_Type => Compilation_Command_Type); + + type Assembly_Command_Type is record + Filename : Virtual_File; + -- Assembly file (positional argument) + + Target : Virtual_File; + -- Output object file (passed through the -o switch) + + end record; + -- Information relative to an assembly command launched by the compiler + -- driver. + + No_Assembly_Command : constant Assembly_Command_Type := + (Filename => No_File, Target => No_File); + + package Assembly_Command_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, Element_Type => Assembly_Command_Type); + + type Link_Command_Type is record + Library_Dirs : String_Vectors.Vector; + -- List of library directories arguments (passed through -L switches) + + Libraries : String_Vectors.Vector; + -- List of libraries (passed through -l switches) + + Object_Files : File_Vectors.Vector; + -- List of object files (positional arguments) + + Source_Files : File_Vectors.Vector; + -- When the compiler driver command compiles and links, this contains + -- the list of files that are compiled by the compiler driver command. + + Target : Virtual_File; + -- Output executable file (passed through the -o switch) + + end record; + -- Information relative to a link command launched by the compiler driver + + No_Link_Command : constant Link_Command_Type := + (Library_Dirs => String_Vectors.Empty_Vector, + Libraries => String_Vectors.Empty_Vector, + Object_Files => File_Vectors.Empty_Vector, + Source_Files => File_Vectors.Empty_Vector, + Target => No_File); + + type Compilation_Database is record + Compilation_Commands : Compilation_Command_Vectors.Vector; + -- List of compilation commands launched by this compiler driver + -- invocation. + + Assembly_Commands : Assembly_Command_Vectors.Vector; + -- List of assembly commands launched by this compiler driver invocation + + Link_Command : Link_Command_Type := No_Link_Command; + -- List of link commands launched by this compiler driver invocation + + end record; + -- Track all of the commands launched by a compiler driver invocation + + type Parsing_Context is record + Orig_Compiler_Driver : Unbounded_String; + -- Full path to the original compiler driver + + Source_Mapping : File_To_File_Maps.Map; + -- We rely on object file symbols to know what coverage buffers we + -- should dump at link time. Nevertheless, an object file referenced in + -- a link command (which we get through the -### verbose switch) does + -- not necessarily exist yet: it can be a temporary file created by a + -- previous compilation command that belongs to the same compiler driver + -- invocation (e.g. when compiling and linking at the same time). + -- + -- To support this case, we thus need to keep track of the temporary + -- files created along the compilation process, to know to which source + -- they ultimately refer, and derive the coverage buffer symbol from it. + -- + -- The Source_Mapping thus maps the temporary object files to the + -- original source. + + Instrumentation_Objects : File_To_String_Vectors_Maps.Map; + -- Maps the original source name to the instrumentation artifact objects + -- (e.g. coverage buffers unit, dump helper unit). + + end record; + + function Starts_With + (Str : Unbounded_String; Pattern : String) return Boolean + is (Index (Str, Pattern, 1) = 1); + -- Returns whether the given Str starts with the given Pattern + + function Ends_With + (Str : Unbounded_String; Pattern : String) return Boolean + is (Length (Str) >= Pattern'Length + and then + Index + (Str, Pattern, From => Positive (Length (Str)), Going => Backward) + = + Length (Str) - Pattern'Length + 1); + -- Returns whether the given Str ends with the given Pattern + + function Split_Args (Command : String) return String_Vectors.Vector; + + function Img (Command : String_Vectors.Vector) return String; + + function Parse_Compiler_Driver_Command + (Context : in out Parsing_Context; + Prj : in out Prj_Desc; + Tmp_Dir : Temporary_Directory; + Args : String_Vectors.Vector) return Compilation_Database; + -- Parse a compiler driver command + + function Parse_Compilation_Command + (Context : in out Parsing_Context; + Prj : in out Prj_Desc; + Command : String_Vectors.Vector) return Compilation_Command_Type; + -- Parse a compilation command + + function Parse_Assembly_Command + (Context : in out Parsing_Context; + Command : String_Vectors.Vector) return Assembly_Command_Type; + -- Parse an assembly command + + function Parse_Link_Command + (Context : Parsing_Context; + Command : String_Vectors.Vector) return Link_Command_Type; + -- Parse a link command + + function Coverage_Buffer_Symbols + (Tmp_Dir : String; + Command : Link_Command_Type; + Compiler_Driver : String; + Config : Instrumentation_Config) return String_Sets.Set; + -- Return the list of coverage buffer symbols in the link closure + + procedure Run_Original_Compiler + (Context : Parsing_Context; + Args : String_Vectors.Vector); + -- Run the wrapped compiler with the given Args + + ---------------- + -- Split_Args -- + ---------------- + + function Split_Args (Command : String) return String_Vectors.Vector is + type State_Kind is + (No_Argument, Simple_Argument, Quoted_Argument); + + State : State_Kind := No_Argument; + Arg : Unbounded_String; + Result : String_Vectors.Vector; + + procedure Append_Arg; + + ---------------- + -- Append_Arg -- + ---------------- + + procedure Append_Arg is + begin + if State /= No_Argument then + Result.Append (Arg); + State := No_Argument; + Arg := Null_Unbounded_String; + end if; + end Append_Arg; + + C : Character; + I : Natural := Command'First; + + begin + while I <= Command'Last loop + C := Command (I); + case State is + when No_Argument => + if C = '"' then + State := Quoted_Argument; + elsif C /= ' ' then + State := Simple_Argument; + Append (Arg, C); + end if; + + when Simple_Argument => + if C = ' ' then + Append_Arg; + else + Append (Arg, C); + end if; + + when Quoted_Argument => + if C = '\' then + I := I + 1; + Append (Arg, Command (I)); + elsif C = '"' then + Append_Arg; + else + Append (Arg, C); + end if; + end case; + I := I + 1; + end loop; + Append_Arg; + return Result; + end Split_Args; + + --------- + -- Img -- + --------- + + function Img (Command : String_Vectors.Vector) return String is + Result : Unbounded_String; + begin + for Arg of Command loop + Append (Result, Arg); + Append (Result, " "); + end loop; + return +Result; + end Img; + + ----------------------------------- + -- Parse_Compiler_Driver_Command -- + ----------------------------------- + + function Parse_Compiler_Driver_Command + (Context : in out Parsing_Context; + Prj : in out Prj_Desc; + Tmp_Dir : Temporary_Directory; + Args : String_Vectors.Vector) return Compilation_Database + is + use type String_Vectors.Vector; + Result : Compilation_Database; + Parsed_Link_Command : Boolean := False; + Commands_Filename : constant String := + Tmp_Dir.Directory_Name / "commands"; + begin + -- Expand the command line using gcc's -### option. TODO??? check if the + -- command we are intercepting is a compile / link target and not a + -- preprocessing / -### action. + + Run_Command + (+Context.Orig_Compiler_Driver, + String_Vectors.To_Vector (+"-###", 1) & Args, + "gnatcov", + Output_File => Commands_Filename); + + -- Then, parse the files containing the list of launched commands, using + -- the following heuristics: + -- + -- * If the command is a cc1 invocation (first argument end with cc1), + -- assume compilation command. + -- * If the command is an as invocation, assume assembly command. + -- * If the command is a collect2 invocation, assume link command. + + declare + Commands_File : File_Type; + begin + Open (Commands_File, In_File, Commands_Filename); + while not End_Of_File (Commands_File) loop + declare + Line : constant String := Get_Line (Commands_File); + Command : constant String_Vectors.Vector := Split_Args (Line); + begin + if Line = "" then + goto Continue; + end if; + if Ends_With (Command.First_Element, "cc1") + or else Ends_With (Command.First_Element, "cc1plus") + then + declare + CC_Command : constant Compilation_Command_Type := + Parse_Compilation_Command (Context, Prj, Command); + begin + if CC_Command /= No_Compilation_Command then + Result.Compilation_Commands.Append (CC_Command); + end if; + end; + elsif Ends_With (Command.First_Element, "as") then + declare + As_Command : constant Assembly_Command_Type := + Parse_Assembly_Command (Context, Command); + begin + if As_Command /= No_Assembly_Command then + Result.Assembly_Commands.Append (As_Command); + end if; + end; + elsif Ends_With (Command.First_Element, "collect2") then + + -- Assume that we can only have a single link command. If + -- that's not the case, error out. + + if Parsed_Link_Command then + Outputs.Fatal_Error + ("The compiler driver invocation yielded several link" + & " commands, which is not supported"); + end if; + Result.Link_Command := + (Parse_Link_Command (Context, Command)); + Parsed_Link_Command := True; + end if; + <> + end; + end loop; + end; + return Result; + end Parse_Compiler_Driver_Command; + + ------------------------------- + -- Parse_Compilation_Command -- + ------------------------------- + + function Parse_Compilation_Command + (Context : in out Parsing_Context; + Prj : in out Prj_Desc; + Command : String_Vectors.Vector) return Compilation_Command_Type + is + use String_Vectors; + PP_Args : String_Vectors.Vector; + -- List of arguments that should be passed to the preprocessor + -- invocation: basically all of the arguments except the compiled source + -- and the -o switch. + + Result : Compilation_Command_Type; + Cur : Cursor := First (Command); + begin + if Ends_With (Command.First_Element, "cc1plus") then + Result.Language := CPP_Language; + elsif Ends_With (Command.First_Element, "cc1") then + Result.Language := C_Language; + end if; + + -- Skip the first argument as it is the compiler executable, and not + -- a compiler argument. + + Cur := Next (Cur); + + while Has_Element (Cur) loop + declare + Arg : constant Unbounded_String := + String_Vectors.Element (Cur); + begin + -- Skip switches arguments that look like filenames. Ideally, we + -- would find the positional argument but it is not + -- straightforward. + + if +Arg in "-dumpbase" | "-dumpbase-ext" then + Cur := Next (Cur); + + -- TODO??? the user can configure the file extension and the + -- implementation should be resilient to this. + + elsif Ends_With (Arg, ".c") + or else Ends_With (Arg, ".cc") + or else Ends_With (Arg, ".cpp") + or else Ends_With (Arg, ".cxx") + then + if Result.File = No_File then + Result.File := Create_Normalized (+Arg); + else + Outputs.Warn + ("Found multiple filenames in the compiler invocation: " + & (+Result.File.Base_Name) & " and " & (+Arg) + & ". Keeping the former, which was parsed before."); + end if; + elsif Arg = "-o" then + Cur := Next (Cur); + Result.Target := + Create_Normalized (+String_Vectors.Element (Cur)); + else + PP_Args.Append (Arg); + end if; + end; + Cur := Next (Cur); + end loop; + + if Result.File = No_File or else Result.Target = No_File then + return No_Compilation_Command; + end if; + Prj.Compiler_Driver (Result.Language) := Command.First_Element; + Prj.Compiler_Options_Unit.Insert (Result.File, PP_Args); + Context.Source_Mapping.Include (Result.Target, Result.File); + return Result; + end Parse_Compilation_Command; + + ---------------------------- + -- Parse_Assembly_Command -- + ---------------------------- + + function Parse_Assembly_Command + (Context : in out Parsing_Context; + Command : String_Vectors.Vector) return Assembly_Command_Type + is + Result : Assembly_Command_Type; + begin + for Cur in Command.Iterate loop + declare + Arg : constant Unbounded_String := + String_Vectors.Element (Cur); + begin + if Arg = "-o" then + Result.Target := + Create_Normalized + (+String_Vectors.Element (String_Vectors.Next (Cur))); + elsif Ends_With (Arg, ".s") then + Result.Filename := Create_Normalized (+Arg); + end if; + end; + end loop; + + -- Error out if the parsing failed + + if Result.Filename = No_File then + Outputs.Fatal_Error + ("Could not find assembly file in assembly command: " + & Img (Command)); + elsif Result.Target = No_File then + Outputs.Fatal_Error + ("Could not find output file in assembly command: " + & Img (Command)); + end if; + + -- If we do not find the original source in the mapping, assume that + -- this is not a file of interest. + + if not Context.Source_Mapping.Contains (Result.Filename) then + return No_Assembly_Command; + end if; + + Context.Source_Mapping.Insert + (Result.Target, Context.Source_Mapping.Element (Result.Filename)); + return Result; + end Parse_Assembly_Command; + + ------------------------ + -- Parse_Link_Command -- + ------------------------ + + function Parse_Link_Command + (Context : Parsing_Context; + Command : String_Vectors.Vector) return Link_Command_Type + is + use String_Vectors; + Result : Link_Command_Type; + begin + -- Find the libraries and library directories in the link command + + for Cur in Command.Iterate loop + declare + Arg : constant Unbounded_String := Element (Cur); + begin + if Arg = "-L" then + Result.Library_Dirs.Append (Element (Next (Cur))); + elsif Starts_With (Arg, "-L") then + Result.Library_Dirs.Append + (Unbounded_Slice (Arg, 3, Length (Arg))); + elsif Arg = "-l" then + Result.Libraries.Append (Element (Next (Cur))); + elsif Starts_With (Arg, "-l") then + Result.Libraries.Append + (Unbounded_Slice (Arg, 3, Length (Arg))); + elsif Arg = "-o" then + Result.Target := Create_Normalized (+Element (Next (Cur))); + elsif Ends_With (Arg, ".o") then + declare + Object_File : constant Virtual_File := + Create_Normalized (+Arg); + begin + if Context.Source_Mapping.Contains (Object_File) then + Result.Source_Files.Append + (Context.Source_Mapping.Element (Object_File)); + else + Result.Object_Files.Append (Create_Normalized (+Arg)); + end if; + end; + elsif Ends_With (Arg, ".a") then + Result.Libraries.Append (Arg); + end if; + end; + end loop; + + if Result.Target = No_File then + Result.Target := Create_Normalized ("a.out"); + end if; + + return Result; + end Parse_Link_Command; + + ----------------------------- + -- Coverage_Buffer_Symbols -- + ----------------------------- + + function Coverage_Buffer_Symbols + (Tmp_Dir : String; + Command : Link_Command_Type; + Compiler_Driver : String; + Config : Instrumentation_Config) return String_Sets.Set + is + function Coverage_Buffer_Symbols + (Symbol_File : Virtual_File) return String_Sets.Set; + -- Return the list of coverage buffer symbols in the given symbol file + -- (object or library file). + + ----------------------------- + -- Coverage_Buffer_Symbols -- + ----------------------------- + + function Coverage_Buffer_Symbols + (Symbol_File : Virtual_File) return String_Sets.Set + is + Args : String_Vectors.Vector; + Output_Filename : constant String := + Tmp_Dir / ("nm_" & Filename_Slug (+Symbol_File.Full_Name)); + Output_File : File_Type; + + Result : String_Sets.Set; + Ignore_Success : Boolean; + + begin + -- Use the compiler nm to dump the list of symbols + + Args.Append (+"--format=just-symbol"); + Args.Append (Full_Name (Symbol_File)); + + -- The command can fail with e.g. "file format not recognized" for + -- system libraries. TODO??? investigate why. We should also avoid + -- invoking nm on system libraries altogether. + + Ignore_Success := + Run_Command + (Command => + +Config.Nms.Element (+Base_Name (Compiler_Driver)), + Arguments => Args, + Origin_Command_Name => "compiler wrapper", + Output_File => Output_Filename, + Ignore_Error => True); + + -- Each line of the output is a symbol + + Open (Output_File, In_File, Output_Filename); + + while not End_Of_File (Output_File) loop + declare + Line_Str : constant String := Get_Line (Output_File); + Line : constant Unbounded_String := +Line_Str; + begin + if Starts_With (Line, "gnatcov_rts_buffers") + + -- The buffer list symbols is also referenced in the link + -- closure: make sure not to pick it as it is named + -- gnatcov_rts_buffers_array_, so + -- gnatcov_rts_buffers_array_main in our case. + + and then Ends_With (Line, "_buffers") + then + Result.Insert (Line); + end if; + end; + end loop; + Close (Output_File); + return Result; + end Coverage_Buffer_Symbols; + + Result : String_Sets.Set; + + begin + -- Search through object files and libraries the list of coverage buffer + -- symbols. + + -- Start by dealing with object files + + for Object_File of Command.Object_Files loop + Result.Union (Coverage_Buffer_Symbols (Object_File)); + end loop; + + -- Then, deal with library files + + declare + Library_Path : Unbounded_String; + begin + for Library_Dir of Command.Library_Dirs loop + Append (Library_Path, Library_Dir); + Append (Library_Path, GNAT.OS_Lib.Path_Separator); + end loop; + Append + (Library_Path, + Ada.Environment_Variables.Value ("LIBRARY_PATH", "")); + + for Library of Command.Libraries loop + if Ends_With (Library, ".a") then + + -- Library filename on the command line, no need to look it up + + Result.Union + (Coverage_Buffer_Symbols (Create_Normalized (+Library))); + else + -- Simple library name passed to the -l option, search the + -- actual file on the library path. + + declare + use type GNAT.OS_Lib.String_Access; + Library_File : GNAT.OS_Lib.String_Access := + GNAT.OS_Lib.Locate_Regular_File + ("lib" & (+Library) & ".a", +Library_Path); + begin + if Library_File /= null then + Result.Union + (Coverage_Buffer_Symbols + (Create_Normalized (Library_File.all))); + GNAT.OS_Lib.Free (Library_File); + end if; + end; + end if; + end loop; + end; + + -- Deal with sources that were compiled _and_ linked by the same driver + -- command. + + for Source of Command.Source_Files loop + if Switches.Files_Of_Interest.Contains (Source) then + declare + Unit : constant Compilation_Unit := + (Language => File_Based_Language, + Unit_Name => Full_Name (Source)); + begin + Result.Insert (+Unit_Buffers_Name (Unit)); + end; + end if; + end loop; + + return Result; + end Coverage_Buffer_Symbols; + + --------------------------- + -- Run_Original_Compiler -- + --------------------------- + + procedure Run_Original_Compiler + (Context : Parsing_Context; + Args : String_Vectors.Vector) is + begin + Run_Command + (Command => +Context.Orig_Compiler_Driver, + Arguments => Args, + Origin_Command_Name => "compiler"); + end Run_Original_Compiler; + + Compiler_Wrapper_Dir : constant String := + Containing_Directory (Config_File); + -- Directory that contains the current program + + Instr_Config : Instrumentation_Config := + Load_Config (Config_File); + -- Instrumentation configuration previously generated by the setup step + + Instr_Dir : Temporary_Directory; + -- Directory holding instrumentation artefacts + + Comp_DB : Compilation_Database; + + Prj : Prj_Desc; + -- Artificial project description to pass to the various instrumentation + -- workflows. + + Buffers_List_Unit : Compilation_Unit; + -- Name of the unit holding the buffer list definitions, if this compiler + -- driver invocation expands to a link command. + + Context : Parsing_Context; + + Instrumented_Files : String_Sets.Set; + -- List of instrumented files (files of interest / main files / both) + +-- Start of processing for Compiler_Wrappers.GCC + +begin + Create_Temporary_Directory + (Instr_Dir, "gnatcov_instr", Auto_Delete => not Switches.Save_Temps); + + -- Set things that must be set as we don't go through gnatcov_bits_specific + + Tag_Provider := Tag_Providers.Create (Default_Tag_Provider_Name); + Traces_Files.Update_Current_Trace_Kind (Traces_Files.Source_Trace_File); + + Context.Orig_Compiler_Driver := + Instr_Config.Compiler_Drivers.Element (Compiler_Exec_Basename); + + -- If this driver invocation is not meant to compile a source file, there + -- is no instrumentation to do: just run the original driver and exit. + + for Arg of Cargs loop + if +Arg in "-###" | "-E" then + Run_Original_Compiler (Context, Cargs); + return; + end if; + end loop; + + -- Parse the compiler driver invocation + + Comp_DB := Parse_Compiler_Driver_Command (Context, Prj, Instr_Dir, Cargs); + + -- Generate an artificial project description to pass compiler switches and + -- default spec / body suffixes. + + Prj.Prj_Name := +"main"; + Prj.Output_Dir := +Instr_Dir.Directory_Name; + Prj.Spec_Suffix := + (C_Language => +".h", CPP_Language => +".hh", others => <>); + Prj.Body_Suffix := + (C_Language => +".c", CPP_Language => +".cc", others => <>); + + -- Then, invoke the right set of gnatcov commands + + -- Start by the compilation command: for each compilation command, we + -- must instrument its source and substitute on the command line the + -- original file with its instrumented version. + + for Cur in Comp_DB.Compilation_Commands.Iterate loop + declare + use Compilation_Command_Vectors; + Comp_Command : constant Compilation_Command_Type := Element (Cur); + Comp_Command_Ref : constant Reference_Type := + Comp_DB.Compilation_Commands.Reference (Cur); + Instrumenter : Language_Instrumenter'Class := + (case Comp_Command.Language is + when C_Language => + Create_C_Instrumenter + (Instr_Config.Tag, Integrated_Instrumentation), + when CPP_Language => + Create_CPP_Instrumenter + (Instr_Config.Tag, Integrated_Instrumentation), + when others => + raise Program_Error + with "Unsupported language for integrated instrumentation"); + + Fullname : constant String := +Comp_Command.File.Full_Name; + Simple_Name : constant String := +Comp_Command.File.Base_Name; + Instr_Name : constant String := (+Prj.Output_Dir) / Simple_Name; + + begin + -- Start by instrumenting the file as a source, if it is a unit of + -- interest. + + if Files_Of_Interest.Contains (Comp_Command.File) then + + -- Pass the compiler switches through the project description + + Instrument.Source + (Instrumenter => Instrumenter, + Files_Of_Interest => Switches.Files_Of_Interest, + Prj => Prj, + Unit_Name => Fullname, + + -- Generate all the SID files under the same directory as the + -- compiler wrapper as they must persist. TODO??? deal with + -- homonym files in SID names. + + SID_Name => Compiler_Wrapper_Dir / (Simple_Name & ".sid")); + + Comp_Command_Ref.Instrumentation_Sources.Append + (Instrumenter.Buffer_Unit + (Compilation_Unit' + (File_Based_Language, Full_Name (Comp_Command.File)), + Prj) + .Unit_Name); + Instrumented_Files.Include (+Fullname); + end if; + + -- Then, instrument it as a main if it is one + + if Instrumenter.Has_Main (Fullname, Prj) then + + -- Pick as the trace name prefix the base name of the main + -- filename + + if Instr_Config.Dump_Config.Channel = Binary_File then + Instr_Config.Dump_Config.Filename_Prefix := + +Ada.Directories.Base_Name (Fullname); + end if; + + Instrumenter.Auto_Dump_Buffers_In_Main + (Instr_Name, Instr_Config.Dump_Config, Prj); + Comp_Command_Ref.Instrumentation_Sources.Append + (Instrumenter.Dump_Helper_Unit + (Compilation_Unit' + (File_Based_Language, +Instr_Name), + Prj) + .Unit_Name); + Instrumented_Files.Include (+Fullname); + end if; + end; + end loop; + + -- Then, deal with the link command + + if Comp_DB.Link_Command /= No_Link_Command then + declare + Instrumenter : constant Language_Instrumenter'Class := + Create_C_Instrumenter + (Instr_Config.Tag, Integrated_Instrumentation); + -- Emit the buffers list unit as a C compilation unit as it is + -- compilable by a C / C++ compiler, which are the languages + -- supported by the integrated instrumentation scheme. + + Buffer_Symbols : constant String_Sets.Set := + Coverage_Buffer_Symbols + (Tmp_Dir => +Prj.Output_Dir, + Command => Comp_DB.Link_Command, + Compiler_Driver => Compiler_Exec, + Config => Instr_Config); + begin + Buffers_List_Unit := + Instrumenter.Emit_Buffers_List_Unit (Buffer_Symbols, Prj); + end; + end if; + + -- Now that we have all of the instrumentation artifacts, launch the + -- original compiler driver command. + + declare + Output_Dir : constant String := +Prj.Output_Dir; + New_Args : String_Vectors.Vector := Cargs; + begin + New_Args.Prepend ("-I" & Instr_Config.GNATcov_RTS_Include_Dir); + + if Comp_DB.Link_Command /= No_Link_Command then + New_Args.Append (+"-lgnatcov_rts"); + New_Args.Prepend ("-L" & Instr_Config.GNATcov_RTS_Object_Dir); + end if; + + -- Start with adding the buffer list unit (if it was emitted) to the + -- compilation closure. + + if Length (Buffers_List_Unit.Unit_Name) /= 0 then + New_Args.Prepend (Buffers_List_Unit.Unit_Name); + end if; + + -- Then, substitute files of interest with their instrumented version, + -- which were generated in Prj.Output_Dir. + + for I in 0 .. Natural (String_Vectors.Length (New_Args) - 1) loop + declare + Arg : constant Unbounded_String := New_Args.Element (I); + begin + if Ada.Directories.Exists (+Arg) then + declare + Base : constant String := Simple_Name (+Arg); + Fullname : constant String := Full_Name (+Arg); + begin + if Instrumented_Files.Contains (+Fullname) then + New_Args.Replace_Element (I, +(Output_Dir / Base)); + end if; + end; + end if; + end; + end loop; + + -- Deal with the instrumentation artifacts + + for Cur in Comp_DB.Compilation_Commands.Iterate loop + declare + use Compilation_Command_Vectors; + Comp_Command : constant Compilation_Command_Type := Element (Cur); + begin + -- If this is a link command, add the instrumentation artifacts + -- to the compiler driver command + + if Comp_DB.Link_Command /= No_Link_Command then + for Instr_Artifact of Comp_Command.Instrumentation_Sources loop + New_Args.Prepend (Instr_Artifact); + end loop; + + -- Otherwise, compile the instrumentation artifacts and package + -- them later with the instrumented source object file once we + -- assemble it. + + else + Context.Instrumentation_Objects.Insert + (Comp_Command.File, String_Vectors.Empty); + + for Instr_Artifact of Comp_Command.Instrumentation_Sources loop + declare + Args_Compilation : String_Vectors.Vector; + Instr_Artifact_Object_Name : constant String := + New_File + (Prj, + Ada.Directories.Base_Name (+Instr_Artifact) & ".o"); + begin + Args_Compilation.Append (+"-c"); + Args_Compilation.Append + ("-I" & Instr_Config.GNATcov_RTS_Include_Dir); + Args_Compilation.Append (Instr_Artifact); + Args_Compilation.Append (+"-o"); + Args_Compilation.Append (+Instr_Artifact_Object_Name); + Run_Original_Compiler (Context, Args_Compilation); + + Context.Instrumentation_Objects + .Reference (Comp_Command.File) + .Append (+Instr_Artifact_Object_Name); + end; + end loop; + end if; + end; + end loop; + + -- Finally, run the alternate compiler driver invocation + + Run_Original_Compiler (Context, New_Args); + + if Comp_DB.Link_Command = No_Link_Command then + + -- Merge coverage buffer object files with instrumented files for + -- each assembly command. + + for Assembly_Command of Comp_DB.Assembly_Commands loop + if Context.Source_Mapping.Contains (Assembly_Command.Filename) then + declare + Orig_Source : constant Virtual_File := + Context.Source_Mapping.Element (Assembly_Command.Filename); + Instr_Objects : constant String_Vectors.Vector := + Context.Instrumentation_Objects.Element (Orig_Source); + Packaged_Name : constant String := + New_File + (Prj, + "instr_" & Filename_Slug (+Orig_Source.Full_Name) + & ".a"); + Success : Boolean; + begin + if not Instr_Objects.Is_Empty then + declare + Args_Ld : String_Vectors.Vector; + begin + Args_Ld.Append (+"-r"); + Args_Ld.Append_Vector (Instr_Objects); + Args_Ld.Append (Full_Name (Assembly_Command.Target)); + Args_Ld.Append (+"-o"); + Args_Ld.Append (+Packaged_Name); + Run_Command + (Command => + +Instr_Config.Linkers.Element + (Compiler_Exec_Basename), + Arguments => Args_Ld, + Origin_Command_Name => "compiler wrapper"); + + -- Finally, replace the original object file with the + -- newly created library file, packaging both the + -- instrumented source and its coverage buffer. + + GNAT.OS_Lib.Copy_File + (Packaged_Name, + +Assembly_Command.Target.Full_Name, + Success, + Mode => GNAT.OS_Lib.Overwrite, + Preserve => GNAT.OS_Lib.Full); + end; + end if; + end; + end if; + end loop; + end if; + end; + +end Instrument.Gcc_Wrapper; From 589b3cd167dee686b46ad23256c54592a44cd456 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 8 Jan 2024 09:29:57 +0000 Subject: [PATCH 0617/1483] Rework comments for stub units in the gnatcov codebase Explain the rationale only once (in gnatcov.gpr) and leave just references to that rationale in stub units. --- tools/gnatcov/gnatcov.gpr | 4 ++++ tools/gnatcov/instrument-ada_preprocessing__stub.ads | 6 ++---- tools/gnatcov/instrument-ada_unit__stub.ads | 4 +--- tools/gnatcov/instrument-c__stub.ads | 3 +-- tools/gnatcov/setup_rts__stub.adb | 2 ++ 5 files changed, 10 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 1121eecfa..c109d9bee 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -99,6 +99,10 @@ project Gnatcov is for Specification ("Qemu_Traces_Entries") use"qemu_traces_entries__" & Bits & ".ads"; + ----------- + -- Stubs -- + ----------- + -- In order to reduce the size of produced executables, whenever -- possible, use stubs for units that pull big dependencies into the -- link closure (GPR2, Libadalang, Libclang). diff --git a/tools/gnatcov/instrument-ada_preprocessing__stub.ads b/tools/gnatcov/instrument-ada_preprocessing__stub.ads index 4914ae82a..050d6aea7 100644 --- a/tools/gnatcov/instrument-ada_preprocessing__stub.ads +++ b/tools/gnatcov/instrument-ada_preprocessing__stub.ads @@ -16,10 +16,8 @@ -- of the license. -- ------------------------------------------------------------------------------ --- Stub of Instrument.Ada_Preprocessing, to avoid pulling a dependency to --- libadalang when gnatcov is not built with Ada instrumentation support --- (basically the gnatcov32 executable that has support for binary traces --- only). +-- Stub of Instrument.Ada_Preprocessing: see the note about Stubs in +-- gnatcov.gpr. package Instrument.Ada_Preprocessing is diff --git a/tools/gnatcov/instrument-ada_unit__stub.ads b/tools/gnatcov/instrument-ada_unit__stub.ads index 4dcdaa4f6..5e03b0619 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.ads +++ b/tools/gnatcov/instrument-ada_unit__stub.ads @@ -16,9 +16,7 @@ -- of the license. -- ------------------------------------------------------------------------------ --- Stub of Instrument.Ada_Unit, to avoid pulling a dependency to libadalang --- when gnatcov is not built with Ada instrumentation support (basically the --- gnatcov32 executable that has support for binary traces only). +-- Stub of Instrument.Ada_Unit: see the note about Stubs in gnatcov.gpr with Instrument.Common; use Instrument.Common; diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index 16dc0445e..6e5de0cf1 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -16,8 +16,7 @@ -- of the license. -- ------------------------------------------------------------------------------ --- Stub of Instrument.C, to avoid pulling a dependency to libclang when --- gnatcov is not built with C instrumentation support. +-- Stub of Instrument.C: see the note about Stubs in gnatcov.gpr with Instrument.Common; use Instrument.Common; diff --git a/tools/gnatcov/setup_rts__stub.adb b/tools/gnatcov/setup_rts__stub.adb index 69b2d7641..85a5515c3 100644 --- a/tools/gnatcov/setup_rts__stub.adb +++ b/tools/gnatcov/setup_rts__stub.adb @@ -16,6 +16,8 @@ -- of the license. -- ------------------------------------------------------------------------------ +-- Stub for the body of Setup_RTS: see the note about Stubs in gnatcov.gpr + package body Setup_RTS is ----------- From 4832960aad3040000141894b27311aa1c5130bfb Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 12 Jan 2024 09:51:00 +0000 Subject: [PATCH 0618/1483] Bump year in copyright notices --- tools/gnatcov/ali_files.adb | 2 +- tools/gnatcov/ali_files.ads | 2 +- tools/gnatcov/annotations-cobertura.adb | 2 +- tools/gnatcov/annotations-cobertura.ads | 2 +- tools/gnatcov/annotations-dynamic_html.adb | 2 +- tools/gnatcov/annotations-dynamic_html.ads | 2 +- tools/gnatcov/annotations-html.adb | 2 +- tools/gnatcov/annotations-html.ads | 2 +- tools/gnatcov/annotations-report.adb | 2 +- tools/gnatcov/annotations-report.ads | 2 +- tools/gnatcov/annotations-xcov.adb | 2 +- tools/gnatcov/annotations-xcov.ads | 2 +- tools/gnatcov/annotations-xml.adb | 2 +- tools/gnatcov/annotations-xml.ads | 2 +- tools/gnatcov/annotations.adb | 2 +- tools/gnatcov/annotations.ads | 2 +- tools/gnatcov/arch__32.ads | 2 +- tools/gnatcov/arch__64.ads | 2 +- tools/gnatcov/argparse.adb | 2 +- tools/gnatcov/argparse.ads | 2 +- tools/gnatcov/bfd_helpers.c | 2 +- tools/gnatcov/binary_files.adb | 2 +- tools/gnatcov/binary_files.ads | 2 +- tools/gnatcov/calendar_utils.adb | 2 +- tools/gnatcov/calendar_utils.ads | 2 +- tools/gnatcov/cfg_dump.adb | 2 +- tools/gnatcov/cfg_dump.ads | 2 +- tools/gnatcov/check_scos.adb | 2 +- tools/gnatcov/check_scos.ads | 2 +- tools/gnatcov/checkpoints.adb | 2 +- tools/gnatcov/checkpoints.ads | 2 +- tools/gnatcov/clang-extensions.adb | 2 +- tools/gnatcov/clang-extensions.ads | 2 +- tools/gnatcov/clang-wrapper.cc | 2 +- tools/gnatcov/coff.ads | 2 +- tools/gnatcov/command_line.adb | 2 +- tools/gnatcov/command_line.ads | 2 +- tools/gnatcov/commands.adb | 2 +- tools/gnatcov/commands.ads | 2 +- tools/gnatcov/compiler_wrappers-gcc.adb | 2 +- tools/gnatcov/compiler_wrappers.ads | 2 +- tools/gnatcov/convert.adb | 2 +- tools/gnatcov/convert.ads | 2 +- tools/gnatcov/coverage-object.adb | 2 +- tools/gnatcov/coverage-object.ads | 2 +- tools/gnatcov/coverage-source.adb | 2 +- tools/gnatcov/coverage-source.ads | 2 +- tools/gnatcov/coverage-tags.adb | 2 +- tools/gnatcov/coverage-tags.ads | 2 +- tools/gnatcov/coverage.adb | 2 +- tools/gnatcov/coverage.ads | 2 +- tools/gnatcov/coverage_options.adb | 2 +- tools/gnatcov/coverage_options.ads | 2 +- tools/gnatcov/decision_map.adb | 2 +- tools/gnatcov/decision_map.ads | 2 +- tools/gnatcov/diagnostics.adb | 2 +- tools/gnatcov/diagnostics.ads | 2 +- tools/gnatcov/disa_aarch64.adb | 2 +- tools/gnatcov/disa_aarch64.ads | 2 +- tools/gnatcov/disa_arm.adb | 2 +- tools/gnatcov/disa_arm.ads | 2 +- tools/gnatcov/disa_common.adb | 2 +- tools/gnatcov/disa_common.ads | 2 +- tools/gnatcov/disa_lmp.adb | 2 +- tools/gnatcov/disa_lmp.ads | 2 +- tools/gnatcov/disa_ppc.adb | 2 +- tools/gnatcov/disa_ppc.ads | 2 +- tools/gnatcov/disa_sparc.adb | 2 +- tools/gnatcov/disa_sparc.ads | 2 +- tools/gnatcov/disa_symbolize.adb | 2 +- tools/gnatcov/disa_symbolize.ads | 2 +- tools/gnatcov/disa_thumb.adb | 2 +- tools/gnatcov/disa_thumb.ads | 2 +- tools/gnatcov/disa_x86.adb | 2 +- tools/gnatcov/disa_x86.ads | 2 +- tools/gnatcov/disassemble_insn_properties.adb | 2 +- tools/gnatcov/disassemble_insn_properties.ads | 2 +- tools/gnatcov/disassemblers.adb | 2 +- tools/gnatcov/disassemblers.ads | 2 +- tools/gnatcov/display.adb | 2 +- tools/gnatcov/display.ads | 2 +- tools/gnatcov/dwarf.ads | 2 +- tools/gnatcov/dwarf_handling.adb | 2 +- tools/gnatcov/dwarf_handling.ads | 2 +- tools/gnatcov/elf32.adb | 2 +- tools/gnatcov/elf32.ads | 2 +- tools/gnatcov/elf64.adb | 2 +- tools/gnatcov/elf64.ads | 2 +- tools/gnatcov/elf_common.adb | 2 +- tools/gnatcov/elf_common.ads | 2 +- tools/gnatcov/elf_disassemblers.adb | 2 +- tools/gnatcov/elf_disassemblers.ads | 2 +- tools/gnatcov/elf_files.adb | 2 +- tools/gnatcov/elf_files.ads | 2 +- .../aunit_variant/harness/fixture/controls-test-suite.ads | 2 +- .../aunit_variant/harness/fixture/geomaps-test-suite.adb | 2 +- .../aunit_variant/harness/fixture/geomaps-test-suite.ads | 2 +- .../harness/fixture/links-gen_test-gen_suite.adb | 2 +- .../harness/fixture/links-gen_test-gen_suite.ads | 2 +- .../examples/aunit_variant/harness/fixture/main_suite.adb | 2 +- .../examples/aunit_variant/harness/fixture/main_suite.ads | 2 +- .../aunit_variant/harness/fixture/robots-test-suite.adb | 2 +- .../aunit_variant/harness/fixture/robots-test-suite.ads | 2 +- .../aunit_variant/harness/fixture/stations-test-suite.adb | 2 +- .../aunit_variant/harness/fixture/stations-test-suite.ads | 2 +- .../aunit_variant/harness/fixture/test_explore.adb | 2 +- .../examples/aunit_variant/harness/old/test_ports.adb | 2 +- .../examples/aunit_variant/harness/old/test_queues.adb | 2 +- .../examples/aunit_variant/harness/old/test_robots.adb | 2 +- .../examples/aunit_variant/harness/old/test_stacks.adb | 2 +- .../examples/aunit_variant/harness/tests/actors-test.adb | 2 +- .../examples/aunit_variant/harness/tests/actors-test.ads | 2 +- .../examples/aunit_variant/harness/tests/controls-test.ads | 2 +- .../examples/aunit_variant/harness/tests/geomaps-test.adb | 2 +- .../examples/aunit_variant/harness/tests/geomaps-test.ads | 2 +- .../aunit_variant/harness/tests/links-gen_test.adb | 2 +- .../aunit_variant/harness/tests/links-gen_test.ads | 2 +- .../examples/aunit_variant/harness/tests/robots-test.adb | 2 +- .../examples/aunit_variant/harness/tests/robots-test.ads | 2 +- .../examples/aunit_variant/harness/tests/stations-test.adb | 2 +- .../examples/aunit_variant/harness/tests/stations-test.ads | 2 +- tools/gnatcov/examples/aunit_variant/src/actors.adb | 2 +- tools/gnatcov/examples/aunit_variant/src/actors.ads | 2 +- tools/gnatcov/examples/aunit_variant/src/controls.ads | 2 +- tools/gnatcov/examples/aunit_variant/src/explore.adb | 2 +- tools/gnatcov/examples/aunit_variant/src/geomaps.adb | 2 +- tools/gnatcov/examples/aunit_variant/src/geomaps.ads | 2 +- tools/gnatcov/examples/aunit_variant/src/links.adb | 2 +- tools/gnatcov/examples/aunit_variant/src/links.ads | 2 +- tools/gnatcov/examples/aunit_variant/src/overview.ads | 2 +- tools/gnatcov/examples/aunit_variant/src/queues.adb | 2 +- tools/gnatcov/examples/aunit_variant/src/queues.ads | 2 +- tools/gnatcov/examples/aunit_variant/src/robots.adb | 2 +- tools/gnatcov/examples/aunit_variant/src/robots.ads | 2 +- .../examples/aunit_variant/src/robots_devices-dummy.adb | 2 +- .../examples/aunit_variant/src/robots_devices-dummy.ads | 2 +- .../gnatcov/examples/aunit_variant/src/robots_devices.ads | 2 +- tools/gnatcov/examples/aunit_variant/src/stacks.adb | 2 +- tools/gnatcov/examples/aunit_variant/src/stacks.ads | 2 +- tools/gnatcov/examples/aunit_variant/src/stations.adb | 2 +- tools/gnatcov/examples/aunit_variant/src/stations.ads | 2 +- tools/gnatcov/examples/branch_traces/src/robot.adb | 2 +- tools/gnatcov/examples/branch_traces/src/robot.ads | 2 +- tools/gnatcov/examples/branch_traces/src/support.adb | 2 +- tools/gnatcov/examples/branch_traces/src/support.ads | 2 +- .../gnatcov/examples/branch_traces/src/test_clear_step.adb | 2 +- tools/gnatcov/examples/branch_traces/src/test_pit_step.adb | 2 +- .../gnatcov/examples/branch_traces/src/test_rock_wait.adb | 2 +- tools/gnatcov/examples/mcdc_checkpoints/src/assert.adb | 2 +- tools/gnatcov/examples/mcdc_checkpoints/src/assert.ads | 2 +- tools/gnatcov/examples/mcdc_checkpoints/src/engines.adb | 2 +- tools/gnatcov/examples/mcdc_checkpoints/src/engines.ads | 2 +- .../gnatcov/examples/mcdc_checkpoints/src/test_stable.adb | 2 +- .../examples/mcdc_checkpoints/src/test_unstable_p.adb | 2 +- .../examples/mcdc_checkpoints/src/test_unstable_t.adb | 2 +- tools/gnatcov/examples/spark_instrumentation/src/foo.adb | 2 +- tools/gnatcov/examples/spark_instrumentation/src/foo.ads | 2 +- tools/gnatcov/examples/spark_instrumentation/src/main.adb | 2 +- .../src/last_chance_/simple_last_chance_handler.adb | 2 +- .../src/last_chance_/simple_last_chance_handler.ads | 2 +- .../simple_last_chance_handler.adb | 2 +- .../simple_last_chance_handler.ads | 2 +- .../simple_last_chance_handler.adb | 2 +- .../simple_last_chance_handler.ads | 2 +- tools/gnatcov/examples/support/src/leon-elf/abort.c | 2 +- tools/gnatcov/examples/support/src/leon3-elf/abort.c | 7 ++++--- tools/gnatcov/examples/support/src/libsupport.adb | 2 +- tools/gnatcov/examples/support/src/libsupport.ads | 2 +- .../examples/support/src/memory/libsupport-memory.adb | 2 +- .../examples/support/src/memory/libsupport-memory.ads | 2 +- tools/gnatcov/examples/xml/src/services.adb | 2 +- tools/gnatcov/examples/xml/src/services.ads | 2 +- tools/gnatcov/examples/xml/src/test_services.adb | 2 +- tools/gnatcov/execs_dbase.adb | 2 +- tools/gnatcov/execs_dbase.ads | 2 +- tools/gnatcov/factory_registry.adb | 2 +- tools/gnatcov/factory_registry.ads | 2 +- tools/gnatcov/files_handling.adb | 2 +- tools/gnatcov/files_handling.ads | 2 +- tools/gnatcov/files_table.adb | 2 +- tools/gnatcov/files_table.ads | 2 +- tools/gnatcov/gnatcov.adb | 2 +- tools/gnatcov/gnatcov_bits_specific.adb | 2 +- tools/gnatcov/hex_images.adb | 2 +- tools/gnatcov/hex_images.ads | 2 +- tools/gnatcov/highlighting.adb | 2 +- tools/gnatcov/highlighting.ads | 2 +- tools/gnatcov/inputs.adb | 2 +- tools/gnatcov/inputs.ads | 2 +- tools/gnatcov/instrument-ada_preprocessing.adb | 2 +- tools/gnatcov/instrument-ada_preprocessing.ads | 2 +- tools/gnatcov/instrument-ada_unit.adb | 2 +- tools/gnatcov/instrument-ada_unit.ads | 2 +- tools/gnatcov/instrument-ada_unit__stub.adb | 2 +- tools/gnatcov/instrument-ada_unit__stub.ads | 2 +- tools/gnatcov/instrument-ada_unit_provider.adb | 2 +- tools/gnatcov/instrument-ada_unit_provider.ads | 2 +- tools/gnatcov/instrument-c.adb | 2 +- tools/gnatcov/instrument-c.ads | 2 +- tools/gnatcov/instrument-c__stub.adb | 2 +- tools/gnatcov/instrument-c__stub.ads | 2 +- tools/gnatcov/instrument-c_utils.adb | 2 +- tools/gnatcov/instrument-c_utils.ads | 2 +- tools/gnatcov/instrument-checkpoints.adb | 2 +- tools/gnatcov/instrument-checkpoints.ads | 2 +- tools/gnatcov/instrument-clean_objdirs.adb | 2 +- tools/gnatcov/instrument-clean_objdirs.ads | 2 +- tools/gnatcov/instrument-common.adb | 2 +- tools/gnatcov/instrument-common.ads | 2 +- tools/gnatcov/instrument-config.adb | 2 +- tools/gnatcov/instrument-input_traces.adb | 2 +- tools/gnatcov/instrument-input_traces.ads | 2 +- tools/gnatcov/instrument-main.adb | 2 +- tools/gnatcov/instrument-projects.adb | 2 +- tools/gnatcov/instrument-setup_config.adb | 2 +- tools/gnatcov/instrument-setup_config.ads | 2 +- tools/gnatcov/instrument-source.adb | 2 +- tools/gnatcov/instrument.adb | 2 +- tools/gnatcov/instrument.ads | 2 +- tools/gnatcov/json.adb | 2 +- tools/gnatcov/json.ads | 2 +- tools/gnatcov/libopcodes_bind/dis_opcodes.ads | 2 +- tools/gnatcov/libopcodes_bind/dis_stream.c | 2 +- tools/gnatcov/libopcodes_bind/dis_stream.h | 2 +- tools/gnatcov/libopcodes_bind/dis_wrapper.c | 2 +- tools/gnatcov/libopcodes_bind/dis_wrapper.h | 2 +- tools/gnatcov/logging.adb | 2 +- tools/gnatcov/logging.ads | 2 +- tools/gnatcov/mc_dc.adb | 2 +- tools/gnatcov/mc_dc.ads | 2 +- tools/gnatcov/object_locations.adb | 2 +- tools/gnatcov/object_locations.ads | 2 +- tools/gnatcov/outputs.adb | 2 +- tools/gnatcov/outputs.ads | 2 +- tools/gnatcov/paths.adb | 2 +- tools/gnatcov/paths.ads | 2 +- tools/gnatcov/pecoff_files.adb | 2 +- tools/gnatcov/pecoff_files.ads | 2 +- tools/gnatcov/perf_counters.adb | 2 +- tools/gnatcov/perf_counters.ads | 2 +- tools/gnatcov/ppc_descs.adb | 2 +- tools/gnatcov/ppc_descs.ads | 2 +- tools/gnatcov/project.adb | 2 +- tools/gnatcov/project.ads | 2 +- tools/gnatcov/qemu_traces.ads | 2 +- tools/gnatcov/qemu_traces_entries__32.ads | 2 +- tools/gnatcov/qemu_traces_entries__64.ads | 2 +- tools/gnatcov/rts/gcvrt.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-base_io.adb | 2 +- tools/gnatcov/rts/gnatcov_rts-base_io.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-buffers.adb | 2 +- tools/gnatcov/rts/gnatcov_rts-buffers.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-strings.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb | 2 +- tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb | 2 +- tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-traces-output.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-traces.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-types.ads | 2 +- tools/gnatcov/rts/gnatcov_rts.ads | 2 +- tools/gnatcov/rts/gnatcov_rts_c-base_io.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-base_io.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-buffers.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-os_interface.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-os_interface.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-strings.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces-output.h | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces.c | 2 +- tools/gnatcov/rts/gnatcov_rts_c-traces.h | 2 +- tools/gnatcov/rundrv-config.adb | 2 +- tools/gnatcov/rundrv-config.ads | 2 +- tools/gnatcov/rundrv-handlers.adb | 2 +- tools/gnatcov/rundrv-handlers.ads | 2 +- tools/gnatcov/rundrv.adb | 2 +- tools/gnatcov/rundrv.ads | 2 +- tools/gnatcov/sc_obligations-bdd.adb | 2 +- tools/gnatcov/sc_obligations-bdd.ads | 2 +- tools/gnatcov/sc_obligations.adb | 2 +- tools/gnatcov/sc_obligations.ads | 2 +- tools/gnatcov/setup_rts.adb | 2 +- tools/gnatcov/setup_rts.ads | 2 +- tools/gnatcov/slocs.adb | 2 +- tools/gnatcov/slocs.ads | 2 +- tools/gnatcov/sparc_descs.ads | 2 +- tools/gnatcov/strings.adb | 2 +- tools/gnatcov/strings.ads | 2 +- tools/gnatcov/subprocesses.adb | 2 +- tools/gnatcov/subprocesses.ads | 2 +- tools/gnatcov/support_files.ads | 2 +- tools/gnatcov/swaps.adb | 2 +- tools/gnatcov/swaps.ads | 2 +- tools/gnatcov/switches.adb | 2 +- tools/gnatcov/switches.ads | 2 +- tools/gnatcov/symbols.adb | 2 +- tools/gnatcov/symbols.ads | 2 +- tools/gnatcov/temp_dirs.adb | 2 +- tools/gnatcov/temp_dirs.ads | 2 +- tools/gnatcov/text_files.adb | 2 +- tools/gnatcov/text_files.ads | 2 +- tools/gnatcov/trace_adapters/nexus/isys2nex.adb | 2 +- tools/gnatcov/trace_adapters/nexus/isys2nex.ads | 2 +- tools/gnatcov/trace_adapters/nexus/isys_drv.adb | 2 +- tools/gnatcov/trace_adapters/nexus/nexus_rep.ads | 2 +- tools/gnatcov/trace_adapters/nexus/nexus_trace_gen.adb | 2 +- tools/gnatcov/trace_adapters/trace32/instructions_info.adb | 2 +- tools/gnatcov/trace_adapters/trace32/instructions_info.ads | 2 +- .../gnatcov/trace_adapters/trace32/trace32-branchflow.adb | 2 +- .../gnatcov/trace_adapters/trace32/trace32-branchflow.ads | 2 +- .../gnatcov/trace_adapters/trace32/trace32-conversion.adb | 2 +- .../gnatcov/trace_adapters/trace32/trace32-conversion.ads | 2 +- tools/gnatcov/trace_adapters/trace32/trace32.ads | 2 +- tools/gnatcov/trace_adapters/trace32/trace32_drv.adb | 2 +- tools/gnatcov/trace_adapters/trace32/trace_output.adb | 2 +- tools/gnatcov/trace_adapters/trace32/trace_output.ads | 2 +- tools/gnatcov/traces.adb | 2 +- tools/gnatcov/traces.ads | 2 +- tools/gnatcov/traces_dbase.adb | 2 +- tools/gnatcov/traces_dbase.ads | 2 +- tools/gnatcov/traces_disa.adb | 2 +- tools/gnatcov/traces_disa.ads | 2 +- tools/gnatcov/traces_dump.adb | 2 +- tools/gnatcov/traces_dump.ads | 2 +- tools/gnatcov/traces_elf.adb | 2 +- tools/gnatcov/traces_elf.ads | 2 +- tools/gnatcov/traces_files.adb | 2 +- tools/gnatcov/traces_files.ads | 2 +- tools/gnatcov/traces_files_registry.adb | 2 +- tools/gnatcov/traces_files_registry.ads | 2 +- tools/gnatcov/traces_lines.adb | 2 +- tools/gnatcov/traces_lines.ads | 2 +- tools/gnatcov/traces_names.adb | 2 +- tools/gnatcov/traces_names.ads | 2 +- tools/gnatcov/traces_source.adb | 2 +- tools/gnatcov/traces_source.ads | 2 +- tools/gnatcov/traces_stats.adb | 2 +- tools/gnatcov/traces_stats.ads | 2 +- tools/gnatcov/version.ads | 2 +- tools/gnatcov/zlib_helpers.c | 2 +- 346 files changed, 349 insertions(+), 348 deletions(-) diff --git a/tools/gnatcov/ali_files.adb b/tools/gnatcov/ali_files.adb index fcdfe7261..c6b7fd2bb 100644 --- a/tools/gnatcov/ali_files.adb +++ b/tools/gnatcov/ali_files.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/ali_files.ads b/tools/gnatcov/ali_files.ads index c58e4de55..b32147b0d 100644 --- a/tools/gnatcov/ali_files.ads +++ b/tools/gnatcov/ali_files.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb index 8331bc4cc..86a1e01b3 100644 --- a/tools/gnatcov/annotations-cobertura.adb +++ b/tools/gnatcov/annotations-cobertura.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/annotations-cobertura.ads b/tools/gnatcov/annotations-cobertura.ads index a62e2a460..8e567be1e 100644 --- a/tools/gnatcov/annotations-cobertura.ads +++ b/tools/gnatcov/annotations-cobertura.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 57a0f4767..cbb3e1a51 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2013-2022, AdaCore -- +-- Copyright (C) 2013-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 -- diff --git a/tools/gnatcov/annotations-dynamic_html.ads b/tools/gnatcov/annotations-dynamic_html.ads index 0ac0b7b8a..fa69de1a5 100644 --- a/tools/gnatcov/annotations-dynamic_html.ads +++ b/tools/gnatcov/annotations-dynamic_html.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2013-2022, AdaCore -- +-- Copyright (C) 2013-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 -- diff --git a/tools/gnatcov/annotations-html.adb b/tools/gnatcov/annotations-html.adb index bf592c06a..1b4d9176a 100644 --- a/tools/gnatcov/annotations-html.adb +++ b/tools/gnatcov/annotations-html.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/annotations-html.ads b/tools/gnatcov/annotations-html.ads index e14e85df8..2becea1a6 100644 --- a/tools/gnatcov/annotations-html.ads +++ b/tools/gnatcov/annotations-html.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 5a9e1427e..e1393303d 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/annotations-report.ads b/tools/gnatcov/annotations-report.ads index d6a4c45a7..13ccc8e27 100644 --- a/tools/gnatcov/annotations-report.ads +++ b/tools/gnatcov/annotations-report.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/annotations-xcov.adb b/tools/gnatcov/annotations-xcov.adb index 6398929a5..5f32f3383 100644 --- a/tools/gnatcov/annotations-xcov.adb +++ b/tools/gnatcov/annotations-xcov.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/annotations-xcov.ads b/tools/gnatcov/annotations-xcov.ads index 52fc56db3..9c3b1a6ac 100644 --- a/tools/gnatcov/annotations-xcov.ads +++ b/tools/gnatcov/annotations-xcov.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index 1a3eaa59a..d2a7e894e 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/annotations-xml.ads b/tools/gnatcov/annotations-xml.ads index d71aa243c..85be589ec 100644 --- a/tools/gnatcov/annotations-xml.ads +++ b/tools/gnatcov/annotations-xml.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index a7362ca3a..308750fd3 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 567077baf..8fe34a45a 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/arch__32.ads b/tools/gnatcov/arch__32.ads index 263d741ac..003feba5d 100644 --- a/tools/gnatcov/arch__32.ads +++ b/tools/gnatcov/arch__32.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/arch__64.ads b/tools/gnatcov/arch__64.ads index 472f7dbdc..2472c42b5 100644 --- a/tools/gnatcov/arch__64.ads +++ b/tools/gnatcov/arch__64.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/argparse.adb b/tools/gnatcov/argparse.adb index d8702b3ef..dee0fdfea 100644 --- a/tools/gnatcov/argparse.adb +++ b/tools/gnatcov/argparse.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2015-2022, AdaCore -- +-- Copyright (C) 2015-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 -- diff --git a/tools/gnatcov/argparse.ads b/tools/gnatcov/argparse.ads index 4c6e59760..d98799b22 100644 --- a/tools/gnatcov/argparse.ads +++ b/tools/gnatcov/argparse.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2015-2022, AdaCore -- +-- Copyright (C) 2015-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 -- diff --git a/tools/gnatcov/bfd_helpers.c b/tools/gnatcov/bfd_helpers.c index 0f5bfa617..b306723e8 100644 --- a/tools/gnatcov/bfd_helpers.c +++ b/tools/gnatcov/bfd_helpers.c @@ -2,7 +2,7 @@ * * * GNATcoverage * * * - * Copyright (C) 2020-2022, AdaCore * + * Copyright (C) 2020-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 * diff --git a/tools/gnatcov/binary_files.adb b/tools/gnatcov/binary_files.adb index f9228c396..9e0313ad4 100644 --- a/tools/gnatcov/binary_files.adb +++ b/tools/gnatcov/binary_files.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/binary_files.ads b/tools/gnatcov/binary_files.ads index 2c7383ee6..5418c5c0c 100644 --- a/tools/gnatcov/binary_files.ads +++ b/tools/gnatcov/binary_files.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/calendar_utils.adb b/tools/gnatcov/calendar_utils.adb index 3fb2bdd68..722c4556a 100644 --- a/tools/gnatcov/calendar_utils.adb +++ b/tools/gnatcov/calendar_utils.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/calendar_utils.ads b/tools/gnatcov/calendar_utils.ads index 073ee358d..6f2fe42f3 100644 --- a/tools/gnatcov/calendar_utils.ads +++ b/tools/gnatcov/calendar_utils.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/cfg_dump.adb b/tools/gnatcov/cfg_dump.adb index ad8ad1f77..0d8f14c29 100644 --- a/tools/gnatcov/cfg_dump.adb +++ b/tools/gnatcov/cfg_dump.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/cfg_dump.ads b/tools/gnatcov/cfg_dump.ads index 7f1b9ee31..c59b49c94 100644 --- a/tools/gnatcov/cfg_dump.ads +++ b/tools/gnatcov/cfg_dump.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/check_scos.adb b/tools/gnatcov/check_scos.adb index 2ab997ee9..e8152944a 100644 --- a/tools/gnatcov/check_scos.adb +++ b/tools/gnatcov/check_scos.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/check_scos.ads b/tools/gnatcov/check_scos.ads index 109ce829f..473a3a8d1 100644 --- a/tools/gnatcov/check_scos.ads +++ b/tools/gnatcov/check_scos.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index eb2ea3515..b5ebb74bc 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index ecb96174b..b9c85fb41 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index f29eeef17..c52da4f5b 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2021-2022, AdaCore -- +-- Copyright (C) 2021-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 -- diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index b516cd84e..5eb1cf7e0 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2021-2022, AdaCore -- +-- Copyright (C) 2021-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 -- diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index f464c32a7..12e4f2d94 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -2,7 +2,7 @@ * * * GNATcoverage * * * - * Copyright (C) 2021, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/coff.ads b/tools/gnatcov/coff.ads index e1af20eb1..23b0b88b6 100644 --- a/tools/gnatcov/coff.ads +++ b/tools/gnatcov/coff.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2015-2022, AdaCore -- +-- Copyright (C) 2015-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 -- diff --git a/tools/gnatcov/command_line.adb b/tools/gnatcov/command_line.adb index 5540c3643..65333f9bf 100644 --- a/tools/gnatcov/command_line.adb +++ b/tools/gnatcov/command_line.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2015-2022, AdaCore -- +-- Copyright (C) 2015-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 -- diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 49cc3b501..b35cfd69c 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2015-2022, AdaCore -- +-- Copyright (C) 2015-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 -- diff --git a/tools/gnatcov/commands.adb b/tools/gnatcov/commands.adb index a936ddeb5..dac2bdbc1 100644 --- a/tools/gnatcov/commands.adb +++ b/tools/gnatcov/commands.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/commands.ads b/tools/gnatcov/commands.ads index ccd27fa87..1335f08a6 100644 --- a/tools/gnatcov/commands.ads +++ b/tools/gnatcov/commands.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 94d2b1151..37ef99f83 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/compiler_wrappers.ads b/tools/gnatcov/compiler_wrappers.ads index 92258e3a9..b554fd906 100644 --- a/tools/gnatcov/compiler_wrappers.ads +++ b/tools/gnatcov/compiler_wrappers.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/convert.adb b/tools/gnatcov/convert.adb index fea3d7003..21aa76782 100644 --- a/tools/gnatcov/convert.adb +++ b/tools/gnatcov/convert.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2013-2022, AdaCore -- +-- Copyright (C) 2013-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 -- diff --git a/tools/gnatcov/convert.ads b/tools/gnatcov/convert.ads index ef5577030..ad0aa4680 100644 --- a/tools/gnatcov/convert.ads +++ b/tools/gnatcov/convert.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2013-2022, AdaCore -- +-- Copyright (C) 2013-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 -- diff --git a/tools/gnatcov/coverage-object.adb b/tools/gnatcov/coverage-object.adb index befd77f17..8474a18a6 100644 --- a/tools/gnatcov/coverage-object.adb +++ b/tools/gnatcov/coverage-object.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/coverage-object.ads b/tools/gnatcov/coverage-object.ads index d4704a44e..1a48d9842 100644 --- a/tools/gnatcov/coverage-object.ads +++ b/tools/gnatcov/coverage-object.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 38ca45cf1..d1bb09c8f 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 3d8f49b54..602a1e07a 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/coverage-tags.adb b/tools/gnatcov/coverage-tags.adb index e1f2a7ad9..6099d034c 100644 --- a/tools/gnatcov/coverage-tags.adb +++ b/tools/gnatcov/coverage-tags.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/coverage-tags.ads b/tools/gnatcov/coverage-tags.ads index b2386897c..b40e6622d 100644 --- a/tools/gnatcov/coverage-tags.ads +++ b/tools/gnatcov/coverage-tags.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/coverage.adb b/tools/gnatcov/coverage.adb index a2ccd5574..f193d9260 100644 --- a/tools/gnatcov/coverage.adb +++ b/tools/gnatcov/coverage.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/coverage.ads b/tools/gnatcov/coverage.ads index f75df24f7..e67cca242 100644 --- a/tools/gnatcov/coverage.ads +++ b/tools/gnatcov/coverage.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/coverage_options.adb b/tools/gnatcov/coverage_options.adb index 38ff21665..3cd660d8d 100644 --- a/tools/gnatcov/coverage_options.adb +++ b/tools/gnatcov/coverage_options.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2021-2022, AdaCore -- +-- Copyright (C) 2021-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 -- diff --git a/tools/gnatcov/coverage_options.ads b/tools/gnatcov/coverage_options.ads index f36c644ed..eecb79223 100644 --- a/tools/gnatcov/coverage_options.ads +++ b/tools/gnatcov/coverage_options.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2021-2022, AdaCore -- +-- Copyright (C) 2021-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 -- diff --git a/tools/gnatcov/decision_map.adb b/tools/gnatcov/decision_map.adb index bb9dad27b..d1808e18f 100644 --- a/tools/gnatcov/decision_map.adb +++ b/tools/gnatcov/decision_map.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/decision_map.ads b/tools/gnatcov/decision_map.ads index cb41a9ae7..8497bf253 100644 --- a/tools/gnatcov/decision_map.ads +++ b/tools/gnatcov/decision_map.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/diagnostics.adb b/tools/gnatcov/diagnostics.adb index a3deea367..f3d536e69 100644 --- a/tools/gnatcov/diagnostics.adb +++ b/tools/gnatcov/diagnostics.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/diagnostics.ads b/tools/gnatcov/diagnostics.ads index fbe251eab..c512957c5 100644 --- a/tools/gnatcov/diagnostics.ads +++ b/tools/gnatcov/diagnostics.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/disa_aarch64.adb b/tools/gnatcov/disa_aarch64.adb index d081ae5b6..006eb3d77 100644 --- a/tools/gnatcov/disa_aarch64.adb +++ b/tools/gnatcov/disa_aarch64.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/disa_aarch64.ads b/tools/gnatcov/disa_aarch64.ads index 72c4f34df..7542dbe18 100644 --- a/tools/gnatcov/disa_aarch64.ads +++ b/tools/gnatcov/disa_aarch64.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/disa_arm.adb b/tools/gnatcov/disa_arm.adb index c17be7eba..47be15741 100644 --- a/tools/gnatcov/disa_arm.adb +++ b/tools/gnatcov/disa_arm.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/disa_arm.ads b/tools/gnatcov/disa_arm.ads index 780ec2c3f..fc1d8f18e 100644 --- a/tools/gnatcov/disa_arm.ads +++ b/tools/gnatcov/disa_arm.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/disa_common.adb b/tools/gnatcov/disa_common.adb index d6d4bbff6..01b846abc 100644 --- a/tools/gnatcov/disa_common.adb +++ b/tools/gnatcov/disa_common.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/disa_common.ads b/tools/gnatcov/disa_common.ads index 80d74e14c..680835dc1 100644 --- a/tools/gnatcov/disa_common.ads +++ b/tools/gnatcov/disa_common.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/disa_lmp.adb b/tools/gnatcov/disa_lmp.adb index d0ae29a4e..db68af07e 100644 --- a/tools/gnatcov/disa_lmp.adb +++ b/tools/gnatcov/disa_lmp.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/disa_lmp.ads b/tools/gnatcov/disa_lmp.ads index cc8c3fed9..23158caa0 100644 --- a/tools/gnatcov/disa_lmp.ads +++ b/tools/gnatcov/disa_lmp.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/disa_ppc.adb b/tools/gnatcov/disa_ppc.adb index 07d2a298e..3498cc1ae 100644 --- a/tools/gnatcov/disa_ppc.adb +++ b/tools/gnatcov/disa_ppc.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/disa_ppc.ads b/tools/gnatcov/disa_ppc.ads index eb0861340..0ce7bd1df 100644 --- a/tools/gnatcov/disa_ppc.ads +++ b/tools/gnatcov/disa_ppc.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/disa_sparc.adb b/tools/gnatcov/disa_sparc.adb index 13cb37e96..020c2f732 100644 --- a/tools/gnatcov/disa_sparc.adb +++ b/tools/gnatcov/disa_sparc.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/disa_sparc.ads b/tools/gnatcov/disa_sparc.ads index bc4099f10..82747ca55 100644 --- a/tools/gnatcov/disa_sparc.ads +++ b/tools/gnatcov/disa_sparc.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/disa_symbolize.adb b/tools/gnatcov/disa_symbolize.adb index a30850cf5..dd50d1f5f 100644 --- a/tools/gnatcov/disa_symbolize.adb +++ b/tools/gnatcov/disa_symbolize.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/disa_symbolize.ads b/tools/gnatcov/disa_symbolize.ads index f5ec33ddf..888d8e2b3 100644 --- a/tools/gnatcov/disa_symbolize.ads +++ b/tools/gnatcov/disa_symbolize.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/disa_thumb.adb b/tools/gnatcov/disa_thumb.adb index 6816d8192..2df0856eb 100644 --- a/tools/gnatcov/disa_thumb.adb +++ b/tools/gnatcov/disa_thumb.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/disa_thumb.ads b/tools/gnatcov/disa_thumb.ads index fd9002ace..dc1646e46 100644 --- a/tools/gnatcov/disa_thumb.ads +++ b/tools/gnatcov/disa_thumb.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/disa_x86.adb b/tools/gnatcov/disa_x86.adb index 0cbfd64d5..797cd9861 100644 --- a/tools/gnatcov/disa_x86.adb +++ b/tools/gnatcov/disa_x86.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/disa_x86.ads b/tools/gnatcov/disa_x86.ads index 025653bbf..48563e046 100644 --- a/tools/gnatcov/disa_x86.ads +++ b/tools/gnatcov/disa_x86.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/disassemble_insn_properties.adb b/tools/gnatcov/disassemble_insn_properties.adb index 439f0b70d..ca5d22076 100644 --- a/tools/gnatcov/disassemble_insn_properties.adb +++ b/tools/gnatcov/disassemble_insn_properties.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2014-2022, AdaCore -- +-- Copyright (C) 2014-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 -- diff --git a/tools/gnatcov/disassemble_insn_properties.ads b/tools/gnatcov/disassemble_insn_properties.ads index 0ad9cd7f3..dfa8ef8be 100644 --- a/tools/gnatcov/disassemble_insn_properties.ads +++ b/tools/gnatcov/disassemble_insn_properties.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2014-2022, AdaCore -- +-- Copyright (C) 2014-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 -- diff --git a/tools/gnatcov/disassemblers.adb b/tools/gnatcov/disassemblers.adb index 3f1146c8c..eaba2d4ad 100644 --- a/tools/gnatcov/disassemblers.adb +++ b/tools/gnatcov/disassemblers.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/disassemblers.ads b/tools/gnatcov/disassemblers.ads index 7d70c3415..4276f1f23 100644 --- a/tools/gnatcov/disassemblers.ads +++ b/tools/gnatcov/disassemblers.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/display.adb b/tools/gnatcov/display.adb index 3f9d65638..9067ca501 100644 --- a/tools/gnatcov/display.adb +++ b/tools/gnatcov/display.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/display.ads b/tools/gnatcov/display.ads index 611e204d4..62f2f0250 100644 --- a/tools/gnatcov/display.ads +++ b/tools/gnatcov/display.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/dwarf.ads b/tools/gnatcov/dwarf.ads index 8c26025ba..a321c3a87 100644 --- a/tools/gnatcov/dwarf.ads +++ b/tools/gnatcov/dwarf.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/dwarf_handling.adb b/tools/gnatcov/dwarf_handling.adb index 997964f24..ae1bd6abf 100644 --- a/tools/gnatcov/dwarf_handling.adb +++ b/tools/gnatcov/dwarf_handling.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/dwarf_handling.ads b/tools/gnatcov/dwarf_handling.ads index f9000eb23..337bf09f3 100644 --- a/tools/gnatcov/dwarf_handling.ads +++ b/tools/gnatcov/dwarf_handling.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/elf32.adb b/tools/gnatcov/elf32.adb index 9f02a1274..994e167f0 100644 --- a/tools/gnatcov/elf32.adb +++ b/tools/gnatcov/elf32.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/elf32.ads b/tools/gnatcov/elf32.ads index 7a2142a6d..75cb42a12 100644 --- a/tools/gnatcov/elf32.ads +++ b/tools/gnatcov/elf32.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/elf64.adb b/tools/gnatcov/elf64.adb index aab3092d1..c09e72012 100644 --- a/tools/gnatcov/elf64.adb +++ b/tools/gnatcov/elf64.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/elf64.ads b/tools/gnatcov/elf64.ads index a017c10a1..f6c8030b5 100644 --- a/tools/gnatcov/elf64.ads +++ b/tools/gnatcov/elf64.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/elf_common.adb b/tools/gnatcov/elf_common.adb index a08ea3380..be9408aa2 100644 --- a/tools/gnatcov/elf_common.adb +++ b/tools/gnatcov/elf_common.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/elf_common.ads b/tools/gnatcov/elf_common.ads index 807069f4c..8dbec8c5a 100644 --- a/tools/gnatcov/elf_common.ads +++ b/tools/gnatcov/elf_common.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/elf_disassemblers.adb b/tools/gnatcov/elf_disassemblers.adb index 02e9f0532..caee79b89 100644 --- a/tools/gnatcov/elf_disassemblers.adb +++ b/tools/gnatcov/elf_disassemblers.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/elf_disassemblers.ads b/tools/gnatcov/elf_disassemblers.ads index f16ee1679..893dc140b 100644 --- a/tools/gnatcov/elf_disassemblers.ads +++ b/tools/gnatcov/elf_disassemblers.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/elf_files.adb b/tools/gnatcov/elf_files.adb index eef7c15ed..20cc24583 100644 --- a/tools/gnatcov/elf_files.adb +++ b/tools/gnatcov/elf_files.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/elf_files.ads b/tools/gnatcov/elf_files.ads index e1701bbcf..fdcdc5d8c 100644 --- a/tools/gnatcov/elf_files.ads +++ b/tools/gnatcov/elf_files.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/controls-test-suite.ads b/tools/gnatcov/examples/aunit_variant/harness/fixture/controls-test-suite.ads index 693485bc2..625a761cd 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/controls-test-suite.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/controls-test-suite.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.adb b/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.adb index e36032c9e..5cb629a49 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.ads b/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.ads index 11289063f..d90d89905 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.adb b/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.adb index a88edb349..ec0f69244 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.ads b/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.ads index a4f09e18d..78e1ed9b5 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/main_suite.adb b/tools/gnatcov/examples/aunit_variant/harness/fixture/main_suite.adb index d3e426290..49332013b 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/main_suite.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/main_suite.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/main_suite.ads b/tools/gnatcov/examples/aunit_variant/harness/fixture/main_suite.ads index 902bac006..517accc2b 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/main_suite.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/main_suite.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.adb b/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.adb index 6ca3517cf..c2b993c2c 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.ads b/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.ads index 8a23ecc08..7d939b2a1 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.adb b/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.adb index 018e1a45e..38a37d88b 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.ads b/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.ads index abf214115..fec422d37 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/test_explore.adb b/tools/gnatcov/examples/aunit_variant/harness/fixture/test_explore.adb index 17dee68e3..a679166a5 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/test_explore.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/test_explore.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/old/test_ports.adb b/tools/gnatcov/examples/aunit_variant/harness/old/test_ports.adb index d2af60a71..c3631649e 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/old/test_ports.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/old/test_ports.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/old/test_queues.adb b/tools/gnatcov/examples/aunit_variant/harness/old/test_queues.adb index 0dd27afbf..44f6522ef 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/old/test_queues.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/old/test_queues.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/old/test_robots.adb b/tools/gnatcov/examples/aunit_variant/harness/old/test_robots.adb index 577340539..84ffb52fa 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/old/test_robots.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/old/test_robots.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/old/test_stacks.adb b/tools/gnatcov/examples/aunit_variant/harness/old/test_stacks.adb index 375fbd682..4dce23841 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/old/test_stacks.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/old/test_stacks.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/actors-test.adb b/tools/gnatcov/examples/aunit_variant/harness/tests/actors-test.adb index 8fbd8256e..c12494f99 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/actors-test.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/actors-test.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/actors-test.ads b/tools/gnatcov/examples/aunit_variant/harness/tests/actors-test.ads index 1ec156ff9..dc7a9bcab 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/actors-test.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/actors-test.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/controls-test.ads b/tools/gnatcov/examples/aunit_variant/harness/tests/controls-test.ads index 5669f1b89..23b4a7dae 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/controls-test.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/controls-test.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.adb b/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.adb index cf04a0e55..8b33bf4b3 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.ads b/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.ads index 2641783d6..01b361b94 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.adb b/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.adb index 317a6792f..e489b6649 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.ads b/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.ads index 48bc48fb3..b164aeff8 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.adb b/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.adb index 21fcc32b2..6fb2d38b4 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.ads b/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.ads index 827505f67..f8ed7018b 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/stations-test.adb b/tools/gnatcov/examples/aunit_variant/harness/tests/stations-test.adb index 997a40f3a..3df16ff17 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/stations-test.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/stations-test.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/stations-test.ads b/tools/gnatcov/examples/aunit_variant/harness/tests/stations-test.ads index 253b72092..4614b3060 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/stations-test.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/stations-test.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/actors.adb b/tools/gnatcov/examples/aunit_variant/src/actors.adb index 5120742a9..96d54c954 100644 --- a/tools/gnatcov/examples/aunit_variant/src/actors.adb +++ b/tools/gnatcov/examples/aunit_variant/src/actors.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/actors.ads b/tools/gnatcov/examples/aunit_variant/src/actors.ads index ffed37048..2ce3dda13 100644 --- a/tools/gnatcov/examples/aunit_variant/src/actors.ads +++ b/tools/gnatcov/examples/aunit_variant/src/actors.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/controls.ads b/tools/gnatcov/examples/aunit_variant/src/controls.ads index 5ea9aa9dc..2377deb3b 100644 --- a/tools/gnatcov/examples/aunit_variant/src/controls.ads +++ b/tools/gnatcov/examples/aunit_variant/src/controls.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/explore.adb b/tools/gnatcov/examples/aunit_variant/src/explore.adb index 242c7b6af..e16f64ab6 100644 --- a/tools/gnatcov/examples/aunit_variant/src/explore.adb +++ b/tools/gnatcov/examples/aunit_variant/src/explore.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/geomaps.adb b/tools/gnatcov/examples/aunit_variant/src/geomaps.adb index 27a271873..2ec3c5f0e 100644 --- a/tools/gnatcov/examples/aunit_variant/src/geomaps.adb +++ b/tools/gnatcov/examples/aunit_variant/src/geomaps.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/geomaps.ads b/tools/gnatcov/examples/aunit_variant/src/geomaps.ads index 068b3419d..3f70704a1 100644 --- a/tools/gnatcov/examples/aunit_variant/src/geomaps.ads +++ b/tools/gnatcov/examples/aunit_variant/src/geomaps.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/links.adb b/tools/gnatcov/examples/aunit_variant/src/links.adb index 225fce1c1..9ee8bb21c 100644 --- a/tools/gnatcov/examples/aunit_variant/src/links.adb +++ b/tools/gnatcov/examples/aunit_variant/src/links.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/links.ads b/tools/gnatcov/examples/aunit_variant/src/links.ads index 9be219fde..986f8d47c 100644 --- a/tools/gnatcov/examples/aunit_variant/src/links.ads +++ b/tools/gnatcov/examples/aunit_variant/src/links.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/overview.ads b/tools/gnatcov/examples/aunit_variant/src/overview.ads index b9e1defe1..b3d19258a 100644 --- a/tools/gnatcov/examples/aunit_variant/src/overview.ads +++ b/tools/gnatcov/examples/aunit_variant/src/overview.ads @@ -1,6 +1,6 @@ ------------------------------------------------------------------------------ -- Couverture/Explore example -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- ------------------------------------------------------------------------------ ------------------------- diff --git a/tools/gnatcov/examples/aunit_variant/src/queues.adb b/tools/gnatcov/examples/aunit_variant/src/queues.adb index 5bef85e80..2792e8a0a 100644 --- a/tools/gnatcov/examples/aunit_variant/src/queues.adb +++ b/tools/gnatcov/examples/aunit_variant/src/queues.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/queues.ads b/tools/gnatcov/examples/aunit_variant/src/queues.ads index ead4fd222..4ac20a203 100644 --- a/tools/gnatcov/examples/aunit_variant/src/queues.ads +++ b/tools/gnatcov/examples/aunit_variant/src/queues.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/robots.adb b/tools/gnatcov/examples/aunit_variant/src/robots.adb index 553305f1d..7b40b847f 100644 --- a/tools/gnatcov/examples/aunit_variant/src/robots.adb +++ b/tools/gnatcov/examples/aunit_variant/src/robots.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/robots.ads b/tools/gnatcov/examples/aunit_variant/src/robots.ads index 579242254..2ee117301 100644 --- a/tools/gnatcov/examples/aunit_variant/src/robots.ads +++ b/tools/gnatcov/examples/aunit_variant/src/robots.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.adb b/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.adb index 9867c401b..1394d0006 100644 --- a/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.adb +++ b/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.ads b/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.ads index 14ea5cd5e..548a2667c 100644 --- a/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.ads +++ b/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/robots_devices.ads b/tools/gnatcov/examples/aunit_variant/src/robots_devices.ads index 4660051f7..4ecbd3df2 100644 --- a/tools/gnatcov/examples/aunit_variant/src/robots_devices.ads +++ b/tools/gnatcov/examples/aunit_variant/src/robots_devices.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/stacks.adb b/tools/gnatcov/examples/aunit_variant/src/stacks.adb index d7b47c3a8..2bad57f2a 100644 --- a/tools/gnatcov/examples/aunit_variant/src/stacks.adb +++ b/tools/gnatcov/examples/aunit_variant/src/stacks.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/stacks.ads b/tools/gnatcov/examples/aunit_variant/src/stacks.ads index bfe62c697..a00cd4aac 100644 --- a/tools/gnatcov/examples/aunit_variant/src/stacks.ads +++ b/tools/gnatcov/examples/aunit_variant/src/stacks.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/stations.adb b/tools/gnatcov/examples/aunit_variant/src/stations.adb index 9417390a2..cd99e0ced 100644 --- a/tools/gnatcov/examples/aunit_variant/src/stations.adb +++ b/tools/gnatcov/examples/aunit_variant/src/stations.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/aunit_variant/src/stations.ads b/tools/gnatcov/examples/aunit_variant/src/stations.ads index 72a4e3ee7..893e76f47 100644 --- a/tools/gnatcov/examples/aunit_variant/src/stations.ads +++ b/tools/gnatcov/examples/aunit_variant/src/stations.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/branch_traces/src/robot.adb b/tools/gnatcov/examples/branch_traces/src/robot.adb index 100de1016..ee0095352 100644 --- a/tools/gnatcov/examples/branch_traces/src/robot.adb +++ b/tools/gnatcov/examples/branch_traces/src/robot.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- ------------------------------------------------------------------------------ diff --git a/tools/gnatcov/examples/branch_traces/src/robot.ads b/tools/gnatcov/examples/branch_traces/src/robot.ads index ddab950fb..f4e00b354 100644 --- a/tools/gnatcov/examples/branch_traces/src/robot.ads +++ b/tools/gnatcov/examples/branch_traces/src/robot.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- ------------------------------------------------------------------------------ diff --git a/tools/gnatcov/examples/branch_traces/src/support.adb b/tools/gnatcov/examples/branch_traces/src/support.adb index b0ea7d16b..31e4f1b6a 100644 --- a/tools/gnatcov/examples/branch_traces/src/support.adb +++ b/tools/gnatcov/examples/branch_traces/src/support.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- ------------------------------------------------------------------------------ diff --git a/tools/gnatcov/examples/branch_traces/src/support.ads b/tools/gnatcov/examples/branch_traces/src/support.ads index 7c584f7a0..19d4f8543 100644 --- a/tools/gnatcov/examples/branch_traces/src/support.ads +++ b/tools/gnatcov/examples/branch_traces/src/support.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- ------------------------------------------------------------------------------ diff --git a/tools/gnatcov/examples/branch_traces/src/test_clear_step.adb b/tools/gnatcov/examples/branch_traces/src/test_clear_step.adb index fd5c92bfa..cc022acbb 100644 --- a/tools/gnatcov/examples/branch_traces/src/test_clear_step.adb +++ b/tools/gnatcov/examples/branch_traces/src/test_clear_step.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- ------------------------------------------------------------------------------ diff --git a/tools/gnatcov/examples/branch_traces/src/test_pit_step.adb b/tools/gnatcov/examples/branch_traces/src/test_pit_step.adb index 5a5004d34..3811ae52b 100644 --- a/tools/gnatcov/examples/branch_traces/src/test_pit_step.adb +++ b/tools/gnatcov/examples/branch_traces/src/test_pit_step.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- ------------------------------------------------------------------------------ diff --git a/tools/gnatcov/examples/branch_traces/src/test_rock_wait.adb b/tools/gnatcov/examples/branch_traces/src/test_rock_wait.adb index 2cb8c8d6b..77e80a890 100644 --- a/tools/gnatcov/examples/branch_traces/src/test_rock_wait.adb +++ b/tools/gnatcov/examples/branch_traces/src/test_rock_wait.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- ------------------------------------------------------------------------------ diff --git a/tools/gnatcov/examples/mcdc_checkpoints/src/assert.adb b/tools/gnatcov/examples/mcdc_checkpoints/src/assert.adb index 5fe9cefb0..3d0260342 100644 --- a/tools/gnatcov/examples/mcdc_checkpoints/src/assert.adb +++ b/tools/gnatcov/examples/mcdc_checkpoints/src/assert.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/examples/mcdc_checkpoints/src/assert.ads b/tools/gnatcov/examples/mcdc_checkpoints/src/assert.ads index f40445c44..9749963c9 100644 --- a/tools/gnatcov/examples/mcdc_checkpoints/src/assert.ads +++ b/tools/gnatcov/examples/mcdc_checkpoints/src/assert.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/examples/mcdc_checkpoints/src/engines.adb b/tools/gnatcov/examples/mcdc_checkpoints/src/engines.adb index 542628af7..e258f56d4 100644 --- a/tools/gnatcov/examples/mcdc_checkpoints/src/engines.adb +++ b/tools/gnatcov/examples/mcdc_checkpoints/src/engines.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/mcdc_checkpoints/src/engines.ads b/tools/gnatcov/examples/mcdc_checkpoints/src/engines.ads index 6e05a0036..e0eb3013c 100644 --- a/tools/gnatcov/examples/mcdc_checkpoints/src/engines.ads +++ b/tools/gnatcov/examples/mcdc_checkpoints/src/engines.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/mcdc_checkpoints/src/test_stable.adb b/tools/gnatcov/examples/mcdc_checkpoints/src/test_stable.adb index 8ad432916..73fd13e26 100644 --- a/tools/gnatcov/examples/mcdc_checkpoints/src/test_stable.adb +++ b/tools/gnatcov/examples/mcdc_checkpoints/src/test_stable.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_p.adb b/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_p.adb index 5b7ea6f01..1a3a8624c 100644 --- a/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_p.adb +++ b/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_p.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_t.adb b/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_t.adb index c2b71197e..2f7fd4324 100644 --- a/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_t.adb +++ b/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_t.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/examples/spark_instrumentation/src/foo.adb b/tools/gnatcov/examples/spark_instrumentation/src/foo.adb index 36f0044ef..a20566e07 100644 --- a/tools/gnatcov/examples/spark_instrumentation/src/foo.adb +++ b/tools/gnatcov/examples/spark_instrumentation/src/foo.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- ------------------------------------------------------------------------------ diff --git a/tools/gnatcov/examples/spark_instrumentation/src/foo.ads b/tools/gnatcov/examples/spark_instrumentation/src/foo.ads index 86d951c65..cafed0af7 100644 --- a/tools/gnatcov/examples/spark_instrumentation/src/foo.ads +++ b/tools/gnatcov/examples/spark_instrumentation/src/foo.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- ------------------------------------------------------------------------------ diff --git a/tools/gnatcov/examples/spark_instrumentation/src/main.adb b/tools/gnatcov/examples/spark_instrumentation/src/main.adb index d6bed2f8a..786c33613 100644 --- a/tools/gnatcov/examples/spark_instrumentation/src/main.adb +++ b/tools/gnatcov/examples/spark_instrumentation/src/main.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- ------------------------------------------------------------------------------ diff --git a/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.adb b/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.adb index faaa767c0..8d2c13af8 100644 --- a/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.adb +++ b/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.ads b/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.ads index 8f108423d..2f6a3c7bd 100644 --- a/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.ads +++ b/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/support/src/last_chance_iSystem-5554/simple_last_chance_handler.adb b/tools/gnatcov/examples/support/src/last_chance_iSystem-5554/simple_last_chance_handler.adb index 4e76d9ac0..21369af9c 100644 --- a/tools/gnatcov/examples/support/src/last_chance_iSystem-5554/simple_last_chance_handler.adb +++ b/tools/gnatcov/examples/support/src/last_chance_iSystem-5554/simple_last_chance_handler.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/support/src/last_chance_iSystem-5554/simple_last_chance_handler.ads b/tools/gnatcov/examples/support/src/last_chance_iSystem-5554/simple_last_chance_handler.ads index 8f108423d..2f6a3c7bd 100644 --- a/tools/gnatcov/examples/support/src/last_chance_iSystem-5554/simple_last_chance_handler.ads +++ b/tools/gnatcov/examples/support/src/last_chance_iSystem-5554/simple_last_chance_handler.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/support/src/last_chance_iSystem-5634/simple_last_chance_handler.adb b/tools/gnatcov/examples/support/src/last_chance_iSystem-5634/simple_last_chance_handler.adb index 4e76d9ac0..21369af9c 100644 --- a/tools/gnatcov/examples/support/src/last_chance_iSystem-5634/simple_last_chance_handler.adb +++ b/tools/gnatcov/examples/support/src/last_chance_iSystem-5634/simple_last_chance_handler.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/support/src/last_chance_iSystem-5634/simple_last_chance_handler.ads b/tools/gnatcov/examples/support/src/last_chance_iSystem-5634/simple_last_chance_handler.ads index 8f108423d..2f6a3c7bd 100644 --- a/tools/gnatcov/examples/support/src/last_chance_iSystem-5634/simple_last_chance_handler.ads +++ b/tools/gnatcov/examples/support/src/last_chance_iSystem-5634/simple_last_chance_handler.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-2024, AdaCore -- -- -- -- Couverture is free software; you can redistribute it and/or modify it -- -- under terms of the GNU General Public License as published by the Free -- diff --git a/tools/gnatcov/examples/support/src/leon-elf/abort.c b/tools/gnatcov/examples/support/src/leon-elf/abort.c index 0c2ae2ab9..786ae5ee1 100644 --- a/tools/gnatcov/examples/support/src/leon-elf/abort.c +++ b/tools/gnatcov/examples/support/src/leon-elf/abort.c @@ -2,7 +2,7 @@ * * * GNATcoverage * * * - * Copyright (C) 2012-2022, AdaCore * + * Copyright (C) 2012-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 * diff --git a/tools/gnatcov/examples/support/src/leon3-elf/abort.c b/tools/gnatcov/examples/support/src/leon3-elf/abort.c index 0c2ae2ab9..fd26e0f21 100644 --- a/tools/gnatcov/examples/support/src/leon3-elf/abort.c +++ b/tools/gnatcov/examples/support/src/leon3-elf/abort.c @@ -2,7 +2,7 @@ * * * GNATcoverage * * * - * Copyright (C) 2012-2022, AdaCore * + * Copyright (C) 2012-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 * @@ -20,7 +20,8 @@ /* Our local last chance handlers for Ada rely on "abort", and this is not part of the standard RTS on leon. */ -void abort (void) +void +abort (void) { - asm ("mov 0, %g1; ta 0"); + asm("mov 0, %g1; ta 0"); } diff --git a/tools/gnatcov/examples/support/src/libsupport.adb b/tools/gnatcov/examples/support/src/libsupport.adb index 7cc72c705..5bc3d7858 100644 --- a/tools/gnatcov/examples/support/src/libsupport.adb +++ b/tools/gnatcov/examples/support/src/libsupport.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/examples/support/src/libsupport.ads b/tools/gnatcov/examples/support/src/libsupport.ads index 047bdfc62..26361f32c 100644 --- a/tools/gnatcov/examples/support/src/libsupport.ads +++ b/tools/gnatcov/examples/support/src/libsupport.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2014-2022, AdaCore -- +-- Copyright (C) 2014-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 -- diff --git a/tools/gnatcov/examples/support/src/memory/libsupport-memory.adb b/tools/gnatcov/examples/support/src/memory/libsupport-memory.adb index 799c9218f..e89e46627 100644 --- a/tools/gnatcov/examples/support/src/memory/libsupport-memory.adb +++ b/tools/gnatcov/examples/support/src/memory/libsupport-memory.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2014-2022, AdaCore -- +-- Copyright (C) 2014-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 -- diff --git a/tools/gnatcov/examples/support/src/memory/libsupport-memory.ads b/tools/gnatcov/examples/support/src/memory/libsupport-memory.ads index cd874429f..917b0d267 100644 --- a/tools/gnatcov/examples/support/src/memory/libsupport-memory.ads +++ b/tools/gnatcov/examples/support/src/memory/libsupport-memory.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2014-2022, AdaCore -- +-- Copyright (C) 2014-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 -- diff --git a/tools/gnatcov/examples/xml/src/services.adb b/tools/gnatcov/examples/xml/src/services.adb index 0f79362f4..7e8c1d13a 100644 --- a/tools/gnatcov/examples/xml/src/services.adb +++ b/tools/gnatcov/examples/xml/src/services.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- Copyright (C) 2009-2024, AdaCore -- -- -- ------------------------------------------------------------------------------ diff --git a/tools/gnatcov/examples/xml/src/services.ads b/tools/gnatcov/examples/xml/src/services.ads index fb98fbb1a..9373a474a 100644 --- a/tools/gnatcov/examples/xml/src/services.ads +++ b/tools/gnatcov/examples/xml/src/services.ads @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- Copyright (C) 2009-2024, AdaCore -- -- -- ------------------------------------------------------------------------------ diff --git a/tools/gnatcov/examples/xml/src/test_services.adb b/tools/gnatcov/examples/xml/src/test_services.adb index e6af3aeba..e96974f04 100644 --- a/tools/gnatcov/examples/xml/src/test_services.adb +++ b/tools/gnatcov/examples/xml/src/test_services.adb @@ -2,7 +2,7 @@ -- -- -- Couverture -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- Copyright (C) 2009-2024, AdaCore -- -- -- ------------------------------------------------------------------------------ diff --git a/tools/gnatcov/execs_dbase.adb b/tools/gnatcov/execs_dbase.adb index c9997358d..edd221b3c 100644 --- a/tools/gnatcov/execs_dbase.adb +++ b/tools/gnatcov/execs_dbase.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/execs_dbase.ads b/tools/gnatcov/execs_dbase.ads index eb4389b80..418c2c7d3 100644 --- a/tools/gnatcov/execs_dbase.ads +++ b/tools/gnatcov/execs_dbase.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/factory_registry.adb b/tools/gnatcov/factory_registry.adb index 264781c7f..7cc31b936 100644 --- a/tools/gnatcov/factory_registry.adb +++ b/tools/gnatcov/factory_registry.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/factory_registry.ads b/tools/gnatcov/factory_registry.ads index bee4c5cd9..ef6a8c751 100644 --- a/tools/gnatcov/factory_registry.ads +++ b/tools/gnatcov/factory_registry.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/files_handling.adb b/tools/gnatcov/files_handling.adb index a94387b46..884a95b3f 100644 --- a/tools/gnatcov/files_handling.adb +++ b/tools/gnatcov/files_handling.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/files_handling.ads b/tools/gnatcov/files_handling.ads index 0f2685526..220c83256 100644 --- a/tools/gnatcov/files_handling.ads +++ b/tools/gnatcov/files_handling.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 3a4d8f7b1..7a6547922 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 87ef8765a..73f0ac5c0 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/gnatcov.adb b/tools/gnatcov/gnatcov.adb index c84d34db6..1c2a1ac62 100644 --- a/tools/gnatcov/gnatcov.adb +++ b/tools/gnatcov/gnatcov.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2021-2022, AdaCore -- +-- Copyright (C) 2021-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 -- diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 4a05c8914..60cbb4248 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/hex_images.adb b/tools/gnatcov/hex_images.adb index ef0e4b8dc..cf3c171bc 100644 --- a/tools/gnatcov/hex_images.adb +++ b/tools/gnatcov/hex_images.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/hex_images.ads b/tools/gnatcov/hex_images.ads index b24c89679..55fd1d0a8 100644 --- a/tools/gnatcov/hex_images.ads +++ b/tools/gnatcov/hex_images.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/highlighting.adb b/tools/gnatcov/highlighting.adb index fc5b9b737..78e3584ed 100644 --- a/tools/gnatcov/highlighting.adb +++ b/tools/gnatcov/highlighting.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2014-2022, AdaCore -- +-- Copyright (C) 2014-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 -- diff --git a/tools/gnatcov/highlighting.ads b/tools/gnatcov/highlighting.ads index 6a517e37f..dd56848b6 100644 --- a/tools/gnatcov/highlighting.ads +++ b/tools/gnatcov/highlighting.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2014-2022, AdaCore -- +-- Copyright (C) 2014-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 -- diff --git a/tools/gnatcov/inputs.adb b/tools/gnatcov/inputs.adb index 12289702f..d98f00831 100644 --- a/tools/gnatcov/inputs.adb +++ b/tools/gnatcov/inputs.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/inputs.ads b/tools/gnatcov/inputs.ads index 301f390b4..c58227091 100644 --- a/tools/gnatcov/inputs.ads +++ b/tools/gnatcov/inputs.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-ada_preprocessing.adb b/tools/gnatcov/instrument-ada_preprocessing.adb index b3e75fe16..3b861d0ba 100644 --- a/tools/gnatcov/instrument-ada_preprocessing.adb +++ b/tools/gnatcov/instrument-ada_preprocessing.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/instrument-ada_preprocessing.ads b/tools/gnatcov/instrument-ada_preprocessing.ads index ec0e3fcf6..efa77c824 100644 --- a/tools/gnatcov/instrument-ada_preprocessing.ads +++ b/tools/gnatcov/instrument-ada_preprocessing.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index fa50015f6..ce7560f60 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 82ac5b1d3..d1f11015f 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-ada_unit__stub.adb b/tools/gnatcov/instrument-ada_unit__stub.adb index 523d98f83..8cc86f06b 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.adb +++ b/tools/gnatcov/instrument-ada_unit__stub.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/instrument-ada_unit__stub.ads b/tools/gnatcov/instrument-ada_unit__stub.ads index 5e03b0619..d799499c1 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.ads +++ b/tools/gnatcov/instrument-ada_unit__stub.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/instrument-ada_unit_provider.adb b/tools/gnatcov/instrument-ada_unit_provider.adb index 879a11c3c..68eccf516 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.adb +++ b/tools/gnatcov/instrument-ada_unit_provider.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/instrument-ada_unit_provider.ads b/tools/gnatcov/instrument-ada_unit_provider.ads index e320e105a..d9947c55a 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.ads +++ b/tools/gnatcov/instrument-ada_unit_provider.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 4ca2d1337..c954a9e32 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 66ccfc712..28761cafb 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-c__stub.adb b/tools/gnatcov/instrument-c__stub.adb index 1b0c5d7f1..638a3be11 100644 --- a/tools/gnatcov/instrument-c__stub.adb +++ b/tools/gnatcov/instrument-c__stub.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2023, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index 6e5de0cf1..95a53c33a 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2023, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index 88c72a30c..c6ce6b56a 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index af3f30e81..8850ea6fe 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index 0f6ef0e22..b99e27772 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-checkpoints.ads b/tools/gnatcov/instrument-checkpoints.ads index 2c6a0b99b..6187b3239 100644 --- a/tools/gnatcov/instrument-checkpoints.ads +++ b/tools/gnatcov/instrument-checkpoints.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-clean_objdirs.adb b/tools/gnatcov/instrument-clean_objdirs.adb index bf43f1d45..57cf336ac 100644 --- a/tools/gnatcov/instrument-clean_objdirs.adb +++ b/tools/gnatcov/instrument-clean_objdirs.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-clean_objdirs.ads b/tools/gnatcov/instrument-clean_objdirs.ads index 8fe9a0098..18b3049b8 100644 --- a/tools/gnatcov/instrument-clean_objdirs.ads +++ b/tools/gnatcov/instrument-clean_objdirs.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 94014e27a..ecd03c01f 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 02e143819..94e7ffab4 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-config.adb b/tools/gnatcov/instrument-config.adb index 34ba19767..9c884a05d 100644 --- a/tools/gnatcov/instrument-config.adb +++ b/tools/gnatcov/instrument-config.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 212604511..72501e909 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-input_traces.ads b/tools/gnatcov/instrument-input_traces.ads index 0dddce1b6..947d6b6f0 100644 --- a/tools/gnatcov/instrument-input_traces.ads +++ b/tools/gnatcov/instrument-input_traces.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument-main.adb b/tools/gnatcov/instrument-main.adb index 134475d8b..4b8c3a569 100644 --- a/tools/gnatcov/instrument-main.adb +++ b/tools/gnatcov/instrument-main.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 2950d1076..7a5b366be 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index 1fb325013..a00ff8421 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/instrument-setup_config.ads b/tools/gnatcov/instrument-setup_config.ads index ab302f54e..c5dd584c5 100644 --- a/tools/gnatcov/instrument-setup_config.ads +++ b/tools/gnatcov/instrument-setup_config.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/instrument-source.adb b/tools/gnatcov/instrument-source.adb index 7b3ab0b41..c20310a11 100644 --- a/tools/gnatcov/instrument-source.adb +++ b/tools/gnatcov/instrument-source.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index eb7c06458..69e1e40eb 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index eeb431366..2aa041062 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/json.adb b/tools/gnatcov/json.adb index 07ea07eee..92d720363 100644 --- a/tools/gnatcov/json.adb +++ b/tools/gnatcov/json.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2022, AdaCore -- +-- Copyright (C) 2022-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 -- diff --git a/tools/gnatcov/json.ads b/tools/gnatcov/json.ads index c9592670c..a9fedfcc2 100644 --- a/tools/gnatcov/json.ads +++ b/tools/gnatcov/json.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2022, AdaCore -- +-- Copyright (C) 2022-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 -- diff --git a/tools/gnatcov/libopcodes_bind/dis_opcodes.ads b/tools/gnatcov/libopcodes_bind/dis_opcodes.ads index ccbe3441e..49e0d2efd 100644 --- a/tools/gnatcov/libopcodes_bind/dis_opcodes.ads +++ b/tools/gnatcov/libopcodes_bind/dis_opcodes.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/libopcodes_bind/dis_stream.c b/tools/gnatcov/libopcodes_bind/dis_stream.c index b97b34284..ab4e8fbff 100644 --- a/tools/gnatcov/libopcodes_bind/dis_stream.c +++ b/tools/gnatcov/libopcodes_bind/dis_stream.c @@ -2,7 +2,7 @@ * * * GNATcoverage * * * - * Copyright (C) 2008-2022, AdaCore * + * Copyright (C) 2008-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 * diff --git a/tools/gnatcov/libopcodes_bind/dis_stream.h b/tools/gnatcov/libopcodes_bind/dis_stream.h index a2e50cf0f..cbbf716f6 100644 --- a/tools/gnatcov/libopcodes_bind/dis_stream.h +++ b/tools/gnatcov/libopcodes_bind/dis_stream.h @@ -2,7 +2,7 @@ * * * GNATcoverage * * * - * Copyright (C) 2008-2022, AdaCore * + * Copyright (C) 2008-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 * diff --git a/tools/gnatcov/libopcodes_bind/dis_wrapper.c b/tools/gnatcov/libopcodes_bind/dis_wrapper.c index b6c442fbd..679e4e14d 100644 --- a/tools/gnatcov/libopcodes_bind/dis_wrapper.c +++ b/tools/gnatcov/libopcodes_bind/dis_wrapper.c @@ -2,7 +2,7 @@ * * * GNATcoverage * * * - * Copyright (C) 2008-2022, AdaCore * + * Copyright (C) 2008-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 * diff --git a/tools/gnatcov/libopcodes_bind/dis_wrapper.h b/tools/gnatcov/libopcodes_bind/dis_wrapper.h index 115b652d6..bef08363d 100644 --- a/tools/gnatcov/libopcodes_bind/dis_wrapper.h +++ b/tools/gnatcov/libopcodes_bind/dis_wrapper.h @@ -2,7 +2,7 @@ * * * GNATcoverage * * * - * Copyright (C) 2008-2022, AdaCore * + * Copyright (C) 2008-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 * diff --git a/tools/gnatcov/logging.adb b/tools/gnatcov/logging.adb index 3514505dd..236101066 100644 --- a/tools/gnatcov/logging.adb +++ b/tools/gnatcov/logging.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/logging.ads b/tools/gnatcov/logging.ads index 83e334592..0fd17d076 100644 --- a/tools/gnatcov/logging.ads +++ b/tools/gnatcov/logging.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/mc_dc.adb b/tools/gnatcov/mc_dc.adb index a798c7948..14da76074 100644 --- a/tools/gnatcov/mc_dc.adb +++ b/tools/gnatcov/mc_dc.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/mc_dc.ads b/tools/gnatcov/mc_dc.ads index 435f889dd..e8d39ac90 100644 --- a/tools/gnatcov/mc_dc.ads +++ b/tools/gnatcov/mc_dc.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/object_locations.adb b/tools/gnatcov/object_locations.adb index b99a0e572..77b74179d 100644 --- a/tools/gnatcov/object_locations.adb +++ b/tools/gnatcov/object_locations.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2014-2022, AdaCore -- +-- Copyright (C) 2014-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 -- diff --git a/tools/gnatcov/object_locations.ads b/tools/gnatcov/object_locations.ads index 51713d98b..5f455760d 100644 --- a/tools/gnatcov/object_locations.ads +++ b/tools/gnatcov/object_locations.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2014-2022, AdaCore -- +-- Copyright (C) 2014-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 -- diff --git a/tools/gnatcov/outputs.adb b/tools/gnatcov/outputs.adb index b8093ec66..552978ef3 100644 --- a/tools/gnatcov/outputs.adb +++ b/tools/gnatcov/outputs.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/outputs.ads b/tools/gnatcov/outputs.ads index 724d30f37..534c36619 100644 --- a/tools/gnatcov/outputs.ads +++ b/tools/gnatcov/outputs.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index 073ba4720..276a1f55a 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2021-2022, AdaCore -- +-- Copyright (C) 2021-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 -- diff --git a/tools/gnatcov/paths.ads b/tools/gnatcov/paths.ads index c67729e7f..93c0e8ae0 100644 --- a/tools/gnatcov/paths.ads +++ b/tools/gnatcov/paths.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2021-2022, AdaCore -- +-- Copyright (C) 2021-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 -- diff --git a/tools/gnatcov/pecoff_files.adb b/tools/gnatcov/pecoff_files.adb index e9d5fc717..b1574f3a5 100644 --- a/tools/gnatcov/pecoff_files.adb +++ b/tools/gnatcov/pecoff_files.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2015-2022, AdaCore -- +-- Copyright (C) 2015-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 -- diff --git a/tools/gnatcov/pecoff_files.ads b/tools/gnatcov/pecoff_files.ads index 0e7c3729a..5db400a7a 100644 --- a/tools/gnatcov/pecoff_files.ads +++ b/tools/gnatcov/pecoff_files.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2015-2022, AdaCore -- +-- Copyright (C) 2015-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 -- diff --git a/tools/gnatcov/perf_counters.adb b/tools/gnatcov/perf_counters.adb index 511002ea0..0eac094ab 100644 --- a/tools/gnatcov/perf_counters.adb +++ b/tools/gnatcov/perf_counters.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/perf_counters.ads b/tools/gnatcov/perf_counters.ads index 7a0f1d98a..bb4af0875 100644 --- a/tools/gnatcov/perf_counters.ads +++ b/tools/gnatcov/perf_counters.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/ppc_descs.adb b/tools/gnatcov/ppc_descs.adb index e253b3c0c..4b2169442 100644 --- a/tools/gnatcov/ppc_descs.adb +++ b/tools/gnatcov/ppc_descs.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/ppc_descs.ads b/tools/gnatcov/ppc_descs.ads index d6ae904db..3f40be288 100644 --- a/tools/gnatcov/ppc_descs.ads +++ b/tools/gnatcov/ppc_descs.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index a35910cee..6c9e23f26 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2012-2022, AdaCore -- +-- Copyright (C) 2012-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 -- diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index ea51b9f7c..592f2a804 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2012-2022, AdaCore -- +-- Copyright (C) 2012-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 -- diff --git a/tools/gnatcov/qemu_traces.ads b/tools/gnatcov/qemu_traces.ads index eaf45426a..12a2dedea 100644 --- a/tools/gnatcov/qemu_traces.ads +++ b/tools/gnatcov/qemu_traces.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/qemu_traces_entries__32.ads b/tools/gnatcov/qemu_traces_entries__32.ads index 2727d93fd..7db527001 100644 --- a/tools/gnatcov/qemu_traces_entries__32.ads +++ b/tools/gnatcov/qemu_traces_entries__32.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/qemu_traces_entries__64.ads b/tools/gnatcov/qemu_traces_entries__64.ads index bda7d9443..a132a26ef 100644 --- a/tools/gnatcov/qemu_traces_entries__64.ads +++ b/tools/gnatcov/qemu_traces_entries__64.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/rts/gcvrt.ads b/tools/gnatcov/rts/gcvrt.ads index 047875429..0d72420db 100644 --- a/tools/gnatcov/rts/gcvrt.ads +++ b/tools/gnatcov/rts/gcvrt.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2023, AdaCore -- +-- Copyright (C) 2023-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-base_io.adb b/tools/gnatcov/rts/gnatcov_rts-base_io.adb index ae46fa21a..4fa5f2e55 100644 --- a/tools/gnatcov/rts/gnatcov_rts-base_io.adb +++ b/tools/gnatcov/rts/gnatcov_rts-base_io.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2023, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-base_io.ads b/tools/gnatcov/rts/gnatcov_rts-base_io.ads index 8032e1462..591cc051e 100644 --- a/tools/gnatcov/rts/gnatcov_rts-base_io.ads +++ b/tools/gnatcov/rts/gnatcov_rts-base_io.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2023, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads index b2260e37d..8185cf969 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2023, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.adb b/tools/gnatcov/rts/gnatcov_rts-buffers.adb index 354483dd7..efb55745f 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.adb +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2023, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index f0483cb46..c44d2f6b2 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2023, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-strings.ads b/tools/gnatcov/rts/gnatcov_rts-strings.ads index e0f9f85e4..ca649c584 100644 --- a/tools/gnatcov/rts/gnatcov_rts-strings.ads +++ b/tools/gnatcov/rts/gnatcov_rts-strings.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2021-2023, AdaCore -- +-- Copyright (C) 2021-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb index b329d9ed1..bd01fcf52 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2023, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads index 4f60936b7..fcd11d2c6 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2023, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb index 31ebeebf8..2e9dc1d5b 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2023, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads index e92b08e20..ecf399931 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2023, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output.ads index 832176101..754769b29 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2023, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces.ads b/tools/gnatcov/rts/gnatcov_rts-traces.ads index a0181e476..80ac3b278 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2022-2023, AdaCore -- +-- Copyright (C) 2022-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts-types.ads b/tools/gnatcov/rts/gnatcov_rts-types.ads index 9ce1379ae..4d6fee41d 100644 --- a/tools/gnatcov/rts/gnatcov_rts-types.ads +++ b/tools/gnatcov/rts/gnatcov_rts-types.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2021-2023, AdaCore -- +-- Copyright (C) 2021-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts.ads b/tools/gnatcov/rts/gnatcov_rts.ads index ca9b500c1..475ebacc7 100644 --- a/tools/gnatcov/rts/gnatcov_rts.ads +++ b/tools/gnatcov/rts/gnatcov_rts.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2023, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/rts/gnatcov_rts_c-base_io.c b/tools/gnatcov/rts/gnatcov_rts_c-base_io.c index 3e68f1026..9de33188f 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-base_io.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-base_io.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2023, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-base_io.h b/tools/gnatcov/rts/gnatcov_rts_c-base_io.h index 0716ef20b..bf0f11fbb 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-base_io.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-base_io.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2023, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c index 48d60797a..953d68170 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2023, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index e1ef95be9..7f6f64cdf 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2023, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.c b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.c index f0150f4c0..900fc2987 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2020-2023, AdaCore * + * Copyright (C) 2020-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h index c2d0cda5d..451082854 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-os_interface.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2020-2023, AdaCore * + * Copyright (C) 2020-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-strings.h b/tools/gnatcov/rts/gnatcov_rts_c-strings.h index 30ff71bef..90324f906 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-strings.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-strings.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2023, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c index 10aeb371c..b483a1bab 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2023, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h index 3dc13f2b4..9d5ab2362 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2023, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c index eae8a38bf..27312de53 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2023, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h index ae0543148..6baffe4cd 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2023, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index fe2d272ba..a8f2ce232 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2023, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h index 3cc71dd81..1e781c858 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2023, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces.c b/tools/gnatcov/rts/gnatcov_rts_c-traces.c index 16b1f5950..2cc782615 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces.c @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2023, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces.h b/tools/gnatcov/rts/gnatcov_rts_c-traces.h index 33664a30d..cfb7e4b30 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces.h @@ -2,7 +2,7 @@ * * * GNATcoverage Instrumentation Runtime * * * - * Copyright (C) 2021-2023, AdaCore * + * Copyright (C) 2021-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 * diff --git a/tools/gnatcov/rundrv-config.adb b/tools/gnatcov/rundrv-config.adb index b4d4c4b6c..181c6213f 100644 --- a/tools/gnatcov/rundrv-config.adb +++ b/tools/gnatcov/rundrv-config.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2016-2022, AdaCore -- +-- Copyright (C) 2016-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 -- diff --git a/tools/gnatcov/rundrv-config.ads b/tools/gnatcov/rundrv-config.ads index f2813ae7b..2c3fe9392 100644 --- a/tools/gnatcov/rundrv-config.ads +++ b/tools/gnatcov/rundrv-config.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/rundrv-handlers.adb b/tools/gnatcov/rundrv-handlers.adb index 78add4f84..61edcf0ed 100644 --- a/tools/gnatcov/rundrv-handlers.adb +++ b/tools/gnatcov/rundrv-handlers.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2016-2022, AdaCore -- +-- Copyright (C) 2016-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 -- diff --git a/tools/gnatcov/rundrv-handlers.ads b/tools/gnatcov/rundrv-handlers.ads index 5b0dfabb3..b8d01ef0d 100644 --- a/tools/gnatcov/rundrv-handlers.ads +++ b/tools/gnatcov/rundrv-handlers.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2016-2022, AdaCore -- +-- Copyright (C) 2016-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 -- diff --git a/tools/gnatcov/rundrv.adb b/tools/gnatcov/rundrv.adb index b61afc2ef..29cf5ebe3 100644 --- a/tools/gnatcov/rundrv.adb +++ b/tools/gnatcov/rundrv.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/rundrv.ads b/tools/gnatcov/rundrv.ads index 54b54afcd..726c4d1fd 100644 --- a/tools/gnatcov/rundrv.ads +++ b/tools/gnatcov/rundrv.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/sc_obligations-bdd.adb b/tools/gnatcov/sc_obligations-bdd.adb index 93a55365f..08398d161 100644 --- a/tools/gnatcov/sc_obligations-bdd.adb +++ b/tools/gnatcov/sc_obligations-bdd.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/sc_obligations-bdd.ads b/tools/gnatcov/sc_obligations-bdd.ads index 1b0cdae5d..444f87faa 100644 --- a/tools/gnatcov/sc_obligations-bdd.ads +++ b/tools/gnatcov/sc_obligations-bdd.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 49fff7540..360ed385b 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 8199f7173..c84570559 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 8649f2313..801cc4302 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2022, AdaCore -- +-- Copyright (C) 2022-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 -- diff --git a/tools/gnatcov/setup_rts.ads b/tools/gnatcov/setup_rts.ads index 4f6d61cef..47e406607 100644 --- a/tools/gnatcov/setup_rts.ads +++ b/tools/gnatcov/setup_rts.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2022, AdaCore -- +-- Copyright (C) 2022-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 -- diff --git a/tools/gnatcov/slocs.adb b/tools/gnatcov/slocs.adb index 080e9a222..e80d0a0e0 100644 --- a/tools/gnatcov/slocs.adb +++ b/tools/gnatcov/slocs.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/slocs.ads b/tools/gnatcov/slocs.ads index 0c1ab727b..57d004c7a 100644 --- a/tools/gnatcov/slocs.ads +++ b/tools/gnatcov/slocs.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/sparc_descs.ads b/tools/gnatcov/sparc_descs.ads index bf49fc8da..26d99d306 100644 --- a/tools/gnatcov/sparc_descs.ads +++ b/tools/gnatcov/sparc_descs.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/strings.adb b/tools/gnatcov/strings.adb index 047d1dc69..9d6a9c8ce 100644 --- a/tools/gnatcov/strings.adb +++ b/tools/gnatcov/strings.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/strings.ads b/tools/gnatcov/strings.ads index 9b322479d..f28db22f4 100644 --- a/tools/gnatcov/strings.ads +++ b/tools/gnatcov/strings.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 4fdda92ad..ca37794a7 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/subprocesses.ads b/tools/gnatcov/subprocesses.ads index 1e9da6c36..38e871eae 100644 --- a/tools/gnatcov/subprocesses.ads +++ b/tools/gnatcov/subprocesses.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/support_files.ads b/tools/gnatcov/support_files.ads index 792ddd0d4..3fce99eb6 100644 --- a/tools/gnatcov/support_files.ads +++ b/tools/gnatcov/support_files.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2020-2022, AdaCore -- +-- Copyright (C) 2020-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 -- diff --git a/tools/gnatcov/swaps.adb b/tools/gnatcov/swaps.adb index 7f785889f..58673e5f3 100644 --- a/tools/gnatcov/swaps.adb +++ b/tools/gnatcov/swaps.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/swaps.ads b/tools/gnatcov/swaps.ads index 625ae6569..a54f2f3fc 100644 --- a/tools/gnatcov/swaps.ads +++ b/tools/gnatcov/swaps.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 925d2ae97..f0df0a7bb 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 0b3f9cdd4..90a7bccb4 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/symbols.adb b/tools/gnatcov/symbols.adb index d18aeabcb..cc9a7441f 100644 --- a/tools/gnatcov/symbols.adb +++ b/tools/gnatcov/symbols.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/symbols.ads b/tools/gnatcov/symbols.ads index 2450c0353..f632118fa 100644 --- a/tools/gnatcov/symbols.ads +++ b/tools/gnatcov/symbols.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/temp_dirs.adb b/tools/gnatcov/temp_dirs.adb index 1f2ff0361..f06ba3a41 100644 --- a/tools/gnatcov/temp_dirs.adb +++ b/tools/gnatcov/temp_dirs.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2022, AdaCore -- +-- Copyright (C) 2022-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 -- diff --git a/tools/gnatcov/temp_dirs.ads b/tools/gnatcov/temp_dirs.ads index fb93eb1f6..9dcc4d029 100644 --- a/tools/gnatcov/temp_dirs.ads +++ b/tools/gnatcov/temp_dirs.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2022, AdaCore -- +-- Copyright (C) 2022-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 -- diff --git a/tools/gnatcov/text_files.adb b/tools/gnatcov/text_files.adb index f506c9dd5..2e4a21a43 100644 --- a/tools/gnatcov/text_files.adb +++ b/tools/gnatcov/text_files.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/text_files.ads b/tools/gnatcov/text_files.ads index 2a45b687f..9a1f2a298 100644 --- a/tools/gnatcov/text_files.ads +++ b/tools/gnatcov/text_files.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/trace_adapters/nexus/isys2nex.adb b/tools/gnatcov/trace_adapters/nexus/isys2nex.adb index a9839f3be..11deb9efb 100755 --- a/tools/gnatcov/trace_adapters/nexus/isys2nex.adb +++ b/tools/gnatcov/trace_adapters/nexus/isys2nex.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/trace_adapters/nexus/isys2nex.ads b/tools/gnatcov/trace_adapters/nexus/isys2nex.ads index db74ea1c4..1b6e265d5 100644 --- a/tools/gnatcov/trace_adapters/nexus/isys2nex.ads +++ b/tools/gnatcov/trace_adapters/nexus/isys2nex.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/trace_adapters/nexus/isys_drv.adb b/tools/gnatcov/trace_adapters/nexus/isys_drv.adb index d6bcf78ae..1c08ee2b5 100644 --- a/tools/gnatcov/trace_adapters/nexus/isys_drv.adb +++ b/tools/gnatcov/trace_adapters/nexus/isys_drv.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2012-2022, AdaCore -- +-- Copyright (C) 2012-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 -- diff --git a/tools/gnatcov/trace_adapters/nexus/nexus_rep.ads b/tools/gnatcov/trace_adapters/nexus/nexus_rep.ads index 84a35b08c..07741e8a9 100755 --- a/tools/gnatcov/trace_adapters/nexus/nexus_rep.ads +++ b/tools/gnatcov/trace_adapters/nexus/nexus_rep.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/trace_adapters/nexus/nexus_trace_gen.adb b/tools/gnatcov/trace_adapters/nexus/nexus_trace_gen.adb index 36265cb8e..42da76dc6 100755 --- a/tools/gnatcov/trace_adapters/nexus/nexus_trace_gen.adb +++ b/tools/gnatcov/trace_adapters/nexus/nexus_trace_gen.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/trace_adapters/trace32/instructions_info.adb b/tools/gnatcov/trace_adapters/trace32/instructions_info.adb index 29d93fe3b..a857cead5 100644 --- a/tools/gnatcov/trace_adapters/trace32/instructions_info.adb +++ b/tools/gnatcov/trace_adapters/trace32/instructions_info.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/trace_adapters/trace32/instructions_info.ads b/tools/gnatcov/trace_adapters/trace32/instructions_info.ads index 892d2db6e..0329e228e 100644 --- a/tools/gnatcov/trace_adapters/trace32/instructions_info.ads +++ b/tools/gnatcov/trace_adapters/trace32/instructions_info.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.adb b/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.adb index 87889e9f9..25d76738c 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.adb +++ b/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.ads b/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.ads index d23145243..9d30b536d 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.ads +++ b/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/trace_adapters/trace32/trace32-conversion.adb b/tools/gnatcov/trace_adapters/trace32/trace32-conversion.adb index 8d4fff4f5..06c3a0c25 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace32-conversion.adb +++ b/tools/gnatcov/trace_adapters/trace32/trace32-conversion.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/trace_adapters/trace32/trace32-conversion.ads b/tools/gnatcov/trace_adapters/trace32/trace32-conversion.ads index 609a13972..d4039f14f 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace32-conversion.ads +++ b/tools/gnatcov/trace_adapters/trace32/trace32-conversion.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/trace_adapters/trace32/trace32.ads b/tools/gnatcov/trace_adapters/trace32/trace32.ads index 157f0f09a..ac38966d1 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace32.ads +++ b/tools/gnatcov/trace_adapters/trace32/trace32.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/trace_adapters/trace32/trace32_drv.adb b/tools/gnatcov/trace_adapters/trace32/trace32_drv.adb index ad793b90b..e28aa6253 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace32_drv.adb +++ b/tools/gnatcov/trace_adapters/trace32/trace32_drv.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2012-2022, AdaCore -- +-- Copyright (C) 2012-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 -- diff --git a/tools/gnatcov/trace_adapters/trace32/trace_output.adb b/tools/gnatcov/trace_adapters/trace32/trace_output.adb index b3283e0e9..d454d9f95 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace_output.adb +++ b/tools/gnatcov/trace_adapters/trace32/trace_output.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/trace_adapters/trace32/trace_output.ads b/tools/gnatcov/trace_adapters/trace32/trace_output.ads index 3396987dc..7bed11c60 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace_output.ads +++ b/tools/gnatcov/trace_adapters/trace32/trace_output.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2017-2022, AdaCore -- +-- Copyright (C) 2017-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 -- diff --git a/tools/gnatcov/traces.adb b/tools/gnatcov/traces.adb index f73bee73a..b7a3c8493 100644 --- a/tools/gnatcov/traces.adb +++ b/tools/gnatcov/traces.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces.ads b/tools/gnatcov/traces.ads index b803b697e..0a535fab8 100644 --- a/tools/gnatcov/traces.ads +++ b/tools/gnatcov/traces.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_dbase.adb b/tools/gnatcov/traces_dbase.adb index 0a4ac7673..cb2561c7e 100644 --- a/tools/gnatcov/traces_dbase.adb +++ b/tools/gnatcov/traces_dbase.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_dbase.ads b/tools/gnatcov/traces_dbase.ads index e958e9077..ea74a7ceb 100644 --- a/tools/gnatcov/traces_dbase.ads +++ b/tools/gnatcov/traces_dbase.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_disa.adb b/tools/gnatcov/traces_disa.adb index ff4ec5ffb..939594eaf 100644 --- a/tools/gnatcov/traces_disa.adb +++ b/tools/gnatcov/traces_disa.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_disa.ads b/tools/gnatcov/traces_disa.ads index 683883377..c01e32944 100644 --- a/tools/gnatcov/traces_disa.ads +++ b/tools/gnatcov/traces_disa.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_dump.adb b/tools/gnatcov/traces_dump.adb index 67673b2ec..fbc7b8206 100644 --- a/tools/gnatcov/traces_dump.adb +++ b/tools/gnatcov/traces_dump.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_dump.ads b/tools/gnatcov/traces_dump.ads index d85937083..942e57aa6 100644 --- a/tools/gnatcov/traces_dump.ads +++ b/tools/gnatcov/traces_dump.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/traces_elf.adb b/tools/gnatcov/traces_elf.adb index deaf1fa2a..b0a4529e2 100644 --- a/tools/gnatcov/traces_elf.adb +++ b/tools/gnatcov/traces_elf.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_elf.ads b/tools/gnatcov/traces_elf.ads index 80efd226f..6ce99049f 100644 --- a/tools/gnatcov/traces_elf.ads +++ b/tools/gnatcov/traces_elf.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_files.adb b/tools/gnatcov/traces_files.adb index 3b3009d11..0e0de600e 100644 --- a/tools/gnatcov/traces_files.adb +++ b/tools/gnatcov/traces_files.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_files.ads b/tools/gnatcov/traces_files.ads index c0f20daae..0bad472eb 100644 --- a/tools/gnatcov/traces_files.ads +++ b/tools/gnatcov/traces_files.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_files_registry.adb b/tools/gnatcov/traces_files_registry.adb index e2d42eb47..dfddc9e0e 100644 --- a/tools/gnatcov/traces_files_registry.adb +++ b/tools/gnatcov/traces_files_registry.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_files_registry.ads b/tools/gnatcov/traces_files_registry.ads index 85f306f8b..2ea1b0df1 100644 --- a/tools/gnatcov/traces_files_registry.ads +++ b/tools/gnatcov/traces_files_registry.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_lines.adb b/tools/gnatcov/traces_lines.adb index 0e2e826f2..c9896c893 100644 --- a/tools/gnatcov/traces_lines.adb +++ b/tools/gnatcov/traces_lines.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2009-2022, AdaCore -- +-- 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 -- diff --git a/tools/gnatcov/traces_lines.ads b/tools/gnatcov/traces_lines.ads index 8e0f62753..9c707755c 100644 --- a/tools/gnatcov/traces_lines.ads +++ b/tools/gnatcov/traces_lines.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_names.adb b/tools/gnatcov/traces_names.adb index fc7c947e9..509fc30f8 100644 --- a/tools/gnatcov/traces_names.adb +++ b/tools/gnatcov/traces_names.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_names.ads b/tools/gnatcov/traces_names.ads index ec2fc70dc..e98c61184 100644 --- a/tools/gnatcov/traces_names.ads +++ b/tools/gnatcov/traces_names.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_source.adb b/tools/gnatcov/traces_source.adb index 6e9a6feab..4395e44d7 100644 --- a/tools/gnatcov/traces_source.adb +++ b/tools/gnatcov/traces_source.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage Instrumentation Runtime -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/traces_source.ads b/tools/gnatcov/traces_source.ads index ce7776bd5..644bf2595 100644 --- a/tools/gnatcov/traces_source.ads +++ b/tools/gnatcov/traces_source.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2019-2022, AdaCore -- +-- Copyright (C) 2019-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 -- diff --git a/tools/gnatcov/traces_stats.adb b/tools/gnatcov/traces_stats.adb index 6907f2b24..788735537 100644 --- a/tools/gnatcov/traces_stats.adb +++ b/tools/gnatcov/traces_stats.adb @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/traces_stats.ads b/tools/gnatcov/traces_stats.ads index 7ddfe1f00..d159853da 100644 --- a/tools/gnatcov/traces_stats.ads +++ b/tools/gnatcov/traces_stats.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2008-2022, AdaCore -- +-- Copyright (C) 2008-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 -- diff --git a/tools/gnatcov/version.ads b/tools/gnatcov/version.ads index d15461af1..5e7f4e795 100644 --- a/tools/gnatcov/version.ads +++ b/tools/gnatcov/version.ads @@ -2,7 +2,7 @@ -- -- -- GNATcoverage -- -- -- --- Copyright (C) 2006-2022, AdaCore -- +-- Copyright (C) 2006-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 -- diff --git a/tools/gnatcov/zlib_helpers.c b/tools/gnatcov/zlib_helpers.c index aa1905859..2a651f71b 100644 --- a/tools/gnatcov/zlib_helpers.c +++ b/tools/gnatcov/zlib_helpers.c @@ -2,7 +2,7 @@ * * * GNATcoverage * * * - * Copyright (C) 2017-2022, AdaCore * + * Copyright (C) 2017-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 * From 786b34005168ab1c342a33fce2b570aba548437a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 12 Jan 2024 16:08:26 +0000 Subject: [PATCH 0619/1483] instrument-projects.adb: remove useless calls to .Copy Standard containers have by-value semantics: assignment creates an implicit copy, and so `Foo := Bar.Copy` will actually create (1) a first transient copy (`Bar.Copy`), and then (2) create a copy of (2) to assign it to `Foo`. Remove that extra copy and simplify the code accordingly. --- tools/gnatcov/instrument-projects.adb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 7a5b366be..ebadcae1a 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -1240,8 +1240,7 @@ begin (Common_Switches (Cmd_Instrument_Source)); for Cur in Instrumented_Sources.Iterate loop declare - Unit_Args : String_Vectors.Vector := - Instrument_Source_Args.Copy; + Unit_Args : String_Vectors.Vector := Instrument_Source_Args; -- Args specific to a gnatcov instrument-source invocation -- (e.g. the common arguments + the sources that must be -- instrumented for a specific unit). @@ -1373,8 +1372,7 @@ begin when Unit_Based_Language => To_Ada (Main.CU_Name.Unit), when File_Based_Language => (+Main.File.Full_Name)); - Unit_Args : String_Vectors.Vector := - Instrument_Main_Args.Copy; + Unit_Args : String_Vectors.Vector := Instrument_Main_Args; begin Unit_Args.Append (Compilation_Unit_Options @@ -1410,8 +1408,7 @@ begin when Unit_Based_Language => To_Ada (Main.CU_Name.Unit), when File_Based_Language => (+Main.File.Full_Name)); - Unit_Args : String_Vectors.Vector := - Instrument_Main_Args.Copy; + Unit_Args : String_Vectors.Vector := Instrument_Main_Args; begin Unit_Args.Append (Compilation_Unit_Options From 10beeeea1c6807d23837062216745412ac92e0b6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 12 Jan 2024 12:23:21 +0000 Subject: [PATCH 0620/1483] Instrument.C: fix main instr. error message for missing C/C++ compiler --- testsuite/tests/instr-cov/no-compiler/main.c | 7 +++++ testsuite/tests/instr-cov/no-compiler/pkg.adb | 10 +++++++ testsuite/tests/instr-cov/no-compiler/pkg.ads | 4 +++ testsuite/tests/instr-cov/no-compiler/test.py | 28 +++++++++++++++++-- tools/gnatcov/instrument-c.adb | 2 ++ 5 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/instr-cov/no-compiler/pkg.adb create mode 100644 testsuite/tests/instr-cov/no-compiler/pkg.ads diff --git a/testsuite/tests/instr-cov/no-compiler/main.c b/testsuite/tests/instr-cov/no-compiler/main.c index 398ec675a..881f7b1aa 100644 --- a/testsuite/tests/instr-cov/no-compiler/main.c +++ b/testsuite/tests/instr-cov/no-compiler/main.c @@ -1,5 +1,12 @@ +extern void adainit (void); +extern void adafinal (void); +extern void pkg_foo (void); + int main (void) { + adainit (); + pkg_foo (); + adafinal (); return 0; } diff --git a/testsuite/tests/instr-cov/no-compiler/pkg.adb b/testsuite/tests/instr-cov/no-compiler/pkg.adb new file mode 100644 index 000000000..37b06eefa --- /dev/null +++ b/testsuite/tests/instr-cov/no-compiler/pkg.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Foo is + begin + Put_Line ("Ada"); + end Foo; + +end Pkg; diff --git a/testsuite/tests/instr-cov/no-compiler/pkg.ads b/testsuite/tests/instr-cov/no-compiler/pkg.ads new file mode 100644 index 000000000..35a997406 --- /dev/null +++ b/testsuite/tests/instr-cov/no-compiler/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + procedure Foo; + pragma Export (C, Foo, "pkg_foo"); +end Pkg; diff --git a/testsuite/tests/instr-cov/no-compiler/test.py b/testsuite/tests/instr-cov/no-compiler/test.py index 19d641520..b65e2c74d 100644 --- a/testsuite/tests/instr-cov/no-compiler/test.py +++ b/testsuite/tests/instr-cov/no-compiler/test.py @@ -36,11 +36,14 @@ # Avoid noisy "creating output path" messages mkdir("obj") +gpr = GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])) + # Now run the instrumenter on a C project with this configuration file and # check the error message. -output = "instr.log" +thistest.log("== Instrument all ==") +output = "instr_0.log" p = xcov_instrument( - gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + gprsw=gpr, covlevel="stmt", extra_args=[f"--config={config_file}"], out=output, @@ -55,4 +58,25 @@ contents_of(output).strip(), ) + +# Likewise, but this time with only Ada units that can be of interest: the C +# source will be instrumented as a main only. +thistest.log("== Instrument Ada only ==") +output = "instr_1.log" +p = xcov_instrument( + gprsw=gpr, + covlevel="stmt", + extra_args=[f"--config={config_file}", "--restricted-to-languages=Ada"], + out=output, + auto_config_args=False, + auto_target_args=False, + register_failure=False, +) +thistest.fail_if_not_equal("'gnatcov instrument' exit code", 1, p.status) +thistest.fail_if_no_match( + "'gnatcov instrument' output", + ".*gnatcov.*: could not find a compiler for C", + contents_of(output).strip(), +) + thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index c954a9e32..b325ee04c 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -4020,6 +4020,8 @@ package body Instrument.C is Main_Cursor : Cursor_T; -- Cursor of the main declaration begin + Check_Compiler_Driver (Prj, Self); + Rew.Start_Rewriting (Filename, Self, Prj); Insert_Extern_Location := From 79cbb2c5fde0014e327a73599647f812ba44f1ac Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 12 Jan 2024 13:18:46 +0000 Subject: [PATCH 0621/1483] command_lines.ads: clarify doc for --restricted-to-languages --- tools/gnatcov/command_line.ads | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index b35cfd69c..1f2aa55ea 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -1349,8 +1349,9 @@ package Command_Line is (Long_Name => "--restricted-to-languages", Pattern => "[LANGUAGE|LIST|@LISTFILE]", Help => - "Restrict the set of languages for instrumentation. Supports Ada, C" - & " and C++.", + "Restrict the set of languages for units of interest. Supports Ada," + & " C and C++. Note that main units of other languages may still be" + & " instrumented to dump the coverage state to trace files.", Commands => (Cmd_Setup | Cmd_Instrument_Project => True, others => False), From b05e895ad36611e0ce74d399a6f13ef2a43f3942 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 15 Jan 2024 13:19:17 +0000 Subject: [PATCH 0622/1483] Harmonize TODO style in comments --- tools/gnatcov/files_table.adb | 2 +- tools/gnatcov/gnatcov_bits_specific.adb | 2 +- tools/gnatcov/instrument-ada_unit.adb | 2 +- tools/gnatcov/instrument-c.adb | 8 ++++---- tools/gnatcov/instrument-gcc_wrapper.adb | 8 ++++---- tools/gnatcov/instrument-projects.adb | 3 +-- tools/gnatcov/instrument-setup_config.adb | 10 ++++----- tools/gnatcov/sc_obligations.adb | 25 +++++++++++------------ tools/gnatcov/subprocesses.adb | 2 +- 9 files changed, 30 insertions(+), 32 deletions(-) diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 7a6547922..7cd2d789f 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -1534,7 +1534,7 @@ package body Files_Table is Try_Open (File, Name.all, Success); - -- TODO???: the FI.Full_Name can only be null in binary traces, when + -- TODO??? The FI.Full_Name can only be null in binary traces, when -- loading SCOs from a library file while there is no debug info for the -- corresponding SCOs. Remove the code below and check that FI.Full_Name -- is not null if / when binary traces are deprecated. diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 60cbb4248..b6b063af2 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1380,7 +1380,7 @@ begin "", Value (Args, Opt_Config), Runtime_Project); - -- TODO???: we should not leave the target and runtime empty, but + -- TODO??? We should not leave the target and runtime empty, but -- we have no project to load here. Dump_Config : constant Any_Dump_Config := diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index ce7560f60..d0097eae2 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6769,7 +6769,7 @@ package body Instrument.Ada_Unit is File_Reader => Instrumenter.File_Reader); Instrumenter.Get_From_File_Count := 0; - -- Load configuration pragmas. TODO???: clarify what happens when there + -- Load configuration pragmas. TODO??? Clarify what happens when there -- is a local configuration pragma file. Libadalang.Config_Pragmas.Set_Mapping diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index b325ee04c..dc2dadb1f 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -727,7 +727,7 @@ package body Instrument.C is return; end if; - -- TODO??? the actual source range should be a Source_Location, and not + -- TODO??? The actual source range should be a Source_Location, and not -- a Local_Source_Location as it can refer to #included files. Info.Actual_Source_Range := (From.L, To.L); @@ -2205,7 +2205,7 @@ package body Instrument.C is when Cursor_Null_Stmt => null; - -- TODO??? there are probably missing special statements, such as + -- TODO??? There are probably missing special statements, such as -- ternary operator etc. Do that in a later step. when Cursor_Call_Expr => @@ -2531,7 +2531,7 @@ package body Instrument.C is Args.Append (+L); else -- Add the -quiet switch to prevent the compiler from outputting - -- execution time statistics. TODO??? check whether this is compiler + -- execution time statistics. TODO??? Check whether this is compiler -- specific (cc1 / cc1plus) when implementing integrated -- instrumentation support for other compilers. @@ -4650,7 +4650,7 @@ package body Instrument.C is end if; -- Consider that File is of interest iff it belongs to a loaded - -- project. TODO???: this should also consider units of interest + -- project. TODO??? This should also consider units of interest -- switches. if UIC.Files_Of_Interest.Contains (File) then diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 95ac49818..7a47e197c 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -312,7 +312,7 @@ is Commands_Filename : constant String := Tmp_Dir.Directory_Name / "commands"; begin - -- Expand the command line using gcc's -### option. TODO??? check if the + -- Expand the command line using gcc's -### option. TODO??? Check if the -- command we are intercepting is a compile / link target and not a -- preprocessing / -### action. @@ -424,7 +424,7 @@ is if +Arg in "-dumpbase" | "-dumpbase-ext" then Cur := Next (Cur); - -- TODO??? the user can configure the file extension and the + -- TODO??? The user can configure the file extension and the -- implementation should be resilient to this. elsif Ends_With (Arg, ".c") @@ -600,7 +600,7 @@ is Args.Append (Full_Name (Symbol_File)); -- The command can fail with e.g. "file format not recognized" for - -- system libraries. TODO??? investigate why. We should also avoid + -- system libraries. TODO??? Investigate why. We should also avoid -- invoking nm on system libraries altogether. Ignore_Success := @@ -830,7 +830,7 @@ begin Unit_Name => Fullname, -- Generate all the SID files under the same directory as the - -- compiler wrapper as they must persist. TODO??? deal with + -- compiler wrapper as they must persist. TODO??? Deal with -- homonym files in SID names. SID_Name => Compiler_Wrapper_Dir / (Simple_Name & ".sid")); diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index ebadcae1a..cf9c395a8 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -1065,8 +1065,7 @@ begin end loop; -- Remove all of the separate whose parent unit was not instrumented, as - -- this is not supported. TODO???: we should probably issue a warning - -- there. + -- this is not supported. TODO??? We should probably issue a warning there. for Source of Files_Of_Interest_Info.Copy loop if Source.Unit_Part = GNATCOLL.Projects.Unit_Separate then diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index a00ff8421..4a6d96de8 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -121,8 +121,8 @@ package body Instrument.Setup_Config is -- For each compiler driver, location of the nm executable begin - -- Find the installed gnatcov_rts, using gprls. TODO???: deal with non - -- native cases. + -- Find the installed gnatcov_rts, using gprls. TODO??? Deal with cross + -- cases. -- -- We are looking for the following lines: -- Source Search Path: @@ -225,8 +225,8 @@ package body Instrument.Setup_Config is (+Compiler_Driver, Compiler_Fullname.all); -- Then, find the linker associated to this compiler. Look - -- for ld / ld.bfd. TODO???: this may need reworking when - -- we want to support toolchain other than ours, not + -- for ld / ld.bfd. TODO??? This may need reworking when we + -- want to support toolchain other than ours, not -- necessarily packaging ld. declare @@ -244,7 +244,7 @@ package body Instrument.Setup_Config is end; -- Do the same with nm, as we need to be able to inspect the - -- object / library file contents. TODO???: this may need + -- object / library file contents. TODO??? This may need -- reworking when we want to support toolchain other than -- ours, not necessarily packaging nm. diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 360ed385b..080edb343 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -4075,20 +4075,19 @@ package body SC_Obligations is if (Enclosing_SCO /= No_SCO_Id and then Equivalent (SCOD, SCO_Vector (Enclosing_SCO))) - - -- The only form of SCO overlapping we allow is - -- SCO nesting. A statement can contain nested - -- statements, e.g. with C++ lambda expressions. - -- We reject every other kind of overlapping. + -- The only form of SCO overlapping we allow is SCO + -- nesting. A statement can contain nested statements, + -- e.g. with C++ lambda expressions. We reject every + -- other kind of overlapping. -- - -- TODO???: with C headers, we can have multiple - -- times the same SCO if the header is included - -- multiple times. This will result in a buggy - -- behavior if the included code expansion varies (as - -- we may accept nested SCO that come from the second - -- inclusion, but that are nested in a SCO from the - -- first inclusion, which makes no sense). Consider - -- this as a marginal use case for now. + -- TODO??? With C headers, we can have multiple times + -- the same SCO if the header is included multiple + -- times. This will result in a buggy behavior if the + -- included code expansion varies (as we may accept + -- nested SCO that come from the second inclusion, but + -- that are nested in a SCO from the first inclusion, + -- which makes no sense). Consider this as a marginal + -- use case for now. or else Invalid_Overlap (SCOD, Enclosing_SCO) or else Invalid_Overlap diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index ca37794a7..f82902fd3 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -482,7 +482,7 @@ package body Subprocesses is Environment, +Pool.Process_Infos (Id).Output_File, - -- TODO??? there will be mangling on the stderr if stdout was + -- TODO??? There will be mangling on the stderr if stdout was -- redirected to an output file. Err_To_Out => Output_File = "", From 3bf223e79f9be71c544b4fcbfe998a60a3ca0c70 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 12 Jan 2024 12:46:31 +0000 Subject: [PATCH 0623/1483] Instrument: show progress for the instrumentation of mains This is useful in general as feedback for users, but will also help identifying the main that is causing trouble in case of a gnatcov bug. --- testsuite/tests/129-instr-progress/test.py | 32 +++++++++++++++++----- tools/gnatcov/instrument-projects.adb | 21 +++++++++----- 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/testsuite/tests/129-instr-progress/test.py b/testsuite/tests/129-instr-progress/test.py index 0b220960f..e9e1f518f 100644 --- a/testsuite/tests/129-instr-progress/test.py +++ b/testsuite/tests/129-instr-progress/test.py @@ -3,6 +3,7 @@ instrumented units. """ +import dataclasses import os import os.path @@ -45,22 +46,39 @@ cwd="xcov", ) + # Units are not instrumented in a particular order: we only want to check that # all of them are listed with the expected formatting. -output = lines_of("instrument.log") -thistest.fail_if_not_equal( - "First line of 'gnatcov instrument' output", - "".join(output[:1]), - "Coverage instrumentation", -) +@dataclasses.dataclass +class Section: + label: str + lines: list[str] + + +sections = [Section("", [])] +for line in lines_of("instrument.log"): + if line.startswith(" "): + sections[-1].lines.append(line) + else: + sections.append(Section(line, [])) + +sorted_lines = [] +for section in sections: + sorted_lines.append(section.label) + sorted_lines += sorted(section.lines) + thistest.fail_if_not_equal( "'gnatcov instrument' output", "\n".join([ + "", + "Coverage instrumentation", " [Ada] main", " [C++] cpp_unit.cpp", " [C] c_unit.c", + "Main instrumentation", + " [Ada] main", ]), - "\n".join(sorted(output[1:])), + "\n".join(sorted_lines), ) thistest.result() diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index cf9c395a8..af2510e1e 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -1352,6 +1352,8 @@ begin -- the main in the project file, if not specified explicitly on the -- command line. + First_Main : Boolean := True; + -- Whether the next main to instrument is the first one begin Instrument_Main_Args.Append (+"instrument-main"); @@ -1402,19 +1404,24 @@ begin if Dump_Config.Trigger /= Manual then declare - Unit_Name : constant Unbounded_String := - +(case Main.CU_Name.Language_Kind is - when Unit_Based_Language => - To_Ada (Main.CU_Name.Unit), - when File_Based_Language => (+Main.File.Full_Name)); + Unit_Name : constant String := + (case Main.CU_Name.Language_Kind is + when Unit_Based_Language => To_Ada (Main.CU_Name.Unit), + when File_Based_Language => +Main.File.Full_Name); Unit_Args : String_Vectors.Vector := Instrument_Main_Args; begin + if not Quiet and then First_Main then + First_Main := False; + Put_Line ("Main instrumentation"); + end if; + Show_Progress (Language, Unit_Name); + Unit_Args.Append (Compilation_Unit_Options (IC, Main.Prj_Info.Desc, Library_Unit_Info' - (Unit_Name => Unit_Name, + (Unit_Name => +Unit_Name, Instr_Project => Main.Prj_Info.Project, Language_Kind => Language_Kind (Language), Language => Language, @@ -1426,7 +1433,7 @@ begin -- instrumented as a unit of interest before, then pass the -- instrumented version. - if Instrumented_Sources.Contains (+Unit_Name) then + if Instrumented_Sources.Contains (Unit_Name) then Main_Filename := +(+Root_Project_Info.Output_Dir) / (+Main.File.Base_Name); From a25ef9ae7b8b46a7b9f744da8978b90069ffe345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 15 Jan 2024 14:52:21 +0100 Subject: [PATCH 0624/1483] Bump trace format version The trace entries used to contain the name of the project to which the trace entry's unit belonged. This was removed by b567aca989fa1a718f80987d9c45e5dfb4bb1839, but the change did not bump the trace format version despite being a breaking change. This change bumps the version number after the fact to avoid potential confusing error messages in the future. --- testsuite/SUITE/srctracelib.py | 2 +- .../gen/arm-elf-linux/gcvrt-pz3791e32c.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68b.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68c.ads | 2 +- .../gen/arm-elf-linux/main_1.adb | 5 +-- .../gen/arm-elf-linux/main_1.sid | Bin 405 -> 405 bytes .../gen/arm-elf-linux/main_2.adb | 5 +-- .../gen/arm-elf-linux/main_2.sid | Bin 405 -> 405 bytes .../gen/arm-elf-linux/pkg.adb | 4 +- .../gen/arm-elf-linux/pkg.ads | 4 +- .../gen/arm-elf-linux/pkg.sid | Bin 1048 -> 1048 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1850 -> 1850 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1860 -> 1860 bytes .../U204-026-arch-mix/gen/main_1.srctrace | Bin 416 -> 416 bytes .../U204-026-arch-mix/gen/main_2.srctrace | Bin 388 -> 388 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 1993 -> 1998 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 1929 -> 1929 bytes .../gen/x86_64-windows/gcvrt-pz3791e32c.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68b.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68c.ads | 2 +- .../gen/x86_64-windows/main_1.adb | 15 +++---- .../gen/x86_64-windows/main_1.sid | Bin 407 -> 407 bytes .../gen/x86_64-windows/main_2.adb | 15 +++---- .../gen/x86_64-windows/main_2.sid | Bin 407 -> 407 bytes .../gen/x86_64-windows/pkg.adb | 38 +++++++++--------- .../gen/x86_64-windows/pkg.ads | 8 ++-- .../gen/x86_64-windows/pkg.sid | Bin 1052 -> 1052 bytes tools/gnatcov/rts/gnatcov_rts_c-traces.h | 5 ++- tools/gnatcov/traces_source.ads | 3 +- 29 files changed, 49 insertions(+), 67 deletions(-) diff --git a/testsuite/SUITE/srctracelib.py b/testsuite/SUITE/srctracelib.py index 195fe36de..413d1581d 100755 --- a/testsuite/SUITE/srctracelib.py +++ b/testsuite/SUITE/srctracelib.py @@ -95,7 +95,7 @@ class SrcTraceFile(object): MAGIC = b'GNATcov source trace file' + b'\x00' * 7 - FORMAT_VERSION = 2 + FORMAT_VERSION = 3 ENDIANITY_NAMES = { 0: 'little-endian', diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads index 75674fce3..a2cc75bbf 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz3791e32c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads index 5830af68f..be559ee3a 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68b is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads index 3e9adb3e0..9cc58c48f 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 5, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb index 172458ad0..104973569 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb @@ -1,9 +1,6 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Pkg; +pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); GCVRT.DB_z794ac68b.Dump_Buffers;end Main_1; - - diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index 4e1a258f439cab1c76dc5baea7ec39022f4de1a3..08b053f72aa5cc89b24134105536b1dcbbb7f59b 100644 GIT binary patch delta 13 UcmbQrJe7HaA0y-6$^MLP03T)qR{#J2 delta 13 UcmbQrJe7HaA0y-M$^MLP03TcgRR910 diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb index 8e8e5daba..ffe66dacd 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb @@ -1,9 +1,6 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Pkg; +pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); GCVRT.DB_z794ac68c.Dump_Buffers;end Main_2; - - diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid index 6349dac17ad6b663845ab009c755b75840509b21..a9c17c17f899228c3dfd3fe35ce8580f1e66142e 100644 GIT binary patch delta 13 UcmbQrJe7HaA0y-6$^MLP03T)qR{#J2 delta 13 UcmbQrJe7HaA0y-M$^MLP03TcgRR910 diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.adb index bef9472e0..09519828e 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.adb @@ -1,5 +1,4 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Ada.Text_IO; use Ada.Text_IO; +pragma Style_Checks (Off); pragma Warnings (Off);with Ada.Text_IO; use Ada.Text_IO; with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package body Pkg is @@ -17,4 +16,3 @@ with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package body Pkg is end Compute; end Pkg; - diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.ads index 8404f8668..1373d53c2 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.ads @@ -1,5 +1,3 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package Pkg is +pragma Style_Checks (Off); pragma Warnings (Off);with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package Pkg is procedure Compute (A, B : Boolean); end Pkg; - diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid index 33f7bd2aa00568400ab2349c18ecfda35d9e24c5..7d08a1c5f421882e845c42cd02b5a2de494e94f2 100644 GIT binary patch delta 26 gcmbQiF@s}68WZE+&FM^njEsLLS28;T$-T_c0DS8SfdBvi delta 26 gcmbQiF@s}68WZF1&FM^njEui0S28;T$-T_c0DPwjdjJ3c diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt index 1d9a4296a7f5c6884cb3783254bcba1010649362..1198c5f7560424b81c54840780ca9522d021a780 100644 GIT binary patch delta 168 zcmdnRw~KFs3FG8-jO?r&3=9k$lXo#{GjdMmWHe&s0`j>gJ1{y;e#%%sc@>k~*T7QO&{DzB+{)O*%D_ZH+rY@mzyPcmW(1H10L=3$ A@&Et; diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index e21e64110d2d13f610d926582767d59b0d3df6c2..0959bb6d3d09ff2e312a72c162f724d1c63e5132 100644 GIT binary patch delta 178 zcmX@YcZ6?)38RRSUSdur69WeW0~j*`X~oHcj8c=2GAc~YX4K&^gec$wN^nhfVAP(( z#xnUOWA)@!OmdT(m^3D*0O=DgJ1{y;e#%%sc@>k~nf*5-6Ud}VthPXbUo6f*(vEd9 zP;ByfR`JQNSR>dy-kwv~@Mhy=Pqr%}#<~WUx`vhthUQkrCRPTf3fcxnlMUI00d!9- AiU0rr diff --git a/testsuite/tests/U204-026-arch-mix/gen/main_1.srctrace b/testsuite/tests/U204-026-arch-mix/gen/main_1.srctrace index 9713cd6378a77d8f2729fb72a13d77c439225cd2..7c30d0abdd55e1857656dad629707067c18129fd 100644 GIT binary patch delta 12 TcmZ3$ynuOv0weQA#d<~n7o!7B delta 12 TcmZ3$ynuOv0wdE##d<~n7oG!5 diff --git a/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace b/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace index f9310f2c01f1f50fa8eb8d28c7a4d558556fa316..2baae32d007021be36fe7b1012e5260c7c1326fa 100644 GIT binary patch delta 12 TcmZo+ZegCFz{tE&F_{qn6$1kK delta 12 TcmZo+ZegCFz{s>wF_{qn6#fGE diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 30379d59a3d747a3b94189e3249878dbc7d266ab..908d23d70e97b006b3f093f50d60f9c1e2ac42bc 100644 GIT binary patch delta 143 zcmX@fe~y1c3^U{3$+67NKyo3oGt*zD$q6hXlYcS)0SbI)0Sa%nX02q5zsA78&@(II zu6F*l6O2H%01z9Q>KT+PXc!q7nHU%vnrec?X9BUaRZM7cYEf}aW=U>(QA~MaS!zs$ mg;~6riEepjUP^v>v6)FsdR}5la(-D%W?pegV$Nhf_T2!bpD(Zg delta 138 zcmX@df0BPg3^U{J$+67NKyo3oGt+OT$q6hXlYcS)0SbI)0Sa%nX02q5y2!x5;KG!9 zzwXV(6O2H%01&67mZj$87v!eqmFSifrKW(QA~PXVo7p- bS!z*YdTLBbetu3dOeiKNKRI!-F#B!*oHH@` diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt index 51f32931dd73b3eda9559d25feb75c1fdbeb62f5..49fc8fb0674e86186f76c7cd02f719e124dd3071 100644 GIT binary patch delta 516 zcmZuuJxc>Y5Z&3YBZ^$%1vNH78xe(zT8QLAuoqH@je=N(5Ise(^arH#nEV1OTPr)e zbYdg;1FUQ@~lry7{&E zQu941K^PuDsQ(OM3^OcIJQ!T+#7IB-ue09c?URv delta 509 zcmY*VJxc>Y5WU&G-AmMv5R%AQiB<~2;YVXQ5XHvQ!bY$Y3z4MAm6AH0$24|=RXRlD-4bz4Y*nP^ zd4Mn|@rj7kl=VgH7>s7H*%=Q^JnGzZlip?7P~QM$0FRIWP%QJ1A~j_n6e{E;zlybG zWft<8 diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb index 36fee4ed0..98e6e9221 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb @@ -1,9 +1,6 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Pkg; - -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is -GNATcov_Dump_Object:GCVRT.DB_z794ac68c.Dump_Controlled_Type;begin - GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); -end Main_2; - - +pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; + +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +GNATcov_Dump_Object:GCVRT.DB_z794ac68c.Dump_Controlled_Type;begin + GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); +end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid index 1134e529a7f6e7fe86c05a6a22689f2fc7805b39..fbbab9f7e9e6327e86286286b59fd63a273c2451 100644 GIT binary patch delta 13 UcmbQvJe_$%03+ky$$^Y+03WObUjP6A delta 13 UcmbQvJe_$%03+k?$$^Y+03V_RT>t<8 diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.adb index f8bb5f57d..09519828e 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.adb @@ -1,20 +1,18 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with Ada.Text_IO; use Ada.Text_IO; - -with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package body Pkg is - - ------------- - -- Compute -- - ------------- - - procedure Compute (A, B : Boolean) is - MCDC_State_2_Var:GNATcov_RTS.Buffers.MCDC_State_Type:=0;MCDC_State_2:constant GNATCov_RTS.Sys.Address:=MCDC_State_2_Var'Address;begin - GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,0);if GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Decision_Buffer,0,1,GCVRT.Pz3791e32c.Buffers_2.MCDC_Buffer,0,MCDC_State_2,GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,TRUE,A )and then GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,FALSE,B ))then - GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,1);Put_Line ("true"); - else - GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,2);Put_Line ("false"); - end if; - end Compute; - -end Pkg; - +pragma Style_Checks (Off); pragma Warnings (Off);with Ada.Text_IO; use Ada.Text_IO; + +with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package body Pkg is + + ------------- + -- Compute -- + ------------- + + procedure Compute (A, B : Boolean) is + MCDC_State_2_Var:GNATcov_RTS.Buffers.MCDC_State_Type:=0;MCDC_State_2:constant GNATCov_RTS.Sys.Address:=MCDC_State_2_Var'Address;begin + GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,0);if GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Decision_Buffer,0,1,GCVRT.Pz3791e32c.Buffers_2.MCDC_Buffer,0,MCDC_State_2,GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,TRUE,A )and then GNATcov_RTS.Buffers.Witness(MCDC_State_2,1,FALSE,B ))then + GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,1);Put_Line ("true"); + else + GNATcov_RTS.Buffers.Witness(GCVRT.Pz3791e32c.Buffers_2.Statement_Buffer,2);Put_Line ("false"); + end if; + end Compute; + +end Pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.ads index aef8a67c2..1373d53c2 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.ads @@ -1,5 +1,3 @@ -pragma Style_Checks (Off); pragma Warnings (Off); -with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package Pkg is - procedure Compute (A, B : Boolean); -end Pkg; - +pragma Style_Checks (Off); pragma Warnings (Off);with GNATcov_RTS.Buffers;with GCVRT.Pz3791e32c;package Pkg is + procedure Compute (A, B : Boolean); +end Pkg; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid index 9f9c03d18e3240f12df704f4b831e9751b806cfa..6dc7d3975054068ec850dd1b32e125205b8e0e62 100644 GIT binary patch delta 26 gcmbQkF^6MA78B#&&Dl(XjEsLL*D^Z;$%D+%0DgA~nE(I) delta 26 gcmbQkF^6MA78B#|&Dl(XjEui0*D^Z;$%D+%0DdzGlK=n! diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces.h b/tools/gnatcov/rts/gnatcov_rts_c-traces.h index cfb7e4b30..fa260dd97 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces.h @@ -31,8 +31,9 @@ extern "C" 0 -- initial version 1 -- extend trace entry model to account for C files - 2 -- introduce fingerprints for bit maps */ -#define GNATCOV_RTS_CURRENT_VERSION 2 + 2 -- introduce fingerprints for bit maps + 3 -- remove the project name from trace entries */ +#define GNATCOV_RTS_CURRENT_VERSION 3 /* LSB_First_Bytes: bit buffers are encoded as sequences of bytes. diff --git a/tools/gnatcov/traces_source.ads b/tools/gnatcov/traces_source.ads index 644bf2595..3642165d8 100644 --- a/tools/gnatcov/traces_source.ads +++ b/tools/gnatcov/traces_source.ads @@ -48,12 +48,13 @@ package Traces_Source is -- trace entries start and end on byte/half word/word/long word boundaries. type Trace_File_Format_Version is new Unsigned_32; - Current_Version : Trace_File_Format_Version := 2; + Current_Version : Trace_File_Format_Version := 3; -- Expected value of the Trace_File_Header.Format_Version field. -- -- 0 -- initial version -- 1 -- extend trace entry model to account for C files -- 2 -- introduce fingerprints for bit maps + -- 3 -- remove the project name from trace entries type Any_Alignment is new Unsigned_8; subtype Supported_Alignment is Any_Alignment; From 074657198cb910b31ae5fc3bd763dd9ba81936af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 15 Jan 2024 16:15:29 +0100 Subject: [PATCH 0625/1483] Add test checking for undocumented breaking changes in trace format The test first checks whether there were any undocument breaking changes in the trace format (i.e. breaking changes which do not include a trace version number bump), then promts the user to update the trace in the test if a breaking change did happen. --- testsuite/tests/207-srctrace-version/foo.c | 7 ++ .../tests/207-srctrace-version/foo.c.sid | Bin 0 -> 1539 bytes testsuite/tests/207-srctrace-version/main.adb | 17 ++++ testsuite/tests/207-srctrace-version/main.sid | Bin 0 -> 994 bytes .../207-srctrace-version/reference.srctrace | Bin 0 -> 360 bytes testsuite/tests/207-srctrace-version/test.py | 74 ++++++++++++++++++ .../tests/207-srctrace-version/update.sh | 6 ++ 7 files changed, 104 insertions(+) create mode 100644 testsuite/tests/207-srctrace-version/foo.c create mode 100644 testsuite/tests/207-srctrace-version/foo.c.sid create mode 100644 testsuite/tests/207-srctrace-version/main.adb create mode 100644 testsuite/tests/207-srctrace-version/main.sid create mode 100644 testsuite/tests/207-srctrace-version/reference.srctrace create mode 100644 testsuite/tests/207-srctrace-version/test.py create mode 100755 testsuite/tests/207-srctrace-version/update.sh diff --git a/testsuite/tests/207-srctrace-version/foo.c b/testsuite/tests/207-srctrace-version/foo.c new file mode 100644 index 000000000..daa6f4c2f --- /dev/null +++ b/testsuite/tests/207-srctrace-version/foo.c @@ -0,0 +1,7 @@ +extern int or_else (int l, int r); + +int +or_else (int l, int r) +{ + return l || r; +} diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid new file mode 100644 index 0000000000000000000000000000000000000000..62710486a5d06c6726a957a94791125cadeefc3d GIT binary patch literal 1539 zcmb_cF;5ji5WahWCW>f?R5q3r9BYhuk{A;$41oe03!s5xUEaHR@Ah)LhtyQmHu48Z z{1K8+(oDv-@KcbeT2LOc$4hS?Cdw+&d$!>^4iBQ+U~v7U8BF1HYReat(pSip|U;lmd;`92+?ELB3!Buav0mTo<01@;v8aGLc zoD6(K#wZ}O0wBQ0H_?%ga|G}yjZusej{`!Wkq&>@i5YtWr}%zu{5V?pyLo*0M|b?M zxn5gsUtmqjC8dJqqLO9_w}UOfhh*Do%jC|WXu{LK36A6s;3RQN;-Uzp!Aw$%;TZ5r zQj8Z?)aCls%pwZtk@9cQd*Nl^dch6OCc{1poZytEkVR=RpeDntrr~LXli}0w@g_oC z*ap~@v3ziv3?ail7$CVCvJYvYh92`{y2k#V=0i{Qd%9=T{!)9Z{U*t?qTW}|r#rbx z@OslcS6M+0(mPq9I$EPqkS0!?e1f$MYh{S^uJ0doOShzRby?cVEBcuz#DBO)eAnb9 i{fe09u6g9T%kg6_%Xr&@YQ(pQ+x%*F(>nL!g8mPu9}8Uo literal 0 HcmV?d00001 diff --git a/testsuite/tests/207-srctrace-version/main.adb b/testsuite/tests/207-srctrace-version/main.adb new file mode 100644 index 000000000..4de03770a --- /dev/null +++ b/testsuite/tests/207-srctrace-version/main.adb @@ -0,0 +1,17 @@ +with Interfaces.C; use Interfaces.C; + +with Support; + +procedure Main is + + function Or_Else (L, R : int) return int; + pragma Import (C, Or_Else, "or_else"); + + function And_Then (L, R : Boolean) return Boolean is + begin + return L and then R; + end And_Then; +begin + Support.Assert (And_Then (True, True)); + Support.Assert (Or_Else (0, 1) = 1); +end Main; diff --git a/testsuite/tests/207-srctrace-version/main.sid b/testsuite/tests/207-srctrace-version/main.sid new file mode 100644 index 0000000000000000000000000000000000000000..c097c077df573af20d29b5e20aabe882920613bd GIT binary patch literal 994 zcma)5J4?hs5Z>IK55#vN_$cgr;N2dASYLG@oLF2Zs4-dZg5KsxHsbFPD?3a7g7_2c zEUYXnEG(`UL2$lJCd5W>V0I=m-^_fOO`7|SwijNmdR^t6_rpLNF(p!QNQ5YnilVmY zS$4yol3t{eSjkBB!&r8-Yp9Wm+>Vk)#U@SylX-HxzFUnW&qS`Ls)UJyP|Kbh=$h-F zI!@URv_p!M#M!S&t!hen(!F`WvPKlcc!5&-3)^cMeWeFA80fpcO`jJfH0Qyfk!8KcEz+-=~OQeu_9RK$C&OZ~> zPLskeW~Jbjy(M`h7>H}&m2i?j1z;*gR?B AGynhq literal 0 HcmV?d00001 diff --git a/testsuite/tests/207-srctrace-version/reference.srctrace b/testsuite/tests/207-srctrace-version/reference.srctrace new file mode 100644 index 0000000000000000000000000000000000000000..15531ccfae0a690af09157178d27212bdab8a421 GIT binary patch literal 360 zcmZ?wa|}t&FHXCsLkOR^SQU{U)vaLn9ZRWmT?XXNLm>L(YamKLY#7o`^D7wf0zC6)l4oLZEao~mDx zT3k|Gnppy6=^GiC>lPO!gZ-fkR8yRppQoRepRbn;HV*6-5DVlU5P;DvKsLyIFn0nK zYPfs7jmy0Iv_y>gy50}zGqa}b`t`6PanIWnQv;po%Yrhw0h1Q4dw+( literal 0 HcmV?d00001 diff --git a/testsuite/tests/207-srctrace-version/test.py b/testsuite/tests/207-srctrace-version/test.py new file mode 100644 index 000000000..ef4bb0640 --- /dev/null +++ b/testsuite/tests/207-srctrace-version/test.py @@ -0,0 +1,74 @@ +""" +Test that when loading a trace with gnatcov, either everything works correctly +or there is a specific error message concerning the trace version number that +is emitted. If a change in format is detected between the trace and the current +gnatcov version, force the user to update the trace. +""" + +import os +import os.path + +from SCOV.minicheck import xcov, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +# Generate a project, it will be helpful for test updates +prj = gprfor(mains=["main.adb"], srcdirs=[".."]) + +# Create a coverage report from the trace under version control. +# Its format is either the same as the one expected by the current gnatcov, in +# which case there should be no problems, or the formats differ, in which case +# we only expect an error message concerning the trace version number. +coverage_log = "coverage_log.txt" +p = xcov( + [ + "coverage", + "--output-dir=.", + "-axcov", + "-cstmt+mcdc", + "--sid=../main.sid", + "--sid=../foo.c.sid", + "--source-search=..", + "-T=../reference.srctrace", + ], + register_failure=False, + out=coverage_log +) + +# If there was an error, the trace format changed between when the trace was +# generated and now. Look for the appropriate error message. +if p.status != 0: + thistest.fail_if_no_match( + "Unexpected error message from 'gnatcov coverage'.\n" + "*** Ensure the trace format version was properly bumped if you made a" + " breaking change in the trace format ***\n", + regexp=r".*gnatcov(\.exe)?: ../reference.srctrace:" + r" unsupported format version", + actual=contents_of(coverage_log) + ) + + # If the correct message was found then great, the trace format number was + # indeed bumped. Now prompt for the test to be updated otherwise we could + # end up with an old trace in the test, and stop testing with the latest + # trace format. + thistest.failed( + "Update the trace and SIDs in this test to the latest" + " format to make test pass again.\n" + "This is simply a matter of running './update.sh' in the test directory." + ) + +# Otherwise, check the coverage report +else: + check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": {"+": {15, 16}, "!": {12}}, + "foo.c.xcov": {"!": {6}} + } + ) + +thistest.result() diff --git a/testsuite/tests/207-srctrace-version/update.sh b/testsuite/tests/207-srctrace-version/update.sh new file mode 100755 index 000000000..27f3eb584 --- /dev/null +++ b/testsuite/tests/207-srctrace-version/update.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +gnatcov instrument -P tmp_/gen.gpr -cstmt+mcdc +cp tmp_/obj/*.sid . +gprbuild -P tmp_/gen.gpr --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts.gpr +GNATCOV_TRACE_FILE=reference.srctrace ./tmp_/main From fbf9bb1e2bb95aa064fea9d81fb606b7b012c644 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 17 Jan 2024 15:20:55 +0100 Subject: [PATCH 0626/1483] instr-cov/short_circuit_and_or: replace TN with GitLab issue in test.opt --- testsuite/tests/instr-cov/short_circuit_and_or/test.opt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/test.opt b/testsuite/tests/instr-cov/short_circuit_and_or/test.opt index cb67a102b..321252117 100644 --- a/testsuite/tests/instr-cov/short_circuit_and_or/test.opt +++ b/testsuite/tests/instr-cov/short_circuit_and_or/test.opt @@ -1 +1 @@ -src-traces XFAIL U705-016: overloading resolution bug in LAL \ No newline at end of file +src-traces XFAIL eng/libadalang/libadalang#1224: overloading resolution bug From b0a635dd66eca16edd219f05f061b6fef0cad74c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 17 Jan 2024 09:53:16 +0000 Subject: [PATCH 0627/1483] instrument-projects.adb: minor reformatting --- tools/gnatcov/instrument-projects.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index af2510e1e..00996516d 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -1182,7 +1182,7 @@ begin Ada_Instrumenter := Create_Ada_Instrumenter - (Tag => IC.Tag, + (Tag => IC.Tag, Config_Pragmas_Filename => +IC.Config_Pragmas_File, Mapping_Filename => +IC.Mapping_File, Predefined_Source_Dirs => IC.Predefined_Source_Dirs, From af7b99146031867b618dedf0c6f878db652d0748 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 17 Jan 2024 14:52:56 +0000 Subject: [PATCH 0628/1483] Instrument.Ada_Unit_Provider: remove an unused function --- .../gnatcov/instrument-ada_unit_provider.adb | 27 ------------------- .../gnatcov/instrument-ada_unit_provider.ads | 4 --- 2 files changed, 31 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit_provider.adb b/tools/gnatcov/instrument-ada_unit_provider.adb index 68eccf516..237a66bfe 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.adb +++ b/tools/gnatcov/instrument-ada_unit_provider.adb @@ -19,12 +19,9 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Text_IO; use Ada.Text_IO; -with GNATCOLL.Projects.Aux; use GNATCOLL.Projects.Aux; - with Libadalang.Unit_Files; with Outputs; -with Project; use Project; package body Instrument.Ada_Unit_Provider is @@ -106,30 +103,6 @@ package body Instrument.Ada_Unit_Provider is return Provider; end Create_Provider; - ---------------------------------- - -- Create_Provider_From_Project -- - ---------------------------------- - - function Create_Provider_From_Project return Unit_Provider_Reference - is - Mapping_File : constant String := - Create_Ada_Mapping_File (Project.Project.Root_Project); - -- The mapping file will be removed by the Finalize procedure in - -- project.adb. - - begin - if Mapping_File = "" then - Outputs.Fatal_Error - ("Error when creating the mapping file for the project " - & Project.Project.Root_Project.Name); - end if; - - return Create_Unit_Provider_Reference - (Create_Provider - (Runtime_Directories => Project.Runtime_Dirs, - Dependencies_Filename => Mapping_File)); - end Create_Provider_From_Project; - ----------------------- -- Get_Unit_Filename -- ----------------------- diff --git a/tools/gnatcov/instrument-ada_unit_provider.ads b/tools/gnatcov/instrument-ada_unit_provider.ads index d9947c55a..693a74b2b 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.ads +++ b/tools/gnatcov/instrument-ada_unit_provider.ads @@ -42,10 +42,6 @@ package Instrument.Ada_Unit_Provider is -- through Runtime_Directories, and from a mapping file in the same format -- as the file passed through -gnatem in the compiler invocation. - function Create_Provider_From_Project return Unit_Provider_Reference; - -- Uses the loaded project (Project.Project) to generate a mapping - -- file and create a unit provider from it. - overriding function Get_Unit_Filename (Provider : Provider_Type; Name : Text_Type; From 97dd74e489ed1cf8ac70f1250ce91d5f25fe3194 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 17 Jan 2024 15:00:43 +0000 Subject: [PATCH 0629/1483] instrument-projects.adb: minor refactoring --- tools/gnatcov/instrument-projects.adb | 33 +++++++++------------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 00996516d..031b1cb96 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -608,33 +608,22 @@ is LU_Info : Library_Unit_Info) return String_Vectors.Vector is Result : String_Vectors.Vector; - - procedure Compilation_Unit_Options_Ada; - - ---------------------------------- - -- Compilation_Unit_Options_Ada -- - ---------------------------------- - - procedure Compilation_Unit_Options_Ada is - begin - Result.Append ("--gnatem=" & IC.Mapping_File); - Result.Append ("--gnatec=" & IC.Config_Pragmas_File); - Result.Append - ("--ada-preprocessor-data=" & IC.Ada_Preprocessor_Data_File); - - -- Load the predefined source directories - - for Dir of IC.Predefined_Source_Dirs loop - Result.Append ("--runtime-dir=" & Dir); - end loop; - end Compilation_Unit_Options_Ada; - begin -- Depending on the language, pass the right set of options case LU_Info.Language is when Ada_Language => - Compilation_Unit_Options_Ada; + Result.Append ("--gnatem=" & IC.Mapping_File); + Result.Append ("--gnatec=" & IC.Config_Pragmas_File); + Result.Append + ("--ada-preprocessor-data=" & IC.Ada_Preprocessor_Data_File); + + -- Load the predefined source directories + + for Dir of IC.Predefined_Source_Dirs loop + Result.Append ("--runtime-dir=" & Dir); + end loop; + when others => null; end case; From 513bb2f14bf66a3eaaf4451abded2312f5d7b203 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 18 Jan 2024 13:48:40 +0000 Subject: [PATCH 0630/1483] instr-cov/entry_guards/extra.opt: fix comment wording --- testsuite/tests/instr-cov/entry_guards/extra.opt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/instr-cov/entry_guards/extra.opt b/testsuite/tests/instr-cov/entry_guards/extra.opt index e1ca6aae1..26465a43d 100644 --- a/testsuite/tests/instr-cov/entry_guards/extra.opt +++ b/testsuite/tests/instr-cov/entry_guards/extra.opt @@ -1,4 +1,4 @@ --- These tests use protected bodies, which not available with light or +-- These tests use protected bodies, which are not available with light or -- embedded runtimes. RTS_FULL ALL DEAD From e2719918c3b3a85c67493db704874a8496f5cf30 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 17 Jan 2024 16:02:25 +0000 Subject: [PATCH 0631/1483] Instrument Ada: fix the handling of configuration pragmas files After the work on parallelized intrumentation, configuration pragmas mappings were tentatively passed from the "instrumentation driver" to the "instrumentation subprocess" using the file that the GNATCOLL.Projects.Aux.Create_Config_Pragmas_File function creates. The problem is that this function is not about the same "configuration pragmas": it seems to process pragmas that deal with source file mappings. As a consequence, the handling of configuration pragmas files was completely broken. Switch back to a pure Libadalang-based implementation of configuration pragmas mappings to restore the previous behavior, and add a (non XFAILed) testcase to check it works as expected. --- .../tests/instr-cov/config_pragmas/gnat.adc | 1 + .../tests/instr-cov/config_pragmas/main.adb | 12 ++ .../tests/instr-cov/config_pragmas/pkg.adb | 27 ++++ .../tests/instr-cov/config_pragmas/pkg.ads | 8 ++ .../tests/instr-cov/config_pragmas/test.opt | 4 + .../tests/instr-cov/config_pragmas/test.py | 42 ++++++ tools/gnatcov/command_line.ads | 8 +- tools/gnatcov/instrument-ada_unit.adb | 122 ++++++++++++++++-- tools/gnatcov/instrument-ada_unit.ads | 31 +++-- tools/gnatcov/instrument-ada_unit__stub.ads | 4 +- tools/gnatcov/instrument-config.adb | 4 +- tools/gnatcov/instrument-projects.adb | 23 +++- 12 files changed, 253 insertions(+), 33 deletions(-) create mode 100644 testsuite/tests/instr-cov/config_pragmas/gnat.adc create mode 100644 testsuite/tests/instr-cov/config_pragmas/main.adb create mode 100644 testsuite/tests/instr-cov/config_pragmas/pkg.adb create mode 100644 testsuite/tests/instr-cov/config_pragmas/pkg.ads create mode 100644 testsuite/tests/instr-cov/config_pragmas/test.opt create mode 100644 testsuite/tests/instr-cov/config_pragmas/test.py diff --git a/testsuite/tests/instr-cov/config_pragmas/gnat.adc b/testsuite/tests/instr-cov/config_pragmas/gnat.adc new file mode 100644 index 000000000..a832dd386 --- /dev/null +++ b/testsuite/tests/instr-cov/config_pragmas/gnat.adc @@ -0,0 +1 @@ +pragma Restrictions (Pure_Barriers); diff --git a/testsuite/tests/instr-cov/config_pragmas/main.adb b/testsuite/tests/instr-cov/config_pragmas/main.adb new file mode 100644 index 000000000..48561e121 --- /dev/null +++ b/testsuite/tests/instr-cov/config_pragmas/main.adb @@ -0,0 +1,12 @@ +with Pkg; + +procedure Main is + T : Pkg.PT; +begin + T.Init (False); + select + T.Wait_Cond; + else + null; + end select; +end Main; diff --git a/testsuite/tests/instr-cov/config_pragmas/pkg.adb b/testsuite/tests/instr-cov/config_pragmas/pkg.adb new file mode 100644 index 000000000..f94440633 --- /dev/null +++ b/testsuite/tests/instr-cov/config_pragmas/pkg.adb @@ -0,0 +1,27 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + protected body PT is + + ---------- + -- Init -- + ---------- + + procedure Init (Cond : Boolean) is + begin + PT.Cond := Cond; + end Init; + + --------------- + -- Wait_Cond -- + --------------- + + entry Wait_Cond + when Cond + is + begin + Put_Line ("OK"); + end Wait_Cond; + + end PT; +end Pkg; diff --git a/testsuite/tests/instr-cov/config_pragmas/pkg.ads b/testsuite/tests/instr-cov/config_pragmas/pkg.ads new file mode 100644 index 000000000..4cad032f1 --- /dev/null +++ b/testsuite/tests/instr-cov/config_pragmas/pkg.ads @@ -0,0 +1,8 @@ +package Pkg is + protected type PT is + procedure Init (Cond : Boolean); + entry Wait_Cond; + private + Cond : Boolean := False; + end PT; +end Pkg; diff --git a/testsuite/tests/instr-cov/config_pragmas/test.opt b/testsuite/tests/instr-cov/config_pragmas/test.opt new file mode 100644 index 000000000..26465a43d --- /dev/null +++ b/testsuite/tests/instr-cov/config_pragmas/test.opt @@ -0,0 +1,4 @@ +-- These tests use protected bodies, which are not available with light or +-- embedded runtimes. +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/instr-cov/config_pragmas/test.py b/testsuite/tests/instr-cov/config_pragmas/test.py new file mode 100644 index 000000000..ca4fcabf7 --- /dev/null +++ b/testsuite/tests/instr-cov/config_pragmas/test.py @@ -0,0 +1,42 @@ +""" +Check that configuration pragmas are correctly interpreted by the instrumenter. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor( + srcdirs=[".."], + mains=["main.adb"], + compiler_extra=( + 'for Local_Configuration_Pragmas use "../gnat.adc";' + ), + ) + ), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) + +# If for some reason the instrumenter ignores the Pure_Barrier restriction in +# gnat.adc, it will instrument the entry barrier decision "when Cond" in +# pkg.adb, which will then not compile because the witness call inserted for +# that decision violates the Pure_Barrier restriction. +check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": {"+": {4, 6, 8, 10}}, + "pkg.ads.xcov": {"+": {6}}, + "pkg.adb.xcov": {"+": {12}, "-": {23}, "?": {20}}, + }, + cwd="xcov", +) + +thistest.result() diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 1f2aa55ea..bb1f234fb 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -137,7 +137,7 @@ package Command_Line is Opt_Body_Suffix, Opt_Dot_Replacement, Opt_Gnatem, - Opt_Gnatec, + Opt_Config_Pragmas_Mapping, Opt_Ada_Preprocessor_Data, Opt_Project_Name, Opt_Source_Root); @@ -1088,11 +1088,11 @@ package Command_Line is At_Most_Once => False, Internal => True), - Opt_Gnatec => Create - (Long_Name => "--gnatec", + Opt_Config_Pragmas_Mapping => Create + (Long_Name => "--config-pragmas-mapping", Pattern => "NAME", Help => - "Name of the file containing configuration pragmas.", + "Name of the file containing the configuration pragmas mapping.", Commands => (Cmd_Instrument_Source | Cmd_Instrument_Main => True, others => False), diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index d0097eae2..816759004 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -32,13 +32,13 @@ with Langkit_Support; with Langkit_Support.Slocs; use Langkit_Support.Slocs; with Langkit_Support.Symbols; use Langkit_Support.Symbols; with Libadalang.Common; use Libadalang.Common; -with Libadalang.Config_Pragmas; with Libadalang.Expr_Eval; with Libadalang.Generic_API; with Libadalang.Generic_API.Introspection; use Libadalang.Generic_API.Introspection; with Libadalang.Sources; use Libadalang.Sources; +with GNATCOLL.JSON; use GNATCOLL.JSON; with GNATCOLL.Utils; with GNATCOLL.VFS; @@ -47,9 +47,11 @@ with Coverage_Options; use Coverage_Options; with Coverage; use Coverage; with Diagnostics; use Diagnostics; with Instrument.Ada_Preprocessing; +with JSON; use JSON; with Namet; use Namet; with Outputs; use Outputs; with Paths; use Paths; +with Project; with SCOs; with Slocs; with Snames; use Snames; @@ -6769,16 +6771,15 @@ package body Instrument.Ada_Unit is File_Reader => Instrumenter.File_Reader); Instrumenter.Get_From_File_Count := 0; - -- Load configuration pragmas. TODO??? Clarify what happens when there - -- is a local configuration pragma file. - - Libadalang.Config_Pragmas.Set_Mapping - (Instrumenter.Context, - Libadalang.Config_Pragmas.Config_Pragmas_Mapping' - (Global_Pragmas => - Instrumenter.Context.Get_From_File - (+Instrumenter.Config_Pragmas_Filename), - others => <>)); + declare + Mapping : Config_Pragmas_Mapping; + begin + Load_Config_Pragmas_Mapping + (Instrumenter.Context, + Mapping, + +Instrumenter.Config_Pragmas_Mapping); + Set_Mapping (Instrumenter.Context, Mapping); + end; end Create_LAL_Context; ------------------- @@ -9020,13 +9021,108 @@ package body Instrument.Ada_Unit is end; end Emit_Buffers_List_Unit; + --------------------------------- + -- Save_Config_Pragmas_Mapping -- + --------------------------------- + + procedure Save_Config_Pragmas_Mapping (Filename : String) is + function "+" (Unit : Analysis_Unit) return JSON_Value + is (if Unit = No_Analysis_Unit + then Create + else Create (Unit.Get_Filename)); + -- Get the filename of Unit as a JSON string, or the JSON null if Unit + -- is null. + + -- First, compute the configuration pragmas mapping for all sources in + -- the loaded project. + + Context : constant Analysis_Context := Create_Context; + Mapping : constant Config_Pragmas_Mapping := + Import_From_Project (Context, Project.Project.all); + + -- Then, turn this mapping into a JSON description + + Desc : constant JSON_Value := Create_Object; + Local : constant JSON_Value := Create_Object; + begin + Desc.Set_Field ("local_pragmas", Local); + Desc.Set_Field ("global_pragmas", +Mapping.Global_Pragmas); + + for Cur in Mapping.Local_Pragmas.Iterate loop + declare + Source_File : constant Analysis_Unit := Unit_Maps.Key (Cur); + Pragmas_File : constant Analysis_Unit := Unit_Maps.Element (Cur); + begin + Local.Set_Field (Source_File.Get_Filename, +Pragmas_File); + end; + end loop; + + -- Finally, write that JSON description to the requested file. + -- + -- No need to be space-efficient here, and a non-compact form will be + -- easier for debugging. + + Write (Filename, Desc, Compact => False); + end Save_Config_Pragmas_Mapping; + + --------------------------------- + -- Load_Config_Pragmas_Mapping -- + --------------------------------- + + procedure Load_Config_Pragmas_Mapping + (Context : Analysis_Context; + Mapping : out Config_Pragmas_Mapping; + Filename : String) + is + -- Parse the JSON description + + Result : constant Read_Result := JSON.Read (Filename); + begin + if not Result.Success then + Outputs.Error ("Cannot read " & Filename); + Outputs.Fatal_Error (Format_Parsing_Error (Result.Error)); + end if; + + -- Decode it into the final mapping + + declare + Global : constant JSON_Value := Result.Value.Get ("global_pragmas"); + begin + if Global.Kind /= JSON_Null_Type then + Mapping.Global_Pragmas := Context.Get_From_File (Global.Get); + end if; + end; + + declare + procedure Process (Name : String; Value : JSON_Value); + -- Insert an entry to Mapping.Local_Pragmas corresponding to the + -- source file at Name and the configuration pragmas file at Value (a + -- JSON string). + + ------------- + -- Process -- + ------------- + + procedure Process (Name : String; Value : JSON_Value) is + Source_File : constant Analysis_Unit := + Context.Get_From_File (Name); + Pragmas_File : constant Analysis_Unit := + Context.Get_From_File (Value.Get); + begin + Mapping.Local_Pragmas.Insert (Source_File, Pragmas_File); + end Process; + begin + Result.Value.Get ("local_pragmas").Map_JSON_Object (Process'Access); + end; + end Load_Config_Pragmas_Mapping; + ----------------------------- -- Create_Ada_Instrumenter -- ----------------------------- function Create_Ada_Instrumenter (Tag : Unbounded_String; - Config_Pragmas_Filename, + Config_Pragmas_Mapping : String; Mapping_Filename : String; Predefined_Source_Dirs : String_Vectors.Vector; Preprocessor_Data_Filename : String) @@ -9056,7 +9152,7 @@ package body Instrument.Ada_Unit is -- Save the location of the file holding the configuration pragmas - Instrumenter.Config_Pragmas_Filename := +Config_Pragmas_Filename; + Instrumenter.Config_Pragmas_Mapping := +Config_Pragmas_Mapping; -- Then, create the analysis context diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index d1f11015f..4b939fdfe 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -24,9 +24,10 @@ with Ada.Strings.Wide_Wide_Hash; with Ada.Strings.Wide_Wide_Unbounded; use Ada.Strings.Wide_Wide_Unbounded; with Langkit_Support.File_Readers; -with Langkit_Support.Text; use Langkit_Support.Text; -with Libadalang.Analysis; use Libadalang.Analysis; -with Libadalang.Rewriting; use Libadalang.Rewriting; +with Langkit_Support.Text; use Langkit_Support.Text; +with Libadalang.Analysis; use Libadalang.Analysis; +with Libadalang.Config_Pragmas; use Libadalang.Config_Pragmas; +with Libadalang.Rewriting; use Libadalang.Rewriting; with Files_Handling; use Files_Handling; with Files_Table; use Files_Table; @@ -51,8 +52,10 @@ package Instrument.Ada_Unit is Event_Handler : Libadalang.Analysis.Event_Handler_Reference; -- Event handler to warn about missing source files - Config_Pragmas_Filename : Unbounded_String; - -- File holding the list of configuration pragmas + Config_Pragmas_Mapping : Unbounded_String; + -- Filename for a JSON description file of a configuration pragmas + -- mapping: see the Save_Config_Pragmas_Mapping and + -- Load_Config_Pragmas_Mapping procedures below. Context : Libadalang.Analysis.Analysis_Context; -- Libadalang context to load all units to rewrite @@ -106,17 +109,29 @@ package Instrument.Ada_Unit is Instr_Units : Unit_Sets.Set; Prj : Prj_Desc); + procedure Save_Config_Pragmas_Mapping (Filename : String); + -- Create a configuration pragmas mapping for the loaded project and write + -- a JSON description file of it to Filename. + + procedure Load_Config_Pragmas_Mapping + (Context : Analysis_Context; + Mapping : out Config_Pragmas_Mapping; + Filename : String); + -- Create a config pragmas mapping from the JSON description in Filename + -- (created by the Save_Config_Pragmas_Mapping procedure) and assign it to + -- Mapping. Context is used to create the analysis units in Mapping. + function Create_Ada_Instrumenter (Tag : Unbounded_String; - Config_Pragmas_Filename, + Config_Pragmas_Mapping : String; Mapping_Filename : String; Predefined_Source_Dirs : String_Vectors.Vector; Preprocessor_Data_Filename : String) return Ada_Instrumenter_Type; -- Create an Ada instrumenter. -- - -- Config_Pragmas_Filename is the fullname to the configuration pragma - -- file. + -- Config_Pragmas_Mapping is the fullname to the configuration pragma + -- mapping file (created by the Save_Config_Pragmas_Mapping procedure). -- -- Mapping_Filename is the fullname to the mapping file, which maps unit -- names to file fullnames. diff --git a/tools/gnatcov/instrument-ada_unit__stub.ads b/tools/gnatcov/instrument-ada_unit__stub.ads index d799499c1..8f2d42a5b 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.ads +++ b/tools/gnatcov/instrument-ada_unit__stub.ads @@ -31,9 +31,11 @@ package Instrument.Ada_Unit is (Self : Ada_Instrumenter_Type) return Src_Supported_Language is (Ada_Language); + procedure Save_Config_Pragmas_Mapping (Filename : String) is null; + function Create_Ada_Instrumenter (Tag : Unbounded_String; - Config_Pragmas_Filename, + Config_Pragmas_Mapping : String; Mapping_Filename : String; Predefined_Source_Dirs : String_Vectors.Vector; Preprocessor_Data_Filename : String) diff --git a/tools/gnatcov/instrument-config.adb b/tools/gnatcov/instrument-config.adb index 9c884a05d..1ded3ee63 100644 --- a/tools/gnatcov/instrument-config.adb +++ b/tools/gnatcov/instrument-config.adb @@ -36,8 +36,8 @@ begin when Ada_Language => return Create_Ada_Instrumenter (Tag => Tag, - Config_Pragmas_Filename => - +Args.String_Args (Opt_Gnatec).Value, + Config_Pragmas_Mapping => + +Args.String_Args (Opt_Config_Pragmas_Mapping).Value, Mapping_Filename => +Args.String_Args (Opt_Gnatem).Value, Predefined_Source_Dirs => diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 031b1cb96..2783e0c50 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -162,7 +162,15 @@ is -- dealing with homonym in different projects). type Inst_Context is limited record - Mapping_File, Config_Pragmas_File : Unbounded_String; + Mapping_File : Unbounded_String; + -- File that describes the mapping of units to source files for all Ada + -- units. + + Config_Pragmas_Mapping : Unbounded_String; + -- File that describes the mapping of Ada source files to configuration + -- pragma files. See the Save_Config_Pragmas_Mapping and + -- Load_Config_Pragmas_Mapping procedures in Instrument.Ada_Unit for + -- more information. Predefined_Source_Dirs : String_Vectors.Vector; @@ -614,7 +622,8 @@ is case LU_Info.Language is when Ada_Language => Result.Append ("--gnatem=" & IC.Mapping_File); - Result.Append ("--gnatec=" & IC.Config_Pragmas_File); + Result.Append + ("--config-pragmas-mapping=" & IC.Config_Pragmas_Mapping); Result.Append ("--ada-preprocessor-data=" & IC.Ada_Preprocessor_Data_File); @@ -1147,13 +1156,16 @@ begin IC.Mapping_File := +Create_Ada_Mapping_File (Project.Project.Root_Project); - IC.Config_Pragmas_File := - +Create_Config_Pragmas_File (Project.Project.Root_Project); + IC.Config_Pragmas_Mapping := + +(+Root_Project_Info.all.Output_Dir) / "config-pragmas.json"; IC.Sources_Of_Interest_Response_File := +(+Root_Project_Info.all.Output_Dir) / ".sources_of_interest"; IC.Ada_Preprocessor_Data_File := +(+Root_Project_Info.all.Output_Dir) / "prep-data.json"; + Instrument.Ada_Unit.Save_Config_Pragmas_Mapping + (+IC.Config_Pragmas_Mapping); + Instrument.Ada_Preprocessing.Create_Preprocessor_Data_File (+IC.Ada_Preprocessor_Data_File); @@ -1172,7 +1184,7 @@ begin Ada_Instrumenter := Create_Ada_Instrumenter (Tag => IC.Tag, - Config_Pragmas_Filename => +IC.Config_Pragmas_File, + Config_Pragmas_Mapping => +IC.Config_Pragmas_Mapping, Mapping_Filename => +IC.Mapping_File, Predefined_Source_Dirs => IC.Predefined_Source_Dirs, Preprocessor_Data_Filename => +IC.Ada_Preprocessor_Data_File); @@ -1459,6 +1471,7 @@ begin end; if not Save_Temps then + Ada.Directories.Delete_File (+IC.Config_Pragmas_Mapping); Ada.Directories.Delete_File (+IC.Sources_Of_Interest_Response_File); Ada.Directories.Delete_File (+IC.Ada_Preprocessor_Data_File); end if; From fcc202c3621d727de93551a6d5d6b1ad61bf2009 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 18 Jan 2024 09:05:59 +0000 Subject: [PATCH 0632/1483] instrument-ada_preprocessing.adb: minor refactoring Use JSON.Write instead of re-implementing writing a JSON document to a file. --- tools/gnatcov/instrument-ada_preprocessing.adb | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tools/gnatcov/instrument-ada_preprocessing.adb b/tools/gnatcov/instrument-ada_preprocessing.adb index 3b861d0ba..c65096ca0 100644 --- a/tools/gnatcov/instrument-ada_preprocessing.adb +++ b/tools/gnatcov/instrument-ada_preprocessing.adb @@ -162,14 +162,7 @@ package body Instrument.Ada_Preprocessing is -- Create the requested file - declare - File : Ada.Text_IO.File_Type; - Doc : constant Unbounded_String := Result.Write (Compact => False); - begin - Create (File, Out_File, Filename); - Put_Line (File, Doc); - Close (File); - end; + JSON.Write (Filename, Result, Compact => False); end Create_Preprocessor_Data_File; ------------------------- From 4dcac6772eec60c7e7046c4264873555bc50c020 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 18 Jan 2024 10:38:43 +0000 Subject: [PATCH 0633/1483] DHTML/Text_Files/JSON: use Ada.Text_IO.Unbounded_IO to avoid hacks Use the Unbounded_IO runtime unit to write unbounded strings directly without 1) having to copy strings on the secondary stack or 2) having to use the non-standard Ada.Strings.Unbounded.Aux unit to retrieve the string buffer behind an unbounded string. --- tools/gnatcov/annotations-dynamic_html.adb | 15 +++------------ tools/gnatcov/json.adb | 17 +---------------- tools/gnatcov/text_files.adb | 12 ++++++++++++ tools/gnatcov/text_files.ads | 9 +++++++-- 4 files changed, 23 insertions(+), 30 deletions(-) diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index cbb3e1a51..b2d584526 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -20,10 +20,7 @@ with Ada.Characters.Handling; with Ada.Directories; use Ada.Directories; with Ada.Exceptions; use Ada.Exceptions; with Ada.Text_IO; - -pragma Warnings (Off, "* is an internal GNAT unit"); - with Ada.Strings.Unbounded.Aux; -pragma Warnings (On, "* is an internal GNAT unit"); +with Ada.Text_IO.Unbounded_IO; with GNATCOLL.JSON; use GNATCOLL.JSON; @@ -838,15 +835,9 @@ package body Annotations.Dynamic_Html is Output : Ada.Text_IO.File_Type; New_Line : Boolean := True) is - use Ada.Text_IO; - - Buffer : US.Aux.Big_String_Access; - Last : Natural; - First : constant Natural := US.Aux.Big_String'First; - + use Ada.Text_IO.Unbounded_IO; begin - US.Aux.Get_String (Item, Buffer, Last); - Put (File => Output, Item => Buffer (First .. Last)); + Put (File => Output, Item => Item); if New_Line then NL (Output => Output); diff --git a/tools/gnatcov/json.adb b/tools/gnatcov/json.adb index 92d720363..d89b523fa 100644 --- a/tools/gnatcov/json.adb +++ b/tools/gnatcov/json.adb @@ -16,10 +16,6 @@ -- of the license. -- ------------------------------------------------------------------------------ -pragma Warnings (Off, "* is an internal GNAT unit"); - with Ada.Strings.Unbounded.Aux; -pragma Warnings (On, "* is an internal GNAT unit"); - with GNAT.Strings; use GNAT.Strings; with Strings; use Strings; @@ -36,20 +32,9 @@ package body JSON is is File : Text_Files.File_Type; Content : constant Unbounded_String := Value.Write (Compact => Compact); - - Buffer : US.Aux.Big_String_Access; - First : constant Natural := US.Aux.Big_String'First; - Last : Natural; begin File.Create (Filename); - - -- Get direct access to the string access under the Content unbounded - -- string. This is the only way to write that string to a file without - -- copying the whole string. This is not just for performance: using - -- To_String could for instance make GNAT's secondary stack overflow. - - US.Aux.Get_String (Content, Buffer, Last); - File.Put (Buffer (First .. Last)); + File.Put (Content); end Write; ---------- diff --git a/tools/gnatcov/text_files.adb b/tools/gnatcov/text_files.adb index 2e4a21a43..91149d06a 100644 --- a/tools/gnatcov/text_files.adb +++ b/tools/gnatcov/text_files.adb @@ -16,6 +16,8 @@ -- of the license. -- ------------------------------------------------------------------------------ +with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO; + with GNAT.OS_Lib; with Outputs; @@ -113,6 +115,11 @@ package body Text_Files is Put (Self.File, Item); end Put; + procedure Put (Self : in out File_Type; Item : Unbounded_String) is + begin + Put (Self.File, Item); + end Put; + -------------- -- Put_Line -- -------------- @@ -122,6 +129,11 @@ package body Text_Files is Put_Line (Self.File, Item); end Put_Line; + procedure Put_Line (Self : in out File_Type; Item : Unbounded_String) is + begin + Put_Line (Self.File, Item); + end Put_Line; + -------------- -- New_Line -- -------------- diff --git a/tools/gnatcov/text_files.ads b/tools/gnatcov/text_files.ads index 9a1f2a298..bb2fb9261 100644 --- a/tools/gnatcov/text_files.ads +++ b/tools/gnatcov/text_files.ads @@ -21,7 +21,7 @@ private with Ada.Finalization; with Ada.Text_IO; -private with Strings; +with Strings; use Strings; package Text_Files is @@ -80,11 +80,17 @@ package Text_Files is procedure Put (Self : in out File_Type; Item : String) with Pre => Self.Is_Open, Inline; + procedure Put (Self : in out File_Type; Item : Unbounded_String) + with Pre => Self.Is_Open, + Inline; -- Write Item to Self procedure Put_Line (Self : in out File_Type; Item : String) with Pre => Self.Is_Open, Inline; + procedure Put_Line (Self : in out File_Type; Item : Unbounded_String) + with Pre => Self.Is_Open, + Inline; -- Write Item to Self and start a new line procedure New_Line (Self : in out File_Type) @@ -106,7 +112,6 @@ package Text_Files is private use Ada.Text_IO; - use Strings; type File_Type is new Ada.Finalization.Limited_Controlled with record File : Ada.Text_IO.File_Type; From 842cb2ded1c16481f5c5834a01f46dec39ab28fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 18 Jan 2024 14:09:12 +0100 Subject: [PATCH 0634/1483] Manual dump: Emit one helper unit per project per language Gnatcov used to only emit a single helper unit per project, either in Ada or in C, which effectivelly prevented the use of the feature when dump indications were contained both in C-like and Ada sources. Instead of tracking for which project a helper unit has already been generated, track instead the set of helper units which have been genereated. This way if two units in the same project require different helper units (because they aren't in the same language), both will get emitted. --- .../instr-cov/mixed_manual_dump/main_ada.adb | 7 +++ .../instr-cov/mixed_manual_dump/main_c.c | 8 +++ .../instr-cov/mixed_manual_dump/test.opt | 2 + .../tests/instr-cov/mixed_manual_dump/test.py | 50 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 27 +++++++--- tools/gnatcov/instrument-ada_unit.ads | 5 +- tools/gnatcov/instrument-c.adb | 11 ++-- tools/gnatcov/instrument-c.ads | 7 ++- tools/gnatcov/instrument-common.ads | 1 - tools/gnatcov/instrument-projects.adb | 33 ++++++------ 10 files changed, 115 insertions(+), 36 deletions(-) create mode 100644 testsuite/tests/instr-cov/mixed_manual_dump/main_ada.adb create mode 100644 testsuite/tests/instr-cov/mixed_manual_dump/main_c.c create mode 100644 testsuite/tests/instr-cov/mixed_manual_dump/test.opt create mode 100644 testsuite/tests/instr-cov/mixed_manual_dump/test.py diff --git a/testsuite/tests/instr-cov/mixed_manual_dump/main_ada.adb b/testsuite/tests/instr-cov/mixed_manual_dump/main_ada.adb new file mode 100644 index 000000000..b2860eb02 --- /dev/null +++ b/testsuite/tests/instr-cov/mixed_manual_dump/main_ada.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_Ada is +begin + Put_Line ("Hello Ada world!"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_Ada; diff --git a/testsuite/tests/instr-cov/mixed_manual_dump/main_c.c b/testsuite/tests/instr-cov/mixed_manual_dump/main_c.c new file mode 100644 index 000000000..66b8781b3 --- /dev/null +++ b/testsuite/tests/instr-cov/mixed_manual_dump/main_c.c @@ -0,0 +1,8 @@ +#include + +int +main (void) +{ + printf ("Hello C world!\n"); + /* GNATCOV_DUMP_BUFFERS */ +} diff --git a/testsuite/tests/instr-cov/mixed_manual_dump/test.opt b/testsuite/tests/instr-cov/mixed_manual_dump/test.opt new file mode 100644 index 000000000..f3556b9ad --- /dev/null +++ b/testsuite/tests/instr-cov/mixed_manual_dump/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD test feature specific to source traces +RTS_ZFP DEAD test uses stdio diff --git a/testsuite/tests/instr-cov/mixed_manual_dump/test.py b/testsuite/tests/instr-cov/mixed_manual_dump/test.py new file mode 100644 index 000000000..24c794663 --- /dev/null +++ b/testsuite/tests/instr-cov/mixed_manual_dump/test.py @@ -0,0 +1,50 @@ +""" +Check that using --dump-trigger=manual works correctly in projects where a +manual dump indication is present both in an Ada source and in a C-like source. + +This is a regression test, gnatcov used to not emit the helper unit for one of +the language kinds, resulting in the instrumented sources failing to build. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, run_cov_program + +Wdir("tmp_") + +# Name for the main_c executable trace +c_trace_name = "main_c.srctrace" + +# We can't build_run_and_coverage as the default trace name only depends on the +# project name so both mains would dump a trace with the same name (execution +# last less than a second). Instead, instrument and execute the first main +# through build_and_run, then run the second main manually. +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid="p", + srcdirs=[".."], + mains=["main_ada.adb", "main_c.c"], + langs=["Ada", "C"], + ) + ), + covlevel="stmt", + mains=["main_ada"], + dump_trigger="manual", + manual_prj_name="p", + extra_coverage_args=["-axcov", c_trace_name], +) + +run_cov_program("./main_c", env={"GNATCOV_TRACE_FILE": c_trace_name}) +xcov(cov_args) +check_xcov_reports( + "*.xcov", + { + "main_ada.adb.xcov": {"+": {5}}, + "main_c.c.xcov": {"+": {6}}, + }, + cwd="obj") + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 816759004..9ec2f4400 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8580,6 +8580,20 @@ package body Instrument.Ada_Unit is end if; end Emit_Pure_Buffer_Unit; + ----------------------------- + -- Dump_Manual_Helper_Unit -- + ----------------------------- + + overriding function Dump_Manual_Helper_Unit + (Self : Ada_Instrumenter_Type; + Prj : Prj_Desc) return Files_Table.Compilation_Unit + is + pragma Unreferenced (Self); + begin + return (Language => Unit_Based_Language, + Unit_Name => +To_Ada (Create_Manual_Helper_Unit_Name (Prj))); + end Dump_Manual_Helper_Unit; + ------------------------------------ -- Create_Manual_Helper_Unit_Name -- ------------------------------------ @@ -8891,28 +8905,25 @@ package body Instrument.Ada_Unit is ---------------------------------- procedure Emit_Dump_Helper_Unit_Manual - (Self : in out Ada_Instrumenter_Type; - Helper_Unit : out Unbounded_String; - Dump_Config : Any_Dump_Config; - Prj : Prj_Desc) + (Self : in out Ada_Instrumenter_Type; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc) is Main : Compilation_Unit_Part; -- Since the dump trigger is "manual" and there is no main to be given, -- the Main argument in the following call to Emit_Dump_Helper_Unit will -- not be used. - Ada_Helper_Unit : Ada_Qualified_Name; + Dummy_Ada_Helper_Unit : Ada_Qualified_Name; begin Emit_Dump_Helper_Unit (Dump_Config => Dump_Config, Instrumenter => Self, Prj => Prj, Main => Main, - Helper_Unit => Ada_Helper_Unit, + Helper_Unit => Dummy_Ada_Helper_Unit, Override_Dump_Trigger => Manual, Has_Controlled => False); - - Helper_Unit := +To_Ada (Ada_Helper_Unit); end Emit_Dump_Helper_Unit_Manual; ---------------------------- diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 4b939fdfe..60eefd3b4 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -85,10 +85,13 @@ package Instrument.Ada_Unit is overriding procedure Emit_Dump_Helper_Unit_Manual (Self : in out Ada_Instrumenter_Type; - Helper_Unit : out Unbounded_String; Dump_Config : Any_Dump_Config; Prj : Prj_Desc); + overriding function Dump_Manual_Helper_Unit + (Self : Ada_Instrumenter_Type; + Prj : Prj_Desc) return Files_Table.Compilation_Unit; + overriding procedure Replace_Manual_Dump_Indication (Self : in out Ada_Instrumenter_Type; Prj : in out Prj_Desc; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index dc2dadb1f..f4b3e4d68 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3831,21 +3831,22 @@ package body Instrument.C is ---------------------------------- overriding procedure Emit_Dump_Helper_Unit_Manual - (Self : in out C_Family_Instrumenter_Type; - Helper_Unit : out Unbounded_String; - Dump_Config : Any_Dump_Config; - Prj : Prj_Desc) + (Self : in out C_Family_Instrumenter_Type; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc) is Main : Compilation_Unit_Part; -- Since the dump trigger is "manual" and there is no main to be given, -- the Main argument in the following call to Emit_Dump_Helper_Unit will -- not be used. + Dummy_Unit_Name : Unbounded_String; + begin Emit_Dump_Helper_Unit (Dump_Config => Dump_Config, Main => Main, - Helper_Unit => Helper_Unit, + Helper_Unit => Dummy_Unit_Name, Instrumenter => Self, Prj => Prj); end Emit_Dump_Helper_Unit_Manual; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 28761cafb..9a5682a0a 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -74,10 +74,9 @@ package Instrument.C is -- procedure is put at the beginning of the file. overriding procedure Emit_Dump_Helper_Unit_Manual - (Self : in out C_Family_Instrumenter_Type; - Helper_Unit : out Unbounded_String; - Dump_Config : Any_Dump_Config; - Prj : Prj_Desc); + (Self : in out C_Family_Instrumenter_Type; + Dump_Config : Any_Dump_Config; + Prj : Prj_Desc); -- Emit the dump helper unit overriding procedure Emit_Buffers_List_Unit diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 94e7ffab4..55dde5972 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -474,7 +474,6 @@ package Instrument.Common is procedure Emit_Dump_Helper_Unit_Manual (Self : in out Language_Instrumenter; - Helper_Unit : out Unbounded_String; Dump_Config : Any_Dump_Config; Prj : Prj_Desc) is null; -- Emit the dump helper unit with the appropriate content to allow for a diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 2783e0c50..2e8c28847 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -130,9 +130,6 @@ is package File_Info_Sets is new Ada.Containers.Indefinite_Ordered_Sets (Element_Type => File_Info, "<" => Less, "=" => Equal); - package Prj_Has_Manual_Helper_Sets is new - Ada.Containers.Indefinite_Ordered_Sets (Element_Type => Unbounded_String); - type Library_Unit_Info is record Unit_Name : Unbounded_String; -- Name of this unit: unit name for unit-based languages, simple name @@ -683,9 +680,9 @@ is -- necessary to find the indication marking the location where the user -- wishes the Dump_Buffers call to be inserted. - Prj_Has_Manual_Helper : Prj_Has_Manual_Helper_Sets.Set; - -- In the case of a manual dump config, set of names of projects for which - -- a manual dump helper unit has already been emitted. + Emitted_Manual_Helpers : String_Sets.Set; + -- In the case of a manual dump config, set of names of manual dump helper + -- units that have been emitted thus far. ------------------------ -- Add_Project_Source -- @@ -848,7 +845,7 @@ is for Source of Project_Sources loop if To_Language (Source.Language) = Language then declare - use Prj_Has_Manual_Helper_Sets; + use String_Sets; Prj_Info : constant Project_Info_Access := Get_Or_Create_Project_Info (IC, Source.Project); @@ -857,8 +854,10 @@ is Prj.Prj_Name = Root_Project_Info.Project.Name; Source_Name : constant String := GNATCOLL.VFS."+" (Source.File.Full_Name); - Helper_Unit : Unbounded_String; Contained_Indication : Boolean := False; + Helper_Unit_Name : constant Unbounded_String := + Instrumenter.Dump_Manual_Helper_Unit (Prj).Unit_Name; + begin Instrumenter.Replace_Manual_Dump_Indication (Prj_Info.Desc, @@ -876,17 +875,17 @@ is Non_Root_Src_Calls.Include (Source_Name); end if; - -- Only generate one manual dump helper unit per project. At - -- this point, if the project's object directory and the - -- instrumented sources directory do not exist there is no need - -- to emit the dump helper unit. There are no units of interest - -- or call to a manual dump procedure for this project. + -- Check if we haven't already generated a helper unit for this + -- project and instrumenter. At this point, if the project's + -- object directory and the instrumented sources directory do + -- not exist there is no need to emit the dump helper unit. + -- There are no units of interest or call to a manual dump + -- procedure for this project. - if Prj_Has_Manual_Helper.Find (Prj.Prj_Name) = No_Element + if not Emitted_Manual_Helpers.Contains (Helper_Unit_Name) and then Dump_Helper_Output_Dir_Exists (Source, Prj) then - Instrumenter.Emit_Dump_Helper_Unit_Manual - (Helper_Unit, Dump_Config, Prj); + Instrumenter.Emit_Dump_Helper_Unit_Manual (Dump_Config, Prj); declare use Files_Table; @@ -930,7 +929,7 @@ is GNATCOLL.VFS.Unchecked_Free (Source_Files); end; - Prj_Has_Manual_Helper.Insert (Prj.Prj_Name); + Emitted_Manual_Helpers.Insert (Helper_Unit_Name); end if; Manual_Dump_Inserted := From 522a2207cc229bfa8b9263389ff120f9f8a16b81 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 15 Jan 2024 09:27:17 +0000 Subject: [PATCH 0635/1483] setup_rts.adb: minor reformatting --- tools/gnatcov/setup_rts.adb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 801cc4302..fe49732f8 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -24,8 +24,8 @@ with Ada.Exceptions; use Ada.Exceptions; with GNAT.OS_Lib; with GNAT.Regexp; -with GNATCOLL.JSON; use GNATCOLL.JSON; -with GNATCOLL.VFS; use GNATCOLL.VFS; +with GNATCOLL.JSON; use GNATCOLL.JSON; +with GNATCOLL.VFS; use GNATCOLL.VFS; with GPR2.Context; with GPR2.Containers; with GPR2.Log; @@ -36,12 +36,12 @@ with GPR2.Project.Configuration; with GPR2.Project.Registry.Attribute; with GPR2.Project.Tree; -with JSON; use JSON; -with Outputs; use Outputs; -with Paths; use Paths; -with Subprocesses; use Subprocesses; +with JSON; use JSON; +with Outputs; use Outputs; +with Paths; use Paths; +with Subprocesses; use Subprocesses; with Support_Files; -with Temp_Dirs; use Temp_Dirs; +with Temp_Dirs; use Temp_Dirs; with Text_Files; package body Setup_RTS is From 1c5fcc128780f4ebc1f328431613a65d93e691c7 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 15 Jan 2024 12:42:13 +0000 Subject: [PATCH 0636/1483] instrument-setup_config.ads: add missing documentation --- tools/gnatcov/instrument-setup_config.ads | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-setup_config.ads b/tools/gnatcov/instrument-setup_config.ads index c5dd584c5..1b62079dd 100644 --- a/tools/gnatcov/instrument-setup_config.ads +++ b/tools/gnatcov/instrument-setup_config.ads @@ -57,8 +57,25 @@ package Instrument.Setup_Config is Dump_Config : Any_Dump_Config; Compiler_Drivers : String_Sets.Set; Output_Dir : String); - -- Setup the configuration to use the integrated-mode of gnatcov + -- Setup the configuration to use the integrated-mode of gnatcov. + -- + -- Files_Of_Interest is the set of files that needs to be instrumented as + -- units of interest. + -- + -- Coverage_Level is the coverage level for which to instrument the files + -- of interest. + -- + -- Dump_Config is the dump configuration to use for the sources to + -- instrument. + -- + -- Compiler_Drivers is the set of names for the compiler drivers to wrap + -- for instrumentation. + -- + -- Output_Dir is the name of the directory in which the compiler wrappers + -- and instrumentation artifacts are put. function Load_Config (Config_File : String) return Instrumentation_Config; + -- Read the configuration file that "gnatcov setup-integration" created and + -- return the instrumentation configuration that is decoded from it. end Instrument.Setup_Config; From cb115e5c99afaec3fb7b59801e20081ae8beb646 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 15 Jan 2024 12:48:05 +0000 Subject: [PATCH 0637/1483] gnatcov setup-integration: fix support for --runtime-project --- .../168-rts_error_msg/test.py | 19 ++++++++----------- tools/gnatcov/gnatcov_bits_specific.adb | 3 ++- tools/gnatcov/instrument-setup_config.adb | 13 ++++++++----- tools/gnatcov/instrument-setup_config.ads | 6 +++++- 4 files changed, 23 insertions(+), 18 deletions(-) diff --git a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py index 7cdf7c550..b93e6f5cd 100644 --- a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py +++ b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py @@ -3,15 +3,9 @@ is helpful when failing to load the coverage runtime project. """ -import os - from SUITE.cutils import Wdir from SUITE.tutils import contents_of, thistest, xcov -# Point gnatcov towards our invalid GNATcov_RTS project -env = os.environ -env["GPR_PROJECT_PATH"] = os.getcwd() - tmp = Wdir("tmp_") # Try to setup for a simple main file @@ -22,8 +16,8 @@ "-cstmt+mcdc", "--output-dir=.", "--files=../main.c", + "--runtime-project=no_such_gnatcov_rts", ], - env=env, out=integration_log, register_failure=False ) @@ -34,10 +28,13 @@ # runtime. thistest.fail_if_no_match( what="gnatcov error message", - regexp=r".*gnatcov(\.exe)?: Failed locating or loading gnatcov_rts\.gpr" - r"(\n|.)*Is the project available on the GPR_PROJECT_PATH\?" - r"(\n|.)*gprls output was:" - r"(\n|.)*", + regexp=( + r".*gnatcov(\.exe)?: Failed locating or loading the" + r" no_such_gnatcov_rts project file" + r"(\n|.)*Is the project available on the GPR_PROJECT_PATH\?" + r"(\n|.)*gprls output was:" + r"(\n|.)*" + ), actual=contents_of(integration_log), ) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index b6b063af2..fc5c2cf7e 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1395,7 +1395,8 @@ begin Coverage_Level => Coverage_Option_Value, Dump_Config => Dump_Config, Compiler_Drivers => Compiler_Drivers_Set, - Output_Dir => Get_Output_Dir); + Output_Dir => Get_Output_Dir, + Runtime_Project => Runtime_Project); end; when Cmd_Gcc_Wrapper => diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index 4a6d96de8..07757de15 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -110,7 +110,8 @@ package body Instrument.Setup_Config is Coverage_Level : String; Dump_Config : Any_Dump_Config; Compiler_Drivers : String_Sets.Set; - Output_Dir : String) + Output_Dir : String; + Runtime_Project : String) is Config : constant JSON_Value := Create_Object; Compilers : constant JSON_Value := Create_Object; @@ -121,8 +122,8 @@ package body Instrument.Setup_Config is -- For each compiler driver, location of the nm executable begin - -- Find the installed gnatcov_rts, using gprls. TODO??? Deal with cross - -- cases. + -- Find the installed coverage runtime, using gprls. TODO??? Deal with + -- cross cases. -- -- We are looking for the following lines: -- Source Search Path: @@ -141,7 +142,7 @@ package body Instrument.Setup_Config is GPRLS_Success : Boolean; begin Args.Append (+"-P"); - Args.Append (+"gnatcov_rts"); + Args.Append (+Runtime_Project); Args.Append (+"-vP1"); GPRLS_Success := Run_Command (Command => "gprls", @@ -151,7 +152,9 @@ package body Instrument.Setup_Config is Ignore_Error => True); Open (Output_File, In_File, Output_Filename); if not GPRLS_Success then - Outputs.Error ("Failed locating or loading gnatcov_rts.gpr"); + Outputs.Error + ("Failed locating or loading the " & Runtime_Project + & " project file"); Warning_Or_Error ("Is the project available on the" & " GPR_PROJECT_PATH?"); Warning_Or_Error ("gprls output was:"); diff --git a/tools/gnatcov/instrument-setup_config.ads b/tools/gnatcov/instrument-setup_config.ads index 1b62079dd..ff589e001 100644 --- a/tools/gnatcov/instrument-setup_config.ads +++ b/tools/gnatcov/instrument-setup_config.ads @@ -56,7 +56,8 @@ package Instrument.Setup_Config is Coverage_Level : String; Dump_Config : Any_Dump_Config; Compiler_Drivers : String_Sets.Set; - Output_Dir : String); + Output_Dir : String; + Runtime_Project : String); -- Setup the configuration to use the integrated-mode of gnatcov. -- -- Files_Of_Interest is the set of files that needs to be instrumented as @@ -73,6 +74,9 @@ package Instrument.Setup_Config is -- -- Output_Dir is the name of the directory in which the compiler wrappers -- and instrumentation artifacts are put. + -- + -- Runtime_Project is the name of the coverage runtime project that was + -- installed by "gnatcov setup". function Load_Config (Config_File : String) return Instrumentation_Config; -- Read the configuration file that "gnatcov setup-integration" created and From 368ca6609692d2c3a885e71e99bfc8aab595e0b0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 15 Jan 2024 10:53:29 +0000 Subject: [PATCH 0638/1483] gnatcov_bits_specific.adb: minor refactoring --- tools/gnatcov/gnatcov_bits_specific.adb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index fc5c2cf7e..c09c2eb6b 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1376,10 +1376,10 @@ begin Value (Args, Opt_Runtime_Project, "gnatcov_rts"); Setup_Cfg : constant Setup_Config := Load - ("", - "", - Value (Args, Opt_Config), - Runtime_Project); + (Target => "", + RTS => "", + Config_File => Value (Args, Opt_Config), + Runtime_Project => Runtime_Project); -- TODO??? We should not leave the target and runtime empty, but -- we have no project to load here. From 85159e5c3cfb38c80e0657c21288da70d4e9b972 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 15 Jan 2024 13:10:36 +0000 Subject: [PATCH 0639/1483] Treat coverage runtime loading failure as a fatal error Attempts to load the coverage runtime in gnatcov were so far optional: in case of failure (gnatcov_rts.gpr cannot be found, wrong target/RTS is used, ...) some output was produced in verbose mode and processing continued with default settings instead of using the configuration that was supposed to be loaded from the coverage runtime. This proved to be a burden for users, as issues that could be detected at "gnatcov instrument" time were invisible, and caused hard to diagnose problems later on (for instance when building instrumented programs). To fix this, make gnatcov abort when it cannot successfully extract information from the coverage runtime project. --- .../168-rts_error_msg/test.py | 10 +- tools/gnatcov/instrument-setup_config.adb | 18 +-- tools/gnatcov/setup_rts.adb | 149 ++++++++---------- tools/gnatcov/setup_rts.ads | 2 +- 4 files changed, 73 insertions(+), 106 deletions(-) diff --git a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py index b93e6f5cd..3d9ba7ad8 100644 --- a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py +++ b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py @@ -29,13 +29,11 @@ thistest.fail_if_no_match( what="gnatcov error message", regexp=( - r".*gnatcov(\.exe)?: Failed locating or loading the" - r" no_such_gnatcov_rts project file" - r"(\n|.)*Is the project available on the GPR_PROJECT_PATH\?" - r"(\n|.)*gprls output was:" - r"(\n|.)*" + ".*gnatcov.*: Could not load the coverage runtime project" + " no_such_gnatcov_rts" + "\nno_such_gnatcov_rts\\.gpr: error: project file \".*\" not found" ), - actual=contents_of(integration_log), + actual=contents_of(integration_log).strip(), ) thistest.result() diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index 07757de15..4c38c7295 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -139,30 +139,16 @@ package body Instrument.Setup_Config is Output_Filename : constant String := Output_Dir / "gprls_output"; Output_File : File_Type; - GPRLS_Success : Boolean; begin Args.Append (+"-P"); Args.Append (+Runtime_Project); Args.Append (+"-vP1"); - GPRLS_Success := Run_Command + Run_Command (Command => "gprls", Arguments => Args, Origin_Command_Name => "gnatcov setup-integration", - Output_File => Output_Filename, - Ignore_Error => True); + Output_File => Output_Filename); Open (Output_File, In_File, Output_Filename); - if not GPRLS_Success then - Outputs.Error - ("Failed locating or loading the " & Runtime_Project - & " project file"); - Warning_Or_Error ("Is the project available on the" - & " GPR_PROJECT_PATH?"); - Warning_Or_Error ("gprls output was:"); - while not End_Of_File (Output_File) loop - Warning_Or_Error (Get_Line (Output_File)); - end loop; - raise Xcov_Exit_Exc; - end if; while not End_Of_File (Output_File) loop declare Line : constant String := Get_Line (Output_File); diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index fe49732f8..64df9560b 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -16,10 +16,9 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Directories; use Ada.Directories; +with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Directories; use Ada.Directories; with Ada.Environment_Variables; -with Ada.Exceptions; use Ada.Exceptions; with GNAT.OS_Lib; with GNAT.Regexp; @@ -139,11 +138,6 @@ package body Setup_RTS is -- If Library_Kind is not an empty string, build for that library kind and -- install it as a variant. - Load_Setup_Config_Error : exception; - -- Exception raised when loading the setup config file failed (because the - -- runtime project could not be loaded / the config file could not be - -- decoded etc.). - function Load (Project_File : String; Setup_Config_File : Virtual_File) return Setup_Config; @@ -156,11 +150,6 @@ package body Setup_RTS is -- Return the base filename for the setup config file corresponding to the -- given Project_Name. - function Load (J : JSON_Value) return Setup_Config - with Pre => J.Kind = JSON_Object_Type; - -- Helper for the public Load function: load a setup config from the given - -- JSON document. - procedure Save_Setup_Config (Project_Dir : String; Project_Name : String; @@ -859,7 +848,6 @@ package body Setup_RTS is Config_File : String; Runtime_Project : String) return Setup_Config is - Result : Setup_Config := Default_Setup_Config; Setup_Config_File : Virtual_File; Prj_Ext : constant String := ".gpr"; @@ -887,14 +875,15 @@ package body Setup_RTS is -- fails to load, just return the default setup config. Load_Project (Prj, Prj_Filename, Target, RTS, Config_File); - if Prj.Log_Messages.Has_Error then - if Setup_RTS_Trace.Is_Active then - Setup_RTS_Trace.Trace - ("Could not load the coverage runtime project to get dump" - & " options defaults: " & Runtime_Project); - Prj.Log_Messages.Output_Messages; - end if; - raise Load_Setup_Config_Error; + if Prj.Log_Messages.Has_Error + or else (Src_Enabled_Languages (Ada_Language) + and then not Prj.Has_Runtime_Project) + then + Error + ("Could not load the coverage runtime project " & Runtime_Project); + Prj.Log_Messages.Output_Messages + (Information => Setup_RTS_Trace.Is_Active); + raise Xcov_Exit_Exc; end if; -- The project file is in $PREFIX/share/gpr, so get $PREFIX first and @@ -915,73 +904,59 @@ package body Setup_RTS is Prefix / (+"share") / (+"gnatcov_rts") / (+Config_File_Basename); end; - if Setup_Config_File.Is_Regular_File then - Result := Load (+Project_File.Full_Name, Setup_Config_File); - elsif Setup_RTS_Trace.Is_Active then - Setup_RTS_Trace.Trace + if not Setup_Config_File.Is_Regular_File then + Error ("Could not find the setup config file: " & (+Setup_Config_File.Full_Name)); - raise Load_Setup_Config_Error; + Fatal_Error + ("Please install the coverage runtime with ""gnatcov setup"""); end if; - -- At that point, setup config file was loaded successfully. Otherwise, - -- we will return through the below exception handler. - - Setup_RTS_Trace.Trace - ("Successfully loaded the setup configuration file " - & (+Setup_Config_File.Full_Name) & "."); - return Result; - - exception - when Load_Setup_Config_Error => - return Result; + return Result : constant Setup_Config := + Load (+Project_File.Full_Name, Setup_Config_File) + do + Setup_RTS_Trace.Trace + ("Successfully loaded the setup configuration file " + & (+Setup_Config_File.Full_Name) & "."); + end return; end Load; function Load (Project_File : String; Setup_Config_File : Virtual_File) return Setup_Config is - -- Load and parse the setup config file + J : JSON_Value; + -- Top-level object in the Setup_Config_File JSON file, validated to be + -- an object (JSON mapping). - Parsed_JSON : constant Read_Result := Read (Setup_Config_File); - begin - -- If parsing was successful, load the various parameters from the JSON - -- document. Otherwise, unless the verbose mode is active, silently - -- ignore the setup config file. - - if Parsed_JSON.Success then - if Parsed_JSON.Value.Kind = JSON_Object_Type then - return Result : Setup_Config := Load (Parsed_JSON.Value) do - Result.Project_File := +Project_File; - end return; - end if; - - elsif Setup_RTS_Trace.Is_Active then - Setup_RTS_Trace.Trace - ("Parsing error while reading the setup config file:"); - Setup_RTS_Trace.Trace (Format_Parsing_Error (Parsed_JSON.Error)); - end if; - - raise Load_Setup_Config_Error; - end Load; - - function Load (J : JSON_Value) return Setup_Config is - - Format_Error : exception; - -- Exception to raise in this function when the format of the setup - -- config file is unexpected and loading it cannot continue. + procedure Stop_With_Error (Message : String) with No_Return; + -- Output an error for the loading of the config file with the given + -- message and raise a Xcov_Exit_Exc exception. procedure Check_Field (Name : String; Kind : JSON_Value_Type); - -- Raise a Format_Error exception if J does not have a Name field or if - -- that field does not have the given kind. + -- Stop with a fatal error if J does not have a Name field or if that + -- field does not have the given kind. function Get (Name : String) return Unbounded_String; - -- Return the Name field in J as a string. If there is no such field or - -- if it is not a string, raise a Format_Error exception. + -- Return the Name field in J as a string. Stop with a fatal error if + -- there is no such field or if it is not a string. function Get (Name : String) return Boolean; -- Likewise, but for a boolean field + --------------------- + -- Stop_With_Error -- + --------------------- + + procedure Stop_With_Error (Message : String) is + begin + Error + ("Error while loading the setup config file " + & (+Setup_Config_File.Full_Name)); + Error (Message); + raise Xcov_Exit_Exc; + end Stop_With_Error; + ----------------- -- Check_Field -- ----------------- @@ -989,11 +964,11 @@ package body Setup_RTS is procedure Check_Field (Name : String; Kind : JSON_Value_Type) is begin if not J.Has_Field (Name) then - raise Format_Error with "missing " & Name & " field"; + Stop_With_Error ("missing " & Name & " field"); end if; if J.Get (Name).Kind /= Kind then - raise Format_Error with "invalid " & Name & " field"; + Stop_With_Error ("invalid " & Name & " field"); end if; end Check_Field; @@ -1013,12 +988,27 @@ package body Setup_RTS is return J.Get (Name); end Get; - Result : Setup_Config := Default_Setup_Config; + -- Load and parse the setup config file + + Parsed_JSON : constant Read_Result := Read (Setup_Config_File); + Result : Setup_Config := Default_Setup_Config; Channel : Any_Dump_Channel; Trigger : Any_Dump_Trigger; + -- Start of processing for Load + begin + if not Parsed_JSON.Success then + Stop_With_Error (Format_Parsing_Error (Parsed_JSON.Error)); + end if; + + Result.Project_File := +Project_File; + J := Parsed_JSON.Value; + if J.Kind /= JSON_Object_Type then + Stop_With_Error ("Object expected at the top-level"); + end if; + declare RTS_Profile : constant String := +Get ("rts-profile"); begin @@ -1026,21 +1016,21 @@ package body Setup_RTS is Result.RTS_Profile_Present := True; exception when Constraint_Error => - raise Format_Error with "invalid rts-profile field"; + Stop_With_Error ("invalid rts-profile field"); end; begin Channel := Value (+Get ("dump-channel")); exception when Constraint_Error => - raise Format_Error with "invalid dump-channel field"; + Stop_With_Error ("invalid dump-channel field"); end; begin Trigger := Value (+Get ("dump-trigger")); exception when Constraint_Error => - raise Format_Error with "invalid dump-trigger field"; + Stop_With_Error ("invalid dump-trigger field"); end; case Channel is @@ -1059,13 +1049,6 @@ package body Setup_RTS is end case; return Result; - - exception - when Exc : Format_Error => - Setup_RTS_Trace.Trace - ("Setup config file decoding error: " - & Exception_Information (Exc)); - raise Load_Setup_Config_Error; end Load; ----------------------- diff --git a/tools/gnatcov/setup_rts.ads b/tools/gnatcov/setup_rts.ads index 47e406607..6655a225a 100644 --- a/tools/gnatcov/setup_rts.ads +++ b/tools/gnatcov/setup_rts.ads @@ -124,7 +124,7 @@ package Setup_RTS is -- Load the setup config associated to the project file called -- Runtime_Project (that project is loaded using Target, RTS and -- Config_File). If we cannot load the runtime project file or if the setup - -- config is missing from this project, just return Default_Setup_Config. + -- config is missing from this project, abort with a fatal error. function Check_RTS_Profile (Profile : Resolved_RTS_Profile; From e97826bfd4a274a137e0e4a07348f04df2a660b7 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 19 Jan 2024 08:45:29 +0000 Subject: [PATCH 0640/1483] instr-cov/config_pragmas: use Simple_Barriers for old compilers The Pure_Barriers resrtiction did not exist for GNAT 5.04a1 or 7.1.2. Use Simple_Barriers instead so that this testcase works with older compilers. --- testsuite/tests/instr-cov/config_pragmas/gnat.adc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/instr-cov/config_pragmas/gnat.adc b/testsuite/tests/instr-cov/config_pragmas/gnat.adc index a832dd386..20d438eb6 100644 --- a/testsuite/tests/instr-cov/config_pragmas/gnat.adc +++ b/testsuite/tests/instr-cov/config_pragmas/gnat.adc @@ -1 +1 @@ -pragma Restrictions (Pure_Barriers); +pragma Restrictions (Simple_Barriers); From 293d7b8548538dffe2c16fac3d39c9faf3c9c73d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 19 Jan 2024 08:50:10 +0000 Subject: [PATCH 0641/1483] instrument-ada_preprocessing.adb: remove useless WITH clause --- tools/gnatcov/instrument-ada_preprocessing.adb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/instrument-ada_preprocessing.adb b/tools/gnatcov/instrument-ada_preprocessing.adb index c65096ca0..d2e31aca5 100644 --- a/tools/gnatcov/instrument-ada_preprocessing.adb +++ b/tools/gnatcov/instrument-ada_preprocessing.adb @@ -16,9 +16,8 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Exceptions; use Ada.Exceptions; -with Ada.Text_IO; use Ada.Text_IO; -with Ada.Text_IO.Unbounded_IO; use Ada.Text_IO.Unbounded_IO; +with Ada.Exceptions; use Ada.Exceptions; +with Ada.Text_IO; use Ada.Text_IO; with GNATCOLL.JSON; use GNATCOLL.JSON; From 6a29996cc35618484867883bd60810d5b6e5df1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 19 Jan 2024 13:40:38 +0100 Subject: [PATCH 0642/1483] gnatcov_rts: reformat various files --- tools/gnatcov/rts/gnatcov_rts_c-buffers.c | 22 ++++++------ .../rts/gnatcov_rts_c-traces-output-base64.c | 4 +-- .../rts/gnatcov_rts_c-traces-output-files.c | 36 +++++++++---------- .../gnatcov/rts/gnatcov_rts_c-traces-output.c | 30 ++++++++-------- 4 files changed, 46 insertions(+), 46 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c index 953d68170..e7c534c66 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c @@ -30,8 +30,8 @@ gnatcov_rts_witness (uint8_t *buffer, gnatcov_rts_bit_id bit) gnatcov_rts_bool gnatcov_rts_witness_decision (uint8_t *buffer, gnatcov_rts_bit_id false_bit, - gnatcov_rts_bit_id true_bit, - gnatcov_rts_bool value) + gnatcov_rts_bit_id true_bit, + gnatcov_rts_bool value) { gnatcov_rts_witness (buffer, value ? true_bit : false_bit); return value; @@ -39,23 +39,23 @@ gnatcov_rts_witness_decision (uint8_t *buffer, gnatcov_rts_bit_id false_bit, gnatcov_rts_bool gnatcov_rts_witness_decision_mcdc (uint8_t *decision_buffer, - gnatcov_rts_bit_id false_bit, - gnatcov_rts_bit_id true_bit, - uint8_t *mcdc_buffer, - gnatcov_rts_bit_id mcdc_base, - gnatcov_rts_bit_id *mcdc_path_address, - gnatcov_rts_bool value) + gnatcov_rts_bit_id false_bit, + gnatcov_rts_bit_id true_bit, + uint8_t *mcdc_buffer, + gnatcov_rts_bit_id mcdc_base, + gnatcov_rts_bit_id *mcdc_path_address, + gnatcov_rts_bool value) { gnatcov_rts_bit_id mcdc_path_index = *mcdc_path_address; gnatcov_rts_witness (mcdc_buffer, mcdc_base + mcdc_path_index); return gnatcov_rts_witness_decision (decision_buffer, false_bit, true_bit, - value); + value); } gnatcov_rts_bool gnatcov_rts_witness_condition (gnatcov_rts_bit_id *mcdc_path_address, - gnatcov_rts_bit_id offset_for_true, - gnatcov_rts_bool first, gnatcov_rts_bool value) + gnatcov_rts_bit_id offset_for_true, + gnatcov_rts_bool first, gnatcov_rts_bool value) { gnatcov_rts_bit_id *mcdc_path_index = (gnatcov_rts_bit_id *) mcdc_path_address; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c index b483a1bab..ee2c133a9 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c @@ -124,7 +124,7 @@ write_bytes (void *output, const void *bytes, unsigned count) buffer->bytes[buffer->next] = bytes_array[i]; buffer->next = buffer->next + 1; if (buffer->next == 3) - flush (buffer); + flush (buffer); } return 0; } @@ -141,7 +141,7 @@ gnatcov_rts_write_trace_file_base64 ( gnatcov_rts_put_string (newline_string); gnatcov_rts_put_string (begin_string); gnatcov_rts_generic_write_trace_file (&buffer, buffers_groups, program_name, - exec_date, user_data, write_bytes); + exec_date, user_data, write_bytes); flush (&buffer); if (buffer.columns != 0) gnatcov_rts_put_string (newline_string); diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c index 27312de53..badb889ad 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c @@ -95,7 +95,7 @@ concat (const char *s1, ...) gnatcov_rts_default_trace_filename for more information. */ char * gnatcov_rts_default_trace_basename (const char *prefix, const char *tag, - unsigned simple) + unsigned simple) { char *extension = ".srctrace"; if (simple) @@ -120,7 +120,7 @@ gnatcov_rts_default_trace_basename (const char *prefix, const char *tag, /* See gnatcov_rts_cc-traces-output-files.h. */ char * gnatcov_rts_default_trace_filename (const char *env_var, const char *prefix, - const char *tag, unsigned simple) + const char *tag, unsigned simple) { char *env_trace_filename = getenv (env_var); @@ -129,25 +129,25 @@ gnatcov_rts_default_trace_filename (const char *env_var, const char *prefix, else { /* The caller is supposed to free the returned string, so create a - copy. */ + copy. */ env_trace_filename = concat (env_trace_filename, NULL); /* If the filename ends with a directory separator, consider that it - refers to a directory: in that case return a filename inside it. */ + refers to a directory: in that case return a filename inside it. */ size_t length = strlen (env_trace_filename); if (length > 0 - && (env_trace_filename[length - 1] == '/' - || env_trace_filename[length - 1] == '\\')) - { - char *basename - = gnatcov_rts_default_trace_basename (prefix, tag, simple); - char *res = concat (env_trace_filename, basename, NULL); - free (env_trace_filename); - free (basename); - return res; - } + && (env_trace_filename[length - 1] == '/' + || env_trace_filename[length - 1] == '\\')) + { + char *basename + = gnatcov_rts_default_trace_basename (prefix, tag, simple); + char *res = concat (env_trace_filename, basename, NULL); + free (env_trace_filename); + free (basename); + return res; + } else - return env_trace_filename; + return env_trace_filename; } } @@ -163,7 +163,7 @@ gnatcov_rts_write_trace_file ( return 1; gnatcov_rts_generic_write_trace_file (file, buffers_groups, program_name, - exec_date, user_data, write_bytes); + exec_date, user_data, write_bytes); fclose (file); return 0; } @@ -176,8 +176,8 @@ gnatcov_rts_write_trace_file_wrapper ( uint64_t exec_date, struct gnatcov_rts_string user_data) { if (gnatcov_rts_write_trace_file (buffers_groups, filename, program_name, - exec_date, user_data) + exec_date, user_data) != 0) fprintf (stderr, "Error occurred while creating the trace file %s: %s\n", - filename, strerror (errno)); + filename, strerror (errno)); } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index a8f2ce232..3c80a5738 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -32,7 +32,7 @@ struct info_entry /* Write `count` padding bytes. */ static void write_padding (gnatcov_rts_write_bytes_callback write_bytes, void *output, - unsigned count) + unsigned count) { unsigned pad_count = (alignment - count) % alignment; if (pad_count != alignment) @@ -61,7 +61,7 @@ write_header (gnatcov_rts_write_bytes_callback write_bytes, void *output) /* Write an information entry (e.g. the program_name, the exec date etc.). */ static void write_info (gnatcov_rts_write_bytes_callback write_bytes, void *output, - uint32_t kind, struct info_entry *data) + uint32_t kind, struct info_entry *data) { struct trace_info_header header; header.kind = kind; @@ -90,7 +90,7 @@ flush (gnatcov_rts_write_bytes_callback write_bytes, void *output, /* Write a coverage bit buffer. */ static void write_buffer (gnatcov_rts_write_bytes_callback write_bytes, void *output, - uint8_t *buffer, unsigned buffer_length) + uint8_t *buffer, unsigned buffer_length) { uint8_t current_byte = 0; uint8_t bit_mask = 1; @@ -100,11 +100,11 @@ write_buffer (gnatcov_rts_write_bytes_callback write_bytes, void *output, for (i = 0; i < buffer_length; i++) { if (buffer[i]) - current_byte = current_byte | bit_mask; + current_byte = current_byte | bit_mask; if (bit_mask == 1 << 7) - flush (write_bytes, output, &bit_mask, ¤t_byte, &bytes_count); + flush (write_bytes, output, &bit_mask, ¤t_byte, &bytes_count); else - bit_mask <<= 1; + bit_mask <<= 1; } flush (write_bytes, output, &bit_mask, ¤t_byte, &bytes_count); @@ -114,7 +114,7 @@ write_buffer (gnatcov_rts_write_bytes_callback write_bytes, void *output, /* Write a coverage buffer (unit information + coverage bit buffers). */ static void write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, - const struct gnatcov_rts_coverage_buffers *buffers) + const struct gnatcov_rts_coverage_buffers *buffers) { struct trace_entry_header header; header.unit_name_length = (uint32_t) buffers->unit_name.length; @@ -127,23 +127,23 @@ write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, memset (header.padding, 0, 5); memcpy (&header.fingerprint, buffers->fingerprint, FINGERPRINT_SIZE); memcpy (&header.bit_maps_fingerprint, buffers->bit_maps_fingerprint, - FINGERPRINT_SIZE); + FINGERPRINT_SIZE); write_bytes (output, (char *) &header, sizeof (header)); write_bytes (output, buffers->unit_name.str, buffers->unit_name.length); write_padding (write_bytes, output, buffers->unit_name.length); write_buffer (write_bytes, output, buffers->statement, - buffers->statement_last_bit + 1); + buffers->statement_last_bit + 1); write_buffer (write_bytes, output, buffers->decision, - buffers->decision_last_bit + 1); + buffers->decision_last_bit + 1); write_buffer (write_bytes, output, buffers->mcdc, - buffers->mcdc_last_bit + 1); + buffers->mcdc_last_bit + 1); } /* Write a uint64_t timestamp (by splitting it in uint8_t chunks). */ void write_date (gnatcov_rts_write_bytes_callback write_bytes, void *output, - uint64_t timestamp) + uint64_t timestamp) { uint8_t formatted_date[8]; struct info_entry entry; @@ -185,17 +185,17 @@ gnatcov_rts_generic_write_trace_file ( write_header (write_bytes, output); write_info (write_bytes, output, GNATCOV_RTS_INFO_PROGRAM_NAME, - &program_name_entry); + &program_name_entry); write_date (write_bytes, output, exec_date); write_info (write_bytes, output, GNATCOV_RTS_INFO_USER_DATA, - &user_data_entry); + &user_data_entry); write_info (write_bytes, output, GNATCOV_RTS_INFO_END, &end_entry); for (i_group = 0; i_group < buffers_groups->length; ++i_group) { group = buffers_groups->groups[i_group]; for (i_buffer = 0; i_buffer < group->length; ++i_buffer) - write_entry (write_bytes, output, group->buffers[i_buffer]); + write_entry (write_bytes, output, group->buffers[i_buffer]); } return 0; From 975780c32511d3ee4727661f5252f3460c38e520 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 19 Jan 2024 14:09:27 +0100 Subject: [PATCH 0643/1483] instr-cov/mixed_manual_dump: various fixes Call the proper program under Windows and propagate the full environment. Properly set the exit status in the C main. --- testsuite/tests/instr-cov/mixed_manual_dump/main_c.c | 1 + testsuite/tests/instr-cov/mixed_manual_dump/test.py | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/instr-cov/mixed_manual_dump/main_c.c b/testsuite/tests/instr-cov/mixed_manual_dump/main_c.c index 66b8781b3..0323c2bc8 100644 --- a/testsuite/tests/instr-cov/mixed_manual_dump/main_c.c +++ b/testsuite/tests/instr-cov/mixed_manual_dump/main_c.c @@ -5,4 +5,5 @@ main (void) { printf ("Hello C world!\n"); /* GNATCOV_DUMP_BUFFERS */ + return 0; } diff --git a/testsuite/tests/instr-cov/mixed_manual_dump/test.py b/testsuite/tests/instr-cov/mixed_manual_dump/test.py index 24c794663..7da30d009 100644 --- a/testsuite/tests/instr-cov/mixed_manual_dump/test.py +++ b/testsuite/tests/instr-cov/mixed_manual_dump/test.py @@ -6,11 +6,13 @@ the language kinds, resulting in the instrumented sources failing to build. """ +import os + from SCOV.minicheck import build_and_run, check_xcov_reports, xcov from SUITE.context import thistest from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches -from SUITE.tutils import gprfor, run_cov_program +from SUITE.tutils import gprfor, run_cov_program, exepath_to Wdir("tmp_") @@ -37,13 +39,15 @@ extra_coverage_args=["-axcov", c_trace_name], ) -run_cov_program("./main_c", env={"GNATCOV_TRACE_FILE": c_trace_name}) +env = dict(os.environ) +env["GNATCOV_TRACE_FILE"] = c_trace_name +run_cov_program(exepath_to("main_c"), env=env) xcov(cov_args) check_xcov_reports( "*.xcov", { "main_ada.adb.xcov": {"+": {5}}, - "main_c.c.xcov": {"+": {6}}, + "main_c.c.xcov": {"+": {6}, '-': {8}}, }, cwd="obj") From 6c3cbb9fb43094d73ab58a0e8af9fbf89488371a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 19 Jan 2024 16:42:49 +0100 Subject: [PATCH 0644/1483] instr-cov/mixed_manual_dump: XFAIL test for cross configurations There's an inconsistency in the order of object files / library files on the command line generated by gprbuild depending on whether there is only a C main in the projet or both C and Ada mains. In the later case (this test), our last chance handler setup fails to properly build. --- testsuite/tests/instr-cov/mixed_manual_dump/test.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/instr-cov/mixed_manual_dump/test.opt b/testsuite/tests/instr-cov/mixed_manual_dump/test.opt index f3556b9ad..656b7e211 100644 --- a/testsuite/tests/instr-cov/mixed_manual_dump/test.opt +++ b/testsuite/tests/instr-cov/mixed_manual_dump/test.opt @@ -1,2 +1,3 @@ bin-traces DEAD test feature specific to source traces RTS_ZFP DEAD test uses stdio +!native XFAIL Build failure with mixed language mains. See #212 From 9592fa3de60a034be50b620730db82d91df2a436 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 22 Jan 2024 12:40:11 +0000 Subject: [PATCH 0645/1483] setup_rts.adb: do not attempt to load setup config for CCG --- tools/gnatcov/setup_rts.adb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 64df9560b..a2e0a21ba 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -38,6 +38,7 @@ with GPR2.Project.Tree; with JSON; use JSON; with Outputs; use Outputs; with Paths; use Paths; +with Project; with Subprocesses; use Subprocesses; with Support_Files; with Temp_Dirs; use Temp_Dirs; @@ -870,6 +871,18 @@ package body Setup_RTS is -- Name of the runtime project file after it has been loaded -- (i.e. resolved file name). begin + -- CCG is a very special target, for which it is not possible to create + -- libraries through project files: CCG users cannot run "gnatcov + -- setup": there is no setup configuration to load in this case, so + -- return a dummy one. + + if To_Lower (Target) = "c" + or else (Project.Is_Project_Loaded + and then To_Lower (Project.Target) = "c") + then + return Default_Setup_Config; + end if; + -- Load the runtime project file, only to locate the prefix where it has -- been installed: do not print any error message, and if the project -- fails to load, just return the default setup config. From 89d77e0425758097e2021c387d0d8727b1734236 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 22 Jan 2024 12:52:40 +0000 Subject: [PATCH 0646/1483] instrument-ada_preprocessing.adb: remove useless WITH clause --- tools/gnatcov/instrument-ada_preprocessing.adb | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/gnatcov/instrument-ada_preprocessing.adb b/tools/gnatcov/instrument-ada_preprocessing.adb index d2e31aca5..9e3b418e7 100644 --- a/tools/gnatcov/instrument-ada_preprocessing.adb +++ b/tools/gnatcov/instrument-ada_preprocessing.adb @@ -17,7 +17,6 @@ ------------------------------------------------------------------------------ with Ada.Exceptions; use Ada.Exceptions; -with Ada.Text_IO; use Ada.Text_IO; with GNATCOLL.JSON; use GNATCOLL.JSON; From 144bfe445030480f70573e3b0383847509cac36e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 16 Jan 2024 16:32:00 +0000 Subject: [PATCH 0647/1483] GNATcov_RTS: remove uses of Ada.Command_Line.Command_Name Passing the actual command name brings little value: the program name recorded in the source trace is not used in practice, and passing the name of the project file instead looks good enough. This change goes in the way of avoiding dependencies on the secondary stack in instrumented projects, which may have the No_Secondary_Stack restriction. --- tools/gnatcov/instrument-ada_unit.adb | 10 +++++++--- tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb | 4 ++-- tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads | 6 ++---- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 9ec2f4400..b3af7a2cc 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8777,6 +8777,9 @@ package body Instrument.Ada_Unit is Indent1 : constant String := " "; Indent2 : constant String := Indent1 & " "; + Project_Name_Str : constant String := + """" & (+Prj.Prj_Name) & """"; + Env_Var : constant String := (if Dump_Config.Filename_Env_Var = "" then U & ".Default_Trace_Filename_Env_Var" @@ -8797,7 +8800,8 @@ package body Instrument.Ada_Unit is File.Put_Line (Indent2 & "(Prefix => " & Prefix & ","); File.Put_Line (Indent2 & " Env_Var => " & Env_Var & ","); File.Put_Line (Indent2 & " Tag => " & Tag & ","); - File.Put (Indent2 & " Simple => " & Simple & ") "); + File.Put (Indent2 & " Simple => " & Simple & "),"); + File.Put_Line (Indent1 & "Program_Name => " & Project_Name_Str); end; when Base64_Standard_Output => @@ -8809,8 +8813,8 @@ package body Instrument.Ada_Unit is File.Put_Line (" Program_Name => """ & (if Dump_Trigger = Manual - then "manual_dump""," - else To_Ada (Main.Unit) & """,")); + then +Prj.Prj_Name + else To_Ada (Main.Unit) & """,")); File.Put (" Exec_Date => 0"); end case; File.Put_Line (");"); diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb index 2e9dc1d5b..576a7c1a1 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb @@ -95,7 +95,7 @@ package body GNATcov_RTS.Traces.Output.Files is procedure Write_Trace_File (Buffers_Groups : Coverage_Buffers_Group_Array; Filename : String := Default_Trace_Filename; - Program_Name : String := Ada.Command_Line.Command_Name; + Program_Name : String := "unknown"; Exec_Date : Time := Clock; User_Data : String := "") is @@ -121,7 +121,7 @@ package body GNATcov_RTS.Traces.Output.Files is procedure Write_Trace_File_Wrapper (Buffers_Groups : Coverage_Buffers_Group_Array; Filename : String := Default_Trace_Filename; - Program_Name : String := Ada.Command_Line.Command_Name; + Program_Name : String := "unknown"; Exec_Date : Time := Clock; User_Data : String := "") is diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads index ecf399931..f39220211 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads @@ -24,8 +24,6 @@ -- This unit needs to be compilable with Ada 95 compilers -with Ada.Command_Line; - with Interfaces; use Interfaces; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; @@ -58,7 +56,7 @@ package GNATcov_RTS.Traces.Output.Files is procedure Write_Trace_File (Buffers_Groups : Coverage_Buffers_Group_Array; Filename : String := Default_Trace_Filename; - Program_Name : String := Ada.Command_Line.Command_Name; + Program_Name : String := "unknown"; Exec_Date : Time := Clock; User_Data : String := ""); -- Write a trace file in Filename to contain the data in Buffers_Groups. @@ -67,7 +65,7 @@ package GNATcov_RTS.Traces.Output.Files is procedure Write_Trace_File_Wrapper (Buffers_Groups : Coverage_Buffers_Group_Array; Filename : String := Default_Trace_Filename; - Program_Name : String := Ada.Command_Line.Command_Name; + Program_Name : String := "unknown"; Exec_Date : Time := Clock; User_Data : String := ""); -- Wrapper around Write_Trace_File that writes an error message to the From b28b814b2fc30c50b5e43b44a4704b7c8465477c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 17 Jan 2024 09:27:59 +0000 Subject: [PATCH 0648/1483] GNATcov_RTS: make Default_Trace_Filneame return a chars_ptr The new return type is less convenient to use, since the caller has to free the result of this function when done with it, but this avoids using the secondary stack (implied by returning a String value), which is necessary for the instrumented projects under the No_Secondary_Stack restriction. --- .../instr-cov/manual-dump/covdump__cov.adb | 7 +- tools/gnatcov/instrument-ada_unit.adb | 120 +++++++++++------- .../rts/gnatcov_rts-traces-output-files.adb | 27 ++-- .../rts/gnatcov_rts-traces-output-files.ads | 9 +- 4 files changed, 96 insertions(+), 67 deletions(-) diff --git a/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb b/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb index f53e6de38..3754a3e67 100644 --- a/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb +++ b/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb @@ -1,11 +1,16 @@ with Ada.Command_Line; +with Interfaces.C.Strings; use Interfaces.C.Strings; + with GCVRT.P; with GNATcov_RTS.Traces.Output.Files; procedure Covdump is + Filename : chars_ptr := + New_String (Ada.Command_Line.Command_Name & ".srctrace"); begin GNATcov_RTS.Traces.Output.Files.Write_Trace_File (Buffers_Groups => GCVRT.P.List, - Filename => Ada.Command_Line.Command_Name & ".srctrace"); + Filename => Filename); + Free (Filename); end Covdump; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index b3af7a2cc..9071cc962 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8680,6 +8680,16 @@ package body Instrument.Ada_Unit is declare Helper_Unit_Name : constant String := To_Ada (Helper_Unit); Dump_Procedure : constant String := To_String (Dump_Procedure_Name); + Output_Unit_Str : constant String := To_Ada (Output_Unit); + + Project_Name_Str : constant String := """" & (+Prj.Prj_Name) & """"; + + -- Indentation levels relative to the body of library-level + -- subprograms. + + Indent1 : constant String := " "; + Indent2 : constant String := Indent1 & " "; + Indent3 : constant String := Indent2 & " "; begin -- Emit the package spec. This includes one Dump_Buffers procedure, -- which dumps all coverage buffers in Main's closure to the source @@ -8753,6 +8763,13 @@ package body Instrument.Ada_Unit is null; end case; + case Dump_Config.Channel is + when Binary_File => + File.Put_Line ("with Interfaces.C.Strings;"); + when others => + null; + end case; + File.Put_Line ("with " & To_Ada (Buffers_List_Unit (+Prj.Prj_Name)) & ";"); @@ -8763,62 +8780,75 @@ package body Instrument.Ada_Unit is File.Put_Line (" procedure " & Dump_Procedure & " is"); - File.Put_Line (" begin"); + case Dump_Config.Channel is + when Binary_File => + declare + Env_Var : constant String := + (if Dump_Config.Filename_Env_Var = "" + then Output_Unit_Str & ".Default_Trace_Filename_Env_Var" + else """" & (+Dump_Config.Filename_Env_Var) + & """"); + Prefix : constant String := + """" & (if Dump_Config.Trigger = Manual + then +Prj.Prj_Name + else +Dump_Config.Filename_Prefix) & """"; + Tag : constant String := + """" & (+Instrumenter.Tag) & """"; + Simple : constant String := + (if Dump_Config.Filename_Simple + then "True" + else "False"); + begin + File.Put_Line + (Indent1 & "Filename : Interfaces.C.Strings.chars_ptr :="); + File.Put_Line + (Indent2 & Output_Unit_Str & ".Default_Trace_Filename"); + File.Put_Line (Indent3 & "(Prefix => " & Prefix & ","); + File.Put_Line (Indent3 & " Env_Var => " & Env_Var & ","); + File.Put_Line (Indent3 & " Tag => " & Tag & ","); + File.Put_Line (Indent3 & " Simple => " & Simple & ");"); + end; + when others => + null; + end case; - File.Put_Line (" " & To_Ada (Output_Proc)); - File.Put (" ("); + File.Put_Line (" begin"); + File.Put_Line (Indent1 & To_Ada (Output_Proc)); File.Put_Line - (To_Ada (Buffers_List_Unit (+Prj.Prj_Name)) & ".List,"); + (Indent2 + & "(Buffers_Groups => " + & To_Ada (Buffers_List_Unit (+Prj.Prj_Name)) + & ".List,"); case Dump_Config.Channel is - when Binary_File => - declare - U : constant String := To_Ada (Output_Unit); - Indent1 : constant String := " "; - Indent2 : constant String := Indent1 & " "; - - Project_Name_Str : constant String := - """" & (+Prj.Prj_Name) & """"; - - Env_Var : constant String := - (if Dump_Config.Filename_Env_Var = "" - then U & ".Default_Trace_Filename_Env_Var" - else """" & (+Dump_Config.Filename_Env_Var) - & """"); - Prefix : constant String := - """" & (if Dump_Config.Trigger = Manual - then +Prj.Prj_Name - else +Dump_Config.Filename_Prefix) & """"; - Tag : constant String := """" & (+Instrumenter.Tag) & """"; - Simple : constant String := - (if Dump_Config.Filename_Simple - then "True" - else "False"); - begin + when Binary_File => File.Put_Line - (Indent1 & "Filename => " & U & ".Default_Trace_Filename"); - File.Put_Line (Indent2 & "(Prefix => " & Prefix & ","); - File.Put_Line (Indent2 & " Env_Var => " & Env_Var & ","); - File.Put_Line (Indent2 & " Tag => " & Tag & ","); - File.Put (Indent2 & " Simple => " & Simple & "),"); - File.Put_Line (Indent1 & "Program_Name => " & Project_Name_Str); - end; + (Indent2 & " Filename => Filename,"); + File.Put + (Indent2 & " Program_Name => " & Project_Name_Str); - when Base64_Standard_Output => + when Base64_Standard_Output => - -- Configurations using this channel generally run on embedded - -- targets and have a small runtime, so our best guess for the - -- program name is the name of the main, and there is no way to - -- get the current execution time. + -- Configurations using this channel generally run on embedded + -- targets and have a small runtime, so our best guess for the + -- program name is the name of the main, and there is no way to + -- get the current execution time. - File.Put_Line (" Program_Name => """ - & (if Dump_Trigger = Manual - then +Prj.Prj_Name - else To_Ada (Main.Unit) & """,")); - File.Put (" Exec_Date => 0"); + File.Put_Line + (Indent2 & " Program_Name => " & Project_Name_Str & ","); + File.Put + (Indent2 & " Exec_Date => 0"); end case; File.Put_Line (");"); + case Dump_Config.Channel is + when Binary_File => + File.Put_Line + (Indent1 & "Interfaces.C.Strings.Free (Filename);"); + when others => + null; + end case; + File.Put_Line (" end " & Dump_Procedure & ";"); File.New_Line; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb index 576a7c1a1..69e94f314 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb @@ -26,8 +26,7 @@ with Ada.Text_IO; use Ada.Text_IO; -with Interfaces.C; use Interfaces.C; -with Interfaces.C.Strings; use Interfaces.C.Strings; +with Interfaces.C; use Interfaces.C; with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; @@ -59,22 +58,20 @@ package body GNATcov_RTS.Traces.Output.Files is (Env_Var : String := Default_Trace_Filename_Env_Var; Prefix : String := "gnatcov"; Tag : String := ""; - Simple : Boolean := False) return String + Simple : Boolean := False) return chars_ptr is Env_Var_C : chars_ptr := New_String (Env_Var); Prefix_C : chars_ptr := New_String (Prefix); Tag_C : chars_ptr := New_String (Tag); Simple_C : constant unsigned := Boolean'Pos (Simple); - Trace_Filename_C : chars_ptr := + Result : constant chars_ptr := Default_Trace_Filename_C (Env_Var_C, Prefix_C, Tag_C, Simple_C); - Trace_Filename : constant String := Value (Trace_Filename_C); begin Free (Env_Var_C); Free (Prefix_C); Free (Tag_C); - Free (Trace_Filename_C); - return Trace_Filename; + return Result; end Default_Trace_Filename; ----------- @@ -94,24 +91,20 @@ package body GNATcov_RTS.Traces.Output.Files is procedure Write_Trace_File (Buffers_Groups : Coverage_Buffers_Group_Array; - Filename : String := Default_Trace_Filename; + Filename : chars_ptr := Default_Trace_Filename; Program_Name : String := "unknown"; Exec_Date : Time := Clock; - User_Data : String := "") - is - Filename_C : chars_ptr := New_String (Filename); + User_Data : String := "") is begin if Write_Trace_File_C ((Buffers_Groups'Length, Buffers_Groups'Address), - Filename_C, + Filename, (Program_Name'Address, Program_Name'Length), Interfaces.Unsigned_64 (Exec_Date), (User_Data'Address, User_Data'Length)) = 1 then - Free (Filename_C); raise IO_Error; end if; - Free (Filename_C); end Write_Trace_File; ------------------------------ @@ -120,7 +113,7 @@ package body GNATcov_RTS.Traces.Output.Files is procedure Write_Trace_File_Wrapper (Buffers_Groups : Coverage_Buffers_Group_Array; - Filename : String := Default_Trace_Filename; + Filename : chars_ptr := Default_Trace_Filename; Program_Name : String := "unknown"; Exec_Date : Time := Clock; User_Data : String := "") @@ -146,8 +139,8 @@ package body GNATcov_RTS.Traces.Output.Files is begin Ada.Text_IO.Put_Line (Standard_Error, - "Error occurred while creating the trace file " & Filename - & ": " & Error_Msg); + "Error occurred while creating the trace file " + & Value (Filename) & ": " & Error_Msg); end; end Write_Trace_File_Wrapper; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads index f39220211..a42e00386 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads @@ -24,7 +24,8 @@ -- This unit needs to be compilable with Ada 95 compilers -with Interfaces; use Interfaces; +with Interfaces; use Interfaces; +with Interfaces.C.Strings; use Interfaces.C.Strings; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; @@ -45,7 +46,7 @@ package GNATcov_RTS.Traces.Output.Files is (Env_Var : String := Default_Trace_Filename_Env_Var; Prefix : String := "gnatcov"; Tag : String := ""; - Simple : Boolean := False) return String; + Simple : Boolean := False) return chars_ptr; -- Return the default name of the trace file to write. Please refer to the -- gnatcov_rts_default_trace_filename function defined in -- gnatcov_rts_c-traces-output-files.h for more information. @@ -55,7 +56,7 @@ package GNATcov_RTS.Traces.Output.Files is procedure Write_Trace_File (Buffers_Groups : Coverage_Buffers_Group_Array; - Filename : String := Default_Trace_Filename; + Filename : chars_ptr := Default_Trace_Filename; Program_Name : String := "unknown"; Exec_Date : Time := Clock; User_Data : String := ""); @@ -64,7 +65,7 @@ package GNATcov_RTS.Traces.Output.Files is procedure Write_Trace_File_Wrapper (Buffers_Groups : Coverage_Buffers_Group_Array; - Filename : String := Default_Trace_Filename; + Filename : chars_ptr := Default_Trace_Filename; Program_Name : String := "unknown"; Exec_Date : Time := Clock; User_Data : String := ""); From bd51eca472c026aad477a027aab2b7ab9ae8a104 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 17 Jan 2024 09:30:07 +0000 Subject: [PATCH 0649/1483] instrument-ada_unit.adb: fix indentation of helper unit body --- tools/gnatcov/instrument-ada_unit.adb | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 9071cc962..19e5ec32d 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8718,7 +8718,7 @@ package body Instrument.Ada_Unit is case Dump_Trigger is when At_Exit | Ravenscar_Task_Termination => File.Put_Line - ("function " + (" function " & To_String (Register_Dump_Function_Name) & " return " & To_Ada (Witness_Dummy_Type_Name) & ";"); File.New_Line; @@ -8860,24 +8860,25 @@ package body Instrument.Ada_Unit is -- Emit a function to schedule a trace dump with atexit File.Put_Line - ("function " + (" function " & To_String (Register_Dump_Function_Name) & " return " & To_Ada (Witness_Dummy_Type_Name) & " is"); - File.Put_Line (" type Callback is access procedure;"); - File.Put_Line (" pragma Convention (C, Callback);"); + File.Put_Line (Indent1 & "type Callback is access procedure;"); + File.Put_Line (Indent1 & "pragma Convention (C, Callback);"); File.New_Line; - File.Put_Line (" function atexit (Func : Callback)" + File.Put_Line (Indent1 & "function atexit (Func : Callback)" & " return Interfaces.C.int;"); - File.Put_Line (" pragma Import (C, atexit);"); - File.Put_Line (" Dummy : constant Interfaces.C.int :="); + File.Put_Line (Indent1 & "pragma Import (C, atexit);"); + File.Put_Line + (Indent1 & "Dummy : constant Interfaces.C.int :="); File.Put_Line - (" atexit (" & Dump_Procedure & "'Access);"); + (Indent2 & "atexit (" & Dump_Procedure & "'Access);"); - File.Put_Line ("begin"); - File.Put_Line (" return (Data => False);"); + File.Put_Line (" begin"); + File.Put_Line (Indent1 & "return (Data => False);"); File.Put_Line - ("end " & To_String (Register_Dump_Function_Name) & ";"); + (" end " & To_String (Register_Dump_Function_Name) & ";"); File.New_Line; when Ravenscar_Task_Termination => From 3967790525aadf0948727f2440d015f74f2493bb Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 18 Jan 2024 13:26:36 +0000 Subject: [PATCH 0650/1483] GNATcov_RTS: do not use Interfaces.C.Strings.Value This is a function that returns a string, and thus its usage necessarily implies a dependency on the secondary stack. Since instrumented projects may be subject to the No_Secondary_Stack restriction, this means that we cannot use thus fonction in the coverage runtime. --- .../rts/gnatcov_rts-traces-output-files.adb | 32 ++++++++++++++++--- 1 file changed, 27 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb index 69e94f314..c09d472d8 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb @@ -25,6 +25,7 @@ -- This unit needs to be compilable with Ada 95 compilers with Ada.Text_IO; use Ada.Text_IO; +with Ada.Unchecked_Conversion; with Interfaces.C; use Interfaces.C; @@ -134,13 +135,34 @@ package body GNATcov_RTS.Traces.Output.Files is exception when IO_Error => declare - C_Error_Msg : constant chars_ptr := C_Strerror (C_Errno); - Error_Msg : constant String := Value (C_Error_Msg); + function "+" is new Ada.Unchecked_Conversion + (chars_ptr, System.Address); + + Error_Msg : constant chars_ptr := C_Strerror (C_Errno); + + -- Since we cannot use the secondary stack, it is not possible to + -- call Interfaces.C.Strings.Value to turn chars_ptr values into + -- String ones. Workaround this with overlays. + + Error_Msg_Length : constant Natural := + Natural (Strlen (Error_Msg)); + Filename_Length : constant Natural := Natural (Strlen (Filename)); + + Ada_Error_Msg : String (1 .. Error_Msg_Length); + for Ada_Error_Msg'Address use +Error_Msg; + pragma Import (Ada, Ada_Error_Msg); + + Ada_Filename : String (1 .. Filename_Length); + for Ada_Filename'Address use +Filename; + pragma Import (Ada, Ada_Filename); begin - Ada.Text_IO.Put_Line + Put (Standard_Error, - "Error occurred while creating the trace file " - & Value (Filename) & ": " & Error_Msg); + "Error occurred while creating the trace file "); + Put (Standard_Error, Ada_Filename); + Put (Standard_Error, ": "); + Put (Standard_Error, Ada_Error_Msg); + New_Line (Standard_Error); end; end Write_Trace_File_Wrapper; From 85f4dbb46766d8195c253a58e2e31cbfcd9bc3a5 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 18 Jan 2024 13:29:25 +0000 Subject: [PATCH 0651/1483] instr-cov/208-no-secsta: new testcase --- .../tests/instr-cov/208-no-secsta/gnat.adc | 1 + .../tests/instr-cov/208-no-secsta/main.adb | 19 +++++++++ .../tests/instr-cov/208-no-secsta/test.py | 39 +++++++++++++++++++ 3 files changed, 59 insertions(+) create mode 100644 testsuite/tests/instr-cov/208-no-secsta/gnat.adc create mode 100644 testsuite/tests/instr-cov/208-no-secsta/main.adb create mode 100644 testsuite/tests/instr-cov/208-no-secsta/test.py diff --git a/testsuite/tests/instr-cov/208-no-secsta/gnat.adc b/testsuite/tests/instr-cov/208-no-secsta/gnat.adc new file mode 100644 index 000000000..e479c000b --- /dev/null +++ b/testsuite/tests/instr-cov/208-no-secsta/gnat.adc @@ -0,0 +1 @@ +pragma Restrictions (No_Secondary_Stack); diff --git a/testsuite/tests/instr-cov/208-no-secsta/main.adb b/testsuite/tests/instr-cov/208-no-secsta/main.adb new file mode 100644 index 000000000..1b9388235 --- /dev/null +++ b/testsuite/tests/instr-cov/208-no-secsta/main.adb @@ -0,0 +1,19 @@ +procedure Main is + + type Int_Range is record + Low_Bound, High_Bound : Integer; + end record; + + function In_Range (Value : Integer; Bounds : Int_Range) return Boolean is + begin + return Value >= Bounds.Low_Bound and then Value <= Bounds.High_Bound; + end In_Range; + + Two_Digits : constant Int_Range := (10, 99); +begin + if In_Range (9, Two_Digits) then + raise Program_Error; + elsif not In_Range (10, Two_Digits) then + raise Program_Error; + end if; +end Main; diff --git a/testsuite/tests/instr-cov/208-no-secsta/test.py b/testsuite/tests/instr-cov/208-no-secsta/test.py new file mode 100644 index 000000000..bb5896717 --- /dev/null +++ b/testsuite/tests/instr-cov/208-no-secsta/test.py @@ -0,0 +1,39 @@ +""" +Check that projects with the No_Secondary_Stack restriction compile fine after +instrumentation. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +p = gprfor( + srcdirs=[".."], + mains=["main.adb"], + compiler_extra='for Local_Configuration_Pragmas use "../gnat.adc";', +) +build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": { + "+": {12}, + "!": {9, 14, 16}, + "-": {15, 17}, + }, + }, + cwd="xcov", +) + +thistest.result() From 8a123030a3102588b9bb29ee63ed7a4dc6f8bd00 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 25 Jan 2024 14:18:03 +0000 Subject: [PATCH 0652/1483] instr-cov/208-no-secsta: rework to harmonize src/bin traces At higher optimization levels, the compiler is able to eliminate dead code in main.adb, and this affects the coverage report in binary traces. Move some code to a separate unit to avoid inlining and thus disable the problematic dead code elimination. This fixes discrepancies in coverage reports with bin/src traces. --- .../tests/instr-cov/208-no-secsta/main.adb | 17 +++++------------ testsuite/tests/instr-cov/208-no-secsta/pkg.adb | 12 ++++++++++++ testsuite/tests/instr-cov/208-no-secsta/pkg.ads | 8 ++++++++ testsuite/tests/instr-cov/208-no-secsta/test.py | 8 +++++--- 4 files changed, 30 insertions(+), 15 deletions(-) create mode 100644 testsuite/tests/instr-cov/208-no-secsta/pkg.adb create mode 100644 testsuite/tests/instr-cov/208-no-secsta/pkg.ads diff --git a/testsuite/tests/instr-cov/208-no-secsta/main.adb b/testsuite/tests/instr-cov/208-no-secsta/main.adb index 1b9388235..81dfb35d1 100644 --- a/testsuite/tests/instr-cov/208-no-secsta/main.adb +++ b/testsuite/tests/instr-cov/208-no-secsta/main.adb @@ -1,19 +1,12 @@ -procedure Main is - - type Int_Range is record - Low_Bound, High_Bound : Integer; - end record; - - function In_Range (Value : Integer; Bounds : Int_Range) return Boolean is - begin - return Value >= Bounds.Low_Bound and then Value <= Bounds.High_Bound; - end In_Range; +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; +procedure Main is Two_Digits : constant Int_Range := (10, 99); begin if In_Range (9, Two_Digits) then - raise Program_Error; + Put_Line ("ERROR!"); elsif not In_Range (10, Two_Digits) then - raise Program_Error; + Put_Line ("ERROR!"); end if; end Main; diff --git a/testsuite/tests/instr-cov/208-no-secsta/pkg.adb b/testsuite/tests/instr-cov/208-no-secsta/pkg.adb new file mode 100644 index 000000000..5582cd2cd --- /dev/null +++ b/testsuite/tests/instr-cov/208-no-secsta/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + -------------- + -- In_Range -- + -------------- + + function In_Range (Value : Integer; Bounds : Int_Range) return Boolean is + begin + return Value >= Bounds.Low_Bound and then Value <= Bounds.High_Bound; + end In_Range; + +end Pkg; diff --git a/testsuite/tests/instr-cov/208-no-secsta/pkg.ads b/testsuite/tests/instr-cov/208-no-secsta/pkg.ads new file mode 100644 index 000000000..7c4b0232e --- /dev/null +++ b/testsuite/tests/instr-cov/208-no-secsta/pkg.ads @@ -0,0 +1,8 @@ +package Pkg is + + type Int_Range is record + Low_Bound, High_Bound : Integer; + end record; + + function In_Range (Value : Integer; Bounds : Int_Range) return Boolean; +end Pkg; diff --git a/testsuite/tests/instr-cov/208-no-secsta/test.py b/testsuite/tests/instr-cov/208-no-secsta/test.py index bb5896717..8c09a092f 100644 --- a/testsuite/tests/instr-cov/208-no-secsta/test.py +++ b/testsuite/tests/instr-cov/208-no-secsta/test.py @@ -28,10 +28,12 @@ "*.xcov", { "main.adb.xcov": { - "+": {12}, - "!": {9, 14, 16}, - "-": {15, 17}, + "+": {5}, + "!": {7, 9}, + "-": {8, 10}, }, + "pkg.adb.xcov": {"!": {9}}, + "pkg.ads.xcov": {}, }, cwd="xcov", ) From d719c3c4c09b8cdf60e235296f4288a2007cd857 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 17 Jan 2024 15:46:45 +0100 Subject: [PATCH 0653/1483] Testsuite: Add an auto_config_args to the gprbuild / xcov API Add a flag to various testsuite APIs to prevent automatically passing the --config argument to gprbuild / gnatcov invocations. --- testsuite/SCOV/minicheck.py | 17 ++++++++---- testsuite/SUITE/context.py | 28 ++------------------ testsuite/SUITE/tutils.py | 53 ++++++++++++++++++++++++++++++------- 3 files changed, 57 insertions(+), 41 deletions(-) diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 04a55bed2..a92b33ae1 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -37,7 +37,8 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, quiet=True, runtime_project=None, gprsw_for_coverage=None, scos_for_run=True, register_failure=True, program_env=None, tolerate_instrument_messages=None, exec_args=None, - auto_languages=True, manual_prj_name=None): + auto_languages=True, manual_prj_name=None, + auto_config_args=True): """ Prepare a project to run a coverage analysis on it. @@ -113,6 +114,8 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, quiet=True, traces files (one per project) can be emitted if there are dump buffers procedure calls in at least two distinct projects. This is the name of the project which trace we want to consider. + :param bool auto_config_args: If False, do not pass the --config argument + to gprbuild and gnatcov invocations. :rtype: list[str] :return: Incomplete list of arguments to pass to `xcov` in order to run @@ -138,7 +141,8 @@ def gprbuild_wrapper(root_project): extracargs=extra_gprbuild_cargs, largs=extra_gprbuild_largs, trace_mode=trace_mode, - runtime_project=runtime_project) + runtime_project=runtime_project, + auto_config_args=auto_config_args) if check_gprbuild_output: gprbuild_out = contents_of('gprbuild.out') @@ -229,6 +233,7 @@ def gprbuild_wrapper(root_project): register_failure=register_failure, tolerate_messages=tolerate_instrument_messages, auto_languages=auto_languages, + auto_config_args=auto_config_args, ) gprbuild_wrapper(gprsw.root_project) @@ -361,17 +366,19 @@ def gprbuild_wrapper(root_project): def build_run_and_coverage(out='coverage.log', err=None, register_failure=True, - **kwargs): + auto_config_args=True, **kwargs): """ Helper to call build_and_run and then invoke `xcov`. This invokes `xcov` with the command-line that build_and_run returns to perform the "gnatcov coverage" step. - `out`, `err` and `register_failure` are forwarded to `xcov`, other + `out` and `err` are forwarded to `xcov`, `register_failure` and + `auto_config_args` are reported to `xcov` and `build_and_run`, other arguments are forwarded to `build_and_run`. """ - xcov_args = build_and_run(register_failure=register_failure, **kwargs) + xcov_args = build_and_run(register_failure=register_failure, + auto_config_args=auto_config_args, **kwargs) xcov(xcov_args, out=out, err=err, register_failure=register_failure) diff --git a/testsuite/SUITE/context.py b/testsuite/SUITE/context.py index 99b80e976..1315b62ab 100644 --- a/testsuite/SUITE/context.py +++ b/testsuite/SUITE/context.py @@ -169,29 +169,6 @@ def __init__(self): self.report = _ReportOutput(self.options.report_file) self.current_test_index = 0 - self.gprconfoptions = [ - # verbose mode for verifiability in qualif mode. - # quiet mode for performance (less io) otherwise. - '-v' if self.options.qualif_level else '-q', - - # gprconfig base, selecting runtime - '--config=%s' % os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR)] - - self.gprvaroptions = [] - - # Workaround a desynchronization between default build configuration - # for TMS570 and GNATemulator's settings: see O519-032. We may get rid - # of this kludge one day adapting GNATemulator. - if self.options.RTS and self.options.RTS.endswith('-tms570'): - self.gprvaroptions.append('-XLOADER=LORAM') - - # For trace32 runs where the test is executed on a real board, we - # choose to have both the code and data in RAM. The default is to run - # from flash which would take more time for the probe to program. It - # would also wear out the flash memory. - if self.options.gnatcov_run and 'trace32' in self.options.gnatcov_run: - self.gprvaroptions.append('-XLOADER=RAM') - # Whether this test will be using project files to locate SCOs when # running gnatcov. This is decided on a per gnatcov invocation basis. # self.options.gnatcov states whether we're queried to do this for @@ -208,10 +185,9 @@ def __init__(self): # environment variable. os.environ['GNATCOV_NO_NATIVE_WARNING'] = '1' - def cleanup(self, project): + def cleanup(self, project, options): """Cleanup possible remnants of previous builds.""" - Run([GPRCLEAN, "-P%s" % project] + - self.gprconfoptions + self.gprvaroptions) + Run([GPRCLEAN, "-P%s" % project] + options) rm('*.xcov') rm('*.bin') diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 9db67d8ff..e8680361c 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -146,11 +146,6 @@ def gprbuild_gargs_with(thisgargs, '-XSTYLE_CHECKS=', # style checks off '-p' # create missing directories (obj, typically) ] - - # Add our testsuite configuration options (selecting target model and board - # essentially). - result.extend(thistest.gprconfoptions) - result.extend(thistest.gprvaroptions) result.extend(to_list(thisgargs)) # If we work with source instrumentation, add the dependency on the @@ -246,6 +241,41 @@ def gprbuild_largs_with(thislargs): return all_largs +def gpr_common_args(project, auto_config_args=True): + """ + Return common GPR tools options for the current testsuite run. + + :param auto_config_args: if False, do not add the --config argument. + """ + gproptions = [] + + gproptions.append( + # verbose mode for verifiability in qualif mode. + # quiet mode for performance (less io) otherwise. + '-v' if thistest.options.qualif_level else '-q', + ) + if auto_config_args: + gproptions.append('--config={}' + .format(os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR))) + + # Workaround a desynchronization between default build configuration + # for TMS570 and GNATemulator's settings: see O519-032. We may get rid + # of this kludge one day adapting GNATemulator. + if thistest.options.RTS and thistest.options.RTS.endswith('-tms570'): + gproptions.append('-XLOADER=LORAM') + + # For trace32 runs where the test is executed on a real board, we + # choose to have both the code and data in RAM. The default is to run + # from flash which would take more time for the probe to program. It + # would also wear out the flash memory. + if ( + thistest.options.gnatcov_run and + 'trace32' in thistest.options.gnatcov_run + ): + gproptions.append('-XLOADER=RAM') + + return gproptions + def gprbuild(project, scovcargs=True, @@ -256,7 +286,8 @@ def gprbuild(project, trace_mode=None, runtime_project=None, out='gprbuild.out', - register_failure=True): + register_failure=True, + auto_config_args=True): """ Cleanup & build the provided PROJECT file using gprbuild, passing GARGS/CARGS/LARGS as gprbuild/cargs/largs command-line switches. Each @@ -275,6 +306,8 @@ def gprbuild(project, Stop with a FatalError if the execution status is not zero and REGISTER_FAILURE is True. Return the process descriptor otherwise. + + If AUTO_CONFIG_ARGS is False, do not pass the --config argument. """ # Fetch options, from what is requested specifically here @@ -288,9 +321,10 @@ def gprbuild(project, all_cargs = gprbuild_cargs_with(scovcargs=scovcargs, suitecargs=suitecargs, thiscargs=extracargs) + common_args = gpr_common_args(project, auto_config_args) # Now cleanup, do build and check status - thistest.cleanup(project) + thistest.cleanup(project, common_args) # lookup the hook for the executable name without extension builder = thistest.suite_gprpgm_for( @@ -303,7 +337,7 @@ def gprbuild(project, builder = BUILDER.BASE_COMMAND args = (to_list(builder) + - ['-P%s' % project] + all_gargs + all_cargs + all_largs) + ['-P%s' % project] + common_args + all_gargs + all_cargs + all_largs) # If there is an altrun hook for gprbuild, it may be a script. # Instruct the Run primitive to parse the shebang to invoke the correct # interpreter in that case. @@ -330,8 +364,7 @@ def gprinstall(project, gargs=None): args = ['gprinstall', '-P', project, '-p'] # Add mandatory options, such as target and RTS info - args.extend(thistest.gprconfoptions) - args.extend(thistest.gprvaroptions) + args.extend(gpr_common_args(project)) # Add user-provided arguments args.extend(to_list(gargs)) From fa6161261cef43a3e7dfc437391098084adef95d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 10 Jan 2024 12:54:18 +0100 Subject: [PATCH 0654/1483] Instrument: Support the --db switch Users can write their own knowledge base to specify custom toolchains. gprbuild supports this through the --db flag. As this can be used to configure new languages (and specify e.g. their body suffix), and new compilers, we should add support for this switch for every gnatcov command that needs to load / build projects. --- .../gnatcov-rt-custom/gnatcov_rts_custom.gpr | 7 +++ .../tests/instr-cov/config_custom_db/main.c | 5 ++ .../config_custom_db/my_config/my_db.xml | 23 ++++++++++ .../tests/instr-cov/config_custom_db/test.opt | 1 + .../tests/instr-cov/config_custom_db/test.py | 46 +++++++++++++++++++ tools/gnatcov/argparse.adb | 5 ++ tools/gnatcov/argparse.ads | 1 + tools/gnatcov/command_line.ads | 14 +++++- tools/gnatcov/gnatcov_bits_specific.adb | 1 + tools/gnatcov/project.adb | 12 +++-- tools/gnatcov/project.ads | 7 +-- tools/gnatcov/setup_rts.adb | 5 ++ tools/gnatcov/setup_rts.ads | 4 +- tools/gnatcov/setup_rts__stub.adb | 1 + tools/gnatcov/switches.adb | 7 ++- 15 files changed, 130 insertions(+), 9 deletions(-) create mode 100644 testsuite/tests/instr-cov/config_custom_db/gnatcov-rt-custom/gnatcov_rts_custom.gpr create mode 100644 testsuite/tests/instr-cov/config_custom_db/main.c create mode 100644 testsuite/tests/instr-cov/config_custom_db/my_config/my_db.xml create mode 100644 testsuite/tests/instr-cov/config_custom_db/test.opt create mode 100644 testsuite/tests/instr-cov/config_custom_db/test.py diff --git a/testsuite/tests/instr-cov/config_custom_db/gnatcov-rt-custom/gnatcov_rts_custom.gpr b/testsuite/tests/instr-cov/config_custom_db/gnatcov-rt-custom/gnatcov_rts_custom.gpr new file mode 100644 index 000000000..bcec9f048 --- /dev/null +++ b/testsuite/tests/instr-cov/config_custom_db/gnatcov-rt-custom/gnatcov_rts_custom.gpr @@ -0,0 +1,7 @@ +library project GNATcov_RTS_Custom extends "gnatcov_rts.gpr" is + for Object_Dir use "obj"; + for Library_Dir use "lib"; + for Library_Name use "gnatcov_rts_custom"; + for Library_Kind use "static"; + for Toolchain_Name ("C") use "MY_GCC"; +end GNATcov_RTS_Custom; diff --git a/testsuite/tests/instr-cov/config_custom_db/main.c b/testsuite/tests/instr-cov/config_custom_db/main.c new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/instr-cov/config_custom_db/main.c @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/config_custom_db/my_config/my_db.xml b/testsuite/tests/instr-cov/config_custom_db/my_config/my_db.xml new file mode 100644 index 000000000..d94d03d76 --- /dev/null +++ b/testsuite/tests/instr-cov/config_custom_db/my_config/my_db.xml @@ -0,0 +1,23 @@ + + + + MY_GCC + gcc + 1.0 + C + + + + + + + + package Compiler is + for Driver ("C") use "gcc"; + for Leading_Required_Switches ("C") use + ("-c", "-x", "c") & Compiler'Leading_Required_Switches ("C"); + for Include_Switches ("C") use ("-I"); + end Compiler; + + + diff --git a/testsuite/tests/instr-cov/config_custom_db/test.opt b/testsuite/tests/instr-cov/config_custom_db/test.opt new file mode 100644 index 000000000..c4b86c03f --- /dev/null +++ b/testsuite/tests/instr-cov/config_custom_db/test.opt @@ -0,0 +1 @@ +!native DEAD Checks support for a custom toolchain only defined natively diff --git a/testsuite/tests/instr-cov/config_custom_db/test.py b/testsuite/tests/instr-cov/config_custom_db/test.py new file mode 100644 index 000000000..b1d75d8df --- /dev/null +++ b/testsuite/tests/instr-cov/config_custom_db/test.py @@ -0,0 +1,46 @@ +""" +Check that gnatcov setup / instrument support custom toolchain definitions that +are passed through the --db command line option. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +prj = gprfor( + mains=["main.c"], + srcdirs=[".."], + extra='for Toolchain_Name ("C") use "MY_GCC";', +) +db_args = ["--db", "../my_config"] + +# Setup with our custom toolchain +xcov( + ["setup", "--prefix=install"] + db_args + + ["../gnatcov-rt-custom/gnatcov_rts_custom.gpr"], + register_failure=True, + auto_config_args=False, + force_project_args=True, +) +env.add_search_path("GPR_PROJECT_PATH", "install/share/gpr") +build_run_and_coverage( + gprsw=GPRswitches(prj), + covlevel="stmt", + mains=["main"], + extra_args=db_args, + extra_gprbuild_args=db_args, + extra_coverage_args=["-axcov", "--output-dir=xcov"], + extra_instr_args=["--runtime-project", "gnatcov_rts_custom"], + auto_config_args=False, +) +check_xcov_reports("*.xcov", {"main.c.xcov": {"+": {4}}}, "xcov") + +thistest.result() diff --git a/tools/gnatcov/argparse.adb b/tools/gnatcov/argparse.adb index dee0fdfea..22758e2c4 100644 --- a/tools/gnatcov/argparse.adb +++ b/tools/gnatcov/argparse.adb @@ -183,6 +183,11 @@ package body Argparse is end if; end Value_Or_Null; + function Value_Or_Null (Opt : String_Option) return String is + begin + return +Value_Or_Null (Opt); + end Value_Or_Null; + ---------------- -- Is_Present -- ---------------- diff --git a/tools/gnatcov/argparse.ads b/tools/gnatcov/argparse.ads index d98799b22..7ff3a35bc 100644 --- a/tools/gnatcov/argparse.ads +++ b/tools/gnatcov/argparse.ads @@ -298,6 +298,7 @@ package Argparse is -- empty value. This is specified thanks to the Present discriminant. function Value_Or_Null (Opt : String_Option) return Unbounded_String; + function Value_Or_Null (Opt : String_Option) return String; -- If Opt is present, return its value. Return the empty string otherwise. type Bool_Array is array (Bool_Options) of Boolean; diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index bb1f234fb..b53e05735 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -140,7 +140,8 @@ package Command_Line is Opt_Config_Pragmas_Mapping, Opt_Ada_Preprocessor_Data, Opt_Project_Name, - Opt_Source_Root); + Opt_Source_Root, + Opt_Db); -- Set of string options we support. More complete descriptions below. type String_List_Options is @@ -1130,6 +1131,17 @@ package Command_Line is & " specified prefix from the filenames in the report.", Commands => (Cmd_Coverage => True, others => False), At_Most_Once => True, + Internal => False), + + Opt_Db => Create + (Long_Name => "--db", + Pattern => "DIR", + Help => + "Parse DIR as an additional GPR knowledge base directory.", + Commands => (Cmd_Setup_Integration + | Cmd_Instrument_Source + | Cmd_Instrument_Main => False, others => True), + At_Most_Once => True, Internal => False) ); diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index c09c2eb6b..43dd59658 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1305,6 +1305,7 @@ begin Target => Target, RTS => Value (Args, Opt_Runtime), Config_File => Value (Args, Opt_Config), + Db_Dir => Value (Args, Opt_Db), Prefix => Value (Args, Opt_Prefix), RTS_Profile => RTS_Profile, Install_Name => Install_Name, diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 6c9e23f26..5a2aa5696 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -1238,9 +1238,9 @@ package body Project is ----------------------- procedure Load_Root_Project - (Prj_Name : String; - Target, Runtime, CGPR_File : GNAT.Strings.String_Access; - From_Driver : Boolean := False) + (Prj_Name : String; + Target, Runtime, CGPR_File, DB_Dir : GNAT.Strings.String_Access; + From_Driver : Boolean := False) is begin if Prj_Tree /= null then @@ -1256,6 +1256,12 @@ package body Project is Initialize (Target, Runtime, CGPR_File); pragma Assert (Env /= null); + -- Include the additional knowledge base + + if DB_Dir /= null then + Env.Add_Config_Dir (Create (+DB_Dir.all)); + end if; + if Obj_Subdir /= "" then Env.Set_Object_Subdir (+(+Obj_Subdir)); end if; diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 592f2a804..6f2bad395 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -84,9 +84,9 @@ package Project is -- the build tree. procedure Load_Root_Project - (Prj_Name : String; - Target, Runtime, CGPR_File : String_Access; - From_Driver : Boolean := False) + (Prj_Name : String; + Target, Runtime, CGPR_File, DB_Dir : GNAT.Strings.String_Access; + From_Driver : Boolean := False) with Pre => not Is_Project_Loaded and then ((Target = null and then Runtime = null) or else CGPR_File = null), @@ -95,6 +95,7 @@ package Project is -- Project_File_Extension). Target is the target prefix, or NULL in the -- native case. Runtime is the Ada runtime to use, or NULL in the default -- runtime case. CGPR_File is the path to the configuration project file, + -- if any. DB_Dir is the path to the additional knowledge base directory, -- if any. -- -- Note that Target/Runtime must not be provided if a configuration project diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index a2e0a21ba..a3ddbacd6 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -665,6 +665,7 @@ package body Setup_RTS is Target : String; RTS : String; Config_File : String; + Db_Dir : String; Prefix : String; RTS_Profile : Any_RTS_Profile; Install_Name : String; @@ -775,6 +776,10 @@ package body Setup_RTS is if Config_File /= "" then Common_Args.Append (+("--config=" & Config_File)); end if; + if Db_Dir /= "" then + Common_Args.Append (+"--db"); + Common_Args.Append (+Db_Dir); + end if; if Prefix /= "" then Install_Args.Append (+("--prefix=" & Prefix)); end if; diff --git a/tools/gnatcov/setup_rts.ads b/tools/gnatcov/setup_rts.ads index 6655a225a..2fb53dab1 100644 --- a/tools/gnatcov/setup_rts.ads +++ b/tools/gnatcov/setup_rts.ads @@ -56,6 +56,7 @@ package Setup_RTS is Target : String; RTS : String; Config_File : String; + Db_Dir : String; Prefix : String; RTS_Profile : Any_RTS_Profile; Install_Name : String; @@ -64,7 +65,8 @@ package Setup_RTS is -- project. -- -- Target/RTS/Config_File are the standard GPR loading parameters to use - -- for the build. + -- for the build. DB_Dir is the path to the additional knowledge base + -- directory, if any. -- -- Prefix is the installation prefix to pass to gprinstall (--prefix -- argument). If the empty string is passed, do not pass --prefix to diff --git a/tools/gnatcov/setup_rts__stub.adb b/tools/gnatcov/setup_rts__stub.adb index 85a5515c3..ce49b7148 100644 --- a/tools/gnatcov/setup_rts__stub.adb +++ b/tools/gnatcov/setup_rts__stub.adb @@ -80,6 +80,7 @@ package body Setup_RTS is Target : String; RTS : String; Config_File : String; + Db_Dir : String; Prefix : String; RTS_Profile : Any_RTS_Profile; Install_Name : String; diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index f0df0a7bb..510c8cb86 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -505,7 +505,12 @@ package body Switches is -- project subsystem and load the root project. Load_Root_Project - (Root_Project.all, Target_Family, Runtime, CGPR_File, From_Driver); + (Root_Project.all, + Target_Family, + Runtime, + CGPR_File, + new String'(Value_Or_Null (Args.String_Args (Opt_Db))), + From_Driver); -- Get common and command-specific switches, decode them (if any) and -- store the result in Project_Args, then merge it into Args. From 71ba01c01e2105d2be852950ce3b342070a988f8 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 26 Jan 2024 09:41:37 +0000 Subject: [PATCH 0655/1483] Project.Load_Root_Project: avoid null/empty string confusion Turn the DB_Dir format into a string, so that there is only one value that means "no db dir": the empty string. So far, Load_Root_Project considered that only a null string access value meant that, whereas the caller used an empty string instead. As a consequence, GNATCOLL.Projects.Add_Config_Dir was always called (generally with an empty string), which could cause the GPR system to fail to detect the C compiler and trigger spurious "is not a file or directory" error messages from gprconfig. --- tools/gnatcov/project.adb | 11 ++++++----- tools/gnatcov/project.ads | 7 ++++--- tools/gnatcov/switches.adb | 2 +- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 5a2aa5696..576e1144c 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -1238,9 +1238,10 @@ package body Project is ----------------------- procedure Load_Root_Project - (Prj_Name : String; - Target, Runtime, CGPR_File, DB_Dir : GNAT.Strings.String_Access; - From_Driver : Boolean := False) + (Prj_Name : String; + Target, Runtime, CGPR_File : GNAT.Strings.String_Access; + DB_Dir : String; + From_Driver : Boolean := False) is begin if Prj_Tree /= null then @@ -1258,8 +1259,8 @@ package body Project is -- Include the additional knowledge base - if DB_Dir /= null then - Env.Add_Config_Dir (Create (+DB_Dir.all)); + if DB_Dir /= "" then + Env.Add_Config_Dir (Create (+DB_Dir)); end if; if Obj_Subdir /= "" then diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 6f2bad395..b936345dc 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -84,9 +84,10 @@ package Project is -- the build tree. procedure Load_Root_Project - (Prj_Name : String; - Target, Runtime, CGPR_File, DB_Dir : GNAT.Strings.String_Access; - From_Driver : Boolean := False) + (Prj_Name : String; + Target, Runtime, CGPR_File : GNAT.Strings.String_Access; + DB_Dir : String; + From_Driver : Boolean := False) with Pre => not Is_Project_Loaded and then ((Target = null and then Runtime = null) or else CGPR_File = null), diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 510c8cb86..e058c6f1d 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -509,7 +509,7 @@ package body Switches is Target_Family, Runtime, CGPR_File, - new String'(Value_Or_Null (Args.String_Args (Opt_Db))), + Value_Or_Null (Args.String_Args (Opt_Db)), From_Driver); -- Get common and command-specific switches, decode them (if any) and From 089c6bd3db70a6d7f070baf33481e0733cc16467 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 26 Jan 2024 10:37:13 +0000 Subject: [PATCH 0656/1483] CI: temporarily rebuild the bootstrapping gnatcov Today's gnatcov wavefront is subtly broken in a way that prevents the CI from running. Temporarily build gnatcov instead of installing the wavefront to unblock the situation. This should be reverted the next business day. --- .gitlab-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a824dd9cc..51a973e31 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -28,7 +28,7 @@ build: - require_issue - *basic_setup # Build using anod - - anod install gnatcov $ACI_TRACK_QUALIFIER --latest + - anod build gnatcov $ACI_TRACK_QUALIFIER --minimal - anod build --minimal gnatcov -Qinstr $ACI_TRACK_QUALIFIER # Package all components created so far @@ -82,6 +82,7 @@ build_community: # then remove temporaries to save disk space. - tar zxf $PACKAGE_ABSOLUTE_NAME -C / - anod-copy-components $ANOD_DEFAULT_SANDBOX_DIR/exp-comps $ANOD_DEFAULT_SANDBOX_DIR + - anod install gnatcov $ACI_TRACK_QUALIFIER - anod install gnatcov -Qinstr $ACI_TRACK_QUALIFIER - rm -rf $PACKAGE_ABSOLUTE_NAME $ANOD_DEFAULT_SANDBOX_DIR/exp-comps From 22b6088e6e6c1eccec4b774648845f8c79cfd23a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 25 Jan 2024 15:39:35 +0000 Subject: [PATCH 0657/1483] Fix the main-end dump trigger when relying on controlled types With GNAT, declaring a controlled type triggers the generation of artificial routines that use the secondary stack. Add pragma No_Tagged_Streams and use the Limimted_Controlled type in helper packages that use controlled types to avoid the generation of these routines, and thus avoid violating the potential No_Secondary_Stack restriction in user code. --- tools/gnatcov/instrument-ada_unit.adb | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 19e5ec32d..4dda249df 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8711,6 +8711,15 @@ package body Instrument.Ada_Unit is end if; File.Put_Line ("package " & Helper_Unit_Name & " is"); File.New_Line; + + -- Do not generate routines to deal with streaming attributes in this + -- helper unit: we do not need them, and they can bring in the + -- secondary stack, which may in turn violate the No_Secondary_Stack + -- restriction from user projects. + + File.Put_Line (" pragma No_Tagged_Streams;"); + File.New_Line; + File.Put_Line (" procedure " & Dump_Procedure & ";"); File.Put_Line (" pragma Convention (C, " & Dump_Procedure & ");"); File.New_Line; @@ -8725,9 +8734,9 @@ package body Instrument.Ada_Unit is when Main_End => if Has_Controlled then - File.Put_Line (" type Dump_Controlled_Type is new" - & " Ada.Finalization.Controlled with"); - File.Put_Line (" null record;"); + File.Put_Line (" type Dump_Controlled_Type is new"); + File.Put_Line (" Ada.Finalization.Limited_Controlled"); + File.Put_Line (" with null record;"); File.Put_Line (" overriding procedure Finalize (Self : in" & " out Dump_Controlled_Type);"); File.New_Line; From 0202d6782667c2c4df6b53b4cfb92bb612e81500 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 25 Jan 2024 15:58:54 +0000 Subject: [PATCH 0658/1483] instrument-ada_unit.adb: rectify a comment Preelaboration matters for the coverage of library-level declarations only, not all declarations. --- tools/gnatcov/instrument-ada_unit.adb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 4dda249df..baa99dea5 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -7954,12 +7954,12 @@ package body Instrument.Ada_Unit is Root_Analysis_Unit : Analysis_Unit; Preelab : Boolean; - -- Set to True if Unit is required to be preelaborable, i.e. it is - -- either preelaborated, or the declaration of a remote types or - -- remote call interface library unit. In this case, do not generate - -- any witness calls for elaboration of declarations: they would be - -- pointless (there is no elaboration code anyway) and, in any case, - -- illegal. + -- Set to True if Unit is required to be preelaborable, i.e. it is + -- either preelaborated, or the declaration of a remote types or remote + -- call interface library unit. In this case, do not generate any + -- witness calls for elaboration of library-level declarations: they + -- would be pointless (there is no elaboration code anyway) and illegal + -- (because of the No_Elaboration_Code restriction). Has_Pragma_SCAO : Boolean; -- Whether there is a pragma Short_Circuit_And_Or that applies to this From 4ea022440e052e6ae4552aa9e6bf43f0b0dab533 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 25 Jan 2024 15:57:23 +0000 Subject: [PATCH 0659/1483] instrument-ada_unit.adb: minor refactoring --- tools/gnatcov/instrument-ada_unit.adb | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index baa99dea5..ce8499449 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -7953,7 +7953,7 @@ package body Instrument.Ada_Unit is Root_Analysis_Unit : Analysis_Unit; - Preelab : Boolean; + Preelab : Boolean := False; -- Set to True if Unit is required to be preelaborable, i.e. it is -- either preelaborated, or the declaration of a remote types or remote -- call interface library unit. In this case, do not generate any @@ -7980,14 +7980,19 @@ package body Instrument.Ada_Unit is (UIC.Root_Unit.P_Decl.P_Fully_Qualified_Name_Array); begin - Preelab := (UIC.Root_Unit.P_Is_Preelaborable - or else UIC.Root_Unit.P_Has_Restriction - (To_Unbounded_Text ("No_Elaboration_Code"))) - and then UIC.Root_Unit.F_Body.Kind = Ada_Library_Item - and then UIC.Root_Unit.F_Body.As_Library_Item.F_Item.Kind in - Ada_Package_Decl - | Ada_Package_Body - | Ada_Generic_Package_Decl; + -- Top-level (relative to the source file) declarations can be + -- instrumented even when they belong to preelaborate units: they + -- just need not to be library-level declarations. + + if UIC.Root_Unit.F_Body.Kind = Ada_Library_Item + and then UIC.Root_Unit.F_Body.As_Library_Item.F_Item.Kind in + Ada_Package_Decl | Ada_Package_Body | Ada_Generic_Package_Decl; + then + Preelab := + UIC.Root_Unit.P_Is_Preelaborable + or else UIC.Root_Unit.P_Has_Restriction + (To_Unbounded_Text ("No_Elaboration_Code")) + end if; exception when Libadalang.Common.Property_Error => Report From 41d426183d8ad2d43ca8f8952d50e6911c67c8e4 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 25 Jan 2024 20:46:48 +0000 Subject: [PATCH 0660/1483] Instrument: handle the No_Elaboration_Code_All pragma/aspect Add this pragma to all GNATcov_RTS units that can be in the closure of user code that can have this pragma/aspect. Also, for instrumented units that have this pragma/aspect: * make gnatcov emit this pragma in the pure buffer unit, so that the instrumented unit stays compilable, * make gnatcov consider that this unit is preelaborate (i.e. do not emit coverage obligations for library-level declarations) to avoid the generation of elaboration code, as this would violate No_Elaboration_Code_All. --- .../tests/instr-cov/216-no-elab-all/main.adb | 12 ++ .../tests/instr-cov/216-no-elab-all/pkg.adb | 12 ++ .../tests/instr-cov/216-no-elab-all/pkg.ads | 11 ++ .../tests/instr-cov/216-no-elab-all/test.py | 36 ++++++ tools/gnatcov/instrument-ada_unit.adb | 118 ++++++++++++++++-- tools/gnatcov/instrument-ada_unit.ads | 3 + tools/gnatcov/rts/gcvrt.ads | 3 + tools/gnatcov/rts/gnatcov_rts-buffers.ads | 1 + tools/gnatcov/rts/gnatcov_rts-strings.ads | 1 + .../gnatcov/rts/gnatcov_rts-traces-output.ads | 1 + tools/gnatcov/rts/gnatcov_rts-traces.ads | 1 + tools/gnatcov/rts/gnatcov_rts-types.ads | 1 + tools/gnatcov/rts/gnatcov_rts.ads | 1 + 13 files changed, 192 insertions(+), 9 deletions(-) create mode 100644 testsuite/tests/instr-cov/216-no-elab-all/main.adb create mode 100644 testsuite/tests/instr-cov/216-no-elab-all/pkg.adb create mode 100644 testsuite/tests/instr-cov/216-no-elab-all/pkg.ads create mode 100644 testsuite/tests/instr-cov/216-no-elab-all/test.py diff --git a/testsuite/tests/instr-cov/216-no-elab-all/main.adb b/testsuite/tests/instr-cov/216-no-elab-all/main.adb new file mode 100644 index 000000000..81dfb35d1 --- /dev/null +++ b/testsuite/tests/instr-cov/216-no-elab-all/main.adb @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Main is + Two_Digits : constant Int_Range := (10, 99); +begin + if In_Range (9, Two_Digits) then + Put_Line ("ERROR!"); + elsif not In_Range (10, Two_Digits) then + Put_Line ("ERROR!"); + end if; +end Main; diff --git a/testsuite/tests/instr-cov/216-no-elab-all/pkg.adb b/testsuite/tests/instr-cov/216-no-elab-all/pkg.adb new file mode 100644 index 000000000..5582cd2cd --- /dev/null +++ b/testsuite/tests/instr-cov/216-no-elab-all/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + -------------- + -- In_Range -- + -------------- + + function In_Range (Value : Integer; Bounds : Int_Range) return Boolean is + begin + return Value >= Bounds.Low_Bound and then Value <= Bounds.High_Bound; + end In_Range; + +end Pkg; diff --git a/testsuite/tests/instr-cov/216-no-elab-all/pkg.ads b/testsuite/tests/instr-cov/216-no-elab-all/pkg.ads new file mode 100644 index 000000000..30ec69f17 --- /dev/null +++ b/testsuite/tests/instr-cov/216-no-elab-all/pkg.ads @@ -0,0 +1,11 @@ +package Pkg is + + pragma No_Elaboration_Code_All; + + type Int_Range is record + Low_Bound, High_Bound : Integer; + end record; + + function In_Range (Value : Integer; Bounds : Int_Range) return Boolean; + +end Pkg; diff --git a/testsuite/tests/instr-cov/216-no-elab-all/test.py b/testsuite/tests/instr-cov/216-no-elab-all/test.py new file mode 100644 index 000000000..05b88b2b9 --- /dev/null +++ b/testsuite/tests/instr-cov/216-no-elab-all/test.py @@ -0,0 +1,36 @@ +""" +Check that units with the No_Elaboration_Code_All pragma still compile after +instrumentation. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": { + "+": {5}, + "!": {7, 9}, + "-": {8, 10}, + }, + "pkg.adb.xcov": {"!": {9}}, + "pkg.ads.xcov": {}, + }, + cwd="xcov", +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index ce8499449..1fb9afa56 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1096,6 +1096,11 @@ package body Instrument.Ada_Unit is function Parent_Decl (Decl : Basic_Decl'Class) return Basic_Decl; -- Return the parent declaration for Decl, or No_Basic_Decl if Decl has no -- parent, or if we cannot find it. + + function Has_No_Elaboration_Code_All + (Unit : LAL.Compilation_Unit) return Boolean; + -- Return whether the No_Elaboration_Code_All aspect/pragma applies to Unit + -------------------------------- -- Instrumentation extensions -- -------------------------------- @@ -1433,15 +1438,19 @@ package body Instrument.Ada_Unit is Prj : Prj_Desc; CU_Names : CU_Name_Vectors.Vector; Language_Version : Unbounded_Wide_Wide_String; - Degenerate_Subprogram_Generics : Generic_Subp_Vectors.Vector); + Degenerate_Subprogram_Generics : Generic_Subp_Vectors.Vector; + Has_No_Elaboration_Code_All : Boolean); -- Emit the unit to contain addresses for the coverage buffers of all of -- the compilation unit parts in CU_Names. PB_Unit holds the name of -- the pure buffer unit, which is generated in the output dir specified in -- the project description Prj. -- -- See the documentation of the eponym fields of the Ada_Unit_Inst_Context - -- record for the Language_Version and Degenerate_Subprogram_Generics - -- parameters. + -- record for the following formals: + -- + -- * Language_Version + -- * Degenerate_Subprogram_Generics + -- * Has_No_Elaboration_Code_All function Create_Manual_Helper_Unit_Name (Prj : Prj_Desc) @@ -2906,6 +2915,61 @@ package body Instrument.Ada_Unit is return No_Basic_Decl; end Parent_Decl; + --------------------------------- + -- Has_No_Elaboration_Code_All -- + --------------------------------- + + function Has_No_Elaboration_Code_All + (Unit : LAL.Compilation_Unit) return Boolean + is + Id : constant Unbounded_Text_Type := + To_Unbounded_Text ("No_Elaboration_Code_All"); + CU : LAL.Compilation_Unit := Unit; + begin + while not CU.Is_Null loop + case CU.F_Body.Kind is + when Ada_Library_Item => + + -- The pragma/aspect can appear in the body or in the spec: + -- check both. + + declare + Parts : constant array (1 .. 2) of LAL.Compilation_Unit := + (CU, CU.P_Other_Part); + begin + for P of Parts loop + if not P.Is_Null + and then P.F_Body.As_Library_Item.F_Item + .P_Has_Aspect (Id) + then + return True; + end if; + end loop; + exit; + end; + + when Ada_Subunit => + + -- For subunits, the pragma/aspect applies only when present in + -- the "root" body or its spec. + + declare + Next : Ada_Node := CU.F_Body.As_Subunit.P_Body_Root.Parent; + begin + while Next.Kind /= Ada_Compilation_Unit loop + Next := Next.Parent; + end loop; + CU := Next.As_Compilation_Unit; + end; + + when others => + exit; + end case; + end loop; + + return False; + end Has_No_Elaboration_Code_All; + ----------------------------------------- -- Traverse_Declarations_Or_Statements -- ----------------------------------------- @@ -7961,6 +8025,9 @@ package body Instrument.Ada_Unit is -- would be pointless (there is no elaboration code anyway) and illegal -- (because of the No_Elaboration_Code restriction). + Has_No_Elab_Code_All : Boolean; + -- Whether the No_Elaboration_Code_All applies to this source file + Has_Pragma_SCAO : Boolean; -- Whether there is a pragma Short_Circuit_And_Or that applies to this -- unit. @@ -7969,12 +8036,28 @@ package body Instrument.Ada_Unit is Root_Analysis_Unit := Rewriter.Rewritten_Unit; - -- Determine whether Unit is required to be preelaborable, and whether - -- we can insert witness calls (which are not preelaborable). - UIC.Root_Unit := Root_Analysis_Unit.Root.As_Compilation_Unit; UIC.Current_Scope_Entity := UIC.Scope_Entities.Root; + -- Determine if this source file/unit has the No_Elaboration_Code_All + -- pragma/aspect. + + begin + Has_No_Elab_Code_All := Has_No_Elaboration_Code_All (UIC.Root_Unit); + exception + when Libadalang.Common.Property_Error => + Report + (Msg => "failed to determine No_Elaboration_Code_All constraint" + & " for " & Filename, + Kind => Warning); + Has_No_Elab_Code_All := False; + end; + UIC.Has_No_Elaboration_Code_All := + UIC.Has_No_Elaboration_Code_All or else Has_No_Elab_Code_All; + + -- Determine whether Unit is required to be preelaborable, and whether + -- we can insert witness calls (which are not preelaborable). + CU_Name.Part := +UIC.Root_Unit.P_Unit_Kind; CU_Name.Unit := To_Qualified_Name (UIC.Root_Unit.P_Decl.P_Fully_Qualified_Name_Array); @@ -7986,12 +8069,13 @@ package body Instrument.Ada_Unit is if UIC.Root_Unit.F_Body.Kind = Ada_Library_Item and then UIC.Root_Unit.F_Body.As_Library_Item.F_Item.Kind in - Ada_Package_Decl | Ada_Package_Body | Ada_Generic_Package_Decl; + Ada_Package_Decl | Ada_Package_Body | Ada_Generic_Package_Decl then Preelab := UIC.Root_Unit.P_Is_Preelaborable or else UIC.Root_Unit.P_Has_Restriction (To_Unbounded_Text ("No_Elaboration_Code")) + or else Has_No_Elab_Code_All; end if; exception when Libadalang.Common.Property_Error => @@ -8473,7 +8557,8 @@ package body Instrument.Ada_Unit is Prj : Prj_Desc; CU_Names : CU_Name_Vectors.Vector; Language_Version : Unbounded_Wide_Wide_String; - Degenerate_Subprogram_Generics : Generic_Subp_Vectors.Vector) + Degenerate_Subprogram_Generics : Generic_Subp_Vectors.Vector; + Has_No_Elaboration_Code_All : Boolean) is Last_Buffer_Index : constant Natural := Natural (CU_Names.Length); Pkg_Name : constant String := To_Ada (PB_Unit.Unit); @@ -8518,7 +8603,16 @@ package body Instrument.Ada_Unit is File.Put_Line ("package " & Pkg_Name & " is"); File.New_Line; File.Put_Line (" pragma Pure;"); + + -- If the instrumented unit has the No_Elaboration_Code_All pragma, all + -- its dependencies must have this pragma too, so this pure buffer unit + -- has to have it. + + if Has_No_Elaboration_Code_All then + File.Put_Line (" pragma No_Elaboration_Code_All;"); + end if; File.New_Line; + for I in 1 .. Last_Buffer_Index loop declare Suffix : constant String := "_" & Img (I); @@ -9296,6 +9390,11 @@ package body Instrument.Ada_Unit is CU_Name_For_Unit (Pure_Buffer_Unit (To_Qualified_Name (Unit_Name)), GPR.Unit_Spec); + -- We consider that theer is no No_Elaboration_Code_All pragma/aspect + -- until we see one. + + UIC.Has_No_Elaboration_Code_All := False; + -- Try to find the spec and / or the body for this compilation unit -- using the unit provider. Then retrieve the separate unit from the -- spec / body / both. @@ -9324,7 +9423,8 @@ package body Instrument.Ada_Unit is Prj => Prj, CU_Names => CU_Names, Language_Version => UIC.Language_Version_Pragma, - Degenerate_Subprogram_Generics => UIC.Degenerate_Subprogram_Generics); + Degenerate_Subprogram_Generics => UIC.Degenerate_Subprogram_Generics, + Has_No_Elaboration_Code_All => UIC.Has_No_Elaboration_Code_All); end Instrument_Unit; -------------------- diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 60eefd3b4..36c0ff6be 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -330,6 +330,9 @@ private -- Name of the compilation unit that holds addresses for the coverage -- buffers of the unit being instrumented. + Has_No_Elaboration_Code_All : Boolean; + -- Whether the No_Elaboration_Code_All applies to this unit + Withed_Units : FQN_Sets.Set; -- Set of units for which we have WITH clauses diff --git a/tools/gnatcov/rts/gcvrt.ads b/tools/gnatcov/rts/gcvrt.ads index 0d72420db..ebd2c6447 100644 --- a/tools/gnatcov/rts/gcvrt.ads +++ b/tools/gnatcov/rts/gcvrt.ads @@ -21,5 +21,8 @@ -- This unit needs to be compilable with Ada 95 compilers package GCVRT is + pragma Pure; + pragma No_Elaboration_Code_All; + end GCVRT; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index c44d2f6b2..ef846c3ac 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -36,6 +36,7 @@ with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; package GNATcov_RTS.Buffers is pragma Pure; + pragma No_Elaboration_Code_All; -- Any_Bit_Id is declared volatile here, as in order to instrument declare -- expressions we need to declare a constant MC_DC_State (a subtype of diff --git a/tools/gnatcov/rts/gnatcov_rts-strings.ads b/tools/gnatcov/rts/gnatcov_rts-strings.ads index ca649c584..1f0eeda9c 100644 --- a/tools/gnatcov/rts/gnatcov_rts-strings.ads +++ b/tools/gnatcov/rts/gnatcov_rts-strings.ads @@ -31,6 +31,7 @@ with GNATcov_RTS.Types; use GNATcov_RTS.Types; package GNATcov_RTS.Strings is pragma Pure; + pragma No_Elaboration_Code_All; type GNATcov_RTS_String is record Str : System.Address; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output.ads index 754769b29..2715de18c 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output.ads @@ -29,5 +29,6 @@ package GNATcov_RTS.Traces.Output is pragma Pure; + pragma No_Elaboration_Code_All; end GNATcov_RTS.Traces.Output; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces.ads b/tools/gnatcov/rts/gnatcov_rts-traces.ads index 80ac3b278..73417b472 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces.ads @@ -27,5 +27,6 @@ package GNATcov_RTS.Traces is pragma Pure; + pragma No_Elaboration_Code_All; end GNATcov_RTS.Traces; diff --git a/tools/gnatcov/rts/gnatcov_rts-types.ads b/tools/gnatcov/rts/gnatcov_rts-types.ads index 4d6fee41d..531f90720 100644 --- a/tools/gnatcov/rts/gnatcov_rts-types.ads +++ b/tools/gnatcov/rts/gnatcov_rts-types.ads @@ -34,6 +34,7 @@ with System; package GNATcov_RTS.Types is pragma Pure; + pragma No_Elaboration_Code_All; type Unsigned_8 is mod 2 ** 8; type Unsigned_64 is mod 2 ** 64; diff --git a/tools/gnatcov/rts/gnatcov_rts.ads b/tools/gnatcov/rts/gnatcov_rts.ads index 475ebacc7..58c233843 100644 --- a/tools/gnatcov/rts/gnatcov_rts.ads +++ b/tools/gnatcov/rts/gnatcov_rts.ads @@ -33,6 +33,7 @@ pragma Warnings (Off, System); package GNATcov_RTS is pragma Pure; + pragma No_Elaboration_Code_All; package Std renames Standard; package Sys renames System; From a42941308c23a32ba4bd20dbfec27d93e2c78983 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 29 Jan 2024 14:19:06 +0000 Subject: [PATCH 0661/1483] gnatcov_rts: disable warnings for pragma No_Elaboration_Code_All This pragma does not exist with old toolchains, which thus warn that it is an unrecognized pragma. The recent tests-185-setup-warnings testcase regression shows that we want to avoid warnings when building gnatcov_rts, so kill these warnings with "pragma Warnings (Off);" in order to fix this regression. --- tools/gnatcov/rts/gcvrt.ads | 2 ++ tools/gnatcov/rts/gnatcov_rts-buffers.ads | 2 ++ tools/gnatcov/rts/gnatcov_rts-strings.ads | 2 ++ tools/gnatcov/rts/gnatcov_rts-traces-output.ads | 2 ++ tools/gnatcov/rts/gnatcov_rts-traces.ads | 2 ++ tools/gnatcov/rts/gnatcov_rts-types.ads | 2 ++ tools/gnatcov/rts/gnatcov_rts.ads | 2 ++ 7 files changed, 14 insertions(+) diff --git a/tools/gnatcov/rts/gcvrt.ads b/tools/gnatcov/rts/gcvrt.ads index ebd2c6447..7233b13a7 100644 --- a/tools/gnatcov/rts/gcvrt.ads +++ b/tools/gnatcov/rts/gcvrt.ads @@ -23,6 +23,8 @@ package GCVRT is pragma Pure; + pragma Warnings (Off); pragma No_Elaboration_Code_All; + pragma Warnings (On); end GCVRT; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index ef846c3ac..e2f40a266 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -36,7 +36,9 @@ with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; package GNATcov_RTS.Buffers is pragma Pure; + pragma Warnings (Off); pragma No_Elaboration_Code_All; + pragma Warnings (On); -- Any_Bit_Id is declared volatile here, as in order to instrument declare -- expressions we need to declare a constant MC_DC_State (a subtype of diff --git a/tools/gnatcov/rts/gnatcov_rts-strings.ads b/tools/gnatcov/rts/gnatcov_rts-strings.ads index 1f0eeda9c..3a7c102be 100644 --- a/tools/gnatcov/rts/gnatcov_rts-strings.ads +++ b/tools/gnatcov/rts/gnatcov_rts-strings.ads @@ -31,7 +31,9 @@ with GNATcov_RTS.Types; use GNATcov_RTS.Types; package GNATcov_RTS.Strings is pragma Pure; + pragma Warnings (Off); pragma No_Elaboration_Code_All; + pragma Warnings (On); type GNATcov_RTS_String is record Str : System.Address; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output.ads index 2715de18c..1ed1370f7 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output.ads @@ -29,6 +29,8 @@ package GNATcov_RTS.Traces.Output is pragma Pure; + pragma Warnings (Off); pragma No_Elaboration_Code_All; + pragma Warnings (On); end GNATcov_RTS.Traces.Output; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces.ads b/tools/gnatcov/rts/gnatcov_rts-traces.ads index 73417b472..a51e471df 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces.ads @@ -27,6 +27,8 @@ package GNATcov_RTS.Traces is pragma Pure; + pragma Warnings (Off); pragma No_Elaboration_Code_All; + pragma Warnings (On); end GNATcov_RTS.Traces; diff --git a/tools/gnatcov/rts/gnatcov_rts-types.ads b/tools/gnatcov/rts/gnatcov_rts-types.ads index 531f90720..0ace624a6 100644 --- a/tools/gnatcov/rts/gnatcov_rts-types.ads +++ b/tools/gnatcov/rts/gnatcov_rts-types.ads @@ -34,7 +34,9 @@ with System; package GNATcov_RTS.Types is pragma Pure; + pragma Warnings (Off); pragma No_Elaboration_Code_All; + pragma Warnings (On); type Unsigned_8 is mod 2 ** 8; type Unsigned_64 is mod 2 ** 64; diff --git a/tools/gnatcov/rts/gnatcov_rts.ads b/tools/gnatcov/rts/gnatcov_rts.ads index 58c233843..4e31e2c7d 100644 --- a/tools/gnatcov/rts/gnatcov_rts.ads +++ b/tools/gnatcov/rts/gnatcov_rts.ads @@ -33,7 +33,9 @@ pragma Warnings (Off, System); package GNATcov_RTS is pragma Pure; + pragma Warnings (Off); pragma No_Elaboration_Code_All; + pragma Warnings (On); package Std renames Standard; package Sys renames System; From 457b227f1d66efd268d1a5f09c2a8f5a832d6ab9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 25 Jan 2024 15:06:27 +0100 Subject: [PATCH 0662/1483] src_traces.rst: add a note about warnings on instrumented source code --- doc/gnatcov/src_traces.rst | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index bfbcf8855..e24701e7f 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -519,6 +519,22 @@ absolutely require :command:`gprbuild` to build the instrumented programs, even though we have augmented that builder with a few features to make that process very efficient and straightforward. +.. note:: + + The variety of supported compilers/compiler versions/optional warnings makes + it an irrealistic goal for |gcvins| (and source code generators in general) to + produce warning-free code. For instance, a hypothetical compiler is + perfectly allowed to warn when functions have more than X statements; yet it + would not be reasonable for |gcvins| to accomodate this restriction. + + It is important to note that these are warnings (notes that the compiler can + emit on code deemed suspicious, but which do not abort compilation), as + opposed to errors, which do abort compilation. + + For these reasons, the most reasonable thing to do with automatically + generated code is to disable “warnings-as-error†(``-gnatwn`` for GNAT, + ``-Wno-error`` for GCC) when building instrumented code. + Extracting a trace from standard output ======================================= From c7eaef14fde1e5ef3bc3f284586e8cbe7430f60a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 29 Jan 2024 17:49:18 +0100 Subject: [PATCH 0663/1483] Revert "CI: temporarily rebuild the bootstrapping gnatcov" This reverts commit 089c6bd3db70a6d7f070baf33481e0733cc16467. --- .gitlab-ci.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 51a973e31..a824dd9cc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -28,7 +28,7 @@ build: - require_issue - *basic_setup # Build using anod - - anod build gnatcov $ACI_TRACK_QUALIFIER --minimal + - anod install gnatcov $ACI_TRACK_QUALIFIER --latest - anod build --minimal gnatcov -Qinstr $ACI_TRACK_QUALIFIER # Package all components created so far @@ -82,7 +82,6 @@ build_community: # then remove temporaries to save disk space. - tar zxf $PACKAGE_ABSOLUTE_NAME -C / - anod-copy-components $ANOD_DEFAULT_SANDBOX_DIR/exp-comps $ANOD_DEFAULT_SANDBOX_DIR - - anod install gnatcov $ACI_TRACK_QUALIFIER - anod install gnatcov -Qinstr $ACI_TRACK_QUALIFIER - rm -rf $PACKAGE_ABSOLUTE_NAME $ANOD_DEFAULT_SANDBOX_DIR/exp-comps From b12f8feb9b656d9805a220061f5377d34c6d31d8 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 29 Jan 2024 16:41:42 +0000 Subject: [PATCH 0664/1483] Workaround a GNATCOLL.Projects.Other_File bug for Ada runtime subunits --- .../runtime/ada_object_path | 0 .../runtime/ada_source_path | 2 + .../runtime/adainclude/empty-dir.txt | 0 .../runtime/gnarl/s-taprop.adb | 20 +++ .../runtime/gnarl/s-taprop.ads | 5 + .../runtime/gnarl/s-taspri.ads | 3 + .../runtime/gnarl/s-tpopsp.adb | 13 ++ .../runtime/gnarl/s-tporft.adb | 5 + .../217-runtime-subunit/runtime/gnat/ada.ads | 4 + .../runtime/gnat/system.ads | 114 ++++++++++++++++++ .../runtime/ravenscar_build.gpr | 15 +++ .../runtime/runtime_build.gpr | 19 +++ .../instr-cov/217-runtime-subunit/test.py | 33 +++++ tools/gnatcov/project.adb | 24 +++- 14 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/instr-cov/217-runtime-subunit/runtime/ada_object_path create mode 100644 testsuite/tests/instr-cov/217-runtime-subunit/runtime/ada_source_path create mode 100644 testsuite/tests/instr-cov/217-runtime-subunit/runtime/adainclude/empty-dir.txt create mode 100644 testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.adb create mode 100644 testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.ads create mode 100644 testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taspri.ads create mode 100644 testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tpopsp.adb create mode 100644 testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tporft.adb create mode 100644 testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/ada.ads create mode 100644 testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/system.ads create mode 100644 testsuite/tests/instr-cov/217-runtime-subunit/runtime/ravenscar_build.gpr create mode 100644 testsuite/tests/instr-cov/217-runtime-subunit/runtime/runtime_build.gpr create mode 100644 testsuite/tests/instr-cov/217-runtime-subunit/test.py diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ada_object_path b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ada_object_path new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ada_source_path b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ada_source_path new file mode 100644 index 000000000..430b67d00 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ada_source_path @@ -0,0 +1,2 @@ +gnat +gnarl diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/adainclude/empty-dir.txt b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/adainclude/empty-dir.txt new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.adb b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.adb new file mode 100644 index 000000000..fd8b1ce92 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.adb @@ -0,0 +1,20 @@ +package body System.Task_Primitives.Operations is + + package Specific is + procedure Dummy; + end Specific; + + package body Specific is separate; + + ----------- + -- Dummy -- + ----------- + + procedure Dummy is + begin + Specific.Dummy; + end Dummy; + + function Register_Foreign_Thread return Integer is separate; + +end System.Task_Primitives.Operations; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.ads b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.ads new file mode 100644 index 000000000..0dcbf8ace --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taprop.ads @@ -0,0 +1,5 @@ +package System.Task_Primitives.Operations is + pragma Preelaborate; + procedure Dummy; + function Register_Foreign_Thread return Integer; +end System.Task_Primitives.Operations; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taspri.ads b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taspri.ads new file mode 100644 index 000000000..dadd20078 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-taspri.ads @@ -0,0 +1,3 @@ +package System.Task_Primitives is + pragma Preelaborate; +end System.Task_Primitives; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tpopsp.adb b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tpopsp.adb new file mode 100644 index 000000000..3e4a9163d --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tpopsp.adb @@ -0,0 +1,13 @@ +separate (System.Task_Primitives.Operations) +package body Specific is + + ----------- + -- Dummy -- + ----------- + + procedure Dummy is + begin + null; + end Dummy; + +end Specific; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tporft.adb b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tporft.adb new file mode 100644 index 000000000..d3d8053a4 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnarl/s-tporft.adb @@ -0,0 +1,5 @@ +separate (System.Task_Primitives.Operations) +function Register_Foreign_Thread return Integer is +begin + return 0; +end Register_Foreign_Thread; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/ada.ads b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/ada.ads new file mode 100644 index 000000000..fed04e343 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/ada.ads @@ -0,0 +1,4 @@ +package Ada is + pragma No_Elaboration_Code_All; + pragma Pure; +end Ada; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/system.ads b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/system.ads new file mode 100644 index 000000000..1a286ad12 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/gnat/system.ads @@ -0,0 +1,114 @@ +package System is + pragma Pure; + pragma No_Elaboration_Code_All; + + subtype Name is String; + System_Name : constant Name := "foo"; + + -- System-Dependent Named Numbers + + Min_Int : constant := -2 ** (Standard'Max_Integer_Size - 1); + Max_Int : constant := 2 ** (Standard'Max_Integer_Size - 1) - 1; + + Max_Binary_Modulus : constant := 2 ** Standard'Max_Integer_Size; + Max_Nonbinary_Modulus : constant := 2 ** Integer'Size - 1; + + Max_Base_Digits : constant := Long_Long_Float'Digits; + Max_Digits : constant := Long_Long_Float'Digits; + + Max_Mantissa : constant := Standard'Max_Integer_Size - 1; + Fine_Delta : constant := 2.0 ** (-Max_Mantissa); + + Tick : constant := 0.000_001; + + -- Storage-related Declarations + + type Address is private; + pragma Preelaborable_Initialization (Address); + Null_Address : constant Address; + + Storage_Unit : constant := 8; + Word_Size : constant := Standard'Word_Size; + Memory_Size : constant := 2 ** Word_Size; + + -- Address comparison + + function "<" (Left, Right : Address) return Boolean; + function "<=" (Left, Right : Address) return Boolean; + function ">" (Left, Right : Address) return Boolean; + function ">=" (Left, Right : Address) return Boolean; + function "=" (Left, Right : Address) return Boolean; + + pragma Import (Intrinsic, "<"); + pragma Import (Intrinsic, "<="); + pragma Import (Intrinsic, ">"); + pragma Import (Intrinsic, ">="); + pragma Import (Intrinsic, "="); + + -- Other System-Dependent Declarations + + type Bit_Order is (High_Order_First, Low_Order_First); + Default_Bit_Order : constant Bit_Order := + Bit_Order'Val (Standard'Default_Bit_Order); + pragma Warnings (Off, Default_Bit_Order); -- kill constant condition warning + + -- Priority-related Declarations (RM D.1) + + -- If the scheduling policy is SCHED_FIFO or SCHED_RR the runtime makes use + -- of the entire range provided by the system. + -- + -- If the scheduling policy is SCHED_OTHER the only valid system priority + -- is 1 and other values are simply ignored. + + Max_Priority : constant Positive := 62; + Max_Interrupt_Priority : constant Positive := 63; + + subtype Any_Priority is Integer range 1 .. 63; + subtype Priority is Any_Priority range 1 .. 62; + subtype Interrupt_Priority is Any_Priority range 63 .. 63; + + Default_Priority : constant Priority := 10; + +private + + type Address is mod Memory_Size; + for Address'Size use Standard'Address_Size; + + Null_Address : constant Address := 0; + + -------------------------------------- + -- System Implementation Parameters -- + -------------------------------------- + + -- These parameters provide information about the target that is used + -- by the compiler. They are in the private part of System, where they + -- can be accessed using the special circuitry in the Targparm unit + -- whose source should be consulted for more detailed descriptions + -- of the individual switch values. + + Backend_Divide_Checks : constant Boolean := False; + Backend_Overflow_Checks : constant Boolean := True; + Command_Line_Args : constant Boolean := True; + Configurable_Run_Time : constant Boolean := True; + Denorm : constant Boolean := True; + Duration_32_Bits : constant Boolean := False; + Exit_Status_Supported : constant Boolean := True; + Machine_Overflows : constant Boolean := False; + Machine_Rounds : constant Boolean := True; + Preallocated_Stacks : constant Boolean := False; + Signed_Zeros : constant Boolean := True; + Stack_Check_Default : constant Boolean := False; + Stack_Check_Probes : constant Boolean := True; + Stack_Check_Limits : constant Boolean := False; + Support_Aggregates : constant Boolean := True; + Support_Atomic_Primitives : constant Boolean := True; + Support_Composite_Assign : constant Boolean := True; + Support_Composite_Compare : constant Boolean := True; + Support_Long_Shifts : constant Boolean := True; + Always_Compatible_Rep : constant Boolean := True; + Suppress_Standard_Library : constant Boolean := True; + Use_Ada_Main_Program_Name : constant Boolean := False; + Frontend_Exceptions : constant Boolean := False; + ZCX_By_Default : constant Boolean := True; + +end System; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ravenscar_build.gpr b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ravenscar_build.gpr new file mode 100644 index 000000000..d4f96c0df --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/ravenscar_build.gpr @@ -0,0 +1,15 @@ +with "runtime_build.gpr"; + +project Ravenscar_Build is + + for Runtime ("Ada") use Runtime_Build'Runtime ("Ada"); + + for Library_Auto_Init use "False"; + for Library_Name use "gnarl"; + for Library_Dir use "adalib"; + for Object_Dir use "obj"; + for Source_Dirs use ("gnarl"); + + package Compiler renames Runtime_Build.Compiler; + +end Ravenscar_Build; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/runtime/runtime_build.gpr b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/runtime_build.gpr new file mode 100644 index 000000000..84e4c4333 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/runtime/runtime_build.gpr @@ -0,0 +1,19 @@ +project Runtime_Build is + + for Runtime ("Ada") use Project'Project_Dir; + + for Library_Auto_Init use "False"; + for Library_Name use "gnat"; + for Library_Dir use "adalib"; + for Object_Dir use "obj"; + for Source_Dirs use ("gnat"); + + package Compiler is + for Default_Switches ("Ada") use ("-gnatg"); + end Compiler; + + package Naming is + for Spec_Suffix ("Asm_CPP") use ".inc"; + end Naming; + +end Runtime_Build; diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/test.py b/testsuite/tests/instr-cov/217-runtime-subunit/test.py new file mode 100644 index 000000000..fbbac3c28 --- /dev/null +++ b/testsuite/tests/instr-cov/217-runtime-subunit/test.py @@ -0,0 +1,33 @@ +""" +Check that the instrumentation of the s-tpopsp.adb and s-tporft.adb sources in +the Ada runtime completes (it used to crash). +""" + +import os.path + +from e3.fs import mkdir, sync_tree + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +# Create a copy of the runtime to avoid polluting the test directory +sync_tree("../runtime", "runtime") + +runtime_prj = os.path.abspath("runtime/ravenscar_build.gpr") +runtime_dir = os.path.dirname(runtime_prj) + +xcov_instrument( + gprsw=GPRswitches(root_project=runtime_prj), + covlevel="stmt+mcdc", + auto_config_args=False, + auto_target_args=False, + extra_args=[ + "--target", thistest.env.target.triplet, "--RTS", runtime_dir + ], +) + +thistest.result() diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 576e1144c..d2d26df6f 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -238,7 +238,29 @@ package body Project is function Owning_Unit_Name (Info : File_Info) return String is begin if Info.Unit_Part = Unit_Separate then - return Prj_Tree.Info (Prj_Tree.Other_File (Info.File)).Unit_Name; + declare + Other : constant File_Info := + Prj_Tree.Info (Prj_Tree.Other_File (Info.File)); + begin + -- TODO??? (eng/das/cov/gnatcoverage#217) + -- GNATCOLL.Projects.Other_File misbehaves for some subunits in + -- the Ada runtime: work around this bug here until it is fixed. + + if Other.Unit_Name /= "" then + return Other.Unit_Name; + end if; + + declare + Unit_Name : constant String := Info.Unit_Name; + begin + if Unit_Name in "s.tpopsp" | "s.tporft" then + return "s.taprop"; + end if; + + raise Program_Error with + "cannot determine owning unit for separate " & Unit_Name; + end; + end; else return Info.Unit_Name; end if; From 1bbfc1dba1ea51ae836effc786d6e3f0698ccd42 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 4 Dec 2023 16:17:49 +0100 Subject: [PATCH 0665/1483] [integrated instrumentation] improve the documentation wrt. the workflow --- doc/gnatcov/integrated_instr.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/gnatcov/integrated_instr.rst b/doc/gnatcov/integrated_instr.rst index aa0926298..4bc3459fe 100644 --- a/doc/gnatcov/integrated_instr.rst +++ b/doc/gnatcov/integrated_instr.rst @@ -22,6 +22,11 @@ Then the process essentially goes like: #. Build the instrumented code using the generated compiler wrapper(s); #. Execute the program to produce a trace. +The compiler wrapper embeds knowledge through the ``gnatcov_config.json`` +configuration file that is generated alongside it. It is thus necessary to +re-run the setup step it if the closure of sources of interest, or if the build +environment (e.g. the path for the original compiler) changes. + Specifying instrumentation switches =================================== From 992be5d1b02d99134d4f75c04ed45b7c52ba673c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 31 Jan 2024 21:03:26 +0000 Subject: [PATCH 0666/1483] SC_Obligations: fix spurious propagation of "non instrumented SCO" info This information is stored in global tables: we need to clear these tables so that when "gnatcov instrument" goes from one unit to another, information from the previous unit does not spuriously percolate to the next unit. --- .../219-non-instr-propagation/main.adb | 16 +++++++ .../219-non-instr-propagation/pkg_1.adb | 33 ++++++++++++++ .../219-non-instr-propagation/pkg_1.ads | 11 +++++ .../219-non-instr-propagation/pkg_2.adb | 28 ++++++++++++ .../219-non-instr-propagation/pkg_2.ads | 10 +++++ .../219-non-instr-propagation/test.opt | 4 ++ .../219-non-instr-propagation/test.py | 45 +++++++++++++++++++ tools/gnatcov/sc_obligations.adb | 2 + 8 files changed, 149 insertions(+) create mode 100644 testsuite/tests/instr-cov/219-non-instr-propagation/main.adb create mode 100644 testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.adb create mode 100644 testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.ads create mode 100644 testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.adb create mode 100644 testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.ads create mode 100644 testsuite/tests/instr-cov/219-non-instr-propagation/test.opt create mode 100644 testsuite/tests/instr-cov/219-non-instr-propagation/test.py diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/main.adb b/testsuite/tests/instr-cov/219-non-instr-propagation/main.adb new file mode 100644 index 000000000..15f32db9c --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/main.adb @@ -0,0 +1,16 @@ +with Pkg_1; +with Pkg_2; + +procedure Main is + T1 : Pkg_1.PT; + T2 : Pkg_2.PT; +begin + T1.Say_Hello; + T1.Set_Cond (False); + T1.Set_Cond (True); + T1.Wait_Cond; + + T2.Set_Cond (False); + T2.Set_Cond (True); + T2.Wait_Cond; +end Main; diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.adb b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.adb new file mode 100644 index 000000000..d8d8f040d --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.adb @@ -0,0 +1,33 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg_1 is + protected body PT is + + procedure Say_Hello is + begin + Put_Line ("Hello"); -- SCO 3 (stmt) + end Say_Hello; + + --------------- + -- Wait_Cond -- + --------------- + + entry Wait_Cond when Cond is -- SCO 4+5 (decision+condition) + begin + Put_Line ("OK"); -- SCO 6 (stmt) + end Wait_Cond; + + -------------- + -- Set_Cond -- + -------------- + + procedure Set_Cond (Value : Boolean) is + begin + if Value then -- SCO 7-8+9 (stmt+decision+condition) + Put_Line ("OK"); -- SCO 10 (stmt) + end if; + Cond := True; -- SCO 11 (stmt) + end Set_Cond; + + end PT; +end Pkg_1; diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.ads b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.ads new file mode 100644 index 000000000..1f12e2f18 --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_1.ads @@ -0,0 +1,11 @@ +pragma Restrictions (Simple_Barriers); + +package Pkg_1 is + protected type PT is -- SCO 1 (stmt) + procedure Say_Hello; + entry Wait_Cond; + procedure Set_Cond (Value : Boolean); + private + Cond : Boolean := False; -- SCO 2 (stmt) + end PT; +end Pkg_1; diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.adb b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.adb new file mode 100644 index 000000000..737d715a7 --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.adb @@ -0,0 +1,28 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg_2 is + protected body PT is + + -------------- + -- Set_Cond -- + -------------- + + procedure Set_Cond (Value : Boolean) is + begin + if Value then -- SCO 3+4+5 (stmt+decision+condition) + Put_Line ("OK"); -- SCO 6 (stmt) + end if; + Cond := True; -- SCO 7 (stmt) + end Set_Cond; + + --------------- + -- Wait_Cond -- + --------------- + + entry Wait_Cond when Cond is -- SCO 8+9 (decision+condition) + begin + Put_Line ("OK"); -- SCO 10 (stmt) + end Wait_Cond; + + end PT; +end Pkg_2; diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.ads b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.ads new file mode 100644 index 000000000..44e14452f --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/pkg_2.ads @@ -0,0 +1,10 @@ +pragma Restrictions (Simple_Barriers); + +package Pkg_2 is + protected type PT is -- SCO 1 (stmt) + procedure Set_Cond (Value : Boolean); + entry Wait_Cond; + private + Cond : Boolean := False; -- SCO 2 (stmt) + end PT; +end Pkg_2; diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/test.opt b/testsuite/tests/instr-cov/219-non-instr-propagation/test.opt new file mode 100644 index 000000000..6518f1a79 --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/test.opt @@ -0,0 +1,4 @@ +-- This testcase relies on protected bodies, which are not available with +-- light or embedded runtimes. +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/test.py b/testsuite/tests/instr-cov/219-non-instr-propagation/test.py new file mode 100644 index 000000000..8b99bb2dd --- /dev/null +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/test.py @@ -0,0 +1,45 @@ +""" +Check that the "non-instrumented SCO" state does not propagate from one +instrumented unit to the other (this is a regression testcase). + +The sources are carefully arranged so that we have two units (Pkg_1 and Pkg_2) +that yield equivalent sequences of SCOs (stmt, stmt, decision, condition, stmt, +... see the comments in the Ada sources). In Pkg_1, one decision is not +instrumented (because of the entry body guard limitation under the +Simple_Barriers restriction) while the corresponding one in Pkg_2 is +instrumented, and conversely, so that we check the absence of propagation +whether Pkg_1 is instrumented before Pkg_2 or the opposite. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.adb"]), + units=["pkg_1", "pkg_2"], + ), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports( + "*.xcov", + { + "pkg_1.adb.xcov": {"+": {8, 17, 26, 27, 29}, "?": {15}}, + "pkg_1.ads.xcov": {}, + "pkg_2.adb.xcov": {"+": {12, 13, 15, 24}, "?": {22}}, + "pkg_2.ads.xcov": {}, + }, + cwd="xcov", +) + +thistest.result() diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 080edb343..94a3e4c9c 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -2065,6 +2065,8 @@ package body SC_Obligations is Inst_Vector.Clear; BDD_Vector.Clear; SCO_Vector.Clear; + Non_Instr_SCOs.Clear; + Non_Instr_MCDC_SCOs.Clear; end Checkpoint_Clear; --------------------- From 1f84127cebb01b9458ea945b10c7125c4c01b130 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 24 Jan 2024 14:29:01 +0100 Subject: [PATCH 0667/1483] tests/LB13-031-post-aspect: Modify test The original test case was a pathological example that was unlikely to be found in real life code, for which the compiler generated slightly off debug information. --- testsuite/tests/LB13-031-post-aspect/src/passor.adb | 4 +++- testsuite/tests/LB13-031-post-aspect/test.opt | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/LB13-031-post-aspect/src/passor.adb b/testsuite/tests/LB13-031-post-aspect/src/passor.adb index e54219acc..8cc3c4030 100644 --- a/testsuite/tests/LB13-031-post-aspect/src/passor.adb +++ b/testsuite/tests/LB13-031-post-aspect/src/passor.adb @@ -1,5 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + procedure Passor (A, B : Boolean) is begin - null; -- # stmt + Put_Line ("Hello world"); -- # stmt end; diff --git a/testsuite/tests/LB13-031-post-aspect/test.opt b/testsuite/tests/LB13-031-post-aspect/test.opt index 4b967bbd5..0a9ed7ea5 100644 --- a/testsuite/tests/LB13-031-post-aspect/test.opt +++ b/testsuite/tests/LB13-031-post-aspect/test.opt @@ -1,4 +1,3 @@ 7.0.3 DEAD testing coverage of expressions in aspects, implemented post 7.0.3 src-traces XFAIL S606-037: src-traces and contracts 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 -leon3-elf,CARGS_O1,bin-traces XFAIL V906-019: contracts with NOP subp body in delay slot From 253577063f8cc621661b3cb5011ca2d94b63b251 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 17 Nov 2023 16:42:11 +0000 Subject: [PATCH 0668/1483] instrument-ada_unit.adb: update after a node kind removal in Libadalang Libadalang no longer has a dedicated node type for lists of Basic_Decl nodes: all such lists can now also contain pragmas, so they are now lists of Ada_Node. (cherry picked from commit d7643ade728cbc06848b356478e02fa87a566f24) --- tools/gnatcov/instrument-ada_unit.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 1fb9afa56..7821b0191 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3822,7 +3822,7 @@ package body Instrument.Ada_Unit is declare Expr_Func : constant Expr_Function := N.As_Expr_Function; Decl_List : constant Node_Rewriting_Handle := - Create_Node (UIC.Rewriting_Context, Ada_Basic_Decl_List); + Create_Node (UIC.Rewriting_Context, Ada_Ada_Node_List); -- List of declarations to hold the statement witness call and -- local MC/DC state holder variables. From 1ae0f33a3c4dbc3bc0d6827dbcd357911658e1fb Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 22 Nov 2023 16:33:10 +0000 Subject: [PATCH 0669/1483] instrument-ada_unit.adb: update after recent Libadalang tree changes (cherry picked from commit a2bc3b3c75dd0641b7dc154b500871ebf4da0bb7) --- tools/gnatcov/instrument-ada_unit.adb | 29 ++++++++++++++++++--------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 7821b0191..011af8b0d 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -4704,13 +4704,16 @@ package body Instrument.Ada_Unit is -- sake of completeness. Instrument_Statement (UIC, N, 'F'); - Process_Expression - (UIC, ISC.As_For_Loop_Spec.F_Var_Decl, 'X'); - Process_Expression - (UIC, ISC.As_For_Loop_Spec.F_Iter_Expr, 'X'); - Process_Expression - (UIC, ISC.As_For_Loop_Spec.F_Iter_Filter, 'W'); - + declare + LS : constant For_Loop_Spec := ISC.As_For_Loop_Spec; + begin + Process_Expression (UIC, LS.F_Var_Decl, 'X'); + Process_Expression (UIC, LS.F_Iter_Expr, 'X'); + if not LS.F_Iter_Filter.Is_Null then + Process_Expression + (UIC, LS.F_Iter_Filter.F_Expr, 'W'); + end if; + end; end if; end if; @@ -6028,9 +6031,15 @@ package body Instrument.Ada_Unit is return Over; when Ada_For_Loop_Spec => - Process_Decisions (UIC, N.As_For_Loop_Spec.F_Var_Decl, 'X'); - Process_Decisions (UIC, N.As_For_Loop_Spec.F_Iter_Expr, 'X'); - Process_Decisions (UIC, N.As_For_Loop_Spec.F_Iter_Filter, 'W'); + declare + LS : constant For_Loop_Spec := N.As_For_Loop_Spec; + begin + Process_Decisions (UIC, LS.F_Var_Decl, 'X'); + Process_Decisions (UIC, LS.F_Iter_Expr, 'X'); + if not LS.F_Iter_Filter.Is_Null then + Process_Decisions (UIC, LS.F_Iter_Filter.F_Expr, 'W'); + end if; + end; return Over; -- Aspects for which we don't want to instrument the decision From 4e5a2102d12482ef043c00027b414dfdcd273c01 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 1 Dec 2023 10:02:00 +0000 Subject: [PATCH 0670/1483] Revert "Ada2022/aggregates/containers: workaround the compiler hang" This reverts commit 0cca65b8680d1218a725039bd80df041fa0e2c87: this workaround is no longer needed now that the GNAT hang has been fixed. (cherry picked from commit 76a6d6c5cc152577ef4e5c8ca56a064aab58a3e6) --- testsuite/tests/Ada2022/aggregates/containers/test.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/testsuite/tests/Ada2022/aggregates/containers/test.py b/testsuite/tests/Ada2022/aggregates/containers/test.py index 087505dcc..e755dd8c5 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/test.py +++ b/testsuite/tests/Ada2022/aggregates/containers/test.py @@ -8,9 +8,5 @@ from SUITE.context import thistest -# GNAT hangs on instrumented code (eng/toolchain/gnat#502): to avoid -# systematically hitting timeouts (wasting precious minutes in a testsuite -# run), abort the testcase early until this is fixed. -thistest.stop(RuntimeError) TestCase(category=CAT.decision).run() thistest.result() From 96d31492ac7d2d7627326cab977456e2e766efb6 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 23 Jan 2024 14:32:22 +0100 Subject: [PATCH 0671/1483] decision_map.adb: Adjust heuristic to identify finalization expansion Adjust the Trace_Destination heuristic to not be tricked by calls to finalization expansion symbols, that may reference source code locations outside of the currently evaluated decision. --- tools/gnatcov/decision_map.adb | 31 ++++++++++++++++++++++++++----- tools/gnatcov/decision_map.ads | 4 ++++ 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/decision_map.adb b/tools/gnatcov/decision_map.adb index d1808e18f..ec2ffd032 100644 --- a/tools/gnatcov/decision_map.adb +++ b/tools/gnatcov/decision_map.adb @@ -80,12 +80,13 @@ package body Decision_Map is -- Return the PC of the first conditional branch instruction in D_Occ. -- Used as unique identifier for occurrences. - type Call_Kind is (Normal, Raise_Exception, Finalizer); + type Call_Kind is (Normal, Raise_Exception, Finalizer, Finalization_Exp); -- Classification of calls within a decision: -- - normal calls to subprograms -- - calls that are known to raise an exception -- - calls to generated block finalizers / cleanup code - + -- - calls to finalization expansion symbols - excluding finalizers + -- -- A basic block in object code package Outcome_Reached_Maps is new Ada.Containers.Ordered_Maps @@ -161,6 +162,8 @@ package body Decision_Map is Finalizer_Symbol_Pattern : constant Regexp := Compile (".*___finalizer\.[0-9]+"); + Pre_Finalizer_Symbol_Pattern : constant Regexp := Compile + ("system__finalization_primitives__.*"); package Pc_Sets is new Ada.Containers.Ordered_Sets (Pc_Type); @@ -410,6 +413,9 @@ package body Decision_Map is elsif Is_Finalizer_Symbol (Sym_Name) then BB.Call := Finalizer; + + elsif Is_Finalization_Expansion_Symbol (Sym_Name) then + BB.Call := Finalization_Exp; end if; end; @@ -2196,9 +2202,15 @@ package body Decision_Map is else False)); - -- Decision for the jump at the end of BB (if any) + -- If this is a call to a finalization symbol (besides the finalizer + -- itself), assume that we remain in the decision. Otherwise, look + -- for the decision for the jump at the end of BB (if any). - D_SCO_For_Jump := Decision_Of_Jump (BB.To_PC); + if BB.Branch = Br_Call and then BB.Call = Finalization_Exp then + D_SCO_For_Jump := D_SCO; + else + D_SCO_For_Jump := Decision_Of_Jump (BB.To_PC); + end if; -- If in an IF-expression, and we're branching into a decision other -- than a nested one (or outside of any decision), then have reached @@ -2289,7 +2301,7 @@ package body Decision_Map is Edge_Info.Dest_Kind := Raise_Exception; end if; - elsif BB.Call = Normal then + elsif BB.Call in Normal | Finalization_Exp then Next_Dest := (BB.To + 1, Delay_Slot => No_PC); After_Call := True; goto Follow_Jump; @@ -3190,6 +3202,15 @@ package body Decision_Map is return Match (Name, Finalizer_Symbol_Pattern); end Is_Finalizer_Symbol; + -------------------------------------- + -- Is_Finalization_Expansion_Symbol -- + -------------------------------------- + + function Is_Finalization_Expansion_Symbol (Name : String) return Boolean is + begin + return Match (Name, Pre_Finalizer_Symbol_Pattern); + end Is_Finalization_Expansion_Symbol; + --------------- -- Write_Map -- --------------- diff --git a/tools/gnatcov/decision_map.ads b/tools/gnatcov/decision_map.ads index 8497bf253..6dd323b98 100644 --- a/tools/gnatcov/decision_map.ads +++ b/tools/gnatcov/decision_map.ads @@ -54,6 +54,10 @@ package Decision_Map is function Is_Finalizer_Symbol (Name : String) return Boolean; -- Return whether Name corresponds to a finalizer symbol name + function Is_Finalization_Expansion_Symbol (Name : String) return Boolean; + -- Return whether Name corresponds to a finalization expansion name, + -- excluding finalizers themselves. + --------------------------------- -- Control flow graph analysis -- --------------------------------- From 55b2a70fd3ea868cf351d2ebe32dbca7e398c482 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 8 Feb 2024 16:05:42 +0000 Subject: [PATCH 0672/1483] Fix instr. of expr. func. with access attr. references in 2022 mode --- .../instr-cov/225-expr-func-access/main.adb | 33 +++++++++++++ .../instr-cov/225-expr-func-access/test.py | 34 ++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 47 +++++++++++++++++-- 3 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/instr-cov/225-expr-func-access/main.adb create mode 100644 testsuite/tests/instr-cov/225-expr-func-access/test.py diff --git a/testsuite/tests/instr-cov/225-expr-func-access/main.adb b/testsuite/tests/instr-cov/225-expr-func-access/main.adb new file mode 100644 index 000000000..655cc016b --- /dev/null +++ b/testsuite/tests/instr-cov/225-expr-func-access/main.adb @@ -0,0 +1,33 @@ +pragma Ada_2022; + +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + + type Integer_Access is access all Integer; + + A : aliased Integer; + B : aliased Integer; + + function Get_Ref (Is_A : Boolean) return Integer_Access + is (if Is_A then A'Access else B'Access); + + function Get_Unc_Ref (Is_A : Boolean) return Integer_Access + is (if Is_A then A'Unchecked_Access else B'Unchecked_Access); + + function Get_Unr_Ref (Is_A : Boolean) return Integer_Access + is (if Is_A then A'Unrestricted_Access else B'Unrestricted_Access); + +begin + Get_Ref (True).all := 1; + Get_Ref (False).all := 2; + + Get_Unc_Ref (True).all := @ + 10; + Get_Unc_Ref (False).all := @ + 20; + + Get_Unr_Ref (True).all := @ + 100; + Get_Unr_Ref (False).all := @ + 200; + + Put_Line (A'Image); + Put_Line (B'Image); +end Main; diff --git a/testsuite/tests/instr-cov/225-expr-func-access/test.py b/testsuite/tests/instr-cov/225-expr-func-access/test.py new file mode 100644 index 000000000..b8a714e3f --- /dev/null +++ b/testsuite/tests/instr-cov/225-expr-func-access/test.py @@ -0,0 +1,34 @@ +""" +Check that, in Ada 2022 mode, expression functions that contain +'(Unrestricted_|Unchecked_)Access attribute references are correctly +instrumented. We used to introduce declare expressions in this case, which is +illegal. +""" + +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": { + "+": {7, 9, 10, 13, 16, 19, 22, 23, 25, 26, 28, 29, 31, 32} + } + }, + cwd="xcov", +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 011af8b0d..0ebe1f3be 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1022,6 +1022,10 @@ package body Instrument.Ada_Unit is -- generated is a primitive of a tagged type, and if that tagged type is -- the return type of the expression function. + function Has_Access_Attribute_Ref (E : Expr) return Boolean; + -- Return whether E or one of its subexpressions is a reference to the + -- 'Access, 'Unchecked_Access or 'Unrestricted_Access attributes. + function Has_Matching_Pragma_For_Unit (Context : Analysis_Context; Unit : LAL.Compilation_Unit; @@ -2830,6 +2834,38 @@ package body Instrument.Ada_Unit is return False; end Return_Type_Is_Controlling; + ------------------------------ + -- Has_Access_Attribute_Ref -- + ------------------------------ + + function Has_Access_Attribute_Ref (E : Expr) return Boolean is + + function Process_Node (N : Ada_Node'Class) return Visit_Status; + -- Helper for Libadalang.Analysis.Traverse. Return Stop if an access + -- attribute reference is found, Into otherwise. + + ------------------ + -- Process_Node -- + ------------------ + + function Process_Node (N : Ada_Node'Class) return Visit_Status is + begin + if N.Kind = Ada_Attribute_Ref + and then Canonicalize (N.As_Attribute_Ref.F_Attribute.Text).Symbol + in "access" | "unchecked_access" | "unrestricted_access" + then + return Stop; + end if; + + return Into; + end Process_Node; + + -- Start of processing for Has_Access_Attribute_Ref + + begin + return E.Traverse (Process_Node'Access) = Stop; + end Has_Access_Attribute_Ref; + --------------------------- -- Return_From_Subp_Body -- --------------------------- @@ -3812,12 +3848,17 @@ package body Instrument.Ada_Unit is UIC.Degenerate_Subprogram_Index + 1; -- Deal with the "easy" Ada 2022 and onwards case for expression - -- functions: - -- Simply nest the expression in a declare expression, and use that - -- to host the statement witness call, and local declarations. + -- functions: simply nest the expression in a declare expression, and + -- use that to host the statement witness call, and local + -- declarations. + -- + -- Note that this is not legal if the expression function body + -- contains *any* reference to a + -- 'Access/'Unchecked_Access/'Unrestricted_Access attribute. if UIC.Language_Version in Decl_Expr_Supported_Versions and then Is_Expr_Function + and then not Has_Access_Attribute_Ref (N.As_Expr_Function.F_Expr) then declare Expr_Func : constant Expr_Function := N.As_Expr_Function; From 0cfe406b47e9a9fea757749bdabb231c33f9b65a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 9 Feb 2024 10:42:02 +0000 Subject: [PATCH 0673/1483] Instrument: fix crash on incomplete type declaration with ATC(C) --- .../226-atc-incomp-type-decl/main.adb | 7 +++++ .../226-atc-incomp-type-decl/pkg.ads | 7 +++++ .../226-atc-incomp-type-decl/test.py | 29 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 4 +-- 4 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/instr-cov/226-atc-incomp-type-decl/main.adb create mode 100644 testsuite/tests/instr-cov/226-atc-incomp-type-decl/pkg.ads create mode 100644 testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py diff --git a/testsuite/tests/instr-cov/226-atc-incomp-type-decl/main.adb b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/main.adb new file mode 100644 index 000000000..f2245cc49 --- /dev/null +++ b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is + T : Pkg.Test_Type; +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/226-atc-incomp-type-decl/pkg.ads b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/pkg.ads new file mode 100644 index 000000000..25e847115 --- /dev/null +++ b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + type Test_Type; + type Test_Type_Ptr is access all Test_Type; + type Test_Type is record + Test_Var : Boolean; + end record; +end Pkg; diff --git a/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py new file mode 100644 index 000000000..5eb94b52a --- /dev/null +++ b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py @@ -0,0 +1,29 @@ +""" +Check that "gnatcov instrument" does not crash when instrumenting an incomplete +type declaration for ATC(C). +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+atc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "*.xcov", + { + "main.adb.xcov": {"+": {4, 6}}, + "pkg.ads.xcov": {}, + }, + cwd="xcov", +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 0ebe1f3be..14be85143 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -4995,9 +4995,7 @@ package body Instrument.Ada_Unit is Typ := 't'; if Assertion_Coverage_Enabled then Process_Contract - (UIC, - N.As_Concrete_Type_Decl, - "Type_Invariant"); + (UIC, N.As_Basic_Decl, "Type_Invariant"); end if; end if; From ec38067525d701c2270e5501f960214f6b1b3fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 18 Jan 2024 16:43:04 +0100 Subject: [PATCH 0674/1483] Regroup manual dump tests under a single directory --- testsuite/tests/instr-cov/ada_manual_dump/test.opt | 1 - testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.opt | 1 - testsuite/tests/instr-cov/c_manual_dump/test.opt | 1 - .../{ada_manual_dump => manual-dump/ada_only}/src-lib1/lib1.adb | 0 .../{ada_manual_dump => manual-dump/ada_only}/src-lib1/lib1.ads | 0 .../{ada_manual_dump => manual-dump/ada_only}/src-lib2/lib2.adb | 0 .../{ada_manual_dump => manual-dump/ada_only}/src-lib2/lib2.ads | 0 .../{ada_manual_dump => manual-dump/ada_only}/src/main.adb | 0 .../ada_only}/src/manual_dump.adb | 0 .../ada_only}/src/manual_dump.ads | 0 .../instr-cov/{ada_manual_dump => manual-dump/ada_only}/test.py | 0 .../ada_subprj}/src-lib1/lib1.adb | 0 .../ada_subprj}/src-lib1/lib1.ads | 0 .../ada_subprj}/src-lib1/src-lib2/lib2.adb | 0 .../ada_subprj}/src-lib1/src-lib2/lib2.ads | 0 .../ada_subprj}/src/main.adb | 0 .../ada_subprj}/test.py | 0 .../tests/instr-cov/manual-dump/{ => basic}/covdump__cov.adb | 0 .../tests/instr-cov/manual-dump/{ => basic}/covdump__nocov.adb | 0 testsuite/tests/instr-cov/manual-dump/{ => basic}/main.adb | 0 testsuite/tests/instr-cov/manual-dump/basic/test.opt | 1 + testsuite/tests/instr-cov/manual-dump/{ => basic}/test.py | 0 .../{c_manual_dump => manual-dump/c_only}/src-lib/foo.c | 0 .../{c_manual_dump => manual-dump/c_only}/src-lib/foo.h | 0 .../instr-cov/{c_manual_dump => manual-dump/c_only}/src/main.c | 0 .../instr-cov/{c_manual_dump => manual-dump/c_only}/test.py | 0 testsuite/tests/instr-cov/manual-dump/extra.opt | 1 + .../{mixed_manual_dump => manual-dump/mixed}/main_ada.adb | 0 .../instr-cov/{mixed_manual_dump => manual-dump/mixed}/main_c.c | 0 .../instr-cov/{mixed_manual_dump => manual-dump/mixed}/test.opt | 1 - .../instr-cov/{mixed_manual_dump => manual-dump/mixed}/test.py | 0 testsuite/tests/instr-cov/manual-dump/test.opt | 2 -- 32 files changed, 2 insertions(+), 6 deletions(-) delete mode 100644 testsuite/tests/instr-cov/ada_manual_dump/test.opt delete mode 100644 testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.opt delete mode 100644 testsuite/tests/instr-cov/c_manual_dump/test.opt rename testsuite/tests/instr-cov/{ada_manual_dump => manual-dump/ada_only}/src-lib1/lib1.adb (100%) rename testsuite/tests/instr-cov/{ada_manual_dump => manual-dump/ada_only}/src-lib1/lib1.ads (100%) rename testsuite/tests/instr-cov/{ada_manual_dump => manual-dump/ada_only}/src-lib2/lib2.adb (100%) rename testsuite/tests/instr-cov/{ada_manual_dump => manual-dump/ada_only}/src-lib2/lib2.ads (100%) rename testsuite/tests/instr-cov/{ada_manual_dump => manual-dump/ada_only}/src/main.adb (100%) rename testsuite/tests/instr-cov/{ada_manual_dump => manual-dump/ada_only}/src/manual_dump.adb (100%) rename testsuite/tests/instr-cov/{ada_manual_dump => manual-dump/ada_only}/src/manual_dump.ads (100%) rename testsuite/tests/instr-cov/{ada_manual_dump => manual-dump/ada_only}/test.py (100%) rename testsuite/tests/instr-cov/{ada_manual_no_dump_in_root => manual-dump/ada_subprj}/src-lib1/lib1.adb (100%) rename testsuite/tests/instr-cov/{ada_manual_no_dump_in_root => manual-dump/ada_subprj}/src-lib1/lib1.ads (100%) rename testsuite/tests/instr-cov/{ada_manual_no_dump_in_root => manual-dump/ada_subprj}/src-lib1/src-lib2/lib2.adb (100%) rename testsuite/tests/instr-cov/{ada_manual_no_dump_in_root => manual-dump/ada_subprj}/src-lib1/src-lib2/lib2.ads (100%) rename testsuite/tests/instr-cov/{ada_manual_no_dump_in_root => manual-dump/ada_subprj}/src/main.adb (100%) rename testsuite/tests/instr-cov/{ada_manual_no_dump_in_root => manual-dump/ada_subprj}/test.py (100%) rename testsuite/tests/instr-cov/manual-dump/{ => basic}/covdump__cov.adb (100%) rename testsuite/tests/instr-cov/manual-dump/{ => basic}/covdump__nocov.adb (100%) rename testsuite/tests/instr-cov/manual-dump/{ => basic}/main.adb (100%) create mode 100644 testsuite/tests/instr-cov/manual-dump/basic/test.opt rename testsuite/tests/instr-cov/manual-dump/{ => basic}/test.py (100%) rename testsuite/tests/instr-cov/{c_manual_dump => manual-dump/c_only}/src-lib/foo.c (100%) rename testsuite/tests/instr-cov/{c_manual_dump => manual-dump/c_only}/src-lib/foo.h (100%) rename testsuite/tests/instr-cov/{c_manual_dump => manual-dump/c_only}/src/main.c (100%) rename testsuite/tests/instr-cov/{c_manual_dump => manual-dump/c_only}/test.py (100%) create mode 100644 testsuite/tests/instr-cov/manual-dump/extra.opt rename testsuite/tests/instr-cov/{mixed_manual_dump => manual-dump/mixed}/main_ada.adb (100%) rename testsuite/tests/instr-cov/{mixed_manual_dump => manual-dump/mixed}/main_c.c (100%) rename testsuite/tests/instr-cov/{mixed_manual_dump => manual-dump/mixed}/test.opt (62%) rename testsuite/tests/instr-cov/{mixed_manual_dump => manual-dump/mixed}/test.py (100%) delete mode 100644 testsuite/tests/instr-cov/manual-dump/test.opt diff --git a/testsuite/tests/instr-cov/ada_manual_dump/test.opt b/testsuite/tests/instr-cov/ada_manual_dump/test.opt deleted file mode 100644 index da626d559..000000000 --- a/testsuite/tests/instr-cov/ada_manual_dump/test.opt +++ /dev/null @@ -1 +0,0 @@ -!src-traces DEAD Checks a feature specific to the instrumenter diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.opt b/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.opt deleted file mode 100644 index da626d559..000000000 --- a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.opt +++ /dev/null @@ -1 +0,0 @@ -!src-traces DEAD Checks a feature specific to the instrumenter diff --git a/testsuite/tests/instr-cov/c_manual_dump/test.opt b/testsuite/tests/instr-cov/c_manual_dump/test.opt deleted file mode 100644 index da626d559..000000000 --- a/testsuite/tests/instr-cov/c_manual_dump/test.opt +++ /dev/null @@ -1 +0,0 @@ -!src-traces DEAD Checks a feature specific to the instrumenter diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src-lib1/lib1.adb b/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib1/lib1.adb similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_dump/src-lib1/lib1.adb rename to testsuite/tests/instr-cov/manual-dump/ada_only/src-lib1/lib1.adb diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src-lib1/lib1.ads b/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib1/lib1.ads similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_dump/src-lib1/lib1.ads rename to testsuite/tests/instr-cov/manual-dump/ada_only/src-lib1/lib1.ads diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src-lib2/lib2.adb b/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib2/lib2.adb similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_dump/src-lib2/lib2.adb rename to testsuite/tests/instr-cov/manual-dump/ada_only/src-lib2/lib2.adb diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src-lib2/lib2.ads b/testsuite/tests/instr-cov/manual-dump/ada_only/src-lib2/lib2.ads similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_dump/src-lib2/lib2.ads rename to testsuite/tests/instr-cov/manual-dump/ada_only/src-lib2/lib2.ads diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src/main.adb b/testsuite/tests/instr-cov/manual-dump/ada_only/src/main.adb similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_dump/src/main.adb rename to testsuite/tests/instr-cov/manual-dump/ada_only/src/main.adb diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src/manual_dump.adb b/testsuite/tests/instr-cov/manual-dump/ada_only/src/manual_dump.adb similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_dump/src/manual_dump.adb rename to testsuite/tests/instr-cov/manual-dump/ada_only/src/manual_dump.adb diff --git a/testsuite/tests/instr-cov/ada_manual_dump/src/manual_dump.ads b/testsuite/tests/instr-cov/manual-dump/ada_only/src/manual_dump.ads similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_dump/src/manual_dump.ads rename to testsuite/tests/instr-cov/manual-dump/ada_only/src/manual_dump.ads diff --git a/testsuite/tests/instr-cov/ada_manual_dump/test.py b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_dump/test.py rename to testsuite/tests/instr-cov/manual-dump/ada_only/test.py diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.adb b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/lib1.adb similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.adb rename to testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/lib1.adb diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.ads b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/lib1.ads similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/lib1.ads rename to testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/lib1.ads diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib2/lib2.adb b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/src-lib2/lib2.adb similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib2/lib2.adb rename to testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/src-lib2/lib2.adb diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib2/lib2.ads b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/src-lib2/lib2.ads similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src-lib1/src-lib2/lib2.ads rename to testsuite/tests/instr-cov/manual-dump/ada_subprj/src-lib1/src-lib2/lib2.ads diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src/main.adb b/testsuite/tests/instr-cov/manual-dump/ada_subprj/src/main.adb similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_no_dump_in_root/src/main.adb rename to testsuite/tests/instr-cov/manual-dump/ada_subprj/src/main.adb diff --git a/testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.py b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py similarity index 100% rename from testsuite/tests/instr-cov/ada_manual_no_dump_in_root/test.py rename to testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py diff --git a/testsuite/tests/instr-cov/manual-dump/covdump__cov.adb b/testsuite/tests/instr-cov/manual-dump/basic/covdump__cov.adb similarity index 100% rename from testsuite/tests/instr-cov/manual-dump/covdump__cov.adb rename to testsuite/tests/instr-cov/manual-dump/basic/covdump__cov.adb diff --git a/testsuite/tests/instr-cov/manual-dump/covdump__nocov.adb b/testsuite/tests/instr-cov/manual-dump/basic/covdump__nocov.adb similarity index 100% rename from testsuite/tests/instr-cov/manual-dump/covdump__nocov.adb rename to testsuite/tests/instr-cov/manual-dump/basic/covdump__nocov.adb diff --git a/testsuite/tests/instr-cov/manual-dump/main.adb b/testsuite/tests/instr-cov/manual-dump/basic/main.adb similarity index 100% rename from testsuite/tests/instr-cov/manual-dump/main.adb rename to testsuite/tests/instr-cov/manual-dump/basic/main.adb diff --git a/testsuite/tests/instr-cov/manual-dump/basic/test.opt b/testsuite/tests/instr-cov/manual-dump/basic/test.opt new file mode 100644 index 000000000..b8eef9d73 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/basic/test.opt @@ -0,0 +1 @@ +!RTS_FULL DEAD Uses the full instrumentation runtime. diff --git a/testsuite/tests/instr-cov/manual-dump/test.py b/testsuite/tests/instr-cov/manual-dump/basic/test.py similarity index 100% rename from testsuite/tests/instr-cov/manual-dump/test.py rename to testsuite/tests/instr-cov/manual-dump/basic/test.py diff --git a/testsuite/tests/instr-cov/c_manual_dump/src-lib/foo.c b/testsuite/tests/instr-cov/manual-dump/c_only/src-lib/foo.c similarity index 100% rename from testsuite/tests/instr-cov/c_manual_dump/src-lib/foo.c rename to testsuite/tests/instr-cov/manual-dump/c_only/src-lib/foo.c diff --git a/testsuite/tests/instr-cov/c_manual_dump/src-lib/foo.h b/testsuite/tests/instr-cov/manual-dump/c_only/src-lib/foo.h similarity index 100% rename from testsuite/tests/instr-cov/c_manual_dump/src-lib/foo.h rename to testsuite/tests/instr-cov/manual-dump/c_only/src-lib/foo.h diff --git a/testsuite/tests/instr-cov/c_manual_dump/src/main.c b/testsuite/tests/instr-cov/manual-dump/c_only/src/main.c similarity index 100% rename from testsuite/tests/instr-cov/c_manual_dump/src/main.c rename to testsuite/tests/instr-cov/manual-dump/c_only/src/main.c diff --git a/testsuite/tests/instr-cov/c_manual_dump/test.py b/testsuite/tests/instr-cov/manual-dump/c_only/test.py similarity index 100% rename from testsuite/tests/instr-cov/c_manual_dump/test.py rename to testsuite/tests/instr-cov/manual-dump/c_only/test.py diff --git a/testsuite/tests/instr-cov/manual-dump/extra.opt b/testsuite/tests/instr-cov/manual-dump/extra.opt new file mode 100644 index 000000000..ab2569354 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD Test specific to src traces feature diff --git a/testsuite/tests/instr-cov/mixed_manual_dump/main_ada.adb b/testsuite/tests/instr-cov/manual-dump/mixed/main_ada.adb similarity index 100% rename from testsuite/tests/instr-cov/mixed_manual_dump/main_ada.adb rename to testsuite/tests/instr-cov/manual-dump/mixed/main_ada.adb diff --git a/testsuite/tests/instr-cov/mixed_manual_dump/main_c.c b/testsuite/tests/instr-cov/manual-dump/mixed/main_c.c similarity index 100% rename from testsuite/tests/instr-cov/mixed_manual_dump/main_c.c rename to testsuite/tests/instr-cov/manual-dump/mixed/main_c.c diff --git a/testsuite/tests/instr-cov/mixed_manual_dump/test.opt b/testsuite/tests/instr-cov/manual-dump/mixed/test.opt similarity index 62% rename from testsuite/tests/instr-cov/mixed_manual_dump/test.opt rename to testsuite/tests/instr-cov/manual-dump/mixed/test.opt index 656b7e211..c4fdf2d52 100644 --- a/testsuite/tests/instr-cov/mixed_manual_dump/test.opt +++ b/testsuite/tests/instr-cov/manual-dump/mixed/test.opt @@ -1,3 +1,2 @@ -bin-traces DEAD test feature specific to source traces RTS_ZFP DEAD test uses stdio !native XFAIL Build failure with mixed language mains. See #212 diff --git a/testsuite/tests/instr-cov/mixed_manual_dump/test.py b/testsuite/tests/instr-cov/manual-dump/mixed/test.py similarity index 100% rename from testsuite/tests/instr-cov/mixed_manual_dump/test.py rename to testsuite/tests/instr-cov/manual-dump/mixed/test.py diff --git a/testsuite/tests/instr-cov/manual-dump/test.opt b/testsuite/tests/instr-cov/manual-dump/test.opt deleted file mode 100644 index 1dfb5a7b0..000000000 --- a/testsuite/tests/instr-cov/manual-dump/test.opt +++ /dev/null @@ -1,2 +0,0 @@ -bin-traces DEAD Check features specific to instrumentation. -!RTS_FULL DEAD Uses the full instrumentation runtime. From 7c910446bac7bca955e87ea60e114bc208f739a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 19 Jan 2024 13:33:38 +0100 Subject: [PATCH 0675/1483] Add trace counter in the trace filenames This allows multiple traces to be dumped in short succession without having one trace being overwritten by the next one. --- .../instr-cov/default_dump_channel/test.py | 4 +- .../instr-cov/manual-dump/ada_only/test.py | 19 +++-- .../manual-dump/trace_index/main.adb | 11 +++ .../instr-cov/manual-dump/trace_index/test.py | 79 +++++++++++++++++++ .../rts/gnatcov_rts_c-traces-output-files.c | 7 +- .../rts/gnatcov_rts_c-traces-output-files.h | 13 +-- 6 files changed, 117 insertions(+), 16 deletions(-) create mode 100644 testsuite/tests/instr-cov/manual-dump/trace_index/main.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/trace_index/test.py diff --git a/testsuite/tests/instr-cov/default_dump_channel/test.py b/testsuite/tests/instr-cov/default_dump_channel/test.py index 2d2ae01f2..999370f5a 100644 --- a/testsuite/tests/instr-cov/default_dump_channel/test.py +++ b/testsuite/tests/instr-cov/default_dump_channel/test.py @@ -38,9 +38,9 @@ class Test: default_prefix = exename_for("main") for t in [ - Test("none", f"{default_prefix}-*-*-*.srctrace"), + Test("none", f"{default_prefix}-*-*-*-0.srctrace"), Test("simple", f"{default_prefix}.srctrace", ["--dump-filename-simple"]), - Test("prefix", "bar-*-*-*.srctrace", ["--dump-filename-prefix=bar"]), + Test("prefix", "bar-*-*-*-0.srctrace", ["--dump-filename-prefix=bar"]), Test("env-var", "mytrace.srctrace", ["--dump-filename-env-var=MY_TRACE_FILE"], diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/test.py b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py index 86eae8ef3..1363faedc 100644 --- a/testsuite/tests/instr-cov/manual-dump/ada_only/test.py +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py @@ -4,14 +4,13 @@ with a call to the dump buffers procedure and output correct traces. """ -import os -import os.path +import glob -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of from SUITE.gprutils import GPRswitches -from SUITE.tutils import gprfor +from SUITE.tutils import gprfor, srctrace_pattern_for tmp = Wdir('tmp_') @@ -29,14 +28,15 @@ langs=["Ada"], ) -p = gprfor(mains=["main.adb"], +p = gprfor(prjid="gen", + mains=["main.adb"], srcdirs=["../src"], objdir="obj", deps=["lib1", "lib2"]) instr_warning = (r"warning: Manual dump trigger indications were found in.*") -build_run_and_coverage( +cov_args = build_and_run( gprsw=GPRswitches(root_project=p, units=["lib1", "main"]), covlevel='stmt', mains=['main'], @@ -59,8 +59,13 @@ def check_call(file): check_call('obj-lib2/lib2-gnatcov-instr/lib2.adb') -# Check that we get the expected coverage reports +# Generate and check coverage reports, using the last trace generated for the +# root project. +trace_file = sorted(glob.glob(srctrace_pattern_for( + "main", manual=True, manual_prj_name="gen" +)))[-1] +xcov(cov_args + [trace_file], out="coverage.log") check_xcov_reports('xcov/*.xcov', { 'xcov/main.adb.xcov': {'+': {12, 15, 19, 24, 26, 27, 28}, '-': {21, 29}}, diff --git a/testsuite/tests/instr-cov/manual-dump/trace_index/main.adb b/testsuite/tests/instr-cov/manual-dump/trace_index/main.adb new file mode 100644 index 000000000..f94b2081b --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/trace_index/main.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put ("Hello"); + pragma Annotate (Xcov, Dump_Buffers); + Put (" Ada"); + pragma Annotate (Xcov, Dump_Buffers); + Put_Line (" world!"); + pragma Annotate (Xcov, Dump_Buffers); +end Main; diff --git a/testsuite/tests/instr-cov/manual-dump/trace_index/test.py b/testsuite/tests/instr-cov/manual-dump/trace_index/test.py new file mode 100644 index 000000000..6edc0a4cc --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/trace_index/test.py @@ -0,0 +1,79 @@ +""" +Test that when multiple traces are dumped by the same executable, no trace file +gets overwritten and we get as many traces as there are dump indications in +the sources. +""" + +import glob + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, srctrace_pattern_for + +tmp=Wdir("tmp_") + +expected_cov = [ + {'+': {5}, '-': {7, 9}}, + {'+': {5,7}, '-': {9}}, + {'+': {5,7,9}}, +] + +def check_trace (cov_args, traces, index): + """ + Create a coverage report from cov_args and traces[index], in the + report_{index} directory, and check the report against expected_cov, + for the corresponding index. + """ + thistest.log(f"======= Checking trace {index + 1} =========") + output_dir=f"report_{index + 1}" + xcov(cov_args + [traces[index], f"--output-dir={output_dir}"], out=f"xcov_{index}") + check_xcov_reports( + "*.xcov", + {"main.adb.xcov": expected_cov[index]}, + cwd=output_dir + ) + + +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid="p", + srcdirs=[".."], + mains=["main.adb"], + ) + ), + covlevel="stmt", + mains=["main"], + dump_trigger="manual", + manual_prj_name="p", + extra_coverage_args=["-axcov"], +) + +# We are expecting three traces, if at this point cov_args has a length of +# less than 4, there's definitively something wrong. +thistest.fail_if( + len(cov_args) < 4, + comment=f"expected at least three traces: {cov_args}" +) + +traces = glob.glob(srctrace_pattern_for("main", manual=True, manual_prj_name="p")) +traces.sort() + +thistest.fail_if( + len(traces) != 3, + comment=f"Expected three traces, got {len(traces)}" +) + +# Check that the traces do indeed contain an index in their filename +thistest.fail_if( + any([not traces[i].endswith(f"-{i}.srctrace") for i in range(3)]), + comment=f"missing trace index in trace filenames: {traces}" +) + +# Check for each trace the coverage results +for i in range(3): + check_trace(cov_args, traces, i) + +thistest.result() diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c index badb889ad..929300037 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c @@ -29,6 +29,8 @@ #include "gnatcov_rts_c-traces-output-files.h" #include "gnatcov_rts_c-traces-output.h" +uint32_t gnatcov_rts_trace_dump_counter = 0; + static int write_bytes (void *output, const void *bytes, unsigned count) { @@ -97,15 +99,18 @@ char * gnatcov_rts_default_trace_basename (const char *prefix, const char *tag, unsigned simple) { + char *extension = ".srctrace"; if (simple) return concat (prefix, extension, NULL); + char *trace_nb = hex_str (gnatcov_rts_trace_dump_counter++); char *pid = hex_str (gnatcov_rts_getpid ()); char *time = hex_str (gnatcov_rts_time_to_uint64 ()); - char *suffix = concat ("-", pid, "-", time, extension, NULL); + char *suffix = concat ("-", pid, "-", time, "-", trace_nb, extension, NULL); free (pid); free (time); + free (trace_nb); char *res; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h index 6baffe4cd..01ca267b7 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h @@ -38,9 +38,10 @@ extern "C" * "PREFIX.srctrace" if SIMPLE is True. - * "PREFIX-TAG-PID-CLOCK.srctrace" if SIMPLE is False (PID is the current - process ID and CLOCK is the execution timestamp). The "-TAG" part is - omitted if TAG is the empty string. + * "PREFIX-TAG-PID-CLOCK-COUNT.srctrace" if SIMPLE is False (PID is the + current process ID, CLOCK is the execution timestamp, COUNT is the + number of previously dumped traces by the program). The "-TAG" part + is omitted if TAG is the empty string. If the ENV_VAR environment variable is defined and not empty, then: @@ -50,9 +51,9 @@ extern "C" * otherwise, just return the content of that environment variable. */ extern char *gnatcov_rts_default_trace_filename (const char *env_var, - const char *prefix, - const char *tag, - unsigned simple); + const char *prefix, + const char *tag, + unsigned simple); /* Write a trace file in FILENAME to contain the data in BUFFERS_GROUPS. From ac2caa4471c7a993c6810d0e845e742fdfcb1588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 23 Jan 2024 10:03:21 +0100 Subject: [PATCH 0676/1483] Add mechanism to specify trace filename prefix in code for manual dump trigger This takes the form of either a third argument to the pragma in Ada sources: `pragma Annotate (Xcov, Dump_Buffers, Prefix);` or as an "argument" in C comment markers: `/* GNATCOV_DUMP_BUFFERS (prefix) */` There is no validation of the type of the expression specified in either case, it is up to the user to ensure that in Ada soruces, Prefix evaluates to a String, and in C that prefix evaluates to a null-terminated char *. --- .../instr-cov/manual-dump/ada_only/test.py | 2 +- .../instr-cov/manual-dump/c_only/test.py | 2 +- .../manual-dump/prefix_in_code/main_ada.adb | 8 ++ .../manual-dump/prefix_in_code/main_c.c | 10 +++ .../manual-dump/prefix_in_code/test.opt | 1 + .../manual-dump/prefix_in_code/test.py | 87 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 40 ++++++--- tools/gnatcov/instrument-c.adb | 26 ++++-- 8 files changed, 157 insertions(+), 19 deletions(-) create mode 100644 testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_ada.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_c.c create mode 100644 testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.opt create mode 100644 testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/test.py b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py index 1363faedc..3066ed3dc 100644 --- a/testsuite/tests/instr-cov/manual-dump/ada_only/test.py +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py @@ -52,7 +52,7 @@ def check_call(file): thistest.fail_if_no_match("missing dump buffers procedure call", - "(\n|.)*GCVRT.DB_manual_lib2.Dump_Buffers;" + "(\n|.)*GCVRT.DB_manual_lib2.Dump_Buffers(.*);" "(\n|.)*", contents_of(file)) diff --git a/testsuite/tests/instr-cov/manual-dump/c_only/test.py b/testsuite/tests/instr-cov/manual-dump/c_only/test.py index 7fdbee9eb..03629bbc2 100644 --- a/testsuite/tests/instr-cov/manual-dump/c_only/test.py +++ b/testsuite/tests/instr-cov/manual-dump/c_only/test.py @@ -53,7 +53,7 @@ lib_file = 'obj/lib-gnatcov-instr/foo.c' thistest.fail_if_no_match ("missing Dump_Buffers call", - "(\n|.)*gnatcov_rts_manual_dump_buffers_lib ();(\n|.)*", + r"(\n|.)*gnatcov_rts_manual_dump_buffers_lib \(.*\);(\n|.)*", contents_of(lib_file)) # Check that we got the expected coverage report diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_ada.adb b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_ada.adb new file mode 100644 index 000000000..fbcbd73a7 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_ada.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_Ada is + Trace_Prefix : constant String := "ada_trace"; +begin + Put_Line ("Hello Ada world!"); + pragma Annotate (XCov, Dump_Buffers, Trace_Prefix); +end Main_Ada; diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_c.c b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_c.c new file mode 100644 index 000000000..103b17e80 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_c.c @@ -0,0 +1,10 @@ +#include + +int +main (void) +{ + char *trace_prefix = "c_trace"; + printf ("Hello C world!\n"); + /* GNATCOV_DUMP_BUFFERS (trace_prefix) */ + return 0; +} \ No newline at end of file diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.opt b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.opt new file mode 100644 index 000000000..b4e2b265a --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.opt @@ -0,0 +1 @@ +!native DEAD test only makes sense for bin-file dump channel diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py new file mode 100644 index 000000000..18cd5feef --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py @@ -0,0 +1,87 @@ +""" +Test that the prefix for the trace can be configured from sources, using +either + + pragma Annotate (Xcov, Dump_Buffers, Prefix); + +or + + /* GNATCOV_DUMP_BUFFERS (prefix) */ + +where prefix designates any expression evaluating to an Ada String or a C +null-terminated char *. +""" + +import glob + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp=Wdir("tmp_") + +expected_cov = { + "ada" : { + "main_ada.adb.xcov": {'+': {4, 6}}, + "main_c.c.xcov": {'-': {6, 7, 9}} + }, + "c" : { + "main_c.c.xcov": {'+': {6, 7}, '-': {9}}, + "main_ada.adb.xcov": {'-': {4, 6}} + } +} + +def check_one_trace(cov_args, lang): + """ + Find the trace generated by the lang executable, assuming the trace prefix + is {lang}_trace. Then create a coverage report from that trace and check we + got the expected results. + """ + + thistest.log(f"======== Checking {lang} trace =========") + + # We expect the trace to be in the format + # {lang}_trace-{unique-part}.srctrace: + trace = glob.glob(f"{lang}_trace-*.srctrace") + + # There is only one dump indication in each main, ensure we found a trace + # and have no spurious traces in the working directory. + thistest.fail_if( + len (trace) != 1, + comment=f"expected a single trace, found {len(trace)}" + ) + + print(trace) + + output_dir = f"output_{lang}/" + xcov( + cov_args + [f"--output-dir={output_dir}"] + trace, + out=f"coverage_{lang}.log" + ) + check_xcov_reports("*.xcov", expected_cov[lang], cwd=output_dir) + +prj_id = "p" + +# Instrument build and run +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid=prj_id, + srcdirs=[".."], + mains=["main_ada.adb", "main_c.c"], + ) + ), + covlevel="stmt", + mains=["main_ada", "main_c"], + dump_trigger="manual", + manual_prj_name=prj_id, + extra_coverage_args=["-axcov"], +) + +# Check the trace name and report for each executable +for lang in ["c", "ada"]: + check_one_trace(cov_args, lang) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 14be85143..ace98cbe2 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -7968,7 +7968,7 @@ package body Instrument.Ada_Unit is Prag_Args : constant Base_Assoc_List := Prag_N.F_Args; begin if Pragma_Name (Prag_N) = Name_Annotate - and then Prag_Args.Children_Count = 2 + and then Prag_Args.Children_Count in 2 .. 3 and then Is_Expected_Argument (Prag_Args, 1, Xcov) and then Is_Expected_Argument (Prag_Args, 2, Dump_Buffers) then @@ -7989,6 +7989,14 @@ package body Instrument.Ada_Unit is To_Nodes (RH, To_Qualified_Name (To_String (Dump_Procedure_Name))); + Dump_Args : constant Node_Rewriting_Handle := + (if Prag_Args.Children_Count = 3 + then Detach (Prag_Args.Child (3)) + else Create_Token_Node + (RH, + Kind => Ada_String_Literal, + Text => To_Text + ("""" & (+Prj.Prj_Name) & """"))); begin -- Add the with clause only once in the file @@ -8008,8 +8016,10 @@ package body Instrument.Ada_Unit is (Handle (N), Create_From_Template (RH, - "{}.{};", - Arguments => (1 => With_Unit, 2 => Dump_Call), + "{}.{} ({});", + Arguments => (1 => With_Unit, + 2 => Dump_Call, + 3 => Dump_Args), Rule => Call_Stmt_Rule)); end; @@ -8866,9 +8876,15 @@ package body Instrument.Ada_Unit is File.Put_Line (" pragma No_Tagged_Streams;"); File.New_Line; - - File.Put_Line (" procedure " & Dump_Procedure & ";"); - File.Put_Line (" pragma Convention (C, " & Dump_Procedure & ");"); + File.Put_Line (" procedure " & Dump_Procedure + & (if Dump_Trigger = Manual + then " (Prefix : String)" + else "") + & ";"); + if Dump_Trigger /= Manual then + File.Put_Line + (" pragma Convention (C, " & Dump_Procedure & ");"); + end if; File.New_Line; case Dump_Trigger is @@ -8934,7 +8950,11 @@ package body Instrument.Ada_Unit is -- Emit the procedure to write the trace file - File.Put_Line (" procedure " & Dump_Procedure & " is"); + File.Put_Line (" procedure " & Dump_Procedure + & (if Dump_Trigger = Manual + then " (Prefix : String)" + else "") + & " is"); case Dump_Config.Channel is when Binary_File => @@ -8945,9 +8965,9 @@ package body Instrument.Ada_Unit is else """" & (+Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := - """" & (if Dump_Config.Trigger = Manual - then +Prj.Prj_Name - else +Dump_Config.Filename_Prefix) & """"; + (if Dump_Config.Trigger = Manual + then "Prefix" + else """" & (+Dump_Config.Filename_Prefix) & """"); Tag : constant String := """" & (+Instrumenter.Tag) & """"; Simple : constant String := diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index f4b3e4d68..88efc3822 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3762,7 +3762,11 @@ package body Instrument.C is File.New_Line; File.Put (Instrumenter.Extern_Prefix); - File.Put_Line ("void " & Dump_Procedure & " (void) {"); + File.Put_Line ("void " & Dump_Procedure & " (" + & (if Dump_Config.Trigger = Manual + then "char *prefix" + else "void") + & ") {"); File.Put_Line (Indent1 & Output_Proc & " ("); File.Put_Line @@ -3777,7 +3781,7 @@ package body Instrument.C is else """" & (+Dump_Config.Filename_Env_Var) & """"); Prefix : constant String := (if Dump_Config.Trigger = Manual - then """" & (+Prj.Prj_Name) & """" + then "prefix" else """" & (+Dump_Config.Filename_Prefix) & """"); Tag : constant String := """" & (+Instrumenter.Tag) & """"; Simple : constant String := @@ -3871,9 +3875,9 @@ package body Instrument.C is Dummy_Main : Compilation_Unit_Part; Dump_Pat : constant Pattern_Matcher := Compile - ("^[\t ]*\/\* GNATCOV_DUMP_BUFFERS \*\/[ \t]*", + ("^[\t ]*\/\* GNATCOV_DUMP_BUFFERS (\((.*)\))? \*\/[ \t]*", Flags => Multiple_Lines); - Matches : Match_Array (0 .. 1); + Matches : Match_Array (0 .. 2); Dump_Procedure : constant String := Dump_Procedure_Symbol (Main => Dummy_Main, Manual => True, Prj_Name => +Prj.Prj_Name); @@ -3950,13 +3954,21 @@ package body Instrument.C is -- Put an external decl for the buffers dump function String'Write - (S, "extern void " & Dump_Procedure & "(void);"); + (S, "extern void " & Dump_Procedure & "(char *prefix);"); end if; String'Write (S, Str (Index .. Matches (0).First)); - -- Replace the match with the call to the dump procedure + -- Replace the match with the call to the dump procedure. + -- Use the project name as prefix if none is given by the user. - String'Write (S, Dump_Procedure & "();"); + if Matches (2) = No_Match then + String'Write + (S, Dump_Procedure & "(" & (+Prj.Prj_Name) & ");"); + else + String'Write + (S, Dump_Procedure & "(" + & Str (Matches (2).First .. Matches (2).Last) & ");"); + end if; Index := Matches (0).Last + 1; end loop; From b6030ae386633ac17dfb36e200ec1ef24f7e0938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 23 Jan 2024 16:22:56 +0100 Subject: [PATCH 0677/1483] Add buffer reset mechanism for source traces This is based on the same mechanism than the one for the manual dump trigger. Users can add `pragma Annotate (Xcov, Reset_Buffers);` or `/* GNATCOV_RESET_BUFFERS */` depending on the language of the source to clear all the coverage buffers for all the units in the project tree rooted at the project in which the unit with the reset indication belongs. --- .../gen/arm-elf-linux/gcvrt-db_z794ac68b.adb | 1 + .../gen/arm-elf-linux/gcvrt-db_z794ac68c.adb | 1 + .../gen/arm-elf-linux/gcvrt-pz3791e32c.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68b.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68c.ads | 2 +- .../gen/arm-elf-linux/main_1.adb | 2 +- .../gen/arm-elf-linux/main_2.adb | 2 +- .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1850 -> 1850 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1860 -> 1860 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 1998 -> 1998 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 1929 -> 1929 bytes .../gen/x86_64-windows/gcvrt-db_z794ac68b.adb | 1 + .../gen/x86_64-windows/gcvrt-db_z794ac68c.adb | 1 + .../gen/x86_64-windows/gcvrt-pz3791e32c.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68b.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68c.ads | 2 +- .../gen/x86_64-windows/main_1.adb | 2 +- .../gen/x86_64-windows/main_2.adb | 2 +- .../tests/instr-cov/buffer_reset/main_ada.adb | 15 ++ .../tests/instr-cov/buffer_reset/main_c.c | 17 ++ .../tests/instr-cov/buffer_reset/pkg.adb | 8 + .../tests/instr-cov/buffer_reset/pkg.ads | 5 + testsuite/tests/instr-cov/buffer_reset/pkh.c | 7 + .../tests/instr-cov/buffer_reset/test.opt | 2 + .../tests/instr-cov/buffer_reset/test.py | 155 ++++++++++++++++++ .../instr-cov/manual-dump/ada_only/test.py | 3 +- .../instr-cov/manual-dump/ada_subprj/test.py | 3 +- .../instr-cov/manual-dump/c_only/test.py | 3 +- tools/gnatcov/instrument-ada_unit.adb | 136 ++++++++++----- tools/gnatcov/instrument-ada_unit.ads | 19 ++- tools/gnatcov/instrument-c.adb | 147 +++++++++++++---- tools/gnatcov/instrument-c.ads | 23 ++- tools/gnatcov/instrument-common.adb | 29 ++-- tools/gnatcov/instrument-common.ads | 40 +++-- tools/gnatcov/instrument-projects.adb | 40 +++-- .../gnatcov/rts/gnatcov_rts-buffers-lists.adb | 39 +++++ .../gnatcov/rts/gnatcov_rts-buffers-lists.ads | 5 + tools/gnatcov/rts/gnatcov_rts.ads | 3 +- tools/gnatcov/rts/gnatcov_rts_c-buffers.c | 39 +++++ tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 26 ++- tools/gnatcov/rts/gnatcov_rts_c-memory.h | 44 +++++ .../rts/gnatcov_rts_c-traces-output-base64.c | 1 + .../rts/gnatcov_rts_c-traces-output-files.c | 1 + .../gnatcov/rts/gnatcov_rts_c-traces-output.c | 1 + .../gnatcov/rts/gnatcov_rts_c-traces-output.h | 15 +- 45 files changed, 691 insertions(+), 159 deletions(-) create mode 100644 testsuite/tests/instr-cov/buffer_reset/main_ada.adb create mode 100644 testsuite/tests/instr-cov/buffer_reset/main_c.c create mode 100644 testsuite/tests/instr-cov/buffer_reset/pkg.adb create mode 100644 testsuite/tests/instr-cov/buffer_reset/pkg.ads create mode 100644 testsuite/tests/instr-cov/buffer_reset/pkh.c create mode 100644 testsuite/tests/instr-cov/buffer_reset/test.opt create mode 100644 testsuite/tests/instr-cov/buffer_reset/test.py create mode 100644 tools/gnatcov/rts/gnatcov_rts-buffers-lists.adb create mode 100644 tools/gnatcov/rts/gnatcov_rts_c-memory.h diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb index f287bda84..3309397db 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb @@ -1,5 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; +with GNATcov_RTS.Buffers.Lists; with Interfaces.C; with GCVRT.Foo; package body GCVRT.DB_z794ac68b is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb index b8d2caccb..7c77385e8 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb @@ -1,5 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; +with GNATcov_RTS.Buffers.Lists; with Interfaces.C; with GCVRT.Foo; package body GCVRT.DB_z794ac68c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads index a2cc75bbf..cdbd12f7e 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 6, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz3791e32c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads index be559ee3a..df7debe5c 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 6, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68b is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads index 9cc58c48f..5b40ecefc 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 5, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 6, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb index 104973569..0e4e6535b 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=6,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); GCVRT.DB_z794ac68b.Dump_Buffers;end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb index ffe66dacd..558a2217e 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=5,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=6,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); GCVRT.DB_z794ac68c.Dump_Buffers;end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt index 1198c5f7560424b81c54840780ca9522d021a780..bf3f525476f6b2323d9296bda1ca96d471f9ceb1 100644 GIT binary patch delta 54 zcmdnRw~KFs6&w4DM5pGTvu{jxWV^0pWUOFlZe?g}Wn!YBZD43+V8F-#0WcZ>-ZczL delta 54 zcmdnRw~KFs6&w48S^HNX&AB$&k?p#Yp_ziAiItI=m7$4(wt=CQfdL}}1i)wj>Ie*r diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index 0959bb6d3d09ff2e312a72c162f724d1c63e5132..ed78518649f375d2ec5a6bc0d865fedd7b462763 100644 GIT binary patch delta 34 qcmX@YcZ6?)6C3*sKdEOwXWy9Y$##>=$XLP9+{)0{%4D(*y95B}#tV`F delta 34 qcmX@YcZ6?)6B~O)L%_wOIoBq8vfbn|G*d7%u`)8VGMuc#E&%}LBMV>v diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 908d23d70e97b006b3f093f50d60f9c1e2ac42bc..60924e6efbc92379bc857f35bd198bf60b44241e 100644 GIT binary patch delta 26 icmX@de~y2{4mNg!lvDFv=iZpSpG}O($Y}C)w(kIz + +extern bool and_then (bool left, bool right); + +int +main (void) +{ + and_then (true, true); + /* GNATCOV_DUMP_BUFFERS ("c-0") */ + /* GNATCOV_RESET_BUFFERS */ + and_then (true, false); + /* GNATCOV_DUMP_BUFFERS ("c-1") */ + /* GNATCOV_RESET_BUFFERS */ + and_then (false, true); + /* GNATCOV_DUMP_BUFFERS ("c-2") */ + return 0; +} diff --git a/testsuite/tests/instr-cov/buffer_reset/pkg.adb b/testsuite/tests/instr-cov/buffer_reset/pkg.adb new file mode 100644 index 000000000..de46c9e85 --- /dev/null +++ b/testsuite/tests/instr-cov/buffer_reset/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + function Or_Else (L, R : Boolean) return Boolean is + begin + return L or else R; + end Or_Else; + +end Pkg; diff --git a/testsuite/tests/instr-cov/buffer_reset/pkg.ads b/testsuite/tests/instr-cov/buffer_reset/pkg.ads new file mode 100644 index 000000000..2bedb4461 --- /dev/null +++ b/testsuite/tests/instr-cov/buffer_reset/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Or_Else (L, R : Boolean) return Boolean; + +end Pkg; diff --git a/testsuite/tests/instr-cov/buffer_reset/pkh.c b/testsuite/tests/instr-cov/buffer_reset/pkh.c new file mode 100644 index 000000000..016dfffad --- /dev/null +++ b/testsuite/tests/instr-cov/buffer_reset/pkh.c @@ -0,0 +1,7 @@ +#include + +bool +and_then (bool left, bool right) +{ + return left && right; +} diff --git a/testsuite/tests/instr-cov/buffer_reset/test.opt b/testsuite/tests/instr-cov/buffer_reset/test.opt new file mode 100644 index 000000000..83c947030 --- /dev/null +++ b/testsuite/tests/instr-cov/buffer_reset/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD Test specific to src trace feature +!native DEAD Test requires bin-file dump channel diff --git a/testsuite/tests/instr-cov/buffer_reset/test.py b/testsuite/tests/instr-cov/buffer_reset/test.py new file mode 100644 index 000000000..c94ff64cf --- /dev/null +++ b/testsuite/tests/instr-cov/buffer_reset/test.py @@ -0,0 +1,155 @@ +""" +Test basic functionality of the buffer reset mechanism, in both C and Ada +source files. +""" + +import glob +import re + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp=Wdir("tmp_") + +# Map from language to the corresponding main report name, and lines with +# coverage obligations. +main_lines = { + "ada": ("main_ada.adb.xcov", [7, 10, 13]), + "c": ("main_c.c.xcov", [8, 11, 14, 16]) +} + +# Units which will only have a partial coverage result in them, regardless of +# the trace. +default_part_cov = { + "ada": {"pkg.adb.xcov": {'!': {5}}}, + "c": {"pkh.c.xcov": {'!': {6}}}, +} + +# Default "nothing executed" expected result for each unit +default_no_cov = { + "ada": { + "main_ada.adb.xcov": {'-': {7, 10, 13}}, + "pkg.adb.xcov": {'-': {5}}, + }, + "c": { + "main_c.c.xcov": {'-': {8, 11, 14, 16}}, + "pkh.c.xcov": {'-': {6}}, + } +} + +def get_expected_cov (trace_name): + """ + Generate an expected coverage results based on the prefix of the trace + indicating which main was executed, and its index. + """ + match = re.match(pattern=r"(.*)-(\d)\.srctrace", string=trace_name) + thistest.fail_if( + not match, + comment="trace name not in expected format: " + trace_name + ) + trace_lang = match.group(1) + idx = int(match.group(2)) + expected_cov = {} + + lines = main_lines[trace_lang][1] + for lang in ("ada", "c"): + if lang == trace_lang: + expected_cov.update({ + main_lines[lang][0]: { + '+': {lines[idx]}, + '-': {lines[i] for i in range(len(lines)) if i != idx} + } + }) + expected_cov.update(default_part_cov[lang]) + else: + expected_cov.update (default_no_cov[lang]) + return expected_cov + + + + +def check_one_exec(cov_args, lang): + """ + Find the traces generated by the lang executable, assuming the trace prefix + is lang. Then create a coverage report from each trace, checking the + expected coverage report. + """ + + thistest.log(f"======== Checking {lang} traces =========") + + # We expect the trace to be in the format + # {lang}-{index}.srctrace: + traces = glob.glob(f"{lang}-[0-9].srctrace") + + # There is three dump indications in each main, we should thus have the + # same number of traces. + thistest.fail_if( + len (traces) != 3, + comment=f"expected 3 traces, found {len(traces)}" + ) + traces.sort() + + for i in range(len(traces)): + thistest.log(f"-- {i+1}. --") + output_dir = f"output_{lang}_{i}/" + xcov( + cov_args + [f"--output-dir={output_dir}", traces[i]], + out=f"coverage_{lang}_{i}.log" + ) + check_xcov_reports( + "*.xcov", + get_expected_cov(traces[i]), + cwd=output_dir + ) + +prj_id = "p" + +# Instrument build and run +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid=prj_id, + srcdirs=[".."], + mains=["main_ada.adb", "main_c.c"], + ) + ), + covlevel="stmt+mcdc", + mains=["main_ada", "main_c"], + dump_trigger="manual", + manual_prj_name=prj_id, + extra_coverage_args=["-axcov+"], + extra_instr_args=["--dump-filename-simple"] +) + +# Check the individual trace contents for each executable +for lang in ["c", "ada"]: + check_one_exec(cov_args, lang) + +# Do a consolidated check with all the traces. We expect exactly six traces and +# no coverage violations except for the final return statement in the c main. +thistest.log ("========== global consolidated check =========") +all_traces = glob.glob("*.srctrace") +thistest.fail_if( + len(all_traces) != 6, + comment=f"expected 6 traces, got {len(all_traces)}" +) +output_dir = "consolidated/" +xcov( + cov_args + [f"--output-dir={output_dir}"] + all_traces, + out="consolidated.log" +) +check_xcov_reports( + "*.xcov", + { + "main_ada.adb.xcov": {'+': {7, 10, 13}}, + "pkg.adb.xcov": {'+': {5}}, + "main_c.c.xcov": {'+': {8, 11, 14}, '-': {16}}, + "pkh.c.xcov": {'+': {6}} + }, + cwd=output_dir +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/test.py b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py index 3066ed3dc..99c8202a1 100644 --- a/testsuite/tests/instr-cov/manual-dump/ada_only/test.py +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py @@ -34,7 +34,8 @@ objdir="obj", deps=["lib1", "lib2"]) -instr_warning = (r"warning: Manual dump trigger indications were found in.*") +instr_warning = (r"warning: Manual buffer dump/reset indications were found" + r" in.*") cov_args = build_and_run( gprsw=GPRswitches(root_project=p, units=["lib1", "main"]), diff --git a/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py index b400e7a85..859e4a99f 100644 --- a/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py +++ b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py @@ -37,7 +37,8 @@ def make_lib_gpr(name, srcdirs, deps): # Running gnatcov natively allows to have one source trace file per # project. -instr_warning = (r"warning: Manual dump trigger indications were found in.*") +instr_warning = (r"warning: Manual buffer dump/reset indications were" + r" found in.*") build_run_and_coverage( gprsw=GPRswitches(root_project=p, units=["lib1", "lib2"]), diff --git a/testsuite/tests/instr-cov/manual-dump/c_only/test.py b/testsuite/tests/instr-cov/manual-dump/c_only/test.py index 03629bbc2..09e2dc453 100644 --- a/testsuite/tests/instr-cov/manual-dump/c_only/test.py +++ b/testsuite/tests/instr-cov/manual-dump/c_only/test.py @@ -34,7 +34,8 @@ gprsw = GPRswitches(root_project=src_gpr) -instr_warning = (r"warning: Manual dump trigger indications were found in.*") +instr_warning = (r"warning: Manual buffer dump/reset indications were found" + r" in.*") build_run_and_coverage(gprsw=gprsw, covlevel="stmt", mains=["main"], extra_coverage_args=["-axcov"], dump_trigger="manual", diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index ace98cbe2..2d52d09d4 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -208,7 +208,8 @@ package body Instrument.Ada_Unit is -- Annotations Xcov, - Dump_Buffers); + Dump_Buffers, + Reset_Buffers); Symbols : constant Symbol_Table := Create_Symbol_Table; -- Holder for name singletons @@ -240,7 +241,8 @@ package body Instrument.Ada_Unit is Ravenscar => Precompute_Symbol (Ravenscar), Restricted => Precompute_Symbol (Restricted), Xcov => Precompute_Symbol (Xcov), - Dump_Buffers => Precompute_Symbol (Dump_Buffers)); + Dump_Buffers => Precompute_Symbol (Dump_Buffers), + Reset_Buffers => Precompute_Symbol (Reset_Buffers)); function As_Symbol (S : All_Symbols) return Symbol_Type is (Precomputed_Symbols (S)); @@ -7916,15 +7918,16 @@ package body Instrument.Ada_Unit is Rewriter.Apply; end Auto_Dump_Buffers_In_Main; - ------------------------------------ - -- Replace_Manual_Dump_Indication -- - ------------------------------------ + -------------------------------- + -- Replace_Manual_Indications -- + -------------------------------- - overriding procedure Replace_Manual_Dump_Indication - (Self : in out Ada_Instrumenter_Type; - Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info; - Has_Manual_Indication : out Boolean) + overriding procedure Replace_Manual_Indications + (Self : in out Ada_Instrumenter_Type; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info; + Has_Dump_Indication : out Boolean; + Has_Reset_Indication : out Boolean) is Instrumented_Filename : constant String := +(Prj.Output_Dir & "/" & GNATCOLL.VFS."+" (Source.File.Base_Name)); @@ -7970,26 +7973,29 @@ package body Instrument.Ada_Unit is if Pragma_Name (Prag_N) = Name_Annotate and then Prag_Args.Children_Count in 2 .. 3 and then Is_Expected_Argument (Prag_Args, 1, Xcov) - and then Is_Expected_Argument (Prag_Args, 2, Dump_Buffers) + and then + (Is_Expected_Argument (Prag_Args, 2, Dump_Buffers) + or else Is_Expected_Argument (Prag_Args, 2, Reset_Buffers)) then -- The pragma statement to be replaced by the actual call - -- to Dump_Buffers has been found. + -- to Dump_Buffers / Reset_Buffers has been found. - if not Has_Manual_Indication then + if not (Has_Dump_Indication or else Has_Reset_Indication) + then Start_Rewriting (Rewriter, Self, Prj, File_To_Search); end if; declare - RH : constant Rewriting_Handle := Rewriter.Handle; - With_Unit : constant Node_Rewriting_Handle := + RH : constant Rewriting_Handle := Rewriter.Handle; + With_Unit : constant Node_Rewriting_Handle := To_Nodes (RH, Create_Manual_Helper_Unit_Name (Prj)); - Dump_Call : constant Node_Rewriting_Handle := + Dump_Call : constant Node_Rewriting_Handle := To_Nodes (RH, To_Qualified_Name (To_String (Dump_Procedure_Name))); - Dump_Args : constant Node_Rewriting_Handle := + Dump_Args : constant Node_Rewriting_Handle := (if Prag_Args.Children_Count = 3 then Detach (Prag_Args.Child (3)) else Create_Token_Node @@ -7997,10 +8003,16 @@ package body Instrument.Ada_Unit is Kind => Ada_String_Literal, Text => To_Text ("""" & (+Prj.Prj_Name) & """"))); + Reset_Call : constant Node_Rewriting_Handle := + To_Nodes + (RH, + To_Qualified_Name + (To_String (Reset_Procedure_Name))); begin -- Add the with clause only once in the file - if not Has_Manual_Indication then + if not (Has_Dump_Indication or else Has_Reset_Indication) + then Insert_Last (Handle (Unit.Root.As_Compilation_Unit.F_Prelude), Create_From_Template @@ -8010,20 +8022,46 @@ package body Instrument.Ada_Unit is Rule => With_Clause_Rule)); end if; - -- Insert the call to the dump procedure + if Is_Expected_Argument (Prag_Args, 2, Dump_Buffers) then - Replace - (Handle (N), - Create_From_Template - (RH, - "{}.{} ({});", - Arguments => (1 => With_Unit, - 2 => Dump_Call, - 3 => Dump_Args), - Rule => Call_Stmt_Rule)); - end; + -- Insert the call to the dump procedure + + if Switches.Misc_Trace.Is_Active then + Switches.Misc_Trace.Trace + ("Found buffer dump indication at " + & Image (N.Full_Sloc_Image)); + end if; + + Replace + (Handle (N), + Create_From_Template + (RH, + "{}.{} ({});", + Arguments => (1 => With_Unit, + 2 => Dump_Call, + 3 => Dump_Args), + Rule => Call_Stmt_Rule)); + Has_Dump_Indication := True; + else + + -- Insert the call to the reset procedure - Has_Manual_Indication := True; + if Switches.Misc_Trace.Is_Active then + Switches.Misc_Trace.Trace + ("Found buffer reset indication at " + & Image (N.Full_Sloc_Image)); + end if; + + Replace + (Handle (N), + Create_From_Template + (RH, + "{}.{};", + Arguments => (1 => With_Unit, 2 => Reset_Call), + Rule => Call_Stmt_Rule)); + Has_Reset_Indication := True; + end if; + end; return Over; end if; end; @@ -8045,18 +8083,19 @@ package body Instrument.Ada_Unit is -- initialized which will lead to finalization issues. To avoid this, -- make sure it is set to No_Rewriting_Handle. - Has_Manual_Indication := False; + Has_Dump_Indication := False; + Has_Reset_Indication := False; Rewriter.Handle := No_Rewriting_Handle; Unit.Root.Traverse (Find_And_Replace_Pragma'Access); - if Has_Manual_Indication then + if Has_Dump_Indication or else Has_Reset_Indication then Create_Directory_If_Not_Exists (GNATCOLL.VFS."+" (Source.Project.Object_Dir.Base_Dir_Name)); Create_Directory_If_Not_Exists (+Prj.Output_Dir); Rewriter.Apply; end if; - end Replace_Manual_Dump_Indication; + end Replace_Manual_Indications; ---------------------------- -- Instrument_Source_File -- @@ -8838,8 +8877,10 @@ package body Instrument.Ada_Unit is Helper_Unit_Name : constant String := To_Ada (Helper_Unit); Dump_Procedure : constant String := To_String (Dump_Procedure_Name); Output_Unit_Str : constant String := To_Ada (Output_Unit); - Project_Name_Str : constant String := """" & (+Prj.Prj_Name) & """"; + Reset_Procedure : constant String := + To_String (Reset_Procedure_Name); + Sys_Lists : Ada_Qualified_Name := Sys_Buffers; -- Indentation levels relative to the body of library-level -- subprograms. @@ -8848,9 +8889,13 @@ package body Instrument.Ada_Unit is Indent2 : constant String := Indent1 & " "; Indent3 : constant String := Indent2 & " "; begin + Sys_Lists.Append (To_Unbounded_String ("Lists")); + -- Emit the package spec. This includes one Dump_Buffers procedure, -- which dumps all coverage buffers in Main's closure to the source - -- trace file. + -- trace file, and in the case of manual dump trigger, a + -- Reset_Buffers procedure which will resets all coverage buffers in + -- the project tree rooted at the project to which Main belongs. Create_File (Prj, @@ -8904,8 +8949,9 @@ package body Instrument.Ada_Unit is & " out Dump_Controlled_Type);"); File.New_Line; end if; - when others => - null; + when Manual => + File.Put_Line (" procedure " & Reset_Procedure & ";"); + File.New_Line; end case; File.Put_Line ("end " & Helper_Unit_Name & ";"); @@ -8925,6 +8971,7 @@ package body Instrument.Ada_Unit is Put_Warnings_And_Style_Checks_Pragmas (File); Put_With (Output_Unit); + Put_With (Sys_Lists); File.Put_Line ("with Interfaces.C;"); case Dump_Trigger is @@ -9102,8 +9149,19 @@ package body Instrument.Ada_Unit is File.New_Line; end if; - when others => - null; + when Manual => + + -- Emit Buffer reset procedure + + File.Put_Line (" procedure " & Reset_Procedure & " is"); + File.Put_Line (" begin"); + File.Put_Line (" " & To_Ada (Sys_Lists) + & ".Reset_Group_Array_Buffers"); + File.Put_Line (" (" + & To_Ada (Buffers_List_Unit (+Prj.Prj_Name)) + & ".C_List);"); + File.Put_Line ("end " & Reset_Procedure & ";"); + File.New_Line; end case; File.Put_Line ("end " & Helper_Unit_Name & ";"); diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 36c0ff6be..93964305e 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -92,11 +92,12 @@ package Instrument.Ada_Unit is (Self : Ada_Instrumenter_Type; Prj : Prj_Desc) return Files_Table.Compilation_Unit; - overriding procedure Replace_Manual_Dump_Indication - (Self : in out Ada_Instrumenter_Type; - Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info; - Has_Manual_Indication : out Boolean); + overriding procedure Replace_Manual_Indications + (Self : in out Ada_Instrumenter_Type; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info; + Has_Dump_Indication : out Boolean; + Has_Reset_Indication : out Boolean); -- Once the instrumentation has finished, if the dump trigger is "manual" -- we expect the user to have indicated the place where a call to the -- manual dump buffers procedure should be inserted by the pragma @@ -106,6 +107,14 @@ package Instrument.Ada_Unit is -- -- This pragma must be found and replaced by the actual call to the dump -- procedure defined in the dump helper unit. + -- + -- Likewise, if the user wishes to reset the coverage buffers during the + -- execution, it should be done through a pragma statement: + -- + -- pragma Annotate (Xcov, Reset_Buffers); + -- + -- If found, this pragma will be replaced by a call to the buffer reset + -- procedure defined in the dump helper unit. overriding procedure Emit_Buffers_List_Unit (Self : Ada_Instrumenter_Type; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 88efc3822..6b87bc70d 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2213,7 +2213,8 @@ package body Instrument.C is -- dump buffers procedure, do nothing. It should not be -- considered for coverage analysis. - if not Is_Manual_Dump_Procedure_Symbol (Get_Callee_Name_Str (N)) + if not Is_Manual_Indication_Procedure_Symbol + (Get_Callee_Name_Str (N)) then Instrument_Statement (N, ' '); if Has_Decision (N) then @@ -3728,16 +3729,19 @@ package body Instrument.C is -- Compute the qualified names we need for instrumentation declare - Filename : constant String := +Helper_Unit; - Dump_Procedure : constant String := + Filename : constant String := +Helper_Unit; + Dump_Procedure : constant String := Dump_Procedure_Symbol (Main, Dump_Config.Trigger = Manual, Prj_Name => +Prj.Prj_Name); + Reset_Procedure : constant String := + Reset_Procedure_Symbol (+Prj.Prj_Name); begin -- Emit the package body Create_File (Prj, File, Filename); File.Put_Line ("#include ""gnatcov_rts_c-strings.h"""); + File.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); case Dump_Config.Channel is when Binary_File => @@ -3826,6 +3830,16 @@ package body Instrument.C is File.Put_Line ("}"); + -- Emit the procedure to clear the buffer groups + + File.New_Line; + File.Put (Instrumenter.Extern_Prefix); + File.Put_Line ("void " & Reset_Procedure & "(void) {"); + File.Put_Line (Indent1 & "gnatcov_rts_reset_group_array ("); + File.Put_Line + (Indent2 & "&" & Unit_Buffers_Array_Name (+Prj.Prj_Name) & ");"); + File.Put_Line ("}"); + File.Close; end; end Emit_Dump_Helper_Unit; @@ -3855,32 +3869,41 @@ package body Instrument.C is Prj => Prj); end Emit_Dump_Helper_Unit_Manual; - ------------------------------------ - -- Replace_Manual_Dump_Indication -- - ------------------------------------ + -------------------------------- + -- Replace_Manual_Indications -- + -------------------------------- - overriding procedure Replace_Manual_Dump_Indication - (Self : in out C_Family_Instrumenter_Type; - Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info; - Has_Manual_Indication : out Boolean) + overriding procedure Replace_Manual_Indications + (Self : in out C_Family_Instrumenter_Type; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info; + Has_Dump_Indication : out Boolean; + Has_Reset_Indication : out Boolean) is Orig_Filename : constant String := +Source.File.Full_Name; begin Check_Compiler_Driver (Prj, Self); declare - Options : Analysis_Options; - PP_Filename : Unbounded_String; - Dummy_Main : Compilation_Unit_Part; - Dump_Pat : constant Pattern_Matcher := + Options : Analysis_Options; + PP_Filename : Unbounded_String; + Dummy_Main : Compilation_Unit_Part; + Dump_Pat : constant Pattern_Matcher := Compile - ("^[\t ]*\/\* GNATCOV_DUMP_BUFFERS (\((.*)\))? \*\/[ \t]*", + ("^[\t ]*\/\* GNATCOV_DUMP_BUFFERS (\((.+)\))? ?\*\/[ \t]*", Flags => Multiple_Lines); - Matches : Match_Array (0 .. 2); - Dump_Procedure : constant String := + Reset_Pat : constant Pattern_Matcher := + Compile + ("^[\t ]*\/\* GNATCOV_RESET_BUFFERS \*\/[ \t]*", + Flags => Multiple_Lines); + Matches_Dump : Match_Array (0 .. 2); + Matches_Reset : Match_Array (0 .. 0); + Dump_Procedure : constant String := Dump_Procedure_Symbol (Main => Dummy_Main, Manual => True, Prj_Name => +Prj.Prj_Name); + Reset_Procedure : constant String := + Reset_Procedure_Symbol (+Prj.Prj_Name); + begin -- Preprocess the source, keeping the comment to look for the manual -- dump indication later. @@ -3937,45 +3960,97 @@ package body Instrument.C is -- original file. begin - Has_Manual_Indication := False; + Has_Dump_Indication := False; + Has_Reset_Indication := False; + Match (Dump_Pat, Str (Index .. Str'Last), Matches_Dump); + Match (Reset_Pat, Str (Index .. Str'Last), Matches_Reset); while Index in Str'Range loop - Match (Dump_Pat, Str (Index .. Str'Last), Matches); - exit when Matches (0) = No_Match; + -- No matches, nothing left to do + exit when Matches_Dump (0) = No_Match + and then Matches_Reset (0) = No_Match; -- Open the output file if this is the first match we find, -- then forward the source code that appear before the match -- unchanged. - if not Has_Manual_Indication then + if not (Has_Dump_Indication or else Has_Reset_Indication) then Create (Output_File, Out_File, Tmp_Filename); S := Stream (Output_File); - Has_Manual_Indication := True; - -- Put an external decl for the buffers dump function + -- Put an external decl for the buffers dump and reset + -- functions. String'Write (S, "extern void " & Dump_Procedure & "(char *prefix);"); + String'Write + (S, "extern void " & Reset_Procedure & "(void);"); end if; - String'Write (S, Str (Index .. Matches (0).First)); - -- Replace the match with the call to the dump procedure. - -- Use the project name as prefix if none is given by the user. + -- If we only have a Dump match, or it is the first of the two + -- to match, insert a dump buffer procedure call in place of + -- the match. - if Matches (2) = No_Match then - String'Write - (S, Dump_Procedure & "(" & (+Prj.Prj_Name) & ");"); + if Matches_Reset (0) = No_Match + or else Matches_Reset (0).First > Matches_Dump (0).First + then + + if Switches.Misc_Trace.Is_Active then + Switches.Misc_Trace.Trace + ("Found buffer dump indication in file " + & (+Source.File.Base_Name)); + end if; + + Has_Dump_Indication := True; + String'Write (S, Str (Index .. Matches_Dump (0).First)); + + -- If we had a prefix specified in the comment, include it + -- in the dump procedure call. + + if Matches_Dump (1) /= No_Match then + String'Write + (S, Dump_Procedure & "(" + & Str + (Matches_Dump (2).First + .. Matches_Dump (2).Last) + & ");"); + + -- Otherwise use the project name as prefix + + else + String'Write + (S, Dump_Procedure & "(""" & (+Prj.Prj_Name) & """);"); + end if; + Index := Matches_Dump (0).Last + 1; + + -- Search for the next dump indication + + Match (Dump_Pat, Str (Index .. Str'Last), Matches_Dump); else - String'Write - (S, Dump_Procedure & "(" - & Str (Matches (2).First .. Matches (2).Last) & ");"); + + -- Otherwise we only have a Reset match, or the reset + -- indication comes before the next Dump indication. + + if Switches.Misc_Trace.Is_Active then + Switches.Misc_Trace.Trace + ("Found buffer reset indication in file " + & (+Source.File.Base_Name)); + end if; + + Has_Reset_Indication := True; + String'Write (S, Str (Index .. Matches_Reset (0).First)); + String'Write (S, Reset_Procedure & "();"); + Index := Matches_Reset (0).Last + 1; + + -- Search for the next reset indication + + Match (Reset_Pat, Str (Index .. Str'Last), Matches_Reset); end if; - Index := Matches (0).Last + 1; end loop; -- If we had a manual indication, and thus wrote a modified source -- file, overwrite the original source file with it. - if Has_Manual_Indication then + if Has_Dump_Indication or else Has_Reset_Indication then declare PP_File : constant Virtual_File := Create (+(+PP_Filename)); Tmp_File : constant Virtual_File := Create (+Tmp_Filename); @@ -4007,7 +4082,7 @@ package body Instrument.C is end if; end; end; - end Replace_Manual_Dump_Indication; + end Replace_Manual_Indications; ------------------------------- -- Auto_Dump_Buffers_In_Main -- diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 9a5682a0a..962520279 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -58,20 +58,25 @@ package Instrument.C is Dump_Config : Any_Dump_Config; Prj : Prj_Desc); - overriding procedure Replace_Manual_Dump_Indication - (Self : in out C_Family_Instrumenter_Type; - Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info; - Has_Manual_Indication : out Boolean); + overriding procedure Replace_Manual_Indications + (Self : in out C_Family_Instrumenter_Type; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info; + Has_Dump_Indication : out Boolean; + Has_Reset_Indication : out Boolean); -- Preprocess Source and look through the text content of the preprocessed - -- file looking for manual dump indications. The C-like languages, the - -- expected indication is the comment alone on its line: + -- file looking for manual dump/reset indications. For C-like languages, + -- the expected indication are comments alone on their line: -- -- /* GNATCOV_DUMP_BUFFERS */ -- + -- or + -- + -- /* GNATOV_RESET_BUFFERS */ + -- -- When one is found the text of the file is modified: the line is replaced - -- by a call to the manual dump procedure and an extern declaration for the - -- procedure is put at the beginning of the file. + -- by a call to the manual dump/reset procedure and an extern declaration + -- for the procedure is put at the beginning of the file. overriding procedure Emit_Dump_Helper_Unit_Manual (Self : in out C_Family_Instrumenter_Type; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index ecd03c01f..57441e158 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -83,20 +83,25 @@ package body Instrument.Common is return Buffer_Symbol (Instrumented_Unit, "mcdc"); end MCDC_Buffer_Symbol; - ------------------------------------- - -- Is_Manual_Dump_Procedure_Symbol -- - ------------------------------------- - - function Is_Manual_Dump_Procedure_Symbol (Symbol : String) return Boolean + Dump_Pattern : constant Pattern_Matcher := + Compile (Dump_Procedure_Symbol + ((File_Based_Language, Null_Unbounded_String), Manual => True)); + Reset_Pattern : constant Pattern_Matcher := + Compile (Reset_Procedure_Symbol ("")); + -- Precomputed patterns to be used as helpers for + -- Is_Manual_Indication_Procedure_Symbol. + + ------------------------------------------- + -- Is_Manual_Indication_Procedure_Symbol -- + ------------------------------------------- + + function Is_Manual_Indication_Procedure_Symbol + (Symbol : String) return Boolean is - Dummy_Main : Compilation_Unit_Part; - Pattern : constant Pattern_Matcher := - Compile (Dump_Procedure_Symbol (Dummy_Main, Manual => True)); - Matches : Match_Array (0 .. 0); begin - Match (Pattern, Symbol, Matches); - return Matches (0) /= No_Match; - end Is_Manual_Dump_Procedure_Symbol; + return Match (Dump_Pattern, Symbol) + or else Match (Reset_Pattern, Symbol); + end Is_Manual_Indication_Procedure_Symbol; ----------------------- -- Unit_Buffers_Name -- diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 55dde5972..c1fe5684b 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -97,6 +97,13 @@ package Instrument.Common is -- Name of the procedure (in main dump helper packages) that dumps all -- coverage buffers to the source trace file. + Reset_Procedure_Name : constant Ada_Identifier := + To_Unbounded_String ("Reset_Buffers"); + -- Name of the procedure (in main dump helper packages) that resets all the + -- coverage buffers accessible from that dump helper package (i.e. the + -- whole project tree, rooted at the project to which the helper unit + -- belongs). + Register_Dump_Function_Name : constant Ada_Identifier := To_Unbounded_String ("Register_Dump_Buffers"); -- Name of the function (in main dump helper packages) that registers the @@ -119,9 +126,15 @@ package Instrument.Common is else "")); -- Return the name of the exported symbol for the Dump_Buffers function - function Is_Manual_Dump_Procedure_Symbol (Symbol : String) return Boolean; - -- For C, manual dump procedures are suffixed by the project's name. Check - -- that Symbol corresponds to the name of one such procedure. + function Reset_Procedure_Symbol (Prj_Name : String) return String is + ("gnatcov_rts_" & To_Lower (To_String (Reset_Procedure_Name)) + & "_" & Prj_Name); + -- Return the name of the exported symbol for the Reset_Buffers procedure + + function Is_Manual_Indication_Procedure_Symbol + (Symbol : String) return Boolean; + -- For C, manual dump/reset procedures are suffixed by the project's name. + -- Check that Symbol corresponds to the name of one such procedure. function Statement_Buffer_Symbol (Instrumented_Unit : Compilation_Unit_Part) return String; @@ -352,7 +365,7 @@ package Instrument.Common is (Strings.Img (Integer (Bit))); Runtime_Version_Check : constant String := - "pragma Compile_Time_Error (GNATcov_RTS.Version /= 5, " + "pragma Compile_Time_Error (GNATcov_RTS.Version /= 6, " & """Incompatible GNATcov_RTS version, please use" & " the GNATcov_RTS project provided with your" & " GNATcoverage distribution."");"; @@ -480,18 +493,23 @@ package Instrument.Common is -- simple call to a procedure dumping the coverage buffers to be made in -- the instrumented source files. - procedure Replace_Manual_Dump_Indication + procedure Replace_Manual_Indications (Self : in out Language_Instrumenter; Prj : in out Prj_Desc; Source : GNATCOLL.Projects.File_Info; - Has_Manual_Indication : out Boolean) is null; - -- Look for the pragma (for Ada) or comment (for C family languages) - -- indicating where the user wishes to the buffers to be dumped in Source. - -- When found, replace it with a call to the buffers dump procedure defined - -- in the dump helper unit. + Has_Dump_Indication : out Boolean; + Has_Reset_Indication : out Boolean) is null; + -- Look for the pragmas (for Ada) or comments (for C family languages) + -- indicating where the user wishes to the buffers to be dumped and/or + -- reset in Source. + -- When found, replace it with a call to the buffers dump/reset procedure + -- defined in the dump helper unit. -- - -- Has_Manual_Indication indicates whether a manual dump indication was + -- Has_Dump_Indication indicates whether a manual dump indication was -- found - and replaced with a call to dump buffers - in the given source. + -- + -- Likewise, Has_Reset_Indication indicates whether a manual buffer reset + -- indication was found and processed. function New_File (Prj : Prj_Desc; Name : String) return String; diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 2e8c28847..e1a5a36c0 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -255,7 +255,7 @@ is Instrumenter : in out Language_Instrumenter'Class; Manual_Dump_Inserted : in out Boolean); -- For all sources in Project_Sources of language Language, call - -- Replace_Manual_Dump_Indication. If a dump procedure call was inserted + -- Replace_Manual_Indications. If a dump procedure call was inserted -- and id there is not one already, also emit a dump helper unit for the -- project the source belongs to. Set Manual_Dump_Inserted to True if at -- least one manual dump indication was found. @@ -854,23 +854,26 @@ is Prj.Prj_Name = Root_Project_Info.Project.Name; Source_Name : constant String := GNATCOLL.VFS."+" (Source.File.Full_Name); - Contained_Indication : Boolean := False; Helper_Unit_Name : constant Unbounded_String := Instrumenter.Dump_Manual_Helper_Unit (Prj).Unit_Name; - + Had_Dump_Indication : Boolean := False; + Had_Reset_Indication : Boolean := False; begin - Instrumenter.Replace_Manual_Dump_Indication + Instrumenter.Replace_Manual_Indications (Prj_Info.Desc, Source, - Contained_Indication); + Had_Dump_Indication, + Had_Reset_Indication); - if Contained_Indication and then not Is_Root_Prj then + if (Had_Dump_Indication or else Had_Reset_Indication) + and then not Is_Root_Prj + then - -- A call to the dump buffers procedure is only able to dump - -- the buffers of the project it is in and its subprojects, - -- meaning coverage data for all projects higher in the - -- project tree will be missing. Record what file this call - -- was in to warn the user later. + -- A call to the dump/reset buffers procedure is only able + -- to dump/reset the buffers of the project it is in and its + -- subprojects, meaning coverage data for all projects + -- higher in the project tree will be missing or not reset. + -- Record what file this call was in to warn the user later. Non_Root_Src_Calls.Include (Source_Name); end if; @@ -933,16 +936,16 @@ is end if; Manual_Dump_Inserted := - Manual_Dump_Inserted or else Contained_Indication; + Manual_Dump_Inserted or else Had_Dump_Indication; end; end if; end loop; if not Non_Root_Src_Calls.Is_Empty then - -- For each manual dump call inserted in a file belonging to a + -- For each manual dump/reset call inserted in a file belonging to a -- non-root project, warn the user the coverage data it will produce - -- will not cover the whole project tree. + -- will not cover the whole project tree or may be inconsistent. declare All_File_Names : Unbounded_String; @@ -953,14 +956,17 @@ is end loop; Outputs.Warn - ("Manual dump trigger indications were found in subprojects in" - & " the following files:" & ASCII.LF + ("Manual buffer dump/reset indications were found in subprojects" + & " in the following files:" & ASCII.LF & (+All_File_Names) & "The coverage report built from the source traces they will" & " produce will show all code from projects higher in the" & " project tree as not covered. To get a full coverage" & " analysis, consider placing the manual dump buffers" - & " indication in the root project."); + & " indication in the root project." & ASCII.LF & ASCII.LF + & "Additionally, resetting the buffers in a subproject may" + & " result in incoherent coverage reports from traces dumped" + & " from a source in a parent project."); end; end if; end Insert_Manual_Dump_Trigger; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.adb b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.adb new file mode 100644 index 000000000..40c6998e3 --- /dev/null +++ b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.adb @@ -0,0 +1,39 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +package body GNATcov_RTS.Buffers.Lists is + + procedure Clear_Buffers_C (Arr : System.Address); + pragma Import (C, Clear_Buffers_C, "gnatcov_rts_reset_group_array"); + + procedure Reset_Group_Array_Buffers + (Arr : GNATcov_RTS_Coverage_Buffers_Group_Array) + is + begin + Clear_Buffers_C (Arr'Address); + end Reset_Group_Array_Buffers; + +end GNATcov_RTS.Buffers.Lists; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads index 8185cf969..ddf7e6b22 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.ads @@ -58,4 +58,9 @@ package GNATcov_RTS.Buffers.Lists is end record; pragma Convention (C, GNATcov_RTS_Coverage_Buffers_Group_Array); + procedure Reset_Group_Array_Buffers + (Arr : GNATcov_RTS_Coverage_Buffers_Group_Array); + -- Set the components of all the buffers in each group to zero, effectively + -- resetting the coverage state of all obligations to "not covered". + end GNATcov_RTS.Buffers.Lists; diff --git a/tools/gnatcov/rts/gnatcov_rts.ads b/tools/gnatcov/rts/gnatcov_rts.ads index 4e31e2c7d..04b5c93e4 100644 --- a/tools/gnatcov/rts/gnatcov_rts.ads +++ b/tools/gnatcov/rts/gnatcov_rts.ads @@ -42,7 +42,7 @@ package GNATcov_RTS is pragma Warnings (Off, Std); pragma Warnings (Off, Sys); - Version : constant := 5; + Version : constant := 6; -- For compatibility with the GNATcoverage in use, GNATcov_RTS is -- versioned. -- @@ -52,5 +52,6 @@ package GNATcov_RTS is -- 4 -- add C witness functions / buffer types -- 5 -- add a non-volatile version of the Witness_Dummy_Type and -- the associated Witness function. + -- 6 -- buffer clear mechanism and trace filename indices end GNATcov_RTS; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c index e7c534c66..23d78ebe0 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c @@ -18,6 +18,7 @@ ****************************************************************************/ #include "gnatcov_rts_c-buffers.h" +#include "gnatcov_rts_c-memory.h" #include #include @@ -65,3 +66,41 @@ gnatcov_rts_witness_condition (gnatcov_rts_bit_id *mcdc_path_address, *mcdc_path_index += offset_for_true; return value; } + +void +gnatcov_rts_reset_buffers (const struct gnatcov_rts_coverage_buffers *buffs) +{ + if (buffs == NULL) + return; + + if (buffs->statement != NULL) + memset (buffs->statement, 0, buffs->statement_last_bit + 1); + if (buffs->decision != NULL) + memset (buffs->decision, 0, buffs->decision_last_bit + 1); + if (buffs->mcdc != NULL) + memset (buffs->mcdc, 0, buffs->mcdc_last_bit + 1); +} + +void +gnatcov_rts_reset_buffer_group ( + const struct gnatcov_rts_coverage_buffers_group *group) +{ + if (group == NULL) + return; + + unsigned i; + for (i = 0; i < group->length; i++) + gnatcov_rts_reset_buffers (group->buffers[i]); +} + +void +gnatcov_rts_reset_group_array ( + const struct gnatcov_rts_coverage_buffers_group_array *arr) +{ + if (arr == NULL) + return; + + unsigned i; + for (i = 0; i < arr->length; i++) + gnatcov_rts_reset_buffer_group (arr->groups[i]); +} diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index 7f6f64cdf..733be9a68 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -137,7 +137,7 @@ extern "C" /* Set the boolean corresponding to BIT to true in BUFFER in various context. */ extern gnatcov_rts_bool gnatcov_rts_witness (uint8_t *buffer, - gnatcov_rts_bit_id bit); + gnatcov_rts_bit_id bit); /* Decisions */ @@ -145,8 +145,8 @@ extern "C" BUFFER. Set the one corresponding to TRUE_BIT otherwise. */ extern gnatcov_rts_bool gnatcov_rts_witness_decision (uint8_t *buffer, gnatcov_rts_bit_id false_bit, - gnatcov_rts_bit_id true_bit, - gnatcov_rts_bool value); + gnatcov_rts_bit_id true_bit, + gnatcov_rts_bool value); /* Same as above, and also set the bit determined by MCDC_BASE and the gnatcov_rts_bit_id value at MCDC_PATH_ADDRESS in the buffer at @@ -168,6 +168,26 @@ extern "C" gnatcov_rts_bit_id *mcdc_path_address, gnatcov_rts_bit_id offset_for_true, gnatcov_rts_bool first, gnatcov_rts_bool value); + /*********************/ + /* Clear subprograms */ + /*********************/ + + /* The following subprograms may be called to clear coverage buffers, + and thus reset the coverage execution information accumulated. */ + + /* Clear the buffers for a single unit. */ + void + gnatcov_rts_reset_buffers (const struct gnatcov_rts_coverage_buffers *buffs); + + /* Clear the buffers for a whole buffer group. */ + void gnatcov_rts_reset_buffer_group ( + const struct gnatcov_rts_coverage_buffers_group *group); + + /* Set all the values in all the buffers of each group denoted by arr to + zero. This clears the buffers of all coverage levels. */ + extern void gnatcov_rts_reset_group_array ( + const struct gnatcov_rts_coverage_buffers_group_array *arr); + #ifdef __cplusplus } #endif diff --git a/tools/gnatcov/rts/gnatcov_rts_c-memory.h b/tools/gnatcov/rts/gnatcov_rts_c-memory.h new file mode 100644 index 000000000..da4e72875 --- /dev/null +++ b/tools/gnatcov/rts/gnatcov_rts_c-memory.h @@ -0,0 +1,44 @@ +/**************************************************************************** + * * + * GNATcoverage Instrumentation Runtime * + * * + * Copyright (C) 2021-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. * + * * + ****************************************************************************/ + +#ifndef GNATCOV_RTS_C_MEMORY_H +#define GNATCOV_RTS_C_MEMORY_H + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + + /* Smallest subset of functions needed for memory manipulations (memcpy and + memset). These functions must either be defined by the runtime (even if it + is in a bareboard environment), or provided by the user. + + Note that we declare them ourselves, as the runtime may not provide the + string.h header: older versions of light runtimes did not package newlib, + and thus did not provide the string.h portable header. Though the memcpy + and memset functions are provided by the light runtime in this case. */ + extern void *memcpy (void *__dest, const void *__src, size_t __n); + extern void *memset (void *__s, int __c, size_t __n); + +#ifdef __cplusplus +} +#endif +#endif // GNATCOV_RTS_C_MEMORY_H diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c index ee2c133a9..54273ffcb 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-base64.c @@ -19,6 +19,7 @@ #include "gnatcov_rts_c-traces-output-base64.h" #include "gnatcov_rts_c-base_io.h" +#include "gnatcov_rts_c-memory.h" #include "gnatcov_rts_c-traces-output.h" static const char *base64_alphabet diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c index 929300037..5278a0d4a 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c @@ -25,6 +25,7 @@ #include #include +#include "gnatcov_rts_c-memory.h" #include "gnatcov_rts_c-os_interface.h" #include "gnatcov_rts_c-traces-output-files.h" #include "gnatcov_rts_c-traces-output.h" diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index 3c80a5738..3926d5e1f 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -18,6 +18,7 @@ ****************************************************************************/ #include "gnatcov_rts_c-traces-output.h" +#include "gnatcov_rts_c-memory.h" #include "gnatcov_rts_c-traces.h" #include diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h index 1e781c858..136454c29 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.h @@ -25,24 +25,13 @@ extern "C" { #endif - /* Smallest subset of functions needed for memory manipulations (memcpy and - memset). These functions must either be defined by the runtime (even if it - is in a bareboard environment), or provided by the user. - - Note that we declare them ourselves, as the runtime may not provide the - string.h header: older versions of light runtimes did not package newlib, - and thus did not provide the string.h portable header. Though the memcpy - and memset functions are provided by the light runtime in this case. */ - extern void *memcpy (void *__dest, const void *__src, size_t __n); - extern void *memset (void *__s, int __c, size_t __n); - /* Callback for trace writing routines. Write the N bytes starting at SOURCE to the OUTPUT stream (OUTPUT is just forwarded from gnatcov_rts_generic_write_trace_file). Return 0 if the write was successful and return any non-zero value in case of error. */ typedef int (*gnatcov_rts_write_bytes_callback) (void *output, - const void *source, - unsigned n); + const void *source, + unsigned n); /* Write a trace file to contain the given coverage BUFFERS_GROUPS to the OUTPUT stream using the WRITE_BYTES callback. PROGRAM_NAME, EXEC_DATE and From ea672c402dd528ac3c4e7687b20ba0326eb1c870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 7 Feb 2024 13:15:04 +0100 Subject: [PATCH 0678/1483] instrument-project.adb: regroup context cleanup to context destruction Cleanup for temporary files used by the insturmenters was done after finishing the coverage instrumentation, thus some artifacts were missing during manual dump instrumentation. This change moves the cleanup of temporary files to the destruction of the instrumentation context, after which point it is sure that the files will not be used anymore. --- tools/gnatcov/instrument-projects.adb | 24 +++++++++++++++++------- tools/gnatcov/json.adb | 1 + 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index e1a5a36c0..88415691f 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -200,7 +200,8 @@ is -- Create an instrumentation context for the currently loaded project procedure Destroy_Context (Context : in out Inst_Context); - -- Free dynamically allocated resources in Context + -- Free dynamically allocated resources in Context, and cleanup temporary + -- files. function Is_Ignored_Source_File (Context : Inst_Context; Filename : String) return Boolean; @@ -414,6 +415,7 @@ is --------------------- procedure Destroy_Context (Context : in out Inst_Context) is + use Ada.Directories; procedure Free is new Ada.Unchecked_Deallocation (Project_Info, Project_Info_Access); begin @@ -430,6 +432,20 @@ is end; end loop; Context.Project_Info_Map := Project_Info_Maps.Empty_Map; + + -- Cleanup temporary artifacts if not instructed to keep them + + if not Save_Temps then + if Exists (+Context.Config_Pragmas_Mapping) then + Delete_File (+Context.Config_Pragmas_Mapping); + end if; + if Exists (+Context.Sources_Of_Interest_Response_File) then + Delete_File (+Context.Sources_Of_Interest_Response_File); + end if; + if Exists (+Context.Ada_Preprocessor_Data_File) then + Delete_File (+Context.Ada_Preprocessor_Data_File); + end if; + end if; end Destroy_Context; ---------------------------- @@ -1475,12 +1491,6 @@ begin end loop; end; - if not Save_Temps then - Ada.Directories.Delete_File (+IC.Config_Pragmas_Mapping); - Ada.Directories.Delete_File (+IC.Sources_Of_Interest_Response_File); - Ada.Directories.Delete_File (+IC.Ada_Preprocessor_Data_File); - end if; - -- Emit the unit to contain the list of coverage buffers, exported to a -- C symbol, in one of the language supported by the project. -- diff --git a/tools/gnatcov/json.adb b/tools/gnatcov/json.adb index d89b523fa..aca40ae1c 100644 --- a/tools/gnatcov/json.adb +++ b/tools/gnatcov/json.adb @@ -35,6 +35,7 @@ package body JSON is begin File.Create (Filename); File.Put (Content); + File.Close; end Write; ---------- From 214a56fe2a7b4fad155c7acc7c185f0307da535b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 7 Feb 2024 13:19:19 +0100 Subject: [PATCH 0679/1483] instrument-ada_unit.adb: Only query a LAL unit once for each file The manual dump indication processing used to query a LAL unit twice when processing a file with manual dump / reset indications: once for the tree traversal, and once when starting the rewrinting session when the manual indication was found. If the LAL context was reset on the second query, the instrumentation would fail due to stale references. This change adds a mechanism to start a rewriting session from an already existing analysis unit. --- tools/gnatcov/instrument-ada_unit.adb | 44 ++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 2d52d09d4..a75600365 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1225,6 +1225,18 @@ package body Instrument.Ada_Unit is -- If there are parsing errors while reading Input_Filename, this raises a -- fatal error and prints the corresponding error messages. + procedure Start_Rewriting + (Self : out Ada_Source_Rewriter'Class; + Instrumenter : in out Ada_Instrumenter_Type'Class; + Prj : Prj_Desc; + Unit : Analysis_Unit); + -- Same as above, but initiating the rewriting session from Unit, skipping + -- the diagnostics checks. + -- + -- This variation must be used if some analysis on a unit had already taken + -- place, in order to avoid a new call to Get_From_File, potentially + -- resetting the context, voiding all previous references. + function Rewritten_Unit (Self : Ada_Source_Rewriter'Class) return Libadalang.Analysis.Analysis_Unit; @@ -6765,12 +6777,8 @@ package body Instrument.Ada_Unit is Prj : Prj_Desc; Input_Filename : String) is - Base_Filename : constant String := - Ada.Directories.Simple_Name (Input_Filename); - Output_Filename : constant String := - New_File (Prj, Base_Filename); - Unit : constant Analysis_Unit := - Get_From_File (Instrumenter, Input_Filename); + Unit : constant Analysis_Unit := + Get_From_File (Instrumenter, Input_Filename); begin if Unit.Has_Diagnostics then Outputs.Error ("instrumentation failed for " & Input_Filename); @@ -6781,8 +6789,25 @@ package body Instrument.Ada_Unit is end loop; raise Xcov_Exit_Exc; end if; + Start_Rewriting (Self, Instrumenter, Prj, Unit); + end Start_Rewriting; - Self.Input_Filename := +Input_Filename; + --------------------- + -- Start_Rewriting -- + --------------------- + + procedure Start_Rewriting + (Self : out Ada_Source_Rewriter'Class; + Instrumenter : in out Ada_Instrumenter_Type'Class; + Prj : Prj_Desc; + Unit : Analysis_Unit) + is + Base_Filename : constant String := + Ada.Directories.Simple_Name (Unit.Get_Filename); + Output_Filename : constant String := + New_File (Prj, Base_Filename); + begin + Self.Input_Filename := +Unit.Get_Filename; Self.Output_Filename := +Output_Filename; Self.Unit := Unit; Self.Handle := Start_Rewriting (Instrumenter.Context); @@ -7943,6 +7968,9 @@ package body Instrument.Ada_Unit is Rewriter : Ada_Source_Rewriter; + Dummy_Ctx : constant Context_Handle := + Create_Context ("Searching manual indications in " & Source_Filename); + function Find_And_Replace_Pragma (N : Ada_Node'Class) return Visit_Status; @@ -7982,7 +8010,7 @@ package body Instrument.Ada_Unit is if not (Has_Dump_Indication or else Has_Reset_Indication) then - Start_Rewriting (Rewriter, Self, Prj, File_To_Search); + Start_Rewriting (Rewriter, Self, Prj, Unit); end if; declare From 69e8dd6c5a17f3b0605c1ccbde27b18805fef9d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 7 Feb 2024 13:25:28 +0100 Subject: [PATCH 0680/1483] Add test regarding context managment and manual indications --- .../manual-dump/lal_ctx_reset/test.py | 93 +++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py diff --git a/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py b/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py new file mode 100644 index 000000000..3d2ebe0ec --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py @@ -0,0 +1,93 @@ +""" +Test that there are no issues when the LAL context is recreated when querying a +unit during the search of manual dump/reset indications. +Two bugs used to make this crash: + - The JSON configuration pragma file used to be deleted after finishing the + coverage instrumentation, thus crashing gnatcov when a LAL context was + recreated. + - The manual dump search first performs a search of the relevant pragmas on + all sources, and only starts a rewriting session once one such pragma is + found. This results in two calls to get_from_file for the same unit, which + leads to stale references once the rewriting sessions was initialized. +This regression test reproduces both bugs. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches, gprcov_for +from SUITE.tutils import gprfor + + +tmp = Wdir ("tmp_") + +# Number of LAL unit queries after which gnatcov reset the LAL context +GNATCOV_CTX_RESET_LIMIT = 50 + +def gen_project(): + """ + Generate a project capable of reproducing the bug. + We need to create exactly 50 sources to instrument for coverage (the limit + at which gnatcov resets its LAL context) then inspect at least one source + in search of a manual buffer dump indication. + Returns a tuple consisting in the generated project name (by gprfor) and + the expected coverage result. + """ + + # First, generate the sources to be instrumented. They'll only consist in + # the bare minimum to generate an obligation: a simple variable + # declaration. + for i in range(GNATCOV_CTX_RESET_LIMIT): + with open(f"pkg_{i}.ads", "w") as pkg_file: + pkg_file.write(f"package Pkg_{i} is\n") + pkg_file.write(" Dummy_Bool : Boolean := False;\n") + pkg_file.write(f"end Pkg_{i};\n") + + # Then, generate a main that pulls all these units in the compilation + # closure, and includes a manual dump indication. + + with open("main.adb", "w") as main_file: + for i in range(GNATCOV_CTX_RESET_LIMIT): + main_file.write(f"with Pkg_{i};\n") + main_file.write("procedure Main is\n") + main_file.write("begin\n") + main_file.write(" null;\n") + main_file.write(" pragma Annotate (Xcov, Dump_Buffers);\n") + main_file.write("end Main;\n") + + # Create a project. The Pkg_{i} sources are of interest for coverage + # purposes, but the main not. + prj = gprfor( + mains=["main.adb"], + prjid="prj", + srcdirs=".", + objdir="obj", + extra=gprcov_for( + units_in=[f"Pkg_{i}" for i in range(GNATCOV_CTX_RESET_LIMIT)] + ) + ) + expected_cov={ + f"pkg_{i}.ads.xcov": {'+': {2}} for i in range(GNATCOV_CTX_RESET_LIMIT) + } + return prj, expected_cov + + +# First, generate a project + +prj, expected_cov = gen_project() + +# Then instrument, build, run, coverage and check +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + mains=["main"], + covlevel="stmt", + extra_coverage_args=["-axcov"], + dump_trigger="manual", + manual_prj_name=os.path.splitext(prj)[0] +) + +check_xcov_reports("*.xcov", expected_cov, cwd="obj") + +thistest.result() From 4a5e727eaf54f2e9d63468cb550b108dd31f4ac7 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 12 Feb 2024 11:50:19 +0000 Subject: [PATCH 0681/1483] instr-cov/225-expr-func-access: rework to avoid bin/src traces diffs Put the expression functions in a body to prevent inlining from affecting coverage reports with binary traces. This fixes the current discrepancies with source traces. --- .../instr-cov/225-expr-func-access/main.adb | 17 ++--------------- .../instr-cov/225-expr-func-access/pkg.adb | 14 ++++++++++++++ .../instr-cov/225-expr-func-access/pkg.ads | 14 ++++++++++++++ .../instr-cov/225-expr-func-access/test.py | 6 +++--- 4 files changed, 33 insertions(+), 18 deletions(-) create mode 100644 testsuite/tests/instr-cov/225-expr-func-access/pkg.adb create mode 100644 testsuite/tests/instr-cov/225-expr-func-access/pkg.ads diff --git a/testsuite/tests/instr-cov/225-expr-func-access/main.adb b/testsuite/tests/instr-cov/225-expr-func-access/main.adb index 655cc016b..85c766fbc 100644 --- a/testsuite/tests/instr-cov/225-expr-func-access/main.adb +++ b/testsuite/tests/instr-cov/225-expr-func-access/main.adb @@ -2,22 +2,9 @@ pragma Ada_2022; with Ada.Text_IO; use Ada.Text_IO; -procedure Main is - - type Integer_Access is access all Integer; - - A : aliased Integer; - B : aliased Integer; - - function Get_Ref (Is_A : Boolean) return Integer_Access - is (if Is_A then A'Access else B'Access); - - function Get_Unc_Ref (Is_A : Boolean) return Integer_Access - is (if Is_A then A'Unchecked_Access else B'Unchecked_Access); - - function Get_Unr_Ref (Is_A : Boolean) return Integer_Access - is (if Is_A then A'Unrestricted_Access else B'Unrestricted_Access); +with Pkg; use Pkg; +procedure Main is begin Get_Ref (True).all := 1; Get_Ref (False).all := 2; diff --git a/testsuite/tests/instr-cov/225-expr-func-access/pkg.adb b/testsuite/tests/instr-cov/225-expr-func-access/pkg.adb new file mode 100644 index 000000000..49c8f5d94 --- /dev/null +++ b/testsuite/tests/instr-cov/225-expr-func-access/pkg.adb @@ -0,0 +1,14 @@ +pragma Ada_2022; + +package body Pkg is + + function Get_Ref (Is_A : Boolean) return Integer_Access + is (if Is_A then A'Access else B'Access); + + function Get_Unc_Ref (Is_A : Boolean) return Integer_Access + is (if Is_A then A'Unchecked_Access else B'Unchecked_Access); + + function Get_Unr_Ref (Is_A : Boolean) return Integer_Access + is (if Is_A then A'Unrestricted_Access else B'Unrestricted_Access); + +end Pkg; diff --git a/testsuite/tests/instr-cov/225-expr-func-access/pkg.ads b/testsuite/tests/instr-cov/225-expr-func-access/pkg.ads new file mode 100644 index 000000000..75afac653 --- /dev/null +++ b/testsuite/tests/instr-cov/225-expr-func-access/pkg.ads @@ -0,0 +1,14 @@ +pragma Ada_2022; + +package Pkg is + + type Integer_Access is access all Integer; + + A : aliased Integer; + B : aliased Integer; + + function Get_Ref (Is_A : Boolean) return Integer_Access; + function Get_Unc_Ref (Is_A : Boolean) return Integer_Access; + function Get_Unr_Ref (Is_A : Boolean) return Integer_Access; + +end Pkg; diff --git a/testsuite/tests/instr-cov/225-expr-func-access/test.py b/testsuite/tests/instr-cov/225-expr-func-access/test.py index b8a714e3f..2baa29230 100644 --- a/testsuite/tests/instr-cov/225-expr-func-access/test.py +++ b/testsuite/tests/instr-cov/225-expr-func-access/test.py @@ -24,9 +24,9 @@ check_xcov_reports( "*.xcov", { - "main.adb.xcov": { - "+": {7, 9, 10, 13, 16, 19, 22, 23, 25, 26, 28, 29, 31, 32} - } + "main.adb.xcov": {"+": {9, 10, 12, 13, 15, 16}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {6, 9, 12}}, }, cwd="xcov", ) From d20bf7b24dc8ff9e0c111d94786a5ab97adb87af Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 12 Feb 2024 11:54:51 +0000 Subject: [PATCH 0682/1483] instr-cov/225-expr-func-access: kill with old toolchains This test checks behavior specific to Ada 2022. Kill it for toolchains that do not support this language version. --- testsuite/tests/instr-cov/225-expr-func-access/test.opt | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 testsuite/tests/instr-cov/225-expr-func-access/test.opt diff --git a/testsuite/tests/instr-cov/225-expr-func-access/test.opt b/testsuite/tests/instr-cov/225-expr-func-access/test.opt new file mode 100644 index 000000000..59ae493a2 --- /dev/null +++ b/testsuite/tests/instr-cov/225-expr-func-access/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Requires Ada 2022, unavailable in 5.04a1 +7.1.2 DEAD Requires Ada 2022, unavailable in 7.1.2 From 58509013769b4f7545dec3984927009dc0d27b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 13 Feb 2024 17:38:03 +0100 Subject: [PATCH 0683/1483] instr-cov/manual-dump/trace_index: kill for cross targets The test is specific to the bin-file dump-channel, so it doesn't make sense in a cross context. --- testsuite/tests/instr-cov/manual-dump/trace_index/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/instr-cov/manual-dump/trace_index/test.opt diff --git a/testsuite/tests/instr-cov/manual-dump/trace_index/test.opt b/testsuite/tests/instr-cov/manual-dump/trace_index/test.opt new file mode 100644 index 000000000..2fc2f0620 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/trace_index/test.opt @@ -0,0 +1 @@ +!native DEAD Test specific to bin-file dump channel, not available on cross From 6392e3c50d45931c719414dfb193e644e9fb6122 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 14 Feb 2024 13:39:07 +0000 Subject: [PATCH 0684/1483] gnatcov.gpr: consider warnings as errors for Ada in dev mode --- tools/gnatcov/gnatcov.gpr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index c109d9bee..22ccb75f4 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -222,7 +222,7 @@ project Gnatcov is case Build_Mode is when "dev" => Mode_Switches := ("-O0", "-g"); - Ada_Mode_Switches := ("-gnata"); + Ada_Mode_Switches := ("-gnata", "-gnatwe"); C_Mode_Switches := ("-Werror"); CPP_Mode_Switches := ("-Werror"); From a0e9511a534fd64827a577392f114005aa80e339 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 14 Feb 2024 14:21:51 +0000 Subject: [PATCH 0685/1483] VC19-001-origin-prj: import from the internal testsuite --- .../VC19-001-origin-prj/src_code/code.adb | 6 +++ .../VC19-001-origin-prj/src_code/code.ads | 3 ++ .../src_test/test_main.adb | 12 +++++ testsuite/tests/VC19-001-origin-prj/test.py | 50 +++++++++++++++++++ 4 files changed, 71 insertions(+) create mode 100644 testsuite/tests/VC19-001-origin-prj/src_code/code.adb create mode 100644 testsuite/tests/VC19-001-origin-prj/src_code/code.ads create mode 100644 testsuite/tests/VC19-001-origin-prj/src_test/test_main.adb create mode 100644 testsuite/tests/VC19-001-origin-prj/test.py diff --git a/testsuite/tests/VC19-001-origin-prj/src_code/code.adb b/testsuite/tests/VC19-001-origin-prj/src_code/code.adb new file mode 100644 index 000000000..ea73d4fcf --- /dev/null +++ b/testsuite/tests/VC19-001-origin-prj/src_code/code.adb @@ -0,0 +1,6 @@ +package body Code is + function Compute (X : Boolean; Y : Boolean) return Boolean is + begin + return X and then Y; + end Compute; +end Code; \ No newline at end of file diff --git a/testsuite/tests/VC19-001-origin-prj/src_code/code.ads b/testsuite/tests/VC19-001-origin-prj/src_code/code.ads new file mode 100644 index 000000000..1a2201fcc --- /dev/null +++ b/testsuite/tests/VC19-001-origin-prj/src_code/code.ads @@ -0,0 +1,3 @@ +package Code is + function Compute (X : Boolean; Y : Boolean) return Boolean; +end Code; \ No newline at end of file diff --git a/testsuite/tests/VC19-001-origin-prj/src_test/test_main.adb b/testsuite/tests/VC19-001-origin-prj/src_test/test_main.adb new file mode 100644 index 000000000..928bae60f --- /dev/null +++ b/testsuite/tests/VC19-001-origin-prj/src_test/test_main.adb @@ -0,0 +1,12 @@ +with Code; + +procedure Test_Main is + procedure Assert (X : Boolean) is + begin + if not X then + raise Program_Error; + end if; + end Assert; +begin + Assert (Code.Compute (True, False) = Code.Compute (False, True)); +end Test_Main; \ No newline at end of file diff --git a/testsuite/tests/VC19-001-origin-prj/test.py b/testsuite/tests/VC19-001-origin-prj/test.py new file mode 100644 index 000000000..d3af4c0e1 --- /dev/null +++ b/testsuite/tests/VC19-001-origin-prj/test.py @@ -0,0 +1,50 @@ +""" +Check that gnatcov correctly uses the Switches attributes from the +project designated by the Origin_Project attribute in the root project. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +# Generate a project file for our code, containing all the relevant +# coverage switches in the Coverage package Switches attributes. +code_prj = gprfor( + mains=[], + prjid="code", + srcdirs=[os.path.join("..", "src_code")], + extra="package Coverage is" + '\n for Switches ("*") use ("--level=stmt+mcdc");' + '\n for Switches ("Coverage") use ("-axcov", "--output-dir=xcov");' + "\nend Coverage;", +) + +# Generate a project for the test driver, "withing" the code project and +# referencing it through the Origin_Project attribute +test_prj = gprfor( + mains=["test_main.adb"], + prjid="test", + srcdirs=[os.path.join("..", "src_test")], + deps=[code_prj], + extra=f'for Origin_Project use "{code_prj}";', +) + +# No level or annotation format provided, everything should be loaded from +# the Origin_Project (code.gpr). +build_run_and_coverage( + gprsw=GPRswitches(root_project=test_prj), + covlevel=None, + extra_coverage_args=[], + mains=["test_main"], +) + +check_xcov_reports("*.xcov", {"code.adb.xcov": {"!": {4}}}, cwd="xcov") + +thistest.result() From c170322a90f93254baab90840681775885369502 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 14 Feb 2024 16:04:48 +0000 Subject: [PATCH 0686/1483] Testsuite: fix style issues in text files Remove trailing whitespaces and trailing lines, ensure that the last line of each file ends with a newline. --- .../1_Core/NoEval/And/FloatOps/src/ops.adb | 4 +- .../1_Core/NoEval/And/FloatOps/src/ops.ads | 12 ++-- .../NoEval/And/FloatOps/src/test_ops_all.adb | 3 +- .../NoEval/And/FloatOps/src/test_ops_f.adb | 1 - .../And/FloatOps/src/test_ops_koova.adb | 3 +- .../And/FloatOps/src/test_ops_okovb.adb | 3 +- .../NoEval/And/FloatOps/src/test_ops_ova.adb | 1 - .../NoEval/And/FloatOps/src/test_ops_ovb.adb | 1 - .../NoEval/And/FloatOps/src/test_ops_t.adb | 1 - .../1_Core/NoEval/And/FloatOps/test.opt | 2 +- .../1_Core/NoEval/Or/FloatOps/src/ops.adb | 2 +- .../1_Core/NoEval/Or/FloatOps/src/ops.ads | 12 ++-- .../NoEval/Or/FloatOps/src/test_ops_all.adb | 3 +- .../NoEval/Or/FloatOps/src/test_ops_f.adb | 1 - .../NoEval/Or/FloatOps/src/test_ops_koova.adb | 3 +- .../NoEval/Or/FloatOps/src/test_ops_okovb.adb | 7 +-- .../NoEval/Or/FloatOps/src/test_ops_ova.adb | 1 - .../NoEval/Or/FloatOps/src/test_ops_ovb.adb | 3 +- .../NoEval/Or/FloatOps/src/test_ops_t.adb | 1 - .../1_Core/NoEval/Or/FloatOps/test.opt | 2 +- .../Operands/AddressCompare/src/fuand.adb | 4 +- .../Operands/AddressCompare/src/fuand.ads | 8 +-- .../1_Core/Operands/Attributes/src/fuor.ads | 3 - .../1_Core/Operands/BitOrdered/src/fuand.adb | 4 +- .../1_Core/Operands/BitOrdered/src/fuand.ads | 4 +- .../Operands/BitOrdered/src/fuand_helper.adb | 1 - .../1_Core/Operands/BitOrdered/src/fuor.adb | 4 +- .../1_Core/Operands/BitOrdered/src/fuor.ads | 2 +- .../Operands/BitOrdered/src/fuor_helper.adb | 1 - .../Operands/BoolAttribute/src/fuand.ads | 14 ++--- .../1_Core/Operands/BoolIndexed/src/fuand.ads | 14 ++--- .../Operands/BoolSelected/src/fuand.ads | 10 ++-- .../1_Core/Operands/EnumOps/src/fuand.ads | 6 +- .../Operands/EnumOps/src/fuand_helper.adb | 3 +- .../1_Core/Operands/EnumOps/src/fuor.adb | 2 +- .../1_Core/Operands/EnumOps/src/fuor.ads | 6 +- .../Operands/EnumOps/src/fuor_helper.adb | 1 - .../1_Core/Operands/FixedOps/src/fuand.ads | 10 ++-- .../Operands/FixedOps/src/fuand_helper.adb | 3 +- .../1_Core/Operands/FixedOps/src/fuor.ads | 10 ++-- .../Operands/FixedOps/src/fuor_helper.adb | 1 - .../1_Core/Operands/FloatOps/src/fuand.ads | 12 ++-- .../Operands/FloatOps/src/fuand_helper.adb | 3 +- .../1_Core/Operands/FloatOps/src/fuor.ads | 12 ++-- .../Operands/FloatOps/src/fuor_helper.adb | 1 - .../1_Core/Operands/IntChar/src/fuand.ads | 20 +++---- .../Operands/IntChar/src/fuand_helper.adb | 3 +- .../1_Core/Operands/IntChar/src/fuor.adb | 2 +- .../1_Core/Operands/IntChar/src/fuor.ads | 20 +++---- .../Operands/IntChar/src/fuor_helper.adb | 1 - .../Operands/P4bitStaType/src/fuand.ads | 14 ++--- .../Operands/P4bitStaType/src/fubool.ads | 8 +-- .../1_Core/Operands/Packed/src/fuand.ads | 4 +- .../Operands/Packed/src/fuand_helper.adb | 3 +- .../1_Core/Operands/Packed/src/fuor.ads | 4 +- .../Operands/Packed/src/fuor_helper.adb | 1 - .../Operands/ParameterModes/src/ops.adb | 22 ++++---- .../Operands/ParameterModes/src/ops.ads | 6 +- .../1_Core/Operands/PbitDynBase/src/fuand.ads | 8 +-- .../Operands/PbitDynBase/src/fubool.ads | 6 +- .../1_Core/Operands/PbitDynBase/src/fuor.ads | 8 +-- .../Operands/PbitDynBaseW/src/fuand.ads | 8 +-- .../Operands/PbitDynBaseW/src/fubool.ads | 6 +- .../1_Core/Operands/PbitDynType/src/fuand.ads | 8 +-- .../Operands/PbitDynType/src/fubool.ads | 6 +- .../Operands/PbitDynTypeV/src/fuand.ads | 8 +-- .../Operands/PbitDynTypeV/src/fubool.ads | 6 +- .../Operands/PbitDynTypeW/src/fuand.ads | 8 +-- .../Operands/PbitDynTypeW/src/fubool.ads | 6 +- .../1_Core/Operands/PbitStaType/src/fuand.ads | 10 ++-- .../Operands/PbitStaType/src/fubool.ads | 8 +-- .../Operands/PbitStaTypeW/src/fuand.ads | 8 +-- .../Operands/PbitStaTypeW/src/fubool.ads | 6 +- .../Operands/PboolStaType/src/fuand.ads | 8 +-- .../Operands/PboolStaType/src/fubool.ads | 6 +- .../1_Core/Operands/Placed/src/fuand.ads | 4 +- .../Operands/Placed/src/fuand_helper.adb | 3 +- .../1_Core/Operands/Placed/src/fuor.ads | 4 +- .../Operands/Placed/src/fuor_helper.adb | 1 - .../1_Core/Operands/PmixStaType/src/fuand.ads | 6 +- .../1_Core/Operands/PmixStaType/src/fuor.ads | 6 +- .../Operands/PnestStaType/src/fuand.ads | 12 ++-- .../Operands/PnestStaType/src/fubool.ads | 12 ++-- .../1_Core/Operands/QualExpr/src/fuand.adb | 4 +- .../1_Core/Operands/QualExpr/src/fuand.ads | 2 +- .../Operands/RangeMembership/src/fuor.ads | 8 +-- .../Operands/SubtypeMembership/src/fuand.ads | 4 +- .../1_Core/Operands/Uindexed/src/fuand.ads | 12 ++-- .../Operands/Uindexed/src/fuand_helper.adb | 3 +- .../1_Core/Operands/Uindexed/src/fuor.ads | 12 ++-- .../Operands/Uindexed/src/fuor_helper.adb | 1 - .../1_Core/Operands/src/fuand_helper.adb | 8 +-- .../1_Core/Operands/src/fubool_helper.adb | 2 +- .../1_Core/Operands/src/test_fuand_0.adb | 1 - .../1_Core/Operands/src/test_fuand_a.adb | 1 - .../1_Core/Operands/src/test_fuand_ab.adb | 2 - .../1_Core/Operands/src/test_fuand_b.adb | 1 - .../1_Core/Operands/src/test_fuand_f.adb | 2 - .../1_Core/Operands/src/test_fuand_t.adb | 2 - .../1_Core/Operands/src/test_fubool_0.adb | 2 - .../1_Core/Operands/src/test_fubool_f.adb | 2 - .../1_Core/Operands/src/test_fubool_t.adb | 2 - .../1_Core/Operands/src/test_fubool_tf.adb | 2 - .../1_Core/Operands/src/test_fuor_ab.adb | 1 - .../1_Core/Operands/src/test_fuor_b.adb | 2 - .../1_Core/Operands/src/test_fuor_f.adb | 1 - .../1_Core/Operands/src/test_fuor_t.adb | 1 - .../Topologies/And/Elsif/src/andthen.adb | 3 - .../Topologies/And/IfElse/src/andthen.adb | 3 - .../Topologies/And/IfExpr/src/andthen.adb | 3 - .../1_Core/Topologies/And/IfExpr/test.opt | 2 +- .../Topologies/And/IfNoElse/src/andthen.adb | 3 - .../Topologies/And/While/src/andthen.adb | 3 - .../Topologies/And/src/test_andthen_f.adb | 1 - .../1_Core/Topologies/Flip/Elsif/src/flip.adb | 1 - .../Topologies/Flip/IfElse/src/flip.adb | 1 - .../Topologies/Flip/IfExpr/src/flip.adb | 1 - .../1_Core/Topologies/Flip/IfExpr/test.opt | 2 +- .../Topologies/Flip/IfNoElse/src/flip.adb | 1 - .../1_Core/Topologies/Flip/While/src/flip.adb | 1 - .../1_Core/Topologies/Flip/src/flip.ads | 1 - .../1_Core/Topologies/Or/Elsif/src/orelse.adb | 3 - .../1_Core/Topologies/Or/Exit/src/orelse.adb | 3 - .../Topologies/Or/IfElse/src/orelse.adb | 3 - .../Topologies/Or/IfExpr/src/orelse.adb | 3 - .../1_Core/Topologies/Or/IfExpr/test.opt | 2 +- .../Topologies/Or/IfNoElse/src/orelse.adb | 3 - .../1_Core/Topologies/Or/While/src/orelse.adb | 3 - .../1_Core/Topologies/Value/IfExpr/test.opt | 2 +- .../Topologies/Value/While/src/value.adb | 1 - .../1_Core/Topologies/Value/src/value.ads | 1 - .../doB/mix_pAndpOrpAndp/Elsif/src/expr.adb | 3 - .../doB/mix_pAndpOrpAndp/IfElse/src/expr.adb | 3 - .../mix_pAndpOrpAndp/IfNoElse/src/expr.adb | 3 - .../doB/mix_pAndpOrpAndp/While/src/expr.adb | 3 - .../doB/mix_pAndpOrpOrp/Elsif/src/expr.adb | 3 - .../doB/mix_pAndpOrpOrp/IfElse/src/expr.adb | 3 - .../doB/mix_pAndpOrpOrp/IfNoElse/src/expr.adb | 3 - .../doB/mix_pAndpOrpOrp/While/src/expr.adb | 3 - .../doB/mix_pOrpOrpAndp/Elsif/src/expr.adb | 3 - .../doB/mix_pOrpOrpAndp/IfElse/src/expr.adb | 3 - .../doB/mix_pOrpOrpAndp/IfNoElse/src/expr.adb | 3 - .../doB/mix_pOrpOrpAndp/While/src/expr.adb | 3 - .../Topologies/doB/ns_And/Elsif/src/expr.adb | 3 - .../Topologies/doB/ns_And/IfElse/src/expr.adb | 3 - .../doB/ns_And/IfNoElse/src/expr.adb | 3 - .../Topologies/doB/ns_And/While/src/expr.adb | 3 - .../Topologies/doB/ns_And/src/test_expr_f.adb | 1 - .../Topologies/doB/ns_Or/Elsif/src/expr.adb | 3 - .../Topologies/doB/ns_Or/Exit/src/expr.adb | 3 - .../Topologies/doB/ns_Or/IfElse/src/expr.adb | 3 - .../doB/ns_Or/IfNoElse/src/expr.adb | 3 - .../Topologies/doB/ns_Or/While/src/expr.adb | 3 - .../doB/ns_pAndpOrpAndp/Elsif/src/expr.adb | 3 - .../doB/ns_pAndpOrpAndp/IfElse/src/expr.adb | 3 - .../doB/ns_pAndpOrpAndp/IfNoElse/src/expr.adb | 3 - .../doB/ns_pAndpOrpAndp/While/src/expr.adb | 3 - .../doB/ns_pAndpOrpOrp/Elsif/src/expr.adb | 3 - .../doB/ns_pAndpOrpOrp/IfElse/src/expr.adb | 3 - .../doB/ns_pAndpOrpOrp/IfNoElse/src/expr.adb | 3 - .../doB/ns_pAndpOrpOrp/While/src/expr.adb | 3 - .../doB/ns_pOrpOrpAndp/Elsif/src/expr.adb | 3 - .../doB/ns_pOrpOrpAndp/IfElse/src/expr.adb | 3 - .../doB/ns_pOrpOrpAndp/IfNoElse/src/expr.adb | 3 - .../doB/ns_pOrpOrpAndp/While/src/expr.adb | 3 - .../pAndpOrpAndp/Elsif/src/expr.adb | 3 - .../pAndpOrpAndp/ForAllIndex/src/expr.adb | 3 - .../pAndpOrpAndp/ForSomeIndex/src/expr.adb | 3 - .../pAndpOrpAndp/IfElse/src/expr.adb | 3 - .../pAndpOrpAndp/IfExpr/src/expr.adb | 3 - .../Topologies/pAndpOrpAndp/IfExpr/test.opt | 2 +- .../pAndpOrpAndp/IfNoElse/src/expr.adb | 3 - .../pAndpOrpAndp/While/src/expr.adb | 3 - .../Topologies/pAndpOrpOrp/Elsif/src/expr.adb | 3 - .../pAndpOrpOrp/ForAllIndex/src/expr.adb | 3 - .../pAndpOrpOrp/ForSomeIndex/src/expr.adb | 3 - .../pAndpOrpOrp/IfElse/src/expr.adb | 3 - .../pAndpOrpOrp/IfExpr/src/expr.adb | 3 - .../Topologies/pAndpOrpOrp/IfExpr/test.opt | 2 +- .../pAndpOrpOrp/IfNoElse/src/expr.adb | 3 - .../Topologies/pAndpOrpOrp/While/src/expr.adb | 3 - .../Topologies/pOrpOrpAndp/Elsif/src/expr.adb | 3 - .../pOrpOrpAndp/ForAllIndex/src/expr.adb | 3 - .../pOrpOrpAndp/ForSomeIndex/src/expr.adb | 3 - .../pOrpOrpAndp/IfElse/src/expr.adb | 3 - .../pOrpOrpAndp/IfNoElse/src/expr.adb | 3 - .../Topologies/pOrpOrpAndp/While/src/expr.adb | 3 - .../Inactive/AssertPragma/src/ops.adb | 4 +- .../Inactive/AssertPragma/src/ops.ads | 6 +- .../AssertPragma/src/test_ops_pos.adb | 1 - .../Inactive/DynamicPredicates/src/ops.adb | 2 +- .../Inactive/DynamicPredicates/src/ops.ads | 6 +- .../PrePost/PostAspect_LibSpec/src/ops.adb | 4 +- .../PrePost/PostAspect_LibSpec/src/ops.ads | 6 +- .../PostClassAspect_LibSpec/src/ops.adb | 4 +- .../PostClassAspect_LibSpec/src/ops.ads | 6 +- .../PrePost/PreAspect_LibSpec/src/ops.adb | 4 +- .../PrePost/PreAspect_LibSpec/src/ops.ads | 6 +- .../PrePost/PreAspect_Local/src/ops.adb | 10 ++-- .../PrePost/PreAspect_Local/src/ops.ads | 4 +- .../PrePost/PrePragma_LibSpec/src/ops.adb | 4 +- .../PrePost/PrePragma_LibSpec/src/ops.ads | 6 +- .../Inactive/PrePost/src/optypes.ads | 2 +- .../Inactive/StaticPredicates/src/ops.adb | 10 ++-- .../Inactive/StaticPredicates/src/ops.ads | 12 ++-- .../Inactive/TypeInvariants/src/ops.adb | 8 +-- .../Inactive/TypeInvariants/src/ops.ads | 14 ++--- .../Consolidation/And/src/andthen.ads | 1 - .../Consolidation/And/src/test_andthen_v0.adb | 2 - .../Consolidation/And/src/test_andthen_v1.adb | 2 - .../Consolidation/And/src/test_andthen_v2.adb | 2 - .../decision/Consolidation/Or/src/orelse.ads | 1 - .../Consolidation/Or/src/test_orelse_v0.adb | 2 - .../Consolidation/Or/src/test_orelse_v1.adb | 1 - .../Consolidation/Or/src/test_orelse_v2.adb | 2 - .../PrecondInBody/src/test_ranges_invalid.adb | 1 - .../PrecondInBody/src/test_ranges_overlap.adb | 1 - .../Qualif/Ada/decision/Exemptions/extra.opt | 2 +- .../If_For_If_Case/src/sensors-status.adb | 1 - .../If_For_If_Case/src/test_broken.adb | 18 +++--- .../If_For_If_Case/src/test_check.adb | 18 +++--- .../If_For_If_Case/src/test_f_ff.adb | 4 +- .../If_For_If_Case/src/test_fu_ff.adb | 10 ++-- .../If_For_If_Case/src/test_fu_fu.adb | 10 ++-- .../If_For_If_Case/src/test_fu_tx.adb | 8 +-- .../If_For_If_Case/src/test_ok.adb | 4 +- .../If_For_If_Case/src/test_ok_brok.adb | 8 +-- .../If_For_If_Case/src/test_ok_check.adb | 8 +-- .../If_For_If_Case/src/test_ok_check_brok.adb | 8 +-- .../If_For_If_Case/src/test_t_0.adb | 2 +- .../If_For_If_Case/src/test_und_check.adb | 10 ++-- .../If_For_If_Case/src/test_und_ok.adb | 8 +-- .../If_For_If_Case/src/test_und_ok_brok.adb | 10 ++-- .../If_For_If_Case/src/test_und_ok_check.adb | 8 +-- .../If_For_If_Case/src/test_undecide.adb | 4 +- .../While_If1/src/slists-count.ads | 1 - .../While_If1/src/test_iff.adb | 1 - .../While_If1/src/test_ift.adb | 1 - .../While_If1/src/test_iftf.adb | 13 ++--- .../While_If1/src/test_noentry.adb | 1 - .../While_If4/src/doif_fx_ff.adb | 1 - .../While_If4/src/doif_fx_ft.adb | 1 - .../While_If4/src/doif_fx_tx.adb | 1 - .../While_If4/src/doif_tf_ff.adb | 1 - .../While_If4/src/doif_tf_ft.adb | 1 - .../While_If4/src/doif_tf_tx.adb | 1 - .../While_If4/src/doif_tt_xx.adb | 1 - .../While_If4/src/test_df_df.adb | 1 - .../While_If4/src/test_df_dt.adb | 3 +- .../While_If4/src/test_df_fu.adb | 7 +-- .../While_If4/src/test_fu_dt.adb | 5 +- .../While_If4/src/test_fu_fu.adb | 9 ++- .../While_If4/src/test_fx_ff.adb | 1 - .../While_If4/src/test_fx_ft.adb | 1 - .../While_If4/src/test_fx_tx.adb | 1 - .../While_If4/src/test_tf_ff.adb | 1 - .../While_If4/src/test_tf_ft.adb | 1 - .../While_If4/src/test_tf_tx.adb | 1 - .../While_If4/src/test_tt_xx.adb | 1 - .../While_If_Case_If/src/slists-forall.adb | 1 - .../While_If_Case_If/src/slists-forall.ads | 1 - .../While_If_Case_If/src/test_act_inh.adb | 1 - .../While_If_Case_If/src/test_activate.adb | 7 +-- .../While_If_Case_If/src/test_f_0_0.adb | 1 - .../While_If_Case_If/src/test_fu_ff_0.adb | 1 - .../While_If_Case_If/src/test_fu_ft_0.adb | 1 - .../While_If_Case_If/src/test_fu_fu_0.adb | 5 +- .../While_If_Case_If/src/test_fu_fu_ff.adb | 5 +- .../While_If_Case_If/src/test_fu_fu_ft.adb | 5 +- .../While_If_Case_If/src/test_fu_fu_fu.adb | 7 +-- .../While_If_Case_If/src/test_fu_fu_tx.adb | 5 +- .../While_If_Case_If/src/test_fu_tx_0.adb | 1 - .../While_If_Case_If/src/test_fu_tx_ff.adb | 7 +-- .../While_If_Case_If/src/test_fu_tx_ft.adb | 7 +-- .../While_If_Case_If/src/test_fu_tx_tx.adb | 7 +-- .../While_If_Case_If/src/test_inhibit.adb | 1 - .../While_If_Case_If/src/test_nocase.adb | 1 - .../While_If_Case_If/src/test_noentry.adb | 1 - .../While_If_Case_If/src/test_noinhibit.adb | 7 +-- .../decision/MixedConstructs/src/sensors.adb | 2 - .../decision/MixedConstructs/src/sensors.ads | 1 - .../decision/MixedConstructs/src/slists.adb | 2 +- .../decision/MixedConstructs/src/vbufs.ads | 1 - .../Robustness/Contracts/CondExpr/src/ops.ads | 2 +- .../Contracts/MultiMembership/src/ops.ads | 4 +- .../Contracts/QuantifiedExpr/src/ops.ads | 4 +- .../Robustness/InlineSequence/src/ops.adb | 10 ++-- .../MultiLineDecisions/And/If/src/andthen.adb | 2 - .../And/While/src/andthen.adb | 2 - .../MultiLineDecisions/Or/If/src/orelse.adb | 2 - .../Or/While/src/orelse.adb | 2 - .../Checks/src/test_register1.adb | 1 - .../Checks/src/test_register2.adb | 2 - .../Expr/src/test_register1.adb | 1 - .../MultiStmtLines/Straight/src/register.adb | 2 +- .../Straight/src/test_register2.adb | 1 - .../Robustness/MultiStmtLines/src/darts.ads | 2 +- .../MultiStmtLines/src/register.ads | 2 - .../Robustness/Ustrings/src/basic.adb | 1 - .../Robustness/Ustrings/src/basic.ads | 5 +- .../decision/Robustness/Ustrings/src/ops.ads | 6 +- .../Robustness/Ustrings/src/test_abab_tf.adb | 2 +- .../Robustness/Ustrings/src/test_basic_f.adb | 1 - .../Robustness/Ustrings/src/test_basic_t.adb | 1 - .../Robustness/Ustrings/src/test_basic_tf.adb | 1 - .../IfExpr/ComplexInDecision/src/test_1.adb | 2 +- .../IfExpr/ComplexInDecision/src/test_2.adb | 2 +- .../IfExpr/ComplexInDecision/src/test_3.adb | 2 +- .../1_Core/IfExpr/SimpleCtl/src/test_f.adb | 1 - .../1_Core/IfExpr/SimpleCtl/src/test_t.adb | 1 - .../1_Core/IfExpr/SimpleCtl/src/test_tf.adb | 2 - .../Qualif/Ada/mcdc/1_Core/IfExpr/extra.opt | 2 +- .../1_Core/NoEval/ShortCut/src/andidor.adb | 1 - .../Operands/ArrayAggregates/src/pools.ads | 1 - .../1_Core/Operands/Attributes/src/fuand.ads | 3 - .../Operands/Attributes/src/fuand_helper.adb | 1 - .../1_Core/Operands/Attributes/src/fuor.ads | 3 - .../Operands/Attributes/src/fuor_helper.adb | 1 - .../1_Core/Operands/BitOrdered/src/fuand.ads | 6 +- .../Operands/BitOrdered/src/fuand_helper.adb | 1 - .../1_Core/Operands/BitOrdered/src/fuor.ads | 2 +- .../Operands/BitOrdered/src/fuor_helper.adb | 1 - .../Operands/Components/src/fuand_helper.adb | 1 - .../Operands/Components/src/fuor_helper.adb | 1 - .../1_Core/Operands/Concats/src/fuand.ads | 1 - .../Operands/Concats/src/fuand_helper.adb | 1 - .../mcdc/1_Core/Operands/Concats/src/fuor.ads | 3 - .../Operands/Concats/src/fuor_helper.adb | 1 - .../1_Core/Operands/EnumOps/src/fuand.ads | 6 +- .../Operands/EnumOps/src/fuand_helper.adb | 3 +- .../mcdc/1_Core/Operands/EnumOps/src/fuor.ads | 6 +- .../Operands/EnumOps/src/fuor_helper.adb | 1 - .../1_Core/Operands/FixedOps/src/fuand.ads | 10 ++-- .../Operands/FixedOps/src/fuand_helper.adb | 3 +- .../1_Core/Operands/FixedOps/src/fuor.ads | 10 ++-- .../Operands/FixedOps/src/fuor_helper.adb | 1 - .../1_Core/Operands/FloatOps/src/fuand.ads | 12 ++-- .../Operands/FloatOps/src/fuand_helper.adb | 3 +- .../1_Core/Operands/FloatOps/src/fuor.ads | 12 ++-- .../Operands/FloatOps/src/fuor_helper.adb | 1 - .../1_Core/Operands/IntChar/src/fuand.ads | 20 +++---- .../Operands/IntChar/src/fuand_helper.adb | 3 +- .../mcdc/1_Core/Operands/IntChar/src/fuor.ads | 20 +++---- .../Operands/IntChar/src/fuor_helper.adb | 1 - .../Operands/Mixed/AttrSlice/src/starts.adb | 1 - .../Mixed/AttrSliceAggr/src/starts.adb | 1 - .../mcdc/1_Core/Operands/Mods/src/fuand.ads | 3 - .../1_Core/Operands/Mods/src/fuand_helper.adb | 1 - .../mcdc/1_Core/Operands/Mods/src/fuor.ads | 3 - .../1_Core/Operands/Mods/src/fuor_helper.adb | 1 - .../mcdc/1_Core/Operands/Packed/src/fuand.ads | 4 +- .../Operands/Packed/src/fuand_helper.adb | 3 +- .../mcdc/1_Core/Operands/Packed/src/fuor.ads | 4 +- .../Operands/Packed/src/fuor_helper.adb | 1 - .../Operands/ParameterModes/src/ops.adb | 22 ++++---- .../Operands/ParameterModes/src/ops.ads | 6 +- .../1_Core/Operands/ParameterModes/test.opt | 2 +- .../mcdc/1_Core/Operands/Placed/src/fuand.ads | 4 +- .../Operands/Placed/src/fuand_helper.adb | 3 +- .../mcdc/1_Core/Operands/Placed/src/fuor.ads | 4 +- .../Operands/Placed/src/fuor_helper.adb | 1 - .../Operands/Ranges/src/fuand_helper.adb | 1 - .../Operands/Ranges/src/fuor_helper.adb | 1 - .../Operands/RecordAggregates/src/fuand.ads | 14 ++--- .../RecordAggregates/src/fuand_helper.adb | 3 +- .../Operands/RecordAggregates/src/fuor.ads | 14 ++--- .../RecordAggregates/src/fuor_helper.adb | 1 - .../Subtypes/src/andthen_variants.ads | 2 +- .../Operands/Subtypes/src/test_andthen_f.adb | 1 - .../Operands/Uindexed/src/fuand_helper.adb | 3 +- .../Operands/Uindexed/src/fuor_helper.adb | 1 - .../1_Core/Operands/Ustrings/src/fuand.ads | 14 ++--- .../Operands/Ustrings/src/fuand_helper.adb | 3 +- .../1_Core/Operands/Ustrings/src/fuor.adb | 2 +- .../1_Core/Operands/Ustrings/src/fuor.ads | 22 ++++---- .../Operands/Ustrings/src/fuor_helper.adb | 1 - .../1_Core/Operands/Xfunctions/src/fuand.adb | 3 +- .../1_Core/Operands/Xfunctions/src/fuand.ads | 14 ++--- .../Operands/Xfunctions/src/fuand_helper.adb | 10 ++-- .../mcdc/1_Core/Operands/src/test_fuand_0.adb | 1 - .../mcdc/1_Core/Operands/src/test_fuand_a.adb | 1 - .../1_Core/Operands/src/test_fuand_ab.adb | 1 - .../mcdc/1_Core/Operands/src/test_fuand_b.adb | 1 - .../mcdc/1_Core/Operands/src/test_fuand_f.adb | 1 - .../mcdc/1_Core/Operands/src/test_fuand_t.adb | 1 - .../mcdc/1_Core/Operands/src/test_fuor_a.adb | 1 - .../mcdc/1_Core/Operands/src/test_fuor_ab.adb | 1 - .../mcdc/1_Core/Operands/src/test_fuor_b.adb | 1 - .../mcdc/1_Core/Operands/src/test_fuor_f.adb | 1 - .../mcdc/1_Core/Operands/src/test_fuor_t.adb | 1 - .../Topologies/And/Aggregate/src/andthen.adb | 3 - .../Topologies/And/Assignment/src/andthen.adb | 1 - .../Topologies/And/DeclInit/src/andthen.adb | 3 - .../Topologies/And/IfExprCtl/src/andthen.adb | 1 - .../1_Core/Topologies/And/IfExprCtl/test.opt | 2 +- .../Topologies/And/Index/src/andthen.adb | 1 - .../And/Pragmas/DebugBody/src/passand.adb | 1 - .../Topologies/And/Pragmas/Mix/src/points.adb | 2 - .../And/Pragmas/PreBody/src/passand.adb | 1 - .../And/Pragmas/PreDecl/src/passand.adb | 1 - .../Topologies/And/Return/src/andthen.adb | 1 - .../Topologies/And/Xfunction/src/andthen.adb | 1 - .../Topologies/And/Xfunction/src/andthen.ads | 4 +- .../Topologies/And/Xreturn/src/andthen.adb | 1 - .../1_Core/Topologies/And/Xreturn/test.opt | 2 +- .../Topologies/And/src/test_andthen_f.adb | 1 - .../Topologies/AndCOr/Actual/src/andcor.adb | 2 +- .../AndCOr/Aggregate/src/andcor.adb | 3 - .../AndCOr/Assignment/src/andcor.adb | 5 +- .../Topologies/AndCOr/Case/src/andcor.adb | 4 +- .../Topologies/AndCOr/DeclInit/src/andcor.adb | 3 - .../AndCOr/Discriminant/src/andcor.adb | 6 +- .../Topologies/AndCOr/Exit/src/andcor.adb | 4 +- .../Topologies/AndCOr/If/src/andcor.adb | 4 +- .../Topologies/AndCOr/IfExprCtl/test.opt | 2 +- .../Topologies/AndCOr/Index/src/andcor.adb | 2 +- .../Topologies/AndCOr/While/src/andcor.adb | 4 +- .../Topologies/AndCOr/Xreturn/src/andcor.adb | 1 - .../1_Core/Topologies/AndCOr/Xreturn/test.opt | 2 +- .../AndIdOr/Aggregate/src/andidor.adb | 1 - .../AndIdOr/Assignment/src/andidor.adb | 1 - .../AndIdOr/DeclInit/src/andidor.adb | 1 - .../AndIdOr/Discriminant/src/andidor.adb | 2 +- .../Topologies/AndIdOr/IfExprCtl/test.opt | 2 +- .../AndIdOr/Xreturn/src/andidor.adb | 1 - .../Topologies/AndIdOr/Xreturn/test.opt | 2 +- .../AndNot/Aggregate/src/andnot.adb | 3 - .../AndNot/Assignment/src/andnot.adb | 1 - .../Topologies/AndNot/DeclInit/src/andnot.adb | 3 - .../Topologies/AndNot/IfExprCtl/test.opt | 2 +- .../Topologies/AndNot/Index/src/andnot.adb | 1 - .../Topologies/AndNot/Return/src/andnot.adb | 1 - .../Topologies/AndNot/Xreturn/src/andnot.adb | 1 - .../1_Core/Topologies/AndNot/Xreturn/test.opt | 2 +- .../Topologies/AndNot/src/test_andnot_f.adb | 1 - .../AndpOrp/Assignment/src/andporp.adb | 1 - .../Topologies/AndpOrp/IfExprCtl/test.opt | 2 +- .../Topologies/AndpOrp/Index/src/andporp.adb | 1 - .../AndpOrp/Xfunction/src/andporp.ads | 2 +- .../AndpOrp/Xreturn/src/andporp.adb | 1 - .../Topologies/AndpOrp/Xreturn/test.opt | 2 +- .../1_Core/Topologies/AndpOrp/src/andporp.ads | 6 +- .../Obvious/src/andporpand_coupled.adb | 47 ++++++++-------- .../Obvious/src/andporpand_coupled.ads | 1 - .../Obvious/src/andporpand_coupled_alt.adb | 45 ++++++++------- .../Obvious/src/andporpand_coupled_alt.ads | 1 - .../Obvious/src/test_andporpand_coupled_2.adb | 2 - .../Obvious/src/test_andporpand_coupled_3.adb | 1 - .../src/test_andporpand_coupled_all.adb | 1 - .../src/test_andporpand_coupled_alt_2.adb | 1 - .../src/test_andporpand_coupled_alt_3.adb | 1 - .../src/test_andporpand_coupled_alt_all.adb | 1 - .../Coupled/cc4/src/test_cc4_all.adb | 2 - .../Coupled/cc4/src/test_cc4_masking.adb | 2 - .../1_Core/Topologies/Diamonds/c3/src/c3.ads | 1 - .../Topologies/Diamonds/c3/src/test_c3_v1.adb | 2 - .../Topologies/Diamonds/c3/src/test_c3_v2.adb | 2 - .../Topologies/Diamonds/c3/src/test_c3_v3.adb | 2 - .../Topologies/Diamonds/c3/src/test_c3_v4.adb | 2 - .../Topologies/Diamonds/c3/src/test_c3_v5.adb | 2 - .../NotAnd/Aggregate/src/notand.adb | 3 - .../NotAnd/Assignment/src/notand.adb | 1 - .../Topologies/NotAnd/DeclInit/src/notand.adb | 3 - .../Topologies/NotAnd/IfExprCtl/test.opt | 2 +- .../Topologies/NotAnd/Index/src/notand.adb | 1 - .../Topologies/NotAnd/Return/src/notand.adb | 1 - .../Topologies/NotAnd/Xreturn/src/notand.adb | 1 - .../1_Core/Topologies/NotAnd/Xreturn/test.opt | 2 +- .../Topologies/NotAnd/src/test_notand_f.adb | 1 - .../NotAndNot/Aggregate/src/notandnot.adb | 3 - .../NotAndNot/Assignment/src/notandnot.adb | 1 - .../NotAndNot/DeclInit/src/notandnot.adb | 3 - .../Topologies/NotAndNot/IfExprCtl/test.opt | 2 +- .../NotAndNot/Index/src/notandnot.adb | 1 - .../NotAndNot/Return/src/notandnot.adb | 1 - .../NotAndNot/Xreturn/src/notandnot.adb | 1 - .../Topologies/NotAndNot/Xreturn/test.opt | 2 +- .../NotAndNot/src/test_notandnot_f.adb | 1 - .../Topologies/NotOr/Aggregate/src/notor.adb | 3 - .../Topologies/NotOr/Assignment/src/notor.adb | 1 - .../Topologies/NotOr/DeclInit/src/notor.adb | 3 - .../1_Core/Topologies/NotOr/If/src/notor.adb | 1 - .../Topologies/NotOr/IfExprCtl/test.opt | 2 +- .../Topologies/NotOr/Index/src/notor.adb | 1 - .../Topologies/NotOr/Return/src/notor.adb | 1 - .../Topologies/NotOr/Xreturn/src/notor.adb | 1 - .../1_Core/Topologies/NotOr/Xreturn/test.opt | 2 +- .../NotOrNot/Aggregate/src/notornot.adb | 3 - .../NotOrNot/Assignment/src/notornot.adb | 1 - .../NotOrNot/DeclInit/src/notornot.adb | 3 - .../Topologies/NotOrNot/If/src/notornot.adb | 1 - .../Topologies/NotOrNot/IfExprCtl/test.opt | 2 +- .../NotOrNot/Index/src/notornot.adb | 1 - .../NotOrNot/Return/src/notornot.adb | 1 - .../NotOrNot/Xreturn/src/notornot.adb | 1 - .../Topologies/NotOrNot/Xreturn/test.opt | 2 +- .../NotOrNot/src/test_notornot_0.adb | 1 - .../Topologies/Or/Aggregate/src/orelse.adb | 3 - .../Topologies/Or/Assignment/src/orelse.adb | 1 - .../Topologies/Or/DeclInit/src/orelse.adb | 3 - .../1_Core/Topologies/Or/If/src/orelse.adb | 1 - .../1_Core/Topologies/Or/IfExprCtl/test.opt | 2 +- .../1_Core/Topologies/Or/Index/src/orelse.adb | 1 - .../Or/Pragmas/DebugBody/src/passor.adb | 1 - .../Or/Pragmas/PreBody/src/passor.adb | 1 - .../Or/Pragmas/PreDecl/src/passor.adb | 1 - .../Topologies/Or/Return/src/orelse.adb | 1 - .../Topologies/Or/Xreturn/src/orelse.adb | 1 - .../1_Core/Topologies/Or/Xreturn/test.opt | 2 +- .../Topologies/OrNot/Aggregate/src/ornot.adb | 3 - .../Topologies/OrNot/Assignment/src/ornot.adb | 1 - .../Topologies/OrNot/DeclInit/src/ornot.adb | 3 - .../1_Core/Topologies/OrNot/If/src/ornot.adb | 1 - .../Topologies/OrNot/IfExprCtl/test.opt | 2 +- .../Topologies/OrNot/Index/src/ornot.adb | 1 - .../Topologies/OrNot/Return/src/ornot.adb | 1 - .../Topologies/OrNot/Xreturn/src/ornot.adb | 1 - .../1_Core/Topologies/OrNot/Xreturn/test.opt | 2 +- .../Topologies/OrNot/src/test_ornot_0.adb | 1 - .../pAndpOr/Assignment/src/pandpor.adb | 1 - .../Topologies/pAndpOr/IfExprCtl/test.opt | 2 +- .../pAndpOr/Xreturn/src/pandpor.adb | 1 - .../Topologies/pAndpOr/Xreturn/test.opt | 2 +- .../Topologies/pAndpOr/src/test_pandpor_0.adb | 1 - .../Topologies/pAndpOr/src/test_pandpor_a.adb | 1 - .../pAndpOr/src/test_pandpor_ab.adb | 1 - .../pAndpOr/src/test_pandpor_abc.adb | 1 - .../pAndpOr/src/test_pandpor_abc_sc.adb | 1 - .../pAndpOr/src/test_pandpor_ac.adb | 1 - .../Topologies/pAndpOr/src/test_pandpor_b.adb | 1 - .../Topologies/pAndpOr/src/test_pandpor_c.adb | 1 - .../pAndpOr/src/test_pandpor_c_mask.adb | 1 - .../pAndpOr/src/test_pandpor_c_sc.adb | 1 - .../pAndpOr/src/test_pandpor_cb.adb | 1 - .../Topologies/pAndpOr/src/test_pandpor_f.adb | 1 - .../Topologies/pAndpOr/src/test_pandpor_t.adb | 1 - .../Assignment/src/porpandporp.adb | 1 - .../pOrpAndpOrp/For/src/porpandporp.adb | 1 - .../Topologies/pOrpAndpOrp/IfExprCtl/test.opt | 2 +- .../pOrpAndpOrp/Index/src/porpandporp.adb | 1 - .../pOrpAndpOrp/Xreturn/src/porpandporp.adb | 1 - .../Topologies/pOrpAndpOrp/Xreturn/test.opt | 2 +- .../Inactive/TypeInvariants/src/ops.adb | 6 +- .../Inactive/TypeInvariants/src/ops.ads | 12 ++-- .../mcdc/Consolidation/And/src/andthen.ads | 2 - .../Consolidation/And/src/test_andthen_v0.adb | 2 - .../Consolidation/And/src/test_andthen_v1.adb | 2 - .../Consolidation/And/src/test_andthen_v2.adb | 2 - .../Consolidation/And/src/test_andthen_v3.adb | 2 - .../Consolidation/AndAB_OrCD/src/a1o2.adb | 2 - .../Ada/mcdc/Consolidation/Or/src/orelse.ads | 2 - .../Consolidation/Or/src/test_orelse_v0.adb | 2 - .../Consolidation/Or/src/test_orelse_v1.adb | 2 - .../Consolidation/Or/src/test_orelse_v2.adb | 2 - .../Consolidation/Or/src/test_orelse_v3.adb | 2 - .../Consolidation/pOrpAnd/src/porpand.adb | 1 - .../pOrpAnd/src/test_porpand_v1.adb | 2 - .../pOrpAnd/src/test_porpand_v2.adb | 2 - .../pOrpAnd/src/test_porpand_v3.adb | 2 - .../pOrpAnd/src/test_porpand_v4.adb | 1 - .../pOrpAnd/src/test_porpand_v5.adb | 2 - .../src/test_ranges_invalid_a.adb | 1 - .../src/test_ranges_invalid_b.adb | 1 - .../src/test_ranges_no_overlap.adb | 1 - .../PrecondInBody/src/test_ranges_overlap.adb | 1 - .../Qualif/Ada/mcdc/Exemptions/extra.opt | 2 +- .../If_For_If_Case/src/sensors-status.adb | 1 - .../If_For_If_Case/src/test_f_ff.adb | 4 +- .../If_For_If_Case/src/test_fu_ff.adb | 10 ++-- .../If_For_If_Case/src/test_fu_tx.adb | 8 +-- .../If_For_If_Case/src/test_ok.adb | 4 +- .../If_For_If_Case/src/test_ok_check_brok.adb | 8 +-- .../If_For_If_Case/src/test_t_0.adb | 2 +- .../If_For_If_Case/src/test_und_ok.adb | 8 +-- .../If_For_If_Case/src/test_und_ok_brok.adb | 10 ++-- .../If_For_If_Case/src/test_undecide.adb | 4 +- .../While_If4/src/doif_fx_ff.adb | 1 - .../While_If4/src/doif_fx_ft.adb | 1 - .../While_If4/src/doif_fx_tx.adb | 1 - .../While_If4/src/doif_tf_ff.adb | 1 - .../While_If4/src/doif_tf_ft.adb | 1 - .../While_If4/src/doif_tf_tx.adb | 1 - .../While_If4/src/doif_tt_xx.adb | 1 - .../While_If4/src/test_df_df.adb | 1 - .../While_If4/src/test_df_dt.adb | 3 +- .../While_If4/src/test_df_fu.adb | 7 +-- .../While_If4/src/test_fu_dt.adb | 5 +- .../While_If4/src/test_fu_fu.adb | 9 ++- .../While_If4/src/test_fx_ff.adb | 1 - .../While_If4/src/test_fx_ft.adb | 1 - .../While_If4/src/test_fx_tx.adb | 1 - .../While_If4/src/test_tf_ff.adb | 1 - .../While_If4/src/test_tf_ft.adb | 1 - .../While_If4/src/test_tf_tx.adb | 1 - .../While_If4/src/test_tt_xx.adb | 1 - .../While_If_Case_If/src/slists-forall.adb | 1 - .../While_If_Case_If/src/slists-forall.ads | 1 - .../While_If_Case_If/src/test_act_inh.adb | 1 - .../While_If_Case_If/src/test_activate.adb | 1 - .../While_If_Case_If/src/test_f_0_0.adb | 1 - .../While_If_Case_If/src/test_fu_a_a.adb | 1 - .../While_If_Case_If/src/test_fu_a_ff.adb | 1 - .../While_If_Case_If/src/test_fu_a_ft.adb | 1 - .../While_If_Case_If/src/test_fu_a_tx.adb | 1 - .../While_If_Case_If/src/test_fu_b_0.adb | 1 - .../While_If_Case_If/src/test_fu_ff_0.adb | 1 - .../While_If_Case_If/src/test_fu_ft_0.adb | 1 - .../While_If_Case_If/src/test_fu_tx_0.adb | 1 - .../While_If_Case_If/src/test_fu_tx_ff.adb | 7 +-- .../While_If_Case_If/src/test_fu_tx_ft.adb | 7 +-- .../While_If_Case_If/src/test_fu_tx_tx.adb | 7 +-- .../While_If_Case_If/src/test_inhibit.adb | 1 - .../While_If_Case_If/src/test_nocase.adb | 1 - .../While_If_Case_If/src/test_noentry.adb | 1 - .../While_If_Case_If/src/test_noinhibit.adb | 7 +-- .../Ada/mcdc/MixedConstructs/src/sensors.adb | 2 - .../Ada/mcdc/MixedConstructs/src/sensors.ads | 1 - .../Ada/mcdc/MixedConstructs/src/slists.adb | 2 +- .../Ada/mcdc/MixedConstructs/src/vbufs.ads | 1 - .../If_And_Eq_Or/src/and_eq_or.adb | 1 - .../If_And_Eq_Or/src/and_eq_or.ads | 2 - .../If_And_Eq_Or/src/test_ac_t.adb | 1 - .../If_And_Eq_Or/src/test_af.adb | 1 - .../If_And_Eq_Or/src/test_at.adb | 1 - .../If_And_Eq_Or/src/test_bd_f.adb | 1 - .../If_And_Eq_Or/src/test_bf.adb | 1 - .../If_And_Eq_Or/src/test_fc.adb | 1 - .../If_And_Eq_Or/src/test_ff.adb | 1 - .../If_And_Eq_Or/src/test_fuf.adb | 1 - .../If_And_Eq_Or/src/test_fut.adb | 1 - .../If_And_Eq_Or/src/test_tc.adb | 1 - .../If_And_Eq_Or/src/test_td.adb | 1 - .../If_And_Eq_Or/src/test_tfu.adb | 1 - .../If_And_Eq_Or/src/test_tt.adb | 1 - .../MultiDecisionExpr/Mix_ABCDEZT/src/mix.adb | 2 - .../Mix_ABCDEZT/src/test_1.adb | 4 +- .../Ret_Or_Eq_And_Not/src/test_ac.adb | 2 - .../Ret_Or_Eq_And_Not/src/test_tt.adb | 2 - .../AndAB_AndAB/src/test_a1a1_v2.adb | 1 - .../TwoFormals/AndAB_AndCD/src/a1a2.adb | 3 +- .../TwoFormals/AndAB_AndCD/src/a1a2.ads | 1 - .../AndAB_AndCD/src/test_a1a2_a_c.adb | 1 - .../AndAB_AndCD/src/test_a1a2_a_cd.adb | 1 - .../AndAB_AndCD/src/test_a1a2_a_d.adb | 1 - .../AndAB_AndCD/src/test_a1a2_a_f.adb | 1 - .../AndAB_AndCD/src/test_a1a2_a_t.adb | 1 - .../AndAB_AndCD/src/test_a1a2_ab_c.adb | 1 - .../AndAB_AndCD/src/test_a1a2_ab_cd.adb | 1 - .../AndAB_AndCD/src/test_a1a2_ab_d.adb | 1 - .../AndAB_AndCD/src/test_a1a2_ab_f.adb | 1 - .../AndAB_AndCD/src/test_a1a2_ab_t.adb | 1 - .../AndAB_AndCD/src/test_a1a2_b_c.adb | 1 - .../AndAB_AndCD/src/test_a1a2_b_cd.adb | 1 - .../AndAB_AndCD/src/test_a1a2_b_d.adb | 1 - .../AndAB_AndCD/src/test_a1a2_b_f.adb | 1 - .../AndAB_AndCD/src/test_a1a2_b_t.adb | 1 - .../AndAB_AndCD/src/test_a1a2_f_c.adb | 1 - .../AndAB_AndCD/src/test_a1a2_f_cd.adb | 1 - .../AndAB_AndCD/src/test_a1a2_f_d.adb | 1 - .../AndAB_AndCD/src/test_a1a2_f_f.adb | 3 +- .../AndAB_AndCD/src/test_a1a2_f_t.adb | 1 - .../AndAB_AndCD/src/test_a1a2_t_c.adb | 1 - .../AndAB_AndCD/src/test_a1a2_t_cd.adb | 1 - .../AndAB_AndCD/src/test_a1a2_t_d.adb | 1 - .../AndAB_AndCD/src/test_a1a2_t_f.adb | 1 - .../AndAB_AndCD/src/test_a1a2_t_t.adb | 1 - .../TwoFormals/AndAB_OrCD/src/a1o2.adb | 1 - .../TwoFormals/AndAB_OrCD/src/a1o2.ads | 1 - .../AndAB_OrCD/src/test_a1o2_a_c.adb | 1 - .../AndAB_OrCD/src/test_a1o2_a_cd.adb | 1 - .../AndAB_OrCD/src/test_a1o2_a_d.adb | 1 - .../AndAB_OrCD/src/test_a1o2_a_f.adb | 1 - .../AndAB_OrCD/src/test_a1o2_a_t.adb | 1 - .../AndAB_OrCD/src/test_a1o2_ab_c.adb | 1 - .../AndAB_OrCD/src/test_a1o2_ab_cd.adb | 1 - .../AndAB_OrCD/src/test_a1o2_ab_d.adb | 1 - .../AndAB_OrCD/src/test_a1o2_ab_f.adb | 1 - .../AndAB_OrCD/src/test_a1o2_ab_t.adb | 1 - .../AndAB_OrCD/src/test_a1o2_b_c.adb | 1 - .../AndAB_OrCD/src/test_a1o2_b_cd.adb | 1 - .../AndAB_OrCD/src/test_a1o2_b_d.adb | 1 - .../AndAB_OrCD/src/test_a1o2_b_f.adb | 1 - .../AndAB_OrCD/src/test_a1o2_b_t.adb | 1 - .../AndAB_OrCD/src/test_a1o2_f_c.adb | 1 - .../AndAB_OrCD/src/test_a1o2_f_cd.adb | 1 - .../AndAB_OrCD/src/test_a1o2_f_d.adb | 1 - .../AndAB_OrCD/src/test_a1o2_f_f.adb | 3 +- .../AndAB_OrCD/src/test_a1o2_f_t.adb | 1 - .../AndAB_OrCD/src/test_a1o2_t_c.adb | 1 - .../AndAB_OrCD/src/test_a1o2_t_cd.adb | 1 - .../AndAB_OrCD/src/test_a1o2_t_d.adb | 1 - .../AndAB_OrCD/src/test_a1o2_t_f.adb | 1 - .../AndAB_OrCD/src/test_a1o2_t_t.adb | 1 - .../MultiDecisionLine/src/evals.adb | 1 - .../MultiDecisionLine/src/evals.ads | 1 - .../MultiLineDecisions/And/If/src/andthen.adb | 2 - .../And/Return/src/andthen.adb | 2 - .../And/src/test_andthen_t.adb | 1 - .../Or/src/test_orelse_t.adb | 1 - .../Recurse/And/src/constructors.adb | 5 +- .../Recurse/And/src/exprs-e_and.adb | 2 +- .../Recurse/Andor_RA/src/constructors.adb | 3 +- .../Recurse/Andor_RC/src/constructors.adb | 3 +- .../Robustness/Recurse/src/exprs-e_val.adb | 5 +- .../Robustness/Recurse/src/exprs-e_val.ads | 1 - .../Ada/mcdc/Robustness/Recurse/src/exprs.ads | 5 +- .../Pragmas/Active/src/support_pragmas.adb | 1 - .../Pragmas/Active/test.opt | 2 +- .../DiscreteSubtypeDefs/src/defs.adb | 2 +- .../DiscreteSubtypeDefs/src/defs.ads | 2 +- .../DiscreteSubtypeDefs/src/test_no.adb | 4 -- .../03_DeclsAndTypes/DynObjects/src/heap.adb | 2 +- .../03_DeclsAndTypes/DynObjects/src/heap.ads | 4 +- .../DynObjects/src/test_heap_0.adb | 1 - .../DynObjects/src/test_heap_all.adb | 1 - .../DynObjects/src/test_heap_neg.adb | 1 - .../DynObjects/src/test_heap_pos.adb | 1 - .../DynObjects/src/test_vectors_0.adb | 3 +- .../DynObjects/src/test_vectors_neg.adb | 3 +- .../DynObjects/src/test_vectors_pos.adb | 3 +- .../DynObjects/src/vectors.adb | 10 ++-- .../DynObjects/src/vectors.ads | 6 +- .../03_DeclsAndTypes/DynObjects/test.opt | 2 +- .../ObjectDecls/src/integer_swap.adb | 1 - .../ObjectDecls/src/matrix_swap.adb | 1 - .../ObjectDecls/src/private_swap.adb | 1 - .../ObjectDecls/src/record_derived_swap.adb | 1 - .../ObjectDecls/src/record_impl_init_swap.adb | 1 - .../ObjectDecls/src/record_swap.adb | 1 - .../src/test_object_declarations_full.adb | 12 ++-- .../src/test_object_declarations_no.adb | 1 - .../src/test_object_declarations_part_1.adb | 6 +- .../src/test_subtype_indications_full.adb | 5 -- .../src/test_subtype_indications_no.adb | 5 -- .../src/test_subtype_indications_part_1.adb | 5 -- .../src/test_subtype_indications_part_2.adb | 5 -- .../SubtypeIndications/test.opt | 2 +- .../51_Assign/src/assignment_statements.adb | 1 - .../51_Assign/src/assignment_statements.ads | 1 - .../src/assignment_statements_elab.adb | 1 - .../src/assignment_statements_elab.ads | 1 - .../52_Null/src/null_statements.ads | 1 - .../57_Exit/src/exit_statements.adb | 1 - .../57_Exit/src/exit_statements.ads | 1 - .../57_Exit/src/exit_statements_support.ads | 1 - .../58_Goto/src/goto_statements_loop.adb | 1 - .../58_Goto/src/goto_statements_straight.adb | 1 - .../53_If/ELSE_Path/src/test_else_path.adb | 1 - .../53_If/Elab_ELSE/src/test_init_else.adb | 1 - .../53_If/Elab_ELSIF/src/test_init_elsif.adb | 1 - .../53_If/Elab_IF/src/test_init_if.adb | 1 - .../53_If/src/if_statements.adb | 1 - .../53_If/src/if_statements.ads | 1 - .../052_CompoundStmts/53_If/src/instances.ads | 1 - .../53_If/src/lib_if_statements.adb | 4 +- .../53_If/src/more_if_statements.adb | 1 - .../54_Case/src/case_statements.adb | 1 - .../54_Case/src/case_statements.ads | 1 - .../54_Case/src/case_statements_support.ads | 1 - .../54_Case/src/more_case_statements.adb | 1 - .../54_Case/src/more_case_statements.ads | 1 - .../550_Loop/Elab_0/src/test_init_loop.adb | 1 - .../550_Loop/Elab_Some/src/test_init_loop.adb | 1 - .../550_Loop/src/case_statements.adb | 1 - .../550_Loop/src/lib_loop_statements.adb | 6 +- .../550_Loop/src/loop_statements.adb | 1 - .../550_Loop/src/loop_statements.ads | 1 - .../550_Loop/src/loop_statements_support.ads | 1 - .../550_Loop/src/more_loop_statements.adb | 1 - .../550_Loop/src/more_loop_statements.ads | 1 - .../OfArray/EmptyArray/src/test_empty.adb | 4 +- .../OfArray/EmptyArray/src/values.adb | 2 +- .../OfArray/EmptyArray/src/values.ads | 4 +- .../OfArray/ObjectArray/src/values.adb | 4 +- .../OfArray/ObjectArray/src/values.ads | 6 +- .../OfArray/PackedArray/src/values.adb | 2 +- .../OfArray/PackedArray/src/values.ads | 6 +- .../OfArray/StraightIntArray/src/values.adb | 2 +- .../OfArray/StraightIntArray/src/values.ads | 2 +- .../OfArray/UncIntArray/src/values.adb | 2 +- .../OfArray/UncIntArray/src/values.ads | 2 +- .../552_Iteration/OfArray/extra.opt | 2 +- .../OfArray/src/test_values_arg.adb | 3 +- .../OfArray/src/test_values_arg_er.adb | 3 +- .../OfArray/src/test_values_arg_it0.adb | 3 +- .../OfArray/src/test_values_arg_it1.adb | 3 +- .../OfArray/src/test_values_gsa.adb | 1 - .../552_Iteration/OfArray/src/values-arg.adb | 4 +- .../552_Iteration/OfArray/src/values-arg.ads | 2 +- .../OfArray/src/values-global.adb | 4 +- .../56_Block/Plain/src/block_statements.adb | 1 - .../56_Block/Plain/src/block_statements.ads | 1 - .../CallSites/src/test_mycolors_0.adb | 1 - .../CallSites/src/test_mycolors_b.adb | 1 - .../CallSites/src/test_mycolors_g.adb | 1 - .../CallSites/src/test_mycolors_gb.adb | 1 - .../CallSites/src/test_mycolors_r.adb | 1 - .../CallSites/src/test_mycolors_rb.adb | 1 - .../CallSites/src/test_mycolors_rg.adb | 1 - .../CallSites/src/test_mycolors_rgb.adb | 1 - .../DeclsAndCalls/Nested/src/nest.adb | 56 +++++++++---------- .../Nested/src/test_nest_dlf.adb | 1 - .../Nested/src/test_nest_dlp.adb | 1 - .../Nested/src/test_nest_dpf.adb | 1 - .../Nested/src/test_nest_dpp.adb | 1 - .../Nested/src/test_nest_ilf.adb | 1 - .../Nested/src/test_nest_ilf_dlf.adb | 1 - .../Nested/src/test_nest_ilf_dlp.adb | 1 - .../Nested/src/test_nest_ilf_dpf.adb | 1 - .../Nested/src/test_nest_ilf_dpp.adb | 1 - .../Nested/src/test_nest_ilfpf.adb | 1 - .../Nested/src/test_nest_ipf.adb | 1 - .../Nested/src/test_nest_ipf_dlf.adb | 1 - .../Nested/src/test_nest_ipf_dlp.adb | 1 - .../Nested/src/test_nest_ipf_dpf.adb | 1 - .../Nested/src/test_nest_ipf_dpp.adb | 1 - .../Derived/Indicators/src/test_allneg.adb | 3 +- .../Derived/Indicators/src/test_allpos.adb | 3 +- .../Derived/Indicators/src/test_allzero.adb | 3 +- .../Derived/Indicators/src/test_mix1.adb | 5 +- .../Derived/Indicators/src/test_mix2.adb | 9 ++- .../Derived/Indicators/src/values.adb | 12 ++-- .../Derived/Indicators/src/values.ads | 18 +++--- .../Derived/Interfaces/src/i_objects.adb | 6 +- .../Derived/Interfaces/src/i_objects.ads | 22 ++++---- .../Derived/Interfaces/src/test_i_all_pos.adb | 9 ++- .../Derived/Interfaces/src/test_i_neg_pos.adb | 5 +- .../Interfaces/src/test_ti_all_all.adb | 17 +++--- .../Interfaces/src/test_ti_all_neg.adb | 13 ++--- .../Interfaces/src/test_ti_neg_pos.adb | 9 ++- .../Interfaces/src/test_ti_neg_zero.adb | 9 ++- .../Interfaces/src/test_ti_pos_neg.adb | 9 ++- .../Derived/Interfaces/src/ti_objects.adb | 10 ++-- .../Derived/Interfaces/src/ti_objects.ads | 28 +++++----- .../Derived/Simple/src/test_notes_dt.adb | 1 - .../No_Return/InBody/src/objects.adb | 8 +-- .../No_Return/InBody/src/objects.ads | 4 +- .../No_Return/LibLevel/src/objects.adb | 6 +- .../No_Return/LibLevel/src/objects.ads | 6 +- .../No_Return/Nested/src/objects.adb | 10 ++-- .../No_Return/Nested/src/objects.ads | 4 +- .../No_Return/src/test_objects_0.adb | 2 +- .../Null/CallsInFlow/src/ops.adb | 18 +++--- .../Null/CallsInFlow/src/ops.ads | 9 ++- .../Null/CallsInFlow/src/test_pv1_inc.adb | 2 - .../Null/CallsInFlow/src/test_pv1_nop1.adb | 2 - .../Null/CallsInFlow/src/test_pv1_nop3.adb | 1 - .../Null/CallsInFlow/src/test_pv2_inc.adb | 1 - .../Null/NullCompletion/src/objects.adb | 6 +- .../Null/NullCompletion/src/objects.ads | 6 +- .../Null/NullDefinition/src/objects.adb | 4 +- .../Null/NullDefinition/src/objects.ads | 8 +-- .../ParameterModes/InOut_Function/src/ops.adb | 10 ++-- .../ParameterModes/InOut_Function/test.opt | 2 +- .../InOut_Procedure/src/ops.adb | 10 ++-- .../In_Out_Function/src/ops.adb | 10 ++-- .../ParameterModes/In_Out_Function/test.opt | 2 +- .../In_Out_Procedure/src/ops.adb | 10 ++-- .../06_Subprograms/ParameterModes/src/ops.ads | 4 +- .../Return/Procedures/src/test_pret_full.adb | 1 - .../Return/Procedures/src/test_pret_part.adb | 1 - .../Xfunctions/Local/src/expr.adb | 8 +-- .../Xfunctions/Local/src/expr.ads | 2 +- .../Xfunctions/Local/src/test_1.adb | 1 - .../Xfunctions/Local/src/test_2.adb | 1 - .../Xfunctions/Local/src/test_3.adb | 1 - .../Xfunctions/Multiline/src/expr.ads | 6 +- .../Xfunctions/Singleline/src/expr.ads | 4 +- .../06_Subprograms/Xfunctions/extra.opt | 2 +- .../06_Subprograms/Xfunctions/src/values.adb | 2 +- .../07_Packages/DeclRegions/src/ops.ads | 14 ++--- .../DeferredConstants/src/environ.adb | 7 +-- .../DeferredConstants/src/environ.ads | 11 ++-- .../DeferredConstants/src/monitor.adb | 4 +- .../DeferredConstants/src/monitor.ads | 6 +- .../src/test_monitor_1cmp.adb | 2 +- .../src/test_monitor_2cmp.adb | 4 +- .../10_Structure/Subunits/src/test_ops_0.adb | 1 - .../10_Structure/Subunits/src/test_ops_i.adb | 1 - .../10_Structure/Subunits/src/test_ops_p.adb | 1 - .../10_Structure/Subunits/src/test_ops_pi.adb | 1 - .../10_Structure/Subunits/src/test_ops_v.adb | 1 - .../10_Structure/Subunits/src/test_ops_vi.adb | 1 - .../10_Structure/Subunits/src/test_ops_vp.adb | 1 - .../Subunits/src/test_ops_vpi.adb | 1 - .../And/Return/IndexCheck/src/fuand.adb | 4 +- .../And/Return/RangeCheck/src/fuand.adb | 4 +- .../And/Return/RemoteCheck/src/fuand.adb | 2 +- .../Flip/Return/IndexCheck/src/flip.adb | 4 +- .../Flip/Return/RangeCheck/src/flip.adb | 4 +- .../Flip/Return/RemoteCheck/src/flip.adb | 4 +- .../Or/Return/IndexCheck/src/fuor.adb | 4 +- .../Or/Return/RangeCheck/src/fuor.adb | 2 +- .../Or/Return/RemoteCheck/src/fuor.adb | 2 +- .../Value/Return/RangeCheck/src/val.adb | 2 +- .../LocalHandlers/WithinElab/src/ctxt.adb | 6 +- .../LocalHandlers/src/test_ctxt_iraise.adb | 1 - .../LocalHandlers/src/test_ctxt_noraise.adb | 1 - .../LocalHandlers/src/test_ctxt_xraise.adb | 1 - .../Propagation/Basics/src/ops.ads | 2 +- .../11_Exceptions/Propagation/src/ctxt.ads | 4 +- .../Default_UnitInstances/src/stacks.ads | 1 - .../Variants_ByConstruct/src/sensors.ads | 2 +- .../Variants_ByConstruct/src/test_cbfn.adb | 8 +-- .../Variants_ByConstruct/src/test_cifn.adb | 3 +- .../Variants_ByConstruct/src/test_cifo.adb | 4 +- .../Variants_ByConstruct/src/test_cnfn.adb | 1 - .../Variants_ByConstruct/src/test_cnfo.adb | 1 - .../Variants_BySubprogram/src/test_5i_8m.adb | 4 +- .../Variants_BySubprogram/src/test_5m_8i.adb | 4 +- .../Variants_BySubprogram/src/test_6i_9i.adb | 1 - .../Variants_BySubprogram/src/test_6i_9m.adb | 3 +- .../Variants_BySubprogram/src/test_6m_9i.adb | 3 +- .../Variants_BySubprogram/src/test_6m_9m.adb | 3 +- .../Variants_BySubprogram/src/test_6mi_9m.adb | 3 +- .../src/test_6mi_9mi.adb | 3 +- .../Variants_BySubprogram/src/v6or9.adb | 7 +-- .../Variants_BySubprogram/src/vops.adb | 6 +- .../Variants_BySubprogram/src/vops.ads | 2 +- .../1_Core/12_GenericUnits/src/stacks_g.ads | 4 +- .../MachineCode/Inserts_In_Cond/src/data.adb | 6 +- .../OpAttributes/Read_Write/src/mystreams.adb | 12 ++-- .../OpAttributes/Read_Write/src/mystreams.ads | 26 ++++----- .../Read_Write/src/test_read_copy.adb | 1 - .../Read_Write/src/test_read_double.adb | 1 - .../Read_Write/src/test_rw_copy.adb | 3 +- .../Read_Write/src/test_rw_double.adb | 3 +- .../OpAttributes/Read_Write/src/test_wcrd.adb | 3 +- .../OpAttributes/Read_Write/src/test_wdrc.adb | 3 +- .../Read_Write/src/test_write_copy.adb | 1 - .../Read_Write/src/test_write_double.adb | 1 - .../OpAttributes/Read_Write/src/trigger.adb | 5 +- .../OpAttributes/Read_Write/src/trigger.ads | 1 - .../Addr_On_Global/src/global_refs-full.ads | 6 +- .../src/global_refs-inrange.ads | 4 +- .../src/global_refs-outrange.ads | 4 +- .../Addr_On_Local/src/process.adb | 15 +++-- .../Addr_On_Local/src/process.ads | 3 +- .../RepAttributes/src/data.adb | 1 - .../MultipleForOne/src/ranges.adb | 1 - .../Contexts/Subprograms/src/counters.adb | 2 - .../Subprograms/src/test_counters_all.adb | 1 - .../ControlFlow/Controls/Goto/src/minx2.adb | 1 - .../Qualif/Ada/stmt/ControlFlow/src/minx2.ads | 1 - .../stmt/ControlFlow/src/test_minx2_full.adb | 2 - .../stmt/ControlFlow/src/test_minx2_le.adb | 2 - ...test_exemptions_all_exempted_code_call.adb | 13 ----- .../test_exemptions_exempted_code_call.adb | 1 - .../src/test_exemptions_no_call.adb | 1 - ...test_exemptions_non_exempted_code_call.adb | 1 - .../StmtsInBody/src/test_push_o.adb | 2 +- .../StmtsInBody/src/test_pushpop_0.adb | 10 ++-- .../StmtsInBody/src/test_pushpop_o.adb | 4 +- .../StmtsInBody/src/test_pushpop_ou.adb | 10 ++-- .../StmtsInBody/src/test_pushpop_u.adb | 4 +- .../stmt/Exemptions/StmtsInElab/src/com.ads | 1 - .../StmtsInElab/src/comi_noinit.ads | 1 - .../Exemptions/StmtsInSubprog/src/test_0.adb | 1 - .../StmtsInSubprog/src/test_exempt_0.adb | 12 ---- .../StmtsInSubprog/src/test_exempt_xr23.adb | 4 +- .../stmt/Exemptions/WholeBody/src/tipos.ads | 2 - .../Qualif/Ada/stmt/Exemptions/extra.opt | 2 +- .../If_For_If_Case/src/sensors-status.adb | 1 - .../If_For_If_Case/src/test_broken.adb | 18 +++--- .../If_For_If_Case/src/test_check.adb | 18 +++--- .../If_For_If_Case/src/test_check_brok.adb | 6 +- .../If_For_If_Case/src/test_ok.adb | 4 +- .../If_For_If_Case/src/test_ok_brok.adb | 8 +-- .../If_For_If_Case/src/test_ok_check.adb | 8 +-- .../If_For_If_Case/src/test_ok_check_brok.adb | 8 +-- .../If_For_If_Case/src/test_und_brok.adb | 8 +-- .../If_For_If_Case/src/test_und_check.adb | 10 ++-- .../If_For_If_Case/src/test_und_ok.adb | 8 +-- .../If_For_If_Case/src/test_und_ok_brok.adb | 10 ++-- .../If_For_If_Case/src/test_und_ok_check.adb | 8 +-- .../If_For_If_Case/src/test_undecide.adb | 4 +- .../While_If1/src/slists-count.ads | 1 - .../While_If1/src/test_iff.adb | 1 - .../While_If1/src/test_ift.adb | 1 - .../While_If1/src/test_iftf.adb | 13 ++--- .../While_If1/src/test_noentry.adb | 1 - .../While_If4/src/test_if_fft.adb | 7 +-- .../While_If4/src/test_if_ftf.adb | 7 +-- .../While_If4/src/test_if_ftt.adb | 11 ++-- .../While_If4/src/test_if_tff.adb | 7 +-- .../While_If4/src/test_if_tft.adb | 11 ++-- .../While_If4/src/test_if_ttf.adb | 11 ++-- .../While_If4/src/test_if_ttt.adb | 13 ++--- .../While_If4/src/test_noentry.adb | 1 - .../While_If_Case_If/src/slists-forall.adb | 1 - .../While_If_Case_If/src/slists-forall.ads | 1 - .../While_If_Case_If/src/test_act_inh.adb | 7 +-- .../While_If_Case_If/src/test_activate.adb | 7 +-- .../While_If_Case_If/src/test_inhibit.adb | 5 +- .../While_If_Case_If/src/test_nocase.adb | 1 - .../While_If_Case_If/src/test_noentry.adb | 1 - .../While_If_Case_If/src/test_noinhibit.adb | 7 +-- .../Ada/stmt/MixedConstructs/src/sensors.adb | 2 - .../Ada/stmt/MixedConstructs/src/sensors.ads | 1 - .../Ada/stmt/MixedConstructs/src/slists.adb | 4 +- .../Ada/stmt/MixedConstructs/src/vbufs.ads | 1 - .../Ada/stmt/Robustness/CondExpr/test.opt | 2 +- .../Homonyms/src/sub_services-flipb.adb | 1 - .../Homonyms/src/sub_services-flipx.adb | 1 - .../stmt/Robustness/LongSequence/src/bump.adb | 1 - .../MultiStatementLines/src/addmult.adb | 1 - .../Robustness/No_Elab_InLib/mylib/bar.ads | 1 - .../Robustness/No_Elab_InLib/mylib/foo.ads | 1 - .../PartialEval/src/test_andthen_ff.adb | 1 - .../Ada/stmt/Robustness/Uindex/src/ops.adb | 10 ++-- .../Ada/stmt/Robustness/Uindex/src/ops.ads | 17 +++--- .../stmt/Robustness/Uindex/src/test_opab.adb | 6 +- .../stmt/Robustness/Uindex/src/test_opb.adb | 4 +- .../src/test_inc_0.adb | 1 - .../If_And_Eq_Or/src/test_at.adb | 1 - .../Ret_Or_Eq_And_Not/src/test_ac_t.adb | 2 +- .../GprFacilities/ConfigAttr/Target/test.opt | 2 +- .../CmdLinePrevails/src/test_lt0.adb | 1 - .../InSubproject/src/test_lt0.adb | 1 - .../GprFacilities/MainAttr/src/andthen.adb | 1 - .../EmptySections/src/test_expr_full.adb | 18 +++--- .../Exemptions/src/test_ranges_invalid.adb | 1 - .../Exemptions/src/test_ranges_overlap.adb | 1 - .../Qualif/Common/Report/Exemptions/test.opt | 2 +- testsuite/Qualif/Common/Report/src/expr.adb | 2 - .../GPR/ByAttr/src/test_and_tf.adb | 2 - .../GPR/ByAttr/src/test_and_tt.adb | 2 - .../GPR/ByAttr/src/test_or_ft.adb | 2 - .../GPR/ByCmdLine/src/test_tc_or_sub.adb | 1 - .../ExtendedGprs/AttrOverride/App/values.ads | 2 - .../AttrOverride/src/test_lt0.adb | 1 - .../GPR/InnerAttr/src/test_and_tf.adb | 2 - .../GPR/InnerAttr/src/test_and_tt.adb | 2 - .../GPR/InnerAttr/src/test_or_ft.adb | 2 - .../GPR/Robustness/NoUnit/src/p.adb | 1 - testsuite/REST/rest.py | 1 - testsuite/SUITE/control.py | 2 +- testsuite/altrun/isys_nexus_5634/setup.py | 1 - .../MA07-028-expr-context/src/expr.adb | 34 +++++------ .../MA07-028-expr-context/src/expr.ads | 18 +++--- .../MA07-028-expr-context/src/test_t.adb | 12 ++-- .../src/test_values_ft.adb | 1 - .../src/test_values_tf.adb | 1 - .../src/test_values_tt.adb | 1 - .../K620-028_fold-inline/src/actuators.adb | 2 - .../K620-028_fold-inline/src/actuators.ads | 1 - .../src/expr.adb | 9 ++- .../src/test_a.adb | 7 +-- .../tests/Ada/mcdc/OrElse-O1/src/orelse.adb | 1 - .../J311_011-lone_return-O1/src/flips.adb | 1 - .../J311_011-lone_return-O1/src/flips.ads | 1 - .../src/test_flips.adb | 2 +- .../stmt/K316-021_setjmp-sloc/src/test_ce.adb | 2 - .../K620-028_fold-inline/src/actuators.adb | 2 - .../K620-028_fold-inline/src/actuators.ads | 1 - .../mylib/ops-values.ads | 3 +- .../PC20-011-EmptyUnit_InLib/src/test_inc.adb | 5 +- .../Ada2012/decision/ForOf/src/test_f.adb | 6 +- .../Ada2012/decision/ForOf/src/test_t.adb | 6 +- .../Ada2012/decision/ForOf/src/values.adb | 4 +- .../Ada2012/decision/ForOf/src/values.ads | 6 +- .../Invariants/MultiOp/src/multiop.adb | 2 +- .../Invariants/MultiOp/src/multiop.ads | 10 ++-- .../Invariants/SingleOp/src/singleop.adb | 4 +- .../Invariants/SingleOp/src/singleop.ads | 8 +-- .../Aspects/Post/MultiOpBody/src/values.adb | 4 +- .../Aspects/Post/MultiOpBody/src/values.ads | 6 +- .../Aspects/Post/SingleOpSpec/src/values.adb | 4 +- .../Aspects/Post/SingleOpSpec/src/values.ads | 4 +- .../Aspects/Pre/MultiOpSpec/src/test_a.adb | 2 +- .../Aspects/Pre/MultiOpSpec/src/test_b.adb | 2 +- .../Aspects/Pre/MultiOpSpec/src/test_t.adb | 2 +- .../Aspects/Pre/MultiOpSpec/src/values.adb | 2 +- .../Aspects/Pre/MultiOpSpec/src/values.ads | 6 +- .../Aspects/Pre/SingleOpBody/src/values.adb | 4 +- .../Aspects/Pre/SingleOpBody/src/values.ads | 4 +- .../tests/Ada2012/mcdc/ForOf/src/test_a.adb | 9 ++- .../tests/Ada2012/mcdc/ForOf/src/test_ab.adb | 9 ++- .../tests/Ada2012/mcdc/ForOf/src/test_b.adb | 9 ++- .../tests/Ada2012/mcdc/ForOf/src/test_f.adb | 7 +-- .../tests/Ada2012/mcdc/ForOf/src/test_t.adb | 7 +-- .../tests/Ada2012/mcdc/ForOf/src/values.adb | 4 +- .../tests/Ada2012/mcdc/ForOf/src/values.ads | 6 +- .../Ada2012/mcdc/IfExpr/AndOp/src/expr.ads | 6 +- .../mcdc/IfExpr/AndOp/src/test_a_opa.adb | 4 +- .../mcdc/IfExpr/AndOp/src/test_a_t.adb | 4 +- .../mcdc/IfExpr/AndOp/src/test_ab_t.adb | 4 +- .../mcdc/IfExpr/AndOp/src/test_b_opa.adb | 4 +- .../mcdc/IfExpr/AndOp/src/test_opa.adb | 4 +- .../mcdc/IfExpr/AndOp/src/test_opb.adb | 2 +- .../mcdc/IfExpr/AndOp/src/test_opb0.adb | 2 +- .../mcdc/IfExpr/AndOp/src/test_opfull.adb | 8 +-- .../mcdc/IfExpr/ExprSctlCval/src/expr.ads | 6 +- .../mcdc/IfExpr/ExprSctlSval/src/expr.ads | 7 +-- .../mcdc/IfExpr/InDeadPost/src/plus.adb | 3 - .../mcdc/IfExpr/InDeadPost/src/test_0.adb | 1 - .../mcdc/IfExpr/InDeadPost/src/test_f.adb | 1 - .../mcdc/IfExpr/InDeadPost/src/test_t.adb | 1 - .../mcdc/IfExpr/InDeadPre/src/plus.adb | 3 - .../mcdc/IfExpr/InDeadPre/src/test_0.adb | 1 - .../mcdc/IfExpr/InDeadPre/src/test_f.adb | 1 - .../mcdc/IfExpr/InDeadPre/src/test_t.adb | 1 - .../mcdc/IfExpr/RetSctlCval/src/expr.adb | 2 +- .../mcdc/IfExpr/RetSctlCval/src/expr.ads | 2 +- .../mcdc/IfExpr/RetSctlSval/src/expr.adb | 2 +- .../mcdc/IfExpr/RetSctlSval/src/expr.ads | 5 +- .../Ada2012/mcdc/InOut/src/test_eval_f.adb | 1 - .../Ada2012/mcdc/InOut/src/test_eval_t.adb | 1 - .../Ada2012/mcdc/InOut/src/test_neval.adb | 1 - .../Ada2012/mcdc/Membership/src/values.ads | 4 +- .../mcdc/Xfunctions/AndStr/src/fuand.adb | 36 ++++++------ .../mcdc/Xfunctions/AndStr/src/fuand.ads | 14 ++--- .../mcdc/Xfunctions/pAndpOr/src/expr.ads | 4 +- .../ForOf/ObjectArray/src/test_values_0.adb | 1 - .../ForOf/ObjectArray/src/test_values_arg.adb | 3 +- .../ForOf/ObjectArray/src/test_values_gsa.adb | 3 +- .../ForOf/ObjectArray/src/values-global.ads | 4 +- .../stmt/ForOf/ObjectArray/src/values.adb | 4 +- .../stmt/ForOf/ObjectArray/src/values.ads | 8 +-- .../ForOf/PackedArray/src/test_values_0.adb | 1 - .../ForOf/PackedArray/src/test_values_arg.adb | 3 +- .../ForOf/PackedArray/src/test_values_gsa.adb | 1 - .../ForOf/PackedArray/src/values-global.ads | 2 +- .../stmt/ForOf/PackedArray/src/values.ads | 4 +- .../StraightIntArray/src/test_values_0.adb | 1 - .../StraightIntArray/src/test_values_arg.adb | 3 +- .../StraightIntArray/src/test_values_gsa.adb | 3 +- .../StraightIntArray/src/values-global.ads | 2 +- .../ForOf/StraightIntArray/src/values.ads | 2 +- .../ForOf/UncIntArray/src/test_values_0.adb | 1 - .../ForOf/UncIntArray/src/test_values_arg.adb | 3 +- .../UncIntArray/src/test_values_empty.adb | 3 +- .../ForOf/UncIntArray/src/test_values_gsa.adb | 1 - .../ForOf/UncIntArray/src/values-global.ads | 2 +- .../stmt/ForOf/UncIntArray/src/values.ads | 4 +- .../Ada2012/stmt/ForOf/src/values-arg.adb | 4 +- .../Ada2012/stmt/ForOf/src/values-arg.ads | 2 +- .../Ada2012/stmt/ForOf/src/values-global.adb | 4 +- .../Ada2012/stmt/InOut/src/test_eval_f.adb | 1 - .../Ada2012/stmt/InOut/src/test_eval_t.adb | 1 - .../Ada2012/stmt/InOut/src/test_neval.adb | 1 - .../AccPvtFullViewBodyParam/src/pak.ads | 1 - .../AccPvtFullViewSpecParam/src/pak.ads | 1 - .../stmt/NullProc/AccPvtParam/src/pak.ads | 1 - .../stmt/NullProc/AccTaggedParam/src/pak.ads | 1 - .../C++/mcdc/AandB/In_DefaultValue/test.opt | 2 +- .../tests/C/mcdc/Exemptions/Invalid/main.c | 2 +- testsuite/tests/C/mcdc/Exemptions/extra.opt | 2 +- testsuite/tests/C/mcdc/misc/src/misc.ads | 2 +- .../tests/C/mcdc/misc/src/test_aligned_x.adb | 1 - .../stmt/Entries/SelectDelay/Lib/src/ops.adb | 1 - .../Entries/SelectDelay/Local/src/ops.adb | 1 - .../stmt/Entries/SelectElse/Lib/src/ops.adb | 1 - .../stmt/Entries/SelectElse/Local/src/ops.adb | 1 - .../stmt/Entries/SelectOr/Lib/src/ops.adb | 1 - .../stmt/Entries/SelectOr/Local/src/ops.adb | 1 - .../Entries/SelectTerminate/Lib/src/ops.adb | 1 - .../Entries/SelectTerminate/Local/src/ops.adb | 1 - .../stmt/Entries/SelectWhen/Lib/src/ops.adb | 1 - .../stmt/Entries/SelectWhen/Lib/test.opt | 2 +- .../stmt/Entries/SelectWhen/Local/src/ops.adb | 1 - .../stmt/Entries/SelectWhen/Local/test.opt | 2 +- .../Entries/StraightAccept/Lib/src/ops.adb | 1 - .../Entries/Local/src/ops.adb | 1 - .../Operations/Lib/src/ops.adb | 1 - .../Operations/Local/src/ops.adb | 1 - .../Mode_Variants_MCDC/src/sensors.ads | 2 +- .../Mode_Variants_MCDC/src/test_cbfn.adb | 8 +-- .../Mode_Variants_MCDC/src/test_cifn.adb | 6 +- .../Mode_Variants_MCDC/src/test_cifo.adb | 4 +- .../Mode_Variants_MCDC/src/test_cnfo.adb | 2 - .../Mode_Variants_STMT/src/test_v5_reset.adb | 1 - .../Generics/Mode_Variants_STMT/src/v5.ads | 1 - .../Mode_Variants_STMT/src/vectors.adb | 14 ++--- .../Mode_Variants_STMT/src/vectors.ads | 6 +- .../HA16-013_cleanups/src/test_blobs.adb | 6 +- .../tests/HA16-013_cleanups/src/vars.adb | 2 +- .../tests/HA16-013_cleanups/src/vars.ads | 6 +- testsuite/tests/I505-018/src/services.adb | 2 - testsuite/tests/I505-018/src/services.ads | 2 - testsuite/tests/I519-015/test.opt | 2 +- testsuite/tests/I519-030/src/kops.adb | 1 - testsuite/tests/I519-030/src/kops.ads | 1 - testsuite/tests/I715-012/src/monitor.ads | 2 +- testsuite/tests/I717-018/src/explore.adb | 2 +- testsuite/tests/I717-018/src/stations.adb | 4 +- testsuite/tests/I914-023/src/robots.adb | 2 - testsuite/tests/I930-019/src/kops.adb | 1 - testsuite/tests/I930-019/src/kops.ads | 1 - testsuite/tests/IA01-015/src/monitor.ads | 2 +- .../tests/IA06-009-offset-from-sym/src/p.adb | 1 - .../IA09-021-unit-nosco/src/test_assert.adb | 2 - .../IA16-028-disp-routines/src/monitor.adb | 2 +- .../IA16-028-disp-routines/src/monitor.ads | 2 +- .../IA21-003-simple-decision-sco/src/pack.ads | 4 +- .../tests/K214-014-gc-sections/src/foo.adb | 1 - .../K804-031_raise-taken/src/test_val_ce.adb | 1 - .../K804-031_raise-taken/src/test_vif_r.adb | 1 - .../K804-031_raise-taken/src/test_vif_rf.adb | 1 - .../K804-031_raise-taken/src/test_vif_rt.adb | 1 - .../K804-031_raise-taken/src/test_vifn_r.adb | 1 - .../K804-031_raise-taken/src/test_vifn_rf.adb | 1 - .../K804-031_raise-taken/src/test_vifn_rt.adb | 1 - .../tests/KC23-012-ocov-exemptions/p.adb | 12 ++-- .../L411-031_missing_gnateS/src/checks.ads | 6 +- .../src/test_assert.adb | 2 - .../tests/L411-031_missing_gnateS/test.opt | 2 +- .../tests/L619-040-output-to-objdir/pgm.adb | 2 +- testsuite/tests/L929-006/test.opt | 2 +- testsuite/tests/LA17-032-scan-decisions/p.adb | 6 +- .../tests/LA23-016_eargs-exe/src/myabs.adb | 3 +- .../tests/LB13-031-post-aspect/src/passor.adb | 1 - .../M204-037-dc-in-aggregate/src/values.adb | 6 +- .../M204-037-dc-in-aggregate/src/values.ads | 6 +- .../src/ops.adb | 5 +- .../src/ops.ads | 2 +- .../src/test_and.adb | 1 - .../src/test_ff.adb | 1 - .../src/test_ft.adb | 3 +- .../src/test_or.adb | 1 - .../src/test_tf.adb | 3 +- .../src/test_tt.adb | 3 +- .../src/test_xor.adb | 1 - .../alternate/src/assert.adb | 1 - .../alternate/src/foo.adb | 3 +- .../alternate/src/foo.ads | 4 +- .../original/src/test_main.adb | 5 +- .../variant1/src/pkg.adb | 4 +- .../variant1/src/pkg.ads | 4 +- .../variant1/src/test_df.adb | 4 +- .../variant1/src/test_dt.adb | 4 +- testsuite/tests/M625-011-GPR-Cunits/src/bar.c | 2 +- testsuite/tests/M625-011-GPR-Cunits/src/bar.h | 2 +- .../tests/M625-040-slow_on_windows/p.adb | 4 +- .../M724-035-eh-warnings/src/test_loc.adb | 1 - .../decision/StaticInline/src/assert.adb | 1 - .../decision/StaticInline/src/counters.adb | 1 - .../decision/StaticInline/src/counters.ads | 3 +- .../decision/StaticInline/src/falseonly.adb | 5 +- .../StaticInline/src/test_falseonly.adb | 5 +- .../StaticInline/src/test_truefalse.adb | 1 - .../StaticInline/src/test_trueonly.adb | 5 +- .../decision/StaticInline/src/truefalse.adb | 5 +- .../decision/StaticInline/src/trueonly.adb | 5 +- .../MB05-039-not-coverable/src/state.ads | 10 ++-- .../stmt/Generics/src/check_local_nrnf.adb | 7 +-- .../stmt/Generics/src/check_local_nrpf.adb | 7 +-- .../stmt/Generics/src/check_local_prnf.adb | 8 +-- .../stmt/Generics/src/check_local_prpf.adb | 7 +-- .../stmt/Generics/src/test_local_prnf.adb | 1 - .../stmt/Generics/src/test_local_prpf.adb | 1 - .../stmt/Generics/src/test_values_mrmf.adb | 1 - .../stmt/Generics/src/test_values_nrnf.adb | 1 - .../stmt/Generics/src/test_values_nrpf.adb | 1 - .../stmt/Generics/src/values.adb | 8 +-- .../stmt/Generics/src/values.ads | 2 +- .../stmt/Generics/src/values_mrmf.adb | 13 ++--- .../stmt/Generics/src/values_nrnf.adb | 9 ++- .../stmt/Generics/src/values_nrnf.ads | 1 - .../stmt/Generics/src/values_nrpf.adb | 9 ++- .../stmt/Generics/src/values_nrpf.ads | 3 +- .../stmt/Generics/src/values_prnf.adb | 9 ++- .../stmt/Generics/src/values_prpf.adb | 9 ++- .../stmt/HandlerElim/src/test_values.adb | 4 +- .../stmt/HandlerElim/src/values.adb | 10 ++-- .../stmt/HandlerElim/src/values.ads | 6 +- .../stmt/StaticGuard/src/ifs.adb | 34 +++++------ .../stmt/StaticGuard/src/ifs.ads | 8 +-- .../stmt/StaticGuard/src/test_ifs.adb | 22 ++++---- .../stmt/SubprogElim/src/misc.adb | 20 +++---- .../stmt/SubprogElim/src/misc.ads | 2 +- .../stmt/SubprogElim/src/test_misc.adb | 2 - .../stmt/Unreachable/src/values.adb | 10 ++-- .../stmt/Unreachable/src/values.ads | 4 +- .../tests/MB15-040-if-cst/src/monitor.adb | 6 +- .../tests/MB15-040-if-cst/src/monitor.ads | 2 +- .../MC05-011-ref-executable/src/double.adb | 1 - .../tests/N106-020-tempfiles/src/actions.adb | 10 ++-- .../tests/N106-020-tempfiles/src/actions.ads | 9 ++- .../N106-020-tempfiles/src/test_tags.adb | 4 +- .../src/hello.adb | 9 ++- .../src/test_casual_nobody.adb | 1 - .../src/test_casual_someone.adb | 1 - .../src/test_formal_nobody.adb | 1 - .../src/test_formal_someone.adb | 1 - testsuite/tests/N630-009-forward_p_x/foo.adb | 2 +- testsuite/tests/N630-009-forward_p_x/test.opt | 2 +- testsuite/tests/NC08-027-target_attr/foo.adb | 2 +- .../O212-062-assertions/src/assertions.adb | 2 +- .../src/pack_type_invariant.ads | 1 - .../O212-062-show-condition-vectors/main.adb | 1 - .../O212-062-show-condition-vectors/pkg.adb | 2 +- .../O212-062-show-condition-vectors/pkg.ads | 1 - .../OB26-040-type-invariants/Aspects/test.opt | 2 +- .../InvariantClass/src/test_t.adb | 3 +- .../InvariantClass/src/types_a.adb | 2 +- .../InvariantClass/src/types_a.ads | 22 ++++---- .../OB26-040-type-invariants/Pragmas/test.opt | 2 +- .../tests/P526-035-origin-project/test.opt | 2 +- .../P614-002-incidental-coverage/src/maps.adb | 2 +- .../P614-002-incidental-coverage/src/maps.ads | 2 +- .../P614-002-incidental-coverage/src/math.adb | 10 ++-- .../P614-002-incidental-coverage/src/math.ads | 5 +- .../src/test_add.adb | 1 - .../src/test_area.adb | 1 - .../P622-010-stack-restore/src/test_n.adb | 1 - .../AB_C/src/p1.adb | 8 +-- .../AB_C/src/p1.ads | 8 +-- .../A_BC_D/src/p1.adb | 6 +- .../A_BC_D/src/p1.ads | 6 +- .../A_B_C/src/p1.adb | 4 +- .../A_B_C/src/p1.ads | 6 +- .../C_X/src/p2.adb | 6 +- .../C_X/src/p2.ads | 4 +- .../C_X/src/test_0.adb | 1 - .../C_X/src/test_1.adb | 1 - .../C_X/src/test_12.adb | 1 - .../C_X/src/test_123.adb | 1 - .../C_X/src/test_13.adb | 1 - .../C_X/src/test_2.adb | 1 - .../C_X/src/test_23.adb | 1 - .../C_X/src/test_3.adb | 1 - .../src/twisters.ads | 4 +- testsuite/tests/Q414-016-task-accept/test.opt | 2 +- .../tests/QA23-039-nocode-pragmas/p2.ads | 2 +- .../tests/QA23-039-nocode-pragmas/p3.ads | 1 - .../tests/R417-010-scope-metrics/test.opt | 2 +- .../LibUnit/UserDefined/src/subp.ads | 2 +- .../NestedProc/UserDefined/src/elab.adb | 2 +- .../LocallyHandled/ExplicitRaise/src/div.adb | 2 +- .../stmt/example/src/cond_raise.adb | 6 +- .../stmt/example/src/test_cond_t.adb | 12 ++-- .../src/check_class_wide_condition.adb | 3 - .../Class_Wide_Condition/src/test_ft.adb | 8 --- .../Class_Wide_Condition/src/test_t.adb | 1 - .../src/check_dispatching_condition.adb | 3 - .../Dispatching_Condition/src/test_ft.adb | 8 --- .../Dispatching_Condition/src/test_t.adb | 1 - .../Ravenscar/OOP/src/class_wide_ops.adb | 1 - .../OOP/src/new_alert_system-objects.ads | 1 - .../Tasking/TaskTypes/src/blocks_by_tasks.adb | 6 +- .../Tasking/TaskTypes/src/blocks_by_tasks.ads | 4 +- .../tests/Ravenscar/example0/src/sync.ads | 1 - .../Engines/src/test_engines_null.adb | 1 - .../Engines/src/test_engines_stable.adb | 1 - .../Engines/src/test_engines_unstable.adb | 1 - .../tests/T117-007-intf-thunks/src/action.ads | 12 ++-- .../T117-007-intf-thunks/src/interface_a.ads | 6 +- .../pkg-test-sep.adb | 2 +- .../tests/TA14-011-show-mcdc-vectors/main.adb | 2 +- .../tests/TA14-011-show-mcdc-vectors/pkg.adb | 2 +- .../tests/TA14-011-show-mcdc-vectors/pkg.ads | 2 +- .../tests/TC03-012-objcov-line-state/main.c | 2 +- .../Ada/src/disjoint_main_1.adb | 2 +- .../Ada/src/disjoint_main_2.adb | 2 +- .../Ada/src/intersecting_main_1.adb | 2 +- .../Ada/src/intersecting_main_2.adb | 2 +- .../U204-029-source-rebase/Ada/src/pkg1.adb | 2 +- .../U204-029-source-rebase/Ada/src/pkg1.ads | 2 +- .../U204-029-source-rebase/Ada/src/pkg2.adb | 2 +- .../U204-029-source-rebase/Ada/src/pkg2.ads | 2 +- .../tests/U208-020-child-project/test.opt | 2 +- .../U208-020-unique-language-project/test.opt | 2 +- .../U219-010-ali-entry-guard-sloc/test.opt | 2 +- .../tests/U630-040-static-decision/test.opt | 2 +- .../tests/U811-028-suppress-output/main.adb | 2 +- .../UA21-030-elab_mcdc_state/src/pkg.adb | 2 +- .../UA21-030-elab_mcdc_state/src/pkg.ads | 2 +- .../UA21-030-elab_mcdc_state/src/pkh.adb | 2 +- .../src/test_elab.adb | 2 +- .../V520-019-duplicate-messages/main.adb | 2 +- .../tests/V520-019-duplicate-messages/pkg.adb | 2 +- .../tests/V520-019-duplicate-messages/pkg.ads | 2 +- .../tests/VB07-015-clean-output-dir/main.adb | 2 +- .../tests/VB07-015-clean-output-dir/pkg.adb | 2 +- .../tests/VB07-015-clean-output-dir/pkg.ads | 2 +- .../VC19-001-origin-prj/src_code/code.adb | 2 +- .../VC19-001-origin-prj/src_code/code.ads | 2 +- .../src_test/test_main.adb | 2 +- testsuite/tests/asm-consolidate/src/lib.adb | 9 ++- testsuite/tests/asm-consolidate/src/lib.ads | 5 +- testsuite/tests/asm-consolidate/src/p1.adb | 2 - testsuite/tests/asm-consolidate/src/p2.adb | 2 - .../IB11-006-compare-floats/inrange.adb | 1 - .../branch-cond/IB12-008-postcond/checkx.adb | 1 - .../IB12-016-lone-not/eval_not.adb | 3 +- .../branch-cond/IB12-016-lone-not/not_if.adb | 1 - .../IB15-004-spec-precond/checkx.adb | 2 - .../IB15-004-spec-precond/services.ads | 2 - .../IB20-015-length-check/starts.adb | 1 - .../IB20-027-addr-compare/regions.ads | 2 - .../IB25-022-shortcut-actions/services.ads | 1 - .../IC01-032-itype-early-elab/starts.adb | 1 - .../IC02-020-shortcut-action/check.adb | 1 - .../branch-cond/J205-019-and-not/check.adb | 1 - .../branch-cond/J205-019-and-not/foo.adb | 1 - .../branch-cond/J205-019-and-not/foo2.adb | 1 - .../branch-cond/J205-019-and-not/foo3.adb | 1 - .../tests/build_run-assert-failure/test.py | 1 - .../pkg_type_invariant.ads | 1 - .../tests/instr-cov/c_custom_naming/test.opt | 2 +- testsuite/tests/instr-cov/c_metaprog/test.opt | 1 - .../tests/instr-cov/c_multiline_stmt/test.opt | 2 +- .../instr-cov/c_special_filenames/test.opt | 2 +- .../instr-cov/decl-inversion/src/test_foo.adb | 2 +- .../tests/instr-cov/decl-inversion/test.opt | 2 +- .../aspects/no-rec_asp_no-prespec/src/foo.ads | 2 +- .../aspects/no-rec_asp_prespec/src/foo.ads | 2 +- .../no-rec_no-asp_no-prespec/src/foo.ads | 2 +- .../aspects/no-rec_no-asp_prespec/src/foo.ads | 2 +- .../aspects/rec_asp_no-prespec/src/foo.ads | 2 +- .../aspects/rec_asp_no-prespec/test.opt | 2 +- .../aspects/rec_asp_prespec/src/foo.ads | 2 +- .../aspects/rec_asp_prespec/test.opt | 2 +- .../aspects/rec_no-asp_no-prespec/src/foo.ads | 2 +- .../aspects/rec_no-asp_no-prespec/test.opt | 2 +- .../aspects/rec_no-asp_prespec/src/foo.ads | 2 +- .../aspects/rec_no-asp_prespec/test.opt | 2 +- .../expr_func/aspects/src/test_foo.adb | 2 +- testsuite/tests/instr-cov/expr_func/extra.opt | 2 +- .../expr_func/generic_prim/src/inst.ads | 2 +- .../instr-cov/expr_func/prev_decl/src/bar.ads | 2 +- .../instr-cov/expr_func/prev_decl/src/foo.ads | 2 +- .../tests/instr-cov/expr_func/prim2/pak.adb | 2 +- .../gpr-complex/src-main_sep/pkg-bar.adb | 2 +- .../nested_block/dotted-decl.adb | 2 +- .../main_autodump/nested_block/dotted-exn.adb | 2 +- .../nested_block/dotted-no_decl.adb | 2 +- .../main_autodump/nested_block/dotted.adb | 2 +- .../main_autodump/nested_block/dotted.ads | 2 +- .../nested_block/simple_decl.adb | 2 +- .../main_autodump/nested_block/simple_exn.adb | 2 +- .../nested_block/simple_no_decl.adb | 2 +- .../main_autodump/pramga_prio/main.adb | 2 +- .../main_autodump/pramga_prio/test.opt | 2 +- .../main_autodump/stubs/main-inner.adb | 2 +- .../instr-cov/main_autodump/stubs/main.adb | 2 +- .../stubs_controlled/main-inner.adb | 2 +- .../main_autodump/stubs_controlled/main.adb | 2 +- .../main_autodump/stubs_controlled/pkg.adb | 2 +- .../main_autodump/stubs_controlled/pkg.ads | 2 +- .../main_autodump/stubs_controlled/test.opt | 2 +- .../main_autodump/task_in_main/main.adb | 2 +- .../main_autodump/task_in_main/test.opt | 2 +- .../manual-dump/prefix_in_code/main_c.c | 2 +- .../manual-dump/prefix_in_code/test.py | 2 +- .../tests/instr-cov/multiline_marker/test.opt | 2 +- testsuite/tests/instr-cov/not_array/test.opt | 2 +- .../instr-cov/null_proc_generic/test.opt | 2 +- .../instr-cov/protected_body/src/foo.ads | 2 +- .../instr-cov/protected_body/src/test_foo.adb | 2 - .../tests/instr-cov/protected_body/test.opt | 2 +- testsuite/tests/instr-cov/pure_units/test.opt | 2 +- .../instr-cov/short_circuit_and_or/gnat.adc | 2 +- .../short_circuit_and_or/type_pkg.ads | 2 +- .../IB19_019-FormalDefault/src/andthen.adb | 3 - .../Andthen/IB19_019-FormalDefault/test.opt | 2 +- .../JC16_008-ComponentDefault/src/andthen.adb | 3 - .../JC16_008-ComponentDefault/test.opt | 2 +- .../decision/Andthen/src/test_andthen_f.adb | 1 - .../tests/xml-check/src/test_andthen_t.adb | 1 - 1461 files changed, 1864 insertions(+), 3142 deletions(-) diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.adb index 025294c6b..84097be42 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.adb @@ -1,9 +1,9 @@ pragma Unsuppress (All_Checks); pragma Check_Float_Overflow; - + package body Ops is - + function Both_Ok (A, B : Capsum) return Boolean is begin if A.X + A. Y <= A.Cap and then B.X + B.Y <= B.Cap then -- # test diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.ads b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.ads index 7dea345ce..291b4d349 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/ops.ads @@ -1,19 +1,19 @@ package Ops is - + type Constrained_Float is new Float range Float'Range; - + type Capsum is record X, Y, Cap : Constrained_Float; end record; - + Cs_Ok : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); Cs_Ko : constant Capsum := (X => 1.0, Y => 2.0, Cap => 1.0); Cs_Ov : constant Capsum := (X => Constrained_Float'Last, Y => Constrained_Float'Last, Cap => 3.0); - + N_Ok, N_Ko, N_Ov : Integer := 0; - + function Both_Ok (A, B : Capsum) return Boolean; - + end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_all.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_all.adb index 86ef863d1..ac552bb1a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_all.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_all.adb @@ -4,7 +4,7 @@ procedure Test_Ops_All is begin Assert (not Both_Ok (Cs_Ok, Cs_Ko)); Assert (Both_Ok (Cs_Ok, Cs_Ok)); - + Assert (not Both_Ok (Cs_Ov, Cs_Ok)); Assert (N_Ok = 1); Assert (N_Ko = 1); @@ -16,4 +16,3 @@ end; -- /ok/ l+ ## 0 -- /ko/ l+ ## 0 -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_f.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_f.adb index 3b6515435..61aa50aa7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_f.adb @@ -13,4 +13,3 @@ end; -- /ok/ l- ## s- -- /ko/ l+ ## 0 -- /ov/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_koova.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_koova.adb index ffe91be1c..ebc9cc558 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_koova.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_koova.adb @@ -3,7 +3,7 @@ with Ops, Support; use Ops, Support; procedure Test_Ops_KoOva is begin Assert (not Both_Ok (Cs_Ok, Cs_Ko)); - + Assert (not Both_Ok (Cs_Ov, Cs_Ok)); Assert (N_Ok = 0); Assert (N_Ko = 1); @@ -15,4 +15,3 @@ end; -- /ok/ l- ## s- -- /ko/ l+ ## 0 -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_okovb.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_okovb.adb index f2cd21836..c2348e82a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_okovb.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_okovb.adb @@ -3,7 +3,7 @@ with Ops, Support; use Ops, Support; procedure Test_Ops_OkOvb is begin Assert (Both_Ok (Cs_Ok, Cs_Ok)); - + Assert (not Both_Ok (Cs_Ok, Cs_Ov)); Assert (N_Ok = 1); Assert (N_Ko = 0); @@ -15,4 +15,3 @@ end; -- /ok/ l+ ## 0 -- /ko/ l- ## s- -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ova.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ova.adb index d8d2e2375..d4461f2c8 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ova.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ova.adb @@ -13,4 +13,3 @@ end; -- /ok/ l- ## s- -- /ko/ l- ## s- -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ovb.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ovb.adb index beae253e8..db4973999 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ovb.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_ovb.adb @@ -13,4 +13,3 @@ end; -- /ok/ l- ## s- -- /ko/ l- ## s- -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_t.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_t.adb index 1bb59c25f..7b65afab6 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_t.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/src/test_ops_t.adb @@ -13,4 +13,3 @@ end; -- /ok/ l+ ## 0 -- /ko/ l- ## s- -- /ov/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/test.opt b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/test.opt index 270577407..f69ac429d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/And/FloatOps/test.opt @@ -3,4 +3,4 @@ p55-elf XFAIL Machine_Overflows True, no raise on overflow -- No urgent need for support bin-traces,RTS_ZFP XFAIL PB15-008: inaccurate decision coverage for floating-point overflow check on ZFP 5.04a1 DEAD pragma "Check-Float-Overflow" not available in 5.04, causing assertion failure -7.1.2 DEAD pragma "Check-Float-Overflow" not available in 7.1.2, causing assertion failure \ No newline at end of file +7.1.2 DEAD pragma "Check-Float-Overflow" not available in 7.1.2, causing assertion failure diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.adb index a6de5d642..bd953d398 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.adb @@ -2,7 +2,7 @@ pragma Unsuppress (All_Checks); pragma Check_Float_Overflow; package body Ops is - + function One_Ok (A, B : Capsum) return Boolean is begin if A.X + A. Y <= A.Cap or else B.X + B.Y <= B.Cap then -- # test diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.ads b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.ads index b55456af4..51dd46833 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/ops.ads @@ -1,19 +1,19 @@ package Ops is - + type Constrained_Float is new Float range Float'Range; - + type Capsum is record X, Y, Cap : Constrained_Float; end record; - + Cs_Ok : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); Cs_Ko : constant Capsum := (X => 1.0, Y => 2.0, Cap => 1.0); Cs_Ov : constant Capsum := (X => Constrained_Float'Last, Y => Constrained_Float'Last, Cap => 3.0); - + N_Ok, N_Ko, N_Ov : Integer := 0; - + function One_Ok (A, B : Capsum) return Boolean; - + end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_all.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_all.adb index 760c7385d..7e33a271b 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_all.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_all.adb @@ -4,7 +4,7 @@ procedure Test_Ops_All is begin Assert (not One_Ok (Cs_Ko, Cs_Ko)); Assert (One_Ok (Cs_Ok, Cs_Ok)); - + Assert (not One_Ok (Cs_Ov, Cs_Ok)); Assert (N_Ok = 1); Assert (N_Ko = 1); @@ -16,4 +16,3 @@ end; -- /ok/ l+ ## 0 -- /ko/ l+ ## 0 -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_f.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_f.adb index 3f0fa68de..112fb9c60 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_f.adb @@ -13,4 +13,3 @@ end; -- /ok/ l- ## s- -- /ko/ l+ ## 0 -- /ov/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_koova.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_koova.adb index 53ce48f32..29ed0931a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_koova.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_koova.adb @@ -3,7 +3,7 @@ with Ops, Support; use Ops, Support; procedure Test_Ops_KoOva is begin Assert (not One_Ok (Cs_Ko, Cs_Ko)); - + Assert (not One_Ok (Cs_Ov, Cs_Ok)); Assert (N_Ok = 0); Assert (N_Ko = 1); @@ -15,4 +15,3 @@ end; -- /ok/ l- ## s- -- /ko/ l+ ## 0 -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_okovb.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_okovb.adb index d1320042e..e09946a26 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_okovb.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_okovb.adb @@ -3,11 +3,11 @@ with Ops, Support; use Ops, Support; procedure Test_Ops_OkOvb is begin Assert (One_Ok (Cs_Ok, Cs_Ko)); - + Assert (One_Ok (Cs_Ok, Cs_Ov)); - + -- The overflow is shortcircuited - + Assert (N_Ok = 2); Assert (N_Ko = 0); Assert (N_Ov = 0); @@ -18,4 +18,3 @@ end; -- /ok/ l+ ## 0 -- /ko/ l- ## s- -- /ov/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ova.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ova.adb index 664d55099..163cc5810 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ova.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ova.adb @@ -13,4 +13,3 @@ end; -- /ok/ l- ## s- -- /ko/ l- ## s- -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ovb.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ovb.adb index 67e4276c3..90b939c0e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ovb.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_ovb.adb @@ -4,7 +4,7 @@ procedure Test_Ops_Ovb is begin -- We must put a Ko first to evaluate the overflow Assert (not One_Ok (Cs_Ko, Cs_Ov)); - + Assert (N_Ok = 0); Assert (N_Ko = 0); Assert (N_Ov = 1); @@ -15,4 +15,3 @@ end; -- /ok/ l- ## s- -- /ko/ l- ## s- -- /ov/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_t.adb b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_t.adb index 902119e53..8ed1d167f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_t.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/src/test_ops_t.adb @@ -13,4 +13,3 @@ end; -- /ok/ l+ ## 0 -- /ko/ l- ## s- -- /ov/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/test.opt b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/test.opt index 270577407..f69ac429d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/NoEval/Or/FloatOps/test.opt @@ -3,4 +3,4 @@ p55-elf XFAIL Machine_Overflows True, no raise on overflow -- No urgent need for support bin-traces,RTS_ZFP XFAIL PB15-008: inaccurate decision coverage for floating-point overflow check on ZFP 5.04a1 DEAD pragma "Check-Float-Overflow" not available in 5.04, causing assertion failure -7.1.2 DEAD pragma "Check-Float-Overflow" not available in 7.1.2, causing assertion failure \ No newline at end of file +7.1.2 DEAD pragma "Check-Float-Overflow" not available in 7.1.2, causing assertion failure diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.adb index 9d885b03a..cf83313e3 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.adb @@ -2,9 +2,9 @@ with Support; use Support; with System; package body Fuand is - + use type System.Address; - + function Eval (R1, R2 : Integer) return Boolean is begin if R1+R2 > 12 -- # eval0 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.ads index 9bea05e8b..826971c6e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/AddressCompare/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + Data : array (1 .. 32) of Integer := (others => 0); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether R1+R2 > 12 and then data(R1)'address < data(R2)'address R1 : Integer := 8; - R2_FX : Integer := 1; - R2_TF : Integer := 5; + R2_FX : Integer := 1; + R2_TF : Integer := 5; R2_TT : Integer := 9; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Attributes/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Attributes/src/fuor.ads index e98f3169d..bbe502dfa 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Attributes/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Attributes/src/fuor.ads @@ -10,6 +10,3 @@ package Fuor is R2_FT : String := "12345"; R2_TX : String := "123"; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.adb index 931458e90..bcf29f55b 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.adb @@ -4,8 +4,8 @@ package body FUAND is begin if Ops.A and then Ops.B then -- # eval0 return True; -- # true - else + else return False; -- # false - end if; + end if; end; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.ads index 63f4b769b..091b757e8 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand.ads @@ -1,11 +1,11 @@ with System; use System; package FUAND is - + type Operands is record A, B : Boolean; end record; - + for Operands'Bit_Order use High_Order_First; for Operands use record A at 0 range 0 .. 0; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand_helper.adb index bb7725fe7..039ed052d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuand_helper.adb @@ -19,4 +19,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.adb index b69213d60..89a1a7cb7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.adb @@ -4,8 +4,8 @@ package body FUOR is begin if Ops.A or else Ops.B then -- # eval0 return True; -- # true - else + else return False; -- # false - end if; + end if; end; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.ads index 257c98b30..c6c879f3f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor.ads @@ -4,7 +4,7 @@ package FUOR is type Operands is record A, B : Boolean; end record; - + for Operands'Bit_Order use Low_Order_First; for Operands use record A at 0 range 0 .. 0; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor_helper.adb index 3a68afb21..0138e1c5d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BitOrdered/src/fuor_helper.adb @@ -19,4 +19,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolAttribute/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolAttribute/src/fuand.ads index adbb90bc1..64064bd2a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolAttribute/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolAttribute/src/fuand.ads @@ -1,24 +1,24 @@ with Ada.Unchecked_Conversion; package FUAND is - + type Rint is new Integer range 1 .. 5; for Rint'Size use 32; - + function To_Rint is new Ada.Unchecked_Conversion (Integer, Rint); - - Values : array (1 .. 3) of Rint := + + Values : array (1 .. 3) of Rint := (1 => To_Rint(1), -- valid 2 => To_Rint(999), -- invalid 3 => To_Rint(1) -- valid - ); - + ); + function Eval (R1, R2 : Integer) return Boolean; -- Whether R1+R2 > 1 and then Values(R1+R2)'Valid R1 : Integer := 1; - R2_FX : Integer := 0; + R2_FX : Integer := 0; R2_TF : Integer := 1; R2_TT : Integer := 2; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolIndexed/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolIndexed/src/fuand.ads index c6b620cce..e2181bcd6 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolIndexed/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolIndexed/src/fuand.ads @@ -1,26 +1,26 @@ package FUAND is - + type Bitmap is array (1 .. 32) of Boolean; - + BM1 : Bitmap := (1 .. 16 => False, 17 .. 32 => True); -- 00000000000000001111111111111111 - + BM2 : Bitmap := (1 .. 8 => False, 9 .. 16 => True, 17 .. 24 => False, 25 .. 32 => True); -- 00000000111111110000000011111111 - + function Eval (R1, R2 : Integer) return Boolean; - + -- BM1(R1+R2) and then BM2(R1+R2) R1 : Integer := 1; - R2_FX : Integer := 0; - R2_TF : Integer := 15; + R2_FX : Integer := 0; + R2_TF : Integer := 15; R2_TT : Integer := 30; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolSelected/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolSelected/src/fuand.ads index 496626cfb..dd3edb927 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolSelected/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/BoolSelected/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + type Bit_Pair is record Bit0, Bit1 : Boolean; end record; - - Values : array (0 .. 3) of Bit_Pair := + + Values : array (0 .. 3) of Bit_Pair := (0 => (Bit1 => False, Bit0 => False), 1 => (Bit1 => False, Bit0 => True), 2 => (Bit1 => True, Bit0 => False), 3 => (Bit1 => True, Bit0 => True)); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether Values(R1+R2).Bit0 and then Values(R1+R2).Bit1 @@ -17,7 +17,7 @@ package FUAND is R1 : Integer := 0; - R2_FX : Integer := 0; + R2_FX : Integer := 0; R2_TF : Integer := 1; R2_TT : Integer := 3; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand.ads index 00ee631b5..7f1a4378b 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand.ads @@ -1,10 +1,10 @@ package FUAND is - + type Value_T is (FF, TT); - + type Operands is record A, B : Value_T; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand_helper.adb index 9ff1337bd..5dcc3f01d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((FF, FF))); @@ -19,4 +19,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.adb index 4f814764b..5f9dde606 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.adb @@ -4,7 +4,7 @@ package body FUOR is begin if Ops.A = TT or else Ops.B = TT then -- # eval0 return True; -- # true - else + else return False; -- # false end if; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.ads index 284ec0f6e..5064af98f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor.ads @@ -1,11 +1,11 @@ package FUOR is - + type T_Values is (TT, FF); for T_Values use (4, 5); - + type Operands is record A, B : T_Values; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor_helper.adb index df4a340ba..e4a7a5c19 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/EnumOps/src/fuor_helper.adb @@ -19,4 +19,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand.ads index f2a8d5a81..c75860991 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand.ads @@ -1,17 +1,17 @@ package FUAND is - + type Volt is delta 0.125 range 0.0 .. 255.0; - + type Capsum is record X, Y, Cap : Volt; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand_helper.adb index 9ff1337bd..5dcc3f01d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((FF, FF))); @@ -19,4 +19,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor.ads index 72fa89695..e282aed19 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor.ads @@ -1,17 +1,17 @@ package FUOR is - + type Volt is delta 0.125 range 0.0 .. 255.0; - + type Capsum is record X, Y, Cap : Volt; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor_helper.adb index df4a340ba..e4a7a5c19 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FixedOps/src/fuor_helper.adb @@ -19,4 +19,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand.ads index b4cc48de7..8c7083925 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand.ads @@ -1,17 +1,17 @@ package FUAND is - - type My_Float is digits 10 range -5.0 .. 5.0; - + + type My_Float is digits 10 range -5.0 .. 5.0; + type Capsum is record X, Y, Cap : My_Float; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand_helper.adb index 9ff1337bd..5dcc3f01d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((FF, FF))); @@ -19,4 +19,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor.ads index ff6ec9867..1d8a3fc95 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor.ads @@ -1,17 +1,17 @@ package FUOR is - - type My_Float is digits 8 range -5.0 .. 5.0; - + + type My_Float is digits 8 range -5.0 .. 5.0; + type Capsum is record X, Y, Cap : My_Float; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor_helper.adb index df4a340ba..e4a7a5c19 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/FloatOps/src/fuor_helper.adb @@ -19,4 +19,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand.ads index 0ca4b9693..2f9504372 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand.ads @@ -1,23 +1,23 @@ package FUAND is - + type Int is new Integer range 600 .. 607; - + type Char is new Character range 'A' .. 'Z'; type Char_Array is array (Int'Range) of Char; - + type Ref is record Index : Int; Data : Char_Array; end record; - + type Operands is record A, B : Ref; end record; - + -- We will evaluate for each operand whether .data(.index) = 'T' - - Common_Data : constant Char_Array := - (600 => 'A', + + Common_Data : constant Char_Array := + (600 => 'A', 601 => 'B', 602 => 'T', 603 => 'Y', @@ -25,11 +25,11 @@ package FUAND is 605 => 'T', 606 => 'U', 607 => 'V'); - + TT1 : constant Ref := (Index => 602, Data => Common_Data); TT2 : constant Ref := (Index => 605, Data => Common_Data); FF1 : constant Ref := (Index => 600, Data => Common_Data); FF2 : constant Ref := (Index => 607, Data => Common_Data); - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand_helper.adb index fce9311a4..0211ee80e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((FF1, TT1))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.adb index 3bf43fde8..3261f7865 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.adb @@ -1,5 +1,5 @@ package body FUOR is - + function Orelse (Ops : Operands) return Boolean is A : Ref renames Ops.A; -- # decl B : Ref renames Ops.B; -- # decl diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.ads index 7052dc3b7..a12b91c91 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor.ads @@ -1,23 +1,23 @@ package FUOR is - + type Int is new Integer range 600 .. 607; - + type Char is new Character range 'A' .. 'Z'; type Char_Array is array (Int'Range) of Char; - + type Ref is record Index : Int; Data : Char_Array; end record; - + type Operands is record A, B : Ref; end record; - + -- We will evaluate for each operand whether .data(.index) = 'T' - - Common_Data : constant Char_Array := - (600 => 'A', + + Common_Data : constant Char_Array := + (600 => 'A', 601 => 'B', 602 => 'T', 603 => 'Y', @@ -25,11 +25,11 @@ package FUOR is 605 => 'T', 606 => 'U', 607 => 'V'); - + TT1 : constant Ref := (Index => 602, Data => Common_Data); TT2 : constant Ref := (Index => 605, Data => Common_Data); FF1 : constant Ref := (Index => 600, Data => Common_Data); FF2 : constant Ref := (Index => 607, Data => Common_Data); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor_helper.adb index 5238fd950..55cdd1d4c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/IntChar/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fuand.ads index 63178caeb..7e6fe26db 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fuand.ads @@ -1,20 +1,20 @@ package FUAND is - + type Bit4 is mod 2 ** 4; for Bit4'Size use 4; - + type Bitmap is array (1 .. 8) of Bit4; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 4 => 0, 5 .. 8 => 7); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; - -- data(R1.X + R2.X) > 5 and then data(R1.Y + R2+Y) > 5 - + -- data(R1.X + R2.X) > 5 and then data(R1.Y + R2+Y) > 5 + R1 : XY := (X => 1, Y => 1); R2_FX : XY := (X => 0, Y => 1); -- data(1+0) = 0 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fubool.ads index b2396eb58..e75d9f84c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/P4bitStaType/src/fubool.ads @@ -1,13 +1,13 @@ package FUBOOL is - + type Bit4 is mod 2 ** 4; for Bit4'Size use 4; - + type Bitmap is array (1 .. 8) of Bit4; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 4 => 0, 5 .. 8 => 7); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) > 5 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand.ads index 517e62691..3e9bd0e79 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand.ads @@ -1,12 +1,12 @@ package FUAND is type I8 is new Integer range -2 ** 7 .. 2 * 7 -1; for I8'Size use 8; - + type Operands is record Sand : Boolean; A, B : I8; end record; pragma Pack (Operands); - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand_helper.adb index 7e7cfe343..c249cbf06 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((Sand => True, A => 0, B => 0))); @@ -18,4 +18,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor.ads index 5e9091817..fb411c6d2 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor.ads @@ -1,12 +1,12 @@ package FUOR is type I8 is new Integer range -2 ** 7 .. 2 * 7 -1; for I8'Size use 8; - + type Operands is record Sand : Boolean; A, B : I8; end record; pragma Pack (Operands); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor_helper.adb index 2d320f623..490338002 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Packed/src/fuor_helper.adb @@ -19,4 +19,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.adb index 0359ed17e..302a242b0 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.adb @@ -3,16 +3,16 @@ pragma Ada_2012; with Support; use Support; package body Ops is - + type T_Status is tagged record A : T_Action; W : T_What_Ahead; end record; - + type T_Qualified_Status is new T_Status with record Ss : T_Safety_Status; end record; - + function Q1 (S : T_Status) return T_Safety_Status is begin if S.A = Step and then S.W = Pit then -- # test @@ -21,7 +21,7 @@ package body Ops is return Safe; -- # safe end if; end; - + procedure Q2 (S : T_Status; Ss : out T_Safety_Status) is begin if S.A = Step and then S.W = Pit then -- # test @@ -30,7 +30,7 @@ package body Ops is Ss := Safe; -- # safe end if; end; - + procedure Q3 (S : in out T_Qualified_Status) is begin if S.A = Step and then S.W = Pit then -- # test @@ -39,7 +39,7 @@ package body Ops is S.Ss := Safe; -- # safe end if; end; - + function Q4 (S : in out T_Qualified_Status) return Integer is begin if S.A = Step and then S.W = Pit then -- # test @@ -49,26 +49,26 @@ package body Ops is end if; return 0; end; - + function Qualify (A : T_Action; W : T_What_Ahead) return T_Safety_Status is S1 : T_Safety_Status; begin S1 := Q1 ((A, W)); - + declare S2 : T_Safety_Status; begin Q2 ((A, W), S2); Assert (S2 = S1); end; - + declare QS : T_Qualified_Status := (A => A, W => W, SS => <>); begin Q3 (QS); Assert (QS.Ss = S1); end; - + declare QS : T_Qualified_Status := (A => A, W => W, SS => <>); X : Integer; @@ -79,5 +79,5 @@ package body Ops is return S1; end; - + end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.ads index d1b21c4f8..c206f1d87 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/ParameterModes/src/ops.ads @@ -1,9 +1,9 @@ package Ops is - + type T_Action is (Hold, Step); type T_What_Ahead is (Ground, Pit); - + type T_Safety_Status is (Safe, Unsafe); - + function Qualify (A : T_Action; W : T_What_Ahead) return T_Safety_Status; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuand.ads index 99586867f..1a0a71874 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap (1 .. 32) := (1 .. 16 => 0, 17 .. 32 => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fubool.ads index 76b6554ed..3e7c063a0 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fubool.ads @@ -1,11 +1,11 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap (1 .. 32) := (1 .. 16 => 0, 17 .. 32 => 1); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuor.ads index f035e8c96..539d5b6c1 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBase/src/fuor.ads @@ -1,15 +1,15 @@ package FUOR is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap (1 .. 32) := (1 .. 16 => 0, 17 .. 32 => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 or else data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fuand.ads index eb62a23fd..ddaefd325 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap (1 .. 1024) := (1 .. 512 => 0, 513 .. 1024 => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fubool.ads index e15ba4b40..cc7b3b9b6 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynBaseW/src/fubool.ads @@ -1,11 +1,11 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap (1 .. 1024) := (1 .. 512 => 0, 513 .. 1024 => 1); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fuand.ads index d0105be4d..1340d70d7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => 0, 17 .. 32 => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fubool.ads index e4bfbc99a..78dd6bbfc 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynType/src/fubool.ads @@ -1,11 +1,11 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => 0, 17 .. 32 => 1); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fuand.ads index 304697743..845837b52 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fuand.ads @@ -1,17 +1,17 @@ with Params; package FUAND is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap (1 .. Params.Mapsize) := (1 .. 16 => 0, others => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fubool.ads index e4bfbc99a..78dd6bbfc 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeV/src/fubool.ads @@ -1,11 +1,11 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => 0, 17 .. 32 => 1); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fuand.ads index ee8886285..0046da938 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 512 => 0, 513 .. 1024 => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fubool.ads index cd6dfd2a4..e6b830cc7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitDynTypeW/src/fubool.ads @@ -1,11 +1,11 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (Natural range <>) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 512 => 0, 513 .. 1024 => 1); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fuand.ads index 473b7f2b9..f5ad9b5d6 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fuand.ads @@ -1,18 +1,18 @@ package FUAND is - + type Bit is mod 2; type Bitmap is array (1 .. 32) of Bit; pragma Pack (Bitmap); - - Data : Bitmap := + + Data : Bitmap := (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- indexes 1 to 16 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 -- indexes 17 to 32 ); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fubool.ads index c5949c605..c895c35f3 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaType/src/fubool.ads @@ -1,14 +1,14 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (1 .. 32) of Bit; pragma Pack (Bitmap); - - Data : Bitmap := + + Data : Bitmap := (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -- indexes 1 to 16 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 -- indexes 17 to 32 ); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fuand.ads index b8aee83a4..eeb86e085 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fuand.ads @@ -1,15 +1,15 @@ package FUAND is - + type Bit is mod 2; type Bitmap is array (1 .. 1024) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 512 => 0, 513 .. 1024 => 1); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) = 1 and then data(R1.Y + R2+Y) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fubool.ads index 383c45244..1811531ad 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PbitStaTypeW/src/fubool.ads @@ -1,11 +1,11 @@ package FUBOOL is - + type Bit is mod 2; type Bitmap is array (1 .. 1024) of Bit; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 512 => 0, 513 .. 1024 => 1); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fuand.ads index f61ba46f4..188f292ed 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fuand.ads @@ -1,14 +1,14 @@ package FUAND is - + type Bitmap is array (1 .. 32) of Boolean; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => False, 17 .. 32 => True); - + type XY is record X, Y : Integer; end record; - + function Eval (R1, R2 : XY) return Boolean; -- data(R1.X + R2.X) and then data(R1.Y + R2+Y) diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fubool.ads index 77d816c25..3aff021f0 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PboolStaType/src/fubool.ads @@ -1,10 +1,10 @@ package FUBOOL is - + type Bitmap is array (1 .. 32) of Boolean; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => False, 17 .. 32 => True); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2) = True diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand.ads index 482f3b392..fb6c936e9 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand.ads @@ -1,7 +1,7 @@ package FUAND is type I32 is new Integer range -2 ** 31 .. 2 * 31 -1; for I32'Size use 32; - + type Operands is record Sand : Boolean; A, B : I32; @@ -11,6 +11,6 @@ package FUAND is A at 0 range 1 .. 32; B at 0 range 33 .. 64; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand_helper.adb index fe846109e..ddbfbfcdd 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((Sand => True, A => 0, B => 0))); @@ -19,4 +19,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor.ads index 519fdf48a..f78d01831 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor.ads @@ -1,7 +1,7 @@ package FUOR is type I32 is new Integer range -2 ** 31 .. 2 * 31 -1; for I32'Size use 32; - + type Operands is record Sand : Boolean; A, B : I32; @@ -11,6 +11,6 @@ package FUOR is A at 0 range 1 .. 32; B at 0 range 33 .. 64; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor_helper.adb index 2d320f623..490338002 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Placed/src/fuor_helper.adb @@ -19,4 +19,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuand.ads index cf8ee58e4..c08e21d7f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuand.ads @@ -1,10 +1,10 @@ package FUAND is - + type Bitmap is array (1 .. 32) of Boolean; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => False, 17 .. 32 => True); - + function Eval (R1, R2 : Integer) return Boolean; -- R1 + R2 is even and then data(R1 + R2) diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuor.ads index e017cde5b..753d7e9ce 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PmixStaType/src/fuor.ads @@ -1,10 +1,10 @@ package FUOR is - + type Bitmap is array (1 .. 32) of Boolean; pragma Pack (Bitmap); - + Data : Bitmap := (1 .. 16 => False, 17 .. 32 => True); - + function Eval (R1, R2 : Integer) return Boolean; -- data(R1 + R2) or else R1 + R2 is even diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fuand.ads index 833f3de04..0059203b0 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fuand.ads @@ -1,24 +1,24 @@ package FUAND is - + type Bit is mod 2; for Bit'Size use 1; - + type Bits is record Bit0, Bit1 : Bit; end record; for Bits'Size use 2; pragma Pack (Bits); - + type Bitmap is array (1 .. 16) of Bits; pragma Pack (Bitmap); - - Data : Bitmap := + + Data : Bitmap := (1 .. 4 => (Bit0 => 0, Bit1 => 0), 5 .. 8 => (Bit0 => 0, Bit1 => 1), 9 .. 12 => (Bit0 => 1, Bit1 => 0), 13 .. 16 => (Bit0 => 1, Bit1 => 1) ); - + function Eval (R1, R2 : Integer) return Boolean; -- data(R1+R2).bit0 is set and then data(R1+R2).bit1 is set diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fubool.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fubool.ads index c9f01cc6d..8996c8737 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fubool.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/src/fubool.ads @@ -1,22 +1,22 @@ package FUBOOL is - + type Bit is mod 2; for Bit'Size use 1; - + type Bits is record Bit0, Bit1 : Bit; end record; for Bits'Size use 2; pragma Pack (Bits); - + type Bitmap is array (1 .. 16) of Bits; pragma Pack (Bitmap); - - Data : Bitmap := + + Data : Bitmap := (1 .. 8 => (Bit0 => 0, Bit1 => 0), 9 .. 16 => (Bit0 => 1, Bit1 => 0) ); - + function Eval (R1, R2 : Integer) return Boolean; -- Whether data(R1 + R2).bit0 = 1 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.adb index e77ca057b..b2a996e6c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.adb @@ -1,9 +1,9 @@ with Support; use Support; package body Fuand is - + type Conflict is (False, True); -- like Boolean - + function Eval (R1, R2 : Integer) return Boolean is begin if Boolean'(R1+R2 > 10) -- # eval0 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.ads index 6b4b43936..26286601b 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/QualExpr/src/fuand.ads @@ -3,7 +3,7 @@ package FUAND is function Eval (R1, R2 : Integer) return Boolean; -- Whether R1+R2 > 10 and then R1 < R2 - + R1 : Integer := 8; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/RangeMembership/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/RangeMembership/src/fuor.ads index 29ef99459..1134f22d6 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/RangeMembership/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/RangeMembership/src/fuor.ads @@ -1,5 +1,5 @@ package FUOR is - + function Eval (R1, R2 : Integer) return Boolean; -- Whether R1+R2 is in 1 .. 10 or else R1+R2 is in 20 .. 30 @@ -7,8 +7,8 @@ package FUOR is R1 : Integer := 7; - R2_FF : Integer := 8; - R2_FT : Integer := 15; + R2_FF : Integer := 8; + R2_FT : Integer := 15; - R2_TX : Integer := 2; + R2_TX : Integer := 2; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/SubtypeMembership/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/SubtypeMembership/src/fuand.ads index 89d8b75cf..8fe81ba55 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/SubtypeMembership/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/SubtypeMembership/src/fuand.ads @@ -1,8 +1,8 @@ package FUAND is - + subtype RangeP is Integer range 10 .. 15; subtype RangeM is Integer range 1 .. 5; - + function Eval (R1, R2 : Integer) return Boolean; -- Whether R1+R2 is in RangeP and then R1-R2 is in RangeM diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand.ads index 905dea8e0..09aeb01f7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand.ads @@ -4,20 +4,20 @@ pragma Ada_2012; -- yielding Integer values. package FUAND is - - type Op_Name is (Op_A, Op_B); - + + type Op_Name is (Op_A, Op_B); + type Operands is tagged record A, B : aliased Integer; end record with Variable_Indexing => V_Indexing; - + type Integer_Ref (Ref : access Integer) is null record with Implicit_Dereference => Ref; - + function V_Indexing (X : aliased in out Operands; Op : Op_Name) - return integer_Ref is + return integer_Ref is (Ref => (case Op is when OP_A => X.A'Access, diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand_helper.adb index 2bc6ba4c4..6b7a59c92 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FX_F is begin Assert (not Andthen ((A => 0, B => 0))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor.ads index 09b72c2b4..d52458917 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor.ads @@ -1,20 +1,20 @@ pragma Ada_2012; package FUOR is - - type Op_Name is (Op_A, Op_B); - + + type Op_Name is (Op_A, Op_B); + type Operands is tagged record A, B : Float; end record with Constant_Indexing => C_Indexing; - + function C_Indexing (X : aliased Operands'Class; Op : Op_Name) - return Float is + return Float is (case Op is when Op_A => X.A, when Op_B => X.B); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor_helper.adb index 092f74b86..a9a489e4a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/Uindexed/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fuand_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fuand_helper.adb index 4298904a1..31bec0eac 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fuand_helper.adb @@ -6,15 +6,15 @@ package body FUAND_Helper is begin Assert (Fuand.Eval (R1, R2_FX) = False); end; - + procedure Eval_TF_F is begin - Assert (Fuand.Eval (R1, R2_TF) = False); + Assert (Fuand.Eval (R1, R2_TF) = False); end; - + procedure Eval_TT_T is begin - Assert (Fuand.Eval (R1, R2_TT) = True); + Assert (Fuand.Eval (R1, R2_TT) = True); end; end; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fubool_helper.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fubool_helper.adb index 8c27384ae..ae1b6dce9 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fubool_helper.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/fubool_helper.adb @@ -6,7 +6,7 @@ package body FUBOOL_Helper is begin Assert (Fubool.Eval (R1, R2_F) = False); end; - + procedure Eval_T is begin Assert (Fubool.Eval (R1, R2_T) = True); diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_0.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_0.adb index 2eafcbe5e..e530fc14c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_0.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_0.adb @@ -17,4 +17,3 @@ end; -- %tags:7.1.2 -- =/decl/ ~l- ## ~s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_a.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_a.adb index 00ba67c2f..ece4a16c5 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_a.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_a.adb @@ -11,4 +11,3 @@ end; -- /eval1/ l+ ## 0c -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_ab.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_ab.adb index be1837f59..f50c64f5b 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_ab.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_ab.adb @@ -12,5 +12,3 @@ end; -- /eval1/ l+ ## 0c -- /true/ l+ ## 0 -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_b.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_b.adb index eab135f5d..09dde96d0 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_b.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_b.adb @@ -11,4 +11,3 @@ end; -- /eval1/ l+ ## 0c -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_f.adb index 1ca4a644e..07244e366 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_f.adb @@ -11,5 +11,3 @@ end; -- /eval1/ l! ## 0c -- /true/ l- ## s- -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_t.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_t.adb index ce04ba31b..f1b08f0ba 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_t.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuand_t.adb @@ -10,5 +10,3 @@ end; -- /eval1/ l! ## 0c -- /true/ l+ ## 0 -- /false/ l- ## s- - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_0.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_0.adb index 67904595e..9ea9482bc 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_0.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_0.adb @@ -9,5 +9,3 @@ end; -- /eval0/ l- ## s- -- /true/ l- ## s- -- /false/ l- ## s- - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_f.adb index 4fa4c652c..0264ec8a0 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_f.adb @@ -9,5 +9,3 @@ end; -- /eval0/ l! ## dT- -- /true/ l- ## s- -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_t.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_t.adb index 23131973f..aa06c4eb3 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_t.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_t.adb @@ -9,5 +9,3 @@ end; -- /eval0/ l! ## dF- -- /true/ l+ ## 0 -- /false/ l- ## s- - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_tf.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_tf.adb index 978cda77b..ebb7994fc 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_tf.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fubool_tf.adb @@ -10,5 +10,3 @@ end; -- /eval0/ l+ ## 0 -- /true/ l+ ## 0 -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_ab.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_ab.adb index 5f64d9e7c..ce61ab7a7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_ab.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_ab.adb @@ -12,4 +12,3 @@ end; -- /eval1/ l+ ## 0c -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_b.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_b.adb index f4639db04..a46e8368c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_b.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_b.adb @@ -11,5 +11,3 @@ end; -- /eval1/ l+ ## 0c -- /true/ l+ ## 0 -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_f.adb index c757331fb..2bce417cc 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_f.adb @@ -10,4 +10,3 @@ end; -- /eval1/ l! ## 0c -- /true/ l- ## s- -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_t.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_t.adb index d0b3d742f..8926024b9 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_t.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_fuor_t.adb @@ -11,4 +11,3 @@ end; -- /eval1/ l! ## 0c -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/Elsif/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/Elsif/src/andthen.adb index 144c200cf..26fea25c9 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/Elsif/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/Elsif/src/andthen.adb @@ -17,6 +17,3 @@ package body Andthen is return F (A, B, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfElse/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfElse/src/andthen.adb index bdaf36884..c13d3c738 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfElse/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfElse/src/andthen.adb @@ -8,6 +8,3 @@ package body Andthen is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/src/andthen.adb index c816b80fc..4610672db 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/src/andthen.adb @@ -5,6 +5,3 @@ package body Andthen is return (if A and then B then True else False); -- # andthen :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfNoElse/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfNoElse/src/andthen.adb index 1cd7de2e8..5e503d125 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfNoElse/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/IfNoElse/src/andthen.adb @@ -7,6 +7,3 @@ package body Andthen is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/While/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/While/src/andthen.adb index 60bad65cf..eb85fc9a1 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/While/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/While/src/andthen.adb @@ -8,6 +8,3 @@ package body Andthen is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/src/test_andthen_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/src/test_andthen_f.adb index f2756ce8d..01cf80ba6 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/src/test_andthen_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/And/src/test_andthen_f.adb @@ -11,4 +11,3 @@ end; -- /retTrue/ l- ## s- -- /retFalse/ l+ ## 0 -- /retVal/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Elsif/src/flip.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Elsif/src/flip.adb index 513ba788b..a7aec5128 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Elsif/src/flip.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Elsif/src/flip.adb @@ -17,4 +17,3 @@ package body Flip is return Doflip (X, Bomb => Identity(False)); -- # returnVal end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfElse/src/flip.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfElse/src/flip.adb index a9b7ac969..f843fe926 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfElse/src/flip.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfElse/src/flip.adb @@ -8,4 +8,3 @@ package body Flip is end if; end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/src/flip.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/src/flip.adb index d6175794d..2d6533c3c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/src/flip.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/src/flip.adb @@ -5,4 +5,3 @@ package body Flip is return (if not X then True else False); -- # ifx-eval :o/d: end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfNoElse/src/flip.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfNoElse/src/flip.adb index 104bc2b8a..771cbe582 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfNoElse/src/flip.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/IfNoElse/src/flip.adb @@ -7,4 +7,3 @@ package body Flip is return False; -- # returnFalse end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/While/src/flip.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/While/src/flip.adb index 5f830b49b..f8e957e31 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/While/src/flip.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/While/src/flip.adb @@ -8,4 +8,3 @@ package body Flip is return False; -- # returnFalse end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/src/flip.ads b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/src/flip.ads index 864886c64..76ac8416e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/src/flip.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/src/flip.ads @@ -1,4 +1,3 @@ package Flip is function F (X : Boolean) return Boolean; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Elsif/src/orelse.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Elsif/src/orelse.adb index 2c89f7c99..93a590f34 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Elsif/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Elsif/src/orelse.adb @@ -20,6 +20,3 @@ package body Orelse is return F (A, B, X => Support.Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Exit/src/orelse.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Exit/src/orelse.adb index ac0fe1efb..f86d8ed93 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Exit/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/Exit/src/orelse.adb @@ -8,6 +8,3 @@ package body Orelse is return True; -- # retTrue end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfElse/src/orelse.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfElse/src/orelse.adb index 6cf273c87..95391f41f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfElse/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfElse/src/orelse.adb @@ -8,6 +8,3 @@ package body Orelse is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/src/orelse.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/src/orelse.adb index c8a4244ea..097259f98 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/src/orelse.adb @@ -5,6 +5,3 @@ package body Orelse is return (if A or else B then True else False); -- # orelse :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfNoElse/src/orelse.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfNoElse/src/orelse.adb index 24fe7f3c6..7ae3a8210 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfNoElse/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/IfNoElse/src/orelse.adb @@ -7,6 +7,3 @@ package body Orelse is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/While/src/orelse.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/While/src/orelse.adb index 81ec0134f..136c160bf 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/While/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Or/While/src/orelse.adb @@ -7,6 +7,3 @@ package body Orelse is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/IfExpr/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/IfExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/IfExpr/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/IfExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/While/src/value.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/While/src/value.adb index 06d7efbad..7bbe03119 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/While/src/value.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/While/src/value.adb @@ -8,4 +8,3 @@ package body Value is return False; -- # returnFalse end; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/src/value.ads b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/src/value.ads index 026f0f2ed..f9c0a8c47 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/src/value.ads +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Value/src/value.ads @@ -1,4 +1,3 @@ package Value is function F (X : Boolean) return Boolean; end; - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/Elsif/src/expr.adb index 3e070b3dd..56218b8b2 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfElse/src/expr.adb index 30a67639f..e886733ed 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfNoElse/src/expr.adb index df9e34d8e..d6120dc1e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/While/src/expr.adb index 2b1b239e4..f9e2a7c5f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpAndp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/Elsif/src/expr.adb index 6a59ea564..e1badcb77 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfElse/src/expr.adb index 0453702a3..75ec0501d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfNoElse/src/expr.adb index 0ee1c22b8..d4dc466af 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/While/src/expr.adb index f82e77907..cd664548b 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pAndpOrpOrp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/Elsif/src/expr.adb index 5d3b8a416..e4488cb26 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfElse/src/expr.adb index b79af4d55..deb835e2d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfNoElse/src/expr.adb index 492c0c0cc..73fdf2106 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/While/src/expr.adb index 373f815dc..d509b184e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/mix_pOrpOrpAndp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/Elsif/src/expr.adb index 92f48c406..aa79631bc 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfElse/src/expr.adb index dd6e5f71f..65d09c012 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfNoElse/src/expr.adb index e46f5fb9f..7167312aa 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/While/src/expr.adb index d508abec1..f3c527499 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/src/test_expr_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/src/test_expr_f.adb index 8d1a8ffab..ce5cfe612 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/src/test_expr_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_And/src/test_expr_f.adb @@ -11,4 +11,3 @@ end; -- /retTrue/ l- ## s- -- /retFalse/ l+ ## 0 -- /retVal/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Elsif/src/expr.adb index 539096465..055bd0287 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Elsif/src/expr.adb @@ -20,6 +20,3 @@ package body Expr is return F (A, B, X => Support.Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Exit/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Exit/src/expr.adb index b4d4819a0..4f13d660c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Exit/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/Exit/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return True; -- # retTrue end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfElse/src/expr.adb index 3ee067f1d..81ce98b85 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfNoElse/src/expr.adb index b364b7027..7cadc7768 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/While/src/expr.adb index c7beada48..719230c63 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_Or/While/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/Elsif/src/expr.adb index fa8b205ff..bd0cd0ff7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfElse/src/expr.adb index f951443bb..d526a2aa1 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfNoElse/src/expr.adb index 4e672a696..f588ae3d3 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/While/src/expr.adb index 6eb51cca6..da872875a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpAndp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/Elsif/src/expr.adb index 116d370a0..7cda7a558 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfElse/src/expr.adb index 4621dc66c..7cddf34c9 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfNoElse/src/expr.adb index 55a2c7262..b7c2b132c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/While/src/expr.adb index 88c24f381..1e088ea9e 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pAndpOrpOrp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/Elsif/src/expr.adb index b80073715..5e7b93860 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfElse/src/expr.adb index 15ca8f019..a3dfb3c63 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfNoElse/src/expr.adb index a1173b427..6321d2381 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/While/src/expr.adb index 19649cc24..cc6fff34a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/ns_pOrpOrpAndp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/Elsif/src/expr.adb index 68eae5b1f..111248266 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForAllIndex/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForAllIndex/src/expr.adb index efa0da511..c8b29c237 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForAllIndex/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForAllIndex/src/expr.adb @@ -11,6 +11,3 @@ package body Expr is return (for all I in Irange => (AA(I) and then BB(I)) or else (CC(I) and then DD(I))); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForSomeIndex/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForSomeIndex/src/expr.adb index 94a058677..f1ec1e831 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForSomeIndex/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/ForSomeIndex/src/expr.adb @@ -11,6 +11,3 @@ package body Expr is return (for some I in Irange => (AA(I) and then BB(I)) or else (CC(I) and then DD(I))); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfElse/src/expr.adb index a9c931691..376da95ee 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/src/expr.adb index 6bf32bf2e..063138b6a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/src/expr.adb @@ -5,6 +5,3 @@ package body Expr is return (if (A and then B) or else (C and then D) then True else False); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfNoElse/src/expr.adb index f01127db1..e687fb3b2 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/While/src/expr.adb index 8734c18e8..7781522e7 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpAndp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/Elsif/src/expr.adb index 4a3de9d07..1c4bf6627 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForAllIndex/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForAllIndex/src/expr.adb index 876f4242a..923eeeb3f 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForAllIndex/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForAllIndex/src/expr.adb @@ -11,6 +11,3 @@ package body Expr is return (for all I in Irange => (AA(I) and then BB(I)) or else (CC(I) or else DD(I))); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForSomeIndex/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForSomeIndex/src/expr.adb index a46335981..46fe7e02c 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForSomeIndex/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/ForSomeIndex/src/expr.adb @@ -11,6 +11,3 @@ package body Expr is return (for some I in Irange => (AA(I) and then BB(I)) or else (CC(I) or else DD(I))); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfElse/src/expr.adb index 4a3992d12..eedb5d671 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/src/expr.adb index 4dd1ec741..aad0a2dce 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/src/expr.adb @@ -5,6 +5,3 @@ package body Expr is return (if (A and then B) or else (C or else D) then True else False); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfNoElse/src/expr.adb index 5186e4ee5..2acbc06e3 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/While/src/expr.adb index 6c74f7806..3c3326a07 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pAndpOrpOrp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/Elsif/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/Elsif/src/expr.adb index 6538efd1b..b9a392db1 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/Elsif/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/Elsif/src/expr.adb @@ -17,6 +17,3 @@ package body Expr is return F (A, B, C, D, Identity(False)); -- # retVal end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForAllIndex/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForAllIndex/src/expr.adb index 6c552fe43..cdc267da2 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForAllIndex/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForAllIndex/src/expr.adb @@ -11,6 +11,3 @@ package body Expr is return (for all I in Irange => (AA(I) or else BB(I)) or else (CC(I) and then DD(I))); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForSomeIndex/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForSomeIndex/src/expr.adb index c3e7c1a96..543bc5b82 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForSomeIndex/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/ForSomeIndex/src/expr.adb @@ -11,6 +11,3 @@ package body Expr is return (for some I in Irange => (AA(I) or else BB(I)) or else (CC(I) and then DD(I))); -- # eval :o/d: end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfElse/src/expr.adb index f4d126afc..ced89eeb2 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfElse/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is end if; end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfNoElse/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfNoElse/src/expr.adb index 6ddf23948..227c1c804 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfNoElse/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/IfNoElse/src/expr.adb @@ -7,6 +7,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/While/src/expr.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/While/src/expr.adb index ae1176e2d..8f967369a 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/While/src/expr.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/pOrpOrpAndp/While/src/expr.adb @@ -8,6 +8,3 @@ package body Expr is return False; -- # retFalse end; end; - - - diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.adb index 387619312..69320002d 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.adb @@ -4,11 +4,11 @@ pragma Assertion_Policy (Ignore); package body Ops is - + procedure Latch_X (X : Integer) is begin Last_X := X; -- # stmt Latches := Latches + 1; -- # stmt pragma Assert (Latches > 0); -- # assert - end; + end; end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.ads index 8b7423984..72f1bd702 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/ops.ads @@ -1,8 +1,8 @@ package Ops is Latches : Integer := 0; - + Last_X : Integer := -1; - + procedure Latch_X (X : Integer); - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/test_ops_pos.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/test_ops_pos.adb index 6af4362d7..6ec4bd5c3 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/test_ops_pos.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/AssertPragma/src/test_ops_pos.adb @@ -9,4 +9,3 @@ end; --# ops.adb -- /stmt/ l+ ## 0 -- /eval/ l. ## 0 - diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.adb index e467dae65..59680d89a 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.adb @@ -1,6 +1,6 @@ package body Ops is - + procedure Check (P : T_Pair) is begin if P.X > 0 then -- # test_pos diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.ads index a7ff22986..92a1cf8bd 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/DynamicPredicates/src/ops.ads @@ -2,13 +2,13 @@ pragma Ada_12; pragma Assertion_Policy (Dynamic_Predicate => Disable); package Ops is - + type T_Pair is record X, Y : Integer; end record with Dynamic_Predicate => T_Pair.X > 0 and then T_Pair.Y > T_Pair.X; -- # check - + N_Positives : Integer := 0; - + procedure Check (P : T_Pair); end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.adb index 032d8ad31..9184b3d5c 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.adb @@ -1,6 +1,6 @@ package body Ops is - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) is begin if Op = Op_Add then -- # test_add @@ -9,5 +9,5 @@ package body Ops is A.Value := A.Value - B.Value; -- # sub end if; end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.ads index 0cb4b6346..a843e1ebf 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostAspect_LibSpec/src/ops.ads @@ -3,11 +3,11 @@ pragma Ada_12; with Optypes; use Optypes; package Ops is - + pragma Assertion_Policy (Post => Disable); - + type T_Operand is new T_Base_Operand with null record; - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) with Post => (A.Valid and then B.Valid); -- # cond end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.adb index 032d8ad31..9184b3d5c 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.adb @@ -1,6 +1,6 @@ package body Ops is - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) is begin if Op = Op_Add then -- # test_add @@ -9,5 +9,5 @@ package body Ops is A.Value := A.Value - B.Value; -- # sub end if; end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.ads index 6cb886e69..1687bf3f9 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PostClassAspect_LibSpec/src/ops.ads @@ -3,11 +3,11 @@ pragma Ada_12; with Optypes; use Optypes; package Ops is - + pragma Assertion_Policy (Post => Disable); - + type T_Operand is new T_Base_Operand with null record; - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) with Post'Class => (A.Valid and then B.Valid); -- # cond end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.adb index cfd13b8c2..08ffdb314 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.adb @@ -1,5 +1,5 @@ package body Ops is - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) is begin if Op = Op_Add then -- # test_add @@ -8,5 +8,5 @@ package body Ops is A.Value := A.Value - B.Value; -- # sub end if; end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.ads index 1137e4905..5e23e6ebc 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_LibSpec/src/ops.ads @@ -3,11 +3,11 @@ pragma Ada_12; with Optypes; use Optypes; package Ops is - + pragma Assertion_Policy (Pre => Disable); - + type T_Operand is new T_Base_Operand with null record; - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) with Pre => (A.Valid and then B.Valid); -- # cond end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.adb index 947d2f051..1081e635b 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.adb @@ -1,14 +1,14 @@ pragma Ada_12; package body Ops is - + pragma Assertion_Policy (Pre => Disable); - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) is - + procedure Perform (Op : T_Operation; A : in out T_Operand; B : T_Operand) with Pre => (A.Valid and then B.Valid); -- # cond - + procedure Perform (Op : T_Operation; A : in out T_Operand; B : T_Operand) is begin @@ -21,5 +21,5 @@ package body Ops is begin Perform (Op, A, B); end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.ads index 8c7d20034..2d7f1373b 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PreAspect_Local/src/ops.ads @@ -1,8 +1,8 @@ with Optypes; use Optypes; package Ops is - + type T_Operand is new T_Base_Operand with null record; - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand); end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.adb index cfd13b8c2..08ffdb314 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.adb @@ -1,5 +1,5 @@ package body Ops is - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand) is begin if Op = Op_Add then -- # test_add @@ -8,5 +8,5 @@ package body Ops is A.Value := A.Value - B.Value; -- # sub end if; end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.ads index f6252a056..c8d0d89d3 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/PrePragma_LibSpec/src/ops.ads @@ -1,11 +1,11 @@ with Optypes; use Optypes; package Ops is - + pragma Assertion_Policy (Pre => Disable); - + type T_Operand is new T_Base_Operand with null record; - + procedure Apply (Op : T_Operation; A : in out T_Operand; B : T_Operand); pragma Precondition (A.Valid and then B.Valid); -- # cond end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/src/optypes.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/src/optypes.ads index 54c424c4e..8ef3a5d86 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/src/optypes.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/PrePost/src/optypes.ads @@ -3,6 +3,6 @@ package Optypes is Valid : Boolean := False; Value : Integer; end record; - + type T_Operation is (Op_Add, Op_Sub); end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.adb index 9d8484e0e..66624ec95 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.adb @@ -3,7 +3,7 @@ pragma Ada_12; with Support; use Support; package body Ops is - + pragma Assertion_Policy (Static_Predicate => Disable); function Wpos (D : T_Day) return T_Wpos is @@ -19,23 +19,23 @@ package body Ops is return Mid; -- # mid end if; end; - + procedure Check_Early (D : T_Day) is ED : Early_Day := D; -- # check_early begin Assert (Wpos (ED) = Early); -- # check_early end; - + procedure Check_Late (D : T_Day) is ED : Late_Day := D; -- # check_late begin Assert (Wpos (ED) = Late); -- # check_late end; - + procedure Check_Mid (D : T_Day) is ED : Mid_Day := D; -- # check_mid begin Assert (Wpos (ED) = Mid); -- # check_mid end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.ads index c6e297b91..ebd54323d 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/StaticPredicates/src/ops.ads @@ -2,22 +2,22 @@ pragma Ada_12; pragma Assertion_Policy (Static_Predicate => Disable); package Ops is - + type T_Day is (Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday); - + subtype Early_Day is T_Day with Static_Predicate => Early_Day in Monday | Tuesday | Wednesday; -- # check-early - + subtype Mid_Day is T_Day with Static_Predicate => Mid_Day = Thursday; -- # check-mid - + subtype Late_Day is T_Day with Static_Predicate => Late_Day in Friday | Saturday | Sunday; -- # check-late - + type T_Wpos is (Early, Mid, Late); function Wpos (D : T_Day) return T_Wpos; - + procedure Check_Early (D : T_Day); procedure Check_Mid (D : T_Day); procedure Check_Late (D : T_Day); diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.adb b/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.adb index 7baa084be..f57186976 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.adb @@ -1,17 +1,17 @@ package body Ops is - + function I_Check (V : T_Value) return Boolean is begin return V.N_Sets >= 0; -- # check end; - + procedure Set (I : in out T_Int; V : Integer; Count : Boolean) is begin I.Value := V; -- # stmt - + if Count then -- # test_count I.N_Sets := I.N_Sets + 1; -- # count end if; end; - + end; diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.ads index c48d8011d..0d8af40f7 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.ads @@ -2,25 +2,25 @@ pragma Ada_2012; pragma Assertion_Policy (Invariant => Disable); package Ops is - + type T_Value is tagged private with Type_Invariant'Class => I_Check(T_Value); - + function I_Check (V : T_Value) return Boolean; - + type T_Int (UB : Integer) is new T_Value with Private; - + procedure Set (I : in out T_Int; V : Integer; Count : Boolean); private - + type T_Value is tagged record N_Sets : Integer := 0; end record; - + type T_Int (UB : Integer) is new T_Value with record Value : Integer := UB; end record with Type_Invariant => (T_Int.Value <= T_Int.UB); - + end; diff --git a/testsuite/Qualif/Ada/decision/Consolidation/And/src/andthen.ads b/testsuite/Qualif/Ada/decision/Consolidation/And/src/andthen.ads index 10f4386a7..a16b1dbf7 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/And/src/andthen.ads +++ b/testsuite/Qualif/Ada/decision/Consolidation/And/src/andthen.ads @@ -7,4 +7,3 @@ function Andthen (A, B : Boolean) return Boolean; -- F X F v0 -- T F F v1 -- T T T v2 - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v0.adb b/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v0.adb index d2d4f9615..6f116cde9 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v0.adb +++ b/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v0.adb @@ -11,5 +11,3 @@ end; -- /eval/ l! ## dT- -- /true/ l- ## s- -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v1.adb b/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v1.adb index 7d47309bb..d00da6530 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v1.adb +++ b/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v1.adb @@ -9,5 +9,3 @@ end; -- /eval/ l! ## dT- -- /true/ l- ## s- -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v2.adb b/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v2.adb index c5b3dcfc8..c9f5f8470 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v2.adb +++ b/testsuite/Qualif/Ada/decision/Consolidation/And/src/test_andthen_v2.adb @@ -9,5 +9,3 @@ end; -- /eval/ l! ## dF- -- /true/ l+ ## 0 -- /false/ l- ## s- - - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/orelse.ads b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/orelse.ads index 5427b6c78..37fd01550 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/orelse.ads +++ b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/orelse.ads @@ -7,4 +7,3 @@ function Orelse (A, B : Boolean) return Boolean; -- F F F v0 -- F T T v1 -- T X T v2 - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v0.adb b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v0.adb index 5d154e86c..5dc0a506c 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v0.adb +++ b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v0.adb @@ -9,5 +9,3 @@ end; -- /eval/ l! ## dT- -- /true/ l- ## s- -- /false/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v1.adb b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v1.adb index 353f864ca..45869bb9e 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v1.adb +++ b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v1.adb @@ -9,4 +9,3 @@ end; -- /eval/ l! ## dF- -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v2.adb b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v2.adb index 2170bfab5..f154372c4 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v2.adb +++ b/testsuite/Qualif/Ada/decision/Consolidation/Or/src/test_orelse_v2.adb @@ -11,5 +11,3 @@ end; -- /eval/ l! ## dF- -- /true/ l+ ## 0 -- /false/ l- ## s- - - diff --git a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_invalid.adb b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_invalid.adb index 4e2a60cb2..643fb7d6d 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_invalid.adb +++ b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_invalid.adb @@ -28,4 +28,3 @@ end; -- /checkOverlap/ l- ## s- -- /overlapTrue/ l- ## s- -- /overlapFalse/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_overlap.adb b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_overlap.adb index ee39f3ece..9c780c1d1 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_overlap.adb +++ b/testsuite/Qualif/Ada/decision/Exemptions/PrecondInBody/src/test_ranges_overlap.adb @@ -45,4 +45,3 @@ end; -- /checkOverlap/ l! ## dF- -- /overlapTrue/ l+ ## 0 -- /overlapFalse/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/Exemptions/extra.opt b/testsuite/Qualif/Ada/decision/Exemptions/extra.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/extra.opt +++ b/testsuite/Qualif/Ada/decision/Exemptions/extra.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/sensors-status.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/sensors-status.adb index 3b5b4b2a2..fdd37df89 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/sensors-status.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/sensors-status.adb @@ -34,4 +34,3 @@ package body Sensors.Status is end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_broken.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_broken.adb index 0ced98b40..be69593d5 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_broken.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_broken.adb @@ -3,24 +3,24 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Broken is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; - + -- Two history entries, both out of range - - S.V := 15; + + S.V := 15; Sample (S); Sample (S); - + Assert (Status_Of (S) = Broken); - + -- A third entry, in range. Still two out of range. - - S.V := 5; + + S.V := 5; Sample (S); - + Assert (Status_Of (S) = Broken); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_check.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_check.adb index 7149f8f0a..5cfc621e2 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_check.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_check.adb @@ -3,23 +3,23 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; - + -- Single history entry, out of range - - S.V := 15; + + S.V := 15; Sample (S); - + Assert (Status_Of (S) = Check); - + -- Two history entries, only one out of range - - S.V := 5; + + S.V := 5; Sample (S); - + Assert (Status_Of (S) = Check); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_f_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_f_ff.adb index 88cf2aba9..fb2851233 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_f_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_f_ff.adb @@ -3,13 +3,13 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_F_FF is S : Sensor; - + begin -- Outer If False only. Inner If False only from F or else F. S.ALB := 1; S.AHB := 15; S.V := 5; -- in range - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb index 131d500eb..807de762e 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb @@ -3,17 +3,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_FU_FF is S : Sensor; - + begin -- Outer If both True and False. Inner If False only from F or else F. - + S.ALB := 1; S.AHB := 15; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; -- in range - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_fu.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_fu.adb index c95713f98..a891c55b2 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_fu.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_fu.adb @@ -3,18 +3,18 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_FU_FU is S : Sensor; - + begin -- Outer and Inner If both True and False. - + S.ALB := 1; S.AHB := 15; - + Assert (Status_Of (S) = Undecidable); - S.V := 0; -- < low bound + S.V := 0; -- < low bound Sample (S); - + S.V := 5; -- in range Sample (S); diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb index a1f70f383..79ab5e80b 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb @@ -6,15 +6,15 @@ procedure Test_FU_TX is begin -- Outer If both True and False. Inner If True only from T or else X. - + S.ALB := 1; S.AHB := 15; - + Assert (Status_Of (S) = Undecidable); - + S.V := 0; -- < low bound Sample (S); - + Assert (Status_Of (S) = Check); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok.adb index 50394b7cb..03c8e7c56 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok.adb @@ -3,12 +3,12 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_OK is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb index b7a7d439d..674978979 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 15; Sample (S); Sample (S); Assert (Status_Of (S) = Broken); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check.adb index 7a32e1b3d..adf7d20b5 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 15; Sample (S); Assert (Status_Of (S) = Check); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb index d6533600d..07c469831 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb @@ -4,19 +4,19 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Check_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); - + S.V := 40; Sample (S); Assert (Status_Of (S) = Broken); diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_t_0.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_t_0.adb index a8dd68a25..9bf811870 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_t_0.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_t_0.adb @@ -3,7 +3,7 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_T_0 is S : aliased Sensor; - + begin -- Outer If True only. Inner If not reached. S.V := 5; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_check.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_check.adb index c69010279..87286041a 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_check.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_check.adb @@ -4,21 +4,21 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Check); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok.adb index d73d62aa8..d71ed71a7 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok.adb @@ -4,17 +4,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Assert (Status_Of (S) = Undecidable); - + Sample (S); Assert (Status_Of (S) = Ok); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb index b3f615ea2..aa3c5b380 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); - + S.V := 40; Sample (S); Assert (Status_Of (S) = Broken); diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb index 3b4c5e5a5..3e50f7c12 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb @@ -4,17 +4,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_undecide.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_undecide.adb index 0dbd628d0..ed6ab2578 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_undecide.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/If_For_If_Case/src/test_undecide.adb @@ -3,12 +3,12 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Undecide is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Assert (Status_Of (S) = Undecidable); end; diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/slists-count.ads b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/slists-count.ads index be1a4bef4..7dfcde28c 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/slists-count.ads +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/slists-count.ads @@ -6,4 +6,3 @@ package Slists.Count is SP : SP_Access := Pass'Access; NT, NF : out Natural); end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iff.adb index 452057a8f..66fde41e1 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iff.adb @@ -26,4 +26,3 @@ end; -- /CO_incT/ l- ## s- -- /CO_incF/ l+ ## 0 -- /CO_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_ift.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_ift.adb index ba97d001e..65c6fc1f9 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_ift.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_ift.adb @@ -27,4 +27,3 @@ end; -- /CO_incT/ l+ ## 0 -- /CO_incF/ l- ## s- -- /CO_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iftf.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iftf.adb index 76312d21b..91786e246 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iftf.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_iftf.adb @@ -10,22 +10,22 @@ procedure Test_Iftf is Sin : aliased Sensor (Hist_Size => 5); -- in range sensor Sout : aliased Sensor (Hist_Size => 5); -- out of range sensor SL : Sensor_List; - + Nt, Nf : Natural; begin - + Sin.V := 5; Sin.ALB := 1; Sin.AHB := 10; - + Prepend (Sin'Unchecked_Access, SL); - + Sout.V := 5; Sout.ALB := 1; Sout.AHB := 3; - + Prepend (Sout'Unchecked_Access, SL); - + Count_In (Sl, Inrange'Access, Nt, Nf); Assert (Nt = 1); Assert (Nf = 1); @@ -40,4 +40,3 @@ end; -- /CO_incT/ l+ ## 0 -- /CO_incF/ l+ ## 0 -- /CO_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_noentry.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_noentry.adb index 645b25b0e..c039912db 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_noentry.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If1/src/test_noentry.adb @@ -21,4 +21,3 @@ end; -- /CO_incT/ l- ## s- -- /CO_incF/ l- ## s- -- /CO_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ff.adb index 0ce55e079..78a70bfd4 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ff.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 0 and then Ok.Len = 1); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ft.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ft.adb index d504b04a4..74da8b900 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ft.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_ft.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_tx.adb index c46f26d9f..f8d1f419e 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_fx_tx.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ff.adb index acc6cac42..35b61b732 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ff.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 0 and then Ok.Len = 1); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ft.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ft.adb index a18667518..6308ac408 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ft.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_ft.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_tx.adb index 4a55c3ecf..4c6cd0284 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tf_tx.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tt_xx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tt_xx.adb index f6ada261e..bb507610d 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tt_xx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/doif_tt_xx.adb @@ -16,4 +16,3 @@ begin Assert (Skip.Len = 1 and then Fault.Len = 0 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_df.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_df.adb index 8f1de5501..446195ea8 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_df.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_df.adb @@ -21,4 +21,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_dt.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_dt.adb index c00f76a1b..944e6f307 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_dt.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_dt.adb @@ -7,7 +7,7 @@ procedure Test_DF_DT is begin Doif_FX_FT; Doif_FX_TX; - + Doif_TF_FT; Doif_TF_TX; end; @@ -25,4 +25,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_fu.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_fu.adb index 607625d83..97822124a 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_fu.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_df_fu.adb @@ -3,12 +3,12 @@ with Doif_TF_FT, Doif_TF_TX, Doif_TF_FF; procedure Test_DF_FU is begin - Doif_FX_FT; + Doif_FX_FT; Doif_TF_FT; - + Doif_FX_TX; Doif_TF_TX; - + Doif_FX_FF; Doif_TF_FF; end; @@ -26,4 +26,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_dt.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_dt.adb index bc296ec08..b48e33125 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_dt.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_dt.adb @@ -4,10 +4,10 @@ procedure Test_FU_DT is begin Doif_FX_FT; Doif_FX_TX; - + Doif_TF_FT; Doif_TF_TX; - + Doif_TT_XX; end; @@ -24,4 +24,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_fu.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_fu.adb index 2dee78d20..4d8cf777c 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_fu.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fu_fu.adb @@ -3,15 +3,15 @@ with Doif_TF_FT, Doif_TF_TX, Doif_TF_FF, Doif_TT_XX; procedure Test_FU_FU is begin - Doif_FX_FT; + Doif_FX_FT; Doif_TF_FT; - + Doif_FX_TX; Doif_TF_TX; - + Doif_FX_FF; Doif_TF_FF; - + Doif_TT_XX; end; @@ -28,4 +28,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ff.adb index 6c8d726ff..58c74ba50 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ff.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ft.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ft.adb index a93ffb3c1..3caac5fbd 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ft.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_ft.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_tx.adb index 1b846ea2d..841b44ff5 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_fx_tx.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ff.adb index 1af77d031..c02e262b5 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ff.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ft.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ft.adb index 53b003ec6..bf5bf2852 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ft.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_ft.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_tx.adb index 9e2c537d0..1b93fd997 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tf_tx.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tt_xx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tt_xx.adb index 9d414583a..0e66a352f 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tt_xx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/src/test_tt_xx.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.adb index dd2dd3ea3..f734bf26f 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.adb @@ -26,4 +26,3 @@ package body Slists.Forall is end; end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.ads b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.ads index d1d942c70..5d475d37b 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.ads +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/slists-forall.ads @@ -3,4 +3,3 @@ package Slists.Forall is procedure ForAll_In (SL : Sensor_List; Op : Sensor_Op; Active_Only : Boolean := False); end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_act_inh.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_act_inh.adb index eb6b2ff8e..b30b503b7 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_act_inh.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_act_inh.adb @@ -39,4 +39,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_activate.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_activate.adb index c1fdc00c6..08ab934fb 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_activate.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_activate.adb @@ -7,16 +7,16 @@ procedure Test_Activate is begin S1.ALB := 1; S1.AHB := 10; - + S2.ALB := 5; S2.AHB := 15; Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); - + Forall_In (SL, Activate, Active_Only => True); Assert ((not S1.Active) and then (not S2.Active)); - + Forall_In (SL, Activate); Assert (S1.Active and then S2.Active); end; @@ -32,4 +32,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb index b6cac0779..e50cf022d 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb @@ -22,4 +22,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb index 3e2108385..904ad2066 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb @@ -26,4 +26,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb index 4125c0496..a86293311 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb @@ -28,4 +28,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_0.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_0.adb index 9e6f2f56a..321b29c16 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_0.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_0.adb @@ -11,10 +11,10 @@ begin -- Inner If decision not reached. Prepend (S'Unchecked_Access, SL); - + S.Active := False; Forall_In (SL, Activate, Active_Only => False); - + S.Active := False; Forall_In (SL, Inhibit, Active_Only => True); end; @@ -30,4 +30,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ff.adb index 1b5001f0b..29e25ec82 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ff.adb @@ -11,10 +11,10 @@ begin -- Inner If False only from F or else F. Prepend (S'Unchecked_Access, SL); - + S.Active := False; Forall_In (SL, Inhibit, Active_Only => True); - + S.Active := True; S.ALB := 1; S.AHB := 12; @@ -33,4 +33,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ft.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ft.adb index 81e7afb63..c5bdae456 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ft.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_ft.adb @@ -11,10 +11,10 @@ begin -- Inner If True only from F or else T. Prepend (S'Unchecked_Access, SL); - + S.Active := False; Forall_In (SL, Inhibit, Active_Only => True); - + S.Active := True; S.ALB := 1; S.AHB := 12; @@ -33,4 +33,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_fu.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_fu.adb index 4305d51b3..76c45c970 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_fu.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_fu.adb @@ -12,16 +12,16 @@ begin Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); - + S1.Active := False; S2.Active := False; Forall_In (SL, Inhibit, Active_Only => True); - + S1.Active := True; S1.ALB := 1; S1.AHB := 12; S1.V := 0; -- < low bound - + S2.Active := True; S2.ALB := 1; S2.AHB := 12; @@ -40,4 +40,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_tx.adb index 0b715496f..b13113a6f 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_fu_tx.adb @@ -11,10 +11,10 @@ begin -- Inner If True only from T or else X. Prepend (S'Unchecked_Access, SL); - + S.Active := False; Forall_In (SL, Inhibit, Active_Only => True); - + S.Active := True; S.ALB := 1; S.AHB := 12; @@ -33,4 +33,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb index 3f3641bd3..337dbbef9 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb @@ -30,4 +30,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb index 960567620..a5d3ee5a2 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb @@ -8,15 +8,15 @@ begin -- While decision covered from loop over non empty list -- First If decision True only from T or else X. -- Inner If decision False only from F or else F. - + S1.ALB := 1; S1.AHB := 15; S1.V := 5; -- in range Prepend (S1'Unchecked_Access, SL); - + S1.Active := True; for X in False .. True loop - Forall_In (SL, Inhibit, Active_Only => X); + Forall_In (SL, Inhibit, Active_Only => X); end loop; end; @@ -31,4 +31,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb index 4dfd25e54..f8ff6f4dc 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb @@ -8,15 +8,15 @@ begin -- While decision covered from loop over non empty list -- First If decision True only from T or else X. -- Inner If decision True only from T or else X. - + S1.ALB := 1; S1.AHB := 15; S1.V := 30; -- > high bound Prepend (S1'Unchecked_Access, SL); - + for X in False .. True loop S1.Active := True; - Forall_In (SL, Inhibit, Active_Only => X); + Forall_In (SL, Inhibit, Active_Only => X); end loop; end; @@ -31,4 +31,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb index 2fc2809e6..a66b9170f 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb @@ -8,15 +8,15 @@ begin -- While decision covered from loop over non empty list -- First If decision True only from T or else X. -- Inner If decision True only from T or else X. - + S1.ALB := 1; S1.AHB := 15; S1.V := 0; -- < low bound Prepend (S1'Unchecked_Access, SL); - + for X in False .. True loop S1.Active := True; - Forall_In (SL, Inhibit, Active_Only => X); + Forall_In (SL, Inhibit, Active_Only => X); end loop; end; @@ -31,4 +31,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_inhibit.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_inhibit.adb index b50f37c55..37549fde0 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_inhibit.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_inhibit.adb @@ -39,4 +39,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_nocase.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_nocase.adb index 070f2bfbd..a169fc396 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_nocase.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_nocase.adb @@ -24,4 +24,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noentry.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noentry.adb index 5ecd96515..7509dbb46 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noentry.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noentry.adb @@ -18,4 +18,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb index bb2dae1c1..248a17063 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb @@ -7,14 +7,14 @@ procedure Test_Noinhibit is begin -- get into the inhibit case selection, arranging for the -- if statement there to always evaluate false - + S1.ALB := 1; S1.AHB := 10; S1.V := 5; -- # in range S1.Active := True; - + Prepend (S1'Unchecked_Access, SL); - + Forall_In (SL, Inhibit); Assert (S1.Active); end; @@ -30,4 +30,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.adb index 404de97f8..a4f0b96fc 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.adb @@ -5,5 +5,3 @@ package body Sensors is Vbufs.Push (S.V, S.History); end; end; - - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.ads b/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.ads index 4af84cd8c..1700b03cd 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.ads +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/src/sensors.ads @@ -16,4 +16,3 @@ package Sensors is -- latch current sensor value for S in its history buffer end; - diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/src/slists.adb b/testsuite/Qualif/Ada/decision/MixedConstructs/src/slists.adb index 168c92b9f..2701bf287 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/src/slists.adb +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/src/slists.adb @@ -5,7 +5,7 @@ package body Slists is package Sensor_Nodes_Pool is new Simple_Pools.Basic_Pool (Data_Type => Sensor_Node, Capacity => 20); - + procedure Prepend (S : Sensor_Access; SL : in out Sensor_List) is NA : constant Sensor_Nodes_Pool.Data_Access := Sensor_Nodes_Pool.Allocate; begin diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/src/vbufs.ads b/testsuite/Qualif/Ada/decision/MixedConstructs/src/vbufs.ads index 1e5ad1b18..49646f52c 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/src/vbufs.ads +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/src/vbufs.ads @@ -13,4 +13,3 @@ package Vbufs is procedure Push (V : Value; VB : in out Vbuffer); end; - diff --git a/testsuite/Qualif/Ada/decision/Robustness/Contracts/CondExpr/src/ops.ads b/testsuite/Qualif/Ada/decision/Robustness/Contracts/CondExpr/src/ops.ads index 7f1d5d0ce..9422b2b17 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Contracts/CondExpr/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/Contracts/CondExpr/src/ops.ads @@ -2,7 +2,7 @@ pragma Ada_2012; package Ops is pragma Assertion_Policy (Ignore); - + procedure Add_Or_Mult (X, Y : Integer; Z : out Integer) with Pre => (if X > 0 then Y > 0 else Y <= 0), Post => (case X is diff --git a/testsuite/Qualif/Ada/decision/Robustness/Contracts/MultiMembership/src/ops.ads b/testsuite/Qualif/Ada/decision/Robustness/Contracts/MultiMembership/src/ops.ads index 4b730577f..4faee4576 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Contracts/MultiMembership/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/Contracts/MultiMembership/src/ops.ads @@ -2,9 +2,9 @@ pragma Ada_2012; package Ops is pragma Assertion_Policy (Ignore); - + function Plus1 (I : Integer) return Integer is (I + 1); - + procedure Add_Or_Mult (X, Y : Integer; Z : out Integer) with Post => (Z in 1 .. Y | 3 | Plus1 (X)); end; diff --git a/testsuite/Qualif/Ada/decision/Robustness/Contracts/QuantifiedExpr/src/ops.ads b/testsuite/Qualif/Ada/decision/Robustness/Contracts/QuantifiedExpr/src/ops.ads index ef1b43c4a..4ec5a462f 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Contracts/QuantifiedExpr/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/Contracts/QuantifiedExpr/src/ops.ads @@ -2,9 +2,9 @@ pragma Ada_2012; package Ops is pragma Assertion_Policy (Ignore); - + Data : array (1 .. 50) of Integer with Volatile; - + procedure Add_Or_Mult (X, Y : Integer; Z : out Integer) with Pre => (for some X of Data => X < 0 or else X mod 2 /= 0), Post => (for all X of Data => X > 0 and then X mod 2 = 0); diff --git a/testsuite/Qualif/Ada/decision/Robustness/InlineSequence/src/ops.adb b/testsuite/Qualif/Ada/decision/Robustness/InlineSequence/src/ops.adb index e85b8a543..2571934cd 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/InlineSequence/src/ops.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/InlineSequence/src/ops.adb @@ -1,18 +1,18 @@ pragma Ada_2012; package body Ops is - + -- Decision on the if-expression below. Single operand and -- no statement involved, so no dominance info available. - + function "abs" (X : Int64) return Uns64 is (if X = Int64'First -- # eval then 2**63 else Uns64 (Int64'(abs X))); -- - + procedure Process (X, Y : Int64) is - + -- Below, two calls to the "abs" expression function -- above in a row. When both calls are inlined, special -- treatment is required to untangle the two decisions. @@ -25,5 +25,3 @@ package body Ops is end; end; - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/If/src/andthen.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/If/src/andthen.adb index 44357981b..004bf36fe 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/If/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/If/src/andthen.adb @@ -8,5 +8,3 @@ begin return False; -- # false end if; end; - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/While/src/andthen.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/While/src/andthen.adb index 740afa7f9..a594a9a18 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/While/src/andthen.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/And/While/src/andthen.adb @@ -9,5 +9,3 @@ begin return False; -- # false end; - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/If/src/orelse.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/If/src/orelse.adb index 3d1046a41..910a12094 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/If/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/If/src/orelse.adb @@ -8,5 +8,3 @@ begin return False; -- # false end if; end; - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/While/src/orelse.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/While/src/orelse.adb index d4f75199b..60dd5637a 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/While/src/orelse.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiLineDecisions/Or/While/src/orelse.adb @@ -8,5 +8,3 @@ begin return False; -- # false end; - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register1.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register1.adb index 51cf7128c..b27535962 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register1.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register1.adb @@ -28,4 +28,3 @@ end Test_Register1; -- =/double/ l! ## s!,dT-:"if Double" -- =/triple/ l! ## s!,dT-:"if Triple" -- =/hits/ l! ## s!,dT- - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register2.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register2.adb index 0641fe6d8..166f98eec 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register2.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Checks/src/test_register2.adb @@ -24,5 +24,3 @@ end Test_Register2; -- %tags:(7.1.2|7.2.2), bin-traces -- =/init/ l! ## s!, dF- -- =/triple/ l! ## s!, dT- - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Expr/src/test_register1.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Expr/src/test_register1.adb index 0c69d7e8c..998eec0ce 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Expr/src/test_register1.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Expr/src/test_register1.adb @@ -28,4 +28,3 @@ end; -- =/double/ l! ## s!,dT-:"if Double" -- =/triple/ l! ## s!,dT-:"if Triple" -- =/hits/ l! ## s!,dT- - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/register.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/register.adb index 9de8bf9f9..4d8876a98 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/register.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/register.adb @@ -19,7 +19,7 @@ begin -- if/else; simple decision if Hit > 0 then This_Score := Hit; else This_Score := 0; End if; -- # init - -- if/no-else; simple decision. No check nor expr eval + -- if/no-else; simple decision. No check nor expr eval if Double then This_Score := Times (This_Score, 2); end if; -- # double -- if/no-else; stmt; simple decision diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/test_register2.adb b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/test_register2.adb index ee9d154c2..87c79488e 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/test_register2.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/Straight/src/test_register2.adb @@ -24,4 +24,3 @@ end; -- %tags:(7.1.2|7.2.2), bin-traces -- =/init/ l! ## s!,dF-:"if Hit > 0" -- =/triple/ l! ## s!,dT-:"if Triple" - diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/darts.ads b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/darts.ads index dd918c42f..75a1acc6b 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/darts.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/darts.ads @@ -1,4 +1,4 @@ -package Darts is +package Darts is type Game is record Score, Hits, Fancy_Hits : Natural := 0; end record; diff --git a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/register.ads b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/register.ads index ef27fd4f0..fa8cd0958 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/register.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/MultiStmtLines/src/register.ads @@ -2,5 +2,3 @@ with Darts; use Darts; procedure Register (Hit : Natural; Double, Triple : Boolean; G : in out Game); - - diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.adb b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.adb index cd91343e5..7892123e9 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.adb @@ -38,4 +38,3 @@ package body Basic is end; end; - diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.ads b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.ads index 6a14a46e4..1b39618e7 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/basic.ads @@ -1,11 +1,10 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; package Basic is - + Last_Long, Last_Short : Unbounded_String := Null_Unbounded_String; - + procedure Try1 (A : String); procedure Try2 (A : String); procedure Try3 (A : String); end; - diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/ops.ads b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/ops.ads index 4a866e76d..fea7b58db 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/ops.ads @@ -3,11 +3,11 @@ use Ada.Strings; use Ada.Strings.Unbounded; package Ops is procedure Tryme (A : String; N : Natural; B : String; X : Integer); - + Last_Long, Last_Short, Last_mapped : Unbounded_String := Null_Unbounded_String; N_Xpos, N_Xneg, N_Xzero : Integer := 0; - + type Last_Category is (Long, Short, Mapped); - + procedure Check (Which : Last_Category; S : String); end; diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_abab_tf.adb b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_abab_tf.adb index f5758a490..6ae18e887 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_abab_tf.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_abab_tf.adb @@ -6,7 +6,7 @@ begin Check (Which => Long, S => ""); Check (Which => Short, S => "A*1"); Check (Which => Mapped, S => "22"); - + Tryme (A => "A", N => 2, B => "B", X => 1); Check (Which => Long, S => ""); Check (Which => Short, S => "A*2"); diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_f.adb b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_f.adb index 448da4a5c..b8c5c0a8c 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_f.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_f.adb @@ -21,4 +21,3 @@ end; -- /test/ l! ## dT- -- /long/ l- ## s- -- /short/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_t.adb b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_t.adb index fcc7503c6..5ecdd6e5f 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_t.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_t.adb @@ -21,4 +21,3 @@ end; -- /test/ l! ## dF- -- /long/ l+ ## 0 -- /short/ l- ## s- - diff --git a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_tf.adb b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_tf.adb index 6feb9e0c3..0d835fb95 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_tf.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/Ustrings/src/test_basic_tf.adb @@ -33,4 +33,3 @@ end; -- /test/ l+ ## 0 -- /long/ l+ ## 0 -- /short/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_1.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_1.adb index ed3769ceb..6e40849cf 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_1.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_1.adb @@ -16,4 +16,4 @@ end Test_1; -- /eval-if-expr/ l! ## eF-, d! -- --%opts: --trace-mode=src --- /eval-if-expr/ l! ## eF-, dF- \ No newline at end of file +-- /eval-if-expr/ l! ## eF-, dF- diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_2.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_2.adb index 335c33c6c..bc437be3e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_2.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_2.adb @@ -16,4 +16,4 @@ end Test_2; -- /eval-if-expr/ l! ## eF-, d! -- --%opts: --trace-mode=src --- /eval-if-expr/ l! ## eF-, dF- \ No newline at end of file +-- /eval-if-expr/ l! ## eF-, dF- diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_3.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_3.adb index e1fda93eb..0e7365d5d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_3.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/ComplexInDecision/src/test_3.adb @@ -17,4 +17,4 @@ end Test_3; -- /eval-if-expr/ l! ## eF-, d! -- --%opts: --trace-mode=src --- /eval-if-expr/ l! ## eF-, dF- \ No newline at end of file +-- /eval-if-expr/ l! ## eF-, dF- diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_f.adb index 91827e62c..9dfeeed57 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_f.adb @@ -17,4 +17,3 @@ end; --%opts: --trace-mode=src -- =/ifa/ l! ## dT- -- =/ifnota/ l! ## dT- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_t.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_t.adb index 43b69c2c1..436f3ca75 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_t.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_t.adb @@ -17,4 +17,3 @@ end; --%opts: --trace-mode=src -- =/ifa/ l! ## dF- -- =/ifnota/ l! ## dF- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_tf.adb b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_tf.adb index 5ba7aec4e..322f66f77 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_tf.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/SimpleCtl/src/test_tf.adb @@ -17,5 +17,3 @@ end; --# sys.adb -- /ifa/ l+ ## 0 -- /ifnota/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/extra.opt b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/extra.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/extra.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/IfExpr/extra.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/NoEval/ShortCut/src/andidor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/NoEval/ShortCut/src/andidor.adb index 9f0e6828e..fc4294f0d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/NoEval/ShortCut/src/andidor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/NoEval/ShortCut/src/andidor.adb @@ -11,4 +11,3 @@ begin return False; -- # false end if; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ArrayAggregates/src/pools.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ArrayAggregates/src/pools.ads index e36d249b5..e419fcd41 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ArrayAggregates/src/pools.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ArrayAggregates/src/pools.ads @@ -20,4 +20,3 @@ package Pools is Valid_Loc : Pool := (others => 'C'); end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand.ads index ff82b82c0..d7de06657 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand.ads @@ -11,6 +11,3 @@ package FUAND is function Poslen_And_Eql (Ops : Keys) return Boolean; -- Whether Ops.A'Length is positive and the same as Ops.B'Length end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand_helper.adb index 26bb3ccc0..d672e6e38 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuand_helper.adb @@ -34,4 +34,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor.ads index b6d8ff187..a47f322a1 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor.ads @@ -11,6 +11,3 @@ package FUOR is function Empty_Or_Eql (Ops : Keys) return Boolean; -- Whether Ops.A'Length is null or the same as Ops.B'Length end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor_helper.adb index aaa5e9402..b3e310e4a 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Attributes/src/fuor_helper.adb @@ -33,4 +33,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand.ads index ff6bd5224..7e52ff999 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand.ads @@ -1,16 +1,16 @@ with System; use System; package FUAND is - + type Operands is record A, B : Boolean; end record; - + for Operands'Bit_Order use High_Order_First; for Operands use record A at 0 range 0 .. 0; B at 0 range 1 .. 1; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand_helper.adb index 484ee3042..d2fddfb57 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuand_helper.adb @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor.ads index 0be8c5d0d..ba108bf8f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor.ads @@ -4,7 +4,7 @@ package FUOR is type Operands is record A, B : Boolean; end record; - + for Operands'Bit_Order use Low_Order_First; for Operands use record A at 0 range 0 .. 0; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor_helper.adb index a9e905750..ee96d2797 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/BitOrdered/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuand_helper.adb index 484ee3042..d2fddfb57 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuand_helper.adb @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuor_helper.adb index a9e905750..ee96d2797 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Components/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand.ads index a214d0cb5..ff5179279 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand.ads @@ -6,4 +6,3 @@ package FUAND is (S, Post1, Post2 : String; Max : Integer) return Boolean; -- Whether Op & Post1 and Op & Post2 remain <= Max in length end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand_helper.adb index 680285f3f..1178df7fe 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuand_helper.adb @@ -35,4 +35,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor.ads index 62976b480..e9b5e63e3 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor.ads @@ -6,6 +6,3 @@ package FUOR is (S, Post1, Post2 : String; Max : Integer) return Boolean; -- Whether Op & Post1 or Op & Post2 remain <= Max in length end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor_helper.adb index c8353377e..b2051f512 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Concats/src/fuor_helper.adb @@ -35,4 +35,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand.ads index 1d3ec79bf..34cfb801f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand.ads @@ -1,10 +1,10 @@ package FUAND is - + type Value_T is (TT, FF); - + type Operands is record A, B : Value_T; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand_helper.adb index a6e04b35a..0f7ff0d2b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FF, FF))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor.ads index 6c07d4075..91f52df5d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor.ads @@ -1,11 +1,11 @@ package FUOR is - + type T_Values is (FF, TT); for T_Values use (4, 5); - + type Operands is record A, B : T_Values; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor_helper.adb index 0d27e2ce8..6d9e19a3e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/EnumOps/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand.ads index f2a8d5a81..c75860991 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand.ads @@ -1,17 +1,17 @@ package FUAND is - + type Volt is delta 0.125 range 0.0 .. 255.0; - + type Capsum is record X, Y, Cap : Volt; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand_helper.adb index a6e04b35a..0f7ff0d2b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FF, FF))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor.ads index 72fa89695..e282aed19 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor.ads @@ -1,17 +1,17 @@ package FUOR is - + type Volt is delta 0.125 range 0.0 .. 255.0; - + type Capsum is record X, Y, Cap : Volt; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor_helper.adb index 0d27e2ce8..6d9e19a3e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FixedOps/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand.ads index b4cc48de7..8c7083925 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand.ads @@ -1,17 +1,17 @@ package FUAND is - - type My_Float is digits 10 range -5.0 .. 5.0; - + + type My_Float is digits 10 range -5.0 .. 5.0; + type Capsum is record X, Y, Cap : My_Float; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand_helper.adb index a6e04b35a..0f7ff0d2b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FF, FF))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor.ads index ff6ec9867..1d8a3fc95 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor.ads @@ -1,17 +1,17 @@ package FUOR is - - type My_Float is digits 8 range -5.0 .. 5.0; - + + type My_Float is digits 8 range -5.0 .. 5.0; + type Capsum is record X, Y, Cap : My_Float; end record; - + FF : constant Capsum := (X => 1.0, Y => 1.0, Cap => 1.0); TT : constant Capsum := (X => 1.0, Y => 1.0, Cap => 3.0); - + type Operands is record A, B : Capsum; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor_helper.adb index 0d27e2ce8..6d9e19a3e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/FloatOps/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand.ads index 183691852..99a63c530 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand.ads @@ -1,23 +1,23 @@ package FUAND is - + type Int is new Integer range 600 .. 607; - + type Char is new Character range 'A' .. 'Z'; type Char_Array is array (Int'Range) of Char; - + type Operand is record Index : Int; Data : Char_Array; end record; - + type Operands is record A, B : Operand; end record; - + -- We will evaluate for each operand whether .data(.index+1) = 'T' - - Common_Data : constant Char_Array := - (600 => 'A', + + Common_Data : constant Char_Array := + (600 => 'A', 601 => 'B', 602 => 'T', 603 => 'Y', @@ -25,11 +25,11 @@ package FUAND is 605 => 'T', 606 => 'U', 607 => 'V'); - + TT1 : constant Operand := (Index => 601, Data => Common_Data); TT2 : constant Operand := (Index => 604, Data => Common_Data); FF1 : constant Operand := (Index => 600, Data => Common_Data); FF2 : constant Operand := (Index => 605, Data => Common_Data); - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand_helper.adb index ae58eca96..5baa576c9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FF1, FF2))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor.ads index 7e097fd9b..f2a3b001b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor.ads @@ -1,23 +1,23 @@ package FUOR is - + type Int is new Integer range 600 .. 607; - + type Char is new Character range 'A' .. 'Z'; type Char_Array is array (Int'Range) of Char; - + type Operand is record Index : Int; Data : Char_Array; end record; - + type Operands is record A, B : Operand; end record; - + -- We will evaluate for each operand whether .data(.index+1) = 'T' - - Common_Data : constant Char_Array := - (600 => 'A', + + Common_Data : constant Char_Array := + (600 => 'A', 601 => 'B', 602 => 'T', 603 => 'Y', @@ -25,11 +25,11 @@ package FUOR is 605 => 'T', 606 => 'U', 607 => 'V'); - + TT1 : constant Operand := (Index => 601, Data => Common_Data); TT2 : constant Operand := (Index => 604, Data => Common_Data); FF1 : constant Operand := (Index => 600, Data => Common_Data); FF2 : constant Operand := (Index => 605, Data => Common_Data); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor_helper.adb index 81864abb1..9eb7d1a3b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/IntChar/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSlice/src/starts.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSlice/src/starts.adb index 355eb2d3b..198f7e29c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSlice/src/starts.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSlice/src/starts.adb @@ -3,4 +3,3 @@ begin return Key'Length <= S'Length -- # startsLength and then S (S'First .. S'First + Key'Length - 1) = Key; -- # startsKey end Starts; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSliceAggr/src/starts.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSliceAggr/src/starts.adb index aefa4b8c6..e12e3b24d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSliceAggr/src/starts.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mixed/AttrSliceAggr/src/starts.adb @@ -3,4 +3,3 @@ begin return Len <= S'Length -- # startsLength and then S (S'First .. S'First + Len - 1) = (1 .. Len => C); -- # startsKey end Starts; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand.ads index 857499cdd..24b6ed4d3 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand.ads @@ -9,6 +9,3 @@ package FUAND is function Mod0_And (OpA, OpB : Modop) return Boolean; -- Whether OpA.X mod OpA.Y and OpB.X mod OpB.Y are null end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand_helper.adb index 76a766289..50a76ffe4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuand_helper.adb @@ -26,4 +26,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor.ads index ecc21cad0..a8af32167 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor.ads @@ -9,6 +9,3 @@ package FUOR is function Mod0_Or (OpA, OpB : Modop) return Boolean; -- Whether OpA.X mod OpA.Y or OpB.X mod OpB.Y is null end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor_helper.adb index 01085abec..b65cd2873 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Mods/src/fuor_helper.adb @@ -26,4 +26,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand.ads index 517e62691..3e9bd0e79 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand.ads @@ -1,12 +1,12 @@ package FUAND is type I8 is new Integer range -2 ** 7 .. 2 * 7 -1; for I8'Size use 8; - + type Operands is record Sand : Boolean; A, B : I8; end record; pragma Pack (Operands); - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand_helper.adb index 470b08e19..959039231 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((Sand => True, A => 0, B => 0))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor.ads index 5e9091817..fb411c6d2 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor.ads @@ -1,12 +1,12 @@ package FUOR is type I8 is new Integer range -2 ** 7 .. 2 * 7 -1; for I8'Size use 8; - + type Operands is record Sand : Boolean; A, B : I8; end record; pragma Pack (Operands); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor_helper.adb index 5253fa9d0..60b7e88c8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Packed/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.adb index 0359ed17e..302a242b0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.adb @@ -3,16 +3,16 @@ pragma Ada_2012; with Support; use Support; package body Ops is - + type T_Status is tagged record A : T_Action; W : T_What_Ahead; end record; - + type T_Qualified_Status is new T_Status with record Ss : T_Safety_Status; end record; - + function Q1 (S : T_Status) return T_Safety_Status is begin if S.A = Step and then S.W = Pit then -- # test @@ -21,7 +21,7 @@ package body Ops is return Safe; -- # safe end if; end; - + procedure Q2 (S : T_Status; Ss : out T_Safety_Status) is begin if S.A = Step and then S.W = Pit then -- # test @@ -30,7 +30,7 @@ package body Ops is Ss := Safe; -- # safe end if; end; - + procedure Q3 (S : in out T_Qualified_Status) is begin if S.A = Step and then S.W = Pit then -- # test @@ -39,7 +39,7 @@ package body Ops is S.Ss := Safe; -- # safe end if; end; - + function Q4 (S : in out T_Qualified_Status) return Integer is begin if S.A = Step and then S.W = Pit then -- # test @@ -49,26 +49,26 @@ package body Ops is end if; return 0; end; - + function Qualify (A : T_Action; W : T_What_Ahead) return T_Safety_Status is S1 : T_Safety_Status; begin S1 := Q1 ((A, W)); - + declare S2 : T_Safety_Status; begin Q2 ((A, W), S2); Assert (S2 = S1); end; - + declare QS : T_Qualified_Status := (A => A, W => W, SS => <>); begin Q3 (QS); Assert (QS.Ss = S1); end; - + declare QS : T_Qualified_Status := (A => A, W => W, SS => <>); X : Integer; @@ -79,5 +79,5 @@ package body Ops is return S1; end; - + end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.ads index d1b21c4f8..c206f1d87 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/src/ops.ads @@ -1,9 +1,9 @@ package Ops is - + type T_Action is (Hold, Step); type T_What_Ahead is (Ground, Pit); - + type T_Safety_Status is (Safe, Unsafe); - + function Qualify (A : T_Action; W : T_What_Ahead) return T_Safety_Status; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/ParameterModes/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand.ads index 482f3b392..fb6c936e9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand.ads @@ -1,7 +1,7 @@ package FUAND is type I32 is new Integer range -2 ** 31 .. 2 * 31 -1; for I32'Size use 32; - + type Operands is record Sand : Boolean; A, B : I32; @@ -11,6 +11,6 @@ package FUAND is A at 0 range 1 .. 32; B at 0 range 33 .. 64; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand_helper.adb index 470b08e19..959039231 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((Sand => True, A => 0, B => 0))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor.ads index 519fdf48a..f78d01831 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor.ads @@ -1,7 +1,7 @@ package FUOR is type I32 is new Integer range -2 ** 31 .. 2 * 31 -1; for I32'Size use 32; - + type Operands is record Sand : Boolean; A, B : I32; @@ -11,6 +11,6 @@ package FUOR is A at 0 range 1 .. 32; B at 0 range 33 .. 64; end record; - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor_helper.adb index 5253fa9d0..60b7e88c8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Placed/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuand_helper.adb index 0689a5415..5d439a93a 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuand_helper.adb @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuor_helper.adb index 9296b6b15..e2371be33 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ranges/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand.ads index 2746e95ca..ddf93dae0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand.ads @@ -1,26 +1,26 @@ package FUAND is - + type Key is new String (1 .. 5); - + type Caller_Operand is record X, Y : Integer; K : Key; end record; - + type Operands is record A, B : Caller_Operand; end record; - + type Operand is record Pos, Even : Boolean; K : Key; end record; - + TTA : constant Caller_Operand := (1, 6, "AAKEY"); TTB : constant Caller_Operand := (5, 5, "BBKEY"); - + FFA : constant Caller_Operand := (1, 6, "AAKEX"); FFB : constant Caller_Operand := (1, 6, "BBKEY"); - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand_helper.adb index 5526edb51..753e03952 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FFA, FFB))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor.ads index 5332b1554..97ec469c5 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor.ads @@ -1,26 +1,26 @@ package FUOR is - + type Key is new String (1 .. 5); - + type Caller_Operand is record X, Y : Integer; K : Key; end record; - + type Operands is record A, B : Caller_Operand; end record; - + type Operand is record Pos, Even : Boolean; K : Key; end record; - + TTA : constant Caller_Operand := (1, 6, "AAKEY"); TTB : constant Caller_Operand := (5, 5, "BBKEY"); - + FFA : constant Caller_Operand := (1, 6, "AAKEX"); FFB : constant Caller_Operand := (1, 6, "BBKEY"); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor_helper.adb index 06d44f69d..1aaf75ec5 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/RecordAggregates/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/andthen_variants.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/andthen_variants.ads index 4636352f0..5b8e5505f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/andthen_variants.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/andthen_variants.ads @@ -1,7 +1,7 @@ package Andthen_Variants is subtype Bool_Subtype is Boolean; function And_Then_Subtype (A, B : Bool_Subtype) return Bool_Subtype; - + type Bool_Type is new Boolean; function And_Then_Type (A, B : Bool_Type) return Bool_Type; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/test_andthen_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/test_andthen_f.adb index 2c2719e64..85d66a02f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/test_andthen_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Subtypes/src/test_andthen_f.adb @@ -11,4 +11,3 @@ end; --# andthen_variants.adb -- /evaluate/ l! ## eT- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuand_helper.adb index 98d566b59..edf4a3c9d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((Values => (A => 0, B => 0)))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor_helper.adb index aeef48e71..57fbf0215 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand.ads index a3db71d5a..4c6d1367c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand.ads @@ -1,28 +1,28 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; package FUAND is - + type Key is new String (1 .. 5); - + type Caller_Operand is record X : Integer; US : Unbounded_String; end record; - + type Operands is record A, B : Caller_Operand; end record; - + type Operand is record Pos : Boolean; K : Unbounded_String; end record; - + TTA : constant Caller_Operand := (1, To_Unbounded_String ("USA")); TTB : constant Caller_Operand := (5, To_Unbounded_String ("USB")); - + FFA : constant Caller_Operand := (-1, To_Unbounded_String ("USA")); FFB : constant Caller_Operand := (1, To_Unbounded_String ("not USB")); - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand_helper.adb index 5526edb51..753e03952 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuand_helper.adb @@ -1,7 +1,7 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FFA, FFB))); @@ -23,4 +23,3 @@ package body FUAND_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.adb index 7edce8ece..5efdabfd0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.adb @@ -5,7 +5,7 @@ package body FUOR is function Orelse (Ops : Operands) return Boolean is Aop : Caller_Operand renames Ops.A; -- # decl Bop : Caller_Operand renames Ops.B; -- # decl - + begin return OperandA'(Match => To_String(Aop.US1 & Aop.US2) = "STARTEND") = (Match => True) -- # evalA or else OperandB'(To_Match => Translate (Bop.US1, To_Mapping("ABC", "012"))) = (To_Match => Bop.US2); -- # evalB diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.ads index 9c002b5f3..e2ceec6e2 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor.ads @@ -1,34 +1,34 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; package FUOR is - + type Key is new String (1 .. 5); - + type Caller_Operand is record US1, US2 : Unbounded_String; end record; - + type Operands is record A, B : Caller_Operand; end record; - + type OperandA is record Match : Boolean; end record; - + type OperandB is record To_Match : Unbounded_String; end record; - - TTA : constant Caller_Operand := + + TTA : constant Caller_Operand := (To_Unbounded_String ("START"), To_Unbounded_String("END")); - TTB : constant Caller_Operand := + TTB : constant Caller_Operand := (To_Unbounded_String("CAB"), To_Unbounded_String("201")); - - FFA : constant Caller_Operand := + + FFA : constant Caller_Operand := (To_Unbounded_String("A"), To_Unbounded_String("B")); FFB : constant Caller_Operand := (To_Unbounded_String("CAB"), To_Unbounded_String("11")); - + function Orelse (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor_helper.adb index 06d44f69d..1aaf75ec5 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Ustrings/src/fuor_helper.adb @@ -23,4 +23,3 @@ package body FUOR_Helper is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.adb index 8832ae009..80d279e13 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.adb @@ -1,6 +1,6 @@ pragma Ada_2012; package body FUAND is - + function Andthen (Ops : Operands) return Boolean is Aop : Control renames Ops.A; -- # decl Bop : Control renames Ops.B; -- # decl @@ -9,4 +9,3 @@ package body FUAND is and then Ops.B.X in Plus1(Bop.Y) | Twice(Bop.Y); -- # evalB end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.ads index fce494f97..226c92e0c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand.ads @@ -1,23 +1,23 @@ pragma Ada_2012; package FUAND is - + -- We will be checking if X in (2*Y | Y+1) - + type Control is record X, Y : Integer; end record; - + function Plus1 (Y : Integer) return Integer is (Y + 1); - + function Twice (Y : Integer) return Integer is (Y * 2); - + FF : constant Control := (X => 1, Y => 1); TT1 : constant Control := (X => 3, Y => 2); -- X = Y + 1 TT2 : constant Control := (X => 4, Y => 2); -- X = Y * 2 - + type Operands is record A, B : Control; end record; - + function Andthen (Ops : Operands) return Boolean; end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand_helper.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand_helper.adb index e8aef6048..a01349183 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand_helper.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Xfunctions/src/fuand_helper.adb @@ -1,25 +1,25 @@ with FUAND, Support; use FUAND, Support; package body FUAND_Helper is - + procedure Eval_FF_F is begin Assert (not Andthen ((FF, FF))); end; - + procedure Eval_FT_F is begin Assert (not Andthen ((FF, TT1))); end; - + procedure Eval_TF_F is begin Assert (not Andthen ((TT2, FF))); end; - + procedure Eval_TT_T is begin Assert (Andthen ((TT1, TT2))); end; - + end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_0.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_0.adb index bafb68bde..d158a3bb6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_0.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_0.adb @@ -10,4 +10,3 @@ end; -- /evalB/ l- ## 0c -- /oncall/ l- ## s- -- /decl/ ~l- ## ~s- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_a.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_a.adb index 42167c5db..c47a678e0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_a.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_a.adb @@ -9,4 +9,3 @@ end; --# fuand.adb -- /evalA/ l! ## 0 -- /evalB/ l! ## c!:"Op" - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_ab.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_ab.adb index 5109ef573..de11d5a5a 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_ab.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_ab.adb @@ -10,4 +10,3 @@ end; --# fuand.adb -- /evalA/ l+ ## 0 -- /evalB/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_b.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_b.adb index 52d563b4b..1e4b972d9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_b.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_b.adb @@ -9,4 +9,3 @@ end; --# fuand.adb -- /evalA/ l! ## c!:"Op" -- /evalB/ l! ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_f.adb index abfacb1cd..f149c4eae 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_f.adb @@ -10,4 +10,3 @@ end; --# fuand.adb -- /evalA/ l! ## eT- -- /evalB/ l! ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_t.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_t.adb index cc3ea60cb..c03165ae3 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_t.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuand_t.adb @@ -8,4 +8,3 @@ end; --# fuand.adb -- /evalA/ l! ## eF- -- /evalB/ l! ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_a.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_a.adb index d868ad212..36fa2f5d9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_a.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_a.adb @@ -9,4 +9,3 @@ end; --# fuor.adb -- /evalA/ l! ## 0 -- /evalB/ l! ## c!:"Op" - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_ab.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_ab.adb index 41d7ca78b..020840e04 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_ab.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_ab.adb @@ -10,4 +10,3 @@ end; --# fuor.adb -- /evalA/ l+ ## 0 -- /evalB/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_b.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_b.adb index a1dc5bbeb..00e74dab5 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_b.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_b.adb @@ -9,4 +9,3 @@ end; --# fuor.adb -- /evalA/ l! ## c!:"Op" -- /evalB/ l! ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_f.adb index 14fa70efd..501888ccf 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_f.adb @@ -8,4 +8,3 @@ end; --# fuor.adb -- /evalA/ l! ## eT- -- /evalB/ l! ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_t.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_t.adb index dfcbfe585..74251979a 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_t.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/src/test_fuor_t.adb @@ -10,4 +10,3 @@ end; --# fuor.adb -- /evalA/ l! ## eF- -- /evalB/ l! ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Aggregate/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Aggregate/src/andthen.adb index 5b0ea626b..65e26b45f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Aggregate/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Aggregate/src/andthen.adb @@ -10,6 +10,3 @@ package body Andthen is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Assignment/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Assignment/src/andthen.adb index 624a8da98..51d909066 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Assignment/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Assignment/src/andthen.adb @@ -12,4 +12,3 @@ package body Andthen is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/DeclInit/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/DeclInit/src/andthen.adb index 3c0375165..1324c2769 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/DeclInit/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/DeclInit/src/andthen.adb @@ -6,6 +6,3 @@ package body Andthen is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/src/andthen.adb index 00f954849..5eb47e9a8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/src/andthen.adb @@ -5,4 +5,3 @@ package body Andthen is return (if A and then B then True else False); -- # evalStmt :o/d: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Index/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Index/src/andthen.adb index 303bb3a9a..16af4ec52 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Index/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Index/src/andthen.adb @@ -6,4 +6,3 @@ package body Andthen is return Values (A and then B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/src/passand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/src/passand.adb index d0de1ab25..c3bebc485 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/src/passand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/src/passand.adb @@ -6,4 +6,3 @@ begin pragma Debug (Assert (A and then B)); -- # eval null; -- # stmt end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/Mix/src/points.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/Mix/src/points.adb index fe127c413..52c0708e9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/Mix/src/points.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/Mix/src/points.adb @@ -23,5 +23,3 @@ package body Points is return P1.X = P2.X and then P1.Y = P2.Y; -- # retSXY end; end; - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreBody/src/passand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreBody/src/passand.adb index 583d7e2c7..df6c30cfb 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreBody/src/passand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreBody/src/passand.adb @@ -6,4 +6,3 @@ procedure Passand (A, B : Boolean) is begin null; -- # stmt end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreDecl/src/passand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreDecl/src/passand.adb index cb211628c..8c24e7ae2 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreDecl/src/passand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/PreDecl/src/passand.adb @@ -4,4 +4,3 @@ procedure Passand (A, B : Boolean) is begin null; -- # stmt end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Return/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Return/src/andthen.adb index 02670874b..642b453a5 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Return/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Return/src/andthen.adb @@ -4,4 +4,3 @@ package body Andthen is return A and then B; -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.adb index 7df6c42b5..8ab468949 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.adb @@ -1,3 +1,2 @@ package body Andthen is end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.ads index 2a4962707..4b5437b25 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xfunction/src/andthen.ads @@ -1,9 +1,9 @@ pragma Ada_2012; package Andthen is - + pragma Elaborate_Body; -- # decl -- Just because the testcase architecture expects to always have a body - + function And_Then (A, B : Boolean) return Boolean is (A and then B); -- # evalStmt :o/e: end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/src/andthen.adb index ce9ef81c0..40c221f04 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/src/andthen.adb @@ -6,4 +6,3 @@ package body Andthen is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/src/test_andthen_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/src/test_andthen_f.adb index c27d52d46..4f66a8299 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/src/test_andthen_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/src/test_andthen_f.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Actual/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Actual/src/andcor.adb index 52266a15d..a0a743601 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Actual/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Actual/src/andcor.adb @@ -6,7 +6,7 @@ package body AndCOr is begin return Value (B or else C); -- # orelse :o/e: end; - + function F (A, B, C : Boolean) return Boolean is begin return Value (A and then Orelse (B, C)); -- # andthen :o/e: diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Aggregate/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Aggregate/src/andcor.adb index 9814e7bbb..0e1f3ed83 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Aggregate/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Aggregate/src/andcor.adb @@ -23,6 +23,3 @@ package body Andcor is end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Assignment/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Assignment/src/andcor.adb index 7bec45763..41e9a0370 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Assignment/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Assignment/src/andcor.adb @@ -1,10 +1,10 @@ package body AndCOr is - + function Orelse (B, C : Boolean) return Boolean is begin return B or else C; -- # orelse :o/e: end; - + procedure Eval_F (A, B, C : Boolean; E : out Boolean) is begin E := A and then Orelse (B, C); -- # andthen :o/e: @@ -17,4 +17,3 @@ package body AndCOr is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Case/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Case/src/andcor.adb index c5f6f1b57..e54185152 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Case/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Case/src/andcor.adb @@ -1,5 +1,5 @@ package body AndCOr is - + function Orelse (B, C : Boolean) return Boolean is begin case B or else C is -- # orelse :o/e: @@ -7,7 +7,7 @@ package body AndCOr is when False => return False; -- # orFalse end case; end; - + function F (A, B, C : Boolean) return Boolean is begin case A and then Orelse (B, C) is -- # andthen :o/e: diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/DeclInit/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/DeclInit/src/andcor.adb index 631326e8c..5f77f7cd9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/DeclInit/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/DeclInit/src/andcor.adb @@ -19,6 +19,3 @@ package body AndCor is end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Discriminant/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Discriminant/src/andcor.adb index a9638dbbc..ff5a19cda 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Discriminant/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Discriminant/src/andcor.adb @@ -1,12 +1,12 @@ package body AndCor is - + type My_Type (Value : Boolean) is null record; - + function Orelse (B, C : Boolean) return Boolean is begin return B or else C; -- # orelse :o/e: end; - + function F (A, B, C : Boolean) return Boolean is R : My_Type (Value => A and then Orelse (B, C)); -- # andthen :o/e: begin diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Exit/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Exit/src/andcor.adb index 4e2006c1e..bace37f98 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Exit/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Exit/src/andcor.adb @@ -1,5 +1,5 @@ package body AndCor is - + function Orelse (B, C : Boolean) return Boolean is begin loop @@ -8,7 +8,7 @@ package body AndCor is end loop; return True; -- # orTrue end; - + function F (A, B, C : Boolean) return Boolean is begin loop diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/If/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/If/src/andcor.adb index 10ab7ea86..dceeeec08 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/If/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/If/src/andcor.adb @@ -1,5 +1,5 @@ package body AndCOr is - + function Orelse (B, C : Boolean) return Boolean is begin if B or else C then -- # orelse :o/d: @@ -8,7 +8,7 @@ package body AndCOr is return False; -- # orFalse end if; end; - + function F (A, B, C : Boolean) return Boolean is begin if A and then Orelse (B, C) then -- # andthen :o/d: diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt index 460eb2f94..cd54c6b08 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt @@ -1,2 +1,2 @@ bin-traces,CARGS_O1 XFAIL T706-019: decision map issue -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Index/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Index/src/andcor.adb index 608324a59..1edc62b3e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Index/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Index/src/andcor.adb @@ -3,7 +3,7 @@ package body AndCOr is begin return B or else C; -- # orelse :o/e: end; - + function F (A, B, C : Boolean) return Boolean is Value : array (Boolean) of Boolean := (False => False, True => True); begin diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/While/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/While/src/andcor.adb index e9fcf6954..7b2a576c4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/While/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/While/src/andcor.adb @@ -1,5 +1,5 @@ package body AndCor is - + function Orelse (B, C : Boolean) return Boolean is begin while B or else C loop -- # orelse :o/d: @@ -7,7 +7,7 @@ package body AndCor is end loop; return False; -- # orFalse end; - + function F (A, B, C : Boolean) return Boolean is begin while A and then Orelse (B, C) loop -- # andthen :o/d: diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/src/andcor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/src/andcor.adb index fe43188aa..836d939e0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/src/andcor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/src/andcor.adb @@ -15,4 +15,3 @@ package body AndCor is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Aggregate/src/andidor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Aggregate/src/andidor.adb index 3691f9673..64b5b21d1 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Aggregate/src/andidor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Aggregate/src/andidor.adb @@ -10,4 +10,3 @@ package body AndIdOr is return E.Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Assignment/src/andidor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Assignment/src/andidor.adb index 6b213617c..ed1f81665 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Assignment/src/andidor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Assignment/src/andidor.adb @@ -12,4 +12,3 @@ package body AndIdOr is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/DeclInit/src/andidor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/DeclInit/src/andidor.adb index 9630d1251..d5cbfa7cf 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/DeclInit/src/andidor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/DeclInit/src/andidor.adb @@ -6,4 +6,3 @@ package body AndIdOr is return R; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Discriminant/src/andidor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Discriminant/src/andidor.adb index 8465ee537..1724c939f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Discriminant/src/andidor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Discriminant/src/andidor.adb @@ -1,5 +1,5 @@ package body AndIdOr is - + type My_Type (Value : Boolean) is null record; function F (A, B, C : Boolean) return Boolean is diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/src/andidor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/src/andidor.adb index f6eccb60f..6688bd7c8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/src/andidor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/src/andidor.adb @@ -8,4 +8,3 @@ package body Andidor is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndIdOr/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Aggregate/src/andnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Aggregate/src/andnot.adb index 5eda527cf..6906e6c1d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Aggregate/src/andnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Aggregate/src/andnot.adb @@ -10,6 +10,3 @@ package body Andnot is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Assignment/src/andnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Assignment/src/andnot.adb index ff5de39f2..fe1165525 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Assignment/src/andnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Assignment/src/andnot.adb @@ -12,4 +12,3 @@ package body Andnot is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/DeclInit/src/andnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/DeclInit/src/andnot.adb index 0bd7fcdfb..d6b74a579 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/DeclInit/src/andnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/DeclInit/src/andnot.adb @@ -6,6 +6,3 @@ package body Andnot is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Index/src/andnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Index/src/andnot.adb index 02624aa39..2f0950d48 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Index/src/andnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Index/src/andnot.adb @@ -6,4 +6,3 @@ package body Andnot is return Values (A and then not B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Return/src/andnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Return/src/andnot.adb index f0a51719a..61679555c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Return/src/andnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Return/src/andnot.adb @@ -4,4 +4,3 @@ package body Andnot is return A and then not B; -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/src/andnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/src/andnot.adb index 9f3db1f2a..e7fc3b704 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/src/andnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/src/andnot.adb @@ -6,4 +6,3 @@ package body Andnot is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/src/test_andnot_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/src/test_andnot_f.adb index 6a9143a21..5c9fb7571 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/src/test_andnot_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndNot/src/test_andnot_f.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Assignment/src/andporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Assignment/src/andporp.adb index 267a83513..6075bfb13 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Assignment/src/andporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Assignment/src/andporp.adb @@ -12,4 +12,3 @@ package body AndPorP is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Index/src/andporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Index/src/andporp.adb index 8d5fb10e2..31cf62266 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Index/src/andporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Index/src/andporp.adb @@ -7,4 +7,3 @@ package body AndPorP is return Values (A and then (B or else C)); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xfunction/src/andporp.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xfunction/src/andporp.ads index 6f9ea93ac..af57bf3c7 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xfunction/src/andporp.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xfunction/src/andporp.ads @@ -2,7 +2,7 @@ pragma Ada_2012; package Andporp is pragma Elaborate_Body; -- # decl -- Just because the testcase architecture expects to always have a body - + function F (A, B, C : Boolean) return Boolean is (A and then (B or else C)); -- # evalStmt :o/e: end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/src/andporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/src/andporp.adb index d06498435..312c4fc97 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/src/andporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/src/andporp.adb @@ -9,4 +9,3 @@ package body AndPorP is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/src/andporp.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/src/andporp.ads index 3880ef535..757833f42 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/src/andporp.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndpOrp/src/andporp.ads @@ -1,3 +1,3 @@ -package AndPorP is - function F (A, B, C : Boolean) return Boolean; -end; \ No newline at end of file +package AndPorP is + function F (A, B, C : Boolean) return Boolean; +end; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.adb index 4c9c4527b..cfaed4fb1 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.adb @@ -1,24 +1,23 @@ -package body AndPorPand_Coupled is - - function F1 (A, B, C : Boolean) return Boolean is - D : Boolean := A; -- # decl - begin - return A and then (B or else C) and then D; -- # F1_evaluate - end F1; - - function F2 (A, B, C : Boolean) return Boolean is - D : Boolean := B; -- # decl - pragma Volatile (D); -- preserve eval of B or else D - begin - return A and then (B or else D) and then C; -- # F2_evaluate - end F2; - - function F3 (A, B, C : Boolean) return Boolean is - D : Boolean := A; -- # decl - pragma Volatile (D); -- preserve eval - begin - return A and then (D or else B) and then C; -- # F3_evaluate - end F3; - -end AndPorPand_Coupled; - +package body AndPorPand_Coupled is + + function F1 (A, B, C : Boolean) return Boolean is + D : Boolean := A; -- # decl + begin + return A and then (B or else C) and then D; -- # F1_evaluate + end F1; + + function F2 (A, B, C : Boolean) return Boolean is + D : Boolean := B; -- # decl + pragma Volatile (D); -- preserve eval of B or else D + begin + return A and then (B or else D) and then C; -- # F2_evaluate + end F2; + + function F3 (A, B, C : Boolean) return Boolean is + D : Boolean := A; -- # decl + pragma Volatile (D); -- preserve eval + begin + return A and then (D or else B) and then C; -- # F3_evaluate + end F3; + +end AndPorPand_Coupled; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.ads index d2a10e2b3..06605c3c4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled.ads @@ -9,4 +9,3 @@ package AndPorPand_Coupled is function F3 (A, B, C : Boolean) return Boolean; end AndPorPand_Coupled; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.adb index e338b26f3..588d7e4c6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.adb @@ -1,23 +1,22 @@ -package body AndPorPand_Coupled_Alt is - - function F1 (A, B, C : Boolean) return Boolean is - begin - return A and then (B or else C) -- # F1_evaluate - and then A; -- # coupF1_evaluate - end F1; - - function F2 (A, B, C : Boolean) return Boolean is - begin - return A and then (B -- # F2_evaluate - or else B) and then C; -- # coupF2_evaluate - end F2; - - function F3 (A, B, C : Boolean) return Boolean is - D : Boolean := A; -- # decl - begin - return A and then -- # F3_evaluate - (A or else B) and then C; -- # coupF3_evaluate - end F3; - -end AndPorPand_Coupled_Alt; - +package body AndPorPand_Coupled_Alt is + + function F1 (A, B, C : Boolean) return Boolean is + begin + return A and then (B or else C) -- # F1_evaluate + and then A; -- # coupF1_evaluate + end F1; + + function F2 (A, B, C : Boolean) return Boolean is + begin + return A and then (B -- # F2_evaluate + or else B) and then C; -- # coupF2_evaluate + end F2; + + function F3 (A, B, C : Boolean) return Boolean is + D : Boolean := A; -- # decl + begin + return A and then -- # F3_evaluate + (A or else B) and then C; -- # coupF3_evaluate + end F3; + +end AndPorPand_Coupled_Alt; diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.ads index 168c991a6..3f10024e9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/andporpand_coupled_alt.ads @@ -9,4 +9,3 @@ package AndPorPand_Coupled_Alt is function F3 (A, B, C : Boolean) return Boolean; end AndPorPand_Coupled_Alt; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_2.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_2.adb index 4fe10af12..5b47017a8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_2.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_2.adb @@ -50,5 +50,3 @@ end Test_AndPorPand_Coupled_2; -- /returnValue/ l+ ## 0 -- /returnTrue/ l+ ## 0 -- /returnFalse/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_3.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_3.adb index ccf3db565..4c2713ee1 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_3.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_3.adb @@ -49,4 +49,3 @@ end Test_AndPorPand_Coupled_3; -- /returnValue/ l+ ## 0 -- /returnTrue/ l+ ## 0 -- /returnFalse/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_all.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_all.adb index 972a859c4..b6069affb 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_all.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_all.adb @@ -59,4 +59,3 @@ end Test_AndPorPand_Coupled_All; -- /returnValue/ l+ ## 0 -- /returnTrue/ l+ ## 0 -- /returnFalse/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_2.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_2.adb index 65d349a1e..4e2896b94 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_2.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_2.adb @@ -53,4 +53,3 @@ end Test_AndPorPand_Coupled_Alt_2; -- /returnValue/ l+ ## 0 -- /returnTrue/ l+ ## 0 -- /returnFalse/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_3.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_3.adb index 232c56931..aa7f22775 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_3.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_3.adb @@ -52,4 +52,3 @@ end Test_AndPorPand_Coupled_Alt_3; -- /returnValue/ l+ ## 0 -- /returnTrue/ l+ ## 0 -- /returnFalse/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_all.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_all.adb index 675299abe..ca1f6c5f6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_all.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/Obvious/src/test_andporpand_coupled_alt_all.adb @@ -61,4 +61,3 @@ end Test_AndPorPand_Coupled_Alt_All; -- /returnValue/ l+ ## 0 -- /returnTrue/ l+ ## 0 -- /returnFalse/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_all.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_all.adb index 04cd17fab..c6216d00a 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_all.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_all.adb @@ -20,5 +20,3 @@ end; --# cc4.adb -- /eval/ u=>l!, l+ ## u=>c!:"not A" - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_masking.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_masking.adb index e917d92c1..0388acea6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_masking.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Coupled/cc4/src/test_cc4_masking.adb @@ -15,5 +15,3 @@ end; --# cc4.adb -- /eval/ u=>l!, l+ ## u=>c!:"not A" - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/c3.ads b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/c3.ads index 9b82d18e1..0ecb1efc6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/c3.ads +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/c3.ads @@ -19,4 +19,3 @@ function C3 (A, B, C : Boolean) return Boolean; -- ip(A) = 1,5 -- ip(B) = 1,3 -- ip(C) = 2,3 4,5 + 2,5 3,4 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v1.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v1.adb index a222fcf30..5f5fdf37f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v1.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v1.adb @@ -9,5 +9,3 @@ end; --# c3.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v2.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v2.adb index 1e186c34c..7a94bb575 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v2.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v2.adb @@ -7,5 +7,3 @@ end; --# c3.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v3.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v3.adb index 5038b909c..b1f79ea81 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v3.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v3.adb @@ -7,5 +7,3 @@ end; --# c3.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v4.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v4.adb index 7414bf4e5..2f08c6e3d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v4.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v4.adb @@ -9,5 +9,3 @@ end; --# c3.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v5.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v5.adb index 7550676e6..1d739d2c0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v5.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Diamonds/c3/src/test_c3_v5.adb @@ -9,5 +9,3 @@ end; --# c3.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Aggregate/src/notand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Aggregate/src/notand.adb index 5e36745c6..8f08f2310 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Aggregate/src/notand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Aggregate/src/notand.adb @@ -10,6 +10,3 @@ package body Notand is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Assignment/src/notand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Assignment/src/notand.adb index 6a3fe0fff..5d744e1d5 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Assignment/src/notand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Assignment/src/notand.adb @@ -12,4 +12,3 @@ package body Notand is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/DeclInit/src/notand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/DeclInit/src/notand.adb index 665ec4574..797f6c48c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/DeclInit/src/notand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/DeclInit/src/notand.adb @@ -6,6 +6,3 @@ package body Notand is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Index/src/notand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Index/src/notand.adb index e894f6bb5..0eddf7deb 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Index/src/notand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Index/src/notand.adb @@ -7,4 +7,3 @@ package body Notand is return Values ((not A) and then B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Return/src/notand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Return/src/notand.adb index 17ba51b33..187502d89 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Return/src/notand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Return/src/notand.adb @@ -4,4 +4,3 @@ package body Notand is return (not A) and then B; -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/src/notand.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/src/notand.adb index b92afb2f8..b4dc7b19b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/src/notand.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/src/notand.adb @@ -6,4 +6,3 @@ package body Notand is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/src/test_notand_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/src/test_notand_f.adb index 7fd39d499..a8be83cad 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/src/test_notand_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAnd/src/test_notand_f.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Aggregate/src/notandnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Aggregate/src/notandnot.adb index 7796148e0..f533d857d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Aggregate/src/notandnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Aggregate/src/notandnot.adb @@ -10,6 +10,3 @@ package body Notandnot is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Assignment/src/notandnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Assignment/src/notandnot.adb index 5a9a646f9..5382d2ca9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Assignment/src/notandnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Assignment/src/notandnot.adb @@ -12,4 +12,3 @@ package body Notandnot is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/DeclInit/src/notandnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/DeclInit/src/notandnot.adb index e74d8d01d..be8d0551b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/DeclInit/src/notandnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/DeclInit/src/notandnot.adb @@ -6,6 +6,3 @@ package body Notandnot is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Index/src/notandnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Index/src/notandnot.adb index 4b008339c..4ba04c6c8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Index/src/notandnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Index/src/notandnot.adb @@ -7,4 +7,3 @@ package body Notandnot is return Values ((not A) and then (not B)); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Return/src/notandnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Return/src/notandnot.adb index b7e5b8bf8..b7956146d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Return/src/notandnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Return/src/notandnot.adb @@ -4,4 +4,3 @@ package body Notandnot is return (not A) and then (not B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/src/notandnot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/src/notandnot.adb index 2d48f9fc0..5fecaa0be 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/src/notandnot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/src/notandnot.adb @@ -6,4 +6,3 @@ package body Notandnot is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/src/test_notandnot_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/src/test_notandnot_f.adb index 2ca75a3cc..2923de606 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/src/test_notandnot_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotAndNot/src/test_notandnot_f.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Aggregate/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Aggregate/src/notor.adb index 16b6eed75..1833f703f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Aggregate/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Aggregate/src/notor.adb @@ -10,6 +10,3 @@ package body Notor is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Assignment/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Assignment/src/notor.adb index fb5422b71..8ae6192c7 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Assignment/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Assignment/src/notor.adb @@ -12,4 +12,3 @@ package body Notor is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/DeclInit/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/DeclInit/src/notor.adb index ffb0701b4..d1ebc8c2e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/DeclInit/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/DeclInit/src/notor.adb @@ -6,6 +6,3 @@ package body Notor is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/If/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/If/src/notor.adb index c67ea5fb5..b8261eb02 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/If/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/If/src/notor.adb @@ -8,4 +8,3 @@ package body Notor is end if; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Index/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Index/src/notor.adb index efe29cf5c..998538ed9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Index/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Index/src/notor.adb @@ -7,4 +7,3 @@ package body Notor is return Values ((not A) or else B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Return/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Return/src/notor.adb index 27f277f62..b3e4c7c4e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Return/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Return/src/notor.adb @@ -4,4 +4,3 @@ package body Notor is return (not A) or else B; -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/src/notor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/src/notor.adb index 46b98d204..3654b4f52 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/src/notor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/src/notor.adb @@ -6,4 +6,3 @@ package body Notor is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOr/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Aggregate/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Aggregate/src/notornot.adb index 1c741a939..98167c30c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Aggregate/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Aggregate/src/notornot.adb @@ -10,6 +10,3 @@ package body Notornot is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Assignment/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Assignment/src/notornot.adb index 32f7579c5..cc9415a88 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Assignment/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Assignment/src/notornot.adb @@ -12,4 +12,3 @@ package body Notornot is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/DeclInit/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/DeclInit/src/notornot.adb index fdc95bedd..b84165401 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/DeclInit/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/DeclInit/src/notornot.adb @@ -6,6 +6,3 @@ package body Notornot is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/If/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/If/src/notornot.adb index 9d541a99d..61fb29dc6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/If/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/If/src/notornot.adb @@ -8,4 +8,3 @@ package body Notornot is end if; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Index/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Index/src/notornot.adb index fd75514dd..6b2ec1bdd 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Index/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Index/src/notornot.adb @@ -6,4 +6,3 @@ package body Notornot is return Values ((not A) or else (not B)); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Return/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Return/src/notornot.adb index a86f68be2..2c5e989b9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Return/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Return/src/notornot.adb @@ -4,4 +4,3 @@ package body Notornot is return (not A) or else (not B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/src/notornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/src/notornot.adb index 3286b3c5b..efb0705e6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/src/notornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/src/notornot.adb @@ -6,4 +6,3 @@ package body Notornot is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/src/test_notornot_0.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/src/test_notornot_0.adb index a691af102..387d3950b 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/src/test_notornot_0.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/NotOrNot/src/test_notornot_0.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l- ## s- -- /returnValue/ l- ## s- -- /decl/ ~l- ## ~s- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Aggregate/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Aggregate/src/orelse.adb index 2eff69d85..8a311548c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Aggregate/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Aggregate/src/orelse.adb @@ -10,6 +10,3 @@ package body Orelse is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Assignment/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Assignment/src/orelse.adb index fbcc6addc..77cf56078 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Assignment/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Assignment/src/orelse.adb @@ -12,4 +12,3 @@ package body Orelse is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/DeclInit/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/DeclInit/src/orelse.adb index 8071136c4..a1519eede 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/DeclInit/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/DeclInit/src/orelse.adb @@ -6,6 +6,3 @@ package body Orelse is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/If/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/If/src/orelse.adb index 5e211c47b..cab437f3c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/If/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/If/src/orelse.adb @@ -8,4 +8,3 @@ package body Orelse is end if; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Index/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Index/src/orelse.adb index a3bce670b..475dca9c4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Index/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Index/src/orelse.adb @@ -6,4 +6,3 @@ package body Orelse is return Values (A or else B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/src/passor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/src/passor.adb index 71bd1ccee..8e0f82f3d 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/src/passor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/src/passor.adb @@ -6,4 +6,3 @@ begin pragma Debug (Assert (A or else B)); -- # eval null; -- # stmt end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreBody/src/passor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreBody/src/passor.adb index b525e505f..bfa782c5e 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreBody/src/passor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreBody/src/passor.adb @@ -6,4 +6,3 @@ procedure Passor (A, B : Boolean) is begin null; -- # stmt end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreDecl/src/passor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreDecl/src/passor.adb index 1b4c92529..dd12488e7 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreDecl/src/passor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/PreDecl/src/passor.adb @@ -4,4 +4,3 @@ procedure Passor (A, B : Boolean) is begin null; -- # stmt end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Return/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Return/src/orelse.adb index 22398b4b0..6671f6b01 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Return/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Return/src/orelse.adb @@ -4,4 +4,3 @@ package body Orelse is return A or else B; -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/src/orelse.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/src/orelse.adb index 2ed183ab5..e85acf379 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/src/orelse.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/src/orelse.adb @@ -6,4 +6,3 @@ package body Orelse is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Aggregate/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Aggregate/src/ornot.adb index 127c70c10..5a6767735 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Aggregate/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Aggregate/src/ornot.adb @@ -10,6 +10,3 @@ package body Ornot is return E.Value; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Assignment/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Assignment/src/ornot.adb index 4f94a0560..e407d69e6 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Assignment/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Assignment/src/ornot.adb @@ -12,4 +12,3 @@ package body Ornot is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/DeclInit/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/DeclInit/src/ornot.adb index f66a770f0..5bcef28f3 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/DeclInit/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/DeclInit/src/ornot.adb @@ -6,6 +6,3 @@ package body Ornot is return E; -- # returnValue end; end; - - - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/If/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/If/src/ornot.adb index 92c8e22e1..1475151d1 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/If/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/If/src/ornot.adb @@ -8,4 +8,3 @@ package body Ornot is end if; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Index/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Index/src/ornot.adb index 53ddbf122..d419767e7 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Index/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Index/src/ornot.adb @@ -7,4 +7,3 @@ package body Ornot is return Values (A or else (not B)); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Return/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Return/src/ornot.adb index 502537c88..af26ed00c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Return/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Return/src/ornot.adb @@ -4,4 +4,3 @@ package body Ornot is return A or else (not B); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/src/ornot.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/src/ornot.adb index c3b66b866..d54b7b2b4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/src/ornot.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/src/ornot.adb @@ -6,4 +6,3 @@ package body Ornot is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/src/test_ornot_0.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/src/test_ornot_0.adb index e2a65173d..4517fe533 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/src/test_ornot_0.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/OrNot/src/test_ornot_0.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l- ## s- -- /returnValue/ l- ## s- -- /decl/ ~l- ## ~s- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Assignment/src/pandpor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Assignment/src/pandpor.adb index 4bb871b9c..9de688ab4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Assignment/src/pandpor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Assignment/src/pandpor.adb @@ -12,4 +12,3 @@ package body PandPor is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/src/pandpor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/src/pandpor.adb index 7d90c1e53..e04ff6c51 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/src/pandpor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/src/pandpor.adb @@ -6,4 +6,3 @@ package body PandPor is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_0.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_0.adb index 06d45a695..36462ea26 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_0.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_0.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l- ## s- -- /returnValue/ l- ## s- -- /decl/ ~l- ## ~s- - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_a.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_a.adb index 7f2dbee8d..eff6f2fe9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_a.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_a.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ab.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ab.adb index d2a8e968d..08a21634f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ab.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ab.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc.adb index 70a21ccae..267cde734 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc.adb @@ -14,4 +14,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc_sc.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc_sc.adb index 5f1e3651f..920ad743f 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc_sc.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_abc_sc.adb @@ -14,4 +14,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ac.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ac.adb index da861f05e..29e15267c 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ac.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_ac.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_b.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_b.adb index bb985b7c3..ccfebd345 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_b.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_b.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c.adb index be8773c36..90b96ec22 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_mask.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_mask.adb index 0258c40cb..5d8e80db8 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_mask.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_mask.adb @@ -14,4 +14,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_sc.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_sc.adb index 341d32f9a..f835fc077 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_sc.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_c_sc.adb @@ -12,4 +12,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_cb.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_cb.adb index babb3f976..d9e0b46c0 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_cb.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_cb.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_f.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_f.adb index 387423f30..1c1553856 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_f.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_f.adb @@ -13,4 +13,3 @@ end; -- /decisionFalse/ l+ ## 0 -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_t.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_t.adb index 54560f044..ff12e17cf 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_t.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pAndpOr/src/test_pandpor_t.adb @@ -15,4 +15,3 @@ end; -- /decisionFalse/ l- ## s- -- /returnValue/ l+ ## 0 -- /decl/ ~l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Assignment/src/porpandporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Assignment/src/porpandporp.adb index 6f67d43a5..45aad66fc 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Assignment/src/porpandporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Assignment/src/porpandporp.adb @@ -12,4 +12,3 @@ package body PorPandPorP is return Value; -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/For/src/porpandporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/For/src/porpandporp.adb index 422c5776e..9f7767181 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/For/src/porpandporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/For/src/porpandporp.adb @@ -12,4 +12,3 @@ package body POrPAndPorP is return Touched (True); -- # returnValue end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/IfExprCtl/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/IfExprCtl/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Index/src/porpandporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Index/src/porpandporp.adb index fbc2ca992..87b343958 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Index/src/porpandporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Index/src/porpandporp.adb @@ -6,4 +6,3 @@ package body PorPandPorP is return Values ((A or else B) and then (C or else D)); -- # evalStmt :o/e: end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/src/porpandporp.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/src/porpandporp.adb index 82d68101f..39303cea4 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/src/porpandporp.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/src/porpandporp.adb @@ -9,4 +9,3 @@ package body PorPandPorP is end return; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/pOrpAndpOrp/Xreturn/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.adb b/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.adb index 67150aad0..9930eea1b 100644 --- a/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.adb +++ b/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.adb @@ -1,17 +1,17 @@ package body Ops is - + procedure Set (P : in out T_Pair'Class; X, Y : Integer) is begin P.X := X; -- # stmt P.Y := Y; -- # stmt P.Is_Set := True; -- # stmt end; - + function Valid (D : T_Double) return Boolean is begin return D.Y = D.X * 2; -- # check end; - + function Bad_Set (D : T_Double) return Boolean is begin return D.Is_Set and then D.Y /= D.X * 2; -- # eval diff --git a/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.ads b/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.ads index 9f9cb2936..39986954a 100644 --- a/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.ads +++ b/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.ads @@ -2,21 +2,21 @@ pragma Ada_2012; pragma Assertion_Policy (Invariant => Disable); package Ops is - + type T_Pair (Checked : Boolean := True) is tagged limited private with Type_Invariant'Class => Valid(T_Pair) or else Unchecked(T_Pair); - + procedure Set (P : in out T_Pair'Class; X, Y : Integer); function Valid (P : T_Pair) return Boolean is (True); -- # fn function Unchecked (P : T_Pair) return Boolean is (not P.Checked); -- # fn - + type T_Double is new T_Pair with private; - + function Valid (D : T_Double) return Boolean; function Bad_Set (D : T_Double) return Boolean; private - + type T_Pair (Checked : Boolean := True) is tagged limited record X, Y : Integer := 0; Is_Set : Boolean := False; @@ -24,5 +24,5 @@ private type T_Double is new T_Pair with null record with Type_Invariant => T_Double.X > 0 and then T_Double.Y > 0; - + end; diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/andthen.ads b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/andthen.ads index a6591813a..3600d1583 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/andthen.ads +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/andthen.ads @@ -13,5 +13,3 @@ function Andthen (A, B : Boolean) return Boolean; -- ip(A) = 3,0 3,1 -- ip(B) = 3,2 - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v0.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v0.adb index a0d410a9f..c222ac99e 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v0.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v0.adb @@ -7,5 +7,3 @@ end; --# andthen.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v1.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v1.adb index 78eb32d97..84f14350e 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v1.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v1.adb @@ -7,5 +7,3 @@ end; --# andthen.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v2.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v2.adb index 6260d1a20..a2ac95a57 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v2.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v2.adb @@ -7,5 +7,3 @@ end; --# andthen.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v3.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v3.adb index 7c663e17b..66228778a 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v3.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/And/src/test_andthen_v3.adb @@ -7,5 +7,3 @@ end; --# andthen.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/AndAB_OrCD/src/a1o2.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/AndAB_OrCD/src/a1o2.adb index 8c7238583..39caf5ef1 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/AndAB_OrCD/src/a1o2.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/AndAB_OrCD/src/a1o2.adb @@ -13,5 +13,3 @@ package body A1O2 is return Andthen (A and then B, C or else D); -- # evals end; end; - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/orelse.ads b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/orelse.ads index ef0afee69..7fe77dc80 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/orelse.ads +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/orelse.ads @@ -13,5 +13,3 @@ function Orelse (A, B : Boolean) return Boolean; -- ip(A) = 0,2 0,3 -- ip(B) = 0,1 - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v0.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v0.adb index fb875377b..0e41a0ffd 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v0.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v0.adb @@ -7,5 +7,3 @@ end; --# orelse.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v1.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v1.adb index b443d6f8e..55d03b105 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v1.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v1.adb @@ -7,5 +7,3 @@ end; --# orelse.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v2.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v2.adb index 517ec51cf..16734e0a0 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v2.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v2.adb @@ -7,5 +7,3 @@ end; --# orelse.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v3.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v3.adb index 7ab32716c..8970b1253 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v3.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/Or/src/test_orelse_v3.adb @@ -7,5 +7,3 @@ end; --# orelse.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/porpand.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/porpand.adb index 64278cb2b..bb2accfc5 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/porpand.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/porpand.adb @@ -2,4 +2,3 @@ function Porpand (A, B, C : Boolean) return Boolean is begin return (A or else B) and then C; -- # eval end; - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v1.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v1.adb index 990b357b6..3fe765cdc 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v1.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v1.adb @@ -9,5 +9,3 @@ end; --# porpand.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v2.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v2.adb index dfceb83b9..43e0a7424 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v2.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v2.adb @@ -7,5 +7,3 @@ end; --# porpand.adb -- /eval/ l! ## eT- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v3.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v3.adb index e794928f9..b03c19622 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v3.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v3.adb @@ -7,5 +7,3 @@ end; --# porpand.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v4.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v4.adb index 6ee0a105f..c3574e4a8 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v4.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v4.adb @@ -9,4 +9,3 @@ end; --# porpand.adb -- /eval/ l! ## eT- - diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v5.adb b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v5.adb index 631434ffa..e77f1d5a5 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v5.adb +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/pOrpAnd/src/test_porpand_v5.adb @@ -9,5 +9,3 @@ end; --# porpand.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_a.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_a.adb index a367a80a1..1229dcd43 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_a.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_a.adb @@ -25,4 +25,3 @@ end; -- /preValid/ l* ## x+ -- /preValid_cond/ l= ## XoT- -- /checkOverlap/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_b.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_b.adb index e44f620fc..e05d51638 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_b.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_invalid_b.adb @@ -25,4 +25,3 @@ end; -- /preValid/ l* ## x+ -- /preValid_cond/ l= ## XoT- -- /checkOverlap/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb index 78fe03d72..06eb48f37 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_no_overlap.adb @@ -26,4 +26,3 @@ end; -- /preValid/ l* ## x+ -- /preValid_cond/ l= ## XoF- -- /checkOverlap/ l! ## eT- - diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_overlap.adb b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_overlap.adb index c3b3d77c8..0e69afa0e 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_overlap.adb +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/PrecondInBody/src/test_ranges_overlap.adb @@ -42,4 +42,3 @@ end; -- /preValid/ l* ## x+ -- /preValid_cond/ l= ## XoF- -- /checkOverlap/ l! ## eF- - diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/extra.opt b/testsuite/Qualif/Ada/mcdc/Exemptions/extra.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/extra.opt +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/extra.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/sensors-status.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/sensors-status.adb index 3b5b4b2a2..fdd37df89 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/sensors-status.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/sensors-status.adb @@ -34,4 +34,3 @@ package body Sensors.Status is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_f_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_f_ff.adb index 44603b2a7..8177416b8 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_f_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_f_ff.adb @@ -3,13 +3,13 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_F_FF is S : Sensor; - + begin -- Outer If False only. Inner If False only from F or else F. S.ALB := 1; S.AHB := 15; S.V := 5; -- in range - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb index 5cf3c1967..ccf2169ce 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_ff.adb @@ -3,17 +3,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_FU_FF is S : Sensor; - + begin -- Outer If both True and False. Inner If False only from F or else F. - + S.ALB := 1; S.AHB := 15; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; -- in range - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb index 178f5c853..9cca081b1 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_fu_tx.adb @@ -6,15 +6,15 @@ procedure Test_FU_TX is begin -- Outer If both True and False. Inner If True only from T or else X. - + S.ALB := 1; S.AHB := 15; - + Assert (Status_Of (S) = Undecidable); - + S.V := 0; -- < low bound Sample (S); - + Assert (Status_Of (S) = Check); end; diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok.adb index ccf7554dc..c0427ae5b 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok.adb @@ -3,12 +3,12 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_OK is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb index 19b502264..a2b3ff264 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb @@ -4,19 +4,19 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Check_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); - + S.V := 40; Sample (S); Assert (Status_Of (S) = Broken); diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_t_0.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_t_0.adb index a8dd68a25..9bf811870 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_t_0.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_t_0.adb @@ -3,7 +3,7 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_T_0 is S : aliased Sensor; - + begin -- Outer If True only. Inner If not reached. S.V := 5; diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok.adb index 84ac650cf..bd5d27804 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok.adb @@ -4,17 +4,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Assert (Status_Of (S) = Undecidable); - + Sample (S); Assert (Status_Of (S) = Ok); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb index ccacd60e1..3f3299f28 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); - + S.V := 40; Sample (S); Assert (Status_Of (S) = Broken); diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_undecide.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_undecide.adb index 0dbd628d0..ed6ab2578 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_undecide.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/If_For_If_Case/src/test_undecide.adb @@ -3,12 +3,12 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Undecide is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Assert (Status_Of (S) = Undecidable); end; diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ff.adb index 0ce55e079..78a70bfd4 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ff.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 0 and then Ok.Len = 1); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ft.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ft.adb index d504b04a4..74da8b900 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ft.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_ft.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_tx.adb index c46f26d9f..f8d1f419e 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_fx_tx.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ff.adb index acc6cac42..35b61b732 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ff.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 0 and then Ok.Len = 1); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ft.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ft.adb index a18667518..6308ac408 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ft.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_ft.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_tx.adb index 4a55c3ecf..4c6cd0284 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tf_tx.adb @@ -19,4 +19,3 @@ begin Assert (Skip.Len = 0 and then Fault.Len = 1 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tt_xx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tt_xx.adb index f6ada261e..bb507610d 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tt_xx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/doif_tt_xx.adb @@ -16,4 +16,3 @@ begin Assert (Skip.Len = 1 and then Fault.Len = 0 and then Ok.Len = 0); end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_df.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_df.adb index 8f1de5501..446195ea8 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_df.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_df.adb @@ -21,4 +21,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_dt.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_dt.adb index c00f76a1b..944e6f307 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_dt.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_dt.adb @@ -7,7 +7,7 @@ procedure Test_DF_DT is begin Doif_FX_FT; Doif_FX_TX; - + Doif_TF_FT; Doif_TF_TX; end; @@ -25,4 +25,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_fu.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_fu.adb index 607625d83..97822124a 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_fu.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_df_fu.adb @@ -3,12 +3,12 @@ with Doif_TF_FT, Doif_TF_TX, Doif_TF_FF; procedure Test_DF_FU is begin - Doif_FX_FT; + Doif_FX_FT; Doif_TF_FT; - + Doif_FX_TX; Doif_TF_TX; - + Doif_FX_FF; Doif_TF_FF; end; @@ -26,4 +26,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_dt.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_dt.adb index bc296ec08..b48e33125 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_dt.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_dt.adb @@ -4,10 +4,10 @@ procedure Test_FU_DT is begin Doif_FX_FT; Doif_FX_TX; - + Doif_TF_FT; Doif_TF_TX; - + Doif_TT_XX; end; @@ -24,4 +24,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_fu.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_fu.adb index 2dee78d20..4d8cf777c 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_fu.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fu_fu.adb @@ -3,15 +3,15 @@ with Doif_TF_FT, Doif_TF_TX, Doif_TF_FF, Doif_TT_XX; procedure Test_FU_FU is begin - Doif_FX_FT; + Doif_FX_FT; Doif_TF_FT; - + Doif_FX_TX; Doif_TF_TX; - + Doif_FX_FF; Doif_TF_FF; - + Doif_TT_XX; end; @@ -28,4 +28,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ff.adb index 6c8d726ff..58c74ba50 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ff.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ft.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ft.adb index a93ffb3c1..3caac5fbd 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ft.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_ft.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_tx.adb index 1b846ea2d..841b44ff5 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_fx_tx.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ff.adb index 1af77d031..c02e262b5 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ff.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ft.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ft.adb index 53b003ec6..bf5bf2852 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ft.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_ft.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_tx.adb index 9e2c537d0..1b93fd997 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tf_tx.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tt_xx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tt_xx.adb index 9d414583a..0e66a352f 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tt_xx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/src/test_tt_xx.adb @@ -18,4 +18,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.adb index dd2dd3ea3..f734bf26f 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.adb @@ -26,4 +26,3 @@ package body Slists.Forall is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.ads b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.ads index d1d942c70..5d475d37b 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.ads +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/slists-forall.ads @@ -3,4 +3,3 @@ package Slists.Forall is procedure ForAll_In (SL : Sensor_List; Op : Sensor_Op; Active_Only : Boolean := False); end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_act_inh.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_act_inh.adb index eb6b2ff8e..b30b503b7 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_act_inh.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_act_inh.adb @@ -39,4 +39,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_activate.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_activate.adb index 304088fcf..fee4db76c 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_activate.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_activate.adb @@ -42,4 +42,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb index b6cac0779..e50cf022d 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_f_0_0.adb @@ -22,4 +22,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_a.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_a.adb index 41846741b..0ef1fe350 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_a.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_a.adb @@ -44,4 +44,3 @@ end; -- /FA_tinhibitHB/ l! ## c!:"Na.S.V" -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ff.adb index ddc2e7f46..c4f15815c 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ff.adb @@ -37,4 +37,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ft.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ft.adb index 734aae0d1..2e0370e01 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ft.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_ft.adb @@ -37,4 +37,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_tx.adb index 6d8e01c7a..3c0cfca65 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_a_tx.adb @@ -37,4 +37,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_b_0.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_b_0.adb index 7d50620f1..1c8a40ff0 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_b_0.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_b_0.adb @@ -34,4 +34,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb index 3e2108385..904ad2066 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ff_0.adb @@ -26,4 +26,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb index 4125c0496..a86293311 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_ft_0.adb @@ -28,4 +28,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb index 3f3641bd3..337dbbef9 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_0.adb @@ -30,4 +30,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb index 960567620..a5d3ee5a2 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ff.adb @@ -8,15 +8,15 @@ begin -- While decision covered from loop over non empty list -- First If decision True only from T or else X. -- Inner If decision False only from F or else F. - + S1.ALB := 1; S1.AHB := 15; S1.V := 5; -- in range Prepend (S1'Unchecked_Access, SL); - + S1.Active := True; for X in False .. True loop - Forall_In (SL, Inhibit, Active_Only => X); + Forall_In (SL, Inhibit, Active_Only => X); end loop; end; @@ -31,4 +31,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb index 4dfd25e54..f8ff6f4dc 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_ft.adb @@ -8,15 +8,15 @@ begin -- While decision covered from loop over non empty list -- First If decision True only from T or else X. -- Inner If decision True only from T or else X. - + S1.ALB := 1; S1.AHB := 15; S1.V := 30; -- > high bound Prepend (S1'Unchecked_Access, SL); - + for X in False .. True loop S1.Active := True; - Forall_In (SL, Inhibit, Active_Only => X); + Forall_In (SL, Inhibit, Active_Only => X); end loop; end; @@ -31,4 +31,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb index 2fc2809e6..a66b9170f 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_fu_tx_tx.adb @@ -8,15 +8,15 @@ begin -- While decision covered from loop over non empty list -- First If decision True only from T or else X. -- Inner If decision True only from T or else X. - + S1.ALB := 1; S1.AHB := 15; S1.V := 0; -- < low bound Prepend (S1'Unchecked_Access, SL); - + for X in False .. True loop S1.Active := True; - Forall_In (SL, Inhibit, Active_Only => X); + Forall_In (SL, Inhibit, Active_Only => X); end loop; end; @@ -31,4 +31,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_inhibit.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_inhibit.adb index b50f37c55..37549fde0 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_inhibit.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_inhibit.adb @@ -39,4 +39,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_nocase.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_nocase.adb index 070f2bfbd..a169fc396 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_nocase.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_nocase.adb @@ -24,4 +24,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noentry.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noentry.adb index 5ecd96515..7509dbb46 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noentry.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noentry.adb @@ -18,4 +18,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb index bb2dae1c1..248a17063 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb @@ -7,14 +7,14 @@ procedure Test_Noinhibit is begin -- get into the inhibit case selection, arranging for the -- if statement there to always evaluate false - + S1.ALB := 1; S1.AHB := 10; S1.V := 5; -- # in range S1.Active := True; - + Prepend (S1'Unchecked_Access, SL); - + Forall_In (SL, Inhibit); Assert (S1.Active); end; @@ -30,4 +30,3 @@ end; -- /FA_tinhibitHB/ l! ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.adb index 404de97f8..a4f0b96fc 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.adb @@ -5,5 +5,3 @@ package body Sensors is Vbufs.Push (S.V, S.History); end; end; - - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.ads b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.ads index 4af84cd8c..1700b03cd 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.ads +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/sensors.ads @@ -16,4 +16,3 @@ package Sensors is -- latch current sensor value for S in its history buffer end; - diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/slists.adb b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/slists.adb index 168c92b9f..2701bf287 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/slists.adb +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/slists.adb @@ -5,7 +5,7 @@ package body Slists is package Sensor_Nodes_Pool is new Simple_Pools.Basic_Pool (Data_Type => Sensor_Node, Capacity => 20); - + procedure Prepend (S : Sensor_Access; SL : in out Sensor_List) is NA : constant Sensor_Nodes_Pool.Data_Access := Sensor_Nodes_Pool.Allocate; begin diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/vbufs.ads b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/vbufs.ads index 1e5ad1b18..49646f52c 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/vbufs.ads +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/src/vbufs.ads @@ -13,4 +13,3 @@ package Vbufs is procedure Push (V : Value; VB : in out Vbuffer); end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.adb index f90033c9b..cc4f4994e 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.adb @@ -6,4 +6,3 @@ begin return False; -- # false end if; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.ads b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.ads index 714977050..9a2115848 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.ads +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/and_eq_or.ads @@ -9,5 +9,3 @@ function And_Eq_Or (A, B, C, D : Boolean) return Boolean; -- 1) F F F -- 2) T X T -- 3) F T T - - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ac_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ac_t.adb index d3c27527c..665bbb5ea 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ac_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ac_t.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## c!:"B", c!:"D", dF-:"(A" -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_af.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_af.adb index 382773744..3265190d2 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_af.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_af.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## c!:"B", eT-:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb index 615dc1be7..bcd61cbf7 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## c!:"B", eF-:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bd_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bd_f.adb index 02db31115..00b3f1b18 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bd_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bd_f.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## c!:"A", c!:"C", dT-:"(A" -- /true/ l- ## s- -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bf.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bf.adb index 30c181e80..17289fabb 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bf.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_bf.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## c!:"A", eT-:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fc.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fc.adb index 1f1db709a..ebaa4f0bd 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fc.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fc.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## eT-:"A", c!:"D" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ff.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ff.adb index 3c518745e..d811f8ddb 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ff.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_ff.adb @@ -10,4 +10,3 @@ end; -- /eval/ l! ## eT-:"A", eT-:"C", dF-:"(A" -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fuf.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fuf.adb index e68b8676c..601206dd9 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fuf.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fuf.adb @@ -12,4 +12,3 @@ end; -- /eval/ l! ## eT-:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fut.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fut.adb index 05de6d400..2c594b51b 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fut.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_fut.adb @@ -12,4 +12,3 @@ end; -- /eval/ l! ## eF-:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tc.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tc.adb index 06ca1bc82..0552aa03b 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tc.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tc.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## eF-:"A", c!:"D" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_td.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_td.adb index 769507a90..b2d4df7ba 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_td.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_td.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## eF-:"A", c!:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tfu.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tfu.adb index b3317c584..3830d7a00 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tfu.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tfu.adb @@ -12,4 +12,3 @@ end; -- /eval/ l! ## eF-:"A" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tt.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tt.adb index de9c71c77..d3995be0f 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tt.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_tt.adb @@ -10,4 +10,3 @@ end; -- /eval/ l! ## eF-:"A", eF-:"C", dF-:"(A" -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/mix.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/mix.adb index e89c32a3e..f2c536d04 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/mix.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/mix.adb @@ -2,5 +2,3 @@ function Mix (A, B, C, D, E, Z, T : Boolean) return Boolean is begin return (A and then ((B or else C) = ((D and then E) /= (Z or else T)))); -- # eval end; - - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/test_1.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/test_1.adb index 6be17a8fe..18dcb4b92 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/test_1.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Mix_ABCDEZT/src/test_1.adb @@ -4,8 +4,8 @@ procedure Test_1 is begin Assert (Mix (A => True, B => True, C => False, -- B or C True | = is T - D => False, E => False, -- D and E False | /= is T | - Z => True, T => True) -- F or G True | + D => False, E => False, -- D and E False | /= is T | + Z => True, T => True) -- F or G True | = True); end; diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac.adb index 78ba1f3cf..290657767 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac.adb @@ -8,5 +8,3 @@ end; --# or_eq_and_not.adb -- /eval/ l! ## c!:"B", c!:"not D" - - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_tt.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_tt.adb index 60ba71aa7..f738d734a 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_tt.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_tt.adb @@ -7,5 +7,3 @@ end; --# or_eq_and_not.adb -- /eval/ l! ## eF-:"A", eF-:"C" - - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndAB/src/test_a1a1_v2.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndAB/src/test_a1a1_v2.adb index 478afbc0f..9f45fcb61 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndAB/src/test_a1a1_v2.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndAB/src/test_a1a1_v2.adb @@ -10,4 +10,3 @@ end; --# a1a1.adb -- /evals/ l! ## eT-:"A and then B," # eT-:"A and then B)" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.adb index 295479011..4cbc39255 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.adb @@ -1,10 +1,9 @@ with Evals; use Evals; package body A1A2 is - + procedure Process (A, B, C, D : Boolean) is begin Eval (A and then B, C and then D); -- # evals end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.ads b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.ads index 713809595..3af024823 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.ads +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/a1a2.ads @@ -2,4 +2,3 @@ package A1A2 is procedure Process (A, B, C, D : Boolean); -- Evaluate A and then B as well as C and then B on the same line. end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_c.adb index f35128403..2a3b33107 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_c.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"B" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_cd.adb index 2f10b8713..50c627ae1 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_cd.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"B" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_d.adb index 706d07fad..3f1ae10b4 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_d.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"B" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_f.adb index 2b2848977..369766e59 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_f.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"B" # eT-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_t.adb index bfeffa40d..a8ebae2e4 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_a_t.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"B" # eF-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_c.adb index e43158709..bdb7c3e49 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_c.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_cd.adb index 31835eb98..d184d0043 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_cd.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_d.adb index 3d7621ea1..95c922864 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_d.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_f.adb index 67237f22f..c0f2cafbd 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_f.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## eT-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_t.adb index 7c63e3fe5..0cfd2a967 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_ab_t.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## eF-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_c.adb index 47cc5403c..8e8339a65 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_c.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"A" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_cd.adb index 8f884d956..acef0de02 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_cd.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"A" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_d.adb index c329a5a11..d2e9d92b2 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_d.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"A" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_f.adb index 043193f21..1398bbb2c 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_f.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"A" # eT-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_t.adb index a7369ec3f..0181d5975 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_b_t.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## c!:"A" # eF-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_c.adb index 9fc4620ea..77c52cc84 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_c.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## eT-:"A and then B" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_cd.adb index b2b15fe3a..5c474c4df 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_cd.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## eT-:"A and then B" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_d.adb index 80a205891..2e1bc8f04 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_d.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## eT-:"A and then B" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_f.adb index a8f4089f1..92ee9541c 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_f.adb @@ -5,10 +5,9 @@ begin Process (A => True, B => False, C => True, D => False); Process (A => False, B => False, C => True, D => False); Process (A => False, B => True, C => True, D => False); - + Process (A => False, B => True, C => False, D => True); end; --# a1a2.adb -- /evals/ l! ## eT-:"A and then B" # eT-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_t.adb index 5545381ed..4da8405b1 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_f_t.adb @@ -7,4 +7,3 @@ end; --# a1a2.adb -- /evals/ l! ## eT-:"A and then B" # eF-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_c.adb index 2ee645591..06cd6b531 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_c.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## eF-:"A and then B" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_cd.adb index 8798a0ef2..a15f5bfbf 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_cd.adb @@ -9,4 +9,3 @@ end; --# a1a2.adb -- /evals/ l! ## eF-:"A and then B" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_d.adb index d81168336..a4aed3570 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_d.adb @@ -8,4 +8,3 @@ end; --# a1a2.adb -- /evals/ l! ## eF-:"A and then B" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_f.adb index 052374ee3..80feebbb5 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_f.adb @@ -7,4 +7,3 @@ end; --# a1a2.adb -- /evals/ l! ## eF-:"A and then B" # eT-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_t.adb index 5cea57143..ba21bf5b0 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_AndCD/src/test_a1a2_t_t.adb @@ -7,4 +7,3 @@ end; --# a1a2.adb -- /evals/ l! ## eF-:"A and then B" # eF-:"C and then D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.adb index 9d5f1276b..da606ac58 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.adb @@ -7,4 +7,3 @@ package body A1O2 is Eval (A and then B, C or else D); -- # evals end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.ads b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.ads index 3e0d8e72b..629ac84db 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.ads +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/a1o2.ads @@ -2,4 +2,3 @@ package A1O2 is procedure Process (A, B, C, D : Boolean); -- Evaluate A and then B as well as C or else B on the same line. end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_c.adb index 393f1e327..3bfa0156d 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_c.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"B" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_cd.adb index 2eb339f7b..37256abe2 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_cd.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"B" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_d.adb index 2293263d6..ade0ceb5e 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_d.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"B" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_f.adb index 1f6bbb98c..57eccc005 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_f.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"B" # eT-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_t.adb index a91bc6dc7..3f234a6c0 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_a_t.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"B" # eF-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_c.adb index 43d0d31c5..ef6053313 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_c.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_cd.adb index e5985ff7c..b81617d4a 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_cd.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_d.adb index aa1659fdf..ecae4f97d 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_d.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_f.adb index c8b6ec71c..71a2ebe22 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_f.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## eT-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_t.adb index 6fa1183ad..cfcd342cc 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_ab_t.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## eF-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_c.adb index 347e18b93..7f6f621af 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_c.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"A" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_cd.adb index c54ad1146..6697e6da4 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_cd.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"A" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_d.adb index dc9ebaefc..762440a2d 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_d.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"A" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_f.adb index 89c65a813..cc6c8e4a6 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_f.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"A" # eT-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_t.adb index f1a67b1d7..a2842cf43 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_b_t.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## c!:"A" # eF-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_c.adb index 8e17f7ddb..7ac80b10e 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_c.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## eT-:"A and then B" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_cd.adb index 94e4e3707..cf12bc75a 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_cd.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## eT-:"A and then B" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_d.adb index c26576f28..83843b0ff 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_d.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## eT-:"A and then B" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_f.adb index 2e97f56de..382ee8de6 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_f.adb @@ -5,10 +5,9 @@ begin Process (A => True, B => False, C => False, D => False); Process (A => False, B => False, C => False, D => False); Process (A => False, B => True, C => False, D => False); - + Process (A => False, B => True, C => False, D => False); end; --# a1o2.adb -- /evals/ l! ## eT-:"A and then B" # eT-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_t.adb index c45fce867..b9a55c688 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_f_t.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## eT-:"A and then B" # eF-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_c.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_c.adb index d392fefa8..f81648d24 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_c.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_c.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## eF-:"A and then B" # c!:"D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_cd.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_cd.adb index 520a26d29..e7073407b 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_cd.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_cd.adb @@ -9,4 +9,3 @@ end; --# a1o2.adb -- /evals/ l! ## eF-:"A and then B" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_d.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_d.adb index c6d4e2bba..92edd8a4c 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_d.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_d.adb @@ -8,4 +8,3 @@ end; --# a1o2.adb -- /evals/ l! ## eF-:"A and then B" # c!:"C" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_f.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_f.adb index 349bb0a55..eeaac6697 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_f.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_f.adb @@ -7,4 +7,3 @@ end; --# a1o2.adb -- /evals/ l! ## eF-:"A and then B" # eT-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_t.adb index 2b6f8d964..663f61dcd 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/TwoFormals/AndAB_OrCD/src/test_a1o2_t_t.adb @@ -7,4 +7,3 @@ end; --# a1o2.adb -- /evals/ l! ## eF-:"A and then B" # eF-:"C or else D" - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.adb index 72a74034e..22d599584 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.adb @@ -9,4 +9,3 @@ package body Evals is VB := B; end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.ads b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.ads index 58ac94219..74243918a 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.ads +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiDecisionLine/src/evals.ads @@ -7,4 +7,3 @@ package Evals is procedure Eval (A, B : Boolean); end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/If/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/If/src/andthen.adb index 93ef737ac..8387e9793 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/If/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/If/src/andthen.adb @@ -8,5 +8,3 @@ begin return False; -- # false end if; end; - - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/Return/src/andthen.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/Return/src/andthen.adb index 5f2733a1e..78be2de43 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/Return/src/andthen.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/Return/src/andthen.adb @@ -3,5 +3,3 @@ begin return A -- # eval0 :o/e: and then B; -- # eval1 end; - - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/src/test_andthen_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/src/test_andthen_t.adb index 7934451d2..5c2639b8c 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/src/test_andthen_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/And/src/test_andthen_t.adb @@ -10,4 +10,3 @@ end; -- /eval1/ l! ## 0 -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/Or/src/test_orelse_t.adb b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/Or/src/test_orelse_t.adb index d1c2c8a35..da8fb0848 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/Or/src/test_orelse_t.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/MultiLineDecisions/Or/src/test_orelse_t.adb @@ -12,4 +12,3 @@ end; -- /eval1/ l! ## 0 -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/constructors.adb b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/constructors.adb index 9ae1c6569..ef4ed97d3 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/constructors.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/constructors.adb @@ -1,10 +1,10 @@ with Simple_Pools; package body Constructors is - + package Band_Pool is new Simple_Pools.Basic_Pool (Data_Type => Band, Capacity => 20); - + function Expr_And (A, B : Expr_Ref) return Expr_Ref is Eptr : constant Band_Pool.Data_Access := Band_Pool.Allocate; begin @@ -23,4 +23,3 @@ package body Constructors is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/exprs-e_and.adb b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/exprs-e_and.adb index cf4477d3c..38d6535b7 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/exprs-e_and.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/And/src/exprs-e_and.adb @@ -4,5 +4,5 @@ package body Exprs.E_And is begin return E.A.all.Eval and then E.B.all.Eval; -- # eval end; - + end; diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RA/src/constructors.adb b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RA/src/constructors.adb index 73bb95dd4..424e817f8 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RA/src/constructors.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RA/src/constructors.adb @@ -4,7 +4,7 @@ package body Constructors is package Bandor_Pool is new Simple_Pools.Basic_Pool (Data_Type => Bandor, Capacity => 20); - + function Expr_Andor (A, B, C : Expr_Ref) return Expr_Ref is Eptr : constant Bandor_Pool.Data_Access := Bandor_Pool.Allocate; begin @@ -23,4 +23,3 @@ package body Constructors is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RC/src/constructors.adb b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RC/src/constructors.adb index 37423d2bb..c5957c5bc 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RC/src/constructors.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/Andor_RC/src/constructors.adb @@ -4,7 +4,7 @@ package body Constructors is package Bandor_Pool is new Simple_Pools.Basic_Pool (Data_Type => Bandor, Capacity => 20); - + function Expr_Andor (A, B, C : Expr_Ref) return Expr_Ref is Eptr : constant Bandor_Pool.Data_Access := Bandor_Pool.Allocate; begin @@ -23,4 +23,3 @@ package body Constructors is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.adb b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.adb index acc9f379b..281481854 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.adb @@ -1,10 +1,10 @@ with Simple_Pools; package body Exprs.E_Val is - + package Bval_Pool is new Simple_Pools.Basic_Pool (Data_Type => Bval, Capacity => 64); - + function Eval (E : Bval) return Boolean is begin return E.V; @@ -18,4 +18,3 @@ package body Exprs.E_Val is end; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.ads b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.ads index 416ded972..18407d837 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.ads +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs-e_val.ads @@ -8,4 +8,3 @@ package Exprs.E_Val is function Expr_Val (V : Boolean) return Expr_Ref; end; - diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs.ads b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs.ads index 13c126148..b46c937b9 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs.ads +++ b/testsuite/Qualif/Ada/mcdc/Robustness/Recurse/src/exprs.ads @@ -1,9 +1,8 @@ package Exprs is - + type Expr is abstract tagged null record; type Expr_Ref is access all Expr'Class; - + function Eval (E : Expr) return Boolean is abstract; function Eval (E : Expr_Ref) return Boolean; end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/support_pragmas.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/support_pragmas.adb index c752ec3ae..98d03b1a9 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/support_pragmas.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/support_pragmas.adb @@ -11,4 +11,3 @@ package body Support_Pragmas is end Debug_Proc2; end Support_Pragmas; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.opt index 9271f3fe6..961ea3846 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.opt @@ -1 +1 @@ -src-traces XFAIL TODO: revisit requirements and expectations once we re-enable assertion instrumentation (U528-022) \ No newline at end of file +src-traces XFAIL TODO: revisit requirements and expectations once we re-enable assertion instrumentation (U528-022) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.adb index c67bd53c9..c26151380 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.adb @@ -47,4 +47,4 @@ package body Defs is return Result; -- # 2_stmt end Some_Fun_2; -end; \ No newline at end of file +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.ads b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.ads index b4bc3465a..91c54c392 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/defs.ads @@ -29,4 +29,4 @@ package Defs is -- real-life-looking contest for a discrete subtype definition in the -- body. -end; \ No newline at end of file +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/test_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/test_no.adb index f83329177..1a8967e5a 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/test_no.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DiscreteSubtypeDefs/src/test_no.adb @@ -28,7 +28,3 @@ end; -- /2_1_loop/ l- ## s- -- /2_2_loop/ l- ## s- -- /2_if/ l- ## s- - - - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.adb index 9fbf4a74e..a35240c76 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.adb @@ -1,5 +1,5 @@ package body Heap is - + function Ptr_To_Abs (X : Integer) return Integer_Access is begin if X > 0 then -- # on-call diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.ads b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.ads index 2f52e7cfe..481000c12 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/heap.ads @@ -1,10 +1,10 @@ package Heap is - + -- This unit is devised to expose services making use of heap allocation -- in object declarations. type Integer_Access is access Integer; function Ptr_To_Abs (X : Integer) return Integer_Access; - + Global : Integer_Access := new Integer'(15); -- # global-decl end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_0.adb index 7f30afa8b..377d24cd3 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_0.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_0.adb @@ -14,4 +14,3 @@ end; -- /pos-stmt/ l- ## s- -- /neg-decl/ l- ## s- -- /neg-stmt/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_all.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_all.adb index b4f8723c8..2879643e7 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_all.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_all.adb @@ -17,4 +17,3 @@ end; -- /pos-stmt/ l+ ## 0 -- /neg-decl/ l+ ## 0 -- /neg-stmt/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_neg.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_neg.adb index 5d7717a7e..69e7e89ce 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_neg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_neg.adb @@ -15,4 +15,3 @@ end; -- /pos-stmt/ l- ## s- -- /neg-decl/ l+ ## 0 -- /neg-stmt/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_pos.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_pos.adb index 6870db52c..ea4a63496 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_pos.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_heap_pos.adb @@ -15,4 +15,3 @@ end; -- /pos-stmt/ l+ ## 0 -- /neg-decl/ l- ## s- -- /neg-stmt/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_0.adb index 241f2d72e..9d9428a69 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_0.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_0.adb @@ -1,5 +1,5 @@ with Vectors; use Vectors; - + procedure Test_Vectors_0 is begin null; @@ -11,4 +11,3 @@ end; -- /pos-stmt/ l- ## s- -- /neg-decl/ l- ## s- -- /neg-stmt/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_neg.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_neg.adb index beaa3f237..313f5b0cf 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_neg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_neg.adb @@ -1,5 +1,5 @@ with Support, Vectors; use Support, Vectors; - + procedure Test_Vectors_Neg is begin Assert (Sum_All_Abs (N => 7, Value => -4) = 28); @@ -11,4 +11,3 @@ end; -- /pos-stmt/ l- ## s- -- /neg-decl/ l+ ## 0 -- /neg-stmt/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_pos.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_pos.adb index e0883533b..373abe394 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_pos.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/test_vectors_pos.adb @@ -1,5 +1,5 @@ with Support, Vectors; use Support, Vectors; - + procedure Test_Vectors_Pos is begin Assert (Sum_All_Abs (N => 5, Value => 3) = 15); @@ -11,4 +11,3 @@ end; -- /pos-stmt/ l+ ## 0 -- /neg-decl/ l- ## s- -- /neg-stmt/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.adb index 2c1642151..8c60b3370 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.adb @@ -1,11 +1,11 @@ package body Vectors is - + function All_Same (N : Integer; Value : Integer) return Vector is begin return Vector'(1 .. N => Value); -- # on-call end; - + function Sum_All_In (V : Vector) return Integer is Sum : Integer := 0; -- # on-call begin @@ -14,12 +14,12 @@ package body Vectors is end loop; return Sum; -- # on-call end; - + function Sum_All_Abs (N : Integer; Value : Integer) return Integer is begin -- point here is to have conditional object declarations resorting to a -- function returning unconstrained for initializers - + if Value > 0 then -- # on-call declare V : Vector := All_Same (N, Value); -- # pos-decl @@ -34,5 +34,5 @@ package body Vectors is end; end if; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.ads b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.ads index 8f0e7e447..6eef34a53 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/src/vectors.ads @@ -1,10 +1,10 @@ package Vectors is - + -- This unit is devised to expose services making use of unconstrained -- array types requiring secondary stack allocations for oject declarations. - + type Vector is array (Natural range <>) of Integer; - + function Sum_All_Abs (N : Integer; Value : Integer) return Integer; end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/test.opt index 5484161b8..22f48c3f5 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/test.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/DynObjects/test.opt @@ -1 +1 @@ -7.1.2,RTS_ZFP DEAD the 7.1.2 zfp RTS doesn't support dynamic allocations \ No newline at end of file +7.1.2,RTS_ZFP DEAD the 7.1.2 zfp RTS doesn't support dynamic allocations diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/integer_swap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/integer_swap.adb index a15c2b5b3..7d48c1121 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/integer_swap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/integer_swap.adb @@ -9,4 +9,3 @@ begin I := J; -- # stmt J := Tmp; -- # stmt end Integer_Swap; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/matrix_swap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/matrix_swap.adb index 5b9111134..669d716d6 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/matrix_swap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/matrix_swap.adb @@ -9,4 +9,3 @@ begin M1 := M2; -- # stmt M2 := Tmp; -- # stmt end Matrix_Swap; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/private_swap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/private_swap.adb index c85f575db..02051f135 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/private_swap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/private_swap.adb @@ -8,4 +8,3 @@ begin V1 := V2; -- # stmt V2 := Tmp; -- # stmt end Private_Swap; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_derived_swap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_derived_swap.adb index 6ffef2c1e..a52ef805f 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_derived_swap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_derived_swap.adb @@ -12,4 +12,3 @@ begin V2 := Tmp; -- # if end if; end Record_Derived_Swap; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_impl_init_swap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_impl_init_swap.adb index d385fc272..f89673b47 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_impl_init_swap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_impl_init_swap.adb @@ -12,4 +12,3 @@ begin V2 := Tmp; -- # if end if; end Record_Impl_Init_Swap; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_swap.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_swap.adb index edd45d6bf..80dc3e03f 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_swap.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/record_swap.adb @@ -8,4 +8,3 @@ begin C1 := C2; -- # stmt C2 := Tmp; -- # stmt end Record_Swap; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_full.adb index ca486db22..764837e16 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_full.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_full.adb @@ -19,7 +19,7 @@ with Support; use Support; procedure Test_Object_Declarations_Full is package Decls_Pack_Matrix is new Decls_Pack_Matrix_G (1, 2); use Decls_Pack_Matrix; - + package Decls_Pack_Records is new Decls_Pack_Records_G; use Decls_Pack_Records; @@ -37,7 +37,7 @@ procedure Test_Object_Declarations_Full is Coord1 : Coordinate := Coordinate_Zero; Coord2 : Coordinate := (1.0, 1.0); - + Coord_Value1 : aliased Coordinate := (1.0, 2.0); Coord_Value2 : aliased Coordinate := (3.0, 4.0); Coord_Var1 : Access_All_Coordinate := Coord_Value1'Unchecked_Access; @@ -48,10 +48,10 @@ procedure Test_Object_Declarations_Full is Matr1 : Matrix := (1 => (1 => 1)); Matr2 : Matrix := (1 => (1 => 2)); - + P_Var1 : T_Private := Get_Private (10); P_Var2 : T_Private := Get_Private (20); - + Int_Value1 : aliased Integer := 1; Int_Value2 : aliased Integer := 2; Var1 : Access_All_Integer := Int_Value1'Unchecked_Access; @@ -97,7 +97,7 @@ begin Assert (Coord2 = Coordinate_Zero and then Coord1 = (1.0, 1.0)); -- Call all the subprograms from library packages - + Decls_Pack_1.Local_Swap (Int1, Int2); Assert (Int1 = 1 and then Int2 = 2); Assert (Decls_Pack_1.Local_Fun (Mon) = Tue); @@ -112,7 +112,7 @@ begin Decls_Pack_Records.Local_Swap (Coord1, Coord2); Assert (Coord1 = Coordinate_Zero and then Coord2 = (1.0, 1.0)); - + Decls_Pack_Derived_Records.Local_Swap (V1, V2); Assert (V1.X = 2.0 and then V1.Y = 20.0 and then diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_no.adb index fe03e74b2..868b3b06d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_no.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_no.adb @@ -40,4 +40,3 @@ end Test_Object_Declarations_No; --# record_impl_init_swap.adb -- /stmt/ l- ## s- -- /if/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_part_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_part_1.adb index 17e5f5ea6..1cd5a77f2 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_part_1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/ObjectDecls/src/test_object_declarations_part_1.adb @@ -27,7 +27,7 @@ procedure Test_Object_Declarations_Part_1 is package Decls_Pack_Matrix is new Decls_Pack_Matrix_G (1, 2); use Decls_Pack_Matrix; - + package Decls_Pack_Derived_Records is new Decls_Pack_Derived_Records_G; use Decls_Pack_Derived_Records; @@ -44,7 +44,7 @@ procedure Test_Object_Declarations_Part_1 is Matr1 : Matrix := (1 => (1 => 1)); Matr2 : Matrix := (1 => (1 => 2)); - + V1 : Derived_Coordinate := (1.0, 10.0); V2 : Derived_Coordinate := (2.0, 20.0); begin @@ -64,7 +64,7 @@ begin Matrix_Swap (Matr1, Matr2); Assert (Matr1 (1, 1) = 2 and then Matr2 (1, 1) = 1); - + -- Call subprograms from library packages Decls_Pack_1.Local_Swap (Int1, Int2); Assert (Int1 = 1 and then Int2 = 2); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_full.adb index 16ff72855..9b9f03b29 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_full.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_full.adb @@ -31,8 +31,3 @@ end Test_Subtype_Indications_Full; -- /2_stmt/ l+ ## 0 -- /3_local_dcl/ l+ ## 0 -- /3_stmt/ l+ ## 0 - - - - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_no.adb index 15bdcfdc8..ff07390bc 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_no.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_no.adb @@ -21,8 +21,3 @@ end Test_Subtype_Indications_No; -- /2_stmt/ l- ## s- -- /3_local_dcl/ l- ## ~s- -- /3_stmt/ l- ## s- - - - - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_1.adb index 3c6bb7722..9bd9b49e4 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_1.adb @@ -25,8 +25,3 @@ end Test_Subtype_Indications_Part_1; -- /2_stmt/ l- ## s- -- /3_local_dcl/ l- ## ~s- -- /3_stmt/ l- ## s- - - - - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_2.adb index dfeb13a2d..aedc1d618 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_2.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_2.adb @@ -30,8 +30,3 @@ end Test_Subtype_Indications_Part_2; -- /2_stmt/ l+ ## 0 -- /3_local_dcl/ l+ ## 0 -- /3_stmt/ l+ ## 0 - - - - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/test.opt index 41fffe494..3bdc92db6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/test.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/test.opt @@ -1 +1 @@ -7.1.2,RTS_ZFP DEAD test resorts to sec stack, not in the 7.1.2 zfp RTS \ No newline at end of file +7.1.2,RTS_ZFP DEAD test resorts to sec stack, not in the 7.1.2 zfp RTS diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.adb index 7eacf06bd..65b79a8b4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.adb @@ -20,4 +20,3 @@ package body Assignment_Statements is end Max_Value; end Assignment_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.ads index 0c9ad10a3..839c835ee 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements.ads @@ -4,4 +4,3 @@ package Assignment_Statements is -- These subprograms contain assignment statements in straightline -- statement sequences end Assignment_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.adb b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.adb index 8a5826ec6..294f5ad30 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.adb @@ -2,4 +2,3 @@ package body Assignment_Statements_Elab is begin I := 1 ; end Assignment_Statements_Elab; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.ads b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.ads index 1e62794c9..78012f874 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/51_Assign/src/assignment_statements_elab.ads @@ -3,4 +3,3 @@ package Assignment_Statements_Elab is pragma Elaborate_Body; I: Integer; end Assignment_Statements_Elab; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/52_Null/src/null_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/52_Null/src/null_statements.ads index 594f4372d..8ce2e885f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/52_Null/src/null_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/52_Null/src/null_statements.ads @@ -17,4 +17,3 @@ package Null_Statements is -- statement sequence end Null_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.adb index 00bdcce73..1210df1b5 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.adb @@ -88,4 +88,3 @@ package body EXIT_Statements is end Compute_On_Matrix; end EXIT_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.ads index fbbed4f92..16e3ea3cf 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements.ads @@ -35,4 +35,3 @@ package EXIT_Statements is -- inner loop, both of them exit the outer loop. end EXIT_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements_support.ads b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements_support.ads index 6a2fd3041..2a54b73cb 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements_support.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/57_Exit/src/exit_statements_support.ads @@ -7,4 +7,3 @@ package EXIT_Statements_Support is type Matrix_Sample is array (Natural range <>, Natural range <>) of Integer; end EXIT_Statements_Support; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_loop.adb b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_loop.adb index 40bb67fab..b212c79f2 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_loop.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_loop.adb @@ -122,4 +122,3 @@ package body GOTO_Statements_Loop is end Update_Sample; end GOTO_Statements_Loop; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_straight.adb b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_straight.adb index c4c2094ac..70ce37b5d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_straight.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/58_Goto/src/goto_statements_straight.adb @@ -23,4 +23,3 @@ package body GOTO_Statements_Straight is end; end GOTO_Statements_Straight; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSE_Path/src/test_else_path.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSE_Path/src/test_else_path.adb index 68f8cb3af..a5a502808 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSE_Path/src/test_else_path.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/ELSE_Path/src/test_else_path.adb @@ -55,4 +55,3 @@ end Test_ELSE_Path; -- /max/ l+ ## 0 -- /ifmax/ l- ## s- -- /elsemax/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/test_init_else.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/test_init_else.adb index 63da57662..17e8686a0 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/test_init_else.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSE/src/test_init_else.adb @@ -15,4 +15,3 @@ end; -- /do_elsif/ l- ## s- -- /test_else/ l+ ## 0 -- /do_else/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/test_init_elsif.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/test_init_elsif.adb index 44bff284a..2e71a4813 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/test_init_elsif.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_ELSIF/src/test_init_elsif.adb @@ -15,4 +15,3 @@ end; -- /do_elsif/ l+ ## 0 -- /test_else/ l- ## s- -- /do_else/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/test_init_if.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/test_init_if.adb index a53faeee2..802c843d9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/test_init_if.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/Elab_IF/src/test_init_if.adb @@ -15,4 +15,3 @@ end; -- /do_elsif/ l- ## s- -- /test_else/ l- ## s- -- /do_else/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.adb index 0b84a14c1..ba8c36b63 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.adb @@ -24,4 +24,3 @@ package body IF_Statements is end Set_Max; end IF_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.ads index 1a1e1066e..b8441332d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/if_statements.ads @@ -14,4 +14,3 @@ package IF_Statements is -- Set Res to maximun from Arg1 and Arg2. The body contains IF statement -- without ELSE path and without ELSIF path end IF_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/instances.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/instances.ads index 721c6bc97..5ddcb67d1 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/instances.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/instances.ads @@ -10,4 +10,3 @@ package Instances is function My_Max_From_Two is new More_If_Statements.Max_From_Two (Integer); end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.adb index d187c670b..90068bc2b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/lib_if_statements.adb @@ -3,7 +3,7 @@ with Lib_Init; -- part of the IF statement below gets exercised. package body Lib_If_Statements is - + Values : array (1 .. 8) of Integer; function Probe (Slot : Integer) return Integer is @@ -17,5 +17,5 @@ begin Values := (others => 0); -- # do_elsif else Values := (others => -1); -- # do_else - end if; + end if; end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.adb index 6a1383e38..e6d907548 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/src/more_if_statements.adb @@ -45,4 +45,3 @@ package body More_IF_Statements is end Max_From_Two; end More_IF_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.adb index 44d12f502..89b10e751 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.adb @@ -40,4 +40,3 @@ package body CASE_Statements is end Adjust_Int_P; end CASE_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.ads index 93e19f8dd..652f3bed6 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements.ads @@ -20,4 +20,3 @@ package CASE_Statements is -- CASE statement with OTHERS choice, with alternatives with one and with -- multiple choices, choices are values or ranges. end CASE_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements_support.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements_support.ads index 1bd6d2b08..0f62059bd 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements_support.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/case_statements_support.ads @@ -8,4 +8,3 @@ package CASE_Statements_Support is subtype Int_Range_2 is Integer range 11 .. 20; end CASE_Statements_Support; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.adb index 7bca6a138..0b5179b1b 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.adb @@ -78,4 +78,3 @@ begin end case; end More_CASE_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.ads index 3cbde0305..6c51d722e 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/src/more_case_statements.ads @@ -25,4 +25,3 @@ package More_CASE_Statements is -- choices that are subtype marks. end More_CASE_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/test_init_loop.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/test_init_loop.adb index cc40cfedb..5e3aae698 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/test_init_loop.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_0/src/test_init_loop.adb @@ -17,4 +17,3 @@ end; -- /elab/ l+ ## 0 -- /test-init/ l+ ## 0 -- /init/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/test_init_loop.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/test_init_loop.adb index a475fb26b..fbcb7c1c0 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/test_init_loop.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/Elab_Some/src/test_init_loop.adb @@ -17,4 +17,3 @@ end; -- /elab/ l+ ## 0 -- /test-init/ l+ ## 0 -- /init/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/case_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/case_statements.adb index 44d12f502..89b10e751 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/case_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/case_statements.adb @@ -40,4 +40,3 @@ package body CASE_Statements is end Adjust_Int_P; end CASE_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb index 1abb69325..359650e05 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/lib_loop_statements.adb @@ -1,9 +1,9 @@ with Lib_Init; package body Lib_Loop_Statements is - + N : Integer; - + function N_Ones return Integer is begin N := 0; -- # count @@ -14,7 +14,7 @@ package body Lib_Loop_Statements is end loop; return N; -- # count end; - + begin N := 0; -- # elab while N < Lib_Init.N1 loop -- # test-init diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.adb index b672435b4..7c93dbe6d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.adb @@ -78,4 +78,3 @@ package body LOOP_Statements is end Sum_First_Under_Limit; end LOOP_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.ads index 729151c98..afe2677d4 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements.ads @@ -35,4 +35,3 @@ package LOOP_Statements is -- loop. end LOOP_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements_support.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements_support.ads index ab900648e..7be1d477e 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements_support.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/loop_statements_support.ads @@ -8,4 +8,3 @@ package LOOP_Statements_Support is type Big_Sample is array (Natural range <>) of Integer; end LOOP_Statements_Support; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.adb index 866285416..276429fb5 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.adb @@ -41,4 +41,3 @@ begin end loop; end More_LOOP_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.ads index 64a1bc69a..113c329f8 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/src/more_loop_statements.ads @@ -21,4 +21,3 @@ package More_LOOP_Statements is -- Replaces in S Old_Ch with New_Ch. The implementation uses FOR loop end More_LOOP_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/test_empty.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/test_empty.adb index a96249a6c..31518a8e9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/test_empty.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/test_empty.adb @@ -3,7 +3,7 @@ with Values.Arg, Support; use Values, Support; procedure Test_Empty is begin Arg.Do_Loop_Over (EA, Early_Return => False, Max_Iterations => EA'Length); -end; +end; --# values-arg.adb -- /decl/ l+ ## 0 -- /test-return/ l+ ## 0 @@ -13,5 +13,3 @@ end; -- /exit/ l- ## s- -- /loop_op/ l- ## s- -- /post-loop/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.adb index 860c60665..1e9109ec4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.adb @@ -5,7 +5,7 @@ package body Values is begin E := E * 2; end; - + procedure Check_Value (E : Integer; V : Integer) is begin Assert (E = V); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.ads index cce9758d4..af210f5f4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/EmptyArray/src/values.ads @@ -1,9 +1,9 @@ package Values is procedure Touch (E : in out Integer); procedure Check_Value (E : Integer; V : Integer); - + type Array_Type is array (Natural range <>) of Integer; VA : Array_Type := (1 .. 8 => 5); - + EA : Array_Type := (1 .. 0 => <>); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.adb index 9e2989520..10bdee3ab 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.adb @@ -1,12 +1,12 @@ with Support; use Support; package body Values is - + procedure Touch (E : in out Object) is begin E.X := E.X * 2; end; - + procedure Check_Value (E : Object; V : Integer) is begin Assert (E.X = V); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.ads index f4568cb83..fdbd6a433 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/ObjectArray/src/values.ads @@ -1,13 +1,13 @@ package Values is - + type Object is tagged record X : Integer; end record; - + procedure Touch (E : in out Object); procedure Check_Value (E : Object; V : Integer); - + type Array_Type is array (1 .. 8) of Object; VA : Array_Type := (others => (X => 5)); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.adb index 41f567d09..35f8441c0 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.adb @@ -5,7 +5,7 @@ package body Values is begin E := E * 2; end; - + procedure Check_Value (E : Num; V : Integer) is begin Assert (Integer(E) = V); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.ads index 1e05c3ec0..cfcfff706 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/PackedArray/src/values.ads @@ -2,12 +2,12 @@ package Values is type Num is mod 2**8; for Num'Size use 8; - + type Array_Type is array (1 .. 4) of Num; pragma Pack (Array_Type); - + procedure Touch (E : in out Num); procedure Check_Value (E : Num; V : Integer); - + VA : Array_Type := (others => 5); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.adb index 860c60665..1e9109ec4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.adb @@ -5,7 +5,7 @@ package body Values is begin E := E * 2; end; - + procedure Check_Value (E : Integer; V : Integer) is begin Assert (E = V); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.ads index 4baf2f760..444b68003 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/StraightIntArray/src/values.ads @@ -1,7 +1,7 @@ package Values is procedure Touch (E : in out Integer); procedure Check_Value (E : Integer; V : Integer); - + type Array_Type is array (1 .. 8) of Integer; VA : Array_Type := (others => 5); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.adb index 860c60665..1e9109ec4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.adb @@ -5,7 +5,7 @@ package body Values is begin E := E * 2; end; - + procedure Check_Value (E : Integer; V : Integer) is begin Assert (E = V); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.ads index 897aeb87a..5f021f458 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/UncIntArray/src/values.ads @@ -1,7 +1,7 @@ package Values is procedure Touch (E : in out Integer); procedure Check_Value (E : Integer; V : Integer); - + type Array_Type is array (Natural range <>) of Integer; VA : Array_Type := (1 .. 8 => 5); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/extra.opt b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/extra.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/extra.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/extra.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg.adb index ba7afce83..4563aecbc 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg.adb @@ -2,7 +2,7 @@ pragma Ada_2012; with Values.ARG, Support; use Values, Support; -procedure Test_Values_ARG is +procedure Test_Values_ARG is begin ARG.Do_Loop_Over (VA, Early_Return => False, Max_Iterations => VA'Length); @@ -20,4 +20,3 @@ end; -- /exit/ l- ## s- -- /loop_op/ l+ ## 0 -- /post-loop/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_er.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_er.adb index f3ec6f901..baa6d607c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_er.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_er.adb @@ -4,7 +4,7 @@ with Values.ARG, Support; use Values, Support; -- test with Early Return -procedure Test_Values_ARG_ER is +procedure Test_Values_ARG_ER is begin ARG.Do_Loop_Over (VA, Early_Return => True, Max_Iterations => VA'Length); @@ -22,4 +22,3 @@ end; -- /exit/ l- ## s- -- /loop_op/ l- ## s- -- /post-loop/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it0.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it0.adb index 5520a630a..acf4073a6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it0.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it0.adb @@ -4,7 +4,7 @@ with Values.ARG, Support; use Values, Support; -- test with limit to 0 iteration -procedure Test_Values_ARG_IT0 is +procedure Test_Values_ARG_IT0 is begin ARG.Do_Loop_Over (VA, Early_Return => False, Max_Iterations => 0); @@ -22,4 +22,3 @@ end; -- /exit/ l+ ## 0 -- /loop_op/ l- ## s- -- /post-loop/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it1.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it1.adb index c10e2822f..2fc86d38a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_arg_it1.adb @@ -4,7 +4,7 @@ with Values.ARG, Support; use Values, Support; -- test with limit to 1 iteration -procedure Test_Values_ARG_IT1 is +procedure Test_Values_ARG_IT1 is begin ARG.Do_Loop_Over (VA, Early_Return => False, Max_Iterations => 1); @@ -23,4 +23,3 @@ end; -- /exit/ l+ ## 0 -- /loop_op/ l+ ## 0 -- /post-loop/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_gsa.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_gsa.adb index 55f0794cf..879ce9a38 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_gsa.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/test_values_gsa.adb @@ -10,4 +10,3 @@ end; --# values-global.adb -- /stmt/ l+ ## 0 -- /loop_op/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.adb index 71cb167c6..49c68a41f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.adb @@ -3,7 +3,7 @@ pragma Ada_2012; with Support; use Support; package body Values.ARG is - + procedure Do_Loop_Over (A : in out Array_Type; Early_Return : Boolean; @@ -23,5 +23,5 @@ package body Values.ARG is end loop; Assert (N_Iterations <= Max_Iterations); -- # post-loop end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.ads index 3f0d49c9b..74e9811d9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-arg.ads @@ -1,5 +1,5 @@ -package Values.Arg is +package Values.Arg is procedure Do_Loop_Over (A : in out Array_Type; Early_Return : Boolean; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-global.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-global.adb index a4f1e3447..98158f351 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-global.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/OfArray/src/values-global.adb @@ -1,12 +1,12 @@ pragma Ada_2012; package body Values.Global is - + procedure Do_Loop is begin for E of VA loop -- # stmt Touch (E); -- # loop_op end loop; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.adb b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.adb index da06e56e0..52eda162d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.adb @@ -98,4 +98,3 @@ package body Block_Statements is end Sum_Min_Max; end Block_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.ads b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.ads index 151fa4935..5bee0672e 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/Plain/src/block_statements.ads @@ -27,4 +27,3 @@ package Block_Statements is -- each. end Block_Statements; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_0.adb index 812e0f5f0..51668970f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_0.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_0.adb @@ -10,4 +10,3 @@ end; -- /red/ l- ## s- -- /green/ l- ## s- -- /blue/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_b.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_b.adb index 437011e16..c0338669b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_b.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_b.adb @@ -10,4 +10,3 @@ end; -- /red/ l- ## s- -- /green/ l- ## s- -- /blue/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_g.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_g.adb index 503b7b55b..6c15d6976 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_g.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_g.adb @@ -10,4 +10,3 @@ end; -- /red/ l- ## s- -- /green/ l+ ## 0 -- /blue/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_gb.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_gb.adb index 41f20cd17..f70a0b889 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_gb.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_gb.adb @@ -11,4 +11,3 @@ end; -- /red/ l- ## s- -- /green/ l+ ## 0 -- /blue/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_r.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_r.adb index 364c39b41..6debd0823 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_r.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_r.adb @@ -10,4 +10,3 @@ end; -- /red/ l+ ## 0 -- /green/ l- ## s- -- /blue/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rb.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rb.adb index 6e66b017d..4956bc5c1 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rb.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rb.adb @@ -11,4 +11,3 @@ end; -- /red/ l+ ## 0 -- /green/ l- ## s- -- /blue/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rg.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rg.adb index 3d5257668..04ba2673b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rg.adb @@ -11,4 +11,3 @@ end; -- /red/ l+ ## 0 -- /green/ l+ ## 0 -- /blue/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rgb.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rgb.adb index bbf29402f..4b9c89279 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rgb.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/CallSites/src/test_mycolors_rgb.adb @@ -12,4 +12,3 @@ end; -- /red/ l+ ## 0 -- /green/ l+ ## 0 -- /blue/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/nest.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/nest.adb index c2a280486..9c674eb8b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/nest.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/nest.adb @@ -1,78 +1,78 @@ with Support; use Support; package body Nest is - + Value : Integer := 0; pragma Volatile (Value); - + procedure Touch (Cd : access Cdata) is begin Cd.Nops := Cd.Nops + 1; -- # touch end; - - procedure Check + + procedure Check (Lfun, Lproc, Pfun, Pproc, Indirect : Boolean; Cd : access Cdata) is -- nested procedure and function - + procedure Inc (X : in out Integer; Cd : access Cdata) is begin Touch (Cd); -- # lproc X := X + 1; -- # lproc end; - + function Positive (X : Integer; Cd : access Cdata) return Boolean is begin Touch (Cd); -- # lfun return X > 0; -- # lfun end; - + -- nested package - + package Ops is - + -- visible operations - + procedure Dec (X : in out Integer; Cd : access Cdata); function Negative (X : Integer; Cd : access Cdata) return Boolean; - + private -- private operations function Neg_P (X : Integer) return Boolean; end; - + package body Ops is - + -- internal subpgram (package body only) - + procedure My_Dec (X : in out Integer) is begin X := X - 1; -- # pproc end; - + procedure Dec (X : in out Integer; Cd : access Cdata) is begin Touch (Cd); -- # pproc My_Dec (Value); -- # pproc end; - + function Neg_P (X : Integer) return Boolean is begin return X < 0; -- # pfun end; - + function Negative (X : Integer; Cd : access Cdata) return Boolean is begin Touch (Cd); -- # pfun return Neg_P (X); -- # pfun end; end; - + type Opcodes is mod 4; Op_Lfun : constant := 1; Op_Pfun : constant := 2; - + type Trigger (Opc : Opcodes; Value : Integer; Cd : access Cdata) is limited record case Opc is @@ -83,14 +83,14 @@ package body Nest is Neg : Boolean := Ops.Negative (Value, Cd); when 3 => P : Boolean := Positive (Value, Cd); - N : Boolean := Ops.Negative (Value, Cd); + N : Boolean := Ops.Negative (Value, Cd); end case; end record; - + Opc : Opcodes := 0; begin Value := 5; -- # check - + if Lfun then -- # check if Indirect then -- # lfun Opc := Opc or Op_Lfun; -- # lfi @@ -98,11 +98,11 @@ package body Nest is Assert (Positive (Value, Cd)); -- # lfd end if; end if; - + if Lproc then -- # check Inc (Value, Cd); -- # lpd end if; - + if Pfun then -- # check if Indirect then -- # pfun Opc := Opc or Op_Pfun; -- # pfi @@ -110,11 +110,11 @@ package body Nest is Assert (not Ops.Negative (Value, Cd)); -- # pfd end if; end if; - + if Pproc then -- # check Ops.Dec (Value, Cd); -- # ppd end if; - + if Indirect then -- # check declare T : Trigger (Opc => Opc, Value => Value, Cd => Cd); -- # indirect @@ -122,7 +122,7 @@ package body Nest is null; -- # indirect end; end if; - + end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlf.adb index a0e12f7bf..8258629a0 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlf.adb @@ -26,4 +26,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlp.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlp.adb index d6a3f34f5..5cd8d8385 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dlp.adb @@ -26,4 +26,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpf.adb index a587d1d36..53c50e982 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpf.adb @@ -26,4 +26,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpp.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpp.adb index f886e3c92..13e70662c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_dpp.adb @@ -26,4 +26,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l+ ## 0 -- /indirect/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf.adb index d483dff42..2cd53e5d6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf.adb @@ -26,4 +26,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlf.adb index ea8906ef5..0a8ac0547 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlf.adb @@ -35,4 +35,3 @@ end; -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlp.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlp.adb index b90ead504..32f948d6e 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dlp.adb @@ -30,4 +30,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpf.adb index e8d800c39..3b75b0bea 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpf.adb @@ -30,4 +30,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpp.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpp.adb index 33c050af0..1550001b6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilf_dpp.adb @@ -35,4 +35,3 @@ end; -- /ppd/ l+ ## 0 -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilfpf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilfpf.adb index 167d7ad5a..961646d91 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilfpf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ilfpf.adb @@ -27,4 +27,3 @@ end; -- /ppi/ l- ## s- -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf.adb index 367bf55b5..4a8c34d03 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf.adb @@ -31,4 +31,3 @@ end; -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlf.adb index 32b8310bf..49e9cd60b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlf.adb @@ -35,4 +35,3 @@ end; -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlp.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlp.adb index d55164d40..da467c729 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dlp.adb @@ -35,4 +35,3 @@ end; -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpf.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpf.adb index 91f215a55..d31f25956 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpf.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpf.adb @@ -35,4 +35,3 @@ end; -- /ppd/ l- ## s- -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpp.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpp.adb index 829e039cb..3aa2354a4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/Nested/src/test_nest_ipf_dpp.adb @@ -35,4 +35,3 @@ end; -- /ppd/ l+ ## 0 -- /indirect/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allneg.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allneg.adb index ba969d5e8..11e74aab6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allneg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allneg.adb @@ -8,7 +8,7 @@ begin Characterize2 (IV); T_Int_Characterize1 (IV); T_Int_Characterize2 (IV); - + Assert (N_Positives = 0); Assert (N_Negatives = 4); Assert (N_Zeroes = 0); @@ -20,4 +20,3 @@ end; -- /test_neg/ l+ ## 0 -- /neg/ l+ ## 0 -- /zero/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allpos.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allpos.adb index d1600694a..f00eebda2 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allpos.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allpos.adb @@ -8,7 +8,7 @@ begin Characterize2 (IV); T_Int_Characterize1 (IV); T_Int_Characterize2 (IV); - + Assert (N_Positives = 4); Assert (N_Negatives = 0); Assert (N_Zeroes = 0); @@ -20,4 +20,3 @@ end; -- /test_neg/ l- ## s- -- /neg/ l- ## s- -- /zero/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allzero.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allzero.adb index a27b2ef22..45e8c192f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allzero.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_allzero.adb @@ -8,7 +8,7 @@ begin Characterize2 (IV); T_Int_Characterize1 (IV); T_Int_Characterize2 (IV); - + Assert (N_Positives = 0); Assert (N_Negatives = 0); Assert (N_Zeroes = 4); @@ -20,4 +20,3 @@ end; -- /test_neg/ l+ ## 0 -- /neg/ l- ## s- -- /zero/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix1.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix1.adb index 4d7129459..3ca1bb02a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix1.adb @@ -11,10 +11,10 @@ procedure Test_Mix1 is begin Characterize1 (IV0); Characterize2 (IVpos); - + T_Int_Characterize1 (IVpos); T_Int_Characterize2 (IVneg); - + Assert (N_Positives = 2); Assert (N_Negatives = 1); Assert (N_Zeroes = 1); @@ -44,4 +44,3 @@ end; -- /test_neg_i2/ l+ ## 0 -- /neg_i2/ l+ ## 0 -- /zero_i2/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix2.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix2.adb index c417c75e4..a0e578bb3 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix2.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/test_mix2.adb @@ -11,17 +11,17 @@ procedure Test_Mix2 is begin Characterize1 (IV0); Characterize1 (IVpos); - + Characterize2 (IV0); Characterize2 (IVneg); - + T_Int_Characterize1 (IVpos); T_Int_Characterize1 (IVneg); - + T_Int_Characterize2 (IV0); T_Int_Characterize2 (IVpos); T_Int_Characterize2 (IVneg); - + Assert (N_Positives = 3); Assert (N_Negatives = 3); Assert (N_Zeroes = 3); @@ -51,4 +51,3 @@ end; -- /test_neg_i2/ l+ ## 0 -- /neg_i2/ l+ ## 0 -- /zero_i2/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.adb index 58f3bfee2..d517b401d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.adb @@ -1,5 +1,5 @@ package body Values is - + procedure Characterize1 (IV : T_Int) is begin if IV.Value > 0 then -- # test_pos_c1 @@ -10,7 +10,7 @@ package body Values is N_Zeroes := N_Zeroes + 1; -- # zero_c1 end if; end; - + overriding procedure Characterize2 (IV : T_Int) is begin @@ -22,7 +22,7 @@ package body Values is N_Zeroes := N_Zeroes + 1; -- # zero_c2 end if; end; - + procedure T_Int_Characterize1 (IV : T_Int) is begin if IV.Value > 0 then -- # test_pos_i1 @@ -31,9 +31,9 @@ package body Values is N_Negatives := N_Negatives + 1; -- # neg_i1 else N_Zeroes := N_Zeroes + 1; -- # zero_i1 - end if; + end if; end; - + not overriding procedure T_Int_Characterize2 (IV : T_Int) is begin @@ -43,6 +43,6 @@ package body Values is N_Negatives := N_Negatives + 1; -- # neg_i2 else N_Zeroes := N_Zeroes + 1; -- # zero_i2 - end if; + end if; end; end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.ads index 373bdbf89..f529290fd 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Indicators/src/values.ads @@ -1,26 +1,26 @@ package Values is - + type T_Value is abstract tagged null record; - + N_Positives : Integer := 0; N_Negatives : Integer := 0; N_Zeroes : Integer := 0; - + procedure Characterize1 (V : T_Value) is abstract; procedure Characterize2 (V : T_Value) is abstract; - + type T_Int is new T_Value with record Value : Integer; end record; - + procedure Characterize1 (IV : T_Int); - + overriding procedure Characterize2 (IV : T_Int); - + procedure T_Int_Characterize1 (IV : T_Int); - + not overriding procedure T_Int_Characterize2 (IV : T_Int); - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.adb index eafc66baa..11f42f84c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.adb @@ -1,5 +1,5 @@ package body I_Objects is - + procedure Characterize (IV : T_Int) is begin if IV.Value > 0 then -- # char_test_pos_int @@ -10,7 +10,7 @@ package body I_Objects is N_Zeroes := N_Zeroes + 1; -- # char_zero_int end if; end; - + procedure Characterize (FV : T_Float) is begin if FV.Value > 0.0 then -- # char_test_pos_float @@ -21,5 +21,5 @@ package body I_Objects is N_Zeroes := N_Zeroes + 1; -- # char_zero_float end if; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.ads index 70cf06472..0801769bb 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/i_objects.ads @@ -2,33 +2,33 @@ -- Case where the object types are derived from a single Interface type. package I_Objects is - + -- The base Interface type: - + type I_Value is Interface; - + N_Positives : Integer := 0; N_Negatives : Integer := 0; N_Zeroes : Integer := 0; - + procedure Characterize (V : I_Value) is abstract; - + -- - + type T_Int is new I_Value with record Value : Integer; end record; - + overriding procedure Characterize (IV : T_Int); - + -- - + type T_Float is new I_Value with record Value : Float; end record; - + overriding procedure Characterize (FV : T_Float); - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_all_pos.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_all_pos.adb index 954b210e5..4623d335b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_all_pos.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_all_pos.adb @@ -10,16 +10,16 @@ procedure Test_I_All_Pos is begin IO.Value := 1; Characterize (IO); - + FO.Value := -11.0; Characterize (FO); - + FO.Value := 117.0; Characterize (FO); - + FO.Value := 0.0; Characterize (FO); - + Assert (N_Positives = 2); Assert (N_Negatives = 1); Assert (N_Zeroes = 1); @@ -37,4 +37,3 @@ end; -- /char_test_neg_float/ l+ ## 0 -- /char_neg_float/ l+ ## 0 -- /char_zero_float/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_neg_pos.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_neg_pos.adb index 3c0808d0d..57a03affd 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_neg_pos.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_i_neg_pos.adb @@ -10,10 +10,10 @@ procedure Test_I_Neg_Pos is begin IO.Value := -1; Characterize (IO); - + FO.Value := 11.0; Characterize (FO); - + Assert (N_Positives = 1); Assert (N_Negatives = 1); Assert (N_Zeroes = 0); @@ -31,4 +31,3 @@ end; -- /char_test_neg_float/ l- ## s- -- /char_neg_float/ l- ## s- -- /char_zero_float/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_all.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_all.adb index 50889debb..81ccd3bc9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_all.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_all.adb @@ -10,28 +10,28 @@ procedure Test_TI_All_All is begin Assign_Id_To (IO); Assert (IO.Id >= 0); - + IO.Value := -1; Characterize (IO); - + IO.Value := 1; Characterize (IO); - + IO.Value := 0; Characterize (IO); - + Assign_Id_To (FO); Assert (FO.Id >= 0); - + FO.Value := -11.0; Characterize (FO); - + FO.Value := 7.0; Characterize (FO); - + FO.Value := 0.0; Characterize (FO); - + Assert (N_Positives = 2); Assert (N_Negatives = 2); Assert (N_Zeroes = 2); @@ -53,4 +53,3 @@ end; -- /char_test_neg_float/ l+ ## 0 -- /char_neg_float/ l+ ## 0 -- /char_zero_float/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_neg.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_neg.adb index d6b8a0847..56c6ff30d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_neg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_all_neg.adb @@ -10,22 +10,22 @@ procedure Test_TI_All_Neg is begin Assign_Id_To (IO); Assert (IO.Id >= 0); - + IO.Value := -1; Characterize (IO); - + IO.Value := 1; Characterize (IO); - + IO.Value := 0; Characterize (IO); - + Assign_Id_To (FO); Assert (FO.Id >= 0); - + FO.Value := -11.0; Characterize (FO); - + Assert (N_Positives = 1); Assert (N_Negatives = 2); Assert (N_Zeroes = 1); @@ -47,4 +47,3 @@ end; -- /char_test_neg_float/ l+ ## 0 -- /char_neg_float/ l+ ## 0 -- /char_zero_float/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_pos.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_pos.adb index 1a4f21152..35155aa82 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_pos.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_pos.adb @@ -10,16 +10,16 @@ procedure Test_TI_Neg_Pos is begin Assign_Id_To (IO); Assert (IO.Id >= 0); - + IO.Value := -1; Characterize (IO); - + Assign_Id_To (FO); Assert (FO.Id >= 0); - + FO.Value := 11.0; Characterize (FO); - + Assert (N_Positives = 1); Assert (N_Negatives = 1); Assert (N_Zeroes = 0); @@ -41,4 +41,3 @@ end; -- /char_test_neg_float/ l- ## s- -- /char_neg_float/ l- ## s- -- /char_zero_float/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_zero.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_zero.adb index f95ebaf64..032a3ae65 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_zero.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_neg_zero.adb @@ -7,16 +7,16 @@ procedure Test_TI_Neg_Zero is begin Assign_Id_To (IO); Assert (IO.Id >= 0); - + IO.Value := -1; Characterize (IO); - + Assign_Id_To (FO); Assert (FO.Id >= 0); - + FO.Value := 0.0; Characterize (FO); - + Assert (N_Positives = 0); Assert (N_Negatives = 1); Assert (N_Zeroes = 1); @@ -38,4 +38,3 @@ end; -- /char_test_neg_float/ l+ ## 0 -- /char_neg_float/ l- ## s- -- /char_zero_float/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_pos_neg.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_pos_neg.adb index 58db71f98..f35bdaed3 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_pos_neg.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/test_ti_pos_neg.adb @@ -10,16 +10,16 @@ procedure Test_TI_Pos_Neg is begin Assign_Id_To (IO); Assert (IO.Id >= 0); - + IO.Value := 1; Characterize (IO); - + Assign_Id_To (FO); Assert (FO.Id >= 0); - + FO.Value := -11.0; Characterize (FO); - + Assert (N_Positives = 1); Assert (N_Negatives = 1); Assert (N_Zeroes = 0); @@ -41,4 +41,3 @@ end; -- /char_test_neg_float/ l+ ## 0 -- /char_neg_float/ l+ ## 0 -- /char_zero_float/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.adb index 35135e5f1..bc958325f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.adb @@ -1,8 +1,8 @@ package body TI_Objects is - + N_Id_Recall : Integer := 0; Next_Id : Integer := 0; - + procedure Assign_Id_To (O : in out Identifiable) is begin if O.Id > 0 then -- # id_test @@ -12,7 +12,7 @@ package body TI_Objects is Next_Id := Next_Id + 1; -- # id_assign end if; end; - + procedure Characterize (IV : T_Int) is begin if IV.Value > 0 then -- # char_test_pos_int @@ -23,7 +23,7 @@ package body TI_Objects is N_Zeroes := N_Zeroes + 1; -- # char_zero_int end if; end; - + procedure Characterize (FV : T_Float) is begin if FV.Value > 0.0 then -- # char_test_pos_float @@ -34,5 +34,5 @@ package body TI_Objects is N_Zeroes := N_Zeroes + 1; -- # char_zero_float end if; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.ads index e6df0c94b..6b0d8951f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Interfaces/src/ti_objects.ads @@ -3,41 +3,41 @@ -- type and an Interface type. package TI_Objects is - + -- The Tagged type: - + type Identifiable is abstract tagged record Id : Integer := -1; end record; - + procedure Assign_Id_To (O : in out Identifiable); - + -- The base Interface type: - + type I_Value is Interface; - + N_Positives : Integer := 0; N_Negatives : Integer := 0; N_Zeroes : Integer := 0; - + procedure Characterize (V : I_Value) is abstract; - + -- - + type T_Int is new Identifiable and I_Value with record Value : Integer; end record; - + overriding procedure Characterize (IV : T_Int); - + -- - + type T_Float is new Identifiable and I_Value with record Value : Float; end record; - + overriding procedure Characterize (FV : T_Float); - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Simple/src/test_notes_dt.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Simple/src/test_notes_dt.adb index dd7733b26..3f7b52d61 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Simple/src/test_notes_dt.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Simple/src/test_notes_dt.adb @@ -19,4 +19,3 @@ end; -- --%opts: --trace-mode=src -- /no-code/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.adb index 2da4ddb91..0d11fad49 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.adb @@ -1,13 +1,13 @@ package body Objects is - + procedure Register_Pos is begin N_Positives := N_Positives + 1; -- # pos end; - + procedure Characterize (X : Integer); pragma No_Return (Characterize); - + procedure Characterize (X : Integer) is begin if X > 0 then -- # test @@ -15,7 +15,7 @@ package body Objects is end if; raise Constraint_Error; -- # test end; - + procedure Proxy_Characterize (X : Integer) is begin Characterize (X); -- # test diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.ads index a35754bc8..6397a816b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/InBody/src/objects.ads @@ -1,8 +1,8 @@ package Objects is - + N_Positives : Integer := 0; - + procedure Proxy_Characterize (X : Integer); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.adb index d0e75b00f..8fb29aa8d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.adb @@ -1,10 +1,10 @@ package body Objects is - + procedure Register_Pos is begin N_Positives := N_Positives + 1; -- # pos end; - + procedure Characterize (X : Integer) is begin if X > 0 then -- # test @@ -12,7 +12,7 @@ package body Objects is end if; raise Constraint_Error; -- # test end; - + procedure Proxy_Characterize (X : Integer) is begin Characterize (X); -- # test diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.ads index 57b2d12d1..62613049e 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/LibLevel/src/objects.ads @@ -1,11 +1,11 @@ package Objects is - + N_Positives : Integer := 0; - + procedure Characterize (X : Integer); pragma No_Return (Characterize); - + procedure Proxy_Characterize (X : Integer); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.adb index f6eaec583..829c13d8b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.adb @@ -1,15 +1,15 @@ package body Objects is - + procedure Register_Pos is begin N_Positives := N_Positives + 1; -- # pos end; - + procedure Proxy_Characterize (X : Integer) is - + procedure Characterize (X : Integer); pragma No_Return (Characterize); -- # pragma - + procedure Characterize (X : Integer) is begin if X > 0 then -- # test @@ -17,7 +17,7 @@ package body Objects is end if; raise Constraint_Error; -- # test end; - + begin Characterize (X); -- # test end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.ads index a35754bc8..6397a816b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/Nested/src/objects.ads @@ -1,8 +1,8 @@ package Objects is - + N_Positives : Integer := 0; - + procedure Proxy_Characterize (X : Integer); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/src/test_objects_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/src/test_objects_0.adb index 685d7c007..1402967cb 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/src/test_objects_0.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/src/test_objects_0.adb @@ -11,7 +11,7 @@ end; -- /pos/ l- ## s- -- Old compilers are less precise in tracking --- dominance +-- dominance -- %tags:(7.1.2|7.2.2) -- =/pragma/ ~l- ## ~s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.adb index cd3e988cd..b0369b628 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.adb @@ -1,15 +1,15 @@ package body Ops is - + procedure Nop3 (X: in out Integer) is null; -- # do_nop3 - + procedure Nop2 (X: in out Integer) is null; -- # do_nop2 - - procedure Inc (X : in out Integer) is + + procedure Inc (X : in out Integer) is begin X := X + 1; -- # do_inc - end; - + end; + procedure Do_Pv1 (X : in out Integer; Opcode : T_Opcode) is begin @@ -23,7 +23,7 @@ package body Ops is Nop3 (X); -- # pv1_nop3 end if; end; - + procedure Do_Pv2 (X : in out Integer; Opcode : T_Opcode) is begin case Opcode is -- # pv2_test @@ -37,7 +37,7 @@ package body Ops is Nop3 (X); -- # pv2_nop3 end case; end; - + procedure Process (X : in out Integer; Opcode : T_Opcode; Pv : T_Processing_Variant) @@ -48,5 +48,5 @@ package body Ops is when Pv2 => Do_Pv2 (X, Opcode); -- # pv2_call end case; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.ads index 3b09d6c35..aff428013 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/ops.ads @@ -1,14 +1,13 @@ package Ops is procedure Nop1 (X: in out Integer) is null; -- # do_nop1 - + procedure Nop2 (X : in out Integer); - + procedure Inc (X : in out Integer); - + type T_Opcode is (Op_Nop1, Op_Nop2, Op_Nop3, Op_Inc); type T_Processing_Variant is (PV1, PV2); - + procedure Process (X : in out Integer; Opcode : T_Opcode; Pv : T_Processing_Variant); end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_inc.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_inc.adb index 8dbf22723..81aa6a5f3 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_inc.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_inc.adb @@ -33,5 +33,3 @@ end; --# ops.ads -- /do_nop1/ l- ## s- - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop1.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop1.adb index bfab31f1f..60a36671b 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop1.adb @@ -33,5 +33,3 @@ end; --# ops.ads -- /do_nop1/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop3.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop3.adb index 0823ebe02..d32ae4c21 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop3.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv1_nop3.adb @@ -33,4 +33,3 @@ end; --# ops.ads -- /do_nop1/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv2_inc.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv2_inc.adb index f8dd3052e..1949dc866 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv2_inc.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/CallsInFlow/src/test_pv2_inc.adb @@ -39,4 +39,3 @@ end; -- %cargs: -O1 -- =/do_nop1/ ~l- ## ~s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.adb index e866fbd8d..0a463ca4c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.adb @@ -1,12 +1,12 @@ package body Objects is procedure Probe (O : T_Object) is null; -- # test - + procedure Process (O : T_Object) is procedure Local_Probe (O : T_Object); -- # decl - + procedure Local_Probe (O : T_Object) is null; -- # test - + begin Local_Probe (O); -- # test end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.ads index e4636765a..09fb783f6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullCompletion/src/objects.ads @@ -2,10 +2,10 @@ with System; package Objects is type T_Object is tagged null record; - + procedure Probe (O : T_Object); - + procedure Process (O : T_Object); - + A_Probe : System.Address; end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.adb index 868069765..3779ef473 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.adb @@ -1,11 +1,11 @@ package body Objects is procedure Local_Probe (O : T_Object) is null; -- # local - + procedure Process (O : T_Object; Local : Boolean) is begin if Local then -- # test Local_Probe (O); -- # local - else + else Probe (O); -- # global end if; end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.ads index 9d85804de..f6d71c868 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/NullDefinition/src/objects.ads @@ -2,14 +2,14 @@ with Support; package Objects is type T_Object is null record; - + procedure Probe (O : T_Object) is null; -- # global - + -- Some declaration with initialization code here, to verify -- that coverage by elaboration doesn't backpropagate: - + X : Integer := Support.Identity(54); -- # decl_with_elab - + procedure Process (O : T_Object; Local : Boolean); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/src/ops.adb index 21a28af12..251d9e0c5 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/src/ops.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/src/ops.adb @@ -1,12 +1,12 @@ pragma Ada_2012; package body Ops is - + type T_Point is record X, Y : Integer; Q : T_Quarter; end record; - + function Set_Q (P : in out T_Point) return T_Quarter is Q : T_Quarter; begin @@ -24,11 +24,11 @@ package body Ops is P.Q := Q; -- # stmt return Q; -- # stmt end; - - function Quarter (X, Y : Integer) return T_Quarter is + + function Quarter (X, Y : Integer) return T_Quarter is P : T_Point := (X => X, Y => Y, Q => <>); begin return Set_Q (P); -- # stmt end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/test.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Function/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Procedure/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Procedure/src/ops.adb index 453a52075..c52ed6324 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Procedure/src/ops.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/InOut_Procedure/src/ops.adb @@ -1,10 +1,10 @@ package body Ops is - + type T_Point is record X, Y : Integer; Q : T_Quarter; end record; - + procedure Set_Q (P : in out T_Point) is Q : T_Quarter; begin @@ -21,12 +21,12 @@ package body Ops is end if; P.Q := Q; -- # stmt end; - - function Quarter (X, Y : Integer) return T_Quarter is + + function Quarter (X, Y : Integer) return T_Quarter is P : T_Point := (X => X, Y => Y, Q => <>); begin Set_Q (P); -- # stmt return P.Q; -- # stmt end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/src/ops.adb index b0ffc3797..7ea7ee955 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/src/ops.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/src/ops.adb @@ -3,11 +3,11 @@ pragma Ada_2012; with Support; use Support; package body Ops is - + type T_Point is record X, Y : Integer; end record; - + function Set_Q (P : T_Point; Q: out T_Quarter) return Integer is begin if P.X > 0 and then P.Y > 0 then -- # test-q1 @@ -27,8 +27,8 @@ package body Ops is return 0; -- # q0 end if; end; - - function Quarter (X, Y : Integer) return T_Quarter is + + function Quarter (X, Y : Integer) return T_Quarter is P : T_Point := (X => X, Y => Y); Q : T_Quarter; Hint : Integer; @@ -37,5 +37,5 @@ package body Ops is Assert (Hint = T_Quarter'Pos (Q)); -- # stmt return Q; -- # stmt end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/test.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Function/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Procedure/src/ops.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Procedure/src/ops.adb index 67e07bb44..cc9637c07 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Procedure/src/ops.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/In_Out_Procedure/src/ops.adb @@ -1,9 +1,9 @@ package body Ops is - + type T_Point is record X, Y : Integer; end record; - + procedure Set_Q (P : T_Point; Q : out T_Quarter) is begin if P.X > 0 and then P.Y > 0 then -- # test-q1 @@ -18,12 +18,12 @@ package body Ops is Q := Q0; -- # q0 end if; end; - - function Quarter (X, Y : Integer) return T_Quarter is + + function Quarter (X, Y : Integer) return T_Quarter is Q : T_Quarter; begin Set_Q ((X => X, Y => Y), Q); -- # stmt return Q; -- # stmt end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/src/ops.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/src/ops.ads index 6a155a553..aee770c94 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/src/ops.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/src/ops.ads @@ -1,11 +1,11 @@ package Ops is -- Y -- ^ - -- Q4 | Q1 + -- Q4 | Q1 -- -----------+----------> X -- Q3 | Q2 -- type T_Quarter is (Q0, Q1, Q2, Q3, Q4); - + function Quarter (X, Y : Integer) return T_Quarter; end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_full.adb index 0fced26ec..916ac3441 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_full.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_full.adb @@ -37,4 +37,3 @@ end Test_Pret_Full; -- /proc2_3/ l+ ## 0 -- /proc2_others/ l+ ## 0 -- /proc2_fin/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_part.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_part.adb index 00ba9b429..722b72a2c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_part.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/Procedures/src/test_pret_part.adb @@ -26,4 +26,3 @@ end Test_Pret_Part; -- /proc2_3/ l- ## s- -- /proc2_others/ l- ## s- -- /proc2_fin/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.adb index 6e89cfe92..764a3d8c2 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.adb @@ -1,10 +1,10 @@ pragma Ada_2012; package body Expr is - + function Plus (X, Y : Integer; Delegate : Boolean) return Integer is - + function Sum (X, Y : Integer) return Integer is (X + Y); -- # delegate - + Sx : Integer := Zx + X; -- # decl Sy : Integer := Zy + Y; -- # decl begin @@ -14,5 +14,5 @@ package body Expr is return Sx + Sy; -- # compute end if; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.ads index ba764c9b8..0f844ec1a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/expr.ads @@ -2,5 +2,5 @@ pragma Ada_2012; package Expr is function Plus (X, Y : Integer; Delegate : Boolean) return Integer; Zx, Zy : Integer := 0; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_1.adb index 45187749c..dd7d0e4f4 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_1.adb @@ -12,4 +12,3 @@ end; -- /test/ l+ ## 0 -- /delegate/ l+ ## 0 -- /compute/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_2.adb index 3c08e2fb5..218fa749f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_2.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_2.adb @@ -12,4 +12,3 @@ end; -- /test/ l+ ## 0 -- /delegate/ l- ## s- -- /compute/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_3.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_3.adb index f1cdea23e..da6be6e06 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_3.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Local/src/test_3.adb @@ -13,4 +13,3 @@ end; -- /test/ l+ ## 0 -- /delegate/ l+ ## 0 -- /compute/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Multiline/src/expr.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Multiline/src/expr.ads index 28ae7ea6d..8bdbd2ef5 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Multiline/src/expr.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Multiline/src/expr.ads @@ -3,11 +3,11 @@ pragma Ada_2012; with Values; package Expr is - function Plus (X, Y : Integer) return Integer is + function Plus (X, Y : Integer) return Integer is (X + Y); -- # stmt - + -- Stick some decl with elab code to make sure that the -- coverage here in absence of call doesn't back-propagate. - + X : Integer := Values.One; -- # decl end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Singleline/src/expr.ads b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Singleline/src/expr.ads index 3e538ba32..1de1a94af 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Singleline/src/expr.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/Singleline/src/expr.ads @@ -4,9 +4,9 @@ with Values; package Expr is function Plus (X, Y : Integer) return Integer is (X + Y); -- # stmt - + -- Stick some decl with elab code to make sure that the -- coverage here in absence of call doesn't back-propagate. - + X : Integer := Values.One; -- # decl end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/extra.opt b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/extra.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/extra.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/extra.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/src/values.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/src/values.adb index 021979ddb..4a7ffbb79 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/src/values.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/src/values.adb @@ -3,5 +3,5 @@ package body Values is begin return 1; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeclRegions/src/ops.ads b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeclRegions/src/ops.ads index af640d591..a4295e69c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeclRegions/src/ops.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeclRegions/src/ops.ads @@ -1,19 +1,19 @@ package Ops is - + -- This package features a private and an internal subprogram (operations), -- with a single API to call them: - + type Opdata is record Np, Ni : Integer := 0; -- Number of calls to each end record; - + procedure Call_Ops (Pop, Iop : Boolean; Opd : in out Opdata); - + private - + -- The private op declaration, within the private part of the package spec - + procedure Op_Private (Opd : in out Opdata); - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.adb b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.adb index cf3ca6e16..034323606 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.adb @@ -1,7 +1,7 @@ package body Environ is - + X : Value := 0; - + function Probe return State is begin X := X + 1; -- # probe @@ -12,10 +12,9 @@ package body Environ is end if; return (X => X); -- # probe end; - + function Match (A, B : State) return Boolean is begin return A.X = B.X; -- # compare end; end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.ads b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.ads index 968275fcb..a1f5be15e 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/environ.ads @@ -1,17 +1,16 @@ package Environ is - + type State is private; - + function Probe return State; - + Did_Initial_Probe, Did_Other_probe : Boolean := False; - + function Match (A, B : State) return Boolean; - + private type Value is mod 2; type State is record X : Value; end record; end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.adb b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.adb index fec072712..66b3035ef 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.adb @@ -1,7 +1,7 @@ with Environ; use Environ; package body Monitor is - + procedure Compare_With_Initial_State_Now is Current_Environ_State : State := Environ.Probe; -- # compare begin @@ -9,5 +9,5 @@ package body Monitor is N_Matches := N_Matches + 1; -- # match end if; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.ads b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.ads index 3328a6f4c..13c920dac 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/monitor.ads @@ -1,12 +1,12 @@ with Environ; package Monitor is - + Initial_Environ_State : constant Environ.State; - + procedure Compare_With_Initial_State_Now; N_Matches : Natural := 0; - + private Initial_Environ_State : constant Environ.State := Environ.Probe; -- # decl end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_1cmp.adb b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_1cmp.adb index 52a27f7bb..5754de817 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_1cmp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_1cmp.adb @@ -5,7 +5,7 @@ procedure Test_Monitor_1Cmp is begin Assert (Did_Initial_Probe = True); Assert (Did_Other_Probe = False); - + Compare_With_Initial_State_Now; Assert (Did_Other_Probe = True); Assert (N_Matches = 0); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_2cmp.adb b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_2cmp.adb index e3ada0916..6b2e95124 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_2cmp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/DeferredConstants/src/test_monitor_2cmp.adb @@ -5,11 +5,11 @@ procedure Test_Monitor_2Cmp is begin Assert (Did_Initial_Probe = True); Assert (Did_Other_Probe = False); - + Compare_With_Initial_State_Now; Assert (Did_Other_Probe = True); Assert (N_Matches = 0); - + Compare_With_Initial_State_Now; Assert (Did_Other_Probe = True); Assert (N_Matches = 1); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_0.adb index a94cb3ecd..efdd2645c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_0.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_0.adb @@ -21,4 +21,3 @@ end; --# ops-isub.adb -- /isub/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_i.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_i.adb index ff956b62a..4379f4b9a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_i.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_i.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_p.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_p.adb index 55e5129c1..9105450a7 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_p.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_p.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_pi.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_pi.adb index fd779f026..cc0210004 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_pi.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_pi.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_v.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_v.adb index 60c538a74..cd4d7b811 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_v.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_v.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vi.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vi.adb index b40fe6321..e1e304ed3 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vi.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vi.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vp.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vp.adb index 6c6c059de..d9ee633ad 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vp.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vp.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vpi.adb b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vpi.adb index f1b5f8216..6d69d2c92 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vpi.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/src/test_ops_vpi.adb @@ -24,4 +24,3 @@ end; --# ops-isub.adb -- /isub/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/src/fuand.adb index 5369db5c6..887cca612 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/src/fuand.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/IndexCheck/src/fuand.adb @@ -3,13 +3,13 @@ with Args; use Args; package body Fuand is pragma Unsuppress (All_Checks); - + function Andthen (A, B : Integer) return Boolean is begin -- Possible out of range array access here return Bool_For (A) and then Bool_For(B); -- # eval end; - + procedure Andthen (A, B : Integer; R : out Boolean) is begin R := Andthen (A, B); -- # eval diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/src/fuand.adb index 24547196a..3b893fb06 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/src/fuand.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RangeCheck/src/fuand.adb @@ -3,13 +3,13 @@ with Args; use Args; package body Fuand is pragma Unsuppress (All_Checks); - + function Andthen (A, B : Integer) return Boolean is begin -- Possible range check failure on conversion here return Bool (Boolval(A)) and then Bool (Boolval(B)); -- # eval end; - + procedure Andthen (A, B : Integer; R : out Boolean) is begin R := Andthen (A, B); -- # eval diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/src/fuand.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/src/fuand.adb index 1cf67eca8..4eaf7552e 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/src/fuand.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/And/Return/RemoteCheck/src/fuand.adb @@ -7,7 +7,7 @@ package body Fuand is -- Safe conversion here, possible raise from Args.Bool return Bool (Intval(A)) and then Bool (Intval(B)); -- # eval end; - + procedure Andthen (A, B : Integer; R : out Boolean) is begin R := Andthen (A, B); -- # eval diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/src/flip.adb index 138fd1da0..4255af607 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/src/flip.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/IndexCheck/src/flip.adb @@ -3,13 +3,13 @@ with Args; use Args; package body Flip is pragma Unsuppress (All_Checks); - + function Neg (A : Integer) return Boolean is begin -- Possible index check failure here return not Bool_For (A); -- # eval end; - + procedure Neg (A : Integer; R : out Boolean) is begin R := Neg (A); -- # eval diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/src/flip.adb index 611e88136..bac6d7072 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/src/flip.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RangeCheck/src/flip.adb @@ -9,10 +9,10 @@ package body Flip is -- Possible range check failure on conversion here return not Bool (Boolval(A)); -- # eval end; - + procedure Neg (A : Integer; R : out Boolean) is begin R := Neg (A); -- # eval end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/src/flip.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/src/flip.adb index 4b60374a9..3ccb9ab77 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/src/flip.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Flip/Return/RemoteCheck/src/flip.adb @@ -7,10 +7,10 @@ package body Flip is -- Safe conversion here, possible raise from Args.Bool return not Bool (Intval(A)); -- # eval end; - + procedure Neg (A : Integer; R : out Boolean) is begin R := Neg (A); -- # eval end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/src/fuor.adb index 6c06de172..722cb3dc8 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/src/fuor.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/IndexCheck/src/fuor.adb @@ -3,13 +3,13 @@ with Args; use Args; package body Fuor is pragma Unsuppress (All_Checks); - + function Orelse (A, B : Integer) return Boolean is begin -- Possible out of range array access here return Bool_For (A) or else Bool_For(B); -- # eval end; - + procedure Orelse (A, B : Integer; R : out Boolean) is begin R := Orelse (A, B); -- # eval diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/src/fuor.adb index d1ebfd389..94ea1103d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/src/fuor.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RangeCheck/src/fuor.adb @@ -9,7 +9,7 @@ package body Fuor is -- Possible range check failure on conversion here return Bool (Boolval(A)) or else Bool (Boolval(B)); -- # eval end; - + procedure Orelse (A, B : Integer; R : out Boolean) is begin R := Orelse (A, B); -- # eval diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/src/fuor.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/src/fuor.adb index cefe41081..fb407e60e 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/src/fuor.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Or/Return/RemoteCheck/src/fuor.adb @@ -7,7 +7,7 @@ package body Fuor is -- Safe conversion here, possible raise from Args.Bool return Bool (Intval(A)) or else Bool (Intval(B)); -- # eval end; - + procedure Orelse (A, B : Integer; R : out Boolean) is begin R := Orelse (A, B); -- # eval diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/src/val.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/src/val.adb index e12aa6d71..49f58959d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/src/val.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/CutEvals/Value/Return/RangeCheck/src/val.adb @@ -14,5 +14,5 @@ package body Val is begin R := To_Bool (A); -- # eval end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/src/ctxt.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/src/ctxt.adb index 603afb7b9..015326e46 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/src/ctxt.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/WithinElab/src/ctxt.adb @@ -1,13 +1,13 @@ pragma Unsuppress (All_Checks); package body Ctxt is - + generic Iraise : Boolean; Xraise : Boolean; package G_Checker is end; - + package body G_Checker is begin declare @@ -28,7 +28,7 @@ package body Ctxt is Check (Iraise => Iraise, Xraise => Xraise); -- # pre end; end; - + procedure Run (Iraise, Xraise : Boolean) is package Checker is new G_Checker (Iraise => Iraise, Xraise => Xraise); diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_iraise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_iraise.adb index 38b499bd7..3f41c049a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_iraise.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_iraise.adb @@ -14,4 +14,3 @@ end; -- /post/ l- ## s- -- /handler/ l+ ## 0 -- /other/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_noraise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_noraise.adb index 332bb1470..4ac2380e6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_noraise.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_noraise.adb @@ -14,4 +14,3 @@ end; -- /post/ l+ ## 0 -- /handler/ l- ## s- -- /other/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_xraise.adb b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_xraise.adb index 1e1b9a709..140909040 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_xraise.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/src/test_ctxt_xraise.adb @@ -14,4 +14,3 @@ end; -- /post/ l- ## s- -- /handler/ l+ ## 0 -- /other/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.ads index 82d51bebc..17ea3794c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/Basics/src/ops.ads @@ -1,4 +1,4 @@ package Ops is procedure Div (X, Y : Integer; T : out Integer; Fault : out Boolean); - procedure Bump (X : in out Integer; Fault : out Boolean); + procedure Bump (X : in out Integer; Fault : out Boolean); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/ctxt.ads b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/ctxt.ads index 1493115e6..68f6394fa 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/ctxt.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/src/ctxt.ads @@ -1,10 +1,10 @@ with Doraise; use Doraise; package Ctxt is - + -- A few globals that let us insert statements at various -- spots and sanity check the logic we ran through. - + X : Integer := 0; Handled : Integer := 0; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/stacks.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/stacks.ads index 6b49be98a..5be249f47 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/stacks.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/stacks.ads @@ -2,4 +2,3 @@ with Stacks_G; package Stacks is new Stacks_G (Value => Integer, Init_Val => 0); - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.ads index ca588cbfc..1047d0237 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.ads @@ -10,6 +10,6 @@ package Sensors is type Temp_Unit is (C, F); procedure Test (Value : Float; Unit : Temp_Unit); - + N_Tests_C, N_Tests_F : Natural := 0; end Sensors; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cbfn.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cbfn.adb index 71a01ddca..24b22303f 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cbfn.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cbfn.adb @@ -7,19 +7,19 @@ begin -- C in range (!low !high => Out-False) Sensors.Test (37.0, C); - + -- C out of range (!low, high => Out-True) Sensors.Test (200.0, C); - + Assert (Sensors.N_Tests_C = 2); Assert (Sensors.N_Tests_F = 0); - + Assert (RC.In_Range_Count = 1); Assert (RC.Out_Of_Range_Count = 1); Assert (RF.In_Range_Count = 0); Assert (RF.Out_Of_Range_Count = 0); - + end Test_CBFN; --# sensors.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifn.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifn.adb index bc4f85e96..cec25a425 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifn.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifn.adb @@ -8,7 +8,7 @@ begin Assert (Sensors.N_Tests_C = 1); Assert (Sensors.N_Tests_F = 0); - + Assert (RC.In_Range_Count = 1); Assert (RC.Out_Of_Range_Count = 0); Assert (RF.In_Range_Count = 0); @@ -36,4 +36,3 @@ end Test_CIFN; -- =/test-out/ l! ## s-@(i:RF) -- =/in-range/ l! ## s-@(i:RF) -- =/out-range/ l- ## s-@(i:RF), s-@(i:RC) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifo.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifo.adb index 20c51400b..e752e0476 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifo.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifo.adb @@ -12,12 +12,12 @@ begin Assert (Sensors.N_Tests_C = 1); Assert (Sensors.N_Tests_F = 1); - + Assert (RC.In_Range_Count = 1); Assert (RC.Out_Of_Range_Count = 0); Assert (RF.In_Range_Count = 0); Assert (RF.Out_Of_Range_Count = 1); - + end Test_CIFO; --# sensors.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfn.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfn.adb index 691cf0bcf..73b77d250 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfn.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfn.adb @@ -25,4 +25,3 @@ end Test_CNFN; -- =/test-out/ l- ## s-@(i:RF), s-@(i:RC) -- =/in-range/ l- ## s-@(i:RF), s-@(i:RC) -- =/out-range/ l- ## s-@(i:RF), s-@(i:RC) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfo.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfo.adb index 3d6063954..9383e29a2 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfo.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfo.adb @@ -27,4 +27,3 @@ end Test_CNFO; -- =/test-out/ l! ## s-@(i:RC) -- =/in-range/ l- ## s-@(i:RF), s-@(i:RC) -- =/out-range/ l! ## s-@(i:RC) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5i_8m.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5i_8m.adb index 44aba7c72..d8f3b46d6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5i_8m.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5i_8m.adb @@ -9,7 +9,7 @@ procedure Test_5i_8m is begin V5.Inc (V5o, 3); Assert (V5o(1) = 4); - + V8.Mult (V8o, 2); Assert (V5o(2) = 4); end; @@ -28,5 +28,3 @@ end; --# v5.ads --# v8.ads - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5m_8i.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5m_8i.adb index cfc4b9fa9..1b1a1ea71 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5m_8i.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5m_8i.adb @@ -9,7 +9,7 @@ procedure Test_5m_8i is begin V5.Inc (V5o, 3); Assert (V5o(1) = 4); - + V8.Mult (V8o, 2); Assert (V5o(2) = 4); end; @@ -28,5 +28,3 @@ end; --# v5.ads --# v8.ads - - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9i.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9i.adb index 527f89058..f614767a8 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9i.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9i.adb @@ -23,4 +23,3 @@ end; -- %cov: -S instance -- =/mult/ l- ## s-@(i:V6), s-@(i:V9) -- =/inc/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9m.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9m.adb index 5e1e08ded..ca98e0483 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9m.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9m.adb @@ -4,7 +4,7 @@ procedure Test_6i_9m is begin V6or9.Check (V6inc => True, V6mult => False, - V9inc => False, + V9inc => False, V9mult => True); end; @@ -23,4 +23,3 @@ end; -- %cov: -S instance -- =/mult/ l! ## s-@(i:V6) -- =/inc/ l! ## s-@(i:V9) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9i.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9i.adb index 66d450275..04da01f4c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9i.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9i.adb @@ -4,7 +4,7 @@ procedure Test_6m_9i is begin V6or9.Check (V6inc => False, V6mult => True, - V9inc => True, + V9inc => True, V9mult => False); end; @@ -23,4 +23,3 @@ end; -- %cov: -S instance -- =/mult/ l! ## s-@(i:V9) -- =/inc/ l! ## s-@(i:V6) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9m.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9m.adb index f800d1eae..37781bd82 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9m.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9m.adb @@ -4,7 +4,7 @@ procedure Test_6m_9m is begin V6or9.Check (V6inc => False, V6mult => True, - V9inc => False, + V9inc => False, V9mult => True); end; @@ -23,4 +23,3 @@ end; -- %cov: -S instance -- =/mult/ l+ ## 0 -- =/inc/ l- ## s-@(i:V6), s-@(i:V9) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9m.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9m.adb index c74a3b32a..50dea2942 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9m.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9m.adb @@ -4,7 +4,7 @@ procedure Test_6mi_9m is begin V6or9.Check (V6inc => True, V6mult => True, - V9inc => False, + V9inc => False, V9mult => True); end; @@ -23,4 +23,3 @@ end; -- %cov: -S instance -- =/mult/ l+ ## 0 -- =/inc/ l! ## s-@(i:V9) - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9mi.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9mi.adb index f8b8247e2..c0bdd76d5 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9mi.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9mi.adb @@ -4,7 +4,7 @@ procedure Test_6mi_9mi is begin V6or9.Check (V6inc => True, V6mult => True, - V9inc => True, + V9inc => True, V9mult => True); end; @@ -23,4 +23,3 @@ end; -- %cov: -S instance -- =/mult/ l+ ## 0 -- =/inc/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.adb index ec12bba31..998bf5e3a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.adb @@ -1,12 +1,12 @@ with Vops, Support; use Support; package body V6or9 is - + procedure Check (V6inc, V6mult, V9inc, V9mult : Boolean) is package V6 is new Vops (Size => 6); -- # i:V6 V6i : V6.Vector_Type := (others => 2); V6m : V6.Vector_Type := (others => 2); - + package V9 is new Vops (Size => 9); -- # i:V9 V9i : V9.Vector_Type := (others => 3); V9m : V9.Vector_Type := (others => 3); @@ -26,7 +26,6 @@ package body V6or9 is if V9mult then -- # stmt V9.Mult (V9m, 2); -- # 9m Assert (V9m(1) = 6); -- # 9m - end if; + end if; end; end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.adb index 9970f51a3..11e51fb0c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.adb @@ -1,17 +1,17 @@ package body Vops is - + procedure Inc (V : in out Vector_Type; Amount : Integer) is begin for I in V'Range loop -- # inc V(I) := V(I) + Amount; -- # inc end loop; end; - + procedure Mult (V : in out Vector_Type; Amount : Integer) is begin for I in V'Range loop -- # mult V(I) := V(I) * Amount; -- # mult end loop; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.ads index af21cdbb4..f68701fe6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.ads @@ -5,7 +5,7 @@ generic Size : in Integer; package Vops is type Vector_Type is array (1 .. Size) of Integer; - + procedure Inc (V : in out Vector_Type; Amount : Integer); procedure Mult (V : in out Vector_Type; Amount : Integer); end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/src/stacks_g.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/src/stacks_g.ads index 1157a032d..a82e27e2d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/src/stacks_g.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/src/stacks_g.ads @@ -18,9 +18,9 @@ private -- We use a small static size here to prevent dragging dependencies to -- memcpy, malloc or secondary stack services, irrelevant to the purpose -- of the testcase family we serve. - + type Value_Array is array (1 .. 5) of Value; -- # elab - + type Stack is record -- # elab Store : Value_Array; -- # line-elab N_Values : Natural := 0; -- # line-elab diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/src/data.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/src/data.adb index 2fa1364d1..976e7d56a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/src/data.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/Inserts_In_Cond/src/data.adb @@ -1,10 +1,10 @@ with System.Machine_Code; use System.Machine_Code; package body Data is - + function Id (X, Pathno: Integer) return Integer is Copy : Integer := X; - pragma Volatile (Copy); + pragma Volatile (Copy); begin if Pathno = 1 then Asm ("nop", Volatile => True); -- # asm_1 @@ -13,5 +13,5 @@ package body Data is end if; return Copy; end; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.adb index c14147f9b..b26c762c7 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.adb @@ -1,6 +1,6 @@ package body Mystreams is - + procedure Sint_Read (S : not null access Root_Stream_Type'Class; Item : out Sint) is @@ -10,8 +10,8 @@ package body Mystreams is when Copy => Item.Value := Latch; -- # read_copy end case; end; - - procedure Sint_Write + + procedure Sint_Write (S : not null access Root_Stream_Type'Class; Item : in Sint) is begin @@ -20,9 +20,9 @@ package body Mystreams is when Copy => Latch := Item.Value; -- # write_copy end case; end; - + -- - + overriding procedure Read (Port : in out Port_T; Buffer : out Stream_Element_Array; @@ -31,7 +31,7 @@ package body Mystreams is begin null; -- # pread end Read; - + overriding procedure Write (Port : in out Port_T; Buffer : Stream_Element_Array) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.ads b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.ads index e90b824e4..4fbb90c8d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/mystreams.ads @@ -1,42 +1,42 @@ with Ada.Streams; use Ada.Streams; package Mystreams is - + type Port_T is new Root_Stream_Type with null record; - + overriding procedure Read (Port : in out Port_T; Buffer : out Stream_Element_Array; Last : out Stream_Element_Offset); - + overriding procedure Write (Port : in out Port_T; Buffer : Stream_Element_Array); - + -- - + type Sint_Mode_Type is (Copy, Double); -- When reading or writing integers from/into a stream, whether -- we should read/fetch the base values untouched or multiply them -- by two; - + Sint_Mode : Sint_Mode_Type := Copy; - + type Sint is record Value : Integer; end record; - + procedure Sint_Read (S : not null access Root_Stream_Type'Class; Item : out Sint); - - procedure Sint_Write + + procedure Sint_Write (S : not null access Root_Stream_Type'Class; Item : in Sint); - + for Sint'Read use Sint_Read; for Sint'Write use Sint_Write; - + Latch : Integer := 0; - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_copy.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_copy.adb index cfe5aecd3..731ea504a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_copy.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_copy.adb @@ -20,4 +20,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_double.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_double.adb index 8b41d6b25..3ff96a5e6 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_double.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_read_double.adb @@ -20,4 +20,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_copy.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_copy.adb index f56d76bfe..17ef634f1 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_copy.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_copy.adb @@ -7,7 +7,7 @@ begin Mystreams.Sint_Mode := Copy; Sint'Write (P'Access, X); Assert (Latch = 1); - + Sint'Read (P'Access, X); Assert (X.Value = 1); end; @@ -23,4 +23,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_double.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_double.adb index ee110151f..63207cde9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_double.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_rw_double.adb @@ -7,7 +7,7 @@ begin Mystreams.Sint_Mode := Double; Sint'Write (P'Access, X); Assert (Latch = 2); - + Sint'Read (P'Access, X); Assert (X.Value = 4); end; @@ -23,4 +23,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wcrd.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wcrd.adb index fb65c8f89..095d0299a 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wcrd.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wcrd.adb @@ -7,7 +7,7 @@ begin Mystreams.Sint_Mode := Copy; Sint'Write (P'Access, X); Assert (Latch = 1); - + Mystreams.Sint_Mode := Double; Sint'Read (P'Access, X); Assert (X.Value = 2); @@ -24,4 +24,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wdrc.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wdrc.adb index bd3ea4299..69cd74529 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wdrc.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_wdrc.adb @@ -7,7 +7,7 @@ begin Mystreams.Sint_Mode := Double; Sint'Write (P'Access, X); Assert (Latch = 2); - + Mystreams.Sint_Mode := Copy; Sint'Read (P'Access, X); Assert (X.Value = 2); @@ -24,4 +24,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_copy.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_copy.adb index 1f374cdb6..543559656 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_copy.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_copy.adb @@ -20,4 +20,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_double.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_double.adb index f614dd34f..a0b65a695 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_double.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/test_write_double.adb @@ -20,4 +20,3 @@ end; -- /pread/ l- ## s- -- /pwrite/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.adb index aaf9317c0..7fc5a6a9c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.adb @@ -1,11 +1,11 @@ with Mystreams; use Mystreams; package body Trigger is - + -- point here is to have calls via operational attributes -- conditioned, controlling that they are not marked covered -- just because they are special sorts of calls. - + procedure Run (Op : Opkind) is P : aliased Port_T; X : Sint := (Value => 1); @@ -16,4 +16,3 @@ package body Trigger is end case; end; end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.ads b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.ads index 0aac346f7..f4738acf2 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/src/trigger.ads @@ -3,4 +3,3 @@ package Trigger is type Opkind is (Read, Write); procedure Run (Op : Opkind); end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-full.ads b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-full.ads index 1e0b54746..77a9d7847 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-full.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-full.ads @@ -1,13 +1,13 @@ with Data; package Global_Refs.Full is - + X : aliased Integer; -- # decl for X'Address use -- # clause Data.Data_Address (Index => Data.Data_Array'First); -- # clause - + Y : aliased Integer; -- # decl for Y'Address use -- # clause Data.Data_Address (Index => Data.Data_Array'Last+1); -- # clause - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-inrange.ads b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-inrange.ads index c2dc60380..6819c0f04 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-inrange.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-inrange.ads @@ -1,9 +1,9 @@ with Data; package Global_Refs.Inrange is - + X : aliased Integer; -- # decl for X'Address use -- # clause Data.Data_Address (Index => Data.Data_Array'First); -- # clause - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-outrange.ads b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-outrange.ads index 6d4ac4ce1..719aa494c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-outrange.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Global/src/global_refs-outrange.ads @@ -1,9 +1,9 @@ with Data; package Global_Refs.Outrange is - + X : aliased Integer; -- # decl for X'Address use -- # clause Data.Data_Address (Index => Data.Data_Array'Last + 1); -- # clause - + end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.adb index cfb9fefdd..73c515bd1 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.adb @@ -1,27 +1,26 @@ with Data, System, Support; use Support; package body Process is - + procedure Check_Inrange is - + V : aliased Integer; -- # in_decl for V'Address use -- # in_clause Data.Data_Address(Index => Data.Data_Array'First); -- # in_clause - + begin Assert (V = Data.Data_Array(Data.Data_Array'First)); -- # in_stmt end; - + procedure Check_Outrange is - + V : aliased Integer; -- # out_decl for V'Address use -- # out_clause Data.Data_Address(Index => Data.Data_Array'Last + 1); -- # out_clause - + use type System.Address; begin Assert (V'Address = System.Null_Address); -- # out_stmt end; - -end; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.ads b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.ads index 92a022ff7..167acd913 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/Addr_On_Local/src/process.ads @@ -1,5 +1,4 @@ -package Process is +package Process is procedure Check_Inrange; procedure Check_Outrange; end; - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/src/data.adb b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/src/data.adb index 0fe7accd7..bcb458aa9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/src/data.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/src/data.adb @@ -9,4 +9,3 @@ package body Data is end if; end; end; - diff --git a/testsuite/Qualif/Ada/stmt/Consolidation/MultipleForOne/src/ranges.adb b/testsuite/Qualif/Ada/stmt/Consolidation/MultipleForOne/src/ranges.adb index 677b0c2b9..b4f836f4b 100644 --- a/testsuite/Qualif/Ada/stmt/Consolidation/MultipleForOne/src/ranges.adb +++ b/testsuite/Qualif/Ada/stmt/Consolidation/MultipleForOne/src/ranges.adb @@ -11,4 +11,3 @@ package body Ranges is end if; end; end; - diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/counters.adb b/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/counters.adb index 3a2eb18af..c7f90cfaf 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/counters.adb +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/counters.adb @@ -26,5 +26,3 @@ package body Counters is end; end; end; - - diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/test_counters_all.adb b/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/test_counters_all.adb index db99734ff..a1a576353 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/test_counters_all.adb +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/Contexts/Subprograms/src/test_counters_all.adb @@ -10,4 +10,3 @@ begin end; --# counters.adb - diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/Controls/Goto/src/minx2.adb b/testsuite/Qualif/Ada/stmt/ControlFlow/Controls/Goto/src/minx2.adb index b5b942d1d..b9e82cd37 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/Controls/Goto/src/minx2.adb +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/Controls/Goto/src/minx2.adb @@ -19,4 +19,3 @@ begin Assert (M = Natural'Min (X, 2)); -- # common return M; -- # common end; - diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/src/minx2.ads b/testsuite/Qualif/Ada/stmt/ControlFlow/src/minx2.ads index e21c5deb3..ce0110498 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/src/minx2.ads +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/src/minx2.ads @@ -1,4 +1,3 @@ function MinX2 (X : Natural) return Natural; -- Compute and return the minimum of X and 2. Feature flow control -- based on goto and return statements. - diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_full.adb b/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_full.adb index 90a0e3580..a51c0cafe 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_full.adb +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_full.adb @@ -15,5 +15,3 @@ end; -- /xgt0/ l+ ## 0 -- /xgt2/ l+ ## 0 -- /xle2/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_le.adb b/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_le.adb index ad88e4230..22db4d35d 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_le.adb +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/src/test_minx2_le.adb @@ -14,5 +14,3 @@ end; -- /xgt0/ l+ ## 0 -- /xgt2/ l- ## s- -- /xle2/ l+ ## 0 - - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_exempted_code_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_exempted_code_call.adb index d2c290228..c1735af67 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_exempted_code_call.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_exempted_code_call.adb @@ -46,16 +46,3 @@ end Test_Exemptions_All_Exempted_Code_Call; -- /xelab_1/ l# ## x0 -- /elab/ l+ ## 0 -- /xelab_2/ l# ## x0 - - - - - - - - - - - - - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_exempted_code_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_exempted_code_call.adb index a45c71ea0..e85e4ab8f 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_exempted_code_call.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_exempted_code_call.adb @@ -49,4 +49,3 @@ end Test_Exemptions_Exempted_Code_Call; -- /xelab_1/ l# ## x0 -- /elab/ l+ ## 0 -- /xelab_2/ l# ## x0 - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb index b5689ce09..dd805168e 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb @@ -40,4 +40,3 @@ end Test_Exemptions_No_Call; -- /xelab_1/ l# ## x0 -- /elab/ l+ ## 0 -- /xelab_2/ l# ## x0 - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb index 74e38a8f8..a05129959 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb @@ -51,4 +51,3 @@ end Test_Exemptions_Non_Exempted_Code_Call; -- /xelab_1/ l# ## x0 -- /elab/ l+ ## 0 -- /xelab_2/ l# ## x0 - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_o.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_o.adb index 9839a964f..8bb76caf7 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_o.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_push_o.adb @@ -9,7 +9,7 @@ begin Push (S, 1); Push (S, 3); Assert (Errcount (S) = 0); - + Push (S, 4); Assert (Errcount (S) = 1); end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_0.adb index ea1eefc79..249586671 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_0.adb @@ -6,15 +6,15 @@ procedure Test_PushPop_0 is S : Stack (Size => 2); V : Integer; begin - Push (S, 1); - Push (S, 2); - + Push (S, 1); + Push (S, 2); + Pop (S, V); Assert (V = 2); - + Pop (S, V); Assert (V = 1); - + Assert (Errcount (S) = 0); end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_o.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_o.adb index 04f397815..373cceb08 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_o.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_o.adb @@ -9,10 +9,10 @@ begin Push (S, 1); Push (S, 2); Assert (Errcount (S) = 0); - + Push (S, 3); Assert (Errcount (S) = 1); - + Pop (S, V); Assert (V = 2); end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_ou.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_ou.adb index a05421256..5469640b3 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_ou.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_ou.adb @@ -6,19 +6,19 @@ procedure Test_PushPop_OU is S : Stack (Size => 2); V : Integer; begin - Push (S, 1); - Push (S, 2); + Push (S, 1); + Push (S, 2); Assert (Errcount (S) = 0); - + Push (S, 3); Assert (Errcount (S) = 1); Pop (S, V); Assert (V = 2); - + Pop (S, V); Assert (V = 1); - + Pop (S, V); Assert (Errcount (S) = 2); end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_u.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_u.adb index 6c9635276..9c50e1bab 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_u.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInBody/src/test_pushpop_u.adb @@ -6,11 +6,11 @@ procedure Test_PushPop_U is S : Stack (Size => 2); V : Integer; begin - Push (S, 1); + Push (S, 1); Pop (S, V); Assert (V = 1); Assert (Errcount (S) = 0); - + Pop (S, V); Assert (Errcount (S) = 1); end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.ads b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.ads index b3bb7b247..825492be4 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.ads +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/com.ads @@ -14,4 +14,3 @@ package Com is -- The package elaboration body calls Initialize if Auto_Initialize -- is True, which can never happen. end; - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/comi_noinit.ads b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/comi_noinit.ads index 32a5a28ca..6ec75025a 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/comi_noinit.ads +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInElab/src/comi_noinit.ads @@ -4,4 +4,3 @@ with Support, Gcom; use Support; package Comi_NoInit is new Gcom (Auto_Init => Identity(False)); - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_0.adb index fa6b14f28..d40658d42 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_0.adb @@ -29,4 +29,3 @@ end Test_0; -- /h_exem_v2/ l= ## Xs- -- /h_exem_v3/ l= ## Xs- -- /h_exem_v4/ l= ## Xs- - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_0.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_0.adb index c9401e6e9..08e0e68c1 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_0.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_0.adb @@ -24,15 +24,3 @@ end; -- /3_exem/ l# ## x0 -- /h_flag/ l+ ## 0 -- /h_exem/ l# ## x0 - - - - - - - - - - - - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr23.adb b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr23.adb index 716dfb969..72be78090 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr23.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/StmtsInSubprog/src/test_exempt_xr23.adb @@ -6,10 +6,10 @@ with MX; use MX; procedure Test_Exempt_XR23 is begin Trigger_XR1; - + -- Region 1 raises an exception, force running the other blocks -- without the exempted regions. - + Trigger_0XR; end; diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.ads b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.ads index 64576eb46..68d462531 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.ads +++ b/testsuite/Qualif/Ada/stmt/Exemptions/WholeBody/src/tipos.ads @@ -1,4 +1,2 @@ function Tipos (X : Integer) return Integer; -- Twice_If_Pos: x * 2 if x positive, x otherwise. - - diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/extra.opt b/testsuite/Qualif/Ada/stmt/Exemptions/extra.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/extra.opt +++ b/testsuite/Qualif/Ada/stmt/Exemptions/extra.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/sensors-status.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/sensors-status.adb index 3b5b4b2a2..fdd37df89 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/sensors-status.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/sensors-status.adb @@ -34,4 +34,3 @@ package body Sensors.Status is end; end; - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_broken.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_broken.adb index 7ed58c3f1..d3ba4b9b4 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_broken.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_broken.adb @@ -3,24 +3,24 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Broken is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; - + -- Two history entries, both out of range - - S.V := 15; + + S.V := 15; Sample (S); Sample (S); - + Assert (Status_Of (S) = Broken); - + -- A third entry, in range. Still two out of range. - - S.V := 5; + + S.V := 5; Sample (S); - + Assert (Status_Of (S) = Broken); end; diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check.adb index 182ff8b10..8155e3ca4 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check.adb @@ -3,23 +3,23 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; - + -- Single history entry, out of range - - S.V := 15; + + S.V := 15; Sample (S); - + Assert (Status_Of (S) = Check); - + -- Two history entries, only one out of range - - S.V := 5; + + S.V := 5; Sample (S); - + Assert (Status_Of (S) = Check); end; diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check_brok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check_brok.adb index b25045422..f059116ab 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check_brok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_check_brok.adb @@ -4,15 +4,15 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Check_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 15; Sample (S); Assert (Status_Of (S) = Check); - + Sample (S); Assert (Status_Of (S) = Broken); end; diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok.adb index 41f130fb0..25da1cff6 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok.adb @@ -3,12 +3,12 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_OK is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Sample (S); Assert (Status_Of (S) = Ok); end; diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb index b5d53ffe8..1a32eb2e2 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_brok.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 15; Sample (S); Sample (S); Assert (Status_Of (S) = Broken); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check.adb index d25eb08eb..b51c551af 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 15; Sample (S); Assert (Status_Of (S) = Check); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb index dc9ce0599..14e2b25be 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_ok_check_brok.adb @@ -4,19 +4,19 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Ok_Check_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); - + S.V := 40; Sample (S); Assert (Status_Of (S) = Broken); diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_brok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_brok.adb index 61d041b89..0dee6dae7 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_brok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_brok.adb @@ -4,18 +4,18 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 1; Sample (S); Sample (S); Assert (Status_Of (S) = Broken); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_check.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_check.adb index c69010279..87286041a 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_check.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_check.adb @@ -4,21 +4,21 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Check); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok.adb index c66ff198b..39350b815 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok.adb @@ -4,17 +4,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Assert (Status_Of (S) = Undecidable); - + Sample (S); Assert (Status_Of (S) = Ok); - + end; --# sensors-status.adb diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb index b3f615ea2..aa3c5b380 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_brok.adb @@ -4,20 +4,20 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok_Brok is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); - + S.V := 40; Sample (S); Assert (Status_Of (S) = Broken); diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb index 3b4c5e5a5..3e50f7c12 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_und_ok_check.adb @@ -4,17 +4,17 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Und_Ok_Check is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 5; S.AHB := 10; - + Assert (Status_Of (S) = Undecidable); - + S.V := 5; Sample (S); Assert (Status_Of (S) = Ok); - + S.V := 1; Sample (S); Assert (Status_Of (S) = Check); diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_undecide.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_undecide.adb index 31c0335c9..bcea68f69 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_undecide.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/If_For_If_Case/src/test_undecide.adb @@ -3,12 +3,12 @@ with Sensors.Status; use Sensors, Sensors.Status; procedure Test_Undecide is S : aliased Sensor (Hist_Size => 5); - + begin S.ALB := 1; S.AHB := 10; S.V := 5; - + Assert (Status_Of (S) = Undecidable); end; diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/slists-count.ads b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/slists-count.ads index be1a4bef4..7dfcde28c 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/slists-count.ads +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/slists-count.ads @@ -6,4 +6,3 @@ package Slists.Count is SP : SP_Access := Pass'Access; NT, NF : out Natural); end; - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iff.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iff.adb index ae80f0d75..bae3dea63 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iff.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iff.adb @@ -26,4 +26,3 @@ end; -- /CO_incT/ l- ## s- -- /CO_incF/ l+ ## 0 -- /CO_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_ift.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_ift.adb index 76fca9e16..48bc0ae73 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_ift.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_ift.adb @@ -27,4 +27,3 @@ end; -- /CO_incT/ l+ ## 0 -- /CO_incF/ l- ## s- -- /CO_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iftf.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iftf.adb index 76312d21b..91786e246 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iftf.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_iftf.adb @@ -10,22 +10,22 @@ procedure Test_Iftf is Sin : aliased Sensor (Hist_Size => 5); -- in range sensor Sout : aliased Sensor (Hist_Size => 5); -- out of range sensor SL : Sensor_List; - + Nt, Nf : Natural; begin - + Sin.V := 5; Sin.ALB := 1; Sin.AHB := 10; - + Prepend (Sin'Unchecked_Access, SL); - + Sout.V := 5; Sout.ALB := 1; Sout.AHB := 3; - + Prepend (Sout'Unchecked_Access, SL); - + Count_In (Sl, Inrange'Access, Nt, Nf); Assert (Nt = 1); Assert (Nf = 1); @@ -40,4 +40,3 @@ end; -- /CO_incT/ l+ ## 0 -- /CO_incF/ l+ ## 0 -- /CO_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_noentry.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_noentry.adb index 449ff9419..347619b89 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_noentry.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If1/src/test_noentry.adb @@ -21,4 +21,3 @@ end; -- /CO_incT/ l- ## s- -- /CO_incF/ l- ## s- -- /CO_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_fft.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_fft.adb index d4d9e1dd3..b18e47280 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_fft.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_fft.adb @@ -6,14 +6,14 @@ procedure Test_If_FFT is S : aliased Sensor (Hist_Size =>5); begin Prepend (S'Unchecked_Access, SL); - + -- Arrange to 'ok' only - + S.ALB := 1; S.AHB := 1; S.V := 1; S.Active := True; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -36,4 +36,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftf.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftf.adb index 3911c8b85..34ad6c442 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftf.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftf.adb @@ -6,14 +6,14 @@ procedure Test_If_FTF is S : aliased Sensor (Hist_Size =>5); begin Prepend (S'Unchecked_Access, SL); - + -- Arrange to 'fault' only - + S.ALB := 1; S.AHB := 1; S.V := 5; S.Active := True; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -36,4 +36,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftt.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftt.adb index 70b0551cd..9f222f822 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftt.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ftt.adb @@ -5,21 +5,21 @@ procedure Test_If_FTT is SL : Sensor_List; S1, S2 : aliased Sensor (Hist_Size =>5); begin - Prepend (S1'Unchecked_Access, SL); + Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); - + -- Arrange to 'fault' and 'ok' only - + S1.ALB := 1; S1.AHB := 1; S1.V := 1; S1.Active := True; - + S2.ALB := 1; S2.AHB := 1; S2.V := 2; S2.Active := True; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -42,4 +42,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tff.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tff.adb index c3d1e3612..d8852b924 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tff.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tff.adb @@ -6,11 +6,11 @@ procedure Test_If_TFF is S : aliased Sensor (Hist_Size =>5); begin Prepend (S'Unchecked_Access, SL); - + -- Arrange to 'skip' only - + S.Active := False; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -33,4 +33,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tft.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tft.adb index 0096a384c..4791c1af0 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tft.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_tft.adb @@ -5,21 +5,21 @@ procedure Test_If_TFT is SL : Sensor_List; S1, S2 : aliased Sensor (Hist_Size =>5); begin - Prepend (S1'Unchecked_Access, SL); + Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); - + -- Arrange to 'skip' and 'ok' only - + S1.ALB := 1; S1.AHB := 1; S1.V := 1; S1.Active := True; - + S2.ALB := 1; S2.AHB := 1; S2.V := 2; S2.Active := False; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -42,4 +42,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttf.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttf.adb index f82455733..975edbb76 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttf.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttf.adb @@ -5,21 +5,21 @@ procedure Test_If_TTF is SL : Sensor_List; S1, S2 : aliased Sensor (Hist_Size =>5); begin - Prepend (S1'Unchecked_Access, SL); + Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); - + -- Arrange to 'skip' and 'fault' only - + S1.ALB := 1; S1.AHB := 1; S1.V := 0; S1.Active := True; - + S2.ALB := 1; S2.AHB := 1; S2.V := 2; S2.Active := False; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -42,4 +42,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l- ## s- -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttt.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttt.adb index 4396abf40..96dfeb04c 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttt.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_if_ttt.adb @@ -5,27 +5,27 @@ procedure Test_If_TTT is SL : Sensor_List; S1, S2, S3 : aliased Sensor (Hist_Size =>5); begin - Prepend (S1'Unchecked_Access, SL); + Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); Prepend (S3'Unchecked_Access, SL); - + -- Arrange to 'skip', 'fault' and 'ok' - + S1.ALB := 1; S1.AHB := 1; S1.V := 3; S1.Active := False; - + S2.ALB := 1; S2.AHB := 1; S2.V := 2; S2.Active := True; - + S3.ALB := 1; S3.AHB := 1; S3.V := 1; S3.Active := True; - + declare Skip, Fault, Ok : Sensor_List; begin @@ -48,4 +48,3 @@ end; -- /AF_fault/ l+ ## 0 -- /AF_ok/ l+ ## 0 -- /AF_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_noentry.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_noentry.adb index a7bbb75c4..aa779903c 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_noentry.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/src/test_noentry.adb @@ -24,4 +24,3 @@ end; -- /AF_fault/ l- ## s- -- /AF_ok/ l- ## s- -- /AF_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.adb index dd2dd3ea3..f734bf26f 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.adb @@ -26,4 +26,3 @@ package body Slists.Forall is end; end; - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.ads b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.ads index d1d942c70..5d475d37b 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.ads +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/slists-forall.ads @@ -3,4 +3,3 @@ package Slists.Forall is procedure ForAll_In (SL : Sensor_List; Op : Sensor_Op; Active_Only : Boolean := False); end; - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.adb index a28cdb8f6..877455f3a 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.adb @@ -8,7 +8,7 @@ begin S1.ALB := 1; S1.AHB := 10; S1.V := 5; -- # in range - + S2.ALB := 5; S2.AHB := 15; S2.V := 1; -- # < low bound @@ -20,10 +20,10 @@ begin Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); Prepend (S3'Unchecked_Access, SL); - + Forall_In (SL, Activate); Assert (S1.Active and then S2.Active and then S3.Active); - + Forall_In (SL, Inhibit); Assert (S1.Active and then (not S2.Active) and then (not S3.Active)); end; @@ -39,4 +39,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_activate.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_activate.adb index c1fdc00c6..08ab934fb 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_activate.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_activate.adb @@ -7,16 +7,16 @@ procedure Test_Activate is begin S1.ALB := 1; S1.AHB := 10; - + S2.ALB := 5; S2.AHB := 15; Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); - + Forall_In (SL, Activate, Active_Only => True); Assert ((not S1.Active) and then (not S2.Active)); - + Forall_In (SL, Activate); Assert (S1.Active and then S2.Active); end; @@ -32,4 +32,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.adb index 8d2160933..4886c1134 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.adb @@ -9,7 +9,7 @@ begin S1.AHB := 10; S1.V := 5; -- # in range S1.Active := True; - + S2.ALB := 5; S2.AHB := 15; S2.V := 1; -- # < low bound @@ -23,7 +23,7 @@ begin Prepend (S1'Unchecked_Access, SL); Prepend (S2'Unchecked_Access, SL); Prepend (S3'Unchecked_Access, SL); - + Forall_In (SL, Inhibit); Assert (S1.Active and then (not S2.Active) and then (not S3.Active)); end; @@ -39,4 +39,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l+ ## 0 -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_nocase.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_nocase.adb index ca014d18c..31e7aef65 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_nocase.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_nocase.adb @@ -24,4 +24,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noentry.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noentry.adb index bd7f368c4..bf9f04fc7 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noentry.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noentry.adb @@ -18,4 +18,3 @@ end; -- /FA_tinhibitHB/ l- ## 0c -- /FA_inhibit/ l- ## s- -- /FA_next/ l- ## s- - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb index f98bb9a1a..88a2d7093 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If_Case_If/src/test_noinhibit.adb @@ -7,14 +7,14 @@ procedure Test_Noinhibit is begin -- get into the inhibit case selection, arranging for the -- if statement there to always evaluate false - + S1.ALB := 1; S1.AHB := 10; S1.V := 5; -- # in range S1.Active := True; - + Prepend (S1'Unchecked_Access, SL); - + Forall_In (SL, Inhibit); Assert (S1.Active); end; @@ -30,4 +30,3 @@ end; -- /FA_tinhibitHB/ l+ ## 0 -- /FA_inhibit/ l- ## s- -- /FA_next/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.adb index 404de97f8..a4f0b96fc 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.adb @@ -5,5 +5,3 @@ package body Sensors is Vbufs.Push (S.V, S.History); end; end; - - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.ads b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.ads index 97d448e97..f7f589942 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.ads +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/sensors.ads @@ -14,4 +14,3 @@ package Sensors is -- latch current sensor value for S in its history buffer end; - diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/slists.adb b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/slists.adb index dfbefee80..a3d2aa1ee 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/slists.adb +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/slists.adb @@ -2,10 +2,10 @@ with Vbufs; use Vbufs; with Simple_Pools; package body Slists is - + package Sensor_Nodes_Pool is new Simple_Pools.Basic_Pool (Data_Type => Sensor_Node, Capacity => 20); - + procedure Prepend (S : Sensor_Access; SL : in out Sensor_List) is NA : constant Sensor_Nodes_Pool.Data_Access := Sensor_Nodes_Pool.Allocate; begin diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/vbufs.ads b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/vbufs.ads index 1e5ad1b18..49646f52c 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/src/vbufs.ads +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/src/vbufs.ads @@ -13,4 +13,3 @@ package Vbufs is procedure Push (V : Value; VB : in out Vbuffer); end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/CondExpr/test.opt b/testsuite/Qualif/Ada/stmt/Robustness/CondExpr/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/CondExpr/test.opt +++ b/testsuite/Qualif/Ada/stmt/Robustness/CondExpr/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipb.adb b/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipb.adb index 4ee3767ad..e7f9936df 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipb.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipb.adb @@ -3,4 +3,3 @@ procedure FlipB (B : in out Boolean) is begin B := not B; -- # flipb end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipx.adb b/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipx.adb index b394e5909..711ca6746 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipx.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/Homonyms/src/sub_services-flipx.adb @@ -3,4 +3,3 @@ procedure FlipX (X : in out Integer) is begin X := -X; -- # flipx end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/LongSequence/src/bump.adb b/testsuite/Qualif/Ada/stmt/Robustness/LongSequence/src/bump.adb index 54c7296c0..b1456198b 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/LongSequence/src/bump.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/LongSequence/src/bump.adb @@ -1100,4 +1100,3 @@ begin X := X + 1; -- # bump X := X + 1; -- # bump end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/MultiStatementLines/src/addmult.adb b/testsuite/Qualif/Ada/stmt/Robustness/MultiStatementLines/src/addmult.adb index a0ab5cb14..963089274 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/MultiStatementLines/src/addmult.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/MultiStatementLines/src/addmult.adb @@ -5,4 +5,3 @@ begin S := X + Y; P := X * Y; -- # compute end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/bar.ads b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/bar.ads index 442b6bb71..07519dec3 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/bar.ads +++ b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/bar.ads @@ -3,4 +3,3 @@ pragma Restrictions (No_Elaboration_Code); package Bar is Z : Integer := 12; -- # decl end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/foo.ads b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/foo.ads index c3b31d30e..e65ac8cc0 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/foo.ads +++ b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/foo.ads @@ -5,4 +5,3 @@ package Foo is X : Myint := 12; -- # decl procedure Set_X (V : Myint); -- # decl end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/PartialEval/src/test_andthen_ff.adb b/testsuite/Qualif/Ada/stmt/Robustness/PartialEval/src/test_andthen_ff.adb index b22a23696..4bf065e23 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/PartialEval/src/test_andthen_ff.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/PartialEval/src/test_andthen_ff.adb @@ -10,4 +10,3 @@ end; --# andthen.adb -- /andthen/ l+ ## 0 - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.adb b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.adb index 1664c15bc..760b9d148 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.adb @@ -1,20 +1,20 @@ pragma Ada_2012; package body Ops is - + function V_Indexing (X : aliased in out Composite_V; Op : Op_Name) return Integer_Ref - is + is begin case Op is -- # indexing when OP_A => return (Ref => X.A'Access); -- # op_a when Op_B => return (Ref => X.B'Access); -- # op_b end case; end; - + function C_Indexing (X : aliased Composite_C'Class; Op : Op_Name) return Integer - is + is begin case Op is -- # indexing when OP_A => return X.A; -- # op_a @@ -22,5 +22,3 @@ package body Ops is end case; end; end; - - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.ads b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.ads index 95a22acac..a0d9a7061 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.ads +++ b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/ops.ads @@ -1,29 +1,28 @@ pragma Ada_2012; package Ops is - - type Op_Name is (Op_A, Op_B); - + + type Op_Name is (Op_A, Op_B); + type Composite_V is tagged record A, B : aliased Integer; end record with Variable_Indexing => V_Indexing; - + type Composite_C is tagged record A, B : aliased Integer; end record with Constant_Indexing => C_Indexing; - + type Integer_Ref (Ref : access Integer) is null record with Implicit_Dereference => Ref; - + function V_Indexing (X : aliased in out Composite_V; Op : Op_Name) return Integer_Ref; - + function C_Indexing (X : aliased Composite_C'Class; Op : Op_Name) return Integer; - + end; - diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opab.adb b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opab.adb index 547125249..ac9bee9ae 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opab.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opab.adb @@ -8,13 +8,13 @@ procedure Test_OPAB is begin CV(Op_A) := 12; Assert (CV.A = 12); - + CV.B := 5; Assert (CV(Op_B) = 5); - + CC.A := 12; Assert (CC(Op_A) = 12); - + CC.B := 5; Assert (CC(Op_B) = 5); end; diff --git a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opb.adb b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opb.adb index 50bad10d1..ce395bad7 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opb.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/Uindex/src/test_opb.adb @@ -8,9 +8,9 @@ procedure Test_OPB is begin CV.B := 5; Assert (CV(Op_B) = 5); - + CC.B := 12; - Assert (CC(Op_B) = 12); + Assert (CC(Op_B) = 12); end; --# ops.adb diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/src/test_inc_0.adb b/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/src/test_inc_0.adb index 516ce9972..a448df957 100644 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/src/test_inc_0.adb +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/src/test_inc_0.adb @@ -8,4 +8,3 @@ begin end; --# inc.adb - diff --git a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb index c251d49c3..5ff7faf25 100644 --- a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb +++ b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/test_at.adb @@ -11,4 +11,3 @@ end; -- /eval/ l! ## c!:"B", eF-:"C" -- /true/ l+ ## 0 -- /false/ l+ ## 0 - diff --git a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac_t.adb b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac_t.adb index d3aefc918..9ce9d4532 100644 --- a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac_t.adb +++ b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/test_ac_t.adb @@ -4,7 +4,7 @@ procedure Test_AC_T is begin Assert -- or-1, and-2 (Or_Eq_And_Not (False, False, False, False) = True); - + Assert -- or-3, and-1 (Or_Eq_And_Not (True, False, True, False) = True); end; diff --git a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.opt b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.opt index 9e5989f5a..141860657 100644 --- a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.opt +++ b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.opt @@ -1,2 +1,2 @@ src-traces DEAD Binary traces specific testcase -7.1.2 DEAD test GPR file attributes that were not supported in 7.1.2 \ No newline at end of file +7.1.2 DEAD test GPR file attributes that were not supported in 7.1.2 diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/src/test_lt0.adb b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/src/test_lt0.adb index 02ee09365..6714556e2 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/src/test_lt0.adb +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/src/test_lt0.adb @@ -12,4 +12,3 @@ begin Assert (N_LT0 = 1); Assert (N_GE0 = 0); end; - diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/src/test_lt0.adb b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/src/test_lt0.adb index 02ee09365..6714556e2 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/src/test_lt0.adb +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/src/test_lt0.adb @@ -12,4 +12,3 @@ begin Assert (N_LT0 = 1); Assert (N_GE0 = 0); end; - diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/src/andthen.adb b/testsuite/Qualif/Common/GprFacilities/MainAttr/src/andthen.adb index 22090ac7b..49cba2788 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/src/andthen.adb +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/src/andthen.adb @@ -2,4 +2,3 @@ function Andthen (A, B : Boolean) return Boolean is begin return A and then B; end; - diff --git a/testsuite/Qualif/Common/Report/EmptySections/src/test_expr_full.adb b/testsuite/Qualif/Common/Report/EmptySections/src/test_expr_full.adb index 57b0f1030..2140d4ff9 100644 --- a/testsuite/Qualif/Common/Report/EmptySections/src/test_expr_full.adb +++ b/testsuite/Qualif/Common/Report/EmptySections/src/test_expr_full.adb @@ -4,30 +4,30 @@ with Support, Expr; use Support, Expr; procedure Test_Expr_Full is begin -- cover and-then - + If_Andthen (True, False, 5); Assert (Expr.Value = 0); - + If_Andthen (False, True, 6); Assert (Expr.Value = 0); - + If_Andthen (False, False, 7); Assert (Expr.Value = 0); - + If_Andthen (True, True, 9); Assert (Expr.Value = 9); - + -- cover or-else - + If_Orelse (True, False, 5); Assert (Expr.Value = 5); - + If_Orelse (False, True, 6); Assert (Expr.Value = 6); - + If_Orelse (False, False, 7); Assert (Expr.Value = 6); - + If_Orelse (True, True, 9); Assert (Expr.Value = 9); end; diff --git a/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_invalid.adb b/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_invalid.adb index 782d0f36f..8a2196429 100644 --- a/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_invalid.adb +++ b/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_invalid.adb @@ -23,4 +23,3 @@ end; -- /checkOverlap/ l- ## s- -- /overlapTrue/ l- ## s- -- /overlapFalse/ l- ## s- - diff --git a/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_overlap.adb b/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_overlap.adb index 4955665a1..a1dfce5dc 100644 --- a/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_overlap.adb +++ b/testsuite/Qualif/Common/Report/Exemptions/src/test_ranges_overlap.adb @@ -46,4 +46,3 @@ end; -- /checkOverlap/ l! ## dF- -- /overlapTrue/ l+ ## 0 -- /overlapFalse/ l- ## s- - diff --git a/testsuite/Qualif/Common/Report/Exemptions/test.opt b/testsuite/Qualif/Common/Report/Exemptions/test.opt index 48973a3f2..a4e1eba80 100644 --- a/testsuite/Qualif/Common/Report/Exemptions/test.opt +++ b/testsuite/Qualif/Common/Report/Exemptions/test.opt @@ -1 +1 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 \ No newline at end of file +5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Common/Report/src/expr.adb b/testsuite/Qualif/Common/Report/src/expr.adb index 7fa6f98bc..2536890b8 100644 --- a/testsuite/Qualif/Common/Report/src/expr.adb +++ b/testsuite/Qualif/Common/Report/src/expr.adb @@ -18,5 +18,3 @@ package body Expr is end; end; - - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tf.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tf.adb index b9e6640a9..d3e0403ad 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tf.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tf.adb @@ -15,5 +15,3 @@ end; --# ops-orelse.adb -- /eval/ l- ## s- - - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tt.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tt.adb index 5239647fa..d53965446 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tt.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_and_tt.adb @@ -15,5 +15,3 @@ end; --# ops-orelse.adb -- /eval/ l- ## s- - - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_or_ft.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_or_ft.adb index 7292a72f8..6d428f3ec 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_or_ft.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/src/test_or_ft.adb @@ -15,5 +15,3 @@ end; --# ops-orelse.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/src/test_tc_or_sub.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/src/test_tc_or_sub.adb index de7eb6836..1d86e07e1 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/src/test_tc_or_sub.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/src/test_tc_or_sub.adb @@ -26,4 +26,3 @@ end; --# ../../intops/src/intops-sub.adb -- /eval/ l+ ## 0 - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/App/values.ads b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/App/values.ads index 7cedd5bd6..6044b2e46 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/App/values.ads +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/App/values.ads @@ -2,5 +2,3 @@ package Values is N_GE0, N_LT0 : Integer := 0; procedure Scan (X : Integer); end; - - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/src/test_lt0.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/src/test_lt0.adb index 02ee09365..6714556e2 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/src/test_lt0.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/src/test_lt0.adb @@ -12,4 +12,3 @@ begin Assert (N_LT0 = 1); Assert (N_GE0 = 0); end; - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tf.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tf.adb index 03dd99082..ead063806 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tf.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tf.adb @@ -15,5 +15,3 @@ end; --# ops/ops-orelse.adb -- /eval/ l- ## s- - - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tt.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tt.adb index 1a34e4a17..b47b81e31 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tt.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_and_tt.adb @@ -15,5 +15,3 @@ end; --# ops/ops-orelse.adb -- /eval/ l- ## s- - - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_or_ft.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_or_ft.adb index 59cba22eb..f9ae2f35b 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_or_ft.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/src/test_or_ft.adb @@ -15,5 +15,3 @@ end; --# ops/ops-orelse.adb -- /eval/ l! ## eF- - - diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/src/p.adb b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/src/p.adb index be364586a..53d54bb47 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/src/p.adb +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/src/p.adb @@ -4,4 +4,3 @@ begin exception when others => null; end; - diff --git a/testsuite/REST/rest.py b/testsuite/REST/rest.py index 8f412eafe..64809ae86 100644 --- a/testsuite/REST/rest.py +++ b/testsuite/REST/rest.py @@ -38,4 +38,3 @@ def toctree(l, depth=2): " :maxdepth: %s\n" % depth] + [" %s" % item for item in l]), post = 1) - diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index 6201904e6..1e27749a8 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -258,7 +258,7 @@ def __init__(self, runtime_name=None): self.has_exception_propagation = False self.discrs = ["RTS_ZFP"] elif ( - self.runtime_name == "light" + self.runtime_name == "light" or self.runtime_name.startswith('light-') ): self.has_light_runtime = True diff --git a/testsuite/altrun/isys_nexus_5634/setup.py b/testsuite/altrun/isys_nexus_5634/setup.py index 6858ebf5b..469b1d8e3 100644 --- a/testsuite/altrun/isys_nexus_5634/setup.py +++ b/testsuite/altrun/isys_nexus_5634/setup.py @@ -11,4 +11,3 @@ if p.status != 0: sys.exit(1) - diff --git a/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.adb b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.adb index 08aa91387..cfa9f4eeb 100644 --- a/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.adb +++ b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.adb @@ -1,85 +1,85 @@ with Support; use Support; package body Expr is - + procedure As_RHS (A, B : Boolean) is begin GB := A and then B; -- # eval end; - + procedure As_CASE (A, B : Boolean) is begin case A and then B is -- # eval when True => GX := GX + 1; -- # true when False => GX := GX - 1; -- # false - end case; + end case; end; - + procedure Set_GB (Value : Boolean) is begin GB := Value; end; - + procedure As_ACTUAL (A, B : Boolean) is begin Set_GB (A and then B); -- # eval end; - + function As_RETURN (A, B : Boolean) return Boolean is begin return A and then B; -- # eval end; - + procedure As_DECLINIT (A, B : Boolean) is X : Boolean := A and then B; -- # eval pragma Volatile (X); begin GB := X; end; - + type My_Bool (Value : Boolean) is null record; - + procedure As_DISCINIT (A, B : Boolean) is X : My_Bool (Value => A and then B); -- # eval pragma Volatile (X); begin GB := X.Value; end; - + type My_Block is array (1 .. 1) of Boolean; - + procedure As_AGGREGATE (A, B : Boolean) is X : My_Block := (others => A and then B); -- # eval pragma Volatile (X); begin GB := X(X'First); end; - + pragma Check_Policy (Precondition, On); pragma Check_Policy (Postcondition, On); - + procedure As_BODYPRECOND (A, B : Boolean) is pragma Precondition (A and then B); -- # freestanding-expr begin GX := GX + 1; end; - + procedure As_BODYPOSTCOND (A, B : Boolean) is pragma Postcondition (A and then B); -- # freestanding-expr begin GX := GX + 1; end; - + procedure As_SPECPRECOND (A, B : Boolean) is begin GX := GX + 1; end; - + procedure As_SPECPOSTCOND (A, B : Boolean) is begin GX := GX + 1; end; - + procedure As_DEBUG_ASSERT (A, B : Boolean) is pragma Debug_Policy (Check); begin diff --git a/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.ads b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.ads index 9200d7b86..8a8457e90 100644 --- a/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.ads +++ b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/expr.ads @@ -1,8 +1,8 @@ package Expr is - + GX : Integer := 0; pragma Volatile (GX); - + GB : Boolean; pragma Volatile (GB); @@ -12,20 +12,20 @@ package Expr is procedure As_AGGREGATE (A, B : Boolean); procedure As_DECLINIT (A, B : Boolean); procedure As_DISCINIT (A, B : Boolean); - + function As_RETURN (A, B : Boolean) return Boolean; - + procedure As_BODYPRECOND (A, B : Boolean); procedure As_BODYPOSTCOND (A, B : Boolean); - + pragma Check_Policy (Precondition, On); pragma Check_Policy (Postcondition, On); - - procedure As_SPECPRECOND (A, B : Boolean); + + procedure As_SPECPRECOND (A, B : Boolean); pragma Precondition (A and then B); -- # freestanding-expr - + procedure As_SPECPOSTCOND (A, B : Boolean); pragma Postcondition (A and then B); -- # freestanding-expr - + procedure As_DEBUG_ASSERT (A, B : Boolean); end; diff --git a/testsuite/tests/Ada/decision/MA07-028-expr-context/src/test_t.adb b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/test_t.adb index b9b9168aa..98b2d3277 100644 --- a/testsuite/tests/Ada/decision/MA07-028-expr-context/src/test_t.adb +++ b/testsuite/tests/Ada/decision/MA07-028-expr-context/src/test_t.adb @@ -8,15 +8,15 @@ begin Expr.As_AGGREGATE (A => True, B => True); Expr.As_DECLINIT (A => True, B => True); Expr.As_DISCINIT (A => True, B => True); - + Expr.GB := Expr.As_RETURN (A => True, B => True); - + Expr.As_BODYPRECOND (A => True, B => True); - Expr.As_BODYPOSTCOND (A => True, B => True); + Expr.As_BODYPOSTCOND (A => True, B => True); Expr.As_SPECPRECOND (A => True, B => True); - Expr.As_SPECPOSTCOND (A => True, B => True); - - Expr.As_DEBUG_ASSERT (A => True, B => True); + Expr.As_SPECPOSTCOND (A => True, B => True); + + Expr.As_DEBUG_ASSERT (A => True, B => True); end; --# expr.adb diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_ft.adb b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_ft.adb index b310051fd..d7ae1f640 100644 --- a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_ft.adb +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_ft.adb @@ -11,4 +11,3 @@ end; --# values.adb -- /pre/ l! ## dF- -- /set/ l+ ## 0 - diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tf.adb b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tf.adb index 576f1f6cd..263d8dfce 100644 --- a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tf.adb +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tf.adb @@ -9,4 +9,3 @@ end; --# values.adb -- /pre/ l! ## dF- -- /set/ l+ ## 0 - diff --git a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tt.adb b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tt.adb index 5f922e78b..1f1c7d1bb 100644 --- a/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tt.adb +++ b/testsuite/tests/Ada/mcdc/K118_027-precond_not/src/test_values_tt.adb @@ -9,4 +9,3 @@ end; --# values.adb -- /pre/ l! ## dF- -- /set/ l+ ## 0 - diff --git a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.adb b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.adb index 6f32b6015..ce6095b15 100644 --- a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.adb +++ b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.adb @@ -24,5 +24,3 @@ package body Actuators is end; end; - - diff --git a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.ads b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.ads index 7969bb92c..bf3eb3449 100644 --- a/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.ads +++ b/testsuite/tests/Ada/mcdc/K620-028_fold-inline/src/actuators.ads @@ -17,4 +17,3 @@ package Actuators is procedure Fast_Increment (A : in out Actuator; Value : Integer); end; - diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.adb b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.adb index f05ae0904..8f088c971 100644 --- a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.adb +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/expr.adb @@ -1,21 +1,20 @@ pragma Short_Circuit_And_Or; package body Expr is - + function Bool_And (A, B : Boolean) return Boolean is begin return A and B; -- # lone-and end; - + function Bool_Or (A, B : Boolean) return Boolean is begin return A or B; -- # lone-or end; - + function Bool_And_Or (A, B, C : Boolean) return Boolean is begin return (A and B) or C; -- # and-or end; - -end; +end; diff --git a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/test_a.adb b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/test_a.adb index 8a57201c9..36caee17f 100644 --- a/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/test_a.adb +++ b/testsuite/tests/Ada/mcdc/L803-037-short-circuit-and-or/src/test_a.adb @@ -4,14 +4,14 @@ with Expr, Assert; use Expr; -- influence of A only. Expect condition independance not demonstrated -- diagnostics on other conditions. -procedure Test_A is +procedure Test_A is begin Assert (Bool_And (True, True) = True); Assert (Bool_and (False, True) = False); - + Assert (Bool_Or (False, False) = False); Assert (Bool_or (True, False) = True); - + Assert (Bool_And_Or (False, True, False) = False); Assert (Bool_And_Or (True, True, False) = True); end; @@ -20,4 +20,3 @@ end; -- /lone-and/ l! ## c!:"B" -- /lone-or/ l! ## c!:"B" -- /and-or/ l! ## c!:"B", c!:"C" - diff --git a/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.adb b/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.adb index a46d275c0..307833ddb 100644 --- a/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.adb +++ b/testsuite/tests/Ada/mcdc/OrElse-O1/src/orelse.adb @@ -12,4 +12,3 @@ package body Orelse is return Value; -- # returnValue end; end; - diff --git a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.adb b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.adb index 06af42dc8..6ab874a10 100644 --- a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.adb +++ b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.adb @@ -11,4 +11,3 @@ package body Flips is end; end; - diff --git a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.ads b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.ads index 1e61128d6..35c7efbbb 100644 --- a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.ads +++ b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/flips.ads @@ -2,4 +2,3 @@ package Flips is procedure Flip (X : in out integer); procedure Flip (B : in out Boolean); end; - diff --git a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/test_flips.adb b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/test_flips.adb index 93d91168d..221db5c52 100644 --- a/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/test_flips.adb +++ b/testsuite/tests/Ada/stmt/J311_011-lone_return-O1/src/test_flips.adb @@ -6,7 +6,7 @@ procedure Test_Flips is begin Flip (B); Assert (B = False); - + Flip (X); Assert (X = -5); end; diff --git a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/test_ce.adb b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/test_ce.adb index 26764ac73..feddddde9 100644 --- a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/test_ce.adb +++ b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/src/test_ce.adb @@ -10,5 +10,3 @@ end; -- /div/ l- ## s- -- /retval/ l- ## s- -- /handle/ l+ ## 0 - - diff --git a/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.adb b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.adb index bec6a172b..0b51e6c68 100644 --- a/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.adb +++ b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.adb @@ -25,5 +25,3 @@ package body Actuators is end; end; - - diff --git a/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.ads b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.ads index 7969bb92c..bf3eb3449 100644 --- a/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.ads +++ b/testsuite/tests/Ada/stmt/K620-028_fold-inline/src/actuators.ads @@ -17,4 +17,3 @@ package Actuators is procedure Fast_Increment (A : in out Actuator; Value : Integer); end; - diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.ads b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.ads index adb96ebc2..d8f0f476f 100644 --- a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.ads +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/ops-values.ads @@ -1,4 +1,3 @@ package Ops.Values is - procedure Inc (X : in out Integer); + procedure Inc (X : in out Integer); end; - diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/src/test_inc.adb b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/src/test_inc.adb index a7f225e40..09d6fd202 100644 --- a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/src/test_inc.adb +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/src/test_inc.adb @@ -1,12 +1,12 @@ with Support, Ops.Values; use Support, Ops.Values; procedure Test_Inc is - + -- The library initialization procedure isn't called automatically in some -- configurations so we call it explicitly from here. Calling it multiple -- times is not a problem, so we're fine in configurations where it is -- called automatically before reaching here. - + procedure Mylib_Init; pragma Import (C, Mylib_Init, "mylibinit"); @@ -22,4 +22,3 @@ end; --# ../mylib/ops-values.adb -- /stmt/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/decision/ForOf/src/test_f.adb b/testsuite/tests/Ada2012/decision/ForOf/src/test_f.adb index 0bc3c0992..334e844b3 100644 --- a/testsuite/tests/Ada2012/decision/ForOf/src/test_f.adb +++ b/testsuite/tests/Ada2012/decision/ForOf/src/test_f.adb @@ -3,8 +3,8 @@ pragma Ada_2012; with Support, Values; use Support, Values; procedure Test_F is - - LA : Array_Type := + + LA : Array_Type := (1 => (X => 2, Count => 0)); begin Process (LA, Bump => False); @@ -16,5 +16,3 @@ end; -- /stmt/ l+ ## 0 -- /eval/ l! ## dT- -- /true/ l- ## s- - - diff --git a/testsuite/tests/Ada2012/decision/ForOf/src/test_t.adb b/testsuite/tests/Ada2012/decision/ForOf/src/test_t.adb index e3b3ab532..92233825c 100644 --- a/testsuite/tests/Ada2012/decision/ForOf/src/test_t.adb +++ b/testsuite/tests/Ada2012/decision/ForOf/src/test_t.adb @@ -3,8 +3,8 @@ pragma Ada_2012; with Support, Values; use Support, Values; procedure Test_T is - - LA : Array_Type := + + LA : Array_Type := (1 => (X => 2, Count => 0)); begin Process (LA, Bump => True); @@ -16,5 +16,3 @@ end; -- /stmt/ l+ ## 0 -- /eval/ l! ## dF- -- /true/ l+ ## 0 - - diff --git a/testsuite/tests/Ada2012/decision/ForOf/src/values.adb b/testsuite/tests/Ada2012/decision/ForOf/src/values.adb index 5aa0ab9f7..1bb006534 100644 --- a/testsuite/tests/Ada2012/decision/ForOf/src/values.adb +++ b/testsuite/tests/Ada2012/decision/ForOf/src/values.adb @@ -1,7 +1,7 @@ pragma Ada_2012; package body Values is - + procedure Process (A : in out Array_Type; Bump : Boolean) is begin for E of A loop -- # stmt @@ -11,5 +11,5 @@ package body Values is end if; end loop; end; - + end; diff --git a/testsuite/tests/Ada2012/decision/ForOf/src/values.ads b/testsuite/tests/Ada2012/decision/ForOf/src/values.ads index d29d8be75..b1015405b 100644 --- a/testsuite/tests/Ada2012/decision/ForOf/src/values.ads +++ b/testsuite/tests/Ada2012/decision/ForOf/src/values.ads @@ -1,12 +1,12 @@ package Values is - + type Object is tagged record X : Integer; Count : Natural; end record; - + type Array_Type is array (Natural range <>) of Object; - + procedure Process (A : in out Array_Type; Bump : Boolean); end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.adb index acbc53d0d..fe704d7ef 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.adb +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.adb @@ -1,5 +1,5 @@ package body Multiop is - + procedure Set (I : in out Int; V : Integer) is begin I.Value := V; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.ads index 9416b856e..d0cbb89c4 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.ads +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/MultiOp/src/multiop.ads @@ -4,16 +4,16 @@ pragma Assertion_Policy (Type_Invariant => Check); -- exercise a multi-operand invariant (complex expr) package Multiop is - + type Int (LB, UB : Integer) is private; - + procedure Set (I : in out Int; V : Integer); - + private - + type Int (LB, UB : Integer) is record Value : Integer := LB; end record with Type_Invariant => (Int.Value >= Int.LB and then Int.Value <= Int.UB); -- # eval - + end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.adb index 78514b176..6ac7ee000 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.adb +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.adb @@ -1,8 +1,8 @@ package body SingleOp is - + procedure Set (I : in out Int; V : Integer) is begin I.Value := V; end; - + end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.ads index 0b1d1e9d4..6cd1ff056 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.ads +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Invariants/SingleOp/src/singleop.ads @@ -4,16 +4,16 @@ pragma Assertion_Policy (Invariant => Check); -- exercise a mono-operand invariant (simple expr) package SingleOp is - + type Int (UB : Integer) is private; - + procedure Set (I : in out Int; V : Integer); private - + type Int (UB : Integer) is record Value : Integer := UB; end record with Invariant => (Int.Value <= Int.UB); -- # eval - + end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.adb index 06f75d599..9bdf01b38 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.adb +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.adb @@ -2,7 +2,7 @@ pragma Ada_2012; pragma Assertion_Policy (Post => Check); package body Values is - + procedure validate (A, B : in out Int) with Post => (A.Valid and then B.Valid) -- # eval is @@ -10,7 +10,7 @@ package body Values is A.Valid := A.Value > 0; -- # stmt B.Valid := B.Value > 0; -- # stmt end; - + procedure Filter (A, B : in out Int) is begin Validate (A, B); -- # stmt diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.ads index 49f289cfe..902b200e3 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.ads +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/MultiOpBody/src/values.ads @@ -1,11 +1,11 @@ package Values is - + type Int is record Value : Integer; Valid : Boolean; end record; - + procedure Filter (A, B : in out Int); - + end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.adb index fc50359a5..d4775815a 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.adb +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.adb @@ -1,7 +1,7 @@ package body Values is - + function Plus (A, B : Integer) return Integer is begin return A + B; -- # stmt - end; + end; end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.ads index 36afff401..bfcc9d6c0 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.ads +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Post/SingleOpSpec/src/values.ads @@ -2,8 +2,8 @@ pragma Ada_2012; pragma Assertion_Policy (Post => Check); package Values is - + function Plus (A, B : Integer) return Integer with Post => (Plus'Result > 0); -- # eval - + end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_a.adb index a888aadc8..ebb7f7adc 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_a.adb +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_a.adb @@ -4,7 +4,7 @@ with Silent_Last_Chance; procedure Test_A is X : Integer; begin - Assert + Assert (Plus ((Value => 5, Valid => True), (Value => 7, Valid => True)) = 12 ); diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_b.adb index 3ac6be1f5..3b85d4e41 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_b.adb +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_b.adb @@ -4,7 +4,7 @@ with Silent_Last_Chance; procedure Test_B is X : Integer; begin - Assert + Assert (Plus ((Value => 5, Valid => True), (Value => 7, Valid => True)) = 12 ); diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_t.adb index 2d6a6083d..0748bb64f 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_t.adb +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/test_t.adb @@ -2,7 +2,7 @@ with Support, Values; use Support, Values; procedure Test_T is begin - Assert + Assert (Plus ((Value => 5, Valid => True), (Value => 7, Valid => True)) = 12 ); diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.adb index 8c1d1625b..27873f776 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.adb +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.adb @@ -1,5 +1,5 @@ package body Values is - + function Plus (A, B : Int) return Integer is begin return A.Value + B.Value; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.ads index 31ba62fb8..888ec633e 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.ads +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/MultiOpSpec/src/values.ads @@ -2,13 +2,13 @@ pragma Ada_2012; pragma Assertion_Policy (Pre => Check); package Values is - + type Int is record Value : Integer; Valid : Boolean; end record; - + function Plus (A, B : Int) return Integer with Pre => (A.Valid and then B.Valid); -- # eval - + end; diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.adb b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.adb index 775eda248..7cc5e9f28 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.adb +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.adb @@ -2,14 +2,14 @@ pragma Ada_2012; pragma Assertion_Policy (Post => Check); package body Values is - + function CheckedPlus (A, B : Integer) return Integer with Post => (CheckedPlus'Result > 0) -- # eval is begin return A + B; -- # stmt end; - + function Plus (A, B : Integer) return Integer is begin return CheckedPlus (A, B); -- # stmt diff --git a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.ads b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.ads index de04efeb8..3cc9787ad 100644 --- a/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.ads +++ b/testsuite/tests/Ada2012/mcdc/Aspects/Pre/SingleOpBody/src/values.ads @@ -1,5 +1,5 @@ package Values is - + function Plus (A, B : Integer) return Integer; - + end; diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_a.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_a.adb index 45ae40daa..a7d57b19f 100644 --- a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_a.adb +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_a.adb @@ -3,15 +3,15 @@ pragma Ada_2012; with Support, Values; use Support, Values; procedure Test_A is - - LA : Array_Type := + + LA : Array_Type := (1 => (A => True, B => True, Expr => <>), 2 => (A => False, B => True, Expr => <>) ); - + begin Process (LA); - for E of LA loop + for E of LA loop Assert (E.Expr = (E.A and then E.B)); end loop; end; @@ -19,4 +19,3 @@ end; --# values.adb -- /stmt/ l+ ## 0 -- /eval/ l! ## c!:"E.B" - diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_ab.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_ab.adb index 14141e6f1..a5732b005 100644 --- a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_ab.adb +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_ab.adb @@ -3,16 +3,16 @@ pragma Ada_2012; with Support, Values; use Support, Values; procedure Test_AB is - - LA : Array_Type := + + LA : Array_Type := (1 => (A => True, B => True, Expr => <>), 2 => (A => True, B => False, Expr => <>), 3 => (A => False, B => True, Expr => <>) ); - + begin Process (LA); - for E of LA loop + for E of LA loop Assert (E.Expr = (E.A and then E.B)); end loop; end; @@ -20,4 +20,3 @@ end; --# values.adb -- /stmt/ l+ ## 0 -- /eval/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_b.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_b.adb index 6e2098710..56fa7924a 100644 --- a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_b.adb +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_b.adb @@ -3,15 +3,15 @@ pragma Ada_2012; with Support, Values; use Support, Values; procedure Test_B is - - LA : Array_Type := + + LA : Array_Type := (1 => (A => True, B => True, Expr => <>), 2 => (A => True, B => False, Expr => <>) ); - + begin Process (LA); - for E of LA loop + for E of LA loop Assert (E.Expr = (E.A and then E.B)); end loop; end; @@ -19,4 +19,3 @@ end; --# values.adb -- /stmt/ l+ ## 0 -- /eval/ l! ## c!:"E.A" - diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_f.adb index f6e45368c..201945e4f 100644 --- a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_f.adb +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_f.adb @@ -3,12 +3,12 @@ pragma Ada_2012; with Support, Values; use Support, Values; procedure Test_F is - - LA : Array_Type := + + LA : Array_Type := (1 => (A => True, B => False, Expr => <>)); begin Process (LA); - for E of LA loop + for E of LA loop Assert (E.Expr = (E.A and then E.B)); end loop; end; @@ -16,4 +16,3 @@ end; --# values.adb -- /stmt/ l+ ## 0 -- /eval/ l! ## eT- - diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_t.adb index 1f4bb86e3..e5becda2e 100644 --- a/testsuite/tests/Ada2012/mcdc/ForOf/src/test_t.adb +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/test_t.adb @@ -3,12 +3,12 @@ pragma Ada_2012; with Support, Values; use Support, Values; procedure Test_T is - - LA : Array_Type := + + LA : Array_Type := (1 => (A => True, B => True, Expr => <>)); begin Process (LA); - for E of LA loop + for E of LA loop Assert (E.Expr = (E.A and then E.B)); end loop; end; @@ -16,4 +16,3 @@ end; --# values.adb -- /stmt/ l+ ## 0 -- /eval/ l! ## eF- - diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/values.adb b/testsuite/tests/Ada2012/mcdc/ForOf/src/values.adb index a4324316d..3d403a9e2 100644 --- a/testsuite/tests/Ada2012/mcdc/ForOf/src/values.adb +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/values.adb @@ -1,12 +1,12 @@ pragma Ada_2012; package body Values is - + procedure Process (A : in out Array_Type) is begin for E of A loop -- # stmt E.Expr := E.A and then E.B; -- # eval end loop; end; - + end; diff --git a/testsuite/tests/Ada2012/mcdc/ForOf/src/values.ads b/testsuite/tests/Ada2012/mcdc/ForOf/src/values.ads index df0627603..16faf5901 100644 --- a/testsuite/tests/Ada2012/mcdc/ForOf/src/values.ads +++ b/testsuite/tests/Ada2012/mcdc/ForOf/src/values.ads @@ -1,11 +1,11 @@ package Values is - + type Object is tagged record A, B, Expr : Boolean; end record; - + type Array_Type is array (Natural range <>) of Object; - + procedure Process (A : in out Array_Type); end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/expr.ads index dfae67258..50fd3d7ef 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/expr.ads +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/expr.ads @@ -2,11 +2,11 @@ pragma Ada_2012; package Expr is -- if-expressions as outer expression operands in expression context. - + -- one outer and-then expr-decision with two operands: "if a" + "if b" -- plus two inner decisions: "A" and "B" controlling the if values. - + function Filter (A, Valat, Valaf, B, Valbt, Valbf : Boolean) return Boolean is ((if A then Valat else Valaf) and then (if B then Valbt else Valbf)); -- # eval - + end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_opa.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_opa.adb index 4b77c8c5b..e1e07ea97 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_opa.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_opa.adb @@ -5,10 +5,10 @@ begin -- A op1 B op2 Outer -- F T F T T -- T F F T F - + Assert (Filter (A => False, Valat => True, Valaf => True, B => False, Valbt => True, Valbf => True) = True); - + Assert (Filter (A => True, Valat => False, Valaf => False, B => False, Valbt => True, Valbf => True) = False); end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_t.adb index decef0956..b53a2bc2e 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_t.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_a_t.adb @@ -5,10 +5,10 @@ begin -- A op1 B op2 Outer -- F T T T T -- T T T T T - + Assert (Filter (A => False, Valat => True, Valaf => True, B => True, Valbt => True, Valbf => True) = True); - + Assert (Filter (A => True, Valat => True, Valaf => True, B => True, Valbt => True, Valbf => True) = True); end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_ab_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_ab_t.adb index 4980eed7f..47c1d4ab3 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_ab_t.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_ab_t.adb @@ -5,10 +5,10 @@ begin -- A op1 B op2 Outer -- F T T T T -- T T F T T - + Assert (Filter (A => False, Valat => True, Valaf => True, B => True, Valbt => True, Valbf => True) = True); - + Assert (Filter (A => True, Valat => True, Valaf => True, B => False, Valbt => True, Valbf => True) = True); end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_b_opa.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_b_opa.adb index 142a027d4..7c6e9e5b7 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_b_opa.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_b_opa.adb @@ -5,10 +5,10 @@ begin -- A op1 B op2 Outer -- F T F T T -- F T T F F - + Assert (Filter (A => False, Valat => True, Valaf => True, B => False, Valbt => True, Valbf => True) = True); - + Assert (Filter (A => False, Valat => False, Valaf => True, B => True, Valbt => False, Valbf => True) = False); end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opa.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opa.adb index 166772520..f236569a8 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opa.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opa.adb @@ -5,10 +5,10 @@ begin -- A op1 B op2 Outer -- F T F T T -- F F F T F - + Assert (Filter (A => False, Valat => True, Valaf => True, B => False, Valbt => True, Valbf => True) = True); - + Assert (Filter (A => False, Valat => True, Valaf => False, B => False, Valbt => True, Valbf => True) = False); end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb.adb index 2e8b522d6..f446ad79f 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb.adb @@ -5,7 +5,7 @@ begin -- A op1 B op2 Outer -- F T F T T -- F T F F F - + Assert (Filter (A => False, Valat => True, Valaf => True, B => False, Valbt => True, Valbf => True) = True); Assert (Filter (A => False, Valat => True, Valaf => True, diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb0.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb0.adb index 3ba378b83..ff0d7d7e2 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb0.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opb0.adb @@ -4,7 +4,7 @@ procedure Test_Opb0 is begin -- A op1 B op2 Outer -- F F X X F - + Assert (Filter (A => False, Valat => False, Valaf => False, B => False, Valbt => True, Valbf => True) = False); end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opfull.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opfull.adb index a52c20aae..08c15c9ea 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opfull.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/AndOp/src/test_opfull.adb @@ -6,14 +6,14 @@ begin -- F T F T T -- F F F T F -- F T F F F - + Assert (Filter (A => False, Valat => True, Valaf => True, B => False, Valbt => True, Valbf => True) = True); - + Assert (Filter (A => False, Valat => True, Valaf => False, B => False, Valbt => True, Valbf => True) = False); - - Assert (Filter (A => False, Valat => True, Valaf => True, + + Assert (Filter (A => False, Valat => True, Valaf => True, B => False, Valbt => True, Valbf => False) = False); end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/expr.ads index 64576aa1a..2f8001d55 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/expr.ads +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlCval/src/expr.ads @@ -2,11 +2,11 @@ pragma Ada_2012; package Expr is type Opkind is (Op_And, Op_Or); - + -- Simple controlling expression, complex value expressions, -- as expression function - - function Eval (Op : Opkind; A, B : Boolean) return Boolean is + + function Eval (Op : Opkind; A, B : Boolean) return Boolean is (if (Op = Op_And) -- # if-opand then (A and then B) -- # then-and else (A or else B) -- # else-or diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/expr.ads index 9b40bdd6f..5427f0a1b 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/expr.ads +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/ExprSctlSval/src/expr.ads @@ -1,15 +1,14 @@ pragma Ada_2012; package Expr is - + -- Simple controlling expression, simple value expressions, -- as expression function. - function Filter (A, B : Integer) return Boolean is + function Filter (A, B : Integer) return Boolean is (if (A > 0) -- # ctl-apos then B > A -- # then-bgt else B < A -- # else-agt ); - + end; - diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/plus.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/plus.adb index 73f22952c..a01d95c79 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/plus.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/plus.adb @@ -7,6 +7,3 @@ is begin return A + B; -- # stmt end; - - - diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_0.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_0.adb index a62f4eb7f..eb28bd557 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_0.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_0.adb @@ -8,4 +8,3 @@ end; --# plus.adb -- /eval/ l. ## 0 -- /stmt/ l- ## s- - diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_f.adb index 7a67115c6..6be12cd0a 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_f.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_f.adb @@ -8,4 +8,3 @@ end; --# plus.adb -- /eval/ l. ## 0 -- /stmt/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_t.adb index aa51bf828..c6303940a 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_t.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPost/src/test_t.adb @@ -8,4 +8,3 @@ end; --# plus.adb -- /eval/ l. ## 0 -- /stmt/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/plus.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/plus.adb index ce6ff9eca..19dee5902 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/plus.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/plus.adb @@ -7,6 +7,3 @@ is begin return A + B; -- # stmt end; - - - diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_0.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_0.adb index a62f4eb7f..eb28bd557 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_0.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_0.adb @@ -8,4 +8,3 @@ end; --# plus.adb -- /eval/ l. ## 0 -- /stmt/ l- ## s- - diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_f.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_f.adb index 7a67115c6..6be12cd0a 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_f.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_f.adb @@ -8,4 +8,3 @@ end; --# plus.adb -- /eval/ l. ## 0 -- /stmt/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_t.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_t.adb index aa51bf828..c6303940a 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_t.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/InDeadPre/src/test_t.adb @@ -8,4 +8,3 @@ end; --# plus.adb -- /eval/ l. ## 0 -- /stmt/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.adb index 68bb2d99c..a264ed7d6 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.adb @@ -3,7 +3,7 @@ package body Expr is function Eval (Op : Opkind; A, B : Boolean) return Boolean is begin -- Simple controlling expression, complex value expressions - + return (if (Op = Op_And) -- # if-opand then (A and then B) -- # then-and else (A or else B) -- # else-or diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.ads index 4c0aadff2..8cf3a00d4 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.ads +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlCval/src/expr.ads @@ -1,5 +1,5 @@ package Expr is type Opkind is (Op_And, Op_Or); - + function Eval (Op : Opkind; A, B : Boolean) return Boolean; end; diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.adb b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.adb index 9ab2ab414..a9860e784 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.adb +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.adb @@ -1,7 +1,7 @@ pragma Ada_2012; package body Expr is - + function Filter (A, B : Integer) return Boolean is begin return (if (A > 0) -- # ctl-apos diff --git a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.ads b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.ads index d08bad391..3fd35bd0c 100644 --- a/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.ads +++ b/testsuite/tests/Ada2012/mcdc/IfExpr/RetSctlSval/src/expr.ads @@ -1,11 +1,10 @@ pragma Ada_2012; package Expr is - + -- Simple controlling expression, simple value expressions, -- as expression function. function Filter (A, B : Integer) return Boolean; - + end; - diff --git a/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_f.adb b/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_f.adb index bea576cdf..75b3b8e23 100644 --- a/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_f.adb +++ b/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_f.adb @@ -13,4 +13,3 @@ end; -- /stmt/ l+ ## 0 -- /test/ l! ## dF- -- /eval/ l! ## eT- - diff --git a/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_t.adb b/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_t.adb index dff7c684a..4e26f3ba1 100644 --- a/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_t.adb +++ b/testsuite/tests/Ada2012/mcdc/InOut/src/test_eval_t.adb @@ -13,4 +13,3 @@ end; -- /stmt/ l+ ## 0 -- /test/ l! ## dF- -- /eval/ l! ## eF- - diff --git a/testsuite/tests/Ada2012/mcdc/InOut/src/test_neval.adb b/testsuite/tests/Ada2012/mcdc/InOut/src/test_neval.adb index cc53e6620..89ca2bcc1 100644 --- a/testsuite/tests/Ada2012/mcdc/InOut/src/test_neval.adb +++ b/testsuite/tests/Ada2012/mcdc/InOut/src/test_neval.adb @@ -13,4 +13,3 @@ end; -- /stmt/ l+ ## 0 -- /test/ l! ## dT- -- /eval/ l- ## s- - diff --git a/testsuite/tests/Ada2012/mcdc/Membership/src/values.ads b/testsuite/tests/Ada2012/mcdc/Membership/src/values.ads index 5d8ab42e5..ef9b24b60 100644 --- a/testsuite/tests/Ada2012/mcdc/Membership/src/values.ads +++ b/testsuite/tests/Ada2012/mcdc/Membership/src/values.ads @@ -1,9 +1,9 @@ pragma Ada_2012; package Values is - + type My_Int is new Integer range 1 .. 8; - + function Even_Odd (X, Y : My_Int) return Boolean is (X in 2 | 4 | 6 | 8 and then Y in 1 | 3 | 5 | 7); -- # eval end; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.adb b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.adb index c6c3d11ea..45421d8ce 100644 --- a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.adb +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.adb @@ -1,58 +1,58 @@ with Support; use Support; package body FUAND is - + function To_String (C : Coord) return String is begin return (1 .. 1 => Character'Val (48 - C)); end; - + function Line (O : Object) return String is begin return To_String (O.X); end; - + function Col (O : Object) return String is begin return To_String (O.Y); end; - + -- - + type Red_Circle is new Object with null record; - + function Shape (O : Red_Circle) return String; function Color (O : Red_Circle) return String; - + function Shape (O : Red_Circle) return String is begin return "circle"; end; - + function Color (O : Red_Circle) return String is begin return "red"; end; - + -- - + type Blue_Square is new Object with null record; - + function Shape (O : Blue_Square) return String; function Color (O : Blue_Square) return String; - + function Shape (O : Blue_Square) return String is begin return "square"; end; - + function Color (O : Blue_Square) return String is begin return "blue"; end; - + -- - + procedure TEST_A is A : Red_Circle := (X => 1, Y => 2); B : Blue_Square := (X => 1, Y => 2); @@ -60,7 +60,7 @@ package body FUAND is Assert (Fight (A, B)); -- T T Assert (not Fight (A, A)); -- F T end; - + procedure TEST_B is A : Red_Circle := (X => 1, Y => 2); B : Blue_Square := (X => 1, Y => 2); @@ -69,12 +69,12 @@ package body FUAND is Assert (Fight (A, B)); -- T T Assert (not Fight (A, C)); -- T F end; - + procedure TEST_T is A : Red_Circle := (X => 1, Y => 2); B : Blue_Square := (X => 1, Y => 2); begin Assert (Fight (A, B)); end; - + end; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.ads b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.ads index e22375666..9ff0bee3f 100644 --- a/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.ads +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/AndStr/src/fuand.ads @@ -1,23 +1,23 @@ pragma Ada_2012; package FUAND is - + type Coord is range 0 .. 9; type Object is abstract tagged record X, Y : Coord; end record; - + function Shape (O : Object) return String is abstract; function Color (O : Object) return String is abstract; - + function Line (O : Object) return String; function Col (O : Object) return String; - - function Fight (A, B : Object'Class) return Boolean is + + function Fight (A, B : Object'Class) return Boolean is ((Color(A) & "-" & Shape(A)) /= (Color(B) & "-" & Shape(B)) and then (Line(A) & Col(A)) = (Line(B) & Col(B))); -- # eval - + procedure Test_A; procedure Test_B; procedure Test_T; - + end; diff --git a/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/expr.ads b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/expr.ads index f8a15451f..a1325e258 100644 --- a/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/expr.ads +++ b/testsuite/tests/Ada2012/mcdc/Xfunctions/pAndpOr/src/expr.ads @@ -1,6 +1,6 @@ pragma Ada_2012; -package Expr is - function F (A, B, C : Boolean) return Boolean is +package Expr is + function F (A, B, C : Boolean) return Boolean is ((A and then B) or else C); -- # eval end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_0.adb b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_0.adb index 43f2ceed9..a6b3329ba 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_0.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_0.adb @@ -12,4 +12,3 @@ end; --# values-global.adb -- /stmt/ l- ## s- -- /loop_op/ l- ## s- - diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_arg.adb index addf20221..13810fd28 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_arg.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_arg.adb @@ -2,7 +2,7 @@ pragma Ada_2012; with Values.ARG, Support; use Values, Support; -procedure Test_Values_ARG is +procedure Test_Values_ARG is LA : Array_Type := (others => (X => 5)); begin ARG.Do_Loop_Over (LA); @@ -14,4 +14,3 @@ end; --# values-arg.adb -- /stmt/ l+ ## 0 -- /loop_op/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_gsa.adb b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_gsa.adb index af55a6cbf..77d90022f 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_gsa.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/test_values_gsa.adb @@ -3,7 +3,7 @@ with Values.Global, Support; use Values, Support; procedure Test_Values_GSA is begin Global.GSA := (others => (X => 4)); - + Global.Do_Loop; Assert (Global.GSA (1).X = 5); Assert (Global.GSA (3).X = 5); @@ -12,4 +12,3 @@ end; --# values-global.adb -- /stmt/ l+ ## 0 -- /loop_op/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values-global.ads b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values-global.ads index b0a468686..228198706 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values-global.ads +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values-global.ads @@ -1,6 +1,6 @@ package Values.Global is - + GSA : Array_Type; - + procedure Do_Loop; end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.adb b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.adb index ee25be553..84bf26181 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.adb @@ -1,8 +1,8 @@ package body Values is - + procedure Touch (E : in out Object) is begin E.X := E.X + 1; end; - + end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.ads b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.ads index d0d2c6781..e1c95fc5c 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.ads +++ b/testsuite/tests/Ada2012/stmt/ForOf/ObjectArray/src/values.ads @@ -1,12 +1,12 @@ package Values is - + type Object is tagged record X : Integer; end record; - + type Array_Type is array (1 .. 8) of Object; - + procedure Touch (E : in out Object); - + end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_0.adb b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_0.adb index 43f2ceed9..a6b3329ba 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_0.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_0.adb @@ -12,4 +12,3 @@ end; --# values-global.adb -- /stmt/ l- ## s- -- /loop_op/ l- ## s- - diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_arg.adb index 77f439ec4..62b5cd71b 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_arg.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_arg.adb @@ -2,7 +2,7 @@ pragma Ada_2012; with Values.ARG, Support; use Values, Support; -procedure Test_Values_ARG is +procedure Test_Values_ARG is LA : Array_Type := (others => 1); begin ARG.Do_Loop_Over (LA); @@ -14,4 +14,3 @@ end; --# values-arg.adb -- /stmt/ l+ ## 0 -- /loop_op/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_gsa.adb b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_gsa.adb index 3acbb6ed4..4d63cb5da 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_gsa.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/test_values_gsa.adb @@ -11,4 +11,3 @@ end; --# values-global.adb -- /stmt/ l+ ## 0 -- /loop_op/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values-global.ads b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values-global.ads index 353d50994..097418586 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values-global.ads +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values-global.ads @@ -1,5 +1,5 @@ -package Values.Global is +package Values.Global is GSA : Array_Type; procedure Do_Loop; end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.ads b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.ads index febf6e08d..30c047deb 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.ads +++ b/testsuite/tests/Ada2012/stmt/ForOf/PackedArray/src/values.ads @@ -2,9 +2,9 @@ package Values is type Num is mod 2**8; for Num'Size use 8; - + type Array_Type is array (1 .. 4) of Num; pragma Pack (Array_Type); - + procedure Touch (E : in out Num); end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_0.adb b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_0.adb index 43f2ceed9..a6b3329ba 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_0.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_0.adb @@ -12,4 +12,3 @@ end; --# values-global.adb -- /stmt/ l- ## s- -- /loop_op/ l- ## s- - diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_arg.adb index 1f8b82990..1052ce376 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_arg.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_arg.adb @@ -2,7 +2,7 @@ pragma Ada_2012; with Values.ARG, Support; use Values, Support; -procedure Test_Values_ARG is +procedure Test_Values_ARG is LA : Array_Type := (others => 5); begin ARG.Do_Loop_Over (LA); @@ -14,4 +14,3 @@ end; --# values-arg.adb -- /stmt/ l+ ## 0 -- /loop_op/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_gsa.adb b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_gsa.adb index 091b624a7..b21b00a41 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_gsa.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/test_values_gsa.adb @@ -3,7 +3,7 @@ with Values.Global, Support; use Values, Support; procedure Test_Values_GSA is begin Global.GSA := (1, 2, 3, 4, 5, 6, 7, 8); - + Global.Do_Loop; Assert (Global.GSA (3) = 6); Assert (Global.GSA (6) = 12); @@ -12,4 +12,3 @@ end; --# values-global.adb -- /stmt/ l+ ## 0 -- /loop_op/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values-global.ads b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values-global.ads index 353d50994..097418586 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values-global.ads +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values-global.ads @@ -1,5 +1,5 @@ -package Values.Global is +package Values.Global is GSA : Array_Type; procedure Do_Loop; end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.ads b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.ads index 85e2e87bb..dec7883bf 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.ads +++ b/testsuite/tests/Ada2012/stmt/ForOf/StraightIntArray/src/values.ads @@ -1,5 +1,5 @@ package Values is type Array_Type is array (1 .. 8) of Integer; - + procedure Touch (E : in out Integer); end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_0.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_0.adb index 43f2ceed9..a6b3329ba 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_0.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_0.adb @@ -12,4 +12,3 @@ end; --# values-global.adb -- /stmt/ l- ## s- -- /loop_op/ l- ## s- - diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_arg.adb index 997457438..c9b734197 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_arg.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_arg.adb @@ -2,7 +2,7 @@ pragma Ada_2012; with Values.ARG, Support; use Values, Support; -procedure Test_Values_ARG is +procedure Test_Values_ARG is LA : Array_Type := (1 .. 12 => 5); pragma Volatile (LA); begin @@ -15,4 +15,3 @@ end; --# values-arg.adb -- /stmt/ l+ ## 0 -- /loop_op/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_empty.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_empty.adb index d58b5795f..5321d43ad 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_empty.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_empty.adb @@ -5,8 +5,7 @@ procedure Test_Values_EMPTY is begin Arg.Do_Loop_Over (LA); end; - + --# values-arg.adb -- /stmt/ l+ ## 0 -- /loop_op/ l- ## s- - diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_gsa.adb b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_gsa.adb index b42fdaed2..e9f32129b 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_gsa.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/test_values_gsa.adb @@ -10,4 +10,3 @@ end; --# values-global.adb -- /stmt/ l+ ## 0 -- /loop_op/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values-global.ads b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values-global.ads index ae6110c86..eb2d3cf71 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values-global.ads +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values-global.ads @@ -1,5 +1,5 @@ -package Values.Global is +package Values.Global is GSA : Array_Type := (1 .. 4 => 1, 5 .. 8 => 2); procedure Do_Loop; end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.ads b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.ads index 51807d164..0a9672070 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.ads +++ b/testsuite/tests/Ada2012/stmt/ForOf/UncIntArray/src/values.ads @@ -1,5 +1,5 @@ -package Values is +package Values is type Array_Type is array (Natural range <>) of Integer; - + procedure Touch (E : in out Integer); end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.adb b/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.adb index cec6ab8b5..570b6c6da 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.adb @@ -1,12 +1,12 @@ pragma Ada_2012; package body Values.ARG is - + procedure Do_Loop_Over (A : in out Array_Type) is begin for E of A loop -- # stmt Touch (E); -- # loop_op end loop; end; - + end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.ads b/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.ads index cfcd6361f..54924ee93 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.ads +++ b/testsuite/tests/Ada2012/stmt/ForOf/src/values-arg.ads @@ -1,4 +1,4 @@ -package Values.Arg is +package Values.Arg is procedure Do_Loop_Over (A : in out Array_Type); end; diff --git a/testsuite/tests/Ada2012/stmt/ForOf/src/values-global.adb b/testsuite/tests/Ada2012/stmt/ForOf/src/values-global.adb index 29903de08..e0c003e8d 100644 --- a/testsuite/tests/Ada2012/stmt/ForOf/src/values-global.adb +++ b/testsuite/tests/Ada2012/stmt/ForOf/src/values-global.adb @@ -1,12 +1,12 @@ pragma Ada_2012; package body Values.Global is - + procedure Do_Loop is begin for E of GSA loop -- # stmt Touch (E); -- # loop_op end loop; end; - + end; diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_f.adb b/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_f.adb index b7199613b..84e948c53 100644 --- a/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_f.adb +++ b/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_f.adb @@ -13,4 +13,3 @@ end; -- /stmt/ l+ ## 0 -- /test/ l+ ## 0 -- /eval/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_t.adb b/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_t.adb index fe62f78b1..9eb84a894 100644 --- a/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_t.adb +++ b/testsuite/tests/Ada2012/stmt/InOut/src/test_eval_t.adb @@ -13,4 +13,3 @@ end; -- /stmt/ l+ ## 0 -- /test/ l+ ## 0 -- /eval/ l+ ## 0 - diff --git a/testsuite/tests/Ada2012/stmt/InOut/src/test_neval.adb b/testsuite/tests/Ada2012/stmt/InOut/src/test_neval.adb index 976c7e158..085633770 100644 --- a/testsuite/tests/Ada2012/stmt/InOut/src/test_neval.adb +++ b/testsuite/tests/Ada2012/stmt/InOut/src/test_neval.adb @@ -13,4 +13,3 @@ end; -- /stmt/ l+ ## 0 -- /test/ l+ ## 0 -- /eval/ l- ## s- - diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.ads index 0bd03811d..58ad97f92 100644 --- a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.ads +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewBodyParam/src/pak.ads @@ -10,4 +10,3 @@ package Pak is private type PR is new R with null record; end Pak; - diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.ads index caf2dc177..ac550a515 100644 --- a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.ads +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtFullViewSpecParam/src/pak.ads @@ -11,4 +11,3 @@ private type PR is new R with null record; procedure PPR1 (X : access PR) is null; -- # npb end Pak; - diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.ads index adea23fac..f8a278a9c 100644 --- a/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.ads +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccPvtParam/src/pak.ads @@ -10,4 +10,3 @@ package Pak is private type PR is new R with null record; end Pak; - diff --git a/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.ads b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.ads index 3a305f818..7cfe43bf7 100644 --- a/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.ads +++ b/testsuite/tests/Ada2012/stmt/NullProc/AccTaggedParam/src/pak.ads @@ -5,4 +5,3 @@ package Pak is procedure PR2 (X : access R) is null; -- # npb procedure Call; end Pak; - diff --git a/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.opt b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.opt index 9b91bd331..b63692c38 100644 --- a/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.opt +++ b/testsuite/tests/C++/mcdc/AandB/In_DefaultValue/test.opt @@ -1 +1 @@ -all XFAIL MCDC instrumentation of default initializers not supported \ No newline at end of file +all XFAIL MCDC instrumentation of default initializers not supported diff --git a/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c b/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c index b72e8019e..8472ba606 100644 --- a/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c +++ b/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c @@ -18,4 +18,4 @@ main (void) /* GNATCOV_EXEMPT_OFF)*/ ? 0 : 1; -} \ No newline at end of file +} diff --git a/testsuite/tests/C/mcdc/Exemptions/extra.opt b/testsuite/tests/C/mcdc/Exemptions/extra.opt index 279c887dd..25d72a22d 100644 --- a/testsuite/tests/C/mcdc/Exemptions/extra.opt +++ b/testsuite/tests/C/mcdc/Exemptions/extra.opt @@ -1 +1 @@ -bin-traces DEAD exemptions not supported in bin traces for C \ No newline at end of file +bin-traces DEAD exemptions not supported in bin traces for C diff --git a/testsuite/tests/C/mcdc/misc/src/misc.ads b/testsuite/tests/C/mcdc/misc/src/misc.ads index 22b07e6da..566eefc05 100644 --- a/testsuite/tests/C/mcdc/misc/src/misc.ads +++ b/testsuite/tests/C/mcdc/misc/src/misc.ads @@ -1,5 +1,5 @@ package Misc is - + function Aligned (X, Y, Factor : Integer) return Boolean; pragma Import (C, Aligned, "aligned"); end; diff --git a/testsuite/tests/C/mcdc/misc/src/test_aligned_x.adb b/testsuite/tests/C/mcdc/misc/src/test_aligned_x.adb index 0b8bc90cc..ce655e415 100644 --- a/testsuite/tests/C/mcdc/misc/src/test_aligned_x.adb +++ b/testsuite/tests/C/mcdc/misc/src/test_aligned_x.adb @@ -8,4 +8,3 @@ end; --# aligned.c -- /eval/ l! ## c!:"!(y" - diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/src/ops.adb index a95f55b77..6eb5a9f71 100644 --- a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Lib/src/ops.adb @@ -53,4 +53,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/src/ops.adb index 305057c62..049a9f393 100644 --- a/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectDelay/Local/src/ops.adb @@ -53,4 +53,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/src/ops.adb index 71d6f02b2..e4f98a001 100644 --- a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Lib/src/ops.adb @@ -38,4 +38,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/src/ops.adb index 8d0912570..388320369 100644 --- a/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectElse/Local/src/ops.adb @@ -37,4 +37,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/src/ops.adb index a28dd017e..5efebbe67 100644 --- a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Lib/src/ops.adb @@ -32,4 +32,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/src/ops.adb index 815d9eb5d..2afa64c07 100644 --- a/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectOr/Local/src/ops.adb @@ -32,4 +32,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/src/ops.adb index 7dc68bda4..3ca416bfc 100644 --- a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Lib/src/ops.adb @@ -36,4 +36,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/src/ops.adb index b0fd8df7e..98ba96163 100644 --- a/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectTerminate/Local/src/ops.adb @@ -36,4 +36,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/src/ops.adb index 683fbfab3..6013c8d85 100644 --- a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/src/ops.adb @@ -42,4 +42,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.opt index 006a31f27..0955f0fce 100644 --- a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.opt +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Lib/test.opt @@ -1,2 +1,2 @@ -RTS_FULL +RTS_FULL ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/src/ops.adb index 5b12ef802..1bf8daf90 100644 --- a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/src/ops.adb @@ -42,4 +42,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.opt b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.opt index 006a31f27..0955f0fce 100644 --- a/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.opt +++ b/testsuite/tests/FullRuntime/stmt/Entries/SelectWhen/Local/test.opt @@ -1,2 +1,2 @@ -RTS_FULL +RTS_FULL ALL DEAD diff --git a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/src/ops.adb index f822b4f59..4b8a793f0 100644 --- a/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/Entries/StraightAccept/Lib/src/ops.adb @@ -27,4 +27,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/src/ops.adb index 8035786c9..d2479cf52 100644 --- a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Entries/Local/src/ops.adb @@ -55,4 +55,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/src/ops.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/src/ops.adb index d8b9020ff..dadb5df12 100644 --- a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Lib/src/ops.adb @@ -34,4 +34,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/src/ops.adb b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/src/ops.adb index 41aecf5ab..f6136a21b 100644 --- a/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/src/ops.adb +++ b/testsuite/tests/FullRuntime/stmt/ProtectedObjects/Operations/Local/src/ops.adb @@ -35,4 +35,3 @@ package body Ops is end; end; - diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.ads b/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.ads index ca588cbfc..1047d0237 100644 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.ads +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.ads @@ -10,6 +10,6 @@ package Sensors is type Temp_Unit is (C, F); procedure Test (Value : Float; Unit : Temp_Unit); - + N_Tests_C, N_Tests_F : Natural := 0; end Sensors; diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cbfn.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cbfn.adb index 157c2fa77..d2ee1721e 100644 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cbfn.adb +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cbfn.adb @@ -7,19 +7,19 @@ begin -- C in range (!low !high => Out-False) Sensors.Test (37.0, C); - + -- C out of range (!low, high => Out-True) Sensors.Test (200.0, C); - + Assert (Sensors.N_Tests_C = 2); Assert (Sensors.N_Tests_F = 0); - + Assert (RC.In_Range_Count = 1); Assert (RC.Out_Of_Range_Count = 1); Assert (RF.In_Range_Count = 0); Assert (RF.Out_Of_Range_Count = 0); - + end Test_CBFN; --# sensors.adb diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifn.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifn.adb index a6be1950f..610fa1cdc 100644 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifn.adb +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifn.adb @@ -8,7 +8,7 @@ begin Assert (Sensors.N_Tests_C = 1); Assert (Sensors.N_Tests_F = 0); - + Assert (RC.In_Range_Count = 1); Assert (RC.Out_Of_Range_Count = 0); Assert (RF.In_Range_Count = 0); @@ -39,11 +39,9 @@ end Test_CIFN; -- %cov: -S instance -- =/test-out/ l! ## s-@(i:RF), dT-@(i:RC) -- =/in-range/ l! ## s-@(i:RF) --- =/out-range/ l- ## s-@(i:RF), s-@(i:RC) +-- =/out-range/ l- ## s-@(i:RF), s-@(i:RC) -- %cov: -S routine %cargs: !-gnatn -- =/test-out/ l! ## s-@(sensors__rf__test), dT-@(sensors__rc__test) -- =/in-range/ l! ## s-@(sensors__rf__test) -- =/out-range/ l- ## s-@(sensors__rf__test), s-@(sensors__rc__test) - - diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifo.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifo.adb index 079eef813..787f4cbdf 100644 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifo.adb +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifo.adb @@ -12,12 +12,12 @@ begin Assert (Sensors.N_Tests_C = 1); Assert (Sensors.N_Tests_F = 1); - + Assert (RC.In_Range_Count = 1); Assert (RC.Out_Of_Range_Count = 0); Assert (RF.In_Range_Count = 0); Assert (RF.Out_Of_Range_Count = 1); - + end Test_CIFO; --# sensors.adb diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfo.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfo.adb index 7ceaa83fd..c53fe94e0 100644 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfo.adb +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfo.adb @@ -36,5 +36,3 @@ end Test_CNFO; -- =/test-out/ l! ## s-@(sensors__rc__test), dF-@(sensors__rf__test) -- =/in-range/ l- ## s-@(sensors__rf__test), s-@(sensors__rc__test) -- =/out-range/ l! ## s-@(sensors__rc__test) - - diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/src/test_v5_reset.adb b/testsuite/tests/Generics/Mode_Variants_STMT/src/test_v5_reset.adb index 119a9f614..eaa198c01 100644 --- a/testsuite/tests/Generics/Mode_Variants_STMT/src/test_v5_reset.adb +++ b/testsuite/tests/Generics/Mode_Variants_STMT/src/test_v5_reset.adb @@ -27,4 +27,3 @@ end; -- instances of interest are --# v5.ads - diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/src/v5.ads b/testsuite/tests/Generics/Mode_Variants_STMT/src/v5.ads index 2b8368830..bfdb37907 100644 --- a/testsuite/tests/Generics/Mode_Variants_STMT/src/v5.ads +++ b/testsuite/tests/Generics/Mode_Variants_STMT/src/v5.ads @@ -1,3 +1,2 @@ with Vectors; package V5 is new Vectors (Size => 5); -- # i:V5 - diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.adb b/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.adb index b7bc017be..4570bc363 100644 --- a/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.adb +++ b/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.adb @@ -1,24 +1,24 @@ package body Vectors is - + function Do_Reset (I : Integer) return Integer is begin return 0; -- # do_reset end; - + function Do_Bump (I : Integer) return Integer is begin return I + 1; -- # do_bump end; - + type Operator is access function (X : Integer) return Integer; - + procedure Iterate_On (V : in out Vector; Op : Operator) is begin for I in V'Range loop -- # iterate V(I) := Op (V (I)); -- # iterate end loop; end; - + procedure Apply (Op : Opkind; V : in out Vector) is begin case Op is -- # apply_op @@ -26,7 +26,5 @@ package body Vectors is when Bump => Iterate_On (V, Do_Bump'Access); -- # apply_bump end case; end; - -end; - +end; diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.ads b/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.ads index e15dbdb5a..fc2f29262 100644 --- a/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.ads +++ b/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.ads @@ -1,10 +1,10 @@ generic Size : Natural; package Vectors is - + type Vector is array (1 .. Size) of Integer; - + type Opkind is (Reset, Bump); - + procedure Apply (Op : Opkind; V : in out Vector); end; diff --git a/testsuite/tests/HA16-013_cleanups/src/test_blobs.adb b/testsuite/tests/HA16-013_cleanups/src/test_blobs.adb index 69e06e514..ed582d1c8 100644 --- a/testsuite/tests/HA16-013_cleanups/src/test_blobs.adb +++ b/testsuite/tests/HA16-013_cleanups/src/test_blobs.adb @@ -8,14 +8,14 @@ begin exception when Program_Error => null; end; - + begin P2; - Assert (Vars.N_Post_Raise = 0); + Assert (Vars.N_Post_Raise = 0); exception when Program_Error => null; end; - + end; --# p1.adb p2.adb vars.adb diff --git a/testsuite/tests/HA16-013_cleanups/src/vars.adb b/testsuite/tests/HA16-013_cleanups/src/vars.adb index a6a0d5ff5..3256dc1f6 100644 --- a/testsuite/tests/HA16-013_cleanups/src/vars.adb +++ b/testsuite/tests/HA16-013_cleanups/src/vars.adb @@ -3,7 +3,7 @@ package body Vars is begin raise Program_Error; -- # call_raise end; - + procedure Post_Raise is begin N_Post_Raise := N_Post_Raise + 1; -- # post_raise diff --git a/testsuite/tests/HA16-013_cleanups/src/vars.ads b/testsuite/tests/HA16-013_cleanups/src/vars.ads index 4e5c13b64..3e41e958b 100644 --- a/testsuite/tests/HA16-013_cleanups/src/vars.ads +++ b/testsuite/tests/HA16-013_cleanups/src/vars.ads @@ -1,9 +1,9 @@ package Vars is - + N : Integer := 12; -- to be used for VLA sizing - + procedure Raise_PE; - + procedure Post_Raise; N_Post_Raise : Integer := 0; end; diff --git a/testsuite/tests/I505-018/src/services.adb b/testsuite/tests/I505-018/src/services.adb index bdec49021..0acdb2f69 100644 --- a/testsuite/tests/I505-018/src/services.adb +++ b/testsuite/tests/I505-018/src/services.adb @@ -12,5 +12,3 @@ package body Services is raise Program_Error; end; end; - - diff --git a/testsuite/tests/I505-018/src/services.ads b/testsuite/tests/I505-018/src/services.ads index c90c53757..0f80506e4 100644 --- a/testsuite/tests/I505-018/src/services.ads +++ b/testsuite/tests/I505-018/src/services.ads @@ -5,5 +5,3 @@ package Services is procedure To_Be_Called; procedure Not_To_Be_Called; end; - - diff --git a/testsuite/tests/I519-015/test.opt b/testsuite/tests/I519-015/test.opt index 9242d937c..15a456bdc 100644 --- a/testsuite/tests/I519-015/test.opt +++ b/testsuite/tests/I519-015/test.opt @@ -1,2 +1,2 @@ ppc-elf -ALL DEAD \ No newline at end of file +ALL DEAD diff --git a/testsuite/tests/I519-030/src/kops.adb b/testsuite/tests/I519-030/src/kops.adb index 550f382aa..fdc3374c2 100644 --- a/testsuite/tests/I519-030/src/kops.adb +++ b/testsuite/tests/I519-030/src/kops.adb @@ -5,4 +5,3 @@ package body Kops is X := X + K; end Inc; end; - diff --git a/testsuite/tests/I519-030/src/kops.ads b/testsuite/tests/I519-030/src/kops.ads index 589ab169d..b97d2afbe 100644 --- a/testsuite/tests/I519-030/src/kops.ads +++ b/testsuite/tests/I519-030/src/kops.ads @@ -5,4 +5,3 @@ package Kops is procedure Inc (X : in out Integer); pragma Inline (Inc); end; - diff --git a/testsuite/tests/I715-012/src/monitor.ads b/testsuite/tests/I715-012/src/monitor.ads index ae8097029..d387b410e 100644 --- a/testsuite/tests/I715-012/src/monitor.ads +++ b/testsuite/tests/I715-012/src/monitor.ads @@ -1,5 +1,5 @@ package Monitor is N_Ops : Integer := 0; - + procedure Touch; end; diff --git a/testsuite/tests/I717-018/src/explore.adb b/testsuite/tests/I717-018/src/explore.adb index 4a8179912..c8ecdbd78 100644 --- a/testsuite/tests/I717-018/src/explore.adb +++ b/testsuite/tests/I717-018/src/explore.adb @@ -70,7 +70,7 @@ begin SR_Situation_Link); end; - -- Then run just one cycle + -- Then run just one cycle Run (S); Run (R); diff --git a/testsuite/tests/I717-018/src/stations.adb b/testsuite/tests/I717-018/src/stations.adb index 321b7803e..4b1ac9aa2 100644 --- a/testsuite/tests/I717-018/src/stations.adb +++ b/testsuite/tests/I717-018/src/stations.adb @@ -123,10 +123,10 @@ package body Stations is Put_Line ("'C'autious mode, 'D'umb mode"); Put ("'P'robe, 'S'tep, Rotate 'L'eft/'R'ight, 'Q'uit ? "); - + -- Dummy version here, for compilation and basic run check in -- batch mode. - + end Run; ---------- diff --git a/testsuite/tests/I914-023/src/robots.adb b/testsuite/tests/I914-023/src/robots.adb index 1ac8c86ed..eb36edb33 100644 --- a/testsuite/tests/I914-023/src/robots.adb +++ b/testsuite/tests/I914-023/src/robots.adb @@ -23,5 +23,3 @@ package body Robots is end; end; - - diff --git a/testsuite/tests/I930-019/src/kops.adb b/testsuite/tests/I930-019/src/kops.adb index 550f382aa..fdc3374c2 100644 --- a/testsuite/tests/I930-019/src/kops.adb +++ b/testsuite/tests/I930-019/src/kops.adb @@ -5,4 +5,3 @@ package body Kops is X := X + K; end Inc; end; - diff --git a/testsuite/tests/I930-019/src/kops.ads b/testsuite/tests/I930-019/src/kops.ads index 589ab169d..b97d2afbe 100644 --- a/testsuite/tests/I930-019/src/kops.ads +++ b/testsuite/tests/I930-019/src/kops.ads @@ -5,4 +5,3 @@ package Kops is procedure Inc (X : in out Integer); pragma Inline (Inc); end; - diff --git a/testsuite/tests/IA01-015/src/monitor.ads b/testsuite/tests/IA01-015/src/monitor.ads index ae8097029..d387b410e 100644 --- a/testsuite/tests/IA01-015/src/monitor.ads +++ b/testsuite/tests/IA01-015/src/monitor.ads @@ -1,5 +1,5 @@ package Monitor is N_Ops : Integer := 0; - + procedure Touch; end; diff --git a/testsuite/tests/IA06-009-offset-from-sym/src/p.adb b/testsuite/tests/IA06-009-offset-from-sym/src/p.adb index 37843ce02..e5bd5de07 100644 --- a/testsuite/tests/IA06-009-offset-from-sym/src/p.adb +++ b/testsuite/tests/IA06-009-offset-from-sym/src/p.adb @@ -5,4 +5,3 @@ procedure P is begin X := X + 1; end; - diff --git a/testsuite/tests/IA09-021-unit-nosco/src/test_assert.adb b/testsuite/tests/IA09-021-unit-nosco/src/test_assert.adb index c01f2e38b..e35764b90 100644 --- a/testsuite/tests/IA09-021-unit-nosco/src/test_assert.adb +++ b/testsuite/tests/IA09-021-unit-nosco/src/test_assert.adb @@ -6,5 +6,3 @@ procedure Test_Assert is begin Checks.Assert (X = 12); end; - - diff --git a/testsuite/tests/IA16-028-disp-routines/src/monitor.adb b/testsuite/tests/IA16-028-disp-routines/src/monitor.adb index 12e627068..27284037c 100644 --- a/testsuite/tests/IA16-028-disp-routines/src/monitor.adb +++ b/testsuite/tests/IA16-028-disp-routines/src/monitor.adb @@ -1,5 +1,5 @@ package body Monitor is - + procedure Touch is begin Nops := Nops + 1; diff --git a/testsuite/tests/IA16-028-disp-routines/src/monitor.ads b/testsuite/tests/IA16-028-disp-routines/src/monitor.ads index a3cd6bf2c..160354c0a 100644 --- a/testsuite/tests/IA16-028-disp-routines/src/monitor.ads +++ b/testsuite/tests/IA16-028-disp-routines/src/monitor.ads @@ -1,4 +1,4 @@ package Monitor is - procedure Touch; + procedure Touch; Nops : Integer := 0; end; diff --git a/testsuite/tests/IA21-003-simple-decision-sco/src/pack.ads b/testsuite/tests/IA21-003-simple-decision-sco/src/pack.ads index 89a530e9f..eb1114116 100644 --- a/testsuite/tests/IA21-003-simple-decision-sco/src/pack.ads +++ b/testsuite/tests/IA21-003-simple-decision-sco/src/pack.ads @@ -1,7 +1,7 @@ package Pack is - + N_True, N_False : Natural := 0; - + Where : Boolean := False; procedure Not_Fully_Covered_Stmt_Wise; diff --git a/testsuite/tests/K214-014-gc-sections/src/foo.adb b/testsuite/tests/K214-014-gc-sections/src/foo.adb index 335884ad2..cb2edf643 100644 --- a/testsuite/tests/K214-014-gc-sections/src/foo.adb +++ b/testsuite/tests/K214-014-gc-sections/src/foo.adb @@ -5,4 +5,3 @@ begin Break_Me (1); Break_Me (True); end Foo; - diff --git a/testsuite/tests/K804-031_raise-taken/src/test_val_ce.adb b/testsuite/tests/K804-031_raise-taken/src/test_val_ce.adb index e85c1eb60..b88d8be4f 100644 --- a/testsuite/tests/K804-031_raise-taken/src/test_val_ce.adb +++ b/testsuite/tests/K804-031_raise-taken/src/test_val_ce.adb @@ -11,4 +11,3 @@ end; -- /true/ l- ## s- -- /false/ l- ## s- -- /handler/ l+ ## 0 - diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vif_r.adb b/testsuite/tests/K804-031_raise-taken/src/test_vif_r.adb index ebafd904a..eb69a8f69 100644 --- a/testsuite/tests/K804-031_raise-taken/src/test_vif_r.adb +++ b/testsuite/tests/K804-031_raise-taken/src/test_vif_r.adb @@ -9,4 +9,3 @@ end; -- /eval/ l! ## d- -- /true/ l- ## s- -- /handler/ l+ ## 0 - diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vif_rf.adb b/testsuite/tests/K804-031_raise-taken/src/test_vif_rf.adb index 077e61b14..0e8ba168f 100644 --- a/testsuite/tests/K804-031_raise-taken/src/test_vif_rf.adb +++ b/testsuite/tests/K804-031_raise-taken/src/test_vif_rf.adb @@ -10,4 +10,3 @@ end; -- /eval/ l! ## dT- -- /true/ l- ## s- -- /handler/ l+ ## 0 - diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vif_rt.adb b/testsuite/tests/K804-031_raise-taken/src/test_vif_rt.adb index 7e08bc5c8..beabace2c 100644 --- a/testsuite/tests/K804-031_raise-taken/src/test_vif_rt.adb +++ b/testsuite/tests/K804-031_raise-taken/src/test_vif_rt.adb @@ -10,4 +10,3 @@ end; -- /eval/ l! ## dF- -- /true/ l+ ## 0 -- /handler/ l+ ## 0 - diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vifn_r.adb b/testsuite/tests/K804-031_raise-taken/src/test_vifn_r.adb index 3d26c7fd1..6a1ef2945 100644 --- a/testsuite/tests/K804-031_raise-taken/src/test_vifn_r.adb +++ b/testsuite/tests/K804-031_raise-taken/src/test_vifn_r.adb @@ -9,4 +9,3 @@ end; -- /eval/ l! ## d- -- /true/ l- ## s- -- /handler/ l+ ## 0 - diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vifn_rf.adb b/testsuite/tests/K804-031_raise-taken/src/test_vifn_rf.adb index 9fd9d931c..2aa979cfc 100644 --- a/testsuite/tests/K804-031_raise-taken/src/test_vifn_rf.adb +++ b/testsuite/tests/K804-031_raise-taken/src/test_vifn_rf.adb @@ -10,4 +10,3 @@ end; -- /eval/ l! ## dT- -- /true/ l- ## s- -- /handler/ l+ ## 0 - diff --git a/testsuite/tests/K804-031_raise-taken/src/test_vifn_rt.adb b/testsuite/tests/K804-031_raise-taken/src/test_vifn_rt.adb index a3b704fb8..81b04d990 100644 --- a/testsuite/tests/K804-031_raise-taken/src/test_vifn_rt.adb +++ b/testsuite/tests/K804-031_raise-taken/src/test_vifn_rt.adb @@ -10,4 +10,3 @@ end; -- /eval/ l! ## dF- -- /true/ l+ ## 0 -- /handler/ l+ ## 0 - diff --git a/testsuite/tests/KC23-012-ocov-exemptions/p.adb b/testsuite/tests/KC23-012-ocov-exemptions/p.adb index 9c397740b..a93fe4634 100644 --- a/testsuite/tests/KC23-012-ocov-exemptions/p.adb +++ b/testsuite/tests/KC23-012-ocov-exemptions/p.adb @@ -1,6 +1,6 @@ procedure P is - + procedure Assert (T : Boolean) is begin pragma Annotate (Xcov, Exempt_On, "assert expected never to trip"); @@ -9,20 +9,16 @@ procedure P is end if; pragma Annotate (Xcov, Exempt_Off, "assert expected never to trip"); end; - + procedure Inc (X : in out Integer) is begin X := X + 1; end; - + V : Integer := 12; pragma Volatile (V); - + begin Inc (V); Assert (V = 13); end; - - - - diff --git a/testsuite/tests/L411-031_missing_gnateS/src/checks.ads b/testsuite/tests/L411-031_missing_gnateS/src/checks.ads index b3f94f64e..07333acac 100644 --- a/testsuite/tests/L411-031_missing_gnateS/src/checks.ads +++ b/testsuite/tests/L411-031_missing_gnateS/src/checks.ads @@ -1,13 +1,13 @@ package Checks is - + -- Weak assertion checking service that just counts assertion -- failures. - + -- The point of this code is to offer something to build and run to check -- for warnings about missing compilation options. We don't care about the -- actual coverage assessments here and need to minimize dependencies -- against runtime services such as an exception last chance handler. - + Assert_Failures : Natural := 0; procedure Assert (Cond : Boolean); diff --git a/testsuite/tests/L411-031_missing_gnateS/src/test_assert.adb b/testsuite/tests/L411-031_missing_gnateS/src/test_assert.adb index c01f2e38b..e35764b90 100644 --- a/testsuite/tests/L411-031_missing_gnateS/src/test_assert.adb +++ b/testsuite/tests/L411-031_missing_gnateS/src/test_assert.adb @@ -6,5 +6,3 @@ procedure Test_Assert is begin Checks.Assert (X = 12); end; - - diff --git a/testsuite/tests/L411-031_missing_gnateS/test.opt b/testsuite/tests/L411-031_missing_gnateS/test.opt index 52989de77..05bc2e529 100644 --- a/testsuite/tests/L411-031_missing_gnateS/test.opt +++ b/testsuite/tests/L411-031_missing_gnateS/test.opt @@ -1 +1 @@ -src-traces DEAD Checks compilation flags for binary coverage \ No newline at end of file +src-traces DEAD Checks compilation flags for binary coverage diff --git a/testsuite/tests/L619-040-output-to-objdir/pgm.adb b/testsuite/tests/L619-040-output-to-objdir/pgm.adb index 7bdb573cf..a65e57e0c 100644 --- a/testsuite/tests/L619-040-output-to-objdir/pgm.adb +++ b/testsuite/tests/L619-040-output-to-objdir/pgm.adb @@ -3,7 +3,7 @@ procedure PGM is -- This is GPR specific test for which we produce our own local project, -- without any libsupport consideration. We must make sure that we don't -- need a libsupport at all: - + pragma Suppress (All_Checks); X : Integer := 12; diff --git a/testsuite/tests/L929-006/test.opt b/testsuite/tests/L929-006/test.opt index a8b9c4e88..3ab09a8e9 100644 --- a/testsuite/tests/L929-006/test.opt +++ b/testsuite/tests/L929-006/test.opt @@ -1,3 +1,3 @@ leon-elf powerpc-elf -ALL DEAD test needs adaptation to run for target \ No newline at end of file +ALL DEAD test needs adaptation to run for target diff --git a/testsuite/tests/LA17-032-scan-decisions/p.adb b/testsuite/tests/LA17-032-scan-decisions/p.adb index 72c69bd34..a0ac2c0ae 100644 --- a/testsuite/tests/LA17-032-scan-decisions/p.adb +++ b/testsuite/tests/LA17-032-scan-decisions/p.adb @@ -1,10 +1,10 @@ with State; use State; -procedure P is +procedure P is begin X := A and then B; -- tree bdd - + Y := (A and then B) or else C; -- !tree bdd - + Z := (A or else B) and then C; -- !tree bdd end; diff --git a/testsuite/tests/LA23-016_eargs-exe/src/myabs.adb b/testsuite/tests/LA23-016_eargs-exe/src/myabs.adb index 5c208e4ac..53d02b5e8 100644 --- a/testsuite/tests/LA23-016_eargs-exe/src/myabs.adb +++ b/testsuite/tests/LA23-016_eargs-exe/src/myabs.adb @@ -2,8 +2,7 @@ function Myabs (X : Integer) return Integer is begin if X < 0 then return -X; - else + else return X; end if; end; - diff --git a/testsuite/tests/LB13-031-post-aspect/src/passor.adb b/testsuite/tests/LB13-031-post-aspect/src/passor.adb index 8cc3c4030..6de9d589a 100644 --- a/testsuite/tests/LB13-031-post-aspect/src/passor.adb +++ b/testsuite/tests/LB13-031-post-aspect/src/passor.adb @@ -4,4 +4,3 @@ procedure Passor (A, B : Boolean) is begin Put_Line ("Hello world"); -- # stmt end; - diff --git a/testsuite/tests/M204-037-dc-in-aggregate/src/values.adb b/testsuite/tests/M204-037-dc-in-aggregate/src/values.adb index 640233788..684eb1afa 100644 --- a/testsuite/tests/M204-037-dc-in-aggregate/src/values.adb +++ b/testsuite/tests/M204-037-dc-in-aggregate/src/values.adb @@ -1,13 +1,13 @@ package body Values is - + procedure Equal (X, Y : Integer; B : out Bool) is begin B := (Value => X = Y); -- # eq end; - + procedure Equal2 (X, Y : Integer; Z, T : Integer; B : out Bool) is begin B := (Value => (X = Y) and then (Z = T)); -- # andthen end; - + end; diff --git a/testsuite/tests/M204-037-dc-in-aggregate/src/values.ads b/testsuite/tests/M204-037-dc-in-aggregate/src/values.ads index 70a07c46b..e12b8b5bb 100644 --- a/testsuite/tests/M204-037-dc-in-aggregate/src/values.ads +++ b/testsuite/tests/M204-037-dc-in-aggregate/src/values.ads @@ -1,10 +1,10 @@ package Values is - + type Bool is record Value : Boolean; end record; - + procedure Equal (X, Y : Integer; B : out Bool); procedure Equal2 (X, Y : Integer; Z, T : Integer; B : out Bool); - + end; diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/ops.adb b/testsuite/tests/M516-014-direct-bool-operators/src/ops.adb index fb6fae6c0..9dec5b304 100644 --- a/testsuite/tests/M516-014-direct-bool-operators/src/ops.adb +++ b/testsuite/tests/M516-014-direct-bool-operators/src/ops.adb @@ -1,5 +1,5 @@ package body Ops is - + procedure Eval (A, B : Boolean) is begin if A and B then -- # eval-and @@ -13,6 +13,3 @@ package body Ops is end if; end; end; - - - diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/ops.ads b/testsuite/tests/M516-014-direct-bool-operators/src/ops.ads index 2ab2631b3..817bf3c8c 100644 --- a/testsuite/tests/M516-014-direct-bool-operators/src/ops.ads +++ b/testsuite/tests/M516-014-direct-bool-operators/src/ops.ads @@ -1,5 +1,5 @@ package Ops is procedure Eval (A, B : Boolean); - + N_And, N_Or, N_Xor : Integer := 0; end; diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_and.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_and.adb index 8177ca924..3394e7ed0 100644 --- a/testsuite/tests/M516-014-direct-bool-operators/src/test_and.adb +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_and.adb @@ -15,4 +15,3 @@ end; -- /or-true/ l+ ## 0 -- /eval-xor/ l+ ## 0 -- /xor-true/ l+ ## 0 - diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_ff.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_ff.adb index f7984d6ea..47b17d950 100644 --- a/testsuite/tests/M516-014-direct-bool-operators/src/test_ff.adb +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_ff.adb @@ -14,4 +14,3 @@ end; -- /or-true/ l- ## s- -- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dT- -- /xor-true/ l- ## s- - diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_ft.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_ft.adb index 6b1b770b1..3151c40c2 100644 --- a/testsuite/tests/M516-014-direct-bool-operators/src/test_ft.adb +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_ft.adb @@ -4,7 +4,7 @@ with Ops; use Ops; procedure Test_FT is begin Eval (A => False, B => True); - Assert (N_And = 0 and then N_Or = 1 and then N_Xor = 1); + Assert (N_And = 0 and then N_Or = 1 and then N_Xor = 1); end; --# ops.adb @@ -14,4 +14,3 @@ end; -- /or-true/ l+ ## 0 -- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dF- -- /xor-true/ l+ ## 0 - diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_or.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_or.adb index 7c01bef25..0ce5dcfff 100644 --- a/testsuite/tests/M516-014-direct-bool-operators/src/test_or.adb +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_or.adb @@ -15,4 +15,3 @@ end; -- /or-true/ l+ ## 0 -- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dT- -- /xor-true/ l- ## s- - diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_tf.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_tf.adb index 328aaf00f..feab57285 100644 --- a/testsuite/tests/M516-014-direct-bool-operators/src/test_tf.adb +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_tf.adb @@ -4,7 +4,7 @@ with Ops; use Ops; procedure Test_TF is begin Eval (A => True, B => False); - Assert (N_And = 0 and then N_Or = 1 and then N_Xor = 1); + Assert (N_And = 0 and then N_Or = 1 and then N_Xor = 1); end; --# ops.adb @@ -14,4 +14,3 @@ end; -- /or-true/ l+ ## 0 -- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dF- -- /xor-true/ l+ ## 0 - diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_tt.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_tt.adb index bcb432ac6..884d38fa4 100644 --- a/testsuite/tests/M516-014-direct-bool-operators/src/test_tt.adb +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_tt.adb @@ -4,7 +4,7 @@ with Ops; use Ops; procedure Test_TT is begin Eval (A => True, B => True); - Assert (N_And = 1 and then N_Or = 1 and then N_Xor = 0); + Assert (N_And = 1 and then N_Or = 1 and then N_Xor = 0); end; --# ops.adb @@ -14,4 +14,3 @@ end; -- /or-true/ l+ ## 0 -- /eval-xor/ s=>l+, d=>l! ## s=>0, d=>dT- -- /xor-true/ l- ## s- - diff --git a/testsuite/tests/M516-014-direct-bool-operators/src/test_xor.adb b/testsuite/tests/M516-014-direct-bool-operators/src/test_xor.adb index b477a5401..778bf197e 100644 --- a/testsuite/tests/M516-014-direct-bool-operators/src/test_xor.adb +++ b/testsuite/tests/M516-014-direct-bool-operators/src/test_xor.adb @@ -15,4 +15,3 @@ end; -- /or-true/ l+ ## 0 -- /eval-xor/ l+ ## 0 -- /xor-true/ l+ ## 0 - diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.adb index e0d4595be..db46a01f7 100644 --- a/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.adb +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/assert.adb @@ -4,4 +4,3 @@ begin raise Program_Error; end if; end; - diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb index 2d38e22b0..51563b259 100644 --- a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb @@ -1,7 +1,7 @@ with Ada.Finalization; use Ada.Finalization; package body Foo is - + type Witness is new Ada.Finalization.Controlled with record Value : Integer; end record; @@ -39,4 +39,3 @@ package body Foo is end Try; end; - diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads index e1188ef7e..aa7e225ed 100644 --- a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads @@ -1,6 +1,6 @@ -package Foo is +package Foo is procedure Try (V : Integer); - + N_Finalize, N_Adjust, N_Then, N_Else : Natural := 0; end; diff --git a/testsuite/tests/M528-002-transient-finalize/original/src/test_main.adb b/testsuite/tests/M528-002-transient-finalize/original/src/test_main.adb index 5c056da2b..96fe869d3 100644 --- a/testsuite/tests/M528-002-transient-finalize/original/src/test_main.adb +++ b/testsuite/tests/M528-002-transient-finalize/original/src/test_main.adb @@ -19,8 +19,8 @@ procedure Test_Main is return False; -- # dfalse end if; end Foo; - - + + begin if Foo (abc) then -- # outer_test_xok Log ("ok"); -- # outer_ok @@ -60,4 +60,3 @@ end; -- /outer_test_xfail/ s=>l+, dmu=>l! ## s=>0, dmu=>dT- -- /outer_err/ l- ## s- -- /outer_ok/ l+ ## 0 - diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.adb b/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.adb index 7354e37e8..c85bff4cc 100644 --- a/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.adb +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.adb @@ -1,5 +1,5 @@ package body Pkg is - + function Foo (Var : Unbounded_String) return Boolean is begin if Var = To_Unbounded_String ("abc") -- # evalA @@ -11,5 +11,5 @@ package body Pkg is return False; -- # dfalse end if; end Foo; - + end; diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.ads b/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.ads index 2b490827f..7708de8f9 100644 --- a/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.ads +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/pkg.ads @@ -1,12 +1,12 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; package Pkg is - + abc : constant Unbounded_String := To_Unbounded_String ("abc"); def : constant Unbounded_String := To_Unbounded_String ("def"); ghi : constant Unbounded_String := To_Unbounded_String ("ghi"); bool : constant Unbounded_String := To_Unbounded_String ("bool"); function Foo (Var : Unbounded_String) return Boolean; - + end; diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/test_df.adb b/testsuite/tests/M528-002-transient-finalize/variant1/src/test_df.adb index 430f86196..c93a6dd48 100644 --- a/testsuite/tests/M528-002-transient-finalize/variant1/src/test_df.adb +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/test_df.adb @@ -1,6 +1,6 @@ with Assert, Pkg; use Pkg; -procedure Test_DF is +procedure Test_DF is begin Assert (not Foo (bool)); end; @@ -11,5 +11,3 @@ end; -- /evalC/ s=>l+, dmu=>l! ## 0 -- /dtrue/ l- ## s- -- /dfalse/ l+ ## 0 - - diff --git a/testsuite/tests/M528-002-transient-finalize/variant1/src/test_dt.adb b/testsuite/tests/M528-002-transient-finalize/variant1/src/test_dt.adb index cbb24aa6b..88a087e61 100644 --- a/testsuite/tests/M528-002-transient-finalize/variant1/src/test_dt.adb +++ b/testsuite/tests/M528-002-transient-finalize/variant1/src/test_dt.adb @@ -1,6 +1,6 @@ with Assert, Pkg; use Pkg; -procedure Test_DT is +procedure Test_DT is begin Assert (Foo (abc)); end; @@ -11,5 +11,3 @@ end; -- /evalC/ s=>l+, dmu=>l! ## 0 -- /dtrue/ l+ ## 0 -- /dfalse/ l- ## s- - - diff --git a/testsuite/tests/M625-011-GPR-Cunits/src/bar.c b/testsuite/tests/M625-011-GPR-Cunits/src/bar.c index 20ba45704..3b079e8fe 100644 --- a/testsuite/tests/M625-011-GPR-Cunits/src/bar.c +++ b/testsuite/tests/M625-011-GPR-Cunits/src/bar.c @@ -4,4 +4,4 @@ int bar (int x) { return x + 1; -} \ No newline at end of file +} diff --git a/testsuite/tests/M625-011-GPR-Cunits/src/bar.h b/testsuite/tests/M625-011-GPR-Cunits/src/bar.h index 90792bc00..7f17a74f5 100644 --- a/testsuite/tests/M625-011-GPR-Cunits/src/bar.h +++ b/testsuite/tests/M625-011-GPR-Cunits/src/bar.h @@ -9,4 +9,4 @@ baz (int x) return x - 1; } -#endif // BAR_H \ No newline at end of file +#endif // BAR_H diff --git a/testsuite/tests/M625-040-slow_on_windows/p.adb b/testsuite/tests/M625-040-slow_on_windows/p.adb index 64f041b55..c46cc9260 100644 --- a/testsuite/tests/M625-040-slow_on_windows/p.adb +++ b/testsuite/tests/M625-040-slow_on_windows/p.adb @@ -2,10 +2,10 @@ procedure P is X : Integer := 0; pragma Volatile (X); - + N_Increments : Integer := 5000; pragma Volatile (N_increments); - + begin for I in 1 .. N_Increments loop X := X + 1; diff --git a/testsuite/tests/M724-035-eh-warnings/src/test_loc.adb b/testsuite/tests/M724-035-eh-warnings/src/test_loc.adb index ef2840c77..35e306b10 100644 --- a/testsuite/tests/M724-035-eh-warnings/src/test_loc.adb +++ b/testsuite/tests/M724-035-eh-warnings/src/test_loc.adb @@ -9,4 +9,3 @@ end Test_Loc; -- /false/ l- ## s- -- /ret/ l+ ## 0 -- /exc/ l- ## s- - diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/assert.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/assert.adb index c391fc68a..db46a01f7 100644 --- a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/assert.adb +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/assert.adb @@ -4,4 +4,3 @@ begin raise Program_Error; end if; end; - diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.adb index d5c12fb4f..5783f905d 100644 --- a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.adb +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.adb @@ -4,4 +4,3 @@ package body Counters is X := X + 1; end; end; - diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.ads b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.ads index a16467c03..265d960ea 100644 --- a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.ads +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/counters.ads @@ -1,6 +1,5 @@ package Counters is Nthen, Nelse : Natural := 0; - + procedure Bump (X : in out Natural); end; - diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/falseonly.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/falseonly.adb index 0c9326c4f..9d971aa4a 100644 --- a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/falseonly.adb +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/falseonly.adb @@ -1,7 +1,7 @@ with Support, Counters; use Support; procedure Falseonly is - + function Pos (X : Integer) return Boolean is begin if X > 0 then -- # test @@ -12,10 +12,9 @@ procedure Falseonly is return False; -- # else end if; end Pos; - + begin Assert (Pos (-1) = False); Assert (Counters.Nthen = 0); Assert (Counters.Nelse = 1); end; - diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_falseonly.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_falseonly.adb index 5321a76b6..7b04287db 100644 --- a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_falseonly.adb +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_falseonly.adb @@ -1,6 +1,6 @@ with Falseonly; -procedure Test_Falseonly is +procedure Test_Falseonly is begin Falseonly; end; @@ -12,6 +12,3 @@ end; -- %cov: --non-coverable -- =/then/ l0 ## s0 - - - diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_truefalse.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_truefalse.adb index eab07046c..ba3a0de93 100644 --- a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_truefalse.adb +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_truefalse.adb @@ -8,4 +8,3 @@ end; -- /test/ l+ ## 0 -- /then/ l+ ## 0 -- /else/ l+ ## 0 - diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_trueonly.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_trueonly.adb index 279ab3b23..6f15c64e7 100644 --- a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_trueonly.adb +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/test_trueonly.adb @@ -1,6 +1,6 @@ with Trueonly; -procedure Test_Trueonly is +procedure Test_Trueonly is begin Trueonly; end; @@ -12,6 +12,3 @@ end; -- %cov: --non-coverable -- =/else/ l0 ## s0 - - - diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/truefalse.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/truefalse.adb index addb2bd46..4ead33d1a 100644 --- a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/truefalse.adb +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/truefalse.adb @@ -1,7 +1,7 @@ with Support, Counters; use Support; procedure Truefalse is - + function Pos (X : Integer) return Boolean is begin if X > 0 then -- # test @@ -12,11 +12,10 @@ procedure Truefalse is return False; -- # else end if; end Pos; - + begin Assert (Pos (1) = True); Assert (Pos (-1) = False); Assert (Counters.Nthen = 1); Assert (Counters.Nelse = 1); end; - diff --git a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/trueonly.adb b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/trueonly.adb index ab81d0d15..a6a38c337 100644 --- a/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/trueonly.adb +++ b/testsuite/tests/MB05-039-not-coverable/decision/StaticInline/src/trueonly.adb @@ -1,7 +1,7 @@ with Support, Counters; use Support; procedure Trueonly is - + function Pos (X : Integer) return Boolean is begin if X > 0 then -- # test @@ -12,10 +12,9 @@ procedure Trueonly is return False; -- # else end if; end Pos; - + begin Assert (Pos (1) = True); Assert (Counters.Nthen = 1); Assert (Counters.Nelse = 0); end; - diff --git a/testsuite/tests/MB05-039-not-coverable/src/state.ads b/testsuite/tests/MB05-039-not-coverable/src/state.ads index 2290511aa..b802e2606 100644 --- a/testsuite/tests/MB05-039-not-coverable/src/state.ads +++ b/testsuite/tests/MB05-039-not-coverable/src/state.ads @@ -1,15 +1,15 @@ package State is - + -- Liveness ticks, expected to click - + Ticks : Integer := 0; pragma Volatile (Ticks); - + -- Death ticks, expected never to clisk - + Dticks : Integer := 0; pragma Volatile (Dticks); - + procedure Tick; procedure Dtick; end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrnf.adb index 317b59e05..2124edd7b 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrnf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrnf.adb @@ -1,15 +1,14 @@ with Support, Values; use Support; procedure Check_Local_NRNF is - + type My_Range is range -100 .. -1; My_Factor : constant := -3; - + package My_Processor is new Values (Value_T => My_Range, Factor => My_Factor); - + X : My_Range := -12; begin Assert (My_Processor.F(X) = Integer(X-4) + My_Factor); end; - diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrpf.adb index 33cbaf715..67ff5e5b6 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrpf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_nrpf.adb @@ -1,15 +1,14 @@ with Support, Values; use Support; procedure Check_Local_NRPF is - + type My_Range is range -100 .. -1; My_Factor : constant := 3; - + package My_Processor is new Values (Value_T => My_Range, Factor => My_Factor); - + X : My_Range := -12; begin Assert (My_Processor.F(X) = Integer(X-4) + 2*My_Factor); end; - diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prnf.adb index 8fe026af1..acd743dc4 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prnf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prnf.adb @@ -1,16 +1,14 @@ with Support, Values; use Support; procedure Check_Local_PRNF is - + type My_Range is range 1 .. 100; My_Factor : constant := -3; - + package My_Processor is new Values (Value_T => My_Range, Factor => My_Factor); - + X : My_Range := 12; begin Assert (My_Processor.F(X) = Integer(X+1) + My_Factor); end; - - diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prpf.adb index a642452e2..ce14d35bd 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prpf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/check_local_prpf.adb @@ -1,15 +1,14 @@ with Support, Values; use Support; procedure Check_Local_PRPF is - + type My_Range is range 1 .. 100; My_Factor : constant := 3; - + package My_Processor is new Values (Value_T => My_Range, Factor => My_Factor); - + X : My_Range := 12; begin Assert (My_Processor.F(X) = Integer(X+1) + 2*My_Factor); end; - diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prnf.adb index 47cab03c5..834fa47dd 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prnf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prnf.adb @@ -17,4 +17,3 @@ end; -- %cargs: -O1 -- =/xneg/ l0 ## s0 - diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prpf.adb index 6196ed64e..5f8e7f497 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prpf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_local_prpf.adb @@ -17,4 +17,3 @@ end; -- %cargs: -O1 -- =/xneg/ l0 ## s0 - diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_mrmf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_mrmf.adb index 64d8c2e52..45255c745 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_mrmf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_mrmf.adb @@ -13,4 +13,3 @@ end; -- /test_factor/ l+ ## 0 -- /fpos/ l+ ## 0 -- /fneg/ l+ ## 0 - diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrnf.adb index 7b2d87943..005f5b073 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrnf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrnf.adb @@ -16,4 +16,3 @@ end; -- %cargs: -O1 -- =/xpos/ l0 ## s0 - diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrpf.adb index 1aeb439e6..54097190a 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrpf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/test_values_nrpf.adb @@ -16,4 +16,3 @@ end; -- %cargs: -O1 -- =/xpos/ l0 ## s0 - diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.adb index 1503f769c..35b6ce0ae 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.adb @@ -5,7 +5,7 @@ with State; use State; -- * The X > 0 test can be always True (or False) for some definitions -- of Value_T. The compiler would normally optimize this away in instances -- on request (-O1), even with -fpreserve-control-flow. --- +-- -- * The tests on formal "in" parameters are always known at -- at compiler time for a given instance, and the compiler -- takes advantage of that to simplify early, even at O0. @@ -20,13 +20,13 @@ package body Values is else V := Integer (X - 4); -- # xneg end if; - + if Factor > 0 then -- # test_factor Adjusted_Factor := Factor * 2; -- # fpos else Adjusted_Factor := Factor; -- # fneg end if; - + return V + Adjusted_Factor; -- # stmt - end; + end; end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.ads index 5a661e743..7d4be5df4 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.ads +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values.ads @@ -1,7 +1,7 @@ generic type Value_T is range <>; Factor : in Integer; - + package Values is function F (X : in Value_T) return Integer; end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.adb index 89d2eaac6..ba0089852 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_mrmf.adb @@ -1,19 +1,19 @@ with Support, Values; use Support; package body Values_MRMF is - + type My_P_Range is range 1 .. 100; My_P_Factor : constant := 3; - + package My_Processor_P is new Values (Value_T => My_P_Range, Factor => My_P_Factor); - + type My_N_Range is range -100 .. -1; My_N_Factor : constant := -3; - + package My_Processor_N is new Values (Value_T => My_N_Range, Factor => My_N_Factor); - + procedure Check is XP : My_P_Range := 12; XN : My_N_Range := -12; @@ -21,6 +21,5 @@ package body Values_MRMF is Assert (My_Processor_P.F(XP) = Integer(XP+1) + 2*My_P_Factor); Assert (My_Processor_N.F(XN) = Integer(XN-4) + My_N_Factor); end; - -end; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.adb index fdf1e121b..753af3198 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.adb @@ -1,18 +1,17 @@ with Support, Values; use Support; package body Values_NRNF is - + type My_Range is range -100 .. -1; My_Factor : constant := -3; - + package My_Processor is new Values (Value_T => My_Range, Factor => My_Factor); - + procedure Check is X : My_Range := -12; begin Assert (My_Processor.F(X) = Integer(X-4) + My_Factor); end; - -end; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.ads index e81428fd4..732a4ae90 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.ads +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrnf.ads @@ -1,4 +1,3 @@ package Values_NRNF is procedure Check; end; - diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.adb index 6290d3694..dd6b12a21 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.adb @@ -1,18 +1,17 @@ with Support, Values; use Support; package body Values_NRPF is - + type My_Range is range -100 .. -1; My_Factor : constant := 3; - + package My_Processor is new Values (Value_T => My_Range, Factor => My_Factor); - + procedure Check is X : My_Range := -12; begin Assert (My_Processor.F(X) = Integer(X-4) + 2*My_Factor); end; - -end; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.ads index e7859cd77..f5410660a 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.ads +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_nrpf.ads @@ -1,4 +1,3 @@ -package Values_NRPF is +package Values_NRPF is procedure Check; end; - diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.adb index 85c067df5..7bf04b286 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prnf.adb @@ -1,18 +1,17 @@ with Support, Values; use Support; package body Values_PRNF is - + type My_Range is range 1 .. 100; My_Factor : constant := -3; - + package My_Processor is new Values (Value_T => My_Range, Factor => My_Factor); - + procedure Check is X : My_Range := 12; begin Assert (My_Processor.F(X) = Integer(X+1) + My_Factor); end; - -end; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.adb index 813beb61d..cd0e788d4 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Generics/src/values_prpf.adb @@ -1,18 +1,17 @@ with Support, Values; use Support; package body Values_PRPF is - + type My_Range is range 1 .. 100; My_Factor : constant := 3; - + package My_Processor is new Values (Value_T => My_Range, Factor => My_Factor); - + procedure Check is X : My_Range := 12; begin Assert (My_Processor.F(X) = Integer(X+1) + 2*My_Factor); end; - -end; +end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/test_values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/test_values.adb index 170308f4e..1eca6801d 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/test_values.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/test_values.adb @@ -4,10 +4,10 @@ procedure Test_Values is V : Integer; begin Assert (One = 1.0); - + V := Value_Of (X => 15); Assert (V = 15); - + Latch (V => 12); V := Value_Of_X; Assert (V = 12); diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.adb index 988efc12a..5d6b9e1fe 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.adb @@ -1,7 +1,7 @@ with State; use State; package body Values is - + function One return Float is begin return 1.0; -- # stmt @@ -10,7 +10,7 @@ package body Values is Dtick; -- # out return 2.0; -- # out end; - + function Value_Of (X : Integer) return Integer is begin return X; -- # stmt @@ -20,14 +20,14 @@ package body Values is when Program_Error => return 66; -- # out end; - + function Value_Of_X return Integer is begin return X; -- # stmt exception when others => return 50; -- # out end; - + procedure Latch (V : Integer) is begin Tick; -- # stmt @@ -38,5 +38,3 @@ package body Values is end; end; end; - - diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.ads b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.ads index 831955303..2c2ec120a 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.ads +++ b/testsuite/tests/MB05-039-not-coverable/stmt/HandlerElim/src/values.ads @@ -1,9 +1,9 @@ package Values is X : Integer := 1; - + function One return Float; - + procedure Latch (V : Integer); - function Value_Of (X : Integer) return Integer; + function Value_Of (X : Integer) return Integer; function Value_Of_X return Integer; end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.adb b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.adb index 8b77db6aa..d481181b6 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.adb @@ -1,13 +1,13 @@ with State; use State; package body IFS is - + -- Expose various cases with if statements controled by constant guards, -- which are simplified early-on by the compiler front-end. - + -- Whether a code-less "if XX then" stmt becomes coverable itself -- depends on whether it dominates coverable statements. - + procedure If_F_Var_Last is begin Tick; -- # reach @@ -15,7 +15,7 @@ package body IFS is Dtick; -- # out end if; end; - + procedure If_F_Cmp_Last is begin Tick; -- # reach @@ -23,7 +23,7 @@ package body IFS is Dtick; -- # out end if; end; - + procedure If_F_Var_Not_Last is begin Tick; -- # reach @@ -41,9 +41,9 @@ package body IFS is end if; Tick; -- # reach end; - + -- - + procedure Ifelse_F_Var_Last is begin Tick; -- # reach @@ -53,7 +53,7 @@ package body IFS is Tick; -- # reach end if; end; - + procedure Ifelse_F_Cmp_Last is begin Tick; -- # reach @@ -63,7 +63,7 @@ package body IFS is Tick; -- # reach end if; end; - + procedure Ifelse_F_Var_Not_Last is begin Tick; -- # reach @@ -74,7 +74,7 @@ package body IFS is end if; Tick; -- # reach end; - + procedure Ifelse_F_Cmp_Not_Last is begin Tick; -- # reach @@ -85,9 +85,9 @@ package body IFS is end if; Tick; -- # reach end; - + -- - + procedure Ifelse_T_Var_Last is begin Tick; -- # reach @@ -97,7 +97,7 @@ package body IFS is Dtick; -- # out end if; end; - + procedure Ifelse_T_Cmp_Last is begin Tick; -- # reach @@ -105,9 +105,9 @@ package body IFS is Tick; -- # reach else Dtick; -- # out - end if; + end if; end; - + procedure Ifelse_T_Var_Not_Last is begin Tick; -- # reach @@ -118,7 +118,7 @@ package body IFS is end if; Tick; -- # reach end; - + procedure Ifelse_T_Cmp_Not_Last is begin Tick; -- # reach @@ -129,5 +129,5 @@ package body IFS is end if; Tick; -- # reach end; - + end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.ads b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.ads index 4659e4434..407db93c3 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.ads +++ b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/ifs.ads @@ -1,18 +1,18 @@ package IFS is - + GT : constant Boolean := True; GF : constant Boolean := False; - + procedure If_F_Var_Last; procedure If_F_Cmp_Last; procedure If_F_Var_Not_Last; procedure If_F_Cmp_Not_Last; - + procedure Ifelse_F_Var_Last; procedure Ifelse_F_Cmp_Last; procedure Ifelse_F_Var_Not_Last; procedure Ifelse_F_Cmp_Not_Last; - + procedure Ifelse_T_Var_Last; procedure Ifelse_T_Cmp_Last; procedure Ifelse_T_Var_Not_Last; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/test_ifs.adb b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/test_ifs.adb index ead89f85f..c413bf51a 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/test_ifs.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/StaticGuard/src/test_ifs.adb @@ -5,37 +5,37 @@ procedure Test_Ifs is begin If_F_Var_Last; Assert (Ticks = 1); - + If_F_Cmp_Last; Assert (Ticks = 2); - + If_F_Var_Not_Last; Assert (Ticks = 4); - + If_F_Cmp_Not_Last; Assert (Ticks = 6); - + Ifelse_F_Var_Last; Assert (Ticks = 8); - + Ifelse_F_Cmp_Last; Assert (Ticks = 10); - + Ifelse_F_Var_Not_Last; Assert (Ticks = 13); - + Ifelse_F_Cmp_Not_Last; Assert (Ticks = 16); - + Ifelse_T_Var_Last; Assert (Ticks = 18); - + Ifelse_T_Cmp_Last; Assert (Ticks = 20); - + Ifelse_T_Var_Not_Last; Assert (Ticks = 23); - + Ifelse_T_Cmp_Not_Last; Assert (Ticks = 26); end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.adb b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.adb index d401e1bd8..888f7a0a9 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.adb @@ -4,33 +4,33 @@ with State; use State; -- # opt_out is for statements taken out only when optimizing. package body Misc is - + -- A local library level subprogram just unused. - + procedure Dump_Old_Log; procedure Dump_Old_Log is begin Dtick; -- # opt_out end; - + -- A local subprogram which only gets called in a section guarded by a -- constant False test: - + procedure Dump_Debug_Log is begin Dtick; -- # opt_out end; - + procedure Check_State is - + -- A nested subprogram just unused - + procedure Crash_Me is begin Dtick; -- # out end; - + -- A nested subprogram called in a guarded false -- sequence of statements @@ -38,7 +38,7 @@ package body Misc is begin Dtick; -- # out end; - + begin Tick; -- # stmt if GF then -- # out @@ -46,5 +46,5 @@ package body Misc is Maybe_Crash_Me; -- # out end if; end; - + end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.ads b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.ads index 06c42bdfc..e665e9029 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.ads +++ b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/misc.ads @@ -1,5 +1,5 @@ package Misc is GF : constant Boolean := False; - + procedure Check_State; end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/test_misc.adb b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/test_misc.adb index 28b2f737b..a20bd4961 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/test_misc.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/SubprogElim/src/test_misc.adb @@ -16,5 +16,3 @@ end; -- %cargs: -O1 -- /opt_out/ l0 ## s0 - - diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.adb b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.adb index daa959467..754621e56 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.adb +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.adb @@ -1,19 +1,19 @@ with State; use State; package body Values is - + function Abs_Of (X : Integer) return Integer is - + begin if X > 0 then -- # stmt return X; -- # xpos else return -X; -- # xneg end if; - + -- We always return prior to this point - + Dtick; -- # out end; - + end; diff --git a/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.ads b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.ads index c0505b416..bccc61f00 100644 --- a/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.ads +++ b/testsuite/tests/MB05-039-not-coverable/stmt/Unreachable/src/values.ads @@ -1,6 +1,6 @@ package Values is - + function Abs_Of (X : Integer) return Integer; - + end; diff --git a/testsuite/tests/MB15-040-if-cst/src/monitor.adb b/testsuite/tests/MB15-040-if-cst/src/monitor.adb index 45554ed8b..2aa57f820 100644 --- a/testsuite/tests/MB15-040-if-cst/src/monitor.adb +++ b/testsuite/tests/MB15-040-if-cst/src/monitor.adb @@ -1,9 +1,9 @@ - + package body Monitor is - + Moncalls : Natural := 0; pragma Volatile (Moncalls); - + procedure Op is begin if Count_Ops then -- # called diff --git a/testsuite/tests/MB15-040-if-cst/src/monitor.ads b/testsuite/tests/MB15-040-if-cst/src/monitor.ads index 69619fddd..3e20fa134 100644 --- a/testsuite/tests/MB15-040-if-cst/src/monitor.ads +++ b/testsuite/tests/MB15-040-if-cst/src/monitor.ads @@ -2,6 +2,6 @@ package Monitor is Count_Ops : constant Boolean := False; Opcount : Natural := 0; - + procedure Op; end; diff --git a/testsuite/tests/MC05-011-ref-executable/src/double.adb b/testsuite/tests/MC05-011-ref-executable/src/double.adb index 24520d5d0..15e28161b 100644 --- a/testsuite/tests/MC05-011-ref-executable/src/double.adb +++ b/testsuite/tests/MC05-011-ref-executable/src/double.adb @@ -2,4 +2,3 @@ procedure Double (X : in out Integer) is begin X := X * 2; end; - diff --git a/testsuite/tests/N106-020-tempfiles/src/actions.adb b/testsuite/tests/N106-020-tempfiles/src/actions.adb index a46fcebc7..46b90c0bc 100644 --- a/testsuite/tests/N106-020-tempfiles/src/actions.adb +++ b/testsuite/tests/N106-020-tempfiles/src/actions.adb @@ -1,8 +1,8 @@ package body Actions is - + Value : Integer := 0; pragma Volatile (Value); - + procedure Process_Positive (X : Integer) is begin if X <= 0 then -- # test_pos @@ -10,7 +10,7 @@ package body Actions is end if; Value := Value + X; -- # do_pos end; - + procedure Process_Negative (X : Integer) is begin if X >= 0 then -- # test_neg @@ -18,14 +18,14 @@ package body Actions is end if; Value := Value + X; -- # do_neg end; - + procedure Process_Zero (X : Integer) is begin if X /= 0 then -- # test_zero raise Constraint_Error; -- # unreach_zero end if; end; - + procedure Process (X : Integer; Action : Action_Access) is begin Action.all (X); diff --git a/testsuite/tests/N106-020-tempfiles/src/actions.ads b/testsuite/tests/N106-020-tempfiles/src/actions.ads index 6658199cf..bf5e169f9 100644 --- a/testsuite/tests/N106-020-tempfiles/src/actions.ads +++ b/testsuite/tests/N106-020-tempfiles/src/actions.ads @@ -1,12 +1,11 @@ package Actions is - + type Action_Access is access procedure (X : Integer); - + procedure Process_Positive (X : Integer); procedure Process_Negative (X : Integer); procedure Process_Zero (X : Integer); - + procedure Process (X : Integer; Action : Action_Access); - -end; +end; diff --git a/testsuite/tests/N106-020-tempfiles/src/test_tags.adb b/testsuite/tests/N106-020-tempfiles/src/test_tags.adb index 4500ca655..1a9b18784 100644 --- a/testsuite/tests/N106-020-tempfiles/src/test_tags.adb +++ b/testsuite/tests/N106-020-tempfiles/src/test_tags.adb @@ -4,8 +4,8 @@ with Actions; use Actions; -- conditional sections of expectation statements depending on -- the testsuite discriminants. -procedure Test_Tags is -begin +procedure Test_Tags is +begin Process (5, Process_Positive'Access); Process (-5, Process_Negative'Access); Process (0, Process_Zero'Access); diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.adb index e142910a5..cf3851287 100644 --- a/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.adb +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/hello.adb @@ -3,11 +3,11 @@ package body Hello is function Get_Hello (Formal : Boolean) return String; -- Returns Hello or Hi depending on the Formal parameter - + --------------- -- Get_Hello -- --------------- - + function Get_Hello (Formal : Boolean) return String is begin if Formal then -- # test_formal @@ -16,14 +16,14 @@ package body Hello is return "Hi"; -- # casual end if; end Get_Hello; - + procedure Process (S : String) is Len : Integer; pragma Volatile (Len); begin Len := S'Length; end; - + --------------- -- Say_Hello -- --------------- @@ -39,4 +39,3 @@ package body Hello is end Say_Hello; end Hello; - diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_nobody.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_nobody.adb index f108ef2c8..c7647d427 100644 --- a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_nobody.adb +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_nobody.adb @@ -12,4 +12,3 @@ end; -- /test_formal/ l! ## dT- -- /formal/ l- ## s- -- /casual/ l+ ## 0 - diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_someone.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_someone.adb index 343b7f65b..0dbf294db 100644 --- a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_someone.adb +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_casual_someone.adb @@ -12,4 +12,3 @@ end; -- /test_formal/ l! ## dT- -- /formal/ l- ## s- -- /casual/ l+ ## 0 - diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_nobody.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_nobody.adb index bbb96dfdf..ba140c6f3 100644 --- a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_nobody.adb +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_nobody.adb @@ -12,4 +12,3 @@ end; -- /test_formal/ l! ## dF- -- /formal/ l+ ## 0 -- /casual/ l- ## s- - diff --git a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_someone.adb b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_someone.adb index 6add91be6..266073e48 100644 --- a/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_someone.adb +++ b/testsuite/tests/N521-029-dc-dynstack-twoways/src/test_formal_someone.adb @@ -12,4 +12,3 @@ end; -- /test_formal/ l! ## dF- -- /formal/ l+ ## 0 -- /casual/ l- ## s- - diff --git a/testsuite/tests/N630-009-forward_p_x/foo.adb b/testsuite/tests/N630-009-forward_p_x/foo.adb index 1089b97f8..13c90e6cd 100644 --- a/testsuite/tests/N630-009-forward_p_x/foo.adb +++ b/testsuite/tests/N630-009-forward_p_x/foo.adb @@ -3,4 +3,4 @@ with Ada.Text_IO; use Ada.Text_IO; procedure Foo is begin Put_Line ("hello there"); -end; +end; diff --git a/testsuite/tests/N630-009-forward_p_x/test.opt b/testsuite/tests/N630-009-forward_p_x/test.opt index 5096f7b9b..bcaa349a6 100644 --- a/testsuite/tests/N630-009-forward_p_x/test.opt +++ b/testsuite/tests/N630-009-forward_p_x/test.opt @@ -1,2 +1,2 @@ -native DEAD testing gnatcov/gnatemu interaction, no gnatemu on native +native DEAD testing gnatcov/gnatemu interaction, no gnatemu on native src-traces DEAD gnatcov/gnatemu interaction not relevant for the trace mode diff --git a/testsuite/tests/NC08-027-target_attr/foo.adb b/testsuite/tests/NC08-027-target_attr/foo.adb index 1089b97f8..13c90e6cd 100644 --- a/testsuite/tests/NC08-027-target_attr/foo.adb +++ b/testsuite/tests/NC08-027-target_attr/foo.adb @@ -3,4 +3,4 @@ with Ada.Text_IO; use Ada.Text_IO; procedure Foo is begin Put_Line ("hello there"); -end; +end; diff --git a/testsuite/tests/O212-062-assertions/src/assertions.adb b/testsuite/tests/O212-062-assertions/src/assertions.adb index c9d7d43c5..ed646b557 100644 --- a/testsuite/tests/O212-062-assertions/src/assertions.adb +++ b/testsuite/tests/O212-062-assertions/src/assertions.adb @@ -25,7 +25,7 @@ package body Assertions is -- Same -- ---------- - function Same (A, B : Boolean) return Boolean + function Same (A, B : Boolean) return Boolean is -- Subprogram body with aspect without prior declaration diff --git a/testsuite/tests/O212-062-assertions/src/pack_type_invariant.ads b/testsuite/tests/O212-062-assertions/src/pack_type_invariant.ads index e9430ebf3..3d2eaf4b2 100644 --- a/testsuite/tests/O212-062-assertions/src/pack_type_invariant.ads +++ b/testsuite/tests/O212-062-assertions/src/pack_type_invariant.ads @@ -19,4 +19,3 @@ private ((B => B)); -- # func_ret_1 end Pack_Type_Invariant; - diff --git a/testsuite/tests/O212-062-show-condition-vectors/main.adb b/testsuite/tests/O212-062-show-condition-vectors/main.adb index 9d9cb6287..801b5e835 100644 --- a/testsuite/tests/O212-062-show-condition-vectors/main.adb +++ b/testsuite/tests/O212-062-show-condition-vectors/main.adb @@ -8,4 +8,3 @@ begin Other_Proc (True, True); Other_Proc (False, True); end Main; - diff --git a/testsuite/tests/O212-062-show-condition-vectors/pkg.adb b/testsuite/tests/O212-062-show-condition-vectors/pkg.adb index f863e28d1..adb1d51f9 100644 --- a/testsuite/tests/O212-062-show-condition-vectors/pkg.adb +++ b/testsuite/tests/O212-062-show-condition-vectors/pkg.adb @@ -8,7 +8,7 @@ package body Pkg is procedure Mystery (A, B, C : Boolean) is function Id (B : Boolean) return Boolean; - + function Id (B : Boolean) return Boolean is begin return B; diff --git a/testsuite/tests/O212-062-show-condition-vectors/pkg.ads b/testsuite/tests/O212-062-show-condition-vectors/pkg.ads index f20a1e22f..c5528490a 100644 --- a/testsuite/tests/O212-062-show-condition-vectors/pkg.ads +++ b/testsuite/tests/O212-062-show-condition-vectors/pkg.ads @@ -4,4 +4,3 @@ package Pkg is procedure Other_Proc (A, B : Boolean); end Pkg; - diff --git a/testsuite/tests/OB26-040-type-invariants/Aspects/test.opt b/testsuite/tests/OB26-040-type-invariants/Aspects/test.opt index 99c8cf2cb..afdb47546 100644 --- a/testsuite/tests/OB26-040-type-invariants/Aspects/test.opt +++ b/testsuite/tests/OB26-040-type-invariants/Aspects/test.opt @@ -1 +1 @@ -7.1.2 DEAD assertion policy pragma in package not supported in 7.1.2 \ No newline at end of file +7.1.2 DEAD assertion policy pragma in package not supported in 7.1.2 diff --git a/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/test_t.adb b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/test_t.adb index 423dd2440..075998536 100644 --- a/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/test_t.adb +++ b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/test_t.adb @@ -5,7 +5,7 @@ procedure Test_T is CIO : CI (UB => 2); STIO : STI (UB => 10); CTIO : CTI (UB => 4); - + begin null; end; @@ -16,4 +16,3 @@ end; -- /ci/ l! ## dF- -- /sti/ l! ## dF- -- /cti/ l! ## dF- - diff --git a/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.adb b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.adb index 860fe450d..7cb145d93 100644 --- a/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.adb +++ b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.adb @@ -1,5 +1,5 @@ package body Types_A is - + function Valid (X : Int) return Boolean is begin return X.Value <= X.UB; diff --git a/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.ads b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.ads index e4f1b9c88..c459314f0 100644 --- a/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.ads +++ b/testsuite/tests/OB26-040-type-invariants/InvariantClass/src/types_a.ads @@ -2,12 +2,12 @@ pragma Ada_2012; package Types_A is pragma Assertion_Policy (Invariant => Check, Type_Invariant => Check); - + type Int (UB : Integer) is tagged private with Type_Invariant'Class => Valid (Int); -- # base - + function Valid (X : Int) return Boolean; - + -- In type names, I stands for Invariant, TI for Type_Invariant, -- S for Simple, C for Complex @@ -15,27 +15,27 @@ package Types_A is type CI is new Int with private; type STI is new Int with private; type CTI is new Int with private; - + private - + type Int (UB : Integer) is tagged record Value : Integer := UB; end record; -- Invariant Aspects, Simple then Complex - + type SI is new Int with null record with Invariant => SI.Value > 0; -- # si - + type CI is new Int with null record with Invariant => CI.Value > 0; -- # ci - + -- Type_Invariant Aspects, Simple then Complex - + type STI is new Int with null record with Type_Invariant => STI.Value > 0; -- # sti - + type CTI is new Int with null record with Type_Invariant => CTI.Value > 0; -- # cti - + end; diff --git a/testsuite/tests/OB26-040-type-invariants/Pragmas/test.opt b/testsuite/tests/OB26-040-type-invariants/Pragmas/test.opt index 99c8cf2cb..afdb47546 100644 --- a/testsuite/tests/OB26-040-type-invariants/Pragmas/test.opt +++ b/testsuite/tests/OB26-040-type-invariants/Pragmas/test.opt @@ -1 +1 @@ -7.1.2 DEAD assertion policy pragma in package not supported in 7.1.2 \ No newline at end of file +7.1.2 DEAD assertion policy pragma in package not supported in 7.1.2 diff --git a/testsuite/tests/P526-035-origin-project/test.opt b/testsuite/tests/P526-035-origin-project/test.opt index 83cb05b0d..a2f909ef8 100644 --- a/testsuite/tests/P526-035-origin-project/test.opt +++ b/testsuite/tests/P526-035-origin-project/test.opt @@ -1 +1 @@ -src-traces DEAD Option "projects" not working rightfully with source coverage. \ No newline at end of file +src-traces DEAD Option "projects" not working rightfully with source coverage. diff --git a/testsuite/tests/P614-002-incidental-coverage/src/maps.adb b/testsuite/tests/P614-002-incidental-coverage/src/maps.adb index 635ad5986..e4bc2c70f 100644 --- a/testsuite/tests/P614-002-incidental-coverage/src/maps.adb +++ b/testsuite/tests/P614-002-incidental-coverage/src/maps.adb @@ -6,7 +6,7 @@ with Math; use Math; package body Maps is - + function Area (R : Rectangle_T) return Natural is begin return Eval (Mult, R.L, R.W); -- # eval diff --git a/testsuite/tests/P614-002-incidental-coverage/src/maps.ads b/testsuite/tests/P614-002-incidental-coverage/src/maps.ads index c5f113f5b..c43312868 100644 --- a/testsuite/tests/P614-002-incidental-coverage/src/maps.ads +++ b/testsuite/tests/P614-002-incidental-coverage/src/maps.ads @@ -2,6 +2,6 @@ package Maps is type Rectangle_T is record L, W : Natural; end record; - + function Area (R : Rectangle_T) return Natural; end; diff --git a/testsuite/tests/P614-002-incidental-coverage/src/math.adb b/testsuite/tests/P614-002-incidental-coverage/src/math.adb index b9a8f15f5..426783d0e 100644 --- a/testsuite/tests/P614-002-incidental-coverage/src/math.adb +++ b/testsuite/tests/P614-002-incidental-coverage/src/math.adb @@ -1,23 +1,23 @@ package body Math is - + N_Adds, N_Mults : Natural := 0; - + procedure Inc (X : in out Integer) is begin X := X + 1; -- # inc end; - + function Eval (Op : Binop_T; X, Y : Integer) return Integer is begin if Op = Add then -- # check-add Inc (N_Adds); -- # add return X + Y; -- # add end if; - + if Op = Mult then -- # check-mult Inc (N_Mults); -- # mult return X * Y; -- # mult end if; end; - + end; diff --git a/testsuite/tests/P614-002-incidental-coverage/src/math.ads b/testsuite/tests/P614-002-incidental-coverage/src/math.ads index 60b26c3bb..f9dbfa318 100644 --- a/testsuite/tests/P614-002-incidental-coverage/src/math.ads +++ b/testsuite/tests/P614-002-incidental-coverage/src/math.ads @@ -1,6 +1,5 @@ package Math is - - type Binop_T is (Add, Mult); + + type Binop_T is (Add, Mult); function Eval (Op : Binop_T; X, Y : Integer) return Integer; end; - diff --git a/testsuite/tests/P614-002-incidental-coverage/src/test_add.adb b/testsuite/tests/P614-002-incidental-coverage/src/test_add.adb index ac03eb57b..413f54770 100644 --- a/testsuite/tests/P614-002-incidental-coverage/src/test_add.adb +++ b/testsuite/tests/P614-002-incidental-coverage/src/test_add.adb @@ -11,4 +11,3 @@ end; -- /add/ l+ ## 0 -- /check-mult/ l- ## s- -- /mult/ l- ## s- - diff --git a/testsuite/tests/P614-002-incidental-coverage/src/test_area.adb b/testsuite/tests/P614-002-incidental-coverage/src/test_area.adb index a31d1e2a4..17127bb77 100644 --- a/testsuite/tests/P614-002-incidental-coverage/src/test_area.adb +++ b/testsuite/tests/P614-002-incidental-coverage/src/test_area.adb @@ -13,4 +13,3 @@ end; --# maps.adb -- /eval/ l+ ## 0 - diff --git a/testsuite/tests/P622-010-stack-restore/src/test_n.adb b/testsuite/tests/P622-010-stack-restore/src/test_n.adb index c8ae8d6c8..02152c474 100644 --- a/testsuite/tests/P622-010-stack-restore/src/test_n.adb +++ b/testsuite/tests/P622-010-stack-restore/src/test_n.adb @@ -12,4 +12,3 @@ end Test_N; -- /second-cond/ l! ## dF- -- /second-stmt/ l+ ## 0 -- /third-stmt/ l- ## s- - diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.adb b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.adb index 255375ede..7641add3d 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.adb +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.adb @@ -1,16 +1,16 @@ package body P1 is - + function F1 (A, B : Boolean) return Boolean; pragma Inline (F1); - + function F1 (A, B : Boolean) return Boolean is begin return A and then B; -- # and end; - + procedure Combine (A, B, C : Boolean) is begin R := F1 (A, B) or else C; -- # or end; - + end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.ads b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.ads index 2136ace3d..43fce56ab 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.ads +++ b/testsuite/tests/PA25-046-inlined-in-decision/AB_C/src/p1.ads @@ -1,14 +1,14 @@ package P1 is - + R : Boolean; - + procedure Combine (A, B, C : Boolean); - + -- A B and C R -- 1 F X F F F -- 2 T F F F F -- 3 T T T X T - + -- 4 F X F T T -- 5 T F F T T diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.adb index 6636563f7..bef749e58 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.adb +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.adb @@ -1,13 +1,13 @@ package body P1 is - + function Orelse (B, C : Boolean) return Boolean is begin return B or else C; -- # or end; - + procedure Combine (A, B, C, D : Boolean) is begin R := A and then Orelse (B, C) and then D; -- # comb end; - + end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.ads b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.ads index dfa12fbd6..a31d580ed 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.ads +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_BC_D/src/p1.ads @@ -1,12 +1,12 @@ package P1 is - + R : Boolean; - + function Orelse (B, C : Boolean) return Boolean; pragma Inline (Orelse); procedure Combine (A, B, C, D : Boolean); - + -- A && (B C or) && D R -- 1 F X X X X F -- 2 T T X T F F diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.adb b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.adb index 1e20557ed..8cc2c424d 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.adb +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.adb @@ -1,10 +1,10 @@ with Twisters; use Twisters; package body P1 is - + procedure Andthen (A, B, C : Boolean) is begin R := A and then Identity (B) and then C; -- # comb end; - + end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.ads b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.ads index 1c4fbfc28..954b6d250 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.ads +++ b/testsuite/tests/PA25-046-inlined-in-decision/A_B_C/src/p1.ads @@ -1,9 +1,9 @@ package P1 is - + R : Boolean; - + procedure Andthen (A, B, C : Boolean); - + -- A B C R -- 1 T T T T -- 2 T T F F diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.adb index f9655952f..0434f60cb 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.adb +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.adb @@ -1,13 +1,13 @@ package body P2 is - + function F2 (X : Integer) return Boolean; pragma Inline (F2); - + function F2 (X : Integer) return Boolean is begin return CX + X > 10; -- # comp end; - + procedure Combine (C : Boolean; X : Integer) is begin R := C or else F2 (X); -- # or diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.ads b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.ads index f79a4628f..78394987d 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.ads +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/p2.ads @@ -2,10 +2,10 @@ package P2 is R : Boolean; CX : Integer := 0; procedure Combine (C : Boolean; X : Integer); - + -- V# C X>10 R -- 1 F F F -- 2 F T T -- 3 T X T - + end; diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_0.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_0.adb index d515c91ee..82b6a095e 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_0.adb +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_0.adb @@ -8,4 +8,3 @@ end; --# p2.adb -- /or/ l- ## s- -- /comp/ l- ## s- - diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_1.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_1.adb index f2e5d859a..6acf8892a 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_1.adb +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_1.adb @@ -9,4 +9,3 @@ end; --# p2.adb -- /or/ l! ## eT- -- /comp/ l+ ## 0 - diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_12.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_12.adb index 015af4a08..1779292ff 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_12.adb +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_12.adb @@ -11,4 +11,3 @@ end; --# p2.adb -- /or/ l! ## c!:"C" -- /comp/ l+ ## 0 - diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_123.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_123.adb index 1e277afd8..ad533f240 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_123.adb +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_123.adb @@ -15,4 +15,3 @@ end; --# p2.adb -- /or/ l+ ## 0 -- /comp/ l+ ## 0 - diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_13.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_13.adb index e123eec72..a15765fca 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_13.adb +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_13.adb @@ -13,4 +13,3 @@ end; --# p2.adb -- /or/ l! ## c!:"F2" -- /comp/ l+ ## 0 - diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_2.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_2.adb index 779c07951..86a26d314 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_2.adb +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_2.adb @@ -9,4 +9,3 @@ end; --# p2.adb -- /or/ l! ## eF- -- /comp/ l+ ## 0 - diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_23.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_23.adb index b8e9ab83c..203b52de2 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_23.adb +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_23.adb @@ -13,4 +13,3 @@ end; --# p2.adb -- /or/ l! ## eF- -- /comp/ l+ ## 0 - diff --git a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_3.adb b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_3.adb index 5a57d0d1a..3be63b795 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_3.adb +++ b/testsuite/tests/PA25-046-inlined-in-decision/C_X/src/test_3.adb @@ -10,4 +10,3 @@ end; --# p2.adb -- /or/ l! ## eF- -- /comp/ l- ## s- - diff --git a/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.ads b/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.ads index cd81c9b36..8aac806c3 100644 --- a/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.ads +++ b/testsuite/tests/PA25-046-inlined-in-decision/src/twisters.ads @@ -1,7 +1,7 @@ package Twisters is - + function Identity (B : Boolean) return Boolean; - + -- We really care about inlining in the middle of decisions -- in this series of tests, so: pragma Inline_Always (Identity); diff --git a/testsuite/tests/Q414-016-task-accept/test.opt b/testsuite/tests/Q414-016-task-accept/test.opt index 006a31f27..0955f0fce 100644 --- a/testsuite/tests/Q414-016-task-accept/test.opt +++ b/testsuite/tests/Q414-016-task-accept/test.opt @@ -1,2 +1,2 @@ -RTS_FULL +RTS_FULL ALL DEAD diff --git a/testsuite/tests/QA23-039-nocode-pragmas/p2.ads b/testsuite/tests/QA23-039-nocode-pragmas/p2.ads index e0b3838d3..74423c643 100644 --- a/testsuite/tests/QA23-039-nocode-pragmas/p2.ads +++ b/testsuite/tests/QA23-039-nocode-pragmas/p2.ads @@ -1,4 +1,4 @@ package P2 is - pragma Pure; + pragma Pure; type Int is new Integer; end; diff --git a/testsuite/tests/QA23-039-nocode-pragmas/p3.ads b/testsuite/tests/QA23-039-nocode-pragmas/p3.ads index 1c1d57821..caeebd3bd 100644 --- a/testsuite/tests/QA23-039-nocode-pragmas/p3.ads +++ b/testsuite/tests/QA23-039-nocode-pragmas/p3.ads @@ -2,4 +2,3 @@ package P3 is pragma Pure; type Int is new Integer; end; - diff --git a/testsuite/tests/R417-010-scope-metrics/test.opt b/testsuite/tests/R417-010-scope-metrics/test.opt index 079fe371b..e74976535 100644 --- a/testsuite/tests/R417-010-scope-metrics/test.opt +++ b/testsuite/tests/R417-010-scope-metrics/test.opt @@ -1,4 +1,4 @@ bin-traces DEAD no support for body metrics with binary traces RTS_ZFP DEAD no tasking support in light runtimes RTS_RAVENSCAR DEAD violates restrictions in the Jorvik profile -5.04a1 DEAD Requires Ada 2012, unavailable in 5.04a1 \ No newline at end of file +5.04a1 DEAD Requires Ada 2012, unavailable in 5.04a1 diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.ads b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.ads index c24d2fc66..a7202229b 100644 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.ads +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/src/subp.ads @@ -1,7 +1,7 @@ package SubP is function func (x: integer) return integer; - + My_Error: Exception; end SubP; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/elab.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/elab.adb index ec0e62ba6..e0b29a379 100644 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/elab.adb +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/src/elab.adb @@ -16,7 +16,7 @@ procedure Elab (Val: Integer) is begin declare - X : integer ; -- # decl + X : integer ; -- # decl package Pack is I : integer range 2..10 := func(Val); -- # implicit_violation end Pack; diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/div.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/div.adb index fd7f6ff89..83db74df1 100644 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/div.adb +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/src/div.adb @@ -1,6 +1,6 @@ package body Div is procedure Divide (X, Y: Integer; Res: out Integer) is - begin + begin if Y = 0 then -- # explicit_check raise My_Constraint_Error; -- # explicit_raise else diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.adb index 070ad9152..063d2c575 100644 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.adb +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/cond_raise.adb @@ -1,11 +1,11 @@ package body Cond_Raise is - + procedure Raise_If (Cond : Boolean) is begin if Cond then -- # test_cond N_Raise := N_Raise + 1; -- # raise raise Constraint_Error; -- # raise - + -- Repeating # raise is done on purpose here, to let -- test drivers designate the set of lines/statements -- that all get to execute or not depending on Cond. @@ -22,5 +22,3 @@ package body Cond_Raise is N_In_Handler := N_In_Handler + 1; -- # in_handler end; end; - - diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_t.adb b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_t.adb index 9a914a282..71bdc398d 100644 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_t.adb +++ b/testsuite/tests/Ravenscar/Exceptions/stmt/example/src/test_cond_t.adb @@ -3,22 +3,22 @@ with Support, Cond_Raise; use Support; procedure Test_Cond_T is begin Cond_Raise.Check_For (Cond => True); - + -- We called once only, raising. So ... - + -- We raised and went into the exception handler once - + Assert (Cond_Raise.N_Raise = 1); Assert (Cond_Raise.N_In_Handler = 1); - + -- We never reached the code past the test deciding if we should raise -- (which we only reach when we call the function without raising). -- Likewise for the code past the inner call, skipped by the exception -- propagation. - + Assert (Cond_Raise.N_Past_Test = 0); Assert (Cond_Raise.N_Past_Call = 0); - + end; -- Expectations on =xcov and =report coverage outcome follow. Note the single diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/check_class_wide_condition.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/check_class_wide_condition.adb index c72db9fed..a0b57586a 100755 --- a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/check_class_wide_condition.adb +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/check_class_wide_condition.adb @@ -30,6 +30,3 @@ exception when Constraint_Error => Result := 0; -- # exc end Check_Class_Wide_Condition; - - - diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ft.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ft.adb index 9dfbd855f..8148e3efe 100755 --- a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ft.adb +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_ft.adb @@ -41,11 +41,3 @@ end Test_FT; -- /true/ l+ ## 0 -- /false/ l+ ## 0 -- /exc/ l- ## s- - - - - - - - - diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_t.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_t.adb index 2333961a0..7bf0914a0 100755 --- a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_t.adb +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Class_Wide_Condition/src/test_t.adb @@ -34,4 +34,3 @@ end Test_T; -- /true/ l+ ## 0 -- /false/ l- ## s- -- /exc/ l- ## s- - diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/check_dispatching_condition.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/check_dispatching_condition.adb index ac63bd866..29b9255d3 100755 --- a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/check_dispatching_condition.adb +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/check_dispatching_condition.adb @@ -30,6 +30,3 @@ exception when Constraint_Error => Result := 0; -- # exc end Check_Dispatching_Condition; - - - diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ft.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ft.adb index de8982998..6acc7e4f4 100755 --- a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ft.adb +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_ft.adb @@ -39,11 +39,3 @@ end Test_FT; -- /true/ l+ ## 0 -- /false/ l+ ## 0 -- /exc/ l- ## s- - - - - - - - - diff --git a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_t.adb b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_t.adb index a9b20e428..96a3f722b 100755 --- a/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_t.adb +++ b/testsuite/tests/Ravenscar/OOP/decision/Core_Example/Dispatching_Condition/src/test_t.adb @@ -33,4 +33,3 @@ end Test_T; -- /true/ l+ ## 0 -- /false/ l- ## s- -- /exc/ l- ## s- - diff --git a/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.adb b/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.adb index 44f4179a8..b2b94b92a 100755 --- a/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.adb +++ b/testsuite/tests/Ravenscar/OOP/src/class_wide_ops.adb @@ -4,4 +4,3 @@ package body Class_Wide_Ops is Handle (A); end Handle_Alert; end; - diff --git a/testsuite/tests/Ravenscar/OOP/src/new_alert_system-objects.ads b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-objects.ads index 468c6b816..b1d96efa9 100755 --- a/testsuite/tests/Ravenscar/OOP/src/new_alert_system-objects.ads +++ b/testsuite/tests/Ravenscar/OOP/src/new_alert_system-objects.ads @@ -12,4 +12,3 @@ package New_Alert_System.Objects is Empty_High_Alert : High_Alert := High_Alert'(Empty_Medium_Alert with Ring_Alarm_At => Zero_Time); end New_Alert_System.Objects; - diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.adb b/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.adb index bc164c88d..09e515f5e 100644 --- a/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.adb +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.adb @@ -1,18 +1,18 @@ package body Blocks_By_Tasks is First_Block, Second_Block, Third_Block : Boolean := False; - + task body Processing is begin -- Block to be covered by instances of type Block1 if Kind = Block1 then -- # blk1_tst First_Block := True; -- # blk1_stmt end if; - + -- Block to be covered by instances of type Block2 if Kind = Block2 then -- # blk2_tst Second_Block := True; -- # blk2_stmt end if; - + -- Block to be covered by instances of type Block3, but none -- created in this test case. if Kind = Block3 then -- # blk3_tst diff --git a/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.ads b/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.ads index c36af64dd..4d3516581 100644 --- a/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.ads +++ b/testsuite/tests/Ravenscar/Tasking/TaskTypes/src/blocks_by_tasks.ads @@ -9,11 +9,11 @@ with System; package Blocks_By_Tasks is type Task_Kind is (Block1, Block2, Block3); - + task type Processing (Kind : Task_Kind) is pragma Priority (System.Priority'Last); end Processing; - + T1 : Processing (Block1); T2 : Processing (Block2); end Blocks_By_Tasks; diff --git a/testsuite/tests/Ravenscar/example0/src/sync.ads b/testsuite/tests/Ravenscar/example0/src/sync.ads index ebf12aa65..94ff96169 100644 --- a/testsuite/tests/Ravenscar/example0/src/sync.ads +++ b/testsuite/tests/Ravenscar/example0/src/sync.ads @@ -46,4 +46,3 @@ package Sync is -- then True. end; - diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_null.adb b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_null.adb index dcd8fb752..11b135a3b 100644 --- a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_null.adb +++ b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_null.adb @@ -31,4 +31,3 @@ end Test_Engines_Null; -- /eval/ l- ## s- -- /true/ l- ## s- -- /false/ l- ## s- - diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_stable.adb b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_stable.adb index 31f0e574e..5e35e3d3d 100644 --- a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_stable.adb +++ b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_stable.adb @@ -32,4 +32,3 @@ end Test_Engines_Stable; -- /eval/ l! ## dF- -- /true/ l+ ## 0 -- /false/ l- ## s- - diff --git a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_unstable.adb b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_unstable.adb index d78f01a20..fb6d2e924 100644 --- a/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_unstable.adb +++ b/testsuite/tests/SanityCheck/decision/Engines/src/test_engines_unstable.adb @@ -32,4 +32,3 @@ end Test_Engines_Unstable; -- /eval/ l! ## dT- -- /true/ l- ## s- -- /false/ l+ ## 0 - diff --git a/testsuite/tests/T117-007-intf-thunks/src/action.ads b/testsuite/tests/T117-007-intf-thunks/src/action.ads index 1c21b6ec7..39411d52a 100644 --- a/testsuite/tests/T117-007-intf-thunks/src/action.ads +++ b/testsuite/tests/T117-007-intf-thunks/src/action.ads @@ -1,14 +1,14 @@ package Action is type T_Action is abstract tagged private; - + type T_NA_Action_Class is not null access all T_Action'Class; - + procedure Init (Obj : in out T_Action) is abstract; - + procedure Run (Obj : in out T_Action) is abstract; - -private + +private type T_Action is abstract tagged null record; - + end Action; diff --git a/testsuite/tests/T117-007-intf-thunks/src/interface_a.ads b/testsuite/tests/T117-007-intf-thunks/src/interface_a.ads index 99aa47802..b91fc2584 100644 --- a/testsuite/tests/T117-007-intf-thunks/src/interface_a.ads +++ b/testsuite/tests/T117-007-intf-thunks/src/interface_a.ads @@ -1,9 +1,9 @@ package Interface_A is type T_Interface_A is interface; - + function Get_Variable (This : in T_Interface_A) return Integer is abstract; - + type T_A_Interface_A_Class is access all T_Interface_A'Class; - + end Interface_A; diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test-sep.adb b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test-sep.adb index f1fbfac5a..8dfff4a05 100644 --- a/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test-sep.adb +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/pkg-test-sep.adb @@ -3,4 +3,4 @@ with Ada.Text_IO; use Ada.Text_IO; separate (pkg.test) procedure Sep is begin Put_Line("This double separate is super useless!"); -end Sep; \ No newline at end of file +end Sep; diff --git a/testsuite/tests/TA14-011-show-mcdc-vectors/main.adb b/testsuite/tests/TA14-011-show-mcdc-vectors/main.adb index 6e6dc8c9b..801b5e835 100644 --- a/testsuite/tests/TA14-011-show-mcdc-vectors/main.adb +++ b/testsuite/tests/TA14-011-show-mcdc-vectors/main.adb @@ -7,4 +7,4 @@ begin Mystery (True, True, False); Other_Proc (True, True); Other_Proc (False, True); -end Main; \ No newline at end of file +end Main; diff --git a/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.adb b/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.adb index 8151a7c53..4febbe7fe 100644 --- a/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.adb +++ b/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.adb @@ -23,4 +23,4 @@ package body Pkg is Put_Line ("not Stuff"); end if; end Other_Proc; -end Pkg; \ No newline at end of file +end Pkg; diff --git a/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.ads b/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.ads index 6d0f7ef24..c5528490a 100644 --- a/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.ads +++ b/testsuite/tests/TA14-011-show-mcdc-vectors/pkg.ads @@ -3,4 +3,4 @@ package Pkg is procedure Mystery (A, B, C : Boolean); procedure Other_Proc (A, B : Boolean); -end Pkg; \ No newline at end of file +end Pkg; diff --git a/testsuite/tests/TC03-012-objcov-line-state/main.c b/testsuite/tests/TC03-012-objcov-line-state/main.c index 54a207666..6c9ca81b7 100644 --- a/testsuite/tests/TC03-012-objcov-line-state/main.c +++ b/testsuite/tests/TC03-012-objcov-line-state/main.c @@ -13,4 +13,4 @@ int main () { return add_n (0, 0); -} \ No newline at end of file +} diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_1.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_1.adb index b150ed2fc..28d252535 100644 --- a/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_1.adb +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_1.adb @@ -6,4 +6,4 @@ procedure Disjoint_Main_1 is begin Put_Line ("Pkg1.Fn1 (True) :" & Integer'Image (Pkg1.Fn1 (True))); Put_Line ("Pkg1.Fn1 (False):" & Integer'Image (Pkg1.Fn1 (False))); -end Disjoint_Main_1; \ No newline at end of file +end Disjoint_Main_1; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_2.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_2.adb index d950ac46f..aafdcb2c7 100644 --- a/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_2.adb +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/disjoint_main_2.adb @@ -6,4 +6,4 @@ procedure Disjoint_Main_2 is begin Put_Line ("Pkg2.Fn2 (True) :" & Integer'Image (Pkg2.Fn2 (True))); Put_Line ("Pkg2.Fn2 (False):" & Integer'Image (Pkg2.Fn2 (False))); -end Disjoint_Main_2; \ No newline at end of file +end Disjoint_Main_2; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_1.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_1.adb index 9fd15ef6e..e1dc8d141 100644 --- a/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_1.adb +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_1.adb @@ -7,4 +7,4 @@ procedure Intersecting_Main_1 is begin Put_Line ("Pkg1.Fn1 (True):" & Integer'Image (Pkg1.Fn1 (True))); Put_Line ("Pkg2.Fn2 (True):" & Integer'Image (Pkg2.Fn2 (True))); -end Intersecting_Main_1; \ No newline at end of file +end Intersecting_Main_1; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_2.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_2.adb index ac77f98a1..41dc08b6f 100644 --- a/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_2.adb +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/intersecting_main_2.adb @@ -7,4 +7,4 @@ procedure Intersecting_Main_2 is begin Put_Line ("Pkg1.Fn1 (False):" & Integer'Image (Pkg1.Fn1 (False))); Put_Line ("Pkg2.Fn2 (False):" & Integer'Image (Pkg2.Fn2 (False))); -end Intersecting_Main_2; \ No newline at end of file +end Intersecting_Main_2; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.adb index 839be84f5..b7e0017f6 100644 --- a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.adb +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.adb @@ -12,4 +12,4 @@ package body Pkg1 is end if; end Fn1; -end Pkg1; \ No newline at end of file +end Pkg1; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.ads b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.ads index 9568ad0c6..783fd6d06 100644 --- a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.ads +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg1.ads @@ -2,4 +2,4 @@ package Pkg1 is function Fn1 (B : Boolean) return Integer; -end Pkg1; \ No newline at end of file +end Pkg1; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.adb b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.adb index dd261a064..ee78667d7 100644 --- a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.adb +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.adb @@ -12,4 +12,4 @@ package body Pkg2 is end if; end Fn2; -end Pkg2; \ No newline at end of file +end Pkg2; diff --git a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.ads b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.ads index f4f9f7b07..e4be9ad20 100644 --- a/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.ads +++ b/testsuite/tests/U204-029-source-rebase/Ada/src/pkg2.ads @@ -2,4 +2,4 @@ package Pkg2 is function Fn2 (B : Boolean) return Integer; -end Pkg2; \ No newline at end of file +end Pkg2; diff --git a/testsuite/tests/U208-020-child-project/test.opt b/testsuite/tests/U208-020-child-project/test.opt index e42397385..796388e67 100644 --- a/testsuite/tests/U208-020-child-project/test.opt +++ b/testsuite/tests/U208-020-child-project/test.opt @@ -1 +1 @@ -bin-traces DEAD Check instrumentation-specific behavior \ No newline at end of file +bin-traces DEAD Check instrumentation-specific behavior diff --git a/testsuite/tests/U208-020-unique-language-project/test.opt b/testsuite/tests/U208-020-unique-language-project/test.opt index e42397385..796388e67 100644 --- a/testsuite/tests/U208-020-unique-language-project/test.opt +++ b/testsuite/tests/U208-020-unique-language-project/test.opt @@ -1 +1 @@ -bin-traces DEAD Check instrumentation-specific behavior \ No newline at end of file +bin-traces DEAD Check instrumentation-specific behavior diff --git a/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt index 843545d10..1a80636a9 100644 --- a/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt +++ b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.opt @@ -1,2 +1,2 @@ !native DEAD Uses full runtime only constructs -RTS_ZFP DEAD Uses full runtime only constructs \ No newline at end of file +RTS_ZFP DEAD Uses full runtime only constructs diff --git a/testsuite/tests/U630-040-static-decision/test.opt b/testsuite/tests/U630-040-static-decision/test.opt index 0635bc667..677ea7107 100644 --- a/testsuite/tests/U630-040-static-decision/test.opt +++ b/testsuite/tests/U630-040-static-decision/test.opt @@ -1,2 +1,2 @@ 5.04a1 DEAD Missing feature (if expression) in GNAT 5.04 -7.1.2 DEAD expression functions support weak in GNAT 7.1.2 \ No newline at end of file +7.1.2 DEAD expression functions support weak in GNAT 7.1.2 diff --git a/testsuite/tests/U811-028-suppress-output/main.adb b/testsuite/tests/U811-028-suppress-output/main.adb index e55ea674d..d9f3b70c2 100644 --- a/testsuite/tests/U811-028-suppress-output/main.adb +++ b/testsuite/tests/U811-028-suppress-output/main.adb @@ -11,4 +11,4 @@ procedure Main is begin Res := Bool1 or else Bool2; -end Main; \ No newline at end of file +end Main; diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.adb b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.adb index 832e755c2..a04188dff 100644 --- a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.adb +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.adb @@ -10,4 +10,4 @@ package body Pkg is begin Ret_Val := A or else C; -- # elab_body -end Pkg; \ No newline at end of file +end Pkg; diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.ads b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.ads index 5d5d8bc1f..2eb2d106e 100644 --- a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.ads +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkg.ads @@ -10,4 +10,4 @@ package Pkg is C : Boolean := A and then B; -- # elab_spec pragma Volatile (C); -end Pkg; \ No newline at end of file +end Pkg; diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.adb b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.adb index 366dca18b..29a585e49 100644 --- a/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.adb +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/pkh.adb @@ -9,4 +9,4 @@ package body Pkh is begin return Inner_Bar.Res_Val; end Bar; -end Pkh; \ No newline at end of file +end Pkh; diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/src/test_elab.adb b/testsuite/tests/UA21-030-elab_mcdc_state/src/test_elab.adb index c854c3e0e..29a516ce3 100644 --- a/testsuite/tests/UA21-030-elab_mcdc_state/src/test_elab.adb +++ b/testsuite/tests/UA21-030-elab_mcdc_state/src/test_elab.adb @@ -25,4 +25,4 @@ end Test_Elab; --# pkh.adb -- --- /elab_fun/ l! ## eT- \ No newline at end of file +-- /elab_fun/ l! ## eT- diff --git a/testsuite/tests/V520-019-duplicate-messages/main.adb b/testsuite/tests/V520-019-duplicate-messages/main.adb index 572bd9f46..dadf3e517 100644 --- a/testsuite/tests/V520-019-duplicate-messages/main.adb +++ b/testsuite/tests/V520-019-duplicate-messages/main.adb @@ -5,4 +5,4 @@ procedure Main is pragma Volatile (X); begin null; -end Main; \ No newline at end of file +end Main; diff --git a/testsuite/tests/V520-019-duplicate-messages/pkg.adb b/testsuite/tests/V520-019-duplicate-messages/pkg.adb index 795d346c6..2959d2732 100644 --- a/testsuite/tests/V520-019-duplicate-messages/pkg.adb +++ b/testsuite/tests/V520-019-duplicate-messages/pkg.adb @@ -10,4 +10,4 @@ package body Pkg is return 2; end Bar; -end Pkg; \ No newline at end of file +end Pkg; diff --git a/testsuite/tests/V520-019-duplicate-messages/pkg.ads b/testsuite/tests/V520-019-duplicate-messages/pkg.ads index 51f8bdaa4..93de195e9 100644 --- a/testsuite/tests/V520-019-duplicate-messages/pkg.ads +++ b/testsuite/tests/V520-019-duplicate-messages/pkg.ads @@ -4,4 +4,4 @@ package Pkg is function Bar return Integer; -end Pkg; \ No newline at end of file +end Pkg; diff --git a/testsuite/tests/VB07-015-clean-output-dir/main.adb b/testsuite/tests/VB07-015-clean-output-dir/main.adb index a628319b4..1f2932234 100644 --- a/testsuite/tests/VB07-015-clean-output-dir/main.adb +++ b/testsuite/tests/VB07-015-clean-output-dir/main.adb @@ -5,4 +5,4 @@ procedure Main is pragma Volatile (X); begin X := Ident (X); -end Main; \ No newline at end of file +end Main; diff --git a/testsuite/tests/VB07-015-clean-output-dir/pkg.adb b/testsuite/tests/VB07-015-clean-output-dir/pkg.adb index 9cdf868ac..7a73f74bb 100644 --- a/testsuite/tests/VB07-015-clean-output-dir/pkg.adb +++ b/testsuite/tests/VB07-015-clean-output-dir/pkg.adb @@ -5,4 +5,4 @@ package body Pkg is return X; end Ident; -end Pkg; \ No newline at end of file +end Pkg; diff --git a/testsuite/tests/VB07-015-clean-output-dir/pkg.ads b/testsuite/tests/VB07-015-clean-output-dir/pkg.ads index 1cca38ca0..9ff0e430a 100644 --- a/testsuite/tests/VB07-015-clean-output-dir/pkg.ads +++ b/testsuite/tests/VB07-015-clean-output-dir/pkg.ads @@ -2,4 +2,4 @@ package Pkg is function Ident (X : Integer) return Integer; -end Pkg; \ No newline at end of file +end Pkg; diff --git a/testsuite/tests/VC19-001-origin-prj/src_code/code.adb b/testsuite/tests/VC19-001-origin-prj/src_code/code.adb index ea73d4fcf..bbea9e083 100644 --- a/testsuite/tests/VC19-001-origin-prj/src_code/code.adb +++ b/testsuite/tests/VC19-001-origin-prj/src_code/code.adb @@ -3,4 +3,4 @@ package body Code is begin return X and then Y; end Compute; -end Code; \ No newline at end of file +end Code; diff --git a/testsuite/tests/VC19-001-origin-prj/src_code/code.ads b/testsuite/tests/VC19-001-origin-prj/src_code/code.ads index 1a2201fcc..22be3a035 100644 --- a/testsuite/tests/VC19-001-origin-prj/src_code/code.ads +++ b/testsuite/tests/VC19-001-origin-prj/src_code/code.ads @@ -1,3 +1,3 @@ package Code is function Compute (X : Boolean; Y : Boolean) return Boolean; -end Code; \ No newline at end of file +end Code; diff --git a/testsuite/tests/VC19-001-origin-prj/src_test/test_main.adb b/testsuite/tests/VC19-001-origin-prj/src_test/test_main.adb index 928bae60f..afd28330d 100644 --- a/testsuite/tests/VC19-001-origin-prj/src_test/test_main.adb +++ b/testsuite/tests/VC19-001-origin-prj/src_test/test_main.adb @@ -9,4 +9,4 @@ procedure Test_Main is end Assert; begin Assert (Code.Compute (True, False) = Code.Compute (False, True)); -end Test_Main; \ No newline at end of file +end Test_Main; diff --git a/testsuite/tests/asm-consolidate/src/lib.adb b/testsuite/tests/asm-consolidate/src/lib.adb index a7746fee5..ad617e158 100644 --- a/testsuite/tests/asm-consolidate/src/lib.adb +++ b/testsuite/tests/asm-consolidate/src/lib.adb @@ -1,11 +1,11 @@ package body Lib is - + -- We will be checking full object coverage by just exercising the source -- condition True and False. Possible overflow checks are not part of the -- goal. - + pragma Suppress (All_Checks); - + procedure Adjust (X : in out Integer) is begin if X > 0 then @@ -14,6 +14,5 @@ package body Lib is X := X + 1; end if; end; - + end; - diff --git a/testsuite/tests/asm-consolidate/src/lib.ads b/testsuite/tests/asm-consolidate/src/lib.ads index 53dc12ae1..b1937e167 100644 --- a/testsuite/tests/asm-consolidate/src/lib.ads +++ b/testsuite/tests/asm-consolidate/src/lib.ads @@ -1,6 +1,5 @@ package Lib is - + procedure Adjust (X : in out Integer); - + end; - diff --git a/testsuite/tests/asm-consolidate/src/p1.adb b/testsuite/tests/asm-consolidate/src/p1.adb index c7bb84eea..ed9b0a062 100644 --- a/testsuite/tests/asm-consolidate/src/p1.adb +++ b/testsuite/tests/asm-consolidate/src/p1.adb @@ -7,5 +7,3 @@ begin Stuff1.Run; Lib.Adjust (X); end; - - diff --git a/testsuite/tests/asm-consolidate/src/p2.adb b/testsuite/tests/asm-consolidate/src/p2.adb index 29290cf96..029ffe337 100644 --- a/testsuite/tests/asm-consolidate/src/p2.adb +++ b/testsuite/tests/asm-consolidate/src/p2.adb @@ -5,5 +5,3 @@ procedure P2 is begin Lib.Adjust (X); end; - - diff --git a/testsuite/tests/branch-cond/IB11-006-compare-floats/inrange.adb b/testsuite/tests/branch-cond/IB11-006-compare-floats/inrange.adb index e3614a0fd..0a3c7b965 100644 --- a/testsuite/tests/branch-cond/IB11-006-compare-floats/inrange.adb +++ b/testsuite/tests/branch-cond/IB11-006-compare-floats/inrange.adb @@ -2,4 +2,3 @@ function Inrange (L, H, X : Float) return Boolean is begin return X >= L and then X <= H; end; - diff --git a/testsuite/tests/branch-cond/IB12-008-postcond/checkx.adb b/testsuite/tests/branch-cond/IB12-008-postcond/checkx.adb index 7f7e0cacd..fe16c8920 100644 --- a/testsuite/tests/branch-cond/IB12-008-postcond/checkx.adb +++ b/testsuite/tests/branch-cond/IB12-008-postcond/checkx.adb @@ -3,4 +3,3 @@ procedure CheckX (X : Integer) is begin null; end; - diff --git a/testsuite/tests/branch-cond/IB12-016-lone-not/eval_not.adb b/testsuite/tests/branch-cond/IB12-016-lone-not/eval_not.adb index bbbee6891..95f7ef86e 100644 --- a/testsuite/tests/branch-cond/IB12-016-lone-not/eval_not.adb +++ b/testsuite/tests/branch-cond/IB12-016-lone-not/eval_not.adb @@ -1,7 +1,6 @@ procedure Eval_Not (A : Boolean; E : out Boolean) is - Ain : Boolean; + Ain : Boolean; begin Ain := A; E := not A; end; - diff --git a/testsuite/tests/branch-cond/IB12-016-lone-not/not_if.adb b/testsuite/tests/branch-cond/IB12-016-lone-not/not_if.adb index ca73380f5..ee25e03ef 100644 --- a/testsuite/tests/branch-cond/IB12-016-lone-not/not_if.adb +++ b/testsuite/tests/branch-cond/IB12-016-lone-not/not_if.adb @@ -6,4 +6,3 @@ begin return not A; end if; end; - diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.adb b/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.adb index 1b15a477c..760b49109 100644 --- a/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.adb +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/checkx.adb @@ -2,5 +2,3 @@ procedure Checkx (X : Float) is begin null; end; - - diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/services.ads b/testsuite/tests/branch-cond/IB15-004-spec-precond/services.ads index f8e5fdd6f..f93c45232 100644 --- a/testsuite/tests/branch-cond/IB15-004-spec-precond/services.ads +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/services.ads @@ -4,5 +4,3 @@ package Services is procedure CheckN (N : T); pragma Precondition (N > 1.0); end; - - diff --git a/testsuite/tests/branch-cond/IB20-015-length-check/starts.adb b/testsuite/tests/branch-cond/IB20-015-length-check/starts.adb index 0d5ca483c..1572eabf1 100644 --- a/testsuite/tests/branch-cond/IB20-015-length-check/starts.adb +++ b/testsuite/tests/branch-cond/IB20-015-length-check/starts.adb @@ -3,4 +3,3 @@ begin return Key'Length = 3 and then S (S'First .. S'First + Key'Length) = "abc"; -- # contents end; - diff --git a/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.ads b/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.ads index 73716d9bb..de21623a7 100644 --- a/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.ads +++ b/testsuite/tests/branch-cond/IB20-027-addr-compare/regions.ads @@ -7,5 +7,3 @@ package Regions is procedure Check (R : Region); end; - - diff --git a/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.ads b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.ads index e5a493d1f..7b32564f9 100644 --- a/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.ads +++ b/testsuite/tests/branch-cond/IB25-022-shortcut-actions/services.ads @@ -8,4 +8,3 @@ package Services is procedure Check_Addr_And (This : Str_Type); procedure Check_Addr_Or (This : Str_Type); end; - diff --git a/testsuite/tests/branch-cond/IC01-032-itype-early-elab/starts.adb b/testsuite/tests/branch-cond/IC01-032-itype-early-elab/starts.adb index 56d6fa64e..179a728d3 100644 --- a/testsuite/tests/branch-cond/IC01-032-itype-early-elab/starts.adb +++ b/testsuite/tests/branch-cond/IC01-032-itype-early-elab/starts.adb @@ -3,4 +3,3 @@ begin return Key'Length <= S'Length -- # startsLength and then S (S'First .. S'First + Key'Length - 1) = Key; -- # startsKey end; - diff --git a/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.adb b/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.adb index 1127677ca..b652ea895 100644 --- a/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.adb +++ b/testsuite/tests/branch-cond/IC02-020-shortcut-action/check.adb @@ -14,4 +14,3 @@ package body Check is pragma Warnings (On, "index for * may assume lower bound of 1"); end; end; - diff --git a/testsuite/tests/branch-cond/J205-019-and-not/check.adb b/testsuite/tests/branch-cond/J205-019-and-not/check.adb index 25f18ab5d..0cf355595 100644 --- a/testsuite/tests/branch-cond/J205-019-and-not/check.adb +++ b/testsuite/tests/branch-cond/J205-019-and-not/check.adb @@ -2,4 +2,3 @@ function Check (A, B, C : Boolean) return Boolean is begin return A and then not (B and then C); end; - diff --git a/testsuite/tests/branch-cond/J205-019-and-not/foo.adb b/testsuite/tests/branch-cond/J205-019-and-not/foo.adb index f6767dd83..c7bdd5990 100644 --- a/testsuite/tests/branch-cond/J205-019-and-not/foo.adb +++ b/testsuite/tests/branch-cond/J205-019-and-not/foo.adb @@ -2,4 +2,3 @@ function Foo (A, B, C, D : Boolean) return Boolean is begin return A and then B and then (not C and then not D); end; - diff --git a/testsuite/tests/branch-cond/J205-019-and-not/foo2.adb b/testsuite/tests/branch-cond/J205-019-and-not/foo2.adb index 593e2c94f..428cb42ab 100644 --- a/testsuite/tests/branch-cond/J205-019-and-not/foo2.adb +++ b/testsuite/tests/branch-cond/J205-019-and-not/foo2.adb @@ -2,4 +2,3 @@ function Foo2 (A, B, C : Boolean) return Boolean is begin return not A and then (B or else C); end; - diff --git a/testsuite/tests/branch-cond/J205-019-and-not/foo3.adb b/testsuite/tests/branch-cond/J205-019-and-not/foo3.adb index ff2bc34b8..aca4292fc 100644 --- a/testsuite/tests/branch-cond/J205-019-and-not/foo3.adb +++ b/testsuite/tests/branch-cond/J205-019-and-not/foo3.adb @@ -2,4 +2,3 @@ function Foo3 (A, B, C : Boolean) return Boolean is begin return A and then not B and then not C; end; - diff --git a/testsuite/tests/build_run-assert-failure/test.py b/testsuite/tests/build_run-assert-failure/test.py index 4eb60e0ec..76b75cb9d 100644 --- a/testsuite/tests/build_run-assert-failure/test.py +++ b/testsuite/tests/build_run-assert-failure/test.py @@ -40,4 +40,3 @@ thistest = Test() thistest.result() - diff --git a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/pkg_type_invariant.ads b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/pkg_type_invariant.ads index 6cd832c73..92365d4b7 100644 --- a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/pkg_type_invariant.ads +++ b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/pkg_type_invariant.ads @@ -21,4 +21,3 @@ private function Get_Value (R : Bool_Record) return Boolean is (R.B); end Pkg_Type_Invariant; - diff --git a/testsuite/tests/instr-cov/c_custom_naming/test.opt b/testsuite/tests/instr-cov/c_custom_naming/test.opt index 3d918a25a..300e53ef2 100644 --- a/testsuite/tests/instr-cov/c_custom_naming/test.opt +++ b/testsuite/tests/instr-cov/c_custom_naming/test.opt @@ -1 +1 @@ -!C++ DEAD test requires a supported C++ compiler \ No newline at end of file +!C++ DEAD test requires a supported C++ compiler diff --git a/testsuite/tests/instr-cov/c_metaprog/test.opt b/testsuite/tests/instr-cov/c_metaprog/test.opt index eb40c018e..796388e67 100644 --- a/testsuite/tests/instr-cov/c_metaprog/test.opt +++ b/testsuite/tests/instr-cov/c_metaprog/test.opt @@ -1,2 +1 @@ bin-traces DEAD Check instrumentation-specific behavior - diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/test.opt b/testsuite/tests/instr-cov/c_multiline_stmt/test.opt index e42397385..796388e67 100644 --- a/testsuite/tests/instr-cov/c_multiline_stmt/test.opt +++ b/testsuite/tests/instr-cov/c_multiline_stmt/test.opt @@ -1 +1 @@ -bin-traces DEAD Check instrumentation-specific behavior \ No newline at end of file +bin-traces DEAD Check instrumentation-specific behavior diff --git a/testsuite/tests/instr-cov/c_special_filenames/test.opt b/testsuite/tests/instr-cov/c_special_filenames/test.opt index 930d7837e..195e6c2d4 100644 --- a/testsuite/tests/instr-cov/c_special_filenames/test.opt +++ b/testsuite/tests/instr-cov/c_special_filenames/test.opt @@ -1 +1 @@ -!C++ DEAD test requires C++ compiler \ No newline at end of file +!C++ DEAD test requires C++ compiler diff --git a/testsuite/tests/instr-cov/decl-inversion/src/test_foo.adb b/testsuite/tests/instr-cov/decl-inversion/src/test_foo.adb index 3bbf356c2..1b8869efa 100644 --- a/testsuite/tests/instr-cov/decl-inversion/src/test_foo.adb +++ b/testsuite/tests/instr-cov/decl-inversion/src/test_foo.adb @@ -20,4 +20,4 @@ end Test_Foo; --# test_foo.adb -- -- /Integer/ l! ## dF- --- /Expr_Fun/ l+ ## 0 \ No newline at end of file +-- /Expr_Fun/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/decl-inversion/test.opt b/testsuite/tests/instr-cov/decl-inversion/test.opt index 498980ea4..da9fbae6f 100644 --- a/testsuite/tests/instr-cov/decl-inversion/test.opt +++ b/testsuite/tests/instr-cov/decl-inversion/test.opt @@ -1,2 +1,2 @@ 5.04a1 DEAD expression functions not available in 5.04 -7.1.2 DEAD support for expression functions weak in 7.1.2 \ No newline at end of file +7.1.2 DEAD support for expression functions weak in 7.1.2 diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/src/foo.ads index 6ad8edce9..ef861ec6f 100644 --- a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/src/foo.ads +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_no-prespec/src/foo.ads @@ -7,4 +7,4 @@ package Foo is with Pre => N > 0, Post => Fact'Result >= N; -end Foo; \ No newline at end of file +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/src/foo.ads index ee19a0d15..dab0d9b59 100644 --- a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/src/foo.ads +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_asp_prespec/src/foo.ads @@ -9,4 +9,4 @@ package Foo is function Fact (N : Integer) return integer is (if N > 1 then N * (N -1) else N); -- # expr_func -end Foo; \ No newline at end of file +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/src/foo.ads index c9f670ca4..f50a262ad 100644 --- a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/src/foo.ads +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_no-prespec/src/foo.ads @@ -5,4 +5,4 @@ package Foo is function Fact (N : Integer) return integer is (if N > 1 then N * (N -1) else N); -- # expr_func -end Foo; \ No newline at end of file +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/src/foo.ads index 91573ff28..1518fb104 100644 --- a/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/src/foo.ads +++ b/testsuite/tests/instr-cov/expr_func/aspects/no-rec_no-asp_prespec/src/foo.ads @@ -7,4 +7,4 @@ package Foo is function Fact (N : Integer) return integer is (if N > 1 then N * (N -1) else N); -- # expr_func -end Foo; \ No newline at end of file +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/src/foo.ads index 3c0268477..f0bf6ec38 100644 --- a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/src/foo.ads +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/src/foo.ads @@ -7,4 +7,4 @@ package Foo is with Pre => N > 0, Post => Fact'Result >= N; -end Foo; \ No newline at end of file +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.opt b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.opt index 8212a024b..13161be34 100644 --- a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.opt +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.opt @@ -1 +1 @@ -bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. \ No newline at end of file +bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/src/foo.ads index d5246ca11..690f200ad 100644 --- a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/src/foo.ads +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/src/foo.ads @@ -9,4 +9,4 @@ package Foo is function Fact (N : Integer) return integer is (if N > 1 then N * Fact (N -1) else N); -- # expr_func -end Foo; \ No newline at end of file +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.opt b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.opt index 8212a024b..13161be34 100644 --- a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.opt +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.opt @@ -1 +1 @@ -bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. \ No newline at end of file +bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/src/foo.ads index 8426ad93f..40f1d6a84 100644 --- a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/src/foo.ads +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/src/foo.ads @@ -5,4 +5,4 @@ package Foo is function Fact (N : Integer) return integer is (if N > 1 then N * Fact (N -1) else N); -- # expr_func -end Foo; \ No newline at end of file +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.opt b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.opt index 8212a024b..13161be34 100644 --- a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.opt +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.opt @@ -1 +1 @@ -bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. \ No newline at end of file +bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/src/foo.ads b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/src/foo.ads index 4af6d0793..2ebba85a9 100644 --- a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/src/foo.ads +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/src/foo.ads @@ -7,4 +7,4 @@ package Foo is function Fact (N : Integer) return integer is (if N > 1 then N * Fact (N -1) else N); -- # expr_func -end Foo; \ No newline at end of file +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.opt b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.opt index 8212a024b..13161be34 100644 --- a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.opt +++ b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.opt @@ -1 +1 @@ -bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. \ No newline at end of file +bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. diff --git a/testsuite/tests/instr-cov/expr_func/aspects/src/test_foo.adb b/testsuite/tests/instr-cov/expr_func/aspects/src/test_foo.adb index 5d7addcd1..0d8339575 100644 --- a/testsuite/tests/instr-cov/expr_func/aspects/src/test_foo.adb +++ b/testsuite/tests/instr-cov/expr_func/aspects/src/test_foo.adb @@ -18,4 +18,4 @@ end Test_Foo; --%opts: --trace-mode=src -- /expr_func/ l! ## dT- --%opts: --trace-mode=bin --- /expr_func/ l! ## d! \ No newline at end of file +-- /expr_func/ l! ## d! diff --git a/testsuite/tests/instr-cov/expr_func/extra.opt b/testsuite/tests/instr-cov/expr_func/extra.opt index 0ae5a81d5..6609aef9d 100644 --- a/testsuite/tests/instr-cov/expr_func/extra.opt +++ b/testsuite/tests/instr-cov/expr_func/extra.opt @@ -1,2 +1,2 @@ 5.04a1 DEAD Requires Ada 2012, unavailable in 5.04a1 -7.1.2 DEAD support for expression functions weak in 7.1.2 \ No newline at end of file +7.1.2 DEAD support for expression functions weak in 7.1.2 diff --git a/testsuite/tests/instr-cov/expr_func/generic_prim/src/inst.ads b/testsuite/tests/instr-cov/expr_func/generic_prim/src/inst.ads index bd66baaa6..3b09a3d6c 100644 --- a/testsuite/tests/instr-cov/expr_func/generic_prim/src/inst.ads +++ b/testsuite/tests/instr-cov/expr_func/generic_prim/src/inst.ads @@ -1,3 +1,3 @@ with Pkg; -package Inst is new Pkg (T => Boolean, Init => True); \ No newline at end of file +package Inst is new Pkg (T => Boolean, Init => True); diff --git a/testsuite/tests/instr-cov/expr_func/prev_decl/src/bar.ads b/testsuite/tests/instr-cov/expr_func/prev_decl/src/bar.ads index e47b0cdf9..b330052b7 100644 --- a/testsuite/tests/instr-cov/expr_func/prev_decl/src/bar.ads +++ b/testsuite/tests/instr-cov/expr_func/prev_decl/src/bar.ads @@ -2,4 +2,4 @@ pragma Ada_2012; package Bar is type T_Bar is new Boolean; -end Bar; \ No newline at end of file +end Bar; diff --git a/testsuite/tests/instr-cov/expr_func/prev_decl/src/foo.ads b/testsuite/tests/instr-cov/expr_func/prev_decl/src/foo.ads index 028449938..6a200520c 100644 --- a/testsuite/tests/instr-cov/expr_func/prev_decl/src/foo.ads +++ b/testsuite/tests/instr-cov/expr_func/prev_decl/src/foo.ads @@ -13,4 +13,4 @@ private function Prim (Self : T) return T_Bar is (False); -- # EF -end Foo; \ No newline at end of file +end Foo; diff --git a/testsuite/tests/instr-cov/expr_func/prim2/pak.adb b/testsuite/tests/instr-cov/expr_func/prim2/pak.adb index fab1782a6..d6062b524 100644 --- a/testsuite/tests/instr-cov/expr_func/prim2/pak.adb +++ b/testsuite/tests/instr-cov/expr_func/prim2/pak.adb @@ -7,4 +7,4 @@ package body Pak is function Make_Internal (Cond : Boolean) return TT is (TT'(X => 3, Y => 4)); -end Pak; \ No newline at end of file +end Pak; diff --git a/testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb b/testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb index 5fab031ea..2d280f90a 100644 --- a/testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb +++ b/testsuite/tests/instr-cov/gpr-complex/src-main_sep/pkg-bar.adb @@ -2,5 +2,5 @@ with Ada.Text_IO; use Ada.Text_IO; separate (Pkg) procedure Bar is begin - Put_Line ("Hello from main-sep"); + Put_Line ("Hello from main-sep"); end Bar; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-decl.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-decl.adb index 16e774d85..1f59650f6 100644 --- a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-decl.adb +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-decl.adb @@ -16,4 +16,4 @@ procedure Dotted.Decl is begin Dotted.Decl.Bar; Decl.Foo; -end Dotted.Decl; \ No newline at end of file +end Dotted.Decl; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-exn.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-exn.adb index 69cc2c09e..345dbb981 100644 --- a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-exn.adb +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-exn.adb @@ -14,4 +14,4 @@ begin exception when Program_Error => Exn.Bar; -end Dotted.Exn; \ No newline at end of file +end Dotted.Exn; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-no_decl.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-no_decl.adb index 62cbd8f7b..129303111 100644 --- a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-no_decl.adb +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted-no_decl.adb @@ -9,4 +9,4 @@ begin Dotted.No_Decl.Block.Foo; No_Decl.Block.Foo; end Block; -end Dotted.No_Decl; \ No newline at end of file +end Dotted.No_Decl; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.adb index 80e18c78b..7bf467818 100644 --- a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.adb +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.adb @@ -12,4 +12,4 @@ package body Dotted is raise Program_Error; end Bar; -end Dotted; \ No newline at end of file +end Dotted; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.ads b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.ads index 412536ca0..5eb2a513f 100644 --- a/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.ads +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/dotted.ads @@ -5,4 +5,4 @@ package Dotted is procedure Bar; -end Dotted; \ No newline at end of file +end Dotted; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_decl.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_decl.adb index 0942da694..bb658b783 100644 --- a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_decl.adb +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_decl.adb @@ -18,4 +18,4 @@ procedure Simple_Decl is begin Simple_Decl.Bar; Dotted.Simple_Decl.Foo; -end Simple_Decl; \ No newline at end of file +end Simple_Decl; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_exn.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_exn.adb index bdef7bf6f..b5ed47a9e 100644 --- a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_exn.adb +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_exn.adb @@ -14,4 +14,4 @@ begin exception when Program_Error => Simple_Exn.Bar; -end Simple_Exn; \ No newline at end of file +end Simple_Exn; diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_no_decl.adb b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_no_decl.adb index 6c05c89a0..e7fc26e2a 100644 --- a/testsuite/tests/instr-cov/main_autodump/nested_block/simple_no_decl.adb +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/simple_no_decl.adb @@ -8,4 +8,4 @@ begin begin Simple_No_Decl.Block.Foo; end Block; -end Simple_No_Decl; \ No newline at end of file +end Simple_No_Decl; diff --git a/testsuite/tests/instr-cov/main_autodump/pramga_prio/main.adb b/testsuite/tests/instr-cov/main_autodump/pramga_prio/main.adb index d3259195e..51a659f98 100644 --- a/testsuite/tests/instr-cov/main_autodump/pramga_prio/main.adb +++ b/testsuite/tests/instr-cov/main_autodump/pramga_prio/main.adb @@ -14,4 +14,4 @@ procedure Main is pragma Volatile (X); begin X := Ident (X); -end Main; \ No newline at end of file +end Main; diff --git a/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.opt b/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.opt index c63def349..2675fc275 100644 --- a/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.opt +++ b/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.opt @@ -1 +1 @@ -RTS_ZFP DEAD requires tasking pragma availability \ No newline at end of file +RTS_ZFP DEAD requires tasking pragma availability diff --git a/testsuite/tests/instr-cov/main_autodump/stubs/main-inner.adb b/testsuite/tests/instr-cov/main_autodump/stubs/main-inner.adb index 937b467b9..9bde02b5f 100644 --- a/testsuite/tests/instr-cov/main_autodump/stubs/main-inner.adb +++ b/testsuite/tests/instr-cov/main_autodump/stubs/main-inner.adb @@ -3,4 +3,4 @@ separate (Main) function Inner (X : Boolean) return Boolean is begin return X; -end Inner; \ No newline at end of file +end Inner; diff --git a/testsuite/tests/instr-cov/main_autodump/stubs/main.adb b/testsuite/tests/instr-cov/main_autodump/stubs/main.adb index bca58ba32..e7e33130f 100644 --- a/testsuite/tests/instr-cov/main_autodump/stubs/main.adb +++ b/testsuite/tests/instr-cov/main_autodump/stubs/main.adb @@ -5,4 +5,4 @@ procedure Main is pragma Volatile (X); begin X := Inner (X); -end Main; \ No newline at end of file +end Main; diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main-inner.adb b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main-inner.adb index 937b467b9..9bde02b5f 100644 --- a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main-inner.adb +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main-inner.adb @@ -3,4 +3,4 @@ separate (Main) function Inner (X : Boolean) return Boolean is begin return X; -end Inner; \ No newline at end of file +end Inner; diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main.adb b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main.adb index cfa3c6310..0c334161e 100644 --- a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main.adb +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/main.adb @@ -13,4 +13,4 @@ procedure Main is Ctrl_Object : Ctrl_Type; begin X := Inner (X); -end Main; \ No newline at end of file +end Main; diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.adb b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.adb index d4f7ce8b3..60fbc3077 100644 --- a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.adb +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.adb @@ -5,4 +5,4 @@ package body Pkg is begin Put_Line ("Got finalized"); end Finalize; -end Pkg; \ No newline at end of file +end Pkg; diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.ads b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.ads index 63f644a27..e4e9b2a67 100644 --- a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.ads +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/pkg.ads @@ -5,4 +5,4 @@ package Pkg is type Ctrl_Type is new Ada.Finalization.Controlled with null record; procedure Finalize (Self : in out Ctrl_Type); -end Pkg; \ No newline at end of file +end Pkg; diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.opt b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.opt index 6a242f522..f53f5512d 100644 --- a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.opt +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.opt @@ -1,2 +1,2 @@ RTS_ZFP DEAD uses controlled types not available in light runtimes -RTS_LIGHT_TASKING DEAD uses controlled types not available in light-tasking runtimes \ No newline at end of file +RTS_LIGHT_TASKING DEAD uses controlled types not available in light-tasking runtimes diff --git a/testsuite/tests/instr-cov/main_autodump/task_in_main/main.adb b/testsuite/tests/instr-cov/main_autodump/task_in_main/main.adb index 8b2f5b711..09cd7e2d1 100644 --- a/testsuite/tests/instr-cov/main_autodump/task_in_main/main.adb +++ b/testsuite/tests/instr-cov/main_autodump/task_in_main/main.adb @@ -17,4 +17,4 @@ procedure Main is begin Put_Line ("In main"); -end Main; \ No newline at end of file +end Main; diff --git a/testsuite/tests/instr-cov/main_autodump/task_in_main/test.opt b/testsuite/tests/instr-cov/main_autodump/task_in_main/test.opt index 06689ed1a..8c98d2f26 100644 --- a/testsuite/tests/instr-cov/main_autodump/task_in_main/test.opt +++ b/testsuite/tests/instr-cov/main_autodump/task_in_main/test.opt @@ -1 +1 @@ -!RTS_FULL DEAD embedded runtimes do not support task hierarchy \ No newline at end of file +!RTS_FULL DEAD embedded runtimes do not support task hierarchy diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_c.c b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_c.c index 103b17e80..0c0eba97f 100644 --- a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_c.c +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_c.c @@ -7,4 +7,4 @@ main (void) printf ("Hello C world!\n"); /* GNATCOV_DUMP_BUFFERS (trace_prefix) */ return 0; -} \ No newline at end of file +} diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py index 18cd5feef..380605d6f 100644 --- a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py @@ -64,7 +64,7 @@ def check_one_trace(cov_args, lang): prj_id = "p" -# Instrument build and run +# Instrument build and run cov_args = build_and_run( gprsw=GPRswitches( gprfor( diff --git a/testsuite/tests/instr-cov/multiline_marker/test.opt b/testsuite/tests/instr-cov/multiline_marker/test.opt index 17f984f55..8dd5f5b75 100644 --- a/testsuite/tests/instr-cov/multiline_marker/test.opt +++ b/testsuite/tests/instr-cov/multiline_marker/test.opt @@ -1 +1 @@ -RTS_ZFP DEAD No libc in light runtimes \ No newline at end of file +RTS_ZFP DEAD No libc in light runtimes diff --git a/testsuite/tests/instr-cov/not_array/test.opt b/testsuite/tests/instr-cov/not_array/test.opt index 6f632999b..89202c61f 100644 --- a/testsuite/tests/instr-cov/not_array/test.opt +++ b/testsuite/tests/instr-cov/not_array/test.opt @@ -1,3 +1,3 @@ RTS_ZFP DEAD Test requires System.Boolean_Array_Operations.Vector_Not 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 -7.1.2 DEAD support for expression functions weak in 7.1.2 \ No newline at end of file +7.1.2 DEAD support for expression functions weak in 7.1.2 diff --git a/testsuite/tests/instr-cov/null_proc_generic/test.opt b/testsuite/tests/instr-cov/null_proc_generic/test.opt index efd316f1d..f31a3b293 100644 --- a/testsuite/tests/instr-cov/null_proc_generic/test.opt +++ b/testsuite/tests/instr-cov/null_proc_generic/test.opt @@ -1,2 +1,2 @@ 5.04a1 DEAD Requires Ada 2012, unavailable in 5.04a1 -7.1.2 DEAD overloading of generic null procedures not supported in 7.1.2 \ No newline at end of file +7.1.2 DEAD overloading of generic null procedures not supported in 7.1.2 diff --git a/testsuite/tests/instr-cov/protected_body/src/foo.ads b/testsuite/tests/instr-cov/protected_body/src/foo.ads index 2afb6dcfa..2625b9de4 100644 --- a/testsuite/tests/instr-cov/protected_body/src/foo.ads +++ b/testsuite/tests/instr-cov/protected_body/src/foo.ads @@ -17,4 +17,4 @@ package Foo is Obj : Obj_Type; -end Foo; \ No newline at end of file +end Foo; diff --git a/testsuite/tests/instr-cov/protected_body/src/test_foo.adb b/testsuite/tests/instr-cov/protected_body/src/test_foo.adb index 2bb48290f..af784b10a 100644 --- a/testsuite/tests/instr-cov/protected_body/src/test_foo.adb +++ b/testsuite/tests/instr-cov/protected_body/src/test_foo.adb @@ -32,5 +32,3 @@ end Test_Foo; --# foo.ads -- /decl/ ~l+ ## 0 - - diff --git a/testsuite/tests/instr-cov/protected_body/test.opt b/testsuite/tests/instr-cov/protected_body/test.opt index f404c4646..67126a044 100644 --- a/testsuite/tests/instr-cov/protected_body/test.opt +++ b/testsuite/tests/instr-cov/protected_body/test.opt @@ -1 +1 @@ -RTS_ZFP DEAD Protected objects not available in zfp runtimes \ No newline at end of file +RTS_ZFP DEAD Protected objects not available in zfp runtimes diff --git a/testsuite/tests/instr-cov/pure_units/test.opt b/testsuite/tests/instr-cov/pure_units/test.opt index 99be653e1..2b67c9ffb 100644 --- a/testsuite/tests/instr-cov/pure_units/test.opt +++ b/testsuite/tests/instr-cov/pure_units/test.opt @@ -1,2 +1,2 @@ 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 -7.1.2 DEAD support for expression functions weak in 7.1.2 \ No newline at end of file +7.1.2 DEAD support for expression functions weak in 7.1.2 diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/gnat.adc b/testsuite/tests/instr-cov/short_circuit_and_or/gnat.adc index 1773c462c..4c135ee37 100644 --- a/testsuite/tests/instr-cov/short_circuit_and_or/gnat.adc +++ b/testsuite/tests/instr-cov/short_circuit_and_or/gnat.adc @@ -1 +1 @@ -pragma Short_Circuit_And_Or; \ No newline at end of file +pragma Short_Circuit_And_Or; diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/type_pkg.ads b/testsuite/tests/instr-cov/short_circuit_and_or/type_pkg.ads index 3557da2b6..ff12ef1a8 100644 --- a/testsuite/tests/instr-cov/short_circuit_and_or/type_pkg.ads +++ b/testsuite/tests/instr-cov/short_circuit_and_or/type_pkg.ads @@ -4,4 +4,4 @@ package Type_Pkg is type Derived is new Boolean; -end Type_Pkg; \ No newline at end of file +end Type_Pkg; diff --git a/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/src/andthen.adb b/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/src/andthen.adb index 20237f05c..b8c8e10ba 100644 --- a/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/src/andthen.adb +++ b/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/src/andthen.adb @@ -17,6 +17,3 @@ package body Andthen is return Expr; -- # retVal end; end; - - - diff --git a/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.opt b/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.opt index c7e7a8b8d..16000abf6 100644 --- a/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.opt +++ b/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.opt @@ -1 +1 @@ -ALL DEAD +ALL DEAD diff --git a/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/src/andthen.adb b/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/src/andthen.adb index 44c418345..06cfd8814 100644 --- a/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/src/andthen.adb +++ b/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/src/andthen.adb @@ -10,6 +10,3 @@ package body Andthen is return E.Value; -- # retVal end; end; - - - diff --git a/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.opt b/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.opt index c7e7a8b8d..16000abf6 100644 --- a/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.opt +++ b/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.opt @@ -1 +1 @@ -ALL DEAD +ALL DEAD diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_f.adb b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_f.adb index e060ff611..ec6fae2cd 100644 --- a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_f.adb +++ b/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_f.adb @@ -11,4 +11,3 @@ end; -- /retTrue/ l- ## s- -- /retFalse/ l+ ## 0 -- /retVal/ l+ ## 0 - diff --git a/testsuite/tests/xml-check/src/test_andthen_t.adb b/testsuite/tests/xml-check/src/test_andthen_t.adb index 9c702799d..29949cd9b 100644 --- a/testsuite/tests/xml-check/src/test_andthen_t.adb +++ b/testsuite/tests/xml-check/src/test_andthen_t.adb @@ -4,4 +4,3 @@ procedure Test_Andthen_T is begin Assert (Andthen (True, True) = True); end; - From 0e977451a49874f8ceb6642ec77b6910de272961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 7 Feb 2024 16:42:01 +0100 Subject: [PATCH 0687/1483] SC_Obligations: rework scope traversal The previous scope traversal algorithm relied on forward iterators for multiway trees, which was an issue when there were SCO gaps in the traversal. It also imposed that the traversal had to be in increasing SCO order. The traversal is now done manually, which means it can be done in arbitrary order (although traversing with SCOs in ascending ordered will increase performance). --- .../tests/222-subp-of-interest-cplx/main.adb | 8 ++ .../tests/222-subp-of-interest-cplx/pkg.adb | 23 +++++ .../tests/222-subp-of-interest-cplx/pkg.ads | 5 + .../tests/222-subp-of-interest-cplx/test.opt | 2 + .../tests/222-subp-of-interest-cplx/test.py | 61 ++++++++++++ tools/gnatcov/sc_obligations.adb | 97 ++++++++++++------- tools/gnatcov/sc_obligations.ads | 51 ++++------ 7 files changed, 178 insertions(+), 69 deletions(-) create mode 100644 testsuite/tests/222-subp-of-interest-cplx/main.adb create mode 100644 testsuite/tests/222-subp-of-interest-cplx/pkg.adb create mode 100644 testsuite/tests/222-subp-of-interest-cplx/pkg.ads create mode 100644 testsuite/tests/222-subp-of-interest-cplx/test.opt create mode 100644 testsuite/tests/222-subp-of-interest-cplx/test.py diff --git a/testsuite/tests/222-subp-of-interest-cplx/main.adb b/testsuite/tests/222-subp-of-interest-cplx/main.adb new file mode 100644 index 000000000..3be21d40b --- /dev/null +++ b/testsuite/tests/222-subp-of-interest-cplx/main.adb @@ -0,0 +1,8 @@ +with Pkg; use Pkg; + +with Support; + +procedure Main is +begin + Support.Assert (One = 1); +end Main; diff --git a/testsuite/tests/222-subp-of-interest-cplx/pkg.adb b/testsuite/tests/222-subp-of-interest-cplx/pkg.adb new file mode 100644 index 000000000..3007f8417 --- /dev/null +++ b/testsuite/tests/222-subp-of-interest-cplx/pkg.adb @@ -0,0 +1,23 @@ +pragma Ada_2012; + +package body Pkg is + + function Zero return Integer is + begin + return 0; + end Zero; + + function One return Integer is + begin + return (if String'("this is a very long decision" + & "that spans multiple lines")'Length = 1 + then 2 + else 1); + end One; + + function Two return Integer is + begin + return 2; + end Two; + +end Pkg; diff --git a/testsuite/tests/222-subp-of-interest-cplx/pkg.ads b/testsuite/tests/222-subp-of-interest-cplx/pkg.ads new file mode 100644 index 000000000..75040b79e --- /dev/null +++ b/testsuite/tests/222-subp-of-interest-cplx/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + function Zero return Integer; + function One return Integer; + function Two return Integer; +end Pkg; diff --git a/testsuite/tests/222-subp-of-interest-cplx/test.opt b/testsuite/tests/222-subp-of-interest-cplx/test.opt new file mode 100644 index 000000000..ae2e6e8ac --- /dev/null +++ b/testsuite/tests/222-subp-of-interest-cplx/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD --subprograms not supported in bin trace mode +5.04a1 DEAD test uses Ada 2012 features diff --git a/testsuite/tests/222-subp-of-interest-cplx/test.py b/testsuite/tests/222-subp-of-interest-cplx/test.py new file mode 100644 index 000000000..c5350dede --- /dev/null +++ b/testsuite/tests/222-subp-of-interest-cplx/test.py @@ -0,0 +1,61 @@ +""" +Test that the scope mechanism (and thus the subprogram of interest feature) +correctly traverses the scopes, even when the traversal is not done with SCOs +in a contiguous order. + +The One subprogram in the sources used to trigger two related issues: + - The decision in One spanning multiple lines, the scope traversal was done + back and forth on the statement SCO then the decision SCO on each line, thus + breaking the precondition for Traverse_SCO; + + - The scope traversal when loading the trace was done on the first covered + statement SCO, which is not in the first scope. The trace entries were thus + silently discarded. + + More details bellow, making references to the old implementation. + + To be more precise, the previous implementation relied on forward iterators + in multi-way trees to traverse the scope tree, in depth first order until it + found a scope that did not contain the traversed SCO. When loading the + coverage buffers from a given trace, Traverse_SCO is only called on SCOs for + which the correspond buffer bit is set. As such, in this example, the first + SCO on which Traverse_SCO will be called is the statement SCO for the return + statement in One. + + When initiating the traversal, Next_SE point to the scope for the whole + CU, which contains the SCO of interest. The traversal then moves to the next + one, which is the scope for Zero. This does not contain SCO, so the traversal + stops, and current_SE thus points to the scope for the whole CU. While it is + true that this scope contains SCO, it is not the deepest one. The current + scope in the traversal is then checked against the set of scopes of interest, + which only consist in the scope for One, so this returns False. The coverage + information is then wrongfully discarded. + +This test checks both bugs. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=["main.adb"],srcdirs=[".."]), + units=["Pkg"] + ), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["--subprograms=pkg.ads:3", "-axcov"] +) + +check_xcov_reports( + "*.xcov", + {"pkg.adb.xcov": {"!": {12, 13}, "+": {14, 15}}}, + cwd="obj" +) + +thistest.result() diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 94a3e4c9c..95c588752 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -66,8 +66,8 @@ package body SC_Obligations is -- Return whether SCO is covered by SE's SCO range function Covers_SCO - (Cur : Scope_Entities_Trees.Cursor; SCO : SCO_Id) return Boolean - is (Covers_SCO (Scope_Entities_Trees.Element (Cur), SCO)); + (ST : Scope_Traversal_Type; SCO : SCO_Id) return Boolean + is (Covers_SCO (Scope_Entities_Trees.Element (ST.Cur), SCO)); -- Return whether SCO is covered by that element's SCO range --------------- @@ -803,59 +803,84 @@ package body SC_Obligations is --------------------- function Scope_Traversal (CU : CU_Id) return Scope_Traversal_Type is - Result : Scope_Traversal_Type; + use Scope_Entities_Trees; begin if CU = No_CU_Id then return No_Scope_Traversal; end if; - Result.It := - new Tree_Iterator'(CU_Vector.Reference (CU).Scope_Entities.Iterate); - Result.Last_SCO := No_SCO_Id; - Result.Current_SE := Scope_Entities_Trees.No_Element; - Result.Next_SE := Result.It.First; - return Result; + return + (CU => CU, + Cur => First_Child (CU_Vector.Reference (CU).Scope_Entities.Root)); end Scope_Traversal; + ------------ + -- Get_CU -- + ------------ + + function Get_CU (ST : Scope_Traversal_Type) return CU_Id is (ST.CU); + ------------------ -- Traverse_SCO -- ------------------ procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) is use Scope_Entities_Trees; - Progressed : Boolean := False; begin - ST.Last_SCO := SCO; + -- Don't do anything if there is no scope attached to ST. - -- Move Next_SE forward in the iterator until we go past the deepest - -- scope that covers SCO. Update Current_SE along the way. + if not Has_Element (ST.Cur) then + return; + end if; + + -- Check whether the current scope covers SCO. If not, find the first + -- one that does in the parent chain. There is always a scope for the + -- compilation unit / file, so this is guaranteed to finish. + + while not Covers_SCO (ST, SCO) loop + ST.Cur := Parent (ST.Cur); + + -- If we reach the root of the tree, this means this SCO is not in + -- any scope, which is clearly a bug. - while Has_Element (ST.Next_SE) and then Covers_SCO (ST.Next_SE, SCO) loop - ST.Current_SE := ST.Next_SE; - ST.Next_SE := ST.It.Next (ST.Next_SE); - Progressed := True; + pragma Assert (not Is_Root (ST.Cur)); end loop; - -- If we have not found a more specific scope for SCO, we still may need - -- to update Current_SE in case the requested SCO is not covered anymore - -- by Current_SE. + -- Descend into the tree until we are on a leaf, or no child of the + -- current scope entity covers the SCO. - if not Progressed then - while Has_Element (ST.Current_SE) - and then not Covers_SCO (ST.Current_SE, SCO) - loop - ST.Current_SE := Parent (ST.Current_SE); - end loop; - end if; - end Traverse_SCO; + Depth_Descent : + while not Is_Leaf (ST.Cur) loop - -------------- - -- Last_SCO -- - -------------- + -- Otherwise, find if there is a child that covers SCO, this is a + -- linear search. We could search by dichotomy as the children are + -- sorted, but this seems overkill. - function Last_SCO (ST : Scope_Traversal_Type) return SCO_Id is - begin - return ST.Last_SCO; - end Last_SCO; + declare + Child : Cursor := First_Child (ST.Cur); + In_Child : Boolean := False; + -- Whether the low bound of Child is lower than SCO (and thus + -- Child covers SCO when exiting the loop). + begin + Child_Search : + while Has_Element (Child) loop + declare + SE : constant Scope_Entity := Element (Child); + begin + In_Child := SE.From <= SCO; + exit Child_Search when SE.To >= SCO; + Child := Next_Sibling (Child); + end; + end loop Child_Search; + + -- If we found a child containing SCO, keep descending into its + -- children, otherwise we have found the inner most scope. + + exit Depth_Descent when not In_Child or else Child = No_Element; + ST.Cur := Child; + pragma Loop_Invariant (Covers_SCO (ST, SCO)); + end; + end loop Depth_Descent; + end Traverse_SCO; -------------------------- -- In_Scope_Of_Interest -- @@ -875,7 +900,7 @@ package body SC_Obligations is -- Otherwise, find at least one scope that covers SCO and that is a -- subprogram of interest. - Cur := ST.Current_SE; + Cur := ST.Cur; while Has_Element (Cur) loop if Subps_Of_Interest.Contains (Element (Cur).Identifier) then return True; diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index c84570559..2ec0fcf66 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -238,9 +238,6 @@ package SC_Obligations is -- Debug helper: print a representation of Scope_Entities on the standard -- output. Each line that is printed has the given Line_Prefix. - subtype Tree_Iterator is - Scope_Entities_Trees.Tree_Iterator_Interfaces.Forward_Iterator'Class; - type Iterator_Acc is access Tree_Iterator; package Scope_Stacks is new Ada.Containers.Doubly_Linked_Lists (Element_Type => Scope_Entities_Trees.Cursor, "=" => Scope_Entities_Trees."="); @@ -256,25 +253,25 @@ package SC_Obligations is -- Is_Active to know whether a given scope is active in the given -- traversal. - function Scope_Traversal (CU : CU_Id) return Scope_Traversal_Type - with Post => Last_SCO (Scope_Traversal'Result) = No_SCO_Id; + function Scope_Traversal (CU : CU_Id) return Scope_Traversal_Type; -- Return a scope traversal for the given compilation unit - procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) - with Pre => Last_SCO (ST) <= SCO, - Post => Last_SCO (ST) = SCO; - -- Traverse the given SCO and update the Scope_Traversal accordingly. Note - -- that the scope traversal must be done on increasing SCOs identifiers. + function Get_CU (ST : Scope_Traversal_Type) return CU_Id; + -- Return the compilation unit id which ST is currently traversing - function Last_SCO (ST : Scope_Traversal_Type) return SCO_Id; - -- Return the last SCO that was passed to Traverse_SCO, or No_SCO_Id if - -- Traverse_SCO has not been called yet on ST. + procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) with + Pre => Get_CU (ST) = No_CU_Id + or else SCO in First_SCO (Get_CU (ST)) .. Last_SCO (Get_CU (ST)); + -- Position ST on the inner-most scope that contains SCO. + -- + -- This does nothing on a scope traversal type not initialized, or + -- initialized on a CU with no scopes attached to it. function In_Scope_Of_Interest (ST : Scope_Traversal_Type) return Boolean; -- Return whether at least one scope in Switches.Subps_Of_Interest contains - -- Last_SCO (ST). Note that this also returns True if - -- Switches.Subps_Of_Interest is empty (i.e. consider that all subprograms - -- are of interest in that case). + -- the last SCO on which Traverse_SCO (ST, ...) was called. Note that this + -- also returns True if Switches.Subps_Of_Interest is empty (i.e. consider + -- that all subprograms are of interest in that case). No_Scope_Entity : constant Scope_Entity := (From => No_SCO_Id, @@ -1384,25 +1381,13 @@ private -- Set the BDD node for the given condition SCO type Scope_Traversal_Type is record - It : Iterator_Acc; - -- Iterator to traverse the scope tree - - Last_SCO : SCO_Id; - -- Keep track of the last SCO requested with Traverse_SCO. We use this - -- to check that SCOs are requested in the right order (lower Ids to - -- higher ones). - - Current_SE : Scope_Entities_Trees.Cursor; - -- Scope that is the deepest in the scope tree and that covers Last_SCO + CU : CU_Id := No_CU_Id; + -- Id of the compilation unit we are currently traversing - Next_SE : Scope_Entities_Trees.Cursor; - -- Next scope that Traverse_SCO needs to consider + Cur : Scope_Entities_Trees.Cursor := Scope_Entities_Trees.No_Element; + -- Current position in the scope tree end record; - No_Scope_Traversal : Scope_Traversal_Type := - (It => null, - Last_SCO => No_SCO_Id, - Current_SE => Scope_Entities_Trees.No_Element, - Next_SE => Scope_Entities_Trees.No_Element); + No_Scope_Traversal : constant Scope_Traversal_Type := (others => <>); end SC_Obligations; From ce5f2d39ebaa802907f4a021b39643d487bc01f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 7 Feb 2024 16:15:04 +0100 Subject: [PATCH 0688/1483] Rework line state computation to properly take into account scopes gnatcov used to skip the line state computation if a given line contained a SCO not part of a subprogram of interest. Rework this to always compute the line state, but ignoring all SCOs not part of a subprogram of interest. --- .../tests/222-subp-line-computation/main.adb | 8 +++++ .../tests/222-subp-line-computation/pkg.ads | 7 ++++ .../tests/222-subp-line-computation/test.opt | 2 ++ .../tests/222-subp-line-computation/test.py | 33 +++++++++++++++++++ tools/gnatcov/annotations-cobertura.adb | 2 +- tools/gnatcov/annotations-dynamic_html.adb | 5 ++- tools/gnatcov/annotations-html.adb | 1 - tools/gnatcov/annotations-report.adb | 2 +- tools/gnatcov/annotations-xcov.adb | 1 - tools/gnatcov/annotations-xml.adb | 2 +- tools/gnatcov/annotations.adb | 14 +------- tools/gnatcov/annotations.ads | 1 - tools/gnatcov/coverage-source.adb | 11 +++++-- tools/gnatcov/coverage-source.ads | 8 ++++- tools/gnatcov/coverage.adb | 4 +-- tools/gnatcov/coverage.ads | 5 --- tools/gnatcov/sc_obligations.adb | 13 ++++++++ tools/gnatcov/sc_obligations.ads | 6 ++++ 18 files changed, 92 insertions(+), 33 deletions(-) create mode 100644 testsuite/tests/222-subp-line-computation/main.adb create mode 100644 testsuite/tests/222-subp-line-computation/pkg.ads create mode 100644 testsuite/tests/222-subp-line-computation/test.opt create mode 100644 testsuite/tests/222-subp-line-computation/test.py diff --git a/testsuite/tests/222-subp-line-computation/main.adb b/testsuite/tests/222-subp-line-computation/main.adb new file mode 100644 index 000000000..28560e8ca --- /dev/null +++ b/testsuite/tests/222-subp-line-computation/main.adb @@ -0,0 +1,8 @@ +with Pkg; + +with Support; + +procedure Main is +begin + Support.Assert (Pkg.Get_Bool); +end Main; diff --git a/testsuite/tests/222-subp-line-computation/pkg.ads b/testsuite/tests/222-subp-line-computation/pkg.ads new file mode 100644 index 000000000..9079d4dd7 --- /dev/null +++ b/testsuite/tests/222-subp-line-computation/pkg.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; + +package Pkg is + + Bool_Val : Boolean := True; function Get_Bool return Boolean is (Bool_Val); + +end Pkg; diff --git a/testsuite/tests/222-subp-line-computation/test.opt b/testsuite/tests/222-subp-line-computation/test.opt new file mode 100644 index 000000000..ae2e6e8ac --- /dev/null +++ b/testsuite/tests/222-subp-line-computation/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD --subprograms not supported in bin trace mode +5.04a1 DEAD test uses Ada 2012 features diff --git a/testsuite/tests/222-subp-line-computation/test.py b/testsuite/tests/222-subp-line-computation/test.py new file mode 100644 index 000000000..47434cc86 --- /dev/null +++ b/testsuite/tests/222-subp-line-computation/test.py @@ -0,0 +1,33 @@ +""" +Test that line state computation is done for lines which contains both SCOs for +a subprogram of interest and SCOs outside of all subprograms of interest. + +Gnatcov used to not compute the coverage state of a line if it contained a SCO +not in the subprogram of interest. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=["main.adb"],srcdirs=[".."]), + units=["pkg"], + ), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["--subprograms=pkg.ads:5", "-axcov+"] +) + +check_xcov_reports( + "*.xcov", + {"pkg.ads.xcov": {"+": {5}}}, + cwd="obj" +) + +thistest.result() diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb index 86a1e01b3..1af26b4bd 100644 --- a/tools/gnatcov/annotations-cobertura.adb +++ b/tools/gnatcov/annotations-cobertura.adb @@ -253,7 +253,7 @@ package body Annotations.Cobertura is Pp.Need_Sources := False; Annotations.Generate_Report - (Pp, True, Context.Subps_Of_Interest, Subdir => "cobertura"); + (Pp, True, Subdir => "cobertura"); Free (Pp.Source_Prefix_Pattern); end Generate_Report; diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index b2d584526..d492f02cf 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -291,9 +291,8 @@ package body Annotations.Dynamic_Html is begin Annotations.Generate_Report (Pp, - Show_Details => True, - Subp_Of_Interest => Context.Subps_Of_Interest, - Subdir => "html"); + Show_Details => True, + Subdir => "html"); end Generate_Report; ------------------------ diff --git a/tools/gnatcov/annotations-html.adb b/tools/gnatcov/annotations-html.adb index 1b4d9176a..e4c8dbe18 100644 --- a/tools/gnatcov/annotations-html.adb +++ b/tools/gnatcov/annotations-html.adb @@ -224,7 +224,6 @@ package body Annotations.Html is Annotations.Generate_Report (Pp, Show_Details, - Context.Subps_Of_Interest, Subdir => (if Show_Details then "shtml+" else "shtml")); end Generate_Report; diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index e1393303d..777987fa2 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -238,7 +238,7 @@ package body Annotations.Report is Open_Report_File (Final_Report_Name.all); end if; - Annotations.Generate_Report (Pp, True, Context.Subps_Of_Interest); + Annotations.Generate_Report (Pp, True); Close_Report_File; end Generate_Report; diff --git a/tools/gnatcov/annotations-xcov.adb b/tools/gnatcov/annotations-xcov.adb index 5f32f3383..e064843cf 100644 --- a/tools/gnatcov/annotations-xcov.adb +++ b/tools/gnatcov/annotations-xcov.adb @@ -88,7 +88,6 @@ package body Annotations.Xcov is Annotations.Generate_Report (Pp, Show_Details, - Context.Subps_Of_Interest, Subdir => (if Pp.Show_Details then "xcov+" else "xcov"), Clean_Pattern => "*.xcov"); end Generate_Report; diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index d2a7e894e..4dee29910 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -287,7 +287,7 @@ package body Annotations.Xml is others => <>); begin Annotations.Generate_Report - (Pp, True, Context.Subps_Of_Interest, Subdir => "xml"); + (Pp, True, Subdir => "xml"); end Generate_Report; ------- diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 308750fd3..a687feb83 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -378,7 +378,6 @@ package body Annotations is procedure Generate_Report (Pp : in out Pretty_Printer'Class; Show_Details : Boolean; - Subp_Of_Interest : Scope_Id_Set; Subdir : String := ""; Clean_Pattern : String := No_Cleaning) is @@ -417,23 +416,12 @@ package body Annotations is LI : constant Line_Info_Access := Get_Line (FI, L); S : Line_State; begin - -- Check that this is a SCO for a subprogram of interest - - if not Subp_Of_Interest.Is_Empty and then LI.SCOs /= null then - for SCO of LI.SCOs.all loop - Traverse_SCO (ST, SCO); - end loop; - if not In_Scope_Of_Interest (ST) then - return; - end if; - end if; - -- Compute state for each coverage objective if Object_Coverage_Enabled then Object.Compute_Line_State (LI); else - Source.Compute_Line_State (L, LI); + Source.Compute_Line_State (L, LI, ST); end if; -- Compute aggregated line state before exemption diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 8fe34a45a..a207c76d8 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -211,7 +211,6 @@ private procedure Generate_Report (Pp : in out Pretty_Printer'Class; Show_Details : Boolean; - Subp_Of_Interest : Scope_Id_Set; Subdir : String := ""; Clean_Pattern : String := No_Cleaning); -- Let Pp generate the annotated sources. If Show_Details is False, only a diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index d1bb09c8f..ce4852530 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -614,7 +614,8 @@ package body Coverage.Source is procedure Compute_Line_State (Line_Num : Positive; - Line_Info : Line_Info_Access) + Line_Info : Line_Info_Access; + ST : in out Scope_Traversal_Type) is procedure Compute_Condition_Level_Line_State (SCO : SCO_Id; @@ -744,7 +745,13 @@ package body Coverage.Source is -- Examine each SCO associated with line for SCO of Line_Info.SCOs.all loop - if Kind (SCO) = Removed then + + -- 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; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 602a1e07a..f75ab36f0 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -23,6 +23,7 @@ with Files_Table; use Files_Table; with Instrument; use Instrument; with Instrument.Input_Traces; use Instrument.Input_Traces; with Logging; +with SC_Obligations; use SC_Obligations; with Traces; use Traces; with Traces_Names; use Traces_Names; with Traces_Lines; use Traces_Lines; @@ -73,9 +74,14 @@ package Coverage.Source is procedure Compute_Line_State (Line_Num : Positive; - Line_Info : Line_Info_Access); + Line_Info : Line_Info_Access; + ST : in out Scope_Traversal_Type); -- Set Line.State based on coverage information accumulated on all SCOs -- that cover the given line. + -- + -- ST is used to filter the SCOs not belonging to subprograms of interest, + -- it must be initialized to the CU for which we are computing coverage or + -- left uninitialized. subtype SCO_State is Line_State range Not_Covered .. Undetermined_Coverage; function Get_Line_State diff --git a/tools/gnatcov/coverage.adb b/tools/gnatcov/coverage.adb index f193d9260..9d5e231cc 100644 --- a/tools/gnatcov/coverage.adb +++ b/tools/gnatcov/coverage.adb @@ -20,7 +20,6 @@ with Ada.Command_Line; with Ada.Containers; with Support_Files; use Support_Files; -with Switches; use Switches; with Version; use Version; package body Coverage is @@ -276,8 +275,7 @@ package body Coverage is (Timestamp => Clock, Version => +Xcov_Version, Command => Command, - Levels => +Coverage_Option_Value, - Subps_Of_Interest => Subps_Of_Interest); + Levels => +Coverage_Option_Value); end Get_Context; --------------- diff --git a/tools/gnatcov/coverage.ads b/tools/gnatcov/coverage.ads index e67cca242..4f2358de0 100644 --- a/tools/gnatcov/coverage.ads +++ b/tools/gnatcov/coverage.ads @@ -27,7 +27,6 @@ with Ada.Calendar; use Ada.Calendar; with Ada.Containers.Ordered_Sets; with Coverage_Options; use Coverage_Options; -with SC_Obligations; use SC_Obligations; with Strings; use Strings; package Coverage is @@ -131,10 +130,6 @@ package Coverage is Levels : Unbounded_String; -- Coverage option for enabled coverage levels - - Subps_Of_Interest : Scope_Id_Set; - -- List of subprogram of interest. If empty, consider that all of - -- the subprograms are of interest. end record; type Context_Access is access all Context; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 95c588752..a3e78776e 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -910,6 +910,19 @@ package body SC_Obligations is return False; end In_Scope_Of_Interest; + -------------------------- + -- In_Scope_Of_Interest -- + -------------------------- + + function In_Scope_Of_Interest + (ST : in out Scope_Traversal_Type; + SCO : SCO_Id) return Boolean + is + begin + Traverse_SCO (ST, SCO); + return In_Scope_Of_Interest (ST); + end In_Scope_Of_Interest; + ----------------- -- Add_Address -- ----------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 2ec0fcf66..f3677c85b 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -273,6 +273,12 @@ package SC_Obligations is -- also returns True if Switches.Subps_Of_Interest is empty (i.e. consider -- that all subprograms are of interest in that case). + function In_Scope_Of_Interest + (ST : in out Scope_Traversal_Type; SCO : SCO_Id) return Boolean with + Pre => Get_CU (ST) = No_CU_Id + or else SCO in First_SCO (Get_CU (ST)) .. Last_SCO (Get_CU (ST)); + -- Shortcut for Traverse_SCO (ST, SCO); return In_Scope_Of_Interest (ST); + No_Scope_Entity : constant Scope_Entity := (From => No_SCO_Id, To => No_SCO_Id, From fdb18ca5071f53247c17d03516f18bfd14792e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 7 Feb 2024 16:40:03 +0100 Subject: [PATCH 0689/1483] instrument-ada_unit.adb: Fix scope identifier for expr. functions The identifier for degenerate subprogram used to be the file and line of the degenerate subprogram itself. This is wrong in case it has a previous declaration. This change fixes this. --- testsuite/tests/222-scope-expr-func/main.adb | 8 +++++ testsuite/tests/222-scope-expr-func/pkg.adb | 9 ++++++ testsuite/tests/222-scope-expr-func/pkg.ads | 4 +++ testsuite/tests/222-scope-expr-func/test.opt | 2 ++ testsuite/tests/222-scope-expr-func/test.py | 33 ++++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 6 +++- 6 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/222-scope-expr-func/main.adb create mode 100644 testsuite/tests/222-scope-expr-func/pkg.adb create mode 100644 testsuite/tests/222-scope-expr-func/pkg.ads create mode 100644 testsuite/tests/222-scope-expr-func/test.opt create mode 100644 testsuite/tests/222-scope-expr-func/test.py diff --git a/testsuite/tests/222-scope-expr-func/main.adb b/testsuite/tests/222-scope-expr-func/main.adb new file mode 100644 index 000000000..7a52cf12f --- /dev/null +++ b/testsuite/tests/222-scope-expr-func/main.adb @@ -0,0 +1,8 @@ +with Pkg; use Pkg; + +with Support; + +procedure Main is +begin + Support.Assert (Zero = 0); +end Main; diff --git a/testsuite/tests/222-scope-expr-func/pkg.adb b/testsuite/tests/222-scope-expr-func/pkg.adb new file mode 100644 index 000000000..f2e21aeca --- /dev/null +++ b/testsuite/tests/222-scope-expr-func/pkg.adb @@ -0,0 +1,9 @@ +pragma Ada_2012; + +package body Pkg is + + function Zero return Integer is (0); + + function One return Integer is (1); + +end Pkg; diff --git a/testsuite/tests/222-scope-expr-func/pkg.ads b/testsuite/tests/222-scope-expr-func/pkg.ads new file mode 100644 index 000000000..ce3ee636c --- /dev/null +++ b/testsuite/tests/222-scope-expr-func/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + function Zero return Integer; + function One return Integer; +end Pkg; diff --git a/testsuite/tests/222-scope-expr-func/test.opt b/testsuite/tests/222-scope-expr-func/test.opt new file mode 100644 index 000000000..ae2e6e8ac --- /dev/null +++ b/testsuite/tests/222-scope-expr-func/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD --subprograms not supported in bin trace mode +5.04a1 DEAD test uses Ada 2012 features diff --git a/testsuite/tests/222-scope-expr-func/test.py b/testsuite/tests/222-scope-expr-func/test.py new file mode 100644 index 000000000..d94081320 --- /dev/null +++ b/testsuite/tests/222-scope-expr-func/test.py @@ -0,0 +1,33 @@ +""" +Test that the subprogram of interest feature works correctly for expression +functions which have a previous declaration. + +gnatcov used to register the actual expression function's sloc as identifier +instead of it first declaration, resulting in an error message being emitted. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=["main.adb"],srcdirs=[".."]), + units=["Pkg"] + ), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["--subprograms=pkg.ads:2", "-axcov"] +) + +check_xcov_reports( + "*.xcov", + {"pkg.adb.xcov": {"+": {5}}}, + cwd="obj" +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index a75600365..5d1fb8638 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -4313,6 +4313,10 @@ package body Instrument.Ada_Unit is N_Spec : constant Subp_Spec := N.P_Subp_Spec_Or_Null.As_Subp_Spec; + Prev_Part : constant Basic_Decl := N.P_Previous_Part_For_Decl; + -- If this is a null procedure or an expression function, it may have + -- a previous declaration that must be used as scope identifier. + begin -- Process decisions nested in formal parameters @@ -4321,7 +4325,7 @@ package body Instrument.Ada_Unit is Enter_Scope (UIC => UIC, Sloc => Sloc (N), - Decl => N); + Decl => (if Prev_Part.Is_Null then N else Prev_Part)); -- Nothing else to do except for the case of degenerate subprograms -- (null procedures and expression functions). From 55995e42af0d88a19073b06b33b581dfe2fd78b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 16 Feb 2024 16:12:02 +0100 Subject: [PATCH 0690/1483] Reactivate test after fix in LAL --- testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt | 1 - 1 file changed, 1 deletion(-) diff --git a/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt b/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt index ab5cc641a..21590854e 100644 --- a/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt +++ b/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt @@ -1,2 +1 @@ RTS_ZFP DEAD Test uses Ada.Containers, not available in that profile -ALL XFAIL Instrument warnings due to LAL property error, see libadalang#1046 From c49caad4491e96d1a1392bbb3931afc95861ec27 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Feb 2024 09:19:26 +0000 Subject: [PATCH 0691/1483] qualification+support: minor reformattings --- qualification/qm/genmodel.py | 8 ++++---- qualification/qm/scripts/generate_plans_pdf.py | 1 - qualification/qm/scripts/generate_tor_pdf.py | 1 - .../examples/support/src/helpers/simple_pools.adb | 10 +++++----- .../examples/support/src/helpers/simple_pools.ads | 8 ++++---- 5 files changed, 13 insertions(+), 15 deletions(-) diff --git a/qualification/qm/genmodel.py b/qualification/qm/genmodel.py index eb00b14c3..f67a72e1d 100755 --- a/qualification/qm/genmodel.py +++ b/qualification/qm/genmodel.py @@ -48,10 +48,10 @@ def __langdir_for(lang): # only keep the non-digital start of the language name as the subdir # to search: return re.match(RE_LANG, string=lang).group(1) - + def __langversion_for(lang): return re.match(RE_LANG, string=lang).group(2) - + def __reqset_triggers_for (lang, chapter): return '\n'.join( @@ -94,7 +94,7 @@ def __gen_model_for(dolevel, languages): __langversion_for(ada_lang), 'extra_block': - __extra_block_for(dolevel=dolevel) + __extra_block_for(dolevel=dolevel) } ) @@ -133,7 +133,7 @@ def __gen_lrm_ref_for(lang): output.close() input.close() - + # ======================================================================= # == MAIN SCRIPT BODY == # ======================================================================= diff --git a/qualification/qm/scripts/generate_plans_pdf.py b/qualification/qm/scripts/generate_plans_pdf.py index 04c5da3c7..bd2d5dc70 100644 --- a/qualification/qm/scripts/generate_plans_pdf.py +++ b/qualification/qm/scripts/generate_plans_pdf.py @@ -4,4 +4,3 @@ # toplevel driver for qmat generation. Not an unreasonable name anyway. generate_doc.generate_pdf('PLANS', 'build/latexpdf') - diff --git a/qualification/qm/scripts/generate_tor_pdf.py b/qualification/qm/scripts/generate_tor_pdf.py index 921356f92..d40a3930b 100644 --- a/qualification/qm/scripts/generate_tor_pdf.py +++ b/qualification/qm/scripts/generate_tor_pdf.py @@ -4,4 +4,3 @@ # toplevel driver for qmat generation. Not an unreasonable name anyway. generate_doc.generate_pdf('TOR', 'build/latexpdf') - diff --git a/tools/gnatcov/examples/support/src/helpers/simple_pools.adb b/tools/gnatcov/examples/support/src/helpers/simple_pools.adb index bd7ca60db..eac17a732 100644 --- a/tools/gnatcov/examples/support/src/helpers/simple_pools.adb +++ b/tools/gnatcov/examples/support/src/helpers/simple_pools.adb @@ -1,17 +1,17 @@ package body Simple_Pools is - + package body Basic_Pool is - + Store : array (1 .. Capacity) of aliased Data_Type; Next_Free : Natural := Store'First; - + function Allocate return Data_Access is This_Index : constant Natural := Next_Free; begin Next_Free := Next_Free + 1; return Store (This_Index)'Access; - end; + end; end; - + end; diff --git a/tools/gnatcov/examples/support/src/helpers/simple_pools.ads b/tools/gnatcov/examples/support/src/helpers/simple_pools.ads index dacd630e8..2b878c278 100644 --- a/tools/gnatcov/examples/support/src/helpers/simple_pools.ads +++ b/tools/gnatcov/examples/support/src/helpers/simple_pools.ads @@ -2,15 +2,15 @@ -- against a generic malloc like memory allocation service that the most -- basic runtime profiles might not feature. This is intended for simple -- tests, never deallocating and never needing more than a few nodes. - + package Simple_Pools is - - generic + + generic type Data_Type is limited private; Capacity : Natural; package Basic_Pool is type Data_Access is access all Data_Type; function Allocate return Data_Access; end; - + end Simple_Pools; From c1c3b630ab37ba02f5c9c73b57225615925ce11d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Feb 2024 15:40:26 +0000 Subject: [PATCH 0692/1483] Fix style issues in all GPR files --- doc/gnatcov/examples/starter/ops.gpr | 2 +- examples/integration/prj.gpr | 2 +- .../Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr | 2 +- testsuite/altrun/example/altrun.gpr | 2 +- .../tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/mylib.gpr | 2 +- testsuite/tests/M502-040-default-prj-path/proj/proj.gpr | 1 - testsuite/tests/N610-006-library/libops.gpr | 1 - testsuite/tests/P907-005-stubbing-generic/common.gpr | 2 +- testsuite/tests/P907-005-stubbing/common.gpr | 2 +- testsuite/tests/RB13-019-win-paths/main.gpr | 2 +- .../tests/T807-011-externally-built-objdir/opslib/opslib.gpr | 2 +- tools/gnatcov/examples/aunit_variant/aunit_variant.gpr | 1 - tools/gnatcov/examples/aunit_variant/harness.gpr | 1 - tools/gnatcov/examples/support/base.gpr | 1 - tools/gnatcov/examples/support/common.gpr | 1 - tools/gnatcov/examples/support/libsupport.gpr | 2 +- tools/gnatcov/gnatcov.gpr | 2 +- 17 files changed, 11 insertions(+), 17 deletions(-) diff --git a/doc/gnatcov/examples/starter/ops.gpr b/doc/gnatcov/examples/starter/ops.gpr index 0b776942f..e6f28e704 100644 --- a/doc/gnatcov/examples/starter/ops.gpr +++ b/doc/gnatcov/examples/starter/ops.gpr @@ -2,4 +2,4 @@ project Ops is for Languages use ("Ada"); for Source_Dirs use ("src"); for Object_Dir use "obj"; -end Ops; \ No newline at end of file +end Ops; diff --git a/examples/integration/prj.gpr b/examples/integration/prj.gpr index 03ca6e950..97dfbe728 100644 --- a/examples/integration/prj.gpr +++ b/examples/integration/prj.gpr @@ -2,7 +2,7 @@ project Prj is for Source_Dirs use ("src"); for Object_Dir use "obj"; - + package Coverage is Cov_Level := ("--level=stmt"); for Switches ("instrument") use ("--dump-trigger=main-end") & Cov_Level; diff --git a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr index 8355f531b..19f25e9e5 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr +++ b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr @@ -7,4 +7,4 @@ library project mylib is package compiler is for switches("ada") use ("-fpreserve-control-flow", "-fdump-scos", "-g"); end compiler; -end mylib; \ No newline at end of file +end mylib; diff --git a/testsuite/altrun/example/altrun.gpr b/testsuite/altrun/example/altrun.gpr index b0614abe2..96a5c3f3e 100644 --- a/testsuite/altrun/example/altrun.gpr +++ b/testsuite/altrun/example/altrun.gpr @@ -2,4 +2,4 @@ project ALTRUN is for Source_Dirs use ("."); for Exec_Dir use "."; for Object_Dir use "obj"; -end ALTRUN; \ No newline at end of file +end ALTRUN; diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/mylib.gpr b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/mylib.gpr index b7d344b86..aa467bb3c 100644 --- a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/mylib.gpr +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/mylib/mylib.gpr @@ -4,4 +4,4 @@ library project mylib is for library_name use project'name; for library_dir use "lib"; for library_interface use ("ops", "ops.values"); -end mylib; \ No newline at end of file +end mylib; diff --git a/testsuite/tests/M502-040-default-prj-path/proj/proj.gpr b/testsuite/tests/M502-040-default-prj-path/proj/proj.gpr index 8f8cb36a6..52baf98c9 100644 --- a/testsuite/tests/M502-040-default-prj-path/proj/proj.gpr +++ b/testsuite/tests/M502-040-default-prj-path/proj/proj.gpr @@ -1,4 +1,3 @@ project Proj is end Proj; - diff --git a/testsuite/tests/N610-006-library/libops.gpr b/testsuite/tests/N610-006-library/libops.gpr index c2207bdb9..7fd74d5ed 100644 --- a/testsuite/tests/N610-006-library/libops.gpr +++ b/testsuite/tests/N610-006-library/libops.gpr @@ -8,4 +8,3 @@ library project Libops is for Library_Dir use "lib"; end Libops; - diff --git a/testsuite/tests/P907-005-stubbing-generic/common.gpr b/testsuite/tests/P907-005-stubbing-generic/common.gpr index 4efd6b94b..cf829a932 100644 --- a/testsuite/tests/P907-005-stubbing-generic/common.gpr +++ b/testsuite/tests/P907-005-stubbing-generic/common.gpr @@ -2,4 +2,4 @@ abstract project common is package compiler is for switches ("Ada") use ("-gnata"); end compiler; -end common; \ No newline at end of file +end common; diff --git a/testsuite/tests/P907-005-stubbing/common.gpr b/testsuite/tests/P907-005-stubbing/common.gpr index 4efd6b94b..cf829a932 100644 --- a/testsuite/tests/P907-005-stubbing/common.gpr +++ b/testsuite/tests/P907-005-stubbing/common.gpr @@ -2,4 +2,4 @@ abstract project common is package compiler is for switches ("Ada") use ("-gnata"); end compiler; -end common; \ No newline at end of file +end common; diff --git a/testsuite/tests/RB13-019-win-paths/main.gpr b/testsuite/tests/RB13-019-win-paths/main.gpr index 7a8723365..d71a0deae 100644 --- a/testsuite/tests/RB13-019-win-paths/main.gpr +++ b/testsuite/tests/RB13-019-win-paths/main.gpr @@ -16,7 +16,7 @@ for Object_Dir use "./obj"; for Languages use ("Ada"); package Compiler is -for Switches("main.adb") use +for Switches("main.adb") use Compiler'Default_Switches ("Ada") & (); diff --git a/testsuite/tests/T807-011-externally-built-objdir/opslib/opslib.gpr b/testsuite/tests/T807-011-externally-built-objdir/opslib/opslib.gpr index a478a47b3..e2e643a1b 100644 --- a/testsuite/tests/T807-011-externally-built-objdir/opslib/opslib.gpr +++ b/testsuite/tests/T807-011-externally-built-objdir/opslib/opslib.gpr @@ -5,7 +5,7 @@ library project Opslib is for Library_Dir use "lib-" & Project'Library_Name; for Object_Dir use "obj-" & Project'Library_Name; - + for Source_Dirs use ("."); type Boolean is ("false", "true"); diff --git a/tools/gnatcov/examples/aunit_variant/aunit_variant.gpr b/tools/gnatcov/examples/aunit_variant/aunit_variant.gpr index 4253c8923..5761e1987 100644 --- a/tools/gnatcov/examples/aunit_variant/aunit_variant.gpr +++ b/tools/gnatcov/examples/aunit_variant/aunit_variant.gpr @@ -4,4 +4,3 @@ project Aunit_variant extends "base" is for Source_Dirs use ("src"); for Object_Dir use "obj/" & Conf.Target; end Aunit_variant; - diff --git a/tools/gnatcov/examples/aunit_variant/harness.gpr b/tools/gnatcov/examples/aunit_variant/harness.gpr index e08a511af..b7b026ac0 100644 --- a/tools/gnatcov/examples/aunit_variant/harness.gpr +++ b/tools/gnatcov/examples/aunit_variant/harness.gpr @@ -11,4 +11,3 @@ project Harness is for Exec_Dir use "obj/" & Conf.Target; end Harness; - diff --git a/tools/gnatcov/examples/support/base.gpr b/tools/gnatcov/examples/support/base.gpr index 858019292..c57b7eee0 100644 --- a/tools/gnatcov/examples/support/base.gpr +++ b/tools/gnatcov/examples/support/base.gpr @@ -26,4 +26,3 @@ abstract project Base is end Linker; end Base; - diff --git a/tools/gnatcov/examples/support/common.gpr b/tools/gnatcov/examples/support/common.gpr index ec0680d85..cf9c70dc6 100644 --- a/tools/gnatcov/examples/support/common.gpr +++ b/tools/gnatcov/examples/support/common.gpr @@ -8,4 +8,3 @@ abstract project Common is for Languages use (); end Common; - diff --git a/tools/gnatcov/examples/support/libsupport.gpr b/tools/gnatcov/examples/support/libsupport.gpr index 91fc3ad60..c91f2e044 100644 --- a/tools/gnatcov/examples/support/libsupport.gpr +++ b/tools/gnatcov/examples/support/libsupport.gpr @@ -44,7 +44,7 @@ library project Libsupport is -- Now compute the set of source directories to use. A common one, -- always, then an additional Target specific one. FOR SELDOM USES -- ONLY. We don't wan't yet another zfp support approx here: - + Source_Dirs := ("src", "src/helpers"); case Conf.Target is diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 22ccb75f4..9c9de7ade 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -22,7 +22,7 @@ project Gnatcov is -- Mandatory externals -- ------------------------- - type Part_Type is + type Part_Type is ("lib32", "lib64", "driver", "gnatcov32", "gnatcov64", "compiler"); Part : Part_Type := external ("PART"); -- Which program this project should build: From 1bfbc0066a1714fbe34b215d4d7692eb4b7c3b10 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Feb 2024 09:22:53 +0000 Subject: [PATCH 0693/1483] CI: add a job to check formatting for various text files --- .check-formatting.py | 184 +++++++++++++++++++++++++++++++++++++++++++ .gitlab-ci.yml | 21 +++++ 2 files changed, 205 insertions(+) create mode 100644 .check-formatting.py diff --git a/.check-formatting.py b/.check-formatting.py new file mode 100644 index 000000000..17b4f971c --- /dev/null +++ b/.check-formatting.py @@ -0,0 +1,184 @@ +#! /usr/bin/env python + +import argparse +import os.path +import sys + +from colorama import Fore, Style + + +args_parser = argparse.ArgumentParser( + description="Check basic formatting rules on text files" +) +args_parser.add_argument( + "--autofix", + action="store_true", + help="When possible, update files to fix detected formatting issues", +) +args_parser.add_argument( + "--force-colors", + action="store_true", + help=( + "Force colored output. This is necessary when the output is not a TTY" + " but still supports ANSI codes." + ), +) +args_parser.add_argument( + "files", + nargs="*", + help=( + "List of files on which to run. If none is passed, process all source" + " files found in the current directory that look like source files." + ), +) + + +class Checker: + + filename_extensions = { + "adb", + "adc", + "ads", + "c", + "cc", + "cpp", + "gpr", + "h", + "hh", + "hpp", + "opt", + "py", + } + """ + List of file extensions that look like source files. + """ + + def __init__(self, autofix: bool = False, force_colors: bool = False): + self.issue_found = False + """ + Whether at least one issue was found so far. + """ + + self.use_colors = force_colors or os.isatty(sys.stdout.fileno()) + """ + Whether to colorize the error messages. + """ + + self.autofix = autofix + """ + Whether to attempt to fix the style issues found in place. + """ + + def report( + self, + filename: str, + message: str, + lineno: int | None = None, + ) -> None: + """ + Report a style issue. + + :param filename: File in which the issue was found. + :param message: Human-readable description of the issue. + :param lineno: Line number for the issue, if applicable, None + otherwise. + """ + self.issue_found = True + + # Build a list of text chunks to print. Put colorama elements in tuples + # so that we can keep only text chunks if the output is not a TTY. + chunks = [ + (Fore.MAGENTA, ), + filename, + (Fore.CYAN, ), + ":", + ] + if lineno is not None: + chunks += [ + (Fore.GREEN, ), + str(lineno), + (Fore.CYAN, ), + ":", + ] + chunks += [ + (Style.RESET_ALL, ), + " ", + message, + ] + + filtered_chunks = [] + for c in chunks: + if isinstance(c, str): + filtered_chunks.append(c) + elif isinstance(c, tuple): + if self.use_colors: + filtered_chunks += c + else: + raise AssertionError + print("".join(filtered_chunks)) + + def process_file(self, filename: str) -> None: + """ + Look for style issues in the given file. + """ + + with open(filename, encoding="utf-8") as f: + try: + content = f.read() + except UnicodeDecodeError as exc: + self.report(filename, str(exc)) + return + if not content: + return + + lines = content.splitlines() + modified = False + + if not content.endswith("\n"): + modified = True + self.report(filename, "missing trailing newline") + + for i, line in enumerate(lines, 1): + stripped_line = line.rstrip() + if line != stripped_line: + modified = True + self.report(filename, "trailing whitespace", i) + lines[i - 1] = stripped_line + + while not lines[-1].strip(): + modified = True + self.report(filename, "last line is empty") + lines.pop() + + # If requested, fix the issues that were found + if self.autofix and modified: + with open(filename, "w") as f: + if lines: + for line in lines: + f.write(line) + f.write("\n") + + @classmethod + def main(cls, argv: list[str] | None = None): + args = args_parser.parse_args(argv) + checker = cls( + autofix=args.autofix, + force_colors=args.force_colors, + ) + + # Process the list of files to check if present, otherwise look for all + # source files in the current directory. + if args.files: + for filename in args.files: + checker.process_file(filename) + else: + for path, _, filenames in os.walk("."): + for f in filenames: + if f.rsplit(".", 1)[-1] in cls.filename_extensions: + checker.process_file(os.path.join(path, f)) + + return 1 if checker.issue_found else 0 + + +if __name__ == "__main__": + sys.exit(Checker.main()) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index a824dd9cc..5aaa30aad 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,6 +6,8 @@ workflow: variables: PACKAGE_BASE_NAME: gnatcoverage.tar.gz PACKAGE_ABSOLUTE_NAME: $CI_PROJECT_DIR/$PACKAGE_BASE_NAME + GITLAB_REMOTE: "https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/" + PIP_INDEX_URL: "https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.adacore-it.com/api/v4/projects/202/packages/pypi/simple" .basic_setup: &basic_setup - unset GITLAB_TOKEN @@ -166,3 +168,22 @@ test_spark: $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/results/new/ <<: *artifacts + +stylechecks: + interruptible: true + stage: test + services: + - image:all-pythons + - run_as_root:false + script: + - git config --global --add + url."${GITLAB_REMOTE}".insteadOf "git@ssh.gitlab.adacore-it.com:" + - git config --global --add + url."${GITLAB_REMOTE}".insteadOf "ssh://git@ssh.gitlab.adacore-it.com/" + + - export PATH="/home/gitlab-ci/.local/bin:$PATH" + - source /it/activate-py311 + - python -m pip install colorama + + - cd $CI_PROJECT_DIR + - python $CI_PROJECT_DIR/.check-formatting.py --force-colors From c40fbede3fea7e1f148abca9fe56525d69bf5924 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Feb 2024 09:28:18 +0000 Subject: [PATCH 0694/1483] CI: start build_community and stylechecks jobs as soon as possible These jobs do not use the instrumented build of gnatcov done in the "build" job, so they can start right away. --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5aaa30aad..9512c9eae 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -48,6 +48,7 @@ build_docs: stage: build services: - image:e3 + needs: [] rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" || ($CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH) changes: @@ -175,6 +176,7 @@ stylechecks: services: - image:all-pythons - run_as_root:false + needs: [] script: - git config --global --add url."${GITLAB_REMOTE}".insteadOf "git@ssh.gitlab.adacore-it.com:" From 432f073b9ba61f22fb02760bef45f072f69932be Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 19 Feb 2024 10:50:14 +0000 Subject: [PATCH 0695/1483] Qualif/Common/UnitsOfInterest/GPR/Robustness: refactoring As a preparation for a change of API for SCOV.minicheck.check_xcov_reports, rework these tests so that calls to check_xcov_reports scan only one subdirectory. Add explicit checks for the other directories. --- .../GPR/Robustness/NoContribPrj/test.py | 27 +++++++++++++++---- .../GPR/Robustness/UnitNotInProjects/test.py | 19 ++++++++++++- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py index 6130d32d1..ed1f31f56 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py @@ -3,6 +3,9 @@ of interest are emitted when expected. """ +import os.path +import glob + from e3.fs import mkdir from SCOV.minicheck import build_run_and_coverage, check_xcov_reports @@ -94,7 +97,21 @@ def run_test(label, slug, main, helper, recursive, projects=[], units=[], expected_cov = {} for c in expected_cov_list: expected_cov.update(c) - check_xcov_reports('obj-*/*.xcov', expected_cov) + check_xcov_reports('*.xcov', expected_cov, 'obj-main') + + # Check that all xcov report files are created in obj-main (i.e. the root + # project). + xcov_files = glob.glob('obj-*/*.xcov') + extra_xcov_files = [ + f + for f in xcov_files + if os.path.dirname(f) != 'obj-main' + ] + thistest.fail_if_not_equal( + "misplaced xcov report files", + "", + "\n".join(extra_xcov_files), + ) # For all testcases, we set up three projects: @@ -110,10 +127,10 @@ def run_test(label, slug, main, helper, recursive, projects=[], units=[], # project of interest (--projects) unless not recursive (no warnings # are expected in this mode). The point of having this project loaded is to # check that indeed gnatcov does not warn about "empty". -main = {'obj-main/main.adb.xcov': {'+': {6, 7}}} -main_support = {'obj-main/main_support.adb.xcov': {'+': {3}}} -helper = {'obj-main/helper.adb.xcov': {'+': {5}}} -helper_support = {'obj-main/helper_support.adb.xcov': {'+': {3}}} +main = {'main.adb.xcov': {'+': {6, 7}}} +main_support = {'main_support.adb.xcov': {'+': {3}}} +helper = {'helper.adb.xcov': {'+': {5}}} +helper_support = {'helper_support.adb.xcov': {'+': {3}}} # Check when --units is passed diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py index 628a47c15..6e069ab1f 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py @@ -4,6 +4,9 @@ reported. """ +import os.path +import glob + from e3.fs import mkdir from SCOV.minicheck import build_run_and_coverage, check_xcov_reports @@ -41,6 +44,20 @@ 'warning: no unit main (from --units) in the projects of interest', contents_of(log_file).strip()) -check_xcov_reports('obj-*/*.xcov', {'obj-main/helper.adb.xcov': {'+': {3}}}) +check_xcov_reports('*.xcov', {'helper.adb.xcov': {'+': {3}}}, 'obj-main') + +# Check that all xcov report files are created in obj-main (i.e. the root +# project). +xcov_files = glob.glob('obj-*/*.xcov') +extra_xcov_files = [ + f + for f in xcov_files + if os.path.dirname(f) != 'obj-main' +] +thistest.fail_if_not_equal( + "misplaced xcov report files", + "", + "\n".join(extra_xcov_files), +) thistest.result() From 710777bde35940a2748ac90ce55ede15be67f77a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 19 Feb 2024 10:56:35 +0000 Subject: [PATCH 0696/1483] instr-cov/endianity: refactor use of check_xcov_reports As a preparation for a change of API for SCOV.minicheck.check_xcov_reports, rework this test so that the call to check_xcov_reports scans only one subdirectory at a time. --- testsuite/tests/instr-cov/endianity/test.py | 22 +++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/testsuite/tests/instr-cov/endianity/test.py b/testsuite/tests/instr-cov/endianity/test.py index 3818dc291..d54c822ad 100644 --- a/testsuite/tests/instr-cov/endianity/test.py +++ b/testsuite/tests/instr-cov/endianity/test.py @@ -37,15 +37,17 @@ tf.write(f) # Check that gnatcov decodes both the same way -xcov(xcov_args + ['--output-dir=xcov-le', 'le.srctrace'], - out='coverage-le.log') -xcov(xcov_args + ['--output-dir=xcov-be', 'be.srctrace'], - out='coverage-be.log') -check_xcov_reports('xcov-*/*.xcov', { - 'xcov-le/main.adb.xcov': {'+': {5, 7, 8}}, - 'xcov-be/main.adb.xcov': {'+': {5, 7, 8}}, - 'xcov-le/pkg.adb.xcov': {'+': {6, 8}, '!': {5}}, - 'xcov-be/pkg.adb.xcov': {'+': {6, 8}, '!': {5}}, -}) +for discr in ('be', 'le'): + xcov_dir = f'xcov-{discr}' + xcov(xcov_args + ['--output-dir', xcov_dir, f'{discr}.srctrace'], + out=f'coverage-{discr}.log') + check_xcov_reports( + '*.xcov', + { + 'main.adb.xcov': {'+': {5, 7, 8}}, + 'pkg.adb.xcov': {'+': {6, 8}, '!': {5}}, + }, + xcov_dir, + ) thistest.result() From 5be92b951f8f60c45c71a74b2e1240ad2d1847e9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 14 Feb 2024 15:40:54 +0000 Subject: [PATCH 0697/1483] Testsuite: simplify SCOV.minicheck.check_xcov_reports --- .../GPR/ExtendedGprs/AttrOverride/test.py | 6 +- .../GPR/ExtendedGprs/ExtendedHasMain/test.py | 8 +-- .../GPR/ExtendedGprs/PartialOverride/test.py | 8 +-- .../GPR/Robustness/BadUnitInAttr/test.py | 2 +- .../GPR/Robustness/BadUnitInSwitch/test.py | 2 +- .../GPR/Robustness/MissingLI/test.py | 2 +- .../GPR/Robustness/NoContribPrj/test.py | 2 +- .../GPR/Robustness/SourcesAttr/test.py | 6 +- .../GPR/Robustness/UnitNotInProjects/test.py | 2 +- testsuite/SCOV/minicheck.py | 55 ++++++++----------- .../tests/106-externally-built-header/test.py | 2 +- .../tests/127-check-line-endings/test.py | 4 +- testsuite/tests/129-instr-progress/test.py | 3 +- .../138-ada-preprocessing/example/test.py | 3 +- .../138-ada-preprocessing/prep_data/test.py | 4 +- .../14-unused-separate/compilable/test.py | 2 +- .../14-unused-separate/uncompilable/test.py | 2 +- testsuite/tests/15-non-instr-cons/test.py | 8 +-- testsuite/tests/152-shared_setup/test.py | 2 +- testsuite/tests/207-srctrace-version/test.py | 2 +- testsuite/tests/222-scope-expr-func/test.py | 6 +- .../tests/222-subp-line-computation/test.py | 6 +- .../tests/222-subp-of-interest-cplx/test.py | 6 +- testsuite/tests/24_mixed_c_c++/test.py | 3 +- testsuite/tests/86-subproj_lang/test.py | 4 +- testsuite/tests/92-long_slugs/test.py | 3 +- .../tests/C/mcdc/Exemptions/Invalid/test.py | 5 +- .../tests/C/mcdc/include-current-dir/test.py | 4 +- testsuite/tests/I812-011/test.py | 2 +- testsuite/tests/IA01-015/test.py | 2 +- testsuite/tests/M625-011-GPR-Cunits/test.py | 5 +- .../OA27-059-inlined-separate-cons/test.py | 9 +-- .../OA27-059-sep-cons-prj-override/test.py | 3 +- testsuite/tests/OA27-059-sep-cons-prj/test.py | 4 +- .../OA27-059-separate-consolidation/test.py | 9 +-- .../tests/P907-005-ckpt-covlevel/test.py | 8 +-- testsuite/tests/P907-005-incremental/test.py | 2 +- .../tests/P907-005-stubbing-generic/test.py | 2 +- testsuite/tests/P907-005-stubbing/test.py | 2 +- .../Q224-032-several-out-of-line/test.py | 2 +- testsuite/tests/Q327-016-glob-ignore/test.py | 5 +- .../tests/Q329-018-create-output-dir/test.py | 4 +- testsuite/tests/Q905-005-compressed/test.py | 2 +- testsuite/tests/RB13-019-win-paths/test.py | 6 +- testsuite/tests/RC04-030-bad-trace/test.py | 18 +++--- .../tests/S527-004-ckpt-no-level/test.py | 2 +- .../tests/S603-009-externally-built/test.py | 12 ++-- .../S619-014-tag-provider-mismatch/test.py | 3 +- testsuite/tests/S621-026-mcdc-ckpt/test.py | 2 +- .../T807-011-externally-built-objdir/test.py | 6 +- .../tests/T825-010-naming-scheme/test.py | 12 ++-- .../tests/TA15-063-ignore-fingerprint/test.py | 8 +-- .../test.py | 6 +- .../tests/TB13-020-expr-func-mcdc/test.py | 8 +-- .../tests/TC03-012-objcov-line-state/test.py | 3 +- testsuite/tests/U204-026-arch-mix/test.py | 3 +- .../U204-029-source-rebase/test_support.py | 6 +- .../tests/U208-020-child-project/test.py | 6 +- testsuite/tests/U208-020-error-call/test.py | 2 +- .../U208-020-unique-language-project/test.py | 4 +- testsuite/tests/U211-014-setup/test.py | 2 +- .../U219-010-ali-entry-guard-sloc/test.py | 4 +- testsuite/tests/U416-006-big-bdd/test.py | 2 +- testsuite/tests/U527-020-dc-from-mcdc/test.py | 4 +- .../UB18-055-switches-in-gprfile/test.py | 2 +- testsuite/tests/V120-034-dup-langs/test.py | 4 +- testsuite/tests/V201-010-multi-report/test.py | 4 +- testsuite/tests/V309-017-setup-config/test.py | 2 +- .../tests/V520-019-duplicate-messages/test.py | 5 +- testsuite/tests/V824-005-sid-ext-prj/test.py | 2 +- .../ignore-main/test.py | 2 +- .../main-unit-of-interest/test.py | 2 +- .../VA04-023-non-instr-sco-reloc/test.py | 3 +- .../tests/VB07-015-clean-output-dir/test.py | 3 +- testsuite/tests/VB18-035-default-opts/test.py | 6 +- .../VB21-022-sid-srctrace-mismatch/test.py | 4 +- testsuite/tests/VC19-001-origin-prj/test.py | 2 +- .../tests/W315-021-generic-preelab/test.py | 3 +- .../tests/excluded_unit_imported_prj/test.py | 3 +- testsuite/tests/header_not_found/test.py | 2 +- .../tests/homonym-units-of-interest/test.py | 3 +- testsuite/tests/ignored-c-file/test.py | 8 +-- testsuite/tests/ignored-c-header/test.py | 2 +- testsuite/tests/ignored-casing/test.py | 4 +- .../141-trigger-manual-pp-search-path/test.py | 8 +-- .../test.py | 8 +-- .../instr-cov/144-no-unknown-warning/test.py | 2 +- .../instr-cov/198-non-instr-scos/test.py | 3 +- .../tests/instr-cov/208-no-secsta/test.py | 3 +- .../tests/instr-cov/216-no-elab-all/test.py | 3 +- .../219-non-instr-propagation/test.py | 3 +- .../instr-cov/225-expr-func-access/test.py | 3 +- .../226-atc-incomp-type-decl/test.py | 3 +- .../instr-cov/C++/109-pp-switches/test.py | 8 +-- .../instr-cov/C++/c++_no_warnings/test.py | 2 +- .../instr-cov/C++/cpp-extern-c-main/test.py | 2 +- .../tests/instr-cov/C++/explicit_lang/test.py | 2 +- .../tests/instr-cov/C++/std-c++20/test.py | 3 +- .../O212-062-unsupported-pragmas/test.py | 8 +-- .../VB03-024-preprocess-included-proj/test.py | 8 +-- .../W502-023-base64-long-lines/test.py | 2 +- .../tests/instr-cov/base64_prefix/test.py | 2 +- .../tests/instr-cov/basic_base64/test.py | 6 +- .../tests/instr-cov/basic_decision/test.py | 6 +- testsuite/tests/instr-cov/basic_stmt/test.py | 6 +- .../tests/instr-cov/bin_file_tunings/test.py | 4 +- .../tests/instr-cov/buffer_reset/test.py | 9 +-- .../tests/instr-cov/c_custom_naming/test.py | 3 +- .../tests/instr-cov/c_empty_source/test.py | 2 +- testsuite/tests/instr-cov/c_gpr_opts/test.py | 3 +- testsuite/tests/instr-cov/c_header/test.py | 3 +- testsuite/tests/instr-cov/c_metaprog/test.py | 2 +- .../tests/instr-cov/c_multiline_stmt/test.py | 5 +- testsuite/tests/instr-cov/c_no_return/test.py | 2 +- testsuite/tests/instr-cov/c_opts/test.py | 2 +- .../instr-cov/c_special_filenames/test.py | 2 +- .../instr-cov/c_ternary_in_if_cond/test.py | 6 +- .../instr-cov/checks_and_warnings/test.py | 6 +- .../instr-cov/cmdline-self-ref-macro/test.py | 2 +- .../instr-cov/compile_time_pragma/test.py | 2 +- .../tests/instr-cov/config_custom_db/test.py | 2 +- .../tests/instr-cov/config_pragmas/test.py | 3 +- testsuite/tests/instr-cov/consistency/test.py | 4 +- testsuite/tests/instr-cov/end_slocs/test.py | 2 +- testsuite/tests/instr-cov/endianity/test.py | 12 ++-- .../instr-cov/entry_guards/restricted/test.py | 2 +- .../instr-cov/explicit_mains_uoi/test.py | 2 +- .../tests/instr-cov/expr_func/aggr/test.py | 2 +- .../tests/instr-cov/expr_func/basic/test.py | 4 +- .../tests/instr-cov/expr_func/generic/test.py | 2 +- .../instr-cov/expr_func/parameterless/test.py | 6 +- .../tests/instr-cov/expr_func/prim/test.py | 2 +- .../tests/instr-cov/expr_func/prim2/test.py | 8 +-- .../tests/instr-cov/ghost_generic/test.py | 3 +- testsuite/tests/instr-cov/gpr-complex/test.py | 2 +- .../tests/instr-cov/library_projects/test.py | 14 ++--- testsuite/tests/instr-cov/main-spec/test.py | 3 +- .../main_autodump/disabled_lang/test.py | 7 +-- .../main_autodump/nested_block/test.py | 16 +++--- .../main_autodump/pramga_prio/test.py | 6 +- .../instr-cov/main_autodump/stubs/test.py | 3 +- .../main_autodump/stubs_controlled/test.py | 3 +- .../main_autodump/task_in_main/test.py | 6 +- testsuite/tests/instr-cov/main_no_ext/test.py | 2 +- .../instr-cov/manual-dump/ada_only/test.py | 8 +-- .../instr-cov/manual-dump/ada_subprj/test.py | 6 +- .../tests/instr-cov/manual-dump/basic/test.py | 2 +- .../instr-cov/manual-dump/c_only/test.py | 8 +-- .../manual-dump/lal_ctx_reset/test.py | 2 +- .../tests/instr-cov/manual-dump/mixed/test.py | 4 +- .../manual-dump/prefix_in_code/test.py | 2 +- .../instr-cov/manual-dump/trace_index/test.py | 6 +- .../instr-cov/missing-runtime-dir/test.py | 2 +- testsuite/tests/instr-cov/mixed_and/test.py | 6 +- .../tests/instr-cov/multi_unit_source/test.py | 2 +- .../tests/instr-cov/multiline_marker/test.py | 2 +- .../tests/instr-cov/nested_ternary/test.py | 2 +- testsuite/tests/instr-cov/no_main/test.py | 4 +- testsuite/tests/instr-cov/not_array/test.py | 2 +- .../tests/instr-cov/null_proc_generic/test.py | 2 +- testsuite/tests/instr-cov/orphan-unit/test.py | 2 +- .../tests/instr-cov/pragma_after_cu/test.py | 8 +-- .../instr-cov/pragma_ghost_predicate/test.py | 3 +- .../tests/instr-cov/pragma_no_body/test.py | 6 +- .../tests/instr-cov/pretty_print/test.py | 6 +- testsuite/tests/instr-cov/pure_units/test.py | 3 +- .../tests/instr-cov/remove_extra_src/test.py | 2 +- testsuite/tests/instr-cov/scalar_and/test.py | 2 +- .../instr-cov/short_circuit_and_or/test.py | 8 ++- .../tests/instr-cov/stmt_after_accept/test.py | 4 +- .../integrated_instrumentation/C++/test.py | 2 +- .../basic_cmake/test.py | 2 +- .../basic_lib/test.py | 5 +- .../basic_stmt/test.py | 2 +- .../cmake_lib/test.py | 2 +- .../compile_and_link/test.py | 2 +- .../isystem/test.py | 2 +- .../special_filenames/test.py | 2 +- .../modified-root-dir/test.py | 2 +- .../unmodified-root-dir/test.py | 6 +- testsuite/tests/shared-libs/ada-main/test.py | 2 +- testsuite/tests/shared-libs/c-main/test.py | 2 +- testsuite/tests/subp_of_interest/test.py | 9 +-- testsuite/tests/subp_of_interest_c/test.py | 3 +- 184 files changed, 319 insertions(+), 496 deletions(-) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py index 675277b1d..902acf2b5 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py @@ -19,8 +19,8 @@ # App_Base is extended by App; App overrides Coverage'Units so that only Values # (not Values.Aux) is selected. -check_xcov_reports('obj/*.xcov', { - 'obj/values.ads.xcov': {}, - 'obj/values.adb.xcov': {'+': {5, 6}, '-': {8}}}) +check_xcov_reports('obj', { + 'values.ads.xcov': {}, + 'values.adb.xcov': {'+': {5, 6}, '-': {8}}}) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py index 5f18ec6d4..41280fd88 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py @@ -36,9 +36,9 @@ # In blob.ads, we expect either '+' or '.' on everything, depending # on the toolchain. Let check_xcov_reports refine that. -check_xcov_reports('ext-obj/*.xcov', { - 'ext-obj/blob.ads.xcov': {}, - 'ext-obj/main1.adb.xcov': {'+': {5}}, - 'ext-obj/main2.adb.xcov': {'+': {5, 6}}}) +check_xcov_reports('ext-obj', { + 'blob.ads.xcov': {}, + 'main1.adb.xcov': {'+': {5}}, + 'main2.adb.xcov': {'+': {5, 6}}}) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py index e2c14694e..3781daffa 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py @@ -37,9 +37,9 @@ gpr_obj_dir='obj-ext', gpr_exe_dir='obj-ext') -check_xcov_reports('obj-ext/*.xcov', { - 'obj-ext/main.adb.xcov': {'+': {5}}, - 'obj-ext/helper.ads.xcov': {}, - 'obj-ext/helper.adb.xcov': {'+': {4}}}) +check_xcov_reports('obj-ext', { + 'main.adb.xcov': {'+': {5}}, + 'helper.ads.xcov': {}, + 'helper.adb.xcov': {'+': {4}}}) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py index e8ce851e8..6577db851 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py @@ -30,6 +30,6 @@ 'warning: no unit no_such_unit in project gen (coverage.units attribute)', contents_of(log_file).strip()) -check_xcov_reports('obj/*.xcov', {'obj/main.adb.xcov': {'+': {5}}}) +check_xcov_reports('obj', {'main.adb.xcov': {'+': {5}}}) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py index a1a571dda..2f8474220 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py @@ -38,6 +38,6 @@ ' interest', log_lines) -check_xcov_reports('obj/*.xcov', {'obj/main.adb.xcov': {'+': {5}}}) +check_xcov_reports('obj', {'main.adb.xcov': {'+': {5}}}) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py index e24935c2b..2b6881612 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py @@ -46,6 +46,6 @@ 'warning: no {} file found for unit helper'.format(what), contents_of(log_file).strip()) -check_xcov_reports('obj/*.xcov', {'obj/main.adb.xcov': {'+': {3}}}) +check_xcov_reports('obj', {'main.adb.xcov': {'+': {3}}}) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py index ed1f31f56..263ca3536 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py @@ -97,7 +97,7 @@ def run_test(label, slug, main, helper, recursive, projects=[], units=[], expected_cov = {} for c in expected_cov_list: expected_cov.update(c) - check_xcov_reports('*.xcov', expected_cov, 'obj-main') + check_xcov_reports('obj-main', expected_cov) # Check that all xcov report files are created in obj-main (i.e. the root # project). diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py index 0570c58f1..56591ac87 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py @@ -39,7 +39,7 @@ def try_one(subdir, extra_covargs, xreports, xwarnings): mains=['test_t'], extra_coverage_args=['--annotate=xcov'] + extra_covargs) - check_xcov_reports('obj/*.xcov', xreports) + check_xcov_reports('obj', xreports) wlog = contents_of('coverage.log') for xw in xwarnings: @@ -54,8 +54,8 @@ def try_one(subdir, extra_covargs, xreports, xwarnings): subdir="wd_1", extra_covargs=[], xreports={ - 'obj/flip.adb.xcov': {'+': {3}}, - 'obj/test_t.adb.xcov': {'+': {4, 6}}}, + 'flip.adb.xcov': {'+': {3}}, + 'test_t.adb.xcov': {'+': {4, 6}}}, xwarnings=[]) try_one( diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py index 6e069ab1f..c8ae6ee8a 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py @@ -44,7 +44,7 @@ 'warning: no unit main (from --units) in the projects of interest', contents_of(log_file).strip()) -check_xcov_reports('*.xcov', {'helper.adb.xcov': {'+': {3}}}, 'obj-main') +check_xcov_reports('obj-main', {'helper.adb.xcov': {'+': {3}}}) # Check that all xcov report files are created in obj-main (i.e. the root # project). diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index a92b33ae1..e56063466 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -483,20 +483,16 @@ def remove_empty_sets(data): ) -def check_xcov_reports(xcov_filename_pattern, expected_cov, cwd=None): +def check_xcov_reports(reports_dir, expected_cov): """ Check the set of XCOV report files and their content. - Collect files that match "xcov_filename_pattern" (a glob pattern) and check - the set of files matches "expected_cov". Then, check that each report - matches the expected coverage results. + This checks that the set of "*.xcov" files in the directory "reports_dir" + matches files mentionned in "expected_cov" and that each report matches the + expected coverage result. "expected_cov" is a mapping: filename -> coverage data. See "check_xcov_content" for the coverage data format. - - If "cwd" is not None, it must be a valid directory name, and both the - filename patterns and the file names in expected_cov must be relative to - it. """ def fmt_sorted_indented_list(items): @@ -508,29 +504,24 @@ def fmt_sorted_indented_list(items): def canonicalize_file(filename): return filename.replace('\\', '/') - home_dir = None - try: - if cwd is not None: - home_dir = os.getcwd() - os.chdir(cwd) - - xcov_files = {canonicalize_file(filename) - for filename in glob.glob(xcov_filename_pattern)} - expected_cov = {canonicalize_file(filename): cov_data - for filename, cov_data in expected_cov.items()} + xcov_files = { + canonicalize_file(filename) + for filename in os.listdir(reports_dir) + if filename.endswith(".xcov") + } + expected_cov = { + canonicalize_file(filename): cov_data + for filename, cov_data in expected_cov.items() + } - thistest.fail_if( - xcov_files != set(expected_cov), - 'Unexpected XCOV files. Expected:\n' - '{}\n' - 'But got instead:\n' - '{}\n'.format(fmt_sorted_indented_list(expected_cov), - fmt_sorted_indented_list(xcov_files)) - ) + thistest.fail_if( + xcov_files != set(expected_cov), + "Unexpected XCOV files. Expected:\n" + f"{fmt_sorted_indented_list(expected_cov)}\n" + "But got instead:\n" + f"{fmt_sorted_indented_list(xcov_files)}\n" + ) - for filename, cov_data in expected_cov.items(): - if filename in xcov_files: - check_xcov_content(filename, cov_data) - finally: - if home_dir is not None: - os.chdir(home_dir) + for filename, cov_data in expected_cov.items(): + if filename in xcov_files: + check_xcov_content(os.path.join(reports_dir, filename), cov_data) diff --git a/testsuite/tests/106-externally-built-header/test.py b/testsuite/tests/106-externally-built-header/test.py index 0645d0d60..e85af939d 100644 --- a/testsuite/tests/106-externally-built-header/test.py +++ b/testsuite/tests/106-externally-built-header/test.py @@ -44,6 +44,6 @@ extra_coverage_args=["-axcov", "--output-dir=."], ) -check_xcov_reports("*.xcov", {"main.c.xcov": {"+": {6, 7}}}) +check_xcov_reports(".", {"main.c.xcov": {"+": {6, 7}}}) thistest.result() diff --git a/testsuite/tests/127-check-line-endings/test.py b/testsuite/tests/127-check-line-endings/test.py index 4ec472ffd..0ce760832 100644 --- a/testsuite/tests/127-check-line-endings/test.py +++ b/testsuite/tests/127-check-line-endings/test.py @@ -30,8 +30,6 @@ comment="wrong line ending in instrumented source", ) -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'+': {5}}, -}) +check_xcov_reports('xcov', {'main.adb.xcov': {'+': {5}}}) thistest.result() diff --git a/testsuite/tests/129-instr-progress/test.py b/testsuite/tests/129-instr-progress/test.py index e9e1f518f..9698163c6 100644 --- a/testsuite/tests/129-instr-progress/test.py +++ b/testsuite/tests/129-instr-progress/test.py @@ -37,13 +37,12 @@ # Sanity check: the insrument-build-coverage process completed with the # expected results. check_xcov_reports( - "*xcov", + "xcov", { "main.adb.xcov": {"+": {7, 8}}, "c_unit.c.xcov": {"+": {8}}, "cpp_unit.cpp.xcov": {"+": {10}}, }, - cwd="xcov", ) diff --git a/testsuite/tests/138-ada-preprocessing/example/test.py b/testsuite/tests/138-ada-preprocessing/example/test.py index 649a7b064..dc7ade4af 100644 --- a/testsuite/tests/138-ada-preprocessing/example/test.py +++ b/testsuite/tests/138-ada-preprocessing/example/test.py @@ -40,7 +40,7 @@ trace_mode="src", ) check_xcov_reports( - "*.xcov", + "xcov", { "test_eval.adb.xcov": {"+": {4}, "!": {12}, "-": {13}}, "vm.ads.xcov": {"+": {3, 4, 6, 7, 16, 17}}, @@ -77,7 +77,6 @@ }, }, }, - cwd="xcov", ) thistest.result() diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/test.py b/testsuite/tests/138-ada-preprocessing/prep_data/test.py index e35269f52..2a7eb5082 100644 --- a/testsuite/tests/138-ada-preprocessing/prep_data/test.py +++ b/testsuite/tests/138-ada-preprocessing/prep_data/test.py @@ -107,9 +107,7 @@ class ReportTestcase(BaseTestcase): extra_coverage_args=["-axcov", "--output-dir=xcov"], trace_mode="src", ) - check_xcov_reports( - "*.xcov", {"pkg.adb.xcov": t.expected_cov}, cwd="xcov" - ) + check_xcov_reports("xcov", {"pkg.adb.xcov": t.expected_cov}) tmp.to_homedir() thistest.log("") diff --git a/testsuite/tests/14-unused-separate/compilable/test.py b/testsuite/tests/14-unused-separate/compilable/test.py index 5a8c06756..aa75aa20f 100644 --- a/testsuite/tests/14-unused-separate/compilable/test.py +++ b/testsuite/tests/14-unused-separate/compilable/test.py @@ -30,6 +30,6 @@ "pkg.ads.xcov": {"+": {2}}, "pkg.adb.xcov": {"-": {2}}, } -check_xcov_reports("*.xcov", expected_cov, "obj") +check_xcov_reports("obj", expected_cov) thistest.result() diff --git a/testsuite/tests/14-unused-separate/uncompilable/test.py b/testsuite/tests/14-unused-separate/uncompilable/test.py index 80707d165..0502ce090 100644 --- a/testsuite/tests/14-unused-separate/uncompilable/test.py +++ b/testsuite/tests/14-unused-separate/uncompilable/test.py @@ -31,6 +31,6 @@ "pkg.ads.xcov": {"+": {2}}, "pkg.adb.xcov": {"-": {2}}, } -check_xcov_reports("*.xcov", expected_cov, "obj") +check_xcov_reports("obj", expected_cov) thistest.result() diff --git a/testsuite/tests/15-non-instr-cons/test.py b/testsuite/tests/15-non-instr-cons/test.py index 0094a59c1..9fed5b080 100644 --- a/testsuite/tests/15-non-instr-cons/test.py +++ b/testsuite/tests/15-non-instr-cons/test.py @@ -41,12 +41,6 @@ # Try to consolidate the checkpoint xcov(xcov_args + ["-Ctest_t.ckpt", "-Ctest_f.ckpt", "-axcov"]) -check_xcov_reports( - "*.xcov", - expected_cov={ - "pkg.ads.xcov": {"?": {10}, "+": {5,6,7}}, - }, - cwd="obj", -) +check_xcov_reports("obj", {"pkg.ads.xcov": {"?": {10}, "+": {5,6,7}}}) thistest.result() diff --git a/testsuite/tests/152-shared_setup/test.py b/testsuite/tests/152-shared_setup/test.py index c038e74d2..8a14d7fd5 100644 --- a/testsuite/tests/152-shared_setup/test.py +++ b/testsuite/tests/152-shared_setup/test.py @@ -120,6 +120,6 @@ ] ) -check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {5}}}, cwd="obj") +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) thistest.result() diff --git a/testsuite/tests/207-srctrace-version/test.py b/testsuite/tests/207-srctrace-version/test.py index ef4bb0640..b63c90746 100644 --- a/testsuite/tests/207-srctrace-version/test.py +++ b/testsuite/tests/207-srctrace-version/test.py @@ -64,7 +64,7 @@ # Otherwise, check the coverage report else: check_xcov_reports( - "*.xcov", + ".", { "main.adb.xcov": {"+": {15, 16}, "!": {12}}, "foo.c.xcov": {"!": {6}} diff --git a/testsuite/tests/222-scope-expr-func/test.py b/testsuite/tests/222-scope-expr-func/test.py index d94081320..1d07718b6 100644 --- a/testsuite/tests/222-scope-expr-func/test.py +++ b/testsuite/tests/222-scope-expr-func/test.py @@ -24,10 +24,6 @@ extra_coverage_args=["--subprograms=pkg.ads:2", "-axcov"] ) -check_xcov_reports( - "*.xcov", - {"pkg.adb.xcov": {"+": {5}}}, - cwd="obj" -) +check_xcov_reports("obj", {"pkg.adb.xcov": {"+": {5}}}) thistest.result() diff --git a/testsuite/tests/222-subp-line-computation/test.py b/testsuite/tests/222-subp-line-computation/test.py index 47434cc86..db209e19e 100644 --- a/testsuite/tests/222-subp-line-computation/test.py +++ b/testsuite/tests/222-subp-line-computation/test.py @@ -24,10 +24,6 @@ extra_coverage_args=["--subprograms=pkg.ads:5", "-axcov+"] ) -check_xcov_reports( - "*.xcov", - {"pkg.ads.xcov": {"+": {5}}}, - cwd="obj" -) +check_xcov_reports("obj", {"pkg.ads.xcov": {"+": {5}}}) thistest.result() diff --git a/testsuite/tests/222-subp-of-interest-cplx/test.py b/testsuite/tests/222-subp-of-interest-cplx/test.py index c5350dede..9734ace95 100644 --- a/testsuite/tests/222-subp-of-interest-cplx/test.py +++ b/testsuite/tests/222-subp-of-interest-cplx/test.py @@ -52,10 +52,6 @@ extra_coverage_args=["--subprograms=pkg.ads:3", "-axcov"] ) -check_xcov_reports( - "*.xcov", - {"pkg.adb.xcov": {"!": {12, 13}, "+": {14, 15}}}, - cwd="obj" -) +check_xcov_reports("obj", {"pkg.adb.xcov": {"!": {12, 13}, "+": {14, 15}}}) thistest.result() diff --git a/testsuite/tests/24_mixed_c_c++/test.py b/testsuite/tests/24_mixed_c_c++/test.py index 9a4f7c42a..60fdaf22d 100644 --- a/testsuite/tests/24_mixed_c_c++/test.py +++ b/testsuite/tests/24_mixed_c_c++/test.py @@ -20,12 +20,11 @@ ) check_xcov_reports( - "*.xcov", + "obj", { "test.cpp.xcov": {"+": {6, 7}}, "pkg.c.xcov": {"+": {4}}, }, - "obj", ) thistest.result() diff --git a/testsuite/tests/86-subproj_lang/test.py b/testsuite/tests/86-subproj_lang/test.py index 89709c9ed..64fee7469 100644 --- a/testsuite/tests/86-subproj_lang/test.py +++ b/testsuite/tests/86-subproj_lang/test.py @@ -41,9 +41,7 @@ ) check_xcov_reports( - "*.xcov", - {"calculations.c.xcov": {"+": {8, 9, 10, 11, 19, 20, 21, 22, 23}}}, - "xcov", + "xcov", {"calculations.c.xcov": {"+": {8, 9, 10, 11, 19, 20, 21, 22, 23}}} ) thistest.result() diff --git a/testsuite/tests/92-long_slugs/test.py b/testsuite/tests/92-long_slugs/test.py index 2beba8384..2338f92d5 100644 --- a/testsuite/tests/92-long_slugs/test.py +++ b/testsuite/tests/92-long_slugs/test.py @@ -67,13 +67,12 @@ # have the same case as the original filename. check_xcov_reports( - "*.xcov", + "obj", { "main.c.xcov": {"+": {6}}, (unit_name.lower() if "windows" in thistest.env.host.platform else unit_name) + ".c.xcov": {"+": {6}}, }, - "obj", ) thistest.result() diff --git a/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py b/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py index 8ae4ae796..48da8ab18 100644 --- a/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py +++ b/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py @@ -23,9 +23,8 @@ ) check_xcov_reports( - "*.xcov", - expected_cov={"main.c.xcov": {"+": {7, 15}, "!": {5, 17}, "-": {9}}}, - cwd="obj" + "obj", + {"main.c.xcov": {"+": {7, 15}, "!": {5, 17}, "-": {9}}}, ) thistest.fail_if_no_match( diff --git a/testsuite/tests/C/mcdc/include-current-dir/test.py b/testsuite/tests/C/mcdc/include-current-dir/test.py index 7f547c0d0..30d386c67 100644 --- a/testsuite/tests/C/mcdc/include-current-dir/test.py +++ b/testsuite/tests/C/mcdc/include-current-dir/test.py @@ -28,12 +28,12 @@ ) check_xcov_reports( - '*.xcov', + 'xcov', { 'pkg.h.xcov': {'+': {7, 8}, '!': {6}}, 'pkg.c.xcov': {'!': {4}}, 'test.c.xcov': {'+': {6, 7, 8}} }, - 'xcov') +) thistest.result() diff --git a/testsuite/tests/I812-011/test.py b/testsuite/tests/I812-011/test.py index 2dd326117..53ff62835 100644 --- a/testsuite/tests/I812-011/test.py +++ b/testsuite/tests/I812-011/test.py @@ -59,6 +59,6 @@ [tlist] ]: xcov(xcov_args + ['--annotate=xcov'] + arg) - check_xcov_reports('*.xcov', {'main.adb.xcov': {'+': {3}}}) + check_xcov_reports('.', {'main.adb.xcov': {'+': {3}}}) thistest.result() diff --git a/testsuite/tests/IA01-015/test.py b/testsuite/tests/IA01-015/test.py index 518696106..bcd51df95 100644 --- a/testsuite/tests/IA01-015/test.py +++ b/testsuite/tests/IA01-015/test.py @@ -35,7 +35,7 @@ def tryseq(label, scoargs): thistest.log('== {} =='.format(label)) xcov(coverage_base_args + scoargs) - check_xcov_reports('*.xcov', expected_reports) + check_xcov_reports('.', expected_reports) if thistest.options.trace_mode == 'src': diff --git a/testsuite/tests/M625-011-GPR-Cunits/test.py b/testsuite/tests/M625-011-GPR-Cunits/test.py index c3dec0732..a18d0b1b8 100644 --- a/testsuite/tests/M625-011-GPR-Cunits/test.py +++ b/testsuite/tests/M625-011-GPR-Cunits/test.py @@ -33,11 +33,10 @@ contents_of(coverage_log) ) -check_xcov_reports('*.xcov', { +check_xcov_reports('.', { 'foo.c.xcov': {'+': {6}}, 'bar.c.xcov': {'+': {6}}, 'bar.h.xcov': {'+': {9}} -} -) +}) thistest.result() diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test.py b/testsuite/tests/OA27-059-inlined-separate-cons/test.py index 888d8c3c3..5063dc4e4 100644 --- a/testsuite/tests/OA27-059-inlined-separate-cons/test.py +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test.py @@ -100,12 +100,5 @@ def clean_output_directory(): 'cons.log') # Finally, check we have the expected reports -check_xcov_reports( - os.path.join('output', '*.xcov'), - { - os.path.join('output', 'pkg.adb.xcov'): { - '+': {5, 6, 8}, - }, - } -) +check_xcov_reports('output', {'pkg.adb.xcov': {'+': {5, 6, 8}}}) thistest.result() diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test.py b/testsuite/tests/OA27-059-sep-cons-prj-override/test.py index a2dee0c00..953b71ac3 100644 --- a/testsuite/tests/OA27-059-sep-cons-prj-override/test.py +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test.py @@ -108,12 +108,11 @@ def clean_output_directory(): clean_output_directory() p = checked_xcov(xcov_args + ['--output-dir=output'] + trace_files, 'cons.log') check_xcov_reports( - '*.xcov', + 'output', { 'pkg_under_test.adb.xcov': {'+': {7, 8, 10}}, 'pkg_under_test-some_procedure.adb.xcov': {'-': {5}}, }, - 'output', ) thistest.result() diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test.py b/testsuite/tests/OA27-059-sep-cons-prj/test.py index 9eb4f0c3a..e55bba12e 100644 --- a/testsuite/tests/OA27-059-sep-cons-prj/test.py +++ b/testsuite/tests/OA27-059-sep-cons-prj/test.py @@ -88,8 +88,6 @@ def clean_output_directory(): # with the expected coverage data. clean_output_directory() p = checked_xcov(xcov_args + ['--output-dir=output'] + trace_files, 'cons.log') -check_xcov_reports( - '*.xcov', {'pkg_under_test.adb.xcov': {'+': {7, 8, 10}}}, 'output' -) +check_xcov_reports('output', {'pkg_under_test.adb.xcov': {'+': {7, 8, 10}}}) thistest.result() diff --git a/testsuite/tests/OA27-059-separate-consolidation/test.py b/testsuite/tests/OA27-059-separate-consolidation/test.py index f130d1fca..fcdb57afb 100644 --- a/testsuite/tests/OA27-059-separate-consolidation/test.py +++ b/testsuite/tests/OA27-059-separate-consolidation/test.py @@ -93,13 +93,6 @@ def build_and_run_tests(ignored_source_files=[]): clean_output_directory() xcov_args = build_and_run_tests(['pkg_under_test-pkg_test.adb']) p = checked_xcov(xcov_args, 'cons-2.log') -check_xcov_reports( - os.path.join('output', '*.xcov'), - { - os.path.join('output', 'pkg_under_test.adb.xcov'): { - '+': {7, 8, 10}, - } - } -) +check_xcov_reports('output', {'pkg_under_test.adb.xcov': {'+': {7, 8, 10}}}) thistest.result() diff --git a/testsuite/tests/P907-005-ckpt-covlevel/test.py b/testsuite/tests/P907-005-ckpt-covlevel/test.py index bbaa4de45..9a6679901 100644 --- a/testsuite/tests/P907-005-ckpt-covlevel/test.py +++ b/testsuite/tests/P907-005-ckpt-covlevel/test.py @@ -69,11 +69,11 @@ def clean_output_directory(): xcov(args + ['--level=stmt'], 'cons-stmt.log') expected = { - os.path.join('output', 'math.adb.xcov'): { - '+': {7, 12, 13, 14, 17, 18, 19}}, - os.path.join('output', 'math.ads.xcov'): {}} + 'math.adb.xcov': {'+': {7, 12, 13, 14, 17, 18, 19}}, + 'math.ads.xcov': {}, +} # Finally, check we have the expected reports for the --level=stmt # consolidation. -check_xcov_reports(os.path.join('output', '*.xcov'), expected) +check_xcov_reports('output', expected) thistest.result() diff --git a/testsuite/tests/P907-005-incremental/test.py b/testsuite/tests/P907-005-incremental/test.py index 08bff3ccb..48989f685 100644 --- a/testsuite/tests/P907-005-incremental/test.py +++ b/testsuite/tests/P907-005-incremental/test.py @@ -43,7 +43,7 @@ # Finally, check we have the expected reports check_xcov_reports( - '*.xcov', + '.', {'math.adb.xcov': {'+': {7, 12, 13, 14, 18, 19}, '!': {17}}, 'math.ads.xcov': {}}) diff --git a/testsuite/tests/P907-005-stubbing-generic/test.py b/testsuite/tests/P907-005-stubbing-generic/test.py index 37dc70d30..4abc78cb1 100644 --- a/testsuite/tests/P907-005-stubbing-generic/test.py +++ b/testsuite/tests/P907-005-stubbing-generic/test.py @@ -56,7 +56,7 @@ def __init__(self, test_dir, exename): # Finally, check we have the expected reports check_xcov_reports( - '*.xcov', + '.', { 'pressure_control.adb.xcov': { '+': {10, 18, 19}, diff --git a/testsuite/tests/P907-005-stubbing/test.py b/testsuite/tests/P907-005-stubbing/test.py index a1bf453f9..4e5040125 100644 --- a/testsuite/tests/P907-005-stubbing/test.py +++ b/testsuite/tests/P907-005-stubbing/test.py @@ -55,7 +55,7 @@ def __init__(self, test_dir, exename): # Finally, check we have the expected reports check_xcov_reports( - '*.xcov', + '.', { 'pressure_control.adb.xcov': { '+': {10, 18, 19}, diff --git a/testsuite/tests/Q224-032-several-out-of-line/test.py b/testsuite/tests/Q224-032-several-out-of-line/test.py index 2170266d7..56016eca8 100644 --- a/testsuite/tests/Q224-032-several-out-of-line/test.py +++ b/testsuite/tests/Q224-032-several-out-of-line/test.py @@ -24,6 +24,6 @@ checked_xcov(['coverage', '-P{}'.format(gpr), '-cstmt', '-axcov', '--output-dir=.', trace], 'coverage.log') -check_xcov_reports('*.xcov', {'bar.c.xcov': {'+': {4}}, }) +check_xcov_reports('.', {'bar.c.xcov': {'+': {4}}}) thistest.result() diff --git a/testsuite/tests/Q327-016-glob-ignore/test.py b/testsuite/tests/Q327-016-glob-ignore/test.py index fdb8f41b3..3e915f5cf 100644 --- a/testsuite/tests/Q327-016-glob-ignore/test.py +++ b/testsuite/tests/Q327-016-glob-ignore/test.py @@ -27,7 +27,6 @@ # Check we have the expected reports check_xcov_reports( - '*.xcov', - {'main.adb.xcov': {'+': {6, 7}}, - 'pkg_a.adb.xcov': {'+': {6}}}) + '.', {'main.adb.xcov': {'+': {6, 7}}, 'pkg_a.adb.xcov': {'+': {6}}} +) thistest.result() diff --git a/testsuite/tests/Q329-018-create-output-dir/test.py b/testsuite/tests/Q329-018-create-output-dir/test.py index d63189006..6ab6aa9f8 100644 --- a/testsuite/tests/Q329-018-create-output-dir/test.py +++ b/testsuite/tests/Q329-018-create-output-dir/test.py @@ -29,7 +29,5 @@ 'gnatcov does not say it is creating directories, it should') # Finally, check we have the expected reports -check_xcov_reports( - os.path.join(output_dir, '*.xcov'), - {os.path.join(output_dir, 'foo.adb.xcov'): {'+': {5}}}) +check_xcov_reports(output_dir, {'foo.adb.xcov': {'+': {5}}}) thistest.result() diff --git a/testsuite/tests/Q905-005-compressed/test.py b/testsuite/tests/Q905-005-compressed/test.py index 638c63445..82fb5a3b2 100644 --- a/testsuite/tests/Q905-005-compressed/test.py +++ b/testsuite/tests/Q905-005-compressed/test.py @@ -19,6 +19,6 @@ checked_xcov(['coverage', '-P{}'.format(gpr), '-cstmt', '-axcov', '--output-dir=.', trace], 'coverage.log') -check_xcov_reports('*.xcov', {'foo.adb.xcov': {'+': {6, 7, 9, 13}}, }) +check_xcov_reports('.', {'foo.adb.xcov': {'+': {6, 7, 9, 13}}}) thistest.result() diff --git a/testsuite/tests/RB13-019-win-paths/test.py b/testsuite/tests/RB13-019-win-paths/test.py index ac16e2159..6a01fc689 100644 --- a/testsuite/tests/RB13-019-win-paths/test.py +++ b/testsuite/tests/RB13-019-win-paths/test.py @@ -79,10 +79,6 @@ ], ) -check_xcov_reports( - "wibble.c.xcov", - {"wibble.c.xcov": {"+": {8, 12}, "!": {6}}}, - cwd="coverage" -) +check_xcov_reports("coverage", {"wibble.c.xcov": {"+": {8, 12}, "!": {6}}}) thistest.result() diff --git a/testsuite/tests/RC04-030-bad-trace/test.py b/testsuite/tests/RC04-030-bad-trace/test.py index eb7ecea5f..9fdee09cd 100644 --- a/testsuite/tests/RC04-030-bad-trace/test.py +++ b/testsuite/tests/RC04-030-bad-trace/test.py @@ -84,23 +84,19 @@ def gnatcov_coverage(keep_reading_traces): # Make sure that without --keep-reading-traces, no coverage report is produced gnatcov_coverage(False) -check_xcov_reports('obj/*.xcov', {}) - - -def in_obj(filename): - return os.path.join('obj', filename) +check_xcov_reports('obj', {}) # Make sure that with it, both the first and the last trace files contributed # to coverage assessment, while the middle one was skipped. gnatcov_coverage(True) check_xcov_reports( - in_obj('*.xcov'), - {in_obj('pkg.adb.xcov'): {'+': {11, 12, 14, 17, 18}, - '-': {15}}, - in_obj('main_a.adb.xcov'): {'+': {5}}, - in_obj('main_b.adb.xcov'): {'-': {5}}, - in_obj('main_c.adb.xcov'): {'+': {5}}} + 'obj', + {'pkg.adb.xcov': {'+': {11, 12, 14, 17, 18}, + '-': {15}}, + 'main_a.adb.xcov': {'+': {5}}, + 'main_b.adb.xcov': {'-': {5}}, + 'main_c.adb.xcov': {'+': {5}}} ) thistest.result() diff --git a/testsuite/tests/S527-004-ckpt-no-level/test.py b/testsuite/tests/S527-004-ckpt-no-level/test.py index a5e168583..b25540b79 100644 --- a/testsuite/tests/S527-004-ckpt-no-level/test.py +++ b/testsuite/tests/S527-004-ckpt-no-level/test.py @@ -38,6 +38,6 @@ actual=contents_of(log_file), ) -check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {2, 5, 6}}}) +check_xcov_reports(".", {"main.adb.xcov": {"+": {2, 5, 6}}}) thistest.result() diff --git a/testsuite/tests/S603-009-externally-built/test.py b/testsuite/tests/S603-009-externally-built/test.py index 30b9070d6..00bd9849b 100644 --- a/testsuite/tests/S603-009-externally-built/test.py +++ b/testsuite/tests/S603-009-externally-built/test.py @@ -90,7 +90,7 @@ def check_coverage(project, externally_built, expected_cov, if not register_failure: return p - check_xcov_reports(os.path.join(output_dir, '*.xcov'), expected_cov) + check_xcov_reports(output_dir, expected_cov) # First, make sure that "gnatcov coverage" on an externally built project @@ -120,18 +120,16 @@ def check_coverage(project, externally_built, expected_cov, # It should not complain with --externally-built-projects p = check_coverage( project='mylib.gpr', externally_built=True, - expected_cov={os.path.join(output_dir, 'mylib.adb.xcov'): {'+': {5, 6}, - '-': {8}}}) + expected_cov={'mylib.adb.xcov': {'+': {5, 6}, '-': {8}}}) # Make sure coverage computation gives the expected result with and without # --externally-built-projects check_coverage( project=main_gpr, externally_built=False, - expected_cov={os.path.join(output_dir, 'main.adb.xcov'): {'+': {4, 6}}}) + expected_cov={'main.adb.xcov': {'+': {4, 6}}}) check_coverage( project=main_gpr, externally_built=True, - expected_cov={os.path.join(output_dir, 'main.adb.xcov'): {'+': {4, 6}}, - os.path.join(output_dir, 'mylib.adb.xcov'): {'+': {5, 6}, - '-': {8}}}) + expected_cov={'main.adb.xcov': {'+': {4, 6}}, + 'mylib.adb.xcov': {'+': {5, 6}, '-': {8}}}) thistest.result() diff --git a/testsuite/tests/S619-014-tag-provider-mismatch/test.py b/testsuite/tests/S619-014-tag-provider-mismatch/test.py index 22add3160..c3d6e4ebd 100644 --- a/testsuite/tests/S619-014-tag-provider-mismatch/test.py +++ b/testsuite/tests/S619-014-tag-provider-mismatch/test.py @@ -37,7 +37,6 @@ 'but got:\n' '{}'.format(indent(expected), indent(actual))) -check_xcov_reports('*.xcov', {'main.adb.xcov': {}, - 'generic_hello.adb.xcov': {}}) +check_xcov_reports('.', {'main.adb.xcov': {}, 'generic_hello.adb.xcov': {}}) thistest.result() diff --git a/testsuite/tests/S621-026-mcdc-ckpt/test.py b/testsuite/tests/S621-026-mcdc-ckpt/test.py index dadf1fc98..fd2599a7c 100644 --- a/testsuite/tests/S621-026-mcdc-ckpt/test.py +++ b/testsuite/tests/S621-026-mcdc-ckpt/test.py @@ -26,7 +26,7 @@ xcov(['coverage', '--annotate=xcov', '--level=stmt+mcdc', '--checkpoint=c1.ckpt', '--checkpoint=c2.ckpt']) -check_xcov_reports('*.xcov', { +check_xcov_reports('.', { 'main1.adb.xcov': {'+': {5}}, 'main2.adb.xcov': {'+': {5, 7, 11, 12, 13, 15}, '!': {4}}}) diff --git a/testsuite/tests/T807-011-externally-built-objdir/test.py b/testsuite/tests/T807-011-externally-built-objdir/test.py index 72f5891ea..419ce39b0 100644 --- a/testsuite/tests/T807-011-externally-built-objdir/test.py +++ b/testsuite/tests/T807-011-externally-built-objdir/test.py @@ -48,9 +48,9 @@ trace_mode='src' ) -check_xcov_reports('report/*.xcov', { - 'report/ops.ads.xcov': {}, - 'report/ops.adb.xcov': {'+': {4, 5}, '-': {6}}, +check_xcov_reports('report', { + 'ops.ads.xcov': {}, + 'ops.adb.xcov': {'+': {4, 5}, '-': {6}}, }) # Re-run the instrumenter on the main, to check that it does not re-create a diff --git a/testsuite/tests/T825-010-naming-scheme/test.py b/testsuite/tests/T825-010-naming-scheme/test.py index 0a1f7aa61..1d2cafdca 100644 --- a/testsuite/tests/T825-010-naming-scheme/test.py +++ b/testsuite/tests/T825-010-naming-scheme/test.py @@ -28,12 +28,12 @@ mains=['main'], extra_coverage_args=['-axcov', '--output-dir=report'] ) -check_xcov_reports('report/*.xcov', { - 'report/main.adb.xcov': {'+': {5}}, - 'report/p.1.ada.xcov': {}, - 'report/p.2.ada.xcov': {'+': {4}}, - 'report/p__q.1.ada.xcov': {'+': {3}}, - 'report/p__q.2.ada.xcov': {'+': {6}}, +check_xcov_reports('report', { + 'main.adb.xcov': {'+': {5}}, + 'p.1.ada.xcov': {}, + 'p.2.ada.xcov': {'+': {4}}, + 'p__q.1.ada.xcov': {'+': {3}}, + 'p__q.2.ada.xcov': {'+': {6}}, }) thistest.result() diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/test.py b/testsuite/tests/TA15-063-ignore-fingerprint/test.py index 52b5c413d..168c1f12a 100644 --- a/testsuite/tests/TA15-063-ignore-fingerprint/test.py +++ b/testsuite/tests/TA15-063-ignore-fingerprint/test.py @@ -62,10 +62,10 @@ def check_empty(filename): "-Cc1.ckpt", "-Cc2.ckpt"], out="log-cons.txt") check_empty("log-cons.txt") -check_xcov_reports("report/*.xcov", { - "report/main.adb.xcov": {"+": {5}}, - "report/pkg.adb.xcov": {"+": {2}}, - "report/pkg-test.adb.xcov": {"-": {8, 9}}, +check_xcov_reports("report", { + "main.adb.xcov": {"+": {5}}, + "pkg.adb.xcov": {"+": {2}}, + "pkg-test.adb.xcov": {"-": {8, 9}}, }) thistest.result() diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py index 1ae63fb4c..40b80df02 100644 --- a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py @@ -43,11 +43,11 @@ def check(report_name, args, expected_files): checked_xcov(args + ['-axcov', '--output-dir='+report_name], f'{report_name}_out.txt') expected = { - os.path.join(report_name, filename): - expected_res_dict[filename] + filename: expected_res_dict[filename] for filename in expected_files } - check_xcov_reports(os.path.join(report_name, 'pkg*.xcov'), expected) + expected["main.adb.xcov"] = {"+": {5, 6}} + check_xcov_reports(report_name, expected) # Check that not passing the option has no effect diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/test.py b/testsuite/tests/TB13-020-expr-func-mcdc/test.py index 8935e0eb4..313a6c763 100644 --- a/testsuite/tests/TB13-020-expr-func-mcdc/test.py +++ b/testsuite/tests/TB13-020-expr-func-mcdc/test.py @@ -27,13 +27,13 @@ mains=["main"], extra_coverage_args=["-axcov", "--output-dir=report"]) -check_xcov_reports("report/*.xcov", { - "report/main.adb.xcov": { +check_xcov_reports("report", { + "main.adb.xcov": { "!": {6, 9, 15, 19}, "+": {11, 12}, "-": {16, 20}}, - "report/pkg.ads.xcov": {}, - "report/pkg.adb.xcov": {"+": {9}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {9}}, }) thistest.result() diff --git a/testsuite/tests/TC03-012-objcov-line-state/test.py b/testsuite/tests/TC03-012-objcov-line-state/test.py index 431d437c7..1d30fb4d1 100644 --- a/testsuite/tests/TC03-012-objcov-line-state/test.py +++ b/testsuite/tests/TC03-012-objcov-line-state/test.py @@ -23,7 +23,6 @@ xcov(['coverage', '-cinsn', '-axcov', '-Pgen', tracename_for('main')]) # Check that line 3 is correctly marked as partially covered -check_xcov_reports('main.c.xcov', - {'main.c.xcov': {'-': {4}, '!': {3}}}) +check_xcov_reports('.', {'main.c.xcov': {'-': {4}, '!': {3}}}) thistest.result() diff --git a/testsuite/tests/U204-026-arch-mix/test.py b/testsuite/tests/U204-026-arch-mix/test.py index 6f3fed02d..e87855bd3 100644 --- a/testsuite/tests/U204-026-arch-mix/test.py +++ b/testsuite/tests/U204-026-arch-mix/test.py @@ -45,13 +45,12 @@ def check_reports(xcov_dir): mains. """ check_xcov_reports( - "*.xcov", + xcov_dir, { "main_1.adb.xcov": {"+": {5}}, "main_2.adb.xcov": {"+": {5}}, "pkg.adb.xcov": {"+": {12, 14}, "!": {11}} }, - xcov_dir, ) diff --git a/testsuite/tests/U204-029-source-rebase/test_support.py b/testsuite/tests/U204-029-source-rebase/test_support.py index f142d6a5f..29e826ca7 100644 --- a/testsuite/tests/U204-029-source-rebase/test_support.py +++ b/testsuite/tests/U204-029-source-rebase/test_support.py @@ -75,11 +75,7 @@ def consolidate_and_check(variant_basename, " not empty:\n " + contents_of(log_filename) ) - check_xcov_reports( - os.path.join(output_dir_name, "*.xcov"), - {os.path.join(output_dir_name, filename): results - for filename, results in expected_xcov_results.items()} - ) + check_xcov_reports(output_dir_name, expected_xcov_results) def run_variant(variant_basename, diff --git a/testsuite/tests/U208-020-child-project/test.py b/testsuite/tests/U208-020-child-project/test.py index 6c62622cf..93eba2b2b 100644 --- a/testsuite/tests/U208-020-child-project/test.py +++ b/testsuite/tests/U208-020-child-project/test.py @@ -23,8 +23,8 @@ gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, trace_mode='src') -check_xcov_reports('xcov/*.xcov', - {'xcov/main.adb.xcov': {'+': {5, 6}}, - 'xcov/pkg.adb.xcov': {'+': {5}}}) +check_xcov_reports('xcov', + {'main.adb.xcov': {'+': {5, 6}}, + 'pkg.adb.xcov': {'+': {5}}}) thistest.result() diff --git a/testsuite/tests/U208-020-error-call/test.py b/testsuite/tests/U208-020-error-call/test.py index ecea0f505..1b7645b0e 100644 --- a/testsuite/tests/U208-020-error-call/test.py +++ b/testsuite/tests/U208-020-error-call/test.py @@ -22,5 +22,5 @@ mains=["main"], extra_coverage_args=["--annotate=xcov"]) -check_xcov_reports('obj/main.c.xcov', {'obj/main.c.xcov': {'+': {6, 7}}}) +check_xcov_reports('obj', {'main.c.xcov': {'+': {6, 7}}}) thistest.result() diff --git a/testsuite/tests/U208-020-unique-language-project/test.py b/testsuite/tests/U208-020-unique-language-project/test.py index fe8404224..d3c3b533f 100644 --- a/testsuite/tests/U208-020-unique-language-project/test.py +++ b/testsuite/tests/U208-020-unique-language-project/test.py @@ -31,7 +31,7 @@ "of an Ada project should only produce Ada files.") break -check_xcov_reports('obj/main.adb.xcov', {'obj/main.adb.xcov': {'+': {3}}}) +check_xcov_reports('obj', {'main.adb.xcov': {'+': {3}}}) build_run_and_coverage( gprsw=GPRswitches( @@ -47,5 +47,5 @@ "of a C project should only produce C files.") break -check_xcov_reports('obj/main.c.xcov', {'obj/main.c.xcov': {'+': {4}}}) +check_xcov_reports('obj', {'main.c.xcov': {'+': {4}}}) thistest.result() diff --git a/testsuite/tests/U211-014-setup/test.py b/testsuite/tests/U211-014-setup/test.py index 4864a0f6d..3dcb8a806 100644 --- a/testsuite/tests/U211-014-setup/test.py +++ b/testsuite/tests/U211-014-setup/test.py @@ -140,7 +140,7 @@ def check_full(label, setup_args, prj_config, runtime_project=rt_prj, "Successfully loaded the setup configuration file" not in contents_of("instrument.log"), "Failed to load the setup config file in `gnatcov instrument`") - check_xcov_reports("*.xcov", prj_config.expected_cov, f"xcov-{label}") + check_xcov_reports(f"xcov-{label}", prj_config.expected_cov) # "gnatcov setup" (+ relevant target options) is supposed to work out of the diff --git a/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py index cad97dfe2..741d33d8e 100644 --- a/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py +++ b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py @@ -22,8 +22,8 @@ checked_xcov(xcov_args, "coverage.log") -check_xcov_reports("obj/*.xcov", { - "obj/main.adb.xcov": {"+": {11, 12, 13}, "-": {16, 17, 20, 21}}, +check_xcov_reports("obj", { + "main.adb.xcov": {"+": {11, 12, 13}, "-": {16, 17, 20, 21}}, }) thistest.result() diff --git a/testsuite/tests/U416-006-big-bdd/test.py b/testsuite/tests/U416-006-big-bdd/test.py index a64b37deb..02fd03a47 100644 --- a/testsuite/tests/U416-006-big-bdd/test.py +++ b/testsuite/tests/U416-006-big-bdd/test.py @@ -67,7 +67,7 @@ def do_one_level(level): expected_cov["testconditions.adb.xcov"]['+'].add(17) expected_cov["compute.c.xcov"]['+'].add(4) - check_xcov_reports("*.xcov", expected_cov, cwd="obj") + check_xcov_reports("obj", expected_cov) if level == "stmt+mcdc": # The order in which sources are instrumented is not specified, so sort diff --git a/testsuite/tests/U527-020-dc-from-mcdc/test.py b/testsuite/tests/U527-020-dc-from-mcdc/test.py index 74fc09df1..5ac38b6f7 100644 --- a/testsuite/tests/U527-020-dc-from-mcdc/test.py +++ b/testsuite/tests/U527-020-dc-from-mcdc/test.py @@ -35,8 +35,6 @@ xcov(xcov_args) -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'+': {2}, '!': {5}, '-': {6}}, -}) +check_xcov_reports('xcov', {'main.adb.xcov': {'+': {2}, '!': {5}, '-': {6}}}) thistest.result() diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/test.py b/testsuite/tests/UB18-055-switches-in-gprfile/test.py index ef6ffc0fd..f07edcadb 100644 --- a/testsuite/tests/UB18-055-switches-in-gprfile/test.py +++ b/testsuite/tests/UB18-055-switches-in-gprfile/test.py @@ -38,6 +38,6 @@ # Check that we have coverage result only for the project of interest, as # specified in the gpr file. -check_xcov_reports("*.xcov", {"b.adb.xcov": {"+": {6}}}) +check_xcov_reports(".", {"b.adb.xcov": {"+": {6}}}) thistest.result() diff --git a/testsuite/tests/V120-034-dup-langs/test.py b/testsuite/tests/V120-034-dup-langs/test.py index 99244db59..6c7198c59 100644 --- a/testsuite/tests/V120-034-dup-langs/test.py +++ b/testsuite/tests/V120-034-dup-langs/test.py @@ -23,8 +23,6 @@ trace_mode="src", ) -check_xcov_reports("obj/*.xcov", { - "obj/main.adb.xcov": {"+": {2, 5}, "-": {6}}, -}) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {2, 5}, "-": {6}}}) thistest.result() diff --git a/testsuite/tests/V201-010-multi-report/test.py b/testsuite/tests/V201-010-multi-report/test.py index 935ee49a9..b5b4db8e1 100644 --- a/testsuite/tests/V201-010-multi-report/test.py +++ b/testsuite/tests/V201-010-multi-report/test.py @@ -25,9 +25,7 @@ ) # For the xcov report kind we can check the actual content -check_xcov_reports("obj/xcov/*.xcov", { - "obj/xcov/main.adb.xcov": {"+": {2, 5}, "-": {6}}, -}) +check_xcov_reports("obj/xcov", {"main.adb.xcov": {"+": {2, 5}, "-": {6}}}) # Check that there is a report in the log of the coverage command thistest.fail_if_no_match( diff --git a/testsuite/tests/V309-017-setup-config/test.py b/testsuite/tests/V309-017-setup-config/test.py index 624c9a1ff..5cbd2ff7f 100644 --- a/testsuite/tests/V309-017-setup-config/test.py +++ b/testsuite/tests/V309-017-setup-config/test.py @@ -91,7 +91,7 @@ def xsetup(install_name, args): dump_channel=None, trace_mode="src", ) - check_xcov_reports("*.xcov", {"foo.adb.xcov": {"+": {5}}}) + check_xcov_reports(".", {"foo.adb.xcov": {"+": {5}}}) # Make sure that the metadata contains the expected dump channel with open("obj/gnatcov-instr.json") as f: diff --git a/testsuite/tests/V520-019-duplicate-messages/test.py b/testsuite/tests/V520-019-duplicate-messages/test.py index 13e5162f5..5e27efcb2 100644 --- a/testsuite/tests/V520-019-duplicate-messages/test.py +++ b/testsuite/tests/V520-019-duplicate-messages/test.py @@ -24,10 +24,9 @@ ) # Check the expected results -check_xcov_reports("*.xcov", +check_xcov_reports("obj", {"main.adb.xcov": {}, - "pkg.adb.xcov" : {'-': {10}}}, - cwd="obj") + "pkg.adb.xcov" : {'-': {10}}}) # Check that we do not have any duplicate messages. In this case, we only # expect a single statment violation. diff --git a/testsuite/tests/V824-005-sid-ext-prj/test.py b/testsuite/tests/V824-005-sid-ext-prj/test.py index 9c3575459..31e1ad17f 100644 --- a/testsuite/tests/V824-005-sid-ext-prj/test.py +++ b/testsuite/tests/V824-005-sid-ext-prj/test.py @@ -45,6 +45,6 @@ # Compute the coverage report and check its contents (sanity check) xcov(xcov_args, out="coverage.log") -check_xcov_reports("*.xcov", {"pkg.adb.xcov": {'+': {11}}}, "output") +check_xcov_reports("output", {"pkg.adb.xcov": {'+': {11}}}) thistest.result() diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py index f7fb0eb15..262c1e51d 100644 --- a/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py +++ b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py @@ -21,6 +21,6 @@ dump_trigger='main-end', ) -check_xcov_reports('*.xcov', {'foo.c.xcov': {'+': {4}}}, 'xcov') +check_xcov_reports('xcov', {'foo.c.xcov': {'+': {4}}}) thistest.result() diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py b/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py index e7248eb1f..f5542b8fb 100644 --- a/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py +++ b/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py @@ -22,6 +22,6 @@ dump_trigger='main-end', ) -check_xcov_reports('*.xcov', {'test.c.xcov': {'+': {4}, '!': {5}}}, 'xcov') +check_xcov_reports('xcov', {'test.c.xcov': {'+': {4}, '!': {5}}}) thistest.result() diff --git a/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py index 799e159e9..93784100a 100644 --- a/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py +++ b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py @@ -33,12 +33,11 @@ ) check_xcov_reports( - "*.xcov", + "obj", expected_cov={ "pkg_1.ads.xcov": {"?": {10}, "+": {12}}, "pkg_2.ads.xcov": {"?": {10}, "+": {12}}, }, - cwd="obj", ) thistest.result() diff --git a/testsuite/tests/VB07-015-clean-output-dir/test.py b/testsuite/tests/VB07-015-clean-output-dir/test.py index 34c986691..e2e8be779 100644 --- a/testsuite/tests/VB07-015-clean-output-dir/test.py +++ b/testsuite/tests/VB07-015-clean-output-dir/test.py @@ -33,11 +33,10 @@ def check_one(units, output_dir, xcov_args): for dir in possible_output_dirs: thistest.log(f"inspecting {dir}") check_xcov_reports( - "*.xcov", + dir, {f"{unit}.adb.xcov": expected_cov_per_unit[unit] for unit in units} if dir == output_dir else {}, - cwd=dir, ) diff --git a/testsuite/tests/VB18-035-default-opts/test.py b/testsuite/tests/VB18-035-default-opts/test.py index ae7795c66..601dd6c84 100644 --- a/testsuite/tests/VB18-035-default-opts/test.py +++ b/testsuite/tests/VB18-035-default-opts/test.py @@ -44,11 +44,7 @@ def check_log(command, log_file): xcov(cov_args + ["-axcov"], out=cov_log) check_log("coverage", cov_log) -check_xcov_reports( - "*.xcov", - {"main.adb.xcov": {"+": {2, 5, 6}, "-": {8}}}, - cwd="obj" -) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {2, 5, 6}, "-": {8}}}) # 3. Run the coverage command without specifying an annotation format and # check if there is a report on the standard output. diff --git a/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py b/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py index b1299e477..bdf830005 100644 --- a/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py +++ b/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py @@ -41,8 +41,6 @@ " inconsistent with the corresponding Source Instrumentation Data", contents_of("coverage.log").strip(), ) -check_xcov_reports( - "*.xcov", {"main.adb.xcov": {"-": {4, 5, 7, 11, 12, 14}}}, "obj" -) +check_xcov_reports("obj", {"main.adb.xcov": {"-": {4, 5, 7, 11, 12, 14}}}) thistest.result() diff --git a/testsuite/tests/VC19-001-origin-prj/test.py b/testsuite/tests/VC19-001-origin-prj/test.py index d3af4c0e1..c2d01885f 100644 --- a/testsuite/tests/VC19-001-origin-prj/test.py +++ b/testsuite/tests/VC19-001-origin-prj/test.py @@ -45,6 +45,6 @@ mains=["test_main"], ) -check_xcov_reports("*.xcov", {"code.adb.xcov": {"!": {4}}}, cwd="xcov") +check_xcov_reports("xcov", {"code.adb.xcov": {"!": {4}}}) thistest.result() diff --git a/testsuite/tests/W315-021-generic-preelab/test.py b/testsuite/tests/W315-021-generic-preelab/test.py index 66596ddca..185348700 100644 --- a/testsuite/tests/W315-021-generic-preelab/test.py +++ b/testsuite/tests/W315-021-generic-preelab/test.py @@ -18,13 +18,12 @@ ) check_xcov_reports( - "*.xcov", + "obj", { "test.adb.xcov": {"+": {4, 6}}, "pkg.ads.xcov": {"+": {}}, "pkg.adb.xcov": {"+": {4}}, }, - "obj", ) thistest.result() diff --git a/testsuite/tests/excluded_unit_imported_prj/test.py b/testsuite/tests/excluded_unit_imported_prj/test.py index 126c5b972..a57fa295c 100644 --- a/testsuite/tests/excluded_unit_imported_prj/test.py +++ b/testsuite/tests/excluded_unit_imported_prj/test.py @@ -40,12 +40,11 @@ # Check that pkg.c is not ignored by checking the report contents check_xcov_reports( - '*.xcov', + 'obj', { 'pkg.c.xcov': {'!': {4}}, 'test.c.xcov': {'+': {6, 7}} }, - 'obj' ) thistest.result() diff --git a/testsuite/tests/header_not_found/test.py b/testsuite/tests/header_not_found/test.py index df236b173..836fdad39 100644 --- a/testsuite/tests/header_not_found/test.py +++ b/testsuite/tests/header_not_found/test.py @@ -24,7 +24,7 @@ def process(gpr_dir, expected_cov): gpr_exe_dir=gpr_obj_dir, extra_coverage_args=["--annotate=xcov"], ) - check_xcov_reports("*.xcov", expected_cov, gpr_obj_dir) + check_xcov_reports(gpr_obj_dir, expected_cov) # Check that the header in the extended project is picked by gnatcov instrument diff --git a/testsuite/tests/homonym-units-of-interest/test.py b/testsuite/tests/homonym-units-of-interest/test.py index 8633124f8..294f6e088 100644 --- a/testsuite/tests/homonym-units-of-interest/test.py +++ b/testsuite/tests/homonym-units-of-interest/test.py @@ -76,12 +76,11 @@ def check_report(prj_ignore, prj_of_interest): else 'pkg.c.xcov' ) check_xcov_reports( - '*.xcov', + 'xcov', { xcov_homonoym_filename: {'!': {4}}, 'test.c.xcov': {'+': {7, 8, 9}} }, - 'xcov' ) wd.to_homedir() diff --git a/testsuite/tests/ignored-c-file/test.py b/testsuite/tests/ignored-c-file/test.py index 4482a7d70..cdb998468 100644 --- a/testsuite/tests/ignored-c-file/test.py +++ b/testsuite/tests/ignored-c-file/test.py @@ -17,12 +17,6 @@ extra_coverage_args=["--annotate=xcov", "--ignore-source-files=foo.c"], ) -check_xcov_reports( - "*.xcov", - { - "test.c.xcov": {"+": {6, 7}} - }, - "obj", -) +check_xcov_reports("obj", {"test.c.xcov": {"+": {6, 7}}}) thistest.result() diff --git a/testsuite/tests/ignored-c-header/test.py b/testsuite/tests/ignored-c-header/test.py index 229b84d90..3d88bff12 100644 --- a/testsuite/tests/ignored-c-header/test.py +++ b/testsuite/tests/ignored-c-header/test.py @@ -52,6 +52,6 @@ expected_coverage.pop("identity.h.xcov") -check_xcov_reports("*.xcov", expected_coverage, "obj") +check_xcov_reports("obj", expected_coverage) thistest.result() diff --git a/testsuite/tests/ignored-casing/test.py b/testsuite/tests/ignored-casing/test.py index 45bd72570..e3e4b438e 100644 --- a/testsuite/tests/ignored-casing/test.py +++ b/testsuite/tests/ignored-casing/test.py @@ -29,7 +29,7 @@ "--annotate=xcov", "--output-dir=out-cov", ignore_opt ], ) -check_xcov_reports("*.xcov", expected_reports, "out-cov") +check_xcov_reports("out-cov", expected_reports) # Then check it on "gnatcov instrument". This separate test makes sense as # --ignore-source-files exercises different code paths depending on the gnatcov @@ -43,6 +43,6 @@ extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], trace_mode="src" ) -check_xcov_reports("*.xcov", expected_reports, "out-instr") +check_xcov_reports("out-instr", expected_reports) thistest.result() diff --git a/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py b/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py index 1dfb57e36..1e66329bf 100644 --- a/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py +++ b/testsuite/tests/instr-cov/141-trigger-manual-pp-search-path/test.py @@ -31,12 +31,6 @@ trace_mode="src", ) -check_xcov_reports( - "*.xcov", - { - "main.c.xcov": {"+": {6}, "-": {8}}, - }, - "xcov", -) +check_xcov_reports("xcov", {"main.c.xcov": {"+": {6}, "-": {8}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py b/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py index 5cc76f804..5f06b9cab 100644 --- a/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py +++ b/testsuite/tests/instr-cov/141-trigger-manual-pp-switch-in-prj/test.py @@ -25,12 +25,6 @@ trace_mode="src", ) -check_xcov_reports( - "*.xcov", - { - "main.c.xcov": {"+": {5}, "-": {7}}, - }, - "xcov", -) +check_xcov_reports("xcov", {"main.c.xcov": {"+": {5}, "-": {7}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/144-no-unknown-warning/test.py b/testsuite/tests/instr-cov/144-no-unknown-warning/test.py index 424428270..819bf69ba 100644 --- a/testsuite/tests/instr-cov/144-no-unknown-warning/test.py +++ b/testsuite/tests/instr-cov/144-no-unknown-warning/test.py @@ -23,6 +23,6 @@ trace_mode="src", ) -check_xcov_reports("xcov/*.xcov", {"xcov/main.c.xcov": {"+": {4}}}) +check_xcov_reports("xcov", {"main.c.xcov": {"+": {4}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/198-non-instr-scos/test.py b/testsuite/tests/instr-cov/198-non-instr-scos/test.py index 5e6f7b59a..d60509597 100644 --- a/testsuite/tests/instr-cov/198-non-instr-scos/test.py +++ b/testsuite/tests/instr-cov/198-non-instr-scos/test.py @@ -30,13 +30,12 @@ ), ) check_xcov_reports( - "*.xcov", + "xcov", { "main.adb.xcov": {"+": {4, 6}}, "pkg.ads.xcov": {"?": {8}}, "pkg.adb.xcov": {"-": {11}}, }, - cwd="xcov", ) thistest.result() diff --git a/testsuite/tests/instr-cov/208-no-secsta/test.py b/testsuite/tests/instr-cov/208-no-secsta/test.py index 8c09a092f..6a4bf93c2 100644 --- a/testsuite/tests/instr-cov/208-no-secsta/test.py +++ b/testsuite/tests/instr-cov/208-no-secsta/test.py @@ -25,7 +25,7 @@ extra_coverage_args=["-axcov", "--output-dir=xcov"], ) check_xcov_reports( - "*.xcov", + "xcov", { "main.adb.xcov": { "+": {5}, @@ -35,7 +35,6 @@ "pkg.adb.xcov": {"!": {9}}, "pkg.ads.xcov": {}, }, - cwd="xcov", ) thistest.result() diff --git a/testsuite/tests/instr-cov/216-no-elab-all/test.py b/testsuite/tests/instr-cov/216-no-elab-all/test.py index 05b88b2b9..c9d0385fe 100644 --- a/testsuite/tests/instr-cov/216-no-elab-all/test.py +++ b/testsuite/tests/instr-cov/216-no-elab-all/test.py @@ -20,7 +20,7 @@ extra_coverage_args=["-axcov", "--output-dir=xcov"], ) check_xcov_reports( - "*.xcov", + "xcov", { "main.adb.xcov": { "+": {5}, @@ -30,7 +30,6 @@ "pkg.adb.xcov": {"!": {9}}, "pkg.ads.xcov": {}, }, - cwd="xcov", ) thistest.result() diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/test.py b/testsuite/tests/instr-cov/219-non-instr-propagation/test.py index 8b99bb2dd..73e7f5322 100644 --- a/testsuite/tests/instr-cov/219-non-instr-propagation/test.py +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/test.py @@ -32,14 +32,13 @@ trace_mode="src", ) check_xcov_reports( - "*.xcov", + "xcov", { "pkg_1.adb.xcov": {"+": {8, 17, 26, 27, 29}, "?": {15}}, "pkg_1.ads.xcov": {}, "pkg_2.adb.xcov": {"+": {12, 13, 15, 24}, "?": {22}}, "pkg_2.ads.xcov": {}, }, - cwd="xcov", ) thistest.result() diff --git a/testsuite/tests/instr-cov/225-expr-func-access/test.py b/testsuite/tests/instr-cov/225-expr-func-access/test.py index 2baa29230..8322e0487 100644 --- a/testsuite/tests/instr-cov/225-expr-func-access/test.py +++ b/testsuite/tests/instr-cov/225-expr-func-access/test.py @@ -22,13 +22,12 @@ extra_coverage_args=["-axcov", "--output-dir=xcov"], ) check_xcov_reports( - "*.xcov", + "xcov", { "main.adb.xcov": {"+": {9, 10, 12, 13, 15, 16}}, "pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {6, 9, 12}}, }, - cwd="xcov", ) thistest.result() diff --git a/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py index 5eb94b52a..8f86fa938 100644 --- a/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py +++ b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py @@ -18,12 +18,11 @@ extra_coverage_args=["-axcov", "--output-dir=xcov"], ) check_xcov_reports( - "*.xcov", + "xcov", { "main.adb.xcov": {"+": {4, 6}}, "pkg.ads.xcov": {}, }, - cwd="xcov", ) thistest.result() diff --git a/testsuite/tests/instr-cov/C++/109-pp-switches/test.py b/testsuite/tests/instr-cov/C++/109-pp-switches/test.py index abf95b554..a50659d5d 100644 --- a/testsuite/tests/instr-cov/C++/109-pp-switches/test.py +++ b/testsuite/tests/instr-cov/C++/109-pp-switches/test.py @@ -22,12 +22,6 @@ trace_mode="src", ) -check_xcov_reports( - "*.xcov", - { - "main.cpp.xcov": {"+": {6}}, - }, - "xcov", -) +check_xcov_reports("xcov", {"main.cpp.xcov": {"+": {6}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py b/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py index 0c71856b8..320d4b463 100644 --- a/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py +++ b/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py @@ -20,6 +20,6 @@ trace_mode='src', ) -check_xcov_reports('xcov/*.xcov', {'xcov/main.cpp.xcov': {'+': {4}}}) +check_xcov_reports('xcov', {'main.cpp.xcov': {'+': {4}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/C++/cpp-extern-c-main/test.py b/testsuite/tests/instr-cov/C++/cpp-extern-c-main/test.py index bfd0f9a06..f8e1e68dd 100644 --- a/testsuite/tests/instr-cov/C++/cpp-extern-c-main/test.py +++ b/testsuite/tests/instr-cov/C++/cpp-extern-c-main/test.py @@ -20,5 +20,5 @@ trace_mode="src", ) -check_xcov_reports("*.xcov", {"main.cpp.xcov": {"+": {6}}}, "xcov") +check_xcov_reports("xcov", {"main.cpp.xcov": {"+": {6}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/C++/explicit_lang/test.py b/testsuite/tests/instr-cov/C++/explicit_lang/test.py index cea21b4c0..2423ece7a 100644 --- a/testsuite/tests/instr-cov/C++/explicit_lang/test.py +++ b/testsuite/tests/instr-cov/C++/explicit_lang/test.py @@ -30,6 +30,6 @@ trace_mode='src', ) -check_xcov_reports("*.xcov", {"main.c.xcov": {"+": {6, 7}}}, "xcov") +check_xcov_reports("xcov", {"main.c.xcov": {"+": {6, 7}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/C++/std-c++20/test.py b/testsuite/tests/instr-cov/C++/std-c++20/test.py index d1b65f61a..4ec9a14f4 100644 --- a/testsuite/tests/instr-cov/C++/std-c++20/test.py +++ b/testsuite/tests/instr-cov/C++/std-c++20/test.py @@ -32,12 +32,11 @@ def gen_prj(): ) check_xcov_reports( - "*.xcov", + "xcov", { "main.cpp.xcov": {"+": {6, 7, 8, 9}}, "cmdline.cpp.xcov": {"+": {11, 12, 13, 21, 27}, "-": {23, 24}}, }, - "xcov" ) tmp.to_homedir() diff --git a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py index eb2dad649..774b8033e 100644 --- a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py +++ b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py @@ -34,10 +34,10 @@ xcov(xcov_args) -check_xcov_reports('xcov/*.xcov', { - 'xcov/pkg_type_invariant.ads.xcov': {'+': {6, 13, 14, 15, 16, 20}, - '-': {22}}, - 'xcov/main.adb.xcov': {'+': {6, 8, 12}}, +check_xcov_reports('xcov', { + 'pkg_type_invariant.ads.xcov': {'+': {6, 13, 14, 15, 16, 20}, + '-': {22}}, + 'main.adb.xcov': {'+': {6, 8, 12}}, }) thistest.result() diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py index d86a005af..3cb16f9e6 100644 --- a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py @@ -49,9 +49,9 @@ def create_lib_gpr(name, deps=[]): build_run_and_coverage(gprsw=gprsw, covlevel="stmt", mains=["main"], extra_coverage_args=["-axcov"]) -check_xcov_reports("obj/*.xcov", - {"obj/main.c.xcov": {"+": {6, 7, 8}}, - "obj/pkg1.c.xcov": {"+": {7, 8}}, - "obj/pkg2.c.xcov": {"+": {6}}}) +check_xcov_reports("obj", + {"main.c.xcov": {"+": {6, 7, 8}}, + "pkg1.c.xcov": {"+": {7, 8}}, + "pkg2.c.xcov": {"+": {6}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py b/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py index d09e7ad30..8849be4a0 100644 --- a/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py +++ b/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py @@ -21,6 +21,6 @@ dump_channel="base64-stdout", ) -check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {5, 6}}}, "obj") +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5, 6}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/base64_prefix/test.py b/testsuite/tests/instr-cov/base64_prefix/test.py index 9d01c567a..73090a834 100644 --- a/testsuite/tests/instr-cov/base64_prefix/test.py +++ b/testsuite/tests/instr-cov/base64_prefix/test.py @@ -95,6 +95,6 @@ trace_filename, ] ) - check_xcov_reports("*.xcov", cov, cwd=xcov_dir) + check_xcov_reports(xcov_dir, cov) thistest.result() diff --git a/testsuite/tests/instr-cov/basic_base64/test.py b/testsuite/tests/instr-cov/basic_base64/test.py index d48901a21..dc75c32a9 100644 --- a/testsuite/tests/instr-cov/basic_base64/test.py +++ b/testsuite/tests/instr-cov/basic_base64/test.py @@ -19,9 +19,9 @@ trace_mode='src', dump_trigger='main-end', dump_channel='base64-stdout') -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'+': {5, 7, 8}}, - 'xcov/pkg.adb.xcov': {'+': {5, 6, 8}}, +check_xcov_reports('xcov', { + 'main.adb.xcov': {'+': {5, 7, 8}}, + 'pkg.adb.xcov': {'+': {5, 6, 8}}, }) thistest.result() diff --git a/testsuite/tests/instr-cov/basic_decision/test.py b/testsuite/tests/instr-cov/basic_decision/test.py index 083f5135d..a2091ec89 100644 --- a/testsuite/tests/instr-cov/basic_decision/test.py +++ b/testsuite/tests/instr-cov/basic_decision/test.py @@ -25,9 +25,9 @@ gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, trace_mode='src') -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'+': {4, 6}}, - 'xcov/pkg.adb.xcov': {'+': {6}, '!': {5}, '-': {8}}, +check_xcov_reports('xcov', { + 'main.adb.xcov': {'+': {4, 6}}, + 'pkg.adb.xcov': {'+': {6}, '!': {5}, '-': {8}}, }) thistest.result() diff --git a/testsuite/tests/instr-cov/basic_stmt/test.py b/testsuite/tests/instr-cov/basic_stmt/test.py index 0bc235949..39a1fc004 100644 --- a/testsuite/tests/instr-cov/basic_stmt/test.py +++ b/testsuite/tests/instr-cov/basic_stmt/test.py @@ -23,9 +23,9 @@ gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, trace_mode='src') -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'+': {5, 7, 8}}, - 'xcov/pkg.adb.xcov': {'+': {5, 6, 8}}, +check_xcov_reports('xcov', { + 'main.adb.xcov': {'+': {5, 7, 8}}, + 'pkg.adb.xcov': {'+': {5, 6, 8}}, }) thistest.result() diff --git a/testsuite/tests/instr-cov/bin_file_tunings/test.py b/testsuite/tests/instr-cov/bin_file_tunings/test.py index 5c6ed9bd0..0ad745c7e 100644 --- a/testsuite/tests/instr-cov/bin_file_tunings/test.py +++ b/testsuite/tests/instr-cov/bin_file_tunings/test.py @@ -119,9 +119,7 @@ class Testcase: # Sanity check that expected trace xcov(xcov_args + traces, out="coverage.log") - check_xcov_reports("xcov/*.xcov", { - "xcov/main.adb.xcov": {"+": {5}}, - }) + check_xcov_reports("xcov", {"main.adb.xcov": {"+": {5}}}) finally: wd.to_homedir() diff --git a/testsuite/tests/instr-cov/buffer_reset/test.py b/testsuite/tests/instr-cov/buffer_reset/test.py index c94ff64cf..f7d87275d 100644 --- a/testsuite/tests/instr-cov/buffer_reset/test.py +++ b/testsuite/tests/instr-cov/buffer_reset/test.py @@ -99,11 +99,7 @@ def check_one_exec(cov_args, lang): cov_args + [f"--output-dir={output_dir}", traces[i]], out=f"coverage_{lang}_{i}.log" ) - check_xcov_reports( - "*.xcov", - get_expected_cov(traces[i]), - cwd=output_dir - ) + check_xcov_reports(output_dir, get_expected_cov(traces[i])) prj_id = "p" @@ -142,14 +138,13 @@ def check_one_exec(cov_args, lang): out="consolidated.log" ) check_xcov_reports( - "*.xcov", + output_dir, { "main_ada.adb.xcov": {'+': {7, 10, 13}}, "pkg.adb.xcov": {'+': {5}}, "main_c.c.xcov": {'+': {8, 11, 14}, '-': {16}}, "pkh.c.xcov": {'+': {6}} }, - cwd=output_dir ) thistest.result() diff --git a/testsuite/tests/instr-cov/c_custom_naming/test.py b/testsuite/tests/instr-cov/c_custom_naming/test.py index b191e1555..1bed00933 100644 --- a/testsuite/tests/instr-cov/c_custom_naming/test.py +++ b/testsuite/tests/instr-cov/c_custom_naming/test.py @@ -36,12 +36,11 @@ ) check_xcov_reports( - "*.xcov", + "xcov", { "main.cc.xcov": {"+": {11, 12}}, "hello.cc.xcov": {"+": {6}}, }, - cwd="xcov", ) thistest.result() diff --git a/testsuite/tests/instr-cov/c_empty_source/test.py b/testsuite/tests/instr-cov/c_empty_source/test.py index 9806e7be2..7e0718332 100644 --- a/testsuite/tests/instr-cov/c_empty_source/test.py +++ b/testsuite/tests/instr-cov/c_empty_source/test.py @@ -21,6 +21,6 @@ trace_mode='src', ) -check_xcov_reports('*.xcov', {'main.c.xcov': {'+': {6}}}, 'xcov') +check_xcov_reports('xcov', {'main.c.xcov': {'+': {6}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/c_gpr_opts/test.py b/testsuite/tests/instr-cov/c_gpr_opts/test.py index 3fad21d70..3a36d154b 100644 --- a/testsuite/tests/instr-cov/c_gpr_opts/test.py +++ b/testsuite/tests/instr-cov/c_gpr_opts/test.py @@ -29,12 +29,11 @@ ) check_xcov_reports( - "*.xcov", + "xcov", { "main.c.xcov": {"+": {16, 19}}, "hello.c.xcov": {"+": {7}}, }, - cwd="xcov", ) thistest.result() diff --git a/testsuite/tests/instr-cov/c_header/test.py b/testsuite/tests/instr-cov/c_header/test.py index 4e8af9c7e..5abf6b44f 100644 --- a/testsuite/tests/instr-cov/c_header/test.py +++ b/testsuite/tests/instr-cov/c_header/test.py @@ -24,12 +24,11 @@ trace_mode='src', ) check_xcov_reports( - '*.xcov', + 'xcov', { 'main.c.xcov': {'+': {6, 7}}, 'fact.h.xcov': {'+': {4, 5, 7}}, }, - "xcov" ) # Check that the header file is not instrumented diff --git a/testsuite/tests/instr-cov/c_metaprog/test.py b/testsuite/tests/instr-cov/c_metaprog/test.py index 673ffd875..ffe8accc4 100644 --- a/testsuite/tests/instr-cov/c_metaprog/test.py +++ b/testsuite/tests/instr-cov/c_metaprog/test.py @@ -22,6 +22,6 @@ trace_mode="src", ) -check_xcov_reports("obj/*.xcov", {"obj/main.c.xcov": {"+": {4, 7}}}) +check_xcov_reports("obj", {"main.c.xcov": {"+": {4, 7}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/test.py b/testsuite/tests/instr-cov/c_multiline_stmt/test.py index a5da42c35..36ec38c6b 100644 --- a/testsuite/tests/instr-cov/c_multiline_stmt/test.py +++ b/testsuite/tests/instr-cov/c_multiline_stmt/test.py @@ -42,12 +42,11 @@ ) check_xcov_reports( - "*.xcov", + "xcov", { "main.c.xcov": {"+": {6, 12, 17, 26, 31, 32}, "-": {27, 28}}, "pkg.c.xcov": {"+": {4}}, }, - "xcov", ) tmp.to_homedir() @@ -70,6 +69,6 @@ trace_mode="src", ) -check_xcov_reports("*.xcov", {"pkg.c.xcov": {"+": {4}}}, "xcov") +check_xcov_reports("xcov", {"pkg.c.xcov": {"+": {4}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/c_no_return/test.py b/testsuite/tests/instr-cov/c_no_return/test.py index 127bac479..95869248b 100644 --- a/testsuite/tests/instr-cov/c_no_return/test.py +++ b/testsuite/tests/instr-cov/c_no_return/test.py @@ -31,7 +31,7 @@ register_failure=False, ) check_xcov_reports( - "*.xcov", {"main.c.xcov": {"+": {4, 5, 6, 12, 13}, "-": {14}}}, "xcov" + "xcov", {"main.c.xcov": {"+": {4, 5, 6, 12, 13}, "-": {14}}} ) tmp_no_return.to_homedir() diff --git a/testsuite/tests/instr-cov/c_opts/test.py b/testsuite/tests/instr-cov/c_opts/test.py index 208aeac73..224eddfef 100644 --- a/testsuite/tests/instr-cov/c_opts/test.py +++ b/testsuite/tests/instr-cov/c_opts/test.py @@ -49,6 +49,6 @@ f"{excerpt} macro definition not found in {log_file}" ) -check_xcov_reports("*.xcov", {"main.c.xcov": {"+": {7, 14}}}, cwd="xcov") +check_xcov_reports("xcov", {"main.c.xcov": {"+": {7, 14}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/c_special_filenames/test.py b/testsuite/tests/instr-cov/c_special_filenames/test.py index e6848b74f..332ab0f05 100644 --- a/testsuite/tests/instr-cov/c_special_filenames/test.py +++ b/testsuite/tests/instr-cov/c_special_filenames/test.py @@ -53,6 +53,6 @@ extra_coverage_args=["-axcov", "--output-dir=xcov"], trace_mode="src", ) -check_xcov_reports("*.xcov", expected_report, "xcov") +check_xcov_reports("xcov", expected_report) thistest.result() diff --git a/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py b/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py index 8c6bea041..7f9c7961e 100644 --- a/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py +++ b/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py @@ -20,10 +20,6 @@ extra_coverage_args=['-axcov', '--output-dir=xcov'], trace_mode='src', ) -check_xcov_reports( - '*.xcov', - {'main.c.xcov': {'+': {4, 5, 7}, '-': {9}}}, - 'xcov' -) +check_xcov_reports('xcov', {'main.c.xcov': {'+': {4, 5, 7}, '-': {9}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/checks_and_warnings/test.py b/testsuite/tests/instr-cov/checks_and_warnings/test.py index 063aacf2f..56eeed9b9 100644 --- a/testsuite/tests/instr-cov/checks_and_warnings/test.py +++ b/testsuite/tests/instr-cov/checks_and_warnings/test.py @@ -27,9 +27,9 @@ extra_gprbuild_cargs=['-gnatwae'], check_gprbuild_output=True, trace_mode='src') -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'+': {13}}, - 'xcov/pkg.ads.xcov': {'+': {2}}, +check_xcov_reports('xcov', { + 'main.adb.xcov': {'+': {13}}, + 'pkg.ads.xcov': {'+': {2}}, }) thistest.result() diff --git a/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py b/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py index 861e77b4c..a12298c4f 100644 --- a/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py +++ b/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py @@ -23,6 +23,6 @@ trace_mode='src', ) -check_xcov_reports('xcov/*.xcov', {'xcov/main.c.xcov': {'+': {4}}}) +check_xcov_reports('xcov', {'main.c.xcov': {'+': {4}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/compile_time_pragma/test.py b/testsuite/tests/instr-cov/compile_time_pragma/test.py index 99f84f9f4..1b0e77cfc 100644 --- a/testsuite/tests/instr-cov/compile_time_pragma/test.py +++ b/testsuite/tests/instr-cov/compile_time_pragma/test.py @@ -20,6 +20,6 @@ mains=["main"], extra_coverage_args=["-axcov", "--output-dir=xcov"], ) -check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {8}}}, "xcov") +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {8}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/config_custom_db/test.py b/testsuite/tests/instr-cov/config_custom_db/test.py index b1d75d8df..811bcc2ee 100644 --- a/testsuite/tests/instr-cov/config_custom_db/test.py +++ b/testsuite/tests/instr-cov/config_custom_db/test.py @@ -41,6 +41,6 @@ extra_instr_args=["--runtime-project", "gnatcov_rts_custom"], auto_config_args=False, ) -check_xcov_reports("*.xcov", {"main.c.xcov": {"+": {4}}}, "xcov") +check_xcov_reports("xcov", {"main.c.xcov": {"+": {4}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/config_pragmas/test.py b/testsuite/tests/instr-cov/config_pragmas/test.py index ca4fcabf7..c685e7908 100644 --- a/testsuite/tests/instr-cov/config_pragmas/test.py +++ b/testsuite/tests/instr-cov/config_pragmas/test.py @@ -30,13 +30,12 @@ # pkg.adb, which will then not compile because the witness call inserted for # that decision violates the Pure_Barrier restriction. check_xcov_reports( - "*.xcov", + "xcov", { "main.adb.xcov": {"+": {4, 6, 8, 10}}, "pkg.ads.xcov": {"+": {6}}, "pkg.adb.xcov": {"+": {12}, "-": {23}, "?": {20}}, }, - cwd="xcov", ) thistest.result() diff --git a/testsuite/tests/instr-cov/consistency/test.py b/testsuite/tests/instr-cov/consistency/test.py index 8857645e0..b52710b0b 100644 --- a/testsuite/tests/instr-cov/consistency/test.py +++ b/testsuite/tests/instr-cov/consistency/test.py @@ -86,8 +86,6 @@ # obligations coming from the first instrumentation. Besides, since it # discarded info from the trace file, gnatcov is supposed to report violations # for all coverage obligations related to the first version of "main.adb". -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'-': {5}}, -}) +check_xcov_reports('xcov', {'main.adb.xcov': {'-': {5}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/end_slocs/test.py b/testsuite/tests/instr-cov/end_slocs/test.py index 49d84b061..a15a27ea8 100644 --- a/testsuite/tests/instr-cov/end_slocs/test.py +++ b/testsuite/tests/instr-cov/end_slocs/test.py @@ -30,6 +30,6 @@ gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, trace_mode='src') -check_xcov_reports('xcov/*.xcov', {'xcov/main.adb.xcov': {'+': {5}}}) +check_xcov_reports('xcov', {'main.adb.xcov': {'+': {5}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/endianity/test.py b/testsuite/tests/instr-cov/endianity/test.py index d54c822ad..b415e115d 100644 --- a/testsuite/tests/instr-cov/endianity/test.py +++ b/testsuite/tests/instr-cov/endianity/test.py @@ -41,13 +41,9 @@ xcov_dir = f'xcov-{discr}' xcov(xcov_args + ['--output-dir', xcov_dir, f'{discr}.srctrace'], out=f'coverage-{discr}.log') - check_xcov_reports( - '*.xcov', - { - 'main.adb.xcov': {'+': {5, 7, 8}}, - 'pkg.adb.xcov': {'+': {6, 8}, '!': {5}}, - }, - xcov_dir, - ) + check_xcov_reports(xcov_dir, { + 'main.adb.xcov': {'+': {5, 7, 8}}, + 'pkg.adb.xcov': {'+': {6, 8}, '!': {5}}, + }) thistest.result() diff --git a/testsuite/tests/instr-cov/entry_guards/restricted/test.py b/testsuite/tests/instr-cov/entry_guards/restricted/test.py index ca8a3387c..40d586877 100644 --- a/testsuite/tests/instr-cov/entry_guards/restricted/test.py +++ b/testsuite/tests/instr-cov/entry_guards/restricted/test.py @@ -28,7 +28,7 @@ extra_coverage_args=["-axcov", "--output-dir=."], ) check_xcov_reports( - "*.xcov", {"pkg.adb.xcov": expected_coverage, "pkg.ads.xcov": {}} + ".", {"pkg.adb.xcov": expected_coverage, "pkg.ads.xcov": {}} ) tmp.to_homedir() diff --git a/testsuite/tests/instr-cov/explicit_mains_uoi/test.py b/testsuite/tests/instr-cov/explicit_mains_uoi/test.py index 420202d48..f891e9f97 100644 --- a/testsuite/tests/instr-cov/explicit_mains_uoi/test.py +++ b/testsuite/tests/instr-cov/explicit_mains_uoi/test.py @@ -20,6 +20,6 @@ extra_instr_args=["main.adb"], extra_gprbuild_args=["main.adb"]) -check_xcov_reports("obj/*.xcov", {"obj/main.adb.xcov": {"+": {2, 5}}}) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {2, 5}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/aggr/test.py b/testsuite/tests/instr-cov/expr_func/aggr/test.py index ad248ece2..b1ae262e0 100644 --- a/testsuite/tests/instr-cov/expr_func/aggr/test.py +++ b/testsuite/tests/instr-cov/expr_func/aggr/test.py @@ -25,7 +25,7 @@ gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, trace_mode='src') -check_xcov_reports('xcov/*.xcov', {'xcov/main.adb.xcov': { +check_xcov_reports('xcov', {'main.adb.xcov': { '+': {4, 5, 7, 12, 14, 17, 19, 21, 22, 23, 24} }}) diff --git a/testsuite/tests/instr-cov/expr_func/basic/test.py b/testsuite/tests/instr-cov/expr_func/basic/test.py index d80777a6c..b98a13ec5 100644 --- a/testsuite/tests/instr-cov/expr_func/basic/test.py +++ b/testsuite/tests/instr-cov/expr_func/basic/test.py @@ -25,8 +25,6 @@ gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, trace_mode='src') -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'+': {7, 9, 11, 15}, '-': {12}} -}) +check_xcov_reports('xcov', {'main.adb.xcov': {'+': {7, 9, 11, 15}, '-': {12}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/generic/test.py b/testsuite/tests/instr-cov/expr_func/generic/test.py index 41cbea501..3dc947ae2 100644 --- a/testsuite/tests/instr-cov/expr_func/generic/test.py +++ b/testsuite/tests/instr-cov/expr_func/generic/test.py @@ -31,7 +31,7 @@ ) # We only expect non-instrumented lines -check_xcov_reports("*.xcov", {"pkg.ads.xcov": {"?": {16, 19}}}) +check_xcov_reports(".", {"pkg.ads.xcov": {"?": {16, 19}}}) # Check that both expression functions are reported as warnings warning_msg = ( diff --git a/testsuite/tests/instr-cov/expr_func/parameterless/test.py b/testsuite/tests/instr-cov/expr_func/parameterless/test.py index a33c5a846..6ee724d92 100644 --- a/testsuite/tests/instr-cov/expr_func/parameterless/test.py +++ b/testsuite/tests/instr-cov/expr_func/parameterless/test.py @@ -25,9 +25,9 @@ gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, trace_mode='src') -check_xcov_reports('xcov/*.xcov', - {'xcov/main.adb.xcov': {'+': {4}}, - 'xcov/pak.ads.xcov': {'+': {4}, '-': {5}}}) +check_xcov_reports('xcov', + {'main.adb.xcov': {'+': {4}}, + 'pak.ads.xcov': {'+': {4}, '-': {5}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/prim/test.py b/testsuite/tests/instr-cov/expr_func/prim/test.py index bbb766a11..bfabe41e5 100644 --- a/testsuite/tests/instr-cov/expr_func/prim/test.py +++ b/testsuite/tests/instr-cov/expr_func/prim/test.py @@ -29,7 +29,7 @@ # TODO: update coverage expectations once compiler bug # has been fixed and XFAIL is removed. -check_xcov_reports('xcov/*.xcov', {'xcov/main.adb.xcov': { +check_xcov_reports('xcov', {'main.adb.xcov': { '+': {4, 5, 7, 12, 14, 17, 19, 21, 22, 23, 24} }}) diff --git a/testsuite/tests/instr-cov/expr_func/prim2/test.py b/testsuite/tests/instr-cov/expr_func/prim2/test.py index a5c6a0f57..44aaf55ee 100644 --- a/testsuite/tests/instr-cov/expr_func/prim2/test.py +++ b/testsuite/tests/instr-cov/expr_func/prim2/test.py @@ -31,9 +31,9 @@ # Coverage expectations aren't really important, we want to check that # the instrumented code is valid. -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'+': {6}}, - 'xcov/pak.ads.xcov' : {'+': {4, 5, 6, 14, 16, 17, 18, 23}, '-': {8, 10}}, - 'xcov/pak.adb.xcov' : {'!': {6}, '+': {8}}}) +check_xcov_reports('xcov', { + 'main.adb.xcov': {'+': {6}}, + 'pak.ads.xcov' : {'+': {4, 5, 6, 14, 16, 17, 18, 23}, '-': {8, 10}}, + 'pak.adb.xcov' : {'!': {6}, '+': {8}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/ghost_generic/test.py b/testsuite/tests/instr-cov/ghost_generic/test.py index 3a830103a..a2f5bc2d8 100644 --- a/testsuite/tests/instr-cov/ghost_generic/test.py +++ b/testsuite/tests/instr-cov/ghost_generic/test.py @@ -20,14 +20,13 @@ extra_coverage_args=["-axcov", "--output-dir=xcov"], ) check_xcov_reports( - "*.xcov", + "xcov", { "main.adb.xcov": {"+": {11, 15}}, "gen.adb.xcov": {"+": {9}, "-": {4}}, "gen.ads.xcov": {}, "non_ghost_inst.ads.xcov": {} }, - cwd="xcov", ) thistest.result() diff --git a/testsuite/tests/instr-cov/gpr-complex/test.py b/testsuite/tests/instr-cov/gpr-complex/test.py index 2d0c98065..fd74a938f 100644 --- a/testsuite/tests/instr-cov/gpr-complex/test.py +++ b/testsuite/tests/instr-cov/gpr-complex/test.py @@ -64,7 +64,7 @@ def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): "--units=pkg", ], ) - check_xcov_reports("*.xcov", expected_xcov, main_prj_obj_dir) + check_xcov_reports(main_prj_obj_dir, expected_xcov) # Try the simple case: the main project extends the library, but does not diff --git a/testsuite/tests/instr-cov/library_projects/test.py b/testsuite/tests/instr-cov/library_projects/test.py index de77cca8d..26a49b240 100644 --- a/testsuite/tests/instr-cov/library_projects/test.py +++ b/testsuite/tests/instr-cov/library_projects/test.py @@ -26,15 +26,15 @@ gpr_obj_dir=main_obj_dir, gpr_exe_dir=main_obj_dir, trace_mode='src') -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'+': {5, 9, 11, 12, 13}}, +check_xcov_reports('xcov', { + 'main.adb.xcov': {'+': {5, 9, 11, 12, 13}}, - 'xcov/vectors.ads.xcov': {'+': {6, 15, 17, 18, 19, 20}}, - 'xcov/vectors.adb.xcov': {'+': {5, 10, 15, 18, 19}, - '-': {16, 25, 26, 28}}, + 'vectors.ads.xcov': {'+': {6, 15, 17, 18, 19, 20}}, + 'vectors.adb.xcov': {'+': {5, 10, 15, 18, 19}, + '-': {16, 25, 26, 28}}, - 'xcov/math.ads.xcov': {'+': {3, 11, 12, 13}}, - 'xcov/math.adb.xcov': {'+': {5, 10}, '-': {15}}, + 'math.ads.xcov': {'+': {3, 11, 12, 13}}, + 'math.adb.xcov': {'+': {5, 10}, '-': {15}}, }) thistest.result() diff --git a/testsuite/tests/instr-cov/main-spec/test.py b/testsuite/tests/instr-cov/main-spec/test.py index c3351a17f..ebe20bf31 100644 --- a/testsuite/tests/instr-cov/main-spec/test.py +++ b/testsuite/tests/instr-cov/main-spec/test.py @@ -32,13 +32,12 @@ extra_coverage_args=["--annotate=xcov"], ) check_xcov_reports( - "*.xcov", + "obj", { "generic_main.adb.xcov": {"+": {5}}, "inst_main.ads.xcov": {}, "pkg-child_main.ads.xcov": {}, }, - "obj", ) thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py b/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py index 20c51f021..aeda6c74b 100644 --- a/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py @@ -26,9 +26,7 @@ trace_mode="src", auto_languages=False, ) -check_xcov_reports( - "*.xcov", {"tested.c.xcov": {"+": {5}, "-": {7}}}, cwd="xcov" -) +check_xcov_reports("xcov", {"tested.c.xcov": {"+": {5}, "-": {7}}}) tmp.to_homedir() # Now check with a project that contains an Ada unit (to analyze) driven by a @@ -47,12 +45,11 @@ auto_languages=False, ) check_xcov_reports( - "*.xcov", + "xcov", { "pkg.adb.xcov": {"+": {10, 22}, "-": {12, 23}}, "pkg.ads.xcov": {}, }, - cwd="xcov" ) tmp.to_homedir() diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/test.py b/testsuite/tests/instr-cov/main_autodump/nested_block/test.py index ca11a73ef..dcb21c208 100644 --- a/testsuite/tests/instr-cov/main_autodump/nested_block/test.py +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/test.py @@ -34,25 +34,25 @@ # the mains got instrumented and build correctly. expected_results = { "dotted-decl": { - "xcov/dotted-decl.adb.xcov": {'+': {7, 12, 13, 17, 18}} + "dotted-decl.adb.xcov": {'+': {7, 12, 13, 17, 18}} }, "dotted-no_decl": { - "xcov/dotted-no_decl.adb.xcov": {'+': {6, 9, 10}} + "dotted-no_decl.adb.xcov": {'+': {6, 9, 10}} }, "dotted-exn": { - "xcov/dotted-exn.adb.xcov": {'+': {4, 9, 12, 13, 16}} + "dotted-exn.adb.xcov": {'+': {4, 9, 12, 13, 16}} }, "simple_decl": { - "xcov/simple_decl.adb.xcov": {'+': {10, 15, 16, 19, 20}} + "simple_decl.adb.xcov": {'+': {10, 15, 16, 19, 20}} }, "simple_no_decl": { - "xcov/simple_no_decl.adb.xcov": {'+': {6, 9}} + "simple_no_decl.adb.xcov": {'+': {6, 9}} }, "simple_exn": { - "xcov/simple_exn.adb.xcov": {'+': {4, 9, 12, 13, 16}} + "simple_exn.adb.xcov": {'+': {4, 9, 12, 13, 16}} }, "simple_only_exn": { - "xcov/simple_only_exn.adb.xcov": {'+': {10, 13, 14, 18}, '-': {20}} + "simple_only_exn.adb.xcov": {'+': {10, 13, 14, 18}, '-': {20}} } } @@ -70,7 +70,7 @@ def do_one_main(main_name): covlevel='stmt', mains=[main_name], extra_coverage_args=['-axcov', '--output-dir=xcov']) - check_xcov_reports('xcov/*.xcov', expected_results[main_name]) + check_xcov_reports('xcov', expected_results[main_name]) for main_name in main_names: diff --git a/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.py b/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.py index 5f542a790..3f0024f06 100644 --- a/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.py +++ b/testsuite/tests/instr-cov/main_autodump/pramga_prio/test.py @@ -28,10 +28,6 @@ ) # We expect all lines to be covered - check_xcov_reports( - "*.xcov", - {"main.adb.xcov": {"+": {10, 13, 16}}}, - cwd="obj", - ) + check_xcov_reports("obj", {"main.adb.xcov": {"+": {10, 13, 16}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/stubs/test.py b/testsuite/tests/instr-cov/main_autodump/stubs/test.py index 2bfe6777c..0adef7d3d 100644 --- a/testsuite/tests/instr-cov/main_autodump/stubs/test.py +++ b/testsuite/tests/instr-cov/main_autodump/stubs/test.py @@ -28,12 +28,11 @@ # We expect all lines to be covered check_xcov_reports( - "*.xcov", + "obj", { "main.adb.xcov": {"+": {4, 7}}, "main-inner.adb.xcov": {"+": {5}}, }, - cwd="obj", ) diff --git a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.py b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.py index ab944db8c..3afb42e59 100644 --- a/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.py +++ b/testsuite/tests/instr-cov/main_autodump/stubs_controlled/test.py @@ -29,14 +29,13 @@ # We expect all lines to be covered check_xcov_reports( - "*.xcov", + "obj", { "main.adb.xcov": {"+": {10, 13, 15}}, "main-inner.adb.xcov": {"+": {5}}, "pkg.adb.xcov": {"+": {6}}, "pkg.ads.xcov": {"+": {5}}, }, - cwd="obj", ) thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/task_in_main/test.py b/testsuite/tests/instr-cov/main_autodump/task_in_main/test.py index 45393f7a1..ba8a58e6f 100644 --- a/testsuite/tests/instr-cov/main_autodump/task_in_main/test.py +++ b/testsuite/tests/instr-cov/main_autodump/task_in_main/test.py @@ -27,10 +27,6 @@ ) # We expect all lines to be covered - check_xcov_reports( - "*.xcov", - {"main.adb.xcov": {"+": {6, 9, 13, 14, 15, 19}}}, - cwd="obj", - ) + check_xcov_reports("obj", {"main.adb.xcov": {"+": {6, 9, 13, 14, 15, 19}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/main_no_ext/test.py b/testsuite/tests/instr-cov/main_no_ext/test.py index c89e9e2d1..aed543d3b 100644 --- a/testsuite/tests/instr-cov/main_no_ext/test.py +++ b/testsuite/tests/instr-cov/main_no_ext/test.py @@ -25,6 +25,6 @@ extra_coverage_args=["--annotate=xcov"], ) -check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {3}}}, gpr_obj_dir) +check_xcov_reports(gpr_obj_dir, {"main.adb.xcov": {"+": {3}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/test.py b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py index 99c8202a1..0a53075d0 100644 --- a/testsuite/tests/instr-cov/manual-dump/ada_only/test.py +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py @@ -67,9 +67,9 @@ def check_call(file): )))[-1] xcov(cov_args + [trace_file], out="coverage.log") -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'+': {12, 15, 19, 24, 26, 27, 28}, - '-': {21, 29}}, - 'xcov/lib1.adb.xcov': {'+': {4, 7}}}) +check_xcov_reports('xcov', { + 'main.adb.xcov': {'+': {12, 15, 19, 24, 26, 27, 28}, + '-': {21, 29}}, + 'lib1.adb.xcov': {'+': {4, 7}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py index 859e4a99f..ede4b8ff6 100644 --- a/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py +++ b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py @@ -50,8 +50,8 @@ def make_lib_gpr(name, srcdirs, deps): manual_prj_name="lib1", tolerate_instrument_messages=instr_warning) -check_xcov_reports('xcov/*.xcov', { - 'xcov/lib1.adb.xcov': {'+': {6, 8}, '-': {10}}, - 'xcov/lib2.adb.xcov': {'+': {4, 6}}}) +check_xcov_reports('xcov', { + 'lib1.adb.xcov': {'+': {6, 8}, '-': {10}}, + 'lib2.adb.xcov': {'+': {4, 6}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/basic/test.py b/testsuite/tests/instr-cov/manual-dump/basic/test.py index b3f0abd78..2bac52d8f 100644 --- a/testsuite/tests/instr-cov/manual-dump/basic/test.py +++ b/testsuite/tests/instr-cov/manual-dump/basic/test.py @@ -50,6 +50,6 @@ " misspelling in the expected pragma" " statement." ) -check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {5}}}, "obj") +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/c_only/test.py b/testsuite/tests/instr-cov/manual-dump/c_only/test.py index 09e2dc453..610e87800 100644 --- a/testsuite/tests/instr-cov/manual-dump/c_only/test.py +++ b/testsuite/tests/instr-cov/manual-dump/c_only/test.py @@ -59,9 +59,9 @@ # Check that we got the expected coverage report -check_xcov_reports("obj/*.xcov", - {"obj/main.c.xcov": {"+": {6, 12, 15, 20, 22}, - "-": {18, 26}}, - "obj/foo.c.xcov": {"+": {4, 8}}}) +check_xcov_reports("obj", + {"main.c.xcov": {"+": {6, 12, 15, 20, 22}, + "-": {18, 26}}, + "foo.c.xcov": {"+": {4, 8}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py b/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py index 3d2ebe0ec..d371b125a 100644 --- a/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py +++ b/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py @@ -88,6 +88,6 @@ def gen_project(): manual_prj_name=os.path.splitext(prj)[0] ) -check_xcov_reports("*.xcov", expected_cov, cwd="obj") +check_xcov_reports("obj", expected_cov) thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/mixed/test.py b/testsuite/tests/instr-cov/manual-dump/mixed/test.py index 7da30d009..89aa82c36 100644 --- a/testsuite/tests/instr-cov/manual-dump/mixed/test.py +++ b/testsuite/tests/instr-cov/manual-dump/mixed/test.py @@ -44,11 +44,11 @@ run_cov_program(exepath_to("main_c"), env=env) xcov(cov_args) check_xcov_reports( - "*.xcov", + "obj", { "main_ada.adb.xcov": {"+": {5}}, "main_c.c.xcov": {"+": {6}, '-': {8}}, }, - cwd="obj") +) thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py index 380605d6f..a0bc7d31b 100644 --- a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py @@ -60,7 +60,7 @@ def check_one_trace(cov_args, lang): cov_args + [f"--output-dir={output_dir}"] + trace, out=f"coverage_{lang}.log" ) - check_xcov_reports("*.xcov", expected_cov[lang], cwd=output_dir) + check_xcov_reports(output_dir, expected_cov[lang]) prj_id = "p" diff --git a/testsuite/tests/instr-cov/manual-dump/trace_index/test.py b/testsuite/tests/instr-cov/manual-dump/trace_index/test.py index 6edc0a4cc..c5cbac4d3 100644 --- a/testsuite/tests/instr-cov/manual-dump/trace_index/test.py +++ b/testsuite/tests/instr-cov/manual-dump/trace_index/test.py @@ -29,11 +29,7 @@ def check_trace (cov_args, traces, index): thistest.log(f"======= Checking trace {index + 1} =========") output_dir=f"report_{index + 1}" xcov(cov_args + [traces[index], f"--output-dir={output_dir}"], out=f"xcov_{index}") - check_xcov_reports( - "*.xcov", - {"main.adb.xcov": expected_cov[index]}, - cwd=output_dir - ) + check_xcov_reports(output_dir, {"main.adb.xcov": expected_cov[index]}) cov_args = build_and_run( diff --git a/testsuite/tests/instr-cov/missing-runtime-dir/test.py b/testsuite/tests/instr-cov/missing-runtime-dir/test.py index 0facbcb14..1bdb755dd 100644 --- a/testsuite/tests/instr-cov/missing-runtime-dir/test.py +++ b/testsuite/tests/instr-cov/missing-runtime-dir/test.py @@ -22,6 +22,6 @@ mains=["main"], extra_coverage_args=["--annotate=xcov"], ) -check_xcov_reports("*.xcov", {"main.adb.xcov": {"+": {5}}}, "obj") +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/mixed_and/test.py b/testsuite/tests/instr-cov/mixed_and/test.py index 4a9c616c4..f2ef7f10f 100644 --- a/testsuite/tests/instr-cov/mixed_and/test.py +++ b/testsuite/tests/instr-cov/mixed_and/test.py @@ -25,8 +25,8 @@ gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, trace_mode='src') -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'+': {4, 6, 8, 10, 12, 14, 17}, - '-': {7, 9, 11, 13, 15}}}) +check_xcov_reports('xcov', { + 'main.adb.xcov': {'+': {4, 6, 8, 10, 12, 14, 17}, + '-': {7, 9, 11, 13, 15}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/multi_unit_source/test.py b/testsuite/tests/instr-cov/multi_unit_source/test.py index 180dc04bf..16a26117b 100644 --- a/testsuite/tests/instr-cov/multi_unit_source/test.py +++ b/testsuite/tests/instr-cov/multi_unit_source/test.py @@ -56,6 +56,6 @@ extra_coverage_args=["--units=pck", "-axcov"], ) -check_xcov_reports("*.xcov", {"pck.adb.xcov": {"+": {9, 10, 11}}}, "obj") +check_xcov_reports("obj", {"pck.adb.xcov": {"+": {9, 10, 11}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/multiline_marker/test.py b/testsuite/tests/instr-cov/multiline_marker/test.py index 957d88ea3..ce2aed0c4 100644 --- a/testsuite/tests/instr-cov/multiline_marker/test.py +++ b/testsuite/tests/instr-cov/multiline_marker/test.py @@ -24,6 +24,6 @@ extra_coverage_args=['-axcov', '--output-dir=xcov'], trace_mode='src', ) -check_xcov_reports("*.xcov", {"main.c.xcov": {"+": {6, 10, 14}}}, "xcov") +check_xcov_reports("xcov", {"main.c.xcov": {"+": {6, 10, 14}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/nested_ternary/test.py b/testsuite/tests/instr-cov/nested_ternary/test.py index 2a121a4b8..c4a455725 100644 --- a/testsuite/tests/instr-cov/nested_ternary/test.py +++ b/testsuite/tests/instr-cov/nested_ternary/test.py @@ -21,6 +21,6 @@ trace_mode='src', ) -check_xcov_reports('*.xcov', {'main.c.xcov': {'!': {4}}}, "xcov") +check_xcov_reports('xcov', {'main.c.xcov': {'!': {4}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/no_main/test.py b/testsuite/tests/instr-cov/no_main/test.py index 092b2b58b..b8ae5e4bc 100644 --- a/testsuite/tests/instr-cov/no_main/test.py +++ b/testsuite/tests/instr-cov/no_main/test.py @@ -25,8 +25,6 @@ gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, trace_mode='src') -check_xcov_reports('xcov/*.xcov', { - 'xcov/pkg.adb.xcov': {'+': {5, 6, 8}}, -}) +check_xcov_reports('xcov', {'pkg.adb.xcov': {'+': {5, 6, 8}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/not_array/test.py b/testsuite/tests/instr-cov/not_array/test.py index ba03248f5..99217d5f7 100644 --- a/testsuite/tests/instr-cov/not_array/test.py +++ b/testsuite/tests/instr-cov/not_array/test.py @@ -30,7 +30,7 @@ gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, trace_mode='src') -check_xcov_reports('xcov/*.xcov', {'xcov/main.adb.xcov': { +check_xcov_reports('xcov', {'main.adb.xcov': { '+': {4, 5, 7, 9, 11, 12, 15}, '!': {13}, }}) diff --git a/testsuite/tests/instr-cov/null_proc_generic/test.py b/testsuite/tests/instr-cov/null_proc_generic/test.py index 9f962ac03..cece8fe2d 100644 --- a/testsuite/tests/instr-cov/null_proc_generic/test.py +++ b/testsuite/tests/instr-cov/null_proc_generic/test.py @@ -30,7 +30,7 @@ ) # We only expect non-instrumented lines -check_xcov_reports("*.xcov", {"pkg.ads.xcov": {"?": {6}}}) +check_xcov_reports(".", {"pkg.ads.xcov": {"?": {6}}}) # Check that the null procedure is reported as a warning warning_msg = ( diff --git a/testsuite/tests/instr-cov/orphan-unit/test.py b/testsuite/tests/instr-cov/orphan-unit/test.py index 1880b8f65..dc9e4b8ca 100644 --- a/testsuite/tests/instr-cov/orphan-unit/test.py +++ b/testsuite/tests/instr-cov/orphan-unit/test.py @@ -33,6 +33,6 @@ contents_of("instrument.log").strip(), ) -check_xcov_reports("*.xcov", expected_cov, "obj") +check_xcov_reports("obj", expected_cov) thistest.result() diff --git a/testsuite/tests/instr-cov/pragma_after_cu/test.py b/testsuite/tests/instr-cov/pragma_after_cu/test.py index 4bb0159ea..02581b766 100644 --- a/testsuite/tests/instr-cov/pragma_after_cu/test.py +++ b/testsuite/tests/instr-cov/pragma_after_cu/test.py @@ -18,10 +18,10 @@ mains=['main'], extra_coverage_args=['-axcov', '--output-dir=xcov'], ) -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'+': {6}}, - 'xcov/raise_error.adb.xcov': {'+': {3}}, - 'xcov/raise_error.ads.xcov': {}, +check_xcov_reports('xcov', { + 'main.adb.xcov': {'+': {6}}, + 'raise_error.adb.xcov': {'+': {3}}, + 'raise_error.ads.xcov': {}, }) thistest.result() diff --git a/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py index 6f90cb1f9..82c654ef3 100644 --- a/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py +++ b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py @@ -26,12 +26,11 @@ extra_coverage_args=["-axcov", "--output-dir=xcov"], ) check_xcov_reports( - "*.xcov", + "xcov", { "main.adb.xcov": {"+": {5}}, "pkg.ads.xcov": {"+": {14}}, }, - "xcov", ) thistest.result() diff --git a/testsuite/tests/instr-cov/pragma_no_body/test.py b/testsuite/tests/instr-cov/pragma_no_body/test.py index 759c8a17b..124c6b3f0 100644 --- a/testsuite/tests/instr-cov/pragma_no_body/test.py +++ b/testsuite/tests/instr-cov/pragma_no_body/test.py @@ -18,9 +18,9 @@ mains=['main'], extra_coverage_args=['-axcov', '--output-dir=xcov'], ) -check_xcov_reports('xcov/*.xcov', { - 'xcov/main.adb.xcov': {'+': {5}}, - 'xcov/orig_pkg.adb.xcov': {'+': {4}}, +check_xcov_reports('xcov', { + 'main.adb.xcov': {'+': {5}}, + 'orig_pkg.adb.xcov': {'+': {4}}, }) thistest.result() diff --git a/testsuite/tests/instr-cov/pretty_print/test.py b/testsuite/tests/instr-cov/pretty_print/test.py index 55f53bc87..f8bcd415b 100644 --- a/testsuite/tests/instr-cov/pretty_print/test.py +++ b/testsuite/tests/instr-cov/pretty_print/test.py @@ -20,10 +20,10 @@ trace_mode="src", ) check_xcov_reports( - "xcov/*.xcov", + "xcov", { - "xcov/main.adb.xcov": {"+": {5, 7, 8}}, - "xcov/pkg.adb.xcov": {"+": {5, 6, 8}}, + "main.adb.xcov": {"+": {5, 7, 8}}, + "pkg.adb.xcov": {"+": {5, 6, 8}}, }, ) diff --git a/testsuite/tests/instr-cov/pure_units/test.py b/testsuite/tests/instr-cov/pure_units/test.py index 852857eb3..eb18197e1 100644 --- a/testsuite/tests/instr-cov/pure_units/test.py +++ b/testsuite/tests/instr-cov/pure_units/test.py @@ -25,11 +25,10 @@ gpr_exe_dir=obj_dir, trace_mode='src') check_xcov_reports( - '*.xcov', + 'xcov', {'pkg.ads.xcov': {'+': {12, 15}, '-': {11, 14}}, 'pkg.adb.xcov': {'+': {5, 6}, '-': {8}}, 'pkg-child.ads.xcov': {'+': {9}, '-': {10, 12, 13}}}, - "xcov" ) thistest.result() diff --git a/testsuite/tests/instr-cov/remove_extra_src/test.py b/testsuite/tests/instr-cov/remove_extra_src/test.py index 2fa7ef7a9..61cfb64c0 100644 --- a/testsuite/tests/instr-cov/remove_extra_src/test.py +++ b/testsuite/tests/instr-cov/remove_extra_src/test.py @@ -64,6 +64,6 @@ gpr_obj_dir='obj-myprog', extra_coverage_args=['-axcov', '--output-dir=xcov'], trace_mode='src') -check_xcov_reports('xcov/*.xcov', {'xcov/prog.adb.xcov': {'+': {5}, '-': {6}}}) +check_xcov_reports('xcov', {'prog.adb.xcov': {'+': {5}, '-': {6}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/scalar_and/test.py b/testsuite/tests/instr-cov/scalar_and/test.py index 12711f082..67aa485f1 100644 --- a/testsuite/tests/instr-cov/scalar_and/test.py +++ b/testsuite/tests/instr-cov/scalar_and/test.py @@ -22,6 +22,6 @@ gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, trace_mode='src') -check_xcov_reports('xcov/*.xcov', {'xcov/main.adb.xcov': {'+': {4, 6}}}) +check_xcov_reports('xcov', {'main.adb.xcov': {'+': {4, 6}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/test.py b/testsuite/tests/instr-cov/short_circuit_and_or/test.py index 539e7f0ab..ad62d57c3 100644 --- a/testsuite/tests/instr-cov/short_circuit_and_or/test.py +++ b/testsuite/tests/instr-cov/short_circuit_and_or/test.py @@ -19,9 +19,11 @@ def check_results(): check_xcov_reports( - "main.adb.xcov", - {"main.adb.xcov": {"!": {42, 43, 53, 54}, "+": {81, 82, 87, 88}}}, - cwd="obj", + "obj", + { + "main.adb.xcov": {"!": {42, 43, 53, 54}, "+": {81, 82, 87, 88}}, + "type_pkg.ads.xcov": {}, + }, ) diff --git a/testsuite/tests/instr-cov/stmt_after_accept/test.py b/testsuite/tests/instr-cov/stmt_after_accept/test.py index 6ad2d2095..a763e43ff 100644 --- a/testsuite/tests/instr-cov/stmt_after_accept/test.py +++ b/testsuite/tests/instr-cov/stmt_after_accept/test.py @@ -19,8 +19,8 @@ extra_coverage_args=["-axcov", "--output-dir=xcov"], trace_mode="src", ) -check_xcov_reports("xcov/*.xcov", { - "xcov/main.adb.xcov": {"+": {14, 15, 18, 19, 30, 32}, "-": {20, 23, 25}}, +check_xcov_reports("xcov", { + "main.adb.xcov": {"+": {14, 15, 18, 19, 30, 32}, "-": {20, 23, 25}}, }) thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/C++/test.py b/testsuite/tests/integrated_instrumentation/C++/test.py index be75c01e7..2e2d756bc 100644 --- a/testsuite/tests/integrated_instrumentation/C++/test.py +++ b/testsuite/tests/integrated_instrumentation/C++/test.py @@ -50,6 +50,6 @@ srctracename_for("test"), ] ) -check_xcov_reports("*.xcov", {"test.cpp.xcov": {"+": {6, 7}}}) +check_xcov_reports(".", {"test.cpp.xcov": {"+": {6, 7}}}) thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/basic_cmake/test.py b/testsuite/tests/integrated_instrumentation/basic_cmake/test.py index 00f00f5eb..b33378ec6 100644 --- a/testsuite/tests/integrated_instrumentation/basic_cmake/test.py +++ b/testsuite/tests/integrated_instrumentation/basic_cmake/test.py @@ -46,6 +46,6 @@ srctracename_for("main"), ] ) -check_xcov_reports("*.xcov", {"main.c.xcov": {"+": {6, 7}}}) +check_xcov_reports(".", {"main.c.xcov": {"+": {6, 7}}}) thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/basic_lib/test.py b/testsuite/tests/integrated_instrumentation/basic_lib/test.py index d782a8b39..507088d13 100644 --- a/testsuite/tests/integrated_instrumentation/basic_lib/test.py +++ b/testsuite/tests/integrated_instrumentation/basic_lib/test.py @@ -58,9 +58,6 @@ srctracename_for("main"), ] ) -check_xcov_reports( - "*.xcov", - {"bar.c.xcov": {"+": {4}}, "foo.c.xcov": {"+": {4}}}, -) +check_xcov_reports(".", {"bar.c.xcov": {"+": {4}}, "foo.c.xcov": {"+": {4}}}) thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/basic_stmt/test.py b/testsuite/tests/integrated_instrumentation/basic_stmt/test.py index 34a22a418..027a67b9d 100644 --- a/testsuite/tests/integrated_instrumentation/basic_stmt/test.py +++ b/testsuite/tests/integrated_instrumentation/basic_stmt/test.py @@ -68,6 +68,6 @@ srctracename_for("test"), ] ) -check_xcov_reports("*.xcov", {"pkg.c.xcov": {"+": {4}}}) +check_xcov_reports(".", {"pkg.c.xcov": {"+": {4}}}) thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/test.py b/testsuite/tests/integrated_instrumentation/cmake_lib/test.py index e53833d69..65999d17e 100644 --- a/testsuite/tests/integrated_instrumentation/cmake_lib/test.py +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/test.py @@ -50,7 +50,7 @@ ] ) check_xcov_reports( - "*.xcov", + ".", { "main.c.xcov": {"+": {8, 9}}, "lib.c.xcov": {"+": {6}}, diff --git a/testsuite/tests/integrated_instrumentation/compile_and_link/test.py b/testsuite/tests/integrated_instrumentation/compile_and_link/test.py index 7ffbdc52f..794a0e972 100644 --- a/testsuite/tests/integrated_instrumentation/compile_and_link/test.py +++ b/testsuite/tests/integrated_instrumentation/compile_and_link/test.py @@ -51,6 +51,6 @@ srctracename_for("test"), ] ) -check_xcov_reports("*.xcov", {"pkg.c.xcov": {"+": {4}}}) +check_xcov_reports(".", {"pkg.c.xcov": {"+": {4}}}) thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/isystem/test.py b/testsuite/tests/integrated_instrumentation/isystem/test.py index 857b38d60..1853bf065 100644 --- a/testsuite/tests/integrated_instrumentation/isystem/test.py +++ b/testsuite/tests/integrated_instrumentation/isystem/test.py @@ -60,6 +60,6 @@ srctracename_for("test"), ] ) -check_xcov_reports("*.xcov", {"test.c.xcov": {"+": {6, 7}}}) +check_xcov_reports(".", {"test.c.xcov": {"+": {6, 7}}}) thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/special_filenames/test.py b/testsuite/tests/integrated_instrumentation/special_filenames/test.py index b2647f3ae..91f85a353 100644 --- a/testsuite/tests/integrated_instrumentation/special_filenames/test.py +++ b/testsuite/tests/integrated_instrumentation/special_filenames/test.py @@ -61,6 +61,6 @@ ["coverage", "-cstmt", "-axcov", srctracename_for("test")] + sid_args ) -check_xcov_reports("*.xcov", expected_report) +check_xcov_reports(".", expected_report) thistest.result() diff --git a/testsuite/tests/relocate-build-tree/modified-root-dir/test.py b/testsuite/tests/relocate-build-tree/modified-root-dir/test.py index 68ad4003f..c252c8ce4 100644 --- a/testsuite/tests/relocate-build-tree/modified-root-dir/test.py +++ b/testsuite/tests/relocate-build-tree/modified-root-dir/test.py @@ -57,6 +57,6 @@ extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], ) -check_xcov_reports("*.xcov", expected_reports, "out-instr") +check_xcov_reports("out-instr", expected_reports) thistest.result() diff --git a/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py index ed46226fe..76e9e47cd 100644 --- a/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py +++ b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py @@ -48,7 +48,7 @@ extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], ) -check_xcov_reports("*.xcov", expected_reports, "out-instr") +check_xcov_reports("out-instr", expected_reports) # Check if relative path for GPR works correctly build_run_and_coverage( @@ -58,7 +58,7 @@ extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], ) -check_xcov_reports("*.xcov", expected_reports, "out-instr") +check_xcov_reports("out-instr", expected_reports) os.environ["GPR_PROJECT_PATH"] += os.pathsep + os.path.dirname(tests_gpr) build_run_and_coverage( @@ -68,6 +68,6 @@ extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], ) -check_xcov_reports("*.xcov", expected_reports, "out-instr") +check_xcov_reports("out-instr", expected_reports) thistest.result() diff --git a/testsuite/tests/shared-libs/ada-main/test.py b/testsuite/tests/shared-libs/ada-main/test.py index b61a030a2..8c2484780 100644 --- a/testsuite/tests/shared-libs/ada-main/test.py +++ b/testsuite/tests/shared-libs/ada-main/test.py @@ -47,6 +47,6 @@ # same kind as the others, so force relocatable. extra_gprbuild_args=['-XLIBRARY_TYPE=relocatable']) -check_xcov_reports('*.xcov', {'mylib.adb.xcov': {'+': {5, 6}, '-': {8}}}) +check_xcov_reports('.', {'mylib.adb.xcov': {'+': {5, 6}, '-': {8}}}) thistest.result() diff --git a/testsuite/tests/shared-libs/c-main/test.py b/testsuite/tests/shared-libs/c-main/test.py index c4adc3c5d..c87c79982 100644 --- a/testsuite/tests/shared-libs/c-main/test.py +++ b/testsuite/tests/shared-libs/c-main/test.py @@ -45,7 +45,7 @@ extra_coverage_args=['--annotate=xcov', '--output-dir=.'], extra_gprbuild_args=['-XLIBRARY_TYPE=relocatable']) -check_xcov_reports('*.xcov', { +check_xcov_reports('.', { 'mylib.adb.xcov': {'+': {5, 6}, '-': {8}}, 'mylib.ads.xcov': {}}) diff --git a/testsuite/tests/subp_of_interest/test.py b/testsuite/tests/subp_of_interest/test.py index f385d7864..75305bb7b 100644 --- a/testsuite/tests/subp_of_interest/test.py +++ b/testsuite/tests/subp_of_interest/test.py @@ -74,13 +74,12 @@ def check_xcov(label, args, expected_output=""): cov_ckpt_args = cov_args[:-1] + ["--checkpoint", ckpt_filename] if src_traces: check_xcov_reports( - "*.xcov", + "xcov_subp", { "main.adb.xcov": {}, "pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {11, 19, 30}}, }, - "xcov_subp", ) # Then check that the checkpoint contains only coverage data for the @@ -89,13 +88,12 @@ def check_xcov(label, args, expected_output=""): thistest.log("== xcov_no_subp ==") check_xcov("xcov_no_subp", cov_ckpt_args) check_xcov_reports( - "*.xcov", + "xcov_no_subp", { "main.adb.xcov": {"-": {5, 6}}, "pkg.ads.xcov": {"-": {7}}, "pkg.adb.xcov": {"+": {11, 19, 30}, "-": {22, 33, 34, 35}}, }, - "xcov_no_subp", ) # Check that we can still select subprograms of interest declared in the @@ -110,12 +108,11 @@ def check_xcov(label, args, expected_output=""): ], ) check_xcov_reports( - "*.xcov", + "xcov_ignore", { "main.adb.xcov": {}, "pkg.adb.xcov": {"+": {30}}, }, - "xcov_ignore", ) # Also check the warnings when the subprogram switch is ill-formed diff --git a/testsuite/tests/subp_of_interest_c/test.py b/testsuite/tests/subp_of_interest_c/test.py index d58f1e4ab..79e002e0e 100644 --- a/testsuite/tests/subp_of_interest_c/test.py +++ b/testsuite/tests/subp_of_interest_c/test.py @@ -31,13 +31,12 @@ ) check_xcov_reports( - "*.xcov", + "obj", { "main.c.xcov": {}, "bar.h.xcov": {}, "pkg.c.xcov": {"+": {4}}, }, - "obj", ) thistest.result() From f9ad8f9626a9a686039bd18560252421d7bde23a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 29 Jan 2024 14:49:34 +0100 Subject: [PATCH 0698/1483] Files_Table: add a Get_Unique_Filename API The Get_Unique_Name API returns a name that is not directly usable as a source filename. Add an API to turn that unique name into a filename and generalize its use in the codebase. --- tools/gnatcov/annotations.adb | 21 --------------------- tools/gnatcov/annotations.ads | 5 ----- tools/gnatcov/files_table.adb | 18 ++++++++++++++++++ tools/gnatcov/files_table.ads | 7 +++++++ tools/gnatcov/outputs.ads | 2 +- 5 files changed, 26 insertions(+), 27 deletions(-) diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index a687feb83..f2e19f25c 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -39,27 +39,6 @@ with Traces_Disa; package body Annotations is - ------------------------- - -- Get_Unique_Filename -- - ------------------------- - - function Get_Unique_Filename - (File : Source_File_Index; - Extension : String) return String - is - -- Just take the unique name and turn path separators into dashes. - -- It should be enough... - - Result : String := Get_Unique_Name (File); - begin - for C of Result loop - if C in '/' | '\' then - C := '-'; - end if; - end loop; - return Result & '.' & Extension; - end Get_Unique_Filename; - procedure Disp_File_Line_State (Pp : in out Pretty_Printer'Class; File_Index : Source_File_Index; diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index a207c76d8..2fca8d0ae 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -75,11 +75,6 @@ package Annotations is private - function Get_Unique_Filename - (File : Source_File_Index; - Extension : String) return String; - -- Return an unique filename to hold coverage annotations for File - function SCO_Text (SCO : SCO_Id; Length : Natural := 8) return String; -- Extract the text of SCO from source file, truncating it to the -- first source line and the first Length characters. If it has been diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 7cd2d789f..1eb0f9683 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -1312,6 +1312,24 @@ package body Files_Table is return File.Unique_Name.all; end Get_Unique_Name; + ------------------------- + -- Get_Unique_Filename -- + ------------------------- + + function Get_Unique_Filename + (Index : Source_File_Index; + Extension : String) return String + is + Result : String := Get_Unique_Name (Index); + begin + for C of Result loop + if C in '/' | '\' then + C := '-'; + end if; + end loop; + return Result & '.' & Extension; + end Get_Unique_Filename; + ---------------------- -- Create_File_Info -- ---------------------- diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 73f0ac5c0..6163e781f 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -152,6 +152,13 @@ package Files_Table is -- (2) after rebasing them using the rebase list; -- (3) from the source search path. + function Get_Unique_Filename + (Index : Source_File_Index; + Extension : String) return String + with Pre => Get_File (Index).Kind = Source_File; + -- Wrapper around Get_Unique_Name, replacing slashes with dashes in the + -- unique name and suffixing with Extension. + procedure Add_Source_Rebase (Old_Prefix : String; New_Prefix : String); -- Add a new entry to the rebase list. This entry says that a file -- whose name is Old_Prefix & "something" should be found in diff --git a/tools/gnatcov/outputs.ads b/tools/gnatcov/outputs.ads index 534c36619..bc8d584e8 100644 --- a/tools/gnatcov/outputs.ads +++ b/tools/gnatcov/outputs.ads @@ -163,7 +163,7 @@ package Outputs is function Get_PP_Filename (SFI : Source_File_Index) return String - is (PP_Temp_Dir.Directory_Name / (Get_Unique_Name (SFI) & ".pp")); + is (PP_Temp_Dir.Directory_Name / (Get_Unique_Filename (SFI, "pp"))); procedure Clean_Dir (Dir : String; From a45ce89f30ce94dd0e8cab7c9ae06a147dd88bf4 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 29 Jan 2024 14:48:09 +0100 Subject: [PATCH 0699/1483] gnatcov setup-integration: Compute the SID filename As SID files are generated in the same directory for every instrumented file, make sure to compute a unique SID filename for each source of interest, and add a unique prefix in case of homonym filenames. --- .../special_filenames/test.py | 18 ++++++++----- tools/gnatcov/files_handling.ads | 7 +++++ tools/gnatcov/instrument-gcc_wrapper.adb | 27 +++++++++++-------- tools/gnatcov/instrument-setup_config.adb | 25 +++++++++++++++-- tools/gnatcov/instrument-setup_config.ads | 3 +++ tools/gnatcov/sc_obligations.adb | 3 --- tools/gnatcov/sc_obligations.ads | 2 ++ 7 files changed, 63 insertions(+), 22 deletions(-) diff --git a/testsuite/tests/integrated_instrumentation/special_filenames/test.py b/testsuite/tests/integrated_instrumentation/special_filenames/test.py index 91f85a353..66338df90 100644 --- a/testsuite/tests/integrated_instrumentation/special_filenames/test.py +++ b/testsuite/tests/integrated_instrumentation/special_filenames/test.py @@ -26,17 +26,23 @@ for src, dest in copy_map.items(): cp(os.path.join("..", src), dest) -# Compute the expected coverage report from the actual source filenames. Note -# that in xcov filenames, "gnatcov coverage" first turns '\' to '/' (during -# path separator canonicalization) and then the unique filename machinery turns -# '/' to '-'. +# Compute canonicalized filenames, which will be the base names for gnatcov +# artifacts (SID and xcov files). Note that "gnatcov" first turns '\' to '/' +# (during path separator canonicalization) and then the unique filename +# machinery turns '/' to '-'. +canonicalized_filenames = { + filename: mapped.replace("\\", "-") + for filename, mapped in copy_map.items() +} + +# Compute the expected coverage report from the actual source filenames coverage_data = { "test.c": {"+": {7, 8, 9}}, "foo.c": {"+": {4, 7}, "-": {5}}, "bar.c": {"+": {4}}, } expected_report = { - "{}.xcov".format(copy_map[filename].replace("\\", "-")): report + "{}.xcov".format(canonicalized_filenames[filename]): report for filename, report in coverage_data.items() } @@ -56,7 +62,7 @@ cmdrun(["test program"], for_pgm=False) # Check coverage expectations -sid_args = [f"--sid={filename}.sid" for filename in sources] +sid_args = [f"--sid={filename}.sid" for filename in canonicalized_filenames.values()] xcov( ["coverage", "-cstmt", "-axcov", srctracename_for("test")] + sid_args diff --git a/tools/gnatcov/files_handling.ads b/tools/gnatcov/files_handling.ads index 220c83256..e825748a1 100644 --- a/tools/gnatcov/files_handling.ads +++ b/tools/gnatcov/files_handling.ads @@ -19,6 +19,7 @@ with Ada.Containers.Ordered_Maps; with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; +with Ada.Strings.Unbounded; with GNATCOLL.VFS; use GNATCOLL.VFS; @@ -56,4 +57,10 @@ package Files_Handling is "<" => GNATCOLL.VFS."<", "=" => GNATCOLL.VFS."="); + package File_To_String_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Virtual_File, + Element_Type => Unbounded_String, + "<" => GNATCOLL.VFS."<", + "=" => Ada.Strings.Unbounded."="); + end Files_Handling; diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 7a47e197c..ce881336d 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -773,6 +773,12 @@ begin end if; end loop; + -- Get the files of interest + + for C in Instr_Config.File_To_SID.Iterate loop + Files_Of_Interest.Insert (File_To_String_Maps.Key (C)); + end loop; + -- Parse the compiler driver invocation Comp_DB := Parse_Compiler_Driver_Command (Context, Prj, Instr_Dir, Cargs); @@ -815,25 +821,24 @@ begin Simple_Name : constant String := +Comp_Command.File.Base_Name; Instr_Name : constant String := (+Prj.Output_Dir) / Simple_Name; + FI : constant File_To_String_Maps.Cursor := + Instr_Config.File_To_SID.Find (Comp_Command.File); begin -- Start by instrumenting the file as a source, if it is a unit of -- interest. - if Files_Of_Interest.Contains (Comp_Command.File) then + if File_To_String_Maps.Has_Element (FI) then -- Pass the compiler switches through the project description Instrument.Source - (Instrumenter => Instrumenter, - Files_Of_Interest => Switches.Files_Of_Interest, - Prj => Prj, - Unit_Name => Fullname, - - -- Generate all the SID files under the same directory as the - -- compiler wrapper as they must persist. TODO??? Deal with - -- homonym files in SID names. - - SID_Name => Compiler_Wrapper_Dir / (Simple_Name & ".sid")); + (Unit_Name => Fullname, + SID_Name => + Compiler_Wrapper_Dir / + (+File_To_String_Maps.Element (FI)), + Instrumenter => Instrumenter, + Files_Of_Interest => Files_Of_Interest, + Prj => Prj); Comp_Command_Ref.Instrumentation_Sources.Append (Instrumenter.Buffer_Unit diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index 4c38c7295..46b29b831 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -28,6 +28,7 @@ with GNAT.Strings; with GNATCOLL.VFS; use GNATCOLL.VFS; with Coverage; +with Files_Table; use Files_Table; with JSON; use JSON; with Logging; with Outputs; use Outputs; @@ -277,11 +278,29 @@ package body Instrument.Setup_Config is -- Then, register the files of interest declare + SFIs : SFI_Sets.Set; Files_Of_Interest_JSON : JSON_Array; + + File_Info : JSON_Value; + -- JSON object containing the name of the file and its SID file + begin + -- Start by adding into the files table all of the files of interest + for F of Files_Of_Interest loop - Append (Files_Of_Interest_JSON, Create (+F.Full_Name)); + SFIs.Insert (Get_Index_From_Full_Name (+F.Full_Name, Source_File)); end loop; + + -- Then, compute file information (SID name) for every file of + -- interest and add entries into the generated configuration. + + for SFI of SFIs loop + File_Info := Create_Object; + File_Info.Set_Field ("source-file", Get_Full_Name (SFI)); + File_Info.Set_Field ("sid-file", Get_Unique_Filename (SFI, "sid")); + Append (Files_Of_Interest_JSON, File_Info); + end loop; + Config.Set_Field ("files-of-interest", Files_Of_Interest_JSON); end; @@ -388,7 +407,9 @@ package body Instrument.Setup_Config is Config_JSON.Get ("files-of-interest"); begin for FOI of FOI_JSON loop - Switches.Files_Of_Interest.Include (Create_Normalized (Get (FOI))); + Result.File_To_SID.Insert + (Create_Normalized (FOI.Get ("source-file")), + FOI.Get ("sid-file")); end loop; end; diff --git a/tools/gnatcov/instrument-setup_config.ads b/tools/gnatcov/instrument-setup_config.ads index ff589e001..ff7a6e72c 100644 --- a/tools/gnatcov/instrument-setup_config.ads +++ b/tools/gnatcov/instrument-setup_config.ads @@ -46,6 +46,9 @@ package Instrument.Setup_Config is -- instrumented sources in the instrumented main executable. For now, -- we always link it statically. + File_To_SID : File_To_String_Maps.Map; + -- Maps a source file to its SID basename + end record; Instrumentation_Config_Filename : constant String := "gnatcov_config.json"; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index a3e78776e..3917a944c 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -4533,9 +4533,6 @@ package body SC_Obligations is ------------------------------- procedure Report_Units_Without_Code is - - package SFI_Sets is new Ada.Containers.Ordered_Sets - (Valid_Source_File_Index); Reported_Origins : SFI_Sets.Set; -- Keep track of origins that we reported, so that we don't report the -- same origin twice. This happens when multiple compilation units share diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index f3677c85b..67281b50d 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -66,6 +66,8 @@ package SC_Obligations is subtype SFI_Vector is SFI_Vectors.Vector; + package SFI_Sets is new Ada.Containers.Ordered_Sets (Source_File_Index); + ------------------------ -- Types of decisions -- ------------------------ From 8abdf9b9d37d162a47e56d2db91df49f2e08558a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 29 Jan 2024 10:10:24 +0100 Subject: [PATCH 0700/1483] Integrated instrumentation: fix the computation of the buffers list To compute the list of buffers in the link closure in the integrated instrumentation mode, gnatcov searches all buffer-like symbols in the object / library / source files referenced in the link command line. This has the downside of pulling all instrumented units from a static library, which can result in a link failure. To fix this, we link two times: * The first time, we link against an empty buffers list. * The second time, we link against a buffers list unit that references exactly the list of coverage buffers included in the first link. --- .../duplicated_symbols_in_libraries/Makefile | 16 + .../libbar/Makefile | 8 + .../libbar/bar.c | 5 + .../libbar/foo.c | 5 + .../libfoo/Makefile | 8 + .../libfoo/bar.c | 5 + .../libfoo/foo.c | 5 + .../duplicated_symbols_in_libraries/main.c | 10 + .../duplicated_symbols_in_libraries/test.py | 96 ++++++ tools/gnatcov/instrument-gcc_wrapper.adb | 274 ++++++------------ 10 files changed, 249 insertions(+), 183 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/Makefile create mode 100644 testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/Makefile create mode 100644 testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/bar.c create mode 100644 testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/foo.c create mode 100644 testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/Makefile create mode 100644 testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/bar.c create mode 100644 testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/foo.c create mode 100644 testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/main.c create mode 100644 testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/Makefile b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/Makefile new file mode 100644 index 000000000..bdb2aacbf --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/Makefile @@ -0,0 +1,16 @@ +main: main.o libbar/libbar.a libfoo/libfoo.a + gcc -o main main.o -Llibbar/ -Llibfoo -lbar -lfoo + +libbar/libbar.a: + $(MAKE) -C libbar + +libfoo/libfoo.a: + $(MAKE) -C libfoo + +%.o: %.c + gcc -c $< -o $@ + +clean: + rm -rf main.o + $(MAKE) -C libbar clean + $(MAKE) -C libfoo clean diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/Makefile b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/Makefile new file mode 100644 index 000000000..1521b5f39 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/Makefile @@ -0,0 +1,8 @@ +libbar.a: foo.o bar.o + ar -rc $@ $^ + +%.o: %.c + gcc -c $< -o $@ + +clean: + rm -f foo.o bar.o libbar.a diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/bar.c b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/bar.c new file mode 100644 index 000000000..291781351 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/bar.c @@ -0,0 +1,5 @@ +int +bar () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/foo.c b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/foo.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libbar/foo.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/Makefile b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/Makefile new file mode 100644 index 000000000..ec29beda6 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/Makefile @@ -0,0 +1,8 @@ +libfoo.a: foo.o bar.o + ar -rc $@ $^ + +%.o: %.c + gcc -c $< -o $@ + +clean: + rm -f foo.o bar.o libfoo.a diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/bar.c b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/bar.c new file mode 100644 index 000000000..291781351 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/bar.c @@ -0,0 +1,5 @@ +int +bar () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/foo.c b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/foo.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/libfoo/foo.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/main.c b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/main.c new file mode 100644 index 000000000..2286f6957 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/main.c @@ -0,0 +1,10 @@ +extern int foo (); +extern int bar (); + +int +main () +{ + foo (); + bar (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py new file mode 100644 index 000000000..6866702ca --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py @@ -0,0 +1,96 @@ +""" +Check that gnatcov integrated instrumentation only includes coverage buffer +symbols that are in the main link closure. It used to include in the coverage +buffers list every coverage buffer symbol that was in a library / object file +on the link command line. This could result in pulling into the link closure +object files that would have not been included otherwise, and thus result in +clashing symbols. + +Also check that gnatcov generates unique SID names when there are homonym +files +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import contents_of, Wdir +from SCOV.minicheck import check_xcov_reports, checked_xcov +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "main.c"), ".") +cp(os.path.join("..", "libbar"), ".", recursive=True) +cp(os.path.join("..", "libfoo"), ".", recursive=True) + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'libbar', 'bar.c')}", + f"--files={os.path.join(cwd, 'libbar', 'foo.c')}", + f"--files={os.path.join(cwd, 'libfoo', 'bar.c')}", + f"--files={os.path.join(cwd, 'libfoo', 'foo.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + "-v", + "--save-temps", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make"], for_pgm=False) + +# Run the executable +cmdrun(["main"], for_pgm=True) + +# Check coverage expectations +log_file = "coverage.log" +xcov( + [ + "coverage", + "--level=stmt", + "--sid=libbar-foo.c.sid", + "--sid=libbar-bar.c.sid", + "--sid=libfoo-foo.c.sid", + "--sid=libfoo-bar.c.sid", + "-axcov", + srctracename_for("main"), + ], + out=log_file, +) + +# TODO: the warnings regarding homonym filenames are unexpected but they do not +# affect the testcase. +thistest.fail_if_no_match( + '"gnatcov output" ({})'.format(log_file), + "Warning: same base name for files:" + f'\r?\n {os.path.join(cwd, "libfoo", "foo.c")}' + f'\r?\n {os.path.join(cwd, "libbar", "foo.c")}' + "\r?\nWarning: same base name for files:" + f'\r?\n {os.path.join(cwd, "libfoo", "bar.c")}' + f'\r?\n {os.path.join(cwd, "libbar", "bar.c")}', + contents_of(log_file), +) +check_xcov_reports( + "*.xcov", + { + "libbar-bar.c.xcov": {"+": {4}}, + "libbar-foo.c.xcov": {"+": {4}}, + "libfoo-bar.c.xcov": {"-": {4}}, + "libfoo-foo.c.xcov": {"-": {4}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index ce881336d..4602d8482 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -19,7 +19,6 @@ with Ada.Containers; use Ada.Containers; with Ada.Containers.Vectors; with Ada.Directories; use Ada.Directories; -with Ada.Environment_Variables; with Ada.Strings; use Ada.Strings; with Ada.Text_IO; use Ada.Text_IO; @@ -98,31 +97,13 @@ is (Index_Type => Positive, Element_Type => Assembly_Command_Type); type Link_Command_Type is record - Library_Dirs : String_Vectors.Vector; - -- List of library directories arguments (passed through -L switches) - - Libraries : String_Vectors.Vector; - -- List of libraries (passed through -l switches) - - Object_Files : File_Vectors.Vector; - -- List of object files (positional arguments) - - Source_Files : File_Vectors.Vector; - -- When the compiler driver command compiles and links, this contains - -- the list of files that are compiled by the compiler driver command. - Target : Virtual_File; -- Output executable file (passed through the -o switch) end record; -- Information relative to a link command launched by the compiler driver - No_Link_Command : constant Link_Command_Type := - (Library_Dirs => String_Vectors.Empty_Vector, - Libraries => String_Vectors.Empty_Vector, - Object_Files => File_Vectors.Empty_Vector, - Source_Files => File_Vectors.Empty_Vector, - Target => No_File); + No_Link_Command : constant Link_Command_Type := (Target => No_File); type Compilation_Database is record Compilation_Commands : Compilation_Command_Vectors.Vector; @@ -201,16 +182,16 @@ is -- Parse an assembly command function Parse_Link_Command - (Context : Parsing_Context; - Command : String_Vectors.Vector) return Link_Command_Type; + (Command : String_Vectors.Vector) return Link_Command_Type; -- Parse a link command function Coverage_Buffer_Symbols - (Tmp_Dir : String; - Command : Link_Command_Type; + (Symbol_File : Virtual_File; + Tmp_Dir : String; Compiler_Driver : String; Config : Instrumentation_Config) return String_Sets.Set; - -- Return the list of coverage buffer symbols in the link closure + -- Return the list of coverage buffer symbols in the given symbol file + -- (object or library file). procedure Run_Original_Compiler (Context : Parsing_Context; @@ -373,7 +354,7 @@ is & " commands, which is not supported"); end if; Result.Link_Command := - (Parse_Link_Command (Context, Command)); + (Parse_Link_Command (Command)); Parsed_Link_Command := True; end if; <> @@ -514,8 +495,7 @@ is ------------------------ function Parse_Link_Command - (Context : Parsing_Context; - Command : String_Vectors.Vector) return Link_Command_Type + (Command : String_Vectors.Vector) return Link_Command_Type is use String_Vectors; Result : Link_Command_Type; @@ -526,32 +506,8 @@ is declare Arg : constant Unbounded_String := Element (Cur); begin - if Arg = "-L" then - Result.Library_Dirs.Append (Element (Next (Cur))); - elsif Starts_With (Arg, "-L") then - Result.Library_Dirs.Append - (Unbounded_Slice (Arg, 3, Length (Arg))); - elsif Arg = "-l" then - Result.Libraries.Append (Element (Next (Cur))); - elsif Starts_With (Arg, "-l") then - Result.Libraries.Append - (Unbounded_Slice (Arg, 3, Length (Arg))); - elsif Arg = "-o" then + if Arg = "-o" then Result.Target := Create_Normalized (+Element (Next (Cur))); - elsif Ends_With (Arg, ".o") then - declare - Object_File : constant Virtual_File := - Create_Normalized (+Arg); - begin - if Context.Source_Mapping.Contains (Object_File) then - Result.Source_Files.Append - (Context.Source_Mapping.Element (Object_File)); - else - Result.Object_Files.Append (Create_Normalized (+Arg)); - end if; - end; - elsif Ends_With (Arg, ".a") then - Result.Libraries.Append (Arg); end if; end; end loop; @@ -568,144 +524,57 @@ is ----------------------------- function Coverage_Buffer_Symbols - (Tmp_Dir : String; - Command : Link_Command_Type; + (Symbol_File : Virtual_File; + Tmp_Dir : String; Compiler_Driver : String; Config : Instrumentation_Config) return String_Sets.Set is - function Coverage_Buffer_Symbols - (Symbol_File : Virtual_File) return String_Sets.Set; - -- Return the list of coverage buffer symbols in the given symbol file - -- (object or library file). - - ----------------------------- - -- Coverage_Buffer_Symbols -- - ----------------------------- - - function Coverage_Buffer_Symbols - (Symbol_File : Virtual_File) return String_Sets.Set - is - Args : String_Vectors.Vector; - Output_Filename : constant String := - Tmp_Dir / ("nm_" & Filename_Slug (+Symbol_File.Full_Name)); - Output_File : File_Type; - - Result : String_Sets.Set; - Ignore_Success : Boolean; - - begin - -- Use the compiler nm to dump the list of symbols - - Args.Append (+"--format=just-symbol"); - Args.Append (Full_Name (Symbol_File)); - - -- The command can fail with e.g. "file format not recognized" for - -- system libraries. TODO??? Investigate why. We should also avoid - -- invoking nm on system libraries altogether. - - Ignore_Success := - Run_Command - (Command => - +Config.Nms.Element (+Base_Name (Compiler_Driver)), - Arguments => Args, - Origin_Command_Name => "compiler wrapper", - Output_File => Output_Filename, - Ignore_Error => True); - - -- Each line of the output is a symbol - - Open (Output_File, In_File, Output_Filename); - - while not End_Of_File (Output_File) loop - declare - Line_Str : constant String := Get_Line (Output_File); - Line : constant Unbounded_String := +Line_Str; - begin - if Starts_With (Line, "gnatcov_rts_buffers") - - -- The buffer list symbols is also referenced in the link - -- closure: make sure not to pick it as it is named - -- gnatcov_rts_buffers_array_, so - -- gnatcov_rts_buffers_array_main in our case. - - and then Ends_With (Line, "_buffers") - then - Result.Insert (Line); - end if; - end; - end loop; - Close (Output_File); - return Result; - end Coverage_Buffer_Symbols; + Args : String_Vectors.Vector; + Output_Filename : constant String := + Tmp_Dir / ("nm_" & Filename_Slug (+Symbol_File.Full_Name)); + Output_File : File_Type; Result : String_Sets.Set; begin - -- Search through object files and libraries the list of coverage buffer - -- symbols. + -- Use the compiler nm to dump the list of symbols - -- Start by dealing with object files + Args.Append (+"--format=just-symbol"); + Args.Append (Full_Name (Symbol_File)); + Run_Command + (Command => + +Config.Nms.Element (+Base_Name (Compiler_Driver)), + Arguments => Args, + Origin_Command_Name => "compiler wrapper", + Output_File => Output_Filename); - for Object_File of Command.Object_Files loop - Result.Union (Coverage_Buffer_Symbols (Object_File)); - end loop; + -- Each line of the output is a symbol - -- Then, deal with library files + Open (Output_File, In_File, Output_Filename); - declare - Library_Path : Unbounded_String; - begin - for Library_Dir of Command.Library_Dirs loop - Append (Library_Path, Library_Dir); - Append (Library_Path, GNAT.OS_Lib.Path_Separator); - end loop; - Append - (Library_Path, - Ada.Environment_Variables.Value ("LIBRARY_PATH", "")); - - for Library of Command.Libraries loop - if Ends_With (Library, ".a") then + while not End_Of_File (Output_File) loop + declare + Line : constant Unbounded_String := +Get_Line (Output_File); + begin + if Starts_With (Line, "gnatcov_rts_buffers") - -- Library filename on the command line, no need to look it up + -- The buffer list symbol is also referenced in the link + -- closure: make sure not to pick it as it is named + -- gnatcov_rts_buffers_array_, so + -- gnatcov_rts_buffers_array_main in our case. - Result.Union - (Coverage_Buffer_Symbols (Create_Normalized (+Library))); - else - -- Simple library name passed to the -l option, search the - -- actual file on the library path. - - declare - use type GNAT.OS_Lib.String_Access; - Library_File : GNAT.OS_Lib.String_Access := - GNAT.OS_Lib.Locate_Regular_File - ("lib" & (+Library) & ".a", +Library_Path); - begin - if Library_File /= null then - Result.Union - (Coverage_Buffer_Symbols - (Create_Normalized (Library_File.all))); - GNAT.OS_Lib.Free (Library_File); - end if; - end; + and then Ends_With (Line, "_buffers") + then + Result.Insert (Line); end if; - end loop; - end; - - -- Deal with sources that were compiled _and_ linked by the same driver - -- command. - - for Source of Command.Source_Files loop - if Switches.Files_Of_Interest.Contains (Source) then - declare - Unit : constant Compilation_Unit := - (Language => File_Based_Language, - Unit_Name => Full_Name (Source)); - begin - Result.Insert (+Unit_Buffers_Name (Unit)); - end; - end if; + end; end loop; + if not Save_Temps then + Delete (Output_File); + else + Close (Output_File); + end if; return Result; end Coverage_Buffer_Symbols; @@ -749,6 +618,9 @@ is Instrumented_Files : String_Sets.Set; -- List of instrumented files (files of interest / main files / both) + Files_Of_Interest : File_Sets.Set; + -- List of files of interest + -- Start of processing for Compiler_Wrappers.GCC begin @@ -874,7 +746,9 @@ begin end; end loop; - -- Then, deal with the link command + -- If this is a link command, add an empty buffers list unit to the link + -- closure. We will compute the correct buffers list unit at the second + -- link. if Comp_DB.Link_Command /= No_Link_Command then declare @@ -885,15 +759,9 @@ begin -- compilable by a C / C++ compiler, which are the languages -- supported by the integrated instrumentation scheme. - Buffer_Symbols : constant String_Sets.Set := - Coverage_Buffer_Symbols - (Tmp_Dir => +Prj.Output_Dir, - Command => Comp_DB.Link_Command, - Compiler_Driver => Compiler_Exec, - Config => Instr_Config); begin Buffers_List_Unit := - Instrumenter.Emit_Buffers_List_Unit (Buffer_Symbols, Prj); + Instrumenter.Emit_Buffers_List_Unit (String_Sets.Empty_Set, Prj); end; end if; @@ -1041,6 +909,46 @@ begin end if; end loop; end if; + + -- If this was a link command, the first link is done with a dummy + -- buffers unit list, to know precisely the list of buffer symbols + -- included in the executable. We generate an accurate buffers unit list + -- by inspecting the executable symbols, and link a second time with + -- this buffers unit list. + -- + -- Note that the buffers list unit compilation unit is included in the + -- compiler driver invocation (through New_Args), and the buffers + -- list compilation unit generated below overwrites the dummy one. + + if Comp_DB.Link_Command /= No_Link_Command + and then Ada.Directories.Exists + (+Comp_DB.Link_Command.Target.Full_Name) + then + declare + Instrumenter : constant Language_Instrumenter'Class := + Create_C_Instrumenter + (Instr_Config.Tag, Integrated_Instrumentation); + -- Emit the buffers list unit as a C compilation unit as it is + -- compilable by a C / C++ compiler, which are the languages + -- supported by the integrated instrumentation scheme. + + begin + -- Generate the buffers list unit + + Buffers_List_Unit := + Instrumenter.Emit_Buffers_List_Unit + (Coverage_Buffer_Symbols + (Symbol_File => Comp_DB.Link_Command.Target, + Tmp_Dir => +Prj.Output_Dir, + Compiler_Driver => Compiler_Exec, + Config => Instr_Config), + Prj); + + -- Then, re-run the link with the correct buffers list unit + + Run_Original_Compiler (Context, New_Args); + end; + end if; end; end Instrument.Gcc_Wrapper; From 417f35310d3cfc75c6562ea8e2c92a6366d7618b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 19 Feb 2024 17:59:20 +0100 Subject: [PATCH 0701/1483] Kill iterator filter test for all runtimes not supporting containers --- testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt b/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt index 21590854e..e1d9057fb 100644 --- a/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt +++ b/testsuite/tests/Ada2022/iter_filter/cont_aggr/test.opt @@ -1 +1 @@ -RTS_ZFP DEAD Test uses Ada.Containers, not available in that profile +!RTS_FULL DEAD Test uses Ada.Containers, not available in that profile From c6149d8798b1b0f979be84727617aad922f37c9a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 19 Feb 2024 18:57:12 +0000 Subject: [PATCH 0702/1483] integrated_instr/duplicated_symbols_in_libraries: remove unused import --- .../duplicated_symbols_in_libraries/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py index 6866702ca..c4219b868 100644 --- a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py @@ -15,9 +15,9 @@ from e3.fs import cp +from SCOV.minicheck import check_xcov_reports from SUITE.control import env from SUITE.cutils import contents_of, Wdir -from SCOV.minicheck import check_xcov_reports, checked_xcov from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov Wdir("tmp_") From 6cff8e1a126d4c20971d2dc38863cca0964e26ca Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 19 Feb 2024 18:59:04 +0000 Subject: [PATCH 0703/1483] integrated_instr/duplicated_symbols_in_libraries: minor refactoring --- .../duplicated_symbols_in_libraries/test.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py index c4219b868..5d4d70e4c 100644 --- a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py @@ -25,10 +25,8 @@ cwd = os.getcwd() # Copy the sources and the Makefile in the temporary directory -cp(os.path.join("..", "Makefile"), ".") -cp(os.path.join("..", "main.c"), ".") -cp(os.path.join("..", "libbar"), ".", recursive=True) -cp(os.path.join("..", "libfoo"), ".", recursive=True) +for item in ["Makefile", "libbar", "libfoo", "main.c"]: + cp(os.path.join("..", item), ".", recursive=True) # Then, setup the instrumentation process xcov( From 499ae35252d61e5c61810e2e1e034c2a21e52719 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 19 Feb 2024 18:59:46 +0000 Subject: [PATCH 0704/1483] integrated_instr/duplicated_symbols_in_libraries: minor refactoring --- .../duplicated_symbols_in_libraries/test.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py index 5d4d70e4c..c3c96aa5b 100644 --- a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py @@ -81,14 +81,11 @@ f'\r?\n {os.path.join(cwd, "libbar", "bar.c")}', contents_of(log_file), ) -check_xcov_reports( - "*.xcov", - { - "libbar-bar.c.xcov": {"+": {4}}, - "libbar-foo.c.xcov": {"+": {4}}, - "libfoo-bar.c.xcov": {"-": {4}}, - "libfoo-foo.c.xcov": {"-": {4}}, - }, -) +check_xcov_reports(".", { + "libbar-bar.c.xcov": {"+": {4}}, + "libbar-foo.c.xcov": {"+": {4}}, + "libfoo-bar.c.xcov": {"-": {4}}, + "libfoo-foo.c.xcov": {"-": {4}}, +}) thistest.result() From 459291e565ab403bc754dd1b7e2a620c775510e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 20 Feb 2024 09:25:27 +0100 Subject: [PATCH 0705/1483] Kill tests with expression functions for 7.1.2 with optimization enabled We have documented a limitation concerning the coverage of expression functions for the 7.1.2 toolchain when optimization is enabled. The two test cases concerned by this change fall in that case, so deactivate them for that config. --- testsuite/tests/222-scope-expr-func/test.opt | 1 + testsuite/tests/222-subp-line-computation/test.opt | 1 + 2 files changed, 2 insertions(+) diff --git a/testsuite/tests/222-scope-expr-func/test.opt b/testsuite/tests/222-scope-expr-func/test.opt index ae2e6e8ac..a2edd5445 100644 --- a/testsuite/tests/222-scope-expr-func/test.opt +++ b/testsuite/tests/222-scope-expr-func/test.opt @@ -1,2 +1,3 @@ bin-traces DEAD --subprograms not supported in bin trace mode 5.04a1 DEAD test uses Ada 2012 features +7.1.2,CARGS_O1 DEAD expression functions and optimization diff --git a/testsuite/tests/222-subp-line-computation/test.opt b/testsuite/tests/222-subp-line-computation/test.opt index ae2e6e8ac..a2edd5445 100644 --- a/testsuite/tests/222-subp-line-computation/test.opt +++ b/testsuite/tests/222-subp-line-computation/test.opt @@ -1,2 +1,3 @@ bin-traces DEAD --subprograms not supported in bin trace mode 5.04a1 DEAD test uses Ada 2012 features +7.1.2,CARGS_O1 DEAD expression functions and optimization From 5507943630dbb6635d2639507e614da7bee4447a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 12 Feb 2024 14:54:39 +0000 Subject: [PATCH 0706/1483] SC_Obligations: assert that bit maps are contained in unit SCOs The bit maps that instrumenters create for some unit should designate only SCOs that belong to this unit. This assumption was so far implicit: since we rely on it, make it more explicit and check it in debug builds. --- tools/gnatcov/sc_obligations.adb | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 3917a944c..28f3be44d 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -145,6 +145,10 @@ package body SC_Obligations is function Has_SCOs (CUI : CU_Info) return Boolean is (CUI.First_SCO <= CUI.Last_SCO); + function Are_Bit_Maps_In_Range + (Bit_Maps : CU_Bit_Maps; CU : CU_Info) return Boolean; + -- Return whether all SCOs referenced in Bit_Maps belong to CU + package CU_Info_Vectors is new Ada.Containers.Vectors (Index_Type => Valid_CU_Id, Element_Type => CU_Info); @@ -4588,6 +4592,23 @@ package body SC_Obligations is SCO_Vector.Reference (C_SCO).BDD_Node := BDD_Node; end Set_BDD_Node; + --------------------------- + -- Are_Bit_Maps_In_Range -- + --------------------------- + + function Are_Bit_Maps_In_Range + (Bit_Maps : CU_Bit_Maps; CU : CU_Info) return Boolean + is + subtype SCO_Range is SCO_Id range CU.First_SCO .. CU.Last_SCO; + begin + return + (for all SCO of Bit_Maps.Statement_Bits.all => SCO in SCO_Range) + and then (for all Info of Bit_Maps.Decision_Bits.all + => Info.D_SCO in SCO_Range) + and then (for all Info of Bit_Maps.MCDC_Bits.all + => Info.D_SCO in SCO_Range); + end Are_Bit_Maps_In_Range; + ------------------ -- Set_Bit_Maps -- ------------------ @@ -4599,6 +4620,8 @@ package body SC_Obligations is Ctx : GNAT.SHA1.Context; LF : constant String := (1 => ASCII.LF); begin + pragma Assert (Are_Bit_Maps_In_Range (Bit_Maps, Info)); + Info.Bit_Maps := Bit_Maps; -- Compute the fingerprint for these bit maps From 4d6a9d5d4bd5505b272126346475e05fb1dd6fc6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 12 Feb 2024 14:57:03 +0000 Subject: [PATCH 0707/1483] sc_obligations.adb: minor reformatting --- tools/gnatcov/sc_obligations.adb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 28f3be44d..f8726e9da 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -4617,8 +4617,9 @@ package body SC_Obligations is use GNAT.SHA1; Info : CU_Info renames CU_Vector.Reference (CU); - Ctx : GNAT.SHA1.Context; - LF : constant String := (1 => ASCII.LF); + Ctx : GNAT.SHA1.Context; + LF : constant String := (1 => ASCII.LF); + begin pragma Assert (Are_Bit_Maps_In_Range (Bit_Maps, Info)); From 1a4a491b392f0f51c8bd09fd8f0d6d053f359a89 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 12 Feb 2024 15:53:33 +0000 Subject: [PATCH 0708/1483] Instrument: fix consolidation support for stubbed subunits In the case of stubbed subunits, the SCOs fingerprint can be identical for each "unit" (CU_Info tense) between instrumentations of the original sources and stubbed projects, but the bit maps will be slightly different in a way that would not hurt consolidation; as a consequence, before this commit, bit maps fingerprints will differ and so gnatcov will refuse the consolidation. An example to clarify: package body Pkg is procedure Proc_A is separate; procedure Proc_B is separate; end Pkg; -- Real implementations for Proc_A and Proc_B: separate (Pkg) procedure Proc_A is begin Stmt_1; Stmt_2; end Proc_A; separate (Pkg) procedure Proc_B is begin Stmt_3; Stmt_4; end Proc_B; The instrumentation of original sources will yield the following low-level SCOs, high-level SCOs and bit maps: LL SCOs: For pkg-proc_a.adb: SCO for Stmt_1 SCO for Stmt_2 For pkg-proc_b.adb: SCO for Stmt_3 SCO for Stmt_4 HL SCOs: For pkg-proc_a.adb: SCO #1 for Stmt_1 SCO #2 for Stmt_2 For pkg-proc_b.adb: SCO #3 for Stmt_3 SCO #4 for Stmt_4 Bit maps (for statements): For pkg-proc_a.adb: 1 => SCO #1 2 => SCO #2 For pkg-proc_b.adb: 1 => SCO #3 2 => SCO #4 However for a build in which Proc_A is stubbed (and thus ignored with --ignore-source-files), we will get instead: LL SCOs: For pkg-proc_b.adb: SCO for Stmt_3 SCO for Stmt_4 HL SCOs: For pkg-proc_b.adb: SCO #1 for Stmt_3 SCO #2 for Stmt_4 Bit maps (for statements): For pkg-proc_b.adb: 1 => SCO #1 2 => SCO #2 The SCOs fingerprint is computed from low-level SCOs: stubbing unit X does not affect the fingerprint of SCOs for unit Y, so we are good. However, currently bit maps fingerprint is computed using high-level SCOs: stubbing unit X will change the numbering of these SCOs, and will thus affect the bit map, and thus its fingerprint: gnatcov will refuse to consolidate source traces created from stubbed builds when it has loaded SIDs created on original sources because of this bit maps fingerprint mismatch. This commit fixs the way we compute fingerprints for instrumentation bit maps so that the fingerprint is identical for Pkg regardless of whether/how the Proc_A/Proc_B subunits are stubbed: instead of using "absolute" SCO ids, we now use SCO ids that are relative to the corresponding unit (i.e. a SCO "offset" from the first SCO of the current unit). Offsets for unit Y do not vary depending on the stubbing of X, and they still help reflecting the structure of bit maps: the fingerprint still plays its safeguard role. --- .../227-subunit-stub/src/lib-src/lib-add.adb | 11 ++ .../227-subunit-stub/src/lib-src/lib-exp.adb | 11 ++ .../227-subunit-stub/src/lib-src/lib-mult.adb | 11 ++ .../227-subunit-stub/src/lib-src/lib.adb | 5 + .../227-subunit-stub/src/lib-src/lib.ads | 5 + .../instr-cov/227-subunit-stub/src/lib.gpr | 4 + .../227-subunit-stub/src/stub_add/lib-add.adb | 18 +++ .../src/stub_mult/lib-mult.adb | 18 +++ .../227-subunit-stub/src/test_exp.gpr | 9 ++ .../src/test_exp/test_exp.adb | 8 ++ .../227-subunit-stub/src/test_mult.gpr | 8 ++ .../src/test_mult/test_mult.adb | 8 ++ .../tests/instr-cov/227-subunit-stub/test.opt | 1 + .../tests/instr-cov/227-subunit-stub/test.py | 118 ++++++++++++++++++ tools/gnatcov/sc_obligations.adb | 38 +++++- 15 files changed, 270 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-add.adb create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-exp.adb create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-mult.adb create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.adb create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.ads create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/src/lib.gpr create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/src/stub_add/lib-add.adb create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/src/stub_mult/lib-mult.adb create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/src/test_exp.gpr create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/src/test_exp/test_exp.adb create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/src/test_mult.gpr create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/src/test_mult/test_mult.adb create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/test.opt create mode 100644 testsuite/tests/instr-cov/227-subunit-stub/test.py diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-add.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-add.adb new file mode 100644 index 000000000..58cffe8aa --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-add.adb @@ -0,0 +1,11 @@ +separate (Lib) +function Add (Left, Right : Positive) return Positive is + Result : Positive := Left; + Remainder : Natural := Right; +begin + while Remainder /= 0 loop + Result := Result + 1; + Remainder := Remainder - 1; + end loop; + return Result; +end Add; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-exp.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-exp.adb new file mode 100644 index 000000000..64d996f58 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-exp.adb @@ -0,0 +1,11 @@ +separate (Lib) +function Exp (Left, Right : Positive) return Positive is +begin + if Right = 1 then + return Left; + elsif Right mod 2 = 0 then + return Exp (Mult (Left, Left), Right / 2); + else + return Mult (Left, Exp (Mult (Left, Left), Right / 2)); + end if; +end Exp; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-mult.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-mult.adb new file mode 100644 index 000000000..817632681 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib-mult.adb @@ -0,0 +1,11 @@ +separate (Lib) +function Mult (Left, Right : Positive) return Positive is +begin + if Right = 1 then + return Left; + elsif Right mod 2 = 0 then + return 2 * Mult (Left, Right / 2); + else + return Add (2 * Mult (Left, Right / 2), Left); + end if; +end Mult; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.adb new file mode 100644 index 000000000..77acdf24f --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.adb @@ -0,0 +1,5 @@ +package body Lib is + function Add (Left, Right : Positive) return Positive is separate; + function Mult (Left, Right : Positive) return Positive is separate; + function Exp (Left, Right : Positive) return Positive is separate; +end Lib; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.ads b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.ads new file mode 100644 index 000000000..52ef162c8 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/lib-src/lib.ads @@ -0,0 +1,5 @@ +package Lib is + function Add (Left, Right : Positive) return Positive; + function Mult (Left, Right : Positive) return Positive; + function Exp (Left, Right : Positive) return Positive; +end Lib; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/lib.gpr b/testsuite/tests/instr-cov/227-subunit-stub/src/lib.gpr new file mode 100644 index 000000000..79c80bcb8 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/lib.gpr @@ -0,0 +1,4 @@ +project Lib is + for Source_Dirs use ("../src/lib-src"); + for Object_Dir use "obj/lib"; +end Lib; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/stub_add/lib-add.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/stub_add/lib-add.adb new file mode 100644 index 000000000..730920dce --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/stub_add/lib-add.adb @@ -0,0 +1,18 @@ +separate (Lib) +function Add (Left, Right : Positive) return Positive is +begin + case Left is + when 1 => + case Right is + when 1 => + return 2; + when others => + null; + end case; + when others => + null; + end case; + + raise Program_Error; + return 1; +end Add; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/stub_mult/lib-mult.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/stub_mult/lib-mult.adb new file mode 100644 index 000000000..1bbbe3fd4 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/stub_mult/lib-mult.adb @@ -0,0 +1,18 @@ +separate (Lib) +function Mult (Left, Right : Positive) return Positive is +begin + case Left is + when 1 => + case Right is + when 1 => + return 1; + when others => + null; + end case; + when others => + null; + end case; + + raise Program_Error; + return 1; +end Mult; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/test_exp.gpr b/testsuite/tests/instr-cov/227-subunit-stub/src/test_exp.gpr new file mode 100644 index 000000000..d74326e62 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/test_exp.gpr @@ -0,0 +1,9 @@ +project Test_Exp extends "lib" is + for Source_Dirs use + ("../src/stub_add", + "../src/stub_mult", + "../src/test_exp"); + for Object_Dir use "obj/test_exp"; + for Exec_Dir use "bin"; + for Main use ("test_exp.adb"); +end Test_Exp; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/test_exp/test_exp.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/test_exp/test_exp.adb new file mode 100644 index 000000000..3698bbd00 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/test_exp/test_exp.adb @@ -0,0 +1,8 @@ +with Lib; + +procedure Test_Exp is +begin + if Lib.Exp (1, 1) /= 1 then + raise Program_Error; + end if; +end Test_Exp; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/test_mult.gpr b/testsuite/tests/instr-cov/227-subunit-stub/src/test_mult.gpr new file mode 100644 index 000000000..3167f27fd --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/test_mult.gpr @@ -0,0 +1,8 @@ +project Test_Mult extends "lib" is + for Source_Dirs use + ("../src/stub_add", + "../src/test_mult"); + for Object_Dir use "obj/test_mult"; + for Exec_Dir use "bin"; + for Main use ("test_mult.adb"); +end Test_Mult; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/src/test_mult/test_mult.adb b/testsuite/tests/instr-cov/227-subunit-stub/src/test_mult/test_mult.adb new file mode 100644 index 000000000..e11a2b242 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/src/test_mult/test_mult.adb @@ -0,0 +1,8 @@ +with Lib; + +procedure Test_Mult is +begin + if Lib.Mult (1, 1) /= 1 then + raise Program_Error; + end if; +end Test_Mult; diff --git a/testsuite/tests/instr-cov/227-subunit-stub/test.opt b/testsuite/tests/instr-cov/227-subunit-stub/test.opt new file mode 100644 index 000000000..2d1c5e0d5 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/test.opt @@ -0,0 +1 @@ +bin-traces XFAIL eng/das/cov/gnatcoverage#227: never worked with bin-traces diff --git a/testsuite/tests/instr-cov/227-subunit-stub/test.py b/testsuite/tests/instr-cov/227-subunit-stub/test.py new file mode 100644 index 000000000..bd34593d6 --- /dev/null +++ b/testsuite/tests/instr-cov/227-subunit-stub/test.py @@ -0,0 +1,118 @@ +""" +Check that computing coverage on an Ada codebase that contains subunits works +correctly when the subunits are stubbed in tests. +""" + +import dataclasses +import os.path +from e3.fs import cp, mkdir + +from SCOV.instr import xcov_instrument +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprbuild, xcov + + +# Note: to avoid "same base name for files" warnings, create local copies of +# project files, but not of sources themselves: project files reference the +# original source directories. + + +@dataclasses.dataclass +class Test: + name: str + """ + Name of this test. + + This is both the name of the project file and the main (executable). + """ + + stubbed_files: list[str] + """ + List of source files from the "lib" project that are stubbed for this + testcase. + """ + + +# Produce one source trace for each testcase. Each testcase use a specific set +# of stubs: exclude them from instrumentation to avoid consolidation warnings +# later on. +cov_argv = [] +all_traces = [] +for test in [ + Test("test_mult", ["lib-add.adb"]), + Test("test_exp", ["lib-add.adb", "lib-mult.adb"]), +]: + thistest.log(f"== {test.name} ==") + tmp = Wdir(f"tmp_{test.name}") + cp("../src/*.gpr", ".") + + cov_argv = build_and_run( + gprsw=GPRswitches(root_project=os.path.abspath(f"{test.name}.gpr")), + covlevel="stmt+decision", + mains=[test.name], + gpr_obj_dir=f"obj/{test.name}", + gpr_exe_dir="bin", + extra_instr_args=[ + f"--ignore-source-files={f}" for f in test.stubbed_files + ], + extra_coverage_args=[], + ) + all_traces.append(os.path.abspath(cov_argv.pop())) + + tmp.to_homedir() + + +# Instrument/compile the "vanilla" (stub-free) library to get the "reference" +# set of SCOs. +thistest.log(f"== cons ==") +tmp = Wdir("tmp_cons") +cp("../src/*.gpr", ".") +lib_gpr = os.path.abspath("lib.gpr") +mkdir("obj/lib") + +if thistest.options.trace_mode == "src": + xcov_instrument( + gprsw=GPRswitches(root_project=lib_gpr), + covlevel="stmt+decision", + out="instrument.log", + ) + thistest.fail_if_not_equal( + '[consolidation] "gnatcov instrument" output', + "", + contents_of("instrument.log"), + ) +else: + gprbuild(lib_gpr) + +# Produce a coverage report using test traces and these SCOs +mkdir("xcov") +xcov( + [ + "coverage", + "-P", + lib_gpr, + "--level=stmt+decision", + "--annotate=xcov", + "--output-dir=xcov", + *all_traces, + ], + out="coverage.log", +) +thistest.fail_if_not_equal( + '[consolidation] "gnatcov coverage" output', + "", + contents_of("coverage.log"), +) +check_xcov_reports( + "xcov", + { + "lib-add.adb.xcov": {"-": {3, 4, 6, 7, 8, 10}}, + "lib-mult.adb.xcov": {"+": {5}, "!": {4}, "-": {6, 7, 9}}, + "lib-exp.adb.xcov": {"+": {5}, "!": {4}, "-": {6, 7, 9}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index f8726e9da..5a03763d3 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -4620,6 +4620,36 @@ package body SC_Obligations is Ctx : GNAT.SHA1.Context; LF : constant String := (1 => ASCII.LF); + procedure Update (SCO : SCO_Id); + -- Helper for fingerprint computation: update Ctx to include a reference + -- to the given SCO. That infomation is made relative to CU's first SCO, + -- so that during consolidation, bit maps are treated as equivalent + -- modulo SCO relocation. For instance, the following units/maps should + -- be equivalent: + -- + -- CU #1 + -- First_SCO => 10 + -- Last_SCO => 12 + -- Statement_Bits => (1 => 10, 2 => 11, 3 => 12) + -- + -- CU #2 + -- First_SCO => 20 + -- Last_SCO => 22 + -- Statement_Bits => (1 => 20, 2 => 21, 3 => 22) + -- + -- Because when we attempt to consolidate CUs #1 and #2, the bit maps + -- will be equal after the relocation of SCOs #20..#22 to #10..#12. + + ------------ + -- Update -- + ------------ + + procedure Update (SCO : SCO_Id) is + Relative_SCO : constant SCO_Id := SCO - Info.First_SCO; + begin + Update (Ctx, Relative_SCO'Image); + end Update; + begin pragma Assert (Are_Bit_Maps_In_Range (Bit_Maps, Info)); @@ -4629,19 +4659,21 @@ package body SC_Obligations is Update (Ctx, "stmt:"); for Id of Bit_Maps.Statement_Bits.all loop - Update (Ctx, Id'Image); + Update (Id); end loop; Update (Ctx, LF); Update (Ctx, "dc:"); for D of Bit_Maps.Decision_Bits.all loop - Update (Ctx, D.D_SCO'Image & ":" & D.Outcome'Image); + Update (D.D_SCO); + Update (Ctx, ":" & D.Outcome'Image); end loop; Update (Ctx, LF); Update (Ctx, "mcdc:"); for M of Bit_Maps.MCDC_Bits.all loop - Update (Ctx, M.D_SCO'Image & ":" & M.Path_Index'Image); + Update (M.D_SCO); + Update (Ctx, ":" & M.Path_Index'Image); end loop; Update (Ctx, LF); From f82d12a6c5155cf3ccad3520e7eace7302b0fef4 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 8 Feb 2024 19:06:17 +0000 Subject: [PATCH 0709/1483] instrument-ada_unit.adb: minor reformatting --- tools/gnatcov/instrument-ada_unit.adb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 5d1fb8638..c46418176 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6371,9 +6371,9 @@ package body Instrument.Ada_Unit is return not (for all DN of N.P_Defining_Names => not DN.P_Is_Ghost_Code); exception when E : Property_Error => - Report (N, - Msg => "Could not determine if decl is ghost: " - & Ada.Exceptions.Exception_Information (E), + Report (Node => N, + Msg => "Could not determine if decl is ghost: " + & Ada.Exceptions.Exception_Information (E), Kind => Low_Warning); return False; @@ -6384,9 +6384,9 @@ package body Instrument.Ada_Unit is return N.P_Is_Ghost_Code; exception when E : Property_Error => - Report (N, - Msg => "Could not determine if stmt is ghost: " - & Ada.Exceptions.Exception_Information (E), + Report (Node => N, + Msg => "Could not determine if stmt is ghost: " + & Ada.Exceptions.Exception_Information (E), Kind => Low_Warning); return False; From 0180483e4c90f788fef2e9bac5a454ddaa08487f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 8 Feb 2024 20:04:41 +0000 Subject: [PATCH 0710/1483] Instrument Ada: fix a crash when package spec is missing --- .../instr-cov/218-missing-pkg-spec/main.adb | 6 ++ .../instr-cov/218-missing-pkg-spec/pkg.adb | 12 +++ .../instr-cov/218-missing-pkg-spec/test.py | 59 ++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 79 +++++++++++++------ 4 files changed, 134 insertions(+), 22 deletions(-) create mode 100644 testsuite/tests/instr-cov/218-missing-pkg-spec/main.adb create mode 100644 testsuite/tests/instr-cov/218-missing-pkg-spec/pkg.adb create mode 100644 testsuite/tests/instr-cov/218-missing-pkg-spec/test.py diff --git a/testsuite/tests/instr-cov/218-missing-pkg-spec/main.adb b/testsuite/tests/instr-cov/218-missing-pkg-spec/main.adb new file mode 100644 index 000000000..1a0fbd373 --- /dev/null +++ b/testsuite/tests/instr-cov/218-missing-pkg-spec/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Process; +end Main; diff --git a/testsuite/tests/instr-cov/218-missing-pkg-spec/pkg.adb b/testsuite/tests/instr-cov/218-missing-pkg-spec/pkg.adb new file mode 100644 index 000000000..b8a6ee05e --- /dev/null +++ b/testsuite/tests/instr-cov/218-missing-pkg-spec/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + ------------- + -- Process -- + ------------- + + procedure Process is + begin + null; + end Process; + +end Pkg; diff --git a/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py b/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py new file mode 100644 index 000000000..a65cfd852 --- /dev/null +++ b/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py @@ -0,0 +1,59 @@ +""" +Check that "gnatcov instrument" does not crash when instrumenting an invalid +project setup that lacks the package spec corresponding to a package body. +""" + +import os.path + +from e3.fs import mkdir + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, lines_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +# Avoid "creating output path" messages from gnatcov +mkdir("obj") + +filename = "instrument.txt" +p = xcov_instrument( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + out=filename, + register_failure=False, +) + +thistest.fail_if(p.status != 0, "'gnatcov instrument' unexpectedly succeeded") + +# There are two warnings that we consider mandatory. Beyound that, we tolerate +# other warnings only (to keep this test robust, we do not want to track the +# exact list of warnings, that may vary as gnatcov evolves). +expected_warnings = { + "warning: While instrumenting main.adb...", + "warning: Cannot find required source file: pkg.ads", +} +actual_warnings = set() +others = [] +for line in lines_of(filename): + if line.startswith("warning: ") or line.startswith("*** warning:"): + actual_warnings.add(line) + else: + others.append(line) + +missing_warnings = expected_warnings - actual_warnings +thistest.fail_if( + missing_warnings, + 'expected "gnatcov instrument" warnings are missing:\n' + + "\n".join(sorted(missing_warnings)), +) + +thistest.fail_if_not_equal( + '"gnatcov instrument" has non-warnings in its output', + "", + "\n".join(others), +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index c46418176..b2343c76f 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -325,6 +325,12 @@ package body Instrument.Ada_Unit is -- not ghost. This is what we need here, as we need to instrument the -- declaration if if at least one defined name is not ghost. + function Safe_Previous_Part_For_Decl + (N : Basic_Decl'Class) return Basic_Decl; + -- Wrapper around P_Previous_Part_For_Decl to protect ourselves against + -- property errors. If the property fails for some reason, return the null + -- node. + function Op_Symbol_To_Name (Op : Libadalang.Analysis.Name) return Wide_Wide_String; -- Given an operator symbol (in its source representation @@ -2537,9 +2543,19 @@ package body Instrument.Ada_Unit is -- it should be based on the previous declaration of the original -- EF to avoid potential visibility issues introduced by -- use-clauses in between the declaration and the completion. + -- + -- Note that Needs_Decl can be true True only when + -- Augmented_Expr_Function_Needs_Decl returns True, and that can + -- happen only when it managed to get the previous part of + -- Common_Node.N, so the call to P_Previous_Part_For_Decl below is + -- guaranteed to return a non-null node. + + Previous_Decl : constant Basic_Decl := + Common_Nodes.N.P_Previous_Part_For_Decl; + pragma Assert (not Previous_Decl.Is_Null); Previous_Spec : constant Subp_Spec := - Common_Nodes.N.P_Previous_Part_For_Decl.As_Subp_Decl.F_Subp_Spec; + Previous_Decl.As_Subp_Decl.F_Subp_Spec; -- Clone the spec of the original declaration @@ -2701,21 +2717,10 @@ package body Instrument.Ada_Unit is -- Check that N has a previous declaration - begin - Previous_Decl := N.P_Previous_Part_For_Decl; - - if Previous_Decl.Is_Null or else Previous_Decl = No_Ada_Node then - return False; - end if; - exception - when Exc : Property_Error => - Report (Node => N, - Msg => "Could not determine if expression function" - & " declaration has a previous part or not: " - & Ada.Exceptions.Exception_Information (Exc), - Kind => Warning); - return False; - end; + Previous_Decl := Safe_Previous_Part_For_Decl (N); + if Previous_Decl.Is_Null then + return False; + end if; -- Check that N is in a public or private part of a package decl -- or that N and its previous part are declared in the same declarative @@ -4228,9 +4233,11 @@ package body Instrument.Ada_Unit is declare Previous_Decl : constant Basic_Decl := N.P_Previous_Part_For_Decl; - -- This property cannot fail because to reach this point - -- we will already have succesfully queried the previous - -- part of N in Augmented_Expr_Function_Needs_Decl. + pragma Assert (not Previous_Decl.Is_Null); + -- P_Previous_Part_For_Decl cannot fail because to reach + -- this point we will already have succesfully queried + -- the previous part of N in + -- Augmented_Expr_Function_Needs_Decl. begin Insert_Before (Handle (Previous_Decl), Augmented_Expr_Function_Decl); @@ -4313,7 +4320,7 @@ package body Instrument.Ada_Unit is N_Spec : constant Subp_Spec := N.P_Subp_Spec_Or_Null.As_Subp_Spec; - Prev_Part : constant Basic_Decl := N.P_Previous_Part_For_Decl; + Prev_Part : constant Basic_Decl := Safe_Previous_Part_For_Decl (N); -- If this is a null procedure or an expression function, it may have -- a previous declaration that must be used as scope identifier. @@ -4368,7 +4375,7 @@ package body Instrument.Ada_Unit is then Basic_Decl (CUN_Body.As_Subunit.F_Body) else CUN_Body.As_Library_Item.F_Item); CU_Prev_Decl : constant Basic_Decl := - CU_Decl.P_Previous_Part_For_Decl; + Safe_Previous_Part_For_Decl (CU_Decl); begin -- For a library unit, scan context clause. If this is a -- body, also obtain WITH clauses from the spec. Also @@ -5298,12 +5305,22 @@ package body Instrument.Ada_Unit is UIC.MCDC_State_Inserter; Local_Inserter : aliased Default_MCDC_State_Inserter := (Local_Decls => Handle (N.F_Decls.F_Decls)); + + -- Fetch the package decl corresponding to N. If that fails, + -- Safe_Previous_Part_For_Decl emits a warning: use the package body + -- instead as an approximation. + + Decl : Basic_Decl := Safe_Previous_Part_For_Decl (N); begin + if Decl.Is_Null then + Decl := N.As_Basic_Decl; + end if; + UIC.Ghost_Code := Safe_Is_Ghost (N); Enter_Scope (UIC => UIC, Sloc => Sloc (N), - Decl => N.P_Previous_Part_For_Decl); + Decl => Decl); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; Traverse_Declarations_Or_Statements @@ -6392,6 +6409,24 @@ package body Instrument.Ada_Unit is end Safe_Is_Ghost; + --------------------------------- + -- Safe_Previous_Part_For_Decl -- + --------------------------------- + + function Safe_Previous_Part_For_Decl + (N : Basic_Decl'Class) return Basic_Decl + is + begin + return N.P_Previous_Part_For_Decl; + exception + when E : Property_Error => + Report (Node => N, + Msg => "Could not resolve the previous declaration: " + & Ada.Exceptions.Exception_Information (E), + Kind => Warning); + return No_Basic_Decl; + end Safe_Previous_Part_For_Decl; + ------------- -- Matches -- ------------- From afca04b927218097e99e850c256cc212658a735b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 21 Feb 2024 09:08:45 +0000 Subject: [PATCH 0711/1483] RB13-019-win-paths: fix code coverage expectations Now that check_xcov_reports looks at all xcov files in a given directory, the coverage expectations have to consider all source files. --- testsuite/tests/RB13-019-win-paths/test.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/RB13-019-win-paths/test.py b/testsuite/tests/RB13-019-win-paths/test.py index 6a01fc689..025b879c2 100644 --- a/testsuite/tests/RB13-019-win-paths/test.py +++ b/testsuite/tests/RB13-019-win-paths/test.py @@ -79,6 +79,10 @@ ], ) -check_xcov_reports("coverage", {"wibble.c.xcov": {"+": {8, 12}, "!": {6}}}) +check_xcov_reports("coverage", { + "wibble.c.xcov": {"+": {8, 12}, "!": {6}}, + "main.adb.xcov": {"+": {7}}, + "driver.c.xcov": {"+": {13, 24, 25, 27}, "!": {11}, "-": {17}}, +}) thistest.result() From cb09bcc7ddec6399f003ec4e8b1db851228be16c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 21 Feb 2024 14:49:40 +0000 Subject: [PATCH 0712/1483] switches.ads: remove some global variables This is just a refactoring: no behavior change intended. --- tools/gnatcov/annotations-dynamic_html.adb | 3 +-- tools/gnatcov/rundrv-handlers.adb | 8 ++++++-- tools/gnatcov/switches.adb | 5 +++-- tools/gnatcov/switches.ads | 9 --------- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index d492f02cf..5e1f9c3f0 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -34,7 +34,6 @@ with Interfaces; with Outputs; with Project; with Support_Files; use Support_Files; -with Switches; with Traces_Disa; with Traces_Files; use Traces_Files; @@ -429,7 +428,7 @@ package body Annotations.Dynamic_Html is declare P_Name : constant String := - (if Switches.Root_Project /= null + (if Is_Project_Loaded then Project_Name (Info.Full_Name.all) else ""); -- Note that P_Name can be "" here either because we don't have a diff --git a/tools/gnatcov/rundrv-handlers.adb b/tools/gnatcov/rundrv-handlers.adb index 61edcf0ed..499c5c559 100644 --- a/tools/gnatcov/rundrv-handlers.adb +++ b/tools/gnatcov/rundrv-handlers.adb @@ -22,9 +22,12 @@ with Ada.Directories; use Ada.Directories; with Ada.Strings; use Ada.Strings; with Ada.Strings.Fixed; use Ada.Strings.Fixed; +with GNATCOLL.VFS; use GNATCOLL.VFS; + with Arch; with Coverage; use Coverage; with Paths; use Paths; +with Project; with Support_Files; with Switches; use Switches; @@ -245,8 +248,9 @@ package body Rundrv.Handlers is Append_Arg (Cmd, "--board=" & Context.Target_Board.all); end if; - if Root_Project /= null then - Append_Arg (Cmd, "-P", Root_Project.all); + if Project.Is_Project_Loaded then + Append_Arg + (Cmd, "-P", +Project.Project.Root_Project.Project_Path.Full_Name); declare use Key_Element_Maps; diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index e058c6f1d..8c6602e5c 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -425,6 +425,9 @@ package body Switches is end Check_Allowed_Option; Project_Args : Parsed_Arguments; + Root_Project : String_Access; + Runtime : String_Access; + CGPR_File : String_Access; -- Start of processing for Load_Project_Arguments @@ -622,8 +625,6 @@ package body Switches is -- internal state accordingly. Load_Target_Option (Default_Target => True); - Copy_Arg (Opt_Runtime, Runtime); - Copy_Arg (Opt_Config, CGPR_File); end Parse_Arguments; ----------- diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 90a7bccb4..e08d8b036 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -221,15 +221,6 @@ package Switches is -- Project related switches that may need to be propagated -- ------------------------------------------------------------- - Root_Project : String_Access := null; - -- Project name as specified to the -P option of the command line - - Runtime : String_Access := null; - -- Name of the runtime (--RTS or defined in the project file) - - CGPR_File : String_Access := null; - -- Name of the configuration project file - package Key_Element_Maps is new Ada.Containers.Indefinite_Ordered_Maps (Key_Type => String, From f67756f3ee2f668772b2f539fba34ac81b7c2c39 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 20 Feb 2024 16:02:13 +0000 Subject: [PATCH 0713/1483] Testsuite: remove altrun/isys_nexus_5634 These are support scripts for a hardware probe that has not been supported for a long time. The fact that they contain Python2 scripts show that they are dead code in practice: remove them to avoid maintenance costs. --- testsuite/altrun/isys_nexus_5634/README.md | 25 - testsuite/altrun/isys_nexus_5634/altrun.gpr | 5 - testsuite/altrun/isys_nexus_5634/crun.adb | 262 - testsuite/altrun/isys_nexus_5634/get_trace.py | 134 - testsuite/altrun/isys_nexus_5634/justrun.xjrf | 4244 ----------------- .../altrun/isys_nexus_5634/post_testcase.py | 22 - .../altrun/isys_nexus_5634/post_testsuite.py | 19 - .../altrun/isys_nexus_5634/pre_testsuite.py | 76 - testsuite/altrun/isys_nexus_5634/setup.py | 13 - testsuite/altrun/isys_nexus_5634/ws/j.xjrf | 3950 --------------- 10 files changed, 8750 deletions(-) delete mode 100644 testsuite/altrun/isys_nexus_5634/README.md delete mode 100644 testsuite/altrun/isys_nexus_5634/altrun.gpr delete mode 100644 testsuite/altrun/isys_nexus_5634/crun.adb delete mode 100644 testsuite/altrun/isys_nexus_5634/get_trace.py delete mode 100755 testsuite/altrun/isys_nexus_5634/justrun.xjrf delete mode 100755 testsuite/altrun/isys_nexus_5634/post_testcase.py delete mode 100755 testsuite/altrun/isys_nexus_5634/post_testsuite.py delete mode 100755 testsuite/altrun/isys_nexus_5634/pre_testsuite.py delete mode 100644 testsuite/altrun/isys_nexus_5634/setup.py delete mode 100755 testsuite/altrun/isys_nexus_5634/ws/j.xjrf diff --git a/testsuite/altrun/isys_nexus_5634/README.md b/testsuite/altrun/isys_nexus_5634/README.md deleted file mode 100644 index 0bf2e657d..000000000 --- a/testsuite/altrun/isys_nexus_5634/README.md +++ /dev/null @@ -1,25 +0,0 @@ -This directory contains programs and data for running the gnatcov testsuite -tests in a particular way when using the iSystem Blue Box attached to a sytem -running the MPC5634M SOC. - -`./testsuite.py` can be passed the argument: - -```shell ---altrun=altrun/isys_nexus_5634 -``` - -to cause: - -* `setup.py` to be called, which builds `crun.exe` from `crun.adb`, which will - be run in place of `gnatcov run` (with the same args that would normally be - passed to `gnatcov run`). - -* `pre_testsuite.py` to be called before the test sequence starts. - -* `post_testsuite.py` to be called one all the tests are finished. - -Crun creates a winIDEA workspace subdirectory (`isyswspace`) under the test -directory and populates it with the `justrun*` workspace and trace doc files, -and then calls `python get_trace.py` to run the target excutable and create a -nexus trace file in `isyswpace/nexus_trace.bin`. Then `crun` runs `gnatcov -convert` to convert the nexus trace into a gnatcov trace. diff --git a/testsuite/altrun/isys_nexus_5634/altrun.gpr b/testsuite/altrun/isys_nexus_5634/altrun.gpr deleted file mode 100644 index 96a5c3f3e..000000000 --- a/testsuite/altrun/isys_nexus_5634/altrun.gpr +++ /dev/null @@ -1,5 +0,0 @@ -project ALTRUN is - for Source_Dirs use ("."); - for Exec_Dir use "."; - for Object_Dir use "obj"; -end ALTRUN; diff --git a/testsuite/altrun/isys_nexus_5634/crun.adb b/testsuite/altrun/isys_nexus_5634/crun.adb deleted file mode 100644 index d8d4cb22c..000000000 --- a/testsuite/altrun/isys_nexus_5634/crun.adb +++ /dev/null @@ -1,262 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2012-2015, 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 Text_IO; use Text_IO; -with Ada.Command_Line; use Ada.Command_Line; -with GNAT.OS_Lib; use GNAT.OS_Lib; -with GNAT.Directory_Operations; use GNAT.Directory_Operations; -with Ada.Directories; - -procedure crun is - - Executable_Path : String_Access; - - Success : Boolean; - - CWD : String := Get_Current_Dir; - - Python_P : String_Access; - Python_Args : Argument_List (1 .. 2); - - Gnatcov_P : String_Access; - Gnatcov_Args : Argument_List (1 .. 11); - Next_Arg_Idx : Natural; - - Crun_Dir : Dir_Type; - Isys_Pfile : String (1 .. 15); - Lasti : Natural; - Crun_Dir_Name : String := Normalize_Pathname ("..", Command_Name); - - Wspace_Dir_Name : String := Normalize_Pathname ("isyswspace"); - - Itmp_Dir_Name : String := Normalize_Pathname ("isystemps", Crun_Dir_Name); - Temp_Dir : Dir_Type; - Temp_Name : String (1 .. 80); - - procedure Empty_Temps_Dir; - procedure Put_Error (Error_Str : String); - - --------------------- - -- Empty_Temps_Dir -- - --------------------- - - procedure Empty_Temps_Dir is - begin - Open (Temp_Dir, Itmp_Dir_Name); - loop - Read (Temp_Dir, Temp_Name, Lasti); - exit when Lasti = 0; - Delete_File - (Normalize_Pathname (Temp_Name (1 .. Lasti), Itmp_Dir_Name), Success); - end loop; - Close (Temp_Dir); - end Empty_Temps_Dir; - - --------------- - -- Put_Error -- - --------------- - - procedure Put_Error (Error_Str : String) is - Prefix : constant String := Command_Name & " error:"; - begin - Put_Line (Standard_Error, Prefix & Error_Str); - end Put_Error; - - type Poss_Arg is record - Arg_Name : String_Access; - Required : Boolean; - Seen : Boolean; - end record; - type Poss_Arg_Array is array (Natural range <>) of Poss_Arg; - Poss_Args : Poss_Arg_Array := ( - (new String'("--target"), True, False), - (new String'("--output"), False, False), - (new String'("--tag"), False, False), - (new String'("--level"), False, False), - (new String'("--scos"), False, False)); - Target_Exec_Seen : Boolean := False; - - Argslog_File : File_Type; - Argslog_Name : String := "runargs.log"; -begin - Create (File => Argslog_File, Name => Argslog_Name); - Put_Line (Argslog_File, "INCOMING......"); - for J in 1 .. Argument_Count loop - Put_Line (Argslog_File, Argument (J)); - end loop; - Close (Argslog_File); - - Executable_Path := new String'(Normalize_Pathname (Argument (2))); - - declare - begin - Remove_Dir (Wspace_Dir_Name, Recursive => True); - exception - when Directory_Error => - null; - end; - declare - begin - Make_Dir (Wspace_Dir_Name); - exception - when Directory_Error => - Put_Error ("Directory_Error creating workspace."); - OS_Exit (1); - end; - declare - begin - Make_Dir (Itmp_Dir_Name); - exception - when Directory_Error => - null; -- Okay if temp dir already exists - end; - - Open (Crun_Dir, Crun_Dir_Name); - loop - Read (Crun_Dir, Isys_Pfile, Lasti); - exit when Lasti = 0; - if Lasti >= 8 and then Isys_Pfile (1 .. 8) = "justrun." then - - Copy_File ( - Normalize_Pathname (Isys_Pfile (1 .. Lasti), Crun_Dir_Name), - Normalize_Pathname (Isys_Pfile (1 .. Lasti), Wspace_Dir_Name), - Success); - end if; - end loop; - CLose (Crun_Dir); - - Python_P := Locate_Exec_On_Path ("python"); - if Python_P = null then - Put_Error ("python not found."); - OS_Exit (1); - end if; - Python_Args (1) := - new String'(Normalize_Pathname ("get_trace.py", Crun_Dir_Name)); - - Python_Args (2) := new String'(Executable_Path.all); - - Open (Argslog_File, Append_File, Argslog_Name); - New_Line (Argslog_File); - Put_Line (Argslog_File, "PYTHON ARGS...."); - Put_Line (Argslog_File, Python_Args (1).all); - Put_Line (Argslog_File, Python_Args (2).all); - Close (Argslog_File); - - - Setenv ("ISYSTEM_TEMP", Itmp_Dir_Name); - Spawn (Python_P.all, Python_Args, Success); - if not Success then - Put_Error ("winIDEA python script failed."); - Empty_Temps_Dir; - OS_Exit (1); - end if; - - Gnatcov_P := Locate_Exec_On_Path ("gnatcov"); - if Gnatcov_P = null then - Put_Error ("gnatcov not found."); - OS_Exit (1); - end if; - Gnatcov_Args (1) := new String'("convert"); - Next_Arg_Idx := 2; - for J in 1 .. Argument_Count loop - if Argument (J) (1) /= '-' then - if Target_Exec_Seen then - Put_Error ("Multiple exec args seen."); - OS_Exit (1); - else - Gnatcov_Args (Next_Arg_Idx) := - new String'("--exec=" & Argument (J)); - Next_Arg_Idx := Next_Arg_Idx + 1; - - Gnatcov_Args (Next_Arg_Idx) := - new String'("--output=" & - Ada.Directories.Base_name (Argument (J)) & - ".trace"); - Next_Arg_Idx := Next_Arg_Idx + 1; - - Target_Exec_Seen := True; - end if; - elsif Argument (J)'Length > 2 and then Argument (J) (1 .. 2) = "-P" then - Gnatcov_Args (Next_Arg_Idx) := new String'(Argument (J)); - Next_Arg_Idx := Next_Arg_Idx + 1; - elsif Argument (J)'Length = 2 and then Argument (J) = "-P" then - Put_Error ("Project switch format ('-P', '')" & - " is not supported. Only ('-P') works."); - OS_Exit (1); - else - for K in Poss_Args'Range loop - if Argument (J)'Length > Poss_Args (K).Arg_Name'Length + 1 - and then Argument (J) (1 .. Poss_Args (K).Arg_Name'Length) - = Poss_Args (K).Arg_Name.all - then - if Poss_Args (K).Seen then - Put_Line (Standard_Error, - Poss_Args (K).Arg_Name.all & " seen twice"); - OS_Exit (1); - end if; - if Poss_Args (K).Arg_Name'Length = 8 and then - Poss_Args (K).Arg_Name.all = "--target" - then - Gnatcov_Args (Next_Arg_Idx) := new String'(Argument (J)); - Next_Arg_Idx := Next_Arg_Idx + 1; - - Gnatcov_Args (Next_Arg_Idx) := - new String'("--trace-source=iSystem-5634"); - else - Gnatcov_Args (Next_Arg_Idx) := new String'(Argument (J)); - end if; - Next_Arg_Idx := Next_Arg_Idx + 1; - Poss_Args (K).Seen := True; - exit; - elsif K = Poss_Args'Last then - Put_Line (Standard_Error, - "Argument """ & Argument (J) & """ not recognized."); - OS_Exit (1); - end if; - end loop; - end if; - end loop; - for K in Poss_Args'Range loop - if Poss_Args (k).Required and then not Poss_Args (K).Seen then - Put_Error (Poss_Args (K).Arg_Name.all & " missing."); - OS_Exit (1); - end if; - end loop; - Gnatcov_Args (Next_Arg_Idx) := - new String'("--hw-trigger-traces=IAC1,main,IAC2"); - Next_Arg_Idx := Next_Arg_Idx + 1; - Gnatcov_Args (Next_Arg_Idx) := - new String'("--input=" & Wspace_Dir_Name & "\nexus_trace.bin"); - - Open (Argslog_File, Append_File, Argslog_Name); - New_Line (Argslog_File); - Put_Line (Argslog_File, "GNATCOV ARGS...."); - for J in 1 .. Next_Arg_Idx loop - Put_Line (Argslog_File, Gnatcov_Args (J).all); - end loop; - Close (Argslog_File); - - Spawn (Gnatcov_P.all, Gnatcov_Args (1 .. Next_Arg_Idx), Success); - if not Success then - Put_Error ("gnatcov convert failed."); - OS_Exit (1); - end if; - - Empty_Temps_Dir; - -end crun; diff --git a/testsuite/altrun/isys_nexus_5634/get_trace.py b/testsuite/altrun/isys_nexus_5634/get_trace.py deleted file mode 100644 index a7104e584..000000000 --- a/testsuite/altrun/isys_nexus_5634/get_trace.py +++ /dev/null @@ -1,134 +0,0 @@ -import time -import sys -import os -executable = sys.argv [1] - -import isystem.connect as ic - -cmgr = ic.ConnectionMgr() -cmgr.connectMRU() -wspaceControl = ic.CWorkspaceController (cmgr) -wspaceControl.open(os.path.abspath('.\isyswspace\justrun.xjrf')) - -print 'WinIDEA workspace is now open' - -traceDoc = ic.CTraceController (cmgr, 'new_trigger.trd', 'w') -triggerIdx = traceDoc.createTrigger ('new_trigger') -traceDoc.select (triggerIdx) - -# Full list of available option can be found in WinIDEA Help->Display Options... -traceDoc.setTriggerOption (triggerIdx, "UseAdvancedTrigger", "TRUE") -traceDoc.setTriggerOption (triggerIdx, "EnableProfiler", "FALSE") -traceDoc.setTriggerOption (triggerIdx, "EnableCoverage", "FALSE") -#traceDoc.setTriggerOption (triggerIdx, "Trigger.Global.ProfilerOperationMode", "Range") - -traceDoc.setTriggerOption (triggerIdx, "HW.Recorder.Start", "Immediately") -traceDoc.setTriggerOption (triggerIdx, "HW.Recorder.BufferSize", "1 GB") -traceDoc.setTriggerOption (triggerIdx, "HW.Recorder.TriggerPosition", "Begin") -traceDoc.setTriggerOption (triggerIdx, "HW.Recorder.StallCPU ", "FALSE") -traceDoc.setTriggerOption (triggerIdx, "HW.Recorder.BreakOnTrigger", "FALSE") - -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.Enabled", "TRUE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].Enabled", "TRUE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].Anything", "FALSE") - -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].IAC_Enable[0]", "TRUE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].IAC_Enable[1]", "TRUE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].IAC_Combination[0]", "None") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.e200[0].IAC_Address[0]", "main") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.e200[0].IAC_Address[1]", "_exit") - -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].RecordProgram", "TRUE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].RecordData", "FALSE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].RecordOTM", "FALSE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].PeriodicOTM", "FALSE") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].RecordWP", "All") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].ProgramTrace", "BranchMsg") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].PgmStart", "IAC1") -traceDoc.setTriggerOption (triggerIdx, "HW.PPC5xxx.HW.e200[0].PgmEnd", "IAC2") - -loader = ic.CLoaderController (cmgr) -executer = ic.CExecutionController (cmgr) -debug = ic.CDebugFacade(cmgr) -status = debug.getCPUStatus() - -print 'Trying to connect to the probe/board...' - -for try_nb in range(10): - debug = ic.CDebugFacade(cmgr) - status = debug.getCPUStatus() - isConnected = (not status.isMustInit()) - print 'is connected: ' + str(isConnected) - print status.toString() - - if isConnected: - break - - try: - debug.reset() - except: - print 'exception in debug.reset()' - - executer = ic.CExecutionController (cmgr) - try: - executer.reset() - except: - print 'exception in executer.reset()' - try: - executer.stop() - except: - print 'exception in executer.stop()' - - time.sleep (1) - -executer.reset () -executer.stop () -MPCCtrl = ic.CMPC5xxxController (cmgr) -TLB = MPCCtrl.getTLB (0) -TLB.m_dwMAS0 = 0x10030000 -TLB.m_dwMAS1 = 0xC0000400 -TLB.m_dwMAS2 = 0x40000008 -TLB.m_dwMAS3 = 0x4000003F -TLB.m_dwMAS4 = 0x00030413 -TLB.m_dwMAS5 = 0x00000000 -MPCCtrl.setTLB (0, TLB) - -downloadConfig = ic.CDownloadConfiguration () -downloadConfig.setCodeOffset (0).setSymbolsOffset (0). \ - setUsedInFullDownload (True). \ - setDownloadFileFormat (ic.CDownloadConfiguration.ftELF); - -dbg = ic.CDebugFacade(cmgr) -loader.targetDownload (downloadConfig, executable, -' LoadSymbols(Global) LoadZeros(0) LoadDwarfSection(1) ReverseBitFields(0) DumpELFHeaders(0) LoadCode(Virtual) CallStack(Automatic) MergeTypes(0) GCC_ARM_double_Format(Swapped) RemoveOptimizedLines(1) InsertInlinedFunctions(0) IgnoreNonStatementLines(1) ') -isyminfo = dbg.getSymbolInfo (ic.IConnectDebug.fMonitor | - ic.IConnectDebug.gafExpression, '_start') -dbg.gotoAddress (0, isyminfo.getAddress () ) -isyminfo = dbg.getSymbolInfo (ic.IConnectDebug.fMonitor | - ic.IConnectDebug.gafExpression, '_exit') - -traceDoc.start () - -print 'Start execution...' - -executer.runUntilAddress (0, isyminfo.getAddress () ) -if not executer.waitUntilStopped (pollingInterval=5000, timeout=400000): - print '!!! EXECUTION TIMEOUT !!!' - -print '... execution stoped.' - -last_chance = dbg.evaluate(ic.IConnectDebug.fRealTime, '__gnat_unexpected_last_chance_call') -if last_chance.getInt() != 0: - print '!!! EXCEPTION RAISED !!!' - -traceDoc.waitUntilLoaded (0, 100) -formatter = ic.CTraceBinExportFormat () -formatter.setTraceItemFlags (0) -formatter.setHeader (False) \ - .addTraceItem (ic.CTraceBinExportFormat.EOCDItem) -exportCfg = ic.CTraceExportConfig () -exportCfg.setFileName ('nexus_trace.bin').setFormatter (formatter) -traceDoc.exportData (exportCfg) -traceDoc.closeAll () - -cmgr.disconnect (0) diff --git a/testsuite/altrun/isys_nexus_5634/justrun.xjrf b/testsuite/altrun/isys_nexus_5634/justrun.xjrf deleted file mode 100755 index cf4f6cc6d..000000000 --- a/testsuite/altrun/isys_nexus_5634/justrun.xjrf +++ /dev/null @@ -1,4244 +0,0 @@ - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - HODGDFEIGHBIMPAB - FFOIJOFDLBGFEHEPLMCGJJGGPCJIBEJH - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - 0 - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - MKGJKBGOKIIJMOAB - HMFBCKJFLOPDDHEDJCOMAJLCICINJJMK - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - 0 - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - HASYST - 1258881024 - - 0 - - - False - - - - 0 - justrun.trd - - - ..\..\..\..\..\calib\justrun.trd - - - - 0 - 0 - 0 - 0 - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 1 - 0 - 0 - 0 - -1 - - 0 - 600 - 0 - -1 - - 1 - 28 - 2 - -1 - - 1 - 227 - File - 10 - 7 - - - 1 - 2 - 6 - -1 - - - 1 - 369 - View - 10 - 8 - - - 1 - 0 - 6 - -1 - - - - 1 - 2 - 6 - -1 - - - 1 - 200 - Project Workspace - 0 - 1 - - - 1 - 5 - 6 - -1 - - - 1 - 700 - 1 - -2 - - - 1 - 0 - 6 - -1 - - - - 1 - 5 - 6 - -1 - - - 0 - 200 - 0 - -1 - - 1 - 200 - Output - 0 - 0 - - - 1 - 5 - 6 - -1 - - - 1 - 480 - DocWnd - 0 - 21 - - justrun.trd - - - - 1 - 0 - 6 - -1 - - - - 1 - 0 - 6 - -1 - - - - - - - True - True - - - - False - - - - 0 - - - 1 - - - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 1 - 0 - - - 0 - 0 - - - - -1 - 0 - - - 0 - 0 - - main - 0 - 0 - 1 - 0 - 1 - True - 0 - 0 - main - 0 - False - 0 - - -1 - 0 - - - - False - False - False - history.txt - True - False - True - 0 - True - False - True - - - $Download.xml - 0 - 1 - 1 - 1 - - - 0 - 1 - 1 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 1 - - <__.0> - DEFAULT - 0 - 0 - - 0 - - - - - - 0 - - - 0 - - - 0 - 0 - 1 - - - - 0xCC - 2 - - - 0 - - - True - True - True - True - symbols.txt - True - True - - - 0 - 1 - 0 - True - 1 - 2 - False - False - False - False - False - 0 - 1 - 0 - 0 - False - 1 - 1 - True - 256 - 1 - _ - 0 - 0 - 0.0000100000000000 - - - 0 - - - - False - True - 1 - False - 200 - True - False - True - False - True - False - False - - 0 - 0 - 0 - 0 - 1 - - - - 1 - - 0 - 0 - 1 - - - - 0 - 0 - 0 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - - AAABACADAEAFAGAHAIAJAKALAMANAOAPBABBBCBDBEBFBGBHBIBJBKBLBMBNBOBP - 0 - - - 1 -
0
- - - 0 - True - -
- - -1 - 0 - - - <__> - 0 - 0 - 0 - - - - <__> - 0 - 0 - 0 - - - - 0 - 0 - -
- - - 0 - - - - - - - - - - - - - - - - - 0 - 1 - 1 - - - - - - - - - - 0 - 0 - - - - - - Build 9.12.144 - - - - 0 - 0 - - - 1 - 0 - 1 - 0 - 1 - - - - - - - - - - - - - - - 0 - - - 2 - - - 0 - 1 - 0 - 0 - 2 - 0 - - - -1 - - 0 - - 0 - 0 - 9600 - COM1 - 8 - 0 - 0 - 0 - 0 - 24 - 80 - 500 - 0 - 1 - 0 - - - - - 0 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - - - 1 - 1 - 1 - 0 - <_166> - 0 - - <_68k> - 0 - - - 1 - 0 - - - 0 - - 1 - - - - 0 - - - - - - - - - - - <_-Cs08>1 - - - 0 - - - 0 - - 0 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - 1 - - - - - 1 - 1 - True - 1 - 0 - 0 - 1 - 0 - 0 - False - False - True - 16 - - 100 - 1 - True - - - - - - - - - - - <__> - Files - 4 - - - - - - - - - - -
- - <_76946E39-78E2-4625-9BF0-751C4C11A09F> - - - 0 - 0 - 0 - 5544 - 1 - - - - -
-
- - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - - - - - 60 - 20 - 70 - 60 - 20 - 70 - 10 - - - 0.0000000000000000 - 0 - 0 - - 0 - 0 - 0 - - - 0 - - - 0 - 0 - 0 - - - 0 - - - 0 - 0 - 0 - - - 0 - - - - - - 0 - - 0 - 0 - - 1 - - - 0.0000000000000000 - 0 - 0 - - 0 - - - - - - - - 0 - 0 - - - - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - 1 - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 1 - -
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
-
-
-
- - - 0 - - - 0 - - - 0 - - 0 - 0 - 0 - Default - 2 - 0 - AAAA - AAAA - AAAA - AAAA - AAAA - AAAA - AAAA - AAAA - - - - - 16000 - - - 0 - - -
- - - 1 - 0 - 0 - 0 - - - - - AIN0 - - - AIN1 - - - AIN0 - - - AIN1 - - - DIN0 - - - DIN1 - - - DIN10 - - - DIN11 - - - DIN12 - - - DIN13 - - - DIN14 - - - DIN15 - - - DIN16 - - - DIN17 - - - DIN18 - - - DIN19 - - - DIN2 - - - DIN20 - - - DIN21 - - - DIN22 - - - DIN23 - - - DIN24 - - - DIN25 - - - DIN26 - - - DIN27 - - - DIN28 - - - DIN29 - - - DIN3 - - - DIN30 - - - DIN31 - - - DIN4 - - - DIN5 - - - DIN6 - - - DIN7 - - - DIN8 - - - DIN9 - - - DOUT0 - - - DOUT1 - - - DOUT10 - - - DOUT11 - - - DOUT12 - - - DOUT13 - - - DOUT14 - - - DOUT15 - - - DOUT16 - - - DOUT17 - - - DOUT18 - - - DOUT19 - - - DOUT2 - - - DOUT20 - - - DOUT21 - - - DOUT22 - - - DOUT23 - - - DOUT24 - - - DOUT25 - - - DOUT26 - - - DOUT27 - - - DOUT28 - - - DOUT29 - - - DOUT3 - - - DOUT30 - - - DOUT31 - - - DOUT4 - - - DOUT5 - - - DOUT6 - - - DOUT7 - - - DOUT8 - - - DOUT9 - - - 1 - 4 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 1 - 1 - - 0 - 0 - 0 - - - - 1 - 1 - - 0 - 0 - 0 - - - - 1 - 0 - - 0 - 0 - 0 - - - - 1 - 0 - - 0 - 0 - 0 - - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 0 - 0 - 0 - - - - - 1 - 1 - 1 - 1 - 1 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 1 - 1 - 1 - 1 - 1 - - - - - - 1 - 1 - 1 - 1 - 1 - - - - - - 1 - 1 - 1 - 1 - 1 - - - - - - 1 - 1 - 1 - 1 - 1 - - - - - -
0
- 0 - False - 0 - 0 - 1 - 0 - 0 - 0 - 0 -
- - 0 - - AAAAAAAA - 0 - - - 1 - #g_TConn - 1 - - #g_TWBuffer - 1 - 0 - - - #g_TRBuffer - 1 - 0 - - - - - 0 - 2 - 0 - 0 - 0 - - - 0 - - - -
- - - 1 - 1 ns - - - 1 - - - 0 - - - 1 - - -
- - 144 - 0 - 9 - 1 - 12 - 151781664 - - - 50 - 0 - 127 - 1 - 11 - 7 - - - <_55xx_AllowFLASHPgmOnlyDuringDL>0 - <_55xx_DCI_CR>-2048 - <_55xx_EnableShadowMemoryProgramming>0 - <_55xx_EVTOOnlyOnBP>0 - <_55xx_InitMMU>0 - <_55xx_InitMMU_VLE>0 - <_55xx_InitRAM>2 - <_55xx_LowPowerDebug>0 - <_55xx_LowPowerDebug_Run>0 - <_55xx_LowPowerDebug_StopBefore>0 - <_55xx_MassEraseDataFLASH>0 - <_55xx_MassEraseProgramFLASH>0 - <_55xx_Mode>0 - <_55xx_NexusEBI>0 - <_55xx_Password type="B">AAAAAAAAAAAAAAAA - <_55xx_PINCR>0 - <_55xx_StopTimerDuringStep>0 - <_55xx_StopWhenReleasedFromReset>0 - <_55xx_UseBDMMemAccessWhenStopped>0 - <_55xx_UsePassword>0 - <_55xx_UseTrapForSWBPsinPowerPCMode>0 - <_83xx_RCWH>0 - <_83xx_RCWL>0 - <_83xx_RCWOverride>0 - True - 0 - False - True - 0 - 0 - 0 - 67108864 - -1048320 - 0 - - 0 - 0 - - - 0x0 - 0 - - - - 0 - 0 - 0 - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - 10 - 114 - 1 - 0 - 4000 - 0 - 0 - 0 - 0 - 10 - 0 - 1 - 0 - 1 - 0 - 0 - 0 - 2 - 1 - 1 - 0 - 0 - 100 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - - - -
0
- 0 - 0 - 0 - 0 - 0 - 0 - 0 -
- - 0 - 1 - 0 - 0 - -
0
- 0 - 0 - 0 -
-
-
- - -
0
- 0 - 0 -
- -
0
- 0 - 0 -
- -
0
- 0 - 0 -
- -
0
- 0 - 0 -
-
- - 0 - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0 - 1000 - 0 - 0 - 500 - 0 - 0 - 0 - 0 - 1 - 0 - - - 1 - 0 - 3300 - False - 0 - 0 - 1 - 1500 - - 0 - 1500 - - - 0 - 1500 - - - 0 - 1500 - - - 0 - 1500 - - - - 0 - - - 0 - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - -
- - 1 - 2 - - 2 - 0 - - - - 10.10.10.10 - 0 - 0 - 3 - 1 - 0 - 5313 - iC5000 (SN 68020) - - - - 0 - - 0 - - -
-
-
-
-
diff --git a/testsuite/altrun/isys_nexus_5634/post_testcase.py b/testsuite/altrun/isys_nexus_5634/post_testcase.py deleted file mode 100755 index 82752b0f5..000000000 --- a/testsuite/altrun/isys_nexus_5634/post_testcase.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python - - -import time -import sys -import os - -altrun_dir = sys.argv[1] -ws_file = altrun_dir + '\ws\j.xjrf' - -import isystem.connect as ic - -# Switch to dummy workspace after test to allow cleanup - - -cmgr = ic.ConnectionMgr() -cmgr.connectMRU() - -wspaceControl = ic.CWorkspaceController (cmgr) -wspaceControl.open(os.path.abspath(ws_file)) - -cmgr.disconnect (0) diff --git a/testsuite/altrun/isys_nexus_5634/post_testsuite.py b/testsuite/altrun/isys_nexus_5634/post_testsuite.py deleted file mode 100755 index 011f6879e..000000000 --- a/testsuite/altrun/isys_nexus_5634/post_testsuite.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python - -# Stop all running instances of winIDEA - -import isystem.connect as ic - -cmgr = ic.ConnectionMgr () - -connectionConfig = ic.CConnectionConfig () - -port = 0 -while (1): - port = cmgr.findExistingInstance ('', connectionConfig) - if (port < 0): - break; - else: - print 'stopping winIDEA at port: ', port - cmgr.connect('', port) - cmgr.disconnect (ic.IConnect.dfCloseServerUnconditional | ic.IConnect.dfCloseAutoSaveNone) diff --git a/testsuite/altrun/isys_nexus_5634/pre_testsuite.py b/testsuite/altrun/isys_nexus_5634/pre_testsuite.py deleted file mode 100755 index 5d7b8ed07..000000000 --- a/testsuite/altrun/isys_nexus_5634/pre_testsuite.py +++ /dev/null @@ -1,76 +0,0 @@ -#!/usr/bin/env python - -# Stop all running instances of winIDEA and then -# start a single instance using the simple workspace -# in the 'ws' directory. - -import os -import isystem.connect as ic -import time - -cmgr = ic.ConnectionMgr () - -connectionMgr = ic.ConnectionMgr() -connectionConfig = ic.CConnectionConfig() -winIDEAInstances = ic.VectorWinIDEAInstanceInfo() - -hostAddress = '' # enumerate instances on local host. You may also specify remote host - # here, for example as IP address: '10.1.2.91' -connectionMgr.enumerateWinIDEAInstances(hostAddress, connectionConfig, winIDEAInstances) - -# Now we'll connect to each of found winIDEA instances and close them -for instance in winIDEAInstances: - instanceCMgr = ic.ConnectionMgr() - instanceCMgr.connect(hostAddress, instance.getTcpPort()) - instanceCMgr.disconnect (ic.IConnect.dfCloseServerUnconditional | ic.IConnect.dfCloseAutoSaveNone) - print 'Kill WinIDEA at port: ', instance.getTcpPort() - -ws1 = os.path.abspath('ws/j.xjrf') -cmgr = ic.ConnectionMgr() -connectionConfig = ic.CConnectionConfig() -connectionConfig.visibility(ic.IConnect.lfShowHidden) - -print "Openning workspace at '%s'" % ws1 -connectionConfig.workspace (ws1) - -port = cmgr.startNewInstance (connectionConfig) -print 'new winIDEA at port: ', port - -cMgr = ic.ConnectionMgr() -cMgr.connectMRU('') - -ide = ic.CIDEController(cMgr) -print 'winIDEA version : ' + ide.getWinIDEAVersion().toString() - -# Set probe communication options -ide.setOption('/IOPEN/Communication.USBDeviceName', 'iC5000 (SN 68020)') -ide.setOption('/IOPEN/Communication.IPAddress', 'iC5000 (SN 68020) : 5313') -ide.setOption('/IOPEN/Communication.Mode', 'USB') -ide.commitOptions('/IOPEN/') - -for try_nb in range(10): - debug = ic.CDebugFacade(cMgr) - status = debug.getCPUStatus() - isConnected = (not status.isMustInit()) - print 'is connected: ' + str(isConnected) - if isConnected: - break - - executer = ic.CExecutionController (cMgr) - try: - executer.reset() - except: - print 'exception in executer.reset()' - try: - executer.stop() - except: - print 'exception in executer.reset()' - - time.sleep (1) - -executer = ic.CExecutionController (cMgr) -executer.reset () -executer.stop () -# the steps above are included because the retrieval -# of the firmware info from the ic5000 doesn't work -# until some action has occured. diff --git a/testsuite/altrun/isys_nexus_5634/setup.py b/testsuite/altrun/isys_nexus_5634/setup.py deleted file mode 100644 index 469b1d8e3..000000000 --- a/testsuite/altrun/isys_nexus_5634/setup.py +++ /dev/null @@ -1,13 +0,0 @@ -# This holds "setup" code for the example altrun/ subdir. - -# This is called before looking for binaries to setup testsuite and testcase -# hooks. Here, we produce one such binary from ada sources. - -from gnatpython.ex import Run -import sys - -p = Run (['gnatmake', '-f', '-g', '-p', '-Paltrun', "crun.adb"], - output=sys.stdout) - -if p.status != 0: - sys.exit(1) diff --git a/testsuite/altrun/isys_nexus_5634/ws/j.xjrf b/testsuite/altrun/isys_nexus_5634/ws/j.xjrf deleted file mode 100755 index 245795517..000000000 --- a/testsuite/altrun/isys_nexus_5634/ws/j.xjrf +++ /dev/null @@ -1,3950 +0,0 @@ - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - MKGJKBGOKIIJMOAB - HMFBCKJFLOPDDHEDJCOMAJLCICINJJMK - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - 0 - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - HASYST - 1258881024 - - 0 - - - False - - - - - -31812 - -32168 - -31672 - -32164 - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 1 - 0 - 0 - 0 - -1 - - 0 - 600 - 0 - -1 - - 1 - 28 - 2 - -1 - - 1 - 227 - File - 10 - 7 - - - 1 - 2 - 6 - -1 - - - 1 - 369 - View - 10 - 8 - - - 1 - 0 - 6 - -1 - - - - 1 - 2 - 6 - -1 - - - 1 - 200 - Project Workspace - 0 - 1 - - - 1 - 5 - 6 - -1 - - - 1 - 700 - 1 - -2 - - - 1 - 0 - 6 - -1 - - - - 1 - 5 - 6 - -1 - - - 1 - 200 - Output - 0 - 0 - - - 1 - 0 - 6 - -1 - - - - - - - True - True - - - - False - - - - 0 - - - 1 - - - 1 - 0 - 0 - 1 - 1 - 1 - 1 - 0 - 1 - 0 - - - 0 - 0 - - - - -1 - 0 - - - 0 - 0 - - main - 0 - 0 - 1 - 0 - 1 - True - 0 - 0 - main - 0 - False - 0 - - -1 - 0 - - - - False - False - False - history.txt - True - False - True - 0 - True - False - True - - - $Download.xml - 0 - 1 - 1 - 1 - - - 0 - 1 - 1 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 1 - - <__.0> - DEFAULT - 0 - 0 - - 0 - - - - - - 0 - - - 0 - - - 0 - 0 - 1 - - - - 0xCC - 2 - - - 0 - - - True - True - True - True - symbols.txt - True - True - - - 0 - 1 - 0 - True - 1 - 2 - False - False - False - False - False - 0 - 1 - 0 - 0 - False - 1 - 1 - True - 256 - 1 - _ - 0 - 0 - 0.0000100000000000 - - - 0 - - - - False - True - 1 - False - 200 - True - False - True - False - True - False - False - - 0 - 0 - 0 - 0 - 1 - - - - 1 - - 0 - 0 - 1 - - - - 0 - 0 - 0 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - - AAABACADAEAFAGAHAIAJAKALAMANAOAPBABBBCBDBEBFBGBHBIBJBKBLBMBNBOBP - 0 - - - 1 -
0
- - - 0 - True - -
- - -1 - 0 - - - <__> - 0 - 0 - 0 - - - - <__> - 0 - 0 - 0 - - - - 0 - 0 - -
- - - 0 - - - - - - - - - - - - - - - - - 0 - 1 - 1 - - - - - - - - - - 0 - 0 - - - - - - Build 9.12.144 - - - - 0 - 0 - - - 1 - 0 - 1 - 0 - 1 - - - - - - - - - - - - - - - 0 - - - 2 - - - 0 - 1 - 0 - 0 - 2 - 0 - - - -1 - - 0 - - 0 - 0 - 9600 - COM1 - 8 - 0 - 0 - 0 - 0 - 24 - 80 - 500 - 0 - 1 - 0 - - - - - 0 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - - - 1 - 1 - 1 - 0 - <_166> - 0 - - <_68k> - 0 - - - 1 - 0 - - - 0 - - 1 - - - - 0 - - - - - - - - - - - <_-Cs08>1 - - - 0 - - - 0 - - 0 - - - - - - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - - - 0 - 1 - - - - - 1 - 1 - True - 1 - 0 - 0 - 1 - 0 - 0 - False - False - True - 16 - - 100 - 1 - True - - - - - - - - - - - <__> - Files - 4 - - - - - - - - - - -
- - <_76946E39-78E2-4625-9BF0-751C4C11A09F> - - - 0 - 0 - 0 - 5544 - 1 - - - - -
-
- - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1258881024 - - - - - - 60 - 20 - 70 - 60 - 20 - 70 - 10 - - - 0.0000000000000000 - 0 - 0 - - 0 - 0 - 0 - - - 0 - - - 0 - 0 - 0 - - - 0 - - - 0 - 0 - 0 - - - 0 - - - - - - 0 - - 0 - 0 - - 1 - - - 0.0000000000000000 - 0 - 0 - - 0 - - - - - - - - 0 - 0 - - - - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - - - - - - - - - 0 - 0 - 0 - 0 - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - - - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - 1 - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 2 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - 0x0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 1 - -
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
- - - 0xFFFFFFFF - 0 - 0x00000000 - - - 0xFFFFFFFF - 0 - 0x00000000 - - -
-
- -
-
-
-
-
-
- - - 0 - - - 0 - - - 0 - - 0 - 0 - 0 - Default - 2 - 0 - AAAA - AAAA - AAAA - AAAA - AAAA - AAAA - AAAA - AAAA - - - - - 16000 - - - 0 - - -
- - - 1 - 0 - 0 - 0 - - - - - AIN0 - - - AIN1 - - - AIN0 - - - AIN1 - - - DIN0 - - - DIN1 - - - DIN10 - - - DIN11 - - - DIN12 - - - DIN13 - - - DIN14 - - - DIN15 - - - DIN16 - - - DIN17 - - - DIN18 - - - DIN19 - - - DIN2 - - - DIN20 - - - DIN21 - - - DIN22 - - - DIN23 - - - DIN24 - - - DIN25 - - - DIN26 - - - DIN27 - - - DIN28 - - - DIN29 - - - DIN3 - - - DIN30 - - - DIN31 - - - DIN4 - - - DIN5 - - - DIN6 - - - DIN7 - - - DIN8 - - - DIN9 - - - DOUT0 - - - DOUT1 - - - DOUT10 - - - DOUT11 - - - DOUT12 - - - DOUT13 - - - DOUT14 - - - DOUT15 - - - DOUT16 - - - DOUT17 - - - DOUT18 - - - DOUT19 - - - DOUT2 - - - DOUT20 - - - DOUT21 - - - DOUT22 - - - DOUT23 - - - DOUT24 - - - DOUT25 - - - DOUT26 - - - DOUT27 - - - DOUT28 - - - DOUT29 - - - DOUT3 - - - DOUT30 - - - DOUT31 - - - DOUT4 - - - DOUT5 - - - DOUT6 - - - DOUT7 - - - DOUT8 - - - DOUT9 - - - 1 - 4 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - 1 - 1 - - 0 - 0 - 0 - - - - 1 - 1 - - 0 - 0 - 0 - - - - 1 - 0 - - 0 - 0 - 0 - - - - 1 - 0 - - 0 - 0 - 0 - - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 1 - 0 - - - 0 - 0 - 0 - - - - - 1 - 1 - 1 - 1 - 1 - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 1 - 1 - 1 - 1 - 1 - - - - - - 1 - 1 - 1 - 1 - 1 - - - - - - 1 - 1 - 1 - 1 - 1 - - - - - - 1 - 1 - 1 - 1 - 1 - - - - - -
0
- 0 - False - 0 - 0 - 1 - 0 - 0 - 0 - 0 -
- - 0 - - AAAAAAAA - 0 - - - 1 - #g_TConn - 1 - - #g_TWBuffer - 1 - 0 - - - #g_TRBuffer - 1 - 0 - - - - - 0 - 2 - 0 - 0 - 0 - - - 0 - - - -
- - - 1 - 1 ns - - - 1 - - - 0 - - - 1 - - -
- - 144 - 0 - 9 - 1 - 12 - 151781664 - - - 50 - 0 - 127 - 1 - 11 - 7 - - - <_55xx_AllowFLASHPgmOnlyDuringDL>0 - <_55xx_DCI_CR>-2048 - <_55xx_EnableShadowMemoryProgramming>0 - <_55xx_EVTOOnlyOnBP>0 - <_55xx_InitMMU>0 - <_55xx_InitMMU_VLE>0 - <_55xx_InitRAM>2 - <_55xx_LowPowerDebug>0 - <_55xx_LowPowerDebug_Run>0 - <_55xx_LowPowerDebug_StopBefore>0 - <_55xx_MassEraseDataFLASH>0 - <_55xx_MassEraseProgramFLASH>0 - <_55xx_Mode>0 - <_55xx_NexusEBI>0 - <_55xx_Password type="B">AAAAAAAAAAAAAAAA - <_55xx_PINCR>0 - <_55xx_StopTimerDuringStep>0 - <_55xx_StopWhenReleasedFromReset>0 - <_55xx_UseBDMMemAccessWhenStopped>0 - <_55xx_UsePassword>0 - <_55xx_UseTrapForSWBPsinPowerPCMode>0 - <_83xx_RCWH>0 - <_83xx_RCWL>0 - <_83xx_RCWOverride>0 - True - 0 - False - True - 0 - 0 - 0 - 67108864 - -1048320 - 0 - - 0 - 0 - - - 0x0 - 0 - - - - 0 - 0 - 0 - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - 10 - 114 - 1 - 0 - 4000 - 0 - 0 - 0 - 0 - 10 - 0 - 1 - 0 - 1 - 0 - 0 - 0 - 2 - 1 - 1 - 0 - 0 - 100 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - - - -
0
- 0 - 0 - 0 - 0 - 0 - 0 - 0 -
- - 0 - 1 - 0 - 0 - -
0
- 0 - 0 - 0 -
-
-
- - -
0
- 0 - 0 -
- -
0
- 0 - 0 -
- -
0
- 0 - 0 -
- -
0
- 0 - 0 -
-
- - 0 - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0 - 1000 - 0 - 0 - 500 - 0 - 0 - 0 - 0 - 1 - 0 - - - 1 - 0 - 3300 - False - 0 - 0 - 1 - 1500 - - 0 - 1500 - - - 0 - 1500 - - - 0 - 1500 - - - 0 - 1500 - - - - 0 - - - 0 - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - - 0 - 0 - AAAAAAAAAAAAAAAA - - -
- - 1 - 2 - - 2 - 0 - - - - 10.10.10.10 - 0 - 0 - 3 - 1 - 0 - 5313 - iC5000 (SN 68020) - - - - 0 - - 0 - - -
-
-
-
-
From 20397da303d3e2bb6a67c6cb57df9165568eef50 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 20 Feb 2024 16:06:03 +0000 Subject: [PATCH 0714/1483] Remove the "nexus" trace adapter The nexus hardware probe has been unsupported for a long time: remove it to avoid maintenance costs. --- tools/gnatcov/Makefile | 5 +- tools/gnatcov/trace_adapters/nexus/.gitignore | 4 - tools/gnatcov/trace_adapters/nexus/Makefile | 55 - .../gnatcov/trace_adapters/nexus/isys2nex.adb | 312 -- .../gnatcov/trace_adapters/nexus/isys2nex.ads | 39 - .../gnatcov/trace_adapters/nexus/isys_drv.adb | 267 -- .../trace_adapters/nexus/isys_trace.py | 63 - .../gnatcov/trace_adapters/nexus/min5554.trd | Bin 800256 -> 0 bytes .../gnatcov/trace_adapters/nexus/min5554.xjrf | 2899 --------------- .../gnatcov/trace_adapters/nexus/min5554.xqrf | 103 - .../gnatcov/trace_adapters/nexus/min5634.trd | Bin 32204 -> 0 bytes .../gnatcov/trace_adapters/nexus/min5634.xjrf | 3146 ----------------- .../gnatcov/trace_adapters/nexus/min5634.xqrf | 130 - tools/gnatcov/trace_adapters/nexus/nexus.gpr | 17 - .../trace_adapters/nexus/nexus_rep.ads | 223 -- .../trace_adapters/nexus/nexus_trace_gen.adb | 1332 ------- 16 files changed, 2 insertions(+), 8593 deletions(-) delete mode 100644 tools/gnatcov/trace_adapters/nexus/.gitignore delete mode 100644 tools/gnatcov/trace_adapters/nexus/Makefile delete mode 100755 tools/gnatcov/trace_adapters/nexus/isys2nex.adb delete mode 100644 tools/gnatcov/trace_adapters/nexus/isys2nex.ads delete mode 100644 tools/gnatcov/trace_adapters/nexus/isys_drv.adb delete mode 100644 tools/gnatcov/trace_adapters/nexus/isys_trace.py delete mode 100755 tools/gnatcov/trace_adapters/nexus/min5554.trd delete mode 100755 tools/gnatcov/trace_adapters/nexus/min5554.xjrf delete mode 100755 tools/gnatcov/trace_adapters/nexus/min5554.xqrf delete mode 100755 tools/gnatcov/trace_adapters/nexus/min5634.trd delete mode 100755 tools/gnatcov/trace_adapters/nexus/min5634.xjrf delete mode 100755 tools/gnatcov/trace_adapters/nexus/min5634.xqrf delete mode 100644 tools/gnatcov/trace_adapters/nexus/nexus.gpr delete mode 100755 tools/gnatcov/trace_adapters/nexus/nexus_rep.ads delete mode 100755 tools/gnatcov/trace_adapters/nexus/nexus_trace_gen.adb diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index 978b24f34..0740f705b 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -108,7 +108,7 @@ include architecture.mk ifeq ($(HOST_OS), windows) ifeq ($(BITS_ARCH), 32) -DEFAULT_ADAPTERS = nexus trace32 +DEFAULT_ADAPTERS = trace32 else DEFAULT_ADAPTERS = endif @@ -131,9 +131,8 @@ BUILD_MODE=dev # == Variables to pass down to sub-makefiles for trace adapters == # ================================================================ -# Trace32 and Nexus (iSystem) adapters use the same prefix as GNATcov +# The Trace32 adapter use the same prefix as GNATcov trace32_ADAPTER_INSTALL_VARS=PREFIX=$(PREFIX) -nexus_ADAPTER_INSTALL_VARS=PREFIX=$(PREFIX) .PHONY: default all adapters bin $(PGMPATH) diff --git a/tools/gnatcov/trace_adapters/nexus/.gitignore b/tools/gnatcov/trace_adapters/nexus/.gitignore deleted file mode 100644 index 835c43071..000000000 --- a/tools/gnatcov/trace_adapters/nexus/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -isys_drv -isys_drv.exe -nexus_trace_gen -nexus_trace_gen.exe diff --git a/tools/gnatcov/trace_adapters/nexus/Makefile b/tools/gnatcov/trace_adapters/nexus/Makefile deleted file mode 100644 index 180b7e3fc..000000000 --- a/tools/gnatcov/trace_adapters/nexus/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -GPRBUILD=gprbuild -PREFIX=install -PARALLEL_BUILD=0 - -include ../../host.mk - -.PHONY: force - -# Files for libexec/gnatcoverage include binary executables -# (which need to be built first), and a python script. - -EXENAMES=nexus_trace_gen isys_drv -PYPROG=isys_trace.py - -# Files for share/gnatcoverage are the winIdea project files -WINIDEA_PROJ_FILES=min5554.trd min5554.xjrf min5554.xqrf \ - min5634.trd min5634.xjrf min5634.xqrf - -# Directory name in the install tree -DIRNAME=gnatcoverage - -DOCFORMATS=pdf html - -all: $(EXENAMES) - -$(EXENAMES): force - $(GPRBUILD) -p -j$(PARALLEL_BUILD) \ - -Pnexus -XPART=lib32 $(EXTRA_ADAFLAGS) $@ - - -################### -# General cleanup # -################### - -.PHONY: clean - -clean: - $(RM) *.o *.ali $(EXENAMES) b~* b__* - -################ -# Installation # -################ - -.PHONY: install-libexec install-share install - -install-libexec: - $(MKDIR) $(PREFIX)/libexec/$(DIRNAME) - $(CP) $(addsuffix $(exeext),$(EXENAMES)) \ - $(PYPROG) $(PREFIX)/libexec/$(DIRNAME) - -install-share: - $(MKDIR) $(PREFIX)/share/$(DIRNAME) - $(CP) $(WINIDEA_PROJ_FILES) $(PREFIX)/share/$(DIRNAME) - -install: install-libexec install-share diff --git a/tools/gnatcov/trace_adapters/nexus/isys2nex.adb b/tools/gnatcov/trace_adapters/nexus/isys2nex.adb deleted file mode 100755 index 11deb9efb..000000000 --- a/tools/gnatcov/trace_adapters/nexus/isys2nex.adb +++ /dev/null @@ -1,312 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- 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.Sequential_IO; -with Interfaces; use Interfaces; - -package body Isys2nex is - - -- The iSystem OCD data comprises a stream of bytes describing - -- sequences of "items" in iSystem's terminology. An initial byte, - -- provides a count of the number of items to follow. For each - -- item, one byte gives the number of bits in the item, and subsequent - -- bytes contain the unsigned integer data starting with the least - -- significant bits and ending when enough bytes have been included - -- to contain the number of bits. A new sequence of bytes starts - -- with a count of items, or the end of the file is seen. - -- - -- In the case of Nexus data, a sequence of items is a Nexus message, - -- and each item is a packet in the Nexus message. The fisrt packet - -- contains the Message TCODE. - - type Item_Unit_T is new Unsigned_8; - package Item_IO is new Ada.Sequential_IO (Item_Unit_T); - use Item_IO; - OCD_File : File_Type; - -- We define a type for the unit of data read from and OCD file, - -- and create and instance of Sequential_IO with that type. - - procedure Open_OCD_File (OCD_Filename : String) is - begin - Open (OCD_File, In_File, OCD_Filename); - exception - when others => - raise Isys2nex_Error with "Error Opening " & OCD_Filename; - end Open_OCD_File; - - procedure Fill_Packet - (Min_Bits : Natural; - Max_Bits : Natural; - Packet : out Nexus_Packet_T; - Bits : out Item_Unit_T); - function Continue_Fill (Bits : Item_Unit_T) return Nexus_Packet_T; - -- These 2 routines are used to fill in a component of a Nexus - -- message -- a packet -- with an item read from the OCD file. - -- 'Fill_Packet' takes the minimum and maximum number of bits expected - -- for the packet, fills in 'Packet' with the value, and 'Bits' with - -- the actual number of bits stated in the item bit-size byte of the - -- the file. This routine is called when the File_Ptr is positioned - -- to read a bit-size value next. If the bit-size is out of the range - -- 'Min_Bits' .. 'Max_Bits', OCD_File will be closed, and Isys2Nex_Error - -- exception will be raised. If the bit-size is too large to fit in - -- 'Packet' (but is valid), Packet will be filled with the first 32 bits, - -- and the calling routine can use Continue_Fill to fill subsequent - -- packets with the remaining bits. - -- - -- Continue_Fill is called called by Fill_Packet after the bit-size - -- byte is read and checked, and is also called directly by - -- Get_Next_Nexus_Msg in the case where an item is too long - -- to fit in a single packet. - - -- Note: the minimum and maximum nuber of bits for a packet is - -- hard coded into the calls below, with values taken from the - -- NZ63C Nexus module used on the Freescale 5554 microcontroller. - -- A better way to list these values should be found. Also, the - -- values are not checked for now, since iSytem's representation - -- sometimes uses more bits than needed, though the values seem - -- to be in the range allowed for by the NZ63C document (i.e., - -- iSytems data appears to sometimes add some extra leading 0s). - -- The iSystem behavior needs to be better understood in order - -- to see if Min_Bits/Max_Bits can actually be used. ??? - - Debug_Status_Msg : aliased Nexus_Message_Rec_T (Debug_Status); - Error_Msg : aliased Nexus_Message_Rec_T (Error_Message); - Watchpoint_Msg : aliased Nexus_Message_Rec_T (Watchpoint_Message); - Resource_Full_Msg : aliased Nexus_Message_Rec_T (Resource_Full_Message); - Prog_Trace_Direct_Branch_Msg : aliased - Nexus_Message_Rec_T (Prog_Trace_Direct_Branch_Message); - Prog_Trace_Indirect_Branch_Msg : aliased - Nexus_Message_Rec_T (Prog_Trace_Indirect_Branch_Message); - Prog_Trace_Direct_Branch_Msg_Sync : aliased - Nexus_Message_Rec_T (Prog_Trace_Direct_Branch_Message_Sync); - Prog_Trace_Indirect_Branch_Msg_Sync : aliased - Nexus_Message_Rec_T (Prog_Trace_Indirect_Branch_Message_Sync); - Prog_Trace_Program_Correlation_Msg : aliased - Nexus_Message_Rec_T (Prog_Trace_Program_Correlation_Message); - -- One record is defined here for each Nexus message type that is - -- handled. In the processing done by Get_Next_Nexus_Msg, - -- one of these records is filled in by the next set of items - -- in the OCD stream, depending upon the TCODE which is always - -- the first item. A pointer to the filled in record is the - -- return value of Get_Next_Nexus_Msg. - - function Get_Next_Nexus_Msg return Nexus_Message_Rec_Ptr_T is - - Num_Items : Item_Unit_T; - Actual_N_Bits : Item_Unit_T; - - Packet : Nexus_Packet_T; - TCODE : Nexus_Tcode_T; - Nexus_Msg : Nexus_Message_Rec_Ptr_T; - - begin - - if not Is_Open (OCD_File) then - raise Isys2nex_Error with "OCD file needs to be open."; - end if; - if End_Of_File (OCD_File) then - Close (OCD_File); - return null; - end if; - - Read (OCD_File, Num_Items); - if Num_Items = 0 then - Close (OCD_File); - raise Isys2nex_Error with "Error in OCD file: Number Items = 0"; - end if; - - Fill_Packet (6, 6, Packet, Actual_N_Bits); - TCODE := Nexus_Tcode_T (Packet); - - if Natural (Num_Items) /= Nexus_N_Packets_Array (TCODE) then - Close (OCD_File); - raise Isys2nex_Error with "Number of Items wrong for TCODE"; - end if; - - case TCODE is - - -- Only message types expected for Program Trace output are - -- handled below. A Data Trace message is an error, e.g. - - when Debug_Status => - Nexus_Msg := Debug_Status_Msg'Access; - Fill_Packet (4, 4, Nexus_Msg.SRC, Actual_N_Bits); - Fill_Packet (8, 8, Nexus_Msg.Debug_Status_V.STATUS, Actual_N_Bits); - - when Ownership_Trace_Message => - raise Isys2nex_Error with "Unhandled TCODE: Ownership Trace"; - - when Prog_Trace_Direct_Branch_Message => - Nexus_Msg := Prog_Trace_Direct_Branch_Msg'Access; - Fill_Packet (4, 4, Nexus_Msg.SRC, Actual_N_Bits); - Fill_Packet (1, 8, - Nexus_Msg.Prog_Trace_Direct_Branch_Message_V.I_CNT, - Actual_N_Bits); - - when Prog_Trace_Indirect_Branch_Message => - Nexus_Msg := Prog_Trace_Indirect_Branch_Msg'Access; - Fill_Packet (4, 4, Nexus_Msg.SRC, Actual_N_Bits); - Fill_Packet (1, 8, - Nexus_Msg.Prog_Trace_Indirect_Branch_Message_V.I_CNT, - Actual_N_Bits); - Fill_Packet - (1, 32, Nexus_Msg.Prog_Trace_Indirect_Branch_Message_V.U_ADDR, - Actual_N_Bits); - - when Data_Trace_Data_Write_Message => - raise Isys2nex_Error with "Unhandled TCODE: Data Trace Write"; - when Data_Trace_Data_Read_Message => - raise Isys2nex_Error with "Unhandled TCODE: Data Trace Read"; - - when Error_Message => - Nexus_Msg := Error_Msg'Access; - Fill_Packet (4, 4, Nexus_Msg.SRC, Actual_N_Bits); - Fill_Packet (8, 8, Nexus_Msg.Error_Message_V.ECODE, Actual_N_Bits); - - when Prog_Trace_Direct_Branch_Message_Sync => - Nexus_Msg := Prog_Trace_Direct_Branch_Msg_Sync'Access; - Fill_Packet (4, 4, Nexus_Msg.SRC, Actual_N_Bits); - Fill_Packet - (1, 8, - Nexus_Msg.Prog_Trace_Direct_Branch_Message_Sync_V.I_CNT, - Actual_N_Bits); - Fill_Packet - (1, 32, - Nexus_Msg.Prog_Trace_Direct_Branch_Message_Sync_V.F_ADDR, - Actual_N_Bits); - - when Prog_Trace_Indirect_Branch_Message_Sync => - Nexus_Msg := Prog_Trace_Indirect_Branch_Msg_Sync'Access; - Fill_Packet (4, 4, Nexus_Msg.SRC, Actual_N_Bits); - Fill_Packet - (1, 8, - Nexus_Msg.Prog_Trace_Indirect_Branch_Message_Sync_V.I_CNT, - Actual_N_Bits); - Fill_Packet - (1, 32, - Nexus_Msg.Prog_Trace_Indirect_Branch_Message_Sync_V.F_ADDR, - Actual_N_Bits); - - when Data_Trace_Data_Write_Message_Sync => - raise Isys2nex_Error with "Unhandled TCODE: Data Write - Sync"; - when Data_Trace_Data_Read_Message_Sync => - raise Isys2nex_Error with "Unhandled TCODE: Data Read - Sync"; - - when Watchpoint_Message => - Nexus_Msg := Watchpoint_Msg'Access; - Fill_Packet (4, 4, Nexus_Msg.SRC, Actual_N_Bits); - Fill_Packet - (4, 4, Nexus_Msg.Watchpoint_Message_V.WPHIT, Actual_N_Bits); - - when Resource_Full_Message => - Nexus_Msg := Resource_Full_Msg'Access; - Fill_Packet (4, 4, Nexus_Msg.SRC, Actual_N_Bits); - Fill_Packet (4, 4, Nexus_Msg.Resource_Full_Message_V.RCODE, - Actual_N_Bits); - Fill_Packet (1, 32, Nexus_Msg.Resource_Full_Message_V.RDATA, - Actual_N_Bits); - - when Prog_Trace_Indirect_Branch_Hist_Message => - raise Isys2nex_Error with - "Unhandled TCODE: Indirect Branch Hist"; - when Prog_Trace_Indirect_Branch_Hist_Message_Sync => - raise Isys2nex_Error with - "Unhandled TCODE: Indirect Branch Hist - Sync"; - when Prog_Trace_Program_Correlation_Message => - Nexus_Msg := Prog_Trace_Program_Correlation_Msg'Access; - Fill_Packet (4, 4, Nexus_Msg.SRC, Actual_N_Bits); - Fill_Packet - (1, 4, - Nexus_Msg.Prog_Trace_Program_Correlation_Message_V.EVCODE, - Actual_N_Bits); - Fill_Packet - (1, 8, - Nexus_Msg.Prog_Trace_Program_Correlation_Message_V.I_CNT, - Actual_N_Bits); - Fill_Packet - (1, 32, - Nexus_Msg.Prog_Trace_Program_Correlation_Message_V.HIST, - Actual_N_Bits); - - when 1 | 7 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 - | 24 | 25 | 26 | 30 | 31 | 32 => - raise Isys2nex_Error with "Ivalid TCODE"; - end case; - return Nexus_Msg; - end Get_Next_Nexus_Msg; - - procedure Fill_Packet - (Min_Bits : Natural; - Max_Bits : Natural; - Packet : out Nexus_Packet_T; - Bits : out Item_Unit_T) is - - pragma Unreferenced (Min_Bits); -- see below - N_Bits : Item_Unit_T; - Bits_To_Fill : Item_Unit_T; - begin - Read (OCD_File, N_Bits); - -- if Natural (N_Bits) < Min_Bits or else Natural (N_Bits) > Max_Bits - -- Close (OCD_File); - -- raise Isys2nex_Error with "Bits for packet out of range"; - -- end if; - if Natural (N_Bits) > 32 and then Max_Bits <= 32 then - Close (OCD_File); - raise Isys2nex_Error with "Bit size too big for packet"; - end if; - -- The OCD file from winIdea is using more bits in some cases - -- than come from the Nexus module. For now, we just check that - -- we don't cross a 32 bit boundary so we can fit the values - -- (which are correct) into the packet type. ??? - Bits := N_Bits; - if Bits > 32 then - Bits_To_Fill := 32; - else - Bits_To_Fill := Bits; - end if; - Packet := Continue_Fill (Bits_To_Fill); - exception - when End_Error => - Close (OCD_File); - raise Isys2nex_Error with "Premature end-of-file in OCD_File"; - end Fill_Packet; - - function Continue_Fill (Bits : Item_Unit_T) return Nexus_Packet_T is - Packet : Nexus_Packet_T; - Byte : Item_Unit_T; - N_Bytes : Positive; - Mult : Nexus_Packet_T; - begin - Packet := 0; - Mult := 1; - N_Bytes := (Integer (Bits) + 7) / 8; - loop - Read (OCD_File, Byte); - Packet := Packet + Nexus_Packet_T (Byte) * Mult; - exit when N_Bytes = 1; - N_Bytes := N_Bytes - 1; - Mult := Mult * 16#100#; - end loop; - return Packet; - exception - when End_Error => - Close (OCD_File); - raise Isys2nex_Error with "Premature end-of-file in OCD_File"; - end Continue_Fill; - -end Isys2nex; diff --git a/tools/gnatcov/trace_adapters/nexus/isys2nex.ads b/tools/gnatcov/trace_adapters/nexus/isys2nex.ads deleted file mode 100644 index 1b6e265d5..000000000 --- a/tools/gnatcov/trace_adapters/nexus/isys2nex.ads +++ /dev/null @@ -1,39 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- 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. -- ------------------------------------------------------------------------------- - --- iSystem's winIdea software, which is used to control iSystem On Chip --- Debugging (OCD) boxes, can be directed to gather OCD realtime program --- trace data and record it to a file. The function Ocdfile_To_Nexus_List --- takes the name of an OCD file created by winIdea, containing Nexus --- program trace data (the OCD trace format used by Freescale PowerPC --- SOCs, and others) and returns a structure representing a list of --- Nexus messages. - -with Nexus_Rep; use Nexus_Rep; - -package Isys2nex is - Isys2nex_Error : exception; - - procedure Open_OCD_File (OCD_Filename : String); - - function Get_Next_Nexus_Msg return Nexus_Message_Rec_Ptr_T; - - -- If there are any problems with the file or it's contents, the - -- Isys2nex_Error is raised with a message that provides some detail. - -end Isys2nex; diff --git a/tools/gnatcov/trace_adapters/nexus/isys_drv.adb b/tools/gnatcov/trace_adapters/nexus/isys_drv.adb deleted file mode 100644 index 1c08ee2b5..000000000 --- a/tools/gnatcov/trace_adapters/nexus/isys_drv.adb +++ /dev/null @@ -1,267 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage -- --- -- --- Copyright (C) 2012-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.Text_IO; use Ada.Text_IO; -with Ada.Command_Line; use Ada.Command_Line; -with GNAT.OS_Lib; use GNAT.OS_Lib; -with GNAT.Directory_Operations; use GNAT.Directory_Operations; - --- This program - isys_drv - is called by 'gnatcov run' and by --- 'gnatcov convert' when the target specified to gnatcov is one that --- indicates that the program should be run (in the case of "'gnatcov --- run') or was run ('gnatcov convert') through an iSytem probe, on a --- target board connected to that probe. --- --- When called by 'gnatcov convert', the target executable has already --- been executed on the processor, and generated a Nexus Program Trace --- data file. Isys_drv runs the program that converts the Nexus trace --- file into the GNATCoverage format, for use by 'gnatcov coverage'. --- --- When called by 'gnatcov run', isys_drv controls the loading and --- execution of the program on the target hardware to generate the --- Nexus trace file, and then runs the translation step. To accomplish --- the execution on the target, isys_drv: --- - Creates a workspace directory under the current working --- directory and populates it with configuration files needed --- by winIdea (the program which runs the probe). --- - Runs a python program which directs winIdea to run the executable --- program on the board and generate program trace data in a file. --- --- - Runs a translation program which converts the trace from winIdea --- into the format used by gnatcov. --- --- When called for 'gnatcov run', 3 arguments are passed. When --- called for 'gnatcov convert' 7 arguments are passed with the --- first 3 being the same as for 'run'. The first 2 designate the --- target processor and the executable run on the target. The --- third argument is either the name of the trace file initialized by --- gnatcov and appended to by the trace conversion program, or an argument --- of the form 'histmap=HH,TT', where TT is the name of the trace file, --- and HH is the name of a history file which is passed to the trace --- conversion program to tell it to output 'history' traces and identifying --- addresses for which history information is needed. --- --- Their is some error checking done by this program, but --- since it is intended to be called from gnatcov (no fat --- fingers), many things are not checked. --- --- This program should reside in ../libexec/gnatcoverage, relative --- to the directory containing the gnatcov program. It expects --- that other programs that it calls (the python program, and --- the trace conversion program) to reside in the same directory. --- It expcts to find the winIDEA configuration files in --- ../../share/gnatcoverage (relative to isys_drive itself). - -procedure isys_drv is - - type Drv_Mode is (Run, Convert); - Mode : Drv_Mode; - - S_Idx1, S_Idx2 : Positive; - - Executable_Path : String_Access; - Histfile_Path : String_Access; - Tracefile_Path : String_Access; - -- Pathnames for the executable run on the board, - -- the history file and the trace file. - - Execs_Dir : String := Normalize_Pathname ("..", Command_Name); - Share_Dir : String := - Normalize_Pathname ("../../share/gnatcoverage", Execs_Dir); - -- Paths to directories containing this program and other programs - -- called by it, and to the directory containing winIdea configuration - -- files. - - Trace_Conversion_Path : String := - Normalize_Pathname ("Nexus_Trace_Gen", Execs_Dir); - Trace_Conv_Args : Argument_List (1 .. 8); - - Success, C_Success : Boolean; - -- Used by various procedures to report/calculate success. - - CWD : String := Get_Current_Dir; - - -- The following declarations are used only in Run mode. - - Python_P : String_Access; - Python_Args : Argument_List (1 .. 3); - - Project_Files_Basename : String_Access; - -- The names of the various winIdea configuration files which are copied - -- from the share/gnatcoverage location to the workspace directoy are - -- constructed from this string, whose value depends upon the particular - -- processor. - - function Create_Workspace_Dir return String; - -- Creates the Workspace directry and returns it's name. - -- Returns "" if it cannot create the directory. - - function Create_Workspace_Dir return String is - D_Name : String := CWD & "workspace"; - -- ??? The point of creating a function for this is to - -- be able to find a name that does not collide. So this - -- fixed name should go away at some point. - begin - Make_Dir (D_Name); - return D_Name; - exception - when Directory_Error => - return ""; - end Create_Workspace_Dir; - - Workspace_Dir : String_Access; - -begin - if Argument_Count = 3 then - Mode := Run; - elsif Argument_Count = 7 then - Mode := Convert; - else - Put_Line (Standard_Error, "Wrong # or args to isys_drv."); - OS_Exit (1); - end if; - - Executable_Path := new String'(Normalize_Pathname (Argument (2))); - - -- Handle the casses where the tracefile argument is either the - -- name of the trace file created by gnatcov (with some information - -- records, and to be appended with the trace records), or of the - -- form histmap=H,T with H being the name of a history map file - -- and T is the name of the trace file. - -- - -- Here we create the path names of the files, or "" for the history - -- map file in the first case above. - - S_Idx1 := Argument (3)'First; - if Argument (3)'Length > 8 and then - Argument (3) (S_Idx1 .. S_Idx1 + 7) = "histmap=" - then - S_Idx1 := S_Idx1 + 8; - S_Idx2 := S_Idx1; - loop - exit when S_Idx2 = Argument (3)'Last - or else Argument (3) (S_Idx2) = ','; - S_Idx2 := S_Idx2 + 1; - end loop; - if S_Idx2 = Argument (3)'Last then - Put_Line (Standard_Error, "Missing tracefile arg to isys_drv."); - OS_Exit (1); - end if; - Histfile_Path := new String' - (Normalize_Pathname (Argument (3) (S_Idx1 .. S_Idx2 - 1))); - Tracefile_Path := new String' - (Normalize_Pathname (Argument (3) (S_Idx2 + 1 .. Argument (3)'Last))); - else - Histfile_Path := new String'("--nohist"); - Tracefile_Path := new String'(Argument (3)); - end if; - - Trace_Conv_Args (1) := new String'(Argument (1)); - Trace_Conv_Args (2) := Executable_Path; - Trace_Conv_Args (4) := Histfile_Path; - Trace_Conv_Args (5) := Tracefile_Path; - - if Mode = Run then - Python_P := Locate_Exec_On_Path ("python"); - if Python_P = null then - Put_Line (Standard_Error, "python not found."); - OS_Exit (1); - end if; - Workspace_Dir := new String'(Create_Workspace_Dir); - Python_Args (1) := - new String'(Normalize_Pathname ("isys_trace.py", Execs_Dir)); - if Argument (1) = "5554" then - Project_Files_Basename := new String'("min5554"); - Python_Args (2) := new String'("5554"); - elsif Argument (1) = "5634" then - Project_Files_Basename := new String'("min5634"); - Python_Args (2) := new String'("5634"); - else - Put_Line (Standard_Error, - "Unknown processor id in call to isys_drv."); - OS_Exit (1); - end if; - Python_Args (3) := new String'(Executable_Path.all); - - Copy_File (Share_Dir & '\' & Project_Files_Basename.all & ".xjrf", - Workspace_Dir.all, C_Success); - Copy_File (Share_Dir & '\' & Project_Files_Basename.all & ".xqrf", - Workspace_Dir.all, Success); - C_Success := C_Success and Success; - Copy_File (Share_Dir & '\' & Project_Files_Basename.all & ".trd", - Workspace_Dir.all, Success); - C_Success := C_Success and Success; - if not C_Success then - Put_Line (Standard_Error, "Error copying winIdea config files."); - OS_Exit (1); - end if; - -- The iSystem program winIdea is what interfaces the host computer - -- to the iSystem HW probe which is connected to the target board. - -- The python script which is called below directs winIdea to run - -- the program, generating a Nexus trace file, and then write out - -- that trace file. WinIdea gets configuration information from - -- a "workspace" file (the .xjrf file) and other configuration - -- files (the others above contain parameters specifying trace - -- generation). WinIdea also uses the directory containing the - -- workspace configuration file as the default location for other - -- files it needs/produces (such as the Nexus trace file). The - -- project file provided is minimal, containing lttle more than - -- the type of hw (probe, target board and communication channel) - -- being used. - - Spawn (Python_P.all, Python_Args, Success); - if not Success then - Put_Line (Standard_Error, "winIDEA python script failed."); - OS_Exit (1); - end if; - Trace_Conv_Args (3) := - new String'(Workspace_Dir.all & '\' & "nexus_trace.bin"); - Trace_Conv_Args (6) := new String'("IAC1"); - Trace_Conv_Args (7) := new String'("main"); - Trace_Conv_Args (8) := new String'("IAC2"); - - else - Trace_Conv_Args (3) := new String'(Argument (4)); - Trace_Conv_Args (6) := new String'(Argument (5)); - Trace_Conv_Args (7) := new String'(Argument (6)); - Trace_Conv_Args (8) := new String'(Argument (7)); - end if; - - Spawn (Trace_Conversion_Path, Trace_Conv_Args, Success); - if not Success then - Put_Line (Standard_Error, "Error from trace conversion."); - OS_Exit (1); - end if; - - if Mode = Run then - declare - begin - Remove_Dir (Workspace_Dir.all, Recursive => True); - exception - -- Remove_Dir was failing when calling itself recursively after - -- removing the contents of the directory, but a simple use - -- of Remove_Dir after that failure, sould succeed. Thus, this - -- delay and try once more. Big improvement. ??? - when Directory_Error => - Put_Line ("Try remove_dir again."); - delay 3.0; - Remove_Dir (Workspace_Dir.all, Recursive => True); - end; - end if; - OS_Exit (0); -end isys_drv; diff --git a/tools/gnatcov/trace_adapters/nexus/isys_trace.py b/tools/gnatcov/trace_adapters/nexus/isys_trace.py deleted file mode 100644 index 37197d99d..000000000 --- a/tools/gnatcov/trace_adapters/nexus/isys_trace.py +++ /dev/null @@ -1,63 +0,0 @@ -import sys -proc_id = sys.argv [1] -executable = sys.argv [2] - -import isystem.connect as ic - -cmgr = ic.ConnectionMgr() -cmgr.connectMRU('.\workspace\min' + proc_id + '.xjrf') - -traceDoc = ic.CTraceController (cmgr, 'min' + proc_id + '.trd', 'w') - -traceDoc.select ('Everything Individual Branch') - -loader = ic.CLoaderController (cmgr) -executer = ic.CExecutionController (cmgr) - -if proc_id == "5554": - executer.resetAndRun (ic.CExecutionController.TOUT_1s) - executer.stop () -elif proc_id == "5634": - executer.reset () - executer.stop () - MPCCtrl = ic.CMPC5xxxController (cmgr) - TLB = MPCCtrl.getTLB (0) - TLB.m_dwMAS0 = 0x10030000 - TLB.m_dwMAS1 = 0xC0000400 - TLB.m_dwMAS2 = 0x40000008 - TLB.m_dwMAS3 = 0x4000003F - TLB.m_dwMAS4 = 0x00030413 - TLB.m_dwMAS5 = 0x00000000 - MPCCtrl.setTLB (0, TLB) -else: - print "Unknown processor ID value: " + proc_id - exit (1) - -downloadConfig = ic.CDownloadConfiguration () -downloadConfig.setCodeOffset (0).setSymbolsOffset (0). \ - setUsedInFullDownload (True). \ - setDownloadFileFormat (ic.CDownloadConfiguration.ftELF); - -dbg = ic.CDebugFacade(cmgr) -# dbg.download() -loader.targetDownload (downloadConfig, executable, -' LoadSymbols(Global) LoadZeros(0) LoadDwarfSection(1) ReverseBitFields(0) DumpELFHeaders(0) LoadCode(Virtual) CallStack(Automatic) MergeTypes(0) GCC_ARM_double_Format(Swapped) RemoveOptimizedLines(1) InsertInlinedFunctions(0) IgnoreNonStatementLines(1) ') -isyminfo = dbg.getSymbolInfo (ic.IConnectDebug.fMonitor | - ic.IConnectDebug.gafExpression, '_start') -dbg.gotoAddress (0, isyminfo.getAddress () ) -isyminfo = dbg.getSymbolInfo (ic.IConnectDebug.fMonitor | - ic.IConnectDebug.gafExpression, '_after_main') - -traceDoc.start () -executer.runUntilAddress (0, isyminfo.getAddress () ) -executer.waitUntilStopped () - -formatter = ic.CTraceBinExportFormat () -formatter.setTraceItemFlags (0) -formatter.setHeader (False) \ - .addTraceItem (ic.CTraceBinExportFormat.EOCDItem) -exportCfg = ic.CTraceExportConfig () -exportCfg.setFileName ('nexus_trace.bin').setFormatter (formatter) -traceDoc.exportData (exportCfg) - -cmgr.disconnect (ic.IConnect.dfCloseServerUnconditional | ic.IConnect.dfCloseAutoSaveNone) diff --git a/tools/gnatcov/trace_adapters/nexus/min5554.trd b/tools/gnatcov/trace_adapters/nexus/min5554.trd deleted file mode 100755 index 56918eb64a483911463f9193dcab9b2ea7292e27..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 800256 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

3rJX`5#CaFa9*I-Xk0i;h^n+|M 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%0DltjrvQH%@Mi#j7Vzf)e;)7`0DlqimjHhm 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 LU;cXzJ@Eel6W8`r diff --git a/tools/gnatcov/trace_adapters/nexus/min5554.xjrf b/tools/gnatcov/trace_adapters/nexus/min5554.xjrf deleted file mode 100755 index fae31f3db..000000000 --- a/tools/gnatcov/trace_adapters/nexus/min5554.xjrf +++ /dev/null @@ -1,2899 +0,0 @@ - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1254453248 - - - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1254453248 - - JCGPGJKEPGFAMNAB - BPGPAMCJBOBBABEGLILNDMBDBBMHGPIM - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - 1 - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - JCGPGJKEPGFAMNAB - DKMJHAJIMPCCOPEFIDMFHPJJACLPMHMP - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - 1 - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - EIACDMJIPEFAMNAB - INFJBNAAEDPJJGEKIKLEBLLDJKDMNAFM - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - 1 - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - JCGPGJKEPGFAMNAB - BPGPAMCJBOBBABEGLILNDMBDBBMHGPIM - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - 1 - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - HASYST - 0 - 1254453248 - - 0 - - - False - nexus_trace.trd - - - 0 - min5554.trd - - - 0 - 38 - 0 - 132 - 0 - nexus_trace.trd - - - - 363 - 0 - 504 - 0 - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 1 - 0 - 0 - 0 - -1 - - 0 - 404 - 0 - -1 - - 1 - 28 - 2 - -1 - - 1 - 227 - File - 10 - 7 - - - 1 - 2 - 6 - -1 - - - 1 - 395 - View - 10 - 8 - - - 1 - 0 - 6 - -1 - - - - 1 - 2 - 6 - -1 - - - 1 - 200 - Project Workspace - 0 - 1 - - - 1 - 5 - 6 - -1 - - - 1 - 700 - 1 - -2 - - - 1 - 0 - 6 - -1 - - - - 1 - 5 - 6 - -1 - - - 0 - 555 - 0 - -1 - - 1 - 200 - Output - 0 - 0 - - - 1 - 5 - 6 - -1 - - - 1 - 640 - DocWnd - 0 - 21 - - min5554.trd - - - - 1 - 0 - 6 - -1 - - - - 1 - 0 - 6 - -1 - - - - - - - True - True - - - - False - - - - 0 - - - 1 - - - 0 - 0 - 1 - 1 - 1 - 1 - 1 - - - 0 - 0 - - - - -1 - 0 - - - 0 - 0 - - main - 0 - 0 - 1 - 0 - 1 - True - 0 - 0 - main - 0 - False - 0 - - -1 - 0 - - - - False - False - False - history.txt - True - False - True - 0 - True - False - True - - - 0 - 1 - 1 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 1 - - DEFAULT - 0 - 0 - - 0 - - - - - 0 - - - True - True - True - True - symbols.txt - True - True - - - 0 - 1 - 0 - True - 1 - 2 - False - False - False - False - False - 0 - 1 - 0 - 0 - False - True - 256 - : - 1 - _ - 0 - 0 - 0.0000100000000000 - - - 0 - - - - False - True - 1 - False - 200 - True - False - True - False - True - False - False - - 0 - 0 - 0 - 0 - 1 - - - - 1 - - 0 - 0 - 1 - - - - 0 - 0 - 0 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - - AAABACADAEAFAGAHAIAJAKALAMANAOAPBABBBCBDBEBFBGBHBIBJBKBLBMBNBOBP - 0 - - - 1 -

0
- - - 0 - True - - - - -1 - 0 - - - <__> - 0 - 0 - 0 - - - - <__> - 0 - 0 - 0 - - - - 0 - 0 - - - - - 0 - - - - - - - - - - - - - - - - - 0 - 1 - 1 - - - - - - - - - - 0 - 0 - - - - - - Build 9.11.87 - - - - 0 - 0 - - - 1 - 0 - 1 - 0 - 1 - - - - - - - - - - - - - - - 0 - - - 2 - - - 0 - 1 - 0 - 0 - 2 - 0 - - - -1 - - 0 - - 0 - 0 - 9600 - COM1 - 8 - 0 - 0 - 0 - 0 - 24 - 80 - 500 - 0 - 1 - 0 - - - - - 0 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - - - <_166> - Tasking - - - GCC - - - FALSE - - - FALSE - - FALSE - FALSE - - - IAR - - - GreenHills - FALSE - - - - - 1 - 1 - True - 1 - 0 - 0 - 1 - 0 - 0 - False - False - True - 16 - - 100 - 1 - True - - - - - - - - - - - <__> - Files - 4 - - - - - - - - - - - - - <_76946E39-78E2-4625-9BF0-751C4C11A09F> - - - Default - false - 5544 - - - - - - - true - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1254453248 - - - 1 - 1 - 1 - 0 - 0 - 0 - 0 - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1254453248 - - - - - - 0 - - 0 - 0 - - 1 - - - 0.0000000000000000 - 0 - 0 - - 0 - - - - - - - - 0 - 0 - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - - <_32bit type="Integer">0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 -
- 0 - 0 - PP - 0 - 0 - AAAAAAAAAAAAAAAA - 0 - 0 - 0 - 0 -
- - 0 -
- 0 - PP - 0 - 0 - AAAAAAAAAAAAAAAA - 0 - 0 - 0 -
- - 0 - 2 - 0 - 0xFFFFFFFF - 0 - 0 - 0x00000000 - - - 0 - 2 - 0 - 0xFFFFFFFF - 0 - 0 - 0x00000000 - - - 0 - 2 - 0 - 0xFFFFFFFF - 0 - 0 - 0x00000000 - - - 0 - 2 - 0 - 0xFFFFFFFF - 0 - 0 - 0x00000000 - - - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> -
- -
- - <__> -
- -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> -
- -
- - <__> -
- -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- -
- 0 - 0 - 0 - 0 -
- -
- 0 - 0 -
- -
- 0 - 0 - 0 - 0 -
- -
- 0 - 0 -
- -
- 0 - 0 - 0 - 0 -
- -
- 0 - 0 -
- -
- 0 - 0 - 0 - 0 -
- -
- 0 - 0 -
- - <__> - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> -
- -
- - <__> -
- -
- -
- - <__> - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> -
- -
- - <__> -
- -
- -
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - -
-
-
- - - 0 - - - 0 - - - - 16000 - -
- - - 1 - 0 - 0 - 0 - - - - - AIN0 - - - AIN1 - - - AOUT0 - - - AOUT1 - - - DIN0 - - - DIN1 - - - DIN2 - - - DIN3 - - - DIN4 - - - DIN5 - - - DIN6 - - - DIN7 - - - DOUT0 - - - DOUT1 - - - DOUT2 - - - DOUT3 - - - DOUT4 - - - DOUT5 - - - DOUT6 - - - DOUT7 - - - TRUE - 16 - 1 - FALSE - 1/1 - Internal - FALSE - CLK - FALSE - - TRUE - 1 - - 0 - 0 - Full - - - - TRUE - 1 - - 0 - 0 - Full - - - - Manual - 0 - - 0 - 0 - Full - - - - Manual - 0 - - 0 - 0 - Full - - - - TRUE - - - TRUE - - - TRUE - - - TRUE - - - TRUE - - - TRUE - - - TRUE - - - TRUE - - - Manual - FALSE - - - Manual - FALSE - - - Manual - FALSE - - - Manual - FALSE - - - Manual - FALSE - - - Manual - FALSE - - - Manual - FALSE - - - Manual - FALSE - - - 0 - 0 - Full - - - - - 1 - 1 - TRUE - TRUE - TRUE - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 1 - 1 - TRUE - TRUE - TRUE - - - - - - 1 - 1 - TRUE - TRUE - TRUE - - - - - - 1 - 1 - TRUE - TRUE - TRUE - - - - - - 1 - 1 - TRUE - TRUE - TRUE - - - - - -
0
- 0 - False - 0 - 0 - 0 - 0 - 0 -
- - 0 - - AAAAAAAA - 0 - - - 1 - #g_TConn - 1 - - #g_TWBuffer - 1 - 0 - - - #g_TRBuffer - 1 - 0 - - - - - 0 - 2 - 0 - 0 - 0 - - - 0 - - - -
- - - 100% - 1 ns - 0 - 0 - - 0 - 100 % - 0 - 1 - 256 MB - 1 - 1 - 0 - 1 - 0 - - - - 1 - - - 0 - - - 0 - - - 1 - - -
- - 87 - 0 - 9 - 1 - 11 - 151716014 - - - 0 - 0 - 0 - 127 - 1 - 11 - 7 - - - <_55xx_AllowFLASHPgmOnlyDuringDL type="Integer">0 - <_55xx_EnableShadowMemoryProgramming type="Integer">0 - <_55xx_InitMMU type="Integer">0 - <_55xx_InitMMU_VLE type="Integer">0 - <_55xx_InitRAM type="Integer">2 - <_55xx_LowPowerDebug type="Integer">0 - <_55xx_LowPowerDebug_Run type="Integer">0 - <_55xx_LowPowerDebug_StopBefore type="Integer">0 - <_55xx_Mode type="Integer">0 - <_55xx_NexusEBI type="Integer">0 - <_55xx_Password type="Buffer">AAAAAAAAAAAAAAAA - <_55xx_StopTimerDuringStep type="Integer">0 - <_55xx_StopWhenReleasedFromReset type="Integer">0 - <_55xx_UseBDMMemAccessWhenStopped type="Integer">0 - <_55xx_UsePassword type="Integer">0 - <_55xx_UseTrapForSWBPsinPowerPCMode type="Integer">0 - <_83xx_RCWH type="Integer">0 - <_83xx_RCWL type="Integer">0 - <_83xx_RCWOverride type="Integer">0 - True - 0 - False - True - 0 - 0 - 0 - 67108864 - -1048320 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 13 - 114 - 0 - 0 - 4000 - 0 - 0 - 0 - 10 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 5 - 1 - 1 - 0 - 0 - 100 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - - - -
0
- 0 - 0 - 0 - 0 - 0 - 0 - 0 -
- - 0 - 1 - 0 - 0 - -
0
- 0 - 0 - 0 -
-
-
- - -
0
- 0 - 0 -
- -
0
- 0 - 0 -
- -
0
- 0 - 0 -
- -
0
- 0 - 0 -
-
- - 0 - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0 - 1000 - 0 - 0 - 500 - 0 - 0 - 0 - 0 - 1 - 0 - - - 1 - 0 - 3300 - False - 0 - 1 - 1 - 1700 - - 0 - 1700 - - - 0 - 1700 - - - 0 - 1700 - - - 0 - 1700 - - - - 0 - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - -
- - 1 - 2 - 2 - - - 0 - 0 - 3 - 1 - 0 - 5313 - - - - - 1 - 0 - -
-
-
-
- diff --git a/tools/gnatcov/trace_adapters/nexus/min5554.xqrf b/tools/gnatcov/trace_adapters/nexus/min5554.xqrf deleted file mode 100755 index 48d7f6d11..000000000 --- a/tools/gnatcov/trace_adapters/nexus/min5554.xqrf +++ /dev/null @@ -1,103 +0,0 @@ - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1254453248 - - 0 - - INC - ASM - OBJ - - - 1 - 1 - C;CPP - - - - - - 1 - OBJ - 0 - True - - - True - - False - 0 - - 0 - - - H - - OBJ;LIB - - \ - - - - - - - - - - - - 0 - 0 - - 0 - - - - - 0 - - - - - - - No filter - - - - True - False - - True - - - True - False - - - - - - False - - 0 - - - - - False - - - 38 - No - - - - - diff --git a/tools/gnatcov/trace_adapters/nexus/min5634.trd b/tools/gnatcov/trace_adapters/nexus/min5634.trd deleted file mode 100755 index 1f7b9124a20f901324763358ab7a34109f1f6966..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 32204 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 diff --git a/tools/gnatcov/trace_adapters/nexus/min5634.xjrf b/tools/gnatcov/trace_adapters/nexus/min5634.xjrf deleted file mode 100755 index 1cd6da095..000000000 --- a/tools/gnatcov/trace_adapters/nexus/min5634.xjrf +++ /dev/null @@ -1,3146 +0,0 @@ - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1254453248 - - - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1254453248 - - JKIMJGCJEIGEMNAB - DKMJHAJIMPCCOPEFIDMFHPJJACLPMHMP - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - 1 - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - JCGPGJKEPGFAMNAB - BPGPAMCJBOBBABEGLILNDMBDBBMHGPIM - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - 1 - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - EIACDMJIPEFAMNAB - INFJBNAAEDPJJGEKIKLEBLLDJKDMNAFM - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - 1 - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - JCGPGJKEPGFAMNAB - BPGPAMCJBOBBABEGLILNDMBDBBMHGPIM - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - 1 - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - CJBCBECLEJGEMNAB - FHHNEPMFFCMBOPEAKMLMIIBPDPIIGCMO - - 0 - -1 - 0 - - - 0 - 1 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - 5000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 0 - 3 - 0 - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 5000 - - - - 10000 - 0 - 10000 - 5000 - - - - - 10000 - 0 - 10000 - 0 - - - - 10000 - 0 - 10000 - 0 - - - - 1 - False - True - True - True - True - True - False - False - False - False - False - False - False - False - True - False - False - False - False - False - False - False - False - True - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAA - ABAAAAAAAAAAAAAA - False - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 35.0000000000000000 - 0 - - - 38.0000000000000000 - 0 - - - - - 0 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 50 - - - 0 - - - 0 - 1 - - - - 0.0000000000000000 - 0 - - - 20.0000000000000000 - 0 - - - 40.0000000000000000 - 0 - - - - - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - HASYST - 0 - 1254453248 - - 0 - - - False - - - - 0 - min5634.trd - - - ..\..\repositories\testsuite-run\Qualif\Ada\mcdc\Robustness\MultiLineDecisions\And\Return\tmp_test_andthen_0\workspace\min5554.trd - - - - 363 - 0 - 504 - 0 - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 0 - - - - - - - - - - - - - - - 1 - 0 - 0 - 0 - -1 - - 0 - 600 - 0 - -1 - - 1 - 28 - 2 - -1 - - 1 - 227 - File - 10 - 7 - - - 1 - 2 - 6 - -1 - - - 1 - 395 - View - 10 - 8 - - - 1 - 0 - 6 - -1 - - - - 1 - 2 - 6 - -1 - - - 1 - 200 - Project Workspace - 0 - 1 - - - 1 - 5 - 6 - -1 - - - 1 - 700 - 1 - -2 - - - 1 - 0 - 6 - -1 - - - - 1 - 5 - 6 - -1 - - - 0 - 200 - 0 - -1 - - 1 - 200 - Output - 0 - 0 - - - 1 - 5 - 6 - -1 - - - 1 - 640 - DocWnd - 0 - 21 - - min5634.trd - - - - 1 - 0 - 6 - -1 - - - - 1 - 0 - 6 - -1 - - - - - - - True - True - - - - False - - - - 0 - - - 1 - - - 0 - 0 - 1 - 1 - 1 - 1 - 1 - - - 0 - 0 - - - - -1 - 0 - - - 0 - 0 - - main - 0 - 0 - 1 - 0 - 1 - True - 0 - 0 - main - 0 - False - 0 - - -1 - 0 - - - - False - False - False - history.txt - True - False - True - 0 - True - False - True - - - 0 - 1 - 1 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 0 - 0 - - - 1 - - DEFAULT - 0 - 0 - - 0 - - - - - 0 - - - True - True - True - True - symbols.txt - True - True - - - 0 - 1 - 0 - True - 1 - 2 - False - False - False - False - False - 0 - 1 - 0 - 0 - False - True - 256 - : - 1 - _ - 0 - 0 - 0.0000100000000000 - - - 0 - - - - False - True - 1 - False - 200 - True - False - True - False - True - False - False - - 0 - 0 - 0 - 0 - 1 - - - - 1 - - 0 - 0 - 1 - - - - 0 - 0 - 0 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - - AAABACADAEAFAGAHAIAJAKALAMANAOAPBABBBCBDBEBFBGBHBIBJBKBLBMBNBOBP - 0 - - - 1 -
0
- - - 0 - True - -
- - -1 - 0 - - - <__> - 0 - 0 - 0 - - - - <__> - 0 - 0 - 0 - - - - 0 - 0 - -
- - - 0 - - - - - - - - - - - - - - - - - 0 - 1 - 1 - - - - - - - - - - 0 - 0 - - - - - - Build 9.11.87 - - - - 0 - 0 - - - 1 - 0 - 1 - 0 - 1 - - - - - - - - - - - - - - - 0 - - - 2 - - - 0 - 1 - 0 - 0 - 2 - 0 - - - -1 - - 0 - - 0 - 0 - 9600 - COM1 - 8 - 0 - 0 - 0 - 0 - 24 - 80 - 500 - 0 - 1 - 0 - - - - - 0 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - - - <_166> - Tasking - - - GCC - - - FALSE - - - FALSE - - FALSE - FALSE - - - IAR - - - GreenHills - FALSE - - - - - 1 - 1 - True - 1 - 0 - 0 - 1 - 0 - 0 - False - False - True - 16 - - 100 - 1 - True - - - - - - - - - - - <__> - Files - 4 - - - - - - - - - - -
- - <_76946E39-78E2-4625-9BF0-751C4C11A09F> - - - Default - false - 5544 - - - - -
-
- - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1254453248 - - - 1 - 1 - 1 - 0 - 0 - 0 - 0 - - - min5634 - Debug - - - - - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1254453248 - - - - - - 0 - - 0 - 0 - - 1 - - - 0.0000000000000000 - 0 - 0 - - 0 - - - - - - - - 0 - 0 - - - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 1 - 1 - 0 - 2 - 0 - 0 - 0 - 0 - 2 - 0 - - <_32bit type="Integer">0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - - - 0 -
- 0 - 0 - PP - 0 - 0 - AAAAAAAAAAAAAAAA - 0 - 0 - 0 - 0 -
- - 0 -
- 0 - PP - 0 - 0 - AAAAAAAAAAAAAAAA - 0 - 0 - 0 -
- - 0 - 2 - 0 - 0xFFFFFFFF - 0 - 0 - 0x00000000 - - - 0 - 2 - 0 - 0xFFFFFFFF - 0 - 0 - 0x00000000 - - - 0 - 2 - 0 - 0xFFFFFFFF - 0 - 0 - 0x00000000 - - - 0 - 2 - 0 - 0xFFFFFFFF - 0 - 0 - 0x00000000 - - - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> -
- -
- - <__> -
- -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> -
- -
- - <__> -
- -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- -
- 0 - 0 - 0 - 0 -
- -
- 0 - 0 -
- -
- 0 - 0 - 0 - 0 -
- -
- 0 - 0 -
- -
- 0 - 0 - 0 - 0 -
- -
- 0 - 0 -
- -
- 0 - 0 - 0 - 0 -
- -
- 0 - 0 -
- - <__> - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> -
- -
- - <__> -
- -
- -
- - <__> - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> - 0 - 0x00000000 - 0xFFFFFFFF - - - - <__> -
- -
- - <__> -
- -
- -
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - - 2 - 1 - 0 - 0 - 0 - - - 2 - 0 - 0 - 0 - 0 - - - 2 -
0
- 0 - 0 -
- - 2 -
0
- 0 - 0 -
-
- - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - -
-
-
- - - 0 - - - 0 - - - - 16000 - -
- - - 1 - 0 - 0 - 0 - - - - - AIN0 - - - AIN1 - - - AOUT0 - - - AOUT1 - - - DIN0 - - - DIN1 - - - DIN2 - - - DIN3 - - - DIN4 - - - DIN5 - - - DIN6 - - - DIN7 - - - DOUT0 - - - DOUT1 - - - DOUT2 - - - DOUT3 - - - DOUT4 - - - DOUT5 - - - DOUT6 - - - DOUT7 - - - TRUE - 16 - 1 - FALSE - 1/1 - Internal - FALSE - CLK - FALSE - - TRUE - 1 - - 0 - 0 - Full - - - - TRUE - 1 - - 0 - 0 - Full - - - - Manual - 0 - - 0 - 0 - Full - - - - Manual - 0 - - 0 - 0 - Full - - - - TRUE - - - TRUE - - - TRUE - - - TRUE - - - TRUE - - - TRUE - - - TRUE - - - TRUE - - - Manual - FALSE - - - Manual - FALSE - - - Manual - FALSE - - - Manual - FALSE - - - Manual - FALSE - - - Manual - FALSE - - - Manual - FALSE - - - Manual - FALSE - - - 0 - 0 - Full - - - - - 1 - 1 - TRUE - TRUE - TRUE - - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 1 - 1 - TRUE - TRUE - TRUE - - - - - - 1 - 1 - TRUE - TRUE - TRUE - - - - - - 1 - 1 - TRUE - TRUE - TRUE - - - - - - 1 - 1 - TRUE - TRUE - TRUE - - - - - -
0
- 0 - False - 0 - 0 - 0 - 0 - 0 -
- - 0 - - AAAAAAAA - 0 - - - 1 - #g_TConn - 1 - - #g_TWBuffer - 1 - 0 - - - #g_TRBuffer - 1 - 0 - - - - - 0 - 2 - 0 - 0 - 0 - - - 0 - - - -
- - - 100% - 1 ns - 0 - 0 - - 0 - 100 % - 0 - 0 - 256 MB - 1 - 1 - 0 - 1 - 0 - - - - 1 - - - 0 - - - 0 - - - 1 - - -
- - 87 - 0 - 9 - 1 - 11 - 151716014 - - - 50 - 50 - 0 - 127 - 1 - 11 - 7 - - - <_55xx_AllowFLASHPgmOnlyDuringDL type="Integer">0 - <_55xx_EnableShadowMemoryProgramming type="Integer">0 - <_55xx_InitMMU type="Integer">0 - <_55xx_InitMMU_VLE type="Integer">0 - <_55xx_InitRAM type="Integer">2 - <_55xx_LowPowerDebug type="Integer">0 - <_55xx_LowPowerDebug_Run type="Integer">0 - <_55xx_LowPowerDebug_StopBefore type="Integer">0 - <_55xx_Mode type="Integer">0 - <_55xx_NexusEBI type="Integer">0 - <_55xx_Password type="Buffer">AAAAAAAAAAAAAAAA - <_55xx_StopTimerDuringStep type="Integer">0 - <_55xx_StopWhenReleasedFromReset type="Integer">0 - <_55xx_UseBDMMemAccessWhenStopped type="Integer">0 - <_55xx_UsePassword type="Integer">0 - <_55xx_UseTrapForSWBPsinPowerPCMode type="Integer">0 - <_83xx_RCWH type="Integer">0 - <_83xx_RCWL type="Integer">0 - <_83xx_RCWOverride type="Integer">0 - True - 0 - False - True - 0 - 0 - 0 - 67108864 - -1048320 - 0 - - - - 0 - 0 - 0 - 0 - 0 - 13 - 114 - 0 - 10000 - 4000 - 0 - 0 - 0 - 10 - 1 - 1 - 0 - 1 - 1 - 0 - 0 - 2 - 1 - 1 - 0 - 0 - 100 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - - - -
0
- 0 - 0 - 0 - 0 - 0 - 0 - 0 -
- - 0 - 1 - 0 - 0 - -
0
- 0 - 0 - 0 -
-
-
- - -
0
- 0 - 0 -
- -
0
- 0 - 0 -
- -
0
- 0 - 0 -
- -
0
- 0 - 0 -
-
- - 0 - - 0 - - - 0 - - - 0 - - - 0 - - - - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - - 0 - 1 - 0 - 0 - 0 - 1 - 0 - - - 0 - 0 - 1000 - 0 - 0 - 500 - 0 - 0 - 0 - 2 - 1 - 0 - - - 1 - 0 - 3300 - False - 0 - 1 - 1 - 1500 - - 0 - 1500 - - - 0 - 1500 - - - 0 - 1500 - - - 0 - 1500 - - - - 0 - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - - AAAAAAAAAAAAAAAA - - -
- - 1 - 2 - 2 - - - 0 - 0 - 3 - 1 - 0 - 5313 - - - - - 1 - 0 - -
-
-
-
-
diff --git a/tools/gnatcov/trace_adapters/nexus/min5634.xqrf b/tools/gnatcov/trace_adapters/nexus/min5634.xqrf deleted file mode 100755 index e45cd6c84..000000000 --- a/tools/gnatcov/trace_adapters/nexus/min5634.xqrf +++ /dev/null @@ -1,130 +0,0 @@ - - - BF283F24-70B9-4f97-86E6-0AD5BAAE9E01 - 0 - 1 - - - 1254453248 - - 0 - - INC - ASM - OBJ - - - 1 - 1 - C;CPP - - - - - - 1 - OBJ - 0 - True - - - True - - False - 0 - - 0 - - - H - - OBJ;LIB - - \ - - - - - - - - - - - - 0 - 0 - - 0 - - - - - 0 - - - - - - min5634 - Debug - No filter - - - - True - False - - True - - - True - False - - - min5634 - Debug - - $(EDNAME) - $(EDNAME) - - - Source files - - - - - - False - - 0 - - - - - False - - - 38 - No - - - - - - - False - - 0 - - - - - False - - - 38 - No - - - - - diff --git a/tools/gnatcov/trace_adapters/nexus/nexus.gpr b/tools/gnatcov/trace_adapters/nexus/nexus.gpr deleted file mode 100644 index daa57938f..000000000 --- a/tools/gnatcov/trace_adapters/nexus/nexus.gpr +++ /dev/null @@ -1,17 +0,0 @@ -with "../../gnatcov"; - -project Nexus is - - for Main use ("nexus_trace_gen.adb", "isys_drv.adb"); - for Object_Dir use "obj"; - for Exec_Dir use "."; - - package Compiler is - for Default_Switches ("Ada") use ("-g", "-gnatyy", "-gnat12"); - end Compiler; - - package Linker is - for Required_Switches use Gnatcov.Linker'Required_Switches; - end Linker; - -end Nexus; diff --git a/tools/gnatcov/trace_adapters/nexus/nexus_rep.ads b/tools/gnatcov/trace_adapters/nexus/nexus_rep.ads deleted file mode 100755 index 07741e8a9..000000000 --- a/tools/gnatcov/trace_adapters/nexus/nexus_rep.ads +++ /dev/null @@ -1,223 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- 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. -- ------------------------------------------------------------------------------- - --- This package provides types and routines for representing and --- manipulating data specified by the Nexus Forum standard (IEEE-ISTO 5001), --- describing a debug interface for embedded processors. --- --- This is a very early version of this package and is subject to --- significant changes as it is adapted to be used with more --- HW implementations of the Nexus standard. --- --- E.g., it is currently strongly influenced by its application to program --- trace capabilites provided by the Freescale NZ63C module on the MPC5554. --- TCODE values are those implemented by the NZ63C as well as the packets --- included in messages, and the ranges of bit sizes for each packet. - -package Nexus_Rep is - - -- Nexus trace data comprises "messages" containing a variable - -- number of "packets" of data, some of which are fixed in size, and some - -- of variable sizes. Each message contains a TCODE value indicating - -- the type of message, and determining which packets are included in - -- the message. - -- - -- A Nexus interface streams out these messages, and here we represent - -- such a stream of messages as a list of record values. The Nexus record - -- is a discrminated type, with the TCODE as the discriminant. All - -- packets are represented by a 32 bit modular type. There are some - -- Nexus packets which can be up to 64 bits in length -- these are - -- represented by a pair of 32 bit packet components. - - type Nexus_Packet_T is mod 2 ** 32; - subtype Nexus_Tcode_T is Nexus_Packet_T range 0 .. 33; - - type Nexus_Message_Rec_T; - type Nexus_Message_Rec_Ptr_T is access all Nexus_Message_Rec_T; - - Debug_Status : constant Nexus_Tcode_T := 0; - Ownership_Trace_Message : constant Nexus_Tcode_T := 2; - Prog_Trace_Direct_Branch_Message : constant Nexus_Tcode_T := 3; - Prog_Trace_Indirect_Branch_Message : constant Nexus_Tcode_T := 4; - Data_Trace_Data_Write_Message : constant Nexus_Tcode_T := 5; - Data_Trace_Data_Read_Message : constant Nexus_Tcode_T := 6; - Error_Message : constant Nexus_Tcode_T := 8; - Prog_Trace_Direct_Branch_Message_Sync : constant Nexus_Tcode_T := 11; - Prog_Trace_Indirect_Branch_Message_Sync : constant Nexus_Tcode_T := 12; - Data_Trace_Data_Write_Message_Sync : constant Nexus_Tcode_T := 13; - Data_Trace_Data_Read_Message_Sync : constant Nexus_Tcode_T := 14; - Watchpoint_Message : constant Nexus_Tcode_T := 15; - Resource_Full_Message : constant Nexus_Tcode_T := 27; - Prog_Trace_Indirect_Branch_Hist_Message : constant Nexus_Tcode_T := 28; - Prog_Trace_Indirect_Branch_Hist_Message_Sync : constant Nexus_Tcode_T := 29; - Prog_Trace_Program_Correlation_Message : constant Nexus_Tcode_T := 33; - - type Debug_Status_Rec is record - STATUS : Nexus_Packet_T; - end record; - type Ownership_Trace_Message_Rec is record - PROCESS : Nexus_Packet_T; - end record; - type Prog_Trace_Direct_Branch_Message_Rec is record - I_CNT : Nexus_Packet_T; - end record; - type Prog_Trace_Indirect_Branch_Message_Rec is record - I_CNT : Nexus_Packet_T; - U_ADDR : Nexus_Packet_T; - end record; - type Data_Trace_Data_Write_Message_Rec is record - DSIZ : Nexus_Packet_T; - U_ADDR : Nexus_Packet_T; - DATA_Lo : Nexus_Packet_T; - DATA_Hi : Nexus_Packet_T; - end record; - type Data_Trace_Data_Read_Message_Rec is record - DSIZ : Nexus_Packet_T; - U_ADDR : Nexus_Packet_T; - DATA_Lo : Nexus_Packet_T; - DATA_Hi : Nexus_Packet_T; - end record; - type Error_Message_Rec is record - ECODE : Nexus_Packet_T; - end record; - type Prog_Trace_Direct_Branch_Message_Sync_Rec is record - I_CNT : Nexus_Packet_T; - F_ADDR : Nexus_Packet_T; - end record; - type Prog_Trace_Indirect_Branch_Message_Sync_Rec is record - I_CNT : Nexus_Packet_T; - F_ADDR : Nexus_Packet_T; - end record; - type Data_Trace_Data_Write_Message_Sync_Rec is record - DSZ : Nexus_Packet_T; - F_ADDR : Nexus_Packet_T; - DATA_Lo : Nexus_Packet_T; - DATA_Hi : Nexus_Packet_T; - end record; - type Data_Trace_Data_Read_Message_Sync_Rec is record - DSZ : Nexus_Packet_T; - F_ADDR : Nexus_Packet_T; - DATA_Lo : Nexus_Packet_T; - DATA_Hi : Nexus_Packet_T; - end record; - type Watchpoint_Message_Rec is record - WPHIT : Nexus_Packet_T; - end record; - type Resource_Full_Message_Rec is record - RCODE : Nexus_Packet_T; - RDATA : Nexus_Packet_T; - end record; - type Prog_Trace_Indirect_Branch_Hist_Message_Rec is record - I_CNT : Nexus_Packet_T; - U_ADDR : Nexus_Packet_T; - HIST : Nexus_Packet_T; - end record; - type Prog_Trace_Indirect_Branch_Hist_Message_Sync_Rec is record - I_CNT : Nexus_Packet_T; - F_ADDR : Nexus_Packet_T; - HIST : Nexus_Packet_T; - end record; - type Prog_Trace_Program_Correlation_Message_Rec is record - EVCODE : Nexus_Packet_T; - I_CNT : Nexus_Packet_T; - HIST : Nexus_Packet_T; - end record; - - type Nexus_Message_Rec_T (Tcode : Nexus_Tcode_T) is record - SRC : Nexus_Packet_T; - case Tcode is - when Debug_Status => - Debug_Status_V - : Debug_Status_Rec; - when Ownership_Trace_Message => - Ownership_Trace_Message_V - : Ownership_Trace_Message_Rec; - when Prog_Trace_Direct_Branch_Message => - Prog_Trace_Direct_Branch_Message_V - : Prog_Trace_Direct_Branch_Message_Rec; - when Prog_Trace_Indirect_Branch_Message => - Prog_Trace_Indirect_Branch_Message_V - : Prog_Trace_Indirect_Branch_Message_Rec; - when Data_Trace_Data_Write_Message => - Data_Trace_Data_Write_Message_V - : Data_Trace_Data_Write_Message_Rec; - when Data_Trace_Data_Read_Message => - Data_Trace_Data_Read_Message_V - : Data_Trace_Data_Read_Message_Rec; - when Error_Message => - Error_Message_V - : Error_Message_Rec; - when Prog_Trace_Direct_Branch_Message_Sync => - Prog_Trace_Direct_Branch_Message_Sync_V - : Prog_Trace_Direct_Branch_Message_Sync_Rec; - when Prog_Trace_Indirect_Branch_Message_Sync => - Prog_Trace_Indirect_Branch_Message_Sync_V - : Prog_Trace_Indirect_Branch_Message_Sync_Rec; - when Data_Trace_Data_Write_Message_Sync => - Data_Trace_Data_Write_Message_Sync_V - : Data_Trace_Data_Write_Message_Sync_Rec; - when Data_Trace_Data_Read_Message_Sync => - Data_Trace_Data_Read_Message_Sync_V - : Data_Trace_Data_Read_Message_Sync_Rec; - when Watchpoint_Message => - Watchpoint_Message_V - : Watchpoint_Message_Rec; - when Resource_Full_Message => - Resource_Full_Message_V - : Resource_Full_Message_Rec; - when Prog_Trace_Indirect_Branch_Hist_Message => - Prog_Trace_Indirect_Branch_Hist_Message_V - : Prog_Trace_Indirect_Branch_Hist_Message_Rec; - when Prog_Trace_Indirect_Branch_Hist_Message_Sync => - Prog_Trace_Indirect_Branch_Hist_Message_Sync_V - : Prog_Trace_Indirect_Branch_Hist_Message_Sync_Rec; - when Prog_Trace_Program_Correlation_Message => - Prog_Trace_Program_Correlation_Message_V - : Prog_Trace_Program_Correlation_Message_Rec; - when 1 | 7 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 - | 24 | 25 | 26 | 30 | 31 | 32 => - null; - end case; - end record; - - subtype Nexus_N_Packets_T is Natural; - type Nexus_N_Packets_Arr_T is array (Nexus_Tcode_T) of Nexus_N_Packets_T; - Nexus_N_Packets_Array : constant Nexus_N_Packets_Arr_T := - (Debug_Status => 3, - Ownership_Trace_Message => 3, - Prog_Trace_Direct_Branch_Message => 3, - Prog_Trace_Indirect_Branch_Message => 4, - Data_Trace_Data_Write_Message => 5, - Data_Trace_Data_Read_Message => 5, - Error_Message => 3, - Prog_Trace_Direct_Branch_Message_Sync => 4, - Prog_Trace_Indirect_Branch_Message_Sync => 4, - Data_Trace_Data_Write_Message_Sync => 5, - Data_Trace_Data_Read_Message_Sync => 5, - Watchpoint_Message => 3, - Resource_Full_Message => 4, - Prog_Trace_Indirect_Branch_Hist_Message => 5, - Prog_Trace_Indirect_Branch_Hist_Message_Sync => 5, - Prog_Trace_Program_Correlation_Message => 5, - others => 0); - -- May not fit here perfectly, but these values are for the convenience - -- of routines which read a file representation of Nexus data that - -- includes a count of packets before each message (iSystem OCD data - -- in particular). - -end Nexus_Rep; diff --git a/tools/gnatcov/trace_adapters/nexus/nexus_trace_gen.adb b/tools/gnatcov/trace_adapters/nexus/nexus_trace_gen.adb deleted file mode 100755 index 42da76dc6..000000000 --- a/tools/gnatcov/trace_adapters/nexus/nexus_trace_gen.adb +++ /dev/null @@ -1,1332 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- 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. -- ------------------------------------------------------------------------------- - --- This program generates a GNATcoverage trace file from data created --- by running a program on a target system under control of an iSystem --- probe, which collects NEXUS realtime program trace data from the target. --- --- This program is only intended to be called from the driver program --- isys_drv. The 2 programs, and the python program also called by --- isys_drv to run the target executable, may all be integrated eventually. --- Checking of errors from arguments or inputs is not thorough since this --- is not a user-run program. --- --- The program requires arguments on the command line naming the --- processor, the executable file, the nexus trace file (aka the --- On Chip Debug file), a history file name (or the argument --- "--nohist") and the name of the initialized qemu trace --- file which is to be filled in. Also, there are arguments --- that describe the HW trigger settings that were used when --- the traces were generated. These are the IAC register that --- was used for the start trigger, the address set in that IAC --- register, and the IAC register used for the stop tirgger or --- the constant '0' if no stop trigger was set. This trigger information --- is used for anchoring BTMs as Nexus tracing is turned on and --- off by the triggers. --- --- Currently this works only for 32 bit PowerPC Book E processors and --- presumption of that constraint is hard-coded in, in many places --- (particularly the 32 bit word size, machine code of 20, swap to --- little endian host). - -with Ada.Unchecked_Deallocation; -with Ada.Unchecked_Conversion; -with Ada.Characters.Handling; use Ada.Characters.Handling; - -with Ada.Command_Line; use Ada.Command_Line; -with Ada.Text_IO; use Ada.Text_IO; -with Interfaces; use Interfaces; -with Ada.Exceptions; use Ada.Exceptions; -with GNAT.OS_Lib; use GNAT.OS_Lib; -with System; use System; - -with System.Storage_Elements; use System.Storage_Elements; - -with GNATCOLL.Mmap; use GNATCOLL.Mmap; - -with Nexus_Rep; use Nexus_Rep; -with Isys2nex; use Isys2nex; - -with Binary_Files; use Binary_Files; -with Elf_Files; use Elf_Files; -with Elf_Common; use Elf_Common; -with Elf32; use Elf32; -with Arch; use Arch; -with Swaps; use Swaps; -with Traces; use Traces; -with Qemu_Traces; use Qemu_Traces; -with Traces_Files; use Traces_Files; -with Strings; use Strings; - -procedure Nexus_Trace_Gen is - - procedure Usage; - - procedure Usage is - procedure P (S : String) renames Put_Line; - begin - P ("usage: Nexus_Trace_Gen proc_id binary_file ocd_file" & - " --nohist|hist_file trace_file"); - P (" PT_Start_IAC_# PT_Start_Addr never|PT_Stop_IAC"); - end Usage; - - use GNAT.OS_Lib; - - Tracefile_Path : String_Access; - Histfile_Path : String_Access; - Executable_Filename : String_Access; - Processor_ID : String_Access; - - OCD_Filename : String_Access; - -- On Chip Debug file: file containing the Nexus trace messages. - - Fd : File_Descriptor; - Executable_File : Elf_File; - Ehdr : Elf_Ehdr; - Text_Shdr_Idx : Elf_Half; - Text_Shdr_Ptr : Elf_Shdr_Acc; - Text_Section_Len : Elf_Addr; - Text_First_Addr : Unsigned_32; - -- Exe_Sym : Elf_Sym; - - type Watchpoint_T is mod 2 ** 8; - Watchpoints_Seen : Watchpoint_T; - - J : Positive; - Under_OK : Boolean; - PT_Start_IAC_Bit : Watchpoint_T; - PT_Stop_IAC_Bit : Watchpoint_T; - PT_Start_Address : Unsigned_32; - PT_Running : Boolean; - -- Vars used for trace start address options procesing and use. - - type Insns_Array is array (Positive range <>) of Unsigned_32; - Insns_Ptr : access Insns_Array; - N_Insns : Positive; - Insn_Count : Natural; - - Number_Exception_Vectors : Natural := 0; - -- In the future, the exeption vectors may be specified - -- on the command line. For now, the name of one is hard - -- to '_jump_to_handler' and if that is found in the target - -- executable, Number_Excetion_Vectors is set to 1. - Exception_Vec_Addr : Unsigned_32; - Impossible_PC : constant Unsigned_32 := 1; - type IBM_Type_Type is (Branch_Insn, Exception_Occur); - IBM_Type : IBM_Type_Type; - - EV_Code : Nexus_Packet_T; - - ICNT_Adj_Val : Nexus_Packet_T; - ICNT_Proc_Adj : Nexus_Packet_T; - function ICNT_Adj return Nexus_Packet_T; - -- The Insrtruction Count value returned in various BT messages needs - -- some adjustement to consistently include all the intrsuctions since - -- that last BT message (or since PT is started). - -- - -- One source of difference between the value returned and the value - -- desired, is differences in implementations of Nexus modules. E.g. the - -- value returned by the module on the 5554 is one short (as if the - -- branch instruction is not counted), whereas the value returned by - -- the 5634 module is the desired count. The variable ICNT_Proc_Adj is - -- set to the processor specific adjustment that is needed. - -- - -- The processor specific adjustment is always needed, but other - -- adjustments result from dynamic events, and only apply to the - -- next BT message that occurs. ICNT_Adj_Val is the actual value - -- that should be applied to the next BT message, and it is the - -- value that is returned by the function ICNT_Adj. ICNT_Adj also - -- resets ICNT_Adj_Val to ICNT_Proc_Adj. - -- - -- Thus, the events that require changes to the adjustment value - -- modify ICNT_Adj_Val, and the function ICNT_Adj is called during - -- BT message processing to get the adjustment needed. - -- - -- One dynamic event is the startup of PT message generation, - -- either when the CPU starts (if DC1 enabling is used -- not allowed - -- at this point) or when the watchpoint programmed into the Watchpoint - -- Trigger register is hit -- this is discovered in Watchpoint Message - -- processing. The ICNT in the initial BTM after this is one to low. - -- - -- The other dynamic event is overflow of the instruction counter between - -- BT messages. This is indicated by a Resource Full message. - - function ICNT_Adj return Nexus_Packet_T is - R : Nexus_Packet_T := ICNT_Adj_Val; - begin - ICNT_Adj_Val := ICNT_Proc_Adj; - return R; - end ICNT_Adj; - - type Insn_Flags_T is record - Been_Executed : Boolean; - Is_Branch : Boolean; - Br_Taken : Boolean; - Br_Not_Taken : Boolean; - Historical : Boolean; - end record; - type Insn_Flags_Array_T is array (Positive range <>) of Insn_Flags_T; - Insn_Flags : access Insn_Flags_Array_T; - - Op_Code : Unsigned_32; - Ext_Op_Code : Unsigned_32; - Insn_Idx : Positive; - Idx2 : Positive; - Block_Begin_Idx : Positive; - Block_End_Idx : Positive; - Trace_Start_Idx : Positive; - New_Addr : Unsigned_32; - Br_Insn : Unsigned_32; - Br_Addr : Unsigned_32; - AA_Bit : Unsigned_32; - U_Addr : Unsigned_32; - Last_Indirect_Or_Sync_Addr : Unsigned_32 := 0; - - Nexus_Msg : Nexus_Message_Rec_Ptr_T; - - Exe_Exception : exception; - procedure Chk_Exe (Msg : String); - procedure Chk_Exe (Msg : String) is - begin - if Get_Status (Executable_File) /= Status_Ok then - raise Exe_Exception with Msg; - end if; - end Chk_Exe; - - procedure Load_Section - (File : Elf_File; - Shdr : Elf_Half; - Addr : System.Address); - -- Load the SHDR section from an ELF FILE at ADDR. This procedure is a - -- compatibility layer between legacy code and the new ELF-loading API. - - ------------------ - -- Load_Section -- - ------------------ - - procedure Load_Section - (File : Elf_File; - Shdr : Elf_Half; - Addr : System.Address) - is - Section : Loaded_Section := - Load_Section (File, Section_Index (Shdr)); - Section_Size : constant Natural := Natural (Size (Section)); - - function Convert is new Ada.Unchecked_Conversion - (System.Address, Str_Access); - - Source : constant String (1 .. Section_Size) - with Import => True, Address => Address_Of (Section); - Dest : constant Str_Access := Convert (Addr); - begin - Dest (1 .. Section_Size) := Source (1 .. Section_Size); - Free (Section); - end Load_Section; - - function Exe_Address_From_Arg - (Arg : String; Required : Boolean) return Unsigned_32; - -- Some command line options can specify an address from the - -- executable. The address can be given either by a symbol name, - -- or a hexadecimal value using either the C 0xHHHH syntax or - -- the Ada 16#HHHH# syntax. A symbol name cannot have "0x" or - -- "16#" as a proper prefix. - -- - -- If a valid address is not found and Required is True, a message will - -- be output to Standard_Error and a Constraint_Error will be raised. - -- - -- If a valid address is not found and Required is False, Impossible_PC - -- is returned. - -- - -- Presumes "Executable_File" has been opened, "Ehdr" retrieved and - -- Section Headers loaded. - - function Exe_Address_From_Arg - (Arg : String; Required : Boolean) return Unsigned_32 - is - A : Unsigned_32 := 0; - Invalid_Insn_Addr : constant Unsigned_32 := 1; - - function Lookup_Sym_Value (S : String) return Unsigned_32; - - function Lookup_Sym_Value (S : String) return Unsigned_32 is - Sym : Elf_Sym; - N_Syms : Natural; - N_Bytes : Natural; - Str_Idx : Natural; - K : Natural; - Symtab_Shdr_Idx : Elf_Half; - Symtab_Shdr_Ptr : Elf_Shdr_Acc; - type Sym_Array_T is array (Positive range <>) of Elf_Sym; - type Sym_Array_Ptr_T is access all Sym_Array_T; - procedure Free is - new Ada.Unchecked_Deallocation (Sym_Array_T, Sym_Array_Ptr_T); - Sym_Array_Ptr : Sym_Array_Ptr_T; - Strtab_Shdr_Idx : Elf_Half; - Strtab_Shdr_Ptr : Elf_Shdr_Acc; - type String_Table_T is array (Natural range <>) of Character; - type String_Table_Ptr_T is access all String_Table_T; - procedure Free is - new Ada.Unchecked_Deallocation (String_Table_T, String_Table_Ptr_T); - String_Table_Ptr : String_Table_Ptr_T; - begin - Symtab_Shdr_Idx := Get_Shdr_By_Name (Executable_File, ".symtab"); - Chk_Exe ("Error finding "".symtab"" section"); - Symtab_Shdr_Ptr := Get_Shdr (Executable_File, Symtab_Shdr_Idx); - Chk_Exe ("Error getting "".symtab"" section header"); - N_Syms := - Natural (Symtab_Shdr_Ptr.Sh_Size / Symtab_Shdr_Ptr.Sh_Entsize); - if N_Syms = 0 then - Put_Line (Standard_Error, "Symbol table is empty."); - raise Constraint_Error; - end if; - Sym_Array_Ptr := new Sym_Array_T (1 .. N_Syms); - Load_Section (Executable_File, Symtab_Shdr_Idx, - Sym_Array_Ptr (Sym_Array_Ptr'First)'Address); - Chk_Exe ("Error loading symbol table"); - -- Load the symbol table - - Strtab_Shdr_Idx := Elf_Half (Symtab_Shdr_Ptr.Sh_Link); - Strtab_Shdr_Ptr := Get_Shdr (Executable_File, Strtab_Shdr_Idx); - Chk_Exe ("Error getting symbol table strings section header"); - N_Bytes := Natural (Strtab_Shdr_Ptr.Sh_Size); - if N_Bytes = 0 then - Put_Line (Standard_Error, "Symbols string table is empty."); - raise Constraint_Error; - end if; - String_Table_Ptr := new String_Table_T (0 .. N_Bytes - 1); - Load_Section (Executable_File, Strtab_Shdr_Idx, - String_Table_Ptr (String_Table_Ptr'First)'Address); - Chk_Exe ("Error loading symbols string table"); - -- Load the string table - - for J in Sym_Array_Ptr'Range loop - Sym := Get_Sym (Executable_File, Sym_Array_Ptr (J)'Address); - Str_Idx := Natural (Sym.St_Name); - if Str_Idx > String_Table_Ptr'Last then - Put_Line (Standard_Error, "String table index too large"); - raise Constraint_Error; - end if; - K := S'First; - loop - exit when S (K) /= String_Table_Ptr (Str_Idx); - Str_Idx := Str_Idx + 1; - if K = S'Last then - if Character'Pos (String_Table_Ptr (Str_Idx)) = 0 then - Free (Sym_Array_Ptr); - Free (String_Table_Ptr); - return Sym.St_Value; - else - exit; - end if; - end if; - K := K + 1; - end loop; - - end loop; - - -- Put_Line (Standard_Error, "Symbol """ & S & """ not found"); - return Impossible_PC; - end Lookup_Sym_Value; - - begin - if Arg'Length > 2 and Has_Prefix (Arg, "0x") then - J := Arg'First + 2; - while J <= Arg'Last loop - A := A * 16; - if Arg (J) in '0' .. '9' then - A := A + (Character'Pos (Arg (J)) - Character'Pos ('0')); - elsif Arg (J) in 'a' .. 'f' then - A := A + (Character'Pos (Arg (J)) - Character'Pos ('a') + 10); - elsif Arg (J) in 'A' .. 'F' then - A := A + (Character'Pos (Arg (J)) - Character'Pos ('A') + 10); - else - Put_Line (Standard_Error, "Invalid Adress: " & Arg); - raise Constraint_Error; - end if; - J := J + 1; - end loop; - return A; - elsif Arg'Length > 3 and Has_Prefix (Arg, "16#") then - J := Arg'First + 3; - Under_OK := False; - while J <= Arg'Last loop - if J = Arg'Last and then Arg (J) = '#' then - return A; - end if; - if J = Arg'Last then - Put_Line (Standard_Error, "Malformed Address: " & Arg); - raise Constraint_Error; - end if; - A := A * 16; - if Arg (J) in '0' .. '9' then - A := A + (Character'Pos (Arg (J)) - Character'Pos ('0')); - Under_OK := True; - elsif Arg (J) in 'a' .. 'f' then - A := A + (Character'Pos (Arg (J)) - Character'Pos ('a') + 10); - Under_OK := True; - elsif Arg (J) in 'A' .. 'F' then - A := A + (Character'Pos (Arg (J)) - Character'Pos ('A') + 10); - Under_OK := True; - elsif Arg (J) = '_' then - if not Under_OK or else J + 1 = Arg'Last then - Put_Line (Standard_Error, "Malformed Address: " & Arg); - raise Constraint_Error; - end if; - Under_OK := False; - A := A / 16; - else - Put_Line (Standard_Error, "Invalid Adress: " & Arg); - raise Constraint_Error; - end if; - J := J + 1; - end loop; - return A; - else - -- In the symbol name case.... look up in Executable - A := Lookup_Sym_Value (Arg); - if Required and then A = Impossible_PC then - Put_Line (Standard_Error, "Symbol """ & Arg & """ not found"); - raise Constraint_Error; - end if; - return A; - end if; - end Exe_Address_From_Arg; - - function To_Hex_Word_Str (Val : Unsigned_32) return String; - function To_Hex_Word_Str (Val : Unsigned_32) return String is - S : String (1 .. 13) := "16#0000_0000#"; - Idx : Positive := 12; - V : Unsigned_32 := Val; - - D : constant array (Unsigned_32 range 0 .. 15) of Character - := ('0', '1', '2', '3', '4', '5', '6', '7', - '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'); - begin - while V /= 0 loop - S (Idx) := D (V mod 16); - Idx := Idx - 1; - if Idx = 8 then - Idx := 7; - end if; - V := V / 16; - end loop; - return S; - end To_Hex_Word_Str; - -- Keep around for debugging. - - No_Insns_Executed : Boolean; - Do_History : Boolean; - History_FD : File_Descriptor; - Trace_FD : File_Descriptor; - Tr_Header : Trace_Header; - Trace_Header_Size : constant Natural := - Trace_Header'Size / System.Storage_Unit; - Entry32 : Trace_Entry32; - E32_Size : constant Natural := Trace_Entry32'Size / System.Storage_Unit; - Writing_Trace : Boolean; - File_Len : Long_Integer; - N_History_Entries : Integer; - Decision_Addr : Unsigned_32; - - In_Block : Boolean; - Block_Start, Block_End : Unsigned_32; - Op : Unsigned_8; - -- Variables used when making final pass over instructions flags - -- array to write out traces. - -begin - - if Argument_Count /= 8 then - Usage; - Set_Exit_Status (1); - return; - end if; - -- for J in 1 .. Argument_Count loop - -- Put (Argument (J) & ' '); - -- end loop; - - Processor_ID := new String'(Argument (1)); - Executable_Filename := new String'(Argument (2)); - OCD_Filename := new String'(Argument (3)); - if Argument (4) = "--nohist" then - Histfile_Path := new String'(""); - Do_History := False; - else - Histfile_Path := new String'(Argument (4)); - Do_History := True; - end if; - - Tracefile_Path := new String'(Argument (5)); - - Fd := Open_Read (Executable_Filename.all, Binary); - if Fd = Invalid_FD then - raise Exe_Exception with Executable_Filename.all & ": File not found"; - end if; - Executable_File := Create_File (Fd, Executable_Filename); - Chk_Exe ("Error Opening"); - Ehdr := Get_Ehdr (Executable_File); - Chk_Exe ("Error reading file header"); - Chk_Exe ("Error retrieving section headers"); - -- Open the executable file before processing of PT_Start_Addr, in - -- case a symbol name is used for the address, which requires - -- processing of the executable. - Exception_Vec_Addr := - Exe_Address_From_Arg ("_jump_to_handler", Required => False); - if Exception_Vec_Addr /= Impossible_PC then - Number_Exception_Vectors := 1; - end if; - - if To_Upper (Argument (6)) = "IAC1" then - PT_Start_IAC_Bit := 1; - elsif To_Upper (Argument (6)) = "IAC2" then - PT_Start_IAC_Bit := 2; - elsif To_Upper (Argument (6)) = "IAC3" then - PT_Start_IAC_Bit := 4; - elsif To_Upper (Argument (6)) = "IAC4" then - PT_Start_IAC_Bit := 8; - else - Put_Line (Standard_Error, "PT_Start_IAC out of range 1 .. 4"); - Set_Exit_Status (1); - return; - end if; - - PT_Start_Address := - Exe_Address_From_Arg (Argument (7), Required => True); - - if Argument (8) = "0" then - PT_Stop_IAC_Bit := 0; - elsif To_Upper (Argument (8)) = "IAC1" then - PT_Stop_IAC_Bit := 1; - elsif To_Upper (Argument (8)) = "IAC2" then - PT_Stop_IAC_Bit := 2; - elsif To_Upper (Argument (8)) = "IAC3" then - PT_Stop_IAC_Bit := 4; - elsif To_Upper (Argument (8)) = "IAC4" then - PT_Stop_IAC_Bit := 8; - else - Put_Line (Standard_Error, - "PT_Stop_IAC must be 'never' or in range 1 .. 4"); - Set_Exit_Status (1); - return; - end if; - - if Number_Exception_Vectors /= 0 and then Do_History then - Put_Line (Standard_Error, - "History file cannot be specified with exception vectors."); - Set_Exit_Status (1); - return; - end if; - - if Processor_ID.all = "5634" then - ICNT_Proc_Adj := 0; - elsif Processor_ID.all = "5554" then - ICNT_Proc_Adj := 1; - else - Put_Line (Standard_Error, "Unrecognized Processor ID (procid)."); - Usage; - Set_Exit_Status (1); - return; - end if; - ICNT_Adj_Val := ICNT_Proc_Adj; - - Text_Shdr_Idx := Get_Shdr_By_Name (Executable_File, ".text"); - Chk_Exe ("Error finding "".text"" section"); - Text_Shdr_Ptr := Get_Shdr (Executable_File, Text_Shdr_Idx); - Chk_Exe ("Error getting "".text"" section header"); - Text_First_Addr := Unsigned_32 (Text_Shdr_Ptr.Sh_Addr); - Text_Section_Len := Text_Shdr_Ptr.Sh_Size; - if Text_Section_Len < 4 then - Close_File (Executable_File); - raise Program_Error with ".text section too small."; - end if; - N_Insns := Positive (Text_Section_Len / 4); - Insns_Ptr := new Insns_Array (1 .. N_Insns); - Load_Section (Executable_File, Text_Shdr_Idx, - Insns_Ptr (Insns_Ptr'First)'Address); - Chk_Exe ("Error reading code from executable"); - for J in Insns_Ptr'Range loop - Insns_Ptr (J) := Swap (Insns_Ptr (J)); - end loop; - -- All the above is to extract the code from the executable into - -- an array of instructions. - -- Two generalization are probably advisable: ??? - -- - go through all sections and find code (not juse .text) - -- - determine if swapping is needed (PPC -> x86 presumed now). - -- Handle gaps in a code segment ??? - - Close_File (Executable_File); - - Insn_Flags := new Insn_Flags_Array_T (1 .. N_Insns); - for J in Insn_Flags'Range loop - Op_Code := Shift_Right (Insns_Ptr (J), 26); - if Op_Code = 16 or else Op_Code = 18 or else - (Op_Code = 19 and then ((Insns_Ptr (J) and 16#3fe#) = 16#20#)) or else - (Op_Code = 19 and then ((Insns_Ptr (J) and 16#3fe#) = 16#64#)) or else - (Op_Code = 19 and then ((Insns_Ptr (J) and 16#3fe#) = 16#12c#)) or else - (Op_Code = 31 and then ((Insns_Ptr (J) and 16#3fe#) = 16#008#)) - then - Insn_Flags (J) := (Is_Branch => True, others => False); - else - Insn_Flags (J) := (others => False); - end if; - end loop; - -- ??? Only the instructions whose mnemonics begin with 'b' are - -- dealt with. Many other instuctions (particularly with major - -- opcode = 19) will cause a change in flow, and will generate - -- NEXUS program trace messages. - - Insn_Idx := Integer (PT_Start_Address - Text_First_Addr) / 4 + 1; - if Insn_Flags (Insn_Idx).Is_Branch then - Put_Line (Standard_Error, - "Start Trigger instruction is a branch instruction."); - Put_Line (Standard_Error, - "Nexus Program trace data must be generated with"); - Put_Line (Standard_Error, "non-branch instruction for Start Trigger."); - Set_Exit_Status (1); - return; - end if; - -- If branch is used for start trigger, the first instruction - -- in the next Branch Trace message would be the target of the - -- branch. Perhaps that could be calculated for direct branches, - -- but for now, all branches are disallowed for start trigger. - - -- If doing History traces, read the addresses that are "interesting" - -- from the history file. For each such address, mark all instructions - -- in the same basic block (go backwards over all non-branches, and - -- forward to the first branch) as Historical in the flags array. - - if Do_History then - - History_FD := Open_Read (Histfile_Path.all, Binary); - if History_FD = Invalid_FD then - raise Program_Error with "Error opening history file."; - end if; - if Read (History_FD, Tr_Header'Address, Trace_Header_Size) - /= Trace_Header_Size - then - Close (History_FD); - raise Program_Error with "Error reading history file."; - end if; - -- Do checks on header ??? - if Natural (Tr_Header.Sizeof_Target_Pc) /= 4 then - Close (History_FD); - raise Program_Error with "Only handle 32 bit history files."; - end if; - - File_Len := File_Length (History_FD) - Long_Integer (Trace_Header_Size); - if File_Len mod Long_Integer (E32_Size) /= 0 then - Close (History_FD); - raise Program_Error with "Unexpected size of history file."; - end if; - - N_History_Entries := Integer (File_Len / Long_Integer (E32_Size)); - - for J in 1 .. N_History_Entries loop - if Read (History_FD, Entry32'Address, E32_Size) /= E32_Size then - Close (History_FD); - raise Program_Error with "Histmap read failure."; - end if; - - Decision_Addr := Entry32.Pc; - if Decision_Addr < Text_First_Addr or else - Decision_Addr >= Text_First_Addr + Unsigned_32 (N_Insns * 4) - then - Close (History_FD); - raise Program_Error with "History map address out of range."; - end if; - - Insn_Idx := Positive (((Decision_Addr - Text_First_Addr) / 4)) - + Insn_Flags'First; - Idx2 := Insn_Idx; - while Idx2 > Insn_Flags'First loop - Idx2 := Idx2 - 1; - exit when Insn_Flags (Idx2).Is_Branch; - Insn_Flags (Idx2).Historical := True; - end loop; - Idx2 := Insn_Idx; - loop - Insn_Flags (Idx2).Historical := True; - exit when Idx2 = Insn_Flags'Last or else - Insn_Flags (Idx2).Is_Branch; - end loop; - - end loop; - Close (History_FD); - - end if; - - -- Open the trace file and set things up to write trace entries. - -- In the case of 'Flat' traces, nothing will be written until - -- all of the Nexus data is processed, which fills in the - -- Insn_Flags_Array. In the case of 'History' traces, basic blocks - -- which include an address found in the history file, will be written - -- out on the fly, during the processing of the Nexus data (in historical - -- order), with the rest of the trace data (basic blocks not of - -- historical interest) will be processed afterwards -- like 'Flat' traces. - - Tr_Header := - (Magic => Qemu_Trace_Magic, - Version => Qemu_Trace_Version, - Kind => Flat, - Sizeof_Target_Pc => Pc_Type_Size, - Big_Endian => Big_Endian_Host, - Machine_Hi => Unsigned_8 (Shift_Right (Unsigned_16 (20), 8)), - Machine_Lo => Unsigned_8 (Unsigned_16 (20) and 16#Ff#), - -- Note hardcoding of machine. Fix ??? - Padding => 0); - if Do_History then - Tr_Header.Kind := History; - end if; - - Trace_FD := Open_Read_Write (Tracefile_Path.all, Binary); - if Trace_FD = Invalid_FD then - raise Program_Error with "Error opening trace file to append."; - end if; - Lseek (Trace_FD, 0, Seek_End); - - if Write (Trace_FD, Tr_Header'Address, Trace_Header_Size) - /= Trace_Header_Size - then - Close (Trace_FD); - raise Program_Error with "Error appending to trace file."; - end if; - - -- In Insn_Flags we have a list of flags set for each instruction. - -- We retrieve the sequence of Nexus messages using Get_Next_Nexus_Msg. - -- We now go trhough the message list writing out History entries - -- if requested, and modifying flags in Insn_Flags to indicate which - -- instructions have been executed, and which direction(s) were taken - -- on executed branch instructions. Later the Insn_Flags array is - -- processed to generate GNATcoverage trace data: all of it in the - -- "Flat" case, or non-histoical blocks in the "History" case. - - Open_OCD_File (OCD_Filename.all); - Nexus_Msg := Get_Next_Nexus_Msg; - if Nexus_Msg = null then - raise Program_Error with "Empty Nexus message list"; - end if; - - PT_Running := False; - - loop - case Nexus_Msg.Tcode is - when Watchpoint_Message => - -- Processing needed for WPs that are used for the start - -- and stop of PT message generation. The transition from - -- stopped state to running state needs to be handled since - -- the instruction count for the subsequent BTM can differ - -- if the WP addr is between branches. - Watchpoints_Seen := - Watchpoint_T (Nexus_Msg.Watchpoint_Message_V.WPHIT); - if (Watchpoints_Seen and PT_Start_IAC_Bit) /= 0 then - if (Watchpoints_Seen and PT_Stop_IAC_Bit) /= 0 then - raise Program_Error with - "Cannot handle simultaneous Start and Stop WP msg"; - end if; - if not PT_Running then - PT_Running := True; - Block_Begin_Idx := - Integer (PT_Start_Address - Text_First_Addr) / 4 + 1; - ICNT_Adj_Val := ICNT_Proc_Adj + 1; - -- ICNT_Adj_Val := ICNT_Proc_Adj; - end if; - elsif (Watchpoints_Seen and PT_Stop_IAC_Bit) /= 0 then - PT_Running := False; - end if; - - when Resource_Full_Message => - -- An RCODE of 0 indicates that the Instruction count - -- has wrapped around and another 255 needs to be added - -- to the I_CNT value returned by the next BTM. - if Nexus_Msg.Resource_Full_Message_V.RCODE = 0 then - ICNT_Adj_Val := ICNT_Adj_Val + 255; - else - raise Program_Error with - "Resource Full Message unexpected RCODE received"; - end if; - - when Prog_Trace_Program_Correlation_Message => - -- There are 2 expected events that generate Program Correlation - -- messages: a breakpoint is set to end execution; the PT - -- stop watchpoint is hit. - EV_Code := - Nexus_Msg.Prog_Trace_Program_Correlation_Message_V.EVCODE; - if EV_Code = 4 or else EV_Code = 0 then - if EV_Code = 4 and then PT_Running then - raise Program_Error with - "Correlation message EVCODE of 4 while PT running"; - -- Watchpoint should have occured to set PT_Running False - end if; - - -- For either Stop Trigger or entering of debug mode (BP), - -- an instruction count is provided for instructions since - -- the last BTM. Here, we mark those instructions as - -- executed. - - Insn_Count := Natural - (Nexus_Msg.Prog_Trace_Program_Correlation_Message_V.I_CNT - + ICNT_Adj); - - if Insn_Count > 0 then - N_Insns := Positive (Insn_Count); - Block_End_Idx := Block_Begin_Idx + N_Insns - 1; - Insn_Idx := Block_Begin_Idx; - if Do_History and then Insn_Flags (Insn_Idx).Historical then - Writing_Trace := True; - Trace_Start_Idx := Insn_Idx; - else - Writing_Trace := False; - end if; - - loop - Insn_Flags (Insn_Idx).Been_Executed := True; - if Insn_Idx = Block_End_Idx then - -- The last instruction should be a branch taken. - if Writing_Trace then - Entry32.Pc := - Unsigned_32 ((Trace_Start_Idx - Insn_Flags'First) - * 4) + Text_First_Addr; - Entry32.Size := - Unsigned_16 ((Insn_Idx - Trace_Start_Idx + 1) - * 4); - Entry32.Pad0 := 0; - if - Write (Trace_FD, Entry32'Address, E32_Size) - /= E32_Size - then - Close (Trace_FD); - raise Program_Error - with "Error writing trace entry."; - end if; - end if; - - exit; - elsif Insn_Flags (Insn_Idx).Is_Branch then - -- A branch may appear in the middle of the I_CNT - -- instructions since the last message. That is a - -- branch that was not taken. - Insn_Flags (Insn_Idx).Br_Not_Taken := True; - - if Writing_Trace then - Entry32.Pc := - Unsigned_32 ((Trace_Start_Idx - Insn_Flags'First) - * 4) + Text_First_Addr; - Entry32.Size := - Unsigned_16 ((Insn_Idx - Trace_Start_Idx + 1) - * 4); - Entry32.Op := Trace_Op_Br1; - Entry32.Pad0 := 0; - if - Write (Trace_FD, Entry32'Address, E32_Size) - /= E32_Size - then - Close (Trace_FD); - raise Program_Error - with "Error writing trace entry."; - end if; - end if; - if - Do_History and then - Insn_Flags (Insn_Idx + 1).Historical - then - Writing_Trace := True; - Trace_Start_Idx := Insn_Idx + 1; - else - Writing_Trace := False; - end if; - end if; - Insn_Idx := Insn_Idx + 1; - end loop; - -- If BP, then exit below. - -- If Stop trigger, then Block_Begin_Index will be - -- calculated, when/if Start trigger is seen. - - if EV_Code = 0 then - -- BP - exit; - end if; - end if; - else - raise Program_Error with - "Correlation message with unxpected EVCODE"; - end if; - - when Prog_Trace_Direct_Branch_Message => - N_Insns := Positive - (Nexus_Msg.Prog_Trace_Direct_Branch_Message_V.I_CNT + ICNT_Adj); - Block_End_Idx := Block_Begin_Idx + N_Insns - 1; - Insn_Idx := Block_Begin_Idx; - if Do_History and then Insn_Flags (Insn_Idx).Historical then - Writing_Trace := True; - Trace_Start_Idx := Insn_Idx; - else - Writing_Trace := False; - end if; - - loop - Insn_Flags (Insn_Idx).Been_Executed := True; - if Insn_Idx = Block_End_Idx then - -- The last instruction should be a branch taken. - if not Insn_Flags (Insn_Idx).Is_Branch then - raise Program_Error with "End of block not a branch"; - end if; - Insn_Flags (Insn_Idx).Br_Taken := True; - if Writing_Trace then - Entry32.Pc := - Unsigned_32 ((Trace_Start_Idx - Insn_Flags'First) * 4) - + Text_First_Addr; - Entry32.Size := - Unsigned_16 ((Insn_Idx - Trace_Start_Idx + 1) * 4); - Entry32.Op := Trace_Op_Br0; - Entry32.Pad0 := 0; - if - Write (Trace_FD, Entry32'Address, E32_Size) /= E32_Size - then - Close (Trace_FD); - raise Program_Error - with "Error writing trace entry."; - end if; - end if; - - exit; - elsif Insn_Flags (Insn_Idx).Is_Branch then - -- A branch may appear in the middle of the I_CNT - -- instructions since the last message. That is a - -- branch that was not taken. - Insn_Flags (Insn_Idx).Br_Not_Taken := True; - - if Writing_Trace then - Entry32.Pc := - Unsigned_32 ((Trace_Start_Idx - Insn_Flags'First) * 4) - + Text_First_Addr; - Entry32.Size := - Unsigned_16 ((Insn_Idx - Trace_Start_Idx + 1) * 4); - Entry32.Op := Trace_Op_Br1; - Entry32.Pad0 := 0; - if - Write (Trace_FD, Entry32'Address, E32_Size) /= E32_Size - then - Close (Trace_FD); - raise Program_Error - with "Error writing trace entry."; - end if; - end if; - if - Do_History and then Insn_Flags (Insn_Idx + 1).Historical - then - Writing_Trace := True; - Trace_Start_Idx := Insn_Idx + 1; - else - Writing_Trace := False; - end if; - end if; - Insn_Idx := Insn_Idx + 1; - end loop; - - -- For Direct Branch messages, the new address is calucluated - -- by analysis of the instruction. - - Br_Insn := Insns_Ptr (Block_End_Idx); - Br_Addr := Text_First_Addr + Unsigned_32 (Block_End_Idx - 1) * 4; - Op_Code := Shift_Right (Br_Insn, 26); - AA_Bit := Shift_Right ((Br_Insn and 2#10#), 1); - if Op_Code = 18 then - New_Addr := Shift_Right_Arithmetic (Shift_Left (Br_Insn, 6), 6); - if AA_Bit = 0 then - New_Addr := New_Addr + Br_Addr; - end if; - elsif Op_Code = 16 then - New_Addr := - Shift_Right_Arithmetic (Shift_Left (Br_Insn, 16), 16); - if AA_Bit = 0 then - New_Addr := New_Addr + Br_Addr; - end if; - elsif Op_Code = 19 then - Ext_Op_Code := Br_Insn and 16#0000_03fe#; - if Ext_Op_Code = 16#12c# then - -- This is an isync op. New_Addr is next instruction. ?? - New_Addr := Br_Addr + 4; - else - raise Program_Error with - "Unexpected Extended opcode for opcode 19 Direct_Branch"; - end if; - else - raise Program_Error with "Unexpected opcode for Direct Branch"; - end if; - Block_Begin_Idx := Positive (New_Addr - Text_First_Addr) / 4 + 1; - - when Prog_Trace_Indirect_Branch_Message => - U_Addr := Unsigned_32 - (Nexus_Msg.Prog_Trace_Indirect_Branch_Message_V.U_ADDR); - New_Addr := Last_Indirect_Or_Sync_Addr xor U_Addr; - if New_Addr = Exception_Vec_Addr then - IBM_Type := Exception_Occur; - else - IBM_Type := Branch_Insn; - end if; - if IBM_Type = Exception_Occur and then - Nexus_Msg.Prog_Trace_Indirect_Branch_Message_V.I_CNT = 0 - then - No_Insns_Executed := True; - else - No_Insns_Executed := False; - N_Insns := Positive - (Nexus_Msg.Prog_Trace_Indirect_Branch_Message_V.I_CNT - + ICNT_Adj); - Block_End_Idx := Block_Begin_Idx + N_Insns - 1; - Insn_Idx := Block_Begin_Idx; - if Do_History and then Insn_Flags (Insn_Idx).Historical then - Writing_Trace := True; - Trace_Start_Idx := Insn_Idx; - else - Writing_Trace := False; - end if; - end if; - - loop - -- exit when No_Insns_Executed; - -- ??? do better fix for warning caused by this. - if No_Insns_Executed then - exit; - end if; - Insn_Flags (Insn_Idx).Been_Executed := True; - if Insn_Idx = Block_End_Idx then - if not Insn_Flags (Insn_Idx).Is_Branch then - if IBM_Type /= Exception_Occur then - Put_Line (Unsigned_32'Image (New_Addr)); - raise Program_Error with - "End of block not a branch(1)"; - end if; - end if; - Insn_Flags (Insn_Idx).Br_Taken := True; - if Writing_Trace then - Entry32.Pc := - Unsigned_32 ((Trace_Start_Idx - Insn_Flags'First) * 4) - + Text_First_Addr; - Entry32.Size := - Unsigned_16 ((Insn_Idx - Trace_Start_Idx + 1) * 4); - Entry32.Op := Trace_Op_Br0; - Entry32.Pad0 := 0; - if - Write (Trace_FD, Entry32'Address, E32_Size) /= E32_Size - then - Close (Trace_FD); - raise Program_Error - with "Error writing trace entry."; - end if; - end if; - - exit; - elsif Insn_Flags (Insn_Idx).Is_Branch then - -- As in the direct Branch case, there can be branches - -- not taken since the last message. - Insn_Flags (Insn_Idx).Br_Not_Taken := True; - - if Writing_Trace then - Entry32.Pc := - Unsigned_32 ((Trace_Start_Idx - Insn_Flags'First) * 4) - + Text_First_Addr; - Entry32.Size := - Unsigned_16 ((Insn_Idx - Trace_Start_Idx + 1) * 4); - Entry32.Op := Trace_Op_Br1; - Entry32.Pad0 := 0; - if - Write (Trace_FD, Entry32'Address, E32_Size) /= E32_Size - then - Close (Trace_FD); - raise Program_Error - with "Error writing trace entry."; - end if; - end if; - if - Do_History and then Insn_Flags (Insn_Idx + 1).Historical - then - Writing_Trace := True; - Trace_Start_Idx := Insn_Idx + 1; - else - Writing_Trace := False; - end if; - end if; - Insn_Idx := Insn_Idx + 1; - end loop; - Block_Begin_Idx := Positive (New_Addr - Text_First_Addr) / 4 + 1; - Last_Indirect_Or_Sync_Addr := New_Addr; - - when Prog_Trace_Direct_Branch_Message_Sync => - N_Insns := Positive - (Nexus_Msg.Prog_Trace_Direct_Branch_Message_Sync_V.I_CNT - + ICNT_Adj); - Block_End_Idx := Block_Begin_Idx + N_Insns - 1; - Insn_Idx := Block_Begin_Idx; - if Do_History and then Insn_Flags (Insn_Idx).Historical then - Writing_Trace := True; - Trace_Start_Idx := Insn_Idx; - else - Writing_Trace := False; - end if; - - loop - Insn_Flags (Insn_Idx).Been_Executed := True; - if Insn_Idx = Block_End_Idx then - if not Insn_Flags (Insn_Idx).Is_Branch then - raise Program_Error with - "End of block not a branch"; - end if; - Insn_Flags (Insn_Idx).Br_Taken := True; - if Writing_Trace then - Entry32.Pc := - Unsigned_32 ((Trace_Start_Idx - Insn_Flags'First) * 4) - + Text_First_Addr; - Entry32.Size := - Unsigned_16 ((Insn_Idx - Trace_Start_Idx + 1) * 4); - Entry32.Op := Trace_Op_Br0; - Entry32.Pad0 := 0; - if - Write (Trace_FD, Entry32'Address, E32_Size) /= E32_Size - then - Close (Trace_FD); - raise Program_Error - with "Error writing trace entry."; - end if; - end if; - - exit; - elsif Insn_Flags (Insn_Idx).Is_Branch then - Insn_Flags (Insn_Idx).Br_Not_Taken := True; - - if Writing_Trace then - Entry32.Pc := - Unsigned_32 ((Trace_Start_Idx - Insn_Flags'First) * 4) - + Text_First_Addr; - Entry32.Size := - Unsigned_16 ((Insn_Idx - Trace_Start_Idx + 1) * 4); - Entry32.Op := Trace_Op_Br1; - Entry32.Pad0 := 0; - if - Write (Trace_FD, Entry32'Address, E32_Size) /= E32_Size - then - Close (Trace_FD); - raise Program_Error - with "Error writing trace entry."; - end if; - end if; - if - Do_History and then Insn_Flags (Insn_Idx + 1).Historical - then - Writing_Trace := True; - Trace_Start_Idx := Insn_Idx + 1; - else - Writing_Trace := False; - end if; - end if; - Insn_Idx := Insn_Idx + 1; - end loop; - - -- In Sync messages, the full address is provided. - New_Addr := Unsigned_32 - (Nexus_Msg.Prog_Trace_Direct_Branch_Message_Sync_V.F_ADDR); - Block_Begin_Idx := Positive (New_Addr - Text_First_Addr) / 4 + 1; - Last_Indirect_Or_Sync_Addr := New_Addr; - - when Prog_Trace_Indirect_Branch_Message_Sync => - New_Addr := Unsigned_32 - (Nexus_Msg.Prog_Trace_Indirect_Branch_Message_Sync_V.F_ADDR); - if New_Addr = Exception_Vec_Addr then - IBM_Type := Exception_Occur; - else - IBM_Type := Branch_Insn; - end if; - if IBM_Type = Exception_Occur and then - Nexus_Msg.Prog_Trace_Indirect_Branch_Message_Sync_V.I_CNT = 0 - then - No_Insns_Executed := True; - else - No_Insns_Executed := False; - N_Insns := Positive - (Nexus_Msg.Prog_Trace_Indirect_Branch_Message_Sync_V.I_CNT - + ICNT_Adj); - Block_End_Idx := Block_Begin_Idx + N_Insns - 1; - Insn_Idx := Block_Begin_Idx; - if Do_History and then Insn_Flags (Insn_Idx).Historical then - Writing_Trace := True; - Trace_Start_Idx := Insn_Idx; - else - Writing_Trace := False; - end if; - end if; - - loop - -- exit when No_Insns_Executed; - -- ??? do better fix for warning caused by this. - if No_Insns_Executed then - exit; - end if; - Insn_Flags (Insn_Idx).Been_Executed := True; - if Insn_Idx = Block_End_Idx then - if not Insn_Flags (Insn_Idx).Is_Branch then - if IBM_Type /= Exception_Occur then - raise Program_Error with - "End of block not a branch(2)"; - end if; - end if; - Insn_Flags (Insn_Idx).Br_Taken := True; - if Writing_Trace then - Entry32.Pc := - Unsigned_32 ((Trace_Start_Idx - Insn_Flags'First) * 4) - + Text_First_Addr; - Entry32.Size := - Unsigned_16 ((Insn_Idx - Trace_Start_Idx + 1) * 4); - Entry32.Op := Trace_Op_Br0; - Entry32.Pad0 := 0; - if - Write (Trace_FD, Entry32'Address, E32_Size) /= E32_Size - then - Close (Trace_FD); - raise Program_Error - with "Error writing trace entry."; - end if; - end if; - - exit; - elsif Insn_Flags (Insn_Idx).Is_Branch then - Insn_Flags (Insn_Idx).Br_Not_Taken := True; - - if Writing_Trace then - Entry32.Pc := - Unsigned_32 ((Trace_Start_Idx - Insn_Flags'First) * 4) - + Text_First_Addr; - Entry32.Size := - Unsigned_16 ((Insn_Idx - Trace_Start_Idx + 1) * 4); - Entry32.Op := Trace_Op_Br1; - Entry32.Pad0 := 0; - if - Write (Trace_FD, Entry32'Address, E32_Size) /= E32_Size - then - Close (Trace_FD); - raise Program_Error - with "Error writing trace entry."; - end if; - end if; - if - Do_History and then Insn_Flags (Insn_Idx + 1).Historical - then - Writing_Trace := True; - Trace_Start_Idx := Insn_Idx + 1; - else - Writing_Trace := False; - end if; - end if; - Insn_Idx := Insn_Idx + 1; - end loop; - - -- In Sync messages, the full address is provided. - Block_Begin_Idx := Positive (New_Addr - Text_First_Addr) / 4 + 1; - Last_Indirect_Or_Sync_Addr := New_Addr; - - when Debug_Status => - exit when (Nexus_Msg.Debug_Status_V.STATUS and 16#80#) /= 0; - -- Processor entered Debug mode. - - when Data_Trace_Data_Write_Message => - raise Program_Error with "Unexpected Data Trace TCODE"; - - when Data_Trace_Data_Read_Message => - raise Program_Error with "Unexpected Data Trace TCODE"; - - when Error_Message => - raise Program_Error with "Unexpected Error Message TCODE"; - - when Ownership_Trace_Message => - raise Program_Error with "Unexpected Ownership Trace TCODE"; - - when Data_Trace_Data_Write_Message_Sync => - raise Program_Error with "Unexpected Data Trace TCODE"; - - when Data_Trace_Data_Read_Message_Sync => - raise Program_Error with "Unexpected Data Trace TCODE"; - - when Prog_Trace_Indirect_Branch_Hist_Message => - raise Program_Error with "Unexpected Branch History TCODE"; - when Prog_Trace_Indirect_Branch_Hist_Message_Sync => - raise Program_Error with "Unexpected Branch History TCODE"; - - when 1 | 7 | 9 | 10 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 - | 24 | 25 | 26 | 30 | 31 | 32 => - raise Program_Error with "Invalid TCODE"; - - end case; - Nexus_Msg := Get_Next_Nexus_Msg; - exit when Nexus_Msg = null; - end loop; - - -- Loop over Insn_Flags, calculating basic blocks and writing - -- trace entries. - - In_Block := False; - for J in Insn_Flags'Range loop - if Insn_Flags (J).Been_Executed then - if not In_Block then - In_Block := True; - Block_Start := Text_First_Addr + Unsigned_32 (J - 1) * 4; - end if; - if Insn_Flags (J).Is_Branch or else J = Insn_Flags'Last then - In_Block := False; - Block_End := Text_First_Addr + Unsigned_32 (J - 1) * 4; - if J /= Insn_Flags'Last then - if not Do_History or else not Insn_Flags (J).Historical then - Op := Trace_Op_Block; - if Insn_Flags (J).Br_Taken then - Op := Op or Trace_Op_Br0; - end if; - if Insn_Flags (J).Br_Not_Taken then - Op := Op or Trace_Op_Br1; - end if; - Entry32.Pc := Block_Start; - Entry32.Size := Unsigned_16 (Block_End - Block_Start + 4); - Entry32.Op := Op; - Entry32.Pad0 := 0; - if - Write (Trace_FD, Entry32'Address, E32_Size) /= E32_Size - then - Close (Trace_FD); - raise Program_Error with "Error appending trace entry."; - end if; - end if; - - else - exit; - end if; - end if; - end if; - end loop; - Close (Trace_FD); - -exception - when E : Isys2nex_Error => - Put_Line (Standard_Error, Exception_Message (E)); - Set_Exit_Status (1); - when E : Program_Error => - Put_Line (Standard_Error, Exception_Message (E)); - Set_Exit_Status (1); - when E : Exe_Exception => - Put_Line (Standard_Error, "In " & Executable_Filename.all & ':' - & Exception_Message (E)); - Close_File (Executable_File); - Set_Exit_Status (1); -end Nexus_Trace_Gen; From a17af8156c461452da6e56efab0906c390e5bda1 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 20 Feb 2024 16:01:38 +0000 Subject: [PATCH 0715/1483] Make sure Python3 can parse all Python scripts --- qualification/qm/plans/qmconf.py | 6 +++--- testsuite/Qualif/qmconf.py | 6 +++--- testsuite/tests/M625-040-slow_on_windows/test.py | 12 ++++++------ testsuite/tests/gnatcov-run.py | 6 +++--- tools/gnatcov/examples/xml/xcov-report.py | 2 +- tools/gnatcov/scripts/syminfo.py | 14 +++++++------- 6 files changed, 23 insertions(+), 23 deletions(-) diff --git a/qualification/qm/plans/qmconf.py b/qualification/qm/plans/qmconf.py index c53fc4612..c0f94f8c1 100644 --- a/qualification/qm/plans/qmconf.py +++ b/qualification/qm/plans/qmconf.py @@ -17,8 +17,8 @@ os.path.dirname(common_file), "qm_prolog.py")) else: - print "Couldn't find common configuration file" - print common_file - print "from: %s" % __file__ + print("Couldn't find common configuration file") + print(common_file) + print("from: %s" % __file__) doc_id = plans_doc_id diff --git a/testsuite/Qualif/qmconf.py b/testsuite/Qualif/qmconf.py index bbaa070a4..a0a73b843 100644 --- a/testsuite/Qualif/qmconf.py +++ b/testsuite/Qualif/qmconf.py @@ -16,9 +16,9 @@ os.path.dirname(common_file), "qm_prolog.py")) else: - print "Couldn't find common configuration file" - print common_file - print "from: %s" % __file__ + print("Couldn't find common configuration file") + print(common_file) + print("from: %s" % __file__) rst_prolog += writer.define_role('raw-html(raw)', {'format': 'html'}) diff --git a/testsuite/tests/M625-040-slow_on_windows/test.py b/testsuite/tests/M625-040-slow_on_windows/test.py index 8cba10dd7..0a94c5d66 100644 --- a/testsuite/tests/M625-040-slow_on_windows/test.py +++ b/testsuite/tests/M625-040-slow_on_windows/test.py @@ -16,7 +16,7 @@ def run(action, repeat, tag): for i in range(repeat): action() end = time.clock() - print '%s: %2.5f' % (tag, end-start) + print('%s: %2.5f' % (tag, end-start)) def eval_gprbuild(): @@ -35,16 +35,16 @@ def eval(what): ps.strip_dirs() ps.sort_stats('time') - print "===================" - print "== %s ==" % what + print("===================") + print("== %s ==" % what) - print "-- profiling stats --" + print("-- profiling stats --") ps.print_stats() - print "-- callers --" + print("-- callers --") ps.print_callers() - print "-- callees --" + print("-- callees --") ps.print_callees() diff --git a/testsuite/tests/gnatcov-run.py b/testsuite/tests/gnatcov-run.py index 788abf72a..f7b51c749 100755 --- a/testsuite/tests/gnatcov-run.py +++ b/testsuite/tests/gnatcov-run.py @@ -79,16 +79,16 @@ def run_command_line(self): def run(self): - print '============== GNATCOV RUN ===================' + print('============== GNATCOV RUN ===================') if not self.args: - print 'gnatcov: missing EXE for run' + print('gnatcov: missing EXE for run') os.exit(1) Run( ['gnatcov', 'run'] + self.run_command_line() + self.args) - print '==============================================' + print('==============================================') runner = Runner() diff --git a/tools/gnatcov/examples/xml/xcov-report.py b/tools/gnatcov/examples/xml/xcov-report.py index 96375321f..b2b72f879 100755 --- a/tools/gnatcov/examples/xml/xcov-report.py +++ b/tools/gnatcov/examples/xml/xcov-report.py @@ -8,7 +8,7 @@ def show_violations(): def pp(source): output = source.pp_violations(r.get_levels()) if output: - print output + print(output) r.visitor(pp) if __name__ == '__main__': diff --git a/tools/gnatcov/scripts/syminfo.py b/tools/gnatcov/scripts/syminfo.py index ebb653d6d..b74fa2862 100755 --- a/tools/gnatcov/scripts/syminfo.py +++ b/tools/gnatcov/scripts/syminfo.py @@ -24,18 +24,18 @@ def format_symbol(symbol): def debug_interval(intval): seen_bounds = set() for i, bound in enumerate(intval.bounds): - print '{:02} - {:x}'.format(i, bound), try: value = intval.values[bound] except KeyError: - print '' + suffix = '' else: - print '-> {:x}'.format(intval.bounds[i + 1]), value + suffix = '-> {:x}'.format(intval.bounds[i + 1]), value + print('{:02} - {:x}{}'.format(i, bound, suffix)) seen_bounds.add(bound) - print '---' + print('---') for unseen in set(intval.values.keys()) - seen_bounds: - print '-> {:x}'.format(unseen), intval.values[unseen] - print '---' + print('-> {:x}'.format(unseen), intval.values[unseen]) + print('---') def get_sym_info(exe_filename): """Parse symbol info in `exe_filename` and return it as an interval map, @@ -91,7 +91,7 @@ def get_sym_info(exe_filename): try: symbol = sym_info[address] except KeyError: - print 'Not found' + print('Not found') sys.exit(1) else: print( From 389c32d78de56bd135f26539baaf63ad7b57d5dd Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 19 Feb 2024 18:55:14 +0000 Subject: [PATCH 0716/1483] SC_Obligations: integrate the "instrumented?" info in SCO_Descriptor --- tools/gnatcov/checkpoints.ads | 6 + tools/gnatcov/sc_obligations.adb | 274 +++++++++++++++++-------------- 2 files changed, 157 insertions(+), 123 deletions(-) diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index b9c85fb41..782930b8f 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -59,6 +59,12 @@ package Checkpoints is -- 13 -- Extend Files_Table.File_Info to distinguish homonym source files -- -- Note that we always use the last version when creating a checkpoint. + -- + -- TODO for the next checkpoint version: + -- + -- * Inline the "instrumented?" booleans in SCO_Descriptor + -- (de)serialization. They are currently stored as separate "maps" in + -- SIDs/checkpoints. type Checkpoint_Purpose is (Instrumentation, Consolidation); -- Purpose of checkpoint can be to provide: diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 5a03763d3..5cb28289d 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -398,6 +398,9 @@ package body SC_Obligations is Pragma_Name : Pragma_Id := Pragma_Id'First; -- For a Pragma_Statement, corresponding pragma identifier + Stmt_Instrumented : Boolean := True; + -- Whether this SCO was instrumented + when Condition => Value : Tristate; -- Indicates whether this condition is always true, always false, @@ -443,6 +446,12 @@ package body SC_Obligations is -- Count of distinct paths through the BDD from the root condition -- to any outcome. + Decision_Instrumented : Boolean := True; + -- Whether this SCO was instrumented for decision coverage + + Decision_Instrumented_For_MCDC : Boolean := True; + -- Whether this SCO was instrumented for MC/DC coverage + when Operator => Operands : Operand_Pair := (others => No_SCO_Id); -- Operands of this operator @@ -521,13 +530,11 @@ package body SC_Obligations is -- contain data loaded from a checkpoint. type Source_Coverage_Vectors is record - CU_Vector : CU_Info_Vectors.Vector; - ALI_Annotations : ALI_Annotation_Maps.Map; - Inst_Vector : Inst_Info_Vectors.Vector; - BDD_Vector : BDD.BDD_Vectors.Vector; - SCO_Vector : SCO_Vectors.Vector; - Non_Instr_SCOs : SCO_Sets.Set; - Non_Instr_MCDC_SCOs : SCO_Sets.Set; + CU_Vector : CU_Info_Vectors.Vector; + ALI_Annotations : ALI_Annotation_Maps.Map; + Inst_Vector : Inst_Info_Vectors.Vector; + BDD_Vector : BDD.BDD_Vectors.Vector; + SCO_Vector : SCO_Vectors.Vector; end record; ----------------------------------------- @@ -746,21 +753,6 @@ package body SC_Obligations is SCO_Vector : SCO_Vectors.Vector renames SC_Vectors.SCO_Vector; -- Vector of high-level Source Coverage Obligations (for all units) - Non_Instr_SCOs : SCO_Sets.Set renames - SC_Vectors.Non_Instr_SCOs; - -- Set of SCOs that were not instrumented, either for stmt or decision. - -- - -- ??? This should really be part of the SCO_Descriptor record, but doing - -- so would break backwards compatibility with checkpoints. This set should - -- be removed once manual serialization of checkpoints/SID files is - -- implemented. - - Non_Instr_MCDC_SCOs : SCO_Sets.Set renames - SC_Vectors.Non_Instr_MCDC_SCOs; - -- Set of decsion SCOs that were not instrumented for MCDC. - -- - -- ??? Same comment as above. - ----------- -- Image -- ----------- @@ -1141,6 +1133,10 @@ package body SC_Obligations is SCOD.Handler_Range := CLS.Read_Source_Location_Range; SCOD.Pragma_Name := Pragma_Id'Val (CLS.Read_U8); + -- See the TODO in the declaration of Checkpoint_Version + + SCOD.Stmt_Instrumented := True; + when Condition => SCOD.Value := CLS.Read_Tristate; Read (CLS, SCOD.PC_Set); @@ -1157,6 +1153,11 @@ package body SC_Obligations is SCOD.Aspect_Name := Aspect_Id'Val (CLS.Read_U8); SCOD.Path_Count := CLS.Read_Integer; + -- See the TODO in the declaration of Checkpoint_Version + + SCOD.Decision_Instrumented := True; + SCOD.Decision_Instrumented_For_MCDC := True; + when Operator => declare First : constant Operand_Position := @@ -1189,11 +1190,16 @@ package body SC_Obligations is Relocs : Checkpoint_Relocations renames CLS.Relocations; Real_CU : CU_Info renames CU_Vector.Reference (Real_CU_Id).Element.all; begin - -- Here we already have loaded full SCO information for this CU, so - -- all we need to do is to populate the tables mapping the SCO and - -- instance IDs for this unit in the checkpoint to their counterparts - -- in the current context, and merge non-instrumented SCO information - -- if available. + -- Here we already have loaded full SCO information for this CU. There + -- are two things to do: + -- + -- * Populate the tables mapping the SCO and instance IDs for this unit + -- in the checkpoint to their counterparts in the current context, and + -- merge non-instrumented SCO information if available. + -- + -- * Merge the information about non instrumented SCOs. We consider that + -- a SCO was instrumented iff at least one merged unit has it + -- instrumented. -- SCOs @@ -1206,6 +1212,31 @@ package body SC_Obligations is Old_SCO_Id + Real_CU.First_SCO - CP_CU.First_SCO); + + declare + Old_SCOD : SCO_Descriptor renames + CP_Vectors.SCO_Vector (Old_SCO_Id); + SCOD : SCO_Descriptor renames + SCO_Vector (Remap_SCO_Id (Relocs, Old_SCO_Id)); + begin + case SCOD.Kind is + when Statement => + if Old_SCOD.Stmt_Instrumented then + SCOD.Stmt_Instrumented := True; + end if; + + when Decision => + if Old_SCOD.Decision_Instrumented then + SCOD.Decision_Instrumented := True; + end if; + if Old_SCOD.Decision_Instrumented_For_MCDC then + SCOD.Decision_Instrumented_For_MCDC := True; + end if; + + when others => + null; + end case; + end; end loop; -- Instances @@ -1227,71 +1258,6 @@ package body SC_Obligations is -- Has_Code indication Real_CU.Has_Code := Real_CU.Has_Code or CP_CU.Has_Code; - - -- Non-Instrumented SCO sets - - declare - use SCO_Sets; - CU_CP_Set : Set; - CU_Set : Set; - Cur : Cursor; - Prev : Cursor; - begin - -- First process the non instrumented SCOs for stmt and decision - -- - -- Since the CU we are loading from the CP is already in the current - -- execution tables, a SCO is non-instrumented iff it was marked as - -- non-instrumented in the current execution, as well as in the CP. - -- - -- We need to take care not to process any SCO outside of the one of - -- this CU, so we build "local" sets containing only the SCOs in the - -- current CU to compute the intersection. - - for SCO of CP_Vectors.Non_Instr_SCOs loop - if SCO /= No_SCO_Id - and then SCO in CP_CU.First_SCO .. CP_CU.Last_SCO - then - CU_CP_Set.Insert (Remap_SCO_Id (Relocs, SCO)); - end if; - end loop; - - Cur := Non_Instr_SCOs.Ceiling (Real_CU.First_SCO); - while Has_Element (Cur) and then Element (Cur) <= Real_CU.Last_SCO - loop - CU_Set.Insert (Element (Cur)); - Prev := Cur; - Next (Cur); - - -- Remove the element from the main set so we can insert the - -- intersection of the CU-specific sets later. - - Non_Instr_SCOs.Delete (Prev); - end loop; - Non_Instr_SCOs.Union (CU_Set.Intersection (CU_CP_Set)); - - -- Same processing for MCDC SCOs - - CU_Set.Clear; - CU_CP_Set.Clear; - - for SCO of CP_Vectors.Non_Instr_MCDC_SCOs loop - if SCO /= No_SCO_Id - and then SCO in CP_CU.First_SCO .. CP_CU.Last_SCO - then - CU_CP_Set.Insert (Remap_SCO_Id (Relocs, SCO)); - end if; - end loop; - - Cur := Non_Instr_MCDC_SCOs.Ceiling (Real_CU.First_SCO); - while Has_Element (Cur) and then Element (Cur) <= Real_CU.Last_SCO - loop - CU_Set.Insert (Element (Cur)); - Prev := Cur; - Next (Cur); - Non_Instr_MCDC_SCOs.Delete (Prev); - end loop; - Non_Instr_MCDC_SCOs.Union (CU_Set.Intersection (CU_CP_Set)); - end; end Checkpoint_Load_Merge_Unit; ------------------------------ @@ -1637,23 +1603,6 @@ package body SC_Obligations is end; end loop; - -- Import information about non instrumented units. Only import SCOs - -- that belong to this CU, as others SCOs might belong to a CU already - -- present in the current execution, and which would not be simply - -- imported as is. - - for SCO of CP_Vectors.Non_Instr_SCOs loop - if SCO in CP_CU.First_SCO .. CP_CU.Last_SCO then - Non_Instr_SCOs.Insert (Remap_SCO_Id (Relocs, SCO)); - end if; - end loop; - - for SCO of CP_Vectors.Non_Instr_MCDC_SCOs loop - if SCO in CP_CU.First_SCO .. CP_CU.Last_SCO then - Non_Instr_MCDC_SCOs.Insert (Remap_SCO_Id (Relocs, SCO)); - end if; - end loop; - -- Perform final fixups and insert CU CP_CU.Last_Instance := @@ -1984,10 +1933,49 @@ package body SC_Obligations is SC_Obligations.BDD.Read (CLS, CP_Vectors.BDD_Vector); Read (CLS, CP_Vectors.SCO_Vector); - -- Load non-instrumented information + -- Initialize all the *Instrument* SCO_Descriptor components from "maps" + -- in CLS. See the TODO in the declaration of Checkpoint_Version. + + declare + SCOs : SCO_Sets.Set; + begin + -- First read uninstrumented SCOs for stmt/decision + + Read (CLS, SCOs); + for SCO of SCOs loop + declare + SCOD : SCO_Descriptor renames CP_Vectors.SCO_Vector (SCO); + begin + case SCOD.Kind is + when Statement => + SCOD.Stmt_Instrumented := False; + when Decision => + SCOD.Decision_Instrumented := False; + when others => + Fatal_Error + ("invalid non-instrumented SCO: " & SCOD.Kind'Image); + end case; + end; + end loop; + + -- Then read uninstrumented SCOs for MC/DC - Read (CLS, CP_Vectors.Non_Instr_SCOs); - Read (CLS, CP_Vectors.Non_Instr_MCDC_SCOs); + Read (CLS, SCOs); + for SCO of SCOs loop + declare + SCOD : SCO_Descriptor renames CP_Vectors.SCO_Vector (SCO); + begin + case SCOD.Kind is + when Decision => + SCOD.Decision_Instrumented_For_MCDC := False; + when others => + Fatal_Error + ("invalid non-instrumented SCO for MC/DC: " + & SCOD.Kind'Image); + end case; + end; + end loop; + end; -- Allocate mapping tables for SCOs, instance identifiers and BDD nodes @@ -2107,8 +2095,6 @@ package body SC_Obligations is Inst_Vector.Clear; BDD_Vector.Clear; SCO_Vector.Clear; - Non_Instr_SCOs.Clear; - Non_Instr_MCDC_SCOs.Clear; end Checkpoint_Clear; --------------------- @@ -2122,8 +2108,47 @@ package body SC_Obligations is Write (CSS.all, Inst_Vector); BDD.Write (CSS.all, BDD_Vector); Write (CSS.all, SCO_Vector); - Write (CSS.all, Non_Instr_SCOs); - Write (CSS.all, Non_Instr_MCDC_SCOs); + + -- Write sets of uninstrumented SCOs. See the TODO in the declaration of + -- Checkpoint_Version. + -- + -- First build sets of non instrumented SCOs from SCO_Vector, then write + -- these sets to the checkpoint. + + declare + Non_Instr_SCOs, Non_Instr_MCDC_SCOs : SCO_Sets.Set; + begin + for SCO in 1 .. SCO_Vector.Last_Index loop + declare + SCOD : SCO_Descriptor renames SCO_Vector (SCO); + Instr, Instr_MCDC : Boolean := True; + begin + case SCOD.Kind is + when Statement => + Instr := SCOD.Stmt_Instrumented; + when Decision => + Instr := SCOD.Decision_Instrumented; + Instr_MCDC := SCOD.Decision_Instrumented_For_MCDC; + when others => + null; + end case; + + -- Beware that the booleans in SCO_Descriptor are true for + -- *instrumented* SCOs while set elements indicate + -- *non-instrumented* SCOs. + + if not Instr then + Non_Instr_SCOs.Insert (SCO); + end if; + if not Instr_MCDC then + Non_Instr_MCDC_SCOs.Insert (SCO); + end if; + end; + end loop; + + Write (CSS.all, Non_Instr_SCOs); + Write (CSS.all, Non_Instr_MCDC_SCOs); + end; end Checkpoint_Save; --------------- @@ -2694,8 +2719,9 @@ package body SC_Obligations is ---------------------------- procedure Set_Stmt_SCO_Non_Instr (SCO : SCO_Id) is + SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); begin - Non_Instr_SCOs.Include (SCO); + SCOD.Stmt_Instrumented := False; end Set_Stmt_SCO_Non_Instr; -------------------------------- @@ -2703,8 +2729,9 @@ package body SC_Obligations is -------------------------------- procedure Set_Decision_SCO_Non_Instr (SCO : SCO_Id) is + SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); begin - Non_Instr_SCOs.Include (SCO); + SCOD.Decision_Instrumented := False; end Set_Decision_SCO_Non_Instr; ----------------------------------------- @@ -2712,8 +2739,9 @@ package body SC_Obligations is ----------------------------------------- procedure Set_Decision_SCO_Non_Instr_For_MCDC (SCO : SCO_Id) is + SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); begin - Non_Instr_MCDC_SCOs.Include (SCO); + SCOD.Decision_Instrumented_For_MCDC := False; end Set_Decision_SCO_Non_Instr_For_MCDC; --------------------------- @@ -2721,22 +2749,22 @@ package body SC_Obligations is --------------------------- function Stmt_SCO_Instrumented (SCO : SCO_Id) return Boolean is - (not Non_Instr_SCOs.Contains (SCO)); + (SCO_Vector (SCO).Stmt_Instrumented); ------------------------------- -- Decision_SCO_Instrumented -- ------------------------------- function Decision_SCO_Instrumented (SCO : SCO_Id) return Boolean is - (not Non_Instr_SCOs.Contains (SCO)); + (SCO_Vector (SCO).Decision_Instrumented); ---------------------------------------- -- Decision_SCO_Instrumented_For_MCDC -- ---------------------------------------- function Decision_SCO_Instrumented_For_MCDC - (SCO : SCO_Id) return Boolean is - (not Non_Instr_MCDC_SCOs.Contains (SCO)); + (SCO : SCO_Id) return Boolean + is (SCO_Vector (SCO).Decision_Instrumented_For_MCDC); ----------- -- Image -- From 5567cb5e8c4ddaa87dde5cc331ee7dd927956ef0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 21 Feb 2024 10:53:41 +0000 Subject: [PATCH 0717/1483] SUITE.tutils.gprbuild_gargs_with: do not add ".gpr" ext. to rt. project Is it legal for callers of the gprbuild or build_and_rurn functions to pass a filename (/path/to/gnatcov_rts.gpr) instead of a project name (gnatcov_rts): do not add the ".gpr" extension so that both cases work correctly. --- testsuite/SUITE/tutils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index e8680361c..5241d3850 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -157,7 +157,7 @@ def gprbuild_gargs_with(thisgargs, runtime_project or RUNTIME_INFO.gnatcov_rts_project ) result += [ - f"--implicit-with={runtime_project}.gpr", + f"--implicit-with={runtime_project}", "--src-subdirs=gnatcov-instr", ] From 7c209dcf551b23b1085ce88df946e1ec7ccf5162 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 22 Feb 2024 14:17:09 +0000 Subject: [PATCH 0718/1483] SUITE.tutils.run_cov_program: handle dump-channel=bin-file with pycross On targets that have filesystem support, it is possible for testcases to use the bin-file dump channel, and thus have the source trace file created directly on the target filesystem. pycross happens to mount that filesystem on the host, and with run-cross2's --save-temps argument, it is possible to access that mount point after the target program has completed. Do this to extract source traces and put them where the rest of the testtsuite expect them: in the current directory. --- testsuite/SUITE/tutils.py | 42 +++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 5241d3850..8f072d8e4 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -15,6 +15,7 @@ import time +from e3.fs import cp from e3.os.fs import touch, unixpath, which from e3.os.process import DEVNULL, Run @@ -900,22 +901,32 @@ def run_cov_program(executable, out=None, env=None, exec_args=None, args = [] exec_args = exec_args or [] inp = None + use_pycross = False # If we are in a cross configuration, run the program using run-cross2 if thistest.options.target and thistest.env.target.platform != "c": + use_pycross = True + # We absolutely need a machine name to run programs with run-cross2 assert thistest.options.board or thistest.env.target.machine - # run-cross2 is a python script. As Windows does not parse shebangs, - # use the python executable as main program instead of the script. - args.append(sys.executable) - args.append(which("run-cross2")) target = thistest.env.target.platform if thistest.options.board: target += f",,{thistest.options.board}" else: target += f",,{thistest.env.target.machine}" - args.append(f"--target={target}") + + # run-cross2 is a python script. As Windows does not parse shebangs, + # use the python executable as main program instead of the script. + args += [ + sys.executable, + which("run-cross2"), + f"--target={target}", + # Instruct pycross to preserve temporary files, which includes the + # directory that is mounted in the target's filesystem. This is + # where the source trace may be created (see below). + "--save-temps", + ] else: # Native programs using a light runtime can't set the exit code, and # will often terminate with a non-zero status code even though nothing @@ -927,9 +938,24 @@ def run_cov_program(executable, out=None, env=None, exec_args=None, args.append(executable) args.extend(exec_args) - return cmdrun(args, out=out, inp=inp, env=env, - register_failure=register_failure, - for_pgm=True) + result = cmdrun( + args, + out=out, + inp=inp, + env=env, + register_failure=register_failure, + for_pgm=True, + ) + + # If the program was run under pycross, hoist source traces that the + # program may have created on the target filesystem so that the rest of the + # testsuite finds sources traces where they expect: in the current + # directory. + if use_pycross: + for filename in glob.glob("hostfs-*/test/*.srctrace"): + cp(filename, ".") + + return result def do(command): From 8f36cf72d657176d37d26b8310ff3867ac316a2c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 21 Feb 2024 10:55:33 +0000 Subject: [PATCH 0719/1483] rts/gnatcov_rts-traces-output-files.adb: kill warnings for no exc. prop. Extend the existing workaround in gnatcov_rts to accomodate for the runtimes that have the No_Exception_Propagation restriction to this source file: native runtimes are unlikely to have this restriction, but gnatcov_rts's full profile is actually compiled with some non-native runtimes (for instance: aarch64-qnx/light-tasking). A commit following this one will add a testcase to check general support for the full profile on such runtimes. --- .../rts/gnatcov_rts-traces-output-files.adb | 33 ++++++++++++++----- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb index c09d472d8..89e76697f 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb @@ -95,16 +95,33 @@ package body GNATcov_RTS.Traces.Output.Files is Filename : chars_ptr := Default_Trace_Filename; Program_Name : String := "unknown"; Exec_Date : Time := Clock; - User_Data : String := "") is + User_Data : String := "") + is + -- See the note about -gnatw.X in gnatcov_rts.gpr + + pragma Warnings (Off); + Buffers_Groups_C : constant GNATcov_RTS_Coverage_Buffers_Group_Array := + (Buffers_Groups'Length, Buffers_Groups'Address); + Program_Name_C : constant GNATcov_RTS_String := + (Program_Name'Address, Program_Name'Length); + Exec_Date_C : constant Unsigned_64 := + Interfaces.Unsigned_64 (Exec_Date); + User_Data_C : constant GNATcov_RTS_String := + (User_Data'Address, User_Data'Length); + pragma Warnings (On); + + Result : constant int := + Write_Trace_File_C + (Buffers_Groups_C, + Filename, + Program_Name_C, + Exec_Date_C, + User_Data_C); begin - if Write_Trace_File_C - ((Buffers_Groups'Length, Buffers_Groups'Address), - Filename, - (Program_Name'Address, Program_Name'Length), - Interfaces.Unsigned_64 (Exec_Date), - (User_Data'Address, User_Data'Length)) = 1 - then + if Result = 1 then + pragma Warnings (Off); raise IO_Error; + pragma Warnings (On); end if; end Write_Trace_File; From 9e4ab67321ac80fc1d6809c376883f4aa09aa5e5 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 21 Feb 2024 09:59:12 +0000 Subject: [PATCH 0720/1483] rts/gnatcov_rts-traces-output-files.adb: delegate error msg output to C Some runtimes (for instance aarch64-qnx/light-tasking) provide on the C side everything necessary to create source traces files and stderr support, yet their Ada.Text_IO package does not provide Standard_Error. To handle correctly these runtimes, delegate the output of error messages to C code. --- .../tests/instr-cov/239-qnx-bin-file/main.adb | 6 ++ .../tests/instr-cov/239-qnx-bin-file/test.opt | 6 ++ .../tests/instr-cov/239-qnx-bin-file/test.py | 44 ++++++++++++ .../rts/gnatcov_rts-traces-output-files.adb | 70 +++++++------------ 4 files changed, 80 insertions(+), 46 deletions(-) create mode 100644 testsuite/tests/instr-cov/239-qnx-bin-file/main.adb create mode 100644 testsuite/tests/instr-cov/239-qnx-bin-file/test.opt create mode 100644 testsuite/tests/instr-cov/239-qnx-bin-file/test.py diff --git a/testsuite/tests/instr-cov/239-qnx-bin-file/main.adb b/testsuite/tests/instr-cov/239-qnx-bin-file/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/instr-cov/239-qnx-bin-file/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt b/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt new file mode 100644 index 000000000..1dedc665b --- /dev/null +++ b/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt @@ -0,0 +1,6 @@ +-- The very purpose of this test is to check the correct support of +-- gnatcov_rts' full profile on embedded runtimes: the only currently known +-- configuration where this makes sense is the light-tasking runtime for a QNX +-- target. +src-traces,qnx,RTS_LIGHT_TASKING +ALL DEAD diff --git a/testsuite/tests/instr-cov/239-qnx-bin-file/test.py b/testsuite/tests/instr-cov/239-qnx-bin-file/test.py new file mode 100644 index 000000000..2468ed702 --- /dev/null +++ b/testsuite/tests/instr-cov/239-qnx-bin-file/test.py @@ -0,0 +1,44 @@ +""" +Check that the "full" profile for GNATcov_RTS works correctly on QNX. +""" + +import os.path + +from e3.fs import mkdir + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +tmp = Wdir("tmp_") + +# Build and install our special gnatcov_rts build +install_dir = os.path.abspath("install") +mkdir(install_dir) +xcov( + ["setup", "--rts-profile=full", "--prefix", install_dir, "-q"], + out="setup.txt", +) +thistest.fail_if_not_equal( + "'gnatcov setup' output not empty", + "", + contents_of("setup.txt"), +) +gnatcov_rts_gpr = os.path.join(install_dir, "share", "gpr", "gnatcov_rts.gpr") + +# Compute code coverage for the test project, to make sure the runtime's +# implementation of the bin-file dump channel works as expected. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], + dump_channel="bin-file", + runtime_project=gnatcov_rts_gpr, +) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) + +thistest.result() diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb index 89e76697f..14a0276c8 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb @@ -24,9 +24,6 @@ -- This unit needs to be compilable with Ada 95 compilers -with Ada.Text_IO; use Ada.Text_IO; -with Ada.Unchecked_Conversion; - with Interfaces.C; use Interfaces.C; with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; @@ -42,6 +39,17 @@ package body GNATcov_RTS.Traces.Output.Files is pragma Import (C, Write_Trace_File_C, External_Name => "gnatcov_rts_write_trace_file"); + procedure Write_Trace_File_Wrapper_C + (Buffers_Groups : GNATcov_RTS_Coverage_Buffers_Group_Array; + Filename : chars_ptr; + Program_Name : GNATcov_RTS_String; + Exec_Date : Unsigned_64; + User_Data : GNATcov_RTS_String); + pragma Import + (C, + Write_Trace_File_Wrapper_C, + External_Name => "gnatcov_rts_write_trace_file_wrapper"); + function Default_Trace_Filename_C (Env_Var : chars_ptr; Prefix : chars_ptr; @@ -136,51 +144,21 @@ package body GNATcov_RTS.Traces.Output.Files is Exec_Date : Time := Clock; User_Data : String := "") is + -- See the note about -gnatw.X in gnatcov_rts.gpr - function C_Strerror (Errnum : C.int) return C.Strings.chars_ptr; - pragma Import (C, C_Strerror, "strerror"); - -- strerror is already a function, we can bind to its symbol directly - - function C_Errno return C.Int; - pragma Import (C, C_Errno, "gnatcov_rts_get_errno"); - -- Get the errno value through the wrapper declared in - -- gnatcov_rts_c-os_interface.h. - + pragma Warnings (Off); + Buffers_Groups_C : constant GNATcov_RTS_Coverage_Buffers_Group_Array := + (Buffers_Groups'Length, Buffers_Groups'Address); + Program_Name_C : constant GNATcov_RTS_String := + (Program_Name'Address, Program_Name'Length); + Exec_Date_C : constant Unsigned_64 := + Interfaces.Unsigned_64 (Exec_Date); + User_Data_C : constant GNATcov_RTS_String := + (User_Data'Address, User_Data'Length); + pragma Warnings (On); begin - Write_Trace_File - (Buffers_Groups, Filename, Program_Name, Exec_Date, User_Data); - exception - when IO_Error => - declare - function "+" is new Ada.Unchecked_Conversion - (chars_ptr, System.Address); - - Error_Msg : constant chars_ptr := C_Strerror (C_Errno); - - -- Since we cannot use the secondary stack, it is not possible to - -- call Interfaces.C.Strings.Value to turn chars_ptr values into - -- String ones. Workaround this with overlays. - - Error_Msg_Length : constant Natural := - Natural (Strlen (Error_Msg)); - Filename_Length : constant Natural := Natural (Strlen (Filename)); - - Ada_Error_Msg : String (1 .. Error_Msg_Length); - for Ada_Error_Msg'Address use +Error_Msg; - pragma Import (Ada, Ada_Error_Msg); - - Ada_Filename : String (1 .. Filename_Length); - for Ada_Filename'Address use +Filename; - pragma Import (Ada, Ada_Filename); - begin - Put - (Standard_Error, - "Error occurred while creating the trace file "); - Put (Standard_Error, Ada_Filename); - Put (Standard_Error, ": "); - Put (Standard_Error, Ada_Error_Msg); - New_Line (Standard_Error); - end; + Write_Trace_File_Wrapper_C + (Buffers_Groups_C, Filename, Program_Name_C, Exec_Date_C, User_Data_C); end Write_Trace_File_Wrapper; end GNATcov_RTS.Traces.Output.Files; From b344dd47853dd253b3326f993207bc7e10e942c3 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 22 Feb 2024 14:34:58 +0000 Subject: [PATCH 0721/1483] GNATcov_RTS: simplify the source trace file writing API Merge the "write_trace_file" and "write_trace_file_wrapper" routines in the Ada and C APIs to keep only "write_trace_file" procedures that print error messages on stderr. This makes the RTS API/implementation simpler. This removes the possibility for gnatcov users to write manual dumping code that handles source trace file creation failure, but this use case is considered too theoretical, especially with gnatcov's manual dump trigger capabilities that we have nowadays. --- tools/gnatcov/instrument-ada_unit.adb | 3 +- tools/gnatcov/instrument-c.adb | 5 +- .../rts/gnatcov_rts-traces-output-files.adb | 58 ++----------------- .../rts/gnatcov_rts-traces-output-files.ads | 15 +---- .../rts/gnatcov_rts_c-traces-output-files.c | 23 ++------ .../rts/gnatcov_rts_c-traces-output-files.h | 13 +---- 6 files changed, 19 insertions(+), 98 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index b2343c76f..0af267ad7 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8936,8 +8936,7 @@ package body Instrument.Ada_Unit is Output_Unit.Append (To_Unbounded_String ("Traces")); Output_Unit.Append (To_Unbounded_String ("Output." & Unit)); - Output_Proc := Output_Unit - & To_Unbounded_String ("Write_Trace_File_Wrapper"); + Output_Proc := Output_Unit & To_Unbounded_String ("Write_Trace_File"); end; declare diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 6b87bc70d..799b73340 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3709,9 +3709,8 @@ package body Instrument.C is Output_Proc : constant String := (case Dump_Config.Channel is - when Binary_File => "gnatcov_rts_write_trace_file_wrapper", - when Base64_Standard_Output => - "gnatcov_rts_write_trace_file_base64"); + when Binary_File => "gnatcov_rts_write_trace_file", + when Base64_Standard_Output => "gnatcov_rts_write_trace_file_base64"); Indent1 : constant String := " "; Indent2 : constant String := Indent1 & " "; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb index 14a0276c8..83740c9a6 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb @@ -30,16 +30,7 @@ with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; package body GNATcov_RTS.Traces.Output.Files is - function Write_Trace_File_C - (Buffers_Groups : GNATcov_RTS_Coverage_Buffers_Group_Array; - Filename : chars_ptr; - Program_Name : GNATcov_RTS_String; - Exec_Date : Unsigned_64; - User_Data : GNATcov_RTS_String) return int; - pragma Import - (C, Write_Trace_File_C, External_Name => "gnatcov_rts_write_trace_file"); - - procedure Write_Trace_File_Wrapper_C + procedure Write_Trace_File_C (Buffers_Groups : GNATcov_RTS_Coverage_Buffers_Group_Array; Filename : chars_ptr; Program_Name : GNATcov_RTS_String; @@ -47,8 +38,8 @@ package body GNATcov_RTS.Traces.Output.Files is User_Data : GNATcov_RTS_String); pragma Import (C, - Write_Trace_File_Wrapper_C, - External_Name => "gnatcov_rts_write_trace_file_wrapper"); + Write_Trace_File_C, + External_Name => "gnatcov_rts_write_trace_file"); function Default_Trace_Filename_C (Env_Var : chars_ptr; @@ -117,48 +108,9 @@ package body GNATcov_RTS.Traces.Output.Files is User_Data_C : constant GNATcov_RTS_String := (User_Data'Address, User_Data'Length); pragma Warnings (On); - - Result : constant int := - Write_Trace_File_C - (Buffers_Groups_C, - Filename, - Program_Name_C, - Exec_Date_C, - User_Data_C); - begin - if Result = 1 then - pragma Warnings (Off); - raise IO_Error; - pragma Warnings (On); - end if; - end Write_Trace_File; - - ------------------------------ - -- Write_Trace_File_Wrapper -- - ------------------------------ - - procedure Write_Trace_File_Wrapper - (Buffers_Groups : Coverage_Buffers_Group_Array; - Filename : chars_ptr := Default_Trace_Filename; - Program_Name : String := "unknown"; - Exec_Date : Time := Clock; - User_Data : String := "") - is - -- See the note about -gnatw.X in gnatcov_rts.gpr - - pragma Warnings (Off); - Buffers_Groups_C : constant GNATcov_RTS_Coverage_Buffers_Group_Array := - (Buffers_Groups'Length, Buffers_Groups'Address); - Program_Name_C : constant GNATcov_RTS_String := - (Program_Name'Address, Program_Name'Length); - Exec_Date_C : constant Unsigned_64 := - Interfaces.Unsigned_64 (Exec_Date); - User_Data_C : constant GNATcov_RTS_String := - (User_Data'Address, User_Data'Length); - pragma Warnings (On); begin - Write_Trace_File_Wrapper_C + Write_Trace_File_C (Buffers_Groups_C, Filename, Program_Name_C, Exec_Date_C, User_Data_C); - end Write_Trace_File_Wrapper; + end Write_Trace_File; end GNATcov_RTS.Traces.Output.Files; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads index a42e00386..cd46d2721 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads @@ -51,9 +51,6 @@ package GNATcov_RTS.Traces.Output.Files is -- gnatcov_rts_default_trace_filename function defined in -- gnatcov_rts_c-traces-output-files.h for more information. - IO_Error : exception; - -- Exception we raise in case of errors during the trace file creation - procedure Write_Trace_File (Buffers_Groups : Coverage_Buffers_Group_Array; Filename : chars_ptr := Default_Trace_Filename; @@ -61,15 +58,7 @@ package GNATcov_RTS.Traces.Output.Files is Exec_Date : Time := Clock; User_Data : String := ""); -- Write a trace file in Filename to contain the data in Buffers_Groups. - -- If unsuccessful, raise IO_Error and leave the error code in errno. - - procedure Write_Trace_File_Wrapper - (Buffers_Groups : Coverage_Buffers_Group_Array; - Filename : chars_ptr := Default_Trace_Filename; - Program_Name : String := "unknown"; - Exec_Date : Time := Clock; - User_Data : String := ""); - -- Wrapper around Write_Trace_File that writes an error message to the - -- standard error if the trace file could not be written. + -- If the source trace file creation fails, print an error message on the + -- standard error. end GNATcov_RTS.Traces.Output.Files; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c index 5278a0d4a..b0064ca22 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c @@ -158,7 +158,7 @@ gnatcov_rts_default_trace_filename (const char *env_var, const char *prefix, } /* See gnatcov_rts_c-traces-output-files.h. */ -int +void gnatcov_rts_write_trace_file ( const struct gnatcov_rts_coverage_buffers_group_array *buffers_groups, const char *filename, struct gnatcov_rts_string program_name, @@ -166,24 +166,13 @@ gnatcov_rts_write_trace_file ( { FILE *file = fopen (filename, "wb+"); if (!file) - return 1; + { + fprintf (stderr, "Error occurred while creating the trace file %s: %s\n", + filename, strerror (errno)); + return; + } gnatcov_rts_generic_write_trace_file (file, buffers_groups, program_name, exec_date, user_data, write_bytes); fclose (file); - return 0; -} - -/* See gnatcov_rts_c-traces-output-files.h. */ -void -gnatcov_rts_write_trace_file_wrapper ( - const struct gnatcov_rts_coverage_buffers_group_array *buffers_groups, - const char *filename, struct gnatcov_rts_string program_name, - uint64_t exec_date, struct gnatcov_rts_string user_data) -{ - if (gnatcov_rts_write_trace_file (buffers_groups, filename, program_name, - exec_date, user_data) - != 0) - fprintf (stderr, "Error occurred while creating the trace file %s: %s\n", - filename, strerror (errno)); } diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h index 01ca267b7..83b00cb94 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.h @@ -63,16 +63,9 @@ extern "C" EXEC_DATE is given to produce the timestamp. Use the current time by default. - Return 0 if the trace creation was successful, 1 otherwise. In case of - error, ERRNO is left to the number for the cause of error. */ - extern int gnatcov_rts_write_trace_file ( - const struct gnatcov_rts_coverage_buffers_group_array *buffers_groups, - const char *filename, struct gnatcov_rts_string program_name, - uint64_t exec_date, struct gnatcov_rts_string user_data); - - /* Call gnatcov_rts_write_trace_file and print an error message on the - standard error if the trace could not be created. */ - extern void gnatcov_rts_write_trace_file_wrapper ( + If the source trace file creation fails, print an error message on the + standard error. */ + extern void gnatcov_rts_write_trace_file ( const struct gnatcov_rts_coverage_buffers_group_array *buffers_groups, const char *filename, struct gnatcov_rts_string program_name, uint64_t exec_date, struct gnatcov_rts_string user_data); From c588ff3f0589cd5fbdb16a1d86f30a1882eaba8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 21 Feb 2024 11:15:57 +0100 Subject: [PATCH 0722/1483] Instrument.Projects: Limit processing of externally built projects This brings in line the behavior of the manual dump trigger processing with the rest of the gnatcov, which is to only process externally-built projects only if requested with --externally-built-projects. --- .../S603-009-externally-built/main/main.adb | 1 + .../S603-009-externally-built/main/main.gpr | 6 - .../tests/S603-009-externally-built/test.py | 283 ++++++++++++------ tools/gnatcov/instrument-projects.adb | 5 +- 4 files changed, 190 insertions(+), 105 deletions(-) delete mode 100644 testsuite/tests/S603-009-externally-built/main/main.gpr diff --git a/testsuite/tests/S603-009-externally-built/main/main.adb b/testsuite/tests/S603-009-externally-built/main/main.adb index 52965a61f..84c8ee74b 100644 --- a/testsuite/tests/S603-009-externally-built/main/main.adb +++ b/testsuite/tests/S603-009-externally-built/main/main.adb @@ -4,4 +4,5 @@ procedure Main is Dummy : Natural := Mylib.Fact (1); begin null; + pragma Annotate (Xcov, Dump_Buffers); end Main; diff --git a/testsuite/tests/S603-009-externally-built/main/main.gpr b/testsuite/tests/S603-009-externally-built/main/main.gpr deleted file mode 100644 index e6fc16ab5..000000000 --- a/testsuite/tests/S603-009-externally-built/main/main.gpr +++ /dev/null @@ -1,6 +0,0 @@ -with "mylib"; - -project Main is - for Object_Dir use "obj"; - for Main use ("main.adb"); -end Main; diff --git a/testsuite/tests/S603-009-externally-built/test.py b/testsuite/tests/S603-009-externally-built/test.py index 00bd9849b..dd7b772d3 100644 --- a/testsuite/tests/S603-009-externally-built/test.py +++ b/testsuite/tests/S603-009-externally-built/test.py @@ -7,129 +7,216 @@ import re import shutil +from e3.fs import cp + from SCOV.instr import xcov_instrument from SCOV.minicheck import build_and_run, check_xcov_reports from SUITE.context import thistest from SUITE.control import env from SUITE.cutils import Wdir, contents_of, indent from SUITE.gprutils import GPRswitches -from SUITE.tutils import gprbuild, gprinstall, xcov +from SUITE.tutils import gprbuild, gprfor, gprinstall, xcov + + +# Dump triggers to be tested. The default one for the platform and manual for +# source traces, irrelevant for bin traces, we simply need one to run the +# test. +# +# TODO the test seems to be dead for bin traces, can we simplify this??? +dump_triggers = ( + ["manual", "auto"] + if thistest.options.trace_mode == "src" + else ["bin-trace"] +) -mylib_gpr = os.path.abspath(os.path.join('mylib', 'mylib.gpr')) -mylib_obj_dir = os.path.abspath(os.path.join('mylib', 'obj')) -main_dir = os.path.abspath('main') -main_gpr = os.path.join(main_dir, 'main.gpr') -main_obj_dir = os.path.join(main_dir, 'obj') +def check_coverage( + project, externally_built, expected_cov, trace_file, register_failure=True +): + """ + Create a coverage report for project from trace_file, + requesting coverage for externally-built projects based on + externally_built, and check the report against expected_cov. + Return the process handle and the output filename for the + "gnatcov coverage" command and ignore its exit status if + register_failure is False. + """ + output_dir = ( + f"xcov_{os.path.basename(project[:-4])}_" + f"{'ext' if externally_built else 'no_ext'}" + ) + thistest.log(f"coverage in {output_dir}") + gnatcov_log = f"gnatcov_{output_dir}.log" + if os.path.isdir(output_dir): + shutil.rmtree(output_dir) + os.mkdir(output_dir) + + args = [ + "coverage", + "-cstmt", + "-axcov", + "-P", + project, + "--output-dir", + output_dir, + trace_file, + ] + if externally_built: + args.append("--externally-built-projects") + p = xcov(args, out=gnatcov_log, register_failure=register_failure) + + if not register_failure: + return p, gnatcov_log + + check_xcov_reports(output_dir, expected_cov) + + +def check_one(dump_trigger, lib_prj): + """ + Build and run the main project, inspecting externally built projects, + then check all four combinations of project/--externally-built-projects + to check the behaviors and results produced by gnatcov, for a given + dump trigger (if applicable) and installed library project. + """ + tmp.to_subdir(f"tmp_{dump_trigger}") + + # Generate a project file for this subdir + obj_main = os.path.abspath("obj_main") + main_gpr = gprfor( + prjid="main", + mains=["main.adb"], + srcdirs=["../main"], + objdir=obj_main, + exedir=obj_main, + deps=[lib_prj], + ) + thistest.log(f"====== Testing {dump_trigger} =======") + # Build the main project using this and run it to produce a trace file + xcov_args = build_and_run( + gprsw=GPRswitches( + root_project=main_gpr, + externally_built_projects=True, + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + gpr_obj_dir=obj_main, + gpr_exe_dir=obj_main, + gprsw_for_coverage=False, + dump_trigger=dump_trigger, + manual_prj_name="main", + ) + trace_file = xcov_args[-1] + + # Check that the instrumenter hasn't tried to instrument the installed + # project + thistest.fail_if( + os.path.exists( + os.path.join(install_dir, "share", "gpr", "mylib-gnatcov-instr") + ), + '"gnatcov instrument" instrumented the installed project', + ) + + # First, make sure that "gnatcov coverage" on an externally built project + # returns an error. + p, log_filename = check_coverage( + project=installed_mylib_gpr, + externally_built=False, + expected_cov=None, + trace_file=trace_file, + register_failure=False, + ) + thistest.fail_if( + p.status == 0, + "gnatcov was supposed to complain when provided an externally built" + " project", + ) + coverage_log = contents_of(log_filename).strip() + expected_log = re.compile( + # Regexp to accommodate output differences between the various + # supported platforms. + "[^\n]*gnatcov[^\n]*: {}".format( + re.escape( + "Root project is marked as externally built, while externally" + " built projects are ignored by default. Consider using" + " --externally-built-projects." + ) + ) + ) + thistest.fail_if( + not expected_log.match(coverage_log), + 'Unexpected output for "gnatcov coverage". Expected:\n' + "{}\n" + "but got:\n" + "{}".format(indent(expected_log.pattern), indent(coverage_log)), + ) + + # It should not complain with --externally-built-projects + p = check_coverage( + project="mylib.gpr", + externally_built=True, + trace_file=trace_file, + expected_cov={"mylib.adb.xcov": {"+": {5, 6}, "-": {8}}}, + ) + + # Make sure coverage computation gives the expected result with and + # without --externally-built-projects + check_coverage( + project=main_gpr, + externally_built=False, + trace_file=trace_file, + expected_cov={"main.adb.xcov": {"+": {4, 6}}}, + ) + check_coverage( + project=main_gpr, + externally_built=True, + trace_file=trace_file, + expected_cov={ + "main.adb.xcov": {"+": {4, 6}}, + "mylib.adb.xcov": {"+": {5, 6}, "-": {8}}, + }, + ) + + +tmp = Wdir("tmp_") + +# Copy the library sources in the working directory +cp("../mylib", ".", recursive=True) + +mylib_obj_dir = "obj_lib" +mylib_gpr = os.path.join("mylib", "mylib.gpr") # Create the installation directory and add it to gprbuild's project lookup # path. -tmp = Wdir('tmp_') -install_dir = os.path.abspath('install') -gpr_install_dir = os.path.join(install_dir, 'share', 'gpr') -installed_mylib_gpr = os.path.join(gpr_install_dir, 'mylib.gpr') +install_dir = os.path.abspath("install") +gpr_install_dir = os.path.join(install_dir, "share", "gpr") +installed_mylib_gpr = os.path.join(gpr_install_dir, "mylib.gpr") os.mkdir(install_dir) env.add_search_path("GPR_PROJECT_PATH", gpr_install_dir) # Build and install the library project -if thistest.options.trace_mode == 'src': +if thistest.options.trace_mode == "src": xcov_instrument( gprsw=GPRswitches(root_project=mylib_gpr), - covlevel='stmt', - gpr_obj_dir=mylib_obj_dir + covlevel="stmt", + gpr_obj_dir=mylib_obj_dir, ) gprbuild(mylib_gpr) -if thistest.options.trace_mode == 'src': +if thistest.options.trace_mode == "src": gprinstall( mylib_gpr, [ - f'--prefix={install_dir}', - '--src-subdirs=gnatcov-instr', - '--implicit-with=gnatcov_rts' - ] + f"--prefix={install_dir}", + "--src-subdirs=gnatcov-instr", + "--implicit-with=gnatcov_rts", + ], ) else: - gprinstall(mylib_gpr, f'--prefix={install_dir}') - -# Build the main project using this and run it to produce a trace file -xcov_args = build_and_run( - gprsw=GPRswitches(root_project=main_gpr, externally_built_projects=True), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov'], - gpr_obj_dir=main_obj_dir, - gpr_exe_dir=main_obj_dir, - gprsw_for_coverage=False -) -trace_file = xcov_args[-1] - -# Check that the instrumenter hasn't tried to instrument the installed project -thistest.fail_if( - os.path.exists(os.path.join(install_dir, - 'share', 'gpr', 'mylib-gnatcov-instr')), - '"gnatcov instrument" instrumented the installed project' -) - -output_dir = 'xcov-report' -gnatcov_log = 'gnatcov.log' - - -def check_coverage(project, externally_built, expected_cov, - register_failure=True): - if os.path.isdir(output_dir): - shutil.rmtree(output_dir) - os.mkdir(output_dir) - - args = ['coverage', '-cstmt', '-axcov', '-P', project, - '--output-dir', output_dir, trace_file] - if externally_built: - args.append('--externally-built-projects') - p = xcov(args, out=gnatcov_log, register_failure=register_failure) - - if not register_failure: - return p - - check_xcov_reports(output_dir, expected_cov) - + gprinstall(mylib_gpr, f"--prefix={install_dir}") -# First, make sure that "gnatcov coverage" on an externally built project -# returns an error. -p = check_coverage( - project=installed_mylib_gpr, externally_built=False, expected_cov=None, - register_failure=False) -thistest.fail_if( - p.status == 0, - 'gnatcov was supposed to complain when provided an externally built' - ' project') -coverage_log = contents_of(gnatcov_log).strip() -expected_log = re.compile( - # Regexp to accommodate output differences between the various - # supported platforms. - '[^\n]*gnatcov[^\n]*: {}'.format(re.escape( - 'Root project is marked as externally built, while externally built' - ' projects are ignored by default. Consider using' - ' --externally-built-projects.'))) -thistest.fail_if(not expected_log.match(coverage_log), - 'Unexpected output for "gnatcov coverage". Expected:\n' - '{}\n' - 'but got:\n' - '{}'.format(indent(expected_log.pattern), - indent(coverage_log))) - -# It should not complain with --externally-built-projects -p = check_coverage( - project='mylib.gpr', externally_built=True, - expected_cov={'mylib.adb.xcov': {'+': {5, 6}, '-': {8}}}) - -# Make sure coverage computation gives the expected result with and without -# --externally-built-projects -check_coverage( - project=main_gpr, externally_built=False, - expected_cov={'main.adb.xcov': {'+': {4, 6}}}) -check_coverage( - project=main_gpr, externally_built=True, - expected_cov={'main.adb.xcov': {'+': {4, 6}}, - 'mylib.adb.xcov': {'+': {5, 6}, '-': {8}}}) +# Run the coverage workflow for each dump trigger +for dump_trigger in dump_triggers: + check_one(dump_trigger, installed_mylib_gpr) thistest.result() diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 88415691f..09421d36c 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -910,7 +910,10 @@ is use Files_Table; Instr_Units : Unit_Sets.Set; Source_Files : GNATCOLL.VFS.File_Array_Access := - Source.Project.Source_Files (Recursive => True); + Source.Project.Source_Files + (Recursive => True, + Include_Externally_Built => + Externally_Built_Projects_Processing_Enabled); begin for S of Source_Files.all loop declare From 367e5dd8819db315576da483a61882597ac25153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 21 Feb 2024 11:45:42 +0100 Subject: [PATCH 0723/1483] instrument-projects.adb: Do not process unknown sources for manual dump When generating the buffer list unit for a given project, after insertion of a manual buffer dump, gnatcov iterates over all the sources to determine the set of actually instrumented sources. This crashed on sources of an unknown language for gnatcov. Properly ignore them instead. --- .../manual-dump/unknown_lang/ident.s | 23 +++++++++++++ .../manual-dump/unknown_lang/main_ada.adb | 11 ++++++ .../manual-dump/unknown_lang/test.opt | 2 ++ .../manual-dump/unknown_lang/test.py | 34 +++++++++++++++++++ tools/gnatcov/instrument-projects.adb | 12 +++++++ 5 files changed, 82 insertions(+) create mode 100644 testsuite/tests/instr-cov/manual-dump/unknown_lang/ident.s create mode 100644 testsuite/tests/instr-cov/manual-dump/unknown_lang/main_ada.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/unknown_lang/test.opt create mode 100644 testsuite/tests/instr-cov/manual-dump/unknown_lang/test.py diff --git a/testsuite/tests/instr-cov/manual-dump/unknown_lang/ident.s b/testsuite/tests/instr-cov/manual-dump/unknown_lang/ident.s new file mode 100644 index 000000000..cee911602 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/unknown_lang/ident.s @@ -0,0 +1,23 @@ + .file "ident.c" + .text + .globl ident + .type ident, @function +ident: +.LFB0: + .cfi_startproc + pushq %rbp + .cfi_def_cfa_offset 16 + .cfi_offset 6, -16 + movq %rsp, %rbp + .cfi_def_cfa_register 6 + movl %edi, -4(%rbp) + movl -4(%rbp), %eax + nop + popq %rbp + .cfi_def_cfa 7, 8 + ret + .cfi_endproc +.LFE0: + .size ident, .-ident + .ident "GCC: (GNU) 13.2.1 20240204 (for GNAT Pro 25.0w 20240204)" + .section .note.GNU-stack,"",@progbits diff --git a/testsuite/tests/instr-cov/manual-dump/unknown_lang/main_ada.adb b/testsuite/tests/instr-cov/manual-dump/unknown_lang/main_ada.adb new file mode 100644 index 000000000..253f5de2f --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/unknown_lang/main_ada.adb @@ -0,0 +1,11 @@ +with Interfaces.C; use Interfaces.C; + +with Support; + +procedure Main_Ada is + function ASM_Ident (X : int) return int; + pragma Import (C, ASM_Ident, "ident"); +begin + Support.Assert (ASM_Ident (3) = 3); + pragma Annotate (Xcov, Dump_Buffers); +end Main_Ada; diff --git a/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.opt b/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.opt new file mode 100644 index 000000000..beda2dc39 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.opt @@ -0,0 +1,2 @@ +x86_64-linux +ALL DEAD test contains assembly sources, only compiles on x86_64-linux diff --git a/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.py b/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.py new file mode 100644 index 000000000..e1cb06455 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.py @@ -0,0 +1,34 @@ +""" +Check that using --dump-trigger=manual properly ignores files for languages +unknown to gnatcov. This used to crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +prj_name = "prj" + +prj=gprfor( + mains=["main_ada.adb"], + prjid=prj_name, + langs=["Ada", "Asm"], + srcdirs=[".."] +) + +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + mains=["main_ada"], + covlevel="stmt", + extra_coverage_args=["-axcov"], + dump_trigger="manual", + manual_prj_name=prj_name +) + +check_xcov_reports("obj", {"main_ada.adb.xcov": {"+": {9}}}) + +thistest.result() diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 09421d36c..9a82eadc8 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -916,6 +916,17 @@ is Externally_Built_Projects_Processing_Enabled); begin for S of Source_Files.all loop + + -- First, check if S is even a source of a language we + -- recognize. If not, it can't have been instrumented + -- so skip it. + + if To_Language_Or_All + (Project.Project.Info (S).Language) = All_Languages + then + goto Skip_File; + end if; + declare use Unit_Maps; Unit_C : constant Unit_Maps.Cursor := @@ -938,6 +949,7 @@ is end; end if; end; + <> end loop; -- The creation of the root project's buffers list unit From 1dca8dac3d2d77967f95d69327bf9aad39e4f8f6 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 19 Feb 2024 19:12:15 +0100 Subject: [PATCH 0724/1483] Scope metrics: Add undetermined coverage metrics The undetermined coverage metrics were not included in the scope metrics, which resulted in a bogus HTML report. Also do a minor refactoring to share common code between line and scope metrics, and set the scope metrics only if they are greater than 0 (which is the default anyway) to shrink the report size. --- tools/gnatcov/annotations-dynamic_html.adb | 54 +++++++++++++--------- 1 file changed, 31 insertions(+), 23 deletions(-) diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 5e1f9c3f0..8508476e0 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -925,18 +925,38 @@ package body Annotations.Dynamic_Html is ------------- function To_JSON (Stats : Counter_Array) return JSON_Value is + Line_Stats : constant JSON_Value := Create_Object; + + procedure Set_If_Not_Null (Field : String; Stat : Natural); + -- Wrapper around Line_Stats.Set_Field. Set Field to Stat if Stat is not + -- null, do nothing otherwise. + + --------------------- + -- Set_If_Not_Null -- + --------------------- + + procedure Set_If_Not_Null (Field : String; Stat : Natural) is + begin + if Stat > 0 then + Line_Stats.Set_Field (Field, Stat); + end if; + end Set_If_Not_Null; + + -- Start of processing for To_JSON + begin - Line_Stats.Set_Field ("noCode", Stats (No_Code)); - Line_Stats.Set_Field ("covered", Stats (Covered)); - Line_Stats.Set_Field - ("partiallyCovered", Stats (Partially_Covered)); - Line_Stats.Set_Field ("notCovered", Stats (Not_Covered)); - Line_Stats.Set_Field ("notCoverable", Stats (Not_Coverable)); - Line_Stats.Set_Field - ("exemptedNoViolation", Stats (Exempted_No_Violation)); - Line_Stats.Set_Field + Set_If_Not_Null ("noCode", Stats (No_Code)); + Set_If_Not_Null ("covered", Stats (Covered)); + Set_If_Not_Null ("partiallyCovered", Stats (Partially_Covered)); + Set_If_Not_Null ("notCovered", Stats (Not_Covered)); + Set_If_Not_Null ("notCoverable", Stats (Not_Coverable)); + Set_If_Not_Null ("undeterminedCoverage", Stats (Undetermined_Coverage)); + Set_If_Not_Null ("exemptedNoViolation", Stats (Exempted_No_Violation)); + Set_If_Not_Null ("exemptedWithViolation", Stats (Exempted_With_Violation)); + Set_If_Not_Null + ("exemptedWithUndetCov", Stats (Exempted_With_Undetermined_Cov)); return Line_Stats; end To_JSON; @@ -964,22 +984,10 @@ package body Annotations.Dynamic_Html is (Level : Coverage_Level; Obligation_Stats : SCO_Tally) is - Level_Stats : constant JSON_Value := Create_Object; + Level_Stats : constant JSON_Value := + To_JSON (Obligation_Stats.Stats); Stats_Holder : constant JSON_Value := Create_Object; begin - Level_Stats.Set_Field ("covered", Obligation_Stats.Stats (Covered)); - Level_Stats.Set_Field - ("notCovered", Obligation_Stats.Stats (Not_Covered)); - Level_Stats.Set_Field - ("partiallyCovered", Obligation_Stats.Stats (Partially_Covered)); - Level_Stats.Set_Field - ("notCoverable", Obligation_Stats.Stats (Not_Coverable)); - Level_Stats.Set_Field - ("exemptedNoViolation", - Obligation_Stats.Stats (Exempted_No_Violation)); - Level_Stats.Set_Field - ("exemptedWithViolation", - Obligation_Stats.Stats (Exempted_With_Violation)); Stats_Holder.Set_Field ("stats", Level_Stats); Stats_Holder.Set_Field ("level", Image (Level)); Append (Ob_Stats_JSON, Stats_Holder); From 52c0d2cde8e3a7475a2c98d280e4945171dacf6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Thu, 15 Feb 2024 17:34:10 +0100 Subject: [PATCH 0725/1483] Fix crash upon missing exemption justification gnatcov used to expect the justification to always be filled in the pragma signaling the start of an exempted region. This led to null pointer access when it was missing. Now, a warning is emitted during instrumentation and the justification is replaced with "No justification" in the report. Similarly, any deviation from the exact expected pragmas is now be reported as a warning. --- .../231-malformed-exempt-markers/main_1.adb | 14 ++ .../231-malformed-exempt-markers/main_2.adb | 5 + .../231-malformed-exempt-markers/test.py | 59 +++++ tools/gnatcov/ali_files.ads | 5 +- tools/gnatcov/annotations-report.adb | 6 +- tools/gnatcov/instrument-ada_unit.adb | 208 ++++++++++++++---- 6 files changed, 250 insertions(+), 47 deletions(-) create mode 100644 testsuite/tests/instr-cov/231-malformed-exempt-markers/main_1.adb create mode 100644 testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb create mode 100644 testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_1.adb b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_1.adb new file mode 100644 index 000000000..63e208439 --- /dev/null +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_1.adb @@ -0,0 +1,14 @@ +procedure Main_1 +is + T : Boolean := True; +begin + pragma Annotate (Xcov, Exempt_On); + if not T then + null; + end if; + pragma Annotate (Xcov, Exempt_Off, "Superfluous argument"); + pragma Annotate (Xcov, Exempt_On, "Invalid" & " argument"); + pragma Annotate (Xcov, AAA, "Unrecognized annotation"); + pragma Annotate (Xcov); + pragma Annotate (Test); -- No warning from gnatcov +end Main_1; diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb new file mode 100644 index 000000000..c859dc63e --- /dev/null +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb @@ -0,0 +1,5 @@ +procedure Main_2 is +begin + pragma Annotate (1); + pragma Annotate (Xcov, 1); +end Main_2; diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py new file mode 100644 index 000000000..4f7582146 --- /dev/null +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py @@ -0,0 +1,59 @@ +""" +Check that any deviation from the expected annotation pragmas is reported to +the user as a warning. Also check that a warning is emitted if an unrecognized +Xcov annotation was found, and that when an argument of the wrong type is +given it is gprbuild and gnatcov that raises an exception. +""" + +from SCOV.minicheck import build_run_and_coverage, xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir('tmp_') + +# Check gnatcov's behaviour upon encountering annotaton pragmas with correctly +# types arguments. + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(prjid="test", + srcdirs=[".."], + mains=["main_1.adb"], + langs=["Ada"])), + covlevel="stmt", + trace_mode="src", + mains=["main_1"], + extra_coverage_args=["--annotate=report"], + tolerate_instrument_messages=".") + +# Check that gnatcov does not raise an exception when finding incorrect +# annotation pragmas. In these cases, it is the compiler that is expected to +# raise an exception. + +xcov_instrument( + gprsw=GPRswitches( + gprfor(prjid="test", + srcdirs=[".."], + mains=["main_2.adb"], + langs=["Ada"])), + covlevel="stmt", + tolerate_messages='.') + +thistest.fail_if_not_equal( + "gnatcov instrument output", + ( + "*** main_1.adb:5:5: warning: No justification given for exempted" + " region\n" + "*** main_1.adb:9:5: warning: At most 2 pragma arguments allowed\n" + "*** main_1.adb:10:5: warning: Invalid justification argument: string" + " literal expected\n" + "*** main_1.adb:11:5: warning: Invalid Xcov annotation kind: aaa\n" + "*** main_1.adb:12:5: warning: Xcov annotation kind missing\n" + "*** main_2.adb:4:5: warning: Invalid Xcov annotation kind\n" + ), + contents_of("instrument.log"), +) + +thistest.result() diff --git a/tools/gnatcov/ali_files.ads b/tools/gnatcov/ali_files.ads index b32147b0d..4164d8a29 100644 --- a/tools/gnatcov/ali_files.ads +++ b/tools/gnatcov/ali_files.ads @@ -36,14 +36,15 @@ package ALI_Files is pragma Suppress (Tampering_Check); - type ALI_Annotation_Kind is (Exempt_On, Exempt_Off, Dump_Buffers); + type ALI_Annotation_Kind is + (Exempt_On, Exempt_Off, Dump_Buffers, Reset_Buffers); type ALI_Annotation is record CU : CU_Id; -- Compilation unit whose LI file this annotation comes from Kind : ALI_Annotation_Kind; - -- On or Off + -- On or Off, Dump or Reset coverage buffers Message : String_Access; -- When Kind = Exempt_On, justification message for the exemption. diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 777987fa2..cec99855e 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -488,7 +488,11 @@ package body Annotations.Report is end if; Put_Line (Output.all, ", justification:"); - Put_Line (Output.all, E.Message.all); + if E.Message /= null then + Put_Line (Output.all, E.Message.all); + else + Put_Line (Output.all, "No justification"); + end if; New_Line (Output.all); diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 0af267ad7..9cd7b9d38 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3203,6 +3203,24 @@ package body Instrument.Ada_Unit is with Pre => Assertion_Coverage_Enabled; -- Register decision of contrat of name Name of declaration node D + function Prag_Arg_Expr (Args : Base_Assoc_List; I : Positive) return Expr + is + (Args.Child (I).As_Pragma_Argument_Assoc.F_Expr); + -- Return the expression for the Index'th argument of a pragma's + -- arguments. + + procedure Process_Annotation + (N : Ada_Node; + Prag_Args : Base_Assoc_List) + with Pre => + N.Kind = Ada_Pragma_Node + and then Pragma_Name (N.As_Pragma_Node) = Name_Annotate; + -- Handle an Annotate pragma. + -- + -- If this is not an Xcov annotation, do nothing. Otherwise, decode it + -- and add it to our internal tables. If the pragma is not correctly + -- formatted (decoding failure), just emit a warning. + procedure Traverse_One (N : Ada_Node); -- Traverse one declaration or statement @@ -3666,6 +3684,143 @@ package body Instrument.Ada_Unit is 'A'); end Process_Contract; + ------------------------ + -- Process_Annotation -- + ------------------------ + + procedure Process_Annotation + (N : Ada_Node; + Prag_Args : Base_Assoc_List) + is + function Get_Arg + (Prag_Args : Base_Assoc_List; + I : Natural) + return Symbol_Type + is + (if Prag_Arg_Expr (Prag_Args, I).Kind = + Libadalang.Common.Ada_Identifier + then As_Symbol (Prag_Arg_Expr (Prag_Args, I).As_Identifier) + else null); + -- Attempt to get the pragma's Ith argument as an identifier. If + -- it is not an identifier, return null. Else, return the identifier + -- as a symbol. + + Nb_Children : constant Natural := Prag_Args.Children_Count; + Kind : Symbol_Type; + Result : ALI_Annotation; + + -- Start of processing for Process_Annotation + + begin + -- Ignore all but Xcov annotations + + if Get_Arg (Prag_Args, 1) /= As_Symbol (Xcov) then + return; + end if; + + -- Decode the annotation kind + + if Nb_Children = 1 then + Report (N, "Xcov annotation kind missing", Warning); + return; + end if; + + Kind := Get_Arg (Prag_Args, 2); + begin + Result.Kind := ALI_Annotation_Kind'Value (Image (Kind)); + exception + when Constraint_Error => + Report + (N, + "Invalid Xcov annotation kind" + & (if Kind /= null + then ": " & Image (Kind) + else ""), + Warning); + return; + end; + + -- Now that the annotation kind is known, validate the remaining + -- arguments expected for that kind. + + case Result.Kind is + when Exempt_On => + + -- Expected formats: + -- * (Xcov, Exempt_On) + -- * (Xcov, Exempt_On, "Justification") + + case Nb_Children is + when 2 => + Report + (N, "No justification given for exempted region", Warning); + UIC.Annotations.Append + (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); + + when 3 => + if Prag_Arg_Expr (Prag_Args, 3).Kind /= Ada_String_Literal + then + Report + (N, + "Invalid justification argument: string literal" + & " expected", + Warning); + return; + end if; + Result.Message := new String' + (To_String (Prag_Arg_Expr (Prag_Args, 3).Text)); + + UIC.Annotations.Append + (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); + + when others => + Report (N, "At most 3 pragma arguments allowed", Warning); + return; + end case; + + when Exempt_Off => + if Nb_Children > 2 then + Report + (N, "At most 2 pragma arguments allowed", Warning); + return; + end if; + + UIC.Annotations.Append + (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); + + when Dump_Buffers => + + -- Expected formats: + -- * (Xcov, Dump_Buffers) + -- * (Xcov, Dump_Buffers, Prefix) + + case Nb_Children is + when 2 => + null; + + when 3 => + if Prag_Arg_Expr (Prag_Args, 3).Kind not in + Ada_String_Literal | Libadalang.Common.Ada_Identifier + then + Report + (N, + "Invalid prefix argument: string literal expected", + Warning); + end if; + + when others => + Report (N, "At most 3 pragma arguments allowed", Warning); + return; + end case; + + when Reset_Buffers => + if Nb_Children /= 2 then + Report (N, "At most 2 pragma arguments allowed", Warning); + return; + end if; + end case; + end Process_Annotation; + ------------------------------------ -- Traverse_Degenerate_Subprogram -- ------------------------------------ @@ -4800,11 +4955,6 @@ package body Instrument.Ada_Unit is Nam : constant Name_Id := Pragma_Name (Prag_N); Arg : Positive := 1; - function Prag_Arg_Expr (Index : Positive) return Expr is - (Prag_Args.Child (Index).As_Pragma_Argument_Assoc.F_Expr); - -- Return the expression for the Index'th argument of the - -- pragma. - begin case Nam is when Name_Type_Invariant @@ -4861,7 +5011,8 @@ package body Instrument.Ada_Unit is begin while not Is_Null (Prag_Args.Child (Index)) loop Process_Expression - (UIC, Prag_Arg_Expr (Index), 'P'); + (UIC, + Prag_Arg_Expr (Prag_Args, Index), 'P'); Index := Index + 1; end loop; end; @@ -4881,51 +5032,20 @@ package body Instrument.Ada_Unit is -- is a P decision, any nested decision in the -- second argument is an X decision. - Process_Expression (UIC, Prag_Arg_Expr (Arg), 'P'); + Process_Expression + (UIC, Prag_Arg_Expr (Prag_Args, Arg), 'P'); Arg := 2; end if; - Process_Expression (UIC, Prag_Arg_Expr (Arg), 'X'); + Process_Expression + (UIC, Prag_Arg_Expr (Prag_Args, Arg), 'X'); when Name_Annotate => - -- If this is a coverage exemption, record it + -- If this is a coverage exemption, record it. Raise + -- a warning if the annotation could not be processed. - if Prag_Args.Children_Count >= 2 - and then As_Symbol (Prag_Arg_Expr (1).As_Identifier) - = As_Symbol (Xcov) - then - declare - Ann_Kind : constant Symbol_Type := - As_Symbol (Prag_Arg_Expr (2).As_Identifier); - Ann : ALI_Annotation; - begin - Ann.Kind := - ALI_Annotation_Kind'Value (Image (Ann_Kind)); - Ann.CU := No_CU_Id; - - if Ann.Kind = Exempt_On - and then Prag_Args.Children_Count >= 3 - and then Prag_Arg_Expr (3).Kind - = Ada_String_Literal - then - Ann.Message := - new String' - (To_String (Prag_Arg_Expr (3) - .As_String_Literal.Text)); - end if; - - UIC.Annotations.Append - (Annotation_Couple' - ((UIC.SFI, +Sloc (N)), Ann)); - - exception - when Constraint_Error => - -- Invalid annotation kind for Xcov: ignore - - null; - end; - end if; + Process_Annotation (N, Prag_Args); Instrument_Statement (UIC, N, 'P'); -- Even though Compile_Time_* pragmas do contain From a551e74d08a94de5aed3c52247fcbab387a09c7c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 23 Feb 2024 14:42:20 +0000 Subject: [PATCH 0726/1483] ignored-casing: create separate temp. dirs to ease debugging --- testsuite/tests/ignored-casing/test.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/ignored-casing/test.py b/testsuite/tests/ignored-casing/test.py index e3e4b438e..f3ded030f 100644 --- a/testsuite/tests/ignored-casing/test.py +++ b/testsuite/tests/ignored-casing/test.py @@ -9,7 +9,6 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import thistest, gprfor -Wdir("tmp_") ignore_opt = "--ignore-source-files=Pkg.adb" expected_reports = { @@ -18,9 +17,10 @@ if env.build.os.name != "windows": expected_reports["pkg.adb.xcov"] = {"+": {7}} -gprsw = GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])) - # First check --ignore-source-files on "gnatcov coverage" +thistest.log("== gnatcov coverage --ignore-source-files ==") +tmp = Wdir("tmp_cov") +gprsw = GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])) build_run_and_coverage( gprsw=gprsw, covlevel="stmt", @@ -30,10 +30,14 @@ ], ) check_xcov_reports("out-cov", expected_reports) +tmp.to_homedir() # Then check it on "gnatcov instrument". This separate test makes sense as # --ignore-source-files exercises different code paths depending on the gnatcov # command. +thistest.log("== gnatcov instrument --ignore-source-files ==") +tmp = Wdir("tmp_instr") +gprsw = GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])) build_run_and_coverage( gprsw=gprsw, @@ -44,5 +48,6 @@ trace_mode="src" ) check_xcov_reports("out-instr", expected_reports) +tmp.to_homedir() thistest.result() From fa81ba9bc3be8c332d4dc4394b8065dbd058af4d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 23 Feb 2024 20:36:48 +0000 Subject: [PATCH 0727/1483] TA27-015-ignore-source-files-source-coverage: add logging --- .../tests/TA27-015-ignore-source-files-source-coverage/test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py index 40b80df02..b698765bf 100644 --- a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py @@ -37,6 +37,7 @@ def check(report_name, args, expected_files): fact that the results for a file should be the same accross all runs and than coverage results match corresponding ones in expected_res_dict. """ + thistest.log(f"== {report_name} ==") # Create report dir to avoid warning message os.mkdir(report_name) From 2ed14246cc2bd39e70ccd9d613d3b4f045a599b2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 23 Feb 2024 20:39:11 +0000 Subject: [PATCH 0728/1483] Report cov. for all src. files of units of interest with source traces Adjust the heuristic in Files_Table.To_Display so that gnatcov generates annotated sources in coverage reports for all source files in all units of interest. In practice, this works only for source traces: with binary traces, gnatcov cannot know that a source file belongs to a unit of interest unless that file has at least one associated coverage obligation. Update coverage expectations in the testsuite accordingly. --- .../GPR/ByAttr/GlobInList/test.py | 2 +- .../GPR/ByAttr/GlobUnits/test.py | 49 ++++++++++++++----- .../UnitsOfInterest/GPR/ByAttr/ListIn/test.py | 4 +- .../GPR/ByAttr/ListInOut/test.py | 27 ++++++---- .../GPR/ByAttr/ListOut/test.py | 31 +++++++++--- .../UnitsOfInterest/GPR/ByAttr/MixIn/test.py | 2 +- .../GPR/ByAttr/MixInOut/test.py | 2 +- .../UnitsOfInterest/GPR/ByAttr/MixOut/test.py | 38 +++++++++----- .../GPR/ByAttr/UnitsIn/test.py | 4 +- .../GPR/ByAttr/UnitsInOut/test.py | 4 +- .../GPR/ByAttr/UnitsOut/test.py | 40 ++++++++++----- .../GPR/ByCmdLine/ProjectsAndUnits/test.py | 7 +-- .../GPR/ByCmdLine/UnitsOverrides/test.py | 2 +- .../GPR/ByCmdLine/test_support.py | 6 ++- .../GPR/ExtendedGprs/AttrOverride/test.py | 12 +++-- .../GPR/ExtendedGprs/ExtendedHasMain/test.py | 14 ++++-- .../GPR/ExtendedGprs/PartialOverride/test.py | 14 ++++-- .../UnitsOfInterest/GPR/InnerAttr/test.py | 10 ++-- .../GPR/Robustness/SourcesAttr/test.py | 1 + testsuite/SCOV/minicheck.py | 34 ++++++++++++- .../138-ada-preprocessing/prep_data/test.py | 6 ++- testsuite/tests/222-scope-expr-func/test.py | 2 +- .../tests/222-subp-line-computation/test.py | 5 +- .../tests/222-subp-of-interest-cplx/test.py | 9 ++-- testsuite/tests/IA01-015/test.py | 2 +- .../OA27-059-inlined-separate-cons/test.py | 8 ++- .../OA27-059-sep-cons-prj-override/test.py | 1 + testsuite/tests/OA27-059-sep-cons-prj/test.py | 8 ++- .../tests/P907-005-ckpt-covlevel/test.py | 2 +- testsuite/tests/P907-005-incremental/test.py | 4 +- .../tests/P907-005-stubbing-generic/test.py | 2 + testsuite/tests/P907-005-stubbing/test.py | 2 + testsuite/tests/Q327-016-glob-ignore/test.py | 9 +++- .../tests/Q614-037-ckpt-pkg-renames/test.py | 3 ++ .../src-traces-index.xml.expected | 34 +++++++++++++ .../tests/S603-009-externally-built/test.py | 6 ++- .../S619-014-tag-provider-mismatch/test.py | 8 ++- .../T807-011-externally-built-objdir/test.py | 9 ++-- .../tests/T825-010-naming-scheme/test.py | 2 +- .../tests/TA15-063-ignore-fingerprint/test.py | 1 + .../test.py | 15 +++--- .../tests/TB13-020-expr-func-mcdc/test.py | 2 +- testsuite/tests/U204-026-arch-mix/test.py | 4 +- .../tests/U204-029-source-rebase/Ada/test.py | 14 +++++- .../tests/U208-020-child-project/test.py | 3 +- testsuite/tests/U416-006-big-bdd/test.py | 3 +- .../UB18-055-switches-in-gprfile/test.py | 2 +- .../tests/V520-019-duplicate-messages/test.py | 7 +-- testsuite/tests/V824-005-sid-ext-prj/test.py | 6 ++- .../tests/VB07-015-clean-output-dir/test.py | 17 ++++--- testsuite/tests/VC19-001-origin-prj/test.py | 2 +- .../tests/W315-021-generic-preelab/test.py | 3 +- testsuite/tests/ignored-c-header/test.py | 5 +- testsuite/tests/ignored-casing/test.py | 3 +- .../tests/instr-cov/208-no-secsta/test.py | 1 + .../tests/instr-cov/216-no-elab-all/test.py | 1 + .../instr-cov/225-expr-func-access/test.py | 1 + .../226-atc-incomp-type-decl/test.py | 1 + .../tests/instr-cov/227-subunit-stub/test.py | 2 + .../tests/instr-cov/base64_prefix/test.py | 6 +-- .../tests/instr-cov/basic_base64/test.py | 3 +- .../tests/instr-cov/basic_decision/test.py | 3 +- testsuite/tests/instr-cov/basic_stmt/test.py | 3 +- .../tests/instr-cov/buffer_reset/test.py | 4 +- .../tests/instr-cov/c_empty_source/test.py | 4 +- testsuite/tests/instr-cov/endianity/test.py | 3 +- .../tests/instr-cov/ghost_generic/test.py | 1 + testsuite/tests/instr-cov/gpr-complex/test.py | 19 +++++-- testsuite/tests/instr-cov/main-spec/test.py | 18 ++++--- .../main_autodump/disabled_lang/test.py | 1 + .../instr-cov/manual-dump/ada_only/test.py | 4 +- .../instr-cov/manual-dump/ada_subprj/test.py | 5 +- .../tests/instr-cov/multi_unit_source/test.py | 4 +- testsuite/tests/instr-cov/no_main/test.py | 6 ++- testsuite/tests/instr-cov/orphan-unit/test.py | 1 + .../tests/instr-cov/pragma_after_cu/test.py | 2 +- .../tests/instr-cov/pragma_no_body/test.py | 2 + .../tests/instr-cov/pretty_print/test.py | 2 + .../instr-cov/short_circuit_and_or/test.py | 1 + .../modified-root-dir/test.py | 2 +- .../unmodified-root-dir/test.py | 6 +-- testsuite/tests/shared-libs/ada-main/test.py | 4 +- testsuite/tests/subp_of_interest_c/test.py | 1 + tools/gnatcov/files_table.adb | 3 +- 84 files changed, 455 insertions(+), 171 deletions(-) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py index b4f7c1a05..417bbe8a8 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py @@ -9,6 +9,6 @@ TestCase(category=None).run(covcontrol=CovControl( ulist_in="../" + list_to_file(["ops*"]), units_out=['ops.orelse'], - xreports=["ops.ads", "ops.adb", "ops-andthen.adb"])) + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"])) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py index 8c3f8f1a2..c3ba7318e 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py @@ -6,20 +6,43 @@ wd = Wdir() -wd.to_subdir('wd_1') -TestCase(category=None).run(covcontrol=CovControl( - units_in=['ops*'], - xreports=['ops.ads', 'ops.adb', 'ops-andthen.adb', 'ops-orelse.adb'])) +wd.to_subdir("wd_1") +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops*"], + xreports=[ + "ops.ads", + "ops.adb", + "ops-andthen.ads", + "ops-andthen.adb", + "ops-orelse.ads", + "ops-orelse.adb", + ], + ) +) -wd.to_subdir('wd_2') -TestCase(category=None).run(covcontrol=CovControl( - units_out=['test*'], - xreports=['ops.ads', 'ops.adb', 'ops-andthen.adb', 'ops-orelse.adb'])) +wd.to_subdir("wd_2") +TestCase(category=None).run( + covcontrol=CovControl( + units_out=["test*"], + xreports=[ + "ops.ads", + "ops.adb", + "ops-andthen.ads", + "ops-andthen.adb", + "ops-orelse.ads", + "ops-orelse.adb", + ], + ) +) -wd.to_subdir('wd_3') -TestCase(category=None).run(covcontrol=CovControl( - units_in=['ops*'], - units_out=['ops.andthen'], - xreports=['ops.ads', 'ops.adb', 'ops-orelse.adb'])) +wd.to_subdir("wd_3") +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops*"], + units_out=["ops.andthen"], + xreports=["ops.ads", "ops.adb", "ops-orelse.ads", "ops-orelse.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py index 19c8bfce6..f06f21db1 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py @@ -17,12 +17,12 @@ wd.to_subdir("wd_2") TestCase(category=None).run(covcontrol=CovControl( ulist_in="../" + list_to_file(["ops", "ops.andthen"]), - xreports=["ops.ads", "ops.adb", "ops-andthen.adb"])) + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"])) # Check on lone child unit only wd.to_subdir("wd_3") TestCase(category=None).run( covcontrol=CovControl(ulist_in="../" + list_to_file(["ops.andthen"]), - xreports=["ops-andthen.adb"])) + xreports=["ops-andthen.ads", "ops-andthen.adb"])) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListInOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListInOut/test.py index 7b12008d3..c9166729e 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListInOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListInOut/test.py @@ -9,22 +9,31 @@ # Remove a parent unit wd.to_subdir("wd_1") TestCase(category=None).run( - covcontrol=CovControl(ulist_in=list_to_tmp(["ops", "ops.andthen"]), - ulist_out=list_to_tmp(["ops"]), - xreports=["ops-andthen.adb"])) + covcontrol=CovControl( + ulist_in=list_to_tmp(["ops", "ops.andthen"]), + ulist_out=list_to_tmp(["ops"]), + xreports=["ops-andthen.ads", "ops-andthen.adb"], + ) +) # Remove a child unit wd.to_subdir("wd_2") TestCase(category=None).run( - covcontrol=CovControl(ulist_in=list_to_tmp(["ops", "ops.andthen"]), - ulist_out=list_to_tmp(["ops.andthen"]), - xreports=["ops.ads", "ops.adb"])) + covcontrol=CovControl( + ulist_in=list_to_tmp(["ops", "ops.andthen"]), + ulist_out=list_to_tmp(["ops.andthen"]), + xreports=["ops.ads", "ops.adb"], + ) +) # Remove one that's not in wd.to_subdir("wd_3") TestCase(category=None).run( - covcontrol=CovControl(ulist_in=list_to_tmp(["ops", "ops.andthen"]), - ulist_out=list_to_tmp(["ops.orelse"]), - xreports=["ops.ads", "ops.adb", "ops-andthen.adb"])) + covcontrol=CovControl( + ulist_in=list_to_tmp(["ops", "ops.andthen"]), + ulist_out=list_to_tmp(["ops.orelse"]), + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py index 4331b3bc5..844f028c8 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py @@ -10,19 +10,34 @@ # Check on lone node unit only wd.to_subdir("wd_1") TestCase(category=None).run( - covcontrol=CovControl(ulist_out="../" + list_to_file(base_out + ["ops"]), - xreports=["ops-andthen.adb", "ops-orelse.adb"])) + covcontrol=CovControl( + ulist_out="../" + list_to_file(base_out + ["ops"]), + xreports=[ + "ops-andthen.ads", + "ops-andthen.adb", + "ops-orelse.ads", + "ops-orelse.adb", + ], + ) +) # Check on child units only wd.to_subdir("wd_2") -TestCase(category=None).run(covcontrol=CovControl( - ulist_out="../" + list_to_file(base_out + ["ops.orelse", "ops.andthen"]), - xreports=["ops.ads", "ops.adb"])) +TestCase(category=None).run( + covcontrol=CovControl( + ulist_out="../" + + list_to_file(base_out + ["ops.orelse", "ops.andthen"]), + xreports=["ops.ads", "ops.adb"], + ) +) # Check on root + child unit wd.to_subdir("wd_3") -TestCase(category=None).run(covcontrol=CovControl( - ulist_out="../" + list_to_file(base_out + ["ops", "ops.andthen"]), - xreports=["ops-orelse.adb"])) +TestCase(category=None).run( + covcontrol=CovControl( + ulist_out="../" + list_to_file(base_out + ["ops", "ops.andthen"]), + xreports=["ops-orelse.ads", "ops-orelse.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py index 191ebc8e8..c9e94ebd9 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py @@ -10,6 +10,6 @@ TestCase(category=None).run(covcontrol=CovControl( units_in=["ops"], ulist_in=list_to_tmp(["ops.andthen"]), - xreports=["ops.ads", "ops.adb", "ops-andthen.adb"])) + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"])) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py index 23c892224..8813d6201 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py @@ -10,7 +10,7 @@ TestCase(category=None).run( covcontrol=CovControl(units_in=["ops", "ops.andthen"], ulist_out=list_to_tmp(["ops"]), - xreports=["ops-andthen.adb"])) + xreports=["ops-andthen.ads", "ops-andthen.adb"])) TestCase(category=None).run( covcontrol=CovControl(units_in=["ops", "ops.andthen"], diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py index 46b580b9a..dd4a53bf3 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py @@ -11,23 +11,37 @@ # Check on lone node unit only wd.to_subdir("wd_1") -TestCase(category=None).run(covcontrol=CovControl( - units_out=base_out, - ulist_out=list_to_tmp(["ops"]), - xreports=["ops-andthen.adb", "ops-orelse.adb"])) +TestCase(category=None).run( + covcontrol=CovControl( + units_out=base_out, + ulist_out=list_to_tmp(["ops"]), + xreports=[ + "ops-andthen.ads", + "ops-andthen.adb", + "ops-orelse.ads", + "ops-orelse.adb", + ], + ) +) # Check on child units only wd.to_subdir("wd_2") -TestCase(category=None).run(covcontrol=CovControl( - units_out=base_out, - ulist_out=list_to_tmp(["ops.orelse", "ops.andthen"]), - xreports=["ops.ads", "ops.adb"])) +TestCase(category=None).run( + covcontrol=CovControl( + units_out=base_out, + ulist_out=list_to_tmp(["ops.orelse", "ops.andthen"]), + xreports=["ops.ads", "ops.adb"], + ) +) # Check on root + child unit wd.to_subdir("wd_3") -TestCase(category=None).run(covcontrol=CovControl( - units_out=base_out, - ulist_out=list_to_tmp(["ops", "ops.andthen"]), - xreports=["ops-orelse.adb"])) +TestCase(category=None).run( + covcontrol=CovControl( + units_out=base_out, + ulist_out=list_to_tmp(["ops", "ops.andthen"]), + xreports=["ops-orelse.ads", "ops-orelse.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py index e434a639d..b016fedb3 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py @@ -16,12 +16,12 @@ wd.to_subdir('wd_2') TestCase(category=None).run(covcontrol=CovControl( units_in=['ops', 'ops.andthen'], - xreports=['ops.ads', 'ops.adb', 'ops-andthen.adb'])) + xreports=['ops.ads', 'ops.adb', 'ops-andthen.ads', 'ops-andthen.adb'])) # Check on lone child unit only wd.to_subdir('wd_3') TestCase(category=None).run(covcontrol=CovControl( units_in=['ops.andthen'], - xreports=['ops-andthen.adb'])) + xreports=['ops-andthen.ads', 'ops-andthen.adb'])) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py index d366c4ea8..b9d1e2f64 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py @@ -21,7 +21,7 @@ TestCase(category=None).run(covcontrol=CovControl( units_in=["ops", "ops.andthen", "ops.orelse"], units_out=["ops", "ops.andthen"], - xreports=["ops-orelse.adb"])) + xreports=["ops-orelse.ads", "ops-orelse.adb"])) # Out does not overlap In wd.to_subdir("wd_2") @@ -29,6 +29,6 @@ TestCase(category=None).run(covcontrol=CovControl( units_in=["ops", "ops.orelse"], units_out=["ops.andthen"], - xreports=["ops.ads", "ops.adb", "ops-orelse.adb"])) + xreports=["ops.ads", "ops.adb", "ops-orelse.ads", "ops-orelse.adb"])) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py index 5ba1f9d9f..0be723bad 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py @@ -4,25 +4,39 @@ from SUITE.cutils import Wdir -base_out = ['test_or_ft', 'test_and_tt', 'test_and_tf'] +base_out = ["test_or_ft", "test_and_tt", "test_and_tf"] wd = Wdir() # Check on lone node unit only -wd.to_subdir('wd_1') -TestCase(category=None).run(covcontrol=CovControl( - units_out=base_out + ['ops'], - xreports=['ops-andthen.adb', 'ops-orelse.adb'])) +wd.to_subdir("wd_1") +TestCase(category=None).run( + covcontrol=CovControl( + units_out=base_out + ["ops"], + xreports=[ + "ops-andthen.ads", + "ops-andthen.adb", + "ops-orelse.ads", + "ops-orelse.adb", + ], + ) +) # Check on child units only -wd.to_subdir('wd_2') -TestCase(category=None).run(covcontrol=CovControl( - units_out=base_out + ['ops.orelse', 'ops.andthen'], - xreports=['ops.ads', 'ops.adb'])) +wd.to_subdir("wd_2") +TestCase(category=None).run( + covcontrol=CovControl( + units_out=base_out + ["ops.orelse", "ops.andthen"], + xreports=["ops.ads", "ops.adb"], + ) +) # Check on root + child unit -wd.to_subdir('wd_3') -TestCase(category=None).run(covcontrol=CovControl( - units_out=base_out + ['ops', 'ops.andthen'], - xreports=['ops-orelse.adb'])) +wd.to_subdir("wd_3") +TestCase(category=None).run( + covcontrol=CovControl( + units_out=base_out + ["ops", "ops.andthen"], + xreports=["ops-orelse.ads", "ops-orelse.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py index d072808be..04ca0430f 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py @@ -21,7 +21,8 @@ units=['intops'], recurse=True, xreports=['intops.ads', 'intops.adb', - 'intops-add.adb', 'intops-sub.adb']) + 'intops-add.ads', 'intops-add.adb', + 'intops-sub.ads', 'intops-sub.adb']) # Lone unit, with child units, in closure @@ -46,13 +47,13 @@ root_project='../boolops/boolops', units=['boolops.andthen'], recurse=False, - xreports=['boolops.ads', 'boolops-andthen.adb']) + xreports=['boolops.ads', 'boolops-andthen.ads', 'boolops-andthen.adb']) check( root_project='gen.gpr', projects=['boolops'], units=['boolops.andthen'], recurse=False, - xreports=['boolops.ads', 'boolops-andthen.adb']) + xreports=['boolops.ads', 'boolops-andthen.ads', 'boolops-andthen.adb']) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/UnitsOverrides/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/UnitsOverrides/test.py index 3d120959a..22ac96f4b 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/UnitsOverrides/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/UnitsOverrides/test.py @@ -22,7 +22,7 @@ root_project='gen.gpr', recurse=True, units=['boolops.andthen'], - xreports=['boolops.ads', 'boolops-andthen.adb']) + xreports=['boolops.ads', 'boolops-andthen.ads', 'boolops-andthen.adb']) # --units=counters in closure, counters reports only # despite the attribute in boolops.gpr diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py index b1940779b..4d2be6ea9 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py @@ -18,9 +18,11 @@ # each project, designated by project short name. _xreports = { 'boolops': ['boolops.ads', 'boolops.adb', - 'boolops-andthen.adb', 'boolops-orelse.adb'], + 'boolops-andthen.ads', 'boolops-andthen.adb', + 'boolops-orelse.ads', 'boolops-orelse.adb'], 'intops': ['intops.ads', 'intops.adb', - 'intops-add.adb', 'intops-sub.adb'], + 'intops-add.ads', 'intops-add.adb', + 'intops-sub.ads', 'intops-sub.adb'], 'counters': ['counters.ads', 'counters.adb'], } all_projects = list(_xreports) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py index 902acf2b5..6f2a5ef42 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py @@ -19,8 +19,14 @@ # App_Base is extended by App; App overrides Coverage'Units so that only Values # (not Values.Aux) is selected. -check_xcov_reports('obj', { - 'values.ads.xcov': {}, - 'values.adb.xcov': {'+': {5, 6}, '-': {8}}}) +check_xcov_reports( + 'obj', + { + 'values.ads.xcov': {}, + 'values.adb.xcov': {'+': {5, 6}, '-': {8}}, + }, + # See eng/das/cov/gnatcoverage#245 + discard_empty=False, +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py index 41280fd88..abd0e2fce 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py @@ -36,9 +36,15 @@ # In blob.ads, we expect either '+' or '.' on everything, depending # on the toolchain. Let check_xcov_reports refine that. -check_xcov_reports('ext-obj', { - 'blob.ads.xcov': {}, - 'main1.adb.xcov': {'+': {5}}, - 'main2.adb.xcov': {'+': {5, 6}}}) +check_xcov_reports( + 'ext-obj', + { + 'blob.ads.xcov': {}, + 'main1.adb.xcov': {'+': {5}}, + 'main2.adb.xcov': {'+': {5, 6}}, + }, + # See eng/das/cov/gnatcoverage#245 + discard_empty=False, +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py index 3781daffa..6510d5f62 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py @@ -37,9 +37,15 @@ gpr_obj_dir='obj-ext', gpr_exe_dir='obj-ext') -check_xcov_reports('obj-ext', { - 'main.adb.xcov': {'+': {5}}, - 'helper.ads.xcov': {}, - 'helper.adb.xcov': {'+': {4}}}) +check_xcov_reports( + 'obj-ext', + { + 'main.adb.xcov': {'+': {5}}, + 'helper.ads.xcov': {}, + 'helper.adb.xcov': {'+': {4}}, + }, + # See eng/das/cov/gnatcoverage#245 + discard_empty=False, +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py index fa3040cb6..c48ec991a 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py @@ -24,7 +24,9 @@ def check(subdir, opspkg, xreports): check( opspkg="", - xreports=["ops.adb", "ops.ads", "ops-andthen.adb", "ops-orelse.adb"], + xreports=["ops.adb", "ops.ads", + "ops-andthen.ads", "ops-andthen.adb", + "ops-orelse.ads", "ops-orelse.adb"], subdir="wd_1", ) @@ -32,7 +34,7 @@ def check(subdir, opspkg, xreports): check( opspkg=gprcov_for(units_in=["ops.andthen"]), - xreports=["ops-andthen.adb"], + xreports=["ops-andthen.ads", "ops-andthen.adb"], subdir="wd_2", ) @@ -40,7 +42,7 @@ def check(subdir, opspkg, xreports): check( opspkg=gprcov_for(units_out=["ops.andthen"]), - xreports=["ops.ads", "ops.adb", "ops-orelse.adb"], + xreports=["ops.ads", "ops.adb", "ops-orelse.ads", "ops-orelse.adb"], subdir="wd_3", ) @@ -50,7 +52,7 @@ def check(subdir, opspkg, xreports): opspkg=gprcov_for( units_in=["ops", "ops.orelse", "ops.andthen"], units_out=["ops.orelse"]), - xreports=["ops.ads", "ops.adb", "ops-andthen.adb"], + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], subdir="wd_3", ) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py index 56591ac87..bdf22d6f1 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py @@ -55,6 +55,7 @@ def try_one(subdir, extra_covargs, xreports, xwarnings): extra_covargs=[], xreports={ 'flip.adb.xcov': {'+': {3}}, + 'flip.ads.xcov': {}, 'test_t.adb.xcov': {'+': {4, 6}}}, xwarnings=[]) diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index e56063466..82e92a146 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -412,7 +412,7 @@ def fmt_cov(cov_data): return ' '.join(result) -def check_xcov_content(filename, expected_cov): +def check_xcov_content(filename, expected_cov, trace_mode=None): """ Dumbed-down version of coverage matching. Check that the XCOV file "filename" matches some expected coverage data. @@ -483,7 +483,7 @@ def remove_empty_sets(data): ) -def check_xcov_reports(reports_dir, expected_cov): +def check_xcov_reports(reports_dir, expected_cov, discard_empty=None): """ Check the set of XCOV report files and their content. @@ -493,6 +493,26 @@ def check_xcov_reports(reports_dir, expected_cov): "expected_cov" is a mapping: filename -> coverage data. See "check_xcov_content" for the coverage data format. + + "discard_empty" is used to adjust test expectations for binary traces: + + * When True, source file for which there are no coverage expectation are + discarded (binary traces have a technical limitation: gnatcov is unable + to generate coverage reports for SCO-less source files: see + eng/das/cov/gnatcoverage#245). + + * When False, reports of source files with no coverage expectations are + checked. + + * If left to None, "discard_empty" is treated as True when the testsuite + runs in binary traces mode, and treated as False when the testsuite runs + in source traces mode. + + None is the most useful default. Tests that force the use of source traces + regardless of the testsuite trace mode should pass discard_empty=True. + Tests that have source files showing up as completely no code with binary + traces should pass discard_empty=False and adjust "expected_cov" depending + on the testsuite trace mode. """ def fmt_sorted_indented_list(items): @@ -504,6 +524,16 @@ def fmt_sorted_indented_list(items): def canonicalize_file(filename): return filename.replace('\\', '/') + if ( + discard_empty + or (discard_empty is None and thistest.options.trace_mode == "bin") + ): + expected_cov = { + filename: expectations + for filename, expectations in expected_cov.items() + if any(lines for lines in expectations.values()) + } + xcov_files = { canonicalize_file(filename) for filename in os.listdir(reports_dir) diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/test.py b/testsuite/tests/138-ada-preprocessing/prep_data/test.py index 2a7eb5082..fd028ed8d 100644 --- a/testsuite/tests/138-ada-preprocessing/prep_data/test.py +++ b/testsuite/tests/138-ada-preprocessing/prep_data/test.py @@ -107,7 +107,11 @@ class ReportTestcase(BaseTestcase): extra_coverage_args=["-axcov", "--output-dir=xcov"], trace_mode="src", ) - check_xcov_reports("xcov", {"pkg.adb.xcov": t.expected_cov}) + check_xcov_reports( + "xcov", + {"pkg.adb.xcov": t.expected_cov, "pkg.ads.xcov": {}}, + discard_empty=False, + ) tmp.to_homedir() thistest.log("") diff --git a/testsuite/tests/222-scope-expr-func/test.py b/testsuite/tests/222-scope-expr-func/test.py index 1d07718b6..a0f78ccb7 100644 --- a/testsuite/tests/222-scope-expr-func/test.py +++ b/testsuite/tests/222-scope-expr-func/test.py @@ -24,6 +24,6 @@ extra_coverage_args=["--subprograms=pkg.ads:2", "-axcov"] ) -check_xcov_reports("obj", {"pkg.adb.xcov": {"+": {5}}}) +check_xcov_reports("obj", {"pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {5}}}) thistest.result() diff --git a/testsuite/tests/222-subp-line-computation/test.py b/testsuite/tests/222-subp-line-computation/test.py index db209e19e..d0fdb2f33 100644 --- a/testsuite/tests/222-subp-line-computation/test.py +++ b/testsuite/tests/222-subp-line-computation/test.py @@ -16,12 +16,11 @@ build_run_and_coverage( gprsw=GPRswitches( - root_project=gprfor(mains=["main.adb"],srcdirs=[".."]), - units=["pkg"], + root_project=gprfor(mains=["main.adb"], srcdirs=[".."]), units=["pkg"] ), covlevel="stmt+decision", mains=["main"], - extra_coverage_args=["--subprograms=pkg.ads:5", "-axcov+"] + extra_coverage_args=["--subprograms=pkg.ads:5", "-axcov+"], ) check_xcov_reports("obj", {"pkg.ads.xcov": {"+": {5}}}) diff --git a/testsuite/tests/222-subp-of-interest-cplx/test.py b/testsuite/tests/222-subp-of-interest-cplx/test.py index 9734ace95..80415e62b 100644 --- a/testsuite/tests/222-subp-of-interest-cplx/test.py +++ b/testsuite/tests/222-subp-of-interest-cplx/test.py @@ -44,14 +44,15 @@ build_run_and_coverage( gprsw=GPRswitches( - root_project=gprfor(mains=["main.adb"],srcdirs=[".."]), - units=["Pkg"] + root_project=gprfor(mains=["main.adb"], srcdirs=[".."]), units=["Pkg"] ), covlevel="stmt+decision", mains=["main"], - extra_coverage_args=["--subprograms=pkg.ads:3", "-axcov"] + extra_coverage_args=["--subprograms=pkg.ads:3", "-axcov"], ) -check_xcov_reports("obj", {"pkg.adb.xcov": {"!": {12, 13}, "+": {14, 15}}}) +check_xcov_reports( + "obj", {"pkg.ads.xcov": {}, "pkg.adb.xcov": {"!": {12, 13}, "+": {14, 15}}} +) thistest.result() diff --git a/testsuite/tests/IA01-015/test.py b/testsuite/tests/IA01-015/test.py index bcd51df95..79ad3cd0e 100644 --- a/testsuite/tests/IA01-015/test.py +++ b/testsuite/tests/IA01-015/test.py @@ -35,7 +35,7 @@ def tryseq(label, scoargs): thistest.log('== {} =='.format(label)) xcov(coverage_base_args + scoargs) - check_xcov_reports('.', expected_reports) + check_xcov_reports('.', expected_reports, discard_empty=False) if thistest.options.trace_mode == 'src': diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test.py b/testsuite/tests/OA27-059-inlined-separate-cons/test.py index 5063dc4e4..34a551edb 100644 --- a/testsuite/tests/OA27-059-inlined-separate-cons/test.py +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test.py @@ -100,5 +100,11 @@ def clean_output_directory(): 'cons.log') # Finally, check we have the expected reports -check_xcov_reports('output', {'pkg.adb.xcov': {'+': {5, 6, 8}}}) +check_xcov_reports( + 'output', + { + 'pkg.ads.xcov': {}, + 'pkg.adb.xcov': {'+': {5, 6, 8}} + }, +) thistest.result() diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test.py b/testsuite/tests/OA27-059-sep-cons-prj-override/test.py index 953b71ac3..55c37d777 100644 --- a/testsuite/tests/OA27-059-sep-cons-prj-override/test.py +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test.py @@ -110,6 +110,7 @@ def clean_output_directory(): check_xcov_reports( 'output', { + 'pkg_under_test.ads.xcov': {}, 'pkg_under_test.adb.xcov': {'+': {7, 8, 10}}, 'pkg_under_test-some_procedure.adb.xcov': {'-': {5}}, }, diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test.py b/testsuite/tests/OA27-059-sep-cons-prj/test.py index e55bba12e..f21777009 100644 --- a/testsuite/tests/OA27-059-sep-cons-prj/test.py +++ b/testsuite/tests/OA27-059-sep-cons-prj/test.py @@ -88,6 +88,12 @@ def clean_output_directory(): # with the expected coverage data. clean_output_directory() p = checked_xcov(xcov_args + ['--output-dir=output'] + trace_files, 'cons.log') -check_xcov_reports('output', {'pkg_under_test.adb.xcov': {'+': {7, 8, 10}}}) +check_xcov_reports( + 'output', + { + 'pkg_under_test.ads.xcov': {}, + 'pkg_under_test.adb.xcov': {'+': {7, 8, 10}}, + }, +) thistest.result() diff --git a/testsuite/tests/P907-005-ckpt-covlevel/test.py b/testsuite/tests/P907-005-ckpt-covlevel/test.py index 9a6679901..b174d9bbf 100644 --- a/testsuite/tests/P907-005-ckpt-covlevel/test.py +++ b/testsuite/tests/P907-005-ckpt-covlevel/test.py @@ -75,5 +75,5 @@ def clean_output_directory(): # Finally, check we have the expected reports for the --level=stmt # consolidation. -check_xcov_reports('output', expected) +check_xcov_reports('output', expected, discard_empty=False) thistest.result() diff --git a/testsuite/tests/P907-005-incremental/test.py b/testsuite/tests/P907-005-incremental/test.py index 48989f685..ad80dc2bb 100644 --- a/testsuite/tests/P907-005-incremental/test.py +++ b/testsuite/tests/P907-005-incremental/test.py @@ -45,6 +45,8 @@ check_xcov_reports( '.', {'math.adb.xcov': {'+': {7, 12, 13, 14, 18, 19}, '!': {17}}, - 'math.ads.xcov': {}}) + 'math.ads.xcov': {}}, + discard_empty=False, +) thistest.result() diff --git a/testsuite/tests/P907-005-stubbing-generic/test.py b/testsuite/tests/P907-005-stubbing-generic/test.py index 4abc78cb1..6653753ce 100644 --- a/testsuite/tests/P907-005-stubbing-generic/test.py +++ b/testsuite/tests/P907-005-stubbing-generic/test.py @@ -58,11 +58,13 @@ def __init__(self, test_dir, exename): check_xcov_reports( '.', { + 'pressure_control.ads.xcov': {}, 'pressure_control.adb.xcov': { '+': {10, 18, 19}, '!': {11}, '-': {12}, }, + 'temperature_control.ads.xcov': {}, 'temperature_control.adb.xcov': { '+': {10, 18, 19}, '!': {11}, diff --git a/testsuite/tests/P907-005-stubbing/test.py b/testsuite/tests/P907-005-stubbing/test.py index 4e5040125..953e3b79e 100644 --- a/testsuite/tests/P907-005-stubbing/test.py +++ b/testsuite/tests/P907-005-stubbing/test.py @@ -57,11 +57,13 @@ def __init__(self, test_dir, exename): check_xcov_reports( '.', { + 'pressure_control.ads.xcov': {}, 'pressure_control.adb.xcov': { '+': {10, 18, 19}, '!': {11}, '-': {12}, }, + 'temperature_control.ads.xcov': {}, 'temperature_control.adb.xcov': { '+': {10, 18, 19}, '!': {11}, diff --git a/testsuite/tests/Q327-016-glob-ignore/test.py b/testsuite/tests/Q327-016-glob-ignore/test.py index 3e915f5cf..58555d4c7 100644 --- a/testsuite/tests/Q327-016-glob-ignore/test.py +++ b/testsuite/tests/Q327-016-glob-ignore/test.py @@ -27,6 +27,13 @@ # Check we have the expected reports check_xcov_reports( - '.', {'main.adb.xcov': {'+': {6, 7}}, 'pkg_a.adb.xcov': {'+': {6}}} + '.', + { + 'main.adb.xcov': {'+': {6, 7}}, + 'pkg_a.adb.xcov': {'+': {6}}, + 'pkg_a.ads.xcov': {}, + 'pkg_b.ads.xcov': {}, + 'pkg_c.ads.xcov': {}, + }, ) thistest.result() diff --git a/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py b/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py index 267d60945..37abeb5d1 100644 --- a/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py +++ b/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py @@ -22,6 +22,9 @@ xcov(['coverage', '-cstmt', '-axcov', '-Cmain.ckpt']) expected_reports = ['foo.adb.xcov', 'main.adb.xcov'] +if thistest.options.trace_mode == "src": + expected_reports += ['bar.ads.xcov', 'foo.ads.xcov'] +expected_reports.sort() got_reports = sorted(glob.glob('*.xcov')) thistest.fail_if( got_reports != expected_reports, diff --git a/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected b/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected index 34fa134e3..a05a70554 100644 --- a/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected +++ b/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected @@ -135,12 +135,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/tests/S603-009-externally-built/test.py b/testsuite/tests/S603-009-externally-built/test.py index dd7b772d3..1d3118c22 100644 --- a/testsuite/tests/S603-009-externally-built/test.py +++ b/testsuite/tests/S603-009-externally-built/test.py @@ -156,7 +156,10 @@ def check_one(dump_trigger, lib_prj): project="mylib.gpr", externally_built=True, trace_file=trace_file, - expected_cov={"mylib.adb.xcov": {"+": {5, 6}, "-": {8}}}, + expected_cov={ + "mylib.adb.xcov": {"+": {5, 6}, "-": {8}}, + "mylib.ads.xcov": {}, + }, ) # Make sure coverage computation gives the expected result with and @@ -174,6 +177,7 @@ def check_one(dump_trigger, lib_prj): expected_cov={ "main.adb.xcov": {"+": {4, 6}}, "mylib.adb.xcov": {"+": {5, 6}, "-": {8}}, + "mylib.ads.xcov": {}, }, ) diff --git a/testsuite/tests/S619-014-tag-provider-mismatch/test.py b/testsuite/tests/S619-014-tag-provider-mismatch/test.py index c3d6e4ebd..2c743176f 100644 --- a/testsuite/tests/S619-014-tag-provider-mismatch/test.py +++ b/testsuite/tests/S619-014-tag-provider-mismatch/test.py @@ -37,6 +37,12 @@ 'but got:\n' '{}'.format(indent(expected), indent(actual))) -check_xcov_reports('.', {'main.adb.xcov': {}, 'generic_hello.adb.xcov': {}}) +expected_cov = { + 'main.adb.xcov': {}, + 'generic_hello.adb.xcov': {}, +} +if thistest.options.trace_mode == "src": + expected_cov["generic_hello.ads.xcov"] = {} +check_xcov_reports('.', expected_cov, discard_empty=False) thistest.result() diff --git a/testsuite/tests/T807-011-externally-built-objdir/test.py b/testsuite/tests/T807-011-externally-built-objdir/test.py index 419ce39b0..d375bd290 100644 --- a/testsuite/tests/T807-011-externally-built-objdir/test.py +++ b/testsuite/tests/T807-011-externally-built-objdir/test.py @@ -48,10 +48,11 @@ trace_mode='src' ) -check_xcov_reports('report', { - 'ops.ads.xcov': {}, - 'ops.adb.xcov': {'+': {4, 5}, '-': {6}}, -}) +check_xcov_reports( + 'report', + {'ops.ads.xcov': {}, 'ops.adb.xcov': {'+': {4, 5}, '-': {6}}}, + discard_empty=False, +) # Re-run the instrumenter on the main, to check that it does not re-create a # SID file for the opslib externall built project. diff --git a/testsuite/tests/T825-010-naming-scheme/test.py b/testsuite/tests/T825-010-naming-scheme/test.py index 1d2cafdca..1ac650370 100644 --- a/testsuite/tests/T825-010-naming-scheme/test.py +++ b/testsuite/tests/T825-010-naming-scheme/test.py @@ -34,6 +34,6 @@ 'p.2.ada.xcov': {'+': {4}}, 'p__q.1.ada.xcov': {'+': {3}}, 'p__q.2.ada.xcov': {'+': {6}}, -}) +}, discard_empty=False) thistest.result() diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/test.py b/testsuite/tests/TA15-063-ignore-fingerprint/test.py index 168c1f12a..4c9dedfcd 100644 --- a/testsuite/tests/TA15-063-ignore-fingerprint/test.py +++ b/testsuite/tests/TA15-063-ignore-fingerprint/test.py @@ -64,6 +64,7 @@ def check_empty(filename): check_empty("log-cons.txt") check_xcov_reports("report", { "main.adb.xcov": {"+": {5}}, + "pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {2}}, "pkg-test.adb.xcov": {"-": {8, 9}}, }) diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py index b698765bf..31f65eb39 100644 --- a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py @@ -26,7 +26,8 @@ trace_file = xcov_args[-1] expected_res_dict = {'pkg.adb.xcov': {'-': {7}}, - 'pkg-say_goodbye.adb.xcov': {'-': {9}}} + 'pkg-say_goodbye.adb.xcov': {'-': {9}}, + 'pkg.ads.xcov': {}} def check(report_name, args, expected_files): @@ -48,22 +49,22 @@ def check(report_name, args, expected_files): for filename in expected_files } expected["main.adb.xcov"] = {"+": {5, 6}} - check_xcov_reports(report_name, expected) + check_xcov_reports(report_name, expected, discard_empty=False) # Check that not passing the option has no effect check('report0', xcov_args + ['--save-checkpoint=full.ckpt'], - ['pkg.adb.xcov', 'pkg-say_goodbye.adb.xcov']) + ['pkg.adb.xcov', 'pkg-say_goodbye.adb.xcov', 'pkg.ads.xcov']) # Check that --ignore-source-files has the expected effect on the 'coverage' # command. check('report1', xcov_args + ['--ignore-source-files=pkg-say_goodbye.adb'], - ['pkg.adb.xcov']) + ['pkg.adb.xcov', 'pkg.ads.xcov']) # Check that --ignore-source-files does not filter checkpoint loading check('report2', xcov_args_no_trace + ['--ignore-source-files=pkg-say_goodbye.adb', '-Cfull.ckpt'], - ['pkg.adb.xcov', 'pkg-say_goodbye.adb.xcov']) + ['pkg.adb.xcov', 'pkg-say_goodbye.adb.xcov', 'pkg.ads.xcov']) # Check that in presence of bot a checkpoint and a SID file, # --ignore-source-files filters the SID file but not the checkpoint. @@ -71,7 +72,7 @@ def check(report_name, args, expected_files): '--save-checkpoint=pkg.ckpt'], 'report3_out.txt') check('report3', xcov_args + ['--ignore-source-files=pkg*.adb', '-Cpkg.ckpt'], - ['pkg.adb.xcov']) + ['pkg.adb.xcov', 'pkg.ads.xcov']) # Check that if a file is ignored when creating the checkpoint, then it is not # present when loading that checkpoint. @@ -79,6 +80,6 @@ def check(report_name, args, expected_files): '--ignore-source-files=pkg.adb'], 'report4_out.txt') check('report4', xcov_args_no_trace + ['-Cpkg_goodbye.ckpt'], - ['pkg-say_goodbye.adb.xcov']) + ['pkg-say_goodbye.adb.xcov', 'pkg.ads.xcov']) thistest.result() diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/test.py b/testsuite/tests/TB13-020-expr-func-mcdc/test.py index 313a6c763..dc1999331 100644 --- a/testsuite/tests/TB13-020-expr-func-mcdc/test.py +++ b/testsuite/tests/TB13-020-expr-func-mcdc/test.py @@ -34,6 +34,6 @@ "-": {16, 20}}, "pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {9}}, -}) +}, discard_empty=False) thistest.result() diff --git a/testsuite/tests/U204-026-arch-mix/test.py b/testsuite/tests/U204-026-arch-mix/test.py index e87855bd3..0f8f37949 100644 --- a/testsuite/tests/U204-026-arch-mix/test.py +++ b/testsuite/tests/U204-026-arch-mix/test.py @@ -49,8 +49,10 @@ def check_reports(xcov_dir): { "main_1.adb.xcov": {"+": {5}}, "main_2.adb.xcov": {"+": {5}}, - "pkg.adb.xcov": {"+": {12, 14}, "!": {11}} + "pkg.adb.xcov": {"+": {12, 14}, "!": {11}}, + "pkg.ads.xcov": {}, }, + discard_empty=False, ) diff --git a/testsuite/tests/U204-029-source-rebase/Ada/test.py b/testsuite/tests/U204-029-source-rebase/Ada/test.py index 63b28ca19..46f319fc9 100644 --- a/testsuite/tests/U204-029-source-rebase/Ada/test.py +++ b/testsuite/tests/U204-029-source-rebase/Ada/test.py @@ -26,7 +26,10 @@ mains_list=["disjoint_main_1.adb"], units_lists=[["Pkg1"]], origin_src_dir="src", - expected_xcov_results={"pkg1.adb.xcov": {'+': {8, 9, 11}}}, + expected_xcov_results={ + "pkg1.ads.xcov": {}, + "pkg1.adb.xcov": {'+': {8, 9, 11}} + }, rebase_dir="/some/random/dir", ) @@ -37,7 +40,10 @@ mains_list=["disjoint_main_1.adb"], units_lists=[["Pkg1"]], origin_src_dir="src", - expected_xcov_results={"pkg1.adb.xcov": {'+': {8, 9, 11}}}, + expected_xcov_results={ + "pkg1.ads.xcov": {}, + "pkg1.adb.xcov": {'+': {8, 9, 11}} + }, suppress_src_dir=True, ) @@ -49,7 +55,9 @@ units_lists=[["Pkg1"], ["Pkg2"]], origin_src_dir="src", expected_xcov_results={ + "pkg1.ads.xcov": {}, "pkg1.adb.xcov": {'+': {8, 9, 11}}, + "pkg2.ads.xcov": {}, "pkg2.adb.xcov": {'+': {8, 9, 11}} }, suppress_src_dir=True, @@ -72,7 +80,9 @@ units_lists=[["Pkg1", "Pkg2"]] * 2, origin_src_dir="src", expected_xcov_results={ + "pkg1.ads.xcov": {}, "pkg1.adb.xcov": {'+': {8, 9, 11}}, + "pkg2.ads.xcov": {}, "pkg2.adb.xcov": {'+': {8, 9, 11}} }, ) diff --git a/testsuite/tests/U208-020-child-project/test.py b/testsuite/tests/U208-020-child-project/test.py index 93eba2b2b..ad17f2a50 100644 --- a/testsuite/tests/U208-020-child-project/test.py +++ b/testsuite/tests/U208-020-child-project/test.py @@ -25,6 +25,7 @@ trace_mode='src') check_xcov_reports('xcov', {'main.adb.xcov': {'+': {5, 6}}, - 'pkg.adb.xcov': {'+': {5}}}) + 'pkg.adb.xcov': {'+': {5}}, + 'pkg.ads.xcov': {}}) thistest.result() diff --git a/testsuite/tests/U416-006-big-bdd/test.py b/testsuite/tests/U416-006-big-bdd/test.py index 02fd03a47..c5340b742 100644 --- a/testsuite/tests/U416-006-big-bdd/test.py +++ b/testsuite/tests/U416-006-big-bdd/test.py @@ -52,6 +52,7 @@ def do_one_level(level): expected_cov = { "test_eval.adb.xcov": {"+": {11, 13, 19, 20}}, "testconditions.adb.xcov": {"+": {22, 23, 24, 25, 26, 27}}, + "testconditions.ads.xcov": {}, "compute.c.xcov": {"+": {5, 6}}, } @@ -67,7 +68,7 @@ def do_one_level(level): expected_cov["testconditions.adb.xcov"]['+'].add(17) expected_cov["compute.c.xcov"]['+'].add(4) - check_xcov_reports("obj", expected_cov) + check_xcov_reports("obj", expected_cov, discard_empty=False) if level == "stmt+mcdc": # The order in which sources are instrumented is not specified, so sort diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/test.py b/testsuite/tests/UB18-055-switches-in-gprfile/test.py index f07edcadb..8a6191ccf 100644 --- a/testsuite/tests/UB18-055-switches-in-gprfile/test.py +++ b/testsuite/tests/UB18-055-switches-in-gprfile/test.py @@ -38,6 +38,6 @@ # Check that we have coverage result only for the project of interest, as # specified in the gpr file. -check_xcov_reports(".", {"b.adb.xcov": {"+": {6}}}) +check_xcov_reports(".", {"b.ads.xcov": {}, "b.adb.xcov": {"+": {6}}}) thistest.result() diff --git a/testsuite/tests/V520-019-duplicate-messages/test.py b/testsuite/tests/V520-019-duplicate-messages/test.py index 5e27efcb2..cafbe71d4 100644 --- a/testsuite/tests/V520-019-duplicate-messages/test.py +++ b/testsuite/tests/V520-019-duplicate-messages/test.py @@ -24,9 +24,10 @@ ) # Check the expected results -check_xcov_reports("obj", - {"main.adb.xcov": {}, - "pkg.adb.xcov" : {'-': {10}}}) +expected_cov = {"main.adb.xcov": {}, "pkg.adb.xcov" : {'-': {10}}} +if thistest.options.trace_mode == "src": + expected_cov["pkg.ads.xcov"] = {} +check_xcov_reports("obj", expected_cov, discard_empty=False) # Check that we do not have any duplicate messages. In this case, we only # expect a single statment violation. diff --git a/testsuite/tests/V824-005-sid-ext-prj/test.py b/testsuite/tests/V824-005-sid-ext-prj/test.py index 31e1ad17f..893fc8a32 100644 --- a/testsuite/tests/V824-005-sid-ext-prj/test.py +++ b/testsuite/tests/V824-005-sid-ext-prj/test.py @@ -45,6 +45,10 @@ # Compute the coverage report and check its contents (sanity check) xcov(xcov_args, out="coverage.log") -check_xcov_reports("output", {"pkg.adb.xcov": {'+': {11}}}) +check_xcov_reports( + "output", + {"pkg.adb.xcov": {'+': {11}}, "pkg.ads.xcov": {}}, + discard_empty=False, +) thistest.result() diff --git a/testsuite/tests/VB07-015-clean-output-dir/test.py b/testsuite/tests/VB07-015-clean-output-dir/test.py index e2e8be779..77c7770d4 100644 --- a/testsuite/tests/VB07-015-clean-output-dir/test.py +++ b/testsuite/tests/VB07-015-clean-output-dir/test.py @@ -15,9 +15,10 @@ tmp = Wdir("tmp_") -expected_cov_per_unit = { - "main": {"+": {4, 7}}, - "pkg": {"+": {5}}, +expected_cov = { + "main.adb": {"+": {4, 7}}, + "pkg.adb": {"+": {5}}, + "pkg.ads": {}, } possible_output_dirs = ["obj", os.path.join("obj", "xcov")] @@ -34,7 +35,7 @@ def check_one(units, output_dir, xcov_args): thistest.log(f"inspecting {dir}") check_xcov_reports( dir, - {f"{unit}.adb.xcov": expected_cov_per_unit[unit] for unit in units} + {f"{unit}.xcov": expected_cov[unit] for unit in units} if dir == output_dir else {}, ) @@ -54,17 +55,17 @@ def check_one(units, output_dir, xcov_args): # First, produce a report for all units, with a single report format specified thistest.log("=== Step 1: all units in obj ===") -check_one(["main", "pkg"], "obj", xcov_args + ["-axcov"]) +check_one(["main.adb", "pkg.adb", "pkg.ads"], "obj", xcov_args + ["-axcov"]) # Then only create a report for pkg, still a single report format thistest.log("=== Step 2: pkg in obj ===") -check_one(["pkg"], "obj", xcov_args + ["-axcov", "--units=pkg"]) +check_one(["pkg.adb", "pkg.ads"], "obj", xcov_args + ["-axcov", "--units=pkg"]) # Now create a report for both units, but specifying two output formats # (thus creating a subdir). thistest.log("=== Step 3: all units in obj/xcov ===") check_one( - ["main", "pkg"], + ["main.adb", "pkg.adb", "pkg.ads"], os.path.join("obj", "xcov"), xcov_args + ["-axcov,html"] ) @@ -72,6 +73,6 @@ def check_one(units, output_dir, xcov_args): # An finally check that the subdir is also cleaned when once again generating # report with a single report format. thistest.log("=== Step 4: pkg in obj ===") -check_one(["pkg"], "obj", xcov_args + ["-axcov", "--units=pkg"]) +check_one(["pkg.adb", "pkg.ads"], "obj", xcov_args + ["-axcov", "--units=pkg"]) thistest.result() diff --git a/testsuite/tests/VC19-001-origin-prj/test.py b/testsuite/tests/VC19-001-origin-prj/test.py index c2d01885f..c42191de7 100644 --- a/testsuite/tests/VC19-001-origin-prj/test.py +++ b/testsuite/tests/VC19-001-origin-prj/test.py @@ -45,6 +45,6 @@ mains=["test_main"], ) -check_xcov_reports("xcov", {"code.adb.xcov": {"!": {4}}}) +check_xcov_reports("xcov", {"code.ads.xcov": {}, "code.adb.xcov": {"!": {4}}}) thistest.result() diff --git a/testsuite/tests/W315-021-generic-preelab/test.py b/testsuite/tests/W315-021-generic-preelab/test.py index 185348700..65107c97d 100644 --- a/testsuite/tests/W315-021-generic-preelab/test.py +++ b/testsuite/tests/W315-021-generic-preelab/test.py @@ -21,9 +21,10 @@ "obj", { "test.adb.xcov": {"+": {4, 6}}, - "pkg.ads.xcov": {"+": {}}, + "pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {4}}, }, + discard_empty=False, ) thistest.result() diff --git a/testsuite/tests/ignored-c-header/test.py b/testsuite/tests/ignored-c-header/test.py index 3d88bff12..fd8ed898f 100644 --- a/testsuite/tests/ignored-c-header/test.py +++ b/testsuite/tests/ignored-c-header/test.py @@ -37,7 +37,8 @@ # depends on the "identity.c". As a result, ignoring "identity.c" implicitly # ignores "identity.h", and gnatcov is supposed to warn for this case. # -# This also implies that gnatcov will not emit a report for "identity.h". +# Since gnatcov emits a report for all source files, we still expect a report +# for "identify.h". # # For binary traces, the CU for "identity.h" does not depend on "identity.c" # (its Origin is "identity.c.gli", instead), so the above is not true. @@ -50,7 +51,7 @@ cov_log, ) - expected_coverage.pop("identity.h.xcov") + expected_coverage["identity.h.xcov"] = {} check_xcov_reports("obj", expected_coverage) diff --git a/testsuite/tests/ignored-casing/test.py b/testsuite/tests/ignored-casing/test.py index f3ded030f..b1c390922 100644 --- a/testsuite/tests/ignored-casing/test.py +++ b/testsuite/tests/ignored-casing/test.py @@ -13,6 +13,7 @@ ignore_opt = "--ignore-source-files=Pkg.adb" expected_reports = { "main.adb.xcov": {"+": {5}}, + "pkg.ads.xcov": {}, } if env.build.os.name != "windows": expected_reports["pkg.adb.xcov"] = {"+": {7}} @@ -47,7 +48,7 @@ extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], trace_mode="src" ) -check_xcov_reports("out-instr", expected_reports) +check_xcov_reports("out-instr", expected_reports, discard_empty=False) tmp.to_homedir() thistest.result() diff --git a/testsuite/tests/instr-cov/208-no-secsta/test.py b/testsuite/tests/instr-cov/208-no-secsta/test.py index 6a4bf93c2..721fd62be 100644 --- a/testsuite/tests/instr-cov/208-no-secsta/test.py +++ b/testsuite/tests/instr-cov/208-no-secsta/test.py @@ -35,6 +35,7 @@ "pkg.adb.xcov": {"!": {9}}, "pkg.ads.xcov": {}, }, + discard_empty=False, ) thistest.result() diff --git a/testsuite/tests/instr-cov/216-no-elab-all/test.py b/testsuite/tests/instr-cov/216-no-elab-all/test.py index c9d0385fe..01d1093df 100644 --- a/testsuite/tests/instr-cov/216-no-elab-all/test.py +++ b/testsuite/tests/instr-cov/216-no-elab-all/test.py @@ -30,6 +30,7 @@ "pkg.adb.xcov": {"!": {9}}, "pkg.ads.xcov": {}, }, + discard_empty=False, ) thistest.result() diff --git a/testsuite/tests/instr-cov/225-expr-func-access/test.py b/testsuite/tests/instr-cov/225-expr-func-access/test.py index 8322e0487..aa7dc81e5 100644 --- a/testsuite/tests/instr-cov/225-expr-func-access/test.py +++ b/testsuite/tests/instr-cov/225-expr-func-access/test.py @@ -28,6 +28,7 @@ "pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {6, 9, 12}}, }, + discard_empty=False, ) thistest.result() diff --git a/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py index 8f86fa938..787fa11b9 100644 --- a/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py +++ b/testsuite/tests/instr-cov/226-atc-incomp-type-decl/test.py @@ -23,6 +23,7 @@ "main.adb.xcov": {"+": {4, 6}}, "pkg.ads.xcov": {}, }, + discard_empty=False, ) thistest.result() diff --git a/testsuite/tests/instr-cov/227-subunit-stub/test.py b/testsuite/tests/instr-cov/227-subunit-stub/test.py index bd34593d6..24534b0fb 100644 --- a/testsuite/tests/instr-cov/227-subunit-stub/test.py +++ b/testsuite/tests/instr-cov/227-subunit-stub/test.py @@ -109,6 +109,8 @@ class Test: check_xcov_reports( "xcov", { + "lib.ads.xcov": {}, + "lib.adb.xcov": {}, "lib-add.adb.xcov": {"-": {3, 4, 6, 7, 8, 10}}, "lib-mult.adb.xcov": {"+": {5}, "!": {4}, "-": {6, 7, 9}}, "lib-exp.adb.xcov": {"+": {5}, "!": {4}, "-": {6, 7, 9}}, diff --git a/testsuite/tests/instr-cov/base64_prefix/test.py b/testsuite/tests/instr-cov/base64_prefix/test.py index 73090a834..cead60290 100644 --- a/testsuite/tests/instr-cov/base64_prefix/test.py +++ b/testsuite/tests/instr-cov/base64_prefix/test.py @@ -35,8 +35,8 @@ run_cov_program(exepath_to(main), out=out_file) # Expected coverage report for both program executions: -main1_cov = {"pkg.adb.xcov": {"+": {11, 14}, "-": {12}}} -main2_cov = {"pkg.adb.xcov": {"+": {11, 12}, "-": {14}}} +main1_cov = {"pkg.adb.xcov": {"+": {11, 14}, "-": {12}}, "pkg.ads.xcov": {}} +main2_cov = {"pkg.adb.xcov": {"+": {11, 12}, "-": {14}}, "pkg.ads.xcov": {}} # Now combine them with different prefixes and check that "gnatcov # extract-base64-trace" correctly loads the last one. @@ -95,6 +95,6 @@ trace_filename, ] ) - check_xcov_reports(xcov_dir, cov) + check_xcov_reports(xcov_dir, cov, discard_empty=False) thistest.result() diff --git a/testsuite/tests/instr-cov/basic_base64/test.py b/testsuite/tests/instr-cov/basic_base64/test.py index dc75c32a9..94b9ccd97 100644 --- a/testsuite/tests/instr-cov/basic_base64/test.py +++ b/testsuite/tests/instr-cov/basic_base64/test.py @@ -22,6 +22,7 @@ check_xcov_reports('xcov', { 'main.adb.xcov': {'+': {5, 7, 8}}, 'pkg.adb.xcov': {'+': {5, 6, 8}}, -}) + 'pkg.ads.xcov': {}, +}, discard_empty=False) thistest.result() diff --git a/testsuite/tests/instr-cov/basic_decision/test.py b/testsuite/tests/instr-cov/basic_decision/test.py index a2091ec89..ae587656e 100644 --- a/testsuite/tests/instr-cov/basic_decision/test.py +++ b/testsuite/tests/instr-cov/basic_decision/test.py @@ -28,6 +28,7 @@ check_xcov_reports('xcov', { 'main.adb.xcov': {'+': {4, 6}}, 'pkg.adb.xcov': {'+': {6}, '!': {5}, '-': {8}}, -}) + 'pkg.ads.xcov': {}, +}, discard_empty=False) thistest.result() diff --git a/testsuite/tests/instr-cov/basic_stmt/test.py b/testsuite/tests/instr-cov/basic_stmt/test.py index 39a1fc004..927764daf 100644 --- a/testsuite/tests/instr-cov/basic_stmt/test.py +++ b/testsuite/tests/instr-cov/basic_stmt/test.py @@ -26,6 +26,7 @@ check_xcov_reports('xcov', { 'main.adb.xcov': {'+': {5, 7, 8}}, 'pkg.adb.xcov': {'+': {5, 6, 8}}, -}) + 'pkg.ads.xcov': {}, +}, discard_empty=False) thistest.result() diff --git a/testsuite/tests/instr-cov/buffer_reset/test.py b/testsuite/tests/instr-cov/buffer_reset/test.py index f7d87275d..f826fe5ec 100644 --- a/testsuite/tests/instr-cov/buffer_reset/test.py +++ b/testsuite/tests/instr-cov/buffer_reset/test.py @@ -24,7 +24,7 @@ # Units which will only have a partial coverage result in them, regardless of # the trace. default_part_cov = { - "ada": {"pkg.adb.xcov": {'!': {5}}}, + "ada": {"pkg.adb.xcov": {'!': {5}}, "pkg.ads.xcov": {}}, "c": {"pkh.c.xcov": {'!': {6}}}, } @@ -33,6 +33,7 @@ "ada": { "main_ada.adb.xcov": {'-': {7, 10, 13}}, "pkg.adb.xcov": {'-': {5}}, + "pkg.ads.xcov": {}, }, "c": { "main_c.c.xcov": {'-': {8, 11, 14, 16}}, @@ -141,6 +142,7 @@ def check_one_exec(cov_args, lang): output_dir, { "main_ada.adb.xcov": {'+': {7, 10, 13}}, + "pkg.ads.xcov": {}, "pkg.adb.xcov": {'+': {5}}, "main_c.c.xcov": {'+': {8, 11, 14}, '-': {16}}, "pkh.c.xcov": {'+': {6}} diff --git a/testsuite/tests/instr-cov/c_empty_source/test.py b/testsuite/tests/instr-cov/c_empty_source/test.py index 7e0718332..ace1da61f 100644 --- a/testsuite/tests/instr-cov/c_empty_source/test.py +++ b/testsuite/tests/instr-cov/c_empty_source/test.py @@ -21,6 +21,8 @@ trace_mode='src', ) -check_xcov_reports('xcov', {'main.c.xcov': {'+': {6}}}) +check_xcov_reports( + 'xcov', {'main.c.xcov': {'+': {6}}, 'pkg.c.xcov': {}}, discard_empty=False +) thistest.result() diff --git a/testsuite/tests/instr-cov/endianity/test.py b/testsuite/tests/instr-cov/endianity/test.py index b415e115d..fb7b613f9 100644 --- a/testsuite/tests/instr-cov/endianity/test.py +++ b/testsuite/tests/instr-cov/endianity/test.py @@ -44,6 +44,7 @@ check_xcov_reports(xcov_dir, { 'main.adb.xcov': {'+': {5, 7, 8}}, 'pkg.adb.xcov': {'+': {6, 8}, '!': {5}}, - }) + 'pkg.ads.xcov': {}, + }, discard_empty=False) thistest.result() diff --git a/testsuite/tests/instr-cov/ghost_generic/test.py b/testsuite/tests/instr-cov/ghost_generic/test.py index a2f5bc2d8..b0d3f133f 100644 --- a/testsuite/tests/instr-cov/ghost_generic/test.py +++ b/testsuite/tests/instr-cov/ghost_generic/test.py @@ -27,6 +27,7 @@ "gen.ads.xcov": {}, "non_ghost_inst.ads.xcov": {} }, + discard_empty=False, ) thistest.result() diff --git a/testsuite/tests/instr-cov/gpr-complex/test.py b/testsuite/tests/instr-cov/gpr-complex/test.py index fd74a938f..78d61f7fd 100644 --- a/testsuite/tests/instr-cov/gpr-complex/test.py +++ b/testsuite/tests/instr-cov/gpr-complex/test.py @@ -70,7 +70,11 @@ def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): # Try the simple case: the main project extends the library, but does not # redefine anything. thistest.log("== Simple case ==") -expected_xcov = {"pkg.adb.xcov": {"+": {5}}, "pkg-bar.adb.xcov": {"+": {3}}} +expected_xcov = { + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {5}}, + "pkg-bar.adb.xcov": {"+": {3}}, +} build_run_cov_and_check( "main_simple.gpr", main_prj_obj_dir="obj-main_simple", @@ -83,7 +87,11 @@ def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): # belonging to the library. We should fix this (and adjust coverage # expectations) if possible. thistest.log("== Redefining Pkg body ==") -expected_xcov = {"pkg.adb.xcov": {"+": {7}}, "pkg-bar.adb.xcov": {"+": {3}}} +expected_xcov = { + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {7}}, + "pkg-bar.adb.xcov": {"+": {3}}, +} build_run_cov_and_check( "main_body.gpr", main_prj_obj_dir="obj-main_body", @@ -93,7 +101,11 @@ def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): # Now the main project defines an alternate separate. thistest.log("== Redefining Pkg.Bar separate ==") -expected_xcov = {"pkg.adb.xcov": {"+": {5}}, "pkg-bar.adb.xcov": {"+": {5}}} +expected_xcov = { + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {5}}, + "pkg-bar.adb.xcov": {"+": {5}}, +} build_run_cov_and_check( "main_sep.gpr", main_prj_obj_dir="obj-main_sep", @@ -103,6 +115,7 @@ def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): # Now the main project defines an alternate spec. thistest.log("== Redefining Pkg spec ==") expected_xcov = { + "pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {5}}, "pkg-bar.adb.xcov": {"+": {3}}, "pkg.ads.xcov": {"+": {4}}, diff --git a/testsuite/tests/instr-cov/main-spec/test.py b/testsuite/tests/instr-cov/main-spec/test.py index ebe20bf31..a6b18e367 100644 --- a/testsuite/tests/instr-cov/main-spec/test.py +++ b/testsuite/tests/instr-cov/main-spec/test.py @@ -18,6 +18,15 @@ main_sources = ["inst_main.ads", "pkg-child_main.ads"] mains = [os.path.splitext(f)[0] for f in main_sources] +expected_cov = { + "generic_main.adb.xcov": {"+": {5}}, + "inst_main.ads.xcov": {}, + "pkg-child_main.ads.xcov": {}, +} +if thistest.options.trace_mode == "src": + expected_cov["generic_main.ads.xcov"] = {} + expected_cov["pkg.ads.xcov"] = {} + # Explicitly test all available dump triggers to maximize coverage for dump_trigger in available_ada_dump_triggers(): thistest.log(f"== {dump_trigger} ==") @@ -31,13 +40,6 @@ mains=mains, extra_coverage_args=["--annotate=xcov"], ) - check_xcov_reports( - "obj", - { - "generic_main.adb.xcov": {"+": {5}}, - "inst_main.ads.xcov": {}, - "pkg-child_main.ads.xcov": {}, - }, - ) + check_xcov_reports("obj", expected_cov, discard_empty=False) thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py b/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py index aeda6c74b..4970a9bac 100644 --- a/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py @@ -50,6 +50,7 @@ "pkg.adb.xcov": {"+": {10, 22}, "-": {12, 23}}, "pkg.ads.xcov": {}, }, + discard_empty=False, ) tmp.to_homedir() diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/test.py b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py index 0a53075d0..ea4a94609 100644 --- a/testsuite/tests/instr-cov/manual-dump/ada_only/test.py +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py @@ -70,6 +70,8 @@ def check_call(file): check_xcov_reports('xcov', { 'main.adb.xcov': {'+': {12, 15, 19, 24, 26, 27, 28}, '-': {21, 29}}, - 'lib1.adb.xcov': {'+': {4, 7}}}) + 'lib1.adb.xcov': {'+': {4, 7}}, + 'lib1.ads.xcov': {}, +}) thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py index ede4b8ff6..6a3737584 100644 --- a/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py +++ b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py @@ -52,6 +52,9 @@ def make_lib_gpr(name, srcdirs, deps): check_xcov_reports('xcov', { 'lib1.adb.xcov': {'+': {6, 8}, '-': {10}}, - 'lib2.adb.xcov': {'+': {4, 6}}}) + 'lib1.ads.xcov': {}, + 'lib2.adb.xcov': {'+': {4, 6}}, + 'lib2.ads.xcov': {}, +}) thistest.result() diff --git a/testsuite/tests/instr-cov/multi_unit_source/test.py b/testsuite/tests/instr-cov/multi_unit_source/test.py index 16a26117b..0fbc9cb11 100644 --- a/testsuite/tests/instr-cov/multi_unit_source/test.py +++ b/testsuite/tests/instr-cov/multi_unit_source/test.py @@ -56,6 +56,8 @@ extra_coverage_args=["--units=pck", "-axcov"], ) -check_xcov_reports("obj", {"pck.adb.xcov": {"+": {9, 10, 11}}}) +check_xcov_reports( + "obj", {"pck.adb.xcov": {"+": {9, 10, 11}}, "pck.ads.xcov": {}} +) thistest.result() diff --git a/testsuite/tests/instr-cov/no_main/test.py b/testsuite/tests/instr-cov/no_main/test.py index b8ae5e4bc..f0f67e3c3 100644 --- a/testsuite/tests/instr-cov/no_main/test.py +++ b/testsuite/tests/instr-cov/no_main/test.py @@ -25,6 +25,10 @@ gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, trace_mode='src') -check_xcov_reports('xcov', {'pkg.adb.xcov': {'+': {5, 6, 8}}}) +check_xcov_reports( + 'xcov', + {'pkg.adb.xcov': {'+': {5, 6, 8}}, 'pkg.ads.xcov': {}}, + discard_empty=False, +) thistest.result() diff --git a/testsuite/tests/instr-cov/orphan-unit/test.py b/testsuite/tests/instr-cov/orphan-unit/test.py index dc9e4b8ca..dc9185aa7 100644 --- a/testsuite/tests/instr-cov/orphan-unit/test.py +++ b/testsuite/tests/instr-cov/orphan-unit/test.py @@ -13,6 +13,7 @@ expected_cov = {"main.adb.xcov": {"+": {5}}} if thistest.options.trace_mode == "src": + expected_cov["pkg-child.ads.xcov"] = {} expected_cov["pkg-child.adb.xcov"] = {"-": {6}} build_run_and_coverage( diff --git a/testsuite/tests/instr-cov/pragma_after_cu/test.py b/testsuite/tests/instr-cov/pragma_after_cu/test.py index 02581b766..39f1519f4 100644 --- a/testsuite/tests/instr-cov/pragma_after_cu/test.py +++ b/testsuite/tests/instr-cov/pragma_after_cu/test.py @@ -22,6 +22,6 @@ 'main.adb.xcov': {'+': {6}}, 'raise_error.adb.xcov': {'+': {3}}, 'raise_error.ads.xcov': {}, -}) +}, discard_empty=False) thistest.result() diff --git a/testsuite/tests/instr-cov/pragma_no_body/test.py b/testsuite/tests/instr-cov/pragma_no_body/test.py index 124c6b3f0..253d9a063 100644 --- a/testsuite/tests/instr-cov/pragma_no_body/test.py +++ b/testsuite/tests/instr-cov/pragma_no_body/test.py @@ -20,7 +20,9 @@ ) check_xcov_reports('xcov', { 'main.adb.xcov': {'+': {5}}, + 'orig_pkg.ads.xcov': {}, 'orig_pkg.adb.xcov': {'+': {4}}, + 'pkg.ads.xcov': {}, }) thistest.result() diff --git a/testsuite/tests/instr-cov/pretty_print/test.py b/testsuite/tests/instr-cov/pretty_print/test.py index f8bcd415b..c347da5a5 100644 --- a/testsuite/tests/instr-cov/pretty_print/test.py +++ b/testsuite/tests/instr-cov/pretty_print/test.py @@ -24,7 +24,9 @@ { "main.adb.xcov": {"+": {5, 7, 8}}, "pkg.adb.xcov": {"+": {5, 6, 8}}, + "pkg.ads.xcov": {}, }, + discard_empty=False, ) thistest.result() diff --git a/testsuite/tests/instr-cov/short_circuit_and_or/test.py b/testsuite/tests/instr-cov/short_circuit_and_or/test.py index ad62d57c3..5744f52af 100644 --- a/testsuite/tests/instr-cov/short_circuit_and_or/test.py +++ b/testsuite/tests/instr-cov/short_circuit_and_or/test.py @@ -24,6 +24,7 @@ def check_results(): "main.adb.xcov": {"!": {42, 43, 53, 54}, "+": {81, 82, 87, 88}}, "type_pkg.ads.xcov": {}, }, + discard_empty=False, ) diff --git a/testsuite/tests/relocate-build-tree/modified-root-dir/test.py b/testsuite/tests/relocate-build-tree/modified-root-dir/test.py index c252c8ce4..2c6899406 100644 --- a/testsuite/tests/relocate-build-tree/modified-root-dir/test.py +++ b/testsuite/tests/relocate-build-tree/modified-root-dir/test.py @@ -57,6 +57,6 @@ extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], ) -check_xcov_reports("out-instr", expected_reports) +check_xcov_reports("out-instr", expected_reports, discard_empty=False) thistest.result() diff --git a/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py index 76e9e47cd..7ff57e9b1 100644 --- a/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py +++ b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py @@ -48,7 +48,7 @@ extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], ) -check_xcov_reports("out-instr", expected_reports) +check_xcov_reports("out-instr", expected_reports, discard_empty=False) # Check if relative path for GPR works correctly build_run_and_coverage( @@ -58,7 +58,7 @@ extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], ) -check_xcov_reports("out-instr", expected_reports) +check_xcov_reports("out-instr", expected_reports, discard_empty=False) os.environ["GPR_PROJECT_PATH"] += os.pathsep + os.path.dirname(tests_gpr) build_run_and_coverage( @@ -68,6 +68,6 @@ extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], ) -check_xcov_reports("out-instr", expected_reports) +check_xcov_reports("out-instr", expected_reports, discard_empty=False) thistest.result() diff --git a/testsuite/tests/shared-libs/ada-main/test.py b/testsuite/tests/shared-libs/ada-main/test.py index 8c2484780..a0be36357 100644 --- a/testsuite/tests/shared-libs/ada-main/test.py +++ b/testsuite/tests/shared-libs/ada-main/test.py @@ -47,6 +47,8 @@ # same kind as the others, so force relocatable. extra_gprbuild_args=['-XLIBRARY_TYPE=relocatable']) -check_xcov_reports('.', {'mylib.adb.xcov': {'+': {5, 6}, '-': {8}}}) +check_xcov_reports( + '.', {'mylib.adb.xcov': {'+': {5, 6}, '-': {8}}, 'mylib.ads.xcov': {}} +) thistest.result() diff --git a/testsuite/tests/subp_of_interest_c/test.py b/testsuite/tests/subp_of_interest_c/test.py index 79e002e0e..6a2121efd 100644 --- a/testsuite/tests/subp_of_interest_c/test.py +++ b/testsuite/tests/subp_of_interest_c/test.py @@ -37,6 +37,7 @@ "bar.h.xcov": {}, "pkg.c.xcov": {"+": {4}}, }, + discard_empty=False, ) thistest.result() diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 1eb0f9683..ee5ea458b 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -1825,7 +1825,8 @@ package body Files_Table is if Object_Coverage_Enabled then return File.Has_Object_Coverage_Info; else - return File.Has_Source_Coverage_Info; + return File.Kind = Source_File + and then File.Ignore_Status in Sometimes | Never; end if; end To_Display; From 11baf12fa22011058c00425f75eca5c4a25420b8 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 22 Feb 2024 18:17:46 +0100 Subject: [PATCH 0729/1483] doc: Document visualization of a coverage report in GPS --- doc/gnatcov/gps.rst | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/doc/gnatcov/gps.rst b/doc/gnatcov/gps.rst index d96b5dcd6..034b1d585 100644 --- a/doc/gnatcov/gps.rst +++ b/doc/gnatcov/gps.rst @@ -39,7 +39,7 @@ respective menu items under the Also Note that you can select a prebuilt gnatcov runtime under the same menu. This will skip the "build the gnatcov runtime" step, and will be especially -useful if you bring modifications to this runtime. By default, GNATstudio will +useful if you bring modifications to this runtime. By default, GNAT Studio will rebuild the runtime that is shipped with GNATcoverage and reinstall it in a temporary directory every time. @@ -58,6 +58,19 @@ file with annotations that represent the coverage state: Note that the Locations view reports all non-covered lines. It makes navigation easy as you only have to click on a diagnostic to go to the corresponding line. +Viewing a coverage report produced outside of GNAT Studio +========================================================= + +If the workflow is not adapted to your process, GNAT Studio also supports +displaying a coverage report produced externally, by first loading the coverage +data using any of the actionable `Load Data` item under +:menuselection:`Analyze --> Coverage`. + +GNAT Studio expects a coverage report under the xcov+ format, under the object +directory of the project (), or under /xcov+. + +Then you can visualize the report by clicking on +:menuselection:`Analyze --> Coverage --> Show coverage report`. GNATtest scenario ================= From 06080cc38b23a31446ca9791c56b12ef6855a9a3 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 16 Feb 2024 14:58:04 +0000 Subject: [PATCH 0730/1483] pre-commit: add flake8 and black --- .flake8 | 2 ++ .pre-commit-config.yaml | 15 +++++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 .flake8 diff --git a/.flake8 b/.flake8 new file mode 100644 index 000000000..17eee26f2 --- /dev/null +++ b/.flake8 @@ -0,0 +1,2 @@ +[flake8] +ignore = E203,E402,W503 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c65082fd2..3494b32e3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,3 +18,18 @@ repos: Maximum: -1 } }"] + - repo: https://github.com/pycqa/flake8 + rev: 6.0.0 + hooks: + - id: flake8 + additional_dependencies: + - flake8-bugbear + - flake8-builtins + - flake8-comprehensions + - pygments + args: ["--config=.flake8"] + - repo: https://github.com/ambv/black + rev: 23.1.0 + hooks: + - id: black + args: ["--line-length=79"] From 34a3662ae6cc44f8636e98768cf3106d9985f569 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 26 Feb 2024 14:43:13 +0100 Subject: [PATCH 0731/1483] Run clang-format on all C/C++ sources --- .../If_And_Eq_Or/src/andeqor.c | 5 +- .../Ret_Or_Eq_And_Not/src/oreqandnot.c | 3 +- testsuite/Qualif/C/src/support.h | 11 ++--- .../01_1_Identifier/src/statements.c | 10 ++-- .../01_2_Constant/src/statements.c | 8 ++-- .../01_3_StringLitteral/src/statements.c | 8 ++-- .../02_01_Subscript/src/statements.c | 12 ++--- .../02_02_Call/src/statements.c | 4 +- .../02_03_Member/src/statements.c | 32 +++++-------- .../02_04_IncrDecr/src/statements.c | 14 +++--- .../02_05_Compound/src/statements.c | 22 ++++----- .../03_01_IncrDecr/src/statements.c | 14 +++--- .../03_03_UnaryOperator/src/statements.c | 32 ++++++------- .../03_041_SizeofExpr/src/statements.c | 10 ++-- .../03_042_SizeofType/src/statements.c | 8 ++-- .../05_Expressions/04_Cast/src/statements.c | 8 ++-- .../05_Multiplicative/src/statements.c | 8 ++-- .../06_Additive/src/statements.c | 8 ++-- .../07_BitwiseShift/src/statements.c | 14 +++--- .../08_Relational/src/statements.c | 26 +++++----- .../09_Equality/src/statements.c | 14 +++--- .../10_BitwiseAnd/src/statements.c | 8 ++-- .../11_BitwiseXor/src/statements.c | 8 ++-- .../12_BitwiseOr/src/statements.c | 8 ++-- .../13_LogicalAnd/src/statements.c | 8 ++-- .../14_LogicalOr/src/statements.c | 4 +- .../15_Conditional/src/statements.c | 16 +++---- .../16_Assignment/src/statements.c | 48 +++++++++---------- .../05_Expressions/17_Comma/src/statements.c | 2 +- .../stmt/Core/05_Expressions/src/statements.h | 11 ++--- .../02_Compound/Basic/src/statements.c | 18 +++---- .../02_Compound/GotoIn/src/statements.c | 10 ++-- .../02_Compound/GotoOut/src/statements.c | 10 ++-- .../02_Compound/src/statements.h | 11 ++--- .../04_Selection/01_If/src/doif.c | 9 ++-- .../04_Selection/01_If/src/doif.h | 4 +- .../04_Selection/02_Switch/src/doswitch.c | 28 +++++------ .../04_Selection/02_Switch/src/doswitch.h | 14 +++--- .../05_Iteration/01_While/src/dowhile.c | 24 +++++----- .../05_Iteration/01_While/src/dowhile.h | 6 +-- .../05_Iteration/02_DoWhile/src/dowhile.c | 28 ++++++----- .../05_Iteration/02_DoWhile/src/dowhile.h | 6 +-- .../05_Iteration/03_For/src/dofor.c | 24 +++++----- .../05_Iteration/03_For/src/dofor.h | 9 ++-- .../06_Jump/01_Goto/src/dogoto.c | 20 ++++---- .../06_Jump/01_Goto/src/dogoto.h | 5 +- .../06_Jump/02_Continue/src/docontinue.c | 21 ++++---- .../06_Jump/02_Continue/src/docontinue.h | 5 +- .../06_Jump/03_Break/src/dobreak.c | 21 ++++---- .../06_Jump/03_Break/src/dobreak.h | 5 +- .../06_Jump/04_Return/src/doreturn.c | 6 +-- .../06_Jump/04_Return/src/doreturn.h | 2 +- .../If_For_If_Case/src/sensors_status.c | 32 ++++++------- .../If_For_If_Case/src/sensors_status.h | 5 +- .../While_If1/src/sensors_predicates.c | 3 +- .../While_If1/src/sensors_predicates.h | 15 +++--- .../While_If1/src/slists_count.c | 17 ++++--- .../While_If1/src/slists_count.h | 10 ++-- .../While_If4/src/slists_fault.c | 27 +++++------ .../While_If4/src/slists_fault.h | 10 ++-- .../While_If_Case_If/src/slists_forall.c | 30 ++++++------ .../While_If_Case_If/src/slists_forall.h | 8 ++-- .../While_If_Case_If/src/test_act_inh.c | 14 +++--- .../While_If_Case_If/src/test_activate.c | 4 +- .../While_If_Case_If/src/test_inhibit.c | 8 ++-- .../C/stmt/MixedConstructs/src/sensors.h | 12 ++--- .../C/stmt/MixedConstructs/src/simple_pools.h | 7 ++- .../C/stmt/MixedConstructs/src/slists.c | 2 +- .../C/stmt/MixedConstructs/src/slists.h | 12 ++--- .../Qualif/C/stmt/MixedConstructs/src/vbufs.c | 11 +++-- .../Qualif/C/stmt/MixedConstructs/src/vbufs.h | 10 ++-- .../104-pragma-directives/src/test_pragma.c | 6 +-- .../106-externally-built-header/main/main.c | 6 +-- .../106-externally-built-header/mylib/mylib.c | 2 +- .../106-externally-built-header/mylib/mylib.h | 2 +- .../tests/129-instr-progress/cpp_unit.cpp | 3 +- testsuite/tests/129-instr-progress/test.py | 2 +- .../AandB/Lambda_Robustness/src/tryme.cpp | 32 ++++++------- .../C++/mcdc/ConstExpr/src/test_constexpr.cpp | 3 +- .../src/test_for_range.cpp | 2 +- .../stmt/StructMemberFun/src/test_struct.cpp | 9 ++-- .../tests/C/mcdc/Exemptions/Invalid/main.c | 10 ++-- .../tests/C/mcdc/Exemptions/Nominal/src/pkg.c | 8 ++-- testsuite/tests/HomonymSymbols/src/support.h | 2 +- .../tests/header_not_found/base_foo/support.h | 3 +- .../header_not_found/include_base_foo/test.c | 5 +- .../include_foo/headers/support.h | 3 +- .../tests/header_not_found/include_foo/test.c | 5 +- testsuite/tests/header_not_found/test.py | 8 ++-- .../C++/68-lambda-decisions/src/pkg.cpp | 8 ++-- .../tests/instr-cov/c_multiline_stmt/main.c | 12 ++--- tools/gnatcov/bfd_helpers.c | 12 ++--- tools/gnatcov/clang-wrapper.cc | 3 +- .../examples/support/src/leon-elf/abort.c | 5 +- tools/gnatcov/libopcodes_bind/dis_stream.c | 4 +- tools/gnatcov/libopcodes_bind/dis_stream.h | 6 +-- tools/gnatcov/libopcodes_bind/dis_wrapper.c | 10 ++-- tools/gnatcov/libopcodes_bind/dis_wrapper.h | 12 ++--- tools/gnatcov/zlib_helpers.c | 4 +- 99 files changed, 541 insertions(+), 553 deletions(-) diff --git a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/andeqor.c b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/andeqor.c index a54eee59a..1d5a9ebc8 100644 --- a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/andeqor.c +++ b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/If_And_Eq_Or/src/andeqor.c @@ -1,8 +1,9 @@ -char andeqor (char A, char B, char C, char D) +char +andeqor (char A, char B, char C, char D) { if ((A && B) == (C || D)) // # eval - return (char) 1; // # true + return (char) 1; // # true else return (char) 0; // # false } diff --git a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/oreqandnot.c b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/oreqandnot.c index 2281abbfa..a32b397c9 100644 --- a/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/oreqandnot.c +++ b/testsuite/Qualif/C/mcdc/Robustness/MultiDecisionExpr/Ret_Or_Eq_And_Not/src/oreqandnot.c @@ -1,5 +1,6 @@ -char oreqandnot (char A, char B, char C, char D) +char +oreqandnot (char A, char B, char C, char D) { return ((A || B) == (C && !D)); // # eval } diff --git a/testsuite/Qualif/C/src/support.h b/testsuite/Qualif/C/src/support.h index 7e2983e28..052a658b8 100644 --- a/testsuite/Qualif/C/src/support.h +++ b/testsuite/Qualif/C/src/support.h @@ -1,11 +1,10 @@ #ifndef SUPPORT_H -# define SUPPORT_H +#define SUPPORT_H -# define NULL ((void *) 0) -# define false 0 -# define true 1 +#define NULL ((void *) 0) +#define false 0 +#define true 1 -extern void -assert (char cond); +extern void assert (char cond); #endif diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/01_1_Identifier/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/01_1_Identifier/src/statements.c index cfd185063..3126f898e 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/01_1_Identifier/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/01_1_Identifier/src/statements.c @@ -3,14 +3,14 @@ int run_statements (int full, int arg) { - arg; // # statements-all - if (full) // # statements-aux-all + arg; // # statements-all + if (full) // # statements-aux-all { - arg; // # statements-cond + arg; // # statements-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ - ++arg; // # statements-aux-cond + ++arg; // # statements-aux-cond } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/01_2_Constant/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/01_2_Constant/src/statements.c index 336ab3e41..c1bb8fdfd 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/01_2_Constant/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/01_2_Constant/src/statements.c @@ -3,14 +3,14 @@ int run_statements (int full, int arg) { - 0x80; // # statements-all - if (full) // # statements-aux-all + 0x80; // # statements-all + if (full) // # statements-aux-all { - 0xff; // # statements-cond + 0xff; // # statements-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ arg += 1; // # statements-aux-cond } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/01_3_StringLitteral/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/01_3_StringLitteral/src/statements.c index 1ee588c00..71ff7e11f 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/01_3_StringLitteral/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/01_3_StringLitteral/src/statements.c @@ -3,14 +3,14 @@ int run_statements (int full, int arg) { - "Hello, "; // # statements-all - if (full) // # statements-aux-all + "Hello, "; // # statements-all + if (full) // # statements-aux-all { "world!"; // # statements-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ - ++arg; // # statements-aux-cond + ++arg; // # statements-aux-cond }; - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_01_Subscript/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_01_Subscript/src/statements.c index 91f215b2d..c8e54d306 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_01_Subscript/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_01_Subscript/src/statements.c @@ -3,17 +3,17 @@ int num (int *arg) { - return ++*arg; // # statements-aux-all + return ++*arg; // # statements-aux-all } int run_statements (int full, int arg) { - int a[2] = { 0, 1, 2 }; // # statements-aux-all + int a[2] = { 0, 1, 2 }; // # statements-aux-all - a[num (&arg)]; // # statements-all - if (full) // # statements-aux-all - a[num (&arg)]; // # statements-cond + a[num (&arg)]; // # statements-all + if (full) // # statements-aux-all + a[num (&arg)]; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_02_Call/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_02_Call/src/statements.c index 50550ef51..77d11437a 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_02_Call/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_02_Call/src/statements.c @@ -3,7 +3,7 @@ static void nop (int *arg) { - ++*arg; // # statements-aux-all + ++*arg; // # statements-aux-all } int @@ -13,5 +13,5 @@ run_statements (int full, int arg) if (full) // # statements-aux-all nop (&arg); // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_03_Member/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_03_Member/src/statements.c index 51547d969..5775d22fe 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_03_Member/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_03_Member/src/statements.c @@ -5,40 +5,34 @@ struct foo int bar; }; -static struct foo foo_objects[5] = -{ - { 1 }, - { 2 }, - { 3 }, - { 4 }, - { 5 }, +static struct foo foo_objects[5] = { + { 1 }, { 2 }, { 3 }, { 4 }, { 5 }, }; struct foo get_foo (int arg) { - foo_objects[arg].bar += 1; // # statements-aux-all - return foo_objects[arg]; // # statements-aux-all + foo_objects[arg].bar += 1; // # statements-aux-all + return foo_objects[arg]; // # statements-aux-all } struct foo * get_foo_p (int arg) { - foo_objects[arg].bar += 1; // # statements-aux-all - return &foo_objects[arg]; // # statements-aux-all + foo_objects[arg].bar += 1; // # statements-aux-all + return &foo_objects[arg]; // # statements-aux-all } - int run_statements (int full, int arg) { - get_foo (++arg).bar; // # statements-all - if (full) // # statements-aux-all - get_foo (++arg).bar; // # statements-cond + get_foo (++arg).bar; // # statements-all + if (full) // # statements-aux-all + get_foo (++arg).bar; // # statements-cond - get_foo_p (++arg)->bar; // # statements-all - if (full) // # statements-aux-all - get_foo_p (++arg)->bar; // # statements-cond + get_foo_p (++arg)->bar; // # statements-all + if (full) // # statements-aux-all + get_foo_p (++arg)->bar; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_04_IncrDecr/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_04_IncrDecr/src/statements.c index 3c4182444..0a257627e 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_04_IncrDecr/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_04_IncrDecr/src/statements.c @@ -3,12 +3,12 @@ int run_statements (int full, int arg) { - arg++; // # statements-all - if (full) // # statements-aux-all - arg++; // # statements-cond + arg++; // # statements-all + if (full) // # statements-aux-all + arg++; // # statements-cond - arg--; // # statements-all - if (full) // # statements-aux-all - arg--; // # statements-cond - return arg; // # statements-aux-all + arg--; // # statements-all + if (full) // # statements-aux-all + arg--; // # statements-cond + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_05_Compound/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_05_Compound/src/statements.c index ec7c388ee..b77051372 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/02_05_Compound/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/02_05_Compound/src/statements.c @@ -2,30 +2,30 @@ struct complex_number { - int real; - int imag; + int real; + int imag; }; int run_statements (int full, int arg) { - (char *) {"Hello, world!"}; // # statements-all - if (full) // # statements-aux-all + (char *){ "Hello, world!" }; // # statements-all + if (full) // # statements-aux-all { - (char *) {"Hello, world!"}; // # statements-cond - ++arg; // # statements-aux-cond + (char *){ "Hello, world!" }; // # statements-cond + ++arg; // # statements-aux-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ } - (struct complex_number) { 1, 2 }; // # statements-all - if (full) // # statements-aux-all + (struct complex_number){ 1, 2 }; // # statements-all + if (full) // # statements-aux-all { - (struct complex_number) { 1, 2 }; // # statements-cond - ++arg; // # statements-aux-cond + (struct complex_number){ 1, 2 }; // # statements-cond + ++arg; // # statements-aux-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_01_IncrDecr/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_01_IncrDecr/src/statements.c index f3dddb0bf..b38a77de5 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_01_IncrDecr/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_01_IncrDecr/src/statements.c @@ -3,13 +3,13 @@ int run_statements (int full, int arg) { - ++arg; // # statements-all - if (full) // # statements-aux-all - ++arg; // # statements-cond + ++arg; // # statements-all + if (full) // # statements-aux-all + ++arg; // # statements-cond - --arg; // # statements-all - if (full) // # statements-aux-all - --arg; // # statements-cond + --arg; // # statements-all + if (full) // # statements-aux-all + --arg; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_03_UnaryOperator/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_03_UnaryOperator/src/statements.c index dc7b94d00..01fe3088d 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_03_UnaryOperator/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_03_UnaryOperator/src/statements.c @@ -3,27 +3,27 @@ int run_statements (int full, int arg) { - int *b = &arg; // # statements-aux-all + int *b = &arg; // # statements-aux-all - &arg; // # statements-all - *b; // # statements-all - +arg; // # statements-all - -arg; // # statements-all - ~arg; // # statements-all - !arg; // # statements-all + &arg; // # statements-all + *b; // # statements-all + +arg; // # statements-all + -arg; // # statements-all + ~arg; // # statements-all + !arg; // # statements-all - if (full) // # statements-aux-all + if (full) // # statements-aux-all { - &arg; // # statements-cond - *b; // # statements-cond - +arg; // # statements-cond - -arg; // # statements-cond - ~arg; // # statements-cond - !arg; // # statements-cond + &arg; // # statements-cond + *b; // # statements-cond + +arg; // # statements-cond + -arg; // # statements-cond + ~arg; // # statements-cond + !arg; // # statements-cond /* The following statement is needed so that the previous statements are considered as covered even if they generate no code. */ - ++arg; // # statements-aux-cond + ++arg; // # statements-aux-cond } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_041_SizeofExpr/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_041_SizeofExpr/src/statements.c index 329da57e7..5a0bc84ac 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_041_SizeofExpr/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_041_SizeofExpr/src/statements.c @@ -3,14 +3,14 @@ int run_statements (int foo, int arg) { - sizeof (arg); // # statements-all - if (foo) // # statements-aux-all - { + sizeof (arg); // # statements-all + if (foo) // # statements-aux-all + { sizeof (arg); // # statements-cond ++arg; // # statements-aux-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ - } + } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_042_SizeofType/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_042_SizeofType/src/statements.c index 50ab477c7..b3da7b170 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/03_042_SizeofType/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/03_042_SizeofType/src/statements.c @@ -3,13 +3,13 @@ int run_statements (int foo, int arg) { - sizeof (int); // # statements-all - if (foo) // # statements-aux-all + sizeof (int); // # statements-all + if (foo) // # statements-aux-all { sizeof (int); // # statements-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ - arg += 1; // # statements-aux-cond + arg += 1; // # statements-aux-cond } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/04_Cast/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/04_Cast/src/statements.c index ad231ad9a..53787a879 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/04_Cast/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/04_Cast/src/statements.c @@ -3,12 +3,12 @@ int run_statements (int full, int arg) { - if (full) // # statements-aux-all + if (full) // # statements-aux-all { - (void) arg; // # statements-cond + (void) arg; // # statements-cond /* The following statement is needed so that the previous statement is considered as covered even if it generates no code. */ - ++arg; // # statements-aux-cond + ++arg; // # statements-aux-cond } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/05_Multiplicative/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/05_Multiplicative/src/statements.c index 1136a85dd..317732b6b 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/05_Multiplicative/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/05_Multiplicative/src/statements.c @@ -3,9 +3,9 @@ int run_statements (int full, int arg) { - ++arg * 0; // # statements-all - if (full) // # statements-aux-all - ++arg * 0; // # statements-cond + ++arg * 0; // # statements-all + if (full) // # statements-aux-all + ++arg * 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/06_Additive/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/06_Additive/src/statements.c index 4fbfc6f7d..ab64b75b4 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/06_Additive/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/06_Additive/src/statements.c @@ -3,9 +3,9 @@ int run_statements (int full, int arg) { - ++arg + 0; // # statements-all - if (full) // # statements-aux-all - ++arg + 0; // # statements-cond + ++arg + 0; // # statements-all + if (full) // # statements-aux-all + ++arg + 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/07_BitwiseShift/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/07_BitwiseShift/src/statements.c index 04aa32ff8..e84035a98 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/07_BitwiseShift/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/07_BitwiseShift/src/statements.c @@ -3,13 +3,13 @@ int run_statements (int full, int arg) { - ++arg << 1; // # statements-all - if (full) // # statements-aux-all - ++arg << 1; // # statements-cond + ++arg << 1; // # statements-all + if (full) // # statements-aux-all + ++arg << 1; // # statements-cond - ++arg >> 1; // # statements-all - if (full) // # statements-aux-all - ++arg >> 1; // # statements-cond + ++arg >> 1; // # statements-all + if (full) // # statements-aux-all + ++arg >> 1; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/08_Relational/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/08_Relational/src/statements.c index 8a358de15..4b00a5713 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/08_Relational/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/08_Relational/src/statements.c @@ -3,21 +3,21 @@ int run_statements (int full, int arg) { - ++arg < 0; // # statements-all - if (full) // # statements-aux-all - ++arg < 0; // # statements-cond + ++arg < 0; // # statements-all + if (full) // # statements-aux-all + ++arg < 0; // # statements-cond - ++arg > 0; // # statements-all - if (full) // # statements-aux-all - ++arg > 0; // # statements-cond + ++arg > 0; // # statements-all + if (full) // # statements-aux-all + ++arg > 0; // # statements-cond - ++arg <= 0; // # statements-all - if (full) // # statements-aux-all - ++arg <= 0; // # statements-cond + ++arg <= 0; // # statements-all + if (full) // # statements-aux-all + ++arg <= 0; // # statements-cond - ++arg >= 0; // # statements-all - if (full) // # statements-aux-all - ++arg >= 0; // # statements-cond + ++arg >= 0; // # statements-all + if (full) // # statements-aux-all + ++arg >= 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/09_Equality/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/09_Equality/src/statements.c index 811d04152..7392a3c13 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/09_Equality/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/09_Equality/src/statements.c @@ -3,13 +3,13 @@ int run_statements (int full, int arg) { - ++arg == 0; // # statements-all - if (full) // # statements-aux-all - ++arg == 0; // # statements-cond + ++arg == 0; // # statements-all + if (full) // # statements-aux-all + ++arg == 0; // # statements-cond - ++arg != 0; // # statements-all - if (full) // # statements-aux-all - ++arg != 0; // # statements-cond + ++arg != 0; // # statements-all + if (full) // # statements-aux-all + ++arg != 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/10_BitwiseAnd/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/10_BitwiseAnd/src/statements.c index 13aaa9846..be3e9efa9 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/10_BitwiseAnd/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/10_BitwiseAnd/src/statements.c @@ -3,9 +3,9 @@ int run_statements (int full, int arg) { - ++arg & 0; // # statements-all - if (full) // # statements-aux-all - ++arg & 0; // # statements-cond + ++arg & 0; // # statements-all + if (full) // # statements-aux-all + ++arg & 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/11_BitwiseXor/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/11_BitwiseXor/src/statements.c index a53e532fd..61148d5ae 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/11_BitwiseXor/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/11_BitwiseXor/src/statements.c @@ -3,9 +3,9 @@ int run_statements (int full, int arg) { - ++arg ^ 0; // # statements-all - if (full) // # statements-aux-all - ++arg ^ 0; // # statements-cond + ++arg ^ 0; // # statements-all + if (full) // # statements-aux-all + ++arg ^ 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/12_BitwiseOr/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/12_BitwiseOr/src/statements.c index 7a40bc253..1337a6987 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/12_BitwiseOr/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/12_BitwiseOr/src/statements.c @@ -3,9 +3,9 @@ int run_statements (int full, int arg) { - ++arg | 0; // # statements-all - if (full) // # statements-aux-all - ++arg | 0; // # statements-cond + ++arg | 0; // # statements-all + if (full) // # statements-aux-all + ++arg | 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/13_LogicalAnd/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/13_LogicalAnd/src/statements.c index 8e7b743fc..3ba34e146 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/13_LogicalAnd/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/13_LogicalAnd/src/statements.c @@ -3,9 +3,9 @@ int run_statements (int full, int arg) { - ++arg && 0; // # statements-all - if (full) // # statements-aux-all - ++arg && 0; // # statements-cond + ++arg && 0; // # statements-all + if (full) // # statements-aux-all + ++arg && 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/14_LogicalOr/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/14_LogicalOr/src/statements.c index c74c64aa2..f0bace27a 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/14_LogicalOr/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/14_LogicalOr/src/statements.c @@ -3,10 +3,10 @@ int run_statements (int full, int arg) { - ++arg || 0; // # statements-all + ++arg || 0; // # statements-all if (full) // # statements-aux-all ++arg || 0; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/15_Conditional/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/15_Conditional/src/statements.c index bec83fc09..552626a51 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/15_Conditional/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/15_Conditional/src/statements.c @@ -3,13 +3,13 @@ static int incr (int *arg) { - return ++*arg; // # statements-aux-all + return ++*arg; // # statements-aux-all } static int decr (int *arg) { - return --*arg; // # statements-aux-all + return --*arg; // # statements-aux-all } int @@ -17,12 +17,12 @@ run_statements (int full, int arg) { /* Call zero and one so that they are covered iff. statements-aux-all must be covered. */ - incr (&arg); // # statements-aux-all - decr (&arg); // # statements-aux-all + incr (&arg); // # statements-aux-all + decr (&arg); // # statements-aux-all - full ? incr (&arg) : decr (&arg); // # statements-all - if (full) // # statements-aux-all - full ? incr (&arg) : decr (&arg); // # statements-cond + full ? incr (&arg) : decr (&arg); // # statements-all + if (full) // # statements-aux-all + full ? incr (&arg) : decr (&arg); // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/16_Assignment/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/16_Assignment/src/statements.c index 888cb09b5..fc2b28934 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/16_Assignment/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/16_Assignment/src/statements.c @@ -3,31 +3,31 @@ int run_statements (int full, int arg) { - arg = arg + 1; // # statements-all - arg *= 2; // # statements-all - arg /= 1; // # statements-all - arg %= 0xff; // # statements-all - arg += 1; // # statements-all - arg -= 1; // # statements-all - arg <<= 1; // # statements-all - arg >>= 1; // # statements-all - arg &= 0xff; // # statements-all - arg ^= 1; // # statements-all - arg |= 1; // # statements-all - if (full) // # statements-aux-all + arg = arg + 1; // # statements-all + arg *= 2; // # statements-all + arg /= 1; // # statements-all + arg %= 0xff; // # statements-all + arg += 1; // # statements-all + arg -= 1; // # statements-all + arg <<= 1; // # statements-all + arg >>= 1; // # statements-all + arg &= 0xff; // # statements-all + arg ^= 1; // # statements-all + arg |= 1; // # statements-all + if (full) // # statements-aux-all { - arg = arg + 1; // # statements-cond - arg *= 2; // # statements-cond - arg /= 1; // # statements-cond - arg %= 0xff; // # statements-cond - arg += 1; // # statements-cond - arg -= 1; // # statements-cond - arg <<= 1; // # statements-cond - arg >>= 1; // # statements-cond - arg &= 0xff; // # statements-cond - arg ^= 1; // # statements-cond - arg |= 1; // # statements-cond + arg = arg + 1; // # statements-cond + arg *= 2; // # statements-cond + arg /= 1; // # statements-cond + arg %= 0xff; // # statements-cond + arg += 1; // # statements-cond + arg -= 1; // # statements-cond + arg <<= 1; // # statements-cond + arg >>= 1; // # statements-cond + arg &= 0xff; // # statements-cond + arg ^= 1; // # statements-cond + arg |= 1; // # statements-cond } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/17_Comma/src/statements.c b/testsuite/Qualif/C/stmt/Core/05_Expressions/17_Comma/src/statements.c index 169e1ab73..c0a371188 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/17_Comma/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/17_Comma/src/statements.c @@ -7,5 +7,5 @@ run_statements (int full, int arg) if (full) // # statements-aux-all arg -= 1, arg += 2; // # statements-cond - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/src/statements.h b/testsuite/Qualif/C/stmt/Core/05_Expressions/src/statements.h index d3bf61595..128183ee5 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/src/statements.h +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/src/statements.h @@ -1,11 +1,10 @@ #ifndef STATEMENTS_H -# define STATEMENTS_H +#define STATEMENTS_H -/* Execute "statemant-all" and "statement-cond" tagged statements if FULL, or just - "statement-all" ones otherwise. - Auxillary "statement-aux-all" tagged statements are executed if and only if - "statement-all" are executed, and "statement-aux-cond" ones are too iff. - "statement-cond" ones are executed.*/ +/* Execute "statemant-all" and "statement-cond" tagged statements if FULL, or + just "statement-all" ones otherwise. Auxillary "statement-aux-all" tagged + statements are executed if and only if "statement-all" are executed, and + "statement-aux-cond" ones are too iff. "statement-cond" ones are executed.*/ int run_statements (int full, int a); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/Basic/src/statements.c b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/Basic/src/statements.c index 522974ebc..1889a5ab3 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/Basic/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/Basic/src/statements.c @@ -4,25 +4,25 @@ int run_statements (int full, int arg) { { - if (!full) // # statements-aux-all + if (!full) // # statements-aux-all { - --arg; // # statements-not-cond - goto middle; // # statements-not-cond + --arg; // # statements-not-cond + goto middle; // # statements-not-cond } - ++arg; // # statements-cond + ++arg; // # statements-cond } middle: - if (!full) // # statements-aux-all + if (!full) // # statements-aux-all { - --arg; // # statements-not-cond - goto end; // # statements-not-cond + --arg; // # statements-not-cond + goto end; // # statements-not-cond } { - ++arg; // # statements-cond + ++arg; // # statements-cond } end: - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoIn/src/statements.c b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoIn/src/statements.c index e62610d9f..c58640253 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoIn/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoIn/src/statements.c @@ -3,16 +3,16 @@ int run_statements (int full, int arg) { - if (full) // # statements-aux-all + if (full) // # statements-aux-all { goto compound_in; // # statements-cond { - arg = 1; // # statement-non-coverable + arg = 1; // # statement-non-coverable -compound_in: ; - ++arg; // # statements-cond + compound_in:; + ++arg; // # statements-cond } } - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoOut/src/statements.c b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoOut/src/statements.c index 928f6e9d0..6aa236643 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoOut/src/statements.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/GotoOut/src/statements.c @@ -4,15 +4,15 @@ int run_statements (int full, int arg) { { - if (!full) // # statements-aux-all + if (!full) // # statements-aux-all { - ++arg; // # statements-not-cond - goto compound_out; // # statements-not-cond + ++arg; // # statements-not-cond + goto compound_out; // # statements-not-cond } - --arg; // # statements-cond + --arg; // # statements-cond } compound_out: - return arg; // # statements-aux-all + return arg; // # statements-aux-all } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/src/statements.h b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/src/statements.h index 1741ccee3..5bae7a388 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/src/statements.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/02_Compound/src/statements.h @@ -1,11 +1,10 @@ #ifndef STATEMENTS_H -# define STATEMENTS_H +#define STATEMENTS_H -/* Execute "statemant-all" and "statement-cond" tagged statements if FULL, or just - "statement-all" ones otherwise. - Auxillary "statement-aux-all" tagged statements are executed if and only if - "statement-all" are executed, and "statement-aux-cond" ones are too iff. - "statement-cond" ones are executed.*/ +/* Execute "statemant-all" and "statement-cond" tagged statements if FULL, or + just "statement-all" ones otherwise. Auxillary "statement-aux-all" tagged + statements are executed if and only if "statement-all" are executed, and + "statement-aux-cond" ones are too iff. "statement-cond" ones are executed.*/ int run_statements (int full, int arg); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.c b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.c index 301c2e63c..24358ca23 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.c @@ -1,10 +1,11 @@ #include "doif.h" -void doif (int cond, int * xstatus) +void +doif (int cond, int *xstatus) { - *xstatus = 0; // # body - if (cond) // # eval - *xstatus |= XST_IF; // # if + *xstatus = 0; // # body + if (cond) // # eval + *xstatus |= XST_IF; // # if else *xstatus |= XST_ELSE; // # else } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.h b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.h index 466f769bf..e2646062b 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/01_If/src/doif.h @@ -1,4 +1,4 @@ -#define XST_IF (0x1 << 0) +#define XST_IF (0x1 << 0) #define XST_ELSE (0x1 << 1) -void doif (int cond, int * xstatus); +void doif (int cond, int *xstatus); diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.c b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.c index ba1b414c4..7bb259b1a 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.c @@ -1,31 +1,31 @@ #include "doswitch.h" void -doswitch (int input, int * xstatus) +doswitch (int input, int *xstatus) { - *xstatus = 0; // # body + *xstatus = 0; // # body - if (input == 0) // # body + if (input == 0) // # body { - *xstatus &= ~XST_INPUT_WAS_ZERO; // # zero - goto zero; // # zero + *xstatus &= ~XST_INPUT_WAS_ZERO; // # zero + goto zero; // # zero } - switch (input) // # eval + switch (input) // # eval { -zero: - *xstatus |= XST_ZERO; // # zero - break; // # zero + zero: + *xstatus |= XST_ZERO; // # zero + break; // # zero case 1: - *xstatus |= XST_ONE; // # one + *xstatus |= XST_ONE; // # one case 2: - *xstatus |= XST_TWO; // # two - break; // # two + *xstatus |= XST_TWO; // # two + break; // # two default: - *xstatus |= XST_DEFAULT; // # default - break; // # default + *xstatus |= XST_DEFAULT; // # default + break; // # default } } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.h b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.h index 00bc1afc3..1105e0138 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/04_Selection/02_Switch/src/doswitch.h @@ -1,12 +1,12 @@ #ifndef DOSWITCH_H -# define DOSWITCH_H +#define DOSWITCH_H -#define XST_ZERO (0x1 << 0) -#define XST_ONE (0x1 << 1) -#define XST_TWO (0x1 << 2) -#define XST_DEFAULT (0x1 << 3) -#define XST_INPUT_WAS_ZERO (0x1 << 4) +#define XST_ZERO (0x1 << 0) +#define XST_ONE (0x1 << 1) +#define XST_TWO (0x1 << 2) +#define XST_DEFAULT (0x1 << 3) +#define XST_INPUT_WAS_ZERO (0x1 << 4) -void doswitch (int input, int * xstatus); +void doswitch (int input, int *xstatus); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.c index d53a4a18d..ac981e8a0 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.c @@ -3,26 +3,26 @@ int dowhile (int start, int behavior) { - int a = start; // # body + int a = start; // # body - if (behavior & GOTO_IN) // # body + if (behavior & GOTO_IN) // # body { - ++a; // # goto-in - goto in_while; // # goto-in + ++a; // # goto-in + goto in_while; // # goto-in } - while (a < 10) // # eval + while (a < 10) // # eval { - ++a; // # while-eval -in_while: - ++a; // # while-in - if (behavior & GOTO_OUT) // # while-in + ++a; // # while-eval + in_while: + ++a; // # while-in + if (behavior & GOTO_OUT) // # while-in { - ++a; // # goto-out - goto out_while; // # goto-out + ++a; // # goto-out + goto out_while; // # goto-out } } out_while: - return a; // # body + return a; // # body } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.h b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.h index 02dd66b3e..2d8b9d077 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/01_While/src/dowhile.h @@ -1,8 +1,8 @@ #ifndef DOWHILE_H -# define DOWHILE_H +#define DOWHILE_H -# define GOTO_IN (0x01 << 0) -# define GOTO_OUT (0x01 << 1) +#define GOTO_IN (0x01 << 0) +#define GOTO_OUT (0x01 << 1) int dowhile (int start, int behavior); diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.c index c6f04b67a..047d7faad 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.c @@ -3,27 +3,29 @@ int dowhile (int start, int behavior) { - int a = start; // # body + int a = start; // # body - if (behavior & GOTO_IN) // # body + if (behavior & GOTO_IN) // # body { - ++a; // # goto-in - goto in_while; // # goto-in + ++a; // # goto-in + goto in_while; // # goto-in } /* Without the following statement, the goto-in is pointless. */ - ++a; // # pre-while + ++a; // # pre-while - do { -in_while: - ++a; // # while - if (behavior & GOTO_OUT) // # while + do + { + in_while: + ++a; // # while + if (behavior & GOTO_OUT) // # while { - ++a; // # goto-out - goto out_while; // # goto-out + ++a; // # goto-out + goto out_while; // # goto-out } - } while (a < 10); // # eval + } + while (a < 10); // # eval out_while: - return a; // # body + return a; // # body } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.h b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.h index 02dd66b3e..2d8b9d077 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/02_DoWhile/src/dowhile.h @@ -1,8 +1,8 @@ #ifndef DOWHILE_H -# define DOWHILE_H +#define DOWHILE_H -# define GOTO_IN (0x01 << 0) -# define GOTO_OUT (0x01 << 1) +#define GOTO_IN (0x01 << 0) +#define GOTO_OUT (0x01 << 1) int dowhile (int start, int behavior); diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.c b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.c index f424e9649..48c810172 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.c @@ -3,16 +3,16 @@ int dofor (int start, int behavior) { - int a = start; // # body - int i; // # body + int a = start; // # body + int i; // # body - if (behavior & GOTO_IN) // # body + if (behavior & GOTO_IN) // # body { - ++a; // # goto-in - goto in_for; // # goto-in + ++a; // # goto-in + goto in_for; // # goto-in } - --a; // # pre-for + --a; // # pre-for // For binary traces, we will have two coverage obligations here: // - The initialization statement and the test expression @@ -23,16 +23,16 @@ dofor (int start, int behavior) // for the update statement). This means the coverage expectations will be // different. - for (i = start; i < 10; ++i) // # eval + for (i = start; i < 10; ++i) // # eval { -in_for: - if (behavior & GOTO_OUT) // # for + in_for: + if (behavior & GOTO_OUT) // # for { - ++a; // # goto-out - goto out_for; // # goto-out + ++a; // # goto-out + goto out_for; // # goto-out } } out_for: - return a + i; // # return + return a + i; // # return } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.h b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.h index cab3a2162..429095828 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/05_Iteration/03_For/src/dofor.h @@ -1,10 +1,9 @@ #ifndef DOFOR_H -# define DOFOR_H +#define DOFOR_H -#define GOTO_IN (0x01 << 0) -#define GOTO_OUT (0x01 << 1) +#define GOTO_IN (0x01 << 0) +#define GOTO_OUT (0x01 << 1) -int -dofor (int start, int behavior); +int dofor (int start, int behavior); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.c b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.c index 92994493d..54137663f 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.c @@ -3,20 +3,20 @@ int dogoto (int full, int arg) { - if (full != -1) // # body + if (full != -1) // # body { - --arg; // # body - goto test; // # body + --arg; // # body + goto test; // # body } - ++arg; // # unreachable + ++arg; // # unreachable test: - if (full) // # body - { - ++arg; // # cond - goto end; // # cond - } + if (full) // # body + { + ++arg; // # cond + goto end; // # cond + } end: - return arg; // # body + return arg; // # body } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.h b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.h index 302fab915..d02883e51 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/01_Goto/src/dogoto.h @@ -1,7 +1,6 @@ #ifndef DOGOTO_H -# define DOGOTO_H +#define DOGOTO_H -int -dogoto (int full, int arg); +int dogoto (int full, int arg); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.c b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.c index 4d030aa70..54a2e0acf 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.c @@ -5,19 +5,20 @@ docontinue (int limit, int arg) { do { - ++arg; // # while - if (arg > limit) // # while + ++arg; // # while + if (arg > limit) // # while { - arg += 2; // # continue-soft - continue; // # continue-soft + arg += 2; // # continue-soft + continue; // # continue-soft } - if (arg >= 10) // # while + if (arg >= 10) // # while { - arg += 3; // # continue-hard - continue; // # continue-hard + arg += 3; // # continue-hard + continue; // # continue-hard } - ++arg; // # not-continue - } while (0 < arg && arg <= 10); // # eval + ++arg; // # not-continue + } + while (0 < arg && arg <= 10); // # eval - return arg; // # body + return arg; // # body } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.h b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.h index 6636c2121..1f821f649 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/02_Continue/src/docontinue.h @@ -1,7 +1,6 @@ #ifndef DOCONTINUE_H -# define DOCONTINUE_H +#define DOCONTINUE_H -int -docontinue (int limit, int arg); +int docontinue (int limit, int arg); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.c b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.c index 2fd939e66..951a56ce2 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.c @@ -3,22 +3,23 @@ int dobreak (int limit, int arg) { - int loop = 1; // # body + int loop = 1; // # body do { - ++arg; // # while - if (arg > limit) // # while + ++arg; // # while + if (arg > limit) // # while { - --arg; // # break-soft - break; // # break-soft + --arg; // # break-soft + break; // # break-soft } - if (arg > 10) // # while + if (arg > 10) // # while { - --arg; // # break-hard - break; // # break-hard + --arg; // # break-hard + break; // # break-hard } - } while (++loop); // # body + } + while (++loop); // # body - return arg; // # body + return arg; // # body } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.h b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.h index 1de5b4147..d147f1ca2 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/03_Break/src/dobreak.h @@ -1,7 +1,6 @@ #ifndef DOBREAK_H -# define DOBREAK_H +#define DOBREAK_H -int -dobreak (int limit, int arg); +int dobreak (int limit, int arg); #endif diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.c b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.c index a70f1be59..c0b465343 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.c +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.c @@ -3,8 +3,8 @@ int doreturn (int cond) { - if (cond) // # body - return 1; // # cond-true + if (cond) // # body + return 1; // # cond-true else - return 0; // # cond-false + return 0; // # cond-false } diff --git a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.h b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.h index ee8515c0b..bd2193b05 100644 --- a/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.h +++ b/testsuite/Qualif/C/stmt/Core/08_Statements/06_Jump/04_Return/src/doreturn.h @@ -1,5 +1,5 @@ #ifndef DORETURN_H -# define DORETURN_H +#define DORETURN_H int doreturn (int cond); diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.c b/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.c index ec687d9a7..fed3583ef 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.c @@ -7,35 +7,35 @@ sensor_get_status (struct sensor *s) enum sensor_status status; int i; - if (s->history.len == 0) // # SO_t0 - status = SENSOR_UNDECIDABLE; // # SO_undecide + if (s->history.len == 0) // # SO_t0 + status = SENSOR_UNDECIDABLE; // # SO_undecide else { - status = SENSOR_OK; // # SO_decide + status = SENSOR_OK; // # SO_decide - i = 0; // # SO_init - while (i < s->history.len) // # SO_loop + i = 0; // # SO_init + while (i < s->history.len) // # SO_loop { - if (s->history.store[i] < s->lower_bound // # SO_tfaultLB - || s->history.store[i] > s->upper_bound) // # SO_tfaultUB + if (s->history.store[i] < s->lower_bound // # SO_tfaultLB + || s->history.store[i] > s->upper_bound) // # SO_tfaultUB { - switch (status) // # SO_fault + switch (status) // # SO_fault { case SENSOR_OK: - status = SENSOR_CHECK; // # SO_check - break; // # SO_check + status = SENSOR_CHECK; // # SO_check + break; // # SO_check case SENSOR_CHECK: case SENSOR_BROKEN: - status = SENSOR_BROKEN; // # SO_broken - break; // # SO_broken + status = SENSOR_BROKEN; // # SO_broken + break; // # SO_broken default: - assert (false); // # SO_PE - break; // # SO_unreachable + assert (false); // # SO_PE + break; // # SO_unreachable } } - ++i; // # SO_iter + ++i; // # SO_iter } } - return status; // # SO_ret + return status; // # SO_ret } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.h b/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.h index 030d8c773..5e2dc14ad 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/If_For_If_Case/src/sensors_status.h @@ -1,5 +1,5 @@ #ifndef SENSORS_STATUS_H -# define SENSORS_STATUS_H +#define SENSORS_STATUS_H #include "sensors.h" @@ -11,7 +11,6 @@ enum sensor_status SENSOR_BROKEN }; -extern enum sensor_status -sensor_get_status (struct sensor *s); +extern enum sensor_status sensor_get_status (struct sensor *s); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.c index 3f1e86963..77a8ec167 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.c @@ -15,6 +15,5 @@ sensor_pass (struct sensor *s) bool sensor_inrange (struct sensor *s) { - return s->lower_bound <= s->value - && s->value <= s->upper_bound; + return s->lower_bound <= s->value && s->value <= s->upper_bound; } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.h b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.h index 352254b68..5738d5b68 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/sensors_predicates.h @@ -1,17 +1,14 @@ #ifndef SENSORS_PREDICATES_H -# define SENSORS_PREDICATES_H +#define SENSORS_PREDICATES_H -# include "sensors.h" +#include "sensors.h" -extern bool -sensor_nopass (struct sensor *s); +extern bool sensor_nopass (struct sensor *s); -extern bool -sensor_pass (struct sensor *s); +extern bool sensor_pass (struct sensor *s); -extern bool -sensor_inrange (struct sensor *s); +extern bool sensor_inrange (struct sensor *s); -typedef bool (*sensor_predicate)(struct sensor *s); +typedef bool (*sensor_predicate) (struct sensor *s); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.c index fed5d257c..b3c266222 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.c @@ -2,19 +2,18 @@ #include "support.h" void -slist_count_in (struct sensor_list *l, - sensor_predicate p, +slist_count_in (struct sensor_list *l, sensor_predicate p, unsigned *count_true, unsigned *count_false) { - struct sensor_node *node = l->head; // # CO_decl + struct sensor_node *node = l->head; // # CO_decl - *count_true = *count_false = 0; // # CO_init - while (node != NULL) // # CO_while + *count_true = *count_false = 0; // # CO_init + while (node != NULL) // # CO_while { - if (p (node->s)) // # CO_test - ++*count_true; // # CO_incT + if (p (node->s)) // # CO_test + ++*count_true; // # CO_incT else - ++*count_false; // # CO_incF - node = node->next; // # CO_next + ++*count_false; // # CO_incF + node = node->next; // # CO_next } } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.h b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.h index 6c07da74e..533793c24 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If1/src/slists_count.h @@ -1,13 +1,11 @@ #ifndef SLISTS_COUNT_H -# define SLISTS_COUNT_H +#define SLISTS_COUNT_H #include "sensors.h" -#include "slists.h" #include "sensors_predicates.h" +#include "slists.h" -extern void -slist_count_in (struct sensor_list *l, - sensor_predicate p, - unsigned *count_true, unsigned *count_false); +extern void slist_count_in (struct sensor_list *l, sensor_predicate p, + unsigned *count_true, unsigned *count_false); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.c index 9c2eb7088..c47bcdb89 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.c @@ -3,21 +3,20 @@ void slist_control (struct sensor_list *l, bool active_only, - struct sensor_list *skipped, - struct sensor_list *fault, + struct sensor_list *skipped, struct sensor_list *fault, struct sensor_list *ok) { - struct sensor_node *node = l->head; // # AF_init + struct sensor_node *node = l->head; // # AF_init - while (node != NULL) // # AF_while - { - if (active_only && !node->s->active) // # AF_evA - slist_prepend (node->s, skipped); // # AF_skip - else if (node->s->value < node->s->lower_bound // # AF_evLB - || node->s->value > node->s->upper_bound) // # AF_evHB - slist_prepend (node->s, fault); // # AF_fault - else - slist_prepend (node->s, ok); // # AF_ok - node = node->next; // # AF_next - } + while (node != NULL) // # AF_while + { + if (active_only && !node->s->active) // # AF_evA + slist_prepend (node->s, skipped); // # AF_skip + else if (node->s->value < node->s->lower_bound // # AF_evLB + || node->s->value > node->s->upper_bound) // # AF_evHB + slist_prepend (node->s, fault); // # AF_fault + else + slist_prepend (node->s, ok); // # AF_ok + node = node->next; // # AF_next + } } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.h b/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.h index c25f87c15..cc9abb26f 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If4/src/slists_fault.h @@ -1,14 +1,12 @@ #ifndef SLISTS_FAULT -# define SLISTS_FAULT +#define SLISTS_FAULT #include "slists.h" #include -extern void -slist_control (struct sensor_list *s, bool active_only, - struct sensor_list *skipped, - struct sensor_list *fault, - struct sensor_list *ok); +extern void slist_control (struct sensor_list *s, bool active_only, + struct sensor_list *skipped, + struct sensor_list *fault, struct sensor_list *ok); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.c index bed3982ac..2bb86f7e3 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.c @@ -4,22 +4,22 @@ void slist_forall_in (struct sensor_list *l, enum sensor_op op, bool active_only) { - struct sensor_node *node = l->head; // # FA_init + struct sensor_node *node = l->head; // # FA_init - while (node != NULL) // # FA_while + while (node != NULL) // # FA_while { - if (node->s->active || !active_only) // # FA_tactive - switch (op) // # FA_case - { - case SENSOR_ACTIVATE: - node->s->active = true; // # FA_activate - break; // # FA_activate - case SENSOR_INHIBIT: - if (node->s->value < node->s->lower_bound // # FA_tinhibitLB - || node->s->value > node->s->upper_bound) // # FA_tinhibitHB - node->s->active = false; // # FA_do_inhibit - break; // # FA_inhibit_end - } - node = node->next; // # FA_next + if (node->s->active || !active_only) // # FA_tactive + switch (op) // # FA_case + { + case SENSOR_ACTIVATE: + node->s->active = true; // # FA_activate + break; // # FA_activate + case SENSOR_INHIBIT: + if (node->s->value < node->s->lower_bound // # FA_tinhibitLB + || node->s->value > node->s->upper_bound) // # FA_tinhibitHB + node->s->active = false; // # FA_do_inhibit + break; // # FA_inhibit_end + } + node = node->next; // # FA_next } } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.h b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.h index cc5082e25..945c5785b 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/slists_forall.h @@ -1,7 +1,7 @@ #ifndef SLISTS_FORALL_H -# define SLISTS_FORALL_H +#define SLISTS_FORALL_H -# include "slists.h" +#include "slists.h" enum sensor_op { @@ -9,7 +9,7 @@ enum sensor_op SENSOR_INHIBIT }; -extern void -slist_forall_in (struct sensor_list *l, enum sensor_op op, bool active_only); +extern void slist_forall_in (struct sensor_list *l, enum sensor_op op, + bool active_only); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.c index 2d4992f75..ea9c4a0be 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_act_inh.c @@ -10,11 +10,11 @@ main (void) struct sensor_list l; sensor_init (1, 10, &s1); - s1.value = 5; /* in range */ + s1.value = 5; /* in range */ sensor_init (5, 15, &s2); - s2.value = 1; /* < low bound */ + s2.value = 1; /* < low bound */ sensor_init (5, 15, &s3); - s3.value = 45; /* > high bound */ + s3.value = 45; /* > high bound */ slist_init (&l); slist_prepend (&s1, &l); @@ -22,12 +22,12 @@ main (void) slist_prepend (&s3, &l); slist_forall_in (&l, SENSOR_ACTIVATE, false); - assert ( s1.active); - assert ( s2.active); - assert ( s3.active); + assert (s1.active); + assert (s2.active); + assert (s3.active); slist_forall_in (&l, SENSOR_INHIBIT, false); - assert ( s1.active); + assert (s1.active); assert (!s2.active); assert (!s3.active); return 0; diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_activate.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_activate.c index 50bfc0c65..acd4b4ce9 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_activate.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_activate.c @@ -21,8 +21,8 @@ main (void) assert (!s2.active); slist_forall_in (&l, SENSOR_ACTIVATE, false); - assert ( s1.active); - assert ( s2.active); + assert (s1.active); + assert (s2.active); return 0; } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.c b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.c index 0a823078f..a53861472 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/While_If_Case_If/src/test_inhibit.c @@ -10,13 +10,13 @@ main (void) struct sensor_list l; sensor_init (1, 10, &s1); - s1.value = 5; /* in range */ + s1.value = 5; /* in range */ s1.active = true; sensor_init (5, 15, &s2); - s2.value = 1; /* < low bound */ + s2.value = 1; /* < low bound */ s2.active = true; sensor_init (5, 15, &s3); - s3.value = 45; /* > high bound */ + s3.value = 45; /* > high bound */ s3.active = true; slist_init (&l); @@ -25,7 +25,7 @@ main (void) slist_prepend (&s3, &l); slist_forall_in (&l, SENSOR_INHIBIT, false); - assert ( s1.active); + assert (s1.active); assert (!s2.active); assert (!s3.active); return 0; diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/src/sensors.h b/testsuite/Qualif/C/stmt/MixedConstructs/src/sensors.h index 2c3aca3c8..9c60f6e88 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/src/sensors.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/src/sensors.h @@ -1,9 +1,9 @@ #ifndef SENSORS_H -# define SENSORS_H +#define SENSORS_H -# include "vbufs.h" +#include "vbufs.h" -# include +#include struct sensor { @@ -14,11 +14,9 @@ struct sensor struct vbuffer history; }; -extern void -sensor_init (int lower_bound, int upper_bound, struct sensor *s); +extern void sensor_init (int lower_bound, int upper_bound, struct sensor *s); /* Latch current sensor value for S in its history buffer. */ -extern void -sensor_sample (struct sensor *s); +extern void sensor_sample (struct sensor *s); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/src/simple_pools.h b/testsuite/Qualif/C/stmt/MixedConstructs/src/simple_pools.h index 0c524bee8..adc477ebd 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/src/simple_pools.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/src/simple_pools.h @@ -1,9 +1,8 @@ #ifndef SIMPLE_POOLS_H -# define SIMPLE_POOLS_H +#define SIMPLE_POOLS_H -# include "slists.h" +#include "slists.h" -extern struct sensor_node * -pool_allocate (void); +extern struct sensor_node *pool_allocate (void); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.c b/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.c index 1474da99e..6caa1d80f 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.c @@ -12,7 +12,7 @@ slist_init (struct sensor_list *l) void slist_prepend (struct sensor *s, struct sensor_list *l) { - struct sensor_node * const node = pool_allocate (); + struct sensor_node *const node = pool_allocate (); node->s = s; node->next = l->head; l->head = node; diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.h b/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.h index 336f40d1e..66895103e 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/src/slists.h @@ -1,8 +1,8 @@ #ifndef SLISTS_H -# define SLISTS_H +#define SLISTS_H -# include "vbufs.h" -# include "sensors.h" +#include "sensors.h" +#include "vbufs.h" struct sensor_node; @@ -18,10 +18,8 @@ struct sensor_list unsigned len; }; -extern void -slist_init (struct sensor_list *l); +extern void slist_init (struct sensor_list *l); -extern void -slist_prepend (struct sensor *s, struct sensor_list *l); +extern void slist_prepend (struct sensor *s, struct sensor_list *l); #endif diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.c b/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.c index e07355d54..713fa1dab 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.c +++ b/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.c @@ -14,11 +14,12 @@ vbuffer_push (int value, struct vbuffer *vbuf) /* Shift right, insert at first position the given VALUE and adjust length. */ - for (i = vbuf->size - 1; i > 0; --i) // # PU_loop0 + for (i = vbuf->size - 1; i > 0; --i) // # PU_loop0 { - if (i < vbuf->size - 1) // # PU_tshift - vbuf->store[i] = vbuf->store[i - 1]; // # PU_shift + if (i < vbuf->size - 1) // # PU_tshift + vbuf->store[i] = vbuf->store[i - 1]; // # PU_shift } - vbuf->store[0] = value; // # PU_update - vbuf->len = (vbuf->len < vbuf->size) ? (vbuf->len + 1) : vbuf->len; // # PU_update + vbuf->store[0] = value; // # PU_update + vbuf->len + = (vbuf->len < vbuf->size) ? (vbuf->len + 1) : vbuf->len; // # PU_update } diff --git a/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.h b/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.h index 3ffb9e2e3..396da43bf 100644 --- a/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.h +++ b/testsuite/Qualif/C/stmt/MixedConstructs/src/vbufs.h @@ -1,7 +1,7 @@ #ifndef VBUFS_H -# define VBUFS_H +#define VBUFS_H -# define HIST_SIZE 10 +#define HIST_SIZE 10 struct vbuffer { @@ -10,10 +10,8 @@ struct vbuffer unsigned len; /* Number of filled entries. */ }; -extern void -vbuffer_init (struct vbuffer *vbuf); +extern void vbuffer_init (struct vbuffer *vbuf); -extern void -vbuffer_push (int value, struct vbuffer *vbuf); +extern void vbuffer_push (int value, struct vbuffer *vbuf); #endif diff --git a/testsuite/tests/104-pragma-directives/src/test_pragma.c b/testsuite/tests/104-pragma-directives/src/test_pragma.c index 148fde6a9..7cf24fd60 100644 --- a/testsuite/tests/104-pragma-directives/src/test_pragma.c +++ b/testsuite/tests/104-pragma-directives/src/test_pragma.c @@ -1,6 +1,6 @@ -#define DISABLE_WARNINGS \ - _Pragma ("GCC diagnostic push") \ - _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") +#define DISABLE_WARNINGS \ + _Pragma ("GCC diagnostic push") \ + _Pragma ("GCC diagnostic ignored \"-Wimplicit-fallthrough\"") DISABLE_WARNINGS diff --git a/testsuite/tests/106-externally-built-header/main/main.c b/testsuite/tests/106-externally-built-header/main/main.c index 1eff0311b..644ed33e9 100644 --- a/testsuite/tests/106-externally-built-header/main/main.c +++ b/testsuite/tests/106-externally-built-header/main/main.c @@ -1,8 +1,8 @@ #include "mylib.h" int -main() +main () { - foo(); - return 0; + foo (); + return 0; } diff --git a/testsuite/tests/106-externally-built-header/mylib/mylib.c b/testsuite/tests/106-externally-built-header/mylib/mylib.c index c0d2890e2..8f8b1830b 100644 --- a/testsuite/tests/106-externally-built-header/mylib/mylib.c +++ b/testsuite/tests/106-externally-built-header/mylib/mylib.c @@ -1,5 +1,5 @@ int -foo() +foo () { return 0; } diff --git a/testsuite/tests/106-externally-built-header/mylib/mylib.h b/testsuite/tests/106-externally-built-header/mylib/mylib.h index cf790ac3e..f8f1dde0b 100644 --- a/testsuite/tests/106-externally-built-header/mylib/mylib.h +++ b/testsuite/tests/106-externally-built-header/mylib/mylib.h @@ -1 +1 @@ -extern int foo(); +extern int foo (); diff --git a/testsuite/tests/129-instr-progress/cpp_unit.cpp b/testsuite/tests/129-instr-progress/cpp_unit.cpp index bbe5360ff..32833a39b 100644 --- a/testsuite/tests/129-instr-progress/cpp_unit.cpp +++ b/testsuite/tests/129-instr-progress/cpp_unit.cpp @@ -1,6 +1,7 @@ #include -extern "C" { +extern "C" +{ extern void cpp_func (void); } diff --git a/testsuite/tests/129-instr-progress/test.py b/testsuite/tests/129-instr-progress/test.py index 9698163c6..2da846687 100644 --- a/testsuite/tests/129-instr-progress/test.py +++ b/testsuite/tests/129-instr-progress/test.py @@ -41,7 +41,7 @@ { "main.adb.xcov": {"+": {7, 8}}, "c_unit.c.xcov": {"+": {8}}, - "cpp_unit.cpp.xcov": {"+": {10}}, + "cpp_unit.cpp.xcov": {"+": {11}}, }, ) diff --git a/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp index 8ec878d79..8cc5c4037 100644 --- a/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp +++ b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp @@ -16,22 +16,22 @@ tryme (bool aa, bool bb, bool skip) } // A lambda function in a for statement - int i = 0; // # other - for (; i++ < 1;) // # other - [] (int aa, int bb) { // # other - if (aa > 0 && bb > 0) // # eval :o/d: - return true; // # lambda_true - else // # lambda_other - return false; // # lambda_false - } (aa, bb); // # lambda_other + int i = 0; // # other + for (; i++ < 1;) // # other + [] (int aa, int bb) { // # other + if (aa > 0 && bb > 0) // # eval :o/d: + return true; // # lambda_true + else // # lambda_other + return false; // # lambda_false + }(aa, bb); // # lambda_other // A nested lambda - [] (int aa, int bb) { // # other - [] (int aa, int bb) { // # other - if (aa > 0 && bb > 0) // # eval :o/d: - return true; // # lambda_true - else // # lambda_other - return false; // # lambda_false - } (aa, bb); // # lambda_other - } (aa, bb); // # lambda_other + [] (int aa, int bb) { // # other + [] (int aa, int bb) { // # other + if (aa > 0 && bb > 0) // # eval :o/d: + return true; // # lambda_true + else // # lambda_other + return false; // # lambda_false + }(aa, bb); // # lambda_other + }(aa, bb); // # lambda_other } diff --git a/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp b/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp index 0d670ddf7..9ed547eba 100644 --- a/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp +++ b/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp @@ -12,7 +12,8 @@ foo () } int -main(){ +main () +{ constexpr bool a = true || false; // # single-ce-decl constexpr bool b = true || false, c = true || false; // # double-ce-decl if constexpr (false) // # if-ce diff --git a/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/src/test_for_range.cpp b/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/src/test_for_range.cpp index 736210b0c..f8b695b0d 100644 --- a/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/src/test_for_range.cpp +++ b/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/src/test_for_range.cpp @@ -6,7 +6,7 @@ main (void) int sum = 0; // # init for (auto i : { 1, 2, 3 }) // # for-range { - sum += i; // # for-body + sum += i; // # for-body } return 0; } diff --git a/testsuite/tests/C++/stmt/StructMemberFun/src/test_struct.cpp b/testsuite/tests/C++/stmt/StructMemberFun/src/test_struct.cpp index b59865918..7fb9f95de 100644 --- a/testsuite/tests/C++/stmt/StructMemberFun/src/test_struct.cpp +++ b/testsuite/tests/C++/stmt/StructMemberFun/src/test_struct.cpp @@ -1,5 +1,8 @@ -struct Foo { - void bar (){ +struct Foo +{ + void + bar () + { return; // # member-fun } }; @@ -8,7 +11,7 @@ int main (void) { struct Foo foo; // # decl - foo.bar(); // # call + foo.bar (); // # call return 0; // # return } diff --git a/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c b/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c index 8472ba606..12a105014 100644 --- a/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c +++ b/testsuite/tests/C/mcdc/Exemptions/Invalid/main.c @@ -13,9 +13,9 @@ int main (void) { return - /* GNATCOV_EXEMPT_ON "In statement"*/ - fact (0) == 1 - /* GNATCOV_EXEMPT_OFF)*/ - ? 0 - : 1; + /* GNATCOV_EXEMPT_ON "In statement"*/ + fact (0) == 1 + /* GNATCOV_EXEMPT_OFF)*/ + ? 0 + : 1; } diff --git a/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.c b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.c index af887905c..79b73498a 100644 --- a/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.c +++ b/testsuite/tests/C/mcdc/Exemptions/Nominal/src/pkg.c @@ -15,8 +15,8 @@ bool orElse (bool a, bool b) { // GNATCOV_EXEMPT_ON "if stmt" // # exempt_oe - if (a || b) // # exempt_oe_v1 - { // # exempt_oe + if (a || b) // # exempt_oe_v1 + { // # exempt_oe // GNATCOV_EXEMPT_OFF // # exempt_oe return true; } @@ -30,6 +30,6 @@ bool negation (bool a) { /* GNATCOV_EXEMPT_ON "single statement, multiline comment"*/ // # exempt_neg - return NOT (a); // # exempt_neg_v1 - /* GNATCOV_EXEMPT_OFF */ // # exempt_neg + return NOT (a); // # exempt_neg_v1 + /* GNATCOV_EXEMPT_OFF */ // # exempt_neg } diff --git a/testsuite/tests/HomonymSymbols/src/support.h b/testsuite/tests/HomonymSymbols/src/support.h index 89c7b234c..6b0c268fc 100644 --- a/testsuite/tests/HomonymSymbols/src/support.h +++ b/testsuite/tests/HomonymSymbols/src/support.h @@ -1,6 +1,6 @@ #ifndef SUPPORT_H #define SUPPORT_H -extern int identity (int n); /* from libsupport. */ +extern int identity (int n); /* from libsupport. */ #endif diff --git a/testsuite/tests/header_not_found/base_foo/support.h b/testsuite/tests/header_not_found/base_foo/support.h index e05eb7e69..8f8b1830b 100644 --- a/testsuite/tests/header_not_found/base_foo/support.h +++ b/testsuite/tests/header_not_found/base_foo/support.h @@ -1,4 +1,5 @@ -int foo() +int +foo () { return 0; } diff --git a/testsuite/tests/header_not_found/include_base_foo/test.c b/testsuite/tests/header_not_found/include_base_foo/test.c index 5991bc01c..fb779d605 100644 --- a/testsuite/tests/header_not_found/include_base_foo/test.c +++ b/testsuite/tests/header_not_found/include_base_foo/test.c @@ -1,6 +1,7 @@ #include "support.h" -int main() +int +main () { - return foo(); + return foo (); } diff --git a/testsuite/tests/header_not_found/include_foo/headers/support.h b/testsuite/tests/header_not_found/include_foo/headers/support.h index 85471f974..1d4a1ab35 100644 --- a/testsuite/tests/header_not_found/include_foo/headers/support.h +++ b/testsuite/tests/header_not_found/include_foo/headers/support.h @@ -1,4 +1,5 @@ -int foo() +int +foo () { // Dummy comment to make this header different from its version in the // extended project. diff --git a/testsuite/tests/header_not_found/include_foo/test.c b/testsuite/tests/header_not_found/include_foo/test.c index 5991bc01c..fb779d605 100644 --- a/testsuite/tests/header_not_found/include_foo/test.c +++ b/testsuite/tests/header_not_found/include_foo/test.c @@ -1,6 +1,7 @@ #include "support.h" -int main() +int +main () { - return foo(); + return foo (); } diff --git a/testsuite/tests/header_not_found/test.py b/testsuite/tests/header_not_found/test.py index 836fdad39..ba3332928 100644 --- a/testsuite/tests/header_not_found/test.py +++ b/testsuite/tests/header_not_found/test.py @@ -30,16 +30,16 @@ def process(gpr_dir, expected_cov): # Check that the header in the extended project is picked by gnatcov instrument # when there is no version in the extending project. expected_cov = { - "test.c.xcov": {"+": {5}}, - "support.h.xcov": {"+": {3}}, + "test.c.xcov": {"+": {6}}, + "support.h.xcov": {"+": {4}}, } process(os.path.join("..", "include_base_foo"), expected_cov) # If there is a version of the header in the extending project, check that this # is the one picked. expected_cov = { - "test.c.xcov": {"+": {5}}, - "support.h.xcov": {"+": {5}}, + "test.c.xcov": {"+": {6}}, + "support.h.xcov": {"+": {6}}, } process(os.path.join("..", "include_foo"), expected_cov) diff --git a/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.cpp b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.cpp index f5cf1b26d..37ae56af3 100644 --- a/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.cpp +++ b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/pkg.cpp @@ -4,8 +4,8 @@ int overly_complex_fact (int n) { return n ? n * // # top_level - [] (int m) { - return m > 1 ? overly_complex_fact (m) : 1; // # lambda - }(n - 1) - : 1; + [] (int m) { + return m > 1 ? overly_complex_fact (m) : 1; // # lambda + }(n - 1) + : 1; } diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/main.c b/testsuite/tests/instr-cov/c_multiline_stmt/main.c index 260024cfb..b44ee29eb 100644 --- a/testsuite/tests/instr-cov/c_multiline_stmt/main.c +++ b/testsuite/tests/instr-cov/c_multiline_stmt/main.c @@ -15,8 +15,8 @@ main () // while. do x++ - // dumb-token - ; + // dumb-token + ; while (x < 2); // Check nested if-else statements. For each un-braced control flow stmt, @@ -26,10 +26,10 @@ main () if (id (x) != x) for (i = 0; i++; i < 10) return 0 - // dumb-token - ; - else if (foo ()) - return 0 // dumb-token ; + else if (foo ()) + return 0 + // dumb-token + ; } diff --git a/tools/gnatcov/bfd_helpers.c b/tools/gnatcov/bfd_helpers.c index b306723e8..980e56099 100644 --- a/tools/gnatcov/bfd_helpers.c +++ b/tools/gnatcov/bfd_helpers.c @@ -27,10 +27,10 @@ do \ { \ if (!(expr)) \ - { \ - (*warn_cb) (call " failed", bfd_errmsg (bfd_get_error ())); \ - return; \ - } \ + { \ + (*warn_cb) (call " failed", bfd_errmsg (bfd_get_error ())); \ + return; \ + } \ } \ while (0) @@ -68,8 +68,8 @@ _gnatcov_for_each_synthetic_symbol ( return; synth_count = bfd_get_synthetic_symtab (abfd, /*static_count*/ 0, - /*static_syms*/ NULL, dyn_count, - dyn_syms, &synthsyms); + /*static_syms*/ NULL, dyn_count, + dyn_syms, &synthsyms); /* Note: synth_count is either -1 or >0, never 0. There is no way distinguish an error condition from the mere absence of synthetic diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 12e4f2d94..bcad36f8e 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -492,7 +492,8 @@ clang_getCalleeName (CXCursor C) switch (D->getKind ()) { case Decl::FunctionTemplate: - return getFunctionDeclName ((cast (D))->getTemplatedDecl ()); + return getFunctionDeclName ( + (cast (D))->getTemplatedDecl ()); case Decl::Function: case Decl::CXXMethod: case Decl::CXXConstructor: diff --git a/tools/gnatcov/examples/support/src/leon-elf/abort.c b/tools/gnatcov/examples/support/src/leon-elf/abort.c index 786ae5ee1..fd26e0f21 100644 --- a/tools/gnatcov/examples/support/src/leon-elf/abort.c +++ b/tools/gnatcov/examples/support/src/leon-elf/abort.c @@ -20,7 +20,8 @@ /* Our local last chance handlers for Ada rely on "abort", and this is not part of the standard RTS on leon. */ -void abort (void) +void +abort (void) { - asm ("mov 0, %g1; ta 0"); + asm("mov 0, %g1; ta 0"); } diff --git a/tools/gnatcov/libopcodes_bind/dis_stream.c b/tools/gnatcov/libopcodes_bind/dis_stream.c index ab4e8fbff..c4782f7b3 100644 --- a/tools/gnatcov/libopcodes_bind/dis_stream.c +++ b/tools/gnatcov/libopcodes_bind/dis_stream.c @@ -63,8 +63,8 @@ stream_printf (disassembler_stream *ds, const char *format, ...) desired. */ int stream_styled_printf (disassembler_stream *ds, - enum disassembler_style style ATTRIBUTE_UNUSED, - const char *format, ...) + enum disassembler_style style ATTRIBUTE_UNUSED, + const char *format, ...) { va_list ap; int res; diff --git a/tools/gnatcov/libopcodes_bind/dis_stream.h b/tools/gnatcov/libopcodes_bind/dis_stream.h index cbbf716f6..e867312fd 100644 --- a/tools/gnatcov/libopcodes_bind/dis_stream.h +++ b/tools/gnatcov/libopcodes_bind/dis_stream.h @@ -37,14 +37,14 @@ extern void delete_stream (disassembler_stream *const ds); extern int stream_printf (disassembler_stream *ptr, const char *format, ...); extern int stream_styled_printf (disassembler_stream *ptr, - enum disassembler_style style, - const char *format, ...); + enum disassembler_style style, + const char *format, ...); extern void clear_stream (disassembler_stream *const ds); extern unsigned char stream_is_empty (disassembler_stream *const ds); extern void set_stream_buffer (disassembler_stream *const ds, char *const buff, - int size); + int size); #endif /* !DIS_STREAM_H_ */ diff --git a/tools/gnatcov/libopcodes_bind/dis_wrapper.c b/tools/gnatcov/libopcodes_bind/dis_wrapper.c index 679e4e14d..bf2e14417 100644 --- a/tools/gnatcov/libopcodes_bind/dis_wrapper.c +++ b/tools/gnatcov/libopcodes_bind/dis_wrapper.c @@ -100,7 +100,7 @@ _create_base_disassembler (enum bfd_architecture arch, const char *options) } init_disassemble_info (&(dh->dinfo), ds, (fprintf_ftype) stream_printf, - (fprintf_styled_ftype) stream_styled_printf); + (fprintf_styled_ftype) stream_styled_printf); dh->dinfo.arch = arch; if (options) { @@ -141,7 +141,7 @@ _create_arm_arch_disassembler (unsigned char for_thumb) represented by DH. */ void set_disassembler_symbolizer (disassemble_handle *const dh, - void *const symbolizer, print_symbol_cb addr_cb) + void *const symbolizer, print_symbol_cb addr_cb) { symbolizer_data *sym_data = dh->dinfo.application_data; @@ -247,9 +247,9 @@ delete_disassembler (disassemble_handle *const dh) Returns the size of the disassembled instruction. */ int disassemble_to_text (disassemble_handle *const dh, bfd_vma pc, - char *const dest, unsigned int dest_size, - bfd_byte *const insn_buffer, unsigned int ib_size, - enum bfd_endian endian) + char *const dest, unsigned int dest_size, + bfd_byte *const insn_buffer, unsigned int ib_size, + enum bfd_endian endian) { int size; diff --git a/tools/gnatcov/libopcodes_bind/dis_wrapper.h b/tools/gnatcov/libopcodes_bind/dis_wrapper.h index bef08363d..cb4c12202 100644 --- a/tools/gnatcov/libopcodes_bind/dis_wrapper.h +++ b/tools/gnatcov/libopcodes_bind/dis_wrapper.h @@ -32,7 +32,7 @@ typedef struct disassemble_handle disassemble_handle; /* Functions of this type can write at most BUFF_SIZE bytes. */ typedef int (*print_symbol_cb) (bfd_vma addr, void *symbolizer, - char *const buff, int buff_size); + char *const buff, int buff_size); extern disassemble_handle *create_arm_disassembler (void); @@ -47,12 +47,12 @@ extern disassemble_handle *create_aarch64_disassembler (void); extern void delete_disassembler (disassemble_handle *const dh); extern int disassemble_to_text (disassemble_handle *const dh, bfd_vma pc, - char *const dest, unsigned int dest_size, - bfd_byte *const insn_buffer, - unsigned int ib_size, enum bfd_endian endian); + char *const dest, unsigned int dest_size, + bfd_byte *const insn_buffer, + unsigned int ib_size, enum bfd_endian endian); extern void set_disassembler_symbolizer (disassemble_handle *const dh, - void *const symbolizer, - print_symbol_cb addr_cb); + void *const symbolizer, + print_symbol_cb addr_cb); #endif /* !DIS_WRAPPER_H_ */ diff --git a/tools/gnatcov/zlib_helpers.c b/tools/gnatcov/zlib_helpers.c index 2a651f71b..a777ca4d9 100644 --- a/tools/gnatcov/zlib_helpers.c +++ b/tools/gnatcov/zlib_helpers.c @@ -27,7 +27,7 @@ decompression was successful. */ int gnatcov_zlib_uncompress (char *in_buffer, uint64_t in_size, char *out_buffer, - uint64_t out_size) + uint64_t out_size) { z_stream strm; @@ -40,5 +40,5 @@ gnatcov_zlib_uncompress (char *in_buffer, uint64_t in_size, char *out_buffer, /* Uncompress and then check that uncompressed data consumed exactly OUT_SIZE bytes. */ return (inflateInit (&strm) == Z_OK && inflate (&strm, Z_FINISH) == Z_OK - && inflateEnd (&strm) == Z_OK && strm.avail_out == 0); + && inflateEnd (&strm) == Z_OK && strm.avail_out == 0); } From 29e00c651a41a96a3c35a02dbb121ab0ea0ae017 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 26 Feb 2024 08:19:29 +0100 Subject: [PATCH 0732/1483] Run black on all Python sources --- .check-formatting.py | 11 +- doc/conf.py | 46 +- doc/gnatcov/gen_prjtrees.py | 21 +- qualification/genbundle.py | 946 ++++++++++-------- qualification/qm/common_conf.py | 87 +- qualification/qm/env/env.py | 12 +- qualification/qm/genmodel.py | 164 +-- qualification/qm/plans/qmconf.py | 13 +- qualification/qm/qm_plugins/generate_doc.py | 27 +- qualification/qm/qm_plugins/importers.py | 702 +++++++------ qualification/qm/qm_plugins/link_lrm.py | 7 +- .../qm/qm_plugins/lrm_index_parser.py | 13 +- qualification/qm/qm_prolog.py | 118 ++- .../qm/scripts/generate_plans_html.py | 2 +- .../qm/scripts/generate_plans_pdf.py | 2 +- qualification/qm/scripts/generate_tor_html.py | 2 +- qualification/qm/scripts/generate_tor_pdf.py | 2 +- testsuite/OCOV/__init__.py | 4 +- testsuite/OCOV/tc.py | 104 +- .../Default_UnitInstances/test.py | 4 +- .../Variants_ByConstruct/test.py | 3 +- .../Variants_BySubprogram/test.py | 3 +- .../Ada/stmt/Robustness/No_Elab_InLib/test.py | 14 +- .../Testsuite/Selftest/assert-failure/test.py | 8 +- .../Selftest/expected-scv-notfound/test.py | 9 +- .../Selftest/unexpected-scv-implicit/test.py | 12 +- .../Selftest/unexpected-scv-r0/test.py | 6 +- .../GprFacilities/ConfigAttr/Target/test.py | 62 +- .../GnatcovSwitches/CmdLinePrevails/test.py | 68 +- .../GnatcovSwitches/Commands/test.py | 120 ++- .../GnatcovSwitches/InSubproject/test.py | 45 +- .../GprFacilities/MainAttr/MultiMain/test.py | 44 +- .../GprFacilities/MainAttr/SingleMain/test.py | 29 +- .../GprFacilities/MainAttr/ZeroMain/test.py | 35 +- .../Subdirs/BuildRunAnalyze/test.py | 27 +- .../GPR/ByAttr/GlobInList/test.py | 11 +- .../UnitsOfInterest/GPR/ByAttr/ListIn/test.py | 22 +- .../UnitsOfInterest/GPR/ByAttr/MixIn/test.py | 11 +- .../GPR/ByAttr/MixInOut/test.py | 18 +- .../GPR/ByAttr/UnitsIn/test.py | 30 +- .../GPR/ByAttr/UnitsInOut/test.py | 35 +- .../GPR/ByCmdLine/DefaultClosure/test.py | 19 +- .../GPR/ByCmdLine/ProjectClosures/test.py | 19 +- .../GPR/ByCmdLine/ProjectSets/test.py | 28 +- .../GPR/ByCmdLine/ProjectsAndUnits/test.py | 48 +- .../GPR/ByCmdLine/UnitsOverrides/test.py | 19 +- .../GPR/ByCmdLine/test_support.py | 47 +- .../GPR/ExtendedGprs/AttrOverride/test.py | 26 +- .../GPR/ExtendedGprs/ExtendedHasMain/test.py | 34 +- .../GPR/ExtendedGprs/PartialOverride/test.py | 35 +- .../GPR/GprsOfInterest/test.py | 172 ++-- .../UnitsOfInterest/GPR/InnerAttr/test.py | 27 +- .../GPR/Robustness/BadUnitInAttr/test.py | 36 +- .../GPR/Robustness/BadUnitInSwitch/test.py | 41 +- .../GPR/Robustness/MissingLI/test.py | 30 +- .../GPR/Robustness/NoContribPrj/test.py | 211 ++-- .../GPR/Robustness/NoUnit/test.py | 45 +- .../GPR/Robustness/SourcesAttr/test.py | 44 +- .../GPR/Robustness/UnitNotInProjects/test.py | 64 +- .../UnitsOfInterest/SCOS/MultiGpr/test.py | 19 +- .../UnitsOfInterest/SCOS/SingleGpr/test.py | 17 +- .../UnitsOfInterest/SCOS/test_support.py | 61 +- testsuite/Qualif/qmconf.py | 19 +- testsuite/REST/rest.py | 49 +- testsuite/SCOV/expgen/__init__.py | 4 +- testsuite/SCOV/expgen/ast.py | 77 +- testsuite/SCOV/expgen/context.py | 51 +- testsuite/SCOV/expgen/generator/__init__.py | 4 +- .../SCOV/expgen/generator/composition.py | 7 +- testsuite/SCOV/expgen/generator/engine.py | 99 +- testsuite/SCOV/expgen/generator/errors.py | 16 +- testsuite/SCOV/expgen/generator/parsing.py | 79 +- testsuite/SCOV/expgen/generator/utils.py | 6 +- testsuite/SCOV/expgen/language/__init__.py | 63 +- .../SCOV/expgen/language/ada/__init__.py | 228 +++-- testsuite/SCOV/expgen/language/ada/context.py | 93 +- testsuite/SCOV/expgen/language/ada/operand.py | 142 +-- testsuite/SCOV/expgen/language/c/__init__.py | 218 ++-- testsuite/SCOV/expgen/language/c/context.py | 7 +- testsuite/SCOV/expgen/language/c/operand.py | 36 +- testsuite/SCOV/expgen/operand.py | 40 +- testsuite/SCOV/expgen/topology.py | 21 +- testsuite/SCOV/expgen/utils.py | 46 +- testsuite/SCOV/htc.py | 21 +- testsuite/SCOV/instr.py | 145 ++- testsuite/SCOV/internals/cnotes.py | 193 +++- testsuite/SCOV/internals/driver.py | 334 ++++--- testsuite/SCOV/internals/lnexpanders.py | 46 +- testsuite/SCOV/internals/rnexpanders.py | 293 ++++-- testsuite/SCOV/internals/segments.py | 75 +- testsuite/SCOV/internals/stags.py | 21 +- testsuite/SCOV/internals/tfiles.py | 1 + testsuite/SCOV/internals/xnexpanders.py | 324 +++--- testsuite/SCOV/internals/xnotep.py | 206 ++-- testsuite/SCOV/map.py | 61 +- testsuite/SCOV/minicheck.py | 299 +++--- testsuite/SCOV/report.py | 135 ++- testsuite/SCOV/tc.py | 134 ++- testsuite/SCOV/tctl.py | 49 +- testsuite/STR/conf.py | 135 +-- testsuite/STR/genrest.py | 688 +++++++------ testsuite/SUITE/context.py | 138 +-- testsuite/SUITE/control.py | 322 +++--- testsuite/SUITE/cutils.py | 63 +- testsuite/SUITE/dutils.py | 24 +- testsuite/SUITE/gprutils.py | 126 +-- testsuite/SUITE/qdata.py | 68 +- testsuite/SUITE/srctracelib.py | 315 +++--- testsuite/SUITE/stream_decoder.py | 55 +- testsuite/SUITE/tgen.py | 62 +- testsuite/SUITE/tracelib.py | 145 +-- testsuite/SUITE/tutils.py | 432 +++++--- testsuite/altrun/ccg_native/cgprbuild.py | 15 +- testsuite/altrun/ccg_native/pre_testsuite.py | 12 +- testsuite/altrun/example/crun.py | 30 +- testsuite/altrun/example/setup.py | 6 +- testsuite/altrun/trace32/crun.py | 68 +- testsuite/altrun/trace32/pre_testsuite.py | 28 +- testsuite/altrun/trace32/t32api.py | 122 ++- testsuite/nexus_info.py | 21 +- .../tests/106-externally-built-header/test.py | 4 +- .../tests/127-check-line-endings/test.py | 15 +- testsuite/tests/129-instr-progress/test.py | 20 +- .../138-ada-preprocessing/example/test.py | 33 +- .../138-ada-preprocessing/prep_data/test.py | 1 + .../14-unused-separate/compilable/test.py | 7 +- .../14-unused-separate/uncompilable/test.py | 7 +- testsuite/tests/15-non-instr-cons/test.py | 5 +- testsuite/tests/152-shared_setup/test.py | 2 +- testsuite/tests/16-check-html/test.py | 6 +- testsuite/tests/207-srctrace-version/test.py | 10 +- testsuite/tests/222-scope-expr-func/test.py | 5 +- testsuite/tests/24_mixed_c_c++/test.py | 3 +- testsuite/tests/92-long_slugs/test.py | 6 +- .../Ada/decision/K303_016-exwhen-abs/test.py | 9 +- .../Ada/stmt/PC20-011-EmptyUnit_InLib/test.py | 6 +- .../tests/C/mcdc/Exemptions/Invalid/test.py | 7 +- testsuite/tests/C/mcdc/Macros/test.py | 13 +- .../tests/C/mcdc/include-current-dir/test.py | 16 +- .../C/stmt/NA28-015-default-return/test.py | 59 +- testsuite/tests/Disassemblers/disaconv.py | 39 +- testsuite/tests/Disassemblers/test.py | 70 +- .../tests/Generics/Mode_Variants_MCDC/test.py | 8 +- .../tests/Generics/Mode_Variants_STMT/test.py | 8 +- .../ObjectCoverage/DifferentOptions/test.py | 19 +- .../With_Debug/Not-Fact/test.py | 15 +- .../ObjectCoverage/With_Debug/Not-Not/test.py | 12 +- .../NotDebug-NotDebug-NotNoDebug/test.py | 15 +- .../Without_Debug/NotDebug-NotNoDebug/test.py | 13 +- .../NotNoDebug-FactNoDebug/test.py | 13 +- .../NotNoDebug-NotNoDebug/test.py | 13 +- .../SourceCoverage/DifferentOptions/test.py | 31 +- .../SourceCoverage/FunctionSections/test.py | 2 +- testsuite/tests/I401-009/test.py | 28 +- testsuite/tests/I427-029/test.py | 105 +- testsuite/tests/I505-018/test.py | 30 +- .../tests/I511-019-response-files/test.py | 29 +- testsuite/tests/I512-020/test.py | 2 +- testsuite/tests/I519-015/test.py | 66 +- testsuite/tests/I519-030/test.py | 95 +- testsuite/tests/I522-010/test.py | 14 +- testsuite/tests/I715-012/test.py | 43 +- testsuite/tests/I716-009/test.py | 42 +- testsuite/tests/I716-021/test.py | 23 +- testsuite/tests/I717-018/test.py | 53 +- testsuite/tests/I812-011/test.py | 65 +- testsuite/tests/I914-023/test.py | 27 +- .../tests/I930-009-ppc-beq-bt-x2/test.py | 21 +- testsuite/tests/I930-009-ppc-beq-bt/test.py | 21 +- .../tests/I930-009-ppc-beq-ft-x2/test.py | 21 +- testsuite/tests/I930-009-ppc-beq-ft/test.py | 21 +- .../tests/I930-009-ppc-beq-npg-bt/test.py | 21 +- .../tests/I930-009-ppc-beq-npg-ft/test.py | 21 +- .../tests/I930-009-ppc-beq-npg-tk/test.py | 21 +- testsuite/tests/I930-009-ppc-beq-nt/test.py | 21 +- .../tests/I930-009-ppc-beq-tb-x2/test.py | 21 +- testsuite/tests/I930-009-ppc-beq-tb/test.py | 21 +- .../tests/I930-009-ppc-beq-tk-x2/test.py | 21 +- testsuite/tests/I930-009-ppc-beq-tk/test.py | 21 +- testsuite/tests/I930-009-ppc-beqlr-bt/test.py | 20 +- testsuite/tests/I930-009-ppc-beqlr-ft/test.py | 20 +- testsuite/tests/I930-009-ppc-beqlr-tb/test.py | 20 +- testsuite/tests/I930-009-ppc-beqlr-tk/test.py | 20 +- .../tests/I930-009-sparc-be-a-ft/test.py | 27 +- .../tests/I930-009-sparc-be-a-npg-ft/test.py | 27 +- .../tests/I930-009-sparc-be-a-npg-tk/test.py | 21 +- .../tests/I930-009-sparc-be-a-nt/test.py | 29 +- .../tests/I930-009-sparc-be-a-tk/test.py | 29 +- testsuite/tests/I930-009-sparc-be-bt/test.py | 21 +- testsuite/tests/I930-009-sparc-be-ft/test.py | 27 +- .../tests/I930-009-sparc-be-npg-bt/test.py | 21 +- .../tests/I930-009-sparc-be-npg-ft/test.py | 21 +- .../tests/I930-009-sparc-be-npg-tk/test.py | 21 +- testsuite/tests/I930-009-sparc-be-nt/test.py | 21 +- testsuite/tests/I930-009-sparc-be-tk/test.py | 21 +- .../I930-009-sparc-cross-boundary/test.py | 27 +- testsuite/tests/I930-019/test.py | 38 +- testsuite/tests/IA01-015/test.py | 65 +- .../tests/IA06-008-override-exec/test.py | 60 +- .../tests/IA06-009-offset-from-sym/test.py | 35 +- testsuite/tests/IA09-021-unit-nosco/test.py | 27 +- testsuite/tests/IA13-015-loop-body/test.py | 24 +- .../tests/IA16-028-disp-routines/test.py | 78 +- .../tests/IA19-009-no-useless-srcs/test.py | 26 +- .../IA21-003-simple-decision-sco/test.py | 36 +- testsuite/tests/IA21-009-nested-scos/test.py | 6 +- .../tests/IA22-004-same-basename/test.py | 52 +- testsuite/tests/IA29-020-basic-checks/test.py | 86 +- .../tests/IA29-023-source-search/test.py | 19 +- testsuite/tests/J618-019-disa-x86/test.py | 4 +- .../tests/J723-017-empty-debug-info/test.py | 4 +- testsuite/tests/JC09-015-set-file/test.py | 4 +- testsuite/tests/K214-014-gc-sections/test.py | 48 +- .../tests/KB30-011-eargs-gnatemu/test.py | 107 +- testsuite/tests/KC06-023-list_as_ali/test.py | 20 +- .../tests/KC23-012-ocov-exemptions/test.py | 56 +- .../L112-050-pro-through-disabled/test.py | 28 +- testsuite/tests/L209-010-asm-outfile/test.py | 48 +- .../tests/L411-031_missing_gnateS/test.py | 43 +- testsuite/tests/L613-012/test.py | 11 +- .../tests/L619-040-output-to-objdir/test.py | 40 +- testsuite/tests/L707-006-src-in-cwd/test.py | 25 +- testsuite/tests/L929-006/test.py | 19 +- .../tests/LA17-032-scan-decisions/test.py | 16 +- testsuite/tests/LA23-016_eargs-exe/test.py | 30 +- .../tests/M502-040-default-prj-path/test.py | 23 +- testsuite/tests/M513-017/test.py | 3 +- testsuite/tests/M515-018/test.py | 24 +- .../tests/M531-035-3264-ld_preload/test.py | 6 +- testsuite/tests/M625-011-GPR-Cunits/test.py | 31 +- .../tests/M625-040-slow_on_windows/test.py | 8 +- .../tests/M726-018-trace-exec-check/test.py | 96 +- testsuite/tests/MA08-031/test.py | 8 +- .../tests/MB15-041-verbose-open-crc32/test.py | 81 +- .../MB19-016-subprogram-less-code/test.py | 45 +- .../tests/MC05-011-ref-executable/test.py | 26 +- testsuite/tests/N107-020-dhtml/test.py | 9 +- .../tests/N107-029-crc32-validity/test.py | 45 +- .../tests/N203-040-same-c-basename/test.py | 45 +- .../tests/N321-039-disas-wrapping/test.py | 25 +- .../N321-045-ppc-disas-large-input/test.py | 6 +- .../tests/N411-046-asm-consolidation/test.py | 25 +- .../N429-018-c-assert/ToMultiStmts/test.py | 4 +- .../N429-018-c-assert/ToSingleStmt/test.py | 4 +- .../tests/N429-018-c-tern-folding/test.py | 4 +- .../tests/N429-020-loop-on-line-ada/test.py | 5 +- testsuite/tests/N429-020-loop-on-line/test.py | 5 +- .../supported/test.py | 4 +- .../unsupported/test.py | 46 +- .../tests/N505-008-c99-main-return/test.py | 2 +- .../N506-014-crash-on-padding-nop/test.py | 4 +- testsuite/tests/N610-006-library/test.py | 72 +- testsuite/tests/N630-009-forward_p_x/test.py | 17 +- .../tests/NA29-019-unit-filters-for-C/test.py | 57 +- testsuite/tests/NC02-014-gpr-X/test.py | 32 +- testsuite/tests/NC08-027-target_attr/test.py | 39 +- .../O212-062-show-condition-vectors/test.py | 51 +- testsuite/tests/O212-062-xml/test.py | 13 +- .../O302-015-src-path-in-project/test.py | 46 +- .../tests/O529-021-wrong-elf-class/test.py | 19 +- testsuite/tests/O916-035-padding-cons/test.py | 206 ++-- .../tests/OA05-051-sharedobjs-opt/test.py | 48 +- testsuite/tests/OA05-051-sharedobjs/test.py | 152 +-- testsuite/tests/OA16-009-exec-prefix/test.py | 63 +- .../tests/OA16-009-windows-suffix/test.py | 23 +- .../OA27-059-inlined-separate-cons/test.py | 93 +- .../OA27-059-sep-cons-prj-override/test.py | 48 +- testsuite/tests/OA27-059-sep-cons-prj/test.py | 42 +- .../OA27-059-separate-consolidation/test.py | 44 +- testsuite/tests/OB23-036/test.py | 18 +- testsuite/tests/P505-032-path-spaces/test.py | 27 +- .../tests/P526-035-origin-project/test.py | 67 +- .../tests/P907-005-ckpt-covlevel/test.py | 79 +- testsuite/tests/P907-005-incremental/test.py | 49 +- .../tests/P907-005-stubbing-generic/test.py | 77 +- testsuite/tests/P907-005-stubbing/test.py | 77 +- .../tests/P913-011-invalid-project/test.py | 38 +- testsuite/tests/PC09-022-auto-exename/test.py | 122 ++- .../Q224-032-several-out-of-line/test.py | 36 +- .../Q308-041-crash-on-generic-in-lib/test.py | 52 +- testsuite/tests/Q327-016-glob-ignore/test.py | 29 +- .../tests/Q329-018-create-output-dir/test.py | 26 +- testsuite/tests/Q519-013-decision-map/test.py | 22 +- .../tests/Q614-037-ckpt-pkg-renames/test.py | 37 +- testsuite/tests/Q901-012-report-title/test.py | 36 +- testsuite/tests/Q905-005-compressed/test.py | 38 +- .../tests/QA23-039-nocode-pragmas/test.py | 65 +- .../tests/QA27-024-prepare-target/test.py | 38 +- .../tests/QB14-023-stack-overflow/test.py | 15 +- testsuite/tests/R404-023-object-stats/test.py | 30 +- .../tests/R417-010-scope-metrics/test.py | 11 +- .../R420-002-aggregate-project-file/test.py | 70 +- .../tests/R507-014-trailing-byte-insn/test.py | 37 +- testsuite/tests/R507-027-xml-summary/test.py | 19 +- testsuite/tests/R521-002-profile-arcs/test.py | 53 +- testsuite/tests/R807-027-symbol-order/test.py | 59 +- testsuite/tests/RB13-019-win-paths/test.py | 51 +- testsuite/tests/RB16-008-gpr-tool/test.py | 50 +- testsuite/tests/RC04-030-bad-trace/test.py | 80 +- .../tests/S213-006-obligation-stats/test.py | 16 +- testsuite/tests/S218-011-time-option/test.py | 34 +- .../tests/S220-058-auto-scos-fetch/test.py | 47 +- .../tests/S506-014-mix-providers/test.py | 188 ++-- testsuite/tests/S529-038-isi-ckpt/test.py | 103 +- .../S619-014-tag-provider-mismatch/test.py | 56 +- testsuite/tests/S621-026-mcdc-ckpt/test.py | 36 +- .../tests/S820-013-ckpt-dup-scos/test.py | 37 +- testsuite/tests/SB06-033-homonyms/test.py | 81 +- testsuite/tests/T117-007-intf-thunks/test.py | 21 +- testsuite/tests/T331-043-native-warn/test.py | 37 +- .../tests/T528-018-dup-proj-crash/test.py | 27 +- .../tests/T611-027-dump-units-to/test.py | 201 ++-- testsuite/tests/T629-012-pragmas/test.py | 15 +- testsuite/tests/T731-036-ckpt-bdd/test.py | 85 +- .../T807-011-externally-built-objdir/test.py | 42 +- .../tests/T825-010-naming-scheme/test.py | 32 +- .../tests/T916-046-bdd-remapping/test.py | 11 +- .../TA12-013-dump-ignore-src-files/test.py | 265 ++--- .../tests/TA14-011-show-mcdc-vectors/test.py | 177 ++-- .../tests/TA15-063-ignore-fingerprint/test.py | 42 +- .../test.py | 86 +- .../tests/TB13-020-expr-func-mcdc/test.py | 22 +- testsuite/tests/TB24-022-missing-sid/test.py | 39 +- .../tests/TC03-012-objcov-line-state/test.py | 21 +- .../tests/TC11-052-internal-error/test.py | 71 +- .../U128-004-displayed-percentages/test.py | 30 +- testsuite/tests/U204-026-arch-mix/test.py | 20 +- .../tests/U204-029-source-rebase/Ada/test.py | 12 +- .../tests/U204-029-source-rebase/C/test.py | 9 +- .../U204-029-source-rebase/test_support.py | 88 +- .../tests/U208-020-child-project/test.py | 27 +- testsuite/tests/U208-020-error-call/test.py | 10 +- .../U208-020-unique-language-project/test.py | 27 +- testsuite/tests/U211-014-setup/test.py | 62 +- .../U219-010-ali-entry-guard-sloc/test.py | 9 +- .../test.py | 10 +- testsuite/tests/U317-004-xml-report/test.py | 17 +- testsuite/tests/U416-006-big-bdd/test.py | 25 +- .../tests/U429-016-gnatcov-misuse/test.py | 32 +- testsuite/tests/U527-020-dc-from-mcdc/test.py | 18 +- .../tests/U811-028-suppress-output/test.py | 26 +- testsuite/tests/U901-029-estamps/test.py | 22 +- .../UB18-055-switches-in-gprfile/test.py | 36 +- testsuite/tests/V201-010-multi-report/test.py | 21 +- testsuite/tests/V309-017-setup-config/test.py | 24 +- .../tests/V520-019-duplicate-messages/test.py | 22 +- testsuite/tests/V616-028-xsd-check/test.py | 10 +- testsuite/tests/V824-005-sid-ext-prj/test.py | 2 +- .../ignore-main/test.py | 19 +- .../main-unit-of-interest/test.py | 16 +- .../VA04-023-non-instr-sco-reloc/test.py | 3 +- .../tests/VB07-015-clean-output-dir/test.py | 2 +- testsuite/tests/Z999-999/test.py | 4 +- testsuite/tests/asm-consolidate/test.py | 51 +- .../IB13-014-const-instances/test.py | 7 +- .../branch-cond/IB15-004-spec-precond/test.py | 9 +- .../tests/build_run-assert-failure/test.py | 5 +- testsuite/tests/cobertura_validation/test.py | 16 +- .../tests/excluded_unit_imported_prj/test.py | 32 +- testsuite/tests/exemptions-check/test.py | 9 +- testsuite/tests/gnatcov-run.py | 47 +- testsuite/tests/gpr-scos/test.py | 50 +- .../tests/homonym-units-of-interest/test.py | 43 +- testsuite/tests/ignored-c-header/test.py | 3 - testsuite/tests/ignored-casing/test.py | 6 +- .../instr-cov/126-main-in-dependency/test.py | 20 +- .../instr-cov/217-runtime-subunit/test.py | 4 +- .../instr-cov/C++/c++_no_warnings/test.py | 16 +- .../tests/instr-cov/C++/explicit_lang/test.py | 14 +- .../tests/instr-cov/C++/std-c++20/test.py | 3 +- .../tests/instr-cov/C++/std-cond-code/test.py | 17 +- .../O212-062-unsupported-pragmas/test.py | 28 +- .../VB03-024-preprocess-included-proj/test.py | 52 +- .../tests/instr-cov/basic_base64/test.py | 31 +- .../tests/instr-cov/basic_decision/test.py | 29 +- testsuite/tests/instr-cov/basic_stmt/test.py | 29 +- .../tests/instr-cov/bin_file_tunings/test.py | 60 +- .../tests/instr-cov/buffer_reset/test.py | 63 +- .../tests/instr-cov/c_empty_source/test.py | 14 +- testsuite/tests/instr-cov/c_header/test.py | 16 +- .../c_macros_no_cov_warnings/test.py | 12 +- testsuite/tests/instr-cov/c_no_return/test.py | 6 +- testsuite/tests/instr-cov/c_opts/test.py | 6 +- .../tests/instr-cov/c_prep_error/test.py | 3 +- .../instr-cov/c_ternary_in_if_cond/test.py | 14 +- .../tests/instr-cov/c_wrong_main/test.py | 14 +- .../instr-cov/checks_and_warnings/test.py | 28 +- .../instr-cov/cmdline-self-ref-macro/test.py | 16 +- .../tests/instr-cov/config_custom_db/test.py | 3 +- testsuite/tests/instr-cov/consistency/test.py | 79 +- .../instr-cov/default_dump_channel/test.py | 28 +- testsuite/tests/instr-cov/end_slocs/test.py | 17 +- testsuite/tests/instr-cov/endianity/test.py | 47 +- .../tests/instr-cov/explicit_mains/test.py | 16 +- .../explicit_mains_ignore_gpr/test.py | 5 +- .../instr-cov/explicit_mains_uoi/test.py | 12 +- .../tests/instr-cov/expr_func/aggr/test.py | 21 +- .../tests/instr-cov/expr_func/basic/test.py | 17 +- .../tests/instr-cov/expr_func/generic/test.py | 6 +- .../instr-cov/expr_func/parameterless/test.py | 21 +- .../tests/instr-cov/expr_func/prim/test.py | 21 +- .../tests/instr-cov/expr_func/prim2/test.py | 27 +- testsuite/tests/instr-cov/ext_gpr/test.py | 26 +- .../tests/instr-cov/file-context/test.py | 27 +- .../tests/instr-cov/ghost_generic/test.py | 2 +- .../tests/instr-cov/library_projects/test.py | 40 +- .../main_autodump/nested_block/test.py | 53 +- .../instr-cov/manual-dump/ada_only/test.py | 95 +- .../instr-cov/manual-dump/ada_subprj/test.py | 56 +- .../tests/instr-cov/manual-dump/basic/test.py | 7 +- .../instr-cov/manual-dump/c_only/test.py | 71 +- .../manual-dump/lal_ctx_reset/test.py | 11 +- .../tests/instr-cov/manual-dump/mixed/test.py | 2 +- .../manual-dump/prefix_in_code/test.py | 23 +- .../instr-cov/manual-dump/trace_index/test.py | 30 +- .../manual-dump/unknown_lang/test.py | 6 +- testsuite/tests/instr-cov/mixed_and/test.py | 27 +- .../tests/instr-cov/multi_unit_source/test.py | 8 +- .../tests/instr-cov/multiline_marker/test.py | 8 +- .../tests/instr-cov/multiple_mains/test.py | 11 +- .../tests/instr-cov/nested_ternary/test.py | 12 +- testsuite/tests/instr-cov/no_main/test.py | 19 +- testsuite/tests/instr-cov/not_array/test.py | 28 +- .../tests/instr-cov/pragma_after_cu/test.py | 22 +- .../tests/instr-cov/pragma_no_body/test.py | 23 +- testsuite/tests/instr-cov/pure_units/test.py | 25 +- .../tests/instr-cov/remove_extra_src/test.py | 57 +- testsuite/tests/instr-cov/scalar_and/test.py | 17 +- .../tests/instr-cov/stmt_after_accept/test.py | 9 +- .../tests/instr-cov/unknown_unit/test.py | 52 +- .../168-rts_error_msg/test.py | 4 +- .../basic_cmake/test.py | 6 +- .../cmake_lib/test.py | 8 +- .../duplicated_symbols_in_libraries/test.py | 15 +- .../special_filenames/test.py | 11 +- .../unmodified-root-dir/test.py | 2 +- testsuite/tests/scos-overlap/test.py | 2 +- testsuite/tests/shared-libs/ada-main/test.py | 46 +- testsuite/tests/shared-libs/c-main/test.py | 51 +- testsuite/tests/subp_of_interest/test.py | 7 +- testsuite/tests/subp_of_interest_c/test.py | 2 +- testsuite/tests/xml-check/test.py | 22 +- testsuite/testsuite.py | 520 +++++----- tools/gnatcov/examples/xml/xcov-report.py | 6 +- tools/gnatcov/examples/xml/xcov.py | 250 +++-- tools/gnatcov/gnatcov-gdb.py | 11 +- tools/gnatcov/misc/design/instrument_mcdc.py | 211 ++-- tools/gnatcov/scripts/bddinfo.py | 120 +-- tools/gnatcov/scripts/decision_cfg.py | 504 +++++----- tools/gnatcov/scripts/dwarfdump.py | 19 +- tools/gnatcov/scripts/gnatcov_gdb/__init__.py | 1 + tools/gnatcov/scripts/gnatcov_gdb/printers.py | 110 +- tools/gnatcov/scripts/intervalmap.py | 119 ++- tools/gnatcov/scripts/slocinfo.py | 50 +- tools/gnatcov/scripts/syminfo.py | 63 +- tools/gnatcov/scripts/traceinfo.py | 49 +- 456 files changed, 13230 insertions(+), 9563 deletions(-) diff --git a/.check-formatting.py b/.check-formatting.py index 17b4f971c..bffe2c63e 100644 --- a/.check-formatting.py +++ b/.check-formatting.py @@ -34,7 +34,6 @@ class Checker: - filename_extensions = { "adb", "adc", @@ -88,20 +87,20 @@ def report( # Build a list of text chunks to print. Put colorama elements in tuples # so that we can keep only text chunks if the output is not a TTY. chunks = [ - (Fore.MAGENTA, ), + (Fore.MAGENTA,), filename, - (Fore.CYAN, ), + (Fore.CYAN,), ":", ] if lineno is not None: chunks += [ - (Fore.GREEN, ), + (Fore.GREEN,), str(lineno), - (Fore.CYAN, ), + (Fore.CYAN,), ":", ] chunks += [ - (Style.RESET_ALL, ), + (Style.RESET_ALL,), " ", message, ] diff --git a/doc/conf.py b/doc/conf.py index 13bac8902..3ac1bd87f 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -24,13 +24,13 @@ # -- General configuration ------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = '1.8' +needs_sphinx = "1.8" # 1.2 for multiple glossary entries # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [ - 'sphinx.ext.imgmath', + "sphinx.ext.imgmath", "sphinx.ext.autodoc", "sphinx.ext.coverage", "sphinx.ext.doctest", @@ -44,10 +44,10 @@ autosectionlabel_prefix_document = True # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. # source_encoding = 'utf-8-sig' @@ -58,9 +58,9 @@ master_doc = "index" # General information about the project. -project = u"GNATDAS" -copyright = u"2009-2022, AdaCore" -docname = u"Manuals" +project = "GNATDAS" +copyright = "2009-2022, AdaCore" +docname = "Manuals" rst_epilog = """ .. |gcv| replace:: :command:`gnatcov` @@ -85,7 +85,7 @@ .. |rarg| replace:: possibly repeated and accepting :term:`@listfile arguments <@listfile argument>` """.format( - project + project ) # The version info for the project you're documenting, acts as replacement for @@ -95,12 +95,12 @@ # Tool version & release. Nightly setups are expected to store this # in a version.txt file for us. Assume we're in a development tree otherwise. -version_file = 'version.txt' +version_file = "version.txt" if os.path.exists(version_file): - with open(version_file, 'r') as f: + with open(version_file, "r") as f: version = f.read() else: - version = 'dev-tree' + version = "dev-tree" release = version @@ -116,7 +116,7 @@ # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. -exclude_patterns = ['_build'] +exclude_patterns = ["_build"] # The reST default role (used for this markup: `text`) to use for all # documents. @@ -151,8 +151,7 @@ # a list of builtin themes. html_theme = "sphinx_rtd_theme" -html_sidebars = { - '**': ['globaltoc.html', 'sourcelink.html', 'searchbox.html']} +html_sidebars = {"**": ["globaltoc.html", "sourcelink.html", "searchbox.html"]} # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the @@ -243,19 +242,24 @@ # to our latex_preamble. latex_documents = [ - (master_doc, master_doc+'.tex', "%s %s" % (project, docname), - u'AdaCore', 'manual'), + ( + master_doc, + master_doc + ".tex", + "%s %s" % (project, docname), + "AdaCore", + "manual", + ), ] # Get rid of the "Release" tag before the version number # in the first page subtitle -latex_additional_files = ['latex_preamble.inc'] +latex_additional_files = ["latex_preamble.inc"] latex_elements = { - 'releasename': 'Version', - 'preamble': r'\input{latex_preamble.inc}', - } + "releasename": "Version", + "preamble": r"\input{latex_preamble.inc}", +} # The name of an image file (relative to this directory) to place at the top # of the title page. @@ -263,7 +267,7 @@ # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -latex_toplevel_sectioning = 'part' +latex_toplevel_sectioning = "part" # If true, show page references after internal links. # latex_show_pagerefs = False diff --git a/doc/gnatcov/gen_prjtrees.py b/doc/gnatcov/gen_prjtrees.py index 3ccadcc36..5c5e31834 100644 --- a/doc/gnatcov/gen_prjtrees.py +++ b/doc/gnatcov/gen_prjtrees.py @@ -4,17 +4,18 @@ def render(tree): - subprocess.call(["dot", "-Tpng", "-o"+tree+".png", tree+".dot"]) - subprocess.call(["dot", "-Tpdf", "-o"+tree+".pdf", tree+".dot"]) + subprocess.call(["dot", "-Tpng", "-o" + tree + ".png", tree + ".dot"]) + subprocess.call(["dot", "-Tpdf", "-o" + tree + ".pdf", tree + ".dot"]) def gen_tree(tmpl, outfile, selected): for line in tmpl: - m = re.search(r'([a-z_0-9]*) \[(.*)\];', line) + m = re.search(r"([a-z_0-9]*) \[(.*)\];", line) if m and m.group(1) in selected: outfile.write( - "\t\t%s [%s,color=darkslateblue, fontcolor=white ];\n" % - (m.group(1), m.group(2))) + "\t\t%s [%s,color=darkslateblue, fontcolor=white ];\n" + % (m.group(1), m.group(2)) + ) else: outfile.write(line) @@ -22,14 +23,14 @@ def gen_tree(tmpl, outfile, selected): tmpl = open("prjtree.dot").readlines() trees = { - 'Proot-nosub': ['root'], - 'Proot-ss_a-nosub': ['ss_a'], - 'Proot-root-ss_a-nosub': ['root', 'ss_a'], - 'Proot-ss_a': ['ss_a', 'sa1', 'sa2', 'sa3', 'common'] + "Proot-nosub": ["root"], + "Proot-ss_a-nosub": ["ss_a"], + "Proot-root-ss_a-nosub": ["root", "ss_a"], + "Proot-ss_a": ["ss_a", "sa1", "sa2", "sa3", "common"], } for k in trees: gen_tree(tmpl, open(k + ".dot", "w"), trees[k]) render(k) os.remove (f"{k}.dot") -render('prjtree') +render("prjtree") diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 938a02349..bd0efdb4b 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -200,7 +200,7 @@ # This lets us access modules that the testuite # code features: -MY_TESTSUITE_DIR=os.path.abspath("../testsuite") +MY_TESTSUITE_DIR = os.path.abspath("../testsuite") sys.path.append(MY_TESTSUITE_DIR) from SUITE.qdata import CTXDATA_FILE, treeref_at @@ -211,25 +211,30 @@ # == MISC UTILITY FUNCTIONS == # ======================================================================= -class Error (Exception): + +class Error(Exception): def __init__(self): pass -def fail_if (p, msg): + +def fail_if(p, msg): if p: print(msg) raise Error -def exit_if (p, msg): + +def exit_if(p, msg): if p: print(msg) sys.exit(1) -def warn_if (p, msg): + +def warn_if(p, msg): if p: print("\n!!! WARNING: %s !!!\n" % msg) -def run_list (cmd, dir=None, env=None): + +def run_list(cmd, dir=None, env=None): """Execute the provided CMD command-list (command name + arguments), temporarily switching to the DIR directory unless None, dumping a .log file tracking the command output in the directory where the command @@ -242,26 +247,29 @@ def run_list (cmd, dir=None, env=None): if dir: print("hopat : %s" % dir) - os.chdir (dir) + os.chdir(dir) - print("run : %s" % ' '.join(cmd)) + print("run : %s" % " ".join(cmd)) - out = os.path.basename(cmd[0])+".log" - p = Run (cmd, output=out, env=env, ignore_environ=False) + out = os.path.basename(cmd[0]) + ".log" + p = Run(cmd, output=out, env=env, ignore_environ=False) - fail_if ( - p.status != 0, "execution failed\n" - + "log was:\n" + contents_of(out)) + fail_if( + p.status != 0, "execution failed\n" + "log was:\n" + contents_of(out) + ) - os.chdir (oriwd) + os.chdir(oriwd) -def run (s, dir=None, env=None): - run_list (s.split(), dir, env=env) -def announce (s): +def run(s, dir=None, env=None): + run_list(s.split(), dir, env=env) + + +def announce(s): print("=========== " + s) -def remove (path): + +def remove(path): """Delete the file or directory subtree designated by PATH""" print("from : %s" % os.getcwd()) @@ -286,68 +294,70 @@ def remove (path): def isdir(path): return os.path.isdir(path) and not os.path.islink(path) - if os.path.exists (local_name): - rm (local_name, recursive=isdir(local_name)) + if os.path.exists(local_name): + rm(local_name, recursive=isdir(local_name)) + + if os.path.exists(path): + mv(path, local_name) + rm(local_name, recursive=isdir(local_name)) - if os.path.exists (path): - mv (path, local_name) - rm (local_name, recursive=isdir(local_name)) # testsuite dirs may include a [user@]remote-host: prefix -def raccess_in (path): - components = path.split(':') + +def raccess_in(path): + components = path.split(":") return components[0] if len(components) > 1 else None -def rdir_in (path): - components = path.split(':') + +def rdir_in(path): + components = path.split(":") return components[1] if len(components) > 1 else None + # current git branch name, used as kit identifier: -def current_gitbranch_at (dirname): +def current_gitbranch_at(dirname): cwd = os.getcwd() os.chdir(dirname) - this_branch = re.search ( - pattern="\* (?P\S*)", - string=output_of("git branch") - ).group('branchname') + this_branch = re.search( + pattern="\* (?P\S*)", string=output_of("git branch") + ).group("branchname") os.chdir(cwd) return this_branch + # ======================================================================= # == QUALIF MATERIAL GENERATION HELPER CLASS == # ======================================================================= -sphinx_target_for = { - "html": "html", - "pdf" : "latexpdf" - } +sphinx_target_for = {"html": "html", "pdf": "latexpdf"} # The master GIT repo where our source artifacts reside -GIT_MASTER = "git@ssh.gitlab.adacore-it.com:eng/das/cov/gnatcoverage-qualification.git" +GIT_MASTER = ( + "git@ssh.gitlab.adacore-it.com:eng/das/cov/gnatcoverage-qualification.git" +) # The subdir name for this clone, relative to --root GIT_CLONE_SUBDIR = "gnatcoverage-git-clone" -class QMAT: - def itemsdir (self): - return os.path.join (self.workdir, "%s" % self.this_docformat.upper()) +class QMAT: + def itemsdir(self): + return os.path.join(self.workdir, "%s" % self.this_docformat.upper()) def __init__(self, options): - self.o = options # Make sure we can designate the work dir easily from anywhere. # Latch repo dir location while we're at it: - self.workdir = os.path.abspath (options.workdir) - self.repodir = os.path.join (self.workdir, GIT_CLONE_SUBDIR) + self.workdir = os.path.abspath(options.workdir) + self.repodir = os.path.join(self.workdir, GIT_CLONE_SUBDIR) # A local place where the testsuite tree may be found, # possibly after remote syncing from testsuite_dir if that @@ -363,26 +373,27 @@ def __init__(self, options): self.passno = 0 - def process_imports(self, dir): """ Process the template file in dir, replacing the occurrences of <%name%> in the text by the contents of name_.rst, according to the qualification parameters """ + def replace_one(p): return contents_of( - os.path.join(dir,p.group(1) + f"_{self.o.trace_mode}.rst") - ) - + os.path.join(dir, p.group(1) + f"_{self.o.trace_mode}.rst") + ) - template_content = contents_of(os.path.join (dir,"content.tmpl")) + template_content = contents_of(os.path.join(dir, "content.tmpl")) with open(os.path.join(dir, "content.rst"), "w") as f: - f.write(re.sub( - pattern=r"<%([^%]+)%>", - repl=replace_one, - string=template_content - )) + f.write( + re.sub( + pattern=r"<%([^%]+)%>", + repl=replace_one, + string=template_content, + ) + ) # --------------------- # -- prepare_content -- @@ -403,34 +414,37 @@ def prepare_content(self, dirs): # -- setup_workdir -- # -------------------- - def setup_workdir (self): - - announce ("setting up working dir at %s" % self.workdir) - - mkdir (self.workdir) + def setup_workdir(self): + announce("setting up working dir at %s" % self.workdir) + mkdir(self.workdir) # --------- # -- log -- # --------- - def log (self, line): - with open (os.path.join(self.workdir, "genbundle.log"), 'a') as f: - f.write (line + '\n') + def log(self, line): + with open(os.path.join(self.workdir, "genbundle.log"), "a") as f: + f.write(line + "\n") # ---------------- # -- git_update -- # ---------------- - def git_update (self): - + def git_update(self): # If we're requested to rsync from an existing repo dir, do so if self.o.gitrsync: - run_list ( - ["rsync", "-ar", self.o.gitrsync + '/', self.repodir + '/', - '--delete', '--delete-excluded', - '--filter', '. dev.rsync', + run_list( + [ + "rsync", + "-ar", + self.o.gitrsync + "/", + self.repodir + "/", + "--delete", + "--delete-excluded", + "--filter", + ". dev.rsync", ] ) return @@ -438,61 +452,60 @@ def git_update (self): # If we're requested to pull/update only, do so if self.o.gitpull: - announce ("updating git clone from origin") + announce("updating git clone from origin") os.chdir(self.repodir) - run ("git pull --rebase origin") + run("git pull --rebase origin") return # If we're requested to reuse an existing clone, do so if self.o.gitreuse: - announce ("reusing existing git clone") + announce("reusing existing git clone") return # Otherwise, get a fresh clone. os.chdir(self.workdir) - gitref = ( - self.o.gitsource if self.o.gitsource - else GIT_MASTER - ) + gitref = self.o.gitsource if self.o.gitsource else GIT_MASTER - announce ("cloning git repository from %s" % gitref) + announce("cloning git repository from %s" % gitref) - remove (GIT_CLONE_SUBDIR) - run ("git clone %s %s" % (gitref, GIT_CLONE_SUBDIR)) + remove(GIT_CLONE_SUBDIR) + run("git clone %s %s" % (gitref, GIT_CLONE_SUBDIR)) # ---------------------- # -- switch_to_branch -- # ---------------------- - def switch_to_branch (self): - announce ("switching to branch '%s'" % self.o.branchname) + def switch_to_branch(self): + announce("switching to branch '%s'" % self.o.branchname) os.chdir(self.repodir) - run ("git checkout %s" % self.o.branchname) + run("git checkout %s" % self.o.branchname) # ----------------- # -- kititem_for -- # ----------------- - def kititem_for (self, part): + def kititem_for(self, part): """The name of the filesystem entity which materializes PART in a kit distribution. This will be a subdirectory name for treeish formats a-la html (e.g. TOR, which will contain content.html etc), or a specific filename (e.g. PLANS.pdf) for other formats. This is what latch_into sets up eventually.""" - this_item_is_tree = (self.this_docformat == 'html') + this_item_is_tree = self.this_docformat == "html" this_item_suffix = ( - '' if this_item_is_tree else '.%s' % self.this_docformat) + "" if this_item_is_tree else ".%s" % self.this_docformat + ) return "%(part)s%(suffix)s" % { "part": part.upper(), - "suffix": this_item_suffix } + "suffix": this_item_suffix, + } # ---------------- # -- latch_into -- @@ -530,17 +543,16 @@ def kititem_for (self, part): # # for the html versions. - def __latch_into (self, dir, part, toplevel, copy_from=None): - - this_target_is_tree = (self.this_docformat == 'html') + def __latch_into(self, dir, part, toplevel, copy_from=None): + this_target_is_tree = self.this_docformat == "html" # Compute the target dir or file name for our copy: this_target = ( - dir if toplevel and this_target_is_tree - else os.path.join ( - dir, self.kititem_for(part=part)) - ) + dir + if toplevel and this_target_is_tree + else os.path.join(dir, self.kititem_for(part=part)) + ) # Compute the source dir or file name for our copy: @@ -549,247 +561,258 @@ def __latch_into (self, dir, part, toplevel, copy_from=None): # doc format. For file outputs, assume the builders are setup to # produce PART., e.g. TOR.pdf: - this_build_subdir = os.path.join ( + this_build_subdir = os.path.join( copy_from if copy_from is not None else "build", - sphinx_target_for[self.this_docformat] - ) + sphinx_target_for[self.this_docformat], + ) this_source = ( - this_build_subdir if this_target_is_tree - else os.path.join(this_build_subdir, - part.upper() + ".%s" % self.this_docformat) + this_build_subdir + if this_target_is_tree + else os.path.join( + this_build_subdir, part.upper() + ".%s" % self.this_docformat ) - + ) # Delete an old version of latched results that might # already be there if we're running with --work-dir. - remove (this_target) + remove(this_target) # Now proceed with the latch operation per se: if not this_target_is_tree: - cp (this_source, this_target, recursive=False) + cp(this_source, this_target, recursive=False) elif copy_from: - cp (this_source, this_target, recursive=True) + cp(this_source, this_target, recursive=True) else: - mv (this_build_subdir, this_target) - - print("%s %s available in %s %s" % ( - self.this_docformat, part.upper(), - this_target, "(toplevel)" if toplevel else "" - )) + mv(this_build_subdir, this_target) + + print( + "%s %s available in %s %s" + % ( + self.this_docformat, + part.upper(), + this_target, + "(toplevel)" if toplevel else "", + ) + ) # ------------------ # -- gen_qm_model -- # ------------------ - def gen_qm_model (self): + def gen_qm_model(self): """Generate model.xml that __qm_build will use.""" - announce ("generating qm model") + announce("generating qm model") - os.chdir ( - os.path.join (self.repodir, "qualification", "qm") - ) + os.chdir(os.path.join(self.repodir, "qualification", "qm")) - run (sys.executable + \ - " genmodel.py --dolevel=%s --languages=%s" % - (self.o.dolevel, self.o.languages)) + run( + sys.executable + + " genmodel.py --dolevel=%s --languages=%s" + % (self.o.dolevel, self.o.languages) + ) # ---------------- # -- __qm_build -- # ---------------- - def __qm_build (self, part): + def __qm_build(self, part): """Build one PART of using the Qualifying Machine.""" - announce ("building %s %s" % (self.this_docformat, part.upper())) + announce("building %s %s" % (self.this_docformat, part.upper())) - os.chdir ( - os.path.join (self.repodir, "qualification", "qm") - ) + os.chdir(os.path.join(self.repodir, "qualification", "qm")) # The qmachine model might use the "build" directory as # a repository, and it has to preexist: - mkdir ("build") - run ("qmachine model.xml -l scripts/generate_%s_%s.py" \ - % (part, self.this_docformat), - env={'GENBUNDLE_DOLEVEL': self.o.dolevel}) + mkdir("build") + run( + "qmachine model.xml -l scripts/generate_%s_%s.py" + % (part, self.this_docformat), + env={"GENBUNDLE_DOLEVEL": self.o.dolevel}, + ) - self.__latch_into ( - dir=self.itemsdir(), part=part, toplevel=False) + self.__latch_into(dir=self.itemsdir(), part=part, toplevel=False) # --------------- # -- build_tor -- # --------------- - def build_tor (self): - + def build_tor(self): # If we have a local testsuite dir at hand and we haven't done so # already, fetch the testsresults that the QM needs to check TOR/TC # consistency: if self.local_testsuite_dir and self.passno == 1: - os.chdir (self.local_testsuite_dir) + os.chdir(self.local_testsuite_dir) def sync(tr): - target_dir = os.path.join ( - self.repodir, "testsuite", os.path.dirname (tr) - ) + target_dir = os.path.join( + self.repodir, "testsuite", os.path.dirname(tr) + ) if os.path.exists(target_dir): - cp (tr, target_dir) + cp(tr, target_dir) else: - print ("ERRRR !! inexistant target dir for %s" % tr) + print("ERRRR !! inexistant target dir for %s" % tr) - [sync(tr) for tr in find (root=".", pattern="tc.dump")] - env_chapter_dir = os.path.join(self.repodir, "testsuite", "Qualif", "Environment") + [sync(tr) for tr in find(root=".", pattern="tc.dump")] + env_chapter_dir = os.path.join( + self.repodir, "testsuite", "Qualif", "Environment" + ) self.process_imports(env_chapter_dir) - self.__qm_build (part="tor") + self.__qm_build(part="tor") # ------------------------------ # -- dump_kit_consistency_log -- # ------------------------------ - def __dump_tree_consistency_info (self, log, suite_ctxdata): - - log.write ("\n-- TREE CONSISTENCY LOG:\n") + def __dump_tree_consistency_info(self, log, suite_ctxdata): + log.write("\n-- TREE CONSISTENCY LOG:\n") if not suite_ctxdata: - log.write ( + log.write( "suite context info unavailable, " - "tree consistency unchecked\n") + "tree consistency unchecked\n" + ) return - os.chdir (self.repodir) + os.chdir(self.repodir) local_treeref = treeref_at(self.repodir) - suite_treeref = suite_ctxdata['treeref'] + suite_treeref = suite_ctxdata["treeref"] if local_treeref == suite_treeref: - log.write ( - "artifact tree ref matches testsuite (%s)\n" % local_treeref) + log.write( + "artifact tree ref matches testsuite (%s)\n" % local_treeref + ) return - log.write ( - "local_treeref = %s , suite_treeref = %s\n" % \ - (local_treeref, suite_treeref) - ) + log.write( + "local_treeref = %s , suite_treeref = %s\n" + % (local_treeref, suite_treeref) + ) - merge_base = output_of ( + merge_base = output_of( "git merge-base %s %s" % (local_treeref, suite_treeref) - ).strip(' \n') + ).strip(" \n") (first, next) = ( - (suite_treeref, local_treeref) if merge_base == suite_treeref - else (local_treeref, suite_treeref) if merge_base == local_treeref - else (None, None)) + (suite_treeref, local_treeref) + if merge_base == suite_treeref + else (local_treeref, suite_treeref) + if merge_base == local_treeref + else (None, None) + ) if first == None: - log.write ( - "!!! local and suite tree refs aren't sequential !!!\n") + log.write("!!! local and suite tree refs aren't sequential !!!\n") return - log.write ( - "%s tree is ahead\n" % \ - ('suite' if first == local_treeref else 'local') - ) - - gitlog_cmd = ( - "git rev-list --oneline %s ^%s" % (next, first)) - log.write ( - '\n'.join (['', gitlog_cmd, '--', output_of(gitlog_cmd), '']) - ) + log.write( + "%s tree is ahead\n" + % ("suite" if first == local_treeref else "local") + ) - def __dump_version_consistency_info (self, log, suite_ctxdata): + gitlog_cmd = "git rev-list --oneline %s ^%s" % (next, first) + log.write("\n".join(["", gitlog_cmd, "--", output_of(gitlog_cmd), ""])) - log.write ("\n-- VERSION CONSISTENCY LOG:\n") + def __dump_version_consistency_info(self, log, suite_ctxdata): + log.write("\n-- VERSION CONSISTENCY LOG:\n") if not suite_ctxdata: - log.write ( + log.write( "suite context info unavailable, " - "versions consistency unchecked\n") + "versions consistency unchecked\n" + ) return - def check_one (tool, actual, expected): - + def check_one(tool, actual, expected): if not expected: - log.write ( - "expected %s version NOT specified\n" % tool) + log.write("expected %s version NOT specified\n" % tool) return note = ( - "matches" if re.search (pattern=expected, string=actual) - else "doesn't match") - - log.write ( - '%(tool)s version "%(actual)s" %(note)s ' \ - 'expectation \"%(expected)s"\n' % { - 'tool' : tool, - 'note' : note, - 'expected': expected, - 'actual' : actual - } - ) - # + "matches" + if re.search(pattern=expected, string=actual) + else "doesn't match" + ) - check_one ( - tool = "gnatpro", - actual = suite_ctxdata['gnatpro']['version'], - expected = self.o.xgnatpro) + log.write( + '%(tool)s version "%(actual)s" %(note)s ' + 'expectation "%(expected)s"\n' + % { + "tool": tool, + "note": note, + "expected": expected, + "actual": actual, + } + ) - check_one ( - tool = "gnatcov", - actual = suite_ctxdata['gnatcov']['version'], - expected = self.o.xgnatcov) + # - def __dump_tr_consistency_info (self, log): + check_one( + tool="gnatpro", + actual=suite_ctxdata["gnatpro"]["version"], + expected=self.o.xgnatpro, + ) - log.write ("\n-- TOR/TR CONSISTENCY LOG:\n") + check_one( + tool="gnatcov", + actual=suite_ctxdata["gnatcov"]["version"], + expected=self.o.xgnatcov, + ) + + def __dump_tr_consistency_info(self, log): + log.write("\n-- TOR/TR CONSISTENCY LOG:\n") - tor_tr_logfile = os.path.join ( - self.repodir, "qualification", "qm", "missing_tr_log.txt") + tor_tr_logfile = os.path.join( + self.repodir, "qualification", "qm", "missing_tr_log.txt" + ) - if not os.path.exists (tor_tr_logfile): - log.write ("QM log NOT available\n") + if not os.path.exists(tor_tr_logfile): + log.write("QM log NOT available\n") return - log.write ( - "%s TOR/TR consistency log from QM @ %s :\n" % \ - ("FRESH" if self.do_tor() else "OLD", tor_tr_logfile) - ) - log.write (contents_of (tor_tr_logfile)) - log.write ("--\n") + log.write( + "%s TOR/TR consistency log from QM @ %s :\n" + % ("FRESH" if self.do_tor() else "OLD", tor_tr_logfile) + ) + log.write(contents_of(tor_tr_logfile)) + log.write("--\n") - def dump_kit_consistency_log (self): - announce ("dumping consistency log - format agnostic") + def dump_kit_consistency_log(self): + announce("dumping consistency log - format agnostic") logfile = os.path.join(self.workdir, "consistency.log") - log = open (logfile, 'w') + log = open(logfile, "w") - log.write ( - "artifact tree at %s (%s)\n" % ( - self.repodir, treeref_at(self.repodir)) - ) - log.write ( - "designated testsuite tree at %s (%s)\n" % \ - (self.o.testsuite_dir, - "REMOTE" if raccess_in(self.o.testsuite_dir) - else "local") + log.write( + "artifact tree at %s (%s)\n" + % (self.repodir, treeref_at(self.repodir)) + ) + log.write( + "designated testsuite tree at %s (%s)\n" + % ( + self.o.testsuite_dir, + "REMOTE" if raccess_in(self.o.testsuite_dir) else "local", ) - log.write ( - "local testsuite tree at %s\n" % self.local_testsuite_dir) + ) + log.write("local testsuite tree at %s\n" % self.local_testsuite_dir) - suite_ctxdata = jload_from ( - os.path.join (self.local_testsuite_dir, CTXDATA_FILE)) + suite_ctxdata = jload_from( + os.path.join(self.local_testsuite_dir, CTXDATA_FILE) + ) - self.__dump_tree_consistency_info (log, suite_ctxdata) - self.__dump_version_consistency_info (log, suite_ctxdata) - self.__dump_tr_consistency_info (log) + self.__dump_tree_consistency_info(log, suite_ctxdata) + self.__dump_version_consistency_info(log, suite_ctxdata) + self.__dump_tr_consistency_info(log) log.close() @@ -799,14 +822,15 @@ def dump_kit_consistency_log (self): # -- localize_testsuite_dir -- # ---------------------------- - def __localize_testsuite_dir (self): + def __localize_testsuite_dir(self): """If testsuite_dir is remote, fetch a local copy. Memorize the local location always.""" - os.chdir (self.workdir) + os.chdir(self.workdir) - self.local_testsuite_dir = \ - hashlib.sha1(self.o.testsuite_dir.encode()).hexdigest() + self.local_testsuite_dir = hashlib.sha1( + self.o.testsuite_dir.encode() + ).hexdigest() # Exclude non qualification tests and internal reports aimed at our # intranet from the transfer. All useless and potentially confusing. @@ -818,108 +842,111 @@ def __localize_testsuite_dir (self): # STR subdir contents entirely. There's no binary there, and artifacts # we all need to produce the STR after the copy (e.g. Makefile). - run ("rsync -arz --delete --delete-excluded %s/ %s %s" % ( - self.o.testsuite_dir, self.local_testsuite_dir, - ' '.join (("--exclude=/tests", - "--exclude=/output", - "--exclude=/rep_gnatcov*", - "--exclude=*.o", - "--exclude=*.obj", - "--exclude=*.exe", - "--exclude=*.trace", - "--exclude=*.dmap", - "--include=*.*", - "--include=*/", - "--include=/STR/**", - "--exclude=*")))) - - self.log ( - "testsuite-dir %s fetched as %s" % ( - self.o.testsuite_dir, self.local_testsuite_dir) + run( + "rsync -arz --delete --delete-excluded %s/ %s %s" + % ( + self.o.testsuite_dir, + self.local_testsuite_dir, + " ".join( + ( + "--exclude=/tests", + "--exclude=/output", + "--exclude=/rep_gnatcov*", + "--exclude=*.o", + "--exclude=*.obj", + "--exclude=*.exe", + "--exclude=*.trace", + "--exclude=*.dmap", + "--include=*.*", + "--include=*/", + "--include=/STR/**", + "--exclude=*", + ) + ), ) + ) + + self.log( + "testsuite-dir %s fetched as %s" + % (self.o.testsuite_dir, self.local_testsuite_dir) + ) - self.local_testsuite_dir = \ - os.path.abspath (self.local_testsuite_dir) + self.local_testsuite_dir = os.path.abspath(self.local_testsuite_dir) # --------------------- # -- prepare_str_dir -- # --------------------- - def __prepare_str_dir (self): + def __prepare_str_dir(self): """Helper for build_str. If we haven't done it already, arrange to generate the STR REST for the designated testsuite-dir, possibly remote. Fetch this dir back as needed then and remember where the corresponding STR subdir (with REST generated) is located.""" - announce ("preparing STR dir @ %s" % self.o.testsuite_dir) + announce("preparing STR dir @ %s" % self.o.testsuite_dir) # Produce REST from the tests results dropped by testsuite run. If we # did not launch one just above, expect results to be available from a # previous run, possibly remote: - raccess = raccess_in (self.o.testsuite_dir) - rdir = rdir_in (self.o.testsuite_dir) + raccess = raccess_in(self.o.testsuite_dir) + rdir = rdir_in(self.o.testsuite_dir) - mkstr_cmd = ( - "(cd %(dir)s/STR && ./mkrest.sh %(level)s)" - % {"dir" : self.o.testsuite_dir if not rdir else rdir, - "level" : self.o.dolevel} - ) + mkstr_cmd = "(cd %(dir)s/STR && ./mkrest.sh %(level)s)" % { + "dir": self.o.testsuite_dir if not rdir else rdir, + "level": self.o.dolevel, + } prefix = ["sh", "-c"] if not raccess else ["ssh", raccess] - run_list (prefix + [mkstr_cmd]) + run_list(prefix + [mkstr_cmd]) # --------------- # -- build_str -- # --------------- - def build_str (self): - announce ("building %s STR" % self.this_docformat) + def build_str(self): + announce("building %s STR" % self.this_docformat) - os.chdir (os.path.join (self.local_testsuite_dir, "STR")) + os.chdir(os.path.join(self.local_testsuite_dir, "STR")) - run ("make %s" % sphinx_target_for[self.this_docformat]) + run("make %s" % sphinx_target_for[self.this_docformat]) - self.__latch_into ( - dir=self.itemsdir(), part='str', toplevel=False) + self.__latch_into(dir=self.itemsdir(), part="str", toplevel=False) # ----------------- # -- build_plans -- # ----------------- - def build_plans (self): + def build_plans(self): plans_root = os.path.join(self.repodir, "qualification", "qm", "plans") trace_specific_content = [ os.path.join( - plans_root, - "Tool_Qualification_Plan", - "Qualified_Interface" + plans_root, "Tool_Qualification_Plan", "Qualified_Interface" ) ] self.prepare_content(trace_specific_content) - self.__qm_build (part="plans") + self.__qm_build(part="plans") # --------------- # -- build_kit -- # --------------- def __relocate_into(self, dir, part): - the_item = self.kititem_for(part=part) - item_source_path = os.path.join (self.itemsdir(), the_item) - item_target_path = os.path.join (dir, the_item) + item_source_path = os.path.join(self.itemsdir(), the_item) + item_target_path = os.path.join(dir, the_item) - remove (item_target_path) + remove(item_target_path) print("move : %s" % item_source_path) print("into : %s" % dir) - mv (item_source_path, dir) + mv(item_source_path, dir) - def build_kit (self): - announce ("building %s kit" % self.this_docformat) + def build_kit(self): + announce("building %s kit" % self.this_docformat) - os.chdir (self.workdir) + os.chdir(self.workdir) # The kit name is computed as: # @@ -933,74 +960,72 @@ def build_kit (self): gitbranch = current_gitbranch_at(self.repodir) kitprefix = ( - "gnatcov-qualkit" if "qualkit" not in gitbranch - else "gnatcov" - ) + "gnatcov-qualkit" if "qualkit" not in gitbranch else "gnatcov" + ) kitid = gitbranch - kitid = kitid.replace('/', '-') - kitid = kitid.replace('.', '_') + kitid = kitid.replace("/", "-") + kitid = kitid.replace(".", "_") # If we are re-constructing a kit with some parts just rebuilt, target # the specified version (stamp) and arrange to keep the old elements # in place: kitstamp = ( - self.o.rekit if self.o.rekit + self.o.rekit + if self.o.rekit else "%4d%02d%02d" % (today.year, today.month, today.day) - ) + ) kitname = "%s-%s-%s" % (kitprefix, kitid, kitstamp) kitdir = "%s-%s" % (kitname, self.this_docformat) - mkdir (kitdir) + mkdir(kitdir) - [self.__relocate_into (dir=kitdir, part=part) for part in self.o.parts] + [self.__relocate_into(dir=kitdir, part=part) for part in self.o.parts] - run ("zip -q -r %(kitdir)s.zip %(kitdir)s" % {"kitdir": kitdir}) + run("zip -q -r %(kitdir)s.zip %(kitdir)s" % {"kitdir": kitdir}) # ----------------------- # -- zip_testsuite_dir -- # ----------------------- def zip_testsuite_dir(self): + os.chdir(self.workdir) - os.chdir (self.workdir) - - relative_testsuite_dir = os.path.basename (self.local_testsuite_dir) + relative_testsuite_dir = os.path.basename(self.local_testsuite_dir) zipname = "%s.zip" % relative_testsuite_dir - remove (zipname) - run ("zip -q -r %s %s" % (zipname, relative_testsuite_dir)) + remove(zipname) + run("zip -q -r %s %s" % (zipname, relative_testsuite_dir)) # --------------------- # -- build_as_needed -- # --------------------- - def do_str (self): - return 'str' in self.o.parts + def do_str(self): + return "str" in self.o.parts - def do_tor (self): - return 'tor' in self.o.parts + def do_tor(self): + return "tor" in self.o.parts - def do_plans (self): - return 'plans' in self.o.parts + def do_plans(self): + return "plans" in self.o.parts - def do_kit (self): + def do_kit(self): return self.o.kitp - def build_as_needed (self, docformat): - + def build_as_needed(self, docformat): self.passno += 1 self.this_docformat = docformat - mkdir (self.itemsdir()) + mkdir(self.itemsdir()) if self.do_str() and self.passno == 1: self.__prepare_str_dir() if self.o.testsuite_dir and not self.local_testsuite_dir: - self.__localize_testsuite_dir () + self.__localize_testsuite_dir() # Build the STR as needed, using the REST generated # by prepare_str_dir above: @@ -1024,169 +1049,205 @@ def build_as_needed (self, docformat): if self.do_kit(): qmat.build_kit() + # ======================================================================= # == MAIN SCRIPT BODY == # ======================================================================= -valid_docformats = ('html', 'pdf') -valid_parts = ('tor', 'plans', 'str') -valid_dolevels = ('doA', 'doB', 'doC') -valid_xada = ('95', '2005', '2012') -valid_languages = ["Ada%s" % version for version in valid_xada] +valid_docformats = ("html", "pdf") +valid_parts = ("tor", "plans", "str") +valid_dolevels = ("doA", "doB", "doC") +valid_xada = ("95", "2005", "2012") +valid_languages = ["Ada%s" % version for version in valid_xada] valid_trace_modes = ("src", "bin") + def commandline(): """Build and return an OptionParser instance for this script.""" op = optparse.OptionParser(usage="%prog ") - op.add_option ( - "--work-dir", dest="workdir", + op.add_option( + "--work-dir", + dest="workdir", help=( "Name of a directory from where a previous kit construction " - "will resume. Must exist already.") - ) + "will resume. Must exist already." + ), + ) - op.add_option ( - "--git-source", dest="gitsource", default=None, + op.add_option( + "--git-source", + dest="gitsource", + default=None, help=( "Git repo we should be cloning to get our source artifacts. " "!! This overrides whatever is in a --work-dir already !!" - ) - ) - op.add_option ( - "--git-pull", dest="gitpull", action="store_true", default=False, + ), + ) + op.add_option( + "--git-pull", + dest="gitpull", + action="store_true", + default=False, help=( "Pull commits from current origin in the git clone setup " "in work-dir." - ) - ) - op.add_option ( - "--git-reuse", dest="gitreuse", action="store_true", default=False, - help=( - "Reuse current git clone setup in work-dir, as-is. " - ) - ) - op.add_option ( - "--git-rsync", dest="gitrsync", default=False, - help=( - "Rsync an existing git repo into our git clone dir." - ) - ) - op.add_option ( - "--branch", dest="branchname", default=None, - help = ( - "The git branch we shall produce the material from.") - ) + ), + ) + op.add_option( + "--git-reuse", + dest="gitreuse", + action="store_true", + default=False, + help=("Reuse current git clone setup in work-dir, as-is. "), + ) + op.add_option( + "--git-rsync", + dest="gitrsync", + default=False, + help=("Rsync an existing git repo into our git clone dir."), + ) + op.add_option( + "--branch", + dest="branchname", + default=None, + help=("The git branch we shall produce the material from."), + ) - op.add_option ( - "--docformat", dest="docformat", - type='string', # choices=valid_docformats, - help = ( + op.add_option( + "--docformat", + dest="docformat", + type="string", # choices=valid_docformats, + help=( "The format we need to produce for each document. " - "At least one of %s. Multiple values separated by ','." \ - % valid_docformats.__str__()) - ) - op.add_option ( - "--parts", dest="parts", default=None, - help = ( + "At least one of %s. Multiple values separated by ','." + % valid_docformats.__str__() + ), + ) + op.add_option( + "--parts", + dest="parts", + default=None, + help=( "A comma separated list of the parts of the qualkit that " - "are to be generated, subset of %s." % valid_parts.__str__()) - ) + "are to be generated, subset of %s." % valid_parts.__str__() + ), + ) - op.add_option ( - "--dolevel", dest="dolevel", default=None, - type='choice', choices=valid_dolevels, - help = ( - "Target DO178 qualification level. One of %s." \ - % valid_dolevels.__str__()) - ) + op.add_option( + "--dolevel", + dest="dolevel", + default=None, + type="choice", + choices=valid_dolevels, + help=( + "Target DO178 qualification level. One of %s." + % valid_dolevels.__str__() + ), + ) - op.add_option ( - "--languages", dest="languages", default=None, - help = ( + op.add_option( + "--languages", + dest="languages", + default=None, + help=( "Comma separated list of languages, for traceability matrix " - "purposes. Amongst %s." % valid_languages.__str__()) - ) + "purposes. Amongst %s." % valid_languages.__str__() + ), + ) - op.add_option ( - "--testsuite-dir", dest="testsuite_dir", default=None, - help = ( - "Name of a directory where the testsuite was run") - ) + op.add_option( + "--testsuite-dir", + dest="testsuite_dir", + default=None, + help=("Name of a directory where the testsuite was run"), + ) - op.add_option ( - "--rekit", dest="rekit", default=None, - help = ( + op.add_option( + "--rekit", + dest="rekit", + default=None, + help=( "rebuild the specified --parts and re-package them in the " - "kit stamped according to this option's value (YYYYMMDD)") - ) + "kit stamped according to this option's value (YYYYMMDD)" + ), + ) - op.add_option ( - "--xgnatpro", dest="xgnatpro", default=None, - help = ( + op.add_option( + "--xgnatpro", + dest="xgnatpro", + default=None, + help=( "Version we expect -gcc -v to match. " - "Mandatory when producing a kit") - ) - op.add_option ( - "--xgnatcov", dest="xgnatcov", default=None, - help = ( + "Mandatory when producing a kit" + ), + ) + op.add_option( + "--xgnatcov", + dest="xgnatcov", + default=None, + help=( "Version we expect gnatcov --version to match. " - "Mandatory when producing a kit") - ) - op.add_option ( - "--xgnatemu", dest="xgnatemu", default=None, - help = ( - "Version we expect -gnatcov --version to match.") - ) + "Mandatory when producing a kit" + ), + ) + op.add_option( + "--xgnatemu", + dest="xgnatemu", + default=None, + help=("Version we expect -gnatcov --version to match."), + ) - op.add_option ( - "--xada", dest="xada", default=None, choices=valid_xada, - help = ( - "Version of the Ada language we are qualifying for (%s)" % \ - '|'.join(valid_xada) - ) - ) + op.add_option( + "--xada", + dest="xada", + default=None, + choices=valid_xada, + help=( + "Version of the Ada language we are qualifying for (%s)" + % "|".join(valid_xada) + ), + ) - op.add_option ( + op.add_option( "--trace-mode", dest="trace_mode", default=None, choices=valid_trace_modes, - help="Trace kind we are qualifying gnatcov for. One of 'src' or 'bin'" + help="Trace kind we are qualifying gnatcov for. One of 'src' or 'bin'", ) return op -def check_valid(options, args): +def check_valid(options, args): # We are producing qualification material. Better know what we're # aiming at, always: - exit_if ( - not options.dolevel, - "Please specify an explicit dolevel (--dolevel)." - ) + exit_if( + not options.dolevel, "Please specify an explicit dolevel (--dolevel)." + ) - exit_if ( + exit_if( not options.trace_mode, - "Please specify an explicit trace-mode (--trace-mode)." - ) + "Please specify an explicit trace-mode (--trace-mode).", + ) # Generating docs can be pretty long. Better make sure the output format # was intentionally stated: - exit_if ( + exit_if( not options.docformat, - ("Please specify the desired output format (--docformat).") - ) + ("Please specify the desired output format (--docformat)."), + ) # Likewise for the git branch name: - exit_if ( + exit_if( not options.branchname, - ("Please specify the git branch name (--branch).") - ) + ("Please specify the git branch name (--branch)."), + ) # Convey whether we are requested to produce a kit: @@ -1195,50 +1256,50 @@ def check_valid(options, args): # Settle on the set of documents we are to produce: options.parts = ( - valid_parts if not options.parts - else options.parts.split(',') - ) + valid_parts if not options.parts else options.parts.split(",") + ) - [exit_if ( + [ + exit_if( part not in valid_parts, - "Requested part '%s' is invalid, none of %s" \ - % (part, valid_parts.__str__()) - ) - for part in options.parts] + "Requested part '%s' is invalid, none of %s" + % (part, valid_parts.__str__()), + ) + for part in options.parts + ] # work dir - exit_if ( - not options.workdir, - "A work dir must be specified (--work-dir)" - ) + exit_if(not options.workdir, "A work dir must be specified (--work-dir)") - warn_if ( - options.kitp and os.path.exists (options.workdir) + warn_if( + options.kitp + and os.path.exists(options.workdir) and ls("%s/*" % options.workdir), - "producing kit within non empty workdir") + "producing kit within non empty workdir", + ) # Producing a STR requires a testsuite dir - exit_if ( - 'str' in options.parts and not options.testsuite_dir, - "--testsuite-dir required when producing a STR" - ) + exit_if( + "str" in options.parts and not options.testsuite_dir, + "--testsuite-dir required when producing a STR", + ) # GIT aspects: - exit_if ( + exit_if( options.gitpull and options.gitsource, "Specifying git source is incompatible with " - "request to pull from current origin" - ) + "request to pull from current origin", + ) # In case we produce TOR/LRM traceability matrixes ... - exit_if ( + exit_if( not options.languages, - "Please specify the qualified languages (--languages)" - ) + "Please specify the qualified languages (--languages)", + ) # -xada, -xgnatcov etc @@ -1249,20 +1310,19 @@ def check_valid(options, args): if __name__ == "__main__": - (options, args) = commandline().parse_args() - check_valid (options, args) + check_valid(options, args) # Make sure that directory options are absolute dirs, to # facilitate switching back and forth from one to the other: - if options.testsuite_dir and not raccess_in (options.testsuite_dir): - options.testsuite_dir = os.path.abspath (options.testsuite_dir) + if options.testsuite_dir and not raccess_in(options.testsuite_dir): + options.testsuite_dir = os.path.abspath(options.testsuite_dir) # Instanciate our helper and proceed with the base directory setup: - qmat = QMAT (options=options) + qmat = QMAT(options=options) qmat.setup_workdir() qmat.git_update() @@ -1275,7 +1335,7 @@ def check_valid(options, args): # Build the various parts and maybe the kit for each requested format: - [qmat.build_as_needed (docformat=f) for f in options.docformat.split(',')] + [qmat.build_as_needed(docformat=f) for f in options.docformat.split(",")] if options.kitp: qmat.zip_testsuite_dir() diff --git a/qualification/qm/common_conf.py b/qualification/qm/common_conf.py index 992ffd3ee..f3ac04475 100644 --- a/qualification/qm/common_conf.py +++ b/qualification/qm/common_conf.py @@ -1,52 +1,59 @@ from collections import OrderedDict from datetime import date -project_name = 'GNATcoverage' -project_name_it = '*%s*' % project_name -owner = 'AdaCore' +project_name = "GNATcoverage" +project_name_it = "*%s*" % project_name +owner = "AdaCore" users = { - 'unassigned': {'name': 'Unassigned', - 'company': '', - 'email': '', - 'team': ''}, - - 'hainque': {'name': 'Olivier Hainque', - 'company': owner, - 'email': 'hainque@adacore.com', - 'team': 'Qualification'}, - - 'guitton': {'name': 'Jerome Guitton', - 'company': owner, - 'email': 'guitton@adacore.com', - 'team': 'Qualification'}, - - 'leguillou': {'name': 'Erwan Leguillou', - 'company': owner, - 'email': 'leguillou@adacore.com', - 'team': 'Qualification'}, - - 'fofanov': {'name': 'Vasily Fofanov', - 'company': owner, - 'email': 'fofanov@adacore.com', - 'team': 'Qualification'}} + "unassigned": { + "name": "Unassigned", + "company": "", + "email": "", + "team": "", + }, + "hainque": { + "name": "Olivier Hainque", + "company": owner, + "email": "hainque@adacore.com", + "team": "Qualification", + }, + "guitton": { + "name": "Jerome Guitton", + "company": owner, + "email": "guitton@adacore.com", + "team": "Qualification", + }, + "leguillou": { + "name": "Erwan Leguillou", + "company": owner, + "email": "leguillou@adacore.com", + "team": "Qualification", + }, + "fofanov": { + "name": "Vasily Fofanov", + "company": owner, + "email": "fofanov@adacore.com", + "team": "Qualification", + }, +} roles = OrderedDict( - [('authors', {'description': 'the authors of the document'}), - ('reviewers', {'description': 'the reviewers of the document'})]) + [ + ("authors", {"description": "the authors of the document"}), + ("reviewers", {"description": "the reviewers of the document"}), + ] +) -assignments = { - 'authors': ['hainque'], - 'reviewers': ['unassigned'] -} +assignments = {"authors": ["hainque"], "reviewers": ["unassigned"]} -release = 'DRAFT 0.0' -version = '(version %s)' % release +release = "DRAFT 0.0" +version = "(version %s)" % release -copyright = '%s, %d' % (owner, date.today().year) +copyright = "%s, %d" % (owner, date.today().year) -extensions = ['sphinx.ext.ifconfig'] +extensions = ["sphinx.ext.ifconfig"] -tor_doc_id = 'PE.' -str_doc_id = 'PE.' -plans_doc_id = 'PE.' +tor_doc_id = "PE." +str_doc_id = "PE." +plans_doc_id = "PE." diff --git a/qualification/qm/env/env.py b/qualification/qm/env/env.py index cb5ab894d..ffb3b38c2 100644 --- a/qualification/qm/env/env.py +++ b/qualification/qm/env/env.py @@ -1,5 +1,7 @@ -{"gnat" : "powerpc-elf", - "version" : "7.0.3", - "switches" : ["-O1 -fpreserve-control-flow"], - "coding standard" : "", - "project_full" : "SomeProject"} +{ + "gnat": "powerpc-elf", + "version": "7.0.3", + "switches": ["-O1 -fpreserve-control-flow"], + "coding standard": "", + "project_full": "SomeProject", +} diff --git a/qualification/qm/genmodel.py b/qualification/qm/genmodel.py index f67a72e1d..7afa4501a 100755 --- a/qualification/qm/genmodel.py +++ b/qualification/qm/genmodel.py @@ -16,32 +16,41 @@ import sys, optparse, re from e3.os.process import Run -def exit_if (p, msg): + +def exit_if(p, msg): if p: print(msg) sys.exit(1) + def contents_of(filename): with open(filename) as fd: return fd.read() + def __extra_block_for(dolevel): """Allow level specific local subsets of testcases.""" - return '\n'.join( - ('', - '', - ' ', - ' ', - ' ', - ' ', - '')) - -RE_LANG="([a-zA-Z]*)([0-9]*)" + return "\n".join( + ( + "", + '', + " ", + ' ', + ' ', + " ", + "", + ) + ) + + +RE_LANG = "([a-zA-Z]*)([0-9]*)" + def __langdir_for(lang): # Requirements for all the versions Ada are all under Ada/ etc; @@ -49,33 +58,42 @@ def __langdir_for(lang): # to search: return re.match(RE_LANG, string=lang).group(1) + def __langversion_for(lang): return re.match(RE_LANG, string=lang).group(2) -def __reqset_triggers_for (lang, chapter): - return '\n'.join( - ('')) +def __reqset_triggers_for(lang, chapter): + return "\n".join( + ( + "", + ) + ) + def __langlevel_triggers_for(dolevel, languages): """Triggers so only the language/criterion sections of relevance are included.""" chapters_for = { - 'doC': ['stmt'], - 'doB': ['stmt', 'decision'], - 'doA': ['stmt', 'decision', 'mcdc'] - } - - return '\n'+'\n'.join( - (__reqset_triggers_for(lang, chapter) - for lang in languages - for chapter in chapters_for[dolevel]) + "doC": ["stmt"], + "doB": ["stmt", "decision"], + "doA": ["stmt", "decision", "mcdc"], + } + + return "\n" + "\n".join( + ( + __reqset_triggers_for(lang, chapter) + for lang in languages + for chapter in chapters_for[dolevel] ) + ) + def __gen_model_for(dolevel, languages): """Generate model.xml from template.xml""" @@ -84,19 +102,18 @@ def __gen_model_for(dolevel, languages): ada_lang = [l for l in languages if "Ada" in l][0] - with open('model.xml', 'w') as f: + with open("model.xml", "w") as f: f.write( - contents_of("template.xml") % { - 'langlevel_reqset_triggers': - __langlevel_triggers_for (dolevel=dolevel, - languages=languages), - 'ada_version': - __langversion_for(ada_lang), - - 'extra_block': - __extra_block_for(dolevel=dolevel) - } - ) + contents_of("template.xml") + % { + "langlevel_reqset_triggers": __langlevel_triggers_for( + dolevel=dolevel, languages=languages + ), + "ada_version": __langversion_for(ada_lang), + "extra_block": __extra_block_for(dolevel=dolevel), + } + ) + def __gen_lrm_ref_for(lang): """Generate lrm_ref_.txt from lrm_ref.txt, filtering @@ -105,8 +122,8 @@ def __gen_lrm_ref_for(lang): lang_version = __langversion_for(lang) - input = open ("LRM/lrm_ref.txt", mode='r') - output = open ("LRM/lrm_ref_%s.txt" % lang_version, mode='w') + input = open("LRM/lrm_ref.txt", mode="r") + output = open("LRM/lrm_ref_%s.txt" % lang_version, mode="w") # The reference matrix lines with section numbers and corresponding # language versions are of the form: @@ -124,7 +141,6 @@ def __gen_lrm_ref_for(lang): short_version = lang_version[-2:] for line in input.readlines(): - m = re.match(pattern="([0-9. ]*)#([0-9, ]*?)#", string=line) if m and short_version not in m.group(2): continue @@ -134,50 +150,50 @@ def __gen_lrm_ref_for(lang): output.close() input.close() + # ======================================================================= # == MAIN SCRIPT BODY == # ======================================================================= -valid_dolevels = ('doA', 'doB', 'doC') -valid_languages = ('Ada95', 'Ada2005', 'Ada2012') +valid_dolevels = ("doA", "doB", "doC") +valid_languages = ("Ada95", "Ada2005", "Ada2012") if __name__ == "__main__": - op = optparse.OptionParser(usage="%prog ") - op.add_option ( - "--dolevel", dest="dolevel", default=None, - type='choice', choices=valid_dolevels, - help = ( - "Target DO178 qualification level. One of %s." \ - % valid_dolevels.__str__()) - ) - - op.add_option ( - "--languages", dest="languages", default=None, - help = ( - "comma separated list of languages amongst %s" \ - % valid_languages.__str__()) - ) + op.add_option( + "--dolevel", + dest="dolevel", + default=None, + type="choice", + choices=valid_dolevels, + help=( + "Target DO178 qualification level. One of %s." + % valid_dolevels.__str__() + ), + ) + + op.add_option( + "--languages", + dest="languages", + default=None, + help=( + "comma separated list of languages amongst %s" + % valid_languages.__str__() + ), + ) (options, args) = op.parse_args() - exit_if ( - not options.dolevel, - "Please specify a DO level (--dolevel)." - ) + exit_if(not options.dolevel, "Please specify a DO level (--dolevel).") - exit_if ( - not options.languages, - "Please specify languages (--languages)." - ) + exit_if(not options.languages, "Please specify languages (--languages).") - languages=options.languages.split(',') + languages = options.languages.split(",") # should check that there is only one instance of a given # language (e.g. only one Ada) __gen_model_for(dolevel=options.dolevel, languages=languages) - [__gen_lrm_ref_for(lang=lang) - for lang in languages if "Ada" in lang] + [__gen_lrm_ref_for(lang=lang) for lang in languages if "Ada" in lang] diff --git a/qualification/qm/plans/qmconf.py b/qualification/qm/plans/qmconf.py index c0f94f8c1..3b3386119 100644 --- a/qualification/qm/plans/qmconf.py +++ b/qualification/qm/plans/qmconf.py @@ -6,16 +6,15 @@ common_file = os.path.join( os.path.dirname( os.path.dirname( - os.path.dirname( - os.path.dirname( - os.path.abspath(__file__))))), - "common_conf.py") + os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + ) + ), + "common_conf.py", +) if os.path.isfile(common_file): execfile(common_file) - execfile(os.path.join( - os.path.dirname(common_file), - "qm_prolog.py")) + execfile(os.path.join(os.path.dirname(common_file), "qm_prolog.py")) else: print("Couldn't find common configuration file") print(common_file) diff --git a/qualification/qm/qm_plugins/generate_doc.py b/qualification/qm/qm_plugins/generate_doc.py index 39ae4085c..4388dfcd0 100644 --- a/qualification/qm/qm_plugins/generate_doc.py +++ b/qualification/qm/qm_plugins/generate_doc.py @@ -2,28 +2,39 @@ import qm import qm.rest.pdfgenerator + def get_userconf(): - # retrieve the author from the environment data artifact - env = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'env.py') - with open(env,"r") as fd: - envdata = eval(fd.read()) + # retrieve the author from the environment data artifact + env = os.path.join(os.path.dirname(os.path.dirname(__file__)), "env.py") + with open(env, "r") as fd: + envdata = eval(fd.read()) + + author = "AdaCore for %s" % (envdata["project_full"]) - author = "AdaCore for %s" % (envdata['project_full']) + return author - return author class GenPDF(qm.rest.pdfgenerator.SphinxGeneratePdf): def userconf(self): # use method from super just to retrieve the 'extras' field - [ author, version, extras ] = qm.rest.pdfgenerator.SphinxGeneratePdf.userconf (self) + [ + author, + version, + extras, + ] = qm.rest.pdfgenerator.SphinxGeneratePdf.userconf(self) author = get_userconf() return [author, version, extras] + class GenHTML(qm.rest.pdfgenerator.SphinxGenerateHtml): def userconf(self): # use method from super just to retrieve the 'extras' field - [ author, version, extras ] = qm.rest.pdfgenerator.SphinxGenerateHtml.userconf (self) + [ + author, + version, + extras, + ] = qm.rest.pdfgenerator.SphinxGenerateHtml.userconf(self) author = get_userconf() return [author, version, extras] diff --git a/qualification/qm/qm_plugins/importers.py b/qualification/qm/qm_plugins/importers.py index 50a787ae5..9ff4bc3f9 100644 --- a/qualification/qm/qm_plugins/importers.py +++ b/qualification/qm/qm_plugins/importers.py @@ -19,15 +19,12 @@ def class_to_string(a): :param a: the artifact :type a: artifact """ - d = {'TORReq_Set': 'rqg', - 'TORReq': 'rq', - 'TC': 'tc', - 'TC_Set': 'tcg'} - - if 'Appendix' in a.full_name: - return 'app' - elif a.name == 'OpEnviron': - return 'env' + d = {"TORReq_Set": "rqg", "TORReq": "rq", "TC": "tc", "TC_Set": "tcg"} + + if "Appendix" in a.full_name: + return "app" + elif a.name == "OpEnviron": + return "env" elif a.__class__.__name__ in d: return d[a.__class__.__name__] else: @@ -44,15 +41,16 @@ def class_to_content_key(a): """ # keys in the model are dependant of the artifact class - d = {'TORReq_Set': 'set_content', - 'TORReq': 'requirement', - 'TC': 'tc_content', - 'TC_Set': 'tc_set_content', - } - - if 'Appendix' in a.full_name: - return 'app' - elif a.name == 'OpEnviron': + d = { + "TORReq_Set": "set_content", + "TORReq": "requirement", + "TC": "tc_content", + "TC_Set": "tc_set_content", + } + + if "Appendix" in a.full_name: + return "app" + elif a.name == "OpEnviron": # OpEnv only is content, not container return None elif a.__class__.__name__ in d: @@ -65,13 +63,16 @@ def class_to_content_key(a): # Tests on artifact class # ########################### + def is_req(a): from qm import TORReq + return isinstance(a, TORReq) def is_reqset(a): from qm import TORReq_Set + return isinstance(a, TORReq_Set) @@ -81,11 +82,13 @@ def is_req_or_set(a): def is_tc(a): from qm import TC + return isinstance(a, TC) def is_tcset(a): from qm import TC_Set + return isinstance(a, TC_Set) @@ -95,6 +98,7 @@ def is_tc_or_set(a): def is_test_result(a): from qm import TR + return isinstance(a, TR) @@ -106,16 +110,18 @@ def is_lrm_section(a): def is_source(a): from qm import Source_files + return isinstance(a, Source_files) def is_consolidation(a): from qm import Conso_Sources + return isinstance(a, Conso_Sources) def is_helper(source_resource): - return not(is_driver(source_resource) or is_functional(source_resource)) + return not (is_driver(source_resource) or is_functional(source_resource)) def is_driver(source_resource): @@ -141,6 +147,7 @@ def is_functional(source_resource): # Utils # ######### + def get_short_description(artifact): """ Get the first line of a file as the short description. @@ -158,7 +165,7 @@ def get_short_description(artifact): if len(line) > 0: # ** has to be removed # from short_description when used in tables - first_line = line.replace('**', '') + first_line = line.replace("**", "") break return first_line @@ -172,8 +179,11 @@ def get_first_req_relative(artifact): :type artifact: artifact """ parent = artifact.relative_to - return (parent if (parent is None or is_req(parent)) - else get_first_req_relative(parent)) + return ( + parent + if (parent is None or is_req(parent)) + else get_first_req_relative(parent) + ) def write_artifact_ref(artifact_full_name, label=None): @@ -190,9 +200,9 @@ def write_artifact_ref(artifact_full_name, label=None): if label is None: label = artifact_full_name - return writer.role('ref', - '%s <%s>' % (label, - artifact_full_name.replace('/', '_')[1:])) + return writer.role( + "ref", "%s <%s>" % (label, artifact_full_name.replace("/", "_")[1:]) + ) def kind_of(artifact): @@ -200,11 +210,17 @@ def kind_of(artifact): :param artifact: the artifact :type artifact: artifact """ - return ("Requirement Group" if is_reqset(artifact) - else "Requirement" if is_req(artifact) - else "Testcase Group" if is_tcset(artifact) - else "Testcase" if is_tc(artifact) - else "Chapter") + return ( + "Requirement Group" + if is_reqset(artifact) + else "Requirement" + if is_req(artifact) + else "Testcase Group" + if is_tcset(artifact) + else "Testcase" + if is_tc(artifact) + else "Chapter" + ) def short_kind_of(artifact): @@ -226,13 +242,15 @@ def relative_links_for(artifact): req = get_first_req_relative(artifact) if req: output += writer.paragraph( - "**Parent Requirement**: %s\n\n" % writer.qmref(req.full_name)) + "**Parent Requirement**: %s\n\n" % writer.qmref(req.full_name) + ) ancestor = artifact.relative_to if ancestor and ancestor != req: output += writer.paragraph( - "**Parent %s**: %s\n\n" % - (short_kind_of(ancestor), write_artifact_ref(ancestor.full_name))) + "**Parent %s**: %s\n\n" + % (short_kind_of(ancestor), write_artifact_ref(ancestor.full_name)) + ) return output @@ -252,6 +270,7 @@ def default_importer(artifact): else: return qm.rest.DefaultImporter() + #################################################################### # Importers @@ -282,9 +301,8 @@ def qmlink_to_rest(self, parent, artifacts): for a in artifacts: if is_lrm_section(a): - if not language_version: - language_version = a.attributes['language'].strip() + language_version = a.attributes["language"].strip() ref = {} for children in a.derived_to: @@ -295,9 +313,12 @@ def qmlink_to_rest(self, parent, artifacts): if parent not in ref.keys(): ref[parent] = [] - ref[parent].append([child.full_name, - child.full_name.replace( - parent, '')]) + ref[parent].append( + [ + child.full_name, + child.full_name.replace(parent, ""), + ] + ) pdf_tc_list = "" html_tc_list = "" @@ -305,62 +326,86 @@ def qmlink_to_rest(self, parent, artifacts): html_comment = "" for req in ref.keys(): - pdf_other_tcs = "" html_tcs = "" if len(ref[req]) > 1: - pdf_other_tcs = "%s + %d other tests" % \ - (writer.role("raw-latex", r'\newline'), - (len(ref[req]) - 1)) - - html_tcs = writer.role("raw-html", r'
').join( - [write_artifact_ref(k[0], - label=k[1]) for k in ref[req]]) - - requirement_str = "Req: %s" % \ - write_artifact_ref(req, - req.replace(REQ_NAME_PREFIX, - '')).strip() - first_tc_str = "* TC: %s" % \ - write_artifact_ref(ref[req][0][0], - label=ref[req][0][1]).strip() + pdf_other_tcs = "%s + %d other tests" % ( + writer.role("raw-latex", r"\newline"), + (len(ref[req]) - 1), + ) + + html_tcs = writer.role("raw-html", r"
").join( + [ + write_artifact_ref(k[0], label=k[1]) + for k in ref[req] + ] + ) + + requirement_str = ( + "Req: %s" + % write_artifact_ref( + req, req.replace(REQ_NAME_PREFIX, "") + ).strip() + ) + first_tc_str = ( + "* TC: %s" + % write_artifact_ref( + ref[req][0][0], label=ref[req][0][1] + ).strip() + ) pdf_tc_list += "%s %s %s %s %s " % ( requirement_str, - writer.role("raw-latex", r'\newline'), + writer.role("raw-latex", r"\newline"), first_tc_str, pdf_other_tcs, - writer.role("raw-latex", r'\newline')) + writer.role("raw-latex", r"\newline"), + ) html_tc_list += "%s %s * TC: %s %s " % ( requirement_str, - writer.role("raw-html", r'
'), + writer.role("raw-html", r"
"), html_tcs, - writer.role("raw-html", r'
')) + writer.role("raw-html", r"
"), + ) - applicable = a.attributes['relevance'].strip() + applicable = a.attributes["relevance"].strip() if pdf_tc_list != "": if applicable == "no" or applicable == "partial": relevance = applicable - comment = a.attributes['comment'].strip() - - pdf_comment = comment + ' ' + \ - writer.role("raw-latex", r'\newline') + ' ' - html_comment = comment + ' ' + \ - writer.role("raw-html", r'
') + ' ' + comment = a.attributes["comment"].strip() + + pdf_comment = ( + comment + + " " + + writer.role("raw-latex", r"\newline") + + " " + ) + html_comment = ( + comment + + " " + + writer.role("raw-html", r"
") + + " " + ) elif applicable == "yes": relevance = "yes" elif applicable == "no*": relevance = "no" - comment = "Section does not require SCA-related " + \ - "tests, but some are supplied " - - pdf_comment = comment + \ - writer.role("raw-latex", r'\newline') + ' ' - html_comment = comment + \ - writer.role("raw-html", r'
') + ' ' + comment = ( + "Section does not require SCA-related " + + "tests, but some are supplied " + ) + + pdf_comment = ( + comment + + writer.role("raw-latex", r"\newline") + + " " + ) + html_comment = ( + comment + writer.role("raw-html", r"
") + " " + ) else: relevance = "unexpected value %s" % applicable @@ -375,62 +420,85 @@ def qmlink_to_rest(self, parent, artifacts): else: if applicable == "no": relevance = "no" - comment = a.attributes['comment'].strip() + comment = a.attributes["comment"].strip() pdf_comment = comment - html_comment = comment + ' ' + \ - writer.role("raw-html", r'
') + ' ' + html_comment = ( + comment + + " " + + writer.role("raw-html", r"
") + + " " + ) elif applicable == "partial": relevance = "PARTIAL but not covered" - comment = a.attributes['comment'].strip() + comment = a.attributes["comment"].strip() pdf_comment = comment - html_comment = comment + ' ' + \ - writer.role("raw-html", r'
') + ' ' + html_comment = ( + comment + + " " + + writer.role("raw-html", r"
") + + " " + ) elif applicable == "yes": relevance = "YES but not covered" elif applicable == "no*": relevance = "NO but" - comment = "Indicated as no* in matrix." + \ - " Some test should be provided." + comment = ( + "Indicated as no* in matrix." + + " Some test should be provided." + ) pdf_comment = comment - html_comment = comment + ' ' + html_comment = comment + " " else: relevance = "unexpected value %s" % applicable - pdf_items.append(["%s" % a.full_name.replace('/', ''), - a.attributes['title'].strip(), - relevance, - pdf_comment]) - - html_items.append(["%s" % a.full_name.replace('/', ''), - a.attributes['title'].strip(), - relevance, - html_comment]) + pdf_items.append( + [ + "%s" % a.full_name.replace("/", ""), + a.attributes["title"].strip(), + relevance, + pdf_comment, + ] + ) + + html_items.append( + [ + "%s" % a.full_name.replace("/", ""), + a.attributes["title"].strip(), + relevance, + html_comment, + ] + ) pdf_table = writer.csv_table( pdf_items, title="TOR/LRM Traceability Matrix for Ada %s" % language_version, headers=["Section", "Title", "Applicable", "Comment"], - latex_format='|p{0.08\linewidth}|p{0.20\linewidth}|' + - 'p{0.10\linewidth}|p{0.50\linewidth}|') + latex_format="|p{0.08\linewidth}|p{0.20\linewidth}|" + + "p{0.10\linewidth}|p{0.50\linewidth}|", + ) html_table = writer.csv_table( html_items, headers=["Section", "Title", "Applicable", "Comment"], - widths=[8, 20, 10, 50]) - - output += writer.paragraph( - "This particular table is established for **Ada %s**." % - language_version + - "\n\The requirement identifiers in this table were shortened by " - "removing the *%s* common prefix.\n\n" % REQ_NAME_PREFIX) + \ - writer.only(pdf_table, "latex") + \ - writer.only(html_table, "html") + widths=[8, 20, 10, 50], + ) + + output += ( + writer.paragraph( + "This particular table is established for **Ada %s**." + % language_version + + "\n\The requirement identifiers in this table were shortened by " + "removing the *%s* common prefix.\n\n" % REQ_NAME_PREFIX + ) + + writer.only(pdf_table, "latex") + + writer.only(html_table, "html") + ) output += "\n\n" @@ -438,7 +506,6 @@ def qmlink_to_rest(self, parent, artifacts): class TCIndexImporter(ArtifactImporter): - def get_recursive_relatives(self, artifact, depth): """ Returns the list of the tc or tc_set children of an artifact @@ -462,7 +529,6 @@ def get_recursive_relatives(self, artifact, depth): return result def qmlink_to_rest(self, parent, artifacts): - html_items = [] pdf_items = [] output = "" @@ -473,39 +539,45 @@ def qmlink_to_rest(self, parent, artifacts): continue if is_tc_or_set(a): - reference = write_artifact_ref(a.full_name, - get_short_description(a)) - - html_items.append([writer.strong(class_to_string(a)), - writer.strong(a.name), - reference]) - pdf_items.append([class_to_string(a), - a.name, - reference]) + reference = write_artifact_ref( + a.full_name, get_short_description(a) + ) + + html_items.append( + [ + writer.strong(class_to_string(a)), + writer.strong(a.name), + reference, + ] + ) + pdf_items.append([class_to_string(a), a.name, reference]) for suba in self.get_recursive_relatives(a, 1): # We do include in the table children artifacts only # in html format. if is_tc(suba): - subref = write_artifact_ref(suba.full_name, - get_short_description(suba)) + subref = write_artifact_ref( + suba.full_name, get_short_description(suba) + ) if is_tcset(suba): subref = writer.qmref(suba.full_name) - html_items.append([class_to_string(suba), - "`..` %s" % suba.name, - subref]) + html_items.append( + [class_to_string(suba), "`..` %s" % suba.name, subref] + ) html_table = writer.csv_table( html_items, headers=["", "TestCases", "Description"], - widths=[3, 25, 65]) + widths=[3, 25, 65], + ) pdf_table = writer.csv_table( pdf_items, headers=["", "TestCases", "Description"], - widths=[3, 25, 65]).strip() + widths=[3, 25, 65], + ).strip() output += writer.only(html_table, "html") output += writer.only(pdf_table, "latex").strip() @@ -521,18 +593,20 @@ def qmlink_to_rest(self, parent, artifacts): links.append((a, default_importer(a))) output += writer.toctree( - ['/%s/content' % artifact_hash(*l) - for l in links - if not is_tc_or_set(l[0]) or is_tc_or_set(parent)], - hidden=True) + [ + "/%s/content" % artifact_hash(*l) + for l in links + if not is_tc_or_set(l[0]) or is_tc_or_set(parent) + ], + hidden=True, + ) return output, links class AppIndexImporter(ArtifactImporter): - def qmlink_to_rest(self, parent, artifacts): - return '', [] + return "", [] class RequirementImporter(ArtifactImporter): @@ -546,14 +620,15 @@ def to_rest(self, artifact): macro %REQ_ID% replaced by the requirement fullname """ - reference = ".. _%s:\n\n" % artifact.full_name.replace('/', '_')[1:] + reference = ".. _%s:\n\n" % artifact.full_name.replace("/", "_")[1:] - result = qm.rest.DefaultImporter().to_rest(artifact) + '\n\n' + result = qm.rest.DefaultImporter().to_rest(artifact) + "\n\n" - result = (reference + re.sub(pattern="%REQ_ID%", - repl="**REQUIREMENT** %s" % - artifact.full_name, - string=result)) + result = reference + re.sub( + pattern="%REQ_ID%", + repl="**REQUIREMENT** %s" % artifact.full_name, + string=result, + ) return result @@ -570,45 +645,42 @@ def to_rest(self, artifact): in order to keep them close in the final pdf generation """ - reference = ".. _%s:\n\n" % artifact.full_name.replace('/', '_')[1:] + reference = ".. _%s:\n\n" % artifact.full_name.replace("/", "_")[1:] result = "" qmlink = "" in_qmlink = False content = qm.rest.DefaultImporter().to_rest(artifact) for line in content.splitlines(): - if line.startswith('.. qmlink:: TCIndexImporter'): + if line.startswith(".. qmlink:: TCIndexImporter"): in_qmlink = True if in_qmlink: - qmlink += line + '\n' + qmlink += line + "\n" else: - result += line + '\n' + result += line + "\n" - result = reference + result + '\n\n' + result = reference + result + "\n\n" result += relative_links_for(artifact) - result = "|\n\n" + writer.minipage(result, r'\linewidth') + "\n\n" + \ - qmlink + result = ( + "|\n\n" + writer.minipage(result, r"\linewidth") + "\n\n" + qmlink + ) return result class ToplevelIndexImporter(ArtifactImporter): - def qmlink_to_rest(self, parent, artifacts): - items = [] html_top_index = "" for a in artifacts: - - items.append([writer.strong(a.name), - writer.qmref(a.full_name)]) + items.append([writer.strong(a.name), writer.qmref(a.full_name)]) if a.name == "Ada": def key(a): - d = {'stmt': 1, 'decision': 2, 'mcdc': 3} + d = {"stmt": 1, "decision": 2, "mcdc": 3} for k in d: if k in a.name: return d[k] @@ -620,94 +692,128 @@ def key(a): selected = a.relatives for suba in selected: - items.append(["`..` %s" % suba.name, - writer.qmref(suba.full_name)]) + items.append( + ["`..` %s" % suba.name, writer.qmref(suba.full_name)] + ) html_top_index += writer.csv_table( - items, - headers=["Chapter", "Description"], - widths=[30, 70]) + items, headers=["Chapter", "Description"], widths=[30, 70] + ) output = writer.only(html_top_index, "html") - links = [(a, qm.rest.DefaultImporter()) - for a in artifacts if "Index/.+" not in a.full_name] + links = [ + (a, qm.rest.DefaultImporter()) + for a in artifacts + if "Index/.+" not in a.full_name + ] - output += writer.toctree(['/%s/content' % artifact_hash(*l) - for l in links if not is_tc_or_set(l[0])], - hidden=True) + output += writer.toctree( + [ + "/%s/content" % artifact_hash(*l) + for l in links + if not is_tc_or_set(l[0]) + ], + hidden=True, + ) return output, links class SubsetIndexTable(ArtifactImporter): - def qmlink_to_rest(self, parent, artifacts): - items = [] header = "" - req = len([a for a in artifacts if class_to_string(a) == 'rq']) - reqg = len([a for a in artifacts if class_to_string(a) == 'rqg']) - tcg = len([a for a in artifacts if class_to_string(a) == 'tcg']) - tc = len([a for a in artifacts if class_to_string(a) == 'tc']) + req = len([a for a in artifacts if class_to_string(a) == "rq"]) + reqg = len([a for a in artifacts if class_to_string(a) == "rqg"]) + tcg = len([a for a in artifacts if class_to_string(a) == "tcg"]) + tc = len([a for a in artifacts if class_to_string(a) == "tc"]) for a in artifacts: - name = a.name - items.append([class_to_string(a), - name, - writer.qmref(a.full_name)]) + items.append([class_to_string(a), name, writer.qmref(a.full_name)]) # in the html, the title is adapted to the content of the table - header = ("Requirements and Groups" if (req > 0 and reqg > 0) else - ("Requirements Group" if (req == 0 and reqg == 1) else - ("Requirements Groups" if (req == 0 and reqg > 1) else - ("Requirement" if (req == 1 and reqg == 0) else - ("Requirements" if (req > 1 and reqg == 0) else - ("Testcases and Groups" if (tc > 0 and tcg > 0) else - ("Testcases" if (tc > 0 and tcg == 0) else - ("Testcases Groups" if (tc == 0 and tcg > 0) else - (""))))))))) + header = ( + "Requirements and Groups" + if (req > 0 and reqg > 0) + else ( + "Requirements Group" + if (req == 0 and reqg == 1) + else ( + "Requirements Groups" + if (req == 0 and reqg > 1) + else ( + "Requirement" + if (req == 1 and reqg == 0) + else ( + "Requirements" + if (req > 1 and reqg == 0) + else ( + "Testcases and Groups" + if (tc > 0 and tcg > 0) + else ( + "Testcases" + if (tc > 0 and tcg == 0) + else ( + "Testcases Groups" + if (tc == 0 and tcg > 0) + else ("") + ) + ) + ) + ) + ) + ) + ) + ) output = writer.csv_table( items, headers=["", "%s" % header, "Description"], - widths=[3, 25, 65]) + widths=[3, 25, 65], + ) return output, [] class SubsetIndexTocTree(ArtifactImporter): - def qmlink_to_rest(self, parent, artifacts): - links = [(a, default_importer(a)) for a in artifacts] - output = writer.toctree(['/%s/content' % artifact_hash(*l) - for l in links if not is_tc_or_set(l[0])], - hidden=True) + output = writer.toctree( + [ + "/%s/content" % artifact_hash(*l) + for l in links + if not is_tc_or_set(l[0]) + ], + hidden=True, + ) return output, links class SubsetIndexImporter(SubsetIndexTable): - def qmlink_to_rest(self, parent, artifacts): - - output, links = SubsetIndexTable.qmlink_to_rest(self, - parent, artifacts) + output, links = SubsetIndexTable.qmlink_to_rest( + self, parent, artifacts + ) links = [(a, default_importer(a)) for a in artifacts] - output += writer.toctree(['/%s/content' % artifact_hash(*l) - for l in links if not is_tc_or_set(l[0])], - hidden=True) + output += writer.toctree( + [ + "/%s/content" % artifact_hash(*l) + for l in links + if not is_tc_or_set(l[0]) + ], + hidden=True, + ) return output, links class TestCaseImporter(ArtifactImporter): - def log_missing_TR(self, artifact): """ Logs in a specific files the test case @@ -725,9 +831,11 @@ def log_missing_TR(self, artifact): break if not has_TR: - with open(MISSING_TR_LOG, 'a') as fd: - fd.write("No TR for artifact %s location: %s\n" % - (artifact.full_name, artifact.location)) + with open(MISSING_TR_LOG, "a") as fd: + fd.write( + "No TR for artifact %s location: %s\n" + % (artifact.full_name, artifact.location) + ) def get_sources(self, artifact): """ @@ -751,15 +859,16 @@ def get_sources(self, artifact): return result def to_rest(self, artifact): + reference = "\n\n.. _%s:\n" % artifact.full_name.replace("/", "_")[1:] - reference = "\n\n.. _%s:\n" % artifact.full_name.replace('/', '_')[1:] - - result_pdf = '**TEST CASE**: %s\n\n' % artifact.full_name - result_html = '%s\n%s\n' % (artifact.full_name, - '=' * len(artifact.full_name)) + result_pdf = "**TEST CASE**: %s\n\n" % artifact.full_name + result_html = "%s\n%s\n" % ( + artifact.full_name, + "=" * len(artifact.full_name), + ) - result_pdf += qm.rest.DefaultImporter().to_rest(artifact) + '\n\n' - result_html += qm.rest.DefaultImporter().to_rest(artifact) + '\n\n' + result_pdf += qm.rest.DefaultImporter().to_rest(artifact) + "\n\n" + result_html += qm.rest.DefaultImporter().to_rest(artifact) + "\n\n" result = reference + writer.only(result_pdf, "latex") result += writer.only(result_html, "html") @@ -787,39 +896,35 @@ def to_rest(self, artifact): do_pdf = False for item in self.get_sources(artifact): - if is_consolidation(item): - consolidation_list += [item.name] - consolidation_list_qmref += [writer.qmref - (item.full_name, - item.name)] + consolidation_list_qmref += [ + writer.qmref(item.full_name, item.name) + ] continue for key in item.contents_keys: if len(item.contents(key)) > 0: - for resource in item.contents(key): - if is_driver(resource): driver_list += [resource.basename] - driver_list_qmref += [writer.qmref - (item.full_name, - resource.basename)] + driver_list_qmref += [ + writer.qmref(item.full_name, resource.basename) + ] continue if is_functional(resource): func_list += [resource.basename] - func_list_qmref += [writer.qmref - (item.full_name, - resource.basename)] + func_list_qmref += [ + writer.qmref(item.full_name, resource.basename) + ] continue helper_list += [resource.basename] - helper_list_qmref += [writer.qmref - (item.full_name, - resource.basename)] + helper_list_qmref += [ + writer.qmref(item.full_name, resource.basename) + ] driver_list.sort() driver_list_qmref.sort() @@ -835,112 +940,112 @@ def to_rest(self, artifact): consolidation_list.sort() consolidation_list_qmref.sort() - for_table_qmref = izip_longest(func_list_qmref, - driver_list_qmref, - helper_list_qmref, - consolidation_list_qmref, - fillvalue="") - - for_table = izip_longest(func_list, - driver_list, - helper_list, - consolidation_list, - fillvalue="") + for_table_qmref = izip_longest( + func_list_qmref, + driver_list_qmref, + helper_list_qmref, + consolidation_list_qmref, + fillvalue="", + ) + + for_table = izip_longest( + func_list, + driver_list, + helper_list, + consolidation_list, + fillvalue="", + ) else: - for_table_qmref = izip_longest(func_list_qmref, - driver_list_qmref, - helper_list_qmref, - fillvalue="") + for_table_qmref = izip_longest( + func_list_qmref, + driver_list_qmref, + helper_list_qmref, + fillvalue="", + ) - for_table = izip_longest(func_list, - driver_list, - helper_list, - fillvalue="") + for_table = izip_longest( + func_list, driver_list, helper_list, fillvalue="" + ) - html_content = writer.csv_table([k for k in for_table_qmref], - headers) + html_content = writer.csv_table([k for k in for_table_qmref], headers) result += writer.only(html_content, "html") - if (do_pdf): - latex_content = writer.csv_table([k for k in for_table], - headers).strip() + if do_pdf: + latex_content = writer.csv_table( + [k for k in for_table], headers + ).strip() result += writer.only(latex_content, "latex") - output = '\n\n' + writer.minipage(result, r'\linewidth') + "|\n\n" + output = "\n\n" + writer.minipage(result, r"\linewidth") + "|\n\n" return output class SourceCodeImporter(ArtifactImporter): - def to_rest(self, artifact): - from qm import Ada_Sources, C_Sources, Conso_Sources result = "" if isinstance(artifact, Ada_Sources): - for key in artifact.contents_keys: for item in artifact.contents(key): result += writer.paragraph_title(item.basename) result += writer.code_block(item.get_content(), "ada") if isinstance(artifact, C_Sources): - for key in artifact.contents_keys: for item in artifact.contents(key): result += writer.paragraph_title(item.basename) result += writer.code_block(item.get_content(), "c") if isinstance(artifact, Conso_Sources): - result += writer.paragraph_title(artifact.name) - result += writer.code_block(artifact.location.get_content(), - "bash") + result += writer.code_block( + artifact.location.get_content(), "bash" + ) return result class IndexImporter(ArtifactImporter): - def append_to_items(self, art, depth): - if is_req(art): self.current_req = art kind_text = writer.strong("(%s)" % class_to_string(art)) - id_text = writer.strong( - "%s" % art.full_name.replace("/TOR", "")) + id_text = writer.strong("%s" % art.full_name.replace("/TOR", "")) elif is_tc(art): kind_text = "(%s)" % class_to_string(art) common_prefix_parent_req = os.path.commonprefix( - (art.full_name, - self.current_req.full_name)) + (art.full_name, self.current_req.full_name) + ) - id_text = \ - "[...]" + art.full_name.replace(common_prefix_parent_req, "") + id_text = "[...]" + art.full_name.replace( + common_prefix_parent_req, "" + ) self.items.append( - [kind_text, id_text, - write_artifact_ref(art.full_name, get_short_description(art))]) + [ + kind_text, + id_text, + write_artifact_ref(art.full_name, get_short_description(art)), + ] + ) def handle(self, art, depth): - if is_req(art) or is_tc(art): self.append_to_items(art, depth) for child in art.relatives: - self.handle(art=child, depth=depth+1) + self.handle(art=child, depth=depth + 1) def qmlink_to_rest(self, parent, artifacts): - self.items = [] def sortkey_for(art): - # Arrange for stmt requirements to come first, before decision and # mcdc. Work from locations, which contain the explicit ordering # requests in the names (numeric prefixes like 1_). @@ -956,12 +1061,13 @@ def sortkey_for(art): self.items, headers=["Kind", "Identification", "Description"], latex_format=( - '|p{0.05\linewidth}|p{0.47\linewidth}||p{0.37\linewidth}|')) + "|p{0.05\linewidth}|p{0.47\linewidth}||p{0.37\linewidth}|" + ), + ) html_table = writer.csv_table( - self.items, - headers=["Kind", "Ref"], - widths=[5, 47, 37]) + self.items, headers=["Kind", "Ref"], widths=[5, 47, 37] + ) output = "" output += writer.only(pdf_table, "latex") @@ -973,7 +1079,6 @@ def sortkey_for(art): class TestCasesImporter(ArtifactImporter): - def short_descs_of_main_ancestors(self, artifact, head): """ Get the first line of both itself and the ancestor @@ -995,8 +1100,9 @@ def short_descs_of_main_ancestors(self, artifact, head): main_desc = get_short_description(parent) desc = get_short_description(artifact) else: - main_desc, desc = self.short_descs_of_main_ancestors(parent, - head) + main_desc, desc = self.short_descs_of_main_ancestors( + parent, head + ) return main_desc, desc @@ -1057,19 +1163,22 @@ def tc_pdf_for(self, toplevel, subdirs, links): :type links: list[(artifact,importer)] """ - pdf_output = '' + pdf_output = "" for subdir in subdirs: subdir_output = self.tc_pdf_for_subdir( - toplevel=toplevel, subdir=subdir, links=links) + toplevel=toplevel, subdir=subdir, links=links + ) if subdir_output: if len(pdf_output) == 0: - pdf_output += writer.section( - '%s Testcases' % toplevel) + '\n' + pdf_output += ( + writer.section("%s Testcases" % toplevel) + "\n" + ) else: - pdf_output += writer.role( - 'raw-latex', r'\newpage') + '\n\n' + pdf_output += ( + writer.role("raw-latex", r"\newpage") + "\n\n" + ) pdf_output += subdir_output @@ -1081,36 +1190,38 @@ def tc_pdf_for_subdir(self, toplevel, subdir, links): """ subdir_links = [ - sdl for sdl in links - if sdl[0].full_name.startswith('/TOR/%s/%s' % (toplevel, subdir))] + sdl + for sdl in links + if sdl[0].full_name.startswith("/TOR/%s/%s" % (toplevel, subdir)) + ] if not subdir_links: - return '' + return "" links_dict = OrderedDict() for sdl in subdir_links: - main_desc, desc = self.short_descs_of_main_ancestors(sdl[0], - subdir) + main_desc, desc = self.short_descs_of_main_ancestors( + sdl[0], subdir + ) if desc not in links_dict: links_dict[desc] = [] links_dict[desc].append(sdl) - pdf_output = '' - pdf_output += writer.subsection('%s' % main_desc) + '\n' + pdf_output = "" + pdf_output += writer.subsection("%s" % main_desc) + "\n" for desc in links_dict.keys(): - pdf_output += writer.subsubsection(desc) + '\n' + pdf_output += writer.subsubsection(desc) + "\n" pdf_output += writer.toctree( - ['/%s/content' % artifact_hash(*l) - for l in links_dict[desc]], - hidden=True) + ["/%s/content" % artifact_hash(*l) for l in links_dict[desc]], + hidden=True, + ) return pdf_output def qmlink_to_rest(self, parent, artifacts): - # cleanup missingTRfile - with open(MISSING_TR_LOG, 'w') as fd: + with open(MISSING_TR_LOG, "w") as fd: fd.write("") # Precompute sets of (artifact, importer) pairs of relevance @@ -1132,22 +1243,25 @@ def qmlink_to_rest(self, parent, artifacts): # Build the html output html_output = writer.toctree( - ['/%s/content' % artifact_hash(*l) - for l in mixed_links], hidden=True) + ["/%s/content" % artifact_hash(*l) for l in mixed_links], + hidden=True, + ) # Then the PDF variant. A bit more work as we need to output # intermediate section titles ourselves and we don't want to # include the sources there. - pdf_output = '' + pdf_output = "" pdf_output += self.tc_pdf_for( - toplevel='Ada', - subdirs=['stmt', 'decision', 'mcdc'], - links=tc_or_set_links) + toplevel="Ada", + subdirs=["stmt", "decision", "mcdc"], + links=tc_or_set_links, + ) pdf_output += self.tc_pdf_for( - toplevel='Common', - subdirs=['Report', 'UnitsOfInterest', 'GprFacilities'], - links=tc_or_set_links) + toplevel="Common", + subdirs=["Report", "UnitsOfInterest", "GprFacilities"], + links=tc_or_set_links, + ) output = writer.only(html_output, "html") output += writer.only(pdf_output, "latex") diff --git a/qualification/qm/qm_plugins/link_lrm.py b/qualification/qm/qm_plugins/link_lrm.py index 8a5f023a2..0261201bb 100644 --- a/qualification/qm/qm_plugins/link_lrm.py +++ b/qualification/qm/qm_plugins/link_lrm.py @@ -1,4 +1,3 @@ - LRMREF = "LRMREF:" @@ -12,9 +11,9 @@ def parse_req(artifact): ref_list = [] for line in loc.get_content().splitlines(): - if line.lstrip().startswith(LRMREF): - ref_list = ['/%s' % k.strip() - for k in line.split(LRMREF, 1)[1].split(',')] + ref_list = [ + "/%s" % k.strip() for k in line.split(LRMREF, 1)[1].split(",") + ] return ref_list diff --git a/qualification/qm/qm_plugins/lrm_index_parser.py b/qualification/qm/qm_plugins/lrm_index_parser.py index d424cc333..76a86ed2f 100644 --- a/qualification/qm/qm_plugins/lrm_index_parser.py +++ b/qualification/qm/qm_plugins/lrm_index_parser.py @@ -6,6 +6,7 @@ class LRMParser(qm.LocationParser): The parser used by the QM to parse lrm_ref file and creates LRM section locations. """ + def __init__(self): self.relpath = None @@ -15,15 +16,14 @@ def parse(self, path, parent): lines = [] self.parent = parent - with open(path, 'r') as fd: + with open(path, "r") as fd: lines = fd.read().splitlines() for line in lines: + if line.startswith("#"): + continue - if line.startswith('#'): - continue - - if line.startswith('Note'): + if line.startswith("Note"): break if len(line.strip()) > 0: @@ -31,4 +31,5 @@ def parse(self, path, parent): qm.LocationParser.register_repository_factory( - 'lrm', '*.txt', LRMParser(), False) + "lrm", "*.txt", LRMParser(), False +) diff --git a/qualification/qm/qm_prolog.py b/qualification/qm/qm_prolog.py index 7b3f1932d..b1fb705ff 100644 --- a/qualification/qm/qm_prolog.py +++ b/qualification/qm/qm_prolog.py @@ -4,59 +4,73 @@ torintro_section_title = "Document Purpose and Organization" testproc_section_title = "Overview of the Test Procedures Organization" -rst_prolog = writer.macro('project_command', '``gnatcov``') \ - + writer.role('raw-latex', - r'\renewcommand{\labelitemi}{$\bullet$}') + '\n\n' \ - + writer.role('raw-latex', - r'\renewcommand{\labelitemii}{$\circ$}') + '\n\n' \ - + writer.role('raw-latex', - r'\renewcommand{\labelitemiii}{$\cdots$}') + '\n\n' \ - + writer.role('raw-latex', - r'\renewcommand{\labelitemiv}{$-$}') + '\n\n' \ - + writer.macro('adacore', 'AdaCore') \ - + writer.macro('gnatpro', 'GNAT Pro') \ - + writer.macro('gnatpro_it', '*GNAT Pro*') \ - + writer.macro('gnatpro_bold', '**GNAT Pro**') \ - + writer.macro('Ada83', '`Ada 83`') \ - + writer.macro('Ada95', '`Ada 95`') \ - + writer.macro('Ada05', '`Ada 2005`') \ - + writer.macro('Ada12', '`Ada 2012`') \ - + writer.macro('QA', 'Quality Assurance') \ - + writer.macro('plans_pdf', r'``PLANS.pdf``') \ - + writer.macro('tor_pdf', r'``TOR.pdf``') \ - + writer.macro('str_pdf', r'``STR.pdf``') \ - + writer.macro('tqa_file', r'``qa.doc``') \ - + writer.macro('tors', r'Tool Operational Requirements') \ - + writer.macro('plans_doc_title', r'*Qualification Plans*') \ - + writer.macro('tor_doc_title', r'*Tool Operational Requirements and V&V Cases and Procedures*') \ - + writer.macro('str_doc_title', r'*Tool Operational Verification and Validation Results*') \ - + writer.macro('tqa_doc_title', r'*Tool Quality Assurance Records*') \ - + writer.macro('plans_doc', r'*PLANS*') \ - + writer.macro('tor_doc', r'*TOR*') \ - + writer.macro('str_doc', r'*STR*') \ - + writer.macro('tqa_doc', '|tqa_doc_title|') \ - + writer.macro('plans_doc_id', r'*' + plans_doc_id + r'*') \ - + writer.macro('tor_doc_id', r'*' + tor_doc_id + r'*') \ - + writer.macro('str_doc_id', r'*' + str_doc_id + r'*') \ - + writer.macro('opcond_section_title', r'%s' % opcond_section_title) \ - + writer.macro('opcond_section_title_ref', r'*%s*' % opcond_section_title) \ - + writer.macro('torintro_section_title', r'%s' % torintro_section_title) \ - + writer.macro('torintro_section_title_ref', r'*%s*' % torintro_section_title) \ - + writer.macro('testproc_section_title', r'%s' % testproc_section_title) \ - + writer.macro('testproc_section_title_ref', r'*%s*' % testproc_section_title) \ - + writer.macro('DAL', 'Design Assurance Level') \ - + writer.macro('PSAC', 'Plan for Software Aspects of Certification') \ - + writer.macro('PSAC_bold', - '**Plan for Software Aspects of Certification**') \ - + writer.macro('V&V', 'Verification and Validation') \ - + writer.macro('RAMS', - 'Reliability, Availability, Maintainability and Safety') \ - + writer.macro('ARM', 'Ada Reference Manual') \ - + writer.macro('standard', 'DO-178C/ED-12C') \ - + writer.macro('tool_standard', 'DO-330/ED-215') \ - + writer.macro('client', '`GENERIC CLIENT`') +rst_prolog = ( + writer.macro("project_command", "``gnatcov``") + + writer.role("raw-latex", r"\renewcommand{\labelitemi}{$\bullet$}") + + "\n\n" + + writer.role("raw-latex", r"\renewcommand{\labelitemii}{$\circ$}") + + "\n\n" + + writer.role("raw-latex", r"\renewcommand{\labelitemiii}{$\cdots$}") + + "\n\n" + + writer.role("raw-latex", r"\renewcommand{\labelitemiv}{$-$}") + + "\n\n" + + writer.macro("adacore", "AdaCore") + + writer.macro("gnatpro", "GNAT Pro") + + writer.macro("gnatpro_it", "*GNAT Pro*") + + writer.macro("gnatpro_bold", "**GNAT Pro**") + + writer.macro("Ada83", "`Ada 83`") + + writer.macro("Ada95", "`Ada 95`") + + writer.macro("Ada05", "`Ada 2005`") + + writer.macro("Ada12", "`Ada 2012`") + + writer.macro("QA", "Quality Assurance") + + writer.macro("plans_pdf", r"``PLANS.pdf``") + + writer.macro("tor_pdf", r"``TOR.pdf``") + + writer.macro("str_pdf", r"``STR.pdf``") + + writer.macro("tqa_file", r"``qa.doc``") + + writer.macro("tors", r"Tool Operational Requirements") + + writer.macro("plans_doc_title", r"*Qualification Plans*") + + writer.macro( + "tor_doc_title", + r"*Tool Operational Requirements and V&V Cases and Procedures*", + ) + + writer.macro( + "str_doc_title", + r"*Tool Operational Verification and Validation Results*", + ) + + writer.macro("tqa_doc_title", r"*Tool Quality Assurance Records*") + + writer.macro("plans_doc", r"*PLANS*") + + writer.macro("tor_doc", r"*TOR*") + + writer.macro("str_doc", r"*STR*") + + writer.macro("tqa_doc", "|tqa_doc_title|") + + writer.macro("plans_doc_id", r"*" + plans_doc_id + r"*") + + writer.macro("tor_doc_id", r"*" + tor_doc_id + r"*") + + writer.macro("str_doc_id", r"*" + str_doc_id + r"*") + + writer.macro("opcond_section_title", r"%s" % opcond_section_title) + + writer.macro("opcond_section_title_ref", r"*%s*" % opcond_section_title) + + writer.macro("torintro_section_title", r"%s" % torintro_section_title) + + writer.macro( + "torintro_section_title_ref", r"*%s*" % torintro_section_title + ) + + writer.macro("testproc_section_title", r"%s" % testproc_section_title) + + writer.macro( + "testproc_section_title_ref", r"*%s*" % testproc_section_title + ) + + writer.macro("DAL", "Design Assurance Level") + + writer.macro("PSAC", "Plan for Software Aspects of Certification") + + writer.macro( + "PSAC_bold", "**Plan for Software Aspects of Certification**" + ) + + writer.macro("V&V", "Verification and Validation") + + writer.macro( + "RAMS", "Reliability, Availability, Maintainability and Safety" + ) + + writer.macro("ARM", "Ada Reference Manual") + + writer.macro("standard", "DO-178C/ED-12C") + + writer.macro("tool_standard", "DO-330/ED-215") + + writer.macro("client", "`GENERIC CLIENT`") +) # We expect to be called through genbundle.py, which should export an # environment variable stating what --dolevel it was passed ('doA', 'doB', # or 'doC'). Expose the significant letter to documents: -rst_prolog += writer.macro('dolevel', os.environ.get('GENBUNDLE_DOLEVEL')[-1]) +rst_prolog += writer.macro("dolevel", os.environ.get("GENBUNDLE_DOLEVEL")[-1]) diff --git a/qualification/qm/scripts/generate_plans_html.py b/qualification/qm/scripts/generate_plans_html.py index 87629cdfb..3bfa3ef63 100644 --- a/qualification/qm/scripts/generate_plans_html.py +++ b/qualification/qm/scripts/generate_plans_html.py @@ -3,4 +3,4 @@ # Locate the output as the other sphinx-based components do, facilitating the # toplevel driver for qmat generation. Not an unreasonable name anyway. -generate_doc.generate_html('PLANS', 'build/html') +generate_doc.generate_html("PLANS", "build/html") diff --git a/qualification/qm/scripts/generate_plans_pdf.py b/qualification/qm/scripts/generate_plans_pdf.py index bd2d5dc70..d50cd6976 100644 --- a/qualification/qm/scripts/generate_plans_pdf.py +++ b/qualification/qm/scripts/generate_plans_pdf.py @@ -3,4 +3,4 @@ # Locate the output as the other sphinx-based components do, facilitating the # toplevel driver for qmat generation. Not an unreasonable name anyway. -generate_doc.generate_pdf('PLANS', 'build/latexpdf') +generate_doc.generate_pdf("PLANS", "build/latexpdf") diff --git a/qualification/qm/scripts/generate_tor_html.py b/qualification/qm/scripts/generate_tor_html.py index 6e63bb98e..cb6b1e713 100644 --- a/qualification/qm/scripts/generate_tor_html.py +++ b/qualification/qm/scripts/generate_tor_html.py @@ -3,4 +3,4 @@ # Locate the output as the other sphinx-based components do, facilitating the # toplevel driver for qmat generation. Not an unreasonable name anyway. -generate_doc.generate_html('TOR', 'build/html') +generate_doc.generate_html("TOR", "build/html") diff --git a/qualification/qm/scripts/generate_tor_pdf.py b/qualification/qm/scripts/generate_tor_pdf.py index d40a3930b..8bc6c5d8b 100644 --- a/qualification/qm/scripts/generate_tor_pdf.py +++ b/qualification/qm/scripts/generate_tor_pdf.py @@ -3,4 +3,4 @@ # Locate the output as the other sphinx-based components do, facilitating the # toplevel driver for qmat generation. Not an unreasonable name anyway. -generate_doc.generate_pdf('TOR', 'build/latexpdf') +generate_doc.generate_pdf("TOR", "build/latexpdf") diff --git a/testsuite/OCOV/__init__.py b/testsuite/OCOV/__init__.py index 3543ec32b..3346078a4 100644 --- a/testsuite/OCOV/__init__.py +++ b/testsuite/OCOV/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -''' +""" TODO -''' +""" diff --git a/testsuite/OCOV/tc.py b/testsuite/OCOV/tc.py index 5a5408d45..7f073a1df 100644 --- a/testsuite/OCOV/tc.py +++ b/testsuite/OCOV/tc.py @@ -8,8 +8,14 @@ from SUITE.context import thistest import SUITE.control from SUITE.cutils import Wdir -from SUITE.tutils import (gprbuild, gprfor, tracename_for, unixpath_to, xcov, - xrun) +from SUITE.tutils import ( + gprbuild, + gprfor, + tracename_for, + unixpath_to, + xcov, + xrun, +) # Cache some values we need repeatedly @@ -17,23 +23,24 @@ class TestCase(object): - - ROUTINES_FILE = 'routines.list' - RESULT_FILE = 'coverage.result' + ROUTINES_FILE = "routines.list" + RESULT_FILE = "coverage.result" SYMBOL_COVERAGE_PATTERN = re.compile( - '^([a-zA-Z_][a-zA-Z0-9_]*)' # Symbol name - ' ([-!+]): ' # Symbol coverage result - '[0-9a-f]+-[0-9a-f]+\n$' # Address range for the symbol + "^([a-zA-Z_][a-zA-Z0-9_]*)" # Symbol name + " ([-!+]): " # Symbol coverage result + "[0-9a-f]+-[0-9a-f]+\n$" # Address range for the symbol ) - NO_COV, PART_COV, FULL_COV = '-!+' + NO_COV, PART_COV, FULL_COV = "-!+" def __init__( self, - test_drivers, coverage_expectations, + test_drivers, + coverage_expectations, extra_sourcedirs=[], - level='branch', annotate='asm', - extra_xcov_args=[] + level="branch", + annotate="asm", + extra_xcov_args=[], ): self.test_drivers = test_drivers self.coverage_expectations = { @@ -46,10 +53,10 @@ def __init__( self.extra_xcov_args = extra_xcov_args def run(self, register_failure=True): - ''' + """ Return if "gnatcov coverage" executed properly. - ''' - Wdir('tmp_') + """ + Wdir("tmp_") # Compile and run separately each test driver. for test_driver, switches in self.test_drivers.items(): @@ -63,45 +70,44 @@ def run(self, register_failure=True): # Consolidate resulting traces and parse the object coverage results. # If consolidation fails, return False. if ( - not self._consolidate_traces(self.RESULT_FILE, - register_failure) and - not register_failure + not self._consolidate_traces(self.RESULT_FILE, register_failure) + and not register_failure ): return False # We can parse the result only if the output is an annotated ASM. - if self.annotate == 'asm': + if self.annotate == "asm": coverage_result = self._parse_coverage_results(self.RESULT_FILE) # Compare results with expectations... thistest.fail_if( coverage_result != self.coverage_expectations, - 'Coverage result:\n' - '{}' - 'do not match coverage expectations:\n' - '{}'.format( + "Coverage result:\n" + "{}" + "do not match coverage expectations:\n" + "{}".format( self.format_coverage(coverage_result), - self.format_coverage(self.coverage_expectations) - ) + self.format_coverage(self.coverage_expectations), + ), ) return True def _compile(self, test_driver, compile_unit_switches): - mkdir('{}-obj'.format(test_driver)) + mkdir("{}-obj".format(test_driver)) project_file = gprfor( - mains=[test_driver + '.c'], + mains=[test_driver + ".c"], prjid=test_driver, - srcdirs=['..'] + self.extra_sourcedirs, - objdir='{}-obj'.format(test_driver), - langs=['C', 'ASM'], - compiler_extra='\n'.join( - ('for Switches("{}") use ' - ' Compiler\'Default_Switches ("C") & ({});').format( - cu, self.fmt_list(switches) - ) + srcdirs=[".."] + self.extra_sourcedirs, + objdir="{}-obj".format(test_driver), + langs=["C", "ASM"], + compiler_extra="\n".join( + ( + 'for Switches("{}") use ' + ' Compiler\'Default_Switches ("C") & ({});' + ).format(cu, self.fmt_list(switches)) for cu, switches in compile_unit_switches.items() - ) + ), ) # We never want the testuite optimization options or source coverage @@ -113,18 +119,18 @@ def _run(self, test_driver): xrun(unixpath_to(test_driver)) def _generate_routines_list(self): - with open(self.ROUTINES_FILE, 'w') as f: + with open(self.ROUTINES_FILE, "w") as f: for routine in self.coverage_expectations: - f.write('{}\n'.format(routine)) + f.write("{}\n".format(routine)) def _consolidate_traces(self, output, register_failure): xcov_args = [ - 'coverage', - '--level=' + self.level, - '--annotate=' + self.annotate, + "coverage", + "--level=" + self.level, + "--annotate=" + self.annotate, ] - if self.level in ('insn', 'branch'): - xcov_args.append('--routines=@' + self.ROUTINES_FILE) + if self.level in ("insn", "branch"): + xcov_args.append("--routines=@" + self.ROUTINES_FILE) xcov_args.extend(self.extra_xcov_args) xcov_args.extend(map(tracename_for, self.test_drivers)) p = xcov(xcov_args, out=output, register_failure=register_failure) @@ -136,7 +142,7 @@ def _parse_coverage_results(self, input_file): lambda: {self.NO_COV: 0, self.PART_COV: 0, self.FULL_COV: 0} ) - with open(input_file, 'r') as f: + with open(input_file, "r") as f: for line in f: m = self.SYMBOL_COVERAGE_PATTERN.match(line) if m: @@ -146,13 +152,13 @@ def _parse_coverage_results(self, input_file): return result def fmt_list(self, items): - ''' + """ Format a list of string for the GPR file. >>> fmt_list(('a', 'b', 'c')) "a", "b", "c" - ''' - return ', '.join(['"{}"'.format(item) for item in items]) + """ + return ", ".join(['"{}"'.format(item) for item in items]) def format_coverage(self, coverage): result = [] @@ -162,6 +168,6 @@ def format_coverage(self, coverage): symbol, cov_result[self.NO_COV], cov_result[self.PART_COV], - cov_result[self.FULL_COV] + cov_result[self.FULL_COV], ) - return ''.join(result) + return "".join(result) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/test.py b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/test.py index 4e6971e89..ed921d36f 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/test.py +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/test.py @@ -8,5 +8,7 @@ # of absolute paths for source files). TestCase().run( CovControl(covoptions="--source-search=../../src") - if thistest.options.trace_mode == 'bin' else None) + if thistest.options.trace_mode == "bin" + else None +) thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.py b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.py index cc7812869..3803d3a25 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.py +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.py @@ -4,6 +4,5 @@ tc = TestCase() tc.run() -tc.run(covcontrol=CovControl(covoptions='-S instance'), - subdirhint='i_') +tc.run(covcontrol=CovControl(covoptions="-S instance"), subdirhint="i_") thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.py b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.py index cc7812869..3803d3a25 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.py +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.py @@ -4,6 +4,5 @@ tc = TestCase() tc.run() -tc.run(covcontrol=CovControl(covoptions='-S instance'), - subdirhint='i_') +tc.run(covcontrol=CovControl(covoptions="-S instance"), subdirhint="i_") thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/test.py b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/test.py index 224a6a72f..c5294fe74 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/test.py +++ b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/test.py @@ -5,9 +5,13 @@ from SUITE.context import thistest from SUITE.gprutils import GPRswitches -libdep = os.path.abspath('mylib/mylib.gpr') -TestCase().run(covcontrol=CovControl( - deps=[libdep], - gprsw=GPRswitches(root_project='gen.gpr', - units=['foo', 'bar', 'klunk']))) +libdep = os.path.abspath("mylib/mylib.gpr") +TestCase().run( + covcontrol=CovControl( + deps=[libdep], + gprsw=GPRswitches( + root_project="gen.gpr", units=["foo", "bar", "klunk"] + ), + ) +) thistest.result() diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.py b/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.py index c07142685..5e5d4b466 100644 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.py +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/assert-failure/test.py @@ -4,7 +4,9 @@ HarnessTestCase( - expected_diags=[HarnessDiagnostic( - text="exception raised while running 'test_afail'")], - category=CAT.stmt).run() + expected_diags=[ + HarnessDiagnostic(text="exception raised while running 'test_afail'") + ], + category=CAT.stmt, +).run() thistest.result() diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/expected-scv-notfound/test.py b/testsuite/Qualif/Appendix/Testsuite/Selftest/expected-scv-notfound/test.py index 44183c3b8..d663c372f 100644 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/expected-scv-notfound/test.py +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/expected-scv-notfound/test.py @@ -6,11 +6,12 @@ # The =report diags we always expect. The =xcov diags we only expect in # !qualif runs as these don't produce the =xcov outputs. expected_diags = [ - HarnessDiagnostic(text='Missing expected sNoCov mark at line 3')] + HarnessDiagnostic(text="Missing expected sNoCov mark at line 3") +] if not thistest.options.qualif_level: expected_diags.append( - HarnessDiagnostic(text='Missing expected lNoCov mark at line 3')) + HarnessDiagnostic(text="Missing expected lNoCov mark at line 3") + ) -HarnessTestCase(expected_diags=expected_diags, - category=CAT.stmt).run() +HarnessTestCase(expected_diags=expected_diags, category=CAT.stmt).run() thistest.result() diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/test.py b/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/test.py index 210a744e1..bf3b34c31 100644 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/test.py +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-implicit/test.py @@ -5,11 +5,13 @@ # The =report diags we always expect. The =xcov diags we only expect in # !qualif runs as these don't produce the =xcov outputs. -expected_diags = [HarnessDiagnostic(text='Unexpected sNoCov mark at sloc 3:4')] +expected_diags = [HarnessDiagnostic(text="Unexpected sNoCov mark at sloc 3:4")] if not thistest.options.qualif_level: - expected_diags.append(HarnessDiagnostic( - text='(inc.adb.xcov) Unexpected lNoCov mark at line 3')) + expected_diags.append( + HarnessDiagnostic( + text="(inc.adb.xcov) Unexpected lNoCov mark at line 3" + ) + ) -HarnessTestCase(expected_diags=expected_diags, - category=CAT.stmt).run() +HarnessTestCase(expected_diags=expected_diags, category=CAT.stmt).run() thistest.result() diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-r0/test.py b/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-r0/test.py index ba68b763f..d6a1c8574 100644 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-r0/test.py +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/unexpected-scv-r0/test.py @@ -5,6 +5,8 @@ HarnessTestCase( expected_diags=[ - HarnessDiagnostic(text='Unexpected sNoCov mark at sloc 3:4')], - category=CAT.stmt).run() + HarnessDiagnostic(text="Unexpected sNoCov mark at sloc 3:4") + ], + category=CAT.stmt, +).run() thistest.result() diff --git a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py index c1ee12eab..43587a4d8 100644 --- a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py +++ b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py @@ -11,42 +11,52 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xrun, - xcov) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xrun, + xcov, +) -gprname = 'p' -mainbase = 'foo' -mainunit = mainbase + '.adb' +gprname = "p" +mainbase = "foo" +mainunit = mainbase + ".adb" env = Env() target = env.target.triplet -Wdir('wd_') +Wdir("wd_") # Get a template for the project file. -gpr_filename = gprfor(prjid=gprname, mains=[mainunit], - srcdirs=['../..'], - langs=["Ada"], - extra='for Target use "%TARGET%"; %RUNTIME%') +gpr_filename = gprfor( + prjid=gprname, + mains=[mainunit], + srcdirs=["../.."], + langs=["Ada"], + extra='for Target use "%TARGET%"; %RUNTIME%', +) gpr_filename = os.path.abspath(gpr_filename) gpr_basename = os.path.basename(gpr_filename) gpr_content = contents_of(gpr_filename) def instantiate_gpr(target): - with open(gpr_basename, 'w') as f: - content = gpr_content.replace('%TARGET%', target) + with open(gpr_basename, "w") as f: + content = gpr_content.replace("%TARGET%", target) content = content.replace( - '%RUNTIME%', + "%RUNTIME%", 'for Runtime ("Ada") use "{}";'.format(thistest.options.RTS) - if thistest.options.RTS else '' + if thistest.options.RTS + else "", ) f.write(content) -for mode in ('no_arg', 'with_arg'): - wd = Wdir('wd_{}'.format(mode)) +for mode in ("no_arg", "with_arg"): + wd = Wdir("wd_{}".format(mode)) exe = exepath_to(mainbase) trace = tracename_for(mainbase) @@ -55,28 +65,26 @@ def instantiate_gpr(target): instantiate_gpr(target) gprbuild(os.path.abspath(gpr_basename)) - argv = ['-P{}'.format(gprname), '-o', trace, exe] + argv = ["-P{}".format(gprname), "-o", trace, exe] # Run with a bad target as the Target attribute in order to check that the # --target argument actually takes precedence. - with_target_arg = mode == 'with_arg' + with_target_arg = mode == "with_arg" if with_target_arg: - instantiate_gpr('this_target_does_not_exist') + instantiate_gpr("this_target_does_not_exist") # Force the passing of --target in the native case, as xrun() does not # pass it when it is the default. if not env.is_cross: - argv.append('--target={}'.format(target)) + argv.append("--target={}".format(target)) - xrun(argv, - auto_config_args=False, - auto_target_args=with_target_arg) + xrun(argv, auto_config_args=False, auto_target_args=with_target_arg) - dump = 'dump.txt' - xcov('dump-trace {}'.format(trace), out=dump) + dump = "dump.txt" + xcov("dump-trace {}".format(trace), out=dump) thistest.fail_if( - len(re.findall('t block$', contents_of(dump), flags=re.M)) < 1, - 'with exe, no block execution trace found in {}'.format(trace) + len(re.findall("t block$", contents_of(dump), flags=re.M)) < 1, + "with exe, no block execution trace found in {}".format(trace), ) wd.to_homedir() diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/test.py b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/test.py index cf59bede7..ce18e2547 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/test.py +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/CmdLinePrevails/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import gprfor, xcov -pgm = 'test_lt0' +pgm = "test_lt0" def run(subdir, extra_args, covlevel=None): @@ -19,17 +19,23 @@ def run(subdir, extra_args, covlevel=None): dirname = f"tmp_{subdir}" wd = Wdir(dirname) - gpr = gprfor(mains=[pgm + '.adb'], - srcdirs=['../src'], - extra=gprcov_for(switches=[ - Csw('*', ['--level=stmt']), - Csw('coverage', ['--annotate=report'])])) + gpr = gprfor( + mains=[pgm + ".adb"], + srcdirs=["../src"], + extra=gprcov_for( + switches=[ + Csw("*", ["--level=stmt"]), + Csw("coverage", ["--annotate=report"]), + ] + ), + ) xcov_args = build_and_run( gprsw=GPRswitches(root_project=gpr), covlevel=covlevel, mains=[pgm], - extra_coverage_args=[] if covlevel is None else ['--level', covlevel]) + extra_coverage_args=[] if covlevel is None else ["--level", covlevel], + ) xcov(xcov_args + extra_args) wd.to_homedir() @@ -39,44 +45,58 @@ def run(subdir, extra_args, covlevel=None): def check_report(label, filename, pattern, check_present=True): report = contents_of(filename) matched = re.search(pattern, report) - thistest.fail_if(not matched if check_present else matched, - label) + thistest.fail_if(not matched if check_present else matched, label) # Check that we get results corresponding to the project file # defaults if we don't tell anything otherwise. -subdir = run("default", ['-o', 'def.rep']) +subdir = run("default", ["-o", "def.rep"]) def_rep = os.path.join(subdir, "def.rep") # Check that we have the output report, that it does contain at least a stmt # coverage violation note, and that it doesn't contain any DC related note. -check_report('missing expected stmt coverage failure indication', - def_rep, 'statement not executed') -check_report('unexpected decision coverage failure indication', - def_rep, 'decision outcome .* never exercised', - check_present=False) +check_report( + "missing expected stmt coverage failure indication", + def_rep, + "statement not executed", +) +check_report( + "unexpected decision coverage failure indication", + def_rep, + "decision outcome .* never exercised", + check_present=False, +) # Override --level up to DC. Check that we now find the DC violations we # expect. -subdir = run("lev", ['-o', 'lev.rep'], covlevel='stmt+decision') +subdir = run("lev", ["-o", "lev.rep"], covlevel="stmt+decision") lev_rep = os.path.join(subdir, "lev.rep") -check_report('missing expected decision coverage failure indication', - lev_rep, 'decision outcome .* never exercised') +check_report( + "missing expected decision coverage failure indication", + lev_rep, + "decision outcome .* never exercised", +) # Override --annotate only. Expect full coverage on the "if" # statement. -subdir = run("ann", ['--annotate=xcov']) -check_report('missing expected full coverage indication', - os.path.join(subdir, "obj", "values.adb.xcov"), r'\+:.*if') +subdir = run("ann", ["--annotate=xcov"]) +check_report( + "missing expected full coverage indication", + os.path.join(subdir, "obj", "values.adb.xcov"), + r"\+:.*if", +) # Override --annotate and --level. Expect partial coverage on the "if" # statement. -subdir = run("lev-ann", ['--annotate=xcov'], covlevel='stmt+decision') -check_report('missing expected partial decision coverage indication', - os.path.join(subdir, "obj", "values.adb.xcov"), '!:.*if') +subdir = run("lev-ann", ["--annotate=xcov"], covlevel="stmt+decision") +check_report( + "missing expected partial decision coverage indication", + os.path.join(subdir, "obj", "values.adb.xcov"), + "!:.*if", +) thistest.result() diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py index a6c95a448..99e66074c 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py @@ -9,21 +9,22 @@ # Check correctness of transmission from Switches to commands for a few # particular commands. Check that Switches ("*") comes before Switches (cmd). -wd = Wdir('wd_') +wd = Wdir("wd_") # We will be exercising combinations of run/coverage operations with option # variations controlled via Coverage attributes in an otherwise common project # file for a simple program. + def gprvariant(id, extra): - return gprfor(prjid=id, srcdirs=['../src'], mains=['p.adb'], extra=extra) + return gprfor(prjid=id, srcdirs=["../src"], mains=["p.adb"], extra=extra) -exe = exepath_to('p') +exe = exepath_to("p") # Build once -gprbuild(gprvariant(id='bld', extra='')) +gprbuild(gprvariant(id="bld", extra="")) # ------------------------------------------------ # -- Simple helpers for coverage/run variations -- @@ -34,34 +35,37 @@ def gprvariant(id, extra): def tag_for(id): - return 'tag-%s' % id + return "tag-%s" % id def tagopt_for(id): - return ['--tag=%s' % tag_for(id)] + return ["--tag=%s" % tag_for(id)] def rep_for(id): - return '%s.rep' % id + return "%s.rep" % id def annopt_for(id): - return ['--annotate=report'] + return ["--annotate=report"] # level expected to be assessed eventually, always -lev = 'stmt+decision' +lev = "stmt+decision" def levopt_for(id): - return ['--level=%s' % lev] + return ["--level=%s" % lev] def try_run(id, gpr): """gnatcov run with common set of options & variations via gpr.""" - log = id + '.rlog' - xrun(['-P%s' % gpr, exe, '-o', '%s.trace' % id], - out=log, register_failure=False) + log = id + ".rlog" + xrun( + ["-P%s" % gpr, exe, "-o", "%s.trace" % id], + out=log, + register_failure=False, + ) return contents_of(log) @@ -70,23 +74,30 @@ def try_cov(id, gpr): gnatcov coverage with common set of options & variations via gpr. Expect valid options and check for commonly expected outcome """ - log = id + '.clog' - xcov(['coverage', '-P%s' % gpr, '%s.trace' % id, '-o', rep_for(id)], - out=log, register_failure=False) + log = id + ".clog" + xcov( + ["coverage", "-P%s" % gpr, "%s.trace" % id, "-o", rep_for(id)], + out=log, + register_failure=False, + ) # Check that we get a report with expected contents wrt options # eventually. The tag & level checks make sure that # # * options intended for run do get there and not to coverage # * options intended for coverage do get there and not to run - thistest.fail_if(not empty(log), 'unexpected contents in %s' % log) + thistest.fail_if(not empty(log), "unexpected contents in %s" % log) rep = contents_of(rep_for(id)) - thistest.fail_if('level: %s' % lev not in rep, - 'missing expected level indication in %s' % rep_for(id)) + thistest.fail_if( + "level: %s" % lev not in rep, + "missing expected level indication in %s" % rep_for(id), + ) - thistest.fail_if(not re.search('tag.*: %s' % tag_for(id), rep), - 'missing expected tag indication in %s' % rep_for(id)) + thistest.fail_if( + not re.search("tag.*: %s" % tag_for(id), rep), + "missing expected tag indication in %s" % rep_for(id), + ) def check_valid_sequence_for(id, gprcov): @@ -100,47 +111,66 @@ def check_valid_sequence_for(id, gprcov): # Basic check for starters. No "*". -id = 'basic' +id = "basic" check_valid_sequence_for( - id=id, gprcov=gprcov_for(switches=[ - Csw('run', tagopt_for(id)), - Csw('coverage', levopt_for(id) + annopt_for(id)) - ])) + id=id, + gprcov=gprcov_for( + switches=[ + Csw("run", tagopt_for(id)), + Csw("coverage", levopt_for(id) + annopt_for(id)), + ] + ), +) # Check that "*" applies to all. Pass --level there. -id = 'star_valid' +id = "star_valid" check_valid_sequence_for( - id=id, gprcov=gprcov_for(switches=[ - Csw('*', levopt_for(id)), - Csw('run', tagopt_for(id)), - Csw('coverage', annopt_for(id)) - ])) + id=id, + gprcov=gprcov_for( + switches=[ + Csw("*", levopt_for(id)), + Csw("run", tagopt_for(id)), + Csw("coverage", annopt_for(id)), + ] + ), +) # Check that command specific args prevail over "*", with "*" placed # before in the gpr file. -id = 'star_postover' +id = "star_postover" check_valid_sequence_for( - id=id, gprcov=gprcov_for(switches=[ - Csw('*', ['--level=stmt+mcdc']), - Csw('run', tagopt_for(id)), - Csw('coverage', levopt_for(id) + annopt_for(id))])) + id=id, + gprcov=gprcov_for( + switches=[ + Csw("*", ["--level=stmt+mcdc"]), + Csw("run", tagopt_for(id)), + Csw("coverage", levopt_for(id) + annopt_for(id)), + ] + ), +) # Likewise, with "*" placed after in the gpr file. -id = 'star_preover' +id = "star_preover" check_valid_sequence_for( - id=id, gprcov=gprcov_for(switches=[ - Csw('run', tagopt_for(id)), - Csw('coverage', levopt_for(id) + annopt_for(id)), - Csw('*', ['--level=stmt+mcdc'])])) + id=id, + gprcov=gprcov_for( + switches=[ + Csw("run", tagopt_for(id)), + Csw("coverage", levopt_for(id) + annopt_for(id)), + Csw("*", ["--level=stmt+mcdc"]), + ] + ), +) # Check that "*" applies to all. Pass invalid for run, check failure. -id = 'star_invalid' -gpr = gprvariant(id=id, extra=gprcov_for(switches=[Csw('*', annopt_for(id))])) +id = "star_invalid" +gpr = gprvariant(id=id, extra=gprcov_for(switches=[Csw("*", annopt_for(id))])) rlog = try_run(id, gpr) thistest.fail_if( '--annotate is not valid with the "run" command.' not in rlog, - 'missing expected failure indication in run log for %s' % id) + "missing expected failure indication in run log for %s" % id, +) thistest.result() diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/test.py b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/test.py index 0ea9858a0..a86ede146 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/test.py +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/test.py @@ -8,43 +8,52 @@ from SUITE.tutils import gprfor -pgm = 'test_lt0' -wd = Wdir('wd_') +pgm = "test_lt0" +wd = Wdir("wd_") # Build and run the single test program, which volontarily performs stmt and # decision coverage violations. # # Enforce --level=stmt+decision here. Check that Default_Switches in # subprojects are ignored -gpr = gprfor(mains=[pgm + '.adb'], - srcdirs=['../src'], - deps=['../App/app'], - extra=gprcov_for(switches=[ - Csw('*', ['--level=stmt+decision']), - Csw('coverage', ['--annotate=report'])])) +gpr = gprfor( + mains=[pgm + ".adb"], + srcdirs=["../src"], + deps=["../App/app"], + extra=gprcov_for( + switches=[ + Csw("*", ["--level=stmt+decision"]), + Csw("coverage", ["--annotate=report"]), + ] + ), +) build_run_and_coverage( gprsw=GPRswitches(root_project=gpr, no_subprojects=False), covlevel=None, mains=[pgm], - extra_coverage_args=['-o', 'def.rep']) + extra_coverage_args=["-o", "def.rep"], +) # Check that we get results corresponding to the root project file despite # "overrides" (other Switches) in subprojects. -rep = contents_of('def.rep') +rep = contents_of("def.rep") -thistest.fail_if(not os.path.exists('def.rep'), - "couldn't find default report") +thistest.fail_if(not os.path.exists("def.rep"), "couldn't find default report") -thistest.fail_if(not re.search('statement not executed', rep), - 'missing expected stmt coverage failure indication') +thistest.fail_if( + not re.search("statement not executed", rep), + "missing expected stmt coverage failure indication", +) thistest.fail_if( - not re.search(r'test.*\.adb:.*: decision outcome .* never exercised', rep), - 'missing expected decision coverage failure indication') + not re.search(r"test.*\.adb:.*: decision outcome .* never exercised", rep), + "missing expected decision coverage failure indication", +) thistest.fail_if( - not re.search('values.adb:.*: decision outcome .* never exercised', rep), - 'missing expected decision coverage failure indication') + not re.search("values.adb:.*: decision outcome .* never exercised", rep), + "missing expected decision coverage failure indication", +) thistest.result() diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/MultiMain/test.py b/testsuite/Qualif/Common/GprFacilities/MainAttr/MultiMain/test.py index f4d98a17b..23d6b3631 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/MultiMain/test.py +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/MultiMain/test.py @@ -5,38 +5,44 @@ from SUITE.tutils import exepath_to, gprbuild, gprfor, xcov, xrun -wd = Wdir('wd_') +wd = Wdir("wd_") # GPR with multiple mains -gprname = 'gen' -mainbases = ['test_tt', 'test_tf'] -mainunits = [base + '.adb' for base in mainbases] +gprname = "gen" +mainbases = ["test_tt", "test_tf"] +mainunits = [base + ".adb" for base in mainbases] -gprbuild(gprfor(prjid=gprname, - srcdirs=['../../../../src', '../../src'], - mains=mainunits)) +gprbuild( + gprfor( + prjid=gprname, + srcdirs=["../../../../src", "../../src"], + mains=mainunits, + ) +) # We expect this to work. The multiple mains in the gpr file are just ignored # when there is an exe on the command line. -exe = exepath_to('test_tt') -trace = 'tt.trace0' -dump = 'tt.dump0' +exe = exepath_to("test_tt") +trace = "tt.trace0" +dump = "tt.dump0" -xrun(['-P', gprname, '-o', trace, exe]) -xcov(['dump-trace', trace], out=dump) +xrun(["-P", gprname, "-o", trace, exe]) +xcov(["dump-trace", trace], out=dump) thistest.fail_if( - len(re.findall('t block$', contents_of(dump), flags=re.M)) < 1, - 'with exe, no block execution trace found in %s' % trace) + len(re.findall("t block$", contents_of(dump), flags=re.M)) < 1, + "with exe, no block execution trace found in %s" % trace, +) # Again, _not_ providing the executable. Expected to fail # from missing command line argument. -trace = 'oops.trace0' -dump = 'oops.dump' -xrun(['-P', gprname, '-o', trace], out=dump, register_failure=False) +trace = "oops.trace0" +dump = "oops.dump" +xrun(["-P", gprname, "-o", trace], out=dump, register_failure=False) thistest.fail_if( - not match(': Please specify an executable to run', dump), - 'missing expected error diag on main-less invocation of gnatcov run') + not match(": Please specify an executable to run", dump), + "missing expected error diag on main-less invocation of gnatcov run", +) thistest.result() diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/SingleMain/test.py b/testsuite/Qualif/Common/GprFacilities/MainAttr/SingleMain/test.py index 2f4fffadf..fd35410a5 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/SingleMain/test.py +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/SingleMain/test.py @@ -5,22 +5,20 @@ from SUITE.tutils import exepath_to, gprbuild, gprfor, xcov, xrun -wd = Wdir('wd_') +wd = Wdir("wd_") # We have two candidate main drivers. Craft a gpr # with a Main attribute listing only the first one. -mainbase1 = 'test_tt' -mainunit1 = mainbase1 + '.adb' +mainbase1 = "test_tt" +mainunit1 = mainbase1 + ".adb" exe1 = exepath_to(mainbase1) -mainbase2 = 'test_tf' -mainunit2 = mainbase2 + '.adb' +mainbase2 = "test_tf" +mainunit2 = mainbase2 + ".adb" exe2 = exepath_to(mainbase2) -gprname = gprfor( - srcdirs=['../../../../src', '../../src'], - mains=[mainunit1]) +gprname = gprfor(srcdirs=["../../../../src", "../../src"], mains=[mainunit1]) # Build both executables, passing both main unit # names on the command line: @@ -32,22 +30,23 @@ # at least an entry showing actual execution of something # for this particular case. -def check(explicit_exe): +def check(explicit_exe): outbase = explicit_exe if explicit_exe else "noexe" - trace = '%s.trace' % outbase - dump = '%s.dt' % outbase + trace = "%s.trace" % outbase + dump = "%s.dt" % outbase - runcmd = ['-P', gprname, '-o', trace] + runcmd = ["-P", gprname, "-o", trace] if explicit_exe: runcmd.append(explicit_exe) xrun(runcmd) - xcov(['dump-trace', trace], out=dump) + xcov(["dump-trace", trace], out=dump) thistest.fail_if( - len(re.findall('t block$', contents_of(dump), flags=re.M)) < 1, - 'with %s, no block trace entry found in %s' % (outbase, trace)) + len(re.findall("t block$", contents_of(dump), flags=re.M)) < 1, + "with %s, no block trace entry found in %s" % (outbase, trace), + ) # With an explicit exe1, we just confirm what the Main attribute diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/ZeroMain/test.py b/testsuite/Qualif/Common/GprFacilities/MainAttr/ZeroMain/test.py index 615dd6301..95646e1ba 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/ZeroMain/test.py +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/ZeroMain/test.py @@ -5,28 +5,33 @@ from SUITE.tutils import exepath_to, gprbuild, gprfor, xcov, xrun -wd = Wdir('wd_') +wd = Wdir("wd_") # GPR without a main. # # We must provide the main executable on the command line. -gprname = 'tt_nomain' -mainbase = 'test_tf' -mainunit = mainbase + '.adb' +gprname = "tt_nomain" +mainbase = "test_tf" +mainunit = mainbase + ".adb" exe = exepath_to(mainbase) -gprbuild(gprfor(prjid=gprname, - srcdirs=['../../../../src', '../../src'], - mains='', - langs=['Ada']), - gargs=[mainunit]) +gprbuild( + gprfor( + prjid=gprname, + srcdirs=["../../../../src", "../../src"], + mains="", + langs=["Ada"], + ), + gargs=[mainunit], +) -trace = 'tf.trace0' -dump = 'tf.dump0' -xrun(['-P', gprname, exe, '-o', trace]) -xcov(['dump-trace', trace], out=dump) +trace = "tf.trace0" +dump = "tf.dump0" +xrun(["-P", gprname, exe, "-o", trace]) +xcov(["dump-trace", trace], out=dump) thistest.fail_if( - len(re.findall('t block$', contents_of(dump), flags=re.M)) < 1, - 'with exe, no block execution trace found in %s' % trace) + len(re.findall("t block$", contents_of(dump), flags=re.M)) < 1, + "with exe, no block execution trace found in %s" % trace, +) thistest.result() diff --git a/testsuite/Qualif/Common/GprFacilities/Subdirs/BuildRunAnalyze/test.py b/testsuite/Qualif/Common/GprFacilities/Subdirs/BuildRunAnalyze/test.py index a26aaad47..5699b06ec 100644 --- a/testsuite/Qualif/Common/GprFacilities/Subdirs/BuildRunAnalyze/test.py +++ b/testsuite/Qualif/Common/GprFacilities/Subdirs/BuildRunAnalyze/test.py @@ -9,28 +9,31 @@ from SUITE.tutils import gprfor -wd = Wdir('wd_') +wd = Wdir("wd_") -gprname = 'p' -mainunit = 'foo.adb' -subdir = 'gnatcov' -mainunit_xcov = os.path.join('obj', subdir, mainunit + '.xcov') +gprname = "p" +mainunit = "foo.adb" +subdir = "gnatcov" +mainunit_xcov = os.path.join("obj", subdir, mainunit + ".xcov") # Arrange to build, run and perform coverage analysis passing # --subdirs to all gprbuild and gnatcov commands, then verify that # we find a report in the designated subdir afterwards. build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(prjid=gprname, mains=[mainunit], - srcdirs=['..']), - subdirs=subdir), - covlevel='stmt', - mains=['foo'], - extra_coverage_args=['-a', 'xcov']) + gprsw=GPRswitches( + root_project=gprfor(prjid=gprname, mains=[mainunit], srcdirs=[".."]), + subdirs=subdir, + ), + covlevel="stmt", + mains=["foo"], + extra_coverage_args=["-a", "xcov"], +) thistest.fail_if( not os.path.exists(mainunit_xcov), - 'The coverage report is missing: {}'.format(mainunit_xcov)) + "The coverage report is missing: {}".format(mainunit_xcov), +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py index 417bbe8a8..e2689ee36 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py @@ -6,9 +6,12 @@ wd = Wdir() wd.to_subdir("wd_1") -TestCase(category=None).run(covcontrol=CovControl( - ulist_in="../" + list_to_file(["ops*"]), - units_out=['ops.orelse'], - xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"])) +TestCase(category=None).run( + covcontrol=CovControl( + ulist_in="../" + list_to_file(["ops*"]), + units_out=["ops.orelse"], + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py index f06f21db1..701c96741 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py @@ -10,19 +10,27 @@ wd.to_subdir("wd_1") TestCase(category=None).run( - covcontrol=CovControl(ulist_in="../" + list_to_file(["ops"]), - xreports=["ops.ads", "ops.adb"])) + covcontrol=CovControl( + ulist_in="../" + list_to_file(["ops"]), xreports=["ops.ads", "ops.adb"] + ) +) # Check on lone node + child unit wd.to_subdir("wd_2") -TestCase(category=None).run(covcontrol=CovControl( - ulist_in="../" + list_to_file(["ops", "ops.andthen"]), - xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"])) +TestCase(category=None).run( + covcontrol=CovControl( + ulist_in="../" + list_to_file(["ops", "ops.andthen"]), + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], + ) +) # Check on lone child unit only wd.to_subdir("wd_3") TestCase(category=None).run( - covcontrol=CovControl(ulist_in="../" + list_to_file(["ops.andthen"]), - xreports=["ops-andthen.ads", "ops-andthen.adb"])) + covcontrol=CovControl( + ulist_in="../" + list_to_file(["ops.andthen"]), + xreports=["ops-andthen.ads", "ops-andthen.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py index c9e94ebd9..8a2c61223 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py @@ -7,9 +7,12 @@ # Mixing units and lists to include wd = Wdir() wd.to_subdir("wd_1") -TestCase(category=None).run(covcontrol=CovControl( - units_in=["ops"], - ulist_in=list_to_tmp(["ops.andthen"]), - xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"])) +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops"], + ulist_in=list_to_tmp(["ops.andthen"]), + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py index 8813d6201..0bf62d2d0 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py @@ -8,13 +8,19 @@ wd = Wdir() wd.to_subdir("wd_1") TestCase(category=None).run( - covcontrol=CovControl(units_in=["ops", "ops.andthen"], - ulist_out=list_to_tmp(["ops"]), - xreports=["ops-andthen.ads", "ops-andthen.adb"])) + covcontrol=CovControl( + units_in=["ops", "ops.andthen"], + ulist_out=list_to_tmp(["ops"]), + xreports=["ops-andthen.ads", "ops-andthen.adb"], + ) +) TestCase(category=None).run( - covcontrol=CovControl(units_in=["ops", "ops.andthen"], - units_out=["ops.andthen"], - xreports=["ops.ads", "ops.adb"])) + covcontrol=CovControl( + units_in=["ops", "ops.andthen"], + units_out=["ops.andthen"], + xreports=["ops.ads", "ops.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py index b016fedb3..dce70ded8 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py @@ -7,21 +7,27 @@ wd = Wdir() # Check on lone node unit only -wd.to_subdir('wd_1') -TestCase(category=None).run(covcontrol=CovControl( - units_in=['ops'], - xreports=['ops.ads', 'ops.adb'])) +wd.to_subdir("wd_1") +TestCase(category=None).run( + covcontrol=CovControl(units_in=["ops"], xreports=["ops.ads", "ops.adb"]) +) # Check on lone node + child unit -wd.to_subdir('wd_2') -TestCase(category=None).run(covcontrol=CovControl( - units_in=['ops', 'ops.andthen'], - xreports=['ops.ads', 'ops.adb', 'ops-andthen.ads', 'ops-andthen.adb'])) +wd.to_subdir("wd_2") +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops", "ops.andthen"], + xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], + ) +) # Check on lone child unit only -wd.to_subdir('wd_3') -TestCase(category=None).run(covcontrol=CovControl( - units_in=['ops.andthen'], - xreports=['ops-andthen.ads', 'ops-andthen.adb'])) +wd.to_subdir("wd_3") +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops.andthen"], + xreports=["ops-andthen.ads", "ops-andthen.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py index b9d1e2f64..12f04a399 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py @@ -13,22 +13,31 @@ # Out overlaps In wd.to_subdir("wd_1") -TestCase(category=None).run(covcontrol=CovControl( - units_in=["ops", "ops.andthen"], - units_out=["ops.andthen"], - xreports=["ops.ads", "ops.adb"])) - -TestCase(category=None).run(covcontrol=CovControl( - units_in=["ops", "ops.andthen", "ops.orelse"], - units_out=["ops", "ops.andthen"], - xreports=["ops-orelse.ads", "ops-orelse.adb"])) +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops", "ops.andthen"], + units_out=["ops.andthen"], + xreports=["ops.ads", "ops.adb"], + ) +) + +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops", "ops.andthen", "ops.orelse"], + units_out=["ops", "ops.andthen"], + xreports=["ops-orelse.ads", "ops-orelse.adb"], + ) +) # Out does not overlap In wd.to_subdir("wd_2") -TestCase(category=None).run(covcontrol=CovControl( - units_in=["ops", "ops.orelse"], - units_out=["ops.andthen"], - xreports=["ops.ads", "ops.adb", "ops-orelse.ads", "ops-orelse.adb"])) +TestCase(category=None).run( + covcontrol=CovControl( + units_in=["ops", "ops.orelse"], + units_out=["ops.andthen"], + xreports=["ops.ads", "ops.adb", "ops-orelse.ads", "ops-orelse.adb"], + ) +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/DefaultClosure/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/DefaultClosure/test.py index c960dc87f..b74ff2ee0 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/DefaultClosure/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/DefaultClosure/test.py @@ -10,9 +10,10 @@ # expect intops, boolops and conters related reports check( - root_project='gen.gpr', + root_project="gen.gpr", recurse=None, - xreports=['intops', 'boolops', 'counters']) + xreports=["intops", "boolops", "counters"], +) # -Pgen, non recursive would yield an empty set of # units of interest, so try another level first: @@ -21,18 +22,20 @@ # expect intops and counters related reports check( - root_project='gen.gpr', - projects=['intops'], + root_project="gen.gpr", + projects=["intops"], recurse=None, - xreports=['intops', 'counters']) + xreports=["intops", "counters"], +) # -Pgen --projects=intops --no-subprojects # expect intops related report only check( - root_project='gen.gpr', - projects=['intops'], + root_project="gen.gpr", + projects=["intops"], recurse=False, - xreports=['intops']) + xreports=["intops"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectClosures/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectClosures/test.py index 210645f48..4cf1d3770 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectClosures/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectClosures/test.py @@ -5,26 +5,29 @@ # expect intops, boolops & counters reports check( - root_project='gen.gpr', + root_project="gen.gpr", recurse=True, - xreports=['intops', 'boolops', 'counters']) + xreports=["intops", "boolops", "counters"], +) # -Pgen --projects=intops.gpr, recursive, # expect intops & counters reports check( - root_project='gen.gpr', - projects=['intops'], + root_project="gen.gpr", + projects=["intops"], recurse=True, - xreports=['intops', 'counters']) + xreports=["intops", "counters"], +) # -Pgen --projects=boolops.gpr, recursive, # expect boolops & counters reports check( - root_project='gen.gpr', - projects=['boolops'], + root_project="gen.gpr", + projects=["boolops"], recurse=True, - xreports=['boolops', 'counters']) + xreports=["boolops", "counters"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py index 729910a2c..cf7be0892 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectSets/test.py @@ -5,36 +5,40 @@ # expect intops related reports only check( - root_project='gen.gpr', - projects=['intops'], + root_project="gen.gpr", + projects=["intops"], recurse=False, - xreports=['intops']) + xreports=["intops"], +) # -Pgen --projects=boolops.gpr, not recursive, # expect boolops related reports only check( - root_project='gen.gpr', - projects=['boolops'], + root_project="gen.gpr", + projects=["boolops"], recurse=False, - xreports=['boolops']) + xreports=["boolops"], +) # -Pgen --projects=boolops.gpr --projects=intops.gpr, not recursive # expect boolops & intops related reports check( - root_project='gen.gpr', - projects=['boolops', 'intops'], + root_project="gen.gpr", + projects=["boolops", "intops"], recurse=False, - xreports=['boolops', 'intops']) + xreports=["boolops", "intops"], +) # -Pgen --projects=boolops.gpr --projects=counters.gpr, not recursive # expect boolops & counters related reports check( - root_project='gen.gpr', - projects=['boolops', 'counters'], + root_project="gen.gpr", + projects=["boolops", "counters"], recurse=False, - xreports=['boolops', 'counters']) + xreports=["boolops", "counters"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py index 04ca0430f..7add63252 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py @@ -9,7 +9,7 @@ # Create a directory to hold temporary files, so that we do not accumulate # uncleaned temporary files across testsuite runs. -temp_file_dir = Wdir('tmp_files') +temp_file_dir = Wdir("tmp_files") temp_file_dir.to_homedir() # Note that intops involves sub-units while boolops involves child-units, @@ -17,43 +17,53 @@ # Lone unit, with sub units, in closure check( - root_project='gen.gpr', - units=['intops'], + root_project="gen.gpr", + units=["intops"], recurse=True, - xreports=['intops.ads', 'intops.adb', - 'intops-add.ads', 'intops-add.adb', - 'intops-sub.ads', 'intops-sub.adb']) + xreports=[ + "intops.ads", + "intops.adb", + "intops-add.ads", + "intops-add.adb", + "intops-sub.ads", + "intops-sub.adb", + ], +) # Lone unit, with child units, in closure check( - root_project='../boolops/boolops', - units=['boolops'], + root_project="../boolops/boolops", + units=["boolops"], recurse=True, - xreports=['boolops.ads', 'boolops.adb']) + xreports=["boolops.ads", "boolops.adb"], +) # Likewise, using a response file to convey the units. check( - root_project='../boolops/boolops', - units=['@%s' % list_to_tmp(['boolops'], dir='tmp_files')], + root_project="../boolops/boolops", + units=["@%s" % list_to_tmp(["boolops"], dir="tmp_files")], recurse=True, - xreports=['boolops.ads', 'boolops.adb']) + xreports=["boolops.ads", "boolops.adb"], +) # Lone child unit from single project, either from -P + --projects # or from a -P designating the subproject directly check( - root_project='../boolops/boolops', - units=['boolops.andthen'], + root_project="../boolops/boolops", + units=["boolops.andthen"], recurse=False, - xreports=['boolops.ads', 'boolops-andthen.ads', 'boolops-andthen.adb']) + xreports=["boolops.ads", "boolops-andthen.ads", "boolops-andthen.adb"], +) check( - root_project='gen.gpr', - projects=['boolops'], - units=['boolops.andthen'], + root_project="gen.gpr", + projects=["boolops"], + units=["boolops.andthen"], recurse=False, - xreports=['boolops.ads', 'boolops-andthen.ads', 'boolops-andthen.adb']) + xreports=["boolops.ads", "boolops-andthen.ads", "boolops-andthen.adb"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/UnitsOverrides/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/UnitsOverrides/test.py index 22ac96f4b..4fab73d96 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/UnitsOverrides/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/UnitsOverrides/test.py @@ -11,26 +11,29 @@ # Without --units, on closure -> everything check( - root_project='gen.gpr', + root_project="gen.gpr", recurse=True, - xreports=['intops', 'boolops', 'counters']) + xreports=["intops", "boolops", "counters"], +) # --units=boolops.andthen in closure, andthen and parent # spec reports only, despite the attribute in boolops.gpr check( - root_project='gen.gpr', + root_project="gen.gpr", recurse=True, - units=['boolops.andthen'], - xreports=['boolops.ads', 'boolops-andthen.ads', 'boolops-andthen.adb']) + units=["boolops.andthen"], + xreports=["boolops.ads", "boolops-andthen.ads", "boolops-andthen.adb"], +) # --units=counters in closure, counters reports only # despite the attribute in boolops.gpr check( - root_project='gen.gpr', + root_project="gen.gpr", recurse=True, - units=['counters'], - xreports=['counters.ads', 'counters.adb']) + units=["counters"], + xreports=["counters.ads", "counters.adb"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py index 4d2be6ea9..2502f3e69 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py @@ -17,13 +17,23 @@ # The set of source file names with coverage obligations attached to # each project, designated by project short name. _xreports = { - 'boolops': ['boolops.ads', 'boolops.adb', - 'boolops-andthen.ads', 'boolops-andthen.adb', - 'boolops-orelse.ads', 'boolops-orelse.adb'], - 'intops': ['intops.ads', 'intops.adb', - 'intops-add.ads', 'intops-add.adb', - 'intops-sub.ads', 'intops-sub.adb'], - 'counters': ['counters.ads', 'counters.adb'], + "boolops": [ + "boolops.ads", + "boolops.adb", + "boolops-andthen.ads", + "boolops-andthen.adb", + "boolops-orelse.ads", + "boolops-orelse.adb", + ], + "intops": [ + "intops.ads", + "intops.adb", + "intops-add.ads", + "intops-add.adb", + "intops-sub.ads", + "intops-sub.adb", + ], + "counters": ["counters.ads", "counters.adb"], } all_projects = list(_xreports) @@ -61,25 +71,25 @@ def check(root_project, recurse, projects=None, units=None, xreports=None): # Append the first letter of each project name will pass through # --project, if any: if projects: - label += '-' + ''.join(prj[0] for prj in projects) + label += "-" + "".join(prj[0] for prj in projects) # Append indication on recursion request: if recurse: - label += '-rt' + label += "-rt" elif recurse is None: - label += '-rn' + label += "-rn" else: - label += '-rf' + label += "-rf" # Arrange to execute each check in its own temporary directory and copying # shared projects in that directory prevent mixups across test variants. - tmpdir = f'wd_{label}' + tmpdir = f"wd_{label}" wd = Wdir(tmpdir) # Copy shared projects in the temporary directory and create their object # directory to avoid spurious warnings. for p in all_projects: - sync_tree(os.path.join(wd.homedir, '..', p), p) + sync_tree(os.path.join(wd.homedir, "..", p), p) mkdir(os.path.join(p, "obj")) # If a list of expected reports is provided, convert into list of @@ -87,8 +97,7 @@ def check(root_project, recurse, projects=None, units=None, xreports=None): if xreports is not None: ctl_xreports = [] for xr in xreports: - ctl_xreports.extend( - _xreports[xr] if xr in _xreports else [xr]) + ctl_xreports.extend(_xreports[xr] if xr in _xreports else [xr]) else: ctl_xreports = None @@ -98,23 +107,19 @@ def check(root_project, recurse, projects=None, units=None, xreports=None): TestCase(category=None).run( covcontrol=CovControl( - # The programs we build and exercise always depend on the three # subprojects (copied above in the parent directory relative to the # TestCase temporary directory). - deps=[f'../{p}/{p}' for p in all_projects], - + deps=[f"../{p}/{p}" for p in all_projects], # What we analyse and check depends on our arguments: gprsw=GPRswitches( root_project=root_project, projects=projects, units=units, no_subprojects=no_subprojects, - xvars=[('BOARD', gnatemu_board_name(env.target.machine))], + xvars=[("BOARD", gnatemu_board_name(env.target.machine))], ), - xreports=ctl_xreports, - # The test driver and the likes are never of interest units_in=[], ), diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py index 6f2a5ef42..f218adcee 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py @@ -1,4 +1,3 @@ - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.gprutils import GPRswitches @@ -6,24 +5,27 @@ from SUITE.tutils import gprfor -wd = Wdir('wd_') +wd = Wdir("wd_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(mains=['test_lt0.adb'], - srcdirs=['../src'], - deps=['../App/app'])), - covlevel='stmt', - mains=['test_lt0'], - extra_args=['--projects=app_base'], - extra_coverage_args=['-axcov']) + gprsw=GPRswitches( + root_project=gprfor( + mains=["test_lt0.adb"], srcdirs=["../src"], deps=["../App/app"] + ) + ), + covlevel="stmt", + mains=["test_lt0"], + extra_args=["--projects=app_base"], + extra_coverage_args=["-axcov"], +) # App_Base is extended by App; App overrides Coverage'Units so that only Values # (not Values.Aux) is selected. check_xcov_reports( - 'obj', + "obj", { - 'values.ads.xcov': {}, - 'values.adb.xcov': {'+': {5, 6}, '-': {8}}, + "values.ads.xcov": {}, + "values.adb.xcov": {"+": {5, 6}, "-": {8}}, }, # See eng/das/cov/gnatcoverage#245 discard_empty=False, diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py index abd0e2fce..99b9600e7 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py @@ -10,38 +10,42 @@ from SUITE.tutils import gprfor -wd = Wdir('wd_') +wd = Wdir("wd_") # Prepare the two project files -p = gprfor(prjid='p', mains=['main1.adb'], srcdirs=['../src'], - objdir='obj-p') -ext_p = 'ext_p.gpr' -with open(ext_p, 'w') as f: - f.write(""" +p = gprfor(prjid="p", mains=["main1.adb"], srcdirs=["../src"], objdir="obj-p") +ext_p = "ext_p.gpr" +with open(ext_p, "w") as f: + f.write( + """ project Ext_P extends "{}" is for Source_Dirs use ("../ext-src"); for Object_Dir use "ext-obj"; for Exec_Dir use "."; for Main use ("main1.adb", "main2.adb"); end Ext_P; - """.format(p)) + """.format( + p + ) + ) build_run_and_coverage( gprsw=GPRswitches(root_project=ext_p), - covlevel='stmt', - mains=['main1', 'main2'], - gpr_obj_dir='ext-obj', - extra_coverage_args=['-axcov']) + covlevel="stmt", + mains=["main1", "main2"], + gpr_obj_dir="ext-obj", + extra_coverage_args=["-axcov"], +) # In blob.ads, we expect either '+' or '.' on everything, depending # on the toolchain. Let check_xcov_reports refine that. check_xcov_reports( - 'ext-obj', + "ext-obj", { - 'blob.ads.xcov': {}, - 'main1.adb.xcov': {'+': {5}}, - 'main2.adb.xcov': {'+': {5, 6}}, + "blob.ads.xcov": {}, + "main1.adb.xcov": {"+": {5}}, + "main2.adb.xcov": {"+": {5, 6}}, }, # See eng/das/cov/gnatcoverage#245 discard_empty=False, diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py index 6510d5f62..f9ef4886b 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py @@ -12,37 +12,42 @@ from SUITE.tutils import gprfor -tmp = Wdir('wd_') +tmp = Wdir("wd_") # The "orig" project contains two units: "main" and "helper". The "ext" project # extends "orig" and overrides only the "helper" unit. # # Previously, gnatcov used to consider that the only unit of interest was # "helper". It now also consider that "main" is a unit of interest. -orig_prj = gprfor(prjid='orig', mains=['main.adb'], srcdirs='..') -ext_prj = 'ext.gpr' -with open(ext_prj, 'w') as f: - f.write(""" +orig_prj = gprfor(prjid="orig", mains=["main.adb"], srcdirs="..") +ext_prj = "ext.gpr" +with open(ext_prj, "w") as f: + f.write( + """ project Ext extends "{}" is for Source_Dirs use ("../src-ext"); for Object_Dir use "obj-ext"; end Ext; -""".format(orig_prj)) +""".format( + orig_prj + ) + ) build_run_and_coverage( gprsw=GPRswitches(root_project=ext_prj), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov'], - gpr_obj_dir='obj-ext', - gpr_exe_dir='obj-ext') + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + gpr_obj_dir="obj-ext", + gpr_exe_dir="obj-ext", +) check_xcov_reports( - 'obj-ext', + "obj-ext", { - 'main.adb.xcov': {'+': {5}}, - 'helper.ads.xcov': {}, - 'helper.adb.xcov': {'+': {4}}, + "main.adb.xcov": {"+": {5}}, + "helper.ads.xcov": {}, + "helper.adb.xcov": {"+": {4}}, }, # See eng/das/cov/gnatcoverage#245 discard_empty=False, diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py index f1f9e94b6..39aee8d1b 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py @@ -14,10 +14,10 @@ import e3.fs -root_project = os.path.abspath('root.gpr') +root_project = os.path.abspath("root.gpr") board = gnatemu_board_name(env.target.machine) -board_arg = '-XBOARD={}'.format(board) -wd = Wdir('wd_') +board_arg = "-XBOARD={}".format(board) +wd = Wdir("wd_") # Every project of interest is setup to feature a single unit named after the # project. Dumping the units of interest for a given analysis, with @@ -32,12 +32,13 @@ root_project=root_project, xvars=[("BOARD", board)], ), - mains=['root'], - covlevel='stmt', - gpr_obj_dir='../obj', - gpr_exe_dir='../obj', + mains=["root"], + covlevel="stmt", + gpr_obj_dir="../obj", + gpr_exe_dir="../obj", extra_args=[board_arg], - extra_coverage_args=[]) + extra_coverage_args=[], +) trace = cov_cmdline[-1] @@ -52,25 +53,35 @@ def check(options, xunits): # Compute the name of a unique output dir for the reports, # based on the options. - opt_str = ''.join( - [opt. - replace('--projects=', ''). - replace('root', 'r'). - replace('../', ''). - replace('.gpr', ''). - replace('_X=True', ''). - replace('--no-subprojects', 'ns'). - strip('-') - for opt in options]) - - odir = 'tmp_' + opt_str - ofile = os.path.join(odir, 'dump-units') - - xcov(['coverage', trace, '--level=stmt', '--annotate=xcov', - '--output-dir={}'.format(odir), - '--dump-units-to={}'.format(ofile), - board_arg] + options, - out='cov-' + opt_str + '.log') + opt_str = "".join( + [ + opt.replace("--projects=", "") + .replace("root", "r") + .replace("../", "") + .replace(".gpr", "") + .replace("_X=True", "") + .replace("--no-subprojects", "ns") + .strip("-") + for opt in options + ] + ) + + odir = "tmp_" + opt_str + ofile = os.path.join(odir, "dump-units") + + xcov( + [ + "coverage", + trace, + "--level=stmt", + "--annotate=xcov", + "--output-dir={}".format(odir), + "--dump-units-to={}".format(ofile), + board_arg, + ] + + options, + out="cov-" + opt_str + ".log", + ) # Primary check, from the list of units reported by --dump-units-to @@ -81,7 +92,8 @@ def check(options, xunits): runits != xunits, "for options '{}', reported list of units not as expected:\n" "expected: {}\n" - "obtained: {}".format(' '.join(options), xunits, runits)) + "obtained: {}".format(" ".join(options), xunits, runits), + ) # Secondary check, from the set of generated reports @@ -92,14 +104,16 @@ def check(options, xunits): # subdir part and the extension. runits = set( - os.path.basename(r).split('.')[0] for r in - e3.fs.ls(os.path.join(odir, '*.xcov'))) + os.path.basename(r).split(".")[0] + for r in e3.fs.ls(os.path.join(odir, "*.xcov")) + ) thistest.fail_if( runits != xunits, "for options '{}', list of units from reports not as expected:\n" "expected: {}\n" - "obtained: {}".format(' '.join(options), xunits, runits)) + "obtained: {}".format(" ".join(options), xunits, runits), + ) # -P alone, recursive or not @@ -107,22 +121,23 @@ def check(options, xunits): # No externally built -check(options=['-P', '../root.gpr'], - xunits=['root', 'ssa', 'a1', 'ssb', 'b1', 'common']) +check( + options=["-P", "../root.gpr"], + xunits=["root", "ssa", "a1", "ssb", "b1", "common"], +) -check(options=['-P', '../root.gpr', '--no-subprojects'], - xunits=['root']) +check(options=["-P", "../root.gpr", "--no-subprojects"], xunits=["root"]) -check(options=['-P', '../ssa.gpr'], - xunits=['ssa', 'a1', 'common']) +check(options=["-P", "../ssa.gpr"], xunits=["ssa", "a1", "common"]) -check(options=['-P', '../ssa.gpr', '--no-subprojects'], - xunits=['ssa']) +check(options=["-P", "../ssa.gpr", "--no-subprojects"], xunits=["ssa"]) # ssa externally built -check(options=['-P', '../root.gpr', '-XSSA_X=True'], - xunits=['root', 'a1', 'ssb', 'b1', 'common']) +check( + options=["-P", "../root.gpr", "-XSSA_X=True"], + xunits=["root", "a1", "ssb", "b1", "common"], +) # -P --projects, recursive or not @@ -131,40 +146,67 @@ def check(options, xunits): # No externally built # Recursive from single child of root, not including root -check(options=['-P', '../root.gpr', '--projects=ssa'], - xunits=['ssa', 'a1', 'common']) +check( + options=["-P", "../root.gpr", "--projects=ssa"], + xunits=["ssa", "a1", "common"], +) -check(options=['-P', '../root.gpr', '--projects=ssb'], - xunits=['ssb', 'b1', 'common']) +check( + options=["-P", "../root.gpr", "--projects=ssb"], + xunits=["ssb", "b1", "common"], +) # Non recursive from single child of root, not including root -check(options=['-P', '../root.gpr', '--projects=ssa', '--no-subprojects'], - xunits=['ssa']) +check( + options=["-P", "../root.gpr", "--projects=ssa", "--no-subprojects"], + xunits=["ssa"], +) -check(options=['-P', '../root.gpr', '--projects=ssb', '--no-subprojects'], - xunits=['ssb']) +check( + options=["-P", "../root.gpr", "--projects=ssb", "--no-subprojects"], + xunits=["ssb"], +) # Non recursive from multiple children of root, not including root -check(options=['-P', '../root.gpr', - '--projects=ssa', '--projects=ssb', - '--no-subprojects'], - xunits=['ssa', 'ssb']) - -check(options=['-P', '../root.gpr', - '--projects=ssa', '--projects=b1', - '--no-subprojects'], - xunits=['ssa', 'b1']) +check( + options=[ + "-P", + "../root.gpr", + "--projects=ssa", + "--projects=ssb", + "--no-subprojects", + ], + xunits=["ssa", "ssb"], +) + +check( + options=[ + "-P", + "../root.gpr", + "--projects=ssa", + "--projects=b1", + "--no-subprojects", + ], + xunits=["ssa", "b1"], +) # Non recursive including root -check(options=['-P', '../root.gpr', - '--projects=root', '--projects=ssb', - '--no-subprojects'], - xunits=['root', 'ssb']) +check( + options=[ + "-P", + "../root.gpr", + "--projects=root", + "--projects=ssb", + "--no-subprojects", + ], + xunits=["root", "ssb"], +) # ssb externally built -check(options=['-P', '../root.gpr', - '--projects=ssb', '-XSSB_X=True'], - xunits=['b1', 'common']) +check( + options=["-P", "../root.gpr", "--projects=ssb", "-XSSB_X=True"], + xunits=["b1", "common"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py index c48ec991a..b22dece24 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py @@ -9,24 +9,29 @@ def check(subdir, opspkg, xreports): - wd.to_subdir(subdir) - ops_gpr = gprfor( - mains=[], prjid="ops", srcdirs="../src/ops", extra=opspkg + ops_gpr = gprfor(mains=[], prjid="ops", srcdirs="../src/ops", extra=opspkg) + + TestCase(category=None).run( + covcontrol=CovControl( + deps=["../ops.gpr"], units_in=[], xreports=xreports + ) ) - TestCase(category=None).run(covcontrol=CovControl( - deps=["../ops.gpr"], units_in=[], xreports = xreports - )) # ops.gpr: no attribute check( opspkg="", - xreports=["ops.adb", "ops.ads", - "ops-andthen.ads", "ops-andthen.adb", - "ops-orelse.ads", "ops-orelse.adb"], + xreports=[ + "ops.adb", + "ops.ads", + "ops-andthen.ads", + "ops-andthen.adb", + "ops-orelse.ads", + "ops-orelse.adb", + ], subdir="wd_1", ) @@ -50,8 +55,8 @@ def check(subdir, opspkg, xreports): check( opspkg=gprcov_for( - units_in=["ops", "ops.orelse", "ops.andthen"], - units_out=["ops.orelse"]), + units_in=["ops", "ops.orelse", "ops.andthen"], units_out=["ops.orelse"] + ), xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], subdir="wd_3", ) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py index 6577db851..0781acae8 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py @@ -9,27 +9,33 @@ from SUITE.tutils import gprfor -tmp = Wdir('wd_') +tmp = Wdir("wd_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor( - 'main.adb', - srcdirs='..', - extra=gprcov_for(units_in=['no_such_unit', 'main']))), - covlevel='stmt', - mains=['main'], + gprsw=GPRswitches( + root_project=gprfor( + "main.adb", + srcdirs="..", + extra=gprcov_for(units_in=["no_such_unit", "main"]), + ) + ), + covlevel="stmt", + mains=["main"], tolerate_instrument_messages="no unit.*in project", - extra_coverage_args=['-axcov'], + extra_coverage_args=["-axcov"], ) -log_file = ('coverage.log' - if thistest.options.trace_mode == 'bin' else - 'instrument.log') +log_file = ( + "coverage.log" + if thistest.options.trace_mode == "bin" + else "instrument.log" +) thistest.fail_if_not_equal( - 'gnatcov output', - 'warning: no unit no_such_unit in project gen (coverage.units attribute)', - contents_of(log_file).strip()) + "gnatcov output", + "warning: no unit no_such_unit in project gen (coverage.units attribute)", + contents_of(log_file).strip(), +) -check_xcov_reports('obj', {'main.adb.xcov': {'+': {5}}}) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py index 2f8474220..4e17fc823 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py @@ -9,35 +9,40 @@ from SUITE.tutils import gprfor -tmp = Wdir('wd_') +tmp = Wdir("wd_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor('main.adb', srcdirs='..'), - units=['no_such_unit', 'main', 'helper.say_hello']), - covlevel='stmt', - mains=['main'], + gprsw=GPRswitches( + root_project=gprfor("main.adb", srcdirs=".."), + units=["no_such_unit", "main", "helper.say_hello"], + ), + covlevel="stmt", + mains=["main"], tolerate_instrument_messages="no unit.*in the projects of interest", - extra_coverage_args=['-axcov'], + extra_coverage_args=["-axcov"], ) -log_file = ('coverage.log' - if thistest.options.trace_mode == 'bin' else - 'instrument.log') +log_file = ( + "coverage.log" + if thistest.options.trace_mode == "bin" + else "instrument.log" +) # Split and re-join lines to avoid spurious CR/LF diffs on Windows. Also sort # lines, as the order in which these warnings is emitted is not deterministic. -log_lines = '\n'.join( +log_lines = "\n".join( sorted(line.rstrip() for line in contents_of(log_file).splitlines()) ).rstrip() thistest.fail_if_not_equal( - 'gnatcov output', - 'warning: no unit helper.say_hello (from --units) in the projects of' - ' interest' - '\nwarning: no unit no_such_unit (from --units) in the projects of' - ' interest', - log_lines) - -check_xcov_reports('obj', {'main.adb.xcov': {'+': {5}}}) + "gnatcov output", + "warning: no unit helper.say_hello (from --units) in the projects of" + " interest" + "\nwarning: no unit no_such_unit (from --units) in the projects of" + " interest", + log_lines, +) + +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py index 2b6881612..379c18e97 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py @@ -22,30 +22,32 @@ from SUITE.tutils import gprfor, xcov -tmp = Wdir('wd_') +tmp = Wdir("wd_") xcov_args = build_and_run( - gprsw=GPRswitches(root_project=gprfor('main.adb', srcdirs='..')), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov']) + gprsw=GPRswitches(root_project=gprfor("main.adb", srcdirs="..")), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) # Unlike the compiler, "gnatcov instrument" processes source files in projects, # even when they are not in the closure of the main. Yet, we want to check that # gnatcov complains when the SID file is missing, so manually remove it, here. -if thistest.options.trace_mode == 'src': - rm(os.path.join('obj', 'helper.sid')) - what = 'SID' +if thistest.options.trace_mode == "src": + rm(os.path.join("obj", "helper.sid")) + what = "SID" else: - what = 'ALI' + what = "ALI" -log_file = 'coverage.log' +log_file = "coverage.log" xcov(xcov_args, out=log_file) thistest.fail_if_not_equal( - 'gnatcov output', - 'warning: no {} file found for unit helper'.format(what), - contents_of(log_file).strip()) + "gnatcov output", + "warning: no {} file found for unit helper".format(what), + contents_of(log_file).strip(), +) -check_xcov_reports('obj', {'main.adb.xcov': {'+': {3}}}) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {3}}}) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py index 263ca3536..be275fecd 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py @@ -15,7 +15,7 @@ from SUITE.tutils import gprfor -tmp = Wdir('wd_') +tmp = Wdir("wd_") class ProjectConfig(object): @@ -25,21 +25,34 @@ class ProjectConfig(object): Coverage package must contain, and the rest (project name, dependencies and mains) is determined during the generation (see the generate method below). """ + def __init__(self, units_in=None, units_out=None): self.units_in = units_in self.units_out = units_out def generate(self, name, deps=(), mains=()): return gprfor( - prjid=name, mains=mains, langs=['Ada'], deps=deps, - srcdirs=['../../src-{}'.format(name)], - objdir='obj-{}'.format(name), - extra=gprcov_for(units_in=self.units_in, - units_out=self.units_out)) - - -def run_test(label, slug, main, helper, recursive, projects=[], units=[], - projects_warned=[], expected_cov_list=[]): + prjid=name, + mains=mains, + langs=["Ada"], + deps=deps, + srcdirs=["../../src-{}".format(name)], + objdir="obj-{}".format(name), + extra=gprcov_for(units_in=self.units_in, units_out=self.units_out), + ) + + +def run_test( + label, + slug, + main, + helper, + recursive, + projects=[], + units=[], + projects_warned=[], + expected_cov_list=[], +): """ Produce a coverage report for the given parameters and check the emitted warnings. @@ -56,56 +69,61 @@ def run_test(label, slug, main, helper, recursive, projects=[], units=[], warnings. :param expected_cov: List of expected coverage reports. """ - thistest.log('== [{}] {} =='.format(slug, label)) - tmp.to_subdir('wd_/{}'.format(slug)) + thistest.log("== [{}] {} ==".format(slug, label)) + tmp.to_subdir("wd_/{}".format(slug)) - expected_output = '\n'.join( - 'warning: project {} provides no unit of interest' - .format(project) for project in projects_warned) + expected_output = "\n".join( + "warning: project {} provides no unit of interest".format(project) + for project in projects_warned + ) # Generate projects for this test (see below for the description of each # project). - ProjectConfig().generate('empty') - helper.generate('helper') - main_prj = main.generate('main', deps=['empty', 'helper'], - mains=['main.adb']) - mkdir('obj-empty') - mkdir('obj-helper') - mkdir('obj-main') + ProjectConfig().generate("empty") + helper.generate("helper") + main_prj = main.generate( + "main", deps=["empty", "helper"], mains=["main.adb"] + ) + mkdir("obj-empty") + mkdir("obj-helper") + mkdir("obj-main") # Generate a coverage report for them build_run_and_coverage( - gprsw=GPRswitches(root_project=main_prj, - projects=projects, - units=units, - no_subprojects=not recursive), - covlevel='stmt', - mains=['main'], - gpr_obj_dir='obj-main', + gprsw=GPRswitches( + root_project=main_prj, + projects=projects, + units=units, + no_subprojects=not recursive, + ), + covlevel="stmt", + mains=["main"], + gpr_obj_dir="obj-main", tolerate_instrument_messages="project.*provides no unit", - extra_coverage_args=['-axcov'], + extra_coverage_args=["-axcov"], ) - log_file = ('coverage.log' - if thistest.options.trace_mode == 'bin' else - 'instrument.log') + log_file = ( + "coverage.log" + if thistest.options.trace_mode == "bin" + else "instrument.log" + ) thistest.fail_if_not_equal( - '[{}/{}] gnatcov output'.format(label, slug), + "[{}/{}] gnatcov output".format(label, slug), expected_output, - contents_of(log_file).strip()) + contents_of(log_file).strip(), + ) expected_cov = {} for c in expected_cov_list: expected_cov.update(c) - check_xcov_reports('obj-main', expected_cov) + check_xcov_reports("obj-main", expected_cov) # Check that all xcov report files are created in obj-main (i.e. the root # project). - xcov_files = glob.glob('obj-*/*.xcov') + xcov_files = glob.glob("obj-*/*.xcov") extra_xcov_files = [ - f - for f in xcov_files - if os.path.dirname(f) != 'obj-main' + f for f in xcov_files if os.path.dirname(f) != "obj-main" ] thistest.fail_if_not_equal( "misplaced xcov report files", @@ -127,47 +145,56 @@ def run_test(label, slug, main, helper, recursive, projects=[], units=[], # project of interest (--projects) unless not recursive (no warnings # are expected in this mode). The point of having this project loaded is to # check that indeed gnatcov does not warn about "empty". -main = {'main.adb.xcov': {'+': {6, 7}}} -main_support = {'main_support.adb.xcov': {'+': {3}}} -helper = {'helper.adb.xcov': {'+': {5}}} -helper_support = {'helper_support.adb.xcov': {'+': {3}}} +main = {"main.adb.xcov": {"+": {6, 7}}} +main_support = {"main_support.adb.xcov": {"+": {3}}} +helper = {"helper.adb.xcov": {"+": {5}}} +helper_support = {"helper_support.adb.xcov": {"+": {3}}} # Check when --units is passed # Pass both projects to --projects and only "main" to --units so that the # "helper" project has no unit of interest: gnatcov must warn about it. -run_test(label='--units present, no UoI in helper', slug='up1', - main=ProjectConfig(), - helper=ProjectConfig(), - projects=['main', 'helper'], - units=['main'], - projects_warned=['helper'], - expected_cov_list=[main], - recursive=False) +run_test( + label="--units present, no UoI in helper", + slug="up1", + main=ProjectConfig(), + helper=ProjectConfig(), + projects=["main", "helper"], + units=["main"], + projects_warned=["helper"], + expected_cov_list=[main], + recursive=False, +) # Pass both projects to --projects and both "main" and "h[ea]lper*" to --units. # The globbing pattern should match helper and helper_support. Both projects # have at least one unit of interest, so we expect no warning. -run_test(label='--units present, all projects have UoI', slug='up2', - main=ProjectConfig(), - helper=ProjectConfig(), - projects=['main', 'helper'], - units=['main', 'h[ea]lper*'], - projects_warned=[], - expected_cov_list=[main, helper, helper_support], - recursive=False) +run_test( + label="--units present, all projects have UoI", + slug="up2", + main=ProjectConfig(), + helper=ProjectConfig(), + projects=["main", "helper"], + units=["main", "h[ea]lper*"], + projects_warned=[], + expected_cov_list=[main, helper, helper_support], + recursive=False, +) # Only pass the root project (-P) in recursive mode and pass # "main" to --units. Even though "helper" is a project of interest, it does not # contain any unit of interest, yet we expect no warning in recursive mode. -run_test(label='--units present, no UoI in helper, recursive', slug='up3', - main=ProjectConfig(), - helper=ProjectConfig(), - units=['main'], - projects_warned=[], - expected_cov_list=[main], - recursive=True) +run_test( + label="--units present, no UoI in helper, recursive", + slug="up3", + main=ProjectConfig(), + helper=ProjectConfig(), + units=["main"], + projects_warned=[], + expected_cov_list=[main], + recursive=True, +) # Check when we don't pass --units @@ -175,35 +202,43 @@ def run_test(label, slug, main, helper, recursive, projects=[], units=[], # Pass both projects to --projects, no --units argument and make "helper" have # an empty Coverage'Units attribute. "helper" has no unit of interest, but it # has an attribute, se we should not warn about it. -run_test(label='--units absent, no UoI in helper with Units', slug='ua1', - main=ProjectConfig(), - helper=ProjectConfig(units_in=[]), - projects=['main', 'helper'], - projects_warned=[], - expected_cov_list=[main, main_support], - recursive=False) +run_test( + label="--units absent, no UoI in helper with Units", + slug="ua1", + main=ProjectConfig(), + helper=ProjectConfig(units_in=[]), + projects=["main", "helper"], + projects_warned=[], + expected_cov_list=[main, main_support], + recursive=False, +) # Pass both projects to --projects, no --units argument and make "helper" have # one unit pattern in its Coverage'Units attribute. All projects have units of # interest, so no warning expected. -run_test(label='--units absent, no UoI in helper with Excluded_Units', - slug='ua2', - main=ProjectConfig(), - helper=ProjectConfig(units_out=['helper*']), - projects=['main', 'helper'], - projects_warned=[], - expected_cov_list=[main, main_support], - recursive=False) +run_test( + label="--units absent, no UoI in helper with Excluded_Units", + slug="ua2", + main=ProjectConfig(), + helper=ProjectConfig(units_out=["helper*"]), + projects=["main", "helper"], + projects_warned=[], + expected_cov_list=[main, main_support], + recursive=False, +) # Pass both projects to --projects in recursive mode, no --units # argument. All projects have units of interest and we are in recursive mode # anyway, so no warning expected. -run_test(label='--units absent, no UoI in helper, recursive', slug='ua3', - main=ProjectConfig(), - helper=ProjectConfig(), - projects_warned=[], - expected_cov_list=[main, main_support, helper, helper_support], - recursive=True) +run_test( + label="--units absent, no UoI in helper, recursive", + slug="ua3", + main=ProjectConfig(), + helper=ProjectConfig(), + projects_warned=[], + expected_cov_list=[main, main_support, helper, helper_support], + recursive=True, +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py index f7d4f869d..db3e96c4b 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py @@ -13,46 +13,59 @@ def try_one_gpr(gpr, no_such): label = os.path.basename(os.getcwd()) - dump = 'xcov.out' + dump = "xcov.out" build_run_and_coverage( gprsw=GPRswitches(root_project=gpr), - covlevel='stmt', - mains=['p'], - extra_coverage_args=['-axcov'], + covlevel="stmt", + mains=["p"], + extra_coverage_args=["-axcov"], out=dump, register_failure=False, ) dump = contents_of(dump) expected_warning = ( - 'no unit {} in project gen (coverage.units attribute)'.format(no_such) - if no_such else 'no unit of interest') + "no unit {} in project gen (coverage.units attribute)".format(no_such) + if no_such + else "no unit of interest" + ) thistest.fail_if( expected_warning not in dump, - '[{}] missing warning on absence of specified unit'.format(label)) + "[{}] missing warning on absence of specified unit".format(label), + ) # Empty by specifying a single, non-existing unit in only wd.to_subdir("wd_1") try_one_gpr( - gpr=gprfor(srcdirs="../src", mains="p.adb", - extra=CovControl(units_in=["no_such_unit"]).gpr()), - no_such="no_such_unit") + gpr=gprfor( + srcdirs="../src", + mains="p.adb", + extra=CovControl(units_in=["no_such_unit"]).gpr(), + ), + no_such="no_such_unit", +) # Empty by excluding the only candidate unit wd.to_subdir("wd_2") -try_one_gpr(gpr=gprfor(srcdirs="../src", mains="p.adb", - extra=CovControl(units_out=["p"]).gpr()), - no_such=None) +try_one_gpr( + gpr=gprfor( + srcdirs="../src", + mains="p.adb", + extra=CovControl(units_out=["p"]).gpr(), + ), + no_such=None, +) # Empty by including the empty set explicitly wd.to_subdir("wd_3") try_one_gpr( gpr=gprfor( - srcdirs="../src", mains="p.adb", - extra=CovControl(units_in=[]).gpr()), - no_such=None) + srcdirs="../src", mains="p.adb", extra=CovControl(units_in=[]).gpr() + ), + no_such=None, +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py index bdf22d6f1..9a709f28a 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py @@ -28,24 +28,31 @@ def try_one(subdir, extra_covargs, xreports, xwarnings): """ wd.to_subdir(subdir) - gpr = gprfor(srcdirs="../src", mains="test_t.adb", - extra='\n'.join( - ['for Source_Files use', - ' ("test_t.adb","flip.ads", "flip.adb");'])) + gpr = gprfor( + srcdirs="../src", + mains="test_t.adb", + extra="\n".join( + [ + "for Source_Files use", + ' ("test_t.adb","flip.ads", "flip.adb");', + ] + ), + ) build_run_and_coverage( gprsw=GPRswitches(root_project=gpr), - covlevel='stmt', - mains=['test_t'], - extra_coverage_args=['--annotate=xcov'] + extra_covargs) + covlevel="stmt", + mains=["test_t"], + extra_coverage_args=["--annotate=xcov"] + extra_covargs, + ) - check_xcov_reports('obj', xreports) + check_xcov_reports("obj", xreports) - wlog = contents_of('coverage.log') + wlog = contents_of("coverage.log") for xw in xwarnings: thistest.fail_if( - xw not in wlog, - 'expected warning "%s" not found in log' % xw) + xw not in wlog, 'expected warning "%s" not found in log' % xw + ) wd.to_homedir() @@ -54,15 +61,18 @@ def try_one(subdir, extra_covargs, xreports, xwarnings): subdir="wd_1", extra_covargs=[], xreports={ - 'flip.adb.xcov': {'+': {3}}, - 'flip.ads.xcov': {}, - 'test_t.adb.xcov': {'+': {4, 6}}}, - xwarnings=[]) + "flip.adb.xcov": {"+": {3}}, + "flip.ads.xcov": {}, + "test_t.adb.xcov": {"+": {4, 6}}, + }, + xwarnings=[], +) try_one( subdir="wd_2", - extra_covargs=['--units=flop'], + extra_covargs=["--units=flop"], xreports={}, - xwarnings=['no unit flop (from --units) in the projects of interest']) + xwarnings=["no unit flop (from --units) in the projects of interest"], +) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py index c8ae6ee8a..2c1057944 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py @@ -16,44 +16,54 @@ from SUITE.tutils import gprfor -tmp = Wdir('wd_') -mkdir('obj-helper') -mkdir('obj-main') +tmp = Wdir("wd_") +mkdir("obj-helper") +mkdir("obj-main") -helper_prj = gprfor(prjid='helper', mains=[], langs=['Ada'], - srcdirs='../src-helper', objdir='obj-helper') -main_prj = gprfor(prjid='main', mains=['main.adb'], langs=['Ada'], - deps=['helper'], srcdirs='../src-main', objdir='obj-main') +helper_prj = gprfor( + prjid="helper", + mains=[], + langs=["Ada"], + srcdirs="../src-helper", + objdir="obj-helper", +) +main_prj = gprfor( + prjid="main", + mains=["main.adb"], + langs=["Ada"], + deps=["helper"], + srcdirs="../src-main", + objdir="obj-main", +) build_run_and_coverage( - gprsw=GPRswitches(root_project=main_prj, - projects=['helper'], - units=['helper', 'main']), - covlevel='stmt', - mains=['main'], - gpr_obj_dir='obj-main', + gprsw=GPRswitches( + root_project=main_prj, projects=["helper"], units=["helper", "main"] + ), + covlevel="stmt", + mains=["main"], + gpr_obj_dir="obj-main", tolerate_instrument_messages="no unit.*in the projects", - extra_coverage_args=['-axcov'], + extra_coverage_args=["-axcov"], ) -log_file = ('coverage.log' - if thistest.options.trace_mode == 'bin' else - 'instrument.log') +log_file = ( + "coverage.log" + if thistest.options.trace_mode == "bin" + else "instrument.log" +) thistest.fail_if_not_equal( - 'gnatcov output', - 'warning: no unit main (from --units) in the projects of interest', - contents_of(log_file).strip()) + "gnatcov output", + "warning: no unit main (from --units) in the projects of interest", + contents_of(log_file).strip(), +) -check_xcov_reports('obj-main', {'helper.adb.xcov': {'+': {3}}}) +check_xcov_reports("obj-main", {"helper.adb.xcov": {"+": {3}}}) # Check that all xcov report files are created in obj-main (i.e. the root # project). -xcov_files = glob.glob('obj-*/*.xcov') -extra_xcov_files = [ - f - for f in xcov_files - if os.path.dirname(f) != 'obj-main' -] +xcov_files = glob.glob("obj-*/*.xcov") +extra_xcov_files = [f for f in xcov_files if os.path.dirname(f) != "obj-main"] thistest.fail_if_not_equal( "misplaced xcov report files", "", diff --git a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/MultiGpr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/MultiGpr/test.py index 04c20260f..10e80d8ea 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/MultiGpr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/MultiGpr/test.py @@ -4,15 +4,18 @@ from test_support import check -wd = Wdir('wd_') +wd = Wdir("wd_") gprbuild( - gprfor(srcdirs=['../src', # For the test sources - '../../../../src'], # For the support sources - deps=['../Mon/mon.gpr'], - mains=['test_ab.adb'])) + gprfor( + srcdirs=[ + "../src", # For the test sources + "../../../../src", + ], # For the support sources + deps=["../Mon/mon.gpr"], + mains=["test_ab.adb"], + ) +) -check( - test_ali='obj/test_ab.ali', - mon_ali='../Mon/obj/monitor.ali') +check(test_ali="obj/test_ab.ali", mon_ali="../Mon/obj/monitor.ali") thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/SingleGpr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/SingleGpr/test.py index c3bab76da..19029b9f3 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/SingleGpr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/SingleGpr/test.py @@ -4,14 +4,17 @@ from test_support import check -wd = Wdir('wd_') +wd = Wdir("wd_") gprbuild( - gprfor(srcdirs=['../src', # For the test sources - '../../../../src'], # For the support sources - mains=['test_ab.adb'])) + gprfor( + srcdirs=[ + "../src", # For the test sources + "../../../../src", + ], # For the support sources + mains=["test_ab.adb"], + ) +) -check( - test_ali='obj/test_ab.ali', - mon_ali='obj/monitor.ali') +check(test_ali="obj/test_ab.ali", mon_ali="obj/monitor.ali") thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/test_support.py b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/test_support.py index c5c85b477..254183e69 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/test_support.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/test_support.py @@ -20,12 +20,12 @@ def _run_and_cov(pgm, level, sco_args): if we are doing mcdc. """ - level_arg = '--level=%s' % level + level_arg = "--level=%s" % level # gnatcov run run_args = [exepath_to(pgm), level_arg] - if 'mcdc' in level_arg: + if "mcdc" in level_arg: run_args.extend(sco_args) xrun(run_args) @@ -33,11 +33,12 @@ def _run_and_cov(pgm, level, sco_args): # gnatcov coverage cov_args = [ - '--annotate=xcov', - '--trace=%s' % tracename_for(os.path.basename(pgm)), - level_arg] + sco_args + "--annotate=xcov", + "--trace=%s" % tracename_for(os.path.basename(pgm)), + level_arg, + ] + sco_args - xcov(['coverage'] + cov_args) + xcov(["coverage"] + cov_args) def _tryone(sco_args, odir): @@ -51,27 +52,31 @@ def _tryone(sco_args, odir): wsd = Wdir(subdir=odir) - _run_and_cov(pgm='../test_ab', level='stmt+mcdc', sco_args=sco_args) + _run_and_cov(pgm="../test_ab", level="stmt+mcdc", sco_args=sco_args) # Check report contents - args = 'stmt+mcdc / ' + ' '.join(sco_args) + args = "stmt+mcdc / " + " ".join(sco_args) - test_xcov = contents_of('test_ab.adb.xcov') + test_xcov = contents_of("test_ab.adb.xcov") thistest.fail_if( - not re.search(r'\+: Monitor.Diamond', test_xcov), - 'failure on check for %s' % args) + not re.search(r"\+: Monitor.Diamond", test_xcov), + "failure on check for %s" % args, + ) - mon_xcov = contents_of('monitor.adb.xcov') + mon_xcov = contents_of("monitor.adb.xcov") thistest.fail_if( - not re.search(r'\!:.*and then', mon_xcov), - 'failure on Decision monitor check for %s' % args) + not re.search(r"\!:.*and then", mon_xcov), + "failure on Decision monitor check for %s" % args, + ) thistest.fail_if( - not re.search(r'\+:.*Hit := Hit \+ 1;', mon_xcov), - 'failure on Hit monitor check for %s' % args) + not re.search(r"\+:.*Hit := Hit \+ 1;", mon_xcov), + "failure on Hit monitor check for %s" % args, + ) thistest.fail_if( - not re.search(r'\+:.*Miss := Miss \+ 1;', mon_xcov), - 'failure on Miss monitor check for %s' % args) + not re.search(r"\+:.*Miss := Miss \+ 1;", mon_xcov), + "failure on Miss monitor check for %s" % args, + ) wsd.to_homedir() @@ -87,18 +92,20 @@ def check(test_ali, mon_ali): # To prevent mixups and facilitate investigation in case # of failure, we execute each sequence of commands from within # a separate subdir. Adjust the paths to ali files accordingly. - test_ali = os.path.join('..', test_ali) - mon_ali = os.path.join('..', mon_ali) + test_ali = os.path.join("..", test_ali) + mon_ali = os.path.join("..", mon_ali) # Check with response file only - _tryone(sco_args=['--scos=@' + list_to_tmp([test_ali, mon_ali])], - odir='response') + _tryone( + sco_args=["--scos=@" + list_to_tmp([test_ali, mon_ali])], + odir="response", + ) # Check with --scos only - _tryone(sco_args=['--scos=' + f for f in [test_ali, mon_ali]], - odir='scos') + _tryone(sco_args=["--scos=" + f for f in [test_ali, mon_ali]], odir="scos") # Check with a mix of a response file and --scos - _tryone(sco_args=['--scos=@' + list_to_tmp([test_ali]), - '--scos=' + mon_ali], - odir='mix') + _tryone( + sco_args=["--scos=@" + list_to_tmp([test_ali]), "--scos=" + mon_ali], + odir="mix", + ) diff --git a/testsuite/Qualif/qmconf.py b/testsuite/Qualif/qmconf.py index a0a73b843..fd6b5f6c6 100644 --- a/testsuite/Qualif/qmconf.py +++ b/testsuite/Qualif/qmconf.py @@ -5,25 +5,22 @@ common_file = os.path.join( os.path.dirname( os.path.dirname( - os.path.dirname( - os.path.dirname( - os.path.abspath(__file__))))), - "common_conf.py") + os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + ) + ), + "common_conf.py", +) if os.path.isfile(common_file): execfile(common_file) - execfile(os.path.join( - os.path.dirname(common_file), - "qm_prolog.py")) + execfile(os.path.join(os.path.dirname(common_file), "qm_prolog.py")) else: print("Couldn't find common configuration file") print(common_file) print("from: %s" % __file__) -rst_prolog += writer.define_role('raw-html(raw)', {'format': 'html'}) +rst_prolog += writer.define_role("raw-html(raw)", {"format": "html"}) doc_id = tor_doc_id -html_sidebars = { - '**': ['localtoc.html', 'sourcelink.html', 'searchbox.html'] -} +html_sidebars = {"**": ["localtoc.html", "sourcelink.html", "searchbox.html"]} diff --git a/testsuite/REST/rest.py b/testsuite/REST/rest.py index 64809ae86..3eaca3606 100644 --- a/testsuite/REST/rest.py +++ b/testsuite/REST/rest.py @@ -1,40 +1,47 @@ +def isolate(text, pre, post): + return "\n" * pre + text + "\n" * post -def isolate (text, pre, post): - return '\n' * pre + text + '\n' * post def heading(title, char, pre=2, post=1): - return isolate ( - pre = pre, - text = '\n'.join ( - (char * len(title), title, char * len(title))), - post = post) + return isolate( + pre=pre, + text="\n".join((char * len(title), title, char * len(title))), + post=post, + ) + def part(title): - return heading(title, '#') + return heading(title, "#") + def chapter(title): - return heading(title, '*') + return heading(title, "*") + def section(title): - return heading(title, '=') + return heading(title, "=") + def emph(content): return "*" + content + "*" + def strong(content): return "**" + content + "**" + def list(content, pre=1, post=1): - return isolate ( - pre = pre, - text = '\n'.join([' * %s' % l for l in content]), - post = post) + return isolate( + pre=pre, text="\n".join([" * %s" % l for l in content]), post=post + ) + def toctree(l, depth=2): - return isolate ( - pre = 1, - text = '\n'.join ( - [".. toctree::", - " :maxdepth: %s\n" % depth] - + [" %s" % item for item in l]), - post = 1) + return isolate( + pre=1, + text="\n".join( + [".. toctree::", " :maxdepth: %s\n" % depth] + + [" %s" % item for item in l] + ), + post=1, + ) diff --git a/testsuite/SCOV/expgen/__init__.py b/testsuite/SCOV/expgen/__init__.py index 3543ec32b..3346078a4 100644 --- a/testsuite/SCOV/expgen/__init__.py +++ b/testsuite/SCOV/expgen/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -''' +""" TODO -''' +""" diff --git a/testsuite/SCOV/expgen/ast.py b/testsuite/SCOV/expgen/ast.py index 2ec22f09b..0a4d0000b 100644 --- a/testsuite/SCOV/expgen/ast.py +++ b/testsuite/SCOV/expgen/ast.py @@ -14,33 +14,36 @@ class RelOp(object): """Available relational operators.""" - GT = '>' - GE = '>=' - LT = '<' - LE = '<=' - EQ = '==' - NE = '!=' + + GT = ">" + GE = ">=" + LT = "<" + LE = "<=" + EQ = "==" + NE = "!=" class Types(object): """Available basic types for local variable declarations.""" - BOOLEAN = 'boolean' - INTEGER = 'integer' + + BOOLEAN = "boolean" + INTEGER = "integer" class TagTypes(object): """Available decision context types for tags.""" - DECISION = ':d:' - EXPRESSION = ':e:' + + DECISION = ":d:" + EXPRESSION = ":e:" -Program = namedtuple('program', 'local_vars statements') +Program = namedtuple("program", "local_vars statements") # Types: used for both declarations and usages -BuiltinType = namedtuple('builtin_type', 'name') -RecordType = namedtuple('record_type', 'name members') -MemberDecl = namedtuple('member_decl', 'type name') +BuiltinType = namedtuple("builtin_type", "name") +RecordType = namedtuple("record_type", "name members") +MemberDecl = namedtuple("member_decl", "type name") # ... and some regularly used ones. Note that builtin types must not be # declared @@ -50,38 +53,38 @@ class TagTypes(object): # Expressions: when adding nodes to these or to topology ones, do not forget to # update the `utils.is_expr` function. -VariableUsage = namedtuple('variable_usage', 'name') -LitteralInteger = namedtuple('litteral_integer', 'value') -LitteralBoolean = namedtuple('litteral_boolean', 'value') -LitteralRecord = namedtuple('litteral_record', 'type members') -Comparison = namedtuple('comparison', 'operator left right') -Call = namedtuple('call', 'function arguments') +VariableUsage = namedtuple("variable_usage", "name") +LitteralInteger = namedtuple("litteral_integer", "value") +LitteralBoolean = namedtuple("litteral_boolean", "value") +LitteralRecord = namedtuple("litteral_record", "type members") +Comparison = namedtuple("comparison", "operator left right") +Call = namedtuple("call", "function arguments") # Topology expressions -And = namedtuple('and_expr', 'left right') -Or = namedtuple('or_expr', 'left right') -Not = namedtuple('not_expr', 'expr') +And = namedtuple("and_expr", "left right") +Or = namedtuple("or_expr", "left right") +Not = namedtuple("not_expr", "expr") # Statements -If = namedtuple('if_stmt', 'condition true_stmt false_stmt') -While = namedtuple('while_stmt', 'condition stmt') -Return = namedtuple('return_stmt', 'expr') -Assign = namedtuple('assign', 'variable expr') +If = namedtuple("if_stmt", "condition true_stmt false_stmt") +While = namedtuple("while_stmt", "condition stmt") +Return = namedtuple("return_stmt", "expr") +Assign = namedtuple("assign", "variable expr") # Language-specific constructs: # - Type -XType = namedtuple('language_specific_type', - 'language declaration usage') +XType = namedtuple("language_specific_type", "language declaration usage") # - Litteral (for actuals, mostly) -XLitteral = namedtuple('language_specific_litteral', - 'language format') +XLitteral = namedtuple("language_specific_litteral", "language format") # - Operand -XOperand = namedtuple('language_specific_operand', - 'language format formal_name') +XOperand = namedtuple( + "language_specific_operand", "language format formal_name" +) # - Context -XContext = namedtuple('language_specific_context', - 'language format decision_expr') +XContext = namedtuple( + "language_specific_context", "language format decision_expr" +) # Tag # Used to tag lines, so that test drivers can reference the correct lines for @@ -92,5 +95,5 @@ class TagTypes(object): # tagged operand, or `all` if all operands are on the same line. In both # cases, `context` must be `TagTypes.(DECISION or EXPRESSION)` depending on # the context of the tagged decision. -Tag = namedtuple('tag', 'name operand context') -TaggedNode = namedtuple('tagged_node', 'tag node') +Tag = namedtuple("tag", "name operand context") +TaggedNode = namedtuple("tagged_node", "tag node") diff --git a/testsuite/SCOV/expgen/context.py b/testsuite/SCOV/expgen/context.py index b6fe52da6..a5fedb5e2 100644 --- a/testsuite/SCOV/expgen/context.py +++ b/testsuite/SCOV/expgen/context.py @@ -46,8 +46,8 @@ def get_program(self, decision_expr): # Tag for statements whose execution depends on the outcome of the decision # expression. -ON_TRUE_TAG = ast.Tag('on-true', None, None) -ON_FALSE_TAG = ast.Tag('on-false', None, None) +ON_TRUE_TAG = ast.Tag("on-true", None, None) +ON_FALSE_TAG = ast.Tag("on-false", None, None) class Call(Context): @@ -56,23 +56,25 @@ class Call(Context): function, and return the result of this call. The user must provide an implementation for this function. - """'' + """ "" TAG_CONTEXT = ast.TagTypes.EXPRESSION def get_program(self, param): - temp_name = 'result' + temp_name = "result" temp_usage = ast.VariableUsage(temp_name) return ast.Program( - [(temp_name, ast.BooleanType), ], + [ + (temp_name, ast.BooleanType), + ], [ ast.Assign( temp_usage, - ast.Call(ast.VariableUsage('identity'), [param]) + ast.Call(ast.VariableUsage("identity"), [param]), ), ast.Return(temp_usage), - ] + ], ) @@ -87,13 +89,17 @@ class If(Context): def get_program(self, condition): return ast.Program( [], # No local variable - [ast.If( - condition, - ast.TaggedNode(ON_TRUE_TAG, - ast.Return(ast.LitteralBoolean(True))), - ast.TaggedNode(ON_FALSE_TAG, - ast.Return(ast.LitteralBoolean(False))) - )] + [ + ast.If( + condition, + ast.TaggedNode( + ON_TRUE_TAG, ast.Return(ast.LitteralBoolean(True)) + ), + ast.TaggedNode( + ON_FALSE_TAG, ast.Return(ast.LitteralBoolean(False)) + ), + ) + ], ) @@ -111,21 +117,24 @@ def get_program(self, condition): [ ast.While( condition, - ast.TaggedNode(ON_TRUE_TAG, - ast.Return(ast.LitteralBoolean(True))) + ast.TaggedNode( + ON_TRUE_TAG, ast.Return(ast.LitteralBoolean(True)) + ), ), - ast.TaggedNode(ON_FALSE_TAG, - ast.Return(ast.LitteralBoolean(False))) - ] + ast.TaggedNode( + ON_FALSE_TAG, ast.Return(ast.LitteralBoolean(False)) + ), + ], ) class Return(Context): - TAG_CONTEXT = ast.TagTypes.EXPRESSION def get_program(self, condition): return ast.Program( [], - [ast.Return(condition), ] + [ + ast.Return(condition), + ], ) diff --git a/testsuite/SCOV/expgen/generator/__init__.py b/testsuite/SCOV/expgen/generator/__init__.py index 3543ec32b..3346078a4 100644 --- a/testsuite/SCOV/expgen/generator/__init__.py +++ b/testsuite/SCOV/expgen/generator/__init__.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -''' +""" TODO -''' +""" diff --git a/testsuite/SCOV/expgen/generator/composition.py b/testsuite/SCOV/expgen/generator/composition.py index b9bad46eb..044fb7388 100644 --- a/testsuite/SCOV/expgen/generator/composition.py +++ b/testsuite/SCOV/expgen/generator/composition.py @@ -13,13 +13,11 @@ import SCOV.expgen.operand as operand -languages = [lang_mod.Language() - for lang_mod in (language.ada, language.c)] +languages = [lang_mod.Language() for lang_mod in (language.ada, language.c)] operand_kinds = [ operand.Variable(), operand.IntegerComparison(ast.RelOp.GT, 1), - # Ada-specific operands ada_operand.Aggregate(), ada_operand.Component(), @@ -31,7 +29,6 @@ # TODO: find how to make coverage expectation match the whole expression # (including the Boolean conversion operator). # -> ada_operand.DerivedType(), - # C-specific operands c_operand.Component(), c_operand.Modulo(), @@ -42,7 +39,6 @@ context.If(), context.While(), context.Return(), - # Ada-specific contexts ada_context.Case(), ada_context.DeclarationInitializer(), @@ -50,7 +46,6 @@ ada_context.ExitWhen(), ada_context.For(), ada_context.Index(), - # C-specific contexts c_context.DeclarationInitializer(), ] diff --git a/testsuite/SCOV/expgen/generator/engine.py b/testsuite/SCOV/expgen/generator/engine.py index 67e9171a2..fd6e297c5 100644 --- a/testsuite/SCOV/expgen/generator/engine.py +++ b/testsuite/SCOV/expgen/generator/engine.py @@ -39,15 +39,15 @@ def run(group_py): with env.get_dir(group_py_dir): generate_all(env) except GenerationError as e: - sys.stderr.write('{}: error: {}\n'.format(e.context, e.message)) + sys.stderr.write("{}: error: {}\n".format(e.context, e.message)) sys.exit(1) def generate_all(env): """Generate code for all topology directories in the current directory.""" # Each directory contains drivers for a given topology. - for topo_dir in os.listdir('.'): - if not os.path.isdir(topo_dir) or topo_dir == 'src': + for topo_dir in os.listdir("."): + if not os.path.isdir(topo_dir) or topo_dir == "src": continue with env.get_dir(topo_dir): generate_topology(topo_dir, env) @@ -60,27 +60,28 @@ def generate_topology(topo_dir, env): # Look at all drivers to collect the truth vectors involved. Extract the # topology used and check that each driver use the same one. - with env.get_dir('src'): - for driver in os.listdir('.'): - if not driver.startswith('test_') or not driver.endswith('.adb'): + with env.get_dir("src"): + for driver in os.listdir("."): + if not driver.startswith("test_") or not driver.endswith(".adb"): continue - drv_topo = parsing.parse_driver( - topo_dir, driver, truth_vectors - ) + drv_topo = parsing.parse_driver(topo_dir, driver, truth_vectors) # Check that this driver has a topology and that its topology is # not different from others. if drv_topo is None: raise DriverError( - topo_dir, driver, None, 'This driver has no topology') - elif ( - topo is not None - and not utils.is_topology_equal(topo.expression, drv_topo) + topo_dir, driver, None, "This driver has no topology" + ) + elif topo is not None and not utils.is_topology_equal( + topo.expression, drv_topo ): raise DriverError( - topo_dir, driver, None, - 'This driver has a different topology from other one') + topo_dir, + driver, + None, + "This driver has a different topology from other one", + ) topo = topology.Topology(drv_topo) # If we happen to get here for subdirectories that are not aimed at @@ -116,7 +117,7 @@ def generate_language(env, topo, truth_vectors, lang): ] first_unused_op_kind = i + topo.arity - with env.get_dir('Op{}'.format(i)): + with env.get_dir("Op{}".format(i)): generate_ctx_op(env, topo, truth_vectors, lang, ctx, op_kinds) # If some operand kinds were not used in the previous combination, use them @@ -140,15 +141,12 @@ def generate_language(env, topo, truth_vectors, lang): operand_kinds_to_test[(k + j) % len(operand_kinds_to_test)] for j in range(topo.arity) ] - with env.get_dir('Op{}'.format(i)): + with env.get_dir("Op{}".format(i)): generate_ctx_op(env, topo, truth_vectors, lang, ctx, op_kinds) def generate_ctx_op(env, topo, truth_vectors, lang, ctx, op_kinds): - formal_names = [ - 'X{}'.format(i + 1) - for i in range(topo.arity) - ] + formal_names = ["X{}".format(i + 1) for i in range(topo.arity)] operands = [ op_kind.get_operand(name) for name, op_kind in zip(formal_names, op_kinds) @@ -159,26 +157,25 @@ def generate_ctx_op(env, topo, truth_vectors, lang, ctx, op_kinds): program = ctx.get_program(decision) # Generate the needed type declarations in the TYPES module. - used_types = utils.make_type_set(sum( - (tuple(op_kind.used_types) for op_kind in op_kinds), - () - )) + used_types = utils.make_type_set( + sum((tuple(op_kind.used_types) for op_kind in op_kinds), ()) + ) - with env.get_dir('src'): + with env.get_dir("src"): # First generate types needed by operands. with open( - lang.get_specification_filename(lang.TYPES_MODULE), 'w' + lang.get_specification_filename(lang.TYPES_MODULE), "w" ) as types_fp: lang.serialize_specification_types(types_fp, used_types) # Then generate the ADA binding for the run module... with open( - ada.get_specification_filename(ada.RUN_MODULE), 'w' + ada.get_specification_filename(ada.RUN_MODULE), "w" ) as run_fp: ada.serialize_run_module_interface(run_fp, lang, truth_vectors) # ... and the run module itself, in the decided language. with open( - lang.get_implementation_filename(lang.RUN_MODULE), 'w' + lang.get_implementation_filename(lang.RUN_MODULE), "w" ) as run_fp: lang.serialize_run_module_implementation( run_fp, op_kinds, truth_vectors @@ -187,59 +184,59 @@ def generate_ctx_op(env, topo, truth_vectors, lang, ctx, op_kinds): # And finally generate the specification and the implementation for the # computing module. with open( - lang.get_specification_filename(lang.COMPUTING_MODULE), 'w' + lang.get_specification_filename(lang.COMPUTING_MODULE), "w" ) as comp_fp: lang.serialize_specification_program( comp_fp, program, formal_names, formal_types ) with open( - lang.get_implementation_filename(lang.COMPUTING_MODULE), 'w' + lang.get_implementation_filename(lang.COMPUTING_MODULE), "w" ) as comp_fp: - # Prepend the "computing" module implementation with some comments # documenting the operands usage and the target of the context. def get_doc(instance): - text = type(instance).__doc__ or '' - text = ' '.join(text.split()) + text = type(instance).__doc__ or "" + text = " ".join(text.split()) return textwrap.wrap(text, 72) lines = [] - lines.append('Operands:') + lines.append("Operands:") for name, op_kind in zip(formal_names, op_kinds): - lines.append(' - {}: {}'.format(name, type(op_kind).__name__)) + lines.append(" - {}: {}".format(name, type(op_kind).__name__)) lines.extend( - ' {}'.format(line) - for line in get_doc(op_kind) + " {}".format(line) for line in get_doc(op_kind) ) - lines.append('Context: {}'.format(type(ctx).__name__)) - lines.extend( - ' {}'.format(line) - for line in get_doc(ctx) - ) + lines.append("Context: {}".format(type(ctx).__name__)) + lines.extend(" {}".format(line) for line in get_doc(ctx)) # Serialize the implementation code itself. for line in lines: comp_fp.write(lang.format_comment(line)) - comp_fp.write('\n') - comp_fp.write('\n') + comp_fp.write("\n") + comp_fp.write("\n") lang.serialize_implementation( - comp_fp, program, formal_names, formal_types, - one_operand_per_line + comp_fp, + program, + formal_names, + formal_types, + one_operand_per_line, ) # The "test.py" testcase file is hardcoded... - with open('test.py', 'w') as test_fp: - test_fp.write("""\ + with open("test.py", "w") as test_fp: + test_fp.write( + """\ from SCOV.tc import * from SCOV.tctl import CAT [TestCase(category=cat).run() for cat in CAT.critcats] thistest.result() -""") +""" + ) # Properly tag it as generated, so that the testsuite framework does not # treat it as a regular testcase next time. - with open('.generated', 'w'): + with open(".generated", "w"): pass diff --git a/testsuite/SCOV/expgen/generator/errors.py b/testsuite/SCOV/expgen/generator/errors.py index 381c048db..4df678214 100644 --- a/testsuite/SCOV/expgen/generator/errors.py +++ b/testsuite/SCOV/expgen/generator/errors.py @@ -1,7 +1,8 @@ class GenerationError(Exception): def __init__(self, context, message): super(GenerationError, self).__init__( - '{}: {}'.format(context, message)) + "{}: {}".format(context, message) + ) self.context = context self.message = message @@ -9,10 +10,13 @@ def __init__(self, context, message): class DriverError(GenerationError): def __init__(self, topo_dir, test_driver, line_no, message): super(DriverError, self).__init__( - '{}/{}{}'.format(topo_dir, test_driver, - ':{}'.format(line_no) - if line_no is not None else ''), - message) + "{}/{}{}".format( + topo_dir, + test_driver, + ":{}".format(line_no) if line_no is not None else "", + ), + message, + ) self.test_driver = test_driver self.line_no = line_no @@ -20,5 +24,5 @@ def __init__(self, topo_dir, test_driver, line_no, message): class BadTopologyError(DriverError): def __init__(self, topo_dir, test_driver, line_no, message): super(BadTopologyError, self).__init__( - topo_dir, test_driver, line_no, 'Bad topology: {}'.format(message) + topo_dir, test_driver, line_no, "Bad topology: {}".format(message) ) diff --git a/testsuite/SCOV/expgen/generator/parsing.py b/testsuite/SCOV/expgen/generator/parsing.py index c8660af15..cb166aa7c 100644 --- a/testsuite/SCOV/expgen/generator/parsing.py +++ b/testsuite/SCOV/expgen/generator/parsing.py @@ -31,15 +31,16 @@ def error(message): def check_eof(i): if i >= len(tokens): - raise error('unexpected end of line') + raise error("unexpected end of line") def parse_or(i): check_eof(i) left, i = parse_and(i) while i < len(tokens): - if tokens[i:i + 2] != ['or', 'else']: + if tokens[i : i + 2] != ["or", "else"]: raise error( - 'expected "or else" but found {}'.format(tokens[i])) + 'expected "or else" but found {}'.format(tokens[i]) + ) i += 2 right, i = parse_and(i) left = ast.And(left, right) @@ -49,9 +50,10 @@ def parse_and(i): check_eof(i) left, i = parse_not(i) while i < len(tokens): - if tokens[i:i + 2] != ['and', 'then']: + if tokens[i : i + 2] != ["and", "then"]: raise error( - 'expected "and then" but found {}'.format(tokens[i])) + 'expected "and then" but found {}'.format(tokens[i]) + ) i += 2 right, i = parse_not(i) left = ast.And(left, right) @@ -59,29 +61,32 @@ def parse_and(i): def parse_not(i): check_eof(i) - if tokens[i] == 'not': + if tokens[i] == "not": expr, i = parse_not(i + 1) return ast.Not(expr), i - elif tokens[i] == '_': + elif tokens[i] == "_": return (topology.OperandPlaceholder(), i + 1) - elif tokens[i] == '(': + elif tokens[i] == "(": result, i = parse_or(i + 1) if i >= len(tokens): raise error('expected ")" but found end of line') - elif tokens[i] != ')': + elif tokens[i] != ")": raise error('expected ")" but found {}'.format(tokens[i])) return (result, i + 1) else: raise error( 'expected "not", "(" or a placeholder but found ' - '{}'.format(tokens[i])) + "{}".format(tokens[i]) + ) # Check that all tokens have been consumed. topo, next_token = parse_or(0) if next_token < len(tokens): - raise error('Too much operands (parsed {})'.format( - ' '.join(tokens[:next_token]) - )) + raise error( + "Too much operands (parsed {})".format( + " ".join(tokens[:next_token]) + ) + ) return topo @@ -91,13 +96,14 @@ def parse_truth(topo_dir, driver, line_no, c): Parse a truth character ('F' or 'T') and return the corresponding truth value, or raise an error. """ - if c == 'F': + if c == "F": return False - elif c == 'T': + elif c == "T": return True else: - raise DriverError(topo_dir, driver, line_no, - 'Invalid truth character: {}'.format(c)) + raise DriverError( + topo_dir, driver, line_no, "Invalid truth character: {}".format(c) + ) def parse_driver(topo_dir, driver, truth_vectors): @@ -107,42 +113,47 @@ def parse_driver(topo_dir, driver, truth_vectors): """ drv_topo = None - for line_no, line in enumerate(open(driver, 'r'), 1): - + for line_no, line in enumerate(open(driver, "r"), 1): # Parse a topology declaration - if line.startswith('-- Topology: '): + if line.startswith("-- Topology: "): if drv_topo is not None: raise DriverError( - topo_dir, driver, line_no, - 'There is more than one topology' + topo_dir, + driver, + line_no, + "There is more than one topology", ) - _, topo_str = line.split(': ', 1) + _, topo_str = line.split(": ", 1) drv_topo = parse_topology( topo_dir, driver, line_no, topo_str.split() ) # Parse a run procedure call, extract a truth vector from it. - elif line.startswith(' Run_'): - + elif line.startswith(" Run_"): if drv_topo is None: raise DriverError( - topo_dir, driver, line_no, - 'A topology is needed before a run procedure is called') + topo_dir, + driver, + line_no, + "A topology is needed before a run procedure is called", + ) - chunks = line.split('_', 2) - assert chunks[0] == ' Run' + chunks = line.split("_", 2) + assert chunks[0] == " Run" if len(chunks) != 3: raise DriverError( - topo_dir, driver, line_no, - 'Invalid run invokation: {}'.format(line.strip())) + topo_dir, + driver, + line_no, + "Invalid run invokation: {}".format(line.strip()), + ) operands_truth = tuple( - parse_truth(topo_dir, driver, line_no, c) - for c in chunks[1] + parse_truth(topo_dir, driver, line_no, c) for c in chunks[1] ) expected_truth = parse_truth( topo_dir, driver, line_no, chunks[2][0] ) - truth_vectors.add(operands_truth + (expected_truth, )) + truth_vectors.add(operands_truth + (expected_truth,)) return drv_topo diff --git a/testsuite/SCOV/expgen/generator/utils.py b/testsuite/SCOV/expgen/generator/utils.py index 17e1e0ce2..577d9b106 100644 --- a/testsuite/SCOV/expgen/generator/utils.py +++ b/testsuite/SCOV/expgen/generator/utils.py @@ -26,12 +26,10 @@ def __exit__(self, type, value, traceback): self.env.pop_dir() def __init__(self): - self.dir_stack = [ - os.getcwd() - ] + self.dir_stack = [os.getcwd()] def get_dir(self, subdir): - """ Return a new directory guard for `subdir`.""" + """Return a new directory guard for `subdir`.""" return self.DirectoryGuard(self, subdir) def push_dir(self, subdir): diff --git a/testsuite/SCOV/expgen/language/__init__.py b/testsuite/SCOV/expgen/language/__init__.py index 34bf390bb..2402c7ce6 100644 --- a/testsuite/SCOV/expgen/language/__init__.py +++ b/testsuite/SCOV/expgen/language/__init__.py @@ -33,21 +33,21 @@ class Language(object): NAME = None - SUPPORT_MODULE = 'support' + SUPPORT_MODULE = "support" # The "types" module is used to define types used by operands. - TYPES_MODULE = 'types' + TYPES_MODULE = "types" # The "run" module contains all "run_*" procedures called by test drivers. - RUN_MODULE = 'run' + RUN_MODULE = "run" # These "run_*" functions call the "compute" function in the "computing" # module. - COMPUTING_MODULE = 'computing' - ENTRY_POINT_NAME = 'compute' - ASSERT_PROC_NAME = 'assert' + COMPUTING_MODULE = "computing" + ENTRY_POINT_NAME = "compute" + ASSERT_PROC_NAME = "assert" # Used to format the name of the test procedures. BOOL_TO_CHAR = { - False: 'F', - True: 'T', + False: "F", + True: "T", } def __init__(self): @@ -82,9 +82,7 @@ def serialize_run_module_implementation( """ raise NotImplementedError() - def serialize_specification_types( - self, stream, types - ): + def serialize_specification_types(self, stream, types): """ Output a specification source that contains declarations for the given `types`. The name of the module for these specification is @@ -103,9 +101,7 @@ def serialize_specification_program( raise NotImplementedError() def serialize_implementation( - self, stream, - program, formal_names, formal_types, - one_operand_per_line + self, stream, program, formal_names, formal_types, one_operand_per_line ): """ Output an implementation source that contain the "compute" function, @@ -120,7 +116,7 @@ def handle(self, expr, *args, **kwargs): handling method, passing it the *args and **kwargs arguments. """ arg_type = type(expr).__name__ - arg_handler = getattr(self, 'handle_{}'.format(arg_type)) + arg_handler = getattr(self, "handle_{}".format(arg_type)) return arg_handler(expr, *args, **kwargs) def format_tree(self, tree, *args, **kwargs): @@ -181,11 +177,9 @@ def check_language(self, xnode): this instance. """ assert xnode.language == self.NAME, ( - '{} construct is specific to {} ' - 'but is used with language {}'.format( - type(xnode).__name__, - xnode.language, - self.NAME + "{} construct is specific to {} " + "but is used with language {}".format( + type(xnode).__name__, xnode.language, self.NAME ) ) @@ -203,12 +197,11 @@ def handle_tagged_node(self, tagged_node): self.handle(tagged_node.node) def get_run_procedure_name(self, truth_vector): - return 'run_{}_{}'.format( - ''.join( - self.BOOL_TO_CHAR[b] - for b in truth_vector[:-1] + return "run_{}_{}".format( + "".join( + self.BOOL_TO_CHAR[b] for b in truth_vector[:-1] ), # Actuals - self.BOOL_TO_CHAR[truth_vector[-1]] # Result + self.BOOL_TO_CHAR[truth_vector[-1]], # Result ) # @@ -244,7 +237,7 @@ def handle_language_specific_context(self, xcontext): self.check_language(xcontext) for line in xcontext.format: try: - index = line.index('{decision_expr}') + index = line.index("{decision_expr}") except ValueError: self.write(line) else: @@ -305,10 +298,12 @@ def filter_types(self, types): # Formatting helper classes # + class IndentationGuard(object): """ Increment the indentation level on entry and decrement it when leaving. """ + def __init__(self, formatter, addend): self.formatter = formatter self.addend = addend @@ -355,7 +350,7 @@ def write(self, string): """ if self.current_column == 0: self.current_column = self.indent_stack[-1] - self.stream.write(' ' * self.indent_stack[-1]) + self.stream.write(" " * self.indent_stack[-1]) self.stream.write(string) self.current_column += len(string) @@ -378,7 +373,7 @@ def indent(self, addend=0): def newline(self): """Flush any tag and insert a new line character.""" self.flush_tags() - self.stream.write('\n') + self.stream.write("\n") self.current_column = 0 def add_tag(self, tag): @@ -387,15 +382,15 @@ def add_tag(self, tag): if self.line_tag: if tag.name != self.line_tag.name: raise ValueError( - 'Trying to insert a `{}` tag on a line where there is a ' - '`{}` tag'.format(tag.name, self.line_tag.name) + "Trying to insert a `{}` tag on a line where there is a " + "`{}` tag".format(tag.name, self.line_tag.name) ) if tag.context != self.line_tag.context: raise ValueError( - 'Trying to insert a `{}` tag on a line where there is a ' - '`{}` tag'.format(tag.context, self.line_tag.context) + "Trying to insert a `{}` tag on a line where there is a " + "`{}` tag".format(tag.context, self.line_tag.context) ) - tag = tag._replace(operand='all') + tag = tag._replace(operand="all") self.line_tag = tag def flush_tags(self): @@ -406,5 +401,5 @@ def flush_tags(self): comment = self.language.format_comment( utils.format_tag(self.line_tag) ) - self.stream.write(' {}'.format(comment)) + self.stream.write(" {}".format(comment)) self.line_tag = None diff --git a/testsuite/SCOV/expgen/language/ada/__init__.py b/testsuite/SCOV/expgen/language/ada/__init__.py index 5255c6f46..ddbdec3fa 100644 --- a/testsuite/SCOV/expgen/language/ada/__init__.py +++ b/testsuite/SCOV/expgen/language/ada/__init__.py @@ -7,18 +7,18 @@ # Serialization of relational operators REL_OP = { - ast.RelOp.GT: '>', - ast.RelOp.GE: '>=', - ast.RelOp.LT: '>', - ast.RelOp.LE: '>=', - ast.RelOp.EQ: '=', - ast.RelOp.NE: '/=', + ast.RelOp.GT: ">", + ast.RelOp.GE: ">=", + ast.RelOp.LT: ">", + ast.RelOp.LE: ">=", + ast.RelOp.EQ: "=", + ast.RelOp.NE: "/=", } # Serialization for builtin types BUILTIN_TYPES = { - ast.Types.BOOLEAN: 'Boolean', - ast.Types.INTEGER: 'Integer', + ast.Types.BOOLEAN: "Boolean", + ast.Types.INTEGER: "Integer", } @@ -31,10 +31,10 @@ def conv_name(name): up_next = False result.append(c.upper()) continue - if c == '_': + if c == "_": up_next = True result.append(c) - return ''.join(result) + return "".join(result) class PackageGuard(object): @@ -47,24 +47,22 @@ def __init__(self, language, is_spec, module_name): self.indent_guard = language.indent(language.INDENT) def __enter__(self): - self.language.write('package {}{} is'.format( - '' if self.is_spec else 'body ', - conv_name(self.module_name) - )) + self.language.write( + "package {}{} is".format( + "" if self.is_spec else "body ", conv_name(self.module_name) + ) + ) self.language.newline() self.indent_guard.__enter__() def __exit__(self, type, value, traceback): self.indent_guard.__exit__(type, value, traceback) - self.language.write( - 'end {};'.format(conv_name(self.module_name)) - ) + self.language.write("end {};".format(conv_name(self.module_name))) self.language.newline() class Language(language.Language): - - NAME = 'Ada' + NAME = "Ada" INDENT = 3 # @@ -72,10 +70,10 @@ class Language(language.Language): # def get_specification_filename(self, module_name): - return '{}.ads'.format(module_name) + return "{}.ads".format(module_name) def get_implementation_filename(self, module_name): - return '{}.adb'.format(module_name) + return "{}.adb".format(module_name) # # Serialization entry points @@ -101,28 +99,33 @@ def serialize_run_module_implementation( self.add_subprogram_signature( procedure_name, None, [], [], False ) - self.write('begin') + self.write("begin") self.newline() with self.indent(self.INDENT): call_to_run = ast.Call( ast.VariableUsage(self.ENTRY_POINT_NAME), [ op_kind.actuals[op_truth] - for op_kind, op_truth - in zip(operand_kinds, truth_vector) - ] + for op_kind, op_truth in zip( + operand_kinds, truth_vector + ) + ], + ) + self.handle( + ast.Call( + ast.VariableUsage(self.ASSERT_PROC_NAME), + [ + ast.Comparison( + ast.RelOp.EQ, + call_to_run, + ast.LitteralBoolean(truth_vector[-1]), + ) + ], + ) ) - self.handle(ast.Call( - ast.VariableUsage(self.ASSERT_PROC_NAME), - [ast.Comparison( - ast.RelOp.EQ, - call_to_run, - ast.LitteralBoolean(truth_vector[-1]) - )] - )) - self.write(';') + self.write(";") self.newline() - self.write('end {};'.format(conv_name(procedure_name))) + self.write("end {};".format(conv_name(procedure_name))) self.newline() # This one is specific to the Ada language, since this is the main @@ -149,14 +152,14 @@ def serialize_run_module_interface( # If the target language is not Ada, use the C # calling/mangling/whatever... convention. if target_language.NAME != self.NAME: - self.write('Pragma Import(C, {}, "{}");'.format( - conv_name(procedure_name), procedure_name - )) + self.write( + 'Pragma Import(C, {}, "{}");'.format( + conv_name(procedure_name), procedure_name + ) + ) self.newline() - def serialize_specification_types( - self, stream, types - ): + def serialize_specification_types(self, stream, types): self.set_stream(stream) with PackageGuard(self, True, self.TYPES_MODULE): for type_decl in types: @@ -173,15 +176,15 @@ def serialize_specification_program( with PackageGuard(self, True, self.COMPUTING_MODULE): self.add_subprogram_signature( - self.ENTRY_POINT_NAME, ast.BooleanType, - formal_names, formal_types, - True + self.ENTRY_POINT_NAME, + ast.BooleanType, + formal_names, + formal_types, + True, ) def serialize_implementation( - self, stream, - program, formal_names, formal_types, - one_operand_per_line + self, stream, program, formal_names, formal_types, one_operand_per_line ): self.set_stream(stream) @@ -191,9 +194,11 @@ def serialize_implementation( with PackageGuard(self, False, self.COMPUTING_MODULE): self.add_subprogram_signature( - self.ENTRY_POINT_NAME, ast.BooleanType, - formal_names, formal_types, - False + self.ENTRY_POINT_NAME, + ast.BooleanType, + formal_names, + formal_types, + False, ) self.handle(program) @@ -203,75 +208,76 @@ def serialize_implementation( def add_use(self, module_name): self.write( - 'with {name}; use {name};'.format(name=conv_name(module_name)) + "with {name}; use {name};".format(name=conv_name(module_name)) ) self.newline() - def add_subprogram_signature(self, name, return_type, formal_names, - formal_types, declaration): + def add_subprogram_signature( + self, name, return_type, formal_names, formal_types, declaration + ): """Add a subprogram signature to the output. If `return_type` is None, the subprogram is considered as a procedure. It is a function otherwise. """ # Add the type of subprogram and its name. - self.write('{} {}'.format( - 'function' if return_type else 'procedure', - conv_name(name), - )) + self.write( + "{} {}".format( + "function" if return_type else "procedure", + conv_name(name), + ) + ) # Add the list of formals. if len(formal_names) > 0: - self.write(' (') - for i, (name, type_) in enumerate( - zip(formal_names, formal_types) - ): + self.write(" (") + for i, (name, type_) in enumerate(zip(formal_names, formal_types)): if i > 0: - self.write('; ') - self.write('{} : '.format(conv_name(name))) + self.write("; ") + self.write("{} : ".format(conv_name(name))) self.handle(type_) - self.write(')') + self.write(")") # Add the return type, if any if return_type: - self.write(' return ') + self.write(" return ") self.handle(return_type) - self.write(';' if declaration else ' is') + self.write(";" if declaration else " is") self.newline() def handle_parent(self, expr): - self.write('(') + self.write("(") with self.indent(): self.handle(expr) - self.write(')') + self.write(")") def helper_binop(self, op, left, right): self.handle_composite_expr(left) if self.one_operand_per_line and utils.contains_tag(left): self.newline() else: - self.write(' ') - self.write('{} '.format(op)) + self.write(" ") + self.write("{} ".format(op)) self.handle_composite_expr(right) def format_comment(self, string): - return '-- {}'.format(string) + return "-- {}".format(string) def handle_program(self, program, declaration=False): with self.indent(self.INDENT): for name, type_ in program.local_vars: - self.write('{} : '.format(conv_name(name))) + self.write("{} : ".format(conv_name(name))) self.handle(type_) - self.write(';') + self.write(";") self.newline() - self.write('begin') + self.write("begin") self.newline() with self.indent(self.INDENT): for stmt in program.statements: self.handle(stmt) - self.write('end;') + self.write("end;") self.newline() # @@ -281,27 +287,27 @@ def handle_program(self, program, declaration=False): def handle_builtin_type(self, builtin_type, declaration=False): if declaration: raise ValueError( - 'Cannot output a type declaration for a builtin type' + "Cannot output a type declaration for a builtin type" ) else: self.write(BUILTIN_TYPES[builtin_type.name]) def handle_record_type(self, record_type, declaration=False): if declaration: - self.write('type {} is record'.format(conv_name(record_type.name))) + self.write("type {} is record".format(conv_name(record_type.name))) self.newline() with self.indent(self.INDENT): for member in record_type.members: self.handle(member) - self.write('end record;') + self.write("end record;") self.newline() else: self.write(conv_name(record_type.name)) def handle_member_decl(self, member_decl): - self.write('{} : '.format(conv_name(member_decl.name))) + self.write("{} : ".format(conv_name(member_decl.name))) self.handle(member_decl.type) - self.write(';') + self.write(";") self.newline() # @@ -309,10 +315,10 @@ def handle_member_decl(self, member_decl): # def handle_variable_usage(self, var): - self.write('{}'.format(conv_name(var.name))) + self.write("{}".format(conv_name(var.name))) def handle_litteral_integer(self, integer): - self.write('{}'.format(integer.value)) + self.write("{}".format(integer.value)) def handle_litteral_boolean(self, boolean): # Python and Ada happen to share the same syntax for litteral @@ -320,15 +326,15 @@ def handle_litteral_boolean(self, boolean): self.write(str(boolean.value)) def handle_litteral_record(self, record): - self.write('(') + self.write("(") for i, (member, decl) in enumerate( zip(record.members, record.type.members) ): if i > 0: - self.write(', ') - self.write('{} => '.format(conv_name(decl.name))) + self.write(", ") + self.write("{} => ".format(conv_name(decl.name))) self.handle(member) - self.write(')') + self.write(")") def handle_comparison(self, comp): self.helper_binop(REL_OP[comp.operator], comp.left, comp.right) @@ -336,86 +342,90 @@ def handle_comparison(self, comp): def handle_call(self, expr): self.handle_composite_expr(expr.function) if len(expr.arguments) > 0: - self.write('(') + self.write("(") with self.indent(): for i, arg in enumerate(expr.arguments): self.handle(arg) if i + 1 < len(expr.arguments): - self.write(',') + self.write(",") self.newline() - self.write(')') + self.write(")") # # Serialization for topology expressions # def handle_and_expr(self, expr): - self.helper_binop('and then', expr.left, expr.right) + self.helper_binop("and then", expr.left, expr.right) def handle_or_expr(self, expr): - self.helper_binop('or else', expr.left, expr.right) + self.helper_binop("or else", expr.left, expr.right) def handle_not_expr(self, expr): - self.write('not ') + self.write("not ") self.handle_composite_expr(expr.expr) def handle_composite_expr(self, expr): - is_composite = isinstance(expr, ( - ast.Comparison, - ast.And, ast.Or, - )) + is_composite = isinstance( + expr, + ( + ast.Comparison, + ast.And, + ast.Or, + ), + ) if is_composite: - self.write('(') + self.write("(") with self.indent(): self.handle(expr) if is_composite: - self.write(')') + self.write(")") # # Serialization for statements # def handle_if_stmt(self, stmt): - self.write('if ') + self.write("if ") with self.indent(): self.handle(stmt.condition) - self.write(' then') + self.write(" then") self.newline() with self.indent(self.INDENT): self.handle(stmt.true_stmt) - self.write('else') + self.write("else") self.newline() with self.indent(self.INDENT): self.handle(stmt.false_stmt) - self.write('end if;') + self.write("end if;") self.newline() def handle_while_stmt(self, stmt): - self.write('while ') + self.write("while ") with self.indent(): self.handle(stmt.condition) - self.write(' loop') + self.write(" loop") self.newline() with self.indent(self.INDENT): self.handle(stmt.stmt) - self.write('end loop;') + self.write("end loop;") self.newline() def handle_return_stmt(self, stmt): - self.write('return ') + self.write("return ") with self.indent(): self.handle(stmt.expr) - self.write(';') + self.write(";") self.newline() def handle_assign(self, stmt): self.handle(stmt.variable) - self.write(' := ') + self.write(" := ") self.handle(stmt.expr) - self.write(';') + self.write(";") self.newline() diff --git a/testsuite/SCOV/expgen/language/ada/context.py b/testsuite/SCOV/expgen/language/ada/context.py index 164619fab..20230b40a 100644 --- a/testsuite/SCOV/expgen/language/ada/context.py +++ b/testsuite/SCOV/expgen/language/ada/context.py @@ -11,42 +11,44 @@ class Case(context.LanguageSpecific): The decision expression is used as the controlling expression of a case statement. """ - LANGUAGE = 'Ada' + + LANGUAGE = "Ada" TAG_CONTEXT = ast.TagTypes.EXPRESSION FORMAT = [ - 'case {decision_expr} is', - ' when True =>', - ' return True; -- # on-true', - ' when False =>', - ' return False; -- # on-false', - 'end case;', + "case {decision_expr} is", + " when True =>", + " return True; -- # on-true", + " when False =>", + " return False; -- # on-false", + "end case;", ] class DeclarationInitializer(context.LanguageSpecific): """The decision expression is used as a local boolean initializer.""" - LANGUAGE = 'Ada' + + LANGUAGE = "Ada" TAG_CONTEXT = ast.TagTypes.EXPRESSION FORMAT = [ - 'declare', - ' E : Boolean := {decision_expr};' - 'begin', - ' return E;', - 'end;', + "declare", + " E : Boolean := {decision_expr};" "begin", + " return E;", + "end;", ] class Discriminant(context.LanguageSpecific): """The decision expression is used as a record discriminant.""" - LANGUAGE = 'Ada' + + LANGUAGE = "Ada" TAG_CONTEXT = ast.TagTypes.EXPRESSION FORMAT = [ - 'declare', - ' type My_Type (Value : Boolean) is null record;', - ' R : My_Type (Value => {decision_expr});', - 'begin', - ' return R.Value;', - 'end;', + "declare", + " type My_Type (Value : Boolean) is null record;", + " R : My_Type (Value => {decision_expr});", + "begin", + " return R.Value;", + "end;", ] @@ -55,14 +57,15 @@ class ExitWhen(context.LanguageSpecific): The decision expression is used as the condition for an EXIT WHEN statement. """ - LANGUAGE = 'Ada' + + LANGUAGE = "Ada" TAG_CONTEXT = ast.TagTypes.DECISION FORMAT = [ - 'loop', - ' exit when {decision_expr};', - ' return False; -- # on-false', - 'end loop;', - 'return True; -- # on-true', + "loop", + " exit when {decision_expr};", + " return False; -- # on-false", + "end loop;", + "return True; -- # on-true", ] @@ -71,31 +74,33 @@ class For(context.LanguageSpecific): The decision expression is used as the controlling expression of a for statement. """ - LANGUAGE = 'Ada' + + LANGUAGE = "Ada" TAG_CONTEXT = ast.TagTypes.EXPRESSION FORMAT = [ - 'declare', - ' E : Boolean := False;', - 'begin', - ' for Value in False .. ({decision_expr}) loop', - ' E := Value;', - ' end loop;', - ' return E;', - 'end;', + "declare", + " E : Boolean := False;", + "begin", + " for Value in False .. ({decision_expr}) loop", + " E := Value;", + " end loop;", + " return E;", + "end;", ] class Index(context.LanguageSpecific): """The decision expression is used as an array subscript.""" - LANGUAGE = 'Ada' + + LANGUAGE = "Ada" TAG_CONTEXT = ast.TagTypes.EXPRESSION FORMAT = [ - 'declare', - ' Values : array (Boolean) of Boolean := (', - ' False => False,', - ' True => True', - ' );', - 'begin', - ' return Value ({decision_expr});', - 'end;', + "declare", + " Values : array (Boolean) of Boolean := (", + " False => False,", + " True => True", + " );", + "begin", + " return Value ({decision_expr});", + "end;", ] diff --git a/testsuite/SCOV/expgen/language/ada/operand.py b/testsuite/SCOV/expgen/language/ada/operand.py index ef754e928..952f5767a 100644 --- a/testsuite/SCOV/expgen/language/ada/operand.py +++ b/testsuite/SCOV/expgen/language/ada/operand.py @@ -10,158 +10,168 @@ # # Bultin ones -INTEGER = ([], 'Integer') -STRING = ([], 'String') +INTEGER = ([], "Integer") +STRING = ([], "String") BOOLEAN_SUBTYPE = ( - ['subtype Bool_Subtype is Boolean;'], # Type declaration - 'Bool_Subtype' # Type usage + ["subtype Bool_Subtype is Boolean;"], # Type declaration + "Bool_Subtype", # Type usage ) BOOLEAN_TYPE = ( - ['type Bool_Type is new Boolean;'], # Type declaration - 'Bool_Type' # Type usage + ["type Bool_Type is new Boolean;"], # Type declaration + "Bool_Type", # Type usage ) -BOOLEAN_ACTUALS = {False: 'False', True: 'True'} +BOOLEAN_ACTUALS = {False: "False", True: "True"} SLOC_RECORD = ( [ # Type declaration - 'type Sloc is record', - ' Line : Integer;', - ' Column : Integer;', - 'end record;', + "type Sloc is record", + " Line : Integer;", + " Column : Integer;", + "end record;", ], - 'Sloc' # Type usage + "Sloc", # Type usage ) TWO_STRINGS = ( [ # Type declaration - 'type Two_Strings (L1, L2 : Integer) is record', - ' First : String (1 .. L1);', - ' Second : String (1 .. L2);', - 'end record;', + "type Two_Strings (L1, L2 : Integer) is record", + " First : String (1 .. L1);", + " Second : String (1 .. L2);", + "end record;", ], - 'Two_Strings' # Type usage + "Two_Strings", # Type usage ) SENSOR = ( [ # Type declaration - 'type Sensor is record', - ' Low, High : Integer;', - ' Value : Integer;', - 'end record;', + "type Sensor is record", + " Low, High : Integer;", + " Value : Integer;", + "end record;", ], - 'Sensor' # Type usage + "Sensor", # Type usage ) class Aggregate(operand.LanguageSpecific): """Compare the argument with some litteral aggregate.""" - LANGUAGE = 'Ada' - USED_TYPES = (SLOC_RECORD, ) + + LANGUAGE = "Ada" + USED_TYPES = (SLOC_RECORD,) PARAM_TYPE = SLOC_RECORD - FORMAT = '{formal_name} = (Line => 1, Column => 2)' + FORMAT = "{formal_name} = (Line => 1, Column => 2)" ACTUALS = { - False: '(Line => 1, Column => 3)', - True: '(Line => 1, Column => 2)', + False: "(Line => 1, Column => 3)", + True: "(Line => 1, Column => 2)", } class Component(operand.LanguageSpecific): """Compare the member of a structure with a litteral integer.""" - LANGUAGE = 'Ada' - USED_TYPES = (SLOC_RECORD, ) + + LANGUAGE = "Ada" + USED_TYPES = (SLOC_RECORD,) PARAM_TYPE = SLOC_RECORD - FORMAT = '{formal_name}.Line = 1' + FORMAT = "{formal_name}.Line = 1" ACTUALS = { - False: '(Line => 2, Column => 1)', - True: '(Line => 1, Column => 1)', + False: "(Line => 2, Column => 1)", + True: "(Line => 1, Column => 1)", } class LengthAttribute(operand.LanguageSpecific): """Compare the length of the argument with a constant.""" - LANGUAGE = 'Ada' - USED_TYPES = (STRING, ) + + LANGUAGE = "Ada" + USED_TYPES = (STRING,) PARAM_TYPE = STRING FORMAT = "{formal_name}'Length > 0" ACTUALS = { - False: '""', - True: '"Hello, world!"', + False: '""', + True: '"Hello, world!"', } class StringConcatenation(operand.LanguageSpecific): """Compare the concatenation of two strings with a litteral string.""" - LANGUAGE = 'Ada' - USED_TYPES = (STRING, TWO_STRINGS, ) + + LANGUAGE = "Ada" + USED_TYPES = ( + STRING, + TWO_STRINGS, + ) PARAM_TYPE = TWO_STRINGS FORMAT = ( - '({formal_name}.Second & {formal_name}.First)' - ' = "Hello, world!"' + "({formal_name}.Second & {formal_name}.First)" ' = "Hello, world!"' ) ACTUALS = { - False: '(Second => "I beg you", L2 => 9,' - ' First => "pardon?", L1 => 7)', - True: '(Second => "Hello, ", L2 => 7,' - ' First => "world!", L1 => 6)', + False: '(Second => "I beg you", L2 => 9,' + ' First => "pardon?", L1 => 7)', + True: '(Second => "Hello, ", L2 => 7,' + ' First => "world!", L1 => 6)', } class StringSlice(operand.LanguageSpecific): """Compare the slice of a string with a litteral string.""" - LANGUAGE = 'Ada' - USED_TYPES = (STRING, ) + + LANGUAGE = "Ada" + USED_TYPES = (STRING,) PARAM_TYPE = STRING FORMAT = ( - '{formal_name}( {formal_name}\'First .. {formal_name}\'Last - 1)' + "{formal_name}( {formal_name}'First .. {formal_name}'Last - 1)" ' = "Hell"' ) ACTUALS = { - False: '"World"', - True: '"Hello"', + False: '"World"', + True: '"Hello"', } class Modulo(operand.LanguageSpecific): """Compare the modulo of the argument with a litteral integer.""" - LANGUAGE = 'Ada' - USED_TYPES = (INTEGER, ) + + LANGUAGE = "Ada" + USED_TYPES = (INTEGER,) PARAM_TYPE = INTEGER - FORMAT = '{formal_name} mod 17 = 0' + FORMAT = "{formal_name} mod 17 = 0" ACTUALS = { - False: '18', - True: '34', + False: "18", + True: "34", } class Range(operand.LanguageSpecific): """Test whether an integer is in a range.""" - LANGUAGE = 'Ada' - USED_TYPES = (SENSOR, ) + + LANGUAGE = "Ada" + USED_TYPES = (SENSOR,) PARAM_TYPE = SENSOR FORMAT = ( - '{formal_name}.Value in ' - '{formal_name}.Low .. {formal_name}.High' + "{formal_name}.Value in " "{formal_name}.Low .. {formal_name}.High" ) ACTUALS = { - False: '(Low => 0, High => 10, Value => 15)', - True: '(Low => 0, High => 10, Value => 10)', + False: "(Low => 0, High => 10, Value => 15)", + True: "(Low => 0, High => 10, Value => 10)", } class Subtype(operand.LanguageSpecific): """Use a subtype of Boolean as an operand.""" - LANGUAGE = 'Ada' - USED_TYPES = (BOOLEAN_SUBTYPE, ) + + LANGUAGE = "Ada" + USED_TYPES = (BOOLEAN_SUBTYPE,) PARAM_TYPE = BOOLEAN_SUBTYPE - FORMAT = '{formal_name}' + FORMAT = "{formal_name}" ACTUALS = BOOLEAN_ACTUALS class DerivedType(operand.LanguageSpecific): """Use a derived type of Boolean as an operand.""" - LANGUAGE = 'Ada' - USED_TYPES = (BOOLEAN_TYPE, ) + + LANGUAGE = "Ada" + USED_TYPES = (BOOLEAN_TYPE,) PARAM_TYPE = BOOLEAN_TYPE - FORMAT = 'Boolean({formal_name})' + FORMAT = "Boolean({formal_name})" ACTUALS = BOOLEAN_ACTUALS diff --git a/testsuite/SCOV/expgen/language/c/__init__.py b/testsuite/SCOV/expgen/language/c/__init__.py index fc588fcb7..11bc57e9d 100644 --- a/testsuite/SCOV/expgen/language/c/__init__.py +++ b/testsuite/SCOV/expgen/language/c/__init__.py @@ -7,18 +7,18 @@ # Serialization of relational operators REL_OP = { - ast.RelOp.GT: '>', - ast.RelOp.GE: '>=', - ast.RelOp.LT: '>', - ast.RelOp.LE: '>=', - ast.RelOp.EQ: '==', - ast.RelOp.NE: '!=', + ast.RelOp.GT: ">", + ast.RelOp.GE: ">=", + ast.RelOp.LT: ">", + ast.RelOp.LE: ">=", + ast.RelOp.EQ: "==", + ast.RelOp.NE: "!=", } # Serialization for builtin types BUILTIN_TYPES = { - ast.Types.BOOLEAN: 'int', - ast.Types.INTEGER: 'int', + ast.Types.BOOLEAN: "int", + ast.Types.INTEGER: "int", } @@ -30,32 +30,31 @@ def __init__(self, language, module_name): self.module_name = module_name def __enter__(self): - self.language.write('#ifndef {}_H'.format(self.module_name.upper())) + self.language.write("#ifndef {}_H".format(self.module_name.upper())) self.language.newline() - self.language.write('#define {}_H'.format(self.module_name.upper())) + self.language.write("#define {}_H".format(self.module_name.upper())) self.language.newline() def __exit__(self, type, value, traceback): - self.language.write('#endif') + self.language.write("#endif") self.language.newline() class Language(language.Language): - - NAME = 'C' + NAME = "C" INDENT = 2 - RUN_MODULE = 'run_body' + RUN_MODULE = "run_body" # # Filename generators # def get_specification_filename(self, module_name): - return '{}.h'.format(module_name) + return "{}.h".format(module_name) def get_implementation_filename(self, module_name): - return '{}.c'.format(module_name) + return "{}.c".format(module_name) # # Serialization entry points @@ -77,36 +76,38 @@ def serialize_run_module_implementation( self.newline() self.add_subprogram_signature( - self.get_run_procedure_name(truth_vector), - None, [], [], False + self.get_run_procedure_name(truth_vector), None, [], [], False ) - self.write('{') + self.write("{") self.newline() with self.indent(self.INDENT): call_to_run = ast.Call( ast.VariableUsage(self.ENTRY_POINT_NAME), [ op_kind.actuals[op_truth] - for op_kind, op_truth - in zip(operand_kinds, truth_vector) - ] + for op_kind, op_truth in zip( + operand_kinds, truth_vector + ) + ], + ) + self.handle( + ast.Call( + ast.VariableUsage(self.ASSERT_PROC_NAME), + [ + ast.Comparison( + ast.RelOp.EQ, + call_to_run, + ast.LitteralBoolean(truth_vector[-1]), + ) + ], + ) ) - self.handle(ast.Call( - ast.VariableUsage(self.ASSERT_PROC_NAME), - [ast.Comparison( - ast.RelOp.EQ, - call_to_run, - ast.LitteralBoolean(truth_vector[-1]) - )] - )) - self.write(';') + self.write(";") self.newline() - self.write('}') + self.write("}") self.newline() - def serialize_specification_types( - self, stream, types - ): + def serialize_specification_types(self, stream, types): self.set_stream(stream) with HeaderGuard(self, self.TYPES_MODULE): for type_decl in types: @@ -122,15 +123,15 @@ def serialize_specification_program( self.newline() self.add_subprogram_signature( - self.ENTRY_POINT_NAME, ast.BooleanType, - formal_names, formal_types, - True + self.ENTRY_POINT_NAME, + ast.BooleanType, + formal_names, + formal_types, + True, ) def serialize_implementation( - self, stream, - program, formal_names, formal_types, - one_operand_per_line + self, stream, program, formal_names, formal_types, one_operand_per_line ): self.set_stream(stream) @@ -142,14 +143,16 @@ def serialize_implementation( self.newline() self.add_subprogram_signature( - self.ENTRY_POINT_NAME, ast.BooleanType, - formal_names, formal_types, - False + self.ENTRY_POINT_NAME, + ast.BooleanType, + formal_names, + formal_types, + False, ) - self.write('{') + self.write("{") self.newline() self.handle(program) - self.write('}') + self.write("}") self.newline() # @@ -160,8 +163,9 @@ def add_include(self, module_name): self.write('#include "{}.h"'.format(module_name)) self.newline() - def add_subprogram_signature(self, name, return_type, formal_names, - formal_types, declaration): + def add_subprogram_signature( + self, name, return_type, formal_names, formal_types, declaration + ): """Add a subprogram signature to the output. If `return_type` is None, the subprogram is considered as a procedure. @@ -169,53 +173,51 @@ def add_subprogram_signature(self, name, return_type, formal_names, """ # Add subprogram return type, prepend subprogram linkage if needed. if declaration: - self.write('extern ') + self.write("extern ") if return_type: self.handle(return_type) else: - self.write('void') + self.write("void") self.newline() # Then add the name of the subprogram and its arguments. - self.write('{} ('.format(name)) - for i, (name, type_) in enumerate( - zip(formal_names, formal_types) - ): + self.write("{} (".format(name)) + for i, (name, type_) in enumerate(zip(formal_names, formal_types)): if i > 0: - self.write(', ') + self.write(", ") self.handle(type_) - self.write(' {}'.format(name)) + self.write(" {}".format(name)) if len(formal_names) == 0: - self.write('void') - self.write(')') + self.write("void") + self.write(")") if declaration: - self.write(';') + self.write(";") self.newline() def handle_parent(self, expr): - self.write('(') + self.write("(") with self.indent(): self.handle(expr) - self.write(')') + self.write(")") def helper_binop(self, op, left, right): self.handle_composite_expr(left) if self.one_operand_per_line and utils.contains_tag(left): self.newline() else: - self.write(' ') - self.write('{} '.format(op)) + self.write(" ") + self.write("{} ".format(op)) self.handle_composite_expr(right) def format_comment(self, string): - return '// {}'.format(string) + return "// {}".format(string) def handle_program(self, program, declaration=False): with self.indent(self.INDENT): for name, type_ in program.local_vars: self.handle(type_) - self.write(' {};'.format(name)) + self.write(" {};".format(name)) self.newline() for stmt in program.statements: @@ -228,28 +230,28 @@ def handle_program(self, program, declaration=False): def handle_builtin_type(self, builtin_type, declaration=False): if declaration: raise ValueError( - 'Cannot output a type declaration for a builtin type' + "Cannot output a type declaration for a builtin type" ) else: self.write(BUILTIN_TYPES[builtin_type.name]) def handle_record_type(self, record_type, declaration=False): if declaration: - self.write('struct {}'.format(record_type.name)) + self.write("struct {}".format(record_type.name)) self.newline() - self.write('{') + self.write("{") self.newline() with self.indent(self.INDENT): for member in record_type.members: self.handle(member) - self.write('};') + self.write("};") self.newline() else: - self.write('struct {}'.format(record_type.name)) + self.write("struct {}".format(record_type.name)) def handle_member_decl(self, member_decl): self.handle(member_decl.type) - self.write(' {};'.format(member_decl.name)) + self.write(" {};".format(member_decl.name)) self.newline() # @@ -257,118 +259,120 @@ def handle_member_decl(self, member_decl): # def handle_variable_usage(self, var): - self.write('{}'.format(var.name)) + self.write("{}".format(var.name)) def handle_litteral_integer(self, integer): - self.write('{}'.format(integer.value)) + self.write("{}".format(integer.value)) def handle_litteral_boolean(self, boolean): - self.write('{}'.format( - {True: 1, False: 0}[boolean.value] - )) + self.write("{}".format({True: 1, False: 0}[boolean.value])) def handle_litteral_record(self, record): - self.write('(') + self.write("(") self.handle(record.type) - self.write(') {') + self.write(") {") for i, member in enumerate(record.members): if i > 0: - self.write(', ') + self.write(", ") self.handle(member) - self.write('}') + self.write("}") def handle_comparison(self, comp): self.helper_binop(REL_OP[comp.operator], comp.left, comp.right) def handle_call(self, expr): self.handle_composite_expr(expr.function) - self.write('(') + self.write("(") with self.indent(): for i, arg in enumerate(expr.arguments): self.handle(arg) if i + 1 < len(expr.arguments): - self.write(',') + self.write(",") self.newline() - self.write(')') + self.write(")") # # Serialization for topology expressions # def handle_and_expr(self, expr): - self.helper_binop('&&', expr.left, expr.right) + self.helper_binop("&&", expr.left, expr.right) def handle_or_expr(self, expr): - self.helper_binop('||', expr.left, expr.right) + self.helper_binop("||", expr.left, expr.right) def handle_not_expr(self, expr): - self.write('!') + self.write("!") self.handle_composite_expr(expr.expr) def handle_composite_expr(self, expr): - is_composite = isinstance(expr, ( - ast.Comparison, - ast.And, ast.Or, - )) + is_composite = isinstance( + expr, + ( + ast.Comparison, + ast.And, + ast.Or, + ), + ) if is_composite: - self.write('(') + self.write("(") with self.indent(): self.handle(expr) if is_composite: - self.write(')') + self.write(")") # # Serialization for statements # def handle_if_stmt(self, stmt): - self.write('if (') + self.write("if (") with self.indent(): self.handle(stmt.condition) - self.write(')') + self.write(")") self.newline() - self.write('{') + self.write("{") self.newline() with self.indent(self.INDENT): self.handle(stmt.true_stmt) - self.write('}') + self.write("}") self.newline() - self.write('else') + self.write("else") self.newline() - self.write('{') + self.write("{") self.newline() with self.indent(self.INDENT): self.handle(stmt.false_stmt) - self.write('}') + self.write("}") self.newline() def handle_while_stmt(self, stmt): - self.write('while (') + self.write("while (") with self.indent(): self.handle(stmt.condition) - self.write(')') + self.write(")") self.newline() - self.write('{') + self.write("{") self.newline() with self.indent(self.INDENT): self.handle(stmt.stmt) - self.write('}') + self.write("}") self.newline() def handle_return_stmt(self, stmt): - self.write('return ') + self.write("return ") with self.indent(): self.handle(stmt.expr) - self.write(';') + self.write(";") self.newline() def handle_assign(self, stmt): self.handle(stmt.variable) - self.write(' = ') + self.write(" = ") self.handle(stmt.expr) - self.write(';') + self.write(";") self.newline() diff --git a/testsuite/SCOV/expgen/language/c/context.py b/testsuite/SCOV/expgen/language/c/context.py index 1b398a990..47442efd2 100644 --- a/testsuite/SCOV/expgen/language/c/context.py +++ b/testsuite/SCOV/expgen/language/c/context.py @@ -8,9 +8,10 @@ class DeclarationInitializer(context.LanguageSpecific): """The decision expression is used as a local boolean initializer.""" - LANGUAGE = 'C' + + LANGUAGE = "C" TAG_CONTEXT = ast.TagTypes.EXPRESSION FORMAT = [ - 'int result = {decision_expr};', - 'return result;', + "int result = {decision_expr};", + "return result;", ] diff --git a/testsuite/SCOV/expgen/language/c/operand.py b/testsuite/SCOV/expgen/language/c/operand.py index 05ebbf6f9..7006ac50e 100644 --- a/testsuite/SCOV/expgen/language/c/operand.py +++ b/testsuite/SCOV/expgen/language/c/operand.py @@ -10,40 +10,42 @@ # # Builtin types -INTEGER = ([], 'int') +INTEGER = ([], "int") SLOC_STRUCT = ( [ # Type declaration - 'struct sloc', - '{', - ' int line;', - ' int column;', - '};' + "struct sloc", + "{", + " int line;", + " int column;", + "};", ], - 'struct sloc' # Type usage + "struct sloc", # Type usage ) class Component(operand.LanguageSpecific): """Compare a field of a structure with a litteral integer.""" - LANGUAGE = 'C' - USED_TYPES = (SLOC_STRUCT, ) + + LANGUAGE = "C" + USED_TYPES = (SLOC_STRUCT,) PARAM_TYPE = SLOC_STRUCT - FORMAT = '{formal_name}.line == 1' + FORMAT = "{formal_name}.line == 1" ACTUALS = { - False: '(struct sloc) {2, 1}', - True: '(struct sloc) {1, 1}', + False: "(struct sloc) {2, 1}", + True: "(struct sloc) {1, 1}", } class Modulo(operand.LanguageSpecific): """Compare the modulo of the arguent with a litteral integer.""" - LANGUAGE = 'C' - USED_TYPES = (INTEGER, ) + + LANGUAGE = "C" + USED_TYPES = (INTEGER,) PARAM_TYPE = INTEGER - FORMAT = '{formal_name} % 17 == 0' + FORMAT = "{formal_name} % 17 == 0" ACTUALS = { - False: '18', - True: '34', + False: "18", + True: "34", } diff --git a/testsuite/SCOV/expgen/operand.py b/testsuite/SCOV/expgen/operand.py index 204daa3df..81e63f273 100644 --- a/testsuite/SCOV/expgen/operand.py +++ b/testsuite/SCOV/expgen/operand.py @@ -67,14 +67,14 @@ def __init__(self): if type_ is self.PARAM_TYPE: param_type = xtype - assert param_type is not None, ( - 'PARAM_TYPE must be present in USED_TYPES' - ) + assert ( + param_type is not None + ), "PARAM_TYPE must be present in USED_TYPES" # Convert ACTUALS to ast.XLitteral nodes. actuals = { - False: ast.XLitteral(self.LANGUAGE, self.ACTUALS[False]), - True: ast.XLitteral(self.LANGUAGE, self.ACTUALS[True]), + False: ast.XLitteral(self.LANGUAGE, self.ACTUALS[False]), + True: ast.XLitteral(self.LANGUAGE, self.ACTUALS[True]), } super(LanguageSpecific, self).__init__(xtypes, param_type, actuals) @@ -109,9 +109,7 @@ class Variable(Operand): def __init__(self): super(Variable, self).__init__( - (ast.BooleanType, ), - ast.BooleanType, - self.ACTUALS + (ast.BooleanType,), ast.BooleanType, self.ACTUALS ) def get_operand(self, param): @@ -125,36 +123,28 @@ class IntegerComparison(Operand): # Each factory takes the compared integer and returns (a false actual, a # true one). ACTUALS_MAKERS = { - ast.RelOp.GT: - lambda value: (value - 1, value + 1), - ast.RelOp.GE: - lambda value: (value - 1, value + 1), - ast.RelOp.LT: - lambda value: (value + 1, value - 2), - ast.RelOp.LE: - lambda value: (value + 1, value - 2), - ast.RelOp.EQ: - lambda value: (value + 1, value), - ast.RelOp.NE: - lambda value: (value, value + 1), + ast.RelOp.GT: lambda value: (value - 1, value + 1), + ast.RelOp.GE: lambda value: (value - 1, value + 1), + ast.RelOp.LT: lambda value: (value + 1, value - 2), + ast.RelOp.LE: lambda value: (value + 1, value - 2), + ast.RelOp.EQ: lambda value: (value + 1, value), + ast.RelOp.NE: lambda value: (value, value + 1), } def __init__(self, operator, value): actual_false, actual_true = self.ACTUALS_MAKERS[operator](value) super(IntegerComparison, self).__init__( - (ast.IntegerType, ), + (ast.IntegerType,), ast.IntegerType, { False: ast.LitteralInteger(actual_false), True: ast.LitteralInteger(actual_true), - } + }, ) self.operator = operator self.value = ast.LitteralInteger(value) def get_operand(self, param): return ast.Comparison( - self.operator, - ast.VariableUsage(param), - self.value + self.operator, ast.VariableUsage(param), self.value ) diff --git a/testsuite/SCOV/expgen/topology.py b/testsuite/SCOV/expgen/topology.py index 18071043c..cb18a0e99 100644 --- a/testsuite/SCOV/expgen/topology.py +++ b/testsuite/SCOV/expgen/topology.py @@ -16,6 +16,7 @@ class OperandPlaceholder(object): """Placeholder to be put in expressions to specify a topology.""" + pass @@ -36,10 +37,7 @@ def get_arity(self, expression): if isinstance(expression, OperandPlaceholder): return 1 else: - return sum( - self.get_arity(sub_expr) - for sub_expr in expression - ) + return sum(self.get_arity(sub_expr) for sub_expr in expression) def instanciate(self, operands, formal_names, context): """ @@ -59,8 +57,8 @@ def helper(expression, i): # it. if isinstance(expression, OperandPlaceholder): result = ast.TaggedNode( - ast.Tag('eval', formal_names[i], context.TAG_CONTEXT), - operands[i] + ast.Tag("eval", formal_names[i], context.TAG_CONTEXT), + operands[i], ) return (result, i + 1) @@ -115,7 +113,7 @@ def helper(expression, i): return (not result, i) else: raise ValueError( - 'Invalid topology node: {}'.format(expression) + "Invalid topology node: {}".format(expression) ) # The number of operands must naturally match the number of @@ -130,21 +128,20 @@ def helper(expression, i): return result def __str__(self): - - placeholders = list(reversed('ABCDEFGHIJ')) + placeholders = list(reversed("ABCDEFGHIJ")) def helper(expr): if isinstance(expr, OperandPlaceholder): return placeholders.pop() elif isinstance(expr, ast.And): - return '({} and {})'.format( + return "({} and {})".format( helper(expr.left), helper(expr.right) ) elif isinstance(expr, ast.Or): - return '({} or {})'.format( + return "({} or {})".format( helper(expr.left), helper(expr.right) ) else: - return 'not {}'.format(helper(expr.expr)) + return "not {}".format(helper(expr.expr)) return helper(self.expression) diff --git a/testsuite/SCOV/expgen/utils.py b/testsuite/SCOV/expgen/utils.py index b8725a131..9da55ecbe 100644 --- a/testsuite/SCOV/expgen/utils.py +++ b/testsuite/SCOV/expgen/utils.py @@ -7,7 +7,7 @@ def check_tag(tag): """Assert whether the given `tag` is valid, or not.""" - if tag.name == 'eval': + if tag.name == "eval": assert tag.context in (ast.TagTypes.DECISION, ast.TagTypes.EXPRESSION) assert tag.operand is not None else: @@ -17,32 +17,38 @@ def check_tag(tag): def format_tag(tag): """Serialize the given `tag`.""" - if tag.name == 'eval': - return '# {}-{} {}'.format(tag.name, tag.operand, tag.context) + if tag.name == "eval": + return "# {}-{} {}".format(tag.name, tag.operand, tag.context) else: - return '# {}'.format(tag.name) + return "# {}".format(tag.name) def contains_tag(node): """Return if the given `node` tree contains a tagged node.""" - return ( - not isinstance(node, (str, bool, int)) and - ( - isinstance(node, ast.TaggedNode) or - any(contains_tag(subnode) for subnode in node) - ) + return not isinstance(node, (str, bool, int)) and ( + isinstance(node, ast.TaggedNode) + or any(contains_tag(subnode) for subnode in node) ) def is_expr(node): """Return whether `node` is an expression.""" - return isinstance(node, ( - ast.VariableUsage, - ast.LitteralInteger, ast.LitteralBoolean, ast.LitteralRecord, - ast.Comparison, ast.Call, - ast.XLitteral, ast.XOperand, - ast.And, ast.Or, ast.Not, - )) + return isinstance( + node, + ( + ast.VariableUsage, + ast.LitteralInteger, + ast.LitteralBoolean, + ast.LitteralRecord, + ast.Comparison, + ast.Call, + ast.XLitteral, + ast.XOperand, + ast.And, + ast.Or, + ast.Not, + ), + ) def make_type_set(types): @@ -58,11 +64,7 @@ def add_if_new(type_): else: return False - return [ - type_ - for type_ in types - if add_if_new(type_) - ] + return [type_ for type_ in types if add_if_new(type_)] def is_topology_equal(topo1, topo2): diff --git a/testsuite/SCOV/htc.py b/testsuite/SCOV/htc.py index 5a96a6553..ef80dbe59 100644 --- a/testsuite/SCOV/htc.py +++ b/testsuite/SCOV/htc.py @@ -34,8 +34,9 @@ def match(self, reported): class HarnessTestCase(TestCase): - def __init__(self, expected_diags, extradrivers="", extracargs="", - category=CAT.auto): + def __init__( + self, expected_diags, extradrivers="", extracargs="", category=CAT.auto + ): TestCase.__init__(self, extradrivers, extracargs, category) # By default, these test cases expect failures from subprocesses @@ -58,7 +59,9 @@ def run(self): for errtext in re.findall( pattern=r"^ \* (?:exception|\(.*\)) .*", string=contents_of(thistest.report.report_file), - flags=re.M)] + flags=re.M, + ) + ] for reported in self.reported_diags: for expected in self.expected_diags: @@ -66,12 +69,16 @@ def run(self): self.__count_match_on(reported, expected) for expected in self.expected_diags: - thistest.fail_if(expected.nmatches != 1, - "expectation check failed - %s" % expected.text) + thistest.fail_if( + expected.nmatches != 1, + "expectation check failed - %s" % expected.text, + ) for i in self.reported_diags: print(i.__dict__) for reported in self.reported_diags: - thistest.fail_if(reported.nmatches != 1, - "reporting check failed - %s" % reported.text) + thistest.fail_if( + reported.nmatches != 1, + "reporting check failed - %s" % reported.text, + ) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 3d05da07b..d1b4d686f 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -15,19 +15,21 @@ def default_dump_trigger(mains): if thistest.options.default_dump_trigger: return thistest.options.default_dump_trigger elif RUNTIME_INFO.has_full_runtime: - return 'atexit' + return "atexit" # It does not make sense to have a dump-trigger=ravenscar-task-termination # if the main is not an Ada program. - elif (all([ext(main) == 'adb' for main in mains]) - and RUNTIME_INFO.has_ravenscar_runtime - # TODO: There seems to be a problem with light-tasking runtimes and - # task-termination, so default back to main end in that case. - # See eng/cov/gnatcoverage#191 - and "light-tasking" not in RUNTIME_INFO.runtime_name): - return 'ravenscar-task-termination' + elif ( + all([ext(main) == "adb" for main in mains]) + and RUNTIME_INFO.has_ravenscar_runtime + # TODO: There seems to be a problem with light-tasking runtimes and + # task-termination, so default back to main end in that case. + # See eng/cov/gnatcoverage#191 + and "light-tasking" not in RUNTIME_INFO.runtime_name + ): + return "ravenscar-task-termination" else: - return 'main-end' + return "main-end" def default_dump_channel(): @@ -35,17 +37,28 @@ def default_dump_channel(): if thistest.options.default_dump_channel: return thistest.options.default_dump_channel elif RUNTIME_INFO.has_full_runtime: - return 'bin-file' + return "bin-file" else: - return 'base64-stdout' - - -def xcov_instrument(gprsw, covlevel, quiet=True, extra_args=[], - dump_trigger="auto", dump_channel="auto", gpr_obj_dir=None, - runtime_project=None, out=None, err=None, - tolerate_messages=None, register_failure=True, - auto_config_args=True, auto_target_args=True, - auto_languages=True): + return "base64-stdout" + + +def xcov_instrument( + gprsw, + covlevel, + quiet=True, + extra_args=[], + dump_trigger="auto", + dump_channel="auto", + gpr_obj_dir=None, + runtime_project=None, + out=None, + err=None, + tolerate_messages=None, + register_failure=True, + auto_config_args=True, + auto_target_args=True, + auto_languages=True, +): """ Run "gnatcov instrument" on a project. @@ -82,7 +95,7 @@ def xcov_instrument(gprsw, covlevel, quiet=True, extra_args=[], if gpr_obj_dir: mkdir(gpr_obj_dir) - covlevel_args = [] if covlevel is None else ['--level', covlevel] + covlevel_args = [] if covlevel is None else ["--level", covlevel] # We want to get the mains to know which dump-trigger should be passed to # the instrumentation command. @@ -96,10 +109,10 @@ def xcov_instrument(gprsw, covlevel, quiet=True, extra_args=[], # If found, split then remove whitespaces and double quotes mains = [] if m: - mains = m.group('mains').split(',') + mains = m.group("mains").split(",") mains = [main.strip(' "') for main in mains] - args = ['instrument'] + covlevel_args + args = ["instrument"] + covlevel_args if quiet: args.append("--quiet") @@ -117,7 +130,7 @@ def xcov_instrument(gprsw, covlevel, quiet=True, extra_args=[], args += gprsw.cov_switches + extra_args if thistest.options.pretty_print: - args.append('--pretty-print') + args.append("--pretty-print") out = out or "instrument.log" result = xcov( @@ -140,9 +153,9 @@ def xcov_instrument(gprsw, covlevel, quiet=True, extra_args=[], # effort attempt at creating objects dirs beforehand but doing # that is cumbersome for some of the more convoluted tests. if GNATCOV_INFO.major_at_most(22): - re_tolerate_messages = '|'.join( - "(?:{})".format(mre) for mre in [ - "object directory.*not found", re_tolerate_messages] + re_tolerate_messages = "|".join( + "(?:{})".format(mre) + for mre in ["object directory.*not found", re_tolerate_messages] ) if register_failure: @@ -155,25 +168,33 @@ def xcov_instrument(gprsw, covlevel, quiet=True, extra_args=[], # app.gpr:4:23: warning: object directory "obj" not found messages = re.findall( - pattern="(?:!!!|\*\*\*|warning:).*$", string=output, - flags=re.MULTILINE) + pattern="(?:!!!|\*\*\*|warning:).*$", + string=output, + flags=re.MULTILINE, + ) unexpected_messages = [ - w for w in messages + w + for w in messages if not re.search(pattern=re_tolerate_messages, string=w) ] thistest.fail_if( unexpected_messages, f"Unexpected messages in the output of 'gnatcov instrument':" - f"\n{indent(output)}" + \ - (f"\n(allowed: {tolerate_messages})" if tolerate_messages else "") + f"\n{indent(output)}" + + ( + f"\n(allowed: {tolerate_messages})" + if tolerate_messages + else "" + ), ) return result -def xcov_convert_base64(base64_file, output_trace_file, out=None, err=None, - register_failure=True): +def xcov_convert_base64( + base64_file, output_trace_file, out=None, err=None, register_failure=True +): """Extract a trace file out of a Base64 file. :param str base64_file: Name of the file to read. @@ -181,8 +202,12 @@ def xcov_convert_base64(base64_file, output_trace_file, out=None, err=None, See SUITE.tutils.xcov for the other supported options. """ - xcov(['extract-base64-trace', base64_file, output_trace_file], - out=out, err=err, register_failure=register_failure) + xcov( + ["extract-base64-trace", base64_file, output_trace_file], + out=out, + err=err, + register_failure=register_failure, + ) def add_dumper_lch_hook(project, obj_dir, subdirs, main_unit): @@ -210,7 +235,7 @@ def add_dumper_lch_hook(project, obj_dir, subdirs, main_unit): # Make sure we have a lowe-cased project *name* (not a filename) project = os.path.basename(project).lower() - if project.endswith('.gpr'): + if project.endswith(".gpr"): project = project[:-4] # Unit that contain helper routines to dump coverage buffers. There is one @@ -220,34 +245,44 @@ def add_dumper_lch_hook(project, obj_dir, subdirs, main_unit): # so there should be no problem using the helper unit of a different main. auto_dump_hash = None - for _,_, files in os.walk (os.path.join(obj_dir, f"{project}-gnatcov-instr")): + for _, _, files in os.walk( + os.path.join(obj_dir, f"{project}-gnatcov-instr") + ): for file in files: - res = re.match(pattern="gcvrt-db_z([0-9a-f]+).adb",string=file) + res = re.match(pattern="gcvrt-db_z([0-9a-f]+).adb", string=file) if res: auto_dump_hash = res.group(1) break if auto_dump_hash: break - assert(auto_dump_hash is not None) + assert auto_dump_hash is not None - auto_dump_unit = 'GCVRT.DB_z{}'.format(auto_dump_hash) + auto_dump_unit = "GCVRT.DB_z{}".format(auto_dump_hash) handler_unit = "Last_Chance_Dumper" def filename(prefix, ext): - return os.path.join(obj_dir, '{}-gnatcov-instr'.format(project), - '{}.{}'.format(prefix, ext)) + return os.path.join( + obj_dir, + "{}-gnatcov-instr".format(project), + "{}.{}".format(prefix, ext), + ) unit_prefix = handler_unit.lower() - with open(filename(unit_prefix, 'ads'), 'w') as f: - f.write(""" + with open(filename(unit_prefix, "ads"), "w") as f: + f.write( + """ package {unit_name} is procedure Lch_Enter; pragma Export (Ada, Lch_Enter, "__lch_enter"); end {unit_name}; - """.format(unit_name=handler_unit)) - with open(filename(unit_prefix, 'adb'), 'w') as f: - f.write(""" + """.format( + unit_name=handler_unit + ) + ) + with open(filename(unit_prefix, "adb"), "w") as f: + f.write( + """ with {auto_dump_unit}; package body {unit_name} is @@ -256,8 +291,10 @@ def filename(prefix, ext): {auto_dump_unit}.Dump_Buffers; end; end {unit_name}; - """.format(unit_name=handler_unit, - auto_dump_unit=auto_dump_unit)) + """.format( + unit_name=handler_unit, auto_dump_unit=auto_dump_unit + ) + ) # Amend the main unit to "with" the generated package so it gets # included in the build. Insert the "with" clause after all pragmas @@ -296,10 +333,12 @@ def available_ada_dump_triggers(): """ if RUNTIME_INFO.has_full_runtime: return ["main-end", "atexit"] - elif (RUNTIME_INFO.has_ravenscar_runtime - # TODO: remove once --dump-trigger=ravenscar-task-termination is - # fixed, see eng/das/cov/gnatcoverage#191. - and "light-tasking" not in RUNTIME_INFO.runtime_name): + elif ( + RUNTIME_INFO.has_ravenscar_runtime + # TODO: remove once --dump-trigger=ravenscar-task-termination is + # fixed, see eng/das/cov/gnatcoverage#191. + and "light-tasking" not in RUNTIME_INFO.runtime_name + ): return ["main-end", "ravenscar-task-termination"] else: return ["main-end"] diff --git a/testsuite/SCOV/internals/cnotes.py b/testsuite/SCOV/internals/cnotes.py index 12abf372c..74f1a9353 100644 --- a/testsuite/SCOV/internals/cnotes.py +++ b/testsuite/SCOV/internals/cnotes.py @@ -158,48 +158,115 @@ # Annotations lower than strictNote won't trigger an unexpected annotation # failure if they appear in a place where they are not explicitly expected. -(lNoCode, lFullCov, lx, - strictNote, - r0, r0c, lx0, lx1, lx2, - deviationNote, - lNoCov, lPartCov, lNotCoverable, lUndetCov, - sNoCov, sPartCov, sNotCoverable, sUndetCov, - dtAlways, dfAlways, - dtNoCov, dfNoCov, dNoCov, dPartCov, dUndetCov, - etNoCov, efNoCov, eNoCov, ePartCov, eUndetCov, - otNoCov, ofNoCov, oNoCov, oPartCov, - cPartCov, - XsNoCov, XsPartCov, XsNotCoverable, XsUndetCov, - XotNoCov, XofNoCov, XoPartCov, XoNoCov, - XcPartCov, - Xr0, Xr0c, - aNoCov, atNoCov, acPartCov, - blockNote, - xBlock0, xBlock1, xBlock2) = range(53) - -NK_image = {None: "None", - lNoCode: "lNoCode", lNotCoverable: "lNotCoverable", - lUndetCov: "lUndetCov", - lFullCov: "lFullCov", lNoCov: "lNoCov", lPartCov: "lPartCov", - r0: "r0", r0c: "r0c", lx0: "lx0", lx1: "lx1", lx2: "lx2", lx: "lx", - sNoCov: "sNoCov", sPartCov: "sPartCov", - sNotCoverable: "sNotCoverable", sUndetCov: "sUndetCov", - dtAlways: "dtAlways", dfAlways: "dfAlways", - dtNoCov: "dtNoCov", dfNoCov: "dfNoCov", dNoCov: "dNoCov", - dPartCov: "dPartCov", dUndetCov: "dUndetCov", - etNoCov: "etNoCov", efNoCov: "efNoCov", eNoCov: "eNoCov", - ePartCov: "ePartCov", eUndetCov: " eUndetCov", - otNoCov: "otNoCov", ofNoCov: "ofNoCov", oNoCov: "oNoCov", - oPartCov: "oPartCov", - xBlock0: "xBlock0", xBlock1: "xBlock1", xBlock2: "xBlock2", - cPartCov: "cPartCov", - XsNoCov: "XsNoCov", XsPartCov: "XsPartCov", - XsNotCoverable: "XsNotCoverable", XsUndetCov: "XsUndetCov", - XotNoCov: "XotNoCov", XofNoCov: "XofNoCov", XoPartCov: "XoPartCov", - XoNoCov: "XoNoCov", - XcPartCov: "XcPartCov", - Xr0: "Xr0", Xr0c: "Xr0c", - aNoCov: "aNoCov", atNoCov: "atNoCov", acPartCov: "acPartCov"} +( + lNoCode, + lFullCov, + lx, + strictNote, + r0, + r0c, + lx0, + lx1, + lx2, + deviationNote, + lNoCov, + lPartCov, + lNotCoverable, + lUndetCov, + sNoCov, + sPartCov, + sNotCoverable, + sUndetCov, + dtAlways, + dfAlways, + dtNoCov, + dfNoCov, + dNoCov, + dPartCov, + dUndetCov, + etNoCov, + efNoCov, + eNoCov, + ePartCov, + eUndetCov, + otNoCov, + ofNoCov, + oNoCov, + oPartCov, + cPartCov, + XsNoCov, + XsPartCov, + XsNotCoverable, + XsUndetCov, + XotNoCov, + XofNoCov, + XoPartCov, + XoNoCov, + XcPartCov, + Xr0, + Xr0c, + aNoCov, + atNoCov, + acPartCov, + blockNote, + xBlock0, + xBlock1, + xBlock2, +) = range(53) + +NK_image = { + None: "None", + lNoCode: "lNoCode", + lNotCoverable: "lNotCoverable", + lUndetCov: "lUndetCov", + lFullCov: "lFullCov", + lNoCov: "lNoCov", + lPartCov: "lPartCov", + r0: "r0", + r0c: "r0c", + lx0: "lx0", + lx1: "lx1", + lx2: "lx2", + lx: "lx", + sNoCov: "sNoCov", + sPartCov: "sPartCov", + sNotCoverable: "sNotCoverable", + sUndetCov: "sUndetCov", + dtAlways: "dtAlways", + dfAlways: "dfAlways", + dtNoCov: "dtNoCov", + dfNoCov: "dfNoCov", + dNoCov: "dNoCov", + dPartCov: "dPartCov", + dUndetCov: "dUndetCov", + etNoCov: "etNoCov", + efNoCov: "efNoCov", + eNoCov: "eNoCov", + ePartCov: "ePartCov", + eUndetCov: " eUndetCov", + otNoCov: "otNoCov", + ofNoCov: "ofNoCov", + oNoCov: "oNoCov", + oPartCov: "oPartCov", + xBlock0: "xBlock0", + xBlock1: "xBlock1", + xBlock2: "xBlock2", + cPartCov: "cPartCov", + XsNoCov: "XsNoCov", + XsPartCov: "XsPartCov", + XsNotCoverable: "XsNotCoverable", + XsUndetCov: "XsUndetCov", + XotNoCov: "XotNoCov", + XofNoCov: "XofNoCov", + XoPartCov: "XoPartCov", + XoNoCov: "XoNoCov", + XcPartCov: "XcPartCov", + Xr0: "Xr0", + Xr0c: "Xr0c", + aNoCov: "aNoCov", + atNoCov: "atNoCov", + acPartCov: "acPartCov", +} # =============================== @@ -209,12 +276,21 @@ # Line notes (=xcov); the set of possible expectations matches the # set of possible emitted indications -elNoteKinds = (lNoCode, lNotCoverable, lUndetCov, lNoCov, lPartCov, lFullCov, - lx0, lx1, lx2) +elNoteKinds = ( + lNoCode, + lNotCoverable, + lUndetCov, + lNoCov, + lPartCov, + lFullCov, + lx0, + lx1, + lx2, +) xlTransparentKinds = (lx,) -xlNoteKinds = elNoteKinds+xlTransparentKinds +xlNoteKinds = elNoteKinds + xlTransparentKinds # Report notes (=report), which feature anti-expectations that # explicitely state expection of absence of emitted notes @@ -223,10 +299,18 @@ sNoteKinds = (sNoCov, sPartCov, sNotCoverable, sUndetCov) # DC indications -dNoteKinds = (dtNoCov, dfNoCov, dPartCov, dNoCov, dtAlways, dfAlways, dUndetCov) +dNoteKinds = ( + dtNoCov, + dfNoCov, + dPartCov, + dNoCov, + dtAlways, + dfAlways, + dUndetCov, +) # MCDC violations -cNoteKinds = (etNoCov, efNoCov, ePartCov, eNoCov, cPartCov, eUndetCov) +cNoteKinds = (etNoCov, efNoCov, ePartCov, eNoCov, cPartCov, eUndetCov) # Assertion violations aNoteKinds = (aNoCov, atNoCov, acPartCov) @@ -256,15 +340,18 @@ # kinds in the Emitted Report Notes set because we do want to handle them as # if they could be emitted and report them as unmatched. -erNoteKinds = sNoteKinds+dNoteKinds+cNoteKinds+xNoteKinds+tNoteKinds+XNoteKinds +erNoteKinds = ( + sNoteKinds + dNoteKinds + cNoteKinds + xNoteKinds + tNoteKinds + XNoteKinds +) erNoteKinds += aNoteKinds -xrNoteKinds = erNoteKinds+rAntiKinds+XrAntiKinds +xrNoteKinds = erNoteKinds + rAntiKinds + XrAntiKinds # ========================== # == Note Kind Predicates == # ========================== + def deviation_p(nkind): """ DEVIATION notes are those representing violations of a coverage mandate @@ -360,6 +447,7 @@ def transparent_p(nkind): # == Coverage Note Classes == # =========================== + class Block: """ Source regions to which expected coverage note instances belong. @@ -368,6 +456,7 @@ class Block: processed. Our purpose is only to associate notes with regions, for which an object id is enough + a parent link to represent nesting trees. """ + def __init__(self, parent): self.parent = parent @@ -394,7 +483,7 @@ def image(self): return "%s%s mark at %s" % ( NK_image[self.kind], "(from %s)" % self.stag.text if self.stag else "", - self.segment + self.segment, ) @@ -437,8 +526,8 @@ class Enote(Cnote): def __init__(self, kind, segment, source, stag=None): Cnote.__init__(self, kind) self.segment = segment # The line segment it designates - self.source = source # The corresponding source name - self.stag = stag # The separation tag it contains + self.source = source # The corresponding source name + self.stag = stag # The separation tag it contains self.discharges = None # The Xnote it discharges diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 782e37400..cc4cf14df 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -28,9 +28,13 @@ from SCOV.tctl import CAT, CovControl -from SCOV.instr import (add_dumper_lch_hook, default_dump_channel, - default_dump_trigger, xcov_convert_base64, - xcov_instrument) +from SCOV.instr import ( + add_dumper_lch_hook, + default_dump_channel, + default_dump_trigger, + xcov_convert_base64, + xcov_instrument, +) from SUITE.context import thistest from SUITE.control import language_info, runtime_info @@ -40,8 +44,13 @@ from SUITE.tutils import gprbuild, gprfor, xrun, xcov, frame from SUITE.tutils import gprbuild_cargs_with from SUITE.tutils import exename_for -from SUITE.tutils import (srctrace_pattern_for, srctracename_for, - tracename_for, ckptname_for, run_cov_program) +from SUITE.tutils import ( + srctrace_pattern_for, + srctracename_for, + tracename_for, + ckptname_for, + run_cov_program, +) from .cnotes import r0, r0c, xBlock0, xBlock1, lx0, lx1, lFullCov, lPartCov from .cnotes import Xr0, Xr0c @@ -125,7 +134,6 @@ class WdirControl: # for the TestCase implementation to decide. def __init__(self, wdbase, bdbase, subdirhint): - # WDBASE is the base prefix to use for testcase Working directory. # BDBASE is the base prefix to use for testcase Binary directory. # Fallback to WDBASE when not provided. @@ -166,14 +174,14 @@ def __init__(self, wdbase, bdbase, subdirhint): r_eln_for = { CAT.stmt: elNoteKinds, CAT.decision: elNoteKinds, - CAT.mcdc: elNoteKinds + CAT.mcdc: elNoteKinds, } # Relevant line expectations r_lxp_for = { CAT.stmt: r_eln_for[CAT.stmt], CAT.decision: r_eln_for[CAT.decision], - CAT.mcdc: r_eln_for[CAT.mcdc] + CAT.mcdc: r_eln_for[CAT.mcdc], } # The set of Report expectations we need to care about varies across @@ -190,10 +198,20 @@ def __init__(self, wdbase, bdbase, subdirhint): # Relevant emitted report notes r_ern_for = { CAT.stmt: tNoteKinds + xNoteKinds + sNoteKinds + XsNoteKinds, - CAT.decision: tNoteKinds + xNoteKinds + sNoteKinds + dNoteKinds + - XsNoteKinds + XoNoteKinds, - CAT.mcdc: tNoteKinds + xNoteKinds + sNoteKinds + dNoteKinds + cNoteKinds + - XsNoteKinds + XoNoteKinds + XcNoteKinds, + CAT.decision: tNoteKinds + + xNoteKinds + + sNoteKinds + + dNoteKinds + + XsNoteKinds + + XoNoteKinds, + CAT.mcdc: tNoteKinds + + xNoteKinds + + sNoteKinds + + dNoteKinds + + cNoteKinds + + XsNoteKinds + + XoNoteKinds + + XcNoteKinds, } # Relevant report expectations @@ -239,10 +257,9 @@ def __discharges(self, en, xn): # The emitted note needs to designate a sloc range within the # expected sloc range and separation tags, when any is expected, # must match. - return ( - en.segment.within(xn.segment) - and ((not xn.stag and not en.stag) - or (xn.stag and en.stag and en.stag.match(xn.stag))) + return en.segment.within(xn.segment) and ( + (not xn.stag and not en.stag) + or (xn.stag and en.stag and en.stag.match(xn.stag)) ) def try_sat_over(self, ekind, xn): @@ -362,8 +379,9 @@ def run(self, discharge_kdict): # notes processing below. for xkind in self.rxp: - self.process_xkind(xkind=xkind, - ekinds=discharge_kdict.get(xkind, [xkind])) + self.process_xkind( + xkind=xkind, ekinds=discharge_kdict.get(xkind, [xkind]) + ) # Then process the relevant emitted notes, complaining about those # that don't discharge any expectation as required, or that discharge @@ -424,7 +442,6 @@ def mode_tracename_for(self, pgm): raise NotImplementedError def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): - # The TESTCASE object that delegates the hard work to us :-) self.testcase = testcase @@ -455,14 +472,14 @@ def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): # Compute the gnatcov coverage specific extra options that we'll have # to pass. We need these early for Xnote expansions. - self.covoptions = ['--level=' + self.xcovlevel] + self.covoptions = ["--level=" + self.xcovlevel] if self.covctl: self.covoptions += to_list(self.covctl.covoptions) # Compute the list of test launch options strings that we need for # expectation CTL lines. - ctl_opts = ['--trace-mode=%s' % thistest.options.trace_mode] + ctl_opts = ["--trace-mode=%s" % thistest.options.trace_mode] self.extracargs = to_list(self.testcase.extracargs) @@ -479,12 +496,13 @@ def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): self.ernotes = {} xnotes = XnotesExpander( - xfile=xfile, xcov_level=xcovlevel, + xfile=xfile, + xcov_level=xcovlevel, ctl_opts=ctl_opts, ctl_cov=self.covoptions, ctl_cargs=gprbuild_cargs_with(thiscargs=self.extracargs), ctl_tags=thistest.options.tags, - ctl_cons=[thistest.options.consolidate] + ctl_cons=[thistest.options.consolidate], ) self.xlnotes = xnotes.xlnotes self.xrnotes = xnotes.xrnotes @@ -514,10 +532,9 @@ def is_subunit(self, soi): # be for a child unit. Check if we also have a line starting with # "separate" to disambiguate. - return ( - '-' in os.path.basename(soi) - and any(line.lstrip().lower().startswith('separate') - for line in lines_of(self.abspaths[soi])) + return "-" in os.path.basename(soi) and any( + line.lstrip().lower().startswith("separate") + for line in lines_of(self.abspaths[soi]) ) def units_of_interest(self): @@ -537,7 +554,7 @@ def units_of_interest(self): extension = ext(soi) if extension == ".adb" or extension == ".ads": if not self.is_subunit(soi): - uoi.add(no_ext(os.path.basename(soi)).replace('-', '.')) + uoi.add(no_ext(os.path.basename(soi)).replace("-", ".")) else: uoi.add(os.path.basename(soi)) @@ -552,12 +569,12 @@ def programs(self): def xcov_translation_for(self, source): """How a SOURCE reference in expectations translates as the basename of an =xcov annotated source file.""" - return source.replace('/', '-') + return source.replace("/", "-") def report_translation_for(self, source): """How a SOURCE reference in expectations translates in slocs found in =report outputs.""" - return os.sep.join(source.split('/')) + return os.sep.join(source.split("/")) def singletest(self): """Whether SELF instantiates a single test.""" @@ -583,10 +600,9 @@ def run(self): # interest, either requested from the command line or for specific # test purposes: - self.gprmode = ( - thistest.options.gprmode - or (self.covctl - and self.covctl.requires_gpr())) + self.gprmode = thistest.options.gprmode or ( + self.covctl and self.covctl.requires_gpr() + ) # Compute our GPR now, which we will need for build of single tests # and/or analysis later on if in gprmode. Turn inlining off for the @@ -598,16 +614,17 @@ def run(self): # an extra subdir level this_depth = thistest.depth + 1 if self.covctl else thistest.depth - self.gpr_obj_dir = 'obj' + self.gpr_obj_dir = "obj" self.gpr = gprfor( mains=self.drivers, prjid="gen", objdir=self.gpr_obj_dir, - srcdirs=["../"*n + "src" for n in range(1, this_depth)], + srcdirs=["../" * n + "src" for n in range(1, this_depth)], exedir=self.abdir(attribute=True), main_cargs="-fno-inline", deps=self.covctl.deps if self.covctl else [], - extra=self.covctl.gpr() if self.covctl else "") + extra=self.covctl.gpr() if self.covctl else "", + ) # For single tests (no consolidation), we first need to build, then # to execute to get an execution trace. All these we already have for @@ -705,15 +722,16 @@ def abdir_for(self, main, attribute=False): return self.adir_for(self.rbdir_for(main, attribute)) def main(self): - # For a single test, discriminate with driver basename. For a # consolidation test, discriminate with the expectation file basename. # We need the latter to allow multiple consolidation scenarii for a # testcase. - return (no_ext(self.drivers[0]) - if self.singletest() - else os.path.basename(no_ext(self.xfile))) + return ( + no_ext(self.drivers[0]) + if self.singletest() + else os.path.basename(no_ext(self.xfile)) + ) def rwdir(self): """Relative path to Working Directory for current instance.""" @@ -744,7 +762,7 @@ def run_test(self, main): if self.testcase.expect_failures: thistest.fail_if( unhandled_exception_in(contents_of(out_file)), - "exception raised while running '%s'." % main + "exception raised while running '%s'." % main, ) def gen_one_xcov_report(self, inputs, format, options=""): @@ -761,17 +779,20 @@ def gen_one_xcov_report(self, inputs, format, options=""): # options which might be absent from the tool qualified interface # descriptions. - covargs = (['--annotate=' + format, inputs] - + self.covoptions + to_list(options)) + covargs = ( + ["--annotate=" + format, inputs] + + self.covoptions + + to_list(options) + ) if self.gprmode: - covargs.append('--output-dir=.') + covargs.append("--output-dir=.") # Run, latching standard output in a file so we can check contents on # return. ofile = format + ".out" - xcov(args=['coverage'] + covargs, out=ofile) + xcov(args=["coverage"] + covargs, out=ofile) # Standard output might typically contain labeling warnings issued # by the static analysis phase, or error messages issued when a trace @@ -782,16 +803,15 @@ def gen_one_xcov_report(self, inputs, format, options=""): thistest.fail_if( os.path.getsize(ofile) > 0, - "xcov standard output not empty (%s):\n--\n%s" % ( - ofile, contents_of(ofile) - ) + "xcov standard output not empty (%s):\n--\n%s" + % (ofile, contents_of(ofile)), ) def force_xcov_report(self, source): - filename = self.xcov_translation_for(source) + '.xcov' + filename = self.xcov_translation_for(source) + ".xcov" if not os.path.exists(filename): - with open(filename, 'w') as report: + with open(filename, "w") as report: report.write("dummy xcov report") def gen_xcov_reports(self): @@ -806,7 +826,7 @@ def gen_xcov_reports(self): # produce a checkpoint for possible future consolidation if the # current execution mode calls for it: - checkpoints = thistest.options.consolidate == 'checkpoints' + checkpoints = thistest.options.consolidate == "checkpoints" single_driver = no_ext(self.drivers[0]) if self.singletest() else None @@ -826,27 +846,36 @@ def gen_xcov_reports(self): inputs = "%s@%s" % ( input_opt, - list_to_file([input_fn(os.path.join(self.awdir_for(pgm), pgm)) - for pgm in self.programs()], - "inputs.list") + list_to_file( + [ + input_fn(os.path.join(self.awdir_for(pgm), pgm)) + for pgm in self.programs() + ], + "inputs.list", + ), ) # Determine what command line options we'll pass to designate units of # interest and maybe produce a coverage checkpoint. We don't need and # don't want to pass SCO options when using checkpoints as inputs. - sco_options = ([] if use_checkpoint_inputs - else self.coverage_sco_options()) + sco_options = ( + [] if use_checkpoint_inputs else self.coverage_sco_options() + ) save_checkpoint_options = ( ["--save-checkpoint=%s" % ckptname_for(single_driver)] - if single_driver and checkpoints else []) + if single_driver and checkpoints + else [] + ) # Now produce the --annotate=report format: self.gen_one_xcov_report( - inputs, format="report", - options=sco_options + save_checkpoint_options + ['-o', 'test.rep']) + inputs, + format="report", + options=sco_options + save_checkpoint_options + ["-o", "test.rep"], + ) # Then an alternate .xcov output format, unless we are performing a # qualification run, for which that format isn't appropriate. No need @@ -865,13 +894,13 @@ def check_unexpected_reports(self): for s in self.ernotes: thistest.fail_if( self.covctl.unexpected(s), - "report note found for %s, not in expected list" % s + "report note found for %s, not in expected list" % s, ) for s in ls("*.xcov"): thistest.fail_if( self.covctl.unexpected(s.rstrip(".xcov")), - "%s report found, for source not in expected list" % s + "%s report found, for source not in expected list" % s, ) def check_expectations(self): @@ -930,7 +959,6 @@ def check_expectations(self): CAT.stmt: 1, CAT.decision: 2, CAT.mcdc: 3, - # Context levels "stmt": 1, "stmt+decision": 2, @@ -957,12 +985,14 @@ def check_expectations(self): strictest_cat_for = { "stmt": CAT.stmt, "stmt+decision": CAT.decision, - "stmt+mcdc": CAT.mcdc + "stmt+mcdc": CAT.mcdc, } - relevance_cat = (self.testcase.category - if self.testcase.category - else strictest_cat_for[self.xcovlevel]) + relevance_cat = ( + self.testcase.category + if self.testcase.category + else strictest_cat_for[self.xcovlevel] + ) # Setup our report and line discharging configurations (kinds of # emitted notes that are allowed to discharge other kinds of expected @@ -970,32 +1000,44 @@ def check_expectations(self): # =report outputs, stricter_level micro relaxations first: - r_discharge_kdict = { - # let an emitted xBlock1 discharge an xBlock0 expectation, as an - # extra exempted violations are most likely irrelevant for the - # category - xBlock0: [xBlock0, xBlock1]} if stricter_level else {} + r_discharge_kdict = ( + { + # let an emitted xBlock1 discharge an xBlock0 expectation, as an + # extra exempted violations are most likely irrelevant for the + # category + xBlock0: [xBlock0, xBlock1] + } + if stricter_level + else {} + ) # Then augment with what is allowed to hit "0" or "0c" expectation # statements: - r_discharge_kdict.update({r0: r_ern_for[relevance_cat], - r0c: r_ern_for[relevance_cat], - Xr0: r_ern_for[relevance_cat], - Xr0c: r_ern_for[relevance_cat]}) + r_discharge_kdict.update( + { + r0: r_ern_for[relevance_cat], + r0c: r_ern_for[relevance_cat], + Xr0: r_ern_for[relevance_cat], + Xr0c: r_ern_for[relevance_cat], + } + ) # =xcov outputs, stricter_level micro relaxations only: - l_discharge_kdict = { - # an emitted l! discharge an expected l+, when the l! is most - # likely caused by irrelevant violations for the category - lFullCov: [lFullCov, lPartCov], - - # an emitted lx1 discharge an lx0 expectation, when the extra - # exempted violations are most likely caused by the level extra - # strictness, hence irrelevant for the category - lx0: [lx0, lx1] - } if stricter_level else {} + l_discharge_kdict = ( + { + # an emitted l! discharge an expected l+, when the l! is most + # likely caused by irrelevant violations for the category + lFullCov: [lFullCov, lPartCov], + # an emitted lx1 discharge an lx0 expectation, when the extra + # exempted violations are most likely caused by the level extra + # strictness, hence irrelevant for the category + lx0: [lx0, lx1], + } + if stricter_level + else {} + ) # Now process source by source, skipping those for which no report # is expected when the list happens to be specified. @@ -1008,18 +1050,20 @@ def check_expectations(self): for source in self.sources_of_interest(): if not self.covctl or self.covctl.expected(source): self.check_expectations_over( - source=source, relevance_cat=relevance_cat, + source=source, + relevance_cat=relevance_cat, r_discharge_kdict=r_discharge_kdict, - l_discharge_kdict=l_discharge_kdict + l_discharge_kdict=l_discharge_kdict, ) - def check_expectations_over(self, source, relevance_cat, - r_discharge_kdict, l_discharge_kdict): + def check_expectations_over( + self, source, relevance_cat, r_discharge_kdict, l_discharge_kdict + ): """Process expectations for a particular SOURCE, comparing expected coverage marks against what is found in the xcov reports for this source.""" - frame("Processing UX for %s" % source, post=0, char='~').display() + frame("Processing UX for %s" % source, post=0, char="~").display() # Source names in expectations might still contain path indications # when they reach here, to indicate that the path components are @@ -1030,11 +1074,11 @@ def check_expectations_over(self, source, relevance_cat, strans = self.report_translation_for(source) _Xchecker( - report='test.rep', + report="test.rep", xdict=self.xrnotes.get(source), rxp=r_rxp_for[relevance_cat], edict=self.ernotes.get(strans, KnoteDict(erNoteKinds)), - ren=r_ern_for[relevance_cat] + ren=r_ern_for[relevance_cat], ).run(r_discharge_kdict) # Line notes checks, meaningless if we're in qualification mode @@ -1044,24 +1088,26 @@ def check_expectations_over(self, source, relevance_cat, strans = self.xcov_translation_for(source) _Xchecker( - report=strans+'.xcov', + report=strans + ".xcov", xdict=self.xlnotes.get(source), rxp=r_lxp_for[relevance_cat], edict=self.elnotes.get(strans, KnoteDict(elNoteKinds)), - ren=r_eln_for[relevance_cat] + ren=r_eln_for[relevance_cat], ).run(l_discharge_kdict) def log(self): frame( - "%s/ %s, %s\n%s coverage with %s" % ( + "%s/ %s, %s\n%s coverage with %s" + % ( os.path.relpath(os.getcwd(), thistest.homedir), [no_ext(main) for main in self.drivers], self.xfile, self.testcase.category.name - if self.testcase.category else "generic", - ' '.join(self.covoptions) + if self.testcase.category + else "generic", + " ".join(self.covoptions), ), - char='*' + char="*", ).display() def to_workdir(self, wdir): @@ -1123,9 +1169,13 @@ def coverage_sco_options(self): # Fallback to --scos/--sid with a list of files we compute here: else: - return ["%s=@%s" % ( - self.mode_scofiles_switch(), - list_to_file(self._scofiles_list(), "scos.list"))] + return [ + "%s=@%s" + % ( + self.mode_scofiles_switch(), + list_to_file(self._scofiles_list(), "scos.list"), + ) + ] def _locate_scofile(self, source): """Return the fullpath of the ali file corresponding to the given @@ -1143,7 +1193,7 @@ def _locate_scofile(self, source): # all identical, and they should be for typical situations where the # same sources were exercised by multiple drivers: - lpath = os.path.join('obj', self.mode_scofile_for(source)) + lpath = os.path.join("obj", self.mode_scofile_for(source)) for main in self.drivers: tloc = os.path.join(self.abdir_for(no_ext(main)), lpath) if os.path.exists(tloc): @@ -1166,10 +1216,13 @@ def _scofiles_list(self): # package. We make our result a set to prevent duplicates and xcov # warnings later on. - return {scof - for scof in (self._locate_scofile(soi) - for soi in self.sources_of_interest()) - if scof} + return { + scof + for scof in ( + self._locate_scofile(soi) for soi in self.sources_of_interest() + ) + if scof + } def wdbase_for(self, covlevel): """ @@ -1197,7 +1250,7 @@ def xcovlevel_for(self, wdname): full name of the assertion level is enabled. """ res = "stmt" - wdbase = wdname.split('_')[0] + wdbase = wdname.split("_")[0] for lvl in ["decision", "mcdc", "uc_mcdc"]: if wdbase[0] == lvl[0]: @@ -1236,12 +1289,13 @@ class SCOV_helper_bin_traces(SCOV_helper): def mode_build(self): gprbuild( - self.gpr, extracargs=self.extracargs, - gargs=self.common_build_gargs()) + self.gpr, + extracargs=self.extracargs, + gargs=self.common_build_gargs(), + ) def mode_execute(self, main): - - out_file = 'xrun_{}.out'.format(main) + out_file = "xrun_{}.out".format(main) # Feed xcov run with full path (absolute dir) of the program so we # can directly get to the binary from the trace when reading it from @@ -1254,9 +1308,12 @@ def mode_execute(self, main): # failures (such as harness tests), assuming that they will perform # further checks that are bound to fail if the execution doesn't # proceed as expected somehow (e.g. not producing a trace). - xrun([main_path, "--level=%s" % self.xcovlevel] + - self.coverage_sco_options(), - out=out_file, register_failure=not self.testcase.expect_failures) + xrun( + [main_path, "--level=%s" % self.xcovlevel] + + self.coverage_sco_options(), + out=out_file, + register_failure=not self.testcase.expect_failures, + ) return out_file @@ -1309,7 +1366,6 @@ class SCOV_helper_src_traces(SCOV_helper): # binary traces. def mode_build(self): - # We first need to instrument, with proper selection of the units of # interest. Expect we are to provide this through a project file as # we have no LI file at hand: @@ -1332,12 +1388,13 @@ def mode_build(self): units=self.covctl.gprsw.units, no_subprojects=self.covctl.gprsw.no_subprojects, xvars=self.covctl.gprsw.xvars, - subdirs=subdirs) + subdirs=subdirs, + ) else: subdirs = None instrument_gprsw = GPRswitches(root_project=self.gpr) - out = 'xinstr.out' + out = "xinstr.out" xcov_instrument( covlevel=self.xcovlevel, extra_args=to_list(self.covctl.covoptions) if self.covctl else [], @@ -1346,7 +1403,8 @@ def mode_build(self): gprsw=instrument_gprsw, gpr_obj_dir=self.gpr_obj_dir, out=out, - tolerate_messages=self.testcase.tolerate_messages) + tolerate_messages=self.testcase.tolerate_messages, + ) # When exception propagation is not available, a test ending with an # unhandled exception goes straight to the last_chance_handler from @@ -1355,20 +1413,23 @@ def mode_build(self): # a last chance handler entry hook to dump the buffers at that point # instead. - if (self.dump_trigger == 'main-end' - and not runtime_info().has_exception_propagation): + if ( + self.dump_trigger == "main-end" + and not runtime_info().has_exception_propagation + ): # The only tests with multiple drivers are consolidation ones, # which compute consolidated coverage reports from data obtained # in previously executed tests (trace files or checkpoints). These # tests are not built, so we can assume here that there is only one # driver to build. assert len(self.drivers) == 1 - if (language_info(self.drivers[0]).name == "Ada"): + if language_info(self.drivers[0]).name == "Ada": add_dumper_lch_hook( project=instrument_gprsw.root_project, obj_dir=self.gpr_obj_dir, subdirs=subdirs, - main_unit=no_ext(self.drivers[0])) + main_unit=no_ext(self.drivers[0]), + ) # Standard output might contain warnings indicating instrumentation # issues. This should not happen, so simply fail as soon as the output @@ -1376,34 +1437,39 @@ def mode_build(self): if not self.testcase.tolerate_messages: thistest.fail_if( os.path.getsize(out) > 0, - 'xcov instrument standard output not empty ({}):' - '\n--' - '\n{}'.format(out, contents_of(out))) + "xcov instrument standard output not empty ({}):" + "\n--" + "\n{}".format(out, contents_of(out)), + ) # Now we can build, instructing gprbuild to fetch the instrumented # sources in their dedicated subdir: gprbuild( - self.gpr, extracargs=self.extracargs, - gargs=self.common_build_gargs() + ['--src-subdirs=gnatcov-instr']) + self.gpr, + extracargs=self.extracargs, + gargs=self.common_build_gargs() + ["--src-subdirs=gnatcov-instr"], + ) def mode_execute(self, main): register_failure = not self.testcase.expect_failures # Run the program itself - out_file = 'cmdrun_{}.out'.format(main) + out_file = "cmdrun_{}.out".format(main) main_path = os.path.join(self.abdir_for(main), exename_for(main)) - run_cov_program(main_path, out=out_file, - register_failure=register_failure) + run_cov_program( + main_path, out=out_file, register_failure=register_failure + ) # If the dump channel just writes text on stdout, extract traces from # it. - if self.dump_channel == 'base64-stdout': + if self.dump_channel == "base64-stdout": # The mode_tracename_for method works only after the trace file has # been created: create a trace file that srctracename_for (called # in mode_tracename_for) will pick up. trace_file = srctrace_pattern_for(main).replace("*", "unique") - xcov_convert_base64(out_file, trace_file, - register_failure=register_failure) + xcov_convert_base64( + out_file, trace_file, register_failure=register_failure + ) return out_file diff --git a/testsuite/SCOV/internals/lnexpanders.py b/testsuite/SCOV/internals/lnexpanders.py index fa9ff44ac..27cbccc04 100644 --- a/testsuite/SCOV/internals/lnexpanders.py +++ b/testsuite/SCOV/internals/lnexpanders.py @@ -10,34 +10,54 @@ from e3.fs import ls -from .cnotes import (KnoteDict, Enote, elNoteKinds, lNoCode, lFullCov, - lPartCov, lNoCov, lNotCoverable, lUndetCov, lx0, lx1, - lx2) +from .cnotes import ( + KnoteDict, + Enote, + elNoteKinds, + lNoCode, + lFullCov, + lPartCov, + lNoCov, + lNotCoverable, + lUndetCov, + lx0, + lx1, + lx2, +) from .segments import Line from .tfiles import Tfile class LnotesExpander: - - NK_for = {'.': lNoCode, '0': lNotCoverable, '?': lUndetCov, - '+': lFullCov, '-': lNoCov, '!': lPartCov, - '#': lx0, '*': lx1, '@': lx2} + NK_for = { + ".": lNoCode, + "0": lNotCoverable, + "?": lUndetCov, + "+": lFullCov, + "-": lNoCov, + "!": lPartCov, + "#": lx0, + "*": lx1, + "@": lx2, + } def process_tline(self, tline): - m = re.match(r'\s*([0-9]+) (.):', tline.text) + m = re.match(r"\s*([0-9]+) (.):", tline.text) if m: self.elnotes[self.source].register( - Enote(kind=self.NK_for[m.group(2)], - segment=Line(int(m.group(1))), - source=self.source)) + Enote( + kind=self.NK_for[m.group(2)], + segment=Line(int(m.group(1))), + source=self.source, + ) + ) def listing_to_enotes(self, dotxcov): - self.source = dotxcov.rsplit('.', 1)[0] + self.source = dotxcov.rsplit(".", 1)[0] self.elnotes[self.source] = KnoteDict(elNoteKinds) Tfile(filename=dotxcov, process=self.process_tline) def __init__(self, dotxcov_pattern): - # xcov --annotate=xcov produces a set of .xcov annotated unit sources, # each featuring a synthetic note per line. diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index 99f82a18b..d7414d36a 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -9,12 +9,41 @@ from SUITE.context import thistest from .cnotes import ( - xBlock0, xBlock1, sNoCov, sPartCov, sNotCoverable, dfAlways, dtAlways, - dfNoCov, dtNoCov, dNoCov, dPartCov, efNoCov, etNoCov, eNoCov, ePartCov, - cPartCov, aNoCov, atNoCov, acPartCov, Enote, KnoteDict, erNoteKinds, - sUndetCov, dUndetCov, eUndetCov, xBlock2, XsNoCov, XsPartCov, - XsNotCoverable, XsUndetCov, XotNoCov, XofNoCov, XoPartCov, XoNoCov, - XcPartCov + xBlock0, + xBlock1, + sNoCov, + sPartCov, + sNotCoverable, + dfAlways, + dtAlways, + dfNoCov, + dtNoCov, + dNoCov, + dPartCov, + efNoCov, + etNoCov, + eNoCov, + ePartCov, + cPartCov, + aNoCov, + atNoCov, + acPartCov, + Enote, + KnoteDict, + erNoteKinds, + sUndetCov, + dUndetCov, + eUndetCov, + xBlock2, + XsNoCov, + XsPartCov, + XsNotCoverable, + XsUndetCov, + XotNoCov, + XofNoCov, + XoPartCov, + XoNoCov, + XcPartCov, ) from .segments import Sloc, Sloc_from_match from .stags import Stag_from @@ -55,13 +84,14 @@ # 2 DECISION violations. <- mapped to an internal "contents # <- block" representation. + class Rdiagline: """ Abstract diagnostic line, a-la "p.adb:8:4 statement not executed". This is a general Sloc followed by some diagnostic text. """ - def __init__(self, sloc, diag): + def __init__(self, sloc, diag): # SLOC object and DIAGnostic text self.sloc = sloc @@ -82,8 +112,9 @@ def __init__(self, sloc, diag): def Rdiagline_from(text): p = re.match(Rdiagline.re, text) - return Rdiagline(sloc=Sloc_from_match(p), - diag=p.group("diag")) if p else None + return ( + Rdiagline(sloc=Sloc_from_match(p), diag=p.group("diag")) if p else None + ) class Rblock: @@ -93,7 +124,6 @@ class Rblock: """ def __init__(self, name, re_start, re_end): - # NAME holds the text with which this block will be referred to in # error messages. RE_START/RE_END are regexps which tells whether a # line of text matches the expected header line for this block: @@ -141,10 +171,11 @@ def check(self): thistest.fail_if( n_starts != n_ends, "(%s report section): %d starts != %d ends" - % (self.name, n_starts, n_ends)) + % (self.name, n_starts, n_ends), + ) def value(self, count): - return (0 if count == "No" else int(count)) + return 0 if count == "No" else int(count) # --------------------------- @@ -155,12 +186,12 @@ def value(self, count): # numbering at the start of the header title, possibly preceded by decorative # characters. + def re_block_number(pre, ndigits): return pre + r"[0-9]\." * ndigits + " " class Rchapter(Rblock): - # Chapter titles are characterized by a single digit number preceded by # two decorative characters, for example: # @@ -168,22 +199,26 @@ class Rchapter(Rblock): def __init__(self, re_start, re_end): Rblock.__init__( - self, name=re_start, + self, + name=re_start, re_start=re_block_number(pre=".. ", ndigits=1) + re_start, - re_end=re_end) + re_end=re_end, + ) class Rsection(Rblock): - # Section titles are characterized by a single digit number preceded by # two decorative characters, for example: # # 2.1. STATEMENT COVERAGE VIOLATIONS def __init__(self, re_start, re_end): - Rblock.__init__(self, name=re_start, - re_start=re_block_number(pre="", ndigits=2) + re_start, - re_end=re_end) + Rblock.__init__( + self, + name=re_start, + re_start=re_block_number(pre="", ndigits=2) + re_start, + re_end=re_end, + ) # -------------------------------- @@ -194,10 +229,9 @@ def __init__(self, re_start, re_end): # messages), which all contain a list of emitted notes + a counter of the # number of such notes at the end. Some are sections, some are chapters. -class Nblock(Rblock): +class Nblock(Rblock): def __init__(self, re_notes): - self.re_notes = re_notes # Remember the set of notes that we found in this block, so @@ -218,9 +252,12 @@ def try_parse_enote(self, rline): # to sort out the note kind and separation tag from the diagnostic # text - enote = Enote(segment=dline.sloc.section, - source=dline.sloc.filename, - kind=None, stag=None) + enote = Enote( + segment=dline.sloc.section, + source=dline.sloc.filename, + kind=None, + stag=None, + ) # Fetch and remove a possible separation tag from the diganostic # text. Removal is useful to facilitate matching of other parts, hence @@ -231,9 +268,11 @@ def __stag_replacement_for(m): enote.stag = Stag_from(m.group(1), True) return "" - this_diag = re.sub(pattern=r" \(from (.*)\)", - repl=__stag_replacement_for, - string=dline.diag) + this_diag = re.sub( + pattern=r" \(from (.*)\)", + repl=__stag_replacement_for, + string=dline.diag, + ) # Then determine the note kind from the remaining contents @@ -242,9 +281,11 @@ def __stag_replacement_for(m): return self.check_enote(this_diag, enote) def report_unexpected_enote(self, rline): - thistest.failed("(%s report section) '%s' does not" - " correspond to any expected violation note" - % (self.name, rline.rstrip('\n'))) + thistest.failed( + "(%s report section) '%s' does not" + " correspond to any expected violation note" + % (self.name, rline.rstrip("\n")) + ) def check_enote(self, rline, enote): if enote.kind is None: @@ -264,7 +305,7 @@ def validate_ecount(self, count): thistest.fail_if( count != self.ecount, "(%s report section) recognized %d notes != summary (%d)\n" - % (self.name, self.ecount, count) + % (self.name, self.ecount, count), ) def ends_on(self, rline): @@ -289,14 +330,12 @@ def nkind_for(self, rline): class Nsection(Nblock, Rsection): - def __init__(self, re_start, re_end, re_notes): Rsection.__init__(self, re_start=re_start, re_end=re_end) Nblock.__init__(self, re_notes=re_notes) class Nchapter(Nblock, Rchapter): - def __init__(self, re_start, re_end, re_notes): Rchapter.__init__(self, re_start=re_start, re_end=re_end) Nblock.__init__(self, re_notes=re_notes) @@ -307,13 +346,17 @@ def __init__(self, re_start, re_end, re_notes): # Leaf specializations, a set of which will be instantiated for report # processing. + class VIOsection(Nsection): """Coverage Violations section.""" def __init__(self, re_start, re_notes): - Nsection.__init__(self, re_start=re_start, - re_end=r"(No|\d+) violation[s]*\.$", - re_notes=re_notes) + Nsection.__init__( + self, + re_start=re_start, + re_end=r"(No|\d+) violation[s]*\.$", + re_notes=re_notes, + ) def re_summary(self): return r"(No|\d+).* %s violation[s]*\.$" % self.name.split()[0] @@ -321,13 +364,16 @@ def re_summary(self): class OERsection(Nsection): """Other errors section.""" + def __init__(self, re_start): - Nsection.__init__(self, re_start=re_start, - re_end=r"(No|\d+) message[s]*\.$", - re_notes=None) + Nsection.__init__( + self, + re_start=re_start, + re_end=r"(No|\d+) message[s]*\.$", + re_notes=None, + ) def nkind_for(self, rline): - # Messages in this section are always unexpected and should trigger # test failure. Just tell we don't know how to bind them on any sort # of expected note kind, and let the generic engine do the rest. @@ -339,28 +385,31 @@ class XREchapter(Nchapter): """Exemptions Regions chapter.""" def __init__(self, re_start, re_notes, exempted_notes): - # The list of notes acceptable for an exempted violation self.exempted_notes = exempted_notes # The number of exempted violations found self.ecount_exempted = 0 - re_end = (r"(No|\d+) exempted region[s]*, " - r"(No|\d+) exempted violation[s]*\.$") + re_end = ( + r"(No|\d+) exempted region[s]*, " + r"(No|\d+) exempted violation[s]*\.$" + ) - Nchapter.__init__(self, re_start=re_start, - re_end=re_end, - re_notes=re_notes) + Nchapter.__init__( + self, re_start=re_start, re_end=re_end, re_notes=re_notes + ) def __check_summary_count(self, sec, sum_count, sec_count): thistest.fail_if( sum_count != sec_count, - "summary count %d != section count %d for %s" % ( - sum_count, sec_count, sec.name)) + "summary count %d != section count %d for %s" + % (sum_count, sec_count, sec.name), + ) thistest.fail_if( len(sec.start_hits) != 1, - "summary found for section starts != 1 (%s)" % sec.name) + "summary found for section starts != 1 (%s)" % sec.name, + ) def check_exempted_summary(self, sec, p): # The emitted notes of exempted violations are logged in self.enotes @@ -370,34 +419,35 @@ def check_exempted_summary(self, sec, p): # separatly. ecount = len(self.enotes) - self.ecount_exempted - self.__check_summary_count(sec, - self.value(p.group(1)), - ecount) + self.__check_summary_count(sec, self.value(p.group(1)), ecount) - self.__check_summary_count(sec, - self.value(p.group(2)), - self.ecount_exempted) + self.__check_summary_count( + sec, self.value(p.group(2)), self.ecount_exempted + ) def __validate(self, actual_count, count, element_counted): thistest.fail_if( actual_count != count, "(%s report section) recognized %d notes != summary (%d)" - "for (%s)\n" - % (self.name, actual_count, count, element_counted) + "for (%s)\n" % (self.name, actual_count, count, element_counted), ) def ends_on(self, rline): p = Rblock.ends_on(self, rline) if p: # Validate the number of exempted regions - self.__validate(len(self.enotes) - self.ecount_exempted, - self.value(p.group(1)), - "exempted regions") + self.__validate( + len(self.enotes) - self.ecount_exempted, + self.value(p.group(1)), + "exempted regions", + ) # Validate the total number of exempted violations - self.__validate(self.ecount_exempted, - self.value(p.group(2)), - "exempted violations") + self.__validate( + self.ecount_exempted, + self.value(p.group(2)), + "exempted violations", + ) return p @@ -416,10 +466,14 @@ def check_enote(self, rline, enote): class NCIchapter(Nchapter): """Non-coverable Items chapter.""" + def __init__(self, re_start, re_notes): - Nchapter.__init__(self, re_start=re_start, - re_end=r"(No|\d+) exclusion[s]*\.$", - re_notes=re_notes) + Nchapter.__init__( + self, + re_start=re_start, + re_end=r"(No|\d+) exclusion[s]*\.$", + re_notes=re_notes, + ) def re_summary(self): return r"(No|\d+) coverage exclusion[s]*\.$" @@ -427,10 +481,14 @@ def re_summary(self): class UCIchapter(Nchapter): """Undetermined Coverage Items chapter.""" + def __init__(self, re_start, re_notes): - Nchapter.__init__(self, re_start=re_start, - re_end=r"(\d+) undetermined coverage item[s]*\.$", - re_notes=re_notes) + Nchapter.__init__( + self, + re_start=re_start, + re_end=r"(\d+) undetermined coverage item[s]*\.$", + re_notes=re_notes, + ) def re_summary(self): return r"(\d+) undetermined coverage item[s]*\.$" @@ -438,9 +496,11 @@ def re_summary(self): class SMRchapter(Rchapter): """Analysis Summary chapter.""" + def __init__(self, re_start, skeys): - Rchapter.__init__(self, re_start=re_start, - re_end=".. END OF REPORT ..$") + Rchapter.__init__( + self, re_start=re_start, re_end=".. END OF REPORT ..$" + ) self.skeys = skeys self.checked = {sec: False for sec in skeys} @@ -451,18 +511,20 @@ def try_match(self, sec, rline): # summary verification has to be done on the number of regions and # the number of violations - if sec.name == 'EXEMPTED REGIONS': + if sec.name == "EXEMPTED REGIONS": sec.check_exempted_summary(sec, p) else: sum_count = self.value(p.group(1)) sec_count = sec.ecount thistest.fail_if( sum_count != sec_count, - "summary count %d != section count %d for %s" % ( - sum_count, sec_count, sec.name)) + "summary count %d != section count %d for %s" + % (sum_count, sec_count, sec.name), + ) thistest.fail_if( len(sec.start_hits) != 1, - "summary found for section starts != 1 (%s)" % sec.name) + "summary found for section starts != 1 (%s)" % sec.name, + ) self.checked[sec] = True def try_parse(self, rline): @@ -477,7 +539,8 @@ def check(self): for sec in self.skeys: thistest.fail_if( len(sec.start_hits) > 0 and not self.checked[sec], - "summary count check missing for section %s" % sec.name) + "summary count check missing for section %s" % sec.name, + ) # At this point, we have the class hierarchy involved in modeling the @@ -500,12 +563,14 @@ def check(self): # We now add grab bags specializations aimed at catching # unexpected blocks: + class Ublock(Rblock): def check(self): thistest.fail_if( len(self.start_hits) > 0, "Unexpected headers caught by %s:\n%s" - % (self.__class__.__name__, ''.join(self.start_hits))) + % (self.__class__.__name__, "".join(self.start_hits)), + ) class Uchapter(Ublock, Rchapter): @@ -523,6 +588,7 @@ def __init__(self): # Just claim immediate end. Everything will be ignored until # the next section or block starter. + class Tchapter(Rchapter): def __init__(self, re_start): Rchapter.__init__(self, re_start=re_start, re_end=".") @@ -531,9 +597,9 @@ def __init__(self, re_start): # Now ready to materialize and wrapup the whole set of blocks needed to # process a report: + class RblockSet: def __init__(self): - # We need a list of all the blocks to drive the report parsing # process, and a list of all the note blocks to setup the analysis # summary checker: @@ -545,29 +611,36 @@ def __init__(self): stmt_notes = { "statement not executed": sNoCov, - "multiple statements on line": sPartCov} + "multiple statements on line": sPartCov, + } self.noteblocks.append( - VIOsection(re_start="STMT COVERAGE", re_notes=stmt_notes)) + VIOsection(re_start="STMT COVERAGE", re_notes=stmt_notes) + ) dc_notes = { "decision outcome FALSE never": dfNoCov, "decision outcome TRUE never": dtNoCov, "decision never evaluated": dNoCov, - "decision not exercised in both directions": dPartCov} + "decision not exercised in both directions": dPartCov, + } self.noteblocks.append( - VIOsection(re_start="DECISION COVERAGE", re_notes=dc_notes)) + VIOsection(re_start="DECISION COVERAGE", re_notes=dc_notes) + ) mcdc_notes = { "decision outcome FALSE never": efNoCov, "decision outcome TRUE never": etNoCov, "decision never evaluated": eNoCov, "decision not exercised in both directions": ePartCov, - "condition has no independent influence pair": cPartCov} + "condition has no independent influence pair": cPartCov, + } self.noteblocks.append( - VIOsection(re_start="UC_MCDC COVERAGE", re_notes=mcdc_notes)) + VIOsection(re_start="UC_MCDC COVERAGE", re_notes=mcdc_notes) + ) self.noteblocks.append( - VIOsection(re_start="MCDC COVERAGE", re_notes=mcdc_notes)) + VIOsection(re_start="MCDC COVERAGE", re_notes=mcdc_notes) + ) # Assertion coverage @@ -576,23 +649,27 @@ def __init__(self): "contract expression never evaluated": aNoCov, } self.noteblocks.append( - VIOsection(re_start="ATC COVERAGE", re_notes=atc_notes)) + VIOsection(re_start="ATC COVERAGE", re_notes=atc_notes) + ) atcc_notes = { "condition was never evaluated during an evaluation of the " "decision to True": acPartCov } self.noteblocks.append( - VIOsection(re_start="ATCC COVERAGE", re_notes=atcc_notes)) + VIOsection(re_start="ATCC COVERAGE", re_notes=atcc_notes) + ) # Non coverable items nc_notes = { "statement has no object code": sNotCoverable, "decision is always TRUE": dtAlways, - "decision is always FALSE": dfAlways} + "decision is always FALSE": dfAlways, + } self.noteblocks.append( - NCIchapter(re_start="NON COVERABLE ITEMS", re_notes=nc_notes)) + NCIchapter(re_start="NON COVERABLE ITEMS", re_notes=nc_notes) + ) # Undetermined coverage items @@ -600,13 +677,14 @@ def __init__(self): "statement was not instrumented": sUndetCov, "decision was not instrumented" " for decision coverage": dUndetCov, - "decision was not instrumented" - " for MC/DC coverage": eUndetCov + "decision was not instrumented" " for MC/DC coverage": eUndetCov, } self.noteblocks.append( - UCIchapter(re_start="UNDETERMINED COVERAGE ITEMS", - re_notes=ni_notes)) + UCIchapter( + re_start="UNDETERMINED COVERAGE ITEMS", re_notes=ni_notes + ) + ) # Exempted regions @@ -614,7 +692,7 @@ def __init__(self): "0 exempted violation": xBlock0, r"[1-9]\d* exempted violation": xBlock1, r"\d+ exempted violations?; [1-9]\d+ exempted undetermined " - r"coverage items?": xBlock2 + r"coverage items?": xBlock2, } # Exempted violations @@ -628,13 +706,16 @@ def __init__(self): "decision outcome TRUE never": XotNoCov, "decision outcome never evaluated": XoNoCov, "decision not exercised in both directions": XoPartCov, - "condition has no independent influence pair": XcPartCov + "condition has no independent influence pair": XcPartCov, } self.noteblocks.append( - XREchapter(re_start="EXEMPTED REGIONS", - re_notes=xr_notes | Xr_notes, - exempted_notes=Xr_notes)) + XREchapter( + re_start="EXEMPTED REGIONS", + re_notes=xr_notes | Xr_notes, + exempted_notes=Xr_notes, + ) + ) # Other note blocks @@ -647,15 +728,18 @@ def __init__(self): # Analysis Summary chapter self.allblocks.append( - SMRchapter(re_start="ANALYSIS SUMMARY", - skeys={s: s.re_summary() for s in self.noteblocks})) + SMRchapter( + re_start="ANALYSIS SUMMARY", + skeys={s: s.re_summary() for s in self.noteblocks}, + ) + ) # Transparent chapters + self.allblocks.append(Tchapter(re_start="ASSESSMENT CONTEXT")) self.allblocks.append( - Tchapter(re_start="ASSESSMENT CONTEXT")) - self.allblocks.append( - Tchapter(re_start="(NON-EXEMPTED )?COVERAGE VIOLATIONS")) + Tchapter(re_start="(NON-EXEMPTED )?COVERAGE VIOLATIONS") + ) # Unexpected chapter/section catchers @@ -677,7 +761,6 @@ class RnotesExpander: """Produce list of Enote instances found in a "report" output.""" def to_enotes(self, report): - # We need to ignore everything not in the report sections # of interest, so until we know we're in ... @@ -696,7 +779,6 @@ def register(self, enote): self.ernotes[source].register(enote) def process_tline(self, tline): - rline = tline.text # Check if we are getting in a section of interest. If so, register @@ -729,7 +811,6 @@ def process_tline(self, tline): return enote def __init__(self, report): - # xcov --annotate=report produces a single report featuring a list of # indications for slocs in all the units. diff --git a/testsuite/SCOV/internals/segments.py b/testsuite/SCOV/internals/segments.py index 3ce5a4c06..2b6197c33 100644 --- a/testsuite/SCOV/internals/segments.py +++ b/testsuite/SCOV/internals/segments.py @@ -31,18 +31,18 @@ def __init__(self, line, col): self.c = col def pastoreq(self, other): - return (self.lineno > other.lineno - or (self.lineno == other.lineno - and (self.c >= other.c or other.c == 0))) + return self.lineno > other.lineno or ( + self.lineno == other.lineno and (self.c >= other.c or other.c == 0) + ) def beforeq(self, other): - return (self.lineno < other.lineno - or (self.lineno == other.lineno - and (self.c <= other.c or other.c == 0))) + return self.lineno < other.lineno or ( + self.lineno == other.lineno and (self.c <= other.c or other.c == 0) + ) def Spoint_from(text): - items = text.split(':', 1) + items = text.split(":", 1) return Spoint(line=int(items[0]), col=int(items[1])) @@ -52,12 +52,14 @@ def Spoint_from(text): # gnatcov outputs. The _str_ images do not need to match the format expected # by their _from sibling in the same class. + class Section: """ A Section is the association of two slocs to materialize the start and the end of a source section, and which knows to determine if it is included within another section. """ + # ... # l0 -> 3: if a and then b then # ^ @@ -75,27 +77,35 @@ def __init__(self, l0, c0, l1, c1): self.sp1 = Spoint(line=l1, col=c1) def within(self, other): - return (self.sp0.pastoreq(other.sp0) - and self.sp1.beforeq(other.sp1)) + return self.sp0.pastoreq(other.sp0) and self.sp1.beforeq(other.sp1) def __str__(self): return "section %d:%d-%d:%d" % ( - self.sp0.lineno, self.sp0.c, self.sp1.lineno, self.sp1.c) + self.sp0.lineno, + self.sp0.c, + self.sp1.lineno, + self.sp1.c, + ) def Section_from(text): - topitems = text.split('-', 1) - subitems0 = topitems[0].split(':', 1) - subitems1 = topitems[1].split(':', 1) - return Section(l0=int(subitems0[0]), c0=int(subitems0[1]), - l1=int(subitems1[0]), c1=int(subitems1[1])) - - -class Segment (Section): + topitems = text.split("-", 1) + subitems0 = topitems[0].split(":", 1) + subitems1 = topitems[1].split(":", 1) + return Section( + l0=int(subitems0[0]), + c0=int(subitems0[1]), + l1=int(subitems1[0]), + c1=int(subitems1[1]), + ) + + +class Segment(Section): """ A Segment is a Section for which the start and end are known to be on the same line. """ + def __init__(self, lno, clo, chi): Section.__init__(self, l0=lno, c0=clo, l1=lno, c1=chi) @@ -104,15 +114,16 @@ def __str__(self): def Segment_from(text): - topitems = text.split(':', 1) - subitems = topitems[1].split('-', 1) - return Segment(lno=int(topitems[0]), - clo=int(subitems[0]), - chi=int(subitems[1])) + topitems = text.split(":", 1) + subitems = topitems[1].split("-", 1) + return Segment( + lno=int(topitems[0]), clo=int(subitems[0]), chi=int(subitems[1]) + ) class Line(Segment): """A Line is a Segment spanning from first to last column.""" + def __init__(self, lno): Segment.__init__(self, lno=lno, clo=0, chi=0) @@ -121,7 +132,7 @@ def __str__(self): def Line_from(text): - items = text.split(':', 1) + items = text.split(":", 1) return Line(lno=int(items[0])) @@ -129,6 +140,7 @@ class Point(Segment): """ A Point is a Segment for which the start and end columns are identical. """ + def __init__(self, lno, col): Segment.__init__(self, lno=lno, clo=col, chi=col) @@ -137,7 +149,7 @@ def __str__(self): def Point_from(text): - items = text.split(':', 1) + items = text.split(":", 1) return Point(lno=int(items[0]), col=int(items[1])) @@ -188,15 +200,16 @@ def __init__(self, filename, section): # Note that the registered LANGINFO extensions embed the '.' character, - re = '(?P[^ ]*)(?P%s):(?P[^ ]*)' % '|'.join( - ext - for li in LANGINFO.values() - for ext in li.src_ext) + re = "(?P[^ ]*)(?P%s):(?P[^ ]*)" % "|".join( + ext for li in LANGINFO.values() for ext in li.src_ext + ) def Sloc_from_match(m): - return Sloc(filename=''.join([m.group("sbase"), m.group("ext")]), - section=Section_within(m.group("sec"))) + return Sloc( + filename="".join([m.group("sbase"), m.group("ext")]), + section=Section_within(m.group("sec")), + ) def Sloc_from(text): diff --git a/testsuite/SCOV/internals/stags.py b/testsuite/SCOV/internals/stags.py index 50e331c44..b3efb90e0 100644 --- a/testsuite/SCOV/internals/stags.py +++ b/testsuite/SCOV/internals/stags.py @@ -25,13 +25,16 @@ class Stag: """Abstract separation tag.""" + def __init__(self, text): self.text = text def match(self, other): - return (False - if self.__class__ != other.__class__ - else self.match_akin(other)) + return ( + False + if self.__class__ != other.__class__ + else self.match_akin(other) + ) def Stag_from(text, from_report): @@ -49,6 +52,7 @@ def Stag_from(text, from_report): class Rtag(Stag): """Routine separation tag. Text is routine name.""" + def __init__(self, text): Stag.__init__(self, text) @@ -65,11 +69,11 @@ class Itag(Stag): def __init__(self, text): Stag.__init__(self, text) - self.components = [Sloc_from(part) - for part in text.rstrip(']').split('[')] + self.components = [ + Sloc_from(part) for part in text.rstrip("]").split("[") + ] def __all_components_match(self, other): - # Check whether any component pair is found not to match: for c1, c2 in zip(self.components, other.components): @@ -82,5 +86,6 @@ def __all_components_match(self, other): return True def match_akin(self, other): - return (len(self.components) == len(other.components) - and self.__all_components_match(other)) + return len(self.components) == len( + other.components + ) and self.__all_components_match(other) diff --git a/testsuite/SCOV/internals/tfiles.py b/testsuite/SCOV/internals/tfiles.py index 96c1086dc..744426383 100644 --- a/testsuite/SCOV/internals/tfiles.py +++ b/testsuite/SCOV/internals/tfiles.py @@ -11,6 +11,7 @@ class Tline: """Associate a line contents with its position in a text file.""" + def __init__(self, lno, text): self.lno = lno self.text = text diff --git a/testsuite/SCOV/internals/xnexpanders.py b/testsuite/SCOV/internals/xnexpanders.py index b60ccac69..e4f0a8196 100644 --- a/testsuite/SCOV/internals/xnexpanders.py +++ b/testsuite/SCOV/internals/xnexpanders.py @@ -14,9 +14,24 @@ from SUITE.control import language_info from SUITE.cutils import FatalError, lines_of from .cnotes import ( - Block, KnoteDict, dNoCov, dPartCov, dfNoCov, dtNoCov, eNoCov, ePartCov, - efNoCov, etNoCov, lPartCov, oNoCov, oPartCov, ofNoCov, otNoCov, sNoCov, - xlNoteKinds, xrNoteKinds + Block, + KnoteDict, + dNoCov, + dPartCov, + dfNoCov, + dtNoCov, + eNoCov, + ePartCov, + efNoCov, + etNoCov, + lPartCov, + oNoCov, + oPartCov, + ofNoCov, + otNoCov, + sNoCov, + xlNoteKinds, + xrNoteKinds, ) from .tfiles import Tfile from .xnotep import XnoteP @@ -343,7 +358,7 @@ def __resolve(self, xpath): the current point. """ - for pdir in ("../"*n + "src/" for n in range(0, thistest.depth)): + for pdir in ("../" * n + "src/" for n in range(0, thistest.depth)): if os.path.exists(pdir + xpath): return pdir + xpath @@ -358,7 +373,7 @@ def __init__(self, xsource): self.xsource = xsource # XPATH: The relative path expressed in the expectation: - self.xpath = xsource[1:] if xsource.startswith('+') else xsource + self.xpath = xsource[1:] if xsource.startswith("+") else xsource # SPATH: The resolved path to an actual source file reachable for # the testcase at hand: @@ -372,7 +387,6 @@ class LineCX: """ def __init__(self, lre, lnp, rnps, override): - self.lre = lre self.lnp = lnp self.rnps = rnps @@ -386,9 +400,11 @@ def instanciate_lnotes_over(self, tline, block, srules): return [self.lnp.instanciate_over(tline, block, srules)] def instanciate_rnotes_over(self, tline, block, srules): - return [rnp.instanciate_over(tline, block, srules) - for rnp in self.rnps - if rnp.kind] + return [ + rnp.instanciate_over(tline, block, srules) + for rnp in self.rnps + if rnp.kind + ] class UnitCX: @@ -426,56 +442,51 @@ def instanciate_notes_for(self, lx, tline, block, srules): # anchors, with the following possible values for each : subst_tuples_for = { - # o/d: Outcome expectations for line are to produce "decision" # expectations, for instance on # # if A and then B then -- # eval :o/d: - - "o/d": {otNoCov: dtNoCov, - ofNoCov: dfNoCov, - oPartCov: dPartCov, - oNoCov: dNoCov}, - + "o/d": { + otNoCov: dtNoCov, + ofNoCov: dfNoCov, + oPartCov: dPartCov, + oNoCov: dNoCov, + }, # o/e: Outcome expectations for line are to produce "expression" # expectations, for instance on # # return Value (A and then B); -- # eval :o/e: - - "o/e": {otNoCov: etNoCov, - ofNoCov: efNoCov, - oPartCov: ePartCov, - oNoCov: eNoCov}, - + "o/e": { + otNoCov: etNoCov, + ofNoCov: efNoCov, + oPartCov: ePartCov, + oNoCov: eNoCov, + }, # o/0: outcome expectations for line are to be ignored, for # contexts where the evaluated expression is not actually a # decision, for instance on # # pragma Precondition (not X); -- # eval :o/0: - - "o/0": {otNoCov: None, - ofNoCov: None, - oPartCov: None, - oNoCov: None, - lPartCov: None}, - + "o/0": { + otNoCov: None, + ofNoCov: None, + oPartCov: None, + oNoCov: None, + lPartCov: None, + }, # s/e: Statement uncovered expectations for line are to be # matched as expression never evaluated, for contexts where # the evaluated expression is not enclosed in a statement, # for instance on # # pragma Precondition (A and then B); -- # eval :s/e: - "s/e": {sNoCov: eNoCov}, - # eval on the line are in expression or decision context - "e": {}, - "d": {} - } + "d": {}, + } def check_srules_on(self, tline): - # Check for kind substitution rules on this line. Reset # at every line for now. @@ -485,7 +496,7 @@ def check_srules_on(self, tline): self.current_srules = None else: self.current_srules = {} - for sim in m.group(1).split(','): + for sim in m.group(1).split(","): self.current_srules.update(self.subst_tuples_for[sim]) # Toplevel processing @@ -494,11 +505,11 @@ def process_tline(self, tline): self.check_srules_on(tline) for lx in self.LXset: if re.search(lx.lre, tline.text): - self.instanciate_notes_for(lx, tline, self.current_block, - self.current_srules) + self.instanciate_notes_for( + lx, tline, self.current_block, self.current_srules + ) def __init__(self, sref, LXset): - self.LXset = LXset # dictionaries of expected line and report notes for our unit @@ -513,14 +524,13 @@ def __init__(self, sref, LXset): self.sref = sref - thistest.stop_if(self.current_block, - FatalError("fuzz block still open at EOF")) + thistest.stop_if( + self.current_block, FatalError("fuzz block still open at EOF") + ) class UXgroup: - def __init__(self, candlists): - # SRLIST: good list of source ref objects from the set of candidate # lists received in CANDLISTS for this group, as specified in the # expectation spec. This is a list of lists like @@ -581,8 +591,10 @@ def __select_srlist_from(self, candlists): thistest.stop_if( len(goodlists) != 1, - FatalError("goodlists = %d, != 1 for %s" - % (len(goodlists), candlists))) + FatalError( + "goodlists = %d, != 1 for %s" % (len(goodlists), candlists) + ), + ) return goodlists[0] @@ -617,8 +629,9 @@ def close(self): # Now instanciate a unit coverage expectations object for each # source ref in our list: - self.uxset = [UnitCX(sref=sref, LXset=self.lxset) - for sref in self.srlist] + self.uxset = [ + UnitCX(sref=sref, LXset=self.lxset) for sref in self.srlist + ] return self.uxset @@ -665,9 +678,16 @@ class XnotesExpander: # | # > g.close () for all parsed groups - def __init__(self, xfile, xcov_level, ctl_opts, ctl_cov, ctl_cargs, - ctl_tags, ctl_cons): - + def __init__( + self, + xfile, + xcov_level, + ctl_opts, + ctl_cov, + ctl_cargs, + ctl_tags, + ctl_cons, + ): # XFILE is the name of the file from which coverage expectations # are to be extracted. @@ -688,11 +708,13 @@ def __init__(self, xfile, xcov_level, ctl_opts, ctl_cov, ctl_cargs, # CTL_TAGS - set of discriminants for the current run, and # CTL_CONS - kinds of consolidation artifacts we are requested to use - self.ctls = {"%opts": ' '.join(ctl_opts), - "%cargs": ' '.join(ctl_cargs), - "%cov": ' '.join(ctl_cov), - "%tags": ' '.join(ctl_tags), - "%cons": ' '.join(ctl_cons)} + self.ctls = { + "%opts": " ".join(ctl_opts), + "%cargs": " ".join(ctl_cargs), + "%cov": " ".join(ctl_cov), + "%tags": " ".join(ctl_tags), + "%cons": " ".join(ctl_cons), + } # And these are the dictionaries we expose. This includes the expected # line notes, the expected report notes, and the absolute paths to the @@ -706,13 +728,14 @@ def __init__(self, xfile, xcov_level, ctl_opts, ctl_cov, ctl_cargs, self.__expose(ux) def __expose(self, ux): - # A '+' prefix on the source reference means we expect # sources to be referenced with relative dir indications: - source = (ux.sref.xpath - if ux.sref.xsource.startswith('+') - else os.path.basename(ux.sref.xpath)) + source = ( + ux.sref.xpath + if ux.sref.xsource.startswith("+") + else os.path.basename(ux.sref.xpath) + ) self.abspaths[source] = os.path.abspath(ux.sref.spath) self.xrnotes[source] = ux.xrdict @@ -739,13 +762,13 @@ def __get_scovdata(self, scov_file): # more flexibility. Also take care of the trailing new-line # character that we get from lines_of. line.strip() - if line.startswith(lang_info.comment + '#'): + if line.startswith(lang_info.comment + "#"): in_scovdata = True if in_scovdata and line.startswith(lang_info.comment): # Also take this opportunity to strip the leading comment # string as well as any space immediately following it. # This will simplify the parsing a little bit. - contents.append(line[len(lang_info.comment):].lstrip()) + contents.append(line[len(lang_info.comment) :].lstrip()) return contents def __parse_scovdata(self, scovdata): @@ -811,11 +834,9 @@ def __parse_groups_from(self, scovdata): lastlx = None for line in scovdata: - ctl_update, ctl_value = self.__try_ctl_update_from(line) if ctl_update: - # A CTL line was found, update our processing state # accordingly: @@ -824,15 +845,13 @@ def __parse_groups_from(self, scovdata): else: grabbing = ctl_value - elif grabbing and line.startswith('+#'): - + elif grabbing and line.startswith("+#"): # A continuation line, to add rnotes that didn't fit # on the previous ones. lastlx.rnps.extend(self.__parse_expected_rnotes(line[3:])) - elif line.startswith('#'): - + elif line.startswith("#"): # A new group starts. Close the current one first and start # grabbing again unconditionally: @@ -842,8 +861,7 @@ def __parse_groups_from(self, scovdata): current_uxg = UXgroup(candlists=self.__parse_sources(line)) grabbing = True - elif grabbing and line.startswith(('/', '=')): - + elif grabbing and line.startswith(("/", "=")): # This must be an LX line. Check lre overriding and add to the # set attached to the current group consistency. @@ -853,13 +871,14 @@ def __parse_groups_from(self, scovdata): lx.lre in current_uxg.lxset and not lx.override, FatalError( "LRE dup without overriding note (%s, %s)" - % (lx.lre, self.xfile))) + % (lx.lre, self.xfile) + ), + ) current_uxg.lxset[lx.lre] = lx lastlx = lx else: - # Not grabbing or regular comment. Just ignore. pass @@ -889,9 +908,11 @@ def __end_parse_on(self, uxg): # # What default notes we expect for what designator text - builtin_lxs = {"__l-s-": "l- ## s-", - "__l!d!": "l! ## d!", - "__l!dT-": "l! ## dT-"} + builtin_lxs = { + "__l-s-": "l- ## s-", + "__l!d!": "l! ## d!", + "__l!dT-": "l! ## dT-", + } def __builtin_lcxs_for(self, uxg): """Add builtin default LineCX for UXG.""" @@ -904,8 +925,10 @@ def __builtin_lcxs_for(self, uxg): # Now compute the list of LCX objects for each of those defaults - return [self.__parse_lcx("/%s/ %s" % (lre, self.builtin_lxs[lre])) - for lre in nothere] + return [ + self.__parse_lcx("/%s/ %s" % (lre, self.builtin_lxs[lre])) + for lre in nothere + ] # CTL parsing for control of conditional sections @@ -925,7 +948,7 @@ def __try_ctl_update_from(self, line): # CTL lines are like "%cov: -S routines %cargs: !-gnatn" # They are the only lines that may start with '%'. - if not line.startswith('%'): + if not line.startswith("%"): return (False, None) # To keep grabbing LX lines, all the CTL parts must evaluate True. @@ -988,17 +1011,15 @@ def __eval_ctl_update_from(self, part): # of options that we were given for the key: this_val = True - for oseq in opts.split(','): - + for oseq in opts.split(","): oseq = oseq.strip() - if oseq.startswith('!'): + if oseq.startswith("!"): invert = True oseq = oseq[1:] else: invert = False - optin = re.search(pattern=oseq, - string=self.ctls[key]) is not None + optin = re.search(pattern=oseq, string=self.ctls[key]) is not None this_val &= not optin if invert else optin @@ -1020,7 +1041,7 @@ def __parse_sources(self, image): # to mean "this section applies to (x0.adb and y0.adb) or (x1.c an # y1.c), whichever set we can reach from here. - return [alt.split(' ') for alt in image[1:].strip().split('|')] + return [alt.split(" ") for alt in image[1:].strip().split("|")] # Instance name resolution helpers for __resolve_stags_from() @@ -1043,7 +1064,6 @@ def __parse_sources(self, image): imark = "i:" def __resolve_itags_within(self, xnp, idict): - # xnp.stag contains something like i:NAME1[i:NAME2[i:NAME3]] to # designate instantiations @@ -1060,20 +1080,25 @@ def __sloc_for(m): # stash a dummy column number here, required to form a regular # Sloc still. - slocs = ["%s:%d:0" % (os.path.basename(sp), tl.lno) - for sp in idict - for tl in idict[sp] - if name in tl.text] + slocs = [ + "%s:%d:0" % (os.path.basename(sp), tl.lno) + for sp in idict + for tl in idict[sp] + if name in tl.text + ] thistest.stop_if( len(slocs) != 1, - FatalError("%d slocs found for stag %s" % (len(slocs), name))) + FatalError("%d slocs found for stag %s" % (len(slocs), name)), + ) return slocs[0] - xnp.stag = re.sub(pattern="%s[A-Za-z_0-9]+" % self.imark, - repl=__sloc_for, - string=xnp.stag) + xnp.stag = re.sub( + pattern="%s[A-Za-z_0-9]+" % self.imark, + repl=__sloc_for, + string=xnp.stag, + ) def __resolve_itags_from(self, all_xnps, uxgroups): """ @@ -1082,9 +1107,9 @@ def __resolve_itags_from(self, all_xnps, uxgroups): all the units in UXGROUPS. """ - i_xnps = [xnp - for xnp in all_xnps - if xnp.stag and self.imark in xnp.stag] + i_xnps = [ + xnp for xnp in all_xnps if xnp.stag and self.imark in xnp.stag + ] if len(i_xnps) == 0: return @@ -1094,9 +1119,9 @@ def __resolve_itags_from(self, all_xnps, uxgroups): def __ilines_for(sp): tf = Tfile(filename=sp, process=lambda tl: None) - return [tl - for tl in tf.contents() - if "# %s" % self.imark in tl.text] + return [ + tl for tl in tf.contents() if "# %s" % self.imark in tl.text + ] spaths = [sref.spath for uxg in uxgroups for sref in uxg.srlist] idict = {sp: __ilines_for(sp) for sp in spaths} @@ -1112,10 +1137,9 @@ def __resolve_stags_from(self, uxgroups): separation tag strings into Stag objects. """ - all_xnps = [xnp - for uxg in uxgroups - for lx in uxg.lxset - for xnp in lx.rnps] + all_xnps = [ + xnp for uxg in uxgroups for lx in uxg.lxset for xnp in lx.rnps + ] self.__resolve_itags_from(all_xnps=all_xnps, uxgroups=uxgroups) @@ -1146,13 +1170,13 @@ def __parse_expected_rnotes(self, image): splitter.whitespace_split = True splitter.whitespace += "#," imlist = list(splitter) - return [rnote - for rnote in (self.__parse_one_expected_rnote(im) - for im in imlist) - if rnote] + return [ + rnote + for rnote in (self.__parse_one_expected_rnote(im) for im in imlist) + if rnote + ] def __parse_one_expected_rnote(self, image): - # We have at hand single note spec, possibly conditioned by the # xcov-level. Something like "s-", "d=>dT-", or "mu=>c!:"B". @@ -1170,18 +1194,18 @@ def __parse_one_expected_rnote(self, image): # possible instance specialization parts and return a note pattern # instance - if '@(' in ntext: - ntext, stag = ntext.split('@(') - stag = stag.rstrip(')') + if "@(" in ntext: + ntext, stag = ntext.split("@(") + stag = stag.rstrip(")") else: stag = None - if ':' in ntext: + if ":" in ntext: # We split only once, as we have occurrences of notes as such: # s-:"P :=" (the string as parsed by shlex would be 's-:P :='), # with a colon inside the quoted string. We don't want to split on # that second colon, as it is part of the source code. - ntext, stext = ntext.split(':', 1) + ntext, stext = ntext.split(":", 1) else: stext = None @@ -1203,10 +1227,12 @@ def __decode_note_choice(self, text): or [('stmt', 'l+'), ('stmt+decision', 'l+')] """ - level_from_char = {"s": ["stmt"], - "d": ["stmt+decision"], - "m": ["stmt+mcdc"], - "u": ["stmt+uc_mcdc"]} + level_from_char = { + "s": ["stmt"], + "d": ["stmt+decision"], + "m": ["stmt+mcdc"], + "u": ["stmt+uc_mcdc"], + } def make_assert_lvl_combinaison(assert_lvl): """ @@ -1214,11 +1240,15 @@ def make_assert_lvl_combinaison(assert_lvl): coverage level combinaisons defined in level_from_char. Return the list of combinaisons. """ - return [level_from_char[c][0] + "+" + assert_lvl - for c in level_from_char] - - assert_level_from_char = {"a": make_assert_lvl_combinaison("atc"), - "c": make_assert_lvl_combinaison("atcc")} + return [ + level_from_char[c][0] + "+" + assert_lvl + for c in level_from_char + ] + + assert_level_from_char = { + "a": make_assert_lvl_combinaison("atc"), + "c": make_assert_lvl_combinaison("atcc"), + } level_from_char.update(assert_level_from_char) @@ -1230,10 +1260,11 @@ def make_assert_lvl_combinaison(assert_lvl): elif len(result) > 2: # Parse error raise FatalError( - "Note choice %s contains more than one arrow" % text) + "Note choice %s contains more than one arrow" % text + ) else: - note = result[1].lstrip(' ') - lev_list = result[0].rstrip(' ') + note = result[1].lstrip(" ") + lev_list = result[0].rstrip(" ") res = [] for lchar in lev_list: @@ -1246,7 +1277,7 @@ def __select_lnote(self, text): """Decode text to return the line note for the current coverage level.""" - lx_lnote_list = [alt.strip() for alt in text.split(',')] + lx_lnote_list = [alt.strip() for alt in text.split(",")] level_table = dict( ln_tuple @@ -1256,28 +1287,30 @@ def __select_lnote(self, text): if self.xcov_level in level_table: return level_table[self.xcov_level] - elif '' in level_table: - return level_table[''] + elif "" in level_table: + return level_table[""] else: raise FatalError( "Missing line expectation choice for level %s in %s" - % (self.xcov_level, text)) + % (self.xcov_level, text) + ) def __select_rnote(self, text): """Decode TEXT into a report note for the current coverage level.""" # Set of level->note_kind associations in TEXT - level_table = dict(ln_tuple - for ln_tuple in self.__decode_note_choice(text)) + level_table = dict( + ln_tuple for ln_tuple in self.__decode_note_choice(text) + ) # If we have one association for the exact level we're running, # use that. Fallback to a default kind if we have one. if self.xcov_level in level_table: return level_table[self.xcov_level] - elif '' in level_table: - return level_table[''] + elif "" in level_table: + return level_table[""] return None @@ -1291,22 +1324,26 @@ def __parse_lcx(self, image): m = re.match( string=image, - pattern=r"\s*(?P=?/.*?/)\s+(?P.*) ## (?P.*)") + pattern=r"\s*(?P=?/.*?/)\s+(?P.*) ## (?P.*)", + ) if m is None: - raise FatalError("Invalid '%s' line expectation spec." - "\nExpected /LRE/ lnotes ## rnotes" % image) + raise FatalError( + "Invalid '%s' line expectation spec." + "\nExpected /LRE/ lnotes ## rnotes" % image + ) lx_lre = m.group("lre") - lre_override = lx_lre[0] == '=' - if lx_lre[0] != '/': + lre_override = lx_lre[0] == "=" + if lx_lre[0] != "/": lx_lre = lx_lre[1:] - lx_lre = lx_lre.strip('/') + lx_lre = lx_lre.strip("/") - lx_lnote = XnoteP(text=self.__select_lnote(m.group("lnote")), - stext=None) + lx_lnote = XnoteP( + text=self.__select_lnote(m.group("lnote")), stext=None + ) lx_rnotes = self.__parse_expected_rnotes(m.group("rnotes")) @@ -1325,8 +1362,9 @@ def __parse_lcx(self, image): else: thistest.stop_if( len(lx_rnotes) > 1 and "0" in lx_rnotes, - FatalError("Contradictory =report expectation in %s" % image) + FatalError("Contradictory =report expectation in %s" % image), ) - return LineCX(lre=lx_lre, lnp=lx_lnote, rnps=lx_rnotes, - override=lre_override) + return LineCX( + lre=lx_lre, lnp=lx_lnote, rnps=lx_rnotes, override=lre_override + ) diff --git a/testsuite/SCOV/internals/xnotep.py b/testsuite/SCOV/internals/xnotep.py index 78da96485..885025ee2 100644 --- a/testsuite/SCOV/internals/xnotep.py +++ b/testsuite/SCOV/internals/xnotep.py @@ -12,14 +12,60 @@ import re from .cnotes import ( - Xnote, block_p, transparent_p, cPartCov, dNoCov, dPartCov, dfAlways, - dfNoCov, dtAlways, dtNoCov, ePartCov, eNoCov, efNoCov, etNoCov, lFullCov, - lNoCode, lNoCov, lNotCoverable, lPartCov, lx0, lx1, lx2, lx, oNoCov, - oPartCov, ofNoCov, otNoCov, r0, r0c, sNoCov, sNotCoverable, sPartCov, - xBlock0, xBlock1, xBlock2, xNoteKinds, lUndetCov, sUndetCov, dUndetCov, - eUndetCov, XsNoCov, XsPartCov, XsNotCoverable, XsUndetCov, XotNoCov, - XofNoCov, XoPartCov, XoNoCov, XcPartCov, Xr0, Xr0c, aNoCov, atNoCov, - acPartCov + Xnote, + block_p, + transparent_p, + cPartCov, + dNoCov, + dPartCov, + dfAlways, + dfNoCov, + dtAlways, + dtNoCov, + ePartCov, + eNoCov, + efNoCov, + etNoCov, + lFullCov, + lNoCode, + lNoCov, + lNotCoverable, + lPartCov, + lx0, + lx1, + lx2, + lx, + oNoCov, + oPartCov, + ofNoCov, + otNoCov, + r0, + r0c, + sNoCov, + sNotCoverable, + sPartCov, + xBlock0, + xBlock1, + xBlock2, + xNoteKinds, + lUndetCov, + sUndetCov, + dUndetCov, + eUndetCov, + XsNoCov, + XsPartCov, + XsNotCoverable, + XsUndetCov, + XotNoCov, + XofNoCov, + XoPartCov, + XoNoCov, + XcPartCov, + Xr0, + Xr0c, + aNoCov, + atNoCov, + acPartCov, ) from .segments import Line, Section, Segment from .stags import Stag_from @@ -45,7 +91,6 @@ def __init__(self, notep): self.lastni = None def instanciate_over(self, tline, block, kind): - # We create a single instance the first time around, then expand the # section over subsequence matches. if self.lastni: @@ -55,7 +100,8 @@ def instanciate_over(self, tline, block, kind): else: thisni = Xnote(xnp=self.notep, block=block, kind=kind) thisni.register_match( - Section(l0=tline.lno, c0=0, l1=tline.lno, c1=0)) + Section(l0=tline.lno, c0=0, l1=tline.lno, c1=0) + ) if thisni: self.lastni = thisni @@ -71,7 +117,6 @@ def __init__(self, notep): self.notep = notep def instanciate_over(self, tline, block, kind): - thisni = Xnote(xnp=self.notep, block=block, kind=kind) thisni.register_match(Line(tline.lno)) @@ -114,9 +159,9 @@ def __extended_segend_for(self, tline, bm): while segend <= linend and pnest >= 0: c = tline.text[segend] - if c == '(': + if c == "(": pnest += 1 - elif c == ')': + elif c == ")": pnest -= 1 segend += 1 @@ -127,7 +172,6 @@ def __extended_segend_for(self, tline, bm): return segend def instanciate_over(self, tline, block, kind): - thisni = Xnote(xnp=self.notep, block=block, kind=kind) # Register matches for Segments corresponding to all the instances of @@ -138,7 +182,7 @@ def instanciate_over(self, tline, block, kind): # not. base = self.stext - if self.stext.startswith('(') and self.stext.endswith('*)'): + if self.stext.startswith("(") and self.stext.endswith("*)"): base = self.stext[0:-2] extend = True else: @@ -151,46 +195,87 @@ def instanciate_over(self, tline, block, kind): for bm in re.finditer(pattern=base, string=tline.text): thisni.register_match( Segment( - tline.lno, bm.start() + 1, + tline.lno, + bm.start() + 1, self.__extended_segend_for(bm=bm, tline=tline) - if extend else bm.end())) + if extend + else bm.end(), + ) + ) thistest.stop_if( thisni.nmatches == 0, - FatalError("couldn't find subtext '%s' in line '%s'" - % (self.stext, tline.text))) + FatalError( + "couldn't find subtext '%s' in line '%s'" + % (self.stext, tline.text) + ), + ) thistest.stop_if( thisni.nmatches > 1, - FatalError("multiple matches of subtext '%s' in line '%s'" - % (self.stext, tline.text))) + FatalError( + "multiple matches of subtext '%s' in line '%s'" + % (self.stext, tline.text) + ), + ) return thisni class XnoteP: - - NK_for = {'l-': lNoCov, 'l!': lPartCov, 'l+': lFullCov, - 'l.': lNoCode, 'l0': lNotCoverable, 'l?': lUndetCov, - 'l#': lx0, 'l*': lx1, 'l@': lx2, 'l=': lx, - 's-': sNoCov, 's!': sPartCov, 's0': sNotCoverable, - 's?': sUndetCov, - 'dT*': dtAlways, 'dF*': dfAlways, - 'dT-': dtNoCov, 'dF-': dfNoCov, 'd!': dPartCov, 'd-': dNoCov, - 'd?': dUndetCov, - 'eT-': etNoCov, 'eF-': efNoCov, 'e!': ePartCov, 'e-': eNoCov, - 'e?': eUndetCov, - 'oT-': otNoCov, 'oF-': ofNoCov, 'o!': oPartCov, 'o-': oNoCov, - 'c!': cPartCov, - 'a-': aNoCov, 'aT-': atNoCov, 'ac!': acPartCov, - 'x0': xBlock0, 'x+': xBlock1, 'x?': xBlock2, - '0': r0, '0c': r0c, - # Exempted notes - 'Xs-': XsNoCov, 'Xs!': XsPartCov, 'Xs0': XsNotCoverable, - 'Xs?': XsUndetCov, - 'XoT-': XotNoCov, 'XoF-': XofNoCov, 'Xo!': XoPartCov, - 'Xo-': XoNoCov, 'Xc!': XcPartCov, - 'X0': Xr0, 'X0c': Xr0c} + NK_for = { + "l-": lNoCov, + "l!": lPartCov, + "l+": lFullCov, + "l.": lNoCode, + "l0": lNotCoverable, + "l?": lUndetCov, + "l#": lx0, + "l*": lx1, + "l@": lx2, + "l=": lx, + "s-": sNoCov, + "s!": sPartCov, + "s0": sNotCoverable, + "s?": sUndetCov, + "dT*": dtAlways, + "dF*": dfAlways, + "dT-": dtNoCov, + "dF-": dfNoCov, + "d!": dPartCov, + "d-": dNoCov, + "d?": dUndetCov, + "eT-": etNoCov, + "eF-": efNoCov, + "e!": ePartCov, + "e-": eNoCov, + "e?": eUndetCov, + "oT-": otNoCov, + "oF-": ofNoCov, + "o!": oPartCov, + "o-": oNoCov, + "c!": cPartCov, + "a-": aNoCov, + "aT-": atNoCov, + "ac!": acPartCov, + "x0": xBlock0, + "x+": xBlock1, + "x?": xBlock2, + "0": r0, + "0c": r0c, + # Exempted notes + "Xs-": XsNoCov, + "Xs!": XsPartCov, + "Xs0": XsNotCoverable, + "Xs?": XsUndetCov, + "XoT-": XotNoCov, + "XoF-": XofNoCov, + "Xo!": XoPartCov, + "Xo-": XoNoCov, + "Xc!": XcPartCov, + "X0": Xr0, + "X0c": Xr0c, + } # The notes prefixed with 'X' correspond to the type of violations we # expect to encounter within an exempted block. In this context we cannot @@ -199,12 +284,11 @@ class XnoteP: # information. def __init__(self, text, stext=None, stag=None): - # WEAK conveys whether it is ok (not triggering test failure) for # expectations produced by this pattern not to be discharged by an # emitted note. - self.weak = text[0] == '~' + self.weak = text[0] == "~" if self.weak: text = text[1:] @@ -232,7 +316,8 @@ def __init__(self, text, stext=None, stag=None): thistest.stop_if( False and self.stext is None and self.kind in xNoteKinds, - FatalError("expected justification text required for %s" % text)) + FatalError("expected justification text required for %s" % text), + ) # STAG is the separation tag that we must find on an emitted note to # discharge expectations produced from this pattern. Initially, at this @@ -245,21 +330,24 @@ def __init__(self, text, stext=None, stag=None): self.factory = ( _XnoteP_block(notep=self) - if block_p(self.kind) else - _XnoteP_line(notep=self) - if not self.stext else - _XnoteP_segment(notep=self, stext=stext)) + if block_p(self.kind) + else _XnoteP_line(notep=self) + if not self.stext + else _XnoteP_segment(notep=self, stext=stext) + ) def instantiate_stag(self): self.stag = Stag_from(self.stag, False) def instanciate_over(self, tline, block, srules): - - kind = (srules[self.kind] - if srules and self.kind in srules - else self.kind) - - return (None - if kind is None or transparent_p(kind) - else self.factory.instanciate_over(tline=tline, block=block, - kind=kind)) + kind = ( + srules[self.kind] if srules and self.kind in srules else self.kind + ) + + return ( + None + if kind is None or transparent_p(kind) + else self.factory.instanciate_over( + tline=tline, block=block, kind=kind + ) + ) diff --git a/testsuite/SCOV/map.py b/testsuite/SCOV/map.py index 9675fac8c..2fe9a792b 100644 --- a/testsuite/SCOV/map.py +++ b/testsuite/SCOV/map.py @@ -9,13 +9,21 @@ from SUITE.control import env from SUITE.cutils import Wdir, match, to_list, list_to_file -from SUITE.tutils import (XCOV, thistest, gprfor, gprbuild, exename_for, do, - maybe_valgrind) +from SUITE.tutils import ( + XCOV, + thistest, + gprfor, + gprbuild, + exename_for, + do, + maybe_valgrind, +) class MapChecker: - def __init__(self, sources, options="", execs=None, alis=None, - ensure_dcscos=True): + def __init__( + self, sources, options="", execs=None, alis=None, ensure_dcscos=True + ): self.sources = to_list(sources) self.options = options self.ensure_dcscos = ensure_dcscos @@ -25,45 +33,56 @@ def __init__(self, sources, options="", execs=None, alis=None, self.execs = to_list(execs) else: self.execs = [ - exename_for(source.split('.')[0]) - for source in self.sources + exename_for(source.split(".")[0]) for source in self.sources ] if alis is not None: self.alis = to_list(alis) else: - self.alis = [os.path.join("obj", "%s.ali" % source.split('.')[0]) - for source in self.sources] + self.alis = [ + os.path.join("obj", "%s.ali" % source.split(".")[0]) + for source in self.sources + ] def run(self): - tmp = Wdir('tmp_') + tmp = Wdir("tmp_") # Compile all the sources. This method will not work if there are # sources that are not in the "." directory, but since executabes are # processed next, there will be an error if not all sources are # compiled. - project = gprfor( - self.sources, srcdirs=[".."], main_cargs=self.options) + project = gprfor(self.sources, srcdirs=[".."], main_cargs=self.options) gprbuild(project, gargs=["-bargs", "-z"]) # If requested, check at least one non statement SCO in alis if self.ensure_dcscos: for ali in self.alis: - thistest.fail_if(not match('^C[^S ]', ali, re.MULTILINE), - "couldn't find non-statement SCO in %s" % ali) + thistest.fail_if( + not match("^C[^S ]", ali, re.MULTILINE), + "couldn't find non-statement SCO in %s" % ali, + ) # Run xcov map-routines and check absence of errors - mapoutput = do(maybe_valgrind([ - XCOV, 'map-routines', f'--target={env.target.triplet}', - '--scos=@{}'.format(list_to_file(self.alis)), - ] + self.execs)) + mapoutput = do( + maybe_valgrind( + [ + XCOV, + "map-routines", + f"--target={env.target.triplet}", + "--scos=@{}".format(list_to_file(self.alis)), + ] + + self.execs + ) + ) - maperrors = [str(m) for m in - re.findall(r"(\*\*\*|\!\!\!)(.*)", mapoutput)] + maperrors = [ + str(m) for m in re.findall(r"(\*\*\*|\!\!\!)(.*)", mapoutput) + ] - thistest.log('\n'.join(maperrors)) + thistest.log("\n".join(maperrors)) thistest.fail_if( maperrors, - "expect no map-routines error for %s" % ", ".join(self.sources)) + "expect no map-routines error for %s" % ", ".join(self.sources), + ) tmp.to_homedir() diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 82e92a146..8b8031e45 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -15,30 +15,62 @@ from e3.fs import rm -from SCOV.instr import (default_dump_channel, xcov_convert_base64, - xcov_instrument) +from SCOV.instr import ( + default_dump_channel, + xcov_convert_base64, + xcov_instrument, +) from SUITE.cutils import contents_of, indent from SUITE.tutils import ( - exepath_to, gprbuild, run_cov_program, srctrace_pattern_for, - srctracename_for, thistest, tracename_for, xcov, xrun, GNATCOV_INFO + exepath_to, + gprbuild, + run_cov_program, + srctrace_pattern_for, + srctracename_for, + thistest, + tracename_for, + xcov, + xrun, + GNATCOV_INFO, ) -COV_RE = re.compile(r'^ *(\d+) (.):.*$') - -def build_and_run(gprsw, covlevel, mains, extra_coverage_args, quiet=True, - scos=None, gpr_obj_dir=None, gpr_exe_dir=None, - ignored_source_files=[], separate_coverage=None, - extra_args=[], extra_run_args=None, extra_instr_args=None, - extra_gprbuild_args=[], extra_gprbuild_cargs=[], - extra_gprbuild_largs=[], absolute_paths=False, - dump_trigger="auto", dump_channel="auto", - check_gprbuild_output=False, trace_mode=None, - runtime_project=None, gprsw_for_coverage=None, - scos_for_run=True, register_failure=True, program_env=None, - tolerate_instrument_messages=None, exec_args=None, - auto_languages=True, manual_prj_name=None, - auto_config_args=True): +COV_RE = re.compile(r"^ *(\d+) (.):.*$") + + +def build_and_run( + gprsw, + covlevel, + mains, + extra_coverage_args, + quiet=True, + scos=None, + gpr_obj_dir=None, + gpr_exe_dir=None, + ignored_source_files=[], + separate_coverage=None, + extra_args=[], + extra_run_args=None, + extra_instr_args=None, + extra_gprbuild_args=[], + extra_gprbuild_cargs=[], + extra_gprbuild_largs=[], + absolute_paths=False, + dump_trigger="auto", + dump_channel="auto", + check_gprbuild_output=False, + trace_mode=None, + runtime_project=None, + gprsw_for_coverage=None, + scos_for_run=True, + register_failure=True, + program_env=None, + tolerate_instrument_messages=None, + exec_args=None, + auto_languages=True, + manual_prj_name=None, + auto_config_args=True, +): """ Prepare a project to run a coverage analysis on it. @@ -124,75 +156,81 @@ def build_and_run(gprsw, covlevel, mains, extra_coverage_args, quiet=True, the given N mains. Upon return, the progam execution log for each main M is available as M_output.txt. """ + def abspath(path): return os.path.abspath(path) if absolute_paths else path def exepath(main): main = os.path.join( gpr_exe_dir, - (os.path.join(gprsw.subdirs, main) if gprsw.subdirs else main)) + (os.path.join(gprsw.subdirs, main) if gprsw.subdirs else main), + ) return abspath(exepath_to(main)) def gprbuild_wrapper(root_project): - # Honor build relevant switches from gprsw here - gprbuild(root_project, - gargs=gprsw.build_switches + extra_gprbuild_args, - extracargs=extra_gprbuild_cargs, - largs=extra_gprbuild_largs, - trace_mode=trace_mode, - runtime_project=runtime_project, - auto_config_args=auto_config_args) + gprbuild( + root_project, + gargs=gprsw.build_switches + extra_gprbuild_args, + extracargs=extra_gprbuild_cargs, + largs=extra_gprbuild_largs, + trace_mode=trace_mode, + runtime_project=runtime_project, + auto_config_args=auto_config_args, + ) if check_gprbuild_output: - gprbuild_out = contents_of('gprbuild.out') + gprbuild_out = contents_of("gprbuild.out") thistest.fail_if( gprbuild_out, - "gprbuild's output (gprbuild.out) is not empty:\n{}" - .format(indent(gprbuild_out))) + "gprbuild's output (gprbuild.out) is not empty:\n{}".format( + indent(gprbuild_out) + ), + ) # When instrumenting, we expect units of interest to be provided # through GPR switches: - assert not (scos and trace_mode == 'src') + assert not (scos and trace_mode == "src") - gpr_exe_dir = gpr_exe_dir or '.' - gpr_obj_dir = gpr_obj_dir or os.path.join(gpr_exe_dir, 'obj') + gpr_exe_dir = gpr_exe_dir or "." + gpr_obj_dir = gpr_obj_dir or os.path.join(gpr_exe_dir, "obj") trace_mode = trace_mode or thistest.options.trace_mode # Use a --level= form for --level to faciliate locating and # replacing the switch at once as a whole if need be. - covlevel_args = [] if covlevel is None else ['--level={}'.format(covlevel)] + covlevel_args = [] if covlevel is None else ["--level={}".format(covlevel)] - xcov_args = ['coverage'] + covlevel_args + xcov_args = ["coverage"] + covlevel_args trace_files = [] # Arguments to pass to "gnatcov coverage" (bin trace mode) or "gnatcov # instrument" (src trace mode), in addition to those conveyed by gprsw. - cov_or_instr_args = ( - extra_args + - ['--ignore-source-files={}'.format(pattern) - for pattern in ignored_source_files]) + cov_or_instr_args = extra_args + [ + "--ignore-source-files={}".format(pattern) + for pattern in ignored_source_files + ] if separate_coverage: - cov_or_instr_args.extend(['-S', separate_coverage]) + cov_or_instr_args.extend(["-S", separate_coverage]) if quiet: cov_or_instr_args.append("--quiet") # Compute arguments to specify units of interest. - if trace_mode == 'bin': - scos_arg = '--scos' - scos_ext = 'ali' + if trace_mode == "bin": + scos_arg = "--scos" + scos_ext = "ali" else: - scos_arg = '--sid' - scos_ext = 'sid' - scos = (['{}={}.{}'.format(scos_arg, abspath(a), scos_ext) - for a in scos] - if scos else - gprsw.cov_switches) + scos_arg = "--sid" + scos_ext = "sid" + scos = ( + ["{}={}.{}".format(scos_arg, abspath(a), scos_ext) for a in scos] + if scos + else gprsw.cov_switches + ) - out_file_ = '{}_output.txt' + out_file_ = "{}_output.txt" - if trace_mode == 'bin': + if trace_mode == "bin": # Build and run each main gprbuild_wrapper(gprsw.root_project) run_args = covlevel_args + extra_args @@ -208,13 +246,17 @@ def gprbuild_wrapper(root_project): for m in mains: out_file = out_file_.format(m) - xrun(run_args + [exepath(m)] + eargs, out=out_file, - env=program_env, register_failure=register_failure) + xrun( + run_args + [exepath(m)] + eargs, + out=out_file, + env=program_env, + register_failure=register_failure, + ) trace_files = [abspath(tracename_for(m)) for m in mains] xcov_args.extend(cov_or_instr_args) - elif trace_mode == 'src': + elif trace_mode == "src": if dump_channel == "auto": dump_channel = default_dump_channel() @@ -229,7 +271,7 @@ def gprbuild_wrapper(root_project): dump_trigger=dump_trigger, dump_channel=dump_channel, runtime_project=runtime_project, - out='instrument.log', + out="instrument.log", register_failure=register_failure, tolerate_messages=tolerate_instrument_messages, auto_languages=auto_languages, @@ -264,10 +306,12 @@ def gprbuild_wrapper(root_project): # Fail if we expected to be able to retrieve the dump channel # actually used, but don't have it: thistest.fail_if( - register_failure and GNATCOV_INFO.has_setup + register_failure + and GNATCOV_INFO.has_setup and actual_dump_channel is None, "Unable to retrieve actual dump_channel from {}".format( - params_file) + params_file + ), ) # At this point, dump_channel is either None (request not to pass an @@ -277,11 +321,12 @@ def gprbuild_wrapper(root_project): # If an explicit dump channel was provided to gnatcov instrument and # we have the actual dump channel used, the two should be consistent: thistest.fail_if( - dump_channel and actual_dump_channel + dump_channel + and actual_dump_channel and dump_channel != actual_dump_channel, "requested dump_channel ({}) != actual ({})".format( dump_channel, actual_dump_channel - ) + ), ) # Now execute each main and collect the trace files we can. Tests @@ -301,14 +346,20 @@ def gprbuild_wrapper(root_project): # Remove potential existing source trace files: the name is # non-deterministic by default, so we want to avoid getting # multiple traces in the current directory. - rm(srctrace_pattern_for(m, - dump_trigger == "manual", - manual_prj_name)) + rm( + srctrace_pattern_for( + m, dump_trigger == "manual", manual_prj_name + ) + ) out_file = out_file_.format(m) - run_cov_program(exepath(m), out=out_file, env=program_env, - register_failure=register_failure, - exec_args=exec_args) + run_cov_program( + exepath(m), + out=out_file, + env=program_env, + register_failure=register_failure, + exec_args=exec_args, + ) # See if we have a trace file at hand or if could create one from # a base64 trace in the output. Operate best effort here, simply @@ -327,25 +378,28 @@ def gprbuild_wrapper(root_project): trace_file = None if known_channel in [None, "bin-file"]: - trace_file = srctracename_for(m, - register_failure=False, - manual=dump_trigger == "manual", - manual_prj_name=manual_prj_name) - - if (not trace_file - and (known_channel == "base64-stdout" - or "source trace file ==" in contents_of(out_file))): - + trace_file = srctracename_for( + m, + register_failure=False, + manual=dump_trigger == "manual", + manual_prj_name=manual_prj_name, + ) + + if not trace_file and ( + known_channel == "base64-stdout" + or "source trace file ==" in contents_of(out_file) + ): # Pick a trace name that is compatible with srctracename_for - src_pattern = srctrace_pattern_for(m, - dump_trigger == "manual", - manual_prj_name) + src_pattern = srctrace_pattern_for( + m, dump_trigger == "manual", manual_prj_name + ) trace_file = src_pattern.replace("*", "unique") # Here we're really supposed to have a trace in the output # so we can be a tad stricter on the conversion outcome. - xcov_convert_base64(out_file, trace_file, - register_failure=register_failure) + xcov_convert_base64( + out_file, trace_file, register_failure=register_failure + ) if trace_file: trace_files.append(abspath(trace_file)) @@ -353,7 +407,7 @@ def gprbuild_wrapper(root_project): xcov_args.extend(cov_or_instr_args) else: - assert False, 'Unknown trace mode: {}'.format(trace_mode) + assert False, "Unknown trace mode: {}".format(trace_mode) # If provided, pass "gnatcov coverage"-specific project arguments, which # replace the list of SCOS. @@ -365,8 +419,13 @@ def gprbuild_wrapper(root_project): return xcov_args + extra_coverage_args + trace_files -def build_run_and_coverage(out='coverage.log', err=None, register_failure=True, - auto_config_args=True, **kwargs): +def build_run_and_coverage( + out="coverage.log", + err=None, + register_failure=True, + auto_config_args=True, + **kwargs, +): """ Helper to call build_and_run and then invoke `xcov`. @@ -377,8 +436,11 @@ def build_run_and_coverage(out='coverage.log', err=None, register_failure=True, `auto_config_args` are reported to `xcov` and `build_and_run`, other arguments are forwarded to `build_and_run`. """ - xcov_args = build_and_run(register_failure=register_failure, - auto_config_args=auto_config_args, **kwargs) + xcov_args = build_and_run( + register_failure=register_failure, + auto_config_args=auto_config_args, + **kwargs, + ) xcov(xcov_args, out=out, err=err, register_failure=register_failure) @@ -390,9 +452,9 @@ def checked_xcov(args, out_file): out = contents_of(out_file) thistest.fail_if( out, - 'gnatcov output not empty ({}):\n' - ' {}\n' - '{}'.format(out_file, ' '.join(args), out) + "gnatcov output not empty ({}):\n" + " {}\n" + "{}".format(out_file, " ".join(args), out), ) @@ -405,11 +467,15 @@ def fmt_cov(cov_data): """ result = [] for cov_char in sorted(cov_data): - result.append('{}({})'.format( - cov_char, ', '.join(str(lineno) - for lineno in sorted(cov_data[cov_char])) - )) - return ' '.join(result) + result.append( + "{}({})".format( + cov_char, + ", ".join( + str(lineno) for lineno in sorted(cov_data[cov_char]) + ), + ) + ) + return " ".join(result) def check_xcov_content(filename, expected_cov, trace_mode=None): @@ -431,15 +497,15 @@ def remove_empty_sets(data): """ Remove entries in "data" that contain empty sets of lines. """ - return {annotation: lines - for annotation, lines in data.items() - if lines} + return { + annotation: lines for annotation, lines in data.items() if lines + } # Check that expected coverage data contain only supported line annotations - invalid_line_annotations = set(expected_cov) - {'+', '!', '-', '?'} - assert not invalid_line_annotations, ( - 'Invalid line annotations: {}' - .format(' '.join(sorted(invalid_line_annotations)))) + invalid_line_annotations = set(expected_cov) - {"+", "!", "-", "?"} + assert not invalid_line_annotations, "Invalid line annotations: {}".format( + " ".join(sorted(invalid_line_annotations)) + ) got_cov = collections.defaultdict(set) dot_lines = set() @@ -449,7 +515,7 @@ def remove_empty_sets(data): if m: lineno, cov_char = m.groups() lineno = int(lineno) - if cov_char == '.': + if cov_char == ".": dot_lines.add(lineno) else: got_cov[cov_char].add(lineno) @@ -464,22 +530,24 @@ def remove_empty_sets(data): refined_expectations = collections.defaultdict(set) refined_expectations.update(expected_cov) - for line in got_cov.get('+', set()): + for line in got_cov.get("+", set()): if line not in expected_non_dot_lines: - refined_expectations['+'].add(line) + refined_expectations["+"].add(line) got_cov = remove_empty_sets(got_cov) refined_expectations = remove_empty_sets(refined_expectations) thistest.fail_if( got_cov != refined_expectations, - '{}: unexpected coverage report content:\n' - 'Expected: {}\n' - 'Refined to: {}\n' - 'But got: {}\n'.format( - filename, fmt_cov(expected_cov), fmt_cov(refined_expectations), - fmt_cov(got_cov) - ) + "{}: unexpected coverage report content:\n" + "Expected: {}\n" + "Refined to: {}\n" + "But got: {}\n".format( + filename, + fmt_cov(expected_cov), + fmt_cov(refined_expectations), + fmt_cov(got_cov), + ), ) @@ -516,17 +584,16 @@ def check_xcov_reports(reports_dir, expected_cov, discard_empty=None): """ def fmt_sorted_indented_list(items): - return '\n'.join(' {}'.format(s) for s in sorted(items)) + return "\n".join(" {}".format(s) for s in sorted(items)) # Avoid discrepancies between filenames on Windows and Unix. Although it is # not the canonical representation, Windows supports using slash as # separators, so use it. def canonicalize_file(filename): - return filename.replace('\\', '/') + return filename.replace("\\", "/") - if ( - discard_empty - or (discard_empty is None and thistest.options.trace_mode == "bin") + if discard_empty or ( + discard_empty is None and thistest.options.trace_mode == "bin" ): expected_cov = { filename: expectations @@ -549,7 +616,7 @@ def canonicalize_file(filename): "Unexpected XCOV files. Expected:\n" f"{fmt_sorted_indented_list(expected_cov)}\n" "But got instead:\n" - f"{fmt_sorted_indented_list(xcov_files)}\n" + f"{fmt_sorted_indented_list(xcov_files)}\n", ) for filename, cov_data in expected_cov.items(): diff --git a/testsuite/SCOV/report.py b/testsuite/SCOV/report.py index fff84aa5a..42d5e063d 100644 --- a/testsuite/SCOV/report.py +++ b/testsuite/SCOV/report.py @@ -30,7 +30,6 @@ class Piece: """Single pattern of text expected somewhere in a report.""" def __init__(self, pattern, pre, nexpected=1): - # Regexp pattern to match over report lines self.pattern = pattern @@ -104,13 +103,18 @@ def check(self): 0 and thistest.log( "--\nChecking {}:\n" "pattern = '{}', nexpected = {}, nmatches = {}\n" - "pre = {}" - .format(self, self.pattern, self.nexpected, nmatches, self.pre)) + "pre = {}".format( + self, self.pattern, self.nexpected, nmatches, self.pre + ) + ) # Punt if we don't have the number of expected matches if nmatches != self.nexpected: - thistest.failed('On "{}", {} matches != expected {}' - .format(self.pattern, nmatches, self.nexpected)) + thistest.failed( + 'On "{}", {} matches != expected {}'.format( + self.pattern, nmatches, self.nexpected + ) + ) return # If we expected matches, have some, and have an ordering @@ -120,12 +124,14 @@ def check(self): first_self = self.__first_match() if not last_pre: thistest.failed( - 'On "%s", absence of match for predecessor "%s"' % ( - self.pattern, self.pre.pattern)) + 'On "%s", absence of match for predecessor "%s"' + % (self.pattern, self.pre.pattern) + ) elif last_pre.lno > first_self.lno: thistest.failed( - 'first match for "%s" too early wrt predecessor "%s"' % ( - self.pattern, self.pre.pattern)) + 'first match for "%s" too early wrt predecessor "%s"' + % (self.pattern, self.pre.pattern) + ) # All the possible per-criterion sections, ordered as they should be in the @@ -137,7 +143,7 @@ def check(self): "stmt": ["STMT"], "stmt+decision": ["STMT", "DECISION"], "stmt+mcdc": ["STMT", "DECISION", "MCDC"], - "stmt+uc_mcdc": ["STMT", "DECISION", "MCDC"] + "stmt+uc_mcdc": ["STMT", "DECISION", "MCDC"], } @@ -154,7 +160,6 @@ def __register(self, rpieces): self.rpElements.extend(rpieces) def __setup_expectations(self, ntraces, xcovlevel, xregions): - self.rpElements = [] # Track the last Piece with nexpected > 0 @@ -187,30 +192,50 @@ def __setup_expectations(self, ntraces, xcovlevel, xregions): # # : gnatcov coverage - covLevel = Piece(pattern=r"Coverage level: stmt(\+(decision|mcdc))?", - pre=cmdLine2) + covLevel = Piece( + pattern=r"Coverage level: stmt(\+(decision|mcdc))?", pre=cmdLine2 + ) trHeader = Piece(pattern="Trace files:", pre=covLevel) - trFile = Piece(pattern=(r'\.trace' - if thistest.options.trace_mode == 'bin' else - r'\.srctrace'), - pre=trHeader, - nexpected=ntraces) + trFile = Piece( + pattern=( + r"\.trace" + if thistest.options.trace_mode == "bin" + else r"\.srctrace" + ), + pre=trHeader, + nexpected=ntraces, + ) trPgm = Piece(pattern="program *:", pre=None, nexpected=ntraces) trDate = Piece(pattern="date *:", pre=None, nexpected=ntraces) trTag = Piece(pattern="tag *:", pre=None, nexpected=ntraces) self.__register( - rpieces=[ctxHeader, runStamp, verNumber, - cmdLine1, cmdLine2, - covLevel, trHeader, trFile, trPgm, trDate, trTag]) + rpieces=[ + ctxHeader, + runStamp, + verNumber, + cmdLine1, + cmdLine2, + covLevel, + trHeader, + trFile, + trPgm, + trDate, + trTag, + ] + ) # NON-EXEMPTED VIOLATIONS - vioHeader = Piece(pattern=(r"\d+. %sCOVERAGE VIOLATIONS" - % ("NON-EXEMPTED " if xregions else "")), - pre=trTag) + vioHeader = Piece( + pattern=( + r"\d+. %sCOVERAGE VIOLATIONS" + % ("NON-EXEMPTED " if xregions else "") + ), + pre=trTag, + ) self.__register(rpieces=[vioHeader]) @@ -224,18 +249,20 @@ def __setup_expectations(self, ntraces, xcovlevel, xregions): # depends on the xcov --level argument nexpected = 1 if crit in crit_for[xcovlevel] else 0 - vsHeader = Piece(pattern="%s COVERAGE" % crit, - nexpected=nexpected, - pre=pre if nexpected else None) + vsHeader = Piece( + pattern="%s COVERAGE" % crit, + nexpected=nexpected, + pre=pre if nexpected else None, + ) self.__register(rpieces=[vsHeader]) # If we do expect a section, add a pattern for the violation # counter and update the current pre chain reference. Unexpected # sections should be left out of that chain. if nexpected > 0: - vsCount = Piece(pattern="([0-9]+|No) violation", - nexpected=-1, - pre=vsHeader) + vsCount = Piece( + pattern="([0-9]+|No) violation", nexpected=-1, pre=vsHeader + ) self.__register(rpieces=[vsCount]) pre = vsCount @@ -243,10 +270,12 @@ def __setup_expectations(self, ntraces, xcovlevel, xregions): if xregions: xmrHeader = Piece(pattern="EXEMPTED REGIONS", pre=pre) - xmrCount = Piece(pattern="([0-9]+|No) exempted region[s]*, " - "([0-9]+|No) exempted violation[s]*", - nexpected=-1, - pre=xmrHeader) + xmrCount = Piece( + pattern="([0-9]+|No) exempted region[s]*, " + "([0-9]+|No) exempted violation[s]*", + nexpected=-1, + pre=xmrHeader, + ) self.__register(rpieces=[xmrHeader, xmrCount]) pre = xmrCount @@ -259,17 +288,19 @@ def __setup_expectations(self, ntraces, xcovlevel, xregions): for crit in crit_for[xcovlevel]: sumLine = Piece( - pattern=("([0-9]+|No) %s%s violation" % - ("non-exempted " if xregions else "", crit)), - pre=pre) + pattern=( + "([0-9]+|No) %s%s violation" + % ("non-exempted " if xregions else "", crit) + ), + pre=pre, + ) self.__register(rpieces=[sumLine]) pre = sumLine if xregions: sumLine = Piece( - pattern="([0-9]+|No) exempted region", - nexpected=-1, - pre=pre) + pattern="([0-9]+|No) exempted region", nexpected=-1, pre=pre + ) self.__register(rpieces=[sumLine]) pre = sumLine @@ -279,9 +310,13 @@ def __setup_expectations(self, ntraces, xcovlevel, xregions): self.__register(rpieces=[rpEnd]) def __process_one_test(self, qde): - frame(text=("report check for xfile = %s\n" % qde.xfile - + "drivers = %s" % str(qde.drivers)), - char='~').display() + frame( + text=( + "report check for xfile = %s\n" % qde.xfile + + "drivers = %s" % str(qde.drivers) + ), + char="~", + ).display() # Count the number of expected exemption regions xregions = 0 @@ -293,15 +328,17 @@ def __process_one_test(self, qde): # applicable xcov-level self.__setup_expectations( ntraces=len(qde.drivers), - xcovlevel=SCOV_helper.xcovlevel_for(self.tc, - os.path.basename - (qde.wdir)), - xregions=xregions) + xcovlevel=SCOV_helper.xcovlevel_for( + self.tc, os.path.basename(qde.wdir) + ), + xregions=xregions, + ) reports = ls(os.path.join(qde.wdir, "test.rep")) - thistest.fail_if(len(reports) != 1, - "expected 1 report, found %d" % len(reports)) + thistest.fail_if( + len(reports) != 1, "expected 1 report, found %d" % len(reports) + ) self.report = Tfile(reports[0], self.__process_line) for rpe in self.rpElements: diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index 1c8a7b375..376ada6b8 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -27,8 +27,10 @@ from e3.fs import ls -from SCOV.internals.driver import (SCOV_helper_bin_traces, - SCOV_helper_src_traces) +from SCOV.internals.driver import ( + SCOV_helper_bin_traces, + SCOV_helper_src_traces, +) from SCOV.internals.driver import WdirControl from SCOV.tctl import CAT from SUITE.context import thistest @@ -37,7 +39,6 @@ class TestCase: - # Helpers for __init__ def __expand_drivers(self, patterns): @@ -59,8 +60,9 @@ def __with_extensions(self, pattern): # We expect .adb for Ada bodies, .c for C sources and .cpp # for C++ sources. - return ' '.join( - "%s%s" % (pattern, ext) for ext in [".adb", ".c", ".cpp"]) + return " ".join( + "%s%s" % (pattern, ext) for ext in [".adb", ".c", ".cpp"] + ) def __expand_shared_controllers(self, drivers, cspecs): """Search and expand possible shared drivers and/or consolidation @@ -75,11 +77,14 @@ def __expand_shared_controllers(self, drivers, cspecs): # possible lists of drivers (each maybe empty). Beware not to include # child or sub units, as these dont mirror as such in the set of test # drivers. - sxx = set(srcmatch.group(1) - for srcmatch in (re.match(r"([a-z_]*).*\.(adb|c)", - os.path.basename(src)) - for src in ls("src/*")) - if srcmatch) + sxx = set( + srcmatch.group(1) + for srcmatch in ( + re.match(r"([a-z_]*).*\.(adb|c)", os.path.basename(src)) + for src in ls("src/*") + ) + if srcmatch + ) # If there is no candidate body in src/, arrange to run all the # drivers. This is useful for test groups on GPR variations for @@ -93,10 +98,11 @@ def __expand_shared_controllers(self, drivers, cspecs): if drivers: self.__expand_drivers( self.__with_extensions( - "%ssrc/test_%s*" % (prefix, body))) + "%ssrc/test_%s*" % (prefix, body) + ) + ) if cspecs: - self.__expand_cspecs( - "%ssrc/cons_%s*.txt" % (prefix, body)) + self.__expand_cspecs("%ssrc/cons_%s*.txt" % (prefix, body)) def __category_from_dir(self): """Compute test category from directory location.""" @@ -106,8 +112,9 @@ def __category_from_dir(self): if re.search(r"/%s" % cat.name, test_dir): return cat - raise FatalError("Unable to infer test category from subdir '%s'" - % test_dir) + raise FatalError( + "Unable to infer test category from subdir '%s'" % test_dir + ) def __drivers_from(self, cspec): """ @@ -123,8 +130,14 @@ def __drivers_from(self, cspec): # match this expression return [drv for drv in self.all_drivers if re.search(drv_expr, drv)] - def __init__(self, extradrivers="", extracargs="", category=CAT.auto, - tolerate_messages=None, assert_lvl=None): + def __init__( + self, + extradrivers="", + extracargs="", + category=CAT.auto, + tolerate_messages=None, + assert_lvl=None, + ): # By default, these test cases expect no error from subprocesses (xrun, # xcov, etc.) self.expect_failures = False @@ -143,13 +156,16 @@ def __init__(self, extradrivers="", extracargs="", category=CAT.auto, # exercise at all self.all_drivers = [] self.__expand_drivers( - self.__with_extensions("src/test_*") + " " + extradrivers) + self.__with_extensions("src/test_*") + " " + extradrivers + ) if not self.all_drivers: self.__expand_shared_controllers(drivers=True, cspecs=False) - thistest.stop_if(not self.all_drivers, - FatalError("Request to exercise empty test_set")) + thistest.stop_if( + not self.all_drivers, + FatalError("Request to exercise empty test_set"), + ) # Seek consolidation specs, then. Similar scheme, local check first, # then seek shared entities @@ -167,9 +183,9 @@ def __init__(self, extradrivers="", extracargs="", category=CAT.auto, # If automatic detection from subdir was requested, do that. # Otherwise, use the provided argument, which might be None or a # criterion related value. - self.category = (self.__category_from_dir() - if category == CAT.auto else - category) + self.category = ( + self.__category_from_dir() if category == CAT.auto else category + ) self.assert_lvl = assert_lvl @@ -198,11 +214,10 @@ def __xcovlevels(self): default_xcovlevels_for = { # Tests without categories should be ready for anything. # Exercise with the strictest possible mode: - None: ["stmt+mcdc"], - - CAT.stmt: ["stmt"], + None: ["stmt+mcdc"], + CAT.stmt: ["stmt"], CAT.decision: ["stmt+decision"], - CAT.mcdc: ["stmt+mcdc", "stmt+uc_mcdc"], + CAT.mcdc: ["stmt+mcdc", "stmt+uc_mcdc"], } # Add a "+" before the name of the assertion coverage level in order @@ -218,9 +233,13 @@ def __register_qde_for(self, drvo): executed. """ self.qdata.register( - QDentry(xfile=drvo.xfile, - drivers=drvo.drivers, xrnotes=drvo.xrnotes, - wdir=os.path.normpath(drvo.awdir()))) + QDentry( + xfile=drvo.xfile, + drivers=drvo.drivers, + xrnotes=drvo.xrnotes, + wdir=os.path.normpath(drvo.awdir()), + ) + ) def __run_one_covlevel(self, covlevel, covcontrol, subdirhint): """ @@ -230,22 +249,32 @@ def __run_one_covlevel(self, covlevel, covcontrol, subdirhint): """ this_scov_helper = ( - SCOV_helper_bin_traces if thistest.options.trace_mode == 'bin' - else SCOV_helper_src_traces if thistest.options.trace_mode == 'src' - else None) + SCOV_helper_bin_traces + if thistest.options.trace_mode == "bin" + else SCOV_helper_src_traces + if thistest.options.trace_mode == "src" + else None + ) # Compute the Working directory base for this level, then run the test # for each indivdual driver. this_wdbase = this_scov_helper.wdbase_for(self, covlevel) - wdctl = WdirControl(wdbase=this_wdbase, bdbase=self._available_bdbase, - subdirhint=subdirhint) + wdctl = WdirControl( + wdbase=this_wdbase, + bdbase=self._available_bdbase, + subdirhint=subdirhint, + ) for driver in self.all_drivers: - drvo = this_scov_helper(self, drivers=[driver], - xfile=driver, - xcovlevel=covlevel, covctl=covcontrol, - wdctl=wdctl) + drvo = this_scov_helper( + self, + drivers=[driver], + xfile=driver, + xcovlevel=covlevel, + covctl=covcontrol, + wdctl=wdctl, + ) self.__register_qde_for(drvo) drvo.run() @@ -254,14 +283,21 @@ def __run_one_covlevel(self, covlevel, covcontrol, subdirhint): self._available_bdbase = this_wdbase # Next, run applicable consolidation tests - wdctl = WdirControl(wdbase=this_wdbase, bdbase=self._available_bdbase, - subdirhint=subdirhint) + wdctl = WdirControl( + wdbase=this_wdbase, + bdbase=self._available_bdbase, + subdirhint=subdirhint, + ) for cspec in self.all_cspecs: - drvo = this_scov_helper(self, drivers=self.__drivers_from(cspec), - xfile=cspec, - xcovlevel=covlevel, covctl=covcontrol, - wdctl=wdctl) + drvo = this_scov_helper( + self, + drivers=self.__drivers_from(cspec), + xfile=cspec, + xcovlevel=covlevel, + covctl=covcontrol, + wdctl=wdctl, + ) self.__register_qde_for(drvo) drvo.run() @@ -283,9 +319,11 @@ def run(self, covcontrol=None, subdirhint=""): # the binaries together with the other artifacts is convenient. self._available_bdbase = None for covlevel in self.__xcovlevels(): - self.__run_one_covlevel(covlevel=covlevel, - covcontrol=covcontrol, - subdirhint=subdirhint) + self.__run_one_covlevel( + covlevel=covlevel, + covcontrol=covcontrol, + subdirhint=subdirhint, + ) finally: # If we are running for qualification purposes, dump data needed # for qualification test-results production purposes. try/finally diff --git a/testsuite/SCOV/tctl.py b/testsuite/SCOV/tctl.py index 59db8d785..89add4ab5 100644 --- a/testsuite/SCOV/tctl.py +++ b/testsuite/SCOV/tctl.py @@ -28,8 +28,17 @@ class CovControl: (covoptions). """ - def __init__(self, deps=(), units_in=None, ulist_in=None, units_out=None, - ulist_out=None, xreports=None, gprsw=None, covoptions=''): + def __init__( + self, + deps=(), + units_in=None, + ulist_in=None, + units_out=None, + ulist_out=None, + xreports=None, + gprsw=None, + covoptions="", + ): # To control "with" dependencies (set of projects that will be withed # by the one we will be generating for the testcase): self.deps = list(deps) @@ -64,8 +73,7 @@ def __init__(self, deps=(), units_in=None, ulist_in=None, units_out=None, self.xreports = xreports def unexpected(self, source): - return (self.xreports is not None and - source not in self.xreports) + return self.xreports is not None and source not in self.xreports def expected(self, source): return not self.unexpected(source) @@ -75,22 +83,26 @@ def requires_gpr(self): Whether honoring this control object implictly requires the use of a project file. """ - return (self.deps - or self.gprsw - or self.units_in is not None - or self.units_out is not None - or self.ulist_in is not None - or self.ulist_out is not None) + return ( + self.deps + or self.gprsw + or self.units_in is not None + or self.units_out is not None + or self.ulist_in is not None + or self.ulist_out is not None + ) def gpr(self): """ The GPR Coverage package corresponding to our lists of attribute contents, as a multiline string. """ - return gprcov_for(units_in=self.units_in, - units_out=self.units_out, - ulist_in=self.ulist_in, - ulist_out=self.ulist_out) + return gprcov_for( + units_in=self.units_in, + units_out=self.units_out, + ulist_in=self.ulist_in, + ulist_out=self.ulist_out, + ) class _Category: @@ -99,6 +111,7 @@ class _Category: A specific category tells the testsuite engine which coverage notes are relevant for a testcase execution. """ + def __init__(self, name): self.name = name @@ -111,12 +124,12 @@ class CAT: """ # Set of criteria related categories - stmt = _Category(name='stmt') - decision = _Category(name='decision') - mcdc = _Category(name='mcdc') + stmt = _Category(name="stmt") + decision = _Category(name="decision") + mcdc = _Category(name="mcdc") critcats = (stmt, decision, mcdc) # Special value asking to determine the category from the Testcase # location (relative pathname from the testsuite root) - auto = _Category(name='auto') + auto = _Category(name="auto") diff --git a/testsuite/STR/conf.py b/testsuite/STR/conf.py index d55f8b618..516437106 100644 --- a/testsuite/STR/conf.py +++ b/testsuite/STR/conf.py @@ -19,11 +19,13 @@ common_file = os.path.join( os.path.dirname( - os.path.dirname( - os.path.dirname( - os.path.abspath(__file__)))), + os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + ), "gnatcoverage-git-clone", - "qualification", "qm", "common_conf.py") + "qualification", + "qm", + "common_conf.py", +) if os.path.isfile(common_file): exec(open(common_file).read()) @@ -35,189 +37,204 @@ # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +# sys.path.insert(0, os.path.abspath('.')) # -- General configuration ----------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix of source filenames. -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'content' +master_doc = "content" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. -#language = None +# language = None # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = [] # The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True +# add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. pygments_style = None # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # -- Options for HTML output --------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'default' +html_theme = "default" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] +# html_theme_path = [] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". html_title = "%s Verification and Validation Results" % project_name # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (within the static path) to use as favicon of the # docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'GNATcoveragedoc' +htmlhelp_basename = "GNATcoveragedoc" # -- Options for LaTeX output -------------------------------------------------- # The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' +# latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' +# latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, author, documentclass [howto/manual]). latex_documents = [ - ('content', 'STR.tex', u'GNATcoverage DO-178C/ED-12C Qualification Material: %s' % doc_standard_name, - u'AdaCore', 'manual'), + ( + "content", + "STR.tex", + "GNATcoverage DO-178C/ED-12C Qualification Material: %s" + % doc_standard_name, + "AdaCore", + "manual", + ), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Additional stuff for the LaTeX preamble, in the QM fashion doc_id = str_doc_id + def project_settings(): full_document_name = project_name if doc_id is not None and len(doc_id) > 0: - full_document_name = '%s - %s' % (project_name, doc_id) - - return '\n'.join([ - r'\newcommand*{\QMFullDocumentName}[0]{' + full_document_name + r'}', - r'\newcommand*{\QMProjectName}[0]{' + project_name + r'}', - r'\newcommand*{\QMDocID}[0]{' + doc_id + r'}', - r'\newcommand*{\QMVersion}[0]{' + version + r'}']) - -latex_preamble = project_settings() + r""" + full_document_name = "%s - %s" % (project_name, doc_id) + + return "\n".join( + [ + r"\newcommand*{\QMFullDocumentName}[0]{" + + full_document_name + + r"}", + r"\newcommand*{\QMProjectName}[0]{" + project_name + r"}", + r"\newcommand*{\QMDocID}[0]{" + doc_id + r"}", + r"\newcommand*{\QMVersion}[0]{" + version + r"}", + ] + ) + + +latex_preamble = ( + project_settings() + + r""" \RequirePackage{lastpage} \addtocontents{toc}{\protect\thispagestyle{mytoc}} @@ -307,13 +324,14 @@ def project_settings(): } \makeatother """ +) # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output -------------------------------------------- @@ -321,6 +339,5 @@ def project_settings(): # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('content', 'gnatcoverage', u'GNATcoverage Documentation', - [u'AdaCore'], 1) + ("content", "gnatcoverage", "GNATcoverage Documentation", ["AdaCore"], 1) ] diff --git a/testsuite/STR/genrest.py b/testsuite/STR/genrest.py index e94872fd0..b71a42806 100644 --- a/testsuite/STR/genrest.py +++ b/testsuite/STR/genrest.py @@ -21,8 +21,9 @@ # --testsuite-dir, though the two should be consistent wrt the python script # sources (e.g. the CTXdata structure must match) -LOCAL_TESTSUITE_DIR = \ - os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +LOCAL_TESTSUITE_DIR = os.path.dirname( + os.path.dirname(os.path.abspath(__file__)) +) sys.path.append(LOCAL_TESTSUITE_DIR) TEST_LOG = "test.py.log" @@ -35,9 +36,22 @@ from SUITE import dutils from SCOV.internals.cnotes import ( - r0, r0c, xBlock0, sNoCov, sPartCov, - dtNoCov, dfNoCov, dPartCov, dNoCov, etNoCov, efNoCov, ePartCov, - eNoCov, cPartCov, xBlock1) + r0, + r0c, + xBlock0, + sNoCov, + sPartCov, + dtNoCov, + dfNoCov, + dPartCov, + dNoCov, + etNoCov, + efNoCov, + ePartCov, + eNoCov, + cPartCov, + xBlock1, +) from SUITE.cutils import FatalError, lines_of from REST import rest @@ -62,6 +76,7 @@ def exit_if(p, msg): print(msg) sys.exit(1) + # ================================================ # == QDregistry - Qualification Data repository == # ================================================ @@ -83,7 +98,6 @@ def exit_if(p, msg): class QualificationDataRepository(object): - def __init__(self, testsuite_dir): """Initialize a Qualification Data repository. @@ -135,14 +149,17 @@ def load_test(self, dirname): tcdf = qdaf_in(dirname) qda = ( - dutils.pload_from(tcdf) if os.path.exists(tcdf) - else Qdata(tcid=dirname)) + dutils.pload_from(tcdf) + if os.path.exists(tcdf) + else Qdata(tcid=dirname) + ) qda.status = std.status qda.comment = std.comment self.qdl.append(qda) + # ======================================= # == Qualification report and helpers == # ======================================= @@ -156,7 +173,6 @@ def load_test(self, dirname): class Column(object): def __init__(self, htext, legend="", hidden=False): - # HTEXT is the column header text, # LEGEND is a brief description of the column contents, # HIDDEN tells if the column should not be displayed @@ -167,113 +183,104 @@ def __init__(self, htext, legend="", hidden=False): class colid(object): - # Testcase description and status, for testcase table - tc = Column( - htext="testcase", legend="Testcase Identifier") + tc = Column(htext="testcase", legend="Testcase Identifier") - sta = Column( - htext="status", - legend="Execution status" - ) + sta = Column(htext="status", legend="Execution status") - cat = Column( - htext="Test category", legend="Test category") + cat = Column(htext="Test category", legend="Test category") # Expectation counters, for testcase table and counters summary nov = Column( htext="nov", - legend="Number of expected absence of violations in testcase") + legend="Number of expected absence of violations in testcase", + ) scv = Column( htext="scv", - legend="Number of expected STATEMENT Coverage violations in testcase") + legend="Number of expected STATEMENT Coverage violations in testcase", + ) dcv = Column( htext="dcv", - legend="Number of expected DECISION Coverage violations in testcase") + legend="Number of expected DECISION Coverage violations in testcase", + ) mcv = Column( htext="mcv", - legend="Number of expected MCDC Coverage violations in testcase") + legend="Number of expected MCDC Coverage violations in testcase", + ) xbv = Column( htext="xbv", legend="Number of expected EXEMPTION " - "blocks with violations in testcase") + "blocks with violations in testcase", + ) - igv = Column( - htext="igv", legend="counters to be ignored", hidden=True) + igv = Column(htext="igv", legend="counters to be ignored", hidden=True) # Status counters and overall status, for status summary failed = Column( htext="failed", - legend="Number of tests with status *failed* in category") + legend="Number of tests with status *failed* in category", + ) passed = Column( htext="passed", - legend="Number of tests with status *passed* in category") + legend="Number of tests with status *passed* in category", + ) xfail = Column( - htext="xfail", - legend="Number of tests with status *xfail* in category") + htext="xfail", legend="Number of tests with status *xfail* in category" + ) ovsta = Column( htext="testsuite status", legend="Testsuite overall status, *passed* if all tests were " - "*passed* or *xfail*") + "*passed* or *xfail*", + ) # Other status counters - uok = Column( - htext="uok", legend="Test ran OK despite expected to fail") + uok = Column(htext="uok", legend="Test ran OK despite expected to fail") # Columns for legend sub-tables - colname = Column( - htext="column", legend=None) + colname = Column(htext="column", legend=None) + + legend = Column(htext="legend", legend=None) - legend = Column( - htext="legend", legend=None) # ------------------------------------ # -- Mappings to column identifiers -- # ------------------------------------ column_for = { - # When counting notes, map note kinds to table columns - r0: colid.nov, r0c: colid.igv, xBlock0: colid.nov, - sNoCov: colid.scv, sPartCov: colid.scv, - dtNoCov: colid.dcv, dfNoCov: colid.dcv, dPartCov: colid.dcv, dNoCov: colid.dcv, - etNoCov: colid.mcv, efNoCov: colid.mcv, ePartCov: colid.mcv, eNoCov: colid.mcv, cPartCov: colid.mcv, - xBlock1: colid.xbv, - # When checking status, map text passed by toplevel driver # to column. - - 'PASS': colid.passed, - 'XPASS': colid.passed, - 'FAIL': colid.failed, - 'XFAIL': colid.xfail, + "PASS": colid.passed, + "XPASS": colid.passed, + "FAIL": colid.failed, + "XFAIL": colid.xfail, } # ------------------------------- @@ -282,9 +289,9 @@ class colid(object): # Violation counters we care about for each possible do-level viocnt_columns_for = { - 'doA': (colid.nov, colid.igv, colid.scv, colid.dcv, colid.mcv, colid.xbv), - 'doB': (colid.nov, colid.igv, colid.scv, colid.dcv, colid.xbv), - 'doC': (colid.nov, colid.igv, colid.scv, colid.xbv) + "doA": (colid.nov, colid.igv, colid.scv, colid.dcv, colid.mcv, colid.xbv), + "doB": (colid.nov, colid.igv, colid.scv, colid.dcv, colid.xbv), + "doC": (colid.nov, colid.igv, colid.scv, colid.xbv), } # Status counters @@ -303,7 +310,6 @@ class colid(object): class CountersCell(object): - def __init__(self): self.expected = 0 self.satisfied = 0 @@ -318,18 +324,19 @@ def augment_by(self, other): self.expected += other.expected self.satisfied += other.satisfied + # Cell to hold a simple integer value # ----------------------------------- class IntCell(object): - def __init__(self, initval=0): self.value = initval def img(self, details=False): return "%d" % self.value + # Cell to hold a simple text # -------------------------- @@ -341,6 +348,7 @@ def __init__(self, text): def img(self, details=False): return "%s" % self.text + # Cell to hold a TC id in a context where the language # and test category are explicit by some other means # ----------------------------------------------------- @@ -351,7 +359,6 @@ def __init__(self, text): self.text = text def img(self, details=False): - # Arrange to strip: # # * The common leading part that can be inferred from the tc @@ -369,25 +376,27 @@ def img(self, details=False): # Applied in sequence and the order matters. re_strip = collections.OrderedDict( - ((QROOTDIR + "/", ""), - ("(Ada|C)/(stmt|decision|mcdc)/", ""), - ("Common/Report/", ""), - ("^[0-9]+_", ""), - ("/[0-9]+_", "/")) + ( + (QROOTDIR + "/", ""), + ("(Ada|C)/(stmt|decision|mcdc)/", ""), + ("Common/Report/", ""), + ("^[0-9]+_", ""), + ("/[0-9]+_", "/"), ) + ) img = self.text for r in re_strip: img = re.sub(pattern=r, repl=re_strip[r], string=img) return img + # Cell to hold a qualification status # ----------------------------------- class QstatusCell(object): def __init__(self, text): - # TEXT is the precise test execution status provided by the toplevel # driver (with uok, xfail, ...). Switch to the qualification status by # mapping to the status counter column. @@ -397,6 +406,7 @@ def __init__(self, text): def img(self, details=False): return "%s" % self.colid.htext + # ============= # == RSTfile == # ============= @@ -408,7 +418,7 @@ def __init__(self, filename): self.open(filename) def open(self, filename): - self.fd = open("source/" + filename, 'w') + self.fd = open("source/" + filename, "w") def write(self, text, pre=0, post=1): self.fd.write(rest.isolate(text=text, pre=pre, post=post)) @@ -416,15 +426,14 @@ def write(self, text, pre=0, post=1): def close(self): self.fd.close() + # ============== # == RSTtable == # ============== class RSTtable(object): - def __init__(self, title, text, columns, contents): - # COLUMNS is the list of columns for this table, CONTENTS is a # list of {col -> text} dictionaries, one per table line. Compared # to CONTENTS.keys(), COLUMNS is useful to enforce a column order. @@ -443,7 +452,6 @@ def __init__(self, title, text, columns, contents): self.text = text def __dump_description(self): - # Dump the table title, descriptive text and legend if self.title: @@ -458,12 +466,14 @@ def __dump_description(self): # as a (description-less) table itself ... ASCIItable( - title=None, text=None, + title=None, + text=None, columns=(colid.colname, colid.legend), contents=[ - {colid.colname: rest.emph(col.htext), - colid.legend: col.legend} for col in self.columns] - ).dump_to(self.rstf) + {colid.colname: rest.emph(col.htext), colid.legend: col.legend} + for col in self.columns + ], + ).dump_to(self.rstf) def __dump_contents(self): [self.dump_centry(ce) for ce in self.contents] @@ -486,7 +496,6 @@ def dump_footer(self): # ------------- def dump_to(self, rstf): - self.rstf = rstf self.__dump_description() @@ -507,33 +516,37 @@ def dump_to(self, rstf): class CSVtable(RSTtable): - - def __init__(self, title, text, columns, contents, - delim='&', controls=()): - + def __init__(self, title, text, columns, contents, delim="&", controls=()): self.controls = controls self.delim = delim RSTtable.__init__( - self, title=title, text=text, - columns=columns, contents=contents) + self, title=title, text=text, columns=columns, contents=contents + ) def dump_header(self): - text = '\n' + '\n'.join( - ['.. csv-table::', - ' :delim: ' + self.delim, - ' :header: %s' % " , ".join( - ['"%s"' % col.htext for col in self.columns]) - ] + [' ' + ctl for ctl in self.controls] - ) + "\n" + text = ( + "\n" + + "\n".join( + [ + ".. csv-table::", + " :delim: " + self.delim, + " :header: %s" + % " , ".join(['"%s"' % col.htext for col in self.columns]), + ] + + [" " + ctl for ctl in self.controls] + ) + + "\n" + ) self.rstf.write(text) def dump_centry(self, ce): entryl = (" %s " % self.delim).join( - [" %s" % ce[col] for col in self.columns]) + [" %s" % ce[col] for col in self.columns] + ) self.rstf.write(entryl) def dump_footer(self): - self.rstf.write('\n') + self.rstf.write("\n") # ================ @@ -551,43 +564,42 @@ def dump_footer(self): class ASCIItable(RSTtable): - def __init__(self, title, text, columns, contents): RSTtable.__init__( - self, title=title, text=text, - columns=columns, contents=contents) + self, title=title, text=text, columns=columns, contents=contents + ) self.__compute_widths() def __compute_widths(self): - # Compute the current width of every column, as the max of # all the texts (on every contents + header line) # This is useful to align the text of every column, for both # content rows and the ReST table separation lines. - self.width = dict( - [(col, 0) for col in self.columns]) + self.width = dict([(col, 0) for col in self.columns]) # Maximize column width over contents entries - [self.width.__setitem__( - col, max(self.width[col], len(centry[col]))) - for centry in self.contents for col in self.columns] + [ + self.width.__setitem__(col, max(self.width[col], len(centry[col]))) + for centry in self.contents + for col in self.columns + ] # Maximize column width with length of column header - [self.width.__setitem__( - col, max(self.width[col], len(col.htext))) - for col in self.columns] + [ + self.width.__setitem__(col, max(self.width[col], len(col.htext))) + for col in self.columns + ] def dump_header(self): - sepl = " ".join( - ["=" * self.width[col] for col in self.columns]) + sepl = " ".join(["=" * self.width[col] for col in self.columns]) headl = " ".join( - ["%-*s" % (self.width[col], col.htext) - for col in self.columns]) + ["%-*s" % (self.width[col], col.htext) for col in self.columns] + ) self.rstf.write(sepl) self.rstf.write(headl) @@ -595,12 +607,12 @@ def dump_header(self): def dump_centry(self, ce): entryl = " ".join( - ["%-*s" % (self.width[col], ce[col]) for col in self.columns]) + ["%-*s" % (self.width[col], ce[col]) for col in self.columns] + ) self.rstf.write(entryl) def dump_footer(self): - sepl = " ".join( - ["=" * self.width[col] for col in self.columns]) + sepl = " ".join(["=" * self.width[col] for col in self.columns]) self.rstf.write(sepl, post=2) @@ -635,27 +647,29 @@ def dump_footer(self): class LISTtable(RSTtable): - def __init__(self, title, text, columns, contents): RSTtable.__init__( - self, title=title, text=text, - columns=columns, contents=contents) + self, title=title, text=text, columns=columns, contents=contents + ) def dump_header(self): - self.rstf.write('.. list-table::') - self.rstf.write(' :header-rows: 1', post=2) + self.rstf.write(".. list-table::") + self.rstf.write(" :header-rows: 1", post=2) - self.rstf.write(' * ' + "\n ".join( - ["- %s" % col.htext for col in self.columns] - )) + self.rstf.write( + " * " + + "\n ".join(["- %s" % col.htext for col in self.columns]) + ) def dump_centry(self, ce): - self.rstf.write(' * ' + "\n ".join( - ["- %s" % ce[col] for col in self.columns] - )) + self.rstf.write( + " * " + + "\n ".join(["- %s" % ce[col] for col in self.columns]) + ) def dump_footer(self): - self.rstf.write('\n', post=2) + self.rstf.write("\n", post=2) + # ============== # == QDreport == @@ -690,35 +704,34 @@ def trymatch(self, qda): class QDreport(object): - def __init__(self, options): - self.o = options # Fetch the testsuite execution context self.suitedata = dutils.jload_from( - os.path.join(self.o.testsuite_dir, CTXDATA_FILE)) + os.path.join(self.o.testsuite_dir, CTXDATA_FILE) + ) # Pick the testsuite dolevel if none was provided. Check # consistency otherwise: - suite_dolevel = self.suitedata['options']['dolevel'] + suite_dolevel = self.suitedata["options"]["dolevel"] fail_if( not suite_dolevel, - "Testsuite at %s was not run in qualification mode" % ( - self.o.testsuite_dir) - ) + "Testsuite at %s was not run in qualification mode" + % (self.o.testsuite_dir), + ) if self.o.dolevel is None: self.o.dolevel = suite_dolevel else: fail_if( self.o.dolevel != suite_dolevel, - "explicit dolevel (%s) doesn't match testsuite (%s)" % ( - self.o.dolevel, suite_dolevel) - ) + "explicit dolevel (%s) doesn't match testsuite (%s)" + % (self.o.dolevel, suite_dolevel), + ) # Setup the list of violation counters we care about wrt the # targetted do-level: @@ -737,34 +750,41 @@ def __init__(self, options): # categories from common ones. lang_categories = [ - (Category( - lang=lang, name="%s STATEMENT Coverage" % lang, - matcher="%s/%s/stmt" % (QROOTDIR, lang)), - Category( - lang=lang, name="%s DECISION Coverage" % lang, - matcher="%s/%s/decision" % (QROOTDIR, lang)), - Category( - lang=lang, name="%s MCDC Coverage" % lang, - matcher="%s/%s/mcdc" % (QROOTDIR, lang)) - ) for lang in QLANGUAGES - ] + ( + Category( + lang=lang, + name="%s STATEMENT Coverage" % lang, + matcher="%s/%s/stmt" % (QROOTDIR, lang), + ), + Category( + lang=lang, + name="%s DECISION Coverage" % lang, + matcher="%s/%s/decision" % (QROOTDIR, lang), + ), + Category( + lang=lang, + name="%s MCDC Coverage" % lang, + matcher="%s/%s/mcdc" % (QROOTDIR, lang), + ), + ) + for lang in QLANGUAGES + ] lang_categories = [ - cat for lang_cats in lang_categories for cat in lang_cats] + cat for lang_cats in lang_categories for cat in lang_cats + ] other_categories = [ Category( - name="REPORT Format", - matcher="%s/Common/Report" % QROOTDIR), - + name="REPORT Format", matcher="%s/Common/Report" % QROOTDIR + ), Category( name="Testsuite Selftest", matcher="%s/Appendix/Testsuite" % QROOTDIR, - internal=True), - - Category( - name="Others", matcher=".") - ] + internal=True, + ), + Category(name="Others", matcher="."), + ] self.categories = lang_categories + other_categories @@ -774,18 +794,19 @@ def __init__(self, options): # were run). This is useful e.g. to decide which sets of compilation # options should be displayed in the environment description items. - self.languages = set( - [cat.lang for cat in lang_categories if cat.qdl]) + self.languages = set([cat.lang for cat in lang_categories if cat.qdl]) - self.dump_trigger=None - self.dump_channel=None + self.dump_trigger = None + self.dump_channel = None # Gather effectively used dump-trigger and dump channel from the logs # in source trace mode. if self.suitedata["options"]["trace_mode"] == "src": - self.dump_trigger, self.dump_channel = \ - self.gather_trigger_and_channel() + ( + self.dump_trigger, + self.dump_channel, + ) = self.gather_trigger_and_channel() self.gen_envinfo(sepfile="env.rst") @@ -812,25 +833,23 @@ def _check_one_dump_option(self, line, option_name, current_value): """ if "gnatcov instrument" in line: matcher = re.search( - pattern=f"--dump-{option_name}" + r"(?:=| )(\S*) ", - string=line + pattern=f"--dump-{option_name}" + r"(?:=| )(\S*) ", string=line ) if matcher is None: - raise FatalError ( + raise FatalError( comment=f"Found no dump {option_name} in gnatcov" - f"instrument command line: {line}" + f"instrument command line: {line}" ) if current_value and matcher.group(1) != current_value: - raise FatalError ( + raise FatalError( comment=f"Inconsistent dump {option_name} found:" - f" got {matcher.group(1)}" - f" but expected {current_value}" + f" got {matcher.group(1)}" + f" but expected {current_value}" ) return matcher.group(1) else: return current_value - def gather_trigger_and_channel(self): """ Inspect all test.py.log files to determine which dump trigger and @@ -840,22 +859,22 @@ def gather_trigger_and_channel(self): """ current_dt = None current_dc = None - for p in find (self.o.testsuite_dir, TEST_LOG): + for p in find(self.o.testsuite_dir, TEST_LOG): for line in lines_of(p): current_dt = self._check_one_dump_option( - line, "trigger", current_dt) + line, "trigger", current_dt + ) current_dc = self._check_one_dump_option( - line, "channel", current_dc) + line, "channel", current_dc + ) return (current_dt, current_dc) - def categorize(self, qda): for cat in self.categories: if cat.trymatch(qda): return - raise FatalError( - comment="unable to categorize testcase %s" % qda.tcid) + raise FatalError(comment="unable to categorize testcase %s" % qda.tcid) # -------------------- # -- compute_tcdata -- @@ -882,26 +901,27 @@ def count(self, note, cell): cell.satisfied += 1 def tcdata_for(self, qd): - # Process one qualification data item, producing a report data line # for one testcase this_tcdata = dict( - [(colid.tc, TcidCell(qd.tcid))] + - [(key, CountersCell()) for key in self.viocnt_columns] + - [(colid.sta, QstatusCell(qd.status))] - ) - - [self.count(note=note, cell=this_tcdata[column_for[note.kind]]) - for qde in qd.entries for src in qde.xrnotes - for notelist in qde.xrnotes[src].values() - for note in notelist] + [(colid.tc, TcidCell(qd.tcid))] + + [(key, CountersCell()) for key in self.viocnt_columns] + + [(colid.sta, QstatusCell(qd.status))] + ) + + [ + self.count(note=note, cell=this_tcdata[column_for[note.kind]]) + for qde in qd.entries + for src in qde.xrnotes + for notelist in qde.xrnotes[src].values() + for note in notelist + ] return this_tcdata def compute_tcdata(self): - self.tcdata = dict( - [(qd, self.tcdata_for(qd)) for qd in self.qdl]) + self.tcdata = dict([(qd, self.tcdata_for(qd)) for qd in self.qdl]) # ------------------ # -- gen_tctables -- @@ -917,18 +937,19 @@ def compute_tcdata(self): # =========== ======== ======== ... ======= def tcdict_for(self, qd): - # Arrange to provide details on the expected versus satisfied # violation counts only when the test has failed somehow: details = column_for[qd.status] != colid.passed return dict( - [(col, "%s" % self.tcdata[qd][col].img(details)) - for col in self.tcdata[qd]]) + [ + (col, "%s" % self.tcdata[qd][col].img(details)) + for col in self.tcdata[qd] + ] + ) def gen_tctables(self, sepfile=None): - if sepfile: self.rstf = RSTfile(sepfile) @@ -977,18 +998,21 @@ def gen_tctables(self, sepfile=None): "\n\n" "A general summary of all the results is provided in the " ":ref:`tssummary` section of this report.\n" - ), + ), columns=self.tccolumns(), contents=None, - ).dump_to(self.rstf) + ).dump_to(self.rstf) - [LISTtable( + [ + LISTtable( title=("%s tests [ %s/... ]" % (cat.name, cat.qmprefix)), text=None, columns=self.tccolumns(), - contents=[self.tcdict_for(qd) for qd in cat.qdl] - ).dump_to(self.rstf) - for cat in self.categories if cat.qdl and not cat.internal] + contents=[self.tcdict_for(qd) for qd in cat.qdl], + ).dump_to(self.rstf) + for cat in self.categories + if cat.qdl and not cat.internal + ] if sepfile: self.rstf.close() @@ -1010,29 +1034,31 @@ def gen_tctables(self, sepfile=None): def sumcolumns(self): return ( - (colid.cat,) # category - + stacnt_columns # #passed, #failed, #xfail - + self.viocnt_columns # nov, scv, ... - + (colid.ovsta,)) # testsuite status + (colid.cat,) # category + + stacnt_columns # #passed, #failed, #xfail + + self.viocnt_columns # nov, scv, ... + + (colid.ovsta,) + ) # testsuite status def init_data_for(self, catid): - # Initial data for the line corresponding to category CATID. The # overall status column is set separately, once the final counter # values are known return dict( - [(colid.cat, TextCell(catid))] + - [(col, IntCell()) for col in stacnt_columns] + - [(col, CountersCell()) for col in self.viocnt_columns]) + [(colid.cat, TextCell(catid))] + + [(col, IntCell()) for col in stacnt_columns] + + [(col, CountersCell()) for col in self.viocnt_columns] + ) def do_sum(self, qd, catsum): - [catsum[key].augment_by(self.tcdata[qd][key]) - for key in self.viocnt_columns] + [ + catsum[key].augment_by(self.tcdata[qd][key]) + for key in self.viocnt_columns + ] catsum[column_for[qd.status]].value += 1 def sumdata_for(self, cat, totsum): - # Compute the summary data for category CAT, and accumulate # into the TOTSUM total summary along the way @@ -1049,16 +1075,19 @@ def sumdata_for(self, cat, totsum): # TOTSUM summary and return thissum.__setitem__( - colid.ovsta, TextCell( - "%s" % "passed" if thissum[colid.failed].value == 0 - else "failed")) + colid.ovsta, + TextCell( + "%s" % "passed" + if thissum[colid.failed].value == 0 + else "failed" + ), + ) [self.do_sum(qd=qd, catsum=totsum) for qd in cat.qdl] return thissum def sumdata(self): - # Compute the base data for the summary table. This is a list of # {colid -> Cell} dictionaries, with one list entry for each test # category + a total. Something like @@ -1074,28 +1103,38 @@ def sumdata(self): totsum = self.init_data_for("Total") catsums = [ - csum for csum in [self.sumdata_for(cat, totsum) - for cat in self.categories if cat.qdl] - if csum] + csum + for csum in [ + self.sumdata_for(cat, totsum) + for cat in self.categories + if cat.qdl + ] + if csum + ] totsum.__setitem__( - colid.ovsta, TextCell( - "%s" % "PASSED" if totsum[colid.failed].value == 0 - else "FAILED")) + colid.ovsta, + TextCell( + "%s" % "PASSED" + if totsum[colid.failed].value == 0 + else "FAILED" + ), + ) return catsums + [totsum] def sumcontents(self): - # Compute the list of { colid -> text } dictionaries for the summary # table, with a list entry for each test category (+ total) - return [dict([(col, "%s" % catsum[col].img()) - for col in self.sumcolumns()]) - for catsum in self.sumdata()] + return [ + dict( + [(col, "%s" % catsum[col].img()) for col in self.sumcolumns()] + ) + for catsum in self.sumdata() + ] def gen_tssummary(self, sepfile): - if sepfile: self.rstf = RSTfile(sepfile) @@ -1110,8 +1149,8 @@ def gen_tssummary(self, sepfile): "refer to the :ref:`tctable` section of this report for an " "explanation of the legend. ", columns=self.sumcolumns(), - contents=self.sumcontents() - ).dump_to(self.rstf) + contents=self.sumcontents(), + ).dump_to(self.rstf) if sepfile: self.rstf.close() @@ -1121,7 +1160,6 @@ def gen_tssummary(self, sepfile): # ----------------------------- def gen_suite_options(self): - def literal(text): return ":literal:`" + text.strip() + "`" @@ -1137,7 +1175,7 @@ def str_relevant_switches_from(switches_string): if skip: skip = False continue - elif sw in ('--log-file', '--old-res'): + elif sw in ("--log-file", "--old-res"): skip = True continue else: @@ -1150,8 +1188,8 @@ def switches_with_eq_from(switches_string): of the form = in SWITCHES_STRING.""" return dict( - [sw.split('=') for - sw in switches_string.split() if '=' in sw]) + [sw.split("=") for sw in switches_string.split() if "=" in sw] + ) itemno = Column(htext="Item #", legend=None) @@ -1170,42 +1208,52 @@ def switches_with_eq_from(switches_string): # - BUILDER.SCOV_CARGS (e.g. -fdump-scos), # - --cargs family - suite_options = self.suitedata['options'] - suite_cmdline = self.suitedata['cmdline'] + suite_options = self.suitedata["options"] + suite_cmdline = self.suitedata["cmdline"] csv_contents = [] # Filter from the command line switches which have no # qualification context value per se and would display badly # within the table. - suite_cmdline = ' '.join( - str_relevant_switches_from(suite_cmdline)) + suite_cmdline = " ".join(str_relevant_switches_from(suite_cmdline)) csv_contents.append( - {itemno: "N/A", - item: "testsuite execution command line", - value: literal(suite_cmdline) - }) + { + itemno: "N/A", + item: "testsuite execution command line", + value: literal(suite_cmdline), + } + ) csv_contents.append( - {itemno: "s1", - item: "compiler switches - language independent", - value: literal(' '.join( - BUILDER.SCOV_CARGS( - collections.namedtuple( - 'SuiteOptions', suite_options.keys()) - (*suite_options.values())) + - [suite_options['cargs']])) - }) + { + itemno: "s1", + item: "compiler switches - language independent", + value: literal( + " ".join( + BUILDER.SCOV_CARGS( + collections.namedtuple( + "SuiteOptions", suite_options.keys() + )(*suite_options.values()) + ) + + [suite_options["cargs"]] + ) + ), + } + ) for lang in self.languages: lang_cargs = suite_options["cargs_%s" % lang] if lang_cargs: csv_contents.append( - {itemno: "s1", - item: "compiler switches - %s specific" % lang, - value: literal(lang_cargs)}) + { + itemno: "s1", + item: "compiler switches - %s specific" % lang, + value: literal(lang_cargs), + } + ) # If we have a -gnatec=bla.adc in the languages cargs, # arrange to dump the contents of bla.adc within a separate @@ -1219,50 +1267,63 @@ def switches_with_eq_from(switches_string): # command line is relative to the testsuite/ subdirectory. # We're call within the STR subdir so ... - with open("../%s" % adc, 'r') as f: + with open("../%s" % adc, "r") as f: adc_contents = f.read().strip() csv_contents.append( - {itemno: "s1", - item: "contents of %s, designated by -gnatec" % adc, - value: (literal(adc_contents) if adc_contents - else rest.emph("empty"))}) + { + itemno: "s1", + item: "contents of %s, designated by -gnatec" % adc, + value: ( + literal(adc_contents) + if adc_contents + else rest.emph("empty") + ), + } + ) # If we have a --RTS=bla on the command line, display it as the # qualification "runtime profile". opts_with_eq = switches_with_eq_from(suite_cmdline) - rts = opts_with_eq.get('--RTS', None) + rts = opts_with_eq.get("--RTS", None) csv_contents.append( - {itemno: "s2", - item: "runtime profile", - value: literal( - ("--RTS=%s" % rts)) if rts - else rest.emph("no --RTS switch")}) + { + itemno: "s2", + item: "runtime profile", + value: literal(("--RTS=%s" % rts)) + if rts + else rest.emph("no --RTS switch"), + } + ) if self.dump_trigger: csv_contents.append( - {itemno: "s3", - item: "GNATcov dump trigger option value", - value: literal (f"--dump-trigger={self.dump_trigger}") - }) + { + itemno: "s3", + item: "GNATcov dump trigger option value", + value: literal(f"--dump-trigger={self.dump_trigger}"), + } + ) if self.dump_channel: csv_contents.append( - {itemno: "s4", - item: "GNATcov dump channel option value", - value: literal(f"--dump-channel={self.dump_channel}") - }) + { + itemno: "s4", + item: "GNATcov dump channel option value", + value: literal(f"--dump-channel={self.dump_channel}"), + } + ) CSVtable( - title=None, text=None, + title=None, + text=None, columns=(itemno, item, value), controls=[":widths: 7, 30, 60"], - contents=csv_contents - ).dump_to(self.rstf) + contents=csv_contents, + ).dump_to(self.rstf) def gen_suite_environ(self): - # We construct a table like # # Environment item | | @@ -1279,63 +1340,72 @@ def gen_suite_environ(self): v2 = Column(htext="", legend=None) - suite_gnatpro = self.suitedata['gnatpro'] - suite_gnatcov = self.suitedata['gnatcov'] - suite_gnatemu = self.suitedata['gnatemu'] - suite_other = self.suitedata['other'] + suite_gnatpro = self.suitedata["gnatpro"] + suite_gnatcov = self.suitedata["gnatcov"] + suite_gnatemu = self.suitedata["gnatemu"] + suite_other = self.suitedata["other"] # Base table entries, always there: table_entries = [ - {itemno: "e1", - item: "testsuite execution timestamp & host system", - v1: self.suitedata['runstamp'], - v2: self.suitedata['host'] - }, - {itemno: "e2", - item: "GNATcov executable & version", - v1: suite_gnatcov['exename'], - v2: suite_gnatcov['version'] - }, - {itemno: "e3", - item: "GNAT Pro executable & version", - v1: suite_gnatpro['exename'], - v2: suite_gnatpro['version'] - }, - ] + { + itemno: "e1", + item: "testsuite execution timestamp & host system", + v1: self.suitedata["runstamp"], + v2: self.suitedata["host"], + }, + { + itemno: "e2", + item: "GNATcov executable & version", + v1: suite_gnatcov["exename"], + v2: suite_gnatcov["version"], + }, + { + itemno: "e3", + item: "GNAT Pro executable & version", + v1: suite_gnatpro["exename"], + v2: suite_gnatpro["version"], + }, + ] # Add a gnatemu version, unless known to be irrelevant (native, # or when a --board option is passed). - suite_options = self.suitedata['options'] - if suite_options['target'] and not suite_options['board']: + suite_options = self.suitedata["options"] + if suite_options["target"] and not suite_options["board"]: table_entries.append( - {itemno: "e4", - item: "GNATemu executable & version", - v1: suite_gnatemu['exename'], - v2: suite_gnatemu['version']}) + { + itemno: "e4", + item: "GNATemu executable & version", + v1: suite_gnatemu["exename"], + v2: suite_gnatemu["version"], + } + ) # Add the "other tool" version if we have it if suite_other: table_entries.append( - {itemno: "e5", - item: "Other toolset executable & version", - v1: suite_other['exename'], - v2: suite_other['version']}) + { + itemno: "e5", + item: "Other toolset executable & version", + v1: suite_other["exename"], + v2: suite_other["version"], + } + ) CSVtable( - title=None, text=None, + title=None, + text=None, columns=(itemno, item, v1, v2), controls=[":widths: 7, 25, 20, 48"], - delim='|', - contents=table_entries - ).dump_to(self.rstf) + delim="|", + contents=table_entries, + ).dump_to(self.rstf) # ??? qemu-system-ppc ??? def gen_envinfo(self, sepfile=None): - if sepfile: self.rstf = RSTfile(sepfile) @@ -1353,33 +1423,39 @@ def gen_envinfo(self, sepfile=None): # --------------- def gen_index(self, sepfiles): - self.rstf = RSTfile("index.rst") - self.rstf.write(rest.chapter('GNATcoverage Software Test Results')) + self.rstf.write(rest.chapter("GNATcoverage Software Test Results")) self.rstf.write(rest.toctree(sepfiles, depth=1)) self.rstf.close() + # ====================== # == main entry point == # ====================== -valid_dolevels = ('doA', 'doB', 'doC') +valid_dolevels = ("doA", "doB", "doC") if __name__ == "__main__": - op = optparse.OptionParser(usage="%prog ") op.add_option( - "--dolevel", dest="dolevel", default=None, - type='choice', choices=valid_dolevels, + "--dolevel", + dest="dolevel", + default=None, + type="choice", + choices=valid_dolevels, help="Target DO178 qualification level. " - "Defaults to the one of testsuite-dir.") + "Defaults to the one of testsuite-dir.", + ) default_testsuite_dir = LOCAL_TESTSUITE_DIR op.add_option( - "--testsuite-dir", dest="testsuite_dir", default=default_testsuite_dir, + "--testsuite-dir", + dest="testsuite_dir", + default=default_testsuite_dir, help="Name of a directory where the testsuite was run. " - "Defaults to \"%s\"." % default_testsuite_dir) + 'Defaults to "%s".' % default_testsuite_dir, + ) (options, args) = op.parse_args() diff --git a/testsuite/SUITE/context.py b/testsuite/SUITE/context.py index 1315b62ab..60c00a0f6 100644 --- a/testsuite/SUITE/context.py +++ b/testsuite/SUITE/context.py @@ -18,19 +18,28 @@ from e3.main import Main from e3.os.fs import cd from e3.os.process import Run -from e3.testsuite.driver.diff import (CanonicalizeLineEndings, LineByLine, - OutputRefiner, RefiningChain) +from e3.testsuite.driver.diff import ( + CanonicalizeLineEndings, + LineByLine, + OutputRefiner, + RefiningChain, +) from SUITE import control from SUITE.control import GPRCLEAN, BUILDER, env -from SUITE.cutils import (exit_if, indent, indent_after_first_line, lines_of, - ndirs_in) +from SUITE.cutils import ( + exit_if, + indent, + indent_after_first_line, + lines_of, + ndirs_in, +) # This module is loaded as part of a Run operation for a test.py # file found and launched by the toplevel driver -logger = logging.getLogger('SUITE.context') +logger = logging.getLogger("SUITE.context") # This is where the toplevel invocation was issued for the individual test # at hand, which we expect to be where the toplevel testsuite.py is located. @@ -58,6 +67,7 @@ class _ReportOutput(object): the contents of the output attribute should be printed on standard output at the next flush. """ + def __init__(self, report_file): """Constructor. @@ -90,7 +100,7 @@ def log(self, text, end_of_line=True): which adds this '\n' by default too. """ if end_of_line: - text += '\n' + text += "\n" self.output += text self.report_fd.write(text) @@ -100,18 +110,17 @@ def flush(self): if print_diff is True). Reset print_diff to False as well. """ if self.print_diff: - sys.stdout.write(self.output + ' ') + sys.stdout.write(self.output + " ") self.output = "" self.print_diff = False self.report_fd.flush() def close(self): - """Close the file descriptor for our report file. - """ + """Close the file descriptor for our report file.""" self.report_fd.close() -class Test (object): +class Test(object): """Test class: Offer test command line and status management facilities. @@ -150,14 +159,14 @@ def __init__(self): # just fine (join("/foo", "/foo/bar") yields "/foo/bar"). testsuite_py_dir = ROOT_DIR - test_py_dir = os.path.dirname(sys.modules['__main__'].__file__) + test_py_dir = os.path.dirname(sys.modules["__main__"].__file__) self.homedir = os.path.join(testsuite_py_dir, test_py_dir) self.reldir = os.path.relpath(self.homedir, start=testsuite_py_dir) # Perform a simple canonicalization of the relative dir to simplify # related computations/assumptions in other parts of the testsuite. - self.reldir = self.reldir.replace('\\', '/') + self.reldir = self.reldir.replace("\\", "/") # Compute the depth of this test wrt testsuite root. self.depth = ndirs_in(os.path.relpath(self.homedir, ROOT_DIR)) @@ -183,31 +192,31 @@ def __init__(self): # coverage is deprecated, as it would make all tests fail. Testcases # that check the presence of this warning can just remove this # environment variable. - os.environ['GNATCOV_NO_NATIVE_WARNING'] = '1' + os.environ["GNATCOV_NO_NATIVE_WARNING"] = "1" def cleanup(self, project, options): """Cleanup possible remnants of previous builds.""" Run([GPRCLEAN, "-P%s" % project] + options) - rm('*.xcov') - rm('*.bin') + rm("*.xcov") + rm("*.bin") # Test status management def log(self, text, new_line=True): - """Calls self.report.log. """ + """Calls self.report.log.""" self.report.log(text, new_line) def flush(self): - """Calls self.report.flush. """ + """Calls self.report.flush.""" self.report.flush() def comment(self, text): """Output a TEXT comment.""" - self.log(' - %s.' % indent_after_first_line(text, ' ')) + self.log(" - %s." % indent_after_first_line(text, " ")) def failed(self, comment="assertion failed"): """Register a check failure.""" - self.log(' * %s' % indent_after_first_line(comment, ' ')) + self.log(" * %s" % indent_after_first_line(comment, " ")) self.report.enable_diffs() self.n_failed += 1 @@ -220,23 +229,25 @@ def fail_if_not_equal(self, what, expected, actual): """Register a check failure when EXPECTED and ACTUAL are not equal.""" self.fail_if( expected != actual, - 'Unexpected {}. Expected:' - '\n{}' - '\nBut got:' - '\n{}'.format(what, indent(str(expected)), indent(str(actual)))) + "Unexpected {}. Expected:" + "\n{}" + "\nBut got:" + "\n{}".format(what, indent(str(expected)), indent(str(actual))), + ) def fail_if_no_match(self, what, regexp, actual): """Register a check failure when ACTUAL does not match regexp.""" if isinstance(regexp, str): regexp = re.compile(regexp) # Canonicalize to Unix-style line endings to have cross-platform checks - actual = actual.replace('\r\n', '\n') + actual = actual.replace("\r\n", "\n") self.fail_if( not regexp.match(actual), - 'Unexpected {}. Expected:' - '\n{}' - '\nBut got:' - '\n{}'.format(what, indent(regexp.pattern), indent(str(actual)))) + "Unexpected {}. Expected:" + "\n{}" + "\nBut got:" + "\n{}".format(what, indent(regexp.pattern), indent(str(actual))), + ) def stop(self, exc): self.failed("Processing failed") @@ -262,14 +273,13 @@ class XcovPathRemover(OutputRefiner): """Remove path lines in outputs.""" def refine(self, output): - if os.path.exists(output.strip('\n:')): + if os.path.exists(output.strip("\n:")): return "" return output return [ # Refiners for the xcov report LineByLine(XcovPathRemover()), - # Ignore platform specificities CanonicalizeLineEndings(), ] @@ -329,9 +339,7 @@ def fail_if_diff_internal( # Send the appropriate logging. self.failed( - "Diff failure: {}\n".format(message) - + "\n{}".format(d) - + "\n" + "Diff failure: {}\n".format(message) + "\n{}".format(d) + "\n" ) def fail_if_diff( @@ -344,8 +352,9 @@ def fail_if_diff( """Wrapper around fail_if_diff_internal, taking an actual_file parameter instead of an actual string.""" with open(actual_file, "r") as f: - self.fail_if_diff_internal(baseline_file, f.read(), - failure_message, output_refiners) + self.fail_if_diff_internal( + baseline_file, f.read(), failure_message, output_refiners + ) def result(self): """Output the final result which the testsuite driver looks for. @@ -355,20 +364,23 @@ def result(self): from SUITE.tutils import run_processes if self.n_failed == 0: - self.log('==== PASSED ============================.') + self.log("==== PASSED ============================.") else: - self.log('**** FAILED ****************************.') + self.log("**** FAILED ****************************.") # Log the total execution time as well as the list of processes that # were run, with their duration. This is useful to investigate where # time is spent exactly when testcases take too long to run. duration = time.time() - self.start_time - logger.debug('Total ellapsed time: {:.3f}s'.format(duration)) + logger.debug("Total ellapsed time: {:.3f}s".format(duration)) if run_processes: - logger.debug('Processes run:') + logger.debug("Processes run:") for p in run_processes: - logger.debug(' [{:6.3f}s] {}'.format( - p.duration, ' '.join(p.original_cmd))) + logger.debug( + " [{:6.3f}s] {}".format( + p.duration, " ".join(p.original_cmd) + ) + ) # Flush the output, in case we forgot to do so earlier. This has no # effect if the flush was already performed. @@ -386,20 +398,27 @@ def __cmdline_options(self): """Return an options object to represent the command line options""" main = Main(platform_args=True) parser = main.argument_parser - parser.add_argument('--timeout', type=int, default=None) - parser.add_argument('--report-file', metavar='FILE', - help='The filename where to store the test report' - ' [required]') - parser.add_argument('--qualif-level', metavar='QUALIF_LEVEL', - help='The target qualification level when we are' - ' running in qualification mode.') + parser.add_argument("--timeout", type=int, default=None) + parser.add_argument( + "--report-file", + metavar="FILE", + help="The filename where to store the test report" " [required]", + ) + parser.add_argument( + "--qualif-level", + metavar="QUALIF_LEVEL", + help="The target qualification level when we are" + " running in qualification mode.", + ) - parser.add_argument('--xcov-level', - help='Force the --level argument passed to xcov' - 'instead of deducing it from the test' - ' category when that normally happens.') + parser.add_argument( + "--xcov-level", + help="Force the --level argument passed to xcov" + "instead of deducing it from the test" + " category when that normally happens.", + ) - parser.add_argument('--tags', default="") + parser.add_argument("--tags", default="") control.add_shared_options_to(parser, toplevel=False) @@ -409,12 +428,13 @@ def __cmdline_options(self): # self-contradictory, but it's easy to do it that way. exit_if( main.args.report_file is None, - "The report file must be specified with --report-file") + "The report file must be specified with --report-file", + ) # Get our tags set as a list. Fetch contents from file if needed # first: - if main.args.tags and main.args.tags.startswith('@'): - main.args.tags = ' '.join(lines_of(main.args.tags[1:])) + if main.args.tags and main.args.tags.startswith("@"): + main.args.tags = " ".join(lines_of(main.args.tags[1:])) if main.args.tags: main.args.tags = main.args.tags.split() @@ -433,7 +453,7 @@ def suite_covpgm_for(self, cmd): Alternate program to launch in lieu of "gnatcov CMD", if any specified with the --gnatcov-CMD= command line option. None otherwise. """ - return getattr(thistest.options, 'gnatcov_%s' % cmd, None) + return getattr(thistest.options, "gnatcov_%s" % cmd, None) def suite_gprpgm_for(self, pgm): """ @@ -442,7 +462,7 @@ def suite_gprpgm_for(self, pgm): return getattr(thistest.options, pgm, None) def support_dir(self): - return os.path.join(ROOT_DIR, 'support') + return os.path.join(ROOT_DIR, "support") def bits(self): """ @@ -458,5 +478,5 @@ def bits(self): # Allow import of a common "test_support" module from test.py when # there is a test_support.py available uptree. __parent_dir = os.path.dirname(os.getcwd()) -if (os.path.exists(os.path.join(__parent_dir, 'test_support.py'))): +if os.path.exists(os.path.join(__parent_dir, "test_support.py")): sys.path.append(__parent_dir) diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index 1e27749a8..21da075de 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -26,15 +26,15 @@ def xcov_pgm(auto_arch, for_target=True): architecture instead. """ arch = env.target if for_target else env.build - return 'gnatcov{bits}{ext}'.format( - bits=str(arch.cpu.bits) if auto_arch else '', - ext=env.host.os.exeext) + return "gnatcov{bits}{ext}".format( + bits=str(arch.cpu.bits) if auto_arch else "", ext=env.host.os.exeext + ) # Append .exe on windows for native tools -GPRBUILD = 'gprbuild' + env.host.os.exeext -GPRCONFIG = 'gprconfig' + env.host.os.exeext -GPRCLEAN = 'gprclean' + env.host.os.exeext +GPRBUILD = "gprbuild" + env.host.os.exeext +GPRCONFIG = "gprconfig" + env.host.os.exeext +GPRCLEAN = "gprclean" + env.host.os.exeext class LangInfo: @@ -62,6 +62,7 @@ class LangInfo: A function which returns the name of the SID file for a given SOURCE file name. This is, for example, "x.sid" for "x.adb". """ + def __init__(self, name, src_ext, comment, scofile_for, sidfile_for=None): self.name = name self.src_ext = src_ext @@ -77,28 +78,31 @@ def __init__(self, name, src_ext, comment, scofile_for, sidfile_for=None): LANGINFO = { "Ada": LangInfo( - name="Ada", src_ext=[".ads", ".adb"], comment='--', - scofile_for=lambda source: no_ext(source) + '.ali', - sidfile_for=lambda source: no_ext(source) + '.sid'), - + name="Ada", + src_ext=[".ads", ".adb"], + comment="--", + scofile_for=lambda source: no_ext(source) + ".ali", + sidfile_for=lambda source: no_ext(source) + ".sid", + ), "C": LangInfo( - name="C", src_ext=[".h", ".c"], comment='//', - scofile_for=lambda source: source + '.gli', - sidfile_for=lambda source: source + '.sid'), - + name="C", + src_ext=[".h", ".c"], + comment="//", + scofile_for=lambda source: source + ".gli", + sidfile_for=lambda source: source + ".sid", + ), "C++": LangInfo( - name="C++", src_ext=[".hh", ".cpp"], - comment='//', + name="C++", + src_ext=[".hh", ".cpp"], + comment="//", scofile_for=None, - sidfile_for=lambda source: source + '.sid'), - - "Asm": LangInfo( - name="Asm", src_ext=[".s"], comment='#', - scofile_for=None), - + sidfile_for=lambda source: source + ".sid", + ), + "Asm": LangInfo(name="Asm", src_ext=[".s"], comment="#", scofile_for=None), "Cons": LangInfo( - name="Consolidation", src_ext=[".txt"], comment='--', - scofile_for=None)} + name="Consolidation", src_ext=[".txt"], comment="--", scofile_for=None + ), +} # List of languages that gnatcov supports KNOWN_LANGUAGES = [li.name for li in LANGINFO.values() if li.scofile_for] @@ -137,8 +141,7 @@ def SCOV_CARGS(options): # Working from binary traces relies on specific properties: - if options.trace_mode == 'bin': - + if options.trace_mode == "bin": # Critical conditional branches must be preserved, source # coverage obligations need to be generated by the compiler, # and debug info is needed. @@ -156,10 +159,10 @@ def SCOV_CARGS(options): # info on partially linked objects, which we'll only get for long # calls on powerpc. - if 'vxworks' in Env().target.triplet: + if "vxworks" in Env().target.triplet: cargs.append("-gno-strict-dwarf") - if 'powerpc' in Env().target.triplet: + if "powerpc" in Env().target.triplet: cargs.append("-mlongcall") return cargs @@ -193,7 +196,6 @@ def RUN_CONFIG_SEQUENCE(toplev_options, toolchain_discriminant): # We build a temporary dummy project file in the current directory, # specifying languages only. with open("suite.gpr", "w") as tempgpr: - # Given GNAT 5.04a1 does not come with a C++ compiler, we'd # resort to the system one to link if C++ is in the list of # languages, causing compatibility issues with the toolchain. @@ -202,15 +204,20 @@ def RUN_CONFIG_SEQUENCE(toplev_options, toolchain_discriminant): # toolchain. added_languages = ( - ', "C++"' if toolchain_discriminant != "5.04a1" - else '') + ', "C++"' if toolchain_discriminant != "5.04a1" else "" + ) - tempgpr.write(""" + tempgpr.write( + """ project %(prjname)s is for Languages use ("Asm", "C", "Ada" %(added_languages)s); end %(prjname)s; - """ % {'prjname': os.path.basename(tempgpr.name).split('.')[0], - 'added_languages': added_languages}) + """ + % { + "prjname": os.path.basename(tempgpr.name).split(".")[0], + "added_languages": added_languages, + } + ) # We now run gprbuild -Ptemp.gpr --target=bla --RTS=blo, which # will complain about missing sources, but only after producing @@ -218,12 +225,19 @@ def RUN_CONFIG_SEQUENCE(toplev_options, toolchain_discriminant): # else (no other file). rm(BUILDER.SUITE_CGPR) - extraopts = ['--target={}'.format(env.target.triplet)] + extraopts = ["--target={}".format(env.target.triplet)] if toplev_options.RTS: - extraopts.append('--RTS=%s' % toplev_options.RTS) - - Run([GPRBUILD, '-P', tempgpr.name, - '--autoconf=%s' % BUILDER.SUITE_CGPR] + extraopts) + extraopts.append("--RTS=%s" % toplev_options.RTS) + + Run( + [ + GPRBUILD, + "-P", + tempgpr.name, + "--autoconf=%s" % BUILDER.SUITE_CGPR, + ] + + extraopts + ) rm(tempgpr.name) @@ -246,28 +260,27 @@ def __init__(self, runtime_name=None): if not self.runtime_name: self.has_full_runtime = True self.discrs = ["RTS_FULL"] - elif 'embedded' in self.runtime_name: + elif "embedded" in self.runtime_name: self.has_ravenscar_runtime = True self.discrs = ["RTS_RAVENSCAR", "RTS_EMBEDDED"] - elif 'light-tasking' in self.runtime_name: + elif "light-tasking" in self.runtime_name: self.has_ravenscar_runtime = True self.has_exception_propagation = False self.discrs = ["RTS_RAVENSCAR", "RTS_LIGHT_TASKING"] - elif self.runtime_name.startswith('zfp'): + elif self.runtime_name.startswith("zfp"): self.has_light_runtime = True self.has_exception_propagation = False self.discrs = ["RTS_ZFP"] - elif ( - self.runtime_name == "light" - or self.runtime_name.startswith('light-') + elif self.runtime_name == "light" or self.runtime_name.startswith( + "light-" ): self.has_light_runtime = True self.has_exception_propagation = False self.discrs = ["RTS_ZFP"] - elif self.runtime_name == 'kernel': + elif self.runtime_name == "kernel": self.has_kernel_runtime = True else: - assert False, 'Unknown runtime: {}'.format(runtime_name) + assert False, "Unknown runtime: {}".format(runtime_name) @property def gnatcov_rts_project(self): @@ -277,11 +290,12 @@ def gnatcov_rts_project(self): # of gnatcov setup. return ( - 'gnatcov_rts_full' if ( - self.has_full_runtime and not gnatcov_info().has_setup) - else 'gnatcov_rts' + "gnatcov_rts_full" + if (self.has_full_runtime and not gnatcov_info().has_setup) + else "gnatcov_rts" ) + def _runtime_info(runtime, target): if target == "c": assert not runtime @@ -298,6 +312,7 @@ def runtime_info(): # Target specificities. We don't have many variants but need to match each # against a few possible triplets. + class TargetInfo: """ Gather target specific information and behaviors @@ -311,11 +326,13 @@ class TargetInfo: symbol into a platform specific one, or None if they are the same. This enables us to use platform-independent symbol names in testcases. """ + def __init__(self, exeext, partiallinks, to_platform_specific_symbol=None): self.exeext = exeext self.partiallinks = partiallinks - self.to_platform_specific_symbol = ( - to_platform_specific_symbol or (lambda x: x)) + self.to_platform_specific_symbol = to_platform_specific_symbol or ( + lambda x: x + ) # For each family of targets we need to distinguish, a regexp to match against @@ -323,18 +340,18 @@ def __init__(self, exeext, partiallinks, to_platform_specific_symbol=None): TARGETINFO = { # VxWorks targets - '.*-vxworks': TargetInfo(exeext='.out', partiallinks=True), - + ".*-vxworks": TargetInfo(exeext=".out", partiallinks=True), # x86-windows targets - 'i686.*-mingw': TargetInfo( - exeext='.exe', partiallinks=False, - to_platform_specific_symbol=lambda x: '_{}'.format(x)), - + "i686.*-mingw": TargetInfo( + exeext=".exe", + partiallinks=False, + to_platform_specific_symbol=lambda x: "_{}".format(x), + ), # x86_64-windows targets - 'x86_64.*mingw': TargetInfo(exeext='.exe', partiallinks=False), - + "x86_64.*mingw": TargetInfo(exeext=".exe", partiallinks=False), # default - '.': TargetInfo(exeext='', partiallinks=False)} + ".": TargetInfo(exeext="", partiallinks=False), +} def target_info(target=None): @@ -353,14 +370,10 @@ def target_info(target=None): class GnatcovInfo: def __init__(self): - p = re.search( - pattern="GNATcoverage (\d+)", - string=version("gnatcov") - ) + p = re.search(pattern="GNATcoverage (\d+)", string=version("gnatcov")) self._major = int(p.group(1)) if p else None self.has_setup = self.major_at_least(23) - def major_at_most(self, val): """ Returns whether the major version of gnatcov is less or equal than @@ -384,6 +397,7 @@ def major(self): """ return self._major + def gnatcov_info(): return GnatcovInfo() @@ -391,17 +405,18 @@ def gnatcov_info(): # Mapping between run-cross2 board names and gnatemu board names BOARD_INFO = { # generic - "qemu" : "", + "qemu": "", # aarch64-elf - "qemu-zynqmp" : "", + "qemu-zynqmp": "", # arm-elf - "qemu-stm32" : "stm32f4", - "qemu-tms570" : "tms570", + "qemu-stm32": "stm32f4", + "qemu-tms570": "tms570", # ppc-elf: - "qemu-8641d" : "", - None : "" + "qemu-8641d": "", + None: "", } + def gnatemu_board_name(name): """ Return the gnatemu board name corresponding to the run-cross2 board name @@ -410,18 +425,21 @@ def gnatemu_board_name(name): """ return BOARD_INFO.get(name, name) + # Allowed pairs for the --gnatcov- family of command line options: -ALTRUN_GNATCOV_PAIRS = (('gnatcov', 'run'), ) +ALTRUN_GNATCOV_PAIRS = (("gnatcov", "run"),) # Allowed pairs for the --pre/post-testsuite/testcase family of command line # options: -ALTRUN_HOOK_PAIRS = (('pre', 'testsuite'), - ('post', 'testsuite'), - ('pre', 'testcase'), - ('post', 'testcase')) +ALTRUN_HOOK_PAIRS = ( + ("pre", "testsuite"), + ("post", "testsuite"), + ("pre", "testcase"), + ("post", "testcase"), +) # Allowed alternatives for the --gpr family of command line options -ALTRUN_GPR = ('gprbuild', ) +ALTRUN_GPR = ("gprbuild",) def altrun_opt_for(p0, p1=None): @@ -437,14 +455,14 @@ def altrun_attr_for(p0, p1=None): def cargs_opt_for(lang): """Name of the command line option to pass for language LANG.""" - return "cargs" + (':%s' % lang if lang else "") + return "cargs" + (":%s" % lang if lang else "") def cargs_attr_for(lang): """ Name of our internal options attribute to hold cargs for language LANG. """ - return "cargs" + ('_%s' % lang if lang else "") + return "cargs" + ("_%s" % lang if lang else "") def add_shared_options_to(parser, toplevel): @@ -457,66 +475,95 @@ def add_shared_options_to(parser, toplevel): # --gnatcov_ family for pgm, cmd in ALTRUN_GNATCOV_PAIRS: parser.add_argument( - '--%s' % altrun_opt_for(pgm, cmd), dest=altrun_attr_for(pgm, cmd), + "--%s" % altrun_opt_for(pgm, cmd), + dest=altrun_attr_for(pgm, cmd), metavar="CMD", - help='Use CMD instead of "%s %s"' % (pgm, cmd)) + help='Use CMD instead of "%s %s"' % (pgm, cmd), + ) # --gpr family for pgm in ALTRUN_GPR: parser.add_argument( - f'--{altrun_opt_for(pgm)}', dest=altrun_attr_for(pgm), + f"--{altrun_opt_for(pgm)}", + dest=altrun_attr_for(pgm), metavar="CMD", - help=f'use CMD instead of "{pgm}"' + help=f'use CMD instead of "{pgm}"', ) # Valgrind control parser.add_argument( - '--enable-valgrind', dest='enable_valgrind', - choices='memcheck callgrind'.split(), - help='Enable the use of Valgrind (memcheck or callgrind) during the' - ' test execution.') + "--enable-valgrind", + dest="enable_valgrind", + choices="memcheck callgrind".split(), + help="Enable the use of Valgrind (memcheck or callgrind) during the" + " test execution.", + ) # RTS for tested programs. Defaulting to "" instead of None lets us # perform RE searches unconditionally to determine profile. parser.add_argument( - '--RTS', dest='RTS', metavar='RTS', default="", + "--RTS", + dest="RTS", + metavar="RTS", + default="", help='--RTS option to pass to gprbuild, if any. Assume "full" profile' - ' by default.') + " by default.", + ) # --board parser.add_argument( - '--board', dest='board', metavar='BOARD', - help='Specific target board to exercize.') + "--board", + dest="board", + metavar="BOARD", + help="Specific target board to exercize.", + ) # --gprmode parser.add_argument( - '--gprmode', dest='gprmode', action='store_true', - help='Use -P instead of --scos for analysis on source coverage tests.') + "--gprmode", + dest="gprmode", + action="store_true", + help="Use -P instead of --scos for analysis on source coverage tests.", + ) # --kernel parser.add_argument( - '--kernel', dest='kernel', metavar='KERNEL', - help='KERNEL to pass to gnatcov run in addition to exe.') + "--kernel", + dest="kernel", + metavar="KERNEL", + help="KERNEL to pass to gnatcov run in addition to exe.", + ) # --trace-mode parser.add_argument( - '--trace-mode', dest='trace_mode', metavar='TRACE_MODE', - choices=('bin', 'src'), default='bin', - help='Kind of execution traces to use for SCOV driven tests.' - ' "bin" for binary traces out of valgrind or qemu,' - ' "src" for source traces out of source level instrumentation.') + "--trace-mode", + dest="trace_mode", + metavar="TRACE_MODE", + choices=("bin", "src"), + default="bin", + help="Kind of execution traces to use for SCOV driven tests." + ' "bin" for binary traces out of valgrind or qemu,' + ' "src" for source traces out of source level instrumentation.', + ) # --trace-size-limit parser.add_argument( - '--trace-size-limit', dest='trace_size_limit', metavar='TRSZ_LIMIT', - help='Best effort request to the execution environment to stop when' - ' the execution trace would grow beyond the provided size. Only' - ' effective for qemu based executions, with values like "10M".') + "--trace-size-limit", + dest="trace_size_limit", + metavar="TRSZ_LIMIT", + help="Best effort request to the execution environment to stop when" + " the execution trace would grow beyond the provided size. Only" + ' effective for qemu based executions, with values like "10M".', + ) # --largs parser.add_argument( - '--largs', dest='largs', metavar='LARGS', default='', - help='-largs to pass to gprbuild.') + "--largs", + dest="largs", + metavar="LARGS", + default="", + help="-largs to pass to gprbuild.", + ) # --cargs[:] family: a common, language agnostic, one + one for each # language we support. --cargs "" should be kept semantically equivalent @@ -524,54 +571,73 @@ def add_shared_options_to(parser, toplevel): # downstream. for lang in [None] + KNOWN_LANGUAGES: parser.add_argument( - '--%s' % cargs_opt_for(lang), dest=cargs_attr_for(lang), - metavar='CARGS', default='', - help='Additional arguments to pass to the %scompiler when' - ' building test programs.' % ('%s ' % lang if lang else '')) + "--%s" % cargs_opt_for(lang), + dest=cargs_attr_for(lang), + metavar="CARGS", + default="", + help="Additional arguments to pass to the %scompiler when" + " building test programs." % ("%s " % lang if lang else ""), + ) # --auto-arch parser.add_argument( - '--auto-arch', action='store_true', - help='Autodetect which "gnatcov" to use (32-bit or 64-bit one).') + "--auto-arch", + action="store_true", + help='Autodetect which "gnatcov" to use (32-bit or 64-bit one).', + ) # --consolidate parser.add_argument( - '--consolidate', dest='consolidate', default="traces", + "--consolidate", + dest="consolidate", + default="traces", help="Artifacts to be used for consolidation specs.", - choices=('traces', 'checkpoints')) + choices=("traces", "checkpoints"), + ) # --pretty-print parser.add_argument( - '--pretty-print', action='store_true', + "--pretty-print", + action="store_true", help='Whether to pretty-print generated sources (for "gnatcov' - ' instrument".') + ' instrument".', + ) # --spark-tests parser.add_argument( - '--spark-tests', dest="spark_tests", metavar='SPARK_TESTSUITE_PATH', - help='Path to the SPARK testsuite. Activate SPARK-specific' - ' tests. Implicitly appends -gnat12 to Ada cargs.') + "--spark-tests", + dest="spark_tests", + metavar="SPARK_TESTSUITE_PATH", + help="Path to the SPARK testsuite. Activate SPARK-specific" + " tests. Implicitly appends -gnat12 to Ada cargs.", + ) # --all-warnings parser.add_argument( - '--all-warnings', action='store_true', - help='Whether to pass --all-warnings to gnatcov.') + "--all-warnings", + action="store_true", + help="Whether to pass --all-warnings to gnatcov.", + ) parser.add_argument( - '--rewrite', action='store_true', - help='Rewrite test baselines according to current outputs.') + "--rewrite", + action="store_true", + help="Rewrite test baselines according to current outputs.", + ) # --default-dump-trigger parser.add_argument( - '--default-dump-trigger', dest='default_dump_trigger', + "--default-dump-trigger", + dest="default_dump_trigger", help='Default dump trigger to be passed to "gnatcov instrument,"' - ' unless the test specifically overrides it.' + " unless the test specifically overrides it.", ) # --default-dump-channel parser.add_argument( - '--default-dump-channel', dest='default_dump_channel', + "--default-dump-channel", + dest="default_dump_channel", help='Default dump channel to be passed to "gnatcov instrument,"' - ' unless the test specifically overrides it.' + " unless the test specifically overrides it.", ) diff --git a/testsuite/SUITE/cutils.py b/testsuite/SUITE/cutils.py index 6a035c988..09b9278d0 100644 --- a/testsuite/SUITE/cutils.py +++ b/testsuite/SUITE/cutils.py @@ -15,6 +15,7 @@ from e3.os.fs import cd, which from e3.os.process import Run + def unhandled_exception_in(log): """ Whether the provided execution log contains an indication @@ -29,15 +30,16 @@ def unhandled_exception_in(log): r"|" r"raised [A-Z_]+ : [-._a-zA-Z]+:[0-9]+ \w+)" ), - string=log + string=log, ) + def strip_prefix(prefix, string): """ If STRING starts with PREFIX, return STRING without the PREFIX part. Return the string unchanged otherwise. """ - return string[len(prefix):] if string.startswith(prefix) else string + return string[len(prefix) :] if string.startswith(prefix) else string def no_ext(filename): @@ -74,45 +76,48 @@ def to_list(blob): Turn input BLOB into a list if it isn't already. Handle None and whitespace separated strings. Return empty list otherwise. """ - return (list(blob) if isinstance(blob, (list, tuple)) - else blob.split() if isinstance(blob, str) - else []) + return ( + list(blob) + if isinstance(blob, (list, tuple)) + else blob.split() + if isinstance(blob, str) + else [] + ) -def indent(blob, indent=' '): +def indent(blob, indent=" "): """ Prefix each line in BLOB's with INDENT. BLOB can be either a single string or a list of strings. The result is a single string anyway. """ lines = list(blob) if isinstance(blob, list) else blob.splitlines() - return '\n'.join('{}{}'.format(indent, line) - for line in lines) + return "\n".join("{}{}".format(indent, line) for line in lines) -def indent_after_first_line(blob, prefix=' '): +def indent_after_first_line(blob, prefix=" "): """Like "indent", but do not change the first line.""" lines = list(blob) if isinstance(blob, list) else blob.splitlines() if len(lines) < 2: - return '\n'.join(lines) + return "\n".join(lines) else: - return '\n'.join(lines[0:1] + indent(lines[1:], prefix).splitlines()) + return "\n".join(lines[0:1] + indent(lines[1:], prefix).splitlines()) -def text_to_file(text, filename='tmp.list'): +def text_to_file(text, filename="tmp.list"): """ Write TEXT to file FILENAME. Overwrite current contents. Return FILENAME. """ - with open(filename, 'w') as fd: + with open(filename, "w") as fd: fd.write(text) return filename -def list_to_file(lines, filename='tmp.list'): +def list_to_file(lines, filename="tmp.list"): """ Write list LINES to file FILENAME, one item per line. Typical use is to generate response files. Return FILENAME. """ - return text_to_file('\n'.join(lines) + '\n', filename) + return text_to_file("\n".join(lines) + "\n", filename) def list_to_tmp(lines, dir=None): @@ -127,7 +132,8 @@ def list_to_tmp(lines, dir=None): # testcases). dir = os.getcwd() if dir is None else os.path.abspath(dir) return text_to_file( - '\n'.join(lines) + '\n', tempfile.mktemp(dir=dir, suffix='.list')) + "\n".join(lines) + "\n", tempfile.mktemp(dir=dir, suffix=".list") + ) def match(pattern, filename, flags=0): @@ -135,7 +141,7 @@ def match(pattern, filename, flags=0): return re.search(pattern, contents_of(filename), flags) is not None -def re_filter(strings, pattern=''): +def re_filter(strings, pattern=""): """Compute the list of entries in STRINGS that match the PATTERN regexp.""" return [t for t in strings if re.search(pattern, t)] @@ -164,23 +170,24 @@ def version(tool, nlines=1): # probe, and if we happen to actually need the tool later on, we'll see # test failures anyway. if not which(tool): - return 'N/A' + return "N/A" # --version often dumps more than the version number on a line. A # copyright notice is typically found there as well. Our heuristic # here is to strip everything past the first comma. def version_on_line(text): - cprpos = text.find(',') + cprpos = text.find(",") return text[0:cprpos] if cprpos != -1 else text - tool_version_output = Run([tool, '--version']).out.split('\n') - version_info = '\n'.join( - [version_on_line(line) for line in tool_version_output[0:nlines]]) + tool_version_output = Run([tool, "--version"]).out.split("\n") + version_info = "\n".join( + [version_on_line(line) for line in tool_version_output[0:nlines]] + ) - if tool == 'gcc': - gcc_target = Run([tool, '-dumpmachine']).out.strip() - version_info += ' [%s]' % gcc_target + if tool == "gcc": + gcc_target = Run([tool, "-dumpmachine"]).out.strip() + version_info += " [%s]" % gcc_target return version_info @@ -246,9 +253,9 @@ class FatalError(Exception): def __init__(self, comment, outfile=None, outstr=None): if outfile is not None: - comment += '. Output was:\n' + contents_of(outfile) + comment += ". Output was:\n" + contents_of(outfile) elif outstr is not None: - comment += '. Output was:\n' + outstr + comment += ". Output was:\n" + outstr self.comment = comment def __str__(self): @@ -261,7 +268,7 @@ def exit_if(t, comment): error status code. """ if t: - sys.stderr.write(comment + '\n') + sys.stderr.write(comment + "\n") exit(1) diff --git a/testsuite/SUITE/dutils.py b/testsuite/SUITE/dutils.py index 607abc75d..cd0f40644 100644 --- a/testsuite/SUITE/dutils.py +++ b/testsuite/SUITE/dutils.py @@ -17,13 +17,14 @@ # Pickle oriented facilities # + def pdump_to(filename, o): - with open(filename, 'wb') as f: + with open(filename, "wb") as f: pickle.dump(o, f) def pload_from(filename): - with open(filename, 'rb') as f: + with open(filename, "rb") as f: return pickle.load(f) @@ -31,13 +32,14 @@ def pload_from(filename): # JSON oriented facilities # + def jdump_to(filename, o): - with open(filename, 'w') as f: + with open(filename, "w") as f: json.dump(o, f) def jload_from(filename): - with open(filename, 'r') as f: + with open(filename, "r") as f: return json.load(f) @@ -51,15 +53,15 @@ def host_string_from(host): os_version = host.os.version # 2008[R2] or 2012[R2] for Windows conveys Server editions - if os_name == 'Windows' and re.match(os_version, '2008|2012'): - os_version = 'Server ' + os_version + if os_name == "Windows" and re.match(os_version, "2008|2012"): + os_version = "Server " + os_version # Fetch precise Redhat version - if os_name == 'Linux' and os_version.startswith('rhES'): - os_name = '' - os_version = contents_of('/etc/redhat-release') + if os_name == "Linux" and os_version.startswith("rhES"): + os_name = "" + os_version = contents_of("/etc/redhat-release") - return ' '.join((os_name, os_version)).strip() + return " ".join((os_name, os_version)).strip() def time_string_from(stamp): @@ -67,4 +69,4 @@ def time_string_from(stamp): Return a textual version of the timestamp in STAMP, a time.localtime() kind of object. """ - return time.strftime('%a %b %d, %Y. %H:%M', stamp) + return time.strftime("%a %b %d, %Y. %H:%M", stamp) diff --git a/testsuite/SUITE/gprutils.py b/testsuite/SUITE/gprutils.py index 97721b106..a7e68de34 100644 --- a/testsuite/SUITE/gprutils.py +++ b/testsuite/SUITE/gprutils.py @@ -31,24 +31,25 @@ def gprdep_for(reldir, wd): # make sure that each test operating with a given relative dir has its own # object dir there and can run in parallel with others. - locid = os.path.basename(reldir.rstrip('/')) - testid = os.path.basename(wd.homedir.rstrip('/')) + locid = os.path.basename(reldir.rstrip("/")) + testid = os.path.basename(wd.homedir.rstrip("/")) - prjname = '%s_%s' % (locid, testid) + prjname = "%s_%s" % (locid, testid) gprdep = os.path.join(wd.homedir, reldir, prjname) - with open(gprdep + '.gpr', 'w') as gprfile: + with open(gprdep + ".gpr", "w") as gprfile: gprfile.write( - contents_of(os.path.join(wd.homedir, '../template.gpr')) % { - 'prjname': prjname, - 'objdir': 'obj_' + testid, - 'pkg_emulator': gpr_emulator_package(), + contents_of(os.path.join(wd.homedir, "../template.gpr")) + % { + "prjname": prjname, + "objdir": "obj_" + testid, + "pkg_emulator": gpr_emulator_package(), } ) return gprdep -Csw = namedtuple('Csw', 'cmd switches') +Csw = namedtuple("Csw", "cmd switches") def __gprattr(attrname, value, aslist): @@ -60,12 +61,13 @@ def __gprattr(attrname, value, aslist): for value == None. Not for an empty list or string. """ if value is None: - return '-- empty %s' % attrname + return "-- empty %s" % attrname elif aslist: - return 'for %s use (%s);' % ( + return "for %s use (%s);" % ( attrname, - ','.join('"%s"' % v for v in value)) + ",".join('"%s"' % v for v in value), + ) else: return 'for %s use "%s";' % (attrname, value) @@ -78,16 +80,19 @@ def __gpr_uattr(value, for_list, to_exclude): have a single list-filename argument. """ return __gprattr( - attrname='%(prefix)s%(kind)s' % { - 'prefix': 'Excluded_' if to_exclude else '', - 'kind': 'Units_List' if for_list else 'Units' + attrname="%(prefix)s%(kind)s" + % { + "prefix": "Excluded_" if to_exclude else "", + "kind": "Units_List" if for_list else "Units", }, value=value, - aslist=not for_list) + aslist=not for_list, + ) -def gprcov_for(units_in=None, ulist_in=None, units_out=None, ulist_out=None, - switches=()): +def gprcov_for( + units_in=None, ulist_in=None, units_out=None, ulist_out=None, switches=() +): """ Compute and return the text of a Coverage GPR package from: @@ -100,28 +105,29 @@ def gprcov_for(units_in=None, ulist_in=None, units_out=None, ulist_out=None, the corresponding argument passed here is None. For SWITCHES, we expect a command->switches sequence of ("command", [options]) Csw tuples. """ - return '\n'.join([ - - 'package Coverage is', - - # Units - __gpr_uattr(for_list=False, to_exclude=False, value=units_in), - - # Excluded_Units - __gpr_uattr(for_list=False, to_exclude=True, value=units_out), - - # Units_List - __gpr_uattr(for_list=True, to_exclude=False, value=ulist_in), - - # Excluded_Units_List - __gpr_uattr(for_list=True, to_exclude=True, value=ulist_out) - ] + [ - # Switches (CMD) - __gprattr(attrname='Switches ("%s")' % csw.cmd, - value=csw.switches, - aslist=True) - for csw in switches - ] + ["end Coverage;"]) + return "\n".join( + [ + "package Coverage is", + # Units + __gpr_uattr(for_list=False, to_exclude=False, value=units_in), + # Excluded_Units + __gpr_uattr(for_list=False, to_exclude=True, value=units_out), + # Units_List + __gpr_uattr(for_list=True, to_exclude=False, value=ulist_in), + # Excluded_Units_List + __gpr_uattr(for_list=True, to_exclude=True, value=ulist_out), + ] + + [ + # Switches (CMD) + __gprattr( + attrname='Switches ("%s")' % csw.cmd, + value=csw.switches, + aslist=True, + ) + for csw in switches + ] + + ["end Coverage;"] + ) class GPRswitches: @@ -137,16 +143,18 @@ class GPRswitches: with the build step that precedes the gnatcov invocations (e.g. --subdirs). """ - def __init__(self, - root_project, - projects=None, - units=None, - no_subprojects=False, - externally_built_projects=False, - relocate_build_tree=False, - root_dir=None, - xvars=None, - subdirs=None): + def __init__( + self, + root_project, + projects=None, + units=None, + no_subprojects=False, + externally_built_projects=False, + relocate_build_tree=False, + root_dir=None, + xvars=None, + subdirs=None, + ): """ :param str root_project: Root project to consider (-P argument). :param list[str] projects: Optional list of projects for units of @@ -181,16 +189,16 @@ def build_switches(self): switches = [] for v in self.xvars: - switches.append('-X{}={}'.format(v[0], v[1])) + switches.append("-X{}={}".format(v[0], v[1])) if self.subdirs: - switches.append('--subdirs={}'.format(self.subdirs)) + switches.append("--subdirs={}".format(self.subdirs)) if self.relocate_build_tree: - switches.append('--relocate-build-tree') + switches.append("--relocate-build-tree") if self.root_dir: - switches.append('--root-dir={}'.format(self.root_dir)) + switches.append("--root-dir={}".format(self.root_dir)) return switches @@ -199,18 +207,18 @@ def cov_switches(self): """ The switches for gnatcov commands, as a list of strings. """ - switches = ['-P{}'.format(self.root_project)] + switches = ["-P{}".format(self.root_project)] for p in self.projects: - switches.append('--projects={}'.format(p)) + switches.append("--projects={}".format(p)) for u in self.units: - switches.append('--units={}'.format(u)) + switches.append("--units={}".format(u)) if self.no_subprojects: - switches.append('--no-subprojects') + switches.append("--no-subprojects") if self.externally_built_projects: - switches.append('--externally-built-projects') + switches.append("--externally-built-projects") return switches + self.build_switches diff --git a/testsuite/SUITE/qdata.py b/testsuite/SUITE/qdata.py index c313510c5..25d996e72 100644 --- a/testsuite/SUITE/qdata.py +++ b/testsuite/SUITE/qdata.py @@ -25,19 +25,19 @@ # List of languages we support qualification tests for -QLANGUAGES = ['Ada'] +QLANGUAGES = ["Ada"] # String that identifies a qualification test at the beginning of it's # sub-directory name relative to the testsuite root -QROOTDIR = 'Qualif' +QROOTDIR = "Qualif" # Extension of datafiles dumped for the purpose of the STR document # production -STREXT = '.dump' +STREXT = ".dump" # Name of a directory where context data aimed at the STR production engine # will be dropped by the testsuite execution driver -QSTRBOX_DIR = '_strbox' +QSTRBOX_DIR = "_strbox" # @@ -58,41 +58,45 @@ # Name of a file, relative to the testsuite toplevel directory, where the # testsuite data of use for the STR production will be made available. -CTXDATA_FILE = os.path.join(QSTRBOX_DIR, 'suite' + STREXT) +CTXDATA_FILE = os.path.join(QSTRBOX_DIR, "suite" + STREXT) def TOOL_info(exename, ver=None): """Context data for a tool involved in a testsuite run.""" - return {'exename': exename, - 'version': ver or version(exename)} + return {"exename": exename, "version": ver or version(exename)} def OPT_info_from(options): """Context data for the command line options info of relevance.""" - return {'target': options.target, - 'board': options.board, - 'trace_mode': options.trace_mode, - 'dolevel': options.qualif_level, - 'cargs': options.cargs, - 'cargs_Ada': options.cargs_Ada, - 'cargs_C': options.cargs_C} - - -def SUITE_context(treeref, runstamp, host, cmdline, options, gnatpro, gnatemu, - gnatcov, other): + return { + "target": options.target, + "board": options.board, + "trace_mode": options.trace_mode, + "dolevel": options.qualif_level, + "cargs": options.cargs, + "cargs_Ada": options.cargs_Ada, + "cargs_C": options.cargs_C, + } + + +def SUITE_context( + treeref, runstamp, host, cmdline, options, gnatpro, gnatemu, gnatcov, other +): """ Toplevel context data structure, wrapping up all the relevant items together. """ - return {'runstamp': runstamp, - 'treeref': treeref, - 'cmdline': cmdline, - 'options': options, - 'host': host, - 'gnatpro': gnatpro, - 'gnatemu': gnatemu, - 'gnatcov': gnatcov, - 'other': other} + return { + "runstamp": runstamp, + "treeref": treeref, + "cmdline": cmdline, + "options": options, + "host": host, + "gnatpro": gnatpro, + "gnatemu": gnatemu, + "gnatcov": gnatcov, + "other": other, + } class TC_status: @@ -112,6 +116,7 @@ def __init__(self, passed=None, xfail=None, status=None, comment=None): # Qualification Data classes, filled and dumped by testcases # + class QDentry: def __init__(self, xfile, drivers, xrnotes, wdir): """ @@ -132,6 +137,7 @@ class Qdata: sequence of QDentry instances; typically one per SCOV_helper execution (that is, per driver + consolidation spec). """ + def __init__(self, tcid): # These are filled and dumped by the testcase execution itself: self.entries = [] @@ -143,10 +149,10 @@ def register(self, ob): self.entries.append(ob) def flush(self): - dutils.pdump_to(qdaf_in('.'), o=self) + dutils.pdump_to(qdaf_in("."), o=self) -QUALDATA_FILE = 'tc' + STREXT +QUALDATA_FILE = "tc" + STREXT def qdaf_in(dirname): @@ -158,7 +164,7 @@ def qdaf_in(dirname): return os.path.join(dirname, QUALDATA_FILE) -STATUSDATA_FILE = 'tcs' + STREXT +STATUSDATA_FILE = "tcs" + STREXT def stdf_in(dirname): @@ -174,4 +180,4 @@ def treeref_at(dirname): directory trees. """ # Assuming git, sha1 for the HEAD reference - return output_of('git rev-parse HEAD', dir=dirname).rstrip('\n') + return output_of("git rev-parse HEAD", dir=dirname).rstrip("\n") diff --git a/testsuite/SUITE/srctracelib.py b/testsuite/SUITE/srctracelib.py index 413d1581d..9f0b39847 100755 --- a/testsuite/SUITE/srctracelib.py +++ b/testsuite/SUITE/srctracelib.py @@ -15,32 +15,32 @@ trace_file_header_struct = Struct( - 'trace file header', - ('magic', '32s'), - ('format_version', 'I'), - ('alignment', 'B'), - ('endianity', 'B'), - ('padding', 'H'), + "trace file header", + ("magic", "32s"), + ("format_version", "I"), + ("alignment", "B"), + ("endianity", "B"), + ("padding", "H"), ) trace_info_header_struct = Struct( - 'trace info header', - ('kind', 'I'), - ('length', 'I'), + "trace info header", + ("kind", "I"), + ("length", "I"), ) trace_entry_header_struct = Struct( - 'trace entry header', - ('unit_name_length', 'I'), - ('stmt_bit_count', 'I'), - ('dc_bit_count', 'I'), - ('mcdc_bit_count', 'I'), - ('language', 'B'), - ('unit_part', 'B'), - ('bit_buffer_encoding', 'B'), - ('fingerprint', '20B'), - ('bit_maps_fingerprint', '20B'), - ('padding', '5B'), + "trace entry header", + ("unit_name_length", "I"), + ("stmt_bit_count", "I"), + ("dc_bit_count", "I"), + ("mcdc_bit_count", "I"), + ("language", "B"), + ("unit_part", "B"), + ("bit_buffer_encoding", "B"), + ("fingerprint", "20B"), + ("bit_maps_fingerprint", "20B"), + ("padding", "5B"), ) @@ -62,8 +62,7 @@ def read_aligned(fp, count, alignment): padding_count = alignment - count % alignment if padding_count != alignment: padding = fp.read(padding_count) - assert (len(padding) == padding_count and - all(c == 0 for c in padding)) + assert len(padding) == padding_count and all(c == 0 for c in padding) return content @@ -84,7 +83,7 @@ def write_aligned(fp, data, alignment): # Write padding bytes padding_count = alignment - len(data) % alignment if padding_count != alignment: - padding = b'\x00' * padding_count + padding = b"\x00" * padding_count fp.write(padding) @@ -93,13 +92,13 @@ class SrcTraceFile(object): In-memory representation of a source trace file. """ - MAGIC = b'GNATcov source trace file' + b'\x00' * 7 + MAGIC = b"GNATcov source trace file" + b"\x00" * 7 FORMAT_VERSION = 3 ENDIANITY_NAMES = { - 0: 'little-endian', - 1: 'big-endian', + 0: "little-endian", + 1: "big-endian", } ENDIANITY_CODES = {value: key for key, value in ENDIANITY_NAMES.items()} @@ -109,7 +108,7 @@ def __init__(self, alignment, endianity, info_entries, entries): self.info_entries = info_entries self.entries = entries - self.big_endian = endianity == 'big-endian' + self.big_endian = endianity == "big-endian" @classmethod def read(cls, fp): @@ -118,27 +117,28 @@ def read(cls, fp): """ header = trace_file_header_struct.read(fp) - magic = header['magic'] + magic = header["magic"] if magic != cls.MAGIC: - raise ValueError('Invalid magic: {}'.format(magic)) + raise ValueError("Invalid magic: {}".format(magic)) - endianity = cls.ENDIANITY_NAMES[header['endianity']] + endianity = cls.ENDIANITY_NAMES[header["endianity"]] - format_version = header['format_version'] + format_version = header["format_version"] # We read the header as little-endian before knowing the trace file # endianity. This matters for the only multi-bytes field in this # header: the format version. Swap its bytes if the endianity is # actually big endian. - if endianity == 'big-endian': + if endianity == "big-endian": format_version = swap_bytes(format_version, 4) if format_version != cls.FORMAT_VERSION: - raise ValueError('Unsupported format version: {}' - .format(format_version)) + raise ValueError( + "Unsupported format version: {}".format(format_version) + ) - alignment = header['alignment'] + alignment = header["alignment"] if alignment not in (1, 2, 4, 8): - raise ValueError('Invalid alignment: {}'.format(alignment)) + raise ValueError("Invalid alignment: {}".format(alignment)) info_entries = [] entries = [] @@ -146,7 +146,7 @@ def read(cls, fp): while True: entry = TraceInfoEntry.read(fp, result, result.big_endian) - if entry.kind == 'end': + if entry.kind == "end": break info_entries.append(entry) @@ -160,45 +160,59 @@ def read(cls, fp): def write(self, fp): """Write this source trace to the `fp` file.""" - big_endian = self.endianity == 'big-endian' - - trace_file_header_struct.write(fp, { - 'magic': self.MAGIC, - 'format_version': self.FORMAT_VERSION, - 'alignment': self.alignment, - 'endianity': self.ENDIANITY_CODES[self.endianity], - 'padding': 0, - }, big_endian=big_endian) + big_endian = self.endianity == "big-endian" + + trace_file_header_struct.write( + fp, + { + "magic": self.MAGIC, + "format_version": self.FORMAT_VERSION, + "alignment": self.alignment, + "endianity": self.ENDIANITY_CODES[self.endianity], + "padding": 0, + }, + big_endian=big_endian, + ) for entry in self.info_entries: entry.write(fp, big_endian, self.alignment) - TraceInfoEntry('end', None).write(fp, big_endian, self.alignment) + TraceInfoEntry("end", None).write(fp, big_endian, self.alignment) for entry in self.entries: entry.write(fp, big_endian, self.alignment) def dump(self): def format_buffer(b): - bounds = ('[{}-{}]'.format(0, len(b.bits) - 1) - if len(b.bits) else '[empty range]') - content = (' '.join(str(i) for i, bit in enumerate(b.bits) if bit) - or '') - return '{} {}'.format(bounds, content) - - print('Source trace file:') - print(' Alignment: {}'.format(self.alignment)) - print(' Endianity: {}'.format(self.endianity)) - print('') + bounds = ( + "[{}-{}]".format(0, len(b.bits) - 1) + if len(b.bits) + else "[empty range]" + ) + content = ( + " ".join(str(i) for i, bit in enumerate(b.bits) if bit) + or "" + ) + return "{} {}".format(bounds, content) + + print("Source trace file:") + print(" Alignment: {}".format(self.alignment)) + print(" Endianity: {}".format(self.endianity)) + print("") for e in self.entries: - print(' Unit {} ({}, SCOS hash={}, bit maps hash={})'.format( - e.unit_name, e.unit_part, - ''.join('{:02x}'.format(b) for b in e.fingerprint), - ''.join('{:02x}'.format(b) for b in e.bit_maps_fingerprint) - )) - print(' Stmt buffer: {}'.format(format_buffer(e.stmt_buffer))) - print(' Dc buffer: {}'.format(format_buffer(e.dc_buffer))) - print(' MCDC buffer: {}'.format(format_buffer(e.mcdc_buffer))) - print('') + print( + " Unit {} ({}, SCOS hash={}, bit maps hash={})".format( + e.unit_name, + e.unit_part, + "".join("{:02x}".format(b) for b in e.fingerprint), + "".join( + "{:02x}".format(b) for b in e.bit_maps_fingerprint + ), + ) + ) + print(" Stmt buffer: {}".format(format_buffer(e.stmt_buffer))) + print(" Dc buffer: {}".format(format_buffer(e.dc_buffer))) + print(" MCDC buffer: {}".format(format_buffer(e.mcdc_buffer))) + print("") class TraceInfoEntry(object): @@ -207,10 +221,10 @@ class TraceInfoEntry(object): """ KIND_NAMES = { - 0: 'end', - 1: 'program-name', - 2: 'exec-date', - 3: 'user-data', + 0: "end", + 1: "program-name", + 2: "exec-date", + 3: "user-data", } KIND_CODES = {value: key for key, value in KIND_NAMES.items()} @@ -224,27 +238,31 @@ def read(cls, fp, trace_file, big_endian): Read a trace info entry from the `fp` file. Return a TraceInfoEntry instance. """ - with fp.label_context('trace info'): + with fp.label_context("trace info"): header = trace_info_header_struct.read(fp, big_endian=big_endian) if not header: return None - kind = cls.KIND_NAMES[header['kind']] + kind = cls.KIND_NAMES[header["kind"]] - if kind == 'end' and header['length']: + if kind == "end" and header["length"]: raise ValueError('invalid "end" marker') - with fp.label_context('data'): - data = read_aligned(fp, header['length'], trace_file.alignment) + with fp.label_context("data"): + data = read_aligned(fp, header["length"], trace_file.alignment) return cls(kind, data) def write(self, fp, big_endian, alignment): """Write this trace info entry to the `fp` file.""" - trace_info_header_struct.write(fp, { - 'kind': self.KIND_CODES[self.kind], - 'length': len(self.data) if self.data else 0, - }, big_endian=big_endian) + trace_info_header_struct.write( + fp, + { + "kind": self.KIND_CODES[self.kind], + "length": len(self.data) if self.data else 0, + }, + big_endian=big_endian, + ) if self.data: write_aligned(fp, self.data, alignment) @@ -255,27 +273,32 @@ class TraceEntry(object): """ UNIT_PART_NAMES = { - 0: 'not_applicable_part', - 1: 'body', - 2: 'spec', - 3: 'separate', + 0: "not_applicable_part", + 1: "body", + 2: "spec", + 3: "separate", } UNIT_PART_CODES = {value: key for key, value in UNIT_PART_NAMES.items()} - LANGUAGE_NAMES = { - 0: 'unit_based', - 1: 'file_based' - } + LANGUAGE_NAMES = {0: "unit_based", 1: "file_based"} LANGUAGE_CODES = {value: key for key, value in LANGUAGE_NAMES.items()} - BIT_BUFFER_ENCODING_NAMES = { - 0: 'lsb_first_bytes' - } + BIT_BUFFER_ENCODING_NAMES = {0: "lsb_first_bytes"} BIT_BUFFER_ENCODING_CODES = { - value: key for key, value in BIT_BUFFER_ENCODING_NAMES.items()} + value: key for key, value in BIT_BUFFER_ENCODING_NAMES.items() + } - def __init__(self, language, unit_part, unit_name, fingerprint, - bit_maps_fingerprint, stmt_buffer, dc_buffer, mcdc_buffer): + def __init__( + self, + language, + unit_part, + unit_name, + fingerprint, + bit_maps_fingerprint, + stmt_buffer, + dc_buffer, + mcdc_buffer, + ): self.language = language self.unit_part = unit_part self.unit_name = unit_name @@ -290,58 +313,79 @@ def read(cls, fp, trace_file, big_endian): """ Read a trace entry from the `fp` file. Return a TraceFile instance. """ - with fp.label_context('trace entry'): + with fp.label_context("trace entry"): header = trace_entry_header_struct.read(fp, big_endian=big_endian) if not header: return None - unit_part = cls.UNIT_PART_NAMES[header['unit_part']] + unit_part = cls.UNIT_PART_NAMES[header["unit_part"]] - language = cls.LANGUAGE_NAMES[header['language']] + language = cls.LANGUAGE_NAMES[header["language"]] - if header['padding'] != (0, 0, 0, 0, 0): - raise ValueError('Invalid padding: {}' - .format(header['padding'])) + if header["padding"] != (0, 0, 0, 0, 0): + raise ValueError( + "Invalid padding: {}".format(header["padding"]) + ) bit_buffer_encoding = cls.BIT_BUFFER_ENCODING_NAMES[ - header['bit_buffer_encoding']] + header["bit_buffer_encoding"] + ] - with fp.label_context('unit name'): + with fp.label_context("unit name"): unit_name = read_aligned( - fp, header['unit_name_length'], trace_file.alignment) + fp, header["unit_name_length"], trace_file.alignment + ) - with fp.label_context('stmt buffer'): + with fp.label_context("stmt buffer"): stmt_buffer = TraceBuffer.read( - fp, trace_file, bit_buffer_encoding, - header['stmt_bit_count']) - with fp.label_context('dc buffer'): + fp, + trace_file, + bit_buffer_encoding, + header["stmt_bit_count"], + ) + with fp.label_context("dc buffer"): dc_buffer = TraceBuffer.read( - fp, trace_file, bit_buffer_encoding, - header['dc_bit_count']) - with fp.label_context('mcdc buffer'): + fp, trace_file, bit_buffer_encoding, header["dc_bit_count"] + ) + with fp.label_context("mcdc buffer"): mcdc_buffer = TraceBuffer.read( - fp, trace_file, bit_buffer_encoding, - header['mcdc_bit_count']) - - return cls(language, unit_part, unit_name, - header['fingerprint'], header['bit_maps_fingerprint'], - stmt_buffer, dc_buffer, mcdc_buffer) + fp, + trace_file, + bit_buffer_encoding, + header["mcdc_bit_count"], + ) + + return cls( + language, + unit_part, + unit_name, + header["fingerprint"], + header["bit_maps_fingerprint"], + stmt_buffer, + dc_buffer, + mcdc_buffer, + ) def write(self, fp, big_endian, alignment): """Write this trace info entry to the `fp` file.""" - trace_entry_header_struct.write(fp, { - 'unit_name_length': len(self.unit_name), - 'stmt_bit_count': len(self.stmt_buffer.bits), - 'dc_bit_count': len(self.dc_buffer.bits), - 'mcdc_bit_count': len(self.mcdc_buffer.bits), - 'language': self.LANGUAGE_CODES[self.language], - 'unit_part': self.UNIT_PART_CODES[self.unit_part], - 'bit_buffer_encoding': - self.BIT_BUFFER_ENCODING_CODES['lsb_first_bytes'], - 'fingerprint': self.fingerprint, - 'bit_maps_fingerprint': self.bit_maps_fingerprint, - 'padding': (0, 0, 0, 0, 0), - }, big_endian=big_endian) + trace_entry_header_struct.write( + fp, + { + "unit_name_length": len(self.unit_name), + "stmt_bit_count": len(self.stmt_buffer.bits), + "dc_bit_count": len(self.dc_buffer.bits), + "mcdc_bit_count": len(self.mcdc_buffer.bits), + "language": self.LANGUAGE_CODES[self.language], + "unit_part": self.UNIT_PART_CODES[self.unit_part], + "bit_buffer_encoding": self.BIT_BUFFER_ENCODING_CODES[ + "lsb_first_bytes" + ], + "fingerprint": self.fingerprint, + "bit_maps_fingerprint": self.bit_maps_fingerprint, + "padding": (0, 0, 0, 0, 0), + }, + big_endian=big_endian, + ) write_aligned(fp, self.unit_name, alignment) @@ -371,7 +415,7 @@ def byte_count(bit_count): @classmethod def read(cls, fp, trace_file, bit_buffer_encoding, bit_count): - assert bit_buffer_encoding == 'lsb_first_bytes' + assert bit_buffer_encoding == "lsb_first_bytes" bytes_count = cls.byte_count(bit_count) bytes_and_padding = read_aligned(fp, bytes_count, trace_file.alignment) @@ -404,15 +448,16 @@ def write(self, fp, alignment): write_aligned(fp, bytes(byte for byte in buffer), alignment) -parser = argparse.ArgumentParser('Decode a source trace file') -parser.add_argument('--debug', '-d', action='store_true', - help='Enable debug traces') -parser.add_argument('trace-file', help='Source trace file to decode') +parser = argparse.ArgumentParser("Decode a source trace file") +parser.add_argument( + "--debug", "-d", action="store_true", help="Enable debug traces" +) +parser.add_argument("trace-file", help="Source trace file to decode") -if __name__ == '__main__': +if __name__ == "__main__": args = parser.parse_args() - with open(getattr(args, 'trace-file'), 'rb') as f: + with open(getattr(args, "trace-file"), "rb") as f: tf = SrcTraceFile.read(ByteStreamDecoder(f, args.debug)) tf.dump() diff --git a/testsuite/SUITE/stream_decoder.py b/testsuite/SUITE/stream_decoder.py index 9c0040134..ce438d8ae 100644 --- a/testsuite/SUITE/stream_decoder.py +++ b/testsuite/SUITE/stream_decoder.py @@ -6,7 +6,7 @@ def swap_bytes(number, size): """Swap bytes in ``number``, assumed to be ``size``-bytes large.""" result = 0 for _ in range(size): - result = (result << 8) | (number & 0xff) + result = (result << 8) | (number & 0xFF) number = number >> 8 return result @@ -17,7 +17,7 @@ class ByteStreamDecoder(object): """ BYTES_PER_LINE = 16 - INDENT = ' ' + INDENT = " " def __init__(self, stream, enabled=False, max_indent=0): """ @@ -41,7 +41,7 @@ def _print(self, message, *args, **kwargs): return if args or kwargs: message = message.format(*args, **kwargs) - print('{}{}'.format(self._indent_prefix, message)) + print("{}{}".format(self._indent_prefix, message)) @contextmanager def label_context(self, label): @@ -51,7 +51,7 @@ def label_context(self, label): :param str label: Label to use. """ - self._print('{} ({:#0x}):', label, self.offset) + self._print("{} ({:#0x}):", label, self.offset) self.label_stack.append(label) yield self.label_stack.pop() @@ -73,24 +73,25 @@ def read(self, size): bytes_part_size += max(0, len(self.INDENT) * reserved_indent) # Number of lines to represent bytes - lines_count = (len(bytes) + self.BYTES_PER_LINE - - 1) // self.BYTES_PER_LINE + lines_count = ( + len(bytes) + self.BYTES_PER_LINE - 1 + ) // self.BYTES_PER_LINE for line in range(lines_count): start_byte = line * self.BYTES_PER_LINE end_byte = (line + 1) * self.BYTES_PER_LINE bytes_slice = bytes[start_byte:end_byte] - bytes_part = ' '.join( - '{:02x}'.format(b) for b in bytes_slice + bytes_part = " ".join( + "{:02x}".format(b) for b in bytes_slice ).ljust(bytes_part_size) - ascii_part = ''.join( - chr(ord('.') if b < ord(' ') or b > ord('~') else b) + ascii_part = "".join( + chr(ord(".") if b < ord(" ") or b > ord("~") else b) for b in bytes_slice ) - self._print('{} | {}'.format(bytes_part, ascii_part)) + self._print("{} | {}".format(bytes_part, ascii_part)) self.offset += len(bytes) return bytes @@ -108,13 +109,15 @@ def __init__(self, label, *fields): :type fields: list[(str, str)] """ self.label = label - self.le_fields = [(name, struct.Struct('<' + fmt)) - for name, fmt in fields] - self.be_fields = [(name, struct.Struct('>' + fmt)) - for name, fmt in fields] + self.le_fields = [ + (name, struct.Struct("<" + fmt)) for name, fmt in fields + ] + self.be_fields = [ + (name, struct.Struct(">" + fmt)) for name, fmt in fields + ] def _fields(self, big_endian=False): - return (self.be_fields if big_endian else self.le_fields) + return self.be_fields if big_endian else self.le_fields def read(self, fp, big_endian=False): """ @@ -148,22 +151,26 @@ def write(self, fp, field_values, big_endian=False): field_values = [dict_field_values.pop(name) for name, _ in fields] unknown_fields = sorted(dict_field_values) if unknown_fields: - raise ValueError('Unknown fields: {}' - .format(' '.join(unknown_fields))) + raise ValueError( + "Unknown fields: {}".format(" ".join(unknown_fields)) + ) if len(field_values) != len(fields): - raise ValueError('{} fields expected, got {}' - .format(len(fields), len(field_values))) + raise ValueError( + "{} fields expected, got {}".format( + len(fields), len(field_values) + ) + ) for value, (_, structure) in zip(field_values, fields): - pack_args = value if isinstance(value, tuple) else (value, ) + pack_args = value if isinstance(value, tuple) else (value,) fp.write(structure.pack(*pack_args)) -if __name__ == '__main__': +if __name__ == "__main__": assert swap_bytes(0, 1) == 0 assert swap_bytes(0, 2) == 0 assert swap_bytes(1, 1) == 1 assert swap_bytes(1, 2) == 0x100 - assert swap_bytes(0xff, 2) == 0xff00 - assert swap_bytes(-1, 2) == 0xffff + assert swap_bytes(0xFF, 2) == 0xFF00 + assert swap_bytes(-1, 2) == 0xFFFF diff --git a/testsuite/SUITE/tgen.py b/testsuite/SUITE/tgen.py index 5a142a0a0..308b447d2 100644 --- a/testsuite/SUITE/tgen.py +++ b/testsuite/SUITE/tgen.py @@ -8,7 +8,7 @@ def body_lines(lines): - return '\n'.join(lines) + '\n' + return "\n".join(lines) + "\n" class Evaluator: @@ -18,35 +18,42 @@ def __init__(self, expr, context): class Ada_Evaluator(Evaluator): - def __init__(self, expr, context): Evaluator.__init__(self, expr, context) def package_spec(self): - return (body_lines(["package This_Evaluator is"]) + - self.expr.predefs() + - body_lines(["end;"])) + return ( + body_lines(["package This_Evaluator is"]) + + self.expr.predefs() + + body_lines(["end;"]) + ) def package_body(self): - return (body_lines(["package body This_Evaluator is"]) + - self.proc_body() + - body_lines(["end;"])) + return ( + body_lines(["package body This_Evaluator is"]) + + self.proc_body() + + body_lines(["end;"]) + ) def proc_formals(self): - return ', '.join("%s : %s" % (op.formal_name, op.formal_type) - for op in expr.op) + return ", ".join( + "%s : %s" % (op.formal_name, op.formal_type) for op in expr.op + ) def proc_body_start(self): - return body_lines(["procedure Eval (%s) is" % (self.proc_formals()), - "begin"]) + return body_lines( + ["procedure Eval (%s) is" % (self.proc_formals()), "begin"] + ) def proc_body_end(self): return body_lines(["end;"]) def proc_body(self): - return (self.proc_body_start() + - self.context.body_for(expr=self.expr) + - self.proc_body_end()) + return ( + self.proc_body_start() + + self.context.body_for(expr=self.expr) + + self.proc_body_end() + ) class OP: @@ -81,8 +88,9 @@ def __init__(self, opclasses): self.vectors = None self.next_arg_index = 0 - self.op = [opclass(formal_name=self.next_arg_name()) - for opclass in opclasses] + self.op = [ + opclass(formal_name=self.next_arg_name()) for opclass in opclasses + ] self.opclass_set = set(opclasses) @@ -95,7 +103,7 @@ def body(self): return "EXPR_NOBODY" def predefs(self): - return '\n'.join(opclass.predefs() for opclass in self.opclass_set) + return "\n".join(opclass.predefs() for opclass in self.opclass_set) class EXPR_And(EXPR): @@ -131,12 +139,15 @@ def body_for(self, expr): class CTX_AdaIf(Context): def body_for(self, expr): - return body_lines([ - "if %s then -- # eval-all :d:" % expr.body(), - " return True; -- # on-true", - "else", - " return False; -- # on-false", - "end if;"]) + return body_lines( + [ + "if %s then -- # eval-all :d:" % expr.body(), + " return True; -- # on-true", + "else", + " return False; -- # on-false", + "end if;", + ] + ) class Tcgen: @@ -155,8 +166,7 @@ def __init__(self, xprname, opkinds, vectors, lang): del op_classnames -expr = EXPR_Ada_AndThen(op0_class=OP_Ada_Bool, - op1_class=OP_Ada_Bool) +expr = EXPR_Ada_AndThen(op0_class=OP_Ada_Bool, op1_class=OP_Ada_Bool) for ctx in [CTX_AdaIf, CTX_AdaReturn]: aev = Ada_Evaluator(expr=expr, context=ctx()) diff --git a/testsuite/SUITE/tracelib.py b/testsuite/SUITE/tracelib.py index 2d27f0fb9..066aa0819 100644 --- a/testsuite/SUITE/tracelib.py +++ b/testsuite/SUITE/tracelib.py @@ -39,10 +39,8 @@ def check(cls, value): """ Assert that `value` is in `cls`'s range. """ - assert cls.in_range(value), 'Invalid {}: {} not in {} .. {}'.format( - cls.__name__, - value, - cls.RANGE[0], cls.RANGE[1] + assert cls.in_range(value), "Invalid {}: {} not in {} .. {}".format( + cls.__name__, value, cls.RANGE[0], cls.RANGE[1] ) @@ -50,6 +48,7 @@ class TraceKind(Enum): """ Kind of trace file. See Trace_Kind in qemu_traces.ads. """ + Flat = 0 History = 1 Info = 2 @@ -62,6 +61,7 @@ class InfoKind(Enum): """ Kind of trace information record. See Info_Kind_Type in qemu_traces.ads. """ + InfoEnd = 0 ExecFileName = 1 CoverageOptions = 2 @@ -81,6 +81,7 @@ class TraceOp(Enum): """ Trace operation bitmasks. See Trace_Op_* in qemu_traces.ads. """ + Block = 0x10 Fault = 0x20 Br0 = 0x01 @@ -88,9 +89,13 @@ class TraceOp(Enum): Special = 0x80 # Helper for the format_flags method, below - flag_chars = [(Block, 'B'), (Fault, 'F'), - (Br0, 'b'), (Br1, 'f'), - (Special, 's')] + flag_chars = [ + (Block, "B"), + (Fault, "F"), + (Br0, "b"), + (Br1, "f"), + (Special, "s"), + ] @classmethod def format_flags(cls, flags): @@ -104,14 +109,16 @@ def format_flags(cls, flags): :param int flags: Integer value for the TraceOp to decode. This is the integer that is read directly from the trace file. """ - return ''.join(char if flags & v else '-' - for v, char in cls.flag_images) + return "".join( + char if flags & v else "-" for v, char in cls.flag_images + ) class TraceSpecial(Enum): """ Special trace operations. See Trace_Special_* in qemu_traces.ads. """ + Loadaddr = 1 LoadSharedObject = 2 UnloadSharedObject = 3 @@ -119,7 +126,7 @@ class TraceSpecial(Enum): RANGE = (1, 3) -TRACE_MAGIC = b'#QEMU-Traces' +TRACE_MAGIC = b"#QEMU-Traces" """ Exepected value of the Magic header field. See Qemu_Trace_Magic in qemu_traces.ads. @@ -143,55 +150,49 @@ def create_trace_header(kind, pc_size, big_endian, machine): pc_size, big_endian, machine >> 8, - machine & 0xff, - 0 + machine & 0xFF, + 0, ) TraceHeaderStruct = Struct( - 'trace file header', - + "trace file header", # See Trace_Header in qemu_traces.ads - ('magic', '12s'), - ('version', 'B'), - ('kind', 'B'), - - ('sizeof_target_pc', 'B'), - ('big_endian', 'B'), - - ('machine_hi', 'B'), - ('machine_lo', 'B'), - ('padding', 'H'), + ("magic", "12s"), + ("version", "B"), + ("kind", "B"), + ("sizeof_target_pc", "B"), + ("big_endian", "B"), + ("machine_hi", "B"), + ("machine_lo", "B"), + ("padding", "H"), ) TraceInfoHeaderStruct = Struct( - 'trace info header', - + "trace info header", # See Trace_Info_Header in qemu_traces.ads - ('kind', 'I'), - ('length', 'I'), + ("kind", "I"), + ("length", "I"), ) TraceEntry32Struct = Struct( - 'trace entry 32', - + "trace entry 32", # See Trace_Entry32 in qemu_traces.ads - ('pc', 'I'), - ('size', 'H'), - ('op', 'B'), - ('padding', 'B'), + ("pc", "I"), + ("size", "H"), + ("op", "B"), + ("padding", "B"), ) TraceEntry64Struct = Struct( - 'trace entry 64', - + "trace entry 64", # See Trace_Entry64 in qemu_traces.ads - ('pc', 'Q'), - ('size', 'H'), - ('op', 'B'), - ('padding0', 'B'), - ('padding1', 'I'), + ("pc", "Q"), + ("size", "H"), + ("op", "B"), + ("padding0", "B"), + ("padding1", "I"), ) @@ -301,8 +302,8 @@ def iter_entries(self, raw=False): while True: loadaddr = next(entries) if ( - loadaddr.is_special and - loadaddr.size == TraceSpecial.Loadaddr + loadaddr.is_special + and loadaddr.size == TraceSpecial.Loadaddr ): offset = loadaddr.pc break @@ -358,27 +359,27 @@ def read(cls, fp): Read a trace info entry from the `fp` file. Return a TraceInfo instance. """ - with fp.label_context('trace info'): + with fp.label_context("trace info"): hdr = unpack_from_file(fp, TraceInfoHeaderStruct) assert hdr kind, length = hdr InfoKind.check(kind) - with fp.label_context('data'): + with fp.label_context("data"): data = fp.read(length) assert len(data) == length - with fp.label_context('padding'): + with fp.label_context("padding"): padding_size = cls.padding_size(len(data)) padding = fp.read(padding_size) - assert len(padding) == padding_size, ( - 'Expected {} padding bytes but got {}'.format( - padding_size, len(padding) - ) - ) - assert padding == (b'\x00' * padding_size), ( - 'Some padding bytes are non-null: {}'.format(repr(padding)) + assert ( + len(padding) == padding_size + ), "Expected {} padding bytes but got {}".format( + padding_size, len(padding) ) + assert padding == ( + b"\x00" * padding_size + ), "Some padding bytes are non-null: {}".format(repr(padding)) return cls(kind, data) @@ -388,7 +389,7 @@ def write(self, fp): """ TraceInfoHeaderStruct.write(fp, (self.kind, len(self.data))) fp.write(self.data) - fp.write(b'\x00' * self.padding_size(len(self.data))) + fp.write(b"\x00" * self.padding_size(len(self.data))) class TraceInfoList(object): @@ -473,7 +474,7 @@ def read(cls, fp, bits): """ Read a trace entry from the `fp` file. Return a TraceEntry instance. """ - with fp.label_context('trace entry'): + with fp.label_context("trace entry"): fields = unpack_from_file(fp, cls.struct(bits)) if not fields: return None @@ -516,38 +517,38 @@ def create_exec_infos(filename, code_size=None): :rtype: TraceInfoList """ stat = os.stat(filename) - with open(filename, 'rb') as f: + with open(filename, "rb") as f: f_contents = f.read() - crc32 = binascii.crc32(f_contents) & 0xffffffff - mtime = datetime.datetime.utcfromtimestamp( - int(stat.st_mtime) - ) + crc32 = binascii.crc32(f_contents) & 0xFFFFFFFF + mtime = datetime.datetime.utcfromtimestamp(int(stat.st_mtime)) def create_trace_info(kind, data_str): - return TraceInfo(kind, data_str.encode('utf-8')) + return TraceInfo(kind, data_str.encode("utf-8")) infos = [ create_trace_info(InfoKind.ExecFileName, filename), - create_trace_info(InfoKind.ExecFileSize, ' ' + str(stat.st_size)), - create_trace_info(InfoKind.ExecTimeStamp, mtime.isoformat(' ')), - create_trace_info(InfoKind.ExecFileCRC32, ' ' + str(crc32)), + create_trace_info(InfoKind.ExecFileSize, " " + str(stat.st_size)), + create_trace_info(InfoKind.ExecTimeStamp, mtime.isoformat(" ")), + create_trace_info(InfoKind.ExecFileCRC32, " " + str(crc32)), ] if code_size: - infos.append(create_trace_info(InfoKind.ExecCodeSize, - ' ' + str(code_size))) + infos.append( + create_trace_info(InfoKind.ExecCodeSize, " " + str(code_size)) + ) return TraceInfoList({info.kind: info for info in infos}) -parser = argparse.ArgumentParser('Decode a binary trace file') -parser.add_argument('--debug', '-d', action='store_true', - help='Enable debug traces') -parser.add_argument('trace-file', help='Binary trace file to decode') +parser = argparse.ArgumentParser("Decode a binary trace file") +parser.add_argument( + "--debug", "-d", action="store_true", help="Enable debug traces" +) +parser.add_argument("trace-file", help="Binary trace file to decode") -if __name__ == '__main__': +if __name__ == "__main__": args = parser.parse_args() - with open(getattr(args, 'trace-file'), 'rb') as f: + with open(getattr(args, "trace-file"), "rb") as f: tf = TraceFile.read(ByteStreamDecoder(f, args.debug, 4)) # TODO: add trace-file dump capabilities diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 8f072d8e4..bf5acd373 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -23,15 +23,26 @@ # Expose a few other items as a test util facilities as well from SUITE import control -from SUITE.control import (BUILDER, KNOWN_LANGUAGES, env, gnatemu_board_name, - language_info, xcov_pgm) +from SUITE.control import ( + BUILDER, + KNOWN_LANGUAGES, + env, + gnatemu_board_name, + language_info, + xcov_pgm, +) from SUITE.context import ROOT_DIR, thistest # Then mind our own business -from SUITE.cutils import (FatalError, contents_of, text_to_file, to_list, - unhandled_exception_in) +from SUITE.cutils import ( + FatalError, + contents_of, + text_to_file, + to_list, + unhandled_exception_in, +) # Precompute some values we might be using repeatedly @@ -41,10 +52,10 @@ GNATCOV_INFO = control.gnatcov_info() XCOV = xcov_pgm(thistest.options.auto_arch) -VALGRIND = 'valgrind' + env.host.os.exeext +VALGRIND = "valgrind" + env.host.os.exeext -MEMCHECK_LOG = 'memcheck.log' -CALLGRIND_LOG = 'callgrind-{}.log' +MEMCHECK_LOG = "memcheck.log" +CALLGRIND_LOG = "callgrind-{}.log" # Pattern to match the line in gprls' verbose output that specifies the full # path to the project file to analyze. @@ -115,7 +126,7 @@ def run_and_log(*args, **kwargs): # Register the command for this process as well as the time it took to run # it. try: - cmd = kwargs['cmds'] + cmd = kwargs["cmds"] except KeyError: cmd = args[0] p.original_cmd = cmd @@ -125,9 +136,7 @@ def run_and_log(*args, **kwargs): return p -def gprbuild_gargs_with(thisgargs, - trace_mode=None, - runtime_project=None): +def gprbuild_gargs_with(thisgargs, trace_mode=None, runtime_project=None): """ Compute and return all the toplevel gprbuild arguments to pass. Account for specific requests in THISGARGS. @@ -143,9 +152,9 @@ def gprbuild_gargs_with(thisgargs, # Force a few bits useful for practical reasons and without influence on # code generation result = [ - '-f', # always rebuild - '-XSTYLE_CHECKS=', # style checks off - '-p' # create missing directories (obj, typically) + "-f", # always rebuild + "-XSTYLE_CHECKS=", # style checks off + "-p", # create missing directories (obj, typically) ] result.extend(to_list(thisgargs)) @@ -153,10 +162,8 @@ def gprbuild_gargs_with(thisgargs, # instrumentation runtime project so that instrumented programs are # compilable in the generated projects. Also use instrumented sources in # the "*-gnatcov-instr" object directories. - if trace_mode == 'src': - runtime_project = ( - runtime_project or RUNTIME_INFO.gnatcov_rts_project - ) + if trace_mode == "src": + runtime_project = runtime_project or RUNTIME_INFO.gnatcov_rts_project result += [ f"--implicit-with={runtime_project}", "--src-subdirs=gnatcov-instr", @@ -180,10 +187,12 @@ def gprbuild_cargs_with(thiscargs, scovcargs=True, suitecargs=True): if thistest.options.qualif_level: thistest.stop_if( not scovcargs, - FatalError("SCOV_CARGS required for qualification test")) + FatalError("SCOV_CARGS required for qualification test"), + ) thistest.stop_if( thiscargs, - FatalError("Specific CARGS forbidden for qualification test")) + FatalError("Specific CARGS forbidden for qualification test"), + ) # Compute the language specific cargs, from testsuite args first: @@ -217,7 +226,7 @@ def gprbuild_cargs_with(thiscargs, scovcargs=True, suitecargs=True): other_cargs.extend(to_list(thiscargs)) if other_cargs: - other_cargs = ['-cargs'] + other_cargs + other_cargs = ["-cargs"] + other_cargs return lang_cargs + other_cargs @@ -233,15 +242,18 @@ def gprbuild_largs_with(thislargs): # On Windows, executables are made position independent by default, which # gnatcov does not handle, so instruct the linker to not create position # independent executables if running in bin trace mode. - if (thistest.env.build.os.name == 'windows' - and thistest.options.trace_mode == 'bin'): - all_largs.append('-no-pie') + if ( + thistest.env.build.os.name == "windows" + and thistest.options.trace_mode == "bin" + ): + all_largs.append("-no-pie") if all_largs: - all_largs.insert(0, '-largs') + all_largs.insert(0, "-largs") return all_largs + def gpr_common_args(project, auto_config_args=True): """ Return common GPR tools options for the current testsuite run. @@ -253,42 +265,47 @@ def gpr_common_args(project, auto_config_args=True): gproptions.append( # verbose mode for verifiability in qualif mode. # quiet mode for performance (less io) otherwise. - '-v' if thistest.options.qualif_level else '-q', + "-v" + if thistest.options.qualif_level + else "-q", ) if auto_config_args: - gproptions.append('--config={}' - .format(os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR))) + gproptions.append( + "--config={}".format(os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR)) + ) # Workaround a desynchronization between default build configuration # for TMS570 and GNATemulator's settings: see O519-032. We may get rid # of this kludge one day adapting GNATemulator. - if thistest.options.RTS and thistest.options.RTS.endswith('-tms570'): - gproptions.append('-XLOADER=LORAM') + if thistest.options.RTS and thistest.options.RTS.endswith("-tms570"): + gproptions.append("-XLOADER=LORAM") # For trace32 runs where the test is executed on a real board, we # choose to have both the code and data in RAM. The default is to run # from flash which would take more time for the probe to program. It # would also wear out the flash memory. if ( - thistest.options.gnatcov_run and - 'trace32' in thistest.options.gnatcov_run + thistest.options.gnatcov_run + and "trace32" in thistest.options.gnatcov_run ): - gproptions.append('-XLOADER=RAM') + gproptions.append("-XLOADER=RAM") return gproptions -def gprbuild(project, - scovcargs=True, - suitecargs=True, - extracargs=None, - gargs=None, - largs=None, - trace_mode=None, - runtime_project=None, - out='gprbuild.out', - register_failure=True, - auto_config_args=True): +def gprbuild( + project, + scovcargs=True, + suitecargs=True, + extracargs=None, + gargs=None, + largs=None, + trace_mode=None, + runtime_project=None, + out="gprbuild.out", + register_failure=True, + auto_config_args=True, +): """ Cleanup & build the provided PROJECT file using gprbuild, passing GARGS/CARGS/LARGS as gprbuild/cargs/largs command-line switches. Each @@ -319,9 +336,9 @@ def gprbuild(project, runtime_project=runtime_project, ) all_largs = gprbuild_largs_with(thislargs=largs) - all_cargs = gprbuild_cargs_with(scovcargs=scovcargs, - suitecargs=suitecargs, - thiscargs=extracargs) + all_cargs = gprbuild_cargs_with( + scovcargs=scovcargs, suitecargs=suitecargs, thiscargs=extracargs + ) common_args = gpr_common_args(project, auto_config_args) # Now cleanup, do build and check status @@ -337,8 +354,14 @@ def gprbuild(project, if builder is None: builder = BUILDER.BASE_COMMAND - args = (to_list(builder) + - ['-P%s' % project] + common_args + all_gargs + all_cargs + all_largs) + args = ( + to_list(builder) + + ["-P%s" % project] + + common_args + + all_gargs + + all_cargs + + all_largs + ) # If there is an altrun hook for gprbuild, it may be a script. # Instruct the Run primitive to parse the shebang to invoke the correct # interpreter in that case. @@ -349,8 +372,9 @@ def gprbuild(project, parse_shebang=has_altrun, ) if register_failure: - thistest.stop_if(p.status != 0, - FatalError("gprbuild exit in error", out)) + thistest.stop_if( + p.status != 0, FatalError("gprbuild exit in error", out) + ) return p @@ -361,8 +385,8 @@ def gprinstall(project, gargs=None): :param None|list[str] gargs: list of command line switches to pass to gprinstall """ - ofile = 'gprinstall.out' - args = ['gprinstall', '-P', project, '-p'] + ofile = "gprinstall.out" + args = ["gprinstall", "-P", project, "-p"] # Add mandatory options, such as target and RTS info args.extend(gpr_common_args(project)) @@ -371,8 +395,9 @@ def gprinstall(project, gargs=None): args.extend(to_list(gargs)) p = run_and_log(args, output=ofile, timeout=thistest.options.timeout) - thistest.stop_if(p.status != 0, - FatalError('gprinstall exit in error', ofile)) + thistest.stop_if( + p.status != 0, FatalError("gprinstall exit in error", ofile) + ) def gpr_emulator_package(): @@ -381,15 +406,29 @@ def gpr_emulator_package(): file to provide this information to GNATemulator. """ gnatemu_board = gnatemu_board_name(env.target.machine) - return ('package Emulator is\n' - ' for Board use "{}";\n' - 'end Emulator;'.format(gnatemu_board) - if gnatemu_board else '') + return ( + "package Emulator is\n" + ' for Board use "{}";\n' + "end Emulator;".format(gnatemu_board) + if gnatemu_board + else "" + ) -def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", - main_cargs=None, langs=None, deps=None, scenario_extra="", - compiler_extra="", extra="", cwd=None): +def gprfor( + mains, + prjid="gen", + srcdirs="src", + objdir=None, + exedir=".", + main_cargs=None, + langs=None, + deps=None, + scenario_extra="", + compiler_extra="", + extra="", + cwd=None, +): """ Generate a simple PRJID.gpr project file to build executables for each main source file in the MAINS list, sources in SRCDIRS. Inexistant directories @@ -416,29 +455,27 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", # Turn the list of main sources into the proper comma separated sequence # of string literals for the Main GPR attribute. - gprmains = ', '.join('"%s"' % m for m in mains) + gprmains = ", ".join('"%s"' % m for m in mains) if gprmains: - gprmains = 'for Main use (%s);' % gprmains + gprmains = "for Main use (%s);" % gprmains # Likewise for source dirs. Filter on existence, to allow widening the set # of tentative dirs while preventing complaints from gprbuild about # inexistent ones. - srcdirs_list = [ - d - for d in srcdirs - if os.path.exists(os.path.join(cwd, d)) - ] + srcdirs_list = [d for d in srcdirs if os.path.exists(os.path.join(cwd, d))] # Determine the language(s) from the sources if they are not explicitly # passed as parameters. if not langs: - lang_infos = [language_info(src) - for srcdir in srcdirs_list - for src in os.listdir(os.path.join(cwd, srcdir))] + lang_infos = [ + language_info(src) + for srcdir in srcdirs_list + for src in os.listdir(os.path.join(cwd, srcdir)) + ] langs = set(li.name for li in lang_infos if li) - srcdirs = ', '.join('"%s"' % d for d in srcdirs_list) - languages = ', '.join('"%s"' % lang for lang in langs) + srcdirs = ", ".join('"%s"' % d for d in srcdirs_list) + languages = ", ".join('"%s"' % lang for lang in langs) # In addition to the provided dependencies, figure out if this project # should extend or with some support or helper facilities. These are @@ -449,7 +486,8 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", # The base project file we need to extend, which drags libsupport, # and the way to refer to it from the project contents. basegpr = ( - "{}/support/base.gpr".format(ROOT_DIR) if not for_library else None) + "{}/support/base.gpr".format(ROOT_DIR) if not for_library else None + ) # For projects with an Ada main, provide visibility on the alternative # last chance handlers. Restricting this to Ada mains ensures that the @@ -463,7 +501,7 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", if not for_library and ".adb" in gprmains: deps.append("{}/support/lch.gpr".format(ROOT_DIR)) - deps = '\n'.join('with "%s";' % dep for dep in deps) + deps = "\n".join('with "%s";' % dep for dep in deps) # If we have specific flags for the mains, append them. This is # typically something like: @@ -472,29 +510,37 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", # Compiler'Default_Switches("Ada") & ("-fno-inline") compswitches = ( - '\n'.join( - ['for Switches("%s") use \n' - ' Compiler\'Default_Switches ("%s") & (%s);' % ( - main, language_info(main).name, ','.join( - ['"%s"' % carg for carg in to_list(main_cargs)])) - for main in mains] - ) + '\n') + "\n".join( + [ + 'for Switches("%s") use \n' + ' Compiler\'Default_Switches ("%s") & (%s);' + % ( + main, + language_info(main).name, + ",".join(['"%s"' % carg for carg in to_list(main_cargs)]), + ) + for main in mains + ] + ) + + "\n" + ) # Now instanciate, dump the contents into the target gpr file and return gprtext = template % { - 'prjname': prjid, - 'extends': ('extends "%s"' % basegpr) if basegpr else "", - 'scenario': scenario_extra, - 'srcdirs': srcdirs, - 'exedir': exedir, - 'objdir': objdir or (exedir + "/obj"), - 'compswitches': compswitches, - 'languages': languages, - 'gprmains': gprmains, - 'deps': deps, - 'compiler_extra': compiler_extra, - 'pkg_emulator': gpr_emulator_package(), - 'extra': extra} + "prjname": prjid, + "extends": ('extends "%s"' % basegpr) if basegpr else "", + "scenario": scenario_extra, + "srcdirs": srcdirs, + "exedir": exedir, + "objdir": objdir or (exedir + "/obj"), + "compswitches": compswitches, + "languages": languages, + "gprmains": gprmains, + "deps": deps, + "compiler_extra": compiler_extra, + "pkg_emulator": gpr_emulator_package(), + "extra": extra, + } return text_to_file( text=gprtext, filename=os.path.join(cwd, prjid + ".gpr") @@ -507,6 +553,7 @@ def gprfor(mains, prjid="gen", srcdirs="src", objdir=None, exedir=".", # PGNNAME is a program name, in the main subprogram name sense. An empty # PGMNAME is allowed, in which case the functions return only the extensions. + def exename_for(pgmname): """Name of the executable for the given program name""" return pgmname + TARGET_INFO.exeext @@ -530,8 +577,9 @@ def srctrace_pattern_for(pgmname, manual=False, manual_prj_name=None): return (manual_prj_name if manual else exename_for(pgmname)) + "*.srctrace" -def srctracename_for(pgmname, register_failure=True, manual=False, - manual_prj_name=None): +def srctracename_for( + pgmname, register_failure=True, manual=False, manual_prj_name=None +): """ Name for the source trace file for the given program name. @@ -571,6 +619,7 @@ def ckptname_for(pgmname): # tests that are going to search for exe filenames in outputs using regular # expressions, where backslashes as directory separators introduce confusion. + def exepath_to(pgmname): """ Return the absolute path to the executable file expected in the current @@ -595,16 +644,22 @@ def maybe_valgrind(command): """ if not thistest.options.enable_valgrind: prefix = [] - elif thistest.options.enable_valgrind == 'memcheck': - prefix = [VALGRIND, '-q', '--log-file=%s' % MEMCHECK_LOG] - elif thistest.options.enable_valgrind == 'callgrind': + elif thistest.options.enable_valgrind == "memcheck": + prefix = [VALGRIND, "-q", "--log-file=%s" % MEMCHECK_LOG] + elif thistest.options.enable_valgrind == "callgrind": log_file = CALLGRIND_LOG.format(thistest.create_callgrind_id()) prefix = [ - VALGRIND, '-q', '--tool=callgrind', - '--callgrind-out-file=%s' % log_file] + VALGRIND, + "-q", + "--tool=callgrind", + "--callgrind-out-file=%s" % log_file, + ] else: - raise ValueError('Invalid Valgrind tool: {}'.format( - thistest.options.enable_valgrind)) + raise ValueError( + "Invalid Valgrind tool: {}".format( + thistest.options.enable_valgrind + ) + ) return prefix + command @@ -643,10 +698,13 @@ def locate_gpr_file(gprswitches): ) -def xcov_suite_args(covcmd, covargs, - auto_config_args=True, - auto_target_args=True, - force_project_args=False): +def xcov_suite_args( + covcmd, + covargs, + auto_config_args=True, + auto_target_args=True, + force_project_args=False, +): """ Arguments we should pass to gnatcov to obey what we received on the command line, in particular --config and --target/--RTS. @@ -660,15 +718,16 @@ def xcov_suite_args(covcmd, covargs, project_handling_enabled = ( force_project_args or covcmd in ("setup", "setup-integration") - or any(arg.startswith('-P') for arg in covargs) + or any(arg.startswith("-P") for arg in covargs) ) # If --config is asked and project handling is involved, pass it and stop # there. If there is a board, it must be described in the project file # (gnatcov's -P argument). if auto_config_args and project_handling_enabled: - return ['--config={}' - .format(os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR))] + return [ + "--config={}".format(os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR)) + ] # Nothing to do if the caller does not want automatic --target/--RTS # arguments. @@ -715,7 +774,7 @@ def xcov_suite_args(covcmd, covargs, targetarg = None if targetarg: - result.append('--target=' + targetarg) + result.append("--target=" + targetarg) # Handle --RTS # @@ -723,13 +782,14 @@ def xcov_suite_args(covcmd, covargs, # *and* we pass a project file (proper GPR loading can require the # runtime information). if project_handling_enabled and thistest.options.RTS: - result.append('--RTS=' + thistest.options.RTS) + result.append("--RTS=" + thistest.options.RTS) return result -def cmdrun(cmd, for_pgm, inp=None, out=None, err=None, env=None, - register_failure=True): +def cmdrun( + cmd, for_pgm, inp=None, out=None, err=None, env=None, register_failure=True +): """ Execute the command+args list in CMD, redirecting its input, output and error streams to INP, OUT and ERR when not None, respectively. If ENV is @@ -750,8 +810,12 @@ def cmdrun(cmd, for_pgm, inp=None, out=None, err=None, env=None, kwargs = { key: value - for key, value in [('input', inp), ('output', out), ('error', err), - ('env', env)] + for key, value in [ + ("input", inp), + ("output", out), + ("error", err), + ("env", env), + ] if value } @@ -764,8 +828,10 @@ def cmdrun(cmd, for_pgm, inp=None, out=None, err=None, env=None, output = contents_of(out) if out else p.out thistest.stop( FatalError( - '"%s"' % ' '.join(cmd) + ' exit in error', - outfile=out, outstr=output) + '"%s"' % " ".join(cmd) + " exit in error", + outfile=out, + outstr=output, + ) ) if register_failure and for_pgm and thistest.options.target: @@ -773,16 +839,27 @@ def cmdrun(cmd, for_pgm, inp=None, out=None, err=None, env=None, thistest.stop_if( unhandled_exception_in(output), FatalError( - '"%s"' % ' '.join(cmd) + ' raised an unhandled exception', - outfile=out, outstr=output) + '"%s"' % " ".join(cmd) + " raised an unhandled exception", + outfile=out, + outstr=output, + ), ) return p -def xcov(args, out=None, err=None, inp=None, env=None, register_failure=True, - auto_config_args=True, auto_target_args=True, - force_project_args=False, auto_languages=True): +def xcov( + args, + out=None, + err=None, + inp=None, + env=None, + register_failure=True, + auto_config_args=True, + auto_target_args=True, + force_project_args=False, + auto_languages=True, +): """ Run xcov with arguments ARGS, timeout control, valgrind control if available and enabled, output directed to OUT and failure registration if @@ -801,9 +878,8 @@ def xcov(args, out=None, err=None, inp=None, env=None, register_failure=True, # gnatcov_rts in gprbuild's prefix, i.e. the current test will try to # modify a global resource. This is always an error, so reject it before it # causes hard to trace damage elsewhere. - assert ( - args[0] != "setup" - or any(arg.startswith("--prefix") for arg in args) + assert args[0] != "setup" or any( + arg.startswith("--prefix") for arg in args ) # Make ARGS a list from whatever it is, to allow unified processing. @@ -813,40 +889,62 @@ def xcov(args, out=None, err=None, inp=None, env=None, register_failure=True, covargs = args[1:] if thistest.options.all_warnings: - covargs = ['--all-warnings'] + covargs - - covargs = xcov_suite_args(covcmd, covargs, auto_config_args, - auto_target_args, force_project_args) + covargs + covargs = ["--all-warnings"] + covargs + + covargs = ( + xcov_suite_args( + covcmd, + covargs, + auto_config_args, + auto_target_args, + force_project_args, + ) + + covargs + ) # Determine which program we are actually going launch. This is # "gnatcov " unless we are to execute some designated program # for this: covpgm = thistest.suite_covpgm_for(covcmd) - covpgm = ([covpgm] if covpgm is not None - else maybe_valgrind([XCOV]) + [covcmd]) + covpgm = ( + [covpgm] if covpgm is not None else maybe_valgrind([XCOV]) + [covcmd] + ) # Execute, check status, raise on error and return otherwise. # # The gprvar options are only needed for the "libsupport" part of our # projects. They are pointless wrt coverage run or analysis activities # so we don't include them here. - p = cmdrun(cmd=covpgm + covargs, inp=inp, out=out, err=err, env=env, - register_failure=register_failure, - for_pgm=(covcmd == "run")) + p = cmdrun( + cmd=covpgm + covargs, + inp=inp, + out=out, + err=err, + env=env, + register_failure=register_failure, + for_pgm=(covcmd == "run"), + ) - if thistest.options.enable_valgrind == 'memcheck': + if thistest.options.enable_valgrind == "memcheck": memcheck_log = contents_of(MEMCHECK_LOG) thistest.fail_if( memcheck_log, - 'MEMCHECK log not empty' + "MEMCHECK log not empty" '\nFROM "%s":' - '\n%s' % (' '.join(covpgm + covargs), memcheck_log)) + "\n%s" % (" ".join(covpgm + covargs), memcheck_log), + ) return p -def xrun(args, out=None, env=None, register_failure=True, - auto_config_args=True, auto_target_args=True): +def xrun( + args, + out=None, + env=None, + register_failure=True, + auto_config_args=True, + auto_target_args=True, +): """ Run with arguments ARGS for the current target, performing operations only relevant to invocations intended to execute a program (for @@ -871,28 +969,35 @@ def xrun(args, out=None, env=None, register_failure=True, runargs = [] if thistest.options.kernel: - runargs.append('--kernel=' + thistest.options.kernel) + runargs.append("--kernel=" + thistest.options.kernel) runargs.extend(to_list(args)) if ( - thistest.options.trace_size_limit and - thistest.options.target and - not gnatemu_board_name(thistest.options.board) + thistest.options.trace_size_limit + and thistest.options.target + and not gnatemu_board_name(thistest.options.board) ): - if '-eargs' not in runargs: - runargs.append('-eargs') - runargs.extend(["-exec-trace-limit", - thistest.options.trace_size_limit]) + if "-eargs" not in runargs: + runargs.append("-eargs") + runargs.extend( + ["-exec-trace-limit", thistest.options.trace_size_limit] + ) - return xcov(['run'] + runargs, inp=nulinput, out=out, env=env, - register_failure=register_failure, - auto_config_args=auto_config_args, - auto_target_args=auto_target_args) + return xcov( + ["run"] + runargs, + inp=nulinput, + out=out, + env=env, + register_failure=register_failure, + auto_config_args=auto_config_args, + auto_target_args=auto_target_args, + ) -def run_cov_program(executable, out=None, env=None, exec_args=None, - register_failure=True): +def run_cov_program( + executable, out=None, env=None, exec_args=None, register_failure=True +): """ Assuming that `executable` was instrumented, run it according to the current target. @@ -967,24 +1072,25 @@ def do(command): class frame: - def register(self, text): if len(text) > self.width: self.width = len(text) def display(self): - thistest.log('\n' * self.pre + self.char * (self.width + 6)) + thistest.log("\n" * self.pre + self.char * (self.width + 6)) for text in self.lines: - thistest.log("%s %s %s" % ( - self.char * 2, text.center(self.width), self.char*2)) - thistest.log(self.char * (self.width + 6) + '\n' * self.post) + thistest.log( + "%s %s %s" + % (self.char * 2, text.center(self.width), self.char * 2) + ) + thistest.log(self.char * (self.width + 6) + "\n" * self.post) - def __init__(self, text, char='o', pre=1, post=1): + def __init__(self, text, char="o", pre=1, post=1): self.pre = pre self.post = post self.char = char self.width = 0 - self.lines = text.split('\n') + self.lines = text.split("\n") for text in self.lines: self.register(text) diff --git a/testsuite/altrun/ccg_native/cgprbuild.py b/testsuite/altrun/ccg_native/cgprbuild.py index 7db80a27e..b6adcab2e 100755 --- a/testsuite/altrun/ccg_native/cgprbuild.py +++ b/testsuite/altrun/ccg_native/cgprbuild.py @@ -60,7 +60,10 @@ def main(): parser.add_argument("--src-subdirs", dest="src_subdirs") parser.add_argument("--implicit-with", dest="implicit_with") parser.add_argument( - "-X", dest="scenario", action="append", type=parse_scenario, + "-X", + dest="scenario", + action="append", + type=parse_scenario, ) parser.add_argument("-v", dest="verbose", action="store_true") @@ -71,7 +74,9 @@ def main(): # Substitute the "--implicit-with=gnatcov_rts.gpr" to point it toward our # own custom RTS. ccg_gnatcov_rts = os.path.join( - altrun_dir, "ccg_gnatcov_rts", "gnatcov_rts.gpr", + altrun_dir, + "ccg_gnatcov_rts", + "gnatcov_rts.gpr", ) custom_rts_dir = None if args.implicit_with and "gnatcov_rts" in args.implicit_with: @@ -117,9 +122,9 @@ def main(): # Assume single main per project file main_name = os.path.basename(get_attr(prj, "Main")).split(".")[0] - prj_dir = get_attr(prj, "Project_Dir") - exec_dir = os.path.join(prj_dir, get_attr(prj, "Exec_Dir")) - obj_dir = os.path.join(prj_dir, get_attr(prj, "Object_Dir")) + prj_dir = get_attr(prj, "Project_Dir") + exec_dir = os.path.join(prj_dir, get_attr(prj, "Exec_Dir")) + obj_dir = os.path.join(prj_dir, get_attr(prj, "Object_Dir")) # Get the list of all the generated C files that need to be compiled. gprls # will return a list of ".o" files, so replace the extension to ".c" diff --git a/testsuite/altrun/ccg_native/pre_testsuite.py b/testsuite/altrun/ccg_native/pre_testsuite.py index 0adbd930b..89dc11925 100644 --- a/testsuite/altrun/ccg_native/pre_testsuite.py +++ b/testsuite/altrun/ccg_native/pre_testsuite.py @@ -114,10 +114,12 @@ def prepare_rts(): # Flag it as externally built amend_file( custom_rts_prj, - [( - "end GNATcov_RTS;", - 'for Externally_Built use "True"; end GNATcov_RTS;' - )], + [ + ( + "end GNATcov_RTS;", + 'for Externally_Built use "True"; end GNATcov_RTS;', + ) + ], ) @@ -163,7 +165,7 @@ def prepare_rts(): "--target=c", "--display=json-compact", ], - what="gprinspect invocation" + what="gprinspect invocation", ) try: prj_info = json.loads(prj_str) diff --git a/testsuite/altrun/example/crun.py b/testsuite/altrun/example/crun.py index 87c86c238..eefeee3f2 100755 --- a/testsuite/altrun/example/crun.py +++ b/testsuite/altrun/example/crun.py @@ -24,9 +24,7 @@ class Runner: - def __init__(self): - self.parse_command_line() self.run() @@ -37,31 +35,25 @@ def parse_command_line(self): # --level and --target are expected to always be there: - op.add_option( - "--level", dest="covlevel", default=None) - op.add_option( - "--target", dest="target", default=None) + op.add_option("--level", dest="covlevel", default=None) + op.add_option("--target", dest="target", default=None) # For source coverage tests not using project files: - op.add_option( - "--scos", dest="scos", default=None) + op.add_option("--scos", dest="scos", default=None) # For tests using project files + op.add_option("-P", dest="gpr", default=None) op.add_option( - "-P", dest="gpr", default=None) - op.add_option( - "--recursive", dest="recurse", default=False, action='store_true') - op.add_option( - "--projects", dest="projects", default=None) - op.add_option( - "--units", dest="units", default=None) + "--recursive", dest="recurse", default=False, action="store_true" + ) + op.add_option("--projects", dest="projects", default=None) + op.add_option("--units", dest="units", default=None) # Then a few optional items - op.add_option( - "-o", dest="ofile", default=None) + op.add_option("-o", dest="ofile", default=None) (self.options, self.args) = op.parse_args() @@ -92,7 +84,6 @@ def run_command_line(self): return args def run(self): - print("============== GNATCOV RUN ===================") if not self.args: @@ -100,7 +91,8 @@ def run(self): os.exit(1) e3.os.process.Run( - ['gnatcov', 'run'] + self.run_command_line() + self.args) + ["gnatcov", "run"] + self.run_command_line() + self.args + ) print("==============================================") diff --git a/testsuite/altrun/example/setup.py b/testsuite/altrun/example/setup.py index 37231dcf8..337a93333 100644 --- a/testsuite/altrun/example/setup.py +++ b/testsuite/altrun/example/setup.py @@ -6,8 +6,10 @@ from e3.os.process import Run import sys -p = Run(['gnatmake', '-f', '-g', '-p', '-Paltrun', 'pre_testsuite.adb'], - output=sys.stdout) +p = Run( + ["gnatmake", "-f", "-g", "-p", "-Paltrun", "pre_testsuite.adb"], + output=sys.stdout, +) if p.status != 0: sys.exit(1) diff --git a/testsuite/altrun/trace32/crun.py b/testsuite/altrun/trace32/crun.py index 72f3e0cba..12d6aac3d 100755 --- a/testsuite/altrun/trace32/crun.py +++ b/testsuite/altrun/trace32/crun.py @@ -34,10 +34,12 @@ def to_list(blob): and whitespace separated strings. Return empty list otherwise.""" return ( - blob if isinstance(blob, list) - else blob.split() if isinstance(blob, str) + blob + if isinstance(blob, list) + else blob.split() + if isinstance(blob, str) else [] - ) + ) # ----------------- @@ -68,9 +70,7 @@ def do(command): class Runner: - def __init__(self): - log("============== CRUN FOR TRACE32 ===================") self.parse_command_line() self.run_with_trace32() @@ -88,55 +88,31 @@ def parse_command_line(self): # --level and --target are expected to always be there: - op.add_option( - "--level", dest="covlevel", default=None - ) - op.add_option( - "--target", dest="target", default=None - ) - op.add_option( - "--RTS", dest="RTS", default=None - ) - op.add_option( - "--config", dest="config", default=None - ) + op.add_option("--level", dest="covlevel", default=None) + op.add_option("--target", dest="target", default=None) + op.add_option("--RTS", dest="RTS", default=None) + op.add_option("--config", dest="config", default=None) # For source coverage tests not using project files: - op.add_option( - "--scos", dest="scos", default=None - ) + op.add_option("--scos", dest="scos", default=None) # For tests using project files + op.add_option("-P", dest="gpr", default=None) op.add_option( - "-P", dest="gpr", default=None - ) - op.add_option( - "--recursive", dest="recurse", default=False, action='store_true' - ) - op.add_option( - "--projects", dest="projects", default=None - ) - op.add_option( - "--units", dest="units", default=None - ) - op.add_option( - "--subdirs", dest="subdirs", default=None - ) - op.add_option( - "-v", "--verbose", dest="verbose", default=None - ) + "--recursive", dest="recurse", default=False, action="store_true" + ) + op.add_option("--projects", dest="projects", default=None) + op.add_option("--units", dest="units", default=None) + op.add_option("--subdirs", dest="subdirs", default=None) + op.add_option("-v", "--verbose", dest="verbose", default=None) - op.add_option( - "--exec-prefix", dest="execprefix", default=None - ) + op.add_option("--exec-prefix", dest="execprefix", default=None) # Then a few optional items - op.add_option( - "-o", dest="ofile", default=None - ) + op.add_option("-o", dest="ofile", default=None) (self.options, self.args) = op.parse_args() @@ -227,7 +203,7 @@ def get_gnatcov_trace_filename(self): return os.path.basename(self.get_executable_filename()) + ".trace" def get_t32_trace_filename(self): - return self.get_gnatcov_trace_filename() + '.t32_branchflow' + return self.get_gnatcov_trace_filename() + ".t32_branchflow" def run_with_trace32(self): print("=============== RUN ON TRACE32 ===================") @@ -236,7 +212,7 @@ def run_with_trace32(self): sys.exit(1) log("Executable is: " + str(self.args)) - handled_targets = ['trace32-stm32f7'] + handled_targets = ["trace32-stm32f7"] if self.options.target not in handled_targets: print("unknown target %s" % self.options.target) return @@ -244,7 +220,7 @@ def run_with_trace32(self): t32api.connect() t32api.basic_setup() - if self.options.target == 'trace32-stm32f7': + if self.options.target == "trace32-stm32f7": t32api.init_trace_stm32f7() t32api.load_executable(self.get_executable_filename()) diff --git a/testsuite/altrun/trace32/pre_testsuite.py b/testsuite/altrun/trace32/pre_testsuite.py index 2c5d1e87c..8eb36515a 100644 --- a/testsuite/altrun/trace32/pre_testsuite.py +++ b/testsuite/altrun/trace32/pre_testsuite.py @@ -13,10 +13,11 @@ def log(str): altrun_dir_path = os.path.dirname(os.path.realpath(__file__)) -os.environ['T32SYS'] = PATH_TO_T32_HOME -os.environ['T32TMP'] = "/tmp" -os.environ['T32PDFVIEWER'] = \ +os.environ["T32SYS"] = PATH_TO_T32_HOME +os.environ["T32TMP"] = "/tmp" +os.environ["T32PDFVIEWER"] = ( PATH_TO_T32_HOME + "/bin/pc_linux64/t32_startpdfviewer.sh" +) # Run t32usbchecker to reset the probe in case it is already connected. # @@ -27,15 +28,16 @@ def log(str): # It should be possble to achive the same result with the # CONNECTIONMODE=AUTOCONNECT parameter of the configuration, however this # parameter doesn't work with the SCREEN=OFF mode. -p = e3.os.process.Run([os.path.dirname(PATH_TO_T32) + '/t32usbchecker'], - output="t32usbchecker.out", - bg=False) - -p = e3.os.process.Run([PATH_TO_T32, - "-c", - os.path.join(altrun_dir_path, 'config.t32') - ], - output="t32.out", - bg=True) +p = e3.os.process.Run( + [os.path.dirname(PATH_TO_T32) + "/t32usbchecker"], + output="t32usbchecker.out", + bg=False, +) + +p = e3.os.process.Run( + [PATH_TO_T32, "-c", os.path.join(altrun_dir_path, "config.t32")], + output="t32.out", + bg=True, +) sleep(20) diff --git a/testsuite/altrun/trace32/t32api.py b/testsuite/altrun/trace32/t32api.py index d47f8b890..8e94ab33e 100644 --- a/testsuite/altrun/trace32/t32api.py +++ b/testsuite/altrun/trace32/t32api.py @@ -8,43 +8,40 @@ T32_OK = 0 EXIT_FAILURE = 1 -PATH_TO_T32 = find_executable('t32marm-qt') +PATH_TO_T32 = find_executable("t32marm-qt") # We can't continue without a t32 executable assert PATH_TO_T32, "no Trace32 executable on path" -PATH_TO_T32_HOME = os.path.join(os.path.dirname(PATH_TO_T32), '../../') -PATH_TO_T32_PY_API = os.path.join(PATH_TO_T32_HOME, 'demo/api/python/legacy') +PATH_TO_T32_HOME = os.path.join(os.path.dirname(PATH_TO_T32), "../../") +PATH_TO_T32_PY_API = os.path.join(PATH_TO_T32_HOME, "demo/api/python/legacy") # auto-detect the correct library -if (platform.system() == 'Windows') or (platform.system()[0:6] == 'CYGWIN'): +if (platform.system() == "Windows") or (platform.system()[0:6] == "CYGWIN"): if ctypes.sizeof(ctypes.c_voidp) == 4: # WINDOWS 32bit t32 = ctypes.cdll.t32api else: # WINDOWS 64bit t32 = ctypes.cdll.t32api64 -elif platform.system() == 'Darwin': +elif platform.system() == "Darwin": # Mac OS X - t32 = ctypes.CDLL(os.path.join(PATH_TO_T32_PY_API, - "./t32api.dylib")) + t32 = ctypes.CDLL(os.path.join(PATH_TO_T32_PY_API, "./t32api.dylib")) else: if ctypes.sizeof(ctypes.c_voidp) == 4: # Linux 32bit - t32 = ctypes.CDLL(os.path.join(PATH_TO_T32_PY_API, - "./t32api.so")) + t32 = ctypes.CDLL(os.path.join(PATH_TO_T32_PY_API, "./t32api.so")) else: # Linux 64bit - t32 = ctypes.CDLL(os.path.join(PATH_TO_T32_PY_API, - "./t32api64.so")) + t32 = ctypes.CDLL(os.path.join(PATH_TO_T32_PY_API, "./t32api64.so")) # ----------------- # -- cmd_wrapper -- # ----------------- -def cmd_wrapper(cmd, wait_for_completion=False): +def cmd_wrapper(cmd, wait_for_completion=False): t32.T32_Cmd(cmd.encode()) if wait_for_completion: @@ -62,37 +59,48 @@ def cmd_wrapper(cmd, wait_for_completion=False): # -- connect -- # ------------- + def connect(node="localhost", port=20000, packlen=1024): t32.T32_Config(b"NODE=", node.encode()) t32.T32_Config(b"PORT=", str(port).encode()) t32.T32_Config(b"PACKLEN=", str(packlen).encode()) - print(' Connecting...') + print(" Connecting...") for i in range(1, 3): if t32.T32_Init() == T32_OK: if t32.T32_Attach(1) == T32_OK: - print('Successfully established a remote connection with' + - ' TRACE32 PowerView.') + print( + "Successfully established a remote connection with" + + " TRACE32 PowerView." + ) break else: if i == 1: - print('Failed once to established a remote connection' + - ' with TRACE32 PowerView.') + print( + "Failed once to established a remote connection" + + " with TRACE32 PowerView." + ) t32.T32_Exit() elif i == 2: - print('Failed twice to established a remote connection' + - ' with TRACE32 PowerView.') - print('Terminating ...') + print( + "Failed twice to established a remote connection" + + " with TRACE32 PowerView." + ) + print("Terminating ...") sys.exit(EXIT_FAILURE) else: if i == 1: - print(' Failed once to initialize a remote connection with' + - ' TRACE32 PowerView.') + print( + " Failed once to initialize a remote connection with" + + " TRACE32 PowerView." + ) t32.T32_Exit() elif i == 2: - print(' Failed twice to initialize a remote connection with' + - ' TRACE32 PowerView.') - print(' Terminating ...') + print( + " Failed twice to initialize a remote connection with" + + " TRACE32 PowerView." + ) + print(" Terminating ...") sys.exit(EXIT_FAILURE) @@ -100,6 +108,7 @@ def connect(node="localhost", port=20000, packlen=1024): # -- basic_setup -- # ----------------- + def basic_setup(): cmd_wrapper("RESet") cmd_wrapper("SYStem.RESet") @@ -115,6 +124,7 @@ def basic_setup(): # -- init_trace_stm32f7 -- # ------------------------ + def init_trace_stm32f7(): # initialize Offchip-Trace # DBGMCU_CR @@ -129,16 +139,19 @@ def init_trace_stm32f7(): cmd_wrapper("Data.Set E:0x40023830 %Long Data.Long(E:0x40023830)|0x10") # GPIOE_MODER - cmd_wrapper("Data.Set E:0x40021000 %Long" + - " Data.Long(E:0x40021000)|0x00002aa0") + cmd_wrapper( + "Data.Set E:0x40021000 %Long" + " Data.Long(E:0x40021000)|0x00002aa0" + ) # GPIOE_OSPEEDR - cmd_wrapper("Data.Set E:0x40021008 %Long" + - " Data.Long(E:0x40021008)|0x00003ff0") + cmd_wrapper( + "Data.Set E:0x40021008 %Long" + " Data.Long(E:0x40021008)|0x00003ff0" + ) # GPIOE_AFRL - cmd_wrapper("Data.Set E:0x40021020 %Long" + - " Data.Long(E:0x40021020)&0xf00000ff") + cmd_wrapper( + "Data.Set E:0x40021020 %Long" + " Data.Long(E:0x40021020)&0xf00000ff" + ) cmd_wrapper("TPIU.PortSize 4", wait_for_completion=True) cmd_wrapper("ETM.Trace ON", wait_for_completion=True) @@ -149,23 +162,24 @@ def init_trace_stm32f7(): # -- load_executable -- # --------------------- -def load_executable(path): +def load_executable(path): # The old breakpoints don't make sense with a new executable so we remove # them all. clear_breakpoints() - cmd_wrapper(f"Data.Load.auto \"{path}\"", wait_for_completion=True) + cmd_wrapper(f'Data.Load.auto "{path}"', wait_for_completion=True) # ------------------- # -- get_cpu_state -- # ------------------- + def get_cpu_state(): systemstate = ctypes.c_uint(0) retval = t32.T32_GetState(ctypes.byref(systemstate)) - if (retval == T32_OK): + if retval == T32_OK: states = ["down", "halted", "stopped", "running"] # Safeguard the little trick @@ -181,8 +195,8 @@ def get_cpu_state(): # -- run_until -- # --------------- -def run_until(symbol, timeout_sec): +def run_until(symbol, timeout_sec): # FIXME: It seems like we have to first do at least one step before using # go.direct. I don't know why at this point. cmd_wrapper("Step.Single 1", wait_for_completion=True) @@ -190,8 +204,7 @@ def run_until(symbol, timeout_sec): cmd_wrapper(f"go.direct {symbol}") # Wait for the CPU to stop or timeout - cmd_wrapper(f"WAIT !STATE.RUN() {timeout_sec}.s", - wait_for_completion=True) + cmd_wrapper(f"WAIT !STATE.RUN() {timeout_sec}.s", wait_for_completion=True) if get_cpu_state() == "running": # Stop the CPU @@ -203,28 +216,32 @@ def run_until(symbol, timeout_sec): # -- set_breakpoint -- # -------------------- + def set_breakpoint(symbol): T32_MEMORY_ACCESS_PROGRAM = 0x1 T32_BPCONFIG_PROGRAM = 0x001 addr = ctypes.c_uint32(get_symbol_address(symbol)) - return t32.T32_WriteBreakpoint(addr, T32_MEMORY_ACCESS_PROGRAM, - T32_BPCONFIG_PROGRAM, 1) + return t32.T32_WriteBreakpoint( + addr, T32_MEMORY_ACCESS_PROGRAM, T32_BPCONFIG_PROGRAM, 1 + ) # ------------------------ # -- get_symbol_address -- # ------------------------ -def get_symbol_address(symbol_name): +def get_symbol_address(symbol_name): addr = ctypes.c_uint32(0) size = ctypes.c_uint32(0) access = ctypes.c_uint32(0) - ret = t32.T32_GetSymbol(symbol_name, - ctypes.byref(addr), - ctypes.byref(size), - ctypes.byref(access)) + ret = t32.T32_GetSymbol( + symbol_name, + ctypes.byref(addr), + ctypes.byref(size), + ctypes.byref(access), + ) if ret == T32_OK: return addr.value @@ -236,12 +253,13 @@ def get_symbol_address(symbol_name): # -- read_register_by_name -- # --------------------------- + def read_register_by_name(name): upper = ctypes.c_uint32(0) lower = ctypes.c_uint32(0) - ret = t32.T32_ReadRegisterByName(name, - ctypes.byref(lower), - ctypes.byref(upper)) + ret = t32.T32_ReadRegisterByName( + name, ctypes.byref(lower), ctypes.byref(upper) + ) if ret == T32_OK: return upper.value * 2**32 + lower.value else: @@ -252,16 +270,20 @@ def read_register_by_name(name): # -- export_trace -- # ------------------ + def export_trace(path): cmd_wrapper("Trace.FLOWPROCESS", wait_for_completion=True) - cmd_wrapper(f"Trace.export.BranchFlow {path} /NOSYMBOL /CALLER", - wait_for_completion=True) + cmd_wrapper( + f"Trace.export.BranchFlow {path} /NOSYMBOL /CALLER", + wait_for_completion=True, + ) # --------------------------- # -- CPU_stopped_at_symbol -- # --------------------------- + def CPU_stopped_at_symbol(symbol): sym_addr = get_symbol_address(symbol) pc_addr = read_register_by_name("PC") @@ -273,6 +295,7 @@ def CPU_stopped_at_symbol(symbol): # -- clear_breakpoints -- # ----------------------- + def clear_breakpoints(): cmd_wrapper("Break.Reset") @@ -281,6 +304,7 @@ def clear_breakpoints(): # -- kill_trace32 -- # ------------------ + def kill_trace32(): connect() t32.T32_Terminate(0) diff --git a/testsuite/nexus_info.py b/testsuite/nexus_info.py index b98ec17ca..051d713e6 100644 --- a/testsuite/nexus_info.py +++ b/testsuite/nexus_info.py @@ -2,7 +2,7 @@ import isystem.connect as ic cmgr = ic.ConnectionMgr() -cmgr.connectMRU('') +cmgr.connectMRU("") ideController = ic.CIDEController(cmgr) @@ -11,31 +11,32 @@ def winIDEA_version(): def firmware_revision(): - firmwareDateInstalledUrl = '/iOPEN/SystemConfig.Firmware.DateInstalled' + firmwareDateInstalledUrl = "/iOPEN/SystemConfig.Firmware.DateInstalled" firmwareDateInstalled = ideController.getOptionInt( - firmwareDateInstalledUrl) + firmwareDateInstalledUrl + ) year = firmwareDateInstalled >> 16 month = (firmwareDateInstalled & 0xFF00) >> 8 - date = (firmwareDateInstalled & 0xFF) + date = firmwareDateInstalled & 0xFF - return '{}{:02d}{:02d}'.format(year, month, date) + return "{}{:02d}{:02d}".format(year, month, date) def probe_model(): # No way to retrieve this automatically. This is what we have: - return 'iSystem iC5000' + return "iSystem iC5000" def workspace_file(): - return ' '.join(fu.find(root="altrun", pattern="justrun.xjrf")) + return " ".join(fu.find(root="altrun", pattern="justrun.xjrf")) -print ( +print( "Nexus Framework ## " "Probe Model: %s, " "Firmware: %s, " "winIDEA: %s, " - "Workspace: %s") % \ - (probe_model(), firmware_revision(), winIDEA_version(), workspace_file()) + "Workspace: %s" +) % (probe_model(), firmware_revision(), winIDEA_version(), workspace_file()) cmgr.disconnect(0) diff --git a/testsuite/tests/106-externally-built-header/test.py b/testsuite/tests/106-externally-built-header/test.py index e85af939d..172fc50ba 100644 --- a/testsuite/tests/106-externally-built-header/test.py +++ b/testsuite/tests/106-externally-built-header/test.py @@ -36,7 +36,9 @@ gprinstall(mylib_gpr, f"--prefix={install_dir}") # Build the main project using this and run it to produce a trace file -main_gpr = gprfor(mains=["main.c"], srcdirs=os.path.join("..", "main"), deps=["mylib"]) +main_gpr = gprfor( + mains=["main.c"], srcdirs=os.path.join("..", "main"), deps=["mylib"] +) xcov_args = build_run_and_coverage( gprsw=GPRswitches(root_project=main_gpr), covlevel="stmt", diff --git a/testsuite/tests/127-check-line-endings/test.py b/testsuite/tests/127-check-line-endings/test.py index 0ce760832..01f55c2ff 100644 --- a/testsuite/tests/127-check-line-endings/test.py +++ b/testsuite/tests/127-check-line-endings/test.py @@ -13,23 +13,24 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src') + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) # Check line endings with open(os.path.join("obj", "gen-gnatcov-instr", "main.adb"), "rb") as f: content = f.read() thistest.fail_if( - b'\r\r\n' in content, + b"\r\r\n" in content, comment="wrong line ending in instrumented source", ) -check_xcov_reports('xcov', {'main.adb.xcov': {'+': {5}}}) +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {5}}}) thistest.result() diff --git a/testsuite/tests/129-instr-progress/test.py b/testsuite/tests/129-instr-progress/test.py index 2da846687..9e6a98e6a 100644 --- a/testsuite/tests/129-instr-progress/test.py +++ b/testsuite/tests/129-instr-progress/test.py @@ -68,15 +68,17 @@ class Section: thistest.fail_if_not_equal( "'gnatcov instrument' output", - "\n".join([ - "", - "Coverage instrumentation", - " [Ada] main", - " [C++] cpp_unit.cpp", - " [C] c_unit.c", - "Main instrumentation", - " [Ada] main", - ]), + "\n".join( + [ + "", + "Coverage instrumentation", + " [Ada] main", + " [C++] cpp_unit.cpp", + " [C] c_unit.c", + "Main instrumentation", + " [Ada] main", + ] + ), "\n".join(sorted_lines), ) diff --git a/testsuite/tests/138-ada-preprocessing/example/test.py b/testsuite/tests/138-ada-preprocessing/example/test.py index dc7ade4af..981bc514c 100644 --- a/testsuite/tests/138-ada-preprocessing/example/test.py +++ b/testsuite/tests/138-ada-preprocessing/example/test.py @@ -48,18 +48,30 @@ "+": { # Eval header 13, - # Pop - 27, 31, - + 27, + 31, # Push - 43, 44, - + 43, + 44, # Eval loop - 61, 62, 70, 72, 87, 89, 90, 96, - + 61, + 62, + 70, + 72, + 87, + 89, + 90, + 96, # Eval wrapper - 117, 118, 121, 122, 123, 125, 126, 127, + 117, + 118, + 121, + 122, + 123, + 125, + 126, + 127, }, "!": { # Branch condition evaluation @@ -68,12 +80,11 @@ "-": { # Jump 75, - # Branch jump 79, - # Push_Lit, Add - 83, 94, + 83, + 94, }, }, }, diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/test.py b/testsuite/tests/138-ada-preprocessing/prep_data/test.py index fd028ed8d..3bc389fa5 100644 --- a/testsuite/tests/138-ada-preprocessing/prep_data/test.py +++ b/testsuite/tests/138-ada-preprocessing/prep_data/test.py @@ -23,6 +23,7 @@ class BaseTestcase: @dataclass class InstrErrorTestcase(BaseTestcase): """Testcase that expects an instrumentation error.""" + expected_msg: str """Regexp for the expected instrumentation error message.""" diff --git a/testsuite/tests/14-unused-separate/compilable/test.py b/testsuite/tests/14-unused-separate/compilable/test.py index aa75aa20f..9ab1e8d71 100644 --- a/testsuite/tests/14-unused-separate/compilable/test.py +++ b/testsuite/tests/14-unused-separate/compilable/test.py @@ -13,8 +13,11 @@ Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], - srcdirs=["../src", "../../src"])), + gprsw=GPRswitches( + root_project=gprfor( + mains=["main.adb"], srcdirs=["../src", "../../src"] + ) + ), covlevel="stmt", mains=["main"], extra_coverage_args=["--annotate=xcov"], diff --git a/testsuite/tests/14-unused-separate/uncompilable/test.py b/testsuite/tests/14-unused-separate/uncompilable/test.py index 0502ce090..89f6a7073 100644 --- a/testsuite/tests/14-unused-separate/uncompilable/test.py +++ b/testsuite/tests/14-unused-separate/uncompilable/test.py @@ -14,8 +14,11 @@ Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], - srcdirs=["../src", "../../src"])), + gprsw=GPRswitches( + root_project=gprfor( + mains=["main.adb"], srcdirs=["../src", "../../src"] + ) + ), covlevel="stmt", mains=["main"], extra_coverage_args=["--annotate=xcov"], diff --git a/testsuite/tests/15-non-instr-cons/test.py b/testsuite/tests/15-non-instr-cons/test.py index 9fed5b080..6377b2ffb 100644 --- a/testsuite/tests/15-non-instr-cons/test.py +++ b/testsuite/tests/15-non-instr-cons/test.py @@ -27,8 +27,7 @@ covlevel="stmt", mains=["test_f", "test_t"], trace_mode="src", - tolerate_instrument_messages=\ - "gnatcov limitation: cannot instrument an expression function", + tolerate_instrument_messages="gnatcov limitation: cannot instrument an expression function", ) trace_t = xcov_args.pop() @@ -41,6 +40,6 @@ # Try to consolidate the checkpoint xcov(xcov_args + ["-Ctest_t.ckpt", "-Ctest_f.ckpt", "-axcov"]) -check_xcov_reports("obj", {"pkg.ads.xcov": {"?": {10}, "+": {5,6,7}}}) +check_xcov_reports("obj", {"pkg.ads.xcov": {"?": {10}, "+": {5, 6, 7}}}) thistest.result() diff --git a/testsuite/tests/152-shared_setup/test.py b/testsuite/tests/152-shared_setup/test.py index 8a14d7fd5..403b33647 100644 --- a/testsuite/tests/152-shared_setup/test.py +++ b/testsuite/tests/152-shared_setup/test.py @@ -101,7 +101,7 @@ # Ignore exit status as there's no way with a light runtime to set the exit # status to 0. run_cov_program( - exepath_to ("main"), + exepath_to("main"), out=run_log, register_failure=False, ) diff --git a/testsuite/tests/16-check-html/test.py b/testsuite/tests/16-check-html/test.py index fd6f7c45d..5f06b8490 100644 --- a/testsuite/tests/16-check-html/test.py +++ b/testsuite/tests/16-check-html/test.py @@ -13,8 +13,7 @@ Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(mains=["foo.adb"], - srcdirs=[".."])), + gprsw=GPRswitches(root_project=gprfor(mains=["foo.adb"], srcdirs=[".."])), covlevel="stmt", mains=["foo"], extra_coverage_args=["--annotate=html", "--output-dir=html"], @@ -22,8 +21,7 @@ js_file = os.path.join("html", "foo.adb.hunk.js") thistest.fail_if( - not os.path.exists(js_file), - "expecting a dynamic html report" + not os.path.exists(js_file), "expecting a dynamic html report" ) thistest.result() diff --git a/testsuite/tests/207-srctrace-version/test.py b/testsuite/tests/207-srctrace-version/test.py index b63c90746..4480711d7 100644 --- a/testsuite/tests/207-srctrace-version/test.py +++ b/testsuite/tests/207-srctrace-version/test.py @@ -36,7 +36,7 @@ "-T=../reference.srctrace", ], register_failure=False, - out=coverage_log + out=coverage_log, ) # If there was an error, the trace format changed between when the trace was @@ -47,8 +47,8 @@ "*** Ensure the trace format version was properly bumped if you made a" " breaking change in the trace format ***\n", regexp=r".*gnatcov(\.exe)?: ../reference.srctrace:" - r" unsupported format version", - actual=contents_of(coverage_log) + r" unsupported format version", + actual=contents_of(coverage_log), ) # If the correct message was found then great, the trace format number was @@ -67,8 +67,8 @@ ".", { "main.adb.xcov": {"+": {15, 16}, "!": {12}}, - "foo.c.xcov": {"!": {6}} - } + "foo.c.xcov": {"!": {6}}, + }, ) thistest.result() diff --git a/testsuite/tests/222-scope-expr-func/test.py b/testsuite/tests/222-scope-expr-func/test.py index a0f78ccb7..8a6515272 100644 --- a/testsuite/tests/222-scope-expr-func/test.py +++ b/testsuite/tests/222-scope-expr-func/test.py @@ -16,12 +16,11 @@ build_run_and_coverage( gprsw=GPRswitches( - root_project=gprfor(mains=["main.adb"],srcdirs=[".."]), - units=["Pkg"] + root_project=gprfor(mains=["main.adb"], srcdirs=[".."]), units=["Pkg"] ), covlevel="stmt+decision", mains=["main"], - extra_coverage_args=["--subprograms=pkg.ads:2", "-axcov"] + extra_coverage_args=["--subprograms=pkg.ads:2", "-axcov"], ) check_xcov_reports("obj", {"pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {5}}}) diff --git a/testsuite/tests/24_mixed_c_c++/test.py b/testsuite/tests/24_mixed_c_c++/test.py index 60fdaf22d..1a0d513b0 100644 --- a/testsuite/tests/24_mixed_c_c++/test.py +++ b/testsuite/tests/24_mixed_c_c++/test.py @@ -12,8 +12,7 @@ Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], - mains=["test.cpp"])), + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["test.cpp"])), covlevel="stmt", mains=["test"], extra_coverage_args=["--annotate=xcov"], diff --git a/testsuite/tests/92-long_slugs/test.py b/testsuite/tests/92-long_slugs/test.py index 2338f92d5..d6ae8fee8 100644 --- a/testsuite/tests/92-long_slugs/test.py +++ b/testsuite/tests/92-long_slugs/test.py @@ -70,7 +70,11 @@ "obj", { "main.c.xcov": {"+": {6}}, - (unit_name.lower() if "windows" in thistest.env.host.platform else unit_name) + ( + unit_name.lower() + if "windows" in thistest.env.host.platform + else unit_name + ) + ".c.xcov": {"+": {6}}, }, ) diff --git a/testsuite/tests/Ada/decision/K303_016-exwhen-abs/test.py b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/test.py index 80df4eeb4..3b5a7182b 100644 --- a/testsuite/tests/Ada/decision/K303_016-exwhen-abs/test.py +++ b/testsuite/tests/Ada/decision/K303_016-exwhen-abs/test.py @@ -5,12 +5,13 @@ # Customer had specific extra options on ppc. We haven't been able to trigger # a failure on this sample case anyway -if 'power' in env.target.triplet: - target_options = '-mcpu=750 -mbig-endian -meabi -msdata=none -memb' +if "power" in env.target.triplet: + target_options = "-mcpu=750 -mbig-endian -meabi -msdata=none -memb" else: - target_options = '' + target_options = "" TestCase( - extracargs='-fdata-sections -ffunction-sections ' + target_options).run() + extracargs="-fdata-sections -ffunction-sections " + target_options +).run() thistest.result() diff --git a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.py b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.py index 7c77975e4..912978ddc 100644 --- a/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.py +++ b/testsuite/tests/Ada/stmt/PC20-011-EmptyUnit_InLib/test.py @@ -10,7 +10,7 @@ TestCase().run( covcontrol=CovControl( deps=[libdep], - gprsw=GPRswitches( - root_project='gen.gpr', - units=['ops', 'ops.values']))) + gprsw=GPRswitches(root_project="gen.gpr", units=["ops", "ops.values"]), + ) +) thistest.result() diff --git a/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py b/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py index 48da8ab18..04c8d0a7d 100644 --- a/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py +++ b/testsuite/tests/C/mcdc/Exemptions/Invalid/test.py @@ -19,7 +19,7 @@ covlevel="stmt+mcdc", mains=["main"], trace_mode="src", - tolerate_instrument_messages="Exemption .* intersects" + tolerate_instrument_messages="Exemption .* intersects", ) check_xcov_reports( @@ -30,7 +30,8 @@ thistest.fail_if_no_match( what="Unexpected instrument output", regexp=r"(warning: Exemption annotation at main\.c:\d+:\d+ intersects a" - r" coverage obligation \(.*\), ignoring it\n)+", - actual=contents_of("instrument.log")) + r" coverage obligation \(.*\), ignoring it\n)+", + actual=contents_of("instrument.log"), +) thistest.result() diff --git a/testsuite/tests/C/mcdc/Macros/test.py b/testsuite/tests/C/mcdc/Macros/test.py index 6627093d7..f119350f3 100644 --- a/testsuite/tests/C/mcdc/Macros/test.py +++ b/testsuite/tests/C/mcdc/Macros/test.py @@ -21,14 +21,17 @@ ] copts_args = "--c-opts=" + ",".join(macro_args) build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], - mains=["test_macros.c"])), + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["test_macros.c"]) + ), covlevel="stmt+mcdc", mains=["test_macros"], extra_instr_args=[copts_args], - extra_coverage_args=["--annotate=xcov+"] + extra_coverage_args=["--annotate=xcov+"], ) -thistest.fail_if_diff(os.path.join("..", "test_macros.c.xcov.expected"), - os.path.join("obj", "test_macros.c.xcov")) +thistest.fail_if_diff( + os.path.join("..", "test_macros.c.xcov.expected"), + os.path.join("obj", "test_macros.c.xcov"), +) thistest.result() diff --git a/testsuite/tests/C/mcdc/include-current-dir/test.py b/testsuite/tests/C/mcdc/include-current-dir/test.py index 30d386c67..aa34848b1 100644 --- a/testsuite/tests/C/mcdc/include-current-dir/test.py +++ b/testsuite/tests/C/mcdc/include-current-dir/test.py @@ -21,18 +21,18 @@ cp(os.path.join("..", src), src) build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=['.'], mains=['test.c'])), - covlevel='stmt+mcdc', - mains=['test'], - extra_coverage_args=['--annotate=xcov', '--output-dir=xcov'], + gprsw=GPRswitches(root_project=gprfor(srcdirs=["."], mains=["test.c"])), + covlevel="stmt+mcdc", + mains=["test"], + extra_coverage_args=["--annotate=xcov", "--output-dir=xcov"], ) check_xcov_reports( - 'xcov', + "xcov", { - 'pkg.h.xcov': {'+': {7, 8}, '!': {6}}, - 'pkg.c.xcov': {'!': {4}}, - 'test.c.xcov': {'+': {6, 7, 8}} + "pkg.h.xcov": {"+": {7, 8}, "!": {6}}, + "pkg.c.xcov": {"!": {4}}, + "test.c.xcov": {"+": {6, 7, 8}}, }, ) diff --git a/testsuite/tests/C/stmt/NA28-015-default-return/test.py b/testsuite/tests/C/stmt/NA28-015-default-return/test.py index 3e9f92021..33999dcbd 100644 --- a/testsuite/tests/C/stmt/NA28-015-default-return/test.py +++ b/testsuite/tests/C/stmt/NA28-015-default-return/test.py @@ -6,7 +6,7 @@ import re -Wdir('tmp_') +Wdir("tmp_") # Point here is to exercise consolidation over distinct executions of the same # program with different command line arguments. The SCOV circuitry isn't @@ -18,14 +18,17 @@ def run_trace_with_args(prefix, exec_args): build_and_run( - gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], - mains=["calc.c"])), + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["calc.c"]) + ), covlevel="stmt", mains=["calc"], extra_coverage_args=[], extra_run_args=["-o", f"{prefix}.trace"], - extra_instr_args=[f"--dump-filename-prefix={prefix}", - "--dump-filename-simple"], + extra_instr_args=[ + f"--dump-filename-prefix={prefix}", + "--dump-filename-simple", + ], register_failure=False, exec_args=exec_args, ) @@ -38,31 +41,39 @@ def trycov(cases, xnocov): there. """ - fun_tracename = (srctracename_for if thistest.options.trace_mode == 'src' - else tracename_for) + fun_tracename = ( + srctracename_for + if thistest.options.trace_mode == "src" + else tracename_for + ) - xcov('coverage --level=stmt --annotate=xcov' - ' -P gen.gpr %s' - % ' '.join(fun_tracename(c) for c in cases)) + xcov( + "coverage --level=stmt --annotate=xcov" + " -P gen.gpr %s" % " ".join(fun_tracename(c) for c in cases) + ) def check_mark_on(line): - m = re.search(string=line, pattern=r'^ *\d+ (?P.):') + m = re.search(string=line, pattern=r"^ *\d+ (?P.):") if not m: return - note = m.group('note') + note = m.group("note") - m = re.search(string=line, pattern='// # (?P.*)') - mark = m.group('mark') if m else None + m = re.search(string=line, pattern="// # (?P.*)") + mark = m.group("mark") if m else None - thistest.fail_if(mark in xnocov and note != '-', - "missing expected '-' note on line:\n%s" % line) + thistest.fail_if( + mark in xnocov and note != "-", + "missing expected '-' note on line:\n%s" % line, + ) - thistest.fail_if(note == '-' and mark not in xnocov, - "unexpected '-' note on line:\n %s" % line) + thistest.fail_if( + note == "-" and mark not in xnocov, + "unexpected '-' note on line:\n %s" % line, + ) - print('checking cases=%s' % str(cases)) - with open('obj/process.c.xcov', 'r') as f: + print("checking cases=%s" % str(cases)) + with open("obj/process.c.xcov", "r") as f: for line in f: check_mark_on(line=line.strip()) @@ -71,9 +82,9 @@ def check_mark_on(line): run_trace_with_args("mult", ["4", "5", "*"]) run_trace_with_args("unsupp", ["4", "5", "#"]) -trycov(cases=['mult', 'plus'], xnocov=['unsupp']) -trycov(cases=['plus'], xnocov=['mult', 'unsupp']) -trycov(cases=['mult'], xnocov=['plus', 'unsupp']) -trycov(cases=['mult', 'plus', 'unsupp'], xnocov=[]) +trycov(cases=["mult", "plus"], xnocov=["unsupp"]) +trycov(cases=["plus"], xnocov=["mult", "unsupp"]) +trycov(cases=["mult"], xnocov=["plus", "unsupp"]) +trycov(cases=["mult", "plus", "unsupp"], xnocov=[]) thistest.result() diff --git a/testsuite/tests/Disassemblers/disaconv.py b/testsuite/tests/Disassemblers/disaconv.py index 755e2d961..7e48d3b47 100644 --- a/testsuite/tests/Disassemblers/disaconv.py +++ b/testsuite/tests/Disassemblers/disaconv.py @@ -9,43 +9,48 @@ parser = argparse.ArgumentParser( description=( - 'Convert a objdump/gnatcov disassembly dump to a simple format' + "Convert a objdump/gnatcov disassembly dump to a simple format" ) ) parser.add_argument( - '-o', '--output', type=argparse.FileType('w'), default=sys.stdout, - dest='output' + "-o", + "--output", + type=argparse.FileType("w"), + default=sys.stdout, + dest="output", ) parser.add_argument( - 'input', type=argparse.FileType('r'), nargs='?', default=sys.stdin, + "input", + type=argparse.FileType("r"), + nargs="?", + default=sys.stdin, ) # Internal data structures + def section(match): - return 'Section' + return "Section" def insn(match): - addr = int(match.group('addr'), 16) - return 'Insn: {:08x}'.format(addr) + addr = int(match.group("addr"), 16) + return "Insn: {:08x}".format(addr) # Input matching # These are the pattern generated by objdump: -OBJDUMP_SECTION = re.compile('^Disassembly of section (?P.+):$') +OBJDUMP_SECTION = re.compile("^Disassembly of section (?P.+):$") OBJDUMP_INSN = re.compile( - '^ *(?P[0-9a-f]+):\t[ 0-9a-f]+\t' - '(?P[^ ]*)' + "^ *(?P[0-9a-f]+):\t[ 0-9a-f]+\t" "(?P[^ ]*)" ) # And those ones are generated by gnatcov disassemble: -GNATCOV_SECTION = re.compile('^Section') +GNATCOV_SECTION = re.compile("^Section") GNATCOV_INSN = re.compile( - '(?P[0-9a-f]+) -: (?: [0-9a-f]{2})+ {3,}' - '(?P[^ ]+)' + "(?P[0-9a-f]+) -: (?: [0-9a-f]{2})+ {3,}" "(?P[^ ]+)" ) @@ -53,9 +58,9 @@ def insn(match): MATCHING_TABLE = ( (OBJDUMP_SECTION, section), - (OBJDUMP_INSN, insn), + (OBJDUMP_INSN, insn), (GNATCOV_SECTION, section), - (GNATCOV_INSN, insn), + (GNATCOV_INSN, insn), ) @@ -67,9 +72,9 @@ def disaconv(fin, fout): m = pattern.match(line) if m: fout.write(action(m)) - fout.write('\n') + fout.write("\n") -if __name__ == '__main__': +if __name__ == "__main__": args = parser.parse_args() disaconv(args.input, args.output) diff --git a/testsuite/tests/Disassemblers/test.py b/testsuite/tests/Disassemblers/test.py index 87fe4da14..6061ef3a7 100644 --- a/testsuite/tests/Disassemblers/test.py +++ b/testsuite/tests/Disassemblers/test.py @@ -25,8 +25,9 @@ # is a key for this mapping, the associated directory names are used to get # testcases. + class Testcase(object): - def __init__(self, test_dir, discriminant, cargs=(), asm_spec=''): + def __init__(self, test_dir, discriminant, cargs=(), asm_spec=""): self.test_dir = test_dir self.discriminant = discriminant self.cargs = cargs @@ -36,13 +37,14 @@ def __init__(self, test_dir, discriminant, cargs=(), asm_spec=''): def prepare(self): if self.asm_spec: - self.spec_file = os.path.abspath('{}.spec'.format(self.test_dir)) - with open(self.spec_file, 'w') as f: - f.write('*asm:\n') - f.write('+ {}\n'.format(self.asm_spec)) + self.spec_file = os.path.abspath("{}.spec".format(self.test_dir)) + with open(self.spec_file, "w") as f: + f.write("*asm:\n") + f.write("+ {}\n".format(self.asm_spec)) - self.cargs = (list(self.cargs) + - ['-specs={}'.format(self.spec_file)]) + self.cargs = list(self.cargs) + [ + "-specs={}".format(self.spec_file) + ] testcases = OrderedDict() @@ -50,38 +52,34 @@ def prepare(self): for tc in ( # Avoid running this on Windows platforms as the assembler will fail # processing the test material, there. - Testcase('x86', 'x86-linux'), - Testcase('x86_64', 'x86_64-linux'), - - Testcase('lmp', 'visium-elf', ['-mcpu=gr6']), - + Testcase("x86", "x86-linux"), + Testcase("x86_64", "x86_64-linux"), + Testcase("lmp", "visium-elf", ["-mcpu=gr6"]), # Use GCC's spec files, in particular the "asm" rule to force the # assemblers' endianity. This short-circuits the -m{little,big}-endian flag # we get from the testuite-wide project configuration file. - Testcase('arm_le', 'arm', ['-mcpu=cortex-r4f'], '-EL'), - Testcase('arm_be', 'arm', ['-mcpu=cortex-r4f'], '-EB'), - Testcase('thumb_le', 'arm', ['-mthumb'], '-EL'), - Testcase('thumb_be', 'arm', ['-mthumb'], '-EB'), - - Testcase('ppc_be', 'ppc-elf', ['-mbig-endian']), - Testcase('ppc_le', 'ppc-elf', ['-mlittle-endian']), - - Testcase('leon', 'leon3-elf'), + Testcase("arm_le", "arm", ["-mcpu=cortex-r4f"], "-EL"), + Testcase("arm_be", "arm", ["-mcpu=cortex-r4f"], "-EB"), + Testcase("thumb_le", "arm", ["-mthumb"], "-EL"), + Testcase("thumb_be", "arm", ["-mthumb"], "-EB"), + Testcase("ppc_be", "ppc-elf", ["-mbig-endian"]), + Testcase("ppc_le", "ppc-elf", ["-mlittle-endian"]), + Testcase("leon", "leon3-elf"), ): testcases[tc.test_dir] = tc def with_ext(name, ext): """Return the given name suffixed by an extension.""" - return '{}{}{}'.format(name, os.path.extsep, ext) + return "{}{}{}".format(name, os.path.extsep, ext) def is_asm(filename): """Return if the given filename is an assembly source.""" - return os.path.splitext(filename)[-1] == '.s' + return os.path.splitext(filename)[-1] == ".s" -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Run tests in each test directory that matches architecture discriminants. for test_dir, tc in testcases.items(): @@ -95,38 +93,32 @@ def is_asm(filename): testcases = list(sorted(filter(is_asm, os.listdir(path)))) # Prepare object file from assembly sources. - project = gprfor( - testcases, srcdirs=path, - main_cargs=tc.cargs - ) - gprbuild(project, gargs=['-c']) + project = gprfor(testcases, srcdirs=path, main_cargs=tc.cargs) + gprbuild(project, gargs=["-c"]) # And then iterate on each testcase to run it. for testcase in testcases: - compile_unit = os.path.splitext(testcase)[0] - objfile = os.path.join('obj', with_ext(compile_unit, 'o')) + objfile = os.path.join("obj", with_ext(compile_unit, "o")) - baseline = os.path.join( - path, with_ext(compile_unit, 'baseline') - ) - disa_gnatcov = with_ext(compile_unit, 'disassembly') + baseline = os.path.join(path, with_ext(compile_unit, "baseline")) + disa_gnatcov = with_ext(compile_unit, "disassembly") # Disassemble it using gnatcov. - xcov(['disassemble', objfile], out=disa_gnatcov) + xcov(["disassemble", objfile], out=disa_gnatcov) # And finally compare it to the baseline. disaconv_diff = diff(baseline, disa_gnatcov) thistest.log( - 'Comparing the disassembly of {}/{}...'.format(test_dir, testcase) + "Comparing the disassembly of {}/{}...".format(test_dir, testcase) ) if disaconv_diff: thistest.log(disaconv_diff) else: - thistest.log('No difference') + thistest.log("No difference") thistest.fail_if( disaconv_diff, - '{}/{}: disassemblies are not the same'.format(test_dir, testcase) + "{}/{}: disassemblies are not the same".format(test_dir, testcase), ) tmp_sub.to_homedir() diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/test.py b/testsuite/tests/Generics/Mode_Variants_MCDC/test.py index e6e2b281b..9088d338c 100644 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/test.py +++ b/testsuite/tests/Generics/Mode_Variants_MCDC/test.py @@ -16,12 +16,10 @@ tc = TestCase(category=CAT.mcdc) tc.run() -tc.run(covcontrol=CovControl(covoptions="-S instance"), - subdirhint="r_") +tc.run(covcontrol=CovControl(covoptions="-S instance"), subdirhint="r_") # -S routine is intractable with inlining -if '-gnatn' not in thistest.suite_cargs_for('Ada'): - tc.run(covcontrol=CovControl(covoptions="-S routine"), - subdirhint="r_") +if "-gnatn" not in thistest.suite_cargs_for("Ada"): + tc.run(covcontrol=CovControl(covoptions="-S routine"), subdirhint="r_") thistest.result() diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/test.py b/testsuite/tests/Generics/Mode_Variants_STMT/test.py index c4a65c292..1d6930b7e 100644 --- a/testsuite/tests/Generics/Mode_Variants_STMT/test.py +++ b/testsuite/tests/Generics/Mode_Variants_STMT/test.py @@ -7,12 +7,10 @@ tc.run() -tc.run(covcontrol=CovControl(covoptions="-S instance"), - subdirhint="i_") +tc.run(covcontrol=CovControl(covoptions="-S instance"), subdirhint="i_") # -S routine is intractable with inlining -if '-gnatn' not in thistest.suite_cargs_for('Ada'): - tc.run(covcontrol=CovControl(covoptions="-S routine"), - subdirhint="r_") +if "-gnatn" not in thistest.suite_cargs_for("Ada"): + tc.run(covcontrol=CovControl(covoptions="-S routine"), subdirhint="r_") thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.py index ca1c4c6bc..939a5bcbb 100644 --- a/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.py +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/DifferentOptions/test.py @@ -8,17 +8,22 @@ # Test expectations -test_drivers = {'test_1': {'not.c': ['-g', '-O0']}, - 'test_2': {'not.c': ['-g', '-O1']}} +test_drivers = { + "test_1": {"not.c": ["-g", "-O0"]}, + "test_2": {"not.c": ["-g", "-O1"]}, +} coverage_expectations = { # The two not.c:f() are compiled with different levels of optimization. In # object coverage, gnatcov is supposed to fail: there is no coverage # expectation. - 'f': {'-': 0, '!': 0, '+': 0}, + "f": {"-": 0, "!": 0, "+": 0}, } -tc = TestCase(test_drivers, coverage_expectations, - extra_sourcedirs=['../../../src']) -thistest.fail_if(tc.run(register_failure=False), - '"gnatcov coverage" was supposed to fail, but it did not') +tc = TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../src"] +) +thistest.fail_if( + tc.run(register_failure=False), + '"gnatcov coverage" was supposed to fail, but it did not', +) thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test.py index 3bac5bc5d..775f7d866 100644 --- a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test.py +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Fact/test.py @@ -8,18 +8,21 @@ # Test expectations. All compile units have debug symbols. -switches = ['-O0', '-g'] -test_drivers = {'test_1': {'not.c': switches, 'fact.c': switches}, - 'test_2': {'not.c': switches, 'fact.c': switches}} +switches = ["-O0", "-g"] +test_drivers = { + "test_1": {"not.c": switches, "fact.c": switches}, + "test_2": {"not.c": switches, "fact.c": switches}, +} coverage_expectations = { # - In test_1, not.c:f() is partially covered # - In test_2, fact.c:f() is fully covered # # There is no consolidation, so there will be one partially covered # routine and one fully covered one. - 'f': {'-': 0, '!': 1, '+': 1}, + "f": {"-": 0, "!": 1, "+": 1}, } -TestCase(test_drivers, coverage_expectations, - extra_sourcedirs=['../../../../src']).run() +TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../../src"] +).run() thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test.py index 99a8aff83..127c55748 100644 --- a/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test.py +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/With_Debug/Not-Not/test.py @@ -6,17 +6,17 @@ from OCOV.tc import TestCase from SUITE.context import thistest -switches = ['-O0', '-g'] +switches = ["-O0", "-g"] # Test expectations -test_drivers = {'test_1': {'not.c': switches}, - 'test_2': {'not.c': switches}} +test_drivers = {"test_1": {"not.c": switches}, "test_2": {"not.c": switches}} coverage_expectations = { # Both not.c:f() are partially covered (each one covers a complementary # part), so there is one fully covered routine after consolidation. - 'f': {'-': 0, '!': 0, '+': 1}, + "f": {"-": 0, "!": 0, "+": 1}, } -TestCase(test_drivers, coverage_expectations, - extra_sourcedirs=['../../../../src']).run() +TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../../src"] +).run() thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test.py index 86c13c0f4..06ecb1609 100644 --- a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test.py +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotDebug-NotNoDebug/test.py @@ -11,9 +11,11 @@ # We are trying to consolidate the traces of these test drivers. Each test # driver has its own project, since it can use different compilation options # for test controllers: -test_drivers = {'test_1': {'not.c': ['-g', '-O0']}, - 'test_2': {'not.c': ['-g', '-O0']}, - 'test_3': {'not.c': ['-g0', '-O0']}} +test_drivers = { + "test_1": {"not.c": ["-g", "-O0"]}, + "test_2": {"not.c": ["-g", "-O0"]}, + "test_3": {"not.c": ["-g0", "-O0"]}, +} # Here, the "not.c" compile unit has debug info except in one test driver (the # last one). @@ -25,9 +27,10 @@ # test_1 and test_2 are consolidated, so there must be one f() that is # fully covered. One other is partially covered for test_3 that do not # consolidate. - 'f': {'-': 0, '!': 1, '+': 1}, + "f": {"-": 0, "!": 1, "+": 1}, } -TestCase(test_drivers, coverage_expectations, - extra_sourcedirs=['../../../../src']).run() +TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../../src"] +).run() thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test.py index 527b71093..09cea09d3 100644 --- a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test.py +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotDebug-NotNoDebug/test.py @@ -11,16 +11,19 @@ # We are trying to consolidate the traces of these test drivers. Each test # driver has its own project, since it can use different compilation options # for test controllers: -test_drivers = {'test_1': {'not.c': ['-g0', '-O0']}, - 'test_2': {'not.c': ['-g', '-O0']}} +test_drivers = { + "test_1": {"not.c": ["-g0", "-O0"]}, + "test_2": {"not.c": ["-g", "-O0"]}, +} # Here, the "not.c" compile unit has debug info only in one test driver. coverage_expectations = { # Both not.c:f() are partially covered (each one covers a complementary # part, so they would be fully covered if consolidated). - 'f': {'-': 0, '!': 2, '+': 0}, + "f": {"-": 0, "!": 2, "+": 0}, } -TestCase(test_drivers, coverage_expectations, - extra_sourcedirs=['../../../../src']).run() +TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../../src"] +).run() thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test.py index 39d0a3b2f..8b5c1a17b 100644 --- a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test.py +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-FactNoDebug/test.py @@ -11,16 +11,19 @@ # We are trying to consolidate the traces of these test drivers. Each test # driver has its own project, since it can use different compilation options # for test controllers: -test_drivers = {'test_1': {'not.c': ['-g0', '-O0']}, - 'test_2': {'fact.c': ['-g0', '-O0']}} +test_drivers = { + "test_1": {"not.c": ["-g0", "-O0"]}, + "test_2": {"fact.c": ["-g0", "-O0"]}, +} # Here, no compile unit has specific compilation flag: no one has debug info. coverage_expectations = { # not.c:f() is fully covered # fact.c:f() is partially covered - 'f': {'-': 0, '!': 1, '+': 1}, + "f": {"-": 0, "!": 1, "+": 1}, } -TestCase(test_drivers, coverage_expectations, - extra_sourcedirs=['../../../../src']).run() +TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../../src"] +).run() thistest.result() diff --git a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test.py b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test.py index 3fb4ab2df..b3cae45e4 100644 --- a/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test.py +++ b/testsuite/tests/HomonymSymbols/ObjectCoverage/Without_Debug/NotNoDebug-NotNoDebug/test.py @@ -10,16 +10,19 @@ # We are trying to consolidate the traces of these test drivers. Each test # driver has its own project, since it can use different compilation options # for test controllers: -test_drivers = {'test_1': {'not.c': ['-g0', '-O0']}, - 'test_2': {'not.c': ['-g0', '-O0']}} +test_drivers = { + "test_1": {"not.c": ["-g0", "-O0"]}, + "test_2": {"not.c": ["-g0", "-O0"]}, +} # Here, no compile unit has debug info. coverage_expectations = { # Both not.c:f() are partially covered (each one covers a complementary # part, so they would be fully covered if consolidated). - 'f': {'-': 0, '!': 2, '+': 0}, + "f": {"-": 0, "!": 2, "+": 0}, } -TestCase(test_drivers, coverage_expectations, - extra_sourcedirs=['../../../../src']).run() +TestCase( + test_drivers, coverage_expectations, extra_sourcedirs=["../../../../src"] +).run() thistest.result() diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.py index 5b655d4d3..459438a66 100644 --- a/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.py +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/DifferentOptions/test.py @@ -9,25 +9,30 @@ from SUITE.cutils import Wdir -test_drivers = {'test_1': {'not.c': ['-O0']}, - 'test_2': {'not.c': ['-O1']}} +test_drivers = {"test_1": {"not.c": ["-O0"]}, "test_2": {"not.c": ["-O1"]}} coverage_expectations = { # There is no object coverage expectation. This entry is to add "f" to the # routines to consolidate. - 'f': None, + "f": None, } # SCOs are the same for each project: not.gli -wd = Wdir('tmp_') -with open('scos.list', 'w') as f: - for sco_f in ['not.gli']: - f.write('test_1-obj/{}\n'.format(sco_f)) +wd = Wdir("tmp_") +with open("scos.list", "w") as f: + for sco_f in ["not.gli"]: + f.write("test_1-obj/{}\n".format(sco_f)) wd.to_homedir() -tc = TestCase(test_drivers, coverage_expectations, - extra_sourcedirs=['../../../src'], - level='stmt', annotate='xcov', - extra_xcov_args=['--scos=@scos.list']) -thistest.fail_if(tc.run(register_failure=False), - '"gnatcov coverage" was supposed to fail, but it did not') +tc = TestCase( + test_drivers, + coverage_expectations, + extra_sourcedirs=["../../../src"], + level="stmt", + annotate="xcov", + extra_xcov_args=["--scos=@scos.list"], +) +thistest.fail_if( + tc.run(register_failure=False), + '"gnatcov coverage" was supposed to fail, but it did not', +) thistest.result() diff --git a/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/test.py b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/test.py index 5280b5ac9..4b0979927 100644 --- a/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/test.py +++ b/testsuite/tests/HomonymSymbols/SourceCoverage/FunctionSections/test.py @@ -3,5 +3,5 @@ from SUITE.context import thistest -TestCase(extracargs='-ffunction-sections', category=CAT.stmt).run() +TestCase(extracargs="-ffunction-sections", category=CAT.stmt).run() thistest.result() diff --git a/testsuite/tests/I401-009/test.py b/testsuite/tests/I401-009/test.py index c3ff8b75e..e62a28f4f 100644 --- a/testsuite/tests/I401-009/test.py +++ b/testsuite/tests/I401-009/test.py @@ -5,17 +5,29 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, match -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -Wdir('tmp_') +Wdir("tmp_") -gprbuild(gprfor(['test_engines.adb'], srcdirs='../src')) +gprbuild(gprfor(["test_engines.adb"], srcdirs="../src")) -xrun(exepath_to('test_engines')) -xcov(['coverage', '--level=branch', '--annotate=xcov', - tracename_for('test_engines')]) +xrun(exepath_to("test_engines")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov", + tracename_for("test_engines"), + ] +) -thistest.fail_if(not match(r' \!:.*return.*Stable_P', 'engines.adb.xcov')) +thistest.fail_if(not match(r" \!:.*return.*Stable_P", "engines.adb.xcov")) thistest.result() diff --git a/testsuite/tests/I427-029/test.py b/testsuite/tests/I427-029/test.py index f20a71b8c..021b5f14b 100644 --- a/testsuite/tests/I427-029/test.py +++ b/testsuite/tests/I427-029/test.py @@ -6,16 +6,23 @@ from SUITE.context import thistest from SUITE.control import target_info from SUITE.cutils import Wdir, match -from SUITE.tutils import (exepath_to, gprbuild, gprfor, maybe_valgrind, - tracename_for, xcov, xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + maybe_valgrind, + tracename_for, + xcov, + xrun, +) -Wdir('tmp_') +Wdir("tmp_") # Context information, basic command line interface checks -print('maybe_valgrind prepends ... ' + str(maybe_valgrind([]))) -xcov(['--version']) -xcov(['--help']) +print("maybe_valgrind prepends ... " + str(maybe_valgrind([]))) +xcov(["--version"]) +xcov(["--help"]) # Core functions checks over the Engines example @@ -31,76 +38,102 @@ # We name each variant with a couple of letters, one per Pressure/Temperature # parameter, each either P or M to denote whether the parameter is set to the # threshold Plus or Minus one. -variants = ['mm', 'mp', 'pm', 'pp'] +variants = ["mm", "mp", "pm", "pp"] # The sources are named accordingly (e.g. test_engines_mm.adb), and we we play # with a number of related outputs (test_engines_mm executable, .trace file # out of qemu, etc.). We Define a class to help handle such variants: + class Vtest: def __init__(self, basename, variant): self.basename = basename self.variant = variant - def filename(self, suffix=''): + def filename(self, suffix=""): """ Return the name to use for a file related to this variant, suffixed with SUFFIX. """ - return self.basename + '_' + self.variant + suffix + return self.basename + "_" + self.variant + suffix def tag(self): """Return a trace tag to associate with this test variant.""" - return '%s, %s variant' % (self.basename, self.variant) + return "%s, %s variant" % (self.basename, self.variant) # Build all the executable variants from a single multi-mains project file -gprbuild(gprfor([Vtest('test_engines', v).filename('.adb') for v in variants], - srcdirs='../src')) +gprbuild( + gprfor( + [Vtest("test_engines", v).filename(".adb") for v in variants], + srcdirs="../src", + ) +) # First, a number of tests over individual variants: for variant in variants: - vt = Vtest('test_engines', variant) + vt = Vtest("test_engines", variant) # Xrun & stick a dedicated tag into the trace output - xrun([exepath_to(vt.filename()), '--tag=' + vt.tag()]) + xrun([exepath_to(vt.filename()), "--tag=" + vt.tag()]) # Compute branch coverage for this variant & check that there's only # partial coverage of the return expression - xcov(['coverage', '--level=branch', '--annotate=xcov', - vt.filename(tracename_for(''))]) + xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov", + vt.filename(tracename_for("")), + ] + ) thistest.fail_if( - not match(r' \!:.*return.*Stable_P', 'engines.adb.xcov'), - 'single input, expected partial coverage over return expr') + not match(r" \!:.*return.*Stable_P", "engines.adb.xcov"), + "single input, expected partial coverage over return expr", + ) # Verify that we can dump the trace and find the tag in the dump output xcov( - ['dump-trace', tracename_for(vt.filename())], - vt.filename('.tracedump')) + ["dump-trace", tracename_for(vt.filename())], vt.filename(".tracedump") + ) thistest.fail_if( - not match('Tag.*(User_Tag).*\nLen.*\nData.*%s' % vt.tag(), - vt.filename('.tracedump')), - 'single input, expected user tag from --dump-trace') + not match( + "Tag.*(User_Tag).*\nLen.*\nData.*%s" % vt.tag(), + vt.filename(".tracedump"), + ), + "single input, expected user tag from --dump-trace", + ) # Now, check that we can combine the trace results from all the variants # and obtain full branch coverage of the return boolean expression. Build # a consolidation routine list for this purpose. -with open('list.stable', 'w') as rl: - rl.write(target_info().to_platform_specific_symbol('engines__stable\n')) - -xcov(['coverage', '--level=branch', '--annotate=xcov', - '--routines=@list.stable'] - + [tracename_for(Vtest('test_engines', v).filename()) - for v in variants]) +with open("list.stable", "w") as rl: + rl.write(target_info().to_platform_specific_symbol("engines__stable\n")) + +xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov", + "--routines=@list.stable", + ] + + [tracename_for(Vtest("test_engines", v).filename()) for v in variants] +) thistest.fail_if( - not match(r' \+:.*return.*Stable_P', 'engines.adb.xcov'), - 'combined inputs, expected full branch coverage over return expr') + not match(r" \+:.*return.*Stable_P", "engines.adb.xcov"), + "combined inputs, expected full branch coverage over return expr", +) # Check that we can produce html without crashing as well ... -xcov(['coverage', '--level=branch', '--annotate=html+', - '--routines=@list.stable'] - + [Vtest('test_engines', v).filename(tracename_for('')) - for v in variants]) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=html+", + "--routines=@list.stable", + ] + + [Vtest("test_engines", v).filename(tracename_for("")) for v in variants] +) thistest.result() diff --git a/testsuite/tests/I505-018/test.py b/testsuite/tests/I505-018/test.py index 6a3121aab..7b6a8f19b 100644 --- a/testsuite/tests/I505-018/test.py +++ b/testsuite/tests/I505-018/test.py @@ -5,26 +5,30 @@ from SUITE.tutils import gprfor -Wdir('tmp_') +Wdir("tmp_") # Check that "gnatcov coverage" produces reports for units exposing more than # one entry point when compiled with -ffunction-sections. build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor( - mains=['test_services.adb'], - srcdirs='../src', - compiler_extra='for Default_Switches ("Ada")' - ' use ("-ffunction-sections");')), - covlevel='stmt', - mains=['test_services'], - extra_coverage_args=['--annotate=xcov'], - scos=['obj/services', 'obj/test_services']) + gprsw=GPRswitches( + root_project=gprfor( + mains=["test_services.adb"], + srcdirs="../src", + compiler_extra='for Default_Switches ("Ada")' + ' use ("-ffunction-sections");', + ) + ), + covlevel="stmt", + mains=["test_services"], + extra_coverage_args=["--annotate=xcov"], + scos=["obj/services", "obj/test_services"], +) # Use match to both verify that expected reports are there and # that coverage results are as we expect as well, while we're at it. thistest.fail_if( - not match('100% of [1-9] lines covered', 'test_services.adb.xcov')) -thistest.fail_if( - not match('-:.*raise Program_Error;', 'services.adb.xcov')) + not match("100% of [1-9] lines covered", "test_services.adb.xcov") +) +thistest.fail_if(not match("-:.*raise Program_Error;", "services.adb.xcov")) thistest.result() diff --git a/testsuite/tests/I511-019-response-files/test.py b/testsuite/tests/I511-019-response-files/test.py index 851c718fe..9671e8b66 100644 --- a/testsuite/tests/I511-019-response-files/test.py +++ b/testsuite/tests/I511-019-response-files/test.py @@ -3,34 +3,35 @@ from SUITE.tutils import gprbuild, gprfor, xcov -Wdir('tmp_') +Wdir("tmp_") # Build a dummy project, to generate objects that we will query with # disp-routines via an explicit list or a response file, to compare # the results. -gprbuild(gprfor(['test_foobar.adb'], srcdirs='../src')) -objects = ['obj/foo.o', 'obj/bar.o'] +gprbuild(gprfor(["test_foobar.adb"], srcdirs="../src")) +objects = ["obj/foo.o", "obj/bar.o"] # Get disp-routines output from explicit command line arguments -xcov(args=['disp-routines'] + objects, - out='explicit.out') +xcov(args=["disp-routines"] + objects, out="explicit.out") # Build response file with same list of objects, and get disp-routines # output from this -with open('foobar.list', 'w') as f: - f.write('\n'.join(objects) + '\n') +with open("foobar.list", "w") as f: + f.write("\n".join(objects) + "\n") -xcov(args=['disp-routines', '@foobar.list'], - out='response.out') +xcov(args=["disp-routines", "@foobar.list"], out="response.out") # Check that both outputs are the same and non-empty, with at least one # of the bits we expect there. Do not rely on symbols ordering: it is not # specified. -response = set_from('response.out') -explicit = set_from('explicit.out') +response = set_from("response.out") +explicit = set_from("explicit.out") thistest.fail_if( explicit != response, - 'expect disp-routines output identical from args or response file') -thistest.fail_if(not any('bar' in symbol for symbol in explicit), - 'expect "bar" in disp-routines output') + "expect disp-routines output identical from args or response file", +) +thistest.fail_if( + not any("bar" in symbol for symbol in explicit), + 'expect "bar" in disp-routines output', +) thistest.result() diff --git a/testsuite/tests/I512-020/test.py b/testsuite/tests/I512-020/test.py index c856b5473..68a2c5eac 100644 --- a/testsuite/tests/I512-020/test.py +++ b/testsuite/tests/I512-020/test.py @@ -2,5 +2,5 @@ from SUITE.tutils import xcov -xcov(['disp-routines', 'ppcstart.elf']) +xcov(["disp-routines", "ppcstart.elf"]) thistest.result() diff --git a/testsuite/tests/I519-015/test.py b/testsuite/tests/I519-015/test.py index 70b2b5eaa..47d4e554b 100644 --- a/testsuite/tests/I519-015/test.py +++ b/testsuite/tests/I519-015/test.py @@ -6,36 +6,50 @@ import re from SUITE.context import thistest -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) from SUITE.cutils import Wdir, contents_of, match -Wdir('tmp_') +Wdir("tmp_") # Context information, basic command line interface checks -gprbuild(gprfor(mains=['test_min.adb', 'test_min1.adb', 'test_min2.adb'], - srcdirs='..'), - gargs=['-O1']) +gprbuild( + gprfor( + mains=["test_min.adb", "test_min1.adb", "test_min2.adb"], srcdirs=".." + ), + gargs=["-O1"], +) -xrun(exepath_to('test_min')) +xrun(exepath_to("test_min")) # Check that the test exercising both sides of the 'if' stmt # get full coverage -xcov('coverage --level=branch --annotate=asm ' + tracename_for('test_min'), - out='test_min.out') +xcov( + "coverage --level=branch --annotate=asm " + tracename_for("test_min"), + out="test_min.out", +) -thistest.fail_if(not match(r'_ada_min \+:.*', 'test_min.out'), - 'full coverage expected') +thistest.fail_if( + not match(r"_ada_min \+:.*", "test_min.out"), "full coverage expected" +) # Seek partial branch coverage for the first test exercising only one side of # the 'if' stmt. Remember what we found. -xrun(exepath_to('test_min1')) -xcov('coverage -c branch -a asm --routines=_ada_min ' - + tracename_for('test_min1'), - out='test_min1.out') +xrun(exepath_to("test_min1")) +xcov( + "coverage -c branch -a asm --routines=_ada_min " + + tracename_for("test_min1"), + out="test_min1.out", +) -m = re.search('(>|v): .* (bclr|bge|blt|bnl)', contents_of('test_min1.out')) +m = re.search("(>|v): .* (bclr|bge|blt|bnl)", contents_of("test_min1.out")) thistest.fail_if(not m, "couldn't find expected partially covered branch") @@ -44,13 +58,17 @@ # Seek the other partial branch coverage for the second test exercising only # the other side of the 'if' stmt. -alt_sign = {'>': 'v', 'v': '>'} - -xrun(exepath_to('test_min2')) -xcov('coverage --level=branch --annotate=asm --routines=@../func.list ' - + tracename_for('test_min2'), - out='test_min2.out') -thistest.fail_if(not match(alt_sign[dir1] + ': .* ' + insn1, 'test_min2.out'), - "couldn't find alternate branch coverage") +alt_sign = {">": "v", "v": ">"} + +xrun(exepath_to("test_min2")) +xcov( + "coverage --level=branch --annotate=asm --routines=@../func.list " + + tracename_for("test_min2"), + out="test_min2.out", +) +thistest.fail_if( + not match(alt_sign[dir1] + ": .* " + insn1, "test_min2.out"), + "couldn't find alternate branch coverage", +) thistest.result() diff --git a/testsuite/tests/I519-030/test.py b/testsuite/tests/I519-030/test.py index be4c10c51..d97b289a2 100644 --- a/testsuite/tests/I519-030/test.py +++ b/testsuite/tests/I519-030/test.py @@ -8,11 +8,17 @@ from SUITE.context import thistest from SUITE.control import target_info from SUITE.cutils import Wdir, match -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -Wdir('tmp_') +Wdir("tmp_") # We expect the routine machine code to appear in two places: in the # associated unit object and at the unique call site. We expect both to be @@ -23,42 +29,71 @@ _target_info = target_info() # Build with inlining activated. Don't force unreferenced symbols away. -gprbuild(project=gprfor(['test_kops.adb'], srcdirs='../src'), - extracargs=['-O1', '-gnatn', '-save-temps']) +gprbuild( + project=gprfor(["test_kops.adb"], srcdirs="../src"), + extracargs=["-O1", "-gnatn", "-save-temps"], +) # Run, then check results. -xrun(exepath_to('test_kops')) +xrun(exepath_to("test_kops")) -instances = ['ops4', 'ops8'] +instances = ["ops4", "ops8"] # We expect all the source level calls to have been inlined, hence the base # object code alone never to be called -xcov(['disp-routines'] + ['obj/' + i + '.o' for i in instances], - out='kops.list') -xcov(['coverage', '--level=branch', '--annotate=xcov+', - '--routines=@kops.list', tracename_for('test_kops')]) -thistest.fail_if(not match(r'-:.*X := X \+ K', 'kops.adb.xcov'), - 'expect body of inlined not to be covered') +xcov( + ["disp-routines"] + ["obj/" + i + ".o" for i in instances], out="kops.list" +) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov+", + "--routines=@kops.list", + tracename_for("test_kops"), + ] +) +thistest.fail_if( + not match(r"-:.*X := X \+ K", "kops.adb.xcov"), + "expect body of inlined not to be covered", +) # And full object code coverage should report partial coverage only -xcov(['coverage', '--level=branch', '--annotate=xcov', - tracename_for('test_kops')]) -thistest.fail_if(not match(r'!:.*X := X \+ K', 'kops.adb.xcov')) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov", + tracename_for("test_kops"), + ] +) +thistest.fail_if(not match(r"!:.*X := X \+ K", "kops.adb.xcov")) # Besides, attached to the generic source, we expect distinct object code # sequences from the testing code (all covered, but we don't check for that). # We request asm inserts for this purpose, and can't be sure about the exact # layout of lines so have '.' match newlines as well. -xcov(['coverage', '--level=branch', '--annotate=xcov+', - tracename_for('test_kops')]) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov+", + tracename_for("test_kops"), + ] +) -symbol = _target_info.to_platform_specific_symbol('_ada_test_kops') +symbol = _target_info.to_platform_specific_symbol("_ada_test_kops") thistest.fail_if( - not match('procedure Inc' + '.*' - + '<{}.*'.format(symbol) * len(instances) - + 'end Inc', - 'kops.adb.xcov', flags=re.DOTALL), - 'expect body of inlined attached to inlined source') + not match( + "procedure Inc" + + ".*" + + "<{}.*".format(symbol) * len(instances) + + "end Inc", + "kops.adb.xcov", + flags=re.DOTALL, + ), + "expect body of inlined attached to inlined source", +) # Likewise, we expect one object code sequence for each generic instance (all # uncovered, but we don't check for that). There's no guarantee on the order @@ -66,10 +101,12 @@ for i in instances: symbol = _target_info.to_platform_specific_symbol(i) thistest.fail_if( - not match('procedure Inc' + '.*' - + '<' + symbol + '__inc' - + '.*' + 'end Inc', - 'kops.adb.xcov', flags=re.DOTALL), - 'expect %s inlined machine code attached to inlined source' % symbol) + not match( + "procedure Inc" + ".*" + "<" + symbol + "__inc" + ".*" + "end Inc", + "kops.adb.xcov", + flags=re.DOTALL, + ), + "expect %s inlined machine code attached to inlined source" % symbol, + ) thistest.result() diff --git a/testsuite/tests/I522-010/test.py b/testsuite/tests/I522-010/test.py index 0391f8407..bafb57d7f 100644 --- a/testsuite/tests/I522-010/test.py +++ b/testsuite/tests/I522-010/test.py @@ -4,12 +4,14 @@ from SUITE.tutils import exepath_to, gprbuild, gprfor, xrun -Wdir('tmp_') +Wdir("tmp_") -extralargs = ',--entry=volp' if target_info().partiallinks else '' -gprbuild(project=gprfor(['volp.adb'], srcdirs='../src'), - extracargs='-ffunction-sections', - largs='-Wl,--gc-sections' + extralargs) -xrun(exepath_to('volp')) +extralargs = ",--entry=volp" if target_info().partiallinks else "" +gprbuild( + project=gprfor(["volp.adb"], srcdirs="../src"), + extracargs="-ffunction-sections", + largs="-Wl,--gc-sections" + extralargs, +) +xrun(exepath_to("volp")) thistest.result() diff --git a/testsuite/tests/I715-012/test.py b/testsuite/tests/I715-012/test.py index 463b78d7e..9522bb668 100644 --- a/testsuite/tests/I715-012/test.py +++ b/testsuite/tests/I715-012/test.py @@ -2,27 +2,42 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, list_to_tmp -from SUITE.tutils import (exepath_to, gprbuild, gprfor, - platform_specific_symbols, tracename_for, xcov, xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + platform_specific_symbols, + tracename_for, + xcov, + xrun, +) -wd = Wdir('tmp_') -gprbuild(project=gprfor(srcdirs=['../src'], mains=['p.adb'])) -symfile = list_to_tmp(platform_specific_symbols(['pack__func'])) +wd = Wdir("tmp_") +gprbuild(project=gprfor(srcdirs=["../src"], mains=["p.adb"])) +symfile = list_to_tmp(platform_specific_symbols(["pack__func"])) -xrun(exepath_to('p')) -xcov(['coverage', '--level=branch', - '--routines=@' + symfile, - '--annotate=xcov+', tracename_for('p')]) +xrun(exepath_to("p")) +xcov( + [ + "coverage", + "--level=branch", + "--routines=@" + symfile, + "--annotate=xcov+", + tracename_for("p"), + ] +) # This test should check that xcov does not generate null report files # for sources that are not considered in the coverage operation. # Here, only pack.adb.xcov should be generated, as the routine list # contains only pack__func, fully defined in pack.adb. -thistest.fail_if(not os.path.exists('pack.adb.xcov') - or os.path.exists('text_io.adb.xcov') - or os.path.exists('monitor.ads.xcov') - or os.path.exists('monitor.adb.xcov') - or os.path.exists('p.adb.xcov')) +thistest.fail_if( + not os.path.exists("pack.adb.xcov") + or os.path.exists("text_io.adb.xcov") + or os.path.exists("monitor.ads.xcov") + or os.path.exists("monitor.adb.xcov") + or os.path.exists("p.adb.xcov") +) thistest.result() diff --git a/testsuite/tests/I716-009/test.py b/testsuite/tests/I716-009/test.py index 22524099c..275054c5b 100644 --- a/testsuite/tests/I716-009/test.py +++ b/testsuite/tests/I716-009/test.py @@ -5,23 +5,39 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, match -from SUITE.tutils import (exepath_to, gprbuild, gprfor, maybe_valgrind, - tracename_for, xcov, xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + maybe_valgrind, + tracename_for, + xcov, + xrun, +) -Wdir('tmp_') +Wdir("tmp_") # Context information, basic command line interface checks -print('maybe_valgrind prepends ...', maybe_valgrind([])) +print("maybe_valgrind prepends ...", maybe_valgrind([])) -gprbuild(project=gprfor(mains=['test_min.adb'], - langs=['Ada', 'Asm'], - srcdirs=['..'])) -xrun(exepath_to('test_min')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_min')], - 'test_min.out') -thistest.fail_if(not match(r'min \+:.*', 'test_min.out'), - 'full coverage expected') +gprbuild( + project=gprfor( + mains=["test_min.adb"], langs=["Ada", "Asm"], srcdirs=[".."] + ) +) +xrun(exepath_to("test_min")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_min"), + ], + "test_min.out", +) +thistest.fail_if( + not match(r"min \+:.*", "test_min.out"), "full coverage expected" +) thistest.result() diff --git a/testsuite/tests/I716-021/test.py b/testsuite/tests/I716-021/test.py index 08e277b83..b863ae35d 100644 --- a/testsuite/tests/I716-021/test.py +++ b/testsuite/tests/I716-021/test.py @@ -1,19 +1,26 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, match -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -Wdir('tmp_') -gprbuild(project=gprfor(['test_p.adb'], srcdirs='../src')) -xrun(exepath_to('test_p')) -xcov(['coverage', '--level=branch', '--annotate=xcov+', - tracename_for('test_p')]) +Wdir("tmp_") +gprbuild(project=gprfor(["test_p.adb"], srcdirs="../src")) +xrun(exepath_to("test_p")) +xcov( + ["coverage", "--level=branch", "--annotate=xcov+", tracename_for("test_p")] +) # We expect the test to exercise the single branch in p.head_of # both ways, and that this branch is associated with the "if" statement # there, something like # # 6 +: if Blength > 0 then -thistest.fail_if(not match(r'[0-9]+ \+:.*if .* then', 'p.adb.xcov')) +thistest.fail_if(not match(r"[0-9]+ \+:.*if .* then", "p.adb.xcov")) thistest.result() diff --git a/testsuite/tests/I717-018/test.py b/testsuite/tests/I717-018/test.py index cf6d84747..1b484bf45 100644 --- a/testsuite/tests/I717-018/test.py +++ b/testsuite/tests/I717-018/test.py @@ -9,25 +9,42 @@ from SUITE.context import thistest from SUITE.control import target_info from SUITE.cutils import Wdir, match -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) - - -Wdir('tmp_') -gprbuild(project=gprfor(['explore.adb'], srcdirs='../src')) - -xrun(exepath_to('explore')) - -xcov(['coverage', '--level=branch', '--annotate=xcov+', - '--routines={}'.format(target_info().to_platform_specific_symbol( - 'robots__robot_control_inport' - )), - tracename_for('explore')]) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +Wdir("tmp_") +gprbuild(project=gprfor(["explore.adb"], srcdirs="../src")) + +xrun(exepath_to("explore")) + +xcov( + [ + "coverage", + "--level=branch", + "--annotate=xcov+", + "--routines={}".format( + target_info().to_platform_specific_symbol( + "robots__robot_control_inport" + ) + ), + tracename_for("explore"), + ] +) thistest.fail_if( - not match(r'\.: function Robot_Situation_Outport', - 'robots.adb.xcov', - flags=re.DOTALL), - 'expect line with empty instruction range dropped') + not match( + r"\.: function Robot_Situation_Outport", + "robots.adb.xcov", + flags=re.DOTALL, + ), + "expect line with empty instruction range dropped", +) thistest.result() diff --git a/testsuite/tests/I812-011/test.py b/testsuite/tests/I812-011/test.py index 53ff62835..439d59a8b 100644 --- a/testsuite/tests/I812-011/test.py +++ b/testsuite/tests/I812-011/test.py @@ -14,51 +14,54 @@ from SUITE.tutils import gprfor, xcov -Wdir('tmp_') +Wdir("tmp_") xcov_args = build_and_run( - gprsw=GPRswitches(root_project=gprfor(['main.adb'], srcdirs='..')), - covlevel='stmt', - mains=['main'], - scos=['obj/main'], - extra_coverage_args=['--level=stmt']) + gprsw=GPRswitches(root_project=gprfor(["main.adb"], srcdirs="..")), + covlevel="stmt", + mains=["main"], + scos=["obj/main"], + extra_coverage_args=["--level=stmt"], +) # Check that the annotated reports are produced in the expected directory -mkdir('xcovs') -mkdir('htmls') -xcov(xcov_args + ['--annotate=xcov', '--output-dir=./xcovs']) -xcov(xcov_args + ['--annotate=html', '--output-dir=./htmls']) -xcov_report = 'main.adb.xcov' -html_report = 'index.html' -thistest.fail_if(os.path.exists('./' + xcov_report) - or os.path.exists('./' + html_report) - or not os.path.exists('./htmls/' + html_report) - or not os.path.exists('./xcovs/' + xcov_report), - 'reports in the wrong output dir') +mkdir("xcovs") +mkdir("htmls") +xcov(xcov_args + ["--annotate=xcov", "--output-dir=./xcovs"]) +xcov(xcov_args + ["--annotate=html", "--output-dir=./htmls"]) +xcov_report = "main.adb.xcov" +html_report = "index.html" +thistest.fail_if( + os.path.exists("./" + xcov_report) + or os.path.exists("./" + html_report) + or not os.path.exists("./htmls/" + html_report) + or not os.path.exists("./xcovs/" + xcov_report), + "reports in the wrong output dir", +) # Check that a proper error message is given when the output dir is not a # directory. -p = xcov(xcov_args + ['--annotate=html', '--output-dir=./gen.gpr'], - out='gen.gpr.out', register_failure=False) +p = xcov( + xcov_args + ["--annotate=html", "--output-dir=./gen.gpr"], + out="gen.gpr.out", + register_failure=False, +) -thistest.fail_if(p.status == 0 - or not match(': cannot create output path ./gen.gpr: ', - 'gen.gpr.out'), - 'no error if output dir is not a directory') +thistest.fail_if( + p.status == 0 + or not match(": cannot create output path ./gen.gpr: ", "gen.gpr.out"), + "no error if output dir is not a directory", +) # Check that gnatcov can take a list of traces using the '@' prefix with the # various forms to pass trace files on the command line, checking the output # report in all cases. trace_file = xcov_args.pop() -tlist = '@' + list_to_tmp([trace_file]) -for arg in [ - ['--trace=' + tlist], - ['-T', tlist], - [tlist] -]: - xcov(xcov_args + ['--annotate=xcov'] + arg) - check_xcov_reports('.', {'main.adb.xcov': {'+': {3}}}) +tlist = "@" + list_to_tmp([trace_file]) +for arg in [["--trace=" + tlist], ["-T", tlist], [tlist]]: + xcov(xcov_args + ["--annotate=xcov"] + arg) + check_xcov_reports(".", {"main.adb.xcov": {"+": {3}}}) thistest.result() diff --git a/testsuite/tests/I914-023/test.py b/testsuite/tests/I914-023/test.py index 94cddc761..9a1a6d720 100644 --- a/testsuite/tests/I914-023/test.py +++ b/testsuite/tests/I914-023/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project = gprfor(['test_robots.adb'])) @@ -24,9 +24,16 @@ # # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_robots')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_robots')], 'robots.out') +xrun(exepath_to("../test_robots")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_robots"), + ], + "robots.out", +) # Expect something like ... @@ -36,9 +43,13 @@ # 18 +: and then Unsafe (C) # [...] # fffc0204 >: 40 9e 00 20 bne- cr7,0xfffc0238 -thistest.fail_if(not match('fff003dc v: 40 9e 00 20 bne', 'robots.out'), - 'expect Mode = Cautious always true') -thistest.fail_if(not match('fff003f8 v: 40 9e 00 48 bne', 'robots.out'), - 'expect Unsafe (C) always false') +thistest.fail_if( + not match("fff003dc v: 40 9e 00 20 bne", "robots.out"), + "expect Mode = Cautious always true", +) +thistest.fail_if( + not match("fff003f8 v: 40 9e 00 48 bne", "robots.out"), + "expect Unsafe (C) always false", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-bt-x2/test.py b/testsuite/tests/I930-009-ppc-beq-bt-x2/test.py index d7ac308ce..cdfe30784 100644 --- a/testsuite/tests/I930-009-ppc-beq-bt-x2/test.py +++ b/testsuite/tests/I930-009-ppc-beq-bt-x2/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,10 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('fff01004 \\+: 41 9e 00 0c beq', 'cond.out'), - 'branch should be taken on both dir') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 \\+: 41 9e 00 0c beq", "cond.out"), + "branch should be taken on both dir", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-bt/test.py b/testsuite/tests/I930-009-ppc-beq-bt/test.py index d7ac308ce..cdfe30784 100644 --- a/testsuite/tests/I930-009-ppc-beq-bt/test.py +++ b/testsuite/tests/I930-009-ppc-beq-bt/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,10 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('fff01004 \\+: 41 9e 00 0c beq', 'cond.out'), - 'branch should be taken on both dir') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 \\+: 41 9e 00 0c beq", "cond.out"), + "branch should be taken on both dir", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-ft-x2/test.py b/testsuite/tests/I930-009-ppc-beq-ft-x2/test.py index cd9c23dd1..671bc61e2 100644 --- a/testsuite/tests/I930-009-ppc-beq-ft-x2/test.py +++ b/testsuite/tests/I930-009-ppc-beq-ft-x2/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,10 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('fff01004 v: 41 9e 00 0c beq', 'cond.out'), - 'branch should be taken') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 v: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-ft/test.py b/testsuite/tests/I930-009-ppc-beq-ft/test.py index cd9c23dd1..671bc61e2 100644 --- a/testsuite/tests/I930-009-ppc-beq-ft/test.py +++ b/testsuite/tests/I930-009-ppc-beq-ft/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,10 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('fff01004 v: 41 9e 00 0c beq', 'cond.out'), - 'branch should be taken') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 v: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-npg-bt/test.py b/testsuite/tests/I930-009-ppc-beq-npg-bt/test.py index 7f5119962..3e8063489 100644 --- a/testsuite/tests/I930-009-ppc-beq-npg-bt/test.py +++ b/testsuite/tests/I930-009-ppc-beq-npg-bt/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,10 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('fff00ffc \\+: 41 9e 00 0c beq', 'cond.out'), - 'branch should be taken') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff00ffc \\+: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-npg-ft/test.py b/testsuite/tests/I930-009-ppc-beq-npg-ft/test.py index f62e19437..ec3505fb7 100644 --- a/testsuite/tests/I930-009-ppc-beq-npg-ft/test.py +++ b/testsuite/tests/I930-009-ppc-beq-npg-ft/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,10 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('fff00ffc v: 41 9e 00 0c beq', 'cond.out'), - 'branch should be taken') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff00ffc v: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-npg-tk/test.py b/testsuite/tests/I930-009-ppc-beq-npg-tk/test.py index 17d5f4e4e..7b47f8b53 100644 --- a/testsuite/tests/I930-009-ppc-beq-npg-tk/test.py +++ b/testsuite/tests/I930-009-ppc-beq-npg-tk/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project = gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr'); @@ -25,10 +25,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('fff00ffc >: 41 9e 00 0c beq', 'cond.out'), - 'branch should be taken') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff00ffc >: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-nt/test.py b/testsuite/tests/I930-009-ppc-beq-nt/test.py index 36ad3bde8..f72fdeb5e 100644 --- a/testsuite/tests/I930-009-ppc-beq-nt/test.py +++ b/testsuite/tests/I930-009-ppc-beq-nt/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,10 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('fff01004 -: 41 9e 00 0c beq', 'cond.out'), - 'branch should not be taken') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 -: 41 9e 00 0c beq", "cond.out"), + "branch should not be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-tb-x2/test.py b/testsuite/tests/I930-009-ppc-beq-tb-x2/test.py index d7ac308ce..cdfe30784 100644 --- a/testsuite/tests/I930-009-ppc-beq-tb-x2/test.py +++ b/testsuite/tests/I930-009-ppc-beq-tb-x2/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,10 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('fff01004 \\+: 41 9e 00 0c beq', 'cond.out'), - 'branch should be taken on both dir') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 \\+: 41 9e 00 0c beq", "cond.out"), + "branch should be taken on both dir", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-tb/test.py b/testsuite/tests/I930-009-ppc-beq-tb/test.py index d7ac308ce..cdfe30784 100644 --- a/testsuite/tests/I930-009-ppc-beq-tb/test.py +++ b/testsuite/tests/I930-009-ppc-beq-tb/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,10 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('fff01004 \\+: 41 9e 00 0c beq', 'cond.out'), - 'branch should be taken on both dir') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 \\+: 41 9e 00 0c beq", "cond.out"), + "branch should be taken on both dir", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-tk-x2/test.py b/testsuite/tests/I930-009-ppc-beq-tk-x2/test.py index 174b10077..7d2e32576 100644 --- a/testsuite/tests/I930-009-ppc-beq-tk-x2/test.py +++ b/testsuite/tests/I930-009-ppc-beq-tk-x2/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,10 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('fff01004 >: 41 9e 00 0c beq', 'cond.out'), - 'branch should be taken') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 >: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beq-tk/test.py b/testsuite/tests/I930-009-ppc-beq-tk/test.py index 174b10077..7d2e32576 100644 --- a/testsuite/tests/I930-009-ppc-beq-tk/test.py +++ b/testsuite/tests/I930-009-ppc-beq-tk/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,10 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('fff01004 >: 41 9e 00 0c beq', 'cond.out'), - 'branch should be taken') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("fff01004 >: 41 9e 00 0c beq", "cond.out"), + "branch should be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beqlr-bt/test.py b/testsuite/tests/I930-009-ppc-beqlr-bt/test.py index 4a779024b..b63a86f2b 100644 --- a/testsuite/tests/I930-009-ppc-beqlr-bt/test.py +++ b/testsuite/tests/I930-009-ppc-beqlr-bt/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,11 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) thistest.fail_if( - not match('fff01008 \\+: 4d 9e 00 20 beqlr cr7', 'cond.out'), - 'branch should be taken') + not match("fff01008 \\+: 4d 9e 00 20 beqlr cr7", "cond.out"), + "branch should be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beqlr-ft/test.py b/testsuite/tests/I930-009-ppc-beqlr-ft/test.py index a560dbdd3..894e241d7 100644 --- a/testsuite/tests/I930-009-ppc-beqlr-ft/test.py +++ b/testsuite/tests/I930-009-ppc-beqlr-ft/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,11 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) thistest.fail_if( - not match('fff01008 v: 4d 9e 00 20 beqlr cr7', 'cond.out'), - 'branch should be taken') + not match("fff01008 v: 4d 9e 00 20 beqlr cr7", "cond.out"), + "branch should be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beqlr-tb/test.py b/testsuite/tests/I930-009-ppc-beqlr-tb/test.py index 4a779024b..b63a86f2b 100644 --- a/testsuite/tests/I930-009-ppc-beqlr-tb/test.py +++ b/testsuite/tests/I930-009-ppc-beqlr-tb/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,11 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) thistest.fail_if( - not match('fff01008 \\+: 4d 9e 00 20 beqlr cr7', 'cond.out'), - 'branch should be taken') + not match("fff01008 \\+: 4d 9e 00 20 beqlr cr7", "cond.out"), + "branch should be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-ppc-beqlr-tk/test.py b/testsuite/tests/I930-009-ppc-beqlr-tk/test.py index 299864663..ad2c410e2 100644 --- a/testsuite/tests/I930-009-ppc-beqlr-tk/test.py +++ b/testsuite/tests/I930-009-ppc-beqlr-tk/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,11 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) thistest.fail_if( - not match('fff01008 >: 4d 9e 00 20 beqlr cr7', 'cond.out'), - 'branch should be taken') + not match("fff01008 >: 4d 9e 00 20 beqlr cr7", "cond.out"), + "branch should be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-ft/test.py b/testsuite/tests/I930-009-sparc-be-a-ft/test.py index d94232269..9344fb189 100644 --- a/testsuite/tests/I930-009-sparc-be-a-ft/test.py +++ b/testsuite/tests/I930-009-sparc-be-a-ft/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,12 +26,23 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('40001404 v: 32 80 00 02 bne,a', 'cond.out'), - 'branch should not be taken') -thistest.fail_if(not match('40001408 -: 90 10 20 02 mov', 'cond.out'), - 'delay slot should not be executed') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001404 v: 32 80 00 02 bne,a", "cond.out"), + "branch should not be taken", +) +thistest.fail_if( + not match("40001408 -: 90 10 20 02 mov", "cond.out"), + "delay slot should not be executed", +) thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.py b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.py index fd9438597..0c069959a 100644 --- a/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.py +++ b/testsuite/tests/I930-009-sparc-be-a-npg-ft/test.py @@ -3,15 +3,26 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild('test_cond.gpr') -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('40001ffc v: 32 80 00 02 bne,a', 'cond.out'), - 'branch should be not taken') -thistest.fail_if(not match('40002000 -: 90 10 20 02 mov', 'cond.out'), - "delay slot shouldn't be executed") +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001ffc v: 32 80 00 02 bne,a", "cond.out"), + "branch should be not taken", +) +thistest.fail_if( + not match("40002000 -: 90 10 20 02 mov", "cond.out"), + "delay slot shouldn't be executed", +) thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.py b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.py index 3a0798a2b..37436f06a 100644 --- a/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.py +++ b/testsuite/tests/I930-009-sparc-be-a-npg-tk/test.py @@ -3,13 +3,22 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild('test_cond.gpr') -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('40001ffc >: 32 80 00 02 bne,a', 'cond.out'), - 'branch should be taken') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001ffc >: 32 80 00 02 bne,a", "cond.out"), + "branch should be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-nt/test.py b/testsuite/tests/I930-009-sparc-be-a-nt/test.py index 4a2ab07c8..46cd96842 100644 --- a/testsuite/tests/I930-009-sparc-be-a-nt/test.py +++ b/testsuite/tests/I930-009-sparc-be-a-nt/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,13 +26,24 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('40001404 v: 32 80 00 02 bne,a', 'cond.out'), - 'branch should not be taken') - -thistest.fail_if(not match('40001408 -: 90 10 20 02 mov', 'cond.out'), - 'delay slot should not be executed') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001404 v: 32 80 00 02 bne,a", "cond.out"), + "branch should not be taken", +) + +thistest.fail_if( + not match("40001408 -: 90 10 20 02 mov", "cond.out"), + "delay slot should not be executed", +) thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-a-tk/test.py b/testsuite/tests/I930-009-sparc-be-a-tk/test.py index 3432109ee..206adb013 100644 --- a/testsuite/tests/I930-009-sparc-be-a-tk/test.py +++ b/testsuite/tests/I930-009-sparc-be-a-tk/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,13 +26,24 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('40001404 >: 32 80 00 02 bne,a', 'cond.out'), - 'branch should be taken') - -thistest.fail_if(not match('40001408 \\+: 90 10 20 02 mov', 'cond.out'), - 'delay slot should be executed') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001404 >: 32 80 00 02 bne,a", "cond.out"), + "branch should be taken", +) + +thistest.fail_if( + not match("40001408 \\+: 90 10 20 02 mov", "cond.out"), + "delay slot should be executed", +) thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-bt/test.py b/testsuite/tests/I930-009-sparc-be-bt/test.py index 6dddab52d..b3dccf739 100644 --- a/testsuite/tests/I930-009-sparc-be-bt/test.py +++ b/testsuite/tests/I930-009-sparc-be-bt/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -25,10 +25,19 @@ # # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('40001430 \\+: 12 80 00 04 bne', 'cond.out'), - 'branch should be taken on both dir') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001430 \\+: 12 80 00 04 bne", "cond.out"), + "branch should be taken on both dir", +) thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-ft/test.py b/testsuite/tests/I930-009-sparc-be-ft/test.py index d9a5ca4d8..4e745ae73 100644 --- a/testsuite/tests/I930-009-sparc-be-ft/test.py +++ b/testsuite/tests/I930-009-sparc-be-ft/test.py @@ -23,17 +23,28 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr'); -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) thistest.fail_if( - not match(re.escape('40001400 v: 12 80 00 04 ' - 'bne 0x40001410 '), - 'cond.out'), - 'branch should be taken on fall-through') + not match( + re.escape( + "40001400 v: 12 80 00 04 " "bne 0x40001410 " + ), + "cond.out", + ), + "branch should be taken on fall-through", +) thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-npg-bt/test.py b/testsuite/tests/I930-009-sparc-be-npg-bt/test.py index 984ce8b24..f673543e1 100644 --- a/testsuite/tests/I930-009-sparc-be-npg-bt/test.py +++ b/testsuite/tests/I930-009-sparc-be-npg-bt/test.py @@ -2,13 +2,22 @@ from SUITE.cutils import Wdir, match from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild('test_cond.gpr') -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('40001ffc \\+: 12 80 00 04 bne', 'cond.out'), - 'branch should be taken on both dir') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001ffc \\+: 12 80 00 04 bne", "cond.out"), + "branch should be taken on both dir", +) thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-npg-ft/test.py b/testsuite/tests/I930-009-sparc-be-npg-ft/test.py index 41f6dfa37..7364f24f8 100644 --- a/testsuite/tests/I930-009-sparc-be-npg-ft/test.py +++ b/testsuite/tests/I930-009-sparc-be-npg-ft/test.py @@ -3,13 +3,22 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild('test_cond.gpr') -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('40001ffc v: 12 80 00 04 bne', 'cond.out'), - 'branch should be taken fall-through') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001ffc v: 12 80 00 04 bne", "cond.out"), + "branch should be taken fall-through", +) thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-npg-tk/test.py b/testsuite/tests/I930-009-sparc-be-npg-tk/test.py index 94a899a5c..ab365f1c0 100644 --- a/testsuite/tests/I930-009-sparc-be-npg-tk/test.py +++ b/testsuite/tests/I930-009-sparc-be-npg-tk/test.py @@ -3,13 +3,22 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild ('test_cond.gpr') -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('40001ffc \\>: 12 80 00 04 bne', 'cond.out'), - 'branch should be taken on both dir') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001ffc \\>: 12 80 00 04 bne", "cond.out"), + "branch should be taken on both dir", +) thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-nt/test.py b/testsuite/tests/I930-009-sparc-be-nt/test.py index b5557ffe2..20047923f 100644 --- a/testsuite/tests/I930-009-sparc-be-nt/test.py +++ b/testsuite/tests/I930-009-sparc-be-nt/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project=gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -26,10 +26,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('40001444 -: 12 80 00 04 bne', 'cond.out'), - 'branch should not be taken') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001444 -: 12 80 00 04 bne", "cond.out"), + "branch should not be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-sparc-be-tk/test.py b/testsuite/tests/I930-009-sparc-be-tk/test.py index cd9b2bd67..b69e729c8 100644 --- a/testsuite/tests/I930-009-sparc-be-tk/test.py +++ b/testsuite/tests/I930-009-sparc-be-tk/test.py @@ -8,7 +8,7 @@ from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project = gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr'); @@ -25,10 +25,19 @@ # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') -thistest.fail_if(not match('40001400 >: 12 80 00 04 bne', 'cond.out'), - 'branch should be taken') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) +thistest.fail_if( + not match("40001400 >: 12 80 00 04 bne", "cond.out"), + "branch should be taken", +) thistest.result() diff --git a/testsuite/tests/I930-009-sparc-cross-boundary/test.py b/testsuite/tests/I930-009-sparc-cross-boundary/test.py index 4b677b7fd..5f6157fbb 100644 --- a/testsuite/tests/I930-009-sparc-cross-boundary/test.py +++ b/testsuite/tests/I930-009-sparc-cross-boundary/test.py @@ -7,7 +7,7 @@ from SUITE.cutils import Wdir, match from SUITE.tutils import exepath_to, tracename_for, xcov, xrun -Wdir('tmp_') +Wdir("tmp_") # gprbuild(project = gprfor(['test_robots.adb'])) # gprbuild('test_cond.gpr') @@ -24,13 +24,24 @@ # # We seek the reported status of the associated cond branch instructions # directly: -xrun(exepath_to('../test_cond')) -xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('test_cond')], 'cond.out') +xrun(exepath_to("../test_cond")) +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + tracename_for("test_cond"), + ], + "cond.out", +) -thistest.fail_if(not match('40001400 \\+: 81 c3 e0 08 retl', 'cond.out'), - 'cond should be covered') -thistest.fail_if(not match('40001404 \\+: 01 00 00 00 nop', 'cond.out'), - 'cond1 should be covered') +thistest.fail_if( + not match("40001400 \\+: 81 c3 e0 08 retl", "cond.out"), + "cond should be covered", +) +thistest.fail_if( + not match("40001404 \\+: 01 00 00 00 nop", "cond.out"), + "cond1 should be covered", +) thistest.result() diff --git a/testsuite/tests/I930-019/test.py b/testsuite/tests/I930-019/test.py index af9134ba5..8ebfdd3a8 100644 --- a/testsuite/tests/I930-019/test.py +++ b/testsuite/tests/I930-019/test.py @@ -5,25 +5,31 @@ from SUITE.tutils import gprfor -Wdir('tmp_') +Wdir("tmp_") # Run, then check results. build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor('test_kops.adb', srcdirs='../src')), - covlevel='stmt', - mains=['test_kops'], - extra_coverage_args=['--annotate=xcov'], - scos=['obj/kops', 'obj/ops4', 'obj/ops8', 'obj/test_kops', 'obj/vars']) + gprsw=GPRswitches(root_project=gprfor("test_kops.adb", srcdirs="../src")), + covlevel="stmt", + mains=["test_kops"], + extra_coverage_args=["--annotate=xcov"], + scos=["obj/kops", "obj/ops4", "obj/ops8", "obj/test_kops", "obj/vars"], +) -thistest.fail_if(not match(r'4 \+:', 'test_kops.adb.xcov'), - 'test_kops.adb:4 not covered') -thistest.fail_if(not match(r'6 \+:', 'test_kops.adb.xcov'), - 'test_kops.adb:6 not covered') -thistest.fail_if(not match(r'7 \+:', 'test_kops.adb.xcov'), - 'test_kops.adb:7 not covered') -thistest.fail_if(not match(r'9 \+:', 'test_kops.adb.xcov'), - 'test_kops.adb:9 not covered') -thistest.fail_if(not match(r'10 \+:', 'test_kops.adb.xcov'), - 'test_kops.adb:10 not covered') +thistest.fail_if( + not match(r"4 \+:", "test_kops.adb.xcov"), "test_kops.adb:4 not covered" +) +thistest.fail_if( + not match(r"6 \+:", "test_kops.adb.xcov"), "test_kops.adb:6 not covered" +) +thistest.fail_if( + not match(r"7 \+:", "test_kops.adb.xcov"), "test_kops.adb:7 not covered" +) +thistest.fail_if( + not match(r"9 \+:", "test_kops.adb.xcov"), "test_kops.adb:9 not covered" +) +thistest.fail_if( + not match(r"10 \+:", "test_kops.adb.xcov"), "test_kops.adb:10 not covered" +) thistest.result() diff --git a/testsuite/tests/IA01-015/test.py b/testsuite/tests/IA01-015/test.py index 79ad3cd0e..1d823e4fe 100644 --- a/testsuite/tests/IA01-015/test.py +++ b/testsuite/tests/IA01-015/test.py @@ -10,45 +10,54 @@ from SUITE.tutils import gprfor, xcov -wd = Wdir('tmp_') +wd = Wdir("tmp_") trace_file = build_and_run( - gprsw=GPRswitches(root_project=gprfor(srcdirs=['../src'], - mains=['trymon.adb'])), - covlevel='stmt', - mains=['trymon'], - extra_coverage_args=[])[-1] - -coverage_base_args = ['coverage', '--level=stmt', '--annotate=xcov', - trace_file] + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["trymon.adb"]) + ), + covlevel="stmt", + mains=["trymon"], + extra_coverage_args=[], +)[-1] + +coverage_base_args = [ + "coverage", + "--level=stmt", + "--annotate=xcov", + trace_file, +] expected_reports = { - 'trymon.adb.xcov': {'+': {24}}, - 'monitor.adb.xcov': {'+': {4}}, - 'monitor.ads.xcov': {}, + "trymon.adb.xcov": {"+": {24}}, + "monitor.adb.xcov": {"+": {4}}, + "monitor.ads.xcov": {}, } # Unlike in binary trace mode, where it is no-code, instrumentation allows to # detect that the Integer library-level variable declaration at line 2 is # covered. -if thistest.options.trace_mode == 'src': - expected_reports['monitor.ads.xcov'] = {'+': {2}} +if thistest.options.trace_mode == "src": + expected_reports["monitor.ads.xcov"] = {"+": {2}} def tryseq(label, scoargs): - thistest.log('== {} =='.format(label)) + thistest.log("== {} ==".format(label)) xcov(coverage_base_args + scoargs) - check_xcov_reports('.', expected_reports, discard_empty=False) + check_xcov_reports(".", expected_reports, discard_empty=False) -if thistest.options.trace_mode == 'src': - option = 'sid' - ext = 'sid' +if thistest.options.trace_mode == "src": + option = "sid" + ext = "sid" else: - option = 'scos' - ext = 'ali' - -sco_files = ['obj/trymon.{}'.format(ext), - 'obj/monitor.{}'.format(ext)] -tryseq('one_response_file', - scoargs=['--{}'.format(option), '@{}'.format(list_to_tmp(sco_files))]) -tryseq('multiple_files', - scoargs=['--{}={}'.format(option, ali) for ali in sco_files]) + option = "scos" + ext = "ali" + +sco_files = ["obj/trymon.{}".format(ext), "obj/monitor.{}".format(ext)] +tryseq( + "one_response_file", + scoargs=["--{}".format(option), "@{}".format(list_to_tmp(sco_files))], +) +tryseq( + "multiple_files", + scoargs=["--{}={}".format(option, ali) for ali in sco_files], +) thistest.result() diff --git a/testsuite/tests/IA06-008-override-exec/test.py b/testsuite/tests/IA06-008-override-exec/test.py index ee492a266..6ff8d8064 100644 --- a/testsuite/tests/IA06-008-override-exec/test.py +++ b/testsuite/tests/IA06-008-override-exec/test.py @@ -4,38 +4,58 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, match -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, - unixpath_to, xcov, xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + unixpath_to, + xcov, + xrun, +) -wd = Wdir('tmp_') +wd = Wdir("tmp_") -gprbuild(gprfor(srcdirs=['../src'], mains=['noop.adb'])) -xrun(unixpath_to('noop')) +gprbuild(gprfor(srcdirs=["../src"], mains=["noop.adb"])) +xrun(unixpath_to("noop")) # On Windows, we cannot override an existing file during a renaming. -if os.path.exists('nop'): - os.unlink('nop') -os.rename(exepath_to('noop'), 'nop') - -p = xcov(['coverage', '--level=branch', '--annotate=asm', - tracename_for('noop')], - out='not_found.out', register_failure=False) +if os.path.exists("nop"): + os.unlink("nop") +os.rename(exepath_to("noop"), "nop") + +p = xcov( + ["coverage", "--level=branch", "--annotate=asm", tracename_for("noop")], + out="not_found.out", + register_failure=False, +) thistest.fail_if( p.status == 0 or not match( - 'Cannot open ELF file %s for trace file' % unixpath_to('noop'), - 'not_found.out'), - 'no error if exec not found') + "Cannot open ELF file %s for trace file" % unixpath_to("noop"), + "not_found.out", + ), + "no error if exec not found", +) # We are not interested in the exact coverage status of the main symbol, so # just look if we have some coverage indication for it as a sanity check that # the coverage analysis request did something. Beware that "main" might be # named after the main subprogram on VxWorks systems. -xcov(['coverage', '--level=branch', '--annotate=asm', - '--exec=nop', tracename_for('noop')], - out='noop.stdout') -thistest.fail_if(not match('main|noop [+!]:', 'noop.stdout'), - '--exec overrides trace file info') +xcov( + [ + "coverage", + "--level=branch", + "--annotate=asm", + "--exec=nop", + tracename_for("noop"), + ], + out="noop.stdout", +) +thistest.fail_if( + not match("main|noop [+!]:", "noop.stdout"), + "--exec overrides trace file info", +) thistest.result() diff --git a/testsuite/tests/IA06-009-offset-from-sym/test.py b/testsuite/tests/IA06-009-offset-from-sym/test.py index 96ea6fd7a..ce79b37ad 100644 --- a/testsuite/tests/IA06-009-offset-from-sym/test.py +++ b/testsuite/tests/IA06-009-offset-from-sym/test.py @@ -6,19 +6,32 @@ from SUITE.context import thistest from SUITE.control import target_info from SUITE.cutils import Wdir, match -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -wd = Wdir('tmp_') -symbol = target_info().to_platform_specific_symbol('_ada_p') +wd = Wdir("tmp_") +symbol = target_info().to_platform_specific_symbol("_ada_p") -gprbuild(gprfor(srcdirs=['../src'], mains=['p.adb'])) -xrun(exepath_to('p')) -xcov(['coverage', - '--level=insn', '--annotate=xcov+', - '--routines={}'.format(symbol), tracename_for('p')]) +gprbuild(gprfor(srcdirs=["../src"], mains=["p.adb"])) +xrun(exepath_to("p")) +xcov( + [ + "coverage", + "--level=insn", + "--annotate=xcov+", + "--routines={}".format(symbol), + tracename_for("p"), + ] +) thistest.fail_if( - not match(r'<{}\+(00000000){{1,2}}>:'.format(symbol), 'p.adb.xcov'), - 'offset from symbols') + not match(r"<{}\+(00000000){{1,2}}>:".format(symbol), "p.adb.xcov"), + "offset from symbols", +) thistest.result() diff --git a/testsuite/tests/IA09-021-unit-nosco/test.py b/testsuite/tests/IA09-021-unit-nosco/test.py index 3644ce365..c3688bc83 100644 --- a/testsuite/tests/IA09-021-unit-nosco/test.py +++ b/testsuite/tests/IA09-021-unit-nosco/test.py @@ -5,13 +5,26 @@ from SUITE.context import thistest from SUITE.cutils import Wdir -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -Wdir('tmp_') -gprbuild(gprfor(['test_assert.adb'], srcdirs='../src')) -xrun(exepath_to('test_assert')) -xcov(['coverage', '--level=stmt', '--annotate=xcov', - '--scos=obj/checks.ali', tracename_for('test_assert')]) +Wdir("tmp_") +gprbuild(gprfor(["test_assert.adb"], srcdirs="../src")) +xrun(exepath_to("test_assert")) +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + "--scos=obj/checks.ali", + tracename_for("test_assert"), + ] +) thistest.result() diff --git a/testsuite/tests/IA13-015-loop-body/test.py b/testsuite/tests/IA13-015-loop-body/test.py index d461d66e1..5503d3a34 100644 --- a/testsuite/tests/IA13-015-loop-body/test.py +++ b/testsuite/tests/IA13-015-loop-body/test.py @@ -1,15 +1,23 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, match -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -Wdir('tmp_') -gprbuild(gprfor(['for_loop.adb'], srcdirs='../src'), gargs='-O0') -xrun(exepath_to('for_loop')) -xcov('coverage --level=branch --annotate=xcov ' + tracename_for('for_loop')) +Wdir("tmp_") +gprbuild(gprfor(["for_loop.adb"], srcdirs="../src"), gargs="-O0") +xrun(exepath_to("for_loop")) +xcov("coverage --level=branch --annotate=xcov " + tracename_for("for_loop")) # We expect the for loop body to be uncovered -thistest.fail_if(not match(r'[0-9]+ -:.*X := X \+ 1', 'for_loop.adb.xcov'), - 'expect loop body to be uncovered') +thistest.fail_if( + not match(r"[0-9]+ -:.*X := X \+ 1", "for_loop.adb.xcov"), + "expect loop body to be uncovered", +) thistest.result() diff --git a/testsuite/tests/IA16-028-disp-routines/test.py b/testsuite/tests/IA16-028-disp-routines/test.py index 282413c9d..3bb2963d8 100644 --- a/testsuite/tests/IA16-028-disp-routines/test.py +++ b/testsuite/tests/IA16-028-disp-routines/test.py @@ -4,56 +4,76 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of, set_from -from SUITE.tutils import (exepath_to, gprbuild, gprfor, - platform_specific_symbols, xcov) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + platform_specific_symbols, + xcov, +) -Wdir('tmp_') +Wdir("tmp_") # Check that --exclude/--include options are properly supported. -gprbuild(gprfor(srcdirs=['../src'], mains=['p.adb'])) -exe = exepath_to('p') +gprbuild(gprfor(srcdirs=["../src"], mains=["p.adb"])) +exe = exepath_to("p") # Simple usage of disp-routines: -xcov(['disp-routines', exe, '--exclude', 'obj/b__p.o'], - out='routines1.txt') +xcov(["disp-routines", exe, "--exclude", "obj/b__p.o"], out="routines1.txt") -r1 = contents_of('routines1.txt') +r1 = contents_of("routines1.txt") -for pattern in ('pack__q', 'pack__r', '_ada_p'): - thistest.fail_if(not re.search(pattern, r1), - "'%s' not found in disp-routines output" % pattern) +for pattern in ("pack__q", "pack__r", "_ada_p"): + thistest.fail_if( + not re.search(pattern, r1), + "'%s' not found in disp-routines output" % pattern, + ) # Check that "p.o - S" return the empty set if p.o is in S: -xcov(['disp-routines', '--include', 'obj/p.o', '--exclude', exe], - out='routines2.txt') +xcov( + ["disp-routines", "--include", "obj/p.o", "--exclude", exe], + out="routines2.txt", +) thistest.fail_if( - os.path.getsize('routines2.txt') > 0, - 'disp-routines -i p.o -o p.exe should return an empty set. Got:\n' + - contents_of('routines2.txt')) + os.path.getsize("routines2.txt") > 0, + "disp-routines -i p.o -o p.exe should return an empty set. Got:\n" + + contents_of("routines2.txt"), +) # Check various properties: that "S + p.o - p.o" is idempotent iff p.o is in S, # that "p.o + b~p.o - p.o - b~p.o + p.o" do exclude b~p.o... comparing the # output of disp-routines against a baseline (do not rely on the order of # output symbols, it is not defined). -copy('obj/p.o', 'obj/p1.o') -copy('obj/p.o', 'obj/p2.o') -copy('obj/b__p.o', 'obj/b__p1.o') - -xcov(['disp-routines', 'obj/p.o', 'obj/b__p.o', '--include', 'obj/pack.o', - '--exclude', 'obj/p1.o', 'obj/b__p1.o', '--include', 'obj/p2.o'], - out='routines3.txt') - -baseline3 = set(platform_specific_symbols(set_from('../baseline3.txt'))) -routines3 = set_from('routines3.txt') - -thistest.fail_if(baseline3 != routines3, - 'Advanced usage of disp-routines') +copy("obj/p.o", "obj/p1.o") +copy("obj/p.o", "obj/p2.o") +copy("obj/b__p.o", "obj/b__p1.o") + +xcov( + [ + "disp-routines", + "obj/p.o", + "obj/b__p.o", + "--include", + "obj/pack.o", + "--exclude", + "obj/p1.o", + "obj/b__p1.o", + "--include", + "obj/p2.o", + ], + out="routines3.txt", +) + +baseline3 = set(platform_specific_symbols(set_from("../baseline3.txt"))) +routines3 = set_from("routines3.txt") + +thistest.fail_if(baseline3 != routines3, "Advanced usage of disp-routines") thistest.result() diff --git a/testsuite/tests/IA19-009-no-useless-srcs/test.py b/testsuite/tests/IA19-009-no-useless-srcs/test.py index f3905c13b..f3f55ded7 100644 --- a/testsuite/tests/IA19-009-no-useless-srcs/test.py +++ b/testsuite/tests/IA19-009-no-useless-srcs/test.py @@ -12,18 +12,22 @@ from SUITE.tutils import gprfor -Wdir('tmp_') +Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(['test_engines.adb'], - srcdirs='../src'), - units=['engines']), - covlevel='stmt', - mains=['test_engines'], - extra_coverage_args=['--annotate=xcov'], - scos=['obj/engines']) + gprsw=GPRswitches( + root_project=gprfor(["test_engines.adb"], srcdirs="../src"), + units=["engines"], + ), + covlevel="stmt", + mains=["test_engines"], + extra_coverage_args=["--annotate=xcov"], + scos=["obj/engines"], +) -thistest.fail_if(not os.path.exists('engines.adb.xcov') - or os.path.exists('test_engines.adb.xcov'), - 'no annotated file when no sco') +thistest.fail_if( + not os.path.exists("engines.adb.xcov") + or os.path.exists("test_engines.adb.xcov"), + "no annotated file when no sco", +) thistest.result() diff --git a/testsuite/tests/IA21-003-simple-decision-sco/test.py b/testsuite/tests/IA21-003-simple-decision-sco/test.py index 6463762c7..f96ee8e49 100644 --- a/testsuite/tests/IA21-003-simple-decision-sco/test.py +++ b/testsuite/tests/IA21-003-simple-decision-sco/test.py @@ -3,19 +3,35 @@ """ from SUITE.context import thistest from SUITE.cutils import Wdir, match -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -Wdir('tmp_') +Wdir("tmp_") -gprbuild(gprfor(srcdirs=['../src'], mains=['p.adb'])) -xrun(exepath_to('p')) +gprbuild(gprfor(srcdirs=["../src"], mains=["p.adb"])) +xrun(exepath_to("p")) -xcov(['map-routines', '--scos=obj/pack.ali']) -xcov(['coverage', '--level=stmt', '--annotate=report', '--scos=obj/pack.ali', - '--report=out', tracename_for('p')]) -thistest.fail_if(not match('pack.adb:7:.* statement not executed', 'out'), - 'missing expected s- diagnostic with simple decision sco') +xcov(["map-routines", "--scos=obj/pack.ali"]) +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=report", + "--scos=obj/pack.ali", + "--report=out", + tracename_for("p"), + ] +) +thistest.fail_if( + not match("pack.adb:7:.* statement not executed", "out"), + "missing expected s- diagnostic with simple decision sco", +) thistest.result() diff --git a/testsuite/tests/IA21-009-nested-scos/test.py b/testsuite/tests/IA21-009-nested-scos/test.py index 2bcf63374..80cf80068 100644 --- a/testsuite/tests/IA21-009-nested-scos/test.py +++ b/testsuite/tests/IA21-009-nested-scos/test.py @@ -3,7 +3,7 @@ from SUITE.tutils import gprbuild, gprfor, xcov -Wdir('tmp_') -gprbuild(gprfor(['nested_same_sloc.adb'], srcdirs='../src')) -xcov(['map-routines', '--scos=obj/nested_same_sloc.ali']) +Wdir("tmp_") +gprbuild(gprfor(["nested_same_sloc.adb"], srcdirs="../src")) +xcov(["map-routines", "--scos=obj/nested_same_sloc.ali"]) thistest.result() diff --git a/testsuite/tests/IA22-004-same-basename/test.py b/testsuite/tests/IA22-004-same-basename/test.py index eb4d28258..dce505fa5 100644 --- a/testsuite/tests/IA22-004-same-basename/test.py +++ b/testsuite/tests/IA22-004-same-basename/test.py @@ -19,13 +19,15 @@ # mv repro main.elf # Context information, basic command line interface checks -print('maybe_valgrind prepends ...', maybe_valgrind([])) +print("maybe_valgrind prepends ...", maybe_valgrind([])) -xrun('main.elf') +xrun("main.elf") -formats = [('xml', '{slug}.xml', r''), - ('html', '{slug}.hunk.js', r'"coverage":"\+","assembly"'), - ('xcov+', '{slug}.xcov', r' *[0-9]+ \+:')] +formats = [ + ("xml", "{slug}.xml", r''), + ("html", "{slug}.hunk.js", r'"coverage":"\+","assembly"'), + ("xcov+", "{slug}.xcov", r" *[0-9]+ \+:"), +] # The pre-built binary embeds full paths to the sources at their build @@ -33,24 +35,40 @@ # dir. The paths gnatcov uses are internally canonicalized, which yields # Windows or Unix paths depending on the host ... + def hostify(path): - return ("C:" + path.replace('/', '\\') - if thistest.env.build.os.name == 'windows' - else path) + return ( + "C:" + path.replace("/", "\\") + if thistest.env.build.os.name == "windows" + else path + ) rebase_args = [ "--source-rebase={}={}".format( - hostify(f"{path}/tests/IA22-004-same-basename"), os.getcwd()) - for path in ("/home/pmderodat/_git/gnatcoverage/testsuite", - "/home/pmderodat/_git/gnatcoverage-extra")] + hostify(f"{path}/tests/IA22-004-same-basename"), os.getcwd() + ) + for path in ( + "/home/pmderodat/_git/gnatcoverage/testsuite", + "/home/pmderodat/_git/gnatcoverage-extra", + ) +] for fmt, filename, pattern in formats: - xcov(['coverage', '--level=insn', '--annotate=' + fmt, 'main.elf.trace', - '--output-dir=tmp'] + rebase_args) + xcov( + [ + "coverage", + "--level=insn", + "--annotate=" + fmt, + "main.elf.trace", + "--output-dir=tmp", + ] + + rebase_args + ) - for slug in ('d1-func.c', 'd2-func.c'): - output = 'tmp/' + filename.format(base='func.c', slug=slug) - thistest.fail_if(not match(pattern, output), - 'no line covered in {}'.format(output)) + for slug in ("d1-func.c", "d2-func.c"): + output = "tmp/" + filename.format(base="func.c", slug=slug) + thistest.fail_if( + not match(pattern, output), "no line covered in {}".format(output) + ) thistest.result() diff --git a/testsuite/tests/IA29-020-basic-checks/test.py b/testsuite/tests/IA29-020-basic-checks/test.py index b7d6f30ac..45d850f9a 100644 --- a/testsuite/tests/IA29-020-basic-checks/test.py +++ b/testsuite/tests/IA29-020-basic-checks/test.py @@ -6,53 +6,75 @@ from SUITE.context import thistest from SUITE.control import target_info from SUITE.cutils import FatalError, Wdir, match -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -Wdir('tmp_') -gprbuild(project=gprfor(['test_engines.adb'], srcdirs='../src')) -xrun(exepath_to('test_engines')) -line = ': return E.P < Stable_P and then E.T < Stable_T;' +Wdir("tmp_") +gprbuild(project=gprfor(["test_engines.adb"], srcdirs="../src")) +xrun(exepath_to("test_engines")) +line = ": return E.P < Stable_P and then E.T < Stable_T;" def src_cov(cov_level, annotate_level, line_coverage): try: - xcov(['coverage', - '--level=' + cov_level, '--annotate=' + annotate_level, - '--scos=obj/engines.ali', tracename_for('test_engines')]) - if annotate_level.find('xcov') != -1: - thistest.fail_if(not match('[0-9]+ ' + line_coverage + line, - 'engines.adb.xcov'), - 'check ' + cov_level + - ' coverage results on engines example') + xcov( + [ + "coverage", + "--level=" + cov_level, + "--annotate=" + annotate_level, + "--scos=obj/engines.ali", + tracename_for("test_engines"), + ] + ) + if annotate_level.find("xcov") != -1: + thistest.fail_if( + not match( + "[0-9]+ " + line_coverage + line, "engines.adb.xcov" + ), + "check " + cov_level + " coverage results on engines example", + ) except FatalError: pass def obj_cov(cov_level, annotate_level, line_coverage): - symbol = target_info().to_platform_specific_symbol('engines__stable') - xcov(['coverage', - '--level=' + cov_level, '--annotate=' + annotate_level, - '--routines={}'.format(symbol), tracename_for('test_engines')]) - if annotate_level.find('xcov') != -1: - thistest.fail_if(not match('[0-9]+ ' + line_coverage + line, - 'engines.adb.xcov'), - 'check ' + cov_level + - ' coverage results on engines example') + symbol = target_info().to_platform_specific_symbol("engines__stable") + xcov( + [ + "coverage", + "--level=" + cov_level, + "--annotate=" + annotate_level, + "--routines={}".format(symbol), + tracename_for("test_engines"), + ] + ) + if annotate_level.find("xcov") != -1: + thistest.fail_if( + not match("[0-9]+ " + line_coverage + line, "engines.adb.xcov"), + "check " + cov_level + " coverage results on engines example", + ) -src_cov_levels = ['stmt', 'stmt+decision', 'stmt+mcdc'] -annotate_levels = ['xcov', 'html'] +src_cov_levels = ["stmt", "stmt+decision", "stmt+mcdc"] +annotate_levels = ["xcov", "html"] -obj_cov_levels = ['insn', 'branch'] -obj_annotate_levels = annotate_levels + ['asm', 'html+', 'xcov+'] +obj_cov_levels = ["insn", "branch"] +obj_annotate_levels = annotate_levels + ["asm", "html+", "xcov+"] -line_coverage = {'insn': r'\+', - 'branch': '!', - 'stmt': r'\+', - 'stmt+decision': r'\+', - 'stmt+mcdc': '!'} +line_coverage = { + "insn": r"\+", + "branch": "!", + "stmt": r"\+", + "stmt+decision": r"\+", + "stmt+mcdc": "!", +} for cov_level in obj_cov_levels: for annotate_level in obj_annotate_levels: diff --git a/testsuite/tests/IA29-023-source-search/test.py b/testsuite/tests/IA29-023-source-search/test.py index a72bcb14f..11889d970 100644 --- a/testsuite/tests/IA29-023-source-search/test.py +++ b/testsuite/tests/IA29-023-source-search/test.py @@ -13,12 +13,13 @@ Wdir("tmp_") xcov_args = build_and_run( - gprsw=GPRswitches(root_project=gprfor(["test_engines.adb"], - srcdirs="../src")), + gprsw=GPRswitches( + root_project=gprfor(["test_engines.adb"], srcdirs="../src") + ), covlevel="stmt", mains=["test_engines"], extra_coverage_args=["--annotate=xcov"], - scos=["obj/engines"] + scos=["obj/engines"], ) xcov(xcov_args + ["--source-search=./src"], out="warnings1.txt") @@ -31,12 +32,16 @@ # Same test but with a response file source_search_filename = os.path.abspath("src-search.txt") -with open(source_search_filename, 'w') as f: +with open(source_search_filename, "w") as f: f.write(os.path.join("..", "newsrc")) -xcov(xcov_args + [f"--source-search=@{source_search_filename}"], out="warnings3.txt") -thistest.fail_if(not empty("warnings3.txt"), - "Source search unsuccessful (response file)") +xcov( + xcov_args + [f"--source-search=@{source_search_filename}"], + out="warnings3.txt", +) +thistest.fail_if( + not empty("warnings3.txt"), "Source search unsuccessful (response file)" +) os.rename("../newsrc", "../src") diff --git a/testsuite/tests/J618-019-disa-x86/test.py b/testsuite/tests/J618-019-disa-x86/test.py index e8f355d23..6670dd589 100644 --- a/testsuite/tests/J618-019-disa-x86/test.py +++ b/testsuite/tests/J618-019-disa-x86/test.py @@ -3,6 +3,6 @@ from SUITE.tutils import xcov -Wdir('tmp_') -xcov(['disassemble', '../insn.o'], 'insn.dis') +Wdir("tmp_") +xcov(["disassemble", "../insn.o"], "insn.dis") thistest.result() diff --git a/testsuite/tests/J723-017-empty-debug-info/test.py b/testsuite/tests/J723-017-empty-debug-info/test.py index bf4812dc7..216b84a79 100644 --- a/testsuite/tests/J723-017-empty-debug-info/test.py +++ b/testsuite/tests/J723-017-empty-debug-info/test.py @@ -3,6 +3,6 @@ from SUITE.tutils import xcov -Wdir('tmp_') -xcov(['dump-lines', '../ada_containers-aunit_lists.elf'], 'dwarf.out') +Wdir("tmp_") +xcov(["dump-lines", "../ada_containers-aunit_lists.elf"], "dwarf.out") thistest.result() diff --git a/testsuite/tests/JC09-015-set-file/test.py b/testsuite/tests/JC09-015-set-file/test.py index 107738555..fb83b2ba5 100644 --- a/testsuite/tests/JC09-015-set-file/test.py +++ b/testsuite/tests/JC09-015-set-file/test.py @@ -3,6 +3,6 @@ from SUITE.tutils import xcov -Wdir('tmp_') -xcov(['dump-lines', '../hello.o'], 'dwarf.out') +Wdir("tmp_") +xcov(["dump-lines", "../hello.o"], "dwarf.out") thistest.result() diff --git a/testsuite/tests/K214-014-gc-sections/test.py b/testsuite/tests/K214-014-gc-sections/test.py index b068eb6be..c14f43399 100644 --- a/testsuite/tests/K214-014-gc-sections/test.py +++ b/testsuite/tests/K214-014-gc-sections/test.py @@ -1,22 +1,42 @@ from SUITE.context import thistest from SUITE.control import target_info from SUITE.cutils import Wdir, match -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -Wdir('tmp_') -extralargs = ',--entry=foo' if target_info().partiallinks else '' +Wdir("tmp_") +extralargs = ",--entry=foo" if target_info().partiallinks else "" -gprbuild(gprfor(['foo.adb'], srcdirs='../src'), - extracargs='-ffunction-sections', - largs='-Wl,--gc-sections' + extralargs) -xrun(exepath_to('foo')) -xcov(['coverage', '--level=stmt', '--annotate=xcov', '--scos=obj/pck.ali', - tracename_for('foo')], out='ignore.out') +gprbuild( + gprfor(["foo.adb"], srcdirs="../src"), + extracargs="-ffunction-sections", + largs="-Wl,--gc-sections" + extralargs, +) +xrun(exepath_to("foo")) +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + "--scos=obj/pck.ali", + tracename_for("foo"), + ], + out="ignore.out", +) -thistest.fail_if(not match(r'\.: null; -- ELIMINATED', 'pck.adb.xcov'), - 'eliminated code not reported') -thistest.fail_if(not match(r'\+: null; -- COVERED', 'pck.adb.xcov'), - 'code not eliminated not reported') +thistest.fail_if( + not match(r"\.: null; -- ELIMINATED", "pck.adb.xcov"), + "eliminated code not reported", +) +thistest.fail_if( + not match(r"\+: null; -- COVERED", "pck.adb.xcov"), + "code not eliminated not reported", +) thistest.result() diff --git a/testsuite/tests/KB30-011-eargs-gnatemu/test.py b/testsuite/tests/KB30-011-eargs-gnatemu/test.py index f30b9f09f..4750959f0 100644 --- a/testsuite/tests/KB30-011-eargs-gnatemu/test.py +++ b/testsuite/tests/KB30-011-eargs-gnatemu/test.py @@ -9,10 +9,10 @@ from SUITE.tutils import gprbuild, gprfor, tracename_for, unixpath_to, xrun -Wdir('tmp_') +Wdir("tmp_") -pgm = 'myinc' -unit = pgm + '.adb' +pgm = "myinc" +unit = pgm + ".adb" exe = unixpath_to(pgm) trace = tracename_for(pgm) @@ -23,51 +23,70 @@ # basename. trace_basename = os.path.basename(trace) -gprbuild(gprfor(mains=[unit], srcdirs=['..'])) +gprbuild(gprfor(mains=[unit], srcdirs=[".."])) def check_eargs(output, eargs, exe, protect_eargs=False): - m = re.search('exec: .*gnatemu.*', output) + m = re.search("exec: .*gnatemu.*", output) e = m.group(0) if protect_eargs: - eargs = ' '.join ([f"'{arg}'" for arg in eargs.split(" ")]) + eargs = " ".join([f"'{arg}'" for arg in eargs.split(" ")]) thistest.fail_if( - not re.search("'--eargs' .*%(eargs)s.* '--eargs-end'.*%(exe)s" - % {'eargs': eargs, 'exe': exe}, e), + not re.search( + "'--eargs' .*%(eargs)s.* '--eargs-end'.*%(exe)s" + % {"eargs": eargs, "exe": exe}, + e, + ), "failed to match eargs='%s' and exe='%s' in output: <<\n%s\n>>" - % (eargs, exe, output)) + % (eargs, exe, output), + ) def gnatcovrun(extra, exe, register_failure=False, eargs=None): - outfile = 'gnatcov.out' - xrun('-v %(extra)s %(exe)s %(eargs)s' - % {'extra': extra, 'exe': exe, - 'eargs': ('-eargs %s' % eargs) if eargs else ''}, - out=outfile, register_failure=register_failure) + outfile = "gnatcov.out" + xrun( + "-v %(extra)s %(exe)s %(eargs)s" + % { + "extra": extra, + "exe": exe, + "eargs": ("-eargs %s" % eargs) if eargs else "", + }, + out=outfile, + register_failure=register_failure, + ) return contents_of(outfile) def gnatemulator(args, exe): - outfile = 'gnatemu.out' - Run(to_list('%(target)s-gnatemu %(args)s %(kernel)s %(exe)s' - % {'target': env.target.triplet, - 'args': args, - 'kernel': (('--kernel=' + thistest.options.kernel) - if thistest.options.kernel else ''), - 'exe': exe}), - output=outfile) + outfile = "gnatemu.out" + Run( + to_list( + "%(target)s-gnatemu %(args)s %(kernel)s %(exe)s" + % { + "target": env.target.triplet, + "args": args, + "kernel": ( + ("--kernel=" + thistest.options.kernel) + if thistest.options.kernel + else "" + ), + "exe": exe, + } + ), + output=outfile, + ) return contents_of(outfile) # stmt coverage, base check on exe expansion + no history request for traces # absence of eargs -extra = '--level=stmt' +extra = "--level=stmt" thistest.log(extra) output = gnatcovrun(extra=extra, exe=exe) check_eargs(output, eargs=trace, exe=exe) # Check absence of "history" trace request for decision coverage -extra = '--level=stmt+decision' +extra = "--level=stmt+decision" thistest.log(extra) output = gnatcovrun(extra=extra, exe=exe) check_eargs(output, eargs=trace, exe=exe) @@ -77,37 +96,41 @@ def gnatemulator(args, exe): # trace size limits in some configurations. In particular VxWorks, where we # run the entire OS, and targets where we might encounter busy loops in the # runtime for cache management. -extra = '--level=stmt+mcdc' +extra = "--level=stmt+mcdc" thistest.log(extra) -is_ignored_target = any(t in env.target.triplet for t in ['vx', 'aarch64']) -output = gnatcovrun(register_failure=not is_ignored_target, - extra=extra, exe=exe) -check_eargs(output, eargs='history,[^,]*%s' % trace_basename, exe=exe) +is_ignored_target = any(t in env.target.triplet for t in ["vx", "aarch64"]) +output = gnatcovrun( + register_failure=not is_ignored_target, extra=extra, exe=exe +) +check_eargs(output, eargs="history,[^,]*%s" % trace_basename, exe=exe) thistest.fail_if( - not re.search('warning: No SCOs specified for MC/DC level', output), - 'failed to match no-sco warning') + not re.search("warning: No SCOs specified for MC/DC level", output), + "failed to match no-sco warning", +) # Check "history" trace request with map + absence of warning. The decision map # filename is random, so use a wide matcher (anything but a comma) for it. -extra = '--level=stmt+mcdc --scos=obj/%s.ali' % pgm +extra = "--level=stmt+mcdc --scos=obj/%s.ali" % pgm thistest.log(extra) output = gnatcovrun(extra=extra, exe=exe) -check_eargs(output, eargs='histmap=[^,]+,[^,]*%s' % trace_basename, exe=exe) +check_eargs(output, eargs="histmap=[^,]+,[^,]*%s" % trace_basename, exe=exe) # Basic call with -eargs, check that they are included in the (single) # --eargs group as well, and check that qemu sees them -eargs = '-version -m 512' -extra = '--level=stmt' -thistest.log(extra + ' eargs for qemu') +eargs = "-version -m 512" +extra = "--level=stmt" +thistest.log(extra + " eargs for qemu") output = gnatcovrun(extra=extra, exe=exe, eargs=eargs) check_eargs(output, eargs=eargs, exe=exe, protect_eargs=True) -eargs1 = '-m 512' -eargs2 = '-version' -output = gnatemulator('-v --eargs %s --eargs-end --eargs %s --eargs-end' - % (eargs1, eargs2), exe) +eargs1 = "-m 512" +eargs2 = "-version" +output = gnatemulator( + "-v --eargs %s --eargs-end --eargs %s --eargs-end" % (eargs1, eargs2), exe +) thistest.fail_if( - not re.search('exec:.*qemu.*%s.*%s' % (eargs1, eargs2), output), - 'failed to match both --eargs sequences') + not re.search("exec:.*qemu.*%s.*%s" % (eargs1, eargs2), output), + "failed to match both --eargs sequences", +) thistest.result() diff --git a/testsuite/tests/KC06-023-list_as_ali/test.py b/testsuite/tests/KC06-023-list_as_ali/test.py index 2655c95e4..f25d7ba15 100644 --- a/testsuite/tests/KC06-023-list_as_ali/test.py +++ b/testsuite/tests/KC06-023-list_as_ali/test.py @@ -3,16 +3,20 @@ from SUITE.tutils import gprbuild, gprfor, xcov -Wdir('tmp_') -gprbuild(gprfor(['p.adb'], srcdirs='../src')) +Wdir("tmp_") +gprbuild(gprfor(["p.adb"], srcdirs="../src")) # Expect silent success -xcov(['map-routines', '--scos=@../plist', 'obj/p.o']) +xcov(["map-routines", "--scos=@../plist", "obj/p.o"]) # Expect failure -p = xcov(['map-routines', '--scos=../plist', 'obj/p.o'], - out='list_as_ali.out', register_failure=False) -thistest.fail_if(p.status == 0 or - not match('malformed ALI file', 'list_as_ali.out'), - 'no error on malformed ALI file') +p = xcov( + ["map-routines", "--scos=../plist", "obj/p.o"], + out="list_as_ali.out", + register_failure=False, +) +thistest.fail_if( + p.status == 0 or not match("malformed ALI file", "list_as_ali.out"), + "no error on malformed ALI file", +) thistest.result() diff --git a/testsuite/tests/KC23-012-ocov-exemptions/test.py b/testsuite/tests/KC23-012-ocov-exemptions/test.py index c3e9f7c8f..62c35b5c0 100644 --- a/testsuite/tests/KC23-012-ocov-exemptions/test.py +++ b/testsuite/tests/KC23-012-ocov-exemptions/test.py @@ -2,46 +2,62 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -Wdir('tmp_') +Wdir("tmp_") # Build and run a program with an "assert" function whose body is covered by an # exemption region. -gpr = gprfor(srcdirs=['..'], mains=['p.adb']) +gpr = gprfor(srcdirs=[".."], mains=["p.adb"]) gprbuild(gpr) -xrun(exepath_to('p')) +xrun(exepath_to("p")) # Exercise branch coverage different ways ... # # Without any sco/ali designation, the exemption region is expected not to be # honored. With --scos or --alis designating the proper ali, the exemption # region is expected to exempt something: -base_coverage = ['coverage', '--level=branch', '--annotate=xcov', - tracename_for('p')] +base_coverage = [ + "coverage", + "--level=branch", + "--annotate=xcov", + tracename_for("p"), +] def check(ali_spec): xcov(base_coverage + ali_spec) - this_report = contents_of('p.adb.xcov') + this_report = contents_of("p.adb.xcov") - xnote_never_true = r'\*' if ali_spec else '!' - xnote_uncovered = r'\*' if ali_spec else '-' - hint = ' '.join(ali_spec) if ali_spec else 'no ali' + xnote_never_true = r"\*" if ali_spec else "!" + xnote_uncovered = r"\*" if ali_spec else "-" + hint = " ".join(ali_spec) if ali_spec else "no ali" thistest.fail_if( - not re.search(pattern='%s:.*# expect-never-true' % xnote_never_true, - string=this_report), - '%s, unmatched expected-never-true' % hint) + not re.search( + pattern="%s:.*# expect-never-true" % xnote_never_true, + string=this_report, + ), + "%s, unmatched expected-never-true" % hint, + ) thistest.fail_if( - not re.search(pattern='%s:.*# expect-uncovered' % xnote_uncovered, - string=this_report), - '%s, unmatched expected-uncovered' % hint) + not re.search( + pattern="%s:.*# expect-uncovered" % xnote_uncovered, + string=this_report, + ), + "%s, unmatched expected-uncovered" % hint, + ) check(ali_spec=[]) -check(ali_spec=['--scos=obj/p.ali']) -check(ali_spec=['--alis=obj/p.ali']) -check(ali_spec=['-P', 'gen.gpr']) +check(ali_spec=["--scos=obj/p.ali"]) +check(ali_spec=["--alis=obj/p.ali"]) +check(ali_spec=["-P", "gen.gpr"]) thistest.result() diff --git a/testsuite/tests/L112-050-pro-through-disabled/test.py b/testsuite/tests/L112-050-pro-through-disabled/test.py index 1d6cf0348..d32dce67e 100644 --- a/testsuite/tests/L112-050-pro-through-disabled/test.py +++ b/testsuite/tests/L112-050-pro-through-disabled/test.py @@ -5,25 +5,29 @@ from SUITE.tutils import gprfor -Wdir('tmp_') +Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=['../src'], - mains=['dom_debug.adb'])), - covlevel='stmt', - mains=['dom_debug'], - extra_coverage_args=['--annotate=xcov'], - scos=['obj/dom_debug'], - extra_gprbuild_args=['-O0']) + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["dom_debug.adb"]) + ), + covlevel="stmt", + mains=["dom_debug"], + extra_coverage_args=["--annotate=xcov"], + scos=["obj/dom_debug"], + extra_gprbuild_args=["-O0"], +) # We expect the first variable declaration to be covered (through back # propagation through disabled dominant pragma Debug). thistest.fail_if( - not match(r'[0-9]+ \+:.*X0 : Integer;', 'dom_debug.adb.xcov'), - 'expect X0 to be covered') + not match(r"[0-9]+ \+:.*X0 : Integer;", "dom_debug.adb.xcov"), + "expect X0 to be covered", +) # The pragma itself is disabled and must be reported as NO CODE thistest.fail_if( - not match(r'[0-9]+ \.:.*pragma Debug', 'dom_debug.adb.xcov'), - 'expect pragma Debug to be marked no-code') + not match(r"[0-9]+ \.:.*pragma Debug", "dom_debug.adb.xcov"), + "expect pragma Debug to be marked no-code", +) thistest.result() diff --git a/testsuite/tests/L209-010-asm-outfile/test.py b/testsuite/tests/L209-010-asm-outfile/test.py index 2772137e1..a489167fd 100644 --- a/testsuite/tests/L209-010-asm-outfile/test.py +++ b/testsuite/tests/L209-010-asm-outfile/test.py @@ -5,37 +5,49 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of, match -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -Wdir('tmp_') +Wdir("tmp_") -pgm = 'plop' -pgreport = pgm + '.cov' -pgout = pgm + '.stdout' +pgm = "plop" +pgreport = pgm + ".cov" +pgout = pgm + ".stdout" -gprbuild(project=gprfor(pgm + '.adb', srcdirs='../src')) +gprbuild(project=gprfor(pgm + ".adb", srcdirs="../src")) xrun(exepath_to(pgm)) def check_output(spec): - fmt = spec['fmt'] - level = spec['level'] - key = spec['key'] - - xcov('coverage --level=%s --annotate=%s --scos=%s -o %s %s' % ( - level, fmt, 'obj/' + pgm + '.ali', pgreport, tracename_for(pgm)), - out=pgout) + fmt = spec["fmt"] + level = spec["level"] + key = spec["key"] + + xcov( + "coverage --level=%s --annotate=%s --scos=%s -o %s %s" + % (level, fmt, "obj/" + pgm + ".ali", pgreport, tracename_for(pgm)), + out=pgout, + ) thistest.fail_if( not match(key, pgreport), - 'expect asm dump in -o argument (%s), %s format' % (pgreport, fmt)) + "expect asm dump in -o argument (%s), %s format" % (pgreport, fmt), + ) thistest.fail_if( len(contents_of(pgout)) > 0, - 'expect empty stdout (directed to %s), %s format' % (pgout, fmt)) + "expect empty stdout (directed to %s), %s format" % (pgout, fmt), + ) -for spec in [{'level': 'branch', 'fmt': 'asm', 'key': 'level'}, - {'level': 'stmt', 'fmt': 'report', 'key': 'VIOLATIONS'}]: +for spec in [ + {"level": "branch", "fmt": "asm", "key": "level"}, + {"level": "stmt", "fmt": "report", "key": "VIOLATIONS"}, +]: check_output(spec) thistest.result() diff --git a/testsuite/tests/L411-031_missing_gnateS/test.py b/testsuite/tests/L411-031_missing_gnateS/test.py index cc6042777..22df94680 100644 --- a/testsuite/tests/L411-031_missing_gnateS/test.py +++ b/testsuite/tests/L411-031_missing_gnateS/test.py @@ -14,8 +14,7 @@ # We need full control over the compilation options here, so disconnect # all the default ones -_cargs = {'scovcargs': False, - 'suitecargs': False} +_cargs = {"scovcargs": False, "suitecargs": False} gprtemplate = """ project %(name)s is @@ -31,32 +30,44 @@ def trywith(thisid, thisopts): - gprname = thisid+".gpr" - with open(gprname, 'w') as gpr: - gpr.write(gprtemplate % { - "name": thisid, - "opts": ','.join('"%s"' % opt for opt in thisopts)}) + gprname = thisid + ".gpr" + with open(gprname, "w") as gpr: + gpr.write( + gprtemplate + % { + "name": thisid, + "opts": ",".join('"%s"' % opt for opt in thisopts), + } + ) gprbuild(gprname, gargs=["test_assert.adb"], **_cargs) xrun(exepath_to("test_assert")) - out = thisid+".out" + out = thisid + ".out" ali = "obj/checks.ali" - xcov(['coverage', '--level=stmt+decision', '--annotate=xcov', - '--scos=%s' % ali, tracename_for("test_assert")], - out=out) + xcov( + [ + "coverage", + "--level=stmt+decision", + "--annotate=xcov", + "--scos=%s" % ali, + tracename_for("test_assert"), + ], + out=out, + ) # Check that we get warning for each critical option not in the set we # passed. For warning checks purposes, equate -gnateS to -fdump-scos. - thisopts = ["-fdump-scos" if opt == "-gnateS" else opt - for opt in thisopts] + thisopts = ["-fdump-scos" if opt == "-gnateS" else opt for opt in thisopts] out = contents_of(out) for opt in critical_opts: if opt not in thisopts: thistest.fail_if( - not re.search("warning: %s: unit compiled without .*%s" - % (ali, opt), out), - 'case "%s" missing warning on %s' % (thisid, opt)) + not re.search( + "warning: %s: unit compiled without .*%s" % (ali, opt), out + ), + 'case "%s" missing warning on %s' % (thisid, opt), + ) # Now exercise the variants, with shortcut for option names diff --git a/testsuite/tests/L613-012/test.py b/testsuite/tests/L613-012/test.py index 91daa8e94..746b67b67 100644 --- a/testsuite/tests/L613-012/test.py +++ b/testsuite/tests/L613-012/test.py @@ -3,12 +3,13 @@ from SUITE.tutils import gprbuild, xcov -wd = Wdir('tmp_') +wd = Wdir("tmp_") -gprbuild('../app.gpr') -xcov(args='map-routines -P../app', out='xcov.out') -output = contents_of('xcov.out') +gprbuild("../app.gpr") +xcov(args="map-routines -P../app", out="xcov.out") +output = contents_of("xcov.out") thistest.fail_if( - 'no unit PAK2 in project App (coverage.units attribute)' not in output) + "no unit PAK2 in project App (coverage.units attribute)" not in output +) thistest.result() diff --git a/testsuite/tests/L619-040-output-to-objdir/test.py b/testsuite/tests/L619-040-output-to-objdir/test.py index 775e14655..ddaf47d90 100644 --- a/testsuite/tests/L619-040-output-to-objdir/test.py +++ b/testsuite/tests/L619-040-output-to-objdir/test.py @@ -14,31 +14,39 @@ from SUITE.tutils import gprfor, xcov -wd = Wdir(subdir='tmp_') +wd = Wdir(subdir="tmp_") # Setup a project file with an explicit object directory specified, build it # and execute the main. xcov_args = build_and_run( - gprsw=GPRswitches(root_project=gprfor(mains=['pgm.adb'], srcdirs=['..'], - objdir='obj', exedir='obj')), - gpr_obj_dir='obj', - covlevel='stmt', - mains=['pgm'], - gpr_exe_dir='obj', - extra_coverage_args=['--annotate=xcov']) + gprsw=GPRswitches( + root_project=gprfor( + mains=["pgm.adb"], srcdirs=[".."], objdir="obj", exedir="obj" + ) + ), + gpr_obj_dir="obj", + covlevel="stmt", + mains=["pgm"], + gpr_exe_dir="obj", + extra_coverage_args=["--annotate=xcov"], +) # Analyze, letting gnatcov pick a place for the report. Check that it picks the # project's object dir: -rm('obj/pgm.adb.xcov') -xcov(xcov_args, out='coverage1.log') -thistest.fail_if(not os.path.exists('obj/pgm.adb.xcov'), - 'could not find expected report in obj dir') +rm("obj/pgm.adb.xcov") +xcov(xcov_args, out="coverage1.log") +thistest.fail_if( + not os.path.exists("obj/pgm.adb.xcov"), + "could not find expected report in obj dir", +) # Analyze again, requesting a specific place for the report. Check that it is # created there: -rm('pgm.adb.xcov') -xcov(xcov_args + ['--output-dir=.'], out='coverage2.log') -thistest.fail_if(not os.path.exists('pgm.adb.xcov'), - 'could not find expected report in current dir') +rm("pgm.adb.xcov") +xcov(xcov_args + ["--output-dir=."], out="coverage2.log") +thistest.fail_if( + not os.path.exists("pgm.adb.xcov"), + "could not find expected report in current dir", +) thistest.result() diff --git a/testsuite/tests/L707-006-src-in-cwd/test.py b/testsuite/tests/L707-006-src-in-cwd/test.py index 66ef24ea4..a464f698a 100644 --- a/testsuite/tests/L707-006-src-in-cwd/test.py +++ b/testsuite/tests/L707-006-src-in-cwd/test.py @@ -1,13 +1,26 @@ from SUITE.context import thistest from SUITE.cutils import Wdir -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -Wdir('tmp_') +Wdir("tmp_") -gprbuild(gprfor(['test_engines.adb'], srcdirs="..")) +gprbuild(gprfor(["test_engines.adb"], srcdirs="..")) xrun(exepath_to("test_engines")) -xcov(['coverage', '--level=stmt', '--annotate=xcov', - tracename_for("test_engines"), '--scos=obj/engines.ali']) +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + tracename_for("test_engines"), + "--scos=obj/engines.ali", + ] +) thistest.result() diff --git a/testsuite/tests/L929-006/test.py b/testsuite/tests/L929-006/test.py index 9a63d6919..c6589c644 100644 --- a/testsuite/tests/L929-006/test.py +++ b/testsuite/tests/L929-006/test.py @@ -6,37 +6,38 @@ from SUITE.tutils import xcov -Wdir('tmp_') +Wdir("tmp_") sfiles_for = { - "leon-elf": ["leon-elf-orphans.s", "leon-elf-emptys.s"], - "powerpc-elf": ["powerpc-elf-orphans.s", "powerpc-elf-emptys.s"] + "leon-elf": ["leon-elf-orphans.s", "leon-elf-emptys.s"], + "powerpc-elf": ["powerpc-elf-orphans.s", "powerpc-elf-emptys.s"], } def do_for(target): - def to_object(sfile): - ofile = sfile.replace('.s', '.o') - Run([target + "-gcc", "-c", '../' + sfile, "-o", ofile]) + ofile = sfile.replace(".s", ".o") + Run([target + "-gcc", "-c", "../" + sfile, "-o", ofile]) return ofile ofiles = [to_object(sfile) for sfile in sfiles_for[target]] out_actual = target + "-actual.out" - out_expected = '../' + target + "-expected.out" + out_expected = "../" + target + "-expected.out" xcov(["scan-objects"] + ofiles, out=out_actual) thistest.fail_if( diff(out_actual, out_expected), - "%s != %s, using explicit list" % (out_actual, out_expected)) + "%s != %s, using explicit list" % (out_actual, out_expected), + ) xcov(["scan-objects", "@" + list_to_file(ofiles)], out=out_actual) thistest.fail_if( diff(out_actual, out_expected), - "%s != %s, using list file argument" % (out_actual, out_expected)) + "%s != %s, using list file argument" % (out_actual, out_expected), + ) do_for(env.target.triplet) diff --git a/testsuite/tests/LA17-032-scan-decisions/test.py b/testsuite/tests/LA17-032-scan-decisions/test.py index e3894fad3..827147640 100644 --- a/testsuite/tests/LA17-032-scan-decisions/test.py +++ b/testsuite/tests/LA17-032-scan-decisions/test.py @@ -9,15 +9,15 @@ from SUITE.tutils import gprbuild, gprfor, xcov -Wdir('tmp_') -gprbuild(gprfor(srcdirs=['..'], mains=['p.adb'])) +Wdir("tmp_") +gprbuild(gprfor(srcdirs=[".."], mains=["p.adb"])) -xcov(['scan-decisions', '--scos=obj/p.ali'], out='out-alis') -dif = diff('../expected.out', 'out-alis') -thistest.fail_if(dif, 'out-alis != expected regarding scan-decisions:\n' + dif) +xcov(["scan-decisions", "--scos=obj/p.ali"], out="out-alis") +dif = diff("../expected.out", "out-alis") +thistest.fail_if(dif, "out-alis != expected regarding scan-decisions:\n" + dif) -xcov(['scan-decisions', '-Pgen.gpr'], out='out-gpr') -dif = diff('../expected.out', 'out-gpr') -thistest.fail_if(dif, 'out-gpr != expected regarding scan-decisions:\n' + dif) +xcov(["scan-decisions", "-Pgen.gpr"], out="out-gpr") +dif = diff("../expected.out", "out-gpr") +thistest.fail_if(dif, "out-gpr != expected regarding scan-decisions:\n" + dif) thistest.result() diff --git a/testsuite/tests/LA23-016_eargs-exe/test.py b/testsuite/tests/LA23-016_eargs-exe/test.py index 83a6fa86f..f00664f02 100644 --- a/testsuite/tests/LA23-016_eargs-exe/test.py +++ b/testsuite/tests/LA23-016_eargs-exe/test.py @@ -5,37 +5,50 @@ Wdir("tmp_") -gprbuild(gprfor(srcdirs=["../src"], mains=['p.adb'])) +gprbuild(gprfor(srcdirs=["../src"], mains=["p.adb"])) exe = exepath_to("p") # Check that "xcov run p" and "xcov run -eargs p" # both work and produce the same result. + def run_check(id, args): rlog = id + ".rlog" trace = id + ".trace" xrun(["-o", trace] + args, out=rlog) thistest.fail_if( not empty(rlog) and not match("/runkernel", rlog), - "unexpected output from %s run:\n%s" % (id, contents_of(rlog))) + "unexpected output from %s run:\n%s" % (id, contents_of(rlog)), + ) def cov_check(id): clog = id + ".clog" trace = id + ".trace" rep = id + ".rep" - xcov(["coverage", "--level=stmt", "--scos=obj/myabs.ali", - "--annotate=report", trace, "-o", rep], - out=clog) + xcov( + [ + "coverage", + "--level=stmt", + "--scos=obj/myabs.ali", + "--annotate=report", + trace, + "-o", + rep, + ], + out=clog, + ) thistest.fail_if( not match("statement not executed", rep), - "missing expected stmt coverage violation note in %s" % rep) + "missing expected stmt coverage violation note in %s" % rep, + ) thistest.fail_if( not empty(clog), - "unexpected output from %s coverage :\n%s" % (id, contents_of(clog))) + "unexpected output from %s coverage :\n%s" % (id, contents_of(clog)), + ) id = "base" @@ -53,6 +66,7 @@ def cov_check(id): thistest.fail_if( not match(": Please specify an executable to run", log), - "missing expected error in log for run without exe") + "missing expected error in log for run without exe", +) thistest.result() diff --git a/testsuite/tests/M502-040-default-prj-path/test.py b/testsuite/tests/M502-040-default-prj-path/test.py index 5d55419ef..3c563757c 100644 --- a/testsuite/tests/M502-040-default-prj-path/test.py +++ b/testsuite/tests/M502-040-default-prj-path/test.py @@ -7,21 +7,20 @@ from SUITE.tutils import exepath_to, gpr_emulator_package, gprbuild, xrun -env.add_search_path(env_var='PATH', - path=os.path.join(os.getcwd(), 'bin'), - append=True) -env.add_search_path(env_var='GPR_PROJECT_PATH', - path=os.path.join(os.getcwd(), 'proj')) +env.add_search_path( + env_var="PATH", path=os.path.join(os.getcwd(), "bin"), append=True +) +env.add_search_path( + env_var="GPR_PROJECT_PATH", path=os.path.join(os.getcwd(), "proj") +) -os.chdir('proj/ut') +os.chdir("proj/ut") text_to_file( - contents_of('ut.gpr.template').format( - pkg_emulator=gpr_emulator_package() - ), - 'ut.gpr' + contents_of("ut.gpr.template").format(pkg_emulator=gpr_emulator_package()), + "ut.gpr", ) -gprbuild('ut') -xrun(['-P', 'ut', exepath_to('obj/main')]) +gprbuild("ut") +xrun(["-P", "ut", exepath_to("obj/main")]) thistest.result() diff --git a/testsuite/tests/M513-017/test.py b/testsuite/tests/M513-017/test.py index 9e97074d6..22fe6e14b 100644 --- a/testsuite/tests/M513-017/test.py +++ b/testsuite/tests/M513-017/test.py @@ -4,6 +4,5 @@ from SUITE.context import thistest -MapChecker(['driver.adb'], - alis=[os.path.join('obj', 'lib.ali')]).run() +MapChecker(["driver.adb"], alis=[os.path.join("obj", "lib.ali")]).run() thistest.result() diff --git a/testsuite/tests/M515-018/test.py b/testsuite/tests/M515-018/test.py index 8a969c23c..02d4d5af1 100644 --- a/testsuite/tests/M515-018/test.py +++ b/testsuite/tests/M515-018/test.py @@ -3,21 +3,29 @@ from SUITE.tutils import gprbuild, gprfor, xcov -Wdir('tmp_') +Wdir("tmp_") # First build the program -gprbuild(gprfor(mains=['return-ternary.c'], srcdirs='..')) +gprbuild(gprfor(mains=["return-ternary.c"], srcdirs="..")) # Then invoke map-routines so that SCOs are loaded. -xcov(['map-routines', - '--scos=obj/return-ternary.c.gli', 'obj/return-ternary.o'], - out='map-routines.txt') +xcov( + [ + "map-routines", + "--scos=obj/return-ternary.c.gli", + "obj/return-ternary.o", + ], + out="map-routines.txt", +) # The test fail if we find something like: # !!! return-ternary.c:3:10: unexpected SCO nesting in SCO #1: STATEMENT at # return-ternary.c:3:3-25, discarding nested SCO thistest.fail_if( - any(line.startswith('!!!') - for line in open('map-routines.txt', 'r').readlines()), - 'map-routines has found something wrong') + any( + line.startswith("!!!") + for line in open("map-routines.txt", "r").readlines() + ), + "map-routines has found something wrong", +) thistest.result() diff --git a/testsuite/tests/M531-035-3264-ld_preload/test.py b/testsuite/tests/M531-035-3264-ld_preload/test.py index 3a3d91219..fd54d91a7 100644 --- a/testsuite/tests/M531-035-3264-ld_preload/test.py +++ b/testsuite/tests/M531-035-3264-ld_preload/test.py @@ -12,18 +12,18 @@ # We build and check the output of a program doing system("ls") -gprbuild(gprfor(mains=['sls.c'], srcdirs='..')) +gprbuild(gprfor(mains=["sls.c"], srcdirs="..")) p = xrun(exepath_to("sls")) thistest.fail_if( re.search(pattern="LD_PRELOAD", string=p.out), - "spurious occurrence of LD_PRELOAD in the gnatcov run output" + "spurious occurrence of LD_PRELOAD in the gnatcov run output", ) thistest.fail_if( not re.search(pattern="gen.gpr", string=p.out), - "missing expected nls.c from the program output" + "missing expected nls.c from the program output", ) thistest.result() diff --git a/testsuite/tests/M625-011-GPR-Cunits/test.py b/testsuite/tests/M625-011-GPR-Cunits/test.py index a18d0b1b8..22a3ffb01 100644 --- a/testsuite/tests/M625-011-GPR-Cunits/test.py +++ b/testsuite/tests/M625-011-GPR-Cunits/test.py @@ -9,34 +9,37 @@ from SUITE.tutils import gprfor -wd = Wdir('tmp_') +wd = Wdir("tmp_") # Create a very simple C project -gpr = gprfor(mains='foo.c', srcdirs=['../src'], langs=["C"]) +gpr = gprfor(mains="foo.c", srcdirs=["../src"], langs=["C"]) # By default build_and_run will use -P to designate the units of interest, # which is what we want here. -coverage_log = 'coverage.log' +coverage_log = "coverage.log" build_run_and_coverage( gprsw=GPRswitches(root_project=gpr), - mains=['foo'], - covlevel='stmt', - extra_coverage_args=['-axcov', '--output-dir=.'], - out=coverage_log + mains=["foo"], + covlevel="stmt", + extra_coverage_args=["-axcov", "--output-dir=."], + out=coverage_log, ) thistest.fail_if( not empty(coverage_log), - comment='"gnatcov coverage" output not empty:\n' + - contents_of(coverage_log) + comment='"gnatcov coverage" output not empty:\n' + + contents_of(coverage_log), ) -check_xcov_reports('.', { - 'foo.c.xcov': {'+': {6}}, - 'bar.c.xcov': {'+': {6}}, - 'bar.h.xcov': {'+': {9}} -}) +check_xcov_reports( + ".", + { + "foo.c.xcov": {"+": {6}}, + "bar.c.xcov": {"+": {6}}, + "bar.h.xcov": {"+": {9}}, + }, +) thistest.result() diff --git a/testsuite/tests/M625-040-slow_on_windows/test.py b/testsuite/tests/M625-040-slow_on_windows/test.py index 0a94c5d66..ef8842ae3 100644 --- a/testsuite/tests/M625-040-slow_on_windows/test.py +++ b/testsuite/tests/M625-040-slow_on_windows/test.py @@ -7,8 +7,8 @@ from SUITE.tutils import exename_for, gprbuild, gprfor, xrun -Wdir('tmp_') -gpr = gprfor(srcdirs=['..'], mains=['p.adb']) +Wdir("tmp_") +gpr = gprfor(srcdirs=[".."], mains=["p.adb"]) def run(action, repeat, tag): @@ -16,7 +16,7 @@ def run(action, repeat, tag): for i in range(repeat): action() end = time.clock() - print('%s: %2.5f' % (tag, end-start)) + print("%s: %2.5f" % (tag, end - start)) def eval_gprbuild(): @@ -33,7 +33,7 @@ def eval(what): ps = pstats.Stats(profiler) ps.strip_dirs() - ps.sort_stats('time') + ps.sort_stats("time") print("===================") print("== %s ==" % what) diff --git a/testsuite/tests/M726-018-trace-exec-check/test.py b/testsuite/tests/M726-018-trace-exec-check/test.py index 4eed6ba08..e4edbf84d 100644 --- a/testsuite/tests/M726-018-trace-exec-check/test.py +++ b/testsuite/tests/M726-018-trace-exec-check/test.py @@ -4,44 +4,50 @@ from SUITE.context import thistest from SUITE.cutils import contents_of, Wdir -from SUITE.tutils import (exename_for, exepath_to, tracename_for, gprbuild, - gprfor, xrun, xcov,) +from SUITE.tutils import ( + exename_for, + exepath_to, + tracename_for, + gprbuild, + gprfor, + xrun, + xcov, +) # Work in a subdirectory -wd = Wdir(subdir='tmp_') +wd = Wdir(subdir="tmp_") -gpr = gprfor(mains=['foo.adb', 'bar.adb'], - srcdirs=['..']) +gpr = gprfor(mains=["foo.adb", "bar.adb"], srcdirs=[".."]) # Executable used to generate the reference trace -expected_program = exename_for('foo') +expected_program = exename_for("foo") # Executable that is different -unexpected_program = exename_for('bar') +unexpected_program = exename_for("bar") # Executable that is corrupted -corrupted_program = exename_for('foo-corrupted') +corrupted_program = exename_for("foo-corrupted") # Real name for the executable used by the trace, convenient for substituing # other executables still keeping the original one. -program_name = exename_for('program') -program_path = exepath_to('program') -trace_name = tracename_for('program') +program_name = exename_for("program") +program_path = exepath_to("program") +trace_name = tracename_for("program") # Prepare the test material gprbuild(project=gpr) -expected_timestamp = (os.stat(expected_program).st_mtime, ) * 2 -unexpected_timestamp = (expected_timestamp[0] + 10, ) * 2 +expected_timestamp = (os.stat(expected_program).st_mtime,) * 2 +unexpected_timestamp = (expected_timestamp[0] + 10,) * 2 shutil.copy(expected_program, corrupted_program) # Add a 'A' byte to expected_program, and a 'B' byte to the corrupted_program. # This way, they will have the same size, but a different checksum. -with open(expected_program, 'ab') as f: - f.write(b'\x00') -with open(corrupted_program, 'ab') as f: - f.write(b'\x01') +with open(expected_program, "ab") as f: + f.write(b"\x00") +with open(corrupted_program, "ab") as f: + f.write(b"\x01") # Generate the reference trace shutil.copy(expected_program, program_name) @@ -49,39 +55,55 @@ xrun(program_path) # Actually run the tests. -Case = namedtuple('Case', 'program timestamp expect_warning label') +Case = namedtuple("Case", "program timestamp expect_warning label") for case in ( - Case(expected_program, expected_timestamp, False, - 'GOOD filesize, timestamp, checksum'), - Case(expected_program, unexpected_timestamp, True, - 'GOOD program, checksum; BAD timestamp'), - Case(unexpected_program, expected_timestamp, True, - 'GOOD timestamp, checksum; BAD program'), - Case(corrupted_program, expected_timestamp, True, - 'GOOD program, timestamp; BAD checksum'), + Case( + expected_program, + expected_timestamp, + False, + "GOOD filesize, timestamp, checksum", + ), + Case( + expected_program, + unexpected_timestamp, + True, + "GOOD program, checksum; BAD timestamp", + ), + Case( + unexpected_program, + expected_timestamp, + True, + "GOOD timestamp, checksum; BAD program", + ), + Case( + corrupted_program, + expected_timestamp, + True, + "GOOD program, timestamp; BAD checksum", + ), ): shutil.copy(case.program, program_name) os.utime(program_name, case.timestamp) process = xcov( - 'coverage -P{} -c stmt -a report {}'.format(gpr, trace_name), - err='log.err', register_failure=False + "coverage -P{} -c stmt -a report {}".format(gpr, trace_name), + err="log.err", + register_failure=False, ) - xcov_warned = contents_of('log.err').startswith('warning: executable file') + xcov_warned = contents_of("log.err").startswith("warning: executable file") def expected_repr(expected): - return 'expected' if expected else 'unexpected' + return "expected" if expected else "unexpected" thistest.fail_if( xcov_warned != case.expect_warning, - '{} ({})'.format( - 'Warnings expected, got no one' - if case.expect_warning else - 'Expected no warnings, but got one', - - case.label - ) + "{} ({})".format( + "Warnings expected, got no one" + if case.expect_warning + else "Expected no warnings, but got one", + case.label, + ), ) thistest.result() diff --git a/testsuite/tests/MA08-031/test.py b/testsuite/tests/MA08-031/test.py index 40aaf8248..f6980fe96 100644 --- a/testsuite/tests/MA08-031/test.py +++ b/testsuite/tests/MA08-031/test.py @@ -3,8 +3,8 @@ from SUITE.tutils import gprfor, gprbuild, xcov -Wdir('tmp_') -gprbuild(gprfor(['f.adb'], srcdirs='../src'), gargs='-c') -xcov(['map-routines', '--scos=obj/f.ali', 'obj/f.o'], out='xcov.out') -thistest.fail_if(match('warning:', 'xcov.out'), 'no labeling warning expected') +Wdir("tmp_") +gprbuild(gprfor(["f.adb"], srcdirs="../src"), gargs="-c") +xcov(["map-routines", "--scos=obj/f.ali", "obj/f.o"], out="xcov.out") +thistest.fail_if(match("warning:", "xcov.out"), "no labeling warning expected") thistest.result() diff --git a/testsuite/tests/MB15-041-verbose-open-crc32/test.py b/testsuite/tests/MB15-041-verbose-open-crc32/test.py index 159ad3e9f..e9ff8ca25 100644 --- a/testsuite/tests/MB15-041-verbose-open-crc32/test.py +++ b/testsuite/tests/MB15-041-verbose-open-crc32/test.py @@ -5,30 +5,37 @@ from e3.os.fs import unixpath from SUITE.cutils import Wdir, FatalError, lines_of -from SUITE.tutils import (exepath_to, gprbuild, gprfor, thistest, - tracename_for, xcov, xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + thistest, + tracename_for, + xcov, + xrun, +) -tmp_ = Wdir('tmp_') +tmp_ = Wdir("tmp_") -GPR_FILE = gprfor('foo.adb', srcdirs='..') -EXE_FILE = exepath_to('foo') -TRACE_FILE = tracename_for('foo') +GPR_FILE = gprfor("foo.adb", srcdirs="..") +EXE_FILE = exepath_to("foo") +TRACE_FILE = tracename_for("foo") SCOS_FILES = [ - os.path.join('obj', 'foo.ali'), + os.path.join("obj", "foo.ali"), ] -CWD_LINE_PREFIX = 'CWD = ' +CWD_LINE_PREFIX = "CWD = " LOG_OPEN_RE = re.compile( r'\[GNATCOV\.MISC\] --- notice: open "(?P[^"]+)"' - r' \(CRC32 = 0x(?P[0-9a-f]{8})\)' + r" \(CRC32 = 0x(?P[0-9a-f]{8})\)" ) def list_to_text(items): - return ''.join( - ' - {}\n'.format(item) - for item in items - ) or ' \n' + return ( + "".join(" - {}\n".format(item) for item in items) + or " \n" + ) def check_same_files(expected, found): @@ -36,10 +43,8 @@ def check_same_files(expected, found): found = set(unixpath(path) for path in found) thistest.fail_if( expected != found, - 'Expecting:\n{}' - 'but found:\n{}'.format( - list_to_text(expected), list_to_text(found) - ) + "Expecting:\n{}" + "but found:\n{}".format(list_to_text(expected), list_to_text(found)), ) @@ -50,10 +55,7 @@ def check_logging(log_file, expected_files): """ # Rebase all input path to the temporary directory. base = os.getcwd() - expected_files = set( - os.path.join(base, path) - for path in expected_files - ) + expected_files = set(os.path.join(base, path) for path in expected_files) checksums = {} gnatcov_cwd = None @@ -62,7 +64,7 @@ def check_logging(log_file, expected_files): # logging. for line in lines_of(log_file): if line.startswith(CWD_LINE_PREFIX): - gnatcov_cwd = line[len(CWD_LINE_PREFIX):].strip() + gnatcov_cwd = line[len(CWD_LINE_PREFIX) :].strip() else: m = LOG_OPEN_RE.match(line) @@ -71,23 +73,24 @@ def check_logging(log_file, expected_files): thistest.stop_if( not gnatcov_cwd, - FatalError("Got a checksum before GNATcov's CWD") + FatalError("Got a checksum before GNATcov's CWD"), ) - filepath = os.path.join(gnatcov_cwd, m.group('file')) - checksums[filepath] = int(m.group('crc32'), 16) + filepath = os.path.join(gnatcov_cwd, m.group("file")) + checksums[filepath] = int(m.group("crc32"), 16) # Check that these checksums match the set of files. check_same_files(expected_files, set(checksums.keys())) # Then check that each checksum is valid. for filename, checksum in checksums.items(): - with open(filename, 'rb') as fp: - expected_checksum = crc32(fp.read()) & 0xffffffff + with open(filename, "rb") as fp: + expected_checksum = crc32(fp.read()) & 0xFFFFFFFF thistest.fail_if( expected_checksum != checksum, - 'Bad checksum for {}: expecting CRC32={:#08x}, but found {:#08x}' - .format(filename, expected_checksum, checksum) + "Bad checksum for {}: expecting CRC32={:#08x}, but found {:#08x}".format( + filename, expected_checksum, checksum + ), ) @@ -96,17 +99,23 @@ def check_logging(log_file, expected_files): # Produce some trace and check the verbose logging. xrun( - ['--verbose', '--level=stmt+mcdc', '-P{}'.format(GPR_FILE), EXE_FILE], - out='xcov-run.log' + ["--verbose", "--level=stmt+mcdc", "-P{}".format(GPR_FILE), EXE_FILE], + out="xcov-run.log", ) -check_logging('xcov-run.log', [EXE_FILE] + SCOS_FILES) +check_logging("xcov-run.log", [EXE_FILE] + SCOS_FILES) # Then compute the coverage report and check again the verbose logging. xcov( - ['coverage', '--verbose', '--level=stmt+mcdc', '--annotate=report', - '-P{}'.format(GPR_FILE), TRACE_FILE], - out='xcov-coverage.log' + [ + "coverage", + "--verbose", + "--level=stmt+mcdc", + "--annotate=report", + "-P{}".format(GPR_FILE), + TRACE_FILE, + ], + out="xcov-coverage.log", ) -check_logging('xcov-coverage.log', [EXE_FILE, TRACE_FILE] + SCOS_FILES) +check_logging("xcov-coverage.log", [EXE_FILE, TRACE_FILE] + SCOS_FILES) thistest.result() diff --git a/testsuite/tests/MB19-016-subprogram-less-code/test.py b/testsuite/tests/MB19-016-subprogram-less-code/test.py index cfb559151..d299e4fd2 100644 --- a/testsuite/tests/MB19-016-subprogram-less-code/test.py +++ b/testsuite/tests/MB19-016-subprogram-less-code/test.py @@ -10,40 +10,55 @@ from SUITE.cutils import Wdir from SUITE.tutils import ( - exepath_to, gprbuild, gprfor, thistest, tracename_for, xcov, xrun + exepath_to, + gprbuild, + gprfor, + thistest, + tracename_for, + xcov, + xrun, ) -rm('tmp_', recursive=True) -tmp_ = Wdir('tmp_') +rm("tmp_", recursive=True) +tmp_ = Wdir("tmp_") # We are producing object coverage reports and need fine control over the # compilation options here -_cargs = {'scovcargs': False, - 'suitecargs': False} +_cargs = {"scovcargs": False, "suitecargs": False} # First stage: compile the C source code to assembly. We want no debug # information at this stage. gpr_stage1 = gprfor( - 'foo.c', prjid='stage1', srcdirs='..', exedir='.', - main_cargs='-g0 -save-temps', langs=('C', )) -gprbuild(gpr_stage1, gargs='-c', **_cargs) + "foo.c", + prjid="stage1", + srcdirs="..", + exedir=".", + main_cargs="-g0 -save-temps", + langs=("C",), +) +gprbuild(gpr_stage1, gargs="-c", **_cargs) # Second stage: assemble to object code with debug information relative to the # assembly. gpr_stage2 = gprfor( - 'foo.s', prjid='stage2', srcdirs='obj', exedir='.', - main_cargs='-g', langs=('Asm', )) + "foo.s", + prjid="stage2", + srcdirs="obj", + exedir=".", + main_cargs="-g", + langs=("Asm",), +) gprbuild(gpr_stage2, **_cargs) -gnatcov_flags = ['-P', gpr_stage2, '--level=branch'] +gnatcov_flags = ["-P", gpr_stage2, "--level=branch"] # Run and compute code coverage. -xrun(gnatcov_flags + [exepath_to('foo')]) -xcov(['coverage'] + gnatcov_flags + ['--annotate=xcov', tracename_for('foo')]) +xrun(gnatcov_flags + [exepath_to("foo")]) +xcov(["coverage"] + gnatcov_flags + ["--annotate=xcov", tracename_for("foo")]) thistest.fail_if( - not os.path.exists(os.path.join('obj', 'foo.s.xcov')), - 'There is no XCOV report for foo.s' + not os.path.exists(os.path.join("obj", "foo.s.xcov")), + "There is no XCOV report for foo.s", ) thistest.result() diff --git a/testsuite/tests/MC05-011-ref-executable/test.py b/testsuite/tests/MC05-011-ref-executable/test.py index 7d4284c2b..01a61e3aa 100644 --- a/testsuite/tests/MC05-011-ref-executable/test.py +++ b/testsuite/tests/MC05-011-ref-executable/test.py @@ -12,35 +12,41 @@ from SUITE.tutils import exepath_to, gprfor, xcov -Wdir('tmp_') +Wdir("tmp_") # Build App which encloses two units (bump and double), and a unit test for # just the bump unit. Then run the unit test. xcov_args = build_and_run( - gprsw=GPRswitches(root_project=gprfor(srcdirs=['../src'], - mains=['test_bump.adb', 'app.adb'])), - covlevel='stmt', - mains=['test_bump'], - extra_coverage_args=['--annotate=report'], - scos=['obj/bump', 'obj/double']) + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=["../src"], mains=["test_bump.adb", "app.adb"] + ) + ), + covlevel="stmt", + mains=["test_bump"], + extra_coverage_args=["--annotate=report"], + scos=["obj/bump", "obj/double"], +) # Do stmt coverage analysis providing scos for all the units and the unit test # trace. Check that we have diagnostics of absence of coverage on the elements # part of the untested unit with or without an additional --exec. + def trycov(exec_args): p = xcov(xcov_args + exec_args) thistest.fail_if( - not re.search(r'double.adb:\d+:\d+: statement not executed', p.out), - 'Missing stmt violation on double.adb, exec_args: %s' % str(exec_args)) + not re.search(r"double.adb:\d+:\d+: statement not executed", p.out), + "Missing stmt violation on double.adb, exec_args: %s" % str(exec_args), + ) trycov(exec_args=[]) # --exec does not make sense (and is not allowed) in source trace mode if thistest.options.trace_mode == "bin": - trycov(exec_args=['--exec=%s' % exepath_to('app')]) + trycov(exec_args=["--exec=%s" % exepath_to("app")]) thistest.result() diff --git a/testsuite/tests/N107-020-dhtml/test.py b/testsuite/tests/N107-020-dhtml/test.py index cea0e585a..ae6cd1f24 100644 --- a/testsuite/tests/N107-020-dhtml/test.py +++ b/testsuite/tests/N107-020-dhtml/test.py @@ -19,18 +19,19 @@ def check(label, scos): wd = Wdir(subdir=f"tmp_{label}") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(mains=['foo.adb'], - srcdirs=['..'])), + gprsw=GPRswitches( + root_project=gprfor(mains=["foo.adb"], srcdirs=[".."]) + ), covlevel="stmt", mains=["foo"], extra_coverage_args=["--annotate=dhtml", "--output-dir=dhtml-report"], scos=scos, ) - index = os.path.join("dhtml-report", 'index.html') + index = os.path.join("dhtml-report", "index.html") thistest.fail_if( not os.path.isfile(index) or os.path.getsize(index) == 0, - f"missing or empty {index} for {label}" + f"missing or empty {index} for {label}", ) wd.to_homedir() diff --git a/testsuite/tests/N107-029-crc32-validity/test.py b/testsuite/tests/N107-029-crc32-validity/test.py index 89be86fab..c1479699f 100644 --- a/testsuite/tests/N107-029-crc32-validity/test.py +++ b/testsuite/tests/N107-029-crc32-validity/test.py @@ -9,19 +9,25 @@ from SUITE.context import thistest from SUITE.cutils import lines_of, Wdir -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) # Work in a subdirectory -wd = Wdir(subdir='tmp_') +wd = Wdir(subdir="tmp_") # Generate the program executable, then run it to get an execution trace: -gpr = gprfor(mains=['foo.adb'], srcdirs=['..']) +gpr = gprfor(mains=["foo.adb"], srcdirs=[".."]) gprbuild(project=gpr) -program_path = exepath_to('foo') -trace_name = tracename_for('foo') +program_path = exepath_to("foo") +trace_name = tracename_for("foo") xrun(program_path) @@ -29,29 +35,34 @@ # # Tag : EXEC_FILE_CRC32 # Data : -xcov(['dump-trace', trace_name], out='trace.dump') -trace_dump = [line.strip() for line in lines_of('trace.dump')] +xcov(["dump-trace", trace_name], out="trace.dump") +trace_dump = [line.strip() for line in lines_of("trace.dump")] -tag_line_no = trace_dump.index('Tag : EXEC_FILE_CRC32') +tag_line_no = trace_dump.index("Tag : EXEC_FILE_CRC32") data_line = trace_dump[tag_line_no + 2] # Get the decimal checksum -prefix = 'Data : ' +prefix = "Data : " thistest.stop_if( not data_line.startswith(prefix), - ValueError('Invalid trace text dump (invalid "Data" line): {!r}' - .format(data_line)) + ValueError( + 'Invalid trace text dump (invalid "Data" line): {!r}'.format(data_line) + ), ) -gnatcov_checksum = int(data_line[len(prefix):]) +gnatcov_checksum = int(data_line[len(prefix) :]) # And then compare it with the one Python computes -with open(program_path, 'rb') as f: +with open(program_path, "rb") as f: # binascii.crc32 returns a signed 32-bit integer. Make it unsigned to be # consistent with GNATcoverage. - expected_checksum = binascii.crc32(f.read()) & 0xffffffff + expected_checksum = binascii.crc32(f.read()) & 0xFFFFFFFF thistest.stop_if( gnatcov_checksum != expected_checksum, - ValueError('CRC32 mismatch: {} (expected) != {} (got)' - .format(expected_checksum, gnatcov_checksum))) + ValueError( + "CRC32 mismatch: {} (expected) != {} (got)".format( + expected_checksum, gnatcov_checksum + ) + ), +) thistest.result() diff --git a/testsuite/tests/N203-040-same-c-basename/test.py b/testsuite/tests/N203-040-same-c-basename/test.py index 47cf95048..16cdeae96 100644 --- a/testsuite/tests/N203-040-same-c-basename/test.py +++ b/testsuite/tests/N203-040-same-c-basename/test.py @@ -8,25 +8,31 @@ from SCOV.tctl import CAT from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) # This must work for source coverage... TestCase(category=CAT.stmt).run() # ... and for object coverage, too! -tmp_ = Wdir('tmp_') +tmp_ = Wdir("tmp_") -gprfile = gprfor('test_foo.c', srcdirs=os.path.join('..', 'src')) -exefile = exepath_to('test_foo') -tracefile = tracename_for('test_foo') -logfile = 'xcov-coverage.log' +gprfile = gprfor("test_foo.c", srcdirs=os.path.join("..", "src")) +exefile = exepath_to("test_foo") +tracefile = tracename_for("test_foo") +logfile = "xcov-coverage.log" -routinesfile = 'routines.list' -with open(routinesfile, 'w') as f: - for symbol in ('main', 'foo', 'other_foo'): - f.write('{}\n'.format(symbol)) +routinesfile = "routines.list" +with open(routinesfile, "w") as f: + for symbol in ("main", "foo", "other_foo"): + f.write("{}\n".format(symbol)) gprbuild(gprfile) xrun(exefile) @@ -35,20 +41,21 @@ # warnings about various source files having the same base name. xcov( [ - 'coverage', - '-P{}'.format(gprfile), - '--level=insn', '--annotate=xcov', - '--routines=@{}'.format(routinesfile), - tracefile + "coverage", + "-P{}".format(gprfile), + "--level=insn", + "--annotate=xcov", + "--routines=@{}".format(routinesfile), + tracefile, ], - out=logfile + out=logfile, ) thistest.fail_if( os.path.getsize(logfile) > 0, - 'xcov standard output not empty ({}):\n--\n{}'.format( + "xcov standard output not empty ({}):\n--\n{}".format( logfile, contents_of(logfile) - ) + ), ) thistest.result() diff --git a/testsuite/tests/N321-039-disas-wrapping/test.py b/testsuite/tests/N321-039-disas-wrapping/test.py index 9fbd7b823..7ed4ed5af 100644 --- a/testsuite/tests/N321-039-disas-wrapping/test.py +++ b/testsuite/tests/N321-039-disas-wrapping/test.py @@ -7,32 +7,31 @@ from SUITE.cutils import Wdir from SUITE.tutils import gprfor, gprbuild, xcov -tmp_ = Wdir('tmp_') +tmp_ = Wdir("tmp_") # We want to link the code at the end of the address space, so get the correct # upper address depending on the architecture. -address = ( - 2**32 - 1 - if '32bits' in thistest.options.tags else - 2**64 - 1 -) +address = 2**32 - 1 if "32bits" in thistest.options.tags else 2**64 - 1 gprfile = gprfor( - ['foo.s'], + ["foo.s"], srcdirs="..", - langs=('Asm'), - extra=''' + langs=("Asm"), + extra=""" package Linker is for Default_Switches ("Asm") use ("-nostdlib", "-Ttext={}"); end Linker; -'''.format(address)) -exefile = 'foo' +""".format( + address + ), +) +exefile = "foo" gprbuild(gprfile) -for subcmd in ('dump-cfg', 'disassemble-insn-properties'): +for subcmd in ("dump-cfg", "disassemble-insn-properties"): # As long as GNATcov do not crash/hangs, everything is fine! - xcov([subcmd, exefile, '_start']) + xcov([subcmd, exefile, "_start"]) thistest.result() diff --git a/testsuite/tests/N321-045-ppc-disas-large-input/test.py b/testsuite/tests/N321-045-ppc-disas-large-input/test.py index dc329e6f3..4de3f4861 100644 --- a/testsuite/tests/N321-045-ppc-disas-large-input/test.py +++ b/testsuite/tests/N321-045-ppc-disas-large-input/test.py @@ -7,12 +7,12 @@ from SUITE.cutils import Wdir from SUITE.tutils import gprfor, gprbuild, xcov -tmp_ = Wdir('tmp_') +tmp_ = Wdir("tmp_") -gprfile = gprfor(['foo.adb'], srcdirs="..") +gprfile = gprfor(["foo.adb"], srcdirs="..") gprbuild(gprfile) # As long as GNATcov do not crash/hangs, everything is fine! -xcov(['disassemble-insn-properties', 'foo', '_ada_foo']) +xcov(["disassemble-insn-properties", "foo", "_ada_foo"]) thistest.result() diff --git a/testsuite/tests/N411-046-asm-consolidation/test.py b/testsuite/tests/N411-046-asm-consolidation/test.py index b81df1f93..49ec8619c 100644 --- a/testsuite/tests/N411-046-asm-consolidation/test.py +++ b/testsuite/tests/N411-046-asm-consolidation/test.py @@ -15,25 +15,28 @@ from SUITE.tutils import tracename_for test_drivers = { - 'test': {'p.s': ['-g']}, + "test": {"p.s": ["-g"]}, } coverage_expectations = { # There is only one "p" routine and we should consolidate them: we expect # only one "+" covered "p" routine. - 'p': {'-': 0, '!': 0, '+': 1}, + "p": {"-": 0, "!": 0, "+": 1}, } -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") -shutil.copy(os.path.join('..', 'test.c'), 'test.c') +shutil.copy(os.path.join("..", "test.c"), "test.c") # Select an assembly source that fits the build platform -variant = 'default' -if env.build.os.name == 'windows': - variant = 'win32' if env.build.cpu.bits == 32 else 'win64' -shutil.copy(os.path.join('..', 'p-{}.s'.format(variant)), 'p.s') - -TestCase(test_drivers, coverage_expectations, - extra_xcov_args=[tracename_for('test')]).run() +variant = "default" +if env.build.os.name == "windows": + variant = "win32" if env.build.cpu.bits == 32 else "win64" +shutil.copy(os.path.join("..", "p-{}.s".format(variant)), "p.s") + +TestCase( + test_drivers, + coverage_expectations, + extra_xcov_args=[tracename_for("test")], +).run() thistest.result() diff --git a/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.py b/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.py index dbe2d1f1e..473958a65 100644 --- a/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.py +++ b/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.py @@ -5,7 +5,7 @@ TestCase( # Note that when C support for GNATcoverage will be ready, this flag # should be automatically enabled with -fdump-scos. - extracargs='-no-integrated-cpp', - category=CAT.stmt + extracargs="-no-integrated-cpp", + category=CAT.stmt, ).run() thistest.result() diff --git a/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.py b/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.py index dbe2d1f1e..473958a65 100644 --- a/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.py +++ b/testsuite/tests/N429-018-c-assert/ToSingleStmt/test.py @@ -5,7 +5,7 @@ TestCase( # Note that when C support for GNATcoverage will be ready, this flag # should be automatically enabled with -fdump-scos. - extracargs='-no-integrated-cpp', - category=CAT.stmt + extracargs="-no-integrated-cpp", + category=CAT.stmt, ).run() thistest.result() diff --git a/testsuite/tests/N429-018-c-tern-folding/test.py b/testsuite/tests/N429-018-c-tern-folding/test.py index 8bede2117..2f452a6da 100644 --- a/testsuite/tests/N429-018-c-tern-folding/test.py +++ b/testsuite/tests/N429-018-c-tern-folding/test.py @@ -7,7 +7,7 @@ TestCase( # Note that when C support for GNATcoverage will be ready, this flag # should be automatically enabled with -fdump-scos. - extracargs='-no-integrated-cpp', - category=cat + extracargs="-no-integrated-cpp", + category=cat, ).run() thistest.result() diff --git a/testsuite/tests/N429-020-loop-on-line-ada/test.py b/testsuite/tests/N429-020-loop-on-line-ada/test.py index a288ad03c..a2d878217 100644 --- a/testsuite/tests/N429-020-loop-on-line-ada/test.py +++ b/testsuite/tests/N429-020-loop-on-line-ada/test.py @@ -3,8 +3,5 @@ from SCOV.map import MapChecker from SUITE.tutils import thistest -MapChecker( - ['foo.adb'], - alis=[os.path.join('obj', 'foo.ali')] -).run() +MapChecker(["foo.adb"], alis=[os.path.join("obj", "foo.ali")]).run() thistest.result() diff --git a/testsuite/tests/N429-020-loop-on-line/test.py b/testsuite/tests/N429-020-loop-on-line/test.py index eb1505ae4..72ca70f3f 100644 --- a/testsuite/tests/N429-020-loop-on-line/test.py +++ b/testsuite/tests/N429-020-loop-on-line/test.py @@ -3,8 +3,5 @@ from SCOV.map import MapChecker from SUITE.tutils import thistest -MapChecker( - ['main.c'], - alis=[os.path.join('obj', 'main.c.gli')] -).run() +MapChecker(["main.c"], alis=[os.path.join("obj", "main.c.gli")]).run() thistest.result() diff --git a/testsuite/tests/N430-005-c-static-inline/supported/test.py b/testsuite/tests/N430-005-c-static-inline/supported/test.py index 8bede2117..2f452a6da 100644 --- a/testsuite/tests/N430-005-c-static-inline/supported/test.py +++ b/testsuite/tests/N430-005-c-static-inline/supported/test.py @@ -7,7 +7,7 @@ TestCase( # Note that when C support for GNATcoverage will be ready, this flag # should be automatically enabled with -fdump-scos. - extracargs='-no-integrated-cpp', - category=cat + extracargs="-no-integrated-cpp", + category=cat, ).run() thistest.result() diff --git a/testsuite/tests/N430-005-c-static-inline/unsupported/test.py b/testsuite/tests/N430-005-c-static-inline/unsupported/test.py index 7be3ccdef..6afa40593 100644 --- a/testsuite/tests/N430-005-c-static-inline/unsupported/test.py +++ b/testsuite/tests/N430-005-c-static-inline/unsupported/test.py @@ -11,20 +11,20 @@ from SUITE.tutils import gprfor -wd = Wdir(subdir='tmp_') +wd = Wdir(subdir="tmp_") build_run_and_coverage( gprsw=GPRswitches( root_project=gprfor( - mains=['test_foo.c'], - srcdirs=os.path.join('..', 'src'), - langs=['C'], + mains=["test_foo.c"], + srcdirs=os.path.join("..", "src"), + langs=["C"], ), - units=['foo.c'], + units=["foo.c"], ), - covlevel='stmt', - mains=['test_foo'], - extra_coverage_args=['-axcov'], + covlevel="stmt", + mains=["test_foo"], + extra_coverage_args=["-axcov"], tolerate_instrument_messages="unexpected SCO overlapping", ) @@ -35,23 +35,25 @@ # different warnings. Note that the instrumentation warning is the most # precise. -if thistest.options.trace_mode == 'src': - output_string = 'gnatcov instrument output' - output_file = 'instrument.log' - expected_output = ('!!! foo.h:1:1: unexpected SCO overlapping with SCO #1: ' - 'STATEMENT at foo.h:1:1-13, discarding overlapping SCO\n' - '!!! foo.h:2:1: unexpected SCO overlapping with SCO #2: ' - 'STATEMENT at foo.h:2:1-21, discarding overlapping SCO') +if thistest.options.trace_mode == "src": + output_string = "gnatcov instrument output" + output_file = "instrument.log" + expected_output = ( + "!!! foo.h:1:1: unexpected SCO overlapping with SCO #1: " + "STATEMENT at foo.h:1:1-13, discarding overlapping SCO\n" + "!!! foo.h:2:1: unexpected SCO overlapping with SCO #2: " + "STATEMENT at foo.h:2:1-21, discarding overlapping SCO" + ) else: - output_string = 'gnatcov coverage output' - output_file = 'coverage.log' - expected_output = ('!!! foo.h:2:8: unexpected SCO overlapping with SCO #2: ' - 'STATEMENT at foo.h:2:8-20, discarding overlapping SCO') + output_string = "gnatcov coverage output" + output_file = "coverage.log" + expected_output = ( + "!!! foo.h:2:8: unexpected SCO overlapping with SCO #2: " + "STATEMENT at foo.h:2:8-20, discarding overlapping SCO" + ) thistest.fail_if_no_match( - output_string, - expected_output, - contents_of(output_file) + output_string, expected_output, contents_of(output_file) ) thistest.result() diff --git a/testsuite/tests/N505-008-c99-main-return/test.py b/testsuite/tests/N505-008-c99-main-return/test.py index 00903c8b1..b6519cc2b 100644 --- a/testsuite/tests/N505-008-c99-main-return/test.py +++ b/testsuite/tests/N505-008-c99-main-return/test.py @@ -3,5 +3,5 @@ from SUITE.context import thistest -TestCase(category=CAT.stmt, extracargs='-std=c99').run() +TestCase(category=CAT.stmt, extracargs="-std=c99").run() thistest.result() diff --git a/testsuite/tests/N506-014-crash-on-padding-nop/test.py b/testsuite/tests/N506-014-crash-on-padding-nop/test.py index de3ab802f..247e9585a 100644 --- a/testsuite/tests/N506-014-crash-on-padding-nop/test.py +++ b/testsuite/tests/N506-014-crash-on-padding-nop/test.py @@ -4,7 +4,7 @@ TestCase( - extracargs=['-no-integrated-cpp', '-falign-functions=32'], - category=CAT.decision + extracargs=["-no-integrated-cpp", "-falign-functions=32"], + category=CAT.decision, ).run() thistest.result() diff --git a/testsuite/tests/N610-006-library/test.py b/testsuite/tests/N610-006-library/test.py index d44280cfc..59cc4dc9e 100644 --- a/testsuite/tests/N610-006-library/test.py +++ b/testsuite/tests/N610-006-library/test.py @@ -5,70 +5,80 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor, thistest, xcov -Wdir('tmp_') +Wdir("tmp_") # We have a library with two units and a test exercising only one # of them. Check that gnatcov reports the untested stmts as uncovered # and emits an explicit notice of absence of object code on stderr # with --verbose. -prj = gprfor(['test_inc.adb'], - srcdirs=['..'], - objdir='obj', - deps=['../libops']) +prj = gprfor( + ["test_inc.adb"], srcdirs=[".."], objdir="obj", deps=["../libops"] +) -xcov_args = build_and_run(gprsw=GPRswitches(root_project=prj), - covlevel='stmt', - mains=['test_inc'], - extra_coverage_args=[]) +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["test_inc"], + extra_coverage_args=[], +) def trycov(verbose, annotate): - # last argument of xcov_args it the trace_file name # Note that coverage collection is on the library, not on # the test project given to build_and_run base_cov_command = ( - 'coverage --level=stmt --annotate=%s -P../libops.gpr %s' - % (annotate, xcov_args[-1])) + "coverage --level=stmt --annotate=%s -P../libops.gpr %s" + % (annotate, xcov_args[-1]) + ) cov_command = base_cov_command if verbose: - cov_command += ' --verbose' + cov_command += " --verbose" - if annotate != 'report': - cov_command += ' --source-search=libops --output-dir=.' + if annotate != "report": + cov_command += " --source-search=libops --output-dir=." p = xcov(cov_command) - nocode_notified = re.search(pattern='no object code for mult.ali', - string=p.out) + nocode_notified = re.search( + pattern="no object code for mult.ali", string=p.out + ) - bin_mode = thistest.options.trace_mode == 'bin' + bin_mode = thistest.options.trace_mode == "bin" if bin_mode and verbose and not nocode_notified: - thistest.failed('missing notice of absence of object code,' - ' verbose=%s, annotate=%s' % (verbose, annotate)) + thistest.failed( + "missing notice of absence of object code," + " verbose=%s, annotate=%s" % (verbose, annotate) + ) if bin_mode and nocode_notified and not verbose: - thistest.failed('unexpected notice of absence of object code,' - ' verbose=%s, annotate=%s' % (verbose, annotate)) + thistest.failed( + "unexpected notice of absence of object code," + " verbose=%s, annotate=%s" % (verbose, annotate) + ) - if annotate == 'report': + if annotate == "report": thistest.fail_if( - not re.search(pattern='mult.adb.*: statement not executed', - string=p.out), - 'missing expected stmt violation for mult.adb in report') + not re.search( + pattern="mult.adb.*: statement not executed", string=p.out + ), + "missing expected stmt violation for mult.adb in report", + ) - if annotate == 'xcov': + if annotate == "xcov": thistest.fail_if( - not re.search(pattern='[0-9]+ -:', - string=contents_of('mult.adb.xcov')), - 'missing expected l- in mult.adb.xcov') + not re.search( + pattern="[0-9]+ -:", string=contents_of("mult.adb.xcov") + ), + "missing expected l- in mult.adb.xcov", + ) for v in (True, False): - for a in ('report', 'xcov'): + for a in ("report", "xcov"): trycov(verbose=v, annotate=a) thistest.result() diff --git a/testsuite/tests/N630-009-forward_p_x/test.py b/testsuite/tests/N630-009-forward_p_x/test.py index bf2ae976e..967b17228 100644 --- a/testsuite/tests/N630-009-forward_p_x/test.py +++ b/testsuite/tests/N630-009-forward_p_x/test.py @@ -8,25 +8,26 @@ # Work in a subdirectory -wd = Wdir(subdir='tmp_') +wd = Wdir(subdir="tmp_") # Build a program expected to run fine for our current target -gpr = gprfor(mains=['foo.adb'], srcdirs=['..']) +gpr = gprfor(mains=["foo.adb"], srcdirs=[".."]) gprbuild(project=gpr) -program_path = exepath_to('foo') +program_path = exepath_to("foo") # Pass a correct -P and fake -X options together with -v. Check that the -P # and -X options are found in the gnatemu command executed, as displayed by # -v. Beware that the -P option may be passed down in various ways, e.g. # -P gen.gpr or -Pgen.gpr, regardless of how we pass it to gnatcov run. -xargs = ['-XFOO=foo1', '-Xbar=bar1'] -xcovargs = ['-P', gpr, '-v', program_path] + xargs +xargs = ["-XFOO=foo1", "-Xbar=bar1"] +xcovargs = ["-P", gpr, "-v", program_path] + xargs p = xrun(xcovargs) for arg in xargs + ["'-P' '*%s'" % re.escape(gpr)]: thistest.fail_if( - not re.search('gnatemu.*%s' % arg, p.out), - 'couldn\'t find "%s" on the gnatemu command line out of %s' % - (arg, ' '.join(xcovargs))) + not re.search("gnatemu.*%s" % arg, p.out), + 'couldn\'t find "%s" on the gnatemu command line out of %s' + % (arg, " ".join(xcovargs)), + ) thistest.result() diff --git a/testsuite/tests/NA29-019-unit-filters-for-C/test.py b/testsuite/tests/NA29-019-unit-filters-for-C/test.py index 2a688fc89..0b8761981 100644 --- a/testsuite/tests/NA29-019-unit-filters-for-C/test.py +++ b/testsuite/tests/NA29-019-unit-filters-for-C/test.py @@ -22,29 +22,35 @@ from SUITE.tutils import gprfor, xcov -Wdir('tmp_') +Wdir("tmp_") def gengpr(attributes, prjname): return gprfor( mains=["test_abs.c"], prjid=prjname, - srcdirs='..', - objdir='obj', - exedir='.', - langs=['C'], + srcdirs="..", + objdir="obj", + exedir=".", + langs=["C"], extra=""" package Coverage is {} end Coverage; - """.format('\n'.join(attributes)) + """.format( + "\n".join(attributes) + ), ) # Build and run first -gprname = gengpr(attributes=[], prjname='build') -xcov_args = build_and_run(GPRswitches(gprname), "stmt", ["test_abs"], - extra_coverage_args=["--annotate=xcov"]) +gprname = gengpr(attributes=[], prjname="build") +xcov_args = build_and_run( + GPRswitches(gprname), + "stmt", + ["test_abs"], + extra_coverage_args=["--annotate=xcov"], +) # Now analyse with different unit selection schemes ... Assign a different # directory to each attempt. Expect reports for the functional unit(s) only. @@ -54,19 +60,22 @@ def trycov(attributes, outdir): # Create dedicated dir and analyse with the specific attributes: mkdir(outdir) gprname = gengpr(attributes=attributes, prjname=outdir) - xcov('%s -P%s --output-dir=%s' % (' '.join(xcov_args), gprname, outdir)) + xcov("%s -P%s --output-dir=%s" % (" ".join(xcov_args), gprname, outdir)) # Check that we have no report for the harness unit and that we have # a report which looks correct for the functional unit: - harness_reports = ls('%s/test*.xcov' % outdir) - thistest.fail_if(harness_reports, - 'unexpected coverage reports for harness units: %s' - % str(harness_reports)) + harness_reports = ls("%s/test*.xcov" % outdir) + thistest.fail_if( + harness_reports, + "unexpected coverage reports for harness units: %s" + % str(harness_reports), + ) - all_reports = ls('%s/*.xcov' % outdir) + all_reports = ls("%s/*.xcov" % outdir) thistest.fail_if( not all_reports, - 'missing expected coverage reports for !harness units in %s' % outdir) + "missing expected coverage reports for !harness units in %s" % outdir, + ) # We expect to find a mix of coverage notes in each expected # report: @@ -74,18 +83,20 @@ def trycov(attributes, outdir): def check_report(r): contents = contents_of(r) - for note in ('+', '-', '.'): - notes = re.findall(r'\d+ \%c:' % note, contents) + for note in ("+", "-", "."): + notes = re.findall(r"\d+ \%c:" % note, contents) thistest.fail_if( - not notes, "missing expected '%c' notes in %s" % (note, r)) + not notes, "missing expected '%c' notes in %s" % (note, r) + ) for r in all_reports: check_report(r) -trycov(attributes=['for excluded_units use ("test_abs.c");'], - outdir='exclude_harness') -trycov(attributes=['for units use ("abs.c");'], - outdir='include_functional') +trycov( + attributes=['for excluded_units use ("test_abs.c");'], + outdir="exclude_harness", +) +trycov(attributes=['for units use ("abs.c");'], outdir="include_functional") thistest.result() diff --git a/testsuite/tests/NC02-014-gpr-X/test.py b/testsuite/tests/NC02-014-gpr-X/test.py index 1a976abbd..298083f18 100644 --- a/testsuite/tests/NC02-014-gpr-X/test.py +++ b/testsuite/tests/NC02-014-gpr-X/test.py @@ -25,26 +25,29 @@ end Coverage; """ -report_types = ['f', 'g'] +report_types = ["f", "g"] def output_dir(what): - return 'output-{}'.format(what) + return "output-{}".format(what) # Build and run once, in a dedicated temp directory -wd = Wdir('tmp_') +wd = Wdir("tmp_") base_args = build_and_run( - gprsw=GPRswitches(root_project=gprfor(mains=['main.adb'], - srcdirs=['..'], extra=extra)), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov']) + gprsw=GPRswitches( + root_project=gprfor(mains=["main.adb"], srcdirs=[".."], extra=extra) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) # Now perform analysis variants + def trycov(this_report, where): # Clear output directories, to notice what is created that should not for what in report_types: @@ -55,21 +58,22 @@ def trycov(this_report, where): # THIS_REPORT conveys what value to pass as -XTHIS_REPORT. # WHERE conveys whether -X should be placed 'before' or 'after' -P. args = list(base_args) - arg_i = len(args) if where == 'after' else 1 - args.insert(arg_i, '-XTHIS_REPORT={}'.format(this_report)) + arg_i = len(args) if where == "after" else 1 + args.insert(arg_i, "-XTHIS_REPORT={}".format(this_report)) xcov(args) this_output_dir = output_dir(this_report) - expected_report = os.path.join(this_output_dir, 'main.adb.xcov') - reports = ls(os.path.join(output_dir('*'), '*.xcov')) + expected_report = os.path.join(this_output_dir, "main.adb.xcov") + reports = ls(os.path.join(output_dir("*"), "*.xcov")) thistest.fail_if( len(reports) > 1 or expected_report not in reports, - 'expected a single {}, got {}'.format(expected_report, reports)) + "expected a single {}, got {}".format(expected_report, reports), + ) for what in report_types: - for where in ('before', 'after'): + for where in ("before", "after"): trycov(this_report=what, where=where) thistest.result() diff --git a/testsuite/tests/NC08-027-target_attr/test.py b/testsuite/tests/NC08-027-target_attr/test.py index bd86b8224..9f471ee43 100644 --- a/testsuite/tests/NC08-027-target_attr/test.py +++ b/testsuite/tests/NC08-027-target_attr/test.py @@ -11,49 +11,54 @@ # Work in a subdirectory -wd = Wdir(subdir='tmp_') +wd = Wdir(subdir="tmp_") # Build a program expected to run fine for our current target -gpr = gprfor(mains=['foo.adb'], srcdirs=['..']) +gpr = gprfor(mains=["foo.adb"], srcdirs=[".."]) gprbuild(project=gpr) -program_path = exepath_to('foo') +program_path = exepath_to("foo") # Check that a Target attribute in a project file is accounted for # by gnatcov run. # # Try to run with a project file containing a fake Target value. # Expect an error complaining about an unknown target. -gpr = gprfor(mains=[], srcdirs=['..'], - extra='for Target use "foo-bar";\n') -runargs = ['-P', gpr, program_path] -p = xrun(runargs, register_failure=False, - auto_config_args=False, - auto_target_args=False) +gpr = gprfor(mains=[], srcdirs=[".."], extra='for Target use "foo-bar";\n') +runargs = ["-P", gpr, program_path] +p = xrun( + runargs, + register_failure=False, + auto_config_args=False, + auto_target_args=False, +) if thistest.bits() == 32: thistest.fail_if( - not re.search('No builtin or GNATemulator execution driver found for' - ' target: foo-bar', p.out), + not re.search( + "No builtin or GNATemulator execution driver found for" + " target: foo-bar", + p.out, + ), "couldn't find indication of unknown target error in gnatcov" - " run output:\n {}".format(indent(p.out))) + " run output:\n {}".format(indent(p.out)), + ) else: # thistest.bits() == 64 # In that case, as gnatcov32 is picked by default if the given target # is invalid, it will fail when loading the executable file. thistest.fail_if( - not re.search('unsupported ELF class', p.out), + not re.search("unsupported ELF class", p.out), "couldn't find indication of ELF class unsupported error in gnatcov" - " run output:\n {}".format(indent(p.out))) + " run output:\n {}".format(indent(p.out)), + ) # Check that an explicit --target on the command line overrides the # Target project file attribute. # # Same arguments as in the previous test, plus correct --target and --RTS # arguments. This one should succeed. -xrun(runargs, - auto_config_args=False, - auto_target_args=True) +xrun(runargs, auto_config_args=False, auto_target_args=True) thistest.result() diff --git a/testsuite/tests/O212-062-show-condition-vectors/test.py b/testsuite/tests/O212-062-show-condition-vectors/test.py index b2ddd7727..338277d6a 100644 --- a/testsuite/tests/O212-062-show-condition-vectors/test.py +++ b/testsuite/tests/O212-062-show-condition-vectors/test.py @@ -10,15 +10,15 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Generate a project, instrument it if necessary and run it, -p = gprfor(mains=['main.adb'], srcdirs=['..']) +p = gprfor(mains=["main.adb"], srcdirs=[".."]) xcov_args_mcdc = build_and_run( gprsw=GPRswitches(root_project=p), - covlevel='stmt+mcdc+atcc', - mains=['main'], - extra_coverage_args=[] + covlevel="stmt+mcdc+atcc", + mains=["main"], + extra_coverage_args=[], ) @@ -35,10 +35,10 @@ def run_and_check(args, output_file, expected_file): thistest.fail_if_no_match( '"gnatcov coverage" output ({})'.format(output_file), - contents_of(expected_file).replace('\r\n', '\n'), - + contents_of(expected_file).replace("\r\n", "\n"), # Canonicalize to Unix-style line endings to have cross-platform checks - contents_of(output_file).replace('\r\n', '\n')) + contents_of(output_file).replace("\r\n", "\n"), + ) # For the following test, a different behavior is expected for source and bin @@ -48,27 +48,34 @@ def run_and_check(args, output_file, expected_file): # Check that mcdc/atcc vectors are displayed under the corresponding # condition violations, and show the conditions indexes in violation messages. -mcdc_atcc_ref_file = ("../bin-mcdc-atcc.expected" - if thistest.options.trace_mode == "bin" - else "../src-mcdc-atcc.expected") +mcdc_atcc_ref_file = ( + "../bin-mcdc-atcc.expected" + if thistest.options.trace_mode == "bin" + else "../src-mcdc-atcc.expected" +) -run_and_check(xcov_args_mcdc + ['-areport', '--show-condition-vectors'], - 'report-stdout-mcdc-atcc.txt', - mcdc_atcc_ref_file) +run_and_check( + xcov_args_mcdc + ["-areport", "--show-condition-vectors"], + "report-stdout-mcdc-atcc.txt", + mcdc_atcc_ref_file, +) # Check that evaluation vectors not part of any pair are displayed below the # other vectors. -ucmcdc_atcc_ref_file = ("../bin-ucmcdc-atcc.expected" - if thistest.options.trace_mode == "bin" - else "../src-ucmcdc-atcc.expected") +ucmcdc_atcc_ref_file = ( + "../bin-ucmcdc-atcc.expected" + if thistest.options.trace_mode == "bin" + else "../src-ucmcdc-atcc.expected" +) -run_and_check(xcov_args_mcdc + ['--level=stmt+uc_mcdc+atcc', - '-areport', - '--show-condition-vectors'], - 'report-stdout-ucmcdc-atcc.txt', - ucmcdc_atcc_ref_file) +run_and_check( + xcov_args_mcdc + + ["--level=stmt+uc_mcdc+atcc", "-areport", "--show-condition-vectors"], + "report-stdout-ucmcdc-atcc.txt", + ucmcdc_atcc_ref_file, +) thistest.result() diff --git a/testsuite/tests/O212-062-xml/test.py b/testsuite/tests/O212-062-xml/test.py index 0b9536db6..be5db73a3 100644 --- a/testsuite/tests/O212-062-xml/test.py +++ b/testsuite/tests/O212-062-xml/test.py @@ -9,18 +9,19 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor, thistest -wd = Wdir('tmp_') +wd = Wdir("tmp_") -gpr = gprfor(['main.adb'], srcdirs='..') +gpr = gprfor(["main.adb"], srcdirs="..") xcov_args = build_run_and_coverage( gprsw=GPRswitches(root_project=gpr), - covlevel='stmt+mcdc+atcc', - mains=['main'], - extra_coverage_args=['-axml']) + covlevel="stmt+mcdc+atcc", + mains=["main"], + extra_coverage_args=["-axml"], +) thistest.fail_if_diff( os.path.join("..", "src-traces-index.xml.expected"), - os.path.join("obj", "index.xml") + os.path.join("obj", "index.xml"), ) thistest.result() diff --git a/testsuite/tests/O302-015-src-path-in-project/test.py b/testsuite/tests/O302-015-src-path-in-project/test.py index 8c7096dc0..042f5d0aa 100644 --- a/testsuite/tests/O302-015-src-path-in-project/test.py +++ b/testsuite/tests/O302-015-src-path-in-project/test.py @@ -15,17 +15,18 @@ from SUITE.tutils import xcov -bin_traces = thistest.options.trace_mode == 'bin' +bin_traces = thistest.options.trace_mode == "bin" # Precompute absolute paths before going to the temporary directory -prj_path = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') -pkg_ads_report_path = os.path.join(obj_dir, 'pkg.ads.xcov') -scos = [os.path.join(obj_dir, name) - for name in ('pkg', 'pkg-hw', 'pkg-io', 'main')] +prj_path = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") +pkg_ads_report_path = os.path.join(obj_dir, "pkg.ads.xcov") +scos = [ + os.path.join(obj_dir, name) for name in ("pkg", "pkg-hw", "pkg-io", "main") +] -wd = Wdir(subdir='tmp_') +wd = Wdir(subdir="tmp_") # Build the project and produce a trace for its main. This is using MCDC + SCOs @@ -33,37 +34,48 @@ # trace mode). xcov_args = build_and_run( gprsw=GPRswitches(root_project=prj_path), - covlevel='stmt+mcdc', - mains=['main'], + covlevel="stmt+mcdc", + mains=["main"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, scos=scos, - extra_coverage_args=['--annotate=xcov']) + extra_coverage_args=["--annotate=xcov"], +) trace_file = xcov_args[-1] # Now check that analysis works one way or the other: with SCOs and with -P in # binary trace mode, and with -P only in other modes. + def try_coverage(xcov_args, use_project): rm(pkg_ads_report_path) if not use_project: - xcov_args = xcov_args + ['--output-dir={}'.format(obj_dir)] + xcov_args = xcov_args + ["--output-dir={}".format(obj_dir)] p = xcov(xcov_args) thistest.fail_if( - p.out, - '"gnatcov coverage" output is not empty:\n--\n{}'.format(p.out)) + p.out, '"gnatcov coverage" output is not empty:\n--\n{}'.format(p.out) + ) thistest.fail_if( not os.path.isfile(pkg_ads_report_path), - '"gnatcov coverage" could not produce a report file for pkg.ads') + '"gnatcov coverage" could not produce a report file for pkg.ads', + ) try_coverage(xcov_args, use_project=False) if bin_traces: - try_coverage(['coverage', '-P', prj_path, '--level=stmt+mcdc', - '--annotate=xcov', trace_file], - use_project=True) + try_coverage( + [ + "coverage", + "-P", + prj_path, + "--level=stmt+mcdc", + "--annotate=xcov", + trace_file, + ], + use_project=True, + ) thistest.result() diff --git a/testsuite/tests/O529-021-wrong-elf-class/test.py b/testsuite/tests/O529-021-wrong-elf-class/test.py index 1103833ee..286d5b8de 100644 --- a/testsuite/tests/O529-021-wrong-elf-class/test.py +++ b/testsuite/tests/O529-021-wrong-elf-class/test.py @@ -8,16 +8,19 @@ # x86_64-linux: # $ gcc -o code-32.o -m32 -c code.s # $ gcc -o code-64.o -m64 -c code.s -bits = '32' if '64bits' in thistest.options.tags else '64' -expected_pattern = (r'.*gnatcov.*: code-{bits}\.o:' - r' unsupported ELF class \({bits}bit\)'.format(bits=bits)) +bits = "32" if "64bits" in thistest.options.tags else "64" +expected_pattern = ( + r".*gnatcov.*: code-{bits}\.o:" + r" unsupported ELF class \({bits}bit\)".format(bits=bits) +) -p = xcov(['disassemble', 'code-{}.o'.format(bits)], register_failure=False) +p = xcov(["disassemble", "code-{}.o".format(bits)], register_failure=False) got_output = p.out.strip() thistest.fail_if( not re.match(expected_pattern, got_output), - 'Could not match:\n' - ' {}\n' - 'against output:\n' - ' {}'.format(expected_pattern, got_output)) + "Could not match:\n" + " {}\n" + "against output:\n" + " {}".format(expected_pattern, got_output), +) thistest.result() diff --git a/testsuite/tests/O916-035-padding-cons/test.py b/testsuite/tests/O916-035-padding-cons/test.py index a7598d3d7..035b11aab 100644 --- a/testsuite/tests/O916-035-padding-cons/test.py +++ b/testsuite/tests/O916-035-padding-cons/test.py @@ -3,8 +3,14 @@ from SUITE.control import target_info from SUITE.context import env, thistest from SUITE.cutils import Wdir, contents_of, match, text_to_file -from SUITE.tutils import (exepath_to, gprfor, gprbuild, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprfor, + gprbuild, + tracename_for, + xcov, + xrun, +) # This test checks that GNATcoverage properly matches padding instructions... @@ -45,97 +51,120 @@ insns_x86 = [ # 1-byte padding - (True, 'nop'), - + (True, "nop"), # 2-bytes padding - (True, 'xchg %ax, %ax'), - (False, 'xchg %ax, %bx'), - (True, '# 66 NOP\n' - '.byte 0x66, 0x90'), - + (True, "xchg %ax, %ax"), + (False, "xchg %ax, %bx"), + (True, "# 66 NOP\n" ".byte 0x66, 0x90"), # 3-bytes padding - (True, 'lea 0x0(%eax),%eax'), - (True, 'lea 0x0(%esi),%esi'), - (False, 'lea 0x0(%eax),%esi'), - (False, 'lea 0x1(%eax),%eax'), - (False, 'lea 0x0(%eax,%eax),%eax'), - (False, 'lea 0x0(%eax,%eax,2),%eax'), - (True, 'lea 0x0(%eax,2),%eax'), - (True, '# NOP DWORD ptr [EAX]\n' - '.byte 0x0F, 0x1F, 0x00'), - + (True, "lea 0x0(%eax),%eax"), + (True, "lea 0x0(%esi),%esi"), + (False, "lea 0x0(%eax),%esi"), + (False, "lea 0x1(%eax),%eax"), + (False, "lea 0x0(%eax,%eax),%eax"), + (False, "lea 0x0(%eax,%eax,2),%eax"), + (True, "lea 0x0(%eax,2),%eax"), + (True, "# NOP DWORD ptr [EAX]\n" ".byte 0x0F, 0x1F, 0x00"), # 4-bytes padding - (True, '# lea 0x0(%esi,%eiz,1),%esi\n' - '.byte 0x8d, 0x74, 0x26, 0x00'), - (True, '# lea 0x0(%esi,%eiz,2),%esi\n' - '.byte 0x8d, 0x74, 0x66, 0x00'), - (False, '# lea 0x0(%ebp,%eiz,1),%esi\n' - '.byte 0x8d, 0x74, 0x25, 0x00'), - (False, '# lea 0x0(%esi,%esi,1),%esi\n' - '.byte 0x8d, 0x74, 0x36, 0x00'), - (True, '# NOP DWORD ptr [EAX + 00H]\n' - '.byte 0x0F, 0x1F, 0x40, 0x00'), - + (True, "# lea 0x0(%esi,%eiz,1),%esi\n" ".byte 0x8d, 0x74, 0x26, 0x00"), + (True, "# lea 0x0(%esi,%eiz,2),%esi\n" ".byte 0x8d, 0x74, 0x66, 0x00"), + (False, "# lea 0x0(%ebp,%eiz,1),%esi\n" ".byte 0x8d, 0x74, 0x25, 0x00"), + (False, "# lea 0x0(%esi,%esi,1),%esi\n" ".byte 0x8d, 0x74, 0x36, 0x00"), + (True, "# NOP DWORD ptr [EAX + 00H]\n" ".byte 0x0F, 0x1F, 0x40, 0x00"), # 5-bytes padding - (True, '# NOP DWORD ptr [EAX + EAX*1 + 00H]\n' - '.byte 0x0F, 0x1F, 0x44, 0x00, 0x00'), - + ( + True, + "# NOP DWORD ptr [EAX + EAX*1 + 00H]\n" + ".byte 0x0F, 0x1F, 0x44, 0x00, 0x00", + ), # 6-bytes padding - (True, '# lea 0x0(%esi),%esi\n' - '.byte 0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00'), - (False, '# lea 0x0(%eax),%esi\n' - '.byte 0x8d, 0xb0, 0x00, 0x00, 0x00, 0x00'), - (True, '# 66 NOP DWORD ptr [EAX + EAX*1 + 00H]\n' - '.byte 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00'), - + ( + True, + "# lea 0x0(%esi),%esi\n" ".byte 0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00", + ), + ( + False, + "# lea 0x0(%eax),%esi\n" ".byte 0x8d, 0xb0, 0x00, 0x00, 0x00, 0x00", + ), + ( + True, + "# 66 NOP DWORD ptr [EAX + EAX*1 + 00H]\n" + ".byte 0x66, 0x0F, 0x1F, 0x44, 0x00, 0x00", + ), # 7-bytes padding - (True, '# lea 0x0(%esi,%eiz,1),%esi\n' - '.byte 0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, 0x00'), - (False, '# lea 0x0(%ebp,%eiz,1),%esi\n' - '.byte 0x8d, 0xb4, 0x25, 0x00, 0x00, 0x00, 0x00'), - (False, '# lea 0x0(,%eiz,1),%esi\n' - '.byte 0x8d, 0x34, 0x25, 0x00, 0x00, 0x00, 0x00'), - (True, '# lea 0x0(,%esi,1),%esi\n' - '.byte 0x8d, 0x34, 0x35, 0x00, 0x00, 0x00, 0x00'), - (False, '# lea 0x0(,%edi,1),%esi\n' - '.byte 0x8d, 0x34, 0x3d, 0x00, 0x00, 0x00, 0x00'), - (False, '# lea 0x0(%eax,%eax,1),%esi\n' - '.byte 0x8d, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00'), - (True, '# NOP DWORD ptr [EAX + 00000000H]\n' - '.byte 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00'), - + ( + True, + "# lea 0x0(%esi,%eiz,1),%esi\n" + ".byte 0x8d, 0xb4, 0x26, 0x00, 0x00, 0x00, 0x00", + ), + ( + False, + "# lea 0x0(%ebp,%eiz,1),%esi\n" + ".byte 0x8d, 0xb4, 0x25, 0x00, 0x00, 0x00, 0x00", + ), + ( + False, + "# lea 0x0(,%eiz,1),%esi\n" + ".byte 0x8d, 0x34, 0x25, 0x00, 0x00, 0x00, 0x00", + ), + ( + True, + "# lea 0x0(,%esi,1),%esi\n" + ".byte 0x8d, 0x34, 0x35, 0x00, 0x00, 0x00, 0x00", + ), + ( + False, + "# lea 0x0(,%edi,1),%esi\n" + ".byte 0x8d, 0x34, 0x3d, 0x00, 0x00, 0x00, 0x00", + ), + ( + False, + "# lea 0x0(%eax,%eax,1),%esi\n" + ".byte 0x8d, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x00", + ), + ( + True, + "# NOP DWORD ptr [EAX + 00000000H]\n" + ".byte 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00", + ), # 8-bytes padding - (True, '# NOP DWORD ptr [EAX + EAX*1 + 00000000H]\n' - '.byte 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00'), - + ( + True, + "# NOP DWORD ptr [EAX + EAX*1 + 00000000H]\n" + ".byte 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00", + ), # 9-bytes padding - (True, '# 66 NOP DWORD ptr [EAX + EAX*1 + 00000000H]\n' - '.byte 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00'), + ( + True, + "# 66 NOP DWORD ptr [EAX + EAX*1 + 00000000H]\n" + ".byte 0x66, 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00", + ), ] test_database = { - 'x86-linux': insns_x86, - 'x86-windows': insns_x86, + "x86-linux": insns_x86, + "x86-windows": insns_x86, } def run_test(platform, insns): - asm_src = os.path.abspath('foo-{}.s'.format(platform)) - Wdir('tmp_') + asm_src = os.path.abspath("foo-{}.s".format(platform)) + Wdir("tmp_") def build_material(name, padding_insn=None): - tmp = Wdir('build-{}'.format(name)) + tmp = Wdir("build-{}".format(name)) - asm_code = contents_of(asm_src).format(padding=padding_insn or '') - asm_filename = text_to_file(asm_code, 'foo.s') - project = gprfor([asm_filename], srcdirs=['.'], objdir='.', - langs=['Asm']) + asm_code = contents_of(asm_src).format(padding=padding_insn or "") + asm_filename = text_to_file(asm_code, "foo.s") + project = gprfor( + [asm_filename], srcdirs=["."], objdir=".", langs=["Asm"] + ) # The assembly files already contain debug information: ask the # assembler not to produce it itself. - gprbuild(project, extracargs='-g0') - xrun(exepath_to('foo')) - trace_name = os.path.abspath(tracename_for('foo')) + gprbuild(project, extracargs="-g0") + xrun(exepath_to("foo")) + trace_name = os.path.abspath(tracename_for("foo")) tmp.to_homedir() return trace_name @@ -143,31 +172,36 @@ def build_material(name, padding_insn=None): # First, build all test material: build programs (reference and # with-padding programs) and generate traces for them. - trace_ref = build_material('ref') + trace_ref = build_material("ref") traces = [] for i, (_, insn) in enumerate(insns): traces.append(build_material(str(i), insn)) # Then try to consolidate each with-padding program with the reference one - routine = target_info().to_platform_specific_symbol('foo') + routine = target_info().to_platform_specific_symbol("foo") for i, ((is_padding, insn), trace_file) in enumerate(zip(insns, traces)): - args = ['coverage', '--level=insn', '--annotate=asm', - '--routines={}'.format(routine), - trace_ref, trace_file] - out_file = 'object-cons-{}.txt'.format(i) + args = [ + "coverage", + "--level=insn", + "--annotate=asm", + "--routines={}".format(routine), + trace_ref, + trace_file, + ] + out_file = "object-cons-{}.txt".format(i) p = xcov(args, out=out_file, register_failure=False) - insn_label = insn.split('\n')[0] + insn_label = insn.split("\n")[0] consolidation_failed = p.status != 0 - command = 'gnatcov {}'.format(' '.join(args)) + command = "gnatcov {}".format(" ".join(args)) # First, if consolidation failed, make sure it is because of symbol # matching. thistest.fail_if( - consolidation_failed and not - match('TRACES_NAMES.CONSOLIDATION_ERROR', out_file), + consolidation_failed + and not match("TRACES_NAMES.CONSOLIDATION_ERROR", out_file), '[{}] "gnatcov coverage" failed in an unexpected way\n' - ' Command was: {}'.format(i, command) + " Command was: {}".format(i, command), ) # Now, check if GNATcoverage correctly matched inserted code as padding @@ -176,13 +210,13 @@ def build_material(name, padding_insn=None): thistest.fail_if( consolidation_failed, '[{}] "{}" was not considered as padding (it is)\n' - ' Command was: {}'.format(i, insn_label, command) + " Command was: {}".format(i, insn_label, command), ) else: thistest.fail_if( not consolidation_failed, '[{}] "{}" was considered as padding (it is not)\n' - ' Command was: {}'.format(i, insn_label, command) + " Command was: {}".format(i, insn_label, command), ) @@ -190,7 +224,7 @@ def build_material(name, padding_insn=None): try: insns = test_database[platform] except KeyError: - thistest.comment('Nothing to test for {}'.format(platform)) + thistest.comment("Nothing to test for {}".format(platform)) else: run_test(platform, insns) diff --git a/testsuite/tests/OA05-051-sharedobjs-opt/test.py b/testsuite/tests/OA05-051-sharedobjs-opt/test.py index f8f3ef595..b7b9468e5 100644 --- a/testsuite/tests/OA05-051-sharedobjs-opt/test.py +++ b/testsuite/tests/OA05-051-sharedobjs-opt/test.py @@ -6,43 +6,43 @@ from SUITE.tutils import exepath_to, gprbuild, gprfor, thistest, xrun -wdir = Wdir('tmp_') +wdir = Wdir("tmp_") -gprbuild(gprfor(['foo.adb'], srcdirs='..')) -exe = exepath_to('foo') +gprbuild(gprfor(["foo.adb"], srcdirs="..")) +exe = exepath_to("foo") for opt, err_msg in [ - ('none', None), - ('all', None), - ('foo.so', None), - ('foo.so bar.so', None), - - ('none all', '"none" and "all" cannot be used at the same time'), - ('all none', '"none" and "all" cannot be used at the same time'), - - ('none foo.so', 'cannot provide shared objects with "none"'), - ('foo.so none', 'cannot provide shared objects with "none"'), - - ('all foo.so', 'cannot provide shared objects with "all"'), - ('foo.so all', 'cannot provide shared objects with "all"'), + ("none", None), + ("all", None), + ("foo.so", None), + ("foo.so bar.so", None), + ("none all", '"none" and "all" cannot be used at the same time'), + ("all none", '"none" and "all" cannot be used at the same time'), + ("none foo.so", 'cannot provide shared objects with "none"'), + ("foo.so none", 'cannot provide shared objects with "none"'), + ("all foo.so", 'cannot provide shared objects with "all"'), + ("foo.so all", 'cannot provide shared objects with "all"'), ]: args = [] for arg in opt.split(): - args.extend(['-L', arg]) + args.extend(["-L", arg]) args.append(exe) p = xrun(args, register_failure=err_msg is None) if err_msg: - pattern = r'.*gnatcov.*: --shared-object\|-L: {}'.format( - re.escape(err_msg)) + pattern = r".*gnatcov.*: --shared-object\|-L: {}".format( + re.escape(err_msg) + ) thistest.fail_if( p.status == 0, - '"{}" was expected to fail, but it did not'.format(' '.join(args))) + '"{}" was expected to fail, but it did not'.format(" ".join(args)), + ) thistest.fail_if( not re.match(pattern, p.out.strip()), - '\nError mesage:' - '\n{}' - '\nDoes not match the expected pattern:' - '\n{}'.format(indent(p.out), indent(pattern))) + "\nError mesage:" + "\n{}" + "\nDoes not match the expected pattern:" + "\n{}".format(indent(p.out), indent(pattern)), + ) thistest.result() diff --git a/testsuite/tests/OA05-051-sharedobjs/test.py b/testsuite/tests/OA05-051-sharedobjs/test.py index 72edc0eea..f79fb3eaf 100644 --- a/testsuite/tests/OA05-051-sharedobjs/test.py +++ b/testsuite/tests/OA05-051-sharedobjs/test.py @@ -17,29 +17,36 @@ from SUITE.tutils import gprbuild, thistest, xcov from SUITE.tracelib import ( - TraceEntry, TraceSpecial, TraceFile, TraceOp, TraceKind, - create_exec_infos, create_trace_header) + TraceEntry, + TraceSpecial, + TraceFile, + TraceOp, + TraceKind, + create_exec_infos, + create_trace_header, +) # Clean artifaacts from previous runs -if os.path.exists('tmp'): - rm('tmp', recursive=True) -mkdir('tmp') +if os.path.exists("tmp"): + rm("tmp", recursive=True) +mkdir("tmp") def in_tmp(*elts): - return os.path.join('tmp', *elts) + return os.path.join("tmp", *elts) # Build the program along with the shared libraries. Since we build with shared # libraries, set LIBRARY_TYPE accordingly so that the implict with of # gnatcov_rts_full works fine. -gprbuild('myprog', gargs=['-XLIBRARY_TYPE=relocatable']) -myprog_filename = in_tmp('bin', 'myprog') +gprbuild("myprog", gargs=["-XLIBRARY_TYPE=relocatable"]) +myprog_filename = in_tmp("bin", "myprog") # And now create a set of traces we'll use to test "gnatcov coverage" + class Symbol(object): def __init__(self, addr, size): self.addr = addr @@ -55,22 +62,18 @@ def last(self): def get_symbol(filename, symbol): - for line in subprocess.check_output( - ['nm', '-S', filename] - ).decode('utf-8').splitlines(): + for line in ( + subprocess.check_output(["nm", "-S", filename]) + .decode("utf-8") + .splitlines() + ): if line.endswith(symbol): addr, size, _ = line.split(None, 2) return Symbol(int(addr, 16), int(size, 16)) - raise ValueError('Could not find symbol {} in {}'.format( - symbol, filename - )) + raise ValueError("Could not find symbol {} in {}".format(symbol, filename)) -ELFHeader = struct.Struct( - '<16s' # e_ident - 'H' # e_type - 'H' # e_machine -) +ELFHeader = struct.Struct("<16s" "H" "H") # e_ident # e_type # e_machine EI_CLASS = 4 ELFCLASS32 = 1 ELFCLASS64 = 2 @@ -80,7 +83,7 @@ def get_symbol(filename, symbol): ELFDATA2MSB = 2 # Get architecture properties from the ELF we just built -with open(myprog_filename, 'rb') as f: +with open(myprog_filename, "rb") as f: hdr = ELFHeader.unpack(f.read(ELFHeader.size)) e_ident = hdr[0] e_type = hdr[1] @@ -88,34 +91,38 @@ def get_symbol(filename, symbol): bits = {ELFCLASS32: 32, ELFCLASS64: 64}[e_ident[EI_CLASS]] big_endian = e_ident[EI_DATA] == ELFDATA2MSB - machine = (((e_machine & 0xff) << 8) | (e_machine >> 8) - if big_endian else - e_machine) + machine = ( + ((e_machine & 0xFF) << 8) | (e_machine >> 8) + if big_endian + else e_machine + ) -so_load_addr = 0xccff0000 +so_load_addr = 0xCCFF0000 trace_file_info = create_exec_infos(myprog_filename) -libnames = ('mylib1', 'mylib2') +libnames = ("mylib1", "mylib2") libfiles = { - libname: in_tmp('lib', 'lib{}.so'.format(libname)) - for libname in libnames + libname: in_tmp("lib", "lib{}.so".format(libname)) for libname in libnames } syms = { - libname: get_symbol(libfile, '{}__f'.format(libname)) + libname: get_symbol(libfile, "{}__f".format(libname)) for libname, libfile in libfiles.items() } load_events = { libname: TraceEntry( - bits, so_load_addr, - TraceSpecial.LoadSharedObject, TraceOp.Special, - create_exec_infos(libfiles[libname], code_size=sym.last + 1) + bits, + so_load_addr, + TraceSpecial.LoadSharedObject, + TraceOp.Special, + create_exec_infos(libfiles[libname], code_size=sym.last + 1), ) for libname, sym in syms.items() } -unload_event = TraceEntry(bits, so_load_addr, TraceSpecial.UnloadSharedObject, - TraceOp.Special) +unload_event = TraceEntry( + bits, so_load_addr, TraceSpecial.UnloadSharedObject, TraceOp.Special +) def write_traces(trace_filename, executed_libs): @@ -124,88 +131,93 @@ def write_traces(trace_filename, executed_libs): entries.append(load_events[libname]) if libname in executed_libs: sym = syms[libname] - entries.append(TraceEntry(bits, so_load_addr + sym.addr, - sym.size, - TraceOp.Block)) + entries.append( + TraceEntry( + bits, so_load_addr + sym.addr, sym.size, TraceOp.Block + ) + ) entries.append(unload_event) tf = TraceFile( create_trace_header(TraceKind.Info, bits // 8, big_endian, machine), trace_file_info, create_trace_header(TraceKind.Flat, bits // 8, big_endian, machine), - entries + entries, ) - with open(trace_filename, 'wb') as f: + with open(trace_filename, "wb") as f: tf.write(f) for trace_filename, executed_libs in [ - ('myprog_0.trace', []), - ('myprog_1.trace', ['mylib1']), - ('myprog_2.trace', ['mylib2']), - ('myprog_12.trace', ['mylib1', 'mylib2']), + ("myprog_0.trace", []), + ("myprog_1.trace", ["mylib1"]), + ("myprog_2.trace", ["mylib2"]), + ("myprog_12.trace", ["mylib1", "mylib2"]), ]: write_traces(in_tmp(trace_filename), executed_libs) # Traces are ready: let's see how coverage goes! + def cov_report_summary(output_dir): summary = [] for cov_file in os.listdir(output_dir): cov_set = set() cov_filepath = os.path.join(output_dir, cov_file) - assert cov_file.endswith('.xcov') + assert cov_file.endswith(".xcov") cov_file = cov_file[:-5] for line in lines_of(cov_filepath): try: - prefix, _ = line.split(':', 1) - _, prefix = prefix.rsplit(' ', 1) + prefix, _ = line.split(":", 1) + _, prefix = prefix.rsplit(" ", 1) except ValueError: continue - if prefix in '+-': + if prefix in "+-": cov_set.add(prefix) - summary.append((cov_file, ''.join(sorted(cov_set)))) + summary.append((cov_file, "".join(sorted(cov_set)))) return sorted(summary) -def format_summary(summary, indent=''): - return '\n'.join( - '{}{}: {}'.format(indent, cov_file, cov_set) +def format_summary(summary, indent=""): + return "\n".join( + "{}{}: {}".format(indent, cov_file, cov_set) for cov_file, cov_set in summary ) expectations = { - '0': [('mylib1.adb', '-'), - ('mylib2.adb', '-'), - ('myprog.adb', '-')], - '1': [('mylib1.adb', '+'), - ('mylib2.adb', '-'), - ('myprog.adb', '-')], - '2': [('mylib1.adb', '-'), - ('mylib2.adb', '+'), - ('myprog.adb', '-')], - '12': [('mylib1.adb', '+'), - ('mylib2.adb', '+'), - ('myprog.adb', '-')]} + "0": [("mylib1.adb", "-"), ("mylib2.adb", "-"), ("myprog.adb", "-")], + "1": [("mylib1.adb", "+"), ("mylib2.adb", "-"), ("myprog.adb", "-")], + "2": [("mylib1.adb", "-"), ("mylib2.adb", "+"), ("myprog.adb", "-")], + "12": [("mylib1.adb", "+"), ("mylib2.adb", "+"), ("myprog.adb", "-")], +} for tag, exp in expectations.items(): - output_dir = in_tmp('report-{}'.format(tag)) + output_dir = in_tmp("report-{}".format(tag)) if os.path.exists(in_tmp(output_dir)): rm(output_dir, recursive=True) mkdir(output_dir) - xcov(['coverage', '-Pmyprog', '--level=stmt', '--annotate=xcov', - '--output-dir', output_dir, in_tmp('myprog_{}.trace'.format(tag))]) + xcov( + [ + "coverage", + "-Pmyprog", + "--level=stmt", + "--annotate=xcov", + "--output-dir", + output_dir, + in_tmp("myprog_{}.trace".format(tag)), + ] + ) summary = cov_report_summary(output_dir) thistest.fail_if( summary != exp, - 'Expected the following coverage report:\n' - '{}\n' - 'But got the following one instead:\n' - '{}'.format(format_summary(exp, ' '), - format_summary(summary, ' '))) + "Expected the following coverage report:\n" + "{}\n" + "But got the following one instead:\n" + "{}".format(format_summary(exp, " "), format_summary(summary, " ")), + ) thistest.result() diff --git a/testsuite/tests/OA16-009-exec-prefix/test.py b/testsuite/tests/OA16-009-exec-prefix/test.py index add496766..343fce512 100644 --- a/testsuite/tests/OA16-009-exec-prefix/test.py +++ b/testsuite/tests/OA16-009-exec-prefix/test.py @@ -6,43 +6,59 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of -from SUITE.tutils import (exename_for, tracename_for, gprfor, gprbuild, xrun, - xcov) +from SUITE.tutils import ( + exename_for, + tracename_for, + gprfor, + gprbuild, + xrun, + xcov, +) # This test needs a clean temporary directory because already existing files # from previous testsuite runs will disturb the executable lookup process. -if os.path.exists('tmp_'): - shutil.rmtree('tmp_') -wd = Wdir('tmp_') +if os.path.exists("tmp_"): + shutil.rmtree("tmp_") +wd = Wdir("tmp_") # Build the two set of sources as two projects. Each one has its own object # directory (which is the exec directory as well). -for src_dir in ('prj1', 'prj2'): - obj_dir = 'obj-{}'.format(src_dir) - gprbuild(gprfor(srcdirs=[os.path.join('..', src_dir)], - objdir=obj_dir, - exedir=obj_dir, - mains=['foo.adb'])) +for src_dir in ("prj1", "prj2"): + obj_dir = "obj-{}".format(src_dir) + gprbuild( + gprfor( + srcdirs=[os.path.join("..", src_dir)], + objdir=obj_dir, + exedir=obj_dir, + mains=["foo.adb"], + ) + ) -exename = exename_for('foo') -tracename = tracename_for('foo') +exename = exename_for("foo") +tracename = tracename_for("foo") -prj1_exe = os.path.join('obj-prj1', exename) -prj2_exe = os.path.join('obj-prj2', exename) -doesnotexist_exe = os.path.join('doesnotexist', exename) +prj1_exe = os.path.join("obj-prj1", exename) +prj2_exe = os.path.join("obj-prj2", exename) +doesnotexist_exe = os.path.join("doesnotexist", exename) # Generate traces and coverage report for prj2's foo.adb while there is a "foo" # executable in the current directory: make sure it works on prj2's program by # making sure we find prj2 source chunks in Xcov reports. shutil.copy(prj1_exe, exename) xrun([prj2_exe]) -xcov(['coverage', '--level=stmt', '--annotate=xcov', - '--scos={}'.format(os.path.join('obj-prj2', 'foo.ali')), - tracename]) +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + "--scos={}".format(os.path.join("obj-prj2", "foo.ali")), + tracename, + ] +) thistest.fail_if( - "This is prj2's foo.adb" not in contents_of('foo.adb.xcov'), - '"gnatcov coverage" did not use the correct program' + "This is prj2's foo.adb" not in contents_of("foo.adb.xcov"), + '"gnatcov coverage" did not use the correct program', ) # Now, when the provided path does not exists, make sure GNATcoverage does not @@ -50,11 +66,10 @@ # option. p = xrun([doesnotexist_exe], register_failure=False) thistest.fail_if( - p.status == 0, - '"gnatcov run" found a program without --exec-prefix' + p.status == 0, '"gnatcov run" found a program without --exec-prefix' ) # And finally make sure it finds the executable with --exec-prefix -p = xrun([doesnotexist_exe, '--exec-prefix=obj-prj2'], register_failure=True) +p = xrun([doesnotexist_exe, "--exec-prefix=obj-prj2"], register_failure=True) thistest.result() diff --git a/testsuite/tests/OA16-009-windows-suffix/test.py b/testsuite/tests/OA16-009-windows-suffix/test.py index 1e8c333e9..9c1bb1b35 100644 --- a/testsuite/tests/OA16-009-windows-suffix/test.py +++ b/testsuite/tests/OA16-009-windows-suffix/test.py @@ -6,25 +6,30 @@ wd = Wdir("tmp_") -gprbuild(gprfor(srcdirs=[".."], mains=['foo.adb'])) +gprbuild(gprfor(srcdirs=[".."], mains=["foo.adb"])) # We want to check that "gnatcov run" will find the executable even though the # input casing is different and even though it misses the ".exe" suffix. -os.rename('foo.exe', 'Foo.Exe') -xrun('foo') +os.rename("foo.exe", "Foo.Exe") +xrun("foo") # Here, we also want to check that the default filename for the trace file is # based on the actual filesystem name, not the name "gnatcov run" received in # the command line. -xcov(['coverage', - '--level=stmt', '--annotate=xcov', - '--scos=obj\\foo.ali', - 'Foo.Exe.trace']) +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + "--scos=obj\\foo.ali", + "Foo.Exe.trace", + ] +) thistest.fail_if( - not os.path.exists('foo.adb.xcov'), + not os.path.exists("foo.adb.xcov"), '"gnatcov coverage" did not produce a XCOV report for the main source' - ' file.' + " file.", ) thistest.result() diff --git a/testsuite/tests/OA27-059-inlined-separate-cons/test.py b/testsuite/tests/OA27-059-inlined-separate-cons/test.py index 34a551edb..00688fd4d 100644 --- a/testsuite/tests/OA27-059-inlined-separate-cons/test.py +++ b/testsuite/tests/OA27-059-inlined-separate-cons/test.py @@ -9,15 +9,18 @@ import os.path import shutil -from SCOV.minicheck import (build_run_and_coverage, checked_xcov, - check_xcov_reports) +from SCOV.minicheck import ( + build_run_and_coverage, + checked_xcov, + check_xcov_reports, +) from SUITE.context import thistest from SUITE.gprutils import GPRswitches from SUITE.cutils import Wdir from SUITE.tutils import tracename_for, xcov -wd = Wdir('tmp_') +wd = Wdir("tmp_") class Testcase(object): @@ -27,84 +30,100 @@ def __init__(self, name, objdir): @property def project_file(self): - return os.path.join('..', '{}.gpr'.format(self.name)) + return os.path.join("..", "{}.gpr".format(self.name)) @property def main(self): - return 'main_{}'.format(self.name) + return "main_{}".format(self.name) def obj_dir(self, *args): - return os.path.join('..', self._objdir, *args) + return os.path.join("..", self._objdir, *args) def exe_dir(self, *args): - return os.path.join('..', 'bin', *args) + return os.path.join("..", "bin", *args) @property def tracename(self): - return tracename_for('main_{}'.format(self.name)) + return tracename_for("main_{}".format(self.name)) @property def checkpoint(self): - return '{}.ckpt'.format(self.name) + return "{}.ckpt".format(self.name) def clean_output_directory(): - if os.path.exists('output'): - shutil.rmtree('output') - os.mkdir('output') + if os.path.exists("output"): + shutil.rmtree("output") + os.mkdir("output") -test1 = Testcase('test1', 'obj1') -test2 = Testcase('test2', 'obj2') +test1 = Testcase("test1", "obj1") +test2 = Testcase("test2", "obj2") testcases = [test1, test2] -covlevel = 'stmt+decision' -extra_args = ['--units=pkg'], -output_arg = '--output-dir=output' +covlevel = "stmt+decision" +extra_args = (["--units=pkg"],) +output_arg = "--output-dir=output" # Build the test material (program and traces) and produce checkpoints for testcase in testcases: thistest.log(f"== {testcase.name} ==") build_run_and_coverage( - gprsw=GPRswitches(root_project=testcase.project_file, units=['pkg']), + gprsw=GPRswitches(root_project=testcase.project_file, units=["pkg"]), covlevel=covlevel, mains=[testcase.main], - ignored_source_files=['pkg-test_driver.adb'], + ignored_source_files=["pkg-test_driver.adb"], gpr_obj_dir=testcase.obj_dir(), gpr_exe_dir=testcase.exe_dir(), - extra_coverage_args=['--save-checkpoint', testcase.checkpoint], - out='ckpt-{}.log'.format(testcase.name), - scos_for_run=False) + extra_coverage_args=["--save-checkpoint", testcase.checkpoint], + out="ckpt-{}.log".format(testcase.name), + scos_for_run=False, + ) # When inlining is enabled, consolidation without checkpoints cannot work, even # with --ignore-source-files. -if ( - thistest.options.trace_mode == 'bin' and - '-O1' in thistest.suite_cargs_for('Ada') +if thistest.options.trace_mode == "bin" and "-O1" in thistest.suite_cargs_for( + "Ada" ): - p = xcov(['coverage', '-c', covlevel, '--annotate=report', output_arg, - test1.tracename, test2.tracename]) + p = xcov( + [ + "coverage", + "-c", + covlevel, + "--annotate=report", + output_arg, + test1.tracename, + test2.tracename, + ] + ) thistest.fail_if( p.status == 0, '"gnatcov coverage" is supposed to complain about different symbols' - ' during consolidation, but it did not.' + " during consolidation, but it did not.", ) # Check that consolidation behaves as expected with the --ignore-source-files # switch: expected number of reports and expected report content. clean_output_directory() -checked_xcov(['coverage', '-c', covlevel, '--annotate=xcov', output_arg, - '-C', test1.checkpoint, - '-C', test2.checkpoint], - 'cons.log') +checked_xcov( + [ + "coverage", + "-c", + covlevel, + "--annotate=xcov", + output_arg, + "-C", + test1.checkpoint, + "-C", + test2.checkpoint, + ], + "cons.log", +) # Finally, check we have the expected reports check_xcov_reports( - 'output', - { - 'pkg.ads.xcov': {}, - 'pkg.adb.xcov': {'+': {5, 6, 8}} - }, + "output", + {"pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {5, 6, 8}}}, ) thistest.result() diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/test.py b/testsuite/tests/OA27-059-sep-cons-prj-override/test.py index 55c37d777..92c1cab3d 100644 --- a/testsuite/tests/OA27-059-sep-cons-prj-override/test.py +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/test.py @@ -16,18 +16,18 @@ from SUITE.tutils import gprbuild -wd = Wdir('tmp_') +wd = Wdir("tmp_") # Copy project sources in the temporary director for f in [ - 'pkg_under_test.gpr', - 'src_under_test', - 'test1', - 'test1.gpr', - 'test2', - 'test2.gpr' + "pkg_under_test.gpr", + "src_under_test", + "test1", + "test1.gpr", + "test2", + "test2.gpr", ]: - sync_tree(os.path.join('..', f), f) + sync_tree(os.path.join("..", f), f) class Testcase(object): @@ -37,28 +37,28 @@ def __init__(self, name, objdir): @property def project_file(self): - return f'{self.name}.gpr' + return f"{self.name}.gpr" @property def main(self): - return f'main_{self.name}' + return f"main_{self.name}" def obj_dir(self, *args): return os.path.join(self._objdir, *args) def exe_dir(self, *args): - return os.path.join('bin', *args) + return os.path.join("bin", *args) def clean_output_directory(): - rm('output') - mkdir('output') + rm("output") + mkdir("output") -test1 = Testcase('test1', 'obj1') -test2 = Testcase('test2', 'obj2') +test1 = Testcase("test1", "obj1") +test2 = Testcase("test2", "obj2") testcases = [test1, test2] -gprsw_for_cov = GPRswitches(root_project='pkg_under_test.gpr') +gprsw_for_cov = GPRswitches(root_project="pkg_under_test.gpr") # The goal of this testcase is to check that the --ignore-source-files # command-line argument, when provided, takes precedence over the @@ -69,7 +69,7 @@ def clean_output_directory(): # --ignore-source-files take precedence, we pass it to ignore only # pkg_under_test-pkg_test.adb, so that pkg_under_test-some_procedure.adb # should show up in coverage reports. -overriding_ignored_source_file = 'pkg_under_test-pkg_test.adb' +overriding_ignored_source_file = "pkg_under_test-pkg_test.adb" # Build the test material: program and traces trace_files = [] @@ -93,26 +93,26 @@ def clean_output_directory(): # (in source trace mode, to get SID files). Since instrumentation uses the # "ignore source files" information, we also need to pass --ignore-source-files # here. -if thistest.options.trace_mode == 'bin': +if thistest.options.trace_mode == "bin": gprbuild(gprsw_for_cov.root_project) else: xcov_instrument( gprsw=gprsw_for_cov, covlevel=None, - extra_args=[f'--ignore-source-files={overriding_ignored_source_file}'], + extra_args=[f"--ignore-source-files={overriding_ignored_source_file}"], ) # The presence of pkg_under_test-some_procedure.adb and the absence of # pkg_under_test-pkg_test.adb prove that --ignored-source-files took # precedence over the Coverage'Ignored_Source_Files project attribute. clean_output_directory() -p = checked_xcov(xcov_args + ['--output-dir=output'] + trace_files, 'cons.log') +p = checked_xcov(xcov_args + ["--output-dir=output"] + trace_files, "cons.log") check_xcov_reports( - 'output', + "output", { - 'pkg_under_test.ads.xcov': {}, - 'pkg_under_test.adb.xcov': {'+': {7, 8, 10}}, - 'pkg_under_test-some_procedure.adb.xcov': {'-': {5}}, + "pkg_under_test.ads.xcov": {}, + "pkg_under_test.adb.xcov": {"+": {7, 8, 10}}, + "pkg_under_test-some_procedure.adb.xcov": {"-": {5}}, }, ) diff --git a/testsuite/tests/OA27-059-sep-cons-prj/test.py b/testsuite/tests/OA27-059-sep-cons-prj/test.py index f21777009..cb8c039e6 100644 --- a/testsuite/tests/OA27-059-sep-cons-prj/test.py +++ b/testsuite/tests/OA27-059-sep-cons-prj/test.py @@ -15,18 +15,18 @@ from SUITE.tutils import gprbuild -wd = Wdir('tmp_') +wd = Wdir("tmp_") # Copy project sources in the temporary director for f in [ - 'pkg_under_test.gpr', - 'src_under_test', - 'test1', - 'test1.gpr', - 'test2', - 'test2.gpr' + "pkg_under_test.gpr", + "src_under_test", + "test1", + "test1.gpr", + "test2", + "test2.gpr", ]: - sync_tree(os.path.join('..', f), f) + sync_tree(os.path.join("..", f), f) class Testcase(object): @@ -36,28 +36,28 @@ def __init__(self, name, objdir): @property def project_file(self): - return f'{self.name}.gpr' + return f"{self.name}.gpr" @property def main(self): - return f'main_{self.name}' + return f"main_{self.name}" def obj_dir(self, *args): return os.path.join(self._objdir, *args) def exe_dir(self, *args): - return os.path.join('bin', *args) + return os.path.join("bin", *args) def clean_output_directory(): - rm('output') - mkdir('output') + rm("output") + mkdir("output") -test1 = Testcase('test1', 'obj1') -test2 = Testcase('test2', 'obj2') +test1 = Testcase("test1", "obj1") +test2 = Testcase("test2", "obj2") testcases = [test1, test2] -gprsw_for_cov = GPRswitches(root_project='pkg_under_test.gpr') +gprsw_for_cov = GPRswitches(root_project="pkg_under_test.gpr") # Build the test material: program and traces trace_files = [] @@ -78,7 +78,7 @@ def clean_output_directory(): # project. This requires the extended project to have its own ALI/SID files, so # build this project (in binary trace mode, to get ALI files) or instrument it # (in source trace mode, to get SID files). -if thistest.options.trace_mode == 'bin': +if thistest.options.trace_mode == "bin": gprbuild(gprsw_for_cov.root_project) else: xcov_instrument(gprsw=gprsw_for_cov, covlevel=None) @@ -87,12 +87,12 @@ def clean_output_directory(): # conflicting symbols between test1 and test2, and succeeds to create a report # with the expected coverage data. clean_output_directory() -p = checked_xcov(xcov_args + ['--output-dir=output'] + trace_files, 'cons.log') +p = checked_xcov(xcov_args + ["--output-dir=output"] + trace_files, "cons.log") check_xcov_reports( - 'output', + "output", { - 'pkg_under_test.ads.xcov': {}, - 'pkg_under_test.adb.xcov': {'+': {7, 8, 10}}, + "pkg_under_test.ads.xcov": {}, + "pkg_under_test.adb.xcov": {"+": {7, 8, 10}}, }, ) diff --git a/testsuite/tests/OA27-059-separate-consolidation/test.py b/testsuite/tests/OA27-059-separate-consolidation/test.py index fcdb57afb..26f4f6685 100644 --- a/testsuite/tests/OA27-059-separate-consolidation/test.py +++ b/testsuite/tests/OA27-059-separate-consolidation/test.py @@ -17,11 +17,11 @@ # Clean up projects build artifacts -for obj_dir in ('bin', 'obj1', 'obj2'): +for obj_dir in ("bin", "obj1", "obj2"): if os.path.exists(obj_dir): shutil.rmtree(obj_dir) -wd = Wdir('tmp_') +wd = Wdir("tmp_") class Testcase(object): @@ -31,27 +31,27 @@ def __init__(self, name, objdir): @property def project_file(self): - return os.path.join('..', '{}.gpr'.format(self.name)) + return os.path.join("..", "{}.gpr".format(self.name)) @property def main(self): - return 'main_{}'.format(self.name) + return "main_{}".format(self.name) def obj_dir(self, *args): - return os.path.join('..', self._objdir, *args) + return os.path.join("..", self._objdir, *args) def exe_dir(self, *args): - return os.path.join('..', 'bin', *args) + return os.path.join("..", "bin", *args) def clean_output_directory(): - if os.path.exists('output'): - shutil.rmtree('output') - os.mkdir('output') + if os.path.exists("output"): + shutil.rmtree("output") + os.mkdir("output") -test1 = Testcase('test1', 'obj1') -test2 = Testcase('test2', 'obj2') +test1 = Testcase("test1", "obj1") +test2 = Testcase("test2", "obj2") testcases = [test1, test2] @@ -62,15 +62,17 @@ def build_and_run_tests(ignored_source_files=[]): trace_files = [] for testcase in testcases: xcov_args = build_and_run( - gprsw=GPRswitches(root_project=testcase.project_file, - units=['pkg_under_test']), - covlevel='stmt+decision', + gprsw=GPRswitches( + root_project=testcase.project_file, units=["pkg_under_test"] + ), + covlevel="stmt+decision", mains=[testcase.main], ignored_source_files=ignored_source_files, gpr_obj_dir=testcase.obj_dir(), gpr_exe_dir=testcase.exe_dir(), - extra_coverage_args=['--annotate=xcov', '--output-dir=output'], - scos_for_run=False) + extra_coverage_args=["--annotate=xcov", "--output-dir=output"], + scos_for_run=False, + ) trace_files.append(xcov_args.pop()) return xcov_args + trace_files @@ -80,19 +82,19 @@ def build_and_run_tests(ignored_source_files=[]): # consolidation error by default. clean_output_directory() xcov_args = build_and_run_tests() -p = xcov(xcov_args, out='cons-1.log', register_failure=False) +p = xcov(xcov_args, out="cons-1.log", register_failure=False) thistest.fail_if( p.status == 0, '"gnatcov coverage" is supposed to complain about different symbols during' - ' consolidation, but it did not.' + " consolidation, but it did not.", ) # Build and run tests with ignored source files. Check that the new option # makes it ignore the problematic symbols, and succeeds to create a report with # the expected coverage data. clean_output_directory() -xcov_args = build_and_run_tests(['pkg_under_test-pkg_test.adb']) -p = checked_xcov(xcov_args, 'cons-2.log') -check_xcov_reports('output', {'pkg_under_test.adb.xcov': {'+': {7, 8, 10}}}) +xcov_args = build_and_run_tests(["pkg_under_test-pkg_test.adb"]) +p = checked_xcov(xcov_args, "cons-2.log") +check_xcov_reports("output", {"pkg_under_test.adb.xcov": {"+": {7, 8, 10}}}) thistest.result() diff --git a/testsuite/tests/OB23-036/test.py b/testsuite/tests/OB23-036/test.py index 9d1929661..7962fc26d 100644 --- a/testsuite/tests/OB23-036/test.py +++ b/testsuite/tests/OB23-036/test.py @@ -11,18 +11,18 @@ from SUITE.tutils import exename_for, gprbuild, gprfor, xcov -wd = Wdir('tmp_') +wd = Wdir("tmp_") -gprbuild(gprfor(srcdirs=[os.path.join(wd.homedir)], - mains=['foo.adb'])) -exename = exename_for('foo') +gprbuild(gprfor(srcdirs=[os.path.join(wd.homedir)], mains=["foo.adb"])) +exename = exename_for("foo") -xcov(['disp-routines', - '--include', exename, - '--exclude', exename], out='disp-routines.out') +xcov( + ["disp-routines", "--include", exename, "--exclude", exename], + out="disp-routines.out", +) thistest.fail_if( - contents_of('disp-routines.out') != '', - '"gnatcov disp-routines" did not yield the expected list of routines' + contents_of("disp-routines.out") != "", + '"gnatcov disp-routines" did not yield the expected list of routines', ) thistest.result() diff --git a/testsuite/tests/P505-032-path-spaces/test.py b/testsuite/tests/P505-032-path-spaces/test.py index 36b74ecee..a588fd8ec 100644 --- a/testsuite/tests/P505-032-path-spaces/test.py +++ b/testsuite/tests/P505-032-path-spaces/test.py @@ -9,22 +9,29 @@ from SUITE.context import thistest from SUITE.cutils import Wdir, match -from SUITE.tutils import (exename_for, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exename_for, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -Wdir('tmp/with spaces') +Wdir("tmp/with spaces") -gpr_file = gprfor(srcdirs=['../..'], mains=['foo.adb'], objdir='obj') +gpr_file = gprfor(srcdirs=["../.."], mains=["foo.adb"], objdir="obj") gprbuild(gpr_file) -foo_exe = os.path.abspath(exename_for('foo')) -foo_trace = os.path.abspath(tracename_for('foo')) +foo_exe = os.path.abspath(exename_for("foo")) +foo_trace = os.path.abspath(tracename_for("foo")) -xrun(['-o', foo_trace, foo_exe]) -xcov(['coverage', '-P', gpr_file, '-c', 'stmt', '-a', 'xcov', foo_trace]) +xrun(["-o", foo_trace, foo_exe]) +xcov(["coverage", "-P", gpr_file, "-c", "stmt", "-a", "xcov", foo_trace]) thistest.fail_if( - not match(r'4 \+: *Put_Line', os.path.join('obj', 'foo.adb.xcov')), - 'Statement at foo.adb:4 is not covered whereas it should be') + not match(r"4 \+: *Put_Line", os.path.join("obj", "foo.adb.xcov")), + "Statement at foo.adb:4 is not covered whereas it should be", +) thistest.result() diff --git a/testsuite/tests/P526-035-origin-project/test.py b/testsuite/tests/P526-035-origin-project/test.py index b0de3219c..6663661b5 100644 --- a/testsuite/tests/P526-035-origin-project/test.py +++ b/testsuite/tests/P526-035-origin-project/test.py @@ -12,37 +12,42 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor, tracename_for -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") def xcov_list(): """ Return the list of *.xcov files in the "obj" subdirectory. """ - return set(os.path.basename(f) - for f in glob.glob(os.path.join('obj', '*.xcov'))) + return set( + os.path.basename(f) for f in glob.glob(os.path.join("obj", "*.xcov")) + ) def clean_xcov(): """ Remove all *.xcov files in the "obj" subdirectory. """ - for filename in glob.glob(os.path.join('obj', '*.xcov')): + for filename in glob.glob(os.path.join("obj", "*.xcov")): os.remove(filename) -gprfor(prjid='p1', srcdirs=['../src-p1'], mains=None, langs='Ada') +gprfor(prjid="p1", srcdirs=["../src-p1"], mains=None, langs="Ada") -p2 = gprfor(prjid='p2', srcdirs=['../src-p2'], mains=['p2.adb'], - deps=['p1'], - extra='for Origin_Project use \"p1\";') +p2 = gprfor( + prjid="p2", + srcdirs=["../src-p2"], + mains=["p2.adb"], + deps=["p1"], + extra='for Origin_Project use "p1";', +) # Check that the Origin_Project provides a default for coverage analysis and # that this default is overiden by the --projects switch. for args, xcovs in [ - ([], {'p1.adb.xcov'}), - (['--projects=p2'], {'p2.adb.xcov'}), - (['--projects=p1', '--projects=p2'], {'p1.adb.xcov', 'p2.adb.xcov'}), + ([], {"p1.adb.xcov"}), + (["--projects=p2"], {"p2.adb.xcov"}), + (["--projects=p1", "--projects=p2"], {"p1.adb.xcov", "p2.adb.xcov"}), ]: clean_xcov() @@ -51,26 +56,30 @@ def clean_xcov(): # to be consistent with gnatcov use model. # If these options are not accounted at instrumentation time, # there won't be SID files for every wanted unit of interest. - build_run_and_coverage(gprsw=GPRswitches(root_project=p2), - covlevel='stmt', - mains=['p2'], - extra_coverage_args=['-a', 'xcov', - '--no-subprojects'], - extra_args=args) - - p2_trace = tracename_for('p2') - - expected = ('\n'.join('* {}'.format(f) for f in sorted(xcovs)) or - ' ') - got = ('\n'.join('* {}'.format(f) for f in sorted(xcov_list())) or - ' ') + build_run_and_coverage( + gprsw=GPRswitches(root_project=p2), + covlevel="stmt", + mains=["p2"], + extra_coverage_args=["-a", "xcov", "--no-subprojects"], + extra_args=args, + ) + + p2_trace = tracename_for("p2") + + expected = ( + "\n".join("* {}".format(f) for f in sorted(xcovs)) or " " + ) + got = ( + "\n".join("* {}".format(f) for f in sorted(xcov_list())) or " " + ) thistest.fail_if( expected != got, - '[{}switches: {}]\n' - 'Unexpected XCOV files. Expected:\n' - '{}\n' - 'But got instead:\n' - '{}\n'.format(p2_trace, ' '.join(args), expected, got)) + "[{}switches: {}]\n" + "Unexpected XCOV files. Expected:\n" + "{}\n" + "But got instead:\n" + "{}\n".format(p2_trace, " ".join(args), expected, got), + ) thistest.result() diff --git a/testsuite/tests/P907-005-ckpt-covlevel/test.py b/testsuite/tests/P907-005-ckpt-covlevel/test.py index b174d9bbf..94643283b 100644 --- a/testsuite/tests/P907-005-ckpt-covlevel/test.py +++ b/testsuite/tests/P907-005-ckpt-covlevel/test.py @@ -10,70 +10,85 @@ from SUITE.tutils import gprfor, xcov -wd = Wdir('tmp_') +wd = Wdir("tmp_") def create_checkpoint(name, covlevel): - gpr_exe_dir = 'exe-{}'.format(name) - gpr_obj_dir = 'obj-{}'.format(name) - prj_file = gprfor(mains=['test_{}.adb'.format(name)], - prjid=name, - srcdirs=os.path.join('..', 'src'), - objdir=gpr_obj_dir, - exedir=gpr_exe_dir, - extra='package Coverage is\n' - ' for Units use ("math");\n' - 'end Coverage;') - ckpt = 'test_{}.ckpt'.format(name) + gpr_exe_dir = "exe-{}".format(name) + gpr_obj_dir = "obj-{}".format(name) + prj_file = gprfor( + mains=["test_{}.adb".format(name)], + prjid=name, + srcdirs=os.path.join("..", "src"), + objdir=gpr_obj_dir, + exedir=gpr_exe_dir, + extra="package Coverage is\n" + ' for Units use ("math");\n' + "end Coverage;", + ) + ckpt = "test_{}.ckpt".format(name) build_run_and_coverage( gprsw=GPRswitches(root_project=prj_file), covlevel=covlevel, - mains=['test_{}'.format(name)], + mains=["test_{}".format(name)], gpr_obj_dir=gpr_obj_dir, gpr_exe_dir=gpr_exe_dir, - extra_coverage_args=['--save-checkpoint={}'.format(ckpt)]) + extra_coverage_args=["--save-checkpoint={}".format(ckpt)], + ) return ckpt def clean_output_directory(): - if os.path.exists('output'): - shutil.rmtree('output') - os.mkdir('output') + if os.path.exists("output"): + shutil.rmtree("output") + os.mkdir("output") # Create two checkpoints with different coverage levels -add_ckpt = create_checkpoint('add', 'stmt') -mult_ckpt = create_checkpoint('mult', 'stmt+decision') +add_ckpt = create_checkpoint("add", "stmt") +mult_ckpt = create_checkpoint("mult", "stmt+decision") # Consolidate both. The only attempt that is expected to suceed is the one # with the weakest common coverage level criteria, i.e. stmt. -args = ['coverage', '--annotate=xcov', '--output-dir=output', '-C', add_ckpt, - '-C', mult_ckpt] +args = [ + "coverage", + "--annotate=xcov", + "--output-dir=output", + "-C", + add_ckpt, + "-C", + mult_ckpt, +] # Attempting to consolidate them in stmt+decision mode should fail since one # checkpoint was produced with a weaker coverage criteria (stmt). # TODO: refine the expected error message. clean_output_directory() -p = xcov(args + ['--level=stmt+decision'], 'cons-stmt-decision.log', - register_failure=False) +p = xcov( + args + ["--level=stmt+decision"], + "cons-stmt-decision.log", + register_failure=False, +) thistest.fail_if( - p.status == 0 or not re.match( - r'.*gnatcov.*: incompatible coverage level: .*test_add.*ckpt was' + p.status == 0 + or not re.match( + r".*gnatcov.*: incompatible coverage level: .*test_add.*ckpt was" r' produced with "stmt" but we expect at least "stmt\+decision"', - contents_of('cons-stmt-decision.log').strip() + contents_of("cons-stmt-decision.log").strip(), ), - 'gnatcov did not complain about inconsistent coverage criteria across' - ' input checkpoints') + "gnatcov did not complain about inconsistent coverage criteria across" + " input checkpoints", +) clean_output_directory() -xcov(args + ['--level=stmt'], 'cons-stmt.log') +xcov(args + ["--level=stmt"], "cons-stmt.log") expected = { - 'math.adb.xcov': {'+': {7, 12, 13, 14, 17, 18, 19}}, - 'math.ads.xcov': {}, + "math.adb.xcov": {"+": {7, 12, 13, 14, 17, 18, 19}}, + "math.ads.xcov": {}, } # Finally, check we have the expected reports for the --level=stmt # consolidation. -check_xcov_reports('output', expected, discard_empty=False) +check_xcov_reports("output", expected, discard_empty=False) thistest.result() diff --git a/testsuite/tests/P907-005-incremental/test.py b/testsuite/tests/P907-005-incremental/test.py index ad80dc2bb..c81ca7a35 100644 --- a/testsuite/tests/P907-005-incremental/test.py +++ b/testsuite/tests/P907-005-incremental/test.py @@ -8,19 +8,22 @@ from SUITE.tutils import gprfor -wd = Wdir('tmp_') +wd = Wdir("tmp_") # Generate a project for test drivers, build and run them to get trace files -prj_file = gprfor(['test_add.adb', 'test_mult.adb'], - srcdirs=os.path.join('..', 'src'), - extra='package Coverage is' - '\n for Units use ("math");' - '\nend Coverage;') +prj_file = gprfor( + ["test_add.adb", "test_mult.adb"], + srcdirs=os.path.join("..", "src"), + extra="package Coverage is" + '\n for Units use ("math");' + "\nend Coverage;", +) xcov_args = build_and_run( gprsw=GPRswitches(root_project=prj_file), - covlevel='stmt+decision', - mains=['test_add', 'test_mult'], - extra_coverage_args=[]) + covlevel="stmt+decision", + mains=["test_add", "test_mult"], + extra_coverage_args=[], +) # Extract trace files arguments from "xcov_args" base_args = xcov_args[:-2] @@ -29,23 +32,29 @@ # Now, consolidate one trace file after the other, accumulating results in a # single checkpoint (this is incremental coverage). -checked_xcov(base_args + ['--save-checkpoint=c1.ckpt', add_trace], - 'checkpoint-1.log') -checked_xcov(base_args + ['--checkpoint=c1.ckpt', - '--save-checkpoint=c2.ckpt', mult_trace], - 'checkpoint-2.log') +checked_xcov( + base_args + ["--save-checkpoint=c1.ckpt", add_trace], "checkpoint-1.log" +) +checked_xcov( + base_args + + ["--checkpoint=c1.ckpt", "--save-checkpoint=c2.ckpt", mult_trace], + "checkpoint-2.log", +) # Generate the final report and check we have the expected result -checked_xcov(base_args + ['--annotate=xcov', '--checkpoint=c2.ckpt', - '--output-dir=.'], - 'report.log') +checked_xcov( + base_args + ["--annotate=xcov", "--checkpoint=c2.ckpt", "--output-dir=."], + "report.log", +) # Finally, check we have the expected reports check_xcov_reports( - '.', - {'math.adb.xcov': {'+': {7, 12, 13, 14, 18, 19}, '!': {17}}, - 'math.ads.xcov': {}}, + ".", + { + "math.adb.xcov": {"+": {7, 12, 13, 14, 18, 19}, "!": {17}}, + "math.ads.xcov": {}, + }, discard_empty=False, ) diff --git a/testsuite/tests/P907-005-stubbing-generic/test.py b/testsuite/tests/P907-005-stubbing-generic/test.py index 6653753ce..eface7a3a 100644 --- a/testsuite/tests/P907-005-stubbing-generic/test.py +++ b/testsuite/tests/P907-005-stubbing-generic/test.py @@ -2,8 +2,11 @@ import os.path import shutil -from SCOV.minicheck import (build_run_and_coverage, checked_xcov, - check_xcov_reports) +from SCOV.minicheck import ( + build_run_and_coverage, + checked_xcov, + check_xcov_reports, +) from SUITE.context import thistest from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches @@ -14,14 +17,16 @@ def __init__(self, test_dir, exename): self.test_dir = test_dir self.exename = exename - self.obj_dir = os.path.join('..', test_dir, 'obj') - self.prj_file = os.path.join('..', test_dir, 'test_runner.gpr') - self.ckpt_file = exename + '.ckpt' + self.obj_dir = os.path.join("..", test_dir, "obj") + self.prj_file = os.path.join("..", test_dir, "test_runner.gpr") + self.ckpt_file = exename + ".ckpt" -test_drivers = [TestDriver('test_p', 'tp1'), - TestDriver('test_t', 'tt1'), - TestDriver('test_sensors', 'ts1')] +test_drivers = [ + TestDriver("test_p", "tp1"), + TestDriver("test_t", "tt1"), + TestDriver("test_sensors", "ts1"), +] # Cleanup any previous test run artefacts @@ -30,47 +35,55 @@ def __init__(self, test_dir, exename): shutil.rmtree(td.obj_dir) -wd = Wdir('tmp_') +wd = Wdir("tmp_") # Build projects, generate trace and checkpoints for each test drivers for td in test_drivers: build_run_and_coverage( gprsw=GPRswitches(root_project=td.prj_file), - covlevel='stmt+decision', + covlevel="stmt+decision", mains=[td.exename], gpr_obj_dir=td.obj_dir, gpr_exe_dir=td.obj_dir, - extra_coverage_args=['--save-checkpoint', td.ckpt_file], - out='ckpt-{}.log'.format(td.exename), - scos_for_run=False) + extra_coverage_args=["--save-checkpoint", td.ckpt_file], + out="ckpt-{}.log".format(td.exename), + scos_for_run=False, + ) # Now, generate the final report -ckpt_args = ['--checkpoint={}'.format(td.ckpt_file) - for td in test_drivers] -checked_xcov(['coverage', '-P', os.path.join('..', 'sensors', 'sensors.gpr'), - '--level=stmt+decision', '--annotate=xcov', - '--output-dir=.'] + ckpt_args, - 'cons.log') +ckpt_args = ["--checkpoint={}".format(td.ckpt_file) for td in test_drivers] +checked_xcov( + [ + "coverage", + "-P", + os.path.join("..", "sensors", "sensors.gpr"), + "--level=stmt+decision", + "--annotate=xcov", + "--output-dir=.", + ] + + ckpt_args, + "cons.log", +) # Finally, check we have the expected reports check_xcov_reports( - '.', + ".", { - 'pressure_control.ads.xcov': {}, - 'pressure_control.adb.xcov': { - '+': {10, 18, 19}, - '!': {11}, - '-': {12}, + "pressure_control.ads.xcov": {}, + "pressure_control.adb.xcov": { + "+": {10, 18, 19}, + "!": {11}, + "-": {12}, + }, + "temperature_control.ads.xcov": {}, + "temperature_control.adb.xcov": { + "+": {10, 18, 19}, + "!": {11}, + "-": {12}, }, - 'temperature_control.ads.xcov': {}, - 'temperature_control.adb.xcov': { - '+': {10, 18, 19}, - '!': {11}, - '-': {12}, - } - } + }, ) thistest.result() diff --git a/testsuite/tests/P907-005-stubbing/test.py b/testsuite/tests/P907-005-stubbing/test.py index 953e3b79e..c1220ac03 100644 --- a/testsuite/tests/P907-005-stubbing/test.py +++ b/testsuite/tests/P907-005-stubbing/test.py @@ -2,8 +2,11 @@ import os.path import shutil -from SCOV.minicheck import (build_run_and_coverage, checked_xcov, - check_xcov_reports) +from SCOV.minicheck import ( + build_run_and_coverage, + checked_xcov, + check_xcov_reports, +) from SUITE.context import thistest from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches @@ -14,14 +17,16 @@ def __init__(self, test_dir, exename): self.test_dir = test_dir self.exename = exename - self.obj_dir = os.path.join('..', test_dir, 'obj') - self.prj_file = os.path.join('..', test_dir, 'test_runner.gpr') - self.ckpt_file = exename + '.ckpt' + self.obj_dir = os.path.join("..", test_dir, "obj") + self.prj_file = os.path.join("..", test_dir, "test_runner.gpr") + self.ckpt_file = exename + ".ckpt" -test_drivers = [TestDriver('test_p', 'tp1'), - TestDriver('test_t', 'tt1'), - TestDriver('test_sensors', 'ts1')] +test_drivers = [ + TestDriver("test_p", "tp1"), + TestDriver("test_t", "tt1"), + TestDriver("test_sensors", "ts1"), +] # Cleanup any previous test run artefacts @@ -30,46 +35,54 @@ def __init__(self, test_dir, exename): shutil.rmtree(td.obj_dir) -wd = Wdir('tmp_') +wd = Wdir("tmp_") # Build projects, generate trace and checkpoints for each test drivers for td in test_drivers: build_run_and_coverage( gprsw=GPRswitches(root_project=td.prj_file), - covlevel='stmt+decision', + covlevel="stmt+decision", mains=[td.exename], gpr_obj_dir=td.obj_dir, gpr_exe_dir=td.obj_dir, - extra_coverage_args=['--save-checkpoint', td.ckpt_file], - out='ckpt-{}.log'.format(td.exename), - scos_for_run=False) + extra_coverage_args=["--save-checkpoint", td.ckpt_file], + out="ckpt-{}.log".format(td.exename), + scos_for_run=False, + ) # Now, generate the final report -ckpt_args = ['--checkpoint={}'.format(td.ckpt_file) - for td in test_drivers] -checked_xcov(['coverage', '-P', os.path.join('..', 'sensors', 'sensors.gpr'), - '--level=stmt+decision', '--annotate=xcov', - '--output-dir=.'] + ckpt_args, - 'cons.log') +ckpt_args = ["--checkpoint={}".format(td.ckpt_file) for td in test_drivers] +checked_xcov( + [ + "coverage", + "-P", + os.path.join("..", "sensors", "sensors.gpr"), + "--level=stmt+decision", + "--annotate=xcov", + "--output-dir=.", + ] + + ckpt_args, + "cons.log", +) # Finally, check we have the expected reports check_xcov_reports( - '.', + ".", { - 'pressure_control.ads.xcov': {}, - 'pressure_control.adb.xcov': { - '+': {10, 18, 19}, - '!': {11}, - '-': {12}, + "pressure_control.ads.xcov": {}, + "pressure_control.adb.xcov": { + "+": {10, 18, 19}, + "!": {11}, + "-": {12}, + }, + "temperature_control.ads.xcov": {}, + "temperature_control.adb.xcov": { + "+": {10, 18, 19}, + "!": {11}, + "-": {12}, }, - 'temperature_control.ads.xcov': {}, - 'temperature_control.adb.xcov': { - '+': {10, 18, 19}, - '!': {11}, - '-': {12}, - } - } + }, ) thistest.result() diff --git a/testsuite/tests/P913-011-invalid-project/test.py b/testsuite/tests/P913-011-invalid-project/test.py index 091716235..2e6ee8dad 100644 --- a/testsuite/tests/P913-011-invalid-project/test.py +++ b/testsuite/tests/P913-011-invalid-project/test.py @@ -5,31 +5,35 @@ from SUITE.tutils import exename_for, gprbuild, gprfor, xcov -wd = Wdir('tmp_') -gprbuild(gprfor(['foo.adb'], srcdirs=['..'])) +wd = Wdir("tmp_") +gprbuild(gprfor(["foo.adb"], srcdirs=[".."])) -p = xcov(['run', '-P', 'does_not_exist.gpr', exename_for('foo')], - out='gnatcov-run.out', - err='gnatcov-run.err', - register_failure=False) +p = xcov( + ["run", "-P", "does_not_exist.gpr", exename_for("foo")], + out="gnatcov-run.out", + err="gnatcov-run.err", + register_failure=False, +) -out_content = contents_of('gnatcov-run.out') -err_content = contents_of('gnatcov-run.err') +out_content = contents_of("gnatcov-run.out") +err_content = contents_of("gnatcov-run.err") expected_err = re.compile( - '^does_not_exist.gpr is not a regular file\n' - '[^\n]*gnatcov(\\.exe)?: Could not load the project file, aborting.\n$') + "^does_not_exist.gpr is not a regular file\n" + "[^\n]*gnatcov(\\.exe)?: Could not load the project file, aborting.\n$" +) thistest.fail_if( p.status != 1, - 'gnatcov returned status code {}, but 1 expected'.format(p.status)) + "gnatcov returned status code {}, but 1 expected".format(p.status), +) thistest.fail_if( - out_content, - 'gnatcov output not empty:\n' - '\n{}\n'.format(out_content)) + out_content, "gnatcov output not empty:\n" "\n{}\n".format(out_content) +) thistest.fail_if( not expected_err.match(err_content), - 'gnatcov error output mismatch:\n' - 'Expected pattern:\n{!r}\n\n' - 'Got:\n{}'.format(expected_err.pattern, err_content)) + "gnatcov error output mismatch:\n" + "Expected pattern:\n{!r}\n\n" + "Got:\n{}".format(expected_err.pattern, err_content), +) thistest.result() diff --git a/testsuite/tests/PC09-022-auto-exename/test.py b/testsuite/tests/PC09-022-auto-exename/test.py index f679431a4..a4a7ed4ea 100644 --- a/testsuite/tests/PC09-022-auto-exename/test.py +++ b/testsuite/tests/PC09-022-auto-exename/test.py @@ -13,12 +13,20 @@ from SUITE.tutils import gprbuild, gprfor, xrun -wd = Wdir('tmp_') +wd = Wdir("tmp_") class Project(object): - def __init__(self, projects, name, srcdir, mains=(), deps=(), build=True, - should_succeed=True): + def __init__( + self, + projects, + name, + srcdir, + mains=(), + deps=(), + build=True, + should_succeed=True, + ): self.projects = projects self.name = name self.srcdir = srcdir @@ -27,8 +35,8 @@ def __init__(self, projects, name, srcdir, mains=(), deps=(), build=True, self.build = build self.should_succeed = should_succeed - self.objdir = 'obj-{}'.format(self.name) - self.exedir = 'exe-{}'.format(self.name) + self.objdir = "obj-{}".format(self.name) + self.exedir = "exe-{}".format(self.name) self.prj_file = None @@ -46,21 +54,22 @@ def all_mains(self): """ result = set() for main in self.mains: - result.add(main.split('.')[0]) + result.add(main.split(".")[0]) for p in self.dep_projects: result.update(p.all_mains) return result def prepare(self): - print('Preparing {}...'.format(self.name)) + print("Preparing {}...".format(self.name)) self.prj_file = gprfor( mains=self.mains, prjid=self.name, - srcdirs=os.path.join('..', self.srcdir), + srcdirs=os.path.join("..", self.srcdir), objdir=self.objdir, exedir=self.exedir, - langs=['Ada'], - deps=self.deps) + langs=["Ada"], + deps=self.deps, + ) if self.build: gprbuild(self.prj_file) @@ -71,71 +80,88 @@ def prepare(self): os.mkdir(dirname) def run(self): - print('') - print('== Running {} =='.format(self.name)) + print("") + print("== Running {} ==".format(self.name)) error_msg_re = None all_mains = self.all_mains if len(all_mains) != 1: - print('Not exactly one main: should fail') + print("Not exactly one main: should fail") error_msg_re = ( - r'.*gnatcov.*: Please specify an executable to run \(EXE\)' - r' on the command line.*') + r".*gnatcov.*: Please specify an executable to run \(EXE\)" + r" on the command line.*" + ) elif not self.build: main = all_mains.pop() - print('Not built: should fail') - error_msg_re = '.*gnatcov.*: .*{}.*: File not found'.format( - re.escape(main)) + print("Not built: should fail") + error_msg_re = ".*gnatcov.*: .*{}.*: File not found".format( + re.escape(main) + ) else: - print('Should succeed') + print("Should succeed") we_think_it_should_succeed = not error_msg_re thistest.stop_if( we_think_it_should_succeed != self.should_succeed, - FatalError('Test declaration disagrees with test framework about' - ' whether this test should fail')) - - log_file = 'run-{}.txt'.format(self.name) - p = xrun(['-P', self.prj_file], - register_failure=not error_msg_re, - out=log_file) + FatalError( + "Test declaration disagrees with test framework about" + " whether this test should fail" + ), + ) + + log_file = "run-{}.txt".format(self.name) + p = xrun( + ["-P", self.prj_file], + register_failure=not error_msg_re, + out=log_file, + ) if error_msg_re: thistest.fail_if( p.status == 0, - 'gnatcov run suceeded whereas it was expected to fail') + "gnatcov run suceeded whereas it was expected to fail", + ) out = contents_of(log_file).strip() thistest.fail_if( not re.match(error_msg_re, out), - '\nFor {}, error message ({}):' - '\n{}' - '\nDoes not match the expected pattern:' - '\n{}' - .format(self.name, log_file, - indent(out), indent(error_msg_re))) + "\nFor {}, error message ({}):" + "\n{}" + "\nDoes not match the expected pattern:" + "\n{}".format( + self.name, log_file, indent(out), indent(error_msg_re) + ), + ) project_files = OrderedDict() for p in ( # Test that the most regular case (one project, one main) succeeds - Project(project_files, 'single', 'src', - mains=('main_proc.adb', ), - should_succeed=True), - + Project( + project_files, + "single", + "src", + mains=("main_proc.adb",), + should_succeed=True, + ), # We expect an error when there is no main at all - Project(project_files, 'nomain', 'src', - should_succeed=False), - + Project(project_files, "nomain", "src", should_succeed=False), # Likewise when there are too many mains - Project(project_files, 'double', 'src', - mains=('main_proc.adb', 'other_proc.adb'), - should_succeed=False), - + Project( + project_files, + "double", + "src", + mains=("main_proc.adb", "other_proc.adb"), + should_succeed=False, + ), # Likewise when there is one main but it has not been built - Project(project_files, 'no_build', 'src', - mains=('main_proc.adb', ), - build=False, - should_succeed=False), + Project( + project_files, + "no_build", + "src", + mains=("main_proc.adb",), + build=False, + should_succeed=False, + ), ): assert p.name not in project_files project_files[p.name] = p diff --git a/testsuite/tests/Q224-032-several-out-of-line/test.py b/testsuite/tests/Q224-032-several-out-of-line/test.py index 56016eca8..01592a6c1 100644 --- a/testsuite/tests/Q224-032-several-out-of-line/test.py +++ b/testsuite/tests/Q224-032-several-out-of-line/test.py @@ -9,21 +9,35 @@ from SCOV.minicheck import checked_xcov, check_xcov_reports from SUITE.cutils import Wdir -from SUITE.tutils import (exepath_to, gprfor, gprbuild, thistest, - tracename_for, xrun) +from SUITE.tutils import ( + exepath_to, + gprfor, + gprbuild, + thistest, + tracename_for, + xrun, +) -wd = Wdir('tmp_') -main = exepath_to('main') -trace = tracename_for('main') +wd = Wdir("tmp_") +main = exepath_to("main") +trace = tracename_for("main") -gpr = gprfor(['main.cpp'], srcdirs='..', langs=['C', 'C++']) +gpr = gprfor(["main.cpp"], srcdirs="..", langs=["C", "C++"]) gprbuild(gpr) -xrun([main], 'run.log') -checked_xcov(['coverage', '-P{}'.format(gpr), '-cstmt', '-axcov', - '--output-dir=.', trace], - 'coverage.log') -check_xcov_reports('.', {'bar.c.xcov': {'+': {4}}}) +xrun([main], "run.log") +checked_xcov( + [ + "coverage", + "-P{}".format(gpr), + "-cstmt", + "-axcov", + "--output-dir=.", + trace, + ], + "coverage.log", +) +check_xcov_reports(".", {"bar.c.xcov": {"+": {4}}}) thistest.result() diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py index 6a4c75d23..8b7aa4ddc 100644 --- a/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py @@ -19,33 +19,49 @@ def try_run(cmd): p = Run(cmd) thistest.fail_if( p.status != 0, - 'Unexpected failure.\n' - 'Command was:\n' - '%s\n' - 'Output was:\n' - '%s' % (' '.join(cmd), p.out)) + "Unexpected failure.\n" + "Command was:\n" + "%s\n" + "Output was:\n" + "%s" % (" ".join(cmd), p.out), + ) home = os.getcwd() -os.chdir('%s/libfoo' % home) -rm('install', recursive=True) +os.chdir("%s/libfoo" % home) +rm("install", recursive=True) -try_run(['gprbuild', '-f', '-Plibfoo.gpr', '-p']) -try_run(['gprinstall', '-f', '-Plibfoo.gpr', '-p', - '--prefix=install', '--project-subdir=gpr']) +try_run(["gprbuild", "-f", "-Plibfoo.gpr", "-p"]) +try_run( + [ + "gprinstall", + "-f", + "-Plibfoo.gpr", + "-p", + "--prefix=install", + "--project-subdir=gpr", + ] +) -os.chdir('%s/app' % home) +os.chdir("%s/app" % home) -try_run(['gprbuild', '-f', '-Pdefault.gpr', '-p']) -try_run(['gnatcov', 'run', 'obj/main']) +try_run(["gprbuild", "-f", "-Pdefault.gpr", "-p"]) +try_run(["gnatcov", "run", "obj/main"]) # The very goal of this testcase is to compute code coverage for a unit that # belongs to a project installed with gprinstall, so we need to enable the # processing of externally built projects. -try_run(['gnatcov', 'coverage', - '--annotate=xcov', - '--level=stmt', - '-Pdefault', '--projects=libfoo', '--externally-built-projects', - 'main.trace']) +try_run( + [ + "gnatcov", + "coverage", + "--annotate=xcov", + "--level=stmt", + "-Pdefault", + "--projects=libfoo", + "--externally-built-projects", + "main.trace", + ] +) thistest.result() diff --git a/testsuite/tests/Q327-016-glob-ignore/test.py b/testsuite/tests/Q327-016-glob-ignore/test.py index 58555d4c7..8a7d56608 100644 --- a/testsuite/tests/Q327-016-glob-ignore/test.py +++ b/testsuite/tests/Q327-016-glob-ignore/test.py @@ -11,29 +11,30 @@ from SUITE.tutils import gprfor -src_dir = os.path.abspath('src') -ignore_list = os.path.abspath('ignore.list') +src_dir = os.path.abspath("src") +ignore_list = os.path.abspath("ignore.list") -wd = Wdir('tmp_') +wd = Wdir("tmp_") # Produce a report with specific patterns to ignore some source files build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(['main.adb'], srcdirs=src_dir)), - covlevel='stmt', - mains=['main'], - ignored_source_files=['@' + ignore_list], - extra_coverage_args=['-a', 'xcov', '--output-dir=.']) + gprsw=GPRswitches(root_project=gprfor(["main.adb"], srcdirs=src_dir)), + covlevel="stmt", + mains=["main"], + ignored_source_files=["@" + ignore_list], + extra_coverage_args=["-a", "xcov", "--output-dir=."], +) # Check we have the expected reports check_xcov_reports( - '.', + ".", { - 'main.adb.xcov': {'+': {6, 7}}, - 'pkg_a.adb.xcov': {'+': {6}}, - 'pkg_a.ads.xcov': {}, - 'pkg_b.ads.xcov': {}, - 'pkg_c.ads.xcov': {}, + "main.adb.xcov": {"+": {6, 7}}, + "pkg_a.adb.xcov": {"+": {6}}, + "pkg_a.ads.xcov": {}, + "pkg_b.ads.xcov": {}, + "pkg_c.ads.xcov": {}, }, ) thistest.result() diff --git a/testsuite/tests/Q329-018-create-output-dir/test.py b/testsuite/tests/Q329-018-create-output-dir/test.py index 6ab6aa9f8..4f7f941e5 100644 --- a/testsuite/tests/Q329-018-create-output-dir/test.py +++ b/testsuite/tests/Q329-018-create-output-dir/test.py @@ -7,27 +7,29 @@ from SUITE.tutils import gprfor, xcov -src_dir = os.path.abspath('.') -wd = Wdir('tmp_') -output_dir = os.path.join('report', 'foo') +src_dir = os.path.abspath(".") +wd = Wdir("tmp_") +output_dir = os.path.join("report", "foo") # Generate a project for our sources, build it and generate a trace for it xcov_args = build_and_run( - gprsw=GPRswitches(root_project=gprfor(['foo.adb'], srcdirs=src_dir)), - covlevel='stmt', - mains=['foo'], - extra_coverage_args=['-axcov', '--output-dir={}'.format(output_dir)]) + gprsw=GPRswitches(root_project=gprfor(["foo.adb"], srcdirs=src_dir)), + covlevel="stmt", + mains=["foo"], + extra_coverage_args=["-axcov", "--output-dir={}".format(output_dir)], +) # Now, try to produce a report in a directory that does not exist (even its # parent does not exist!). -assert not os.path.exists('report') -xcov(xcov_args, 'coverage.log') +assert not os.path.exists("report") +xcov(xcov_args, "coverage.log") # Check that gnatcov reports that it creates these directories thistest.fail_if( - 'info: creating output path ' not in contents_of('coverage.log'), - 'gnatcov does not say it is creating directories, it should') + "info: creating output path " not in contents_of("coverage.log"), + "gnatcov does not say it is creating directories, it should", +) # Finally, check we have the expected reports -check_xcov_reports(output_dir, {'foo.adb.xcov': {'+': {5}}}) +check_xcov_reports(output_dir, {"foo.adb.xcov": {"+": {5}}}) thistest.result() diff --git a/testsuite/tests/Q519-013-decision-map/test.py b/testsuite/tests/Q519-013-decision-map/test.py index f194bba52..316f9d08d 100644 --- a/testsuite/tests/Q519-013-decision-map/test.py +++ b/testsuite/tests/Q519-013-decision-map/test.py @@ -5,20 +5,20 @@ from SUITE.tutils import exepath_to, gprbuild, gprfor, thistest, xcov -src_dir = os.path.abspath('.') -wd = Wdir('tmp_') -exe_path = exepath_to('foo') -dmap_path = exe_path + '.dmap' +src_dir = os.path.abspath(".") +wd = Wdir("tmp_") +exe_path = exepath_to("foo") +dmap_path = exe_path + ".dmap" # Generate a project for our sources, build it and generate a decision map for # foo.adb -prj_file = gprfor(['foo.adb'], srcdirs=src_dir, objdir='.') +prj_file = gprfor(["foo.adb"], srcdirs=src_dir, objdir=".") gprbuild(prj_file) -xcov(['map-routines', '--scos=bar.ali', exe_path]) -xcov(['dump-trace', dmap_path], out='dump-trace.txt') +xcov(["map-routines", "--scos=bar.ali", exe_path]) +xcov(["dump-trace", dmap_path], out="dump-trace.txt") -dump_trace = contents_of('dump-trace.txt') +dump_trace = contents_of("dump-trace.txt") pattern = """\ Kind: DECISION_MAP @@ -28,9 +28,9 @@ thistest.fail_if( not re.match(pattern, dump_trace, re.DOTALL), 'Could not match "gnatcov dump-trace" output:\n' - '{}\n' - 'against the expected pattern:\n' - '{}\n'.format(indent(dump_trace), indent(pattern)) + "{}\n" + "against the expected pattern:\n" + "{}\n".format(indent(dump_trace), indent(pattern)), ) thistest.result() diff --git a/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py b/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py index 37abeb5d1..22977477b 100644 --- a/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py +++ b/testsuite/tests/Q614-037-ckpt-pkg-renames/test.py @@ -7,30 +7,35 @@ from SUITE.tutils import gprfor, thistest, xcov -src_dir = os.path.abspath('.') -wd = Wdir('tmp_') +src_dir = os.path.abspath(".") +wd = Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(['main.adb'], srcdirs=src_dir, - objdir='.')), - gpr_obj_dir='.', - covlevel='stmt', - mains=['main'], - extra_coverage_args=['--save-checkpoint=main.ckpt'], - scos=['bar', 'foo', 'main']) -xcov(['coverage', '-cstmt', '-axcov', '-Cmain.ckpt']) + gprsw=GPRswitches( + root_project=gprfor(["main.adb"], srcdirs=src_dir, objdir=".") + ), + gpr_obj_dir=".", + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--save-checkpoint=main.ckpt"], + scos=["bar", "foo", "main"], +) +xcov(["coverage", "-cstmt", "-axcov", "-Cmain.ckpt"]) -expected_reports = ['foo.adb.xcov', 'main.adb.xcov'] +expected_reports = ["foo.adb.xcov", "main.adb.xcov"] if thistest.options.trace_mode == "src": - expected_reports += ['bar.ads.xcov', 'foo.ads.xcov'] + expected_reports += ["bar.ads.xcov", "foo.ads.xcov"] expected_reports.sort() -got_reports = sorted(glob.glob('*.xcov')) +got_reports = sorted(glob.glob("*.xcov")) thistest.fail_if( got_reports != expected_reports, - ('Expected the following reports: {}\n' - 'But got instead: {}'.format( - expected_reports, got_reports)) + ( + "Expected the following reports: {}\n" + "But got instead: {}".format( + expected_reports, got_reports + ) + ), ) thistest.result() diff --git a/testsuite/tests/Q901-012-report-title/test.py b/testsuite/tests/Q901-012-report-title/test.py index 08be60116..567da2454 100644 --- a/testsuite/tests/Q901-012-report-title/test.py +++ b/testsuite/tests/Q901-012-report-title/test.py @@ -7,42 +7,44 @@ from SUITE.tutils import gprfor, thistest, xcov -src_dir = os.path.abspath('.') -wd = Wdir('tmp_') +src_dir = os.path.abspath(".") +wd = Wdir("tmp_") xcov_args = build_and_run( - gprsw=GPRswitches(root_project=gprfor(['foo.adb'], srcdirs=src_dir, - objdir='.')), - gpr_obj_dir='.', - covlevel='stmt', - mains=['foo'], + gprsw=GPRswitches( + root_project=gprfor(["foo.adb"], srcdirs=src_dir, objdir=".") + ), + gpr_obj_dir=".", + covlevel="stmt", + mains=["foo"], extra_coverage_args=[], - scos=['foo']) + scos=["foo"], +) def run_checks(name, report_title, prefix): - html_dir = '{}-html'.format(name) + html_dir = "{}-html".format(name) args = list(xcov_args) if report_title is None: pass else: - args.append('--report-title={}'.format(report_title)) + args.append("--report-title={}".format(report_title)) - xcov(args + ['-ahtml', '--output-dir={}'.format(html_dir)]) + xcov(args + ["-ahtml", "--output-dir={}".format(html_dir)]) def do_match(title, dirname, filename): path = os.path.join(dirname, filename) - text = '{}'.format(title) + text = "{}".format(title) thistest.fail_if( not match(re.escape(text), path), - 'Could not match {} in {}'.format(repr(text), path) + "Could not match {} in {}".format(repr(text), path), ) - do_match(prefix + 'GNATcoverage Report', html_dir, 'index.html') + do_match(prefix + "GNATcoverage Report", html_dir, "index.html") -run_checks('none', None, '') -run_checks('empty', '', '') -run_checks('full', 'My in conjunction' - ' with --units to specify units of interest.' - '\nwarning: Using option --scos with source trace files has no effect.' - '\nPlease consider using option --sid or -P in conjunction' - ' with --units to specify units of interest.') - -check("trace_mix", - coverage_args=['--mix-trace-kind', - '--scos', 'obj/main.ali', - '--sid', 'obj/main.sid', - src_trace, bin_trace], - expected_results=expected_log, - expect_failure=False) + "warning: Mixing source traces and binary traces is not supported. " + "Please only use a single kind of traces." + "\nwarning: ignoring duplicate SCOs for main.adb (from main.ali)" + "\nwarning: previous SCOs for this unit came from instrumenting main.adb" + "\nwarning: Using option --sid with binary trace files has no effect." + "\nPlease consider using option --scos or -P in conjunction" + " with --units to specify units of interest." + "\nwarning: Using option --scos with source trace files has no effect." + "\nPlease consider using option --sid or -P in conjunction" + " with --units to specify units of interest." +) + +check( + "trace_mix", + coverage_args=[ + "--mix-trace-kind", + "--scos", + "obj/main.ali", + "--sid", + "obj/main.sid", + src_trace, + bin_trace, + ], + expected_results=expected_log, + expect_failure=False, +) # Check that without --mix-trace-kind, providing traces of different kind # results in an error. -check("mix_not_allowed", - coverage_args=['--scos', 'obj/main.ali', - '--sid', 'obj/main.sid', - src_trace, bin_trace], - expected_results=r'.*gnatcov(\.exe)?: Mixing source traces and binary' - r' traces is not supported\. Please only use a single kind of traces\.', - expect_failure=True) +check( + "mix_not_allowed", + coverage_args=[ + "--scos", + "obj/main.ali", + "--sid", + "obj/main.sid", + src_trace, + bin_trace, + ], + expected_results=r".*gnatcov(\.exe)?: Mixing source traces and binary" + r" traces is not supported\. Please only use a single kind of traces\.", + expect_failure=True, +) # Check that using --scos in source trace mode emits a warning. # Also produce a checkpoint for later testing. -check("scos_with_src", - coverage_args=['--scos', 'obj/main.ali', '--sid', 'obj/main.sid', - '--save-checkpoint=src.ckpt', - src_trace], - expected_results=re.escape( - 'warning: Using option --scos with source trace files' - ' has no effect.\nPlease consider using option --sid or' - ' -P in conjunction with --units to specify units of' - ' interest.' - ), - expect_failure=False) +check( + "scos_with_src", + coverage_args=[ + "--scos", + "obj/main.ali", + "--sid", + "obj/main.sid", + "--save-checkpoint=src.ckpt", + src_trace, + ], + expected_results=re.escape( + "warning: Using option --scos with source trace files" + " has no effect.\nPlease consider using option --sid or" + " -P in conjunction with --units to specify units of" + " interest." + ), + expect_failure=False, +) # Check that using --sid with binary traces emits a warning. # Also produce a checkpoint for later testing. -check("sid_with_bin", - coverage_args=['--scos', 'obj/main.ali', '--sid', 'obj/main.sid', - '--save-checkpoint=bin.ckpt', - bin_trace], - expected_results=re.escape( - 'warning: Using option --sid with binary trace files' - ' has no effect.\nPlease consider using option --scos or' - ' -P in conjunction with --units to specify units of' - ' interest.' - ), - expect_failure=False) +check( + "sid_with_bin", + coverage_args=[ + "--scos", + "obj/main.ali", + "--sid", + "obj/main.sid", + "--save-checkpoint=bin.ckpt", + bin_trace, + ], + expected_results=re.escape( + "warning: Using option --sid with binary trace files" + " has no effect.\nPlease consider using option --scos or" + " -P in conjunction with --units to specify units of" + " interest." + ), + expect_failure=False, +) # Check that mixing tarce kinds through checkpoints is rejected -check("mixed_checkpoint", - coverage_args=['-Csrc.ckpt', '-Cbin.ckpt'], - expected_results=r'.*gnatcov(\.exe)?: Mixing source traces and binary' - r' traces is not supported\. Please only use a single kind of traces\.', - expect_failure=True) +check( + "mixed_checkpoint", + coverage_args=["-Csrc.ckpt", "-Cbin.ckpt"], + expected_results=r".*gnatcov(\.exe)?: Mixing source traces and binary" + r" traces is not supported\. Please only use a single kind of traces\.", + expect_failure=True, +) thistest.result() diff --git a/testsuite/tests/S529-038-isi-ckpt/test.py b/testsuite/tests/S529-038-isi-ckpt/test.py index c233cc1f0..5d967840e 100644 --- a/testsuite/tests/S529-038-isi-ckpt/test.py +++ b/testsuite/tests/S529-038-isi-ckpt/test.py @@ -18,23 +18,23 @@ from SUITE.tutils import gprfor, srctracename_for, xcov -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") def main(i): - return 'main{}'.format(i) + return "main{}".format(i) def sid(i): - return 'i{}.sid'.format(i) + return "i{}.sid".format(i) def ckpt(i): - return 'c{}.ckpt'.format(i) + return "c{}.ckpt".format(i) def trace(i): - return srctracename_for('main{}'.format(i)) + return srctracename_for("main{}".format(i)) def check_error(argv, log_name, expected_error): @@ -44,55 +44,72 @@ def check_error(argv, log_name, expected_error): expected_re = re.compile( # Regexp to accommodate output differences between the various # supported platforms. - '[^\n]*gnatcov[^\n]*: {}'.format(re.escape(expected_error))) + "[^\n]*gnatcov[^\n]*: {}".format(re.escape(expected_error)) + ) - thistest.fail_if(p.status == 0, - 'gnatcov was expected to fail, it did not') + thistest.fail_if(p.status == 0, "gnatcov was expected to fail, it did not") thistest.fail_if( not expected_re.match(actual_error), 'Unexpected output for "gnatcov coverage" ({}). Expected:\n' - '{}\n' - 'but got:\n' - '{}'.format(log_name, - indent(repr(expected_re.pattern)), - indent(actual_error))) + "{}\n" + "but got:\n" + "{}".format( + log_name, indent(repr(expected_re.pattern)), indent(actual_error) + ), + ) -gpr = gprfor(['main1.adb', 'main2.adb'], srcdirs='..') +gpr = gprfor(["main1.adb", "main2.adb"], srcdirs="..") # Prepare material for the checks: instrument both main1 and main2, produce # traces and create consolidation checkpoints for them. for i in (1, 2): - sid_file = 'obj/main{}.sid'.format(i) + sid_file = "obj/main{}.sid".format(i) build_run_and_coverage( gprsw=GPRswitches(root_project=gpr, units=[main(i)]), - covlevel='stmt+mcdc', + covlevel="stmt+mcdc", mains=[main(i)], - extra_coverage_args=[ - '--save-checkpoint', ckpt(i), - '--sid', sid_file], - trace_mode='src') + extra_coverage_args=["--save-checkpoint", ckpt(i), "--sid", sid_file], + trace_mode="src", + ) cp(sid_file, sid(i)) # Check that gnatcov complains when passing a consolidation checkpoint as an # SID file. -check_error(argv=['coverage', '--annotate=xcov', '--level=stmt+mcdc', - '--sid', ckpt(1), trace(1)], - log_name='ckpt_as_sid.log', - expected_error=('invalid Source Instrumentation Data (SID) file ' - '{}, name of file should have .sid extension' - .format(ckpt(1)))) +check_error( + argv=[ + "coverage", + "--annotate=xcov", + "--level=stmt+mcdc", + "--sid", + ckpt(1), + trace(1), + ], + log_name="ckpt_as_sid.log", + expected_error=( + "invalid Source Instrumentation Data (SID) file " + "{}, name of file should have .sid extension".format(ckpt(1)) + ), +) # Check that gnatcov complains when passing an SID file as a consolidation # checkpoint. -check_error(argv=['coverage', '--level=stmt+mcdc', - '--checkpoint', sid(1), - '--checkpoint', sid(2), - '--save-checkpoint', 'consolidated.ckpt'], - log_name='sid_as_ckpt.log', - expected_error='{} is a Source Instrumentation Data (SID) while a' - ' checkpoint was expected'.format(sid(1))) +check_error( + argv=[ + "coverage", + "--level=stmt+mcdc", + "--checkpoint", + sid(1), + "--checkpoint", + sid(2), + "--save-checkpoint", + "consolidated.ckpt", + ], + log_name="sid_as_ckpt.log", + expected_error="{} is a Source Instrumentation Data (SID) while a" + " checkpoint was expected".format(sid(1)), +) # Finally, check that information from SID files does not leak into @@ -102,11 +119,21 @@ def check_error(argv, log_name, expected_error): # Here, even though c1.ckpt was produced while i1.sid was loaded, one must # provide i1.sid in order to decode main1.srctrace: loading c1.ckpt is not # enough. -xcov(['coverage', '-v', '--annotate=xcov', '--level=stmt+mcdc', - '--checkpoint', ckpt(1), trace(1)], - out='leak.log') +xcov( + [ + "coverage", + "-v", + "--annotate=xcov", + "--level=stmt+mcdc", + "--checkpoint", + ckpt(1), + trace(1), + ], + out="leak.log", +) thistest.fail_if( - '[GNATCOV.MISC] discarding source trace entry for unknown instrumented' - ' unit: body of main1' not in lines_of('leak.log')) + "[GNATCOV.MISC] discarding source trace entry for unknown instrumented" + " unit: body of main1" not in lines_of("leak.log") +) thistest.result() diff --git a/testsuite/tests/S619-014-tag-provider-mismatch/test.py b/testsuite/tests/S619-014-tag-provider-mismatch/test.py index 2c743176f..c5f3ff871 100644 --- a/testsuite/tests/S619-014-tag-provider-mismatch/test.py +++ b/testsuite/tests/S619-014-tag-provider-mismatch/test.py @@ -12,37 +12,51 @@ from SUITE.tutils import gprfor, xcov -wd = Wdir('tmp_') +wd = Wdir("tmp_") # First, create a checkpoint using the default tag provider -ckpt = 'c.ckpt' +ckpt = "c.ckpt" build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(['main.adb'], srcdirs='..')), - covlevel='stmt+decision', - mains=['main'], - extra_coverage_args=['--save-checkpoint', ckpt]) + gprsw=GPRswitches(root_project=gprfor(["main.adb"], srcdirs="..")), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["--save-checkpoint", ckpt], +) # Now try to load it while asking for the non-default tag provider. Don't pass # the trace file, as we are interested only in checkpoint processing. -xcov(['coverage', '-cstmt+decision', '-axcov', '-Sinstance', '-C', ckpt, - '--output-dir=.'], - out='consolidate.log') - -expected = ('warning: cannot merge coverage information from {} as it is' - ' separated by default'.format(ckpt)) -actual = contents_of('consolidate.log').strip() -thistest.fail_if(expected != actual, - 'Unexpected output for "gnatcov coverage". Expected:\n' - '{}\n' - 'but got:\n' - '{}'.format(indent(expected), indent(actual))) +xcov( + [ + "coverage", + "-cstmt+decision", + "-axcov", + "-Sinstance", + "-C", + ckpt, + "--output-dir=.", + ], + out="consolidate.log", +) + +expected = ( + "warning: cannot merge coverage information from {} as it is" + " separated by default".format(ckpt) +) +actual = contents_of("consolidate.log").strip() +thistest.fail_if( + expected != actual, + 'Unexpected output for "gnatcov coverage". Expected:\n' + "{}\n" + "but got:\n" + "{}".format(indent(expected), indent(actual)), +) expected_cov = { - 'main.adb.xcov': {}, - 'generic_hello.adb.xcov': {}, + "main.adb.xcov": {}, + "generic_hello.adb.xcov": {}, } if thistest.options.trace_mode == "src": expected_cov["generic_hello.ads.xcov"] = {} -check_xcov_reports('.', expected_cov, discard_empty=False) +check_xcov_reports(".", expected_cov, discard_empty=False) thistest.result() diff --git a/testsuite/tests/S621-026-mcdc-ckpt/test.py b/testsuite/tests/S621-026-mcdc-ckpt/test.py index fd2599a7c..1158379d6 100644 --- a/testsuite/tests/S621-026-mcdc-ckpt/test.py +++ b/testsuite/tests/S621-026-mcdc-ckpt/test.py @@ -7,27 +7,39 @@ from SUITE.tutils import gprfor, xcov -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") -gpr = gprfor(['main1.adb', 'main2.adb'], srcdirs='..') +gpr = gprfor(["main1.adb", "main2.adb"], srcdirs="..") # Create a checkpoint for the execution of "main1" and another for "main2" for i in (1, 2): build_run_and_coverage( gprsw=GPRswitches(root_project=gpr), - covlevel='stmt+mcdc', - mains=['main{}'.format(i)], - extra_coverage_args=['--save-checkpoint=c{}.ckpt'.format(i)], - scos=['obj/main{}'.format(i)]) + covlevel="stmt+mcdc", + mains=["main{}".format(i)], + extra_coverage_args=["--save-checkpoint=c{}.ckpt".format(i)], + scos=["obj/main{}".format(i)], + ) # Now consolidate both. c1.ckpt comes first in order to check that, when # c2.ckpt is loaded, all SCOs in it, and in particular the ones in evaluation # vectors for MC/DC, are properly remapped. -xcov(['coverage', '--annotate=xcov', '--level=stmt+mcdc', - '--checkpoint=c1.ckpt', '--checkpoint=c2.ckpt']) - -check_xcov_reports('.', { - 'main1.adb.xcov': {'+': {5}}, - 'main2.adb.xcov': {'+': {5, 7, 11, 12, 13, 15}, '!': {4}}}) +xcov( + [ + "coverage", + "--annotate=xcov", + "--level=stmt+mcdc", + "--checkpoint=c1.ckpt", + "--checkpoint=c2.ckpt", + ] +) + +check_xcov_reports( + ".", + { + "main1.adb.xcov": {"+": {5}}, + "main2.adb.xcov": {"+": {5, 7, 11, 12, 13, 15}, "!": {4}}, + }, +) thistest.result() diff --git a/testsuite/tests/S820-013-ckpt-dup-scos/test.py b/testsuite/tests/S820-013-ckpt-dup-scos/test.py index 312151534..7f129b313 100644 --- a/testsuite/tests/S820-013-ckpt-dup-scos/test.py +++ b/testsuite/tests/S820-013-ckpt-dup-scos/test.py @@ -6,27 +6,42 @@ from SUITE.context import thistest from SUITE.cutils import Wdir -from SUITE.tutils import (exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun) +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) -wd = Wdir('tmp_') +wd = Wdir("tmp_") -exe = exepath_to('main') -trace = tracename_for('main') -gpr = gprfor(['main.c'], srcdirs='..') +exe = exepath_to("main") +trace = tracename_for("main") +gpr = gprfor(["main.c"], srcdirs="..") # Build the test program and generate a trace file gprbuild(gpr) xrun([exe]) # Load the duplicated ALIs and create a checkpoint -ckpt = 'c.ckpt' -xcov(['coverage', '-c', 'stmt', '--save-checkpoint', ckpt, - '--scos=obj/main.c.gli', '--scos=obj/foo.c.gli', - trace]) +ckpt = "c.ckpt" +xcov( + [ + "coverage", + "-c", + "stmt", + "--save-checkpoint", + ckpt, + "--scos=obj/main.c.gli", + "--scos=obj/foo.c.gli", + trace, + ] +) # Now try to generate a report from this checkpoint -xcov(['coverage', '-a', 'xcov', '-c', 'stmt', '--checkpoint', ckpt]) +xcov(["coverage", "-a", "xcov", "-c", "stmt", "--checkpoint", ckpt]) thistest.result() diff --git a/testsuite/tests/SB06-033-homonyms/test.py b/testsuite/tests/SB06-033-homonyms/test.py index e657d792e..4f0ea5de7 100644 --- a/testsuite/tests/SB06-033-homonyms/test.py +++ b/testsuite/tests/SB06-033-homonyms/test.py @@ -15,7 +15,7 @@ from SUITE.cutils import Wdir, contents_of -wd = Wdir('tmp_') +wd = Wdir("tmp_") log_dir = os.getcwd() wd.to_homedir() @@ -30,45 +30,68 @@ def try_run(cmd, out_file): out = contents_of(out_file) thistest.fail_if( p.status != 0, - 'Unexpected failure.\n' - 'Command was:\n' - '%s\n' - 'Output was:\n' - '%s' % (' '.join(cmd), out)) + "Unexpected failure.\n" + "Command was:\n" + "%s\n" + "Output was:\n" + "%s" % (" ".join(cmd), out), + ) return out -os.chdir(in_home('libfoo')) -rm('install', recursive=True) - -try_run(['gprbuild', '-f', '-Plibfoo.gpr', '-p'], 'gprbuild-libfoo.txt') -try_run(['gprinstall', '-f', '-Plibfoo.gpr', '-p', - '--prefix=install', '--project-subdir=gpr'], - 'gprinstall.txt') +os.chdir(in_home("libfoo")) +rm("install", recursive=True) + +try_run(["gprbuild", "-f", "-Plibfoo.gpr", "-p"], "gprbuild-libfoo.txt") +try_run( + [ + "gprinstall", + "-f", + "-Plibfoo.gpr", + "-p", + "--prefix=install", + "--project-subdir=gpr", + ], + "gprinstall.txt", +) -os.chdir(in_home('app')) +os.chdir(in_home("app")) -try_run(['gprbuild', '-f', '-Pdefault.gpr', '-p'], 'gprbuild-app.txt') -try_run(['gnatcov', 'run', 'obj/main'], 'gnatcov-run.txt') +try_run(["gprbuild", "-f", "-Pdefault.gpr", "-p"], "gprbuild-app.txt") +try_run(["gnatcov", "run", "obj/main"], "gnatcov-run.txt") # The very goal of this testcase is to compute code coverage for a unit that # belongs to a project installed with gprinstall, so we need to enable the # processing of externally built projects. -log_file = 'gnatcov-coverage.txt' -log = try_run(['gnatcov', 'coverage', - '--annotate=xcov', - '--level=stmt', - '-Pdefault', '--externally-built-projects', - 'main.trace'], log_file) +log_file = "gnatcov-coverage.txt" +log = try_run( + [ + "gnatcov", + "coverage", + "--annotate=xcov", + "--level=stmt", + "-Pdefault", + "--externally-built-projects", + "main.trace", + ], + log_file, +) thistest.fail_if_no_match( '"gnatcov output" ({})'.format(log_file), - 'Warning: same base name for files:' - '\r?\n [^\n]+{}' - '\r?\n [^\n]+{}' - .format(os.path.join('SB06-033-homonyms', 'libfoo', 'install', 'include', - 'libfoo', 'lib.adb'), - os.path.join('SB06-033-homonyms', 'libfoo', 'lib.adb')), - log + "Warning: same base name for files:" + "\r?\n [^\n]+{}" + "\r?\n [^\n]+{}".format( + os.path.join( + "SB06-033-homonyms", + "libfoo", + "install", + "include", + "libfoo", + "lib.adb", + ), + os.path.join("SB06-033-homonyms", "libfoo", "lib.adb"), + ), + log, ) thistest.result() diff --git a/testsuite/tests/T117-007-intf-thunks/test.py b/testsuite/tests/T117-007-intf-thunks/test.py index b053c1eca..670ab2bcb 100644 --- a/testsuite/tests/T117-007-intf-thunks/test.py +++ b/testsuite/tests/T117-007-intf-thunks/test.py @@ -6,19 +6,24 @@ from SUITE.tutils import thistest, gprfor -tmp_ = Wdir('tmp_') +tmp_ = Wdir("tmp_") -gpr = gprfor(srcdirs='../src', mains=['ut_main.adb']) -build_run_and_coverage(gprsw=GPRswitches(root_project=gpr), - covlevel='stmt', mains=['ut_main'], - extra_coverage_args=['--annotate=xcov']) +gpr = gprfor(srcdirs="../src", mains=["ut_main.adb"]) +build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt", + mains=["ut_main"], + extra_coverage_args=["--annotate=xcov"], +) # We do not expect uncovered lines in package_a, as the code generated # for the interface type declaration is thunk code, which is to be # ignored for coverage purposes. -report_package_a = contents_of('obj/package_a.ads.xcov') -thistest.fail_if(re.search(string=report_package_a, pattern=r'-:'), - "unexpected uncovered code") +report_package_a = contents_of("obj/package_a.ads.xcov") +thistest.fail_if( + re.search(string=report_package_a, pattern=r"-:"), + "unexpected uncovered code", +) thistest.result() diff --git a/testsuite/tests/T331-043-native-warn/test.py b/testsuite/tests/T331-043-native-warn/test.py index 2843966da..7340a5bd7 100644 --- a/testsuite/tests/T331-043-native-warn/test.py +++ b/testsuite/tests/T331-043-native-warn/test.py @@ -10,44 +10,49 @@ from SUITE.tutils import gprfor, thistest -tmp = Wdir('tmp') +tmp = Wdir("tmp") # The testsuite automatically disables the warning we want to test: override # this decision just for this testcase. -os.environ.pop('GNATCOV_NO_NATIVE_WARNING', None) +os.environ.pop("GNATCOV_NO_NATIVE_WARNING", None) is_native = not Env().is_cross build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.adb'])), - covlevel='stmt', - mains=['main'], - extra_coverage_args=["-axcov"]) + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) warning_exceprt = ( - 'Support for coverage of non-instrumented native programs is deprecated' + "Support for coverage of non-instrumented native programs is deprecated" ) def check_warning_absent(logfile): - thistest.fail_if(warning_exceprt in contents_of(logfile), - "unexpected warning in {}".format(logfile)) + thistest.fail_if( + warning_exceprt in contents_of(logfile), + "unexpected warning in {}".format(logfile), + ) def check_warning_present(logfile): - thistest.fail_if(warning_exceprt not in contents_of(logfile), - "missing warning in {}".format(logfile)) + thistest.fail_if( + warning_exceprt not in contents_of(logfile), + "missing warning in {}".format(logfile), + ) # Depending on the trace mode and the target, check the presence/absence of the # warning. -if thistest.options.trace_mode == 'src': - check_warning_absent('instrument.log') +if thistest.options.trace_mode == "src": + check_warning_absent("instrument.log") elif is_native: - check_warning_present('main_output.txt') + check_warning_present("main_output.txt") else: - check_warning_absent('main_output.txt') -check_warning_absent('coverage.log') + check_warning_absent("main_output.txt") +check_warning_absent("coverage.log") thistest.result() diff --git a/testsuite/tests/T528-018-dup-proj-crash/test.py b/testsuite/tests/T528-018-dup-proj-crash/test.py index d2fbe5e0a..6d5c56229 100644 --- a/testsuite/tests/T528-018-dup-proj-crash/test.py +++ b/testsuite/tests/T528-018-dup-proj-crash/test.py @@ -10,18 +10,25 @@ from SUITE.tutils import gprfor -tmp = Wdir('tmp_') -p1 = gprfor(prjid='p1', srcdirs=['../src-p1'], objdir='obj-p1', - mains=[], langs=['Ada']) -p2 = gprfor(prjid='p2', srcdirs=['../src-p2'], objdir='obj-p2', - deps=['p1'], mains=['p2.adb']) +tmp = Wdir("tmp_") +p1 = gprfor( + prjid="p1", srcdirs=["../src-p1"], objdir="obj-p1", mains=[], langs=["Ada"] +) +p2 = gprfor( + prjid="p2", + srcdirs=["../src-p2"], + objdir="obj-p2", + deps=["p1"], + mains=["p2.adb"], +) build_run_and_coverage( - gprsw=GPRswitches(root_project=p2, projects=['p1', 'p2']), - covlevel='stmt', - mains=['p2'], - gpr_obj_dir='obj-p2', - extra_coverage_args=['-axcov']) + gprsw=GPRswitches(root_project=p2, projects=["p1", "p2"]), + covlevel="stmt", + mains=["p2"], + gpr_obj_dir="obj-p2", + extra_coverage_args=["-axcov"], +) thistest.result() diff --git a/testsuite/tests/T611-027-dump-units-to/test.py b/testsuite/tests/T611-027-dump-units-to/test.py index 6ce8730fc..9c1fdb1b9 100644 --- a/testsuite/tests/T611-027-dump-units-to/test.py +++ b/testsuite/tests/T611-027-dump-units-to/test.py @@ -9,15 +9,16 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Generate a project, instrument it and run it -p = gprfor(mains=['main.adb'], srcdirs=['..']) +p = gprfor(mains=["main.adb"], srcdirs=[".."]) xcov_args = build_and_run( gprsw=GPRswitches(root_project=p), - covlevel='stmt', - mains=['main'], - extra_coverage_args=[]) + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], +) xcov_args_no_trace = xcov_args[:-1] trace_file = xcov_args[-1] @@ -34,19 +35,20 @@ def check_output(output_file, expected_content, regexp=False): :param bool regexp: Whether to match as a regexp (by default, check content equality). """ - checker = (thistest.fail_if_no_match - if regexp - else thistest.fail_if_not_equal) + checker = ( + thistest.fail_if_no_match if regexp else thistest.fail_if_not_equal + ) checker( '"gnatcov coverage" output ({})'.format(output_file), expected_content, - # Canonicalize to Unix-style line endings to have cross-platform checks - contents_of(output_file).replace('\r\n', '\n')) + contents_of(output_file).replace("\r\n", "\n"), + ) -def run_and_check(args, output_file, expected_content, regexp=False, - success_expected=True): +def run_and_check( + args, output_file, expected_content, regexp=False, success_expected=True +): """ Run gnatcov with the given arguments. @@ -63,132 +65,157 @@ def run_and_check(args, output_file, expected_content, regexp=False, thistest.fail_if( p.status == 0, 'the call to "gnatcov coverage" was expected to fail, yet it' - ' succeeded (see {})'.format(output_file) + " succeeded (see {})".format(output_file), ) check_output(output_file, expected_content, regexp) # Check that --dump-units-to is rejected when used in object coverage mode run_and_check( - ['coverage', '-cinsn', '-aasm', trace_file, '-P', p, '--dump-units-to=-'], - 'objcov.txt', - '.*gnatcov.*: --dump-units-to works in source coverage only', + ["coverage", "-cinsn", "-aasm", trace_file, "-P", p, "--dump-units-to=-"], + "objcov.txt", + ".*gnatcov.*: --dump-units-to works in source coverage only", regexp=True, - success_expected=False) + success_expected=False, +) # Check that nothing is dumped without --dump-units-to -run_and_check(xcov_args + ['-axcov'], 'xcov-nodump.txt', '') +run_and_check(xcov_args + ["-axcov"], "xcov-nodump.txt", "") # Check that when *not* using the "report" format, the list is printed on # stdout with --dump-units-to=-. -run_and_check(xcov_args + ['-axcov', '--dump-units-to=-'], - 'xcov-stdout1.txt', 'main\npkg\n') -run_and_check(xcov_args + ['-axcov', '--units=main', '--dump-units-to=-'], - 'xcov-stdout2.txt', 'main\n') +run_and_check( + xcov_args + ["-axcov", "--dump-units-to=-"], + "xcov-stdout1.txt", + "main\npkg\n", +) +run_and_check( + xcov_args + ["-axcov", "--units=main", "--dump-units-to=-"], + "xcov-stdout2.txt", + "main\n", +) # Check that the list is written to the designated file (foo1.txt) and not on # the standard output with --dump-units-to=foo1.txt. -run_and_check(xcov_args + ['-axcov', '--dump-units-to=foo1.txt'], - 'xcov-foo.txt', '') -check_output('foo1.txt', 'main\npkg\n') +run_and_check( + xcov_args + ["-axcov", "--dump-units-to=foo1.txt"], "xcov-foo.txt", "" +) +check_output("foo1.txt", "main\npkg\n") # Check that with --dump-units-to=-, the list is included in the "report" # annotation format... REPORT_PATTERN = ( - '(.|\n)*=+' - '\n== 4\\. UNITS OF INTEREST ==' - '\n=+' - '\n' - '\nmain' - '\npkg' - '\n' - '\n\\*\\* END OF REPORT \\*\\*' - '\n(.|\n)*') + "(.|\n)*=+" + "\n== 4\\. UNITS OF INTEREST ==" + "\n=+" + "\n" + "\nmain" + "\npkg" + "\n" + "\n\\*\\* END OF REPORT \\*\\*" + "\n(.|\n)*" +) # ... on the standard output... run_and_check( - xcov_args + ['-areport', '--dump-units-to=-'], 'report-stdout.txt', - REPORT_PATTERN, regexp=True) + xcov_args + ["-areport", "--dump-units-to=-"], + "report-stdout.txt", + REPORT_PATTERN, + regexp=True, +) # ... or in the designated report file run_and_check( - xcov_args + ['-areport', '--dump-units-to=-', '--output=report1.txt'], - 'report-stdout.txt', '') -check_output('report1.txt', REPORT_PATTERN, regexp=True) + xcov_args + ["-areport", "--dump-units-to=-", "--output=report1.txt"], + "report-stdout.txt", + "", +) +check_output("report1.txt", REPORT_PATTERN, regexp=True) # Check that even with "-a report", the list is put in the designated file # (foo2.txt) with --dump-units-to=foo2.txt. Check also that the report does # *not* contain the list of units of interest. run_and_check( - xcov_args + ['-areport', '--dump-units-to=foo2.txt', - '--output=report2.txt'], - 'report-redirected.txt', '') + xcov_args + + ["-areport", "--dump-units-to=foo2.txt", "--output=report2.txt"], + "report-redirected.txt", + "", +) check_output( - 'report2.txt', - '(.|\n)*=+' - '\n== 3\\. ANALYSIS SUMMARY ==' - '\n=+' - '\n' - '\nNo STMT violation.' - '\n' - '\n\\*\\* END OF REPORT \\*\\*' - '\n(.|\n)*', - regexp=True) -check_output('foo2.txt', 'main\npkg\n') + "report2.txt", + "(.|\n)*=+" + "\n== 3\\. ANALYSIS SUMMARY ==" + "\n=+" + "\n" + "\nNo STMT violation." + "\n" + "\n\\*\\* END OF REPORT \\*\\*" + "\n(.|\n)*", + regexp=True, +) +check_output("foo2.txt", "main\npkg\n") # Now check that gnatcov refuses to dump the list of units of interest when # --scos or --sid is involved. -if thistest.options.trace_mode == 'bin': - scos_optname = '--scos' - scos_ext = 'ali' +if thistest.options.trace_mode == "bin": + scos_optname = "--scos" + scos_ext = "ali" else: - scos_optname = '--sid' - scos_ext = 'sid' -scos_arg = '{}=obj/main.{}'.format(scos_optname, scos_ext) + scos_optname = "--sid" + scos_ext = "sid" +scos_arg = "{}=obj/main.{}".format(scos_optname, scos_ext) run_and_check( - xcov_args + ['-axcov', '--dump-units-to=.', scos_arg], - 'xcov-scos.txt', - 'We will not be able to dump the list of units of interest: {} is' - ' present\n' - '.*gnatcov.*: Cannot dump the list of names for units of interest: see' - ' above.'.format(scos_optname), + xcov_args + ["-axcov", "--dump-units-to=.", scos_arg], + "xcov-scos.txt", + "We will not be able to dump the list of units of interest: {} is" + " present\n" + ".*gnatcov.*: Cannot dump the list of names for units of interest: see" + " above.".format(scos_optname), regexp=True, - success_expected=False) + success_expected=False, +) # Check that the list of units of interest is written when just creating a # checkpoint and --dump-units-to is passed. run_and_check( - xcov_args + ['--units=main', '--dump-units-to=-', - '--save-checkpoint=c1.ckpt'], - 'ckpt-1.txt', - 'main\n') + xcov_args + + ["--units=main", "--dump-units-to=-", "--save-checkpoint=c1.ckpt"], + "ckpt-1.txt", + "main\n", +) run_and_check( - xcov_args + ['--units=pkg', '--save-checkpoint=c2.ckpt'], - 'ckpt-2.txt', - '') + xcov_args + ["--units=pkg", "--save-checkpoint=c2.ckpt"], "ckpt-2.txt", "" +) # Now check that it is properly reconstitued during checkpoint consolidation run_and_check( - ['coverage', '-cstmt', '-axcov', '--dump-units-to=-', - '-Cc1.ckpt', '-Cc2.ckpt'], - 'ckpt-cons.txt', - 'main\npkg\n') + [ + "coverage", + "-cstmt", + "-axcov", + "--dump-units-to=-", + "-Cc1.ckpt", + "-Cc2.ckpt", + ], + "ckpt-cons.txt", + "main\npkg\n", +) # Finally, check that trying to dump units after loading a checkpoint which # was created using --scos/--sid is rejected. run_and_check( - xcov_args + ['--save-checkpoint=c3.ckpt', scos_arg], - 'ckpt-3.txt', - '') + xcov_args + ["--save-checkpoint=c3.ckpt", scos_arg], "ckpt-3.txt", "" +) run_and_check( - xcov_args_no_trace + ['-axcov', '--dump-units-to=.', '-Cc3.ckpt'], - 'ckpt-cons-invalid.txt', - 'We will not be able to dump the list of units of interest: c3.ckpt does' - ' not contain the list of units \\(produced with --scos or --sid\\)\n' - '.*gnatcov.*: Cannot dump the list of names for units of interest: see' - ' above.', + xcov_args_no_trace + ["-axcov", "--dump-units-to=.", "-Cc3.ckpt"], + "ckpt-cons-invalid.txt", + "We will not be able to dump the list of units of interest: c3.ckpt does" + " not contain the list of units \\(produced with --scos or --sid\\)\n" + ".*gnatcov.*: Cannot dump the list of names for units of interest: see" + " above.", regexp=True, - success_expected=False) + success_expected=False, +) thistest.result() diff --git a/testsuite/tests/T629-012-pragmas/test.py b/testsuite/tests/T629-012-pragmas/test.py index 1d75df8f6..067cb8b9f 100644 --- a/testsuite/tests/T629-012-pragmas/test.py +++ b/testsuite/tests/T629-012-pragmas/test.py @@ -7,21 +7,22 @@ from SUITE.cutils import Wdir, lines_of -wd = Wdir('tmp_') +wd = Wdir("tmp_") # Get the list of pragmas that gnatcov knows -xcov(['dump-pragmas'], out='gnatcov.txt') -gnatcov_names = set(line.strip() for line in lines_of('gnatcov.txt')) +xcov(["dump-pragmas"], out="gnatcov.txt") +gnatcov_names = set(line.strip() for line in lines_of("gnatcov.txt")) # Get the list of pragmas that GNAT knows -xcov(['dump-pragmas', '--gnat-pragmas'], out='gnat.txt') -gnat_names = set(line.strip() for line in lines_of('gnat.txt')) +xcov(["dump-pragmas", "--gnat-pragmas"], out="gnat.txt") +gnat_names = set(line.strip() for line in lines_of("gnat.txt")) # Check that gnatcov knows about all pragmas from gnat_util -missing_names = '\n'.join(sorted(gnat_names - gnatcov_names)) +missing_names = "\n".join(sorted(gnat_names - gnatcov_names)) thistest.fail_if( missing_names, - 'gnatcov does not know about the following pragmas:\n' + missing_names) + "gnatcov does not know about the following pragmas:\n" + missing_names, +) thistest.result() diff --git a/testsuite/tests/T731-036-ckpt-bdd/test.py b/testsuite/tests/T731-036-ckpt-bdd/test.py index bc2c70ffe..b59c345e6 100644 --- a/testsuite/tests/T731-036-ckpt-bdd/test.py +++ b/testsuite/tests/T731-036-ckpt-bdd/test.py @@ -17,7 +17,7 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Generate sources for the test program. The point of this program is to have # one unit (DC_Unit) that generates lots of BDD nodes (i.e. lots of decisions), @@ -47,8 +47,8 @@ end C; end Helper; """ -text_to_file(helper_ads_text, 'helper.ads') -text_to_file(helper_adb_text, 'helper.adb') +text_to_file(helper_ads_text, "helper.ads") +text_to_file(helper_adb_text, "helper.adb") # Emit DC_Unit itself, with 1000 decisions (3 BDD nodes each) dc_unit_ads_text = """ @@ -57,27 +57,26 @@ end DC_Unit; """ dc_unit_adb_text = [ - 'with Helper; use Helper;', - 'package body DC_Unit is', - ' procedure Run is', - ' begin' + "with Helper; use Helper;", + "package body DC_Unit is", + " procedure Run is", + " begin", ] for _ in range(1000): - dc_unit_adb_text.extend([ - ' if (A and then B) or C then', - ' raise Program_Error;', - ' end if;' - ]) -dc_unit_adb_text.extend([ - ' end Run;', - 'end DC_Unit;' -]) -text_to_file(dc_unit_ads_text, 'dc_unit.ads') -list_to_file(dc_unit_adb_text, 'dc_unit.adb') + dc_unit_adb_text.extend( + [ + " if (A and then B) or C then", + " raise Program_Error;", + " end if;", + ] + ) +dc_unit_adb_text.extend([" end Run;", "end DC_Unit;"]) +text_to_file(dc_unit_ads_text, "dc_unit.ads") +list_to_file(dc_unit_adb_text, "dc_unit.adb") # Start the preparation of source excerpts for the Main unit -main_adb_context_clauses = ['with DC_Unit;'] -main_adb_statements = ['DC_Unit.Run;'] +main_adb_context_clauses = ["with DC_Unit;"] +main_adb_statements = ["DC_Unit.Run;"] # Generate sources for the Simple_Unit_* units simple_unit_ads = """ @@ -94,41 +93,49 @@ end Simple_Unit_{n}; """ for n in range(1, 11): - text_to_file(simple_unit_ads.format(n=n), - 'simple_unit_{}.ads'.format(n)) - text_to_file(simple_unit_adb.format(n=n), - 'simple_unit_{}.adb'.format(n)) - main_adb_context_clauses.append('with Simple_Unit_{};'.format(n)) - main_adb_statements.append('Simple_Unit_{}.Run;'.format(n)) + text_to_file(simple_unit_ads.format(n=n), "simple_unit_{}.ads".format(n)) + text_to_file(simple_unit_adb.format(n=n), "simple_unit_{}.adb".format(n)) + main_adb_context_clauses.append("with Simple_Unit_{};".format(n)) + main_adb_statements.append("Simple_Unit_{}.Run;".format(n)) # Finally, generate the Main unit main_adb_sources = ( - main_adb_context_clauses + ['procedure Main is', 'begin'] - + main_adb_statements + ['end Main;'] + main_adb_context_clauses + + ["procedure Main is", "begin"] + + main_adb_statements + + ["end Main;"] ) -list_to_file(main_adb_sources, 'main.adb') +list_to_file(main_adb_sources, "main.adb") # Generate the project file, run the instrumenter, run the program and produce # a checkpoint. -p = gprfor(mains=['main.adb'], srcdirs=['.']) +p = gprfor(mains=["main.adb"], srcdirs=["."]) build_run_and_coverage( gprsw=GPRswitches(root_project=p), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['--save-checkpoint=c0.ckpt'], - extra_gprbuild_args=['-j128']) + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--save-checkpoint=c0.ckpt"], + extra_gprbuild_args=["-j128"], +) # Load the same checkpoint multiple times. This used to create redundant BDDs, # making the checkpoint grow over time. Checking that each loading/saving cycle # does not make the checkpoint grow verifies that this bug is gone. expected_size = None for n in range(5): - prev_checkpoint = 'c{}.ckpt'.format(n) - next_checkpoint = 'c{}.ckpt'.format(n + 1) - ckpt_list = 'ckpt_list_{}.txt'.format(n) + prev_checkpoint = "c{}.ckpt".format(n) + next_checkpoint = "c{}.ckpt".format(n + 1) + ckpt_list = "ckpt_list_{}.txt".format(n) list_to_file([prev_checkpoint] * 50, ckpt_list) - xcov(['coverage', '-cstmt', '-C@{}'.format(ckpt_list), - '--save-checkpoint', next_checkpoint]) + xcov( + [ + "coverage", + "-cstmt", + "-C@{}".format(ckpt_list), + "--save-checkpoint", + next_checkpoint, + ] + ) size = os.path.getsize(next_checkpoint) if expected_size is None: diff --git a/testsuite/tests/T807-011-externally-built-objdir/test.py b/testsuite/tests/T807-011-externally-built-objdir/test.py index d375bd290..67dbbea2f 100644 --- a/testsuite/tests/T807-011-externally-built-objdir/test.py +++ b/testsuite/tests/T807-011-externally-built-objdir/test.py @@ -15,23 +15,24 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") -opslib_gpr = os.path.join('..', 'opslib', 'opslib.gpr') -tests_gpr = os.path.join('..', 'tests.gpr') -tests_obj_dir = os.path.join('..', 'obj') -sid_pattern = os.path.join('..', 'opslib', 'obj-opslib', '*.sid') +opslib_gpr = os.path.join("..", "opslib", "opslib.gpr") +tests_gpr = os.path.join("..", "tests.gpr") +tests_obj_dir = os.path.join("..", "obj") +sid_pattern = os.path.join("..", "opslib", "obj-opslib", "*.sid") -tests_gprsw = GPRswitches(root_project=tests_gpr, - xvars=[('OPSLIB_EXTERNALLY_BUILT', 'true')], - externally_built_projects=True) +tests_gprsw = GPRswitches( + root_project=tests_gpr, + xvars=[("OPSLIB_EXTERNALLY_BUILT", "true")], + externally_built_projects=True, +) # First, instrument and build the opslib library project xcov_instrument( - gprsw=GPRswitches(root_project=opslib_gpr), - covlevel='stmt+decision' + gprsw=GPRswitches(root_project=opslib_gpr), covlevel="stmt+decision" ) -gprbuild(opslib_gpr, trace_mode='src', out='gprbuild-opslib.out') +gprbuild(opslib_gpr, trace_mode="src", out="gprbuild-opslib.out") # Now instrument, build and run the test driver. When run on this test project, # the instrumenter used to remove the instrumented sources in the opslib @@ -40,29 +41,30 @@ # because of the missing buffer units in opslib. build_run_and_coverage( gprsw=tests_gprsw, - covlevel='stmt+decision', - mains=['test_inc'], - extra_coverage_args=['-axcov', '--output-dir=report'], + covlevel="stmt+decision", + mains=["test_inc"], + extra_coverage_args=["-axcov", "--output-dir=report"], gpr_obj_dir=tests_obj_dir, gpr_exe_dir=tests_obj_dir, - trace_mode='src' + trace_mode="src", ) check_xcov_reports( - 'report', - {'ops.ads.xcov': {}, 'ops.adb.xcov': {'+': {4, 5}, '-': {6}}}, + "report", + {"ops.ads.xcov": {}, "ops.adb.xcov": {"+": {4, 5}, "-": {6}}}, discard_empty=False, ) # Re-run the instrumenter on the main, to check that it does not re-create a # SID file for the opslib externall built project. rm(sid_pattern) -xcov_instrument(gprsw=tests_gprsw, covlevel='stmt+decision') +xcov_instrument(gprsw=tests_gprsw, covlevel="stmt+decision") sids = ls(sid_pattern) thistest.fail_if( sids, - '"gnatcov instrument" wrongly re-created SID files: {}' - .format(sorted(sids)), + '"gnatcov instrument" wrongly re-created SID files: {}'.format( + sorted(sids) + ), ) thistest.result() diff --git a/testsuite/tests/T825-010-naming-scheme/test.py b/testsuite/tests/T825-010-naming-scheme/test.py index 1ac650370..48f990391 100644 --- a/testsuite/tests/T825-010-naming-scheme/test.py +++ b/testsuite/tests/T825-010-naming-scheme/test.py @@ -9,10 +9,12 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") p = gprfor( - mains=['main.adb'], prjid='p', srcdirs=['..'], + mains=["main.adb"], + prjid="p", + srcdirs=[".."], extra=""" package Naming is for Spec_Suffix ("Ada") use ".1.ada"; @@ -20,20 +22,24 @@ for Dot_Replacement use "__"; for Body ("main") use "main.adb"; end Naming; - """ + """, ) build_run_and_coverage( gprsw=GPRswitches(root_project=p), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=report'] + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=report"], +) +check_xcov_reports( + "report", + { + "main.adb.xcov": {"+": {5}}, + "p.1.ada.xcov": {}, + "p.2.ada.xcov": {"+": {4}}, + "p__q.1.ada.xcov": {"+": {3}}, + "p__q.2.ada.xcov": {"+": {6}}, + }, + discard_empty=False, ) -check_xcov_reports('report', { - 'main.adb.xcov': {'+': {5}}, - 'p.1.ada.xcov': {}, - 'p.2.ada.xcov': {'+': {4}}, - 'p__q.1.ada.xcov': {'+': {3}}, - 'p__q.2.ada.xcov': {'+': {6}}, -}, discard_empty=False) thistest.result() diff --git a/testsuite/tests/T916-046-bdd-remapping/test.py b/testsuite/tests/T916-046-bdd-remapping/test.py index a51643489..9f98f208a 100644 --- a/testsuite/tests/T916-046-bdd-remapping/test.py +++ b/testsuite/tests/T916-046-bdd-remapping/test.py @@ -13,13 +13,14 @@ from SUITE.tutils import gprfor -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") -p = gprfor(srcdirs=['..'], mains=['main.adb']) +p = gprfor(srcdirs=[".."], mains=["main.adb"]) build_run_and_coverage( gprsw=GPRswitches(root_project=p), - covlevel='stmt+mcdc', - mains=['main'], - extra_coverage_args=['--save-checkpoint=partial.ckpt']) + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["--save-checkpoint=partial.ckpt"], +) thistest.result() diff --git a/testsuite/tests/TA12-013-dump-ignore-src-files/test.py b/testsuite/tests/TA12-013-dump-ignore-src-files/test.py index d60d9dcb3..7a758661c 100644 --- a/testsuite/tests/TA12-013-dump-ignore-src-files/test.py +++ b/testsuite/tests/TA12-013-dump-ignore-src-files/test.py @@ -10,15 +10,16 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Generate a project, instrument it and run it -p = gprfor(mains=['main.adb'], srcdirs=['..'], langs=['Ada', 'C']) +p = gprfor(mains=["main.adb"], srcdirs=[".."], langs=["Ada", "C"]) xcov_args = build_and_run( gprsw=GPRswitches(root_project=p), - covlevel='stmt', - mains=['main'], - extra_coverage_args=[]) + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], +) xcov_args_no_trace = xcov_args[:-1] trace_file = xcov_args[-1] @@ -35,19 +36,20 @@ def check_output(output_file, expected_content, regexp=False): :param bool regexp: Whether to match as a regexp (by default, check content equality). """ - checker = (thistest.fail_if_no_match - if regexp - else thistest.fail_if_not_equal) + checker = ( + thistest.fail_if_no_match if regexp else thistest.fail_if_not_equal + ) checker( '"gnatcov coverage" output ({})'.format(output_file), expected_content, - # Canonicalize to Unix-style line endings to have cross-platform checks - contents_of(output_file).replace('\r\n', '\n')) + contents_of(output_file).replace("\r\n", "\n"), + ) -def run_and_check(args, output_file, expected_content, regexp=False, - success_expected=True): +def run_and_check( + args, output_file, expected_content, regexp=False, success_expected=True +): """ Run gnatcov with the given arguments. @@ -64,159 +66,158 @@ def run_and_check(args, output_file, expected_content, regexp=False, thistest.fail_if( p.status == 0, 'the call to "gnatcov coverage" was expected to fail, yet it' - ' succeeded (see {})'.format(output_file) + " succeeded (see {})".format(output_file), ) check_output(output_file, expected_content, regexp) # Check that nothing is dumped without --dump-units-to -run_and_check(xcov_args + ['-axcov'], 'xcov-nodump.txt', '') +run_and_check(xcov_args + ["-axcov"], "xcov-nodump.txt", "") # Check that when *not* using the "--ignored-source-files" option, the list of # units is still printed. run_and_check( - xcov_args + [ - '-axcov', '--dump-units-to=-', '--save-checkpoint=all_files.ckpt' - ], - 'xcov-stdout1.txt', - expected_content=( - 'foo.c\n' - 'identity.h\n' - 'main\n' - 'pkg\n' - 'pkh\n' - ), + xcov_args + + ["-axcov", "--dump-units-to=-", "--save-checkpoint=all_files.ckpt"], + "xcov-stdout1.txt", + expected_content=("foo.c\n" "identity.h\n" "main\n" "pkg\n" "pkh\n"), ) run_and_check( - xcov_args + ['-axcov', '--units=main', '--dump-units-to=-'], - 'xcov-stdout2.txt', - expected_content='main\n', + xcov_args + ["-axcov", "--units=main", "--dump-units-to=-"], + "xcov-stdout2.txt", + expected_content="main\n", ) # Check that dumping the list of units with ignored source files works on the # "report" output. REPORT_PATTERN = ( - '(.|\n)*=+' - '\n== 4\\. UNITS OF INTEREST ==' - '\n=+' - '\n' - '\nfoo.c' - '\nidentity.h' - '\n identity.h always ignored' - '\nmain' - '\npkg' - '\n pkg-test.adb always ignored' - '\npkh' - '\n pkh-test.adb always ignored' - '\n' - '\n\\*\\* END OF REPORT \\*\\*' - '\n(.|\n)*') + "(.|\n)*=+" + "\n== 4\\. UNITS OF INTEREST ==" + "\n=+" + "\n" + "\nfoo.c" + "\nidentity.h" + "\n identity.h always ignored" + "\nmain" + "\npkg" + "\n pkg-test.adb always ignored" + "\npkh" + "\n pkh-test.adb always ignored" + "\n" + "\n\\*\\* END OF REPORT \\*\\*" + "\n(.|\n)*" +) run_and_check( - xcov_args + [ - '-areport', - '--dump-units-to=-', - '--ignore-source-files=*-test.adb', - '--ignore-source-files=identity.h', + xcov_args + + [ + "-areport", + "--dump-units-to=-", + "--ignore-source-files=*-test.adb", + "--ignore-source-files=identity.h", ], - 'report-stdout.txt', - REPORT_PATTERN, regexp=True) + "report-stdout.txt", + REPORT_PATTERN, + regexp=True, +) # Check that the units of separates of level deeper than one is listed under # the correct unit. run_and_check( - xcov_args + [ - '-axcov', '--dump-units-to=-', '--ignore-source-files=pkg-test-sep.adb' + xcov_args + + [ + "-axcov", + "--dump-units-to=-", + "--ignore-source-files=pkg-test-sep.adb", ], - 'xcov-stdout3.txt', + "xcov-stdout3.txt", expected_content=( - 'foo.c\n' - 'identity.h\n' - 'main\n' - 'pkg\n' - ' pkg-test-sep.adb always ignored\n' - 'pkh\n' + "foo.c\n" + "identity.h\n" + "main\n" + "pkg\n" + " pkg-test-sep.adb always ignored\n" + "pkh\n" ), ) # Check that a file ignored but that isn't part of a unit of interest # is not listed. run_and_check( - xcov_args + [ - '-axcov', - '--dump-units-to=-', - '--units=pkg', - '--ignore-source-files=*-test.adb', - '--ignore-source-files=identity.h', - '--save-checkpoint=pkg.ckpt', + xcov_args + + [ + "-axcov", + "--dump-units-to=-", + "--units=pkg", + "--ignore-source-files=*-test.adb", + "--ignore-source-files=identity.h", + "--save-checkpoint=pkg.ckpt", ], - 'xcov-stdout4.txt', - expected_content=( - 'pkg\n' - ' pkg-test.adb always ignored\n' - ), + "xcov-stdout4.txt", + expected_content=("pkg\n" " pkg-test.adb always ignored\n"), ) # Check that a file ignored that is part of a unit of interest is listed run_and_check( - xcov_args + [ - '-axcov', - '--dump-units-to=-', - '--units=pkh', - '--ignore-source-files=pkh-test.adb', - '--save-checkpoint=pkh.ckpt', + xcov_args + + [ + "-axcov", + "--dump-units-to=-", + "--units=pkh", + "--ignore-source-files=pkh-test.adb", + "--save-checkpoint=pkh.ckpt", ], - 'xcov-stdout5.txt', - expected_content=( - 'pkh\n' - ' pkh-test.adb always ignored\n' - ), + "xcov-stdout5.txt", + expected_content=("pkh\n" " pkh-test.adb always ignored\n"), ) # Check that loading results from a checkpoint shows files that were ignored # when creating the checkpoint. run_and_check( - xcov_args_no_trace + ['-axcov', '--dump-units-to=-', '-Cpkh.ckpt'], - 'xcov-stdout6.txt', + xcov_args_no_trace + ["-axcov", "--dump-units-to=-", "-Cpkh.ckpt"], + "xcov-stdout6.txt", expected_content=( - 'foo.c\n' - 'identity.h\n' - 'main\n' - 'pkg\n' - 'pkh\n' - ' pkh-test.adb always ignored\n' + "foo.c\n" + "identity.h\n" + "main\n" + "pkg\n" + "pkh\n" + " pkh-test.adb always ignored\n" ), ) run_and_check( - xcov_args_no_trace + [ - '-axcov', '--dump-units-to=-', '-Cpkg.ckpt', '-Cpkh.ckpt' - ], - 'xcov-stdout7.txt', + xcov_args_no_trace + + ["-axcov", "--dump-units-to=-", "-Cpkg.ckpt", "-Cpkh.ckpt"], + "xcov-stdout7.txt", expected_content=( - 'foo.c\n' - 'identity.h\n' - 'main\n' - 'pkg\n' - ' pkg-test.adb always ignored\n' - 'pkh\n' - ' pkh-test.adb always ignored\n' + "foo.c\n" + "identity.h\n" + "main\n" + "pkg\n" + " pkg-test.adb always ignored\n" + "pkh\n" + " pkh-test.adb always ignored\n" ), ) # Check that combining results from runs were a file was ignored in some # of them but not all displays the files as 'sometimes ignored'. run_and_check( - xcov_args_no_trace + [ - '-axcov', '--dump-units-to=-', '-Cpkg.ckpt', '-Call_files.ckpt', + xcov_args_no_trace + + [ + "-axcov", + "--dump-units-to=-", + "-Cpkg.ckpt", + "-Call_files.ckpt", ], - 'xcov-stdout8.txt', + "xcov-stdout8.txt", expected_content=( - 'foo.c\n' - 'identity.h\n' - 'main\n' - 'pkg\n' - ' pkg-test.adb sometimes ignored\n' - 'pkh\n' + "foo.c\n" + "identity.h\n" + "main\n" + "pkg\n" + " pkg-test.adb sometimes ignored\n" + "pkh\n" ), ) @@ -224,32 +225,34 @@ def run_and_check(args, output_file, expected_content, regexp=False, # and that if a file is ignored when analyzing a trace but is present in a # checkpoint, then it is marked as 'sometimes ignored'. run_and_check( - xcov_args + [ - '-axcov', - '--ignore-source-files=pkh-test.adb', - '--save-checkpoint=pkh_not_pkg.ckpt', + xcov_args + + [ + "-axcov", + "--ignore-source-files=pkh-test.adb", + "--save-checkpoint=pkh_not_pkg.ckpt", ], - 'xcov-sdtout9.txt', - '', + "xcov-sdtout9.txt", + "", ) run_and_check( - xcov_args + [ - '-axcov', - '--dump-units-to=-', - '--ignore-source-files=*test.adb', - '--ignore-source-files=identity.h', - '-Cpkh_not_pkg.ckpt', + xcov_args + + [ + "-axcov", + "--dump-units-to=-", + "--ignore-source-files=*test.adb", + "--ignore-source-files=identity.h", + "-Cpkh_not_pkg.ckpt", ], - 'xcov-stdout9.txt', + "xcov-stdout9.txt", expected_content=( - 'foo.c\n' - 'identity.h\n' - ' identity.h sometimes ignored\n' - 'main\n' - 'pkg\n' - ' pkg-test.adb sometimes ignored\n' - 'pkh\n' - ' pkh-test.adb always ignored\n' + "foo.c\n" + "identity.h\n" + " identity.h sometimes ignored\n" + "main\n" + "pkg\n" + " pkg-test.adb sometimes ignored\n" + "pkh\n" + " pkh-test.adb always ignored\n" ), ) diff --git a/testsuite/tests/TA14-011-show-mcdc-vectors/test.py b/testsuite/tests/TA14-011-show-mcdc-vectors/test.py index d6d8188b5..948a72571 100644 --- a/testsuite/tests/TA14-011-show-mcdc-vectors/test.py +++ b/testsuite/tests/TA14-011-show-mcdc-vectors/test.py @@ -9,15 +9,16 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Generate a project, instrument it if necessary and run it, -p = gprfor(mains=['main.adb'], srcdirs=['..']) +p = gprfor(mains=["main.adb"], srcdirs=[".."]) xcov_args_mcdc = build_and_run( gprsw=GPRswitches(root_project=p), - covlevel='stmt+mcdc', - mains=['main'], - extra_coverage_args=[]) + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=[], +) def check_output(output_file, expected_content, regexp=False): @@ -32,19 +33,20 @@ def check_output(output_file, expected_content, regexp=False): :param bool regexp: Whether to match as a regexp (by default, check content equality). """ - checker = (thistest.fail_if_no_match - if regexp - else thistest.fail_if_not_equal) + checker = ( + thistest.fail_if_no_match if regexp else thistest.fail_if_not_equal + ) checker( '"gnatcov coverage" output ({})'.format(output_file), expected_content, - # Canonicalize to Unix-style line endings to have cross-platform checks - contents_of(output_file).replace('\r\n', '\n')) + contents_of(output_file).replace("\r\n", "\n"), + ) -def run_and_check(args, output_file, expected_content, regexp=False, - success_expected=True): +def run_and_check( + args, output_file, expected_content, regexp=False, success_expected=True +): """ Run gnatcov with the given arguments. @@ -61,7 +63,7 @@ def run_and_check(args, output_file, expected_content, regexp=False, thistest.fail_if( p.status == 0, 'the call to "gnatcov coverage" was expected to fail, yet it' - ' succeeded (see {})'.format(output_file) + " succeeded (see {})".format(output_file), ) check_output(output_file, expected_content, regexp) @@ -70,55 +72,65 @@ def run_and_check(args, output_file, expected_content, regexp=False, # --show-mcdc-vectors REPORT_PATTERN_NO_VECTORS = ( - '(.|\n)*' - '\n' - r'\n2\.3\. MCDC COVERAGE' - '\n-+' - '\n' - r'\npkg\.adb:6:22: condition has no independent influence pair' - ', MC/DC not achieved' - r'\npkg\.adb:6:33: condition has no independent influence pair' - ', MC/DC not achieved' - r'\npkg\.adb:20:21: condition has no independent influence pair' - ', MC/DC not achieved' - '\n' - r'\n3 violations\.') - -run_and_check(xcov_args_mcdc + ['-areport'], 'report-stdout.txt', - REPORT_PATTERN_NO_VECTORS, regexp=True) + "(.|\n)*" + "\n" + r"\n2\.3\. MCDC COVERAGE" + "\n-+" + "\n" + r"\npkg\.adb:6:22: condition has no independent influence pair" + ", MC/DC not achieved" + r"\npkg\.adb:6:33: condition has no independent influence pair" + ", MC/DC not achieved" + r"\npkg\.adb:20:21: condition has no independent influence pair" + ", MC/DC not achieved" + "\n" + r"\n3 violations\." +) + +run_and_check( + xcov_args_mcdc + ["-areport"], + "report-stdout.txt", + REPORT_PATTERN_NO_VECTORS, + regexp=True, +) # Check that mcdc vectors are displayed under the corresponding # condition violations, and show the conditions indexes in violation messages. REPORT_PATTERN_MCDC = ( - '(.|\n)*' - '\n' - r'\n2\.3\. MCDC COVERAGE' - '\n-+' - '\n' + "(.|\n)*" + "\n" + r"\n2\.3\. MCDC COVERAGE" + "\n-+" + "\n" r'\npkg\.adb:6:22: condition 1 \("B"\) has no independent influence pair' - ', MC/DC not achieved' + ", MC/DC not achieved" r'\npkg\.adb:6:33: condition 2 \("C"\) has no independent influence pair' - ', MC/DC not achieved' - r'\npkg.adb:6:11: Decision of the form \(\(\(C0 and then C1\)' - r' and then C2\) or else C3\)' - '\nEvaluation vectors found:' - '\n F - - F -> FALSE In a pair for C0, C3' - '\n T T F T -> TRUE In a pair for C3' - '\n T T T - -> TRUE In a pair for C0' - '\n' + ", MC/DC not achieved" + r"\npkg.adb:6:11: Decision of the form \(\(\(C0 and then C1\)" + r" and then C2\) or else C3\)" + "\nEvaluation vectors found:" + "\n F - - F -> FALSE In a pair for C0, C3" + "\n T T F T -> TRUE In a pair for C3" + "\n T T T - -> TRUE In a pair for C0" + "\n" r'\npkg\.adb:20:21: condition 1 \("B"\) has no independent influence pair' - ', MC/DC not achieved' - r'\npkg.adb:20:10: Decision of the form \(C0 and then C1\)' - '\nEvaluation vectors found:' - '\n F - -> FALSE In a pair for C0' - '\n T T -> TRUE In a pair for C0' - '\n' - '\n' - r'\n3 violations\.') - -run_and_check(xcov_args_mcdc + ['-areport', '--show-mcdc-vectors'], - 'report-stdout.txt', REPORT_PATTERN_MCDC, regexp=True) + ", MC/DC not achieved" + r"\npkg.adb:20:10: Decision of the form \(C0 and then C1\)" + "\nEvaluation vectors found:" + "\n F - -> FALSE In a pair for C0" + "\n T T -> TRUE In a pair for C0" + "\n" + "\n" + r"\n3 violations\." +) + +run_and_check( + xcov_args_mcdc + ["-areport", "--show-mcdc-vectors"], + "report-stdout.txt", + REPORT_PATTERN_MCDC, + regexp=True, +) # Check that evaluation vectors not part of any pair are displayed @@ -129,35 +141,40 @@ def run_and_check(args, output_file, expected_content, regexp=False, xcov_args_uc_mcdc = xcov_args_mcdc + ["--level=stmt+uc_mcdc"] REPORT_PATTERN_UC_MCDC = ( - '(.|\n)*' - '\n' - r'\n2\.3\. UC_MCDC COVERAGE' - '\n-+' - '\n' + "(.|\n)*" + "\n" + r"\n2\.3\. UC_MCDC COVERAGE" + "\n-+" + "\n" r'\npkg\.adb:6:22: condition 1 \("B"\) has no independent influence pair' - ', MC/DC not achieved' + ", MC/DC not achieved" r'\npkg\.adb:6:33: condition 2 \("C"\) has no independent influence pair' - ', MC/DC not achieved' + ", MC/DC not achieved" r'\npkg\.adb:6:44: condition 3 \("A"\) has no independent influence pair' - ', MC/DC not achieved' - r'\npkg.adb:6:11: Decision of the form \(\(\(C0 and then C1\)' - r' and then C2\) or else C3\)' - '\nEvaluation vectors found:' - '\n F - - F -> FALSE In a pair for C0' - '\n T T T - -> TRUE In a pair for C0' - '\n T T F T -> TRUE Not part of any pair' - '\n' + ", MC/DC not achieved" + r"\npkg.adb:6:11: Decision of the form \(\(\(C0 and then C1\)" + r" and then C2\) or else C3\)" + "\nEvaluation vectors found:" + "\n F - - F -> FALSE In a pair for C0" + "\n T T T - -> TRUE In a pair for C0" + "\n T T F T -> TRUE Not part of any pair" + "\n" r'\npkg\.adb:20:21: condition 1 \("B"\) has no independent influence pair' - ', MC/DC not achieved' - r'\npkg.adb:20:10: Decision of the form \(C0 and then C1\)' - '\nEvaluation vectors found:' - '\n F - -> FALSE In a pair for C0' - '\n T T -> TRUE In a pair for C0' - '\n' - '\n' - r'\n4 violations\.') - -run_and_check(xcov_args_uc_mcdc + ['-areport', '--show-mcdc-vectors'], - 'report-stdout.txt', REPORT_PATTERN_UC_MCDC, regexp=True) + ", MC/DC not achieved" + r"\npkg.adb:20:10: Decision of the form \(C0 and then C1\)" + "\nEvaluation vectors found:" + "\n F - -> FALSE In a pair for C0" + "\n T T -> TRUE In a pair for C0" + "\n" + "\n" + r"\n4 violations\." +) + +run_and_check( + xcov_args_uc_mcdc + ["-areport", "--show-mcdc-vectors"], + "report-stdout.txt", + REPORT_PATTERN_UC_MCDC, + regexp=True, +) thistest.result() diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/test.py b/testsuite/tests/TA15-063-ignore-fingerprint/test.py index 4c9dedfcd..298369fbb 100644 --- a/testsuite/tests/TA15-063-ignore-fingerprint/test.py +++ b/testsuite/tests/TA15-063-ignore-fingerprint/test.py @@ -20,7 +20,7 @@ def check_empty(filename): content = contents_of(filename) thistest.fail_if( content, - f'Output of "gnatcov coverage" not empty ({filename}):\n\n{content}' + f'Output of "gnatcov coverage" not empty ({filename}):\n\n{content}', ) @@ -37,7 +37,8 @@ def check_empty(filename): covlevel="stmt", mains=["main"], extra_coverage_args=["--save-checkpoint=c1.ckpt"], - out="log-cov1.txt") + out="log-cov1.txt", +) check_empty("log-cov1.txt") # Build and run test1.gpr's main.adb, then compute a partial coverage report @@ -50,23 +51,38 @@ def check_empty(filename): mains=["main"], ignored_source_files=["pkg-test.adb"], extra_coverage_args=["--save-checkpoint=c2.ckpt"], - out="log-cov2.txt") + out="log-cov2.txt", +) check_empty("log-cov2.txt") # Avoid the "info: creating output path report" message os.mkdir("report") # Consolidate both partial reports and produce an XCOV report -xcov(["coverage", "-P", p, "--projects", "p", "-cstmt", "-axcov", - "--output-dir=report", - "-Cc1.ckpt", "-Cc2.ckpt"], - out="log-cons.txt") +xcov( + [ + "coverage", + "-P", + p, + "--projects", + "p", + "-cstmt", + "-axcov", + "--output-dir=report", + "-Cc1.ckpt", + "-Cc2.ckpt", + ], + out="log-cons.txt", +) check_empty("log-cons.txt") -check_xcov_reports("report", { - "main.adb.xcov": {"+": {5}}, - "pkg.ads.xcov": {}, - "pkg.adb.xcov": {"+": {2}}, - "pkg-test.adb.xcov": {"-": {8, 9}}, -}) +check_xcov_reports( + "report", + { + "main.adb.xcov": {"+": {5}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {2}}, + "pkg-test.adb.xcov": {"-": {8, 9}}, + }, +) thistest.result() diff --git a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py index 31f65eb39..64675a87f 100644 --- a/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py +++ b/testsuite/tests/TA27-015-ignore-source-files-source-coverage/test.py @@ -12,22 +12,25 @@ import os -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Generate a project, instrument it and run it -p = gprfor(mains=['main.adb'], srcdirs=['..']) +p = gprfor(mains=["main.adb"], srcdirs=[".."]) xcov_args = build_and_run( gprsw=GPRswitches(root_project=p), - covlevel='stmt', - mains=['main'], - trace_mode='src', - extra_coverage_args=[]) + covlevel="stmt", + mains=["main"], + trace_mode="src", + extra_coverage_args=[], +) xcov_args_no_trace = xcov_args[:-1] trace_file = xcov_args[-1] -expected_res_dict = {'pkg.adb.xcov': {'-': {7}}, - 'pkg-say_goodbye.adb.xcov': {'-': {9}}, - 'pkg.ads.xcov': {}} +expected_res_dict = { + "pkg.adb.xcov": {"-": {7}}, + "pkg-say_goodbye.adb.xcov": {"-": {9}}, + "pkg.ads.xcov": {}, +} def check(report_name, args, expected_files): @@ -42,44 +45,67 @@ def check(report_name, args, expected_files): # Create report dir to avoid warning message os.mkdir(report_name) - checked_xcov(args + ['-axcov', '--output-dir='+report_name], - f'{report_name}_out.txt') + checked_xcov( + args + ["-axcov", "--output-dir=" + report_name], + f"{report_name}_out.txt", + ) expected = { - filename: expected_res_dict[filename] - for filename in expected_files + filename: expected_res_dict[filename] for filename in expected_files } expected["main.adb.xcov"] = {"+": {5, 6}} check_xcov_reports(report_name, expected, discard_empty=False) # Check that not passing the option has no effect -check('report0', xcov_args + ['--save-checkpoint=full.ckpt'], - ['pkg.adb.xcov', 'pkg-say_goodbye.adb.xcov', 'pkg.ads.xcov']) +check( + "report0", + xcov_args + ["--save-checkpoint=full.ckpt"], + ["pkg.adb.xcov", "pkg-say_goodbye.adb.xcov", "pkg.ads.xcov"], +) # Check that --ignore-source-files has the expected effect on the 'coverage' # command. -check('report1', xcov_args + ['--ignore-source-files=pkg-say_goodbye.adb'], - ['pkg.adb.xcov', 'pkg.ads.xcov']) +check( + "report1", + xcov_args + ["--ignore-source-files=pkg-say_goodbye.adb"], + ["pkg.adb.xcov", "pkg.ads.xcov"], +) # Check that --ignore-source-files does not filter checkpoint loading -check('report2', xcov_args_no_trace + - ['--ignore-source-files=pkg-say_goodbye.adb', '-Cfull.ckpt'], - ['pkg.adb.xcov', 'pkg-say_goodbye.adb.xcov', 'pkg.ads.xcov']) +check( + "report2", + xcov_args_no_trace + + ["--ignore-source-files=pkg-say_goodbye.adb", "-Cfull.ckpt"], + ["pkg.adb.xcov", "pkg-say_goodbye.adb.xcov", "pkg.ads.xcov"], +) # Check that in presence of bot a checkpoint and a SID file, # --ignore-source-files filters the SID file but not the checkpoint. -checked_xcov(xcov_args + ['--ignore-source-files=pkg-say_goodbye.adb', - '--save-checkpoint=pkg.ckpt'], - 'report3_out.txt') -check('report3', xcov_args + ['--ignore-source-files=pkg*.adb', '-Cpkg.ckpt'], - ['pkg.adb.xcov', 'pkg.ads.xcov']) +checked_xcov( + xcov_args + + [ + "--ignore-source-files=pkg-say_goodbye.adb", + "--save-checkpoint=pkg.ckpt", + ], + "report3_out.txt", +) +check( + "report3", + xcov_args + ["--ignore-source-files=pkg*.adb", "-Cpkg.ckpt"], + ["pkg.adb.xcov", "pkg.ads.xcov"], +) # Check that if a file is ignored when creating the checkpoint, then it is not # present when loading that checkpoint. -checked_xcov(xcov_args + ['--save-checkpoint=pkg_goodbye.ckpt', - '--ignore-source-files=pkg.adb'], - 'report4_out.txt') -check('report4', xcov_args_no_trace + ['-Cpkg_goodbye.ckpt'], - ['pkg-say_goodbye.adb.xcov', 'pkg.ads.xcov']) +checked_xcov( + xcov_args + + ["--save-checkpoint=pkg_goodbye.ckpt", "--ignore-source-files=pkg.adb"], + "report4_out.txt", +) +check( + "report4", + xcov_args_no_trace + ["-Cpkg_goodbye.ckpt"], + ["pkg-say_goodbye.adb.xcov", "pkg.ads.xcov"], +) thistest.result() diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/test.py b/testsuite/tests/TB13-020-expr-func-mcdc/test.py index dc1999331..af12fa170 100644 --- a/testsuite/tests/TB13-020-expr-func-mcdc/test.py +++ b/testsuite/tests/TB13-020-expr-func-mcdc/test.py @@ -25,15 +25,17 @@ gprsw=GPRswitches(root_project=p), covlevel="stmt+mcdc", mains=["main"], - extra_coverage_args=["-axcov", "--output-dir=report"]) - -check_xcov_reports("report", { - "main.adb.xcov": { - "!": {6, 9, 15, 19}, - "+": {11, 12}, - "-": {16, 20}}, - "pkg.ads.xcov": {}, - "pkg.adb.xcov": {"+": {9}}, -}, discard_empty=False) + extra_coverage_args=["-axcov", "--output-dir=report"], +) + +check_xcov_reports( + "report", + { + "main.adb.xcov": {"!": {6, 9, 15, 19}, "+": {11, 12}, "-": {16, 20}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {9}}, + }, + discard_empty=False, +) thistest.result() diff --git a/testsuite/tests/TB24-022-missing-sid/test.py b/testsuite/tests/TB24-022-missing-sid/test.py index 196b8bfc6..8bccaf258 100644 --- a/testsuite/tests/TB24-022-missing-sid/test.py +++ b/testsuite/tests/TB24-022-missing-sid/test.py @@ -11,22 +11,33 @@ gprfor(prjid="p1", srcdirs=["../src-p1"], mains=None, langs="Ada") -p2 = gprfor(prjid="p2", srcdirs=["../src-p2"], mains=["p2.adb"], - deps=["p1"], - extra="for Origin_Project use \"p1\";") +p2 = gprfor( + prjid="p2", + srcdirs=["../src-p2"], + mains=["p2.adb"], + deps=["p1"], + extra='for Origin_Project use "p1";', +) # Build the projects and produce a trace for the main -build_run_and_coverage(gprsw=GPRswitches(root_project=p2), - covlevel="stmt", - mains=["p2"], - extra_coverage_args=["-a", "xcov", - "--no-subprojects", - "--projects=p2", - "-v"], - trace_mode="src") +build_run_and_coverage( + gprsw=GPRswitches(root_project=p2), + covlevel="stmt", + mains=["p2"], + extra_coverage_args=[ + "-a", + "xcov", + "--no-subprojects", + "--projects=p2", + "-v", + ], + trace_mode="src", +) -thistest.fail_if("warning: no SID file found for unit p2" - not in contents_of("coverage.log"), - "No warning for missing SID file (for p2)") +thistest.fail_if( + "warning: no SID file found for unit p2" + not in contents_of("coverage.log"), + "No warning for missing SID file (for p2)", +) thistest.result() diff --git a/testsuite/tests/TC03-012-objcov-line-state/test.py b/testsuite/tests/TC03-012-objcov-line-state/test.py index 1d30fb4d1..7f6da16ba 100644 --- a/testsuite/tests/TC03-012-objcov-line-state/test.py +++ b/testsuite/tests/TC03-012-objcov-line-state/test.py @@ -9,20 +9,27 @@ from SCOV.minicheck import check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir -from SUITE.tutils import exepath_to, exename_for, gprfor, xcov, xrun, tracename_for +from SUITE.tutils import ( + exepath_to, + exename_for, + gprfor, + xcov, + xrun, + tracename_for, +) -Wdir('tmp') +Wdir("tmp") -prj = gprfor(srcdirs=['..'], objdir='.', mains=['main.c'], prjid='gen') +prj = gprfor(srcdirs=[".."], objdir=".", mains=["main.c"], prjid="gen") # Compile assembly -Run(['gcc', '-o', exename_for('main'), os.path.join('..', 'main.s')]) +Run(["gcc", "-o", exename_for("main"), os.path.join("..", "main.s")]) # Run and coverage -xrun(['-cinsn', exepath_to('main')]) -xcov(['coverage', '-cinsn', '-axcov', '-Pgen', tracename_for('main')]) +xrun(["-cinsn", exepath_to("main")]) +xcov(["coverage", "-cinsn", "-axcov", "-Pgen", tracename_for("main")]) # Check that line 3 is correctly marked as partially covered -check_xcov_reports('.', {'main.c.xcov': {'-': {4}, '!': {3}}}) +check_xcov_reports(".", {"main.c.xcov": {"-": {4}, "!": {3}}}) thistest.result() diff --git a/testsuite/tests/TC11-052-internal-error/test.py b/testsuite/tests/TC11-052-internal-error/test.py index 125526d57..0cd9a7d74 100644 --- a/testsuite/tests/TC11-052-internal-error/test.py +++ b/testsuite/tests/TC11-052-internal-error/test.py @@ -19,28 +19,29 @@ def check(args, trigger, info): env["GNATCOV_INTERNAL_ERROR_TRIGGER"] = trigger p = xcov(args + ["-q"], out=out, env=env, register_failure=False) thistest.fail_if( - p.status == 0, - "gnatcov returned success exit code, error expected" + p.status == 0, "gnatcov returned success exit code, error expected" ) expected_output = re.compile( - "\n".join([ - ".*", - "== gnatcov bug detected ==", - "", - "gnatcov just encountered an internal error:", - f"raised CONSTRAINT_ERROR : {trigger.upper().replace('-', '_')}", - # Depending on how gnatcov is built, exception info may contain - # stack traces. - "((Load address: [x0-9a-f]+\n)?Call stack traceback locations:", - "[x0-9a-f ]+", - ")?", - "", - "(?P.*)", - "", - "This is gnatcov version .*", - ]), - re.MULTILINE + "\n".join( + [ + ".*", + "== gnatcov bug detected ==", + "", + "gnatcov just encountered an internal error:", + f"raised CONSTRAINT_ERROR : {trigger.upper().replace('-', '_')}", + # Depending on how gnatcov is built, exception info may contain + # stack traces. + "((Load address: [x0-9a-f]+\n)?Call stack traceback locations:", + "[x0-9a-f ]+", + ")?", + "", + "(?P.*)", + "", + "This is gnatcov version .*", + ] + ), + re.MULTILINE, ) # The difference between expected and actual output generally is @@ -67,21 +68,29 @@ def check(args, trigger, info): prj = gprfor(srcdirs=[".."], mains=["main.adb"]) os.mkdir("obj") -check(args=["coverage"], - trigger="arguments-loading", - info=r"No coverage processing context information available\.") +check( + args=["coverage"], + trigger="arguments-loading", + info=r"No coverage processing context information available\.", +) -check(args=["instrument", "-P", prj, "--level=stmt"], - trigger="ada-instrument-start-file", - info=r"Instrumenting [^\n]*main\.adb") +check( + args=["instrument", "-P", prj, "--level=stmt"], + trigger="ada-instrument-start-file", + info=r"Instrumenting [^\n]*main\.adb", +) -check(args=["instrument", "-P", prj, "--level=stmt"], - trigger="ada-instrument-null-proc", - info=r"Instrumenting NullSubpDecl at [^\n]*main\.adb:7:4-7:33") +check( + args=["instrument", "-P", prj, "--level=stmt"], + trigger="ada-instrument-null-proc", + info=r"Instrumenting NullSubpDecl at [^\n]*main\.adb:7:4-7:33", +) -check(args=["instrument", "-P", prj, "--level=stmt"], - trigger="ada-instrument-insert-stmt-witness", - info=r"Instrumenting ConcreteTypeDecl at [^\n]*main\.adb:6:4-6:26") +check( + args=["instrument", "-P", prj, "--level=stmt"], + trigger="ada-instrument-insert-stmt-witness", + info=r"Instrumenting ConcreteTypeDecl at [^\n]*main\.adb:6:4-6:26", +) # Instrument the example project, run its main to produce a source trace and # then trigger an internal error while loading the SID file. diff --git a/testsuite/tests/U128-004-displayed-percentages/test.py b/testsuite/tests/U128-004-displayed-percentages/test.py index 2d49044b2..e094d0de3 100644 --- a/testsuite/tests/U128-004-displayed-percentages/test.py +++ b/testsuite/tests/U128-004-displayed-percentages/test.py @@ -8,20 +8,26 @@ prj = gprfor(srcdirs=[".."], mains=["main1.adb", "main99.adb"]) -build_run_and_coverage(gprsw=GPRswitches(root_project=prj), - covlevel="stmt", - mains=["main99"], - extra_coverage_args=["-a", "xcov"]) +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main99"], + extra_coverage_args=["-a", "xcov"], +) # For percentages > 99%, GNATcoverage should always round down -thistest.fail_if("99% of 241 lines covered" not in - contents_of("obj/pkg.adb.xcov")) +thistest.fail_if( + "99% of 241 lines covered" not in contents_of("obj/pkg.adb.xcov") +) -build_run_and_coverage(gprsw=GPRswitches(root_project=prj), - covlevel="stmt", - mains=["main1"], - extra_coverage_args=["-a", "xcov"]) +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main1"], + extra_coverage_args=["-a", "xcov"], +) # Symetrically, for percentages < 1%, GNATcoverage should round up -thistest.fail_if("1% of 241 lines covered" not in - contents_of("obj/pkg.adb.xcov")) +thistest.fail_if( + "1% of 241 lines covered" not in contents_of("obj/pkg.adb.xcov") +) thistest.result() diff --git a/testsuite/tests/U204-026-arch-mix/test.py b/testsuite/tests/U204-026-arch-mix/test.py index 0f8f37949..e0f77735e 100644 --- a/testsuite/tests/U204-026-arch-mix/test.py +++ b/testsuite/tests/U204-026-arch-mix/test.py @@ -72,8 +72,10 @@ def check_reports(xcov_dir): # The instrumentation part was done in "gen.sh". Restore SIDs and instrumented # sources for the two cases to test and do the build+run+coverage. -for name, gen_dir_name in [("win", "x86_64-windows"), - ("linux", "arm-elf-linux")]: +for name, gen_dir_name in [ + ("win", "x86_64-windows"), + ("linux", "arm-elf-linux"), +]: thistest.log(f"== 1. {name} ==") # Generate a dedicated project for this @@ -117,8 +119,10 @@ def check_reports(xcov_dir): xcov( cov_args + ["--output-dir=2-xcov"] - + [f"--checkpoint={os.path.join('..', 'gen', ckpt)}" - for ckpt in ["src-main_1.ckpt", "src-main_2.ckpt"]] + + [ + f"--checkpoint={os.path.join('..', 'gen', ckpt)}" + for ckpt in ["src-main_1.ckpt", "src-main_2.ckpt"] + ] ) check_reports("2-xcov") @@ -133,14 +137,16 @@ def check_reports(xcov_dir): p = xcov( cov_args + ["--output-dir=3-xcov"] - + [f"--checkpoint={os.path.join('..', 'gen', ckpt)}" - for ckpt in ["bin-main_1.ckpt", "bin-main_2.ckpt"]], + + [ + f"--checkpoint={os.path.join('..', 'gen', ckpt)}" + for ckpt in ["bin-main_1.ckpt", "bin-main_2.ckpt"] + ], out="3-coverage-out.txt", register_failure=False, ) thistest.fail_if( p.status == 0, - "'gnatcov coverage' exited with status code 0 while an error was expected" + "'gnatcov coverage' exited with status code 0 while an error was expected", ) # Since the checkpoint for main_1 was created for 32-bits while the checkpoint diff --git a/testsuite/tests/U204-029-source-rebase/Ada/test.py b/testsuite/tests/U204-029-source-rebase/Ada/test.py index 46f319fc9..896c87b7d 100644 --- a/testsuite/tests/U204-029-source-rebase/Ada/test.py +++ b/testsuite/tests/U204-029-source-rebase/Ada/test.py @@ -28,7 +28,7 @@ origin_src_dir="src", expected_xcov_results={ "pkg1.ads.xcov": {}, - "pkg1.adb.xcov": {'+': {8, 9, 11}} + "pkg1.adb.xcov": {"+": {8, 9, 11}}, }, rebase_dir="/some/random/dir", ) @@ -42,7 +42,7 @@ origin_src_dir="src", expected_xcov_results={ "pkg1.ads.xcov": {}, - "pkg1.adb.xcov": {'+': {8, 9, 11}} + "pkg1.adb.xcov": {"+": {8, 9, 11}}, }, suppress_src_dir=True, ) @@ -56,9 +56,9 @@ origin_src_dir="src", expected_xcov_results={ "pkg1.ads.xcov": {}, - "pkg1.adb.xcov": {'+': {8, 9, 11}}, + "pkg1.adb.xcov": {"+": {8, 9, 11}}, "pkg2.ads.xcov": {}, - "pkg2.adb.xcov": {'+': {8, 9, 11}} + "pkg2.adb.xcov": {"+": {8, 9, 11}}, }, suppress_src_dir=True, ) @@ -81,9 +81,9 @@ origin_src_dir="src", expected_xcov_results={ "pkg1.ads.xcov": {}, - "pkg1.adb.xcov": {'+': {8, 9, 11}}, + "pkg1.adb.xcov": {"+": {8, 9, 11}}, "pkg2.ads.xcov": {}, - "pkg2.adb.xcov": {'+': {8, 9, 11}} + "pkg2.adb.xcov": {"+": {8, 9, 11}}, }, ) diff --git a/testsuite/tests/U204-029-source-rebase/C/test.py b/testsuite/tests/U204-029-source-rebase/C/test.py index 8fc1ab830..661fe9596 100644 --- a/testsuite/tests/U204-029-source-rebase/C/test.py +++ b/testsuite/tests/U204-029-source-rebase/C/test.py @@ -14,13 +14,18 @@ run_variant( variant_basename="intersecting", mains_list=["main1.c", "main2.c"], - units_lists=[["main1.c", ], ["main2.c"]], + units_lists=[ + [ + "main1.c", + ], + ["main2.c"], + ], origin_src_dir="src", expected_xcov_results={ "main1.c.xcov": {"+": {7, 8, 9}}, "main2.c.xcov": {"+": {7, 8, 9}}, "a-pkg.h.xcov": {"+": {5, 7, 11}}, - "b-pkg.h.xcov": {"+": {5, 7, 11}} + "b-pkg.h.xcov": {"+": {5, 7, 11}}, }, ) diff --git a/testsuite/tests/U204-029-source-rebase/test_support.py b/testsuite/tests/U204-029-source-rebase/test_support.py index 29e826ca7..1cccfbf2f 100644 --- a/testsuite/tests/U204-029-source-rebase/test_support.py +++ b/testsuite/tests/U204-029-source-rebase/test_support.py @@ -11,7 +11,7 @@ def out_of_source_checkpoint( - variant_name, main, units, origin_src_dir, suppress_src_dir + variant_name, main, units, origin_src_dir, suppress_src_dir ): """ Create a checkpoint with a copy of the sources in origin_src_dir, using @@ -30,13 +30,13 @@ def out_of_source_checkpoint( build_run_and_coverage( gprsw=GPRswitches( - gprfor(mains=[main], - srcdirs=local_src_dir, - objdir="obj"), - units=units), + gprfor(mains=[main], srcdirs=local_src_dir, objdir="obj"), + units=units, + ), covlevel="stmt", mains=[os.path.splitext(main)[0]], - extra_coverage_args=[f"--save-checkpoint={checkpoint_name}"]) + extra_coverage_args=[f"--save-checkpoint={checkpoint_name}"], + ) if suppress_src_dir: shutil.rmtree(local_src_dir) @@ -44,12 +44,14 @@ def out_of_source_checkpoint( return (checkpoint_name, os.path.abspath(local_src_dir)) -def consolidate_and_check(variant_basename, - expected_xcov_results, - expect_failure, - checkpoints, - rebase_opts, - output_dir_name): +def consolidate_and_check( + variant_basename, + expected_xcov_results, + expect_failure, + checkpoints, + rebase_opts, + output_dir_name, +): """ Consolidate the given set of checkpoints and create xcov reports. The xcov reports are checked against expected_xcov_results, and if @@ -58,34 +60,39 @@ def consolidate_and_check(variant_basename, """ log_filename = f"coverage-{output_dir_name}.log" mkdir(output_dir_name) - xcov(["coverage", "-cstmt", "-axcov", f"--output-dir={output_dir_name}"] - + [f"-C{checkpoint}" for checkpoint in checkpoints] - + rebase_opts, - out=log_filename) + xcov( + ["coverage", "-cstmt", "-axcov", f"--output-dir={output_dir_name}"] + + [f"-C{checkpoint}" for checkpoint in checkpoints] + + rebase_opts, + out=log_filename, + ) if expect_failure: thistest.fail_if_no_match( f"'gnatcov coverage' output ({variant_basename}-{output_dir_name})", r"^(warning: can't open .*\n)+$", - contents_of(log_filename)) + contents_of(log_filename), + ) else: thistest.fail_if( not empty(log_filename), f"'gnatcov coverage' output ({variant_basename}-{output_dir_name})" - " not empty:\n " + contents_of(log_filename) + " not empty:\n " + contents_of(log_filename), ) check_xcov_reports(output_dir_name, expected_xcov_results) -def run_variant(variant_basename, - mains_list, - units_lists, - origin_src_dir, - expected_xcov_results, - rebase_dir=None, - expect_failure=False, - suppress_src_dir=False): +def run_variant( + variant_basename, + mains_list, + units_lists, + origin_src_dir, + expected_xcov_results, + rebase_dir=None, + expect_failure=False, + suppress_src_dir=False, +): """ Create a set of checkpoints using, for checkpoint i, the sources in origin_src_dir, the main in mains_list[i] and the units in units_lists[i]. @@ -108,12 +115,18 @@ def run_variant(variant_basename, # Create a checkpoint for each set of main/units_of_interest and retrieve # the checkpoint's name, as well as the path to the source directory used # to create said checkpoint. - checkpoints, prefixes = zip(*[ - out_of_source_checkpoint( - f"{variant_basename}_{i}", main, units, origin_src_dir, - suppress_src_dir) - for i, (main, units) in enumerate(zip(mains_list, units_lists)) - ]) + checkpoints, prefixes = zip( + *[ + out_of_source_checkpoint( + f"{variant_basename}_{i}", + main, + units, + origin_src_dir, + suppress_src_dir, + ) + for i, (main, units) in enumerate(zip(mains_list, units_lists)) + ] + ) # Test individual options passed to gnatcov for each checkpoint consolidate_and_check( @@ -122,8 +135,9 @@ def run_variant(variant_basename, expect_failure, checkpoints, rebase_opts=[ - f"--source-rebase={prefix}={rebase_dir}" for prefix in prefixes], - output_dir_name="simple" + f"--source-rebase={prefix}={rebase_dir}" for prefix in prefixes + ], + output_dir_name="simple", ) # Test using one globbing pattern to specify source rebase for all @@ -135,13 +149,13 @@ def run_variant(variant_basename, expect_failure, checkpoints, rebase_opts=[f"--source-rebase={glob_pattern}={rebase_dir}"], - output_dir_name="globbing_pattern" + output_dir_name="globbing_pattern", ) # Test using a response file to specify source rebase for all checkpoints response_file_name = "src-rebase.txt" - with open(response_file_name, 'w') as f: + with open(response_file_name, "w") as f: f.writelines([f"{prefix}={rebase_dir}\n" for prefix in prefixes]) consolidate_and_check( @@ -150,7 +164,7 @@ def run_variant(variant_basename, expect_failure, checkpoints, rebase_opts=[f"--source-rebase=@{response_file_name}"], - output_dir_name="response_file" + output_dir_name="response_file", ) wd.to_homedir() diff --git a/testsuite/tests/U208-020-child-project/test.py b/testsuite/tests/U208-020-child-project/test.py index ad17f2a50..e07adb00e 100644 --- a/testsuite/tests/U208-020-child-project/test.py +++ b/testsuite/tests/U208-020-child-project/test.py @@ -10,22 +10,27 @@ from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p-child.gpr') -obj_dir = os.path.abspath('obj/p-child') +p_gpr = os.path.abspath("p-child.gpr") +obj_dir = os.path.abspath("obj/p-child") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') -check_xcov_reports('xcov', - {'main.adb.xcov': {'+': {5, 6}}, - 'pkg.adb.xcov': {'+': {5}}, - 'pkg.ads.xcov': {}}) + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5, 6}}, + "pkg.adb.xcov": {"+": {5}}, + "pkg.ads.xcov": {}, + }, +) thistest.result() diff --git a/testsuite/tests/U208-020-error-call/test.py b/testsuite/tests/U208-020-error-call/test.py index 1b7645b0e..839693bc2 100644 --- a/testsuite/tests/U208-020-error-call/test.py +++ b/testsuite/tests/U208-020-error-call/test.py @@ -13,14 +13,16 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor -Wdir('tmp_') +Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches( - gprfor(prjid="p", srcdirs=[".."], mains=["main.c"], langs=["C"])), + gprfor(prjid="p", srcdirs=[".."], mains=["main.c"], langs=["C"]) + ), covlevel="stmt", mains=["main"], - extra_coverage_args=["--annotate=xcov"]) + extra_coverage_args=["--annotate=xcov"], +) -check_xcov_reports('obj', {'main.c.xcov': {'+': {6, 7}}}) +check_xcov_reports("obj", {"main.c.xcov": {"+": {6, 7}}}) thistest.result() diff --git a/testsuite/tests/U208-020-unique-language-project/test.py b/testsuite/tests/U208-020-unique-language-project/test.py index d3c3b533f..4b40528d9 100644 --- a/testsuite/tests/U208-020-unique-language-project/test.py +++ b/testsuite/tests/U208-020-unique-language-project/test.py @@ -12,40 +12,45 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor -Wdir('tmp_') +Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches( gprfor( - prjid="ada_prj", srcdirs=[".."], - mains=["main.adb"], langs=["Ada"] - )), + prjid="ada_prj", srcdirs=[".."], mains=["main.adb"], langs=["Ada"] + ) + ), covlevel="stmt", mains=["main"], - extra_coverage_args=["--annotate=xcov"]) + extra_coverage_args=["--annotate=xcov"], +) for f in os.listdir("obj/ada_prj-gnatcov-instr"): if ext(f) not in LANGINFO["Ada"].src_ext: thistest.failed( f"{f} is not an Ada source. Instrumentation " - "of an Ada project should only produce Ada files.") + "of an Ada project should only produce Ada files." + ) break -check_xcov_reports('obj', {'main.adb.xcov': {'+': {3}}}) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {3}}}) build_run_and_coverage( gprsw=GPRswitches( - gprfor(prjid="c_prj", srcdirs=[".."], mains=["main.c"], langs=["C"])), + gprfor(prjid="c_prj", srcdirs=[".."], mains=["main.c"], langs=["C"]) + ), covlevel="stmt", mains=["main"], - extra_coverage_args=["--annotate=xcov"]) + extra_coverage_args=["--annotate=xcov"], +) for f in os.listdir("obj/c_prj-gnatcov-instr"): if ext(f) not in LANGINFO["C"].src_ext: thistest.failed( f"{f} is not a C source. Instrumentation " - "of a C project should only produce C files.") + "of a C project should only produce C files." + ) break -check_xcov_reports('obj', {'main.c.xcov': {'+': {4}}}) +check_xcov_reports("obj", {"main.c.xcov": {"+": {4}}}) thistest.result() diff --git a/testsuite/tests/U211-014-setup/test.py b/testsuite/tests/U211-014-setup/test.py index 3dcb8a806..e842c9d83 100644 --- a/testsuite/tests/U211-014-setup/test.py +++ b/testsuite/tests/U211-014-setup/test.py @@ -49,16 +49,15 @@ class PrjConfig: """ Project file, executable name and expected coverage report. """ + project_file: str objdir: str expected_cov: ExpectedCov @classmethod - def create(cls, - tag: str, - langs: List[str], - main: str, - expected_cov: ExpectedCov): + def create( + cls, tag: str, langs: List[str], main: str, expected_cov: ExpectedCov + ): objdir = f"obj-{tag}" return cls( project_file=gprfor( @@ -79,15 +78,21 @@ def gprsw(self): # Create simple projects to host our experiments ada_prj = PrjConfig.create( - tag="ada", langs=["Ada"], main="foo.adb", + tag="ada", + langs=["Ada"], + main="foo.adb", expected_cov={"foo.adb.xcov": {"+": {5}}}, ) c_prj = PrjConfig.create( - tag="c", langs=["C"], main="foo.c", + tag="c", + langs=["C"], + main="foo.c", expected_cov={"foo.c.xcov": {"+": {6, 7}}}, ) mixed_prj = PrjConfig.create( - tag="mixed", langs=["Ada", "C"], main="foo.adb", + tag="mixed", + langs=["Ada", "C"], + main="foo.adb", expected_cov={ "foo.adb.xcov": {"+": {11}}, "pkg.ads.xcov": {"+": {5, 6}}, @@ -114,8 +119,14 @@ def xsetup(args, out, register_failure=True, auto_config_args=True): ) -def check_full(label, setup_args, prj_config, runtime_project=rt_prj, - dump_channel="auto", auto_config_args=True): +def check_full( + label, + setup_args, + prj_config, + runtime_project=rt_prj, + dump_channel="auto", + auto_config_args=True, +): """ Run "gnatcov setup" with the arguments (setup_args), then compute code coverage and check the report for the given project (prj_config). @@ -134,12 +145,13 @@ def check_full(label, setup_args, prj_config, runtime_project=rt_prj, trace_mode="src", runtime_project=runtime_project, dump_channel=dump_channel, - extra_instr_args=["-v"] + extra_instr_args=["-v"], ) thistest.fail_if( "Successfully loaded the setup configuration file" not in contents_of("instrument.log"), - "Failed to load the setup config file in `gnatcov instrument`") + "Failed to load the setup config file in `gnatcov instrument`", + ) check_xcov_reports(f"xcov-{label}", prj_config.expected_cov) @@ -169,14 +181,13 @@ def check_full(label, setup_args, prj_config, runtime_project=rt_prj, # The core runtime is implemented in C, so C must be enabled thistest.log("== ada-only ==") log_file = "setup-ada-only.txt" -p = xsetup(["--restricted-to-languages=Ada"], - log_file, - register_failure=False) -thistest.fail_if(p.status == 0, - "gnatcov setup succeeded when we expected it to fail") +p = xsetup(["--restricted-to-languages=Ada"], log_file, register_failure=False) +thistest.fail_if( + p.status == 0, "gnatcov setup succeeded when we expected it to fail" +) thistest.fail_if_no_match( log_file, - '.*The C language must be enabled.*', + ".*The C language must be enabled.*", contents_of(log_file), ) @@ -198,7 +209,7 @@ def check_full(label, setup_args, prj_config, runtime_project=rt_prj, gprsw=mixed_prj.gprsw, covlevel="stmt", runtime_project=rt_prj, - out="instr-basic-bad-lang.txt" + out="instr-basic-bad-lang.txt", ) p = gprbuild( mixed_prj.project_file, @@ -208,8 +219,9 @@ def check_full(label, setup_args, prj_config, runtime_project=rt_prj, out=log_file, register_failure=False, ) -thistest.fail_if(p.status == 0, - "gprbuild succeeded when we expected it to fail") +thistest.fail_if( + p.status == 0, "gprbuild succeeded when we expected it to fail" +) thistest.fail_if_no_match( log_file, '.*foo.adb:.*"gnatcov_rts.ads" not found.*', @@ -246,8 +258,12 @@ def check_full(label, setup_args, prj_config, runtime_project=rt_prj, # Check C89 backward-compatibility, as we want to support instrumentation # with older toolchains. -check_full("ext_rt", [rt_ext_file, "-gargs", "-cargs:C", "-std=c89"], - ada_prj, dump_channel="base64-stdout") +check_full( + "ext_rt", + [rt_ext_file, "-gargs", "-cargs:C", "-std=c89"], + ada_prj, + dump_channel="base64-stdout", +) # Check that passing a full path to --runtime-project works check_full( diff --git a/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py index 741d33d8e..0d0865fbb 100644 --- a/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py +++ b/testsuite/tests/U219-010-ali-entry-guard-sloc/test.py @@ -22,8 +22,11 @@ checked_xcov(xcov_args, "coverage.log") -check_xcov_reports("obj", { - "main.adb.xcov": {"+": {11, 12, 13}, "-": {16, 17, 20, 21}}, -}) +check_xcov_reports( + "obj", + { + "main.adb.xcov": {"+": {11, 12, 13}, "-": {16, 17, 20, 21}}, + }, +) thistest.result() diff --git a/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.py b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.py index 878d36606..cc4edcb50 100644 --- a/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.py +++ b/testsuite/tests/U219-010-wrong-sloc-dominant-decision/test.py @@ -13,8 +13,7 @@ tmp = Wdir("tmp_") xcov_args = build_and_run( - gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], - mains=["main.adb"])), + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), covlevel="stmt", mains=["main"], extra_coverage_args=["-axcov"], @@ -23,12 +22,12 @@ # Artificially create wrong source locations to check that gnatcov does # not crash on these. -with open('obj/main.ali', 'r') as f: +with open("obj/main.ali", "r") as f: content = f.read() assert "CS >T5:4 6:7-6:17" in content content = content.replace(">T5:4", ">T5:5") -with open('obj/main.ali', 'w') as f: +with open("obj/main.ali", "w") as f: f.write(content) xcov(xcov_args, out="coverage.log") @@ -40,6 +39,7 @@ "!!! main.adb:6:7: dominant decision of statement SCO #4: STATEMENT " "at main.adb:6:7-17 has no associated SCO, discarding dominance " "information\n", - contents_of("coverage.log")) + contents_of("coverage.log"), +) thistest.result() diff --git a/testsuite/tests/U317-004-xml-report/test.py b/testsuite/tests/U317-004-xml-report/test.py index 5b68660be..ac942986f 100644 --- a/testsuite/tests/U317-004-xml-report/test.py +++ b/testsuite/tests/U317-004-xml-report/test.py @@ -14,16 +14,19 @@ gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains="main.adb")), covlevel="stmt", mains=["main"], - extra_coverage_args=["-a", "xml"]) + extra_coverage_args=["-a", "xml"], +) -if thistest.options.trace_mode == 'src': - expected_match = \ - '' + ) else: - expected_match = \ - '' + ) -thistest.fail_if(expected_match not in contents_of('obj/main.adb.xml')) +thistest.fail_if(expected_match not in contents_of("obj/main.adb.xml")) thistest.result() diff --git a/testsuite/tests/U416-006-big-bdd/test.py b/testsuite/tests/U416-006-big-bdd/test.py index c5340b742..b2f024fbc 100644 --- a/testsuite/tests/U416-006-big-bdd/test.py +++ b/testsuite/tests/U416-006-big-bdd/test.py @@ -16,6 +16,7 @@ tmp = Wdir() + def warning_re_for(filename, sloc): """ Return a regexp for the warning expected for the given file name and source @@ -34,7 +35,9 @@ def do_one_level(level): tmp.to_subdir(f"tmp_{level}") thistest.log(f"===== {level} =====") - gpr = gprfor(mains=["test_eval.adb"], srcdirs=["../src"], langs=["Ada", "C"]) + gpr = gprfor( + mains=["test_eval.adb"], srcdirs=["../src"], langs=["Ada", "C"] + ) build_run_and_coverage( gprsw=GPRswitches(root_project=gpr), @@ -62,11 +65,11 @@ def do_one_level(level): # coverage items in the report. if level == "stmt+mcdc": - expected_cov["testconditions.adb.xcov"]['?'] = {17} - expected_cov["compute.c.xcov"]['?'] = {4} + expected_cov["testconditions.adb.xcov"]["?"] = {17} + expected_cov["compute.c.xcov"]["?"] = {4} else: - expected_cov["testconditions.adb.xcov"]['+'].add(17) - expected_cov["compute.c.xcov"]['+'].add(4) + expected_cov["testconditions.adb.xcov"]["+"].add(17) + expected_cov["compute.c.xcov"]["+"].add(4) check_xcov_reports("obj", expected_cov, discard_empty=False) @@ -78,13 +81,17 @@ def do_one_level(level): thistest.fail_if_no_match( what="Unexpected/missing warnings for MC/DC path limit", - regexp="^" + "\n".join([ - warning_re_for("compute.c", "4:11"), - warning_re_for("testconditions.adb", "17:9"), - ]), + regexp="^" + + "\n".join( + [ + warning_re_for("compute.c", "4:11"), + warning_re_for("testconditions.adb", "17:9"), + ] + ), actual=log, ) + # Run the mcdc case do_one_level("stmt+mcdc") diff --git a/testsuite/tests/U429-016-gnatcov-misuse/test.py b/testsuite/tests/U429-016-gnatcov-misuse/test.py index 97af9932c..675a9937e 100644 --- a/testsuite/tests/U429-016-gnatcov-misuse/test.py +++ b/testsuite/tests/U429-016-gnatcov-misuse/test.py @@ -9,16 +9,17 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Generate a project, instrument it and run it -p = gprfor(mains=['main.adb'], srcdirs=['..']) +p = gprfor(mains=["main.adb"], srcdirs=[".."]) xcov_args = build_and_run( gprsw=GPRswitches(root_project=p), - covlevel='stmt', - mains=['main'], - extra_coverage_args=[]) + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], +) trace_file = xcov_args[-1] @@ -31,7 +32,8 @@ def check_output(output_file, expected_content): thistest.fail_if_no_match( '"gnatcov coverage" output ({})'.format(output_file), expected_content, - contents_of(output_file)) + contents_of(output_file), + ) def run_and_check(args, output_file, expected_content): @@ -44,22 +46,24 @@ def run_and_check(args, output_file, expected_content): thistest.fail_if( p.status == 0, 'the call to "gnatcov coverage" was expected to fail, yet it' - ' succeeded (see {})'.format(output_file) + " succeeded (see {})".format(output_file), ) check_output(output_file, expected_content) # Check that an error is emitted when using --units without -P run_and_check( - ['coverage', "--level=stmt", "--units=main", trace_file], - 'missing_project.txt', - '.*gnatcov.*: --units requires -P') + ["coverage", "--level=stmt", "--units=main", trace_file], + "missing_project.txt", + ".*gnatcov.*: --units requires -P", +) # Check the error message when not attempting to provide any SCOs run_and_check( - ['coverage', "--level=stmt", trace_file], - 'missing_scos.txt', - '.*gnatcov.*: Please specify SCOs on the command line, specifying Units ' - 'in project or using \\[--units and -P\\]\\|--scos\\|--sid\\..*') + ["coverage", "--level=stmt", trace_file], + "missing_scos.txt", + ".*gnatcov.*: Please specify SCOs on the command line, specifying Units " + "in project or using \\[--units and -P\\]\\|--scos\\|--sid\\..*", +) thistest.result() diff --git a/testsuite/tests/U527-020-dc-from-mcdc/test.py b/testsuite/tests/U527-020-dc-from-mcdc/test.py index 5ac38b6f7..737b8d2db 100644 --- a/testsuite/tests/U527-020-dc-from-mcdc/test.py +++ b/testsuite/tests/U527-020-dc-from-mcdc/test.py @@ -9,7 +9,7 @@ from SUITE.tutils import xcov, gprfor from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) @@ -20,21 +20,23 @@ xcov_args = build_and_run( gprsw=GPRswitches(root_project=gpr), extra_coverage_args=[], - covlevel='stmt+mcdc', - mains=['main'], - trace_mode='src') + covlevel="stmt+mcdc", + mains=["main"], + trace_mode="src", +) # Switch to --level=stmt+decision, add the arguments for the # output format/location then check that we can produce a report: xcov_args = [ - '--level=stmt+decision' if arg.startswith('--level') else arg - for arg in xcov_args] + "--level=stmt+decision" if arg.startswith("--level") else arg + for arg in xcov_args +] -xcov_args.extend(['--annotate=xcov', '--output-dir=xcov']) +xcov_args.extend(["--annotate=xcov", "--output-dir=xcov"]) xcov(xcov_args) -check_xcov_reports('xcov', {'main.adb.xcov': {'+': {2}, '!': {5}, '-': {6}}}) +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {2}, "!": {5}, "-": {6}}}) thistest.result() diff --git a/testsuite/tests/U811-028-suppress-output/test.py b/testsuite/tests/U811-028-suppress-output/test.py index f6231b383..2a805ddf2 100644 --- a/testsuite/tests/U811-028-suppress-output/test.py +++ b/testsuite/tests/U811-028-suppress-output/test.py @@ -16,11 +16,11 @@ tmp = Wdir("tmp_") p = gprfor( - mains=["main.adb"], - srcdirs=[".."], - extra='package Coverage is' - '\n for Switches ("Coverage") use ("--annotate=report");' - '\nend Coverage;\n' + mains=["main.adb"], + srcdirs=[".."], + extra="package Coverage is" + '\n for Switches ("Coverage") use ("--annotate=report");' + "\nend Coverage;\n", ) xcov_args = build_and_run( @@ -64,15 +64,17 @@ # of a coverage report specified in the project file but a checkpoint # is still emitted. -xcov(xcov_args + ["--cancel-annotate", "--save-checkpoint=prj_attr.ckpt"], - out='suppress-report-project-file.txt') +xcov( + xcov_args + ["--cancel-annotate", "--save-checkpoint=prj_attr.ckpt"], + out="suppress-report-project-file.txt", +) thistest.fail_if( not empty("suppress-report-project-file.txt"), - comment="report output not suppressed (from project file)" + comment="report output not suppressed (from project file)", ) thistest.fail_if( not exists("prj_attr.ckpt"), - comment="Checkpoint file does not exist (project attribute)" + comment="Checkpoint file does not exist (project attribute)", ) @@ -91,11 +93,11 @@ thistest.fail_if( not empty("suppress-report.txt"), - comment="report output not suppressed (from command line)" + comment="report output not suppressed (from command line)", ) thistest.fail_if( not exists("cmd_line_report.ckpt"), - comment="Checkpoint file does not exists (--annotate=report)" + comment="Checkpoint file does not exists (--annotate=report)", ) # Check that specifying --annotate=supress-output with --annotate=xcov on the @@ -117,7 +119,7 @@ ) thistest.fail_if( not exists("cmd_line_xcov.ckpt"), - comment="Checkpoint file does not exist (--annotate=xcov)" + comment="Checkpoint file does not exist (--annotate=xcov)", ) thistest.result() diff --git a/testsuite/tests/U901-029-estamps/test.py b/testsuite/tests/U901-029-estamps/test.py index eeab9f5f8..a4ba405ca 100644 --- a/testsuite/tests/U901-029-estamps/test.py +++ b/testsuite/tests/U901-029-estamps/test.py @@ -12,7 +12,7 @@ import re from datetime import date -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) @@ -20,13 +20,14 @@ # dates advertised in the report are consistent with what we perceive is the # current date. -report = 'report' +report = "report" xcov_args = build_run_and_coverage( gprsw=GPRswitches(root_project=gpr), extra_coverage_args=["--annotate=report", "-o", report], - covlevel='stmt', - mains=['main']) + covlevel="stmt", + mains=["main"], +) # We expect to find two items mentioning the date: # @@ -49,17 +50,18 @@ date_re = r"\d{4}-\d{2}-\d{2}" for pattern in ( - r"Date.*execution: (?P%s)" % date_re, - r"date *: (?P%s)" % date_re + r"Date.*execution: (?P%s)" % date_re, + r"date *: (?P%s)" % date_re, ): m = re.search(pattern=pattern, string=report) thistest.fail_if( - not m, - "couldn't find a match for pattern '%s' in report" % pattern) + not m, "couldn't find a match for pattern '%s' in report" % pattern + ) thistest.fail_if( - m.group('date') != today, - "date found (%s) doesn't match today (%s)" % (m.group('date'), today)) + m.group("date") != today, + "date found (%s) doesn't match today (%s)" % (m.group("date"), today), + ) thistest.result() diff --git a/testsuite/tests/UB18-055-switches-in-gprfile/test.py b/testsuite/tests/UB18-055-switches-in-gprfile/test.py index 8a6191ccf..313309cb1 100644 --- a/testsuite/tests/UB18-055-switches-in-gprfile/test.py +++ b/testsuite/tests/UB18-055-switches-in-gprfile/test.py @@ -11,7 +11,7 @@ from SUITE.gprutils import GPRswitches from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") gpr_coverage_package = """ package Coverage is @@ -21,19 +21,37 @@ end Coverage; """ -a_gpr = gprfor(mains=["main.adb"], prjid="a", srcdirs=os.path.join("..", "a"), - objdir="obj-a", deps=["b"], extra=gpr_coverage_package) -b_gpr = gprfor(mains=[], prjid="b", srcdirs=os.path.join("..", "b"), - langs=["Ada"], objdir="obj-b", deps=["c"]) -c_gpr = gprfor(mains=[], prjid="c", srcdirs=os.path.join("..", "c"), - langs=["Ada"], objdir="obj-c") +a_gpr = gprfor( + mains=["main.adb"], + prjid="a", + srcdirs=os.path.join("..", "a"), + objdir="obj-a", + deps=["b"], + extra=gpr_coverage_package, +) +b_gpr = gprfor( + mains=[], + prjid="b", + srcdirs=os.path.join("..", "b"), + langs=["Ada"], + objdir="obj-b", + deps=["c"], +) +c_gpr = gprfor( + mains=[], + prjid="c", + srcdirs=os.path.join("..", "c"), + langs=["Ada"], + objdir="obj-c", +) build_run_and_coverage( gprsw=GPRswitches(root_project=a_gpr), - covlevel='stmt', + covlevel="stmt", mains=["main"], gpr_obj_dir="obj-a", - extra_coverage_args=['-axcov', "--output-dir=."]) + extra_coverage_args=["-axcov", "--output-dir=."], +) # Check that we have coverage result only for the project of interest, as # specified in the gpr file. diff --git a/testsuite/tests/V201-010-multi-report/test.py b/testsuite/tests/V201-010-multi-report/test.py index b5b4db8e1..13a9f812f 100644 --- a/testsuite/tests/V201-010-multi-report/test.py +++ b/testsuite/tests/V201-010-multi-report/test.py @@ -17,11 +17,10 @@ xcov_args = build_run_and_coverage( gprsw=GPRswitches(root_project=gpr), - extra_coverage_args=["--annotate=report,xcov,dhtml", - "--annotate=xml"], + extra_coverage_args=["--annotate=report,xcov,dhtml", "--annotate=xml"], covlevel="stmt", mains=["main"], - out="coverage.log" + out="coverage.log", ) # For the xcov report kind we can check the actual content @@ -30,24 +29,22 @@ # Check that there is a report in the log of the coverage command thistest.fail_if_no_match( what="did not find report in the coverage output", - regexp=r'(.|\n)*' - r'\n\*\* COVERAGE REPORT \*\*' - r'(.|\n)*' - r'\n\*\* END OF REPORT \*\*', - actual=contents_of('coverage.log') + regexp=r"(.|\n)*" + r"\n\*\* COVERAGE REPORT \*\*" + r"(.|\n)*" + r"\n\*\* END OF REPORT \*\*", + actual=contents_of("coverage.log"), ) # For the others, we'll fall back to checking that there are files produced # in the expected directories thistest.fail_if( - not os.path.exists("obj/html/main.adb.hunk.js"), - "no html report produced" + not os.path.exists("obj/html/main.adb.hunk.js"), "no html report produced" ) thistest.fail_if( - not os.path.exists("obj/xml/main.adb.xml"), - "no xml report produced" + not os.path.exists("obj/xml/main.adb.xml"), "no xml report produced" ) thistest.result() diff --git a/testsuite/tests/V309-017-setup-config/test.py b/testsuite/tests/V309-017-setup-config/test.py index 5cbd2ff7f..3edd12cb9 100644 --- a/testsuite/tests/V309-017-setup-config/test.py +++ b/testsuite/tests/V309-017-setup-config/test.py @@ -41,8 +41,9 @@ def xsetup(install_name, args): [ "setup", f"--install-name={install_name}", - f"--prefix={rt_install_dir}" - ] + args, + f"--prefix={rt_install_dir}", + ] + + args, force_project_args=True, ) @@ -72,11 +73,12 @@ def xsetup(install_name, args): # * bin-file (the ultimate default for native targets). for label, rt_name, dump_args, expected_dump_channel in [ ("def_def", "rt_def", [], "bin-file"), - ("def_base64", - "rt_def", - ["--dump-channel=base64-stdout"], - "base64-stdout"), - + ( + "def_base64", + "rt_def", + ["--dump-channel=base64-stdout"], + "base64-stdout", + ), ("b64_def", "rt_b64", [], "base64-stdout"), ("b64_binfile", "rt_b64", ["--dump-channel=bin-file"], "bin-file"), ]: @@ -97,10 +99,14 @@ def xsetup(install_name, args): with open("obj/gnatcov-instr.json") as f: params = json.load(f) thistest.fail_if_not_equal( - "actual dump trigger", "atexit", params["dump-trigger"], + "actual dump trigger", + "atexit", + params["dump-trigger"], ) thistest.fail_if_not_equal( - "actual dump channel", expected_dump_channel, params["dump-channel"], + "actual dump channel", + expected_dump_channel, + params["dump-channel"], ) thistest.result() diff --git a/testsuite/tests/V520-019-duplicate-messages/test.py b/testsuite/tests/V520-019-duplicate-messages/test.py index cafbe71d4..16a342704 100644 --- a/testsuite/tests/V520-019-duplicate-messages/test.py +++ b/testsuite/tests/V520-019-duplicate-messages/test.py @@ -20,24 +20,26 @@ covlevel="stmt", mains=["main"], extra_coverage_args=["-areport,xcov", "--output-dir=obj"], - out="coverage.log" + out="coverage.log", ) # Check the expected results -expected_cov = {"main.adb.xcov": {}, "pkg.adb.xcov" : {'-': {10}}} +expected_cov = {"main.adb.xcov": {}, "pkg.adb.xcov": {"-": {10}}} if thistest.options.trace_mode == "src": expected_cov["pkg.ads.xcov"] = {} check_xcov_reports("obj", expected_cov, discard_empty=False) # Check that we do not have any duplicate messages. In this case, we only # expect a single statment violation. -thistest.fail_if_no_match("More than one violation detected", - r"(.|\n)*2.1. STMT COVERAGE" - r"\n------------------" - r"\n" - r"\npkg.adb:10:7: statement not executed" - r"\n" - r"\n1 violation.(.|\n)*", - contents_of("coverage.log")) +thistest.fail_if_no_match( + "More than one violation detected", + r"(.|\n)*2.1. STMT COVERAGE" + r"\n------------------" + r"\n" + r"\npkg.adb:10:7: statement not executed" + r"\n" + r"\n1 violation.(.|\n)*", + contents_of("coverage.log"), +) thistest.result() diff --git a/testsuite/tests/V616-028-xsd-check/test.py b/testsuite/tests/V616-028-xsd-check/test.py index 68bf5c56f..bc8861f01 100644 --- a/testsuite/tests/V616-028-xsd-check/test.py +++ b/testsuite/tests/V616-028-xsd-check/test.py @@ -25,8 +25,7 @@ def check_xml(xsd_file, xml_file): except Exception as exc: thistest.failed( "The XSD does not validate {}: \n {}".format( - os.path.abspath(xml_file), - exc + os.path.abspath(xml_file), exc ) ) @@ -42,11 +41,12 @@ def xml_file(output_dir): def build_run_coverage_and_check(covlevel): build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], - mains=["test.adb"])), + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["test.adb"]) + ), covlevel=covlevel, mains=["test"], - extra_coverage_args=["--annotate=xml"] + extra_coverage_args=["--annotate=xml"], ) check_xml(xsd_file("obj"), xml_file("obj")) diff --git a/testsuite/tests/V824-005-sid-ext-prj/test.py b/testsuite/tests/V824-005-sid-ext-prj/test.py index 893fc8a32..5e8da86f5 100644 --- a/testsuite/tests/V824-005-sid-ext-prj/test.py +++ b/testsuite/tests/V824-005-sid-ext-prj/test.py @@ -47,7 +47,7 @@ xcov(xcov_args, out="coverage.log") check_xcov_reports( "output", - {"pkg.adb.xcov": {'+': {11}}, "pkg.ads.xcov": {}}, + {"pkg.adb.xcov": {"+": {11}}, "pkg.ads.xcov": {}}, discard_empty=False, ) diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py index 262c1e51d..81d023d93 100644 --- a/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py +++ b/testsuite/tests/V824-009-dump-trigger-main-end/ignore-main/test.py @@ -9,18 +9,19 @@ from SUITE.tutils import gprfor from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(mains=['test.c'], srcdirs=['..']), - units=["foo.c"]), - covlevel='stmt+mcdc', - mains=['test'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src', - dump_trigger='main-end', + gprsw=GPRswitches( + root_project=gprfor(mains=["test.c"], srcdirs=[".."]), units=["foo.c"] + ), + covlevel="stmt+mcdc", + mains=["test"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="main-end", ) -check_xcov_reports('xcov', {'foo.c.xcov': {'+': {4}}}) +check_xcov_reports("xcov", {"foo.c.xcov": {"+": {4}}}) thistest.result() diff --git a/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py b/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py index f5542b8fb..cb2547056 100644 --- a/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py +++ b/testsuite/tests/V824-009-dump-trigger-main-end/main-unit-of-interest/test.py @@ -11,17 +11,17 @@ from SUITE.tutils import gprfor from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(mains=['test.c'], srcdirs=['..'])), - covlevel='stmt+mcdc', - mains=['test'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src', - dump_trigger='main-end', + gprsw=GPRswitches(root_project=gprfor(mains=["test.c"], srcdirs=[".."])), + covlevel="stmt+mcdc", + mains=["test"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="main-end", ) -check_xcov_reports('xcov', {'test.c.xcov': {'+': {4}, '!': {5}}}) +check_xcov_reports("xcov", {"test.c.xcov": {"+": {4}, "!": {5}}}) thistest.result() diff --git a/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py index 93784100a..6fca30fc1 100644 --- a/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py +++ b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py @@ -28,8 +28,7 @@ covlevel="stmt+mcdc", mains=["main"], trace_mode="src", - tolerate_instrument_messages=\ - "cannot instrument generic expression function", + tolerate_instrument_messages="cannot instrument generic expression function", ) check_xcov_reports( diff --git a/testsuite/tests/VB07-015-clean-output-dir/test.py b/testsuite/tests/VB07-015-clean-output-dir/test.py index 77c7770d4..73a90627d 100644 --- a/testsuite/tests/VB07-015-clean-output-dir/test.py +++ b/testsuite/tests/VB07-015-clean-output-dir/test.py @@ -67,7 +67,7 @@ def check_one(units, output_dir, xcov_args): check_one( ["main.adb", "pkg.adb", "pkg.ads"], os.path.join("obj", "xcov"), - xcov_args + ["-axcov,html"] + xcov_args + ["-axcov,html"], ) # An finally check that the subdir is also cleaned when once again generating diff --git a/testsuite/tests/Z999-999/test.py b/testsuite/tests/Z999-999/test.py index 06cb5382c..49fdfa77e 100644 --- a/testsuite/tests/Z999-999/test.py +++ b/testsuite/tests/Z999-999/test.py @@ -2,8 +2,8 @@ print("tool versions are now emitted as comments attached to this run") -print('valgrind control: ' + str(maybe_valgrind([]))) +print("valgrind control: " + str(maybe_valgrind([]))) -print('End of Z999-999') +print("End of Z999-999") # This test will fail by not calling thistest.result() diff --git a/testsuite/tests/asm-consolidate/test.py b/testsuite/tests/asm-consolidate/test.py index 19af6b2bf..f12fd96c8 100644 --- a/testsuite/tests/asm-consolidate/test.py +++ b/testsuite/tests/asm-consolidate/test.py @@ -6,8 +6,15 @@ from SUITE.context import thistest from SUITE.control import target_info -from SUITE.tutils import (exename_for, exepath_to, gprbuild, gprfor, xcov, - xrun, tracename_for) +from SUITE.tutils import ( + exename_for, + exepath_to, + gprbuild, + gprfor, + xcov, + xrun, + tracename_for, +) from SUITE.cutils import Wdir @@ -15,29 +22,31 @@ # Build two programs using a common "lib" unit, organized so the unit object # code is placed at different addresses in the two executables. -gpr = gprfor(srcdirs=["../src"], mains=['p1.adb', 'p2.adb']) +gpr = gprfor(srcdirs=["../src"], mains=["p1.adb", "p2.adb"]) gprbuild(gpr) # Check that the lib subprograms are at different addresses -libsym = target_info().to_platform_specific_symbol('lib__adjust') +libsym = target_info().to_platform_specific_symbol("lib__adjust") def address_range_for(symname, bin): m = re.search( - pattern=r'(?P\S*-\S*) symbol for %s' % symname, - string=xcov(['dump-symbols', bin]).out) + pattern=r"(?P\S*-\S*) symbol for %s" % symname, + string=xcov(["dump-symbols", bin]).out, + ) - return m.group('address_range') + return m.group("address_range") thistest.fail_if( - address_range_for(libsym, exename_for('p1')) - == address_range_for(libsym, exename_for('p2')), - 'address ranges for %s are identical' % libsym) + address_range_for(libsym, exename_for("p1")) + == address_range_for(libsym, exename_for("p2")), + "address ranges for %s are identical" % libsym, +) # Execute both programs: -xrun(exepath_to('p1')) -xrun(exepath_to('p2')) +xrun(exepath_to("p1")) +xrun(exepath_to("p2")) # Do object level coverage analysis. We expect each program to cover the # lib symbol only partially, and the two combined to cover the lib symbol @@ -45,20 +54,22 @@ def address_range_for(symname, bin): def check(pgmlist): - covnote = '!' if len(pgmlist) == 1 else '+' + covnote = "!" if len(pgmlist) == 1 else "+" out = xcov( - 'coverage --level=branch --annotate=asm %s --routines=%s' % ( - ' '.join(tracename_for(pgm) for pgm in pgmlist), libsym)).out + "coverage --level=branch --annotate=asm %s --routines=%s" + % (" ".join(tracename_for(pgm) for pgm in pgmlist), libsym) + ).out - results = re.findall(string=out, pattern='%s \\%c:' % (libsym, covnote)) + results = re.findall(string=out, pattern="%s \\%c:" % (libsym, covnote)) thistest.fail_if( len(results) != 1, - "unexpected #matches for %s:\n%s" % (pgmlist, results)) + "unexpected #matches for %s:\n%s" % (pgmlist, results), + ) -check(pgmlist=['p1']) -check(pgmlist=['p2']) -check(pgmlist=['p1', 'p2']) +check(pgmlist=["p1"]) +check(pgmlist=["p2"]) +check(pgmlist=["p1", "p2"]) thistest.result() diff --git a/testsuite/tests/branch-cond/IB13-014-const-instances/test.py b/testsuite/tests/branch-cond/IB13-014-const-instances/test.py index 9f1f9fdde..7215f7151 100644 --- a/testsuite/tests/branch-cond/IB13-014-const-instances/test.py +++ b/testsuite/tests/branch-cond/IB13-014-const-instances/test.py @@ -2,6 +2,9 @@ from SCOV.map import MapChecker -MapChecker(sources=["services.adb", "test_services.adb"], - execs=["test_services"], alis="obj/services.ali").run() +MapChecker( + sources=["services.adb", "test_services.adb"], + execs=["test_services"], + alis="obj/services.ali", +).run() thistest.result() diff --git a/testsuite/tests/branch-cond/IB15-004-spec-precond/test.py b/testsuite/tests/branch-cond/IB15-004-spec-precond/test.py index ab3d00c67..66ae79677 100644 --- a/testsuite/tests/branch-cond/IB15-004-spec-precond/test.py +++ b/testsuite/tests/branch-cond/IB15-004-spec-precond/test.py @@ -4,7 +4,10 @@ MapChecker("checkx.adb", options="-gnata -save-temps").run() -MapChecker(sources=["services.adb", "test_services.ads"], options="-gnata", - execs=[exename_for("test_services")], - alis=["obj/services.ali"]).run() +MapChecker( + sources=["services.adb", "test_services.ads"], + options="-gnata", + execs=[exename_for("test_services")], + alis=["obj/services.ali"], +).run() thistest.result() diff --git a/testsuite/tests/build_run-assert-failure/test.py b/testsuite/tests/build_run-assert-failure/test.py index 76b75cb9d..f012a22dc 100644 --- a/testsuite/tests/build_run-assert-failure/test.py +++ b/testsuite/tests/build_run-assert-failure/test.py @@ -23,14 +23,15 @@ mains=["p"], covlevel="stmt", extra_coverage_args=[], - register_failure=True + register_failure=True, ) except FatalError: pass else: thistest.stop( FatalError( - "expected FatalError from build_and_run, got different exception") + "expected FatalError from build_and_run, got different exception" + ) ) # If we reach here, the test is PASSED. The failure registration diff --git a/testsuite/tests/cobertura_validation/test.py b/testsuite/tests/cobertura_validation/test.py index 26138fe78..64efeb271 100644 --- a/testsuite/tests/cobertura_validation/test.py +++ b/testsuite/tests/cobertura_validation/test.py @@ -18,13 +18,19 @@ sync_tree(os.path.join("..", "src"), "src") -gprsw = gprsw = GPRswitches(root_project=gprfor(srcdirs=["src"], mains=["test.adb"])) +gprsw = gprsw = GPRswitches( + root_project=gprfor(srcdirs=["src"], mains=["test.adb"]) +) scos_list = ["obj/lib.c", "obj/pkg", "obj/test"] def build_run_coverage_and_check( - covlevel, output_opt=None, source_root=None, hide_src=False, expected_filenames=None + covlevel, + output_opt=None, + source_root=None, + hide_src=False, + expected_filenames=None, ): # We need to use manually designated SCOs if we are to remove the sources # from the project. @@ -86,7 +92,9 @@ def build_run_coverage_and_check( thistest.log(f"== Prefix: {prefix} ==") build_run_coverage_and_check( - "stmt", source_root=os.path.join(os.getcwd(), prefix), expected_filenames=expected_filenames + "stmt", + source_root=os.path.join(os.getcwd(), prefix), + expected_filenames=expected_filenames, ) # Check that the report can be emitted in the absence of the project sources. We @@ -100,7 +108,7 @@ def build_run_coverage_and_check( "cobertura-no_src.xml", source_root=os.path.join(os.getcwd(), "src"), hide_src=True, - expected_filenames=expected_filenames + expected_filenames=expected_filenames, ) thistest.result() diff --git a/testsuite/tests/excluded_unit_imported_prj/test.py b/testsuite/tests/excluded_unit_imported_prj/test.py index a57fa295c..cbfecd34b 100644 --- a/testsuite/tests/excluded_unit_imported_prj/test.py +++ b/testsuite/tests/excluded_unit_imported_prj/test.py @@ -8,9 +8,9 @@ from SUITE.cutils import contents_of, Wdir from SUITE.tutils import thistest, gprfor -Wdir('tmp_') +Wdir("tmp_") -prj1 = gprfor(mains=[], prjid='prj1', srcdirs=['../prj1'], objdir='obj-prj1') +prj1 = gprfor(mains=[], prjid="prj1", srcdirs=["../prj1"], objdir="obj-prj1") # Check that ignoring pkg.c in the main project yields a warning, as the pkg.c # unit is in the prj1 dependency and not in the root project. @@ -19,32 +19,32 @@ for Excluded_Units use ("pkg.c"); end Coverage; """ -p = gprfor(mains=['test.c'], deps=['prj1'], srcdirs=['..'], extra=extra_p) +p = gprfor(mains=["test.c"], deps=["prj1"], srcdirs=[".."], extra=extra_p) build_run_and_coverage( gprsw=GPRswitches(root_project=p), - covlevel='stmt+mcdc', - mains=['test'], - extra_coverage_args=['--annotate=xcov'], + covlevel="stmt+mcdc", + mains=["test"], + extra_coverage_args=["--annotate=xcov"], tolerate_instrument_messages="no unit .* in project", ) -warning_file = ('coverage.log' if thistest.options.trace_mode == 'bin' - else 'instrument.log') +warning_file = ( + "coverage.log" + if thistest.options.trace_mode == "bin" + else "instrument.log" +) thistest.fail_if_not_equal( warning_file, - 'warning: no unit pkg.c in project gen' - ' (coverage.excluded_units attribute)\n', - contents_of(warning_file) + "warning: no unit pkg.c in project gen" + " (coverage.excluded_units attribute)\n", + contents_of(warning_file), ) # Check that pkg.c is not ignored by checking the report contents check_xcov_reports( - 'obj', - { - 'pkg.c.xcov': {'!': {4}}, - 'test.c.xcov': {'+': {6, 7}} - }, + "obj", + {"pkg.c.xcov": {"!": {4}}, "test.c.xcov": {"+": {6, 7}}}, ) thistest.result() diff --git a/testsuite/tests/exemptions-check/test.py b/testsuite/tests/exemptions-check/test.py index 7632138e1..e5758222f 100644 --- a/testsuite/tests/exemptions-check/test.py +++ b/testsuite/tests/exemptions-check/test.py @@ -9,14 +9,15 @@ from SUITE.tutils import gprbuild, gprfor, xcov -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") -gprbuild(gprfor(['hello.adb'], srcdirs='../src')) +gprbuild(gprfor(["hello.adb"], srcdirs="../src")) -xcov(['map-routines', '--scos=obj/hello.ali', 'obj/hello.o'], "out") +xcov(["map-routines", "--scos=obj/hello.ali", "obj/hello.o"], "out") dif = diff("../expected", "out") thistest.fail_if( - dif, "out != expected on exemption pragma placement rules:\n" + dif) + dif, "out != expected on exemption pragma placement rules:\n" + dif +) thistest.result() diff --git a/testsuite/tests/gnatcov-run.py b/testsuite/tests/gnatcov-run.py index f7b51c749..c7e8fe98e 100755 --- a/testsuite/tests/gnatcov-run.py +++ b/testsuite/tests/gnatcov-run.py @@ -36,59 +36,60 @@ def parse_command_line(self): op = optparse.OptionParser() # --level and --target are expected to always be there: - op.add_option('--level', dest='covlevel', default=None) - op.add_option('--target', dest='target', default=None) + op.add_option("--level", dest="covlevel", default=None) + op.add_option("--target", dest="target", default=None) # For source coverage tests not using project files: - op.add_option('--scos', dest='scos', default=None) + op.add_option("--scos", dest="scos", default=None) # For tests using project files - op.add_option('-P', dest='gpr', default=None) - op.add_option('--recursive', dest='recurse', default=False, - action='store_true') - op.add_option('--projects', dest='projects', default=None) - op.add_option('--units', dest='units', default=None) + op.add_option("-P", dest="gpr", default=None) + op.add_option( + "--recursive", dest="recurse", default=False, action="store_true" + ) + op.add_option("--projects", dest="projects", default=None) + op.add_option("--units", dest="units", default=None) # Then a few optional items - op.add_option('-o', dest='ofile', default=None) + op.add_option("-o", dest="ofile", default=None) self.options, self.args = op.parse_args() def run_command_line(self): """Compute a list of command line arguments to pass to gnatcov run from what we have received.""" - args = ['--level=%s' % self.options.covlevel, - '--target=%s' % self.options.target] + args = [ + "--level=%s" % self.options.covlevel, + "--target=%s" % self.options.target, + ] if self.options.scos: - args.append('--scos=%s' % self.options.scos) + args.append("--scos=%s" % self.options.scos) if self.options.gpr: - args.append('-P=%s' % self.options.gpr) + args.append("-P=%s" % self.options.gpr) if self.options.gpr: - args.append('--projects=%s' % self.options.projects) + args.append("--projects=%s" % self.options.projects) if self.options.gpr: - args.append('--units=%s' % self.options.units) + args.append("--units=%s" % self.options.units) if self.options.recurse: - args.append('--recursive') + args.append("--recursive") if self.options.ofile: - args.append('-o %s' % self.options.ofile) + args.append("-o %s" % self.options.ofile) return args def run(self): - - print('============== GNATCOV RUN ===================') + print("============== GNATCOV RUN ===================") if not self.args: - print('gnatcov: missing EXE for run') + print("gnatcov: missing EXE for run") os.exit(1) - Run( - ['gnatcov', 'run'] + self.run_command_line() + self.args) + Run(["gnatcov", "run"] + self.run_command_line() + self.args) - print('==============================================') + print("==============================================") runner = Runner() diff --git a/testsuite/tests/gpr-scos/test.py b/testsuite/tests/gpr-scos/test.py index 2d6654077..c6b525b46 100644 --- a/testsuite/tests/gpr-scos/test.py +++ b/testsuite/tests/gpr-scos/test.py @@ -13,15 +13,16 @@ from SUITE.tutils import gprfor, xcov -wd = Wdir('tmp_') +wd = Wdir("tmp_") # Build and run our example test, 1 driver + 2 units -project = gprfor(srcdirs=['../src'], mains=['test_ops.adb']) +project = gprfor(srcdirs=["../src"], mains=["test_ops.adb"]) xcov_args = build_and_run( gprsw=GPRswitches(root_project=project), - covlevel='stmt', - mains=['test_ops'], - extra_coverage_args=['--annotate=xcov']) + covlevel="stmt", + mains=["test_ops"], + extra_coverage_args=["--annotate=xcov"], +) # Now exercise various combinations of units of interest @@ -32,39 +33,42 @@ # regardless of --scos or -P, so they are straightforward to find # or remove in all circumstances. + def trycov(sco_units, with_project, expected_reports): - rm('*.xcov', recursive=False) + rm("*.xcov", recursive=False) - src_trace = thistest.options.trace_mode == 'src' + src_trace = thistest.options.trace_mode == "src" sco_args = [ - '--{}=obj/{}.{}'.format('sid' if src_trace else 'scos', - unit, - 'sid' if src_trace else 'ali') + "--{}=obj/{}.{}".format( + "sid" if src_trace else "scos", unit, "sid" if src_trace else "ali" + ) for unit in sco_units ] - project_args = ['-P', project] if with_project else [] - xcov(xcov_args + sco_args + project_args + ['--output-dir=.']) + project_args = ["-P", project] if with_project else [] + xcov(xcov_args + sco_args + project_args + ["--output-dir=."]) - reports = ls('*.xcov') + reports = ls("*.xcov") thistest.fail_if( set(reports) != set(expected_reports), - 'With %s, %s (found) != %s (expected)' % ( - str(sco_args), str(reports), str(expected_reports))) + "With %s, %s (found) != %s (expected)" + % (str(sco_args), str(reports), str(expected_reports)), + ) # --scos/--sid alone -trycov(sco_units=['inc'], with_project=False, - expected_reports=['inc.adb.xcov']) +trycov( + sco_units=["inc"], with_project=False, expected_reports=["inc.adb.xcov"] +) # -P alone -trycov(sco_units=[], with_project=True, - expected_reports=['inc.adb.xcov', - 'dec.adb.xcov', - 'test_ops.adb.xcov']) +trycov( + sco_units=[], + with_project=True, + expected_reports=["inc.adb.xcov", "dec.adb.xcov", "test_ops.adb.xcov"], +) # --scos with -P, check that --scos prevails -trycov(sco_units=['dec'], with_project=True, - expected_reports=['dec.adb.xcov']) +trycov(sco_units=["dec"], with_project=True, expected_reports=["dec.adb.xcov"]) thistest.result() diff --git a/testsuite/tests/homonym-units-of-interest/test.py b/testsuite/tests/homonym-units-of-interest/test.py index 294f6e088..405e71a1f 100644 --- a/testsuite/tests/homonym-units-of-interest/test.py +++ b/testsuite/tests/homonym-units-of-interest/test.py @@ -14,21 +14,21 @@ from SUITE.cutils import Wdir from SUITE.tutils import thistest, gprfor, xcov -wd = Wdir('tmp_') +wd = Wdir("tmp_") # Run the build and run in a dedicated directory -prj1 = gprfor(mains=[], prjid='prj1', srcdirs=['../prj1'], objdir='obj-prj1') -prj2 = gprfor(mains=[], prjid='prj2', srcdirs=['../prj2'], objdir='obj-prj2') -p = gprfor(mains=['test.c'], deps=['prj1', 'prj2'], srcdirs=['..']) +prj1 = gprfor(mains=[], prjid="prj1", srcdirs=["../prj1"], objdir="obj-prj1") +prj2 = gprfor(mains=[], prjid="prj2", srcdirs=["../prj2"], objdir="obj-prj2") +p = gprfor(mains=["test.c"], deps=["prj1", "prj2"], srcdirs=[".."]) xcov_args = build_and_run( # TODO: The test fails if we pass an absolute path to root_project, which # is unexpected. gprsw=GPRswitches(root_project=os.path.basename(p)), - covlevel='stmt+mcdc', - mains=['test'], - extra_coverage_args=['--annotate=xcov', '--output-dir=xcov'], + covlevel="stmt+mcdc", + mains=["test"], + extra_coverage_args=["--annotate=xcov", "--output-dir=xcov"], ) # Now onto coverage. Try to ignore pkg.c in prj1, and in prj2 in two different @@ -59,11 +59,16 @@ def check_report(prj_ignore, prj_of_interest): Check that the report is correct when the homonym source file (pkg.c) is ignored in prj_ignore and of interest in prj_of_interest. """ - subdir = f'tmp_cov_ignore_{prj_ignore}' + subdir = f"tmp_cov_ignore_{prj_ignore}" wd = Wdir(subdir) - sync_tree(os.path.join('..', 'tmp_'), '.') - gprfor(mains=[], prjid=prj_ignore, srcdirs=[f'../{prj_ignore}'], - objdir=f'obj-{prj_ignore}', extra=ignore_pkg) + sync_tree(os.path.join("..", "tmp_"), ".") + gprfor( + mains=[], + prjid=prj_ignore, + srcdirs=[f"../{prj_ignore}"], + objdir=f"obj-{prj_ignore}", + extra=ignore_pkg, + ) xcov(xcov_args) # The filtering of units of interest is done at a later stage for binary @@ -72,19 +77,17 @@ def check_report(prj_ignore, prj_of_interest): # suffix computed from gnatcov file table to differentiate homonym source # files will be different from source traces. xcov_homonoym_filename = ( - f'{prj_of_interest}-pkg.c.xcov' if thistest.options.trace_mode == 'bin' - else 'pkg.c.xcov' + f"{prj_of_interest}-pkg.c.xcov" + if thistest.options.trace_mode == "bin" + else "pkg.c.xcov" ) check_xcov_reports( - 'xcov', - { - xcov_homonoym_filename: {'!': {4}}, - 'test.c.xcov': {'+': {7, 8, 9}} - }, + "xcov", + {xcov_homonoym_filename: {"!": {4}}, "test.c.xcov": {"+": {7, 8, 9}}}, ) wd.to_homedir() -check_report('prj1', 'prj2') -check_report('prj2', 'prj1') +check_report("prj1", "prj2") +check_report("prj2", "prj1") thistest.result() diff --git a/testsuite/tests/ignored-c-header/test.py b/testsuite/tests/ignored-c-header/test.py index fd8ed898f..4e3dfb1e6 100644 --- a/testsuite/tests/ignored-c-header/test.py +++ b/testsuite/tests/ignored-c-header/test.py @@ -16,11 +16,8 @@ mains=["test"], extra_coverage_args=[ "--annotate=xcov", - # Ignore directly "twice.h" - "--ignore-source-files=twice.h", - # Ignore indirectly "identity.h", as its CU's origin is "identity.c". # It is important for test reliability to check this testcase that only # "identity.c" includes "identity.h". diff --git a/testsuite/tests/ignored-casing/test.py b/testsuite/tests/ignored-casing/test.py index b1c390922..fc32b3768 100644 --- a/testsuite/tests/ignored-casing/test.py +++ b/testsuite/tests/ignored-casing/test.py @@ -27,7 +27,9 @@ covlevel="stmt", mains=["main"], extra_coverage_args=[ - "--annotate=xcov", "--output-dir=out-cov", ignore_opt + "--annotate=xcov", + "--output-dir=out-cov", + ignore_opt, ], ) check_xcov_reports("out-cov", expected_reports) @@ -46,7 +48,7 @@ mains=["main"], extra_instr_args=[ignore_opt], extra_coverage_args=["--annotate=xcov", "--output-dir=out-instr"], - trace_mode="src" + trace_mode="src", ) check_xcov_reports("out-instr", expected_reports, discard_empty=False) tmp.to_homedir() diff --git a/testsuite/tests/instr-cov/126-main-in-dependency/test.py b/testsuite/tests/instr-cov/126-main-in-dependency/test.py index 798bf3d39..96b3b1402 100644 --- a/testsuite/tests/instr-cov/126-main-in-dependency/test.py +++ b/testsuite/tests/instr-cov/126-main-in-dependency/test.py @@ -12,17 +12,25 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") -main_prj = gprfor(srcdirs=[os.path.join("..", "src-main-dep")], - prjid="main_dep", mains=["main.adb"], objdir="obj-main") -root_prj = gprfor(srcdirs=[os.path.join("..", "src")], deps=[main_prj], - mains=["main_root.adb"], objdir="obj") +main_prj = gprfor( + srcdirs=[os.path.join("..", "src-main-dep")], + prjid="main_dep", + mains=["main.adb"], + objdir="obj-main", +) +root_prj = gprfor( + srcdirs=[os.path.join("..", "src")], + deps=[main_prj], + mains=["main_root.adb"], + objdir="obj", +) # This also checks that we do not produce multiple traces build_run_and_coverage( gprsw=GPRswitches(root_project=root_prj), - covlevel='stmt', + covlevel="stmt", mains=["main_root"], extra_coverage_args=["-axcov"], ) diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/test.py b/testsuite/tests/instr-cov/217-runtime-subunit/test.py index fbbac3c28..9caec2f99 100644 --- a/testsuite/tests/instr-cov/217-runtime-subunit/test.py +++ b/testsuite/tests/instr-cov/217-runtime-subunit/test.py @@ -25,9 +25,7 @@ covlevel="stmt+mcdc", auto_config_args=False, auto_target_args=False, - extra_args=[ - "--target", thistest.env.target.triplet, "--RTS", runtime_dir - ], + extra_args=["--target", thistest.env.target.triplet, "--RTS", runtime_dir], ) thistest.result() diff --git a/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py b/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py index 320d4b463..e7565c956 100644 --- a/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py +++ b/testsuite/tests/instr-cov/C++/c++_no_warnings/test.py @@ -9,17 +9,17 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.cpp'])), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - extra_gprbuild_cargs=['-Werror'], - trace_mode='src', + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.cpp"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + extra_gprbuild_cargs=["-Werror"], + trace_mode="src", ) -check_xcov_reports('xcov', {'main.cpp.xcov': {'+': {4}}}) +check_xcov_reports("xcov", {"main.cpp.xcov": {"+": {4}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/C++/explicit_lang/test.py b/testsuite/tests/instr-cov/C++/explicit_lang/test.py index 2423ece7a..1dc226e0e 100644 --- a/testsuite/tests/instr-cov/C++/explicit_lang/test.py +++ b/testsuite/tests/instr-cov/C++/explicit_lang/test.py @@ -11,10 +11,12 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") p = gprfor( - srcdirs=[".."], mains=["main.c"], langs=["C++"], + srcdirs=[".."], + mains=["main.c"], + langs=["C++"], extra=""" package Naming is for Body_Suffix ("C++") use ".c"; @@ -24,10 +26,10 @@ # Build and produce a coverage report for the test project. build_run_and_coverage( gprsw=GPRswitches(root_project=p), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src', + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", ) check_xcov_reports("xcov", {"main.c.xcov": {"+": {6, 7}}}) diff --git a/testsuite/tests/instr-cov/C++/std-c++20/test.py b/testsuite/tests/instr-cov/C++/std-c++20/test.py index 4ec9a14f4..6c3b49738 100644 --- a/testsuite/tests/instr-cov/C++/std-c++20/test.py +++ b/testsuite/tests/instr-cov/C++/std-c++20/test.py @@ -12,8 +12,7 @@ def gen_prj(): - return GPRswitches(root_project=gprfor(srcdirs=[".."], - mains=["main.cpp"])) + return GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.cpp"])) tmp = Wdir("tmp_valid-instrumentation") diff --git a/testsuite/tests/instr-cov/C++/std-cond-code/test.py b/testsuite/tests/instr-cov/C++/std-cond-code/test.py index 229d1e9e4..6d1964aff 100644 --- a/testsuite/tests/instr-cov/C++/std-cond-code/test.py +++ b/testsuite/tests/instr-cov/C++/std-cond-code/test.py @@ -10,8 +10,13 @@ from SUITE.gprutils import GPRswitches -def run_variant(variant_name, extra_instr_cppargs, extra_gprbuild_cargs, - tolerate_instrument_messages=None, pred=lambda: True): +def run_variant( + variant_name, + extra_instr_cppargs, + extra_gprbuild_cargs, + tolerate_instrument_messages=None, + pred=lambda: True, +): """ Build and run the project with the given arguments, and check the predicate holds. @@ -24,8 +29,9 @@ def run_variant(variant_name, extra_instr_cppargs, extra_gprbuild_cargs, tmp = Wdir(f"tmp_{variant_name}") build_and_run( - gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], - mains=["main.cpp"])), + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.cpp"]) + ), covlevel="stmt", mains=["main"], extra_instr_args=[f"--c++-opts={','.join(extra_instr_cppargs)}"], @@ -37,8 +43,7 @@ def run_variant(variant_name, extra_instr_cppargs, extra_gprbuild_cargs, ) thistest.fail_if( - not pred(), - f"Unexpected assertion failure for variant {variant_name}" + not pred(), f"Unexpected assertion failure for variant {variant_name}" ) tmp.to_homedir() diff --git a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py index 774b8033e..d6f9a9a34 100644 --- a/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py +++ b/testsuite/tests/instr-cov/O212-062-unsupported-pragmas/test.py @@ -5,39 +5,45 @@ type invariants. """ -from SCOV.minicheck import (check_xcov_reports, build_and_run, xcov) +from SCOV.minicheck import check_xcov_reports, build_and_run, xcov from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of from SUITE.tutils import gprfor from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") xcov_args = build_and_run( gprsw=GPRswitches( - root_project=gprfor(srcdirs=["../"], - mains=["main.adb"])), + root_project=gprfor(srcdirs=["../"], mains=["main.adb"]) + ), mains=["main"], extra_coverage_args=["-axcov", "--output-dir=xcov"], covlevel="stmt+decision+atcc", register_failure=False, - ) +) thistest.fail_if_no_match( "'gnatcov instrument' output", r".*gnatcov limitation: pragma Precondition ignored.*\n" + r".*gnatcov limitation: pragma Postcondition ignored.*\n" + r".*gnatcov limitation: pragma Type_Invariant ignored.*", - contents_of("instrument.log").strip()) + contents_of("instrument.log").strip(), +) xcov(xcov_args) -check_xcov_reports('xcov', { - 'pkg_type_invariant.ads.xcov': {'+': {6, 13, 14, 15, 16, 20}, - '-': {22}}, - 'main.adb.xcov': {'+': {6, 8, 12}}, -}) +check_xcov_reports( + "xcov", + { + "pkg_type_invariant.ads.xcov": { + "+": {6, 13, 14, 15, 16, 20}, + "-": {22}, + }, + "main.adb.xcov": {"+": {6, 8, 12}}, + }, +) thistest.result() diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py index 3cb16f9e6..d11c41e16 100644 --- a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py @@ -17,28 +17,30 @@ def create_lib_gpr(name, deps=[]): :param name: Name of the library. """ - return gprfor(mains=[], - prjid=name, - srcdirs=f"../src-{name}", - langs=["C"], - deps=deps, - extra=f""" + return gprfor( + mains=[], + prjid=name, + srcdirs=f"../src-{name}", + langs=["C"], + deps=deps, + extra=f""" for Library_Name use "{name}"; for Library_Dir use "{name}"; - """ - ) + """, + ) tmp = Wdir("tmp_") # Create the GPR file for the root project -src_gpr = gprfor(mains=["main.c"], - prjid="main", - srcdirs="../src", - objdir="obj", - langs=["C"], - deps=["lib1", "lib2"] - ) +src_gpr = gprfor( + mains=["main.c"], + prjid="main", + srcdirs="../src", + objdir="obj", + langs=["C"], + deps=["lib1", "lib2"], +) # Create the GPR files for the libraries lib1_gpr = create_lib_gpr("lib1", ["lib2"]) @@ -46,12 +48,20 @@ def create_lib_gpr(name, deps=[]): gprsw = GPRswitches(root_project=src_gpr) -build_run_and_coverage(gprsw=gprsw, covlevel="stmt", mains=["main"], - extra_coverage_args=["-axcov"]) +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], +) -check_xcov_reports("obj", - {"main.c.xcov": {"+": {6, 7, 8}}, - "pkg1.c.xcov": {"+": {7, 8}}, - "pkg2.c.xcov": {"+": {6}}}) +check_xcov_reports( + "obj", + { + "main.c.xcov": {"+": {6, 7, 8}}, + "pkg1.c.xcov": {"+": {7, 8}}, + "pkg2.c.xcov": {"+": {6}}, + }, +) thistest.result() diff --git a/testsuite/tests/instr-cov/basic_base64/test.py b/testsuite/tests/instr-cov/basic_base64/test.py index 94b9ccd97..99880a5c5 100644 --- a/testsuite/tests/instr-cov/basic_base64/test.py +++ b/testsuite/tests/instr-cov/basic_base64/test.py @@ -9,20 +9,25 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs='..', mains=['main.adb'])), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src', - dump_trigger='main-end', - dump_channel='base64-stdout') -check_xcov_reports('xcov', { - 'main.adb.xcov': {'+': {5, 7, 8}}, - 'pkg.adb.xcov': {'+': {5, 6, 8}}, - 'pkg.ads.xcov': {}, -}, discard_empty=False) + gprsw=GPRswitches(root_project=gprfor(srcdirs="..", mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="main-end", + dump_channel="base64-stdout", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5, 7, 8}}, + "pkg.adb.xcov": {"+": {5, 6, 8}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, +) thistest.result() diff --git a/testsuite/tests/instr-cov/basic_decision/test.py b/testsuite/tests/instr-cov/basic_decision/test.py index ae587656e..b120593f2 100644 --- a/testsuite/tests/instr-cov/basic_decision/test.py +++ b/testsuite/tests/instr-cov/basic_decision/test.py @@ -12,23 +12,28 @@ from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt+decision', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') -check_xcov_reports('xcov', { - 'main.adb.xcov': {'+': {4, 6}}, - 'pkg.adb.xcov': {'+': {6}, '!': {5}, '-': {8}}, - 'pkg.ads.xcov': {}, -}, discard_empty=False) + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {4, 6}}, + "pkg.adb.xcov": {"+": {6}, "!": {5}, "-": {8}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, +) thistest.result() diff --git a/testsuite/tests/instr-cov/basic_stmt/test.py b/testsuite/tests/instr-cov/basic_stmt/test.py index 927764daf..6971047b5 100644 --- a/testsuite/tests/instr-cov/basic_stmt/test.py +++ b/testsuite/tests/instr-cov/basic_stmt/test.py @@ -10,23 +10,28 @@ from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') -check_xcov_reports('xcov', { - 'main.adb.xcov': {'+': {5, 7, 8}}, - 'pkg.adb.xcov': {'+': {5, 6, 8}}, - 'pkg.ads.xcov': {}, -}, discard_empty=False) + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5, 7, 8}}, + "pkg.adb.xcov": {"+": {5, 6, 8}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, +) thistest.result() diff --git a/testsuite/tests/instr-cov/bin_file_tunings/test.py b/testsuite/tests/instr-cov/bin_file_tunings/test.py index 0ad745c7e..e7c22bb40 100644 --- a/testsuite/tests/instr-cov/bin_file_tunings/test.py +++ b/testsuite/tests/instr-cov/bin_file_tunings/test.py @@ -37,44 +37,46 @@ class Testcase: for tc in [ # Kind of sanity check: only use defaults, like all other testcases Testcase("regular", [], {}, f"{trace_prefix}-*.srctrace"), - # Check that with default instrumentation options and # GNATCOV_TRACE_FILE set to a filename, the trace file is created using # that filename. - Testcase("env_filename", - [], - {"GNATCOV_TRACE_FILE": "foo.srctrace"}, - "foo.srctrace"), - + Testcase( + "env_filename", + [], + {"GNATCOV_TRACE_FILE": "foo.srctrace"}, + "foo.srctrace", + ), # Check that with default instrumentation options and # GNATCOV_TRACE_FILE set to a directory name, the trace file is created # with a standard name under that directory. - Testcase("env_dir", - [], - {"GNATCOV_TRACE_FILE": "traces-dir/"}, - f"traces-dir/{trace_prefix}-*.srctrace"), - + Testcase( + "env_dir", + [], + {"GNATCOV_TRACE_FILE": "traces-dir/"}, + f"traces-dir/{trace_prefix}-*.srctrace", + ), # Check that with --dump-filename-env-var, the name of the environment # variable changes. - Testcase("foo_env_1", - ["--dump-filename-env-var=FOO"], - {"GNATCOV_TRACE_FILE": "foo.srctrace"}, - f"{trace_prefix}-*.srctrace"), - Testcase("foo_env_2", - ["--dump-filename-env-var=FOO"], - {"FOO": "foo.srctrace"}, - "foo.srctrace"), - + Testcase( + "foo_env_1", + ["--dump-filename-env-var=FOO"], + {"GNATCOV_TRACE_FILE": "foo.srctrace"}, + f"{trace_prefix}-*.srctrace", + ), + Testcase( + "foo_env_2", + ["--dump-filename-env-var=FOO"], + {"FOO": "foo.srctrace"}, + "foo.srctrace", + ), # Check that with --dump-file-name-prefix, the given prefix replaces the # program basename. Testcase("prefix", ["--dump-filename-prefix=bar"], {}, "bar-*.srctrace"), - # Check that with --dump-file-name-simple, the produced trace has a # deterministic name. - Testcase("simple", - ["--dump-filename-simple"], - {}, - f"{trace_prefix}.srctrace"), + Testcase( + "simple", ["--dump-filename-simple"], {}, f"{trace_prefix}.srctrace" + ), ]: thistest.log(f"==== {tc.test_name} ====") @@ -85,15 +87,15 @@ class Testcase: env.update(tc.extra_env_vars) xcov_args = build_and_run( - gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], - mains=["main.adb"])), + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.adb"]) + ), covlevel="stmt", mains=["main"], extra_instr_args=tc.extra_args, extra_coverage_args=["-axcov", "--output-dir=xcov"], trace_mode="src", program_env=env, - # The very goal of this testcase is to produce trace files with # non-default names. build_and_run cannot deal with them, so skip # checks here: the computing below are enough to check that the @@ -113,7 +115,7 @@ class Testcase: thistest.fail_if( True, f"Too many source trace matched {tc.expected_trace}:\n" - + "\n".join(f"* {tf}" for tf in traces) + + "\n".join(f"* {tf}" for tf in traces), ) continue diff --git a/testsuite/tests/instr-cov/buffer_reset/test.py b/testsuite/tests/instr-cov/buffer_reset/test.py index f826fe5ec..c2d966026 100644 --- a/testsuite/tests/instr-cov/buffer_reset/test.py +++ b/testsuite/tests/instr-cov/buffer_reset/test.py @@ -12,44 +12,44 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor -tmp=Wdir("tmp_") +tmp = Wdir("tmp_") # Map from language to the corresponding main report name, and lines with # coverage obligations. main_lines = { "ada": ("main_ada.adb.xcov", [7, 10, 13]), - "c": ("main_c.c.xcov", [8, 11, 14, 16]) + "c": ("main_c.c.xcov", [8, 11, 14, 16]), } # Units which will only have a partial coverage result in them, regardless of # the trace. default_part_cov = { - "ada": {"pkg.adb.xcov": {'!': {5}}, "pkg.ads.xcov": {}}, - "c": {"pkh.c.xcov": {'!': {6}}}, + "ada": {"pkg.adb.xcov": {"!": {5}}, "pkg.ads.xcov": {}}, + "c": {"pkh.c.xcov": {"!": {6}}}, } # Default "nothing executed" expected result for each unit default_no_cov = { "ada": { - "main_ada.adb.xcov": {'-': {7, 10, 13}}, - "pkg.adb.xcov": {'-': {5}}, + "main_ada.adb.xcov": {"-": {7, 10, 13}}, + "pkg.adb.xcov": {"-": {5}}, "pkg.ads.xcov": {}, }, "c": { - "main_c.c.xcov": {'-': {8, 11, 14, 16}}, - "pkh.c.xcov": {'-': {6}}, - } + "main_c.c.xcov": {"-": {8, 11, 14, 16}}, + "pkh.c.xcov": {"-": {6}}, + }, } -def get_expected_cov (trace_name): + +def get_expected_cov(trace_name): """ Generate an expected coverage results based on the prefix of the trace indicating which main was executed, and its index. """ match = re.match(pattern=r"(.*)-(\d)\.srctrace", string=trace_name) thistest.fail_if( - not match, - comment="trace name not in expected format: " + trace_name + not match, comment="trace name not in expected format: " + trace_name ) trace_lang = match.group(1) idx = int(match.group(2)) @@ -58,20 +58,20 @@ def get_expected_cov (trace_name): lines = main_lines[trace_lang][1] for lang in ("ada", "c"): if lang == trace_lang: - expected_cov.update({ - main_lines[lang][0]: { - '+': {lines[idx]}, - '-': {lines[i] for i in range(len(lines)) if i != idx} + expected_cov.update( + { + main_lines[lang][0]: { + "+": {lines[idx]}, + "-": {lines[i] for i in range(len(lines)) if i != idx}, + } } - }) + ) expected_cov.update(default_part_cov[lang]) else: - expected_cov.update (default_no_cov[lang]) + expected_cov.update(default_no_cov[lang]) return expected_cov - - def check_one_exec(cov_args, lang): """ Find the traces generated by the lang executable, assuming the trace prefix @@ -88,8 +88,7 @@ def check_one_exec(cov_args, lang): # There is three dump indications in each main, we should thus have the # same number of traces. thistest.fail_if( - len (traces) != 3, - comment=f"expected 3 traces, found {len(traces)}" + len(traces) != 3, comment=f"expected 3 traces, found {len(traces)}" ) traces.sort() @@ -98,10 +97,11 @@ def check_one_exec(cov_args, lang): output_dir = f"output_{lang}_{i}/" xcov( cov_args + [f"--output-dir={output_dir}", traces[i]], - out=f"coverage_{lang}_{i}.log" + out=f"coverage_{lang}_{i}.log", ) check_xcov_reports(output_dir, get_expected_cov(traces[i])) + prj_id = "p" # Instrument build and run @@ -118,7 +118,7 @@ def check_one_exec(cov_args, lang): dump_trigger="manual", manual_prj_name=prj_id, extra_coverage_args=["-axcov+"], - extra_instr_args=["--dump-filename-simple"] + extra_instr_args=["--dump-filename-simple"], ) # Check the individual trace contents for each executable @@ -127,25 +127,24 @@ def check_one_exec(cov_args, lang): # Do a consolidated check with all the traces. We expect exactly six traces and # no coverage violations except for the final return statement in the c main. -thistest.log ("========== global consolidated check =========") +thistest.log("========== global consolidated check =========") all_traces = glob.glob("*.srctrace") thistest.fail_if( - len(all_traces) != 6, - comment=f"expected 6 traces, got {len(all_traces)}" + len(all_traces) != 6, comment=f"expected 6 traces, got {len(all_traces)}" ) output_dir = "consolidated/" xcov( cov_args + [f"--output-dir={output_dir}"] + all_traces, - out="consolidated.log" + out="consolidated.log", ) check_xcov_reports( output_dir, { - "main_ada.adb.xcov": {'+': {7, 10, 13}}, + "main_ada.adb.xcov": {"+": {7, 10, 13}}, "pkg.ads.xcov": {}, - "pkg.adb.xcov": {'+': {5}}, - "main_c.c.xcov": {'+': {8, 11, 14}, '-': {16}}, - "pkh.c.xcov": {'+': {6}} + "pkg.adb.xcov": {"+": {5}}, + "main_c.c.xcov": {"+": {8, 11, 14}, "-": {16}}, + "pkh.c.xcov": {"+": {6}}, }, ) diff --git a/testsuite/tests/instr-cov/c_empty_source/test.py b/testsuite/tests/instr-cov/c_empty_source/test.py index ace1da61f..9b2196d8c 100644 --- a/testsuite/tests/instr-cov/c_empty_source/test.py +++ b/testsuite/tests/instr-cov/c_empty_source/test.py @@ -10,19 +10,19 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Build and produce a coverage report for the test project. build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.c'])), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src', + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", ) check_xcov_reports( - 'xcov', {'main.c.xcov': {'+': {6}}, 'pkg.c.xcov': {}}, discard_empty=False + "xcov", {"main.c.xcov": {"+": {6}}, "pkg.c.xcov": {}}, discard_empty=False ) thistest.result() diff --git a/testsuite/tests/instr-cov/c_header/test.py b/testsuite/tests/instr-cov/c_header/test.py index 5abf6b44f..0cf4b81cc 100644 --- a/testsuite/tests/instr-cov/c_header/test.py +++ b/testsuite/tests/instr-cov/c_header/test.py @@ -13,21 +13,21 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Build and produce a coverage report for the test project. build_run_and_coverage( gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src', + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", ) check_xcov_reports( - 'xcov', + "xcov", { - 'main.c.xcov': {'+': {6, 7}}, - 'fact.h.xcov': {'+': {4, 5, 7}}, + "main.c.xcov": {"+": {6, 7}}, + "fact.h.xcov": {"+": {4, 5, 7}}, }, ) diff --git a/testsuite/tests/instr-cov/c_macros_no_cov_warnings/test.py b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/test.py index 911368e02..caa1d9367 100644 --- a/testsuite/tests/instr-cov/c_macros_no_cov_warnings/test.py +++ b/testsuite/tests/instr-cov/c_macros_no_cov_warnings/test.py @@ -10,14 +10,14 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.c'])), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axml'], - trace_mode='src', + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axml"], + trace_mode="src", ) # Check that gnatcov coverage did not raise any warning diff --git a/testsuite/tests/instr-cov/c_no_return/test.py b/testsuite/tests/instr-cov/c_no_return/test.py index 95869248b..a619e4867 100644 --- a/testsuite/tests/instr-cov/c_no_return/test.py +++ b/testsuite/tests/instr-cov/c_no_return/test.py @@ -17,17 +17,17 @@ # Check when the main function does not exit through a return build_run_and_coverage( gprsw=GPRswitches( - root_project=gprfor(srcdirs=[os.path.join("..", "no_return")], mains=["main.c"]) + root_project=gprfor( + srcdirs=[os.path.join("..", "no_return")], mains=["main.c"] + ) ), covlevel="stmt", mains=["main"], extra_coverage_args=["-axcov", "--output-dir=xcov"], trace_mode="src", dump_trigger="main-end", - # With older toolchains, a missing return results in an arbitrary exit # code, so let's ignore failures. - register_failure=False, ) check_xcov_reports( diff --git a/testsuite/tests/instr-cov/c_opts/test.py b/testsuite/tests/instr-cov/c_opts/test.py index 224eddfef..d503e52b6 100644 --- a/testsuite/tests/instr-cov/c_opts/test.py +++ b/testsuite/tests/instr-cov/c_opts/test.py @@ -20,7 +20,6 @@ # Also add these as two "--c-opts" arguments. ["-DA", "-D", "B", "-UB"], ["-I", other_dir], - # Check the processing of backslashes ["-DBACKSLASH=\\"], ["-DDOUBLE_BACKSLASH=\\\\"], @@ -36,8 +35,7 @@ covlevel="stmt", mains=["main"], extra_instr_args=( - ["--c-opts={}".format(",".join(args)) for args in c_opts] - + ["-v"] + ["--c-opts={}".format(",".join(args)) for args in c_opts] + ["-v"] ), extra_coverage_args=["-axcov", "--output-dir=xcov"], trace_mode="src", @@ -46,7 +44,7 @@ for excerpt in ["-DBACKSLASH=\\", "-DDOUBLE_BACKSLASH=\\", "-DCOMMA=,"]: thistest.fail_if( excerpt not in contents_of(log_file), - f"{excerpt} macro definition not found in {log_file}" + f"{excerpt} macro definition not found in {log_file}", ) check_xcov_reports("xcov", {"main.c.xcov": {"+": {7, 14}}}) diff --git a/testsuite/tests/instr-cov/c_prep_error/test.py b/testsuite/tests/instr-cov/c_prep_error/test.py index 82b4bd517..2c8a3338b 100644 --- a/testsuite/tests/instr-cov/c_prep_error/test.py +++ b/testsuite/tests/instr-cov/c_prep_error/test.py @@ -28,8 +28,7 @@ log = contents_of(log_file) for excerpt in ["foo.hh", "Preprocessing failed: aborting"]: thistest.fail_if( - excerpt not in log, - f"Missing excerpt in {log_file}: {repr(excerpt)}" + excerpt not in log, f"Missing excerpt in {log_file}: {repr(excerpt)}" ) thistest.result() diff --git a/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py b/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py index 7f9c7961e..0ce0542d4 100644 --- a/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py +++ b/testsuite/tests/instr-cov/c_ternary_in_if_cond/test.py @@ -10,16 +10,16 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Build and produce a coverage report for the test project. build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.c'])), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src', + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", ) -check_xcov_reports('xcov', {'main.c.xcov': {'+': {4, 5, 7}, '-': {9}}}) +check_xcov_reports("xcov", {"main.c.xcov": {"+": {4, 5, 7}, "-": {9}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/c_wrong_main/test.py b/testsuite/tests/instr-cov/c_wrong_main/test.py index de829d9d6..045643742 100644 --- a/testsuite/tests/instr-cov/c_wrong_main/test.py +++ b/testsuite/tests/instr-cov/c_wrong_main/test.py @@ -12,21 +12,21 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Create object directory to avoid GPR warning mkdir("obj") p = xcov_instrument( - GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.c'])), - covlevel='stmt', + GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", register_failure=False, ) -thistest.fail_if_not_equal('gnatcov instrument status code', 1, p.status) +thistest.fail_if_not_equal("gnatcov instrument status code", 1, p.status) thistest.fail_if_no_match( - 'gnatcov instrument output', - '.*gnatcov.*: Could not find main function in main.c', - contents_of('instrument.log').strip(), + "gnatcov instrument output", + ".*gnatcov.*: Could not find main function in main.c", + contents_of("instrument.log").strip(), ) thistest.result() diff --git a/testsuite/tests/instr-cov/checks_and_warnings/test.py b/testsuite/tests/instr-cov/checks_and_warnings/test.py index 56eeed9b9..273a15c11 100644 --- a/testsuite/tests/instr-cov/checks_and_warnings/test.py +++ b/testsuite/tests/instr-cov/checks_and_warnings/test.py @@ -12,24 +12,28 @@ from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt+decision', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - extra_gprbuild_cargs=['-gnatwae'], + extra_gprbuild_cargs=["-gnatwae"], check_gprbuild_output=True, - trace_mode='src') -check_xcov_reports('xcov', { - 'main.adb.xcov': {'+': {13}}, - 'pkg.ads.xcov': {'+': {2}}, -}) + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {13}}, + "pkg.ads.xcov": {"+": {2}}, + }, +) thistest.result() diff --git a/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py b/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py index a12298c4f..c1b1e1ded 100644 --- a/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py +++ b/testsuite/tests/instr-cov/cmdline-self-ref-macro/test.py @@ -12,17 +12,17 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=['..'], mains=['main.c'])), - covlevel='stmt', - mains=['main'], - extra_instr_args=['--c-opts=-Dreturn=int a; return'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src', + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--c-opts=-Dreturn=int a; return"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", ) -check_xcov_reports('xcov', {'main.c.xcov': {'+': {4}}}) +check_xcov_reports("xcov", {"main.c.xcov": {"+": {4}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/config_custom_db/test.py b/testsuite/tests/instr-cov/config_custom_db/test.py index 811bcc2ee..f0b2ef49d 100644 --- a/testsuite/tests/instr-cov/config_custom_db/test.py +++ b/testsuite/tests/instr-cov/config_custom_db/test.py @@ -24,7 +24,8 @@ # Setup with our custom toolchain xcov( - ["setup", "--prefix=install"] + db_args + ["setup", "--prefix=install"] + + db_args + ["../gnatcov-rt-custom/gnatcov_rts_custom.gpr"], register_failure=True, auto_config_args=False, diff --git a/testsuite/tests/instr-cov/consistency/test.py b/testsuite/tests/instr-cov/consistency/test.py index b52710b0b..e7eaf0ae4 100644 --- a/testsuite/tests/instr-cov/consistency/test.py +++ b/testsuite/tests/instr-cov/consistency/test.py @@ -15,26 +15,26 @@ from SUITE.tutils import thistest, xcov -p_gpr = 'p.gpr' -first_sid_file = 'first.sid' +p_gpr = "p.gpr" +first_sid_file = "first.sid" -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # As this test modifies source files, create a working copy -for filename in ('p.gpr', 'main.adb'): - cp(os.path.join('..', filename), filename) +for filename in ("p.gpr", "main.adb"): + cp(os.path.join("..", filename), filename) # Instrument the input project and back up the SID file for main.adb xcov_instrument( - gprsw=GPRswitches(root_project=p_gpr), - gpr_obj_dir='obj', - covlevel='stmt') -cp(os.path.join('obj', 'main.sid'), first_sid_file) + gprsw=GPRswitches(root_project=p_gpr), gpr_obj_dir="obj", covlevel="stmt" +) +cp(os.path.join("obj", "main.sid"), first_sid_file) # Modify the source file and re-instrument it -with open('main.adb', 'w') as f: - f.write(""" +with open("main.adb", "w") as f: + f.write( + """ with Ada.Text_IO; use Ada.Text_IO; procedure Main is @@ -50,42 +50,59 @@ begin Put_Line ("Fact (6) = " & Integer'Image (Fact (6))); end Main; -""") +""" + ) # Now, instrument and build it. Then run the main program, letting it produce a # trace. xcov_args = build_and_run( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt', - gpr_obj_dir='obj', - gpr_exe_dir='obj', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src') + covlevel="stmt", + gpr_obj_dir="obj", + gpr_exe_dir="obj", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) srctrace = xcov_args[-1] # Now try to run a coverage analysis with the trace file produced for the # second SID file but giving gnatcov the first one. -out_file = 'gnatcov.out' -mkdir('xcov') -xcov(['coverage', '-axcov', '-cstmt', '--output-dir=xcov', - '--sid', first_sid_file, srctrace], out=out_file) +out_file = "gnatcov.out" +mkdir("xcov") +xcov( + [ + "coverage", + "-axcov", + "-cstmt", + "--output-dir=xcov", + "--sid", + first_sid_file, + srctrace, + ], + out=out_file, +) # Check that gnatcov warns about inconsistent fingerprints actual = contents_of(out_file).strip() -expected = ('warning: traces for body of main (from {}) are' - ' inconsistent with the corresponding Source Instrumentation Data' - .format(srctrace)) -thistest.fail_if(expected != actual, - 'Unexpected output for "gnatcov coverage". Expected:\n' - '{}\n' - 'but got:\n' - '{}'.format(indent(expected), indent(actual))) +expected = ( + "warning: traces for body of main (from {}) are" + " inconsistent with the corresponding Source Instrumentation Data".format( + srctrace + ) +) +thistest.fail_if( + expected != actual, + 'Unexpected output for "gnatcov coverage". Expected:\n' + "{}\n" + "but got:\n" + "{}".format(indent(expected), indent(actual)), +) # gnatcov only see the first SID file, so it is expected to have the coverage # obligations coming from the first instrumentation. Besides, since it # discarded info from the trace file, gnatcov is supposed to report violations # for all coverage obligations related to the first version of "main.adb". -check_xcov_reports('xcov', {'main.adb.xcov': {'-': {5}}}) +check_xcov_reports("xcov", {"main.adb.xcov": {"-": {5}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/default_dump_channel/test.py b/testsuite/tests/instr-cov/default_dump_channel/test.py index 999370f5a..079b47761 100644 --- a/testsuite/tests/instr-cov/default_dump_channel/test.py +++ b/testsuite/tests/instr-cov/default_dump_channel/test.py @@ -15,8 +15,14 @@ from SUITE.context import thistest from SUITE.cutils import Wdir -from SUITE.tutils import (exename_for, exepath_to, gprbuild, gprfor, - run_cov_program, xcov) +from SUITE.tutils import ( + exename_for, + exepath_to, + gprbuild, + gprfor, + run_cov_program, + xcov, +) @dataclass @@ -41,16 +47,20 @@ class Test: Test("none", f"{default_prefix}-*-*-*-0.srctrace"), Test("simple", f"{default_prefix}.srctrace", ["--dump-filename-simple"]), Test("prefix", "bar-*-*-*-0.srctrace", ["--dump-filename-prefix=bar"]), - Test("env-var", - "mytrace.srctrace", - ["--dump-filename-env-var=MY_TRACE_FILE"], - {"MY_TRACE_FILE": "mytrace.srctrace"}), + Test( + "env-var", + "mytrace.srctrace", + ["--dump-filename-env-var=MY_TRACE_FILE"], + {"MY_TRACE_FILE": "mytrace.srctrace"}, + ), ]: tmp = Wdir(f"tmp_{t.label}") prj = gprfor(mains=["main.adb"], srcdirs=[".."]) - xcov(["instrument", "-P", prj, "-cstmt", "--dump-trigger=atexit"] - + t.options) + xcov( + ["instrument", "-P", prj, "-cstmt", "--dump-trigger=atexit"] + + t.options + ) gprbuild(prj, trace_mode="src") env = dict(os.environ) @@ -59,7 +69,7 @@ class Test: thistest.fail_if( len(glob.glob(t.srctrace_pattern)) != 1, - f"{t.label}: could not find a file matching {t.srctrace_pattern}" + f"{t.label}: could not find a file matching {t.srctrace_pattern}", ) tmp.to_homedir() diff --git a/testsuite/tests/instr-cov/end_slocs/test.py b/testsuite/tests/instr-cov/end_slocs/test.py index a15a27ea8..420e059d8 100644 --- a/testsuite/tests/instr-cov/end_slocs/test.py +++ b/testsuite/tests/instr-cov/end_slocs/test.py @@ -12,24 +12,25 @@ from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') +p_gpr = os.path.abspath("p.gpr") # If it does not exist, create p.gpr's object directory to avoid noise in # gnatcov's output. -obj_dir = os.path.abspath('obj') +obj_dir = os.path.abspath("obj") if not os.path.isdir(obj_dir): os.mkdir(obj_dir) -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') -check_xcov_reports('xcov', {'main.adb.xcov': {'+': {5}}}) + trace_mode="src", +) +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {5}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/endianity/test.py b/testsuite/tests/instr-cov/endianity/test.py index fb7b613f9..747f7dc2d 100644 --- a/testsuite/tests/instr-cov/endianity/test.py +++ b/testsuite/tests/instr-cov/endianity/test.py @@ -15,36 +15,43 @@ from SUITE.tutils import gprfor, xcov -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Build a project, run it and create a source trace file xcov_args = build_and_run( - gprsw=GPRswitches(root_project=gprfor('main.adb', srcdirs='..')), - covlevel='stmt+mcdc', - mains=['main'], - extra_coverage_args=['-axcov'], - trace_mode='src') + gprsw=GPRswitches(root_project=gprfor("main.adb", srcdirs="..")), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["-axcov"], + trace_mode="src", +) trace_file = xcov_args[-1] # Read this trace file and generate two other files, one per endianity -with open(trace_file, 'rb') as f: +with open(trace_file, "rb") as f: tf = SrcTraceFile.read(ByteStreamDecoder(f)) -with open('le.srctrace', 'wb') as f: - tf.endianity = 'little-endian' +with open("le.srctrace", "wb") as f: + tf.endianity = "little-endian" tf.write(f) -with open('be.srctrace', 'wb') as f: - tf.endianity = 'big-endian' +with open("be.srctrace", "wb") as f: + tf.endianity = "big-endian" tf.write(f) # Check that gnatcov decodes both the same way -for discr in ('be', 'le'): - xcov_dir = f'xcov-{discr}' - xcov(xcov_args + ['--output-dir', xcov_dir, f'{discr}.srctrace'], - out=f'coverage-{discr}.log') - check_xcov_reports(xcov_dir, { - 'main.adb.xcov': {'+': {5, 7, 8}}, - 'pkg.adb.xcov': {'+': {6, 8}, '!': {5}}, - 'pkg.ads.xcov': {}, - }, discard_empty=False) +for discr in ("be", "le"): + xcov_dir = f"xcov-{discr}" + xcov( + xcov_args + ["--output-dir", xcov_dir, f"{discr}.srctrace"], + out=f"coverage-{discr}.log", + ) + check_xcov_reports( + xcov_dir, + { + "main.adb.xcov": {"+": {5, 7, 8}}, + "pkg.adb.xcov": {"+": {6, 8}, "!": {5}}, + "pkg.ads.xcov": {}, + }, + discard_empty=False, + ) thistest.result() diff --git a/testsuite/tests/instr-cov/explicit_mains/test.py b/testsuite/tests/instr-cov/explicit_mains/test.py index 7b090ad57..3fc48547e 100644 --- a/testsuite/tests/instr-cov/explicit_mains/test.py +++ b/testsuite/tests/instr-cov/explicit_mains/test.py @@ -46,7 +46,11 @@ def create_gprsw(mains, with_asm=False): if with_asm: langs.append("Asm") mains_gpr = gprfor( - mains=mains, prjid="mains", srcdirs="..", langs=langs, deps=["mylib"], + mains=mains, + prjid="mains", + srcdirs="..", + langs=langs, + deps=["mylib"], ) # Create object/library directories to avoid GPR warnings that they are @@ -110,10 +114,9 @@ def check_error(label, mains, expected_error_msg): # in each case. -def check_gen_traces(label, - gpr_mains, - xcov_mains, - program_for_expected_traces): +def check_gen_traces( + label, gpr_mains, xcov_mains, program_for_expected_traces +): """ Run a test variant to check mains with coverage buffer dumps. @@ -131,16 +134,13 @@ def check_gen_traces(label, build_and_run( gprsw=create_gprsw(gpr_mains), covlevel="stmt", - # Build and run all actual mains in all cases (we want to check the # instrumentation status for all of them). extra_gprbuild_args=["main1.adb", "main2.adb"], mains=["main1", "main2"], - extra_instr_args=xcov_mains, extra_coverage_args=[], trace_mode="src", - # Since instrumentation may insert coverage buffer dumps only for a # subset of mains, calls to "gnatcov extract-base64-trace" will fail # for mains that do not dump. This is as expected, so ignore these diff --git a/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/test.py b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/test.py index 1079bf726..74b0ca0ad 100644 --- a/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/test.py +++ b/testsuite/tests/instr-cov/explicit_mains_ignore_gpr/test.py @@ -23,17 +23,14 @@ covlevel="stmt", extra_coverage_args=[], trace_mode="src", - # Only instrument foo.adb as a main extra_instr_args=["foo.adb"], - # Build and execute foo.adb and bar.adb extra_gprbuild_args=["foo.adb", "bar.adb"], mains=["foo", "bar"], - # We expect there not to be a trace file for bar, so don't register not # finding it as an error. - register_failure=False + register_failure=False, ) # Check that we only get traces for foo diff --git a/testsuite/tests/instr-cov/explicit_mains_uoi/test.py b/testsuite/tests/instr-cov/explicit_mains_uoi/test.py index f891e9f97..2201cd2c9 100644 --- a/testsuite/tests/instr-cov/explicit_mains_uoi/test.py +++ b/testsuite/tests/instr-cov/explicit_mains_uoi/test.py @@ -15,10 +15,14 @@ gprsw = GPRswitches(gpr_file) -build_run_and_coverage(gprsw=gprsw, covlevel="stmt", mains=["main"], - extra_coverage_args=["-axcov"], - extra_instr_args=["main.adb"], - extra_gprbuild_args=["main.adb"]) +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + extra_instr_args=["main.adb"], + extra_gprbuild_args=["main.adb"], +) check_xcov_reports("obj", {"main.adb.xcov": {"+": {2, 5}}}) diff --git a/testsuite/tests/instr-cov/expr_func/aggr/test.py b/testsuite/tests/instr-cov/expr_func/aggr/test.py index b1ae262e0..08ed44e95 100644 --- a/testsuite/tests/instr-cov/expr_func/aggr/test.py +++ b/testsuite/tests/instr-cov/expr_func/aggr/test.py @@ -12,21 +12,22 @@ from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') -check_xcov_reports('xcov', {'main.adb.xcov': { - '+': {4, 5, 7, 12, 14, 17, 19, 21, 22, 23, 24} -}}) + trace_mode="src", +) +check_xcov_reports( + "xcov", {"main.adb.xcov": {"+": {4, 5, 7, 12, 14, 17, 19, 21, 22, 23, 24}}} +) thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/basic/test.py b/testsuite/tests/instr-cov/expr_func/basic/test.py index b98a13ec5..35d113381 100644 --- a/testsuite/tests/instr-cov/expr_func/basic/test.py +++ b/testsuite/tests/instr-cov/expr_func/basic/test.py @@ -12,19 +12,20 @@ from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') -check_xcov_reports('xcov', {'main.adb.xcov': {'+': {7, 9, 11, 15}, '-': {12}}}) + trace_mode="src", +) +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {7, 9, 11, 15}, "-": {12}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/generic/test.py b/testsuite/tests/instr-cov/expr_func/generic/test.py index 3dc947ae2..c663aae0f 100644 --- a/testsuite/tests/instr-cov/expr_func/generic/test.py +++ b/testsuite/tests/instr-cov/expr_func/generic/test.py @@ -26,8 +26,7 @@ mains=["test_main"], extra_coverage_args=["-axcov", "--output-dir=."], trace_mode="src", - tolerate_instrument_messages=\ - "cannot instrument generic expression function", + tolerate_instrument_messages="cannot instrument generic expression function", ) # We only expect non-instrumented lines @@ -40,8 +39,7 @@ ) thistest.fail_if_not_equal( "'gnatcov instrument' log", - f"!!! pkg.ads:15:4: {warning_msg}\n" - f"!!! pkg.ads:18:4: {warning_msg}\n", + f"!!! pkg.ads:15:4: {warning_msg}\n" f"!!! pkg.ads:18:4: {warning_msg}\n", contents_of("instrument.log"), ) diff --git a/testsuite/tests/instr-cov/expr_func/parameterless/test.py b/testsuite/tests/instr-cov/expr_func/parameterless/test.py index 6ee724d92..aae78db5e 100644 --- a/testsuite/tests/instr-cov/expr_func/parameterless/test.py +++ b/testsuite/tests/instr-cov/expr_func/parameterless/test.py @@ -12,22 +12,23 @@ from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt+uc_mcdc', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt+uc_mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') -check_xcov_reports('xcov', - {'main.adb.xcov': {'+': {4}}, - 'pak.ads.xcov': {'+': {4}, '-': {5}}}) + trace_mode="src", +) +check_xcov_reports( + "xcov", {"main.adb.xcov": {"+": {4}}, "pak.ads.xcov": {"+": {4}, "-": {5}}} +) thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/prim/test.py b/testsuite/tests/instr-cov/expr_func/prim/test.py index bfabe41e5..78df7d726 100644 --- a/testsuite/tests/instr-cov/expr_func/prim/test.py +++ b/testsuite/tests/instr-cov/expr_func/prim/test.py @@ -12,25 +12,26 @@ from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt+uc_mcdc', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt+uc_mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') + trace_mode="src", +) # TODO: update coverage expectations once compiler bug # has been fixed and XFAIL is removed. -check_xcov_reports('xcov', {'main.adb.xcov': { - '+': {4, 5, 7, 12, 14, 17, 19, 21, 22, 23, 24} -}}) +check_xcov_reports( + "xcov", {"main.adb.xcov": {"+": {4, 5, 7, 12, 14, 17, 19, 21, 22, 23, 24}}} +) thistest.result() diff --git a/testsuite/tests/instr-cov/expr_func/prim2/test.py b/testsuite/tests/instr-cov/expr_func/prim2/test.py index 44aaf55ee..396673373 100644 --- a/testsuite/tests/instr-cov/expr_func/prim2/test.py +++ b/testsuite/tests/instr-cov/expr_func/prim2/test.py @@ -14,26 +14,31 @@ from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt+uc_mcdc', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt+uc_mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') + trace_mode="src", +) # Coverage expectations aren't really important, we want to check that # the instrumented code is valid. -check_xcov_reports('xcov', { - 'main.adb.xcov': {'+': {6}}, - 'pak.ads.xcov' : {'+': {4, 5, 6, 14, 16, 17, 18, 23}, '-': {8, 10}}, - 'pak.adb.xcov' : {'!': {6}, '+': {8}}}) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {6}}, + "pak.ads.xcov": {"+": {4, 5, 6, 14, 16, 17, 18, 23}, "-": {8, 10}}, + "pak.adb.xcov": {"!": {6}, "+": {8}}, + }, +) thistest.result() diff --git a/testsuite/tests/instr-cov/ext_gpr/test.py b/testsuite/tests/instr-cov/ext_gpr/test.py index 183296675..accfeb5a2 100644 --- a/testsuite/tests/instr-cov/ext_gpr/test.py +++ b/testsuite/tests/instr-cov/ext_gpr/test.py @@ -24,18 +24,20 @@ # ultimate extending project, which should contain all instrumented sources. thistest.fail_if_no_match( "instrumented directories", - "\n".join([ - r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", - r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", - r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", - r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-p_ext2\.ads", - r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", - r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", - r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", - r"obj-p_ext2/p_ext2-gnatcov-instr/pkg\.ads", - r"obj-p_ext2/p_ext2-gnatcov-instr/pkg1\.ads", - r"obj-p_ext2/p_ext2-gnatcov-instr/pkg2\.ads", - ]), + "\n".join( + [ + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-p_ext2\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/pkg\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/pkg1\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/pkg2\.ads", + ] + ), "\n".join( f.replace("\\", "/") for f in sorted(glob.glob("obj-*/*-gnatcov-instr/*")) diff --git a/testsuite/tests/instr-cov/file-context/test.py b/testsuite/tests/instr-cov/file-context/test.py index 1a519f6fe..08f9b10d5 100644 --- a/testsuite/tests/instr-cov/file-context/test.py +++ b/testsuite/tests/instr-cov/file-context/test.py @@ -34,17 +34,20 @@ def do_instr(label, args): ) return output_file + # Check that we print the source file that is currently instrumented when # warnings/errors occur at most once, and never for other files. log = do_instr("basic", []) thistest.fail_if_not_equal( f'"gnatcov instrument" output', contents_of(log).strip(), - "\n".join([ - "warning: While instrumenting main.adb...", - "warning: Cannot find required source file: missing_a.ads", - "warning: Cannot find required source file: missing_b.ads", - ]), + "\n".join( + [ + "warning: While instrumenting main.adb...", + "warning: Cannot find required source file: missing_a.ads", + "warning: Cannot find required source file: missing_b.ads", + ] + ), ) # In verbose mode: always print it once. @@ -59,12 +62,14 @@ def do_instr(label, args): ] thistest.fail_if_not_equal( f'"gnatcov instrument" output', - "\n".join([ - "[GNATCOV.MISC] Instrumenting main.adb", - "warning: Cannot find required source file: missing_a.ads", - "warning: Cannot find required source file: missing_b.ads", - "[GNATCOV.MISC] Instrumenting pkg.ads", - ]), + "\n".join( + [ + "[GNATCOV.MISC] Instrumenting main.adb", + "warning: Cannot find required source file: missing_a.ads", + "warning: Cannot find required source file: missing_b.ads", + "[GNATCOV.MISC] Instrumenting pkg.ads", + ] + ), "\n".join(actual_lines), ) diff --git a/testsuite/tests/instr-cov/ghost_generic/test.py b/testsuite/tests/instr-cov/ghost_generic/test.py index b0d3f133f..9a9c3f9bf 100644 --- a/testsuite/tests/instr-cov/ghost_generic/test.py +++ b/testsuite/tests/instr-cov/ghost_generic/test.py @@ -25,7 +25,7 @@ "main.adb.xcov": {"+": {11, 15}}, "gen.adb.xcov": {"+": {9}, "-": {4}}, "gen.ads.xcov": {}, - "non_ghost_inst.ads.xcov": {} + "non_ghost_inst.ads.xcov": {}, }, discard_empty=False, ) diff --git a/testsuite/tests/instr-cov/library_projects/test.py b/testsuite/tests/instr-cov/library_projects/test.py index 26a49b240..01384418a 100644 --- a/testsuite/tests/instr-cov/library_projects/test.py +++ b/testsuite/tests/instr-cov/library_projects/test.py @@ -12,29 +12,31 @@ from SUITE.gprutils import GPRswitches -main_gpr = os.path.abspath('main.gpr') -main_obj_dir = os.path.abspath('obj-main') +main_gpr = os.path.abspath("main.gpr") +main_obj_dir = os.path.abspath("obj-main") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=main_gpr, - projects=['main', 'math', 'vectors']), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + gprsw=GPRswitches( + root_project=main_gpr, projects=["main", "math", "vectors"] + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=main_obj_dir, gpr_exe_dir=main_obj_dir, - trace_mode='src') -check_xcov_reports('xcov', { - 'main.adb.xcov': {'+': {5, 9, 11, 12, 13}}, - - 'vectors.ads.xcov': {'+': {6, 15, 17, 18, 19, 20}}, - 'vectors.adb.xcov': {'+': {5, 10, 15, 18, 19}, - '-': {16, 25, 26, 28}}, - - 'math.ads.xcov': {'+': {3, 11, 12, 13}}, - 'math.adb.xcov': {'+': {5, 10}, '-': {15}}, -}) + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5, 9, 11, 12, 13}}, + "vectors.ads.xcov": {"+": {6, 15, 17, 18, 19, 20}}, + "vectors.adb.xcov": {"+": {5, 10, 15, 18, 19}, "-": {16, 25, 26, 28}}, + "math.ads.xcov": {"+": {3, 11, 12, 13}}, + "math.adb.xcov": {"+": {5, 10}, "-": {15}}, + }, +) thistest.result() diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/test.py b/testsuite/tests/instr-cov/main_autodump/nested_block/test.py index dcb21c208..24a7c6847 100644 --- a/testsuite/tests/instr-cov/main_autodump/nested_block/test.py +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/test.py @@ -27,33 +27,28 @@ # # The mains of the form "*no_decl" have no top level decalrations nor exception # handlers, and should not have their qualified names renamed. -main_names = ["simple_no_decl", "simple_decl", "simple_exn", "simple_only_exn", - "dotted-decl", "dotted-no_decl", "dotted-exn"] +main_names = [ + "simple_no_decl", + "simple_decl", + "simple_exn", + "simple_only_exn", + "dotted-decl", + "dotted-no_decl", + "dotted-exn", +] # The expected results are not really of imporance here, what matters is that # the mains got instrumented and build correctly. expected_results = { - "dotted-decl": { - "dotted-decl.adb.xcov": {'+': {7, 12, 13, 17, 18}} - }, - "dotted-no_decl": { - "dotted-no_decl.adb.xcov": {'+': {6, 9, 10}} - }, - "dotted-exn": { - "dotted-exn.adb.xcov": {'+': {4, 9, 12, 13, 16}} - }, - "simple_decl": { - "simple_decl.adb.xcov": {'+': {10, 15, 16, 19, 20}} - }, - "simple_no_decl": { - "simple_no_decl.adb.xcov": {'+': {6, 9}} - }, - "simple_exn": { - "simple_exn.adb.xcov": {'+': {4, 9, 12, 13, 16}} - }, + "dotted-decl": {"dotted-decl.adb.xcov": {"+": {7, 12, 13, 17, 18}}}, + "dotted-no_decl": {"dotted-no_decl.adb.xcov": {"+": {6, 9, 10}}}, + "dotted-exn": {"dotted-exn.adb.xcov": {"+": {4, 9, 12, 13, 16}}}, + "simple_decl": {"simple_decl.adb.xcov": {"+": {10, 15, 16, 19, 20}}}, + "simple_no_decl": {"simple_no_decl.adb.xcov": {"+": {6, 9}}}, + "simple_exn": {"simple_exn.adb.xcov": {"+": {4, 9, 12, 13, 16}}}, "simple_only_exn": { - "simple_only_exn.adb.xcov": {'+': {10, 13, 14, 18}, '-': {20}} - } + "simple_only_exn.adb.xcov": {"+": {10, 13, 14, 18}, "-": {20}} + }, } @@ -62,15 +57,15 @@ def do_one_main(main_name): create a project, instrument build and compute coverage reports for the given main, from the expected results dictionnary defined above. """ - tmp.to_subdir(f'tmp_{main_name}') - p = gprfor(mains=[f"{main_name}.adb"], - srcdirs=[".."]) + tmp.to_subdir(f"tmp_{main_name}") + p = gprfor(mains=[f"{main_name}.adb"], srcdirs=[".."]) build_run_and_coverage( - gprsw=GPRswitches(root_project=p, units=[main_name.replace('-', '.')]), - covlevel='stmt', + gprsw=GPRswitches(root_project=p, units=[main_name.replace("-", ".")]), + covlevel="stmt", mains=[main_name], - extra_coverage_args=['-axcov', '--output-dir=xcov']) - check_xcov_reports('xcov', expected_results[main_name]) + extra_coverage_args=["-axcov", "--output-dir=xcov"], + ) + check_xcov_reports("xcov", expected_results[main_name]) for main_name in main_names: diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/test.py b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py index ea4a94609..f0cb98e73 100644 --- a/testsuite/tests/instr-cov/manual-dump/ada_only/test.py +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/test.py @@ -12,66 +12,75 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor, srctrace_pattern_for -tmp = Wdir('tmp_') - -lib1_p = gprfor(mains=[], - prjid="lib1", - srcdirs="../src-lib1", - objdir="obj-lib1", - langs=["Ada"], - ) - -lib2_p = gprfor(mains=[], - prjid="lib2", - srcdirs="../src-lib2", - objdir="obj-lib2", - langs=["Ada"], - ) - -p = gprfor(prjid="gen", - mains=["main.adb"], - srcdirs=["../src"], - objdir="obj", - deps=["lib1", "lib2"]) - -instr_warning = (r"warning: Manual buffer dump/reset indications were found" - r" in.*") +tmp = Wdir("tmp_") + +lib1_p = gprfor( + mains=[], + prjid="lib1", + srcdirs="../src-lib1", + objdir="obj-lib1", + langs=["Ada"], +) + +lib2_p = gprfor( + mains=[], + prjid="lib2", + srcdirs="../src-lib2", + objdir="obj-lib2", + langs=["Ada"], +) + +p = gprfor( + prjid="gen", + mains=["main.adb"], + srcdirs=["../src"], + objdir="obj", + deps=["lib1", "lib2"], +) + +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) cov_args = build_and_run( gprsw=GPRswitches(root_project=p, units=["lib1", "main"]), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src', + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", dump_trigger="manual", manual_prj_name="gen", - tolerate_instrument_messages=instr_warning) + tolerate_instrument_messages=instr_warning, +) # Check that gnatcov inserted the call to the dump buffers procedure in the # lib2.adb which is not a unit of interest def check_call(file): - thistest.fail_if_no_match("missing dump buffers procedure call", - "(\n|.)*GCVRT.DB_manual_lib2.Dump_Buffers(.*);" - "(\n|.)*", - contents_of(file)) + thistest.fail_if_no_match( + "missing dump buffers procedure call", + "(\n|.)*GCVRT.DB_manual_lib2.Dump_Buffers(.*);" "(\n|.)*", + contents_of(file), + ) -check_call('obj-lib2/lib2-gnatcov-instr/lib2.adb') +check_call("obj-lib2/lib2-gnatcov-instr/lib2.adb") # Generate and check coverage reports, using the last trace generated for the # root project. -trace_file = sorted(glob.glob(srctrace_pattern_for( - "main", manual=True, manual_prj_name="gen" -)))[-1] +trace_file = sorted( + glob.glob(srctrace_pattern_for("main", manual=True, manual_prj_name="gen")) +)[-1] xcov(cov_args + [trace_file], out="coverage.log") -check_xcov_reports('xcov', { - 'main.adb.xcov': {'+': {12, 15, 19, 24, 26, 27, 28}, - '-': {21, 29}}, - 'lib1.adb.xcov': {'+': {4, 7}}, - 'lib1.ads.xcov': {}, -}) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {12, 15, 19, 24, 26, 27, 28}, "-": {21, 29}}, + "lib1.adb.xcov": {"+": {4, 7}}, + "lib1.ads.xcov": {}, + }, +) thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py index 6a3737584..ad4e6bccc 100644 --- a/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py +++ b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py @@ -13,48 +13,54 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") def make_lib_gpr(name, srcdirs, deps): - return gprfor(mains=[], - prjid=name, - srcdirs=srcdirs, - objdir="obj-" + name, - langs=["Ada"], - deps=deps) + return gprfor( + mains=[], + prjid=name, + srcdirs=srcdirs, + objdir="obj-" + name, + langs=["Ada"], + deps=deps, + ) lib1_p = make_lib_gpr("lib1", "../src-lib1", ["lib2"]) lib2_p = make_lib_gpr("lib2", "../src-lib1/src-lib2", None) -p = gprfor(mains=["main.adb"], - srcdirs=["../src"], - objdir="obj", - deps=["lib1", "lib2"]) +p = gprfor( + mains=["main.adb"], srcdirs=["../src"], objdir="obj", deps=["lib1", "lib2"] +) # Check that we get the expected coverage reports # Running gnatcov natively allows to have one source trace file per # project. -instr_warning = (r"warning: Manual buffer dump/reset indications were" - r" found in.*") +instr_warning = ( + r"warning: Manual buffer dump/reset indications were" r" found in.*" +) build_run_and_coverage( gprsw=GPRswitches(root_project=p, units=["lib1", "lib2"]), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src', + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", dump_trigger="manual", manual_prj_name="lib1", - tolerate_instrument_messages=instr_warning) - -check_xcov_reports('xcov', { - 'lib1.adb.xcov': {'+': {6, 8}, '-': {10}}, - 'lib1.ads.xcov': {}, - 'lib2.adb.xcov': {'+': {4, 6}}, - 'lib2.ads.xcov': {}, -}) + tolerate_instrument_messages=instr_warning, +) + +check_xcov_reports( + "xcov", + { + "lib1.adb.xcov": {"+": {6, 8}, "-": {10}}, + "lib1.ads.xcov": {}, + "lib2.adb.xcov": {"+": {4, 6}}, + "lib2.ads.xcov": {}, + }, +) thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/basic/test.py b/testsuite/tests/instr-cov/manual-dump/basic/test.py index 2bac52d8f..b5d3b0845 100644 --- a/testsuite/tests/instr-cov/manual-dump/basic/test.py +++ b/testsuite/tests/instr-cov/manual-dump/basic/test.py @@ -18,7 +18,6 @@ srcdirs=[".."], mains=["main.adb"], langs=["Ada"], - # Depending on the build mode, use a different implementation of # the Covdump procedure. This allows the regular build to work (no # dependency on GNATcov_RTS nor coverage buffers) and at the same @@ -46,9 +45,9 @@ extra_gprbuild_args=["-XCOV_BUILD=True"], extra_coverage_args=["--annotate=xcov", "-XCOV_BUILD=True"], tolerate_instrument_messages="warning: no indication for dump location was" - " found, this might be caused by a" - " misspelling in the expected pragma" - " statement." + " found, this might be caused by a" + " misspelling in the expected pragma" + " statement.", ) check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) diff --git a/testsuite/tests/instr-cov/manual-dump/c_only/test.py b/testsuite/tests/instr-cov/manual-dump/c_only/test.py index 610e87800..546c358a1 100644 --- a/testsuite/tests/instr-cov/manual-dump/c_only/test.py +++ b/testsuite/tests/instr-cov/manual-dump/c_only/test.py @@ -13,55 +13,68 @@ tmp = Wdir("tmp_") # Create the GPR file for the root project -src_gpr = gprfor(mains=["main.c"], - prjid="main", - srcdirs="../src", - objdir="obj", - langs=["C"], - deps=["lib"] - ) +src_gpr = gprfor( + mains=["main.c"], + prjid="main", + srcdirs="../src", + objdir="obj", + langs=["C"], + deps=["lib"], +) # Create the GPR files for the library -lib_gpr = gprfor(mains=[], - prjid="lib", - srcdirs="../src-lib", - langs=["C"], - extra=""" +lib_gpr = gprfor( + mains=[], + prjid="lib", + srcdirs="../src-lib", + langs=["C"], + extra=""" for Library_Name use "lib"; for Library_Dir use "lib"; - """ - ) + """, +) gprsw = GPRswitches(root_project=src_gpr) -instr_warning = (r"warning: Manual buffer dump/reset indications were found" - r" in.*") +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) -build_run_and_coverage(gprsw=gprsw, covlevel="stmt", mains=["main"], - extra_coverage_args=["-axcov"], dump_trigger="manual", - manual_prj_name="main", - tolerate_instrument_messages=instr_warning) +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + dump_trigger="manual", + manual_prj_name="main", + tolerate_instrument_messages=instr_warning, +) thistest.fail_if_not_equal( what="gprbuild output not empty", expected="", - actual=contents_of("gprbuild.out").strip() + actual=contents_of("gprbuild.out").strip(), ) # Check that that the dump call indication was correctly replaced in the sub # project -lib_file = 'obj/lib-gnatcov-instr/foo.c' +lib_file = "obj/lib-gnatcov-instr/foo.c" thistest.fail_if_no_match -("missing Dump_Buffers call", - r"(\n|.)*gnatcov_rts_manual_dump_buffers_lib \(.*\);(\n|.)*", - contents_of(lib_file)) +( + "missing Dump_Buffers call", + r"(\n|.)*gnatcov_rts_manual_dump_buffers_lib \(.*\);(\n|.)*", + contents_of(lib_file), +) # Check that we got the expected coverage report -check_xcov_reports("obj", - {"main.c.xcov": {"+": {6, 12, 15, 20, 22}, - "-": {18, 26}}, - "foo.c.xcov": {"+": {4, 8}}}) +check_xcov_reports( + "obj", + { + "main.c.xcov": {"+": {6, 12, 15, 20, 22}, "-": {18, 26}}, + "foo.c.xcov": {"+": {4, 8}}, + }, +) thistest.result() diff --git a/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py b/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py index d371b125a..1062c195e 100644 --- a/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py +++ b/testsuite/tests/instr-cov/manual-dump/lal_ctx_reset/test.py @@ -21,11 +21,12 @@ from SUITE.tutils import gprfor -tmp = Wdir ("tmp_") +tmp = Wdir("tmp_") # Number of LAL unit queries after which gnatcov reset the LAL context GNATCOV_CTX_RESET_LIMIT = 50 + def gen_project(): """ Generate a project capable of reproducing the bug. @@ -66,10 +67,10 @@ def gen_project(): objdir="obj", extra=gprcov_for( units_in=[f"Pkg_{i}" for i in range(GNATCOV_CTX_RESET_LIMIT)] - ) + ), ) - expected_cov={ - f"pkg_{i}.ads.xcov": {'+': {2}} for i in range(GNATCOV_CTX_RESET_LIMIT) + expected_cov = { + f"pkg_{i}.ads.xcov": {"+": {2}} for i in range(GNATCOV_CTX_RESET_LIMIT) } return prj, expected_cov @@ -85,7 +86,7 @@ def gen_project(): covlevel="stmt", extra_coverage_args=["-axcov"], dump_trigger="manual", - manual_prj_name=os.path.splitext(prj)[0] + manual_prj_name=os.path.splitext(prj)[0], ) check_xcov_reports("obj", expected_cov) diff --git a/testsuite/tests/instr-cov/manual-dump/mixed/test.py b/testsuite/tests/instr-cov/manual-dump/mixed/test.py index 89aa82c36..5c9da1d96 100644 --- a/testsuite/tests/instr-cov/manual-dump/mixed/test.py +++ b/testsuite/tests/instr-cov/manual-dump/mixed/test.py @@ -47,7 +47,7 @@ "obj", { "main_ada.adb.xcov": {"+": {5}}, - "main_c.c.xcov": {"+": {6}, '-': {8}}, + "main_c.c.xcov": {"+": {6}, "-": {8}}, }, ) diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py index a0bc7d31b..223028e9d 100644 --- a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py @@ -20,19 +20,20 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor -tmp=Wdir("tmp_") +tmp = Wdir("tmp_") expected_cov = { - "ada" : { - "main_ada.adb.xcov": {'+': {4, 6}}, - "main_c.c.xcov": {'-': {6, 7, 9}} + "ada": { + "main_ada.adb.xcov": {"+": {4, 6}}, + "main_c.c.xcov": {"-": {6, 7, 9}}, + }, + "c": { + "main_c.c.xcov": {"+": {6, 7}, "-": {9}}, + "main_ada.adb.xcov": {"-": {4, 6}}, }, - "c" : { - "main_c.c.xcov": {'+': {6, 7}, '-': {9}}, - "main_ada.adb.xcov": {'-': {4, 6}} - } } + def check_one_trace(cov_args, lang): """ Find the trace generated by the lang executable, assuming the trace prefix @@ -49,8 +50,7 @@ def check_one_trace(cov_args, lang): # There is only one dump indication in each main, ensure we found a trace # and have no spurious traces in the working directory. thistest.fail_if( - len (trace) != 1, - comment=f"expected a single trace, found {len(trace)}" + len(trace) != 1, comment=f"expected a single trace, found {len(trace)}" ) print(trace) @@ -58,10 +58,11 @@ def check_one_trace(cov_args, lang): output_dir = f"output_{lang}/" xcov( cov_args + [f"--output-dir={output_dir}"] + trace, - out=f"coverage_{lang}.log" + out=f"coverage_{lang}.log", ) check_xcov_reports(output_dir, expected_cov[lang]) + prj_id = "p" # Instrument build and run diff --git a/testsuite/tests/instr-cov/manual-dump/trace_index/test.py b/testsuite/tests/instr-cov/manual-dump/trace_index/test.py index c5cbac4d3..d7b8701c7 100644 --- a/testsuite/tests/instr-cov/manual-dump/trace_index/test.py +++ b/testsuite/tests/instr-cov/manual-dump/trace_index/test.py @@ -12,23 +12,27 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor, srctrace_pattern_for -tmp=Wdir("tmp_") +tmp = Wdir("tmp_") expected_cov = [ - {'+': {5}, '-': {7, 9}}, - {'+': {5,7}, '-': {9}}, - {'+': {5,7,9}}, + {"+": {5}, "-": {7, 9}}, + {"+": {5, 7}, "-": {9}}, + {"+": {5, 7, 9}}, ] -def check_trace (cov_args, traces, index): + +def check_trace(cov_args, traces, index): """ Create a coverage report from cov_args and traces[index], in the report_{index} directory, and check the report against expected_cov, for the corresponding index. """ thistest.log(f"======= Checking trace {index + 1} =========") - output_dir=f"report_{index + 1}" - xcov(cov_args + [traces[index], f"--output-dir={output_dir}"], out=f"xcov_{index}") + output_dir = f"report_{index + 1}" + xcov( + cov_args + [traces[index], f"--output-dir={output_dir}"], + out=f"xcov_{index}", + ) check_xcov_reports(output_dir, {"main.adb.xcov": expected_cov[index]}) @@ -50,22 +54,22 @@ def check_trace (cov_args, traces, index): # We are expecting three traces, if at this point cov_args has a length of # less than 4, there's definitively something wrong. thistest.fail_if( - len(cov_args) < 4, - comment=f"expected at least three traces: {cov_args}" + len(cov_args) < 4, comment=f"expected at least three traces: {cov_args}" ) -traces = glob.glob(srctrace_pattern_for("main", manual=True, manual_prj_name="p")) +traces = glob.glob( + srctrace_pattern_for("main", manual=True, manual_prj_name="p") +) traces.sort() thistest.fail_if( - len(traces) != 3, - comment=f"Expected three traces, got {len(traces)}" + len(traces) != 3, comment=f"Expected three traces, got {len(traces)}" ) # Check that the traces do indeed contain an index in their filename thistest.fail_if( any([not traces[i].endswith(f"-{i}.srctrace") for i in range(3)]), - comment=f"missing trace index in trace filenames: {traces}" + comment=f"missing trace index in trace filenames: {traces}", ) # Check for each trace the coverage results diff --git a/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.py b/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.py index e1cb06455..db3e95dd9 100644 --- a/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.py +++ b/testsuite/tests/instr-cov/manual-dump/unknown_lang/test.py @@ -13,11 +13,11 @@ prj_name = "prj" -prj=gprfor( +prj = gprfor( mains=["main_ada.adb"], prjid=prj_name, langs=["Ada", "Asm"], - srcdirs=[".."] + srcdirs=[".."], ) build_run_and_coverage( @@ -26,7 +26,7 @@ covlevel="stmt", extra_coverage_args=["-axcov"], dump_trigger="manual", - manual_prj_name=prj_name + manual_prj_name=prj_name, ) check_xcov_reports("obj", {"main_ada.adb.xcov": {"+": {9}}}) diff --git a/testsuite/tests/instr-cov/mixed_and/test.py b/testsuite/tests/instr-cov/mixed_and/test.py index f2ef7f10f..d66b949ea 100644 --- a/testsuite/tests/instr-cov/mixed_and/test.py +++ b/testsuite/tests/instr-cov/mixed_and/test.py @@ -12,21 +12,28 @@ from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') -check_xcov_reports('xcov', { - 'main.adb.xcov': {'+': {4, 6, 8, 10, 12, 14, 17}, - '-': {7, 9, 11, 13, 15}}}) + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": { + "+": {4, 6, 8, 10, 12, 14, 17}, + "-": {7, 9, 11, 13, 15}, + } + }, +) thistest.result() diff --git a/testsuite/tests/instr-cov/multi_unit_source/test.py b/testsuite/tests/instr-cov/multi_unit_source/test.py index 0fbc9cb11..5ecc3e8c9 100644 --- a/testsuite/tests/instr-cov/multi_unit_source/test.py +++ b/testsuite/tests/instr-cov/multi_unit_source/test.py @@ -27,11 +27,15 @@ """ mkdir("obj") -prj = gprfor(srcdirs=[os.path.join("..", "src")], mains=["main.adb"], extra=extra) +prj = gprfor( + srcdirs=[os.path.join("..", "src")], mains=["main.adb"], extra=extra +) # Check that the instrumentation crashes and does not leave stale # instrumentation artefacts when trying to instrument the multi-unit source. -xcov_instrument(gprsw=GPRswitches(prj), covlevel="stmt", register_failure=False) +xcov_instrument( + gprsw=GPRswitches(prj), covlevel="stmt", register_failure=False +) thistest.fail_if_no_match( "gnatcov instrument output", ( diff --git a/testsuite/tests/instr-cov/multiline_marker/test.py b/testsuite/tests/instr-cov/multiline_marker/test.py index ce2aed0c4..d25d2a855 100644 --- a/testsuite/tests/instr-cov/multiline_marker/test.py +++ b/testsuite/tests/instr-cov/multiline_marker/test.py @@ -19,10 +19,10 @@ # Build and produce a coverage report for the test project. build_run_and_coverage( gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src', + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", ) check_xcov_reports("xcov", {"main.c.xcov": {"+": {6, 10, 14}}}) diff --git a/testsuite/tests/instr-cov/multiple_mains/test.py b/testsuite/tests/instr-cov/multiple_mains/test.py index b490c546a..07e205110 100644 --- a/testsuite/tests/instr-cov/multiple_mains/test.py +++ b/testsuite/tests/instr-cov/multiple_mains/test.py @@ -16,9 +16,14 @@ build_and_run( gprsw=GPRswitches( - root_project=gprfor(srcdirs=["../src"], - mains=["test_a.adb", "test_b.adb"])), - covlevel="stmt", mains=[], extra_coverage_args=[], trace_mode="src", + root_project=gprfor( + srcdirs=["../src"], mains=["test_a.adb", "test_b.adb"] + ) + ), + covlevel="stmt", + mains=[], + extra_coverage_args=[], + trace_mode="src", ) thistest.result() diff --git a/testsuite/tests/instr-cov/nested_ternary/test.py b/testsuite/tests/instr-cov/nested_ternary/test.py index c4a455725..797c3d6c6 100644 --- a/testsuite/tests/instr-cov/nested_ternary/test.py +++ b/testsuite/tests/instr-cov/nested_ternary/test.py @@ -10,17 +10,17 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Build and produce a coverage report for the test project. build_run_and_coverage( gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])), - covlevel='stmt+decision', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src', + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", ) -check_xcov_reports('xcov', {'main.c.xcov': {'!': {4}}}) +check_xcov_reports("xcov", {"main.c.xcov": {"!": {4}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/no_main/test.py b/testsuite/tests/instr-cov/no_main/test.py index f0f67e3c3..b2842abae 100644 --- a/testsuite/tests/instr-cov/no_main/test.py +++ b/testsuite/tests/instr-cov/no_main/test.py @@ -12,22 +12,23 @@ from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') + trace_mode="src", +) check_xcov_reports( - 'xcov', - {'pkg.adb.xcov': {'+': {5, 6, 8}}, 'pkg.ads.xcov': {}}, + "xcov", + {"pkg.adb.xcov": {"+": {5, 6, 8}}, "pkg.ads.xcov": {}}, discard_empty=False, ) diff --git a/testsuite/tests/instr-cov/not_array/test.py b/testsuite/tests/instr-cov/not_array/test.py index 99217d5f7..e92947c6c 100644 --- a/testsuite/tests/instr-cov/not_array/test.py +++ b/testsuite/tests/instr-cov/not_array/test.py @@ -11,10 +11,10 @@ from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Use --all-decisions so that, even though we are using stmt+decision, we can # check if the "X and then Y" decision is properly instrumented (thanks to its @@ -24,15 +24,21 @@ # sources that make GNAT crash. build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt+decision', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov', '--all-decisions'], + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov", "--all-decisions"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') -check_xcov_reports('xcov', {'main.adb.xcov': { - '+': {4, 5, 7, 9, 11, 12, 15}, - '!': {13}, -}}) + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": { + "+": {4, 5, 7, 9, 11, 12, 15}, + "!": {13}, + } + }, +) thistest.result() diff --git a/testsuite/tests/instr-cov/pragma_after_cu/test.py b/testsuite/tests/instr-cov/pragma_after_cu/test.py index 39f1519f4..7d9b2d7ec 100644 --- a/testsuite/tests/instr-cov/pragma_after_cu/test.py +++ b/testsuite/tests/instr-cov/pragma_after_cu/test.py @@ -10,18 +10,22 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {6}}, + "raise_error.adb.xcov": {"+": {3}}, + "raise_error.ads.xcov": {}, + }, + discard_empty=False, ) -check_xcov_reports('xcov', { - 'main.adb.xcov': {'+': {6}}, - 'raise_error.adb.xcov': {'+': {3}}, - 'raise_error.ads.xcov': {}, -}, discard_empty=False) thistest.result() diff --git a/testsuite/tests/instr-cov/pragma_no_body/test.py b/testsuite/tests/instr-cov/pragma_no_body/test.py index 253d9a063..863ff033f 100644 --- a/testsuite/tests/instr-cov/pragma_no_body/test.py +++ b/testsuite/tests/instr-cov/pragma_no_body/test.py @@ -10,19 +10,22 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5}}, + "orig_pkg.ads.xcov": {}, + "orig_pkg.adb.xcov": {"+": {4}}, + "pkg.ads.xcov": {}, + }, ) -check_xcov_reports('xcov', { - 'main.adb.xcov': {'+': {5}}, - 'orig_pkg.ads.xcov': {}, - 'orig_pkg.adb.xcov': {'+': {4}}, - 'pkg.ads.xcov': {}, -}) thistest.result() diff --git a/testsuite/tests/instr-cov/pure_units/test.py b/testsuite/tests/instr-cov/pure_units/test.py index eb18197e1..118fecec0 100644 --- a/testsuite/tests/instr-cov/pure_units/test.py +++ b/testsuite/tests/instr-cov/pure_units/test.py @@ -11,24 +11,27 @@ from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') + trace_mode="src", +) check_xcov_reports( - 'xcov', - {'pkg.ads.xcov': {'+': {12, 15}, '-': {11, 14}}, - 'pkg.adb.xcov': {'+': {5, 6}, '-': {8}}, - 'pkg-child.ads.xcov': {'+': {9}, '-': {10, 12, 13}}}, + "xcov", + { + "pkg.ads.xcov": {"+": {12, 15}, "-": {11, 14}}, + "pkg.adb.xcov": {"+": {5, 6}, "-": {8}}, + "pkg-child.ads.xcov": {"+": {9}, "-": {10, 12, 13}}, + }, ) thistest.result() diff --git a/testsuite/tests/instr-cov/remove_extra_src/test.py b/testsuite/tests/instr-cov/remove_extra_src/test.py index 61cfb64c0..ad0edb00c 100644 --- a/testsuite/tests/instr-cov/remove_extra_src/test.py +++ b/testsuite/tests/instr-cov/remove_extra_src/test.py @@ -27,43 +27,56 @@ from SUITE.gprutils import GPRswitches -Wdir('tmp_') +Wdir("tmp_") # Create projects -mylib_gpr = gprfor(prjid='mylib', mains=[], langs=['Ada'], - srcdirs=['../src-mylib'], - objdir='obj-mylib') -dummy_gpr = gprfor(prjid='dummy', mains=[], langs=['C'], - srcdirs=['../src-myprog'], - objdir='obj-myprog') -myprog_gpr = gprfor(prjid='myprog', mains=['prog.adb'], - srcdirs=['../src-myprog'], - objdir='obj-myprog', - deps=['mylib', 'dummy']) +mylib_gpr = gprfor( + prjid="mylib", + mains=[], + langs=["Ada"], + srcdirs=["../src-mylib"], + objdir="obj-mylib", +) +dummy_gpr = gprfor( + prjid="dummy", + mains=[], + langs=["C"], + srcdirs=["../src-myprog"], + objdir="obj-myprog", +) +myprog_gpr = gprfor( + prjid="myprog", + mains=["prog.adb"], + srcdirs=["../src-myprog"], + objdir="obj-myprog", + deps=["mylib", "dummy"], +) # Instrument mylib.gpr xcov_instrument( gprsw=GPRswitches(root_project=mylib_gpr), - covlevel='stmt', - gpr_obj_dir='obj-mylib', - out='instr-mylib.log') + covlevel="stmt", + gpr_obj_dir="obj-mylib", + out="instr-mylib.log", +) # Create a non-empty directory in the mylib-gnatcov-instr folder, to check that # the removal machinery handles it well (ignores it). -subdir = os.path.join('obj-mylib', 'mylib-gnatcov-instr', 'foo') +subdir = os.path.join("obj-mylib", "mylib-gnatcov-instr", "foo") os.mkdir(subdir) -with open(os.path.join(subdir, 'foo.txt'), 'w') as f: +with open(os.path.join(subdir, "foo.txt"), "w") as f: pass # Instrument, build, run and generate a coverage report for myprog.gpr (and not # mylib.gpr). build_run_and_coverage( gprsw=GPRswitches(root_project=myprog_gpr, no_subprojects=True), - covlevel='stmt', - mains=['prog'], - gpr_obj_dir='obj-myprog', - extra_coverage_args=['-axcov', '--output-dir=xcov'], - trace_mode='src') -check_xcov_reports('xcov', {'prog.adb.xcov': {'+': {5}, '-': {6}}}) + covlevel="stmt", + mains=["prog"], + gpr_obj_dir="obj-myprog", + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports("xcov", {"prog.adb.xcov": {"+": {5}, "-": {6}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/scalar_and/test.py b/testsuite/tests/instr-cov/scalar_and/test.py index 67aa485f1..9a5f058d4 100644 --- a/testsuite/tests/instr-cov/scalar_and/test.py +++ b/testsuite/tests/instr-cov/scalar_and/test.py @@ -9,19 +9,20 @@ from SUITE.gprutils import GPRswitches -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches(root_project=p_gpr), - covlevel='stmt+decision', - mains=['main'], - extra_coverage_args=['-axcov', '--output-dir=xcov'], + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') -check_xcov_reports('xcov', {'main.adb.xcov': {'+': {4, 6}}}) + trace_mode="src", +) +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {4, 6}}}) thistest.result() diff --git a/testsuite/tests/instr-cov/stmt_after_accept/test.py b/testsuite/tests/instr-cov/stmt_after_accept/test.py index a763e43ff..a44b88bcc 100644 --- a/testsuite/tests/instr-cov/stmt_after_accept/test.py +++ b/testsuite/tests/instr-cov/stmt_after_accept/test.py @@ -19,8 +19,11 @@ extra_coverage_args=["-axcov", "--output-dir=xcov"], trace_mode="src", ) -check_xcov_reports("xcov", { - "main.adb.xcov": {"+": {14, 15, 18, 19, 30, 32}, "-": {20, 23, 25}}, -}) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {14, 15, 18, 19, 30, 32}, "-": {20, 23, 25}}, + }, +) thistest.result() diff --git a/testsuite/tests/instr-cov/unknown_unit/test.py b/testsuite/tests/instr-cov/unknown_unit/test.py index 4fb028703..e30ba57c5 100644 --- a/testsuite/tests/instr-cov/unknown_unit/test.py +++ b/testsuite/tests/instr-cov/unknown_unit/test.py @@ -16,40 +16,52 @@ from SUITE.tutils import xcov -p_gpr = os.path.abspath('p.gpr') -obj_dir = os.path.abspath('obj') -unrelated_sid = 'unrelated_instr.sid' +p_gpr = os.path.abspath("p.gpr") +obj_dir = os.path.abspath("obj") +unrelated_sid = "unrelated_instr.sid" -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") # Instrument the main, only to get an SID file that is unrelated to the units # we want to cover (pkg). xcov_instrument( - gprsw=GPRswitches(root_project=p_gpr, units=['main']), - gpr_obj_dir='obj', - covlevel='stmt') -cp(os.path.join('..', 'obj', 'main.sid'), unrelated_sid) + gprsw=GPRswitches(root_project=p_gpr, units=["main"]), + gpr_obj_dir="obj", + covlevel="stmt", +) +cp(os.path.join("..", "obj", "main.sid"), unrelated_sid) # Instrument/build/run the project only for the "pkg" unit xcov_args = build_and_run( - gprsw=GPRswitches(root_project=p_gpr, units=['pkg']), - covlevel='stmt', - mains=['main'], + gprsw=GPRswitches(root_project=p_gpr, units=["pkg"]), + covlevel="stmt", + mains=["main"], extra_coverage_args=[], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, - trace_mode='src') + trace_mode="src", +) trace_file = xcov_args[-1] # Try to produce a coverage report for it, but providing the wrong SID -mkdir('xcov') -p = xcov(['coverage', '-v', '-axcov', '--output-dir=xcov', - '--level', 'stmt', - '--sid', unrelated_sid, trace_file], - out='coverage.log') +mkdir("xcov") +p = xcov( + [ + "coverage", + "-v", + "-axcov", + "--output-dir=xcov", + "--level", + "stmt", + "--sid", + unrelated_sid, + trace_file, + ], + out="coverage.log", +) thistest.fail_if( - '[GNATCOV.MISC] discarding source trace entry for unknown instrumented' - ' unit: body of pkg' - not in lines_of('coverage.log')) + "[GNATCOV.MISC] discarding source trace entry for unknown instrumented" + " unit: body of pkg" not in lines_of("coverage.log") +) thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py index 3d9ba7ad8..eeffaca35 100644 --- a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py +++ b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py @@ -19,7 +19,7 @@ "--runtime-project=no_such_gnatcov_rts", ], out=integration_log, - register_failure=False + register_failure=False, ) thistest.fail_if(p.status == 0, "gnatcov exit status shouldn't be success") @@ -31,7 +31,7 @@ regexp=( ".*gnatcov.*: Could not load the coverage runtime project" " no_such_gnatcov_rts" - "\nno_such_gnatcov_rts\\.gpr: error: project file \".*\" not found" + '\nno_such_gnatcov_rts\\.gpr: error: project file ".*" not found' ), actual=contents_of(integration_log).strip(), ) diff --git a/testsuite/tests/integrated_instrumentation/basic_cmake/test.py b/testsuite/tests/integrated_instrumentation/basic_cmake/test.py index b33378ec6..cf894a5b4 100644 --- a/testsuite/tests/integrated_instrumentation/basic_cmake/test.py +++ b/testsuite/tests/integrated_instrumentation/basic_cmake/test.py @@ -29,8 +29,10 @@ env.add_search_path(env_var="PATH", path=cwd) # Then, run the build process unchanged -compiler_wrapper = os.path.join(cwd, 'gcc') -cmdrun(["cmake", "..", f"-DCMAKE_C_COMPILER={compiler_wrapper}"], for_pgm=False) +compiler_wrapper = os.path.join(cwd, "gcc") +cmdrun( + ["cmake", "..", f"-DCMAKE_C_COMPILER={compiler_wrapper}"], for_pgm=False +) cmdrun(["make"], for_pgm=False) # Run the executable diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/test.py b/testsuite/tests/integrated_instrumentation/cmake_lib/test.py index 65999d17e..1a921d870 100644 --- a/testsuite/tests/integrated_instrumentation/cmake_lib/test.py +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/test.py @@ -31,8 +31,10 @@ env.add_search_path(env_var="PATH", path=cwd) # Then, run the build process unchanged -compiler_wrapper = os.path.join(cwd, 'gcc') -cmdrun(["cmake", "..", f"-DCMAKE_C_COMPILER={compiler_wrapper}"], for_pgm=False) +compiler_wrapper = os.path.join(cwd, "gcc") +cmdrun( + ["cmake", "..", f"-DCMAKE_C_COMPILER={compiler_wrapper}"], for_pgm=False +) cmdrun(["make"], for_pgm=False) # Run the executable @@ -54,7 +56,7 @@ { "main.c.xcov": {"+": {8, 9}}, "lib.c.xcov": {"+": {6}}, - } + }, ) thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py index c3c96aa5b..712be42d1 100644 --- a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py @@ -81,11 +81,14 @@ f'\r?\n {os.path.join(cwd, "libbar", "bar.c")}', contents_of(log_file), ) -check_xcov_reports(".", { - "libbar-bar.c.xcov": {"+": {4}}, - "libbar-foo.c.xcov": {"+": {4}}, - "libfoo-bar.c.xcov": {"-": {4}}, - "libfoo-foo.c.xcov": {"-": {4}}, -}) +check_xcov_reports( + ".", + { + "libbar-bar.c.xcov": {"+": {4}}, + "libbar-foo.c.xcov": {"+": {4}}, + "libfoo-bar.c.xcov": {"-": {4}}, + "libfoo-foo.c.xcov": {"-": {4}}, + }, +) thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/special_filenames/test.py b/testsuite/tests/integrated_instrumentation/special_filenames/test.py index 66338df90..2b81fd9c3 100644 --- a/testsuite/tests/integrated_instrumentation/special_filenames/test.py +++ b/testsuite/tests/integrated_instrumentation/special_filenames/test.py @@ -19,7 +19,7 @@ # case of a filename containing a double quote or a backslash on Windows # because of filename restrictions on that platform. copy_map = { - "bar.c": 'src bar.c' if env.build.os.name == "windows" else 'src\\"bar.c', + "bar.c": "src bar.c" if env.build.os.name == "windows" else 'src\\"bar.c', "foo.c": "src foo$@.c", "test.c": "test.c", } @@ -62,11 +62,10 @@ cmdrun(["test program"], for_pgm=False) # Check coverage expectations -sid_args = [f"--sid={filename}.sid" for filename in canonicalized_filenames.values()] -xcov( - ["coverage", "-cstmt", "-axcov", srctracename_for("test")] - + sid_args -) +sid_args = [ + f"--sid={filename}.sid" for filename in canonicalized_filenames.values() +] +xcov(["coverage", "-cstmt", "-axcov", srctracename_for("test")] + sid_args) check_xcov_reports(".", expected_report) thistest.result() diff --git a/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py index 7ff57e9b1..a384542cb 100644 --- a/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py +++ b/testsuite/tests/relocate-build-tree/unmodified-root-dir/test.py @@ -14,7 +14,7 @@ expected_reports = { - "ops.adb.xcov": {'+': {4, 5}, '-': {6}}, + "ops.adb.xcov": {"+": {4, 5}, "-": {6}}, "ops.ads.xcov": {}, } diff --git a/testsuite/tests/scos-overlap/test.py b/testsuite/tests/scos-overlap/test.py index b13730661..eac3ca1c8 100644 --- a/testsuite/tests/scos-overlap/test.py +++ b/testsuite/tests/scos-overlap/test.py @@ -81,7 +81,7 @@ def run_variant(label, col_ranges, expected_warnings): thistest.fail_if_not_equal( '"gnatcov instrument" warnings', "\n".join(str(w) for w in expected_warnings), - "\n".join(line.rstrip() for line in contents_of(log).splitlines()) + "\n".join(line.rstrip() for line in contents_of(log).splitlines()), ) wd.to_homedir() diff --git a/testsuite/tests/shared-libs/ada-main/test.py b/testsuite/tests/shared-libs/ada-main/test.py index a0be36357..6aec67df9 100644 --- a/testsuite/tests/shared-libs/ada-main/test.py +++ b/testsuite/tests/shared-libs/ada-main/test.py @@ -12,43 +12,53 @@ from SUITE.tutils import gprfor -wd = Wdir('tmp_') +wd = Wdir("tmp_") # Create one project file to build the pure Ada library to test mylib_gpr = gprfor( - mains=[], prjid='mylib', langs=['Ada'], - srcdirs='../src-mylib', objdir='obj-mylib', + mains=[], + prjid="mylib", + langs=["Ada"], + srcdirs="../src-mylib", + objdir="obj-mylib", extra='for Library_Name use "mylib";' - '\nfor Library_Kind use "relocatable";' - '\nfor Library_Dir use "lib-mylib";') + '\nfor Library_Kind use "relocatable";' + '\nfor Library_Dir use "lib-mylib";', +) # Create another project to build Ada program to test the library main_gpr = gprfor( - mains=['main.adb'], prjid='main', langs=['Ada'], deps=['mylib'], - srcdirs='../src-main', objdir='obj-main') + mains=["main.adb"], + prjid="main", + langs=["Ada"], + deps=["mylib"], + srcdirs="../src-main", + objdir="obj-main", +) # Make sure that subprocesses can import the shared library for mylib. On Unix # systems, there is nothing specific to do thanks to RPATH magic, but on # Windows we need to add its directory to PATH. -lib_dir = os.path.abspath('lib-mylib') -os.environ['PATH'] = '{}{}{}'.format( - lib_dir, os.path.pathsep, os.environ['PATH']) +lib_dir = os.path.abspath("lib-mylib") +os.environ["PATH"] = "{}{}{}".format( + lib_dir, os.path.pathsep, os.environ["PATH"] +) build_run_and_coverage( - gprsw=GPRswitches(root_project=main_gpr, - projects=['mylib']), - covlevel='stmt', - gpr_obj_dir='obj-main', - mains=['main'], - extra_coverage_args=['--annotate=xcov', '--output-dir=.'], + gprsw=GPRswitches(root_project=main_gpr, projects=["mylib"]), + covlevel="stmt", + gpr_obj_dir="obj-main", + mains=["main"], + extra_coverage_args=["--annotate=xcov", "--output-dir=."], # There are several projects in the closure: main_gpr, mylib_gpr and # gnatcov_rts_full. GPRbuild will complain if one library does not have the # same kind as the others, so force relocatable. - extra_gprbuild_args=['-XLIBRARY_TYPE=relocatable']) + extra_gprbuild_args=["-XLIBRARY_TYPE=relocatable"], +) check_xcov_reports( - '.', {'mylib.adb.xcov': {'+': {5, 6}, '-': {8}}, 'mylib.ads.xcov': {}} + ".", {"mylib.adb.xcov": {"+": {5, 6}, "-": {8}}, "mylib.ads.xcov": {}} ) thistest.result() diff --git a/testsuite/tests/shared-libs/c-main/test.py b/testsuite/tests/shared-libs/c-main/test.py index c87c79982..666fd359e 100644 --- a/testsuite/tests/shared-libs/c-main/test.py +++ b/testsuite/tests/shared-libs/c-main/test.py @@ -12,41 +12,50 @@ from SUITE.tutils import gprfor -wd = Wdir('tmp_') +wd = Wdir("tmp_") # Create one project file to build the pure Ada library to test mylib_gpr = gprfor( - mains=[], prjid='mylib', langs=['Ada'], - srcdirs='../src-mylib', objdir='obj-mylib', + mains=[], + prjid="mylib", + langs=["Ada"], + srcdirs="../src-mylib", + objdir="obj-mylib", extra='for Library_Name use "mylib";' - '\nfor Library_Kind use "relocatable";' - '\nfor Library_Dir use "lib-mylib";') + '\nfor Library_Kind use "relocatable";' + '\nfor Library_Dir use "lib-mylib";', +) # Create another project to build the mixed C/Ada program to test the library. main_gpr = gprfor( - mains=['main.c'], prjid='main', langs=['Ada', 'C'], deps=['mylib'], - srcdirs='../src-main', objdir='obj-main', + mains=["main.c"], + prjid="main", + langs=["Ada", "C"], + deps=["mylib"], + srcdirs="../src-main", + objdir="obj-main", ) # Make sure that subprocesses can import the shared library for mylib. On Unix # systems, there is nothing specific to do thanks to RPATH magic, but on # Windows we need to add its directory to PATH. -lib_dir = os.path.abspath('lib-mylib') -os.environ['PATH'] = '{}{}{}'.format( - lib_dir, os.path.pathsep, os.environ['PATH']) +lib_dir = os.path.abspath("lib-mylib") +os.environ["PATH"] = "{}{}{}".format( + lib_dir, os.path.pathsep, os.environ["PATH"] +) build_run_and_coverage( - gprsw=GPRswitches(root_project=main_gpr, - projects=['mylib']), - covlevel='stmt', - gpr_obj_dir='obj-main', - mains=['main'], - extra_coverage_args=['--annotate=xcov', '--output-dir=.'], - extra_gprbuild_args=['-XLIBRARY_TYPE=relocatable']) - -check_xcov_reports('.', { - 'mylib.adb.xcov': {'+': {5, 6}, '-': {8}}, - 'mylib.ads.xcov': {}}) + gprsw=GPRswitches(root_project=main_gpr, projects=["mylib"]), + covlevel="stmt", + gpr_obj_dir="obj-main", + mains=["main"], + extra_coverage_args=["--annotate=xcov", "--output-dir=."], + extra_gprbuild_args=["-XLIBRARY_TYPE=relocatable"], +) + +check_xcov_reports( + ".", {"mylib.adb.xcov": {"+": {5, 6}, "-": {8}}, "mylib.ads.xcov": {}} +) thistest.result() diff --git a/testsuite/tests/subp_of_interest/test.py b/testsuite/tests/subp_of_interest/test.py index 75305bb7b..176ef0db6 100644 --- a/testsuite/tests/subp_of_interest/test.py +++ b/testsuite/tests/subp_of_interest/test.py @@ -66,8 +66,8 @@ def check_xcov(label, args, expected_output=""): ], expected_output=( "" - if src_traces else - "warning: Ignoring --subprograms switches as this is not supported" + if src_traces + else "warning: Ignoring --subprograms switches as this is not supported" " with binary traces." ), ) @@ -102,7 +102,8 @@ def check_xcov(label, args, expected_output=""): thistest.log("== xcov_ignore ==") check_xcov( "xcov_ignore", - cov_args + [ + cov_args + + [ f"--subprograms={pkg_body}:20", "--ignore-source-files=pkg.ads", ], diff --git a/testsuite/tests/subp_of_interest_c/test.py b/testsuite/tests/subp_of_interest_c/test.py index 6a2121efd..e909bd915 100644 --- a/testsuite/tests/subp_of_interest_c/test.py +++ b/testsuite/tests/subp_of_interest_c/test.py @@ -22,7 +22,7 @@ ), covlevel="stmt", mains=["main"], - trace_mode='src', + trace_mode="src", extra_coverage_args=[ "-axcov", "--subprograms", diff --git a/testsuite/tests/xml-check/test.py b/testsuite/tests/xml-check/test.py index f0b771686..952fef99f 100644 --- a/testsuite/tests/xml-check/test.py +++ b/testsuite/tests/xml-check/test.py @@ -9,20 +9,22 @@ from SUITE.tutils import gprfor -tmp = Wdir('tmp_') +tmp = Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor("test_andthen_t.adb", - srcdirs='../src')), - covlevel='stmt+mcdc', - mains=['test_andthen_t'], - extra_coverage_args=['--annotate=xml', '--output-dir=.'], - scos=['obj/andthen']) - -xmldoc = minidom.parse('andthen.adb.xml') + gprsw=GPRswitches( + root_project=gprfor("test_andthen_t.adb", srcdirs="../src") + ), + covlevel="stmt+mcdc", + mains=["test_andthen_t"], + extra_coverage_args=["--annotate=xml", "--output-dir=."], + scos=["obj/andthen"], +) + +xmldoc = minidom.parse("andthen.adb.xml") print(xmldoc.toxml()) -xmldoc = minidom.parse('index.xml') +xmldoc = minidom.parse("index.xml") print(xmldoc.toxml()) thistest.result() diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 4e0e8eddb..2c6b66883 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -94,7 +94,7 @@ class QlevelInfo(object): def __init__(self, levelid, subtrees, xcovlevel): - self.levelid = levelid # string identifier + self.levelid = levelid # string identifier # regexp of directory subtrees: testdirs that match this # hold qualification tests for this level @@ -114,7 +114,7 @@ def hosts(self, test_dir): RE_QCOMMON = "(Common|Appendix)" -RE_QLANG = "(%s)" % '|'.join(QLANGUAGES) +RE_QLANG = "(%s)" % "|".join(QLANGUAGES) # A regular expression that matches subdirs of qualification tests # that should apply for coverage criteria RE_CRIT. @@ -122,9 +122,11 @@ def hosts(self, test_dir): def RE_SUBTREE(re_crit): return "%(root)s/((%(common)s)|(%(lang)s/(%(crit)s)))" % { - "root": QROOTDIR, "common": RE_QCOMMON, - "lang": RE_QLANG, "crit": re_crit - } + "root": QROOTDIR, + "common": RE_QCOMMON, + "lang": RE_QLANG, + "crit": re_crit, + } # Note that we expect test directory names to be in unix form here. @@ -135,21 +137,17 @@ def RE_SUBTREE(re_crit): "doA": QlevelInfo( levelid="doA", subtrees=RE_SUBTREE(re_crit="stmt|decision|mcdc"), - xcovlevel="stmt+mcdc" - ), - + xcovlevel="stmt+mcdc", + ), "doB": QlevelInfo( levelid="doB", subtrees=RE_SUBTREE(re_crit="stmt|decision"), - xcovlevel="stmt+decision" - ), - + xcovlevel="stmt+decision", + ), "doC": QlevelInfo( - levelid="doC", - subtrees=RE_SUBTREE(re_crit="stmt"), - xcovlevel="stmt" - ) - } + levelid="doC", subtrees=RE_SUBTREE(re_crit="stmt"), xcovlevel="stmt" + ), +} # =============================== # == Compilation Flags Control == @@ -288,7 +286,7 @@ def maybe_exec(log, bin, args=None, edir=None): if not bin: return - to_run = [sys.executable, bin] if bin.endswith('.py') else [bin] + to_run = [sys.executable, bin] if bin.endswith(".py") else [bin] if args: to_run.extend([arg for arg in args if arg]) @@ -307,7 +305,7 @@ def maybe_exec(log, bin, args=None, edir=None): class TestPyRunner: """Helper to run a "test.py" test script.""" - filename = 'test.py' + filename = "test.py" def __init__(self, driver, result, test_prefix, working_prefix): """ @@ -334,7 +332,7 @@ def __init__(self, driver, result, test_prefix, working_prefix): # Create a "canonical" directory name for this testcase, useful to # simplify some platform-independent processings. - self.unix_test_dir = self.test_dir().replace('\\', '/') + self.unix_test_dir = self.test_dir().replace("\\", "/") # Load all relevant *.opt files to control the execution of this test self.test_control_creator = self.parse_opt() @@ -359,21 +357,21 @@ def outf(self): Same location as the test source script, with same name + a .out extra suffix extension. """ - return self.test_dir(self.filename + '.out') + return self.test_dir(self.filename + ".out") def logf(self): """ Similar to outfile, for the file where logs of the commands executed by the provided test object should go. """ - return self.test_dir(self.filename + '.log') + return self.test_dir(self.filename + ".log") def errf(self): """ Similar to outf, for the file where diffs of the provided test object should go. """ - return self.test_dir(self.filename + '.err') + return self.test_dir(self.filename + ".err") def qdaf(self): return qdaf_in(self.test_dir()) @@ -383,7 +381,7 @@ def ctxf(self): The file containing a SUITE_context describing the testcase run (the file is in pickle format). """ - return self.test_dir('ctx.dump') + return self.test_dir("ctx.dump") # -------------------------------------- # -- Testscase specific discriminants -- @@ -399,14 +397,14 @@ def discriminants(self): lang = self.lang() if lang: - discs.append('LANG_%s' % lang.upper()) + discs.append("LANG_%s" % lang.upper()) return discs def lang(self): """The language specific subtree SELF pertains to.""" for lang in control.KNOWN_LANGUAGES: - if '/{}/'.format(lang) in self.unix_test_dir: + if "/{}/".format(lang) in self.unix_test_dir: return lang return None @@ -421,16 +419,16 @@ def lookup_extra_opt(self): # world, this would be the tessuite root directory, but in practice we # often run the testsuite on "Qualif/ ../extra/tests/", so if there is # an "extra" directory above the root directory, allow one level up. - root_dir = self.driver.test_env['testsuite_root_dir'] - up_root = os.path.abspath(os.path.join(root_dir, '..')) - if os.path.exists(os.path.join(up_root, 'extra')): + root_dir = self.driver.test_env["testsuite_root_dir"] + up_root = os.path.abspath(os.path.join(root_dir, "..")) + if os.path.exists(os.path.join(up_root, "extra")): root_dir = up_root # Climb up from the testcase directory to the testsuite root directory # and gather all extra.opt files found in the way. - d = self.test_dir('..') + d = self.test_dir("..") while d.startswith(root_dir): - extra_opt = os.path.join(d, 'extra.opt') + extra_opt = os.path.join(d, "extra.opt") if os.path.exists(extra_opt): result.append(extra_opt) d = os.path.dirname(d) @@ -449,7 +447,7 @@ def parse_opt(self): # directory tree order, then feed that to the opt file parser. opt_files = [] - test_opt = self.test_dir('test.opt') + test_opt = self.test_dir("test.opt") if os.path.exists(test_opt): opt_files.append(test_opt) @@ -458,14 +456,15 @@ def parse_opt(self): opt_lines = sum((lines_of(f) for f in opt_files), []) # Create a single "control.opt" file to contain all control directives - control_opt = self.working_dir('control.opt') - with open(control_opt, 'w') as f: + control_opt = self.working_dir("control.opt") + with open(control_opt, "w") as f: for line in opt_lines: - f.write(line + '\n') + f.write(line + "\n") return AdaCoreLegacyTestControlCreator( system_tags=self.env.suite_discriminants + self.discriminants(), - opt_filename=control_opt) + opt_filename=control_opt, + ) def set_up(self): mopt = self.env.main_options @@ -492,13 +491,15 @@ def set_up(self): # Construct the test command line - testcase_cmd = [sys.executable, - self.test_dir(self.filename), - '--report-file=' + outf, - '--log-file=' + logf] + testcase_cmd = [ + sys.executable, + self.test_dir(self.filename), + "--report-file=" + outf, + "--log-file=" + logf, + ] if mopt.enable_valgrind: - testcase_cmd.append('--enable-valgrind=' + mopt.enable_valgrind) + testcase_cmd.append("--enable-valgrind=" + mopt.enable_valgrind) # Propagate our command line arguments as testcase options. # @@ -511,63 +512,65 @@ def set_up(self): # the requested level (validated by GNATcovTestFinder.probe): if mopt.qualif_level: - testcase_cmd.append('--qualif-level=%s' % mopt.qualif_level) + testcase_cmd.append("--qualif-level=%s" % mopt.qualif_level) testcase_cmd.append( - '--xcov-level=%s' % QLEVEL_INFO[mopt.qualif_level].xcovlevel) + "--xcov-level=%s" % QLEVEL_INFO[mopt.qualif_level].xcovlevel + ) if mopt.build: - testcase_cmd.append('--build=%s' % mopt.build) + testcase_cmd.append("--build=%s" % mopt.build) if mopt.target: - testcase_cmd.append('--target=%s' % mopt.target) + testcase_cmd.append("--target=%s" % mopt.target) if mopt.board: - testcase_cmd.append('--board=%s' % mopt.board) + testcase_cmd.append("--board=%s" % mopt.board) if mopt.gprmode: - testcase_cmd.append('--gprmode') + testcase_cmd.append("--gprmode") if mopt.trace_mode: - testcase_cmd.append('--trace-mode=%s' % mopt.trace_mode) + testcase_cmd.append("--trace-mode=%s" % mopt.trace_mode) if mopt.kernel: - testcase_cmd.append('--kernel=%s' % mopt.kernel) + testcase_cmd.append("--kernel=%s" % mopt.kernel) if mopt.trace_size_limit: testcase_cmd.append( - '--trace-size-limit=%s' % mopt.trace_size_limit) + "--trace-size-limit=%s" % mopt.trace_size_limit + ) if mopt.RTS: - testcase_cmd.append('--RTS=%s' % mopt.RTS) + testcase_cmd.append("--RTS=%s" % mopt.RTS) if mopt.largs: - testcase_cmd.append('--largs=%s' % mopt.largs.strip()) + testcase_cmd.append("--largs=%s" % mopt.largs.strip()) - testcase_cmd.append('--tags=@%s' % self.env.discr_file) + testcase_cmd.append("--tags=@%s" % self.env.discr_file) if mopt.auto_arch: - testcase_cmd.append('--auto-arch') + testcase_cmd.append("--auto-arch") if mopt.consolidate: - testcase_cmd.append('--consolidate=%s' % mopt.consolidate) + testcase_cmd.append("--consolidate=%s" % mopt.consolidate) if mopt.pretty_print: - testcase_cmd.append('--pretty-print') + testcase_cmd.append("--pretty-print") if mopt.spark_tests: - testcase_cmd.append('--spark-tests=%s' % mopt.spark_tests) + testcase_cmd.append("--spark-tests=%s" % mopt.spark_tests) if mopt.all_warnings: - testcase_cmd.append('--all-warnings') + testcase_cmd.append("--all-warnings") if mopt.default_dump_trigger: testcase_cmd.append( - f'--default-dump-trigger={mopt.default_dump_trigger}' + f"--default-dump-trigger={mopt.default_dump_trigger}" ) if mopt.default_dump_channel: testcase_cmd.append( - f'--default-dump-channel={mopt.default_dump_channel}' + f"--default-dump-channel={mopt.default_dump_channel}" ) # --gnatcov_ family @@ -575,9 +578,13 @@ def set_up(self): for pgm, cmd in control.ALTRUN_GNATCOV_PAIRS: if getattr(mopt, altrun_attr_for(pgm, cmd)) is None: continue - testcase_cmd.append('--%(opt)s=%(val)s' % { - 'opt': altrun_opt_for(pgm, cmd), - 'val': getattr(mopt, altrun_attr_for(pgm, cmd))}) + testcase_cmd.append( + "--%(opt)s=%(val)s" + % { + "opt": altrun_opt_for(pgm, cmd), + "val": getattr(mopt, altrun_attr_for(pgm, cmd)), + } + ) # --gpr family for pgm in control.ALTRUN_GPR: @@ -591,9 +598,13 @@ def set_up(self): # --cargs family for lang in [None] + control.KNOWN_LANGUAGES: - testcase_cmd.append('--%(opt)s=%(val)s' % { - "opt": cargs_opt_for(lang), - "val": getattr(mopt, cargs_attr_for(lang))}) + testcase_cmd.append( + "--%(opt)s=%(val)s" + % { + "opt": cargs_opt_for(lang), + "val": getattr(mopt, cargs_attr_for(lang)), + } + ) # Compute the testcase timeout, whose default vary depending on whether # we use Valgrind. @@ -621,8 +632,9 @@ def maybe_exec(self, bin, args=None, edir=None): def run(self): mopt = self.env.main_options - self.maybe_exec(mopt.pre_testcase, args=[mopt.altrun], - edir=self.test_dir()) + self.maybe_exec( + mopt.pre_testcase, args=[mopt.altrun], edir=self.test_dir() + ) # Run the "test.py" script in the testsuite root directory (as # expected: the script will change its own CWD later). @@ -630,14 +642,15 @@ def run(self): self.test_py_process = Run( self.testcase_cmd, cwd=self.env.root_dir, - timeout=self.testcase_timeout) + timeout=self.testcase_timeout, + ) end_time = time.time() self.result.time = end_time - start_time # To ease debugging, copy the consolidated standard outputs (stdout + # stderr) to the "test.py.err" file. - with open(self.errf(), 'w') as f: + with open(self.errf(), "w") as f: f.write(self.test_py_process.out) # If the script exitted with an error status code, consider that the @@ -660,17 +673,15 @@ def tear_down(self): # Execute a post-testcase action if requested so, before the test # artifacts might be cleared by a post-run cleanup: - self.maybe_exec(args.post_testcase, args=[args.altrun], - edir=self.test_dir()) + self.maybe_exec( + args.post_testcase, args=[args.altrun], edir=self.test_dir() + ) # Perform post-run cleanups if requested so. Note that this may # alter the test execution status to make sure that unexpected cleanup # failures get visibility: - if ( - self.result.status != TestStatus.FAIL - and args.do_post_run_cleanups - ): + if self.result.status != TestStatus.FAIL and args.do_post_run_cleanups: self.do_post_run_cleanups(ts_options=args) if args.qualif_level: @@ -678,20 +689,24 @@ def tear_down(self): def analyze(self): if self.test_py_failed: - self.push_failure("test.py exitted with status code {}" - .format(self.test_py_process.status)) + self.push_failure( + "test.py exitted with status code {}".format( + self.test_py_process.status + ) + ) elif cutils.match("==== PASSED ==================", self.outf()): self.push_success() else: self.push_failure("Missing PASSED tag in output file") - def run_test(self, previous_values, slot): + def run_test(self, previous_values, slot): """Run the testcase, analyze its result and push the result.""" try: self.test_control = self.test_control_creator.create(self.driver) except ValueError as exc: return self.push_error( - "Error while interpreting control: {}".format(exc)) + "Error while interpreting control: {}".format(exc) + ) # If test control tells us to skip the test, stop right here if self.test_control.skip: @@ -758,10 +773,13 @@ def latch_status(self): r = self.result pdump_to( self.stdf(), - o=TC_status(passed=r.status in (TestStatus.PASS, TestStatus.XPASS), - xfail=self.test_control.xfail, - status=r.status.name, - comment=self.test_control.message)) + o=TC_status( + passed=r.status in (TestStatus.PASS, TestStatus.XPASS), + xfail=self.test_control.xfail, + status=r.status.name, + comment=self.test_control.message, + ), + ) def latched_status(self): return pload_from(self.stdf()) @@ -771,20 +789,29 @@ def _handle_info_for(self, path): the provided PATH, such as the output of the "handle" sysinternal on Windows.""" - if sys.platform != 'win32': + if sys.platform != "win32": return "No handle info on non-windows platform" # Adjust the provided path to something - path = re.sub('^[a-zA-Z]:(.*)', r'\1', path).replace('/', '\\') + path = re.sub("^[a-zA-Z]:(.*)", r"\1", path).replace("/", "\\") gpdir = os.path.dirname(sys.executable) handle_path = os.path.abspath( - os.path.join(gpdir, 'Lib', 'site-packages', - 'gnatpython', 'internal', 'data', 'libexec', - 'x86-windows', 'handle.exe')) + os.path.join( + gpdir, + "Lib", + "site-packages", + "gnatpython", + "internal", + "data", + "libexec", + "x86-windows", + "handle.exe", + ) + ) - return Run([handle_path, '/AcceptEULA', '-a', '-u', path]).out + return Run([handle_path, "/AcceptEULA", "-a", "-u", path]).out def do_post_run_cleanups(self, ts_options): """Cleanup temporary artifacts from the testcase directory. @@ -827,24 +854,24 @@ def cleanup_on_match(subdirs, prefixes, parent): # Perform a filesystem walk to craft the list of items we # can/should remove. Make it topdown so we can arrange not to # recurse within subirectories we cleanup as a whole. - for dirpath, dirnames, filenames in ( - os.walk(self.test_dir(), topdown=True)): - + for dirpath, dirnames, filenames in os.walk( + self.test_dir(), topdown=True + ): # Nothing in "obj" dirs ever needs to be preserved cleanup_on_match( - subdirs=dirnames, prefixes=['tmp', 'obj'], - parent=dirpath) + subdirs=dirnames, prefixes=["tmp", "obj"], parent=dirpath + ) # We can also always get rid of all the pure binary artifacts, # wherever they are produced. Files without extension, most often # executables, are considered never of interest. for fn in filenames: if ( - fn.endswith('.trace') - or fn.endswith('.obj') - or fn.endswith('.o') - or fn.endswith('.exe') - or '.' not in fn + fn.endswith(".trace") + or fn.endswith(".obj") + or fn.endswith(".o") + or fn.endswith(".exe") + or "." not in fn ): cleanup_q.append(os.path.join(dirpath, fn)) @@ -855,13 +882,14 @@ def cleanup_on_match(subdirs, prefixes, parent): # packages. if not ts_options.qualif_level: for fn in filenames: - if (fn == 'test.py.log'): + if fn == "test.py.log": cleanup_q.append(os.path.join(dirpath, fn)) cleanup_on_match( subdirs=dirnames, - prefixes=['st_', 'dc_', 'mc_', 'uc_'], - parent=dirpath) + prefixes=["st_", "dc_", "mc_", "uc_"], + parent=dirpath, + ) # Deal with occasional removal failures presumably caused by stray # handles. Expand glob patterns locally, issue separate rm requests @@ -873,31 +901,34 @@ def cleanup_on_match(subdirs, prefixes, parent): except Exception: handle_comment = self._handle_info_for(path) self.passed = False - self.status = 'RMFAILED' + self.status = "RMFAILED" comments.append( - "Removal of %s failed\nHandle info follows:" % path) + "Removal of %s failed\nHandle info follows:" % path + ) comments.append(handle_comment) - with open(self.errf(), 'a') as f: - f.write('\n'.join(comments)) + with open(self.errf(), "a") as f: + f.write("\n".join(comments)) class TestPyDriver(TestDriver): """ Test driver that runs "test.py" scripts. """ + def add_test(self, dag): self.runner = TestPyRunner( self, self.result, self.test_dir(), self.working_dir() ) - self.add_fragment(dag, 'run', self.runner.run_test) + self.add_fragment(dag, "run", self.runner.run_test) class GroupPyDriver(TestDriver): """ Test driver that runs "group.py" scripts. """ + def add_test(self, dag): # Generator of unique indexes for generated testcases indexes = itertools.count(1) @@ -921,8 +952,7 @@ def add_test_py_run(self, dag, test_dir, index): # as for regular tests. test_rel_dir = os.path.relpath(test_dir, self.test_dir()) test_name = "{}-{}".format( - self.test_name, - test_rel_dir.replace("\\", "/").replace("/", "-") + self.test_name, test_rel_dir.replace("\\", "/").replace("/", "-") ) # For debuggability, derive the group.py test environment @@ -938,9 +968,7 @@ def add_test_py_run(self, dag, test_dir, index): class GNATcovTestFinder(TestFinder): - def probe(self, testsuite, dirpath, dirnames, filenames): - # If we are running in qualification mode, punt if this test # is not within the subtrees attached to the requested level. qlevel = testsuite.main.args.qualif_level @@ -949,12 +977,12 @@ def probe(self, testsuite, dirpath, dirnames, filenames): # If directory contains a "test.py" file *and* not a ".generated" # one, this this is a regular testcase. - if 'test.py' in filenames and '.generated' not in filenames: + if "test.py" in filenames and ".generated" not in filenames: driver_cls = TestPyDriver # If it contains a "group.py" file, then this is a special test that # generates several actual testcases. - elif 'group.py' in filenames: + elif "group.py" in filenames: driver_cls = GroupPyDriver # Otherwise, there is no testcase @@ -965,7 +993,7 @@ def probe(self, testsuite, dirpath, dirnames, filenames): return ParsedTest( test_name=testsuite.test_name(dirpath), driver_cls=driver_cls, - test_env={'testsuite_root_dir': testsuite.root_dir}, + test_env={"testsuite_root_dir": testsuite.root_dir}, test_dir=dirpath, ) @@ -976,7 +1004,6 @@ def probe(self, testsuite, dirpath, dirnames, filenames): class TestSuite(e3.testsuite.Testsuite): - enable_cross_support = True @property @@ -991,7 +1018,7 @@ def test_name(self, test_dir): # strip leading "..". pattern = os.path.pardir + os.path.sep while result.startswith(pattern): - result = result[len(pattern):] + result = result[len(pattern) :] # Run some name canonicalization and replace directory separators with # dashes. @@ -1000,7 +1027,7 @@ def test_name(self, test_dir): # Tests from the internal testsuite used to be located in the "tests" # subdirectory. They are now in "../extra/tests", but we want the GAIA # name to remain the same. - return strip_prefix('extra-', result) + return strip_prefix("extra-", result) # -------------------------- # -- GAIA file facilities -- @@ -1014,24 +1041,24 @@ def _push_log(self, textlist, filename): # consecutive failures. We must be careful not to dump a possibly # invalid empty line in the output file in such a case. if textlist: - with open(os.path.join(self.output_dir, filename), mode='a') as fd: - fd.write('\n'.join(textlist) + '\n') + with open(os.path.join(self.output_dir, filename), mode="a") as fd: + fd.write("\n".join(textlist) + "\n") def _push_comments(self, textlist): - self._push_log(textlist=textlist, filename='comment') + self._push_log(textlist=textlist, filename="comment") self._comment_lines.extend(textlist) def _push_results(self, textlist): - self._push_log(textlist=textlist, filename='results') + self._push_log(textlist=textlist, filename="results") def _push_altrun(self, textlist): - self._push_log(textlist=textlist, filename='altrun') + self._push_log(textlist=textlist, filename="altrun") def _discriminants_log(self): - return os.path.join(self.output_dir, 'discs') + return os.path.join(self.output_dir, "discs") def write_comment_file(self, f): - f.write('\n'.join(self._comment_lines) + '\n') + f.write("\n".join(self._comment_lines) + "\n") # ------------------------------- # -- STR production facilities -- @@ -1050,10 +1077,9 @@ def _dump_ctxdata(self): if self.main.args.other_tool_info: (toolname, version_info) = Run( [sys.executable, self.main.args.other_tool_info], timeout=20 - ).out.split('##') + ).out.split("##") - other_tool_info = TOOL_info( - exename=toolname, ver=version_info) + other_tool_info = TOOL_info(exename=toolname, ver=version_info) else: other_tool_info = None @@ -1068,9 +1094,9 @@ def _dump_ctxdata(self): gnatpro=TOOL_info(self.tool("gcc")), gnatemu=TOOL_info(self.tool("gnatemu")), gnatcov=TOOL_info("gnatcov"), - other=other_tool_info - ) - ) + other=other_tool_info, + ), + ) # ----------------------- # -- Common facilities -- @@ -1085,13 +1111,11 @@ def tool(self, name): :rtype: str """ if self.env.is_cross: - return self.env.target.triplet + '-' + name + return self.env.target.triplet + "-" + name else: return name - def _build_libsupport(self): - args = self.main.args libsup_vars = [] @@ -1120,18 +1144,19 @@ def _build_libsupport(self): if args.target and "qnx" in args.target: libsup_vars.append("SILENT_LCH=exit") - logfile = os.path.join(self.output_dir, 'build_support.out') + logfile = os.path.join(self.output_dir, "build_support.out") - p = Run(['make', '--debug', '-C', 'support', '-f', 'Makefile.libsupport'] + - libsup_vars, - output=logfile) + p = Run( + ["make", "--debug", "-C", "support", "-f", "Makefile.libsupport"] + + libsup_vars, + output=logfile, + ) if p.status != 0: raise FatalError( - ("Problem during libsupport construction. %s:\n" % - logfile) + - contents_of(logfile)) - + ("Problem during libsupport construction. %s:\n" % logfile) + + contents_of(logfile) + ) def set_up(self): """ @@ -1156,7 +1181,8 @@ def set_up(self): if not re.search("-gnat95|-gnat05|-gnat12", cargs_ada + cargs): if args.qualif_level: raise FatalError( - "Missing -gnat<95|05|12> in cargs:Ada for qualification") + "Missing -gnat<95|05|12> in cargs:Ada for qualification" + ) else: setattr(args, attr_cargs_ada, cargs_ada + " -gnat05") @@ -1168,20 +1194,19 @@ def set_up(self): # Expect an explicit -gnatec if we're running for qualification if args.qualif_level and "-gnatec" not in cargs_ada: - raise FatalError( - "Missing -gnatec in cargs:Ada for qualification") + raise FatalError("Missing -gnatec in cargs:Ada for qualification") # Source traces require the use of project files to convey units of # interest, which --gprmode will do: - if args.trace_mode == 'src': + if args.trace_mode == "src": args.gprmode = True # On some targets, we need to link with -lgnat for any executable # to run and the toolchain doesn't do it automatically in some cases # (e.g. C only programs). This is a workaround: - if args.target and '-elf' in args.target: + if args.target and "-elf" in args.target: args.largs += " -lgnat" # e3.testsuite forces the writing of the "comment" file at the end of @@ -1191,12 +1216,12 @@ def set_up(self): # Initialize the GAIA log files. We need to do that before setting up # the altrun hooks, as their execution may dump output logs. - for f in ('comment', 'results', 'discs', 'altrun'): - open(os.path.join(self.output_dir, f), 'w').close() + for f in ("comment", "results", "discs", "altrun"): + open(os.path.join(self.output_dir, f), "w").close() # Add current directory in PYTHONPATH, allowing Python testcase scripts # to find the SUITE and SCOV packages: - self.env.add_search_path('PYTHONPATH', self.root_dir) + self.env.add_search_path("PYTHONPATH", self.root_dir) # Generate the discs list for test.opt parsing, and dump the list in # a file that we can then to determine which discriminants were set @@ -1204,7 +1229,8 @@ def set_up(self): self.env.suite_discriminants = self._discriminants() self._push_log( textlist=[" ".join(self.env.suite_discriminants)], - filename=self._discriminants_log()) + filename=self._discriminants_log(), + ) # Setup the alternate run hooks, if any self._setup_altrun_hooks() @@ -1221,7 +1247,7 @@ def set_up(self): self._init_strbox() self._dump_ctxdata() - with open('python_bin.dump', 'w') as f: + with open("python_bin.dump", "w") as f: f.write(sys.executable) # Dump useful comments about this run for starters @@ -1241,12 +1267,13 @@ def set_up(self): toolchain_discriminants = self._toolchain_discriminants() toolchain_discriminant = ( - toolchain_discriminants[0] if toolchain_discriminants - else None) + toolchain_discriminants[0] if toolchain_discriminants else None + ) BUILDER.RUN_CONFIG_SEQUENCE( toplev_options=self.main.args, - toolchain_discriminant=toolchain_discriminant) + toolchain_discriminant=toolchain_discriminant, + ) # Build support library as needed @@ -1273,21 +1300,24 @@ def tear_down(self): # ----------------------------------- def _options_comment(self): - return "Testsuite options:\n" + " ".join(quote_arg(arg) - for arg in sys.argv[1:]) + return "Testsuite options:\n" + " ".join( + quote_arg(arg) for arg in sys.argv[1:] + ) def _versions_comment(self): all_versions = [ - version("gnatcov") + ", " + version(self.tool("gnatls"))] + version("gnatcov") + ", " + version(self.tool("gnatls")) + ] if self.main.args.target: all_versions.append(version(self.tool("gnatemu"), nlines=2)) - return '\n'.join(["Running versions:"] + all_versions) + '\n' + return "\n".join(["Running versions:"] + all_versions) + "\n" def _early_comments(self): - return ['\n\n'.join([self._options_comment(), - self._versions_comment()])] + return [ + "\n\n".join([self._options_comment(), self._versions_comment()]) + ] # ------------------------------- # -- Discriminant computations -- @@ -1297,42 +1327,44 @@ def _discriminants(self): """Full set of discriminants that apply to this test""" return ( - self._base_discriminants() + - self._board_discriminants() + - self._qualif_level_discriminants() + - self._cargs_discriminants() + - self._rts_discriminants() + - self._toolchain_discriminants() + - self._gnatcov_discriminants()) + self._base_discriminants() + + self._board_discriminants() + + self._qualif_level_discriminants() + + self._cargs_discriminants() + + self._rts_discriminants() + + self._toolchain_discriminants() + + self._gnatcov_discriminants() + ) def _base_discriminants(self): - # List of toolchain discriminants for which we don't want to run # C++ tests, due to lack of compatibility with modern hosts. unsupported_cpp_toolchains = ["7.1.2", "5.04a1"] - result = ['ALL'] + self.env.discriminants + result = ["ALL"] + self.env.discriminants toolchain_discrs = self._toolchain_discriminants() # Only enable C++ tests if we have a C++ compiler that is not # blacklisted. - if which(self.tool('g++')) and ( + if which(self.tool("g++")) and ( not toolchain_discrs or toolchain_discrs[0] not in unsupported_cpp_toolchains ): - result.append('C++') + result.append("C++") # Add a discriminant to track the current trace mode - result.append('src-traces' - if self.main.args.trace_mode == 'src' - else 'bin-traces') + result.append( + "src-traces" + if self.main.args.trace_mode == "src" + else "bin-traces" + ) if self.main.args.spark_tests: - result.append('spark-tests') + result.append("spark-tests") if self.main.args.all_warnings: - result.append('all-warnings') + result.append("all-warnings") return result @@ -1348,11 +1380,14 @@ def _board_discriminants(self): # board was requested are good enough: boardname = ( - self.main.args.board if self.main.args.board - else self.env.target.machine if self.env.target.machine - else None) + self.main.args.board + if self.main.args.board + else self.env.target.machine + if self.env.target.machine + else None + ) - return ['board', boardname] if boardname else [] + return ["board", boardname] if boardname else [] def _cargs_discriminants(self): """ @@ -1367,12 +1402,16 @@ def _cargs_discriminants(self): Return an empty list if --cargs was not used. """ - allopts = ' '.join( - [getattr(self.main.args, attr) - for attr in (cargs_attr_for(lang) - for lang in [None] + control.KNOWN_LANGUAGES)] - ) - return ["CARGS_%s" % arg.lstrip('-') for arg in allopts.split()] + allopts = " ".join( + [ + getattr(self.main.args, attr) + for attr in ( + cargs_attr_for(lang) + for lang in [None] + control.KNOWN_LANGUAGES + ) + ] + ) + return ["CARGS_%s" % arg.lstrip("-") for arg in allopts.split()] def _qualif_level_discriminants(self): """ @@ -1382,9 +1421,10 @@ def _qualif_level_discriminants(self): """ return ( - [] if not self.main.args.qualif_level + [] + if not self.main.args.qualif_level else [self.main.args.qualif_level.upper()] - ) + ) def _rts_discriminants(self): """ @@ -1393,11 +1433,9 @@ def _rts_discriminants(self): option. """ return _runtime_info( - self.main.args.RTS, - self.env.target.platform + self.main.args.RTS, self.env.target.platform ).discrs - def _toolchain_discriminants(self): """ Compute the discriminant that reflects the version of the @@ -1406,8 +1444,9 @@ def _toolchain_discriminants(self): gcc_version = version(self.tool("gcc")) # Different version numbering for old GNAT versions - m = (re.search(r"GNAT Pro (\d\.\d\.\d)", gcc_version) or - re.search(r"GNAT Pro (5.04a1)", gcc_version)) + m = re.search(r"GNAT Pro (\d\.\d\.\d)", gcc_version) or re.search( + r"GNAT Pro (5.04a1)", gcc_version + ) return [m.group(1)] if m else [] @@ -1424,40 +1463,50 @@ def _gnatcov_discriminants(self): else [] ) - # -------------------------- # -- Command-line options -- # -------------------------- def add_options(self, parser): parser.add_argument( - '--post-run-cleanups', dest='do_post_run_cleanups', - action='store_true', - help='Request post-run cleanup of temporary artifacts.') + "--post-run-cleanups", + dest="do_post_run_cleanups", + action="store_true", + help="Request post-run cleanup of temporary artifacts.", + ) parser.add_argument( - '--qualif-level', choices=list(QLEVEL_INFO), - metavar='QUALIF_LEVEL', - help='State we are running in qualification mode for a' - ' QUALIF_LEVEL target. This selects a set of applicable tests' - ' for that level.') + "--qualif-level", + choices=list(QLEVEL_INFO), + metavar="QUALIF_LEVEL", + help="State we are running in qualification mode for a" + " QUALIF_LEVEL target. This selects a set of applicable tests" + " for that level.", + ) parser.add_argument( - '--other-tool-info', dest='other_tool_info', - metavar='OTHER_TOOL_INFO', default="", - help='Name of a python script outputing other tool##version info') + "--other-tool-info", + dest="other_tool_info", + metavar="OTHER_TOOL_INFO", + default="", + help="Name of a python script outputing other tool##version info", + ) # --pre|post family for when, what in control.ALTRUN_HOOK_PAIRS: parser.add_argument( - '--%s' % altrun_opt_for(when, what), + "--%s" % altrun_opt_for(when, what), dest=altrun_attr_for(when, what), - help='Run CMD %s to %s run' % (when, what), metavar="CMD") + help="Run CMD %s to %s run" % (when, what), + metavar="CMD", + ) parser.add_argument( - '--altrun', metavar="ALTRUN_SUBDIR", - help='Name of custom hooks directory.') + "--altrun", + metavar="ALTRUN_SUBDIR", + help="Name of custom hooks directory.", + ) # Options shared with testcase scripts @@ -1476,11 +1525,14 @@ def _resolve_paths(self): # First deal with options accepting filenames per se: attributes_to_resolve = ( - ["kernel", "altrun"] + - [altrun_attr_for(p0, p1) - for p0, p1 in (control.ALTRUN_HOOK_PAIRS - + control.ALTRUN_GNATCOV_PAIRS)] + - [altrun_attr_for(p0) for p0 in control.ALTRUN_GPR] + ["kernel", "altrun"] + + [ + altrun_attr_for(p0, p1) + for p0, p1 in ( + control.ALTRUN_HOOK_PAIRS + control.ALTRUN_GNATCOV_PAIRS + ) + ] + + [altrun_attr_for(p0) for p0 in control.ALTRUN_GPR] ) for attr in attributes_to_resolve: @@ -1502,11 +1554,12 @@ def resolve(carg): """ carg_needs_resolution = any( - carg.startswith(prefix) for prefix in prefixes_to_resolve) + carg.startswith(prefix) for prefix in prefixes_to_resolve + ) if carg_needs_resolution: - (opt, path) = carg.split('=') - return '='.join((opt, os.path.abspath(path))) + (opt, path) = carg.split("=") + return "=".join((opt, os.path.abspath(path))) else: return carg @@ -1514,7 +1567,7 @@ def resolve(carg): cargs_attr = cargs_attr_for(lang) current_cargs = getattr(self.main.args, cargs_attr).split() new_cargs = [resolve(carg) for carg in current_cargs] - setattr(self.main.args, cargs_attr, ' '.join(new_cargs)) + setattr(self.main.args, cargs_attr, " ".join(new_cargs)) # ----------------------------- # -- altrun hooks & friends -- @@ -1531,8 +1584,9 @@ def maybe_exec(self, bin, args=None, edir=None): log = Log("") p = maybe_exec(log, bin, args, edir) self._push_altrun(log.log.splitlines()) - exit_if(p.status != 0, - "Altrun hook failed ({}):\n{}".format(bin, p.out)) + exit_if( + p.status != 0, "Altrun hook failed ({}):\n{}".format(bin, p.out) + ) def _bin_for(self, base, indir=None): """For a provided BASE filename (directory path allowed), return @@ -1550,21 +1604,21 @@ def _bin_for(self, base, indir=None): if there is more than one possibility. """ - candidate_exe = ( - base + (self.env.host.os.exeext - if self.env.host.os.exeext else "")) - candidates = [candidate_exe, base+".py"] + candidate_exe = base + ( + self.env.host.os.exeext if self.env.host.os.exeext else "" + ) + candidates = [candidate_exe, base + ".py"] def relative_for(p): return p if indir is None else os.path.join(indir, p) - programs = [ - p for p in candidates if os.path.exists(relative_for(p))] + programs = [p for p in candidates if os.path.exists(relative_for(p))] exit_if( len(programs) > 1, - "from %s, too many binaries for %s:\n%s" % - (os.getcwd(), base, '\n'.join(programs))) + "from %s, too many binaries for %s:\n%s" + % (os.getcwd(), base, "\n".join(programs)), + ) return programs[0] if programs else None def _setup_altrun_hooks(self): @@ -1580,8 +1634,7 @@ def _setup_altrun_hooks(self): # hook of interest. Switch to the local directory for the setup step, # designed for local operations: - self.maybe_exec( - bin=self._bin_for("setup", indir=ctldir), edir=ctldir) + self.maybe_exec(bin=self._bin_for("setup", indir=ctldir), edir=ctldir) def install_altrun_for(p0, p1=None, binbase=None): """Establish an implicit value for the --P0_P1 command line option @@ -1596,8 +1649,8 @@ def install_altrun_for(p0, p1=None, binbase=None): attr = altrun_attr_for(p0, p1) exit_if( getattr(self.main.args, attr), - "%s altrun conflicts with explicit --%s" % (bin, attr) - ) + "%s altrun conflicts with explicit --%s" % (bin, attr), + ) self._push_altrun(["hooking %s to %s" % (attr, bin)]) setattr(self.main.args, attr, bin) @@ -1607,7 +1660,8 @@ def install_altrun_for(p0, p1=None, binbase=None): for when, what in control.ALTRUN_HOOK_PAIRS: install_altrun_for( - p0=when, p1=what, binbase=altrun_opt_for(when, what)) + p0=when, p1=what, binbase=altrun_opt_for(when, what) + ) # For the gnatcov replacements, map on binaries called # 'c': diff --git a/tools/gnatcov/examples/xml/xcov-report.py b/tools/gnatcov/examples/xml/xcov-report.py index b2b72f879..95c0e82c2 100755 --- a/tools/gnatcov/examples/xml/xcov-report.py +++ b/tools/gnatcov/examples/xml/xcov-report.py @@ -3,13 +3,17 @@ import sys from xcov import XCovReport + def show_violations(): r = XCovReport(sys.argv[1]) + def pp(source): output = source.pp_violations(r.get_levels()) if output: print(output) + r.visitor(pp) -if __name__ == '__main__': + +if __name__ == "__main__": show_violations() diff --git a/tools/gnatcov/examples/xml/xcov.py b/tools/gnatcov/examples/xml/xcov.py index 87c914f4f..6d0e56b24 100644 --- a/tools/gnatcov/examples/xml/xcov.py +++ b/tools/gnatcov/examples/xml/xcov.py @@ -6,17 +6,19 @@ COVERAGE_STATE = { - '.': 'no_code', # no code for this line, - '+': 'covered', # the coverage criteria is satisfied - '-': 'not_covered', # no instructions executed - '!': 'partially_covered'} # the coverage criteria is partially satisfied on - # this line + ".": "no_code", # no code for this line, + "+": "covered", # the coverage criteria is satisfied + "-": "not_covered", # no instructions executed + "!": "partially_covered", +} # the coverage criteria is partially satisfied on +# this line + +LEVELS = ("branch", "insn", "stmt", "decision", "mcdc") -LEVELS = ('branch', 'insn', 'stmt', 'decision', 'mcdc') def is_covered(obj): """Return True if obj is marked as covered or no_code""" - return obj.coverage in ('no_code', 'covered') + return obj.coverage in ("no_code", "covered") class Trace(object): @@ -40,10 +42,13 @@ def __init__(self, filename, program, date, tag): def __str__(self): """Pretty print the object content""" - return """ %(filename)s + return ( + """ %(filename)s program: %(program)s date: %(date)s - tag: %(tag)s""" % self.__dict__ + tag: %(tag)s""" + % self.__dict__ + ) class SrcLine(object): @@ -66,9 +71,9 @@ def __init__(self, xml_node=None): def parse_node(self, xml_node): """Parse a xml node (inside a src_mapping/src)""" - self.num = int(xml_node.getAttribute('num')) - self.src = xml_node.getAttribute('src') - self.exempted = bool(xml_node.getAttribute('exempted')) + self.num = int(xml_node.getAttribute("num")) + self.src = xml_node.getAttribute("src") + self.exempted = bool(xml_node.getAttribute("exempted")) class RefLine(SrcLine): @@ -92,16 +97,15 @@ def __init__(self, xml_node=None): def parse_node(self, xml_node): SrcLine.parse_node(self, xml_node) - if xml_node.hasAttribute('coverage'): - self.coverage = COVERAGE_STATE[xml_node.getAttribute('coverage')] - if xml_node.hasAttribute('column_begin'): - self.column_begin = int(xml_node.getAttribute('column_begin')) - if xml_node.hasAttribute('column_end'): - self.column_end = int(xml_node.getAttribute('column_end')) + if xml_node.hasAttribute("coverage"): + self.coverage = COVERAGE_STATE[xml_node.getAttribute("coverage")] + if xml_node.hasAttribute("column_begin"): + self.column_begin = int(xml_node.getAttribute("column_begin")) + if xml_node.hasAttribute("column_end"): + self.column_end = int(xml_node.getAttribute("column_end")) class Statement(object): - def __init__(self, sco_id, text, coverage): self.sco_id = int(sco_id) self.text = text @@ -110,29 +114,33 @@ def __init__(self, sco_id, text, coverage): class Decision(object): - def __init__(self, xml_node=None): self.sco_id = 0 self.text = "" self.coverage = None self.src_lines = [] - self.conditions = [] # Associated mcdc conditions + self.conditions = [] # Associated mcdc conditions if xml_node is not None: self.parse_node(xml_node) def parse_node(self, node): - self.sco_id = int(node.getAttribute('id')) - self.text = node.getAttribute('text') - self.coverage = COVERAGE_STATE[node.getAttribute('coverage')] + self.sco_id = int(node.getAttribute("id")) + self.text = node.getAttribute("text") + self.coverage = COVERAGE_STATE[node.getAttribute("coverage")] # Get only direct src child (condition inside decision contain src # node) - top_src = [n for n in node.childNodes - if hasattr(n, 'tagName') and n.tagName == 'src'] - assert(len(top_src) == 1) - self.src_lines = [RefLine(xml_node=n) - for n in top_src[0].getElementsByTagName('line')] - for cond in node.getElementsByTagName('condition'): + top_src = [ + n + for n in node.childNodes + if hasattr(n, "tagName") and n.tagName == "src" + ] + assert len(top_src) == 1 + self.src_lines = [ + RefLine(xml_node=n) + for n in top_src[0].getElementsByTagName("line") + ] + for cond in node.getElementsByTagName("condition"): self.conditions.append(Condition(cond)) @@ -149,15 +157,14 @@ def __init__(self, xml_node=None): self.parse_node(xml_node) def parse_node(self, node): - self.sco_id = int(node.getAttribute('id')) - self.text = node.getAttribute('text') - self.coverage = node.getAttribute('coverage') - for src in node.getElementsByTagName('src'): + self.sco_id = int(node.getAttribute("id")) + self.text = node.getAttribute("text") + self.coverage = node.getAttribute("coverage") + for src in node.getElementsByTagName("src"): self.src_lines = parse_src_node(src, None) class Message(object): - def __init__(self, kind, sco, message): self.kind = kind self.sco = sco @@ -166,25 +173,27 @@ def __init__(self, kind, sco, message): def parse_src_node(node, parent): - return [RefLine(xml_node=n) for n in node.getElementsByTagName('line')] + return [RefLine(xml_node=n) for n in node.getElementsByTagName("line")] def parse_message_node(node): m = Message( - kind=node.getAttribute('node'), - sco=node.getAttribute('SCO'), - message=node.getAttribute('message')) + kind=node.getAttribute("node"), + sco=node.getAttribute("SCO"), + message=node.getAttribute("message"), + ) if m.sco: - m.sco_id = int(m.sco.split(':')[0].split('#')[1]) + m.sco_id = int(m.sco.split(":")[0].split("#")[1]) return m def parse_statement_node(node, parent): stmt = Statement( - sco_id=int(node.getAttribute('id')), - text=node.getAttribute('text'), - coverage=node.getAttribute('coverage')) - for src in node.getElementsByTagName('src'): + sco_id=int(node.getAttribute("id")), + text=node.getAttribute("text"), + coverage=node.getAttribute("coverage"), + ) + for src in node.getElementsByTagName("src"): stmt.src_lines = parse_src_node(src, parent) return stmt @@ -202,11 +211,10 @@ def __init__(self, xml_node=None, srclines=None): self.src_lines = srclines def parse_node(self, node): - self.coverage = COVERAGE_STATE[node.getAttribute('coverage')] + self.coverage = COVERAGE_STATE[node.getAttribute("coverage")] class SrcMapping(object): - def __init__(self, source, xml_node=None): self.source = source self.coverage = None @@ -219,21 +227,32 @@ def __init__(self, source, xml_node=None): def parse_node(self, node): # Get only direct src child - top_src = [n for n in node.childNodes - if hasattr(n, 'tagName') and n.tagName == 'src'] - assert(len(top_src) == 1) - self.src_lines = [SrcLine(xml_node=n) - for n in top_src[0].getElementsByTagName('line')] - - self.coverage = COVERAGE_STATE[node.getAttribute('coverage')] - self.statement = [parse_statement_node(n, self) for n in - node.getElementsByTagName('statement')] - self.decision = [Decision(n) for n in - node.getElementsByTagName('decision')] - self.messages = [parse_message_node(n) for n in - node.getElementsByTagName('message')] - self.instruction_set = [InstructionSet(n, self.src_lines) for n in - node.getElementsByTagName('instruction_set')] + top_src = [ + n + for n in node.childNodes + if hasattr(n, "tagName") and n.tagName == "src" + ] + assert len(top_src) == 1 + self.src_lines = [ + SrcLine(xml_node=n) + for n in top_src[0].getElementsByTagName("line") + ] + + self.coverage = COVERAGE_STATE[node.getAttribute("coverage")] + self.statement = [ + parse_statement_node(n, self) + for n in node.getElementsByTagName("statement") + ] + self.decision = [ + Decision(n) for n in node.getElementsByTagName("decision") + ] + self.messages = [ + parse_message_node(n) for n in node.getElementsByTagName("message") + ] + self.instruction_set = [ + InstructionSet(n, self.src_lines) + for n in node.getElementsByTagName("instruction_set") + ] # Register messages for m in self.messages: @@ -258,25 +277,34 @@ def get_msg(obj, level): will be printed in the report; otherwise, fall back to a general error message. """ - if hasattr(obj, 'sco_id') and obj.sco_id in self.source.messages: - return "%s: %s" % (obj.__class__.__name__.upper(), - self.source.messages[obj.sco_id].message) + if hasattr(obj, "sco_id") and obj.sco_id in self.source.messages: + return "%s: %s" % ( + obj.__class__.__name__.upper(), + self.source.messages[obj.sco_id].message, + ) else: covstatus = obj.coverage - if obj.__class__.__name__.lower() == 'instructionset': - return "line %s for %s coverage" % (covstatus.upper(), - level.upper()) - elif obj.__class__.__name__.lower() == 'decision' and level == 'mcdc': + if obj.__class__.__name__.lower() == "instructionset": + return "line %s for %s coverage" % ( + covstatus.upper(), + level.upper(), + ) + elif ( + obj.__class__.__name__.lower() == "decision" + and level == "mcdc" + ): for cond in obj.conditions: if not is_covered(cond): return get_msg(cond, level) else: return "%s not covered" % obj.__class__.__name__.lower() - level_to_obj_name = {'stmt': 'statement', - 'mcdc': 'decision', - 'branch': 'instruction_set', - 'insn' : 'instruction_set'} + level_to_obj_name = { + "stmt": "statement", + "mcdc": "decision", + "branch": "instruction_set", + "insn": "instruction_set", + } for level in LEVELS: msg = [] @@ -287,28 +315,30 @@ def get_msg(obj, level): if msg: return msg -class SourceFile(object): +class SourceFile(object): def __init__(self, filename): self.__xml = minidom.parse(filename) # this document should contain only one node - self.__source = self.__xml.getElementsByTagName('source')[0] - self.filename = self.__source.getAttribute('file') - self.coverage_level = self.__source.getAttribute('coverage_level') - self.messages = {} # message id -> Message - self.lines = {} # line number -> Line + self.__source = self.__xml.getElementsByTagName("source")[0] + self.filename = self.__source.getAttribute("file") + self.coverage_level = self.__source.getAttribute("coverage_level") + self.messages = {} # message id -> Message + self.lines = {} # line number -> Line # Parse all src_mapping self.src_mappings = [ - SrcMapping(source=self, xml_node=n) for n in - self.__source.getElementsByTagName('src_mapping')] + SrcMapping(source=self, xml_node=n) + for n in self.__source.getElementsByTagName("src_mapping") + ] def get_lines(self): - return [line for sm in self.src_mappings - for line in sm.src_lines] + return [line for sm in self.src_mappings for line in sm.src_lines] def get_non_exempted_violations(self, levels): - list_ = [sm.get_non_exempted_violations(levels) for sm in self.src_mappings] + list_ = [ + sm.get_non_exempted_violations(levels) for sm in self.src_mappings + ] list_ = [l for l in list_ if l is not None] result = [] for l in list_: @@ -317,44 +347,52 @@ def get_non_exempted_violations(self, levels): def pp_violations(self, levels): violations_list = self.get_non_exempted_violations(levels) - violations_list.sort(key=lambda x: x[1].sco_id if hasattr(x[1], 'sco_id') else 0) - - return "\n".join(["%s:%d:%d: %s" % ( - self.filename, line.num, - line.column_begin, msg) + violations_list.sort( + key=lambda x: x[1].sco_id if hasattr(x[1], "sco_id") else 0 + ) + + return "\n".join( + [ + "%s:%d:%d: %s" + % (self.filename, line.num, line.column_begin, msg) for msg, obj in violations_list - for line in obj.src_lines]) + for line in obj.src_lines + ] + ) class XCovReport(object): - - def __init__(self, report_name='index.iml'): + def __init__(self, report_name="index.iml"): self.__xml = minidom.parse(report_name) self.coverage_level = None self.trace_file = [] self.source_names = [] # Get trace files - for element in self.__xml.getElementsByTagName('coverage_report'): - self.coverage_level = element.getAttribute('coverage_level') - for cov_info in element.getElementsByTagName('coverage_info'): - for include in cov_info.getElementsByTagName('xi:include'): + for element in self.__xml.getElementsByTagName("coverage_report"): + self.coverage_level = element.getAttribute("coverage_level") + for cov_info in element.getElementsByTagName("coverage_info"): + for include in cov_info.getElementsByTagName("xi:include"): # Open included file to get all trace object for trace in minidom.parse( - include.getAttribute( - 'href')).getElementsByTagName('trace'): - self.trace_file.append(Trace( - filename=trace.getAttribute('filename'), - program=trace.getAttribute('program'), - date=trace.getAttribute('date'), - tag=trace.getAttribute('tag'))) + include.getAttribute("href") + ).getElementsByTagName("trace"): + self.trace_file.append( + Trace( + filename=trace.getAttribute("filename"), + program=trace.getAttribute("program"), + date=trace.getAttribute("date"), + tag=trace.getAttribute("tag"), + ) + ) self.source_names = [ - include_file.getAttribute('href') - for sources in self.__xml.getElementsByTagName('sources') - for include_file in sources.getElementsByTagName('xi:include')] + include_file.getAttribute("href") + for sources in self.__xml.getElementsByTagName("sources") + for include_file in sources.getElementsByTagName("xi:include") + ] def get_levels(self): - return [p for p in self.coverage_level.split('+')] + return [p for p in self.coverage_level.split("+")] def visitor(self, func): for src in self.source_names: diff --git a/tools/gnatcov/gnatcov-gdb.py b/tools/gnatcov/gnatcov-gdb.py index 73cafc240..521b3cd6d 100644 --- a/tools/gnatcov/gnatcov-gdb.py +++ b/tools/gnatcov/gnatcov-gdb.py @@ -22,9 +22,14 @@ # Make the gnatcov_gdb package available import os.path import sys -sys.path.append(os.path.join( - os.path.dirname(os.path.realpath(os.path.expanduser(__file__))), - 'scripts')) + +sys.path.append( + os.path.join( + os.path.dirname(os.path.realpath(os.path.expanduser(__file__))), + "scripts", + ) +) import gnatcov_gdb + gnatcov_gdb.setup() diff --git a/tools/gnatcov/misc/design/instrument_mcdc.py b/tools/gnatcov/misc/design/instrument_mcdc.py index e439df594..b2a014f7f 100644 --- a/tools/gnatcov/misc/design/instrument_mcdc.py +++ b/tools/gnatcov/misc/design/instrument_mcdc.py @@ -104,7 +104,7 @@ def __init__(self, lhs, rhs): self.rhs = rhs def __repr__(self): - return '({} and {})'.format(self.lhs, self.rhs) + return "({} and {})".format(self.lhs, self.rhs) @property def operands(self): @@ -119,7 +119,7 @@ def __init__(self, lhs, rhs): self.rhs = rhs def __repr__(self): - return '({} or {})'.format(self.lhs, self.rhs) + return "({} or {})".format(self.lhs, self.rhs) @property def operands(self): @@ -133,7 +133,7 @@ def __init__(self, expr): self.expr = expr def __repr__(self): - return 'not {}'.format(self.expr) + return "not {}".format(self.expr) @property def operands(self): @@ -258,14 +258,16 @@ def compute_edges(expr, for_false, for_true): def write_dot(self, f): """Emit this BDD as a dot diagram to the "f" file.""" - print('False [shape=box];', file=f) - print('True [shape=box];', file=f) + print("False [shape=box];", file=f) + print("True [shape=box];", file=f) for c in self.edges: - print('{} [shape=circle];'.format(c), file=f) + print("{} [shape=circle];".format(c), file=f) for e in self.edges.values(): - print('{e.condition} -> {e.for_false} [label=false];\n' - '{e.condition} -> {e.for_true} [label=true];' - .format(e=e), file=f) + print( + "{e.condition} -> {e.for_false} [label=false];\n" + "{e.condition} -> {e.for_true} [label=true];".format(e=e), + file=f, + ) class IndexedBDD(object): @@ -350,9 +352,11 @@ def compute_edges(node): # Create an IndexedBDD edge for the BDD edge corresponding to # "node". simple_edge = self.bdd.edges[node] - edge = IndexedBDD.EdgePair(simple_edge.condition, - simple_edge.for_false, - simple_edge.for_true) + edge = IndexedBDD.EdgePair( + simple_edge.condition, + simple_edge.for_false, + simple_edge.for_true, + ) # Compute outgoing edges for both destination nodes compute_edges(simple_edge.for_false) @@ -380,14 +384,18 @@ def conditions(self): def write_dot(self, f): """Emit this indexed BDD as a dot diagram to the "f" file.""" + def node_id(offset, node): - return '{}_{}'.format(node, offset) + return "{}_{}".format(node, offset) def output_node(offset, node): - print('{} [shape={}];'.format( - node_id(offset, node), - 'circle' if isinstance(node, Condition) else 'box' - ), file=f) + print( + "{} [shape={}];".format( + node_id(offset, node), + "circle" if isinstance(node, Condition) else "box", + ), + file=f, + ) def process_edges(offset, node): self_id = node_id(offset, node) @@ -405,11 +413,18 @@ def process_edges(offset, node): right_id = node_id(right_offset, edge_pair.for_true) output_node(right_offset, edge_pair.for_true) - print('{} -> {} [label="false+{}"];\n' - '{} -> {} [label="true+{}"];' - .format(self_id, left_id, 0, - self_id, right_id, edge_pair.offset_for_true), - file=f) + print( + '{} -> {} [label="false+{}"];\n' + '{} -> {} [label="true+{}"];'.format( + self_id, + left_id, + 0, + self_id, + right_id, + edge_pair.offset_for_true, + ), + file=f, + ) process_edges(left_offset, edge_pair.for_false) process_edges(right_offset, edge_pair.for_true) @@ -427,38 +442,39 @@ def ada_eval_code(ibdd): variable. """ result = [ - 'function Decision', + "function Decision", ] for i, cond in enumerate(ibdd.conditions): - param = '{}{} : Boolean := False'.format( - (' (' if i == 0 else ' '), - cond + param = "{}{} : Boolean := False".format( + (" (" if i == 0 else " "), cond ) - param += ';' if i < len(ibdd.conditions) - 1 else ') return Boolean' + param += ";" if i < len(ibdd.conditions) - 1 else ") return Boolean" result.append(param) - result.extend([ - 'is', - ' Index : Positive := 1;', - ' Result : Boolean;', - 'begin', - ]) + result.extend( + [ + "is", + " Index : Positive := 1;", + " Result : Boolean;", + "begin", + ] + ) - result_label = 'Return_Result' + result_label = "Return_Result" def cond_label(cond): - return 'Cond_{}'.format(cond) + return "Cond_{}".format(cond) visited = {False, True} def process_single_edge(node, offset): if offset: - result.append(' Index := Index + {};'.format(offset)) + result.append(" Index := Index + {};".format(offset)) if isinstance(node, bool): - result.append(' Result := {};'.format(node)) - result.append(' goto {};'.format(result_label)) + result.append(" Result := {};".format(node)) + result.append(" goto {};".format(result_label)) else: - result.append(' goto {};'.format(cond_label(node))) + result.append(" goto {};".format(cond_label(node))) def process_edges(node): if node in visited: @@ -466,27 +482,29 @@ def process_edges(node): visited.add(node) edge_pair = ibdd.edges[node] - result.append(' <<{}>> if {} then'.format(cond_label(node), node)) + result.append(" <<{}>> if {} then".format(cond_label(node), node)) process_single_edge(edge_pair.for_true, edge_pair.offset_for_true) - result.append(' else') + result.append(" else") process_single_edge(edge_pair.for_false, 0) - result.append(' end if;') + result.append(" end if;") process_edges(edge_pair.for_false) process_edges(edge_pair.for_true) process_edges(ibdd.entry_condition) - result.extend([ - ' <<{}>> Witnessed_Index := Index;'.format(result_label), - ' return Result;', - 'end Decision;' - ]) - return '\n'.join(result) + result.extend( + [ + " <<{}>> Witnessed_Index := Index;".format(result_label), + " return Result;", + "end Decision;", + ] + ) + return "\n".join(result) -def indent(text, prefix=' '): - return '\n'.join(prefix + line for line in text.splitlines()) +def indent(text, prefix=" "): + return "\n".join(prefix + line for line in text.splitlines()) def test(name, expr): @@ -494,38 +512,38 @@ def test(name, expr): ibdd = IndexedBDD(bdd) # Graphical diagram to show the various BDDs forms - dot_file = '{}.dot'.format(name) - png_file = '{}.png'.format(name) + dot_file = "{}.dot".format(name) + png_file = "{}.png".format(name) - with open(dot_file, 'w') as f: - print('digraph InstrumentMCDC {', file=f) + with open(dot_file, "w") as f: + print("digraph InstrumentMCDC {", file=f) print('decision [shape=box,label="{}"];'.format(expr), file=f) - print('subgraph cluster_BDD {', file=f) + print("subgraph cluster_BDD {", file=f) print('label="BDD";', file=f) - print('color=black;', file=f) + print("color=black;", file=f) bdd.write_dot(f) - print('}', file=f) + print("}", file=f) - print('subgraph cluster_IndexedBDD {', file=f) + print("subgraph cluster_IndexedBDD {", file=f) print('label="Indexed BDD";', file=f) - print('color=black;', file=f) + print("color=black;", file=f) ibdd.write_dot(f) - print('}', file=f) + print("}", file=f) - print('}', file=f) - subprocess.check_call(['dot', '-Tpng', '-o', png_file, dot_file]) + print("}", file=f) + subprocess.check_call(["dot", "-Tpng", "-o", png_file, dot_file]) # Small program to test the code that the ada_eval_code function above # emits. - ada_file = '{}.adb'.format(name) + ada_file = "{}.adb".format(name) - with open(ada_file, 'w') as f: - print('procedure {} is'.format(name), file=f) - print(' Witnessed_Index : Positive;', file=f) + with open(ada_file, "w") as f: + print("procedure {} is".format(name), file=f) + print(" Witnessed_Index : Positive;", file=f) print(indent(ada_eval_code(ibdd)), file=f) - print('begin', file=f) + print("begin", file=f) # Enumerate all possible decision evaluations and emit assertions to # check that 1) the decision evaluates the expected boolean result and @@ -551,30 +569,35 @@ def enumerate_tests(node, path): enumerate_tests(ibdd.entry_condition, []) for index, (path, result) in enumerate(tests, 1): - print(' pragma Assert(Decision ({}) = {});'.format( - ', '.join('{} => {}'.format(cond, value) - for cond, value in path), - result - ), file=f) - print(' pragma Assert (Witnessed_Index = {});'.format(index), - file=f) - - print('end {};'.format(name), file=f) - - subprocess.check_call(['gnatmake', '-q', '-g', '-gnata', ada_file]) - subprocess.check_call(['./{}'.format(name)]) - - -if __name__ == '__main__': - A = Condition('A') - B = Condition('B') - C = Condition('C') - D = Condition('D') - E = Condition('E') - F = Condition('F') - G = Condition('G') - - test('test_1', Not(A & B) | C) - test('test_2', (A & Not(B)) | (C & (D | E))) - test('test_3', (A & B & C & D) | (E & (F | G))) - test('test_4', (A & (B | C))) + print( + " pragma Assert(Decision ({}) = {});".format( + ", ".join( + "{} => {}".format(cond, value) for cond, value in path + ), + result, + ), + file=f, + ) + print( + " pragma Assert (Witnessed_Index = {});".format(index), file=f + ) + + print("end {};".format(name), file=f) + + subprocess.check_call(["gnatmake", "-q", "-g", "-gnata", ada_file]) + subprocess.check_call(["./{}".format(name)]) + + +if __name__ == "__main__": + A = Condition("A") + B = Condition("B") + C = Condition("C") + D = Condition("D") + E = Condition("E") + F = Condition("F") + G = Condition("G") + + test("test_1", Not(A & B) | C) + test("test_2", (A & Not(B)) | (C & (D | E))) + test("test_3", (A & B & C & D) | (E & (F | G))) + test("test_4", (A & (B | C))) diff --git a/tools/gnatcov/scripts/bddinfo.py b/tools/gnatcov/scripts/bddinfo.py index 815c39c2a..6062287c2 100644 --- a/tools/gnatcov/scripts/bddinfo.py +++ b/tools/gnatcov/scripts/bddinfo.py @@ -8,44 +8,44 @@ # These pattern expect no error from gnatcov output. They make a lot of # assumptions over its format. COND_LINE = re.compile( - b'^---.*@(?P[0-9a-f]+) .*: notice:' - b' cond branch for SCO #(?P\d+):' - b' CONDITION at (?P.*) \(.*\)' - b'$' + b"^---.*@(?P[0-9a-f]+) .*: notice:" + b" cond branch for SCO #(?P\d+):" + b" CONDITION at (?P.*) \(.*\)" + b"$" ) EDGES_LINE = re.compile( - b'^---.*@(?P[0-9a-f]+) .*: notice:' - b' (?P.*)->BRANCH' - b' = [0-9a-f]+ (?P.*)' - b' /' - b' (?P.*)->FALLTHROUGH' - b' = [0-9a-f]+ (?P.*)' - b'$' + b"^---.*@(?P[0-9a-f]+) .*: notice:" + b" (?P.*)->BRANCH" + b" = [0-9a-f]+ (?P.*)" + b" /" + b" (?P.*)->FALLTHROUGH" + b" = [0-9a-f]+ (?P.*)" + b"$" ) # Destination kinds for edges in a decision. -DestCondition = collections.namedtuple('DestCondition', 'sco_no') -DestOutcome = collections.namedtuple('DestOutcome', 'value') -DestRaiseException = collections.namedtuple('DestRaiseException', '') -DestUnknown = collections.namedtuple('DestUnknown', '') +DestCondition = collections.namedtuple("DestCondition", "sco_no") +DestOutcome = collections.namedtuple("DestOutcome", "value") +DestRaiseException = collections.namedtuple("DestRaiseException", "") +DestUnknown = collections.namedtuple("DestUnknown", "") # Information about an edge that leaves a basic block because of a branch. -EdgeInfo = collections.namedtuple('EdgeInfo', +EdgeInfo = collections.namedtuple( + "EdgeInfo", # What the edge determine about the evaluation of the condition: # Unknown -> None, True or False - 'cond_eval' + "cond_eval" # Destination kind for the edge. - ' dest_kind' + " dest_kind", ) -BranchInfo = collections.namedtuple('BranchInfo', +BranchInfo = collections.namedtuple( + "BranchInfo", # SCO number and sloc for the corresponding condition - 'cond_sco_no' - ' cond_sloc_range' + "cond_sco_no" " cond_sloc_range" # Edge information for the fallthrough/branch destinations. - ' edge_fallthrough' - ' edge_branch' + " edge_fallthrough" " edge_branch", ) @@ -53,32 +53,32 @@ def parse_edge_info(raw_cond_eval, raw_dest_kind): """Parse edge info for given fields. Return an EdgeInfo field.""" cond_eval = { - 'UNKNOWN': None, - 'FALSE': False, - 'TRUE': True, + "UNKNOWN": None, + "FALSE": False, + "TRUE": True, }[raw_cond_eval] - dest_chunks = raw_dest_kind.split(' ') + dest_chunks = raw_dest_kind.split(" ") kind = dest_chunks[0] - if kind == 'CONDITION': + if kind == "CONDITION": # raw_dest_kind is like 'CONDITION (12)': remove parents sco_no = int(dest_chunks[1][1:-1]) dest_kind = DestCondition(sco_no) - elif kind == 'OUTCOME': + elif kind == "OUTCOME": # raw_dest_kind is like 'OUTCOME (TRUE)': remove parents value = { - 'UNKNOWN': None, - 'FALSE': False, - 'TRUE': True, + "UNKNOWN": None, + "FALSE": False, + "TRUE": True, }[dest_chunks[1][1:-1]] dest_kind = DestOutcome(value) - elif kind == 'RAISE_EXCEPTION': + elif kind == "RAISE_EXCEPTION": dest_kind = DestRaiseException() - elif kind == 'UNKNOWN': + elif kind == "UNKNOWN": dest_kind = DestUnknown() else: raise ValueError( - 'Invalid edge destination kind: {}'.format(raw_dest_kind) + "Invalid edge destination kind: {}".format(raw_dest_kind) ) return EdgeInfo(cond_eval, dest_kind) @@ -92,42 +92,42 @@ def get_bdd_info(exe_filename, scos): # Let gnatcov build the BDD for us. proc = subprocess.Popen( [ - 'gnatcov', 'map-routines', '-v', - '--scos={}'.format(scos), exe_filename, - ], stdout=subprocess.PIPE, + "gnatcov", + "map-routines", + "-v", + "--scos={}".format(scos), + exe_filename, + ], + stdout=subprocess.PIPE, ) outs, errs = proc.communicate() if proc.returncode != 0: - raise RuntimeError('gnatcov map-routines returned an error') + raise RuntimeError("gnatcov map-routines returned an error") # Parse its output and collect information. cond_sco_nos = {} edge_infos = {} - for line in outs.split(b'\n'): - + for line in outs.split(b"\n"): m = COND_LINE.match(line) if m: - pc = int(m.group('insn_pc'), 16) - cond_sco_nos[pc] = ( - int(m.group('sco_no')), - m.group('sloc_range') - ) + pc = int(m.group("insn_pc"), 16) + cond_sco_nos[pc] = (int(m.group("sco_no")), m.group("sloc_range")) continue m = EDGES_LINE.match(line) if m: - pc = int(m.group('insn_pc'), 16) + pc = int(m.group("insn_pc"), 16) edge_infos[pc] = ( # Fallthrough edge parse_edge_info( - m.group('fallthrough_cond_eval'), - m.group('fallthrough_dest_kind') + m.group("fallthrough_cond_eval"), + m.group("fallthrough_dest_kind"), ), # Branch edge parse_edge_info( - m.group('branch_cond_eval'), - m.group('branch_dest_kind'), - ) + m.group("branch_cond_eval"), + m.group("branch_dest_kind"), + ), ) continue @@ -144,11 +144,15 @@ def get_edge_info(pc): for pc, (cond_sco_no, cond_sloc_range) in cond_sco_nos.items() } -if __name__ == '__main__': + +if __name__ == "__main__": import sys + for pc, br_info in get_bdd_info(sys.argv[1], sys.argv[2]).items(): - print('{:x}: SCO #{} {}'.format( - pc, br_info.cond_sco_no, br_info.cond_sloc_range - )) - print(' fallthrough: {}'.format(br_info.edge_fallthrough)) - print(' branch : {}'.format(br_info.edge_branch)) + print( + "{:x}: SCO #{} {}".format( + pc, br_info.cond_sco_no, br_info.cond_sloc_range + ) + ) + print(" fallthrough: {}".format(br_info.edge_fallthrough)) + print(" branch : {}".format(br_info.edge_branch)) diff --git a/tools/gnatcov/scripts/decision_cfg.py b/tools/gnatcov/scripts/decision_cfg.py index ee7526592..47c19f449 100755 --- a/tools/gnatcov/scripts/decision_cfg.py +++ b/tools/gnatcov/scripts/decision_cfg.py @@ -16,81 +16,76 @@ JUMP, FALLTHROUGH, BRANCH = range(3) -STYLE_NONE = 'solid' -STYLE_BRANCH_FALLTHROUGH = 'dashed' -STYLE_BRANCH_TAKEN = 'dotted' -COLOR_COVERED = '"#008000"' -COLOR_NOT_COVERED = '"#a00000"' -COLOR_UNCOVERABLE = '"#c0c0c0"' -COLOR_WARNING = '"#ff8000"' -COLOR_NONE = '"#000000"' +STYLE_NONE = "solid" +STYLE_BRANCH_FALLTHROUGH = "dashed" +STYLE_BRANCH_TAKEN = "dotted" +COLOR_COVERED = '"#008000"' +COLOR_NOT_COVERED = '"#a00000"' +COLOR_UNCOVERABLE = '"#c0c0c0"' +COLOR_WARNING = '"#ff8000"' +COLOR_NONE = '"#000000"' STYLES = { - JUMP: STYLE_NONE, + JUMP: STYLE_NONE, FALLTHROUGH: STYLE_BRANCH_FALLTHROUGH, - BRANCH: STYLE_BRANCH_TAKEN, + BRANCH: STYLE_BRANCH_TAKEN, } -SLOC_RANGE = re.compile( - '^([^:]*):(\d+):(\d+)-(\d+):(\d+)$' +SLOC_RANGE = re.compile("^([^:]*):(\d+):(\d+)-(\d+):(\d+)$") +SlocRange = collections.namedtuple( + "SlocRange", "filename" " start_line start_column" " end_line end_column" ) -SlocRange = collections.namedtuple('SlocRange', - 'filename' - ' start_line start_column' - ' end_line end_column' -) -AddressRange = collections.namedtuple('AddressRange', 'low high') -AroundAddress = collections.namedtuple('AroundAddress', 'pc') -Program = collections.namedtuple('Program', 'filename arch') +AddressRange = collections.namedtuple("AddressRange", "low high") +AroundAddress = collections.namedtuple("AroundAddress", "pc") +Program = collections.namedtuple("Program", "filename arch") # A program is the `filename` ELF file, and when disassembled, it can contain # the inconditional `jumps` instructions and the `branches` instructions. # Decoder for the e_machine ELF header field. Depend on the EI_DATA header # field. ARCH_STRUCT = { - 1: struct.Struct('H'), + 1: struct.Struct("H"), } OBJDUMP_INSN = re.compile( - '^[ ]*(?P[0-9a-f]+):' - '\t[0-9a-f ]+\t' - '(?P[^ ]+)' - '[ ]?(?:[ ]+(?P.+))?\n$' + "^[ ]*(?P[0-9a-f]+):" + "\t[0-9a-f ]+\t" + "(?P[^ ]+)" + "[ ]?(?:[ ]+(?P.+))?\n$" ) -OBJDUMP_DEST = re.compile('^(?P[0-9a-f]+) <(?P[^>]+)>$') +OBJDUMP_DEST = re.compile("^(?P[0-9a-f]+) <(?P[^>]+)>$") + def does_raise_exception(symbol): """Return if `symbol` is used to raise an exception.""" if symbol is None: return False - return ( - symbol in ('__gnat_last_chance_handler', '__gnat_raise_exception') - or symbol.startswith('__gnat_rcheck_') - ) + return symbol in ( + "__gnat_last_chance_handler", + "__gnat_raise_exception", + ) or symbol.startswith("__gnat_rcheck_") + class Toolchain(object): """Manage access to toolchain programs.""" def __init__(self, prefix=None): self.prefix = prefix - self.objdump = self.get('objdump') + self.objdump = self.get("objdump") def get(self, program): """Return the program name including the toolchain prefix.""" - return ( - '{}-{}'.format(self.prefix, program) - if self.prefix else - program - ) + return "{}-{}".format(self.prefix, program) if self.prefix else program + class Arch(object): - CALL = 'call' - RET = 'ret' - COND_RET = 'cond-ret' - JUMP = 'jump' - BRANCH = 'branch' + CALL = "call" + RET = "ret" + COND_RET = "cond-ret" + JUMP = "jump" + BRANCH = "branch" @staticmethod def get_insn_properties(insn): @@ -108,27 +103,25 @@ def get_insn_properties(insn): """ raise NotImplementedError() + class ArchX86(Arch): - CALLS = set('call callq'.split()) - RETS = set('ret retl retq'.split()) - JUMPS = set('jmp jmpl jmpq'.split()) + CALLS = set("call callq".split()) + RETS = set("ret retl retq".split()) + JUMPS = set("jmp jmpl jmpq".split()) BRANCHES = set( - 'ja jae jb jbe jc jcxz jecxz je jg jge jl jle jna jnae jnb jnbe jnc' - ' jne jng jnge jnl jnle jno jnp jns jnz jo jp jpe jpo js jz'.split() + "ja jae jb jbe jc jcxz jecxz je jg jge jl jle jna jnae jnb jnbe jnc" + " jne jng jnge jnl jnle jno jnp jns jnz jo jp jpe jpo js jz".split() ) @staticmethod def get_insn_dest(insn): - if insn.operands.startswith('*'): + if insn.operands.startswith("*"): # TODO: handle rip-relative jumps return (None, None) else: m = OBJDUMP_DEST.match(insn.operands) if m: - return ( - int(m.group('pc'), 16), - m.group('symbol') - ) + return (int(m.group("pc"), 16), m.group("symbol")) else: return (None, None) @@ -137,146 +130,145 @@ def get_insn_properties(insn): if insn.mnemonic in ArchX86.RETS: return (Arch.RET, None, None) elif insn.mnemonic in ArchX86.JUMPS: - return (Arch.JUMP, ) + ArchX86.get_insn_dest(insn) + return (Arch.JUMP,) + ArchX86.get_insn_dest(insn) elif insn.mnemonic in ArchX86.BRANCHES: - return (Arch.BRANCH, ) + ArchX86.get_insn_dest(insn) + return (Arch.BRANCH,) + ArchX86.get_insn_dest(insn) elif insn.mnemonic in ArchX86.CALLS: _, symbol = ArchX86.get_insn_dest(insn) return (Arch.CALL, None, symbol) else: return (None, None, None) + class ArchPPC32(Arch): @staticmethod def get_insn_dest(operand): m = OBJDUMP_DEST.match(operand) if m: - return ( - int(m.group('pc'), 16), - m.group('symbol') - ) + return (int(m.group("pc"), 16), m.group("symbol")) else: return (None, None) @staticmethod def get_insn_properties(insn): - if not insn.mnemonic.startswith('b'): + if not insn.mnemonic.startswith("b"): return (None, None, None) # Strip prediction any hint. - mnemonic = insn.mnemonic.rstrip('+-') + mnemonic = insn.mnemonic.rstrip("+-") # Branch can go to an absolute address, to the link register or to the # control register. dest_in_reg = False return_from_subroutine = False - if mnemonic.endswith('l') or mnemonic.endswith('la'): + if mnemonic.endswith("l") or mnemonic.endswith("la"): # Branch and Link (call) - if 'ctr' in mnemonic: + if "ctr" in mnemonic: # To ConTrol Register (destination known at runtime) symbol = None - elif mnemonic.startswith('blr'): + elif mnemonic.startswith("blr"): # To Link Register (anyway this is a call, *not* a return) symbol = None else: - _, symbol = ArchPPC32.get_insn_dest(insn.operands.split(',')[0]) + _, symbol = ArchPPC32.get_insn_dest( + insn.operands.split(",")[0] + ) return (Arch.CALL, None, symbol) - elif mnemonic.endswith('lr'): + elif mnemonic.endswith("lr"): # To Link Register (return) - if mnemonic != 'blr': + if mnemonic != "blr": return (Arch.COND_RET, None, None) else: return (Arch.RET, None, None) - elif mnemonic.endswith('ctr'): + elif mnemonic.endswith("ctr"): # To ConTrol Register (destination known at runtime) return (Arch.BRANCH, None, None) - elif mnemonic.endswith('a'): + elif mnemonic.endswith("a"): mnemonic = mnemonic[:-1] - operands = insn.operands.split(',') - if ' ' in operands[0]: + operands = insn.operands.split(",") + if " " in operands[0]: pc, symbol = ArchPPC32.get_insn_dest(operands[0]) else: pc, symbol = ArchPPC32.get_insn_dest(operands[1]) - return ( - Arch.BRANCH if mnemonic != 'b' else Arch.JUMP, - pc, symbol - ) + return (Arch.BRANCH if mnemonic != "b" else Arch.JUMP, pc, symbol) + class ArchSPARC32(Arch): @staticmethod def get_insn_dest(operand): m = OBJDUMP_DEST.match(operand) if m: - return ( - int(m.group('pc'), 16), - m.group('symbol') - ) + return (int(m.group("pc"), 16), m.group("symbol")) else: return (None, None) @staticmethod def get_insn_properties(insn): - if insn.mnemonic.startswith('b') and insn.mnemonic != 'b': + if insn.mnemonic.startswith("b") and insn.mnemonic != "b": addr, symbol = ArchSPARC32.get_insn_dest( - insn.operands.split(',')[0] + insn.operands.split(",")[0] ) return (Arch.BRANCH, addr, symbol) - elif insn.mnemonic in ('jmp', 'b'): + elif insn.mnemonic in ("jmp", "b"): addr, symbol = ArchSPARC32.get_insn_dest( - insn.operands.split(',')[0] + insn.operands.split(",")[0] ) return (Arch.JUMP, addr, symbol) - elif insn.mnemonic == 'call': + elif insn.mnemonic == "call": addr, symbol = ArchSPARC32.get_insn_dest( - insn.operands.split(',')[0] + insn.operands.split(",")[0] ) return (Arch.CALL, addr, symbol) - elif insn.mnemonic == 'ret': + elif insn.mnemonic == "ret": return (Arch.RET, None, None) else: return (None, None, None) + ARCHITECTURES = { # SPARC 32bit - 2: ArchSPARC32, + 2: ArchSPARC32, # x86 - 3: ArchX86, + 3: ArchX86, # PowerPC 32bit 20: ArchPPC32, # x86_64 62: ArchX86, } + def which(program): """Return whether `program` is in the PATH.""" - with open(os.devnull, 'rb+') as devnull: + with open(os.devnull, "rb+") as devnull: proc = subprocess.Popen( - ['which', program], stdin=devnull, stdout=devnull + ["which", program], stdin=devnull, stdout=devnull ) proc.wait() return proc.returncode == 0 + def parse_target(string): """Check `string` is a valid toolchain prefix and return toolchain.""" toolchain = Toolchain(string) if not which(toolchain.objdump): raise argparse.ArgumentTypeError( - 'No {} found'.format(toolchain.objdump) + "No {} found".format(toolchain.objdump) ) return toolchain + def parse_program(string): """Check that `string` is a valid ELF and get the architecture from it. Return (string, architecture). """ - with argparse.FileType('rb')(string) as f: + with argparse.FileType("rb")(string) as f: # Read the ELF header just to get the machine type. elf_ident = f.read(16) - if elf_ident[:4] != b'\x7fELF': - raise argparse.ArgumentTypeError('{}: not an ELF'.format(string)) + if elf_ident[:4] != b"\x7fELF": + raise argparse.ArgumentTypeError("{}: not an ELF".format(string)) ei_data = ord(elf_ident[5:6]) arch_struct = ARCH_STRUCT[ei_data] @@ -284,80 +276,85 @@ def parse_program(string): _ = f.read(2) # Here is the e_machine field! - elf_machine, = arch_struct.unpack(f.read(2)) + (elf_machine,) = arch_struct.unpack(f.read(2)) try: arch = ARCHITECTURES[elf_machine] except: raise argparse.ArgumentTypeError( - '{}: unhandled architecture ({})'.format( - string, elf_machine - ) + "{}: unhandled architecture ({})".format(string, elf_machine) ) else: return Program(string, arch) + def parse_sloc_range(string): m = SLOC_RANGE.match(string) if not m: raise argparse.ArgumentTypeError( - 'Invalid sloc range: {}'.format(string) + "Invalid sloc range: {}".format(string) ) filename, start_line, start_column, end_line, end_column = m.groups() return SlocRange( - filename.encode('ascii'), - int(start_line), int(start_column), - int(end_line), int(end_column), + filename.encode("ascii"), + int(start_line), + int(start_column), + int(end_line), + int(end_column), ) + def parse_address_range(string): - chunks = string.split('..') + chunks = string.split("..") if len(chunks) != 2: raise argparse.ArgumentTypeError( - 'Invalid address range: {}'.format(string) + "Invalid address range: {}".format(string) ) low, high = chunks try: low = int(low, 16) except ValueError: raise argparse.ArgumentTypeError( - 'Invalid hexadecimal low address: {}'.format(low) + "Invalid hexadecimal low address: {}".format(low) ) try: high = int(high, 16) except ValueError: raise argparse.ArgumentTypeError( - 'Invalid hexadecimal high address: {}'.format(low) + "Invalid hexadecimal high address: {}".format(low) ) return AddressRange(low, high) + def parse_around_address(string): pc_string = string[1:] try: pc = int(pc_string, 16) except ValueError: raise argparse.ArgumentTypeError( - 'Invalid hexadecimal address: {}'.format(pc_string) + "Invalid hexadecimal address: {}".format(pc_string) ) else: return AroundAddress(pc) + def parse_location(string): - if ':' in string: + if ":" in string: return parse_sloc_range(string) - elif string.startswith('@'): + elif string.startswith("@"): return parse_around_address(string) - elif '..' in string: + elif ".." in string: return parse_address_range(string) else: return syminfo.Symbol(None, None, string) + def slocs_match_range(slocs, sloc_range): """Return if any of the `slocs` match `sloc_range`.""" for sloc in slocs: if ( - sloc_range.filename not in sloc.filename or - sloc.line < sloc_range.start_line or - sloc.line > sloc_range.end_line + sloc_range.filename not in sloc.filename + or sloc.line < sloc_range.start_line + or sloc.line > sloc_range.end_line ): continue elif sloc.line == sloc_range.start_line: @@ -373,14 +370,16 @@ def slocs_match_range(slocs, sloc_range): # decision. return False + class Locations(object): """Gather information about code matching criterias.""" def __init__( - self, symbols, + self, + symbols, matched_symbols, matched_addr_ranges, - matched_sloc_ranges + matched_sloc_ranges, ): self.symbols = symbols self.matched_symbols = set(matched_symbols) @@ -413,6 +412,7 @@ def match(self, slocs, address): class Insn: """A single instruction. It knows if it ends a basic block and which are its execution successors.""" + def __init__(self, pc, mnemonic, operands, slocs=None): self.pc = pc self.next_pc = None @@ -434,12 +434,10 @@ def end_basic_block(self): self.ends_basic_block = True def __repr__(self): - return 'Insn({:x} {} {})'.format( - self.pc, self.mnemonic, self.operands - ) + return "Insn({:x} {} {})".format(self.pc, self.mnemonic, self.operands) -class EdgesSet: +class EdgesSet: def __init__(self): # Mapping: source PC -> set of destinations PC self.edges = {} @@ -464,11 +462,10 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): get_insn_properties = program.arch.get_insn_properties # Let objdump disassemble the program for us... - args = [toolchain.objdump, '-d', program.filename] - print('Disassembling: {}'.format(args)) + args = [toolchain.objdump, "-d", program.filename] + print("Disassembling: {}".format(args)) proc = subprocess.Popen( - args, - stdin=open(os.devnull, 'rb'), stdout=subprocess.PIPE + args, stdin=open(os.devnull, "rb"), stdout=subprocess.PIPE ) # ... and filter instructions in the given sloc range. @@ -490,7 +487,7 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): while True: # Read as many lines as possible from objdump - line = proc.stdout.readline().decode('ascii') + line = proc.stdout.readline().decode("ascii") if not line: break @@ -499,10 +496,9 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): if not m: continue - pc = int(m.group('pc'), 16) + pc = int(m.group("pc"), 16) insn = Insn( - pc, m.group('mnemonic'), m.group('operands'), - sloc_info.get(pc, []) + pc, m.group("mnemonic"), m.group("operands"), sloc_info.get(pc, []) ) if last_instruction: last_instruction.next_pc = pc @@ -523,9 +519,8 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): # Out of the decision: end the previous basic block if needed. instructions[-1].end_basic_block() - if ( - last_instruction_raises_exception and - (sloc_in_decision or last_instruction_in_decision) + if last_instruction_raises_exception and ( + sloc_in_decision or last_instruction_in_decision ): uncoverable_edges.add((last_instruction.pc, pc)) @@ -551,8 +546,9 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): insn.end_basic_block() # Update "last_*" information for the next iteration. - last_instruction_can_fallthrough = ( - insn_type not in (Arch.RET, Arch.JUMP) + last_instruction_can_fallthrough = insn_type not in ( + Arch.RET, + Arch.JUMP, ) last_instruction_raises_exception = raises_exception last_instruction_in_decision = sloc_in_decision @@ -561,8 +557,7 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): # Break basic blocks for instructions that must start one. for insn in instructions: if any( - successor in basic_block_starters - for successor in insn.successors + successor in basic_block_starters for successor in insn.successors ): insn.end_basic_block() @@ -584,60 +579,77 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): return cfg, uncoverable_edges, outside_instructions -if __name__ == '__main__': +if __name__ == "__main__": import sys parser = argparse.ArgumentParser( - description='Build the CFG for some decision in a program' + description="Build the CFG for some decision in a program" ) parser.add_argument( - '-o', '--output', type=argparse.FileType('w'), default=sys.stdout, - dest='output', - help='File to output the dot graph to (default: stdout)' + "-o", + "--output", + type=argparse.FileType("w"), + default=sys.stdout, + dest="output", + help="File to output the dot graph to (default: stdout)", ) parser.add_argument( - '--target', dest='toolchain', type=parse_target, default=None, + "--target", + dest="toolchain", + type=parse_target, + default=None, help=( - 'Prefix used to reach the toolchain' - ' (example: powerpc-elf for powerpc-elf-objdump)' - ) + "Prefix used to reach the toolchain" + " (example: powerpc-elf for powerpc-elf-objdump)" + ), ) parser.add_argument( - '-T', '--format', default=None, - help='If given, call dot to produce the actual output passing it' - ' this argument' + "-T", + "--format", + default=None, + help="If given, call dot to produce the actual output passing it" + " this argument", ) parser.add_argument( - '-b', '--basename', action='store_true', - help='Only print basename in source locations' + "-b", + "--basename", + action="store_true", + help="Only print basename in source locations", ) parser.add_argument( - '-B', '--bdd', dest='scos', - help='Use SCOS to display the binary decision diagram (BDD)' + "-B", + "--bdd", + dest="scos", + help="Use SCOS to display the binary decision diagram (BDD)", ) parser.add_argument( - '-k', '--keep-uncoverable-edges', dest='keep_uncoverable_edges', - action='store_true', - help='Do not strip edges that are supposed to be uncoverable due to' - ' exceptions' + "-k", + "--keep-uncoverable-edges", + dest="keep_uncoverable_edges", + action="store_true", + help="Do not strip edges that are supposed to be uncoverable due to" + " exceptions", ) parser.add_argument( - '-t', '--traces', dest='traces', - help='Use a set of traces to hilight executed instructions' + "-t", + "--traces", + dest="traces", + help="Use a set of traces to hilight executed instructions", ) parser.add_argument( - 'program', type=parse_program, - help='The program to analyse' + "program", type=parse_program, help="The program to analyse" ) parser.add_argument( - 'location', type=parse_location, nargs='+', + "location", + type=parse_location, + nargs="+", help=( - 'Location of the decision to analyse.' - ' Can be a sloc range (example: 10:5-11:21),' - ' a symbol name (example: ada__text_io__put_line__2),' - ' an address range (example: 0x200..0x300)' - ' or the symbol around some address (example: @0x0808f31a)' - ) + "Location of the decision to analyse." + " Can be a sloc range (example: 10:5-11:21)," + " a symbol name (example: ada__text_io__put_line__2)," + " an address range (example: 0x200..0x300)" + " or the symbol around some address (example: @0x0808f31a)" + ), ) args = parser.parse_args() @@ -649,10 +661,11 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): # If asked to, start dot to format the output. if args.format: - with open(os.devnull, 'wb') as devnull: + with open(os.devnull, "wb") as devnull: dot_process = subprocess.Popen( - ['dot', '-T{}'.format(args.format), '-o', args.output.name], - stdin=subprocess.PIPE, stdout=devnull + ["dot", "-T{}".format(args.format), "-o", args.output.name], + stdin=subprocess.PIPE, + stdout=devnull, ) args.output.close() f = dot_process.stdin @@ -662,9 +675,9 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): sym_info, overlap_syms = syminfo.get_sym_info(args.program.filename) if overlap_syms: - sys.stderr.write('warning: some symbols overlap with others:\n') + sys.stderr.write("warning: some symbols overlap with others:\n") for sym in overlap_syms: - sys.stderr.write(' - {}\n'.format(syminfo.format_symbol(sym))) + sys.stderr.write(" - {}\n".format(syminfo.format_symbol(sym))) # Build accepted locations accepted_symbols = [] @@ -681,7 +694,7 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): try: symbol = sym_info[loc.pc] except KeyError: - sys.stderr.write('No symbol around: {:#08x}\n'.format(loc.pc)) + sys.stderr.write("No symbol around: {:#08x}\n".format(loc.pc)) sys.exit(1) accepted_symbols.append(symbol.name) else: @@ -690,16 +703,12 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): assert False locations = Locations( - sym_info, - accepted_symbols, - accepted_addr_ranges, - accepted_slocs + sym_info, accepted_symbols, accepted_addr_ranges, accepted_slocs ) sloc_info = slocinfo.get_sloc_info(args.program.filename) decision_cfg, uncoverable_edges, outside_insns = get_decision_cfg( - args.program, args.toolchain, - sloc_info, locations + args.program, args.toolchain, sloc_info, locations ) # Load the BDD if asked to. Reminder: this is a map: @@ -707,15 +716,15 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): # edges info). bdd_info = ( bddinfo.get_bdd_info(args.program.filename, args.scos) - if args.scos is not None else - {} + if args.scos is not None + else {} ) # Load traces if asked to. executed_insns, leave_flags = ( traceinfo.get_trace_info(args.traces) - if args.traces is not None else - (None, None) + if args.traces is not None + else (None, None) ) trace_info = executed_insns is not None @@ -764,9 +773,9 @@ def check_edge(edge_info, dest_pc): def pc_to_name(pc, unknown=False): if unknown: - return 'bb_{:x}_unknown_dest'.format(pc) + return "bb_{:x}_unknown_dest".format(pc) else: - return 'bb_{:x}'.format(pc) + return "bb_{:x}".format(pc) def get_bb_condition(basic_block): """Return the condition the basic block belongs to or None if there is @@ -802,24 +811,26 @@ def helper(basic_block): def format_edge_info(edge_info, condition): if edge_info is None: - return ['???'] + return ["???"] result = [] if edge_info.cond_eval is not None: - result.append('Cond #{} is {}'.format( - condition, edge_info.cond_eval - )) + result.append( + "Cond #{} is {}".format(condition, edge_info.cond_eval) + ) dest_kind = edge_info.dest_kind if isinstance(dest_kind, bddinfo.DestOutcome): - result.append('Outcome {}'.format( - '???' if dest_kind.value is None else dest_kind.value - )) + result.append( + "Outcome {}".format( + "???" if dest_kind.value is None else dest_kind.value + ) + ) elif isinstance(dest_kind, bddinfo.DestRaiseException): - result.append('EXCEPTION') + result.append("EXCEPTION") elif isinstance(dest_kind, bddinfo.DestUnknown): - result.append('???') + result.append("???") return result or None @@ -833,65 +844,65 @@ def format_edge_color(branch_insn, kind, uncoverable): except KeyError: covered = False else: - covered = ( - (kind == FALLTHROUGH and flags.fallthrough) - or (kind == BRANCH and flags.branch) + covered = (kind == FALLTHROUGH and flags.fallthrough) or ( + kind == BRANCH and flags.branch ) else: covered = False return ( (COLOR_WARNING if uncoverable else COLOR_COVERED) - if covered else - (COLOR_UNCOVERABLE if uncoverable else COLOR_NOT_COVERED) + if covered + else (COLOR_UNCOVERABLE if uncoverable else COLOR_NOT_COVERED) ) def format_text_label(lines): - label = ''.join('{}\n'.format(line) for line in lines) - label = label.replace('\\', '\\\\').replace('"', '\\"') - label = label.replace('\n', '\\l') + label = "".join("{}\n".format(line) for line in lines) + label = label.replace("\\", "\\\\").replace('"', '\\"') + label = label.replace("\n", "\\l") return '"{}"'.format(label) def html_escape(line): - for char, escape in ( - ('&', 'amp'), - ('<', 'lt'), ('>', 'gt') - ): - line = line.replace(char, '&{};'.format(escape)) + for char, escape in (("&", "amp"), ("<", "lt"), (">", "gt")): + line = line.replace(char, "&{};".format(escape)) return line def html_color(line, color=None): if color: - return '{}'.format( - color, html_escape(line) - ) + return "{}".format(color, html_escape(line)) else: return html_escape(line) def format_html_label(lines): - label = ''.join('{}
'.format(line) for line in lines) - return '<{}>'.format(label) + label = "".join('{}
'.format(line) for line in lines) + return "<{}>".format(label) def add_edge(from_, to, label, color=COLOR_NONE, style=STYLE_NONE): # Handle nicely unknown branch destinations. if to is None: to_name = pc_to_name(from_, unknown=True) add_node( - pc, None, - format_text_label(['???']), - shape='ellipse', unknown=True + pc, + None, + format_text_label(["???"]), + shape="ellipse", + unknown=True, ) else: to_name = pc_to_name(to) destinations.add(to) - edges.append(' {} -> {} [{}color={},style={},penwidth=3];'.format( - pc_to_name(from_), to_name, - 'label={}, '.format(format_text_label(label)) if label else '', - color, style - )) + edges.append( + " {} -> {} [{}color={},style={},penwidth=3];".format( + pc_to_name(from_), + to_name, + "label={}, ".format(format_text_label(label)) if label else "", + color, + style, + ) + ) - def add_node(pc, condition, label, shape='box', unknown=False): + def add_node(pc, condition, label, shape="box", unknown=False): by_condition[condition].append( - ' {} [shape={}, fontname=monospace, label={}];\n'.format( + " {} [shape={}, fontname=monospace, label={}];\n".format( pc_to_name(pc, unknown), shape, label ) ) @@ -902,9 +913,11 @@ def process_edge(kind, to_pc, label): uncoverable = (insn.pc, to_pc) in uncoverable_edges if args.keep_uncoverable_edges or not uncoverable: add_edge( - from_pc, to_pc, label, + from_pc, + to_pc, + label, format_edge_color(insn, kind, uncoverable), - STYLES[kind] + STYLES[kind], ) successors = insn.successors @@ -929,15 +942,21 @@ def process_edge(kind, to_pc, label): if trace_info: color = ( COLOR_COVERED - if insn.pc in executed_insns else - COLOR_NOT_COVERED + if insn.pc in executed_insns + else COLOR_NOT_COVERED ) else: color = None - label.append(html_color(' {:x} {:<8}{}'.format( - insn.pc, insn.mnemonic, - ' {}'.format(insn.operands) if insn.operands else '' - ), color)) + label.append( + html_color( + " {:x} {:<8}{}".format( + insn.pc, + insn.mnemonic, + " {}".format(insn.operands) if insn.operands else "", + ), + color, + ) + ) # Add the box to the correct condition cluster subgraph. condition, branch_info = get_bb_condition(basic_block) @@ -948,51 +967,48 @@ def process_edge(kind, to_pc, label): label_fallthrough = format_edge_info( branch_info.edge_fallthrough, condition ) - label_branch = format_edge_info( - branch_info.edge_branch, condition - ) + label_branch = format_edge_info(branch_info.edge_branch, condition) add_node(pc, condition, format_html_label(label)) # Then add outgoing edges for it. process_successor_edges( - pc, basic_block[-1], - (label_fallthrough, label_branch) + pc, basic_block[-1], (label_fallthrough, label_branch) ) for insn in outside_insns.values(): label = [] for sloc in insn.slocs: label.append(slocinfo.format_sloc(sloc, args.basename)) - label.append(' {:#0x}'.format(insn.pc)) - add_node(insn.pc, None, format_text_label(label), shape='ellipse') + label.append(" {:#0x}".format(insn.pc)) + add_node(insn.pc, None, format_text_label(label), shape="ellipse") process_successor_edges(insn.pc, insn, (None, None)) - for out_dest in (destinations - nodes): + for out_dest in destinations - nodes: label = [] for sloc in sloc_info.get(out_dest, []): label.append(slocinfo.format_sloc(sloc, args.basename)) - label.append(' {:#0x}'.format(out_dest)) - add_node(out_dest, None, format_text_label(label), 'ellipse') + label.append(" {:#0x}".format(out_dest)) + add_node(out_dest, None, format_text_label(label), "ellipse") - f.write('digraph cfg {\n') - f.write(' graph [splines=ortho]\n') + f.write("digraph cfg {\n") + f.write(" graph [splines=ortho]\n") for sco_no, nodes in by_condition.items(): if sco_no is not None: - f.write('subgraph cluster_condition_{} {{\n'.format(sco_no)) + f.write("subgraph cluster_condition_{} {{\n".format(sco_no)) # TODO: add a label for the subgraph... for node in nodes: f.write(node) - f.write('\n') + f.write("\n") if sco_no is not None: - f.write('}\n') + f.write("}\n") for edge in edges: f.write(edge) - f.write('\n') + f.write("\n") - f.write('}\n') + f.write("}\n") f.close() diff --git a/tools/gnatcov/scripts/dwarfdump.py b/tools/gnatcov/scripts/dwarfdump.py index 6780b583c..35cf283df 100755 --- a/tools/gnatcov/scripts/dwarfdump.py +++ b/tools/gnatcov/scripts/dwarfdump.py @@ -10,40 +10,37 @@ import slocinfo -OBJDUMP_ADDR = re.compile('^ *([0-9a-f]+):') +OBJDUMP_ADDR = re.compile("^ *([0-9a-f]+):") def do_dump(sloc_info, cmd): # Start the subprocess to disassemble (most likely objdump -d) - print('Executing: {}'.format(cmd)) - print('') + print("Executing: {}".format(cmd)) + print("") proc = subprocess.Popen(cmd, stdout=subprocess.PIPE) outs, _ = proc.communicate() outs = outs.decode() last_slocs = [] - for line in outs.split('\n'): + for line in outs.split("\n"): m = OBJDUMP_ADDR.match(line) if m: addr = int(m.group(1), 16) slocs = sloc_info.get(addr, []) if slocs != last_slocs: - print('') + print("") for sloc in slocs: - print('>>> {}'.format(slocinfo.format_sloc(sloc))) + print(">>> {}".format(slocinfo.format_sloc(sloc))) last_slocs = slocs sys.stdout.flush() print(line) -if __name__ == '__main__': +if __name__ == "__main__": import errno try: - do_dump( - slocinfo.get_sloc_info(sys.argv[-1]), - sys.argv[1:] - ) + do_dump(slocinfo.get_sloc_info(sys.argv[-1]), sys.argv[1:]) except IOError as e: if e.errno != errno.EPIPE: raise diff --git a/tools/gnatcov/scripts/gnatcov_gdb/__init__.py b/tools/gnatcov/scripts/gnatcov_gdb/__init__.py index 238d523e1..9e7df5b41 100644 --- a/tools/gnatcov/scripts/gnatcov_gdb/__init__.py +++ b/tools/gnatcov/scripts/gnatcov_gdb/__init__.py @@ -12,6 +12,7 @@ _setup_done = False + def setup(): global _setup_done if not _setup_done: diff --git a/tools/gnatcov/scripts/gnatcov_gdb/printers.py b/tools/gnatcov/scripts/gnatcov_gdb/printers.py index fbfa8ddfb..868561685 100644 --- a/tools/gnatcov/scripts/gnatcov_gdb/printers.py +++ b/tools/gnatcov/scripts/gnatcov_gdb/printers.py @@ -24,7 +24,7 @@ class SubPrettyPrinter(gdb.printing.SubPrettyPrinter): @classmethod def type_name(cls): - return cls.name.replace('.', '__').lower() + return cls.name.replace(".", "__").lower() @classmethod def matches(cls, value): @@ -39,7 +39,7 @@ class PCTypePrinter(SubPrettyPrinter): Pretty-printer for Traces.Pc_Type. """ - name = 'Traces.Pc_Type' + name = "Traces.Pc_Type" def to_string(self): return hex(int(self.value)) @@ -50,7 +50,7 @@ class ArchAddrPrinter(SubPrettyPrinter): Pretty-printer for Arch.Arch_Addr. """ - name = 'Arch.Arch_Addr' + name = "Arch.Arch_Addr" def to_string(self): return hex(int(self.value)) @@ -61,10 +61,10 @@ class LocalSlocPrinter(SubPrettyPrinter): Pretty-printer for Slocs.Local_Source_Location. """ - name = 'Slocs.Local_Source_Location' + name = "Slocs.Local_Source_Location" def to_string(self): - return '{}:{}'.format(self.value['line'], self.value['column']) + return "{}:{}".format(self.value["line"], self.value["column"]) class SlocPrinter(SubPrettyPrinter): @@ -72,11 +72,12 @@ class SlocPrinter(SubPrettyPrinter): Pretty-printer for Slocs.Source_Location. """ - name = 'Slocs.Source_Location' + name = "Slocs.Source_Location" def to_string(self): - return '[file {}] {}'.format(self.value['source_file'], - self.value['l']) + return "[file {}] {}".format( + self.value["source_file"], self.value["l"] + ) class SCOId(SubPrettyPrinter): @@ -84,10 +85,10 @@ class SCOId(SubPrettyPrinter): Pretty-printer for SC_Obligations.SCO_Id. """ - name = 'SC_Obligations.SCO_Id' + name = "SC_Obligations.SCO_Id" def to_string(self): - return 'SCO#{}'.format(int(self.value)) + return "SCO#{}".format(int(self.value)) class AddressInfo(SubPrettyPrinter): @@ -95,45 +96,47 @@ class AddressInfo(SubPrettyPrinter): Pretty-printer for Traces_Elf.Address_Info_Acc. """ - name = 'Traces_Elf.Address_Info_Acc' + name = "Traces_Elf.Address_Info_Acc" def to_string(self): if not self.value: - return 'null' + return "null" v = decoded_record(self.value.dereference()) - kind = str(v['kind']) - prefix = '{} ({}..{})'.format( - '_'.join(k.capitalize() for k in kind.split('_')), - v['first'], v['last'] + kind = str(v["kind"]) + prefix = "{} ({}..{})".format( + "_".join(k.capitalize() for k in kind.split("_")), + v["first"], + v["last"], ) - if kind == 'compilation_unit_addresses': - suffix = 'DIE_CU: {}'.format(v['die_cu']) + if kind == "compilation_unit_addresses": + suffix = "DIE_CU: {}".format(v["die_cu"]) - elif kind == 'section_addresses': - name = StringAccess(v['section_name']) - suffix = '{} [index: {}]'.format(name.get_string(), - v['section_sec_idx']) + elif kind == "section_addresses": + name = StringAccess(v["section_name"]) + suffix = "{} [index: {}]".format( + name.get_string(), v["section_sec_idx"] + ) - elif kind == 'subprogram_addresses': - suffix = repr(StringAccess(v['subprogram_name']).get_string()) + elif kind == "subprogram_addresses": + suffix = repr(StringAccess(v["subprogram_name"]).get_string()) - elif kind == 'inlined_subprogram_addresses': - suffix = 'call at {}'.format(v['call_sloc']) + elif kind == "inlined_subprogram_addresses": + suffix = "call at {}".format(v["call_sloc"]) - elif kind == 'symbol_addresses': - suffix = repr(StringAccess(v['symbol_name']).get_string()) + elif kind == "symbol_addresses": + suffix = repr(StringAccess(v["symbol_name"]).get_string()) - elif kind == 'line_addresses': - suffix = str(v['sloc']) - if v['disc']: - suffix += ' [disc: {}]'.format(v['disc']) + elif kind == "line_addresses": + suffix = str(v["sloc"]) + if v["disc"]: + suffix += " [disc: {}]".format(v["disc"]) else: - suffix = '' + suffix = "" - return '{} => {}'.format(prefix, suffix) + return "{} => {}".format(prefix, suffix) class InsnSetRangesPrinter(SubPrettyPrinter): @@ -141,11 +144,11 @@ class InsnSetRangesPrinter(SubPrettyPrinter): Pretty-printer for Elf_Disassemblers.Insn_Set_Ranges. """ - name = 'Elf_Disassemblers.Insn_Set_Ranges' + name = "Elf_Disassemblers.Insn_Set_Ranges" @property def set_pp(self): - return OrderedSetPrinter(self.value['_parent']) + return OrderedSetPrinter(self.value["_parent"]) def to_string(self): return self.set_pp.to_string() @@ -159,12 +162,13 @@ class InsnSetRangePrinter(SubPrettyPrinter): Pretty-printer for Elf_Disassemblers.Insn_Set_Range """ - name = 'Elf_Disassemblers.Insn_Set_Range' + name = "Elf_Disassemblers.Insn_Set_Range" def to_string(self): - return '{:0x} .. {:0x} => {}'.format( - int(self.value['first']), int(self.value['last']), - self.value['insn_set'] + return "{:0x} .. {:0x} => {}".format( + int(self.value["first"]), + int(self.value["last"]), + self.value["insn_set"], ) @@ -176,13 +180,19 @@ def __call__(self, value): def register_printers(objfile): - gdb.printing.register_pretty_printer(objfile, PrettyPrinter('gnatcov', [ - ArchAddrPrinter, - PCTypePrinter, - SlocPrinter, - LocalSlocPrinter, - SCOId, - AddressInfo, - InsnSetRangesPrinter, - InsnSetRangePrinter, - ])) + gdb.printing.register_pretty_printer( + objfile, + PrettyPrinter( + "gnatcov", + [ + ArchAddrPrinter, + PCTypePrinter, + SlocPrinter, + LocalSlocPrinter, + SCOId, + AddressInfo, + InsnSetRangesPrinter, + InsnSetRangePrinter, + ], + ), + ) diff --git a/tools/gnatcov/scripts/intervalmap.py b/tools/gnatcov/scripts/intervalmap.py index adf53cfb0..ab91efdda 100644 --- a/tools/gnatcov/scripts/intervalmap.py +++ b/tools/gnatcov/scripts/intervalmap.py @@ -22,10 +22,10 @@ def __setitem__(self, interval, value): """ if not isinstance(interval, slice): - raise TypeError('Interval required') + raise TypeError("Interval required") elif interval.start is None or interval.stop is None: - raise ValueError('Interval must have integer bounds') + raise ValueError("Interval must have integer bounds") elif interval.start >= interval.stop: # Do nothing for the empty interval. @@ -65,11 +65,12 @@ def __setitem__(self, interval, value): if self.bounds[start_insert_index - 1] in self.values: # Example: [3;4[ is added to bounds [1;6] raise ValueError( - '[{};{}[ is inside previously added' - ' interval [{};{}['.format( - interval.start, interval.stop, + "[{};{}[ is inside previously added" + " interval [{};{}[".format( + interval.start, + interval.stop, self.bounds[start_insert_index - 1], - self.bounds[start_insert_index] + self.bounds[start_insert_index], ) ) @@ -84,36 +85,44 @@ def __setitem__(self, interval, value): elif stop_insert_index > start_insert_index + 1: # Example: [2;4[ is added to bounds [1;3;5] - raise ValueError('[{};{}[ contains previous bound {}'.format( - interval.start, interval.stop, - self.bounds[start_insert_index + 1] - )) + raise ValueError( + "[{};{}[ contains previous bound {}".format( + interval.start, + interval.stop, + self.bounds[start_insert_index + 1], + ) + ) else: # Here, start_insert_index + 1 == stop_insert_index. if self.bounds[start_insert_index] != interval.start: # Example: [1;3[ is added to bounds [2;4] - raise ValueError('[{};{}[ contains previous bound {}'.format( - interval.start, interval.stop, - self.bounds[start_insert_index] - )) + raise ValueError( + "[{};{}[ contains previous bound {}".format( + interval.start, + interval.stop, + self.bounds[start_insert_index], + ) + ) # The starting bound is already inserted: just check it doesn't # start any previously added interval. elif interval.start in self.values: # Example: [3; 4] is added to bounds [1;2;3;5] raise ValueError( - '[{};{}[ overlaps with previously added' - ' interval [{};{}['.format( - interval.start, interval.stop, - interval.start, self.bounds[start_insert_index + 1] + "[{};{}[ overlaps with previously added" + " interval [{};{}[".format( + interval.start, + interval.stop, + interval.start, + self.bounds[start_insert_index + 1], ) ) # The starting bound is already inserted: check for the ending one. elif ( - stop_insert_index >= len(self.bounds) or - self.bounds[stop_insert_index] != interval.stop + stop_insert_index >= len(self.bounds) + or self.bounds[stop_insert_index] != interval.stop ): # Example: [2; 4] is added to bounds [1;2;4;5] self.bounds.insert(stop_insert_index, interval.stop) @@ -125,7 +134,6 @@ def __setitem__(self, interval, value): # And finally, insert the value itself! self.values[interval.start] = value - def __getitem__(self, key): """Return the value associated to the interval that contains `key`. @@ -134,15 +142,14 @@ def __getitem__(self, key): start_bound_index = bisect.bisect_right(self.bounds, key) if start_bound_index < 1: - raise KeyError('No interval contains {}'.format(key)) + raise KeyError("No interval contains {}".format(key)) else: start_bound = self.bounds[start_bound_index - 1] return self.values[start_bound] def __contains__(self, key): - """Return if `key` belongs to some covered interval. - """ + """Return if `key` belongs to some covered interval.""" try: self[key] except KeyError: @@ -176,13 +183,15 @@ def items(self): yield item def __repr__(self): - return '{{{}}}'.format(', '.join( - '[{}; {}[: {}'.format(low, high, repr(value)) - for (low, high), value in self.items() - )) + return "{{{}}}".format( + ", ".join( + "[{}; {}[: {}".format(low, high, repr(value)) + for (low, high), value in self.items() + ) + ) -if __name__ == '__main__': +if __name__ == "__main__": # Run tests... m = IntervalMap() @@ -208,51 +217,51 @@ def sanity_check(): last_bound_starts_interval = starts_interval def add(low, high, value, exception_expected=None): - print('Adding [{}; {}[: {}'.format(low, high, repr(value))) + print("Adding [{}; {}[: {}".format(low, high, repr(value))) try: m[low:high] = value except Exception as e: if exception_expected and isinstance(e, exception_expected): - print(' {}: {}'.format(type(e).__name__, e)) + print(" {}: {}".format(type(e).__name__, e)) else: raise else: if exception_expected: raise RuntimeError( - 'I was expecting an error, but nothing happened.' + "I was expecting an error, but nothing happened." ) else: - print(' ', m) - print(' >>', m.bounds) + print(" ", m) + print(" >>", m.bounds) sanity_check() - print('Empty interval map') - print(' ', m) + print("Empty interval map") + print(" ", m) - add(1, 4, 'B') + add(1, 4, "B") - add(0, 2, 'Z', ValueError) - add(0, 4, 'Z', ValueError) - add(0, 5, 'Z', ValueError) + add(0, 2, "Z", ValueError) + add(0, 4, "Z", ValueError) + add(0, 5, "Z", ValueError) - add(1, 2, 'Z', ValueError) - add(1, 4, 'Z', ValueError) - add(1, 5, 'Z', ValueError) + add(1, 2, "Z", ValueError) + add(1, 4, "Z", ValueError) + add(1, 5, "Z", ValueError) - add(2, 3, 'Z', ValueError) - add(2, 4, 'Z', ValueError) - add(2, 5, 'Z', ValueError) + add(2, 3, "Z", ValueError) + add(2, 4, "Z", ValueError) + add(2, 5, "Z", ValueError) - add(3, 0, 'Z') + add(3, 0, "Z") - add(0, 1, 'A') - add(4, 5, 'B') + add(0, 1, "A") + add(4, 5, "B") - add(10, 15, 'D') - add(20, 25, 'F') - add(30, 35, 'H') + add(10, 15, "D") + add(20, 25, "F") + add(30, 35, "H") - add(5, 8, 'C') - add(18, 20, 'E') - add(25, 30, 'G') + add(5, 8, "C") + add(18, 20, "E") + add(25, 30, "G") diff --git a/tools/gnatcov/scripts/slocinfo.py b/tools/gnatcov/scripts/slocinfo.py index ba506b76f..ffc195138 100644 --- a/tools/gnatcov/scripts/slocinfo.py +++ b/tools/gnatcov/scripts/slocinfo.py @@ -9,28 +9,25 @@ SLOC_INFO_LINE = re.compile( - b'^(?P[0-9a-f]+)-(?P[0-9a-f]+)' - b' line (?P[^:]+):(?P\d+)(?:[:](?P\d+))?' - b'(?: discriminator (?P\d+))?$' + b"^(?P[0-9a-f]+)-(?P[0-9a-f]+)" + b" line (?P[^:]+):(?P\d+)(?:[:](?P\d+))?" + b"(?: discriminator (?P\d+))?$" ) -Sloc = collections.namedtuple('Sloc', 'filename line column discriminator') +Sloc = collections.namedtuple("Sloc", "filename line column discriminator") def format_sloc(sloc, basename=False): if sloc is None: - return 'No source line information' - filename = sloc.filename.decode('ascii') - filename = ( - os.path.basename(filename) - if basename else - filename - ) - return '{}:{}{}{}'.format( - filename, sloc.line, - '' if sloc.column is None else ':{}'.format(sloc.column), - '' - if sloc.discriminator is None else - ' discriminator {}'.format(sloc.discriminator), + return "No source line information" + filename = sloc.filename.decode("ascii") + filename = os.path.basename(filename) if basename else filename + return "{}:{}{}{}".format( + filename, + sloc.line, + "" if sloc.column is None else ":{}".format(sloc.column), + "" + if sloc.discriminator is None + else " discriminator {}".format(sloc.discriminator), ) @@ -43,14 +40,15 @@ def get_sloc_info(exe_filename): # Let gnatcov parse ELF and DWARF for us. proc = subprocess.Popen( - ['gnatcov', 'dump-lines', exe_filename], stdout=subprocess.PIPE + ["gnatcov", "dump-lines", exe_filename], stdout=subprocess.PIPE ) outs, errs = proc.communicate() if proc.returncode != 0: - raise RuntimeError('gnatcov dump-lines returned an error') + raise RuntimeError("gnatcov dump-lines returned an error") # Used to store only one string per filename (reducing memory consumption). strings = {} + def uniq_string(string): try: return strings[string] @@ -64,16 +62,16 @@ def int_or_none(value): else: return int(value) - for line in outs.split(b'\n'): + for line in outs.split(b"\n"): m = SLOC_INFO_LINE.match(line) if m: - pc_start = int(m.group('pc_start'), 16) - pc_stop = int(m.group('pc_stop'), 16) + 1 + pc_start = int(m.group("pc_start"), 16) + pc_stop = int(m.group("pc_stop"), 16) + 1 sloc = Sloc( - uniq_string(m.group('src_file')), - int_or_none(m.group('line')), - int_or_none(m.group('column')), - int_or_none(m.group('discriminator')), + uniq_string(m.group("src_file")), + int_or_none(m.group("line")), + int_or_none(m.group("column")), + int_or_none(m.group("discriminator")), ) try: sloc_info[pc_start:pc_stop] = [sloc] diff --git a/tools/gnatcov/scripts/syminfo.py b/tools/gnatcov/scripts/syminfo.py index b74fa2862..f00859982 100755 --- a/tools/gnatcov/scripts/syminfo.py +++ b/tools/gnatcov/scripts/syminfo.py @@ -9,33 +9,34 @@ CODE_SYMBOL_LINE = re.compile( - b'^(?P[0-9a-f]+) (?P[0-9a-f]+)' - b' [Tt] (?P[a-zA-Z0-9_$@.]+)$' + b"^(?P[0-9a-f]+) (?P[0-9a-f]+)" + b" [Tt] (?P[a-zA-Z0-9_$@.]+)$" ) -Symbol = collections.namedtuple('Symbol', 'pc size name') +Symbol = collections.namedtuple("Symbol", "pc size name") def format_symbol(symbol): - return '{} ({:x}-{:x})'.format( - symbol.name, - symbol.pc, symbol.pc + symbol.size + return "{} ({:x}-{:x})".format( + symbol.name, symbol.pc, symbol.pc + symbol.size ) + def debug_interval(intval): seen_bounds = set() for i, bound in enumerate(intval.bounds): try: value = intval.values[bound] except KeyError: - suffix = '' + suffix = "" else: - suffix = '-> {:x}'.format(intval.bounds[i + 1]), value - print('{:02} - {:x}{}'.format(i, bound, suffix)) + suffix = "-> {:x}".format(intval.bounds[i + 1]), value + print("{:02} - {:x}{}".format(i, bound, suffix)) seen_bounds.add(bound) - print('---') + print("---") for unseen in set(intval.values.keys()) - seen_bounds: - print('-> {:x}'.format(unseen), intval.values[unseen]) - print('---') + print("-> {:x}".format(unseen), intval.values[unseen]) + print("---") + def get_sym_info(exe_filename): """Parse symbol info in `exe_filename` and return it as an interval map, @@ -48,16 +49,13 @@ def get_sym_info(exe_filename): overlap_syms = [] # Let nm parse ELF and the symbol table for us. - proc = subprocess.Popen( - ['nm', '-S', exe_filename], - stdout=subprocess.PIPE - ) + proc = subprocess.Popen(["nm", "-S", exe_filename], stdout=subprocess.PIPE) n = 0 while True: n += 1 # Read as many lines as possible from nm. - line = proc.stdout.readline().decode('ascii') + line = proc.stdout.readline().decode("ascii") if not line: break @@ -66,18 +64,18 @@ def get_sym_info(exe_filename): if not m: continue - pc = int(m.group('pc'), 16) - size = int(m.group('size'), 16) - symbol = Symbol(pc, size, m.group('name')) + pc = int(m.group("pc"), 16) + size = int(m.group("size"), 16) + symbol = Symbol(pc, size, m.group("name")) try: - sym_info[pc:pc + size] = symbol + sym_info[pc : pc + size] = symbol except ValueError: overlap_syms.append(symbol) return sym_info, overlap_syms -if __name__ == '__main__': +if __name__ == "__main__": import sys binary = sys.argv[1] @@ -85,21 +83,24 @@ def get_sym_info(exe_filename): sym_info, overlap_syms = get_sym_info(binary) if overlap_syms: - sys.stderr.write('warning: some symbols overlap with others:\n') + sys.stderr.write("warning: some symbols overlap with others:\n") for sym in overlap_syms: - sys.stderr.write(' - {}\n'.format(syminfo.format_symbol(sym))) + sys.stderr.write(" - {}\n".format(syminfo.format_symbol(sym))) try: symbol = sym_info[address] except KeyError: - print('Not found') + print("Not found") sys.exit(1) else: print( - '{:#08x} is inside {}:' - ' {:#08x}-{:#08x}' - ' ({:#x}/{:#x} bytes)'.format( - address, symbol.name, - symbol.pc, symbol.pc + symbol.size, - address - symbol.pc, symbol.size + "{:#08x} is inside {}:" + " {:#08x}-{:#08x}" + " ({:#x}/{:#x} bytes)".format( + address, + symbol.name, + symbol.pc, + symbol.pc + symbol.size, + address - symbol.pc, + symbol.size, ) ) diff --git a/tools/gnatcov/scripts/traceinfo.py b/tools/gnatcov/scripts/traceinfo.py index 06e6d165c..f7177d297 100644 --- a/tools/gnatcov/scripts/traceinfo.py +++ b/tools/gnatcov/scripts/traceinfo.py @@ -8,23 +8,21 @@ TRACE_LINE = re.compile( - b'^(?P[0-9a-f]+)-(?P[0-9a-f]+) .: [0-9a-f]{2}' - b' (?P-|t)(?P-|t)' - b'(?P-|t)(?P-|t)' - b' block$' + b"^(?P[0-9a-f]+)-(?P[0-9a-f]+) .: [0-9a-f]{2}" + b" (?P-|t)(?P-|t)" + b"(?P-|t)(?P-|t)" + b" block$" ) LeaveFlags = collections.namedtuple( - 'LeaveFlags', - 'special fault block fallthrough branch' + "LeaveFlags", "special fault block fallthrough branch" ) + def merge_flags(f1, f2): """Return the merge of two leave flags.""" - return LeaveFlags(*( - flag1 or flag2 for flag1, flag2 in zip(f1, f2) - )) + return LeaveFlags(*(flag1 or flag2 for flag1, flag2 in zip(f1, f2))) def get_trace_info(traces): @@ -33,12 +31,12 @@ def get_trace_info(traces): """ # Let gnatcov parse the traces for us. proc = subprocess.Popen( - ['gnatcov', 'dump-trace', traces], stdout=subprocess.PIPE + ["gnatcov", "dump-trace", traces], stdout=subprocess.PIPE ) outs, errs = proc.communicate() if proc.returncode != 0: - raise RuntimeError('gnatcov dump-trace returned an error') + raise RuntimeError("gnatcov dump-trace returned an error") # Parse its output and collect information. @@ -49,20 +47,20 @@ def get_trace_info(traces): # First collect all traces ranges, unifying ranges that start at the same # address. - for line in outs.split(b'\n'): + for line in outs.split(b"\n"): m = TRACE_LINE.match(line) if m: - pc_start = int(m.group('start'), 16) + pc_start = int(m.group("start"), 16) # For gnatcov, the end address is executed, but for our interval # map, the end bound is not covered. - pc_end = int(m.group('end'), 16) + 1 + pc_end = int(m.group("end"), 16) + 1 flags = LeaveFlags( - m.group('special') == 't', - m.group('fault') == 't', + m.group("special") == "t", + m.group("fault") == "t", True, - m.group('fallthrough') == 't', - m.group('branch') == 't', + m.group("fallthrough") == "t", + m.group("branch") == "t", ) # If pc_start is already in the range, just take the longest trace. @@ -92,26 +90,27 @@ def get_trace_info(traces): # interval to the result. if last_interval: if last_interval[1] < pc_start: - executed_insns[last_interval[0]:last_interval[1]] = True + executed_insns[last_interval[0] : last_interval[1]] = True last_interval = (pc_start, pc_end) else: last_interval = ( last_interval[0], - max(last_interval[1], pc_end) + max(last_interval[1], pc_end), ) else: last_interval = (pc_start, pc_end) if last_interval: - executed_insns[last_interval[0]:last_interval[1]] = True + executed_insns[last_interval[0] : last_interval[1]] = True return (executed_insns, leave_flags) -if __name__ == '__main__': +if __name__ == "__main__": import sys + executed_insns, leave_flags = get_trace_info(sys.argv[1]) for (pc_start, pc_end), _ in executed_insns.items(): - print('{:x}-{:x}: {}'.format( - pc_start, pc_end - 1, leave_flags[pc_end] - )) + print( + "{:x}-{:x}: {}".format(pc_start, pc_end - 1, leave_flags[pc_end]) + ) From 9f2c9f7d8921d07de024f7f8c9c64bcc27d1a28f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 26 Feb 2024 22:01:11 +0000 Subject: [PATCH 0733/1483] SCOV/minicheck.py: minor reformatting --- testsuite/SCOV/minicheck.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 8b8031e45..65ca05f5f 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -142,10 +142,10 @@ def build_and_run( :param None|list[str] exec_args: List of arguments to pass to the executable. This will only work for native configurations. :param bool auto_languages: See SUITE.tutils.xcov. - :param None|str manual_prj_name: when the dump trigger is manual, several + :param None|str manual_prj_name: When the dump trigger is manual, several traces files (one per project) can be emitted if there are dump buffers procedure calls in at least two distinct projects. This is the name of - the project which trace we want to consider. + the project for which we want to consider traces. :param bool auto_config_args: If False, do not pass the --config argument to gprbuild and gnatcov invocations. From 59b4241b93c9933954f45ad31a3c283d2907a6f3 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 26 Feb 2024 17:04:16 +0000 Subject: [PATCH 0734/1483] instrument-projects.adb: minor reformatting --- tools/gnatcov/instrument-projects.adb | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 9a82eadc8..f5f29619d 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -1089,6 +1089,7 @@ begin Only_UOIs => True); if Dump_Config.Trigger = Manual then + -- The expected manual dump indication can be located in any -- source file, not only in sources of interest. From e041c367da6a5a1f8fe056c54cc28fbd7011beec Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 26 Feb 2024 16:53:04 +0000 Subject: [PATCH 0735/1483] Instrument: do not expand manual dumps in externally built projects --- .../250-manual-dump-ext-built/main/main.adb | 7 ++ .../250-manual-dump-ext-built/mylib/mylib.adb | 11 +++ .../250-manual-dump-ext-built/mylib/mylib.ads | 3 + .../250-manual-dump-ext-built/test.opt | 1 + .../250-manual-dump-ext-built/test.py | 67 +++++++++++++++++++ tools/gnatcov/instrument-projects.adb | 19 ++---- 6 files changed, 96 insertions(+), 12 deletions(-) create mode 100644 testsuite/tests/instr-cov/250-manual-dump-ext-built/main/main.adb create mode 100644 testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.adb create mode 100644 testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.ads create mode 100644 testsuite/tests/instr-cov/250-manual-dump-ext-built/test.opt create mode 100644 testsuite/tests/instr-cov/250-manual-dump-ext-built/test.py diff --git a/testsuite/tests/instr-cov/250-manual-dump-ext-built/main/main.adb b/testsuite/tests/instr-cov/250-manual-dump-ext-built/main/main.adb new file mode 100644 index 000000000..5cfc5d418 --- /dev/null +++ b/testsuite/tests/instr-cov/250-manual-dump-ext-built/main/main.adb @@ -0,0 +1,7 @@ +with Mylib; + +procedure Main is +begin + Mylib.Say_Hello; + pragma Annotate (Xcov, Dump_Buffers); +end Main; diff --git a/testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.adb b/testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.adb new file mode 100644 index 000000000..9be8d0432 --- /dev/null +++ b/testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Mylib is + + procedure Say_Hello is + begin + pragma Annotate (Xcov, Dump_Buffers); + Put_Line ("Hello, world!"); + end Say_Hello; + +end Mylib; diff --git a/testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.ads b/testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.ads new file mode 100644 index 000000000..008ed737d --- /dev/null +++ b/testsuite/tests/instr-cov/250-manual-dump-ext-built/mylib/mylib.ads @@ -0,0 +1,3 @@ +package Mylib is + procedure Say_Hello; +end Mylib; diff --git a/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.opt b/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.opt new file mode 100644 index 000000000..6f0a4412b --- /dev/null +++ b/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Test is specific to instrumentation (manual dumps) diff --git a/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.py b/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.py new file mode 100644 index 000000000..715e6cf2c --- /dev/null +++ b/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.py @@ -0,0 +1,67 @@ +""" +Check that gnatcov's instrumenter ignores manual dump annotations in externally +built projects even when --externally-built-projects is passed. +""" + +from e3.fs import find + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprbuild, gprfor + + +tmp = Wdir("tmp_") + +# Build uninstrumented "mylib.gpr" +mylib_gpr = gprfor( + prjid="mylib", + srcdirs="../mylib", + objdir="obj-mylib", + mains=[], + extra=""" + for Library_Name use "mylib"; + for Library_Dir use "lib-mylib"; + + type Boolean is ("False", "True"); + Ext_Built : Boolean := external ("EXT_BUILT", "True"); + for Externally_Built use Ext_Built; + + package Coverage is + for Units use (); + end Coverage; + """, +) +gprbuild(mylib_gpr, gargs=["-XEXT_BUILT=False"]) + +# Build and run "main.adb" from "main.gpr", which depends on "mylib.gpr". If +# manual dump expansion processed mylib's sources, we would get a warning +# saying that the instrumenter has found a manual dump in a subproject. +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + prjid="main", + mains=["main.adb"], + deps=[mylib_gpr], + srcdirs=["../main"], + ), + externally_built_projects=True, + ), + covlevel="stmt", + mains=["main"], + dump_trigger="manual", + manual_prj_name="main", + extra_coverage_args=["--annotate=xcov"], +) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) + +# As a double check in addition to the warning detection mentionned above, make +# sure that no instrumented sources were created for mylib. +thistest.fail_if_not_equal( + "instrumented sources for mylib", + "", + "\n".join(sorted(find("obj-mylib", "*.ads") + find("obj-mylib", "*.adb"))), +) + +thistest.result() diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index f5f29619d..dc630ea66 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -247,8 +247,8 @@ is procedure Add_Project_Source (Project : GPR.Project_Type; Source_File : GPR.File_Info); - -- Add Source_File to the C or Ada list of all project sources depending on - -- its language. + -- If an instrumenter supports Source_File's language and if Project is not + -- externally built, add Source_File to Project_Sources. procedure Insert_Manual_Dump_Trigger (Language : Src_Supported_Language; @@ -705,18 +705,13 @@ is ------------------------ procedure Add_Project_Source - (Project : GPR.Project_Type; Source_File : GPR.File_Info) - is - pragma Unreferenced (Project); + (Project : GPR.Project_Type; Source_File : GPR.File_Info) is begin - -- Check if gnatcov was built with support for this language. If not, - -- exit early. - - if not Builtin_Support (To_Language (Source_File.Language)) then - return; + if Builtin_Support (To_Language (Source_File.Language)) + and then not Project.Externally_Built + then + Project_Sources.Insert (Source_File); end if; - - Project_Sources.Insert (Source_File); end Add_Project_Source; --------------------------- From 1b21355b0c45d8473b489c591f8492cad6cfe132 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 27 Feb 2024 13:11:52 +0100 Subject: [PATCH 0736/1483] Document the XML report format --- doc/gnatcov/cov_source.rst | 13 ++++++++++++- tools/gnatcov/command_line.ads | 2 +- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index b90df8bb7..e683e6848 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -52,7 +52,7 @@ The available options are as follows: :cmd-option:`-a`, :cmd-option:`--annotate` |marg|: Request one or more output report formats. All the criteria support - ``xcov[+]``, ``html``, ``cobertura`` and ``report`` formats, with + ``cobertura``, ``html,``, ``report``, ``xcov[+]``, ``xml`` formats, with interpretations that vary depending on the assessed criteria. See the corresponding documentation later in this chapter for more details. This option accepts comma separated values and/or can be specified multiple times @@ -338,6 +338,17 @@ See the :ref:`sample annotated source ` appendix for a sample of html annotated source. +XML report, xml (:cmd-option:`=xml`) +------------------------------------ + +:cmd-option:`--annotate=xml` produces a coverage report in the XML format, as +specified per the ``gnatcov-xml-report.xsd`` (XML schema description) that is +generated alongside. + +This report format is on par with the HTML report in terms of features, and it +is the preferred choice for programmatically accessing the coverage results. + + Cobertura report (:cmd-option:`=cobertura`) ------------------------------------------- diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index b53e05735..031bba4bc 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -1375,7 +1375,7 @@ package Command_Line is Pattern => "[FORM|LIST]", Help => "Generate a FORM report. FORM is one of:" - & ASCII.LF & " asm, xcov, html, xcov+, cobertura, report." + & ASCII.LF & " asm, cobertura, html, report, xcov, xcov+, xml." & ASCII.LF & "Multiple reports can be produced in a single" & " execution by passing a comma separated list of FORMs to this" & " option, or by specifying this option multiple times on the" From f5a854090107ef471d1c15d9828818617c0d7837 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 27 Feb 2024 16:03:36 +0100 Subject: [PATCH 0737/1483] Reorder alphabetically coverage report format sections --- doc/gnatcov/cov_source.rst | 176 ++++++++++++++++++------------------- 1 file changed, 88 insertions(+), 88 deletions(-) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index e683e6848..aa98d2a72 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -239,6 +239,94 @@ application unit: end Between; +Cobertura report (:cmd-option:`=cobertura`) +------------------------------------------- + +:cmd-option:`--annotate=cobertura` produces a coverage report in the Cobertura +format, as specified per the cobertura.dtd (document type description) that is +generated alongside. + +This format specification is not maintained by gnatcov, and it does not thus +provide all of the information that other report formats do, notably MC/DC +coverage information, violation messages. Decision violations are output using +the "branch" terminology of Cobertura (one decision being two branches, and +either 0, 1 or 2 of those branches are covered). + +It is mainly provided for integration with external tools, such as continuous +integration systems, e.g. gitlab, which supports integration of coverage reports +into merge requests using this format. + +File names in this coverage report are absolute. Depending on the use context of +this coverage report, it can also make sense to strip a given prefix from the +absolute paths to make them relative to, e.g. a project root. The +:cmd-option:`--source-root` command line option accepts a string prefix that +will be removed from absolute path references in the report. + + +Annotated sources, html (:cmd-option:`=html`) +--------------------------------------------- + +For source coverage criteria, |gcvcov| :cmd-option:`--annotate=html` produces an +index-based report under the HTML format (the other command names are aliases +for backward compatibility). + +To navigate the report, open the index.html file using the browser of your +choice. This index file contains a summary of the assessment context (assessed +criteria, trace files involved, ...) and of the coverage results for all the +units, with links to their annotated sources. If the :cmd-option:`-P` was used +to designate the source units of interest, sources are indexed per-project. + +Note that some dynamic filtering / sorting can be applied: + +* Filter by kind of coverage obligations: either reporting on lines, or on + statement / decision / MCDC (one or several) obligations, depending on the + coverage level. See :ref:`synthetic-metrics` for more information. + +* Sort indexes by clicking on column headers, allowing for example sorts keyed + on unit names or on relative coverage achievement. + +See our :ref:`sample html index ` appendix for an +example index page, which embeds a self-description of all the items it +contains. + +The user can browse through an annotated version of the sources from the index. +Each annotated source page contains a summary of the assessment results. This +summary can be expanded to print subprogram metrics: the user can click on a +subprogram's metrics to access it in the annotated source immediately. This +summary is followed by the original source lines, all numbered and marked with a +coverage annotation as in the :cmd-option:`--annotate=xcov` case. Lines with +obligations are colorized in green, orange or red for ``+``, ``!`` or ``-`` +coverage respectively. + +See the :ref:`sample annotated source ` appendix for a +sample of html annotated source. + + +Violations summary, text (:cmd-option:`=report`) +------------------------------------------------ + +For source coverage criteria, |gcvcov| :cmd-option:`--annotate=report` produces +a summary that lists all the :term:`coverage violations ` +(failure to satisfy some aspect of a coverage criterion) relevant to the set of +assessed criteria. + +The report features explicit start/end of report notifications and at least +three sections in between: Assessment Context, Coverage Violations, and +Analysis Summary. Should |gcv| be unable to determine the coverage state of +some coverage obligations, those will be reported in a dedicated Undetermined +Coverage Items section, with a description of why the tool was unable to +determine the coverage state for each obligation. A few variations are +introduced when :term:`exemption regions ` are in scope. +See the :ref:`exemptions` section for more details on their use and effect on +the output reports. + +If :cmd-option:`--dump-units-to -` is also on the command line, a *UNITS OF +INTEREST* section is produced, which contains the list of units considered +of-interest for the reported assessment, as well as the list of source files +individually ignored with the ``Ignored_Source_Files`` project attribute and +corresponding command-line option. + + Annotated sources, text (:cmd-option:`=xcov[+]`) ------------------------------------------------ @@ -299,45 +387,6 @@ improperly satisfied obligation is an uncovered statement on line 7:: STATEMENT "return V ..." at 7:10 not executed -Annotated sources, html (:cmd-option:`=html`) ---------------------------------------------- - -For source coverage criteria, |gcvcov| :cmd-option:`--annotate=html` produces an -index-based report under the HTML format (the other command names are aliases -for backward compatibility). - -To navigate the report, open the index.html file using the browser of your -choice. This index file contains a summary of the assessment context (assessed -criteria, trace files involved, ...) and of the coverage results for all the -units, with links to their annotated sources. If the :cmd-option:`-P` was used -to designate the source units of interest, sources are indexed per-project. - -Note that some dynamic filtering / sorting can be applied: - -* Filter by kind of coverage obligations: either reporting on lines, or on - statement / decision / MCDC (one or several) obligations, depending on the - coverage level. See :ref:`synthetic-metrics` for more information. - -* Sort indexes by clicking on column headers, allowing for example sorts keyed - on unit names or on relative coverage achievement. - -See our :ref:`sample html index ` appendix for an -example index page, which embeds a self-description of all the items it -contains. - -The user can browse through an annotated version of the sources from the index. -Each annotated source page contains a summary of the assessment results. This -summary can be expanded to print subprogram metrics: the user can click on a -subprogram's metrics to access it in the annotated source immediately. This -summary is followed by the original source lines, all numbered and marked with a -coverage annotation as in the :cmd-option:`--annotate=xcov` case. Lines with -obligations are colorized in green, orange or red for ``+``, ``!`` or ``-`` -coverage respectively. - -See the :ref:`sample annotated source ` appendix for a -sample of html annotated source. - - XML report, xml (:cmd-option:`=xml`) ------------------------------------ @@ -349,55 +398,6 @@ This report format is on par with the HTML report in terms of features, and it is the preferred choice for programmatically accessing the coverage results. -Cobertura report (:cmd-option:`=cobertura`) -------------------------------------------- - -:cmd-option:`--annotate=cobertura` produces a coverage report in the Cobertura -format, as specified per the cobertura.dtd (document type description) that is -generated alongside. - -This format specification is not maintained by gnatcov, and it does not thus -provide all of the information that other report formats do, notably MC/DC -coverage information, violation messages. Decision violations are output using -the "branch" terminology of Cobertura (one decision being two branches, and -either 0, 1 or 2 of those branches are covered). - -It is mainly provided for integration with external tools, such as continuous -integration systems, e.g. gitlab, which supports integration of coverage reports -into merge requests using this format. - -File names in this coverage report are absolute. Depending on the use context of -this coverage report, it can also make sense to strip a given prefix from the -absolute paths to make them relative to, e.g. a project root. The -:cmd-option:`--source-root` command line option accepts a string prefix that -will be removed from absolute path references in the report. - - -Violations summary, text (:cmd-option:`=report`) ------------------------------------------------- - -For source coverage criteria, |gcvcov| :cmd-option:`--annotate=report` produces -a summary that lists all the :term:`coverage violations ` -(failure to satisfy some aspect of a coverage criterion) relevant to the set of -assessed criteria. - -The report features explicit start/end of report notifications and at least -three sections in between: Assessment Context, Coverage Violations, and -Analysis Summary. Should |gcv| be unable to determine the coverage state of -some coverage obligations, those will be reported in a dedicated Undetermined -Coverage Items section, with a description of why the tool was unable to -determine the coverage state for each obligation. A few variations are -introduced when :term:`exemption regions ` are in scope. -See the :ref:`exemptions` section for more details on their use and effect on -the output reports. - -If :cmd-option:`--dump-units-to -` is also on the command line, a *UNITS OF -INTEREST* section is produced, which contains the list of units considered -of-interest for the reported assessment, as well as the list of source files -individually ignored with the ``Ignored_Source_Files`` project attribute and -corresponding command-line option. - - Assessment Context ^^^^^^^^^^^^^^^^^^ From 37958e0076ffbec43240f767e77c693c8fe765b0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 28 Feb 2024 16:27:11 +0000 Subject: [PATCH 0738/1483] instr-cov/250-manual-dump-ext-built: kill with 5.04a1 --- testsuite/tests/instr-cov/250-manual-dump-ext-built/test.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.opt b/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.opt index 6f0a4412b..09e22da78 100644 --- a/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.opt +++ b/testsuite/tests/instr-cov/250-manual-dump-ext-built/test.opt @@ -1 +1,2 @@ +5.04a1 DEAD Pragma Annotate (Xcov) not supported bin-traces DEAD Test is specific to instrumentation (manual dumps) From e1b2f30212ba798c28d6e73ced3bbbd5ad53bb0e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 26 Feb 2024 08:14:00 +0100 Subject: [PATCH 0739/1483] doc: address flake8 warnings --- doc/conf.py | 6 ++++-- doc/gnatcov/gen_prjtrees.py | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 3ac1bd87f..462ce446c 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -59,7 +59,7 @@ # General information about the project. project = "GNATDAS" -copyright = "2009-2022, AdaCore" +copyright = "2009-2022, AdaCore" # noqa: A001 docname = "Manuals" rst_epilog = """ @@ -287,8 +287,10 @@ # Custom :cmd-option: role def cmd_option_role( - name, rawtext, text, lineno, inliner, options={}, content=[] + name, rawtext, text, lineno, inliner, options=None, content=None ): + options = options or {} + content = content or [] node = nodes.literal(rawtext, text, *content, **options) return [node], [] diff --git a/doc/gnatcov/gen_prjtrees.py b/doc/gnatcov/gen_prjtrees.py index 5c5e31834..3579af24e 100644 --- a/doc/gnatcov/gen_prjtrees.py +++ b/doc/gnatcov/gen_prjtrees.py @@ -31,6 +31,6 @@ def gen_tree(tmpl, outfile, selected): for k in trees: gen_tree(tmpl, open(k + ".dot", "w"), trees[k]) render(k) - os.remove (f"{k}.dot") + os.remove(f"{k}.dot") render("prjtree") From b375f0f67d7b377e4cc9f3cfdda762265fdbce0c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 26 Feb 2024 09:46:29 +0100 Subject: [PATCH 0740/1483] Address flake8 issues in various scripts --- tools/gnatcov/examples/xml/xcov.py | 17 +++++++---------- tools/gnatcov/misc/design/instrument_mcdc.py | 2 +- tools/gnatcov/scripts/bddinfo.py | 4 ++-- tools/gnatcov/scripts/decision_cfg.py | 10 ++++------ tools/gnatcov/scripts/slocinfo.py | 4 ++-- tools/gnatcov/scripts/syminfo.py | 2 +- 6 files changed, 17 insertions(+), 22 deletions(-) diff --git a/tools/gnatcov/examples/xml/xcov.py b/tools/gnatcov/examples/xml/xcov.py index 6d0e56b24..cad2b23ad 100644 --- a/tools/gnatcov/examples/xml/xcov.py +++ b/tools/gnatcov/examples/xml/xcov.py @@ -2,7 +2,6 @@ """API to read xcov XML coverage reports""" from xml.dom import minidom -from time import strftime COVERAGE_STATE = { @@ -257,8 +256,8 @@ def parse_node(self, node): # Register messages for m in self.messages: self.source.messages[m.sco_id] = m - for l in self.src_lines: - self.source.lines[l.num] = l + for line in self.src_lines: + self.source.lines[line.num] = line def get_non_exempted_violations(self, levels): """Report violations (as done by xcov --annotate=report) @@ -336,13 +335,11 @@ def get_lines(self): return [line for sm in self.src_mappings for line in sm.src_lines] def get_non_exempted_violations(self, levels): - list_ = [ - sm.get_non_exempted_violations(levels) for sm in self.src_mappings - ] - list_ = [l for l in list_ if l is not None] result = [] - for l in list_: - result.extend(l) + for sm in self.src_mappings: + violations = sm.get_non_exempted_violations(levels) + if violations is not None: + result.extend(violations) return result def pp_violations(self, levels): @@ -392,7 +389,7 @@ def __init__(self, report_name="index.iml"): ] def get_levels(self): - return [p for p in self.coverage_level.split("+")] + return self.coverage_level.split("+") def visitor(self, func): for src in self.source_names: diff --git a/tools/gnatcov/misc/design/instrument_mcdc.py b/tools/gnatcov/misc/design/instrument_mcdc.py index b2a014f7f..8c0b379c6 100644 --- a/tools/gnatcov/misc/design/instrument_mcdc.py +++ b/tools/gnatcov/misc/design/instrument_mcdc.py @@ -242,7 +242,7 @@ def compute_edges(expr, for_false, for_true): root = compute_edges(expr.expr, for_true, for_false) else: - assert False + raise AssertionError return root diff --git a/tools/gnatcov/scripts/bddinfo.py b/tools/gnatcov/scripts/bddinfo.py index 6062287c2..4a44775eb 100644 --- a/tools/gnatcov/scripts/bddinfo.py +++ b/tools/gnatcov/scripts/bddinfo.py @@ -9,8 +9,8 @@ # assumptions over its format. COND_LINE = re.compile( b"^---.*@(?P[0-9a-f]+) .*: notice:" - b" cond branch for SCO #(?P\d+):" - b" CONDITION at (?P.*) \(.*\)" + b" cond branch for SCO #(?P\\d+):" + b" CONDITION at (?P.*) \\(.*\\)" b"$" ) EDGES_LINE = re.compile( diff --git a/tools/gnatcov/scripts/decision_cfg.py b/tools/gnatcov/scripts/decision_cfg.py index 47c19f449..1912da983 100755 --- a/tools/gnatcov/scripts/decision_cfg.py +++ b/tools/gnatcov/scripts/decision_cfg.py @@ -31,7 +31,7 @@ BRANCH: STYLE_BRANCH_TAKEN, } -SLOC_RANGE = re.compile("^([^:]*):(\d+):(\d+)-(\d+):(\d+)$") +SLOC_RANGE = re.compile(r"^([^:]*):(\d+):(\d+)-(\d+):(\d+)$") SlocRange = collections.namedtuple( "SlocRange", "filename" " start_line start_column" " end_line end_column" ) @@ -159,8 +159,6 @@ def get_insn_properties(insn): # Branch can go to an absolute address, to the link register or to the # control register. - dest_in_reg = False - return_from_subroutine = False if mnemonic.endswith("l") or mnemonic.endswith("la"): # Branch and Link (call) if "ctr" in mnemonic: @@ -279,7 +277,7 @@ def parse_program(string): (elf_machine,) = arch_struct.unpack(f.read(2)) try: arch = ARCHITECTURES[elf_machine] - except: + except KeyError: raise argparse.ArgumentTypeError( "{}: unhandled architecture ({})".format(string, elf_machine) ) @@ -700,7 +698,7 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): else: # We are not supposed to end up here since args.location items come # from arguments parsing. - assert False + raise AssertionError locations = Locations( sym_info, accepted_symbols, accepted_addr_ranges, accepted_slocs @@ -730,7 +728,7 @@ def get_decision_cfg(program, toolchain, sloc_info, locations): # Use the BDD, and especially its EXCEPTION edges info to tag as # uncoverable the successors of basic blocks that raise an exception. - for pc, basic_block in decision_cfg.items(): + for _, basic_block in decision_cfg.items(): last_insn = basic_block[-1] try: branch_info = bdd_info[last_insn.pc] diff --git a/tools/gnatcov/scripts/slocinfo.py b/tools/gnatcov/scripts/slocinfo.py index ffc195138..1e8930a08 100644 --- a/tools/gnatcov/scripts/slocinfo.py +++ b/tools/gnatcov/scripts/slocinfo.py @@ -10,8 +10,8 @@ SLOC_INFO_LINE = re.compile( b"^(?P[0-9a-f]+)-(?P[0-9a-f]+)" - b" line (?P[^:]+):(?P\d+)(?:[:](?P\d+))?" - b"(?: discriminator (?P\d+))?$" + b" line (?P[^:]+):(?P\\d+)(?:[:](?P\\d+))?" + b"(?: discriminator (?P\\d+))?$" ) Sloc = collections.namedtuple("Sloc", "filename line column discriminator") diff --git a/tools/gnatcov/scripts/syminfo.py b/tools/gnatcov/scripts/syminfo.py index f00859982..33902cbc0 100755 --- a/tools/gnatcov/scripts/syminfo.py +++ b/tools/gnatcov/scripts/syminfo.py @@ -85,7 +85,7 @@ def get_sym_info(exe_filename): if overlap_syms: sys.stderr.write("warning: some symbols overlap with others:\n") for sym in overlap_syms: - sys.stderr.write(" - {}\n".format(syminfo.format_symbol(sym))) + sys.stderr.write(" - {}\n".format(sym_info.format_symbol(sym))) try: symbol = sym_info[address] except KeyError: From 07451e600e94ec9539a3c21e70ea382e2dadafe5 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 23 Feb 2024 22:09:37 +0100 Subject: [PATCH 0741/1483] testsuite/.gitignore: add internal-tests --- testsuite/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/.gitignore b/testsuite/.gitignore index 0184a825b..d5f9a3008 100644 --- a/testsuite/.gitignore +++ b/testsuite/.gitignore @@ -15,3 +15,4 @@ __pycache__ wd_* test.py.* .~undo-tree~ +internal-tests From b1e6c087cae6509a6cecd028d69384a67e1960f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 28 Feb 2024 15:08:04 +0100 Subject: [PATCH 0742/1483] Kill test for 5.04a1 --- .../instr-cov/231-malformed-exempt-markers/main_1.adb | 1 - .../instr-cov/231-malformed-exempt-markers/main_2.adb | 1 + .../tests/instr-cov/231-malformed-exempt-markers/test.opt | 1 + .../tests/instr-cov/231-malformed-exempt-markers/test.py | 8 ++++---- 4 files changed, 6 insertions(+), 5 deletions(-) create mode 100644 testsuite/tests/instr-cov/231-malformed-exempt-markers/test.opt diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_1.adb b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_1.adb index 63e208439..43c92f5b1 100644 --- a/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_1.adb +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_1.adb @@ -7,7 +7,6 @@ begin null; end if; pragma Annotate (Xcov, Exempt_Off, "Superfluous argument"); - pragma Annotate (Xcov, Exempt_On, "Invalid" & " argument"); pragma Annotate (Xcov, AAA, "Unrecognized annotation"); pragma Annotate (Xcov); pragma Annotate (Test); -- No warning from gnatcov diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb index c859dc63e..5cac79ee8 100644 --- a/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb @@ -2,4 +2,5 @@ procedure Main_2 is begin pragma Annotate (1); pragma Annotate (Xcov, 1); + pragma Annotate (Xcov, Exempt_On, "Invalid" & " argument"); end Main_2; diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.opt b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.opt new file mode 100644 index 000000000..e32df191c --- /dev/null +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD requires feature support lacking in 5.04a1 diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py index 4f7582146..013e50dbe 100644 --- a/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py @@ -47,11 +47,11 @@ "*** main_1.adb:5:5: warning: No justification given for exempted" " region\n" "*** main_1.adb:9:5: warning: At most 2 pragma arguments allowed\n" - "*** main_1.adb:10:5: warning: Invalid justification argument: string" - " literal expected\n" - "*** main_1.adb:11:5: warning: Invalid Xcov annotation kind: aaa\n" - "*** main_1.adb:12:5: warning: Xcov annotation kind missing\n" + "*** main_1.adb:10:5: warning: Invalid Xcov annotation kind: aaa\n" + "*** main_1.adb:11:5: warning: Xcov annotation kind missing\n" "*** main_2.adb:4:5: warning: Invalid Xcov annotation kind\n" + "*** main_2.adb:5:5: warning: Invalid justification argument: string" + " literal expected\n" ), contents_of("instrument.log"), ) From e9d6a87d77100a6785300d4868bbbb45ff893c1e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 26 Feb 2024 09:17:15 +0100 Subject: [PATCH 0743/1483] Address flake8 issues in testsuite framework scripts --- testsuite/OCOV/tc.py | 8 +-- .../GPR/ByCmdLine/ProjectsAndUnits/test.py | 2 +- testsuite/SCOV/expgen/generator/utils.py | 2 +- testsuite/SCOV/expgen/language/__init__.py | 2 +- .../SCOV/expgen/language/ada/__init__.py | 4 +- testsuite/SCOV/expgen/language/c/__init__.py | 2 +- testsuite/SCOV/instr.py | 18 +++--- testsuite/SCOV/internals/driver.py | 26 +++++---- testsuite/SCOV/internals/xnexpanders.py | 4 +- testsuite/SCOV/minicheck.py | 34 ++++++------ testsuite/SCOV/tc.py | 4 +- testsuite/SUITE/context.py | 8 ++- testsuite/SUITE/control.py | 4 +- testsuite/SUITE/cutils.py | 35 ++++++------ testsuite/SUITE/stream_decoder.py | 12 ++-- testsuite/SUITE/tutils.py | 4 +- testsuite/altrun/ccg_native/pre_testsuite.py | 2 +- testsuite/altrun/trace32/crun.py | 4 +- testsuite/altrun/trace32/pre_testsuite.py | 4 +- testsuite/testsuite.py | 55 ++++++++++--------- 20 files changed, 124 insertions(+), 110 deletions(-) diff --git a/testsuite/OCOV/tc.py b/testsuite/OCOV/tc.py index 7f073a1df..6ec93466e 100644 --- a/testsuite/OCOV/tc.py +++ b/testsuite/OCOV/tc.py @@ -37,20 +37,20 @@ def __init__( self, test_drivers, coverage_expectations, - extra_sourcedirs=[], + extra_sourcedirs=None, level="branch", annotate="asm", - extra_xcov_args=[], + extra_xcov_args=None, ): self.test_drivers = test_drivers self.coverage_expectations = { TARGET_INFO.to_platform_specific_symbol(symbol): data for symbol, data in coverage_expectations.items() } - self.extra_sourcedirs = extra_sourcedirs + self.extra_sourcedirs = extra_sourcedirs or [] self.level = level self.annotate = annotate - self.extra_xcov_args = extra_xcov_args + self.extra_xcov_args = extra_xcov_args or [] def run(self, register_failure=True): """ diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py index 7add63252..0c1744977 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/ProjectsAndUnits/test.py @@ -43,7 +43,7 @@ check( root_project="../boolops/boolops", - units=["@%s" % list_to_tmp(["boolops"], dir="tmp_files")], + units=["@%s" % list_to_tmp(["boolops"], dirname="tmp_files")], recurse=True, xreports=["boolops.ads", "boolops.adb"], ) diff --git a/testsuite/SCOV/expgen/generator/utils.py b/testsuite/SCOV/expgen/generator/utils.py index 577d9b106..7e46388c4 100644 --- a/testsuite/SCOV/expgen/generator/utils.py +++ b/testsuite/SCOV/expgen/generator/utils.py @@ -22,7 +22,7 @@ def __init__(self, env, subdir): def __enter__(self): self.env.push_dir(self.subdir) - def __exit__(self, type, value, traceback): + def __exit__(self, exctype, value, traceback): self.env.pop_dir() def __init__(self): diff --git a/testsuite/SCOV/expgen/language/__init__.py b/testsuite/SCOV/expgen/language/__init__.py index 2402c7ce6..472e54f89 100644 --- a/testsuite/SCOV/expgen/language/__init__.py +++ b/testsuite/SCOV/expgen/language/__init__.py @@ -311,7 +311,7 @@ def __init__(self, formatter, addend): def __enter__(self): self.formatter.push_indent(self.addend) - def __exit__(self, type, value, traceback): + def __exit__(self, exptype, value, traceback): self.formatter.pop_indent() diff --git a/testsuite/SCOV/expgen/language/ada/__init__.py b/testsuite/SCOV/expgen/language/ada/__init__.py index ddbdec3fa..af8b80a79 100644 --- a/testsuite/SCOV/expgen/language/ada/__init__.py +++ b/testsuite/SCOV/expgen/language/ada/__init__.py @@ -55,8 +55,8 @@ def __enter__(self): self.language.newline() self.indent_guard.__enter__() - def __exit__(self, type, value, traceback): - self.indent_guard.__exit__(type, value, traceback) + def __exit__(self, exctype, value, traceback): + self.indent_guard.__exit__(exctype, value, traceback) self.language.write("end {};".format(conv_name(self.module_name))) self.language.newline() diff --git a/testsuite/SCOV/expgen/language/c/__init__.py b/testsuite/SCOV/expgen/language/c/__init__.py index 11bc57e9d..726cd3851 100644 --- a/testsuite/SCOV/expgen/language/c/__init__.py +++ b/testsuite/SCOV/expgen/language/c/__init__.py @@ -35,7 +35,7 @@ def __enter__(self): self.language.write("#define {}_H".format(self.module_name.upper())) self.language.newline() - def __exit__(self, type, value, traceback): + def __exit__(self, exctype, value, traceback): self.language.write("#endif") self.language.newline() diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index d1b4d686f..0c576d860 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -20,7 +20,7 @@ def default_dump_trigger(mains): # It does not make sense to have a dump-trigger=ravenscar-task-termination # if the main is not an Ada program. elif ( - all([ext(main) == "adb" for main in mains]) + all(ext(main) == "adb" for main in mains) and RUNTIME_INFO.has_ravenscar_runtime # TODO: There seems to be a problem with light-tasking runtimes and # task-termination, so default back to main end in that case. @@ -46,7 +46,7 @@ def xcov_instrument( gprsw, covlevel, quiet=True, - extra_args=[], + extra_args=None, dump_trigger="auto", dump_channel="auto", gpr_obj_dir=None, @@ -66,7 +66,8 @@ def xcov_instrument( :param None|str covlevel: Coverage level for the instrumentation (--level argument). Not passed if None. :param bool quiet: Whether to pass the "--quiet" flag. - :param list[str] extra_args: Extra arguments to append to the command line. + :param list[str] | None extra_args: Extra arguments to append to the + command line. :param None|str dump_trigger: If None, do not pass the --dump-trigger argument. If "auto", pass the result of default_dump_trigger(). Otherwise, pass the given value. @@ -127,7 +128,7 @@ def xcov_instrument( if runtime_project: args += ["--runtime-project", runtime_project] - args += gprsw.cov_switches + extra_args + args += gprsw.cov_switches + (extra_args or []) if thistest.options.pretty_print: args.append("--pretty-print") @@ -168,7 +169,7 @@ def xcov_instrument( # app.gpr:4:23: warning: object directory "obj" not found messages = re.findall( - pattern="(?:!!!|\*\*\*|warning:).*$", + pattern=r"(?:!!!|\*\*\*|warning:).*$", string=output, flags=re.MULTILINE, ) @@ -240,9 +241,10 @@ def add_dumper_lch_hook(project, obj_dir, subdirs, main_unit): # Unit that contain helper routines to dump coverage buffers. There is one # such unit per main. The only differences between two such units of the - # same project is the name of the main unit which is encoded in the trace (in - # place of the actual executable name). This is not checked by the testsuite - # so there should be no problem using the helper unit of a different main. + # same project is the name of the main unit which is encoded in the trace + # (in place of the actual executable name). This is not checked by the + # testsuite so there should be no problem using the helper unit of a + # different main. auto_dump_hash = None for _, _, files in os.walk( diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index cc4cf14df..8fa68f688 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -38,7 +38,7 @@ from SUITE.context import thistest from SUITE.control import language_info, runtime_info -from SUITE.cutils import ext, to_list, list_to_file, match, no_ext +from SUITE.cutils import ext, to_list, list_to_file, no_ext from SUITE.cutils import contents_of, lines_of, unhandled_exception_in from SUITE.gprutils import GPRswitches from SUITE.tutils import gprbuild, gprfor, xrun, xcov, frame @@ -765,10 +765,12 @@ def run_test(self, main): "exception raised while running '%s'." % main, ) - def gen_one_xcov_report(self, inputs, format, options=""): - """Helper for gen_xcov_reports, to produce one specific report for a - particulat FORMAT, from provided INPUTS. The command output is saved - in a file named FORMAT.out.""" + def gen_one_xcov_report(self, inputs, report_format, options=""): + """ + Helper for gen_xcov_reports, to produce one specific report for a + particular REPORT_FORMAT, from provided INPUTS. The command output is + saved in a file named REPORT_FORMAT.out. + """ # Compute the set of arguments we are to pass to gnatcov coverage. @@ -780,7 +782,7 @@ def gen_one_xcov_report(self, inputs, format, options=""): # descriptions. covargs = ( - ["--annotate=" + format, inputs] + ["--annotate=" + report_format, inputs] + self.covoptions + to_list(options) ) @@ -791,7 +793,7 @@ def gen_one_xcov_report(self, inputs, format, options=""): # Run, latching standard output in a file so we can check contents on # return. - ofile = format + ".out" + ofile = report_format + ".out" xcov(args=["coverage"] + covargs, out=ofile) # Standard output might typically contain labeling warnings issued @@ -873,7 +875,7 @@ def gen_xcov_reports(self): self.gen_one_xcov_report( inputs, - format="report", + report_format="report", options=sco_options + save_checkpoint_options + ["-o", "test.rep"], ) @@ -886,7 +888,7 @@ def gen_xcov_reports(self): if thistest.options.qualif_level: return - self.gen_one_xcov_report(inputs, format="xcov", options=sco_options) + self.gen_one_xcov_report(inputs, report_format="xcov", options=sco_options) def check_unexpected_reports(self): """Check that we don't have unexpected reports or notes.""" @@ -1002,9 +1004,9 @@ def check_expectations(self): r_discharge_kdict = ( { - # let an emitted xBlock1 discharge an xBlock0 expectation, as an - # extra exempted violations are most likely irrelevant for the - # category + # Let an emitted xBlock1 discharge an xBlock0 expectation, as + # an extra exempted violations are most likely irrelevant for + # the category. xBlock0: [xBlock0, xBlock1] } if stricter_level diff --git a/testsuite/SCOV/internals/xnexpanders.py b/testsuite/SCOV/internals/xnexpanders.py index e4f0a8196..33eb450fb 100644 --- a/testsuite/SCOV/internals/xnexpanders.py +++ b/testsuite/SCOV/internals/xnexpanders.py @@ -14,7 +14,6 @@ from SUITE.control import language_info from SUITE.cutils import FatalError, lines_of from .cnotes import ( - Block, KnoteDict, dNoCov, dPartCov, @@ -1153,7 +1152,8 @@ def __parse_expected_rnotes(self, image): # We will use shlex (which is useful for parsing quoted strings). # It enables us to split the given string, according a given separator, # but still preserves quoted text altogether (i.e. if there is a - # separator in some quoted text, it won't be considered as a separator). + # separator in some quoted text, it won't be considered as a + # separator). # # The separator can be a "#", or a ",", so we will split on them. We # will also remove whitespaces (as when splitting, shlex also skips diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 65ca05f5f..2a4853c8a 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -8,7 +8,6 @@ """ import collections -import glob import json import os.path import re @@ -47,14 +46,14 @@ def build_and_run( scos=None, gpr_obj_dir=None, gpr_exe_dir=None, - ignored_source_files=[], + ignored_source_files=None, separate_coverage=None, - extra_args=[], + extra_args=None, extra_run_args=None, extra_instr_args=None, - extra_gprbuild_args=[], - extra_gprbuild_cargs=[], - extra_gprbuild_largs=[], + extra_gprbuild_args=None, + extra_gprbuild_cargs=None, + extra_gprbuild_largs=None, absolute_paths=False, dump_trigger="auto", dump_channel="auto", @@ -101,21 +100,21 @@ def build_and_run( :param None|str gpr_exe_dir: Optional name of the directory where gprbuild will create executables to run. If left to None, assume they are produced in the current directory. - :param list[str] ignored_source_files: List of file patterns to pass using - the --ignore-source-files option. + :param list[str] | None ignored_source_files: List of file patterns to pass + using the --ignore-source-files option. :param None|str separate_coverage: If provided, the argument is forwarded to gnatcov using the -S option. - :param list[str] extra_args: List of arguments to pass to any + :param list[str] | None extra_args: List of arguments to pass to any execution of gnatcov (gnatcov run|instrument|coverage). :param list[str] extra_run_args: List of arguments to pass to all executions of "gnatcov run". :param list[str] extra_instr_args: List of arguments to pass to all executions of "gnatcov instrument". - :param list[str] extra_gprbuild_args: List of arguments to pass to + :param list[str] | None extra_gprbuild_args: List of arguments to pass to gprbuild. - :param list[str] extra_gprbuild_cargs: List of arguments to pass to + :param list[str] | None extra_gprbuild_cargs: List of arguments to pass to gprbuild's -cargs section. - :param list[str] extra_gprbuild_largs: List of arguments to pass to + :param list[str] | None extra_gprbuild_largs: List of arguments to pass to gprbuild's -largs section. :param bool absolute_paths: If true, use absolute paths in the result. :param None|str dump_trigger: See xcov_instrument. @@ -171,9 +170,9 @@ def gprbuild_wrapper(root_project): # Honor build relevant switches from gprsw here gprbuild( root_project, - gargs=gprsw.build_switches + extra_gprbuild_args, - extracargs=extra_gprbuild_cargs, - largs=extra_gprbuild_largs, + gargs=gprsw.build_switches + (extra_gprbuild_args or []), + extracargs=extra_gprbuild_cargs or [], + largs=extra_gprbuild_largs or [], trace_mode=trace_mode, runtime_project=runtime_project, auto_config_args=auto_config_args, @@ -192,6 +191,8 @@ def gprbuild_wrapper(root_project): # through GPR switches: assert not (scos and trace_mode == "src") + extra_args = extra_args or [] + gpr_exe_dir = gpr_exe_dir or "." gpr_obj_dir = gpr_obj_dir or os.path.join(gpr_exe_dir, "obj") @@ -206,6 +207,7 @@ def gprbuild_wrapper(root_project): # Arguments to pass to "gnatcov coverage" (bin trace mode) or "gnatcov # instrument" (src trace mode), in addition to those conveyed by gprsw. + ignored_source_files = ignored_source_files or [] cov_or_instr_args = extra_args + [ "--ignore-source-files={}".format(pattern) for pattern in ignored_source_files @@ -407,7 +409,7 @@ def gprbuild_wrapper(root_project): xcov_args.extend(cov_or_instr_args) else: - assert False, "Unknown trace mode: {}".format(trace_mode) + raise AssertionError("Unknown trace mode: {}".format(trace_mode)) # If provided, pass "gnatcov coverage"-specific project arguments, which # replace the list of SCOS. diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index 376ada6b8..735f5d748 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -77,14 +77,14 @@ def __expand_shared_controllers(self, drivers, cspecs): # possible lists of drivers (each maybe empty). Beware not to include # child or sub units, as these dont mirror as such in the set of test # drivers. - sxx = set( + sxx = { srcmatch.group(1) for srcmatch in ( re.match(r"([a-z_]*).*\.(adb|c)", os.path.basename(src)) for src in ls("src/*") ) if srcmatch - ) + } # If there is no candidate body in src/, arrange to run all the # drivers. This is useful for test groups on GPR variations for diff --git a/testsuite/SUITE/context.py b/testsuite/SUITE/context.py index 60c00a0f6..715da210a 100644 --- a/testsuite/SUITE/context.py +++ b/testsuite/SUITE/context.py @@ -26,7 +26,7 @@ ) from SUITE import control -from SUITE.control import GPRCLEAN, BUILDER, env +from SUITE.control import GPRCLEAN, env from SUITE.cutils import ( exit_if, indent, @@ -349,8 +349,10 @@ def fail_if_diff( failure_message="unexpected output", output_refiners=None, ): - """Wrapper around fail_if_diff_internal, taking an actual_file parameter - instead of an actual string.""" + """ + Wrapper around fail_if_diff_internal, taking an actual_file parameter + instead of an actual string. + """ with open(actual_file, "r") as f: self.fail_if_diff_internal( baseline_file, f.read(), failure_message, output_refiners diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index 21da075de..1e5d5c06c 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -280,7 +280,7 @@ def __init__(self, runtime_name=None): elif self.runtime_name == "kernel": self.has_kernel_runtime = True else: - assert False, "Unknown runtime: {}".format(runtime_name) + raise AssertionError("Unknown runtime: {}".format(runtime_name)) @property def gnatcov_rts_project(self): @@ -370,7 +370,7 @@ def target_info(target=None): class GnatcovInfo: def __init__(self): - p = re.search(pattern="GNATcoverage (\d+)", string=version("gnatcov")) + p = re.search(pattern=r"GNATcoverage (\d+)", string=version("gnatcov")) self._major = int(p.group(1)) if p else None self.has_setup = self.major_at_least(23) diff --git a/testsuite/SUITE/cutils.py b/testsuite/SUITE/cutils.py index 09b9278d0..26d10bccc 100644 --- a/testsuite/SUITE/cutils.py +++ b/testsuite/SUITE/cutils.py @@ -120,19 +120,20 @@ def list_to_file(lines, filename="tmp.list"): return text_to_file("\n".join(lines) + "\n", filename) -def list_to_tmp(lines, dir=None): +def list_to_tmp(lines, dirname=None): """ - Write list LINES to a temporary file in DIR (or the current directory), one - item per line. Return the temporary file name, chosen not to conflict with - already exisiting files. + Write list LINES to a temporary file in DIRNAME (or the current directory), + one item per line. Return the temporary file name, chosen not to conflict + with already exisiting files. """ # By default, create the temporary file in the current working directory. # Make sure the returned path is absolute, so that the result can be used # even after the current working directory changes (which happens often in # testcases). - dir = os.getcwd() if dir is None else os.path.abspath(dir) + dirname = os.getcwd() if dirname is None else os.path.abspath(dirname) return text_to_file( - "\n".join(lines) + "\n", tempfile.mktemp(dir=dir, suffix=".list") + "\n".join(lines) + "\n", + tempfile.mktemp(dir=dirname, suffix=".list"), ) @@ -203,14 +204,14 @@ def ndirs_in(path): return nsplits -def output_of(cmd, dir=None): +def output_of(cmd, dirname=None): """ - Execute CMD and return it's output, switching to DIR before if not None, - and switching back to the original cwd as needed. + Execute CMD and return it's output, switching to DIRNAME before if not + None, and switching back to the original cwd as needed. """ cwd = os.getcwd() - if dir is not None: - cd(dir) + if dirname is not None: + cd(dirname) output = Run(cmd.split()).out cd(cwd) return output @@ -230,16 +231,16 @@ def __init__(self, subdir=None): if subdir: self.to_subdir(subdir) - def to_subdir(self, dir): + def to_subdir(self, dirname): """ - Change the current directory to `dir`, relative to `self`'s home + Change the current directory to `dirname`, relative to `self`'s home directory. Create it if needed, after first removing it. """ self.to_homedir() - if os.path.exists(dir): - shutil.rmtree(dir) - mkdir(dir) - cd(dir) + if os.path.exists(dirname): + shutil.rmtree(dirname) + mkdir(dirname) + cd(dirname) def to_homedir(self): """ diff --git a/testsuite/SUITE/stream_decoder.py b/testsuite/SUITE/stream_decoder.py index ce438d8ae..ab75d78ec 100644 --- a/testsuite/SUITE/stream_decoder.py +++ b/testsuite/SUITE/stream_decoder.py @@ -63,7 +63,7 @@ def read(self, size): :param int size: Number of bytes to read. :rtype: str """ - bytes = self.stream.read(size) + byte_str = self.stream.read(size) if self.enabled: # Two characters per byte and one space in between. Adjust to # account for the maximum indentation. @@ -72,15 +72,15 @@ def read(self, size): reserved_indent = self.max_indent - len(self.label_stack) bytes_part_size += max(0, len(self.INDENT) * reserved_indent) - # Number of lines to represent bytes + # Number of lines to represent byte_str lines_count = ( - len(bytes) + self.BYTES_PER_LINE - 1 + len(byte_str) + self.BYTES_PER_LINE - 1 ) // self.BYTES_PER_LINE for line in range(lines_count): start_byte = line * self.BYTES_PER_LINE end_byte = (line + 1) * self.BYTES_PER_LINE - bytes_slice = bytes[start_byte:end_byte] + bytes_slice = byte_str[start_byte:end_byte] bytes_part = " ".join( "{:02x}".format(b) for b in bytes_slice @@ -92,8 +92,8 @@ def read(self, size): ) self._print("{} | {}".format(bytes_part, ascii_part)) - self.offset += len(bytes) - return bytes + self.offset += len(byte_str) + return byte_str class Struct(object): diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index bf5acd373..7c7d4ae89 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -17,7 +17,7 @@ from e3.fs import cp from e3.os.fs import touch, unixpath, which -from e3.os.process import DEVNULL, Run +from e3.os.process import Run # Expose a few other items as a test util facilities as well @@ -472,7 +472,7 @@ def gprfor( for srcdir in srcdirs_list for src in os.listdir(os.path.join(cwd, srcdir)) ] - langs = set(li.name for li in lang_infos if li) + langs = {li.name for li in lang_infos if li} srcdirs = ", ".join('"%s"' % d for d in srcdirs_list) languages = ", ".join('"%s"' % lang for lang in langs) diff --git a/testsuite/altrun/ccg_native/pre_testsuite.py b/testsuite/altrun/ccg_native/pre_testsuite.py index 89dc11925..c7c0e2460 100644 --- a/testsuite/altrun/ccg_native/pre_testsuite.py +++ b/testsuite/altrun/ccg_native/pre_testsuite.py @@ -169,7 +169,7 @@ def prepare_rts(): ) try: prj_info = json.loads(prj_str) -except: +except Exception: print("failed parsing project info:") print(prj_str) exit(1) diff --git a/testsuite/altrun/trace32/crun.py b/testsuite/altrun/trace32/crun.py index 12d6aac3d..1dc26b07f 100755 --- a/testsuite/altrun/trace32/crun.py +++ b/testsuite/altrun/trace32/crun.py @@ -22,8 +22,8 @@ # --------- # -- log -- # --------- -def log(str): - print("trace32/crun.py:" + str) +def log(msg): + print("trace32/crun.py:" + msg) # ------------- diff --git a/testsuite/altrun/trace32/pre_testsuite.py b/testsuite/altrun/trace32/pre_testsuite.py index 8eb36515a..f34378e68 100644 --- a/testsuite/altrun/trace32/pre_testsuite.py +++ b/testsuite/altrun/trace32/pre_testsuite.py @@ -7,8 +7,8 @@ # --------- # -- log -- # --------- -def log(str): - print("trace32/pre_testsuite.py:" + str) +def log(msg): + print("trace32/pre_testsuite.py:" + msg) altrun_dir_path = os.path.dirname(os.path.realpath(__file__)) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 2c6b66883..9571b8cbf 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -266,12 +266,12 @@ def RE_SUBTREE(re_crit): # option. -def maybe_exec(log, bin, args=None, edir=None): +def maybe_exec(log, binfile, args=None, edir=None): """ - Execute the provided BIN program file, if any. + Execute the provided BINFILE program file, if any. Run this program in the current working directory EDIR is None. Otherwise, - run it in the location where BIN resides if EDIR is "...", or in EDIR's + run it in the location where BINFILE resides if EDIR is "...", or in EDIR's value otherwise. Pass the provided list of ARGS, if any, on the command line. Skip possible @@ -283,20 +283,22 @@ def maybe_exec(log, bin, args=None, edir=None): Return the process object. """ - if not bin: + if not binfile: return - to_run = [sys.executable, bin] if bin.endswith(".py") else [bin] + to_run = ( + [sys.executable, binfile] if binfile.endswith(".py") else [binfile] + ) if args: to_run.extend([arg for arg in args if arg]) if edir == "...": - edir = os.path.dirname(bin) + edir = os.path.dirname(binfile) p = Run(to_run, cwd=edir) - log += "\nRunning hook: {}\n".format(bin) + log += "\nRunning hook: {}\n".format(binfile) log += p.out return p @@ -618,16 +620,16 @@ def set_up(self): self.testcase_cmd = testcase_cmd self.testcase_timeout = timeout - def maybe_exec(self, bin, args=None, edir=None): + def maybe_exec(self, binfile, args=None, edir=None): """ Shortcut for the global maybe_exec. Log the result in ``self.result.log`` and abort the testcase on failure. """ - if not bin: + if not binfile: return - if maybe_exec(self.result.log, bin, args, edir).status != 0: - raise TestAbortWithError("Altrun hook failed ({})".format(bin)) + if maybe_exec(self.result.log, binfile, args, edir).status != 0: + raise TestAbortWithError("Altrun hook failed ({})".format(binfile)) def run(self): mopt = self.env.main_options @@ -943,7 +945,7 @@ def add_test(self, dag): ) # Look for all "test.py" that were generated under this test directory - for dirpath, dirnames, filenames in os.walk(self.test_dir()): + for dirpath, _, filenames in os.walk(self.test_dir()): if "test.py" in filenames: self.add_test_py_run(dag, dirpath, next(indexes)) @@ -1188,7 +1190,7 @@ def set_up(self): # Most SPARK testcases require Ada 2022 - if getattr(args, "spark_tests"): + if args.spark_tests: setattr(args, attr_cargs_ada, cargs_ada + " -gnat2022") # Expect an explicit -gnatec if we're running for qualification @@ -1285,7 +1287,7 @@ def set_up(self): # TODO: re-implement this feature self.n_consecutive_failures = 0 - self.maybe_exec(bin=self.main.args.pre_testsuite, edir="...") + self.maybe_exec(binfile=self.main.args.pre_testsuite, edir="...") # Make testsuite options and the discriminants file available from # testcases. @@ -1293,7 +1295,7 @@ def set_up(self): self.env.discr_file = self._discriminants_log() def tear_down(self): - self.maybe_exec(bin=self.main.args.post_testsuite, edir="...") + self.maybe_exec(binfile=self.main.args.post_testsuite, edir="...") # ----------------------------------- # -- Early comments about this run -- @@ -1573,19 +1575,20 @@ def resolve(carg): # -- altrun hooks & friends -- # ----------------------------- - def maybe_exec(self, bin, args=None, edir=None): + def maybe_exec(self, binfile, args=None, edir=None): """ Shortcut for the global maybe_exec. Log the result in the altrun log file, and abort the testsuite on failure. """ - if not bin: + if not binfile: return log = Log("") - p = maybe_exec(log, bin, args, edir) + p = maybe_exec(log, binfile, args, edir) self._push_altrun(log.log.splitlines()) exit_if( - p.status != 0, "Altrun hook failed ({}):\n{}".format(bin, p.out) + p.status != 0, + "Altrun hook failed ({}):\n{}".format(binfile, p.out), ) def _bin_for(self, base, indir=None): @@ -1634,26 +1637,28 @@ def _setup_altrun_hooks(self): # hook of interest. Switch to the local directory for the setup step, # designed for local operations: - self.maybe_exec(bin=self._bin_for("setup", indir=ctldir), edir=ctldir) + self.maybe_exec( + binfile=self._bin_for("setup", indir=ctldir), edir=ctldir + ) def install_altrun_for(p0, p1=None, binbase=None): """Establish an implicit value for the --P0_P1 command line option if we find a matching binary program in the altrun subdir we are processing. BINBASE provides the binary base name to use.""" - bin = self._bin_for(os.path.join(ctldir, binbase)) + binfile = self._bin_for(os.path.join(ctldir, binbase)) - if not bin: + if not binfile: return attr = altrun_attr_for(p0, p1) exit_if( getattr(self.main.args, attr), - "%s altrun conflicts with explicit --%s" % (bin, attr), + "%s altrun conflicts with explicit --%s" % (binfile, attr), ) - self._push_altrun(["hooking %s to %s" % (attr, bin)]) - setattr(self.main.args, attr, bin) + self._push_altrun(["hooking %s to %s" % (attr, binfile)]) + setattr(self.main.args, attr, binfile) # For the toplevel testsuite driver hooks, map on binaries # matching the command line option names: From 44dbfbba8cf7dca76bc13e82f55b21db8551a36f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 27 Feb 2024 09:59:47 +0100 Subject: [PATCH 0744/1483] CI: add a testsuite run with GNAT 5.04a1 --- .gitlab-ci.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9512c9eae..4a708c69f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -148,6 +148,37 @@ test_src_traces: <<: *artifacts +test_5.04a1_src_traces: + interruptible: true + services: + - image:e3 + - cpu:16 + - mem:16 + stage: test + script: + - *basic_test_setup + + # GNAT 5.04a1 does not ship "ar" nor "ld". Make the ones from stable-gnat + # available as if they were installed system-wide. + - anod install stable-gnat + - STABLE_GNAT_BSN=$(anod eval --primitive=install stable-gnat build_space_name) + - STABLE_GNAT_PREFIX="$ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$STABLE_GNAT_BSN/install" + - mkdir build-essentials + - export PATH="$PWD/build-essentials:$PATH" + - ln -s $STABLE_GNAT_PREFIX/bin/ar build-essentials/ + - ln -s $STABLE_GNAT_PREFIX/x86_64-pc-linux-gnu/bin/ld build-essentials/ + # Test using anod + - anod test gnatcov --minimal -Q5.04a1,src-traces,instr $ACI_TRACK_QUALIFIER + - TEST_BSN=$(anod eval --primitive=test gnatcov -Q5.04a1,src-traces,instr $ACI_TRACK_QUALIFIER build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - e3-testsuite-report + --failure-exit-code 1 + --xunit-output $CI_PROJECT_DIR/xunit_output.xml + --xunit-name src-traces + $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/results/new/ + + <<: *artifacts + test_spark: interruptible: true services: From 08d94c81c2abf434bf656180953cef3169b99709 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 26 Feb 2024 09:16:34 +0100 Subject: [PATCH 0745/1483] Address flake8 warnings in the Qualif testsuite --- .../GnatcovSwitches/Commands/test.py | 96 ++++++++++--------- .../GPR/GprsOfInterest/test.py | 4 +- .../UnitsOfInterest/GPR/InnerAttr/test.py | 6 +- .../GPR/Robustness/NoContribPrj/test.py | 26 +++-- testsuite/REST/rest.py | 10 +- testsuite/STR/conf.py | 4 +- testsuite/STR/genrest.py | 22 ++--- 7 files changed, 88 insertions(+), 80 deletions(-) diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py index 99e66074c..13a3bd6fd 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py @@ -17,14 +17,16 @@ # file for a simple program. -def gprvariant(id, extra): - return gprfor(prjid=id, srcdirs=["../src"], mains=["p.adb"], extra=extra) +def gprvariant(prjid, extra): + return gprfor( + prjid=prjid, srcdirs=["../src"], mains=["p.adb"], extra=extra + ) exe = exepath_to("p") # Build once -gprbuild(gprvariant(id="bld", extra="")) +gprbuild(gprvariant(prjid="bld", extra="")) # ------------------------------------------------ # -- Simple helpers for coverage/run variations -- @@ -34,19 +36,19 @@ def gprvariant(id, extra): # --annotate, valid only for gnatcov coverage. -def tag_for(id): - return "tag-%s" % id +def tag_for(prjid): + return "tag-%s" % prjid -def tagopt_for(id): - return ["--tag=%s" % tag_for(id)] +def tagopt_for(prjid): + return ["--tag=%s" % tag_for(prjid)] -def rep_for(id): - return "%s.rep" % id +def rep_for(prjid): + return "%s.rep" % prjid -def annopt_for(id): +def annopt_for(prjid): return ["--annotate=report"] @@ -54,29 +56,29 @@ def annopt_for(id): lev = "stmt+decision" -def levopt_for(id): +def levopt_for(prjid): return ["--level=%s" % lev] -def try_run(id, gpr): +def try_run(prjid, gpr): """gnatcov run with common set of options & variations via gpr.""" - log = id + ".rlog" + log = prjid + ".rlog" xrun( - ["-P%s" % gpr, exe, "-o", "%s.trace" % id], + ["-P%s" % gpr, exe, "-o", "%s.trace" % prjid], out=log, register_failure=False, ) return contents_of(log) -def try_cov(id, gpr): +def try_cov(prjid, gpr): """ gnatcov coverage with common set of options & variations via gpr. Expect valid options and check for commonly expected outcome """ - log = id + ".clog" + log = prjid + ".clog" xcov( - ["coverage", "-P%s" % gpr, "%s.trace" % id, "-o", rep_for(id)], + ["coverage", "-P%s" % gpr, "%s.trace" % prjid, "-o", rep_for(prjid)], out=log, register_failure=False, ) @@ -88,75 +90,75 @@ def try_cov(id, gpr): # * options intended for coverage do get there and not to run thistest.fail_if(not empty(log), "unexpected contents in %s" % log) - rep = contents_of(rep_for(id)) + rep = contents_of(rep_for(prjid)) thistest.fail_if( "level: %s" % lev not in rep, - "missing expected level indication in %s" % rep_for(id), + "missing expected level indication in %s" % rep_for(prjid), ) thistest.fail_if( - not re.search("tag.*: %s" % tag_for(id), rep), - "missing expected tag indication in %s" % rep_for(id), + not re.search("tag.*: %s" % tag_for(prjid), rep), + "missing expected tag indication in %s" % rep_for(prjid), ) -def check_valid_sequence_for(id, gprcov): +def check_valid_sequence_for(prjid, gprcov): """ Common checking sequence for a specific gpr coverage package with valid options for both run and coverage. """ - gpr = gprvariant(id=id, extra=gprcov) - try_run(id, gpr) - try_cov(id, gpr) + gpr = gprvariant(prjid=prjid, extra=gprcov) + try_run(prjid, gpr) + try_cov(prjid, gpr) # Basic check for starters. No "*". -id = "basic" +prjid = "basic" check_valid_sequence_for( - id=id, + prjid=prjid, gprcov=gprcov_for( switches=[ - Csw("run", tagopt_for(id)), - Csw("coverage", levopt_for(id) + annopt_for(id)), + Csw("run", tagopt_for(prjid)), + Csw("coverage", levopt_for(prjid) + annopt_for(prjid)), ] ), ) # Check that "*" applies to all. Pass --level there. -id = "star_valid" +prjid = "star_valid" check_valid_sequence_for( - id=id, + prjid=prjid, gprcov=gprcov_for( switches=[ - Csw("*", levopt_for(id)), - Csw("run", tagopt_for(id)), - Csw("coverage", annopt_for(id)), + Csw("*", levopt_for(prjid)), + Csw("run", tagopt_for(prjid)), + Csw("coverage", annopt_for(prjid)), ] ), ) # Check that command specific args prevail over "*", with "*" placed # before in the gpr file. -id = "star_postover" +prjid = "star_postover" check_valid_sequence_for( - id=id, + prjid=prjid, gprcov=gprcov_for( switches=[ Csw("*", ["--level=stmt+mcdc"]), - Csw("run", tagopt_for(id)), - Csw("coverage", levopt_for(id) + annopt_for(id)), + Csw("run", tagopt_for(prjid)), + Csw("coverage", levopt_for(prjid) + annopt_for(prjid)), ] ), ) # Likewise, with "*" placed after in the gpr file. -id = "star_preover" +prjid = "star_preover" check_valid_sequence_for( - id=id, + prjid=prjid, gprcov=gprcov_for( switches=[ - Csw("run", tagopt_for(id)), - Csw("coverage", levopt_for(id) + annopt_for(id)), + Csw("run", tagopt_for(prjid)), + Csw("coverage", levopt_for(prjid) + annopt_for(prjid)), Csw("*", ["--level=stmt+mcdc"]), ] ), @@ -164,13 +166,15 @@ def check_valid_sequence_for(id, gprcov): # Check that "*" applies to all. Pass invalid for run, check failure. -id = "star_invalid" -gpr = gprvariant(id=id, extra=gprcov_for(switches=[Csw("*", annopt_for(id))])) -rlog = try_run(id, gpr) +prjid = "star_invalid" +gpr = gprvariant( + prjid=prjid, extra=gprcov_for(switches=[Csw("*", annopt_for(prjid))]) +) +rlog = try_run(prjid, gpr) thistest.fail_if( '--annotate is not valid with the "run" command.' not in rlog, - "missing expected failure indication in run log for %s" % id, + "missing expected failure indication in run log for %s" % prjid, ) thistest.result() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py index 39aee8d1b..745ddf0a4 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py @@ -103,10 +103,10 @@ def check(options, xunits): # Map the report files to a set of units by stripping both the leading # subdir part and the extension. - runits = set( + runits = { os.path.basename(r).split(".")[0] for r in e3.fs.ls(os.path.join(odir, "*.xcov")) - ) + } thistest.fail_if( runits != xunits, diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py index b22dece24..c1a3c0285 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py @@ -1,7 +1,7 @@ from SCOV.tc import TestCase from SCOV.tctl import CovControl from SUITE.context import thistest -from SUITE.cutils import Wdir, list_to_file +from SUITE.cutils import Wdir from SUITE.tutils import gprfor from SUITE.gprutils import gprcov_for @@ -14,9 +14,7 @@ def check(subdir, opspkg, xreports): ops_gpr = gprfor(mains=[], prjid="ops", srcdirs="../src/ops", extra=opspkg) TestCase(category=None).run( - covcontrol=CovControl( - deps=["../ops.gpr"], units_in=[], xreports=xreports - ) + covcontrol=CovControl(deps=[ops_gpr], units_in=[], xreports=xreports) ) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py index be275fecd..629fd7bca 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py @@ -48,10 +48,10 @@ def run_test( main, helper, recursive, - projects=[], - units=[], - projects_warned=[], - expected_cov_list=[], + projects=None, + units=None, + projects_warned=None, + expected_cov_list=None, ): """ Produce a coverage report for the given parameters and check the emitted @@ -63,12 +63,17 @@ def run_test( :param ProjectConfig main: Configuration for the "main" project. :param ProjectConfig helper: Configuration for the "helper" project. :param bool recursive: Whether to not pass --no-subprojects. - :param list[str] projects: List of projects to pass with --projects. - :param list[str] units: List of units to pass with --units. - :param list[str] projects_warned: List of projects for which we expected - warnings. + :param list[str] | None projects: List of projects to pass with --projects. + :param list[str] | None units: List of units to pass with --units. + :param list[str] | None projects_warned: List of projects for which we + expected warnings. :param expected_cov: List of expected coverage reports. """ + projects = projects or [] + units = units or [] + projects_warned = projects_warned or [] + expected_cov_list = expected_cov_list or [] + thistest.log("== [{}] {} ==".format(slug, label)) tmp.to_subdir("wd_/{}".format(slug)) @@ -115,8 +120,9 @@ def run_test( ) expected_cov = {} - for c in expected_cov_list: - expected_cov.update(c) + if expected_cov_list: + for c in expected_cov_list: + expected_cov.update(c) check_xcov_reports("obj-main", expected_cov) # Check that all xcov report files are created in obj-main (i.e. the root diff --git a/testsuite/REST/rest.py b/testsuite/REST/rest.py index 3eaca3606..4e691f46b 100644 --- a/testsuite/REST/rest.py +++ b/testsuite/REST/rest.py @@ -30,18 +30,20 @@ def strong(content): return "**" + content + "**" -def list(content, pre=1, post=1): +def list(content, pre=1, post=1): # noqa: A001 return isolate( - pre=pre, text="\n".join([" * %s" % l for l in content]), post=post + pre=pre, + text="\n".join([" * %s" % line for line in content]), + post=post, ) -def toctree(l, depth=2): +def toctree(lines, depth=2): return isolate( pre=1, text="\n".join( [".. toctree::", " :maxdepth: %s\n" % depth] - + [" %s" % item for item in l] + + [" %s" % item for item in lines] ), post=1, ) diff --git a/testsuite/STR/conf.py b/testsuite/STR/conf.py index 516437106..c97058097 100644 --- a/testsuite/STR/conf.py +++ b/testsuite/STR/conf.py @@ -334,10 +334,12 @@ def project_settings(): # latex_domain_indices = True -# -- Options for manual page output -------------------------------------------- +# -- Options for manual page output ------------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ ("content", "gnatcoverage", "GNATcoverage Documentation", ["AdaCore"], 1) ] + +# flake8: noqa diff --git a/testsuite/STR/genrest.py b/testsuite/STR/genrest.py index b71a42806..6af4839c2 100644 --- a/testsuite/STR/genrest.py +++ b/testsuite/STR/genrest.py @@ -417,7 +417,7 @@ def __init__(self, filename): self.fd = None self.open(filename) - def open(self, filename): + def open(self, filename): # noqa: A003 self.fd = open("source/" + filename, "w") def write(self, text, pre=0, post=1): @@ -577,7 +577,7 @@ def __compute_widths(self): # This is useful to align the text of every column, for both # content rows and the ReST table separation lines. - self.width = dict([(col, 0) for col in self.columns]) + self.width = {col: 0 for col in self.columns} # Maximize column width over contents entries @@ -794,7 +794,7 @@ def __init__(self, options): # were run). This is useful e.g. to decide which sets of compilation # options should be displayed in the environment description items. - self.languages = set([cat.lang for cat in lang_categories if cat.qdl]) + self.languages = {cat.lang for cat in lang_categories if cat.qdl} self.dump_trigger = None self.dump_channel = None @@ -921,7 +921,7 @@ def tcdata_for(self, qd): return this_tcdata def compute_tcdata(self): - self.tcdata = dict([(qd, self.tcdata_for(qd)) for qd in self.qdl]) + self.tcdata = {qd: self.tcdata_for(qd) for qd in self.qdl} # ------------------ # -- gen_tctables -- @@ -942,12 +942,10 @@ def tcdict_for(self, qd): details = column_for[qd.status] != colid.passed - return dict( - [ - (col, "%s" % self.tcdata[qd][col].img(details)) - for col in self.tcdata[qd] - ] - ) + return { + col: "%s" % self.tcdata[qd][col].img(details) + for col in self.tcdata[qd] + } def gen_tctables(self, sepfile=None): if sepfile: @@ -1128,9 +1126,7 @@ def sumcontents(self): # table, with a list entry for each test category (+ total) return [ - dict( - [(col, "%s" % catsum[col].img()) for col in self.sumcolumns()] - ) + {col: "%s" % catsum[col].img() for col in self.sumcolumns()} for catsum in self.sumdata() ] From 788d18afdba6178633054be64f1ee0863063d3e9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 26 Feb 2024 10:06:07 +0100 Subject: [PATCH 0746/1483] Address flake8 issues in the regular testsuite --- .../tests/106-externally-built-header/test.py | 9 ++---- testsuite/tests/15-non-instr-cons/test.py | 4 ++- testsuite/tests/185-setup-warnings/test.py | 3 -- testsuite/tests/207-srctrace-version/test.py | 7 ++--- .../tests/222-subp-of-interest-cplx/test.py | 12 ++++---- .../Ada2022/aggregates/containers/test.py | 4 +-- testsuite/tests/Disassemblers/test.py | 2 +- testsuite/tests/LA23-016_eargs-exe/test.py | 30 +++++++++---------- .../tests/M625-040-slow_on_windows/test.py | 8 ++--- .../tests/MB15-041-verbose-open-crc32/test.py | 12 ++++---- .../OA27-059-separate-consolidation/test.py | 2 +- .../tests/P526-035-origin-project/test.py | 4 +-- testsuite/tests/R404-023-object-stats/test.py | 2 +- testsuite/tests/RB13-019-win-paths/test.py | 16 +++------- testsuite/tests/T629-012-pragmas/test.py | 4 +-- .../tests/TC11-052-internal-error/test.py | 8 +++-- .../U204-029-source-rebase/test_support.py | 3 +- .../VA04-023-non-instr-sco-reloc/test.py | 4 ++- .../tests/VB07-015-clean-output-dir/test.py | 12 ++++---- testsuite/tests/asm-consolidate/test.py | 4 +-- testsuite/tests/cobertura_validation/test.py | 4 +-- testsuite/tests/ignored-c-file/test.py | 2 +- .../tests/instr-cov/208-no-secsta/test.py | 2 -- .../tests/instr-cov/216-no-elab-all/test.py | 2 -- .../instr-cov/217-runtime-subunit/test.py | 4 +-- .../instr-cov/218-missing-pkg-spec/test.py | 2 -- .../219-non-instr-propagation/test.py | 2 -- .../instr-cov/225-expr-func-access/test.py | 2 -- .../tests/instr-cov/227-subunit-stub/test.py | 2 +- .../instr-cov/C++/109-pp-switches/test.py | 3 +- .../VB03-024-preprocess-included-proj/test.py | 4 +-- .../tests/instr-cov/c_multiline_stmt/test.py | 2 -- .../instr-cov/compile_time_pragma/test.py | 3 -- .../tests/instr-cov/config_custom_db/test.py | 2 -- .../instr-cov/entry_guards/restricted/test.py | 2 +- .../instr-cov/expr_func/ada_2022/test.py | 4 +-- .../tests/instr-cov/expr_func/generic/test.py | 4 ++- .../tests/instr-cov/file-context/test.py | 4 +-- testsuite/tests/instr-cov/gpr-complex/test.py | 1 - .../main_autodump/nested_block/test.py | 4 +-- .../instr-cov/manual-dump/ada_subprj/test.py | 5 +--- .../instr-cov/manual-dump/trace_index/test.py | 2 +- .../instr-cov/missing-runtime-dir/test.py | 2 +- .../tests/instr-cov/multi_unit_source/test.py | 4 +-- .../instr-cov/pragma_ghost_predicate/test.py | 5 ---- .../integrated_instrumentation/no_uoi/test.py | 3 +- testsuite/tests/subp_of_interest/test.py | 4 +-- 47 files changed, 97 insertions(+), 133 deletions(-) diff --git a/testsuite/tests/106-externally-built-header/test.py b/testsuite/tests/106-externally-built-header/test.py index 172fc50ba..fb4cd94aa 100644 --- a/testsuite/tests/106-externally-built-header/test.py +++ b/testsuite/tests/106-externally-built-header/test.py @@ -7,18 +7,15 @@ """ import os.path -import re -import shutil -from e3.fs import cp, rm +from e3.fs import cp -from SCOV.instr import xcov_instrument from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.control import env -from SUITE.cutils import Wdir, contents_of, indent +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches -from SUITE.tutils import gprfor, gprbuild, gprinstall, xcov +from SUITE.tutils import gprfor, gprbuild, gprinstall tmp = Wdir("tmp_") diff --git a/testsuite/tests/15-non-instr-cons/test.py b/testsuite/tests/15-non-instr-cons/test.py index 6377b2ffb..50c57c057 100644 --- a/testsuite/tests/15-non-instr-cons/test.py +++ b/testsuite/tests/15-non-instr-cons/test.py @@ -27,7 +27,9 @@ covlevel="stmt", mains=["test_f", "test_t"], trace_mode="src", - tolerate_instrument_messages="gnatcov limitation: cannot instrument an expression function", + tolerate_instrument_messages=( + "gnatcov limitation: cannot instrument an expression function" + ), ) trace_t = xcov_args.pop() diff --git a/testsuite/tests/185-setup-warnings/test.py b/testsuite/tests/185-setup-warnings/test.py index 132b1c185..3acd3af8f 100644 --- a/testsuite/tests/185-setup-warnings/test.py +++ b/testsuite/tests/185-setup-warnings/test.py @@ -3,9 +3,6 @@ directories when loading the "gnatcov_rts.gpr" project file. """ -import os -import os.path - from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of from SUITE.tutils import xcov diff --git a/testsuite/tests/207-srctrace-version/test.py b/testsuite/tests/207-srctrace-version/test.py index 4480711d7..bde6dab78 100644 --- a/testsuite/tests/207-srctrace-version/test.py +++ b/testsuite/tests/207-srctrace-version/test.py @@ -5,14 +5,10 @@ gnatcov version, force the user to update the trace. """ -import os -import os.path - from SCOV.minicheck import xcov, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of from SUITE.tutils import gprfor -from SUITE.gprutils import GPRswitches tmp = Wdir("tmp_") @@ -58,7 +54,8 @@ thistest.failed( "Update the trace and SIDs in this test to the latest" " format to make test pass again.\n" - "This is simply a matter of running './update.sh' in the test directory." + "This is simply a matter of running './update.sh' in the test" + " directory." ) # Otherwise, check the coverage report diff --git a/testsuite/tests/222-subp-of-interest-cplx/test.py b/testsuite/tests/222-subp-of-interest-cplx/test.py index 80415e62b..e319f7244 100644 --- a/testsuite/tests/222-subp-of-interest-cplx/test.py +++ b/testsuite/tests/222-subp-of-interest-cplx/test.py @@ -24,12 +24,12 @@ When initiating the traversal, Next_SE point to the scope for the whole CU, which contains the SCO of interest. The traversal then moves to the next - one, which is the scope for Zero. This does not contain SCO, so the traversal - stops, and current_SE thus points to the scope for the whole CU. While it is - true that this scope contains SCO, it is not the deepest one. The current - scope in the traversal is then checked against the set of scopes of interest, - which only consist in the scope for One, so this returns False. The coverage - information is then wrongfully discarded. + one, which is the scope for Zero. This does not contain SCO, so the + traversal stops, and current_SE thus points to the scope for the whole CU. + While it is true that this scope contains SCO, it is not the deepest one. + The current scope in the traversal is then checked against the set of scopes + of interest, which only consist in the scope for One, so this returns False. + The coverage information is then wrongfully discarded. This test checks both bugs. """ diff --git a/testsuite/tests/Ada2022/aggregates/containers/test.py b/testsuite/tests/Ada2022/aggregates/containers/test.py index e755dd8c5..54724f7a9 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/test.py +++ b/testsuite/tests/Ada2022/aggregates/containers/test.py @@ -1,6 +1,6 @@ """ -Test correct handling and instrumentation of container aggregates, and decisions -nested within. +Test correct handling and instrumentation of container aggregates, and +decisions nested within. """ from SCOV.tc import TestCase diff --git a/testsuite/tests/Disassemblers/test.py b/testsuite/tests/Disassemblers/test.py index 6061ef3a7..b12b12503 100644 --- a/testsuite/tests/Disassemblers/test.py +++ b/testsuite/tests/Disassemblers/test.py @@ -90,7 +90,7 @@ def is_asm(filename): path = os.path.join(tmp.homedir, test_dir) tmp_sub = Wdir(test_dir) - testcases = list(sorted(filter(is_asm, os.listdir(path)))) + testcases = sorted(filter(is_asm, os.listdir(path))) # Prepare object file from assembly sources. project = gprfor(testcases, srcdirs=path, main_cargs=tc.cargs) diff --git a/testsuite/tests/LA23-016_eargs-exe/test.py b/testsuite/tests/LA23-016_eargs-exe/test.py index f00664f02..5a88c01aa 100644 --- a/testsuite/tests/LA23-016_eargs-exe/test.py +++ b/testsuite/tests/LA23-016_eargs-exe/test.py @@ -13,20 +13,20 @@ # both work and produce the same result. -def run_check(id, args): - rlog = id + ".rlog" - trace = id + ".trace" +def run_check(slug, args): + rlog = slug + ".rlog" + trace = slug + ".trace" xrun(["-o", trace] + args, out=rlog) thistest.fail_if( not empty(rlog) and not match("/runkernel", rlog), - "unexpected output from %s run:\n%s" % (id, contents_of(rlog)), + "unexpected output from %s run:\n%s" % (slug, contents_of(rlog)), ) -def cov_check(id): - clog = id + ".clog" - trace = id + ".trace" - rep = id + ".rep" +def cov_check(slug): + clog = slug + ".clog" + trace = slug + ".trace" + rep = slug + ".rep" xcov( [ "coverage", @@ -47,17 +47,17 @@ def cov_check(id): thistest.fail_if( not empty(clog), - "unexpected output from %s coverage :\n%s" % (id, contents_of(clog)), + "unexpected output from %s coverage :\n%s" % (slug, contents_of(clog)), ) -id = "base" -run_check(id, args=[exe]) -cov_check(id) +slug = "base" +run_check(slug, args=[exe]) +cov_check(slug) -id = "eargs" -run_check(id, args=["-eargs", exe]) -cov_check(id) +slug = "eargs" +run_check(slug, args=["-eargs", exe]) +cov_check(slug) # Check that a bare "xcov run" complains about absence of executable # on the command line. diff --git a/testsuite/tests/M625-040-slow_on_windows/test.py b/testsuite/tests/M625-040-slow_on_windows/test.py index ef8842ae3..5bb4c9501 100644 --- a/testsuite/tests/M625-040-slow_on_windows/test.py +++ b/testsuite/tests/M625-040-slow_on_windows/test.py @@ -13,7 +13,7 @@ def run(action, repeat, tag): start = time.clock() - for i in range(repeat): + for _ in range(repeat): action() end = time.clock() print("%s: %2.5f" % (tag, end - start)) @@ -27,7 +27,7 @@ def eval_xrun(): run(action=lambda: xrun(exename_for("p")), repeat=50, tag="xrun") -def eval(what): +def profile(what): profiler = cProfile.Profile() profiler.run("eval_%s()" % what) @@ -48,7 +48,7 @@ def eval(what): ps.print_callees() -eval("gprbuild") -eval("xrun") +profile("gprbuild") +profile("xrun") thistest.result() diff --git a/testsuite/tests/MB15-041-verbose-open-crc32/test.py b/testsuite/tests/MB15-041-verbose-open-crc32/test.py index e9ff8ca25..63ac31221 100644 --- a/testsuite/tests/MB15-041-verbose-open-crc32/test.py +++ b/testsuite/tests/MB15-041-verbose-open-crc32/test.py @@ -39,8 +39,8 @@ def list_to_text(items): def check_same_files(expected, found): - expected = set(unixpath(path) for path in expected) - found = set(unixpath(path) for path in found) + expected = {unixpath(path) for path in expected} + found = {unixpath(path) for path in found} thistest.fail_if( expected != found, "Expecting:\n{}" @@ -55,7 +55,7 @@ def check_logging(log_file, expected_files): """ # Rebase all input path to the temporary directory. base = os.getcwd() - expected_files = set(os.path.join(base, path) for path in expected_files) + expected_files = {os.path.join(base, path) for path in expected_files} checksums = {} gnatcov_cwd = None @@ -88,9 +88,9 @@ def check_logging(log_file, expected_files): expected_checksum = crc32(fp.read()) & 0xFFFFFFFF thistest.fail_if( expected_checksum != checksum, - "Bad checksum for {}: expecting CRC32={:#08x}, but found {:#08x}".format( - filename, expected_checksum, checksum - ), + f"Bad checksum for {filename}:" + f" expecting CRC32={expected_checksum:#08x}," + f" but found {checksum:#08x}", ) diff --git a/testsuite/tests/OA27-059-separate-consolidation/test.py b/testsuite/tests/OA27-059-separate-consolidation/test.py index 26f4f6685..4d02afd45 100644 --- a/testsuite/tests/OA27-059-separate-consolidation/test.py +++ b/testsuite/tests/OA27-059-separate-consolidation/test.py @@ -55,7 +55,7 @@ def clean_output_directory(): testcases = [test1, test2] -def build_and_run_tests(ignored_source_files=[]): +def build_and_run_tests(ignored_source_files=None): """ Build the test material: program and traces. """ diff --git a/testsuite/tests/P526-035-origin-project/test.py b/testsuite/tests/P526-035-origin-project/test.py index 6663661b5..264e2c628 100644 --- a/testsuite/tests/P526-035-origin-project/test.py +++ b/testsuite/tests/P526-035-origin-project/test.py @@ -19,9 +19,9 @@ def xcov_list(): """ Return the list of *.xcov files in the "obj" subdirectory. """ - return set( + return { os.path.basename(f) for f in glob.glob(os.path.join("obj", "*.xcov")) - ) + } def clean_xcov(): diff --git a/testsuite/tests/R404-023-object-stats/test.py b/testsuite/tests/R404-023-object-stats/test.py index 9da7f3110..47c516f88 100644 --- a/testsuite/tests/R404-023-object-stats/test.py +++ b/testsuite/tests/R404-023-object-stats/test.py @@ -30,7 +30,7 @@ 1 fully covered 2 partially covered 1 not executed""" -result = "\n".join(l.rstrip() for l in lines[-7:]) +result = "\n".join(line.rstrip() for line in lines[-7:]) thistest.fail_if( baseline != result, diff --git a/testsuite/tests/RB13-019-win-paths/test.py b/testsuite/tests/RB13-019-win-paths/test.py index 233634a81..11bafbbf6 100644 --- a/testsuite/tests/RB13-019-win-paths/test.py +++ b/testsuite/tests/RB13-019-win-paths/test.py @@ -7,7 +7,6 @@ """ import os.path -import shutil from e3.fs import cp from e3.os.process import PIPE, Run, STDOUT @@ -16,14 +15,7 @@ from SUITE.control import env from SUITE.cutils import FatalError, Wdir from SUITE.gprutils import GPRswitches -from SUITE.tutils import ( - exepath_to, - gprfor, - thistest, - tracename_for, - xcov, - xrun, -) +from SUITE.tutils import gprfor, thistest tmp = Wdir("tmp_") @@ -47,9 +39,9 @@ "-fdump-scos", "-g", "-save-temps", - # TODO??? This is necessary in order to have the C sources build - # with an arm-elf toolchain and a stm32f4 RTS, it is not clear if - # we could make this more generic. + # TODO??? This is necessary in order to have the C sources + # build with an arm-elf toolchain and a stm32f4 RTS, it is + # not clear if we could make this more generic. "-mlittle-endian", "-mfloat-abi=hard", "-mcpu=cortex-m4", diff --git a/testsuite/tests/T629-012-pragmas/test.py b/testsuite/tests/T629-012-pragmas/test.py index 067cb8b9f..c18e8ea8d 100644 --- a/testsuite/tests/T629-012-pragmas/test.py +++ b/testsuite/tests/T629-012-pragmas/test.py @@ -11,11 +11,11 @@ # Get the list of pragmas that gnatcov knows xcov(["dump-pragmas"], out="gnatcov.txt") -gnatcov_names = set(line.strip() for line in lines_of("gnatcov.txt")) +gnatcov_names = {line.strip() for line in lines_of("gnatcov.txt")} # Get the list of pragmas that GNAT knows xcov(["dump-pragmas", "--gnat-pragmas"], out="gnat.txt") -gnat_names = set(line.strip() for line in lines_of("gnat.txt")) +gnat_names = {line.strip() for line in lines_of("gnat.txt")} # Check that gnatcov knows about all pragmas from gnat_util missing_names = "\n".join(sorted(gnat_names - gnatcov_names)) diff --git a/testsuite/tests/TC11-052-internal-error/test.py b/testsuite/tests/TC11-052-internal-error/test.py index 0cd9a7d74..cb89be2b8 100644 --- a/testsuite/tests/TC11-052-internal-error/test.py +++ b/testsuite/tests/TC11-052-internal-error/test.py @@ -22,6 +22,7 @@ def check(args, trigger, info): p.status == 0, "gnatcov returned success exit code, error expected" ) + trigger_msg = trigger.upper().replace("-", "_") expected_output = re.compile( "\n".join( [ @@ -29,10 +30,11 @@ def check(args, trigger, info): "== gnatcov bug detected ==", "", "gnatcov just encountered an internal error:", - f"raised CONSTRAINT_ERROR : {trigger.upper().replace('-', '_')}", + f"raised CONSTRAINT_ERROR : {trigger_msg}", # Depending on how gnatcov is built, exception info may contain # stack traces. - "((Load address: [x0-9a-f]+\n)?Call stack traceback locations:", + "((Load address: [x0-9a-f]+\n)?Call stack traceback" + " locations:", "[x0-9a-f ]+", ")?", "", @@ -104,7 +106,7 @@ def check(args, trigger, info): check( args=xcov_args, trigger="load-checkpoint", - info="Loading [^\n]*main\.sid", + info=r"Loading [^\n]*main\.sid", ) thistest.result() diff --git a/testsuite/tests/U204-029-source-rebase/test_support.py b/testsuite/tests/U204-029-source-rebase/test_support.py index 1cccfbf2f..7c6c23c79 100644 --- a/testsuite/tests/U204-029-source-rebase/test_support.py +++ b/testsuite/tests/U204-029-source-rebase/test_support.py @@ -69,7 +69,8 @@ def consolidate_and_check( if expect_failure: thistest.fail_if_no_match( - f"'gnatcov coverage' output ({variant_basename}-{output_dir_name})", + "'gnatcov coverage' output" + f" ({variant_basename}-{output_dir_name})", r"^(warning: can't open .*\n)+$", contents_of(log_filename), ) diff --git a/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py index 6fca30fc1..eedd88380 100644 --- a/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py +++ b/testsuite/tests/VA04-023-non-instr-sco-reloc/test.py @@ -28,7 +28,9 @@ covlevel="stmt+mcdc", mains=["main"], trace_mode="src", - tolerate_instrument_messages="cannot instrument generic expression function", + tolerate_instrument_messages=( + "cannot instrument generic expression function" + ), ) check_xcov_reports( diff --git a/testsuite/tests/VB07-015-clean-output-dir/test.py b/testsuite/tests/VB07-015-clean-output-dir/test.py index 73a90627d..132c79805 100644 --- a/testsuite/tests/VB07-015-clean-output-dir/test.py +++ b/testsuite/tests/VB07-015-clean-output-dir/test.py @@ -31,12 +31,12 @@ def check_one(units, output_dir, xcov_args): directories that are not output_dir contain no .xcov files. """ xcov(xcov_args) - for dir in possible_output_dirs: - thistest.log(f"inspecting {dir}") + for dirname in possible_output_dirs: + thistest.log(f"inspecting {dirname}") check_xcov_reports( - dir, + dirname, {f"{unit}.xcov": expected_cov[unit] for unit in units} - if dir == output_dir + if dirname == output_dir else {}, ) @@ -50,8 +50,8 @@ def check_one(units, output_dir, xcov_args): ) # Create the possible output dirs -for dir in possible_output_dirs: - mkdir(os.path.join(os.getcwd(), dir)) +for dirname in possible_output_dirs: + mkdir(os.path.join(os.getcwd(), dirname)) # First, produce a report for all units, with a single report format specified thistest.log("=== Step 1: all units in obj ===") diff --git a/testsuite/tests/asm-consolidate/test.py b/testsuite/tests/asm-consolidate/test.py index f12fd96c8..d9f010201 100644 --- a/testsuite/tests/asm-consolidate/test.py +++ b/testsuite/tests/asm-consolidate/test.py @@ -29,10 +29,10 @@ libsym = target_info().to_platform_specific_symbol("lib__adjust") -def address_range_for(symname, bin): +def address_range_for(symname, binfile): m = re.search( pattern=r"(?P\S*-\S*) symbol for %s" % symname, - string=xcov(["dump-symbols", bin]).out, + string=xcov(["dump-symbols", binfile]).out, ) return m.group("address_range") diff --git a/testsuite/tests/cobertura_validation/test.py b/testsuite/tests/cobertura_validation/test.py index 64efeb271..20873cfb2 100644 --- a/testsuite/tests/cobertura_validation/test.py +++ b/testsuite/tests/cobertura_validation/test.py @@ -97,8 +97,8 @@ def build_run_coverage_and_check( expected_filenames=expected_filenames, ) -# Check that the report can be emitted in the absence of the project sources. We -# have to rely on sid files to convey the coverage obligations +# Check that the report can be emitted in the absence of the project sources. +# We have to rely on sid files to convey the coverage obligations thistest.log("== Report with no sources ==") # No pkg.ads in the report as there are no coverage obligations for it expected_filenames = {"lib.c", "pkg.adb", "test.adb"} diff --git a/testsuite/tests/ignored-c-file/test.py b/testsuite/tests/ignored-c-file/test.py index cdb998468..b0200b7cb 100644 --- a/testsuite/tests/ignored-c-file/test.py +++ b/testsuite/tests/ignored-c-file/test.py @@ -5,7 +5,7 @@ from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.gprutils import GPRswitches -from SUITE.cutils import contents_of, Wdir +from SUITE.cutils import Wdir from SUITE.tutils import thistest, gprfor Wdir("tmp_") diff --git a/testsuite/tests/instr-cov/208-no-secsta/test.py b/testsuite/tests/instr-cov/208-no-secsta/test.py index 721fd62be..e9cf5d315 100644 --- a/testsuite/tests/instr-cov/208-no-secsta/test.py +++ b/testsuite/tests/instr-cov/208-no-secsta/test.py @@ -3,8 +3,6 @@ instrumentation. """ -import os.path - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir diff --git a/testsuite/tests/instr-cov/216-no-elab-all/test.py b/testsuite/tests/instr-cov/216-no-elab-all/test.py index 01d1093df..1154302db 100644 --- a/testsuite/tests/instr-cov/216-no-elab-all/test.py +++ b/testsuite/tests/instr-cov/216-no-elab-all/test.py @@ -3,8 +3,6 @@ instrumentation. """ -import os.path - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/test.py b/testsuite/tests/instr-cov/217-runtime-subunit/test.py index 9caec2f99..05f332b4a 100644 --- a/testsuite/tests/instr-cov/217-runtime-subunit/test.py +++ b/testsuite/tests/instr-cov/217-runtime-subunit/test.py @@ -5,11 +5,11 @@ import os.path -from e3.fs import mkdir, sync_tree +from e3.fs import sync_tree from SCOV.instr import xcov_instrument from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches tmp = Wdir("tmp_") diff --git a/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py b/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py index a65cfd852..73ce4884a 100644 --- a/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py +++ b/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py @@ -3,8 +3,6 @@ project setup that lacks the package spec corresponding to a package body. """ -import os.path - from e3.fs import mkdir from SCOV.instr import xcov_instrument diff --git a/testsuite/tests/instr-cov/219-non-instr-propagation/test.py b/testsuite/tests/instr-cov/219-non-instr-propagation/test.py index 73e7f5322..e705c6f81 100644 --- a/testsuite/tests/instr-cov/219-non-instr-propagation/test.py +++ b/testsuite/tests/instr-cov/219-non-instr-propagation/test.py @@ -11,8 +11,6 @@ whether Pkg_1 is instrumented before Pkg_2 or the opposite. """ -import os.path - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir diff --git a/testsuite/tests/instr-cov/225-expr-func-access/test.py b/testsuite/tests/instr-cov/225-expr-func-access/test.py index aa7dc81e5..6ef776dba 100644 --- a/testsuite/tests/instr-cov/225-expr-func-access/test.py +++ b/testsuite/tests/instr-cov/225-expr-func-access/test.py @@ -5,8 +5,6 @@ illegal. """ -import os.path - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir diff --git a/testsuite/tests/instr-cov/227-subunit-stub/test.py b/testsuite/tests/instr-cov/227-subunit-stub/test.py index 24534b0fb..36eccdf2b 100644 --- a/testsuite/tests/instr-cov/227-subunit-stub/test.py +++ b/testsuite/tests/instr-cov/227-subunit-stub/test.py @@ -67,7 +67,7 @@ class Test: # Instrument/compile the "vanilla" (stub-free) library to get the "reference" # set of SCOs. -thistest.log(f"== cons ==") +thistest.log("== cons ==") tmp = Wdir("tmp_cons") cp("../src/*.gpr", ".") lib_gpr = os.path.abspath("lib.gpr") diff --git a/testsuite/tests/instr-cov/C++/109-pp-switches/test.py b/testsuite/tests/instr-cov/C++/109-pp-switches/test.py index a50659d5d..f3e9d749d 100644 --- a/testsuite/tests/instr-cov/C++/109-pp-switches/test.py +++ b/testsuite/tests/instr-cov/C++/109-pp-switches/test.py @@ -3,10 +3,9 @@ """ from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -from SCOV.instr import xcov_instrument from SUITE.context import thistest from SUITE.cutils import Wdir -from SUITE.tutils import gprbuild, gprfor +from SUITE.tutils import gprfor from SUITE.gprutils import GPRswitches diff --git a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py index d11c41e16..ba68a5552 100644 --- a/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py +++ b/testsuite/tests/instr-cov/VB03-024-preprocess-included-proj/test.py @@ -10,7 +10,7 @@ from SUITE.gprutils import GPRswitches -def create_lib_gpr(name, deps=[]): +def create_lib_gpr(name, deps=None): """ Create a gpr file for the library. @@ -22,7 +22,7 @@ def create_lib_gpr(name, deps=[]): prjid=name, srcdirs=f"../src-{name}", langs=["C"], - deps=deps, + deps=deps or [], extra=f""" for Library_Name use "{name}"; for Library_Dir use "{name}"; diff --git a/testsuite/tests/instr-cov/c_multiline_stmt/test.py b/testsuite/tests/instr-cov/c_multiline_stmt/test.py index 36ec38c6b..4e077e934 100644 --- a/testsuite/tests/instr-cov/c_multiline_stmt/test.py +++ b/testsuite/tests/instr-cov/c_multiline_stmt/test.py @@ -21,8 +21,6 @@ gnatcov used to insert the closing brace before the terminating semicolon. """ -import os.path - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir diff --git a/testsuite/tests/instr-cov/compile_time_pragma/test.py b/testsuite/tests/instr-cov/compile_time_pragma/test.py index 1b0e77cfc..c254bc150 100644 --- a/testsuite/tests/instr-cov/compile_time_pragma/test.py +++ b/testsuite/tests/instr-cov/compile_time_pragma/test.py @@ -3,9 +3,6 @@ instrumented. """ -import os -import os.path - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir diff --git a/testsuite/tests/instr-cov/config_custom_db/test.py b/testsuite/tests/instr-cov/config_custom_db/test.py index f0b2ef49d..1263df9dc 100644 --- a/testsuite/tests/instr-cov/config_custom_db/test.py +++ b/testsuite/tests/instr-cov/config_custom_db/test.py @@ -3,8 +3,6 @@ are passed through the --db command line option. """ -import os - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.control import env diff --git a/testsuite/tests/instr-cov/entry_guards/restricted/test.py b/testsuite/tests/instr-cov/entry_guards/restricted/test.py index 40d586877..956a5c6b3 100644 --- a/testsuite/tests/instr-cov/entry_guards/restricted/test.py +++ b/testsuite/tests/instr-cov/entry_guards/restricted/test.py @@ -5,7 +5,7 @@ from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of +from SUITE.cutils import Wdir from SUITE.tutils import gprfor from SUITE.gprutils import GPRswitches diff --git a/testsuite/tests/instr-cov/expr_func/ada_2022/test.py b/testsuite/tests/instr-cov/expr_func/ada_2022/test.py index eda23b557..550150f60 100644 --- a/testsuite/tests/instr-cov/expr_func/ada_2022/test.py +++ b/testsuite/tests/instr-cov/expr_func/ada_2022/test.py @@ -1,6 +1,6 @@ """ -Check that limitations concerning expression function instrumentation are lifted -when Ada 2022, and thus declare expressions are available. +Check that limitations concerning expression function instrumentation are +lifted when Ada 2022, and thus declare expressions are available. This test reflects the various limitations that are documented in the user manual: diff --git a/testsuite/tests/instr-cov/expr_func/generic/test.py b/testsuite/tests/instr-cov/expr_func/generic/test.py index c663aae0f..135495964 100644 --- a/testsuite/tests/instr-cov/expr_func/generic/test.py +++ b/testsuite/tests/instr-cov/expr_func/generic/test.py @@ -26,7 +26,9 @@ mains=["test_main"], extra_coverage_args=["-axcov", "--output-dir=."], trace_mode="src", - tolerate_instrument_messages="cannot instrument generic expression function", + tolerate_instrument_messages=( + "cannot instrument generic expression function" + ), ) # We only expect non-instrumented lines diff --git a/testsuite/tests/instr-cov/file-context/test.py b/testsuite/tests/instr-cov/file-context/test.py index 08f9b10d5..c209fe38c 100644 --- a/testsuite/tests/instr-cov/file-context/test.py +++ b/testsuite/tests/instr-cov/file-context/test.py @@ -39,7 +39,7 @@ def do_instr(label, args): # warnings/errors occur at most once, and never for other files. log = do_instr("basic", []) thistest.fail_if_not_equal( - f'"gnatcov instrument" output', + '"gnatcov instrument" output', contents_of(log).strip(), "\n".join( [ @@ -61,7 +61,7 @@ def do_instr(label, args): ) ] thistest.fail_if_not_equal( - f'"gnatcov instrument" output', + '"gnatcov instrument" output', "\n".join( [ "[GNATCOV.MISC] Instrumenting main.adb", diff --git a/testsuite/tests/instr-cov/gpr-complex/test.py b/testsuite/tests/instr-cov/gpr-complex/test.py index 78d61f7fd..ce6478606 100644 --- a/testsuite/tests/instr-cov/gpr-complex/test.py +++ b/testsuite/tests/instr-cov/gpr-complex/test.py @@ -115,7 +115,6 @@ def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): # Now the main project defines an alternate spec. thistest.log("== Redefining Pkg spec ==") expected_xcov = { - "pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {5}}, "pkg-bar.adb.xcov": {"+": {3}}, "pkg.ads.xcov": {"+": {4}}, diff --git a/testsuite/tests/instr-cov/main_autodump/nested_block/test.py b/testsuite/tests/instr-cov/main_autodump/nested_block/test.py index 24a7c6847..fe3f4ca1b 100644 --- a/testsuite/tests/instr-cov/main_autodump/nested_block/test.py +++ b/testsuite/tests/instr-cov/main_autodump/nested_block/test.py @@ -54,8 +54,8 @@ def do_one_main(main_name): """ - create a project, instrument build and compute coverage reports for the given - main, from the expected results dictionnary defined above. + create a project, instrument build and compute coverage reports for the + given main, from the expected results dictionnary defined above. """ tmp.to_subdir(f"tmp_{main_name}") p = gprfor(mains=[f"{main_name}.adb"], srcdirs=[".."]) diff --git a/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py index ad4e6bccc..a74a98d15 100644 --- a/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py +++ b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py @@ -4,12 +4,9 @@ gnatcov is able to provide the correct coverage analysis. """ -import os -import os.path - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor diff --git a/testsuite/tests/instr-cov/manual-dump/trace_index/test.py b/testsuite/tests/instr-cov/manual-dump/trace_index/test.py index d7b8701c7..ac4bbf494 100644 --- a/testsuite/tests/instr-cov/manual-dump/trace_index/test.py +++ b/testsuite/tests/instr-cov/manual-dump/trace_index/test.py @@ -68,7 +68,7 @@ def check_trace(cov_args, traces, index): # Check that the traces do indeed contain an index in their filename thistest.fail_if( - any([not traces[i].endswith(f"-{i}.srctrace") for i in range(3)]), + any(not traces[i].endswith(f"-{i}.srctrace") for i in range(3)), comment=f"missing trace index in trace filenames: {traces}", ) diff --git a/testsuite/tests/instr-cov/missing-runtime-dir/test.py b/testsuite/tests/instr-cov/missing-runtime-dir/test.py index 1bdb755dd..7f36ff129 100644 --- a/testsuite/tests/instr-cov/missing-runtime-dir/test.py +++ b/testsuite/tests/instr-cov/missing-runtime-dir/test.py @@ -7,7 +7,7 @@ import os from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -from SUITE.cutils import contents_of, Wdir +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import thistest, gprfor diff --git a/testsuite/tests/instr-cov/multi_unit_source/test.py b/testsuite/tests/instr-cov/multi_unit_source/test.py index 5ecc3e8c9..b1fe6d57f 100644 --- a/testsuite/tests/instr-cov/multi_unit_source/test.py +++ b/testsuite/tests/instr-cov/multi_unit_source/test.py @@ -40,8 +40,8 @@ "gnatcov instrument output", ( ".*gnatcov.*: instrumentation failed for .*code.ada\n" - ".*gnatcov.*: source files containing multiple compilation units are not" - " supported" + ".*gnatcov.*: source files containing multiple compilation units are" + " not supported" ), contents_of("instrument.log"), ) diff --git a/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py index 82c654ef3..e2f3bc2ba 100644 --- a/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py +++ b/testsuite/tests/instr-cov/pragma_ghost_predicate/test.py @@ -5,12 +5,7 @@ this example program. """ -import os.path - -from e3.fs import cp - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -from SUITE.control import env from SUITE.context import thistest from SUITE.cutils import Wdir from SUITE.tutils import gprfor diff --git a/testsuite/tests/integrated_instrumentation/no_uoi/test.py b/testsuite/tests/integrated_instrumentation/no_uoi/test.py index 4e6ad8e9c..09e33ad13 100644 --- a/testsuite/tests/integrated_instrumentation/no_uoi/test.py +++ b/testsuite/tests/integrated_instrumentation/no_uoi/test.py @@ -13,8 +13,7 @@ from SUITE.control import env from SUITE.cutils import Wdir -from SCOV.minicheck import check_xcov_reports -from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov +from SUITE.tutils import cmdrun, thistest, xcov # To avoid source repository pollution and interference between successive test diff --git a/testsuite/tests/subp_of_interest/test.py b/testsuite/tests/subp_of_interest/test.py index 176ef0db6..e931adb22 100644 --- a/testsuite/tests/subp_of_interest/test.py +++ b/testsuite/tests/subp_of_interest/test.py @@ -67,8 +67,8 @@ def check_xcov(label, args, expected_output=""): expected_output=( "" if src_traces - else "warning: Ignoring --subprograms switches as this is not supported" - " with binary traces." + else "warning: Ignoring --subprograms switches as this is not" + " supported with binary traces." ), ) cov_ckpt_args = cov_args[:-1] + ["--checkpoint", ckpt_filename] From f716b5f91df54fbfb810934637abffb027cd2757 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 26 Feb 2024 14:17:26 +0000 Subject: [PATCH 0747/1483] instr-cov/manual-dump/c_only: fix call to fail_if_not_equal "Reformat" so that a call to this method actually happens, and adjust the regular expression so that it does matches the expected code pattern. --- testsuite/tests/instr-cov/manual-dump/c_only/test.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/instr-cov/manual-dump/c_only/test.py b/testsuite/tests/instr-cov/manual-dump/c_only/test.py index 546c358a1..7a574c391 100644 --- a/testsuite/tests/instr-cov/manual-dump/c_only/test.py +++ b/testsuite/tests/instr-cov/manual-dump/c_only/test.py @@ -60,10 +60,9 @@ # project lib_file = "obj/lib-gnatcov-instr/foo.c" -thistest.fail_if_no_match -( +thistest.fail_if_no_match( "missing Dump_Buffers call", - r"(\n|.)*gnatcov_rts_manual_dump_buffers_lib \(.*\);(\n|.)*", + r"(\n|.)*gnatcov_rts_manual_dump_buffers_lib\(.*\);(\n|.)*", contents_of(lib_file), ) From f2be5ab3fd674343a06b29d71265358ea12a158c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 1 Mar 2024 17:14:44 +0000 Subject: [PATCH 0748/1483] instr-cov/W502-023-base64-long-lines: stabilize for arm-elf Something in the pipeline (the Ada runtime? Qemu?) has trouble handling the very long lines that the test program writes on the serial port, making this test unstable on arm-elf. Since the point of this testcase is to make sure that "gnatcov extract-base64-trace" does not crash (regardless of how the input text file was created), rework it so that the very long line is written by Python, which should fix the unstability. --- .../W502-023-base64-long-lines/main.adb | 4 +-- .../W502-023-base64-long-lines/test.py | 36 ++++++++++++++++--- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/testsuite/tests/instr-cov/W502-023-base64-long-lines/main.adb b/testsuite/tests/instr-cov/W502-023-base64-long-lines/main.adb index f5f08b178..3373e6745 100644 --- a/testsuite/tests/instr-cov/W502-023-base64-long-lines/main.adb +++ b/testsuite/tests/instr-cov/W502-023-base64-long-lines/main.adb @@ -2,7 +2,5 @@ with Ada.Text_IO; use Ada.Text_IO; procedure Main is begin - for I in 1 .. 10_000 loop - Put ((1 .. 1000 => 'A')); - end loop; + Put_Line ("Hello, world!"); end Main; diff --git a/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py b/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py index 8849be4a0..19b0f1af4 100644 --- a/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py +++ b/testsuite/tests/instr-cov/W502-023-base64-long-lines/test.py @@ -3,15 +3,16 @@ very long lines (it used to crash with a stack overflow). """ -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -from SUITE.cutils import Wdir +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.cutils import Wdir, contents_of from SUITE.gprutils import GPRswitches -from SUITE.tutils import thistest, gprfor +from SUITE.tutils import gprfor, thistest, xcov Wdir("tmp_") -build_run_and_coverage( +# First produce a source trace from the test program +xcov_args = build_and_run( gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), covlevel="stmt", mains=["main"], @@ -21,6 +22,31 @@ dump_channel="base64-stdout", ) -check_xcov_reports("obj", {"main.adb.xcov": {"+": {5, 6}}}) +# Then produce an alternate base64 trace with very long lines +with open("base64_long_lines.txt", "w") as f: + for _ in range(10000): + f.write("A" * 1000) + f.write("\n") + f.write(contents_of("main_output.txt")) + +# Extract the source trace from base64 +xcov( + ["extract-base64-trace", "base64_long_lines.txt", xcov_args[-1]], + out="extract.txt", +) +thistest.fail_if_not_equal( + "'gnatcov extract-base64-trace' output", + "", + contents_of("extract.txt"), +) + +# Produce the coverage report and check its contents +xcov(xcov_args, out="coverage.txt") +thistest.fail_if_not_equal( + "'gnatcov coverage' output", + "", + contents_of("coverage.txt"), +) +check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) thistest.result() From 9e2677eace0b7eb59d880debb7bd6226ee8323f4 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 15 Mar 2022 15:42:41 +0100 Subject: [PATCH 0749/1483] Fix soundness issue in the decision map analysis gnatcov was incorrectly labeling some control flow branches as outcome, when they were branching into an inlined body. In the following example, assuming Orelse is inlined: function Orelse (B, C : Boolean) return Boolean is begin return (if B or else C then True else False); end; function F (A, B, C : Boolean) return Boolean is begin return (if A and then Orelse (B, C) then True else False); -- #D1 end; gnatcov incorrectly labeled an edge as implementing the valuation `False` for the condition A, and as an outcome of the decision #D1, which is unsound behaviour. As it could not find an edge for the valuation `True`, it also resulted in a `condition lacks edge` warning. TN: T706-019 --- .../Topologies/AndCOr/IfExprCtl/test.opt | 1 - tools/gnatcov/decision_map.adb | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt index cd54c6b08..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt @@ -1,2 +1 @@ -bin-traces,CARGS_O1 XFAIL T706-019: decision map issue 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/tools/gnatcov/decision_map.adb b/tools/gnatcov/decision_map.adb index ec2ffd032..fd3a9ac2f 100644 --- a/tools/gnatcov/decision_map.adb +++ b/tools/gnatcov/decision_map.adb @@ -2081,6 +2081,25 @@ package body Decision_Map is end if; BB := Find_Basic_Block (Ctx.Basic_Blocks, Next_PC); + + -- If we are branching into an inlined subprogram, we can't deduce + -- anything from it. + -- + -- TODO??? The above is a very conservative guess. If needed in + -- practice, we could refine this to handle various manageable cases. + + declare + BB_Inline_Info : constant Address_Info_Acc := + Get_Address_Info + (Exe.all, Inlined_Subprogram_Addresses, BB.To_PC); + begin + if BB_Inline_Info /= null + and then BB_Inline_Info /= D_Occ.Inlined_Body + then + return; + end if; + end; + if BB = No_Basic_Block then if After_Call or else Next_PC not in Ctx.Subprg.First .. Ctx.Subprg.Last From e2844eae19f0372c811d5288331a5e73a252cbd6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 1 Mar 2024 16:54:57 +0000 Subject: [PATCH 0750/1483] instr-cov/91-homonym-runtime-sources: new testcase --- .../91-homonym-runtime-sources/main.adb | 6 + .../runtime/ada_object_path | 0 .../runtime/ada_source_path | 2 + .../runtime/adainclude/empty-dir.txt | 0 .../runtime/gnat/a-textio.ads | 1 + .../runtime/gnat/ada.ads | 4 + .../runtime/gnat/system.ads | 114 ++++++++++++++++++ .../runtime/gnat_user/a-textio.ads | 3 + .../runtime/runtime_build.gpr | 19 +++ .../91-homonym-runtime-sources/test.py | 39 ++++++ 10 files changed, 188 insertions(+) create mode 100644 testsuite/tests/instr-cov/91-homonym-runtime-sources/main.adb create mode 100644 testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/ada_object_path create mode 100644 testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/ada_source_path create mode 100644 testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/adainclude/empty-dir.txt create mode 100644 testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/a-textio.ads create mode 100644 testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/ada.ads create mode 100644 testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/system.ads create mode 100644 testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat_user/a-textio.ads create mode 100644 testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/runtime_build.gpr create mode 100644 testsuite/tests/instr-cov/91-homonym-runtime-sources/test.py diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/main.adb b/testsuite/tests/instr-cov/91-homonym-runtime-sources/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/ada_object_path b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/ada_object_path new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/ada_source_path b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/ada_source_path new file mode 100644 index 000000000..a678f5061 --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/ada_source_path @@ -0,0 +1,2 @@ +gnat_user +gnat diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/adainclude/empty-dir.txt b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/adainclude/empty-dir.txt new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/a-textio.ads b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/a-textio.ads new file mode 100644 index 000000000..421376db9 --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/a-textio.ads @@ -0,0 +1 @@ +dummy diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/ada.ads b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/ada.ads new file mode 100644 index 000000000..fed04e343 --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/ada.ads @@ -0,0 +1,4 @@ +package Ada is + pragma No_Elaboration_Code_All; + pragma Pure; +end Ada; diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/system.ads b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/system.ads new file mode 100644 index 000000000..1a286ad12 --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat/system.ads @@ -0,0 +1,114 @@ +package System is + pragma Pure; + pragma No_Elaboration_Code_All; + + subtype Name is String; + System_Name : constant Name := "foo"; + + -- System-Dependent Named Numbers + + Min_Int : constant := -2 ** (Standard'Max_Integer_Size - 1); + Max_Int : constant := 2 ** (Standard'Max_Integer_Size - 1) - 1; + + Max_Binary_Modulus : constant := 2 ** Standard'Max_Integer_Size; + Max_Nonbinary_Modulus : constant := 2 ** Integer'Size - 1; + + Max_Base_Digits : constant := Long_Long_Float'Digits; + Max_Digits : constant := Long_Long_Float'Digits; + + Max_Mantissa : constant := Standard'Max_Integer_Size - 1; + Fine_Delta : constant := 2.0 ** (-Max_Mantissa); + + Tick : constant := 0.000_001; + + -- Storage-related Declarations + + type Address is private; + pragma Preelaborable_Initialization (Address); + Null_Address : constant Address; + + Storage_Unit : constant := 8; + Word_Size : constant := Standard'Word_Size; + Memory_Size : constant := 2 ** Word_Size; + + -- Address comparison + + function "<" (Left, Right : Address) return Boolean; + function "<=" (Left, Right : Address) return Boolean; + function ">" (Left, Right : Address) return Boolean; + function ">=" (Left, Right : Address) return Boolean; + function "=" (Left, Right : Address) return Boolean; + + pragma Import (Intrinsic, "<"); + pragma Import (Intrinsic, "<="); + pragma Import (Intrinsic, ">"); + pragma Import (Intrinsic, ">="); + pragma Import (Intrinsic, "="); + + -- Other System-Dependent Declarations + + type Bit_Order is (High_Order_First, Low_Order_First); + Default_Bit_Order : constant Bit_Order := + Bit_Order'Val (Standard'Default_Bit_Order); + pragma Warnings (Off, Default_Bit_Order); -- kill constant condition warning + + -- Priority-related Declarations (RM D.1) + + -- If the scheduling policy is SCHED_FIFO or SCHED_RR the runtime makes use + -- of the entire range provided by the system. + -- + -- If the scheduling policy is SCHED_OTHER the only valid system priority + -- is 1 and other values are simply ignored. + + Max_Priority : constant Positive := 62; + Max_Interrupt_Priority : constant Positive := 63; + + subtype Any_Priority is Integer range 1 .. 63; + subtype Priority is Any_Priority range 1 .. 62; + subtype Interrupt_Priority is Any_Priority range 63 .. 63; + + Default_Priority : constant Priority := 10; + +private + + type Address is mod Memory_Size; + for Address'Size use Standard'Address_Size; + + Null_Address : constant Address := 0; + + -------------------------------------- + -- System Implementation Parameters -- + -------------------------------------- + + -- These parameters provide information about the target that is used + -- by the compiler. They are in the private part of System, where they + -- can be accessed using the special circuitry in the Targparm unit + -- whose source should be consulted for more detailed descriptions + -- of the individual switch values. + + Backend_Divide_Checks : constant Boolean := False; + Backend_Overflow_Checks : constant Boolean := True; + Command_Line_Args : constant Boolean := True; + Configurable_Run_Time : constant Boolean := True; + Denorm : constant Boolean := True; + Duration_32_Bits : constant Boolean := False; + Exit_Status_Supported : constant Boolean := True; + Machine_Overflows : constant Boolean := False; + Machine_Rounds : constant Boolean := True; + Preallocated_Stacks : constant Boolean := False; + Signed_Zeros : constant Boolean := True; + Stack_Check_Default : constant Boolean := False; + Stack_Check_Probes : constant Boolean := True; + Stack_Check_Limits : constant Boolean := False; + Support_Aggregates : constant Boolean := True; + Support_Atomic_Primitives : constant Boolean := True; + Support_Composite_Assign : constant Boolean := True; + Support_Composite_Compare : constant Boolean := True; + Support_Long_Shifts : constant Boolean := True; + Always_Compatible_Rep : constant Boolean := True; + Suppress_Standard_Library : constant Boolean := True; + Use_Ada_Main_Program_Name : constant Boolean := False; + Frontend_Exceptions : constant Boolean := False; + ZCX_By_Default : constant Boolean := True; + +end System; diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat_user/a-textio.ads b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat_user/a-textio.ads new file mode 100644 index 000000000..c6278247a --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/gnat_user/a-textio.ads @@ -0,0 +1,3 @@ +package Ada.Text_IO is + procedure Put_Line (S : String) is null; +end Ada.Text_IO; diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/runtime_build.gpr b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/runtime_build.gpr new file mode 100644 index 000000000..a0dfa9727 --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/runtime/runtime_build.gpr @@ -0,0 +1,19 @@ +project Runtime_Build is + + for Runtime ("Ada") use Project'Project_Dir; + + for Library_Auto_Init use "False"; + for Library_Name use "gnat"; + for Library_Dir use "adalib"; + for Object_Dir use "obj"; + for Source_Dirs use ("gnat_user", "gnat"); + + package Compiler is + for Default_Switches ("Ada") use ("-gnatg"); + end Compiler; + + package Naming is + for Spec_Suffix ("Asm_CPP") use ".inc"; + end Naming; + +end Runtime_Build; diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/test.py b/testsuite/tests/instr-cov/91-homonym-runtime-sources/test.py new file mode 100644 index 000000000..33a91f669 --- /dev/null +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/test.py @@ -0,0 +1,39 @@ +""" +Check that the instrumentation of a project does not crash when the Ada runtime +for this project contains homonym sources in its source directories. +""" + +import os.path + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +# Avoid "creating output path" info messages +os.mkdir("obj") + +xcov_instrument( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+mcdc", + auto_config_args=False, + auto_target_args=False, + extra_args=[ + "--target", + thistest.env.target.triplet, + "--RTS", + os.path.abspath("../runtime"), + ], + out="instrument.log", +) + +thistest.fail_if_not_equal( + "'gnatcov instrument' output", + "", + contents_of("instrument.log"), +) + +thistest.result() From a0079a6d1dfbd7475c73f3fd65211095f2b24e2a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 27 Feb 2024 13:12:48 +0100 Subject: [PATCH 0751/1483] Enable inlining of witness subprograms This results in two changes in practice: * On the Ada side, duplicate the definitions of the witness subprograms instead of using the C version,to enable inlining without having to use -flto. * On the C side, put witness function definitions in a dedicated header that we include in instrumented code, rather than having extern linkage declarations. --- .../gen/arm-elf-linux/gcvrt-pz3791e32c.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68b.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68c.ads | 2 +- .../gen/arm-elf-linux/main_1.adb | 2 +- .../gen/arm-elf-linux/main_2.adb | 2 +- .../gen/x86_64-windows/gcvrt-pz3791e32c.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68b.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68c.ads | 2 +- .../gen/x86_64-windows/main_1.adb | 2 +- .../gen/x86_64-windows/main_2.adb | 2 +- tools/gnatcov/instrument-c.adb | 32 +------ tools/gnatcov/instrument-common.ads | 2 +- tools/gnatcov/rts/gnatcov_rts-buffers.adb | 82 +++++------------- tools/gnatcov/rts/gnatcov_rts-buffers.ads | 7 ++ tools/gnatcov/rts/gnatcov_rts.ads | 3 +- tools/gnatcov/rts/gnatcov_rts_c-buffers.c | 45 ---------- tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 43 ---------- tools/gnatcov/rts/gnatcov_rts_c-witness.h | 84 +++++++++++++++++++ 18 files changed, 129 insertions(+), 189 deletions(-) create mode 100644 tools/gnatcov/rts/gnatcov_rts_c-witness.h diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads index cdbd12f7e..aa24ad350 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 6, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz3791e32c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads index df7debe5c..bc3a938bb 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 6, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68b is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads index 5b40ecefc..d5709f6fb 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 6, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb index 0e4e6535b..2907ece19 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=6,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=7,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); GCVRT.DB_z794ac68b.Dump_Buffers;end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb index 558a2217e..7ffd105bc 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=6,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=7,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); GCVRT.DB_z794ac68c.Dump_Buffers;end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads index 543870490..d736880fc 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 6, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz3791e32c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads index c50dfad54..8bc7f44f9 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 6, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68b is diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads index 48ed9aec8..650e4a63f 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 6, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb index 7bc8940f5..e30a47621 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=6,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=7,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is GNATcov_Dump_Object:GCVRT.DB_z794ac68b.Dump_Controlled_Type;begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb index f5ecc1794..53de509b9 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=6,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=7,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is GNATcov_Dump_Object:GCVRT.DB_z794ac68c.Dump_Controlled_Type;begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); end Main_2; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 799b73340..0362a827c 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3336,34 +3336,10 @@ package body Instrument.C is MCDC_Buffer_Symbol (UIC.Instrumented_Unit), Array_Size => Buffers_Count); end; - Put_Extern_Decl - ("unsigned", - "gnatcov_rts_witness", - Func_Args => "unsigned char *buffer_address, unsigned bit_id"); - Put_Extern_Decl - ("unsigned", - "gnatcov_rts_witness_decision", - Func_Args => "unsigned char *buffer_address," - & " unsigned false_bit," - & " unsigned true_bit," - & " unsigned value"); - Put_Extern_Decl - ("unsigned", - "gnatcov_rts_witness_decision_mcdc", - Func_Args => "unsigned char *decision_buffer_address," - & " unsigned false_bit," - & " unsigned true_bit," - & " unsigned char *mcdc_buffer_address," - & " unsigned mcdc_base," - & " unsigned *mcdc_path_address," - & " unsigned value"); - Put_Extern_Decl - ("unsigned", - "gnatcov_rts_witness_condition", - Func_Args => "unsigned *mcdc_path_address," - & "unsigned offset_for_true," - & " unsigned first," - & " unsigned value"); + CX_Rewriter_Insert_Text_After + (UIC.Rewriter, + Insert_Extern_Location, + ASCII.LF & "#include ""gnatcov_rts_c-witness.h""" & ASCII.LF); Rewriter.Apply; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index c1fe5684b..23bc670d9 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -365,7 +365,7 @@ package Instrument.Common is (Strings.Img (Integer (Bit))); Runtime_Version_Check : constant String := - "pragma Compile_Time_Error (GNATcov_RTS.Version /= 6, " + "pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, " & """Incompatible GNATcov_RTS version, please use" & " the GNATcov_RTS project provided with your" & " GNATcoverage distribution."");"; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.adb b/tools/gnatcov/rts/gnatcov_rts-buffers.adb index efb55745f..f020c4b42 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.adb +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.adb @@ -26,62 +26,15 @@ package body GNATcov_RTS.Buffers is - function To_Bool (Bool : GNATcov_RTS_Bool) return Boolean; - - function To_GNATcov_RTS_Bool (Bool : Boolean) return GNATcov_RTS_Bool; - - function GNATcov_RTS_Witness - (Buffer_Address : System.Address; Bit : Bit_Id) return GNATcov_RTS_Bool; - pragma Import (C, GNATcov_RTS_Witness); - - function GNATcov_RTS_Witness_Decision_MCDC - (Decision_Buffer_Address : System.Address; - False_Bit, True_Bit : Bit_Id; - MCDC_Buffer_Address : System.Address; - MCDC_Base : Bit_Id; - MCDC_Path_Address : System.Address; - Value : GNATcov_RTS_Bool) return GNATcov_RTS_Bool; - pragma Import (C, GNATcov_RTS_Witness_Decision_MCDC); - - function GNATcov_RTS_Witness_Condition - (MCDC_Path_Address : System.Address; - Offset_For_True : Any_Bit_Id; - First : GNATcov_RTS_Bool; - Value : GNATcov_RTS_Bool) return GNATcov_RTS_Bool; - pragma Import (C, GNATcov_RTS_Witness_Condition); - - ------------- - -- To_Bool -- - ------------- - - function To_Bool (Bool : GNATcov_RTS_Bool) return Boolean is - begin - return Bool /= 0; - end To_Bool; - - ------------------------- - -- To_GNATcov_RTS_bool -- - ------------------------- - - function To_GNATcov_RTS_Bool (Bool : Boolean) return GNATcov_RTS_Bool is - begin - if Bool then - return 1; - else - return 0; - end if; - end To_GNATcov_RTS_Bool; - ------------- -- Witness -- ------------- procedure Witness (Buffer_Address : System.Address; Bit : Bit_Id) is - Ignored : constant GNATcov_RTS_Bool := - GNATcov_RTS_Witness (Buffer_Address, Bit); - pragma Unreferenced (Ignored); + Buffer : Coverage_Buffer_Type (0 .. Bit); + for Buffer'Address use Buffer_Address; begin - null; + Buffer (Bit) := True; end Witness; function Witness @@ -130,13 +83,13 @@ package body GNATcov_RTS.Buffers is MCDC_Path_Address : System.Address; Value : Boolean) return Boolean is + MCDC_Path_Index : Any_Bit_Id; + for MCDC_Path_Index'Address use MCDC_Path_Address; + pragma Import (Ada, MCDC_Path_Index); + begin - return - To_Bool - (GNATcov_RTS_Witness_Decision_MCDC - (Decision_Buffer_Address, False_Bit, True_Bit, - MCDC_Buffer_Address, MCDC_Base, MCDC_Path_Address, - To_GNATcov_RTS_Bool (Value))); + Witness (MCDC_Buffer_Address, MCDC_Base + MCDC_Path_Index); + return Witness (Decision_Buffer_Address, False_Bit, True_Bit, Value); end Witness; function Witness @@ -145,12 +98,19 @@ package body GNATcov_RTS.Buffers is First : Boolean; Value : Boolean) return Boolean is + MCDC_Path_Index : Any_Bit_Id; + for MCDC_Path_Index'Address use Buffer_Address; + pragma Import (Ada, MCDC_Path_Index); begin - return - To_Bool - (GNATcov_RTS_Witness_Condition - (Buffer_Address, Offset_For_True, To_GNATcov_RTS_Bool (First), - To_GNATcov_RTS_Bool (Value))); + if First then + MCDC_Path_Index := 0; + end if; + + if Value then + MCDC_Path_Index := MCDC_Path_Index + Offset_For_True; + end if; + + return Value; end Witness; end GNATcov_RTS.Buffers; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index e2f40a266..b24e83de2 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -108,6 +108,7 @@ package GNATcov_RTS.Buffers is -- to True in Buffer in various context. procedure Witness (Buffer_Address : System.Address; Bit : Bit_Id); + pragma Inline (Witness); -- This variant is used as part of sequence of statements, to witness -- that we have reached a specific point in the sequence. @@ -118,6 +119,7 @@ package GNATcov_RTS.Buffers is function Witness (Buffer_Address : System.Address; Bit : Bit_Id) return Witness_Dummy_Type; + pragma Inline (Witness); -- This variant is used in contexts where statements are not allowed -- but declarations are, for example ahead of library level declarations -- to witness their elaboration. @@ -140,11 +142,13 @@ package GNATcov_RTS.Buffers is function Witness (Buffer_Address : System.Address; Bit : Bit_Id) return Non_Volatile_Witness_Dummy_Type; + pragma Inline (Witness); -- This variant uses a non-volatile return type to be compatible with ghost -- code. function Witness (Buffer_Address : System.Address; Bit : Bit_Id) return Boolean; + pragma Inline (Witness); -- This variant is used in Boolean expression contexts and always returns -- True. @@ -164,6 +168,7 @@ package GNATcov_RTS.Buffers is (Buffer_Address : System.Address; False_Bit, True_Bit : Bit_Id; Value : Boolean) return Boolean; + pragma Inline (Witness); -- If Value is False, set the Boolean corresponding to False_Bit to True in -- Buffer. Set the one corresponding to True_Bit otherwise. @@ -174,6 +179,7 @@ package GNATcov_RTS.Buffers is MCDC_Base : Bit_Id; MCDC_Path_Address : System.Address; Value : Boolean) return Boolean; + pragma Inline (Witness); -- Same as above, and also set the bit determined by MCDC_Base and the -- Bit_Id value at MCDC_Path_Address in the buffer at MCDC_Buffer_Address. -- Note that MCDC_Path may not be passed by value, because it is not known @@ -187,6 +193,7 @@ package GNATcov_RTS.Buffers is Offset_For_True : Any_Bit_Id; First : Boolean; Value : Boolean) return Boolean; + pragma Inline (Witness); -- Buffer_Address is the address of an MCDC_State_Type local variable. -- If First is True, first reset it to 0. -- If Value is True, add Offset_For_True. diff --git a/tools/gnatcov/rts/gnatcov_rts.ads b/tools/gnatcov/rts/gnatcov_rts.ads index 04b5c93e4..4a666279f 100644 --- a/tools/gnatcov/rts/gnatcov_rts.ads +++ b/tools/gnatcov/rts/gnatcov_rts.ads @@ -42,7 +42,7 @@ package GNATcov_RTS is pragma Warnings (Off, Std); pragma Warnings (Off, Sys); - Version : constant := 6; + Version : constant := 7; -- For compatibility with the GNATcoverage in use, GNATcov_RTS is -- versioned. -- @@ -53,5 +53,6 @@ package GNATcov_RTS is -- 5 -- add a non-volatile version of the Witness_Dummy_Type and -- the associated Witness function. -- 6 -- buffer clear mechanism and trace filename indices + -- 7 -- enable inlining of witness subprograms end GNATcov_RTS; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c index 23d78ebe0..2a6a32e32 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c @@ -22,51 +22,6 @@ #include #include -gnatcov_rts_bool -gnatcov_rts_witness (uint8_t *buffer, gnatcov_rts_bit_id bit) -{ - buffer[bit] = 1; - return 1; -} - -gnatcov_rts_bool -gnatcov_rts_witness_decision (uint8_t *buffer, gnatcov_rts_bit_id false_bit, - gnatcov_rts_bit_id true_bit, - gnatcov_rts_bool value) -{ - gnatcov_rts_witness (buffer, value ? true_bit : false_bit); - return value; -} - -gnatcov_rts_bool -gnatcov_rts_witness_decision_mcdc (uint8_t *decision_buffer, - gnatcov_rts_bit_id false_bit, - gnatcov_rts_bit_id true_bit, - uint8_t *mcdc_buffer, - gnatcov_rts_bit_id mcdc_base, - gnatcov_rts_bit_id *mcdc_path_address, - gnatcov_rts_bool value) -{ - gnatcov_rts_bit_id mcdc_path_index = *mcdc_path_address; - gnatcov_rts_witness (mcdc_buffer, mcdc_base + mcdc_path_index); - return gnatcov_rts_witness_decision (decision_buffer, false_bit, true_bit, - value); -} - -gnatcov_rts_bool -gnatcov_rts_witness_condition (gnatcov_rts_bit_id *mcdc_path_address, - gnatcov_rts_bit_id offset_for_true, - gnatcov_rts_bool first, gnatcov_rts_bool value) -{ - gnatcov_rts_bit_id *mcdc_path_index - = (gnatcov_rts_bit_id *) mcdc_path_address; - if (first) - *mcdc_path_index = 0; - if (value) - *mcdc_path_index += offset_for_true; - return value; -} - void gnatcov_rts_reset_buffers (const struct gnatcov_rts_coverage_buffers *buffs) { diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index 733be9a68..2b9e4dd02 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -125,49 +125,6 @@ extern "C" const struct gnatcov_rts_coverage_buffers_group **groups; }; - /***********************/ - /* Witness subprograms */ - /***********************/ - - /* The following subprograms are called by generated code to record - the execution of constructs. */ - - /* Statements */ - - /* Set the boolean corresponding to BIT to true in BUFFER in various - context. */ - extern gnatcov_rts_bool gnatcov_rts_witness (uint8_t *buffer, - gnatcov_rts_bit_id bit); - - /* Decisions */ - - /* If VALUE is false, set the boolean corresponding to FALSE_BIT to true in - BUFFER. Set the one corresponding to TRUE_BIT otherwise. */ - extern gnatcov_rts_bool - gnatcov_rts_witness_decision (uint8_t *buffer, gnatcov_rts_bit_id false_bit, - gnatcov_rts_bit_id true_bit, - gnatcov_rts_bool value); - - /* Same as above, and also set the bit determined by MCDC_BASE and the - gnatcov_rts_bit_id value at MCDC_PATH_ADDRESS in the buffer at - MCDC_BUFFER_ADDRESS. Note that MCDC_PATH may not be passed by value, - because it is not known until the side effect of the actual for the VALUE - formal have been evaluated. */ - extern gnatcov_rts_bool gnatcov_rts_witness_decision_mcdc ( - uint8_t *decision_buffer, gnatcov_rts_bit_id false_bit, - gnatcov_rts_bit_id true_bit, uint8_t *mcdc_buffer, - gnatcov_rts_bit_id mcdc_base, gnatcov_rts_bit_id *mcdc_path_address, - gnatcov_rts_bool value); - - /* Conditions */ - - /* MCDC_PATH_ADDRESS is the address of a local variable storing the - mcdc_state. If FIRST is true, first reset it to 0. If VALUE is true, add - OFFSET_FOR_TRUE. */ - extern gnatcov_rts_bool gnatcov_rts_witness_condition ( - gnatcov_rts_bit_id *mcdc_path_address, gnatcov_rts_bit_id offset_for_true, - gnatcov_rts_bool first, gnatcov_rts_bool value); - /*********************/ /* Clear subprograms */ /*********************/ diff --git a/tools/gnatcov/rts/gnatcov_rts_c-witness.h b/tools/gnatcov/rts/gnatcov_rts_c-witness.h new file mode 100644 index 000000000..1943d2186 --- /dev/null +++ b/tools/gnatcov/rts/gnatcov_rts_c-witness.h @@ -0,0 +1,84 @@ +/**************************************************************************** + * * + * GNATcoverage Instrumentation Runtime * + * * + * Copyright (C) 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. * + * * + ****************************************************************************/ + +/***********************/ +/* Witness subprograms */ +/***********************/ + +/* The following subprograms are called by generated code to record + the execution of constructs. */ + +/* Statements */ + +/* Set the boolean corresponding to BIT to true in BUFFER in various + context. */ +static inline unsigned +gnatcov_rts_witness (unsigned char *buffer, unsigned bit_id) +{ + buffer[bit_id] = 1; + return 1; +} + +/* Decisions */ + +/* If VALUE is false, set the boolean corresponding to FALSE_BIT to true in + BUFFER. Set the one corresponding to TRUE_BIT otherwise. */ +static inline unsigned +gnatcov_rts_witness_decision (unsigned char *buffer, unsigned false_bit, + unsigned true_bit, unsigned value) +{ + gnatcov_rts_witness (buffer, value ? true_bit : false_bit); + return value; +} + +/* Same as above, and also set the bit determined by MCDC_BASE and the + gnatcov_rts_bit_id value at MCDC_PATH_ADDRESS in the buffer at + MCDC_BUFFER_ADDRESS. Note that MCDC_PATH may not be passed by value, + because it is not known until the side effect of the actual for the VALUE + formal have been evaluated. */ +static inline unsigned +gnatcov_rts_witness_decision_mcdc (unsigned char *decision_buffer, + unsigned false_bit, unsigned true_bit, + unsigned char *mcdc_buffer, + unsigned mcdc_base, + unsigned *mcdc_path_address, unsigned value) +{ + unsigned mcdc_path_index = *mcdc_path_address; + gnatcov_rts_witness (mcdc_buffer, mcdc_base + mcdc_path_index); + return gnatcov_rts_witness_decision (decision_buffer, false_bit, true_bit, + value); +} + +/* Conditions */ + +/* MCDC_PATH_ADDRESS is the address of a local variable storing the + mcdc_state. If FIRST is true, first reset it to 0. If VALUE is true, add + OFFSET_FOR_TRUE. */ +static inline unsigned +gnatcov_rts_witness_condition (unsigned *mcdc_path_address, + unsigned offset_for_true, unsigned first, + unsigned value) +{ + unsigned *mcdc_path_index = mcdc_path_address; + if (first) + *mcdc_path_index = 0; + if (value) + *mcdc_path_index += offset_for_true; + return value; +} From 358c9d751a84b284563f1ee8e4faf410ddb7a3a2 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 1 Mar 2024 18:10:25 +0100 Subject: [PATCH 0752/1483] Fix Object_Dir for compiler wrapper The compiler wrapper no longer packages the instrumentation capabilities of gnatcov, but acts as a wrapper around gnatcov64, and thus uses the stubbed version of instrument units. --- tools/gnatcov/Makefile | 2 +- tools/gnatcov/gnatcov.gpr | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index 0740f705b..b8ab51656 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -54,7 +54,7 @@ PGMNAME=gnatcov PGMPATH=obj32/$(BUILD_MODE)/$(PGMNAME) PGM32PATH=obj32/$(BUILD_MODE)/gnatcov32 PGM64PATH=obj64/$(BUILD_MODE)/gnatcov64 -COMPILERPATH=obj64/$(BUILD_MODE)/compiler_wrappers-gcc +COMPILERPATH=obj32/$(BUILD_MODE)/compiler_wrappers-gcc # Directory name in the install tree DIRNAME=gnatcoverage diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 9c9de7ade..da07bcc62 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -290,8 +290,8 @@ project Gnatcov is Object_Dir := ""; case Part is - when "driver" | "lib32" | "gnatcov32" => Object_Dir := "obj32"; - when "gnatcov64" | "compiler" => Object_Dir := "obj64"; + when "driver" | "lib32" | "gnatcov32" | "compiler" => Object_Dir := "obj32"; + when "gnatcov64" => Object_Dir := "obj64"; -- gnatcov64 uses the real instrumenter.adb while lib64 uses the stub -- one, so they cannot use the same object directory. From 8fd92b786d6a32cc2c7542d95baf1e2fcb43ba33 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 1 Mar 2024 16:24:35 +0000 Subject: [PATCH 0753/1483] instr-cov/ada-derived-bool: new testcase --- .../instr-cov/ada-derived-bool/src/bar.adb | 21 +++++++++++++++++++ .../instr-cov/ada-derived-bool/src/bar.ads | 14 +++++++++++++ .../instr-cov/ada-derived-bool/src/test_0.adb | 13 ++++++++++++ .../instr-cov/ada-derived-bool/src/test_f.adb | 13 ++++++++++++ .../instr-cov/ada-derived-bool/src/test_t.adb | 13 ++++++++++++ .../ada-derived-bool/src/test_tf.adb | 14 +++++++++++++ .../tests/instr-cov/ada-derived-bool/test.opt | 1 + .../tests/instr-cov/ada-derived-bool/test.py | 12 +++++++++++ 8 files changed, 101 insertions(+) create mode 100644 testsuite/tests/instr-cov/ada-derived-bool/src/bar.adb create mode 100644 testsuite/tests/instr-cov/ada-derived-bool/src/bar.ads create mode 100644 testsuite/tests/instr-cov/ada-derived-bool/src/test_0.adb create mode 100644 testsuite/tests/instr-cov/ada-derived-bool/src/test_f.adb create mode 100644 testsuite/tests/instr-cov/ada-derived-bool/src/test_t.adb create mode 100644 testsuite/tests/instr-cov/ada-derived-bool/src/test_tf.adb create mode 100644 testsuite/tests/instr-cov/ada-derived-bool/test.opt create mode 100644 testsuite/tests/instr-cov/ada-derived-bool/test.py diff --git a/testsuite/tests/instr-cov/ada-derived-bool/src/bar.adb b/testsuite/tests/instr-cov/ada-derived-bool/src/bar.adb new file mode 100644 index 000000000..7f953da17 --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/src/bar.adb @@ -0,0 +1,21 @@ +with Ada.Text_IO; + +package body Bar is + + procedure Msg (M : String) is + begin + Ada.Text_IO.Put_Line (M); -- # msg + end Msg; + + procedure Proc (V : Rec; B : My_Boolean) is + begin + if B -- # cond1 + and not V.Val -- # cond2 + then + Msg("Uh oh"); -- # then + else + Msg("Hooray"); -- # else + end if; + end Proc; + +end Bar; diff --git a/testsuite/tests/instr-cov/ada-derived-bool/src/bar.ads b/testsuite/tests/instr-cov/ada-derived-bool/src/bar.ads new file mode 100644 index 000000000..04a88f9b6 --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/src/bar.ads @@ -0,0 +1,14 @@ +pragma Ada_2012; + +package Bar is + + type My_Boolean is new Boolean with Convention => C, Object_Size => 8; + + type Rec is record + Val : My_Boolean; + end record; + + procedure Msg (M : String); + procedure Proc (V : Rec; B : My_Boolean); + +end Bar; diff --git a/testsuite/tests/instr-cov/ada-derived-bool/src/test_0.adb b/testsuite/tests/instr-cov/ada-derived-bool/src/test_0.adb new file mode 100644 index 000000000..ffd8501ec --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/src/test_0.adb @@ -0,0 +1,13 @@ +with Bar; use Bar; + +procedure Test_0 is +begin + Msg (""); +end Test_0; + +--# bar.adb +-- /msg/ l+ ## 0 +-- /cond1/ l- ## s- +-- /cond2/ l- ## 0 +-- /then/ l- ## s- +-- /else/ l- ## s- diff --git a/testsuite/tests/instr-cov/ada-derived-bool/src/test_f.adb b/testsuite/tests/instr-cov/ada-derived-bool/src/test_f.adb new file mode 100644 index 000000000..4f1def857 --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/src/test_f.adb @@ -0,0 +1,13 @@ +with Bar; use Bar; + +procedure Test_F is +begin + Proc ((Val => True), False); +end Test_F; + +--# bar.adb +-- /msg/ l+ ## 0 +-- /cond1/ l! ## dT- +-- /cond2/ l! ## 0 +-- /then/ l- ## s- +-- /else/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/ada-derived-bool/src/test_t.adb b/testsuite/tests/instr-cov/ada-derived-bool/src/test_t.adb new file mode 100644 index 000000000..42f785e41 --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/src/test_t.adb @@ -0,0 +1,13 @@ +with Bar; use Bar; + +procedure Test_T is +begin + Proc ((Val => False), True); +end Test_T; + +--# bar.adb +-- /msg/ l+ ## 0 +-- /cond1/ l! ## dF- +-- /cond2/ l! ## 0 +-- /then/ l+ ## 0 +-- /else/ l- ## s- diff --git a/testsuite/tests/instr-cov/ada-derived-bool/src/test_tf.adb b/testsuite/tests/instr-cov/ada-derived-bool/src/test_tf.adb new file mode 100644 index 000000000..9612684e0 --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/src/test_tf.adb @@ -0,0 +1,14 @@ +with Bar; use Bar; + +procedure Test_TF is +begin + Proc ((Val => True), True); + Proc ((Val => False), True); +end Test_TF; + +--# bar.adb +-- /msg/ l+ ## 0 +-- /cond1/ l+ ## 0 +-- /cond2/ l+ ## 0 +-- /then/ l+ ## 0 +-- /else/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/ada-derived-bool/test.opt b/testsuite/tests/instr-cov/ada-derived-bool/test.opt new file mode 100644 index 000000000..c41d7f927 --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Test uses Ada 2012 constructs diff --git a/testsuite/tests/instr-cov/ada-derived-bool/test.py b/testsuite/tests/instr-cov/ada-derived-bool/test.py new file mode 100644 index 000000000..4934f0a5a --- /dev/null +++ b/testsuite/tests/instr-cov/ada-derived-bool/test.py @@ -0,0 +1,12 @@ +""" +Regression testcase specific to the Ada instrumenter (material and bug report +come from CS0038132): check that gnatcov correctly instruments a decision that +involves a derived boolean type. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.decision).run() +thistest.result() From 30642f198ace9074dac9d680db6f9c8394840f00 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 5 Mar 2024 10:54:55 +0100 Subject: [PATCH 0754/1483] Instrumentation runtime: deactivate warnings The code triggers compiler warnings when compiled against a light runtime profile, where the No_Exception_Propagation restriction is in effect. --- tools/gnatcov/rts/gnatcov_rts-buffers.adb | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.adb b/tools/gnatcov/rts/gnatcov_rts-buffers.adb index f020c4b42..a38584946 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.adb +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.adb @@ -34,7 +34,12 @@ package body GNATcov_RTS.Buffers is Buffer : Coverage_Buffer_Type (0 .. Bit); for Buffer'Address use Buffer_Address; begin + -- Here and below: deactivate warnings about possible exception + -- propagation under light runtimes. + + pragma Warnings (Off); Buffer (Bit) := True; + pragma Warnings (On); end Witness; function Witness @@ -88,7 +93,9 @@ package body GNATcov_RTS.Buffers is pragma Import (Ada, MCDC_Path_Index); begin + pragma Warnings (Off); Witness (MCDC_Buffer_Address, MCDC_Base + MCDC_Path_Index); + pragma Warnings (On); return Witness (Decision_Buffer_Address, False_Bit, True_Bit, Value); end Witness; @@ -107,7 +114,9 @@ package body GNATcov_RTS.Buffers is end if; if Value then + pragma Warnings (Off); MCDC_Path_Index := MCDC_Path_Index + Offset_For_True; + pragma Warnings (On); end if; return Value; From 66a76926eabfef18b8b8caec2a44c7f9d02b4ed7 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 5 Mar 2024 11:52:07 +0100 Subject: [PATCH 0755/1483] Revert "Fix soundness issue in the decision map analysis" This reverts commit 9e2677eace0b7eb59d880debb7bd6226ee8323f4. --- .../Topologies/AndCOr/IfExprCtl/test.opt | 1 + tools/gnatcov/decision_map.adb | 19 ------------------- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt index a4e1eba80..cd54c6b08 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt @@ -1 +1,2 @@ +bin-traces,CARGS_O1 XFAIL T706-019: decision map issue 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/tools/gnatcov/decision_map.adb b/tools/gnatcov/decision_map.adb index fd3a9ac2f..ec2ffd032 100644 --- a/tools/gnatcov/decision_map.adb +++ b/tools/gnatcov/decision_map.adb @@ -2081,25 +2081,6 @@ package body Decision_Map is end if; BB := Find_Basic_Block (Ctx.Basic_Blocks, Next_PC); - - -- If we are branching into an inlined subprogram, we can't deduce - -- anything from it. - -- - -- TODO??? The above is a very conservative guess. If needed in - -- practice, we could refine this to handle various manageable cases. - - declare - BB_Inline_Info : constant Address_Info_Acc := - Get_Address_Info - (Exe.all, Inlined_Subprogram_Addresses, BB.To_PC); - begin - if BB_Inline_Info /= null - and then BB_Inline_Info /= D_Occ.Inlined_Body - then - return; - end if; - end; - if BB = No_Basic_Block then if After_Call or else Next_PC not in Ctx.Subprg.First .. Ctx.Subprg.Last From 2fe4fe0d8a29b46c80093f702f1ce6f29c98910f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 26 Feb 2024 08:43:48 +0100 Subject: [PATCH 0756/1483] Address flake8 warnings in qualification-related scripts --- qualification/genbundle.py | 61 +++++++++++++----------- qualification/qm/common_conf.py | 2 +- qualification/qm/env/env.py | 2 + qualification/qm/genmodel.py | 52 +++++++++----------- qualification/qm/plans/qmconf.py | 3 ++ qualification/qm/qm_plugins/importers.py | 51 ++++++++++---------- qualification/qm/qm_prolog.py | 2 + testsuite/Qualif/qmconf.py | 2 + 8 files changed, 91 insertions(+), 84 deletions(-) diff --git a/qualification/genbundle.py b/qualification/genbundle.py index bd0efdb4b..411c949ce 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -196,16 +196,20 @@ from datetime import date -import optparse, sys, os.path, shutil, re, hashlib +import hashlib +import optparse +import os.path +import re +import sys # This lets us access modules that the testuite # code features: MY_TESTSUITE_DIR = os.path.abspath("../testsuite") sys.path.append(MY_TESTSUITE_DIR) -from SUITE.qdata import CTXDATA_FILE, treeref_at -from SUITE.cutils import contents_of, output_of -from SUITE.dutils import jload_from +from SUITE.qdata import CTXDATA_FILE, treeref_at # noqa: E402 +from SUITE.cutils import contents_of, output_of # noqa: E402 +from SUITE.dutils import jload_from # noqa: E402 # ======================================================================= # == MISC UTILITY FUNCTIONS == @@ -234,7 +238,7 @@ def warn_if(p, msg): print("\n!!! WARNING: %s !!!\n" % msg) -def run_list(cmd, dir=None, env=None): +def run_list(cmd, dirname=None, env=None): """Execute the provided CMD command-list (command name + arguments), temporarily switching to the DIR directory unless None, dumping a .log file tracking the command output in the directory where the command @@ -261,7 +265,7 @@ def run_list(cmd, dir=None, env=None): os.chdir(oriwd) -def run(s, dir=None, env=None): +def run(s, dirname=None, env=None): run_list(s.split(), dir, env=env) @@ -323,7 +327,7 @@ def current_gitbranch_at(dirname): os.chdir(dirname) this_branch = re.search( - pattern="\* (?P\S*)", string=output_of("git branch") + pattern=r"\* (?P\S*)", string=output_of("git branch") ).group("branchname") os.chdir(cwd) @@ -373,20 +377,20 @@ def __init__(self, options): self.passno = 0 - def process_imports(self, dir): + def process_imports(self, dirname): """ - Process the template file in dir, replacing the occurrences of + Process the template file in dirname, replacing the occurrences of <%name%> in the text by the contents of name_.rst, according to the qualification parameters """ def replace_one(p): return contents_of( - os.path.join(dir, p.group(1) + f"_{self.o.trace_mode}.rst") + os.path.join(dirname, p.group(1) + f"_{self.o.trace_mode}.rst") ) - template_content = contents_of(os.path.join(dir, "content.tmpl")) - with open(os.path.join(dir, "content.rst"), "w") as f: + template_content = contents_of(os.path.join(dirname, "content.tmpl")) + with open(os.path.join(dirname, "content.rst"), "w") as f: f.write( re.sub( pattern=r"<%([^%]+)%>", @@ -404,10 +408,10 @@ def prepare_content(self, dirs): Prepare the content files by choosing the correct content_*.rst file according to the qualification parameters. """ - for dir in dirs: + for dirname in dirs: cp( - os.path.join(dir, f"content_{self.o.trace_mode}.rst"), - os.path.join(dir, f"content.rst"), + os.path.join(dirname, f"content_{self.o.trace_mode}.rst"), + os.path.join(dirname, "content.rst"), ) # -------------------- @@ -543,15 +547,15 @@ def kititem_for(self, part): # # for the html versions. - def __latch_into(self, dir, part, toplevel, copy_from=None): + def __latch_into(self, dirname, part, toplevel, copy_from=None): this_target_is_tree = self.this_docformat == "html" # Compute the target dir or file name for our copy: this_target = ( - dir + dirname if toplevel and this_target_is_tree - else os.path.join(dir, self.kititem_for(part=part)) + else os.path.join(dirname, self.kititem_for(part=part)) ) # Compute the source dir or file name for our copy: @@ -638,7 +642,7 @@ def __qm_build(self, part): env={"GENBUNDLE_DOLEVEL": self.o.dolevel}, ) - self.__latch_into(dir=self.itemsdir(), part=part, toplevel=False) + self.__latch_into(dirname=self.itemsdir(), part=part, toplevel=False) # --------------- # -- build_tor -- @@ -703,7 +707,7 @@ def __dump_tree_consistency_info(self, log, suite_ctxdata): "git merge-base %s %s" % (local_treeref, suite_treeref) ).strip(" \n") - (first, next) = ( + (first, next_item) = ( (suite_treeref, local_treeref) if merge_base == suite_treeref else (local_treeref, suite_treeref) @@ -711,7 +715,7 @@ def __dump_tree_consistency_info(self, log, suite_ctxdata): else (None, None) ) - if first == None: + if first is None: log.write("!!! local and suite tree refs aren't sequential !!!\n") return @@ -720,7 +724,7 @@ def __dump_tree_consistency_info(self, log, suite_ctxdata): % ("suite" if first == local_treeref else "local") ) - gitlog_cmd = "git rev-list --oneline %s ^%s" % (next, first) + gitlog_cmd = "git rev-list --oneline %s ^%s" % (next_item, first) log.write("\n".join(["", gitlog_cmd, "--", output_of(gitlog_cmd), ""])) def __dump_version_consistency_info(self, log, suite_ctxdata): @@ -910,7 +914,7 @@ def build_str(self): run("make %s" % sphinx_target_for[self.this_docformat]) - self.__latch_into(dir=self.itemsdir(), part="str", toplevel=False) + self.__latch_into(dirname=self.itemsdir(), part="str", toplevel=False) # ----------------- # -- build_plans -- @@ -930,18 +934,18 @@ def build_plans(self): # -- build_kit -- # --------------- - def __relocate_into(self, dir, part): + def __relocate_into(self, dirname, part): the_item = self.kititem_for(part=part) item_source_path = os.path.join(self.itemsdir(), the_item) - item_target_path = os.path.join(dir, the_item) + item_target_path = os.path.join(dirname, the_item) remove(item_target_path) print("move : %s" % item_source_path) - print("into : %s" % dir) + print("into : %s" % dirname) - mv(item_source_path, dir) + mv(item_source_path, dirname) def build_kit(self): announce("building %s kit" % self.this_docformat) @@ -981,7 +985,8 @@ def build_kit(self): mkdir(kitdir) - [self.__relocate_into(dir=kitdir, part=part) for part in self.o.parts] + for part in self.o.parts: + self.__relocate_into(dirname=kitdir, part=part) run("zip -q -r %(kitdir)s.zip %(kitdir)s" % {"kitdir": kitdir}) diff --git a/qualification/qm/common_conf.py b/qualification/qm/common_conf.py index f3ac04475..53b0ce2b6 100644 --- a/qualification/qm/common_conf.py +++ b/qualification/qm/common_conf.py @@ -50,7 +50,7 @@ release = "DRAFT 0.0" version = "(version %s)" % release -copyright = "%s, %d" % (owner, date.today().year) +copyright = "%s, %d" % (owner, date.today().year) # noqa: A001 extensions = ["sphinx.ext.ifconfig"] diff --git a/qualification/qm/env/env.py b/qualification/qm/env/env.py index ffb3b38c2..76339cade 100644 --- a/qualification/qm/env/env.py +++ b/qualification/qm/env/env.py @@ -5,3 +5,5 @@ "coding standard": "", "project_full": "SomeProject", } + +# flake8: noqa diff --git a/qualification/qm/genmodel.py b/qualification/qm/genmodel.py index 7afa4501a..7588e6a80 100755 --- a/qualification/qm/genmodel.py +++ b/qualification/qm/genmodel.py @@ -13,8 +13,9 @@ # traceability matrix production (and maybe the set of TORs # and testcases someday) -import sys, optparse, re -from e3.os.process import Run +import optparse +import re +import sys def exit_if(p, msg): @@ -31,22 +32,17 @@ def contents_of(filename): def __extra_block_for(dolevel): """Allow level specific local subsets of testcases.""" - return "\n".join( - ( - "", - '', - " ", - ' ', - ' ', - " ", - "", - ) - ) + return f""" + + + + + +""" RE_LANG = "([a-zA-Z]*)([0-9]*)" @@ -100,7 +96,7 @@ def __gen_model_for(dolevel, languages): # We expect one version of Ada to be part of the language set - ada_lang = [l for l in languages if "Ada" in l][0] + ada_lang = [lang for lang in languages if "Ada" in lang][0] with open("model.xml", "w") as f: f.write( @@ -122,9 +118,6 @@ def __gen_lrm_ref_for(lang): lang_version = __langversion_for(lang) - input = open("LRM/lrm_ref.txt", mode="r") - output = open("LRM/lrm_ref_%s.txt" % lang_version, mode="w") - # The reference matrix lines with section numbers and corresponding # language versions are of the form: # @@ -140,15 +133,14 @@ def __gen_lrm_ref_for(lang): short_version = lang_version[-2:] - for line in input.readlines(): - m = re.match(pattern="([0-9. ]*)#([0-9, ]*?)#", string=line) - if m and short_version not in m.group(2): - continue - - output.write(line) + with open("LRM/lrm_ref.txt", mode="r") as inf: + with open("LRM/lrm_ref_%s.txt" % lang_version, mode="w") as outf: + for line in inf: + m = re.match(pattern="([0-9. ]*)#([0-9, ]*?)#", string=line) + if m and short_version not in m.group(2): + continue - output.close() - input.close() + outf.write(line) # ======================================================================= diff --git a/qualification/qm/plans/qmconf.py b/qualification/qm/plans/qmconf.py index 3b3386119..a5e760896 100644 --- a/qualification/qm/plans/qmconf.py +++ b/qualification/qm/plans/qmconf.py @@ -21,3 +21,6 @@ print("from: %s" % __file__) doc_id = plans_doc_id + + +# flake8: noqa diff --git a/qualification/qm/qm_plugins/importers.py b/qualification/qm/qm_plugins/importers.py index 9ff4bc3f9..b980211cf 100644 --- a/qualification/qm/qm_plugins/importers.py +++ b/qualification/qm/qm_plugins/importers.py @@ -479,8 +479,8 @@ def qmlink_to_rest(self, parent, artifacts): pdf_items, title="TOR/LRM Traceability Matrix for Ada %s" % language_version, headers=["Section", "Title", "Applicable", "Comment"], - latex_format="|p{0.08\linewidth}|p{0.20\linewidth}|" - + "p{0.10\linewidth}|p{0.50\linewidth}|", + latex_format=r"|p{0.08\linewidth}|p{0.20\linewidth}|" + + r"p{0.10\linewidth}|p{0.50\linewidth}|", ) html_table = writer.csv_table( @@ -491,10 +491,10 @@ def qmlink_to_rest(self, parent, artifacts): output += ( writer.paragraph( - "This particular table is established for **Ada %s**." - % language_version - + "\n\The requirement identifiers in this table were shortened by " - "removing the *%s* common prefix.\n\n" % REQ_NAME_PREFIX + "This particular table is established for **Ada" + f" {language_version}**." + "\n\\The requirement identifiers in this table were shortened" + f" by removing the *{REQ_NAME_PREFIX}* common prefix.\n\n" ) + writer.only(pdf_table, "latex") + writer.only(html_table, "html") @@ -594,9 +594,9 @@ def qmlink_to_rest(self, parent, artifacts): output += writer.toctree( [ - "/%s/content" % artifact_hash(*l) - for l in links - if not is_tc_or_set(l[0]) or is_tc_or_set(parent) + "/%s/content" % artifact_hash(*link) + for link in links + if not is_tc_or_set(link[0]) or is_tc_or_set(parent) ], hidden=True, ) @@ -710,9 +710,9 @@ def key(a): output += writer.toctree( [ - "/%s/content" % artifact_hash(*l) - for l in links - if not is_tc_or_set(l[0]) + "/%s/content" % artifact_hash(*link) + for link in links + if not is_tc_or_set(link[0]) ], hidden=True, ) @@ -784,9 +784,9 @@ def qmlink_to_rest(self, parent, artifacts): output = writer.toctree( [ - "/%s/content" % artifact_hash(*l) - for l in links - if not is_tc_or_set(l[0]) + "/%s/content" % artifact_hash(*link) + for link in links + if not is_tc_or_set(link[0]) ], hidden=True, ) @@ -804,9 +804,9 @@ def qmlink_to_rest(self, parent, artifacts): output += writer.toctree( [ - "/%s/content" % artifact_hash(*l) - for l in links - if not is_tc_or_set(l[0]) + "/%s/content" % artifact_hash(*link) + for link in links + if not is_tc_or_set(link[0]) ], hidden=True, ) @@ -967,14 +967,12 @@ def to_rest(self, artifact): func_list, driver_list, helper_list, fillvalue="" ) - html_content = writer.csv_table([k for k in for_table_qmref], headers) + html_content = writer.csv_table(list(for_table_qmref), headers) result += writer.only(html_content, "html") if do_pdf: - latex_content = writer.csv_table( - [k for k in for_table], headers - ).strip() + latex_content = writer.csv_table(list(for_table), headers).strip() result += writer.only(latex_content, "latex") output = "\n\n" + writer.minipage(result, r"\linewidth") + "|\n\n" @@ -1061,7 +1059,7 @@ def sortkey_for(art): self.items, headers=["Kind", "Identification", "Description"], latex_format=( - "|p{0.05\linewidth}|p{0.47\linewidth}||p{0.37\linewidth}|" + r"|p{0.05\linewidth}|p{0.47\linewidth}||p{0.37\linewidth}|" ), ) @@ -1213,7 +1211,10 @@ def tc_pdf_for_subdir(self, toplevel, subdir, links): for desc in links_dict.keys(): pdf_output += writer.subsubsection(desc) + "\n" pdf_output += writer.toctree( - ["/%s/content" % artifact_hash(*l) for l in links_dict[desc]], + [ + "/%s/content" % artifact_hash(*link) + for link in links_dict[desc] + ], hidden=True, ) @@ -1243,7 +1244,7 @@ def qmlink_to_rest(self, parent, artifacts): # Build the html output html_output = writer.toctree( - ["/%s/content" % artifact_hash(*l) for l in mixed_links], + ["/%s/content" % artifact_hash(*link) for link in mixed_links], hidden=True, ) diff --git a/qualification/qm/qm_prolog.py b/qualification/qm/qm_prolog.py index b1fb705ff..01b582b46 100644 --- a/qualification/qm/qm_prolog.py +++ b/qualification/qm/qm_prolog.py @@ -74,3 +74,5 @@ # environment variable stating what --dolevel it was passed ('doA', 'doB', # or 'doC'). Expose the significant letter to documents: rst_prolog += writer.macro("dolevel", os.environ.get("GENBUNDLE_DOLEVEL")[-1]) + +# flake8: noqa diff --git a/testsuite/Qualif/qmconf.py b/testsuite/Qualif/qmconf.py index fd6b5f6c6..a589a6f54 100644 --- a/testsuite/Qualif/qmconf.py +++ b/testsuite/Qualif/qmconf.py @@ -24,3 +24,5 @@ doc_id = tor_doc_id html_sidebars = {"**": ["localtoc.html", "sourcelink.html", "searchbox.html"]} + +# flake8: noqa From 6d2596b28d42ff84ac8e60c2287d8feac0549f44 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 6 Mar 2024 09:18:49 +0000 Subject: [PATCH 0757/1483] Testsuite: do last minute reformattings --- testsuite/SCOV/internals/driver.py | 4 +++- .../231-malformed-exempt-markers/test.py | 24 ++++++++++--------- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 8fa68f688..8d0cd570f 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -888,7 +888,9 @@ def gen_xcov_reports(self): if thistest.options.qualif_level: return - self.gen_one_xcov_report(inputs, report_format="xcov", options=sco_options) + self.gen_one_xcov_report( + inputs, report_format="xcov", options=sco_options + ) def check_unexpected_reports(self): """Check that we don't have unexpected reports or notes.""" diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py index 013e50dbe..465f63c96 100644 --- a/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py @@ -11,22 +11,23 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor -Wdir('tmp_') +Wdir("tmp_") # Check gnatcov's behaviour upon encountering annotaton pragmas with correctly # types arguments. build_run_and_coverage( gprsw=GPRswitches( - gprfor(prjid="test", - srcdirs=[".."], - mains=["main_1.adb"], - langs=["Ada"])), + gprfor( + prjid="test", srcdirs=[".."], mains=["main_1.adb"], langs=["Ada"] + ) + ), covlevel="stmt", trace_mode="src", mains=["main_1"], extra_coverage_args=["--annotate=report"], - tolerate_instrument_messages=".") + tolerate_instrument_messages=".", +) # Check that gnatcov does not raise an exception when finding incorrect # annotation pragmas. In these cases, it is the compiler that is expected to @@ -34,12 +35,13 @@ xcov_instrument( gprsw=GPRswitches( - gprfor(prjid="test", - srcdirs=[".."], - mains=["main_2.adb"], - langs=["Ada"])), + gprfor( + prjid="test", srcdirs=[".."], mains=["main_2.adb"], langs=["Ada"] + ) + ), covlevel="stmt", - tolerate_messages='.') + tolerate_messages=".", +) thistest.fail_if_not_equal( "gnatcov instrument output", From 326f0655062d92e45c2424af9433c0e7051e8998 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 20 Feb 2024 09:10:16 +0000 Subject: [PATCH 0758/1483] CI: run flake8 and black pre-commit checks --- .gitlab-ci.yml | 12 ++++++++++-- .pre-commit-config-ci.yaml | 16 ++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 .pre-commit-config-ci.yaml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 4a708c69f..07d053604 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -216,7 +216,15 @@ stylechecks: - export PATH="/home/gitlab-ci/.local/bin:$PATH" - source /it/activate-py311 - - python -m pip install colorama + - python -m pip install colorama pre-commit - cd $CI_PROJECT_DIR - - python $CI_PROJECT_DIR/.check-formatting.py --force-colors + + # TODO (eng/das/cov/gnatcoverage#230): Once we have found a way to install + # the clang-format pre-commit hook in the CI, use the standard + # ".pre-commit-config.yaml" file. + - pre-commit install --config .pre-commit-config-ci.yaml + - pre-commit install-hooks --config .pre-commit-config-ci.yaml + - pre-commit run --config .pre-commit-config-ci.yaml -a --show-diff-on-failure + + - python .check-formatting.py --force-colors diff --git a/.pre-commit-config-ci.yaml b/.pre-commit-config-ci.yaml new file mode 100644 index 000000000..595ae7dbc --- /dev/null +++ b/.pre-commit-config-ci.yaml @@ -0,0 +1,16 @@ +repos: + - repo: git@ssh.gitlab.adacore-it.com:it/flake8.git + rev: 6.0.0 + hooks: + - id: flake8 + additional_dependencies: + - flake8-bugbear + - flake8-builtins + - flake8-comprehensions + - pygments + args: ["--config=.flake8"] + - repo: git@ssh.gitlab.adacore-it.com:it/black.git + rev: 23.1.0 + hooks: + - id: black + args: ["--line-length=79"] From f1981354857193f7d3a4142e868801f887181c29 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 6 Mar 2024 15:24:12 +0100 Subject: [PATCH 0759/1483] gnatcov.gpr: Fix bits arch for the "compiler" build configuration The object directory for the "compiler" build was changed by 358c9d751, but the Bits_Type for this configuration was not updated accordingly which broke incremental compilation. --- tools/gnatcov/gnatcov.gpr | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index da07bcc62..b5b1ea413 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -79,15 +79,16 @@ project Gnatcov is -- and subprograms. -- -- Note that we build the "gnatcov" driver in 32-bit mode as an - -- optimization: unlike "gnatcov64", none of "lib32", "gnatcov32" and - -- "driver" need source instrumentation support, so they all use the same - -- sources, and can thus share the same object directory. + -- optimization: unlike "gnatcov64", none of "lib32", "gnatcov32", + -- "compiler" and "driver" need source instrumentation support, + -- so they all use the same sources, and can thus share the same + -- object directory. type Bits_Type is ("32", "64"); Bits : Bits_Type := "32"; case Part is - when "lib64" | "gnatcov64" | "compiler" => Bits := "64"; - when "driver" | "lib32" | "gnatcov32" => Bits := "32"; + when "lib64" | "gnatcov64" => Bits := "64"; + when "driver" | "lib32" | "gnatcov32" | "compiler" => Bits := "32"; end case; ------------------------------------------- From 36d14f53d3c2ac62ad7eb5b9888091639c6eac28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Chigot?= Date: Fri, 1 Mar 2024 11:11:09 +0100 Subject: [PATCH 0760/1483] tools: move to a build using binutils installation Up to now, the binutils libraries were pulled from its build directory. It requires additional scenario variables, hardcoded paths, etc, making hard to maintain overall. The binutils build for gnatcoverage have been updated to install properly these libraries and to set all the required environment variable. eng/toolchain/binutils#24 --- tools/gnatcov/Makefile | 14 ----------- tools/gnatcov/README.md | 25 +++++++++++-------- tools/gnatcov/gnatcov.gpr | 18 ++++--------- tools/gnatcov/trace_adapters/trace32/Makefile | 2 -- 4 files changed, 20 insertions(+), 39 deletions(-) diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index b8ab51656..e6b82c674 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -31,9 +31,6 @@ # on possibly case-insensitive filesystems. PREFIX=$(PWD)/local -# By default, assume that the binutils dependency was built in the source tree. -BINUTILS_BUILD_DIR?=$(BINUTILS_SRC_DIR) - # ---------------- # -- To cleanup -- # ---------------- @@ -148,8 +145,6 @@ all: bin adapters BIN_COMMON_BUILD_ARGS=\ -Pgnatcov.gpr -p -j$(PROCESSORS) \ -XBUILD_MODE=$(BUILD_MODE) \ - -XBINUTILS_SRC_DIR="$(BINUTILS_SRC_DIR)" \ - -XBINUTILS_BUILD_DIR="$(BINUTILS_BUILD_DIR)" \ -XC_SUPPORT=$(C_SUPPORT) \ $(EXTRA_ADAFLAGS) \ -largs $(LD_FLAGS) \ @@ -165,15 +160,6 @@ INSTR_BIN_BUILD_ARGS=\ --implicit-with=gnatcov_rts bin: -# Unlike BINUTILS_BUILD_DIR for which we have a default fallback, -# BINUTILS_SRC_DIR must be defined explicitely. - @if [ -z "$(BINUTILS_SRC_DIR)" ]; then \ - echo "Please define the BINUTILS_SRC_DIR and" \ - " BINUTILS_BUILD_DIR variables to point to the binutils" \ - " source and build directories."; \ - exit 1; \ - fi - ifdef INSTRUMENTED # We need to instrument and build at the same time: the driver and # gnatcov32 builds share the same object directory, meaning that diff --git a/tools/gnatcov/README.md b/tools/gnatcov/README.md index 18a5fd896..d2ac8b879 100644 --- a/tools/gnatcov/README.md +++ b/tools/gnatcov/README.md @@ -59,24 +59,29 @@ environment variable designating the GNAT installation root. gnatcoll-core $ make install ``` -2. Build libopcodes, libbfd and libiberty libraries from Binutils, which - gnatcov needs to support object code disassembling on all platforms. +2. Build static libraries provided by Binutils, which gnatcov needs to support + object code disassembling on all platforms. - Best is to use a Binutils release for this, such as 2.35 which + Binutils libraries are statically linked into gnatcov, so binutils can be + installed in a temporary directory (`$prefix_binutils` in the commands below) + just for gnatcov’s build. + + Best is to use a Binutils release for this, such as 2.42 which is known to work. ```shell - binutils-2.35 $ ./configure --enable-targets=all \ + binutils-2.42 $ ./configure --enable-targets=all \ + --prefix=$prefix_binutils \ + --enable-install-libiberty \ --disable-werror --disable-gdb \ --disable-sim --disable-ld --disable-libquadmath \ --disable-readline - binutils-2.35 $ make + binutils-2.42 $ make + binutils-2.42 $ make install + binutils-2.42 $ export LIBRARY_PATH=$prefix_binutils/lib64:$prefix_binutils/lib:$LIBRARY_PATH + binutils-2.42 $ export C_INCLUDE_PATH=$prefix_binutils/include:$C_INCLUDE_PATH ``` - These libraries are statically linked, so installation is not required: the - gnatcov build process only needs access to the source+build directory (no - need to run `make install`). - 3. Build or install Libadalang: please refer to [Libadalang's instructions](https://github.com/adacore/libadalang#quick-guide-to-use-libadalang). Note that when building GNATcoverage's `master` branch, you should use @@ -95,6 +100,6 @@ environment variable designating the GNAT installation root. ```shell gnatcoverage/tools/gnatcov $ - make BINUTILS_SRC_DIR= C_SUPPORT=False bin + make C_SUPPORT=False bin make PREFIX=$prefix install-bin install-examples ``` diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index b5b1ea413..9c0cf90ca 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -41,11 +41,6 @@ project Gnatcov is -- -- * "gnatcov64": the homonym program, for everything else. - Binutils_Src_Dir := external ("BINUTILS_SRC_DIR"); - Binutils_Build_Dir := external ("BINUTILS_BUILD_DIR", Binutils_Src_Dir); - -- Directories that contain the source tree for binutils, and its build - -- tree, if different (in the case of out-of-tree builds). - ------------------------ -- Optional externals -- ------------------------ @@ -210,10 +205,7 @@ project Gnatcov is ("-gnat12", "-gnatwa", "-gnatyg"); C_Common_Switches := - ("-DTARGET_BITS=" & Bits, "-Wall", "-Wextra", "-std=c99", - "-I" & Binutils_Build_Dir & "/bfd", - "-I" & Binutils_Src_Dir & "/include", - "-I" & Binutils_Src_Dir & "/bfd"); + ("-DTARGET_BITS=" & Bits, "-Wall", "-Wextra", "-std=c99"); Mode_Switches := (); Ada_Mode_Switches := (); @@ -258,10 +250,10 @@ project Gnatcov is package Linker is for Required_Switches use - (Binutils_Build_Dir & "/opcodes/libopcodes.a", - Binutils_Build_Dir & "/bfd/libbfd.a", - Binutils_Build_Dir & "/libiberty/libiberty.a", - Binutils_Build_Dir & "/libsframe/.libs/libsframe.a", + ("-l:libopcodes.a", + "-l:libbfd.a", + "-l:libiberty.a", + "-l:libsframe.a", "-lz", "-static-libstdc++", "-static-libgcc"); diff --git a/tools/gnatcov/trace_adapters/trace32/Makefile b/tools/gnatcov/trace_adapters/trace32/Makefile index e7da42db3..44df025e8 100644 --- a/tools/gnatcov/trace_adapters/trace32/Makefile +++ b/tools/gnatcov/trace_adapters/trace32/Makefile @@ -30,8 +30,6 @@ all: bin BIN_COMMON_BUILD_ARGS=\ -Ptrace32.gpr -p -j$(PARALLEL_BUILD) \ - -XBINUTILS_SRC_DIR="$(BINUTILS_SRC_DIR)" \ - -XBINUTILS_BUILD_DIR="$(BINUTILS_BUILD_DIR)" \ -largs $(LD_FLAGS) \ -cargs:c++ $(CXXFLAGS) \ $(EXTRA_ADAFLAGS) \ From cd4c89ff34767a534cf582c9c2be7881396a04b2 Mon Sep 17 00:00:00 2001 From: Fedor Rybin Date: Wed, 6 Mar 2024 22:28:15 +0300 Subject: [PATCH 0761/1483] Document --reporter switch for gnattest Fixes eng/ide/libadalang-tools#111 --- doc/gnattest/gnattest_part.rst | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/doc/gnattest/gnattest_part.rst b/doc/gnattest/gnattest_part.rst index b93c0e463..01b46efc8 100644 --- a/doc/gnattest/gnattest_part.rst +++ b/doc/gnattest/gnattest_part.rst @@ -382,6 +382,14 @@ Switches for ``gnattest`` in framework generation mode Adds time measurements for each test in generated test driver. + .. index:: --reporter (gnattest) + +:switch:`--reporter={val}` + Use specified reporter in the test driver. ``val`` is expected to be a name + of child package of AUnit.Reporter. Test drivers generated with non-default + reporter specified cannot be properly processd by test execution mode of ``gnattest``. + + :switch:`--tests-root`, :switch:`--subdirs` and :switch:`--tests-dir` switches are mutually exclusive. From 5974d4ab73e1fb4df1b3a89281a7dc1d4735c8df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 10 Jan 2024 15:01:30 +0100 Subject: [PATCH 0762/1483] Mention possibility of covering some contracts With the addition of assertion coverage, the statement that no coverage obligations are ever generated for contracts has become false. Adapt this statement to mention in which cases gnatcov can perform coverage analysis of contracts. --- doc/gnatcov/cov_source.rst | 2 +- doc/gnatcov/src_traces.rst | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index aa98d2a72..a389fee79 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -1474,7 +1474,7 @@ absence of other known violations for that same line. .. _scov-atcc: -Assertion True Condition Coverage analysis (ATCC) +Assertion True Condition Coverage (ATCC) analysis ================================================= Core notions and Reporting (:cmd-option:`--level=...+atcc`) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index e24701e7f..48954d646 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -684,7 +684,8 @@ Some parts of SPARK sources do not necessarily generate executable code when compiled, and are mainly used to aid the proof of the program. Computing coverage for such source regions isn't meaningful and are thus ignored by the instrumenter. This means that those regions will not have any -coverage obligation attached to them in the coverage reports. +coverage obligation attached to them in the coverage reports, unless +explicity requested by enabling the coverage of assertions. The concerned pieces of code are notably: @@ -695,6 +696,11 @@ Note that since no coverage obligations are emitted for such source constructs, they will not appear in the coverage reports even if assertions are enabled and the assertion policy enables the compilation of ghost code. +It is however possible to request coverage information for some contracts that +generate executable code with assertion coverage levels, as described in +:ref:`scov-atc` and :ref:`scov-atcc`. Note that any ghost code that is not +part of a contract will never be instrumented. + .. _examples_src_traces: Example use cases From bd3e2c88046378cb5b2b40cd7f11b4bdf9e15941 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 21 Jun 2023 13:50:06 +0200 Subject: [PATCH 0763/1483] Add generation of coverage percentage indices When generating xcov, xcov+ and report format reports coverage indices are also generated, one for the enabled coverage level and one for the lines metric. They contain the percentage of lines/obligations that fall under each coverage state of each unit of interest, project and aggregation of all projects. Also, only log the creation of an output directory if quiet mode is disabled or if the directory to be created is an output subdirectory. --- .../tests/QC29-006-index/ref-sid/atc.index | 27 + .../tests/QC29-006-index/ref-sid/atcc.index | 27 + .../QC29-006-index/ref-sid/decision.index | 27 + .../tests/QC29-006-index/ref-sid/lines.index | 27 + .../tests/QC29-006-index/ref-sid/mcdc.index | 27 + .../tests/QC29-006-index/ref-sid/stmt.index | 27 + testsuite/tests/QC29-006-index/ref/atc.index | 39 ++ testsuite/tests/QC29-006-index/ref/atcc.index | 39 ++ .../tests/QC29-006-index/ref/decision.index | 39 ++ .../tests/QC29-006-index/ref/lines.index | 39 ++ testsuite/tests/QC29-006-index/ref/mcdc.index | 39 ++ testsuite/tests/QC29-006-index/ref/stmt.index | 39 ++ .../tests/QC29-006-index/src-lib/lib.ads | 8 + testsuite/tests/QC29-006-index/src-root/a.adb | 6 + testsuite/tests/QC29-006-index/src-root/a.ads | 3 + .../tests/QC29-006-index/src-root/main.adb | 18 + .../QC29-006-index/src-root/src-foo/b.ads | 3 + .../QC29-006-index/src-root/src-foo/foo.adb | 29 ++ .../QC29-006-index/src-root/src-foo/foo.ads | 1 + .../src-root/src-foo/src-bar/bar.adb | 32 ++ .../src-root/src-foo/src-bar/bar.ads | 1 + testsuite/tests/QC29-006-index/test.opt | 1 + testsuite/tests/QC29-006-index/test.py | 169 ++++++ tools/gnatcov/annotations-index.adb | 488 ++++++++++++++++++ tools/gnatcov/annotations-index.ads | 25 + tools/gnatcov/files_table.ads | 4 +- tools/gnatcov/gnatcov_bits_specific.adb | 11 + tools/gnatcov/outputs.adb | 7 +- tools/gnatcov/outputs.ads | 5 +- 29 files changed, 1201 insertions(+), 6 deletions(-) create mode 100644 testsuite/tests/QC29-006-index/ref-sid/atc.index create mode 100644 testsuite/tests/QC29-006-index/ref-sid/atcc.index create mode 100644 testsuite/tests/QC29-006-index/ref-sid/decision.index create mode 100644 testsuite/tests/QC29-006-index/ref-sid/lines.index create mode 100644 testsuite/tests/QC29-006-index/ref-sid/mcdc.index create mode 100644 testsuite/tests/QC29-006-index/ref-sid/stmt.index create mode 100644 testsuite/tests/QC29-006-index/ref/atc.index create mode 100644 testsuite/tests/QC29-006-index/ref/atcc.index create mode 100644 testsuite/tests/QC29-006-index/ref/decision.index create mode 100644 testsuite/tests/QC29-006-index/ref/lines.index create mode 100644 testsuite/tests/QC29-006-index/ref/mcdc.index create mode 100644 testsuite/tests/QC29-006-index/ref/stmt.index create mode 100644 testsuite/tests/QC29-006-index/src-lib/lib.ads create mode 100644 testsuite/tests/QC29-006-index/src-root/a.adb create mode 100644 testsuite/tests/QC29-006-index/src-root/a.ads create mode 100644 testsuite/tests/QC29-006-index/src-root/main.adb create mode 100644 testsuite/tests/QC29-006-index/src-root/src-foo/b.ads create mode 100644 testsuite/tests/QC29-006-index/src-root/src-foo/foo.adb create mode 100644 testsuite/tests/QC29-006-index/src-root/src-foo/foo.ads create mode 100644 testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.adb create mode 100644 testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.ads create mode 100644 testsuite/tests/QC29-006-index/test.opt create mode 100644 testsuite/tests/QC29-006-index/test.py create mode 100644 tools/gnatcov/annotations-index.adb create mode 100644 tools/gnatcov/annotations-index.ads diff --git a/testsuite/tests/QC29-006-index/ref-sid/atc.index b/testsuite/tests/QC29-006-index/ref-sid/atc.index new file mode 100644 index 000000000..9863aea7d --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref-sid/atc.index @@ -0,0 +1,27 @@ +atc + +Global: + - 66%, ! 0%, + 33% out of 6 obligations + + +Other sources: + - 66%, ! 0%, + 33% out of 6 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + b.ads: + - -%, ! -%, + -% out of 0 obligations + bar.adb: + - 100%, ! 0%, + 0% out of 1 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 3 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + lib.ads: + - 0%, ! 0%, + 100% out of 2 obligations + main.adb: + - -%, ! -%, + -% out of 0 obligations diff --git a/testsuite/tests/QC29-006-index/ref-sid/atcc.index b/testsuite/tests/QC29-006-index/ref-sid/atcc.index new file mode 100644 index 000000000..34af82743 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref-sid/atcc.index @@ -0,0 +1,27 @@ +atcc + +Global: + - 81%, ! 0%, + 18% out of 11 obligations + + +Other sources: + - 81%, ! 0%, + 18% out of 11 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + b.ads: + - -%, ! -%, + -% out of 0 obligations + bar.adb: + - 100%, ! 0%, + 0% out of 1 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 6 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + lib.ads: + - 50%, ! 0%, + 50% out of 4 obligations + main.adb: + - -%, ! -%, + -% out of 0 obligations diff --git a/testsuite/tests/QC29-006-index/ref-sid/decision.index b/testsuite/tests/QC29-006-index/ref-sid/decision.index new file mode 100644 index 000000000..7635c019d --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref-sid/decision.index @@ -0,0 +1,27 @@ +decision + +Global: + - 57%, ! 42%, + 0% out of 7 obligations + + +Other sources: + - 57%, ! 42%, + 0% out of 7 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + b.ads: + - -%, ! -%, + -% out of 0 obligations + bar.adb: + - 100%, ! 0%, + 0% out of 1 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 3 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + lib.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - 0%, ! 100%, + 0% out of 3 obligations diff --git a/testsuite/tests/QC29-006-index/ref-sid/lines.index b/testsuite/tests/QC29-006-index/ref-sid/lines.index new file mode 100644 index 000000000..5ecdce6d5 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref-sid/lines.index @@ -0,0 +1,27 @@ +lines + +Global: + - 69%, ! 12%, + 18% out of 33 lines + + +Other sources: + - 69%, ! 12%, + 18% out of 33 lines + + a.adb: + - 0%, ! 0%, + 100% out of 1 lines + a.ads: + - -%, ! -%, + -% out of 0 lines + b.ads: + - 100%, ! 0%, + 0% out of 1 lines + bar.adb: + - 100%, ! 0%, + 0% out of 11 lines + bar.ads: + - -%, ! -%, + -% out of 0 lines + foo.adb: + - 100%, ! 0%, + 0% out of 10 lines + foo.ads: + - -%, ! -%, + -% out of 0 lines + lib.ads: + - 0%, ! 33%, + 66% out of 3 lines + main.adb: + - 14%, ! 42%, + 42% out of 7 lines diff --git a/testsuite/tests/QC29-006-index/ref-sid/mcdc.index b/testsuite/tests/QC29-006-index/ref-sid/mcdc.index new file mode 100644 index 000000000..c5cdd49d4 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref-sid/mcdc.index @@ -0,0 +1,27 @@ +mcdc + +Global: + - 100%, ! 0%, + 0% out of 13 obligations + + +Other sources: + - 100%, ! 0%, + 0% out of 13 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + b.ads: + - -%, ! -%, + -% out of 0 obligations + bar.adb: + - 100%, ! 0%, + 0% out of 3 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 4 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + lib.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - 100%, ! 0%, + 0% out of 6 obligations diff --git a/testsuite/tests/QC29-006-index/ref-sid/stmt.index b/testsuite/tests/QC29-006-index/ref-sid/stmt.index new file mode 100644 index 000000000..319ac824b --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref-sid/stmt.index @@ -0,0 +1,27 @@ +stmt + +Global: + - 74%, ! 0%, + 25% out of 31 obligations + + +Other sources: + - 74%, ! 0%, + 25% out of 31 obligations + + a.adb: + - 0%, ! 0%, + 100% out of 1 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + b.ads: + - 100%, ! 0%, + 0% out of 1 obligations + bar.adb: + - 100%, ! 0%, + 0% out of 11 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 10 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + lib.ads: + - 0%, ! 0%, + 100% out of 1 obligations + main.adb: + - 14%, ! 0%, + 85% out of 7 obligations diff --git a/testsuite/tests/QC29-006-index/ref/atc.index b/testsuite/tests/QC29-006-index/ref/atc.index new file mode 100644 index 000000000..c3487adf5 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref/atc.index @@ -0,0 +1,39 @@ +atc + +Global: + - 66%, ! 0%, + 33% out of 6 obligations + + +bar: + - 100%, ! 0%, + 0% out of 1 obligations + + bar.adb: + - 100%, ! 0%, + 0% out of 1 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + +foo: + - 100%, ! 0%, + 0% out of 3 obligations + + b.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 3 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + +lib: + - 0%, ! 0%, + 100% out of 2 obligations + + lib.ads: + - 0%, ! 0%, + 100% out of 2 obligations + +main: + - -%, ! -%, + -% out of 0 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - -%, ! -%, + -% out of 0 obligations diff --git a/testsuite/tests/QC29-006-index/ref/atcc.index b/testsuite/tests/QC29-006-index/ref/atcc.index new file mode 100644 index 000000000..af3b52610 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref/atcc.index @@ -0,0 +1,39 @@ +atcc + +Global: + - 81%, ! 0%, + 18% out of 11 obligations + + +bar: + - 100%, ! 0%, + 0% out of 1 obligations + + bar.adb: + - 100%, ! 0%, + 0% out of 1 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + +foo: + - 100%, ! 0%, + 0% out of 6 obligations + + b.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 6 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + +lib: + - 50%, ! 0%, + 50% out of 4 obligations + + lib.ads: + - 50%, ! 0%, + 50% out of 4 obligations + +main: + - -%, ! -%, + -% out of 0 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - -%, ! -%, + -% out of 0 obligations diff --git a/testsuite/tests/QC29-006-index/ref/decision.index b/testsuite/tests/QC29-006-index/ref/decision.index new file mode 100644 index 000000000..da1717404 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref/decision.index @@ -0,0 +1,39 @@ +decision + +Global: + - 57%, ! 42%, + 0% out of 7 obligations + + +bar: + - 100%, ! 0%, + 0% out of 1 obligations + + bar.adb: + - 100%, ! 0%, + 0% out of 1 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + +foo: + - 100%, ! 0%, + 0% out of 3 obligations + + b.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 3 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + +lib: + - -%, ! -%, + -% out of 0 obligations + + lib.ads: + - -%, ! -%, + -% out of 0 obligations + +main: + - 0%, ! 100%, + 0% out of 3 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - 0%, ! 100%, + 0% out of 3 obligations diff --git a/testsuite/tests/QC29-006-index/ref/lines.index b/testsuite/tests/QC29-006-index/ref/lines.index new file mode 100644 index 000000000..7d8d07366 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref/lines.index @@ -0,0 +1,39 @@ +lines + +Global: + - 69%, ! 12%, + 18% out of 33 lines + + +bar: + - 100%, ! 0%, + 0% out of 11 lines + + bar.adb: + - 100%, ! 0%, + 0% out of 11 lines + bar.ads: + - -%, ! -%, + -% out of 0 lines + +foo: + - 100%, ! 0%, + 0% out of 11 lines + + b.ads: + - 100%, ! 0%, + 0% out of 1 lines + foo.adb: + - 100%, ! 0%, + 0% out of 10 lines + foo.ads: + - -%, ! -%, + -% out of 0 lines + +lib: + - 0%, ! 33%, + 66% out of 3 lines + + lib.ads: + - 0%, ! 33%, + 66% out of 3 lines + +main: + - 12%, ! 37%, + 50% out of 8 lines + + a.adb: + - 0%, ! 0%, + 100% out of 1 lines + a.ads: + - -%, ! -%, + -% out of 0 lines + main.adb: + - 14%, ! 42%, + 42% out of 7 lines diff --git a/testsuite/tests/QC29-006-index/ref/mcdc.index b/testsuite/tests/QC29-006-index/ref/mcdc.index new file mode 100644 index 000000000..408a15798 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref/mcdc.index @@ -0,0 +1,39 @@ +mcdc + +Global: + - 100%, ! 0%, + 0% out of 13 obligations + + +bar: + - 100%, ! 0%, + 0% out of 3 obligations + + bar.adb: + - 100%, ! 0%, + 0% out of 3 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + +foo: + - 100%, ! 0%, + 0% out of 4 obligations + + b.ads: + - -%, ! -%, + -% out of 0 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 4 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + +lib: + - -%, ! -%, + -% out of 0 obligations + + lib.ads: + - -%, ! -%, + -% out of 0 obligations + +main: + - 100%, ! 0%, + 0% out of 6 obligations + + a.adb: + - -%, ! -%, + -% out of 0 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - 100%, ! 0%, + 0% out of 6 obligations diff --git a/testsuite/tests/QC29-006-index/ref/stmt.index b/testsuite/tests/QC29-006-index/ref/stmt.index new file mode 100644 index 000000000..7fec24cb9 --- /dev/null +++ b/testsuite/tests/QC29-006-index/ref/stmt.index @@ -0,0 +1,39 @@ +stmt + +Global: + - 74%, ! 0%, + 25% out of 31 obligations + + +bar: + - 100%, ! 0%, + 0% out of 11 obligations + + bar.adb: + - 100%, ! 0%, + 0% out of 11 obligations + bar.ads: + - -%, ! -%, + -% out of 0 obligations + +foo: + - 100%, ! 0%, + 0% out of 11 obligations + + b.ads: + - 100%, ! 0%, + 0% out of 1 obligations + foo.adb: + - 100%, ! 0%, + 0% out of 10 obligations + foo.ads: + - -%, ! -%, + -% out of 0 obligations + +lib: + - 0%, ! 0%, + 100% out of 1 obligations + + lib.ads: + - 0%, ! 0%, + 100% out of 1 obligations + +main: + - 12%, ! 0%, + 87% out of 8 obligations + + a.adb: + - 0%, ! 0%, + 100% out of 1 obligations + a.ads: + - -%, ! -%, + -% out of 0 obligations + main.adb: + - 14%, ! 0%, + 85% out of 7 obligations diff --git a/testsuite/tests/QC29-006-index/src-lib/lib.ads b/testsuite/tests/QC29-006-index/src-lib/lib.ads new file mode 100644 index 000000000..248add341 --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-lib/lib.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Lib is + function Id (B : Boolean) return Boolean is (B) + with Pre => B or else not B or else B, + Post => Id'Result = B; +end Lib; diff --git a/testsuite/tests/QC29-006-index/src-root/a.adb b/testsuite/tests/QC29-006-index/src-root/a.adb new file mode 100644 index 000000000..4d38cf1f6 --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/a.adb @@ -0,0 +1,6 @@ +package body A is + procedure A_Proc (Dummy : Boolean) is + begin + null; + end A_Proc; +end A; diff --git a/testsuite/tests/QC29-006-index/src-root/a.ads b/testsuite/tests/QC29-006-index/src-root/a.ads new file mode 100644 index 000000000..7035b4026 --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/a.ads @@ -0,0 +1,3 @@ +package A is + procedure A_Proc (Dummy : Boolean); +end A; diff --git a/testsuite/tests/QC29-006-index/src-root/main.adb b/testsuite/tests/QC29-006-index/src-root/main.adb new file mode 100644 index 000000000..6e63c63c7 --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/main.adb @@ -0,0 +1,18 @@ +with A; +with Foo; +with Lib; + +procedure Main is + T : Boolean := True; + F : Boolean := False; +begin + if Lib.Id (T) or else F then + T := T and then True; + end if; + + if F and then Foo then + F := F and then False; + end if; + + A.A_Proc (True); +end Main; diff --git a/testsuite/tests/QC29-006-index/src-root/src-foo/b.ads b/testsuite/tests/QC29-006-index/src-root/src-foo/b.ads new file mode 100644 index 000000000..89a3e5a35 --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/src-foo/b.ads @@ -0,0 +1,3 @@ +package B is + function Return_T return Boolean is (True); +end B; diff --git a/testsuite/tests/QC29-006-index/src-root/src-foo/foo.adb b/testsuite/tests/QC29-006-index/src-root/src-foo/foo.adb new file mode 100644 index 000000000..e9b1738b9 --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/src-foo/foo.adb @@ -0,0 +1,29 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +with Bar; +with Lib; + +function Foo return Boolean +is + T : Boolean := True; + F : Boolean := False; +begin + if not T then + T := T and then T; + end if; + + begin + if T then + pragma Assert (T); + pragma Assert (T or else T or else T); + pragma Assert (T and then Lib.Id (F)); + end if; + exception + when Ada.Assertions.Assertion_Error => null; + end; + + return T; +end Foo; diff --git a/testsuite/tests/QC29-006-index/src-root/src-foo/foo.ads b/testsuite/tests/QC29-006-index/src-root/src-foo/foo.ads new file mode 100644 index 000000000..b7cfdb3ca --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/src-foo/foo.ads @@ -0,0 +1 @@ +function Foo return Boolean; diff --git a/testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.adb b/testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.adb new file mode 100644 index 000000000..efc9e191f --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.adb @@ -0,0 +1,32 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +function Bar return Boolean +is + T : Boolean := True; + F : Boolean := False; + + Res : Boolean := False; + + function MCDC_Violation (A, B : Boolean) return Boolean is + begin + if (A and then not B) or else A then + return True; + end if; + return True; + end MCDC_Violation; + +begin + Res := MCDC_Violation (T, F); + Res := MCDC_Violation (F, F); + + begin + pragma Assert (Res); + exception + when Ada.Assertions.Assertion_Error => null; + end; + + return Res; +end Bar; diff --git a/testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.ads b/testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.ads new file mode 100644 index 000000000..f51db2cee --- /dev/null +++ b/testsuite/tests/QC29-006-index/src-root/src-foo/src-bar/bar.ads @@ -0,0 +1 @@ +function Bar return Boolean; diff --git a/testsuite/tests/QC29-006-index/test.opt b/testsuite/tests/QC29-006-index/test.opt new file mode 100644 index 000000000..7ba037dcf --- /dev/null +++ b/testsuite/tests/QC29-006-index/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Test uses pre/postconditions as apects for ATCC coverage diff --git a/testsuite/tests/QC29-006-index/test.py b/testsuite/tests/QC29-006-index/test.py new file mode 100644 index 000000000..c00f7712f --- /dev/null +++ b/testsuite/tests/QC29-006-index/test.py @@ -0,0 +1,169 @@ +""" +Test that the coverage indices generated along the xcov and report format +reports contains the correct information. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov, srctracename_for +from SUITE.gprutils import GPRswitches + +import glob + + +def create_lib_gpr(name, srcdir, objdir, deps=None, extra=""): + """ + Create a gpr file for the library. + + :param name: Name of the library. + """ + + return gprfor( + mains=[], + prjid=name, + srcdirs=[srcdir], + objdir=objdir, + langs=["Ada"], + deps=deps, + extra=extra, + ) + + +tmp = Wdir("tmp_") + +# Create the GPR file for the root project +src_gpr = gprfor( + mains=["main.adb"], + prjid="main", + srcdirs=["../src-root"], + objdir="obj", + langs=["Ada"], + deps=["foo", "lib"], +) + +# Create the GPR files for the libraries +lib_gpr = create_lib_gpr( + "lib", + "../src-lib", + "obj-lib", + extra=""" + for Library_Name use "lib"; + for Library_Dir use "lib"; + """, +) +foo_gpr = create_lib_gpr( + "foo", "../src-root/src-foo", "obj-foo", ["bar", "lib"] +) +bar_gpr = create_lib_gpr("bar", "../src-root/src-foo/src-bar", "obj-bar") + +gprsw = GPRswitches(root_project=src_gpr) + + +def check_indices(metrics, statsdir, refdir=""): + """ + Check that the index file corresponding to each coverage metric in + "metrics" contains the expected statistics. + """ + + for metric in metrics: + filename = f"{metric}.index" + idx = f"{statsdir}/{filename}" + ref = f"{refdir}/{filename}" + ref_path = f"../{ref}" + + if thistest.options.trace_mode == "src": + thistest.fail_if_diff( + ref_path, + idx, + f"unexpected index content for {filename} " + f"with baseline {ref}", + ) + else: + idx_contents = contents_of(idx) + ref_contents = ( + r"(.|\n)*bar:" + r"\n - 100%, ! 0%, \+ 0% out of 15 lines" + r"\n" + r"\n bar.adb:" + r"\n - 100%, ! 0%, \+ 0% out of 15 lines" + r"\n" + r"\nfoo:" + r"\n - 100%, ! 0%, \+ 0% out of 8 lines" + r"\n" + r"\n foo.adb:" + r"\n - 100%, ! 0%, \+ 0% out of 8 lines" + r"\n" + r"\nlib:" + r"\n - 0%, ! 66%, \+ 33% out of 3 lines" + r"\n" + r"\n lib.ads:" + r"\n - 0%, ! 66%, \+ 33% out of 3 lines" + r"\n" + r"\nmain:" + r"\n - 0%, ! 10%, \+ 90% out of 10 lines" + r"\n" + r"\n a.adb:" + r"\n - 0%, ! 0%, \+ 100% out of 3 lines" + r"\n a.ads:" + r"\n - -%, ! -%, \+ -% out of 0 lines" + r"\n main.adb:" + r"\n - 0%, ! 14%, \+ 85% out of 7 lines" + r"(.|\n)*" + ) + thistest.fail_if_no_match( + f"Unexpected coverage index {idx}" " content", + ref_contents, + idx_contents, + ) + + +if thistest.options.trace_mode == "src": + # Instrument and run coverage analysis, then check that the coverage stats + # are correct. + build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt+mcdc+atcc", + mains=["main"], + extra_coverage_args=["--annotate=xcov,report"], + out="coverage.log", + ) + + metrics = ["lines", "stmt", "decision", "mcdc", "atc", "atcc"] + check_indices(metrics, "obj/stats", "ref") + + # Now compute the coverage by using .sid files. There is no project + # information available for the sources and we expected their stats to be + # displayed under the "Other sources" category. + objdirs = glob.glob("obj*") + sids = [] + for objdir in objdirs: + sids += glob.glob(f"{objdir}/*.sid") + + xcov( + [ + "coverage", + "--level=stmt+mcdc+atcc", + "--annotate=xcov,report,cobertura", + ] + + ["--sid=" + file for file in sids] + + ["--trace=" + srctracename_for("main")], + out="coverage.log", + ) + + check_indices(metrics, "stats", "ref-sid") + +else: + metrics = ["lines"] + + build_run_and_coverage( + gprsw=gprsw, + covlevel="branch", + mains=["main"], + extra_coverage_args=["--annotate=xcov+,cobertura"], + out="couverage.log", + ) + + check_indices(metrics, "obj/stats") + +thistest.result() diff --git a/tools/gnatcov/annotations-index.adb b/tools/gnatcov/annotations-index.adb new file mode 100644 index 000000000..1e3600493 --- /dev/null +++ b/tools/gnatcov/annotations-index.adb @@ -0,0 +1,488 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 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.Characters.Handling; +with Ada.Containers.Indefinite_Ordered_Maps; +with Ada.Text_IO; use Ada.Text_IO; + +with GNAT.OS_Lib; + +with Coverage; use Coverage; +with Coverage_Options; use Coverage_Options; +with Project; +with Outputs; use Outputs; + +-- This package generates one coverage statistics report per enabled coverage +-- level and one for the coverage stats of lines. If multiple report formats +-- are to be generated, these stats are created in a "stats" subdirectory. + +package body Annotations.Index is + + subtype Index_Cov_States is Any_Line_State range Not_Covered .. Covered; + subtype Percentage is Natural range 0 .. 100; + + type Stats_Per_State is array (Index_Cov_States) of Natural + with Default_Component_Value => 0; + -- Array of coverage percentage per coverage state + + type Project_Stats is record + Total : Natural := 0; + -- Total number of lines/obligations to be covered + + Stats : Stats_Per_State; + -- Array of coverage percentage per state + + Files_Stats : Strings.Unbounded_String; + -- String expressing the coverage stats of each of the project's units + -- of interest. + + end record; + -- Record storing a project's coverage information + + package Projects_Stats_Maps is new Ada.Containers.Indefinite_Ordered_Maps + (Key_Type => String, + Element_Type => Project_Stats); + -- Map associating the project's name to its coverage statistics + + function "+" (P : Percentage) return String; + -- Return a string representation of P that is always three characters long + -- by replacing the missing digits by spaces. + + function Build_Stat_String + (Name : String; + Stats : Stats_Per_State; + Total : Natural; + Lines : Boolean; + Is_Prj : Boolean := False) + return String; + -- Return a formated string expressing the coverage stats + + function Compute_Percentage + (Stats : Stats_Per_State; + Total : Positive) + return Stats_Per_State; + -- Return an array of coverage percentage, dividing each value of Stats by + -- Total. + + procedure Generate_Index + (L : Coverage_Level := Stmt; + Lines : Boolean); + -- Generate the coverage index file for coverage level L, or for lines if + -- Lines is set to True. + + ---------------------- + -- Generate_Indices -- + ---------------------- + + procedure Generate_Indices + is + Output_Dir : constant String := Get_Output_Dir; + Output_Subdir : constant String := + Output_Dir & "/stats" & GNAT.OS_Lib.Directory_Separator; + begin + if Annotations.Multiple_Reports then + -- Create a "stats" directory where the + -- "-.index" files will be stored. + + Clean_Dir (Output_Subdir, ""); + Set_Output_Dir (Output_Subdir); + end if; + + -- Generate the index for lines... + Generate_Index (Lines => True); + + -- ... and the indices for each enabled source coverage level + for Cov_Lvl in Source_Coverage_Level loop + if Enabled (Cov_Lvl) + or else (Cov_Lvl = Decision and then Decision_Coverage_Enabled) + or else (Cov_Lvl = ATC and then Assertion_Coverage_Enabled) + then + Generate_Index (L => Cov_Lvl, Lines => False); + end if; + end loop; + + if Annotations.Multiple_Reports then + -- Set the output dir to its original value + Set_Output_Dir (Output_Dir); + end if; + end Generate_Indices; + + --------- + -- "+" -- + --------- + + function "+" (P : Percentage) return String + is + P_Str : Unbounded_String := +Percentage'Image (P); + Needed_Spaces : constant Natural := 3 - (Length (P_Str) - 1); + begin + for I in 1 .. Needed_Spaces loop + P_Str := " " & P_Str; + end loop; + + return +P_Str; + end "+"; + + ----------------------- + -- Build_Stat_String -- + ----------------------- + + function Build_Stat_String + (Name : String; + Stats : Stats_Per_State; + Total : Natural; + Lines : Boolean; + Is_Prj : Boolean := False) + return String + is + function Metric_Stats + (Stats : Stats_Per_State; + Total : Natural) + return String; + -- Express the Stats as a string + + ------------------ + -- Metric_Stats -- + ------------------ + + function Metric_Stats + (Stats : Stats_Per_State; + Total : Natural) + return String + is + Percentages : Stats_Per_State; + Res : Unbounded_String := +"- -%, ! -%, + -%"; + begin + if Is_Prj and then Total = 0 then + return +Res; + end if; + + if Total /= 0 then + Percentages := Compute_Percentage (Stats, Total); + Res := Null_Unbounded_String; + + for State in Stats'Range loop + Append + (Res, + State_Char (State) + & (+Percentages (State)) + & "%" + & (if State /= Stats'Last then ", " else "")); + end loop; + end if; + + return +Res; + end Metric_Stats; + begin + return + +(+(if Is_Prj then "" else " ") + & Name & ":" & ASCII.LF + & " " & Metric_Stats (Stats, Total) + & " out of" & Natural'Image (Total) + & (if Lines then " lines" else " obligations")); + end Build_Stat_String; + + ------------------------- + -- Compute_Percentage -- + ------------------------- + + function Compute_Percentage + (Stats : Stats_Per_State; + Total : Positive) + return Stats_Per_State + is + begin + return Res : Stats_Per_State do + for State in Stats_Per_State'Range loop + Res (State) := (Stats (State) * 100) / Total; + end loop; + end return; + end Compute_Percentage; + + -------------------- + -- Generate_Index -- + -------------------- + + procedure Generate_Index + (L : Coverage_Level := Stmt; + Lines : Boolean) + is + Projects_Stats : Projects_Stats_Maps.Map := + Projects_Stats_Maps.Empty_Map; + Other_Sources_Stats : Project_Stats; + + procedure Update + (Prj_Stats : in out Project_Stats; + File_Total : Natural; + File_Stats : Stats_Per_State; + File_Name : String; + Lines : Boolean; + Is_Prj : Boolean := False); + -- Update a project's stats with those of a file + + procedure Process_One_File (Source_Index : Source_File_Index); + -- Compute and store the coverage statistics for the file designated by + -- Source_Index. + + procedure Write_Index; + -- Create the index file and write the coverage statistics in it + + ------------ + -- Update -- + ------------ + + procedure Update + (Prj_Stats : in out Project_Stats; + File_Total : Natural; + File_Stats : Stats_Per_State; + File_Name : String; + Lines : Boolean; + Is_Prj : Boolean := False) + is + begin + -- If the file contained relevant obligations or lines, update its + -- project's statistics. + + if File_Total /= 0 then + + -- If no file containing relevant coverage obligations had already + -- been registered under this project, the project's stats are the + -- same as that of the file for now... + + if Prj_Stats.Total = 0 then + Prj_Stats.Total := File_Total; + Prj_Stats.Stats := File_Stats; + else + -- ... otherwise update the project stats accordingly + + Prj_Stats.Total := Prj_Stats.Total + File_Total; + + -- For now the files' obligations per state are only added. + -- Only all stats have been stored must they be divided by the + -- total number of obligations to get the project's coverage + -- percentages. + + for State in Stats_Per_State'Range loop + Prj_Stats.Stats (State) := + (Prj_Stats.Stats (State) + File_Stats (State)); + end loop; + end if; + end if; + + -- Finally, append the string representation of the file's statistics + + Append + (Prj_Stats.Files_Stats, + ASCII.LF & (if Is_Prj then "" & ASCII.LF else "") + & Build_Stat_String + (File_Name, + File_Stats, + File_Total, + Lines => Lines, + Is_Prj => Is_Prj)); + end Update; + + ---------------------- + -- Process_One_File -- + ---------------------- + + procedure Process_One_File (Source_Index : Source_File_Index) + is + Info : constant File_Info_Access := Get_File (Source_Index); + Total : constant Natural := + (if Info.Kind = Source_File + then + (if Lines + then Get_Total (Info.Li_Stats) + else Info.Ob_Stats (L).Total) + else 0); + + function Compute_File_Stats return Stats_Per_State; + -- Compute the coverage statistics of the file designated by + -- Source_Index + + ------------------------ + -- Compute_File_Stats -- + ------------------------ + + function Compute_File_Stats return Stats_Per_State is + begin + return Result : Stats_Per_State do + for State in Stats_Per_State'Range loop + Result (State) := + (if Total = 0 + then 0 + else + (if Lines + then Info.Li_Stats (State) + else Info.Ob_Stats (L).Stats (State))); + end loop; + end return; + end Compute_File_Stats; + + Stats : constant Stats_Per_State := Compute_File_Stats; + Source_Name : constant String := Info.Simple_Name.all; + Prj_Name : constant String := + (if Info.Kind = Source_File and then Project.Is_Project_Loaded + then Project.Project_Name + (Get_Full_Name (Source_Index, Or_Simple => True)) + else ""); + -- Note that P_Name can be "" here either because we don't have + -- a root project at all or because we were unable to find the + -- project to which the source pertains. + + -- Start of Process_One_File + + begin + -- If we know to which project the file belongs to, store its stats + -- properly. Else, store the stats in Other_Projects_Stats. + + if Prj_Name /= "" then + declare + procedure Update_Stats + (Key : String; + Element : in out Project_Stats); + -- Update the project's stats according to the file's + + ------------------ + -- Update_Stats -- + ------------------ + + procedure Update_Stats + (Key : String; + Element : in out Project_Stats) + is + pragma Unreferenced (Key); + begin + Update (Element, + Total, + Stats, + Source_Name, + Lines => Lines, + Is_Prj => False); + end Update_Stats; + + Prj_C : constant Projects_Stats_Maps.Cursor := + Projects_Stats.Find (Prj_Name); + begin + if not Projects_Stats_Maps.Has_Element (Prj_C) then + Projects_Stats.Insert + (Prj_Name, + (Total => Total, + Stats => Stats, + Files_Stats => + ASCII.LF + & (+Build_Stat_String + (Source_Name, Stats, Total, Lines)))); + else + Projects_Stats.Update_Element (Prj_C, Update_Stats'Access); + end if; + end; + else + if Info.Kind = Source_File then + Update (Other_Sources_Stats, + Total, + Stats, + Source_Name, + Lines => Lines, + Is_Prj => False); + end if; + end if; + end Process_One_File; + + ----------------- + -- Write_Index -- + ----------------- + + procedure Write_Index + is + Cov_Index_File : File_Type; + + Metric : constant String := + (if Lines + then "lines" + else Ada.Characters.Handling.To_Lower (Coverage_Level'Image (L))); + Filename : constant String := Metric & ".index"; + + Contents : Unbounded_String := Null_Unbounded_String; + -- Informations to be written in the index file + + Global_Stats : Project_Stats; + -- The aggregated stats of all projects + begin + + -- Go through all the projects' coverage statistics and append them + -- to the Content string to be written to the index file. + -- Additionally, compute the global coverage stats. + + for C in Projects_Stats.Iterate loop + declare + Prj_Name : constant String := Projects_Stats_Maps.Key (C); + Prj_Stats : constant Project_Stats := + Projects_Stats_Maps.Element (C); + begin + Update + (Global_Stats, + Prj_Stats.Total, + Prj_Stats.Stats, + Prj_Name, + Lines => Lines, + Is_Prj => True); + + Append + (Global_Stats.Files_Stats, ASCII.LF & Prj_Stats.Files_Stats); + end; + end loop; + + if Length (Other_Sources_Stats.Files_Stats) /= 0 then + Update + (Global_Stats, + Other_Sources_Stats.Total, + Other_Sources_Stats.Stats, + "Other sources", + Lines => Lines, + Is_Prj => True); + + Append + (Global_Stats.Files_Stats, + ASCII.LF & Other_Sources_Stats.Files_Stats); + end if; + + Append (Contents, Global_Stats.Files_Stats); + + -- Create the index file and write its contents + + Create_Output_File (Cov_Index_File, Filename); + Put_Line (Cov_Index_File, Metric); + Put_Line (Cov_Index_File, + ASCII.LF + & Build_Stat_String + ("Global", + Global_Stats.Stats, + Global_Stats.Total, + Is_Prj => True, + Lines => Lines)); + Put_Line (Cov_Index_File, +Contents); + end Write_Index; + + begin + Files_Table_Iterate (Process_One_File'Access); + Write_Index; + end Generate_Index; + +end Annotations.Index; diff --git a/tools/gnatcov/annotations-index.ads b/tools/gnatcov/annotations-index.ads new file mode 100644 index 000000000..3cee03171 --- /dev/null +++ b/tools/gnatcov/annotations-index.ads @@ -0,0 +1,25 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 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. -- +------------------------------------------------------------------------------ + +package Annotations.Index is + + procedure Generate_Indices; + -- Create the coverage index files: one for lines and one per enabled + -- coverage level. + +end Annotations.Index; diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 6163e781f..fd104f16a 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -405,8 +405,8 @@ package Files_Table is -- lines, number of lines that are covered). Ob_Stats : Ob_Stat_Array; - -- Obligation counters for each kind of SCO (stmt, decision, - -- mcdc). Stores how many statement are covered, how many + -- Obligation counters for each kind of SCO (stmt, decision, mcdc, + -- atc and atcc). Stores how many statement are covered, how many -- decisions are covered etc. Has_Source_Coverage_Info : Boolean := False; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 43dd59658..ad5d671ac 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -39,6 +39,7 @@ with Annotations.Html; with Annotations.Report; with Annotations.Xcov; with Annotations.Xml; +with Annotations.Index; with Annotations; use Annotations; with Binary_Files; with CFG_Dump; @@ -2354,6 +2355,16 @@ begin (Context'Unchecked_Access, Output, Dump_Units_In_Report); end if; + -- For report and xcov reports, also generate coverage stats + -- indices. + + if Annotation (Annotate_Report) + or else Annotation (Annotate_Xcov) + or else Annotation (Annotate_Xcov_Plus) + then + Annotations.Index.Generate_Indices; + end if; + if Annotation (Annotate_Unknown) then pragma Assert (Save_Checkpoint /= null); end if; diff --git a/tools/gnatcov/outputs.adb b/tools/gnatcov/outputs.adb index 552978ef3..a3c592113 100644 --- a/tools/gnatcov/outputs.adb +++ b/tools/gnatcov/outputs.adb @@ -316,12 +316,15 @@ package body Outputs is -- Set_Output_Dir -- --------------------- - procedure Set_Output_Dir (Output_Dir : String) is + procedure Set_Output_Dir (Output_Dir : String; Subdir : Boolean := False) is begin Free (Report_Output_Dir); if not Is_Directory (Output_Dir) then - Put_Line (Standard_Error, "info: creating output path " & Output_Dir); + if not Switches.Quiet and then not Subdir then + Put_Line + (Standard_Error, "info: creating output path " & Output_Dir); + end if; begin Ada.Directories.Create_Path (Output_Dir); exception diff --git a/tools/gnatcov/outputs.ads b/tools/gnatcov/outputs.ads index bc8d584e8..e3703ce02 100644 --- a/tools/gnatcov/outputs.ads +++ b/tools/gnatcov/outputs.ads @@ -137,12 +137,13 @@ package Outputs is function Output_Dir_Defined return Boolean; -- True if the output directory has been set - procedure Set_Output_Dir (Output_Dir : String); + procedure Set_Output_Dir (Output_Dir : String; Subdir : Boolean := False); -- Set the path to the directory where report files will be stored. -- This procedure shall be called before any use of Create_Output_File -- (presumably when parsing xcov's options). The default output dir is -- the root project's object directory if using a project, or the current - -- directory if not. + -- directory if not. Subdir indicates wether the directory is an output + -- subdirectory. function Get_Output_Dir return String; -- Return the output dir. If Report_Output_Dir is null, initialize it From 0884876bcefccc04d0717dbf71be349da3c0c306 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 27 Feb 2024 15:39:12 +0100 Subject: [PATCH 0764/1483] Only log output dir creation when not quiet Only log the creation of an output directory if it not a subdirectory and if quiet mode is not enabled. Also, clean the tests that manually created the directory before invoking gnatcov to avoid the log message. --- testsuite/tests/129-instr-progress/test.py | 5 ----- testsuite/tests/138-ada-preprocessing/errors/test.py | 6 ------ testsuite/tests/138-ada-preprocessing/example/test.py | 6 ------ .../tests/138-ada-preprocessing/prep_data/test.py | 5 ----- testsuite/tests/92-long_slugs/test.py | 5 ----- testsuite/tests/Q329-018-create-output-dir/test.py | 1 + testsuite/tests/TA15-063-ignore-fingerprint/test.py | 4 +--- testsuite/tests/TB13-020-expr-func-mcdc/test.py | 5 ----- testsuite/tests/V201-010-multi-report/test.py | 2 +- testsuite/tests/instr-cov/198-non-instr-scos/test.py | 6 ------ testsuite/tests/instr-cov/218-missing-pkg-spec/test.py | 5 ----- testsuite/tests/instr-cov/no-compiler/test.py | 4 ---- testsuite/tests/instr-cov/unexpected-ada-main/test.py | 5 ----- tools/gnatcov/annotations-index.adb | 10 ++++------ tools/gnatcov/annotations.adb | 2 +- 15 files changed, 8 insertions(+), 63 deletions(-) diff --git a/testsuite/tests/129-instr-progress/test.py b/testsuite/tests/129-instr-progress/test.py index 9e6a98e6a..a4eb82a7b 100644 --- a/testsuite/tests/129-instr-progress/test.py +++ b/testsuite/tests/129-instr-progress/test.py @@ -4,8 +4,6 @@ """ import dataclasses -import os -import os.path from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest @@ -16,9 +14,6 @@ tmp = Wdir("tmp_") -# Avoid "creating output path" info messages -os.mkdir("obj") - build_run_and_coverage( gprsw=GPRswitches( root_project=gprfor( diff --git a/testsuite/tests/138-ada-preprocessing/errors/test.py b/testsuite/tests/138-ada-preprocessing/errors/test.py index 2433e87ad..1129274c5 100644 --- a/testsuite/tests/138-ada-preprocessing/errors/test.py +++ b/testsuite/tests/138-ada-preprocessing/errors/test.py @@ -2,9 +2,6 @@ Check various error cases related to the use of preprocessing in Ada. """ -import os -import os.path - from SCOV.instr import xcov_instrument from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of @@ -14,9 +11,6 @@ tmp = Wdir("tmp_") -# Avoid "creating output path" info messages -os.mkdir("obj") - for basename, expected_msg in [ ( "no_such_file", diff --git a/testsuite/tests/138-ada-preprocessing/example/test.py b/testsuite/tests/138-ada-preprocessing/example/test.py index 981bc514c..6d94608eb 100644 --- a/testsuite/tests/138-ada-preprocessing/example/test.py +++ b/testsuite/tests/138-ada-preprocessing/example/test.py @@ -3,9 +3,6 @@ as expected on an example project. """ -import os -import os.path - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir @@ -15,9 +12,6 @@ tmp = Wdir("tmp_") -# Avoid "creating output path" info messages -os.mkdir("obj") - # Test the working case. The "log" preprocessing symbol is set to "false" in # "prep.txt", so all logging lines are supposed to be disabled and thus not # create coverage obligations. Yet the line numbers for the code remaining are diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/test.py b/testsuite/tests/138-ada-preprocessing/prep_data/test.py index 3bc389fa5..a03c08244 100644 --- a/testsuite/tests/138-ada-preprocessing/prep_data/test.py +++ b/testsuite/tests/138-ada-preprocessing/prep_data/test.py @@ -4,8 +4,6 @@ """ from dataclasses import dataclass -import os -import os.path from SCOV.instr import xcov_instrument from SCOV.minicheck import build_run_and_coverage, check_xcov_reports @@ -58,9 +56,6 @@ class ReportTestcase(BaseTestcase): thistest.log(f"== {t.label} ==") tmp = Wdir(f"tmp_{t.label}") - # Avoid "creating output path" info messages - os.mkdir("obj") - gprsw = GPRswitches( root_project=gprfor( mains=["main.adb"], diff --git a/testsuite/tests/92-long_slugs/test.py b/testsuite/tests/92-long_slugs/test.py index d6ae8fee8..71c3eb075 100644 --- a/testsuite/tests/92-long_slugs/test.py +++ b/testsuite/tests/92-long_slugs/test.py @@ -5,8 +5,6 @@ unit names. """ -from e3.fs import mkdir - from SCOV.minicheck import ( build_run_and_coverage, check_xcov_reports, @@ -20,9 +18,6 @@ prj_switches = GPRswitches(gprfor(srcdirs=[".."], mains=["main.c"])) -# Suppress "creating output path ..." messages from the log -mkdir("obj") - # First, check that using the legacy slugs produces paths that exceed the path # limit. diff --git a/testsuite/tests/Q329-018-create-output-dir/test.py b/testsuite/tests/Q329-018-create-output-dir/test.py index 4f7f941e5..b1afe1c40 100644 --- a/testsuite/tests/Q329-018-create-output-dir/test.py +++ b/testsuite/tests/Q329-018-create-output-dir/test.py @@ -16,6 +16,7 @@ gprsw=GPRswitches(root_project=gprfor(["foo.adb"], srcdirs=src_dir)), covlevel="stmt", mains=["foo"], + quiet=False, extra_coverage_args=["-axcov", "--output-dir={}".format(output_dir)], ) diff --git a/testsuite/tests/TA15-063-ignore-fingerprint/test.py b/testsuite/tests/TA15-063-ignore-fingerprint/test.py index 298369fbb..df0e65d92 100644 --- a/testsuite/tests/TA15-063-ignore-fingerprint/test.py +++ b/testsuite/tests/TA15-063-ignore-fingerprint/test.py @@ -55,9 +55,6 @@ def check_empty(filename): ) check_empty("log-cov2.txt") -# Avoid the "info: creating output path report" message -os.mkdir("report") - # Consolidate both partial reports and produce an XCOV report xcov( [ @@ -69,6 +66,7 @@ def check_empty(filename): "-cstmt", "-axcov", "--output-dir=report", + "--quiet", "-Cc1.ckpt", "-Cc2.ckpt", ], diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/test.py b/testsuite/tests/TB13-020-expr-func-mcdc/test.py index af12fa170..4dfc7b5ba 100644 --- a/testsuite/tests/TB13-020-expr-func-mcdc/test.py +++ b/testsuite/tests/TB13-020-expr-func-mcdc/test.py @@ -5,8 +5,6 @@ (No reason not to also run it with binary traces.) """ -import os - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir @@ -18,9 +16,6 @@ p = gprfor(prjid="p", srcdirs=[".."], mains=["main.adb"]) -# Avoid the "info: creating output path report" message -os.mkdir("report") - build_run_and_coverage( gprsw=GPRswitches(root_project=p), covlevel="stmt+mcdc", diff --git a/testsuite/tests/V201-010-multi-report/test.py b/testsuite/tests/V201-010-multi-report/test.py index 13a9f812f..4ebcc44ad 100644 --- a/testsuite/tests/V201-010-multi-report/test.py +++ b/testsuite/tests/V201-010-multi-report/test.py @@ -30,7 +30,7 @@ thistest.fail_if_no_match( what="did not find report in the coverage output", regexp=r"(.|\n)*" - r"\n\*\* COVERAGE REPORT \*\*" + r"\*\* COVERAGE REPORT \*\*" r"(.|\n)*" r"\n\*\* END OF REPORT \*\*", actual=contents_of("coverage.log"), diff --git a/testsuite/tests/instr-cov/198-non-instr-scos/test.py b/testsuite/tests/instr-cov/198-non-instr-scos/test.py index d60509597..bdf1a3aab 100644 --- a/testsuite/tests/instr-cov/198-non-instr-scos/test.py +++ b/testsuite/tests/instr-cov/198-non-instr-scos/test.py @@ -4,9 +4,6 @@ the next source file that is instrumented for the same unit (pkg.adb). """ -import os -import os.path - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir @@ -16,9 +13,6 @@ tmp = Wdir("tmp_") -# Avoid "creating output path" info messages -os.mkdir("obj") - build_run_and_coverage( gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), covlevel="stmt", diff --git a/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py b/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py index 73ce4884a..d09c4e7e2 100644 --- a/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py +++ b/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py @@ -3,8 +3,6 @@ project setup that lacks the package spec corresponding to a package body. """ -from e3.fs import mkdir - from SCOV.instr import xcov_instrument from SUITE.context import thistest from SUITE.cutils import Wdir, lines_of @@ -13,9 +11,6 @@ tmp = Wdir("tmp_") -# Avoid "creating output path" messages from gnatcov -mkdir("obj") - filename = "instrument.txt" p = xcov_instrument( gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), diff --git a/testsuite/tests/instr-cov/no-compiler/test.py b/testsuite/tests/instr-cov/no-compiler/test.py index b65e2c74d..0cc4d8d1d 100644 --- a/testsuite/tests/instr-cov/no-compiler/test.py +++ b/testsuite/tests/instr-cov/no-compiler/test.py @@ -3,7 +3,6 @@ environment. It used to emit a cryptic error message: invalid path "". """ -from e3.fs import mkdir from e3.os.process import DEVNULL, Run, STDOUT from SCOV.instr import xcov_instrument @@ -33,9 +32,6 @@ error=STDOUT, ) -# Avoid noisy "creating output path" messages -mkdir("obj") - gpr = GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.c"])) # Now run the instrumenter on a C project with this configuration file and diff --git a/testsuite/tests/instr-cov/unexpected-ada-main/test.py b/testsuite/tests/instr-cov/unexpected-ada-main/test.py index 94ab44dc2..d57ff9e40 100644 --- a/testsuite/tests/instr-cov/unexpected-ada-main/test.py +++ b/testsuite/tests/instr-cov/unexpected-ada-main/test.py @@ -3,8 +3,6 @@ dump of coverage buffers in mains. """ -from e3.fs import mkdir - from SCOV.instr import xcov_instrument from SUITE.cutils import contents_of, Wdir from SUITE.gprutils import GPRswitches @@ -13,9 +11,6 @@ Wdir("tmp_") -# Avoid the "creation output path" notice -mkdir("obj") - xcov_instrument( gprsw=GPRswitches(root_project=gprfor(mains=["main.ads"], srcdirs=[".."])), covlevel="stmt", diff --git a/tools/gnatcov/annotations-index.adb b/tools/gnatcov/annotations-index.adb index 1e3600493..b9df60660 100644 --- a/tools/gnatcov/annotations-index.adb +++ b/tools/gnatcov/annotations-index.adb @@ -95,13 +95,11 @@ package body Annotations.Index is Output_Subdir : constant String := Output_Dir & "/stats" & GNAT.OS_Lib.Directory_Separator; begin - if Annotations.Multiple_Reports then - -- Create a "stats" directory where the - -- "-.index" files will be stored. + -- Create a "stats" directory where the "-.index" + -- files will be stored. - Clean_Dir (Output_Subdir, ""); - Set_Output_Dir (Output_Subdir); - end if; + Clean_Dir (Output_Subdir, ""); + Set_Output_Dir (Output_Subdir, Subdir => True); -- Generate the index for lines... Generate_Index (Lines => True); diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index f2e19f25c..5ecf4bfec 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -491,7 +491,7 @@ package body Annotations is Clean_Dir (Output_Subdir, Clean_Pattern); end if; if Multiple_Reports then - Set_Output_Dir (Output_Subdir); + Set_Output_Dir (Output_Subdir, Subdir => True); end if; end; end if; From c4c4de0d06ea8283e119741dcd7262ac8c3bf23b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 22 Feb 2024 15:16:30 +0000 Subject: [PATCH 0765/1483] Instrument: fix the handling of elaboration constraints in subunits Depending on where the corresponding stub is located in the owning library unit, subunits for package bodies may inherit elaboration restrictions (Preelaborate pragma, No_Elaboration_Code restriction, ...). This means that the instrumentation of these subunits must determine whether elaboration constraints apply on that subunit before instrumenting declarations in the package body. This case is currently ignored, so "gnatcov instrument" generates invalid code for subunits that have elaboration constraints. This commit fixes that. --- .../instr-cov/243-no-elab-subunit/main.adb | 12 +++ .../243-no-elab-subunit/pkg-nested.adb | 24 ++++++ .../243-no-elab-subunit/pkg-proc-nested.adb | 24 ++++++ .../243-no-elab-subunit/pkg-proc.adb | 16 ++++ .../instr-cov/243-no-elab-subunit/pkg.adb | 7 ++ .../instr-cov/243-no-elab-subunit/pkg.ads | 14 ++++ .../instr-cov/243-no-elab-subunit/test.py | 80 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 71 ++++++++++++---- 8 files changed, 234 insertions(+), 14 deletions(-) create mode 100644 testsuite/tests/instr-cov/243-no-elab-subunit/main.adb create mode 100644 testsuite/tests/instr-cov/243-no-elab-subunit/pkg-nested.adb create mode 100644 testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc-nested.adb create mode 100644 testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc.adb create mode 100644 testsuite/tests/instr-cov/243-no-elab-subunit/pkg.adb create mode 100644 testsuite/tests/instr-cov/243-no-elab-subunit/pkg.ads create mode 100644 testsuite/tests/instr-cov/243-no-elab-subunit/test.py diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/main.adb b/testsuite/tests/instr-cov/243-no-elab-subunit/main.adb new file mode 100644 index 000000000..8238f29ad --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/main.adb @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; + +procedure Main is + use Pkg.Nested; +begin + Set (1); + if Get /= 1 then + Put_Line ("ERROR"); + Pkg.Proc; + end if; +end Main; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-nested.adb b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-nested.adb new file mode 100644 index 000000000..25a1f5097 --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-nested.adb @@ -0,0 +1,24 @@ +separate (Pkg) +package body Nested is + + Register : Integer := 0; + + --------- + -- Set -- + --------- + + procedure Set (Value : Integer) is + begin + Register := Value; + end Set; + + --------- + -- Get -- + --------- + + function Get return Integer is + begin + return Register; + end Get; + +end Nested; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc-nested.adb b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc-nested.adb new file mode 100644 index 000000000..6e8e1aebc --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc-nested.adb @@ -0,0 +1,24 @@ +separate (Pkg.Proc) +package body Nested is + + Register : Integer := 0; + + --------- + -- Set -- + --------- + + procedure Set (Value : Integer) is + begin + Register := Value; + end Set; + + --------- + -- Get -- + --------- + + function Get return Integer is + begin + return Register; + end Get; + +end Nested; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc.adb b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc.adb new file mode 100644 index 000000000..451e25214 --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc.adb @@ -0,0 +1,16 @@ +separate (Pkg) +procedure Proc is + + package Nested is + procedure Set (Value : Integer); + function Get return Integer; + end Nested; + + package body Nested is separate; + +begin + Nested.Set (1); + if Nested.Get /= 1 then + raise Program_Error; + end if; +end Proc; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.adb b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.adb new file mode 100644 index 000000000..f3b570944 --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.adb @@ -0,0 +1,7 @@ +package body Pkg is + + package body Nested is separate; + + procedure Proc is separate; + +end Pkg; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.ads b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.ads new file mode 100644 index 000000000..5bb5812f1 --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.ads @@ -0,0 +1,14 @@ +-- CONFIG_PRAGMA + +package Pkg is + + -- PRAGMA + + package Nested is + procedure Set (Value : Integer); + function Get return Integer; + end Nested; + + procedure Proc; + +end Pkg; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/test.py b/testsuite/tests/instr-cov/243-no-elab-subunit/test.py new file mode 100644 index 000000000..4d140c124 --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/test.py @@ -0,0 +1,80 @@ +""" +Check that the Ada instrumenter does not violate elaboration constraints in a +unit spec when instrumenting a subunit corresponding to that spec. +""" + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +pragma_pattern = "-- PRAGMA" +config_pragma_pattern = "-- CONFIG_PRAGMA" + +# Check that gnatcov procedures valid code for a subunit (pkg-nested.adb) when +# that subunit implements a library-level package body. Test both for an +# elaboration pragma and for the No_Elaboration_Code restriction since their +# handling involves different code paths in gnatcov. +# +# Check that we can still compute code coverage for the elaboration of +# declaration in a package body subunit when it is not library level +# (proc-nested.adb). This is possible only if gnatcov knows that this package +# is not library-level: it is possible to insert witness calls even if the unit +# has elaboration restrictions. +for name, pattern, pragma in [ + ( + "no_elab_code", + config_pragma_pattern, + "pragma Restrictions (No_Elaboration_Code);", + ), + ( + "preelab", + pragma_pattern, + "pragma Preelaborate;", + ), + ( + "no_elab_code_all", + pragma_pattern, + "pragma No_Elaboration_Code_All;", + ), +]: + thistest.log(f"== {name}: {pragma} ==") + tmp = Wdir(f"tmp_{name}") + + # Instantiate the project sources in the temporary directory + for ext in ["adb", "ads"]: + cp(f"../*.{ext}", ".") + with open("pkg.ads", "w") as f: + f.write(contents_of("../pkg.ads").replace(pattern, pragma)) + + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["."], mains=["main.adb"]) + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + ) + + expected = { + "main.adb.xcov": {"+": {7, 8}, "-": {9, 10}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {}, + "pkg-nested.adb.xcov": {"+": {12, 21}}, + "pkg-proc.adb.xcov": {"-": {12, 13, 14}}, + "pkg-proc-nested.adb.xcov": {"-": {4, 12, 21}}, + } + # Deal with coverage report discrepancies between source and binary traces + if thistest.options.trace_mode == "bin": + expected.pop("pkg.adb.xcov") + if pattern == config_pragma_pattern: + expected.pop("pkg.ads.xcov") + check_xcov_reports("obj", expected, discard_empty=False) + + tmp.to_homedir() + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 9cd7b9d38..6c8472080 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1109,6 +1109,11 @@ package body Instrument.Ada_Unit is -- Return the parent declaration for Decl, or No_Basic_Decl if Decl has no -- parent, or if we cannot find it. + function Decls_Are_Library_Level + (Unit : Libadalang.Analysis.Compilation_Unit) return Boolean; + -- Return whether declarations that appear directly under the given + -- compilation unit are library-level. + function Has_No_Elaboration_Code_All (Unit : LAL.Compilation_Unit) return Boolean; -- Return whether the No_Elaboration_Code_All aspect/pragma applies to Unit @@ -2970,6 +2975,49 @@ package body Instrument.Ada_Unit is return No_Basic_Decl; end Parent_Decl; + ----------------------------- + -- Decls_Are_Library_Level -- + ----------------------------- + + function Decls_Are_Library_Level + (Unit : Libadalang.Analysis.Compilation_Unit) return Boolean is + begin + case Unit.F_Body.Kind is + when Ada_Library_Item => + + -- For library units, only packages (generic, declarations and + -- bodies) contain library-level declarations. + + return Unit.F_Body.As_Library_Item.F_Item.Kind in + Ada_Package_Decl + | Ada_Package_Body + | Ada_Generic_Package_Decl; + + when Ada_Subunit => + + -- We consider that declarations in subunits are library-level if + -- the subunit is for a package body (in Ada, the only other valid + -- case is a subprogram body) and if the stub for that package + -- body is itself at library-level. + + declare + Parent : Basic_Decl := + Unit.F_Body.As_Subunit.F_Body.As_Basic_Decl; + begin + while not Parent.Is_Null loop + if Parent.Kind in Ada_Base_Subp_Body then + return False; + end if; + Parent := Parent_Decl (Parent); + end loop; + return True; + end; + + when others => + raise Program_Error; + end case; + end Decls_Are_Library_Level; + --------------------------------- -- Has_No_Elaboration_Code_All -- --------------------------------- @@ -8347,20 +8395,15 @@ package body Instrument.Ada_Unit is (UIC.Root_Unit.P_Decl.P_Fully_Qualified_Name_Array); begin - -- Top-level (relative to the source file) declarations can be - -- instrumented even when they belong to preelaborate units: they - -- just need not to be library-level declarations. - - if UIC.Root_Unit.F_Body.Kind = Ada_Library_Item - and then UIC.Root_Unit.F_Body.As_Library_Item.F_Item.Kind in - Ada_Package_Decl | Ada_Package_Body | Ada_Generic_Package_Decl - then - Preelab := - UIC.Root_Unit.P_Is_Preelaborable - or else UIC.Root_Unit.P_Has_Restriction - (To_Unbounded_Text ("No_Elaboration_Code")) - or else Has_No_Elab_Code_All; - end if; + -- Library level declarations can be instrumented only when + -- elaboration code is allowed. + + Preelab := + Decls_Are_Library_Level (UIC.Root_Unit) + and then (UIC.Root_Unit.P_Is_Preelaborable + or else UIC.Root_Unit.P_Has_Restriction + (To_Unbounded_Text ("No_Elaboration_Code")) + or else Has_No_Elab_Code_All); exception when Libadalang.Common.Property_Error => Report From 6ab8b64d37fa9de8f8dde3e254b1ef7c48a89c6f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 21 Feb 2024 14:23:00 +0000 Subject: [PATCH 0766/1483] Instrument: warn for unexpected instr. souces in ext. built projects --- .../src-lib/mylib.adb | 14 +++ .../src-lib/mylib.ads | 3 + .../221-stale-external-instr/src-p/main.adb | 6 ++ .../221-stale-external-instr/test.opt | 1 + .../221-stale-external-instr/test.py | 90 +++++++++++++++++++ tools/gnatcov/instrument-clean_objdirs.adb | 86 ++++++++++++++---- 6 files changed, 185 insertions(+), 15 deletions(-) create mode 100644 testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.adb create mode 100644 testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.ads create mode 100644 testsuite/tests/instr-cov/221-stale-external-instr/src-p/main.adb create mode 100644 testsuite/tests/instr-cov/221-stale-external-instr/test.opt create mode 100644 testsuite/tests/instr-cov/221-stale-external-instr/test.py diff --git a/testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.adb b/testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.adb new file mode 100644 index 000000000..12aa258d3 --- /dev/null +++ b/testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Mylib is + + --------------- + -- Say_Hello -- + --------------- + + procedure Say_Hello is + begin + Put_Line ("Hello world!"); + end Say_Hello; + +end Mylib; diff --git a/testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.ads b/testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.ads new file mode 100644 index 000000000..008ed737d --- /dev/null +++ b/testsuite/tests/instr-cov/221-stale-external-instr/src-lib/mylib.ads @@ -0,0 +1,3 @@ +package Mylib is + procedure Say_Hello; +end Mylib; diff --git a/testsuite/tests/instr-cov/221-stale-external-instr/src-p/main.adb b/testsuite/tests/instr-cov/221-stale-external-instr/src-p/main.adb new file mode 100644 index 000000000..4b41908b1 --- /dev/null +++ b/testsuite/tests/instr-cov/221-stale-external-instr/src-p/main.adb @@ -0,0 +1,6 @@ +with Mylib; + +procedure Main is +begin + Mylib.Say_Hello; +end Main; diff --git a/testsuite/tests/instr-cov/221-stale-external-instr/test.opt b/testsuite/tests/instr-cov/221-stale-external-instr/test.opt new file mode 100644 index 000000000..08d567967 --- /dev/null +++ b/testsuite/tests/instr-cov/221-stale-external-instr/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Checks an instrumentation-specific warning diff --git a/testsuite/tests/instr-cov/221-stale-external-instr/test.py b/testsuite/tests/instr-cov/221-stale-external-instr/test.py new file mode 100644 index 000000000..ec1d0458f --- /dev/null +++ b/testsuite/tests/instr-cov/221-stale-external-instr/test.py @@ -0,0 +1,90 @@ +""" +Check that "gnatcov instrument" warns about instrumented sources found in +externally built projects that are not of interest. +""" + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprbuild, gprfor + + +tmp = Wdir("tmp_") + +# Create the "lib" project, that is externally built by default, and a project +# "p" that depends on "lib". +lib = gprfor( + prjid="lib", + srcdirs=["../src-lib"], + objdir="obj-lib", + mains=[], + extra=""" + type Boolean is ("False", "True"); + Ext_Built : Boolean := external ("LIB_EXT_BUILT", "True"); + for Externally_Built use Ext_Built; + """, +) +p = gprfor( + prjid="p", + deps=["lib"], + srcdirs=["../src-p"], + objdir="obj-p", + mains=["main.adb"], +) + +# Instrument and build the "lib" project +thistest.log("== Instrument Lib ==") +xcov_instrument( + gprsw=GPRswitches(root_project=lib), + covlevel="stmt", + gpr_obj_dir="obj-lib", + extra_args=["-XLIB_EXT_BUILT=False"], + out="instr-lib.txt", +) +thistest.fail_if_not_equal( + '"gnatcov instrument" output', + "", + contents_of("instr-lib.txt"), +) +gprbuild(lib, gargs=["-XLIB_EXT_BUILT=False"], out="gprbuild-lib.txt") + +# Instrument the "p" project. We expect gnatcov to notice and warn that there +# are instrumented sources in "lib" even though it is not a project of +# interest. +thistest.log("== Instrument P ==") +xcov_instrument( + gprsw=GPRswitches(root_project=p), + covlevel="stmt", + gpr_obj_dir="obj-p", + out="instr-p.txt", + tolerate_messages=".", +) +thistest.fail_if_not_equal( + '"gnatcov instrument" output', + 'warning: Project "lib" is externally built and does not contain units of' + " interest, however it contains instrumented sources", + contents_of("instr-p.txt").strip(), +) + +# Sanity check that the warning is useful: +# +# Instrumentation of main.adb considered that sources from "lib.gpr" were not +# of interest, so auto-dumping code does not reference coverage buffer units +# for "lib.gpr". As a result, these coverage buffers are not included in the +# build closure. +# +# However, sources for "lib.gpr" were instrumented and thus try to use coverage +# buffers, so we expect a link failure here. +thistest.log("== Build P ==") +gprbuild_desc = gprbuild(p, out="gprbuild-p.txt", register_failure=False) +thistest.fail_if( + gprbuild_desc.status == 0, + "build of P was expected to fail", +) +thistest.fail_if( + "undefined reference to" not in contents_of("gprbuild-p.txt"), + "Expected link error message not found in gprbuild-p.txt", +) + +thistest.result() diff --git a/tools/gnatcov/instrument-clean_objdirs.adb b/tools/gnatcov/instrument-clean_objdirs.adb index 57cf336ac..6a90bce6d 100644 --- a/tools/gnatcov/instrument-clean_objdirs.adb +++ b/tools/gnatcov/instrument-clean_objdirs.adb @@ -16,12 +16,13 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Directories; use Ada.Directories; +with Ada.Directories; use Ada.Directories; with GNATCOLL.Projects; use GNATCOLL.Projects; with Instrument.Common; use Instrument.Common; -with Project; +with Outputs; use Outputs; +with Project; use Project; procedure Instrument.Clean_Objdirs is @@ -30,6 +31,9 @@ procedure Instrument.Clean_Objdirs is -- built, remove all files from the "$project_name-gnatcov-instr" folder in -- Project's object directory. + function Has_Regular_Files (Directory : String) return Boolean; + -- Return whether Directory contains at least one regular file + ------------------ -- Clean_Subdir -- ------------------ @@ -37,24 +41,75 @@ procedure Instrument.Clean_Objdirs is procedure Clean_Subdir (Project : Project_Type) is Output_Dir : constant String := Project_Output_Dir (Project); begin - if - -- Leave externally built projects out of the picture - - Project.Externally_Built + -- Some projects don't have an object directory: ignore them as there is + -- nothing to do. - -- Some projects don't have an object directory: ignore them as there - -- is nothing to do. - - or else Output_Dir'Length = 0 + if Output_Dir'Length = 0 or else not Exists (Output_Dir) or else Kind (Output_Dir) /= Directory then return; end if; + -- Unless externally built project processing has been enabled, having + -- instrumented sources in externally built projects is very suspicious + -- and could easily trigger build errors later on. + -- + -- For instance, if: + -- + -- * project P depends on project Lib + -- * Lib is instrumented + -- * P is instrumented while Lib is tagged as externally built + -- + -- then auto-dump code for P's main will not try to dump coverage + -- buffers for Lib, and thus the link of P's main executable will fail + -- because Lib's units refer to their coverage buffers, which are not + -- included in the link. + -- + -- To avoid confusion, warn about such cases now, so that users have a + -- clear lead on how to address such problems. + + if Project.Externally_Built then + if not Externally_Built_Projects_Processing_Enabled + and then Has_Regular_Files (Output_Dir) + then + -- Short of re-implementing non trivial project handling logic, + -- there is no API that allows us to determine whether files in + -- Output_Dir would be considered as sources with --src-subdirs: + -- consider that all files there could be sources. + + Warn ("Project """ & Project.Name & """ is externally built and" + & " does not contain units of interest, however it contains" + & " instrumented sources"); + end if; + + -- We should never try to modify externally built projects, so do not + -- remove their instrumented source directory. + + return; + end if; + Delete_Tree (Directory => Output_Dir); end Clean_Subdir; + ----------------------- + -- Has_Regular_Files -- + ----------------------- + + function Has_Regular_Files (Directory : String) return Boolean is + S : Search_Type; + begin + return Result : Boolean do + Start_Search + (Search => S, + Directory => Directory, + Pattern => "", + Filter => (Ordinary_File => True, others => False)); + Result := More_Entries (S); + End_Search (S); + end return; + end Has_Regular_Files; + -- Start of processing for Instrument.Clean_Objdirs begin @@ -63,10 +118,11 @@ begin -- with the build of the extending project. if not Save_Temps then - Project.Iterate_Projects - (Root_Project => Project.Project.Root_Project, - Process => Clean_Subdir'Access, - Recursive => True, - Include_Extended => True); + Iterate_Projects + (Root_Project => Project.Project.Root_Project, + Process => Clean_Subdir'Access, + Recursive => True, + Include_Extended => True, + Include_Externally_Built => True); end if; end Instrument.Clean_Objdirs; From 233838d4dd32d159034462c4595470330f200a26 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 8 Mar 2024 10:15:51 +0000 Subject: [PATCH 0767/1483] instr-cov/243-no-elab-subunit: adjust testcase for bin-traces/-O1 Introduce an inter-unit dependency to break the compiler's dataflow analysis and thus avoid dead code elimination that interferes with coverage analysis. --- .../tests/instr-cov/243-no-elab-subunit/pkg-proc.adb | 4 +++- .../tests/instr-cov/243-no-elab-subunit/pkg.ads | 2 ++ .../tests/instr-cov/243-no-elab-subunit/test.py | 4 +++- .../tests/instr-cov/243-no-elab-subunit/utils.adb | 12 ++++++++++++ .../tests/instr-cov/243-no-elab-subunit/utils.ads | 10 ++++++++++ 5 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/instr-cov/243-no-elab-subunit/utils.adb create mode 100644 testsuite/tests/instr-cov/243-no-elab-subunit/utils.ads diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc.adb b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc.adb index 451e25214..8611a17b9 100644 --- a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc.adb +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg-proc.adb @@ -1,3 +1,5 @@ +with Utils; use Utils; + separate (Pkg) procedure Proc is @@ -10,7 +12,7 @@ procedure Proc is begin Nested.Set (1); - if Nested.Get /= 1 then + if Identity (Nested.Get) /= 1 then raise Program_Error; end if; end Proc; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.ads b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.ads index 5bb5812f1..17230f9b7 100644 --- a/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.ads +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/pkg.ads @@ -1,3 +1,5 @@ +pragma Ada_2012; + -- CONFIG_PRAGMA package Pkg is diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/test.py b/testsuite/tests/instr-cov/243-no-elab-subunit/test.py index 4d140c124..6139b84fb 100644 --- a/testsuite/tests/instr-cov/243-no-elab-subunit/test.py +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/test.py @@ -65,8 +65,10 @@ "pkg.ads.xcov": {}, "pkg.adb.xcov": {}, "pkg-nested.adb.xcov": {"+": {12, 21}}, - "pkg-proc.adb.xcov": {"-": {12, 13, 14}}, + "pkg-proc.adb.xcov": {"-": {14, 15, 16}}, "pkg-proc-nested.adb.xcov": {"-": {4, 12, 21}}, + "utils.ads.xcov": {}, + "utils.adb.xcov": {"-": {9}}, } # Deal with coverage report discrepancies between source and binary traces if thistest.options.trace_mode == "bin": diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/utils.adb b/testsuite/tests/instr-cov/243-no-elab-subunit/utils.adb new file mode 100644 index 000000000..bd521f374 --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/utils.adb @@ -0,0 +1,12 @@ +package body Utils is + + -------------- + -- Identity -- + -------------- + + function Identity (I : Integer) return Integer is + begin + return I; + end Identity; + +end Utils; diff --git a/testsuite/tests/instr-cov/243-no-elab-subunit/utils.ads b/testsuite/tests/instr-cov/243-no-elab-subunit/utils.ads new file mode 100644 index 000000000..20cc1241f --- /dev/null +++ b/testsuite/tests/instr-cov/243-no-elab-subunit/utils.ads @@ -0,0 +1,10 @@ +package Utils is + + pragma No_Elaboration_Code_All; + pragma Preelaborate; + + function Identity (I : Integer) return Integer; + -- The only purpose of this function is to break the compiler's data flow + -- analysis so that high optimization levels cannot optimize code too much. + +end Utils; From 5efc621edde4893be3f3329bcf49d59dc66a7a0b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 8 Mar 2024 16:55:19 +0100 Subject: [PATCH 0768/1483] SUITE/qdata.py: update call to output_of after recent renaming --- testsuite/SUITE/qdata.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/SUITE/qdata.py b/testsuite/SUITE/qdata.py index 25d996e72..f36b778da 100644 --- a/testsuite/SUITE/qdata.py +++ b/testsuite/SUITE/qdata.py @@ -180,4 +180,4 @@ def treeref_at(dirname): directory trees. """ # Assuming git, sha1 for the HEAD reference - return output_of("git rev-parse HEAD", dir=dirname).rstrip("\n") + return output_of("git rev-parse HEAD", dirname=dirname).rstrip("\n") From 69b910c92f393ecdbd8a8bff4976746599c79ab1 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 11 Mar 2024 14:06:39 +0000 Subject: [PATCH 0769/1483] Add a deprecation warning for the "-S" command line argument --- testsuite/SCOV/internals/driver.py | 14 +++++++++++--- .../tests/S619-014-tag-provider-mismatch/test.py | 5 +++-- tools/gnatcov/gnatcov_bits_specific.adb | 1 + 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 8d0cd570f..9d15de773 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -803,10 +803,18 @@ def gen_one_xcov_report(self, inputs, report_format, options=""): # Note that we do this in qualification mode as well, even though what # we're looking at is not stricly part of the qualified interface. + # Warnings about -S being deprecated are expected: just ignore them + output_lines = lines_of(ofile) + for i, line in reversed(list(enumerate(output_lines))): + if line == ( + "warning: -S is deprecated. This option will be removed in" + " release 26." + ): + output_lines.pop(i) + output = "\n".join(output_lines) + thistest.fail_if( - os.path.getsize(ofile) > 0, - "xcov standard output not empty (%s):\n--\n%s" - % (ofile, contents_of(ofile)), + output, f"xcov standard output not empty ({ofile}:\n--\n{output}" ) def force_xcov_report(self, source): diff --git a/testsuite/tests/S619-014-tag-provider-mismatch/test.py b/testsuite/tests/S619-014-tag-provider-mismatch/test.py index c5f3ff871..c0a0e94c9 100644 --- a/testsuite/tests/S619-014-tag-provider-mismatch/test.py +++ b/testsuite/tests/S619-014-tag-provider-mismatch/test.py @@ -39,8 +39,9 @@ ) expected = ( - "warning: cannot merge coverage information from {} as it is" - " separated by default".format(ckpt) + "warning: -S is deprecated. This option will be removed in release 26." + "\nwarning: cannot merge coverage information from {} as it is separated" + " by default".format(ckpt) ) actual = contents_of("consolidate.log").strip() thistest.fail_if( diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index ad5d671ac..d6772c228 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -690,6 +690,7 @@ procedure GNATcov_Bits_Specific is end if; if Args.String_Args (Opt_Separate).Present then + Warn ("-S is deprecated. This option will be removed in release 26."); declare Name : constant String := +Args.String_Args (Opt_Separate).Value; begin From 403bfca4164859c168729d4d31ae6104ad070912 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 6 Mar 2024 16:36:52 +0000 Subject: [PATCH 0770/1483] tools/gnatcov/examples/support/src: apply clang-format --- tools/gnatcov/examples/support/src/leon-elf/abort.c | 2 +- tools/gnatcov/examples/support/src/leon3-elf/abort.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/examples/support/src/leon-elf/abort.c b/tools/gnatcov/examples/support/src/leon-elf/abort.c index fd26e0f21..d93161409 100644 --- a/tools/gnatcov/examples/support/src/leon-elf/abort.c +++ b/tools/gnatcov/examples/support/src/leon-elf/abort.c @@ -23,5 +23,5 @@ void abort (void) { - asm("mov 0, %g1; ta 0"); + asm ("mov 0, %g1; ta 0"); } diff --git a/tools/gnatcov/examples/support/src/leon3-elf/abort.c b/tools/gnatcov/examples/support/src/leon3-elf/abort.c index fd26e0f21..d93161409 100644 --- a/tools/gnatcov/examples/support/src/leon3-elf/abort.c +++ b/tools/gnatcov/examples/support/src/leon3-elf/abort.c @@ -23,5 +23,5 @@ void abort (void) { - asm("mov 0, %g1; ta 0"); + asm ("mov 0, %g1; ta 0"); } From cfad40670d4d0e6c1f3babbd219b352eee54b27b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 6 Mar 2024 16:17:57 +0100 Subject: [PATCH 0771/1483] CI: run the clang-format pre-commit hook --- .gitlab-ci.yml | 22 +++++++++++++--------- .pre-commit-config-ci.yaml | 16 ---------------- .pre-commit-config.yaml | 6 +++--- 3 files changed, 16 insertions(+), 28 deletions(-) delete mode 100644 .pre-commit-config-ci.yaml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 07d053604..23a3e201b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -205,26 +205,30 @@ stylechecks: interruptible: true stage: test services: - - image:all-pythons + - image:e3 - run_as_root:false needs: [] script: + - *basic_setup + - git config --global --add url."${GITLAB_REMOTE}".insteadOf "git@ssh.gitlab.adacore-it.com:" - git config --global --add url."${GITLAB_REMOTE}".insteadOf "ssh://git@ssh.gitlab.adacore-it.com/" - - export PATH="/home/gitlab-ci/.local/bin:$PATH" - - source /it/activate-py311 + # Install the clang-format executable and make it available + - anod install stable-libclang + - eval `anod printenv stable-libclang` + + # Create a virtual env to install our deps + - python -mvenv /tmp/venv + - . /tmp/venv/bin/activate - python -m pip install colorama pre-commit - cd $CI_PROJECT_DIR - # TODO (eng/das/cov/gnatcoverage#230): Once we have found a way to install - # the clang-format pre-commit hook in the CI, use the standard - # ".pre-commit-config.yaml" file. - - pre-commit install --config .pre-commit-config-ci.yaml - - pre-commit install-hooks --config .pre-commit-config-ci.yaml - - pre-commit run --config .pre-commit-config-ci.yaml -a --show-diff-on-failure + - pre-commit install + - pre-commit install-hooks + - pre-commit run -a --show-diff-on-failure - python .check-formatting.py --force-colors diff --git a/.pre-commit-config-ci.yaml b/.pre-commit-config-ci.yaml deleted file mode 100644 index 595ae7dbc..000000000 --- a/.pre-commit-config-ci.yaml +++ /dev/null @@ -1,16 +0,0 @@ -repos: - - repo: git@ssh.gitlab.adacore-it.com:it/flake8.git - rev: 6.0.0 - hooks: - - id: flake8 - additional_dependencies: - - flake8-bugbear - - flake8-builtins - - flake8-comprehensions - - pygments - args: ["--config=.flake8"] - - repo: git@ssh.gitlab.adacore-it.com:it/black.git - rev: 23.1.0 - hooks: - - id: black - args: ["--line-length=79"] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 3494b32e3..1044b9494 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ repos: - - repo: https://github.com/doublify/pre-commit-clang-format + - repo: git@ssh.gitlab.adacore-it.com:eng/shared/mirrors/pre-commit-clang-format rev: 62302476d0da01515660132d76902359bed0f782 hooks: - id: clang-format @@ -18,7 +18,7 @@ repos: Maximum: -1 } }"] - - repo: https://github.com/pycqa/flake8 + - repo: git@ssh.gitlab.adacore-it.com:it/flake8.git rev: 6.0.0 hooks: - id: flake8 @@ -28,7 +28,7 @@ repos: - flake8-comprehensions - pygments args: ["--config=.flake8"] - - repo: https://github.com/ambv/black + - repo: git@ssh.gitlab.adacore-it.com:it/black.git rev: 23.1.0 hooks: - id: black From c9f5c968cef1ae0f2a24cf27f54f78a3220d1b90 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 12 Mar 2024 12:14:37 +0100 Subject: [PATCH 0772/1483] Fix mention of Global_Configuration_File in documentation The attribute to specify a file containing a list of configuration pragmas is the Global_Configuration_Pragmas attribute, belonging to the Builder package. --- doc/gnatcov/src_traces.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 48954d646..c5027996c 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -654,7 +654,7 @@ specifying it on the gprbuild command line with the ``-gnatec`` switch:: gprbuild -Pproject --src-subdirs=gnatcov-instr --implicit-with= -cargs:Ada -gnatec=instrument-spark.adc -or by way of a ``Global_Configuration_File`` project file attribute, +or by way of a ``Global_Configuration_Pragmas`` project file attribute, possibly controlled by a scenario variable as in: .. code-block:: ada @@ -662,9 +662,9 @@ possibly controlled by a scenario variable as in: type mode is ("prod", "coverage"); BUILD_MODE : mode := external ("BUILD_MODE", "prod") - package Compiler is + package Builder is case BUILD_MODE is - when "coverage" => for Global_Configuration_File use "instrument-spark.adc"; + when "coverage" => for Global_Configuration_Pragmas use "instrument-spark.adc"; when "prod" => null; end case; end Compiler; From 8dc4cdfbd091bd1a2af19431715bb54bff5f56e0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 11 Mar 2024 14:25:51 +0000 Subject: [PATCH 0773/1483] Harmonize warnings emission code There should be only two ways to emit warnings in gnatcov: * Diagnostics.Report with Kind => (Low_)Warning, for all warnings that attached to a specific SCO/code location. * Outputs.Warn, for all other warnings. Rework the few locations in gnatcov where this is not the case. --- tools/gnatcov/ali_files.adb | 18 +++++++++--------- tools/gnatcov/traces_elf.adb | 29 +++++++++++++---------------- 2 files changed, 22 insertions(+), 25 deletions(-) diff --git a/tools/gnatcov/ali_files.adb b/tools/gnatcov/ali_files.adb index c6b7fd2bb..164c6fcb9 100644 --- a/tools/gnatcov/ali_files.adb +++ b/tools/gnatcov/ali_files.adb @@ -579,30 +579,30 @@ package body ALI_Files is if With_SCOs then if No_Object then - Put_Line ("warning: no object generated for " & ALI_Filename); + Warn ("no object generated for " & ALI_Filename); else if not Preserve_Control_Flow_Seen then - Put_Line - ("warning: " & ALI_Filename + Warn + (ALI_Filename & ": unit compiled without -fpreserve-control-flow"); end if; if not Dump_SCOs_Seen then - Put_Line - ("warning: " & ALI_Filename + Warn + (ALI_Filename & ": unit compiled without SCO generation (-fdump-scos)"); end if; if not Debug_Seen then - Put_Line - ("warning: " & ALI_Filename + Warn + (ALI_Filename & ": unit compiled without debug information (-g)"); end if; if Profile_Arcs_Seen then - Put_Line - ("warning: " & ALI_Filename + Warn + (ALI_Filename & ": unit compiled with instrumentation (-fprofile-arcs)"); end if; end if; diff --git a/tools/gnatcov/traces_elf.adb b/tools/gnatcov/traces_elf.adb index b0a4529e2..2dd1248e1 100644 --- a/tools/gnatcov/traces_elf.adb +++ b/tools/gnatcov/traces_elf.adb @@ -5257,12 +5257,11 @@ package body Traces_Elf is -- what we have allocated for the symbol already. if Strict then - Put_Line - (Standard_Error, - "warning: empty symbol " & Sym_Name.all - & " at " & Hex_Image (A_Sym.St_Value) - & " in section " - & Get_Shdr_Name (Efile, A_Sym.St_Shndx)); + Outputs.Warn + ("empty symbol " & Sym_Name.all + & " at " & Hex_Image (A_Sym.St_Value) + & " in section " + & Get_Shdr_Name (Efile, A_Sym.St_Shndx)); end if; Free (Sym_Name); @@ -5361,13 +5360,12 @@ package body Traces_Elf is pragma Assert (Sym.Last >= Sym.First); if Strict and then Sym.First + Offset > Addr then - Put_Line - (Standard_Error, - "warning: no symbols for " - & Hex_Image (Addr) & "-" - & Hex_Image (Sym.First + Offset - 1) - & " in section " & Get_Shdr_Name (Efile, I) - & " [" & Unsigned_16'Image (I) & " ]"); + Outputs.Warn + ("no symbols for " + & Hex_Image (Addr) & "-" + & Hex_Image (Sym.First + Offset - 1) + & " in section " & Get_Shdr_Name (Efile, I) + & " [" & Unsigned_16'Image (I) & " ]"); end if; if Sym_Cb /= null then @@ -5388,9 +5386,8 @@ package body Traces_Elf is end loop; if Strict and then Addr < Last then - Put_Line - (Standard_Error, - "warning: no symbols for " + Outputs.Warn + ("no symbols for " & Hex_Image (Addr) & "-" & Hex_Image (Last) & " in section " & Get_Shdr_Name (Efile, I) & " [" & Unsigned_16'Image (I) & " ]"); From a45b24fbb06f1fdc37377d2c8f43a4f69740171b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 11 Mar 2024 15:23:59 +0000 Subject: [PATCH 0774/1483] Introduce the -W/--warnings-as-errors command line switch Keep this new switch internal for now as the final switch (expected to be common with other tools) has not been decided yet. --- .../missing-srcdir/main.adb | 4 + .../missing-srcfile/main.adb | 6 ++ .../tests/255-warnings-as-errors/test.py | 102 ++++++++++++++++++ tools/gnatcov/command_line.ads | 13 ++- tools/gnatcov/diagnostics.adb | 4 + tools/gnatcov/outputs.adb | 16 +++ tools/gnatcov/outputs.ads | 17 ++- tools/gnatcov/setup_rts.adb | 10 ++ tools/gnatcov/switches.adb | 9 ++ tools/gnatcov/switches.ads | 4 + 10 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/255-warnings-as-errors/missing-srcdir/main.adb create mode 100644 testsuite/tests/255-warnings-as-errors/missing-srcfile/main.adb create mode 100644 testsuite/tests/255-warnings-as-errors/test.py diff --git a/testsuite/tests/255-warnings-as-errors/missing-srcdir/main.adb b/testsuite/tests/255-warnings-as-errors/missing-srcdir/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/255-warnings-as-errors/missing-srcdir/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/255-warnings-as-errors/missing-srcfile/main.adb b/testsuite/tests/255-warnings-as-errors/missing-srcfile/main.adb new file mode 100644 index 000000000..f759cb8a0 --- /dev/null +++ b/testsuite/tests/255-warnings-as-errors/missing-srcfile/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Foo; +end Main; diff --git a/testsuite/tests/255-warnings-as-errors/test.py b/testsuite/tests/255-warnings-as-errors/test.py new file mode 100644 index 000000000..e151b53e0 --- /dev/null +++ b/testsuite/tests/255-warnings-as-errors/test.py @@ -0,0 +1,102 @@ +""" +Check that --warnings-as-errors works as expected. +""" + +import re + +from e3.fs import mkdir, rm + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + + +def check(slug, project, warning): + """ + Check that "gnatcov instrument" on the given project yields the expected + warning, and that it exits with an error when --warnings-as-errors is + passed. + """ + + # Run "gnatcov instrument" once with default arguments, just to check that + # gnatcov succeeds and emits a warning. + thistest.log(f"== {slug}: sanity check ==") + log = f"{slug}-sc.txt" + process = xcov_instrument( + gprsw=GPRswitches(root_project=project), + covlevel="stmt", + register_failure=False, + out=log, + ) + thistest.fail_if(process.status != 0, "'gnatcov instrument' exit in error") + thistest.fail_if_no_match( + "'gnatcov instrument' output", warning, contents_of(log) + ) + + # Then pass --warnings-as-errors to check the exit code + thistest.log(f"== {slug}: warnings-as-errors ==") + log = f"{slug}-err.txt" + process = xcov_instrument( + gprsw=GPRswitches(root_project=project), + covlevel="stmt", + extra_args=["--warnings-as-errors"], + register_failure=False, + out=log, + ) + thistest.fail_if( + process.status == 0, "'gnatcov instrument' exit without error" + ) + thistest.fail_if_no_match( + "'gnatcov instrument' output", warning, contents_of(log) + ) + + +# Check the handling of warnings emitted before command line options (including +# --warnings-as-errors) are fully loaded. It also happens to be emitted by +# LibGPR. +# +# To achieve that, create a project with one listed source directory that does +# not exist and run "gnatcov instrument" on it: we expect a warning that +# complains about the missing directory. Note that we expect the warning twice: +# once for the wrapper gnatcov program, and one for the gnatcov64 program (both +# need to load the project). +# +# In order to create that project, we need to temporarily create that source +# directory so that gprfor does not strip it automagically. +missing_dir = "foobar" +mkdir(missing_dir) +project = gprfor( + prjid="missing_srcdir", + mains=["main.adb"], + srcdirs=["../missing-srcdir", missing_dir], +) +rm(missing_dir, recursive=True) +check( + "missing-srcdir", + project, + '.*warning: "foobar" is not a valid directory' + '\n\n.*warning: "foobar" is not a valid directory\n', +) + +# Create a project with a missing source file, on which the Ada instrumenter +# will complain. This checks the handling of warnings emitted after command +# line options are fully loaded. +check( + "missing-srcfile", + gprfor( + prjid="missing_srcfile", + mains=["main.adb"], + srcdirs=["../missing-srcfile"], + ), + re.escape( + "warning: While instrumenting main.adb..." + "\nwarning: Cannot find required source file: pkg.ads" + ), +) + +thistest.result() diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 031bba4bc..1fb3d76f9 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -92,7 +92,8 @@ package Command_Line is Opt_Save_Temps, Opt_SPARK_Compat, Opt_Full_Slugs, - Opt_Relocate_Build_Tree); + Opt_Relocate_Build_Tree, + Opt_Warnings_As_Errors); -- Set of boolean options we support. More complete descriptions below. type String_Options is @@ -607,7 +608,15 @@ package Command_Line is Help => "Relocate object, library and exec directories in the" & " current directory.", Commands => (Cmd_All_Setups => False, others => True), - Internal => False)); + Internal => False), + + Opt_Warnings_As_Errors => Create + (Long_Name => "--warnings-as-errors", + Short_Name => "-W", + Help => "Treat warnings as errors, i.e. exit with a non-zero" + & " status code if a warning is emitted.", + Commands => (others => True), + Internal => True)); String_Infos : constant String_Option_Info_Array := (Opt_Project => Create diff --git a/tools/gnatcov/diagnostics.adb b/tools/gnatcov/diagnostics.adb index f3d536e69..a80578639 100644 --- a/tools/gnatcov/diagnostics.adb +++ b/tools/gnatcov/diagnostics.adb @@ -24,6 +24,7 @@ with Command_Line; use Command_Line; with Coverage.Tags; use Coverage.Tags; with Files_Table; use Files_Table; with Hex_Images; use Hex_Images; +with Outputs; with Switches; use Switches; package body Diagnostics is @@ -281,6 +282,9 @@ package body Diagnostics is if Diagnostics_Trace.Is_Active or else (M.Kind < Violation and then not Suppress_Message (M)) then + if M.Kind in Warning then + Outputs.Register_Warning; + end if; Put_Line (Image (M)); end if; end Output_Message; diff --git a/tools/gnatcov/outputs.adb b/tools/gnatcov/outputs.adb index a3c592113..772851a64 100644 --- a/tools/gnatcov/outputs.adb +++ b/tools/gnatcov/outputs.adb @@ -200,6 +200,18 @@ package body Outputs is raise Xcov_Exit_Exc; end Normal_Exit; + ---------------------- + -- Register_Warning -- + ---------------------- + + procedure Register_Warning is + begin + Warnings_Registered := True; + if Switches.Warnings_As_Errors then + Set_Exit_Status (Failure); + end if; + end Register_Warning; + -------------------- -- Create_Context -- -------------------- @@ -353,6 +365,10 @@ package body Outputs is procedure Warning_Or_Error (Msg : String) is begin + -- Maybe Msg is an error, maybe it is a warning. In both cases, it is + -- fine to plan for a failure exit code in warnings-as-errors mode. + + Register_Warning; Put_Line (Standard_Error, Msg); end Warning_Or_Error; diff --git a/tools/gnatcov/outputs.ads b/tools/gnatcov/outputs.ads index e3703ce02..157185032 100644 --- a/tools/gnatcov/outputs.ads +++ b/tools/gnatcov/outputs.ads @@ -56,7 +56,22 @@ package Outputs is -- Same as Fatal_Error, but print the command-line usage before terminating procedure Normal_Exit with No_Return; - -- Cause Xcov to terminate. exit status OK + -- Cause Xcov to terminate with the success exit code. Since this shortcuts + -- gnatcov's regular error-tracking mechanisms, it is used only in one + -- specific case: the handling of early exit to handle --help. + + procedure Register_Warning; + -- Keep track of the fact that one warning was emitted. + -- + -- This is used to implement the "exit with failure" behavior of the + -- -W|--warnings-as-errors command line flags. + + Warnings_Registered : Boolean := False; + -- Whether Register_Warning was called once. Tracking this separately from + -- Register_Warning is necessary to implement correct "warnings-as-errors" + -- behavior for warnings that are emitted before the + -- "-W|--warnings-as-errors" command line switches themselves are + -- processed. --------------------- -- Internal errors -- diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index a3ddbacd6..b1569363e 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -433,6 +433,16 @@ package body Setup_RTS is Logs.Has_Error or else (Has_Ada and then not Prj.Has_Runtime_Project); begin + if Logs.Has_Element + (Information => False, + Warning => True, + Error => False, + Lint => False, + Read => False, + Unread => False) + then + Register_Warning; + end if; Logs.Output_Messages (Information => Setup_RTS_Trace.Is_Active); if Has_Error then Fatal_Error ("Could not load the coverage runtime project file"); diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 8c6602e5c..534d82c0b 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -625,6 +625,15 @@ package body Switches is -- internal state accordingly. Load_Target_Option (Default_Target => True); + + -- At this point we know what the final value for Warnings_As_Errors + -- should be: if we already emitted a warning, make sure the exit code + -- is updated accordingly. + + Warnings_As_Errors := Args.Bool_Args (Opt_Warnings_As_Errors); + if Warnings_Registered then + Register_Warning; + end if; end Parse_Arguments; ----------- diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index e08d8b036..b19831a74 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -91,6 +91,10 @@ package Switches is -- Miscellaneous switches -- ---------------------------- + Warnings_As_Errors : Boolean := False; + -- Whether to treat the warnings that gnatcov emits as errors, i.e. whether + -- gnatcov must exit with a non-zero status code if it emits warning. + Quiet : Boolean := False; -- Whenther the "--quiet/-q" command line switch is active. -- From d2049e6c8a8e2ce18ff550c91dc3488ca64db006 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Mon, 11 Mar 2024 18:53:59 +0100 Subject: [PATCH 0775/1483] Kill test for bin traces and 7.1.2 --- testsuite/tests/QC29-006-index/test.opt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/tests/QC29-006-index/test.opt b/testsuite/tests/QC29-006-index/test.opt index 7ba037dcf..3e4bc171a 100644 --- a/testsuite/tests/QC29-006-index/test.opt +++ b/testsuite/tests/QC29-006-index/test.opt @@ -1 +1,3 @@ 5.04a1 DEAD Test uses pre/postconditions as apects for ATCC coverage +7.1.2 DEAD Expression function support weak in 7.1.2 +bin-traces DEAD Expected slight differences in coverage percentages From 0f8f3e6e8a924ceac4e07eb57f50c6886710ca01 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 6 Mar 2024 14:30:01 +0000 Subject: [PATCH 0776/1483] Check target/RTS consistency between setup/instrument Make "gnatcov setup" record the requested target/RTS in the installed coverage runtime. Also make "gnatcov instrument" check consistency between its own target/RTS info and the one found in the coverage runtime installation, and warn if they are inconsistent. --- testsuite/tests/U211-014-setup/test.py | 5 + .../instr-cov/217-runtime-subunit/test.py | 5 + .../91-homonym-runtime-sources/test.py | 13 +- tools/gnatcov/setup_rts.adb | 197 ++++++++++++++++-- 4 files changed, 190 insertions(+), 30 deletions(-) diff --git a/testsuite/tests/U211-014-setup/test.py b/testsuite/tests/U211-014-setup/test.py index e842c9d83..7a2ce63e5 100644 --- a/testsuite/tests/U211-014-setup/test.py +++ b/testsuite/tests/U211-014-setup/test.py @@ -210,6 +210,11 @@ def check_full( covlevel="stmt", runtime_project=rt_prj, out="instr-basic-bad-lang.txt", + # Since "gnatcov setup" excluded Ada from the coverage runtime languages, + # no runtime was used to compile it, and thus it is expected that we get a + # discrepancy between "rt_prj" (no runtime) and "mixed_prj" (current + # testsuite runtime). + tolerate_messages="Current runtime is", ) p = gprbuild( mixed_prj.project_file, diff --git a/testsuite/tests/instr-cov/217-runtime-subunit/test.py b/testsuite/tests/instr-cov/217-runtime-subunit/test.py index 05f332b4a..f444f8d30 100644 --- a/testsuite/tests/instr-cov/217-runtime-subunit/test.py +++ b/testsuite/tests/instr-cov/217-runtime-subunit/test.py @@ -26,6 +26,11 @@ auto_config_args=False, auto_target_args=False, extra_args=["--target", thistest.env.target.triplet, "--RTS", runtime_dir], + # For practical purposes, this test instruments a fake runtime. Since this + # runtime is incomplete, it is not possible to build the coverage runtime + # for it: we cannot run "gnatcov setup" and thus we expect a warning about + # the runtime mismatch. + tolerate_messages="Current runtime is", ) thistest.result() diff --git a/testsuite/tests/instr-cov/91-homonym-runtime-sources/test.py b/testsuite/tests/instr-cov/91-homonym-runtime-sources/test.py index 33a91f669..097e4979a 100644 --- a/testsuite/tests/instr-cov/91-homonym-runtime-sources/test.py +++ b/testsuite/tests/instr-cov/91-homonym-runtime-sources/test.py @@ -7,7 +7,7 @@ from SCOV.instr import xcov_instrument from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor @@ -27,13 +27,12 @@ "--RTS", os.path.abspath("../runtime"), ], + # This test instruments a fake runtime. For practical purposes, that + # runtime is incomplete: it is not possible to build the coverage runtime + # for it, we cannot run "gnatcov setup" and thus we expect a warning about + # the runtime mismatch. + tolerate_messages="Current runtime is", out="instrument.log", ) -thistest.fail_if_not_equal( - "'gnatcov instrument' output", - "", - contents_of("instrument.log"), -) - thistest.result() diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index b1569363e..28cd64c48 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -27,6 +27,7 @@ with GNATCOLL.JSON; use GNATCOLL.JSON; with GNATCOLL.VFS; use GNATCOLL.VFS; with GPR2.Context; with GPR2.Containers; +with GPR2.KB; with GPR2.Log; with GPR2.Path_Name; with GPR2.Project.Attribute; @@ -111,13 +112,19 @@ package body Setup_RTS is Target : String; RTS : String; Config_File : String; - Actual_RTS : out Unbounded_String; + Actual_Target : out Unbounded_String; + Actual_RTS_Dir : out Unbounded_String; + Actual_RTS_Name : out Unbounded_String; Auto_RTS_Profile : out Any_RTS_Profile; Lib_Support : out Library_Support); -- Load the project file at Project_File using the Target/RTS/Config_File -- parameters, then try to guess the profile of the actual runtime in -- effect (Auto_RTS_Profile) and determine the support for libraries for -- this configuration (Lib_Support). + -- + -- Set Actual_Target, Actual_RTS_Dir and Actual_RTS_Name to the actual + -- target/RTS names for the loaded project: they can be different from + -- Target/RTS because of canonicalization and Config_File. procedure Uninstall (Project_Name, Prefix : String); -- Try to uninstall a previous installation of the project called @@ -139,6 +146,18 @@ package body Setup_RTS is -- If Library_Kind is not an empty string, build for that library kind and -- install it as a variant. + procedure Check_Target_RTS_Consistency + (GNATcov_RTS_Project : String; + Setup_Target : String; + Setup_RTS_Dir : String; + Setup_RTS_Name : String); + -- If no project was loaded, do nothing. + -- + -- Otherwise, check that the target and runtime of the loaded project match + -- Setup_Target and Setup_RTS_Dir/Setup_RTS_Name (meant to be the + -- target/runtime for the coverage runtime project GNATcov_RTS_Project used + -- to run the instrumenter). + function Load (Project_File : String; Setup_Config_File : Virtual_File) return Setup_Config; @@ -154,10 +173,13 @@ package body Setup_RTS is procedure Save_Setup_Config (Project_Dir : String; Project_Name : String; + Target : String; + RTS_Dir : String; + RTS_Name : String; Config : Setup_Config); - -- Write Config as a JSON file in Project_Dir for the Project_Name runtime - -- project to install. Use a filename that will match the Install'Artifacts - -- attribute in the runtime project file. + -- Write Target/RTS_Dir/RTS_Name/Config as a JSON file in Project_Dir for + -- the Project_Name runtime project to install. Use a filename that will + -- match the Install'Artifacts attribute in the runtime project file. function Has_Shared_Lib (RTS_Dir : String; Shared_Lib_Ext : String) return Boolean; @@ -395,7 +417,9 @@ package body Setup_RTS is Target : String; RTS : String; Config_File : String; - Actual_RTS : out Unbounded_String; + Actual_Target : out Unbounded_String; + Actual_RTS_Dir : out Unbounded_String; + Actual_RTS_Name : out Unbounded_String; Auto_RTS_Profile : out Any_RTS_Profile; Lib_Support : out Library_Support) is @@ -449,17 +473,21 @@ package body Setup_RTS is end if; end; - Actual_RTS := - (if Prj.Has_Runtime_Project - then +String (Prj.Runtime (Main_Language)) - else Null_Unbounded_String); + -- Compute canoncial target/RTS names using GPR2. Show them in debug + -- traces: they can be slightly different from the names users passed. - -- Show the actual names for the target and the runtime that GPR2 uses. - -- They can be slightly different from the names users passed. + Actual_Target := +String (Prj.Target (Canonical => True)); + Setup_RTS_Trace.Trace ("Actual target: " & (+Actual_Target)); - Setup_RTS_Trace.Trace - ("Actual target: " & String (Prj.Target (Canonical => True))); - Setup_RTS_Trace.Trace ("Actual RTS: " & (+Actual_RTS)); + if Prj.Has_Runtime_Project then + Actual_RTS_Dir := +String (Prj.Runtime_Project.Dir_Name.Value); + Actual_RTS_Name := +String (Prj.Runtime (Main_Language)); + Setup_RTS_Trace.Trace ("Runtime project was loaded"); + Setup_RTS_Trace.Trace ("Actual RTS directory: " & (+Actual_RTS_Dir)); + Setup_RTS_Trace.Trace ("Actual RTS name: " & (+Actual_RTS_Name)); + else + Setup_RTS_Trace.Trace ("No runtime project loaded"); + end if; -- The best heuristic we have to determine if the actual runtime is -- "full" is to look for an Ada source file that is typically found in @@ -683,7 +711,9 @@ package body Setup_RTS is is Temp_Dir : Temporary_Directory; - Actual_RTS : Unbounded_String; + Actual_Target : Unbounded_String; + Actual_RTS_Dir : Unbounded_String; + Actual_RTS_Name : Unbounded_String; Auto_RTS_Profile : Any_RTS_Profile; Actual_RTS_Profile : Resolved_RTS_Profile; Lib_Support : Library_Support; @@ -703,7 +733,9 @@ package body Setup_RTS is Target, RTS, Config_File, - Actual_RTS, + Actual_Target, + Actual_RTS_Dir, + Actual_RTS_Name, Auto_RTS_Profile, Lib_Support); @@ -738,7 +770,7 @@ package body Setup_RTS is Dump_Config : constant Any_Dump_Config := Load_Dump_Config - (Default_Dump_Config (Actual_RTS_Profile, +Actual_RTS)); + (Default_Dump_Config (Actual_RTS_Profile, +Actual_RTS_Name)); begin -- Try to uninstall a previous installation of the instrumentation -- runtime in the requested prefix. This is to avoid installation @@ -755,12 +787,16 @@ package body Setup_RTS is -- project. Save_Setup_Config - (Containing_Directory (Actual_Project_File), - Install_Name, - (Project_File => <>, - RTS_Profile => Actual_RTS_Profile, - RTS_Profile_Present => True, - Default_Dump_Config => Dump_Config)); + (Project_Dir => Containing_Directory (Actual_Project_File), + Project_Name => Install_Name, + Target => +Actual_Target, + RTS_Dir => +Actual_RTS_Dir, + RTS_Name => +Actual_RTS_Name, + Config => + (Project_File => <>, + RTS_Profile => Actual_RTS_Profile, + RTS_Profile_Present => True, + Default_Dump_Config => Dump_Config)); -- Check that the RTS profile is compatible with the selected -- defaults for the dump config. @@ -854,6 +890,109 @@ package body Setup_RTS is end; end Setup; + ---------------------------------- + -- Check_Target_RTS_Consistency -- + ---------------------------------- + + procedure Check_Target_RTS_Consistency + (GNATcov_RTS_Project : String; + Setup_Target : String; + Setup_RTS_Dir : String; + Setup_RTS_Name : String) + is + + function Canonicalize_Target (Name : String) return String; + function Canonicalize_Runtime (Name : String) return String; + -- Since the expected target/RTS couple comes from "gnatcov setup" + -- (GPR2-based) while the actual one come from the Project package + -- (GNATCOLL.Projects), we have to deal with inconsistencies between the + -- two. + -- + -- For the target, we can use GPR2's capability to normalize target + -- names (GPR2.KB.Normalized_Target). + -- + -- For the runtime, GPR2 and GNATCOLL.Projects are not perfectly + -- concordant wrt the formatting of runtime names: GPR2 can return an + -- empty string for the default runtime, sometimes the name is a + -- directory name, sometimes that directory name has a trailing + -- directory separator, ... + -- + -- In addition, unless --config is used, GNATCOLL.Projects is likely to + -- return an empty string for the default runtime, so we are not able to + -- check runtime consistency in this case. Hopefully inconsistency will + -- be unlikely when this happens: assuming the target is the same, it is + -- likely that the user never tries to use a non-default runtime. + -- + -- TODO??? (eng/das/cov/gnatcoverage#72) Once the GPR2 transition is + -- over, we should not have to worry about discrepancies anymore. + + function Canonicalize_Target (Name : String) return String + is (String + (GPR2.KB.Create.Normalized_Target (GPR2.Name_Type (Name)))); + + -------------------------- + -- Canonicalize_Runtime -- + -------------------------- + + function Canonicalize_Runtime (Name : String) return String is + + -- Strip trailing directory separators from Name (see the above + -- comment). + + Last : Natural := Name'Last; + begin + for I in reverse Name'Range loop + exit when Name (I) not in '/' | '\'; + Last := I - 1; + end loop; + + return Name (Name'First .. Last); + end Canonicalize_Runtime; + + -- Start of processing for Check_Target_RTS_Consistency + + begin + -- If no project was loaded, there is no current target/RTS, and so + -- nothing to check. + + if not Project.Is_Project_Loaded then + return; + end if; + + declare + function Error_Message (What, Expected, Actual : String) return String + is ("Current " & What & " is:" + & ASCII.LF & " " + & (if Actual = "" then "" else Actual) + & ASCII.LF & "which is inconsistent with the " & What + & " for " & GNATcov_RTS_Project & ": " + & ASCII.LF & " " + & (if Expected = "" then "" else Expected)); + + Expected_Target : constant String := + Canonicalize_Target (Setup_Target); + Expected_RTS_Dir : constant String := + Canonicalize_Runtime (Setup_RTS_Dir); + Expected_RTS_Name : constant String := + Canonicalize_Runtime (Setup_RTS_Name); + + Actual_Target : constant String := + Canonicalize_Target (Project.Target); + Actual_RTS : constant String := + Canonicalize_Runtime (Project.Runtime); + + begin + if Expected_Target /= Actual_Target then + Warn (Error_Message ("target", Expected_Target, Actual_Target)); + elsif Actual_RTS /= "" + and then Expected_RTS_Dir /= Actual_RTS + and then Expected_RTS_Name /= Actual_RTS + then + Warn (Error_Message ("runtime", Expected_RTS_Dir, Actual_RTS)); + end if; + end; + end Check_Target_RTS_Consistency; + ---------- -- Load -- ---------- @@ -1037,6 +1176,12 @@ package body Setup_RTS is Stop_With_Error ("Object expected at the top-level"); end if; + Check_Target_RTS_Consistency + (Project_File, + +Get ("target"), + +Get ("runtime-dir"), + +Get ("runtime-name")); + declare RTS_Profile : constant String := +Get ("rts-profile"); begin @@ -1086,6 +1231,9 @@ package body Setup_RTS is procedure Save_Setup_Config (Project_Dir : String; Project_Name : String; + Target : String; + RTS_Dir : String; + RTS_Name : String; Config : Setup_Config) is Config_Filename : constant String := @@ -1095,6 +1243,9 @@ package body Setup_RTS is J : constant JSON_Value := Create_Object; begin + J.Set_Field ("target", Target); + J.Set_Field ("runtime-dir", RTS_Dir); + J.Set_Field ("runtime-name", RTS_Name); J.Set_Field ("rts-profile", Image (Config.RTS_Profile)); declare Dump_Cfg : Any_Dump_Config renames Config.Default_Dump_Config; From e5646c40f80dea8009075591e9f582be87c8fb37 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 19 Mar 2024 11:29:32 +0100 Subject: [PATCH 0777/1483] Port the 22-sustained Ada runtime This is a copy of the 22-sustained branch Ada runtime. --- .../ada-rts/gnatcov_rts-buffers-lists.ads | 36 ++ tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb | 137 ++++++++ tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads | 222 +++++++++++++ .../gnatcov_rts-traces-output-base64.adb | 179 ++++++++++ .../gnatcov_rts-traces-output-base64.ads | 37 +++ .../gnatcov_rts-traces-output-bytes_io.adb | 63 ++++ .../gnatcov_rts-traces-output-bytes_io.ads | 69 ++++ .../gnatcov_rts-traces-output-text_io.ads | 46 +++ .../ada-rts/gnatcov_rts-traces-output.adb | 313 ++++++++++++++++++ .../ada-rts/gnatcov_rts-traces-output.ads | 56 ++++ tools/gnatcov/ada-rts/gnatcov_rts-traces.adb | 45 +++ tools/gnatcov/ada-rts/gnatcov_rts-traces.ads | 241 ++++++++++++++ tools/gnatcov/ada-rts/gnatcov_rts.ads | 48 +++ tools/gnatcov/ada-rts/gnatcov_rts_aamp.gpr | 27 ++ 14 files changed, 1519 insertions(+) create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.adb create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.ads create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-traces-output-text_io.ads create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-traces.adb create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-traces.ads create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts.ads create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts_aamp.gpr diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads new file mode 100644 index 000000000..e994c12b8 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads @@ -0,0 +1,36 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2021, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- Parent package to host lists of buffers for units of interest + +-- This unit needs to be compilable with Ada 95 compilers + +package GNATcov_RTS.Buffers.Lists is + + type Unit_Coverage_Buffers_Access is access all Unit_Coverage_Buffers; + + type Unit_Coverage_Buffers_Array is + array (Positive range <>) of Unit_Coverage_Buffers_Access; + +end GNATcov_RTS.Buffers.Lists; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb new file mode 100644 index 000000000..116a6d833 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb @@ -0,0 +1,137 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2022, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +package body GNATcov_RTS.Buffers is + + ----------------- + -- To_String -- + ---------------- + + function To_String (Arr : Uint8_Array) return String is + Result : String (Arr'Range); + begin + for I in Arr'Range loop + Result (I) := Character'Val (Arr (I)); + end loop; + return Result; + end To_String; + + ------------------- + -- From_String -- + ------------------- + + function From_String (Str : String) return Uint8_Array + is + Result : Uint8_Array (Str'Range); + begin + for I in Str'Range loop + Result (I) := Character'Pos (Str (I)); + end loop; + return Result; + end From_String; + + subtype Unbounded_Coverage_Buffer_Type is Coverage_Buffer_Type (Bit_Id); + + ------------- + -- Witness -- + ------------- + + procedure Witness (Buffer_Address : System.Address; Bit : Bit_Id) is + Buffer : Unbounded_Coverage_Buffer_Type; + for Buffer'Address use Buffer_Address; + pragma Import (Ada, Buffer); + begin + Buffer (Bit) := True; + end Witness; + + function Witness + (Buffer_Address : System.Address; Bit : Bit_Id) return Witness_Dummy_Type + is + begin + Witness (Buffer_Address, Bit); + return (Data => False); + end Witness; + + function Witness + (Buffer_Address : System.Address; Bit : Bit_Id) return Boolean + is + begin + Witness (Buffer_Address, Bit); + return False; + end Witness; + + function Witness + (Buffer_Address : System.Address; + False_Bit, True_Bit : Bit_Id; + Value : Boolean) return Boolean is + begin + if Value then + Witness (Buffer_Address, True_Bit); + else + Witness (Buffer_Address, False_Bit); + end if; + return Value; + end Witness; + + function Witness + (Decision_Buffer_Address : System.Address; + False_Bit, True_Bit : Bit_Id; + MCDC_Buffer_Address : System.Address; + MCDC_Base : Bit_Id; + MCDC_Path_Address : System.Address; + Value : Boolean) return Boolean + is + MCDC_Path_Index : Any_Bit_Id; + for MCDC_Path_Index'Address use MCDC_Path_Address; + pragma Import (Ada, MCDC_Path_Index); + + begin + Witness (MCDC_Buffer_Address, MCDC_Base + MCDC_Path_Index); + return Witness (Decision_Buffer_Address, False_Bit, True_Bit, Value); + end Witness; + + function Witness + (Buffer_Address : System.Address; + Offset_For_True : Any_Bit_Id; + First : Boolean; + Value : Boolean) return Boolean + is + MCDC_Path_Index : Any_Bit_Id; + for MCDC_Path_Index'Address use Buffer_Address; + pragma Import (Ada, MCDC_Path_Index); + begin + if First then + MCDC_Path_Index := 0; + end if; + + if Value then + MCDC_Path_Index := MCDC_Path_Index + Offset_For_True; + end if; + + return Value; + end Witness; + +end GNATcov_RTS.Buffers; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads new file mode 100644 index 000000000..01440666e --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads @@ -0,0 +1,222 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2022, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This package provides types and subprograms to maintain data about the +-- satisfaction of coverage obligations. + +-- This unit needs to be compilable with Ada 95 compilers + +with Interfaces; +with System; + +package GNATcov_RTS.Buffers is + + pragma Pure; + + -- All data takes the form of big arrays of booleans: coverage buffers. How + -- to interpret these depend on the type of coverage obligation. + -- + -- For statement coverage, each statement is assigned such a boolean, which + -- indicates whether it was executed. + -- + -- For decision coverage, each decision is assigned two booleans: one which + -- indicates whether the decision reached the False outcome and another for + -- the True outcome. + + type Any_Unit_Part is + (Not_Applicable_Part, Unit_Body, Unit_Spec, Unit_Separate); + -- Not_Applicable_Part is a default value used for compilation units in + -- languages that are not unit-based. + + type Any_Language_Kind is (Unit_Based_Language, File_Based_Language); + + --------------------------------------------- + -- Mapping of coverage buffer bits to SCOs -- + --------------------------------------------- + + --------------------------- + -- Source trace bit maps -- + --------------------------- + + -- As instrumentation is inserted, bit positions in coverage buffers are + -- allocated, and these allocations are associated to low-level SCO Ids. + -- Once low-level SCOs are converted to high-level SCOs, new mappings + -- are generated to allow mapping bit positions to high level SCOs when + -- processing buffers from a target run. + + type Any_Bit_Id is new Integer; + No_Bit_Id : constant Any_Bit_Id := -1; + subtype Bit_Id is Any_Bit_Id range 0 .. Any_Bit_Id'Last; + -- Unique identifier for a boolean in a coverage buffer + + type Coverage_Buffer_Type is array (Bit_Id range <>) of Boolean; + -- Even though it is tempting to pack this array to save memory, we must + -- avoid bit packing to allow concurrent writes to coverage buffers. + + type Uint8_Array is array (Positive range <>) of Interfaces.Unsigned_8; + + function To_String (Arr : Uint8_Array) return String; + + function From_String (Str : String) return Uint8_Array; + + type SCOs_Hash is new Uint8_Array (1 .. 20); + -- Hash type to perform consistency checks over Source Coverage + -- Obligations. 20-byte to hold a SHA-1. + + type Unit_Coverage_Buffers is record + Fingerprint : SCOs_Hash; + -- Hash of SCO info for this unit, as gnatcov computes it (see + -- SC_Obligations). Used a fast way to check that coverage obligations + -- and coverage data are consistent. Specific hash values are computed + -- during instrumentation. + + Language_Kind : Any_Language_Kind; + -- Language kind for this unit + + Unit_Part : Any_Unit_Part; + Unit_Name_Length : Positive; + Unit_Name : System.Address; + -- Unit kind and name for the instrumented unit. The Unit_Name field + -- accounts both for unit-based languages (such as Ada) and file-based + -- languages such as C. + -- + -- The Unit_Part field is only there for unit-based languages and is set + -- to Not_Applicable_Part for file-based languages. + -- + -- More specifically, for unit-based languages, Unit_Name is the fully + -- qualified name of the compilation unit (or subunit) in lower case. + -- For instance: "foo", "ada.text_io" or "foo.bar.my_subunit". + -- + -- For file-based languages, Unit_Name is the simple filename, e.g. + -- "foo.c". + + Project_Name_Length : Natural; + Project_Name : System.Address; + -- Project name for this compilation unit. This is only initialized for + -- file-based languages (otherwise, it is an empty string). + + Statement, Decision, MCDC : System.Address; + -- Addresses of coverage buffers for statement obligations, decision + -- obligations and MC/DC obligations. The address refer to + -- Coverage_Buffer_Type arrays whose bounds go from + -- 0 to Unit_Coverage_Buffers.*_Last_Bit. + + Statement_Last_Bit, Decision_Last_Bit, MCDC_Last_Bit : Any_Bit_Id; + -- Index for the last bits in coverage buffers for statements, decisions + -- and MC/DC. + end record; + + ------------------------- + -- Witness subprograms -- + ------------------------- + + -- The following subprograms are called by generated code to record + -- the execution of constructs. + + -- Note that the Buffer_Address parameters below are required so that: + -- + -- * functions don't have IN OUT formals, which are illegal before Ada + -- 2012; + -- + -- * our hack for pure units to be able to reference coverage buffers + -- (which are global state, i.e. unreachable from pure units) works. + + -- Statements and declarations + + -- The following Witness subprograms set the Boolean corresponding to Bit + -- to True in Buffer in various context. + + procedure Witness (Buffer_Address : System.Address; Bit : Bit_Id); + -- This variant is used as part of sequence of statements, to witness + -- that we have reached a specific point in the sequence. + + type Witness_Dummy_Type is record + Data : Boolean; + end record; + function Witness + (Buffer_Address : System.Address; Bit : Bit_Id) return Witness_Dummy_Type; + -- This variant is used in contexts where statements are not allowed + -- but declarations are, for example ahead of library level declarations + -- to witness their elaboration. + + -- Use a dummy type of minimal but non-zero size to prevent the compiler + -- from optimizing calls away, as this unit is Pure. Use a composite type + -- to prevent ambiguities in contexts where the Boolean variant below + -- might be used, for example in constructs like + -- + -- case Witness (Buffer, Bit) is + -- when others => ... + -- end case; + -- + -- used for some kinds of expression functions. + + function Witness + (Buffer_Address : System.Address; Bit : Bit_Id) return Boolean; + -- This variant is used in Boolean expression contexts and always returns + -- True. + + -- Decisions + + subtype MCDC_State_Type is Any_Bit_Id; + + -- When instrumenting expression functions, we need to conjure up storage + -- for MC/DC state as limited aggregates. The following type provides for + -- this use case. + + type MCDC_State_Holder is limited record + State : aliased MCDC_State_Type; + end record; + + function Witness + (Buffer_Address : System.Address; + False_Bit, True_Bit : Bit_Id; + Value : Boolean) return Boolean; + -- If Value is False, set the Boolean corresponding to False_Bit to True in + -- Buffer. Set the one corresponding to True_Bit otherwise. + + function Witness + (Decision_Buffer_Address : System.Address; + False_Bit, True_Bit : Bit_Id; + MCDC_Buffer_Address : System.Address; + MCDC_Base : Bit_Id; + MCDC_Path_Address : System.Address; + Value : Boolean) return Boolean; + -- Same as above, and also set the bit determined by MCDC_Base and the + -- Bit_Id value at MCDC_Path_Address in the buffer at MCDC_Buffer_Address. + -- Note that MCDC_Path may not be passed by value, because it is not known + -- until the side effects of the actual for the Value formal have been + -- evaluated. + + -- Conditions + + function Witness + (Buffer_Address : System.Address; + Offset_For_True : Any_Bit_Id; + First : Boolean; + Value : Boolean) return Boolean; + -- Buffer_Address is the address of an MCDC_State_Type local variable. + -- If First is True, first reset it to 0. + -- If Value is True, add Offset_For_True. + +end GNATcov_RTS.Buffers; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb new file mode 100644 index 000000000..3f3820423 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb @@ -0,0 +1,179 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2022, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +with GNATcov_RTS.Traces.Output.Text_IO; + +package body GNATcov_RTS.Traces.Output.Base64 is + + package TIO renames Output.Text_IO; -- Just a shorthand + + -- Base64-over-stdout stream + + type Uint6 is mod 2 ** 6; + Base64_Alphabet : constant array (Uint6) of Character := + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + & "abcdefghijklmnopqrstuvwxyz" + & "0123456789" + & "+/"; + Base64_Padding : constant Character := '='; + + type Base64_Buffer_Index is range 1 .. 4; + subtype Valid_Base64_Buffer_Index is Base64_Buffer_Index range 1 .. 3; + type Base64_Buffer_Array is array (Valid_Base64_Buffer_Index) of Unsigned_8; + + type Base64_Buffer is record + Bytes : Base64_Buffer_Array := (others => 0); + -- We output base64 content by groups of 4 digits, which encode for 3 + -- input bytes. This buffer is used to accumulate input bytes. + + Next : Base64_Buffer_Index := 1; + -- Index of the next cell in Bytes where to store an input byte. This + -- means that a given time, only the Bytes (1 .. Next - 1) slice contain + -- input bytes. + + Columns : Natural := 0; + -- Number of output digits on the current line. We keep track of this to + -- break lines at 80 digits. + end record; + + procedure Write_Bytes + (Output : in out Base64_Buffer; Bytes : Uint8_Array); + -- Callback for Generic_Write_Trace_File + + procedure Flush (Output : in out Base64_Buffer); + -- Flush the remaining bytes in Output to the standard output. If the + -- buffer is not full, this means it's the end of the content: pad with + -- '=' bytes as needed. + + ----------------- + -- Write_Bytes -- + ----------------- + + procedure Write_Bytes + (Output : in out Base64_Buffer; Bytes : Uint8_Array) + is + begin + for I in Bytes'Range loop + Output.Bytes (Output.Next) := Bytes (I); + Output.Next := Output.Next + 1; + if Output.Next = Base64_Buffer_Index'Last then + Flush (Output); + end if; + end loop; + end Write_Bytes; + + ----------- + -- Flush -- + ----------- + + procedure Flush (Output : in out Base64_Buffer) is + + function "+" (Bits : Uint6) return Character; + -- Shortcut to get the ASCII representation of the given 6 bits + + --------- + -- "+" -- + --------- + + function "+" (Bits : Uint6) return Character is + begin + return Base64_Alphabet (Bits); + end "+"; + + -- Split input bytes (3 bytes = 24 bits) into 4 groups of 6 bits + + In_Bytes : Base64_Buffer_Array renames Output.Bytes; + Out_Digits : String (1 .. 4); + begin + case Output.Next is + when 1 => + return; + + when 2 => + Out_Digits (1) := +Uint6 (In_Bytes (1) / 4); + Out_Digits (2) := +(Uint6 (In_Bytes (1) mod 4) * 16); + Out_Digits (3) := Base64_Padding; + Out_Digits (4) := Base64_Padding; + + when 3 => + Out_Digits (1) := +Uint6 (In_Bytes (1) / 4); + Out_Digits (2) := +(Uint6 (In_Bytes (1) mod 4) * 16 + or Uint6 (In_Bytes (2) / 16)); + Out_Digits (3) := +(Uint6 (In_Bytes (2) mod 16) * 4); + Out_Digits (4) := Base64_Padding; + + when 4 => + Out_Digits (1) := +Uint6 (In_Bytes (1) / 4); + Out_Digits (2) := +(Uint6 (In_Bytes (1) mod 4) * 16 + or Uint6 (In_Bytes (2) / 16)); + Out_Digits (3) := +(Uint6 (In_Bytes (2) mod 16) * 4 + or Uint6 (In_Bytes (3) / 64)); + Out_Digits (4) := +(Uint6 (In_Bytes (3) mod 64)); + end case; + + -- Output the 4 characters corresponding to each group of 6 bits. + -- Introduce a newline when needed in order to avoid exceeding 80 + -- characters per line. + + TIO.Put (Out_Digits); + Output.Columns := Output.Columns + 4; + if Output.Columns >= 80 then + Output.Columns := 0; + TIO.New_Line; + end if; + + Output.Bytes := (others => 0); + Output.Next := 1; + end Flush; + + ---------------------- + -- Write_Trace_File -- + ---------------------- + + procedure Write_Trace_File + (Buffers : Unit_Coverage_Buffers_Array; + Program_Name : String; + Exec_Date : Serialized_Timestamp; + User_Data : String := "") + is + procedure Helper is new Generic_Write_Trace_File (Base64_Buffer); + Buffer : Base64_Buffer := + (Bytes => (others => 0), + Next => 1, + Columns => 0); + begin + TIO.New_Line; + TIO.Put_Line ("== GNATcoverage source trace file =="); + Helper (Buffer, Buffers, Program_Name, Exec_Date, User_Data); + Flush (Buffer); + if Buffer.Columns /= 0 then + TIO.New_Line; + end if; + TIO.Put_Line ("== End =="); + TIO.New_Line; + end Write_Trace_File; + +end GNATcov_RTS.Traces.Output.Base64; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads new file mode 100644 index 000000000..771d01472 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads @@ -0,0 +1,37 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2021, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +package GNATcov_RTS.Traces.Output.Base64 is + + procedure Write_Trace_File + (Buffers : Unit_Coverage_Buffers_Array; + Program_Name : String; + Exec_Date : Serialized_Timestamp; + User_Data : String := ""); + -- Write a Base64-encoded trace file to the standard output + -- (Ada.Text_IO.Standard_Output). + +end GNATcov_RTS.Traces.Output.Base64; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.adb new file mode 100644 index 000000000..df9288908 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.adb @@ -0,0 +1,63 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2021, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +package body GNATcov_RTS.Traces.Output.Bytes_IO is + + ------------ + -- Close -- + ------------ + + procedure Close (File : in out File_Type) is + begin + OSLIB.Close (FD => File.FD); + end Close; + + ------------- + -- Create -- + ------------- + + procedure Create (File : in out File_Type; Name : String) is + begin + File.FD := OSLIB.Create_File (Name => Name, Fmode => OSLIB.Binary); + if File.FD = OSLIB.Invalid_FD then + raise IO_Error; + end if; + end Create; + + ------------ + -- Write -- + ------------ + + procedure Write (File : File_Type; Byte : U8) is + N : Integer; + begin + N := OSLIB.Write (FD => File.FD, A => Byte'Address, N => 1); + if N /= 1 then + raise IO_Error; + end if; + end Write; + +end GNATcov_RTS.Traces.Output.Bytes_IO; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.ads new file mode 100644 index 000000000..c84b49590 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.ads @@ -0,0 +1,69 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2021, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +-- This provides the base IO interface for use by the "bin-file" trace +-- dumper, restricted to configurations where we can assume that a full +-- GNAT RTS is available. +-- +-- The interface is devised as a simple subset of Ada.Direct_IO. It may +-- be used from "atexit" handlers though, so may only resort to low level +-- mechanisms as this triggers after the runtime has been finalized. + +-- The base IO interface exposed by GNAT.OS_Lib, going through elementary +-- int file descriptors, is well suited for our purpose. + +with Interfaces; +with GNAT.OS_Lib; + +private package GNATcov_RTS.Traces.Output.Bytes_IO is + + package OSLIB renames GNAT.OS_Lib; + use type OSLIB.File_Descriptor; + + -- Expose File_Type as a limited record type with implicit + -- initializers so clients can simply declare a F : File_Type; + -- object and call Create as with Direct_IO. + + type File_Type is limited record + FD : OSLIB.File_Descriptor := OSLIB.Invalid_FD; + end record; + + subtype U8 is Interfaces.Unsigned_8; + + IO_Error : exception; + -- Exception we raise in case of errors reported by the underlying + -- IO engine. + + procedure Close (File : in out File_Type); + + procedure Create (File : in out File_Type; Name : String); + -- Create or reset a file of the requested Name, ready for writing + -- in binary mode. Raise IO_Error if the operation somehow fails and + -- would yield an invalid File descriptor. + + procedure Write (File : File_Type; Byte : U8); + +end GNATcov_RTS.Traces.Output.Bytes_IO; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-text_io.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-text_io.ads new file mode 100644 index 000000000..df45056f8 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-text_io.ads @@ -0,0 +1,46 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2021, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +-- This provides the base IO interface for use by the "base64-stdout" trace +-- dumper, available in all configurations. +-- +-- The interface is devised as a simple subset of Ada.Text_IO. It may +-- be used from "atexit" handlers though, so may only resort to low level +-- mechanisms as this triggers after the runtime has been finalized. + +-- GNAT.IO provides the low level services we need and is available from +-- most if not all the GNAT runtime profiles so is a good common ground for +-- our use. + +with GNAT.IO; + +private package GNATcov_RTS.Traces.Output.Text_IO is + + procedure New_Line (N : Positive := 1) renames GNAT.IO.New_Line; + procedure Put (S : String) renames GNAT.IO.Put; + procedure Put_Line (S : String) renames GNAT.IO.Put_Line; + +end GNATcov_RTS.Traces.Output.Text_IO; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb new file mode 100644 index 000000000..2ce72f086 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb @@ -0,0 +1,313 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2022, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +with Ada.Unchecked_Conversion; + +with System; + +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; + +package body GNATcov_RTS.Traces.Output is + + ------------------------------ + -- Generic_Write_Trace_File -- + ------------------------------ + + procedure Generic_Write_Trace_File + (Output : in out Output_Stream; + Buffers : Unit_Coverage_Buffers_Array; + Program_Name : String; + Exec_Date : Serialized_Timestamp; + User_Data : String := "") + is + + Alignment : constant Unsigned_8 := 8; + -- Alignment (in bytes) to use when writing trace files. It is used + -- to align record types / strings written in the trace. + + generic + type T is mod <>; + with function Shift_Right + (Value : T; + Amount : Natural) return T is <>; + procedure Write_Unsigned (Output : in out Output_Stream; U : T); + -- Generic implementation for Write_U8, Write_U16 and Write_U32. + -- Write the bytes in little-endian order. + + procedure Write_Padding (Output : in out Output_Stream; Count : Natural); + -- Write X bytes of padding to Output so that Count + X is a multiple of + -- Alignment. + + procedure Write_Header (Output : in out Output_Stream); + -- Write a trace file header to Output + + procedure Write_Info + (Output : in out Output_Stream; + Kind : Supported_Info_Kind; + Data : String); + -- Write a trace info entry to Output + + procedure Write_Entry + (Output : in out Output_Stream; Buffers : Unit_Coverage_Buffers); + -- Write a whole trace entry (header, unit name and buffers) for Buffers + -- to Output. + + procedure Write_Buffer + (Output : in out Output_Stream; Buffer : Coverage_Buffer_Type); + -- Write the Buffer coverage buffer to Output + + procedure Write_Buffer + (Output : in out Output_Stream; + Buffer_Address : System.Address; + Last_Bit : Any_Bit_Id); + -- Wrapper for Write_Buffer to use a buffer from its address and upper + -- bound. + + -------------------- + -- Write_Unsigned -- + -------------------- + + procedure Write_Unsigned (Output : in out Output_Stream; U : T) is + Bytes : Uint8_Array (1 .. T'Size / 8); + Value : T := U; + begin + for I in Bytes'Range loop + Bytes (I) := Unsigned_8 (Value and 16#FF#); + Value := Shift_Right (Value, 8); + end loop; + Write_Bytes (Output, Bytes); + end Write_Unsigned; + + procedure Write_U8 is new Write_Unsigned (T => Unsigned_8); + procedure Write_U16 is new Write_Unsigned (T => Unsigned_16); + procedure Write_U32 is new Write_Unsigned (T => Unsigned_32); + + ------------------- + -- Write_Padding -- + ------------------- + + procedure Write_Padding (Output : in out Output_Stream; Count : Natural) + is + Alignment : constant Natural := + Natural (Generic_Write_Trace_File.Alignment); + Pad_Count : constant Natural := Alignment - Count mod Alignment; + begin + if Pad_Count /= Alignment then + declare + Bytes : constant Uint8_Array (1 .. Pad_Count) := (others => 0); + begin + Write_Bytes (Output, Bytes); + end; + end if; + end Write_Padding; + + ------------------ + -- Write_Header -- + ------------------ + + procedure Write_Header (Output : in out Output_Stream) is + begin + Write_Bytes (Output, From_String (Trace_File_Magic)); + Write_U32 (Output, Unsigned_32 (Current_Version)); + Write_U8 (Output, Alignment); + + -- The Write_Unsigned subprogram (which is used to write bytes) + -- writes the bytes in the little endian order. + + Write_U8 (Output, Unsigned_8 (Little_Endian)); + Write_U16 (Output, 0); + end Write_Header; + + ---------------- + -- Write_Info -- + ---------------- + + procedure Write_Info + (Output : in out Output_Stream; + Kind : Supported_Info_Kind; + Data : String) + is + begin + Write_U32 (Output, Unsigned_32 (Kind)); + Write_U32 (Output, Unsigned_32 (Data'Length)); + Write_Bytes (Output, From_String (Data)); + Write_Padding (Output, Data'Length); + end Write_Info; + + ----------------- + -- Write_Entry -- + ----------------- + + procedure Write_Entry + (Output : in out Output_Stream; Buffers : Unit_Coverage_Buffers) + is + type Unit_Name_String is new String (1 .. Buffers.Unit_Name_Length); + type Unit_Name_String_Acc is access all Unit_Name_String; + + type Project_Name_String is + new String (1 .. Buffers.Project_Name_Length); + type Project_Name_String_Acc is access all Project_Name_String; + + function To_Unit_Name_String_Acc is + new Ada.Unchecked_Conversion (System.Address, Unit_Name_String_Acc); + + function To_Project_Name_String_Acc is + new Ada.Unchecked_Conversion + (System.Address, Project_Name_String_Acc); + + Unit_Name : constant Unit_Name_String_Acc := + To_Unit_Name_String_Acc (Buffers.Unit_Name); + + Project_Name : constant Project_Name_String_Acc := + To_Project_Name_String_Acc (Buffers.Project_Name); + + begin + -- Write trace entry header + + Write_U32 (Output, Unsigned_32 (Buffers.Unit_Name_Length)); + Write_U32 (Output, Unsigned_32 (Buffers.Project_Name_Length)); + Write_U32 (Output, Unsigned_32 (Buffers.Statement_Last_Bit + 1)); + Write_U32 (Output, Unsigned_32 (Buffers.Decision_Last_Bit + 1)); + Write_U32 (Output, Unsigned_32 (Buffers.MCDC_Last_Bit + 1)); + Write_U8 + (Output, + Unsigned_8 (Any_Language_Kind_Map (Buffers.Language_Kind))); + Write_U8 + (Output, + Unsigned_8 + (GNATcov_RTS.Buffers.Any_Unit_Part'Pos (Buffers.Unit_Part))); + Write_U8 (Output, Unsigned_8 (LSB_First_Bytes)); + Write_Bytes (Output, Uint8_Array (Buffers.Fingerprint)); + Write_Bytes (Output, (1 .. 5 => 0)); + + -- Write unit name and project name + + Write_Bytes (Output, From_String (String (Unit_Name.all))); + Write_Padding (Output, Unit_Name.all'Length); + + Write_Bytes (Output, From_String (String (Project_Name.all))); + Write_Padding (Output, Project_Name.all'Length); + + -- Write coverage buffers + + Write_Buffer (Output, Buffers.Statement, Buffers.Statement_Last_Bit); + Write_Buffer (Output, Buffers.Decision, Buffers.Decision_Last_Bit); + Write_Buffer (Output, Buffers.MCDC, Buffers.MCDC_Last_Bit); + end Write_Entry; + + ------------------ + -- Write_Buffer -- + ------------------ + + procedure Write_Buffer + (Output : in out Output_Stream; Buffer : Coverage_Buffer_Type) + is + + procedure Append_Bit (Value : Boolean); + procedure Flush; + + Current_Byte : Interfaces.Unsigned_8 := 0; + Bit_Mask : Interfaces.Unsigned_8 := 1; + Bytes_Count : Natural := 0; + + ---------------- + -- Append_Bit -- + ---------------- + + procedure Append_Bit (Value : Boolean) is + begin + if Value then + Current_Byte := Current_Byte or Bit_Mask; + end if; + Bit_Mask := 2 * Bit_Mask; + if Bit_Mask = 2 ** 8 then + Flush; + end if; + end Append_Bit; + + ----------- + -- Flush -- + ----------- + + procedure Flush is + begin + if Bit_Mask /= 1 then + Write_Bytes (Output, (1 => Current_Byte)); + Current_Byte := 0; + Bit_Mask := 1; + Bytes_Count := Bytes_Count + 1; + end if; + end Flush; + + -- Start of processing for Write_Buffer + + begin + -- Write bytes that are included in the coverage buffer + + for J in Buffer'Range loop + Append_Bit (Buffer (J)); + end loop; + Flush; + + -- Complete with the required padding + + Write_Padding (Output, Bytes_Count); + end Write_Buffer; + + ------------------ + -- Write_Buffer -- + ------------------ + + procedure Write_Buffer + (Output : in out Output_Stream; + Buffer_Address : System.Address; + Last_Bit : Any_Bit_Id) + is + Buffer : Coverage_Buffer_Type (0 .. Last_Bit); + for Buffer'Address use Buffer_Address; + pragma Import (Ada, Buffer); + + -- Buffer could be declared constant in theory, but would then be + -- wrongly flagged as an incorrectly placed deferred constant + -- declaration by some old toolchains (as observed with 5.04). + begin + Write_Buffer (Output, Buffer); + end Write_Buffer; + + -- Start of processing for Generic_Write_Trace_File + + begin + Write_Header (Output); + Write_Info (Output, Info_Program_Name, Program_Name); + Write_Info (Output, Info_Exec_Date, Exec_Date); + Write_Info (Output, Info_User_Data, User_Data); + Write_Info (Output, Info_End, ""); + for I in Buffers'Range loop + Write_Entry (Output, Buffers (I).all); + end loop; + end Generic_Write_Trace_File; + +end GNATcov_RTS.Traces.Output; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads new file mode 100644 index 000000000..1c9e7f626 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads @@ -0,0 +1,56 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2022, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; + +package GNATcov_RTS.Traces.Output is + + subtype Serialized_Timestamp is String (1 .. 8); + -- Little-endian 64-bit unsigned integer. Represents a date/time as the + -- number of seconds that passed since the Unix Epoch. In other words, a + -- 64-bit Unix timestamp. + + generic + type Output_Stream (<>) is limited private; + -- Entity where the trace file is written + + with procedure Write_Bytes + (Stream : in out Output_Stream; + Bytes : Uint8_Array) is <>; + -- Write Bytes to the given Stream + + procedure Generic_Write_Trace_File + (Output : in out Output_Stream; + Buffers : Unit_Coverage_Buffers_Array; + Program_Name : String; + Exec_Date : Serialized_Timestamp; + User_Data : String := ""); + -- Write a trace file to Output to contain the coverage data in Buffers. + -- + -- Program_Name, Exec_Date, and User_Data are used to fill the + -- corresponding metadata in the written trace file. + +end GNATcov_RTS.Traces.Output; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces.adb new file mode 100644 index 000000000..2c3496a1f --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces.adb @@ -0,0 +1,45 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2021, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- This unit needs to be compilable with Ada 95 compilers + +with System; + +package body GNATcov_RTS.Traces is + + ---------------------- + -- Native_Endianity -- + ---------------------- + + function Native_Endianity return Supported_Endianity is + use type System.Bit_Order; + begin + if System.Default_Bit_Order = System.Low_Order_First then + return Little_Endian; + else + return Big_Endian; + end if; + end Native_Endianity; + +end GNATcov_RTS.Traces; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads new file mode 100644 index 000000000..bc4c6f262 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads @@ -0,0 +1,241 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2022, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- Trace file format for instrumented programs + +-- This unit needs to be compilable with Ada 95 compilers + +with Interfaces; use Interfaces; + +with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; + +package GNATcov_RTS.Traces is + + -- Execution of an instrumented program sets bits in its coverage buffers. + -- These bits convey information that GNATcov will later on use to + -- discharge coverage obligations. + -- + -- This unit describes a file format for an instrumented program to + -- communicate these coverage buffers to GNATcov. + + -- This format expects bytes/Characters to be 8-bit values. + + -- Each trace file starts with a header (see Trace_File_Header), followed + -- by a sequence of trace info entries (see Trace_Entry_Header) ending with + -- a Info_End entry, and then contains zero or several trace entries, + -- typically one per instrumented unit. Each trace entry is padded so that + -- trace entries start and end on byte/half word/word/long word boundaries. + + type Trace_File_Format_Version is new Unsigned_32; + Current_Version : Trace_File_Format_Version := 1; + -- Expected value of the Trace_File_Header.Format_Version field. + -- + -- 0 -- initial version + -- 1 -- extend trace entry model to account for C files + + type Any_Alignment is new Unsigned_8; + subtype Supported_Alignment is Any_Alignment; + -- Number of bytes the trace file writer used to pad trace entries. The + -- size of the trace file is supposed to be a multiple of this value. + -- Supported alignments are: 1, 2, 4 and 8. + + type Any_Endianity is new Unsigned_8; + Little_Endian : constant Any_Endianity := 0; + Big_Endian : constant Any_Endianity := 1; + subtype Supported_Endianity is + Any_Endianity range Little_Endian .. Big_Endian; + -- Endianity to decode multi-byte scalars + + function Native_Endianity return Supported_Endianity; + -- Return the native endianity + + type Hash_Type is new Unsigned_32; + -- Hash type to perform consistency checks + + type Any_Unit_Part is new Unsigned_8; + Not_Applicable_Part : constant Any_Unit_Part := + Buffers.Any_Unit_Part'Pos (Buffers.Not_Applicable_Part); + Unit_Body : constant Any_Unit_Part := + Buffers.Any_Unit_Part'Pos (Buffers.Unit_Body); + Unit_Spec : constant Any_Unit_Part := + Buffers.Any_Unit_Part'Pos (Buffers.Unit_Spec); + Unit_Separate : constant Any_Unit_Part := + Buffers.Any_Unit_Part'Pos (Buffers.Unit_Separate); + subtype All_Unit_Part is + Any_Unit_Part range Not_Applicable_Part .. Unit_Separate; + subtype Supported_Unit_Part is + Any_Unit_Part range Unit_Body .. Unit_Separate; + -- Describe the kind of unit referenced by a trace entry + + Unit_Part_Map : constant + array (Buffers.Any_Unit_Part) of All_Unit_Part := + (Buffers.Not_Applicable_Part => Not_Applicable_Part, + Buffers.Unit_Body => Unit_Body, + Buffers.Unit_Spec => Unit_Spec, + Buffers.Unit_Separate => Unit_Separate); + + type Any_Bit_Count is new Unsigned_32; + -- Number of bits contained in a coverage buffer + + type Any_Language_Kind is new Unsigned_8; + Unit_Based_Language : constant Any_Language_Kind := + Buffers.Any_Language_Kind'Pos (Buffers.Unit_Based_Language); + File_Based_Language : constant Any_Language_Kind := + Buffers.Any_Language_Kind'Pos (Buffers.File_Based_Language); + subtype Supported_Language_Kind is + Any_Language_Kind range Unit_Based_Language .. File_Based_Language; + -- Language kind for a compilation unit + + Any_Language_Kind_Map : constant + array (Buffers.Any_Language_Kind) of Supported_Language_Kind := + (Buffers.Unit_Based_Language => Unit_Based_Language, + Buffers.File_Based_Language => File_Based_Language); + + ----------------------- + -- Trace file header -- + ----------------------- + + Trace_File_Magic : constant String (1 .. 32) := + "GNATcov source trace file" & (26 .. 32 => ASCII.NUL); + -- Expected value of the Trace_File_Header.Magic field (32 bytes) + + type Trace_File_Header is record + Magic : Uint8_Array (1 .. 32); + + Format_Version : Trace_File_Format_Version; + Alignment : Any_Alignment; + Endianity : Any_Endianity; + + Padding : Unsigned_16; + -- Padding used only to make the size of the trace file header a + -- multiple of 8 bytes. Must be zero. + end record; + pragma Pack (Trace_File_Header); + + ----------------------- + -- Trace information -- + ----------------------- + + -- Each trace info entry starts with the following header. Then goes the + -- bytes for the entry content, NUL-padded according to the trace file + -- alignment. + + type Any_Info_Kind is new Unsigned_32; + + Info_End : constant Any_Info_Kind := 0; + -- Special trace info entry: indicates the end of a sequence of entries. No + -- data is associated to this trace info entry. + + Info_Program_Name : constant Any_Info_Kind := 1; + -- Name of the program that produced this trace + + Info_Exec_Date : constant Any_Info_Kind := 2; + -- Date for the program execution that produced this trace + + Info_User_Data : constant Any_Info_Kind := 3; + -- Arbitrary storage for user data. This is exposed to users as the trace + -- "tag". + + subtype Supported_Info_Kind is + Any_Info_Kind range Info_End .. Info_User_Data; + + type Trace_Info_Header is record + Kind : Any_Info_Kind; + -- Kind for this trace info entry + + Length : Unsigned_32; + -- Length of the data associated to this entry + end record; + pragma Pack (Trace_Info_Header); + + ------------------------ + -- Trace entry header -- + ------------------------ + + -- Each trace entry starts with the following header. Then goes: + -- + -- * The name of the unit describes. It is NUL-padded according to the + -- trace file alignment. + -- + -- * The statement coverage buffer. It is also NUL-padded. + -- + -- * The decision coverage buffer. It is also NUL-padded. + -- + -- * The MC/DC coverage buffer. It is also NUL-padded. + + type Any_Bit_Buffer_Encoding is new Unsigned_8; + -- Encoding used to store coverage buffers + + LSB_First_Bytes : constant Any_Bit_Buffer_Encoding := 0; + -- LSB_First_Bytes: bit buffers are encoded as sequences of bytes. + -- + -- * Booleans are encoded with bits the usual way: 0 for False and 1 for + -- True. + -- + -- * Byte X contains bits for bits 8 * Y to 8 * Y + 7. For instance, byte + -- 1 contains bits 8 to 15. + -- + -- * Inside byte X, least significant bit maps to bit 8 * Y while the most + -- significant bit maps to bit 8 * Y + 7. + + subtype Supported_Bit_Buffer_Encoding is + Any_Bit_Buffer_Encoding range LSB_First_Bytes .. LSB_First_Bytes; + + type Trace_Entry_Header is record + Unit_Name_Length : Unsigned_32; + -- Length of the unit name / filename for the unit this trace entry + -- describes. + + Project_Name_Length : Unsigned_32; + -- For file-based languages, length of the project name this file + -- belongs to. For unit-based languages, the unit name is unique so this + -- piece of information is not needed (thus will be 0). + + Statement_Bit_Count : Any_Bit_Count; + Decision_Bit_Count : Any_Bit_Count; + MCDC_Bit_Count : Any_Bit_Count; + -- Number of bits in the statement, decision and MC/DC coverage buffers + + Language_Kind : Any_Language_Kind; + -- Language for this unit + + Unit_Part : Any_Unit_Part; + -- Part of the unit this trace entry describes. Not_Applicable_Part for + -- file-based languages. + + Bit_Buffer_Encoding : Any_Bit_Buffer_Encoding; + -- Encoding used to represent statement and decision coverage buffers + + Fingerprint : Buffers.SCOs_Hash; + -- Hash of SCO info for this unit. Useds a fast way to check that + -- coverage obligations and coverage data are consistent. Specific hash + -- values are computed during instrumentation. + + Padding : Uint8_Array (1 .. 5); + -- Padding used only to make the size of this trace entry header a + -- multiple of 8 bytes. Must be zero. + end record; + pragma Pack (Trace_Entry_Header); + +end GNATcov_RTS.Traces; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts.ads b/tools/gnatcov/ada-rts/gnatcov_rts.ads new file mode 100644 index 000000000..69aa21402 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts.ads @@ -0,0 +1,48 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2019-2021, 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- Namespace for all support packages required to do instrumentation-based +-- coverage computation in GNATcoverage. + +-- This unit needs to be compilable with Ada 95 compilers + +with System; + +package GNATcov_RTS is + + pragma Pure; + + package Std renames Standard; + package Sys renames System; + + Version : constant := 4; + -- For compatibility with the GNATcoverage in use, GNATcov_RTS is + -- versioned. + -- + -- 1 -- initial runtime version + -- 2 -- extend trace entry model to account for C files + -- 3 -- add a renaming of the Standard and System packages in GNATcov_RTS + -- 4 -- add C witness functions / buffer types + +end GNATcov_RTS; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts_aamp.gpr b/tools/gnatcov/ada-rts/gnatcov_rts_aamp.gpr new file mode 100644 index 000000000..8c2c4b8a7 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts_aamp.gpr @@ -0,0 +1,27 @@ +-- Project specific to the AAMP target, which does not support libraries, and +-- does not have a C compiler. + +project GNATcov_RTS_AAMP is + for Source_Files use + ("gnatcov_rts.ads", + "gnatcov_rts-buffers.ads", + "gnatcov_rts-buffers.adb", + "gnatcov_rts-buffers-lists.ads", + "gnatcov_rts-traces.ads", + "gnatcov_rts-traces.adb", + "gnatcov_rts-traces-output.ads", + "gnatcov_rts-traces-output.adb", + "gnatcov_rts-traces-output-text_io.ads", + "gnatcov_rts-traces-output-base64.ads", + "gnatcov_rts-traces-output-base64.adb"); + for Object_Dir use "obj-gnatcov_rts"; + for Languages use ("Ada"); + + package Compiler is + + -- Use the universal addressing switch, which is recommended when + -- compiling for the AAMP target (and is only available on this target). + + for Default_Switches ("Ada") use ("-univ"); + end Compiler; +end GNATcov_RTS_AAMP; From b329d7807a4d82c6a2c6a47369c3cc9f8e262889 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 7 Mar 2024 17:10:25 +0100 Subject: [PATCH 0778/1483] Adapt the Ada 22.2-sustained instrumentation runtime Adapt the Ada instrumentation runtime from the 22.2-sustained setup to account for instrumentation scheme modifications, and changes in representation of internal trace structures. Also make modifications to the runtime to drop use of secondary stack. --- tools/gnatcov/Makefile | 5 + tools/gnatcov/ada-rts/gcvrt.ads | 30 ++++++ .../ada-rts/gnatcov_rts-buffers-lists.ads | 32 ++++++- tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb | 31 +----- tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads | 80 +++++++--------- tools/gnatcov/ada-rts/gnatcov_rts-strings.ads | 44 +++++++++ .../gnatcov_rts-traces-output-base64.adb | 10 +- .../gnatcov_rts-traces-output-base64.ads | 8 +- .../ada-rts/gnatcov_rts-traces-output.adb | 94 ++++++++++--------- .../ada-rts/gnatcov_rts-traces-output.ads | 10 +- tools/gnatcov/ada-rts/gnatcov_rts-traces.ads | 23 +++-- tools/gnatcov/ada-rts/gnatcov_rts-types.ads | 50 ++++++++++ tools/gnatcov/ada-rts/gnatcov_rts.ads | 9 +- tools/gnatcov/ada-rts/gnatcov_rts_aamp.gpr | 20 ++-- 14 files changed, 286 insertions(+), 160 deletions(-) create mode 100644 tools/gnatcov/ada-rts/gcvrt.ads create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-strings.ads create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-types.ads diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index e6b82c674..98e2128b7 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -256,8 +256,12 @@ install-examples: install-gnatcov_rts: $(RM) -r $(PREFIX)/share/$(DIRNAME)/gnatcov_rts $(MKDIR) $(PREFIX)/share/$(DIRNAME)/gnatcov_rts + $(RM) -r $(PREFIX)/share/$(DIRNAME)/gnatcov_ada_rts + $(MKDIR) $(PREFIX)/share/$(DIRNAME)/gnatcov_ada_rts $(CP) -r rts/*.gpr rts/*.ads rts/*.adb rts/*.c rts/*.h \ $(PREFIX)/share/$(DIRNAME)/gnatcov_rts + $(CP) -r ada-rts/*.gpr ada-rts/*.ads ada-rts/*.adb \ + $(PREFIX)/share/$(DIRNAME)/gnatcov_ada_rts # Create library/object directories for gnatcov_rts in the installed tree. # This is necessary for out-of-tree builds of gnatcov_rts to work, as # gnatcov_rts may be read-only after final installation, and gprbuild @@ -268,6 +272,7 @@ install-gnatcov_rts: mkdir $(PREFIX)/share/$(DIRNAME)/gnatcov_rts/$$d-$$lt; \ done; \ done + $(MKDIR) $(PREFIX)/share/$(DIRNAME)/gnatcov_ada_rts/obj-gnatcov_rts install-lib: $(MKDIR) $(PREFIX)/lib/gnatcoverage diff --git a/tools/gnatcov/ada-rts/gcvrt.ads b/tools/gnatcov/ada-rts/gcvrt.ads new file mode 100644 index 000000000..7233b13a7 --- /dev/null +++ b/tools/gnatcov/ada-rts/gcvrt.ads @@ -0,0 +1,30 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2023-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. -- +------------------------------------------------------------------------------ + +-- Namespace for units generated for instrumentation purposes +-- +-- This unit needs to be compilable with Ada 95 compilers + +package GCVRT is + + pragma Pure; + pragma Warnings (Off); + pragma No_Elaboration_Code_All; + pragma Warnings (On); + +end GCVRT; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads index e994c12b8..2c2b4eb2d 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads @@ -28,9 +28,35 @@ package GNATcov_RTS.Buffers.Lists is - type Unit_Coverage_Buffers_Access is access all Unit_Coverage_Buffers; + pragma Preelaborate; - type Unit_Coverage_Buffers_Array is - array (Positive range <>) of Unit_Coverage_Buffers_Access; + type Coverage_Buffers_Access is + access constant GNATcov_RTS_Coverage_Buffers; + pragma Convention (C, Coverage_Buffers_Access); + + type Coverage_Buffers_Group is + array (Positive range <>) of Coverage_Buffers_Access; + pragma Convention (C, Coverage_Buffers_Group); + + type GNATcov_RTS_Coverage_Buffers_Group is record + Length : aliased unsigned; + Buffers : System.Address; + -- Address of a Coverage_Buffers_Group array of Length items + end record; + pragma Convention (C, GNATcov_RTS_Coverage_Buffers_Group); + + type Coverage_Buffers_Group_Access is + access constant GNATcov_RTS_Coverage_Buffers_Group; + + type Coverage_Buffers_Group_Array is + array (Positive range <>) of Coverage_Buffers_Group_Access; + pragma Convention (C, Coverage_Buffers_Group_Array); + + type GNATcov_RTS_Coverage_Buffers_Group_Array is record + Length : aliased unsigned; + Groups : System.Address; + -- Address of a Coverage_Buffers_Group_Array array of Length items + end record; + pragma Convention (C, GNATcov_RTS_Coverage_Buffers_Group_Array); end GNATcov_RTS.Buffers.Lists; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb index 116a6d833..2d47e87ec 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb @@ -26,41 +26,12 @@ package body GNATcov_RTS.Buffers is - ----------------- - -- To_String -- - ---------------- - - function To_String (Arr : Uint8_Array) return String is - Result : String (Arr'Range); - begin - for I in Arr'Range loop - Result (I) := Character'Val (Arr (I)); - end loop; - return Result; - end To_String; - - ------------------- - -- From_String -- - ------------------- - - function From_String (Str : String) return Uint8_Array - is - Result : Uint8_Array (Str'Range); - begin - for I in Str'Range loop - Result (I) := Character'Pos (Str (I)); - end loop; - return Result; - end From_String; - - subtype Unbounded_Coverage_Buffer_Type is Coverage_Buffer_Type (Bit_Id); - ------------- -- Witness -- ------------- procedure Witness (Buffer_Address : System.Address; Bit : Bit_Id) is - Buffer : Unbounded_Coverage_Buffer_Type; + Buffer : Coverage_Buffer_Type (0 .. Bit); for Buffer'Address use Buffer_Address; pragma Import (Ada, Buffer); begin diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads index 01440666e..e2938b027 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads @@ -30,43 +30,26 @@ with Interfaces; with System; +with GNATcov_RTS.Types; use GNATcov_RTS.Types; +with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; + package GNATcov_RTS.Buffers is pragma Pure; + pragma Warnings (Off); + pragma No_Elaboration_Code; + pragma Warnings (On); - -- All data takes the form of big arrays of booleans: coverage buffers. How - -- to interpret these depend on the type of coverage obligation. - -- - -- For statement coverage, each statement is assigned such a boolean, which - -- indicates whether it was executed. - -- - -- For decision coverage, each decision is assigned two booleans: one which - -- indicates whether the decision reached the False outcome and another for - -- the True outcome. - - type Any_Unit_Part is - (Not_Applicable_Part, Unit_Body, Unit_Spec, Unit_Separate); - -- Not_Applicable_Part is a default value used for compilation units in - -- languages that are not unit-based. - - type Any_Language_Kind is (Unit_Based_Language, File_Based_Language); + -- Any_Bit_Id is declared volatile here, as in order to instrument declare + -- expressions we need to declare a constant MC_DC_State (a subtype of + -- Any_Bit_Id) object, but prevent the compiler from optimizing out the + -- variable. - --------------------------------------------- - -- Mapping of coverage buffer bits to SCOs -- - --------------------------------------------- + type Any_Bit_Id is new int; + pragma Volatile (Any_Bit_Id); - --------------------------- - -- Source trace bit maps -- - --------------------------- - - -- As instrumentation is inserted, bit positions in coverage buffers are - -- allocated, and these allocations are associated to low-level SCO Ids. - -- Once low-level SCOs are converted to high-level SCOs, new mappings - -- are generated to allow mapping bit positions to high level SCOs when - -- processing buffers from a target run. - - type Any_Bit_Id is new Integer; No_Bit_Id : constant Any_Bit_Id := -1; + subtype Bit_Id is Any_Bit_Id range 0 .. Any_Bit_Id'Last; -- Unique identifier for a boolean in a coverage buffer @@ -74,29 +57,33 @@ package GNATcov_RTS.Buffers is -- Even though it is tempting to pack this array to save memory, we must -- avoid bit packing to allow concurrent writes to coverage buffers. - type Uint8_Array is array (Positive range <>) of Interfaces.Unsigned_8; + Fingerprint_Size : constant := 20; - function To_String (Arr : Uint8_Array) return String; + type GNATcov_RTS_Bool is new unsigned; - function From_String (Str : String) return Uint8_Array; + type Any_Unit_Part is + (Not_Applicable_Part, Unit_Body, Unit_Spec, Unit_Separate); + pragma Convention (C, Any_Unit_Part); + + type Any_Language_Kind is (Unit_Based_Language, File_Based_Language); + pragma Convention (C, Any_Language_Kind); - type SCOs_Hash is new Uint8_Array (1 .. 20); - -- Hash type to perform consistency checks over Source Coverage - -- Obligations. 20-byte to hold a SHA-1. + type Fingerprint_Type is array (1 .. 20) of Unsigned_8; + for Fingerprint_Type'Component_Size use 8; + for Fingerprint_Type'Size use 20 * 8; - type Unit_Coverage_Buffers is record - Fingerprint : SCOs_Hash; + type GNATcov_RTS_Coverage_Buffers is record + Fingerprint : Fingerprint_Type; -- Hash of SCO info for this unit, as gnatcov computes it (see -- SC_Obligations). Used a fast way to check that coverage obligations -- and coverage data are consistent. Specific hash values are computed -- during instrumentation. - Language_Kind : Any_Language_Kind; + Language : Any_Language_Kind; -- Language kind for this unit - Unit_Part : Any_Unit_Part; - Unit_Name_Length : Positive; - Unit_Name : System.Address; + Unit_Part : Any_Unit_Part; + Unit_Name : GNATcov_RTS_String; -- Unit kind and name for the instrumented unit. The Unit_Name field -- accounts both for unit-based languages (such as Ada) and file-based -- languages such as C. @@ -111,10 +98,11 @@ package GNATcov_RTS.Buffers is -- For file-based languages, Unit_Name is the simple filename, e.g. -- "foo.c". - Project_Name_Length : Natural; - Project_Name : System.Address; - -- Project name for this compilation unit. This is only initialized for - -- file-based languages (otherwise, it is an empty string). + Bit_Maps_Fingerprint : Fingerprint_Type; + -- Hash of buffer bit mappings for this unit, as gnatcov computes it + -- (see SC_Obligations). Used as a fast way to check that gnatcov will + -- be able to interpret buffer bits from a source traces using buffer + -- bit mappings from SID files. Statement, Decision, MCDC : System.Address; -- Addresses of coverage buffers for statement obligations, decision diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-strings.ads b/tools/gnatcov/ada-rts/gnatcov_rts-strings.ads new file mode 100644 index 000000000..3a7c102be --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-strings.ads @@ -0,0 +1,44 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2021-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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- Ada bindings for gnatcov_rts_c-strings.h +-- +-- This unit needs to be compilable with Ada 95 compilers + +with GNATcov_RTS.Types; use GNATcov_RTS.Types; + +package GNATcov_RTS.Strings is + + pragma Pure; + pragma Warnings (Off); + pragma No_Elaboration_Code_All; + pragma Warnings (On); + + type GNATcov_RTS_String is record + Str : System.Address; + Length : size_t; + end record; + pragma Convention (C_Pass_By_Copy, GNATcov_RTS_String); + +end GNATcov_RTS.Strings; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb index 3f3820423..b409cf657 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb @@ -154,10 +154,10 @@ package body GNATcov_RTS.Traces.Output.Base64 is ---------------------- procedure Write_Trace_File - (Buffers : Unit_Coverage_Buffers_Array; - Program_Name : String; - Exec_Date : Serialized_Timestamp; - User_Data : String := "") + (Buffers_Groups : Coverage_Buffers_Group_Array; + Program_Name : String; + Exec_Date : Unsigned_64; + User_Data : String := "") is procedure Helper is new Generic_Write_Trace_File (Base64_Buffer); Buffer : Base64_Buffer := @@ -167,7 +167,7 @@ package body GNATcov_RTS.Traces.Output.Base64 is begin TIO.New_Line; TIO.Put_Line ("== GNATcoverage source trace file =="); - Helper (Buffer, Buffers, Program_Name, Exec_Date, User_Data); + Helper (Buffer, Buffers_Groups, Program_Name, Exec_Date, User_Data); Flush (Buffer); if Buffer.Columns /= 0 then TIO.New_Line; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads index 771d01472..a3d3dbda9 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads @@ -27,10 +27,10 @@ package GNATcov_RTS.Traces.Output.Base64 is procedure Write_Trace_File - (Buffers : Unit_Coverage_Buffers_Array; - Program_Name : String; - Exec_Date : Serialized_Timestamp; - User_Data : String := ""); + (Buffers_Groups : Coverage_Buffers_Group_Array; + Program_Name : String; + Exec_Date : Unsigned_64; + User_Data : String := ""); -- Write a Base64-encoded trace file to the standard output -- (Ada.Text_IO.Standard_Output). diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb index 2ce72f086..d8b3a0d3a 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb @@ -37,11 +37,11 @@ package body GNATcov_RTS.Traces.Output is ------------------------------ procedure Generic_Write_Trace_File - (Output : in out Output_Stream; - Buffers : Unit_Coverage_Buffers_Array; - Program_Name : String; - Exec_Date : Serialized_Timestamp; - User_Data : String := "") + (Output : in out Output_Stream; + Buffers_Groups : Coverage_Buffers_Group_Array; + Program_Name : String; + Exec_Date : Unsigned_64; + User_Data : String := "") is Alignment : constant Unsigned_8 := 8; @@ -71,7 +71,7 @@ package body GNATcov_RTS.Traces.Output is -- Write a trace info entry to Output procedure Write_Entry - (Output : in out Output_Stream; Buffers : Unit_Coverage_Buffers); + (Output : in out Output_Stream; Buffers : GNATcov_RTS_Coverage_Buffers); -- Write a whole trace entry (header, unit name and buffers) for Buffers -- to Output. @@ -104,6 +104,11 @@ package body GNATcov_RTS.Traces.Output is procedure Write_U8 is new Write_Unsigned (T => Unsigned_8); procedure Write_U16 is new Write_Unsigned (T => Unsigned_16); procedure Write_U32 is new Write_Unsigned (T => Unsigned_32); + procedure Write_U64 is new Write_Unsigned (T => Unsigned_64); + + Padding_Constant : constant Uint8_Array (1 .. 16) := (others => 0); + -- Contant to avoid a local array declaration every time we need to do + -- padding, as it uses the secondary stack on the aamp platform. ------------------- -- Write_Padding -- @@ -117,7 +122,9 @@ package body GNATcov_RTS.Traces.Output is begin if Pad_Count /= Alignment then declare - Bytes : constant Uint8_Array (1 .. Pad_Count) := (others => 0); + Bytes : Uint8_Array (1 .. Pad_Count); + for Bytes'Address use Padding_Constant'Address; + pragma Import (Ada, Bytes); begin Write_Bytes (Output, Bytes); end; @@ -128,9 +135,14 @@ package body GNATcov_RTS.Traces.Output is -- Write_Header -- ------------------ - procedure Write_Header (Output : in out Output_Stream) is + procedure Write_Header (Output : in out Output_Stream) + is + Trace_File_Magic_Bytes : constant Uint8_Array + (1 .. Trace_File_Magic'Length); + for Trace_File_Magic_Bytes'Address use Trace_File_Magic'Address; + pragma Import (Ada, Trace_File_Magic_Bytes); begin - Write_Bytes (Output, From_String (Trace_File_Magic)); + Write_Bytes (Output, Trace_File_Magic_Bytes); Write_U32 (Output, Unsigned_32 (Current_Version)); Write_U8 (Output, Alignment); @@ -150,10 +162,13 @@ package body GNATcov_RTS.Traces.Output is Kind : Supported_Info_Kind; Data : String) is + Data_Bytes : constant Uint8_Array (1 .. Data'Length); + for Data_Bytes'Address use Data'Address; + pragma Import (Ada, Data_Bytes); begin Write_U32 (Output, Unsigned_32 (Kind)); Write_U32 (Output, Unsigned_32 (Data'Length)); - Write_Bytes (Output, From_String (Data)); + Write_Bytes (Output, Data_Bytes); Write_Padding (Output, Data'Length); end Write_Info; @@ -162,54 +177,40 @@ package body GNATcov_RTS.Traces.Output is ----------------- procedure Write_Entry - (Output : in out Output_Stream; Buffers : Unit_Coverage_Buffers) + (Output : in out Output_Stream; Buffers : GNATcov_RTS_Coverage_Buffers) is - type Unit_Name_String is new String (1 .. Buffers.Unit_Name_Length); - type Unit_Name_String_Acc is access all Unit_Name_String; - - type Project_Name_String is - new String (1 .. Buffers.Project_Name_Length); - type Project_Name_String_Acc is access all Project_Name_String; + Unit_Name_Bytes : Uint8_Array + (1 .. Integer (Buffers.Unit_Name.Length)); + for Unit_Name_Bytes'Address use Buffers.Unit_Name.Str; + pragma Import (Ada, Unit_Name_Bytes); - function To_Unit_Name_String_Acc is - new Ada.Unchecked_Conversion (System.Address, Unit_Name_String_Acc); - - function To_Project_Name_String_Acc is + subtype Bounded_Uint8_Array is Uint8_Array (1 .. 20); + function To_Uint8_Array is new Ada.Unchecked_Conversion - (System.Address, Project_Name_String_Acc); - - Unit_Name : constant Unit_Name_String_Acc := - To_Unit_Name_String_Acc (Buffers.Unit_Name); - - Project_Name : constant Project_Name_String_Acc := - To_Project_Name_String_Acc (Buffers.Project_Name); - + (Fingerprint_Type, Bounded_Uint8_Array); begin -- Write trace entry header - Write_U32 (Output, Unsigned_32 (Buffers.Unit_Name_Length)); - Write_U32 (Output, Unsigned_32 (Buffers.Project_Name_Length)); + Write_U32 (Output, Unsigned_32 (Buffers.Unit_Name.Length)); Write_U32 (Output, Unsigned_32 (Buffers.Statement_Last_Bit + 1)); Write_U32 (Output, Unsigned_32 (Buffers.Decision_Last_Bit + 1)); Write_U32 (Output, Unsigned_32 (Buffers.MCDC_Last_Bit + 1)); Write_U8 (Output, - Unsigned_8 (Any_Language_Kind_Map (Buffers.Language_Kind))); + Unsigned_8 (Any_Language_Kind_Map (Buffers.Language))); Write_U8 (Output, Unsigned_8 (GNATcov_RTS.Buffers.Any_Unit_Part'Pos (Buffers.Unit_Part))); Write_U8 (Output, Unsigned_8 (LSB_First_Bytes)); - Write_Bytes (Output, Uint8_Array (Buffers.Fingerprint)); + Write_Bytes (Output, To_Uint8_Array (Buffers.Fingerprint)); + Write_Bytes (Output, To_Uint8_Array (Buffers.Bit_Maps_Fingerprint)); Write_Bytes (Output, (1 .. 5 => 0)); - -- Write unit name and project name + -- Write the unit name - Write_Bytes (Output, From_String (String (Unit_Name.all))); - Write_Padding (Output, Unit_Name.all'Length); - - Write_Bytes (Output, From_String (String (Project_Name.all))); - Write_Padding (Output, Project_Name.all'Length); + Write_Bytes (Output, Unit_Name_Bytes); + Write_Padding (Output, Integer (Buffers.Unit_Name.Length)); -- Write coverage buffers @@ -302,11 +303,20 @@ package body GNATcov_RTS.Traces.Output is begin Write_Header (Output); Write_Info (Output, Info_Program_Name, Program_Name); - Write_Info (Output, Info_Exec_Date, Exec_Date); + Write_Info (Output, Info_Exec_Date, String'(1 .. 8 => 'A')); Write_Info (Output, Info_User_Data, User_Data); Write_Info (Output, Info_End, ""); - for I in Buffers'Range loop - Write_Entry (Output, Buffers (I).all); + for I in Buffers_Groups'Range loop + declare + Buffers : Coverage_Buffers_Group + (1 .. Integer (Buffers_Groups (I).Length)); + for Buffers'Address use Buffers_Groups (I).Buffers; + pragma Import (C, Buffers); + begin + for J in Buffers'Range loop + Write_Entry (Output, Buffers (J).all); + end loop; + end; end loop; end Generic_Write_Trace_File; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads index 1c9e7f626..fcbe14c73 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads @@ -43,11 +43,11 @@ package GNATcov_RTS.Traces.Output is -- Write Bytes to the given Stream procedure Generic_Write_Trace_File - (Output : in out Output_Stream; - Buffers : Unit_Coverage_Buffers_Array; - Program_Name : String; - Exec_Date : Serialized_Timestamp; - User_Data : String := ""); + (Output : in out Output_Stream; + Buffers_Groups : Coverage_Buffers_Group_Array; + Program_Name : String; + Exec_Date : Unsigned_64; + User_Data : String := ""); -- Write a trace file to Output to contain the coverage data in Buffers. -- -- Program_Name, Exec_Date, and User_Data are used to fill the diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads index bc4c6f262..56bab68e7 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads @@ -32,6 +32,9 @@ with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; package GNATcov_RTS.Traces is + type Uint8_Array is array (Positive range <>) of Interfaces.Unsigned_8; + pragma Pack (Uint8_Array); + -- Execution of an instrumented program sets bits in its coverage buffers. -- These bits convey information that GNATcov will later on use to -- discharge coverage obligations. @@ -48,11 +51,13 @@ package GNATcov_RTS.Traces is -- trace entries start and end on byte/half word/word/long word boundaries. type Trace_File_Format_Version is new Unsigned_32; - Current_Version : Trace_File_Format_Version := 1; + Current_Version : Trace_File_Format_Version := 3; -- Expected value of the Trace_File_Header.Format_Version field. -- -- 0 -- initial version -- 1 -- extend trace entry model to account for C files + -- 2 -- introduce fingerprints for bit maps + -- 3 -- remove the project name from trace entries type Any_Alignment is new Unsigned_8; subtype Supported_Alignment is Any_Alignment; @@ -70,9 +75,6 @@ package GNATcov_RTS.Traces is function Native_Endianity return Supported_Endianity; -- Return the native endianity - type Hash_Type is new Unsigned_32; - -- Hash type to perform consistency checks - type Any_Unit_Part is new Unsigned_8; Not_Applicable_Part : constant Any_Unit_Part := Buffers.Any_Unit_Part'Pos (Buffers.Not_Applicable_Part); @@ -207,11 +209,6 @@ package GNATcov_RTS.Traces is -- Length of the unit name / filename for the unit this trace entry -- describes. - Project_Name_Length : Unsigned_32; - -- For file-based languages, length of the project name this file - -- belongs to. For unit-based languages, the unit name is unique so this - -- piece of information is not needed (thus will be 0). - Statement_Bit_Count : Any_Bit_Count; Decision_Bit_Count : Any_Bit_Count; MCDC_Bit_Count : Any_Bit_Count; @@ -227,11 +224,17 @@ package GNATcov_RTS.Traces is Bit_Buffer_Encoding : Any_Bit_Buffer_Encoding; -- Encoding used to represent statement and decision coverage buffers - Fingerprint : Buffers.SCOs_Hash; + Fingerprint : Buffers.Fingerprint_Type; -- Hash of SCO info for this unit. Useds a fast way to check that -- coverage obligations and coverage data are consistent. Specific hash -- values are computed during instrumentation. + Bit_Maps_Fingerprint : Buffers.Fingerprint_Type; + -- Hash of buffer bit mappings for this unit, as gnatcov computes it + -- (see SC_Obligations). Used as a fast way to check that gnatcov will + -- be able to interpret buffer bits from a source traces using buffer + -- bit mappings from SID files. + Padding : Uint8_Array (1 .. 5); -- Padding used only to make the size of this trace entry header a -- multiple of 8 bytes. Must be zero. diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-types.ads b/tools/gnatcov/ada-rts/gnatcov_rts-types.ads new file mode 100644 index 000000000..0ace624a6 --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-types.ads @@ -0,0 +1,50 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 2021-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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +-- Basic types to use in source trace buffers. We try to avoid using types +-- from Interfaces and Interfaces.C, and in general to minimize the set of +-- dependencies of GNATcov_RTS on the Ada runtime, so that we can compute code +-- coverage for these runtime units. +-- +-- This unit needs to be compilable with Ada 95 compilers + +with System; + +package GNATcov_RTS.Types is + + pragma Pure; + pragma Warnings (Off); + pragma No_Elaboration_Code_All; + pragma Warnings (On); + + type Unsigned_8 is mod 2 ** 8; + type Unsigned_64 is mod 2 ** 64; + + -- We assume here that Integer (Ada) is a correct mapping for int (C) + + type int is new Integer; + type unsigned is mod 2 ** int'Size; + type size_t is mod System.Memory_Size; + +end GNATcov_RTS.Types; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts.ads b/tools/gnatcov/ada-rts/gnatcov_rts.ads index 69aa21402..0265d9b4d 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts.ads @@ -32,11 +32,14 @@ with System; package GNATcov_RTS is pragma Pure; + pragma Warnings (Off); + pragma No_Elaboration_Code_All; + pragma Warnings (On); package Std renames Standard; package Sys renames System; - Version : constant := 4; + Version : constant := 7; -- For compatibility with the GNATcoverage in use, GNATcov_RTS is -- versioned. -- @@ -44,5 +47,9 @@ package GNATcov_RTS is -- 2 -- extend trace entry model to account for C files -- 3 -- add a renaming of the Standard and System packages in GNATcov_RTS -- 4 -- add C witness functions / buffer types + -- 5 -- add a non-volatile version of the Witness_Dummy_Type and + -- the associated Witness function. + -- 6 -- buffer clear mechanism and trace filename indices + -- 7 -- enable inlining of witness subprograms end GNATcov_RTS; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts_aamp.gpr b/tools/gnatcov/ada-rts/gnatcov_rts_aamp.gpr index 8c2c4b8a7..0bef57a76 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts_aamp.gpr +++ b/tools/gnatcov/ada-rts/gnatcov_rts_aamp.gpr @@ -1,19 +1,11 @@ --- Project specific to the AAMP target, which does not support libraries, and --- does not have a C compiler. +-- Ada Instrumentation runtime for gnatcov, for the AAMP target. +-- +-- This project is meant to be built and installed before instrumenting +-- projects with "gnatcov instrument", and then to be used when building +-- instrumented programs thanks to gprbuild's --implicit-with option. project GNATcov_RTS_AAMP is - for Source_Files use - ("gnatcov_rts.ads", - "gnatcov_rts-buffers.ads", - "gnatcov_rts-buffers.adb", - "gnatcov_rts-buffers-lists.ads", - "gnatcov_rts-traces.ads", - "gnatcov_rts-traces.adb", - "gnatcov_rts-traces-output.ads", - "gnatcov_rts-traces-output.adb", - "gnatcov_rts-traces-output-text_io.ads", - "gnatcov_rts-traces-output-base64.ads", - "gnatcov_rts-traces-output-base64.adb"); + for Source_Dirs use ("."); for Object_Dir use "obj-gnatcov_rts"; for Languages use ("Ada"); From e7a7cc899419c4e9472b68394d435a0bd1b45e8c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 18 Mar 2024 12:45:05 +0100 Subject: [PATCH 0779/1483] Drop dependency to Interfaces.C --- tools/gnatcov/instrument-ada_unit.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 6c8472080..a2d102c27 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8715,7 +8715,6 @@ package body Instrument.Ada_Unit is begin Create_File (Prj, File, To_Filename (Prj, Ada_Language, Buffer_Unit)); Put_Warnings_And_Style_Checks_Pragmas (File); - File.Put_Line ("with Interfaces.C; use Interfaces.C;"); File.Put_Line ("with System;"); File.Put_Line ("with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers;"); File.Put_Line @@ -9201,12 +9200,13 @@ package body Instrument.Ada_Unit is Put_With (Output_Unit); Put_With (Sys_Lists); - File.Put_Line ("with Interfaces.C;"); case Dump_Trigger is when Ravenscar_Task_Termination => File.Put_Line ("with Ada.Task_Identification;"); File.Put_Line ("with Ada.Task_Termination;"); + when At_Exit => + File.Put_Line ("with Interfaces.C;"); when others => null; end case; From d6bd121f64d26829d4d135d61bfaa1efe2ef81bb Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 19 Mar 2024 10:35:32 +0100 Subject: [PATCH 0780/1483] Workaround GNATCOLL.Projects bug GNATCOLL.Projects used to assume that the gnatls executable for the aamp platform was `aamp-gnatls` whereas it is `gnaampls`. This was fixed under eng/toolchain/gnatcoll-core!84 but apply a workaround in gnatcov as well to remove at the next stable bump. --- tools/gnatcov/instrument-ada_unit.adb | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index a2d102c27..0cfa9f252 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -7793,6 +7793,16 @@ package body Instrument.Ada_Unit is (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean is begin + -- GNATCOLL.Projects does not adequately load the runtime for the aamp + -- target, which means that we end up assuming that finalization is not + -- restricted. It actually is restricted using the aamp5-small runtime. + -- The GNATCOLL.Projects bug was fixed, but also workaround the issue + -- to make it work for non-edge gnatcov, and revert this at next bump. + -- Ref: eng/shared/anod#300. + + if Project.Target = "aamp" then + return True; + end if; return not Has_Unit (Context, "Ada.Finalization", Unit_Specification) or else Has_Matching_Pragma_For_Unit (Context, Unit, Pragma_Restricts_Finalization_Matchers); @@ -7806,6 +7816,11 @@ package body Instrument.Ada_Unit is (Context : Analysis_Context; Unit : LAL.Compilation_Unit) return Boolean is begin + -- See above. Revert this at the next bump as well (eng/shared/anod#300) + + if Project.Target = "aamp" then + return True; + end if; return not Has_Unit (Context, "Ada.Task.Termination", Unit_Specification) or else not Has_Unit (Context, "Ada.Task.Identification", Unit_Specification) From d47ab3e21bc2bb4caa8e7ec7f2b979be453b85c2 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 19 Mar 2024 10:37:31 +0100 Subject: [PATCH 0781/1483] Project initialization: fix gnatls executable name --- tools/gnatcov/project.adb | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index d2d26df6f..a14b4cca2 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -707,8 +707,10 @@ package body Project is Gnatls_Version : GNAT.Strings.String_Access; begin Env.Set_Path_From_Gnatls - (Gnatls => (if Target = null then "" else Target.all & '-') - & "gnatls", + (Gnatls => + (if Target = null then "gnatls" + elsif Target.all = "aamp" then "gnaampls" + else Target.all & "-gnatls"), GNAT_Version => Gnatls_Version, Errors => null); if Gnatls_Version /= null then From f38661d464447a06870e5c4ce1aac443d846d4d7 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 19 Mar 2024 10:41:27 +0100 Subject: [PATCH 0782/1483] Setup: do not try to load the setup config for the aamp target The aamp target does not support library project, so users are not expected to use `gnatcov setup` for this target. --- tools/gnatcov/setup_rts.adb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 28cd64c48..a1227d252 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -1025,14 +1025,14 @@ package body Setup_RTS is -- Name of the runtime project file after it has been loaded -- (i.e. resolved file name). begin - -- CCG is a very special target, for which it is not possible to create - -- libraries through project files: CCG users cannot run "gnatcov - -- setup": there is no setup configuration to load in this case, so - -- return a dummy one. + -- CCG and AAMP are very special targets, for which it is not possible + -- to create libraries through project files: CCG users cannot run + -- "gnatcov setup": there is no setup configuration to load in this + -- case, so return a dummy one. - if To_Lower (Target) = "c" + if To_Lower (Target) in "c" | "aamp" or else (Project.Is_Project_Loaded - and then To_Lower (Project.Target) = "c") + and then To_Lower (Project.Target) in "c" | "aamp") then return Default_Setup_Config; end if; From 1ee3c7484f80cadd3fd2a747d6e57690f05920f6 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 19 Mar 2024 15:05:41 +0100 Subject: [PATCH 0783/1483] instr-cov/gpr-complex: minor refactoring --- testsuite/tests/instr-cov/gpr-complex/test.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/testsuite/tests/instr-cov/gpr-complex/test.py b/testsuite/tests/instr-cov/gpr-complex/test.py index ce6478606..1b4de7717 100644 --- a/testsuite/tests/instr-cov/gpr-complex/test.py +++ b/testsuite/tests/instr-cov/gpr-complex/test.py @@ -12,6 +12,7 @@ from SCOV.instr import xcov_instrument from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest +from SUITE.control import env from SUITE.cutils import no_ext, Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprbuild, gprinstall @@ -40,13 +41,9 @@ # Add the newly installed library to gprbuild's project lookup path. Use the # ADA_PROJECT_PATH environment variable to be compatible with the 5.04 # toolchain. -gpr_install_dir = os.path.join(install_dir, "share", "gpr") -old_path = os.environ.get("ADA_PROJECT_PATH", "") -if old_path: - new_path = "{}{}{}".format(gpr_install_dir, os.path.pathsep, old_path) -else: - new_path = gpr_install_dir -os.environ["ADA_PROJECT_PATH"] = new_path +env.add_search_path( + "ADA_PROJECT_PATH", os.path.join(install_dir, "share", "gpr") +) def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): From 8eb92ef41e0aa2cf66ce33b53824264ccc86c05e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 28 Mar 2024 14:14:15 +0100 Subject: [PATCH 0784/1483] instrument-ada_unit.adb: Do not use project facilities for aamp workaround A recent aamp-related gnatcoll.projects bug lead to the inclusion of a query to the project target in instrument-ada_unit.adb, which may fail when parallelization is enabled. As we can get this information from the command line, use that instead to be more robust. --- tools/gnatcov/instrument-ada_unit.adb | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 0cfa9f252..045ea71ad 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -7800,7 +7800,9 @@ package body Instrument.Ada_Unit is -- to make it work for non-edge gnatcov, and revert this at next bump. -- Ref: eng/shared/anod#300. - if Project.Target = "aamp" then + if Switches.Target_Family not in null + and then Switches.Target_Family.all = "aamp" + then return True; end if; return not Has_Unit (Context, "Ada.Finalization", Unit_Specification) @@ -7818,7 +7820,9 @@ package body Instrument.Ada_Unit is begin -- See above. Revert this at the next bump as well (eng/shared/anod#300) - if Project.Target = "aamp" then + if Switches.Target_Family not in null + and then Switches.Target_Family.all = "aamp" + then return True; end if; return not Has_Unit (Context, "Ada.Task.Termination", Unit_Specification) From 23e2639a25af80f25d34d29e296dd03f5e3e8906 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 28 Mar 2024 14:52:48 +0100 Subject: [PATCH 0785/1483] Manual dump trigger: skip processing of headers Do not process header files when processing the files to insert calls to dump buffers when using the manual dump triggers. Also fix the external linkage for C++ files. --- .../pragma_once_in_spec/src/main.cpp | 19 +++++++ .../pragma_once_in_spec/src/stuff.hpp | 6 +++ .../manual-dump/pragma_once_in_spec/test.py | 53 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 9 +++- tools/gnatcov/instrument-projects.adb | 4 +- 5 files changed, 88 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/main.cpp create mode 100644 testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/stuff.hpp create mode 100644 testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.py diff --git a/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/main.cpp b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/main.cpp new file mode 100644 index 000000000..1cc378426 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/main.cpp @@ -0,0 +1,19 @@ +#include "stuff.hpp" + +#include + +int +main (int argc, char **argv) +{ + + (void) argc; + (void) argv; + + Stuff a = { 5 }; + + std::cout << a.data << "\n"; + + /* GNATCOV_DUMP_BUFFERS */ + + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/stuff.hpp b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/stuff.hpp new file mode 100644 index 000000000..f599519ae --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/stuff.hpp @@ -0,0 +1,6 @@ +#pragma once + +struct Stuff +{ + int data; +}; diff --git a/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.py b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.py new file mode 100644 index 000000000..62568ea3e --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.py @@ -0,0 +1,53 @@ +""" +Regression test: check that gnatcov does not process headers in the context of +the manual dump trigger preprocessing. To do that, put a #pragma once in a +header, and instrument with -Werror. + +Also checks that it puts the right external linkage prefix for a C++ file (e.g. +extern "C"), as otherwise the dependency is not resolved at link time as +gnatcov declares the dump/reset procedures as C symbols. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +gpr = gprfor( + mains=["main.cpp"], + prjid="main", + srcdirs="../src", + compiler_extra='for Default_Switches("C++") use ("-Werror");', + extra=""" + package Naming is + for Spec_Suffix ("C++") use ".hpp"; + for Body_Suffix ("C++") use ".cpp"; + end Naming; + """, +) +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) +build_run_and_coverage( + gprsw=GPRswitches(gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + dump_trigger="manual", + manual_prj_name="main", + tolerate_instrument_messages=instr_warning, +) + +# Check that we got the expected coverage report + +check_xcov_reports( + "obj", + { + "main.cpp.xcov": {"+": {9, 10, 12, 14}, "-": {18}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 0362a827c..beba6fb9f 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3879,6 +3879,9 @@ package body Instrument.C is Reset_Procedure : constant String := Reset_Procedure_Symbol (+Prj.Prj_Name); + Extern_Prefix : constant String := + C_Family_Instrumenter_Type'Class (Self).Extern_Prefix; + begin -- Preprocess the source, keeping the comment to look for the manual -- dump indication later. @@ -3956,9 +3959,11 @@ package body Instrument.C is -- functions. String'Write - (S, "extern void " & Dump_Procedure & "(char *prefix);"); + (S, + Extern_Prefix & "void " & Dump_Procedure + & "(char *prefix);"); String'Write - (S, "extern void " & Reset_Procedure & "(void);"); + (S, Extern_Prefix & "void " & Reset_Procedure & "(void);"); end if; -- If we only have a Dump match, or it is the first of the two diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index dc630ea66..971ee8a77 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -854,7 +854,9 @@ is begin for Source of Project_Sources loop - if To_Language (Source.Language) = Language then + if To_Language (Source.Language) = Language + and then Source.Unit_Part = GNATCOLL.Projects.Unit_Body + then declare use String_Sets; From a2287ed1b608f64ce5983793a71ea54c3ac726b2 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 3 Apr 2024 10:52:09 +0200 Subject: [PATCH 0786/1483] Kill test when there is no C++ compiler --- .../tests/instr-cov/manual-dump/pragma_once_in_spec/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.opt diff --git a/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.opt b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.opt new file mode 100644 index 000000000..195e6c2d4 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.opt @@ -0,0 +1 @@ +!C++ DEAD test requires C++ compiler From fca4680de9b360b16a756465aa973169f9b7be29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 5 Apr 2024 14:08:55 +0200 Subject: [PATCH 0787/1483] instrument-c.adb: update dump function declaration to use const char* The extern declaration that is emited for the function responsible for dumping the coverage buffers used to take a `char *` parameter for the trace prefix, which does not allow using a string literal in C++. Update the declaration to a `const char *` to solve this issue, and add a test with C++ sources to ensure no warning is emitted on the insturmented C++ sources. --- .../manual-dump/cpp_only/src-lib/foo.cpp | 9 +++ .../manual-dump/cpp_only/src-lib/foo.h | 1 + .../manual-dump/cpp_only/src/main.cpp | 27 +++++++ .../instr-cov/manual-dump/cpp_only/test.opt | 1 + .../instr-cov/manual-dump/cpp_only/test.py | 81 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 6 +- 6 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.cpp create mode 100644 testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.h create mode 100644 testsuite/tests/instr-cov/manual-dump/cpp_only/src/main.cpp create mode 100644 testsuite/tests/instr-cov/manual-dump/cpp_only/test.opt create mode 100644 testsuite/tests/instr-cov/manual-dump/cpp_only/test.py diff --git a/testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.cpp b/testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.cpp new file mode 100644 index 000000000..690bc85c0 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.cpp @@ -0,0 +1,9 @@ +int +foo () +{ + int res = 1; + // This is a comment + /* GNATCOV_DUMP_BUFFERS */ + // This is another comment + return res; +} diff --git a/testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.h b/testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.h new file mode 100644 index 000000000..a4536647c --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/cpp_only/src-lib/foo.h @@ -0,0 +1 @@ +int foo (); diff --git a/testsuite/tests/instr-cov/manual-dump/cpp_only/src/main.cpp b/testsuite/tests/instr-cov/manual-dump/cpp_only/src/main.cpp new file mode 100644 index 000000000..151547cf5 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/cpp_only/src/main.cpp @@ -0,0 +1,27 @@ +#include "foo.h" + +void +increment (int *x) +{ + (*x)++; +} + +int +main () +{ + int x = 1; + // The only call that should not count as a violation when never executed + // is that of the dump buffers procedure. + if (1 == 2) + { + /* GNATCOV_DUMP_BUFFERS */ + return 0; + } + increment (&x); + + x += foo (); + + /* GNATCOV_DUMP_BUFFERS */ + + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/cpp_only/test.opt b/testsuite/tests/instr-cov/manual-dump/cpp_only/test.opt new file mode 100644 index 000000000..5a8819395 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/cpp_only/test.opt @@ -0,0 +1 @@ +!C++ DEAD test specific to C++ handling diff --git a/testsuite/tests/instr-cov/manual-dump/cpp_only/test.py b/testsuite/tests/instr-cov/manual-dump/cpp_only/test.py new file mode 100644 index 000000000..556ac9297 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/cpp_only/test.py @@ -0,0 +1,81 @@ +""" +Test that when using manual dump trigger in C++ with a specific comment +indicating where to dump the coverage buffers, gnatcov is able to replace it +with a call to the dump buffers procedure and output correct traces. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +# Create the GPR file for the root project +src_gpr = gprfor( + mains=["main.cpp"], + prjid="main", + srcdirs="../src", + objdir="obj", + langs=["C++"], + deps=["lib"], +) + +# Create the GPR files for the library +lib_gpr = gprfor( + mains=[], + prjid="lib", + srcdirs="../src-lib", + langs=["C++"], + extra=""" + for Library_Name use "lib"; + for Library_Dir use "lib"; + """, +) + +gprsw = GPRswitches(root_project=src_gpr) + +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) + +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov"], + dump_trigger="manual", + manual_prj_name="main", + tolerate_instrument_messages=instr_warning, +) + +# Ensure we get no compilation warnings, this used to be the case without the +# proper dump function declaration. +thistest.fail_if_not_equal( + what="gprbuild output not empty", + expected="", + actual=contents_of("gprbuild.out").strip(), +) + +# Check that that the dump call indication was correctly replaced in the sub +# project + +lib_file = "obj/lib-gnatcov-instr/foo.cpp" +thistest.fail_if_no_match( + "missing Dump_Buffers call", + r"(\n|.)*gnatcov_rts_manual_dump_buffers_lib\(.*\);(\n|.)*", + contents_of(lib_file), +) + +# Check that we got the expected coverage report + +check_xcov_reports( + "obj", + { + "main.cpp.xcov": {"+": {6, 12, 15, 20, 22}, "-": {18, 26}}, + "foo.cpp.xcov": {"+": {4, 8}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index beba6fb9f..7f217d1d9 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3957,11 +3957,15 @@ package body Instrument.C is -- Put an external decl for the buffers dump and reset -- functions. + -- + -- The external decl for the dump procedure takes a const + -- char * to avoid any warnings when using a string literal + -- as the trace prefix. String'Write (S, Extern_Prefix & "void " & Dump_Procedure - & "(char *prefix);"); + & "(const char *prefix);"); String'Write (S, Extern_Prefix & "void " & Reset_Procedure & "(void);"); end if; From 6fb0f6d8f6db269c3abe51a6039e7025254cab7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 5 Apr 2024 14:14:12 +0200 Subject: [PATCH 0788/1483] instrument-c.adb: Disambiguate helper unit object filenames for C and C++ The helper units for manual dump trigger used to have the same simple name between C++ and C, resulting in a object filename collision if both are generated for a given project. This change differentiates the simple names of these units to avoid the issue. --- .../{mixed => mixed_ada_c}/main_ada.adb | 0 .../{mixed => mixed_ada_c}/main_c.c | 0 .../{mixed => mixed_ada_c}/test.opt | 0 .../{mixed => mixed_ada_c}/test.py | 0 .../manual-dump/mixed_all/main_ada.adb | 7 +++ .../instr-cov/manual-dump/mixed_all/main_c.c | 9 +++ .../manual-dump/mixed_all/main_cpp.cpp | 9 +++ .../instr-cov/manual-dump/mixed_all/test.opt | 3 + .../instr-cov/manual-dump/mixed_all/test.py | 61 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 8 ++- 10 files changed, 95 insertions(+), 2 deletions(-) rename testsuite/tests/instr-cov/manual-dump/{mixed => mixed_ada_c}/main_ada.adb (100%) rename testsuite/tests/instr-cov/manual-dump/{mixed => mixed_ada_c}/main_c.c (100%) rename testsuite/tests/instr-cov/manual-dump/{mixed => mixed_ada_c}/test.opt (100%) rename testsuite/tests/instr-cov/manual-dump/{mixed => mixed_ada_c}/test.py (100%) create mode 100644 testsuite/tests/instr-cov/manual-dump/mixed_all/main_ada.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/mixed_all/main_c.c create mode 100644 testsuite/tests/instr-cov/manual-dump/mixed_all/main_cpp.cpp create mode 100644 testsuite/tests/instr-cov/manual-dump/mixed_all/test.opt create mode 100644 testsuite/tests/instr-cov/manual-dump/mixed_all/test.py diff --git a/testsuite/tests/instr-cov/manual-dump/mixed/main_ada.adb b/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/main_ada.adb similarity index 100% rename from testsuite/tests/instr-cov/manual-dump/mixed/main_ada.adb rename to testsuite/tests/instr-cov/manual-dump/mixed_ada_c/main_ada.adb diff --git a/testsuite/tests/instr-cov/manual-dump/mixed/main_c.c b/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/main_c.c similarity index 100% rename from testsuite/tests/instr-cov/manual-dump/mixed/main_c.c rename to testsuite/tests/instr-cov/manual-dump/mixed_ada_c/main_c.c diff --git a/testsuite/tests/instr-cov/manual-dump/mixed/test.opt b/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/test.opt similarity index 100% rename from testsuite/tests/instr-cov/manual-dump/mixed/test.opt rename to testsuite/tests/instr-cov/manual-dump/mixed_ada_c/test.opt diff --git a/testsuite/tests/instr-cov/manual-dump/mixed/test.py b/testsuite/tests/instr-cov/manual-dump/mixed_ada_c/test.py similarity index 100% rename from testsuite/tests/instr-cov/manual-dump/mixed/test.py rename to testsuite/tests/instr-cov/manual-dump/mixed_ada_c/test.py diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_all/main_ada.adb b/testsuite/tests/instr-cov/manual-dump/mixed_all/main_ada.adb new file mode 100644 index 000000000..b2860eb02 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_all/main_ada.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_Ada is +begin + Put_Line ("Hello Ada world!"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_Ada; diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_all/main_c.c b/testsuite/tests/instr-cov/manual-dump/mixed_all/main_c.c new file mode 100644 index 000000000..0323c2bc8 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_all/main_c.c @@ -0,0 +1,9 @@ +#include + +int +main (void) +{ + printf ("Hello C world!\n"); + /* GNATCOV_DUMP_BUFFERS */ + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_all/main_cpp.cpp b/testsuite/tests/instr-cov/manual-dump/mixed_all/main_cpp.cpp new file mode 100644 index 000000000..333e8cdda --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_all/main_cpp.cpp @@ -0,0 +1,9 @@ +#include + +int +main (void) +{ + std::cout << "hello C++ world!" << std::endl; + /* GNATCOV_DUMP_BUFFERS */ + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_all/test.opt b/testsuite/tests/instr-cov/manual-dump/mixed_all/test.opt new file mode 100644 index 000000000..ab2120f34 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_all/test.opt @@ -0,0 +1,3 @@ +RTS_ZFP DEAD test uses stdio +!C++ DEAD test requires C++ compiler +!native XFAIL Build failure with mixed language mains. See #212 diff --git a/testsuite/tests/instr-cov/manual-dump/mixed_all/test.py b/testsuite/tests/instr-cov/manual-dump/mixed_all/test.py new file mode 100644 index 000000000..0967aa292 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/mixed_all/test.py @@ -0,0 +1,61 @@ +""" +Check that using --dump-trigger=manual works correctly in projects where a +manual dump indication is present in an Ada source and in all supported C-like +sources. + +This is a regression test, gnatcov used to emit helper units with colliding +object filenames, resulting in the instrumented sources failing to build. +""" + +import os + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, run_cov_program, exepath_to + +Wdir("tmp_") + +# Name for the main_c and main_cpp executable traces +c_trace_name = "main_c.srctrace" +cpp_trace_name = "main_cpp.srctrace" + +# We can't build_run_and_coverage as the default trace name only depends on the +# project name so all mains would dump a trace with the same name (execution +# last less than a second). Instead, instrument and execute the first main +# through build_and_run, then run the other mains manually. +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid="p", + srcdirs=[".."], + mains=["main_ada.adb", "main_c.c", "main_cpp.cpp"], + langs=["Ada", "C", "C++"], + ) + ), + covlevel="stmt", + mains=["main_ada"], + dump_trigger="manual", + manual_prj_name="p", + extra_coverage_args=["-axcov", c_trace_name, cpp_trace_name], +) + +env = dict(os.environ) +env["GNATCOV_TRACE_FILE"] = c_trace_name +run_cov_program(exepath_to("main_c"), env=env) + +env["GNATCOV_TRACE_FILE"] = cpp_trace_name +run_cov_program(exepath_to("main_cpp"), env=env) + +xcov(cov_args) +check_xcov_reports( + "obj", + { + "main_ada.adb.xcov": {"+": {5}}, + "main_c.c.xcov": {"+": {6}, "-": {8}}, + "main_cpp.cpp.xcov": {"+": {6}, "-": {8}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 7f217d1d9..c3a2692a9 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -4286,13 +4286,17 @@ package body Instrument.C is (Self : C_Family_Instrumenter_Type; Prj : Prj_Desc) return Compilation_Unit is + Lang : Src_Supported_Language renames + C_Family_Instrumenter_Type'Class (Self).Language; Filename : constant String := New_File (Prj, To_Symbol_Name (Sys_Prefix) & "_d_b_" & (+Prj.Prj_Name) - & (+Prj.Body_Suffix - (C_Family_Instrumenter_Type'Class (Self).Language))); + & (if Lang = CPP_Language then "_cpp" else "_c") + & (+Prj.Body_Suffix (Lang))); + -- The _cpp or _c suffix is required so that in case both C and C++ + -- helper units are generated, they don't have homonym object filenames. begin return Compilation_Unit' (Language => File_Based_Language, From 132f0d207e014172456a02f9aff1b7c987ffee53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Mon, 25 Mar 2024 12:27:46 +0100 Subject: [PATCH 0789/1483] Prevent ATCC from finding nested decisions in aspects Currently, assertion coverage should not look into nested decisions. Due to an omission, it does for aspects and applies regular coverage levels to them. This commit corrects this behavior by avoiding finding nested decisions in aspects. This should be improved upon by precisely defining what a condition is in the context of an assertion and applying a relevant coverage level to such nested decisions. --- .../tests/O212-062-atcc-nested/src/nested.adb | 37 +++++++++++++++++++ .../tests/O212-062-atcc-nested/src/nested.ads | 29 +++++++++++++++ .../O212-062-atcc-nested/src/test_nested.adb | 15 ++++++++ testsuite/tests/O212-062-atcc-nested/test.opt | 3 ++ testsuite/tests/O212-062-atcc-nested/test.py | 6 +++ tools/gnatcov/instrument-ada_unit.adb | 2 +- 6 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/O212-062-atcc-nested/src/nested.adb create mode 100644 testsuite/tests/O212-062-atcc-nested/src/nested.ads create mode 100644 testsuite/tests/O212-062-atcc-nested/src/test_nested.adb create mode 100644 testsuite/tests/O212-062-atcc-nested/test.opt create mode 100644 testsuite/tests/O212-062-atcc-nested/test.py diff --git a/testsuite/tests/O212-062-atcc-nested/src/nested.adb b/testsuite/tests/O212-062-atcc-nested/src/nested.adb new file mode 100644 index 000000000..aee4d6849 --- /dev/null +++ b/testsuite/tests/O212-062-atcc-nested/src/nested.adb @@ -0,0 +1,37 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package body Nested is + + function One return Integer is + begin + pragma Assert -- # success + (T and then (F or else -- # fail + (T and then (T -- # fail + or else F)))); -- # fail + return 1; -- # success + end One; + + -- One of the branches of the if expression is never exercised. + -- No violation is expected since gnatcov should not look into nested + -- decisions in assertions (FIXME: for now) + function Two return Integer is + begin + pragma Assert -- # success + ((if T then T else F) and then (F or else -- # success + (T and then (if (T and then F) -- # success + then T -- # success + else T)))); -- # success + return 2; -- # success + end Two; + + function Three return Integer is + begin + pragma Assert (if (T and then (T and then -- # success + (if T then T else F))) -- # success + then (T and then T) -- # success + else T); -- # success + return 3; -- # success + end Three; + +end nested; diff --git a/testsuite/tests/O212-062-atcc-nested/src/nested.ads b/testsuite/tests/O212-062-atcc-nested/src/nested.ads new file mode 100644 index 000000000..4d4a44b98 --- /dev/null +++ b/testsuite/tests/O212-062-atcc-nested/src/nested.ads @@ -0,0 +1,29 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Nested is + + T : Boolean := True; -- # success + F : Boolean := False; -- # success + + function One return Integer + with Pre => (T and then T) or else F, -- # fail + Post => One'Result = 1 and then -- # fail + (T and then -- # fail + (T or else -- # fail + (F or else T))); -- # fail + + function Two return Integer + with Pre => (T and then (if T then T else T)) or else F, -- # fail + Post => (if Two'Result = 2 and then -- # success + (T and then -- # success + (F or else (T or else F))) -- # success + then T -- # success + else F); -- # success + + function Three return Integer + with Post => (if (Three'Result = 2 and then (T and then -- # success + (if T then T else F))) -- # success + then (T and then T) -- # success + else T); -- # success +end Nested; diff --git a/testsuite/tests/O212-062-atcc-nested/src/test_nested.adb b/testsuite/tests/O212-062-atcc-nested/src/test_nested.adb new file mode 100644 index 000000000..6af8d40a1 --- /dev/null +++ b/testsuite/tests/O212-062-atcc-nested/src/test_nested.adb @@ -0,0 +1,15 @@ +with Nested; use Nested; + +procedure Test_Nested is + Dummy : Integer := One; +begin + Dummy := Two; + Dummy := Three; +end Test_Nested; + +--# nested.ads +-- /success/ l+ ## 0 +-- /fail/ l! ## ac! +--# nested.adb +-- /success/ l+ ## 0 +-- /fail/ l! ## ac! diff --git a/testsuite/tests/O212-062-atcc-nested/test.opt b/testsuite/tests/O212-062-atcc-nested/test.opt new file mode 100644 index 000000000..51a393770 --- /dev/null +++ b/testsuite/tests/O212-062-atcc-nested/test.opt @@ -0,0 +1,3 @@ +bin-traces XFAIL Assertion coverage not yet supported for binary traces +5.04a1 DEAD Test contains Ada_2012 features +7.1.2 DEAD Test contains Ada_2012 features diff --git a/testsuite/tests/O212-062-atcc-nested/test.py b/testsuite/tests/O212-062-atcc-nested/test.py new file mode 100644 index 000000000..db03ebbfe --- /dev/null +++ b/testsuite/tests/O212-062-atcc-nested/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.decision, assert_lvl="atcc").run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 045ea71ad..ad5b541e6 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6223,7 +6223,7 @@ package body Instrument.Ada_Unit is -- should not be checked. Therefore they should be -- instrumented. - if T /= 'P' then + if T not in 'P' | 'A' | 'a' then Find_Nested_Decisions (EN); end if; return Over; From 45aa0032d0fb997e441b00d78bc390155256c9e3 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Tue, 2 Apr 2024 19:20:40 +0200 Subject: [PATCH 0790/1483] Fix oversights from recent change addressing flake8 warnings In particular from 2fe4fe0d8, where some renamings of "dir" function argument names as "dirname" left a few stray references to "dir" in function bodies. --- qualification/genbundle.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 411c949ce..3f9e897e3 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -249,9 +249,9 @@ def run_list(cmd, dirname=None, env=None): oriwd = os.getcwd() print("from : %s" % oriwd) - if dir: - print("hopat : %s" % dir) - os.chdir(dir) + if dirname: + print("hopat : %s" % dirname) + os.chdir(dirname) print("run : %s" % " ".join(cmd)) @@ -266,7 +266,7 @@ def run_list(cmd, dirname=None, env=None): def run(s, dirname=None, env=None): - run_list(s.split(), dir, env=env) + run_list(s.split(), dirname=dirname, env=env) def announce(s): From 994c09d81105c85ddb7eb32268f23a04441612d7 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 3 Apr 2024 16:34:28 +0200 Subject: [PATCH 0791/1483] Add missing quote at end of nested string constant in genmodel.py --- qualification/qm/genmodel.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qualification/qm/genmodel.py b/qualification/qm/genmodel.py index 7588e6a80..823074317 100755 --- a/qualification/qm/genmodel.py +++ b/qualification/qm/genmodel.py @@ -36,7 +36,7 @@ def __extra_block_for(dolevel): From af6ce4417b6aaf1377fea791ec6859ec4c0451c0 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 3 Apr 2024 17:06:06 +0200 Subject: [PATCH 0792/1483] Revert to old fashioned formatted strings in qm_plugins/importers.py As this script is processed through the python interpreter embedded within qmachine, which is python 2.7. --- qualification/qm/qm_plugins/importers.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/qualification/qm/qm_plugins/importers.py b/qualification/qm/qm_plugins/importers.py index b980211cf..de6eeb078 100644 --- a/qualification/qm/qm_plugins/importers.py +++ b/qualification/qm/qm_plugins/importers.py @@ -491,10 +491,10 @@ def qmlink_to_rest(self, parent, artifacts): output += ( writer.paragraph( - "This particular table is established for **Ada" - f" {language_version}**." + "This particular table is established for **Ada %s**." "\n\\The requirement identifiers in this table were shortened" - f" by removing the *{REQ_NAME_PREFIX}* common prefix.\n\n" + " by removing the *%s* common prefix.\n\n" + % (language_version, REQ_NAME_PREFIX) ) + writer.only(pdf_table, "latex") + writer.only(html_table, "html") From b96e40a16cfcb4727907205f23a88e6b78bbea94 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 3 Apr 2023 01:01:26 -0700 Subject: [PATCH 0793/1483] Remove obsolete svn related items in testsuite/qualification Remove qualification/setup.sh, much outdated Remove obsolete references to svn artifacts Minor rework of obsolete sections in testsuite/README.md, to remove refs to valgrind for native configurations, suggest --trace-mode in example commands Likewise in tools/gnatcov/README.md and tools/gnatcov/examples/README.md Part of work for issue eng/cov/gnatcoverage-qualification#1 Part of work for W227-016 (qualkit 1329-W227-016) --- qualification/setup.sh | 107 ------------------------------- testsuite/README.md | 49 +++++--------- testsuite/SUITE/qdata.py | 8 +-- testsuite/cleanup.sh | 6 +- tools/gnatcov/README.md | 2 +- tools/gnatcov/examples/README.md | 8 +-- 6 files changed, 27 insertions(+), 153 deletions(-) delete mode 100644 qualification/setup.sh diff --git a/qualification/setup.sh b/qualification/setup.sh deleted file mode 100644 index 8b6ce6514..000000000 --- a/qualification/setup.sh +++ /dev/null @@ -1,107 +0,0 @@ -# Very rough script that collects the steps necessary to prepare an -# environment capable of producing the GNATcoverage qualification package -# (with genbundle.py). - -# This script usually doesn't work straight out (for example the format in -# which some of the preriquisites are archived has changed, or today's build -# of one component has failed). It provides, nevertheless, a precise idea of -# the required components and a possible way to set them up for the task. - -# The general idea is to setup a temporary work directory where we -# will have -# -# - a "PACKAGES" subdirectory, where the preriquisite components are fetched -# (binary distributions pre-packaged by gnatmail somewhere) -# -# - a "local" subdirectory, where they are all installed and that should be -# prepended to PATH to produce a qualification bundle. - -TMP=$HOME/tmp-gnatcov -mkdir $TMP || exit 1 - -# ------------------------------ -# -- fetch & install packages -- -# ------------------------------ - -# fetch - -GNATMAIL=tolbiac:/tolbiac.a/gnatmail -FTP=tolbiac:/ftpserver/art/file-view -DAILYBINDIR=$GNATMAIL/gcc-45/binaries/today/ -OS=$(uname -o) - -case $OS in - *win*) - OS=windows - HOST_GNATEMU=rostov - HOST_GNATCOV=rostov - HOST_QMACHINE=tormes - UNPACK="unzip -q" - PACKEXT="zip" - ;; - - *Linux*) - OS=linux - HOST_GNATEMU=chinon - HOST_GNATCOV=chinon - HOST_QMACHINE=chinon - UNPACK="tar xzf" - PACKEXT="tar.gz" - ;; - -esac - -PACKDIR=$TMP/PACKAGES -mkdir $PACKDIR || exit 1 - -cd $PACKDIR - -rsync $DAILYBINDIR/ppc-elf-$OS/${HOST_GNATEMU}/gnatemulator-\*.$PACKEXT . -rsync $DAILYBINDIR/x86-$OS/${HOST_GNATCOV}/gnatcoverage-\*.$PACKEXT . -rsync $DAILYBINDIR/x86-$OS/${HOST_QMACHINE}/qmachine-\*.$PACKEXT . - -rsync $GNATMAIL/svn-binaries/gnatpython/1.2/distrib/x86-$OS/gnatpython-\*.tgz . - -rsync $FTP/ada-6.4.2/ppc-elf-$OS/gnat/gnatpro-\* . - -# install - -LOCAL=$TMP/local -mkdir $LOCAL || exit 1 - -$(echo $UNPACK) gnatemulator-*.$PACKEXT -cp -rp gnatemulator-*-bin/* $LOCAL - -$(echo $UNPACK) gnatcoverage-*.$PACKEXT -cp -rp gnatcoverage-*-bin/* $LOCAL - -$(echo $UNPACK) qmachine-*.$PACKEXT -cp -rp qmachine-*-bin/* $LOCAL - -tar xzf gnatpython-*.tgz -cp -rp gnatpython-*-bin $LOCAL/gnatpython - -case $OS in - windows) - ./gnatpro-*.exe /S "/D=`cygpath -w $LOCAL`";; - - *) - tar xzf gnatpro-* - cd gnat-*bin - ./doinstall -esac - -# ------------------------------------------------ -# -- retrieve and run the material build script -- -# ------------------------------------------------ - -PATH=$LOCAL/bin:$LOCAL/gnatpython:$LOCAL/gnatpython/Scripts:$PATH - -cd $TMP - -svn export svn://scm.forge.open-do.org/scmrepos/svn/couverture/trunk/couverture/qualification/genbundle.py - -TEMP=$TMP -DATE=`date +%Y-%m-%d` -python ./genbundle.py --root-dir=$TMP/QMAT - diff --git a/testsuite/README.md b/testsuite/README.md index be4e0caa1..d7e235c5f 100644 --- a/testsuite/README.md +++ b/testsuite/README.md @@ -8,13 +8,9 @@ This is a Python driven testsuite for GNATcoverage. Most tests use gprbuild to build programs for run/analysis by gnatcov/gnatemu. -The testsuite driver is `/testsuite.py`. It scans the following -subdirectories for `test.py` instances and runs every one it finds after -switching to where it was found: - -* `Qualif/` (DO-178 qualification testsuite) -* `../extra/tests/` (other testcases) - +The testsuite driver is `/testsuite.py`. It scans the subdirectories +provided as arguments for `test.py` instances and runs every one it finds after +switching the current directory to where it was found. Prerequisites ------------- @@ -23,7 +19,7 @@ You need, on your `PATH`: * The gnatcov binary that you wish to exercise -* gprbuild >= 1.3.0 +* gprbuild version >= 22 * The [e3-core](https://github.com/AdaCore/e3-core/) and [e3-testsuite](https://github.com/adacore/e3-testsuite/) Python packages. @@ -34,28 +30,16 @@ You need, on your `PATH`: * The `-gnatemu` binaries you wish to exercise if you are willing to run tests for a cross target. -Native runs are supported on x86 and x86_64-linux, using an instrumented -version of Valgrind. An instrumented Valgrind is bundled in recent binary -packages of GNATcoverage. If you are building from sources, you need to -install the GNATcoverage trace adapter into your Valgrind distrib. See the -Makefiles for this particular purpose. - -If you are running tests for a ZFP or Ravenscar configuration (not a full -runtime), you also need at the toplevel, together with this README: a `support` -subdirectory corresponding to the one in the gnatcov examples. - -If you retrieved this testsuite subdir as part of a full GNATcoverage tree, you -have the gnatcov sources in `../tools` and may for example do: - -```shell -ln -s ../tools/gnatcov/examples/support support -``` +* An e3-testsuite distribution, https://github.com/AdaCore/e3-testsuite -Otherwise, you might just checkout the relevant subdir from the scm repo, for -example with: +If you are running tests for a light (formerly ZFP)s or Ravenscar configuration +(not a full runtime), you also need at the toplevel, together with this +README: a `support` subdirectory corresponding to the one in the gnatcov +examples. Assuming you have the GNATcoverage source repository at hand in +$gnatcov-src-dir, this could be setup with a mere symbolic link like: ```shell -svn co svn+ssh://$OPENDO_ROOT/tools/gnatcov/examples/support +ln -s $gnatcov-src-dir/tools/gnatcov/examples/support support ``` @@ -73,13 +57,12 @@ Note the use of target _product_ names here, not GCC target triplets. For example: ```shell -# Cross configurations, using GNATemulator: -./testsuite.py --target=ppc-elf --RTS=powerpc-elf/ravenscar-sfp-prep -./testsuite.py --target=leon-elf --RTS=ravenscar -./testsuite.py --target=ppc-vx6 --RTS=kernel --kernel=tests/kernels/vx6.8-fastsbc +# Cross configurations, using binary traces or source instrumentation: +./testsuite.py --target=ppc-elf --RTS=light-mpc8641 --trace-mode=src +./testsuite.py --target=leon3-elf --RTS=embedded-leon3 --trace-mode=bin -# Native configuration, using an instrumented valgrind (x86-linux or x86_64-linux): -./testsuite.py +# Windows or Linux native configuration, using source instrumentation: +./testsuite.py --trace-mode=src ``` The optional `regexp` at the end instructs the driver to run only those tests diff --git a/testsuite/SUITE/qdata.py b/testsuite/SUITE/qdata.py index f36b778da..3c6c96ea8 100644 --- a/testsuite/SUITE/qdata.py +++ b/testsuite/SUITE/qdata.py @@ -174,10 +174,10 @@ def stdf_in(dirname): def treeref_at(dirname): """ - A string representative of where the DIRNAME directory originates from - (e.g. svn rev or git commit), to be used for consistency checks when - multiple operations are done separately but should work over synchronized - directory trees. + A string representative of the git commit where the DIRNAME + directory originates from, to be used for consistency checks + when multiple operations are done separately but should work + over synchronized directory trees. """ # Assuming git, sha1 for the HEAD reference return output_of("git rev-parse HEAD", dirname=dirname).rstrip("\n") diff --git a/testsuite/cleanup.sh b/testsuite/cleanup.sh index fb9cc9fd7..a1fe3fc61 100644 --- a/testsuite/cleanup.sh +++ b/testsuite/cleanup.sh @@ -16,9 +16,9 @@ rm -rf $(find -type d -name 'obj_*') rm -rf $(find -type f -name 'tmp*.list') rm -rf $(find -type f -name '*~') -rm -rf $(find -type f -name 'test.py.???' | grep -v svn) -rm -rf $(find -type f -name '*.adb.*' | grep -v svn) -rm -rf $(find -type f -name '*.dump' | grep -v svn) +rm -rf $(find -type f -name 'test.py.???') +rm -rf $(find -type f -name '*.adb.*') +rm -rf $(find -type f -name '*.dump') rm -rf $(find -type d -name 'memcheck.log') rm -rf $(find -type d -name 'callgrind-*.log') diff --git a/tools/gnatcov/README.md b/tools/gnatcov/README.md index d2ac8b879..38b7be9d3 100644 --- a/tools/gnatcov/README.md +++ b/tools/gnatcov/README.md @@ -32,7 +32,7 @@ exercise it by just switching to share/examples/gnatcoverage/starter and typing: ```shell -engines $ make [TARGET=powerpc-elf] [RTS=zfp-mpc8641] +engines $ make [TARGET=powerpc-elf] [RTS=light-mpc8641] ``` The local Makefile includes a generic Makefile common to all the examples, and diff --git a/tools/gnatcov/examples/README.md b/tools/gnatcov/examples/README.md index 23ec01de5..6675a4da8 100644 --- a/tools/gnatcov/examples/README.md +++ b/tools/gnatcov/examples/README.md @@ -15,9 +15,8 @@ examples can only run on specific targets), you may select the following target to use by setting the `TARGET` and `RTS` variables explicitly: ```shell -make TARGET=powerpc-elf RTS=zfp-mpc8641 runs on bare PowerPC -make TARGET=powerpc-eabispe RTS=zfp-p2020 runs on bare PowerPC/e500v2 -make TARGET=leon-elf RTS=zfp-leon runs on bare LEON2 +make TARGET=powerpc-elf RTS=light-mpc8641 runs on bare PowerPC +make TARGET=leon3-elf RTS=light-leon3 runs on bare LEON2 ``` as well as: @@ -26,5 +25,4 @@ as well as: make ``` -for native `x86-linux/windows` or `x86_64-linux/windows` runs relying on a -specially instrumented version of Valgrind or DynamoRIO. +for native `x86-linux/windows` or `x86_64-linux/windows` runs. From eb9020229d150b5ddc20d92eacf3ab904cb6fc11 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Sat, 22 Apr 2023 00:44:35 -0700 Subject: [PATCH 0794/1483] driver.py: Remove redundant/inaccurate instrumentation output check From the SCOV driver, replicating what xcov_instrument now already does in a more accurate fashion, in particular regarding warnings about object directories. Part of work for qualkit 1329-W227-016 --- testsuite/SCOV/internals/driver.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 9d15de773..a9cfd568f 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -1406,7 +1406,11 @@ def mode_build(self): subdirs = None instrument_gprsw = GPRswitches(root_project=self.gpr) + # Instrument now, requesting the propagation of instrumentation + # issues on the test status. Note that we expect this to include + # a check on instrumentation warnings. out = "xinstr.out" + xcov_instrument( covlevel=self.xcovlevel, extra_args=to_list(self.covctl.covoptions) if self.covctl else [], @@ -1415,8 +1419,8 @@ def mode_build(self): gprsw=instrument_gprsw, gpr_obj_dir=self.gpr_obj_dir, out=out, - tolerate_messages=self.testcase.tolerate_messages, - ) + register_failure=True, + tolerate_messages=self.testcase.tolerate_messages) # When exception propagation is not available, a test ending with an # unhandled exception goes straight to the last_chance_handler from @@ -1443,17 +1447,6 @@ def mode_build(self): main_unit=no_ext(self.drivers[0]), ) - # Standard output might contain warnings indicating instrumentation - # issues. This should not happen, so simply fail as soon as the output - # file is not empty. - if not self.testcase.tolerate_messages: - thistest.fail_if( - os.path.getsize(out) > 0, - "xcov instrument standard output not empty ({}):" - "\n--" - "\n{}".format(out, contents_of(out)), - ) - # Now we can build, instructing gprbuild to fetch the instrumented # sources in their dedicated subdir: gprbuild( From 9c7887a4c3d4743b600beef9012b3ef685ce277c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 11 May 2023 16:19:39 +0200 Subject: [PATCH 0795/1483] Genbundle: Perform consistency checks on status files Genbundle used to perform consistency checks on the tc.dump file, mostly containing the SCO counters for each testcase (as in SCOV Testcase). There are tests in the Common directory that have multiple SCOV Testcases per actual test (i.e. testcase as identified in the TOR document), which made this consistency check impossible. The consistency check is now done on the testcase status file, tcs.dump, as only one is generated per test. --- qualification/genbundle.py | 3 ++- qualification/qm/template.xml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 3f9e897e3..a4a7bbec7 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -665,7 +665,8 @@ def sync(tr): else: print("ERRRR !! inexistant target dir for %s" % tr) - [sync(tr) for tr in find(root=".", pattern="tc.dump")] + [sync(tr) for tr in find(root=".", pattern="tcs.dump")] + env_chapter_dir = os.path.join( self.repodir, "testsuite", "Qualif", "Environment" ) diff --git a/qualification/qm/template.xml b/qualification/qm/template.xml index 3b86b5066..a9ff80221 100644 --- a/qualification/qm/template.xml +++ b/qualification/qm/template.xml @@ -357,7 +357,7 @@ From 0ac7eafa8fda9f0a4e4f1788b026a4a3962f644e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 11 May 2023 16:24:59 +0200 Subject: [PATCH 0796/1483] Genrest: Add support for test with multiple tc.dump files genrest.py used to ignore testcase dump files for tests with more than one SCOV Testcase. This limitation is now lifted by aggregating the SCO tallies in each tc.dump file found in the directory tree rooted at the test directory. --- testsuite/STR/genrest.py | 27 ++++++++++++--------------- testsuite/SUITE/qdata.py | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/testsuite/STR/genrest.py b/testsuite/STR/genrest.py index 6af4839c2..8410424b0 100644 --- a/testsuite/STR/genrest.py +++ b/testsuite/STR/genrest.py @@ -28,7 +28,7 @@ TEST_LOG = "test.py.log" -from SUITE.qdata import qdaf_in, stdf_in +from SUITE.qdata import qdafs_from, stdf_in from SUITE.qdata import STATUSDATA_FILE, QLANGUAGES, QROOTDIR from SUITE.qdata import CTXDATA_FILE, Qdata from SUITE.control import BUILDER @@ -133,26 +133,23 @@ def load_test(self, dirname): print("loading from %s" % dirname) # Some tests in the Common chapter have status data and multiple - # individual test data files in subdirectories. Their purpose is to - # verify the proper behavior of a general functionality such as the - # ability to use project files, not to verify that the tool assesses - # such or such criteria properly. Even if they use an internal - # facility that does this as well, the individual datapoints - # are irrelevant and shouldn't be loaded. The general test result - # remains of interest of course. + # individual test data files in subdirectories. To properly load + # these multiple test data files, load them one at a time and merge + # the entries in the Qdata object of the whole testcase. # Fetch the status data first, then complete it with test data - # at the same place if any. + # located in the directory tree rooted at dirname, if any. std = dutils.pload_from(stdf_in(dirname)) - tcdf = qdaf_in(dirname) + tcdfs = qdafs_from(dirname) - qda = ( - dutils.pload_from(tcdf) - if os.path.exists(tcdf) - else Qdata(tcid=dirname) - ) + qda = Qdata(tcid=dirname) + + for tcdf in tcdfs: + sub_qda = dutils.pload_from (tcdf) + for entry in sub_qda.entries: + qda.register (entry) qda.status = std.status qda.comment = std.comment diff --git a/testsuite/SUITE/qdata.py b/testsuite/SUITE/qdata.py index 3c6c96ea8..0661057ba 100644 --- a/testsuite/SUITE/qdata.py +++ b/testsuite/SUITE/qdata.py @@ -164,9 +164,22 @@ def qdaf_in(dirname): return os.path.join(dirname, QUALDATA_FILE) -STATUSDATA_FILE = "tcs" + STREXT +def qdafs_from(dirname): + """ + List of filenames for qualification data to be pickled, from the directory + tree rooted at dirname. Each returned filename hosts instances of objects + representing test executions, each holding dictionaries of expected notes + together with their dischargers. + """ + return [ + os.path.join(dir, file) + for (dir, _, files) in os.walk(dirname) + for file in files if file == QUALDATA_FILE + ] +STATUSDATA_FILE = "tcs" + STREXT + def stdf_in(dirname): """Filename for execution status data to be picked up DIR""" return os.path.join(dirname, STATUSDATA_FILE) From 5d800534168bda52b98f99302f65628ee25bf003 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Fri, 12 May 2023 15:11:57 +0200 Subject: [PATCH 0797/1483] Relax STR/conf.py knowledge of the common_conf.py location Remove the knowledge wired in conf.py of the subdir name chosen by genbundle for the gnatcov repo image, allowing easier modifications of this choice when need be. Part of W227-016 (gntacov qualkit 1329-W227-016) --- testsuite/STR/conf.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/testsuite/STR/conf.py b/testsuite/STR/conf.py index c97058097..7eddd9165 100644 --- a/testsuite/STR/conf.py +++ b/testsuite/STR/conf.py @@ -11,28 +11,28 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os +import sys, os, glob doc_standard_name = "Tool Operational Verification and Validation Results" rst_prolog = ".. |str_doc| replace:: *%s*" % doc_standard_name -common_file = os.path.join( +# Locate and import common_conf.py + +work_dir = os.path.join( os.path.dirname( - os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - ), - "gnatcoverage-git-clone", - "qualification", - "qm", - "common_conf.py", + os.path.dirname( + os.path.dirname( + os.path.abspath(__file__)))) ) +common_conf_glob = f"{work_dir}/*/qualification/qm/common_conf.py" +common_conf_candidates = glob.glob(common_conf_glob) + +assert len(common_conf_candidates) == 1, \ + f"{__file__} couldn't locate lone common_conf.py out of {common_conf_glob}" -if os.path.isfile(common_file): - exec(open(common_file).read()) -else: - print("Couldn't find common configuration file") - print(common_file) - print("from: %s" % __file__) +common_conf_py = common_conf_candidates[0] +exec(open(common_conf_py).read()) # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the From 4968053e624c429e2c438d7f0b0341e874f383a7 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Thu, 11 May 2023 07:56:11 -0700 Subject: [PATCH 0798/1483] Adapt genbundle to support anod invocations Adjust genbundle to support invocations from Anod, which operate from an untarred source package, not a git repository. Essentially: - Generalize --git-rsync to --rsync-from (switch name, internal variables and comments) - make --branch optional - Add a --kitid switch to let callers request a specific kit identifier instead of inferring it from the current git branch. This is more appropriate for Anod driven builds, which don't have a git repo at hand (hence no branch name to query) and know the kit identifier upfront; - Update the default URL to match a recent move of the project to gitlab. Part of W227-016 (gnatcov qualkit 1329-W227-016) --- qualification/genbundle.py | 101 ++++++++++++++++++++----------------- 1 file changed, 56 insertions(+), 45 deletions(-) diff --git a/qualification/genbundle.py b/qualification/genbundle.py index a4a7bbec7..c9e50c86c 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -158,7 +158,7 @@ # | # | (clone by genbundle.py) # v -# $work-dir/ gnatcoverage-git-clone/ +# $work-dir/ # qualification/qm/plans/ <- PLANS artifacts # testsuite/ <- TOR artifacts # @@ -346,8 +346,16 @@ def current_gitbranch_at(dirname): "git@ssh.gitlab.adacore-it.com:eng/das/cov/gnatcoverage-qualification.git" ) -# The subdir name for this clone, relative to --root -GIT_CLONE_SUBDIR = "gnatcoverage-git-clone" +# The name of the subdir in the working directory where we'll fetch TOR +# artifacts from. This would be an image of a "gnatcoverage" repository, from +# either +# +# - the immediate result of a git clone command, or +# - an rsync from a cloned repo somewhere (--rsync ), +# - an rsync from a source package, typically prepared from a branch +# for a qualification project (--rsync ). + +REPO_IMAGE_SUBDIR = "gnatcoverage-git-clone" class QMAT: @@ -361,7 +369,7 @@ def __init__(self, options): # Latch repo dir location while we're at it: self.workdir = os.path.abspath(options.workdir) - self.repodir = os.path.join(self.workdir, GIT_CLONE_SUBDIR) + self.repodir = os.path.join(self.workdir, REPO_IMAGE_SUBDIR) # A local place where the testsuite tree may be found, # possibly after remote syncing from testsuite_dir if that @@ -431,27 +439,23 @@ def log(self, line): with open(os.path.join(self.workdir, "genbundle.log"), "a") as f: f.write(line + "\n") + # ---------------- + # -- rsync_from -- + # ---------------- + + def rsync_from(self, rsync_source): + run_list( + ["rsync", "-ar", rsync_source + '/', self.repodir + '/', + '--delete', '--delete-excluded', + '--filter', '. dev.rsync', + ] + ) + # ---------------- # -- git_update -- # ---------------- def git_update(self): - # If we're requested to rsync from an existing repo dir, do so - - if self.o.gitrsync: - run_list( - [ - "rsync", - "-ar", - self.o.gitrsync + "/", - self.repodir + "/", - "--delete", - "--delete-excluded", - "--filter", - ". dev.rsync", - ] - ) - return # If we're requested to pull/update only, do so @@ -476,8 +480,8 @@ def git_update(self): announce("cloning git repository from %s" % gitref) - remove(GIT_CLONE_SUBDIR) - run("git clone %s %s" % (gitref, GIT_CLONE_SUBDIR)) + remove(REPO_IMAGE_SUBDIR) + run("git clone %s %s" % (gitref, REPO_IMAGE_SUBDIR)) # ---------------------- # -- switch_to_branch -- @@ -957,20 +961,22 @@ def build_kit(self): # # gnatcov-qualkit-- # - # where is the kit production stamp (now), and is - # computed from the git branch off which the artifacts are taken. The - # git branch name might contain the "qualkit" indication already. + # is the kit production stamp (now), + # is the kit identifier, typically -. today = date.today() - gitbranch = current_gitbranch_at(self.repodir) - kitprefix = ( - "gnatcov-qualkit" if "qualkit" not in gitbranch else "gnatcov" - ) + # If the kitid is not provided, assume the artifacts repo image holds + # a git clone and compute the id from the current branch there: - kitid = gitbranch - kitid = kitid.replace("/", "-") - kitid = kitid.replace(".", "_") + if self.o.kitid: + kitid = self.o.kitid + else: + gitbranch = current_gitbranch_at(self.repodir) + + kitid = gitbranch.replace("qualkit-", "") + kitid = kitid.replace('/', '-') + kitid = kitid.replace('.', '_') # If we are re-constructing a kit with some parts just rebuilt, target # the specified version (stamp) and arrange to keep the old elements @@ -981,7 +987,7 @@ def build_kit(self): if self.o.rekit else "%4d%02d%02d" % (today.year, today.month, today.day) ) - kitname = "%s-%s-%s" % (kitprefix, kitid, kitstamp) + kitname = "gnatcov-qualkit-%s-%s" % (kitid, kitstamp) kitdir = "%s-%s" % (kitname, self.this_docformat) mkdir(kitdir) @@ -1109,10 +1115,10 @@ def commandline(): help=("Reuse current git clone setup in work-dir, as-is. "), ) op.add_option( - "--git-rsync", - dest="gitrsync", + "--rsync-from", + dest="rsync_from", default=False, - help=("Rsync an existing git repo into our git clone dir."), + help=("Rsync an existing repo image into our local image dir."), ) op.add_option( "--branch", @@ -1120,6 +1126,12 @@ def commandline(): default=None, help=("The git branch we shall produce the material from."), ) + op.add_option ( + "--kitid", + dest="kitid", + default=False, + help=("Use the provided argument as the kit identifier.") + ) op.add_option( "--docformat", @@ -1248,13 +1260,6 @@ def check_valid(options, args): ("Please specify the desired output format (--docformat)."), ) - # Likewise for the git branch name: - - exit_if( - not options.branchname, - ("Please specify the git branch name (--branch)."), - ) - # Convey whether we are requested to produce a kit: options.kitp = options.rekit or not options.parts @@ -1331,8 +1336,14 @@ def check_valid(options, args): qmat = QMAT(options=options) qmat.setup_workdir() - qmat.git_update() - qmat.switch_to_branch() + + if options.rsync_from: + qmat.rsync_from(options.rsync_from) + else: + qmat.git_update() + + if options.branchname: + qmat.switch_to_branch() # Produce each part we are requested to produce, with a tailored # QM model: From 060fde6dc23e35276ae41525e3c65b2eb6f7f60b Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 15 May 2023 09:22:32 +0200 Subject: [PATCH 0799/1483] Tighten requirements on generics to aggregation mode only Per instance coverage assessment is not supported by the instrumenter and we have never had a qualification project using -S instance with binary traces. Simplify the requirements and testcase descriptions to not mention the possibility at all. Part of W227-016 (gnatcov qualkit 1329-W227-016) Part of W426-013 (gnatcov qualkit 999-W426-013) --- .../Variants_ByConstruct/tc.rst | 2 +- .../Variants_BySubprogram/tc.rst | 2 +- .../Ada/stmt/1_Core/12_GenericUnits/req.rst | 32 ++++++------------- 3 files changed, 12 insertions(+), 24 deletions(-) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/tc.rst index 7bd614eb1..9081d5cb7 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/tc.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/tc.rst @@ -1,6 +1,6 @@ **Exercise SC on multiple generic instances, triggering different paths** -Exercise aggregated and per-instance Statement Coverage on multiple instances +Exercise Statement Coverage on multiple instances of generic packages provided either as local packages within another package spec. Enforce coverage variations by calling subprograms with arguments values controlling different paths within the subprograms thanks to conditional diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/tc.rst index cb21cce5a..969bebc33 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/tc.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/tc.rst @@ -1,6 +1,6 @@ **Exercise SC on multiple generic instances, triggering different subprograms** -Exercise aggregated and per-instance Statement Coverage on multiple instances +Exercise Statement Coverage on multiple instances of generic packages provided either as independant compilation units or as local packages within a subprogram body. Enforce coverage variations by calling different subsets of subprograms exposed by each instance and going diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/req.rst index f36495a89..34de34b59 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/req.rst @@ -4,35 +4,23 @@ SC requirements for ARM chap. 12 : Generic Units %REQ_ID% -Unless requested otherwise by a command line argument to `gnatcov coverage`, -the tool aggregates for a given generic source the coverage achieved by -different instantiations of the entities offered by this source. +For a given `generic` source (package or subprogram), the tool +aggregates the coverage achieved by different instantiations of the +entities offered by this source. -In this default mode, Statements or declarations within generic source code -shall only be reported uncovered when they are never executed at all, -regardless of the instantiations from which the execution might originate. - -Conversely, with `-S instance` on the `gnatcov coverage` command line, the -tool shall perform a separate assessment and report about coverage violations -for each instantiation independently from the others. +Statements or declarations within generic source code shall only be +reported uncovered when they are never executed at all, regardless of +the instantiations from which the execution might originate. .. rubric:: Testing Strategy We check a variety of statement constructs in different kinds of generic sources (packages and subprograms) through library-level and local -instantiations, some in default, aggregation, mode only, some both in -aggregation and per-instance modes. - -In aggregation mode, we verify that a statement in a generic source is -reported uncovered only if it is exercised through none of the instances. - -In per-instance mode, we exercise execution of a generic statement through -multiple combinations of instances and verify that the tool reports the -expected set of coverage violations for each distinct instance. Variations -within one instance is achieved by calling a particular set of subprograms -exposed by the instance, or by the use of conditional constructs within -subprograms. +instantiations. + +We verify that a statement in a generic source is reported uncovered +only if it is exercised through none of the instances. .. qmlink:: TCIndexImporter From 35c0044e2d5056ea0b54177d91ccf1ddd688c4d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 15 May 2023 10:57:51 +0200 Subject: [PATCH 0800/1483] Various cosmetic improvments to PLANS and STR documents This change brings a few cosmetic improvments to the PLANS and STR documents: - rewrap long commands in the qualified interface to avoid clipping in the pdf version of the PLANS document; - remove the document width limit for the html version of the STR document, to aid redability of the verification environment tables; - replace spurrious ":literal:``" markers by "" in the verification environment tables when the correspondig table entry is empty. Part of W227-016 (gnatcov qualkit 1329-W227-016) --- .../Qualified_Interface/content_src.rst | 7 +++++-- testsuite/STR/conf.py | 4 ++-- testsuite/STR/genrest.py | 3 ++- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst b/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst index 6ceb67e22..fda785784 100644 --- a/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst +++ b/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst @@ -35,7 +35,9 @@ use GNATcoverage as follows: .. code-block:: text - gnatcov instrument [--target= --RTS=] --level= --dump-trigger= --dump-channel= -P + gnatcov instrument [--target= --RTS=] + --dump-trigger= --dump-channel= + --level= -P * Build the application and test executables with the GNAT Pro toolchain @@ -60,7 +62,8 @@ use GNATcoverage as follows: .. code-block:: text - gnatcov coverage --annotate=report --level= -P @ -o + gnatcov coverage --annotate=report -o + --level= -P @ In the sample commands above: diff --git a/testsuite/STR/conf.py b/testsuite/STR/conf.py index 7eddd9165..d262d5bb7 100644 --- a/testsuite/STR/conf.py +++ b/testsuite/STR/conf.py @@ -99,12 +99,12 @@ # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = "default" +html_theme = "classic" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -# html_theme_options = {} +html_theme_options = {'body_max_width': None} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] diff --git a/testsuite/STR/genrest.py b/testsuite/STR/genrest.py index 8410424b0..7aecd9e15 100644 --- a/testsuite/STR/genrest.py +++ b/testsuite/STR/genrest.py @@ -1154,7 +1154,8 @@ def gen_tssummary(self, sepfile): def gen_suite_options(self): def literal(text): - return ":literal:`" + text.strip() + "`" + text = text.strip() + return ":literal:`" + text + "`" if text else "" def str_relevant_switches_from(switches_string): """The list of individual pieces in `switches_string` From b390a2372a6efc8ce554e9976a3b28cc12687726 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 15 May 2023 11:17:55 +0200 Subject: [PATCH 0801/1483] Adjust stmt requirements and tests on pragmas for instrumentation Assert-like pragmas are never considered as statements with the source instrumentation scheme. All the other pragmas possibly generating code (e.g. Debug) are always considered as statements by the instrumenter. This change acknowledges the src/bin traces difference in the requirements and testcase decriptions, and refines the test procedures to better cover the variety of situations instead of just XFAILing the legacy tests. Pragmas/Active and Pragmas/Inactive respectively become Pragmas/Policy_On and Pragmas/Policy_Off to clarify the actual kind of particularity enforced in each subdir. Part of W227-016 (gnatcov qualkit 1329-W227-016) Part of W426-013 (gnatcov qualkit 999-W426-013) --- .../02_LexicalElements/Pragmas/Active/tc.rst | 7 ---- .../Pragmas/Active/test.opt | 1 - .../Pragmas/Inactive/src/asserts.ads | 4 -- .../Pragmas/Inactive/src/test_asserts_0.adb | 14 ------- .../Pragmas/Inactive/src/test_asserts_t.adb | 14 ------- .../Pragmas/Inactive/tc.rst | 8 ---- .../src/pragmas.adb} | 10 ++++- .../Pragmas/Policy_Off/src/pragmas.ads | 10 +++++ .../Pragmas/Policy_Off/src/test_pragmas_0.adb | 21 ++++++++++ .../Pragmas/Policy_Off/src/test_pragmas_t.adb | 30 ++++++++++++++ .../Pragmas/Policy_Off/tc.rst | 10 +++++ .../Pragmas/{Active => Policy_Off}/test.py | 0 .../{Active => Policy_On}/src/pragmas.adb | 0 .../{Active => Policy_On}/src/pragmas.ads | 0 .../src/support_pragmas.adb | 0 .../src/support_pragmas.ads | 0 .../src/test_pragmas_assert_debug.adb | 18 ++++++--- .../src/test_pragmas_full.adb | 10 ++++- .../src/test_pragmas_no.adb | 12 +++++- .../src/test_pragmas_pre_post.adb | 13 ++++++- .../Pragmas/Policy_On/tc.rst | 9 +++++ .../Pragmas/{Inactive => Policy_On}/test.py | 0 .../1_Core/02_LexicalElements/Pragmas/req.rst | 39 +++++++++++-------- 23 files changed, 156 insertions(+), 74 deletions(-) delete mode 100755 testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/tc.rst delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.opt delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/asserts.ads delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_0.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_t.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/tc.rst rename testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/{Inactive/src/asserts.adb => Policy_Off/src/pragmas.adb} (65%) create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.ads create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_0.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_t.adb create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/tc.rst rename testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/{Active => Policy_Off}/test.py (100%) rename testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/{Active => Policy_On}/src/pragmas.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/{Active => Policy_On}/src/pragmas.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/{Active => Policy_On}/src/support_pragmas.adb (100%) rename testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/{Active => Policy_On}/src/support_pragmas.ads (100%) rename testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/{Active => Policy_On}/src/test_pragmas_assert_debug.adb (71%) rename testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/{Active => Policy_On}/src/test_pragmas_full.adb (85%) rename testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/{Active => Policy_On}/src/test_pragmas_no.adb (83%) rename testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/{Active => Policy_On}/src/test_pragmas_pre_post.adb (77%) create mode 100755 testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/tc.rst rename testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/{Inactive => Policy_On}/test.py (100%) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/tc.rst deleted file mode 100755 index 794042b5c..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/tc.rst +++ /dev/null @@ -1,7 +0,0 @@ -**Exercise SC on active pragmas** - -Check that active pragmas which are not elaborated are reported as -uncovered. Exercise Assert, Debug, Precondition and Postcondition pragmas -placed in various source contexts. - -LRMREF: 2.8 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.opt deleted file mode 100644 index 961ea3846..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.opt +++ /dev/null @@ -1 +0,0 @@ -src-traces XFAIL TODO: revisit requirements and expectations once we re-enable assertion instrumentation (U528-022) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/asserts.ads b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/asserts.ads deleted file mode 100644 index 6046428a1..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/asserts.ads +++ /dev/null @@ -1,4 +0,0 @@ -package Asserts is - procedure Sum (X, Y, UB : Integer; R : out Integer); - procedure Dif (X, Y, LB : Integer; R : out Integer); -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_0.adb deleted file mode 100644 index 880d0ed8d..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_0.adb +++ /dev/null @@ -1,14 +0,0 @@ -with Support, Asserts; use Asserts, Support; - --- Don't call into the functional code. Expect s- only on active lines --- with real statements, not on the pragma ones since deactivated by the --- check policy. - -procedure Test_Asserts_0 is -begin - null; -end; - ---# asserts.adb --- /eval/ l- ## s- --- /assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_t.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_t.adb deleted file mode 100644 index 7b3d00994..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/test_asserts_t.adb +++ /dev/null @@ -1,14 +0,0 @@ -with Support, Asserts; use Asserts, Support; - -procedure Test_Asserts_T is - R : Integer; -begin - Sum (X => 2, Y => 3, UB => 10, R => R); - Assert (R = 5); - Dif (X => 5, Y => 1, LB => 1, R => R); - Assert (R = 4); -end; - ---# asserts.adb --- /eval/ l+ ## 0 --- /assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/tc.rst deleted file mode 100644 index 2ba136583..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/tc.rst +++ /dev/null @@ -1,8 +0,0 @@ -**Exercise SC on inactive pragmas** - -Check that inactive pragmas are ignored; Place Assert pragmas at various -locations in a number of subprogram bodies, and verify that they are never -reported uncovered, even when the subprograms are not called. - -LRMREF: 2.8 - diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/asserts.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.adb similarity index 65% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/asserts.adb rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.adb index 49f4f0106..bfb8973c9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/src/asserts.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.adb @@ -2,15 +2,23 @@ pragma Check_Policy (Assertion, Off); -package body Asserts is +package body Pragmas is + + procedure Log_Debug is + begin + Debug_Events := Debug_Events + 1; -- # log + end; + procedure Sum (X, Y, UB : Integer; R : out Integer) is begin + pragma Debug (Log_Debug); -- # debug pragma Assert (X + Y <= UB); -- # assert R := X + Y; -- # eval end; procedure Dif (X, Y, LB : Integer; R : out Integer) is begin + pragma Debug (Log_Debug); -- # debug R := X - Y; -- # eval pragma Assert (X - Y >= LB); -- # assert end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.ads b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.ads new file mode 100644 index 000000000..d03282781 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.ads @@ -0,0 +1,10 @@ +package Pragmas is + procedure Sum (X, Y, UB : Integer; R : out Integer); + procedure Dif (X, Y, LB : Integer; R : out Integer); + + -- Number of calls to subprogram invoked through pragma + -- Debug. Shoulds remain 0 as we're in a testcase intended to + -- exercise situations where such pragmas are deactivated + -- by a Check_Policy. + Debug_Events : Integer := 0; +end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_0.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_0.adb new file mode 100644 index 000000000..56c62856b --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_0.adb @@ -0,0 +1,21 @@ +with Support, Pragmas; use Pragmas, Support; + +-- Don't call into the functional code. Expect s- only on active lines +-- with real statements, not on the inactive pragma ones. + +procedure Test_Pragmas_0 is +begin + Assert (Pragmas.Debug_Events = 0); +end; + +--# pragmas.adb +-- /eval/ l- ## s- +-- /log/ l- ## s- + +--%opts:--trace-mode=bin +-- /debug/ l. ## 0 +-- /assert/ l. ## 0 + +--%opts:--trace-mode=src +-- /debug/ l- ## s- +-- /assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_t.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_t.adb new file mode 100644 index 000000000..2d704568c --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/test_pragmas_t.adb @@ -0,0 +1,30 @@ +with Support, Pragmas; use Pragmas, Support; + +-- Invoke the two subprograms, each featuring Assert and Debug +-- pragmas. Compilation-wise, the pragmas are inactive and the +-- Log_Debug subprogram is never called. + +-- pragma Debug is perceived as an active "statement" by the +-- source instrumenter, though, and pragma Assert not. + +procedure Test_Pragmas_T is + R : Integer; +begin + Sum (X => 2, Y => 3, UB => 10, R => R); + Assert (R = 5); + Dif (X => 5, Y => 1, LB => 1, R => R); + Assert (R = 4); + Assert (Debug_Events = 0); +end; + +--# pragmas.adb +-- /eval/ l+ ## 0 +-- /log/ l- ## s- + +--%opts:--trace-mode=bin +-- /debug/ l. ## 0 +-- /assert/ l. ## 0 + +--%opts:--trace-mode=src +-- /debug/ l+ ## 0 +-- /assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/tc.rst new file mode 100644 index 000000000..ba25bc6af --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/tc.rst @@ -0,0 +1,10 @@ +**Exercise SC on pragmas deactivated by a Debug or Assertion/Check policy** + +With binary traces, all the pragmas possibly generating code should +not be considered as statements. + +With source traces, the non-Assert pragmas should be considered as +statements despite the Policy deactivating them for compilation purposes. + +LRMREF: 2.8 + diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.py b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/pragmas.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/pragmas.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/pragmas.adb rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/pragmas.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/pragmas.ads b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/pragmas.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/pragmas.ads rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/pragmas.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/support_pragmas.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/support_pragmas.adb similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/support_pragmas.adb rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/support_pragmas.adb diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/support_pragmas.ads b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/support_pragmas.ads similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/support_pragmas.ads rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/support_pragmas.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_assert_debug.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_assert_debug.adb similarity index 71% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_assert_debug.adb rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_assert_debug.adb index ca11eb8d5..b48085c74 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_assert_debug.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_assert_debug.adb @@ -1,6 +1,6 @@ --- Test driver for pragmas. It calls a subprogram that has Precondition and --- Postcondition pragmas associated with it, so these pragmas are expected to --- be reported as covered, and Debug and Assert pragmas - as uncovered. +-- Test driver for pragmas. It calls a subprogram that has +-- Precondition and Postcondition pragmas associated with it and +-- paths to all the Debug and Assert pragmas therein are exercised. with Support; use Support; with Pragmas; use Pragmas; @@ -27,12 +27,20 @@ end Test_Pragmas_Assert_Debug; -- /oneelement/ l+ ## 0 -- /XgtR/ l+ ## 0 -- /XltL/ l+ ## 0 +-- /safedecl/ ~l- ## ~s- +-- /is_safe/ l- ## s- + -- /1debug/ l+ ## 0 -- /2debug/ l+ ## 0 + +--%opts: --trace-mode=bin -- /1assert/ l+ ## 0 -- /2assert/ l+ ## 0 -- /3assert/ l+ ## 0 -- /4assert/ l+ ## 0 --- /safedecl/ ~l- ## ~s- --- /is_safe/ l- ## s- +--%opts: --trace-mode=src +-- /1assert/ l. ## 0 +-- /2assert/ l. ## 0 +-- /3assert/ l. ## 0 +-- /4assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_full.adb similarity index 85% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_full.adb rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_full.adb index efc131937..6ad53e7c6 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_full.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_full.adb @@ -28,11 +28,19 @@ end Test_Pragmas_Full; -- /oneelement/ l+ ## 0 -- /XgtR/ l+ ## 0 -- /XltL/ l+ ## 0 +-- /is_safe/ l+ ## 0 + -- /1debug/ l+ ## 0 -- /2debug/ l+ ## 0 + +--%opts: --trace-mode=bin -- /1assert/ l+ ## 0 -- /2assert/ l+ ## 0 -- /3assert/ l+ ## 0 -- /4assert/ l+ ## 0 --- /is_safe/ l+ ## 0 +--%opts: --trace-mode=src +-- /1assert/ l. ## 0 +-- /2assert/ l. ## 0 +-- /3assert/ l. ## 0 +-- /4assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_no.adb similarity index 83% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_no.adb rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_no.adb index be9fcff48..41fc8ca8d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_no.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_no.adb @@ -25,12 +25,20 @@ end Test_Pragmas_No; -- /oneelement/ l- ## s- -- /XgtR/ l- ## s- -- /XltL/ l- ## s- +-- /safedecl/ ~l- ## ~s- +-- /is_safe/ l- ## s- + -- /1debug/ l- ## s- -- /2debug/ l- ## s- + +--%opts: --trace-mode=bin -- /1assert/ l- ## s- -- /2assert/ l- ## s- -- /3assert/ l- ## s- -- /4assert/ l- ## s- --- /safedecl/ ~l- ## ~s- --- /is_safe/ l- ## s- +--%opts: --trace-mode=src +-- /1assert/ l. ## 0 +-- /2assert/ l. ## 0 +-- /3assert/ l. ## 0 +-- /4assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_pre_post.adb b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_pre_post.adb similarity index 77% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_pre_post.adb rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_pre_post.adb index 200a68534..546baabd4 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Active/src/test_pragmas_pre_post.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/src/test_pragmas_pre_post.adb @@ -25,11 +25,22 @@ end Test_Pragmas_Pre_Post; -- /oneelement/ l- ## s- -- /XgtR/ l- ## s- -- /XltL/ l- ## s- +-- /is_safe/ l+ ## 0 + -- /1debug/ l- ## s- -- /2debug/ l- ## s- + +-- Assert pragmas are activated explicitly in this testcase, +-- but considered always inactive for source traces + +--%opts: --trace-mode=bin -- /1assert/ l- ## s- -- /2assert/ l- ## s- -- /3assert/ l- ## s- -- /4assert/ l- ## s- --- /is_safe/ l+ ## 0 +--%opts: --trace-mode=src +-- /1assert/ l. ## 0 +-- /2assert/ l. ## 0 +-- /3assert/ l. ## 0 +-- /4assert/ l. ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/tc.rst new file mode 100755 index 000000000..dc8440406 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/tc.rst @@ -0,0 +1,9 @@ +**Exercise SC on pragmas activated by a Debug or Assertion/Check policy** + +With binary traces, all the pragmas possibly generating code should +be considered as statements. + +With source traces, the Assert pragmas should not be considered as +statements despite the Policy activating them for compilation purposes. + +LRMREF: 2.8 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/test.py b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/test.py similarity index 100% rename from testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Inactive/test.py rename to testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_On/test.py diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/req.rst index 91350979d..314902891 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/req.rst @@ -6,28 +6,35 @@ SC requirements for Pragmas (ARM 2.8) -Different kinds of pragmas exist, some always active, some possibly ignored -depending on configuration parameters. They may be located in various -contexts, some possibly never elaborated such as as subprogram declarative -parts. - -* Inactive pragmas shall be ignored; - -* Active pragmas that were never elaborated as part of the program execution - shall be reported uncovered. - +Different kinds of pragmas exist, some possibly generating code such +as `Debug` or `Assert` pragmas. From the compiler standpoint, these +are either active or ignored depending on `Assertion_Policy`, +`Check_Policy` controls or alike. For statement coverage analysis, +they shall be considered as statements on their own according to the +following rules: + +- With binary traces, a pragma is considered as a statement in + accordance with the actual Assertion/Debug/Check policy applicable + to the unit where the pragma appears, which makes it active or + inactive from the compiler's standpoint. + +- With source instrumentation, Assert-like pragmas (Assert, + Assert_And_Cut, Check, Precondition/Postcondition, Assume, + Loop_Invariant, Type_Invariant) are never considered as statements + on their own and all the other pragmas are always considered as + statements, regardless of the Assertion/Debug/Check policy applying to + their unit. .. rubric:: Testing Strategy +Exercise Assert, Debug, Precondition and Postcondition pragmas placed +in various source contexts, explicitly either activated or deactivated +by local Check_Policy or Debug_Policy. - -We check this requirement for different kinds of pragmas in various -possible source regions, with the following set of testcases: - +Check that pragmas considered as statements but never elaborated are +reported uncovered and that other pragmas are ignored. .. qmlink:: TCIndexImporter * - - From ed6ed821a3f43d6171c7a50750e81983877a813d Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 22 May 2023 08:34:41 +0200 Subject: [PATCH 0802/1483] Refine command line entry simplification for STR Simplify /possibly/long/path/to/testsuite.py as testsuite.py. Adapt to the switch to e3, which launches testsuite.py with a slightly different sequence of arguments than gnatpython. Part of W227-016 (gnatcov qualkit 1329-W227-016) --- testsuite/STR/genrest.py | 45 +++++++++++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 5 deletions(-) diff --git a/testsuite/STR/genrest.py b/testsuite/STR/genrest.py index 7aecd9e15..328681110 100644 --- a/testsuite/STR/genrest.py +++ b/testsuite/STR/genrest.py @@ -1157,22 +1157,57 @@ def literal(text): text = text.strip() return ":literal:`" + text + "`" if text else "" + def simplify(sw): + """Given a piece of the testuite.py command line used to execute + the qualification test run, return what should be inserted for + it in the list displayed in the STR document, if anything.""" + + # Simplify /path/to/whatever/testsuite.py: + if "testsuite.py" in sw: + return 'testsuite.py' + + # Some switches are entirely meaningless wrt qualification + # and can be omitted from the STR: + if any( + sw.startswith(candidate) + for candidate in [ + "--log-file=", + "--old-output-dir=", + "--output-dir=", + "--failure-exit-code=", + "--gaia-output", + "--dump-environ", + "--generate-text-report", + ] + ): + return None + + return sw + def str_relevant_switches_from(switches_string): """The list of individual pieces in `switches_string` - which are of relevance to this STR document. These are - all the switches except --log-file and --old-res + their - argument, of interest to gaia only.""" + which are of relevance to this STR document.""" result = [] skip = False for sw in switches_string.split(): + + # If we are to skip this arg for a switch to drop + # encountered just before on the command line, do so: if skip: skip = False continue - elif sw in ("--log-file", "--old-res"): + + # If this is a switch to drop with an arg to follow, + # skip this switch and request skipping the arg: + if sw in ["-t"]: skip = True continue - else: + + # Now see if this switch can be simplified, possibly + # even entirely removed: + sw = simplify(sw) + if sw: result.append(sw) return result From ff981543dadcd0c0d02636faba09b2b666c4e680 Mon Sep 17 00:00:00 2001 From: Vasiliy Fofanov Date: Sun, 11 Jun 2023 20:59:33 +0200 Subject: [PATCH 0803/1483] Plans tailoring for TQL-1 qualification use case. For eng/cert/gnatcheck-and-gnatcov-tql-5-qualif-for-airbus#1 --- .../Certification_Credit/content.rst | 6 ++++- .../Compliance/content.rst | 12 +++++----- .../User_Activities/Qualification/content.rst | 24 +++++++++++-------- 3 files changed, 25 insertions(+), 17 deletions(-) diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Certification_Credit/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/Certification_Credit/content.rst index 1f0923432..735ebe886 100644 --- a/qualification/qm/plans/Tool_Qualification_Plan/Certification_Credit/content.rst +++ b/qualification/qm/plans/Tool_Qualification_Plan/Certification_Credit/content.rst @@ -5,7 +5,11 @@ Sought Certification Credit GNATcoverage aims at automating the Structural Coverage Analysis activities required by the Software Verification Process of |standard|, in section -6.4.4.2 and table A-7, objectives 5, 6 and 7 depending on the software level. +6.4.4.2 and table A-7, objectives 5, 6 and 7 depending on the software level; +or Structural Coverage Analysis activities +required by the Tool Verification Process of |tool_standard|, in section +6.1.4.3 and table T-7, objectives 6, 7 and 8 depending on the qualification level. + Any coverage limitations are enumerated in section *Language Version and Scope* of the |tor_doc_title| document; it is the user's responsibility to assure that the code subject to analysis conforms to what this qualification diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Compliance/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/Compliance/content.rst index c9d3a4eb3..d69e77425 100644 --- a/qualification/qm/plans/Tool_Qualification_Plan/Compliance/content.rst +++ b/qualification/qm/plans/Tool_Qualification_Plan/Compliance/content.rst @@ -2,17 +2,17 @@ Compliance With Guidance ======================== This section contains the compliance matrices with the guidance contained in -section 12.2 of [|standard|] and section 11.3.2 of [|tool_standard|] from a -Tool Developer's perspective. +section 12.2 of [|standard|] (or Appendix B of [|tool_standard|], as appropriate) +and section 11.3.2 of [|tool_standard|]. .. tabularcolumns:: |p{0.15\linewidth}|p{0.10\linewidth}|p{0.65\linewidth}| -.. csv-table:: Compliance with Section 12.2 of |standard| +.. csv-table:: Compliance with Section 12.2 of |standard| or Appendix B of |tool_standard|, as appropriate :delim: # :header: "Section", "Achieved", "Notes" - 12.2.1 #Yes#GNATcoverage qualification is needed. See :ref:`certification-credit`. - 12.2.2 #Yes#GNATcoverage qualification level is **TQL-5** for all software levels. See :ref:`tql`. + 12.2.1 or Appendix B #Yes#GNATcoverage qualification is needed. See :ref:`certification-credit`. + 12.2.2 or Appendix B #Yes#GNATcoverage impact corresponds to **Criteria 3**. According to Table 12-1 Tool Qualification Level is **TQL-5** for all software and assurance levels. See :ref:`tql`. .. tabularcolumns:: |p{0.15\linewidth}|p{0.18\linewidth}|p{0.60\linewidth}| @@ -23,7 +23,7 @@ Tool Developer's perspective. T-0, Objectives 1, 3, 6, 7 # Not applicable # Apply to Tool User, not to Tool Developer per section 11.3 of |tool_standard|. T-0, Objective 2 # Yes # See the requirement description items in the |tor_doc| document. - T-0, Objective 4 # Not Applicable # Not required for TQL-5. See :ref:`tqap` for AdaCore's QA procedures nevertheless. + T-0, Objective 4 # Not Applicable # Not required for TQL-5. Nevertheless, see :ref:`tqap` for AdaCore's QA procedures. T-0, Objective 5 # Yes # See the test and test-cases description items in the |tor_doc| document. T-1 to T-7 # Not Applicable # Not required for TQL-5. T-8 # Up to the applicant # See :ref:`user-conf-management` for suggested configuration items. diff --git a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst index f9cfb502c..d623b53f7 100644 --- a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst +++ b/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst @@ -2,16 +2,18 @@ ============================ #. **Reference** |project_name_bold| **in the Plan for Software Aspects of - Certification (PSAC)**. The user needs to: + Certification (PSAC) and, if appropriate, in Tool Qualification Plan**. + The user needs to: - * Identify |project_name| as a verification tool that needs to be - qualified; + * identify |project_name| as a TQL-5 tool with regard to software level + A, B, and C, or with regard to tool qualification level 1, 2, and 3, + whichever is appropriate, that needs to be qualified; * Include references to the |project_name| qualification kit documents that were received to support this particular use of the tool. #. **Delivery Acceptance.** On delivery of |project_name| and its - qualification kit, the user shall + qualification kit, the user shall: * Assess whether the qualified Operational Environment is representative of the user's Operational Environment; @@ -30,14 +32,16 @@ #. **Obtain a tool qualification agreement**, see section 9.0.b of |tool_standard|. -#. **Update Environment Configuration Index (SECI).** Refer to the - |project_name| qualification kit for details associated with its - environment configuration. +#. **Update the Software or Tool Life Cycle Environment Configuration Index.** + Refer to the |project_name| qualification kit for details associated with + its environment configuration. -#. **Update the Software Accomplishment Summary (SAS).** The SAS needs to be - updated: +#. **Update the Software or Tool Accomplishment Summary (SAS or TAS).** + The SAS/TAS needs to be updated: * For Table A-7 of |standard|: achievement of the objectives 5, 6 and 7, - depending on the software level. + depending on the software level; or for Table T-7 of |tool_standard|: + achievement of the objectives 6, 7 and 8, depending on the qualification + level (as appropriate). * For qualification status of |project_name|: refer to |str_doc| report. From 7cb6e5812980cd86d8b4f030bbcbec1918ac5e7c Mon Sep 17 00:00:00 2001 From: Vasiliy Fofanov Date: Mon, 12 Jun 2023 11:32:54 +0000 Subject: [PATCH 0804/1483] Fix normative refs in Tool Qualification Plan --- .../Tool_Qualification_Plan/Compliance/content.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Compliance/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/Compliance/content.rst index d69e77425..9336a1b6f 100644 --- a/qualification/qm/plans/Tool_Qualification_Plan/Compliance/content.rst +++ b/qualification/qm/plans/Tool_Qualification_Plan/Compliance/content.rst @@ -2,18 +2,18 @@ Compliance With Guidance ======================== This section contains the compliance matrices with the guidance contained in -section 12.2 of [|standard|] (or Appendix B of [|tool_standard|], as appropriate) +section 12.2 of [|standard|] (or section 4.4(e) of [|tool_standard|], as appropriate) and section 11.3.2 of [|tool_standard|]. .. tabularcolumns:: |p{0.15\linewidth}|p{0.10\linewidth}|p{0.65\linewidth}| -.. csv-table:: Compliance with Section 12.2 of |standard| or Appendix B of |tool_standard|, as appropriate +.. csv-table:: Compliance with Section 12.2 of |standard| or section 4.4(e) of |tool_standard|, as appropriate :delim: # :header: "Section", "Achieved", "Notes" - 12.2.1 or Appendix B #Yes#GNATcoverage qualification is needed. See :ref:`certification-credit`. - 12.2.2 or Appendix B #Yes#GNATcoverage impact corresponds to **Criteria 3**. According to Table 12-1 Tool Qualification Level is **TQL-5** for all software and assurance levels. See :ref:`tql`. - + 12.2.1 or 4.4(e) #Yes#GNATcoverage qualification is needed. See :ref:`certification-credit`. + 12.2.2 #Yes#GNATcoverage impact corresponds to **Criteria 3**. According to Table 12-1 Tool Qualification Level is **TQL-5** for all assurance levels. See :ref:`tql`. + 4.4(e) #Yes#GNATcoverage is a tool that cannot introduce an error in the output of the qualified tool, but may fail to detect an error in the tool life cycle data, hence the applicable TQL is **TQL-5**. See :ref:`tql` .. tabularcolumns:: |p{0.15\linewidth}|p{0.18\linewidth}|p{0.60\linewidth}| From fa302179786a1b91a51d53ba852f578fb0e6602c Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 12 Jun 2023 14:43:18 +0200 Subject: [PATCH 0805/1483] Refine use of |today| and |release| in doc history entries Fix delimiter in the sources for the PLANS document and introduce the macros in the sources for the TOR document. Part of W227-016 (qualkit-1329-W227-016) --- qualification/qm/plans/content.rst | 2 +- testsuite/Qualif/content.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qualification/qm/plans/content.rst b/qualification/qm/plans/content.rst index 99f71ef39..41b2e5526 100644 --- a/qualification/qm/plans/content.rst +++ b/qualification/qm/plans/content.rst @@ -5,7 +5,7 @@ GNATcoverage - |standard| Qualification Material: |plans_doc_title| .. rubric:: Revision History .. csv-table:: - :delim: | + :delim: & :header: "Version #", "Date", "Comment" |release| & |today| & Initial version diff --git a/testsuite/Qualif/content.rst b/testsuite/Qualif/content.rst index bdac324ad..1be316087 100644 --- a/testsuite/Qualif/content.rst +++ b/testsuite/Qualif/content.rst @@ -18,10 +18,10 @@ GNATcoverage - |standard| Qualification Material: |tor_doc_title| .. rubric:: Revision History .. csv-table:: - :delim: | + :delim: & :header: "Version #", "Date", "Comment" - DRAFT 0.0 | | Draft for interim delivery, pre internal QA + |release| & |today| & Latest revision .. only:: html From cec91d4291ec32d02cfe11a04ec08f0240e70156 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 12 Jun 2023 17:37:31 +0200 Subject: [PATCH 0806/1483] Remove reviewers from the list of relevant roles Listing the reviewers is not mandatory and removing the list simplifies the production process. Part of W227-016 (qualkit-1329-W227-016) --- qualification/qm/common_conf.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/qualification/qm/common_conf.py b/qualification/qm/common_conf.py index 53b0ce2b6..bfa632e5a 100644 --- a/qualification/qm/common_conf.py +++ b/qualification/qm/common_conf.py @@ -41,11 +41,10 @@ roles = OrderedDict( [ ("authors", {"description": "the authors of the document"}), - ("reviewers", {"description": "the reviewers of the document"}), ] ) -assignments = {"authors": ["hainque"], "reviewers": ["unassigned"]} +assignments = {"authors": ["hainque"]} release = "DRAFT 0.0" version = "(version %s)" % release From e3bc1c78e9ba776ceb3fb52be1e63c8ffd9a9053 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Thu, 15 Jun 2023 13:33:30 +0200 Subject: [PATCH 0807/1483] STR conf.py set latex_elements['preeamble'] from latex_preamble This makes the STR latex_preamble visible to our current version of sphinx and restores the display of the document identifier in footers. --- testsuite/STR/conf.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/testsuite/STR/conf.py b/testsuite/STR/conf.py index d262d5bb7..73117c9cb 100644 --- a/testsuite/STR/conf.py +++ b/testsuite/STR/conf.py @@ -326,6 +326,9 @@ def project_settings(): """ ) +latex_elements = { + 'preamble' : latex_preamble +} # Documents to append as an appendix to all manuals. # latex_appendices = [] From cd1ab7c26e950a2723d0b26de685dd6d76ffc971 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Thu, 15 Jun 2023 18:25:42 +0200 Subject: [PATCH 0808/1483] Add common_conf.py variables for versions used in document refs At the same spot where we currently have doc identifiers, so we think of updating them at the same time. Stick intended values for the current project there. Later on, we'll want these instantiated from the environment but that's a more involved change, not for the current cycle. --- qualification/qm/common_conf.py | 8 ++++++++ .../plans/Introduction/Referenced_Documents/content.rst | 8 ++++---- qualification/qm/qm_prolog.py | 3 +++ 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/qualification/qm/common_conf.py b/qualification/qm/common_conf.py index bfa632e5a..1133511cb 100644 --- a/qualification/qm/common_conf.py +++ b/qualification/qm/common_conf.py @@ -53,6 +53,14 @@ extensions = ["sphinx.ext.ifconfig"] +# Parameters - which could be templated and instantiated +# from parameters known at higher levels of the kit production +# process: + tor_doc_id = "PE." str_doc_id = "PE." plans_doc_id = "PE." + +gnatpro_version = "GNATPRO.X" +gprbuild_version = "GPRBUILD.Y" +gnatcov_version = "GNATCOV.Z" diff --git a/qualification/qm/plans/Introduction/Referenced_Documents/content.rst b/qualification/qm/plans/Introduction/Referenced_Documents/content.rst index b822f34e1..e12485a96 100644 --- a/qualification/qm/plans/Introduction/Referenced_Documents/content.rst +++ b/qualification/qm/plans/Introduction/Referenced_Documents/content.rst @@ -25,13 +25,13 @@ for Safety-Critical Applications* - ERTS2 2010 .. rubric:: GNAT Pro UG -AdaCore: *GNAT User's Guide for Native Platforms*, part of the GNAT Pro 7.4.3 -release documentation (file *share/doc/gnat/pdf/gnat_ugn.pdf*). +AdaCore: *GNAT User's Guide for Native Platforms*, part of the GNAT Pro +|gnatpro_version| release documentation (file *share/doc/gnat/pdf/gnat_ugn.pdf*). .. rubric:: GNATcoverage UG -AdaCore: *GNATcoverage User's Guide*, part of the GNATcoverage 1.4.3 release -documentation (file *share/doc/gnatdas/pdf/gnatdas.pdf*). +AdaCore: *GNATcoverage User's Guide*, part of the GNATcoverage +|gnatcov_version| release documentation (file *share/doc/gnatdas/pdf/gnatdas.pdf*). .. rubric:: |plans_doc_title| diff --git a/qualification/qm/qm_prolog.py b/qualification/qm/qm_prolog.py index 01b582b46..79b275923 100644 --- a/qualification/qm/qm_prolog.py +++ b/qualification/qm/qm_prolog.py @@ -45,6 +45,9 @@ + writer.macro("plans_doc_id", r"*" + plans_doc_id + r"*") + writer.macro("tor_doc_id", r"*" + tor_doc_id + r"*") + writer.macro("str_doc_id", r"*" + str_doc_id + r"*") + + writer.macro("gnatcov_version", r"%s" % gnatcov_version) \ + + writer.macro("gnatpro_version", r"%s" % gnatpro_version) \ + + writer.macro("gprbuild_version", r"%s" % gprbuild_version) \ + writer.macro("opcond_section_title", r"%s" % opcond_section_title) + writer.macro("opcond_section_title_ref", r"*%s*" % opcond_section_title) + writer.macro("torintro_section_title", r"%s" % torintro_section_title) From 3728d3e50ffe878a7dbb33582a633086a1e46f9e Mon Sep 17 00:00:00 2001 From: Josue NAVA BELLO Date: Wed, 5 Jul 2023 09:45:15 +0200 Subject: [PATCH 0809/1483] update Change Control in PLAN to AWS backup instead of local backup --- .../Developer/Methods_And_Activities/content.rst | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst b/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst index 1dd208291..37028cf65 100644 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst +++ b/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst @@ -20,12 +20,14 @@ AdaCore ticket system deployed within the whole company since 1998. Change control -------------- -Integrity of configuration items is guaranteed by the Git -repositories where all configuration items are located. Only authorized -engineers can modify configuration items and all modifications are -recorded. In addition, all repositories and mail servers are mirrored with -machines physically located in Paris (France) and New York. This increases -confidence in the durability of qualification data (activity 7.2.4.a). +Integrity of configuration items is guaranteed by Git repositories where all +configuration items are located. Only authorized engineers can modify +configuration items and all modifications are recorded. The sources and scripts +for the AdaCore products are maintained in Git repositories that are completely +backed up at least every 2 hours. All repositories are stored electronically +and are backed up to geographically isolated locations in AWS (in EU and US). +This increases AdaCore's confidence in the durability of qualification data +(activity 7.2.4.a). Each change to a configuration item is associated to a unique ID, which unambiguously identifies the version of a configuration item over From c9501da1c98aee11d8c1669c6679f0a39be44f2a Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Wed, 27 Mar 2024 13:16:29 +0100 Subject: [PATCH 0810/1483] Straigthen formatting and flake8 rules after chain of changes --- qualification/genbundle.py | 23 ++++++++++++++--------- qualification/qm/qm_prolog.py | 6 +++--- testsuite/SCOV/internals/driver.py | 3 ++- testsuite/STR/conf.py | 16 +++++++--------- testsuite/STR/genrest.py | 27 +++++++++++++-------------- testsuite/SUITE/qdata.py | 8 +++++--- 6 files changed, 44 insertions(+), 39 deletions(-) diff --git a/qualification/genbundle.py b/qualification/genbundle.py index c9e50c86c..7608812cd 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -445,9 +445,15 @@ def log(self, line): def rsync_from(self, rsync_source): run_list( - ["rsync", "-ar", rsync_source + '/', self.repodir + '/', - '--delete', '--delete-excluded', - '--filter', '. dev.rsync', + [ + "rsync", + "-ar", + rsync_source + "/", + self.repodir + "/", + "--delete", + "--delete-excluded", + "--filter", + ". dev.rsync", ] ) @@ -456,7 +462,6 @@ def rsync_from(self, rsync_source): # ---------------- def git_update(self): - # If we're requested to pull/update only, do so if self.o.gitpull: @@ -975,8 +980,8 @@ def build_kit(self): gitbranch = current_gitbranch_at(self.repodir) kitid = gitbranch.replace("qualkit-", "") - kitid = kitid.replace('/', '-') - kitid = kitid.replace('.', '_') + kitid = kitid.replace("/", "-") + kitid = kitid.replace(".", "_") # If we are re-constructing a kit with some parts just rebuilt, target # the specified version (stamp) and arrange to keep the old elements @@ -1126,12 +1131,12 @@ def commandline(): default=None, help=("The git branch we shall produce the material from."), ) - op.add_option ( + op.add_option( "--kitid", dest="kitid", default=False, - help=("Use the provided argument as the kit identifier.") - ) + help=("Use the provided argument as the kit identifier."), + ) op.add_option( "--docformat", diff --git a/qualification/qm/qm_prolog.py b/qualification/qm/qm_prolog.py index 79b275923..8350484d3 100644 --- a/qualification/qm/qm_prolog.py +++ b/qualification/qm/qm_prolog.py @@ -45,9 +45,9 @@ + writer.macro("plans_doc_id", r"*" + plans_doc_id + r"*") + writer.macro("tor_doc_id", r"*" + tor_doc_id + r"*") + writer.macro("str_doc_id", r"*" + str_doc_id + r"*") - + writer.macro("gnatcov_version", r"%s" % gnatcov_version) \ - + writer.macro("gnatpro_version", r"%s" % gnatpro_version) \ - + writer.macro("gprbuild_version", r"%s" % gprbuild_version) \ + + writer.macro("gnatcov_version", r"%s" % gnatcov_version) + + writer.macro("gnatpro_version", r"%s" % gnatpro_version) + + writer.macro("gprbuild_version", r"%s" % gprbuild_version) + writer.macro("opcond_section_title", r"%s" % opcond_section_title) + writer.macro("opcond_section_title_ref", r"*%s*" % opcond_section_title) + writer.macro("torintro_section_title", r"%s" % torintro_section_title) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index a9cfd568f..8d7d99904 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -1420,7 +1420,8 @@ def mode_build(self): gpr_obj_dir=self.gpr_obj_dir, out=out, register_failure=True, - tolerate_messages=self.testcase.tolerate_messages) + tolerate_messages=self.testcase.tolerate_messages, + ) # When exception propagation is not available, a test ending with an # unhandled exception goes straight to the last_chance_handler from diff --git a/testsuite/STR/conf.py b/testsuite/STR/conf.py index 73117c9cb..46e161ef9 100644 --- a/testsuite/STR/conf.py +++ b/testsuite/STR/conf.py @@ -21,15 +21,15 @@ work_dir = os.path.join( os.path.dirname( - os.path.dirname( - os.path.dirname( - os.path.abspath(__file__)))) + os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + ) ) common_conf_glob = f"{work_dir}/*/qualification/qm/common_conf.py" common_conf_candidates = glob.glob(common_conf_glob) -assert len(common_conf_candidates) == 1, \ - f"{__file__} couldn't locate lone common_conf.py out of {common_conf_glob}" +assert ( + len(common_conf_candidates) == 1 +), f"{__file__} couldn't locate lone common_conf.py out of {common_conf_glob}" common_conf_py = common_conf_candidates[0] exec(open(common_conf_py).read()) @@ -104,7 +104,7 @@ # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -html_theme_options = {'body_max_width': None} +html_theme_options = {"body_max_width": None} # Add any paths that contain custom themes here, relative to this directory. # html_theme_path = [] @@ -326,9 +326,7 @@ def project_settings(): """ ) -latex_elements = { - 'preamble' : latex_preamble -} +latex_elements = {"preamble": latex_preamble} # Documents to append as an appendix to all manuals. # latex_appendices = [] diff --git a/testsuite/STR/genrest.py b/testsuite/STR/genrest.py index 328681110..d4ada784b 100644 --- a/testsuite/STR/genrest.py +++ b/testsuite/STR/genrest.py @@ -147,9 +147,9 @@ def load_test(self, dirname): qda = Qdata(tcid=dirname) for tcdf in tcdfs: - sub_qda = dutils.pload_from (tcdf) + sub_qda = dutils.pload_from(tcdf) for entry in sub_qda.entries: - qda.register (entry) + qda.register(entry) qda.status = std.status qda.comment = std.comment @@ -1164,21 +1164,21 @@ def simplify(sw): # Simplify /path/to/whatever/testsuite.py: if "testsuite.py" in sw: - return 'testsuite.py' + return "testsuite.py" # Some switches are entirely meaningless wrt qualification # and can be omitted from the STR: if any( sw.startswith(candidate) - for candidate in [ - "--log-file=", - "--old-output-dir=", - "--output-dir=", - "--failure-exit-code=", - "--gaia-output", - "--dump-environ", - "--generate-text-report", - ] + for candidate in [ + "--log-file=", + "--old-output-dir=", + "--output-dir=", + "--failure-exit-code=", + "--gaia-output", + "--dump-environ", + "--generate-text-report", + ] ): return None @@ -1191,7 +1191,6 @@ def str_relevant_switches_from(switches_string): result = [] skip = False for sw in switches_string.split(): - # If we are to skip this arg for a switch to drop # encountered just before on the command line, do so: if skip: @@ -1199,7 +1198,7 @@ def str_relevant_switches_from(switches_string): continue # If this is a switch to drop with an arg to follow, - # skip this switch and request skipping the arg: + # skip this switch and request skipping the arg: if sw in ["-t"]: skip = True continue diff --git a/testsuite/SUITE/qdata.py b/testsuite/SUITE/qdata.py index 0661057ba..0b5f855c9 100644 --- a/testsuite/SUITE/qdata.py +++ b/testsuite/SUITE/qdata.py @@ -172,14 +172,16 @@ def qdafs_from(dirname): together with their dischargers. """ return [ - os.path.join(dir, file) - for (dir, _, files) in os.walk(dirname) - for file in files if file == QUALDATA_FILE + os.path.join(d, f) + for (d, _, files) in os.walk(dirname) + for f in files + if f == QUALDATA_FILE ] STATUSDATA_FILE = "tcs" + STREXT + def stdf_in(dirname): """Filename for execution status data to be picked up DIR""" return os.path.join(dirname, STATUSDATA_FILE) From e1d1ea3517141f47d6f0a1aca235eaec2005431f Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Mon, 8 Apr 2024 12:09:15 +0200 Subject: [PATCH 0811/1483] Prevent local subprogram optimization on Qualif/.../Pragmas/Policy_Off A subprogram only called through "pragma Debug" statements is never actually called when testing with the pragma Assertion_Policy off. When the subprogram is local to a unit, optimization just gets rid of the corresponding code entirely and the corresponding statements are reported "no code" with binary traces. This change just exposes the said subprogram to prevent the removal, allowing consistent expectations across trace and optimization modes. --- .../02_LexicalElements/Pragmas/Policy_Off/src/pragmas.ads | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.ads b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.ads index d03282781..e0c224e9e 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.ads +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/Policy_Off/src/pragmas.ads @@ -7,4 +7,10 @@ package Pragmas is -- exercise situations where such pragmas are deactivated -- by a Check_Policy. Debug_Events : Integer := 0; + + procedure Log_Debug; + -- Register a Debug_Event. Exposed to prevent removal of the + -- entire subprogram by optimization when it happens to be + -- never called, which would make it "no code" for binary traces. + end; From 97c43c97359e3470fef273ddbf6e2cafcbb8cffa Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 12 Apr 2024 11:43:04 +0200 Subject: [PATCH 0812/1483] Instrument: Fix import of compiler switches gnatcov now considers compiler switches specified through the Compiler.Switches attribute indexed by the language string. Enhance the existing test to consider all possible combinations. --- testsuite/SUITE/tutils.py | 32 +++++----- testsuite/tests/instr-cov/c_gpr_opts/hello.c | 13 ---- testsuite/tests/instr-cov/c_gpr_opts/main.c | 20 ------ testsuite/tests/instr-cov/c_gpr_opts/test.py | 39 ------------ .../src-c++/main.cpp | 17 ++++++ .../compiler_switches_gpr_opts/src-c/main.c | 17 ++++++ .../compiler_switches_gpr_opts/test.opt | 1 + .../compiler_switches_gpr_opts/test.py | 61 +++++++++++++++++++ tools/gnatcov/instrument-projects.adb | 13 +++- 9 files changed, 126 insertions(+), 87 deletions(-) delete mode 100644 testsuite/tests/instr-cov/c_gpr_opts/hello.c delete mode 100644 testsuite/tests/instr-cov/c_gpr_opts/main.c delete mode 100644 testsuite/tests/instr-cov/c_gpr_opts/test.py create mode 100644 testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c++/main.cpp create mode 100644 testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c/main.c create mode 100644 testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.opt create mode 100644 testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.py diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 7c7d4ae89..d0a29386c 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -509,21 +509,25 @@ def gprfor( # for Switches("test_blob.adb") use # Compiler'Default_Switches("Ada") & ("-fno-inline") - compswitches = ( - "\n".join( - [ - 'for Switches("%s") use \n' - ' Compiler\'Default_Switches ("%s") & (%s);' - % ( - main, - language_info(main).name, - ",".join(['"%s"' % carg for carg in to_list(main_cargs)]), - ) - for main in mains - ] + compswitches = "" + if main_cargs: + compswitches = ( + "\n".join( + [ + 'for Switches("%s") use \n' + ' Compiler\'Default_Switches ("%s") & (%s);' + % ( + main, + language_info(main).name, + ",".join( + ['"%s"' % carg for carg in to_list(main_cargs)] + ), + ) + for main in mains + ] + ) + + "\n" ) - + "\n" - ) # Now instanciate, dump the contents into the target gpr file and return gprtext = template % { diff --git a/testsuite/tests/instr-cov/c_gpr_opts/hello.c b/testsuite/tests/instr-cov/c_gpr_opts/hello.c deleted file mode 100644 index a2affa303..000000000 --- a/testsuite/tests/instr-cov/c_gpr_opts/hello.c +++ /dev/null @@ -1,13 +0,0 @@ -extern void dummy_putf (const char *fmt, ...); - -void -hello (const char *who) -{ -#ifdef A - dummy_putf ("Hello %s\n", who); -#endif - -#ifdef B - dummy_putf ("Goodbye %s\n", who); -#endif -} diff --git a/testsuite/tests/instr-cov/c_gpr_opts/main.c b/testsuite/tests/instr-cov/c_gpr_opts/main.c deleted file mode 100644 index 4af127a44..000000000 --- a/testsuite/tests/instr-cov/c_gpr_opts/main.c +++ /dev/null @@ -1,20 +0,0 @@ -extern void hello (const char *who); - -void -dummy_putf (const char *fmt, ...) -{ -} - -int -main (void) -{ -#ifdef A - hello ("A"); -#endif - -#ifdef B - hello ("B"); -#endif - - return 0; -} diff --git a/testsuite/tests/instr-cov/c_gpr_opts/test.py b/testsuite/tests/instr-cov/c_gpr_opts/test.py deleted file mode 100644 index 3a36d154b..000000000 --- a/testsuite/tests/instr-cov/c_gpr_opts/test.py +++ /dev/null @@ -1,39 +0,0 @@ -""" -Check that compiler switches are properly imported from project files. -""" - -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -from SUITE.context import thistest -from SUITE.cutils import Wdir -from SUITE.tutils import gprfor -from SUITE.gprutils import GPRswitches - - -tmp = Wdir("tmp_") - -build_run_and_coverage( - gprsw=GPRswitches( - root_project=gprfor( - srcdirs=[".."], - mains=["main.c"], - compiler_extra=""" - for Default_Switches ("C") use ("-DA"); - for Switches ("main.c") use ("-DB"); - """, - ), - ), - covlevel="stmt", - mains=["main"], - extra_coverage_args=["-axcov", "--output-dir=xcov"], - trace_mode="src", -) - -check_xcov_reports( - "xcov", - { - "main.c.xcov": {"+": {16, 19}}, - "hello.c.xcov": {"+": {7}}, - }, -) - -thistest.result() diff --git a/testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c++/main.cpp b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c++/main.cpp new file mode 100644 index 000000000..17dd56060 --- /dev/null +++ b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c++/main.cpp @@ -0,0 +1,17 @@ +#ifndef A +#error +#endif + +#ifndef B +#error +#endif + +#ifdef C +#error +#endif + +int +main (void) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c/main.c b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c/main.c new file mode 100644 index 000000000..17dd56060 --- /dev/null +++ b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/src-c/main.c @@ -0,0 +1,17 @@ +#ifndef A +#error +#endif + +#ifndef B +#error +#endif + +#ifdef C +#error +#endif + +int +main (void) +{ + return 0; +} diff --git a/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.opt b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.opt new file mode 100644 index 000000000..ee85ccc4c --- /dev/null +++ b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.opt @@ -0,0 +1 @@ +!C++ DEAD Test requires a C++ compiler diff --git a/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.py b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.py new file mode 100644 index 000000000..35c74eaea --- /dev/null +++ b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.py @@ -0,0 +1,61 @@ +""" +Check that compiler switches are properly imported from project files. +GNATcoverage used to ignore Compiler.Switches when it was used to specify +language specific compiler switches. +""" + +from SCOV.minicheck import xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") +xcov_args = ["instrument", "--level=stmt"] + + +def check_lang(lang, file_ext): + def gprfor_wrapper(prjid, compiler_extra): + return gprfor( + prjid=prjid, + srcdirs=[f"../src-{lang}"], + mains=[f"main.{file_ext}"], + compiler_extra=compiler_extra, + ) + + # Check using the Compiler.Default_Switches attribute for language specific + # compiler switches. + prj_lds = gprfor_wrapper( + prjid=f"lang_default_switches_{file_ext}", + compiler_extra=f""" + for Default_Switches ("{lang}") use ("-DA", "-DB"); + """, + ) + xcov(xcov_args + ["-P", prj_lds]) + + # Check using the Compiler.Switches attribute for language specific + # compiler switches. + prj_ls = gprfor_wrapper( + prjid=f"lang_switches_{file_ext}", + compiler_extra=f""" + for Switches ("{lang}") use ("-DA", "-DB"); + """, + ) + xcov(xcov_args + ["-P", prj_ls]) + + # Check using the Compiler.Switches attribute both for file specific + # compiler switches. + prj_fs = gprfor_wrapper( + prjid=f"file_switches_{file_ext}", + compiler_extra=f""" + for Default_Switches ("{lang}") use ("-DC"); + for Switches ("{lang}") use ("-DC"); + for Switches ("main.{file_ext}") use ("-DA", "-DB"); + """, + ) + xcov(xcov_args + ["-P", prj_fs]) + + +check_lang("c", "c") +check_lang("c++", "cpp") + +thistest.result() diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 971ee8a77..f10d50bb2 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -364,12 +364,23 @@ is -- fill the compilation unit specific switches that will override -- the project defaults, if there are any (see -- Add_Instrumented_Unit). + -- + -- Language specific switches can be specified through the + -- Compiler.Switches or the Compiler.Default_Switches attribute, + -- the former being prioritized over the latter. Switches := Prj.Attribute_Value - (Attribute => GPR.Compiler_Default_Switches_Attribute, + (Attribute => GPR.Build ("compiler", "switches"), Index => Image (Lang)); + if Switches = null then + Switches := + Prj.Attribute_Value + (Attribute => GPR.Compiler_Default_Switches_Attribute, + Index => Image (Lang)); + end if; + -- If we manage to find appropriate switches, convert them to a -- string vector import the switches. From 09f70797dae6cdb4a36daaaa6c5e573e8b84fedf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20AMIARD?= Date: Tue, 19 Mar 2024 14:13:26 +0000 Subject: [PATCH 0813/1483] Adapt to changes in LAL/Langkit related to Symbol_Type Symbol_Type is now a private type, where it was an access type before. Instances of null have to be replaced with No_Symbol (cherry picked from commit b6426cba7ede6731016e6928e1f3d03a7bba6592) --- tools/gnatcov/instrument-ada_unit.adb | 36 +++++++++++++-------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index ad5b541e6..d3626f675 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1053,7 +1053,7 @@ package body Instrument.Ada_Unit is -- Return whether the given unit exists Pragma_Restricts_Finalization_Matchers : constant Pragma_Matcher_Array := - ((As_Symbol (Restrictions), null, As_Symbol (No_Finalization)), + ((As_Symbol (Restrictions), No_Symbol, As_Symbol (No_Finalization)), (As_Symbol (Restrictions), As_Symbol (No_Dependence), As_Symbol ("ada.finalization"))); @@ -1066,8 +1066,8 @@ package body Instrument.Ada_Unit is -- or the whole project. Pragma_Prevents_Task_Termination_Matchers : constant Pragma_Matcher_Array := - ((As_Symbol (Restrictions), null, As_Symbol (No_Finalization)), - (As_Symbol (Restrictions), null, As_Symbol (No_Tasking)), + ((As_Symbol (Restrictions), No_Symbol, As_Symbol (No_Finalization)), + (As_Symbol (Restrictions), No_Symbol, As_Symbol (No_Tasking)), (As_Symbol (Restrictions), As_Symbol (No_Dependence), As_Symbol ("ada.task_termination")), @@ -1085,13 +1085,13 @@ package body Instrument.Ada_Unit is -- project or in Unit. Pragma_Restricts_Entry_Guards_Matchers : constant Pragma_Matcher_Array := - ((As_Symbol (Restrictions), null, As_Symbol (Pure_Barriers)), - (As_Symbol (Restrictions), null, As_Symbol (Simple_Barriers)), - (As_Symbol (Profile), null, As_Symbol (GNAT_Extended_Ravenscar)), - (As_Symbol (Profile), null, As_Symbol (GNAT_Ravenscar_EDF)), - (As_Symbol (Profile), null, As_Symbol (Jorvik)), - (As_Symbol (Profile), null, As_Symbol (Ravenscar)), - (As_Symbol (Profile), null, As_Symbol (Restricted))); + ((As_Symbol (Restrictions), No_Symbol, As_Symbol (Pure_Barriers)), + (As_Symbol (Restrictions), No_Symbol, As_Symbol (Simple_Barriers)), + (As_Symbol (Profile), No_Symbol, As_Symbol (GNAT_Extended_Ravenscar)), + (As_Symbol (Profile), No_Symbol, As_Symbol (GNAT_Ravenscar_EDF)), + (As_Symbol (Profile), No_Symbol, As_Symbol (Jorvik)), + (As_Symbol (Profile), No_Symbol, As_Symbol (Ravenscar)), + (As_Symbol (Profile), No_Symbol, As_Symbol (Restricted))); -- Matchers for Restrictions pragmas that restrict entry guards so that we -- cannot instrument them as decisions (Pure_Barriers and Simple_Barriers, -- plus various Ada runtime profiles). @@ -3748,7 +3748,7 @@ package body Instrument.Ada_Unit is (if Prag_Arg_Expr (Prag_Args, I).Kind = Libadalang.Common.Ada_Identifier then As_Symbol (Prag_Arg_Expr (Prag_Args, I).As_Identifier) - else null); + else No_Symbol); -- Attempt to get the pragma's Ith argument as an identifier. If -- it is not an identifier, return null. Else, return the identifier -- as a symbol. @@ -3781,9 +3781,7 @@ package body Instrument.Ada_Unit is Report (N, "Invalid Xcov annotation kind" - & (if Kind /= null - then ": " & Image (Kind) - else ""), + & (if Kind /= No_Symbol then ": " & Image (Kind) else ""), Warning); return; end; @@ -6613,7 +6611,7 @@ package body Instrument.Ada_Unit is function As_Symbol (E : Expr) return Symbol_Type is begin if E.Is_Null then - return null; + return No_Symbol; end if; case Ada_Expr (E.Kind) is @@ -6626,8 +6624,8 @@ package body Instrument.Ada_Unit is Prefix : constant Symbol_Type := As_Symbol (DN.F_Prefix.As_Expr); begin - return (if Prefix = null - then null + return (if Prefix = No_Symbol + then No_Symbol else Find (Symbols, Image (Prefix) @@ -6636,7 +6634,7 @@ package body Instrument.Ada_Unit is end; when others => - return null; + return No_Symbol; end case; end As_Symbol; @@ -6655,7 +6653,7 @@ package body Instrument.Ada_Unit is A : constant Pragma_Argument_Assoc := Assoc.As_Pragma_Argument_Assoc; begin - if Matcher.Assoc_Name = null then + if Matcher.Assoc_Name = No_Symbol then -- We expect an "Expr_Name" expression From 3df4296624394db75b1fb76b1b071e23d0e30845 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 12 Apr 2024 16:54:39 +0200 Subject: [PATCH 0814/1483] Address new compiler warning (cherry picked from commit 4b2ca7fce257c00c17914d7fadc66e9f180c86c8) --- tools/gnatcov/qemu_traces.ads | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/qemu_traces.ads b/tools/gnatcov/qemu_traces.ads index 12a2dedea..3d9ce8930 100644 --- a/tools/gnatcov/qemu_traces.ads +++ b/tools/gnatcov/qemu_traces.ads @@ -202,6 +202,7 @@ package Qemu_Traces is Sec : Unsigned_8; -- 0 .. 59 Pad : Unsigned_8; -- 0 end record; + pragma Universal_Aliasing (Trace_Info_Date); --------------------------------------------------- -- Execution Trace Section (.Kind = Raw|History) -- From 82c52d26a2b1f824f48e9257fe558579562a6be0 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 15 Apr 2024 14:53:24 +0200 Subject: [PATCH 0815/1483] Forward auto_config_args to the gnatcov coverage invocation --- testsuite/SCOV/minicheck.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 2a4853c8a..cc7c79ff3 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -443,7 +443,13 @@ def build_run_and_coverage( auto_config_args=auto_config_args, **kwargs, ) - xcov(xcov_args, out=out, err=err, register_failure=register_failure) + xcov( + xcov_args, + auto_config_args=auto_config_args, + out=out, + err=err, + register_failure=register_failure, + ) def checked_xcov(args, out_file): From 4ca435d3cecd94ccf0eccc5876ba21c8e9e037a9 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 15 Apr 2024 14:54:33 +0200 Subject: [PATCH 0816/1483] Check that gnatcov generates instrumented files in the right obj dir Regression test: check that gnatcov create instrumentation artifacts in the right object directory. It used to create them in the wrong object directory when the object directory value depended on the Project'Target attribute and when the target was passed explicitly on the command line. --- .../gnatcoll-core#48-wrong-objdir/main.adb | 6 ++++ .../main_common.gpr | 15 ++++++++ .../main_x86.gpr | 16 +++++++++ .../gnatcoll-core#48-wrong-objdir/test.opt | 1 + .../gnatcoll-core#48-wrong-objdir/test.py | 34 +++++++++++++++++++ 5 files changed, 72 insertions(+) create mode 100644 testsuite/tests/gnatcoll-core#48-wrong-objdir/main.adb create mode 100644 testsuite/tests/gnatcoll-core#48-wrong-objdir/main_common.gpr create mode 100644 testsuite/tests/gnatcoll-core#48-wrong-objdir/main_x86.gpr create mode 100644 testsuite/tests/gnatcoll-core#48-wrong-objdir/test.opt create mode 100644 testsuite/tests/gnatcoll-core#48-wrong-objdir/test.py diff --git a/testsuite/tests/gnatcoll-core#48-wrong-objdir/main.adb b/testsuite/tests/gnatcoll-core#48-wrong-objdir/main.adb new file mode 100644 index 000000000..6e16d750d --- /dev/null +++ b/testsuite/tests/gnatcoll-core#48-wrong-objdir/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello world"); +end Main; diff --git a/testsuite/tests/gnatcoll-core#48-wrong-objdir/main_common.gpr b/testsuite/tests/gnatcoll-core#48-wrong-objdir/main_common.gpr new file mode 100644 index 000000000..f13e8c0ab --- /dev/null +++ b/testsuite/tests/gnatcoll-core#48-wrong-objdir/main_common.gpr @@ -0,0 +1,15 @@ +abstract project Main_Common is + + Target := project'Target; + + Target_Dir := "error :("; + case Target is + when "x86_64-pc-linux-gnu" => + Target_Dir := "obj-x86"; + when others => + Target_Dir := "unknown-"; + end case; + + Build_Dir := Target_Dir; + +end Main_Common; diff --git a/testsuite/tests/gnatcoll-core#48-wrong-objdir/main_x86.gpr b/testsuite/tests/gnatcoll-core#48-wrong-objdir/main_x86.gpr new file mode 100644 index 000000000..c7e50610d --- /dev/null +++ b/testsuite/tests/gnatcoll-core#48-wrong-objdir/main_x86.gpr @@ -0,0 +1,16 @@ +with "main_common.gpr"; + +project Main_x86 is + + for Target use "x86_64-pc-linux-gnu"; + + for Languages use ("Ada"); + + for Source_Dirs use ("."); + + for Main use ("main.adb"); + + for Object_Dir use Main_Common.Build_Dir; + for Exec_Dir use "exe"; + +end Main_x86; diff --git a/testsuite/tests/gnatcoll-core#48-wrong-objdir/test.opt b/testsuite/tests/gnatcoll-core#48-wrong-objdir/test.opt new file mode 100644 index 000000000..3cde64263 --- /dev/null +++ b/testsuite/tests/gnatcoll-core#48-wrong-objdir/test.opt @@ -0,0 +1 @@ +!x86_64-linux DEAD Target specific test diff --git a/testsuite/tests/gnatcoll-core#48-wrong-objdir/test.py b/testsuite/tests/gnatcoll-core#48-wrong-objdir/test.py new file mode 100644 index 000000000..58a610e96 --- /dev/null +++ b/testsuite/tests/gnatcoll-core#48-wrong-objdir/test.py @@ -0,0 +1,34 @@ +""" +Regression test: check that gnatcov create instrumentation artifacts in the +right object directory. It used to create them in the wrong object directory +when the object directory value depended on the Project'Target attribute and +when the target was passed explicitly on the command line. +""" + +import os.path + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches + +Wdir("tmp_") +for src in ("main_x86.gpr", "main_common.gpr", "main.adb"): + cp(os.path.join("..", src), src) + +build_run_and_coverage( + gprsw=GPRswitches(root_project="main_x86.gpr"), + mains=["main"], + covlevel="stmt", + gpr_exe_dir="exe", + gpr_obj_dir="obj-x86", + extra_coverage_args=["-axcov", "--output-dir=xcov"], + auto_config_args=False, + extra_args=["--target=x86_64-pc-linux-gnu"], +) + +check_xcov_reports("xcov", {"main.adb.xcov": {"+": {5}}}) + +thistest.result() From f940559fc5f0d18879a4733c62cb244b6ec7bb5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 3 Apr 2024 09:57:01 +0200 Subject: [PATCH 0817/1483] Force references to coverage buffers in Ada mains for manual dump trigger When using a manual dump trigger, with sources of interest in the root project, but no dump indication in that project, the coverage buffers units for that project would then not be in the main's compilation closure, resulting in a link error. This change fixes this by always making a reference to the dump helper unit in the Ada mains, which transitively make references to all the buffer units for the whole project tree. --- .../instr-cov/manual-dump/ada_subprj/test.py | 101 +++++++++++------- tools/gnatcov/instrument-ada_unit.adb | 18 ++++ tools/gnatcov/instrument-ada_unit.ads | 5 + tools/gnatcov/instrument-c.adb | 7 ++ tools/gnatcov/instrument-c.ads | 3 + tools/gnatcov/instrument-common.ads | 5 + tools/gnatcov/instrument-projects.adb | 22 +++- 7 files changed, 120 insertions(+), 41 deletions(-) diff --git a/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py index a74a98d15..12f407e44 100644 --- a/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py +++ b/testsuite/tests/instr-cov/manual-dump/ada_subprj/test.py @@ -10,8 +10,6 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor -tmp = Wdir("tmp_") - def make_lib_gpr(name, srcdirs, deps): return gprfor( @@ -24,40 +22,69 @@ def make_lib_gpr(name, srcdirs, deps): ) -lib1_p = make_lib_gpr("lib1", "../src-lib1", ["lib2"]) -lib2_p = make_lib_gpr("lib2", "../src-lib1/src-lib2", None) - -p = gprfor( - mains=["main.adb"], srcdirs=["../src"], objdir="obj", deps=["lib1", "lib2"] -) - -# Check that we get the expected coverage reports - -# Running gnatcov natively allows to have one source trace file per -# project. -instr_warning = ( - r"warning: Manual buffer dump/reset indications were" r" found in.*" -) - -build_run_and_coverage( - gprsw=GPRswitches(root_project=p, units=["lib1", "lib2"]), - covlevel="stmt", - mains=["main"], - extra_coverage_args=["-axcov", "--output-dir=xcov"], - trace_mode="src", - dump_trigger="manual", - manual_prj_name="lib1", - tolerate_instrument_messages=instr_warning, -) - -check_xcov_reports( - "xcov", - { - "lib1.adb.xcov": {"+": {6, 8}, "-": {10}}, - "lib1.ads.xcov": {}, - "lib2.adb.xcov": {"+": {4, 6}}, - "lib2.ads.xcov": {}, - }, -) +def check_one(with_units): + """ + Do a build, run, coverage, and report-check workflow, ensuring we get the + expected warnings and coverage results. + + with_units controls wether the --units option is passed + to gnatcov instrument to restrict analysis to the units in the projects + where the manual dump indication has visibility. + """ + + suffix = "units" if with_units else "no_units" + tmp = Wdir("tmp_" + suffix) + + make_lib_gpr("lib1", "../src-lib1", ["lib2"]) + make_lib_gpr("lib2", "../src-lib1/src-lib2", None) + + p = gprfor( + mains=["main.adb"], + srcdirs=["../src"], + objdir="obj", + deps=["lib1", "lib2"], + ) + + # Check that we get the expected coverage reports + + # Running gnatcov natively allows to have one source trace file per + # project. + instr_warning = ( + r"warning: Manual buffer dump/reset indications were" r" found in.*" + ) + + build_run_and_coverage( + gprsw=GPRswitches( + root_project=p, units=["lib1", "lib2"] if with_units else None + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov_" + suffix], + trace_mode="src", + dump_trigger="manual", + manual_prj_name="lib1", + tolerate_instrument_messages=instr_warning, + ) + + # If with_units is False, we expect coverage violations for main.adb + check_xcov_reports( + "xcov_" + suffix, + { + "lib1.adb.xcov": {"+": {6, 8}, "-": {10}}, + "lib1.ads.xcov": {}, + "lib2.adb.xcov": {"+": {4, 6}}, + "lib2.ads.xcov": {}, + } + | ( + {} + if with_units + else {"main.adb.xcov": {"-": {10, 13, 15, 16, 17}}} + ), + ) + tmp.to_homedir() + + +check_one(with_units=False) +check_one(with_units=True) thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index d3626f675..907dd350b 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8175,6 +8175,7 @@ package body Instrument.Ada_Unit is (Self : in out Ada_Instrumenter_Type; Prj : in out Prj_Desc; Source : GNATCOLL.Projects.File_Info; + Is_Main : Boolean; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean) is @@ -8346,6 +8347,23 @@ package body Instrument.Ada_Unit is (GNATCOLL.VFS."+" (Source.Project.Object_Dir.Base_Dir_Name)); Create_Directory_If_Not_Exists (+Prj.Output_Dir); Rewriter.Apply; + elsif Is_Main then + + -- If this is a main, force a reference to the dump helper unit to + -- ensure coverage buffers make it to the compilation closure. + + Start_Rewriting (Rewriter, Self, Prj, Unit); + Insert_Last + (Handle (Unit.Root.As_Compilation_Unit.F_Prelude), + Create_From_Template + (Rewriter.Handle, + Template => "with {};", + Arguments => + (1 => To_Nodes + (Rewriter.Handle, + Create_Manual_Helper_Unit_Name (Prj))), + Rule => With_Clause_Rule)); + Rewriter.Apply; end if; end Replace_Manual_Indications; diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 93964305e..06abbab36 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -96,6 +96,7 @@ package Instrument.Ada_Unit is (Self : in out Ada_Instrumenter_Type; Prj : in out Prj_Desc; Source : GNATCOLL.Projects.File_Info; + Is_Main : Boolean; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean); -- Once the instrumentation has finished, if the dump trigger is "manual" @@ -115,6 +116,10 @@ package Instrument.Ada_Unit is -- -- If found, this pragma will be replaced by a call to the buffer reset -- procedure defined in the dump helper unit. + -- + -- If Is_Main is True and no pragmas were found, still add a reference to + -- the helper unit to ensure the coverage buffers are included in the + -- main's compilation closure. overriding procedure Emit_Buffers_List_Unit (Self : Ada_Instrumenter_Type; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index c3a2692a9..26854ac97 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3852,9 +3852,16 @@ package body Instrument.C is (Self : in out C_Family_Instrumenter_Type; Prj : in out Prj_Desc; Source : GNATCOLL.Projects.File_Info; + Is_Main : Boolean; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean) is + pragma Unreferenced (Is_Main); + -- when C-like languages are present, gprbuild doesn't compile only + -- what's in the closure of the main, but rather all sources and lets + -- the linker only pick the object files that are relevant. As such we + -- don't need to add references to the helper unit in main source files. + Orig_Filename : constant String := +Source.File.Full_Name; begin Check_Compiler_Driver (Prj, Self); diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 962520279..ab33c0a96 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -62,6 +62,7 @@ package Instrument.C is (Self : in out C_Family_Instrumenter_Type; Prj : in out Prj_Desc; Source : GNATCOLL.Projects.File_Info; + Is_Main : Boolean; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean); -- Preprocess Source and look through the text content of the preprocessed @@ -77,6 +78,8 @@ package Instrument.C is -- When one is found the text of the file is modified: the line is replaced -- by a call to the manual dump/reset procedure and an extern declaration -- for the procedure is put at the beginning of the file. + -- + -- Is_Main has no effect for C-like languages. overriding procedure Emit_Dump_Helper_Unit_Manual (Self : in out C_Family_Instrumenter_Type; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 23bc670d9..b66c27907 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -497,6 +497,7 @@ package Instrument.Common is (Self : in out Language_Instrumenter; Prj : in out Prj_Desc; Source : GNATCOLL.Projects.File_Info; + Is_Main : Boolean; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean) is null; -- Look for the pragmas (for Ada) or comments (for C family languages) @@ -505,6 +506,10 @@ package Instrument.Common is -- When found, replace it with a call to the buffers dump/reset procedure -- defined in the dump helper unit. -- + -- Is_Main indicates whether Source would have been instrumented as a main + -- with another dump trigger, each instrumenter may process this + -- information differently. + -- -- Has_Dump_Indication indicates whether a manual dump indication was -- found - and replaced with a call to dump buffers - in the given source. -- diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index f10d50bb2..ecec2b080 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -254,7 +254,8 @@ is (Language : Src_Supported_Language; Project_Sources : in out File_Info_Sets.Set; Instrumenter : in out Language_Instrumenter'Class; - Manual_Dump_Inserted : in out Boolean); + Manual_Dump_Inserted : in out Boolean; + Mains : Main_To_Instrument_Vectors.Vector); -- For all sources in Project_Sources of language Language, call -- Replace_Manual_Indications. If a dump procedure call was inserted -- and id there is not one already, also emit a dump helper unit for the @@ -845,7 +846,8 @@ is (Language : Src_Supported_Language; Project_Sources : in out File_Info_Sets.Set; Instrumenter : in out Language_Instrumenter'Class; - Manual_Dump_Inserted : in out Boolean) + Manual_Dump_Inserted : in out Boolean; + Mains : Main_To_Instrument_Vectors.Vector) is function Dump_Helper_Output_Dir_Exists (Source : File_Info; Prj : Prj_Desc) @@ -882,10 +884,20 @@ is Instrumenter.Dump_Manual_Helper_Unit (Prj).Unit_Name; Had_Dump_Indication : Boolean := False; Had_Reset_Indication : Boolean := False; + + Is_Main : constant Boolean := + (for some Main of Mains => + (GNATCOLL.VFS."+" (Main.File.Full_Name)) = Source_Name); + -- Whether Source is a main which would have been instrumented + -- with another dump trigger. The lookup should be reasonable + -- in cost given that there shouldn't be that many mains in the + -- top level main project. + begin Instrumenter.Replace_Manual_Indications (Prj_Info.Desc, Source, + Is_Main, Had_Dump_Indication, Had_Reset_Indication); @@ -1246,7 +1258,8 @@ begin (Lang, Project_Sources, Instrumenters (Lang).all, - Manual_Dump_Inserted); + Manual_Dump_Inserted, + Mains_To_Instrument (Lang)); end loop; end if; @@ -1552,7 +1565,8 @@ begin (Ada_Language, Project_Sources, Ada_Instrumenter, - Manual_Dump_Inserted); + Manual_Dump_Inserted, + Mains_To_Instrument (Ada_Language)); -- At this point, all source files for all languages have been looked -- through to insert a call to the manual dump procedure. If no call From 55e521531f9d734207b68563e42731f1422e82ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 3 Apr 2024 15:11:41 +0200 Subject: [PATCH 0818/1483] Document coverage buffer reset API --- doc/gnatcov/src_traces.rst | 97 +++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index c5027996c..fa0d5492b 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -258,6 +258,7 @@ The instrumentation process can be parallelized using the ``-j`` (shorthand for ``--jobs``) switch. ``-j0`` can be used for maximal parallelism, and ``-jN`` with N > 0 to specify the desired level of concurrency. +.. _Dump_Triggers: Output strategies for main units -------------------------------- @@ -293,7 +294,7 @@ collected coverage data. You will have to indicate the point at which you wish to emit this data by inserting: - a ``pragma Annotate (Xcov, Dump_Buffers);`` pragma statement in Ada code; -- a ``/* GNATCOV_DUMP_BUFFERS */`` comment on its own line in C code +- a ``/* GNATCOV_DUMP_BUFFERS */`` comment on its own line in C and C++ code where necessary in your code. During instrumentation, |gcv| will replace them with a call to the procedure responsible for dumping the coverage buffers, @@ -313,6 +314,100 @@ dump configuration the traces are sequentially dumped in the same output file, from which the |gcv| command ``extrace-base64-trace`` will be able to produce a source trace file. +It is also possible to configure the prefix of the trace filename +(see :ref:`instr-tracename` for more details) through these indications: + +- ``pragma Annotate (Xcov, Dump_Buffers, Prefix);`` in Ada code, where + ``Prefix`` resolves to type ``String``; +- ``/* GNATCOV_DUMP_BUFFERS (Prefix) */`` in C or C++ code, where ``Prefix`` + resolves to a null-terminated ``char *`` type. + +No type checking will be done during instrumentation, the values passed as +prefix indications are used as parameters to the buffer dump procedure call. +The Ada procedure call expects a ``String`` parameter, and the C or C++ +functions expect a null-terminated ``const char *``, so in both cases +specifying a string literal is allowed. If the prefix indication does not +resolve to the correct type, the instrumented code will fail to build. + +This can be used in case multiple traces are dumped in rapid succession, to +distinguish between each trace: + +.. code-block:: Ada + + procedure Dump is + Prefix : constant String := "variable"; + begin + -- Ok, Prefix is of type String + -- Trace filename will be "variable-.srctrace" + + pragma Annotate (Xcov, Dump_Buffers, Prefix); + + -- Ok, String literal + -- Trace filename will be "literal-.srctrace" + + pragma Annotate (Xcov, Dump_Buffers, "literal"); + + -- Not ok, Undefined does not resolve to a variable of type String + -- This will fail to compile. + + pragma Annotate (Xcov, Dump_Buffers, Undefined); + end Dump; + +.. code-block:: c + + void dump(void){ + + /* Ok, prefix if type char * and null-terminated. + Trace filename will be "variable-.srctrace" */ + char *prefix = "variable"; + /* GNATCOV_DUMP_BUFFERS (prefix) */ + + /* Ok, string literal. + Trace filename will be "literal-.srctrace" */ + /* GNATCOV_DUMP_BUFFERS ("literal") */ + + /* Not ok, Undefined does not resolve to a null terminated string. + This will not compile. */ + /* GNATCOV_DUMP_BUFFERS (Undefined) */ + } + + +Resetting coverage information during the execution +--------------------------------------------------- + +|gcvins| offers the possibility to indicate, in the program sources, one or +multiple locations at which the buffers used to track the execution of the +program should be cleared. This can be used in various situations where a finer +grain control of the traces generated by the instrumented program is required. +For instance, this can be used to ignore some initialization phase in the +coverage report, or to emit multiple coverage traces from a single execution of +the instrumented program, each trace containing the coverage information for a +specific part of the execution, such as in a unit test driver. + +This fine grain control of the coverage buffers mandates the use of a manual +dump of the coverage buffers, thus requiring passing the +``--dump-trigger=manual`` command line option to |gcvins| +invocations, as described in :ref:`Dump_Triggers`. + +The buffer reset location indications follow a similar convention as the manual +dump of the traces. Indicating the point at which coverage buffers must be +cleared is done by inserting: + +- a ``pragma Annotate (Xcov, Reset_Buffers);`` pragma statement in Ada code; +- a ``/* GNATCOV_RESET_BUFFERS */`` comment on its own line in C and C++ code + +where necessary. During instrumentation, |gcv| will replace them +with a call to the procedure responsible for clearing the coverage buffers. +Therefore, the pragmas or comments should be placed at locations at which such +a procedure call would be legal and appropriate. + +For performance reasons, no synchronization mechanisms are used to protect the +buffer clear procedure call against concurrent writes in the coverage buffers +(by regular program execution). **It is up to the user to ensure that no other +section of the instrumented code runs concurrently to the buffer clear +procedure, otherwise the correctness of the corresponding coverage report +cannot be guaranteed.** + .. _instr-tracename: Controlling trace file names From 764341fdf5220d65e796c28fed11db480f5c69a7 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 11 Apr 2024 12:01:04 +0200 Subject: [PATCH 0819/1483] Accept any kind of string static expression as an exemption message --- .../231-malformed-exempt-markers/main_2.adb | 3 +- .../231-malformed-exempt-markers/test.py | 11 ++- tools/gnatcov/instrument-ada_unit.adb | 71 +++++++++++++++---- 3 files changed, 65 insertions(+), 20 deletions(-) diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb index 5cac79ee8..f5c651e09 100644 --- a/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/main_2.adb @@ -2,5 +2,6 @@ procedure Main_2 is begin pragma Annotate (1); pragma Annotate (Xcov, 1); - pragma Annotate (Xcov, Exempt_On, "Invalid" & " argument"); + pragma Annotate (Xcov, Exempt_On, "Valid" & " argument"); + pragma Annotate (Xcov, Exempt_On, 16#DEAD_BEEF#); end Main_2; diff --git a/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py index 465f63c96..76c732ada 100644 --- a/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py +++ b/testsuite/tests/instr-cov/231-malformed-exempt-markers/test.py @@ -1,8 +1,7 @@ """ Check that any deviation from the expected annotation pragmas is reported to the user as a warning. Also check that a warning is emitted if an unrecognized -Xcov annotation was found, and that when an argument of the wrong type is -given it is gprbuild and gnatcov that raises an exception. +Xcov annotation was found, or if an argument of the wrong type is given. """ from SCOV.minicheck import build_run_and_coverage, xcov_instrument @@ -13,8 +12,8 @@ Wdir("tmp_") -# Check gnatcov's behaviour upon encountering annotaton pragmas with correctly -# types arguments. +# Check gnatcov's behaviour upon encountering annotation pragmas with correctly +# typed arguments. build_run_and_coverage( gprsw=GPRswitches( @@ -52,8 +51,8 @@ "*** main_1.adb:10:5: warning: Invalid Xcov annotation kind: aaa\n" "*** main_1.adb:11:5: warning: Xcov annotation kind missing\n" "*** main_2.adb:4:5: warning: Invalid Xcov annotation kind\n" - "*** main_2.adb:5:5: warning: Invalid justification argument: string" - " literal expected\n" + "*** main_2.adb:6:5: warning: Invalid justification argument:" + " static string expression expected\n" ), contents_of("instrument.log"), ) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 907dd350b..760c9d0f5 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3753,6 +3753,44 @@ package body Instrument.Ada_Unit is -- it is not an identifier, return null. Else, return the identifier -- as a symbol. + procedure Safe_String_Eval + (E : Expr; + Result : out Unbounded_Text_Type; + Success : out Boolean); + -- Evaluate the given Expr E and set Result to the evaluated string + -- and Success to True if it could be evaluated, otherwise set + -- Success to False. + + ---------------------- + -- Safe_String_Eval -- + ---------------------- + + procedure Safe_String_Eval + (E : Expr; + Result : out Unbounded_Text_Type; + Success : out Boolean) + is + use Libadalang.Expr_Eval; + begin + -- TODO??? Check for P_Is_Static_Expr prior to evaluating + -- when eng/libadalang/libadalang#1359 is implemented instead of + -- using exception handling. + + declare + String_Expr_Eval : constant Eval_Result := Expr_Eval (E); + begin + if String_Expr_Eval.Kind /= String_Lit then + Success := False; + return; + end if; + Result := As_String (String_Expr_Eval); + Success := True; + end; + exception + when Property_Error => + Success := False; + end Safe_String_Eval; + Nb_Children : constant Natural := Prag_Args.Children_Count; Kind : Symbol_Type; Result : ALI_Annotation; @@ -3804,20 +3842,27 @@ package body Instrument.Ada_Unit is (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); when 3 => - if Prag_Arg_Expr (Prag_Args, 3).Kind /= Ada_String_Literal - then - Report - (N, - "Invalid justification argument: string literal" - & " expected", - Warning); - return; - end if; - Result.Message := new String' - (To_String (Prag_Arg_Expr (Prag_Args, 3).Text)); + declare + String_Value : Unbounded_Text_Type; + Success : Boolean; + begin + Safe_String_Eval + (Prag_Arg_Expr (Prag_Args, 3), String_Value, Success); + if not Success then + Report + (N, + "Invalid justification argument: static string" + & " expression expected", + Warning); + return; + end if; + Result.Message := new String' + (To_UTF8 (To_Text (String_Value))); - UIC.Annotations.Append - (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); + UIC.Annotations.Append + (Annotation_Couple' + ((UIC.SFI, +Sloc (N)), Result)); + end; when others => Report (N, "At most 3 pragma arguments allowed", Warning); From 385e2f5daff81a25f4142ec69d010c4a96489fd2 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 11 Apr 2024 12:07:54 +0200 Subject: [PATCH 0820/1483] Fix typo --- tools/gnatcov/instrument-c.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 26854ac97..353f7bb1d 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3047,7 +3047,7 @@ package body Instrument.C is Start_Matcher : constant Pattern_Matcher := Compile ("GNATCOV_EXEMPT_ON ""(.*)"""); End_Matcher : constant Pattern_Matcher := - Compile ("GNATCOV_EXEMPT_OF"); + Compile ("GNATCOV_EXEMPT_OFF"); Match_Res : Match_Array (0 .. 1); procedure Search_Exempt_In_Token (Token : Token_T); From cb37ed18298b25d1b57384a54fdfbf7cf691b8fb Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 12 Apr 2024 12:38:38 +0200 Subject: [PATCH 0821/1483] Accept any kind of string expression as a trace prefix ... ... in manual dump buffer annotations. --- .../manual-dump/prefix_in_code/main_ada.adb | 3 ++- .../manual-dump/prefix_in_code/test.py | 8 -------- tools/gnatcov/instrument-ada_unit.adb | 17 ++++++----------- 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_ada.adb b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_ada.adb index fbcbd73a7..78b1c7fef 100644 --- a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_ada.adb +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/main_ada.adb @@ -4,5 +4,6 @@ procedure Main_Ada is Trace_Prefix : constant String := "ada_trace"; begin Put_Line ("Hello Ada world!"); - pragma Annotate (XCov, Dump_Buffers, Trace_Prefix); + pragma Annotate (XCov, Dump_Buffers, Main_Ada.Trace_Prefix); + pragma Annotate (XCov, Dump_Buffers, "valid" & "prefix"); end Main_Ada; diff --git a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py index 223028e9d..d5535affd 100644 --- a/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py +++ b/testsuite/tests/instr-cov/manual-dump/prefix_in_code/test.py @@ -47,14 +47,6 @@ def check_one_trace(cov_args, lang): # {lang}_trace-{unique-part}.srctrace: trace = glob.glob(f"{lang}_trace-*.srctrace") - # There is only one dump indication in each main, ensure we found a trace - # and have no spurious traces in the working directory. - thistest.fail_if( - len(trace) != 1, comment=f"expected a single trace, found {len(trace)}" - ) - - print(trace) - output_dir = f"output_{lang}/" xcov( cov_args + [f"--output-dir={output_dir}"] + trace, diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 760c9d0f5..ba54c9631 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3886,18 +3886,13 @@ package body Instrument.Ada_Unit is -- * (Xcov, Dump_Buffers, Prefix) case Nb_Children is - when 2 => - null; + when 2 | 3 => - when 3 => - if Prag_Arg_Expr (Prag_Args, 3).Kind not in - Ada_String_Literal | Libadalang.Common.Ada_Identifier - then - Report - (N, - "Invalid prefix argument: string literal expected", - Warning); - end if; + -- TODO??? check that the Prefix expression is a string + -- type when eng/libadalang/libadalang#1360 is dealt + -- with. + + null; when others => Report (N, "At most 3 pragma arguments allowed", Warning); From 906eb11e879873f919c4bcbdb0cf384448670923 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Thu, 27 Apr 2023 15:30:16 +0000 Subject: [PATCH 0822/1483] testsuite.py unixify test dir names scanned for Qualification This change unixifies the candidate test dir names before checking if some Qualification subdir pattern matches, as the filtering patterns are expressed with forward slashes and the find operation on Windows might return Windows style paths. This fixes Qualification runs on Windows, which find 0 test to run otherwise. Take the opportunity to use "unixify" rather than ad-hoc slash replacements in a couple of places. Part of W426-013 --- testsuite/testsuite.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 9571b8cbf..709454c03 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -14,7 +14,7 @@ import itertools from e3.fs import mkdir, rm, cp -from e3.os.fs import which +from e3.os.fs import which, unixpath from e3.os.process import Run, quote_arg import e3.testsuite from e3.testsuite.control import AdaCoreLegacyTestControlCreator @@ -110,7 +110,10 @@ def hosts(self, test_dir): provided test directory, which may be relative to a testsuite root or absolute. """ - return re.search(pattern=self.subtrees, string=test_dir) + + # Expect filtering subtrees using forward slashes, so make + # sure the provided test_dir is amenable so such patterns. + return re.search(pattern=self.subtrees, string=unixpath(test_dir)) RE_QCOMMON = "(Common|Appendix)" @@ -149,6 +152,7 @@ def RE_SUBTREE(re_crit): ), } + # =============================== # == Compilation Flags Control == # =============================== @@ -334,7 +338,7 @@ def __init__(self, driver, result, test_prefix, working_prefix): # Create a "canonical" directory name for this testcase, useful to # simplify some platform-independent processings. - self.unix_test_dir = self.test_dir().replace("\\", "/") + self.unix_test_dir = unixpath(self.test_dir()) # Load all relevant *.opt files to control the execution of this test self.test_control_creator = self.parse_opt() @@ -954,7 +958,7 @@ def add_test_py_run(self, dag, test_dir, index): # as for regular tests. test_rel_dir = os.path.relpath(test_dir, self.test_dir()) test_name = "{}-{}".format( - self.test_name, test_rel_dir.replace("\\", "/").replace("/", "-") + self.test_name, unixpath(test_rel_dir).replace("/", "-") ) # For debuggability, derive the group.py test environment @@ -1024,7 +1028,7 @@ def test_name(self, test_dir): # Run some name canonicalization and replace directory separators with # dashes. - result = result.replace("\\", "/").rstrip("/").replace("/", "-") + result = unixpath(result).rstrip("/").replace("/", "-") # Tests from the internal testsuite used to be located in the "tests" # subdirectory. They are now in "../extra/tests", but we want the GAIA From fe9f01c66fd2ea3967223779d062db1e42592139 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Thu, 27 Apr 2023 15:54:14 +0000 Subject: [PATCH 0823/1483] Extend instr.py tolerance for inexistant obj dir to 23 Warnings by gnatcov instrument about missing obj dirs are harmless and release 23 still outputs them. Part of W426-013 (qualkit 999-W426-013) --- testsuite/SCOV/instr.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 0c576d860..aa026046c 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -153,7 +153,7 @@ def xcov_instrument( # issued when instrumenting before building. Tests do a best # effort attempt at creating objects dirs beforehand but doing # that is cumbersome for some of the more convoluted tests. - if GNATCOV_INFO.major_at_most(22): + if not GNATCOV_INFO.major_at_least(24): re_tolerate_messages = "|".join( "(?:{})".format(mre) for mre in ["object directory.*not found", re_tolerate_messages] From 63c73c9e62dcb9aff43f278469f356320d8dddb9 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Thu, 27 Apr 2023 16:32:40 +0000 Subject: [PATCH 0824/1483] Rename test drivers for path shortening purposes Useful to prevent spurious test failures from overlong path names on Windows. Part of W426-013 (gnatcov qualkit 999-W426-013) --- .../src/{test_derived_subprograms_full.adb => test_full.adb} | 4 ++-- ...derived_subprograms_indirect_1.adb => test_indirect_1.adb} | 4 ++-- ...derived_subprograms_indirect_2.adb => test_indirect_2.adb} | 4 ++-- .../src/{test_derived_subprograms_no.adb => test_no.adb} | 4 ++-- .../src/{test_derived_subprograms_part.adb => test_part.adb} | 4 ++-- ...tions_all_exempted_code_call.adb => test_all_exempted.adb} | 4 ++-- ...l_non_exempted_code_call.adb => test_all_non_exempted.adb} | 4 ++-- ...st_exemptions_exempted_code_call.adb => test_exempted.adb} | 4 ++-- .../src/{test_exemptions_no_call.adb => test_no.adb} | 4 ++-- ...tions_non_exempted_code_call.adb => test_non_exempted.adb} | 4 ++-- 10 files changed, 20 insertions(+), 20 deletions(-) rename testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/{test_derived_subprograms_full.adb => test_full.adb} (95%) rename testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/{test_derived_subprograms_indirect_1.adb => test_indirect_1.adb} (94%) rename testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/{test_derived_subprograms_indirect_2.adb => test_indirect_2.adb} (93%) rename testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/{test_derived_subprograms_no.adb => test_no.adb} (89%) rename testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/{test_derived_subprograms_part.adb => test_part.adb} (92%) rename testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/{test_exemptions_all_exempted_code_call.adb => test_all_exempted.adb} (92%) rename testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/{test_exemptions_all_non_exempted_code_call.adb => test_all_non_exempted.adb} (93%) rename testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/{test_exemptions_exempted_code_call.adb => test_exempted.adb} (93%) rename testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/{test_exemptions_no_call.adb => test_no.adb} (94%) rename testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/{test_exemptions_non_exempted_code_call.adb => test_non_exempted.adb} (93%) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_full.adb similarity index 95% rename from testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_full.adb rename to testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_full.adb index e076c4f20..775a88800 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_full.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_full.adb @@ -7,7 +7,7 @@ with Derived_1; use Derived_1; with Derived_2; use Derived_2; with Subprogram_Pack; use Subprogram_Pack; with Support; use Support; -procedure Test_Derived_Subprograms_Full is +procedure Test_Full is Var_T : T := (I => 1); Var_Derived_T_1 : Derived_T_1 := (I => 2); Var_Derived_T_2 : Derived_T_2 := (I => 3); @@ -44,7 +44,7 @@ begin Proc2 (Var_Derived_T_1); Assert (Var_Derived_T_1.I = 4); -end Test_Derived_Subprograms_Full; +end Test_Full; --# subprogram_pack.adb -- /fun1/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_indirect_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_indirect_1.adb similarity index 94% rename from testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_indirect_1.adb rename to testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_indirect_1.adb index a8755b933..2ee33e97c 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_indirect_1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_indirect_1.adb @@ -7,7 +7,7 @@ with Derived_1; use Derived_1; with Derived_2; use Derived_2; with Subprogram_Pack; use Subprogram_Pack; with Support; use Support; -procedure Test_Derived_Subprograms_Indirect_1 is +procedure Test_Indirect_1 is Var_T : T := (I => 1); Var_Derived_T_1 : Derived_T_1 := (I => 2); Var_Derived_T_2 : Derived_T_2 := (I => 3); @@ -34,7 +34,7 @@ begin Indirect_Call := Proc1'Access; Indirect_Call (Var_Derived_T_1); Assert (Var_Derived_T_1.I = 3); -end Test_Derived_Subprograms_Indirect_1; +end Test_Indirect_1; --# subprogram_pack.adb -- /fun1/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_indirect_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_indirect_2.adb similarity index 93% rename from testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_indirect_2.adb rename to testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_indirect_2.adb index 443b2fff5..c4c81bdee 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_indirect_2.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_indirect_2.adb @@ -6,7 +6,7 @@ with Derived_1; use Derived_1; with Derived_2; use Derived_2; with Subprogram_Pack; use Subprogram_Pack; with Support; use Support; -procedure Test_Derived_Subprograms_Indirect_2 is +procedure Test_Indirect_2 is Var_T : T := (I => 1); Var_Derived_T_1 : Derived_T_1 := (I => 2); Var_Derived_T_2 : Derived_T_2 := (I => 3); @@ -23,7 +23,7 @@ begin -- reported as uncovered Assert (Var_Derived_T_1.I = 4); -end Test_Derived_Subprograms_Indirect_2; +end Test_Indirect_2; --# subprogram_pack.adb -- /fun1/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_no.adb similarity index 89% rename from testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_no.adb rename to testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_no.adb index b24447740..f29bb1142 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_no.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_no.adb @@ -6,10 +6,10 @@ with Derived_1; use Derived_1; with Derived_2; use Derived_2; with Subprogram_Pack; use Subprogram_Pack; with Support; use Support; -procedure Test_Derived_Subprograms_No is +procedure Test_No is begin Assert (True); -end Test_Derived_Subprograms_No; +end Test_No; --# subprogram_pack.adb -- /fun1/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_part.adb b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_part.adb similarity index 92% rename from testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_part.adb rename to testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_part.adb index e7a2473e5..9315a4d20 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_derived_subprograms_part.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/Tagged/src/test_part.adb @@ -7,7 +7,7 @@ with Derived_1; use Derived_1; with Derived_2; use Derived_2; with Subprogram_Pack; use Subprogram_Pack; with Support; use Support; -procedure Test_Derived_Subprograms_Part is +procedure Test_Part is Var_T : T := (I => 1); Var_Derived_T_1 : Derived_T_1 := (I => 2); Var_Derived_T_2 : Derived_T_2 := (I => 3); @@ -16,7 +16,7 @@ begin Int := Fun3 (Var_Derived_T_2, 1); Assert (Int = 4); -end Test_Derived_Subprograms_Part; +end Test_Part; --# subprogram_pack.adb -- /fun1/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_exempted_code_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_all_exempted.adb similarity index 92% rename from testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_exempted_code_call.adb rename to testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_all_exempted.adb index c1735af67..a6ecbe190 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_exempted_code_call.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_all_exempted.adb @@ -4,7 +4,7 @@ with Exemptions; with Support; use Support; -procedure Test_Exemptions_All_Exempted_Code_Call is +procedure Test_All_Exempted is I : Integer := 1; J : Integer := 2; K : Integer := 3; @@ -19,7 +19,7 @@ begin Assert (Exemptions.Factorial (Positive'Last) = Positive'Last); -- Code in exemption section is executed -end Test_Exemptions_All_Exempted_Code_Call; +end Test_All_Exempted; --# exemptions.ads -- /decl/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_non_exempted_code_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_all_non_exempted.adb similarity index 93% rename from testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_non_exempted_code_call.adb rename to testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_all_non_exempted.adb index dbb1ff30e..ea83b13b3 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_all_non_exempted_code_call.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_all_non_exempted.adb @@ -9,7 +9,7 @@ with Exemptions; with Support; use Support; -procedure Test_Exemptions_All_Non_Exempted_Code_Call is +procedure Test_All_Non_Exempted is I, J, K : Integer := 1; begin Assert (Exemptions.X = 3); @@ -23,7 +23,7 @@ begin Assert (Exemptions.Another_Factorial (Positive'Last) = Positive'Last); -- No exempted code in this function -end Test_Exemptions_All_Non_Exempted_Code_Call; +end Test_All_Non_Exempted; --# exemptions.ads -- /decl/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_exempted_code_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exempted.adb similarity index 93% rename from testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_exempted_code_call.adb rename to testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exempted.adb index e85e4ab8f..424491b5a 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_exempted_code_call.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exempted.adb @@ -7,7 +7,7 @@ with Exemptions; with Support; use Support; -procedure Test_Exemptions_Exempted_Code_Call is +procedure Test_Exempted is I : Integer := 1; J : Integer := 2; K : Integer := 3; @@ -22,7 +22,7 @@ begin Assert (Exemptions.Factorial (Positive'Last) = Positive'Last); -- Code in exemption section is executed -end Test_Exemptions_Exempted_Code_Call; +end Test_Exempted; --# exemptions.ads -- /decl/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_no.adb similarity index 94% rename from testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb rename to testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_no.adb index dd805168e..06125fd6b 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_no_call.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_no.adb @@ -6,12 +6,12 @@ with Exemptions; with Support; use Support; -procedure Test_Exemptions_No_Call is +procedure Test_No is begin Assert (Exemptions.X = 3); Assert (Exemptions.Y = 1); Assert (Exemptions.Z = 2); -end Test_Exemptions_No_Call; +end Test_No; --# exemptions.ads -- /decl/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_non_exempted.adb similarity index 93% rename from testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb rename to testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_non_exempted.adb index a05129959..0f7bc7b5e 100755 --- a/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_exemptions_non_exempted_code_call.adb +++ b/testsuite/Qualif/Ada/stmt/Exemptions/MixInUnits/src/test_non_exempted.adb @@ -9,7 +9,7 @@ with Exemptions; with Support; use Support; -procedure Test_Exemptions_Non_Exempted_Code_Call is +procedure Test_Non_Exempted is I, J, K : Integer := 1; begin Assert (Exemptions.X = 3); @@ -22,7 +22,7 @@ begin Assert (Exemptions.Another_Factorial (3) = 6); -- No exempted code in this function -end Test_Exemptions_Non_Exempted_Code_Call; +end Test_Non_Exempted; --# exemptions.ads -- /decl/ l+ ## 0 From b9193fffd7a1f27ee0fb9298c0b5610eeb7857b0 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Fri, 21 Apr 2023 06:28:36 -0700 Subject: [PATCH 0825/1483] Refine Operational Environment entries Remove pointless mentions of "executable name". Add an "e4" entry for the gprbuild version. W427-019 (gnatcov qualkit 999-W426-013, TOR) --- testsuite/Qualif/Environment/env_table_src.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/testsuite/Qualif/Environment/env_table_src.rst b/testsuite/Qualif/Environment/env_table_src.rst index f97d0497f..c946ceb96 100644 --- a/testsuite/Qualif/Environment/env_table_src.rst +++ b/testsuite/Qualif/Environment/env_table_src.rst @@ -3,10 +3,11 @@ :widths: 5, 30, 60 :delim: | - e1 | Host Operating System name and version | Linux Redhat 7 - e2 | GNATcoverage executable name and version | GNATcoverage 19.3 (20200318) - e3 | GNAT Pro compiler executable name and version | gcc (GCC) 7.3.1 20180924 (for GNAT Pro 19lts 20200331) [i686-pc-linux-gnu] + e1 | Host Operating System name and version | Windows x86_64 + e2 | GNATcoverage version | GNATcoverage 23.1 (20230113) + e3 | GNAT Pro GCC version | GCC 11.3.1 20220922 (for GNAT Pro 23.1 20230113) + e4 | gprbuild version | GPRBUILD Pro 23.1 (20230113) (x86_64-w64-mingw32) s1 | GNAT Pro compilation switches | -gnat12 - s2 | GNAT Pro Runtime Library Profile | No --RTS switch expected. Programs shall honor the :ref:`language-scope` restrictions, nevertheless. + s2 | GNAT Pro Runtime Library Profile | No --RTS switch expected. Programs shall nevertheless honor the :ref:`language-scope` restrictions. s3 | GNATcov dump trigger switch value | :literal:`--dump-triger=atexit` s4 | GNATcov dump channel switch value | :literal:`--dump-channel=bin-file` From a2dacc38af0145043ff55a2520ef1bf6601d6c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 16 May 2023 16:07:07 +0200 Subject: [PATCH 0826/1483] genbundle.py: work around missing permissions When working on a qualrun result that was produced in a Windows environment, then zipped and unpacked in a linux environment, all executable permissions are removed. To work around this, invoke mkrest.sh through a sh invocation. Part of W426-013 (gnatcov qualkit 999-W426-013) --- qualification/genbundle.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 7608812cd..49b78635a 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -906,10 +906,11 @@ def __prepare_str_dir(self): raccess = raccess_in(self.o.testsuite_dir) rdir = rdir_in(self.o.testsuite_dir) - mkstr_cmd = "(cd %(dir)s/STR && ./mkrest.sh %(level)s)" % { + mkstr_cmd = "(cd %(dir)s/STR && sh ./mkrest.sh %(level)s)" % { "dir": self.o.testsuite_dir if not rdir else rdir, "level": self.o.dolevel, } + prefix = ["sh", "-c"] if not raccess else ["ssh", raccess] run_list(prefix + [mkstr_cmd]) From 673f0a09f492f152cff02e7d93dc81edc08dbcb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 16 May 2023 17:10:42 +0200 Subject: [PATCH 0827/1483] Shorten paths to avoid path limit issues on Windows Fix some small typos along the way Part of W426-013 (gnatcov qualkit 999-W426-013) --- ...st_subtype_indications_full.adb => test_full.adb} | 4 ++-- .../{test_subtype_indications_no.adb => test_no.adb} | 4 ++-- ...ubtype_indications_part_1.adb => test_part_1.adb} | 12 ++++++------ ...ubtype_indications_part_2.adb => test_part_2.adb} | 12 ++++++------ ...stantiations_elab_only.adb => test_elab_only.adb} | 4 ++-- .../{test_instantiations_full.adb => test_full.adb} | 4 ++-- ...est_instantiations_part_1.adb => test_part_1.adb} | 4 ++-- ...est_instantiations_part_2.adb => test_part_2.adb} | 4 ++-- ...est_instantiations_part_3.adb => test_part_3.adb} | 4 ++-- ...est_instantiations_part_4.adb => test_part_4.adb} | 4 ++-- ...est_instantiations_part_5.adb => test_part_5.adb} | 4 ++-- ...est_instantiations_part_6.adb => test_part_6.adb} | 4 ++-- ...stantiations_elab_only.adb => test_elab_only.adb} | 4 ++-- .../{test_instantiations_full.adb => test_full.adb} | 6 +++--- .../src/{test_instantiations_no.adb => test_no.adb} | 4 ++-- ...est_instantiations_part_1.adb => test_part_1.adb} | 4 ++-- ...est_instantiations_part_2.adb => test_part_2.adb} | 4 ++-- .../12_GenericUnits/Default_UnitInstances/tc.rst | 2 +- 18 files changed, 44 insertions(+), 44 deletions(-) rename testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/{test_subtype_indications_full.adb => test_full.adb} (91%) rename testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/{test_subtype_indications_no.adb => test_no.adb} (87%) rename testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/{test_subtype_indications_part_1.adb => test_part_1.adb} (59%) rename testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/{test_subtype_indications_part_2.adb => test_part_2.adb} (64%) rename testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/{test_instantiations_elab_only.adb => test_elab_only.adb} (91%) rename testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/{test_instantiations_full.adb => test_full.adb} (93%) rename testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/{test_instantiations_part_1.adb => test_part_1.adb} (92%) rename testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/{test_instantiations_part_2.adb => test_part_2.adb} (91%) rename testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/{test_instantiations_part_3.adb => test_part_3.adb} (91%) rename testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/{test_instantiations_part_4.adb => test_part_4.adb} (92%) rename testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/{test_instantiations_part_5.adb => test_part_5.adb} (93%) rename testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/{test_instantiations_part_6.adb => test_part_6.adb} (92%) rename testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/{test_instantiations_elab_only.adb => test_elab_only.adb} (91%) rename testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/{test_instantiations_full.adb => test_full.adb} (87%) rename testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/{test_instantiations_no.adb => test_no.adb} (96%) rename testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/{test_instantiations_part_1.adb => test_part_1.adb} (92%) rename testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/{test_instantiations_part_2.adb => test_part_2.adb} (93%) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_full.adb similarity index 91% rename from testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_full.adb rename to testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_full.adb index 9b9f03b29..96780bec2 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_full.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_full.adb @@ -6,7 +6,7 @@ with Decls_Support; use Decls_Support; with Subtype_Indications; use Subtype_Indications; with Support; use Support; -procedure Test_Subtype_Indications_Full is +procedure Test_Full is V : Var_String := Get_Var_String (1, "a"); V1 : Vector (1 .. 3) := (1, 2, 3); V2 : Vector (1 .. 3); @@ -18,7 +18,7 @@ begin Assert (V2 (1) = 3 and then V2 (2) = 2 and then V2 (3) = 1); Assert (Some_Fun (2, "ab") = 2); -end Test_Subtype_Indications_Full; +end Test_Full; --# subtype_indications.ads -- /dcl/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_no.adb similarity index 87% rename from testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_no.adb rename to testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_no.adb index ff07390bc..91f32b66b 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_no.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_no.adb @@ -5,10 +5,10 @@ with Subtype_Indications; with Support; use Support; -procedure Test_Subtype_Indications_No is +procedure Test_No is begin Assert (True); -end Test_Subtype_Indications_No; +end Test_No; --# subtype_indications.ads -- /dcl/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_part_1.adb similarity index 59% rename from testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_1.adb rename to testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_part_1.adb index 9bd9b49e4..b71172adb 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_part_1.adb @@ -1,18 +1,18 @@ -- Test driver for subtype indications. It calls a subprogram from the --- functional code (another driver - Test_Subtype_Indications_Part_2 calls --- other routines), so the library-level declaration and some of the local --- declarations are expected to be reported as covered, and other local --- declarations are expected to be reported as uncovered. +-- functional code (another driver - Test_Part_2 calls other routines), +-- so the library-level declaration and some of the local declarations are +-- expected to be reported as covered, and other local declarations are +-- expected to be reported as uncovered. with Decls_Support; use Decls_Support; with Subtype_Indications; use Subtype_Indications; with Support; use Support; -procedure Test_Subtype_Indications_Part_1 is +procedure Test_Part_1 is V : Var_String := Get_Var_String (1, "a"); begin Assert (V.Data = "a"); -end Test_Subtype_Indications_Part_1; +end Test_Part_1; --# subtype_indications.ads -- /dcl/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_part_2.adb similarity index 64% rename from testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_2.adb rename to testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_part_2.adb index aedc1d618..6f89e2fe7 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_subtype_indications_part_2.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/SubtypeIndications/src/test_part_2.adb @@ -1,14 +1,14 @@ -- Test driver for subtype indications. It calls two subprograms from the --- functional code (another driver - Test_Subtype_Indications_Part_1 calls --- another routin), so the library-level declaration and some of the local --- declarations are expected to be reported as covered, and other local --- declarations are expected to be reported as uncovered. +-- functional code (another driver - Test_Part_1 calls another routine), so +-- the library-level declaration and some of the local declarations are +-- expected to be reported as covered, and other local declarations are +-- expected to be reported as uncovered. with Decls_Support; use Decls_Support; with Subtype_Indications; use Subtype_Indications; with Support; use Support; -procedure Test_Subtype_Indications_Part_2 is +procedure Test_Part_2 is V1 : Vector (1 .. 3) := (1, 2, 3); V2 : Vector (1 .. 3); @@ -17,7 +17,7 @@ begin Assert (V2 (1) = 3 and then V2 (2) = 2 and then V2 (3) = 1); Assert (Some_Fun (2, "ab") = 2); -end Test_Subtype_Indications_Part_2; +end Test_Part_2; --# subtype_indications.ads -- /dcl/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_elab_only.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_elab_only.adb similarity index 91% rename from testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_elab_only.adb rename to testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_elab_only.adb index e3b13e138..435740de5 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_elab_only.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_elab_only.adb @@ -6,10 +6,10 @@ with Pack; with Local_Instantiations; with Support; use Support; -procedure Test_Instantiations_Elab_Only is +procedure Test_Elab_Only is begin Assert (Local_Instantiations.Pack_Instance.Var = 'A'); -end Test_Instantiations_Elab_Only; +end Test_Elab_Only; --# pack.adb -- /new_value_g/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_full.adb similarity index 93% rename from testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_full.adb rename to testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_full.adb index 8e5a160ac..d4cd47969 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_full.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_full.adb @@ -5,7 +5,7 @@ with Pack; with Local_Instantiations; with Support; use Support; -procedure Test_Instantiations_Full is +procedure Test_Full is Int1 : Integer := 1; Int2 : Integer := 2; @@ -25,7 +25,7 @@ begin Local_Instantiations.Update (Int1); Assert (Int1 = 2); -end Test_Instantiations_Full; +end Test_Full; --# pack.adb -- /new_value_g/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_1.adb similarity index 92% rename from testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_1.adb rename to testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_1.adb index 8b3942903..9fc54a96b 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_1.adb @@ -6,7 +6,7 @@ with Pack; with Local_Instantiations; with Support; use Support; -procedure Test_Instantiations_Part_1 is +procedure Test_Part_1 is use Local_Instantiations.Stacks; S : Stack; Int : Integer := 0; @@ -14,7 +14,7 @@ begin Push (13, S); Pop (Int, S); Assert (Int = 13); -end Test_Instantiations_Part_1; +end Test_Part_1; --# pack.adb -- /new_value_g/ ~l- ## ~s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_2.adb similarity index 91% rename from testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_2.adb rename to testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_2.adb index c141fe5cb..4b13b5ceb 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_2.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_2.adb @@ -6,12 +6,12 @@ with Pack; with Local_Instantiations; with Support; use Support; -procedure Test_Instantiations_Part_2 is +procedure Test_Part_2 is Int : Integer := 0; begin Local_Instantiations.Update (Int); Assert (Int = 1); -end Test_Instantiations_Part_2; +end Test_Part_2; --# pack.adb -- /new_value_g/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_3.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_3.adb similarity index 91% rename from testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_3.adb rename to testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_3.adb index 2e095ebe1..f2b2ed8c1 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_3.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_3.adb @@ -6,10 +6,10 @@ with Pack; with Local_Instantiations; with Support; use Support; -procedure Test_Instantiations_Part_3 is +procedure Test_Part_3 is begin Assert (Local_Instantiations.New_Value (0) = 1); -end Test_Instantiations_Part_3; +end Test_Part_3; --# pack.adb -- /new_value_g/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_4.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_4.adb similarity index 92% rename from testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_4.adb rename to testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_4.adb index 1e0832a27..ae2caa116 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_4.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_4.adb @@ -6,7 +6,7 @@ with Pack; with Local_Instantiations; with Support; use Support; -procedure Test_Instantiations_Part_4 is +procedure Test_Part_4 is use Local_Instantiations.Pack_Instance; Char : Character := 'B'; begin @@ -14,7 +14,7 @@ begin Swap (Var, Char); Assert (Var = 'B'); Assert (Char = 'A'); -end Test_Instantiations_Part_4; +end Test_Part_4; --# pack.adb -- /new_value_g/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_5.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_5.adb similarity index 93% rename from testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_5.adb rename to testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_5.adb index 9dc2759fd..e3d52e38e 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_5.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_5.adb @@ -8,7 +8,7 @@ with Pack; with Local_Instantiations; with Support; use Support; -procedure Test_Instantiations_Part_5 is +procedure Test_Part_5 is Int1 : Integer := 1; Int2 : Integer := 2; Bool1 : Boolean := True; @@ -24,7 +24,7 @@ begin Assert (Int2 = 1); Assert (not Bool1); Assert (Bool2); -end Test_Instantiations_Part_5; +end Test_Part_5; --# pack.adb -- /new_value_g/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_6.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_6.adb similarity index 92% rename from testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_6.adb rename to testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_6.adb index 487d2d03c..965f779f3 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_instantiations_part_6.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_LocalInstances/src/test_part_6.adb @@ -7,11 +7,11 @@ with Pack; with Local_Instantiations; with Support; use Support; -procedure Test_Instantiations_Part_6 is +procedure Test_Part_6 is Bool2 : Boolean := False; begin Assert (Local_Instantiations.Fun_With_Instantiations (0) = 1); -end Test_Instantiations_Part_6; +end Test_Part_6; --# pack.adb -- /new_value_g/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_elab_only.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_elab_only.adb similarity index 91% rename from testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_elab_only.adb rename to testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_elab_only.adb index 127c28a17..c91829678 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_elab_only.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_elab_only.adb @@ -8,10 +8,10 @@ with Pack_Instance_Lib_Level; with Stacks; with Update; with Support; use Support; -procedure Test_Instantiations_Elab_Only is +procedure Test_Elab_Only is begin Assert (Pack_Instance_Lib_Level.Var = 0.0); -end Test_Instantiations_Elab_Only; +end Test_Elab_Only; --# pack.adb -- /new_value_g/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_full.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_full.adb similarity index 87% rename from testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_full.adb rename to testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_full.adb index aa9761a2c..ed8e7b02a 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_full.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_full.adb @@ -1,4 +1,4 @@ --- Test driver for library-level generic instantiations. It exsecutes all the +-- Test driver for library-level generic instantiations. It executes all the -- functional code corresponding to library-level instantiations, so -- everything is expected to be reported as covered except the code of -- Pack.Proc. @@ -8,7 +8,7 @@ with Pack_Instance_Lib_Level; with Stacks; with Update; with Support; use Support; -procedure Test_Instantiations_Full is +procedure Test_Full is S : Stacks.Stack := Stacks.Default_Stack; I : Integer := 1; @@ -31,7 +31,7 @@ begin Update (J); Assert (J = 1); -end Test_Instantiations_Full; +end Test_Full; --# pack.adb -- /new_value_g/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_no.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_no.adb similarity index 96% rename from testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_no.adb rename to testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_no.adb index 54b41ca74..61dd99ca0 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_no.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_no.adb @@ -6,10 +6,10 @@ with Pack; with Stacks_G, Update_G; with Support; use Support; -procedure Test_Instantiations_No is +procedure Test_No is begin Assert (True); -end Test_Instantiations_No; +end Test_No; --# pack.adb -- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_part_1.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_part_1.adb similarity index 92% rename from testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_part_1.adb rename to testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_part_1.adb index 8252f0133..11fc42e73 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_part_1.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_part_1.adb @@ -7,7 +7,7 @@ with Pack_Instance_Lib_Level; with Stacks; with Update; with Support; use Support; -procedure Test_Instantiations_Part_1 is +procedure Test_Part_1 is S : Stacks.Stack := Stacks.Default_Stack; begin Assert (Pack_Instance_Lib_Level.Var = 0.0); @@ -15,7 +15,7 @@ begin Assert (New_Value (0) = 1); Assert (Stacks.N_Values (S) = 1); -end Test_Instantiations_Part_1; +end Test_Part_1; --# pack.adb -- /new_value_g/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_part_2.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_part_2.adb similarity index 93% rename from testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_part_2.adb rename to testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_part_2.adb index 98d24aba7..45c1044ef 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_instantiations_part_2.adb +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/src/test_part_2.adb @@ -7,7 +7,7 @@ with Pack_Instance_Lib_Level; with Stacks; with Update; with Support; use Support; -procedure Test_Instantiations_Part_2 is +procedure Test_Part_2 is S : Stacks.Stack; I : Integer := 1; J : Integer := 2; @@ -23,7 +23,7 @@ begin Pack_Instance_Lib_Level.Swap (F1, F2); Assert (F1 = 2.0 and then F2 = 1.0); -end Test_Instantiations_Part_2; +end Test_Part_2; --# pack.adb -- /new_value_g/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/tc.rst index e4579da5b..14c822fe6 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/tc.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Default_UnitInstances/tc.rst @@ -1,7 +1,7 @@ **Exercise aggregated SC on instances providing compilation units** Exercise aggregated (default mode) Statement Coverage on instances of generic -packages or subprograms, all provided as independant compilation units on +packages or subprograms, all provided as independent compilation units on their own. LRMREF: 12.3 From 5af6d1d413aab1f29fa8c3b84038925b906620c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 16 May 2023 18:00:47 +0200 Subject: [PATCH 0828/1483] cutils.py: strip the tool version strings When dumping the tool versions in the testsuite environment dump, tool version strings are split by line on a "\n". This results, when run on windows, in stray carriage returns being included in the dump file, in turn messing up the formatting of the environment tables in the STR document. Fix this by consistently stripping each line of the version string. Part of W426-013 (gnatcov qualkit 999-W426-013) --- testsuite/SUITE/cutils.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testsuite/SUITE/cutils.py b/testsuite/SUITE/cutils.py index 26d10bccc..bbdea6379 100644 --- a/testsuite/SUITE/cutils.py +++ b/testsuite/SUITE/cutils.py @@ -181,7 +181,9 @@ def version_on_line(text): cprpos = text.find(",") return text[0:cprpos] if cprpos != -1 else text - tool_version_output = Run([tool, "--version"]).out.split("\n") + tool_version_output = [ + line.strip() for line in Run([tool, "--version"]).out.split("\n") + ] version_info = "\n".join( [version_on_line(line) for line in tool_version_output[0:nlines]] ) From 5861a30cb89b815d2bf7a97e9d9b6ef702ff59e7 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Fri, 5 May 2023 03:41:47 -0700 Subject: [PATCH 0829/1483] Acknowledge if-expressions and quantified-expressions support As we now have requirements and testcases in place for if-expressions and quantified-expressions, remove the statement claiming that their coverage assessment is not qualified. W427-019 (gnatcov qualkit 999-W426-013, TOR) --- testsuite/Qualif/Environment/content.tmpl | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/testsuite/Qualif/Environment/content.tmpl b/testsuite/Qualif/Environment/content.tmpl index 6efbce3b7..cd37ce2b5 100644 --- a/testsuite/Qualif/Environment/content.tmpl +++ b/testsuite/Qualif/Environment/content.tmpl @@ -113,11 +113,9 @@ In addition: present in the source programs at all, are disabled, for instance thanks to an Assertion_Policy pragma. -* For statement, decision or mcdc analysis on Ada 2012, the tool is not - qualified to assess coverage of the new forms of expression introduced in - the language, in particular *conditional expressions*, *generalized - membership tests* with more than one alternative, and *quantified - expressions*. +* For decision or mcdc analysis on Ada 2012, the tool is not + qualified to assess coverage *generalized membership tests* with + more than one alternative. Such expressions are only allowed in assertion/contracts contexts, disabled for coverage analysis purposes as previously described in this section. From 751808263a69e67bcf520f087ba00ca2f0403258 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Tue, 30 May 2023 17:55:26 +0200 Subject: [PATCH 0830/1483] Fix Assertion_Policy in decision/Assertions/Inactive/TypeInvariants The test verifies the tool behavior in a context where a TypeInvariant is meant to be disabled, resulting in an invariant check function never called. The disabling is implicit in absence in -gnata (invariants are not activated by default), and doubled by an explicit Assertion_Policy pragma in case -gnata is in the compilation flags. The pragma needs to target the precise kind of aspect attached to the declaration. We have type T_Value is tagged private with Type_Invariant'Class => I_Check(T_Value); so the Assertion_Policy should target Type_Invariant'Class. It was targetting "Invariant" so far and the test was failing when compiled with -gnata. Part of W426-013 (gnatcov qualkit 999-W426-013) --- .../Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.ads b/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.ads index 0d8af40f7..22fc3d02e 100644 --- a/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.ads +++ b/testsuite/Qualif/Ada/decision/Assertions/Inactive/TypeInvariants/src/ops.ads @@ -1,5 +1,5 @@ pragma Ada_2012; -pragma Assertion_Policy (Invariant => Disable); +pragma Assertion_Policy (Type_Invariant'Class => Disable); package Ops is From cab27e940af02ed7219934405b1fa1b48a6f2acc Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Thu, 1 Jun 2023 09:26:10 +0200 Subject: [PATCH 0831/1483] Fix Assertion_Policy in mcdc/Assertions/Inactive/TypeInvariants Similar to the previous change on decision/Assertions. Multiple kinds of aspects in the source (Type_Invariant and Type_Invariant'Class), inhibited at once with a global Assertion_Policy request. Part of W426-013 (gnatcov qualkit 999-W426-013) --- .../Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.ads b/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.ads index 39986954a..177d9e26c 100644 --- a/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.ads +++ b/testsuite/Qualif/Ada/mcdc/Assertions/Inactive/TypeInvariants/src/ops.ads @@ -1,5 +1,5 @@ pragma Ada_2012; -pragma Assertion_Policy (Invariant => Disable); +pragma Assertion_Policy (Disable); package Ops is From bcb6d64de2f6aaa7ad70e0b9b3093bd457b62d3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Fri, 29 Mar 2024 12:48:45 +0100 Subject: [PATCH 0832/1483] Mark assertion coverage as experimental --- doc/gnatcov/cov_source.rst | 8 ++++---- tools/gnatcov/command_line.ads | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index a389fee79..8d592cb3a 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -1417,8 +1417,8 @@ X2 (condition 2 False) at the same time when X1 < X2. .. _scov-atc: -Assertion True Coverage (ATC) analysis -====================================== +Assertion True Coverage (ATC) analysis (experimental) +===================================================== Along with the previous coverage levels, |gcv| can provide different strictness levels of assertion coverage for source traces for Ada. @@ -1474,8 +1474,8 @@ absence of other known violations for that same line. .. _scov-atcc: -Assertion True Condition Coverage (ATCC) analysis -================================================= +Assertion True Condition Coverage (ATCC) analysis (experimental) +================================================================ Core notions and Reporting (:cmd-option:`--level=...+atcc`) ----------------------------------------------------------- diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 1fb3d76f9..fde4acd13 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -739,6 +739,8 @@ package Command_Line is & ASCII.LF & "For the ""instrument"" command, " & "a source coverage level is required." + & ASCII.LF + & "ATC and ATCC are experimental features." ), Commands => (Cmd_Run | Cmd_Coverage From 9817ea14587069528848d7bb782c392b9d81cbf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 22 Apr 2024 14:42:39 +0200 Subject: [PATCH 0833/1483] Instrument.Projects: Remove spurious directory check When using the manual dump trigger, gnatcov used to check, for all projects, that there exists a directory with the same basename as the project's object directory. This is not needed as we also check the existence of the output dir (which is inside the object directory), and breaks the feature when gnatcov is not invoked exactly in the same directory as where the object dir will be created. This change removes the spurrious check. --- .../manual-dump/deep_obj/main_ada.adb | 7 ++ .../instr-cov/manual-dump/deep_obj/main_c.c | 9 +++ .../manual-dump/deep_obj/main_cpp.cpp | 9 +++ .../instr-cov/manual-dump/deep_obj/test.opt | 3 + .../instr-cov/manual-dump/deep_obj/test.py | 68 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 16 +---- tools/gnatcov/instrument-projects.adb | 10 +-- 7 files changed, 98 insertions(+), 24 deletions(-) create mode 100644 testsuite/tests/instr-cov/manual-dump/deep_obj/main_ada.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/deep_obj/main_c.c create mode 100644 testsuite/tests/instr-cov/manual-dump/deep_obj/main_cpp.cpp create mode 100644 testsuite/tests/instr-cov/manual-dump/deep_obj/test.opt create mode 100644 testsuite/tests/instr-cov/manual-dump/deep_obj/test.py diff --git a/testsuite/tests/instr-cov/manual-dump/deep_obj/main_ada.adb b/testsuite/tests/instr-cov/manual-dump/deep_obj/main_ada.adb new file mode 100644 index 000000000..b2860eb02 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/deep_obj/main_ada.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_Ada is +begin + Put_Line ("Hello Ada world!"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_Ada; diff --git a/testsuite/tests/instr-cov/manual-dump/deep_obj/main_c.c b/testsuite/tests/instr-cov/manual-dump/deep_obj/main_c.c new file mode 100644 index 000000000..0323c2bc8 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/deep_obj/main_c.c @@ -0,0 +1,9 @@ +#include + +int +main (void) +{ + printf ("Hello C world!\n"); + /* GNATCOV_DUMP_BUFFERS */ + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/deep_obj/main_cpp.cpp b/testsuite/tests/instr-cov/manual-dump/deep_obj/main_cpp.cpp new file mode 100644 index 000000000..333e8cdda --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/deep_obj/main_cpp.cpp @@ -0,0 +1,9 @@ +#include + +int +main (void) +{ + std::cout << "hello C++ world!" << std::endl; + /* GNATCOV_DUMP_BUFFERS */ + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/deep_obj/test.opt b/testsuite/tests/instr-cov/manual-dump/deep_obj/test.opt new file mode 100644 index 000000000..ab2120f34 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/deep_obj/test.opt @@ -0,0 +1,3 @@ +RTS_ZFP DEAD test uses stdio +!C++ DEAD test requires C++ compiler +!native XFAIL Build failure with mixed language mains. See #212 diff --git a/testsuite/tests/instr-cov/manual-dump/deep_obj/test.py b/testsuite/tests/instr-cov/manual-dump/deep_obj/test.py new file mode 100644 index 000000000..ba0fb7d71 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/deep_obj/test.py @@ -0,0 +1,68 @@ +""" +Check that using --dump-trigger=manual works correctly when gnatcov is not run +in the same directory as where the project's output directory is created. + +In these situations, gnatcov used to not emit the dump helper unit, as gnatcov +used to check the existence of the basename of the object directory, which was +thus not found. +""" + +import os + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, run_cov_program, exepath_to + +Wdir("tmp_") + +# Name for the main_c and main_cpp executable traces +c_trace_name = "main_c.srctrace" +cpp_trace_name = "main_cpp.srctrace" + + +# Create an object directory deeply nested, so that gnatcov is not run in the +# same directory as where it will be created. +obj_dir = "deep/obj/dir" + +# We can't build_run_and_coverage as the default trace name only depends on the +# project name so all mains would dump a trace with the same name (execution +# last less than a second). Instead, instrument and execute the first main +# through build_and_run, then run the other mains manually. +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid="p", + srcdirs=[".."], + objdir=obj_dir, + mains=["main_ada.adb", "main_c.c", "main_cpp.cpp"], + langs=["Ada", "C", "C++"], + ) + ), + covlevel="stmt", + mains=["main_ada"], + gpr_obj_dir=obj_dir, + dump_trigger="manual", + manual_prj_name="p", + extra_coverage_args=["-axcov", c_trace_name, cpp_trace_name], +) + +env = dict(os.environ) +env["GNATCOV_TRACE_FILE"] = c_trace_name +run_cov_program(exepath_to("main_c"), env=env) + +env["GNATCOV_TRACE_FILE"] = cpp_trace_name +run_cov_program(exepath_to("main_cpp"), env=env) + +xcov(cov_args) +check_xcov_reports( + obj_dir, + { + "main_ada.adb.xcov": {"+": {5}}, + "main_c.c.xcov": {"+": {6}, "-": {8}}, + "main_cpp.cpp.xcov": {"+": {6}, "-": {8}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index ba54c9631..3e2fadecf 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8242,9 +8242,6 @@ package body Instrument.Ada_Unit is -- If N is the expected pragma statement, replace it with the actual -- call. - procedure Create_Directory_If_Not_Exists (Name : String); - -- Create the directory of name Name if it does not exist yet - function Find_And_Replace_Pragma (N : Ada_Node'Class) return Visit_Status is function Is_Expected_Argument @@ -8361,15 +8358,6 @@ package body Instrument.Ada_Unit is end if; return Into; end Find_And_Replace_Pragma; - - procedure Create_Directory_If_Not_Exists (Name : String) - is - begin - if not Ada.Directories.Exists (Name) then - Ada.Directories.Create_Directory (Name); - end if; - end Create_Directory_If_Not_Exists; - begin -- If no pragma is found in this file then Start_Rewriting will not be -- called. In this case, Rewriter.Handle will not be properly @@ -8383,9 +8371,7 @@ package body Instrument.Ada_Unit is Unit.Root.Traverse (Find_And_Replace_Pragma'Access); if Has_Dump_Indication or else Has_Reset_Indication then - Create_Directory_If_Not_Exists - (GNATCOLL.VFS."+" (Source.Project.Object_Dir.Base_Dir_Name)); - Create_Directory_If_Not_Exists (+Prj.Output_Dir); + Ada.Directories.Create_Path (+Prj.Output_Dir); Rewriter.Apply; elsif Is_Main then diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index ecec2b080..101dbc90e 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -849,14 +849,6 @@ is Manual_Dump_Inserted : in out Boolean; Mains : Main_To_Instrument_Vectors.Vector) is - function Dump_Helper_Output_Dir_Exists - (Source : File_Info; Prj : Prj_Desc) - return Boolean - is (Ada.Directories.Exists - (GNATCOLL.VFS."+" (Source.Project.Object_Dir.Base_Dir_Name)) - and then Ada.Directories.Exists (+Prj.Output_Dir)); - -- True if the project's object directory and the instrumented sources - -- directory exist, False otherwise. package Non_Root_Src_Calls_Sets is new Ada.Containers.Indefinite_Ordered_Sets (Element_Type => String); @@ -922,7 +914,7 @@ is -- procedure for this project. if not Emitted_Manual_Helpers.Contains (Helper_Unit_Name) - and then Dump_Helper_Output_Dir_Exists (Source, Prj) + and then Ada.Directories.Exists (+Prj.Output_Dir) then Instrumenter.Emit_Dump_Helper_Unit_Manual (Dump_Config, Prj); From 0083100fa1c93e77f99c6877c5e58f9d9c81fa9e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 15 Mar 2022 15:42:41 +0100 Subject: [PATCH 0834/1483] Fix soundness issue in the decision map analysis gnatcov was incorrectly labeling some control flow branches as outcome, when they were branching into an inlined body. In the following example, assuming Orelse is inlined: function Orelse (B, C : Boolean) return Boolean is begin return (if B or else C then True else False); end; function F (A, B, C : Boolean) return Boolean is begin return (if A and then Orelse (B, C) then True else False); -- #D1 end; gnatcov incorrectly labeled an edge as implementing the valuation `False` for the condition A, and as an outcome of the decision #D1, which is unsound behaviour. As it could not find an edge for the valuation `True`, it also resulted in a `condition lacks edge` warning. TN: T706-019 --- .../Topologies/AndCOr/IfExprCtl/test.opt | 1 - tools/gnatcov/decision_map.adb | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt index cd54c6b08..a4e1eba80 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/AndCOr/IfExprCtl/test.opt @@ -1,2 +1 @@ -bin-traces,CARGS_O1 XFAIL T706-019: decision map issue 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/tools/gnatcov/decision_map.adb b/tools/gnatcov/decision_map.adb index ec2ffd032..fd3a9ac2f 100644 --- a/tools/gnatcov/decision_map.adb +++ b/tools/gnatcov/decision_map.adb @@ -2081,6 +2081,25 @@ package body Decision_Map is end if; BB := Find_Basic_Block (Ctx.Basic_Blocks, Next_PC); + + -- If we are branching into an inlined subprogram, we can't deduce + -- anything from it. + -- + -- TODO??? The above is a very conservative guess. If needed in + -- practice, we could refine this to handle various manageable cases. + + declare + BB_Inline_Info : constant Address_Info_Acc := + Get_Address_Info + (Exe.all, Inlined_Subprogram_Addresses, BB.To_PC); + begin + if BB_Inline_Info /= null + and then BB_Inline_Info /= D_Occ.Inlined_Body + then + return; + end if; + end; + if BB = No_Basic_Block then if After_Call or else Next_PC not in Ctx.Subprg.First .. Ctx.Subprg.Last From 5a2350647494decf95294451bea936cd08109bb4 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 6 Mar 2024 15:08:21 +0100 Subject: [PATCH 0835/1483] Use dominant information to refine coverage data We use the dominant information from statements that are covered by a program execution, but we do not use this information when coverable statements with dominant information are not covered. This information can actually be used to set a known outcome taken for a given decision, and to not have degraded origins which can result in uncomplete coverage results being reported at e.g. consolidation. --- tools/gnatcov/coverage-source.adb | 94 ++++++++++++++++++++++++- tools/gnatcov/coverage-source.ads | 3 + tools/gnatcov/decision_map.adb | 6 +- tools/gnatcov/gnatcov_bits_specific.adb | 9 +++ 4 files changed, 106 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index ce4852530..9238fba6d 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -114,8 +114,8 @@ package body Coverage.Source is when Decision => Outcome_Taken, Known_Outcome_Taken : Outcome_Taken_Type := - No_Outcome_Taken; - -- Each of these components is set True when the corresponding + 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 @@ -719,6 +719,8 @@ package body Coverage.Source is 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 @@ -1863,7 +1865,7 @@ package body Coverage.Source is declare SL : constant Tagged_Slocs := - Tag_Provider.Get_Slocs_And_Tags (PC); + Tag_Provider.Get_Slocs_And_Tags (PC); SCOs : access SCO_Id_Array; Single_SCO : aliased SCO_Id_Array := (0 => No_SCO_Id); @@ -1934,6 +1936,92 @@ package body Coverage.Source is end loop Trace_Insns; end Compute_Source_Coverage; + ---------------------------- + -- Refine_Source_Coverage -- + ---------------------------- + + procedure Refine_Source_Coverage + is + -- Refine the outcome taken information. See the documentation of + -- Process_SCO below. + + procedure Process_SCO (SCO : SCO_Id); + -- Infer that an outcome has been taken for the following specific case: + -- * The given SCO is a statement SCO#1 dominated by a decision SCO#2 + -- valuation V. + -- * The decision SCO#2 has an Outcome_Taken (*) set. + -- + -- This configuration allows us to conclude that the "not V" outcome of + -- SCO#2 is covered: set Known_Outcome_Taken accordingly. + -- + -- TODO??? If separate instance coverage is maintained eventually + -- (#258), deal with SCI tags. + + ----------------- + -- Process_SCO -- + ----------------- + + procedure Process_SCO (SCO : SCO_Id) + is + SCI : Source_Coverage_Info_Access; + Dom_SCO : SCO_Id; + Dom_Val : Boolean; + begin + -- If this is not a statement SCO, it does not have dominant + -- information: skip it. + + if Kind (SCO) /= Statement then + return; + end if; + + -- Also skip it if it has no associated SCI, or if this is not a + -- coverable SCO. + + SCI := Get_SCI (SCO, No_SC_Tag); + if SCI = null + or else not SCI.Basic_Block_Has_Code + or else SCI.Executed + then + return; + end if; + + Dominant (SCO, Dom_SCO, Dom_Val); + if Dom_SCO = No_SCO_Id or else Kind (Dom_SCO) /= Decision then + return; + end if; + + -- We deliberately ignore handling of separate instances coverage + -- (with a Tag that is not No_SCO_Tag), to avoid complexifying the + -- implementation. + + SCI := Get_SCI (Dom_SCO, No_SC_Tag); + if SCI /= null then + if SCI.Outcome_Taken (True) or else SCI.Outcome_Taken (False) then + declare + procedure Set_Known_Outcome_Taken + (SCI : in out Source_Coverage_Info); + + ----------------------------- + -- Set_Known_Outcome_Taken -- + ----------------------------- + + procedure Set_Known_Outcome_Taken + (SCI : in out Source_Coverage_Info) is + begin + SCI.Known_Outcome_Taken (not Dom_Val) := True; + end Set_Known_Outcome_Taken; + + begin + Update_SCI + (Dom_SCO, No_SC_Tag, Set_Known_Outcome_Taken'Access); + end; + end if; + end if; + end Process_SCO; + begin + SC_Obligations.Iterate (Process_SCO'Access); + end Refine_Source_Coverage; + procedure Compute_Source_Coverage (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index f75ab36f0..7cc555815 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -83,6 +83,9 @@ package Coverage.Source is -- it must be initialized to the CU for which we are computing coverage or -- left uninitialized. + procedure Refine_Source_Coverage; + -- Refine source coverage according to dominance information + subtype SCO_State is Line_State range Not_Covered .. Undetermined_Coverage; function Get_Line_State (SCO : SCO_Id; diff --git a/tools/gnatcov/decision_map.adb b/tools/gnatcov/decision_map.adb index fd3a9ac2f..49f50338e 100644 --- a/tools/gnatcov/decision_map.adb +++ b/tools/gnatcov/decision_map.adb @@ -1153,7 +1153,7 @@ package body Decision_Map is for J in Boolean'Range loop declare Candidate_Outcome : constant Tristate := - Outcome (CBI.Condition, J); + Outcome (CBI.Condition, J); begin if Candidate_Outcome /= Unknown then Outcome_Seen := True; @@ -1594,8 +1594,8 @@ package body Decision_Map is begin if Candidate_Outcome = Unknown or else not Known_Outcome - (not To_Boolean (Candidate_Outcome)). - Contains (CBI.Edges (Edge).Destination) + (not To_Boolean (Candidate_Outcome)). + Contains (CBI.Edges (Edge).Destination) then Set_Known_Origin (Cond_Branch_PC, diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index d6772c228..4f8451544 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -2206,6 +2206,15 @@ begin Process_Trace (+RT.Filename, +RT.Executable); end loop; + -- Use dominant information to refine decision coverage + -- information wrt. outcomes taken. This is a binary information + -- specificity as we always know which outcomes were taken in the + -- context of source traces. + + if Currently_Accepted_Trace_Kind = Binary_Trace_File then + Refine_Source_Coverage; + end if; + -- Warn when using --scos with source traces or --sid with bin -- traces. From d77285e31bf0233731d9dd7d4f932b054d741e16 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 22 Apr 2024 15:30:59 +0200 Subject: [PATCH 0836/1483] Refactor insertion of with dump helper Move the insertion of the withing of the dump helper unit in the context of the manual dump process to a dedicated procedure. --- tools/gnatcov/instrument-ada_unit.adb | 67 +++++++++++++++------ tools/gnatcov/instrument-ada_unit.ads | 10 ++- tools/gnatcov/instrument-ada_unit__stub.ads | 7 +++ tools/gnatcov/instrument-c.adb | 7 --- tools/gnatcov/instrument-c.ads | 1 - tools/gnatcov/instrument-common.ads | 5 -- tools/gnatcov/instrument-projects.adb | 29 ++++----- 7 files changed, 76 insertions(+), 50 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 3e2fadecf..1fd747740 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -40,7 +40,6 @@ with Libadalang.Sources; use Libadalang.Sources; with GNATCOLL.JSON; use GNATCOLL.JSON; with GNATCOLL.Utils; -with GNATCOLL.VFS; with ALI_Files; use ALI_Files; with Coverage_Options; use Coverage_Options; @@ -8215,7 +8214,6 @@ package body Instrument.Ada_Unit is (Self : in out Ada_Instrumenter_Type; Prj : in out Prj_Desc; Source : GNATCOLL.Projects.File_Info; - Is_Main : Boolean; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean) is @@ -8242,6 +8240,10 @@ package body Instrument.Ada_Unit is -- If N is the expected pragma statement, replace it with the actual -- call. + ----------------------------- + -- Find_And_Replace_Pragma -- + ----------------------------- + function Find_And_Replace_Pragma (N : Ada_Node'Class) return Visit_Status is function Is_Expected_Argument @@ -8358,6 +8360,7 @@ package body Instrument.Ada_Unit is end if; return Into; end Find_And_Replace_Pragma; + begin -- If no pragma is found in this file then Start_Rewriting will not be -- called. In this case, Rewriter.Handle will not be properly @@ -8373,26 +8376,52 @@ package body Instrument.Ada_Unit is if Has_Dump_Indication or else Has_Reset_Indication then Ada.Directories.Create_Path (+Prj.Output_Dir); Rewriter.Apply; - elsif Is_Main then - - -- If this is a main, force a reference to the dump helper unit to - -- ensure coverage buffers make it to the compilation closure. - - Start_Rewriting (Rewriter, Self, Prj, Unit); - Insert_Last - (Handle (Unit.Root.As_Compilation_Unit.F_Prelude), - Create_From_Template - (Rewriter.Handle, - Template => "with {};", - Arguments => - (1 => To_Nodes - (Rewriter.Handle, - Create_Manual_Helper_Unit_Name (Prj))), - Rule => With_Clause_Rule)); - Rewriter.Apply; end if; end Replace_Manual_Indications; + ------------------------------ + -- Insert_With_Dump_Helper -- + ------------------------------ + + procedure Insert_With_Dump_Helper + (Self : in out Ada_Instrumenter_Type; + Source : GNATCOLL.VFS.Virtual_File; + Prj : in out Prj_Desc) + is + Instrumented_Filename : constant String := + +(Prj.Output_Dir & "/" & GNATCOLL.VFS."+" (Source.Base_Name)); + Source_Filename : constant String := + GNATCOLL.VFS."+" (Source.Full_Name); + Instrumented_Exists : constant Boolean := + Ada.Directories.Exists (Instrumented_Filename); + File_To_Search : constant String := (if Instrumented_Exists + then Instrumented_Filename + else Source_Filename); + Unit : constant Libadalang.Analysis.Analysis_Unit := + Self.Context.Get_From_File (File_To_Search, Reparse => True); + + Rewriter : Ada_Source_Rewriter; + + Dummy_Ctx : constant Context_Handle := + Create_Context ("Inserting with dump helper in " & Source_Filename); + + begin + Ada.Directories.Create_Path (+Prj.Output_Dir); + + Start_Rewriting (Rewriter, Self, Prj, Unit); + Insert_Last + (Handle (Unit.Root.As_Compilation_Unit.F_Prelude), + Create_From_Template + (Rewriter.Handle, + Template => "with {};", + Arguments => + (1 => To_Nodes + (Rewriter.Handle, + Create_Manual_Helper_Unit_Name (Prj))), + Rule => With_Clause_Rule)); + Rewriter.Apply; + end Insert_With_Dump_Helper; + ---------------------------- -- Instrument_Source_File -- ---------------------------- diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 06abbab36..c39118419 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -29,6 +29,8 @@ with Libadalang.Analysis; use Libadalang.Analysis; with Libadalang.Config_Pragmas; use Libadalang.Config_Pragmas; with Libadalang.Rewriting; use Libadalang.Rewriting; +with GNATCOLL.VFS; + with Files_Handling; use Files_Handling; with Files_Table; use Files_Table; with Instrument.Ada_Unit_Provider; @@ -96,7 +98,6 @@ package Instrument.Ada_Unit is (Self : in out Ada_Instrumenter_Type; Prj : in out Prj_Desc; Source : GNATCOLL.Projects.File_Info; - Is_Main : Boolean; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean); -- Once the instrumentation has finished, if the dump trigger is "manual" @@ -121,6 +122,13 @@ package Instrument.Ada_Unit is -- the helper unit to ensure the coverage buffers are included in the -- main's compilation closure. + procedure Insert_With_Dump_Helper + (Self : in out Ada_Instrumenter_Type; + Source : GNATCOLL.VFS.Virtual_File; + Prj : in out Prj_Desc); + -- Add a reference to the helper unit to ensure the coverage buffers are + -- included in the main's compilation closure. + overriding procedure Emit_Buffers_List_Unit (Self : Ada_Instrumenter_Type; Instr_Units : Unit_Sets.Set; diff --git a/tools/gnatcov/instrument-ada_unit__stub.ads b/tools/gnatcov/instrument-ada_unit__stub.ads index 8f2d42a5b..9f6424fee 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.ads +++ b/tools/gnatcov/instrument-ada_unit__stub.ads @@ -18,6 +18,8 @@ -- Stub of Instrument.Ada_Unit: see the note about Stubs in gnatcov.gpr +with GNATCOLL.VFS; + with Instrument.Common; use Instrument.Common; package Instrument.Ada_Unit is @@ -42,4 +44,9 @@ package Instrument.Ada_Unit is return Ada_Instrumenter_Type is (Ada_Instrumenter_Type'(others => <>)); + procedure Insert_With_Dump_Helper + (Self : in out Ada_Instrumenter_Type; + Source : GNATCOLL.VFS.Virtual_File; + Prj : in out Prj_Desc) is null; + end Instrument.Ada_Unit; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 353f7bb1d..853eea289 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3852,16 +3852,9 @@ package body Instrument.C is (Self : in out C_Family_Instrumenter_Type; Prj : in out Prj_Desc; Source : GNATCOLL.Projects.File_Info; - Is_Main : Boolean; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean) is - pragma Unreferenced (Is_Main); - -- when C-like languages are present, gprbuild doesn't compile only - -- what's in the closure of the main, but rather all sources and lets - -- the linker only pick the object files that are relevant. As such we - -- don't need to add references to the helper unit in main source files. - Orig_Filename : constant String := +Source.File.Full_Name; begin Check_Compiler_Driver (Prj, Self); diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index ab33c0a96..c6680a8b0 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -62,7 +62,6 @@ package Instrument.C is (Self : in out C_Family_Instrumenter_Type; Prj : in out Prj_Desc; Source : GNATCOLL.Projects.File_Info; - Is_Main : Boolean; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean); -- Preprocess Source and look through the text content of the preprocessed diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index b66c27907..23bc670d9 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -497,7 +497,6 @@ package Instrument.Common is (Self : in out Language_Instrumenter; Prj : in out Prj_Desc; Source : GNATCOLL.Projects.File_Info; - Is_Main : Boolean; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean) is null; -- Look for the pragmas (for Ada) or comments (for C family languages) @@ -506,10 +505,6 @@ package Instrument.Common is -- When found, replace it with a call to the buffers dump/reset procedure -- defined in the dump helper unit. -- - -- Is_Main indicates whether Source would have been instrumented as a main - -- with another dump trigger, each instrumenter may process this - -- information differently. - -- -- Has_Dump_Indication indicates whether a manual dump indication was -- found - and replaced with a call to dump buffers - in the given source. -- diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 101dbc90e..ba248db6d 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -254,8 +254,7 @@ is (Language : Src_Supported_Language; Project_Sources : in out File_Info_Sets.Set; Instrumenter : in out Language_Instrumenter'Class; - Manual_Dump_Inserted : in out Boolean; - Mains : Main_To_Instrument_Vectors.Vector); + Manual_Dump_Inserted : in out Boolean); -- For all sources in Project_Sources of language Language, call -- Replace_Manual_Indications. If a dump procedure call was inserted -- and id there is not one already, also emit a dump helper unit for the @@ -846,8 +845,7 @@ is (Language : Src_Supported_Language; Project_Sources : in out File_Info_Sets.Set; Instrumenter : in out Language_Instrumenter'Class; - Manual_Dump_Inserted : in out Boolean; - Mains : Main_To_Instrument_Vectors.Vector) + Manual_Dump_Inserted : in out Boolean) is package Non_Root_Src_Calls_Sets is new @@ -877,19 +875,10 @@ is Had_Dump_Indication : Boolean := False; Had_Reset_Indication : Boolean := False; - Is_Main : constant Boolean := - (for some Main of Mains => - (GNATCOLL.VFS."+" (Main.File.Full_Name)) = Source_Name); - -- Whether Source is a main which would have been instrumented - -- with another dump trigger. The lookup should be reasonable - -- in cost given that there shouldn't be that many mains in the - -- top level main project. - begin Instrumenter.Replace_Manual_Indications (Prj_Info.Desc, Source, - Is_Main, Had_Dump_Indication, Had_Reset_Indication); @@ -1250,8 +1239,7 @@ begin (Lang, Project_Sources, Instrumenters (Lang).all, - Manual_Dump_Inserted, - Mains_To_Instrument (Lang)); + Manual_Dump_Inserted); end loop; end if; @@ -1557,13 +1545,20 @@ begin (Ada_Language, Project_Sources, Ada_Instrumenter, - Manual_Dump_Inserted, - Mains_To_Instrument (Ada_Language)); + Manual_Dump_Inserted); + + for Main of Mains_To_Instrument (Ada_Language) loop + Insert_With_Dump_Helper + (Ada_Instrumenter, + Source => Main.File, + Prj => Main.Prj_Info.Desc); + end loop; -- At this point, all source files for all languages have been looked -- through to insert a call to the manual dump procedure. If no call -- has been inserted (i.e. no manual dump location indication was -- found), warn the user. + if not Manual_Dump_Inserted then Outputs.Warn ("no indication for dump location was found, this might be" From b48edfe5e9cc110a7ac163609c0388215bb201f0 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 23 Apr 2024 11:26:42 +0200 Subject: [PATCH 0837/1483] Do not consider lambda expressions as scope entities --- tools/gnatcov/instrument-c.adb | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 853eea289..8493e5a50 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2409,14 +2409,15 @@ package body Instrument.C is UIC.MCDC_State_Declaration_Node; Save_Disable_Instrumentation : constant Boolean := UIC.Disable_Instrumentation; + Cursor_Kind : Cursor_Kind_T; begin for N of L loop -- Only traverse the function declarations that belong to a unit of -- interest. if Is_Source_Of_Interest (UIC, N) then - - case Kind (N) is + Cursor_Kind := Kind (N); + case Cursor_Kind is -- Traverse the statements of function bodies @@ -2439,7 +2440,9 @@ package body Instrument.C is -- of the function body. begin - UIC.Pass.Enter_Scope (UIC, N); + if Cursor_Kind /= Cursor_Lambda_Expr then + UIC.Pass.Enter_Scope (UIC, N); + end if; -- Do not instrument constexpr function as it would -- violate the constexpr restrictions. @@ -2459,7 +2462,9 @@ package body Instrument.C is UIC.Pass.Insert_Text_Before_Token (UIC, End_Sloc (Fun_Body), +TB); end if; - UIC.Pass.Exit_Scope (UIC); + if Cursor_Kind /= Cursor_Lambda_Expr then + UIC.Pass.Exit_Scope (UIC); + end if; UIC.Disable_Instrumentation := Save_Disable_Instrumentation; end; From 1d53ca1c436526f2e1af56c91a7cbdaadc078bc0 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 8 Apr 2024 17:26:47 +0200 Subject: [PATCH 0838/1483] minicheck.py: Refactor trace file computation This makes it easier to test the manual dump, e.g. when there are multiple traces emitted with the same naming pattern. --- testsuite/SCOV/minicheck.py | 34 ++++++++++--------- .../instr-cov/manual-dump/trace_index/test.py | 7 ++-- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index cc7c79ff3..004c01e37 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -8,6 +8,7 @@ """ import collections +import glob import json import os.path import re @@ -25,7 +26,6 @@ gprbuild, run_cov_program, srctrace_pattern_for, - srctracename_for, thistest, tracename_for, xcov, @@ -343,17 +343,19 @@ def gprbuild_wrapper(root_project): known_channel = dump_channel or actual_dump_channel - trace_files = [] + # Remove potential existing source trace files: the name is + # non-deterministic by default, so we want to avoid getting + # multiple traces in the current directory. for m in mains: - # Remove potential existing source trace files: the name is - # non-deterministic by default, so we want to avoid getting - # multiple traces in the current directory. rm( srctrace_pattern_for( m, dump_trigger == "manual", manual_prj_name ) ) + patterns = set() + trace_files = [] + for m in mains: out_file = out_file_.format(m) run_cov_program( exepath(m), @@ -377,17 +379,14 @@ def gprbuild_wrapper(root_project): # simply assume that if we fail to get a trace when our context # expects one, there will be some kind of test failure afterwards. - trace_file = None - if known_channel in [None, "bin-file"]: - trace_file = srctracename_for( - m, - register_failure=False, - manual=dump_trigger == "manual", - manual_prj_name=manual_prj_name, + patterns.add( + srctrace_pattern_for( + m, dump_trigger == "manual", manual_prj_name + ) ) - if not trace_file and ( + elif ( known_channel == "base64-stdout" or "source trace file ==" in contents_of(out_file) ): @@ -395,6 +394,7 @@ def gprbuild_wrapper(root_project): src_pattern = srctrace_pattern_for( m, dump_trigger == "manual", manual_prj_name ) + patterns.add(src_pattern) trace_file = src_pattern.replace("*", "unique") # Here we're really supposed to have a trace in the output @@ -403,8 +403,10 @@ def gprbuild_wrapper(root_project): out_file, trace_file, register_failure=register_failure ) - if trace_file: - trace_files.append(abspath(trace_file)) + # Expand the list of patterns + if patterns: + for pattern in patterns: + trace_files.extend(glob.glob(pattern)) xcov_args.extend(cov_or_instr_args) @@ -418,7 +420,7 @@ def gprbuild_wrapper(root_project): elif scos: xcov_args.extend(scos) - return xcov_args + extra_coverage_args + trace_files + return xcov_args + extra_coverage_args + list(trace_files) def build_run_and_coverage( diff --git a/testsuite/tests/instr-cov/manual-dump/trace_index/test.py b/testsuite/tests/instr-cov/manual-dump/trace_index/test.py index ac4bbf494..998bd8ae2 100644 --- a/testsuite/tests/instr-cov/manual-dump/trace_index/test.py +++ b/testsuite/tests/instr-cov/manual-dump/trace_index/test.py @@ -51,11 +51,8 @@ def check_trace(cov_args, traces, index): extra_coverage_args=["-axcov"], ) -# We are expecting three traces, if at this point cov_args has a length of -# less than 4, there's definitively something wrong. -thistest.fail_if( - len(cov_args) < 4, comment=f"expected at least three traces: {cov_args}" -) +# Remove the traces from the coverage arguments +cov_args = cov_args[:-3] traces = glob.glob( srctrace_pattern_for("main", manual=True, manual_prj_name="p") From 59a57e18b7effc3507e8d7977346b985553144fa Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 11 Apr 2024 16:42:32 +0200 Subject: [PATCH 0839/1483] Manual dump-trigger: allow for finer-grained configuration Allow the user to specify the files containing manual indications, through --dump-trigger=manual, where files can either be a list of filenames or a response file containing a list of filenames. --- doc/gnatcov/src_traces.rst | 12 +- .../manual-dump/basic/covdump__cov.adb | 4 +- .../tests/instr-cov/manual-dump/basic/test.py | 5 +- .../manual-dump/files_specified/foo.adb | 7 + .../manual-dump/files_specified/foo_c.c | 6 + .../manual-dump/files_specified/foo_cpp.cpp | 6 + .../files_specified/foo_skipped.adb | 7 + .../files_specified/foo_skipped_c.c | 6 + .../files_specified/foo_skipped_cpp.cpp | 6 + .../manual-dump/files_specified/main.adb | 30 +++ .../manual-dump/files_specified/test.opt | 2 + .../manual-dump/files_specified/test.py | 124 +++++++++ tools/gnatcov/command_line.ads | 67 ++--- tools/gnatcov/instrument-projects.adb | 239 ++++++++++-------- tools/gnatcov/setup_rts.adb | 37 +-- tools/gnatcov/switches.adb | 76 +++++- tools/gnatcov/switches.ads | 4 + 17 files changed, 461 insertions(+), 177 deletions(-) create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/foo.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/foo_c.c create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/foo_cpp.cpp create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_c.c create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_cpp.cpp create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/main.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/test.opt create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/test.py diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index fa0d5492b..566b7be4e 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -297,10 +297,16 @@ to emit this data by inserting: - a ``/* GNATCOV_DUMP_BUFFERS */`` comment on its own line in C and C++ code where necessary in your code. During instrumentation, |gcv| will replace them -with a call to the procedure responsible for dumping the coverage buffers, -at which point the source traces will be created during the execution of the +with a call to the procedure responsible for dumping the coverage buffers, at +which point the source traces will be created during the execution of the program. Therefore, the pragma or comment should be placed at a location at -which such a function call would be appropriate. +which such a function call would be appropriate. By default, gnatcov will look +into all the files of the project. Alternatively, the user can specify the list +of files containing manual indications using +``--dump-trigger=manual,@FILES.list`` or ``--dump-trigger=manual,FILE1,FILE2`` +where the files are specified as full / relative names. Note that for C / C++ +files, the user shall specify the files where the ``/* GNATCOV_DUMP_BUFFERS */`` +indication is ultimately expanded by the preprocessor. A dump procedure is only able to dump the buffers of the project tree which root is the project it is called from. A dump procedure call done in a diff --git a/testsuite/tests/instr-cov/manual-dump/basic/covdump__cov.adb b/testsuite/tests/instr-cov/manual-dump/basic/covdump__cov.adb index 3754a3e67..0e71f53e7 100644 --- a/testsuite/tests/instr-cov/manual-dump/basic/covdump__cov.adb +++ b/testsuite/tests/instr-cov/manual-dump/basic/covdump__cov.adb @@ -2,7 +2,7 @@ with Ada.Command_Line; with Interfaces.C.Strings; use Interfaces.C.Strings; -with GCVRT.P; +with GCVRT.Main; with GNATcov_RTS.Traces.Output.Files; procedure Covdump is @@ -10,7 +10,7 @@ procedure Covdump is New_String (Ada.Command_Line.Command_Name & ".srctrace"); begin GNATcov_RTS.Traces.Output.Files.Write_Trace_File - (Buffers_Groups => GCVRT.P.List, + (Buffers_Groups => GCVRT.Main .List, Filename => Filename); Free (Filename); end Covdump; diff --git a/testsuite/tests/instr-cov/manual-dump/basic/test.py b/testsuite/tests/instr-cov/manual-dump/basic/test.py index b5d3b0845..44352cfd8 100644 --- a/testsuite/tests/instr-cov/manual-dump/basic/test.py +++ b/testsuite/tests/instr-cov/manual-dump/basic/test.py @@ -14,7 +14,7 @@ build_run_and_coverage( gprsw=GPRswitches( gprfor( - prjid="p", + prjid="main", srcdirs=[".."], mains=["main.adb"], langs=["Ada"], @@ -41,13 +41,14 @@ ), covlevel="stmt", mains=["main"], - extra_instr_args=["--dump-trigger=manual"], extra_gprbuild_args=["-XCOV_BUILD=True"], extra_coverage_args=["--annotate=xcov", "-XCOV_BUILD=True"], tolerate_instrument_messages="warning: no indication for dump location was" " found, this might be caused by a" " misspelling in the expected pragma" " statement.", + dump_trigger="manual", + manual_prj_name="main", ) check_xcov_reports("obj", {"main.adb.xcov": {"+": {5}}}) diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/foo.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/foo.adb new file mode 100644 index 000000000..f885b4f2b --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/foo.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; + +procedure Foo is +begin + Ada.Text_IO.Put_Line ("Hello world!"); + pragma Annotate (Xcov, Dump_Buffers); +end Foo; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_c.c b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_c.c new file mode 100644 index 000000000..4c8ae8bfd --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_c.c @@ -0,0 +1,6 @@ +void +foo_c () +{ + int a = 0; + /* GNATCOV_DUMP_BUFFERS */ +} diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_cpp.cpp b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_cpp.cpp new file mode 100644 index 000000000..28ab55088 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_cpp.cpp @@ -0,0 +1,6 @@ +extern "C" void +foo_cpp () +{ + int ret = 0; + /* GNATCOV_DUMP_BUFFERS */ +} diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped.adb new file mode 100644 index 000000000..c5c13aacd --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; + +procedure Foo_Skipped is +begin + Ada.Text_IO.Put_Line ("Hello world!"); + pragma Annotate (Xcov, Dump_Buffers); +end Foo_Skipped; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_c.c b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_c.c new file mode 100644 index 000000000..36d55c5e5 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_c.c @@ -0,0 +1,6 @@ +void +foo_skipped_c () +{ + int a = 0; + /* GNATCOV_DUMP_BUFFERS */ +} diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_cpp.cpp b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_cpp.cpp new file mode 100644 index 000000000..e8611fc8e --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_cpp.cpp @@ -0,0 +1,6 @@ +extern "C" void +foo_skipped_cpp () +{ + int a = 0; + /* GNATCOV_DUMP_BUFFERS */ +} diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/main.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/main.adb new file mode 100644 index 000000000..2073a499a --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/main.adb @@ -0,0 +1,30 @@ +with Foo; +with Foo_Skipped; + +procedure Main is + procedure Foo_C; + pragma Import (C, Foo_C, "foo_c"); + + procedure Foo_Skipped_C; + pragma Import (C, Foo_Skipped_C, "foo_skipped_c"); + + procedure Foo_Cpp; + pragma Import (CPP, Foo_Cpp, "foo_cpp"); + + procedure Foo_Skipped_Cpp; + pragma Import (CPP, Foo_Skipped_CPP, "foo_skipped_cpp"); + +begin + Foo; + pragma Annotate (Xcov, Reset_Buffers); + Foo_Skipped; + pragma Annotate (Xcov, Reset_Buffers); + Foo_C; + pragma Annotate (Xcov, Reset_Buffers); + Foo_Skipped_C; + pragma Annotate (Xcov, Reset_Buffers); + Foo_Cpp; + pragma Annotate (Xcov, Reset_Buffers); + Foo_Skipped_Cpp; + pragma Annotate (Xcov, Reset_Buffers); +end Main; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/test.opt b/testsuite/tests/instr-cov/manual-dump/files_specified/test.opt new file mode 100644 index 000000000..c1c6553e7 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/test.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD GNAT 5.04a1 crashes on unrecognized pragmas +!C++ DEAD Test requires a C++ compiler diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/test.py b/testsuite/tests/instr-cov/manual-dump/files_specified/test.py new file mode 100644 index 000000000..65b61a1b9 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/test.py @@ -0,0 +1,124 @@ +""" +This test checks that when instrumenting a file with +`--dump-trigger=manual,@file`, where file contains the list of files with +manual indications, gnatcov only processes the specific files. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +test_dir = os.getcwd() + +# Expected xcov report +expected_xcov = { + "main.adb.xcov": {"+": {18, 22, 26}, "-": {20, 24, 28}}, + "foo.adb.xcov": {"+": {5}}, + "foo_skipped.adb.xcov": {"-": {5}}, + "foo_c.c.xcov": {"+": {4}}, + "foo_skipped_c.c.xcov": {"-": {4}}, + "foo_cpp.cpp.xcov": {"+": {4}}, + "foo_skipped_cpp.cpp.xcov": {"-": {4}}, +} + + +def GPRswitches_wrapper(): + """ + Generate a project file in the current directory and return the GPRswitches + """ + return GPRswitches( + gprfor( + prjid="main", + srcdirs=[".."], + mains=["main.adb"], + langs=["Ada", "C", "C++"], + ), + ) + + +thistest.log("====== Pass filenames on the command line ======") +tmp = Wdir("tmp_simple") + +# Check by passing a simple filename +build_run_and_coverage( + gprsw=GPRswitches_wrapper(), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov", "--output-dir=xcov"], + dump_trigger="manual,../main.adb,../foo.adb,../foo_c.c,../foo_cpp.cpp", + manual_prj_name="main", +) +check_xcov_reports("xcov", expected_xcov) + +# Check by passing a response file +thistest.log("====== Pass filenames through a response file ======") +tmp.to_homedir() +tmp = Wdir("tmp_resp") + +with open("resp", "w") as resp_file: + resp_file.write(os.path.join(test_dir, "main.adb") + "\n") + resp_file.write(os.path.join(test_dir, "foo.adb") + "\n") + resp_file.write(os.path.join(test_dir, "foo_c.c") + "\n") + resp_file.write(os.path.join(test_dir, "foo_cpp.cpp") + "\n") +build_run_and_coverage( + gprsw=GPRswitches_wrapper(), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov", "--output-dir=xcov"], + dump_trigger="manual,@resp", + manual_prj_name="main", +) +check_xcov_reports("xcov", expected_xcov) + +# Check error cases +thistest.log("===== Check error cases =====") +tmp.to_homedir() +tmp = Wdir("tmp_err") +GPRswitches_wrapper() + +# Check that gnatcov exits with an error when passing a file that does not +# exist. +instr_out = "instr_wrong_file.out" +xcov( + [ + "instrument", + "-Pmain", + "--level=stmt", + "--dump-trigger=manual,unknown", + "--quiet", + ], + out=instr_out, + register_failure=False, +) +thistest.fail_if_no_match( + "missing error in gnatcov instrument output", + r".*/gnatcov(\.exe)?: File unknown does not exist", + contents_of(instr_out), +) + +# Check that gnatcov exits with an error when passing +# --dump-trigger=atexit,file. +instr_out = "instr_wrong_trigger.out" +xcov( + [ + "instrument", + "-Pmain", + "--level=stmt", + "--dump-trigger=atexit,../main.adb", + "--quiet", + ], + out=instr_out, + register_failure=False, +) +thistest.fail_if_no_match( + "missing error in gnatcov instrument output", + r".*/gnatcov(\.exe)?: --dump-trigger=atexit|main-end accepts a single" + " argument", + contents_of(instr_out), +) + +thistest.result() diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index fde4acd13..8d3cfd5f1 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -118,7 +118,6 @@ package Command_Line is Opt_Trace_Source, Opt_Save_Checkpoint, Opt_Report_Title, - Opt_Dump_Trigger, Opt_Dump_Channel, Opt_Dump_Filename_Env_Var, Opt_Dump_Filename_Prefix, @@ -171,7 +170,8 @@ package Command_Line is Opt_CPP_Opts, Opt_Files, Opt_Runtime_Dir, - Opt_Compiler_Wrappers); + Opt_Compiler_Wrappers, + Opt_Dump_Trigger); -- Set of string list options we support. More complete descriptions below. subtype Cmd_Instrument is Command_Type @@ -825,34 +825,6 @@ package Command_Line is At_Most_Once => False, Internal => False), - Opt_Dump_Trigger => Create - (Long_Name => "--dump-trigger", - Help => "Select a trigger to dump coverage buffers in the" - & " instrumented program." - & ASCII.LF & ASCII.LF - & """manual"" (the default) does nothing specific," - & " leaving the responsibility to schedule the dump" - & " when appropriate." - & ASCII.LF & ASCII.LF - & """atexit"" uses the libc's atexit() routine to" - & " schedule the dump." - & ASCII.LF & ASCII.LF - & """main-end"" instructs to append a call to the" - & " dump routine at the end of the main subprogram." - & ASCII.LF & ASCII.LF - & """ravenscar-task-termination"" uses the Ravenscar" - & "-specific Ada.Task_Termination to schedule the" - & " dump on task termination." - & ASCII.LF & ASCII.LF - & "Except for ""manual"", these methods inject code" - & " in all mains in the project closure to dump" - & " coverage buffers for all units of interest in the" - & " main closure. The --dump-channel option" - & " determines the dump procedure.", - Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), - At_Most_Once => False, - Internal => False, - Pattern => "manual|atexit|main-end"), Opt_Dump_Channel => Create (Long_Name => "--dump-channel", Help => "Select a channel to dump coverage buffers in the" @@ -1430,7 +1402,40 @@ package Command_Line is "List of compiler drivers for which we should generate wrappers." & " Supported compilers are: gcc, g++.", Commands => (others => True), - Internal => True) + Internal => True), + + Opt_Dump_Trigger => Create + (Long_Name => "--dump-trigger", + Help => "Select a trigger to dump coverage buffers in the" + & " instrumented program." + & ASCII.LF & ASCII.LF + & """manual"" (the default) does nothing specific," + & " leaving the responsibility to schedule the dump" + & " when appropriate, as specified in the" + & " documentation. A list of files containing the" + & " manual indications can be optionally specified." + & " If not, gnatcov processes every file of the" + & " project." + & ASCII.LF & ASCII.LF + & """atexit"" uses the libc's atexit() routine to" + & " schedule the dump." + & ASCII.LF & ASCII.LF + & """main-end"" instructs to append a call to the" + & " dump routine at the end of the main subprogram." + & ASCII.LF & ASCII.LF + & """ravenscar-task-termination"" uses the Ravenscar" + & "-specific Ada.Task_Termination to schedule the" + & " dump on task termination." + & ASCII.LF & ASCII.LF + & "Except for ""manual"", these methods inject code" + & " in all mains in the project closure to dump" + & " coverage buffers for all units of interest in the" + & " main closure. The --dump-channel option" + & " determines the dump procedure.", + Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), + Pattern => "manual[,FILES]|atexit|main-end", + Internal => False, + Accepts_Comma_Separator => True) ); procedure Bool_Callback diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index ba248db6d..d26b49653 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -254,12 +254,16 @@ is (Language : Src_Supported_Language; Project_Sources : in out File_Info_Sets.Set; Instrumenter : in out Language_Instrumenter'Class; - Manual_Dump_Inserted : in out Boolean); + Manual_Dump_Inserted : in out Boolean; + Manual_Indication_Files : File_Sets.Set); -- For all sources in Project_Sources of language Language, call -- Replace_Manual_Indications. If a dump procedure call was inserted -- and id there is not one already, also emit a dump helper unit for the -- project the source belongs to. Set Manual_Dump_Inserted to True if at -- least one manual dump indication was found. + -- + -- Only process the files that are in Manual_Indication_Files if it is not + -- empty. procedure Add_Instrumented_Unit (Project : GPR.Project_Type; Source_File : GPR.File_Info); @@ -845,7 +849,8 @@ is (Language : Src_Supported_Language; Project_Sources : in out File_Info_Sets.Set; Instrumenter : in out Language_Instrumenter'Class; - Manual_Dump_Inserted : in out Boolean) + Manual_Dump_Inserted : in out Boolean; + Manual_Indication_Files : File_Sets.Set) is package Non_Root_Src_Calls_Sets is new @@ -855,122 +860,136 @@ is -- Set of names of source files containing a dump buffers indication -- that belong to a non-root project. + Processed_Files : File_Info_Sets.Set; + -- List of files processed for the manual indications replacement. This + -- is a subset of Project_Sources, discarding header files and only + -- processing the files specified by the user requested (through + -- --dump-trigger=manual[,FILES]). + begin + -- Filter the set of processed files + for Source of Project_Sources loop if To_Language (Source.Language) = Language - and then Source.Unit_Part = GNATCOLL.Projects.Unit_Body + and then Source.Unit_Part = GNATCOLL.Projects.Unit_Body + and then (Manual_Indication_Files.Is_Empty + or else Manual_Indication_Files.Contains (Source.File)) then - declare - use String_Sets; - - Prj_Info : constant Project_Info_Access := - Get_Or_Create_Project_Info (IC, Source.Project); - Prj : Prj_Desc renames Prj_Info.Desc; - Is_Root_Prj : constant Boolean := - Prj.Prj_Name = Root_Project_Info.Project.Name; - Source_Name : constant String := - GNATCOLL.VFS."+" (Source.File.Full_Name); - Helper_Unit_Name : constant Unbounded_String := - Instrumenter.Dump_Manual_Helper_Unit (Prj).Unit_Name; - Had_Dump_Indication : Boolean := False; - Had_Reset_Indication : Boolean := False; + Processed_Files.Include (Source); + end if; + end loop; - begin - Instrumenter.Replace_Manual_Indications - (Prj_Info.Desc, - Source, - Had_Dump_Indication, - Had_Reset_Indication); - - if (Had_Dump_Indication or else Had_Reset_Indication) - and then not Is_Root_Prj - then - - -- A call to the dump/reset buffers procedure is only able - -- to dump/reset the buffers of the project it is in and its - -- subprojects, meaning coverage data for all projects - -- higher in the project tree will be missing or not reset. - -- Record what file this call was in to warn the user later. - - Non_Root_Src_Calls.Include (Source_Name); - end if; + -- Onto the manual indication replacement - -- Check if we haven't already generated a helper unit for this - -- project and instrumenter. At this point, if the project's - -- object directory and the instrumented sources directory do - -- not exist there is no need to emit the dump helper unit. - -- There are no units of interest or call to a manual dump - -- procedure for this project. - - if not Emitted_Manual_Helpers.Contains (Helper_Unit_Name) - and then Ada.Directories.Exists (+Prj.Output_Dir) - then - Instrumenter.Emit_Dump_Helper_Unit_Manual (Dump_Config, Prj); - - declare - use Files_Table; - Instr_Units : Unit_Sets.Set; - Source_Files : GNATCOLL.VFS.File_Array_Access := - Source.Project.Source_Files - (Recursive => True, - Include_Externally_Built => - Externally_Built_Projects_Processing_Enabled); - begin - for S of Source_Files.all loop - - -- First, check if S is even a source of a language we - -- recognize. If not, it can't have been instrumented - -- so skip it. - - if To_Language_Or_All - (Project.Project.Info (S).Language) = All_Languages - then - goto Skip_File; - end if; + for Source of Processed_Files loop + declare + use String_Sets; + + Prj_Info : constant Project_Info_Access := + Get_Or_Create_Project_Info (IC, Source.Project); + Prj : Prj_Desc renames Prj_Info.Desc; + Is_Root_Prj : constant Boolean := + Prj.Prj_Name = Root_Project_Info.Project.Name; + Source_Name : constant String := + GNATCOLL.VFS."+" (Source.File.Full_Name); + Helper_Unit_Name : constant Unbounded_String := + Instrumenter.Dump_Manual_Helper_Unit (Prj).Unit_Name; + Had_Dump_Indication : Boolean := False; + Had_Reset_Indication : Boolean := False; + begin + Instrumenter.Replace_Manual_Indications + (Prj_Info.Desc, + Source, + Had_Dump_Indication, + Had_Reset_Indication); + + if (Had_Dump_Indication or else Had_Reset_Indication) + and then not Is_Root_Prj + then + -- A call to the dump/reset buffers procedure is only able + -- to dump/reset the buffers of the project it is in and its + -- subprojects, meaning coverage data for all projects + -- higher in the project tree will be missing or not reset. + -- Record what file this call was in to warn the user later. + + Non_Root_Src_Calls.Include (Source_Name); + end if; + + -- Check if we haven't already generated a helper unit for this + -- project and instrumenter. At this point, if the project's + -- object directory and the instrumented sources directory do + -- not exist there is no need to emit the dump helper unit. + -- There are no units of interest or call to a manual dump + -- procedure for this project. + + if not Emitted_Manual_Helpers.Contains (Helper_Unit_Name) + and then Ada.Directories.Exists (+Prj.Output_Dir) + then + Instrumenter.Emit_Dump_Helper_Unit_Manual (Dump_Config, Prj); + + declare + use Files_Table; + Instr_Units : Unit_Sets.Set; + Source_Files : GNATCOLL.VFS.File_Array_Access := + Source.Project.Source_Files + (Recursive => True, + Include_Externally_Built => + Externally_Built_Projects_Processing_Enabled); + begin + for S of Source_Files.all loop + + -- First, check if S is even a source of a language we + -- recognize. If not, it can't have been instrumented + -- so skip it. - declare - use Unit_Maps; - Unit_C : constant Unit_Maps.Cursor := - Instrumented_Sources.Find - (+To_Compilation_Unit - (Project.Project.Info (S)).Unit_Name); - begin - if Unit_C /= Unit_Maps.No_Element then - declare - Unit : constant Library_Unit_Info := - Element (Unit_C); - Instr_Unit : constant Compilation_Unit := - Compilation_Unit' - (Unit.Language_Kind, - Unit.Unit_Name); - begin - if not Instr_Units.Contains (Instr_Unit) then - Instr_Units.Insert (Instr_Unit); - end if; - end; - end if; - end; - <> - end loop; - - -- The creation of the root project's buffers list unit - -- is already taken care of by the regular - -- instrumentation process, so skip it. - - if not Is_Root_Prj then - Instrumenter.Emit_Buffers_List_Unit (Instr_Units, Prj); + if To_Language_Or_All + (Project.Project.Info (S).Language) = All_Languages + then + goto Skip_File; end if; - GNATCOLL.VFS.Unchecked_Free (Source_Files); - end; + declare + use Unit_Maps; + Unit_C : constant Unit_Maps.Cursor := + Instrumented_Sources.Find + (+To_Compilation_Unit + (Project.Project.Info (S)).Unit_Name); + begin + if Unit_C /= Unit_Maps.No_Element then + declare + Unit : constant Library_Unit_Info := + Element (Unit_C); + Instr_Unit : constant Compilation_Unit := + Compilation_Unit' + (Unit.Language_Kind, + Unit.Unit_Name); + begin + if not Instr_Units.Contains (Instr_Unit) then + Instr_Units.Insert (Instr_Unit); + end if; + end; + end if; + end; + <> + end loop; - Emitted_Manual_Helpers.Insert (Helper_Unit_Name); - end if; + -- The creation of the root project's buffers list unit + -- is already taken care of by the regular + -- instrumentation process, so skip it. - Manual_Dump_Inserted := - Manual_Dump_Inserted or else Had_Dump_Indication; - end; - end if; + if not Is_Root_Prj then + Instrumenter.Emit_Buffers_List_Unit (Instr_Units, Prj); + end if; + + GNATCOLL.VFS.Unchecked_Free (Source_Files); + end; + + Emitted_Manual_Helpers.Insert (Helper_Unit_Name); + end if; + + Manual_Dump_Inserted := + Manual_Dump_Inserted or else Had_Dump_Indication; + end; end loop; if not Non_Root_Src_Calls.Is_Empty then @@ -1239,7 +1258,8 @@ begin (Lang, Project_Sources, Instrumenters (Lang).all, - Manual_Dump_Inserted); + Manual_Dump_Inserted, + Dump_Config.Manual_Indication_Files); end loop; end if; @@ -1545,7 +1565,8 @@ begin (Ada_Language, Project_Sources, Ada_Instrumenter, - Manual_Dump_Inserted); + Manual_Dump_Inserted, + Dump_Config.Manual_Indication_Files); for Main of Mains_To_Instrument (Ada_Language) loop Insert_With_Dump_Helper diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index a1227d252..21345068e 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -36,13 +36,14 @@ with GPR2.Project.Configuration; with GPR2.Project.Registry.Attribute; with GPR2.Project.Tree; -with JSON; use JSON; -with Outputs; use Outputs; -with Paths; use Paths; +with Files_Handling; use Files_Handling; +with JSON; use JSON; +with Outputs; use Outputs; +with Paths; use Paths; with Project; -with Subprocesses; use Subprocesses; +with Subprocesses; use Subprocesses; with Support_Files; -with Temp_Dirs; use Temp_Dirs; +with Temp_Dirs; use Temp_Dirs; with Text_Files; package body Setup_RTS is @@ -313,10 +314,12 @@ package body Setup_RTS is -- runtimes). return - (Channel => Base64_Standard_Output, - Trigger => (if GNAT.Regexp.Match (RTS, Ravenscar_RTS_Regexp) - then Ravenscar_Task_Termination - else Main_End)); + (Channel => Base64_Standard_Output, + Trigger => + (if GNAT.Regexp.Match (RTS, Ravenscar_RTS_Regexp) + then Ravenscar_Task_Termination + else Main_End), + Manual_Indication_Files => File_Sets.Empty_Set); end case; end Default_Dump_Config; @@ -1209,16 +1212,18 @@ package body Setup_RTS is case Channel is when Binary_File => Result.Default_Dump_Config := - (Channel => Binary_File, - Trigger => Trigger, - Filename_Simple => Get ("dump-filename-simple"), - Filename_Env_Var => Get ("dump-filename-env-var"), - Filename_Prefix => Get ("dump-filename-prefix")); + (Channel => Binary_File, + Trigger => Trigger, + Filename_Simple => Get ("dump-filename-simple"), + Filename_Env_Var => Get ("dump-filename-env-var"), + Filename_Prefix => Get ("dump-filename-prefix"), + Manual_Indication_Files => File_Sets.Empty_Set); when Base64_Standard_Output => Result.Default_Dump_Config := - (Channel => Base64_Standard_Output, - Trigger => Trigger); + (Channel => Base64_Standard_Output, + Trigger => Trigger, + Manual_Indication_Files => File_Sets.Empty_Set); end case; return Result; diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 534d82c0b..ad8f060ac 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -18,13 +18,15 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Command_Line; +with Ada.Containers; use Ada.Containers; +with Ada.Directories; with Ada.Exceptions; with Ada.Strings.Fixed; -with Ada.Text_IO; use Ada.Text_IO; +with Ada.Text_IO; use Ada.Text_IO; with Inputs; -with Outputs; use Outputs; -with Project; use Project; +with Outputs; use Outputs; +with Project; use Project; package body Switches is @@ -165,10 +167,14 @@ package body Switches is function Load_Dump_Config (Default_Dump_Config : Any_Dump_Config) return Any_Dump_Config is + use String_Vectors; Dump_Channel_Opt : String_Option renames Args.String_Args (Opt_Dump_Channel); - Dump_Trigger_Opt : String_Option renames - Args.String_Args (Opt_Dump_Trigger); + Dump_Trigger_Opt : Vector; + + Manual_Indication_Files : File_Sets.Set; + -- Files containing manual indications (optional) when using the manual + -- dump trigger. Dump_Filename_Env_Var_Opt : String_Option renames Args.String_Args (Opt_Dump_Filename_Env_Var); @@ -194,10 +200,50 @@ package body Switches is end; end if; + -- Two cases for the dump-trigger: + + -- * It is a single string, in which case we expect the dump-trigger + -- to be atexit|main-end|manual. + -- + -- * It is a string list, in which case we expect the first argument + -- to be manual, and the rest a list of files to process for the + -- manual indications replacement. + + Copy_Arg_List (Opt_Dump_Trigger, Dump_Trigger_Opt); Dump_Trigger := Default_Dump_Config.Trigger; - if Dump_Trigger_Opt.Present then + if not Dump_Trigger_Opt.Is_Empty then begin - Dump_Trigger := Value (+Dump_Trigger_Opt.Value); + -- Process the dump trigger value + + Dump_Trigger := Value (+Dump_Trigger_Opt.First_Element); + + -- Now check whether there are additional arguments + + if Dump_Trigger_Opt.Length > 1 then + if Dump_Trigger /= Manual then + Fatal_Error + ("--dump-trigger=atexit|main-end accepts a single" + & " argument"); + end if; + + declare + Cur : Cursor := Next (Dump_Trigger_Opt.First); + begin + while Has_Element (Cur) loop + declare + Filename : constant String := +Element (Cur); + begin + if not Ada.Directories.Exists (Filename) then + Fatal_Error + ("File " & Filename & " does not exist"); + end if; + Manual_Indication_Files.Include + (Create_Normalized (Filename)); + Cur := Next (Cur); + end; + end loop; + end; + end if; exception when Exc : Constraint_Error => Fatal_Error (Ada.Exceptions.Exception_Message (Exc)); @@ -238,15 +284,17 @@ package body Switches is case Dump_Channel is when Binary_File => Dump_Config := - (Channel => Binary_File, - Trigger => Dump_Trigger, - Filename_Simple => Dump_Filename_Simple, - Filename_Env_Var => Dump_Filename_Env_Var, - Filename_Prefix => Dump_Filename_Prefix); + (Channel => Binary_File, + Trigger => Dump_Trigger, + Manual_Indication_Files => Manual_Indication_Files, + Filename_Simple => Dump_Filename_Simple, + Filename_Env_Var => Dump_Filename_Env_Var, + Filename_Prefix => Dump_Filename_Prefix); when Base64_Standard_Output => Dump_Config := - (Channel => Base64_Standard_Output, - Trigger => Dump_Trigger); + (Channel => Base64_Standard_Output, + Trigger => Dump_Trigger, + Manual_Indication_Files => Manual_Indication_Files); end case; end return; end Load_Dump_Config; diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index b19831a74..cae2b753c 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -271,6 +271,10 @@ package Switches is is record Trigger : Any_Dump_Trigger := Manual; + Manual_Indication_Files : File_Sets.Set; + -- Files containing manual indications as specified per the user + -- (optional). + case Channel is when Binary_File => Filename_Simple : Boolean := False; From 7893eca438495459c51de1b650c5647f333c703b Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 23 Apr 2024 11:31:39 +0200 Subject: [PATCH 0840/1483] Minor reformatting --- tools/gnatcov/diagnostics.adb | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/diagnostics.adb b/tools/gnatcov/diagnostics.adb index a80578639..c98265d0b 100644 --- a/tools/gnatcov/diagnostics.adb +++ b/tools/gnatcov/diagnostics.adb @@ -206,13 +206,13 @@ package body Diagnostics is Kind : Report_Kind := Error) is M : constant Message := - (Kind => Kind, - Exe => Exe, - PC => PC, - Sloc => Sloc, - SCO => SCO, - Tag => Tag, - Msg => +Msg); + (Kind => Kind, + Exe => Exe, + PC => PC, + Sloc => Sloc, + SCO => SCO, + Tag => Tag, + Msg => +Msg); begin Output_Message (M); Store_Message (M); From cb86918aade4da1c05251a4c8b2b422acfa1b01c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 23 Apr 2024 11:31:59 +0200 Subject: [PATCH 0841/1483] Add language information to the HTML report Let gnatquilt know about the language for the source file, to improve code highlighting. --- tools/gnatcov/annotations-dynamic_html.adb | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 8508476e0..8f36b6fa9 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -23,6 +23,7 @@ with Ada.Text_IO; with Ada.Text_IO.Unbounded_IO; with GNATCOLL.JSON; use GNATCOLL.JSON; +with GNATCOLL.VFS; use GNATCOLL.VFS; with GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; @@ -34,6 +35,7 @@ with Interfaces; with Outputs; with Project; with Support_Files; use Support_Files; +with Switches; use Switches; with Traces_Disa; with Traces_Files; use Traces_Files; @@ -426,6 +428,44 @@ package body Annotations.Dynamic_Html is Source.Set_Field ("liStats", Line_Stats); Source.Set_Field ("enAllStats", To_JSON (Info.Ob_Stats)); + -- Set the language for this source file + + if Is_Project_Loaded then + + -- If the project was loaded, get the language information from it + + declare + Lang : constant String := + Project.Project.Info (Create (+Info.Full_Name.all)).Language; + begin + case To_Language_Or_All (Lang) is + when Ada_Language => + Source.Set_Field ("language", "ada"); + when C_Language => + Source.Set_Field ("language", "c"); + when CPP_Language => + Source.Set_Field ("language", "cpp"); + when All_Languages => + null; + end case; + end; + else + -- If no project was loaded, infer the language from the + -- source extension. + + declare + Ext : constant String := Extension (Info.Simple_Name.all); + begin + if Ext in "adb" | "ads" | "ada.1" | "ada.2" then + Source.Set_Field ("language", "ada"); + elsif Ext in "c" | "h" then + Source.Set_Field ("language", "c"); + elsif Ext in "cpp" | "cc" | "hpp" then + Source.Set_Field ("language", "cpp"); + end if; + end; + end if; + declare P_Name : constant String := (if Is_Project_Loaded From b349283f5eb0225b4fed3d6ef4a87f623e673e3f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 26 Apr 2024 11:08:31 +0200 Subject: [PATCH 0842/1483] manual-dump/files_specified: fix regression under windows --- testsuite/SCOV/minicheck.py | 15 ++++++--------- .../instr-cov/manual-dump/files_specified/test.py | 6 +++--- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 004c01e37..aef4843e0 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -259,6 +259,9 @@ def gprbuild_wrapper(root_project): xcov_args.extend(cov_or_instr_args) elif trace_mode == "src": + # Deal with --dump-trigger=manual, + is_manual = dump_trigger.split(",")[0] == "manual" + if dump_channel == "auto": dump_channel = default_dump_channel() @@ -347,11 +350,7 @@ def gprbuild_wrapper(root_project): # non-deterministic by default, so we want to avoid getting # multiple traces in the current directory. for m in mains: - rm( - srctrace_pattern_for( - m, dump_trigger == "manual", manual_prj_name - ) - ) + rm(srctrace_pattern_for(m, is_manual, manual_prj_name)) patterns = set() trace_files = [] @@ -381,9 +380,7 @@ def gprbuild_wrapper(root_project): if known_channel in [None, "bin-file"]: patterns.add( - srctrace_pattern_for( - m, dump_trigger == "manual", manual_prj_name - ) + srctrace_pattern_for(m, is_manual, manual_prj_name) ) elif ( @@ -392,7 +389,7 @@ def gprbuild_wrapper(root_project): ): # Pick a trace name that is compatible with srctracename_for src_pattern = srctrace_pattern_for( - m, dump_trigger == "manual", manual_prj_name + m, is_manual, manual_prj_name ) patterns.add(src_pattern) trace_file = src_pattern.replace("*", "unique") diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/test.py b/testsuite/tests/instr-cov/manual-dump/files_specified/test.py index 65b61a1b9..5a8ed0e2b 100644 --- a/testsuite/tests/instr-cov/manual-dump/files_specified/test.py +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/test.py @@ -75,7 +75,7 @@ def GPRswitches_wrapper(): check_xcov_reports("xcov", expected_xcov) # Check error cases -thistest.log("===== Check error cases =====") +thistest.log("====== Check error cases ======") tmp.to_homedir() tmp = Wdir("tmp_err") GPRswitches_wrapper() @@ -96,7 +96,7 @@ def GPRswitches_wrapper(): ) thistest.fail_if_no_match( "missing error in gnatcov instrument output", - r".*/gnatcov(\.exe)?: File unknown does not exist", + r".*gnatcov(\.exe)?: File unknown does not exist", contents_of(instr_out), ) @@ -116,7 +116,7 @@ def GPRswitches_wrapper(): ) thistest.fail_if_no_match( "missing error in gnatcov instrument output", - r".*/gnatcov(\.exe)?: --dump-trigger=atexit|main-end accepts a single" + r".*gnatcov(\.exe)?: --dump-trigger=atexit|main-end accepts a single" " argument", contents_of(instr_out), ) From cfec24008e1c51d9f0255a842e88ed997cea2ffe Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 26 Apr 2024 12:45:25 +0200 Subject: [PATCH 0843/1483] LICENSE: remove outdated license terms The html report no longer uses the Google Closure library. --- tools/gnatcov/LICENSE.dhtml | 182 ------------------------------------ 1 file changed, 182 deletions(-) diff --git a/tools/gnatcov/LICENSE.dhtml b/tools/gnatcov/LICENSE.dhtml index 772898263..162c3ba4f 100644 --- a/tools/gnatcov/LICENSE.dhtml +++ b/tools/gnatcov/LICENSE.dhtml @@ -1,184 +1,2 @@ GNATcoverage as a whole is licensed under the terms of the General Public License version 3 (see LICENSE). - -However, the gnatcov-dhtml.min.js file used in dynamic html reports -incorporates code from the Google Closure library -(http://code.google.com/p/closure-library/) licensed under the Apache 2.0 -license reproduced below: - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS From 207350242fdbaebca1adda83e2fcdf87298635f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Mon, 22 Apr 2024 11:09:15 +0200 Subject: [PATCH 0844/1483] Attach violations to last location All violations were always attached to the first line of the statement or decision it is relative to. For report formats displaying violations in the source code, whenever a statement or decision spaned multiple lines it was "cut" by the violations as they were shown directly under the first line. To improve readability, violations are now attached to the last line of the statement or decision so they can be displayed after the last line. This also has the added bonus of allowing the user to select the text of the statement or decision with no hindrance from the violations. --- .../tests/285-violations-display/ref.xcov | 51 ++++++++++++++++++ .../tests/285-violations-display/src/main.adb | 38 +++++++++++++ .../tests/285-violations-display/test.py | 38 +++++++++++++ tools/gnatcov/annotations-report.adb | 6 ++- tools/gnatcov/diagnostics.adb | 53 ++++++++++++------- tools/gnatcov/diagnostics.ads | 30 ++++++----- 6 files changed, 182 insertions(+), 34 deletions(-) create mode 100644 testsuite/tests/285-violations-display/ref.xcov create mode 100644 testsuite/tests/285-violations-display/src/main.adb create mode 100644 testsuite/tests/285-violations-display/test.py diff --git a/testsuite/tests/285-violations-display/ref.xcov b/testsuite/tests/285-violations-display/ref.xcov new file mode 100644 index 000000000..3a00e7605 --- /dev/null +++ b/testsuite/tests/285-violations-display/ref.xcov @@ -0,0 +1,51 @@ +(.|\n)* +21% of 19 lines covered +67% statement coverage \(6 out of 9\) +50% decision coverage \(1 out of 2\) +20% MC\/DC coverage \(1 out of 5\) + +Coverage level: stmt\+mcdc + 1 \.: procedure Main + 2 \.: is + 3 \+: T : Boolean := True; + 4 \+: F : Boolean := False; + 5 \.: + 6 \.: function Concat \(S1, S2, S3: String\) return String is + 7 \.: begin + 8 -: return S1 & S2 & S3; +statement "return S1\.\.\." at 8:9 not executed + 9 \.: end Concat; + 10 \.: + 11 \.: procedure Test \(B : Boolean\) is + 12 \.: begin + 13 !: if B + 14 !: and then + 15 !: \(T + 16 !: or else F\) +condition "T" at 15:18 has no independent influence pair, MC/DC not achieved +condition "F" at 16:25 has no independent influence pair, MC/DC not achieved + 17 \.: then + 18 !: if F + 19 !: or else + 20 !: F +decision "F\.\.\." at 18:16 outcome TRUE never exercised + 21 \.: then + 22 \.: declare + 23 -: Dummy : String := Concat + 24 -: \( + 25 -: "B", + 26 -: "C", + 27 -: "D" + 28 -: \); +statement "Dummy : S\.\.\." at 23:21 not executed + 29 \.: begin + 30 -: null; +statement "null;" at 30:21 not executed + 31 \.: end; + 32 \.: end if; + 33 \.: end if; + 34 \.: end Test; + 35 \.: begin + 36 \+: Test \(T\); + 37 \+: Test \(F\); + 38 \.: end Main; diff --git a/testsuite/tests/285-violations-display/src/main.adb b/testsuite/tests/285-violations-display/src/main.adb new file mode 100644 index 000000000..5880ee71f --- /dev/null +++ b/testsuite/tests/285-violations-display/src/main.adb @@ -0,0 +1,38 @@ +procedure Main +is + T : Boolean := True; + F : Boolean := False; + + function Concat (S1, S2, S3: String) return String is + begin + return S1 & S2 & S3; + end Concat; + + procedure Test (B : Boolean) is + begin + if B + and then + (T + or else F) + then + if F + or else + F + then + declare + Dummy : String := Concat + ( + "B", + "C", + "D" + ); + begin + null; + end; + end if; + end if; + end Test; +begin + Test (T); + Test (F); +end Main; diff --git a/testsuite/tests/285-violations-display/test.py b/testsuite/tests/285-violations-display/test.py new file mode 100644 index 000000000..31d7d3ca3 --- /dev/null +++ b/testsuite/tests/285-violations-display/test.py @@ -0,0 +1,38 @@ +""" +Check the display of violations in xcov reports. They should always be +attached to the last line of the statement/decision and displayed after +its last line. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +root = gprfor( + prjid="gen", + srcdirs="../src", + mains=["main.adb"], + objdir="obj", +) + +build_run_and_coverage( + gprsw=GPRswitches(root), + covlevel="stmt+mcdc", + mains=["main"], + trace_mode="src", + extra_coverage_args=["--annotate=xcov+"], +) + +# Check the contents of the report by comparing it to the exact expected report +# as we want to make sure the violations are displayed where they should. +thistest.fail_if_no_match( + "xcov+ report", + contents_of("../ref.xcov"), + contents_of("obj/main.adb.xcov"), +) + +thistest.result() diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index cec99855e..5595c9e7c 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -579,7 +579,11 @@ package body Annotations.Report is end if; else - Put (Output.all, Image (M.Sloc, Unique_Name => True)); + Put (Output.all, Image + ((if SC_Obligations.Kind (M.SCO) = Condition + then First_Sloc (Enclosing_Decision (M.SCO)) + else First_Sloc (M.SCO)), + Unique_Name => True)); Put (Output.all, ": "); end if; diff --git a/tools/gnatcov/diagnostics.adb b/tools/gnatcov/diagnostics.adb index c98265d0b..1e30687ee 100644 --- a/tools/gnatcov/diagnostics.adb +++ b/tools/gnatcov/diagnostics.adb @@ -108,7 +108,7 @@ package body Diagnostics is -- Diagnostics can be emitted before the file table is complete, -- so we cannot rely on unique filenames, here. - return " " & Image (M.Sloc, Unique_Name => False) & ":"; + return " " & Image (M.Violation_Sloc, Unique_Name => False) & ":"; else return ""; end if; @@ -197,22 +197,26 @@ package body Diagnostics is end Report; procedure Report - (Msg : String; - Exe : Exe_File_Acc := null; - PC : Pc_Type := No_PC; - Sloc : Source_Location := No_Location; - SCO : SCO_Id := No_SCO_Id; - Tag : SC_Tag := No_SC_Tag; - Kind : Report_Kind := Error) + (Msg : String; + Exe : Exe_File_Acc := null; + PC : Pc_Type := No_PC; + Sloc : Source_Location := No_Location; + Violation_Sloc : Source_Location := No_Location; + SCO : SCO_Id := No_SCO_Id; + Tag : SC_Tag := No_SC_Tag; + Kind : Report_Kind := Error) is M : constant Message := - (Kind => Kind, - Exe => Exe, - PC => PC, - Sloc => Sloc, - SCO => SCO, - Tag => Tag, - Msg => +Msg); + (Kind => Kind, + Exe => Exe, + PC => PC, + Sloc => Sloc, + Violation_Sloc => (if Sloc /= No_Location + then Sloc + else Violation_Sloc), + SCO => SCO, + Tag => Tag, + Msg => +Msg); begin Output_Message (M); Store_Message (M); @@ -228,18 +232,29 @@ package body Diagnostics is Msg : String; Kind : Coverage_Kind) is - Sloc : Source_Location; + Sloc : Source_Location; + -- Sloc of the message + + Violation_Sloc : Source_Location; + -- Sloc of the violation the message expresses begin -- For an MC/DC violation, the message is attached to the decision for -- the benefit of HTML output. if SC_Obligations.Kind (SCO) = Condition then - Sloc := First_Sloc (Enclosing_Decision (SCO)); + Sloc := Last_Sloc (Enclosing_Decision (SCO)); + Violation_Sloc := First_Sloc (Enclosing_Decision (SCO)); else - Sloc := First_Sloc (SCO); + Sloc := Last_Sloc (SCO); + Violation_Sloc := First_Sloc (SCO); end if; - Report (Msg, Sloc => Sloc, SCO => SCO, Tag => Tag, Kind => Kind); + Report (Msg, + Sloc => Sloc, + Violation_Sloc => Violation_Sloc, + SCO => SCO, + Tag => Tag, + Kind => Kind); end Report_Coverage; ---------------------- diff --git a/tools/gnatcov/diagnostics.ads b/tools/gnatcov/diagnostics.ads index c512957c5..13501f857 100644 --- a/tools/gnatcov/diagnostics.ads +++ b/tools/gnatcov/diagnostics.ads @@ -60,13 +60,14 @@ package Diagnostics is subtype Coverage_Kind is Report_Kind range Info .. Exclusion; type Message is record - Kind : Report_Kind; - Exe : Exe_File_Acc; - PC : Pc_Type; - Sloc : Source_Location; - SCO : SCO_Id; - Tag : SC_Tag; - Msg : Unbounded_String; + Kind : Report_Kind; + Exe : Exe_File_Acc; + PC : Pc_Type; + Sloc : Source_Location; + Violation_Sloc : Source_Location; + SCO : SCO_Id; + Tag : SC_Tag; + Msg : Unbounded_String; end record; package Message_Vectors is new Ada.Containers.Vectors @@ -110,13 +111,14 @@ package Diagnostics is -- has message kind Exclusion. procedure Report - (Msg : String; - Exe : Exe_File_Acc := null; - PC : Pc_Type := No_PC; - Sloc : Source_Location := No_Location; - SCO : SCO_Id := No_SCO_Id; - Tag : SC_Tag := No_SC_Tag; - Kind : Report_Kind := Error); + (Msg : String; + Exe : Exe_File_Acc := null; + PC : Pc_Type := No_PC; + Sloc : Source_Location := No_Location; + Violation_Sloc : Source_Location := No_Location; + SCO : SCO_Id := No_SCO_Id; + Tag : SC_Tag := No_SC_Tag; + Kind : Report_Kind := Error); -- Output diagnostic message during coverage analysis. Messages with Notice -- kind are omitted unless global flag Verbose is set. A prefix is -- prepended depending on message kind: From b70d00128f1841e9982f29fa2871f54c9102cd38 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 2 May 2024 10:32:33 +0200 Subject: [PATCH 0845/1483] Only use the last occurence of --dump-trigger --dump-trigger used to be a string option, which meant only the last occurrence was used, and previous ones were ignored. This changed when --dump-trigger=manual started accepting a comma-separated list of files in which to search for a manual dump indication, and thus all occurrences of the --dump-trigger switch were concatenated together. This change restores the original behavior, only taking into account the last --dump-trigger switch, but still processing the value as a comma-separated list. --- testsuite/SCOV/minicheck.py | 4 +- .../tests/275-dump-trigger-last/main.adb | 8 ++ .../tests/275-dump-trigger-last/test.opt | 2 + testsuite/tests/275-dump-trigger-last/test.py | 98 +++++++++++++++++++ tools/gnatcov/argparse.adb | 19 +--- tools/gnatcov/command_line.ads | 80 ++++++++------- tools/gnatcov/strings.adb | 24 +++++ tools/gnatcov/strings.ads | 5 + tools/gnatcov/switches.adb | 20 +++- 9 files changed, 203 insertions(+), 57 deletions(-) create mode 100644 testsuite/tests/275-dump-trigger-last/main.adb create mode 100644 testsuite/tests/275-dump-trigger-last/test.opt create mode 100644 testsuite/tests/275-dump-trigger-last/test.py diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index aef4843e0..9fc4dd968 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -260,7 +260,9 @@ def gprbuild_wrapper(root_project): elif trace_mode == "src": # Deal with --dump-trigger=manual, - is_manual = dump_trigger.split(",")[0] == "manual" + is_manual = ( + dump_trigger.split(",")[0] == "manual" if dump_trigger else False + ) if dump_channel == "auto": dump_channel = default_dump_channel() diff --git a/testsuite/tests/275-dump-trigger-last/main.adb b/testsuite/tests/275-dump-trigger-last/main.adb new file mode 100644 index 000000000..fb43c3230 --- /dev/null +++ b/testsuite/tests/275-dump-trigger-last/main.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("This is a first statement"); + pragma Annotate (Xcov, Dump_Buffers); + Put_Line ("This is a second statement"); +end Main; diff --git a/testsuite/tests/275-dump-trigger-last/test.opt b/testsuite/tests/275-dump-trigger-last/test.opt new file mode 100644 index 000000000..a31a7dfe1 --- /dev/null +++ b/testsuite/tests/275-dump-trigger-last/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD test specific to source traces +5.04a1 DEAD Compiler tries to resolve symbols in pragma annotate diff --git a/testsuite/tests/275-dump-trigger-last/test.py b/testsuite/tests/275-dump-trigger-last/test.py new file mode 100644 index 000000000..03fea8e33 --- /dev/null +++ b/testsuite/tests/275-dump-trigger-last/test.py @@ -0,0 +1,98 @@ +""" +Test that "gnatcov instrument" only uses the last --dump-trigger option +present on the command line or project file. This was no longer the case when +--dump-trigger=manual started accepting files to be searched as a comma +separated string. +""" + +import glob + +from SCOV.instr import default_dump_trigger +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches, gprcov_for, Csw +from SUITE.tutils import gprfor + +expected_cov = {"main.adb.xcov": {"+": {5, 7}}} + +tmp = Wdir() + + +def check_one(tc_id, extra_instr_args=None, extra_prj_content=""): + """ + Run a build, run, coverage and report-check workflow. The expected coverage + shall always be expected_cov. + + tc_prefix is used to differentiate artefact names from each invocation, + namely the temporary directory name. + + extra_instr_args is forwarded to build_and_run's homonym parameter, note + that if it is left empty, no --dump-trigger switch will be passed to the + gnatcov instrument invocation. + + extra_prj_content is passed to gprfor's extra parameter if not None. + """ + + tmp.to_subdir(f"tmp_{tc_id}") + thistest.log(f"========= {tc_id} =========") + prj = gprfor( + mains=["main.adb"], + srcdirs=[".."], + extra=extra_prj_content, + ) + build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + dump_trigger=None, + mains=["main"], + extra_instr_args=extra_instr_args, + extra_coverage_args=["-axcov"], + ) + check_xcov_reports("obj", expected_cov) + + # Check that a single trace was created + nb_traces = len(glob.glob("*.srctrace")) + thistest.fail_if_not_equal( + "Unexpected number of traces", expected=1, actual=nb_traces + ) + + +# Auto dump trigger to be used in the test +dump_trigger = default_dump_trigger(["main.adb"]) + +# Test that with two arguments on the command line, only the second one is +# taken into account. +check_one( + "cmd_line", + extra_instr_args=[ + "--dump-trigger=manual", + f"--dump-trigger={dump_trigger}", + ], +) + +# Test that if there is a dump trigger indication in the project file, and on +# the command line, the later will be used. +check_one( + "prj_and_cmd", + extra_instr_args=[f"--dump-trigger={dump_trigger}"], + extra_prj_content=gprcov_for( + switches=[Csw("instrument", ["--dump-trigger=manual"])] + ), +) + +# Test that if there are multiple occurrences of the --dump-trigger switch in +# the project Switches attribute, only the last one is used. +check_one( + "prj_switches", + extra_prj_content=gprcov_for( + switches=[ + Csw( + "instrument", + ["--dump-trigger=manual", f"--dump-trigger={dump_trigger}"], + ) + ] + ), +) + +thistest.result() diff --git a/tools/gnatcov/argparse.adb b/tools/gnatcov/argparse.adb index 22758e2c4..16264519e 100644 --- a/tools/gnatcov/argparse.adb +++ b/tools/gnatcov/argparse.adb @@ -804,24 +804,7 @@ package body Argparse is -- Split values for comma-separated string list options - declare - Last : constant Natural := Length (Str); - Arg_Start_Index : Natural := 1; - begin - -- Add a value for all slices before commas - - for I in 1 .. Last loop - if Element (Str, I) = ',' then - Str_Vec.Append - (Unbounded_Slice (Str, Arg_Start_Index, I - 1)); - Arg_Start_Index := I + 1; - end if; - end loop; - - -- Do not forget to add the slice after the comma - - Str_Vec.Append (Unbounded_Slice (Str, Arg_Start_Index, Last)); - end; + Append_From_String (Str_Vec, Str); return False; else diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 8d3cfd5f1..61c68ea96 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -118,6 +118,7 @@ package Command_Line is Opt_Trace_Source, Opt_Save_Checkpoint, Opt_Report_Title, + Opt_Dump_Trigger, Opt_Dump_Channel, Opt_Dump_Filename_Env_Var, Opt_Dump_Filename_Prefix, @@ -170,8 +171,7 @@ package Command_Line is Opt_CPP_Opts, Opt_Files, Opt_Runtime_Dir, - Opt_Compiler_Wrappers, - Opt_Dump_Trigger); + Opt_Compiler_Wrappers); -- Set of string list options we support. More complete descriptions below. subtype Cmd_Instrument is Command_Type @@ -825,6 +825,47 @@ package Command_Line is At_Most_Once => False, Internal => False), + -- --dump-trigger is a special case: It used to only accept a single + -- value, but it now should also accept a comma separated list of + -- filenames for the manual case. In order not to break compatibility + -- with the previous behavior (last --dump-trigger switch present was + -- the one used), we'll need to split the option string manually. + + Opt_Dump_Trigger => Create + (Long_Name => "--dump-trigger", + Help => "Select a trigger to dump coverage buffers in the" + & " instrumented program." + & ASCII.LF & ASCII.LF + & """manual"" (the default) does nothing specific," + & " leaving the responsibility to schedule the dump" + & " when appropriate, as specified in the" + & " documentation. A list of files containing the" + & " manual indications can be optionally specified." + & " If not, gnatcov processes every file of the" + & " project." + & ASCII.LF & ASCII.LF + & """atexit"" uses the libc's atexit() routine to" + & " schedule the dump." + & ASCII.LF & ASCII.LF + & """main-end"" instructs to append a call to the" + & " dump routine at the end of the main subprogram." + & ASCII.LF & ASCII.LF + & """ravenscar-task-termination"" uses the Ravenscar" + & "-specific Ada.Task_Termination to schedule the" + & " dump on task termination." + & ASCII.LF & ASCII.LF + & "Except for ""manual"", these methods inject code" + & " in all mains in the project closure to dump" + & " coverage buffers for all units of interest in the" + & " main closure. The --dump-channel option" + & " determines the dump procedure." + & ASCII.LF & ASCII.LF & "Only the last occurrence of" + & " the switch is taken into account.", + Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), + At_Most_Once => False, + Pattern => "manual[,FILES]|atexit|main-end", + Internal => False), + Opt_Dump_Channel => Create (Long_Name => "--dump-channel", Help => "Select a channel to dump coverage buffers in the" @@ -1402,40 +1443,7 @@ package Command_Line is "List of compiler drivers for which we should generate wrappers." & " Supported compilers are: gcc, g++.", Commands => (others => True), - Internal => True), - - Opt_Dump_Trigger => Create - (Long_Name => "--dump-trigger", - Help => "Select a trigger to dump coverage buffers in the" - & " instrumented program." - & ASCII.LF & ASCII.LF - & """manual"" (the default) does nothing specific," - & " leaving the responsibility to schedule the dump" - & " when appropriate, as specified in the" - & " documentation. A list of files containing the" - & " manual indications can be optionally specified." - & " If not, gnatcov processes every file of the" - & " project." - & ASCII.LF & ASCII.LF - & """atexit"" uses the libc's atexit() routine to" - & " schedule the dump." - & ASCII.LF & ASCII.LF - & """main-end"" instructs to append a call to the" - & " dump routine at the end of the main subprogram." - & ASCII.LF & ASCII.LF - & """ravenscar-task-termination"" uses the Ravenscar" - & "-specific Ada.Task_Termination to schedule the" - & " dump on task termination." - & ASCII.LF & ASCII.LF - & "Except for ""manual"", these methods inject code" - & " in all mains in the project closure to dump" - & " coverage buffers for all units of interest in the" - & " main closure. The --dump-channel option" - & " determines the dump procedure.", - Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), - Pattern => "manual[,FILES]|atexit|main-end", - Internal => False, - Accepts_Comma_Separator => True) + Internal => True) ); procedure Bool_Callback diff --git a/tools/gnatcov/strings.adb b/tools/gnatcov/strings.adb index 9d6a9c8ce..35307871d 100644 --- a/tools/gnatcov/strings.adb +++ b/tools/gnatcov/strings.adb @@ -315,4 +315,28 @@ package body Strings is end Match_Pattern_List; + ------------------------ + -- Append_From_String -- + ------------------------ + + procedure Append_From_String + (Vec : in out String_Vectors.Vector; From : Unbounded_String) + is + Last : constant Natural := Length (From); + Arg_Start_Index : Natural := 1; + begin + -- Add a value for all slices before commas + + for I in 1 .. Last loop + if Element (From, I) = ',' then + Vec.Append (Unbounded_Slice (From, Arg_Start_Index, I - 1)); + Arg_Start_Index := I + 1; + end if; + end loop; + + -- Do not forget to add the slice after the comma + + Vec.Append (Unbounded_Slice (From, Arg_Start_Index, Last)); + end Append_From_String; + end Strings; diff --git a/tools/gnatcov/strings.ads b/tools/gnatcov/strings.ads index f28db22f4..5c0b59f13 100644 --- a/tools/gnatcov/strings.ads +++ b/tools/gnatcov/strings.ads @@ -151,6 +151,11 @@ package Strings is -- TODO??? Handle Unicode source texts + procedure Append_From_String + (Vec : in out String_Vectors.Vector; From : Unbounded_String); + -- Process From as if it was a comma separated list, and append each + -- element to Vec. + private pragma Inline (Hash); pragma Inline (Equal); diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index ad8f060ac..138b262d1 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -209,10 +209,26 @@ package body Switches is -- to be manual, and the rest a list of files to process for the -- manual indications replacement. - Copy_Arg_List (Opt_Dump_Trigger, Dump_Trigger_Opt); Dump_Trigger := Default_Dump_Config.Trigger; - if not Dump_Trigger_Opt.Is_Empty then + if Args.String_Args (Opt_Dump_Trigger).Present then begin + -- Post-process the switch value manually, see comment for the + -- Opt_Dump_Trigger option in command_lines.ads. + + declare + Non_Expanded_Args : Vector; + begin + -- Split the argument in a string list + + Append_From_String + (Non_Expanded_Args, + Args.String_Args (Opt_Dump_Trigger).Value); + + -- Expand possible response files + + Copy_Arg_List (Non_Expanded_Args, Dump_Trigger_Opt); + end; + -- Process the dump trigger value Dump_Trigger := Value (+Dump_Trigger_Opt.First_Element); From 5d95f718493336e993831f4cc792460c171ffc9b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 3 May 2024 11:24:05 +0200 Subject: [PATCH 0846/1483] gnatcov_rts: Make internal utility functions static This is to avoid symbol conflict with user code. This also adds a test checking that gnatcov_rts does not export any symbol that is not prefixed with "gnatcov_rts". --- testsuite/tests/292-rts-syms/test.opt | 2 + testsuite/tests/292-rts-syms/test.py | 47 +++++++++++++++++++ .../rts/gnatcov_rts_c-traces-output-files.c | 2 +- .../gnatcov/rts/gnatcov_rts_c-traces-output.c | 4 +- 4 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/292-rts-syms/test.opt create mode 100644 testsuite/tests/292-rts-syms/test.py diff --git a/testsuite/tests/292-rts-syms/test.opt b/testsuite/tests/292-rts-syms/test.opt new file mode 100644 index 000000000..b93a4625d --- /dev/null +++ b/testsuite/tests/292-rts-syms/test.opt @@ -0,0 +1,2 @@ +!native DEAD Test need full gnatcov RTS +5.04a1 DEAD This compiler does not ship nm diff --git a/testsuite/tests/292-rts-syms/test.py b/testsuite/tests/292-rts-syms/test.py new file mode 100644 index 000000000..ef88cdedf --- /dev/null +++ b/testsuite/tests/292-rts-syms/test.py @@ -0,0 +1,47 @@ +""" +Check that all external symbols exported by gnatcov_rts are prefixed +with "gnatcov_rts" to avoid conflicts with user code. +""" + +import os + +from e3.os.fs import which + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import contents_of, exename_for, run_and_log, xcov + +tmp = Wdir("tmp_") + +nm = which(exename_for("nm")) + +gcvrt_prefix = "gnatcov_rts" + +# Setup gnatcov locally so we don't need to search for the archive +xcov(["setup", "--prefix", gcvrt_prefix]) + +gnatcov_rts_lib = os.path.join( + gcvrt_prefix, "lib", "gnatcov_rts.static", "libgnatcov_rts.a" +) + +symbol_file = "gnatcov_rts_symbols.txt" +run_and_log( + [ + nm, + "-g", # Only print external symbols + "-U", # Only print symbols defined in the library + "-j", # Only print the symbol name + gnatcov_rts_lib, + ], + output=symbol_file, +) + +symbols = contents_of(symbol_file).splitlines() +for symbol in symbols: + thistest.fail_if( + not symbol.startswith("gnatcov_rts"), + comment=f"gnatcov_rts exports a symbol not prefixed by 'gnatcov_rts'" + f": {symbol}", + ) + +thistest.result() diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c index b0064ca22..eee93a177 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output-files.c @@ -50,7 +50,7 @@ hex_str (uint64_t value) } /* Return the concatenation of the given strings */ -char * +static char * concat (const char *s1, ...) { va_list args; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index 3926d5e1f..c06babb78 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -22,7 +22,7 @@ #include "gnatcov_rts_c-traces.h" #include -const unsigned alignment = sizeof (void *); +static const unsigned alignment = sizeof (void *); struct info_entry { @@ -142,7 +142,7 @@ write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, } /* Write a uint64_t timestamp (by splitting it in uint8_t chunks). */ -void +static void write_date (gnatcov_rts_write_bytes_callback write_bytes, void *output, uint64_t timestamp) { From d3f933bd363874d7488861896ea745b09191d509 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 6 May 2024 10:05:02 +0200 Subject: [PATCH 0847/1483] Kill test for eng/das/cov/gnatcoverage#292 in various configurations The test does not work for gnat 7.1.2 as the nm shipped with the compiler does not support some of the options required in the test, and kill the test for x86 hosts, as some additional symbols unrelated to gnatcov_rts are exported and thus break the test. --- testsuite/tests/292-rts-syms/test.opt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/tests/292-rts-syms/test.opt b/testsuite/tests/292-rts-syms/test.opt index b93a4625d..323e3c035 100644 --- a/testsuite/tests/292-rts-syms/test.opt +++ b/testsuite/tests/292-rts-syms/test.opt @@ -1,2 +1,4 @@ !native DEAD Test need full gnatcov RTS 5.04a1 DEAD This compiler does not ship nm +7.1.2 DEAD The nm version in 7.1.2 does not support the required options +!x86_64 DEAD Additional symbols unrelated to gnatcov_rts exported under x86 From 8ca04b5fcd03fa7a716b440398e1b4e42d192ba8 Mon Sep 17 00:00:00 2001 From: Olivier Hainque Date: Tue, 30 Apr 2024 12:14:41 +0000 Subject: [PATCH 0848/1483] Display srctrace format versions on incompatibility error This change extends the error message displayed by gnatcov when an attempt is made to feed it a src trace advertising a a trace format version different from the one the tool knows how to handle. --- .../280-incompatible-srctrace-formats/p.gpr | 3 ++ .../p0-23-2.srctrace | Bin 0 -> 248 bytes .../280-incompatible-srctrace-formats/p0.adb | 4 ++ .../280-incompatible-srctrace-formats/test.py | 47 ++++++++++++++++++ tools/gnatcov/instrument-input_traces.adb | 9 +++- 5 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/280-incompatible-srctrace-formats/p.gpr create mode 100644 testsuite/tests/280-incompatible-srctrace-formats/p0-23-2.srctrace create mode 100644 testsuite/tests/280-incompatible-srctrace-formats/p0.adb create mode 100644 testsuite/tests/280-incompatible-srctrace-formats/test.py diff --git a/testsuite/tests/280-incompatible-srctrace-formats/p.gpr b/testsuite/tests/280-incompatible-srctrace-formats/p.gpr new file mode 100644 index 000000000..cc2637d0b --- /dev/null +++ b/testsuite/tests/280-incompatible-srctrace-formats/p.gpr @@ -0,0 +1,3 @@ +project P is + for object_dir use "obj"; +end p; diff --git a/testsuite/tests/280-incompatible-srctrace-formats/p0-23-2.srctrace b/testsuite/tests/280-incompatible-srctrace-formats/p0-23-2.srctrace new file mode 100644 index 0000000000000000000000000000000000000000..4773feabe3b153e4ea601708b2fe59d48b413351 GIT binary patch literal 248 zcmZ?wa|}t&FH#oJ~N0w0w8%10J#GW7#Tw699n26evU6^+2wUnheiI0 i+*bVZ>E*^XTkE*88=I^`T}@;@J=q`lhXG;>LO%d%fk9OO literal 0 HcmV?d00001 diff --git a/testsuite/tests/280-incompatible-srctrace-formats/p0.adb b/testsuite/tests/280-incompatible-srctrace-formats/p0.adb new file mode 100644 index 000000000..37a5b708c --- /dev/null +++ b/testsuite/tests/280-incompatible-srctrace-formats/p0.adb @@ -0,0 +1,4 @@ +procedure P0 is +begin + null; +end; diff --git a/testsuite/tests/280-incompatible-srctrace-formats/test.py b/testsuite/tests/280-incompatible-srctrace-formats/test.py new file mode 100644 index 000000000..1453baa53 --- /dev/null +++ b/testsuite/tests/280-incompatible-srctrace-formats/test.py @@ -0,0 +1,47 @@ +""" +Verify that gnatcov errors out when requested to process a source +trace advertising a trace format version other than the one it (gnatcov) +knows to handle, and that the error message contains an indication of +the trace format versions involved. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov + +# The test dir contains a dummy program and a corresponding coverage +# srctrace produced from instrumentation by an old version of gnatcov +# (release 23.2) in a native configuration. + +# Try to analyze this srctrace and expect the trace version check to +# fail immediately. The check is so early that the actual contents of +# the stored trace doesn't really matter, in particular the target/RTS +# configuration for which the trace was produced compared to that for +# which this test is being run. + +tmp = Wdir("tmp_") + +gpr = gprfor(srcdirs=[".."], langs=["Ada"], mains=["p0.adb"]) + +p = xcov( + [ + "coverage", + "--level=stmt", + "-P{}".format(gpr), + "../p0-23-2.srctrace", + ], + register_failure=False, +) + +thistest.fail_if(p.status == 0, "analysis succeeded but was expected to fail") + +thistest.fail_if_no_match( + what="output from gnatcov coverage", + regexp=( + r"(?s:.*p0-23-2.srctrace: Trace format v2 is not supported " + "by this version of gnatcov. Handling v[0-9]+ only.)" + ), + actual=p.out, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 72501e909..1814e8296 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -356,7 +356,14 @@ package body Instrument.Input_Traces is -- Go on checking fields... if Raw_Header.Format_Version /= Current_Version then - Create_Error (Result, "unsupported format version"); + Create_Error ( + Result, + "Trace format v" & + Strings.Img (Integer (Raw_Header.Format_Version)) & + " is not supported by this version of gnatcov. " & + "Handling v" + & Strings.Img (Integer (Current_Version)) & + " only."); return; elsif Raw_Header.Alignment not in 1 | 2 | 4 | 8 then From 879a1ae1bccdbacffba6330a7ee7bfad15af010e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 21 May 2024 11:36:11 +0000 Subject: [PATCH 0849/1483] Link against the static libz --- tools/gnatcov/gnatcov.gpr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 9c0cf90ca..45c6194a4 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -254,7 +254,7 @@ project Gnatcov is "-l:libbfd.a", "-l:libiberty.a", "-l:libsframe.a", - "-lz", + "-l:libz.a", "-static-libstdc++", "-static-libgcc"); end Linker; From b30bf2857058bae473ad2ffe9ed0570a87d9ea79 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 31 May 2024 13:31:48 +0000 Subject: [PATCH 0850/1483] IA22-004-same-basename: adapt after recent GNATCOLL.JSON changes Recent GNATCOLL.JSON changes affected the way JSON values are serialized (object keys are now sorted, they used to appear in order of creation). Adapt a regexp that matches GNATquilt's JSON input files accordingly. --- testsuite/tests/IA22-004-same-basename/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/IA22-004-same-basename/test.py b/testsuite/tests/IA22-004-same-basename/test.py index dce505fa5..d35340357 100644 --- a/testsuite/tests/IA22-004-same-basename/test.py +++ b/testsuite/tests/IA22-004-same-basename/test.py @@ -25,7 +25,7 @@ formats = [ ("xml", "{slug}.xml", r''), - ("html", "{slug}.hunk.js", r'"coverage":"\+","assembly"'), + ("html", "{slug}.hunk.js", r'"coverage":"\+",.*"assembly"'), ("xcov+", "{slug}.xcov", r" *[0-9]+ \+:"), ] From 49471d856d5c56dc8681f35067c0b5537b837014 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 21 May 2024 15:42:05 +0200 Subject: [PATCH 0851/1483] Implement SARIF report generation Generate a SARIF report upon the use of '--annotate=sarif' for source traces. --- tools/gnatcov/annotations-cobertura.adb | 1 - tools/gnatcov/annotations-dynamic_html.adb | 1 - tools/gnatcov/annotations-index.adb | 1 - tools/gnatcov/annotations-report.adb | 106 +---- tools/gnatcov/annotations-report.ads | 4 + tools/gnatcov/annotations-sarif.adb | 494 +++++++++++++++++++++ tools/gnatcov/annotations-sarif.ads | 31 ++ tools/gnatcov/annotations.adb | 84 +++- tools/gnatcov/annotations.ads | 18 + tools/gnatcov/command_line.ads | 3 +- tools/gnatcov/coverage.adb | 23 + tools/gnatcov/coverage.ads | 4 + tools/gnatcov/gnatcov_bits_specific.adb | 26 +- 13 files changed, 681 insertions(+), 115 deletions(-) create mode 100644 tools/gnatcov/annotations-sarif.adb create mode 100644 tools/gnatcov/annotations-sarif.ads diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb index 1af26b4bd..e568ad580 100644 --- a/tools/gnatcov/annotations-cobertura.adb +++ b/tools/gnatcov/annotations-cobertura.adb @@ -32,7 +32,6 @@ with Interfaces.C; use Interfaces.C; with Annotations.Xml; use Annotations.Xml; with Command_Line; use Command_Line; with Coverage; use Coverage; -with Coverage_Options; use Coverage_Options; with Coverage.Source; use Coverage.Source; with Outputs; use Outputs; with Paths; diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 8f36b6fa9..918ba9736 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -29,7 +29,6 @@ with GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; with Annotations.Html; -with Coverage_Options; use Coverage_Options; with Hex_Images; with Interfaces; with Outputs; diff --git a/tools/gnatcov/annotations-index.adb b/tools/gnatcov/annotations-index.adb index b9df60660..63ba55750 100644 --- a/tools/gnatcov/annotations-index.adb +++ b/tools/gnatcov/annotations-index.adb @@ -23,7 +23,6 @@ with Ada.Text_IO; use Ada.Text_IO; with GNAT.OS_Lib; with Coverage; use Coverage; -with Coverage_Options; use Coverage_Options; with Project; with Outputs; use Outputs; diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 5595c9e7c..782086007 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -23,7 +23,6 @@ with Ada.Text_IO; use Ada.Text_IO; with ALI_Files; with Calendar_Utils; use Calendar_Utils; -with Coverage_Options; use Coverage_Options; with Coverage; use Coverage; with Coverage.Source; use Coverage.Source; with Coverage.Tags; use Coverage.Tags; @@ -56,25 +55,6 @@ package body Annotations.Report is -- Pretty printer type for the final report - type Report_Section is - range Coverage_Level'Pos (Coverage_Level'First) - .. Coverage_Level'Pos (Coverage_Level'Last) + 3; - -- There is one report section for each coverage level, plus the following - -- three special sections: - subtype Coverage_Violations is Report_Section - range Coverage_Level'Pos (Coverage_Level'First) - .. Coverage_Level'Pos (Coverage_Level'Last); - - Coverage_Exclusions : constant Report_Section := Report_Section'Last - 2; - Undetermined_Coverage : constant Report_Section := Report_Section'Last - 1; - Other_Errors : constant Report_Section := Report_Section'Last; - - function Section_Of_SCO (SCO : SCO_Id) return Report_Section; - function Section_Of_Message (M : Message) return Report_Section; - -- Indicate the coverage criterion a given SCO/message pertains to (by its - -- 'Pos), or Other_Errors if SCO has no related section/M is not a - -- violation message. - function Underline (S : String; C : Character := '-') return String; -- Return, as a string with line-feeds, S underlined with a sequence -- of C, for example @@ -638,7 +618,7 @@ package body Annotations.Report is "other message", when Coverage_Exclusions => "coverage exclusion", - when Undetermined_Coverage => + when Undet_Coverage => "undetermined coverage item")) & ".")); -- Count of total (coverable) and covered SCOs is displayed only @@ -699,11 +679,11 @@ package body Annotations.Report is -- No need to have the section header and so on if there are no -- non-instrumented constructs. - if not Pp.Nonexempted_Messages (Undetermined_Coverage).Is_Empty then + if not Pp.Nonexempted_Messages (Undet_Coverage).Is_Empty then Pp.Chapter ("UNDETERMINED COVERAGE ITEMS"); New_Line (Output.all); Messages_For_Section - (Undetermined_Coverage, + (Undet_Coverage, Title => "", Item => "undetermined coverage items"); end if; @@ -934,86 +914,6 @@ package body Annotations.Report is New_Line (Output.all); end Section; - ------------------------ - -- Section_Of_Message -- - ------------------------ - - function Section_Of_Message (M : Message) return Report_Section is - begin - if M.SCO /= No_SCO_Id and then M.Kind in Coverage_Kind then - case M.Kind is - when Exclusion => - return Coverage_Exclusions; - when Undetermined_Cov => - return Undetermined_Coverage; - when others => - pragma Assert (M.Kind = Violation or else M.Kind = Info); - - declare - S : constant Report_Section := Section_Of_SCO (M.SCO); - begin - if S = Other_Errors then - -- A violation message is expected to always be relevant to - -- some report section. - - raise Program_Error with "unexpected SCO kind in violation"; - end if; - return S; - end; - end case; - - else - pragma Assert (M.Kind not in Coverage_Kind); - - return Other_Errors; - end if; - end Section_Of_Message; - - -------------------- - -- Section_Of_SCO -- - -------------------- - - function Section_Of_SCO (SCO : SCO_Id) return Report_Section is - MCDC_Section : Report_Section; - begin - -- Need to initialize MCDC_Section specially because it is erroneous - -- to evaluate MCDC_Level if MCDC coverage is not enabled. - - if MCDC_Coverage_Enabled then - MCDC_Section := Coverage_Level'Pos (MCDC_Level); - else - MCDC_Section := Other_Errors; - end if; - - case Kind (SCO) is - when Statement => - return Coverage_Level'Pos (Stmt); - - when Decision => - if Is_Expression (SCO) - and then not Decision_Requires_Assertion_Coverage (SCO) - then - return MCDC_Section; - elsif Decision_Requires_Assertion_Coverage (SCO) then - return Coverage_Level'Pos (ATC); - else - return Coverage_Level'Pos (Decision); - end if; - - when Condition => - if Enabled (ATCC) - and then Decision_Requires_Assertion_Coverage (SCO) - then - return Coverage_Level'Pos (ATCC); - else - return MCDC_Section; - end if; - - when others => - return Other_Errors; - end case; - end Section_Of_SCO; - ----------------- -- Underline -- ----------------- diff --git a/tools/gnatcov/annotations-report.ads b/tools/gnatcov/annotations-report.ads index 13ccc8e27..0126062ec 100644 --- a/tools/gnatcov/annotations-report.ads +++ b/tools/gnatcov/annotations-report.ads @@ -28,4 +28,8 @@ package Annotations.Report is -- null, dump it on stdout. If Dump_Units, add a section to describe the -- list of units of interest considered. + subtype Coverage_Violations is Report_Section + range Coverage_Level'Pos (Coverage_Level'First) + .. Coverage_Level'Pos (Coverage_Level'Last); + end Annotations.Report; diff --git a/tools/gnatcov/annotations-sarif.adb b/tools/gnatcov/annotations-sarif.adb new file mode 100644 index 000000000..d28a648b1 --- /dev/null +++ b/tools/gnatcov/annotations-sarif.adb @@ -0,0 +1,494 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 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.Characters.Handling; +with Ada.Containers.Vectors; + +with Ada.Text_IO; use Ada.Text_IO; + +with GNATCOLL.JSON; use GNATCOLL.JSON; + +with Coverage; use Coverage; +with Outputs; use Outputs; +with Version; + +package body Annotations.Sarif is + + type Result_Info is record + Is_Violation : Boolean; + -- True if is a violation, False if undetermined coverage + + Is_Exempted : Boolean; + -- True is the violation is in an exempted region + + Rule_Id : Unbounded_String; + -- Id of the rule the violation violates + + Message : Unbounded_String; + -- Message describing the cause of the violation + + Location : Unbounded_String; + -- Full name of the file of the violation + + Region : Local_Source_Location; + -- Location of the violation within the file + end record; + -- Record describing the elements of a result. A result represents a + -- violation. + + package Result_Info_Vectors is new Ada.Containers.Vectors + (Index_Type => Natural, + Element_Type => Result_Info); + -- Vector storing the results' information of this run of gnatcov + + type Sarif_Pretty_Printer is new Pretty_Printer with record + -- Pretty printer type for the SARIF annotation format + + Sarif_Filename : Unbounded_String := +"coverage.sarif"; + Sarif_File : File_Type; + + Contents : JSON_Value := Create_Object; + -- JSON value of the whole SARIF report, to be written in the report + -- file. + + Exemption : Slocs.Source_Location := Slocs.No_Location; + -- Exemption sloc applying to current line, if any + + Results : Result_Info_Vectors.Vector := Result_Info_Vectors.Empty_Vector; + -- List of violations to be reported + end record; + -- Pretty printer for the SARIF annotation format + + ------------------------------------------------- + -- Sarif_Pretty_Printer's primitive operations -- + -- (inherited from Pretty_Printer) -- + ------------------------------------------------- + + procedure Pretty_Print_End (Pp : in out Sarif_Pretty_Printer); + + procedure Pretty_Print_Start_File + (Pp : in out Sarif_Pretty_Printer; + File : Source_File_Index; + Skip : out Boolean); + + procedure Pretty_Print_End_File (Pp : in out Sarif_Pretty_Printer) is null; + + procedure Pretty_Print_Start_Line + (Pp : in out Sarif_Pretty_Printer; + Line_Num : Natural; + Info : Line_Info_Access; + Line : String); + + procedure Pretty_Print_Message + (Pp : in out Sarif_Pretty_Printer; + M : Message); + + ---------------------------- + -- SARIF report elements -- + ---------------------------- + + type Rule_Info is record + Id : UTF8_Unbounded_String := Null_Unbounded_String; + -- Unique "code" for the rule + + Name : UTF8_Unbounded_String := Null_Unbounded_String; + -- Full name of the rule + + Short_Descr : UTF8_Unbounded_String := Null_Unbounded_String; + -- Short description of the rule + + Help_Uri : UTF8_Unbounded_String := Null_Unbounded_String; + -- Link to the documentation webpage describing the rule in detail + + Config : UTF8_Unbounded_String := Null_Unbounded_String; + -- Default severity level of a violation of this rule + end record; + -- Coverage analysis rule representation + + type Rules_Range is range + Source_Coverage_Level'Pos (Source_Coverage_Level'First) .. + Source_Coverage_Level'Pos (Source_Coverage_Level'Last) + 1; + + Undet_Rule : constant Rules_Range := Rules_Range'Last; + + type Rule_Info_Arrays is array (Rules_Range) of Rule_Info; + -- List of rules for currently enabled coverage levels, and one rule for + -- undetermined coverage. + + Doc_Link : constant String := + "https://docs.adacore.com/gnatcoverage-docs/html/"; + + Rules : constant Rule_Info_Arrays := + (Source_Coverage_Level'Pos (Stmt) => + (Id => +Stmt'Image, + Name => +"Statement Coverage", + Short_Descr => + +"Control flow should reach the statement at least once.", + Help_Uri => + +(Doc_Link & "gnatcov/cov_source.html#statement-coverage-analysis"), + Config => +"error"), + Source_Coverage_Level'Pos (Decision) => + (Id => +Coverage_Level'Image (Decision), + Name => +"Decision Coverage", + Short_Descr => + +("The decision has been evaluated at least once to True" + & " and once False during program execution"), + Help_Uri => + +(Doc_Link & "gnatcov/cov_source.html#decision-coverage-analysis"), + Config => +"error"), + Source_Coverage_Level'Pos (MCDC) => + (Id => +MCDC'Image, + Name => +"Modified Condition/Decision Coverage", + Short_Descr => + +("The independant effect of the conditions on the" + & " enclosing decision was demonstrated by the tests"), + Help_Uri => +(Doc_Link + & "gnatcov/cov_source.html#modified-condition-decision-coverage" + & "-analysis"), + Config => +"error"), + Source_Coverage_Level'Pos (UC_MCDC) => + (Id => +UC_MCDC'Image, + Name => + +"Unique Cause Modified Condition/Decision Coverage", + Short_Descr => + +("The independent influence of a specific condition" + & " must be demonstrated by a pair of tests where only that" + & " condition changes and the decision value toggles."), + Help_Uri => +(Doc_Link & "gnatcov/cov_source.html#mcdc-variants"), + Config => +"error"), + Source_Coverage_Level'Pos (ATC) => + (Id => +ATC'Image, + Name => +"Assertion True Coverage", + Short_Descr => + +"Control flow should reach the assertion at least once", + Help_Uri => +(Doc_Link + & "gnatcov/cov_source.html#assertion-true-coverage-atc-analysis"), + Config => +"error"), + Source_Coverage_Level'Pos (ATCC) => + (Id => +ATCC'Image, + Name => +"Assertion True Condition Coverage", + Short_Descr => + +("The assertion decision has been evaluated at least once" + & " to True and once False during program execution"), + Help_Uri => +(Doc_Link + & "gnatcov/cov_source.html#assertion-true-condition-coverage-" + & "analysis-atcc"), + Config => +"error"), + Undet_Rule => + (Id => +"UNDET", + Name => +"Undetermined Coverage", + Short_Descr => +("Gnatcov was unable to determine the coverage state" + & " of the obligation"), + Help_Uri => Null_Unbounded_String, + Config => +"warning")); + + function Create_Rules return JSON_Array; + -- Return the SARIF rules for the enabled coverage levels + + function Create_Tool return JSON_Value; + -- Return the SARIF tool informations + + function Create_Results + (Results : Result_Info_Vectors.Vector) + return JSON_Array; + -- Return the JSON array of SARIF results representing each of the + -- violations found. + + ------------------ + -- Create_Rules -- + ------------------ + + function Create_Rules return JSON_Array + is + function Create_Rule (R : Rule_Info) return JSON_Value; + -- Create single rule as a JSON object + + function Create_Rule (R : Rule_Info) return JSON_Value + is + Rule : constant JSON_Value := Create_Object; + Short_Description : constant JSON_Value := Create_Object; + Default_Configuration : constant JSON_Value := Create_Object; + + begin + Rule.Set_Field ("id", R.Id); + Rule.Set_Field ("name", R.Name); + + Short_Description.Set_Field ("text", R.Short_Descr); + Rule.Set_Field ("shortDescription", Short_Description); + + if R.Help_Uri /= Null_Unbounded_String then + Rule.Set_Field ("helpUri", R.Help_Uri); + end if; + + Default_Configuration.Set_Field ("level", R.Config); + Rule.Set_Field ("defaultConfiguration", Default_Configuration); + + return Rule; + end Create_Rule; + + Rules_Arr : JSON_Array := Empty_Array; + begin + for L of Coverage_Levels_Enabled loop + Append + (Rules_Arr, Create_Rule (Rules (Source_Coverage_Level'Pos (L)))); + end loop; + + Append (Rules_Arr, Create_Rule (Rules (Undet_Rule))); + + return Rules_Arr; + end Create_Rules; + + ----------------- + -- Create_Tool -- + ----------------- + + function Create_Tool return JSON_Value + is + function Create_Driver return JSON_Value; + + function Create_Driver return JSON_Value + is + Driver : constant JSON_Value := Create_Object; + begin + Driver.Set_Field ("name", "gnatcov"); + Driver.Set_Field ("version", Standard.Version.Xcov_Version); + Driver.Set_Field ("informationUri", Doc_Link & "gnatcov.html"); + Driver.Set_Field ("rules", Create_Rules); + + return Driver; + end Create_Driver; + + Tool : constant JSON_Value := Create_Object; + begin + Tool.Set_Field ("driver", Create_Driver); + return Tool; + end Create_Tool; + + -------------------- + -- Create_Results -- + -------------------- + + function Create_Results + (Results : Result_Info_Vectors.Vector) + return JSON_Array + is + function Create_Result (R : Result_Info) return JSON_Value; + -- Return a single SARIF results representing one violations + + ------------------- + -- Create_Result -- + ------------------- + + function Create_Result (R : Result_Info) return JSON_Value + is + Res, Msg_Text, Region, Physical_Location, Uri, Locations + : constant JSON_Value := Create_Object; + + Locations_Arr : JSON_Array := Empty_Array; + + begin + -- The level of a result can be one of "none", "note", "warning", + -- "error". We set it according to the following: + -- + -- * error : a non-exempted violation + -- * warning : undetermined coverage + -- * note : an exempted violation + + Res.Set_Field ("ruleId", R.Rule_Id); + Res.Set_Field ("kind", "fail"); + + Res.Set_Field ("level", + (if R.Is_Exempted + then "note" + else + (if R.Is_Violation then "error" else "warning"))); + + Msg_Text.Set_Field ("text", R.Message); + Res.Set_Field ("message", Msg_Text); + + Region.Set_Field ("startLine", R.Region.Line); + Region.Set_Field ("startColumn", R.Region.Column); + + Uri.Set_Field ("uri", R.Location); + Physical_Location.Set_Field ("artifactLocation", Uri); + Physical_Location.Set_Field ("region", Region); + + Locations.Set_Field ("physicalLocation", Physical_Location); + Append (Locations_Arr, Locations); + Res.Set_Field ("locations", Locations_Arr); + + return Res; + end Create_Result; + + Results_Arr : JSON_Array := Empty_Array; + begin + for R of Results loop + Append (Results_Arr, Create_Result (R)); + end loop; + + return Results_Arr; + end Create_Results; + + ----------------------------- + -- Pretty_Print_Start_File -- + ----------------------------- + + procedure Pretty_Print_Start_File + (Pp : in out Sarif_Pretty_Printer; + File : Source_File_Index; + Skip : out Boolean) + is + pragma Unreferenced (Pp); + + Info : constant File_Info_Access := Get_File (File); + begin + if Info.Li_Stats (Covered) /= Get_Total (Info.Li_Stats) then + + -- Some uncovered or partially covered lines are present + + Skip := False; + + else + -- Everything covered: nothing to report for this file + + Skip := True; + end if; + end Pretty_Print_Start_File; + + -------------------------- + -- Pretty_Print_Message -- + -------------------------- + + procedure Pretty_Print_Message + (Pp : in out Sarif_Pretty_Printer; + M : Message) + is + begin + if M.Kind > Notice then + declare + Rep_Section : constant Report_Section := Section_Of_Message (M); + + -- Rep_Section can directly correspond to a source coverage level, + -- or be Coverage_Exclusions, Undet_Coverage or Other_Errors. + -- The message is only added to the SARIF report when Rep_Section + -- is linked to a source coverage level. + + Rep_Section_Pos : constant Integer := + Report_Section'Pos (Rep_Section); + First_Level_Pos : constant Integer := + Source_Coverage_Level'Pos (Source_Coverage_Level'First); + Last_Level_Pos : constant Integer := + Source_Coverage_Level'Pos (Source_Coverage_Level'Last); + Is_Coverage_Level : constant Boolean := + First_Level_Pos <= Rep_Section_Pos + and then Rep_Section_Pos <= Last_Level_Pos; + begin + if (Is_Coverage_Level and then M.Kind in Violation) + or else M.Kind = Undetermined_Cov + then + Pp.Results.Append + ((Is_Violation => M.Kind = Violation, + Is_Exempted => Pp.Exemption /= Slocs.No_Location, + Rule_Id => + (if M.Kind = Undetermined_Cov + then Rules (Undet_Rule).Id + else Rules + (Source_Coverage_Level'Pos + (Coverage_Level'Val (Rep_Section))).Id), + Message => + Ada.Characters.Handling.To_Lower + (SCO_Kind'Image (Kind (M.SCO))) & (+" ") & M.Msg, + Location => + +(Get_File (M.Sloc.Source_File).Full_Name.all), + Region => First_Sloc (M.SCO).L)); + end if; + end; + end if; + end Pretty_Print_Message; + + ----------------------------- + -- Pretty_Print_Start_Line -- + ----------------------------- + + procedure Pretty_Print_Start_Line + (Pp : in out Sarif_Pretty_Printer; + Line_Num : Natural; + Info : Line_Info_Access; + Line : String) + is + pragma Unreferenced (Line_Num, Line); + begin + Pp.Exemption := Info.Exemption; + end Pretty_Print_Start_Line; + + ---------------------- + -- Pretty_Print_End -- + ---------------------- + + procedure Pretty_Print_End (Pp : in out Sarif_Pretty_Printer) + is + function Create_Run return JSON_Value; + + function Create_Run return JSON_Value + is + Run : constant JSON_Value := Create_Object; + begin + Run.Set_Field ("tool", Create_Tool); + Run.Set_Field ("results", Create_Results (Pp.Results)); + + return Run; + end Create_Run; + -- A run represents a single invocation of a single analysis tool, and + -- the run has to describe the tool that produced it. + + Run_Arr : JSON_Array := Empty_Array; + + Schema_Link : constant String := + "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json"; + begin + Pp.Contents.Set_Field ("$schema", Schema_Link); + Pp.Contents.Set_Field ("version", "2.1.0"); + + Append (Run_Arr, Create_Run); + Pp.Contents.Set_Field ("runs", Run_Arr); + + Put_Line (Pp.Sarif_File, Pp.Contents.Write); + end Pretty_Print_End; + + --------------------- + -- Generate_Report -- + --------------------- + + procedure Generate_Report (Context : Coverage.Context_Access) + is + Pp : Sarif_Pretty_Printer := + (Need_Sources => True, + Context => Context, + others => <>); + begin + Create_Output_File (Pp.Sarif_File, +Pp.Sarif_Filename); + + Annotations.Generate_Report + (Pp, + True, + Subdir => ("sarif")); + + Close (Pp.Sarif_File); + end Generate_Report; + +end Annotations.Sarif; diff --git a/tools/gnatcov/annotations-sarif.ads b/tools/gnatcov/annotations-sarif.ads new file mode 100644 index 000000000..0fe7a9044 --- /dev/null +++ b/tools/gnatcov/annotations-sarif.ads @@ -0,0 +1,31 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 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. -- +------------------------------------------------------------------------------ + +package Annotations.Sarif is + + procedure Generate_Report (Context : Coverage.Context_Access); + -- Generate a report in the SARIF report format. This report format + -- is designed to be used in visualiztion tools and IDEs, e.g. + -- VisualStudio. The specification for this format is found here: + -- https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html + -- + -- This format is able to represent all gnatcov source coverage metrics and + -- the corresponding violations. Violations are reported as errors, + -- undertermined coverage as warnings and exempted violations as notes. + +end Annotations.Sarif; diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 5ecf4bfec..f773394c4 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -27,7 +27,6 @@ with Interfaces; with ALI_Files; use ALI_Files; with Calendar_Utils; with Coverage; -with Coverage_Options; use Coverage_Options; with Coverage.Object; with Coverage.Source; use Coverage.Source; with Coverage.Tags; @@ -863,6 +862,9 @@ package body Annotations is elsif Option = "cobertura" then return Annotate_Cobertura; + elsif Option = "sarif" then + return Annotate_Sarif; + else return Annotate_Unknown; end if; @@ -1084,4 +1086,84 @@ package body Annotations is else To_Lower (SCO_Kind'Image (K))); end SCO_Kind_Image; + ------------------------ + -- Section_Of_Message -- + ------------------------ + + function Section_Of_Message (M : Message) return Report_Section is + begin + if M.SCO /= No_SCO_Id and then M.Kind in Coverage_Kind then + case M.Kind is + when Exclusion => + return Coverage_Exclusions; + when Undetermined_Cov => + return Undet_Coverage; + when others => + pragma Assert (M.Kind = Violation or else M.Kind = Info); + + declare + S : constant Report_Section := Section_Of_SCO (M.SCO); + begin + if S = Other_Errors then + -- A violation message is expected to always be relevant to + -- some report section. + + raise Program_Error with "unexpected SCO kind in violation"; + end if; + return S; + end; + end case; + + else + pragma Assert (M.Kind not in Coverage_Kind); + + return Other_Errors; + end if; + end Section_Of_Message; + + -------------------- + -- Section_Of_SCO -- + -------------------- + + function Section_Of_SCO (SCO : SCO_Id) return Report_Section is + MCDC_Section : Report_Section; + begin + -- Need to initialize MCDC_Section specially because it is erroneous + -- to evaluate MCDC_Level if MCDC coverage is not enabled. + + if Coverage.MCDC_Coverage_Enabled then + MCDC_Section := Coverage_Level'Pos (Coverage.MCDC_Level); + else + MCDC_Section := Other_Errors; + end if; + + case Kind (SCO) is + when Statement => + return Coverage_Level'Pos (Stmt); + + when Decision => + if Is_Expression (SCO) + and then not Decision_Requires_Assertion_Coverage (SCO) + then + return MCDC_Section; + elsif Decision_Requires_Assertion_Coverage (SCO) then + return Coverage_Level'Pos (ATC); + else + return Coverage_Level'Pos (Decision); + end if; + + when Condition => + if Coverage.Enabled (ATCC) + and then Decision_Requires_Assertion_Coverage (SCO) + then + return Coverage_Level'Pos (ATCC); + else + return MCDC_Section; + end if; + + when others => + return Other_Errors; + end case; + end Section_Of_SCO; + end Annotations; diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 2fca8d0ae..9ea36b4d9 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -22,6 +22,7 @@ with GNAT.Strings; use GNAT.Strings; with Binary_Files; use Binary_Files; with Coverage; +with Coverage_Options; use Coverage_Options; with Diagnostics; use Diagnostics; with Disa_Symbolize; use Disa_Symbolize; with Elf_Disassemblers; use Elf_Disassemblers; @@ -50,6 +51,7 @@ package Annotations is Annotate_Cobertura, Annotate_Xml, Annotate_Report, + Annotate_Sarif, Annotate_Unknown); function To_Annotation_Format (Option : String) return Annotation_Format; @@ -73,6 +75,22 @@ package Annotations is -- True if more than one report annotation format which requires writing -- the report to the output directory is requested. + type Report_Section is + range Coverage_Level'Pos (Coverage_Level'First) + .. Coverage_Level'Pos (Coverage_Level'Last) + 3; + -- For report and SARIF formats. There is one report section for each + -- coverage level, plus the following three special sections: + + Coverage_Exclusions : constant Report_Section := Report_Section'Last - 2; + Undet_Coverage : constant Report_Section := Report_Section'Last - 1; + Other_Errors : constant Report_Section := Report_Section'Last; + + function Section_Of_Message (M : Message) return Report_Section; + -- Indicate the coverage criterion a given SCO/message pertains to (by its + -- 'Pos), or Other_Errors if SCO has no related section/M is not a + -- violation message. + function Section_Of_SCO (SCO : SCO_Id) return Report_Section; + private function SCO_Text (SCO : SCO_Id; Length : Natural := 8) return String; diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 61c68ea96..bced9ee8c 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -1399,7 +1399,8 @@ package Command_Line is Pattern => "[FORM|LIST]", Help => "Generate a FORM report. FORM is one of:" - & ASCII.LF & " asm, cobertura, html, report, xcov, xcov+, xml." + & ASCII.LF + & " asm, cobertura, html, report, sarif, xcov, xcov+, xml." & ASCII.LF & "Multiple reports can be produced in a single" & " execution by passing a comma separated list of FORMs to this" & " option, or by specifying this option multiple times on the" diff --git a/tools/gnatcov/coverage.adb b/tools/gnatcov/coverage.adb index 9d5e231cc..1258968f9 100644 --- a/tools/gnatcov/coverage.adb +++ b/tools/gnatcov/coverage.adb @@ -227,6 +227,29 @@ package body Coverage is return Res; end Source_Levels_Enabled; + ----------------------------- + -- Coverage_Levels_Enabled -- + ----------------------------- + + function Coverage_Levels_Enabled return Levels_Sets.Set is + begin + if Source_Coverage_Enabled then + return Source_Levels_Enabled; + else + declare + Res : Levels_Sets.Set; + begin + if Enabled (Insn) then + Res.Include (Insn); + end if; + if Enabled (Branch) then + Res.Include (Branch); + end if; + return Res; + end; + end if; + end Coverage_Levels_Enabled; + --------------------- -- Is_Load_Allowed -- --------------------- diff --git a/tools/gnatcov/coverage.ads b/tools/gnatcov/coverage.ads index 4f2358de0..ab9338c1a 100644 --- a/tools/gnatcov/coverage.ads +++ b/tools/gnatcov/coverage.ads @@ -98,6 +98,10 @@ package Coverage is -- as it will return the coverage levels implicitely enabled (such as -- decision when passing stmt+mcdc). + function Coverage_Levels_Enabled return Levels_Sets.Set; + -- Return the set of coverage levels enabled. Similar as the above but + -- including object coverage levels. + function Is_Load_Allowed (Filename : String; Checkpoint_Levels : Levels_Type) return String; -- If loading a checkpoint state (from Filename) with the given coverage diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 4f8451544..bc18d7a5a 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -34,6 +34,7 @@ with Snames; with ALI_Files; with Annotations.Cobertura; +with Annotations.Sarif; with Annotations.Dynamic_Html; with Annotations.Html; with Annotations.Report; @@ -1670,14 +1671,20 @@ begin -- object coverage. if Object_Coverage_Enabled then - if Annotation (Annotate_Report) then + if Annotation (Annotate_Report) + or else Annotation (Annotate_Sarif) + then Fatal_Error - ("""report"" output format (from --annotate) is" - & " only for source coverage criteria" - & ASCII.LF - & " (--level=" & Source_Level_Options - & ", not --level=" - & Coverage_Option_Value (Current_Levels) & ")"); + ("""" + & (if Annotation (Annotate_Report) + then "report" + else "SARIF") + & """ output format (from --annotate) is" + & " only for source coverage criteria" + & ASCII.LF + & " (--level=" & Source_Level_Options + & ", not --level=" + & Coverage_Option_Value (Current_Levels) & ")"); elsif not Checkpoints_Inputs.Is_Empty or else Save_Checkpoint /= null @@ -2360,6 +2367,11 @@ begin (Context'Unchecked_Access); end if; + if Annotation (Annotate_Sarif) then + Annotations.Sarif.Generate_Report + (Context'Unchecked_Access); + end if; + if Annotation (Annotate_Report) then Annotations.Report.Generate_Report (Context'Unchecked_Access, Output, Dump_Units_In_Report); From 03a02c785f6db0eecd14b2901c911cd0a3f415b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 21 May 2024 15:42:39 +0200 Subject: [PATCH 0852/1483] Add tests for SARIF report gen Tests for Ada, C, C++ and all three. For each, test that the SARIF report is correct when there are violations and when there are none to be reported. --- .../tests/213-sarif-report/ada/full/ref.sarif | 1 + .../213-sarif-report/ada/full/src-lib/lib.ads | 8 +++ .../213-sarif-report/ada/full/src-root/a.adb | 15 ++++ .../213-sarif-report/ada/full/src-root/a.ads | 9 +++ .../ada/full/src-root/main.adb | 25 +++++++ .../ada/full/src-root/src-foo/b.ads | 3 + .../ada/full/src-root/src-foo/foo.adb | 29 ++++++++ .../ada/full/src-root/src-foo/foo.ads | 1 + .../ada/full/src-root/src-foo/src-bar/bar.adb | 34 ++++++++++ .../ada/full/src-root/src-foo/src-bar/bar.ads | 1 + .../tests/213-sarif-report/ada/full/test.opt | 3 + .../tests/213-sarif-report/ada/full/test.py | 67 ++++++++++++++++++ .../ada/no-violations/main.adb | 4 ++ .../ada/no-violations/ref.sarif | 1 + .../ada/no-violations/test.opt | 1 + .../ada/no-violations/test.py | 29 ++++++++ .../213-sarif-report/all-lang/full/ref.sarif | 1 + .../all-lang/full/src-lib/lib.ads | 8 +++ .../all-lang/full/src-root/a.adb | 15 ++++ .../all-lang/full/src-root/a.ads | 9 +++ .../all-lang/full/src-root/c_source.c | 41 +++++++++++ .../all-lang/full/src-root/cpp_source.cpp | 41 +++++++++++ .../all-lang/full/src-root/main.adb | 34 ++++++++++ .../all-lang/full/src-root/src-foo/b.ads | 3 + .../all-lang/full/src-root/src-foo/foo.adb | 29 ++++++++ .../all-lang/full/src-root/src-foo/foo.ads | 1 + .../full/src-root/src-foo/src-bar/bar.adb | 34 ++++++++++ .../full/src-root/src-foo/src-bar/bar.ads | 1 + .../213-sarif-report/all-lang/full/test.opt | 2 + .../213-sarif-report/all-lang/full/test.py | 68 +++++++++++++++++++ .../all-lang/no-violations/c_source.c | 7 ++ .../all-lang/no-violations/cpp_source.cpp | 10 +++ .../all-lang/no-violations/main.adb | 9 +++ .../all-lang/no-violations/ref.sarif | 1 + .../all-lang/no-violations/test.opt | 2 + .../all-lang/no-violations/test.py | 34 ++++++++++ .../tests/213-sarif-report/c/full/ref.sarif | 1 + .../213-sarif-report/c/full/src-lib/lib.c | 12 ++++ .../213-sarif-report/c/full/src-lib/lib.h | 3 + .../213-sarif-report/c/full/src-root/main.c | 31 +++++++++ .../c/full/src-root/src-foo/b.c | 7 ++ .../c/full/src-root/src-foo/b.h | 3 + .../c/full/src-root/src-foo/foo.c | 15 ++++ .../c/full/src-root/src-foo/foo.h | 3 + .../c/full/src-root/src-foo/src-bar/bar.c | 27 ++++++++ .../c/full/src-root/src-foo/src-bar/bar.h | 3 + .../tests/213-sarif-report/c/full/test.opt | 1 + .../tests/213-sarif-report/c/full/test.py | 62 +++++++++++++++++ .../213-sarif-report/c/no-violations/main.c | 5 ++ .../c/no-violations/ref.sarif | 1 + .../213-sarif-report/c/no-violations/test.opt | 1 + .../213-sarif-report/c/no-violations/test.py | 29 ++++++++ .../tests/213-sarif-report/cpp/full/ref.sarif | 1 + .../213-sarif-report/cpp/full/src-lib/lib.cpp | 12 ++++ .../213-sarif-report/cpp/full/src-lib/lib.hpp | 3 + .../cpp/full/src-root/main.cpp | 31 +++++++++ .../cpp/full/src-root/src-foo/b.cpp | 7 ++ .../cpp/full/src-root/src-foo/b.hpp | 3 + .../cpp/full/src-root/src-foo/foo.cpp | 15 ++++ .../cpp/full/src-root/src-foo/foo.hpp | 3 + .../cpp/full/src-root/src-foo/src-bar/bar.cpp | 27 ++++++++ .../cpp/full/src-root/src-foo/src-bar/bar.hpp | 3 + .../tests/213-sarif-report/cpp/full/test.opt | 3 + .../tests/213-sarif-report/cpp/full/test.py | 62 +++++++++++++++++ .../cpp/no-violations/main.cpp | 5 ++ .../cpp/no-violations/ref.sarif | 1 + .../cpp/no-violations/test.opt | 2 + .../cpp/no-violations/test.py | 29 ++++++++ 68 files changed, 992 insertions(+) create mode 100644 testsuite/tests/213-sarif-report/ada/full/ref.sarif create mode 100644 testsuite/tests/213-sarif-report/ada/full/src-lib/lib.ads create mode 100644 testsuite/tests/213-sarif-report/ada/full/src-root/a.adb create mode 100644 testsuite/tests/213-sarif-report/ada/full/src-root/a.ads create mode 100644 testsuite/tests/213-sarif-report/ada/full/src-root/main.adb create mode 100644 testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/b.ads create mode 100644 testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.adb create mode 100644 testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.ads create mode 100644 testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.adb create mode 100644 testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.ads create mode 100644 testsuite/tests/213-sarif-report/ada/full/test.opt create mode 100644 testsuite/tests/213-sarif-report/ada/full/test.py create mode 100644 testsuite/tests/213-sarif-report/ada/no-violations/main.adb create mode 100644 testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif create mode 100644 testsuite/tests/213-sarif-report/ada/no-violations/test.opt create mode 100644 testsuite/tests/213-sarif-report/ada/no-violations/test.py create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/ref.sarif create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/src-lib/lib.ads create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/src-root/a.adb create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/src-root/a.ads create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/src-root/c_source.c create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/src-root/cpp_source.cpp create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/src-root/main.adb create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/b.ads create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.adb create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.ads create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.adb create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.ads create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/test.opt create mode 100644 testsuite/tests/213-sarif-report/all-lang/full/test.py create mode 100644 testsuite/tests/213-sarif-report/all-lang/no-violations/c_source.c create mode 100644 testsuite/tests/213-sarif-report/all-lang/no-violations/cpp_source.cpp create mode 100644 testsuite/tests/213-sarif-report/all-lang/no-violations/main.adb create mode 100644 testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif create mode 100644 testsuite/tests/213-sarif-report/all-lang/no-violations/test.opt create mode 100644 testsuite/tests/213-sarif-report/all-lang/no-violations/test.py create mode 100644 testsuite/tests/213-sarif-report/c/full/ref.sarif create mode 100644 testsuite/tests/213-sarif-report/c/full/src-lib/lib.c create mode 100644 testsuite/tests/213-sarif-report/c/full/src-lib/lib.h create mode 100644 testsuite/tests/213-sarif-report/c/full/src-root/main.c create mode 100644 testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.c create mode 100644 testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.h create mode 100644 testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.c create mode 100644 testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.h create mode 100644 testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.c create mode 100644 testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.h create mode 100644 testsuite/tests/213-sarif-report/c/full/test.opt create mode 100644 testsuite/tests/213-sarif-report/c/full/test.py create mode 100644 testsuite/tests/213-sarif-report/c/no-violations/main.c create mode 100644 testsuite/tests/213-sarif-report/c/no-violations/ref.sarif create mode 100644 testsuite/tests/213-sarif-report/c/no-violations/test.opt create mode 100644 testsuite/tests/213-sarif-report/c/no-violations/test.py create mode 100644 testsuite/tests/213-sarif-report/cpp/full/ref.sarif create mode 100644 testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.cpp create mode 100644 testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.hpp create mode 100644 testsuite/tests/213-sarif-report/cpp/full/src-root/main.cpp create mode 100644 testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.cpp create mode 100644 testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.hpp create mode 100644 testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.cpp create mode 100644 testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.hpp create mode 100644 testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.cpp create mode 100644 testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.hpp create mode 100644 testsuite/tests/213-sarif-report/cpp/full/test.opt create mode 100644 testsuite/tests/213-sarif-report/cpp/full/test.py create mode 100644 testsuite/tests/213-sarif-report/cpp/no-violations/main.cpp create mode 100644 testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif create mode 100644 testsuite/tests/213-sarif-report/cpp/no-violations/test.opt create mode 100644 testsuite/tests/213-sarif-report/cpp/no-violations/test.py diff --git a/testsuite/tests/213-sarif-report/ada/full/ref.sarif b/testsuite/tests/213-sarif-report/ada/full/ref.sarif new file mode 100644 index 000000000..e2326eec2 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/ref.sarif @@ -0,0 +1 @@ +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/a\.adb"},"region":{"startLine":5,"startColumn":8}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/a\.adb"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/a\.adb"},"region":{"startLine":8,"startColumn":9}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/a\.adb"},"region":{"startLine":10,"startColumn":9}}}\]},{"ruleId":"UNDET","kind":"fail","level":"warning","message":{"text":"statement was not instrumented"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/a\.ads"},"region":{"startLine":8,"startColumn":31}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/b\.ads"},"region":{"startLine":2,"startColumn":39}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar\.adb"},"region":{"startLine":16,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar\.adb"},"region":{"startLine":17,"startColumn":15}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar\.adb"},"region":{"startLine":30,"startColumn":44}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/foo\.adb"},"region":{"startLine":14,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/foo\.adb"},"region":{"startLine":15,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/foo\.adb"},"region":{"startLine":19,"startColumn":8}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/foo\.adb"},"region":{"startLine":21,"startColumn":32}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/foo\.adb"},"region":{"startLine":21,"startColumn":42}}}\]},{"ruleId":"ATC","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/foo\.adb"},"region":{"startLine":22,"startColumn":22}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-lib/lib\.ads"},"region":{"startLine":6,"startColumn":42}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/main\.adb"},"region":{"startLine":10,"startColumn":6}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/main\.adb"},"region":{"startLine":11,"startColumn":10}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/main\.adb"},"region":{"startLine":14,"startColumn":6}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/main\.adb"},"region":{"startLine":15,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/main\.adb"},"region":{"startLine":19,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/main\.adb"},"region":{"startLine":20,"startColumn":5}}}\]}\]}\]} diff --git a/testsuite/tests/213-sarif-report/ada/full/src-lib/lib.ads b/testsuite/tests/213-sarif-report/ada/full/src-lib/lib.ads new file mode 100644 index 000000000..248add341 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-lib/lib.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Lib is + function Id (B : Boolean) return Boolean is (B) + with Pre => B or else not B or else B, + Post => Id'Result = B; +end Lib; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/a.adb b/testsuite/tests/213-sarif-report/ada/full/src-root/a.adb new file mode 100644 index 000000000..f57e05802 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/a.adb @@ -0,0 +1,15 @@ +package body A is + procedure A_Proc (Dummy : Boolean) is + begin + pragma Annotate (Xcov, Exempt_On, "Justification"); + if Dummy and then not Dummy then + pragma Assert (Dummy); + declare + Dummy_2 : Boolean := not Dummy and then Dummy; + begin + null; + end; + end if; + pragma Annotate (Xcov, Exempt_Off); + end A_Proc; +end A; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/a.ads b/testsuite/tests/213-sarif-report/ada/full/src-root/a.ads new file mode 100644 index 000000000..ed422ab7b --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/a.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; + +package A is + procedure A_Proc (Dummy : Boolean); + + type T is tagged null record; + + function Create return T is (null record); +end A; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/main.adb b/testsuite/tests/213-sarif-report/ada/full/src-root/main.adb new file mode 100644 index 000000000..bcb0d65d0 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/main.adb @@ -0,0 +1,25 @@ +with A; +with Foo; +with Lib; + +procedure Main is + T : Boolean := True; + F : Boolean := False; + Rec : A.T := A.Create; +begin + if Lib.Id (T) or else F then + T := T and then True; + end if; + + if F and then Foo then + F := F and then False; + end if; + + pragma Annotate (Xcov, Exempt_On, "Test"); + if not Foo then + T := not F; + end if; + pragma Annotate (Xcov, Exempt_Off); + + A.A_Proc (True); +end Main; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/b.ads b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/b.ads new file mode 100644 index 000000000..89a3e5a35 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/b.ads @@ -0,0 +1,3 @@ +package B is + function Return_T return Boolean is (True); +end B; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.adb b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.adb new file mode 100644 index 000000000..92c7a5edc --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.adb @@ -0,0 +1,29 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +with Bar; +with Lib; + +function Foo return Boolean +is + T : Boolean := Bar; + F : Boolean := False; +begin + if not T then + T := T and then T; + end if; + + begin + if T then + pragma Assert (T); + pragma Assert (T or else T or else T); + pragma Assert (T and then Lib.Id (F)); + end if; + exception + when Ada.Assertions.Assertion_Error => null; + end; + + return T; +end Foo; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.ads b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.ads new file mode 100644 index 000000000..b7cfdb3ca --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/foo.ads @@ -0,0 +1 @@ +function Foo return Boolean; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.adb b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.adb new file mode 100644 index 000000000..b23814520 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.adb @@ -0,0 +1,34 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +function Bar return Boolean +is + T : Boolean := True; + F : Boolean := False; + + Res : Boolean := False; + + function MCDC_Violation (A, B : Boolean) return Boolean is + begin + if (A and + then not B) + or else A then + return True; + end if; + return True; + end MCDC_Violation; + +begin + Res := MCDC_Violation (T, F); + Res := MCDC_Violation (F, F); + + begin + pragma Assert (Res); + exception + when Ada.Assertions.Assertion_Error => null; + end; + + return Res; +end Bar; diff --git a/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.ads b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.ads new file mode 100644 index 000000000..f51db2cee --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar.ads @@ -0,0 +1 @@ +function Bar return Boolean; diff --git a/testsuite/tests/213-sarif-report/ada/full/test.opt b/testsuite/tests/213-sarif-report/ada/full/test.opt new file mode 100644 index 000000000..dc69ef071 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/test.opt @@ -0,0 +1,3 @@ +bin-traces DEAD SARIF reports are only generated for source traces +5.04a1 DEAD Test uses expression function and Ada_2012 +7.1.2 DEAD Test uses Ada_2012 features diff --git a/testsuite/tests/213-sarif-report/ada/full/test.py b/testsuite/tests/213-sarif-report/ada/full/test.py new file mode 100644 index 000000000..92730c782 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/full/test.py @@ -0,0 +1,67 @@ +""" +Check the SARIF coverage report emitted for an Ada project containing +statement, decision, mcdc, atc, and atcc violations, some of which are +exempted. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +lib = gprfor( + prjid="lib", + srcdirs="../src-lib", + mains=None, + objdir="obj-lib", +) + +foo = gprfor( + prjid="foo", + srcdirs="../src-root/src-foo", + mains=["foo.adb"], + objdir="obj-foo", + deps=["bar", "lib"], +) + +bar = gprfor( + prjid="bar", + srcdirs="../src-root/src-foo/src-bar", + mains=["bar.adb"], + objdir="obj-bar", +) + +root = gprfor( + prjid="gen", + srcdirs="../src-root", + mains=["main.adb"], + objdir="obj", + deps=["lib", "foo"], +) + +instr_msg = ( + r"\*\*\* a.ads:8:3: warning: gnatcov limitation: cannot instrument an" + " expression function which is a primitive of its return type, when this" + r" type is a tagged type\. Consider turning it into a regular function" + r" body\." +) + +build_run_and_coverage( + gprsw=GPRswitches(root), + covlevel="stmt+mcdc+atcc", + mains=["main"], + trace_mode="src", + extra_coverage_args=["--annotate=sarif"], + tolerate_instrument_messages=instr_msg, +) + +thistest.fail_if_no_match( + "SARIF report", + contents_of("../ref.sarif"), + contents_of("obj/coverage.sarif"), +) + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/ada/no-violations/main.adb b/testsuite/tests/213-sarif-report/ada/no-violations/main.adb new file mode 100644 index 000000000..afbdbab88 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/no-violations/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end; diff --git a/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif new file mode 100644 index 000000000..05e3e2645 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif @@ -0,0 +1 @@ +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[\]}\]} diff --git a/testsuite/tests/213-sarif-report/ada/no-violations/test.opt b/testsuite/tests/213-sarif-report/ada/no-violations/test.opt new file mode 100644 index 000000000..5fb8b75f0 --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/no-violations/test.opt @@ -0,0 +1 @@ +bin-traces DEAD SARIF reports are only generated for source traces diff --git a/testsuite/tests/213-sarif-report/ada/no-violations/test.py b/testsuite/tests/213-sarif-report/ada/no-violations/test.py new file mode 100644 index 000000000..86b43043a --- /dev/null +++ b/testsuite/tests/213-sarif-report/ada/no-violations/test.py @@ -0,0 +1,29 @@ +""" +Check the validity of the SARIF report generated for an Ada project in which no +coverage violations were found. +""" +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(prjid="test", srcdirs=[".."], mains=["main.adb"], langs=["Ada"]) + ), + covlevel=("stmt"), + trace_mode="src", + mains=["main"], + extra_coverage_args=["--annotate=sarif"], +) + +thistest.fail_if_no_match( + "SARIF report", + contents_of("../ref.sarif"), + contents_of("obj/coverage.sarif"), +) + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif new file mode 100644 index 000000000..5475c3fdf --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif @@ -0,0 +1 @@ +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/a\.adb"},"region":{"startLine":5,"startColumn":8}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/a\.adb"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/a\.adb"},"region":{"startLine":8,"startColumn":9}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/a\.adb"},"region":{"startLine":10,"startColumn":9}}}\]},{"ruleId":"UNDET","kind":"fail","level":"warning","message":{"text":"statement was not instrumented"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/a\.ads"},"region":{"startLine":8,"startColumn":31}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/b\.ads"},"region":{"startLine":2,"startColumn":39}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar\.adb"},"region":{"startLine":16,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar\.adb"},"region":{"startLine":17,"startColumn":15}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar\.adb"},"region":{"startLine":30,"startColumn":44}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":8,"startColumn":13}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":8,"startColumn":20}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":8,"startColumn":25}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":27,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":34,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":36,"startColumn":7}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":9,"startColumn":13}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":9,"startColumn":20}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":9,"startColumn":25}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":27,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":34,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":36,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/foo\.adb"},"region":{"startLine":14,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/foo\.adb"},"region":{"startLine":15,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/foo\.adb"},"region":{"startLine":19,"startColumn":8}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/foo\.adb"},"region":{"startLine":21,"startColumn":32}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/foo\.adb"},"region":{"startLine":21,"startColumn":42}}}\]},{"ruleId":"ATC","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/foo\.adb"},"region":{"startLine":22,"startColumn":22}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-lib/lib\.ads"},"region":{"startLine":6,"startColumn":42}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/main\.adb"},"region":{"startLine":18,"startColumn":6}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/main\.adb"},"region":{"startLine":19,"startColumn":10}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/main\.adb"},"region":{"startLine":22,"startColumn":6}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/main\.adb"},"region":{"startLine":23,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/main\.adb"},"region":{"startLine":27,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/main\.adb"},"region":{"startLine":28,"startColumn":5}}}\]}\]}\]} diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-lib/lib.ads b/testsuite/tests/213-sarif-report/all-lang/full/src-lib/lib.ads new file mode 100644 index 000000000..248add341 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-lib/lib.ads @@ -0,0 +1,8 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Lib is + function Id (B : Boolean) return Boolean is (B) + with Pre => B or else not B or else B, + Post => Id'Result = B; +end Lib; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/a.adb b/testsuite/tests/213-sarif-report/all-lang/full/src-root/a.adb new file mode 100644 index 000000000..f57e05802 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/a.adb @@ -0,0 +1,15 @@ +package body A is + procedure A_Proc (Dummy : Boolean) is + begin + pragma Annotate (Xcov, Exempt_On, "Justification"); + if Dummy and then not Dummy then + pragma Assert (Dummy); + declare + Dummy_2 : Boolean := not Dummy and then Dummy; + begin + null; + end; + end if; + pragma Annotate (Xcov, Exempt_Off); + end A_Proc; +end A; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/a.ads b/testsuite/tests/213-sarif-report/all-lang/full/src-root/a.ads new file mode 100644 index 000000000..ed422ab7b --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/a.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; + +package A is + procedure A_Proc (Dummy : Boolean); + + type T is tagged null record; + + function Create return T is (null record); +end A; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/c_source.c b/testsuite/tests/213-sarif-report/all-lang/full/src-root/c_source.c new file mode 100644 index 000000000..2e8505763 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/c_source.c @@ -0,0 +1,41 @@ +#include + +extern int cpp_func (int a); + +bool +MCDC_Violation (bool t, bool f) +{ + if ((t || f) && (t || f)) + { + return true; + } + + return true; +} + +int +c_func (int a, int b) +{ + + bool t = true; + bool f = false; + + // DECISISON violation + if (!t) + { + // STMT violation + t = false; + } + + t = MCDC_Violation (f, f); + t = MCDC_Violation (t, f); + + /* GNATCOV_EXEMPT_ON "c_justification"*/ + if (!t) + { + t = false; + } + /* GNATCOV_EXEMPT_OFF */ + + return cpp_func (a) + cpp_func (b); +} diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/cpp_source.cpp b/testsuite/tests/213-sarif-report/all-lang/full/src-root/cpp_source.cpp new file mode 100644 index 000000000..3c31ac1f3 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/cpp_source.cpp @@ -0,0 +1,41 @@ +extern "C" +{ + extern int cpp_func (int a); +} + +bool +MCDC_Violation (bool t, bool f) +{ + if ((t || f) && (t || f)) + { + return true; + } + + return true; +} + +int +cpp_func (int a) +{ + bool t = true; + bool f = false; + + // DECISISON violation + if (!t) + { + // STMT violation + t = false; + } + + MCDC_Violation (f, f); + MCDC_Violation (t, f); + + /* GNATCOV_EXEMPT_ON "cpp justification"*/ + if (!t) + { + t = false; + } + /* GNATCOV_EXEMPT_OFF */ + + return a; +} diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/main.adb b/testsuite/tests/213-sarif-report/all-lang/full/src-root/main.adb new file mode 100644 index 000000000..5762643dc --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/main.adb @@ -0,0 +1,34 @@ +with A; +with Foo; +with Lib; + +procedure Main +is + + function C_Func (A : Integer; B : Integer) return Integer; + pragma Import (C, C_Func, "c_func"); + + T : Boolean := True; + F : Boolean := False; + Rec : A.T := A.Create; + Dummy_I : Integer := C_Func (1, 2); + +begin + + if Lib.Id (T) or else F then + T := T and then True; + end if; + + if F and then Foo then + F := F and then False; + end if; + + pragma Annotate (Xcov, Exempt_On, "Test"); + if not Foo then + T := not F; + end if; + pragma Annotate (Xcov, Exempt_Off); + + A.A_Proc (True); + +end Main; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/b.ads b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/b.ads new file mode 100644 index 000000000..89a3e5a35 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/b.ads @@ -0,0 +1,3 @@ +package B is + function Return_T return Boolean is (True); +end B; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.adb b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.adb new file mode 100644 index 000000000..92c7a5edc --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.adb @@ -0,0 +1,29 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +with Bar; +with Lib; + +function Foo return Boolean +is + T : Boolean := Bar; + F : Boolean := False; +begin + if not T then + T := T and then T; + end if; + + begin + if T then + pragma Assert (T); + pragma Assert (T or else T or else T); + pragma Assert (T and then Lib.Id (F)); + end if; + exception + when Ada.Assertions.Assertion_Error => null; + end; + + return T; +end Foo; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.ads b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.ads new file mode 100644 index 000000000..b7cfdb3ca --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/foo.ads @@ -0,0 +1 @@ +function Foo return Boolean; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.adb b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.adb new file mode 100644 index 000000000..b23814520 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.adb @@ -0,0 +1,34 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +with Ada.Assertions; + +function Bar return Boolean +is + T : Boolean := True; + F : Boolean := False; + + Res : Boolean := False; + + function MCDC_Violation (A, B : Boolean) return Boolean is + begin + if (A and + then not B) + or else A then + return True; + end if; + return True; + end MCDC_Violation; + +begin + Res := MCDC_Violation (T, F); + Res := MCDC_Violation (F, F); + + begin + pragma Assert (Res); + exception + when Ada.Assertions.Assertion_Error => null; + end; + + return Res; +end Bar; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.ads b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.ads new file mode 100644 index 000000000..f51db2cee --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar.ads @@ -0,0 +1 @@ +function Bar return Boolean; diff --git a/testsuite/tests/213-sarif-report/all-lang/full/test.opt b/testsuite/tests/213-sarif-report/all-lang/full/test.opt new file mode 100644 index 000000000..9a428d8ac --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD SARIF reports are only generated for source traces +!C++ DEAD Test needs C++ compiler diff --git a/testsuite/tests/213-sarif-report/all-lang/full/test.py b/testsuite/tests/213-sarif-report/all-lang/full/test.py new file mode 100644 index 000000000..7cb4b9d2a --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/full/test.py @@ -0,0 +1,68 @@ +""" +Check the SARIF coverage report emitted for a project containing statement, +decision, mcdc, atc, and atcc violations, some of which are exempted. The +project contains Ada, C and C++ sources. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +lib = gprfor( + prjid="lib", + srcdirs="../src-lib", + mains=None, + objdir="obj-lib", +) + +foo = gprfor( + prjid="foo", + srcdirs="../src-root/src-foo", + mains=["foo.adb"], + objdir="obj-foo", + deps=["bar", "lib"], +) + +bar = gprfor( + prjid="bar", + srcdirs="../src-root/src-foo/src-bar", + mains=["bar.adb"], + objdir="obj-bar", +) + +root = gprfor( + prjid="gen", + srcdirs="../src-root", + mains=["main.adb"], + objdir="obj", + deps=["lib", "foo"], + langs=["Ada", "C", "C++"], +) + +instr_msg = ( + r"\*\*\* a.ads:8:3: warning: gnatcov limitation: cannot instrument an" + " expression function which is a primitive of its return type, when this" + r" type is a tagged type\. Consider turning it into a regular function" + r" body\." +) + +build_run_and_coverage( + gprsw=GPRswitches(root), + covlevel="stmt+mcdc+atcc", + mains=["main"], + trace_mode="src", + extra_coverage_args=["--annotate=sarif,report"], + tolerate_instrument_messages=instr_msg, +) + +thistest.fail_if_no_match( + "SARIF report", + contents_of("../ref.sarif"), + contents_of("obj/coverage.sarif"), +) + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/c_source.c b/testsuite/tests/213-sarif-report/all-lang/no-violations/c_source.c new file mode 100644 index 000000000..8ca8567b9 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/c_source.c @@ -0,0 +1,7 @@ +extern int cpp_func (int a); + +int +c_func (int a, int b) +{ + return cpp_func (a) + cpp_func (b); +} diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/cpp_source.cpp b/testsuite/tests/213-sarif-report/all-lang/no-violations/cpp_source.cpp new file mode 100644 index 000000000..5eee65489 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/cpp_source.cpp @@ -0,0 +1,10 @@ +extern "C" +{ + extern int cpp_func (int a); +} + +int +cpp_func (int a) +{ + return a; +} diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/main.adb b/testsuite/tests/213-sarif-report/all-lang/no-violations/main.adb new file mode 100644 index 000000000..8a92a0426 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/main.adb @@ -0,0 +1,9 @@ +procedure Main +is + function C_Func (A : Integer) return Integer; + pragma Import (C, C_Func, "c_func"); + + Dummy_I : Integer := 1; +begin + Dummy_I := C_Func (Dummy_I); +end; diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif new file mode 100644 index 000000000..05e3e2645 --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif @@ -0,0 +1 @@ +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[\]}\]} diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/test.opt b/testsuite/tests/213-sarif-report/all-lang/no-violations/test.opt new file mode 100644 index 000000000..9a428d8ac --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD SARIF reports are only generated for source traces +!C++ DEAD Test needs C++ compiler diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py b/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py new file mode 100644 index 000000000..ffb1a06eb --- /dev/null +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py @@ -0,0 +1,34 @@ +""" +Check the validity of the SARIF report generated for a project in which no +coverage violations were found. The project contains Ada, C, and C++ sources. +""" +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor( + prjid="test", + srcdirs=[".."], + mains=["main.adb"], + langs=["Ada", "C", "C++"], + ) + ), + covlevel=("stmt"), + trace_mode="src", + mains=["main"], + extra_coverage_args=["--annotate=sarif"], +) + +thistest.fail_if_no_match( + "SARIF report", + contents_of("../ref.sarif"), + contents_of("obj/coverage.sarif"), +) + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/c/full/ref.sarif b/testsuite/tests/213-sarif-report/c/full/ref.sarif new file mode 100644 index 000000000..fad137258 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/ref.sarif @@ -0,0 +1 @@ +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/src-foo/src-bar/bar\.c"},"region":{"startLine":6,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/src-foo/src-bar/bar\.c"},"region":{"startLine":6,"startColumn":20}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/src-foo/foo\.c"},"region":{"startLine":9,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/src-foo/foo\.c"},"region":{"startLine":11,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-lib/lib\.c"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-lib/lib\.c"},"region":{"startLine":8,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/main\.c"},"region":{"startLine":13,"startColumn":7}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/main\.c"},"region":{"startLine":15,"startColumn":11}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/main\.c"},"region":{"startLine":18,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/main\.c"},"region":{"startLine":20,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/main\.c"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/main\.c"},"region":{"startLine":26,"startColumn":7}}}\]}\]}\]} diff --git a/testsuite/tests/213-sarif-report/c/full/src-lib/lib.c b/testsuite/tests/213-sarif-report/c/full/src-lib/lib.c new file mode 100644 index 000000000..def98f8a9 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-lib/lib.c @@ -0,0 +1,12 @@ +#include "lib.h" + +bool +lib_identity (bool b) +{ + if (!b && b) + { + return b; + } + + return b; +} diff --git a/testsuite/tests/213-sarif-report/c/full/src-lib/lib.h b/testsuite/tests/213-sarif-report/c/full/src-lib/lib.h new file mode 100644 index 000000000..09a57fce0 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-lib/lib.h @@ -0,0 +1,3 @@ +#include + +bool lib_identity (bool b); diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/main.c b/testsuite/tests/213-sarif-report/c/full/src-root/main.c new file mode 100644 index 000000000..e3ae22b08 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/main.c @@ -0,0 +1,31 @@ +#include + +#include "bar.h" +#include "foo.h" +#include "lib.h" + +int +main (void) +{ + int t = bar (); + int f = false; + + if (lib_identity (t) || f) + { + t = t && true; + } + + if (f && foo ()) + { + f = f && false; + } + + /* GNATCOV_EXEMPT_ON "justification" */ + if (!foo ()) + { + t = !f; + } + /* GNATCOV_EXEMPT_OFF */ + + return 0; +} diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.c b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.c new file mode 100644 index 000000000..cfef6e064 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.c @@ -0,0 +1,7 @@ +#include "b.h" + +bool +return_t () +{ + return true; +} diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.h b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.h new file mode 100644 index 000000000..b5da8581c --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/b.h @@ -0,0 +1,3 @@ +#include + +bool return_t (); diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.c b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.c new file mode 100644 index 000000000..1f484b130 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.c @@ -0,0 +1,15 @@ +#include "foo.h" +#include "b.h" + +bool +foo () +{ + bool t = true; + + if (!t) + { + t = return_t () && t; + } + + return return_t (); +} diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.h b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.h new file mode 100644 index 000000000..cfd5aee9d --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/foo.h @@ -0,0 +1,3 @@ +#include + +bool foo (); diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.c b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.c new file mode 100644 index 000000000..59935f8cb --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.c @@ -0,0 +1,27 @@ +#include "bar.h" + +bool +mcdc_violation (int a, int b) +{ + if ((a && !b) || a) + { + return true; + } + else + { + return true; + } +} + +bool +bar () +{ + bool t = true; + bool f = false; + bool res = false; + + res = mcdc_violation (t, f); + res = mcdc_violation (f, f); + + return res; +} diff --git a/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.h b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.h new file mode 100644 index 000000000..4310c9378 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/src-root/src-foo/src-bar/bar.h @@ -0,0 +1,3 @@ +#include + +bool bar (); diff --git a/testsuite/tests/213-sarif-report/c/full/test.opt b/testsuite/tests/213-sarif-report/c/full/test.opt new file mode 100644 index 000000000..5fb8b75f0 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/test.opt @@ -0,0 +1 @@ +bin-traces DEAD SARIF reports are only generated for source traces diff --git a/testsuite/tests/213-sarif-report/c/full/test.py b/testsuite/tests/213-sarif-report/c/full/test.py new file mode 100644 index 000000000..68b9d53a3 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/full/test.py @@ -0,0 +1,62 @@ +""" +Check the SARIF coverage report emitted for a C project containing statement, +decision, mcdc violations some of which are exempted. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +lib = gprfor( + prjid="lib", + srcdirs="../src-lib", + mains=None, + objdir="obj-lib", + langs=["C"], +) + +foo = gprfor( + prjid="foo", + srcdirs="../src-root/src-foo", + mains=["foo.c"], + objdir="obj-foo", + deps=["bar", "lib"], + langs=["C"], +) + +bar = gprfor( + prjid="bar", + srcdirs="../src-root/src-foo/src-bar", + mains=["bar.c"], + objdir="obj-bar", + langs=["C"], +) + +root = gprfor( + prjid="gen", + srcdirs="../src-root", + mains=["main.c"], + objdir="obj", + deps=["lib", "foo"], + langs=["C"], +) + +build_run_and_coverage( + gprsw=GPRswitches(root), + covlevel="stmt+mcdc+atcc", + mains=["main"], + trace_mode="src", + extra_coverage_args=["--annotate=sarif"], +) + +thistest.fail_if_no_match( + "SARIF report", + contents_of("../ref.sarif"), + contents_of("obj/coverage.sarif"), +) + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/c/no-violations/main.c b/testsuite/tests/213-sarif-report/c/no-violations/main.c new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/no-violations/main.c @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif new file mode 100644 index 000000000..05e3e2645 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif @@ -0,0 +1 @@ +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[\]}\]} diff --git a/testsuite/tests/213-sarif-report/c/no-violations/test.opt b/testsuite/tests/213-sarif-report/c/no-violations/test.opt new file mode 100644 index 000000000..5fb8b75f0 --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/no-violations/test.opt @@ -0,0 +1 @@ +bin-traces DEAD SARIF reports are only generated for source traces diff --git a/testsuite/tests/213-sarif-report/c/no-violations/test.py b/testsuite/tests/213-sarif-report/c/no-violations/test.py new file mode 100644 index 000000000..0371b331f --- /dev/null +++ b/testsuite/tests/213-sarif-report/c/no-violations/test.py @@ -0,0 +1,29 @@ +""" +Check the validity of the SARIF report generated for a C project in which no +coverage violations were found. +""" +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(prjid="test", srcdirs=[".."], mains=["main.c"], langs=["C"]) + ), + covlevel=("stmt"), + trace_mode="src", + mains=["main"], + extra_coverage_args=["--annotate=sarif"], +) + +thistest.fail_if_no_match( + "SARIF report", + contents_of("../ref.sarif"), + contents_of("obj/coverage.sarif"), +) + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/cpp/full/ref.sarif b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif new file mode 100644 index 000000000..d9443784c --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif @@ -0,0 +1 @@ +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar\.cpp"},"region":{"startLine":6,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar\.cpp"},"region":{"startLine":6,"startColumn":20}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/src-foo/foo\.cpp"},"region":{"startLine":9,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/src-foo/foo\.cpp"},"region":{"startLine":11,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-lib/lib\.cpp"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-lib/lib\.cpp"},"region":{"startLine":8,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/main\.cpp"},"region":{"startLine":13,"startColumn":7}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/main\.cpp"},"region":{"startLine":15,"startColumn":11}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/main\.cpp"},"region":{"startLine":18,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/main\.cpp"},"region":{"startLine":20,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/main\.cpp"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/main\.cpp"},"region":{"startLine":26,"startColumn":7}}}\]}\]}\]} diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.cpp b/testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.cpp new file mode 100644 index 000000000..498e18812 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.cpp @@ -0,0 +1,12 @@ +#include "lib.hpp" + +bool +lib_identity (bool b) +{ + if (!b && b) + { + return b; + } + + return b; +} diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.hpp b/testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.hpp new file mode 100644 index 000000000..09a57fce0 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-lib/lib.hpp @@ -0,0 +1,3 @@ +#include + +bool lib_identity (bool b); diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/main.cpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/main.cpp new file mode 100644 index 000000000..111e576c4 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/main.cpp @@ -0,0 +1,31 @@ +#include + +#include "bar.hpp" +#include "foo.hpp" +#include "lib.hpp" + +int +main (void) +{ + int t = bar (); + int f = false; + + if (lib_identity (t) || f) + { + t = t && true; + } + + if (f && foo ()) + { + f = f && false; + } + + /* GNATCOV_EXEMPT_ON "justification" */ + if (!foo ()) + { + t = !f; + } + /* GNATCOV_EXEMPT_OFF */ + + return 0; +} diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.cpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.cpp new file mode 100644 index 000000000..e6baafc5d --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.cpp @@ -0,0 +1,7 @@ +#include "b.hpp" + +bool +return_t () +{ + return true; +} diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.hpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.hpp new file mode 100644 index 000000000..b5da8581c --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/b.hpp @@ -0,0 +1,3 @@ +#include + +bool return_t (); diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.cpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.cpp new file mode 100644 index 000000000..c318eaf6e --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.cpp @@ -0,0 +1,15 @@ +#include "foo.hpp" +#include "b.hpp" + +bool +foo () +{ + bool t = true; + + if (!t) + { + t = return_t () && t; + } + + return return_t (); +} diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.hpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.hpp new file mode 100644 index 000000000..cfd5aee9d --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/foo.hpp @@ -0,0 +1,3 @@ +#include + +bool foo (); diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.cpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.cpp new file mode 100644 index 000000000..5d10705c3 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.cpp @@ -0,0 +1,27 @@ +#include "bar.hpp" + +bool +mcdc_violation (int a, int b) +{ + if ((a && !b) || a) + { + return true; + } + else + { + return true; + } +} + +bool +bar () +{ + bool t = true; + bool f = false; + bool res = false; + + res = mcdc_violation (t, f); + res = mcdc_violation (f, f); + + return res; +} diff --git a/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.hpp b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.hpp new file mode 100644 index 000000000..c51c698e8 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar.hpp @@ -0,0 +1,3 @@ +#include + +bool bar(); diff --git a/testsuite/tests/213-sarif-report/cpp/full/test.opt b/testsuite/tests/213-sarif-report/cpp/full/test.opt new file mode 100644 index 000000000..5af7cdcf7 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/test.opt @@ -0,0 +1,3 @@ +bin-traces DEAD SARIF reports are only generated for source traces +!C++ DEAD Test uses expression function and Ada_2012 +7.1.2 DEAD Test uses Ada_2012 features diff --git a/testsuite/tests/213-sarif-report/cpp/full/test.py b/testsuite/tests/213-sarif-report/cpp/full/test.py new file mode 100644 index 000000000..74fc196b5 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/full/test.py @@ -0,0 +1,62 @@ +""" +Check the SARIF coverage report emitted for a C++ project containing statement, +decision, mcdc violations, some of which are exempted. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +lib = gprfor( + prjid="lib", + srcdirs="../src-lib", + mains=None, + objdir="obj-lib", + langs=["C++"], +) + +foo = gprfor( + prjid="foo", + srcdirs="../src-root/src-foo", + mains=["foo.cpp"], + objdir="obj-foo", + deps=["bar", "lib"], + langs=["C++"], +) + +bar = gprfor( + prjid="bar", + srcdirs="../src-root/src-foo/src-bar", + mains=["bar.cpp"], + objdir="obj-bar", + langs=["C++"], +) + +root = gprfor( + prjid="gen", + srcdirs="../src-root", + mains=["main.cpp"], + objdir="obj", + deps=["lib", "foo"], + langs=["C++"], +) + +build_run_and_coverage( + gprsw=GPRswitches(root), + covlevel="stmt+mcdc+atcc", + mains=["main"], + trace_mode="src", + extra_coverage_args=["--annotate=sarif"], +) + +thistest.fail_if_no_match( + "SARIF report", + contents_of("../ref.sarif"), + contents_of("obj/coverage.sarif"), +) + +thistest.result() diff --git a/testsuite/tests/213-sarif-report/cpp/no-violations/main.cpp b/testsuite/tests/213-sarif-report/cpp/no-violations/main.cpp new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/no-violations/main.cpp @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif new file mode 100644 index 000000000..05e3e2645 --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif @@ -0,0 +1 @@ +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[\]}\]} diff --git a/testsuite/tests/213-sarif-report/cpp/no-violations/test.opt b/testsuite/tests/213-sarif-report/cpp/no-violations/test.opt new file mode 100644 index 000000000..9a428d8ac --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/no-violations/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD SARIF reports are only generated for source traces +!C++ DEAD Test needs C++ compiler diff --git a/testsuite/tests/213-sarif-report/cpp/no-violations/test.py b/testsuite/tests/213-sarif-report/cpp/no-violations/test.py new file mode 100644 index 000000000..88eabe92a --- /dev/null +++ b/testsuite/tests/213-sarif-report/cpp/no-violations/test.py @@ -0,0 +1,29 @@ +""" +Check the validity of the SARIF report generated for a C++ project in which no +coverage violations were found. +""" +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(prjid="test", srcdirs=[".."], mains=["main.cpp"], langs=["C++"]) + ), + covlevel=("stmt"), + trace_mode="src", + mains=["main"], + extra_coverage_args=["--annotate=sarif"], +) + +thistest.fail_if_no_match( + "SARIF report", + contents_of("../ref.sarif"), + contents_of("obj/coverage.sarif"), +) + +thistest.result() From 73494f208bf7076a3b863406270928e23b8b6a69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 21 May 2024 15:48:45 +0200 Subject: [PATCH 0853/1483] Document SARIF report generation --- doc/gnatcov/cov_source.rst | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index 8d592cb3a..76f2d92de 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -302,6 +302,24 @@ See the :ref:`sample annotated source ` appendix for a sample of html annotated source. +SARIF report (:cmd-option:`=sarif`) +----------------------------------- + +For source coverage criteria, |gcvcov| :cmd-option:`--annotate=sarif` produces +a JSON-based report under the Static Analysis Results Interchange Format +(SARIF). + +The generation of SARIF reports is mainly provided to allow viewing gnatcov +coverage reports with external IDEs that supports viewing them (for example, +Visual Studio Code with Microsoft's SARIF Viewer extension). To navigate this +report, open the ``coverage.sarif`` file using an integrated development +environment which supports viewing SARIF results. + +The reports contain information on the violations observed by gnatcov as +"Results" and the enabled coverage levels as "Rules". Each violation is +registered as "error". Exempted violations are reported as "note" and +undetermined coverage results as "warning". + Violations summary, text (:cmd-option:`=report`) ------------------------------------------------ From 17cd825c0f86b1ef0feb5dd8e65b5f721aab7589 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 7 Jun 2024 09:24:34 +0000 Subject: [PATCH 0854/1483] Setup: display a summary of the environment updates for users --- testsuite/tests/199-setup-summary/test.py | 84 +++++++++++++++++++++++ tools/gnatcov/setup_rts.adb | 39 +++++++++++ 2 files changed, 123 insertions(+) create mode 100644 testsuite/tests/199-setup-summary/test.py diff --git a/testsuite/tests/199-setup-summary/test.py b/testsuite/tests/199-setup-summary/test.py new file mode 100644 index 000000000..5b41a4d26 --- /dev/null +++ b/testsuite/tests/199-setup-summary/test.py @@ -0,0 +1,84 @@ +""" +Check that "gnatcov setup" displays a summary of env updates needed after a +successful run. +""" + +import os.path +import re + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import xcov + + +tmp = Wdir("tmp_") + +filename = "setup.log" +xcov(["setup", "--prefix=foo"], out=filename) +output = contents_of(filename) + +output_re = re.compile( + "(.|\n)*" + "\nThe coverage runtime has been successfully installed." + "\nIt was installed in: foo" + "\nIn order to use it, remember to add:" + "\n" + "\n (?P.*)" + "\n" + "\nto the GPR_PROJECT_PATH environment variable, and" + "\n" + "\n (?P.*)" + "\n" + "\nto the (?P.*) environment variable." +) +m = output_re.match(output) +thistest.fail_if_no_match("gnatcov setup output", output_re.pattern, output) +if m is not None: + if thistest.env.build.os.name == "windows": + shared_lib_dirname = "bin" + shared_lib_var = "PATH" + shared_lib_filename = "libgnatcov_rts.dll" + else: + shared_lib_dirname = "lib" + shared_lib_var = "LD_LIBRARY_PATH" + shared_lib_filename = "libgnatcov_rts.so" + + gpr_dir = m.group("gpr_dir") + shared_lib_dir = m.group("shared_lib_dir") + + # Check what gnatcov prints + thistest.fail_if_not_equal( + "Mentionned GPR directory", + os.path.realpath("foo/share/gpr"), + os.path.realpath(gpr_dir), + ) + thistest.fail_if_not_equal( + "Mentionned shared lib directory", + os.path.realpath(f"foo/{shared_lib_dirname}"), + os.path.realpath(shared_lib_dir), + ) + thistest.fail_if_not_equal( + "Mentionned shared lib env var", + shared_lib_var, + m.group("shared_lib_var"), + ) + + # Sanity check: the mentionned directories should contain the expected + # files. + thistest.fail_if( + not os.path.exists(os.path.join(gpr_dir, "gnatcov_rts.gpr")), + f"Cannot find {filename}", + ) + if not thistest.env.is_cross: + thistest.fail_if( + not os.path.exists( + os.path.join(shared_lib_dir, shared_lib_filename) + ), + f"Cannot find {filename}", + ) + +# Note that we cannot test here the summary when --prefix is not passed, since +# that would install gnatcov_rts in the toolchain prefix, which the testsuite +# is not allowed to do. + +thistest.result() diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 21345068e..86964bca4 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -19,6 +19,7 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Directories; use Ada.Directories; with Ada.Environment_Variables; +with Ada.Text_IO; use Ada.Text_IO; with GNAT.OS_Lib; with GNAT.Regexp; @@ -891,6 +892,44 @@ package body Setup_RTS is end case; end; end; + + if not Quiet then + New_Line; + Put_Line ("The coverage runtime has been successfully installed."); + if Prefix = "" then + Put_Line + ("It was installed in the toolchain's prefix: the environment" + & " is ready to use it."); + else + declare + Dir_Sep : Character renames + GNAT.OS_Lib.Directory_Separator; + On_Windows : constant Boolean := Dir_Sep = '\'; + + Norm_Prefix : constant String := + GNAT.OS_Lib.Normalize_Pathname + (Prefix, Resolve_Links => False); + GPR_Dir : constant String := + Norm_Prefix & Dir_Sep & "share" & Dir_Sep & "gpr"; + Shared_Lib_Dir : constant String := + Norm_Prefix & Dir_Sep & (if On_Windows then "bin" else "lib"); + Shared_Lib_Var : constant String := + (if On_Windows then "PATH" else "LD_LIBRARY_PATH"); + begin + Put_Line ("It was installed in: " & Prefix); + Put_Line ("In order to use it, remember to add:"); + New_Line; + Put_Line (" " & GPR_Dir); + New_Line; + Put_Line ("to the GPR_PROJECT_PATH environment variable, and"); + New_Line; + Put_Line (" " & Shared_Lib_Dir); + New_Line; + Put_Line ("to the " & Shared_Lib_Var + & " environment variable."); + end; + end if; + end if; end Setup; ---------------------------------- From d0629c11ec5554e363351bec490aa7dfa6333f45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Mon, 10 Jun 2024 20:13:39 +0200 Subject: [PATCH 0855/1483] Fix SARIF test regex for windows --- testsuite/tests/213-sarif-report/ada/full/ref.sarif | 2 +- testsuite/tests/213-sarif-report/all-lang/full/ref.sarif | 2 +- testsuite/tests/213-sarif-report/c/full/ref.sarif | 2 +- testsuite/tests/213-sarif-report/cpp/full/ref.sarif | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/testsuite/tests/213-sarif-report/ada/full/ref.sarif b/testsuite/tests/213-sarif-report/ada/full/ref.sarif index e2326eec2..283f60a1e 100644 --- a/testsuite/tests/213-sarif-report/ada/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/ada/full/ref.sarif @@ -1 +1 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/a\.adb"},"region":{"startLine":5,"startColumn":8}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/a\.adb"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/a\.adb"},"region":{"startLine":8,"startColumn":9}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/a\.adb"},"region":{"startLine":10,"startColumn":9}}}\]},{"ruleId":"UNDET","kind":"fail","level":"warning","message":{"text":"statement was not instrumented"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/a\.ads"},"region":{"startLine":8,"startColumn":31}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/b\.ads"},"region":{"startLine":2,"startColumn":39}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar\.adb"},"region":{"startLine":16,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar\.adb"},"region":{"startLine":17,"startColumn":15}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/src-bar/bar\.adb"},"region":{"startLine":30,"startColumn":44}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/foo\.adb"},"region":{"startLine":14,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/foo\.adb"},"region":{"startLine":15,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/foo\.adb"},"region":{"startLine":19,"startColumn":8}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/foo\.adb"},"region":{"startLine":21,"startColumn":32}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/foo\.adb"},"region":{"startLine":21,"startColumn":42}}}\]},{"ruleId":"ATC","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/src-foo/foo\.adb"},"region":{"startLine":22,"startColumn":22}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-lib/lib\.ads"},"region":{"startLine":6,"startColumn":42}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/main\.adb"},"region":{"startLine":10,"startColumn":6}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/main\.adb"},"region":{"startLine":11,"startColumn":10}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/main\.adb"},"region":{"startLine":14,"startColumn":6}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/main\.adb"},"region":{"startLine":15,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/main\.adb"},"region":{"startLine":19,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/ada/full/src-root/main\.adb"},"region":{"startLine":20,"startColumn":5}}}\]}\]}\]} +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":5,"startColumn":8}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":8,"startColumn":9}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":10,"startColumn":9}}}\]},{"ruleId":"UNDET","kind":"fail","level":"warning","message":{"text":"statement was not instrumented"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.ads"},"region":{"startLine":8,"startColumn":31}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)b\.ads"},"region":{"startLine":2,"startColumn":39}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startLine":16,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startLine":17,"startColumn":15}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startLine":30,"startColumn":44}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":14,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":15,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":19,"startColumn":8}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":21,"startColumn":32}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":21,"startColumn":42}}}\]},{"ruleId":"ATC","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":22,"startColumn":22}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.ads"},"region":{"startLine":6,"startColumn":42}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":10,"startColumn":6}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":11,"startColumn":10}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":14,"startColumn":6}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":15,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":19,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":20,"startColumn":5}}}\]}\]}\]} diff --git a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif index 5475c3fdf..527a8602d 100644 --- a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif @@ -1 +1 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/a\.adb"},"region":{"startLine":5,"startColumn":8}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/a\.adb"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/a\.adb"},"region":{"startLine":8,"startColumn":9}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/a\.adb"},"region":{"startLine":10,"startColumn":9}}}\]},{"ruleId":"UNDET","kind":"fail","level":"warning","message":{"text":"statement was not instrumented"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/a\.ads"},"region":{"startLine":8,"startColumn":31}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/b\.ads"},"region":{"startLine":2,"startColumn":39}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar\.adb"},"region":{"startLine":16,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar\.adb"},"region":{"startLine":17,"startColumn":15}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/src-bar/bar\.adb"},"region":{"startLine":30,"startColumn":44}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":8,"startColumn":13}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":8,"startColumn":20}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":8,"startColumn":25}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":27,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":34,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/c_source\.c"},"region":{"startLine":36,"startColumn":7}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":9,"startColumn":13}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":9,"startColumn":20}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":9,"startColumn":25}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":27,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":34,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/cpp_source\.cpp"},"region":{"startLine":36,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/foo\.adb"},"region":{"startLine":14,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/foo\.adb"},"region":{"startLine":15,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/foo\.adb"},"region":{"startLine":19,"startColumn":8}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/foo\.adb"},"region":{"startLine":21,"startColumn":32}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/foo\.adb"},"region":{"startLine":21,"startColumn":42}}}\]},{"ruleId":"ATC","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/src-foo/foo\.adb"},"region":{"startLine":22,"startColumn":22}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-lib/lib\.ads"},"region":{"startLine":6,"startColumn":42}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/main\.adb"},"region":{"startLine":18,"startColumn":6}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/main\.adb"},"region":{"startLine":19,"startColumn":10}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/main\.adb"},"region":{"startLine":22,"startColumn":6}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/main\.adb"},"region":{"startLine":23,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/main\.adb"},"region":{"startLine":27,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/all-lang/full/src-root/main\.adb"},"region":{"startLine":28,"startColumn":5}}}\]}\]}\]} +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":5,"startColumn":8}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":8,"startColumn":9}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":10,"startColumn":9}}}\]},{"ruleId":"UNDET","kind":"fail","level":"warning","message":{"text":"statement was not instrumented"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.ads"},"region":{"startLine":8,"startColumn":31}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)b\.ads"},"region":{"startLine":2,"startColumn":39}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startLine":16,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startLine":17,"startColumn":15}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startLine":30,"startColumn":44}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":8,"startColumn":13}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":8,"startColumn":20}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":8,"startColumn":25}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":27,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":34,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":36,"startColumn":7}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":9,"startColumn":13}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":9,"startColumn":20}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":9,"startColumn":25}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":27,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":34,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":36,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":14,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":15,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":19,"startColumn":8}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":21,"startColumn":32}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":21,"startColumn":42}}}\]},{"ruleId":"ATC","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":22,"startColumn":22}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.ads"},"region":{"startLine":6,"startColumn":42}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":18,"startColumn":6}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":19,"startColumn":10}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":22,"startColumn":6}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":23,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":27,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":28,"startColumn":5}}}\]}\]}\]} diff --git a/testsuite/tests/213-sarif-report/c/full/ref.sarif b/testsuite/tests/213-sarif-report/c/full/ref.sarif index fad137258..863cee712 100644 --- a/testsuite/tests/213-sarif-report/c/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/c/full/ref.sarif @@ -1 +1 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/src-foo/src-bar/bar\.c"},"region":{"startLine":6,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/src-foo/src-bar/bar\.c"},"region":{"startLine":6,"startColumn":20}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/src-foo/foo\.c"},"region":{"startLine":9,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/src-foo/foo\.c"},"region":{"startLine":11,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-lib/lib\.c"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-lib/lib\.c"},"region":{"startLine":8,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/main\.c"},"region":{"startLine":13,"startColumn":7}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/main\.c"},"region":{"startLine":15,"startColumn":11}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/main\.c"},"region":{"startLine":18,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/main\.c"},"region":{"startLine":20,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/main\.c"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/c/full/src-root/main\.c"},"region":{"startLine":26,"startColumn":7}}}\]}\]}\]} +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.c"},"region":{"startLine":6,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.c"},"region":{"startLine":6,"startColumn":20}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.c"},"region":{"startLine":9,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.c"},"region":{"startLine":11,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.c"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.c"},"region":{"startLine":8,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startLine":13,"startColumn":7}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startLine":15,"startColumn":11}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startLine":18,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startLine":20,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startLine":26,"startColumn":7}}}\]}\]}\]} diff --git a/testsuite/tests/213-sarif-report/cpp/full/ref.sarif b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif index d9443784c..e6d4d0587 100644 --- a/testsuite/tests/213-sarif-report/cpp/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif @@ -1 +1 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar\.cpp"},"region":{"startLine":6,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC/DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/src-foo/src-bar/bar\.cpp"},"region":{"startLine":6,"startColumn":20}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/src-foo/foo\.cpp"},"region":{"startLine":9,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/src-foo/foo\.cpp"},"region":{"startLine":11,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-lib/lib\.cpp"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-lib/lib\.cpp"},"region":{"startLine":8,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/main\.cpp"},"region":{"startLine":13,"startColumn":7}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/main\.cpp"},"region":{"startLine":15,"startColumn":11}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/main\.cpp"},"region":{"startLine":18,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/main\.cpp"},"region":{"startLine":20,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/main\.cpp"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*/213-sarif-report/cpp/full/src-root/main\.cpp"},"region":{"startLine":26,"startColumn":7}}}\]}\]}\]} +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.cpp"},"region":{"startLine":6,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.cpp"},"region":{"startLine":6,"startColumn":20}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.cpp"},"region":{"startLine":9,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.cpp"},"region":{"startLine":11,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.cpp"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.cpp"},"region":{"startLine":8,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startLine":13,"startColumn":7}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startLine":15,"startColumn":11}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startLine":18,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startLine":20,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startLine":26,"startColumn":7}}}\]}\]}\]} From 9009e0cc3bb778f67091e52328357966d1ebc752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 14 Jun 2024 17:13:09 +0200 Subject: [PATCH 0856/1483] Instrument.*: Use a qualified name to represent project names GPR projects allow dotted names, which are not directly usable in sources or symbol names. As such, represent the project names as qualified names, and convert them to symbols / slugs when using them to generate source constructs. --- testsuite/SUITE/tutils.py | 6 ++- .../manual-dump/dotted_prj/src/main.adb | 6 +++ .../manual-dump/dotted_prj/src/main_c.c | 8 ++++ .../manual-dump/dotted_prj/src/pkg.adb | 8 ++++ .../manual-dump/dotted_prj/src/pkg.ads | 5 ++ .../manual-dump/dotted_prj/src/pkg_c.c | 7 +++ .../manual-dump/dotted_prj/src/pkg_c.h | 1 + .../instr-cov/manual-dump/dotted_prj/test.py | 47 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 27 ++++++----- tools/gnatcov/instrument-c.adb | 28 ++++++----- tools/gnatcov/instrument-common.adb | 2 +- tools/gnatcov/instrument-common.ads | 15 +++--- tools/gnatcov/instrument-gcc_wrapper.adb | 2 +- tools/gnatcov/instrument-projects.adb | 4 +- tools/gnatcov/instrument.adb | 5 +- tools/gnatcov/instrument.ads | 5 +- 16 files changed, 136 insertions(+), 40 deletions(-) create mode 100644 testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main_c.c create mode 100644 testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.c create mode 100644 testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.h create mode 100644 testsuite/tests/instr-cov/manual-dump/dotted_prj/test.py diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index d0a29386c..3a77d03b4 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -441,6 +441,9 @@ def gprfor( If CWD is None, generate the project file in the current directory. Generate it in the CWD directory otherwise. + + If PRJID contains any '.', they are replaced by '-' in the project + filename. """ cwd = cwd or os.getcwd() @@ -547,7 +550,8 @@ def gprfor( } return text_to_file( - text=gprtext, filename=os.path.join(cwd, prjid + ".gpr") + text=gprtext, + filename=os.path.join(cwd, prjid.replace(".", "-") + ".gpr"), ) diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main.adb b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main.adb new file mode 100644 index 000000000..9923e2521 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Main is +begin + Pkg.Do_Dump; +end Main; diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main_c.c b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main_c.c new file mode 100644 index 000000000..12ea53f32 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/main_c.c @@ -0,0 +1,8 @@ +#include "pkg_c.h" + +int +main () +{ + do_dump (); + return 0; +} diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.adb b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.adb new file mode 100644 index 000000000..e681359db --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + procedure Do_Dump is + begin + pragma Annotate (Xcov, Dump_Buffers); + end Do_Dump; + +end Pkg; diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.ads b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.ads new file mode 100644 index 000000000..410a9040d --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + procedure Do_Dump; + +end Pkg; diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.c b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.c new file mode 100644 index 000000000..01a1528f5 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.c @@ -0,0 +1,7 @@ +#include "pkg_c.h" + +void +do_dump () +{ + /* GNATCOV_DUMP_BUFFERS */ +} diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.h b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.h new file mode 100644 index 000000000..7b02b950e --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/src/pkg_c.h @@ -0,0 +1 @@ +void do_dump (); diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.py b/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.py new file mode 100644 index 000000000..26f590832 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.py @@ -0,0 +1,47 @@ +""" +Test that the sources generated when using --dump-trigger=manual on a project +which has a dotted name compile correctly. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +# Empty dummy project, just to make the Base.Prj a legal project +empty = gprfor(srcdirs=[], prjid="empty", mains=[]) + +# The prjid is at the heart of this test, keep it a dotted name +gpr = gprfor( + mains=["main.adb", "main_c.c"], + prjid="empty.prj", + srcdirs="../src", + deps=[empty], + langs=["Ada", "C"], +) + +build_run_and_coverage( + gprsw=GPRswitches(gpr), + covlevel="stmt", + mains=["main", "main_c"], + extra_coverage_args=["-axcov"], + dump_trigger="manual", + manual_prj_name="empty.prj", +) + +# Check that we got the expected coverage report +check_xcov_reports( + "obj", + { + "main_c.c.xcov": {"+": {6}, "-": {7}}, + "pkg_c.c.xcov": {}, + "main.adb.xcov": {"+": {5}}, + "pkg.adb.xcov": {}, + "pkg.ads.xcov": {}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 1fd747740..b9743970a 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1435,7 +1435,7 @@ package body Instrument.Ada_Unit is -------------------------- function Buffers_List_Unit - (Project_Name : String) return Ada_Qualified_Name; + (Project_Name : Ada_Qualified_Name) return Ada_Qualified_Name; -- Returns the name of the unit containing the array of coverage buffers. -- It is named after the given project main name (e.g. if the -- project p.gpr, its name is .). @@ -8294,7 +8294,8 @@ package body Instrument.Ada_Unit is (RH, Kind => Ada_String_Literal, Text => To_Text - ("""" & (+Prj.Prj_Name) & """"))); + ("""" & (To_Ada (Prj.Prj_Name)) + & """"))); Reset_Call : constant Node_Rewriting_Handle := To_Nodes (RH, @@ -8743,11 +8744,10 @@ package body Instrument.Ada_Unit is ----------------------- function Buffers_List_Unit - (Project_Name : String) return Ada_Qualified_Name + (Project_Name : Ada_Qualified_Name) return Ada_Qualified_Name is Project_Name_Slug : constant String := - Qualified_Name_Slug - (To_Qualified_Name (Project_Name), Use_Hash => False); + Qualified_Name_Slug (Project_Name, Use_Hash => False); begin return Ada_Identifier_Vectors."&" (Sys_Prefix, Instrument.Ada_Identifier (+Project_Name_Slug)); @@ -9121,7 +9121,9 @@ package body Instrument.Ada_Unit is begin Helper_Unit := Sys_Prefix; Helper_Unit.Append - (To_Unbounded_String ("D" & "B_manual_" & (+Prj.Prj_Name))); + (To_Unbounded_String + ("D" & "B_manual_" + & Qualified_Name_Slug (Prj.Prj_Name, Use_Hash => False))); return Helper_Unit; end Create_Manual_Helper_Unit_Name; @@ -9195,7 +9197,8 @@ package body Instrument.Ada_Unit is Helper_Unit_Name : constant String := To_Ada (Helper_Unit); Dump_Procedure : constant String := To_String (Dump_Procedure_Name); Output_Unit_Str : constant String := To_Ada (Output_Unit); - Project_Name_Str : constant String := """" & (+Prj.Prj_Name) & """"; + Project_Name_Str : constant String := + """" & To_Ada (Prj.Prj_Name) & """"; Reset_Procedure : constant String := To_String (Reset_Procedure_Name); Sys_Lists : Ada_Qualified_Name := Sys_Buffers; @@ -9309,7 +9312,7 @@ package body Instrument.Ada_Unit is end case; File.Put_Line - ("with " & To_Ada (Buffers_List_Unit (+Prj.Prj_Name)) & ";"); + ("with " & To_Ada (Buffers_List_Unit (Prj.Prj_Name)) & ";"); File.Put_Line ("package body " & Helper_Unit_Name & " is"); File.New_Line; @@ -9360,7 +9363,7 @@ package body Instrument.Ada_Unit is File.Put_Line (Indent2 & "(Buffers_Groups => " - & To_Ada (Buffers_List_Unit (+Prj.Prj_Name)) + & To_Ada (Buffers_List_Unit (Prj.Prj_Name)) & ".List,"); case Dump_Config.Channel is when Binary_File => @@ -9477,7 +9480,7 @@ package body Instrument.Ada_Unit is File.Put_Line (" " & To_Ada (Sys_Lists) & ".Reset_Group_Array_Buffers"); File.Put_Line (" (" - & To_Ada (Buffers_List_Unit (+Prj.Prj_Name)) + & To_Ada (Buffers_List_Unit (Prj.Prj_Name)) & ".C_List);"); File.Put_Line ("end " & Reset_Procedure & ";"); File.New_Line; @@ -9525,7 +9528,7 @@ package body Instrument.Ada_Unit is is Buffers_CU_Name : constant Compilation_Unit_Part := CU_Name_For_Unit - (Buffers_List_Unit (+Prj.Prj_Name), GNATCOLL.Projects.Unit_Spec); + (Buffers_List_Unit (Prj.Prj_Name), GNATCOLL.Projects.Unit_Spec); File : Text_Files.File_Type; begin -- Emit the unit to contain the list of buffers @@ -9613,7 +9616,7 @@ package body Instrument.Ada_Unit is File.Put_Line (" pragma Export (C, C_List, """ - & Unit_Buffers_Array_Name (+Prj.Prj_Name) & """);"); + & Unit_Buffers_Array_Name (Prj.Prj_Name) & """);"); File.New_Line; File.Put_Line ("end " & Unit_Name & ";"); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 8493e5a50..f2ba622c7 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3712,9 +3712,9 @@ package body Instrument.C is Filename : constant String := +Helper_Unit; Dump_Procedure : constant String := Dump_Procedure_Symbol - (Main, Dump_Config.Trigger = Manual, Prj_Name => +Prj.Prj_Name); + (Main, Dump_Config.Trigger = Manual, Prj.Prj_Name); Reset_Procedure : constant String := - Reset_Procedure_Symbol (+Prj.Prj_Name); + Reset_Procedure_Symbol (Prj.Prj_Name); begin -- Emit the package body @@ -3740,7 +3740,7 @@ package body Instrument.C is (File, Instrumenter, "const struct gnatcov_rts_coverage_buffers_group_array", - Unit_Buffers_Array_Name (+Prj.Prj_Name)); + Unit_Buffers_Array_Name (Prj.Prj_Name)); -- Emit the procedure to write the trace file @@ -3755,7 +3755,7 @@ package body Instrument.C is File.Put_Line (Indent1 & Output_Proc & " ("); File.Put_Line (Indent2 & "&" - & Unit_Buffers_Array_Name (+Prj.Prj_Name) & ","); + & Unit_Buffers_Array_Name (Prj.Prj_Name) & ","); case Dump_Config.Channel is when Binary_File => declare @@ -3782,7 +3782,7 @@ package body Instrument.C is & "STR (" & C_String_Literal (if Dump_Config.Trigger = Manual - then +Prj.Prj_Name + then To_Ada (Prj.Prj_Name) else +Main.Filename) & "),"); File.Put_Line (Indent2 & "gnatcov_rts_time_to_uint64()" & ","); @@ -3799,7 +3799,7 @@ package body Instrument.C is File.Put_Line (Indent2 & "STR (" & C_String_Literal (if Dump_Config.Trigger = Manual - then +Prj.Prj_Name + then To_Ada (Prj.Prj_Name) else +Main.Filename) & "),"); File.Put_Line (Indent2 & "0,"); @@ -3817,7 +3817,7 @@ package body Instrument.C is File.Put_Line ("void " & Reset_Procedure & "(void) {"); File.Put_Line (Indent1 & "gnatcov_rts_reset_group_array ("); File.Put_Line - (Indent2 & "&" & Unit_Buffers_Array_Name (+Prj.Prj_Name) & ");"); + (Indent2 & "&" & Unit_Buffers_Array_Name (Prj.Prj_Name) & ");"); File.Put_Line ("}"); File.Close; @@ -3880,9 +3880,9 @@ package body Instrument.C is Matches_Reset : Match_Array (0 .. 0); Dump_Procedure : constant String := Dump_Procedure_Symbol - (Main => Dummy_Main, Manual => True, Prj_Name => +Prj.Prj_Name); + (Main => Dummy_Main, Manual => True, Prj_Name => Prj.Prj_Name); Reset_Procedure : constant String := - Reset_Procedure_Symbol (+Prj.Prj_Name); + Reset_Procedure_Symbol (Prj.Prj_Name); Extern_Prefix : constant String := C_Family_Instrumenter_Type'Class (Self).Extern_Prefix; @@ -4007,7 +4007,9 @@ package body Instrument.C is else String'Write - (S, Dump_Procedure & "(""" & (+Prj.Prj_Name) & """);"); + (S, + Dump_Procedure & "(""" & (To_Ada (Prj.Prj_Name)) + & """);"); end if; Index := Matches_Dump (0).Last + 1; @@ -4297,7 +4299,7 @@ package body Instrument.C is New_File (Prj, To_Symbol_Name (Sys_Prefix) - & "_d_b_" & (+Prj.Prj_Name) + & "_d_b_" & To_Symbol_Name (Prj.Prj_Name) & (if Lang = CPP_Language then "_cpp" else "_c") & (+Prj.Body_Suffix (Lang))); -- The _cpp or _c suffix is required so that in case both C and C++ @@ -4530,7 +4532,7 @@ package body Instrument.C is Unit_Name => +New_File (Prj, - "gcvrtc-" & (+Prj.Prj_Name) + "gcvrtc-" & To_Symbol_Name (Prj.Prj_Name) & (+Prj.Body_Suffix (C_Family_Instrumenter_Type'Class (Self).Language)))); @@ -4538,7 +4540,7 @@ package body Instrument.C is Buffer_Array_Decl : constant String := "const struct gnatcov_rts_coverage_buffers_group_array " - & Unit_Buffers_Array_Name (+Prj.Prj_Name); + & Unit_Buffers_Array_Name (Prj.Prj_Name); Buffer_Unit_Length : constant String := Count_Type'Image (Buffer_Symbols.Length); begin diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 57441e158..5049339c3 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -87,7 +87,7 @@ package body Instrument.Common is Compile (Dump_Procedure_Symbol ((File_Based_Language, Null_Unbounded_String), Manual => True)); Reset_Pattern : constant Pattern_Matcher := - Compile (Reset_Procedure_Symbol ("")); + Compile (Reset_Procedure_Symbol (Ada_Identifier_Vectors.Empty_Vector)); -- Precomputed patterns to be used as helpers for -- Is_Manual_Indication_Procedure_Symbol. diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 23bc670d9..e1077657f 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -113,7 +113,8 @@ package Instrument.Common is function Dump_Procedure_Symbol (Main : Compilation_Unit_Part; Manual : Boolean := False; - Prj_Name : String := "") return String + Prj_Name : Ada_Qualified_Name := Ada_Identifier_Vectors.Empty_Vector) + return String is ("gnatcov_rts_" & (if Manual @@ -122,13 +123,14 @@ package Instrument.Common is & "_" & To_Lower (To_String (Dump_Procedure_Name)) & (if Manual - then "_" & Prj_Name + then "_" & To_Symbol_Name (Prj_Name) else "")); -- Return the name of the exported symbol for the Dump_Buffers function - function Reset_Procedure_Symbol (Prj_Name : String) return String is + function Reset_Procedure_Symbol + (Prj_Name : Ada_Qualified_Name) return String is ("gnatcov_rts_" & To_Lower (To_String (Reset_Procedure_Name)) - & "_" & Prj_Name); + & "_" & To_Symbol_Name (Prj_Name)); -- Return the name of the exported symbol for the Reset_Buffers procedure function Is_Manual_Indication_Procedure_Symbol @@ -155,8 +157,9 @@ package Instrument.Common is -- Name of the symbol that references the -- gnatcov_rts_coverage_buffers_group struct for this file. - function Unit_Buffers_Array_Name (Prj_Name : String) return String is - ("gnatcov_rts_buffers_array_" & Prj_Name); + function Unit_Buffers_Array_Name + (Prj_Name : Ada_Qualified_Name) return String is + ("gnatcov_rts_buffers_array_" & To_Symbol_Name (Prj_Name)); -- Name of the symbol that designates the -- gnatcov_rts_coverage_buffers_array struct, which contains an array of -- coverage buffers for all instrumented units in this project. diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 4602d8482..8a96adb2e 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -658,7 +658,7 @@ begin -- Generate an artificial project description to pass compiler switches and -- default spec / body suffixes. - Prj.Prj_Name := +"main"; + Prj.Prj_Name := To_Qualified_Name ("main"); Prj.Output_Dir := +Instr_Dir.Directory_Name; Prj.Spec_Suffix := (C_Language => +".h", CPP_Language => +".hh", others => <>); diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index d26b49653..d91f3281c 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -302,7 +302,7 @@ is end if; end loop; - Result.Prj_Name := +Prj.Name; + Result.Prj_Name := To_Qualified_Name (Prj.Name); Result.Dot_Replacement := +Dot_Replacement; -- Register the source directories of the project tree @@ -889,7 +889,7 @@ is Get_Or_Create_Project_Info (IC, Source.Project); Prj : Prj_Desc renames Prj_Info.Desc; Is_Root_Prj : constant Boolean := - Prj.Prj_Name = Root_Project_Info.Project.Name; + To_Ada (Prj.Prj_Name) = Root_Project_Info.Project.Name; Source_Name : constant String := GNATCOLL.VFS."+" (Source.File.Full_Name); Helper_Unit_Name : constant Unbounded_String := diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 69e1e40eb..58274ee40 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -486,6 +486,7 @@ package body Instrument is use Command_Line.Parser; Language : constant Some_Language := To_Language (+Args.String_Args (Opt_Lang).Value); + Prj_Name : Unbounded_String; Result : Prj_Desc; procedure Fill_If_Present @@ -517,9 +518,11 @@ package body Instrument is Fill_If_Present (Opt_Output_Directory, Result.Output_Dir); Fill_If_Present (Opt_Spec_Suffix, Result.Spec_Suffix (Language)); Fill_If_Present (Opt_Body_Suffix, Result.Body_Suffix (Language)); - Fill_If_Present (Opt_Project_Name, Result.Prj_Name); + Fill_If_Present (Opt_Project_Name, Prj_Name); Fill_If_Present (Opt_Dot_Replacement, Result.Dot_Replacement); + Result.Prj_Name := To_Qualified_Name (+Prj_Name); + -- Compiler options are loaded through the --c/c++-opts switch return Result; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 2aa041062..146ae0fdb 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -164,8 +164,7 @@ package Instrument is function Canonicalize (Name : Ada_Qualified_Name) return Ada_Qualified_Name; -- Fold casing of Ada identifiers - function To_Symbol_Name (Name : Ada_Qualified_Name) return String - with Pre => not Name.Is_Empty; + function To_Symbol_Name (Name : Ada_Qualified_Name) return String; -- Lower case each name of the qualified name, and joined them with an -- underscore, to have a C-like syntax. -- @@ -262,7 +261,7 @@ package Instrument is type C_Lang_Array_Vec is array (C_Family_Language) of String_Vectors.Vector; type Prj_Desc is record - Prj_Name : Unbounded_String; + Prj_Name : Ada_Qualified_Name; -- Name for the project Output_Dir : Unbounded_String; From c3e0634eb6ee62cfa9a5c6fbd274a26c70794aa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 17 Jun 2024 14:41:40 +0200 Subject: [PATCH 0857/1483] Use the most exending project for manual dump trigger processing When processing files for a manual dump trigger, gnatcov used to iterate over all the sources in the project tree. Each source file is associated to the project in which it is originally located by GNATCOLL.Projects, whereas we would need to associate each file to the most extending project for its original project, to ensure the coverage buffers for all files in the extending project are dumped, not only those in the extended project. This change ensures that each file is associated to the most-extending project when processing it for manual dump trigger items. --- .../instr-cov/manual-dump/ext_prj/p_ext.gpr | 7 ++ .../manual-dump/ext_prj/src_base/common.adb | 15 +++++ .../manual-dump/ext_prj/src_base/common.ads | 5 ++ .../ext_prj/src_base/contractor.adb | 7 ++ .../ext_prj/src_base/contractor.ads | 5 ++ .../manual-dump/ext_prj/src_base/main.adb | 7 ++ .../manual-dump/ext_prj/src_ext/common.adb | 5 ++ .../ext_prj/src_ext/contractor.adb | 10 +++ .../instr-cov/manual-dump/ext_prj/test.py | 64 +++++++++++++++++++ tools/gnatcov/instrument-projects.adb | 7 +- 10 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/instr-cov/manual-dump/ext_prj/p_ext.gpr create mode 100644 testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.ads create mode 100644 testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.ads create mode 100644 testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/main.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/common.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/contractor.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/ext_prj/test.py diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/p_ext.gpr b/testsuite/tests/instr-cov/manual-dump/ext_prj/p_ext.gpr new file mode 100644 index 000000000..716dbeab1 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/p_ext.gpr @@ -0,0 +1,7 @@ +project P_Ext extends "./p_base.gpr" is + + for Source_Dirs use ("../src_ext"); + for Object_Dir use "obj_ext"; + for Exec_Dir use "."; + +end P_Ext; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.adb b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.adb new file mode 100644 index 000000000..54a20625b --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Common is + + procedure Say_Hello is + begin + Put_Line ("Hello from Base!"); + + -- This is to check that this overridden source does not generate a + -- trace, as it should not be compiled even after instrumentation. + + pragma Annotate (Xcov, Dump_Buffers); + end Say_Hello; + +end Common; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.ads b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.ads new file mode 100644 index 000000000..b65b7a750 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/common.ads @@ -0,0 +1,5 @@ +package Common is + + procedure Say_Hello; + +end Common; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.adb b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.adb new file mode 100644 index 000000000..301de539c --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Contractor is + + procedure Say_Hello is null; + +end Contractor; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.ads b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.ads new file mode 100644 index 000000000..28eae2237 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/contractor.ads @@ -0,0 +1,5 @@ +package Contractor is + + procedure Say_Hello; + +end Contractor; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/main.adb b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/main.adb new file mode 100644 index 000000000..b3cf894f7 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_base/main.adb @@ -0,0 +1,7 @@ +with Common; + +procedure Main is +begin + Common.Say_Hello; + pragma Annotate (Xcov, Dump_Buffers); +end Main; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/common.adb b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/common.adb new file mode 100644 index 000000000..45145b1df --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/common.adb @@ -0,0 +1,5 @@ +with Contractor; + +package body Common is + procedure Say_Hello renames Contractor.Say_Hello; +end Common; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/contractor.adb b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/contractor.adb new file mode 100644 index 000000000..7df3e7c8a --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/src_ext/contractor.adb @@ -0,0 +1,10 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Contractor is + + procedure Say_Hello is + begin + Put_Line ("Hello from Ext!"); + end Say_Hello; + +end Contractor; diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/test.py b/testsuite/tests/instr-cov/manual-dump/ext_prj/test.py new file mode 100644 index 000000000..c58144dd5 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/test.py @@ -0,0 +1,64 @@ +""" +Test that instrumentation of a project tree including an extended project +produces valid sources, and that coverage for all units is properly dumped. +""" + +import glob +import os + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +base_gpr = gprfor( + mains=["main.adb"], + srcdirs=["../src_base"], + objdir="obj_base", + prjid="p_base", +) +ext_gpr = "p_ext.gpr" + +# gprfor does not allow the creation of an extend project, so use our own. +cp(os.path.join("..", ext_gpr), ".") + +# Run the coverage cycle +build_run_and_coverage( + gprsw=GPRswitches(ext_gpr), + covlevel="stmt", + mains=["main"], + gpr_obj_dir="obj_ext", + dump_trigger="manual", + manual_prj_name="", + extra_coverage_args=["-axcov"], +) + + +# Check that there only is a single trace produced, to ensure that the manual +# dump indication in the overridden common.adb file has not been compiled. +traces = glob.glob("*.srctrace") +thistest.fail_if_not_equal( + "Unexpected number of traces", + expected=1, + actual=len(traces), +) + +# Check the coverage contents +check_xcov_reports( + "obj_ext", + { + "main.adb.xcov": {"+": {5}}, + "common.ads.xcov": {}, + "common.adb.xcov": {}, + "contractor.ads.xcov": {}, + "contractor.adb.xcov": {"+": {7}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index d91f3281c..f95b53008 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -885,8 +885,13 @@ is declare use String_Sets; + -- The sources we are processing should be viewed from the most + -- extending project we are processing, to ensure it dumps the + -- buffers of all the sources in the extending projects as well. + Prj_Info : constant Project_Info_Access := - Get_Or_Create_Project_Info (IC, Source.Project); + Get_Or_Create_Project_Info + (IC, Source.Project.Extending_Project (Recurse => True)); Prj : Prj_Desc renames Prj_Info.Desc; Is_Root_Prj : constant Boolean := To_Ada (Prj.Prj_Name) = Root_Project_Info.Project.Name; From 78487285b65a60656ae3be0cd05377c307000d3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 18 Jun 2024 11:40:49 +0200 Subject: [PATCH 0858/1483] XFAIL extending project test for manual dump on cross There is an issue in gprbuild resulting in duplicate last_chance_handler symbols being defined, preventing the compilation of the test. XFail it while this is not yet resolved --- testsuite/tests/instr-cov/manual-dump/dotted_prj/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/instr-cov/manual-dump/dotted_prj/test.opt diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.opt b/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.opt new file mode 100644 index 000000000..2998a5c08 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.opt @@ -0,0 +1 @@ +!native XFAIL Build failure with mixed language mains. See #212 From 9180cb706da26f78ba92cc3cb24ba7b6508de3b9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 22 May 2024 14:58:38 +0000 Subject: [PATCH 0859/1483] SC_Obligations: add support for pragma Interrupts_System_By_Default (cherry picked from commit d19bfbeb4d9090f3650a7f6525566e51298cc32b) --- tools/gnatcov/sc_obligations.ads | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 67281b50d..74098dd20 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -925,6 +925,7 @@ package SC_Obligations is Pragma_Interrupt_Handler, Pragma_Interrupt_Priority, Pragma_Interrupt_State, + Pragma_Interrupts_System_By_Default, Pragma_Invariant, Pragma_Keep_Names, Pragma_License, @@ -1235,6 +1236,7 @@ package SC_Obligations is Pragma_Inspection_Point => False, Pragma_Interface_Name => False, Pragma_Interrupt_Handler => False, + Pragma_Interrupts_System_By_Default => False, Pragma_Keep_Names => False, Pragma_Link_With => False, Pragma_Linker_Alias => False, From 1c33d45e7ae4d8eb959ee9203fec51223574bd83 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 28 May 2024 08:10:11 +0000 Subject: [PATCH 0860/1483] 222-subp-of-interest-cplx/pkg.adb: rework after recent LAL enhancements Libadalang now correctly detects static expressions that contain string concatenations as static expressions. As a consequence, gnatcov now considers that decisions involving these can be static, and thus does not generate obligations for these obligations. Rework this testcase to avoid static expressions. (cherry picked from commit cb249a6f50fcee3e742352b49b552b24fd016aa6) --- testsuite/tests/222-subp-of-interest-cplx/pkg.adb | 9 +++++++-- testsuite/tests/222-subp-of-interest-cplx/pkg.ads | 1 + 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/222-subp-of-interest-cplx/pkg.adb b/testsuite/tests/222-subp-of-interest-cplx/pkg.adb index 3007f8417..d93ae1e13 100644 --- a/testsuite/tests/222-subp-of-interest-cplx/pkg.adb +++ b/testsuite/tests/222-subp-of-interest-cplx/pkg.adb @@ -9,8 +9,8 @@ package body Pkg is function One return Integer is begin - return (if String'("this is a very long decision" - & "that spans multiple lines")'Length = 1 + return (if String'(String_Identity ("this is a very long decision") + & String_Identity ("that spans multiple lines"))'Length = 1 then 2 else 1); end One; @@ -20,4 +20,9 @@ package body Pkg is return 2; end Two; + function String_Identity (S : String) return String is + begin + return S; + end String_Identity; + end Pkg; diff --git a/testsuite/tests/222-subp-of-interest-cplx/pkg.ads b/testsuite/tests/222-subp-of-interest-cplx/pkg.ads index 75040b79e..d3a8fa4b1 100644 --- a/testsuite/tests/222-subp-of-interest-cplx/pkg.ads +++ b/testsuite/tests/222-subp-of-interest-cplx/pkg.ads @@ -2,4 +2,5 @@ package Pkg is function Zero return Integer; function One return Integer; function Two return Integer; + function String_Identity (S : String) return String; end Pkg; From 1c7f21b08120ed45ff3d8ce37e51674f5d2f477a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 11 Jun 2024 08:48:24 +0200 Subject: [PATCH 0861/1483] Fix SARIF tests to fit new GNATCOLL.JSON ordering (cherry picked from commit 8c7fcdbd47accd16f34b49ff9476ed6a20c0eecf) --- testsuite/tests/213-sarif-report/ada/full/ref.sarif | 2 +- testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif | 2 +- testsuite/tests/213-sarif-report/all-lang/full/ref.sarif | 2 +- .../tests/213-sarif-report/all-lang/no-violations/ref.sarif | 2 +- testsuite/tests/213-sarif-report/c/full/ref.sarif | 2 +- testsuite/tests/213-sarif-report/c/no-violations/ref.sarif | 2 +- testsuite/tests/213-sarif-report/cpp/full/ref.sarif | 2 +- testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif | 2 +- 8 files changed, 8 insertions(+), 8 deletions(-) diff --git a/testsuite/tests/213-sarif-report/ada/full/ref.sarif b/testsuite/tests/213-sarif-report/ada/full/ref.sarif index 283f60a1e..e376eafdc 100644 --- a/testsuite/tests/213-sarif-report/ada/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/ada/full/ref.sarif @@ -1 +1 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":5,"startColumn":8}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":8,"startColumn":9}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":10,"startColumn":9}}}\]},{"ruleId":"UNDET","kind":"fail","level":"warning","message":{"text":"statement was not instrumented"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.ads"},"region":{"startLine":8,"startColumn":31}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)b\.ads"},"region":{"startLine":2,"startColumn":39}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startLine":16,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startLine":17,"startColumn":15}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startLine":30,"startColumn":44}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":14,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":15,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":19,"startColumn":8}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":21,"startColumn":32}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":21,"startColumn":42}}}\]},{"ruleId":"ATC","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":22,"startColumn":22}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.ads"},"region":{"startLine":6,"startColumn":42}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":10,"startColumn":6}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":11,"startColumn":10}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":14,"startColumn":6}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":15,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":19,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":20,"startColumn":5}}}\]}\]}\]} +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":8,"startLine":5}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":7,"startLine":6}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":9,"startLine":8}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":9,"startLine":10}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"warning","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.ads"},"region":{"startColumn":31,"startLine":8}}}\],"message":{"text":"statement was not instrumented"},"ruleId":"UNDET"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)b\.ads"},"region":{"startColumn":39,"startLine":2}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startColumn":14,"startLine":16}}}\],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startColumn":15,"startLine":17}}}\],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startColumn":44,"startLine":30}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":10,"startLine":14}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":5,"startLine":15}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":8,"startLine":19}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":32,"startLine":21}}}\],"message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"ruleId":"ATCC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":42,"startLine":21}}}\],"message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"ruleId":"ATCC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":22,"startLine":22}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"ATC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.ads"},"region":{"startColumn":42,"startLine":6}}}\],"message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"ruleId":"ATCC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":6,"startLine":10}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":10,"startLine":11}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":6,"startLine":14}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":5,"startLine":15}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":10,"startLine":19}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":5,"startLine":20}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"}\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} diff --git a/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif index 05e3e2645..af298c0be 100644 --- a/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif +++ b/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif @@ -1 +1 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[\]}\]} +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} diff --git a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif index 527a8602d..2d10f1574 100644 --- a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif @@ -1 +1 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":5,"startColumn":8}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":8,"startColumn":9}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startLine":10,"startColumn":9}}}\]},{"ruleId":"UNDET","kind":"fail","level":"warning","message":{"text":"statement was not instrumented"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.ads"},"region":{"startLine":8,"startColumn":31}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)b\.ads"},"region":{"startLine":2,"startColumn":39}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startLine":16,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startLine":17,"startColumn":15}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startLine":30,"startColumn":44}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":8,"startColumn":13}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":8,"startColumn":20}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":8,"startColumn":25}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":27,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":34,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startLine":36,"startColumn":7}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":9,"startColumn":13}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":9,"startColumn":20}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":9,"startColumn":25}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":27,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":34,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startLine":36,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":14,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":15,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":19,"startColumn":8}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":21,"startColumn":32}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":21,"startColumn":42}}}\]},{"ruleId":"ATC","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startLine":22,"startColumn":22}}}\]},{"ruleId":"ATCC","kind":"fail","level":"error","message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.ads"},"region":{"startLine":6,"startColumn":42}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":18,"startColumn":6}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":19,"startColumn":10}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":22,"startColumn":6}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":23,"startColumn":5}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":27,"startColumn":10}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startLine":28,"startColumn":5}}}\]}\]}\]} +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":8,"startLine":5}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":7,"startLine":6}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":9,"startLine":8}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":9,"startLine":10}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"warning","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.ads"},"region":{"startColumn":31,"startLine":8}}}],"message":{"text":"statement was not instrumented"},"ruleId":"UNDET"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)b\.ads"},"region":{"startColumn":39,"startLine":2}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startColumn":14,"startLine":16}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startColumn":15,"startLine":17}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startColumn":44,"startLine":30}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":13,"startLine":8}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":20,"startLine":8}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":25,"startLine":8}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":7,"startLine":24}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":7,"startLine":27}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":7,"startLine":34}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":7,"startLine":36}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":13,"startLine":9}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":20,"startLine":9}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":25,"startLine":9}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":7,"startLine":24}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":7,"startLine":27}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":7,"startLine":34}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":7,"startLine":36}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":10,"startLine":14}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":5,"startLine":15}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":8,"startLine":19}}}],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":32,"startLine":21}}}],"message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"ruleId":"ATCC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":42,"startLine":21}}}],"message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"ruleId":"ATCC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":22,"startLine":22}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"ATC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.ads"},"region":{"startColumn":42,"startLine":6}}}],"message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"ruleId":"ATCC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":6,"startLine":18}}}],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":10,"startLine":19}}}],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":6,"startLine":22}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":5,"startLine":23}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":10,"startLine":27}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":5,"startLine":28}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"}],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}],"version":".*"}}}],"version":"2\.1\.0"} diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif index 05e3e2645..af298c0be 100644 --- a/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif @@ -1 +1 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[\]}\]} +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} diff --git a/testsuite/tests/213-sarif-report/c/full/ref.sarif b/testsuite/tests/213-sarif-report/c/full/ref.sarif index 863cee712..38905f4a6 100644 --- a/testsuite/tests/213-sarif-report/c/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/c/full/ref.sarif @@ -1 +1 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.c"},"region":{"startLine":6,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.c"},"region":{"startLine":6,"startColumn":20}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.c"},"region":{"startLine":9,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.c"},"region":{"startLine":11,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.c"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.c"},"region":{"startLine":8,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startLine":13,"startColumn":7}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startLine":15,"startColumn":11}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startLine":18,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startLine":20,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startLine":26,"startColumn":7}}}\]}\]}\]} +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.c"},"region":{"startColumn":14,"startLine":6}}}\],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.c"},"region":{"startColumn":20,"startLine":6}}}\],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.c"},"region":{"startColumn":7,"startLine":9}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.c"},"region":{"startColumn":7,"startLine":11}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.c"},"region":{"startColumn":7,"startLine":6}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.c"},"region":{"startColumn":7,"startLine":8}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startColumn":7,"startLine":13}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startColumn":11,"startLine":15}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startColumn":7,"startLine":18}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startColumn":7,"startLine":20}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startColumn":7,"startLine":24}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startColumn":7,"startLine":26}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"}\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} diff --git a/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif index 05e3e2645..af298c0be 100644 --- a/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif +++ b/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif @@ -1 +1 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[\]}\]} +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} diff --git a/testsuite/tests/213-sarif-report/cpp/full/ref.sarif b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif index e6d4d0587..5a97eb0bf 100644 --- a/testsuite/tests/213-sarif-report/cpp/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif @@ -1 +1 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","defaultConfiguration":{"level":"error"}},{"id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.cpp"},"region":{"startLine":6,"startColumn":14}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.cpp"},"region":{"startLine":6,"startColumn":20}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.cpp"},"region":{"startLine":9,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.cpp"},"region":{"startLine":11,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.cpp"},"region":{"startLine":6,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.cpp"},"region":{"startLine":8,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startLine":13,"startColumn":7}}}\]},{"ruleId":"MCDC","kind":"fail","level":"error","message":{"text":"decision outcome FALSE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startLine":15,"startColumn":11}}}\]},{"ruleId":"DECISION","kind":"fail","level":"error","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startLine":18,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"error","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startLine":20,"startColumn":7}}}\]},{"ruleId":"DECISION","kind":"fail","level":"note","message":{"text":"decision outcome TRUE never exercised"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startLine":24,"startColumn":7}}}\]},{"ruleId":"STMT","kind":"fail","level":"note","message":{"text":"statement not executed"},"locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startLine":26,"startColumn":7}}}\]}\]}\]} +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.cpp"},"region":{"startColumn":14,"startLine":6}}}\],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.cpp"},"region":{"startColumn":20,"startLine":6}}}\],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.cpp"},"region":{"startColumn":7,"startLine":9}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.cpp"},"region":{"startColumn":7,"startLine":11}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.cpp"},"region":{"startColumn":7,"startLine":6}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.cpp"},"region":{"startColumn":7,"startLine":8}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startColumn":7,"startLine":13}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startColumn":11,"startLine":15}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startColumn":7,"startLine":18}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startColumn":7,"startLine":20}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startColumn":7,"startLine":24}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startColumn":7,"startLine":26}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"}\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} diff --git a/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif index 05e3e2645..af298c0be 100644 --- a/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif +++ b/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif @@ -1 +1 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","version":"2\.1\.0","runs":\[{"tool":{"driver":{"name":"gnatcov","version":".*","informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","rules":\[{"id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","defaultConfiguration":{"level":"error"}},{"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"},"defaultConfiguration":{"level":"warning"}}\]}},"results":\[\]}\]} +{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} From 070aa324774f440586bb52bc194a2be3c847db28 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 18 Jun 2024 12:22:58 +0200 Subject: [PATCH 0862/1483] Fix typo --- tools/gnatcov/instrument-setup_config.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index 46b29b831..96674dcb9 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -382,7 +382,7 @@ package body Instrument.Setup_Config is begin if not Parsed_JSON.Success then Outputs.Fatal_Error - ("Parsing errror while reading the instrumentation configuration" + ("Parsing error while reading the instrumentation configuration" & " file."); end if; Config_JSON := Parsed_JSON.Value; From bafc5e03800fde32de86aa31fa5211e384e3109c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 18 Jun 2024 12:23:07 +0200 Subject: [PATCH 0863/1483] Load instrumentation config in Compiler_Wrappers.Gcc This is to enable the verbose output and to display the gnatcov gcc-wrapper command run. --- tools/gnatcov/compiler_wrappers-gcc.adb | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 37ef99f83..13a574d08 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -41,6 +41,10 @@ procedure Compiler_Wrappers.Gcc is Gnatcov_Exec : constant String := "gnatcov" & GNAT.OS_Lib.Get_Executable_Suffix.all; Args : String_Vectors.Vector; + + -- Load the configuration to enable verbose output if required + + Dummy : Instrumentation_Config := Load_Config (Config_Filename); begin Args.Append (+"gcc-wrapper"); Args.Append (+Config_Filename); From 11a0bb5836fdef0d089a489f7e7ed4c99080ca4a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 18 Jun 2024 12:24:15 +0200 Subject: [PATCH 0864/1483] Ignore link commands producing shared libraries We only need to analyze and generate additional code for mains, so skip link commands that yield shared objects / libraries. --- tools/gnatcov/instrument-gcc_wrapper.adb | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 8a96adb2e..4893e5a4f 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -516,6 +516,19 @@ is Result.Target := Create_Normalized ("a.out"); end if; + -- We are only interested in link commands yielding an executable, + -- ignore all others. Use the output name as an heuristic. + + declare + Target : constant String := +Result.Target.Base_Name; + begin + if Ends_With (+Target, ".so") + or else Ends_With (+Target, ".o") + then + return No_Link_Command; + end if; + end; + return Result; end Parse_Link_Command; From d7a0c624d01eb4d3917163c96499cf79291bb4ce Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 18 Jun 2024 12:26:01 +0200 Subject: [PATCH 0865/1483] Integrated instrumentation: support shared libraries When linking against an instrumented shared library, gnatcov now picks up on coverage buffer symbols in the shared library and integrate it to the list of dumped buffers. --- .../shared_lib/Makefile | 12 +++ .../shared_lib/lib/Makefile | 8 ++ .../shared_lib/lib/bar.c | 5 + .../shared_lib/lib/foo.c | 5 + .../shared_lib/main.c | 10 ++ .../shared_lib/test.py | 80 ++++++++++++++ tools/gnatcov/instrument-gcc_wrapper.adb | 102 ++++++++++++++++-- 7 files changed, 212 insertions(+), 10 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/shared_lib/Makefile create mode 100644 testsuite/tests/integrated_instrumentation/shared_lib/lib/Makefile create mode 100644 testsuite/tests/integrated_instrumentation/shared_lib/lib/bar.c create mode 100644 testsuite/tests/integrated_instrumentation/shared_lib/lib/foo.c create mode 100644 testsuite/tests/integrated_instrumentation/shared_lib/main.c create mode 100644 testsuite/tests/integrated_instrumentation/shared_lib/test.py diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/Makefile b/testsuite/tests/integrated_instrumentation/shared_lib/Makefile new file mode 100644 index 000000000..0c83caa56 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/Makefile @@ -0,0 +1,12 @@ +main: main.o lib/libfoobar.so + gcc -o main main.o -Llib/ -lfoobar + +lib/libfoobar.so: + $(MAKE) -C lib + +%.o: %.c + gcc -c $< -o $@ + +clean: + rm -rf main.o + $(MAKE) -C lib clean diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/lib/Makefile b/testsuite/tests/integrated_instrumentation/shared_lib/lib/Makefile new file mode 100644 index 000000000..b17460389 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/lib/Makefile @@ -0,0 +1,8 @@ +libfoobar.so: foo.o bar.o + gcc -shared -o $@ $^ + +%.o: %.c + gcc -c -fpic $< -o $@ + +clean: + rm -f foo.o bar.o libfoobar.so diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/lib/bar.c b/testsuite/tests/integrated_instrumentation/shared_lib/lib/bar.c new file mode 100644 index 000000000..291781351 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/lib/bar.c @@ -0,0 +1,5 @@ +int +bar () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/lib/foo.c b/testsuite/tests/integrated_instrumentation/shared_lib/lib/foo.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/lib/foo.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/main.c b/testsuite/tests/integrated_instrumentation/shared_lib/main.c new file mode 100644 index 000000000..2286f6957 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/main.c @@ -0,0 +1,10 @@ +extern int foo (); +extern int bar (); + +int +main () +{ + foo (); + bar (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/test.py b/testsuite/tests/integrated_instrumentation/shared_lib/test.py new file mode 100644 index 000000000..b2b5da519 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/test.py @@ -0,0 +1,80 @@ +""" +Regression test: when using integrated instrumentation and linking against +and instrumented shared library, gnatcov used not to include coverage buffers +from the shared library, which resulted in the shared library units not being +covered. +""" + +import os +import os.path + +from e3.fs import cp + +from SCOV.minicheck import check_xcov_reports +from SUITE.control import env +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "main.c"), ".") +cp(os.path.join("..", "lib"), ".", recursive=True) + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'lib', 'foo.c')}", + f"--files={os.path.join(cwd, 'lib', 'bar.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Check that when running the build process without LD_LIBRARY_PATH set, +# gnatcov warns that it cannot find the shared library dependency (because it +# relies on ldd, which looks at the LD_LIBRARY_PATH to know the shared library +# location). +cmdrun(["make"], out="make.out", for_pgm=False) +thistest.fail_if( + "warning: Could not find library libfoobar.so. Add its directory to" + " the LD_LIBRARY_PATH if this is an instrumented library." + not in contents_of("make.out"), + "Missing warning in make output", +) + + +# Then, run the build process with LD_LIBRARY_PATH properly set +env.add_search_path( + "LD_LIBRARY_PATH", + os.path.join(cwd, "lib"), +) +cmdrun(["make", "clean"], for_pgm=False) +cmdrun(["make"], for_pgm=False) + + +# Run the executable +cmdrun(["main"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=foo.c.sid", + "--sid=bar.c.sid", + "-axcov", + srctracename_for("main"), + ] +) +check_xcov_reports(".", {"bar.c.xcov": {"+": {4}}, "foo.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 4893e5a4f..7e7af8937 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -20,6 +20,7 @@ with Ada.Containers; use Ada.Containers; with Ada.Containers.Vectors; with Ada.Directories; use Ada.Directories; with Ada.Strings; use Ada.Strings; +with Ada.Strings.Fixed; with Ada.Text_IO; use Ada.Text_IO; with GNATCOLL.VFS; use GNATCOLL.VFS; @@ -517,7 +518,7 @@ is end if; -- We are only interested in link commands yielding an executable, - -- ignore all others. Use the output name as an heuristic. + -- ignore all others. Use the output name as a heuristic. declare Target : constant String := +Result.Target.Base_Name; @@ -934,8 +935,8 @@ begin -- list compilation unit generated below overwrites the dummy one. if Comp_DB.Link_Command /= No_Link_Command - and then Ada.Directories.Exists - (+Comp_DB.Link_Command.Target.Full_Name) + and then Ada.Directories.Exists + (+Comp_DB.Link_Command.Target.Full_Name) then declare Instrumenter : constant Language_Instrumenter'Class := @@ -945,17 +946,98 @@ begin -- compilable by a C / C++ compiler, which are the languages -- supported by the integrated instrumentation scheme. + Buffer_Symbols : String_Sets.Set; + + procedure Add_Coverage_Buffer_Symbols (Symbol_File : Virtual_File); + -- Add the coverage buffers symbols referenced in the Symbol_File + -- to Buffer_Symbols. + + --------------------------------- + -- Add_Coverage_Buffer_Symbols -- + --------------------------------- + + procedure Add_Coverage_Buffer_Symbols (Symbol_File : Virtual_File) + is + begin + Buffer_Symbols.Union + (Coverage_Buffer_Symbols + (Symbol_File => Symbol_File, + Tmp_Dir => +Prj.Output_Dir, + Compiler_Driver => Compiler_Exec, + Config => Instr_Config)); + end Add_Coverage_Buffer_Symbols; + begin + -- Grab the buffer symbols in the link closure + + Add_Coverage_Buffer_Symbols (Comp_DB.Link_Command.Target); + + -- Get the buffer symbols in the dynamic libraries the executable + -- depends on. + + declare + Args : String_Vectors.Vector; + Ldd_Filename : constant String := + (+Prj.Output_Dir) + / ("ldd_" + & Filename_Slug (+Comp_DB.Link_Command.Target.Full_Name)); + Ldd_File : File_Type; + begin + Args.Append (+(+Comp_DB.Link_Command.Target.Full_Name)); + Run_Command + (Command => +"ldd", + Arguments => Args, + Origin_Command_Name => "compiler wrapper", + Output_File => Ldd_Filename); + + Open (Ldd_File, In_File, Ldd_Filename); + while not End_Of_File (Ldd_File) loop + declare + use Ada.Strings.Fixed; + Line : constant String := Get_Line (Ldd_File); + Arrow_Index : constant Natural := Index (Line, "=>"); + Filename_End : constant Natural := + Index (Line, " ", Line'Last, Going => Backward) - 1; + begin + -- The format of the output of ldd is: + -- (=> ())? + -- + -- We only analyze libraries when the fullname is + -- specified as it is a kernel library otherwise. + + if Arrow_Index /= 0 then + declare + Lib_Filename : constant String := + Line (Arrow_Index + 3 .. Filename_End); + begin + -- If the library is not on the LD_LIBRARY_PATH, + -- it will be displayed as: + -- + -- => not found + + if Line (Arrow_Index + 3 .. Line'Last) = "not found" + then + Outputs.Warn + ("Could not find library " + & Line (Line'First + 1 .. Arrow_Index - 2) + & ". Add its directory to the" + & " LD_LIBRARY_PATH if this is an" + & " instrumented library."); + else + Add_Coverage_Buffer_Symbols + (Create (+Lib_Filename)); + end if; + end; + end if; + end; + end loop; + Close (Ldd_File); + end; + -- Generate the buffers list unit Buffers_List_Unit := - Instrumenter.Emit_Buffers_List_Unit - (Coverage_Buffer_Symbols - (Symbol_File => Comp_DB.Link_Command.Target, - Tmp_Dir => +Prj.Output_Dir, - Compiler_Driver => Compiler_Exec, - Config => Instr_Config), - Prj); + Instrumenter.Emit_Buffers_List_Unit (Buffer_Symbols, Prj); -- Then, re-run the link with the correct buffers list unit From 64c86cb808feed9ef5f2ccaf95848f817182f7ab Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 20 Jun 2024 14:44:42 +0200 Subject: [PATCH 0866/1483] Integrated instrumentation: do not pass the -include switch When compiling instrumented file, we should omit the -include switch as otherwise it will result in reinclusion of the file. --- .../include_switch/glob.h | 3 + .../include_switch/test.c | 5 ++ .../include_switch/test.py | 62 ++++++++++++++++++ tools/gnatcov/instrument-gcc_wrapper.adb | 65 ++++++++++++++++--- 4 files changed, 127 insertions(+), 8 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/include_switch/glob.h create mode 100644 testsuite/tests/integrated_instrumentation/include_switch/test.c create mode 100644 testsuite/tests/integrated_instrumentation/include_switch/test.py diff --git a/testsuite/tests/integrated_instrumentation/include_switch/glob.h b/testsuite/tests/integrated_instrumentation/include_switch/glob.h new file mode 100644 index 000000000..c15b449d6 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/include_switch/glob.h @@ -0,0 +1,3 @@ +// Define a global variable. If this file ends up included multiple time, this +// will yield an error. +int glob = 2; diff --git a/testsuite/tests/integrated_instrumentation/include_switch/test.c b/testsuite/tests/integrated_instrumentation/include_switch/test.c new file mode 100644 index 000000000..a9bce4a14 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/include_switch/test.c @@ -0,0 +1,5 @@ +int +main () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/include_switch/test.py b/testsuite/tests/integrated_instrumentation/include_switch/test.py new file mode 100644 index 000000000..d37055912 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/include_switch/test.py @@ -0,0 +1,62 @@ +""" +Regression test: when the user passed the -include switch to gcc, it was +processed both by gnatcov when instrumenting the file and by gcc when compiling +the instrumented file. This resulted in reincluding the file, which could yield +a compilation error. GNATcov now passes the -fpreprocessed switch to the gcc +invocation, which means it now longer tries to preprocess the instrumented file +(that is already preprocessed). +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources in the temporary directory +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "glob.h"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'test.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, compile and link. Test all the various way of passing a -include file +cmdrun(["gcc", "-include", "glob.h", "test.c", "-o", "test"], for_pgm=False) +cmdrun(["gcc", "--include", "glob.h", "test.c", "-o", "test"], for_pgm=False) +cmdrun(["gcc", "--include=glob.h", "test.c", "-o", "test"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=test.c.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports(".", {"test.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 7e7af8937..488031a77 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -199,6 +199,12 @@ is Args : String_Vectors.Vector); -- Run the wrapped compiler with the given Args + function Remove_Pp_Switches + (Args : String_Vectors.Vector) return String_Vectors.Vector; + -- Remove preprocessing switches that should not be processed multiple + -- times (e.g. at instrumentation time, and at compile time). A noteworthy + -- example is the -include switch. + ---------------- -- Split_Args -- ---------------- @@ -606,6 +612,36 @@ is Origin_Command_Name => "compiler"); end Run_Original_Compiler; + ------------------------ + -- Remove_Pp_Switches -- + ------------------------ + + function Remove_Pp_Switches + (Args : String_Vectors.Vector) return String_Vectors.Vector + is + use String_Vectors; + Result : Vector; + Cur : Cursor := Args.First; + begin + while Has_Element (Cur) loop + declare + Arg : constant Unbounded_String := Element (Cur); + begin + if Starts_With (Arg, "--include=") then + null; + elsif Starts_With (Arg, "-include") + or else Starts_With (Arg, "--include") + then + Cur := Next (Cur); + else + Result.Append (Element (Cur)); + end if; + end; + Cur := Next (Cur); + end loop; + return Result; + end Remove_Pp_Switches; + Compiler_Wrapper_Dir : constant String := Containing_Directory (Config_File); -- Directory that contains the current program @@ -615,7 +651,7 @@ is -- Instrumentation configuration previously generated by the setup step Instr_Dir : Temporary_Directory; - -- Directory holding instrumentation artefacts + -- Directory holding instrumentation artifacts Comp_DB : Compilation_Database; @@ -635,6 +671,9 @@ is Files_Of_Interest : File_Sets.Set; -- List of files of interest + Has_Link_Command : Boolean := False; + -- Indicates whether the compiler driver command creates an executable + -- Start of processing for Compiler_Wrappers.GCC begin @@ -668,6 +707,7 @@ begin -- Parse the compiler driver invocation Comp_DB := Parse_Compiler_Driver_Command (Context, Prj, Instr_Dir, Cargs); + Has_Link_Command := Comp_DB.Link_Command /= No_Link_Command; -- Generate an artificial project description to pass compiler switches and -- default spec / body suffixes. @@ -764,7 +804,7 @@ begin -- closure. We will compute the correct buffers list unit at the second -- link. - if Comp_DB.Link_Command /= No_Link_Command then + if Has_Link_Command then declare Instrumenter : constant Language_Instrumenter'Class := Create_C_Instrumenter @@ -784,11 +824,20 @@ begin declare Output_Dir : constant String := +Prj.Output_Dir; - New_Args : String_Vectors.Vector := Cargs; + New_Args : String_Vectors.Vector; begin + -- Filter out preprocessing switch that should not be passed to the + -- compiler invocation when compiling an instrumented source. + + if Instrumented_Files.Length > 0 then + New_Args := Remove_Pp_Switches (Cargs); + else + New_Args := Cargs; + end if; + New_Args.Prepend ("-I" & Instr_Config.GNATcov_RTS_Include_Dir); - if Comp_DB.Link_Command /= No_Link_Command then + if Has_Link_Command then New_Args.Append (+"-lgnatcov_rts"); New_Args.Prepend ("-L" & Instr_Config.GNATcov_RTS_Object_Dir); end if; @@ -830,7 +879,7 @@ begin -- If this is a link command, add the instrumentation artifacts -- to the compiler driver command - if Comp_DB.Link_Command /= No_Link_Command then + if Has_Link_Command then for Instr_Artifact of Comp_Command.Instrumentation_Sources loop New_Args.Prepend (Instr_Artifact); end loop; @@ -934,9 +983,9 @@ begin -- compiler driver invocation (through New_Args), and the buffers -- list compilation unit generated below overwrites the dummy one. - if Comp_DB.Link_Command /= No_Link_Command - and then Ada.Directories.Exists - (+Comp_DB.Link_Command.Target.Full_Name) + if Has_Link_Command + and then Ada.Directories.Exists + (+Comp_DB.Link_Command.Target.Full_Name) then declare Instrumenter : constant Language_Instrumenter'Class := From cfc9c8b93f3e5e6ab79f6fafb73d9f3d9913572f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 20 Jun 2024 17:16:20 +0200 Subject: [PATCH 0867/1483] C/C++ instrumentation: add support for the -include switch --- doc/gnatcov/src_traces.rst | 8 ++++ .../tests/instr-cov/include_switch/main.c | 8 ++++ .../tests/instr-cov/include_switch/pkg1.h | 7 +++ .../tests/instr-cov/include_switch/pkg2.h | 7 +++ .../tests/instr-cov/include_switch/pkg3.h | 7 +++ .../tests/instr-cov/include_switch/test.opt | 1 + .../tests/instr-cov/include_switch/test.py | 45 +++++++++++++++++++ tools/gnatcov/instrument-common.adb | 11 +++++ tools/gnatcov/instrument-common.ads | 5 ++- 9 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/instr-cov/include_switch/main.c create mode 100644 testsuite/tests/instr-cov/include_switch/pkg1.h create mode 100644 testsuite/tests/instr-cov/include_switch/pkg2.h create mode 100644 testsuite/tests/instr-cov/include_switch/pkg3.h create mode 100644 testsuite/tests/instr-cov/include_switch/test.opt create mode 100644 testsuite/tests/instr-cov/include_switch/test.py diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 566b7be4e..b761251e5 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -575,6 +575,14 @@ coverage violations on all statement obligations associated with expression functions. Explicitly disabling optimization (with ``-O0`` for instance) will resolve this issue. +C/C++ limitations +^^^^^^^^^^^^^^^^^ + +The instrumentation process yields preprocessed versions of the sources. Thus, +it is required to remove any :cmd-option:`-include` switch that is passed to +the compiler invocation, by having a dedicated scenario variable for a coverage +build for instance. + .. _instr-build: Building instrumented components diff --git a/testsuite/tests/instr-cov/include_switch/main.c b/testsuite/tests/instr-cov/include_switch/main.c new file mode 100644 index 000000000..62b0a28be --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/main.c @@ -0,0 +1,8 @@ +int +main () +{ + hello_from_pkg1 (); + hello_from_pkg2 (); + hello_from_pkg3 (); + return 0; +} diff --git a/testsuite/tests/instr-cov/include_switch/pkg1.h b/testsuite/tests/instr-cov/include_switch/pkg1.h new file mode 100644 index 000000000..1c3d1afec --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/pkg1.h @@ -0,0 +1,7 @@ +#include + +void +hello_from_pkg1 () +{ + printf ("Hello from pkg1\n"); +} diff --git a/testsuite/tests/instr-cov/include_switch/pkg2.h b/testsuite/tests/instr-cov/include_switch/pkg2.h new file mode 100644 index 000000000..134cc979f --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/pkg2.h @@ -0,0 +1,7 @@ +#include + +void +hello_from_pkg2 () +{ + printf ("Hello from pkg2\n"); +} diff --git a/testsuite/tests/instr-cov/include_switch/pkg3.h b/testsuite/tests/instr-cov/include_switch/pkg3.h new file mode 100644 index 000000000..68c866da9 --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/pkg3.h @@ -0,0 +1,7 @@ +#include + +void +hello_from_pkg3 () +{ + printf ("Hello from pkg3\n"); +} diff --git a/testsuite/tests/instr-cov/include_switch/test.opt b/testsuite/tests/instr-cov/include_switch/test.opt new file mode 100644 index 000000000..796388e67 --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific behavior diff --git a/testsuite/tests/instr-cov/include_switch/test.py b/testsuite/tests/instr-cov/include_switch/test.py new file mode 100644 index 000000000..9eb4cbe9d --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/test.py @@ -0,0 +1,45 @@ +""" +Check that gnatcov instrument correctly processes `-include` switches which can +alter the preprocessing of the file. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +# Test every possible way for extra safety +c_opts = [ + ["--include=../pkg1.h"], + ["--include", "../pkg2.h"], + ["-include", "../pkg3.h"], +] + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=[".."], mains=["main.c"]), + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=( + ["--c-opts={}".format(",".join(args)) for args in c_opts] + ), + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "xcov", + { + "main.c.xcov": {"+": {4, 5, 6}}, + "pkg1.h.xcov": {"+": {6}}, + "pkg2.h.xcov": {"+": {6}}, + "pkg3.h.xcov": {"+": {6}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 5049339c3..4699194df 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -478,6 +478,10 @@ package body Instrument.Common is Add_Macro_Switches (Options.Builtin_Macros); end if; Add_Macro_Switches (Options.PP_Macros); + for Included of Options.Include_Files loop + Args.Append (+"-include"); + Args.Append (Included); + end loop; end if; -- Add other compiler switches as they may also influence both the @@ -661,6 +665,13 @@ package body Instrument.Common is or else Has_Prefix (A, "-W") then Self.Compiler_Switches.Append (+A); + + elsif Has_Prefix (A, "--include=") then + Self.Include_Files.Append (+A (11 .. A'Last)); + + elsif A in "-include" | "--include" then + Self.Include_Files.Append (Args (I + 1)); + I := I + 1; end if; I := I + 1; end; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index e1077657f..328625994 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -568,6 +568,9 @@ package Instrument.Common is PP_Search_Path : String_Vectors.Vector; -- List of directories to search when looking for an included file + Include_Files : String_Vectors.Vector; + -- Header files passed through a -include switch + Builtin_Macros : Macro_Set; -- Set of predefined macros for the project compiler driver @@ -577,7 +580,7 @@ package Instrument.Common is Compiler_Switches : String_Vectors.Vector; -- List of compiler switches that can influence the file preprocessing. -- The list should be amended alongside our discoveries. It is - -- currently: -std, -fno-exceptions, -fno-rtti, -W* switches. + -- currently: -std, -fno-exceptions, -fno-rtti, and -W* -include. Raw_Switches : String_Vectors.Vector; -- List of switches passed to the compiler driver without filtering From cbeecff3c9c9bf660465f33f56720512d7d904cb Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 21 Jun 2024 10:56:25 +0200 Subject: [PATCH 0868/1483] Fix typo --- testsuite/SUITE/tutils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 3a77d03b4..8a03628e8 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -829,7 +829,7 @@ def cmdrun( p = run_and_log(cmd, timeout=thistest.options.timeout, **kwargs) - # Check for FataError conditions. Minimize the situations where we look + # Check for FatalError conditions. Minimize the situations where we look # into the program's output as this is a central spot. if register_failure and p.status != 0: From e4dfc88f2fd4d7d64d37e57b9823a60df44ca788 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 3 Jul 2024 11:37:41 +0000 Subject: [PATCH 0869/1483] instr-cov/include_switch: fix testcase to work on cross targets --- testsuite/tests/instr-cov/include_switch/main.c | 8 +++++++- testsuite/tests/instr-cov/include_switch/pkg1.h | 6 +++--- testsuite/tests/instr-cov/include_switch/pkg2.h | 6 +++--- testsuite/tests/instr-cov/include_switch/pkg3.h | 6 +++--- testsuite/tests/instr-cov/include_switch/test.py | 2 +- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/testsuite/tests/instr-cov/include_switch/main.c b/testsuite/tests/instr-cov/include_switch/main.c index 62b0a28be..82649a864 100644 --- a/testsuite/tests/instr-cov/include_switch/main.c +++ b/testsuite/tests/instr-cov/include_switch/main.c @@ -1,8 +1,14 @@ int -main () +main (void) { hello_from_pkg1 (); hello_from_pkg2 (); hello_from_pkg3 (); return 0; } + +void +print_msg (const char *msg) +{ + (void *) msg; +} diff --git a/testsuite/tests/instr-cov/include_switch/pkg1.h b/testsuite/tests/instr-cov/include_switch/pkg1.h index 1c3d1afec..2ef0ae73c 100644 --- a/testsuite/tests/instr-cov/include_switch/pkg1.h +++ b/testsuite/tests/instr-cov/include_switch/pkg1.h @@ -1,7 +1,7 @@ -#include +extern void print_msg (const char *msg); void -hello_from_pkg1 () +hello_from_pkg1 (void) { - printf ("Hello from pkg1\n"); + print_msg ("Hello from pkg1\n"); } diff --git a/testsuite/tests/instr-cov/include_switch/pkg2.h b/testsuite/tests/instr-cov/include_switch/pkg2.h index 134cc979f..be0316e2c 100644 --- a/testsuite/tests/instr-cov/include_switch/pkg2.h +++ b/testsuite/tests/instr-cov/include_switch/pkg2.h @@ -1,7 +1,7 @@ -#include +extern void print_msg (const char *msg); void -hello_from_pkg2 () +hello_from_pkg2 (void) { - printf ("Hello from pkg2\n"); + print_msg ("Hello from pkg2\n"); } diff --git a/testsuite/tests/instr-cov/include_switch/pkg3.h b/testsuite/tests/instr-cov/include_switch/pkg3.h index 68c866da9..1e228d9a1 100644 --- a/testsuite/tests/instr-cov/include_switch/pkg3.h +++ b/testsuite/tests/instr-cov/include_switch/pkg3.h @@ -1,7 +1,7 @@ -#include +extern void print_msg (const char *msg); void -hello_from_pkg3 () +hello_from_pkg3 (void) { - printf ("Hello from pkg3\n"); + print_msg ("Hello from pkg3\n"); } diff --git a/testsuite/tests/instr-cov/include_switch/test.py b/testsuite/tests/instr-cov/include_switch/test.py index 9eb4cbe9d..4cfb3bc0a 100644 --- a/testsuite/tests/instr-cov/include_switch/test.py +++ b/testsuite/tests/instr-cov/include_switch/test.py @@ -35,7 +35,7 @@ check_xcov_reports( "xcov", { - "main.c.xcov": {"+": {4, 5, 6}}, + "main.c.xcov": {"+": {4, 5, 6, 13}}, "pkg1.h.xcov": {"+": {6}}, "pkg2.h.xcov": {"+": {6}}, "pkg3.h.xcov": {"+": {6}}, From 6ebf747a1a1c18b5c3ac83ddc2348125298a4143 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 19 Jun 2024 15:48:15 +0200 Subject: [PATCH 0870/1483] gnatcov_rts_c-witness.h: use int instead or unsigned for booleans Most relational and equality operators return an int, so change the parameters and return types of witness functions that concern boolean expression from unsigned to int to minimize warnings when -Wsign-conversion is active. --- testsuite/tests/C/mcdc/sign-warn/src/foo.c | 28 ++++++++++++++ testsuite/tests/C/mcdc/sign-warn/src/foo.h | 1 + .../tests/C/mcdc/sign-warn/src/test_foo.c | 37 +++++++++++++++++++ testsuite/tests/C/mcdc/sign-warn/test.py | 20 ++++++++++ tools/gnatcov/rts/gnatcov_rts_c-witness.h | 14 +++---- 5 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 testsuite/tests/C/mcdc/sign-warn/src/foo.c create mode 100644 testsuite/tests/C/mcdc/sign-warn/src/foo.h create mode 100644 testsuite/tests/C/mcdc/sign-warn/src/test_foo.c create mode 100644 testsuite/tests/C/mcdc/sign-warn/test.py diff --git a/testsuite/tests/C/mcdc/sign-warn/src/foo.c b/testsuite/tests/C/mcdc/sign-warn/src/foo.c new file mode 100644 index 000000000..6bfe65c3b --- /dev/null +++ b/testsuite/tests/C/mcdc/sign-warn/src/foo.c @@ -0,0 +1,28 @@ +#include "foo.h" + +#include + +int +do_test (int *x, int *y, int *z) +{ + + // pointer equality ops in condition + if (x == NULL || y == NULL) // # ob + { + + // and in decision + if (z == NULL) // # ob + return 0; // # ob + return *z; // # ob + } + + // Relational ops in conditions + if (*x < 0 && *y < 0) // # ob + return *z; // # ob + + // Relational ops in decision + if (*y < 0) // # ob + return *y; // # ob + + return *z; // # ob +} diff --git a/testsuite/tests/C/mcdc/sign-warn/src/foo.h b/testsuite/tests/C/mcdc/sign-warn/src/foo.h new file mode 100644 index 000000000..78c3f280c --- /dev/null +++ b/testsuite/tests/C/mcdc/sign-warn/src/foo.h @@ -0,0 +1 @@ +int do_test (int *x, int *y, int *z); diff --git a/testsuite/tests/C/mcdc/sign-warn/src/test_foo.c b/testsuite/tests/C/mcdc/sign-warn/src/test_foo.c new file mode 100644 index 000000000..d93dba2d8 --- /dev/null +++ b/testsuite/tests/C/mcdc/sign-warn/src/test_foo.c @@ -0,0 +1,37 @@ +#include "foo.h" + +#include + +int +main () +{ + // Aiming for full coverage + int x, y, z; + + x = 1; + y = 2; + z = 3; + do_test (NULL, NULL, NULL); + do_test (NULL, NULL, &z); + do_test (&x, NULL, NULL); + do_test (&x, &y, &z); + + x = -2; + y = 1; + z = 3; + do_test (&x, &y, &z); + + x = 2; + y = -1; + z = 3; + do_test (&x, &y, &z); + + x = -2; + y = -1; + z = 3; + do_test (&x, &y, &z); +} + +//# foo.c +// +// /ob/ l+ ## 0 diff --git a/testsuite/tests/C/mcdc/sign-warn/test.py b/testsuite/tests/C/mcdc/sign-warn/test.py new file mode 100644 index 000000000..c09b0bab9 --- /dev/null +++ b/testsuite/tests/C/mcdc/sign-warn/test.py @@ -0,0 +1,20 @@ +""" +Test that the introduction of witness function call in the decision expressions +does not generate warnings with -Wsign-conversion, on logical and relational +operators. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +# Run the testcases for decision and mcdc to test all witness_* function +# variants. +# +# Enable warnings as errors to stop the test should we get any warnings, as +# otherwise the output of gprbuild is not checked. +TestCase(extracargs="-Wsign-conversion -Werror", category=CAT.decision).run() +TestCase(extracargs="-Wsign-conversion -Werror", category=CAT.mcdc).run() + +thistest.result() diff --git a/tools/gnatcov/rts/gnatcov_rts_c-witness.h b/tools/gnatcov/rts/gnatcov_rts_c-witness.h index 1943d2186..1193daa25 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-witness.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-witness.h @@ -28,7 +28,7 @@ /* Set the boolean corresponding to BIT to true in BUFFER in various context. */ -static inline unsigned +static inline int gnatcov_rts_witness (unsigned char *buffer, unsigned bit_id) { buffer[bit_id] = 1; @@ -39,9 +39,9 @@ gnatcov_rts_witness (unsigned char *buffer, unsigned bit_id) /* If VALUE is false, set the boolean corresponding to FALSE_BIT to true in BUFFER. Set the one corresponding to TRUE_BIT otherwise. */ -static inline unsigned +static inline int gnatcov_rts_witness_decision (unsigned char *buffer, unsigned false_bit, - unsigned true_bit, unsigned value) + unsigned true_bit, int value) { gnatcov_rts_witness (buffer, value ? true_bit : false_bit); return value; @@ -52,12 +52,12 @@ gnatcov_rts_witness_decision (unsigned char *buffer, unsigned false_bit, MCDC_BUFFER_ADDRESS. Note that MCDC_PATH may not be passed by value, because it is not known until the side effect of the actual for the VALUE formal have been evaluated. */ -static inline unsigned +static inline int gnatcov_rts_witness_decision_mcdc (unsigned char *decision_buffer, unsigned false_bit, unsigned true_bit, unsigned char *mcdc_buffer, unsigned mcdc_base, - unsigned *mcdc_path_address, unsigned value) + unsigned *mcdc_path_address, int value) { unsigned mcdc_path_index = *mcdc_path_address; gnatcov_rts_witness (mcdc_buffer, mcdc_base + mcdc_path_index); @@ -70,10 +70,10 @@ gnatcov_rts_witness_decision_mcdc (unsigned char *decision_buffer, /* MCDC_PATH_ADDRESS is the address of a local variable storing the mcdc_state. If FIRST is true, first reset it to 0. If VALUE is true, add OFFSET_FOR_TRUE. */ -static inline unsigned +static inline int gnatcov_rts_witness_condition (unsigned *mcdc_path_address, unsigned offset_for_true, unsigned first, - unsigned value) + int value) { unsigned *mcdc_path_index = mcdc_path_address; if (first) From 39f7abb340da8aed449e647078b17c6c1edac507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 12 Jul 2024 16:49:55 +0200 Subject: [PATCH 0871/1483] Fix return status of test executable for c sign warning test It used to make the test fail with the 7.1.2 compiler --- testsuite/tests/C/mcdc/sign-warn/src/test_foo.c | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/C/mcdc/sign-warn/src/test_foo.c b/testsuite/tests/C/mcdc/sign-warn/src/test_foo.c index d93dba2d8..adfcd51a7 100644 --- a/testsuite/tests/C/mcdc/sign-warn/src/test_foo.c +++ b/testsuite/tests/C/mcdc/sign-warn/src/test_foo.c @@ -30,6 +30,7 @@ main () y = -1; z = 3; do_test (&x, &y, &z); + return 0; } //# foo.c From 23a84b0f8126450176363092941a030c07c28b01 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 12 Sep 2023 15:21:56 +0200 Subject: [PATCH 0872/1483] Simplify updates for the arch-mix test Clarify the update process in a README.md and add script utilities dedicated to updating the windows-specific artifacts using iod. --- testsuite/tests/U204-026-arch-mix/README.md | 22 ++++++++++++ testsuite/tests/U204-026-arch-mix/update.sh | 26 ++++++++++++++ .../update_arch_mix_windows.sh | 35 +++++++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 testsuite/tests/U204-026-arch-mix/README.md create mode 100755 testsuite/tests/U204-026-arch-mix/update.sh create mode 100755 testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh diff --git a/testsuite/tests/U204-026-arch-mix/README.md b/testsuite/tests/U204-026-arch-mix/README.md new file mode 100644 index 000000000..89e6d3138 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/README.md @@ -0,0 +1,22 @@ +This test checks that "gnatcov coverage" can deal with SID and checkpoint files +produced in various cross-configuration scenarios. + +Since we can't run the test on multiple hosts, we store compilation and trace +artifacts for each host instead of generating them every time the test is rerun. +If the format of these artifacts (traces, checkpoints) changes, the previously +stored format may become incompatible with the newer version of 'gnatcov.' In +such cases, we need to update the test to use artifacts in the newer format. + +Updating the artifacts is necessary for both Windows (native) and Linux (native, +as well as the aarch64-elf and arm-elf targets). To do this, you'll need a +native toolchain for both hosts and a cross toolchain for arm-eabi and +aarch64-elf for Linux, with the instrumentation runtime setup. + +In addition, also install the sshpass utility, available through apt: + +``` +apt install -y sshpass +``` + +Then, to update instrumentation and trace artifacts for all hosts / targets, +run the `update.sh` script. diff --git a/testsuite/tests/U204-026-arch-mix/update.sh b/testsuite/tests/U204-026-arch-mix/update.sh new file mode 100755 index 000000000..3504e16d6 --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/update.sh @@ -0,0 +1,26 @@ +#! /bin/bash + +set -ex + +cwd=$PWD +unamestr=$(uname) +if [ "$unamestr" != "Linux" ] +then + echo "Please run this script from a linux OS" + exit 1 +fi + +# Update the linux artifacts +cd .. +cp -rf U204-026-arch-mix /tmp/ +cd /tmp/U204-026-arch-mix +./gen.sh linux +cd $cwd +cp -rf /tmp/U204-026-arch-mix/* . + +# Then update the windows artifacts +[ ! -d '/tmp/iod-dev' ] && git clone git@ssh.gitlab.adacore-it.com:eng/shared/iod-dev /tmp/iod-dev +/tmp/iod-dev/create-base.py --base-image x86_64-windows-2019 +git_branch=$(git rev-parse --abbrev-ref HEAD) +sshpass ssh iod 'bash -s' < update_arch_mix_windows.sh $git_branch +rsync -av iod:/Users/itmgr/gnatcoverage/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/* gen/x86_64-windows/ diff --git a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh new file mode 100755 index 000000000..67dd4b2ee --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh @@ -0,0 +1,35 @@ +# Update windows artifacts for U204-026-arch-mix + +set -e + +if [ $# -eq 0 ]; then + echo "No arguments provided. Please provide the name of the gnatcov branch" + exit 1 +fi + +# Create a sandbox +cd /Users/itmgr +git clone git@ssh.gitlab.adacore-it.com:eng/cov/gnatcoverage +anod init wave + +# Checkout the right gnatcov branch +cd /Users/itmgr/gnatcoverage +git checkout $1 + +# Build gnatcov +cd /Users/itmgr/wave +anod vcs --add-repo gnatcoverage /Users/itmgr/gnatcoverage +anod build gnatcov --interactive never +eval $(anod printenv gnatcov) +eval $(anod printenv stable-gnatall) + +# Then, retrieve the sources of the arch-mix test +rm -rf /Users/itmgr/gnatcoverage/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows +cp -r /Users/itmgr/gnatcoverage/testsuite/tests/U204-026-arch-mix /cygdrive/c/tmp +cd /cygdrive/c/tmp/U204-026-arch-mix +chmod +x gen.sh +./gen.sh windows + +# Copy back the generated sources +rm -rf +cp -rf /cygdrive/c/tmp/U204-026-arch-mix/ /Users/itmgr/gnatcoverage/testsuite/tests/ From 52161bf25498f522122952444d7572ca0a4932b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Thu, 30 May 2024 07:42:59 +0000 Subject: [PATCH 0873/1483] Trace adapters. Add LLVM_JSON trace adapter --- .../trace_adapters/llvm_json/CMakeLists.txt | 35 ++++ .../gnatcov/trace_adapters/llvm_json/Makefile | 35 ++++ .../trace_adapters/llvm_json/README.md | 30 +++ .../llvm_json/gnatcov_llvm_exporter.gpr | 10 + .../trace_adapters/llvm_json/src/main.cpp | 196 ++++++++++++++++++ 5 files changed, 306 insertions(+) create mode 100644 tools/gnatcov/trace_adapters/llvm_json/CMakeLists.txt create mode 100644 tools/gnatcov/trace_adapters/llvm_json/Makefile create mode 100644 tools/gnatcov/trace_adapters/llvm_json/README.md create mode 100644 tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr create mode 100644 tools/gnatcov/trace_adapters/llvm_json/src/main.cpp diff --git a/tools/gnatcov/trace_adapters/llvm_json/CMakeLists.txt b/tools/gnatcov/trace_adapters/llvm_json/CMakeLists.txt new file mode 100644 index 000000000..a1992221f --- /dev/null +++ b/tools/gnatcov/trace_adapters/llvm_json/CMakeLists.txt @@ -0,0 +1,35 @@ +cmake_minimum_required(VERSION 3.0) +project(gnatcov_llvm_exporter) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +include(CMakePrintHelpers) + +# Find LLVM package +find_package(LLVM REQUIRED CONFIG) + +# Set LLVM include directories +include_directories(${LLVM_INCLUDE_DIRS}) + +# Set LLVM definitions +add_definitions(${LLVM_DEFINITIONS}) +add_definitions("-fno-rtti") + +# Set source files +set(SOURCE_FILES src/main.cpp) + +# Add executable target +add_executable(gnatcov_llvm_exporter ${SOURCE_FILES}) + +# Link LLVM libraries +llvm_map_components_to_libnames( + LLVM_LIBRARIES + demangle + coverage + profiledata + support +) + +# Link LLVM libraries to the executable +target_link_libraries(gnatcov_llvm_exporter ${LLVM_LIBRARIES}) diff --git a/tools/gnatcov/trace_adapters/llvm_json/Makefile b/tools/gnatcov/trace_adapters/llvm_json/Makefile new file mode 100644 index 000000000..944921d45 --- /dev/null +++ b/tools/gnatcov/trace_adapters/llvm_json/Makefile @@ -0,0 +1,35 @@ +LLVM_CXXFLAGS := $(shell llvm-config --cxxflags) +LLVM_LDFLAGS := $(shell llvm-config --ldflags) +LLVM_LIBS := $(shell llvm-config --libs --system-libs) + +# Set this to the right path for you. +LIBSTD_PATH := "$(dir $(shell which gnat))../lib64/" + +GPRBUILD_FLAGS := \ + -cargs:c++ ${LLVM_CXXFLAGS} -g \ + -largs \ + --verbose \ + -fuse-ld=lld \ + -L ${LIBSTD_PATH} \ + ${LLVM_LDFLAGS} \ + ${LLVM_LIBS} + +gprbuild: + @gprbuild -v ${GPRBUILD_FLAGS} + +cmake: + mkdir -p build + cmake \ + -B build \ + -DCMAKE_C_COMPILER=clang \ + -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_CXX_FLAGS="${LLVM_CXXFLAGS}" \ + -DCMAKE_EXE_LINKER_FLAGS="-L ${LIBSTD_PATH}" + cd build && make + +.PHONY: clean + +clean: + gprclean + ${RM} -rf obj + ${RM} -rf build diff --git a/tools/gnatcov/trace_adapters/llvm_json/README.md b/tools/gnatcov/trace_adapters/llvm_json/README.md new file mode 100644 index 000000000..6a746bae6 --- /dev/null +++ b/tools/gnatcov/trace_adapters/llvm_json/README.md @@ -0,0 +1,30 @@ +Note: You'll need an LLVM toolchain installed at `${LLVM_INSTALL}`. + +`${LLVM_INSTALL}/bin/llvm-*` commands should be in the PATH. + +## Anod env setup + +Required anod dependencies : +- `gnatall` +- `stable-libclang` +- `thirdparty-zlib` if the LLVM build from which you will take inputs was + compiled with ZLIB enabled. + +## Build + +It is possible to build this tool with CMake or GPRbuild. + +Both are wrapped in a Makefile to handle environment configuration. + +### Build with GPRBUILD + +You might want to adapt `LIBSTD_PATH` to the path of the `lib64` directory +installed by anod's gnatall. + +### Build with Cmake + +**Minimum required CMake version**: 3.0 + +The purpose of the CMake alternative is to generate a `compile_commands.json` +file that helps LSPs to find declarations. + diff --git a/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr b/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr new file mode 100644 index 000000000..f0a244b36 --- /dev/null +++ b/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr @@ -0,0 +1,10 @@ +project GNATcov_LLVM_exporter is + + for Languages use ("C++"); + + for Source_Dirs use ("src"); + for Main use ("main.cpp"); + + for Object_Dir use "obj"; + +end GNATcov_LLVM_exporter; diff --git a/tools/gnatcov/trace_adapters/llvm_json/src/main.cpp b/tools/gnatcov/trace_adapters/llvm_json/src/main.cpp new file mode 100644 index 000000000..0549865dd --- /dev/null +++ b/tools/gnatcov/trace_adapters/llvm_json/src/main.cpp @@ -0,0 +1,196 @@ +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Demangle/Demangle.h" +#include "llvm/ProfileData/Coverage/CoverageMapping.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/JSON.h" +#include "llvm/Support/VirtualFileSystem.h" +#include +#include +#include + +using namespace llvm; + +enum MCDCState +{ + DontCare = -1, + False = 0, + True = 1, +}; + +std::string +dump_kind (const coverage::CounterMappingRegion ®ion) +{ + switch (region.Kind) + { + case coverage::CounterMappingRegion::CodeRegion: + return "CodeRegion"; + case coverage::CounterMappingRegion::ExpansionRegion: + return "ExpansionRegion"; + case coverage::CounterMappingRegion::SkippedRegion: + return "SkippedRegion"; + case coverage::CounterMappingRegion::GapRegion: + return "GapRegion"; + case coverage::CounterMappingRegion::BranchRegion: + return "BranchRegion"; + case coverage::CounterMappingRegion::MCDCDecisionRegion: + return "MCDCDecisionRegion"; + case coverage::CounterMappingRegion::MCDCBranchRegion: + return "MCDCBranchRegion"; + } +} + +// Create a JSON array starting of a vector of objects. +// F is the conversion function, should be of type `json::Object F(T &)` +template +json::Array +dump_array (const std::vector ®ions, Fct &&fct) +{ + json::Array result; + + std::transform (regions.begin (), regions.end (), + std::back_inserter (result), + std::function (std::forward (fct))); + + return result; +} + +json::Array +dump_location_span (const coverage::CounterMappingRegion &mapping_region) +{ + auto start = mapping_region.startLoc (); + auto end = mapping_region.endLoc (); + return json::Array ({ start.first, start.second, end.first, end.second }); +} + +json::Array +dump_test_vectors (coverage::MCDCRecord &mcdc_record) +{ + json::Array test_vectors; + + for (auto tv_index = 0; tv_index < mcdc_record.getNumTestVectors (); + ++tv_index) + { + json::Array tv_conditions; + for (auto condition_index = 0; + condition_index < mcdc_record.getNumConditions (); + ++condition_index) + { + MCDCState state; + switch (mcdc_record.getTVCondition (tv_index, condition_index)) + { + case coverage::MCDCRecord::MCDC_DontCare: + state = MCDCState::DontCare; + break; + case coverage::MCDCRecord::MCDC_False: + state = MCDCState::False; + break; + case coverage::MCDCRecord::MCDC_True: + state = MCDCState::True; + break; + } + tv_conditions.push_back (static_cast (state)); + } + + auto decision_result = mcdc_record.getTVResult (tv_index); + test_vectors.push_back (json::Object ( + { { "vector", std::move (tv_conditions) }, + { "decision_outcome", static_cast (decision_result) } })); + } + return test_vectors; +} + +json::Object +dump_mcdc_record (const coverage::MCDCRecord &mcdc_record) +{ + return json::Object ( + { { "span", dump_location_span (mcdc_record.getDecisionRegion ()) }, + { "num_conditions", mcdc_record.getNumConditions () }, + { "test_vectors", dump_test_vectors (const_cast ( + mcdc_record)) } }); +} + +json::Object +dump_branch_region (const coverage::CountedRegion ®ion) +{ + return json::Object ({ { "span", dump_location_span (region) }, + { "true_count", region.ExecutionCount }, + { "false_count", region.FalseExecutionCount }, + { "kind", dump_kind (region) } }); +} + +json::Object +dump_code_region (const coverage::CountedRegion ®ion) +{ + return json::Object ({ { "span", dump_location_span (region) }, + { "count", region.ExecutionCount }, + { "kind", dump_kind (region) } }); +} + +json::Object +dump_function (const coverage::FunctionRecord &fct) +{ + return json::Object ( + { { "name", fct.Name }, + { "demangled_name", rustDemangle (std::string_view (fct.Name)) }, + { "mcdc_records", dump_array (fct.MCDCRecords, dump_mcdc_record) }, + { "branch_regions", + dump_array (fct.CountedBranchRegions, dump_branch_region) }, + { "code_regions", dump_array (fct.CountedRegions, dump_code_region) } }); +} + +json::Object +dump_coverage_for_source_file (const coverage::CoverageMapping &coverage, + StringRef sourcefile) +{ + json::Array functions; + + auto fct_iterator = coverage.getCoveredFunctions (sourcefile); + std::transform (fct_iterator.begin (), fct_iterator.end (), + std::back_inserter (functions), dump_function); + + return json::Object ({ { "filename", sourcefile.str () }, + { "functions", std::move (functions) } }); +} + +json::Object +dump_coverage (const coverage::CoverageMapping &coverage) +{ + json::Array file_coverages + = dump_array (coverage.getUniqueSourceFiles (), [&] (StringRef filename) { + return dump_coverage_for_source_file (coverage, filename); + }); + + return json::Object ({ { "data", std::move (file_coverages) } }); +} + +int +main (int argc, const char *argv[]) +{ + cl::opt profdata_filename ( + "instr-prof", cl::Required, cl::desc (".profdata file location")); + cl::opt object_filename (cl::Positional, cl::Required, + cl::desc ("object file location")); + cl::ParseCommandLineOptions (argc, argv, + "GNATcov LLVM profiling data exporting tool"); + + auto FS = vfs::getRealFileSystem (); + + auto coverage_or_err = coverage::CoverageMapping::load ( + { object_filename }, profdata_filename, *FS); + + if (Error e = coverage_or_err.takeError ()) + { + errs () << "Failed to load coverage: " << toString (std::move (e)); + return EXIT_FAILURE; + } + + auto coverage = std::move (coverage_or_err->get ()); + + auto json_export = dump_coverage (*coverage); + + outs () << std::move (json_export); + + return EXIT_SUCCESS; +} From df95d7888b3845722b7d8ba16e5ad11be463499b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 22 Jul 2024 16:33:55 +0200 Subject: [PATCH 0874/1483] instrument-c.adb: minor reformatting --- tools/gnatcov/instrument-c.adb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index f2ba622c7..1b4f45b77 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3948,7 +3948,9 @@ package body Instrument.C is Match (Dump_Pat, Str (Index .. Str'Last), Matches_Dump); Match (Reset_Pat, Str (Index .. Str'Last), Matches_Reset); while Index in Str'Range loop + -- No matches, nothing left to do + exit when Matches_Dump (0) = No_Match and then Matches_Reset (0) = No_Match; @@ -4016,8 +4018,8 @@ package body Instrument.C is -- Search for the next dump indication Match (Dump_Pat, Str (Index .. Str'Last), Matches_Dump); - else + else -- Otherwise we only have a Reset match, or the reset -- indication comes before the next Dump indication. From a37c2403eb562fd3e70a64b860fe3047bf53c6e4 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 22 Jul 2024 18:54:28 +0000 Subject: [PATCH 0875/1483] Instrument.C: fix handling of manual dump/reset indications The current logic to handle both kinds of indication gets stuck in an infinite loop when the two last indications are a dump, then a reset. Rework this area to use a single regular expression to cover both kinds of indication, which simplifies the handling loop and avoids the faulty logic. --- .../tests/instr-cov/312-dump-reset/main.c | 15 +++ .../instr-cov/312-dump-reset/stub_stdio.c | 5 + .../tests/instr-cov/312-dump-reset/test.opt | 1 + .../tests/instr-cov/312-dump-reset/test.py | 26 +++++ tools/gnatcov/instrument-c.adb | 103 ++++++++---------- 5 files changed, 94 insertions(+), 56 deletions(-) create mode 100644 testsuite/tests/instr-cov/312-dump-reset/main.c create mode 100644 testsuite/tests/instr-cov/312-dump-reset/stub_stdio.c create mode 100644 testsuite/tests/instr-cov/312-dump-reset/test.opt create mode 100644 testsuite/tests/instr-cov/312-dump-reset/test.py diff --git a/testsuite/tests/instr-cov/312-dump-reset/main.c b/testsuite/tests/instr-cov/312-dump-reset/main.c new file mode 100644 index 000000000..d0e13e11e --- /dev/null +++ b/testsuite/tests/instr-cov/312-dump-reset/main.c @@ -0,0 +1,15 @@ +extern void stub_puts (const char *); + +int +main (void) +{ + stub_puts ("This should be covered in first dump"); + + /* GNATCOV_DUMP_BUFFERS */ + + /* GNATCOV_RESET_BUFFERS */ + + stub_puts ("This should be covered in second dump"); + + return 0; +} diff --git a/testsuite/tests/instr-cov/312-dump-reset/stub_stdio.c b/testsuite/tests/instr-cov/312-dump-reset/stub_stdio.c new file mode 100644 index 000000000..3c540e6f9 --- /dev/null +++ b/testsuite/tests/instr-cov/312-dump-reset/stub_stdio.c @@ -0,0 +1,5 @@ +void +stub_puts (const char *s) +{ + (void) s; +} diff --git a/testsuite/tests/instr-cov/312-dump-reset/test.opt b/testsuite/tests/instr-cov/312-dump-reset/test.opt new file mode 100644 index 000000000..1c9ab5c59 --- /dev/null +++ b/testsuite/tests/instr-cov/312-dump-reset/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Test specific to src trace feature diff --git a/testsuite/tests/instr-cov/312-dump-reset/test.py b/testsuite/tests/instr-cov/312-dump-reset/test.py new file mode 100644 index 000000000..b4c0b6cc9 --- /dev/null +++ b/testsuite/tests/instr-cov/312-dump-reset/test.py @@ -0,0 +1,26 @@ +""" +Regression testcase: for a C/C++ source that contains a manual dump directive +followed by a reset directive, "gnatcov instrument" used to get stuck in an +infinite loop. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(srcdirs=[".."], mains=["main.c"]), units=["main.c"] + ), + covlevel="stmt", + mains=["main"], + dump_trigger="manual", + manual_prj_name="gen", + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports("xcov", {"main.c.xcov": {"+": {6}, "-": {12, 14}}}) +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 1b4f45b77..5189c0f61 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -68,6 +68,23 @@ package body Instrument.C is is (SCOs.SCO_Unit_Table.Table (SCOs.SCO_Unit_Table.Last).File_Index); -- Return the source file for the last low-level SCO that was created + Buffer_Command_Pattern : constant Pattern_Matcher := + Compile + ("^[\t ]*\/\* (?:" + & "(GNATCOV_DUMP_BUFFERS (?:\((.+)\))?)" + & "|(GNATCOV_RESET_BUFFERS)" + & ") ?\*\/[ \t]*", + Flags => Multiple_Lines); + -- Regexp to match a buffer control command in a C/C++ comment. + -- + -- Group 1: whole "dump" command + -- Group 2: prefix for the source file to create + -- Group 3: whole "reset" command + + Buffer_Dump_Group : constant := 1; + Buffer_Dump_Prefix_Group : constant := 2; + Buffer_Reset_Group : constant := 3; + ------------------------------ -- Preprocessing utilities -- ------------------------------ @@ -3868,16 +3885,7 @@ package body Instrument.C is Options : Analysis_Options; PP_Filename : Unbounded_String; Dummy_Main : Compilation_Unit_Part; - Dump_Pat : constant Pattern_Matcher := - Compile - ("^[\t ]*\/\* GNATCOV_DUMP_BUFFERS (\((.+)\))? ?\*\/[ \t]*", - Flags => Multiple_Lines); - Reset_Pat : constant Pattern_Matcher := - Compile - ("^[\t ]*\/\* GNATCOV_RESET_BUFFERS \*\/[ \t]*", - Flags => Multiple_Lines); - Matches_Dump : Match_Array (0 .. 2); - Matches_Reset : Match_Array (0 .. 0); + Matches : Match_Array (0 .. 4); Dump_Procedure : constant String := Dump_Procedure_Symbol (Main => Dummy_Main, Manual => True, Prj_Name => Prj.Prj_Name); @@ -3945,14 +3953,11 @@ package body Instrument.C is begin Has_Dump_Indication := False; Has_Reset_Indication := False; - Match (Dump_Pat, Str (Index .. Str'Last), Matches_Dump); - Match (Reset_Pat, Str (Index .. Str'Last), Matches_Reset); - while Index in Str'Range loop - -- No matches, nothing left to do + -- Iterate on all matches for the command pattern found in Str - exit when Matches_Dump (0) = No_Match - and then Matches_Reset (0) = No_Match; + Match (Buffer_Command_Pattern, Str (Index .. Str'Last), Matches); + while Index in Str'Range and then Matches (0) /= No_Match loop -- Open the output file if this is the first match we find, -- then forward the source code that appear before the match @@ -3977,67 +3982,53 @@ package body Instrument.C is (S, Extern_Prefix & "void " & Reset_Procedure & "(void);"); end if; - -- If we only have a Dump match, or it is the first of the two - -- to match, insert a dump buffer procedure call in place of - -- the match. + -- Forward whatever comes since the last match (or the + -- beginning of the file, if this is the first match) and this + -- match. - if Matches_Reset (0) = No_Match - or else Matches_Reset (0).First > Matches_Dump (0).First - then + String'Write (S, Str (Index .. Matches (0).First)); + + -- Now insert the substitution for the command we found + if Matches (Buffer_Dump_Group) /= No_Match then if Switches.Misc_Trace.Is_Active then Switches.Misc_Trace.Trace ("Found buffer dump indication in file " & (+Source.File.Base_Name)); end if; - Has_Dump_Indication := True; - String'Write (S, Str (Index .. Matches_Dump (0).First)); - -- If we had a prefix specified in the comment, include it - -- in the dump procedure call. - - if Matches_Dump (1) /= No_Match then - String'Write - (S, Dump_Procedure & "(" - & Str - (Matches_Dump (2).First - .. Matches_Dump (2).Last) - & ");"); - - -- Otherwise use the project name as prefix - - else - String'Write - (S, - Dump_Procedure & "(""" & (To_Ada (Prj.Prj_Name)) - & """);"); - end if; - Index := Matches_Dump (0).Last + 1; - - -- Search for the next dump indication + -- in the dump procedure call. Use the project name as the + -- prefix otherwise. - Match (Dump_Pat, Str (Index .. Str'Last), Matches_Dump); + declare + Prefix : constant String := + (if Matches (Buffer_Dump_Prefix_Group) = No_Match + then """" & To_Ada (Prj.Prj_Name) & """" + else Str (Matches (Buffer_Dump_Prefix_Group).First + .. Matches (Buffer_Dump_Prefix_Group).Last)); + begin + String'Write (S, Dump_Procedure & "(" & Prefix & ");"); + end; + Has_Dump_Indication := True; else - -- Otherwise we only have a Reset match, or the reset - -- indication comes before the next Dump indication. - + pragma Assert (Matches (Buffer_Reset_Group) /= No_Match); if Switches.Misc_Trace.Is_Active then Switches.Misc_Trace.Trace ("Found buffer reset indication in file " & (+Source.File.Base_Name)); end if; - Has_Reset_Indication := True; - String'Write (S, Str (Index .. Matches_Reset (0).First)); String'Write (S, Reset_Procedure & "();"); - Index := Matches_Reset (0).Last + 1; + Has_Reset_Indication := True; + end if; - -- Search for the next reset indication + -- Search for the next dump indication - Match (Reset_Pat, Str (Index .. Str'Last), Matches_Reset); - end if; + Index := Matches (0).Last + 1; + Match + (Buffer_Command_Pattern, Str (Index .. Str'Last), Matches); end loop; -- If we had a manual indication, and thus wrote a modified source From c2de3cb704734d6a2c6bb7764327ae5e12e3e8fb Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 22 Jul 2024 19:08:11 +0000 Subject: [PATCH 0876/1483] Instrument.C: fix an off-by-one error in comment substitution --- .../instr-cov/c-manual-unindented/main.c | 11 ++++++++ .../c-manual-unindented/stub_stdio.c | 5 ++++ .../instr-cov/c-manual-unindented/test.opt | 1 + .../instr-cov/c-manual-unindented/test.py | 28 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 4 +-- 5 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/instr-cov/c-manual-unindented/main.c create mode 100644 testsuite/tests/instr-cov/c-manual-unindented/stub_stdio.c create mode 100644 testsuite/tests/instr-cov/c-manual-unindented/test.opt create mode 100644 testsuite/tests/instr-cov/c-manual-unindented/test.py diff --git a/testsuite/tests/instr-cov/c-manual-unindented/main.c b/testsuite/tests/instr-cov/c-manual-unindented/main.c new file mode 100644 index 000000000..e184255cb --- /dev/null +++ b/testsuite/tests/instr-cov/c-manual-unindented/main.c @@ -0,0 +1,11 @@ +extern void stub_puts (const char *); + +/* clang-format off */ +int +main (void) +{ +stub_puts ("Hello world"); +/* GNATCOV_DUMP_BUFFERS */ +return 0; +} +/* clang-format on */ diff --git a/testsuite/tests/instr-cov/c-manual-unindented/stub_stdio.c b/testsuite/tests/instr-cov/c-manual-unindented/stub_stdio.c new file mode 100644 index 000000000..3c540e6f9 --- /dev/null +++ b/testsuite/tests/instr-cov/c-manual-unindented/stub_stdio.c @@ -0,0 +1,5 @@ +void +stub_puts (const char *s) +{ + (void) s; +} diff --git a/testsuite/tests/instr-cov/c-manual-unindented/test.opt b/testsuite/tests/instr-cov/c-manual-unindented/test.opt new file mode 100644 index 000000000..1c9ab5c59 --- /dev/null +++ b/testsuite/tests/instr-cov/c-manual-unindented/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Test specific to src trace feature diff --git a/testsuite/tests/instr-cov/c-manual-unindented/test.py b/testsuite/tests/instr-cov/c-manual-unindented/test.py new file mode 100644 index 000000000..18f468f94 --- /dev/null +++ b/testsuite/tests/instr-cov/c-manual-unindented/test.py @@ -0,0 +1,28 @@ +""" +Regression testcase: unindented manual dump/reset directives used to be +incorrectly replaced in instrumented sources due to an off-by-one bug (the +comment opening character used to survive the instrumentation while the rest of +the comment was removed). +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") +build_run_and_coverage( + gprsw=GPRswitches( + gprfor(srcdirs=[".."], mains=["main.c"]), units=["main.c"] + ), + covlevel="stmt", + mains=["main"], + dump_trigger="manual", + manual_prj_name="gen", + extra_coverage_args=["-axcov", "--output-dir=xcov"], + extra_instr_args=["--save-temps"], +) +check_xcov_reports("xcov", {"main.c.xcov": {"+": {7}, "-": {9}}}) +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 5189c0f61..b96677fd0 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3982,11 +3982,11 @@ package body Instrument.C is (S, Extern_Prefix & "void " & Reset_Procedure & "(void);"); end if; - -- Forward whatever comes since the last match (or the + -- Forward whatever comes between the last match (or the -- beginning of the file, if this is the first match) and this -- match. - String'Write (S, Str (Index .. Matches (0).First)); + String'Write (S, Str (Index .. Matches (0).First - 1)); -- Now insert the substitution for the command we found From 27466adc19a0cf2ab4cd95609a55d86b74d770be Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 27 Jun 2024 12:19:40 +0200 Subject: [PATCH 0877/1483] Instrument: implement block instrumentation This commit introduces a new --instrument-block switch, to instrument a sequence of statements rather than each statements. The implementation is documented in the design-instrument_block.ads file. --- .../Topologies/And/Pragmas/DebugBody/test.opt | 1 + .../Topologies/Or/Pragmas/DebugBody/test.opt | 2 + .../LocalHandlers/AcrossBlocks/test.opt | 1 + .../LocalHandlers/Raise/test.opt | 4 + .../LocalHandlers/SelectHandler/test.opt | 1 + .../11_Exceptions/Propagation/extra.opt | 1 + testsuite/SCOV/instr.py | 3 + testsuite/SCOV/internals/driver.py | 4 +- testsuite/SUITE/control.py | 8 + testsuite/tests/207-srctrace-version/test.opt | 1 + .../Ada/stmt/K316-021_setjmp-sloc/test.opt | 1 + testsuite/tests/HA16-013_cleanups/test.opt | 1 + .../tests/Ravenscar/Exceptions/extra.opt | 1 + .../stmt/ExceptionHandler/Explicit/test.opt | 3 - .../stmt/ExceptionHandler/Implicit/test.opt | 3 - .../stmt/ExceptionHandler/ReRaise/test.opt | 3 - .../PackageElab/Local/NestedBlock1/test.opt | 3 - .../PackageElab/Local/NestedBlock2/test.opt | 3 - .../PackageElab/Local/SimpleBlock/test.opt | 3 - .../Propagated/LibUnit/Predefined/test.opt | 3 - .../Propagated/LibUnit/UserDefined/test.opt | 3 - .../Propagated/NestedProc/Predefined/test.opt | 3 - .../NestedProc/UserDefined/test.opt | 3 - .../LocallyHandled/ExplicitRaise/test.opt | 3 - .../LocallyHandled/ImplicitRaise/test.opt | 3 - .../Propagated/ExplicitRaise/test.opt | 3 - .../Propagated/ImplicitRaise/test.opt | 3 - .../Exceptions/stmt/example/test.opt | 3 - .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 668 -> 668 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2020 -> 2036 bytes .../gen/arm-elf-linux/gcvrt-bz3791e32c.ads | 3 +- .../gen/arm-elf-linux/gcvrt-bz794ac68b.ads | 3 +- .../gen/arm-elf-linux/gcvrt-bz794ac68c.ads | 3 +- .../gen/arm-elf-linux/gcvrt-db_z794ac68b.adb | 7 +- .../gen/arm-elf-linux/gcvrt-db_z794ac68b.ads | 2 + .../gen/arm-elf-linux/gcvrt-db_z794ac68c.adb | 7 +- .../gen/arm-elf-linux/gcvrt-db_z794ac68c.ads | 2 + .../gen/arm-elf-linux/main_1.sid | Bin 405 -> 409 bytes .../gen/arm-elf-linux/main_2.sid | Bin 405 -> 409 bytes .../gen/arm-elf-linux/pkg.sid | Bin 1048 -> 1056 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1850 -> 1846 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1860 -> 1856 bytes .../U204-026-arch-mix/gen/main_1.srctrace | Bin 416 -> 416 bytes .../U204-026-arch-mix/gen/main_2.srctrace | Bin 388 -> 384 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 1998 -> 1986 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 1929 -> 1922 bytes .../gen/x86_64-windows/gcvrt-bz3791e32c.ads | 3 +- .../gen/x86_64-windows/gcvrt-bz794ac68b.ads | 3 +- .../gen/x86_64-windows/gcvrt-bz794ac68c.ads | 3 +- .../gen/x86_64-windows/gcvrt-db_z794ac68b.adb | 7 +- .../gen/x86_64-windows/gcvrt-db_z794ac68b.ads | 7 +- .../gen/x86_64-windows/gcvrt-db_z794ac68c.adb | 7 +- .../gen/x86_64-windows/gcvrt-db_z794ac68c.ads | 7 +- .../gen/x86_64-windows/main_1.sid | Bin 407 -> 411 bytes .../gen/x86_64-windows/main_2.sid | Bin 407 -> 411 bytes .../gen/x86_64-windows/pkg.sid | Bin 1052 -> 1060 bytes .../tests/U204-026-arch-mix/main_2-out.txt | 14 +- testsuite/tests/U204-026-arch-mix/test.opt | 1 + .../instr-cov/manual-dump/ada_only/test.opt | 1 + .../instr-cov/manual-dump/dotted_prj/test.opt | 1 + testsuite/testsuite.py | 6 + tools/gnatcov/checkpoints.ads | 3 +- tools/gnatcov/command_line.ads | 13 +- tools/gnatcov/coverage-source.adb | 57 ++ tools/gnatcov/design/README.md | 5 + .../gnatcov/design/design-instrument_block.md | 119 +++ tools/gnatcov/files_table.ads | 5 +- tools/gnatcov/instrument-ada_unit.adb | 806 +++++++++++------- tools/gnatcov/instrument-ada_unit.ads | 70 +- tools/gnatcov/instrument-c.adb | 155 +++- tools/gnatcov/instrument-c.ads | 18 +- tools/gnatcov/instrument-common.adb | 23 + tools/gnatcov/instrument-common.ads | 13 + tools/gnatcov/sc_obligations.adb | 71 ++ tools/gnatcov/sc_obligations.ads | 15 + tools/gnatcov/switches.adb | 1 + tools/gnatcov/switches.ads | 3 + 77 files changed, 1143 insertions(+), 395 deletions(-) create mode 100644 testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/test.opt create mode 100644 testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/test.opt create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/test.opt create mode 100644 testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/test.opt create mode 100644 testsuite/tests/207-srctrace-version/test.opt create mode 100644 testsuite/tests/Ravenscar/Exceptions/extra.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.opt delete mode 100644 testsuite/tests/Ravenscar/Exceptions/stmt/example/test.opt create mode 100644 testsuite/tests/instr-cov/manual-dump/ada_only/test.opt create mode 100644 tools/gnatcov/design/README.md create mode 100644 tools/gnatcov/design/design-instrument_block.md diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/test.opt new file mode 100644 index 000000000..21cc3c381 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/And/Pragmas/DebugBody/test.opt @@ -0,0 +1 @@ +block DEAD Test with exceptions breaking the control flow diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/test.opt b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/test.opt new file mode 100644 index 000000000..fee549a96 --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Topologies/Or/Pragmas/DebugBody/test.opt @@ -0,0 +1,2 @@ + +block DEAD Test with exceptions breaking the control flow diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/test.opt new file mode 100644 index 000000000..21cc3c381 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/AcrossBlocks/test.opt @@ -0,0 +1 @@ +block DEAD Test with exceptions breaking the control flow diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/test.opt new file mode 100644 index 000000000..b51b8ff11 --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/Raise/test.opt @@ -0,0 +1,4 @@ +block DEAD Test with exceptions breaking the control flow +RTS_EMBEDDED +RTS_FULL +ALL DEAD diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.opt index 9e44a9266..df47406b3 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/LocalHandlers/SelectHandler/test.opt @@ -1,2 +1,3 @@ RTS_RAVENSCAR,powerpc,7.1.2,bin-traces SKIP !zfp sjlj eh issue fixed post 7.0, K316-021 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 +block DEAD Test with exceptions breaking the control flow diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/extra.opt b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/extra.opt index 3f9983d16..d5f4f5ab9 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/extra.opt +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/Propagation/extra.opt @@ -1,2 +1,3 @@ RTS_ZFP DEAD no support for exception propagation in ZFP runtimes RTS_LIGHT_TASKING DEAD no support for exception propagation in light-tasking runtimes +block DEAD Tests with exceptions breaking the control flow diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index aa026046c..ed050343b 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -133,6 +133,9 @@ def xcov_instrument( if thistest.options.pretty_print: args.append("--pretty-print") + if thistest.options.block: + args.append("--instrument-block") + out = out or "instrument.log" result = xcov( args, diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 8d7d99904..417366c2a 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -950,7 +950,7 @@ def check_expectations(self): # When we're running for a level stricter than the test category # (e.g. running a stmt test with --level=stmt+decision), we # - # * Just ignore some emitted notes, simply irrelevant for the catgory + # * Just ignore some emitted notes, simply irrelevant for the category # (e.g. dT-, which doesn't change the statement coverage status of # the outer statement). This is conveyed by the rp_?notes_for sets. # @@ -963,7 +963,7 @@ def check_expectations(self): # when that happens. # Symbolic strength of each category and context level, to let us - # determine when we're running some test of a given catgeory with a + # determine when we're running some test of a given category with a # stricter --level strength = { diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index 1e5d5c06c..34312dd0b 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -641,3 +641,11 @@ def add_shared_options_to(parser, toplevel): help='Default dump channel to be passed to "gnatcov instrument,"' " unless the test specifically overrides it.", ) + + # --block + parser.add_argument( + "--block", + action="store_true", + help='Pass --block-instrument to "gnatcov instrument",' + " to enable block instrumentation.", + ) diff --git a/testsuite/tests/207-srctrace-version/test.opt b/testsuite/tests/207-srctrace-version/test.opt new file mode 100644 index 000000000..e18554f17 --- /dev/null +++ b/testsuite/tests/207-srctrace-version/test.opt @@ -0,0 +1 @@ +block DEAD Hard-coded SID files diff --git a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.opt b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.opt index 4c1ae3354..cfb29ed49 100644 --- a/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.opt +++ b/testsuite/tests/Ada/stmt/K316-021_setjmp-sloc/test.opt @@ -1 +1,2 @@ RTS_RAVENSCAR,powerpc,7.0.3 SKIP !zfp sjlj eh issue fixed post 7.0, K316-021 +block DEAD Exception breaking the control flow diff --git a/testsuite/tests/HA16-013_cleanups/test.opt b/testsuite/tests/HA16-013_cleanups/test.opt index a413475c5..6ee8973ff 100644 --- a/testsuite/tests/HA16-013_cleanups/test.opt +++ b/testsuite/tests/HA16-013_cleanups/test.opt @@ -1,2 +1,3 @@ RTS_ZFP DEAD test on exception propagation cleanups, zfp-irrelevant RTS_LIGHT_TASKING DEAD test on exception propagation cleanups, light-tasking irrelevant +block DEAD Exception breaking the control flow diff --git a/testsuite/tests/Ravenscar/Exceptions/extra.opt b/testsuite/tests/Ravenscar/Exceptions/extra.opt new file mode 100644 index 000000000..85c5c9990 --- /dev/null +++ b/testsuite/tests/Ravenscar/Exceptions/extra.opt @@ -0,0 +1 @@ +block DEAD Tests with exceptions breaking the control flow diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Explicit/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/Implicit/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/ExceptionHandler/ReRaise/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock1/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/NestedBlock2/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Local/SimpleBlock/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/Predefined/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/LibUnit/UserDefined/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/Predefined/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/PackageElab/Propagated/NestedProc/UserDefined/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ExplicitRaise/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/LocallyHandled/ImplicitRaise/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ExplicitRaise/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/SubProgBody/Propagated/ImplicitRaise/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/Ravenscar/Exceptions/stmt/example/test.opt b/testsuite/tests/Ravenscar/Exceptions/stmt/example/test.opt deleted file mode 100644 index 91ac4985a..000000000 --- a/testsuite/tests/Ravenscar/Exceptions/stmt/example/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -RTS_EMBEDDED -RTS_FULL -ALL DEAD diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index edde38ac124f89f4b3eb758e41abd30945d393e3..ef7beeb1229659140fa7b4044fe9bde594417b85 100644 GIT binary patch delta 73 zcmbQkI)`zQGu+O zKu$~|5ECR!ASNadi2VVGiirutWCenA@B2LGke8D*xxYQn`*GfL?p^)y!$(hA8}GNC zzx+_RR5s?DF-2pHdot&x($e)pWD4&2n)_`(dvovY*6Vjq+s0ghC+W0Ty4Ko~<6G|6 zw(U;Kc3Wwhq@7ipuBPog*OJqcbos%uwfDQW>qu7p-};%;)#oaj8~NkM%kq~gI7x&n z=4SrT0hhsRo+ZA2Tl`fM=MN)r8N3OO5kCgA{)O@{z!CZx-C=&|XADk|Zx76TM_|@J zR{9CJhxk9hGLK&D z2Ddn`1@!1Y9p?i-?{5{{!}(qyp645Mi66or!#{_=fqEfc_B+d7ZnrA%_f>r8SNtKr z)Z2u=iTEQh@8itt;twqO&XoTE{V;wEy@ve3FZq5$=REQcjN1?A8zCR}Z`FQ-F8%C6 z=lmxAKFIysRqy)@%nudnnMV9w)}*CpTBv(%p`|GMIV_e=Z+ dnCG#t=Kmec{!VZnCfVQ=tA3REKT z9zS`#a4It9gE2W{jD0fS7nkDr{AIIXpU>Lg%SX?yZEie$@h~&y44!1Ak*4itx@h^5 z{bgy^SWer^^(?7pYxTxj)|}@$XSF0-ZLQYpS=ww`l2!h{{>*9X>&lr6^T(aj@|Pi; zB*F!AasIFZM{vin#NWIk{-VjxA9`>E_u)M816b?-3jBZIn0|U!HNW&TfD`hKV9j>~ zYyIOu{{**)|Lgp+pQtSLBI^G@*Liqd`pF0WZ}^Mk_qzCt__g1+_;tVALA=)`evGdB zd+%8Kp9Gu>ICd=ORe)p8D+%-}to_#D1pl2t@49&DXDc}G?sb{(koipE68sa^d7F-& zhwMLsJNVaOonOnb_`NRN4f6HiD(9WTTHosuKSa;#`vO|@0WZf{QACi;0pddSoi03iSMK9ytdta zko)&0c;EM6{a)ROa5cWvR}`lpP=jg-JN}0?JClL71sWyvyZb~dY`_+8gG_F zuW{Zrc%6JL@^#@ctnm@7^P0eV|4-nU{9l|d`%CFZzc07p3iU?xqx*Y~uHWx1Sob%< zul)?2U+VP(zt?5HyMcd7K0U8dpdZ3Ik0YmZo{pvd=fM9i;C<(p_ybta^EdO;dWG3P WQ@gak61wt1z|-LVn6||0y#E2h|7p?y diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads index 04a1130a6..19defc245 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads @@ -1,5 +1,4 @@ pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; with System; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; @@ -56,7 +55,7 @@ package Buffers_2 is Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), + Bit_Maps_Fingerprint => (31, 7, 116, 68, 128, 108, 109, 251, 97, 162, 61, 255, 238, 251, 162, 56, 7, 34, 238, 156), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads index 15d7322a1..2ba90de4d 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads @@ -1,5 +1,4 @@ pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; with System; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; @@ -27,7 +26,7 @@ package Buffers_1 is Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), + Bit_Maps_Fingerprint => (14, 208, 170, 79, 214, 204, 239, 198, 105, 130, 182, 250, 66, 192, 111, 106, 70, 106, 188, 135), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads index bf5286f05..a7410a898 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads @@ -1,5 +1,4 @@ pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; with System; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; @@ -27,7 +26,7 @@ package Buffers_1 is Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), + Bit_Maps_Fingerprint => (14, 208, 170, 79, 214, 204, 239, 198, 105, 130, 182, 250, 66, 192, 111, 106, 70, 106, 188, 135), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb index 3309397db..7f9e91472 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.adb @@ -1,15 +1,14 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with GNATcov_RTS.Buffers.Lists; -with Interfaces.C; with GCVRT.Foo; package body GCVRT.DB_z794ac68b is procedure Dump_Buffers is begin - GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GCVRT.Foo.List, - Program_Name => "main_1", + GNATcov_RTS.Traces.Output.Base64.Write_Trace_File + (Buffers_Groups => GCVRT.Foo.List, + Program_Name => "Foo", Exec_Date => 0); end Dump_Buffers; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads index f401c6be8..aa7c96670 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads @@ -2,6 +2,8 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Buffers; package GCVRT.DB_z794ac68b is + pragma No_Tagged_Streams; + procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb index 7c77385e8..7daa5a71a 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.adb @@ -1,15 +1,14 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with GNATcov_RTS.Buffers.Lists; -with Interfaces.C; with GCVRT.Foo; package body GCVRT.DB_z794ac68c is procedure Dump_Buffers is begin - GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GCVRT.Foo.List, - Program_Name => "main_2", + GNATcov_RTS.Traces.Output.Base64.Write_Trace_File + (Buffers_Groups => GCVRT.Foo.List, + Program_Name => "Foo", Exec_Date => 0); end Dump_Buffers; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads index f2304e341..3d79c2f4f 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads @@ -2,6 +2,8 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Buffers; package GCVRT.DB_z794ac68c is + pragma No_Tagged_Streams; + procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index 08b053f72aa5cc89b24134105536b1dcbbb7f59b..7b6ae03aa4e119ac03218c6683215d21066f4626 100644 GIT binary patch delta 56 zcmbQrJd;_(-On*3IloLHIU_YWyC6R^uY`ebqR2uCz6-1Tubp{+EVF6bFQ)_fS#DW- L+8Kag;>j}rT$vXv delta 52 zcmV-40L%ZG1C;|5M@~UhV{djKV`yb#YjAIAZgc<*krbg6^69axwSEd~fr2_!MKm1p Kj}rT$vXv delta 52 zcmV-40L%ZG1C;|5M@~UhV{djKV`yb#YjAIAZgc<*krbg6^69axwSEd~fr2_!MKm1p KcmMzZ delta 57 zcmV-90LK5I2$%>IM@~UhV{djKV`yb#YjAIAZgc<*krd#O_k delta 119 zcmdnSw~J52-On*3IloLHIU_YWyC6R^uY`ejqlgk4&mIN_h8KxW%|B<~I5F9YZG#7p z&%g-8TtJ+kl%=1Wn3)%E2ojM3Vj}}16I}yCT_a-!Lvt%bV=EIA1#JUED+2?N3J`$N E0J=9B?*IS* diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index ed78518649f375d2ec5a6bc0d865fedd7b462763..50d9705065207ebc1916373270caff8045ed876e 100644 GIT binary patch delta 84 zcmV-a0IUDR4!{l+M@~UhV{djKV`yb#YjAIAZgc<+u@u+?0dSM;12F-7vmXQ>0t~tU q004Lw*tTZF49Sy92C|X|AQ3k$F)<)9HaajdIx#XJD=;#XF$WWkrx^wS delta 105 zcmX@WcZ5&G-On*3IloLHIU_YWyC6R^uY`ejqsR?rMvuvFnGG33Hp{cfGx6+WU|^Wx zC-v;->>DR0d$Da|0rD9p|6x;5G1N6ORxmWTGBma_F;&nuFtjo-U2Gw+XOHf{UmbRa*=Eo)Ev#K|_;#UHnb e$g`KYH00#|PF!UB|K0CJ7VJvz=1i_;R0RML1u7u` delta 93 zcmZ3$ynuOv4i_5(14C|NW?sDEL^Ds3PcJvF*;>by-PmLm>S`kM>B;`UKNBb0U>ASf fBC=3=PuItu4mnHO)wFwxjUz rYcv;1@9FyZm2+A@!`3rVGh8Be-^IlUb6RUKEp_mskQcGqor&JvF8zKR>4! cCKQvCpPV>Zn7y1Eq?H+n-SYD%&tW$L0QS=@ng9R* delta 152 zcmX@ae~w?o-On*3IloLHIU_YWyC6R^uY`ejqsRib_-hOd3uZ18xZFvX6D5kPM*MS1OScHE3yCp diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt index f0ad3ba793962d77b5840857d2cc345557a20587..7b310185a0a4ad1822d277ca89ea8cb3766d1f90 100644 GIT binary patch delta 83 zcmeC=Z{inm_j3$M&M#9)&PYwpF38W!D`DWC^CbMXC?y!!-;2pem`g5I5Bw#Tdxq1 f&%g-8Y(Siwn3)%EG&z7>PQ=j4zyKr+0x%i?(|i@7 diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz3791e32c.ads index fe5c16979..c262eccf6 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz3791e32c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz3791e32c.ads @@ -1,5 +1,4 @@ pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; with System; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; @@ -56,7 +55,7 @@ package Buffers_2 is Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Bit_Maps_Fingerprint => (161, 27, 188, 138, 241, 245, 9, 150, 143, 0, 181, 204, 90, 152, 68, 88, 187, 222, 106, 42), + Bit_Maps_Fingerprint => (31, 7, 116, 68, 128, 108, 109, 251, 97, 162, 61, 255, 238, 251, 162, 56, 7, 34, 238, 156), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads index 621358f4b..2d3700afa 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads @@ -1,5 +1,4 @@ pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; with System; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; @@ -27,7 +26,7 @@ package Buffers_1 is Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), + Bit_Maps_Fingerprint => (14, 208, 170, 79, 214, 204, 239, 198, 105, 130, 182, 250, 66, 192, 111, 106, 70, 106, 188, 135), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads index 02173f249..98b03e63a 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads @@ -1,5 +1,4 @@ pragma Style_Checks (Off); pragma Warnings (Off); -with Interfaces.C; use Interfaces.C; with System; with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; @@ -27,7 +26,7 @@ package Buffers_1 is Language => Unit_Based_Language, Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), - Bit_Maps_Fingerprint => (242, 233, 177, 172, 181, 126, 10, 107, 129, 130, 58, 85, 69, 52, 28, 242, 228, 191, 81, 252), + Bit_Maps_Fingerprint => (14, 208, 170, 79, 214, 204, 239, 198, 105, 130, 182, 250, 66, 192, 111, 106, 70, 106, 188, 135), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.adb index adc5226d9..845ba4ae7 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.adb @@ -1,15 +1,14 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with GNATcov_RTS.Buffers.Lists; -with Interfaces.C; with GCVRT.Foo; package body GCVRT.DB_z794ac68b is procedure Dump_Buffers is begin - GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GCVRT.Foo.List, - Program_Name => "main_1", + GNATcov_RTS.Traces.Output.Base64.Write_Trace_File + (Buffers_Groups => GCVRT.Foo.List, + Program_Name => "Foo", Exec_Date => 0); end Dump_Buffers; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.ads index ae6165f07..2528a0247 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68b.ads @@ -3,11 +3,14 @@ with GNATcov_RTS.Buffers; with Ada.Finalization; package GCVRT.DB_z794ac68b is + pragma No_Tagged_Streams; + procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); - type Dump_Controlled_Type is new Ada.Finalization.Controlled with - null record; + type Dump_Controlled_Type is new + Ada.Finalization.Limited_Controlled + with null record; overriding procedure Finalize (Self : in out Dump_Controlled_Type); end GCVRT.DB_z794ac68b; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.adb index 7eb73049e..b05673245 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.adb @@ -1,15 +1,14 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Traces.Output.Base64; with GNATcov_RTS.Buffers.Lists; -with Interfaces.C; with GCVRT.Foo; package body GCVRT.DB_z794ac68c is procedure Dump_Buffers is begin - GNATcov_RTS.Traces.Output.Base64.Write_Trace_File_Wrapper - (GCVRT.Foo.List, - Program_Name => "main_2", + GNATcov_RTS.Traces.Output.Base64.Write_Trace_File + (Buffers_Groups => GCVRT.Foo.List, + Program_Name => "Foo", Exec_Date => 0); end Dump_Buffers; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.ads index 2fd733d04..5b89c6053 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-db_z794ac68c.ads @@ -3,11 +3,14 @@ with GNATcov_RTS.Buffers; with Ada.Finalization; package GCVRT.DB_z794ac68c is + pragma No_Tagged_Streams; + procedure Dump_Buffers; pragma Convention (C, Dump_Buffers); - type Dump_Controlled_Type is new Ada.Finalization.Controlled with - null record; + type Dump_Controlled_Type is new + Ada.Finalization.Limited_Controlled + with null record; overriding procedure Finalize (Self : in out Dump_Controlled_Type); end GCVRT.DB_z794ac68c; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid index 208089dc712e0b5f4b5cafa4ccdcdaa1c98fa859..5de7c2738c22c11a72a90a4de804fdad8d163701 100644 GIT binary patch delta 56 zcmbQvJeyg>-On*3IloLHIU_YWyC6R^uY`ebqR3(iz6-1Tubp{+EVF6bFQ)_fS#DW- L+8Kag;^{L0U9%T7 delta 52 zcmV-40L%ZI1D697M@~UhV{djKV`yb#YjAIAZgc<*krbm8^69axwSEd~fr2_!MKm1p K-On*3IloLHIU_YWyC6R^uY`ebqR3(iz6-1Tubp{+EVF6bFQ)_fS#DW- L+8Kag;^{L0U9%T7 delta 52 zcmV-40L%ZI1D697M@~UhV{djKV`yb#YjAIAZgc<*krbm8^69axwSEd~fr2_!MKm1p KS{CpIl8@!6~^$C`b0JY3o Pm_%5+-fAkdkO7negzOjo diff --git a/testsuite/tests/U204-026-arch-mix/main_2-out.txt b/testsuite/tests/U204-026-arch-mix/main_2-out.txt index d32628f61..3451400b6 100644 --- a/testsuite/tests/U204-026-arch-mix/main_2-out.txt +++ b/testsuite/tests/U204-026-arch-mix/main_2-out.txt @@ -1,11 +1,11 @@ true == GNATcoverage source trace file == -R05BVGNvdiBzb3VyY2UgdHJhY2UgZmlsZQAAAAAAAAACAAAABAAAAAEAAAAGAAAAbWFpbl8yAAACAAAA -CAAAAAAAAAAAAAAAAwAAAAAAAAAAAAAAAAAAAAYAAAABAAAAAAAAAAAAAAAAAQB9GwBxvIzrm759tO6L -X2zG5UjeC/Lpsay1fgprgYI6VUU0HPLkv1H8AAAAAABtYWluXzEAAAAAAAAGAAAAAQAAAAAAAAAAAAAA -AAEA8u0hD3mvaqCR4eIKrxDP3xobG5Ty6bGstX4Ka4GCOlVFNBzy5L9R/AAAAAAAbWFpbl8yAAABAAAA -AwAAAAAAAAAAAAAAAAAAAAACAKyHeINRQaranFeaHiNHYKYOoX3YErzvNm+cLnrwWmfiF3ojV5y5jcIA -AAAAAHBrZwADAAAAAwAAAAIAAAADAAAAAAEAqUhjt6IPXPIu0fM3sFIRPv5MmTChG7yK8fUJlo8Atcxa -mERYu95qKgAAAAAAcGtnAAMAAAACAAAABAAAAA== +R05BVGNvdiBzb3VyY2UgdHJhY2UgZmlsZQAAAAAAAAADAAAABAAAAAEAAAADAAAARm9vAAIAAAAIAAAA +AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAABgAAAAEAAAAAAAAAAAAAAAABAH0bAHG8jOubvn207otfbMbl +SN4LDtCqT9bM78Zpgrb6QsBvakZqvIcAAAAAAG1haW5fMQAAAAAAAAYAAAABAAAAAAAAAAAAAAAAAQDy +7SEPea9qoJHh4gqvEM/fGhsblA7Qqk/WzO/GaYK2+kLAb2pGaryHAAAAAABtYWluXzIAAAEAAAADAAAA +AAAAAAAAAAAAAAAAAAIArId4g1FBqtqcV5oeI0dgpg6hfdgSvO82b5wuevBaZ+IXeiNXnLmNwgAAAAAA +cGtnAAMAAAADAAAAAgAAAAMAAAAAAQCpSGO3og9c8i7R8zewUhE+/kyZMB8HdESAbG37YaI9/+77ojgH +Iu6cAAAAAABwa2cAAwAAAAIAAAAEAAAA == End == diff --git a/testsuite/tests/U204-026-arch-mix/test.opt b/testsuite/tests/U204-026-arch-mix/test.opt index 8c2fc9d10..29bdb5343 100644 --- a/testsuite/tests/U204-026-arch-mix/test.opt +++ b/testsuite/tests/U204-026-arch-mix/test.opt @@ -1,2 +1,3 @@ RTS_ZFP DEAD Native instrumentation not compatible with cross light profiles RTS_LIGHT_TASKING DEAD Native instr not compatible with cross light-tasking profiles +block DEAD Hard-coded instrumented files and SIDs diff --git a/testsuite/tests/instr-cov/manual-dump/ada_only/test.opt b/testsuite/tests/instr-cov/manual-dump/ada_only/test.opt new file mode 100644 index 000000000..df44ecc9c --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/ada_only/test.opt @@ -0,0 +1 @@ +block DEAD Manual dump wrapped in procedure call (unsupported when using block coverage) diff --git a/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.opt b/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.opt index 2998a5c08..df25bcf77 100644 --- a/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.opt +++ b/testsuite/tests/instr-cov/manual-dump/dotted_prj/test.opt @@ -1 +1,2 @@ !native XFAIL Build failure with mixed language mains. See #212 +block DEAD Manual dump wrapped in procedure call (unsupported when using block coverage) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 709454c03..84da16496 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -579,6 +579,9 @@ def set_up(self): f"--default-dump-channel={mopt.default_dump_channel}" ) + if mopt.block: + testcase_cmd.append("--block") + # --gnatcov_ family for pgm, cmd in control.ALTRUN_GNATCOV_PAIRS: @@ -1372,6 +1375,9 @@ def _base_discriminants(self): if self.main.args.all_warnings: result.append("all-warnings") + if self.main.args.block: + result.append("block") + return result def _board_discriminants(self): diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 782930b8f..032d61665 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -39,7 +39,7 @@ with Traces_Source; use Traces_Source; package Checkpoints is - subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 13; + subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 14; -- For compatibility with previous Gnatcov versions, the checkpoint -- file format is versioned. -- @@ -57,6 +57,7 @@ package Checkpoints is -- 11 -- fingerprints for buffer bit maps -- 12 -- Extend Unit_List to distinguish homonym source files -- 13 -- Extend Files_Table.File_Info to distinguish homonym source files + -- 14 -- Extend CU_Info to implement block coverage -- -- Note that we always use the last version when creating a checkpoint. -- diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index bced9ee8c..5bef9a100 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -93,7 +93,8 @@ package Command_Line is Opt_SPARK_Compat, Opt_Full_Slugs, Opt_Relocate_Build_Tree, - Opt_Warnings_As_Errors); + Opt_Warnings_As_Errors, + Opt_Instrument_Block); -- Set of boolean options we support. More complete descriptions below. type String_Options is @@ -616,7 +617,15 @@ package Command_Line is Help => "Treat warnings as errors, i.e. exit with a non-zero" & " status code if a warning is emitted.", Commands => (others => True), - Internal => True)); + Internal => True), + + Opt_Instrument_Block => Create + (Long_Name => "--instrument-block", + Help => "Instrument the statements as blocks, i.e. insert a" + & " single instrumentation counter incrementation for a" + & " statement block.", + Commands => (Cmd_Instrument => True, others => False), + Internal => False)); String_Infos : constant String_Option_Info_Array := (Opt_Project => Create diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 9238fba6d..2b4ffb96b 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -2154,6 +2154,29 @@ package body Coverage.Source is end if; end loop; + -- If there are blocks, discharge all of the blocks statement SCOs + -- when one of them (which actually is the last) is covered. + + declare + Stmt_Blocks : SCO_Id_Vector_Vector renames Blocks (CU); + Block_Index : Positive; + begin + if not Stmt_Blocks.Is_Empty then + Block_Index := Stmt_Blocks.First_Index; + for J in Stmt_Buffer'Range loop + if Stmt_Buffer (J) then + for SCO of Stmt_Blocks.Element (Block_Index) loop + Update_SCI_Wrapper + (SCO => SCO, + Tag => No_SC_Tag, + Process => Set_Executed'Access); + end loop; + end if; + Block_Index := Block_Index + 1; + end loop; + end if; + end; + ST := Scope_Traversal (CU); for J in Decision_Buffer'Range loop if Decision_Buffer (J) then @@ -2459,6 +2482,40 @@ package body Coverage.Source is Tag => No_SC_Tag, Process => Process_SCI'Access); end loop; + + -- If statements were instrumented as blocks, also process the non- + -- instrumented statement SCOs in blocks. + + declare + Stmt_Blocks : SCO_Id_Vector_Vector renames Blocks (CU); + Block_Index : Positive; + begin + if not Stmt_Blocks.Is_Empty then + Block_Index := Stmt_Blocks.First_Index; + + for Bit in Stmt_Bit_Map'Range loop + + -- Assert that the SCO corresponding to the current bit + -- corresponds to the last statement SCO of the current block. + + if Stmt_Blocks.Element (Block_Index).Last_Element + /= Stmt_Bit_Map (Bit) + then + Outputs.Fatal_Error + ("Contents of statement blocks is inconsistent with source" + & " coverage obligations"); + end if; + + for SCO of Stmt_Blocks.Element (Block_Index) loop + Update_SCI + (SCO => SCO, + Tag => No_SC_Tag, + Process => Process_SCI'Access); + end loop; + Block_Index := Block_Index + 1; + end loop; + end if; + end; end Initialize_SCI_For_Instrumented_CU; -------------------------- diff --git a/tools/gnatcov/design/README.md b/tools/gnatcov/design/README.md new file mode 100644 index 000000000..caa90ba8b --- /dev/null +++ b/tools/gnatcov/design/README.md @@ -0,0 +1,5 @@ +# Design documentation of GNATcoverage features + +This directory contains design documentation for the following features: + +* [Block instrumentation through the `--block-instrumentation` switch](design-instrument_block.md). diff --git a/tools/gnatcov/design/design-instrument_block.md b/tools/gnatcov/design/design-instrument_block.md new file mode 100644 index 000000000..1da190ee4 --- /dev/null +++ b/tools/gnatcov/design/design-instrument_block.md @@ -0,0 +1,119 @@ +# Design documentation of block instrumentation + +Block instrumentation (when using the `--instrument-block` instrument switch) +consists in dividing the code in *statement blocks* that execute altogether. +Instead of having a bit and a call setting this bit to monitor the execution of +a statement SCO, gnatcov instruments a block of statements as a whole, resulting +in having one bit and one call for the N statements constitutive of the block. +This makes the instrumented code more efficient by lessening the memory +footprint and the executable size. We deliberately choose to always instrument +the last statement of the block for soundness purposes. Indeed, if the execution +aborts before the end of the block, the tool will report violations over all of +the statements of the block even though some of them may have been covered. + +Uninstrumented code: +```Ada +procedure P is +begin + Put_Line ("Hello"); + Put_Line ("world"); +end P; +``` + +Without --instrument-block: + +```Ada +procedure P is +begin + Witness (Xcov_Stmt_Buffers, 1); + Put_Line ("Hello"); + Witness (Xcov_Stmt_Buffers, 2); + Put_Line ("world"); +end P; +``` + +With --instrument-block: + +```Ada +procedure P is +begin + Put_Line ("Hello"); + Witness (Xcov_Stmt_Buffers, 1); + Put_Line ("world"); +end P; +``` + +The implementation is done at multiple levels: + +## Implementation at the instrumentation step + +First, let's focus on the instrumentation side. The implementation is similar +for Ada, and C/C++. Knowing what is a block requires semantic knowledge of the +code, and specifically knowing what are the control flow entry points (e.g. +labels) and splitting points (e.g. conditional branches). Any code construct +checking one of the two criteria ends the current statement block. Refer to the +End_Statement_Block (ESB) subprogram in Instrument.Ada_Unit and Instrument.C. + +We keep track of the blocks by using a block stack (refer to +Ada\_Unit\_Inst\_Context.Block\_Stack). Block cannot nest in the control flow, +but they can in the source. Let's take a look at the following: + +```Ada +procedure P is -- Start_Statement_Block (SSB), + -- Block_Stack: [B0] + I : Integer := 0; -- SCO#0, {B0: [SCO#0]} + procedure P_Nested is -- SSB, Block_Stack: [B0, B1] + begin + null; -- SCO#1, {B0: [SCO#0], B1: [SCO#1]} + end P_Nested; -- End_Statement_Block (ESB), + -- Block_Stack: [B0] +begin + null; -- SCO#2, {B0: [SCO#0, SCO#2], B1: [SCO#1]} +end P; -- ESB, Block_Stack: [] +``` + +We can see that the declaration and the body of P belong to the same block, +which nests Block 1 (that consists of P\_Nested body). Thus, in addition to the +End\_Statement\_Block subprogram, we introduce a Start\_Statement\_Block (SSB) +to add a new block entry into the stack. We could technically put the +declaration of I and the body of P in different blocks to avoid this kind of +complexity, but as this is a common code occurrence in Ada, it will effectively +hinder the performance impact. + +Then, any control flow statement can end the current statement block, e.g.: + +```Ada +procedure P (B : Boolean) -- SSB, Block_Stack: [B0] +is + I : Integer := 0; -- SCO#0, {B0: [SCO#0]} +begin + if B -- SCO#1, {B0: [SCO#0, SCO#1]}, + -- ESB, Block_Stack: [] + then -- SSB, Block_Stack: [B1] + Put_Line (I'Image); -- SCO#2, {B0: [SCO#0, SCO#1], B1: [SCO#2]} + end if; -- ESB, Block_Stack: [] + -- SSB, Block_Stack: [B2] + I := 2; -- SCO#3, {..., B2: [SCO#3]} +end P; -- ESB, Block_Stack: [] +``` + +As we usually do not know when instrumenting the statement that this is the last +of the block, we defer the statement instrumentation to the next call to the +End\_Statement\_Block subprogram. In the block stack, we thus need to preserve +the information required to properly instrument the last encountered statement +of the block. + +We then save this block information into checkpoints; in the CU_Info.Blocks +record member. + +## Implementation at the coverage step + +On the coverage side, gnatcov loads statement blocks from checkpoints. Refer to +SC_Obligations. + +All the statement SCOs that are in a statement block are considered as coverable +(meaning they will yield coverage results): this is done in +Coverage.Source.Initialize\_SCI\_For\_Instrumented_CU. Every bit in statement +coverage buffers (in the CU\_Info.Bit\_Maps) discharge all the block statement +SCOs (rather than a single statement obligation). Refer to +Coverage.Source.Compute\_Source\_Coverage. diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index fd104f16a..b4fbd5f82 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -224,12 +224,9 @@ package Files_Table is -- Exec from where the address range has been extracted end record; - package SCO_Id_Vectors is new Ada.Containers.Vectors - (Index_Type => Natural, Element_Type => SCO_Id); - type Line_State_Cell is (Cell_1, Cell_2, Cell_3); Coverage_Level_To_Cell : constant - array (Coverage_Level) of Line_State_Cell := + array (Coverage_Level) of Line_State_Cell := (Insn => Cell_1, Branch => Cell_2, Stmt => Cell_1, diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index b9743970a..7521fff47 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -552,15 +552,19 @@ package body Instrument.Ada_Unit is type Statement_Witness_Flavor is (Procedure_Call, Function_Call, Declaration); function Make_Statement_Witness - (UIC : Ada_Unit_Inst_Context; - Bit : Bit_Id; - Flavor : Statement_Witness_Flavor; - In_Generic : Boolean) return Node_Rewriting_Handle; + (UIC : Ada_Unit_Inst_Context; + Bit : Bit_Id; + Flavor : Statement_Witness_Flavor; + In_Generic : Boolean; + In_Decl_Expr : Boolean) return Node_Rewriting_Handle; -- Create a procedure call statement or object declaration to witness -- execution of the low level SCO with the given bit id. -- - -- In_Generic is used to indicate whether the statment witness is destined + -- In_Generic indicates whether the statement witness is destined -- to be inserted in a generic package or subprogram. + -- + -- In_Decl_Expr indicates whether the statement witness is inserted as + -- a declaration in a declare expression. procedure Ensure_With (UIC : in out Ada_Unit_Inst_Context'Class; Unit : Text_Type); @@ -1136,6 +1140,21 @@ package body Instrument.Ada_Unit is -- UIC.Current_Scope_Entity.Parent, if any. Assume that the last generated -- SCO (SCOs.SCO_Table.Last) is the last SCO for the current scope. + procedure Start_Statement_Block (UIC : in out Ada_Unit_Inst_Context); + -- Start a new statement block on top of the currently active block + + procedure End_Statement_Block (UIC : in out Ada_Unit_Inst_Context); + -- End the currently active statement block + + procedure Insert_Stmt_Witness + (UIC : in out Ada_Unit_Inst_Context; + Stmt_Instr_Info : Stmt_Instr_Info_Type; + Bit : Any_Bit_Id); + -- Insert a statement witness call for the given Bit. + -- + -- Stmt_Instr_Info controls the insertion of the witness call. Refer to the + -- definition of Stmt_Instr_Info_Type for more information. + ---------------------------- -- Context miscellaneous -- ---------------------------- @@ -1666,10 +1685,11 @@ package body Instrument.Ada_Unit is ---------------------------- function Make_Statement_Witness - (UIC : Ada_Unit_Inst_Context; - Bit : Bit_Id; - Flavor : Statement_Witness_Flavor; - In_Generic : Boolean) return Node_Rewriting_Handle + (UIC : Ada_Unit_Inst_Context; + Bit : Bit_Id; + Flavor : Statement_Witness_Flavor; + In_Generic : Boolean; + In_Decl_Expr : Boolean) return Node_Rewriting_Handle is Bit_Img : constant String := Img (Bit); E : Instrumentation_Entities renames UIC.Entities; @@ -1685,7 +1705,7 @@ package body Instrument.Ada_Unit is function Decl_Img return String is ("Discard_" & UIC.Instrumented_Unit.Part'Img & Bit_Img - & " :" & (if UIC.In_Decl_Expr then " constant" else "") & " {}." + & " :" & (if In_Decl_Expr then " constant" else "") & " {}." & (if In_Generic and then Switches.SPARK_Compat then "Non_Volatile_" else "") @@ -1866,7 +1886,7 @@ package body Instrument.Ada_Unit is Gen_Names_Prefix : Wide_Wide_String) return Degenerate_Subp_Common_Nodes is RC : Rewriting_Handle renames UIC.Rewriting_Context; - Insert_Info : Insertion_Info renames UIC.Current_Insertion_Info.all; + Insert_Info : Insertion_Info renames UIC.Current_Insertion_Info.Get; begin return Result : Degenerate_Subp_Common_Nodes do Result.N := N; @@ -3082,8 +3102,8 @@ package body Instrument.Ada_Unit is Preelab : Boolean := False; P : Ada_Node := No_Ada_Node; Is_Select_Stmt_Alternative : Boolean := False; - Priv_Part : Private_Part := No_Private_Part) - with Post => UIC.Current_Insertion_Info = UIC'Old.Current_Insertion_Info; + Priv_Part : Private_Part := No_Private_Part; + Is_Block : Boolean := True); -- Process L, a list of statements or declarations. If P is present, it is -- processed as though it had been prepended to L. -- @@ -3098,8 +3118,8 @@ package body Instrument.Ada_Unit is -- If L is the list of declarations for a public part, Priv_Part is the -- corresponding private part (if any). -- - -- The postcondition ensures that the Current_Insertion_Info has been - -- correctly reset to its value upon entry. + -- Is_Block indicates whether the statement list should be considered as + -- a statement block or not. -- The following Traverse_* routines perform appropriate calls to -- Traverse_Declarations_Or_Statements to traverse specific node kinds. @@ -3190,46 +3210,22 @@ package body Instrument.Ada_Unit is -- Traverse_Declarations_Or_Statements -- ----------------------------------------- - type Instrument_Location_Type is - (Before, After, Before_Parent, Inside_Expr); - -- Where to insert the witness call for a statement: - - -- Before: common case, insert immediately before the statement in - -- the same sequence, so that the statement is recorded as having - -- been executed (at least partially), even if it raises an exception. - -- - -- After: special cases where this is not legal (e.g. for the first - -- statement of an alternative in a SELECT statement [except for a DELAY - -- alternative, see below], which has special semantics). In these rare - -- cases, the location indication is set to After to indicate that the - -- witness must be inserted after the statement, not before. - -- - -- Before_Parent: special case of a DELAY or entry call alternative: the - -- evaluation of the delay duration, entry name, or entry call actuals - -- occurs inconditionally as soon as the enclosing SELECT statement is - -- executed, so we insert the witness immediately before the SELECT. - -- - -- Inside_Expr: special cases where we cannot insert a witness call as a - -- statement, or as a declaration (before or after). Such occurrences are - -- elsif statements. In this case, we will insert the witness call inside - -- the underlying boolean expression. - procedure Traverse_Declarations_Or_Statements (UIC : in out Ada_Unit_Inst_Context; L : Ada_List'Class; Preelab : Boolean := False; P : Ada_Node := No_Ada_Node; Is_Select_Stmt_Alternative : Boolean := False; - Priv_Part : Private_Part := No_Private_Part) + Priv_Part : Private_Part := No_Private_Part; + Is_Block : Boolean := True) is - Current_Insertion_Info : aliased Insertion_Info := (Method => None); - procedure Instrument_Statement (UIC : in out Ada_Unit_Inst_Context; N : Ada_Node'Class; Typ : Character; Insertion_N : Node_Rewriting_Handle := No_Node_Rewriting_Handle); - -- Instrument the statement N. + -- Instrument the statement N, or register it into the current block + -- if block instrumentation is active. -- -- Typ is the letter that identifies the type of statement/declaration -- that is being instrumented. @@ -3454,14 +3450,14 @@ package body Instrument.Ada_Unit is -- ... there is no enclosing list to which a witness call -- can be attached. - UIC.Current_Insertion_Info.Method /= None + UIC.Current_Insertion_Info.Get.Method /= None -- ... this is a top-level declaration in a Preelaborate -- package. - and then (UIC.Current_Insertion_Info.Method + and then (UIC.Current_Insertion_Info.Get.Method not in Statement | Declaration - or else not UIC.Current_Insertion_Info.Preelab) + or else not UIC.Current_Insertion_Info.Get.Preelab) -- ... this is a pragma that we know for certain will not -- generate code (such as Annotate or elaboration control @@ -3481,9 +3477,6 @@ package body Instrument.Ada_Unit is declare Bit : Any_Bit_Id; - Insert_Info : constant Insertion_Info_Access := - UIC.Current_Insertion_Info; - LL_SCO_Id : constant Nat := SCOs.SCO_Table.Last; begin -- Create an artificial internal error, if requested @@ -3501,217 +3494,38 @@ package body Instrument.Ada_Unit is return; end if; - -- Allocate a bit in the statement coverage buffer - - Bit := Allocate_Statement_Bit (UIC.Unit_Bits, LL_SCO_Id); - - case Insert_Info.Method is - - when Statement | Declaration => - - if Instrument_Location = Inside_Expr then - declare - Old_Cond : Node_Rewriting_Handle := Actual_Insertion_N; - New_Cond : constant Node_Rewriting_Handle := - Create_Regular_Node - (RC, - Ada_Bin_Op, - Children => - (1 => Make_Statement_Witness - (UIC, - Bit => Bit, - Flavor => Function_Call, - In_Generic => UIC.In_Generic), - - 2 => Make (UIC, Ada_Op_Or_Else), - - -- Placeholder for relocation of old condition - -- after it is detached from the tree. - - 3 => No_Node_Rewriting_Handle)); - - begin - -- Detach old condition from tree and replace it with - -- OR ELSE node. - - Replace (Old_Cond, New_Cond); - - -- Now reattach old condition in new OR ELSE node. If - -- it is AND, OR, XOR, AND THEN binary operation or an - -- IF expression, or a quantified expression (FOR ALL, - -- FOR SOME), we need to wrap it in parens to generate - -- valid code. - - -- Now reattach old condition in the new OR ELSE node. - -- We will wrap it in parens to preserve the semantics - -- of the condition. - -- - -- The two operands of the OR ELSE may not have the - -- same type (Standard.Boolean for the Witness return - -- type). We could convert the result of the witness - -- call to the actual type of the expression, but this - -- requires "withing" the package in which the derived - -- boolean type is defined in case it is not visible. - -- Instead, as this is a top-level boolean expression, - -- we can simply convert the original expression to - -- Standard.Boolean. - - Old_Cond := Create_Call_Expr - (RC, - F_Name => Create_Identifier - (RC, To_Text ("GNATcov_RTS.Std.Boolean")), - F_Suffix => Create_Regular_Node - (RC, - Ada_Assoc_List, - (1 => Create_Param_Assoc - (RC, - F_Designator => No_Node_Rewriting_Handle, - F_R_Expr => Old_Cond)))); - - Set_Child - (New_Cond, Member_Refs.Bin_Op_F_Right, Old_Cond); - end; - - else - declare - Ref_Node : Node_Rewriting_Handle; - Insert_Sibling : Boolean; - Is_Before : Boolean; - Witness_Call : Node_Rewriting_Handle; - begin - -- In the case of an accept_statement containing a - -- sequence of statements, if Instrument_Location - -- is After, we want to call the witness after the - -- entry has been accepted, but before the enclosed - -- statements are executed, so insert the witness - -- call in the inner statement list at first position. - - if Kind (Actual_Insertion_N) - = Ada_Accept_Stmt_With_Stmts - and then Instrument_Location = After - then - Ref_Node := Child - (Actual_Insertion_N, - (Member_Refs.Accept_Stmt_With_Stmts_F_Stmts, - Member_Refs.Handled_Stmts_F_Stmts)); - Insert_Sibling := False; - - else - Ref_Node := Actual_Insertion_N; - Insert_Sibling := True; - - -- Set Is_Before according to the requested - -- insertion mode. - -- - -- Also update Ref_Node so that it is the - -- "reference" node to use for insertion, i.e. the - -- sibling in the target insertion list (Ref_List, - -- below). - -- - -- Note that the witness is inserted at the current - -- location of the statement, so that it will occur - -- immediately *before* it in the instrumented - -- sources. This is necessary because we want to - -- mark a statement as executed anytime it has - -- commenced execution (including in cases it - -- raises an exception or otherwise transfers - -- control). However in some special cases we have - -- to insert after the statement, see the comment - -- for Instrument_Location_Type. - - declare - Ref_List : Node_Rewriting_Handle; - begin - case Instrument_Location is - when Before => - Is_Before := True; - Ref_List := Insert_Info.RH_List; - - when Before_Parent => - Is_Before := True; - Ref_List := Insert_Info.Parent.RH_List; - - when After => - Is_Before := False; - Ref_List := Insert_Info.RH_List; - - -- The cases where we need to instrument - -- inside an expression are handled before, - -- as they do not trigger the insertion of a - -- new statement in a statement list. - - when Inside_Expr => - raise Program_Error; - end case; - - while Parent (Ref_Node) /= Ref_List loop - Ref_Node := Parent (Ref_Node); - end loop; - end; - end if; - - -- Insert witness statement or declaration - - Witness_Call := - Make_Statement_Witness - (UIC, - Bit => Bit, - Flavor => - (case Insert_Info.Method is - when Statement => Procedure_Call, - when Declaration => Declaration, - when Expression_Function | None => - raise Program_Error), - In_Generic => UIC.In_Generic); - - if Insert_Sibling then - if Is_Before then - Insert_Before (Ref_Node, Witness_Call); - else - Insert_After (Ref_Node, Witness_Call); - end if; - else - Insert_First (Ref_Node, Witness_Call); - end if; - end; - end if; - - when Expression_Function => - - -- Create both the witness call and a formal parameter to - -- accept it as an actual. + -- If block instrumentation is enabled, insert a single witness + -- call at the end of the block. This is handled by + -- End_Statement_Block. + if Switches.Instrument_Block then declare - RC : constant Rewriting_Handle := UIC.Rewriting_Context; - - Formal_Name : constant Node_Rewriting_Handle := - Make_Identifier (UIC, "Dummy_Witness_Result"); - Formal_Def_Id : constant Node_Rewriting_Handle := - Create_Regular_Node - (RC, - Ada_Defining_Name_List, - Children => (1 => Create_Defining_Name - (RC, Formal_Name))); + Current_Block : Block_Stacks.Reference_Type renames + UIC.Block_Stack.Reference (UIC.Block_Stack.Last_Index); begin - Insert_Info.Witness_Actual := Make_Statement_Witness - (UIC, - Bit => Bit, - Flavor => Function_Call, - In_Generic => UIC.In_Generic); - - Insert_Info.Witness_Formal := Create_Param_Spec - (RC, - F_Ids => Formal_Def_Id, - F_Has_Aliased => No_Node_Rewriting_Handle, - F_Mode => No_Node_Rewriting_Handle, - F_Type_Expr => Make_Std_Ref (UIC, "Boolean"), - F_Default_Expr => No_Node_Rewriting_Handle, - F_Aspects => No_Node_Rewriting_Handle); + Current_Block.Block.Append (SCO_Id (LL_SCO_Id)); + Current_Block.Last_Stmt_Instr_Info.Insertion_N := + Actual_Insertion_N; + Current_Block.Last_Stmt_Instr_Info.Instrument_Location := + Instrument_Location; + Current_Block.Last_Stmt_Instr_Info.Insert_Info_Ref := + UIC.Current_Insertion_Info; + Current_Block.Last_Stmt_Instr_Info.In_Decl_Expr := + UIC.In_Decl_Expr; + return; end; + end if; - when None => - raise Program_Error; - end case; + Bit := Allocate_Statement_Bit (UIC.Unit_Bits, LL_SCO_Id); + + Insert_Stmt_Witness + (UIC => UIC, + Stmt_Instr_Info => Stmt_Instr_Info_Type' + (Insertion_N => Actual_Insertion_N, + Instrument_Location => Instrument_Location, + Insert_Info_Ref => UIC.Current_Insertion_Info, + In_Decl_Expr => UIC.In_Decl_Expr), + Bit => Bit); end; end if; end Instrument_Statement; @@ -3823,6 +3637,14 @@ package body Instrument.Ada_Unit is return; end; + -- End the statement block if this is a Dump/Reset_Buffers + -- annotation. + + if Result.Kind in Dump_Buffers | Reset_Buffers then + End_Statement_Block (UIC); + Start_Statement_Block (UIC); + end if; + -- Now that the annotation kind is known, validate the remaining -- arguments expected for that kind. @@ -3923,7 +3745,7 @@ package body Instrument.Ada_Unit is -- description of the of transformation we implement in this -- procedure. - Saved_Insertion_Info : constant Insertion_Info_Access := + Saved_Insertion_Info : constant Insertion_Info_Ref := UIC.Current_Insertion_Info; -- Insertion info inherited from the caller, which "points" to the -- degenerate subprogram N. We "save" it because this procedure @@ -3986,12 +3808,12 @@ package body Instrument.Ada_Unit is Local_Inserter : aliased Default_MCDC_State_Inserter; begin - II.RH_List := Stmt_list_RH; II.Preelab := False; - II.Parent := Saved_Insertion_Info; + II.Parent := + Insertion_Info_Access (Saved_Insertion_Info.Unchecked_Get); - UIC.Current_Insertion_Info := II'Unchecked_Access; + Insertion_Info_SP.Set (UIC.Current_Insertion_Info, II); Local_Inserter.Local_Decls := Decl_List; UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; @@ -4142,7 +3964,7 @@ package body Instrument.Ada_Unit is -- Dummy declaration to provide a node before which the -- statement witness will be inserted. - Local_Insertion_Info : aliased Insertion_Info := + Local_Insertion_Info : constant Insertion_Info := (Method => Declaration, RH_List => Decl_List, Preelab => False, @@ -4174,8 +3996,7 @@ package body Instrument.Ada_Unit is Member_Refs.Expr_Function_F_Expr, Create_Paren_Expr (UIC.Rewriting_Context, Decl_Expr)); - UIC.Current_Insertion_Info := - Local_Insertion_Info'Unchecked_Access; + UIC.Current_Insertion_Info.Set (Local_Insertion_Info); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; -- Flag that we are in a declare expression, in order to force @@ -4190,6 +4011,14 @@ package body Instrument.Ada_Unit is -- using the Insertion_N param. Instrument_Statement (UIC, Expr_Func.F_Expr, 'X', Dummy_Decl); + + -- Preemptively end the statement block. We need to end it in + -- the non Ada 2022 case (see the call to End_Statement_Block + -- below), so for consistency, we must end it here as well. + + End_Statement_Block (UIC); + Start_Statement_Block (UIC); + Process_Expression (UIC, Expr_Func.F_Expr, 'X'); -- Restore context @@ -4353,7 +4182,9 @@ package body Instrument.Ada_Unit is -- 2. Statement instrumentation -- ---------------------------------- - UIC.Current_Insertion_Info := New_Insertion_Info'Unchecked_Access; + Insertion_Info_SP.Set + (UIC.Current_Insertion_Info, New_Insertion_Info); + UIC.MCDC_State_Inserter := EF_Inserter'Unchecked_Access; -- Output statement SCO for degenerate subprogram body (null @@ -4368,8 +4199,8 @@ package body Instrument.Ada_Unit is end; else -- Even though there is a "null" keyword in the null procedure, - -- is no dedicated node for it in the Libadalang parse tree: use - -- the whole null procedure declaration to provide a sloc. + -- there is no dedicated node for it in the Libadalang parse tree: + -- use the whole null procedure declaration to provide a sloc. Instrument_Statement (UIC => UIC, @@ -4378,6 +4209,18 @@ package body Instrument.Ada_Unit is Insertion_N => NP_Nodes.Null_Stmt); end if; + -- Preemptively end the block to force the instrumentation of the + -- expression function: we need the insertion info that is filled by + -- Insert_Stmt_Witness (transitively called by End_Statement_Block). + + End_Statement_Block (UIC); + Start_Statement_Block (UIC); + + -- The insertion info has been completed by calls to + -- Insert_Stmt_Witness. + + New_Insertion_Info := UIC.Current_Insertion_Info.Get; + -- Restore saved insertion context UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; @@ -4573,6 +4416,7 @@ package body Instrument.Ada_Unit is (UIC => UIC, Sloc => Sloc (N), Decl => (if Prev_Part.Is_Null then N else Prev_Part)); + Start_Statement_Block (UIC); -- Nothing else to do except for the case of degenerate subprograms -- (null procedures and expression functions). @@ -4589,6 +4433,7 @@ package body Instrument.Ada_Unit is Traverse_Degenerate_Subprogram (N, N_Spec); end if; Exit_Scope (UIC); + End_Statement_Block (UIC); end Traverse_Subp_Decl_Or_Stub; ------------------ @@ -4673,6 +4518,7 @@ package body Instrument.Ada_Unit is if CU_Decl.Kind = Ada_Generic_Package_Decl then UIC.In_Generic := True; end if; + Traverse_Declarations_Or_Statements (UIC, P => CU_Decl.As_Ada_Node, @@ -4802,13 +4648,19 @@ package body Instrument.Ada_Unit is when Ada_Exit_Stmt => Instrument_Statement (UIC, N, 'E'); + End_Statement_Block (UIC); + Start_Statement_Block (UIC); Process_Expression (UIC, As_Exit_Stmt (N).F_Cond_Expr, 'E'); when Ada_Decl_Block | Ada_Begin_Block => if N.Kind = Ada_Decl_Block then + + -- A declaration block does not start a new block + Traverse_Declarations_Or_Statements - (UIC, L => As_Decl_Block (N).F_Decls.F_Decls); + (UIC, L => As_Decl_Block (N).F_Decls.F_Decls, + Is_Block => False); end if; Traverse_Handled_Statement_Sequence @@ -4820,6 +4672,7 @@ package body Instrument.Ada_Unit is when Ada_If_Stmt => Instrument_Statement (UIC, N, 'I'); + End_Statement_Block (UIC); declare If_N : constant If_Stmt := N.As_If_Stmt; @@ -4840,10 +4693,12 @@ package body Instrument.Ada_Unit is Elif : constant Elsif_Stmt_Part := Alt.Child (J).As_Elsif_Stmt_Part; begin + Start_Statement_Block (UIC); Instrument_Statement (UIC, Ada_Node (Elif), 'I', Insertion_N => Handle (Elif.F_Cond_Expr)); + End_Statement_Block (UIC); Process_Expression (UIC, Elif.F_Cond_Expr, 'I'); -- Traverse the statements in the ELSIF @@ -4860,8 +4715,14 @@ package body Instrument.Ada_Unit is L => If_N.F_Else_Stmts.As_Ada_Node_List); end; + -- Start a new statement block for statements after the if + + Start_Statement_Block (UIC); + when Ada_Case_Stmt => Instrument_Statement (UIC, N, 'C'); + End_Statement_Block (UIC); + declare Case_N : constant Case_Stmt := N.As_Case_Stmt; Alt_L : constant Case_Stmt_Alternative_List := @@ -4883,25 +4744,37 @@ package body Instrument.Ada_Unit is end loop; end; + -- Start a new statement sequence for statements after the case + + Start_Statement_Block (UIC); + -- ACCEPT statement when Ada_Accept_Stmt | Ada_Accept_Stmt_With_Stmts => Instrument_Statement (UIC, N, 'A'); + End_Statement_Block (UIC); if N.Kind = Ada_Accept_Stmt_With_Stmts then -- Process sequence of statements + Start_Statement_Block (UIC); Traverse_Handled_Statement_Sequence (UIC, N => N.As_Accept_Stmt_With_Stmts.F_Stmts); + End_Statement_Block (UIC); end if; + -- Open a new statement sequence for statements after the if + + Start_Statement_Block (UIC); + -- SELECT statement -- (all 4 non-terminals: selective_accept, timed_entry_call, -- conditional_entry_call, and asynchronous_select). when Ada_Select_Stmt => Instrument_Statement (UIC, N, 'S'); + End_Statement_Block (UIC); declare Sel_N : constant Select_Stmt := As_Select_Stmt (N); @@ -4938,6 +4811,9 @@ package body Instrument.Ada_Unit is (UIC, L => Sel_N.F_Abort_Stmts.As_Ada_Node_List); end; + -- Open a new statement block for statements after the select + + Start_Statement_Block (UIC); -- There is no SCO for a TERMINATE alternative in instrumentation -- mode, because there is no place to attach a witness. It would @@ -4952,12 +4828,19 @@ package body Instrument.Ada_Unit is | Ada_Requeue_Stmt => Instrument_Statement (UIC, N, ' '); + End_Statement_Block (UIC); + + -- Open a new statement block for statements afterwards + + Start_Statement_Block (UIC); -- Simple return statement. which is an exit point, but we -- have to process the return expression for decisions. when Ada_Return_Stmt => Instrument_Statement (UIC, N, ' '); + End_Statement_Block (UIC); + Start_Statement_Block (UIC); Process_Expression (UIC, N.As_Return_Stmt.F_Return_Expr, 'X'); @@ -4971,8 +4854,10 @@ package body Instrument.Ada_Unit is begin Process_Expression (UIC, ER_N.F_Decl, 'X'); + Start_Statement_Block (UIC); Traverse_Handled_Statement_Sequence (UIC, N => ER_N.F_Stmts); + End_Statement_Block (UIC); end; when Ada_Base_Loop_Stmt => @@ -5023,6 +4908,8 @@ package body Instrument.Ada_Unit is end if; end if; + End_Statement_Block (UIC); + Start_Statement_Block (UIC); Traverse_Declarations_Or_Statements (UIC, L => Loop_S.F_Stmts.As_Ada_Node_List); @@ -5209,6 +5096,10 @@ package body Instrument.Ada_Unit is (if N.Kind in Ada_Generic_Instantiation then 'i' else 'r')); Exit_Scope (UIC); + when Ada_Label => + End_Statement_Block (UIC); + Start_Statement_Block (UIC); + when others => -- Determine required type character code, or ASCII.NUL if @@ -5256,7 +5147,6 @@ package body Instrument.Ada_Unit is | Ada_Task_Body_Stub | Ada_Use_Package_Clause | Ada_Use_Type_Clause - | Ada_Label => Typ := ASCII.NUL; @@ -5271,6 +5161,13 @@ package body Instrument.Ada_Unit is if Typ /= ASCII.NUL then Instrument_Statement (UIC, N, Typ); end if; + + if Is_Select_Stmt_Alternative + and then N.Kind in Ada_Delay_Stmt | Ada_Call_Expr + then + End_Statement_Block (UIC); + Start_Statement_Block (UIC); + end if; end; -- Process any embedded decisions @@ -5279,7 +5176,7 @@ package body Instrument.Ada_Unit is end case; end Traverse_One; - Saved_Insertion_Info : constant Insertion_Info_Access := + Saved_Insertion_Info : constant Insertion_Info_Ref := UIC.Current_Insertion_Info; Items_Count : constant Natural := @@ -5288,9 +5185,14 @@ package body Instrument.Ada_Unit is -- Start of processing for Traverse_Declarations_Or_Statements begin + if Is_Block then + Start_Statement_Block (UIC); + end if; + -- Push new insertion info - UIC.Current_Insertion_Info := Current_Insertion_Info'Unchecked_Access; + Insertion_Info_SP.Set + (UIC.Current_Insertion_Info, Insertion_Info'(Method => None)); -- Process single prefixed node @@ -5310,7 +5212,8 @@ package body Instrument.Ada_Unit is begin II.RH_List := Handle (L); II.Preelab := Preelab; - II.Parent := Saved_Insertion_Info; + II.Parent := + Insertion_Info_Access (Saved_Insertion_Info.Unchecked_Get); if Method = Declaration then II.RH_Private_List := @@ -5319,7 +5222,7 @@ package body Instrument.Ada_Unit is else Handle (Priv_Part.F_Decls)); end if; - Current_Insertion_Info := II; + Insertion_Info_SP.Set (UIC.Current_Insertion_Info, II); end; end if; @@ -5346,6 +5249,10 @@ package body Instrument.Ada_Unit is -- Pop insertion info UIC.Current_Insertion_Info := Saved_Insertion_Info; + + if Is_Block then + End_Statement_Block (UIC); + end if; end Traverse_Declarations_Or_Statements; ----------------------------- @@ -5480,7 +5387,7 @@ package body Instrument.Ada_Unit is end if; Traverse_Declarations_Or_Statements - (UIC, L => N.F_Stmts.As_Ada_Node_List); + (UIC, L => N.F_Stmts.As_Ada_Node_List, Is_Block => False); for J in 1 .. N.F_Exceptions.Children_Count loop declare @@ -5489,9 +5396,11 @@ package body Instrument.Ada_Unit is -- Note: the exceptions list can also contain pragmas if Handler.Kind = Ada_Exception_Handler then + Start_Statement_Block (UIC); Traverse_Declarations_Or_Statements (UIC, L => Handler.As_Exception_Handler.F_Stmts.As_Ada_Node_List); + End_Statement_Block (UIC); end if; end; end loop; @@ -5528,9 +5437,11 @@ package body Instrument.Ada_Unit is Decl => Decl); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; + Start_Statement_Block (UIC); Traverse_Declarations_Or_Statements - (UIC, N.F_Decls.F_Decls, Preelab); + (UIC, N.F_Decls.F_Decls, Preelab, Is_Block => False); Traverse_Handled_Statement_Sequence (UIC, N => N.F_Stmts); + End_Statement_Block (UIC); UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; Exit_Scope (UIC); @@ -5558,16 +5469,19 @@ package body Instrument.Ada_Unit is Decl => N.As_Basic_Decl); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; + Start_Statement_Block (UIC); Traverse_Declarations_Or_Statements (UIC, N.F_Public_Part.F_Decls, Preelab, - Priv_Part => N.F_Private_Part); + Priv_Part => N.F_Private_Part, Is_Block => False); if not N.F_Private_Part.Is_Null then Traverse_Declarations_Or_Statements (UIC, - L => N.F_Private_Part.F_Decls, - Preelab => Preelab); + L => N.F_Private_Part.F_Decls, + Preelab => Preelab, + Is_Block => False); end if; + End_Statement_Block (UIC); UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; Exit_Scope (UIC); UIC.Ghost_Code := False; @@ -5634,15 +5548,18 @@ package body Instrument.Ada_Unit is -- Vis_Decl and Priv_Decl may be Empty at least for empty task type -- declarations. Querying F_Decls is invalid in this case. + Start_Statement_Block (UIC); if not Vis_Decl.Is_Null then Traverse_Declarations_Or_Statements - (UIC, L => Vis_Decl.F_Decls, Priv_Part => Priv_Decl); + (UIC, L => Vis_Decl.F_Decls, Priv_Part => Priv_Decl, + Is_Block => False); end if; if not Priv_Decl.Is_Null then Traverse_Declarations_Or_Statements - (UIC, L => Priv_Decl.F_Decls); + (UIC, L => Priv_Decl.F_Decls, Is_Block => False); end if; + End_Statement_Block (UIC); end Traverse_Sync_Definition; -------------------------------------- @@ -5728,9 +5645,11 @@ package body Instrument.Ada_Unit is Local_Inserter.Local_Decls := Handle (Decls.F_Decls); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; - Traverse_Declarations_Or_Statements (UIC, L => Decls.F_Decls); - + Start_Statement_Block (UIC); + Traverse_Declarations_Or_Statements + (UIC, L => Decls.F_Decls, Is_Block => False); Traverse_Handled_Statement_Sequence (UIC, N => HSS); + End_Statement_Block (UIC); Exit_Scope (UIC); @@ -5753,6 +5672,10 @@ package body Instrument.Ada_Unit is -- instrument each declaration as a statement and process the nested -- expressions. + function Process_Raise_Expr (N : Ada_Node'Class) return Visit_Status; + -- Helper to Libadalang's Traverse. Only operates on Raise_Exprs, + -- ending the current statement block if a raise expression is found. + procedure Process_Decisions (UIC : in out Ada_Unit_Inst_Context; N : Ada_Node'Class; @@ -5764,7 +5687,7 @@ package body Instrument.Ada_Unit is function Process_Decl_Expr (N : Ada_Node'Class) return Visit_Status is begin - if N.Kind in Ada_Decl_Expr then + if N.Kind = Ada_Decl_Expr then declare Saved_Inserter : constant Any_MCDC_State_Inserter := UIC.MCDC_State_Inserter; @@ -5791,6 +5714,20 @@ package body Instrument.Ada_Unit is end if; end Process_Decl_Expr; + ------------------------ + -- Process_Raise_Expr -- + ------------------------ + + function Process_Raise_Expr (N : Ada_Node'Class) return Visit_Status is + begin + if N.Kind = Ada_Raise_Expr then + End_Statement_Block (UIC); + Start_Statement_Block (UIC); + return Over; + end if; + return Into; + end Process_Raise_Expr; + ----------------------- -- Process_Decisions -- ----------------------- @@ -6375,6 +6312,7 @@ package body Instrument.Ada_Unit is end if; Process_Decisions (UIC, N, T); N.Traverse (Process_Decl_Expr'Access); + N.Traverse (Process_Raise_Expr'Access); end Process_Expression; ------------------------- @@ -7011,6 +6949,291 @@ package body Instrument.Ada_Unit is UIC.Current_Scope_Entity := Parent_Scope; end Exit_Scope; + --------------------------- + -- Start_Statement_Block -- + --------------------------- + + procedure Start_Statement_Block (UIC : in out Ada_Unit_Inst_Context) is + begin + if not Switches.Instrument_Block then + return; + end if; + UIC.Block_Stack.Append + (Block_Information' + (Block => SCO_Id_Vectors.Empty_Vector, + others => <>)); + end Start_Statement_Block; + + ------------------------- + -- End_Statement_Block -- + ------------------------- + + procedure End_Statement_Block (UIC : in out Ada_Unit_Inst_Context) + is + Bit : Any_Bit_Id; + begin + if not Switches.Instrument_Block then + return; + end if; + + declare + Current_Block : constant Block_Information := + UIC.Block_Stack.Last_Element; + begin + -- Delete the block if it is empty + + if Current_Block.Block.Is_Empty then + UIC.Block_Stack.Delete_Last; + return; + end if; + + -- Allocate a single statement bit for the last statement (arbitrary) + -- of the block. + + Bit := + Allocate_Statement_Bit + (UIC.Unit_Bits, Nat (Current_Block.Block.Last_Element)); + Insert_Stmt_Witness + (UIC => UIC, + Stmt_Instr_Info => Current_Block.Last_Stmt_Instr_Info, + Bit => Bit); + UIC.Blocks.Append (Current_Block.Block); + end; + UIC.Block_Stack.Delete_Last; + end End_Statement_Block; + + ------------------------- + -- Insert_Stmt_Witness -- + ------------------------- + + procedure Insert_Stmt_Witness + (UIC : in out Ada_Unit_Inst_Context; + Stmt_Instr_Info : Stmt_Instr_Info_Type; + Bit : Any_Bit_Id) + is + RC : Rewriting_Handle renames UIC.Rewriting_Context; + Insertion_N : Node_Rewriting_Handle renames + Stmt_Instr_Info.Insertion_N; + Instrument_Location : Instrument_Location_Type renames + Stmt_Instr_Info.Instrument_Location; + Insert_Info : Insertion_Info renames + Stmt_Instr_Info.Insert_Info_Ref.Get; + begin + -- Create an artificial internal error, if requested + + Raise_Stub_Internal_Error_For (Ada_Instrument_Insert_Stmt_Witness); + + case Insert_Info.Method is + + when Statement | Declaration => + + if Instrument_Location = Inside_Expr then + declare + Old_Cond : Node_Rewriting_Handle := Insertion_N; + New_Cond : constant Node_Rewriting_Handle := + Create_Regular_Node + (RC, + Ada_Bin_Op, + Children => + (1 => Make_Statement_Witness + (UIC, + Bit => Bit, + Flavor => Function_Call, + In_Generic => UIC.In_Generic, + In_Decl_Expr => Stmt_Instr_Info.In_Decl_Expr), + + 2 => Make (UIC, Ada_Op_Or_Else), + + -- Placeholder for relocation of old condition + -- after it is detached from the tree. + + 3 => No_Node_Rewriting_Handle)); + + begin + -- Detach old condition from tree and replace it with + -- OR ELSE node. + + Replace (Old_Cond, New_Cond); + + -- Now reattach old condition in new OR ELSE node. If + -- it is AND, OR, XOR, AND THEN binary operation or an + -- IF expression, or a quantified expression (FOR ALL, + -- FOR SOME), we need to wrap it in parens to generate + -- valid code. + + -- Now reattach old condition in the new OR ELSE node. + -- We will wrap it in parens to preserve the semantics + -- of the condition. + -- + -- The two operands of the OR ELSE may not have the + -- same type (Standard.Boolean for the Witness return + -- type). We could convert the result of the witness + -- call to the actual type of the expression, but this + -- requires "withing" the package in which the derived + -- boolean type is defined in case it is not visible. + -- Instead, as this is a top-level boolean expression, + -- we can simply convert the original expression to + -- Standard.Boolean. + + Old_Cond := Create_Call_Expr + (RC, + F_Name => Create_Identifier + (RC, To_Text ("GNATcov_RTS.Std.Boolean")), + F_Suffix => Create_Regular_Node + (RC, + Ada_Assoc_List, + (1 => Create_Param_Assoc + (RC, + F_Designator => No_Node_Rewriting_Handle, + F_R_Expr => Old_Cond)))); + + Set_Child + (New_Cond, Member_Refs.Bin_Op_F_Right, Old_Cond); + end; + + else + declare + Ref_Node : Node_Rewriting_Handle; + Insert_Sibling : Boolean; + Is_Before : Boolean; + Witness_Call : Node_Rewriting_Handle; + begin + -- In the case of an accept_statement containing a + -- sequence of statements, if Instrument_Location + -- is After, we want to call the witness after the + -- entry has been accepted, but before the enclosed + -- statements are executed, so insert the witness + -- call in the inner statement list at first position. + + if Kind (Insertion_N) = Ada_Accept_Stmt_With_Stmts + and then Instrument_Location = After + then + Ref_Node := Child + (Insertion_N, + (Member_Refs.Accept_Stmt_With_Stmts_F_Stmts, + Member_Refs.Handled_Stmts_F_Stmts)); + Insert_Sibling := False; + + else + Ref_Node := Insertion_N; + Insert_Sibling := True; + + -- Set Is_Before according to the requested + -- insertion mode. + -- + -- Also update Ref_Node so that it is the + -- "reference" node to use for insertion, i.e. the + -- sibling in the target insertion list (Ref_List, + -- below). + -- + -- Note that the witness is inserted at the current + -- location of the statement, so that it will occur + -- immediately *before* it in the instrumented + -- sources. This is necessary because we want to + -- mark a statement as executed anytime it has + -- commenced execution (including in cases it + -- raises an exception or otherwise transfers + -- control). However in some special cases we have + -- to insert after the statement, see the comment + -- for Instrument_Location_Type. + + declare + Ref_List : Node_Rewriting_Handle; + begin + case Instrument_Location is + when Before => + Is_Before := True; + Ref_List := Insert_Info.RH_List; + + when Before_Parent => + Is_Before := True; + Ref_List := Insert_Info.Parent.RH_List; + + when After => + Is_Before := False; + Ref_List := Insert_Info.RH_List; + + -- The cases where we need to instrument + -- inside an expression are handled before, + -- as they do not trigger the insertion of a + -- new statement in a statement list. + + when Inside_Expr => + raise Program_Error; + end case; + + while Parent (Ref_Node) /= Ref_List loop + Ref_Node := Parent (Ref_Node); + end loop; + end; + end if; + + -- Insert witness statement or declaration + + Witness_Call := + Make_Statement_Witness + (UIC, + Bit => Bit, + Flavor => + (case Insert_Info.Method is + when Statement => Procedure_Call, + when Declaration => Declaration, + when Expression_Function | None => + raise Program_Error), + In_Generic => UIC.In_Generic, + In_Decl_Expr => Stmt_Instr_Info.In_Decl_Expr); + + if Insert_Sibling then + if Is_Before then + Insert_Before (Ref_Node, Witness_Call); + else + Insert_After (Ref_Node, Witness_Call); + end if; + else + Insert_First (Ref_Node, Witness_Call); + end if; + end; + end if; + + when Expression_Function => + + -- Create both the witness call and a formal parameter to + -- accept it as an actual. + + declare + RC : constant Rewriting_Handle := UIC.Rewriting_Context; + + Formal_Name : constant Node_Rewriting_Handle := + Make_Identifier (UIC, "Dummy_Witness_Result"); + Formal_Def_Id : constant Node_Rewriting_Handle := + Create_Regular_Node + (RC, + Ada_Defining_Name_List, + Children => + (1 => Create_Defining_Name (RC, Formal_Name))); + begin + Insert_Info.Witness_Actual := Make_Statement_Witness + (UIC, + Bit => Bit, + Flavor => Function_Call, + In_Generic => UIC.In_Generic, + In_Decl_Expr => Stmt_Instr_Info.In_Decl_Expr); + + Insert_Info.Witness_Formal := Create_Param_Spec + (RC, + F_Ids => Formal_Def_Id, + F_Has_Aliased => No_Node_Rewriting_Handle, + F_Mode => No_Node_Rewriting_Handle, + F_Type_Expr => Make_Std_Ref (UIC, "Boolean"), + F_Default_Expr => No_Node_Rewriting_Handle, + F_Aspects => No_Node_Rewriting_Handle); + end; + + when None => + raise Program_Error; + end case; + end Insert_Stmt_Witness; + --------------------- -- Start_Rewriting -- --------------------- @@ -8518,6 +8741,8 @@ package body Instrument.Ada_Unit is UIC.Unit_Bits.Last_Path_Bit := No_Bit_Id; UIC.Unit_Bits.Decision_Bits := LL_Decision_SCO_Bit_Allocs.Empty; UIC.Unit_Bits.Statement_Bits := LL_Statement_SCO_Bit_Allocs.Empty; + UIC.Block_Stack := Block_Stacks.Empty_Vector; + UIC.Blocks := SCO_Id_Vector_Vectors.Empty_Vector; -- Instrumentation of another source file in the same unit may have -- produced non-instrumented low-level SCOs in UIC.Non_Instr_LL_SCOs, @@ -8575,10 +8800,16 @@ package body Instrument.Ada_Unit is Append_Unit (UIC.SFI); Traverse_Declarations_Or_Statements - (UIC => UIC, - L => No_Ada_List, - Preelab => Preelab, - P => Rewriter.Rewritten_Unit.Root); + (UIC => UIC, + L => No_Ada_List, + Preelab => Preelab, + P => Rewriter.Rewritten_Unit.Root, + Is_Block => False); + + -- Check that there are no open statement blocks at the end of the + -- instrumentation processs. + + pragma Assert (UIC.Block_Stack.Is_Empty); -- Convert low level SCOs from the instrumenter to high level SCOs. -- This creates BDDs for every decision. @@ -8719,6 +8950,11 @@ package body Instrument.Ada_Unit is Remap_Scope_Entities (UIC.Scope_Entities, SCO_Map); Set_Scope_Entities (UIC.CU, UIC.Scope_Entities); + + -- Remap low level SCOs in blocks to high level SCOs + + Remap_Blocks (UIC.Blocks, SCO_Map); + Set_Blocks (UIC.CU, UIC.Blocks); end; -- Emit the instrumented source file diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index c39118419..53d54d188 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -29,6 +29,7 @@ with Libadalang.Analysis; use Libadalang.Analysis; with Libadalang.Config_Pragmas; use Libadalang.Config_Pragmas; with Libadalang.Rewriting; use Libadalang.Rewriting; +with GNATCOLL.Refcount; use GNATCOLL.Refcount; with GNATCOLL.VFS; with Files_Handling; use Files_Handling; @@ -237,6 +238,10 @@ private end case; end record; + package Insertion_Info_SP is new Shared_Pointers + (Element_Type => Insertion_Info); + subtype Insertion_Info_Ref is Insertion_Info_SP.Ref; + type Source_Decision is record LL_SCO : Nat; -- Low-level SCO id of decision @@ -320,6 +325,64 @@ private package Generic_Subp_Vectors is new Ada.Containers.Vectors (Natural, Generic_Subp); + type Instrument_Location_Type is + (Before, After, Before_Parent, Inside_Expr); + -- Where to insert the witness call for a statement: + + -- Before: common case, insert immediately before the statement in + -- the same sequence, so that the statement is recorded as having + -- been executed (at least partially), even if it raises an exception. + -- + -- After: special cases where this is not legal (e.g. for the first + -- statement of an alternative in a SELECT statement [except for a DELAY + -- alternative, see below], which has special semantics). In these rare + -- cases, the location indication is set to After to indicate that the + -- witness must be inserted after the statement, not before. + -- + -- Before_Parent: special case of a DELAY or entry call alternative: the + -- evaluation of the delay duration, entry name, or entry call actuals + -- occurs inconditionally as soon as the enclosing SELECT statement is + -- executed, so we insert the witness immediately before the SELECT. + -- + -- Inside_Expr: special cases where we cannot insert a witness call as a + -- statement, or as a declaration (before or after). Such occurrences are + -- elsif statements. In this case, we will insert the witness call inside + -- the underlying boolean expression. + + type Stmt_Instr_Info_Type is record + Insertion_N : Node_Rewriting_Handle; + -- Node for the insertion of the witness call + + Instrument_Location : Instrument_Location_Type; + -- Instrument location controlling the insertion of the witness call. + -- Refer to the type definition of Instrument_Location_Type for more + -- information. + + Insert_Info_Ref : Insertion_Info_Ref; + -- Insertion information controlling the insertion of the witness call. + -- The insertion of the witness call also fills this record when e.g. + -- instrumenting an expression function. Refer to the type definition + -- of Insertion_Info for more information. + + In_Decl_Expr : Boolean; + -- True when this is a declaration in a declare expression + end record; + -- Information relative to the instrumentation of a statement + + type Block_Information is record + Block : SCO_Id_Vectors.Vector; + -- Statement SCOs for the block + + Last_Stmt_Instr_Info : Stmt_Instr_Info_Type; + -- Instrumentation information for the last encountered statement of the + -- block. + + end record; + -- Information relative to a block of statements + + package Block_Stacks is new Ada.Containers.Vectors + (Index_Type => Positive, Element_Type => Block_Information); + type Ada_Unit_Inst_Context is new Instrument.Common.Unit_Inst_Context with record Language_Version_Pragma : Unbounded_Wide_Wide_String; @@ -364,7 +427,7 @@ private MCDC_State_Inserter : Any_MCDC_State_Inserter; -- Service supporting insertion of temporary MC/DC state variables - Current_Insertion_Info : Insertion_Info_Access; + Current_Insertion_Info : Insertion_Info_Ref; -- Insertion_Info for the list being traversed Degenerate_Subprogram_Generics : Generic_Subp_Vectors.Vector; @@ -404,6 +467,11 @@ private -- Used to only insert constant object declarations in the declare -- expression, as non-constant objects are not allowed per -- RM 4.5.9 (5/5). + + Block_Stack : Block_Stacks.Vector; + -- Currently processed blocks (blocks can nest in the source, + -- when e.g. we have a nested subprogram declaration). + end record; function Insert_MCDC_State diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index b96677fd0..fe861c224 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -238,6 +238,14 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context'Class; N : Cursor_T); + overriding procedure Start_Statement_Block + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class); + + overriding procedure End_Statement_Block + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class); + Record_PP_Info_Pass : aliased Record_PP_Info_Pass_Kind; Instrument_Pass : aliased Instrument_Pass_Kind; @@ -977,6 +985,20 @@ package body Instrument.C is UIC.Instrumented_Entities.Insert (From.Source_File, (others => <>)); end if; + -- End the statement block if we entered a new file: we do not want + -- blocks with statements in different files. + + declare + use type SCOs.SCO_Unit_Index; + begin + if SCOs.SCO_Unit_Table.Last /= 0 + and then Last_File /= From.Source_File + then + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); + end if; + end; + Append_SCO (C1, C2, From.L, To.L, From.Source_File, Last, Pragma_Aspect_Name); @@ -1108,6 +1130,40 @@ package body Instrument.C is UIC.Instrumented_CXX_For_Ranges.Append (N); end Register_CXX_For_Range; + --------------------------- + -- Start_Statement_Block -- + --------------------------- + + procedure Start_Statement_Block + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class) is + begin + UIC.Block_Stack.Append (Source_Statement_Vectors.Empty_Vector); + end Start_Statement_Block; + + ------------------------- + -- End_Statement_Block -- + ------------------------- + + procedure End_Statement_Block + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class) + is + Current_Block : constant Source_Statement_Vectors.Vector := + UIC.Block_Stack.Last_Element; + begin + -- Delete the block if it is empty + + if Current_Block.Is_Empty then + UIC.Block_Stack.Delete_Last; + return; + end if; + + UIC.Find_Instrumented_Entities (Last_File).Blocks.Append + (Current_Block); + UIC.Block_Stack.Delete_Last; + end End_Statement_Block; + -------------------------- -- Instrument_Statement -- -------------------------- @@ -1122,7 +1178,7 @@ package body Instrument.C is if UIC.Disable_Instrumentation then UIC.Non_Instr_LL_SCOs.Include (SCO_Id (LL_SCO)); else - UIC.Find_Instrumented_Entities (Last_File).Statements.Append + UIC.Block_Stack.Reference (UIC.Block_Stack.Last).Append (C_Source_Statement' (LL_SCO => LL_SCO, Instr_Scheme => Instr_Scheme, @@ -1428,7 +1484,8 @@ package body Instrument.C is procedure Traverse_Statements (UIC : in out C_Unit_Inst_Context; L : Cursor_Vectors.Vector; - Trailing_Braces : out Unbounded_String); + Trailing_Braces : out Unbounded_String; + Is_Block : Boolean := True); -- Process L, a list of statements or declarations. Set Trailing_Braces -- to the list of braces that should be inserted after this statements' -- list. @@ -1506,9 +1563,11 @@ package body Instrument.C is (Cursor : Cursor_T) return Child_Visit_Result_T is begin if Kind (Cursor) = Cursor_Lambda_Expr then + UIC.Pass.Start_Statement_Block (UIC); Traverse_Declarations (UIC => UIC, L => Cursor_Vectors.To_Vector (Cursor, 1)); + UIC.Pass.End_Statement_Block (UIC); return Child_Visit_Continue; end if; return Child_Visit_Recurse; @@ -1972,7 +2031,8 @@ package body Instrument.C is procedure Traverse_Statements (UIC : in out C_Unit_Inst_Context; L : Cursor_Vectors.Vector; - Trailing_Braces : out Unbounded_String) + Trailing_Braces : out Unbounded_String; + Is_Block : Boolean := True) is procedure Traverse_One (N : Cursor_T; Trailing_Braces : out Unbounded_String); @@ -2048,10 +2108,13 @@ package body Instrument.C is case Kind (N) is when Cursor_Compound_Stmt => - Traverse_Statements (UIC, Get_Children (N), TB); + Traverse_Statements + (UIC, Get_Children (N), TB, Is_Block => False); when Cursor_If_Stmt => Instrument_Statement (N, 'I'); + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); declare Then_Part : constant Cursor_T := Get_Then (N); @@ -2083,6 +2146,8 @@ package body Instrument.C is when Cursor_Switch_Stmt => Instrument_Statement (N, 'C'); + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); declare Switch_Cond : constant Cursor_T := Get_Cond (N); Alt : constant Cursor_T := Get_Body (N); @@ -2119,7 +2184,8 @@ package body Instrument.C is then Cond else Get_Var_Init_Expr (Cond_Var)), Instr_Scheme => Instr_Expr); - + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); Process_Expression (UIC, Cond, 'W'); Traverse_Statements (UIC, To_Vector (While_Body), TB); end; @@ -2130,7 +2196,8 @@ package body Instrument.C is Do_While : constant Cursor_T := Get_Cond (N); begin - Traverse_Statements (UIC, To_Vector (Do_Body), TB); + Traverse_Statements + (UIC, To_Vector (Do_Body), TB, Is_Block => False); -- Insert the trailing braces resulting from the body -- traversal before the while. @@ -2142,8 +2209,9 @@ package body Instrument.C is Instrument_Statement (Do_While, 'W', Instr_Scheme => Instr_Expr); + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); Process_Expression (UIC, Do_While, 'W'); - end; when Cursor_For_Stmt => @@ -2155,8 +2223,12 @@ package body Instrument.C is begin Instrument_Statement (For_Init, ' ', Insertion_N => N); + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); Instrument_Statement (For_Cond, 'F', Instr_Scheme => Instr_Expr); + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); -- The guard expression for the FOR loop is a decision. The -- closest match for this kind of decision is a while loop. @@ -2167,6 +2239,8 @@ package body Instrument.C is Instrument_Statement (For_Inc, ' ', Instr_Scheme => Instr_Expr); + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); end; when Cursor_CXX_For_Range_Stmt => @@ -2186,6 +2260,8 @@ package body Instrument.C is Instrument_Statement (For_Init_Stmt, ' ', Insertion_N => For_Init_Stmt); + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); Process_Expression (UIC, For_Init_Stmt, 'X'); -- Preemptively end the introduced outer scope as it is @@ -2201,21 +2277,36 @@ package body Instrument.C is (For_Range_Decl, ' ', Insertion_N => N, Instr_Scheme => Instr_Stmt); + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); Process_Expression (UIC, For_Range_Decl, 'X'); -- Generate obligations for body statements Traverse_Statements (UIC, To_Vector (For_Body), TB); + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); end; when Cursor_Goto_Stmt | Cursor_Indirect_Goto_Stmt => Instrument_Statement (N, ' '); + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); when Cursor_Label_Stmt => - Traverse_Statements (UIC, Get_Children (N), TB); + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); + Traverse_Statements + (UIC, Get_Children (N), TB, Is_Block => False); + + when Cursor_Break_Stmt => + Instrument_Statement (N, ' '); + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); when Cursor_Stmt_Expr => - Traverse_Statements (UIC, Get_Children (N), TB); + Traverse_Statements + (UIC, Get_Children (N), TB, Is_Block => False); -- Null statement, we won't monitor their execution @@ -2227,12 +2318,16 @@ package body Instrument.C is when Cursor_Call_Expr => -- Check the name of the callee. If the callee is the manual - -- dump buffers procedure, do nothing. It should not be - -- considered for coverage analysis. + -- dump buffers procedure, end the statement block and + -- do not instrument the call expression as it should not + -- be considered for coverage analysis. - if not Is_Manual_Indication_Procedure_Symbol - (Get_Callee_Name_Str (N)) + if Is_Manual_Indication_Procedure_Symbol + (Get_Callee_Name_Str (N)) then + UIC.Pass.End_Statement_Block (UIC); + UIC.Pass.Start_Statement_Block (UIC); + else Instrument_Statement (N, ' '); if Has_Decision (N) then Process_Expression (UIC, N, 'X'); @@ -2403,6 +2498,9 @@ package body Instrument.C is -- Start of processing for Traverse_Statements begin + if Is_Block then + UIC.Pass.Start_Statement_Block (UIC); + end if; for N of L loop if Trailing_Braces /= "" then UIC.Pass.Insert_Text_Before @@ -2411,6 +2509,9 @@ package body Instrument.C is end if; Traverse_One (N, Trailing_Braces); end loop; + if Is_Block then + UIC.Pass.End_Statement_Block (UIC); + end if; end Traverse_Statements; --------------------------- @@ -3138,6 +3239,11 @@ package body Instrument.C is (UIC => UIC, L => Get_Children (Get_Translation_Unit_Cursor (UIC.TU))); + -- Check that there are no open statement blocks at the end of the + -- instrumentation processs. + + pragma Assert (UIC.Block_Stack.Is_Empty); + -- Check whether there is a mismatch between Last_SCO and -- SCOs.SCO_Table.Last. If there is, warn the user and discard the -- preprocessed info: the SCO mapping will be wrong. @@ -3209,12 +3315,29 @@ package body Instrument.C is Unit_Bits : Allocated_Bits renames UIC.Allocated_Bits.Reference (Ent.Buffers_Index); Bit_Maps : CU_Bit_Maps; + + Blocks : SCO_Id_Vector_Vector; begin -- Allocate bits in coverage buffers and insert the -- corresponding witness calls. - for SS of Ent.Statements loop - Insert_Statement_Witness (UIC, Ent.Buffers_Index, SS); + for Block of Ent.Blocks loop + if Switches.Instrument_Block then + declare + Block_SCOs : SCO_Id_Vectors.Vector; + begin + Insert_Statement_Witness + (UIC, Ent.Buffers_Index, Block.Last_Element); + for SS of Block loop + Block_SCOs.Append (SCO_Map (SS.LL_SCO)); + end loop; + Blocks.Append (Block_SCOs); + end; + else + for SS of Block loop + Insert_Statement_Witness (UIC, Ent.Buffers_Index, SS); + end loop; + end if; end loop; if Coverage.Enabled (Coverage_Options.Decision) @@ -3301,6 +3424,8 @@ package body Instrument.C is -- Associate these bit maps to the corresponding CU Set_Bit_Maps (UIC.CUs.Element (SFI), Bit_Maps); + + Set_Blocks (UIC.CUs.Element (SFI), Blocks); end; end loop; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index c6680a8b0..89a47743f 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -224,6 +224,11 @@ package Instrument.C is package Source_Condition_Vectors is new Ada.Containers.Vectors (Natural, C_Source_Condition); + package Block_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, + Element_Type => Source_Statement_Vectors.Vector, + "=" => Source_Statement_Vectors."="); + type C_Instrumented_Entities is record Buffers_Index : Natural := 0; -- 1-based index of the set of coverage buffers for this source file. We @@ -231,7 +236,7 @@ package Instrument.C is -- known, we allocate coverage buffers (UIC.Allocated_Bits) and -- initialize Buffers_Index at the same time. - Statements : Source_Statement_Vectors.Vector; + Blocks : Block_Vectors.Vector; Decisions : Source_Decision_Vectors.Vector; Conditions : Source_Condition_Vectors.Vector; -- Statements, decisions and conditions (for MC/DC) to be instrumented @@ -396,6 +401,9 @@ package Instrument.C is -- to store these, see the documentation of the Fix_CXX_For_Ranges -- subprogram. + Block_Stack : Block_Vectors.Vector; + -- Currently processed blocks (blocks can nest in the source, + -- when e.g. we have a lambda expression). end record; type C_Source_Rewriter is tagged limited private; @@ -501,6 +509,14 @@ private N : Cursor_T) is null; -- See the documentation of Fix_CXX_For_Ranges + procedure Start_Statement_Block + (Pass : Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class) is null; + + procedure End_Statement_Block + (Pass : Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class) is null; + type C_Source_Rewriter is limited new Ada.Finalization.Limited_Controlled with record CIdx : Index_T; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 4699194df..369ed61d5 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -367,6 +367,29 @@ package body Instrument.Common is end loop; end Remap_Scope_Entities; + ------------------ + -- Remap_Blocks -- + ------------------ + + procedure Remap_Blocks + (Blocks : in out SCO_Id_Vector_Vector; + SCO_Map : LL_HL_SCO_Map) + is + Result : SCO_Id_Vector_Vector; + begin + for Block of Blocks loop + declare + Result_Block : SCO_Id_Vectors.Vector; + begin + for LL_SCO of Block loop + Result_Block.Append (SCO_Map (Nat (LL_SCO))); + end loop; + Result.Append (Result_Block); + end; + end loop; + Blocks := Result; + end Remap_Blocks; + -------------- -- New_File -- -------------- diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 328625994..915d98fb3 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -326,6 +326,9 @@ package Instrument.Common is package Annotation_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Annotation_Couple); + package Nat_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, Element_Type => Nat); + type Unit_Inst_Context is tagged record Instrumented_Unit : Compilation_Unit_Part; -- Name of the compilation unit being instrumented @@ -351,6 +354,10 @@ package Instrument.Common is Non_Instr_LL_SCOs : SCO_Sets.Set; -- Set of low level SCO ids that were not instrumented + + Blocks : SCO_Id_Vector_Vector; + -- This is used when the block coverage level is enabled: list of blocks + end record; procedure Import_Annotations @@ -399,6 +406,12 @@ package Instrument.Common is -- Convert low level SCOs in Scope_Entity to high-level SCOs using the -- mapping in SCO_Map. + procedure Remap_Blocks + (Blocks : in out SCO_Id_Vector_Vector; + SCO_Map : LL_HL_SCO_Map); + -- Convert low level SCOs in Blocks to high-level SCOs using the + -- mapping in SCO_Map. + package CU_Name_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Compilation_Unit_Part); diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 5cb28289d..fbd4488c5 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -126,6 +126,11 @@ package body SC_Obligations is Scope_Entities : Scope_Entities_Tree := Scope_Entities_Trees.Empty_Tree; -- Scope tree, used to output e.g. subprogram metrics + Blocks : SCO_Id_Vector_Vector; + -- List of blocks. A block is a list of statement SCOs. Note that this + -- is specific to source instrumentation, but a container cannot be + -- a discriminant-dependent component. + case Provider is when Compiler => null; @@ -617,6 +622,19 @@ package body SC_Obligations is Vectors => SCO_Vectors, Read_Element => Read); + procedure Read is new Read_Vector + (Index_Type => Positive, + Element_Type => SCO_Id, + Vectors => SCO_Id_Vectors, + Read_Element => Read); + + procedure Read is new Read_Vector + (Index_Type => Positive, + Element_Type => SCO_Id_Vectors.Vector, + "=" => SCO_Id_Vectors."=", + Vectors => SCO_Id_Vector_Vectors, + Read_Element => Read); + procedure Checkpoint_Load_Merge_Unit (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; @@ -730,6 +748,19 @@ package body SC_Obligations is Vectors => SCO_Vectors, Write_Element => Write); + procedure Write is new Write_Vector + (Index_Type => Positive, + Element_Type => SCO_Id, + Vectors => SCO_Id_Vectors, + Write_Element => Write_SCO); + + procedure Write is new Write_Vector + (Index_Type => Positive, + Element_Type => SCO_Id_Vectors.Vector, + "=" => SCO_Id_Vectors."=", + Vectors => SCO_Id_Vector_Vectors, + Write_Element => Write); + ------------------ -- Local tables -- ------------------ @@ -951,6 +982,15 @@ package body SC_Obligations is return CU_Vector.Reference (CU).Element.Bit_Maps; end Bit_Maps; + ------------ + -- Blocks -- + ------------ + + function Blocks (CU : CU_Id) return SCO_Id_Vector_Vector is + begin + return CU_Vector.Reference (CU).Element.Blocks; + end Blocks; + ----------------- -- Has_PP_Info -- ----------------- @@ -1093,6 +1133,10 @@ package body SC_Obligations is end loop; end; Value.Bit_Maps_Fingerprint := CLS.Read_Fingerprint; + + -- Read block information + + Read (CLS, Value.Blocks); end if; end case; @@ -1532,6 +1576,19 @@ package body SC_Obligations is end loop; end if; + -- Remap blocks information + + for Block_Cur in CP_CU.Blocks.Iterate loop + declare + Block_Ref : constant SCO_Id_Vector_Vectors.Reference_Type := + CP_CU.Blocks.Reference (Block_Cur); + begin + for SCO_Cur in Block_Ref.Iterate loop + Remap_SCO_Id (Block_Ref.Reference (SCO_Cur)); + end loop; + end; + end loop; + -- Remap macro information declare @@ -1832,6 +1889,10 @@ package body SC_Obligations is end loop; CSS.Write (Value.Bit_Maps_Fingerprint); + + -- Write the blocks information + + Write (CSS, Value.Blocks); end if; end case; @@ -4709,6 +4770,16 @@ package body SC_Obligations is (GNAT.SHA1.Binary_Message_Digest'(GNAT.SHA1.Digest (Ctx))); end Set_Bit_Maps; + ---------------- + -- Set_Blocks -- + ---------------- + + procedure Set_Blocks (CU : CU_Id; Blocks : SCO_Id_Vector_Vector) is + Info : CU_Info renames CU_Vector.Reference (CU); + begin + Info.Blocks := Blocks; + end Set_Blocks; + ------------------------ -- Get_Scope_Entities -- ------------------------ diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 74098dd20..8d9d0bc4c 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -712,13 +712,28 @@ package SC_Obligations is MCDC_Bits : MCDC_Bit_Map_Access; end record; + package SCO_Id_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, Element_Type => SCO_Id); + + package SCO_Id_Vector_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, + Element_Type => SCO_Id_Vectors.Vector, + "=" => SCO_Id_Vectors."="); + subtype SCO_Id_Vector_Vector is SCO_Id_Vector_Vectors.Vector; + function Bit_Maps (CU : CU_Id) return CU_Bit_Maps; -- For a unit whose coverage is assessed through source code -- instrumentation, return bit maps. + function Blocks (CU : CU_Id) return SCO_Id_Vector_Vector; + -- For a unit whose coverage is assessed through source code + -- instrumentation, return blocks information. + procedure Set_Bit_Maps (CU : CU_Id; Bit_Maps : CU_Bit_Maps); -- Set the tables mapping source trace bit indices to SCO discharge info + procedure Set_Blocks (CU : CU_Id; Blocks : SCO_Id_Vector_Vector); + -- With languages featuring macros such as C, coverage obligations are -- established from expanded code but the user level sources against which -- we produce reports are the original unexpanded ones. Here, we instate diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 138b262d1..5e71db7ce 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -698,6 +698,7 @@ package body Switches is if Warnings_Registered then Register_Warning; end if; + Instrument_Block := Args.Bool_Args (Opt_Instrument_Block); end Parse_Arguments; ----------- diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index cae2b753c..5ff3612fa 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -167,6 +167,9 @@ package Switches is Subps_Of_Interest : SC_Obligations.Scope_Id_Set; -- List of subprograms of interest requested by users on the command line + Instrument_Block : Boolean := False; + -- When True, instrument statement blocks instead of statements + type Separated_Source_Coverage_Type is (None, Routines, Instances); Separated_Source_Coverage : Separated_Source_Coverage_Type := None; From 64d9e5480678ff2d716e0db05b32b5da5f413c68 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 11 Jul 2024 16:16:34 +0200 Subject: [PATCH 0878/1483] 207-srctrace-version: update test Following a checkpoint version update, update the test. Also adapt it to make full path references in traces / checkpoints file-system agnostic. --- .../tests/207-srctrace-version/foo.c.sid | Bin 1539 -> 1132 bytes testsuite/tests/207-srctrace-version/main.adb | 14 ++++++++---- testsuite/tests/207-srctrace-version/main.sid | Bin 994 -> 1357 bytes testsuite/tests/207-srctrace-version/p.gpr | 7 ++++++ .../207-srctrace-version/reference.srctrace | Bin 360 -> 304 bytes testsuite/tests/207-srctrace-version/test.py | 6 +---- .../tests/207-srctrace-version/update.sh | 21 +++++++++++++----- 7 files changed, 34 insertions(+), 14 deletions(-) create mode 100644 testsuite/tests/207-srctrace-version/p.gpr diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid index 62710486a5d06c6726a957a94791125cadeefc3d..3247a9a5fa3bf7a81a892018a45692aef44d266b 100644 GIT binary patch delta 204 zcmZqXdBb7l?&lbioL{DpoRONGU67xdSHi%@00E3Zz`(!+#0~`($t{?Cl2v+R zg9@WWrM~LsdF!Vrvo+kGvU19Oe!DfhLO>>L-obdBkpo%zf?R5q3r9BYhuk{A;$41oe03!s5xUEaHR@Ah)LhtyQmHu48Z z{1K8+(oDv-@KcbeT2LOc$4hS?Cdw+&d$!>^4iBQ+U~v7U8BF1HYReat(pSip|U;lmd;`92+?ELB3!Buav0mTo<01@;v8aGLc zoD6(K#wZ}O0wBQ0H_?%ga|G}yjZusej{`!Wkq&>@i5YtWr}%zu{5V?pyLo*0M|b?M zxn5gsUtmqjC8dJqqLO9_w}UOfhh*Do%jC|WXu{LK36A6s;3RQN;-Uzp!Aw$%;TZ5r zQj8Z?)aCls%pwZtk@9cQd*Nl^dch6OCc{1poZytEkVR=RpeDntrr~LXli}0w@g_oC z*ap~@v3ziv3?ail7$CVCvJYvYh92`{y2k#V=0i{Qd%9=T{!)9Z{U*t?qTW}|r#rbx z@OslcS6M+0(mPq9I$EPqkS0!?e1f$MYh{S^uJ0doOShzRby?cVEBcuz#DBO)eAnb9 i{fe09u6g9T%kg6_%Xr&@YQ(pQ+x%*F(>nL!g8mPu9}8Uo diff --git a/testsuite/tests/207-srctrace-version/main.adb b/testsuite/tests/207-srctrace-version/main.adb index 4de03770a..0d78b898a 100644 --- a/testsuite/tests/207-srctrace-version/main.adb +++ b/testsuite/tests/207-srctrace-version/main.adb @@ -1,17 +1,23 @@ with Interfaces.C; use Interfaces.C; -with Support; - procedure Main is + function Or_Else (L, R : int) return int; pragma Import (C, Or_Else, "or_else"); + procedure Assert (B : Boolean) is + begin + if not B then + raise Program_Error; + end if; + end Assert; + function And_Then (L, R : Boolean) return Boolean is begin return L and then R; end And_Then; begin - Support.Assert (And_Then (True, True)); - Support.Assert (Or_Else (0, 1) = 1); + Assert (And_Then (True, True)); + Assert (Or_Else (0, 1) = 1); end Main; diff --git a/testsuite/tests/207-srctrace-version/main.sid b/testsuite/tests/207-srctrace-version/main.sid index c097c077df573af20d29b5e20aabe882920613bd..ad7ad0d76efd842daec4cfc1e09da42669dacf64 100644 GIT binary patch literal 1357 zcmb7^zfK!L5XN_HAS6J9kbn>=0^E_vITRtKcH>mgKFfpXR^M0qy)fxD!l*ikdi_>64myoi{I=2j?0s2TG_n{zmC@-bpPQfa z!JoDI;N!*e_V4=X*!iy?`*t`Yi<0P==o8UNQ3w$DH3uI*j*Abu9C2y>)Z$b`W^E7m z!JF@;tIOlBCui;G#o^KB#>MNW;?{U8+=_;GT{_g1vgVvMJXR+@>aF$rQ7?gtD7;E5 zmQE%zA63=j=BKUQD4v$JVObX?tDYMX85JcTyVT=+DevAr6E{TW@nrO*#7i(i+LSSX z;1IhaiZE?WgZ-y$YfbQwzRW%0*l;Gg+1Hj$J&UnG1~ASE9%apS$er9+2yNR^XWx_GN|~k|UoLcq+y&h{DGk za@raC8ZIIxSN$dDWiD9v~qZvJg literal 994 zcma)5J4?hs5Z>IK55#vN_$cgr;N2dASYLG@oLF2Zs4-dZg5KsxHsbFPD?3a7g7_2c zEUYXnEG(`UL2$lJCd5W>V0I=m-^_fOO`7|SwijNmdR^t6_rpLNF(p!QNQ5YnilVmY zS$4yol3t{eSjkBB!&r8-Yp9Wm+>Vk)#U@SylX-HxzFUnW&qS`Ls)UJyP|Kbh=$h-F zI!@URv_p!M#M!S&t!hen(!F`WvPKlcc!5&-3)^cMeWeFA80fpcO`jJfH0Qyfk!8KcEz+-=~OQeu_9RK$C&OZ~> zPLskeW~Jbjy(M`h7>H}&m2i?j1z;*gR?B AGynhq diff --git a/testsuite/tests/207-srctrace-version/p.gpr b/testsuite/tests/207-srctrace-version/p.gpr new file mode 100644 index 000000000..c2454791b --- /dev/null +++ b/testsuite/tests/207-srctrace-version/p.gpr @@ -0,0 +1,7 @@ +project P is + for Source_Dirs use ("."); + for Object_Dir use "obj"; + for Exec_Dir use "obj"; + for Languages use ("Ada", "C"); + for Main use ("main.adb"); +end P; diff --git a/testsuite/tests/207-srctrace-version/reference.srctrace b/testsuite/tests/207-srctrace-version/reference.srctrace index 15531ccfae0a690af09157178d27212bdab8a421..496804ef7e67e708ff592e113a9b0fd3b499c25e 100644 GIT binary patch delta 184 zcmaFCw1H`YjxHku14951g8&l{a{%$W)%|H8J~N0w0`e0R)nqI6RX5LDKSi0X;r^7B zQ||NIt=SaTFrUlx?f4VbiW Date: Tue, 30 Jul 2024 17:20:54 +0200 Subject: [PATCH 0879/1483] Reinstate proper test filter for Ravenscar tests --- testsuite/tests/Ravenscar/Exceptions/extra.opt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/tests/Ravenscar/Exceptions/extra.opt b/testsuite/tests/Ravenscar/Exceptions/extra.opt index 85c5c9990..274d5fa68 100644 --- a/testsuite/tests/Ravenscar/Exceptions/extra.opt +++ b/testsuite/tests/Ravenscar/Exceptions/extra.opt @@ -1 +1,3 @@ block DEAD Tests with exceptions breaking the control flow +RTS_ZFP DEAD no support for exception propagation in ZFP runtimes +RTS_LIGHT_TASKING DEAD no support for exception propagation in light-tasking runtimes From 4c3a1f19e68b7f1c4d7654cc7ff4f5c93ee33cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 24 Apr 2024 16:07:07 +0200 Subject: [PATCH 0880/1483] Reject non-library aggregate project files It is not always possible and/or well defined to support aggregate projects. While we refine what it would mean to support this kind of project, explicitely reject them to avoid confusion and crashes. --- doc/gnatcov/gpr.rst | 5 ++ doc/gnatcov/units_of_interest.rst | 6 ++ testsuite/tests/281_aggr_reject/a.gpr | 5 ++ testsuite/tests/281_aggr_reject/aggr.gpr | 5 ++ testsuite/tests/281_aggr_reject/b.gpr | 5 ++ .../tests/281_aggr_reject/src_a/main.adb | 6 ++ .../tests/281_aggr_reject/src_b/main.adb | 7 ++ testsuite/tests/281_aggr_reject/test.py | 63 +++++++++++++++ .../src1/foo.adb | 6 -- .../src2/foo.adb | 7 -- .../R420-002-aggregate-project-file/test.opt | 2 - .../R420-002-aggregate-project-file/test.py | 77 ------------------- tools/gnatcov/project.adb | 9 +++ 13 files changed, 111 insertions(+), 92 deletions(-) create mode 100644 testsuite/tests/281_aggr_reject/a.gpr create mode 100644 testsuite/tests/281_aggr_reject/aggr.gpr create mode 100644 testsuite/tests/281_aggr_reject/b.gpr create mode 100644 testsuite/tests/281_aggr_reject/src_a/main.adb create mode 100644 testsuite/tests/281_aggr_reject/src_b/main.adb create mode 100644 testsuite/tests/281_aggr_reject/test.py delete mode 100644 testsuite/tests/R420-002-aggregate-project-file/src1/foo.adb delete mode 100644 testsuite/tests/R420-002-aggregate-project-file/src2/foo.adb delete mode 100644 testsuite/tests/R420-002-aggregate-project-file/test.opt delete mode 100644 testsuite/tests/R420-002-aggregate-project-file/test.py diff --git a/doc/gnatcov/gpr.rst b/doc/gnatcov/gpr.rst index f93f029bb..3b70815f9 100644 --- a/doc/gnatcov/gpr.rst +++ b/doc/gnatcov/gpr.rst @@ -30,6 +30,11 @@ coverage perspectives. In the root project, a ``Coverage`` package may be used to specify the arguments for |gcv| commands and the target/runtime profile may be set using toplevel attributes. +Please note that **non-library aggregate project files are currently not +supported** and will be rejected by |gcv|. The aggregated projects will have +to be processed individually and coverage reports consolidated +:ref:`through checkpoints`, when this makes sense. + .. _switches_attr: Specifying |gcv| command Switches diff --git a/doc/gnatcov/units_of_interest.rst b/doc/gnatcov/units_of_interest.rst index a596ff89e..e62efef43 100644 --- a/doc/gnatcov/units_of_interest.rst +++ b/doc/gnatcov/units_of_interest.rst @@ -53,6 +53,12 @@ Finer grain control is possible with additional switches and attributes, letting users first specify the set of :dfn:`projects of interest` where the units of interest reside, then may filter the *units* of interest therein. +Please note that **non-library aggregate project files are currently not +supported** and will be rejected by |gcv|. The aggregated projects will have +to be processed individually and coverage reports consolidated +:ref:`through checkpoints`, when this makes sense. + + Conveying *projects* of interest ******************************** diff --git a/testsuite/tests/281_aggr_reject/a.gpr b/testsuite/tests/281_aggr_reject/a.gpr new file mode 100644 index 000000000..940fb9670 --- /dev/null +++ b/testsuite/tests/281_aggr_reject/a.gpr @@ -0,0 +1,5 @@ +project A is + for Object_Dir use "obj_a"; + for Source_Dirs use ("../src_a"); + for Main use ("main.adb"); +end A; diff --git a/testsuite/tests/281_aggr_reject/aggr.gpr b/testsuite/tests/281_aggr_reject/aggr.gpr new file mode 100644 index 000000000..1b0c97248 --- /dev/null +++ b/testsuite/tests/281_aggr_reject/aggr.gpr @@ -0,0 +1,5 @@ +aggregate project Aggr is + + for Project_Files use ("./a.gpr", "./b.gpr"); + +end Aggr; diff --git a/testsuite/tests/281_aggr_reject/b.gpr b/testsuite/tests/281_aggr_reject/b.gpr new file mode 100644 index 000000000..5c21c2f5a --- /dev/null +++ b/testsuite/tests/281_aggr_reject/b.gpr @@ -0,0 +1,5 @@ +project B is + for Object_Dir use "obj_b"; + for Source_Dirs use ("../src_b"); + for Main use ("main.adb"); +end B; diff --git a/testsuite/tests/281_aggr_reject/src_a/main.adb b/testsuite/tests/281_aggr_reject/src_a/main.adb new file mode 100644 index 000000000..e4ff0a810 --- /dev/null +++ b/testsuite/tests/281_aggr_reject/src_a/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("This is the A main, it only has a single statement."); +end Main; diff --git a/testsuite/tests/281_aggr_reject/src_b/main.adb b/testsuite/tests/281_aggr_reject/src_b/main.adb new file mode 100644 index 000000000..87a07299f --- /dev/null +++ b/testsuite/tests/281_aggr_reject/src_b/main.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put ("This is the B main,"); + Put_Line (" it has a two statements."); +end Main; diff --git a/testsuite/tests/281_aggr_reject/test.py b/testsuite/tests/281_aggr_reject/test.py new file mode 100644 index 000000000..eb574f830 --- /dev/null +++ b/testsuite/tests/281_aggr_reject/test.py @@ -0,0 +1,63 @@ +""" +Test that gnatcov properly reject non-library aggregate projects +""" + +from e3.fs import cp + +from SCOV.minicheck import xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import contents_of + + +def check_cmd(cmd, extra_args=None, trace_mode=None): + """ + Check that the gnatcov command cmd properly rejects the aggregate project + aggr.gpr, emitting the EXPECTED_ERR_MSG error message. + + The check is only performed the the current trace mode matches trace_mode, + if not None. + + extra_args are concatenated to the arguments passed to xcov. + """ + if trace_mode and thistest.options.trace_mode != trace_mode: + return + + log = f"{cmd}.log" + p_cmd = xcov( + [cmd, "-Paggr.gpr", "-q", "-cstmt"] + + (extra_args if extra_args else []), + register_failure=False, + out=log, + ) + thistest.fail_if( + p_cmd.status == 0, + comment=f"'gnatcov {cmd}' did not exit with an error status", + ) + thistest.fail_if_no_match( + f"unexpected or empty 'gnatcov {cmd}' error message", + regexp=r".*gnatcov(.exe)?:" + r" non-library aggregate projects are not supported", + actual=contents_of(log).strip(), + ) + + +tmp = Wdir("tmp_") + +# copy the projects in the test directory to avoid having lingering artifacts +cp("../*.gpr", ".") + +trace_suffix = "srctrace" if thistest.options.trace_mode == "src" else "trace" + +# Test all the gnatcov subcommands, when relevant to the trace mode, properly +# reject aggregate projects. +tests = [ + ("instrument", None, "src"), + ("run", ["dummy_exe"], "bin"), + ("coverage", [f"dummy.{trace_suffix}"], None), +] + +for cmd, extra, mode in tests: + check_cmd(cmd, extra, mode) + +thistest.result() diff --git a/testsuite/tests/R420-002-aggregate-project-file/src1/foo.adb b/testsuite/tests/R420-002-aggregate-project-file/src1/foo.adb deleted file mode 100644 index e9f45d970..000000000 --- a/testsuite/tests/R420-002-aggregate-project-file/src1/foo.adb +++ /dev/null @@ -1,6 +0,0 @@ -with Ada.Text_IO; use Ada.Text_IO; - -procedure Foo is -begin - Put_Line ("Hello, world!"); -end Foo; diff --git a/testsuite/tests/R420-002-aggregate-project-file/src2/foo.adb b/testsuite/tests/R420-002-aggregate-project-file/src2/foo.adb deleted file mode 100644 index 2a837257d..000000000 --- a/testsuite/tests/R420-002-aggregate-project-file/src2/foo.adb +++ /dev/null @@ -1,7 +0,0 @@ -with Ada.Text_IO; use Ada.Text_IO; - -procedure Foo is -begin - Put_Line ("Hello, world!"); - Put_Line ("Second edition..."); -end Foo; diff --git a/testsuite/tests/R420-002-aggregate-project-file/test.opt b/testsuite/tests/R420-002-aggregate-project-file/test.opt deleted file mode 100644 index df872a03f..000000000 --- a/testsuite/tests/R420-002-aggregate-project-file/test.opt +++ /dev/null @@ -1,2 +0,0 @@ -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 -!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/R420-002-aggregate-project-file/test.py b/testsuite/tests/R420-002-aggregate-project-file/test.py deleted file mode 100644 index f45aef9d2..000000000 --- a/testsuite/tests/R420-002-aggregate-project-file/test.py +++ /dev/null @@ -1,77 +0,0 @@ -import os.path -import re - -from SUITE.cutils import Wdir, contents_of, indent -from SUITE.tutils import ( - exepath_to, - gprbuild, - gprfor, - thistest, - tracename_for, - xcov, - xrun, -) - - -root_dir = os.path.abspath(".") -wd = Wdir("tmp_") - - -gpr1 = gprfor( - ["foo.adb"], - prjid="src1", - srcdirs=os.path.join(root_dir, "src1"), - objdir="obj1", - exedir="obj1", -) -gpr2 = gprfor( - ["foo.adb"], - prjid="gpr", - srcdirs=os.path.join(root_dir, "src2"), - objdir="obj2", - exedir="obj2", -) -aggr = "aggr.gpr" - -with open(aggr, "w") as f: - f.write( - """aggregate project Aggr is - for Project_Files use ("{}", "{}"); -end Aggr; -""".format( - gpr1, gpr2 - ) - ) - -exe1 = os.path.join("obj1", "foo") -exe2 = os.path.join("obj2", "foo") -trace1 = tracename_for(exe1) -trace2 = tracename_for(exe2) - -gprbuild(aggr, extracargs=["-fdump-scos"]) -xrun([exepath_to(exe1), "-o", trace1]) -xrun([exepath_to(exe2), "-o", trace2]) -xcov( - ["coverage", "-P", aggr, "-cstmt", "-areport", trace1, trace2], - out="coverage.txt", - register_failure=False, -) -log = contents_of("coverage.txt") - -pattern = """\ -.*gnatcov.*: error: the following source file: - foo\\.adb -appears as the main source file in: - .*obj1.foo.ali - .*obj2.foo.ali -Is the same ALI file provided twice\\?\ -""" -thistest.fail_if( - not re.match(pattern, log, re.DOTALL), - 'Could not match "gnatcov coverage" output:\n' - "{}\n" - "against the expected pattern:\n" - "{}\n".format(indent(log), indent(pattern)), -) - -thistest.result() diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index a14b4cca2..b280659e4 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -1321,6 +1321,15 @@ package body Project is Env.Set_Object_Subdir (+(+Obj_Subdir)); end if; + -- We do not support non-library aggregate projects, no need to go + -- further. + + if Prj_Tree.Root_Project.Is_Aggregate_Project and then + not Prj_Tree.Root_Project.Is_Aggregate_Library + then + Fatal_Error ("non-library aggregate projects are not supported"); + end if; + -- If we were asked only to load the project file, stop there (i.e. -- before computing the list of projects/units of interest). From e9fa6ef6547e9de662f942b9e3c3b92e361e267b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 9 Aug 2024 11:58:17 +0200 Subject: [PATCH 0881/1483] SC_Obligation: Add support for pragma First_Controlling_Parameter This is the 255th pragma introduced, so we need to increase the size of the Pragma_Id fields in checkpoints and SID files. --- .../tests/207-srctrace-version/foo.c.sid | Bin 1132 -> 1129 bytes testsuite/tests/207-srctrace-version/main.sid | Bin 1357 -> 1363 bytes .../207-srctrace-version/reference.srctrace | Bin 304 -> 304 bytes .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 668 -> 1508 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2036 -> 2596 bytes .../gen/arm-elf-linux/gcvrt-foo.ads | 2 +- .../gen/arm-elf-linux/main_1.sid | Bin 409 -> 410 bytes .../gen/arm-elf-linux/main_2.sid | Bin 409 -> 410 bytes .../gen/arm-elf-linux/pkg.sid | Bin 1056 -> 1059 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1846 -> 1851 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1856 -> 1861 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 1986 -> 1996 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 1922 -> 1927 bytes .../gen/x86_64-windows/gcvrt-foo.ads | 2 +- .../gen/x86_64-windows/main_1.sid | Bin 411 -> 412 bytes .../gen/x86_64-windows/main_2.sid | Bin 411 -> 412 bytes .../gen/x86_64-windows/pkg.sid | Bin 1060 -> 1063 bytes tools/gnatcov/checkpoints.ads | 3 ++- tools/gnatcov/sc_obligations.adb | 4 ++-- tools/gnatcov/sc_obligations.ads | 2 ++ 20 files changed, 8 insertions(+), 5 deletions(-) diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid index 3247a9a5fa3bf7a81a892018a45692aef44d266b..5c7abb43ec2597faf22b1fcd644e66ab9a0c229b 100644 GIT binary patch delta 62 zcmaFE@sdNt-On*3IloLHIU_YWyC6R^uY`erqevnX^M3}W$sd_S7I!l-3fM9*Fz9FG S=cei>7p0aKr%s;Fd=>zTt`wI5 delta 61 zcmaFK@rFah-On*3IloLHIU_YWyC6R^uY`ebqevnX1ps#p6pH`= diff --git a/testsuite/tests/207-srctrace-version/main.sid b/testsuite/tests/207-srctrace-version/main.sid index ad7ad0d76efd842daec4cfc1e09da42669dacf64..bf9bae2fe456d042cbab7a7b0427a1df926abe2b 100644 GIT binary patch delta 72 zcmX@hb(u@V-On*3IloLHIU_YWyC6R^uY`erqlg|8QzFA;XC`N+{|uAcnVy5Fd}a`D S^JZp2MiBQX3s{nq)dc`!G8a?; delta 66 zcmcc2b(TxS-On*3IloLHIU_YWyC6R^uY`ebqlg|8W5Q$?CTGUKlRKH71IZ$0Abaz6 QWpby diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index ef7beeb1229659140fa7b4044fe9bde594417b85..3847bda74fe611ddb071b62731490ed2c810c471 100644 GIT binary patch literal 1508 zcmYk6O-NKx7>2)@rtv0X-CIORivzll(7H2CG=>X_DI_dPrf3nQW?<2eRD=r`A|fI~ zh)9Tpw1|)pkr0t+Au@!7xDb(uXcZyR+C{70_skn4UY~it=Q}@hujkfZyKwn>bMZ;{ zox4vH$&^{68U9*;Yqu&mP+fb_68Kz=>v7NhQxCiEJ-VGSOC$4gnX|cUY*vNOhjC@& zY_2)ZH^(h56Q9fE@ayN|c$dkaKGTxV#OVL`Q~&?^Tp8;(?z13ep)FQfkThrSJtJEJ zQ^+gIAHV>4O}Q+;uKd~i$hLfTwypXOc*r9A>3wLWfa`?TgmsUiejcnrt}wDIz8+dX z7{L#N0epp#jU#ivtDervo{_DCY3y%Pc?&#=@%WlS6Y5Q13ONRGcRZPMzV0k9-zrbi zx5*cj+vQ364*9FfMX(d|zg2z*ay^p$3!b>o%FEyy{J{Q-9|YM?vVX|a*@*I(JV{@Y zpHQBXC+Vl+gR@VbxPKs@_lEMOXJ~KG&;5{`Z_d-%yz-(vNxvk&qWn>w zq+b=ws*|j*gZ}v`Z^@JNJK|T>N!GuE9QQ+c7c3&TrYpV;hp$KW7d2Xq?f?J) literal 668 zcmYk2Jud`N6o$`?wL7sQc8G|GOxTEKWA7Rkg+fqBBnYCA_%6sISqhaxAtIs@5tTwA zqEajN2Z*RtDut*OqEL9w%q?tk_nG%S_k7&bF*Q0do0};wudeSpZbGC>gn#ikpQ%*3 z&Pj{IcMWG}WwU#0d1HIgh$PW^0#hsu^ogYSZr~L1g)o;d=8OqUIG8ts#zeK!dbg+7 zj7NS( zO3){M05vbBFGpyt{|HBj)7HCoGE$+g*14`0FTk%rt^W%5@F$a6$Cr7i`7d^k1#|^{ z#eC}jqBXx2U501T+`e4c_=)X5!kX*2pM|Y(8ftzc)H#-5Gx_^4i9WUd6RgL7gPIpQ zTE~}Rn1Exj1unr_Sc3YFL#TWEA+Hmzxp7_@X3-B&_jFsbeVGWG6BVX44j{HDe oyWcys=6^t!`=3!fBW?6m|B}A?jsWT$b5@_(eVjv$UqOBUA6+g%+yDRo diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_2.trace b/testsuite/tests/U204-026-arch-mix/bin-main_2.trace index c906f833e36dae85e4cda73f0b2a8ea4c91caa89..f42903d9e2869276e89b694b0a534c8a8cad1063 100644 GIT binary patch delta 690 zcmeyuzeHq$94iMW7a#vbWhEm+V>5OJ1_oguHZm|W(KWEpHLz4LG_W!>u`)De-~ftq z0kML)ftiJ=v7w;}!^ZMd)_MU31)wMc!vStE#lXTK1ZEt8^A*7S6L3C6{tTQCk-q@v zL*%bO`5aL5?m+oK7l6%!^6TLiK7cCVfhu@|X5a@j17LiZgTKJlLoE0K=R+Ly2aV6b z19FEm1JD5w4J=>*5Fes}1ImZF7{-Um^T5$30$N@FQ0wxMI#RkgfncT~!uL$#8 z44SG07=Q9!HjOAK2WDgd%m}Cz2IR|6zRwoQjii6FKD#P6lKGSUfqZ27d^Guf_E-y8 Wk`b^3g&-opM4)_FfWi2%00RI8i!p2f delta 149 zcmZ1?@`Znb94k9FA0y91WhEm60|Ryj1_oguHZm|W(KRsFH8fN(G_f);v@$ee-~ftq z1F?dknW>q9fw8%P`Nr~8Rz)2KA)qJ&!yS+$5U4=;3_K9Nz+_qWenyGOXW8``MJCH~ dXiQ$p;Xj#$Q(>|R5T^j~6wU|^1qMN|asa_I7hnJY diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads index 718d038b9..414d9af4f 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo.ads @@ -20,6 +20,6 @@ package GCVRT.Foo is 3 => gnatcov_rts_buffers_z3791e32c_buffers'Access); C_List : constant GNATcov_RTS.Buffers.Lists.GNATcov_RTS_Coverage_Buffers_Group_Array := ( 3, List'Address); - pragma Export (C, C_List, "gnatcov_rts_buffers_array_Foo"); + pragma Export (C, C_List, "gnatcov_rts_buffers_array_foo"); end GCVRT.Foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index 7b6ae03aa4e119ac03218c6683215d21066f4626..3ce2380ef56b8dd8f1ee342c2ba8dd5b88062549 100644 GIT binary patch delta 36 rcmbQqJd0Vx-On*3IloLHIU_YWyC6R^uY`erqlg_N(|?A^!HjMI)in!A delta 35 qcmbQmJd;_(-On*3IloLHIU_YWyC6R^uY`ebqlg_Ni<4ObjdxEHo!avF+fs&^54BFf_6< NG_f)?oh;8T4gdzYB98z7 delta 135 zcmdnZw~bH4-On*3IloLHIU_YWyC6R^uY`ebqlh&#{d;FMe1VV;wW3=9kcK%A0VmYS1akeixUqFYjwnmRe2ZHJ1vuA!lVp_!F| Tp%sv!ZD3?&U;xqp0x%i?$b%)V diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index 50d9705065207ebc1916373270caff8045ed876e..013e29d5854aa28614bac34e8c4564faae3fb1e3 100644 GIT binary patch delta 145 zcmX@Wca%@W-On*3IloLHIU_YWyC6R^uY`erqlh&#(|?A|0nCbwKzec!i!;Z621X_Z z1_q8vthOMbUo6fb6?UvFj0y*?AD((+uINcdpu7MO8=2}Elq+Z$85o%uSQuDnPEKOm frDCCLV5wkeWMyb#WoW9PZD3?&U;xqp0x%i?KT+PXc!q7nHX3YSZIR8 zX9BUaRZM7cYEf}aW=U>(QA~MaS!zs$g;~6riEepjUP^v>v6)FsdR}4)&`B|wdBr7( KIg|O=w*Ua^yJcw%WzcE+zBqIX@g8&d4nd%voD`*%Q7?~JY7+7ddzQDE#0INM8b^rhX delta 98 zcmZqYZ{inm_j3$M&M#9)&PYwpF38W!D`DW0Nqaz3+w uI2Nq6j0zd|?{lXe<~hm8z`!5?#3`v|sX6%txv6<2x+O)asgtj=Z2|y-_#%h^ diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads index 4d6b4219d..f0c30210d 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo.ads @@ -20,6 +20,6 @@ package GCVRT.Foo is 3 => gnatcov_rts_buffers_z3791e32c_buffers'Access); C_List : constant GNATcov_RTS.Buffers.Lists.GNATcov_RTS_Coverage_Buffers_Group_Array := ( 3, List'Address); - pragma Export (C, C_List, "gnatcov_rts_buffers_array_Foo"); + pragma Export (C, C_List, "gnatcov_rts_buffers_array_foo"); end GCVRT.Foo; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid index 5de7c2738c22c11a72a90a4de804fdad8d163701..d54d4518ed370abfd0c4c72fc082ed0d17386ca5 100644 GIT binary patch delta 36 rcmbQuJcn7t-On*3IloLHIU_YWyC6R^uY`erqlg0|(|?A^p^R<-)!7SC delta 35 qcmbQkJeyg>-On*3IloLHIU_YWyC6R^uY`ebqlg0|-On*3IloLHIU_YWyC6R^uY`ebqlg0|XKzed3vonY~$s7#; DuYVA; delta 48 zcmZ3^v4lg!-On*3IloLHIU_YWyC6R^uY`ebqevVR CSS.Write (Value.Value); diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 8d9d0bc4c..2cfbe7a92 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -913,6 +913,7 @@ package SC_Obligations is Pragma_Fast_Math, Pragma_Favor_Top_Level, Pragma_Finalize_Storage_Only, + Pragma_First_Controlling_Parameter, Pragma_Ghost, Pragma_Global, Pragma_Gnat_Annotate, @@ -1230,6 +1231,7 @@ package SC_Obligations is Pragma_Extensions_Visible => False, Pragma_External => False, Pragma_Finalize_Storage_Only => False, + Pragma_First_Controlling_Parameter => False, Pragma_Ghost => False, Pragma_Global => False, Pragma_Gnat_Annotate => False, From 03c8139bc0b186a06f8e8b4184f8c3c91e3ea6f4 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 5 Jul 2024 16:05:06 +0200 Subject: [PATCH 0882/1483] Add Start/End_Sloc information for scope entities This is needed to include coverage information that may not be in the SCOs range, e.g. disabled coverage information. --- tools/gnatcov/annotations-dynamic_html.adb | 21 ++++++++++---- tools/gnatcov/annotations-xml.adb | 24 +++++++++------- tools/gnatcov/checkpoints.ads | 3 +- tools/gnatcov/instrument-ada_unit.adb | 33 +++++++++++++--------- tools/gnatcov/instrument-c.adb | 6 +++- tools/gnatcov/sc_obligations.adb | 6 ++++ tools/gnatcov/sc_obligations.ads | 7 +++++ 7 files changed, 68 insertions(+), 32 deletions(-) diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 918ba9736..988413c54 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -562,7 +562,9 @@ package body Annotations.Dynamic_Html is is use Scope_Entities_Trees; - function To_JSON (Cur : Cursor) return JSON_Value; + function To_JSON + (Cur : Cursor; + Is_Root : Boolean := False) return JSON_Value; -- Convert a scope entity to a JSON scoped metric: compute line and -- obligation statistics for the given scope and recursively for -- child scopes. Store the result as a JSON object, with the name and @@ -572,7 +574,9 @@ package body Annotations.Dynamic_Html is -- To_JSON -- ------------- - function To_JSON (Cur : Cursor) return JSON_Value + function To_JSON + (Cur : Cursor; + Is_Root : Boolean := False) return JSON_Value is Scope_Ent : constant Scope_Entity := Element (Cur); Child : Cursor := First_Child (Cur); @@ -581,11 +585,16 @@ package body Annotations.Dynamic_Html is Children_Scope_Metrics_JSON : JSON_Array; -- Representation of the scope metrics for the html format + File_Info : constant File_Info_Access := Get_File (File); Line_Stats : constant Li_Stat_Array := Line_Metrics - (Get_File (File), - First_Sloc (Scope_Ent.From).L.Line, - Last_Sloc (Scope_Ent.To).L.Line); + (File_Info, + Scope_Ent.Start_Sloc.Line, + (if Is_Root then Last_Line (File_Info) + else Scope_Ent.End_Sloc.Line)); + -- Adjust Scope_Ent.End_Sloc for the root node as it is + -- No_Local_Location by default. + Ob_Stats : constant Ob_Stat_Array := Obligation_Metrics (Scope_Ent.From, Scope_Ent.To); begin @@ -604,7 +613,7 @@ package body Annotations.Dynamic_Html is begin for Cur in Scope_Entities.Iterate_Children (Scope_Entities.Root) loop - Pp.Scope_Metrics := To_JSON (Cur); + Pp.Scope_Metrics := To_JSON (Cur, Is_Root => True); end loop; end Pretty_Print_Scope_Entities; diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index 4dee29910..44a112cd1 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -566,27 +566,31 @@ package body Annotations.Xml is is use Scope_Entities_Trees; - procedure Pp_Scope_Entity (Cur : Cursor); + procedure Pp_Scope_Entity (Cur : Cursor; Is_Root : Boolean := False); --------------------- -- Pp_Scope_Entity -- --------------------- - procedure Pp_Scope_Entity (Cur : Cursor) + procedure Pp_Scope_Entity (Cur : Cursor; Is_Root : Boolean := False) is Scope_Ent : constant Scope_Entity := Element (Cur); Child : Cursor := First_Child (Cur); + + File_Info : constant File_Info_Access := Get_File (File); + Line_Stats : constant Li_Stat_Array := + Line_Metrics + (File_Info, + Scope_Ent.Start_Sloc.Line, + (if Is_Root then Last_Line (File_Info) + else Scope_Ent.End_Sloc.Line)); + -- Adjust Scope_Ent.End_Sloc for the root node as it is + -- No_Local_Location by default. begin Pp.ST ("scope_metric", A ("scope_name", Scope_Ent.Name) & A ("scope_line", Img (Scope_Ent.Sloc.Line))); - Print_Coverage_Li_Stats - (Pp, - Line_Metrics - (Get_File (File), - First_Sloc (Scope_Ent.From).L.Line, - Last_Sloc (Scope_Ent.To).L.Line), - Dest_Compilation_Unit); + Print_Coverage_Li_Stats (Pp, Line_Stats, Dest_Compilation_Unit); Print_Coverage_Ob_Stats (Pp, Obligation_Metrics (Scope_Ent.From, Scope_Ent.To), @@ -600,7 +604,7 @@ package body Annotations.Xml is begin for Cur in Scope_Entities.Iterate_Children (Scope_Entities.Root) loop - Pp_Scope_Entity (Cur); + Pp_Scope_Entity (Cur, Is_Root => True); end loop; end Pretty_Print_Scope_Entities; diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index dad31a753..974689934 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -39,7 +39,7 @@ with Traces_Source; use Traces_Source; package Checkpoints is - subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 15; + subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 16; -- For compatibility with previous Gnatcov versions, the checkpoint -- file format is versioned. -- @@ -59,6 +59,7 @@ package Checkpoints is -- 13 -- Extend Files_Table.File_Info to distinguish homonym source files -- 14 -- Extend CU_Info to implement block coverage -- 15 -- Increase size of Pragma_Id after addition of 255th pragma + -- 16 -- Extend Scope_Entity to include the Start/End_Sloc of the scope -- -- Note that we always use the last version when creating a checkpoint. -- diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 7521fff47..ab913349b 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1127,13 +1127,13 @@ package body Instrument.Ada_Unit is procedure Enter_Scope (UIC : in out Ada_Unit_Inst_Context; - Sloc : Source_Location; + N : Ada_Node'Class; Decl : Basic_Decl); -- Enter a scope. This must be completed with a call to the function - -- Exit_Scope, defined below. Scope_Name is the name of the scope, which - -- is defined at location Sloc. Assume that the scope first SCO is the next - -- generated SCO (SCOs.SCO_Table.Last + 1). Update UIC.Current_Scope_Entity - -- to the created entity. + -- Exit_Scope, defined below. Assume that the scope first SCO is the next + -- generated SCO (SCOs.SCO_Table.Last + 1), and also assume that decl + -- refers to the the specification of N, to uniquely identify the scope. + -- Update UIC.Current_Scope_Entity to the created entity. procedure Exit_Scope (UIC : in out Ada_Unit_Inst_Context); -- Exit the current scope, updating UIC.Current_Scope_Entity to @@ -4414,7 +4414,7 @@ package body Instrument.Ada_Unit is Enter_Scope (UIC => UIC, - Sloc => Sloc (N), + N => N, Decl => (if Prev_Part.Is_Null then N else Prev_Part)); Start_Statement_Block (UIC); @@ -5089,7 +5089,7 @@ package body Instrument.Ada_Unit is => Enter_Scope (UIC => UIC, - Sloc => Sloc (N), + N => N, Decl => N.As_Basic_Decl); Instrument_Statement (UIC, N, @@ -5433,7 +5433,7 @@ package body Instrument.Ada_Unit is UIC.Ghost_Code := Safe_Is_Ghost (N); Enter_Scope (UIC => UIC, - Sloc => Sloc (N), + N => N, Decl => Decl); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; @@ -5465,7 +5465,7 @@ package body Instrument.Ada_Unit is UIC.Ghost_Code := Safe_Is_Ghost (N); Enter_Scope (UIC => UIC, - Sloc => Sloc (N), + N => N, Decl => N.As_Basic_Decl); UIC.MCDC_State_Inserter := Local_Inserter'Unchecked_Access; @@ -5617,7 +5617,7 @@ package body Instrument.Ada_Unit is begin Enter_Scope (UIC => UIC, - Sloc => Sloc (N), + N => N, Decl => Decl); end; @@ -6890,9 +6890,14 @@ package body Instrument.Ada_Unit is procedure Enter_Scope (UIC : in out Ada_Unit_Inst_Context; - Sloc : Source_Location; + N : Ada_Node'Class; Decl : Basic_Decl) is + function Local_Sloc + (Sloc : Source_Location) return Slocs.Local_Source_Location + is ((Line => Natural (Sloc.Line), + Column => Natural (Sloc.Column))); + Decl_SFI : constant Source_File_Index := Get_Index_From_Generic_Name (Decl.Unit.Get_Filename, @@ -6901,11 +6906,11 @@ package body Instrument.Ada_Unit is New_Scope_Ent : constant Scope_Entity := (From => SCO_Id (SCOs.SCO_Table.Last + 1), To => No_SCO_Id, + Start_Sloc => Local_Sloc (Start_Sloc (N.Sloc_Range)), + End_Sloc => Local_Sloc (End_Sloc (N.Sloc_Range)), Name => +Langkit_Support.Text.To_UTF8 (Decl.P_Defining_Name.F_Name.Text), - Sloc => - (Line => Natural (Sloc.Line), - Column => Natural (Sloc.Column)), + Sloc => Local_Sloc (Sloc (N)), Identifier => (Decl_SFI => Decl_SFI, Decl_Line => Natural (Decl.Sloc_Range.Start_Line))); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index fe861c224..4d9f5de8d 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -601,8 +601,10 @@ package body Instrument.C is New_Scope_Ent : constant Scope_Entity := (From => SCO_Id (SCOs.SCO_Table.Last + 1), To => No_SCO_Id, + Start_Sloc => (Line => 1, Column => 0), + End_Sloc => No_Local_Location, Name => +Get_Simple_Name (SFI), - Sloc => (Line => 0, Column => 0), + Sloc => (Line => 1, Column => 0), Identifier => (Decl_SFI => SFI, Decl_Line => 0)); Scope_Entity_Position : Scope_Entities_Trees.Cursor; @@ -643,6 +645,8 @@ package body Instrument.C is New_Scope_Ent : constant Scope_Entity := (From => SCO_Id (SCOs.SCO_Table.Last + 1), To => No_SCO_Id, + Start_Sloc => Sloc.L, + End_Sloc => End_Sloc (N).L, Name => +Get_Decl_Name_Str (N), Sloc => Sloc.L, Identifier => (Decl_SFI => File, Decl_Line => Sloc.L.Line)); diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 1147dcbbc..5a75c2917 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -1062,6 +1062,9 @@ package body SC_Obligations is Value.From := CLS.Read_SCO; Value.To := CLS.Read_SCO; + Value.Start_Sloc := CLS.Read_Local_Source_Location; + Value.End_Sloc := CLS.Read_Local_Source_Location; + Value.Name := CLS.Read_Unbounded_String; Value.Sloc := CLS.Read_Local_Source_Location; @@ -1841,6 +1844,9 @@ package body SC_Obligations is CSS.Write_SCO (Value.From); CSS.Write_SCO (Value.To); + CSS.Write (Value.Start_Sloc); + CSS.Write (Value.End_Sloc); + CSS.Write (Value.Name); CSS.Write (Value.Sloc); diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 2cfbe7a92..faac6ee1c 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -200,6 +200,11 @@ package SC_Obligations is -- instrumentation, From and To designate low level SCOs that are then -- converted to high level SCOs after processing the low level SCOs. + Start_Sloc, End_Sloc : Local_Source_Location; + -- Start/End_Sloc for this scope. This is more precise than the SCO + -- range as the SCO range may skip over lines with disabled coverage, + -- which we want to report on. + Name : Unbounded_String; Sloc : Local_Source_Location; -- Name (as it appears in the source) and sloc of this scope definition @@ -284,6 +289,8 @@ package SC_Obligations is No_Scope_Entity : constant Scope_Entity := (From => No_SCO_Id, To => No_SCO_Id, + Start_Sloc => No_Local_Location, + End_Sloc => No_Local_Location, Name => +"", Sloc => No_Local_Location, Identifier => No_Scope_Entity_Identifier); From ae0932c216d631443c813085e0dbcb51092f5ee2 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 5 Jul 2024 17:09:14 +0200 Subject: [PATCH 0883/1483] Fix typo --- testsuite/SUITE/tutils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 8a03628e8..cf816df06 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -872,7 +872,7 @@ def xcov( Run xcov with arguments ARGS, timeout control, valgrind control if available and enabled, output directed to OUT and failure registration if register_failure is True. Return the process status descriptor. ARGS may be - a list or a whitespace separated string. + a list or a whitespace separated strings. If AUTO_LANGUAGES is True, the gnatcov sub-command is "instrument" and the testsuite is not in qualification mode, automatically pass the From 196d39220f2b750e52112be85662a8cd647883e6 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 5 Jul 2024 17:09:41 +0200 Subject: [PATCH 0884/1483] Remove unneeded field from html report --- tools/gnatcov/annotations-dynamic_html.adb | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 988413c54..bb2e8ae30 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -629,7 +629,6 @@ package body Annotations.Dynamic_Html is is Coverage_State : constant String := (1 => State_Char (Aggregated_State (Info.all))); - Exempted : constant Boolean := Info.Exemption /= Slocs.No_Location; Mapping : constant JSON_Value := Create_Object; Line_Obj : constant JSON_Value := Create_Object; @@ -640,7 +639,6 @@ package body Annotations.Dynamic_Html is Clear (Pp.Current_Conditions); Line_Obj.Set_Field ("lineNumber", Img (Line_Num)); - Line_Obj.Set_Field ("exempted", Exempted'Img); Line_Obj.Set_Field ("src", Line); Mapping.Set_Field ("coverage", Coverage_State); From d43f22ff2a12666dc43d55ef875c51dbdebdaba8 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 9 Jul 2024 12:14:38 +0200 Subject: [PATCH 0885/1483] Modify driver behavior when using --consolidate=checkpoints When using the --consolidate=checkpoints testsuite option, the driver will systematically produce a checkpoint, and then produce coverage reports (xcov, and report) from that checkpoint, even when producing a coverage report for a single test driver. This commit is in the context of adding support for disabling coverage annotations, which will only be displayed as such when producing a report by using checkpoints. --- testsuite/SCOV/internals/driver.py | 51 ++++++++++++++++++------------ 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 417366c2a..42627594d 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -840,51 +840,62 @@ def gen_xcov_reports(self): single_driver = no_ext(self.drivers[0]) if self.singletest() else None - use_checkpoint_inputs = checkpoints and not single_driver - # We request traces as input with "@inputs.list", where the file # contains the list of traces to use, derived from the set of drivers. # We request checkpoints as inputs with "--checkpoint=@inputs.list", # where the file contains the list of checkpoints to use, derived # from the set of drivers as well: - input_opt, input_fn = ( - ("--checkpoint=", ckptname_for) - if use_checkpoint_inputs - else ("", self.mode_tracename_for) - ) - - inputs = "%s@%s" % ( - input_opt, + trace_inputs = "@%s" % ( list_to_file( [ - input_fn(os.path.join(self.awdir_for(pgm), pgm)) + self.mode_tracename_for( + os.path.join(self.awdir_for(pgm), pgm) + ) for pgm in self.programs() ], "inputs.list", ), ) + ckpt_inputs = "--checkpoint=@%s" % ( + list_to_file( + [ + ckptname_for(os.path.join(self.awdir_for(pgm), pgm)) + for pgm in self.programs() + ], + "ckpts.list", + ), + ) # Determine what command line options we'll pass to designate units of # interest and maybe produce a coverage checkpoint. We don't need and # don't want to pass SCO options when using checkpoints as inputs. - sco_options = ( - [] if use_checkpoint_inputs else self.coverage_sco_options() - ) + sco_options = [] if checkpoints else self.coverage_sco_options() - save_checkpoint_options = ( - ["--save-checkpoint=%s" % ckptname_for(single_driver)] - if single_driver and checkpoints - else [] - ) + # Produce the checkpoint if required + if checkpoints and single_driver: + save_checkpoint_options = ( + ["--save-checkpoint=%s" % ckptname_for(single_driver)] + if single_driver and checkpoints + else [] + ) + self.gen_one_xcov_report( + trace_inputs, + report_format="report", + options=self.coverage_sco_options() + + save_checkpoint_options + + ["--cancel-annotate"], + ) + + inputs = ckpt_inputs if checkpoints else trace_inputs # Now produce the --annotate=report format: self.gen_one_xcov_report( inputs, report_format="report", - options=sco_options + save_checkpoint_options + ["-o", "test.rep"], + options=sco_options + ["-o", "test.rep"], ) # Then an alternate .xcov output format, unless we are performing a From 3d5f6f145decbbb8b99919a3c9b3c892c497e032 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 9 Jul 2024 12:22:45 +0200 Subject: [PATCH 0886/1483] Merge annotations from different checkpoints This commit is in the context of introducing support for coverage disabling annotations. It is allowed to have a varying set of coverage disabling annotations for two different checkpoints, and we want to account for all of them in the resulting report. As the previous behavior was to ignore the annotations from a checkpoint if the compilation unit had already been loaded from another checkpoint, we change it to now also include the annotations from the newly loaded checkpoint. --- tools/gnatcov/sc_obligations.adb | 140 +++++++++++++++---------------- 1 file changed, 67 insertions(+), 73 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 5a75c2917..51e1d8d59 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -2059,91 +2059,84 @@ package body SC_Obligations is CP_Vectors.BDD_Vector.First_Index, CP_Vectors.BDD_Vector.Last_Index); - declare - Last_Existing_CU_Id : constant CU_Id := CU_Vector.Last_Index; + -- Remap and merge into current tables - begin - -- Remap and merge into current tables + for Cur in CP_Vectors.CU_Vector.Iterate loop + declare + use CU_Info_Vectors; - for Cur in CP_Vectors.CU_Vector.Iterate loop - declare - use CU_Info_Vectors; + CP_CU_Id : constant CU_Id := To_Index (Cur); + CP_CU : CU_Info := Element (Cur); + New_CU_Id : CU_Id := No_CU_Id; - CP_CU_Id : constant CU_Id := To_Index (Cur); - CP_CU : CU_Info := Element (Cur); - New_CU_Id : CU_Id := No_CU_Id; + -- If the CU Origin or its Main_Source files are ignored, we + -- cannot load this CU. - -- If the CU Origin or its Main_Source files are ignored, we - -- cannot load this CU. + Origin_Ignored : constant Boolean := + SFI_Ignored (Relocs, CP_CU.Origin); + Main_Source_Ignored : constant Boolean := + SFI_Ignored (Relocs, CP_CU.Main_Source); + begin + if Origin_Ignored or else Main_Source_Ignored then + SCOs_Trace.Trace + ("Ignoring CU from SID file: Id" & CP_CU_Id'Img); + + -- If we cannot load this CU *not* because its main source is + -- ignored, but rather because the origin is ignored, warn the + -- user: they probably did not want to ignore this CU, but we + -- have to in order not to break our data structure invariants: + -- Origin cannot be null. + + if not Main_Source_Ignored then + Warn + ("gnatcov limitation: ignoring unit " + & Get_Simple_Name + (Remap_SFI (Relocs, CP_CU.Main_Source)) + & " from " & (+CLS.Filename) + & " because " + & (+Get_Simple_Name (Relocs, CP_CU.Origin)) + & " is ignored"); + end if; - Origin_Ignored : constant Boolean := - SFI_Ignored (Relocs, CP_CU.Origin); - Main_Source_Ignored : constant Boolean := - SFI_Ignored (Relocs, CP_CU.Main_Source); - begin - if Origin_Ignored or else Main_Source_Ignored then - SCOs_Trace.Trace - ("Ignoring CU from SID file: Id" & CP_CU_Id'Img); - - -- If we cannot load this CU *not* because its main source - -- is ignored, but rather because the origin is ignored, - -- warn the user: they probably did not want to ignore this - -- CU, but we have to in order not to break our data - -- structure invariants: Origin cannot be null. - - if not Main_Source_Ignored then - Warn - ("gnatcov limitation: ignoring unit " - & Get_Simple_Name - (Remap_SFI (Relocs, CP_CU.Main_Source)) - & " from " & (+CLS.Filename) - & " because " - & (+Get_Simple_Name (Relocs, CP_CU.Origin)) - & " is ignored"); - end if; + Ignore_CU_Id (Relocs, CP_CU_Id); - Ignore_CU_Id (Relocs, CP_CU_Id); + else + Checkpoint_Load_Unit + (CLS, + CP_Vectors, + CP_CU, + CP_CU_Id => CP_CU_Id, + New_CU_Id => New_CU_Id); + Set_CU_Id_Map (Relocs, CP_CU_Id, New_CU_Id); + end if; + end; + end loop; - else - Checkpoint_Load_Unit - (CLS, - CP_Vectors, - CP_CU, - CP_CU_Id => CP_CU_Id, - New_CU_Id => New_CU_Id); - Set_CU_Id_Map (Relocs, CP_CU_Id, New_CU_Id); - end if; - end; - end loop; + -- Remap annotations - -- Remap annotations + for Cur in CP_Vectors.ALI_Annotations.Iterate loop + declare + use ALI_Annotation_Maps; + Annotation_Sloc : Source_Location := Key (Cur); + Annotation : ALI_Annotation := Element (Cur); - for Cur in CP_Vectors.ALI_Annotations.Iterate loop - declare - use ALI_Annotation_Maps; - Annotation_Sloc : Source_Location := Key (Cur); - Annotation : ALI_Annotation := Element (Cur); + begin + if not CU_Id_Ignored (Relocs, Annotation.CU) then - begin - if not CU_Id_Ignored (Relocs, Annotation.CU) then - -- If this annotation comes from a compilation unit whose - -- data is being imported from this checkpoint (i.e. whose - -- CU id is higher than the last existing one upon entry), - -- add it now (else it is assumed to be already present in - -- the ALI_Annotation map). + -- Even if the CU was already loaded, the set of annotations + -- can be different from one checkpoint to another (e.g. the + -- coverage disabled regions can vary), so add them in all + -- cases. - pragma Assert - (Remap_CU_Id (Relocs, Annotation.CU) /= No_CU_Id); - Annotation.CU := Remap_CU_Id (Relocs, Annotation.CU); - if Annotation.CU > Last_Existing_CU_Id then - Remap_SFI (Relocs, Annotation_Sloc.Source_File); - ALI_Annotations.Insert (Annotation_Sloc, Annotation); - end if; - end if; - end; - end loop; + pragma Assert + (Remap_CU_Id (Relocs, Annotation.CU) /= No_CU_Id); + Annotation.CU := Remap_CU_Id (Relocs, Annotation.CU); + Remap_SFI (Relocs, Annotation_Sloc.Source_File); + ALI_Annotations.Include (Annotation_Sloc, Annotation); + end if; + end; + end loop; - end; end Checkpoint_Load; ---------------------- @@ -3372,6 +3365,7 @@ package body SC_Obligations is -- An ALI file is involved: we are in binary traces mode, and so -- there is no need to compute the number of BDD execution paths for -- decisions. + Count_Paths => False); -- For the units we successfully loaded, copy annotations from the ALI From 5fbe0471bd55b8b4262f7af56fa1e8aa5c7f24dc Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 9 Jul 2024 12:11:09 +0200 Subject: [PATCH 0887/1483] Add new coverage disabling annotations This commit introduces Cov_Off / Cov_On annotation to selectively disable coverage analysis over a source code region. This is done through pragma Annotate for Ada, and comment markers for C. The disabled coverage regions are reported as D lines (for Disabled) in the various kind of reports, and have there is a dedicated section for the report format. --- testsuite/SCOV/internals/cnotes.py | 21 +- testsuite/SCOV/internals/lnexpanders.py | 2 + testsuite/SCOV/internals/rnexpanders.py | 24 +- testsuite/SCOV/internals/xnotep.py | 4 + testsuite/SCOV/minicheck.py | 2 +- .../src-traces-index.xml.expected | 12 + .../main.adb.xml.expected | 188 +++++---- .../bin-traces-index.xml.expected | 12 + .../src-traces-index.xml.expected | 15 + .../223-selective-instr/Ada/src/test_main.adb | 34 ++ .../223-selective-instr/Ada/test.opt | 1 + .../instr-cov/223-selective-instr/Ada/test.py | 16 + .../223-selective-instr/C/src/cons_a_b.txt | 12 + .../instr-cov/223-selective-instr/C/src/pkg.h | 17 + .../223-selective-instr/C/src/test_a.c | 18 + .../223-selective-instr/C/src/test_b.c | 18 + .../instr-cov/223-selective-instr/C/test.py | 23 ++ .../instr-cov/223-selective-instr/extra.opt | 1 + tools/gnatcov/ali_files.ads | 2 +- tools/gnatcov/annotations-dynamic_html.adb | 8 +- tools/gnatcov/annotations-html.adb | 2 + tools/gnatcov/annotations-report.adb | 93 +++++ tools/gnatcov/annotations-sarif.adb | 2 +- tools/gnatcov/annotations-xml.adb | 1 + tools/gnatcov/annotations.adb | 11 +- tools/gnatcov/coverage-object.adb | 13 +- tools/gnatcov/files_table.adb | 70 ++-- tools/gnatcov/files_table.ads | 14 +- tools/gnatcov/gnatcov-xml-report.xsd | 9 +- tools/gnatcov/instrument-ada_unit.adb | 41 +- tools/gnatcov/instrument-c.adb | 361 +++++++++++++----- tools/gnatcov/instrument-c.ads | 8 + tools/gnatcov/instrument-common.ads | 3 + tools/gnatcov/traces_lines.adb | 2 +- tools/gnatcov/traces_lines.ads | 6 +- 35 files changed, 845 insertions(+), 221 deletions(-) create mode 100644 testsuite/tests/instr-cov/223-selective-instr/Ada/src/test_main.adb create mode 100644 testsuite/tests/instr-cov/223-selective-instr/Ada/test.opt create mode 100644 testsuite/tests/instr-cov/223-selective-instr/Ada/test.py create mode 100644 testsuite/tests/instr-cov/223-selective-instr/C/src/cons_a_b.txt create mode 100644 testsuite/tests/instr-cov/223-selective-instr/C/src/pkg.h create mode 100644 testsuite/tests/instr-cov/223-selective-instr/C/src/test_a.c create mode 100644 testsuite/tests/instr-cov/223-selective-instr/C/src/test_b.c create mode 100644 testsuite/tests/instr-cov/223-selective-instr/C/test.py create mode 100644 testsuite/tests/instr-cov/223-selective-instr/extra.opt diff --git a/testsuite/SCOV/internals/cnotes.py b/testsuite/SCOV/internals/cnotes.py index 74f1a9353..dcbf66af2 100644 --- a/testsuite/SCOV/internals/cnotes.py +++ b/testsuite/SCOV/internals/cnotes.py @@ -93,6 +93,7 @@ # lNoCode : no code for line (=xcov) # lNotCoverable : no code but statement on line, hence not coverable (=xcov) # lUndetCov : scos present but could not determine coverage state (=xcov) +# lDisCov : coverage analysis disabled for the line (=xcov) # lFullCov : full coverage for line (=xcov) # r0 : expect empty set of violations (=report) # r0c : like r0, on a statement continuation line (=report) @@ -135,6 +136,8 @@ # xBlock1 : exempted block, >0 deviations (=report) # xBlock2 : exempted block, >0 undetermined coverage items (=report) +# dBlock : disabled block + # Transient kinds: these may be used in expectations and should always be # subject to substitution rules mapping them to other kinds. No emitted note # will ever match them. These are useful for shared drivers when the actual @@ -173,6 +176,7 @@ lPartCov, lNotCoverable, lUndetCov, + lDisCov, sNoCov, sPartCov, sNotCoverable, @@ -212,13 +216,15 @@ xBlock0, xBlock1, xBlock2, -) = range(53) + dBlock, +) = range(55) NK_image = { None: "None", lNoCode: "lNoCode", lNotCoverable: "lNotCoverable", lUndetCov: "lUndetCov", + lDisCov: "lDisCov", lFullCov: "lFullCov", lNoCov: "lNoCov", lPartCov: "lPartCov", @@ -266,6 +272,7 @@ aNoCov: "aNoCov", atNoCov: "atNoCov", acPartCov: "acPartCov", + dBlock: "dBlock", } @@ -280,6 +287,7 @@ lNoCode, lNotCoverable, lUndetCov, + lDisCov, lNoCov, lPartCov, lFullCov, @@ -330,6 +338,9 @@ XNoteKinds = XsNoteKinds + XoNoteKinds + XcNoteKinds +# Disabled coverage regions +disabledNoteKinds = (dBlock,) + # Anti-expectations rAntiKinds = (r0, r0c) @@ -341,7 +352,13 @@ # if they could be emitted and report them as unmatched. erNoteKinds = ( - sNoteKinds + dNoteKinds + cNoteKinds + xNoteKinds + tNoteKinds + XNoteKinds + sNoteKinds + + dNoteKinds + + cNoteKinds + + xNoteKinds + + tNoteKinds + + XNoteKinds + + disabledNoteKinds ) erNoteKinds += aNoteKinds xrNoteKinds = erNoteKinds + rAntiKinds + XrAntiKinds diff --git a/testsuite/SCOV/internals/lnexpanders.py b/testsuite/SCOV/internals/lnexpanders.py index 27cbccc04..279fac196 100644 --- a/testsuite/SCOV/internals/lnexpanders.py +++ b/testsuite/SCOV/internals/lnexpanders.py @@ -20,6 +20,7 @@ lNoCov, lNotCoverable, lUndetCov, + lDisCov, lx0, lx1, lx2, @@ -33,6 +34,7 @@ class LnotesExpander: ".": lNoCode, "0": lNotCoverable, "?": lUndetCov, + "D": lDisCov, "+": lFullCov, "-": lNoCov, "!": lPartCov, diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index d7414d36a..8cd26d8a0 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -44,6 +44,7 @@ XoPartCov, XoNoCov, XcPartCov, + dBlock, ) from .segments import Sloc, Sloc_from_match from .stags import Stag_from @@ -341,7 +342,7 @@ def __init__(self, re_start, re_end, re_notes): Nblock.__init__(self, re_notes=re_notes) -# VIOsection, OERsection, XREchapter, NCIchapter, SMRchapter +# VIOsection, OERsection, XREchapter, NCIchapter, SMRchapter, DCRChapter # # Leaf specializations, a set of which will be instantiated for report # processing. @@ -464,6 +465,21 @@ def check_enote(self, rline, enote): return enote +class DCRchapter(Nsection): + """Disabled Coverage Regions section.""" + + def __init__(self, re_start): + Nchapter.__init__( + self, + re_start=re_start, + re_end=r"(\d+) region[s]* with disabled coverage\.$", + re_notes={".*": dBlock}, + ) + + def re_summary(self): + return r"(\d+) region[s]* with disabled coverage\.$" + + class NCIchapter(Nchapter): """Non-coverable Items chapter.""" @@ -721,6 +737,12 @@ def __init__(self): self.noteblocks.append(OERsection(re_start="OTHER ERRORS")) + self.noteblocks.append( + DCRchapter( + re_start="COVERAGE DISABLED REGIONS", + ) + ) + # We're done with the note blocks at this point self.allblocks.extend(self.noteblocks) diff --git a/testsuite/SCOV/internals/xnotep.py b/testsuite/SCOV/internals/xnotep.py index 885025ee2..35470de3a 100644 --- a/testsuite/SCOV/internals/xnotep.py +++ b/testsuite/SCOV/internals/xnotep.py @@ -52,6 +52,7 @@ sUndetCov, dUndetCov, eUndetCov, + lDisCov, XsNoCov, XsPartCov, XsNotCoverable, @@ -66,6 +67,7 @@ aNoCov, atNoCov, acPartCov, + dBlock, ) from .segments import Line, Section, Segment from .stags import Stag_from @@ -230,6 +232,7 @@ class XnoteP: "l.": lNoCode, "l0": lNotCoverable, "l?": lUndetCov, + "lD": lDisCov, "l#": lx0, "l*": lx1, "l@": lx2, @@ -263,6 +266,7 @@ class XnoteP: "x?": xBlock2, "0": r0, "0c": r0c, + "dB": dBlock, # Exempted notes "Xs-": XsNoCov, "Xs!": XsPartCov, diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 9fc4dd968..0340e0112 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -511,7 +511,7 @@ def remove_empty_sets(data): } # Check that expected coverage data contain only supported line annotations - invalid_line_annotations = set(expected_cov) - {"+", "!", "-", "?"} + invalid_line_annotations = set(expected_cov) - {"+", "!", "-", "?", "D"} assert not invalid_line_annotations, "Invalid line annotations: {}".format( " ".join(sorted(invalid_line_annotations)) ) diff --git a/testsuite/tests/O212-062-xml/src-traces-index.xml.expected b/testsuite/tests/O212-062-xml/src-traces-index.xml.expected index d7e76c018..bd43dae9e 100644 --- a/testsuite/tests/O212-062-xml/src-traces-index.xml.expected +++ b/testsuite/tests/O212-062-xml/src-traces-index.xml.expected @@ -14,6 +14,7 @@ + @@ -23,6 +24,7 @@ + @@ -34,6 +36,7 @@ + @@ -45,6 +48,7 @@ + @@ -56,6 +60,7 @@ + @@ -67,6 +72,7 @@ + @@ -78,6 +84,7 @@ + @@ -87,6 +94,7 @@ + @@ -98,6 +106,7 @@ + @@ -109,6 +118,7 @@ + @@ -120,6 +130,7 @@ + @@ -131,6 +142,7 @@ + diff --git a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected index da608bc35..8b71fbe1a 100644 --- a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected +++ b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected @@ -9,6 +9,7 @@ + @@ -18,6 +19,7 @@ + @@ -29,6 +31,7 @@ + @@ -40,6 +43,7 @@ + @@ -51,6 +55,7 @@ + @@ -60,6 +65,7 @@ + @@ -71,6 +77,7 @@ + @@ -82,6 +89,7 @@ + @@ -95,6 +103,7 @@ + @@ -104,6 +113,7 @@ + @@ -115,6 +125,7 @@ + @@ -126,6 +137,7 @@ + @@ -137,6 +149,7 @@ + @@ -146,6 +159,7 @@ + @@ -157,6 +171,7 @@ + @@ -168,6 +183,7 @@ + @@ -183,6 +199,7 @@ + @@ -192,6 +209,7 @@ + @@ -203,6 +221,7 @@ + @@ -214,6 +233,7 @@ + @@ -225,6 +245,7 @@ + @@ -234,6 +255,7 @@ + @@ -245,6 +267,7 @@ + @@ -256,6 +279,7 @@ + @@ -271,6 +295,7 @@ + @@ -280,6 +305,7 @@ + @@ -291,6 +317,7 @@ + @@ -302,19 +329,21 @@ + - - + + + @@ -324,6 +353,7 @@ + @@ -335,6 +365,7 @@ + @@ -346,6 +377,7 @@ + @@ -359,6 +391,7 @@ + @@ -368,6 +401,7 @@ + @@ -379,6 +413,7 @@ + @@ -390,6 +425,7 @@ + @@ -398,56 +434,56 @@ - + - + - + - + - + - + - + - + @@ -462,35 +498,35 @@ - + - + - + - + - + @@ -504,28 +540,28 @@ - + - + - + - + @@ -540,42 +576,42 @@ - + - + - + - + - + - + @@ -611,28 +647,28 @@ - + - + - + - + @@ -646,28 +682,28 @@ - + - + - + - + @@ -681,7 +717,7 @@ - + @@ -695,42 +731,42 @@ - + - + - + - + - + - + @@ -744,7 +780,7 @@ - + @@ -758,28 +794,28 @@ - + - + - + - + @@ -800,56 +836,56 @@ - + - + - + - + - + - + - + - + @@ -863,7 +899,7 @@ - + @@ -877,28 +913,28 @@ - + - + - + - + @@ -912,14 +948,14 @@ - + - + @@ -933,28 +969,28 @@ - + - + - + - + @@ -968,7 +1004,7 @@ - + @@ -982,7 +1018,7 @@ - + @@ -996,7 +1032,7 @@ - + @@ -1010,7 +1046,7 @@ - + @@ -1024,21 +1060,21 @@ - + - + - + @@ -1052,7 +1088,7 @@ - + @@ -1066,7 +1102,7 @@ - + @@ -1080,7 +1116,7 @@ - + @@ -1094,14 +1130,14 @@ - + - + diff --git a/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected b/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected index 126080317..c0182c86b 100644 --- a/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected +++ b/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected @@ -14,6 +14,7 @@ + @@ -23,6 +24,7 @@ + @@ -34,6 +36,7 @@ + @@ -45,6 +48,7 @@ + @@ -54,6 +58,7 @@ + @@ -65,6 +70,7 @@ + @@ -78,6 +84,7 @@ + @@ -87,6 +94,7 @@ + @@ -98,6 +106,7 @@ + @@ -111,6 +120,7 @@ + @@ -120,6 +130,7 @@ + @@ -131,6 +142,7 @@ + diff --git a/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected b/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected index a05a70554..58e08d1e2 100644 --- a/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected +++ b/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected @@ -14,6 +14,7 @@ + @@ -23,6 +24,7 @@ + @@ -34,6 +36,7 @@ + @@ -45,6 +48,7 @@ + @@ -54,6 +58,7 @@ + @@ -65,6 +70,7 @@ + @@ -78,6 +84,7 @@ + @@ -87,6 +94,7 @@ + @@ -98,6 +106,7 @@ +
@@ -111,6 +120,7 @@ + @@ -120,6 +130,7 @@ + @@ -131,6 +142,7 @@ + @@ -144,6 +156,7 @@ + @@ -153,6 +166,7 @@ + @@ -164,6 +178,7 @@ + diff --git a/testsuite/tests/instr-cov/223-selective-instr/Ada/src/test_main.adb b/testsuite/tests/instr-cov/223-selective-instr/Ada/src/test_main.adb new file mode 100644 index 000000000..5b668492e --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/Ada/src/test_main.adb @@ -0,0 +1,34 @@ +procedure Test_Main +is + A, B : Boolean := True; + + procedure Foo (B: Boolean) is null; -- # cov_on + + procedure Uncovered; + + procedure Uncovered is + begin + pragma Annotate (Xcov, Cov_Off); -- # cov_off + Foo (A and then B); -- # cov_off + pragma Annotate (Xcov, Cov_On); -- # cov_off + end Uncovered; + +begin + pragma Annotate (Xcov, Cov_Off); -- # cov_off + Foo (A and then B); -- # cov_off + pragma Annotate (Xcov, Cov_On); -- # cov_off + + -- Check with a justification message + + pragma Annotate (Xcov, Cov_Off, "coverage is disabled"); -- # cov_off + Foo (A and then B); -- # cov_off + pragma Annotate (Xcov, Cov_On); -- # cov_off + + Foo (A and then B); -- # partial_cov_on +end Test_Main; + +--# test_main.adb +-- +-- /cov_off/ lD ## 0 +-- /cov_on/ l+ ## 0 +-- /partial_cov_on/ l! ## eF- diff --git a/testsuite/tests/instr-cov/223-selective-instr/Ada/test.opt b/testsuite/tests/instr-cov/223-selective-instr/Ada/test.opt new file mode 100644 index 000000000..374349458 --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/Ada/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD GNAT 5.04a1 rejects unrecognized annotation pragmas diff --git a/testsuite/tests/instr-cov/223-selective-instr/Ada/test.py b/testsuite/tests/instr-cov/223-selective-instr/Ada/test.py new file mode 100644 index 000000000..a041d027f --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/Ada/test.py @@ -0,0 +1,16 @@ +""" +Check gnatcov support for selective instrumentation for Ada. +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT +from SCOV.tc import TestCase + +TestCase( + category=CAT.mcdc, + tolerate_messages=( + r".* No justification given for disabled coverage region" + ), +).run() + +thistest.result() diff --git a/testsuite/tests/instr-cov/223-selective-instr/C/src/cons_a_b.txt b/testsuite/tests/instr-cov/223-selective-instr/C/src/cons_a_b.txt new file mode 100644 index 000000000..b78b04823 --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/C/src/cons_a_b.txt @@ -0,0 +1,12 @@ +drivers=. + +--# pkg.h +-- /cov-off-a/ lD ## dB +-- /cov-off-b/ lD ## dB +-- /cov-on/ l- ## s- +-- +--# test_a.c +-- /covered/ l+ ## 0 +-- +--# test_b.c +-- /covered/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/223-selective-instr/C/src/pkg.h b/testsuite/tests/instr-cov/223-selective-instr/C/src/pkg.h new file mode 100644 index 000000000..4ae5d7891 --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/C/src/pkg.h @@ -0,0 +1,17 @@ +int +foo (int a, int b) +{ +#ifdef A + /* GNATCOV_COV_OFF */ // # cov-off-a + int c = a && b; // # cov-off-a + /* GNATCOV_COV_ON */ // # cov-off-a +#endif + +#ifdef B + /* GNATCOV_COV_OFF */ // # cov-off-b + int d = a && b; // # cov-off-b + /* GNATCOV_COV_ON */ // # cov-off-b +#endif + + return 0; // # cov-on +} diff --git a/testsuite/tests/instr-cov/223-selective-instr/C/src/test_a.c b/testsuite/tests/instr-cov/223-selective-instr/C/src/test_a.c new file mode 100644 index 000000000..667f196fe --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/C/src/test_a.c @@ -0,0 +1,18 @@ +#define A + +#include "pkg.h" + +int +main () +{ + return 0; // # covered +} + +//# pkg.h +// +// /cov-off-a/ lD ## dB +// /cov-on/ l- ## s- +// +//# test_a.c +// +// /covered/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/223-selective-instr/C/src/test_b.c b/testsuite/tests/instr-cov/223-selective-instr/C/src/test_b.c new file mode 100644 index 000000000..d81a99966 --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/C/src/test_b.c @@ -0,0 +1,18 @@ +#define B 1 + +#include "pkg.h" + +int +main () +{ + return 0; // # covered +} + +//# pkg.h +// +// /cov-off-b/ lD ## dB +// /cov-on/ l- ## s- +// +//# test_b.c +// +// /covered/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/223-selective-instr/C/test.py b/testsuite/tests/instr-cov/223-selective-instr/C/test.py new file mode 100644 index 000000000..fbc1d1794 --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/C/test.py @@ -0,0 +1,23 @@ +""" +Check gnatcov support for selective instrumentation for C when a file has +various preprocessing configuration resulting in varying preprocessed versions, +and the user has disabled coverage for every code region differing across +preprocessing invocations. + +Note that in this case, the user must use checkpoint consolidation, as there +can only exists one version of the SIDs at a time. +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT +from SCOV.tc import TestCase + +thistest.options.consolidate = "checkpoints" +TestCase( + category=CAT.mcdc, + tolerate_messages=( + r".* No justification given for disabled coverage region" + ), +).run() + +thistest.result() diff --git a/testsuite/tests/instr-cov/223-selective-instr/extra.opt b/testsuite/tests/instr-cov/223-selective-instr/extra.opt new file mode 100644 index 000000000..ea8a3c8ac --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific feature diff --git a/tools/gnatcov/ali_files.ads b/tools/gnatcov/ali_files.ads index 4164d8a29..33417d5c6 100644 --- a/tools/gnatcov/ali_files.ads +++ b/tools/gnatcov/ali_files.ads @@ -37,7 +37,7 @@ package ALI_Files is pragma Suppress (Tampering_Check); type ALI_Annotation_Kind is - (Exempt_On, Exempt_Off, Dump_Buffers, Reset_Buffers); + (Exempt_On, Exempt_Off, Dump_Buffers, Reset_Buffers, Cov_On, Cov_Off); type ALI_Annotation is record CU : CU_Id; diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index bb2e8ae30..299ee9472 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -411,6 +411,8 @@ package body Annotations.Dynamic_Html is Line_Stats.Set_Field ("notCoverable", Info.Li_Stats (Not_Coverable)); Line_Stats.Set_Field ("undeterminedCoverage", Info.Li_Stats (Undetermined_Coverage)); + Line_Stats.Set_Field + ("disabledCoverage", Info.Li_Stats (Disabled_Coverage)); Line_Stats.Set_Field ("exemptedNoViolation", Info.Li_Stats (Exempted_No_Violation)); Line_Stats.Set_Field @@ -567,8 +569,9 @@ package body Annotations.Dynamic_Html is Is_Root : Boolean := False) return JSON_Value; -- Convert a scope entity to a JSON scoped metric: compute line and -- obligation statistics for the given scope and recursively for - -- child scopes. Store the result as a JSON object, with the name and - -- the line of the scope. + -- child scopes. Is_Root indicates whether the given Cur is the root + -- scope. Store the result as a JSON object, with the name and the line + -- of the scope. ------------- -- To_JSON -- @@ -998,6 +1001,7 @@ package body Annotations.Dynamic_Html is Set_If_Not_Null ("notCovered", Stats (Not_Covered)); Set_If_Not_Null ("notCoverable", Stats (Not_Coverable)); Set_If_Not_Null ("undeterminedCoverage", Stats (Undetermined_Coverage)); + Set_If_Not_Null ("disabledCoverage", Stats (Disabled_Coverage)); Set_If_Not_Null ("exemptedNoViolation", Stats (Exempted_No_Violation)); Set_If_Not_Null ("exemptedWithViolation", Stats (Exempted_With_Violation)); diff --git a/tools/gnatcov/annotations-html.adb b/tools/gnatcov/annotations-html.adb index e4c8dbe18..38e68d16a 100644 --- a/tools/gnatcov/annotations-html.adb +++ b/tools/gnatcov/annotations-html.adb @@ -680,6 +680,8 @@ package body Annotations.Html is Wrh (Pp, "exempted, undetermined coverage item present"); when Exempted_No_Violation => Wrh (Pp, "exempted, no violation"); + when Disabled_Coverage => + Wrh (Pp, "coverage disabled"); end case; if Pp.Show_Line_Details then diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 782086007..dd0e5a5b3 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -103,6 +103,9 @@ package body Annotations.Report is Exemption : Slocs.Source_Location := Slocs.No_Location; -- Exemption sloc applying to current line, if any + Disabled_Cov : Slocs.Source_Location := Slocs.No_Location; + -- Disabled coverage sloc applying to current line, if any + Nonexempted_Messages : Messages_Array; -- All output messages, classified by section according to relevant -- coverage level. @@ -284,9 +287,14 @@ package body Annotations.Report is Total_Exempted_Regions : Natural; Total_Exempted_Violations : Natural := 0; + Total_Disabled_Cov_Regions : Natural; + function Has_Exempted_Region return Boolean; -- True iff there's at least one exempted region + function Has_Disabled_Cov_Region return Boolean; + -- True iff there's at least one region with disabled coverage + procedure Messages_For_Section (MC : Report_Section; Title : String; @@ -303,6 +311,9 @@ package body Annotations.Report is procedure Output_Exemption (C : Cursor); -- Show summary information for exemption denoted by C + procedure Output_Disable_Cov (C : Cursor); + -- Show summary information for disabled coverage regions + procedure Count_SCO (SCO : SCO_Id); -- Account for SCO in the coverage tally @@ -357,6 +368,22 @@ package body Annotations.Report is return False; end Has_Exempted_Region; + ---------------------------- + -- Has_Disable_Cov_Region -- + ---------------------------- + + function Has_Disabled_Cov_Region return Boolean is + C : Cursor := ALI_Annotations.First; + begin + while Has_Element (C) loop + if Element (C).Kind = Cov_Off then + return True; + end if; + Next (C); + end loop; + return False; + end Has_Disabled_Cov_Region; + Non_Exempted_Str : constant String := "non-exempted "; Non_Exempted : String renames Non_Exempted_Str (Non_Exempted_Str'First .. @@ -504,6 +531,51 @@ package body Annotations.Report is Total_Exempted_Regions := Total_Exempted_Regions + 1; end Output_Exemption; + ------------------------ + -- Output_Disable_Cov -- + ------------------------ + + procedure Output_Disable_Cov (C : Cursor) is + E : constant ALI_Annotation := Element (C); + Next_C : constant Cursor := Next (C); + Sloc : constant Source_Location := Key (C); + End_Sloc : Source_Location := Slocs.No_Location; + begin + if E.Kind /= Cov_Off then + return; + end if; + + -- Determine end sloc of disabled coverage region + + if Next_C /= No_Element then + declare + Next_Sloc : constant Source_Location := Key (Next_C); + Next_E : constant ALI_Annotation := Element (Next_C); + begin + if Next_E.Kind = Cov_On + and then Sloc.Source_File = Next_Sloc.Source_File + then + End_Sloc := Next_Sloc; + end if; + end; + end if; + + -- Output summary for this region + + New_Line (Output.all); + Put (Output.all, Image (To_Range (Sloc, End_Sloc))); + if End_Sloc = Slocs.No_Location then + Put (Output.all, "-"); + end if; + Put_Line (Output.all, ", justification:"); + if E.Message /= null then + Put_Line (Output.all, E.Message.all); + else + Put_Line (Output.all, "No justification"); + end if; + Total_Disabled_Cov_Regions := Total_Disabled_Cov_Regions + 1; + end Output_Disable_Cov; + -------------------------- -- Messages_For_Section -- -------------------------- @@ -702,6 +774,18 @@ package body Annotations.Report is & "."); end if; + if Has_Disabled_Cov_Region then + Pp.Chapter ("COVERAGE DISABLED REGIONS"); + Total_Disabled_Cov_Regions := 0; + ALI_Annotations.Iterate (Output_Disable_Cov'Access); + + New_Line (Output.all); + Put_Line + (Output.all, + Pluralize (Total_Disabled_Cov_Regions, "region") + & " with disabled coverage."); + end if; + Pp.Chapter ("ANALYSIS SUMMARY"); New_Line (Output.all); @@ -719,6 +803,14 @@ package body Annotations.Report is & "."); end if; + if Has_Disabled_Cov_Region then + New_Line (Output.all); + Put_Line + (Output.all, + Pluralize (Total_Disabled_Cov_Regions, "region") + & " with disabled coverage."); + end if; + if Pp.Dump_Units then Pp.Chapter ("UNITS OF INTEREST"); New_Line (Output.all); @@ -751,6 +843,7 @@ package body Annotations.Report is pragma Unreferenced (Line_Num, Line); begin Pp.Exemption := Info.Exemption; + Pp.Disabled_Cov := Info.Disabled_Cov; end Pretty_Print_Start_Line; -------------------------- diff --git a/tools/gnatcov/annotations-sarif.adb b/tools/gnatcov/annotations-sarif.adb index d28a648b1..3126c7dde 100644 --- a/tools/gnatcov/annotations-sarif.adb +++ b/tools/gnatcov/annotations-sarif.adb @@ -31,7 +31,7 @@ package body Annotations.Sarif is type Result_Info is record Is_Violation : Boolean; - -- True if is a violation, False if undetermined coverage + -- True if is a violation, False if undetermined/disabled coverage Is_Exempted : Boolean; -- True is the violation is in an exempted region diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index 44a112cd1..f103b5eae 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -938,6 +938,7 @@ package body Annotations.Xml is Stats (Exempted_With_Violation)); Print_Metric_Ratio ("exempted_undetermined_coverage", Stats (Exempted_With_Undetermined_Cov)); + Print_Metric_Ratio ("disabled_coverage", Stats (Disabled_Coverage)); end Print_Coverage_Stats; diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index f773394c4..957889bf4 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -88,6 +88,10 @@ package body Annotations is end if; end if; + if Info.Disabled_Cov /= Slocs.No_Location then + return Disabled_Coverage; + end if; + -- Non-exempted case for J in Info.State'Range loop @@ -428,7 +432,8 @@ package body Annotations is return; end if; - Populate_Exemptions (File_Index); + Populate_Annotations (File_Index, Exemption); + Populate_Annotations (File_Index, Disable_Coverage); ST := Scope_Traversal (Comp_Unit (File_Index)); Iterate_On_Lines (FI, Compute_Line_State'Access); @@ -934,7 +939,9 @@ package body Annotations is -- Update counts. Note that No_Code lines are always counted as -- No_Code even if they are part of an exempted region. - if LI.State = Line_States'(others => No_Code) then + if S = Disabled_Coverage then + Result (S) := Result (S) + 1; + elsif LI.State = Line_States'(others => No_Code) then Result (No_Code) := Result (No_Code) + 1; else Result (S) := Result (S) + 1; diff --git a/tools/gnatcov/coverage-object.adb b/tools/gnatcov/coverage-object.adb index 8474a18a6..9d355e9e4 100644 --- a/tools/gnatcov/coverage-object.adb +++ b/tools/gnatcov/coverage-object.adb @@ -251,8 +251,17 @@ package body Coverage.Object is -- when not using source traces. raise Program_Error with - "Undetermined_Coverage line state reserved for source" - & " coverage"; + "Undetermined_Coverage line state reserved for source" + & " coverage"; + + when Disabled_Coverage => + + -- Line can't be marked as disabled coverage line state when not + -- using source traces. + + raise Program_Error with + "Disabled_Coverage line state reserved for source" + & " coverage"; end case; end Update_Line_State; diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index ee5ea458b..1fb9fb5f5 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -1706,11 +1706,14 @@ package body Files_Table is end if; end Sloc_To_SCO_Map; - ------------------------- - -- Populate_Exemptions -- - ------------------------- + -------------------------- + -- Populate_Annotations -- + -------------------------- - procedure Populate_Exemptions (FI : Source_File_Index) is + procedure Populate_Annotations + (FI : Source_File_Index; + Kind : ALI_Region_Annotation_Kind) + is use ALI_Annotation_Maps; Info : File_Info renames Files_Table (FI).all; @@ -1727,6 +1730,11 @@ package body Files_Table is Current_Annot_Sloc : Source_Location; Current_Annotation : ALI_Annotation; + Start_Annotation : constant ALI_Annotation_Kind := + (case Kind is + when Exemption => Exempt_On, + when Disable_Coverage => Cov_Off); + function Annotation_In_File (Cur : Cursor) return Boolean is (Has_Element (Cur) and then Key (Cur).Source_File = FI); -- Returns whether the annotation represented by Cur is in the same file @@ -1752,47 +1760,53 @@ package body Files_Table is return; end if; - -- Iterate on all the lines and mark those in an active exemption + -- Iterate on all the lines and mark those in an active annotated -- region. -- -- The complexity in the loop bellow stems from two factors to keep in -- mind when reading the code: - -- - Exemption annotations do not always have a corresponding SCO, - -- this is currently always true for Ada sources, but always false + -- - Annotations do not always have a corresponding SCO, this is + -- currently always true for Ada sources, but always false -- for C sources. - -- - We cannot expect an Exempt_On annotation to be followed by an - -- Exempt_Off annotation: there could be multiple annotations of the - -- same kind back to back, or we could very well have a lone annoation - -- in a file. + -- - We cannot expect a annotation to be followed by an end annotation: + -- there could be multiple annotations of the same kind back to back, + -- or we could very well have a lone annotation in a file. loop - -- If we are in an active exemption region but have reached the end - -- of the registered lines, allocate lines until the next exemption - -- annotation of this file. If there is no next annotation in the - -- file, simply exit the loop. + -- If we are in an active annotated region but have reached the end + -- of the registered lines, allocate lines until the next annotation + -- of this file. If there is no next annotation in the file, simply + -- exit the loop. -- - -- This implies that if the last annotation of a file is Exempt_On, - -- all the lines starting at the annotation until the last line with - -- a SCO will be marked as exempted. We can't go up to the actual end - -- of the file because we don't have the actual number of lines of - -- the file. In practice this is ok because the lines that we won't - -- process are lines without SCOs in them. + -- This implies that if the last annotation of a file is a start + -- annotation, all the lines starting at the annotation until the + -- last line with a SCO will be annotated. We can't go up to the + -- actual end of the file because we don't have the actual number of + -- lines of the file. In practice this is ok because the lines that + -- we won't process are lines without SCOs in them. if Current_Line_Num > Last_Line_Num then exit when not - (Current_Annotation.Kind = Exempt_On + (Current_Annotation.Kind = Start_Annotation and then Annotation_In_File (Next_Annot_Cur)); Last_Line_Num := Key (Next_Annot_Cur).L.Line; Expand_Line_Table (FI, Last_Line_Num); end if; - -- Annotate lines when we are in an active exemption region, + -- Annotate lines when we are in an active annotated region, -- otherwise skip lines until the next annotation if it exists, or -- exit the loop if there is no more annotations. - if Current_Annotation.Kind = Exempt_On then - Info.Lines.Element - (Current_Line_Num).all.Exemption := Current_Annot_Sloc; + if Current_Annotation.Kind = Start_Annotation then + case Kind is + when Exemption => + Info.Lines.Element + (Current_Line_Num).all.Exemption := Current_Annot_Sloc; + + when Disable_Coverage => + Info.Lines.Element + (Current_Line_Num).all.Disabled_Cov := Current_Annot_Sloc; + end case; else exit when not Annotation_In_File (Next_Annot_Cur); Current_Line_Num := Key (Next_Annot_Cur).L.Line; @@ -1802,7 +1816,7 @@ package body Files_Table is and then Current_Line_Num = Key (Next_Annot_Cur).L.Line then -- We do not bump the line number here so that lines corresponding - -- to an exempt_on or exempt_off are processed twice, one for each + -- to the start / end annotation are processed twice, one for each -- kind of annotation, and thus end up in the annotated region. Annotation_Cur := Next_Annot_Cur; @@ -1814,7 +1828,7 @@ package body Files_Table is Current_Line_Num := Current_Line_Num + 1; end if; end loop; - end Populate_Exemptions; + end Populate_Annotations; ---------------- -- To_Display -- diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index b4fbd5f82..397fd12c0 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -295,6 +295,10 @@ package Files_Table is -- If this line is covered by an exemption, this is set to the sloc of -- the Exempt_On annotation. + Disabled_Cov : Source_Location := Slocs.No_Location; + -- If this line is covered by a coverage disabling annotation, this is + -- set to the sloc of the Cov_Off annotation. + Is_Multistatement : Tristate := Unknown; -- Whether there are more than one statement SCO on this line, or -- Unknown if not computed yet. @@ -508,9 +512,13 @@ package Files_Table is -- Get line info (or text) at File:Index (or at Sloc) - procedure Populate_Exemptions (FI : Source_File_Index); - -- Fill the Exemption field in the Line_Info records of FI based on the - -- information in Annotation_Map. + type ALI_Region_Annotation_Kind is (Exemption, Disable_Coverage); + + procedure Populate_Annotations + (FI : Source_File_Index; + Kind : ALI_Region_Annotation_Kind); + -- Fill the Exemption/Disabled_Cov field according to Kind in the Line_Info + -- records of FI based on the information in Annotation_Map. function Writeable_Sloc_To_SCO_Map (Index : Source_File_Index; diff --git a/tools/gnatcov/gnatcov-xml-report.xsd b/tools/gnatcov/gnatcov-xml-report.xsd index 12e01007d..4cb5b7f6e 100644 --- a/tools/gnatcov/gnatcov-xml-report.xsd +++ b/tools/gnatcov/gnatcov-xml-report.xsd @@ -68,7 +68,7 @@ + minOccurs="9" maxOccurs="9"/> + @@ -99,7 +100,7 @@ + minOccurs="9" maxOccurs="9"/> @@ -107,7 +108,7 @@ + minOccurs="9" maxOccurs="9"/> @@ -150,7 +151,7 @@ + minOccurs="9" maxOccurs="9"/> @@ -3649,16 +3652,27 @@ package body Instrument.Ada_Unit is -- arguments expected for that kind. case Result.Kind is - when Exempt_On => + when Exempt_On | Cov_Off => -- Expected formats: - -- * (Xcov, Exempt_On) - -- * (Xcov, Exempt_On, "Justification") + -- * (Xcov, ) + -- * (Xcov, , "Justification") + if Result.Kind = Cov_Off then + UIC.Disable_Coverage := True; + end if; case Nb_Children is when 2 => - Report - (N, "No justification given for exempted region", Warning); + if Result.Kind = Exempt_On then + Report + (N, "No justification given for exempted region", + Warning); + elsif Result.Kind = Cov_Off then + Report + (N, + "No justification given for disabled coverage region", + Warning); + end if; UIC.Annotations.Append (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); @@ -3696,9 +3710,18 @@ package body Instrument.Ada_Unit is (N, "At most 2 pragma arguments allowed", Warning); return; end if; + UIC.Annotations.Append + (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); + when Cov_On => + if Nb_Children > 2 then + Report + (N, "At most 2 pragma arguments allowed", Warning); + return; + end if; + UIC.Disable_Coverage := False; UIC.Annotations.Append - (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); + (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); when Dump_Buffers => @@ -4229,7 +4252,7 @@ package body Instrument.Ada_Unit is -- There is nothing else to do if we gave up instrumenting this -- subprogram. - if UIC.Disable_Instrumentation then + if UIC.Disable_Instrumentation or else UIC.Disable_Coverage then UIC.Disable_Instrumentation := Save_Disable_Instrumentation; return; end if; @@ -6298,7 +6321,7 @@ package body Instrument.Ada_Unit is -- Start of processing for Process_Decisions begin - if N.Is_Null then + if N.Is_Null or else UIC.Disable_Coverage then return; end if; Hash_Entries.Init; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 4d9f5de8d..5a738bfb6 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -99,12 +99,11 @@ package body Instrument.C is -- temporary file. procedure Preprocess_Source - (Filename : String; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc; - PP_Filename : out Unbounded_String; - Options : in out Analysis_Options; - Keep_Comments : Boolean := False); + (Filename : String; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; + PP_Filename : out Unbounded_String; + Options : in out Analysis_Options); -- Preprocess the source at Filename and extend Options using the Prj and -- the preprocessor output to retrieve standard search paths. -- @@ -354,6 +353,33 @@ package body Instrument.C is -- -- and now we have valid, and correctly instrumented code. + ---------------------------------------- + -- Processing of coverage annotations -- + ---------------------------------------- + + type Start_Or_End is (Start_Annotation, End_Annotation); + + procedure Search_Annotation_Couple + (UIC : in out C_Unit_Inst_Context; + Start_Matcher, End_Matcher : String; + Process : + access procedure (Kind : Start_Or_End; + Line : String; + Match : Match_Array; + Sloc : Source_Location_T)); + -- Search for the annotation couple in the source. Call Process for every + -- found annotation. + + procedure Populate_Annotations (UIC : in out C_Unit_Inst_Context); + -- Look for exemption / disabling coverage markers in the source code and + -- fill UIC.Annotations (and also UIC.Disable_Cov_Regions for disabling + -- coverage markers) accordingly. + + function Is_Disabled_Region + (UIC : C_Unit_Inst_Context'Class; Sloc : Source_Location) return Boolean; + -- Whether coverage is disabled (by GNATCOV_COV_OFF/ON comment markers) + -- for the given Sloc. + ---------------------------- -- Source level rewriting -- ---------------------------- @@ -978,6 +1004,10 @@ package body Instrument.C is Pragma_Aspect_Name : Name_Id := Namet.No_Name) is begin + if UIC.Disable_Coverage then + return; + end if; + -- Insert a new entry to the UIC.Instrumented_Entities maps: even if -- this SOI does not possess instrumented SCOs (it can be the case if -- all of the code constructs are not instrumentable), we want an empty @@ -1940,6 +1970,10 @@ package body Instrument.C is end Process_Decisions; begin + if UIC.Disable_Coverage then + return; + end if; + Process_Decisions (UIC, N, T); Visit (N, Process_Lambda_Expr'Access); end Process_Expression; @@ -2097,11 +2131,15 @@ package body Instrument.C is Save_Disable_Instrumentation : constant Boolean := UIC.Disable_Instrumentation; + Save_Disable_Coverage : constant Boolean := + UIC.Disable_Coverage; begin if Curlify (N) then Append (Trailing_Braces, '}'); end if; + UIC.Disable_Coverage := Is_Disabled_Region (UIC, Start_Sloc (N)); + -- If this statement does not belong to a source of interest, skip -- it altogether. @@ -2361,6 +2399,7 @@ package body Instrument.C is end if; end case; + UIC.Disable_Coverage := Save_Disable_Coverage; Append (Trailing_Braces, TB); end Traverse_One; @@ -2390,7 +2429,7 @@ package body Instrument.C is -- statement source location range. begin - if Is_Null (N) then + if Is_Null (N) or else UIC.Disable_Coverage then return; end if; @@ -2710,12 +2749,11 @@ package body Instrument.C is ----------------------- procedure Preprocess_Source - (Filename : String; - Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc; - PP_Filename : out Unbounded_String; - Options : in out Analysis_Options; - Keep_Comments : Boolean := False) + (Filename : String; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : Prj_Desc; + PP_Filename : out Unbounded_String; + Options : in out Analysis_Options) is Cmd : Command_Type; -- The command to preprocess the file @@ -2752,14 +2790,15 @@ package body Instrument.C is (Command => Prj.Compiler_Driver (Instrumenter.Language), others => <>); - if Keep_Comments then - Append_Arg (Cmd, "-C"); - end if; - -- Add the preprocessing flag Append_Arg (Cmd, "-E"); + -- Keep the code comments as they may contain exemption / coverage + -- disabling markers. + + Append_Arg (Cmd, "-C"); + -- Add all of the compiler / compiler driver options to the -- preprocessing command line. @@ -3007,6 +3046,193 @@ package body Instrument.C is end if; end Finalize; + ------------------------------ + -- Search_Annotation_Couple -- + ------------------------------ + + procedure Search_Annotation_Couple + (UIC : in out C_Unit_Inst_Context; + Start_Matcher, End_Matcher : String; + Process : + access procedure (Kind : Start_Or_End; + Line : String; + Match : Match_Array; + Sloc : Source_Location_T)) + is + Start_Matcher_Pattern : constant Pattern_Matcher := + Compile (Start_Matcher); + End_Matcher_Pattern : constant Pattern_Matcher := + Compile (End_Matcher); + + Match_Res : Match_Array (0 .. 1); + -- The maximal number of parenthesized groups is one (for the "exempt + -- on" marker). + + procedure Search_Matcher_In_Token (Token : Token_T); + + ---------------------------- + -- Search_Matcher_In_Token -- + ---------------------------- + + procedure Search_Matcher_In_Token (Token : Token_T) + is + Token_Str : constant String := Get_Token_Spelling (UIC.TU, Token); + pragma Unreferenced (Token_Str); + begin + if Get_Token_Kind (Token) = Token_Comment then + declare + Comment : constant String := Get_Token_Spelling (UIC.TU, Token); + begin + Match (Start_Matcher_Pattern, Comment, Match_Res); + if Match_Res (0) /= No_Match then + Process.all + (Kind => Start_Annotation, + Line => Comment, + Match => Match_Res, + Sloc => Get_Token_Location (UIC.TU, Token)); + end if; + Match (End_Matcher_Pattern, Comment, Match_Res); + if Match_Res (0) /= No_Match then + Process.all + (Kind => End_Annotation, + Line => Comment, + Match => Match_Res, + Sloc => Get_Token_Location (UIC.TU, Token)); + end if; + end; + end if; + end Search_Matcher_In_Token; + begin + Iterate_Tokens + (UIC.TU, + Get_Translation_Unit_Cursor (UIC.TU), + Search_Matcher_In_Token'Access); + end Search_Annotation_Couple; + + -------------------------- + -- Populate_Annotations -- + -------------------------- + + procedure Populate_Annotations (UIC : in out C_Unit_Inst_Context) + is + procedure Process_Exemption + (Kind : Start_Or_End; + Line : String; + Match : Match_Array; + Source_Loc : Source_Location_T); + -- Process an exemption marker (GNATCOV_EXEMPT_ON/OFF) + + Last_Cov_Off : Source_Location_T; + -- Location of the last found GNATCOV_COV_OFF marker + + procedure Process_Disable_Cov + (Kind : Start_Or_End; + Line : String; + Match : Match_Array; + Source_Loc : Source_Location_T); + -- Process a marker disabling coverage (GNATCOV_COV_ON/OFF) + + ----------------------- + -- Process_Exemption -- + ----------------------- + + procedure Process_Exemption + (Kind : Start_Or_End; + Line : String; + Match : Match_Array; + Source_Loc : Source_Location_T) + is + Ann : ALI_Annotation; + begin + if Kind = Start_Annotation then + Ann.Kind := Exempt_On; + + -- Check if there is a justification message + + if Match (1).First /= 0 then + Ann.Message := + new String'(Line (Match (1).First .. Match (1).Last)); + end if; + else + Ann.Kind := Exempt_Off; + end if; + UIC.Annotations.Append + (Annotation_Couple'(Sloc (Source_Loc), Ann)); + end Process_Exemption; + + ------------------------- + -- Process_Disable_Cov -- + ------------------------- + + procedure Process_Disable_Cov + (Kind : Start_Or_End; + Line : String; + Match : Match_Array; + Source_Loc : Source_Location_T) + is + Ann : ALI_Annotation; + begin + if Kind = Start_Annotation then + Last_Cov_Off := Source_Loc; + Ann.Kind := Cov_Off; + + -- Check if there is a justification message + + if Match (1).First /= 0 then + Ann.Message := + new String'(Line (Match (1).First .. Match (1).Last)); + end if; + else + -- Add an entry into UIC.Disable_Cov_Regions + + declare + First_Sloc : constant Source_Location := + Sloc (Last_Cov_Off); + Last_Sloc : constant Source_Location := + Sloc (Source_Loc); + begin + UIC.Disable_Cov_Regions.Append + (Source_Location_Range' + (Source_File => First_Sloc.Source_File, + L => + (First_Sloc => First_Sloc.L, + Last_Sloc => Last_Sloc.L))); + Last_Cov_Off := Get_Null_Location; + Ann.Kind := Cov_On; + end; + end if; + UIC.Annotations.Append + (Annotation_Couple'(Sloc (Source_Loc), Ann)); + end Process_Disable_Cov; + begin + Search_Annotation_Couple + (UIC => UIC, + Start_Matcher => "GNATCOV_EXEMPT_ON(:? ""(.*)"")?", + End_Matcher => "GNATCOV_EXEMPT_OFF", + Process => Process_Exemption'Access); + Search_Annotation_Couple + (UIC => UIC, + Start_Matcher => "GNATCOV_COV_OFF(:? ""(.*)"")?", + End_Matcher => "GNATCOV_COV_ON", + Process => Process_Disable_Cov'Access); + end Populate_Annotations; + + ------------------------ + -- Is_Disabled_Region -- + ------------------------ + + function Is_Disabled_Region + (UIC : C_Unit_Inst_Context'Class; Sloc : Source_Location) return Boolean + is + begin + for Disabled_Region of UIC.Disable_Cov_Regions loop + if In_Range (Sloc, Disabled_Region) then + return True; + end if; + end loop; + return False; + end Is_Disabled_Region; + -------------------- -- Record_PP_Info -- -------------------- @@ -3016,10 +3242,15 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context; Instrumenter : C_Family_Instrumenter_Type'Class) is - Args : String_Vectors.Vector; + UIC_Copy : C_Unit_Inst_Context := UIC; + -- We need to use a copy of the original instrumentation context to + -- avoid overwriting UIC.CIdx which already contains the preprocessed + -- version of the file at this stage. + + Args : String_Vectors.Vector; begin - UIC.Pass := Record_PP_Info_Pass'Access; - UIC.CIdx := + UIC_Copy.Pass := Record_PP_Info_Pass'Access; + UIC_Copy.CIdx := Create_Index (Exclude_Declarations_From_PCH => 0, Display_Diagnostics => 0); @@ -3052,9 +3283,9 @@ package body Instrument.C is declare C_Args : chars_ptr_array := To_Chars_Ptr_Array (Args); begin - UIC.TU := + UIC_Copy.TU := Parse_Translation_Unit - (C_Idx => UIC.CIdx, + (C_Idx => UIC_Copy.CIdx, Source_Filename => Orig_Filename, Command_Line_Args => C_Args'Address, Num_Command_Line_Args => C_Args'Length, @@ -3064,8 +3295,12 @@ package body Instrument.C is Free (C_Args); end; Traverse_Declarations - (UIC => UIC, - L => Get_Children (Get_Translation_Unit_Cursor (UIC.TU))); + (UIC => UIC_Copy, + L => Get_Children (Get_Translation_Unit_Cursor (UIC_Copy.TU))); + + -- Save into UIC the preprocessing information + + UIC.LL_PP_Info_Map := UIC_Copy.LL_PP_Info_Map; end Record_PP_Info; @@ -3161,62 +3396,25 @@ package body Instrument.C is Preprocess_Source (Orig_Filename, Self, Prj, PP_Filename, UIC.Options); - -- Start by recording preprocessing information + -- Parse the preprocessed version of the file - Record_PP_Info (Orig_Filename, UIC, Self); - - -- Then record exemption annotations in the comments. Reuse the TU from - -- the preprocessing information recording pass as we want the - -- annotations to refer to unpreprocessed locations. + Start_Rewriting + (Self => Rewriter, + Filename => +PP_Filename, + Instrumenter => Self, + Prj => Prj); + UIC.TU := Rewriter.TU; + UIC.Rewriter := Rewriter.Rewriter; - Search_Exemptions : - declare - Start_Matcher : constant Pattern_Matcher := - Compile ("GNATCOV_EXEMPT_ON ""(.*)"""); - End_Matcher : constant Pattern_Matcher := - Compile ("GNATCOV_EXEMPT_OFF"); - Match_Res : Match_Array (0 .. 1); + -- Start by recording exemption / coverage disabling markers. Use the + -- translation unit resulting from the preprocessed version of the file + -- as we want to take into account indications in headers. - procedure Search_Exempt_In_Token (Token : Token_T); + Populate_Annotations (UIC); - ---------------------------- - -- Search_Exempt_In_Token -- - ---------------------------- + -- Record preprocessing information - procedure Search_Exempt_In_Token (Token : Token_T) is - begin - if Get_Token_Kind (Token) = Token_Comment then - declare - Comment : constant String := - Get_Token_Spelling (UIC.TU, Token); - Ann : ALI_Annotation; - begin - Match (Start_Matcher, Comment, Match_Res); - if Match_Res (1) /= No_Match then - Ann.Kind := Exempt_On; - Ann.Message := - new String' - (Comment (Match_Res (1).First .. Match_Res (1).Last)); - UIC.Annotations.Append - ((Sloc (Get_Token_Location (UIC.TU, Token)), Ann)); - end if; - Match (End_Matcher, Comment, Match_Res); - if Match_Res (0) /= No_Match then - Ann.Kind := Exempt_Off; - UIC.Annotations.Append - ((Sloc - (Get_Range_End (Get_Token_Extent (UIC.TU, Token))), - Ann)); - end if; - end; - end if; - end Search_Exempt_In_Token; - begin - Iterate_Tokens - (UIC.TU, - Get_Translation_Unit_Cursor (UIC.TU), - Search_Exempt_In_Token'Access); - end Search_Exemptions; + Record_PP_Info (Orig_Filename, UIC, Self); -- Save the last SCO of the first pass (for a consistency check with -- the second pass later), and reset the SCO tables for the @@ -3229,13 +3427,6 @@ package body Instrument.C is UIC.Pass := Instrument_Pass'Access; - Start_Rewriting - (Self => Rewriter, - Filename => +PP_Filename, - Instrumenter => Self, - Prj => Prj); - UIC.TU := Rewriter.TU; - UIC.Rewriter := Rewriter.Rewriter; Insert_Extern_Location := Start_Sloc (Get_Translation_Unit_Cursor (UIC.TU)); @@ -4025,11 +4216,7 @@ package body Instrument.C is C_Family_Instrumenter_Type'Class (Self).Extern_Prefix; begin - -- Preprocess the source, keeping the comment to look for the manual - -- dump indication later. - - Preprocess_Source - (Orig_Filename, Self, Prj, PP_Filename, Options, True); + Preprocess_Source (Orig_Filename, Self, Prj, PP_Filename, Options); declare use Files_Handling.File_To_String_Vectors_Maps; Cur : Cursor; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 89a47743f..7938b5dd4 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -347,6 +347,9 @@ package Instrument.C is -- root of each tree is the scope corresponding to the file itself in which -- all its scopes are stored. + package Sloc_Range_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, Element_Type => Source_Location_Range); + type C_Unit_Inst_Context is new Instrument.Common.Unit_Inst_Context with record TU : Translation_Unit_T; @@ -404,6 +407,11 @@ package Instrument.C is Block_Stack : Block_Vectors.Vector; -- Currently processed blocks (blocks can nest in the source, -- when e.g. we have a lambda expression). + + Disable_Cov_Regions : Sloc_Range_Vectors.Vector; + -- List of regions where coverage is disabled, as delimited + -- by GNATCOV_COV_OFF/ON markers. + end record; type C_Source_Rewriter is tagged limited private; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 915d98fb3..1e2672dde 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -352,6 +352,9 @@ package Instrument.Common is -- Set to True to deactivate instrumentation and prevent any code -- rewriting. + Disable_Coverage : Boolean := False; + -- Set to True to deactivate instrumentation and SCO emissions + Non_Instr_LL_SCOs : SCO_Sets.Set; -- Set of low level SCO ids that were not instrumented diff --git a/tools/gnatcov/traces_lines.adb b/tools/gnatcov/traces_lines.adb index c9896c893..e57c866ff 100644 --- a/tools/gnatcov/traces_lines.adb +++ b/tools/gnatcov/traces_lines.adb @@ -61,7 +61,7 @@ package body Traces_Lines is when Not_Covered => return Line_State'Min (L, Partially_Covered); - when Partially_Covered => + when Partially_Covered | Disabled_Coverage => return R; when Covered => diff --git a/tools/gnatcov/traces_lines.ads b/tools/gnatcov/traces_lines.ads index 9c707755c..a774b9e17 100644 --- a/tools/gnatcov/traces_lines.ads +++ b/tools/gnatcov/traces_lines.ads @@ -43,6 +43,9 @@ package Traces_Lines is -- Code present but coverage assessment impossible (for instance code -- not instrumented). + Disabled_Coverage, + -- Coverage analysis was disabled for this line + Exempted_With_Violation, -- Exempted line in an exemption block that has a violation @@ -59,7 +62,7 @@ package Traces_Lines is ); subtype Line_State is Any_Line_State - range Not_Covered .. Undetermined_Coverage; + range Not_Covered .. Disabled_Coverage; -- Non-exempted line state type State_Char_Array is array (Any_Line_State) of Character; @@ -74,6 +77,7 @@ private (No_Code => '.', Not_Coverable => '0', Undetermined_Coverage => '?', + Disabled_Coverage => 'D', Not_Covered => '-', Partially_Covered => '!', Covered => '+', From 608969c8de953679b759c7e8aa72cf054a63b32e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 9 Jul 2024 12:20:50 +0200 Subject: [PATCH 0888/1483] Typo / cosmetic / rewording fixes --- testsuite/SCOV/internals/driver.py | 2 +- testsuite/SCOV/internals/rnexpanders.py | 4 ++-- testsuite/SCOV/internals/xnotep.py | 2 +- tools/gnatcov/checkpoints.ads | 8 ++++---- tools/gnatcov/command_line.ads | 6 +++--- tools/gnatcov/instrument-c.adb | 1 + tools/gnatcov/instrument-checkpoints.adb | 4 ++-- 7 files changed, 14 insertions(+), 13 deletions(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 42627594d..42b5eb415 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -270,7 +270,7 @@ def try_sat_over(self, ekind, xn): # Note that we only check for section inclusions here, so don't # validate the correctness of exemption justifications at this stage. - # Ensuring that an emitted note is not used to satify multiple + # Ensuring that an emitted note is not used to satisfy multiple # expectations is stricter so the most correct in principle. for en in self.edict[ekind]: diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index 8cd26d8a0..2c69d91ee 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -260,7 +260,7 @@ def try_parse_enote(self, rline): stag=None, ) - # Fetch and remove a possible separation tag from the diganostic + # Fetch and remove a possible separation tag from the diagnostic # text. Removal is useful to facilitate matching of other parts, hence # attempted first. @@ -417,7 +417,7 @@ def check_exempted_summary(self, sec, p): # to be checked for discharging expected notes later on. However # we still need to check the number of notes belonging to the exempted # region itself and the number of notes for exempted violations - # separatly. + # separately. ecount = len(self.enotes) - self.ecount_exempted self.__check_summary_count(sec, self.value(p.group(1)), ecount) diff --git a/testsuite/SCOV/internals/xnotep.py b/testsuite/SCOV/internals/xnotep.py index 35470de3a..a439161bc 100644 --- a/testsuite/SCOV/internals/xnotep.py +++ b/testsuite/SCOV/internals/xnotep.py @@ -81,7 +81,7 @@ class _XnoteP_block: """ - Block notes are relevant for a general section. Eventhough the block is + Block notes are relevant for a general section. Even though the block is matched line by line, we need to materialize a single note for the whole block. """ diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 974689934..031c8617e 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -19,10 +19,10 @@ -- This unit controls the generation and processing of coverage state -- checkpoint files for incremental coverage. -with Ada.Containers; use Ada.Containers; +with Ada.Containers; use Ada.Containers; with Ada.Containers.Multiway_Trees; with Ada.Containers.Vectors; -with Ada.Streams; use Ada.Streams; +with Ada.Streams; use Ada.Streams; with Interfaces; with GNAT.Regexp; @@ -233,8 +233,8 @@ package Checkpoints is -- the current run. procedure Remap_SFI - (Relocs : Checkpoint_Relocations; - CP_SFI : in out Source_File_Index) with + (Relocs : Checkpoint_Relocations; + CP_SFI : in out Source_File_Index) with Pre => not SFI_Ignored (Relocs, CP_SFI); -- Remap one source file index. -- diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 5bef9a100..fc82d4271 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -575,9 +575,9 @@ package Command_Line is Opt_Cancel_Annotate => Create (Long_Name => "--cancel-annotate", Help => "Prevent gnatcov from generating a coverage report if" - & "one was requested by --annotate. This option requires" - & " --save-checkpoint to also be specified on the" - & "command line.", + & " one was requested by --annotate. This option" + & " requires --save-checkpoint to also be specified on" + & " the command line.", Commands => (Cmd_Coverage => True, others => False), Internal => True), diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 5a738bfb6..c4761cbb9 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2576,6 +2576,7 @@ package body Instrument.C is -- Only traverse the function declarations that belong to a unit of -- interest. + if Is_Source_Of_Interest (UIC, N) then Cursor_Kind := Kind (N); case Cursor_Kind is diff --git a/tools/gnatcov/instrument-checkpoints.adb b/tools/gnatcov/instrument-checkpoints.adb index b99e27772..832ee6c9c 100644 --- a/tools/gnatcov/instrument-checkpoints.adb +++ b/tools/gnatcov/instrument-checkpoints.adb @@ -124,8 +124,8 @@ package body Instrument.Checkpoints is elsif CP_PP_Cmds.Reference (CP_Cur) /= PP_Cmds.Reference (Cur) then - Warn ("inconsistent information for instrumented file " - & Get_Full_Name (SFI)); + Warn ("inconsistent preprocessing information for" + & " instrumented file " & Get_Full_Name (SFI)); end if; end; end if; From 152114bd45deceb98ee3537603ba663b34196795 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 9 Jul 2024 12:21:34 +0200 Subject: [PATCH 0889/1483] xml report: remove exempted field This field is redundant with the contents of the "coverage" field (which will vary if the line was exempted). --- tools/gnatcov/annotations-xml.adb | 4 +--- tools/gnatcov/gnatcov-xml-report.xsd | 1 - 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index f103b5eae..afa2f53ed 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -630,14 +630,12 @@ package body Annotations.Xml is Line : String) is Coverage_State : constant String := - (1 => State_Char (Aggregated_State (Info.all))); - Exempted : constant Boolean := Info.Exemption /= Slocs.No_Location; + (1 => State_Char (Aggregated_State (Info.all))); begin Pp.ST ("src_mapping", A ("coverage", Coverage_State)); Pp.ST ("src"); Pp.T ("line", A ("num", Img (Line_Num)) - & A ("exempted", Exempted'Img) & A ("src", Line)); Pp.ET ("src"); end Pretty_Print_Start_Line; diff --git a/tools/gnatcov/gnatcov-xml-report.xsd b/tools/gnatcov/gnatcov-xml-report.xsd index 4cb5b7f6e..b0c98ca7c 100644 --- a/tools/gnatcov/gnatcov-xml-report.xsd +++ b/tools/gnatcov/gnatcov-xml-report.xsd @@ -219,7 +219,6 @@ - From 4c1d45eb81bfd3b97d766956704adf4eccbf4ce3 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 17 Jul 2024 10:36:00 +0200 Subject: [PATCH 0890/1483] Introduce fingerprint for annotations Introduce fingerprint for annotations in source traces and checkpoints / SIDs to forbid the processing of a trace with a SID that has a different set of annotations than the SID that was produced at instrumentation time. --- testsuite/SUITE/srctracelib.py | 21 +- .../223-selective-instr/unsupported/pkg.c | 15 + .../223-selective-instr/unsupported/pkg.h | 1 + .../223-selective-instr/unsupported/test.c | 8 + .../223-selective-instr/unsupported/test.py | 74 ++ tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads | 5 + .../ada-rts/gnatcov_rts-traces-output.adb | 4 +- tools/gnatcov/ada-rts/gnatcov_rts-traces.ads | 10 +- tools/gnatcov/ada-rts/gnatcov_rts.ads | 3 +- tools/gnatcov/ali_files.adb | 700 -------------- tools/gnatcov/ali_files.ads | 109 --- tools/gnatcov/annotations-report.adb | 6 +- tools/gnatcov/annotations.adb | 68 +- tools/gnatcov/annotations.ads | 12 - tools/gnatcov/checkpoints.adb | 24 + tools/gnatcov/checkpoints.ads | 8 + tools/gnatcov/coverage-source.adb | 18 +- tools/gnatcov/coverage-source.ads | 15 +- tools/gnatcov/files_table.adb | 5 +- tools/gnatcov/gnatcov_bits_specific.adb | 3 +- tools/gnatcov/instrument-ada_unit.adb | 6 +- tools/gnatcov/instrument-c.adb | 32 +- tools/gnatcov/instrument-common.adb | 7 +- tools/gnatcov/instrument-common.ads | 8 +- tools/gnatcov/instrument-input_traces.adb | 45 +- tools/gnatcov/instrument-input_traces.ads | 15 +- tools/gnatcov/rts/gnatcov_rts-buffers.ads | 1 + tools/gnatcov/rts/gnatcov_rts.ads | 3 +- tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 5 + .../gnatcov/rts/gnatcov_rts_c-traces-output.c | 4 +- tools/gnatcov/rts/gnatcov_rts_c-traces.h | 12 +- tools/gnatcov/sc_obligations.adb | 888 ++++++++++++++++-- tools/gnatcov/sc_obligations.ads | 84 ++ tools/gnatcov/traces_source.ads | 33 +- 34 files changed, 1220 insertions(+), 1032 deletions(-) create mode 100644 testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.c create mode 100644 testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.h create mode 100644 testsuite/tests/instr-cov/223-selective-instr/unsupported/test.c create mode 100644 testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py delete mode 100644 tools/gnatcov/ali_files.adb delete mode 100644 tools/gnatcov/ali_files.ads diff --git a/testsuite/SUITE/srctracelib.py b/testsuite/SUITE/srctracelib.py index 9f0b39847..47feaa33e 100755 --- a/testsuite/SUITE/srctracelib.py +++ b/testsuite/SUITE/srctracelib.py @@ -40,7 +40,8 @@ ("bit_buffer_encoding", "B"), ("fingerprint", "20B"), ("bit_maps_fingerprint", "20B"), - ("padding", "5B"), + ("annotations_fingerprint", "20B"), + ("padding", "B"), ) @@ -94,7 +95,7 @@ class SrcTraceFile(object): MAGIC = b"GNATcov source trace file" + b"\x00" * 7 - FORMAT_VERSION = 3 + FORMAT_VERSION = 4 ENDIANITY_NAMES = { 0: "little-endian", @@ -200,13 +201,19 @@ def format_buffer(b): print("") for e in self.entries: print( - " Unit {} ({}, SCOS hash={}, bit maps hash={})".format( + ( + " Unit {} ({}, SCOS hash={}, bit maps hash={}, " + " annotations hash={})" + ).format( e.unit_name, e.unit_part, "".join("{:02x}".format(b) for b in e.fingerprint), "".join( "{:02x}".format(b) for b in e.bit_maps_fingerprint ), + "".join( + "{:02x}".format(b) for b in e.annotations_fingerprint + ), ) ) print(" Stmt buffer: {}".format(format_buffer(e.stmt_buffer))) @@ -295,6 +302,7 @@ def __init__( unit_name, fingerprint, bit_maps_fingerprint, + annotations_fingerprint, stmt_buffer, dc_buffer, mcdc_buffer, @@ -304,6 +312,7 @@ def __init__( self.unit_name = unit_name self.fingerprint = fingerprint self.bit_maps_fingerprint = bit_maps_fingerprint + self.annotations_fingerprint = annotations_fingerprint self.stmt_buffer = stmt_buffer self.dc_buffer = dc_buffer self.mcdc_buffer = mcdc_buffer @@ -322,7 +331,7 @@ def read(cls, fp, trace_file, big_endian): language = cls.LANGUAGE_NAMES[header["language"]] - if header["padding"] != (0, 0, 0, 0, 0): + if header["padding"] != 0: raise ValueError( "Invalid padding: {}".format(header["padding"]) ) @@ -361,6 +370,7 @@ def read(cls, fp, trace_file, big_endian): unit_name, header["fingerprint"], header["bit_maps_fingerprint"], + header["annotations_fingerprint"], stmt_buffer, dc_buffer, mcdc_buffer, @@ -382,7 +392,8 @@ def write(self, fp, big_endian, alignment): ], "fingerprint": self.fingerprint, "bit_maps_fingerprint": self.bit_maps_fingerprint, - "padding": (0, 0, 0, 0, 0), + "annotations_fingerprint": self.annotations_fingerprint, + "padding": 0, }, big_endian=big_endian, ) diff --git a/testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.c b/testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.c new file mode 100644 index 000000000..bcba1958e --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.c @@ -0,0 +1,15 @@ +int +foo () +{ +#ifdef A + /* GNATCOV_COV_OFF */ + return 0; +/* GNATCOV_COV_ON */ +#endif +#ifdef B + /* GNATCOV_COV_OFF */ + return 1; +/* GNATCOV_COV_ON */ +#endif + return 2; +} diff --git a/testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.h b/testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.h new file mode 100644 index 000000000..f8f1dde0b --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/unsupported/pkg.h @@ -0,0 +1 @@ +extern int foo (); diff --git a/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.c b/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.c new file mode 100644 index 000000000..14eebbdb7 --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.c @@ -0,0 +1,8 @@ +#include "pkg.h" + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py b/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py new file mode 100644 index 000000000..d09f37329 --- /dev/null +++ b/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py @@ -0,0 +1,74 @@ +""" +Check that gnatcov correctly detects annotation inconsistencies, e.g. when the +user tries to produce a report from a source trace resulting from the +instrumentation of a program with annotations that are not the same as the +current source instrumentation data. +""" + +import os.path + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + +Wdir("tmp_") + +# Generate the root project +root_project = gprfor(srcdirs=[os.path.join("..")], mains=["test.c"]) + +# Configure the build with -DA which results in the inclusion of an annotated +# region at pkg.c from line 3 to line 6. +build_and_run( + gprsw=GPRswitches(root_project), + covlevel="stmt", + mains=["test"], + extra_instr_args=[ + "--c-opts=-DA", + "--dump-filename-simple", + "--dump-filename-prefix=a", + ], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="main-end", +) + +# Configure the build with -DB which results in the inclusion of an annotated +# region at pkg.c from line 8 to line 11, thus differing from the above. +cov_args = build_and_run( + gprsw=GPRswitches(root_project), + covlevel="stmt", + mains=["test"], + extra_instr_args=[ + "--c-opts=-DB", + "--dump-filename-simple", + "--dump-filename-prefix=b", + ], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="main-end", +) + +# Now, try to generate a coverage report from both traces. +xcov(cov_args + ["a.srctrace", "b.srctrace"], out="cov.out") + +# Check that gnatcov warns about inconsistency between a.srctrace and the +# source instrumentation data. +thistest.fail_if_no_match( + "'gnatcov coverage' output", + r"warning: traces for .* are inconsistent with the corresponding Source" + " Instrumentation Data", + contents_of("cov.out"), +) + +# Check that the coverage report is as expected (e.g. a.srctrace is skipped). +check_xcov_reports( + "xcov", + { + "test.c.xcov": {"+": {6, 7}}, + "pkg.c.xcov": {"D": {10, 11, 12}, "-": {14}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads index e2938b027..df7631497 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads @@ -104,6 +104,11 @@ package GNATcov_RTS.Buffers is -- be able to interpret buffer bits from a source traces using buffer -- bit mappings from SID files. + Annotations_Fingerprint : Fingerprint_Type; + -- Hash of annotations for this unit, as gnatcov computes it (see + -- SC_Obligations). Used as a fast way to check that source traces and + -- coverage data are consistent. + Statement, Decision, MCDC : System.Address; -- Addresses of coverage buffers for statement obligations, decision -- obligations and MC/DC obligations. The address refer to diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb index d8b3a0d3a..83e40180d 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb @@ -205,7 +205,9 @@ package body GNATcov_RTS.Traces.Output is Write_U8 (Output, Unsigned_8 (LSB_First_Bytes)); Write_Bytes (Output, To_Uint8_Array (Buffers.Fingerprint)); Write_Bytes (Output, To_Uint8_Array (Buffers.Bit_Maps_Fingerprint)); - Write_Bytes (Output, (1 .. 5 => 0)); + Write_Bytes + (Output, To_Uint8_Array (Buffers.Annotations_Fingerprint)); + Write_Bytes (Output, (1 .. 1 => 0)); -- Write the unit name diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads index 56bab68e7..1f73839f8 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads @@ -51,13 +51,14 @@ package GNATcov_RTS.Traces is -- trace entries start and end on byte/half word/word/long word boundaries. type Trace_File_Format_Version is new Unsigned_32; - Current_Version : Trace_File_Format_Version := 3; + Current_Version : Trace_File_Format_Version := 4; -- Expected value of the Trace_File_Header.Format_Version field. -- -- 0 -- initial version -- 1 -- extend trace entry model to account for C files -- 2 -- introduce fingerprints for bit maps -- 3 -- remove the project name from trace entries + -- 4 -- introduce fingerprints for annotations type Any_Alignment is new Unsigned_8; subtype Supported_Alignment is Any_Alignment; @@ -235,7 +236,12 @@ package GNATcov_RTS.Traces is -- be able to interpret buffer bits from a source traces using buffer -- bit mappings from SID files. - Padding : Uint8_Array (1 .. 5); + Annotations_Fingerprint : Fingerprint_Type; + -- Hash of annotations for this unit, as gnatcov computes it (see + -- SC_Obligations). Used as a fast way to check that source traces and + -- coverage data are consistent. + + Padding : Uint8_Array (1 .. 1); -- Padding used only to make the size of this trace entry header a -- multiple of 8 bytes. Must be zero. end record; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts.ads b/tools/gnatcov/ada-rts/gnatcov_rts.ads index 0265d9b4d..ca00975fe 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts.ads @@ -39,7 +39,7 @@ package GNATcov_RTS is package Std renames Standard; package Sys renames System; - Version : constant := 7; + Version : constant := 8; -- For compatibility with the GNATcoverage in use, GNATcov_RTS is -- versioned. -- @@ -51,5 +51,6 @@ package GNATcov_RTS is -- the associated Witness function. -- 6 -- buffer clear mechanism and trace filename indices -- 7 -- enable inlining of witness subprograms + -- 8 -- introduce fingerprint for annotations end GNATcov_RTS; diff --git a/tools/gnatcov/ali_files.adb b/tools/gnatcov/ali_files.adb deleted file mode 100644 index 164c6fcb9..000000000 --- a/tools/gnatcov/ali_files.adb +++ /dev/null @@ -1,700 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- 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.Characters.Handling; use Ada.Characters.Handling; -with Ada.Text_IO; use Ada.Text_IO; - -with GNAT.Regpat; use GNAT.Regpat; -with SCOs; - -with Checkpoints; use Checkpoints; -with Diagnostics; use Diagnostics; -with Files_Table; use Files_Table; -with Get_SCOs; -with Inputs; use Inputs; -with Outputs; use Outputs; -with Strings; use Strings; - -package body ALI_Files is - - use all type Unbounded_String; - - procedure Read - (CLS : in out Checkpoint_Load_State; Value : out ALI_Annotation); - -- Read a ALI_Annotation from CLS - - procedure Write - (CSS : in out Checkpoint_Save_State; Value : ALI_Annotation); - -- Write a ALI_Annotation to CSS - - ----------------------------------------------- - -- Regular expressions for ALI files parsing -- - ----------------------------------------------- - - D_Regexp : constant String := "(([^""\t ]+)|(""([^""]|"""")+""))[\t ]"; - D_Matcher : constant Pattern_Matcher := Compile (D_Regexp); - - N_Regexp : constant String := - "A([0-9]*):([0-9]*)(:[^ ]*)? xcov ([^ ]*)( ""(.*)"")?"; - N_Matcher : constant Pattern_Matcher := Compile (N_Regexp); - - U_Regexp : constant String := "^[^\t ]*[\t ]+([^\t ]*)"; - U_Matcher : constant Pattern_Matcher := Compile (U_Regexp); - - V_Regexp : constant String := "^V ""(.*)""$"; - V_Matcher : constant Pattern_Matcher := Compile (V_Regexp); - - function Unquote (Filename : String) return String; - -- If needed, unquote a filename, such as the ones that can be found on D - -- lines. - - procedure Mark_Ignored_Units - (Ignored_Source_Files : access GNAT.Regexp.Regexp; - Deps : SFI_Vector); - -- Mark SCOs.SCO_Unit_Table entries to be ignored by setting their Dep_Num - -- to Missing_Dep_Num. - - ------------- - -- Unquote -- - ------------- - - function Unquote (Filename : String) return String is - Result : Unbounded_String; - In_Quote : Boolean := False; - -- True when we just met a double quote inside a quoted filename. False - -- otherwise. - - begin - if Filename (Filename'First) /= '"' then - return Filename; - else - -- To unquote, just copy the string removing consecutive double - -- quotes. - - for C of Filename (Filename'First + 1 .. Filename'Last - 1) loop - if C = '"' then - if not In_Quote then - Append (Result, C); - end if; - In_Quote := not In_Quote; - else - Append (Result, C); - end if; - end loop; - return +Result; - end if; - end Unquote; - - ------------------------ - -- Mark_Ignored_Units -- - ------------------------ - - procedure Mark_Ignored_Units - (Ignored_Source_Files : access GNAT.Regexp.Regexp; - Deps : SFI_Vector) - is - use SCOs; - Deps_Present : constant Boolean := not Deps.Is_Empty; - begin - if Ignored_Source_Files = null then - return; - end if; - - for J in SCO_Unit_Table.First + 1 .. SCO_Unit_Table.Last loop - declare - U : SCO_Unit_Table_Entry renames SCO_Unit_Table.Table (J); - - SFI : constant Source_File_Index := - (if Deps_Present - then Deps.Element (U.Dep_Num) - else Get_Index_From_Generic_Name - (U.File_Name.all, Source_File)); - -- Source file corresponding to this unit. Use the name from the - -- SCO "C" line if there are no list of dependencies ("D" lines, - -- missing for old GLI files for C). - - Match_Name : constant String := Get_Simple_Name (SFI); - -- Name to use for matching against the pattern of ignored files - begin - -- In case we got SFI from the Deps vector, make sure it is - -- considered as a source file. - - Consolidate_File_Kind (SFI, Source_File); - - -- Do the ignored file matching itself - - if GNAT.Regexp.Match (Match_Name, Ignored_Source_Files.all) then - Consolidate_Ignore_Status (SFI, Always); - U.Dep_Num := Missing_Dep_Num; - else - Consolidate_Ignore_Status (SFI, Never); - end if; - end; - end loop; - end Mark_Ignored_Units; - - -------------- - -- Load_ALI -- - -------------- - - procedure Load_ALI (ALI_Filename : String) is - Discard_ALI : Source_File_Index; - Discard_Units, Discard_Deps : SFI_Vector; - - pragma Unreferenced (Discard_ALI); - pragma Warnings (Off, Discard_Units); - pragma Warnings (Off, Discard_Deps); - - begin - Discard_ALI := - Load_ALI (ALI_Filename => ALI_Filename, - Ignored_Source_Files => null, - Units => Discard_Units, - Deps => Discard_Deps, - ALI_Annotations => ALI_Annotations, - With_SCOs => False); - end Load_ALI; - - -------------- - -- Load_ALI -- - -------------- - - function Load_ALI - (ALI_Filename : String; - Ignored_Source_Files : access GNAT.Regexp.Regexp; - Units : out SFI_Vector; - Deps : out SFI_Vector; - ALI_Annotations : in out ALI_Annotation_Maps.Map; - With_SCOs : Boolean) return Source_File_Index - is - ALI_File : File_Type; - ALI_Index : Source_File_Index; - - Line : String_Access; - Index : Natural; - - Matches : Match_Array (0 .. 10); - -- For regex matching - - function Match (Index : Integer) return String; - -- Return Index'th match in Line - - function Get_Stripped_Line (F : File_Type) return String; - -- Like Get_Line but strip trailing CR, to allow for processing Windows - -- LI files on a UNIX host. - - function Getc return Character; - -- Consume and return next character from Line. - -- Load next line if at end of line. Return ^Z if at end of file. - - function Nextc return Character; - -- Peek at next character in Line. Return ^Z if at end of file. - - procedure Skipc; - -- Skip one character in Line - - function Check_Message (M1, M2 : String_Access) return Boolean; - -- Return True if either M1 or M2 is null or designates an empty string, - -- else return True if M1 and M2 designate identical strings. - - ------------------- - -- Check_Message -- - ------------------- - - function Check_Message (M1, M2 : String_Access) return Boolean is - begin - return False - or else M1 = null or else M1.all = "" - or else M2 = null or else M2.all = "" - or else M1.all = M2.all; - end Check_Message; - - ---------- - -- Getc -- - ---------- - - function Getc return Character is - Next_Char : constant Character := Nextc; - begin - Index := Index + 1; - if Index > Line'Last + 1 then - - -- Note: normally we should just read the next line from ALI_File - -- and reset Index. However some older versions of the compiler - -- generated duplicated SCOs in some cases, so if we get two - -- successive identical lines, we ignore them and keep reading. - - while not End_Of_File (ALI_File) loop - declare - Next_Line : constant String := Get_Stripped_Line (ALI_File); - begin - if Next_Line = Line.all then - Report - ("ignoring duplicate line in ALI file " - & ALI_Filename, Kind => Warning); - - else - Free (Line); - Line := new String'(Next_Line); - Index := 1; - - exit; - end if; - end; - end loop; - end if; - return Next_Char; - end Getc; - - ----------------------- - -- Get_Stripped_Line -- - ----------------------- - - function Get_Stripped_Line (F : File_Type) return String is - Line : constant String := Get_Line (F); - Last : Integer := Line'Last; - begin - if Last in Line'Range and then Line (Last) = ASCII.CR then - Last := Last - 1; - end if; - return Line (Line'First .. Last); - end Get_Stripped_Line; - - ----------- - -- Match -- - ----------- - - function Match (Index : Integer) return String is - begin - if Matches (Index) = No_Match then - return ""; - else - return Line (Matches (Index).First .. Matches (Index).Last); - end if; - end Match; - - ----------- - -- Nextc -- - ----------- - - function Nextc return Character is - begin - if Index = Line'Last + 1 then - return ASCII.LF; - - elsif Index in Line'Range then - return Line (Index); - - else - return Character'Val (16#1a#); - end if; - end Nextc; - - ----------- - -- Skipc -- - ----------- - - procedure Skipc is - C : Character; - pragma Unreferenced (C); - begin - C := Getc; - end Skipc; - - procedure Get_SCOs_From_ALI is new Get_SCOs; - - -- Local variables - - No_Object : Boolean := False; - -- Set True if the P line contains the NO flag - - Preserve_Control_Flow_Seen : Boolean := False; - -- Set True if unit has been compiled with -fpreserve-control-flow - - Dump_SCOs_Seen : Boolean := False; - -- Set True if unit has been compiled with -fdump-scos (or -gnateS) - - Debug_Seen : Boolean := False; - -- Set True if unit has been compiled with -g - - Profile_Arcs_Seen : Boolean := False; - -- Set True if unit has been compiled with -fprofile-arcs - - Expected_Annotation_Kind : ALI_Annotation_Kind; - Expected_Annotation_Msg : String_Access; - -- Variables for checking of annotation validity: annotations must - -- come in (Exempt_On, Exempt_Off) pairs, nesting forbidden, and - -- the Exempt_Off message must be either empty or identical to the - -- Exempt_On one. - - -- Start of processing for Load_ALI - - begin - pragma Assert (Deps.Last_Index = 0); - - -- First check whether this ALI has been already loaded. We identify - -- this by the fact that it already has an assigned Source_File_Index. - - ALI_Index := Get_Index_From_Full_Name - (ALI_Filename, Library_File, Insert => False); - if ALI_Index /= No_Source_File then - Report - ("ignoring duplicate ALI file " & ALI_Filename, Kind => Warning); - return No_Source_File; - end if; - - ALI_Index := Get_Index_From_Full_Name - (ALI_Filename, Library_File, Insert => True); - Log_File_Open (ALI_Filename); - Open (ALI_File, In_File, ALI_Filename); - - -- Check that the first line is a valid ALI V line. - - declare - V_Line : constant String := Get_Stripped_Line (ALI_File); - Error_Msg : Unbounded_String; - begin - Match (V_Matcher, V_Line, Matches); - if Matches (0) = No_Match then - Error_Msg := - +("malformed ALI file """ & ALI_Filename & """"); - - if V_Line'Length > 3 - and then - To_Lower (V_Line (V_Line'Last - 3 .. V_Line'Last)) = ".ali" - then - Append - (Error_Msg, - ASCII.LF - & "to load ALIs from list use ""--scos=@" - & ALI_Filename & """"); - end if; - Fatal_Error (+Error_Msg); - end if; - end; - - -- Here once the ALI file has been succesfully opened - - SCOs_Trace.Trace ("Loading SCOs from " & ALI_Filename); - - Expected_Annotation_Kind := Exempt_On; - Expected_Annotation_Msg := null; - - Scan_ALI : while not End_Of_File (ALI_File) loop - loop - Free (Line); - Line := new String'(Get_Stripped_Line (ALI_File)); - exit when Line'Length > 0; - end loop; - - case Line (1) is - when 'A' => - if Line.all = "A -fpreserve-control-flow" then - Preserve_Control_Flow_Seen := True; - - elsif Line.all = "A -fdump-scos" - or else - Line.all = "A -gnateS" - then - Dump_SCOs_Seen := True; - - elsif Line.all = "A -g" then - Debug_Seen := True; - - elsif Line.all = "A -fprofile-arcs" then - Profile_Arcs_Seen := True; - end if; - - when 'P' => - declare - P_Start : Integer; - begin - P_Start := 2; - loop - while P_Start <= Line'Last - and then Line (P_Start) = ' ' - loop - P_Start := P_Start + 1; - end loop; - exit when P_Start > Line'Last - 1; - - declare - Param : constant String (1 .. 2) := - Line (P_Start .. P_Start + 1); - begin - if Param = "NO" then - No_Object := True; - end if; - end; - - P_Start := P_Start + 2; - end loop; - end; - - when 'U' => - Match (U_Matcher, Line (3 .. Line'Last), Matches); - if Matches (0) /= No_Match then - Units.Append (Get_Index_From_Generic_Name (Match (1), - Source_File)); - end if; - - when 'D' => - Match (D_Matcher, Line (3 .. Line'Last), Matches); - if Matches (0) /= No_Match then - - -- Dependency files are source files. However, in order to - -- avoid unnecessary conflicts at consolidation time, we - -- don't want to consider them for coverage analysis unless - -- they are in the units of interest. So consider them as - -- stubs at this stage. - - Deps.Append (Get_Index_From_Generic_Name - (Unquote (Match (1)), Stub_File)); - end if; - - when 'N' => - declare - Annotation : ALI_Annotation; - Valid : Boolean; - Sloc : Source_Location; - begin - Match (N_Matcher, Line (3 .. Line'Last), Matches); - if Matches (0) /= No_Match then - declare - Note_SFN : constant String := Match (3); - Note_SFI : Source_File_Index := Units.Last_Element; - - begin - if Note_SFN'Length > 0 then - - -- Case of a separate: the source file is not the - -- current compilation unit but some other one - -- identified explicitly. - - Note_SFI := Get_Index_From_Generic_Name - (Note_SFN (Note_SFN'First + 1 - .. Note_SFN'Last), - Source_File); - end if; - - Sloc := - (Source_File => Note_SFI, - L => (Line => - Integer'Value (Match (1)), - Column => - Integer'Value (Match (2)))); - end; - - Valid := True; - - declare - Msg : constant String := Match (6); - begin - Annotation := - (CU => No_CU_Id, - Kind => ALI_Annotation_Kind'Value (Match (4)), - Message => (if Msg'Length > 0 - then new String'(Msg) - else null), - others => <>); - exception - when Constraint_Error => - Report (Sloc, "bad annotation " & Match (4)); - Valid := False; - end; - - if Valid then - if Annotation.Kind /= Expected_Annotation_Kind then - Report (Sloc, "unexpected " - & Annotation.Kind'Img & " " - & Annotation.Message.all - & " (expected " - & Expected_Annotation_Kind'Img - & ")"); - elsif not Check_Message - (Annotation.Message, Expected_Annotation_Msg) - then - Report (Sloc, "unexpected EXEMPT_OFF " - & Annotation.Message.all - & " (expected " - & Expected_Annotation_Msg.all - & ")"); - end if; - - if Annotation.Kind = Exempt_On then - if Annotation.Message = null then - Report (Sloc, "empty message for EXEMPT_ON"); - end if; - - Expected_Annotation_Kind := Exempt_Off; - Expected_Annotation_Msg := Annotation.Message; - - else - Expected_Annotation_Kind := Exempt_On; - Expected_Annotation_Msg := null; - end if; - - ALI_Annotations.Insert - (Key => Sloc, New_Item => Annotation); - end if; - end if; - end; - - when 'C' => - exit Scan_ALI; - - when others => - null; - end case; - end loop Scan_ALI; - - if Expected_Annotation_Kind = Exempt_Off then - declare - use ALI_Annotation_Maps; - Last_Ann_Cursor : constant Cursor := ALI_Annotations.Last; - Last_Ann_Sloc : constant Source_Location := - Key (Last_Ann_Cursor); - Last_Ann : constant ALI_Annotation := - Element (Last_Ann_Cursor); - begin - Report (Last_Ann_Sloc, - "missing Exempt_Off " & Last_Ann.Message.all); - end; - end if; - - if With_SCOs then - if No_Object then - Warn ("no object generated for " & ALI_Filename); - - else - if not Preserve_Control_Flow_Seen then - Warn - (ALI_Filename - & ": unit compiled without -fpreserve-control-flow"); - end if; - - if not Dump_SCOs_Seen then - Warn - (ALI_Filename - & ": unit compiled without SCO generation (-fdump-scos)"); - end if; - - if not Debug_Seen then - Warn - (ALI_Filename - & ": unit compiled without debug information (-g)"); - end if; - - if Profile_Arcs_Seen then - Warn - (ALI_Filename - & ": unit compiled with instrumentation (-fprofile-arcs)"); - end if; - end if; - - if not End_Of_File (ALI_File) - and then Dump_SCOs_Seen - and then not No_Object - then - Index := 1; - Get_SCOs_From_ALI; - Mark_Ignored_Units (Ignored_Source_Files, Deps); - - else - -- In this case, we will not parse SCOs: reset parsing tables so - -- that further processing don't start using stale SCO entries. - - SCOs.Initialize; - end if; - end if; - - Close (ALI_File); - return ALI_Index; - end Load_ALI; - - ---------- - -- Read -- - ---------- - - procedure Read - (CLS : in out Checkpoint_Load_State; Value : out ALI_Annotation) is - begin - Value.CU := CLS.Read_CU; - Value.Kind := ALI_Annotation_Kind'Val (CLS.Read_U8); - - declare - Msg : constant String := CLS.Read_String; - begin - if Msg'Length > 0 then - Value.Message := new String'(Msg); - end if; - end; - - Value.Violation_Count := 0; - Value.Undetermined_Cov_Count := 0; - end Read; - - procedure Read - (CLS : in out Checkpoints.Checkpoint_Load_State; - Value : out ALI_Annotation_Maps.Map) - is - procedure Read_Map is new Checkpoints.Read_Map - (Key_Type => Source_Location, - Element_Type => ALI_Annotation, - Map_Type => ALI_Annotation_Maps.Map, - Clear => ALI_Annotation_Maps.Clear, - Insert => ALI_Annotation_Maps.Insert, - Read_Key => Read, - Read_Element => Read); - begin - Read_Map (CLS, Value); - end Read; - - ----------- - -- Write -- - ----------- - - procedure Write (CSS : in out Checkpoint_Save_State; Value : ALI_Annotation) - is - begin - CSS.Write_CU (Value.CU); - CSS.Write_U8 (ALI_Annotation_Kind'Pos (Value.Kind)); - CSS.Write_Unbounded (if Value.Message = null - then "" - else Value.Message.all); - end Write; - - procedure Write - (CSS : in out Checkpoints.Checkpoint_Save_State; - Value : ALI_Annotation_Maps.Map) - is - procedure Write_Map is new Checkpoints.Write_Map - (Key_Type => Source_Location, - Element_Type => ALI_Annotation, - Map_Type => ALI_Annotation_Maps.Map, - Cursor_Type => ALI_Annotation_Maps.Cursor, - Length => ALI_Annotation_Maps.Length, - Iterate => ALI_Annotation_Maps.Iterate, - Query_Element => ALI_Annotation_Maps.Query_Element, - Write_Key => Write, - Write_Element => Write); - begin - Write_Map (CSS, Value); - end Write; - -end ALI_Files; diff --git a/tools/gnatcov/ali_files.ads b/tools/gnatcov/ali_files.ads deleted file mode 100644 index 33417d5c6..000000000 --- a/tools/gnatcov/ali_files.ads +++ /dev/null @@ -1,109 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- 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. -- ------------------------------------------------------------------------------- - --- ALI files reader - -with Ada.Containers.Ordered_Maps; - -with GNAT.Regexp; -with GNAT.Strings; use GNAT.Strings; - -limited with Checkpoints; -with SC_Obligations; use SC_Obligations; -with Slocs; use Slocs; -with Types; use Types; - -package ALI_Files 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); - - type ALI_Annotation_Kind is - (Exempt_On, Exempt_Off, Dump_Buffers, Reset_Buffers, Cov_On, Cov_Off); - - type ALI_Annotation is record - CU : CU_Id; - -- Compilation unit whose LI file this annotation comes from - - Kind : ALI_Annotation_Kind; - -- On or Off, Dump or Reset coverage buffers - - Message : String_Access; - -- When Kind = Exempt_On, justification message for the exemption. - -- This is null if no justification is given (i.e. this is never an - -- access to an empty string). - - Violation_Count : Natural := 0; - -- When Kind = Exempt_On, this counts the violation "hits" on this - -- exemption: - -- - -- * exempted violation messages if generating a report, - -- - -- * exempted non/partially covered lines otherwise. - - Undetermined_Cov_Count : Natural := 0; - -- When Kind = Exempt_On, this counts the number of "hits" for - -- undetermined coverage items: currently exempted non-instrumented - -- messages when generating a report, or lines marked as - -- non instrumented otherwise. - -- - -- This is relevant only for source trace based coverage analysis. - end record; - - package ALI_Annotation_Maps is - new Ada.Containers.Ordered_Maps - (Key_Type => Source_Location, - Element_Type => ALI_Annotation); - - procedure Read - (CLS : in out Checkpoints.Checkpoint_Load_State; - Value : out ALI_Annotation_Maps.Map); - -- Read a ALI_Annotation_Maps.Map from CLS - - procedure Write - (CSS : in out Checkpoints.Checkpoint_Save_State; - Value : ALI_Annotation_Maps.Map); - -- Write a ALI_Annotation_Maps.Map to CSS - - ALI_Annotations : ALI_Annotation_Maps.Map; - - function Load_ALI - (ALI_Filename : String; - Ignored_Source_Files : access GNAT.Regexp.Regexp; - Units : out SFI_Vector; - Deps : out SFI_Vector; - ALI_Annotations : in out ALI_Annotation_Maps.Map; - With_SCOs : Boolean) return Types.Source_File_Index; - -- Load coverage related information (coverage exemptions and, if With_SCOs - -- is True, source coverage obligations) from ALI_Filename. Returns the - -- source file index for the ALI file. Subsequent calls for the same ALI - -- file will return No_Source_File immediately, without reloading the file. - -- Units are the units contained in this compilation. - -- - -- Ignore all source obligations according to Ignored_Source_Files (see - -- SC_Obligations.Load_SCOs' documentation). - -- - -- Deps are the dependencies of the compilation. - - procedure Load_ALI (ALI_Filename : String); - -- Load ALI information for Filename, without SCOs - -end ALI_Files; diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index dd0e5a5b3..76c8ffbaa 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -21,7 +21,6 @@ with Ada.Containers.Vectors; with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Text_IO; use Ada.Text_IO; -with ALI_Files; with Calendar_Utils; use Calendar_Utils; with Coverage; use Coverage; with Coverage.Source; use Coverage.Source; @@ -280,7 +279,10 @@ package body Annotations.Report is ---------------------- procedure Pretty_Print_End (Pp : in out Report_Pretty_Printer) is - use ALI_Files, ALI_Files.ALI_Annotation_Maps; + use SC_Obligations.ALI_Annotation_Maps; + + ALI_Annotations : constant ALI_Annotation_Maps.Map := + Get_All_Annotations; Output : constant File_Access := Get_Output; diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 957889bf4..8c5ead1cc 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -24,7 +24,6 @@ with GNAT.OS_Lib; with Interfaces; -with ALI_Files; use ALI_Files; with Calendar_Utils; with Coverage; with Coverage.Object; @@ -521,40 +520,14 @@ package body Annotations is end Generate_Report; - ------------------- - -- Get_Exemption -- - ------------------- - - function Get_Exemption (Sloc : Source_Location) return Source_Location is - use ALI_Annotation_Maps; - - Cur : constant Cursor := ALI_Annotations.Floor (Sloc); - begin - if not Ignore_Exemptions_Trace.Is_Active - and then Cur /= No_Element - and then Key (Cur).Source_File = Sloc.Source_File - then - declare - A : constant ALI_Annotation := Element (Cur); - begin - if A.Kind = Exempt_On then - return Key (Cur); - end if; - end; - end if; - - return Slocs.No_Location; - end Get_Exemption; - ----------------------------------- -- Get_Exemption_Violation_Count -- ----------------------------------- function Get_Exemption_Violation_Count - (Sloc : Source_Location) return Natural - is + (Sloc : Source_Location) return Natural is begin - return ALI_Annotations.Element (Sloc).Violation_Count; + return Get_Annotations (Sloc.Source_File).Element (Sloc).Violation_Count; end Get_Exemption_Violation_Count; ----------------------------------- @@ -562,10 +535,10 @@ package body Annotations is ----------------------------------- function Get_Exemption_Undet_Cov_Count - (Sloc : Source_Location) return Natural - is + (Sloc : Source_Location) return Natural is begin - return ALI_Annotations.Element (Sloc).Undetermined_Cov_Count; + return Get_Annotations (Sloc.Source_File) + .Element (Sloc).Undetermined_Cov_Count; end Get_Exemption_Undet_Cov_Count; --------------------------- @@ -573,38 +546,11 @@ package body Annotations is --------------------------- function Get_Exemption_Message - (Sloc : Source_Location) return String_Access - is + (Sloc : Source_Location) return String_Access is begin - return ALI_Annotations.Element (Sloc).Message; + return Get_Annotations (Sloc.Source_File).Element (Sloc).Message; end Get_Exemption_Message; - ----------------------------------- - -- Inc_Violation_Exemption_Count -- - ----------------------------------- - - procedure Inc_Violation_Exemption_Count (Sloc : Source_Location) is - use ALI_Annotation_Maps; - - Cur : constant Cursor := ALI_Annotations.Find (Sloc); - E : ALI_Annotation renames ALI_Annotations.Reference (Cur); - begin - E.Violation_Count := E.Violation_Count + 1; - end Inc_Violation_Exemption_Count; - - ----------------------------------- - -- Inc_Undet_Cov_Exemption_Count -- - ----------------------------------- - - procedure Inc_Undet_Cov_Exemption_Count (Sloc : Source_Location) is - use ALI_Annotation_Maps; - - Cur : constant Cursor := ALI_Annotations.Find (Sloc); - E : ALI_Annotation renames ALI_Annotations.Reference (Cur); - begin - E.Undetermined_Cov_Count := E.Undetermined_Cov_Count + 1; - end Inc_Undet_Cov_Exemption_Count; - ------------------------ -- Message_Annotation -- ------------------------ diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 9ea36b4d9..6b5e1b8ac 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -253,10 +253,6 @@ private -- about the original processing context. Empty string for traces processed -- in the current Gnatcov execution. - function Get_Exemption (Sloc : Source_Location) return Source_Location; - -- If the given Sloc is covered by an exemption, return the source location - -- of the corresponding exemption annotation, else return No_Location. - function Get_Exemption_Message (Sloc : Source_Location) return String_Access; -- For a Sloc denoting an Exempt_On annotation, return the descriptive @@ -271,14 +267,6 @@ private -- Return the exempted line/message undetermined coverage items counter for -- exemption at Sloc. - procedure Inc_Violation_Exemption_Count (Sloc : Source_Location); - -- Increment the exempted line/message violation counter for exemption at - -- Sloc. - - procedure Inc_Undet_Cov_Exemption_Count (Sloc : Source_Location); - -- Increment the exempted line/message undetermined coverage items counter - -- for exemption at Sloc. - procedure Output_Multiline_Msg (Output : Ada.Text_IO.File_Type; Text : String); diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index b5ebb74bc..f49254df9 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -422,6 +422,30 @@ package body Checkpoints is return CP_SCO_Id; end Remap_SCO_Id; + --------------------------- + -- Remap_ALI_Annotations -- + --------------------------- + + procedure Remap_ALI_Annotations + (Relocs : Checkpoint_Relocations; + CP_ALI_Annotations : in out ALI_Annotation_Maps.Map) + is + use ALI_Annotation_Maps; + Result : Map; + begin + for Cur in CP_ALI_Annotations.Iterate loop + declare + Sloc : Source_Location := Key (Cur); + begin + Remap_SFI (Relocs, Sloc.Source_File); + if Sloc.Source_File /= No_Source_File then + Result.Include (Sloc, Element (Cur)); + end if; + end; + end loop; + CP_ALI_Annotations := Result; + end Remap_ALI_Annotations; + procedure Checkpoint_Load (Filename : String; Purpose : Checkpoint_Purpose; diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 031c8617e..55ddf4f3e 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -245,6 +245,14 @@ package Checkpoints is -- A stream associated with global state shared across phases of a -- checkpoint load or save. + procedure Remap_ALI_Annotations + (Relocs : Checkpoint_Relocations; + CP_ALI_Annotations : in out ALI_Annotation_Maps.Map); + -- Remap one source file index. + + -- A stream associated with global state shared across phases of a + -- checkpoint load or save. + type Stateful_Stream (Stream : access Root_Stream_Type'Class) is abstract new Root_Stream_Type with record diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 2b4ffb96b..1a289d367 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -2023,13 +2023,14 @@ package body Coverage.Source is end Refine_Source_Coverage; procedure Compute_Source_Coverage - (Filename : String; - Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Part; - Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; - Stmt_Buffer : Coverage_Buffer; - Decision_Buffer : Coverage_Buffer; - MCDC_Buffer : Coverage_Buffer) + (Filename : String; + Fingerprint : SC_Obligations.Fingerprint_Type; + CU_Name : Compilation_Unit_Part; + Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; + Annotations_Fingerprint : SC_Obligations.Fingerprint_Type; + Stmt_Buffer : Coverage_Buffer; + Decision_Buffer : Coverage_Buffer; + MCDC_Buffer : Coverage_Buffer) is CU : CU_Id; BM : CU_Bit_Maps; @@ -2128,6 +2129,9 @@ package body Coverage.Source is if Fingerprint /= SC_Obligations.Fingerprint (CU) or else Bit_Maps_Fingerprint /= SC_Obligations.Bit_Maps_Fingerprint (CU) + or else + Annotations_Fingerprint /= + SC_Obligations.Annotations_Fingerprint (CU) then Warn ("traces for " & Unit_Image & " (from " & Filename & ") are" & " inconsistent with the corresponding Source Instrumentation" diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 7cc555815..4a8417564 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -61,13 +61,14 @@ package Coverage.Source is -- determine the coverage state of each SCO. procedure Compute_Source_Coverage - (Filename : String; - Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Part; - Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; - Stmt_Buffer : Coverage_Buffer; - Decision_Buffer : Coverage_Buffer; - MCDC_Buffer : Coverage_Buffer); + (Filename : String; + Fingerprint : SC_Obligations.Fingerprint_Type; + CU_Name : Compilation_Unit_Part; + Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; + Annotations_Fingerprint : SC_Obligations.Fingerprint_Type; + Stmt_Buffer : Coverage_Buffer; + Decision_Buffer : Coverage_Buffer; + MCDC_Buffer : Coverage_Buffer); -- Analyze source instrumentation traces to determine the coverage state -- of each SCO. Generic actual for -- Instrument.Input_Traces.Generic_Read_Source_Trace_File. diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 1fb9fb5f5..3d2f897d1 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -29,7 +29,6 @@ with Osint; with GNATCOLL.VFS; use GNATCOLL.VFS; -with ALI_Files; use ALI_Files; with Checkpoints; use Checkpoints; with Coverage; use Coverage; with Outputs; @@ -1724,8 +1723,10 @@ package body Files_Table is -- expanded later if we find that there are exemption annotations past -- this line. + Annotations : constant ALI_Annotation_Maps.Map := + Get_Annotations (FI); Annotation_Cur : Cursor := - ALI_Annotations.Ceiling ((FI, (Current_Line_Num, 0))); + Annotations.Ceiling ((FI, (Current_Line_Num, 0))); Next_Annot_Cur : Cursor; Current_Annot_Sloc : Source_Location; Current_Annotation : ALI_Annotation; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index bc18d7a5a..215eb5f3b 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -32,7 +32,6 @@ with System.Multiprocessors; with Snames; -with ALI_Files; with Annotations.Cobertura; with Annotations.Sarif; with Annotations.Dynamic_Html; @@ -322,7 +321,7 @@ procedure GNATcov_Bits_Specific is -- get exemptions as they apply to instruction/branch coverage. for Filename of ALIs_Inputs loop - ALI_Files.Load_ALI (+Filename); + Load_ALI (+Filename); end loop; end if; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 539e71300..06df6d250 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -41,7 +41,6 @@ with Libadalang.Sources; use Libadalang.Sources; with GNATCOLL.JSON; use GNATCOLL.JSON; with GNATCOLL.Utils; -with ALI_Files; use ALI_Files; with Coverage_Options; use Coverage_Options; with Coverage; use Coverage; with Diagnostics; use Diagnostics; @@ -9190,6 +9189,11 @@ package body Instrument.Ada_Unit is (SC_Obligations.Bit_Maps_Fingerprint (CU)) & ","); + File.Put_Line (" Annotations_Fingerprint => " + & Format_Fingerprint + (SC_Obligations.Annotations_Fingerprint (CU)) + & ","); + File.Put_Line (" Statement => Statement_Buffer'Address,"); File.Put_Line (" Decision => Decision_Buffer'Address,"); File.Put_Line (" MCDC => MCDC_Buffer'Address,"); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index c4761cbb9..ceb2d5184 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -35,7 +35,6 @@ with Interfaces; use Interfaces; with Interfaces.C; use Interfaces.C; with Interfaces.C.Strings; use Interfaces.C.Strings; -with ALI_Files; use ALI_Files; with Coverage; use Coverage; with Coverage_Options; with Hex_Images; use Hex_Images; @@ -56,8 +55,8 @@ package body Instrument.C is procedure Free (Self : in out chars_ptr_array); -- Free all strings in Self - procedure Filter_Annotations; - -- Remove any exemption annotations from the map that intersects a + procedure Filter_Annotations (UIC : in out C_Unit_Inst_Context'Class); + -- Remove any exemption annotations from UIC.Annotations that intersects a -- statement SCO. This is not part of Import_Annotations as this is only -- required for C annotations, where the exemption markers can be -- arbitrarily placed. This would also not work for Ada exemptions as there @@ -546,14 +545,13 @@ package body Instrument.C is -- Filter_Annotations -- ------------------------ - procedure Filter_Annotations is - use ALI_Annotation_Maps; - Cur : Cursor := ALI_Annotations.First; - Del_Cur : Cursor; + procedure Filter_Annotations (UIC : in out C_Unit_Inst_Context'Class) is + use Annotation_Vectors; + Filtered_Annotations : Vector; begin - while Has_Element (Cur) loop + for Ann of UIC.Annotations loop declare - Sloc : constant Source_Location := Key (Cur); + Sloc : constant Source_Location := Ann.Sloc; LI : constant Line_Info_Access := Get_Line (Sloc); Deleted : Boolean := False; begin @@ -565,9 +563,6 @@ package body Instrument.C is then for SCO of LI.SCOs.all loop if Slocs.In_Range (Sloc, Sloc_Range (SCO)) then - Del_Cur := Cur; - Next (Cur); - ALI_Annotations.Delete (Del_Cur); Warn ("Exemption annotation at " & Slocs.Image (Sloc) & " intersects a coverage obligation (" & Image (SCO, True) & "), ignoring it"); @@ -577,10 +572,11 @@ package body Instrument.C is end loop; end if; if not Deleted then - Next (Cur); + Filtered_Annotations.Append (Ann); end if; end; end loop; + UIC.Annotations := Filtered_Annotations; end Filter_Annotations; ----------------- @@ -3497,8 +3493,8 @@ package body Instrument.C is -- Import annotations in our internal tables - UIC.Import_Annotations (UIC.CUs); - Filter_Annotations; + Filter_Annotations (UIC); + Import_Annotations (UIC, UIC.CUs); Import_Non_Instrumented_LL_SCOs (UIC, SCO_Map); for Cur in UIC.Instrumented_Entities.Iterate loop @@ -3929,6 +3925,12 @@ package body Instrument.C is & "," & ASCII.LF + & " .annotations_fingerprint = " + & Format_Fingerprint + (SC_Obligations.Annotations_Fingerprint (CU)) + & "," + & ASCII.LF + -- We do not use the created pointer (Statement_Buffer) to -- initialize the buffer fields, as this is rejected by old -- versions of the compiler (up to the 20 version): the diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 369ed61d5..32a0ad41d 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -257,14 +257,15 @@ package body Instrument.Common is ------------------------ procedure Import_Annotations - (UIC : in out Unit_Inst_Context; Created_Units : Created_Unit_Maps.Map) is + (UIC : in out Unit_Inst_Context; Created_Units : Created_Unit_Maps.Map) + is + ALI_Annotations : ALI_Annotation_Maps.Map; begin for Couple of UIC.Annotations loop - Couple.Annotation.CU := - Created_Units.Element (Couple.Sloc.Source_File); ALI_Annotations.Insert (Key => Couple.Sloc, New_Item => Couple.Annotation); end loop; + Set_Annotations (ALI_Annotations); end Import_Annotations; ------------------------------------- diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 1e2672dde..ff8a8a09d 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -58,7 +58,6 @@ with GNAT.Regpat; use GNAT.Regpat; with GNATCOLL.JSON; use GNATCOLL.JSON; -with ALI_Files; use ALI_Files; with Files_Handling; use Files_Handling; with Files_Table; use Files_Table; with Namet; use Namet; @@ -319,7 +318,7 @@ package Instrument.Common is -- * collect couples of sloc/annotations during the tree traversal; -- * once the CU_Id for the instrumented file is known, fill in the -- Annotation.CU component and add the sloc/annotation couple to - -- ALI_Files.ALI_Annotation map. + -- the ALI_Annotation map of the right SC_Obligations.CU_Vector entry. -- -- This record type is just a helper to hold data between these two steps. @@ -345,8 +344,7 @@ package Instrument.Common is Annotations : Annotation_Vectors.Vector; -- Annotations created during the instrumentation process, to insert in - -- ALI_Files.ALI_Annotations afterwards, when the compilation unit - -- (SC_Obligations.CU_Info) for this annotation is ready. + -- CU_Info.ALI_Annotations afterwards. Disable_Instrumentation : Boolean := False; -- Set to True to deactivate instrumentation and prevent any code @@ -378,7 +376,7 @@ package Instrument.Common is (Strings.Img (Integer (Bit))); Runtime_Version_Check : constant String := - "pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, " + "pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, " & """Incompatible GNATcov_RTS version, please use" & " the GNATcov_RTS project provided with your" & " GNATcoverage distribution."");"; diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 1814e8296..46eb2811d 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -516,7 +516,7 @@ package body Instrument.Input_Traces is Create_Error (Result, "invalid bit buffer encoding"); return False; - elsif Raw_Header.Padding /= (1 .. 5 => ASCII.NUL) then + elsif Raw_Header.Padding /= (1 .. 1 => ASCII.NUL) then Create_Error (Result, "invalid entry header padding"); return False; end if; @@ -679,10 +679,15 @@ package body Instrument.Input_Traces is function Convert is new Ada.Unchecked_Conversion (Traces_Source.Fingerprint_Type, SC_Obligations.Fingerprint_Type); + Fingerprint : constant SC_Obligations.Fingerprint_Type := Convert (Entry_Header.Fingerprint); Bit_Maps_Fingerprint : constant SC_Obligations.Fingerprint_Type := - Convert (Entry_Header.Bit_Maps_Fingerprint); + Convert (Entry_Header.Bit_Maps_Fingerprint); + + Annotations_Fingerprint : constant + SC_Obligations.Fingerprint_Type := + Convert (Entry_Header.Annotations_Fingerprint); Statement_Buffer_Size : constant Natural := Buffer_Size (Entry_Header.Bit_Buffer_Encoding, @@ -758,6 +763,7 @@ package body Instrument.Input_Traces is Fingerprint, CU_Name, Bit_Maps_Fingerprint, + Annotations_Fingerprint, Statement_Buffer (0 .. Last_Bit (Entry_Header.Statement_Bit_Count)), Decision_Buffer @@ -784,13 +790,14 @@ package body Instrument.Input_Traces is (Kind : Traces_Source.Supported_Info_Kind; Data : String); procedure On_Trace_Entry - (Filename : String; - Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Part; - Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; - Stmt_Buffer : Coverage_Buffer; - Decision_Buffer : Coverage_Buffer; - MCDC_Buffer : Coverage_Buffer); + (Filename : String; + Fingerprint : SC_Obligations.Fingerprint_Type; + CU_Name : Compilation_Unit_Part; + Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; + Annotations_Fingerprint : SC_Obligations.Fingerprint_Type; + Stmt_Buffer : Coverage_Buffer; + Decision_Buffer : Coverage_Buffer; + MCDC_Buffer : Coverage_Buffer); -- Callbacks for Read_Source_Trace_File Last_Is_Info : Boolean := False; @@ -824,13 +831,14 @@ package body Instrument.Input_Traces is -------------------- procedure On_Trace_Entry - (Filename : String; - Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Part; - Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; - Stmt_Buffer : Coverage_Buffer; - Decision_Buffer : Coverage_Buffer; - MCDC_Buffer : Coverage_Buffer) + (Filename : String; + Fingerprint : SC_Obligations.Fingerprint_Type; + CU_Name : Compilation_Unit_Part; + Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; + Annotations_Fingerprint : SC_Obligations.Fingerprint_Type; + Stmt_Buffer : Coverage_Buffer; + Decision_Buffer : Coverage_Buffer; + MCDC_Buffer : Coverage_Buffer) is pragma Unreferenced (Filename); use Ada.Text_IO; @@ -858,6 +866,11 @@ package body Instrument.Input_Traces is Put (Hex_Images.Hex_Image (Interfaces.Unsigned_8 (B))); end loop; + Put (", annotations hash="); + for B of Annotations_Fingerprint loop + Put (Hex_Images.Hex_Image (Interfaces.Unsigned_8 (B))); + end loop; + Put_Line (")"); Dump_Buffer ("Statement", Stmt_Buffer); Dump_Buffer ("Decision", Decision_Buffer); diff --git a/tools/gnatcov/instrument-input_traces.ads b/tools/gnatcov/instrument-input_traces.ads index 947d6b6f0..94b33e8d0 100644 --- a/tools/gnatcov/instrument-input_traces.ads +++ b/tools/gnatcov/instrument-input_traces.ads @@ -32,13 +32,14 @@ package Instrument.Input_Traces is (Kind : Traces_Source.Supported_Info_Kind; Data : String) is <>; with procedure On_Trace_Entry - (Filename : String; - Fingerprint : SC_Obligations.Fingerprint_Type; - CU_Name : Compilation_Unit_Part; - Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; - Stmt_Buffer : Coverage_Buffer; - Decision_Buffer : Coverage_Buffer; - MCDC_Buffer : Coverage_Buffer) is <>; + (Filename : String; + Fingerprint : SC_Obligations.Fingerprint_Type; + CU_Name : Compilation_Unit_Part; + Bit_Maps_Fingerprint : SC_Obligations.Fingerprint_Type; + Annotations_Fingerprint : SC_Obligations.Fingerprint_Type; + Stmt_Buffer : Coverage_Buffer; + Decision_Buffer : Coverage_Buffer; + MCDC_Buffer : Coverage_Buffer) is <>; procedure Generic_Read_Source_Trace_File (Filename : String; Result : out Traces_Files.Read_Result); diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index b24e83de2..42367696f 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -81,6 +81,7 @@ package GNATcov_RTS.Buffers is Unit_Part : Any_Unit_Part; Unit_Name : GNATcov_RTS_String; Bit_Maps_Fingerprint : Fingerprint_Type; + Annotations_Fingerprint : Fingerprint_Type; Statement, Decision, MCDC : System.Address; Statement_Last_Bit, Decision_Last_Bit, MCDC_Last_Bit : Any_Bit_Id; diff --git a/tools/gnatcov/rts/gnatcov_rts.ads b/tools/gnatcov/rts/gnatcov_rts.ads index 4a666279f..2c8e5bf37 100644 --- a/tools/gnatcov/rts/gnatcov_rts.ads +++ b/tools/gnatcov/rts/gnatcov_rts.ads @@ -42,7 +42,7 @@ package GNATcov_RTS is pragma Warnings (Off, Std); pragma Warnings (Off, Sys); - Version : constant := 7; + Version : constant := 8; -- For compatibility with the GNATcoverage in use, GNATcov_RTS is -- versioned. -- @@ -54,5 +54,6 @@ package GNATcov_RTS is -- the associated Witness function. -- 6 -- buffer clear mechanism and trace filename indices -- 7 -- enable inlining of witness subprograms + -- 8 -- introduce fingerprints for annotations end GNATcov_RTS; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index 2b9e4dd02..cdb6f57df 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -99,6 +99,11 @@ extern "C" from SID files. */ uint8_t bit_maps_fingerprint[FINGERPRINT_SIZE]; + /* Hash of annotations for this unit, as gnatcov computes it (see + SC_Obligations). Used as a fast way to check that source traces and + coverage data are consistent. */ + uint8_t annotations_fingerprint[FINGERPRINT_SIZE]; + /* Pointers to coverage buffers for statement obligations, decision obligations and MC/DC obligations. The size of each array is in the corresponding *_last_bit field. */ diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c index c06babb78..6bb1f9985 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces-output.c @@ -125,10 +125,12 @@ write_entry (gnatcov_rts_write_bytes_callback write_bytes, void *output, header.language_kind = (uint8_t) buffers->language_kind; header.unit_part = (uint8_t) buffers->unit_part; header.bit_buffer_encoding = GNATCOV_RTS_LSB_FIRST_BYTES; - memset (header.padding, 0, 5); + memset (header.padding, 0, 1); memcpy (&header.fingerprint, buffers->fingerprint, FINGERPRINT_SIZE); memcpy (&header.bit_maps_fingerprint, buffers->bit_maps_fingerprint, FINGERPRINT_SIZE); + memcpy (&header.annotations_fingerprint, buffers->annotations_fingerprint, + FINGERPRINT_SIZE); write_bytes (output, (char *) &header, sizeof (header)); write_bytes (output, buffers->unit_name.str, buffers->unit_name.length); diff --git a/tools/gnatcov/rts/gnatcov_rts_c-traces.h b/tools/gnatcov/rts/gnatcov_rts_c-traces.h index fa260dd97..aa18a7b4b 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-traces.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-traces.h @@ -32,8 +32,9 @@ extern "C" 0 -- initial version 1 -- extend trace entry model to account for C files 2 -- introduce fingerprints for bit maps - 3 -- remove the project name from trace entries */ -#define GNATCOV_RTS_CURRENT_VERSION 3 + 3 -- remove the project name from trace entries + 3 -- introduce fingerprints for annotations */ +#define GNATCOV_RTS_CURRENT_VERSION 4 /* LSB_First_Bytes: bit buffers are encoded as sequences of bytes. @@ -142,9 +143,14 @@ extern "C" from SID files. */ uint8_t bit_maps_fingerprint[20]; + /* Hash of annotations for this unit, as gnatcov computes it (see + SC_Obligations). Used as a fast way to check that source traces and + coverage data are consistent. */ + uint8_t annotations_fingerprint[20]; + /* Padding used only to make the size of this trace entry header a multiple of 8 bytes. Must be zero. */ - uint8_t padding[5]; + uint8_t padding[1]; }; #ifdef __cplusplus diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 51e1d8d59..48edc2d7a 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -26,17 +26,20 @@ with Ada.Unchecked_Deallocation; with Interfaces; -with Aspects; use Aspects; -with Namet; use Namet; +with Aspects; use Aspects; +with Get_SCOs; +with GNAT.Regpat; use GNAT.Regpat; +with Namet; use Namet; +with SC_Obligations; with SCOs; with Snames; -with ALI_Files; use ALI_Files; with Checkpoints; use Checkpoints; with Coverage.Source; with Coverage.Tags; use Coverage, Coverage.Tags; with Diagnostics; use Diagnostics; with Files_Table; use Files_Table; +with Inputs; use Inputs; with Outputs; use Outputs; with SC_Obligations.BDD; with Switches; use Switches; @@ -131,6 +134,12 @@ package body SC_Obligations is -- is specific to source instrumentation, but a container cannot be -- a discriminant-dependent component. + ALI_Annotations : ALI_Annotation_Maps.Map; + -- List of annotations for the unit + + Annotations_Fingerprint : Fingerprint_Type := No_Fingerprint; + -- Hash of ALI_Annotations, for consistency checks with source traces + case Provider is when Compiler => null; @@ -535,11 +544,10 @@ package body SC_Obligations is -- contain data loaded from a checkpoint. type Source_Coverage_Vectors is record - CU_Vector : CU_Info_Vectors.Vector; - ALI_Annotations : ALI_Annotation_Maps.Map; - Inst_Vector : Inst_Info_Vectors.Vector; - BDD_Vector : BDD.BDD_Vectors.Vector; - SCO_Vector : SCO_Vectors.Vector; + CU_Vector : CU_Info_Vectors.Vector; + Inst_Vector : Inst_Info_Vectors.Vector; + BDD_Vector : BDD.BDD_Vectors.Vector; + SCO_Vector : SCO_Vectors.Vector; end record; ----------------------------------------- @@ -635,6 +643,20 @@ package body SC_Obligations is Vectors => SCO_Id_Vector_Vectors, Read_Element => Read); + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out ALI_Annotation); + -- Read a ALI_Annotation from CLS + + procedure Read is new Checkpoints.Read_Map + (Key_Type => Source_Location, + Element_Type => ALI_Annotation, + Map_Type => ALI_Annotation_Maps.Map, + Clear => ALI_Annotation_Maps.Clear, + Insert => ALI_Annotation_Maps.Insert, + Read_Key => Read, + Read_Element => Read); + -- Read a ALI_Annotation_Maps.Map from CLS + procedure Checkpoint_Load_Merge_Unit (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; @@ -761,6 +783,22 @@ package body SC_Obligations is Vectors => SCO_Id_Vector_Vectors, Write_Element => Write); + procedure Write + (CSS : in out Checkpoint_Save_State; Value : ALI_Annotation); + -- Write a ALI_Annotation to CSS + + procedure Write is new Checkpoints.Write_Map + (Key_Type => Source_Location, + Element_Type => ALI_Annotation, + Map_Type => ALI_Annotation_Maps.Map, + Cursor_Type => ALI_Annotation_Maps.Cursor, + Length => ALI_Annotation_Maps.Length, + Iterate => ALI_Annotation_Maps.Iterate, + Query_Element => ALI_Annotation_Maps.Query_Element, + Write_Key => Write, + Write_Element => Write); + -- Write a ALI_Annotation_Maps.Map to CSS + ------------------ -- Local tables -- ------------------ @@ -1090,6 +1128,9 @@ package body SC_Obligations is Value.Has_Code := CLS.Read_Boolean; Value.Fingerprint := CLS.Read_Fingerprint; Read (CLS, Value.PP_Info_Map); + Read (CLS, Value.Scope_Entities); + Read (CLS, Value.ALI_Annotations); + Value.Annotations_Fingerprint := CLS.Read_Fingerprint; case Value.Provider is when Compiler => @@ -1142,8 +1183,6 @@ package body SC_Obligations is Read (CLS, Value.Blocks); end if; end case; - - Read (CLS, Value.Scope_Entities); end Read; procedure Read (CLS : in out Checkpoint_Load_State; Element : out Inst_Info) @@ -1224,6 +1263,23 @@ package body SC_Obligations is Element := SCOD; end Read; + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out ALI_Annotation) is + begin + Value.Kind := ALI_Annotation_Kind'Val (CLS.Read_U8); + + declare + Msg : constant String := CLS.Read_String; + begin + if Msg'Length > 0 then + Value.Message := new String'(Msg); + end if; + end; + + Value.Violation_Count := 0; + Value.Undetermined_Cov_Count := 0; + end Read; + -------------------------------- -- Checkpoint_Load_Merge_Unit -- -------------------------------- @@ -1244,6 +1300,8 @@ package body SC_Obligations is -- in the checkpoint to their counterparts in the current context, and -- merge non-instrumented SCO information if available. -- + -- * Merge the annotations + -- -- * Merge the information about non instrumented SCOs. We consider that -- a SCO was instrumented iff at least one merged unit has it -- instrumented. @@ -1305,6 +1363,20 @@ package body SC_Obligations is -- Has_Code indication Real_CU.Has_Code := Real_CU.Has_Code or CP_CU.Has_Code; + + -- Remap ALI annotations and then merge them + + declare + Remapped_Annotations : ALI_Annotation_Maps.Map := + CP_CU.ALI_Annotations; + begin + Remap_ALI_Annotations (Relocs, Remapped_Annotations); + for Cur in Remapped_Annotations.Iterate loop + Real_CU.ALI_Annotations.Include + (ALI_Annotation_Maps.Key (Cur), + ALI_Annotation_Maps.Element (Cur)); + end loop; + end; end Checkpoint_Load_Merge_Unit; ------------------------------ @@ -1647,6 +1719,10 @@ package body SC_Obligations is pragma Assert (SCOs_Nested_And_Ordered (CP_CU.Scope_Entities)); end if; + -- Remap ALI annotations + + Remap_ALI_Annotations (Relocs, CP_CU.ALI_Annotations); + -- Preallocate line table entries for last file Prealloc_Lines (Cur_Source_File, Last_Line); @@ -1867,6 +1943,9 @@ package body SC_Obligations is CSS.Write (Value.Has_Code); CSS.Write (Value.Fingerprint); Write (CSS, Value.PP_Info_Map); + Write (CSS, Value.Scope_Entities); + Write (CSS, Value.ALI_Annotations); + CSS.Write (Value.Annotations_Fingerprint); case Value.Provider is when Compiler => @@ -1902,7 +1981,6 @@ package body SC_Obligations is end if; end case; - Write (CSS, Value.Scope_Entities); end Write; procedure Write @@ -1962,6 +2040,14 @@ package body SC_Obligations is end case; end Write; + procedure Write (CSS : in out Checkpoint_Save_State; Value : ALI_Annotation) + is + begin + CSS.Write_U8 (ALI_Annotation_Kind'Pos (Value.Kind)); + CSS.Write_Unbounded + (if Value.Message = null then "" else Value.Message.all); + end Write; + ---------- -- Free -- ---------- @@ -1995,7 +2081,6 @@ package body SC_Obligations is -- This part must be kept consistent with Checkpoint_Save Read (CLS, CP_Vectors.CU_Vector); - Read (CLS, CP_Vectors.ALI_Annotations); Read (CLS, CP_Vectors.Inst_Vector); SC_Obligations.BDD.Read (CLS, CP_Vectors.BDD_Vector); Read (CLS, CP_Vectors.SCO_Vector); @@ -2112,31 +2197,6 @@ package body SC_Obligations is end; end loop; - -- Remap annotations - - for Cur in CP_Vectors.ALI_Annotations.Iterate loop - declare - use ALI_Annotation_Maps; - Annotation_Sloc : Source_Location := Key (Cur); - Annotation : ALI_Annotation := Element (Cur); - - begin - if not CU_Id_Ignored (Relocs, Annotation.CU) then - - -- Even if the CU was already loaded, the set of annotations - -- can be different from one checkpoint to another (e.g. the - -- coverage disabled regions can vary), so add them in all - -- cases. - - pragma Assert - (Remap_CU_Id (Relocs, Annotation.CU) /= No_CU_Id); - Annotation.CU := Remap_CU_Id (Relocs, Annotation.CU); - Remap_SFI (Relocs, Annotation_Sloc.Source_File); - ALI_Annotations.Include (Annotation_Sloc, Annotation); - end if; - end; - end loop; - end Checkpoint_Load; ---------------------- @@ -2151,7 +2211,6 @@ package body SC_Obligations is CU_Map.Clear; Origin_To_CUs_Map.Clear; CU_Vector.Clear; - ALI_Annotations.Clear; Inst_Vector.Clear; BDD_Vector.Clear; SCO_Vector.Clear; @@ -2164,7 +2223,6 @@ package body SC_Obligations is procedure Checkpoint_Save (CSS : access Checkpoint_Save_State) is begin Write (CSS.all, CU_Vector); - Write (CSS.all, ALI_Annotations); Write (CSS.all, Inst_Vector); BDD.Write (CSS.all, BDD_Vector); Write (CSS.all, SCO_Vector); @@ -3286,6 +3344,15 @@ package body SC_Obligations is return CU_Vector.Reference (CU).Bit_Maps_Fingerprint; end Bit_Maps_Fingerprint; + ----------------------------- + -- Annotations_Fingerprint -- + ----------------------------- + + function Annotations_Fingerprint (CU : CU_Id) return Fingerprint_Type is + begin + return CU_Vector.Reference (CU).Annotations_Fingerprint; + end Annotations_Fingerprint; + --------------- -- Load_SCOs -- --------------- @@ -3371,23 +3438,7 @@ package body SC_Obligations is -- For the units we successfully loaded, copy annotations from the ALI -- file to our internal table, filling in the compilation unit. - for Cur in Temp_ALI_Annotations.Iterate loop - declare - A : ALI_Annotation := ALI_Annotation_Maps.Element (Cur); - - -- This annotation comes from a specific source file. Check if - -- there is a CU that we just created for that source file. - - S : constant Source_Location := ALI_Annotation_Maps.Key (Cur); - CU_Cur : constant Created_Unit_Maps.Cursor := - Created_Units.Find (S.Source_File); - begin - if Created_Unit_Maps.Has_Element (CU_Cur) then - A.CU := Created_Unit_Maps.Element (CU_Cur); - ALI_Annotations.Insert (S, A); - end if; - end; - end loop; + Set_Annotations (Temp_ALI_Annotations); -- Initialize the relevant ".LI" and ".Main_Source" fields in the files -- table. @@ -4780,6 +4831,60 @@ package body SC_Obligations is Info.Blocks := Blocks; end Set_Blocks; + --------------------- + -- Set_Annotations -- + --------------------- + + procedure Set_Annotations (Annotations : ALI_Annotation_Maps.Map) + is + use GNAT.SHA1; + + Current_SFI : Source_File_Index := No_Source_File; + Current_CU : CU_Id := No_CU_Id; + Current_Ctx : GNAT.SHA1.Context := Initial_Context; + -- Current file being processed + + begin + -- As a reminder, Source_Location sort on the file index first, so we + -- are guaranteed to have annotations grouped by source files. + + for Cur in Annotations.Iterate loop + declare + use ALI_Annotation_Maps; + Sloc : constant Source_Location := Key (Cur); + Ann : constant ALI_Annotation := Element (Cur); + begin + -- If we are entering a new file, reset the hashing context and + -- dump the annotations fingerprint that was processed. + + if Sloc.Source_File /= Current_SFI then + if Current_CU /= No_CU_Id then + CU_Vector.Reference (Current_CU).Annotations_Fingerprint := + Fingerprint_Type + (GNAT.SHA1.Binary_Message_Digest' + (GNAT.SHA1.Digest (Current_Ctx))); + end if; + Current_Ctx := Initial_Context; + Current_SFI := Sloc.Source_File; + Current_CU := Comp_Unit (Current_SFI); + end if; + Update (Current_Ctx, Image (Sloc)); + Update (Current_Ctx, ALI_Annotation_Kind'Image (Ann.Kind)); + if Ann.Message /= null then + Update (Current_Ctx, Ann.Message.all); + end if; + CU_Vector.Reference (Current_CU).ALI_Annotations.Include + (Sloc, Ann); + end; + end loop; + if Current_CU /= No_CU_Id then + CU_Vector.Reference (Current_CU).Annotations_Fingerprint := + Fingerprint_Type + (GNAT.SHA1.Binary_Message_Digest' + (GNAT.SHA1.Digest (Current_Ctx))); + end if; + end Set_Annotations; + ------------------------ -- Get_Scope_Entities -- ------------------------ @@ -4960,6 +5065,677 @@ package body SC_Obligations is end loop; end Set_Unit_Has_Code; + --------------- + -- ALI files -- + --------------- + + ----------------------------------------------- + -- Regular expressions for ALI files parsing -- + ----------------------------------------------- + + D_Regexp : constant String := "(([^""\t ]+)|(""([^""]|"""")+""))[\t ]"; + D_Matcher : constant Pattern_Matcher := Compile (D_Regexp); + + N_Regexp : constant String := + "A([0-9]*):([0-9]*)(:[^ ]*)? xcov ([^ ]*)( ""(.*)"")?"; + N_Matcher : constant Pattern_Matcher := Compile (N_Regexp); + + U_Regexp : constant String := "^[^\t ]*[\t ]+([^\t ]*)"; + U_Matcher : constant Pattern_Matcher := Compile (U_Regexp); + + V_Regexp : constant String := "^V ""(.*)""$"; + V_Matcher : constant Pattern_Matcher := Compile (V_Regexp); + + function Unquote (Filename : String) return String; + -- If needed, unquote a filename, such as the ones that can be found on D + -- lines. + + procedure Mark_Ignored_Units + (Ignored_Source_Files : access GNAT.Regexp.Regexp; + Deps : SFI_Vector); + -- Mark SCOs.SCO_Unit_Table entries to be ignored by setting their Dep_Num + -- to Missing_Dep_Num. + + ------------- + -- Unquote -- + ------------- + + function Unquote (Filename : String) return String is + Result : Unbounded_String; + In_Quote : Boolean := False; + -- True when we just met a double quote inside a quoted filename. False + -- otherwise. + + begin + if Filename (Filename'First) /= '"' then + return Filename; + else + -- To unquote, just copy the string removing consecutive double + -- quotes. + + for C of Filename (Filename'First + 1 .. Filename'Last - 1) loop + if C = '"' then + if not In_Quote then + Append (Result, C); + end if; + In_Quote := not In_Quote; + else + Append (Result, C); + end if; + end loop; + return +Result; + end if; + end Unquote; + + ------------------------ + -- Mark_Ignored_Units -- + ------------------------ + + procedure Mark_Ignored_Units + (Ignored_Source_Files : access GNAT.Regexp.Regexp; + Deps : SFI_Vector) + is + use SCOs; + Deps_Present : constant Boolean := not Deps.Is_Empty; + begin + if Ignored_Source_Files = null then + return; + end if; + + for J in SCO_Unit_Table.First + 1 .. SCO_Unit_Table.Last loop + declare + U : SCO_Unit_Table_Entry renames SCO_Unit_Table.Table (J); + + SFI : constant Source_File_Index := + (if Deps_Present + then Deps.Element (U.Dep_Num) + else Get_Index_From_Generic_Name + (U.File_Name.all, Source_File)); + -- Source file corresponding to this unit. Use the name from the + -- SCO "C" line if there are no list of dependencies ("D" lines, + -- missing for old GLI files for C). + + Match_Name : constant String := Get_Simple_Name (SFI); + -- Name to use for matching against the pattern of ignored files + begin + -- In case we got SFI from the Deps vector, make sure it is + -- considered as a source file. + + Consolidate_File_Kind (SFI, Source_File); + + -- Do the ignored file matching itself + + if GNAT.Regexp.Match (Match_Name, Ignored_Source_Files.all) then + Consolidate_Ignore_Status (SFI, Always); + U.Dep_Num := Missing_Dep_Num; + else + Consolidate_Ignore_Status (SFI, Never); + end if; + end; + end loop; + end Mark_Ignored_Units; + + --------------------- + -- Get_Annotations -- + --------------------- + + function Get_Annotations (CU : CU_Id) return ALI_Annotation_Maps.Map is + begin + if CU = No_CU_Id then + return ALI_Annotation_Maps.Empty_Map; + end if; + return CU_Vector.Element (CU).ALI_Annotations; + end Get_Annotations; + + function Get_Annotations + (SFI : Source_File_Index) return ALI_Annotation_Maps.Map is + begin + return Get_Annotations (Comp_Unit (SFI)); + end Get_Annotations; + + ------------------------- + -- Get_All_Annotations -- + ------------------------- + + function Get_All_Annotations return ALI_Annotation_Maps.Map + is + use ALI_Annotation_Maps; + Result : Map; + begin + for CU of CU_Vector loop + for Cur in CU.ALI_Annotations.Iterate loop + Result.Insert (Key (Cur), Element (Cur)); + end loop; + end loop; + return Result; + end Get_All_Annotations; + + ----------------------------------- + -- Inc_Violation_Exemption_Count -- + ----------------------------------- + + procedure Inc_Violation_Exemption_Count (Sloc : Source_Location) is + E : ALI_Annotation renames + CU_Vector.Reference (Comp_Unit (Sloc.Source_File)) + .ALI_Annotations.Reference (Sloc); + begin + E.Violation_Count := E.Violation_Count + 1; + end Inc_Violation_Exemption_Count; + + ----------------------------------- + -- Inc_Undet_Cov_Exemption_Count -- + ----------------------------------- + + procedure Inc_Undet_Cov_Exemption_Count (Sloc : Source_Location) is + E : ALI_Annotation renames + CU_Vector.Reference (Comp_Unit (Sloc.Source_File)) + .ALI_Annotations.Reference (Sloc); + begin + E.Undetermined_Cov_Count := E.Undetermined_Cov_Count + 1; + end Inc_Undet_Cov_Exemption_Count; + + -------------- + -- Load_ALI -- + -------------- + + procedure Load_ALI (ALI_Filename : String) is + Discard_ALI : Source_File_Index; + Discard_Units, Discard_Deps : SFI_Vector; + Discard_Created_Units : Created_Unit_Maps.Map; + + ALI_Annotations : ALI_Annotation_Maps.Map; + ALI_Index : constant Source_File_Index := + Get_Index_From_Full_Name (ALI_Filename, Library_File, Insert => False); + begin + Discard_ALI := + Load_ALI + (ALI_Filename => ALI_Filename, + Ignored_Source_Files => null, + Units => Discard_Units, + Deps => Discard_Deps, + ALI_Annotations => ALI_Annotations, + With_SCOs => False); + + -- Add the annotations to the internal CU_Vector vector + + for Cur in ALI_Annotations.Iterate loop + declare + Sloc : constant Source_Location := + ALI_Annotation_Maps.Key (Cur); + Ignore_CU_Id : CU_Id; + begin + if not CU_Map.Contains (Sloc.Source_File) then + Ignore_CU_Id := + Allocate_CU + (Provider => Compiler, + Origin => ALI_Index, + Main_Source => Sloc.Source_File, + Fingerprint => Fingerprint_Type'(others => 0), + Created_Units => Discard_Created_Units); + end if; + CU_Vector.Reference (CU_Map.Element (Sloc.Source_File)) + .ALI_Annotations + .Include (Sloc, ALI_Annotation_Maps.Element (Cur)); + end; + end loop; + end Load_ALI; + + -------------- + -- Load_ALI -- + -------------- + + function Load_ALI + (ALI_Filename : String; + Ignored_Source_Files : access GNAT.Regexp.Regexp; + Units : out SFI_Vector; + Deps : out SFI_Vector; + ALI_Annotations : in out ALI_Annotation_Maps.Map; + With_SCOs : Boolean) return Source_File_Index + is + ALI_File : File_Type; + ALI_Index : Source_File_Index; + + Line : String_Access; + Index : Natural; + + Matches : Match_Array (0 .. 10); + -- For regex matching + + function Match (Index : Integer) return String; + -- Return Index'th match in Line + + function Get_Stripped_Line (F : File_Type) return String; + -- Like Get_Line but strip trailing CR, to allow for processing Windows + -- LI files on a UNIX host. + + function Getc return Character; + -- Consume and return next character from Line. + -- Load next line if at end of line. Return ^Z if at end of file. + + function Nextc return Character; + -- Peek at next character in Line. Return ^Z if at end of file. + + procedure Skipc; + -- Skip one character in Line + + function Check_Message (M1, M2 : String_Access) return Boolean; + -- Return True if either M1 or M2 is null or designates an empty string, + -- else return True if M1 and M2 designate identical strings. + + ------------------- + -- Check_Message -- + ------------------- + + function Check_Message (M1, M2 : String_Access) return Boolean is + begin + return False + or else M1 = null or else M1.all = "" + or else M2 = null or else M2.all = "" + or else M1.all = M2.all; + end Check_Message; + + ---------- + -- Getc -- + ---------- + + function Getc return Character is + Next_Char : constant Character := Nextc; + begin + Index := Index + 1; + if Index > Line'Last + 1 then + + -- Note: normally we should just read the next line from ALI_File + -- and reset Index. However some older versions of the compiler + -- generated duplicated SCOs in some cases, so if we get two + -- successive identical lines, we ignore them and keep reading. + + while not End_Of_File (ALI_File) loop + declare + Next_Line : constant String := Get_Stripped_Line (ALI_File); + begin + if Next_Line = Line.all then + Report + ("ignoring duplicate line in ALI file " + & ALI_Filename, Kind => Warning); + + else + Free (Line); + Line := new String'(Next_Line); + Index := 1; + + exit; + end if; + end; + end loop; + end if; + return Next_Char; + end Getc; + + ----------------------- + -- Get_Stripped_Line -- + ----------------------- + + function Get_Stripped_Line (F : File_Type) return String is + Line : constant String := Get_Line (F); + Last : Integer := Line'Last; + begin + if Last in Line'Range and then Line (Last) = ASCII.CR then + Last := Last - 1; + end if; + return Line (Line'First .. Last); + end Get_Stripped_Line; + + ----------- + -- Match -- + ----------- + + function Match (Index : Integer) return String is + begin + if Matches (Index) = No_Match then + return ""; + else + return Line (Matches (Index).First .. Matches (Index).Last); + end if; + end Match; + + ----------- + -- Nextc -- + ----------- + + function Nextc return Character is + begin + if Index = Line'Last + 1 then + return ASCII.LF; + + elsif Index in Line'Range then + return Line (Index); + + else + return Character'Val (16#1a#); + end if; + end Nextc; + + ----------- + -- Skipc -- + ----------- + + procedure Skipc is + C : Character; + pragma Unreferenced (C); + begin + C := Getc; + end Skipc; + + procedure Get_SCOs_From_ALI is new Get_SCOs; + + -- Local variables + + No_Object : Boolean := False; + -- Set True if the P line contains the NO flag + + Preserve_Control_Flow_Seen : Boolean := False; + -- Set True if unit has been compiled with -fpreserve-control-flow + + Dump_SCOs_Seen : Boolean := False; + -- Set True if unit has been compiled with -fdump-scos (or -gnateS) + + Debug_Seen : Boolean := False; + -- Set True if unit has been compiled with -g + + Profile_Arcs_Seen : Boolean := False; + -- Set True if unit has been compiled with -fprofile-arcs + + Expected_Annotation_Kind : ALI_Annotation_Kind; + Expected_Annotation_Msg : String_Access; + -- Variables for checking of annotation validity: annotations must + -- come in (Exempt_On, Exempt_Off) pairs, nesting forbidden, and + -- the Exempt_Off message must be either empty or identical to the + -- Exempt_On one. + + -- Start of processing for Load_ALI + + begin + pragma Assert (Deps.Last_Index = 0); + + -- First check whether this ALI has been already loaded. We identify + -- this by the fact that it already has an assigned Source_File_Index. + + ALI_Index := Get_Index_From_Full_Name + (ALI_Filename, Library_File, Insert => False); + if ALI_Index /= No_Source_File then + Report + ("ignoring duplicate ALI file " & ALI_Filename, Kind => Warning); + return No_Source_File; + end if; + + ALI_Index := Get_Index_From_Full_Name + (ALI_Filename, Library_File, Insert => True); + Log_File_Open (ALI_Filename); + Open (ALI_File, In_File, ALI_Filename); + + -- Check that the first line is a valid ALI V line. + + declare + V_Line : constant String := Get_Stripped_Line (ALI_File); + Error_Msg : Unbounded_String; + begin + Match (V_Matcher, V_Line, Matches); + if Matches (0) = No_Match then + Error_Msg := + +("malformed ALI file """ & ALI_Filename & """"); + + if V_Line'Length > 3 + and then + To_Lower (V_Line (V_Line'Last - 3 .. V_Line'Last)) = ".ali" + then + Append + (Error_Msg, + ASCII.LF + & "to load ALIs from list use ""--scos=@" + & ALI_Filename & """"); + end if; + Fatal_Error (+Error_Msg); + end if; + end; + + -- Here once the ALI file has been succesfully opened + + SCOs_Trace.Trace ("Loading SCOs from " & ALI_Filename); + + Expected_Annotation_Kind := Exempt_On; + Expected_Annotation_Msg := null; + + Scan_ALI : while not End_Of_File (ALI_File) loop + loop + Free (Line); + Line := new String'(Get_Stripped_Line (ALI_File)); + exit when Line'Length > 0; + end loop; + + case Line (1) is + when 'A' => + if Line.all = "A -fpreserve-control-flow" then + Preserve_Control_Flow_Seen := True; + + elsif Line.all = "A -fdump-scos" + or else + Line.all = "A -gnateS" + then + Dump_SCOs_Seen := True; + + elsif Line.all = "A -g" then + Debug_Seen := True; + + elsif Line.all = "A -fprofile-arcs" then + Profile_Arcs_Seen := True; + end if; + + when 'P' => + declare + P_Start : Integer; + begin + P_Start := 2; + loop + while P_Start <= Line'Last + and then Line (P_Start) = ' ' + loop + P_Start := P_Start + 1; + end loop; + exit when P_Start > Line'Last - 1; + + declare + Param : constant String (1 .. 2) := + Line (P_Start .. P_Start + 1); + begin + if Param = "NO" then + No_Object := True; + end if; + end; + + P_Start := P_Start + 2; + end loop; + end; + + when 'U' => + Match (U_Matcher, Line (3 .. Line'Last), Matches); + if Matches (0) /= No_Match then + Units.Append (Get_Index_From_Generic_Name (Match (1), + Source_File)); + end if; + + when 'D' => + Match (D_Matcher, Line (3 .. Line'Last), Matches); + if Matches (0) /= No_Match then + + -- Dependency files are source files. However, in order to + -- avoid unnecessary conflicts at consolidation time, we + -- don't want to consider them for coverage analysis unless + -- they are in the units of interest. So consider them as + -- stubs at this stage. + + Deps.Append (Get_Index_From_Generic_Name + (Unquote (Match (1)), Stub_File)); + end if; + + when 'N' => + declare + Annotation : ALI_Annotation; + Valid : Boolean; + Sloc : Source_Location; + begin + Match (N_Matcher, Line (3 .. Line'Last), Matches); + if Matches (0) /= No_Match then + declare + Note_SFN : constant String := Match (3); + Note_SFI : Source_File_Index := Units.Last_Element; + + begin + if Note_SFN'Length > 0 then + + -- Case of a separate: the source file is not the + -- current compilation unit but some other one + -- identified explicitly. + + Note_SFI := Get_Index_From_Generic_Name + (Note_SFN (Note_SFN'First + 1 + .. Note_SFN'Last), + Source_File); + end if; + + Sloc := + (Source_File => Note_SFI, + L => (Line => + Integer'Value (Match (1)), + Column => + Integer'Value (Match (2)))); + end; + + Valid := True; + + declare + Msg : constant String := Match (6); + begin + Annotation := + (Kind => ALI_Annotation_Kind'Value (Match (4)), + Message => (if Msg'Length > 0 + then new String'(Msg) + else null), + others => <>); + exception + when Constraint_Error => + Report (Sloc, "bad annotation " & Match (4)); + Valid := False; + end; + + if Valid then + if Annotation.Kind /= Expected_Annotation_Kind then + Report (Sloc, "unexpected " + & Annotation.Kind'Img & " " + & Annotation.Message.all + & " (expected " + & Expected_Annotation_Kind'Img + & ")"); + elsif not Check_Message + (Annotation.Message, Expected_Annotation_Msg) + then + Report (Sloc, "unexpected EXEMPT_OFF " + & Annotation.Message.all + & " (expected " + & Expected_Annotation_Msg.all + & ")"); + end if; + + if Annotation.Kind = Exempt_On then + if Annotation.Message = null then + Report (Sloc, "empty message for EXEMPT_ON"); + end if; + + Expected_Annotation_Kind := Exempt_Off; + Expected_Annotation_Msg := Annotation.Message; + + else + Expected_Annotation_Kind := Exempt_On; + Expected_Annotation_Msg := null; + end if; + + ALI_Annotations.Insert + (Key => Sloc, New_Item => Annotation); + end if; + end if; + end; + + when 'C' => + exit Scan_ALI; + + when others => + null; + end case; + end loop Scan_ALI; + + if Expected_Annotation_Kind = Exempt_Off then + declare + use ALI_Annotation_Maps; + Last_Ann_Cursor : constant Cursor := ALI_Annotations.Last; + Last_Ann_Sloc : constant Source_Location := + Key (Last_Ann_Cursor); + Last_Ann : constant ALI_Annotation := + Element (Last_Ann_Cursor); + begin + Report (Last_Ann_Sloc, + "missing Exempt_Off " & Last_Ann.Message.all); + end; + end if; + + if With_SCOs then + if No_Object then + Warn ("no object generated for " & ALI_Filename); + + else + if not Preserve_Control_Flow_Seen then + Warn + (ALI_Filename + & ": unit compiled without -fpreserve-control-flow"); + end if; + + if not Dump_SCOs_Seen then + Warn + (ALI_Filename + & ": unit compiled without SCO generation (-fdump-scos)"); + end if; + + if not Debug_Seen then + Warn + (ALI_Filename + & ": unit compiled without debug information (-g)"); + end if; + + if Profile_Arcs_Seen then + Warn + (ALI_Filename + & ": unit compiled with instrumentation (-fprofile-arcs)"); + end if; + end if; + + if not End_Of_File (ALI_File) + and then Dump_SCOs_Seen + and then not No_Object + then + Index := 1; + Get_SCOs_From_ALI; + Mark_Ignored_Units (Ignored_Source_Files, Deps); + + else + -- In this case, we will not parse SCOs: reset parsing tables so + -- that further processing don't start using stale SCO entries. + + SCOs.Initialize; + end if; + end if; + + Close (ALI_File); + return ALI_Index; + end Load_ALI; + ---------------- -- Sloc_Range -- ---------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index faac6ee1c..5ef91334a 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -28,6 +28,7 @@ with Ada.Containers.Multiway_Trees; with GNAT.Regexp; with GNAT.SHA1; +with GNAT.Strings; use GNAT.Strings; with Namet; with Types; use Types; @@ -136,6 +137,9 @@ package SC_Obligations is function Bit_Maps_Fingerprint (CU : CU_Id) return Fingerprint_Type; -- Hash of buffer bit mappings in CU + function Annotations_Fingerprint (CU : CU_Id) return Fingerprint_Type; + -- Hash of annotations in CU + function Comp_Unit (Src_File : Source_File_Index) return CU_Id; -- Return the identifier for the compilation unit containing the given -- source, or No_CU_Id if no such LI file has been loaded. @@ -149,6 +153,86 @@ package SC_Obligations is -- Emit an error message for any unit of interest for which no object code -- has been seen. + --------------- + -- ALI files -- + --------------- + + type ALI_Annotation_Kind is + (Exempt_On, Exempt_Off, Dump_Buffers, Reset_Buffers, Cov_On, Cov_Off); + + type ALI_Annotation is record + Kind : ALI_Annotation_Kind; + -- On or Off, Dump or Reset coverage buffers + + Message : String_Access; + -- When Kind = Exempt_On, justification message for the exemption. + -- This is null if no justification is given (i.e. this is never an + -- access to an empty string). + + Violation_Count : Natural := 0; + -- When Kind = Exempt_On, this counts the violation "hits" on this + -- exemption: + -- + -- * exempted violation messages if generating a report, + -- + -- * exempted non/partially covered lines otherwise. + + Undetermined_Cov_Count : Natural := 0; + -- When Kind = Exempt_On, this counts the number of "hits" for + -- undetermined coverage items: currently exempted non-instrumented + -- messages when generating a report, or lines marked as + -- non instrumented otherwise. + -- + -- This is relevant only for source trace based coverage analysis. + end record; + + package ALI_Annotation_Maps is + new Ada.Containers.Ordered_Maps + (Key_Type => Source_Location, + Element_Type => ALI_Annotation); + + procedure Set_Annotations (Annotations : ALI_Annotation_Maps.Map); + -- Set annotations. Add them to the right CU_Info according to their + -- source location. + + function Get_Annotations (CU : CU_Id) return ALI_Annotation_Maps.Map; + function Get_Annotations + (SFI : Source_File_Index) return ALI_Annotation_Maps.Map; + -- Return the set of annotations for the given compilation unit / source + -- file index. + + function Get_All_Annotations return ALI_Annotation_Maps.Map; + -- Return all annotations + + procedure Inc_Violation_Exemption_Count (Sloc : Source_Location); + -- Increment the exempted line/message violation counter for exemption at + -- Sloc. + + procedure Inc_Undet_Cov_Exemption_Count (Sloc : Source_Location); + -- Increment the exempted line/message undetermined coverage items counter + -- for exemption at Sloc. + + procedure Load_ALI (ALI_Filename : String); + -- Load ALI information for Filename, without SCOs + + function Load_ALI + (ALI_Filename : String; + Ignored_Source_Files : access GNAT.Regexp.Regexp; + Units : out SFI_Vector; + Deps : out SFI_Vector; + ALI_Annotations : in out ALI_Annotation_Maps.Map; + With_SCOs : Boolean) return Types.Source_File_Index; + -- Load coverage related information (coverage exemptions and, if With_SCOs + -- is True, source coverage obligations) from ALI_Filename. Returns the + -- source file index for the ALI file. Subsequent calls for the same ALI + -- file will return No_Source_File immediately, without reloading the file. + -- Units are the units contained in this compilation. + -- + -- Ignore all source obligations according to Ignored_Source_Files (see + -- SC_Obligations.Load_SCOs' documentation). + -- + -- Deps are the dependencies of the compilation. + --------------- -- Instances -- --------------- diff --git a/tools/gnatcov/traces_source.ads b/tools/gnatcov/traces_source.ads index 3642165d8..fa060891c 100644 --- a/tools/gnatcov/traces_source.ads +++ b/tools/gnatcov/traces_source.ads @@ -48,13 +48,14 @@ package Traces_Source is -- trace entries start and end on byte/half word/word/long word boundaries. type Trace_File_Format_Version is new Unsigned_32; - Current_Version : Trace_File_Format_Version := 3; + Current_Version : Trace_File_Format_Version := 4; -- Expected value of the Trace_File_Header.Format_Version field. -- -- 0 -- initial version -- 1 -- extend trace entry model to account for C files -- 2 -- introduce fingerprints for bit maps -- 3 -- remove the project name from trace entries + -- 4 -- introduce fingerprint for annotations type Any_Alignment is new Unsigned_8; subtype Supported_Alignment is Any_Alignment; @@ -247,24 +248,30 @@ package Traces_Source is -- be able to interpret buffer bits from a source traces using buffer -- bit mappings from SID files. - Padding : String (1 .. 5); + Annotations_Fingerprint : Fingerprint_Type; + -- Hash of annotations for this unit, as gnatcov computes it (see + -- SC_Obligations). Used as a fast way to check that source traces and + -- coverage data are consistent. + + Padding : String (1 .. 1); -- Padding used only to make the size of this trace entry header a -- multiple of 8 bytes. Must be zero. end record; for Trace_Entry_Header use record - Unit_Name_Length at 0 range 0 .. 31; - Statement_Bit_Count at 4 range 0 .. 31; - Decision_Bit_Count at 8 range 0 .. 31; - MCDC_Bit_Count at 12 range 0 .. 31; - Language_Kind at 16 range 0 .. 7; - Unit_Part at 17 range 0 .. 7; - Bit_Buffer_Encoding at 18 range 0 .. 7; - Fingerprint at 19 range 0 .. 20 * 8 - 1; - Bit_Maps_Fingerprint at 39 range 0 .. 20 * 8 - 1; - Padding at 59 range 0 .. 5 * 8 - 1; + Unit_Name_Length at 0 range 0 .. 31; + Statement_Bit_Count at 4 range 0 .. 31; + Decision_Bit_Count at 8 range 0 .. 31; + MCDC_Bit_Count at 12 range 0 .. 31; + Language_Kind at 16 range 0 .. 7; + Unit_Part at 17 range 0 .. 7; + Bit_Buffer_Encoding at 18 range 0 .. 7; + Fingerprint at 19 range 0 .. 20 * 8 - 1; + Bit_Maps_Fingerprint at 39 range 0 .. 20 * 8 - 1; + Annotations_Fingerprint at 59 range 0 .. 20 * 8 - 1; + Padding at 79 range 0 .. 1 * 8 - 1; end record; - for Trace_Entry_Header'Size use 64 * 8; + for Trace_Entry_Header'Size use 80 * 8; end Traces_Source; From 63d71535525277c22de97fb05eec03bd61ff2d47 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 16 Aug 2024 12:01:24 +0200 Subject: [PATCH 0891/1483] Fix arch-mix update script --- testsuite/tests/U204-026-arch-mix/README.md | 3 +++ testsuite/tests/U204-026-arch-mix/update.sh | 2 +- .../tests/U204-026-arch-mix/update_arch_mix_windows.sh | 6 +++--- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/testsuite/tests/U204-026-arch-mix/README.md b/testsuite/tests/U204-026-arch-mix/README.md index 89e6d3138..e3e2f1dd5 100644 --- a/testsuite/tests/U204-026-arch-mix/README.md +++ b/testsuite/tests/U204-026-arch-mix/README.md @@ -18,5 +18,8 @@ In addition, also install the sshpass utility, available through apt: apt install -y sshpass ``` +In order for the update to work on windows, push the contents of your branch to +the eng/das/cov/gnatcoverage origin remote. + Then, to update instrumentation and trace artifacts for all hosts / targets, run the `update.sh` script. diff --git a/testsuite/tests/U204-026-arch-mix/update.sh b/testsuite/tests/U204-026-arch-mix/update.sh index 3504e16d6..d31d36544 100755 --- a/testsuite/tests/U204-026-arch-mix/update.sh +++ b/testsuite/tests/U204-026-arch-mix/update.sh @@ -23,4 +23,4 @@ cp -rf /tmp/U204-026-arch-mix/* . /tmp/iod-dev/create-base.py --base-image x86_64-windows-2019 git_branch=$(git rev-parse --abbrev-ref HEAD) sshpass ssh iod 'bash -s' < update_arch_mix_windows.sh $git_branch -rsync -av iod:/Users/itmgr/gnatcoverage/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/* gen/x86_64-windows/ +rsync -av iod:/cygdrive/c/tmp/U204-026-arch-mix/gen/* gen/ diff --git a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh index 67dd4b2ee..4886d690d 100755 --- a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh +++ b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh @@ -1,7 +1,5 @@ # Update windows artifacts for U204-026-arch-mix -set -e - if [ $# -eq 0 ]; then echo "No arguments provided. Please provide the name of the gnatcov branch" exit 1 @@ -14,7 +12,8 @@ anod init wave # Checkout the right gnatcov branch cd /Users/itmgr/gnatcoverage -git checkout $1 +git fetch origin +git checkout origin/$1 # Build gnatcov cd /Users/itmgr/wave @@ -28,6 +27,7 @@ rm -rf /Users/itmgr/gnatcoverage/testsuite/tests/U204-026-arch-mix/gen/x86_64-wi cp -r /Users/itmgr/gnatcoverage/testsuite/tests/U204-026-arch-mix /cygdrive/c/tmp cd /cygdrive/c/tmp/U204-026-arch-mix chmod +x gen.sh +gnatcov setup ./gen.sh windows # Copy back the generated sources From 9aaa9d9e6c8bc4e8b8000b6757cf43a617b602ff Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 16 Aug 2024 15:08:10 +0200 Subject: [PATCH 0892/1483] Update U204-026 test following checkpoint / traces version format bump --- .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 1508 -> 668 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2596 -> 2036 bytes .../gen/arm-elf-linux/gcvrt-bz3791e32c.ads | 2 ++ .../gen/arm-elf-linux/gcvrt-bz794ac68b.ads | 1 + .../gen/arm-elf-linux/gcvrt-bz794ac68c.ads | 1 + .../gen/arm-elf-linux/gcvrt-pz3791e32c.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68b.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68c.ads | 2 +- .../gen/arm-elf-linux/main_1.adb | 2 +- .../gen/arm-elf-linux/main_1.sid | Bin 410 -> 446 bytes .../gen/arm-elf-linux/main_2.adb | 2 +- .../gen/arm-elf-linux/main_2.sid | Bin 410 -> 446 bytes .../gen/arm-elf-linux/pkg.sid | Bin 1059 -> 1135 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1851 -> 1919 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1861 -> 1929 bytes .../U204-026-arch-mix/gen/main_1.srctrace | Bin 416 -> 480 bytes .../U204-026-arch-mix/gen/main_2.srctrace | Bin 384 -> 448 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 1996 -> 2152 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 1927 -> 2083 bytes .../gen/x86_64-windows/gcvrt-bz3791e32c.ads | 2 ++ .../gen/x86_64-windows/gcvrt-bz794ac68b.ads | 1 + .../gen/x86_64-windows/gcvrt-bz794ac68c.ads | 1 + .../gen/x86_64-windows/gcvrt-pz3791e32c.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68b.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68c.ads | 2 +- .../gen/x86_64-windows/main_1.adb | 2 +- .../gen/x86_64-windows/main_1.sid | Bin 412 -> 448 bytes .../gen/x86_64-windows/main_2.adb | 2 +- .../gen/x86_64-windows/main_2.sid | Bin 412 -> 448 bytes .../gen/x86_64-windows/pkg.sid | Bin 1063 -> 1139 bytes .../tests/U204-026-arch-mix/main_2-out.txt | 13 +++++++------ 31 files changed, 25 insertions(+), 16 deletions(-) diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index 3847bda74fe611ddb071b62731490ed2c810c471..5c5bff2c03eeb11b054484df81c5058276939645 100644 GIT binary patch literal 668 zcmYk2ze`(D6vxkdO_PhpVqQZjC6uQL;u8AuUSdrK2Z;`XU`tyZgeGc-mb8VmgOh`U z6cHy0C6hykBAuKa@&|}GIdyW7%nstv!OwZ`4h`IV-uHX%`EgJ2)xz@I@|$jZt>CKfUZ<5ymW^%;>2-;X(A5LU~RT0ID=wJ55il3(%v{@R)Tr3YeCl9N9fF_YrSIn2W=Xz+g+F)p0u z-V^*em_;Y_WGVJ@(t#fFZK!z(J=sNT{ZrT^PFr*2KrZjl>9B2 zM(7&w2mk9Fa;OkGuVPz*n#?v9jJS|BX0_Bx=CIame40q_tdlgFR1l? z!x5NhM{cZt8~eVvcE87H&A)~&_lI#jC(r4t{!jYqJA9~fytDei?&A<@ybtyL_pCZW A`~Uy| literal 1508 zcmYk6O-NKx7>2)@rtv0X-CIORivzll(7H2CG=>X_DI_dPrf3nQW?<2eRD=r`A|fI~ zh)9Tpw1|)pkr0t+Au@!7xDb(uXcZyR+C{70_skn4UY~it=Q}@hujkfZyKwn>bMZ;{ zox4vH$&^{68U9*;Yqu&mP+fb_68Kz=>v7NhQxCiEJ-VGSOC$4gnX|cUY*vNOhjC@& zY_2)ZH^(h56Q9fE@ayN|c$dkaKGTxV#OVL`Q~&?^Tp8;(?z13ep)FQfkThrSJtJEJ zQ^+gIAHV>4O}Q+;uKd~i$hLfTwypXOc*r9A>3wLWfa`?TgmsUiejcnrt}wDIz8+dX z7{L#N0epp#jU#ivtDervo{_DCY3y%Pc?&#=@%WlS6Y5Q13ONRGcRZPMzV0k9-zrbi zx5*cj+vQ364*9FfMX(d|zg2z*ay^p$3!b>o%FEyy{J{Q-9|YM?vVX|a*@*I(JV{@Y zpHQBXC+Vl+gR@VbxPKs@_lEMOXJ~KG&;5{`Z_d-%yz-(vNxvk&qWn>w zq+b=ws*|j*gZ}v`Z^@JNJK|T>N!GuE9QQ+c7c3&TrYpV;hp$KW7d2Xq?f?J) diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_2.trace b/testsuite/tests/U204-026-arch-mix/bin-main_2.trace index f42903d9e2869276e89b694b0a534c8a8cad1063..e863c76b1b7bb3bd2a83ca8c276d8f62e1b4cbcb 100644 GIT binary patch delta 148 zcmZ1?@`ZnbJc|G?lhQ0uyfX##Q>){qYfGXgDDtLot;0H7VV0@T^zrfW)EcgNELmc!6jnBXX za)&bm&;bw)EMNf;AEJQ+%7?ia#)rxCz|>Fv%i6EV0X4+}CJHsh2FmA|+{>n~2=iPF znyLgCfAU^7jVLGwW@G@&2&feXAR@p-pnO<>!T7KM0|4!|F=PM$ diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads index 19defc245..4f8fb6567 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz3791e32c.ads @@ -27,6 +27,7 @@ package Buffers_1 is Unit_Part => Unit_Spec, Unit_Name => (Unit_Name'Address, Unit_Name'Length), Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, @@ -56,6 +57,7 @@ package Buffers_2 is Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), Bit_Maps_Fingerprint => (31, 7, 116, 68, 128, 108, 109, 251, 97, 162, 61, 255, 238, 251, 162, 56, 7, 34, 238, 156), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads index 2ba90de4d..98a55c9bb 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68b.ads @@ -27,6 +27,7 @@ package Buffers_1 is Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), Bit_Maps_Fingerprint => (14, 208, 170, 79, 214, 204, 239, 198, 105, 130, 182, 250, 66, 192, 111, 106, 70, 106, 188, 135), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads index a7410a898..4bc122bc6 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-bz794ac68c.ads @@ -27,6 +27,7 @@ package Buffers_1 is Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), Bit_Maps_Fingerprint => (14, 208, 170, 79, 214, 204, 239, 198, 105, 130, 182, 250, 66, 192, 111, 106, 70, 106, 188, 135), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads index aa24ad350..59a1337ec 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz3791e32c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads index bc3a938bb..faa4d9e4d 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68b is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads index d5709f6fb..5e6ce0228 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb index 2907ece19..d7ef728a8 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=7,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=8,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); GCVRT.DB_z794ac68b.Dump_Buffers;end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index 3ce2380ef56b8dd8f1ee342c2ba8dd5b88062549..4708c617687ec39a6caa21ba1f8ff7ef47cc7977 100644 GIT binary patch delta 77 zcmbQmypLJL-On*3IloLHIU_YWyC6R^uY^HhqDZSOBLf2iGG>PI*?=_9#9M|OKpG4t LPPLfK%s3qYgwPGn delta 52 zcmdnTJd0Vx-On*3IloLHIU_YWyC6R^uY`erqDbq+&nCQ#3=9l#JaL=hWPQed0G=WZ A`2YX_ diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb index 7ffd105bc..4bbc2b311 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=7,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=8,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); GCVRT.DB_z794ac68c.Dump_Buffers;end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid index b7c2843c8f2bd72f166d384049dc653656aa08a0..e200e6f637df233b35534e1df05d4e16351dc563 100644 GIT binary patch delta 77 zcmbQmypLJL-On*3IloLHIU_YWyC6R^uY^HhqDZSOBLf2iGG>PI*?=_9#9M|OKpG4t LPPLfK%s3qYgwPGn delta 52 zcmdnTJd0Vx-On*3IloLHIU_YWyC6R^uY`erqDbq+&nCQ#3=9l#JaL=hWPQed0G=WZ A`2YX_ diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid index c7e885ae91b00ee8d7f1ded72bc167cb1f03ba59..3df827109252dc14151314cafc6be6bc105a70f9 100644 GIT binary patch delta 107 zcmZ3?@t#A(-On*3IloLHIU_YWyC6R^uY^HhqR5uXnamQC6PQ>gp3s^2!%UWmfq{V$ tirIlQGn6d^q&X+gWYps21hQCwSOA14A7Ip*T)-?iS)Va>^D9P6CIF6M7MK74 delta 66 zcmaFQv6w@|-On*3IloLHIU_YWyC6R^uY`erqR5tsPjn{pFj`H%!5GKO#K6G72*vD^ RlNq%p&t=r!Y{g{C1OT(55!nC$ diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt index 27f302cbdab38aaa4f44be3ee8b9c3860ed3610b..7a1889f46a14049be47f4266b5957e0ecbd8536d 100644 GIT binary patch delta 130 zcmdnZ_n%M1-On*3IloLHIU_YWyC6R^uY^HhqlgC6WGiOT$(Br>V7i_uV6p=|85n?+g8+;M0P@EnIsgCw delta 114 zcmey*x0_GI-On*3IloLHIU_YWyC6R^uY`erqlgC6#r#d2;21eiEE6ova3g*(}p(HB{Iay6qW0F5CD8vpj;qm diff --git a/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace b/testsuite/tests/U204-026-arch-mix/gen/main_2.srctrace index ee5a68bf6c0a80ce6745cdad4d6da76e31c17cd3..7dd13a1b78d51f5016f250edc68cc7e9524ad1cf 100644 GIT binary patch delta 90 ycmZo*KEOOdfstjRVlg)Z0!-`=MB&~>;Z9a(^i)77hOi2<(;1k7OeP>^0b&3LUkKj- delta 38 rcmX@W+`v3RfsuKlV)4W!K9d-ICdV+k2oz+eGcYqSFfaiz3lIYU(2WQW diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 645b0a7ad381c4512688943e9e6c43bb33023677..520943c838f06096f59d01382548dfb34b9ba62b 100644 GIT binary patch delta 166 zcmX@Z|3W~--On*3IloLHIU_YWyC6R^uY^Hhqeu=TFEaxJ10xW#0Wr_yT1M5$9n2Dw z7csh_$vlP1a4}g;?gXlEVRGYy=@pvX%%sQ52{eHPhy_4+@;WBH$rG3bH{WD>!YtqL jdV90uS@Dw~i$Kywrg{eD3K~WRMkWRphNhG6uzdgk^duz{ delta 81 zcmV-X0IvV&5X=u0M@~UhV{djKV`yb#YjAIAZgc<-u@r0plaK)-lga@`lOO^jlUf2g nldJ+plL7-LlQ{z`vv>pH0|yv)?Y=3V6_a2G76LFhlXwU4R@xf4 diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt index e244bea0f2ec6d2bb4d505c9da4d8084e3074517..134f9b4f88c18b15dbb7717b429a73519ab197dc 100644 GIT binary patch delta 167 zcmZqYUo0Tv?&lbioL{DpoRONGU67xdSHd8$Q6zZlO>pxCI>NDOi<4ObjdxEHoz Unit_Spec, Unit_Name => (Unit_Name'Address, Unit_Name'Length), Bit_Maps_Fingerprint => (18, 188, 239, 54, 111, 156, 46, 122, 240, 90, 103, 226, 23, 122, 35, 87, 156, 185, 141, 194), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, @@ -56,6 +57,7 @@ package Buffers_2 is Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), Bit_Maps_Fingerprint => (31, 7, 116, 68, 128, 108, 109, 251, 97, 162, 61, 255, 238, 251, 162, 56, 7, 34, 238, 156), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads index 2d3700afa..f18b67c82 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68b.ads @@ -27,6 +27,7 @@ package Buffers_1 is Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), Bit_Maps_Fingerprint => (14, 208, 170, 79, 214, 204, 239, 198, 105, 130, 182, 250, 66, 192, 111, 106, 70, 106, 188, 135), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads index 98b03e63a..16970adcb 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-bz794ac68c.ads @@ -27,6 +27,7 @@ package Buffers_1 is Unit_Part => Unit_Body, Unit_Name => (Unit_Name'Address, Unit_Name'Length), Bit_Maps_Fingerprint => (14, 208, 170, 79, 214, 204, 239, 198, 105, 130, 182, 250, 66, 192, 111, 106, 70, 106, 188, 135), + Annotations_Fingerprint => (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), Statement => Statement_Buffer'Address, Decision => Decision_Buffer'Address, MCDC => MCDC_Buffer'Address, diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads index d736880fc..3e54dc4f9 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz3791e32c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads index 8bc7f44f9..c37eb3685 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68b is diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads index 650e4a63f..a41ab39aa 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 7, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb index e30a47621..c7f0007ae 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=7,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=8,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is GNATcov_Dump_Object:GCVRT.DB_z794ac68b.Dump_Controlled_Type;begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid index d54d4518ed370abfd0c4c72fc082ed0d17386ca5..56db5bf555e9a0779c08b1ec0573398110a54fc0 100644 GIT binary patch delta 88 zcmbQke1KWR-On*3IloLHIU_YWyC6R^uY^HhqDZ?eBLf2iGG>PI*?=_9#5;zQ0~lG* N@x;YClUW(30{~V{5?TNN delta 52 zcmX@WJcn7t-On*3IloLHIU_YWyC6R^uY`erqDcG1uO_^V3=9l#JaLENWJAV&0H0tE A1poj5 diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb index 53de509b9..0480a5e96 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=7,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=8,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is GNATcov_Dump_Object:GCVRT.DB_z794ac68c.Dump_Controlled_Type;begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid index 8d53b75a1e00857651b85b903fb475437fd797f6..809b7fefd0e6aba105cd0a0e55fe6ffacfb38b0a 100644 GIT binary patch delta 88 zcmbQke1KWR-On*3IloLHIU_YWyC6R^uY^HhqDZ?eBLf2iGG>PI*?=_9#5;zQ0~lG* N@x;YClUW(30{~V{5?TNN delta 52 zcmX@WJcn7t-On*3IloLHIU_YWyC6R^uY`erqDcG1uO_^V3=9l#JaLENWJAV&0H0tE A1poj5 diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid index 51759c7994491e4d50466c9c5148f83b5d698804..78a506f4145a99f1144827953e78b69279a51ec5 100644 GIT binary patch delta 111 zcmZ3^@tH%!-On*3IloLHIU_YWyC6R^uY^HhqR5WPJDCM1A7JL1cv^SjA2V4d1_lO3 sC}s!J%uu!vkmj5`mr;wC6Ubr#VgV4Ie1uUCq#KOQ7^617W3*%f05NPC6#xJL delta 66 zcmey&v7AH1-On*3IloLHIU_YWyC6R^uY`erqR5VkFLWjgFj`H%!x+cQ#K6G72*vD^ R(;2lUFJ#o-Y{z8E1OT`?5&ZxF diff --git a/testsuite/tests/U204-026-arch-mix/main_2-out.txt b/testsuite/tests/U204-026-arch-mix/main_2-out.txt index 3451400b6..bef2cf381 100644 --- a/testsuite/tests/U204-026-arch-mix/main_2-out.txt +++ b/testsuite/tests/U204-026-arch-mix/main_2-out.txt @@ -1,11 +1,12 @@ true == GNATcoverage source trace file == -R05BVGNvdiBzb3VyY2UgdHJhY2UgZmlsZQAAAAAAAAADAAAABAAAAAEAAAADAAAARm9vAAIAAAAIAAAA +R05BVGNvdiBzb3VyY2UgdHJhY2UgZmlsZQAAAAAAAAAEAAAABAAAAAEAAAADAAAARm9vAAIAAAAIAAAA AAAAAAAAAAADAAAAAAAAAAAAAAAAAAAABgAAAAEAAAAAAAAAAAAAAAABAH0bAHG8jOubvn207otfbMbl -SN4LDtCqT9bM78Zpgrb6QsBvakZqvIcAAAAAAG1haW5fMQAAAAAAAAYAAAABAAAAAAAAAAAAAAAAAQDy -7SEPea9qoJHh4gqvEM/fGhsblA7Qqk/WzO/GaYK2+kLAb2pGaryHAAAAAABtYWluXzIAAAEAAAADAAAA -AAAAAAAAAAAAAAAAAAIArId4g1FBqtqcV5oeI0dgpg6hfdgSvO82b5wuevBaZ+IXeiNXnLmNwgAAAAAA -cGtnAAMAAAADAAAAAgAAAAMAAAAAAQCpSGO3og9c8i7R8zewUhE+/kyZMB8HdESAbG37YaI9/+77ojgH -Iu6cAAAAAABwa2cAAwAAAAIAAAAEAAAA +SN4LDtCqT9bM78Zpgrb6QsBvakZqvIcAAAAAAAAAAAAAAAAAAAAAAAAAAABtYWluXzEAAAAAAAAGAAAA +AQAAAAAAAAAAAAAAAAEA8u0hD3mvaqCR4eIKrxDP3xobG5QO0KpP1szvxmmCtvpCwG9qRmq8hwAAAAAA +AAAAAAAAAAAAAAAAAAAAAG1haW5fMgAAAQAAAAMAAAAAAAAAAAAAAAAAAAAAAgCsh3iDUUGq2pxXmh4j +R2CmDqF92BK87zZvnC568Fpn4hd6I1ecuY3CAAAAAAAAAAAAAAAAAAAAAAAAAAAAcGtnAAMAAAADAAAA +AgAAAAMAAAAAAQCpSGO3og9c8i7R8zewUhE+/kyZMB8HdESAbG37YaI9/+77ojgHIu6cAAAAAAAAAAAA +AAAAAAAAAAAAAAAAcGtnAAMAAAACAAAABAAAAA== == End == From 07368841a5b8a52f73475f2deb8af626a0b3acd9 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 16 Aug 2024 15:12:08 +0200 Subject: [PATCH 0893/1483] Update 207-srctrace-version test Following changes to the trace format. --- .../tests/207-srctrace-version/foo.c.sid | Bin 1129 -> 1195 bytes testsuite/tests/207-srctrace-version/main.sid | Bin 1363 -> 1431 bytes .../207-srctrace-version/reference.srctrace | Bin 304 -> 336 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid index 5c7abb43ec2597faf22b1fcd644e66ab9a0c229b..bf7313e5187484f56706fdb85eaeb26e732eef65 100644 GIT binary patch delta 172 zcmaFKv6@rF-On*3IloLHIU_YWyC6R^uY^Hhqlh}=!~?98r!n$NF(3g(Ae$A4)AIB6 zk{KtjXO!k;2692d>_E&k`8cEA(f~DzB^3Yw delta 125 zcmZ3@`I1A#-On*3IloLHIU_YWyC6R^uY`erqlh}=04?rMS12!{`)67hjKF@z{JV5$lS@?jH&<=(g=b8 delta 25 hcmcb>w1H`Y0weQ8MS14buUjWNhfZ8kG1-7o0RV9*2-*Mu From 7230026ab09addb6620b5fd5b37d0372e082046c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 19 Aug 2024 11:45:48 +0200 Subject: [PATCH 0894/1483] selective-instr: adapt test to make it work for cross targets --- .../223-selective-instr/unsupported/test.py | 60 +++++++++++-------- 1 file changed, 34 insertions(+), 26 deletions(-) diff --git a/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py b/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py index d09f37329..3f675bb31 100644 --- a/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py +++ b/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py @@ -5,6 +5,7 @@ current source instrumentation data. """ +import os import os.path from SCOV.minicheck import build_and_run, check_xcov_reports @@ -17,41 +18,48 @@ # Generate the root project root_project = gprfor(srcdirs=[os.path.join("..")], mains=["test.c"]) +gprsw = GPRswitches(root_project) # Configure the build with -DA which results in the inclusion of an annotated # region at pkg.c from line 3 to line 6. -build_and_run( - gprsw=GPRswitches(root_project), - covlevel="stmt", - mains=["test"], - extra_instr_args=[ - "--c-opts=-DA", - "--dump-filename-simple", - "--dump-filename-prefix=a", - ], - extra_coverage_args=["-axcov", "--output-dir=xcov"], - trace_mode="src", - dump_trigger="main-end", +tmp_a = Wdir("a") +trace_a = os.path.abspath( + build_and_run( + gprsw=gprsw, + covlevel="stmt", + mains=["test"], + extra_instr_args=["--c-opts=-DA"], + gpr_exe_dir="..", + extra_coverage_args=[], + trace_mode="src", + )[-1] ) +tmp_a.to_homedir() # Configure the build with -DB which results in the inclusion of an annotated # region at pkg.c from line 8 to line 11, thus differing from the above. -cov_args = build_and_run( - gprsw=GPRswitches(root_project), - covlevel="stmt", - mains=["test"], - extra_instr_args=[ - "--c-opts=-DB", - "--dump-filename-simple", - "--dump-filename-prefix=b", - ], - extra_coverage_args=["-axcov", "--output-dir=xcov"], - trace_mode="src", - dump_trigger="main-end", +tmp_b = Wdir("b") +trace_b = os.path.abspath( + build_and_run( + gprsw=gprsw, + covlevel="stmt", + mains=["test"], + extra_instr_args=["--c-opts=-DB"], + trace_mode="src", + gpr_exe_dir="..", + extra_coverage_args=[], + )[-1] ) +tmp_b.to_homedir() -# Now, try to generate a coverage report from both traces. -xcov(cov_args + ["a.srctrace", "b.srctrace"], out="cov.out") +# Now, try to generate a coverage report from both traces +os.mkdir("xcov") +xcov( + ["coverage"] + + gprsw.cov_switches + + ["-axcov", "--output-dir=xcov", "--level=stmt", trace_a, trace_b], + out="cov.out", +) # Check that gnatcov warns about inconsistency between a.srctrace and the # source instrumentation data. From e386d3546c7609d2a831e1f2ec50c3568681e26e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 19 Aug 2024 15:59:14 +0200 Subject: [PATCH 0895/1483] Document disabling coverage analysis mechanism --- doc/gnatcov/disable_cov.rst | 130 +++++++++++++++++++++++++++++++++++ doc/gnatcov/gnatcov_part.rst | 1 + 2 files changed, 131 insertions(+) create mode 100644 doc/gnatcov/disable_cov.rst diff --git a/doc/gnatcov/disable_cov.rst b/doc/gnatcov/disable_cov.rst new file mode 100644 index 000000000..b71bd3000 --- /dev/null +++ b/doc/gnatcov/disable_cov.rst @@ -0,0 +1,130 @@ +.. _disable_cov: + +************************* +Disable coverage analysis +************************* + +It is possible to fully disable coverage analysis over a specific region. In +contrast to exemption regions, gnatcov skips over disabled coverage region and +treats them similarily as a no code region, e.g. with no source coverage +obligations. + +Such a mechanism can typically be used to disable coverage for a code region +that may or may not expand according to the build configuration at use. + +This mechanism only works when using source traces. + +Defining :term:`Disabled Coverage Regions ` +===================================================================== + +:dfn:`Disabled Coverage Regions` are lexical sections of sources in which +coverage analysis is fully disabled. + +For Ada with the |gnat| compilers, regions are defined by the insertion of +dedicated pragmas in the sources: + +- ``pragma Annotate (Xcov, Cov_Off, "justification text");`` starts a region, + providing some justification text that will be recalled in coverage reports. + +- ``pragma Annotate (Xcov, Cov_On);`` closes the current disabled coverage + region. + +There may be no overlap between disabled coverage regions. + +To illustrate, let us consider a common assertion control procedure in Ada: + +.. code-block:: ada + + procedure Eassert (T : Boolean) is + begin + pragma Annotate (Xcov, Cov_Off, "my justification"); + if not T then + raise Program_Error; + end if; + pragma Annotate (Xcov, Cov_On); + end Eassert; + +For C code, disabled coverage regions are defined using comment markers to +delimit the region + +- Any comment containing the string ``GNATCOV_COV_OFF`` followed by a string in + double quotes starts a region, the string within the double quotes being used + as justification text that will be recalled in coverage reports. + +- Any comment containing the string ``GNATCOV_COV_ON`` closes the current + region. + +The following assert function illustrates the definition of a disabled coverage +region: + +.. code-block:: C + + void + assert (bool x){ + // GNATCOV_COV_OFF "my justification" + if (!x) + abort(); + // GNATCOV_COV_ON + } + +Consolidating traces with varying disabled coverage regions +=========================================================== + +As stated, there can be a varying set of disabled coverage regions according +to the build configuration and when considering C/C++ preprocessing. If you +lie in that case, read thoroughly the information below. + +It is not allowed to consolidate traces originating from instrumentations with +mismatching disabled coverage regions. If doing so, gnatcov will warn with +``traces for (from ) are inconsistent with the corresponding Source Instrumentation Data``. + +To circumvent this, it is mandatory to produce checkpoints using the +instrumentation artifacts the source trace originates from. GNATcov then allows +consolidation of checkpoints with mismatching disabled coverage regions. See +:ref:`consolidation` for more information. + + +Reporting about disabled coverage regions +========================================= + +Exempted regions are reported as blocks in both the annotated source and the +synthetic text reports, for both source and object coverage metrics. In +annotated source reports, a ``D`` annotates all the lines of a disabled coverage +region. + +For our ``Eassert`` above, a typical :cmd-option:`=xcov` output for +:cmd-option:`stmt+decision` coverage for would be:: + + 6 .: procedure Eassert (T : Boolean) is + 7 .: begin + 8 D: pragma Annotate (Xcov, Cov_Off, "my justification"); + 9 D: if not T then + 10 D: raise Program_Error; + 11 D: end if; + 12 D: pragma Annotate (Xcov, Cov_On); + 13 .: end Eassert; + + +In synthetic text reports, a single indication is emitted for each disabled +coverage region as a whole, and the indications for all the regions are grouped +in a separate *Disabled Coverage Regions* report section, only present if there +are disabled coverage regions in the analysis scope. + +The corresponding :cmd-option:`=report` excerpt below illustrates this for the +``Eassert`` example:: + + ... + ================================== + == 3. DISABLED COVERAGE REGIONS == + ================================== + + eassert.adb:8:4-12:4: justification: + "my justification" + + 1 region with disabled coverage. + + ========================= + == 4. ANALYSIS SUMMARY == + ========================= + + 1 region with disabled coverage. diff --git a/doc/gnatcov/gnatcov_part.rst b/doc/gnatcov/gnatcov_part.rst index 9b483486f..8c03e8529 100644 --- a/doc/gnatcov/gnatcov_part.rst +++ b/doc/gnatcov/gnatcov_part.rst @@ -12,6 +12,7 @@ GNATcoverage User's Guide cov_source consolidation exemptions + disable_cov gpr gps glossary From 7cf4d4305e38c3c7cea4d185ddd81d9b03e1a362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 27 Aug 2024 17:16:50 +0200 Subject: [PATCH 0896/1483] doinstall.tmplt: Update support email address --- tools/gnatcov/doinstall.tmplt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/doinstall.tmplt b/tools/gnatcov/doinstall.tmplt index eceefddb3..ed15ffb8d 100755 --- a/tools/gnatcov/doinstall.tmplt +++ b/tools/gnatcov/doinstall.tmplt @@ -115,7 +115,7 @@ EOF if $error_exit; then cat << EOF - Don't hesitate to send a message to report@adacore.com + Don't hesitate to send a message to support@adacore.com with you customer number on the subject line if you have any question about this installation process. From 408cd15a7e7f62d174c353e10bd02d204d750276 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 17 Jun 2024 15:14:21 +0200 Subject: [PATCH 0897/1483] Refactor message printing in annotations-report.adb... ... to avoid printing SCO-related information on a message not attached on any SCO. --- testsuite/tests/300-no-sco-msg/main.adb | 20 +++++++++ testsuite/tests/300-no-sco-msg/test.opt | 2 + testsuite/tests/300-no-sco-msg/test.py | 47 ++++++++++++++++++++ tools/gnatcov/annotations-report.adb | 59 +++++++++++++++---------- 4 files changed, 104 insertions(+), 24 deletions(-) create mode 100644 testsuite/tests/300-no-sco-msg/main.adb create mode 100644 testsuite/tests/300-no-sco-msg/test.opt create mode 100644 testsuite/tests/300-no-sco-msg/test.py diff --git a/testsuite/tests/300-no-sco-msg/main.adb b/testsuite/tests/300-no-sco-msg/main.adb new file mode 100644 index 000000000..dcdaff132 --- /dev/null +++ b/testsuite/tests/300-no-sco-msg/main.adb @@ -0,0 +1,20 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + type String_Acc is access all String; + Str : aliased String := "Hello World!"; + Str_Acc : constant String_Acc := Str'Access; + Cond : Boolean := True; + pragma Volatile(Cond); + Ptr : String_Acc := (if Cond then Str_Acc else Str_Acc); +begin + Put_Line ("Yay!"); + if Cond then + Ptr := Str_Acc; + else + Ptr := Str_Acc; + end if; + Put_Line (Ptr.all); +end Main; diff --git a/testsuite/tests/300-no-sco-msg/test.opt b/testsuite/tests/300-no-sco-msg/test.opt new file mode 100644 index 000000000..46ef7588f --- /dev/null +++ b/testsuite/tests/300-no-sco-msg/test.opt @@ -0,0 +1,2 @@ +!bin-traces DEAD requires bin traces to produce the proper message +5.04a1 DEAD Test requires Ada 2012 diff --git a/testsuite/tests/300-no-sco-msg/test.py b/testsuite/tests/300-no-sco-msg/test.py new file mode 100644 index 000000000..3f833132c --- /dev/null +++ b/testsuite/tests/300-no-sco-msg/test.py @@ -0,0 +1,47 @@ +""" +Test that gnatcov does not crash when messages are not attached to any SCO. +It used to crash when generating a --annotate=report coverage report in +presence of such messages. +""" + +from SCOV.minicheck import build_run_and_coverage +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +root = gprfor( + srcdirs="..", + mains=["main.adb"], + objdir="obj", +) + +rep = "test.rep" + +build_run_and_coverage( + gprsw=GPRswitches(root), + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=[ + "--annotate=report", + "--log=BRANCH_STATS", + "--all-messages", + ], + out=rep, +) + +# Check the contents of the report to ensure the expected message is indeed +# emitted (otherwise the test is pointless). +thistest.fail_if_no_match( + "missing warning message", + regexp=r"(.|\n)*2.3. OTHER ERRORS" + r"(.|\n)+-----------------" + r"(.|\n)+main\.adb:19:4: non-traceable: cond branch for" + r" OTHER_STATEMENT" + r"(.|\n)*", + actual=contents_of(rep), +) + +thistest.result() diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 76c8ffbaa..3654ac26b 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -606,39 +606,46 @@ package body Annotations.Report is M : Message renames Message_Vectors.Element (C); Msg : constant String := +M.Msg; First : Natural := Msg'First; - Show_Vectors : constant Boolean := - (Switches.Show_MCDC_Vectors - and then not Is_Assertion_To_Cover (M.SCO)) - or else Switches.Show_Condition_Vectors; begin - -- For info messages (such as the messages displayed with - -- --show-mcdc-vectors and --show-condition vectors), do not - -- display the SCO, as it is only used to attach the message to - -- the right report location. - if M.Kind /= Info and then M.SCO /= No_SCO_Id then - Put - (Output.all, Image (First_Sloc (M.SCO), Unique_Name => True)); - Put (Output.all, ": "); - if Msg (First) = '^' then - First := First + 1; - else + declare + Show_Vectors : constant Boolean := + (Switches.Show_MCDC_Vectors + and then not Is_Assertion_To_Cover (M.SCO)) + or else Switches.Show_Condition_Vectors; + begin Put (Output.all, - SCO_Kind_Image (M.SCO) - & (if Show_Vectors and then Kind (M.SCO) = Condition - then Index (M.SCO)'Image - & " (" & SCO_Image (M.SCO) & ") " - else " ")); - end if; + Image (First_Sloc (M.SCO), Unique_Name => True)); + Put (Output.all, ": "); + if Msg (First) = '^' then + First := First + 1; + else + Put + (Output.all, + SCO_Kind_Image (M.SCO) + & (if Show_Vectors and then Kind (M.SCO) = Condition + then Index (M.SCO)'Image + & " (" & SCO_Image (M.SCO) & ") " + else " ")); + end if; + end; + + elsif M.SCO /= No_SCO_Id then + + -- For info messages (such as the messages displayed with + -- --show-mcdc-vectors and --show-condition vectors), do not + -- display the SCO, as it is only used to attach the message to + -- the right report location. - else Put (Output.all, Image ((if SC_Obligations.Kind (M.SCO) = Condition then First_Sloc (Enclosing_Decision (M.SCO)) else First_Sloc (M.SCO)), Unique_Name => True)); Put (Output.all, ": "); + else + Put (Output.all, Image (M.Sloc) & ": "); end if; Output_Multiline_Msg @@ -651,7 +658,9 @@ package body Annotations.Report is end if; New_Line (Output.all); - Output_Annotations (Output.all, SCO_Annotations (M.SCO)); + if M.SCO /= No_SCO_Id then + Output_Annotations (Output.all, SCO_Annotations (M.SCO)); + end if; end Output_Message; -- Start of processing for Messages_For_Section @@ -975,7 +984,9 @@ package body Annotations.Report is is Info : constant File_Info_Access := Get_File (File); begin - if Info.Li_Stats (Covered) /= Get_Total (Info.Li_Stats) then + if Info.Li_Stats (Covered) /= Get_Total (Info.Li_Stats) + or else (Pp.Show_Details and then Info.Li_Stats (Not_Coverable) /= 0) + then -- Some uncovered or partially covered lines are present From 96509b752deea9c27b3b7fbb53b7cf24be6c94fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 14 Jun 2024 14:00:49 +0200 Subject: [PATCH 0898/1483] Consider decisions with no object level control flow impact as non-coverable These are decisions with no branches in the executable and which do not dominate any statement (such as if-expressions). As their evaluation has no impact on the execution of the program, and their valuation cannot be traced back from other statements, consider that there is nothing to be covered. Also modify the testsuite to recognise non-coverable decisions. --- testsuite/SCOV/internals/cnotes.py | 5 +- testsuite/SCOV/internals/rnexpanders.py | 2 + testsuite/SCOV/internals/xnotep.py | 2 + .../tests/300-non-cov-decision/src/pkg.adb | 18 +++++++ .../tests/300-non-cov-decision/src/pkg.ads | 5 ++ .../300-non-cov-decision/src/test_pkg.adb | 16 ++++++ testsuite/tests/300-non-cov-decision/test.opt | 1 + testsuite/tests/300-non-cov-decision/test.py | 19 +++++++ tools/gnatcov/coverage-source.adb | 20 +++++++ tools/gnatcov/sc_obligations.adb | 53 +++++++++++++++++++ tools/gnatcov/sc_obligations.ads | 9 ++++ tools/gnatcov/traces_lines.adb | 19 +++---- 12 files changed, 155 insertions(+), 14 deletions(-) create mode 100644 testsuite/tests/300-non-cov-decision/src/pkg.adb create mode 100644 testsuite/tests/300-non-cov-decision/src/pkg.ads create mode 100644 testsuite/tests/300-non-cov-decision/src/test_pkg.adb create mode 100644 testsuite/tests/300-non-cov-decision/test.opt create mode 100644 testsuite/tests/300-non-cov-decision/test.py diff --git a/testsuite/SCOV/internals/cnotes.py b/testsuite/SCOV/internals/cnotes.py index dcbf66af2..be445cfde 100644 --- a/testsuite/SCOV/internals/cnotes.py +++ b/testsuite/SCOV/internals/cnotes.py @@ -183,6 +183,7 @@ sUndetCov, dtAlways, dfAlways, + dNotCoverable, dtNoCov, dfNoCov, dNoCov, @@ -217,7 +218,7 @@ xBlock1, xBlock2, dBlock, -) = range(55) +) = range(56) NK_image = { None: "None", @@ -240,6 +241,7 @@ sUndetCov: "sUndetCov", dtAlways: "dtAlways", dfAlways: "dfAlways", + dNotCoverable: "dNotCoverable", dtNoCov: "dtNoCov", dfNoCov: "dfNoCov", dNoCov: "dNoCov", @@ -314,6 +316,7 @@ dNoCov, dtAlways, dfAlways, + dNotCoverable, dUndetCov, ) diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index 2c69d91ee..afa42f177 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -16,6 +16,7 @@ sNotCoverable, dfAlways, dtAlways, + dNotCoverable, dfNoCov, dtNoCov, dNoCov, @@ -682,6 +683,7 @@ def __init__(self): "statement has no object code": sNotCoverable, "decision is always TRUE": dtAlways, "decision is always FALSE": dfAlways, + "decision has no object code": dNotCoverable, } self.noteblocks.append( NCIchapter(re_start="NON COVERABLE ITEMS", re_notes=nc_notes) diff --git a/testsuite/SCOV/internals/xnotep.py b/testsuite/SCOV/internals/xnotep.py index a439161bc..8b8cf3ec7 100644 --- a/testsuite/SCOV/internals/xnotep.py +++ b/testsuite/SCOV/internals/xnotep.py @@ -17,6 +17,7 @@ transparent_p, cPartCov, dNoCov, + dNotCoverable, dPartCov, dfAlways, dfNoCov, @@ -243,6 +244,7 @@ class XnoteP: "s?": sUndetCov, "dT*": dtAlways, "dF*": dfAlways, + "d0": dNotCoverable, "dT-": dtNoCov, "dF-": dfNoCov, "d!": dPartCov, diff --git a/testsuite/tests/300-non-cov-decision/src/pkg.adb b/testsuite/tests/300-non-cov-decision/src/pkg.adb new file mode 100644 index 000000000..9a8ebc9b9 --- /dev/null +++ b/testsuite/tests/300-non-cov-decision/src/pkg.adb @@ -0,0 +1,18 @@ +pragma Ada_2012; + +with Ada.Text_IO; + +package body Pkg is + + procedure Foo (X : Boolean) is + type String_Acc is access all String; + Str : aliased String := "Hello World!"; -- # st + Str_Acc : constant String_Acc := Str'Access; -- # st + Cond : Boolean := True; -- # st + pragma Volatile(Cond); + Ptr : String_Acc := (if Cond then Str_Acc else Str_Acc); -- # dc + begin + Ada.Text_IO.Put_Line (Ptr.all); -- # st + end Foo; + +end Pkg; diff --git a/testsuite/tests/300-non-cov-decision/src/pkg.ads b/testsuite/tests/300-non-cov-decision/src/pkg.ads new file mode 100644 index 000000000..8965cb39b --- /dev/null +++ b/testsuite/tests/300-non-cov-decision/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + procedure Foo (X : Boolean); + +end Pkg; diff --git a/testsuite/tests/300-non-cov-decision/src/test_pkg.adb b/testsuite/tests/300-non-cov-decision/src/test_pkg.adb new file mode 100644 index 000000000..d20ff9aa4 --- /dev/null +++ b/testsuite/tests/300-non-cov-decision/src/test_pkg.adb @@ -0,0 +1,16 @@ +with Pkg; + +procedure Test_Pkg is +begin + Pkg.Foo(True); +end Test_Pkg; + +--# pkg.adb +-- /st/ l+ ## 0 +-- /dc/ l+ ## 0 + +-- %opts: --trace-mode=src +-- =/dc/ l! ## dF- + +-- %cov: --non-coverable +-- =/dc/ l0 ## d0 diff --git a/testsuite/tests/300-non-cov-decision/test.opt b/testsuite/tests/300-non-cov-decision/test.opt new file mode 100644 index 000000000..17a9a09d6 --- /dev/null +++ b/testsuite/tests/300-non-cov-decision/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Test requires Ada 2012 support diff --git a/testsuite/tests/300-non-cov-decision/test.py b/testsuite/tests/300-non-cov-decision/test.py new file mode 100644 index 000000000..8ac0d3ed9 --- /dev/null +++ b/testsuite/tests/300-non-cov-decision/test.py @@ -0,0 +1,19 @@ +""" +Test that gnatcov reports decisions for which no conditional branches have been +generated, and which does not dominate any statement as not-coverable instead +of a violation. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + + +TestCase(category=CAT.decision).run() + +if thistest.options.trace_mode == "bin": + TestCase(category=CAT.decision).run( + covcontrol=CovControl(covoptions="--non-coverable"), subdirhint="nc_" + ) + +thistest.result() diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 1a289d367..eb27f47ea 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -1061,6 +1061,26 @@ package body Coverage.Source is SCI.Tag, "was not instrumented for decision coverage", Kind => Undetermined_Cov); + + -- If the decision has not conditional branches at + -- all, mark it as uncoverable and report it. We + -- should already have leveraged back-propagation, + -- at this point, so a decision with no outcomes + -- taken is either never evaluated, or has no + -- branches to track the evaluation. + + elsif not Decision_Has_Influence (SCO) then + if Report_If_Excluded (SCO) then + SCO_State := Not_Coverable; + Report_Exclusion + (SCO, SCI.Tag, Msg => "has no object code"); + else + -- Mark the SCO as no code if not reporting + -- it, to avoid having a violation in the + -- reports. + + SCO_State := No_Code; + end if; else Report_Violation (SCO, SCI.Tag, "never evaluated"); diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 48edc2d7a..1ca2a8c02 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -44,6 +44,7 @@ with Outputs; use Outputs; with SC_Obligations.BDD; with Switches; use Switches; with Traces_Elf; use Traces_Elf; +with Traces_Files; package body SC_Obligations is @@ -2995,6 +2996,58 @@ package body SC_Obligations is return SCOD.Index; end Index; + ---------------------------- + -- Decision_Has_Influence -- + ---------------------------- + + function Decision_Has_Influence (SCO : SCO_Id) return Boolean is + use BDD; + SCOD : SCO_Descriptor renames SCO_Vector.Constant_Reference (SCO); + First : constant BDD_Node_Id := SCOD.Decision_BDD.First_Node; + Last : constant BDD_Node_Id := SCOD.Decision_BDD.Last_Node; + + begin + if Traces_Files.Currently_Accepted_Trace_Kind in + Traces_Files.Source_Trace_File .. Traces_Files.All_Trace_Files + then + return True; + end if; + + -- Iterate over all BDD nodes to more efficiently iterate over the + -- condition SCOs, and record whether we have found a branch for it. + + for J in First .. Last loop + declare + BDDN : BDD_Node renames BDD_Vector.Constant_Reference (J); + begin + if BDDN.Kind = Condition and then + not SCO_Vector.Constant_Reference (BDDN.C_SCO).PC_Set.Is_Empty + then + return True; + end if; + end; + end loop; + + -- Here if the decision has no conditional branches associated, check + -- whether it dominates some statement. + + for S_SCO_Cur in SCO_Vector.Iterate loop + declare + S_SCOD : SCO_Descriptor renames + SCO_Vector.Constant_Reference (S_SCO_Cur); + begin + if S_SCOD.Kind = Statement and then S_SCOD.Dominant = SCO then + return True; + end if; + end; + end loop; + + -- If not, this decision has no impact over the control flow of the + -- program. + + return False; + end Decision_Has_Influence; + ----------------- -- Register_CU -- ----------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 5ef91334a..3868829a3 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -638,6 +638,15 @@ package SC_Obligations is -- For a statement within an exception handler, return the sloc range of -- the (innermost) handler. + function Decision_Has_Influence (SCO : SCO_Id) return Boolean with + Pre => Kind (SCO) = Decision; + -- Wether the decision designated by SCO has at least one known branch in + -- the executable, or dominates at least one statement. If not, the + -- decision has no impact on the control flow of the program. + -- + -- This always returns True is the accepted trace kind includes source + -- traces. + -- Condition SCOs function Index (SCO : SCO_Id) return Condition_Index; diff --git a/tools/gnatcov/traces_lines.adb b/tools/gnatcov/traces_lines.adb index e57c866ff..5b600e66f 100644 --- a/tools/gnatcov/traces_lines.adb +++ b/tools/gnatcov/traces_lines.adb @@ -28,18 +28,11 @@ package body Traces_Lines is when No_Code => return R; - when Not_Coverable => - if R = No_Code then - return L; - else - return R; - end if; - - -- We don't want non instrumented code to mask any confirmed - -- violations, but we still want them to show up if gnatcov does not - -- detect any violation. + -- We don't want non instrumented code / Not_Coverable code to mask + -- any confirmed violations, but we still want them to show up if + -- gnatcov does not detect any violation. - when Undetermined_Coverage => + when Not_Coverable | Undetermined_Coverage => if R in No_Code | Covered then return L; else @@ -48,10 +41,10 @@ package body Traces_Lines is when others => case R is - when No_Code | Not_Coverable => + when No_Code => return L; - when Undetermined_Coverage => + when Undetermined_Coverage | Not_Coverable => if L = Covered then return R; else From dfe3a4110e1b1857af7c0793bd0db11bf8da0b09 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 28 Aug 2024 14:19:50 +0200 Subject: [PATCH 0899/1483] CI: update scripts after the removal of stable-* specs --- .gitlab-ci.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 23a3e201b..d54b9f397 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -158,10 +158,10 @@ test_5.04a1_src_traces: script: - *basic_test_setup - # GNAT 5.04a1 does not ship "ar" nor "ld". Make the ones from stable-gnat + # GNAT 5.04a1 does not ship "ar" nor "ld". Make the ones from gnat/stable # available as if they were installed system-wide. - - anod install stable-gnat - - STABLE_GNAT_BSN=$(anod eval --primitive=install stable-gnat build_space_name) + - anod install gnat -Qstable + - STABLE_GNAT_BSN=$(anod eval --primitive=install gnat -Qstable build_space_name) - STABLE_GNAT_PREFIX="$ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$STABLE_GNAT_BSN/install" - mkdir build-essentials - export PATH="$PWD/build-essentials:$PATH" @@ -217,8 +217,8 @@ stylechecks: url."${GITLAB_REMOTE}".insteadOf "ssh://git@ssh.gitlab.adacore-it.com/" # Install the clang-format executable and make it available - - anod install stable-libclang - - eval `anod printenv stable-libclang` + - anod install libclang -Qstable + - eval `anod printenv libclang -Qstable` # Create a virtual env to install our deps - python -mvenv /tmp/venv From cde98bf5a2d6bde1b17c5ec609a37cedaa9ba4de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 29 Aug 2024 15:09:24 +0200 Subject: [PATCH 0900/1483] Various testsuite fixes related to non-coverage decision SCOs This disables some tests in configurations where the required conditions are not met for the test to succeed: - 300-non-cov-decision: disable for 7.1.2 as the compiler optimizes Ada 2012 expressions too aggressively. - 300-no-sco-msg: Disable in binary traces when optimization or compilation options suppress the emission of non-traceable branches, which are required for gnatcov to emit the required message. - TB13-020-expr-func: Rework the test to prevent the compiler from optimizing out the initialization of a constant not referenced anywhere. --- testsuite/tests/300-no-sco-msg/test.opt | 2 ++ testsuite/tests/300-non-cov-decision/test.opt | 1 + testsuite/tests/TB13-020-expr-func-mcdc/main.adb | 3 ++- testsuite/tests/TB13-020-expr-func-mcdc/test.py | 2 +- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/300-no-sco-msg/test.opt b/testsuite/tests/300-no-sco-msg/test.opt index 46ef7588f..3bab65018 100644 --- a/testsuite/tests/300-no-sco-msg/test.opt +++ b/testsuite/tests/300-no-sco-msg/test.opt @@ -1,2 +1,4 @@ !bin-traces DEAD requires bin traces to produce the proper message +CARGS_O1 DEAD optimization deletes branch leading to required message +CARGS_gnatp DEAD runtime checks required to produce branch leading to message 5.04a1 DEAD Test requires Ada 2012 diff --git a/testsuite/tests/300-non-cov-decision/test.opt b/testsuite/tests/300-non-cov-decision/test.opt index 17a9a09d6..371d64be9 100644 --- a/testsuite/tests/300-non-cov-decision/test.opt +++ b/testsuite/tests/300-non-cov-decision/test.opt @@ -1 +1,2 @@ 5.04a1 DEAD Test requires Ada 2012 support +7.1.2 DEAD optimization on this compiler is too aggressive on Ada 2012 diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/main.adb b/testsuite/tests/TB13-020-expr-func-mcdc/main.adb index ac487bc3a..597273750 100644 --- a/testsuite/tests/TB13-020-expr-func-mcdc/main.adb +++ b/testsuite/tests/TB13-020-expr-func-mcdc/main.adb @@ -3,7 +3,8 @@ pragma Ada_2012; with Pkg; procedure Main is - Dummy : constant Integer := (if Pkg.Flag then 1 else 2); + Dummy : Integer := (if Pkg.Flag then 1 else 2); + pragma Volatile (Dummy); function Is_Null (Self : Pkg.Point) return Boolean is (Pkg.Is_Null (Self.X) and then Pkg.Is_Null (Self.Y)); diff --git a/testsuite/tests/TB13-020-expr-func-mcdc/test.py b/testsuite/tests/TB13-020-expr-func-mcdc/test.py index 4dfc7b5ba..bcba8e97a 100644 --- a/testsuite/tests/TB13-020-expr-func-mcdc/test.py +++ b/testsuite/tests/TB13-020-expr-func-mcdc/test.py @@ -26,7 +26,7 @@ check_xcov_reports( "report", { - "main.adb.xcov": {"!": {6, 9, 15, 19}, "+": {11, 12}, "-": {16, 20}}, + "main.adb.xcov": {"!": {6, 10, 16, 20}, "+": {12, 13}, "-": {17, 21}}, "pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {9}}, }, From 7d8d70767028154e9469e6e91efa236d6acb3106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Fri, 17 May 2024 15:21:43 +0200 Subject: [PATCH 0901/1483] Implement function and call coverage This new coverage level can be activated through the use of "fun_call" in the "--annotate" switch. It measures the coverage of functions and calls like so: * A function is covered if it was entered at least once * A call is covered if it was executed at least once --- tools/gnatcov/annotations-sarif.adb | 10 +- tools/gnatcov/annotations.adb | 28 +- tools/gnatcov/checkpoints.adb | 7 +- tools/gnatcov/coverage-source.adb | 78 +- tools/gnatcov/coverage.adb | 3 + tools/gnatcov/coverage.ads | 3 +- tools/gnatcov/coverage_options.adb | 29 +- tools/gnatcov/coverage_options.ads | 14 +- tools/gnatcov/files_table.ads | 19 +- tools/gnatcov/instrument-ada_unit.adb | 1026 +++++++++++++++++++++---- tools/gnatcov/instrument-common.adb | 6 +- tools/gnatcov/instrument-projects.adb | 1 + tools/gnatcov/sc_obligations.adb | 157 +++- tools/gnatcov/sc_obligations.ads | 22 +- 14 files changed, 1202 insertions(+), 201 deletions(-) diff --git a/tools/gnatcov/annotations-sarif.adb b/tools/gnatcov/annotations-sarif.adb index 3126c7dde..15b67af9e 100644 --- a/tools/gnatcov/annotations-sarif.adb +++ b/tools/gnatcov/annotations-sarif.adb @@ -171,7 +171,7 @@ package body Annotations.Sarif is & " condition changes and the decision value toggles."), Help_Uri => +(Doc_Link & "gnatcov/cov_source.html#mcdc-variants"), Config => +"error"), - Source_Coverage_Level'Pos (ATC) => + Source_Coverage_Level'Pos (ATC) => (Id => +ATC'Image, Name => +"Assertion True Coverage", Short_Descr => @@ -189,6 +189,14 @@ package body Annotations.Sarif is & "gnatcov/cov_source.html#assertion-true-condition-coverage-" & "analysis-atcc"), Config => +"error"), + Source_Coverage_Level'Pos (Fun_Call) => + (Id => +Fun_Call'Image, + Name => +"Function and Call coverage", + Short_Descr => + (+"The subprogram was entered at least once or the call" + & " was executed at least once"), + Help_Uri => +"FIXME", + Config => +"error"), Undet_Rule => (Id => +"UNDET", Name => +"Undetermined Coverage", diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 8c5ead1cc..bc8722e6c 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -347,6 +347,12 @@ package body Annotations is when Operator => null; + when Fun_Call_SCO_Kind => + if Coverage.Enabled (Fun_Call) then + SCO_State := Get_Line_State (SCO, Fun_Call); + Pretty_Print_Statement (Pp, SCO, SCO_State); + end if; + end case; end if; end loop; @@ -1031,12 +1037,21 @@ package body Annotations is function SCO_Kind_Image (SCO : SCO_Id) return String is K : constant SCO_Kind := Kind (SCO); + + Image : Unbounded_String := +""; begin - return (if Kind (SCO) in Decision - and then Decision_Type (SCO) in Pragma_Decision | Aspect - and then Coverage.Assertion_Coverage_Enabled - then "contract expression" - else To_Lower (SCO_Kind'Image (K))); + if Kind (SCO) in Decision + and then Decision_Type (SCO) in Pragma_Decision | Aspect + and then Coverage.Assertion_Coverage_Enabled + then + Image := +"contract expression"; + elsif Kind (SCO) = Fun then + Image := +"function"; + else + Image := +To_Lower (SCO_Kind'Image (K)); + end if; + + return +Image; end SCO_Kind_Image; ------------------------ @@ -1114,6 +1129,9 @@ package body Annotations is return MCDC_Section; end if; + when Fun_Call_SCO_Kind => + return Coverage_Level'Pos (Fun_Call); + when others => return Other_Errors; end case; diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index f49254df9..1a175217a 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -503,7 +503,7 @@ package body Checkpoints is Supported_Levels (MCDC_Coverage_Level'Range) := (others => True); Supported_Levels (Decision) := True; end if; - for Level in Insn .. ATCC loop + for Level in Insn .. Fun_Call loop CSS.Write (Supported_Levels (Level)); end loop; @@ -641,7 +641,7 @@ package body Checkpoints is -- reading code. declare - CP_Levels : U8_Array (1 .. 8); + CP_Levels : U8_Array (1 .. 9); Levels : Levels_Type; begin CLS.Read (CP_Levels); @@ -653,7 +653,8 @@ package body Checkpoints is MCDC => Boolean'Val (CP_Levels (5)), UC_MCDC => Boolean'Val (CP_Levels (6)), ATC => Boolean'Val (CP_Levels (7)), - ATCC => Boolean'Val (CP_Levels (8))); + ATCC => Boolean'Val (CP_Levels (8)), + Fun_Call => Boolean'Val (CP_Levels (9))); declare Error_Msg : constant String := Coverage.Is_Load_Allowed (Filename, Levels); diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index eb27f47ea..4ccc775b9 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -89,7 +89,7 @@ package body Coverage.Source is type Line_States is array (Coverage_Level) of Line_State; - type Source_Coverage_Info (Kind : SCO_Kind := Statement) is record + 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. @@ -127,6 +127,10 @@ package body Coverage.Source is -- 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 id this call or function was executed at least once + when others => null; end case; @@ -1122,6 +1126,59 @@ package body Coverage.Source is (SCO, SCO_State, Line_Info, SCI, MCDC_Level); end if; end if; + + -- For fun_call coverage, only compute the SCO state on the + -- first line, and re-use the SCI cache to set the line state + -- on subprograms or calls spanning multiple lines. + + elsif Kind (SCO) in Fun_Call_SCO_Kind + and then Enabled (Fun_Call) + and then First_Sloc (SCO).L.Line = Line_Num + then + if not Fun_Call_SCO_Instrumented (SCO) then + SCO_State := Undetermined_Coverage; + Report_Coverage + (SCO, + SCI.Tag, + "was not instrumented", + Kind => Undetermined_Cov); + + -- For call statements, we only need to rely on the state + -- of the enclosing statement. + + elsif Is_Call_Stmt (SCO) then + declare + S_SCO : constant SCO_Id := Enclosing_Statement (SCO); + S_SCI : constant Source_Coverage_Info_Access := + (if S_SCO = No_SCO_Id + then null + else Get_SCI (S_SCO, SCI.Tag)); + begin + SCO_State := + (if S_SCI /= null and then S_SCI.Executed + then Covered + else Not_Covered); + end; + else + SCO_State := + (if SCI.Fun_Call_Executed + then Covered + else Not_Covered); + end if; + + if SCO_State = Not_Covered then + Report_Violation (SCO, SCI.Tag, "not executed"); + end if; + + Update_Line_State + (Line_Info, SCO, SCI.Tag, Fun_Call, SCO_State); + + elsif Kind (SCO) in Fun_Call_SCO_Kind + and then Enabled (Fun_Call) + then + SCO_State := SCI.State (Fun_Call); + Update_Line_State + (Line_Info, SCO, SCI.Tag, Fun_Call, SCO_State); end if; end loop; end SCOs_Of_Line; @@ -2081,7 +2138,12 @@ package body Coverage.Source is procedure Set_Executed (SCI : in out Source_Coverage_Info) is begin - SCI.Executed := True; + if SCI.Kind = Statement then + SCI.Executed := True; + elsif SCI.Kind in Fun_Call_SCO_Kind then + SCI.Fun_Call_Executed := True; + end if; + end Set_Executed; ---------------- @@ -2488,7 +2550,9 @@ package body Coverage.Source is procedure Process_SCI (SCI : in out Source_Coverage_Info) is begin - SCI.Basic_Block_Has_Code := True; + if SCI.Kind = Statement then + SCI.Basic_Block_Has_Code := True; + end if; end Process_SCI; Stmt_Bit_Map : Statement_Bit_Map renames @@ -2625,7 +2689,7 @@ package body Coverage.Source is CP_SCI.Tag := SC_Tag (CLS.Read_I32); declare - States : array (1 .. 8) of Line_State; + States : array (1 .. 9) of Line_State; begin for I in States'Range loop States (I) := CLS.Read_Line_State; @@ -2638,6 +2702,7 @@ package body Coverage.Source is CP_SCI.State (UC_MCDC) := States (6); CP_SCI.State (ATC) := States (7); CP_SCI.State (ATCC) := States (8); + CP_SCI.State (Fun_Call) := States (9); end; case CP_SCI.Kind is @@ -2654,6 +2719,8 @@ package body Coverage.Source is CP_SCI.Known_Outcome_Taken (True) := CLS.Read_Boolean; Read (CLS, CP_SCI.Evaluations); + when Fun_Call_SCO_Kind => + CP_SCI.Fun_Call_Executed := CLS.Read_Boolean; when others => null; @@ -2695,6 +2762,9 @@ package body Coverage.Source is Write (CSS, Value.Evaluations); + when Fun_Call_SCO_Kind => + CSS.Write (Value.Fun_Call_Executed); + when others => null; end case; diff --git a/tools/gnatcov/coverage.adb b/tools/gnatcov/coverage.adb index 1258968f9..c3240719e 100644 --- a/tools/gnatcov/coverage.adb +++ b/tools/gnatcov/coverage.adb @@ -223,6 +223,9 @@ package body Coverage is Res.Include (ATCC); end if; end if; + if Enabled (Fun_Call) then + Res.Include (Fun_Call); + end if; end if; return Res; end Source_Levels_Enabled; diff --git a/tools/gnatcov/coverage.ads b/tools/gnatcov/coverage.ads index ab9338c1a..4a179279a 100644 --- a/tools/gnatcov/coverage.ads +++ b/tools/gnatcov/coverage.ads @@ -42,7 +42,8 @@ package Coverage is when MCDC => "MCDC", when UC_MCDC => "UC_MCDC", when ATC => "ATC", - when ATCC => "ATCC"); + when ATCC => "ATCC", + when Fun_Call => "Function and call"); -- Case sensitive version of Coverage_Level'Image procedure Set_Coverage_Levels (Opt : String); diff --git a/tools/gnatcov/coverage_options.adb b/tools/gnatcov/coverage_options.adb index 3cd660d8d..d72fd8f2d 100644 --- a/tools/gnatcov/coverage_options.adb +++ b/tools/gnatcov/coverage_options.adb @@ -130,7 +130,8 @@ package body Coverage_Options is & "+" & Level_Str (MCDC) & "|" & "+" & Level_Str (UC_MCDC) & ")?" & "(+" & Level_Str (ATC) & "|" - & "+" & Level_Str (ATCC) & ")?"; + & "+" & Level_Str (ATCC) & ")?" + & "(+" & Level_Str (Fun_Call) & ")?"; end Source_Level_Options; ------------------------------------- @@ -139,9 +140,25 @@ package body Coverage_Options is procedure Add_Source_Coverage_Level_Combinaisons is procedure Add_Assert_Coverage_Levels (Combinaison : Levels_Type); - -- Register the coverage level Combinaison combined plus each level + -- Register the coverage level Combinaison combined with each level -- of assertion coverage. + procedure Add_Fun_Call_Coverage_Level (Combinaison : Levels_Type); + -- Register the coverage level Combinaison combined with function and + -- call coverage. + + --------------------------------- + -- Add_Fun_Call_Coverage_Level -- + --------------------------------- + + procedure Add_Fun_Call_Coverage_Level (Combinaison : Levels_Type) + is + Comb : Levels_Type := Combinaison; + begin + Comb (Fun_Call) := True; + Add_Source_Level_Option (Comb); + end Add_Fun_Call_Coverage_Level; + -------------------------------- -- Add_Assert_Coverage_Levels -- -------------------------------- @@ -158,6 +175,9 @@ package body Coverage_Options is Add_Source_Level_Option (Comb); + -- Add CallFunc to the current combinaison + Add_Fun_Call_Coverage_Level (Comb); + -- Deactivate Lvl to add the next assertion level to the -- combinaison Comb Comb (Lvl) := False; @@ -171,9 +191,11 @@ package body Coverage_Options is Combinaison : Levels_Type := (Stmt => True, others => False); begin - -- Add "stmt" only and combine it with all possible assertion levels + -- Add "stmt" only. Combine it alone with "callfunc", and then with all + -- possible assertion levels. Add_Source_Level_Option (Combinaison); + Add_Fun_Call_Coverage_Level (Combinaison); Add_Assert_Coverage_Levels (Combinaison); -- Do the same for all other regular source coverage options @@ -184,6 +206,7 @@ package body Coverage_Options is Combinaison (Lvl) := True; Add_Source_Level_Option (Combinaison); + Add_Fun_Call_Coverage_Level (Combinaison); Add_Assert_Coverage_Levels (Combinaison); -- Deactivate Lvl to combine the next level with "stmt" diff --git a/tools/gnatcov/coverage_options.ads b/tools/gnatcov/coverage_options.ads index eecb79223..caabdb62c 100644 --- a/tools/gnatcov/coverage_options.ads +++ b/tools/gnatcov/coverage_options.ads @@ -27,7 +27,7 @@ package Coverage_Options is use all type Unbounded_String; type Coverage_Level is - (Insn, Branch, Stmt, Decision, MCDC, UC_MCDC, ATC, ATCC); + (Insn, Branch, Stmt, Decision, MCDC, UC_MCDC, ATC, ATCC, Fun_Call); -- Coverage objectives supported by xcov. The following values are -- supported: @@ -39,6 +39,7 @@ package Coverage_Options is -- * source coverage at unique cause MC/DC level (UC_MCDC); -- * source coverage at ATC level (ATC); -- * source coverage at ATCC level (ATCC). + -- * source coverage at Call level (Fun_Call) -- The terms "instruction", "branch", "statement", "decision" and "MCDC" -- should be understood here as they are defined in the DO-178B standard; @@ -52,9 +53,18 @@ package Coverage_Options is -- * "ATCC" : all the conditions of the decision have been evaluated at -- least once as part of an evaluation to True of the whole -- decision. + -- + -- The "Fun_Call" coverage criteria mesures the coverage of calls and that + -- of functions. They must be understood as: + -- + -- * Function coverage : a function (for Ada, understand "subprogram") is + -- covered if it was entered at least once; + -- + -- * Call coverage : a call is covered if it was executed as least + -- once. subtype Object_Coverage_Level is Coverage_Level range Insn .. Branch; - subtype Source_Coverage_Level is Coverage_Level range Stmt .. ATCC; + subtype Source_Coverage_Level is Coverage_Level range Stmt .. Fun_Call; subtype MCDC_Coverage_Level is Coverage_Level range MCDC .. UC_MCDC; subtype Contract_Condition_Level is Coverage_Level range ATCC .. ATCC; diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 397fd12c0..2f9a95a5d 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -224,7 +224,8 @@ package Files_Table is -- Exec from where the address range has been extracted end record; - type Line_State_Cell is (Cell_1, Cell_2, Cell_3); + type Line_State_Cell is (Cell_1, Cell_2, Cell_3, Cell_4); + Coverage_Level_To_Cell : constant array (Coverage_Level) of Line_State_Cell := (Insn => Cell_1, @@ -234,14 +235,14 @@ package Files_Table is MCDC => Cell_2, UC_MCDC => Cell_2, ATC => Cell_3, - ATCC => Cell_3); - -- For one specific execution of GNATcov, we know that each line needs at - -- most only three states (insn, branch, stmt, stmt+decision, stmt+mcdc, - -- stmt+uc_mcdc, stmt+atc, stmt+decision+atc, stmt+mcdc+atc, - -- stmt+uc_mcdc+atc, stmt+atcc, stmt+decision+atcc, stmt+mcdc+atcc, - -- stmt+uc_mcdc_atcc). Thus, there is no need to store the state for all - -- coverage levels at the same time. This table is thus used to convert the - -- coverage level to the appropriate state "storage cell". + ATCC => Cell_3, + Fun_Call => Cell_4); + -- For one specific execution of GNATcov, we know that + -- each line needs at most only four states (insn, branch, + -- stmt(+decision|+mcdc|+uc_mcdc)?(+atc|+atcc)?(funcall)?). Thus, there is + -- no need to store the state for all coverage levels at the same time. + -- This table is thus used to convert the coverage level to the appropriate + -- state "storage cell". type Line_States is array (Line_State_Cell) of Line_State; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 06df6d250..6b9afc076 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -247,7 +247,7 @@ package body Instrument.Ada_Unit is function As_Symbol (Id : Identifier) return Symbol_Type; function As_Name (Id : Identifier) return Name_Id; - -- Canonicalize Id and return a corresponding Name_Id/Symbol_Type + -- Canonicalize Node and return a corresponding Name_Id/Symbol_Type function As_Symbol (Id : Text_Type) return Symbol_Type is (Find (Symbols, Id)); @@ -369,7 +369,7 @@ package body Instrument.Ada_Unit is function Is_Ghost (UIC : Ada_Unit_Inst_Context; - EF : Expr_Function) return Boolean; + D : Basic_Decl) return Boolean; -- Return whether the given expression function is ghost (EF or its -- canonical declaration has a Ghost aspect). @@ -557,7 +557,7 @@ package body Instrument.Ada_Unit is In_Generic : Boolean; In_Decl_Expr : Boolean) return Node_Rewriting_Handle; -- Create a procedure call statement or object declaration to witness - -- execution of the low level SCO with the given bit id. + -- execution of the low level SCO with the given bit Node. -- -- In_Generic indicates whether the statement witness is destined -- to be inserted in a generic package or subprogram. @@ -565,6 +565,12 @@ package body Instrument.Ada_Unit is -- In_Decl_Expr indicates whether the statement witness is inserted as -- a declaration in a declare expression. + procedure Fill_Expression_Insertion_Info + (UIC : in out Ada_Unit_Inst_Context; + Bit : Any_Bit_Id; + Insert_Info : out Insertion_Info); + -- Fill Insertion_Info with new witness formal and actual + procedure Ensure_With (UIC : in out Ada_Unit_Inst_Context'Class; Unit : Text_Type); -- Ensure that the unit being instrumented has a dependency on the named @@ -724,10 +730,10 @@ package body Instrument.Ada_Unit is -- -- ------------- Public Part ------------- -- - -- -- See Create_Augmented_Expr_Function.Augmented_Expr_Function + -- -- See Create_Augmented_Function.Augmented_Function -- -- -- -- Sometimes, we don't emit this declaration, - -- -- see Augmented_Expr_Function_Needs_Decl + -- -- see Augmented_Function_Needs_Decl -- function Foo_With_State_[Subprogram_Index] -- (Arg1 : Arg1_Type; -- Arg2 : Arg2_Type; @@ -742,7 +748,7 @@ package body Instrument.Ada_Unit is -- -- ------------ Private part ------------- -- - -- -- See Create_Augmented_Expr_Function.Augmented_Expr_Function + -- -- See Create_Augmented_Function.Augmented_Function -- function Foo_With_State_[Subprogram_Index] -- (Arg1 : Arg1_Type; -- Arg2 : Arg2_Type; @@ -751,7 +757,7 @@ package body Instrument.Ada_Unit is -- return Boolean -- is ([origin expression plus Witness calls using MCDC_State_2]);; -- - -- -- See Create_Augmented_Expr_Function.New_Expr_Function + -- -- See Create_Augmented_Function.New_Function -- function Foo (Arg1 : Arg1_Type; Arg2 : Arg2_Type) return Boolean -- is (Foo_With_State_[Subprogram_Index] -- (Arg1, @@ -770,7 +776,7 @@ package body Instrument.Ada_Unit is -- we geenrate the following declarations in the instrumented unit, -- replacing the original declaration: -- - -- -- See Create_Augmented_Expr_Function.Augmented_Expr_Function + -- -- See Create_Augmented_Function.Augmented_Function -- package Expr_Func_Pkg_[Subprogram_Index] is -- function Foo_With_State_[Subprogram_Index] -- (Arg : Arg_Type; @@ -778,7 +784,7 @@ package body Instrument.Ada_Unit is -- return Ret_Type is (); -- end Expr_Func_Pkg_[Subprogram_Index]; -- - -- -- See Create_Augmented_Expr_Function.New_Expr_Function + -- -- See Create_Augmented_Function.New_Function -- function Foo (Arg : Arg_Type] return Ret_Type is -- (Expr_Func_Pkg_[Subprogram_Index].Foo_With_State_[Subprogram_Index] -- (Arg, )); @@ -942,10 +948,16 @@ package body Instrument.Ada_Unit is NP_Nodes : Null_Proc_Nodes; Subp_Body : out Node_Rewriting_Handle; Instance : out Node_Rewriting_Handle; - Renaming_Decl : out Node_Rewriting_Handle); + Renaming_Decl : out Node_Rewriting_Handle; + Fun_Witness : Node_Rewriting_Handle); -- Create the body for the generic subprogram (Subp_Body), its -- instantiation declaration (Instance) and the renaming for this instance -- (Renaming_Decl). + -- Fun_Witness is only used for function coverage. It is set the + -- No_Node_Rewriting_Handle if function coverage is not needed, and to a + -- valid witness call if it is. If set, it is inserted at the beginning of + -- the generic subprogram and responsible for discharging the function SCO + -- associated to the null procedure. function Clone_Params (UIC : Ada_Unit_Inst_Context; @@ -971,29 +983,70 @@ package body Instrument.Ada_Unit is UIC : in out Ada_Unit_Inst_Context'Class; Name : String) return String; - procedure Create_Augmented_Expr_Function + function Create_Function_Witness_Var + (UIC : Ada_Unit_Inst_Context; + Fun_Witness : Node_Rewriting_Handle) + return Node_Rewriting_Handle + is (Create_From_Template + (UIC.Rewriting_Context, + Template => "Dummy_Witness_Var : constant Boolean := {};", + Arguments => (1 => Fun_Witness), + Rule => Basic_Decls_Rule)) + with Pre => Fun_Witness /= No_Node_Rewriting_Handle; + -- Create a dummy variable and set it to the properly set function witness + -- call. The function witness must be a function call. + + procedure Instrument_For_Function_Coverage + (UIC : in out Ada_Unit_Inst_Context; + Spec : Subp_Spec; + Witness_Flavor : Statement_Witness_Flavor; + Fun_Witness : out Node_Rewriting_Handle) + with Pre => Enabled (Fun_Call); + -- Add a function coverage SCO to Spec and set Fun_Witness to a valid + -- witness call of flavor Flavor. + + procedure Create_Augmented_Function (UIC : Ada_Unit_Inst_Context; Common_Nodes : Degenerate_Subp_Common_Nodes; Formal_Params : Node_Rewriting_Handle; Call_Params : Node_Rewriting_Handle; - Augmented_Expr_Function : out Node_Rewriting_Handle; - Augmented_Expr_Function_Decl : out Node_Rewriting_Handle; - New_Expr_Function : out Node_Rewriting_Handle); - -- Create the augmented expression function from the original one - -- (Augmented_Expr_Function) and create the expression function - -- (New_Expr_Function) that will serve as a replacement to the original - -- one. Also create a declaration for the augmented expression function, - -- if needed. It should be inserted right before the previous declaration - -- of the original expression function (which is guaranteed to exist). + Augmented_Function : out Node_Rewriting_Handle; + Augmented_Function_Decl : out Node_Rewriting_Handle; + New_Function : out Node_Rewriting_Handle; + Fun_Witness : Node_Rewriting_Handle := + No_Node_Rewriting_Handle); + -- Create the augmented function from the original one (Augmented_Function) + -- and create the new function (New_Function) that will serve as a + -- replacement to the original one. Also create a declaration for the + -- augmented function, if needed. It should be inserted right before the + -- previous declaration of the original function (which is guaranteed to + -- exist). -- - -- If the original expresison function is a primitive of its return type, - -- then Agmented_Expr_Function will not be a handle to the expression - -- function, but rather to the nested package containing the augmented - -- expression function. In such case, Used_Nested_Package will be true. + -- If the original function is a primitive of its return type, then + -- Agmented_Function will not be a handle to the function, but rather to + -- the nested package containing the augmented function. -- - -- If keep_Aspects is set to True, the aspects of the original expression - -- function will be propagated to the augmented expression function, - -- otherwise the augmented expression function will have no aspects. + -- * Common_Nodes: + -- Contains the original nodes from which the new functions will + -- be made. + -- * Formal_Params: + -- The list of formals that Augmented_Function will accept + -- * Call_Params: + -- The list of parameters that will be passed to the call to + -- Augmented_Function made in New_Function. + -- * Augmented_Function: + -- The newly created subprogram whose body contains all the statements + -- from the original function. + -- * Augmented_Function_Decl: + -- The declaration of Augmented_Function if needed. + -- * New_Function: + -- The new intermediate function that replaces the original one. + -- Responsible for calling Augmented_Function. + -- * Fun_Witness: + -- Only used for function coverage. It contains the valid witness call + -- to be inserted as needed in New_Function to discharge the function + -- SCO, or is set to No_Node_Rewriting_Handle if function coverage is + -- not needed. function Augmented_Expr_Function_Needs_Decl (N : Expr_Function) return Boolean; @@ -1890,7 +1943,9 @@ package body Instrument.Ada_Unit is return Result : Degenerate_Subp_Common_Nodes do Result.N := N; Result.N_Spec := N_Spec; - Result.N_Overriding := N.As_Base_Subp_Body.F_Overriding; + Result.N_Overriding := (if Kind (N) = Ada_Subp_Decl + then N.As_Subp_Decl.F_Overriding + else N.As_Base_Subp_Body.F_Overriding); Result.N_Name := N_Spec.F_Subp_Name.F_Name; Result.N_Params := (if N_Spec.F_Subp_Params.Is_Null @@ -2312,13 +2367,20 @@ package body Instrument.Ada_Unit is NP_Nodes : Null_Proc_Nodes; Subp_Body : out Node_Rewriting_Handle; Instance : out Node_Rewriting_Handle; - Renaming_Decl : out Node_Rewriting_Handle) + Renaming_Decl : out Node_Rewriting_Handle; + Fun_Witness : Node_Rewriting_Handle) is RC : Rewriting_Handle renames UIC.Rewriting_Context; E : Instrumentation_Entities renames UIC.Entities; begin -- Create the generic subprogram body + if Fun_Witness /= No_Node_Rewriting_Handle then + -- If the Fun_Witness is a valid witness call, insert it at the + -- beginning of the generic subprogram. + Insert_First (NP_Nodes.Stmt_List, Fun_Witness); + end if; + Subp_Body := Create_Subp_Body (RC, F_Overriding => No_Node_Rewriting_Handle, @@ -2464,37 +2526,96 @@ package body Instrument.Ada_Unit is return Name & ".State'Address"; end Insert_MCDC_State; - ------------------------------------ - -- Create_Augmented_Expr_Function -- - ------------------------------------ + -------------------------------------- + -- Instrument_For_Function_Coverage -- + -------------------------------------- + + procedure Instrument_For_Function_Coverage + (UIC : in out Ada_Unit_Inst_Context; + Spec : Subp_Spec; + Witness_Flavor : Statement_Witness_Flavor; + Fun_Witness : out Node_Rewriting_Handle) + is + Loc_Range : constant Source_Location_Range := Sloc_Range (Spec); + begin + -- Add a function coverage SCO to the specification Spec + + Append_SCO + (C1 => 'c', + C2 => 'F', + From => +Start_Sloc (Loc_Range), + To => +Inclusive_End_Sloc (Loc_Range), + SFI => UIC.SFI, + Last => True, + Pragma_Aspect_Name => Namet.No_Name); + + -- Exit early if the context disallows instrumentation + + if UIC.Disable_Instrumentation then + UIC.Non_Instr_LL_SCOs.Include (SCO_Id (SCOs.SCO_Table.Last)); + Fun_Witness := No_Node_Rewriting_Handle; + return; + end if; + + -- Set Fun_Witness to a statement witness of flavor Witness_Flavor and + -- responsible for discharging the function SCO we just created. + + Fun_Witness := + Make_Statement_Witness + (UIC, + Bit => + Allocate_Statement_Bit (UIC.Unit_Bits, SCOs.SCO_Table.Last), + Flavor => Witness_Flavor, + In_Generic => UIC.In_Generic, + In_Decl_Expr => UIC.In_Decl_Expr); + end Instrument_For_Function_Coverage; - procedure Create_Augmented_Expr_Function + ------------------------------- + -- Create_Augmented_Function -- + ------------------------------- + + procedure Create_Augmented_Function (UIC : Ada_Unit_Inst_Context; Common_Nodes : Degenerate_Subp_Common_Nodes; Formal_Params : Node_Rewriting_Handle; Call_Params : Node_Rewriting_Handle; - Augmented_Expr_Function : out Node_Rewriting_Handle; - Augmented_Expr_Function_Decl : out Node_Rewriting_Handle; - New_Expr_Function : out Node_Rewriting_Handle) + Augmented_Function : out Node_Rewriting_Handle; + Augmented_Function_Decl : out Node_Rewriting_Handle; + New_Function : out Node_Rewriting_Handle; + Fun_Witness : Node_Rewriting_Handle := + No_Node_Rewriting_Handle) is RC : Rewriting_Handle renames UIC.Rewriting_Context; - -- Compute the name of the augmented expression function + -- Compute the name of the augmented function Orig_Name_Text : constant Wide_Wide_String := Text (Common_Nodes.N_Name); Is_Op_Symbol : constant Boolean := Orig_Name_Text (Orig_Name_Text'First) = '"'; - Augmented_Expr_Func_Name : constant Wide_Wide_String := + Fun_Cov : constant Boolean := Enabled (Fun_Call); + -- True if function coverage is needed + + Augmented_Func_Name : constant Wide_Wide_String := (if Is_Op_Symbol then Op_Symbol_To_Name (Common_Nodes.N_Name) & "_Op" else Orig_Name_Text) - & "_With_State_" - & To_Wide_Wide_String (Img (UIC.Degenerate_Subprogram_Index)); - - Need_WP : constant Boolean := - Augmented_EF_Needs_Wrapper_Package (Common_Nodes); + & (if not Fun_Cov + then "_With_State_" + else "_") + & To_Wide_Wide_String (Img (UIC.Degenerate_Subprogram_Index)) + & (if Fun_Cov + then "_GNATCOV_Aux" + else ""); + + Is_Subp_Body : constant Boolean := + Fun_Cov and then Common_Nodes.N.Kind = Ada_Subp_Body; + -- We only need to consider subprogram bodies when function coverage is + -- needed. + + Need_WP : constant Boolean := not Is_Subp_Body + and then Augmented_EF_Needs_Wrapper_Package (Common_Nodes); -- Create the expression for New_Expr_Function that will call that -- augmented expression function. @@ -2506,35 +2627,75 @@ package body Instrument.Ada_Unit is F_Prefix => Clone (Common_Nodes.Wrapper_Pkg_Name), F_Suffix => Create_Identifier (RC, - Text => Augmented_Expr_Func_Name)) + Text => Augmented_Func_Name)) else Create_Identifier - (RC, Text => Augmented_Expr_Func_Name)); + (RC, Text => Augmented_Func_Name)); - Call_Expr : constant Node_Rewriting_Handle := Create_Call_Expr - (RC, - F_Name => Callee, - F_Suffix => Call_Params); + Call_Expr : constant Node_Rewriting_Handle := + (if Call_Params = No_Node_Rewriting_Handle + then Callee + else Create_Call_Expr + (RC, + F_Name => Callee, + F_Suffix => Call_Params)); -- No need for a declaration if we are using a nested package - Needs_Decl : constant Boolean := not Need_WP - and then Augmented_Expr_Function_Needs_Decl + Needs_Decl : constant Boolean := + Common_Nodes.N.Kind = Ada_Expr_Function + and then not Need_WP + and then Augmented_Expr_Function_Needs_Decl (Common_Nodes.N.As_Expr_Function); Orig_Aspects : constant Aspect_Spec := Common_Nodes.N.F_Aspects; begin + -- Create the new augmented function - New_Expr_Function := - Create_Expr_Function - (RC, - F_Overriding => Clone (Common_Nodes.N_Overriding), - F_Subp_Spec => Clone (Common_Nodes.N_Spec), - F_Expr => Create_Paren_Expr (RC, Call_Expr), - F_Aspects => No_Node_Rewriting_Handle); + if Is_Subp_Body then - -- The original expression function becomes the augmented one: + -- For a regular subrogram needing function coverage, two statements + -- will be inserted in the body of the new function. First the + -- witness call linked to the function SCO, next the return or call + -- statement calling the new augmented function. - Augmented_Expr_Function := Handle (Common_Nodes.N); + declare + Stmts : constant Node_Rewriting_Handle := + Create_Regular_Node + (Handle => UIC.Rewriting_Context, + Kind => Ada_Stmt_List, + Children => + (1 => Fun_Witness, + 2 => + (if Common_Nodes.N.Kind = Ada_Subp_Body + and then + Common_Nodes.N.As_Subp_Body.F_Subp_Spec.F_Subp_Kind = + Ada_Subp_Kind_Function + then Create_Return_Stmt (RC, Call_Expr) + else Create_Call_Stmt (RC, Call_Expr)))); + begin + New_Function := + Create_Subp_Body + (RC, + F_Overriding => Clone (Common_Nodes.N_Overriding), + F_Subp_Spec => Clone (Common_Nodes.N_Spec), + F_Aspects => No_Node_Rewriting_Handle, + F_Decls => No_Node_Rewriting_Handle, + F_Stmts => Stmts, + F_End_Name => Make_Identifier (UIC, Orig_Name_Text)); + end; + else + New_Function := + Create_Expr_Function + (RC, + F_Overriding => Clone (Common_Nodes.N_Overriding), + F_Subp_Spec => Clone (Common_Nodes.N_Spec), + F_Expr => Create_Paren_Expr (RC, Call_Expr), + F_Aspects => No_Node_Rewriting_Handle); + end if; + + -- The original function becomes the augmented one: + + Augmented_Function := Handle (Common_Nodes.N); -- overriding keyword is purely optional, so there is no drawback in -- removing it. @@ -2547,15 +2708,27 @@ package body Instrument.Ada_Unit is Replace (Handle (Common_Nodes.N_Name), - Make_Identifier (UIC, Augmented_Expr_Func_Name)); + Make_Identifier (UIC, Augmented_Func_Name)); + + if Is_Subp_Body + and then not Common_Nodes.N.As_Subp_Body.F_End_Name.Is_Null + then + -- For regular subprogram bodies, also change the end name + + Replace + (Handle (Common_Nodes.N.As_Subp_Body.F_End_Name), + Make_Identifier (UIC, Augmented_Func_Name)); + end if; -- Use the "augmented formal params" (i.e. original formals plus the -- witness one and the MC/DC state holders). - Set_Child - (Handle (Common_Nodes.N_Spec), - Member_Refs.Subp_Spec_F_Subp_Params, - Create_Params (RC, Formal_Params)); + if Formal_Params /= No_Node_Rewriting_Handle then + Set_Child + (Handle (Common_Nodes.N_Spec), + Member_Refs.Subp_Spec_F_Subp_Params, + Create_Params (RC, Formal_Params)); + end if; -- If we also need a declaration for the augmented expression -- function, create it. Otherwise, set it to No_Node_Rewriting_Handle. @@ -2568,7 +2741,7 @@ package body Instrument.Ada_Unit is -- use-clauses in between the declaration and the completion. -- -- Note that Needs_Decl can be true True only when - -- Augmented_Expr_Function_Needs_Decl returns True, and that can + -- Augmented_Function_Needs_Decl returns True, and that can -- happen only when it managed to get the previous part of -- Common_Node.N, so the call to P_Previous_Part_For_Decl below is -- guaranteed to return a non-null node. @@ -2582,28 +2755,36 @@ package body Instrument.Ada_Unit is -- Clone the spec of the original declaration - New_Spec : constant Node_Rewriting_Handle := Clone (Previous_Spec); - + New_Spec : constant Node_Rewriting_Handle := + (if Fun_Cov + then Handle (Previous_Spec) + else Clone (Previous_Spec)); begin -- Replace the original EF name by the augmented EF name - - Set_Child (New_Spec, - Member_Refs.Subp_Spec_F_Subp_Name, - Make_Identifier (UIC, Augmented_Expr_Func_Name)); + if not Fun_Cov then + Set_Child (New_Spec, + Member_Refs.Subp_Spec_F_Subp_Name, + Make_Identifier (UIC, Augmented_Func_Name)); + end if; -- Add the augmented params to this spec as well - Set_Child - (New_Spec, - Member_Refs.Subp_Spec_F_Subp_Params, - Create_Params (RC, Clone (Formal_Params))); + if Formal_Params /= No_Node_Rewriting_Handle then + Set_Child + (New_Spec, + Member_Refs.Subp_Spec_F_Subp_Params, + Create_Params (RC, Clone (Formal_Params))); + end if; - Augmented_Expr_Function_Decl := Create_Subp_Decl - (Handle => UIC.Rewriting_Context, - F_Overriding => No_Node_Rewriting_Handle, - F_Subp_Spec => New_Spec, - F_Aspects => No_Node_Rewriting_Handle); + Augmented_Function_Decl := + (if not Fun_Cov + then Create_Subp_Decl + (Handle => UIC.Rewriting_Context, + F_Overriding => No_Node_Rewriting_Handle, + F_Subp_Spec => New_Spec, + F_Aspects => No_Node_Rewriting_Handle) + else No_Node_Rewriting_Handle); exception when Exc : Property_Error => @@ -2614,7 +2795,7 @@ package body Instrument.Ada_Unit is Kind => Low_Warning); end; else - Augmented_Expr_Function_Decl := No_Node_Rewriting_Handle; + Augmented_Function_Decl := No_Node_Rewriting_Handle; if not Orig_Aspects.Is_Null then declare @@ -2632,7 +2813,7 @@ package body Instrument.Ada_Unit is then Replace (Handle (N.As_Attribute_Ref.F_Prefix), - Make_Identifier (UIC, Augmented_Expr_Func_Name)); + Make_Identifier (UIC, Augmented_Func_Name)); end if; return Into; end Replace_Attr_Subp_Name; @@ -2661,7 +2842,7 @@ package body Instrument.Ada_Unit is -- Attach the aspect specifications of the original expression -- function to the augmented one. - Set_Child (Augmented_Expr_Function, + Set_Child (Augmented_Function, Member_Refs.Basic_Decl_F_Aspects, Detach (Orig_Aspects)); end if; @@ -2669,7 +2850,12 @@ package body Instrument.Ada_Unit is -- If the original expression function is ghost, so must be the -- augmented one. - if Is_Ghost (UIC, Common_Nodes.N.As_Expr_Function) then + if Is_Ghost + (UIC, + (if Common_Nodes.N.Kind = Ada_Expr_Function + then Common_Nodes.N.As_Expr_Function.As_Basic_Decl + else Common_Nodes.N.As_Basic_Decl)) + then declare Ghost_Aspect : constant Node_Rewriting_Handle := Create_Aspect_Assoc @@ -2684,7 +2870,7 @@ package body Instrument.Ada_Unit is begin if Needs_Decl then Set_Child - (Augmented_Expr_Function_Decl, + (Augmented_Function_Decl, Member_Refs.Basic_Decl_F_Aspects, Aspects); else @@ -2702,12 +2888,12 @@ package body Instrument.Ada_Unit is -- return its handle instead of the one of the expression function. Insert_Last - (Common_Nodes.Wrapper_Pkg_Decls, Augmented_Expr_Function); + (Common_Nodes.Wrapper_Pkg_Decls, Augmented_Function); - Augmented_Expr_Function := Common_Nodes.Wrapper_Pkg; + Augmented_Function := Common_Nodes.Wrapper_Pkg; end if; - end Create_Augmented_Expr_Function; + end Create_Augmented_Function; ---------------------------------------- -- Augmented_Expr_Function_Needs_Decl -- @@ -3180,6 +3366,20 @@ package body Instrument.Ada_Unit is -- -- This also processes any nested declare expressions. + function Is_Call_Leaf (Node : Ada_Node'Class) return Boolean; + -- Return True if Node is the leaf of a call expression, that is there are + -- no nodes in the children of Node identifying the same call. + -- + -- This is used to avoid processing the same call multiple times when + -- traversing the AST. E.g. when processing a dotted name A.B.C (..), both + -- A.B.C (..) and C (..) designate the same call. As such, we should only + -- process it once; we choose to do this on the inner-most node. + + function Full_Call (Node : Ada_Node'Class) return Ada_Node; + -- From an node that is a call, get its parent if it is a + -- Dotted_Name. Return the dotted name if this is a call with no arguments, + -- or the Call_Expr parent if it is a call with arguments. + -------------------------- -- Internal Subprograms -- -------------------------- @@ -3544,7 +3744,7 @@ package body Instrument.Ada_Unit is Process_Expression (UIC, P_Get_Aspect_Spec_Expr (D, To_Unbounded_Text (Name)), - 'A'); + 'A'); end Process_Contract; ------------------------ @@ -3561,7 +3761,7 @@ package body Instrument.Ada_Unit is return Symbol_Type is (if Prag_Arg_Expr (Prag_Args, I).Kind = - Libadalang.Common.Ada_Identifier + Libadalang.Common.Ada_Identifier then As_Symbol (Prag_Arg_Expr (Prag_Args, I).As_Identifier) else No_Symbol); -- Attempt to get the pragma's Ith argument as an identifier. If @@ -3777,7 +3977,13 @@ package body Instrument.Ada_Unit is UIC.MCDC_State_Inserter; -- Likewise for MC/DC state inserter - procedure To_Regular_Subprogram (N : Base_Subp_Body); + Fun_Cov : constant Boolean := Enabled (Fun_Call); + -- True if function coverage is enabled. If True, the function will + -- be instrumented for function coverage. + + procedure To_Regular_Subprogram + (N : Base_Subp_Body; + Fun_Witness : Node_Rewriting_Handle := No_Node_Rewriting_Handle); -- Turns N into an instrumented regular function, by creating a -- function with the same subp_spec as the original expression -- function or null procedure, and a single return statement with the @@ -3787,12 +3993,20 @@ package body Instrument.Ada_Unit is -- The SCO associated with the new single statement has the -- sloc of the whole original subprogram. + procedure Create_Witness_Formal + (Formal : out Node_Rewriting_Handle; + Formal_Name : Wide_Wide_String); + -- Fill Formal with a new Node_Rewriting_Handle being a formal to + -- receive a witness call. + --------------------------- -- To_Regular_Subprogram -- --------------------------- - procedure To_Regular_Subprogram (N : Base_Subp_Body) is - + procedure To_Regular_Subprogram + (N : Base_Subp_Body; + Fun_Witness : Node_Rewriting_Handle := No_Node_Rewriting_Handle) + is Single_Stmt_RH : constant Node_Rewriting_Handle := (if N.Kind = Ada_Expr_Function then Create_Return_Stmt @@ -3854,27 +4068,69 @@ package body Instrument.Ada_Unit is Process_Expression (UIC, N.As_Expr_Function.F_Expr, 'X'); end if; + if Fun_Witness /= No_Node_Rewriting_Handle then + Insert_First + (Decl_List, + Create_From_Template + (UIC.Rewriting_Context, + Template => "Dummy_Witness_Var : Boolean := {};", + Arguments => (1 => Fun_Witness), + Rule => Basic_Decls_Rule)); + end if; + -- Insert the new regular function in place of the old subprogram - Replace (Handle (N), - Create_Subp_Body - (Handle => UIC.Rewriting_Context, - F_Overriding => Detach (N.F_Overriding), - F_Subp_Spec => Detach (N.F_Subp_Spec), - F_Aspects => Detach (N.F_Aspects), - F_Decls => Proc_Decls, - F_Stmts => Stmts_RH, - F_End_Name => Proc_Name)); + Replace + (Handle (N), + Create_Subp_Body + (Handle => UIC.Rewriting_Context, + F_Overriding => Detach (N.F_Overriding), + F_Subp_Spec => Detach (N.F_Subp_Spec), + F_Aspects => Detach (N.F_Aspects), + F_Decls => Proc_Decls, + F_Stmts => Stmts_RH, + F_End_Name => Proc_Name)); UIC.Current_Insertion_Info := Saved_Insertion_Info; UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; end To_Regular_Subprogram; + -------------------------- + -- Crete_Witness_Formal -- + -------------------------- + + procedure Create_Witness_Formal + (Formal : out Node_Rewriting_Handle; + Formal_Name : Wide_Wide_String) + is + Formal_Id : constant Node_Rewriting_Handle := + Make_Identifier (UIC, Formal_Name); + Formal_Def_Id : constant Node_Rewriting_Handle := + Create_Regular_Node + (UIC.Rewriting_Context, + Ada_Defining_Name_List, + Children => + (1 => Create_Defining_Name + (UIC.Rewriting_Context, Formal_Id))); + begin + Formal := Create_Param_Spec + (UIC.Rewriting_Context, + F_Ids => Formal_Def_Id, + F_Has_Aliased => No_Node_Rewriting_Handle, + F_Mode => No_Node_Rewriting_Handle, + F_Type_Expr => Make_Std_Ref (UIC, "Boolean"), + F_Default_Expr => No_Node_Rewriting_Handle, + F_Aspects => No_Node_Rewriting_Handle); + end Create_Witness_Formal; + Is_Expr_Function : constant Boolean := N.Kind = Ada_Expr_Function; + Is_Subp_Body : constant Boolean := N.Kind = Ada_Subp_Body; Gen_Names_Prefix : constant Wide_Wide_String := To_Wide_Wide_String - ((if Is_Expr_Function then "Func_Expr" else "Null_Proc") + ((if Is_Expr_Function + then "Func_Expr" + else (if Fun_Cov then "Aux" else "Null_Proc")) & "_" & Img (UIC.Degenerate_Subprogram_Index) & Part_Tags (UIC.Instrumented_Unit.Part) @@ -3883,6 +4139,7 @@ package body Instrument.Ada_Unit is Call_Params : constant Node_Rewriting_Handle := (if Is_Expr_Function + or else (Fun_Cov and then not N_Spec.F_Subp_Params.Is_Null) then Make (UIC, Ada_Assoc_List) else No_Node_Rewriting_Handle); -- List of formal/actual associations for the call to the augmented @@ -3890,11 +4147,15 @@ package body Instrument.Ada_Unit is Formal_Params : constant Node_Rewriting_Handle := (if Is_Expr_Function + or else (Fun_Cov and then not N_Spec.F_Subp_Params.Is_Null) then Clone_Params (UIC, N_Spec) else No_Node_Rewriting_Handle); -- List of formal parameters for the augmented function. Unused if we -- are not processing an expression function. + Fun_Witness : Node_Rewriting_Handle := No_Node_Rewriting_Handle; + -- Function witness to be inserted if function coverage is needed + ------------------------------------ -- Collection of various nodes... -- ------------------------------------ @@ -3914,6 +4175,8 @@ package body Instrument.Ada_Unit is New_Insertion_Info : aliased Insertion_Info; -- Witness insertion info for statements (for both null procedures -- and expression functions). + New_Fun_Insertion_Info : aliased Insertion_Info; + -- Witness insertion info for function SCO Save_Disable_Instrumentation : constant Boolean := UIC.Disable_Instrumentation; @@ -4060,7 +4323,7 @@ package body Instrument.Ada_Unit is & "cannot instrument generic expression functions." & " Consider turning it into a regular function body."); - else + elsif not Is_Subp_Body then -- As Traverse_Degenerate_Subprogram deals only with expression -- functions and null procedures, we are in the case of a -- generic null procedure here. @@ -4138,13 +4401,39 @@ package body Instrument.Ada_Unit is -- instrumentation issues. if not N.P_Semantic_Parent.Is_Null - and then N.P_Semantic_Parent.Kind = Ada_Protected_Body + and then N.P_Semantic_Parent.Kind = Ada_Protected_Body then - To_Regular_Subprogram (N.As_Base_Subp_Body); + declare + Fun_Witness : Node_Rewriting_Handle := No_Node_Rewriting_Handle; + begin + if Fun_Cov then + Instrument_For_Function_Coverage + (UIC, + N.As_Basic_Decl.P_Subp_Spec_Or_Null.As_Subp_Spec, + Function_Call, + Fun_Witness); + end if; + + if not Is_Subp_Body then + -- Turn the expression function or null procedure into + -- a regular subprogram. If function coverage is needed, + -- declare a variable in this new subprogram which will + -- be set to a witness call linked to the function SCO. + + To_Regular_Subprogram (N.As_Base_Subp_Body, Fun_Witness); + else + if Fun_Witness /= No_Node_Rewriting_Handle then + Insert_First + (Handle (N.As_Subp_Body.F_Decls.F_Decls), + Create_Function_Witness_Var (UIC, Fun_Witness)); + end if; + end if; + end; + return; end if; - if Is_Expr_Function then + if Is_Expr_Function or else Is_Subp_Body then -- The statement instrumentation below will take care of assigning -- .Witness_* components to their definitive values. @@ -4154,6 +4443,13 @@ package body Instrument.Ada_Unit is Witness_Actual => No_Node_Rewriting_Handle, Witness_Formal => No_Node_Rewriting_Handle); + if Is_Expr_Function and then Fun_Cov then + New_Fun_Insertion_Info := + (Method => Expression_Function, + Witness_Actual => No_Node_Rewriting_Handle, + Witness_Formal => No_Node_Rewriting_Handle); + end if; + if not UIC.Disable_Instrumentation then -- Pass all expression function parameters to the augmented @@ -4219,7 +4515,7 @@ package body Instrument.Ada_Unit is Instrument_Statement (UIC, N_Expr, 'X'); Process_Expression (UIC, N_Expr, 'X'); end; - else + elsif N.Kind /= Ada_Subp_Body then -- Even though there is a "null" keyword in the null procedure, -- there is no dedicated node for it in the Libadalang parse tree: -- use the whole null procedure declaration to provide a sloc. @@ -4243,6 +4539,34 @@ package body Instrument.Ada_Unit is New_Insertion_Info := UIC.Current_Insertion_Info.Get; + if Fun_Cov then + + if Is_Expr_Function then + -- For function coverage for expression functions, we need a + -- second formal parameter meant to receive the function + -- coverage witness call. + + Create_Witness_Formal + (New_Fun_Insertion_Info.Witness_Formal, + "Dummy_Witness_Formal_Fun"); + end if; + + -- If function coverage is needed, append a function coverage SCO + -- and prepare the witness statement to be inserted in the new + -- subprogram body later. + + declare + Witness_Flavor : constant Statement_Witness_Flavor := + (if Is_Expr_Function + then Function_Call + else Procedure_Call); + + begin + Instrument_For_Function_Coverage + (UIC, Common_Nodes.N_Spec, Witness_Flavor, Fun_Witness); + end; + end if; + -- Restore saved insertion context UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; @@ -4258,10 +4582,29 @@ package body Instrument.Ada_Unit is if Is_Expr_Function then - -- Pass the witness call to the augmented expression function + -- Pass the witness call to the augmented/auxiliary expression + -- function. + + if Call_Params /= No_Node_Rewriting_Handle then + Insert_Last (Call_Params, New_Insertion_Info.Witness_Actual); + + -- If function coverage is needed, pass a second witness call + -- as argument. This one is responsible for discharging the + -- function SCO. + + if Fun_Cov then + Insert_Last (Call_Params, Fun_Witness); + end if; + end if; - Insert_Last (Call_Params, New_Insertion_Info.Witness_Actual); - Insert_Last (Formal_Params, New_Insertion_Info.Witness_Formal); + if Formal_Params /= No_Node_Rewriting_Handle then + Insert_Last (Formal_Params, New_Insertion_Info.Witness_Formal); + + if Fun_Cov then + Insert_Last + (Formal_Params, New_Fun_Insertion_Info.Witness_Formal); + end if; + end if; end if; ---------------------------- @@ -4287,13 +4630,14 @@ package body Instrument.Ada_Unit is -- recursive ones), as the generated code requires the declaration to -- be legal Ada. - if N.As_Base_Subp_Body.P_Previous_Part.Is_Null - and then (not Is_Expr_Function - or else Is_Self_Referencing (UIC, N.As_Expr_Function)) + if Kind (N) in Ada_Base_Subp_Body + and then N.As_Base_Subp_Body.P_Previous_Part.Is_Null + and then (not Is_Expr_Function + or else Is_Self_Referencing (UIC, N.As_Expr_Function)) then + Insert_Before - (Stub, - Create_Subp_Decl + (Stub, Create_Subp_Decl (RC, F_Overriding => Detach (Common_Nodes.N_Overriding), F_Subp_Spec => Clone (N_Spec), @@ -4304,37 +4648,38 @@ package body Instrument.Ada_Unit is -- added to the augmented function later on. end if; - if Is_Expr_Function then + if Is_Expr_Function or else Is_Subp_Body then declare - Augmented_Expr_Function : Node_Rewriting_Handle; - Augmented_Expr_Function_Decl : Node_Rewriting_Handle; - New_Expr_Function : Node_Rewriting_Handle; + Augmented_Function : Node_Rewriting_Handle; + Augmented_Function_Decl : Node_Rewriting_Handle; + New_Function : Node_Rewriting_Handle; begin -- Create the augmented expression function and amend the -- original one. - Create_Augmented_Expr_Function + Create_Augmented_Function (UIC, Common_Nodes, Formal_Params, Call_Params, - Augmented_Expr_Function, - Augmented_Expr_Function_Decl, - New_Expr_Function); + Augmented_Function, + Augmented_Function_Decl, + New_Function, + Fun_Witness); -- First comes the augmented expression function, then the new -- expression function. - Insert_Before (Stub, Augmented_Expr_Function); - Insert_Before (Stub, New_Expr_Function); + Insert_Before (Stub, Augmented_Function); + Insert_Before (Stub, New_Function); -- If we need to insert a declaration for the new expression -- function, find the correct spot to add it, and keep track -- of this insertion if it happens in the same list as the -- one currently being instrumented. - if Augmented_Expr_Function_Decl /= No_Node_Rewriting_Handle then + if Augmented_Function_Decl /= No_Node_Rewriting_Handle then declare Previous_Decl : constant Basic_Decl := N.P_Previous_Part_For_Decl; @@ -4345,11 +4690,10 @@ package body Instrument.Ada_Unit is -- Augmented_Expr_Function_Needs_Decl. begin Insert_Before - (Handle (Previous_Decl), Augmented_Expr_Function_Decl); + (Handle (Previous_Decl), Augmented_Function_Decl); end; end if; end; - else -- For null procedures... @@ -4367,7 +4711,10 @@ package body Instrument.Ada_Unit is NP_Nodes, Subp_Body, Instance, - Renaming_Decl); + Renaming_Decl, + (if Fun_Cov + then Fun_Witness + else No_Node_Rewriting_Handle)); -- Insert the renaming in the wrapper package @@ -4432,7 +4779,9 @@ package body Instrument.Ada_Unit is begin -- Process decisions nested in formal parameters - Process_Expression (UIC, N_Spec.F_Subp_Params, 'X'); + if not N_Spec.Is_Null then + Process_Expression (UIC, N_Spec.F_Subp_Params, 'X'); + end if; Enter_Scope (UIC => UIC, @@ -4446,14 +4795,18 @@ package body Instrument.Ada_Unit is if N.Kind in Ada_Null_Subp_Decl then Traverse_Degenerate_Subprogram (N, N_Spec); - elsif N.Kind in Ada_Subp_Decl then + elsif N.Kind in Ada_Subp_Decl then Process_Contracts (N.As_Subp_Decl); elsif N.Kind in Ada_Expr_Function then Process_Contracts (N.As_Expr_Function); Traverse_Degenerate_Subprogram (N, N_Spec); + + elsif N.Kind in Ada_Subp_Body and then Enabled (Fun_Call) then + Traverse_Degenerate_Subprogram (N, N_Spec); end if; + Exit_Scope (UIC); End_Statement_Block (UIC); end Traverse_Subp_Decl_Or_Stub; @@ -4632,11 +4985,39 @@ package body Instrument.Ada_Unit is when Ada_Subp_Body | Ada_Task_Body - => - if Is_Generic (UIC, N.As_Basic_Decl) then - UIC.In_Generic := True; - end if; - Traverse_Subprogram_Or_Task_Body (UIC, N); + => + declare + Is_Generic_Subp : constant Boolean := + Is_Generic (UIC, N.As_Basic_Decl); + + Fun_Witness : Node_Rewriting_Handle := + No_Node_Rewriting_Handle; + begin + UIC.In_Generic := Is_Generic_Subp; + + Traverse_Subprogram_Or_Task_Body (UIC, N); + + if Enabled (Fun_Call) then + if Is_Generic_Subp + or else + (UIC.Current_Insertion_Info.Get.Method = None + and then N.Kind /= Ada_Null_Subp_Decl) + then + Instrument_For_Function_Coverage + (UIC, + N.As_Subp_Body.F_Subp_Spec, + Function_Call, + Fun_Witness); + + Insert_First + (Handle (N.As_Subp_Body.F_Decls.F_Decls), + Create_Function_Witness_Var (UIC, Fun_Witness)); + else + Traverse_Subp_Decl_Or_Stub (N.As_Basic_Decl); + end if; + end if; + end; + UIC.In_Generic := Saved_In_Generic; -- Entry body @@ -4721,6 +5102,7 @@ package body Instrument.Ada_Unit is Ada_Node (Elif), 'I', Insertion_N => Handle (Elif.F_Cond_Expr)); End_Statement_Block (UIC); + Process_Expression (UIC, Elif.F_Cond_Expr, 'I'); -- Traverse the statements in the ELSIF @@ -5122,8 +5504,25 @@ package body Instrument.Ada_Unit is End_Statement_Block (UIC); Start_Statement_Block (UIC); - when others => + when Ada_Call_Stmt => + Instrument_Statement (UIC, N, ' '); + + if Enabled (Fun_Call) then + Append_SCO + (C1 => 'c', + C2 => 'S', + From => + +Start_Sloc (N.As_Call_Stmt.F_Call.Sloc_Range), + To => + +Inclusive_End_Sloc (N.As_Call_Stmt.F_Call.Sloc_Range), + SFI => UIC.SFI, + Last => True, + Pragma_Aspect_Name => Namet.No_Name); + end if; + + Process_Expression (UIC, N, 'X'); + when others => -- Determine required type character code, or ASCII.NUL if -- no SCO should be generated for this node. @@ -5204,7 +5603,7 @@ package body Instrument.Ada_Unit is Items_Count : constant Natural := (if L.Is_Null then 0 else L.Children_Count); - -- Start of processing for Traverse_Declarations_Or_Statements + -- Start of processing for Traverse_Declarations_Or_Statements begin if Is_Block then @@ -5689,6 +6088,25 @@ package body Instrument.Ada_Unit is N : Ada_Node'Class; T : Character) is + procedure Process_Call_Expression (N : Ada_Node'Class); + -- Traverse the expression N to instrument calls for call coverage. + -- + -- To instument a call expression, the original call expresison is + -- replaced by an if-expression. The call: + -- + -- Foo (X) + -- + -- Becomes: + -- + -- (if + -- then Foo (X) + -- else Foo (X)) + -- + -- Note that only the parameters of the original call will be + -- instrumented. Since the witness call should always return False, + -- the original call is that in the "else" branch. The one in the + -- "then" branch should never be executed. + function Process_Decl_Expr (N : Ada_Node'Class) return Visit_Status; -- Helper to Libadalang's Traverse. Only operates on Decl_Exprs, -- instrument each declaration as a statement and process the nested @@ -5703,6 +6121,198 @@ package body Instrument.Ada_Unit is N : Ada_Node'Class; T : Character); + ----------------------------- + -- Process_Call_Expression -- + ----------------------------- + + procedure Process_Call_Expression (N : Ada_Node'Class) + is + function Aux_Process_Call_Expression + (Node : Ada_Node'Class) + return Visit_Status; + -- Auxiliary function, responsible for the actual instrumentation. It + -- is called on all children of N. if Node is a call expression it is + -- instrumented. Otherwise, Into is returned to ensure all children + -- are visited. This is needed in order to find nested calls in + -- expressions. + + --------------------------------- + -- Aux_Process_Call_Expression -- + --------------------------------- + + function Aux_Process_Call_Expression + (Node : Ada_Node'Class) + return Visit_Status + is + Full_Call_Node : Ada_Node; + begin + if Is_Call_Leaf (Node) then + Full_Call_Node := Full_Call (Node); + + -- Skip calls that are direct children of call statements + + if Full_Call_Node.Parent.Kind in Ada_Call_Stmt then + return Into; + end if; + + -- Generate a SCO for this call + + declare + Orig_Handle : constant Node_Rewriting_Handle := + Handle (Full_Call_Node); + Dummy_Handle : constant Node_Rewriting_Handle := + Create_Node (UIC.Rewriting_Context, Full_Call_Node.Kind); + Then_Node : constant Node_Rewriting_Handle := + Clone (Full_Call_Node); + + Return_Type : Base_Type_Decl := No_Base_Type_Decl; + + Needs_Qualified_Expr : constant Boolean := + Full_Call_Node.Parent.Kind = Ada_Dotted_Name; + -- We only need to turn the if-expression into a qualified + -- when the parent of the call and its parent are both + -- dotted named. For example, with A and B packages, F a + -- function returning a record and X a field of this record: + -- + -- A.B.F.X + -- + -- Here the instrumentation of F needs to be a name, so we + -- need the fully qualifed if-expression. But for: + -- + -- A.B.F + -- + -- The if-expression alone suffices. + + Do_Not_Instrument : Boolean := False; + -- Whether we can instrument this call. Depends on whether + -- we need to use a qualified expression to insturment, and + -- if the return type of the call is visible from the call + -- site or not. + + Location : constant Source_Location_Range := + Full_Call_Node.Sloc_Range; + begin + Append_SCO + (C1 => 'c', + C2 => 'E', + From => +Start_Sloc (Location), + To => +Inclusive_End_Sloc (Location), + SFI => UIC.SFI, + Last => True, + Pragma_Aspect_Name => Namet.No_Name); + + -- Pre-compute the return type of the expression if we + -- need to generate a qualified expression. + -- + -- If we cannot determine it, do not insturment the call. + + begin + if Needs_Qualified_Expr then + Return_Type := + Full_Call_Node.As_Expr.P_Expression_Type; + end if; + exception + when Property_Error => + Report + (Full_Call_Node, + "Failed to retrieve the expression type of the" + & " call", + Kind => Warning); + Do_Not_Instrument := True; + end; + + -- TODO: LIMITATION + -- Currently, gnatcov is unable to determine if the full + -- name of a type is visible and can be explicitely used in + -- a unit. For this reason, we cannot currently turn + -- the if-expressions into fully qualified names. This is + -- need for call the are in the middle of a dotted name. + -- For now, do not instrument calls that wouls require such + -- an instrumentation. + + Do_Not_Instrument := Needs_Qualified_Expr; + + if not Do_Not_Instrument then + Fill_Expression_Insertion_Info + (UIC, + Allocate_Statement_Bit + (UIC.Unit_Bits, + SCOs.SCO_Table.Last), + UIC.Current_Insertion_Info.Get); + + Replace (Orig_Handle, Dummy_Handle); + + declare + If_Expression : constant Node_Rewriting_Handle := + Create_Paren_Expr + (UIC.Rewriting_Context, + Create_If_Expr + (UIC.Rewriting_Context, + UIC.Current_Insertion_Info.Get.Witness_Actual, + Then_Node, + No_Node_Rewriting_Handle, + Orig_Handle + )); + + Qualified_Expr : constant Node_Rewriting_Handle := + (if Needs_Qualified_Expr + then + Create_Qual_Expr + (UIC.Rewriting_Context, + F_Prefix => To_Nodes + (UIC.Rewriting_Context, + To_Qualified_Name + (Return_Type.As_Basic_Decl + .P_Fully_Qualified_Name_Array)), + F_Suffix => + Create_Paren_Expr (UIC.Rewriting_Context, + If_Expression)) + else No_Node_Rewriting_Handle); + begin + if Needs_Qualified_Expr then + Replace (Dummy_Handle, Qualified_Expr); + else + Replace (Dummy_Handle, If_Expression); + end if; + end; + else + Report + (UIC, + Full_Call_Node, + "gnatcov limitation: cannot instrument calls within" + & " dotted names", + Warning); + UIC.Non_Instr_LL_SCOs.Include + (SCO_Id (SCOs.SCO_Table.Last)); + end if; + end; + end if; + + return Into; + + end Aux_Process_Call_Expression; + + Saved_Insertion_Info : constant Insertion_Info := + UIC.Current_Insertion_Info.Get; + + Local_Insertion_Info : constant Insertion_Info (Expression_Function) + := + (Method => Expression_Function, + Witness_Actual => No_Node_Rewriting_Handle, + Witness_Formal => No_Node_Rewriting_Handle); + begin + if N.Is_Null then + return; + end if; + + UIC.Current_Insertion_Info.Set (Local_Insertion_Info); + + N.Traverse (Aux_Process_Call_Expression'Access); + + Insertion_Info_SP.Set + (UIC.Current_Insertion_Info, Saved_Insertion_Info); + end Process_Call_Expression; + ----------------------- -- Process_Decl_Expr -- ----------------------- @@ -5801,7 +6411,7 @@ package body Instrument.Ada_Unit is -- to worry about overwriting them. Current_Decision : Nat; - -- Low level SCO id of current decision + -- Low level SCO Id of current decision X_Not_Decision : Boolean; -- This flag keeps track of whether a decision sequence in the @@ -6333,10 +6943,138 @@ package body Instrument.Ada_Unit is return; end if; Process_Decisions (UIC, N, T); + + -- Then, look for all call expressions to instrument them. However, + -- avoid instrumenting calls that are in subprogram specifications. + -- If this subprogram has a previous declaration and calls for default + -- parameter values, the buffer indices passed to the two witness calls + -- inserted in the declaration and the body specifications will be + -- different, and the declaration and body will not be conformant + -- with each other anymore. + + if Enabled (Fun_Call) + and then N.Parent.Kind /= Ada_Subp_Spec + then + if N.Kind = Ada_Call_Stmt then + for Child of N.Children loop + if Child.Kind = Ada_Call_Expr then + Process_Call_Expression + (Child.As_Call_Expr.F_Suffix); + end if; + end loop; + else + Process_Call_Expression (N); + end if; + end if; + N.Traverse (Process_Decl_Expr'Access); N.Traverse (Process_Raise_Expr'Access); end Process_Expression; + ------------------ + -- Is_Call_Leaf -- + ------------------ + + function Is_Call_Leaf (Node : Ada_Node'Class) return Boolean is + begin + case Node.Kind is + when LALCO.Ada_Name => + + -- The suffix of a Dotted name will designate the same call + + if Node.Kind in Ada_Dotted_Name then + return False; + end if; + + -- The prefix of a call expr (that is actually a call) will + -- designate the same call. + + if Node.Kind in Ada_Call_Expr + and then Node.As_Call_Expr.P_Kind = Call + then + return False; + end if; + + return + (Node.As_Name.P_Is_Call + or else (Node.Parent.Kind = Ada_Call_Expr + and then Node.Parent.As_Call_Expr.P_Kind = Call)); + + -- TODO??? Only process operators if they are **not** predefined + -- operators? + + when Ada_Un_Op | Ada_Bin_Op | Ada_Concat_Op => + return False; + + when others => + return False; + end case; + end Is_Call_Leaf; + + --------------- + -- Full_Call -- + --------------- + + function Full_Call (Node : Ada_Node'Class) return Ada_Node + is + Call : Ada_Node; + begin + -- Ensure Node is the inner-most node identifying a call. + + pragma Assert (Is_Call_Leaf (Node)); + + Call := Node.As_Ada_Node; + + if Call.Parent.Kind = Ada_Dotted_Name then + Call := Call.Parent; + end if; + + if Call.Parent.Kind = Ada_Call_Expr then + Call := Call.Parent; + end if; + + return Call; + end Full_Call; + + ------------------------------------ + -- Fill_Expression_Insertion_Info -- + ------------------------------------ + + procedure Fill_Expression_Insertion_Info + (UIC : in out Ada_Unit_Inst_Context; + Bit : Any_Bit_Id; + Insert_Info : out Insertion_Info) + is + Formal_Name : constant Node_Rewriting_Handle := + Make_Identifier (UIC, "Dummy_Witness_Result"); + Formal_Def_Id : constant Node_Rewriting_Handle := + Create_Regular_Node + (UIC.Rewriting_Context, + Ada_Defining_Name_List, + Children => + (1 => Create_Defining_Name (UIC.Rewriting_Context, Formal_Name))); + begin + -- Create both the witness call and a formal parameter to + -- accept it as an actual. + + Insert_Info.Witness_Actual := Make_Statement_Witness + (UIC, + Bit => Bit, + Flavor => Function_Call, + In_Generic => UIC.In_Generic, + In_Decl_Expr => UIC.In_Decl_Expr); + + Insert_Info.Witness_Formal := Create_Param_Spec + (UIC.Rewriting_Context, + F_Ids => Formal_Def_Id, + F_Has_Aliased => No_Node_Rewriting_Handle, + F_Mode => No_Node_Rewriting_Handle, + F_Type_Expr => Make_Std_Ref (UIC, "Boolean"), + F_Default_Expr => No_Node_Rewriting_Handle, + F_Aspects => No_Node_Rewriting_Handle); + + end Fill_Expression_Insertion_Info; + ------------------------- -- Is_Logical_Operator -- ------------------------- @@ -6831,9 +7569,9 @@ package body Instrument.Ada_Unit is function Is_Ghost (UIC : Ada_Unit_Inst_Context; - EF : Expr_Function) return Boolean + D : Basic_Decl) return Boolean is - Decl : Basic_Decl := EF.As_Basic_Decl; + Decl : Basic_Decl := D; begin -- We are looking for a Ghost aspect for the given expression function. -- If this expression function has a declaration, the aspect must be @@ -6844,7 +7582,7 @@ package body Instrument.Ada_Unit is exception when Exc : Property_Error => Report - (UIC, EF, + (UIC, Decl, "Failed to look for a previous declaration of this expression" & " function" & Ada.Exceptions.Exception_Information (Exc), Warning); diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 32a0ad41d..2c4e6083d 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -283,7 +283,9 @@ package body Instrument.Common is when Statement => Set_Stmt_SCO_Non_Instr (Remapped_SCO); when Decision => Set_Decision_SCO_Non_Instr (Remapped_SCO); when Condition => Set_Decision_SCO_Non_Instr_For_MCDC - (Enclosing_Decision (Remapped_SCO)); + (Enclosing_Decision (Remapped_SCO)); + when Fun_Call_SCO_Kind => + Set_Fun_Call_SCO_Non_Instr (Remapped_SCO); when others => null; end case; @@ -334,7 +336,7 @@ package body Instrument.Common is SCOs.SCO_Table.Append ((From => - (Logical_Line_Number (From.Line), Column_Number (From.Column)), + (Logical_Line_Number (From.Line), Column_Number (From.Column)), To => (Logical_Line_Number (To.Line), Column_Number (To.Column)), C1 => C1, diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index f95b53008..93e6348bf 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -1406,6 +1406,7 @@ begin Instrument_Main_Args : String_Vectors.Vector; Main_Filename : Unbounded_String; + -- Fullname for the main. It can either be an instrumented version of -- the main (if it also was instrumented as a source), or the original -- version. diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 1ca2a8c02..19f354285 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -70,9 +70,9 @@ package body SC_Obligations is -- Return whether SCO is covered by SE's SCO range function Covers_SCO - (ST : Scope_Traversal_Type; SCO : SCO_Id) return Boolean - is (Covers_SCO (Scope_Entities_Trees.Element (ST.Cur), SCO)); - -- Return whether SCO is covered by that element's SCO range + (ST : Scope_Traversal_Type; SCO : SCO_Id) return Boolean; + -- Return whether SCO is covered by that element's SCO range. Id the SCO is + -- a function SCO, then the scope can be the root of the tree. --------------- -- Instances -- @@ -473,14 +473,20 @@ package body SC_Obligations is Op_Kind : Operator_Kind; -- Kind of operation this node represents + + when Fun_Call_SCO_Kind => + Is_Expr : Boolean := False; + -- Set to true if it is a call and an expression + + Fun_Call_Instrumented : Boolean := True; + -- Whether this function or call SCO was instrumented end case; end case; end record; Removed_SCO_Descriptor : constant SCO_Descriptor := (Kind => Removed); - package SCO_Vectors is - new Ada.Containers.Vectors + package SCO_Vectors is new Ada.Containers.Vectors (Index_Type => Valid_SCO_Id, Element_Type => SCO_Descriptor); @@ -906,9 +912,16 @@ package body SC_Obligations is ST.Cur := Parent (ST.Cur); -- If we reach the root of the tree, this means this SCO is not in - -- any scope, which is clearly a bug. + -- any scope, which is clearly a bug. Unless this is a function SCO + -- which can be at the root of the tree. - pragma Assert (not Is_Root (ST.Cur)); + declare + SCOD : SCO_Descriptor renames SCO_Vector (SCO); + begin + if SCOD.Kind /= Fun then + pragma Assert (not Is_Root (ST.Cur)); + end if; + end; end loop; -- Descend into the tree until we are on a leaf, or no child of the @@ -1259,6 +1272,10 @@ package body SC_Obligations is SCOD.Operands (Right) := CLS.Read_SCO; end; SCOD.Op_Kind := Operator_Kind'Val (CLS.Read_U8); + + when Fun_Call_SCO_Kind => + SCOD.Is_Expr := CLS.Read_Boolean; + SCOD.Fun_Call_Instrumented := CLS.Read_Boolean; end case; Element := SCOD; @@ -1339,6 +1356,11 @@ package body SC_Obligations is SCOD.Decision_Instrumented_For_MCDC := True; end if; + when Fun_Call_SCO_Kind => + if Old_SCOD.Fun_Call_Instrumented then + SCOD.Fun_Call_Instrumented := True; + end if; + when others => null; end case; @@ -1613,6 +1635,9 @@ package body SC_Obligations is New_SCOD.PC_Set.Clear; + when Fun_Call_SCO_Kind => + null; + end case; -- Append new SCOD and record mapping @@ -1734,7 +1759,7 @@ package body SC_Obligations is declare SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); begin - if SCOD.Kind in Statement | Decision then + if SCOD.Kind in Statement | Decision | Fun_Call_SCO_Kind then Add_SCO_To_Lines (SCO, SCOD); end if; end; @@ -2038,6 +2063,10 @@ package body SC_Obligations is CSS.Write_SCO (Value.Operands (Left)); CSS.Write_SCO (Value.Operands (Right)); CSS.Write_U8 (Operator_Kind'Pos (Value.Op_Kind)); + + when Fun_Call_SCO_Kind => + CSS.Write (Value.Is_Expr); + CSS.Write (Value.Fun_Call_Instrumented); end case; end Write; @@ -2552,7 +2581,16 @@ package body SC_Obligations is L : Local_Source_Location_Range renames Left.Sloc_Range.L; R : Local_Source_Location_Range renames Right.Sloc_Range.L; begin - return L.First_Sloc < R.First_Sloc and then R.Last_Sloc < L.Last_Sloc; + -- For call coverage, we allow Left and Right to share their First_Sloc + -- as for a call statement the statement SCO will be on the whole + -- statement, and the call SCO will start at the beginning of the + -- statement and end before the semi-colon marking its end. + -- For any other SCOs, neither the first nor the last location have a + -- reason to be shared. + return + (if Left.Kind = Call and then Right.Kind = Call + then L.First_Sloc <= R.First_Sloc and then R.Last_Sloc < L.Last_Sloc + else L.First_Sloc < R.First_Sloc and then R.Last_Sloc < L.Last_Sloc); end Nested; --------------------- @@ -2863,6 +2901,16 @@ package body SC_Obligations is SCOD.Decision_Instrumented_For_MCDC := False; end Set_Decision_SCO_Non_Instr_For_MCDC; + ---------------------------- + -- Set_Call_SCO_Non_Instr -- + ---------------------------- + + procedure Set_Fun_Call_SCO_Non_Instr (SCO : SCO_Id) is + SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); + begin + SCOD.Fun_Call_Instrumented := False; + end Set_Fun_Call_SCO_Non_Instr; + --------------------------- -- Stmt_SCO_Instrumented -- --------------------------- @@ -2885,6 +2933,13 @@ package body SC_Obligations is (SCO : SCO_Id) return Boolean is (SCO_Vector (SCO).Decision_Instrumented_For_MCDC); + ------------------------------- + -- Fun_Call_SCO_Instrumented -- + ------------------------------- + + function Fun_Call_SCO_Instrumented (SCO : SCO_Id) return Boolean is + (SCO_Vector (SCO).Fun_Call_Instrumented); + ----------- -- Image -- ----------- @@ -3274,6 +3329,17 @@ package body SC_Obligations is return False; end Is_Quantified_Expression; + ------------------ + -- Is_Call_Stmt -- + ------------------ + + function Is_Call_Stmt (SCO : SCO_Id) return Boolean + is + SCOD : constant SCO_Descriptor := SCO_Vector.Reference (SCO); + begin + return Kind (SCO) = Call and then not SCOD.Is_Expr; + end Is_Call_Stmt; + ---------------------------------- -- Is_Pragma_Pre_Post_Condition -- ---------------------------------- @@ -3981,22 +4047,43 @@ package body SC_Obligations is end case; end if; - when 'S' | 's' => + when 'S' | 's' | 'C' | 'c' => pragma Assert (State.Current_Decision = No_SCO_Id); - New_SCO := Add_SCO - (SCO_Descriptor' - (Kind => Statement, - Origin => CU, - Sloc_Range => SCO_Range, - S_Kind => To_Statement_Kind (SCOE.C2), - Dominant => State.Dom_SCO, - Dominant_Sloc => State.Dom_Sloc, - Dominant_Value => State.Dom_Val, - Handler_Range => State.Current_Handler_Range, - Pragma_Name => Case_Insensitive_Get_Pragma_Id - (SCOE.Pragma_Aspect_Name), - others => <>)); + if SCOE.C1 = 'c' then + + if SCOE.C2 = 'F' then + New_SCO := Add_SCO + (SCO_Descriptor' + (Kind => Fun, + Origin => CU, + Sloc_Range => SCO_Range, + Is_Expr => False, + others => <>)); + else + New_SCO := Add_SCO + (SCO_Descriptor' + (Kind => Call, + Origin => CU, + Sloc_Range => SCO_Range, + Is_Expr => SCOE.C2 = 'E', + others => <>)); + end if; + else + New_SCO := Add_SCO + (SCO_Descriptor' + (Kind => Statement, + Origin => CU, + Sloc_Range => SCO_Range, + S_Kind => To_Statement_Kind (SCOE.C2), + Dominant => State.Dom_SCO, + Dominant_Sloc => State.Dom_Sloc, + Dominant_Value => State.Dom_Val, + Handler_Range => State.Current_Handler_Range, + Pragma_Name => Case_Insensitive_Get_Pragma_Id + (SCOE.Pragma_Aspect_Name), + others => <>)); + end if; State.Current_Handler_Range := No_Range; State.Dom_Val := Unknown; @@ -4259,7 +4346,12 @@ package body SC_Obligations is (L.D_Kind = R.D_Kind and then L.Control_Location = R.Control_Location), when Operator => - L.Op_Kind = R.Op_Kind); + L.Op_Kind = R.Op_Kind, + when Fun => + True, + when Call => + L.Is_Expr = R.Is_Expr + ); end Equivalent; ------------------------ @@ -4340,6 +4432,10 @@ package body SC_Obligations is null; + when Fun_Call_SCO_Kind => + SCOD.Parent := Enclosing_SCO; + Add_SCO_To_Lines (SCO, SCOD); + end case; declare @@ -5051,6 +5147,17 @@ package body SC_Obligations is return False; end SCOs_Nested_And_Ordered; + ---------------- + -- Covers_SCO -- + ---------------- + + function Covers_SCO + (ST : Scope_Traversal_Type; SCO : SCO_Id) return Boolean + is + ((SCO_Vector (SCO).Kind = Fun + and then Scope_Entities_Trees.Is_Root (ST.Cur)) + or else Covers_SCO (Scope_Entities_Trees.Element (ST.Cur), SCO)); + ------------------------ -- Set_Scope_Entities -- ------------------------ @@ -5976,6 +6083,8 @@ package body SC_Obligations is when 'r' => return Renaming_Declaration; when 'i' => return Generic_Instantiation; when 'd' => return Other_Declaration; + when 'c' => return Call_Stmt; + when 'e' => return Call_Expr; when 'A' => return Accept_Statement; when 'C' => return Case_Statement; when 'E' => return Exit_Statement; diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 3868829a3..b36808daa 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -245,7 +245,7 @@ package SC_Obligations is -- Source Coverage Obligations -- --------------------------------- - -- One one side, gnatutil's scos.ads defines data structures for low level + -- On one side, gnatutil's scos.ads defines data structures for low level -- SCO tables: this is SCO_Unit_Table and SCO_Table from the SCOs unit, -- i.e. tables to hold the parsing of SCOs from LI files or SCOs that the -- source instrumenter creates; @@ -379,12 +379,15 @@ package SC_Obligations is Sloc => No_Local_Location, Identifier => No_Scope_Entity_Identifier); - type Any_SCO_Kind is (Removed, Statement, Decision, Condition, Operator); - subtype SCO_Kind is Any_SCO_Kind range Statement .. Operator; + type Any_SCO_Kind is + (Removed, Statement, Decision, Condition, Operator, Fun, Call); + subtype SCO_Kind is Any_SCO_Kind range Statement .. Call; -- Removed is used for SCOs coming from C code in static inline functions -- present in headers. These SCOs can appear duplicated in multiple -- compilation units and we replace all but one of the duplicated entries -- with a Removed one. + subtype Fun_Call_SCO_Kind is Any_SCO_Kind range Fun .. Call; + -- The three types of SCO that are needed for function and call coverage procedure Add_Address (SCO : SCO_Id; Address : Pc_Type); -- Record Address in SCO's address list @@ -568,6 +571,8 @@ package SC_Obligations is Select_Statement, While_Loop_Statement, Degenerate_Subprogram_Statement, + Call_Stmt, + Call_Expr, Other_Statement); subtype Statement_Kind is Any_Statement_Kind @@ -618,6 +623,10 @@ package SC_Obligations is Pre => Kind (SCO) = Decision; -- Mark this decision SCO as non-instrumented for MCDC coverage + procedure Set_Fun_Call_SCO_Non_Instr (SCO : SCO_Id) with + Pre => Kind (SCO) in Fun_Call_SCO_Kind; + -- FIXME + function Stmt_SCO_Instrumented (SCO : SCO_Id) return Boolean with Pre => Kind (SCO) = Statement; -- Whether this statment SCO was instrumented @@ -631,6 +640,10 @@ package SC_Obligations is Pre => Kind (SCO) = Decision; -- Whether this decision SCO was instrumented for MCDC coverage + function Fun_Call_SCO_Instrumented (SCO : SCO_Id) return Boolean with + Pre => Kind (SCO) in Fun_Call_SCO_Kind; + -- Whether this function or call SCO was instrumented + function Is_Pragma_Pre_Post_Condition (SCO : SCO_Id) return Boolean; -- True if SCO is for a pragma Pre/Postcondition @@ -727,6 +740,9 @@ package SC_Obligations is function Is_Quantified_Expression (SCO : SCO_Id) return Boolean; -- True if SCO is a condition that is a quantified expression + function Is_Call_Stmt (SCO : SCO_Id) return Boolean; + -- True is SCO is a call statement + function Path_Count (SCO : SCO_Id) return Natural; -- Return count of paths through decision's BDD from root condition to -- any outcome. This should be a positive number for any decision From 2ed19c9f181d57a3fb3ae437dbfafdcd7cf5151f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 21 Aug 2024 18:07:53 +0200 Subject: [PATCH 0902/1483] Add tests for function and call coverage And adapt the testsuite to check new function and call coverage level --- testsuite/.gitignore | 1 + testsuite/SCOV/internals/cnotes.py | 20 +++- testsuite/SCOV/internals/driver.py | 73 +++++++++--- testsuite/SCOV/internals/rnexpanders.py | 16 ++- testsuite/SCOV/internals/xnexpanders.py | 23 ++-- testsuite/SCOV/internals/xnotep.py | 8 ++ testsuite/SCOV/tc.py | 9 +- .../access_to_subp/src/access_to_subp.adb | 33 ++++++ .../access_to_subp/src/test_called.adb | 16 +++ .../access_to_subp/src/test_not_called.adb | 17 +++ .../access_to_subp/test.py | 7 ++ .../dotted_name/src/call.adb | 13 +++ .../dotted_name/src/pkg.adb | 17 +++ .../dotted_name/src/pkg.ads | 11 ++ .../dotted_name/src/test_dotted.adb | 17 +++ .../287-function_call_cov/dotted_name/test.py | 6 + .../dotted_type/src/make_call.adb | 52 +++++++++ .../dotted_type/src/pkg4.ads | 5 + .../dotted_type/src/pkg5.ads | 7 ++ .../dotted_type/src/test_dotted_type.adb | 30 +++++ .../287-function_call_cov/dotted_type/test.py | 11 ++ .../src/make_call.adb | 32 +++++ .../dotted_type_not_imported/src/pkg.adb | 9 ++ .../dotted_type_not_imported/src/pkg.ads | 18 +++ .../src/test_dotted_type_not_imported.adb | 34 ++++++ .../tests/287-function_call_cov/extra.opt | 3 + .../generics/src/in_proc_decls.adb | 59 ++++++++++ .../src/test_in_proc_decls_called.adb | 19 +++ .../src/test_in_proc_decls_not_called.adb | 21 ++++ .../287-function_call_cov/generics/test.py | 14 +++ .../import_call/src/add.c | 5 + .../import_call/src/call_add.adb | 24 ++++ .../import_call/src/test_import_called.adb | 17 +++ .../src/test_import_not_called.adb | 17 +++ .../287-function_call_cov/import_call/test.py | 7 ++ .../nested_calls/src/nested.adb | 32 +++++ .../nested_calls/src/test_nested.adb | 18 +++ .../nested_calls/test.py | 7 ++ .../null_procedures/src/pkg.adb | 4 + .../null_procedures/src/pkg.ads | 5 + .../null_procedures/src/test_called.adb | 13 +++ .../null_procedures/src/test_not_called.adb | 11 ++ .../null_procedures/test.py | 7 ++ .../protected_body/src/foo.adb | 26 +++++ .../protected_body/src/foo.ads | 15 +++ .../protected_body/src/test_called.adb | 26 +++++ .../protected_body/src/test_not_called.adb | 20 ++++ .../protected_body/test.py | 7 ++ .../subp_kinds/src/no_decls_called.adb | 109 ++++++++++++++++++ .../subp_kinds/src/no_decls_not_called.adb | 57 +++++++++ .../subp_kinds/src/test_no_decls_called.adb | 22 ++++ .../src/test_no_decls_not_called.adb | 16 +++ .../287-function_call_cov/subp_kinds/test.py | 7 ++ .../src/call_with_decls.adb | 61 ++++++++++ .../src/test_with_decls_called.adb | 24 ++++ .../src/test_with_decls_not_called.adb | 16 +++ .../subp_kinds_with_decls/src/with_decls.adb | 53 +++++++++ .../subp_kinds_with_decls/src/with_decls.ads | 25 ++++ .../subp_kinds_with_decls/test.py | 7 ++ 59 files changed, 1229 insertions(+), 30 deletions(-) create mode 100644 testsuite/tests/287-function_call_cov/access_to_subp/src/access_to_subp.adb create mode 100644 testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb create mode 100644 testsuite/tests/287-function_call_cov/access_to_subp/src/test_not_called.adb create mode 100644 testsuite/tests/287-function_call_cov/access_to_subp/test.py create mode 100644 testsuite/tests/287-function_call_cov/dotted_name/src/call.adb create mode 100644 testsuite/tests/287-function_call_cov/dotted_name/src/pkg.adb create mode 100644 testsuite/tests/287-function_call_cov/dotted_name/src/pkg.ads create mode 100644 testsuite/tests/287-function_call_cov/dotted_name/src/test_dotted.adb create mode 100644 testsuite/tests/287-function_call_cov/dotted_name/test.py create mode 100644 testsuite/tests/287-function_call_cov/dotted_type/src/make_call.adb create mode 100644 testsuite/tests/287-function_call_cov/dotted_type/src/pkg4.ads create mode 100644 testsuite/tests/287-function_call_cov/dotted_type/src/pkg5.ads create mode 100644 testsuite/tests/287-function_call_cov/dotted_type/src/test_dotted_type.adb create mode 100644 testsuite/tests/287-function_call_cov/dotted_type/test.py create mode 100644 testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/make_call.adb create mode 100644 testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.adb create mode 100644 testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.ads create mode 100644 testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/test_dotted_type_not_imported.adb create mode 100644 testsuite/tests/287-function_call_cov/extra.opt create mode 100644 testsuite/tests/287-function_call_cov/generics/src/in_proc_decls.adb create mode 100644 testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_called.adb create mode 100644 testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_not_called.adb create mode 100644 testsuite/tests/287-function_call_cov/generics/test.py create mode 100644 testsuite/tests/287-function_call_cov/import_call/src/add.c create mode 100644 testsuite/tests/287-function_call_cov/import_call/src/call_add.adb create mode 100644 testsuite/tests/287-function_call_cov/import_call/src/test_import_called.adb create mode 100644 testsuite/tests/287-function_call_cov/import_call/src/test_import_not_called.adb create mode 100644 testsuite/tests/287-function_call_cov/import_call/test.py create mode 100644 testsuite/tests/287-function_call_cov/nested_calls/src/nested.adb create mode 100644 testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb create mode 100644 testsuite/tests/287-function_call_cov/nested_calls/test.py create mode 100644 testsuite/tests/287-function_call_cov/null_procedures/src/pkg.adb create mode 100644 testsuite/tests/287-function_call_cov/null_procedures/src/pkg.ads create mode 100644 testsuite/tests/287-function_call_cov/null_procedures/src/test_called.adb create mode 100644 testsuite/tests/287-function_call_cov/null_procedures/src/test_not_called.adb create mode 100644 testsuite/tests/287-function_call_cov/null_procedures/test.py create mode 100644 testsuite/tests/287-function_call_cov/protected_body/src/foo.adb create mode 100644 testsuite/tests/287-function_call_cov/protected_body/src/foo.ads create mode 100644 testsuite/tests/287-function_call_cov/protected_body/src/test_called.adb create mode 100644 testsuite/tests/287-function_call_cov/protected_body/src/test_not_called.adb create mode 100644 testsuite/tests/287-function_call_cov/protected_body/test.py create mode 100644 testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_called.adb create mode 100644 testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_not_called.adb create mode 100644 testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_called.adb create mode 100644 testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_not_called.adb create mode 100644 testsuite/tests/287-function_call_cov/subp_kinds/test.py create mode 100644 testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/call_with_decls.adb create mode 100644 testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_called.adb create mode 100644 testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_not_called.adb create mode 100644 testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.adb create mode 100644 testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.ads create mode 100644 testsuite/tests/287-function_call_cov/subp_kinds_with_decls/test.py diff --git a/testsuite/.gitignore b/testsuite/.gitignore index d5f9a3008..37d8630f9 100644 --- a/testsuite/.gitignore +++ b/testsuite/.gitignore @@ -4,6 +4,7 @@ datcc_* m_* s_* u_* +*fc_*/ tmp_* tmp bin diff --git a/testsuite/SCOV/internals/cnotes.py b/testsuite/SCOV/internals/cnotes.py index be445cfde..ec7ae1a86 100644 --- a/testsuite/SCOV/internals/cnotes.py +++ b/testsuite/SCOV/internals/cnotes.py @@ -132,6 +132,11 @@ # acPartCov : assertion condition was never evaluated during an evaluation of # the decision to True (=report) +# fNoCov : subprogram never entered (=report) +# cNoCov : call statement or expression never evaluated (=report) +# fUndetCov : subprogram with undetermined coverage state (=report) +# cUndetCov : call with undetermined coverage state (=report) + # xBlock0 : exempted block, 0 deviations (=report) # xBlock1 : exempted block, >0 deviations (=report) # xBlock2 : exempted block, >0 undetermined coverage items (=report) @@ -213,12 +218,16 @@ aNoCov, atNoCov, acPartCov, + fNoCov, + cNoCov, + fUndetCov, + cUndetCov, blockNote, xBlock0, xBlock1, xBlock2, dBlock, -) = range(56) +) = range(60) NK_image = { None: "None", @@ -274,6 +283,10 @@ aNoCov: "aNoCov", atNoCov: "atNoCov", acPartCov: "acPartCov", + fNoCov: "fNoCov", + cNoCov: "cNoCov", + fUndetCov: "fUndetCov", + cUndetCov: "cUndetCov", dBlock: "dBlock", } @@ -326,6 +339,9 @@ # Assertion violations aNoteKinds = (aNoCov, atNoCov, acPartCov) +# Function and call coverage violations +fNoteKinds = (fNoCov, cNoCov, fUndetCov, cUndetCov) + # Exemption regions xNoteKinds = (xBlock0, xBlock1, xBlock2) @@ -363,7 +379,7 @@ + XNoteKinds + disabledNoteKinds ) -erNoteKinds += aNoteKinds +erNoteKinds += aNoteKinds + fNoteKinds xrNoteKinds = erNoteKinds + rAntiKinds + XrAntiKinds diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 42b5eb415..4651678ad 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -38,7 +38,7 @@ from SUITE.context import thistest from SUITE.control import language_info, runtime_info -from SUITE.cutils import ext, to_list, list_to_file, no_ext +from SUITE.cutils import ext, to_list, list_to_file, no_ext, FatalError from SUITE.cutils import contents_of, lines_of, unhandled_exception_in from SUITE.gprutils import GPRswitches from SUITE.tutils import gprbuild, gprfor, xrun, xcov, frame @@ -55,7 +55,14 @@ from .cnotes import r0, r0c, xBlock0, xBlock1, lx0, lx1, lFullCov, lPartCov from .cnotes import Xr0, Xr0c from .cnotes import KnoteDict, elNoteKinds, erNoteKinds, rAntiKinds -from .cnotes import xNoteKinds, sNoteKinds, dNoteKinds, cNoteKinds, tNoteKinds +from .cnotes import ( + xNoteKinds, + sNoteKinds, + dNoteKinds, + cNoteKinds, + tNoteKinds, + fNoteKinds, +) from .cnotes import XsNoteKinds, XoNoteKinds, XcNoteKinds from .cnotes import strict_p, deviation_p, anti_p, positive_p @@ -257,10 +264,15 @@ def __discharges(self, en, xn): # The emitted note needs to designate a sloc range within the # expected sloc range and separation tags, when any is expected, # must match. - return en.segment.within(xn.segment) and ( - (not xn.stag and not en.stag) - or (xn.stag and en.stag and en.stag.match(xn.stag)) - ) + a = en.segment.within(xn.segment) + b = not xn.stag and not en.stag + c = xn.stag and en.stag + d = c and en.stag.match(xn.stag) + return a and (b or d) + # return en.segment.within(xn.segment) and ( + # (not xn.stag and not en.stag) + # or (xn.stag and en.stag and en.stag.match(xn.stag)) + # ) def try_sat_over(self, ekind, xn): # See if expected note XN is satisfied by one of the emitted notes of @@ -994,6 +1006,17 @@ def check_expectations(self): "stmt+mcdc+atcc": 3, "stmt+uc_mcdc+atc": 3, "stmt+uc_mcdc+atcc": 3, + "stmt+fun_call": 1, + "stmt+decision+fun_call": 2, + "stmt+mcdc+fun_call": 3, + "stmt+uc_mcdc+fun_call": 3, + "stmt+atc+fun_call": 1, + "stmt+decision+atc+fun_call": 2, + "stmt+decision+atcc+fun_call": 2, + "stmt+mcdc+atc+fun_call": 3, + "stmt+mcdc+atcc+fun_call": 3, + "stmt+uc_mcdc+atc+fun_call": 3, + "stmt+uc_mcdc+atcc+fun_call": 3, } stricter_level = ( @@ -1005,16 +1028,20 @@ def check_expectations(self): # kinds from the strictest category possibly corresponding to the # xcov-level. - strictest_cat_for = { - "stmt": CAT.stmt, - "stmt+decision": CAT.decision, - "stmt+mcdc": CAT.mcdc, - } + def strictest_cat_for(level: str): + if level.startswith("stmt+mcdc"): + return CAT.mcdc + elif level.startswith("stmt+decision"): + return CAT.decision + elif level.startswith("stmt"): + return CAT.stmt + else: + thistest.stop(FatalError("unknwon coverage level: " + level)) relevance_cat = ( self.testcase.category if self.testcase.category - else strictest_cat_for[self.xcovlevel] + else strictest_cat_for(self.xcovlevel) ) # Setup our report and line discharging configurations (kinds of @@ -1095,13 +1122,25 @@ def check_expectations_over( # Report notes checks + # Augment the set of recognized deviations based on the additional + # level(s) that are enabled. + # + # TODO: Also augment the expected notes for assertion coverage, the + # testsuite currently does not work for those levels? + + tc_r_rxp_for = r_rxp_for[relevance_cat] + tc_r_ern_for = r_ern_for[relevance_cat] + + if self.testcase.fun_call_lvl: + tc_r_rxp_for += fNoteKinds + tc_r_ern_for += fNoteKinds strans = self.report_translation_for(source) _Xchecker( report="test.rep", xdict=self.xrnotes.get(source), - rxp=r_rxp_for[relevance_cat], + rxp=tc_r_rxp_for, edict=self.ernotes.get(strans, KnoteDict(erNoteKinds)), - ren=r_ern_for[relevance_cat], + ren=tc_r_ern_for, ).run(r_discharge_kdict) # Line notes checks, meaningless if we're in qualification mode @@ -1254,7 +1293,8 @@ def wdbase_for(self, covlevel): Uses the first letter of the highest level ('s' for "stmt" or 'u' for "stmt+uc_mcdc") and the full name of the assertion level if assertion - coverage is enabled. + coverage is enabled. If function and call coverage is needed, append + "fc". """ levels = covlevel.split("+") @@ -1262,7 +1302,8 @@ def wdbase_for(self, covlevel): return "s_" wdbase = levels[1][0] - wdbase += levels[-1] if self.assert_lvl else "" + wdbase += levels[-2] if self.assert_lvl else "" + wdbase += "fc" if self.fun_call_lvl else "" return wdbase + "_" diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index afa42f177..cff0415c0 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -29,6 +29,10 @@ aNoCov, atNoCov, acPartCov, + fNoCov, + cNoCov, + fUndetCov, + cUndetCov, Enote, KnoteDict, erNoteKinds, @@ -677,6 +681,14 @@ def __init__(self): VIOsection(re_start="ATCC COVERAGE", re_notes=atcc_notes) ) + fun_call_notes = { + "function not executed": fNoCov, + "call not executed": cNoCov, + } + self.noteblocks.append( + VIOsection(re_start="FUN_CALL COVERAGE", re_notes=fun_call_notes) + ) + # Non coverable items nc_notes = { @@ -695,7 +707,9 @@ def __init__(self): "statement was not instrumented": sUndetCov, "decision was not instrumented" " for decision coverage": dUndetCov, - "decision was not instrumented" " for MC/DC coverage": eUndetCov, + "decision was not instrumented for MC/DC coverage": eUndetCov, + "function was not instrumented": fUndetCov, + "call was not instrumented": cUndetCov, } self.noteblocks.append( diff --git a/testsuite/SCOV/internals/xnexpanders.py b/testsuite/SCOV/internals/xnexpanders.py index 33eb450fb..73f91dfe6 100644 --- a/testsuite/SCOV/internals/xnexpanders.py +++ b/testsuite/SCOV/internals/xnexpanders.py @@ -1234,24 +1234,27 @@ def __decode_note_choice(self, text): "u": ["stmt+uc_mcdc"], } - def make_assert_lvl_combinaison(assert_lvl): + def make_new_lvl_combinaison(lvl): """ - Add the assertion coverage level assert_lvl to other regular - coverage level combinaisons defined in level_from_char. Return the - list of combinaisons. + Add the coverage level lvl to other regular coverage level + combinaisons defined in level_from_char. Return the list of + combinaisons. """ - return [ - level_from_char[c][0] + "+" + assert_lvl - for c in level_from_char - ] + return [level_from_char[c][0] + "+" + lvl for c in level_from_char] assert_level_from_char = { - "a": make_assert_lvl_combinaison("atc"), - "c": make_assert_lvl_combinaison("atcc"), + "a": make_new_lvl_combinaison("atc"), + "c": make_new_lvl_combinaison("atcc"), } level_from_char.update(assert_level_from_char) + fun_call_level_from_char = { + "f": make_new_lvl_combinaison("fun_call"), + } + + level_from_char.update(fun_call_level_from_char) + result = text.split("=>") if len(result) == 1: diff --git a/testsuite/SCOV/internals/xnotep.py b/testsuite/SCOV/internals/xnotep.py index 8b8cf3ec7..f68d80bde 100644 --- a/testsuite/SCOV/internals/xnotep.py +++ b/testsuite/SCOV/internals/xnotep.py @@ -68,6 +68,10 @@ aNoCov, atNoCov, acPartCov, + fNoCov, + cNoCov, + fUndetCov, + cUndetCov, dBlock, ) from .segments import Line, Section, Segment @@ -263,6 +267,10 @@ class XnoteP: "a-": aNoCov, "aT-": atNoCov, "ac!": acPartCov, + "f-": fNoCov, + "c-": cNoCov, + "f?": fUndetCov, + "c?": cUndetCov, "x0": xBlock0, "x+": xBlock1, "x?": xBlock2, diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index 735f5d748..7bbb1164f 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -137,6 +137,7 @@ def __init__( category=CAT.auto, tolerate_messages=None, assert_lvl=None, + fun_call_lvl=False, ): # By default, these test cases expect no error from subprocesses (xrun, # xcov, etc.) @@ -188,6 +189,7 @@ def __init__( ) self.assert_lvl = assert_lvl + self.fun_call_lvl = fun_call_lvl # - extra compilation arguments, added to what --cargs was provided to # the testsuite command line: @@ -225,7 +227,12 @@ def __xcovlevels(self): # passed to gnatcov. alvl = ("+" + self.assert_lvl) if self.assert_lvl else "" - return [d + alvl for d in default_xcovlevels_for[self.category]] + # Append "+fun_call" to activate function and call coverage if needed + fclvl = "+fun_call" if self.fun_call_lvl else "" + + return [ + d + alvl + fclvl for d in default_xcovlevels_for[self.category] + ] def __register_qde_for(self, drvo): """ diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/src/access_to_subp.adb b/testsuite/tests/287-function_call_cov/access_to_subp/src/access_to_subp.adb new file mode 100644 index 000000000..7f3da15c1 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/access_to_subp/src/access_to_subp.adb @@ -0,0 +1,33 @@ +pragma Ada_2012; + +procedure Access_To_Subp -- # fun +is + type Point is record -- # decl + X, Y : Float; -- # dstmt + end record; -- # dstmt + + function Set (X, Y : Float) return Point is (X, Y); -- # stmt + + function Reset (X, Y : Float) return Point is (0.0, 0.0); -- # stmt + + type Pt_Acc is access function (X, Y : Float) return Point; -- # decl + + function Run_Callback (Callback : Pt_Acc) return Point is -- # fun + begin + return Callback (1.0, 2.00); -- # call_1 + end; + + Set_Acc : constant Pt_Acc := Set'Access; -- # decl + Reset_Acc : constant Pt_Acc := Reset'Access; -- # decl + + Dispatch_Table : constant array (1 .. 2) of Pt_Acc := -- # decl + (Set_Acc, Reset_Acc); -- # dstmt + + -- LIMITATION: Selected component with a call expression for a prefix + -- F : Float := Run_Callback (Set_Acc).X; + P : Point := Run_Callback (Set_Acc); -- # call_2 +begin + P := Run_Callback (Set_Acc); -- # call_3 + P := Set_Acc.all (1.0, 2.0); -- # call_4 + P := Dispatch_Table (2) (1.0, 3.0); -- # call_5 +end Access_To_Subp; diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb new file mode 100644 index 000000000..8b2c3db43 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb @@ -0,0 +1,16 @@ +with Access_To_Subp; + +-- Check function and call coverage for an acces to a subprogram. +-- Here, all calls and functions are executed. + +procedure Test_Not_Called is +begin + Access_To_Subp; +end; + +--# access_to_subp.adb +-- /decl/ l+ ## 0 +-- /dstmt/ l+ ## 0 +-- /stmt/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /call/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/src/test_not_called.adb b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_not_called.adb new file mode 100644 index 000000000..a4c7d7833 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_not_called.adb @@ -0,0 +1,17 @@ +with Access_To_Subp; + +-- Check function and call coverage for an acces to a subprogram. +-- Here, no calls are made so expect function and call violation for all such +-- SCOs. + +procedure Test_Not_Called is +begin + null; +end; + +--# access_to_subp.adb +-- /decl/ l- ## s- +-- /dstmt/ l- ## 0 +-- /stmt/ l- ## s=><-, f=>s-,f- +-- /fun/ l- ## f- +-- /call/ l- ## s=>s-, f=>s-,c- diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/test.py b/testsuite/tests/287-function_call_cov/access_to_subp/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/access_to_subp/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/dotted_name/src/call.adb b/testsuite/tests/287-function_call_cov/dotted_name/src/call.adb new file mode 100644 index 000000000..7e5ce0608 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/src/call.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; + +With Pkg; + +procedure Call +is + Dummy : Integer := 8; -- #decl +begin + if Pkg.A.B.F then -- # if_cond + Pkg.A.B.P (Dummy); -- # v_call_stmt + Dummy := Pkg.A.B.P (2); -- # v_call_expr + end if; +end Call; diff --git a/testsuite/tests/287-function_call_cov/dotted_name/src/pkg.adb b/testsuite/tests/287-function_call_cov/dotted_name/src/pkg.adb new file mode 100644 index 000000000..800e12fea --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/src/pkg.adb @@ -0,0 +1,17 @@ +pragma Ada_2012; + +package body Pkg is + package body A is + package body B is + procedure P (X : out Integer) is -- # v_fun + begin + X := 42; -- # v_stmt + end P; + + function P (X : Integer) return Integer is -- # v_fun + begin + return 42; -- # v_stmt + end P; + end B; + end A; +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/dotted_name/src/pkg.ads b/testsuite/tests/287-function_call_cov/dotted_name/src/pkg.ads new file mode 100644 index 000000000..cce56f67d --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/src/pkg.ads @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package Pkg is + package A is + package B is + function F return Boolean is (False); -- # stmt + procedure P (X : out Integer); + function P (X : Integer) return Integer; + end B; + end A; +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/dotted_name/src/test_dotted.adb b/testsuite/tests/287-function_call_cov/dotted_name/src/test_dotted.adb new file mode 100644 index 000000000..35ce9e1d6 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/src/test_dotted.adb @@ -0,0 +1,17 @@ +with Call; + +procedure Test_Dotted is +begin + Call; +end Test_Dotted; + +--# call.adb +-- /decl/ l+ ## 0 +-- /if_cond/ sdf=>l! ## s=>0, d=>dT-, f=>dT- +-- /v_call_stmt/ l- ## s=>s-, f=>s-,c- +-- /v_call_expr/ sf=>l- ## s=>s-, f=>s-,c- +--# pkg.adb +-- /v_fun/ l- ## f- +-- /v_stmt/ l- ## s- +--# pkg.ads +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/dotted_name/test.py b/testsuite/tests/287-function_call_cov/dotted_name/test.py new file mode 100644 index 000000000..9d1fe305b --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/dotted_type/src/make_call.adb b/testsuite/tests/287-function_call_cov/dotted_type/src/make_call.adb new file mode 100644 index 000000000..d699a964a --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type/src/make_call.adb @@ -0,0 +1,52 @@ +pragma Ada_2012; + +with Pkg5; + +procedure Make_Call -- # fun +is + package Pkg1 is + + subtype T1 is Integer; -- # decl + type New_T1 is new Integer; -- # decl + + function F1 (X : T1) return T1 is (X); -- # fun + function New_F1 (X : New_T1) return New_T1 is (X); -- # fun + + package Pkg2 is + + subtype T2 is Boolean; -- # decl + + function F2 (X : T2) return T2 is (X); -- # fun + + package Pkg3 is + + subtype T3 is Float; -- # decl + + function F3 (X : T3) return T3 is (X); -- # fun + + end Pkg3; + end Pkg2; + end Pkg1; + + Dummy1 : Integer := Pkg1.F1 (8); -- # call + Dummy2 : Boolean := Pkg1.Pkg2.F2 (True); -- # call + Dummy3 : Float := Pkg1.Pkg2.Pkg3.F3 (0.0); -- # call + Dummy4 : Boolean := Pkg5.F.B; -- # dummy4 +begin + if -- # if + Pkg1.Pkg2.F2 -- # d_f2 + (Pkg1.F1 (42) -- # d_f1 + = 42 -- # deci + and then -- # deci + Pkg1.Pkg2.Pkg3.F3 (5.0) -- # d_f3 + = 5.0 -- # deci + and then -- # deci + Integer(Pkg1.New_F1 (0)) -- # d_nf1 + /= 0 -- # deci + and then -- # deci + Pkg5.F.B) -- # p_pkg5 + and then False -- # p_call + then + null; -- # null + end if; +end Make_Call; diff --git a/testsuite/tests/287-function_call_cov/dotted_type/src/pkg4.ads b/testsuite/tests/287-function_call_cov/dotted_type/src/pkg4.ads new file mode 100644 index 000000000..e0c721dc1 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type/src/pkg4.ads @@ -0,0 +1,5 @@ +package Pkg4 is + type T is record -- # decl + B : Boolean; -- # decl + end record; -- # decl +end Pkg4; diff --git a/testsuite/tests/287-function_call_cov/dotted_type/src/pkg5.ads b/testsuite/tests/287-function_call_cov/dotted_type/src/pkg5.ads new file mode 100644 index 000000000..c7c5d6ee6 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type/src/pkg5.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; + +with Pkg4; + +package Pkg5 is + function F return Pkg4.T is ((B => True)); -- # fun +end Pkg5; diff --git a/testsuite/tests/287-function_call_cov/dotted_type/src/test_dotted_type.adb b/testsuite/tests/287-function_call_cov/dotted_type/src/test_dotted_type.adb new file mode 100644 index 000000000..de40b6dd1 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type/src/test_dotted_type.adb @@ -0,0 +1,30 @@ +with Make_Call; + +-- Test function and call coverage on functions taking and returning types +-- with dotted names. + +procedure Test_Dotted_Type is +begin + Make_Call; +end Test_Dotted_Type; + +--# make_call.adb +-- /fun/ l+ ## 0 +-- /decl/ l+ ## 0 +-- /call/ l+ ## 0 +-- /dummy4/ l? ## c? +-- /if/ l+ ## 0 +-- /d_f2/ l+ ## 0 +-- /d_f1/ l! ## eT- +-- /d_call/ l! ## c- +-- /d_f3/ l! ## 0 +-- /d_nf1/ l! ## 0 +-- /deci/ l! ## 0 +-- /v_dec/ l- ## 0 +-- /p_call/ l! ## c- +-- /p_pkg5/ l! ## c? +-- /null/ l- ## s- +--# pkg4.ads +-- /decl/ l+ ## 0 +--# pkg5.ads +-- /fun/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/dotted_type/test.py b/testsuite/tests/287-function_call_cov/dotted_type/test.py new file mode 100644 index 000000000..cd617b2ad --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type/test.py @@ -0,0 +1,11 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase( + category=CAT.mcdc, + fun_call_lvl=True, + tolerate_messages=(r"cannot instrument calls within dotted names"), +).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/make_call.adb b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/make_call.adb new file mode 100644 index 000000000..ffbea1acb --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/make_call.adb @@ -0,0 +1,32 @@ +pragma Ada_2012; + +With Pkg; use Pkg; + +procedure Make_Call +is + Create_Acc : constant Pt_Acc := Create'Access; -- # decl + + A : Float := Run_Callback (Create_Acc) -- # A1 + .X; -- # A2 + + B : Float := Run_Callback (Create_Acc) -- # B1 + .Get_X; -- # B2 + + C : Point'Class := Id -- # C1 + (Run_Callback (Create_Acc)); -- # C2 + + D : Float := Id -- # D1 + (Run_Callback (Create_Acc) -- # D2 + .Get_X); -- # D3 + + E : Float := Id -- # E1 + (Run_Callback (Create_Acc)) -- # E2 + .Id -- # E3 + .Get_X; -- # E4 + + F : Float := Point'(1.0, 2.0) -- # F1 + .Id -- # F2 + .Get_X; -- # F3 +begin + null; -- # stmt +end Make_Call; diff --git a/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.adb b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.adb new file mode 100644 index 000000000..4d99b594b --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.adb @@ -0,0 +1,9 @@ +pragma Ada_2012; + +package body Pkg is + + function Run_Callback (Callback : Pt_Acc) return Point is -- # fun + begin + return Callback (1.0, 2.00); -- # call + end; +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.ads b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.ads new file mode 100644 index 000000000..c06cd1d5b --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/pkg.ads @@ -0,0 +1,18 @@ +pragma Ada_2012; + +package Pkg is + type Point is tagged record -- # decl + X, Y : Float; -- # dstmt + end record; -- # dstmt + + function Create (X, Y : Float) return Point is (X, Y); -- # expr_pri + + type Pt_Acc is access function (X, Y : Float) return Point; -- # decl + + function Run_Callback (Callback : Pt_Acc) return Point; + + function Id (P : Point) return Point'Class is (P); -- # expr_fun + function Id (F : Float) return Float is (F); -- # expr_fun + function Get_X (P : Point) return Float is (P.X); -- # expr_fun + +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/test_dotted_type_not_imported.adb b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/test_dotted_type_not_imported.adb new file mode 100644 index 000000000..9c3104605 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_type_not_imported/src/test_dotted_type_not_imported.adb @@ -0,0 +1,34 @@ +with Make_Call; + +procedure Test_Dotted_Type_Not_Imported is +begin + Make_Call; +end Test_Dotted_Type_Not_Imported; + +--#make_call.adb +-- /decl/ l+ ## 0 +-- /A1/ l! ## c? +-- /A2/ l+ ## 0 +-- /B1/ l! ## c? +-- /B2/ l+ ## 0 +-- /C1/ l+ ## 0 +-- /C2/ l+ ## 0 +-- /D1/ l+ ## 0 +-- /D2/ l! ## c? +-- /D3/ l+ ## 0 +-- /E1/ l! ## c? +-- /E2/ l! ## 0 +-- /E3/ l! ## c? +-- /E4/ l+ ## 0 +-- /F1/ l! ## c? +-- /F2/ l! ## c? +-- /F3/ l+ ## 0 +-- /stmt/ l+ ## 0 +--#pkg.ads +-- /expr_pri/ l- ## s?,f- +-- /decl/ l+ ## 0 +-- /dstmt/ l+ ## 0 +-- /expr_fun/ l+ ## 0 +--#pkg.adb +-- /fun/ l+ ## 0 +-- /call/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/extra.opt b/testsuite/tests/287-function_call_cov/extra.opt new file mode 100644 index 000000000..13f556330 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/extra.opt @@ -0,0 +1,3 @@ +bin-traces XFAIL Function and call coverage not supported for binary traces +5.04a1 DEAD Test contains expression functions and Ada_2012 features +7.1.2 DEAD Test contains expression functions and Ada_2012 features diff --git a/testsuite/tests/287-function_call_cov/generics/src/in_proc_decls.adb b/testsuite/tests/287-function_call_cov/generics/src/in_proc_decls.adb new file mode 100644 index 000000000..db36fc70c --- /dev/null +++ b/testsuite/tests/287-function_call_cov/generics/src/in_proc_decls.adb @@ -0,0 +1,59 @@ +pragma Ada_2012; + +procedure In_Proc_Decls -- # p +is + Dummy : Integer := 0; -- # decl + + -- Generic procedure + + generic + Type A is private; + procedure P1 (X : A); + + procedure P1 (X : A) is -- # fun + begin + Dummy := 1; -- # stmt + end P1; + + -- Generic null procedure + + generic + Type D is private; + procedure P2 (X : D); + + procedure P2 (X : D) is null; -- # null_fun + + -- Generic function + + generic + Type B is private; + function F1 (X : B) return B; + + function F1 (X : B) return B -- # fun + is + Dummy : B := X; -- # stmt + begin + return Dummy; -- # stmt + end F1; + + -- Generic expression function + + generic + Type C is private; + function F2 (X : C) return C; + + function F2 (X : C) return C is (X); -- # exp_fun + + -- Instanciations + -- LIMITATION : function coverage is currently not computed for + -- instanciations of generic subprograms + procedure Inst_P1 is new P1 (Integer); -- # stmt + procedure Inst_P2 is new P1 (Integer); -- # stmt + function Inst_F1 is new F1 (Integer); -- # stmt + function Inst_F2 is new F2 (Integer); -- # stmt +begin + Inst_P1 (42); -- # cstmt + Inst_P2 (42); -- # cstmt + Dummy := Inst_F1 (42); -- # cstmt + Dummy := Inst_F2 (42); -- # cstmt +end In_Proc_Decls; diff --git a/testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_called.adb b/testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_called.adb new file mode 100644 index 000000000..562f65e48 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_called.adb @@ -0,0 +1,19 @@ +with In_Proc_Decls; + +-- Check the coverage of a generic procedure, generic null procedure, generic +-- function and a generic expression function declared in a regular procedure +-- when called. We expect the generic subprograms to be covered. Currently, +-- the coverage of instanciations of generic subprograms is not computed. + +procedure Test_In_Proc_Decls_Called is +begin + In_Proc_Decls; +end Test_In_Proc_Decls_Called; + +--# in_proc_decls.adb +-- /p/ l+ ## 0 +-- /decl/ l+ ## 0 +-- /stmt/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /exp_fun/ l? ## s=>s?, f=>s?,f? +-- /null_fun/ l? ## s=>s?, f=>s?,f? diff --git a/testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_not_called.adb b/testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_not_called.adb new file mode 100644 index 000000000..484f5ebbb --- /dev/null +++ b/testsuite/tests/287-function_call_cov/generics/src/test_in_proc_decls_not_called.adb @@ -0,0 +1,21 @@ +with In_Proc_Decls; + +-- Check the coverage of a generic procedure, generic null, procedure, generic +-- function and a generic expression function declared in a regular procedure +-- when not called. We expect the generic subprograms to not be covered. +-- Currently, the coverage of instanciations of generic subprograms is not +-- computed. + +procedure Test_In_Proc_Decls_Not_Called is +begin + null; +end Test_In_Proc_Decls_Not_Called; + +--# in_proc_decls.adb +-- /p/ l- ## f- +-- /decl/ l- ## s- +-- /stmt/ l- ## s- +-- /fun/ l- ## f- +-- /exp_fun/ l? ## s=>s?, f=>s?,f? +-- /null_fun/ l? ## s=>s?, f=>s?,f? +-- /cstmt/ l- ## s-,c- diff --git a/testsuite/tests/287-function_call_cov/generics/test.py b/testsuite/tests/287-function_call_cov/generics/test.py new file mode 100644 index 000000000..c9c73843c --- /dev/null +++ b/testsuite/tests/287-function_call_cov/generics/test.py @@ -0,0 +1,14 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase( + category=CAT.mcdc, + fun_call_lvl=True, + tolerate_messages=( + r"cannot instrument generic expression functions|" + r"cannot instrument generic null procedures" + ), +).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/import_call/src/add.c b/testsuite/tests/287-function_call_cov/import_call/src/add.c new file mode 100644 index 000000000..a76197af4 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/import_call/src/add.c @@ -0,0 +1,5 @@ +int +add (int x, int y) +{ + return x + y; +} diff --git a/testsuite/tests/287-function_call_cov/import_call/src/call_add.adb b/testsuite/tests/287-function_call_cov/import_call/src/call_add.adb new file mode 100644 index 000000000..417d5a0dc --- /dev/null +++ b/testsuite/tests/287-function_call_cov/import_call/src/call_add.adb @@ -0,0 +1,24 @@ +pragma Ada_2012; + +procedure Call_Add -- # fun +is + function Add (X, Y : Integer) return Integer; + pragma Import (C, Add); + + Dummy : Integer := 0; -- # stmt +begin + if Add (40, 2) /= 42 then -- # if_1 + Dummy := Add (42, 2); -- # call_1 + end if; + + if Dummy = 50 then -- # if_2 + if Add (40, 2) /= 42 then -- # if_3 + Dummy := Add (42, 2); -- # call_2 + end if; + end if; + + if Add (40, 2) = 42 then -- # if_4 + Dummy := Add (42, 2); -- # call_3 + end if; + +end Call_Add; diff --git a/testsuite/tests/287-function_call_cov/import_call/src/test_import_called.adb b/testsuite/tests/287-function_call_cov/import_call/src/test_import_called.adb new file mode 100644 index 000000000..36ef7c109 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/import_call/src/test_import_called.adb @@ -0,0 +1,17 @@ +with Call_Add; + +procedure Test_Import_Called is +begin + Call_Add; +end Test_Import_Called; + +--# call_add.adb +-- /fun/ l+ ## 0 +-- /stmt/ l+ ## 0 +-- /if_1/ l! ## dT- +-- /call_1/ l- ## s=>s-, f=>s-,c- +-- /if_2/ l! ## dT- +-- /if_3/ l- ## s=>s-, f=>s-,c- +-- /call_2/ l- ## s=>s-, f=>s-,c- +-- /if_4/ l! ## dF- +-- /call_3/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/import_call/src/test_import_not_called.adb b/testsuite/tests/287-function_call_cov/import_call/src/test_import_not_called.adb new file mode 100644 index 000000000..a2ec0ddb2 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/import_call/src/test_import_not_called.adb @@ -0,0 +1,17 @@ +with Call_Add; + +procedure Test_Import_Not_Called is +begin + null; +end Test_Import_Not_Called; + +--# call_add.adb +-- /fun/ l- ## f- +-- /stmt/ l- ## s- +-- /if_1/ l- ## s=>s-, f=>s-,c- +-- /call_1/ l- ## s=>s-, f=>s-,c- +-- /if_2/ l- ## s- +-- /if_3/ l- ## s=>s-, f=>s-,c- +-- /call_2/ l- ## s=>s-, f=>s-,c- +-- /if_4/ l- ## s=>s-, f=>s-,c- +-- /call_3/ l- ## s=>s-, f=>s-,c- diff --git a/testsuite/tests/287-function_call_cov/import_call/test.py b/testsuite/tests/287-function_call_cov/import_call/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/import_call/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/nested_calls/src/nested.adb b/testsuite/tests/287-function_call_cov/nested_calls/src/nested.adb new file mode 100644 index 000000000..f665cfa67 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/nested_calls/src/nested.adb @@ -0,0 +1,32 @@ +pragma Ada_2012; + +procedure Nested +is + I : Integer := 1; -- # stmt + + function B (X : Integer := 5; Y : Boolean := True) return Integer -- # fun + is + begin + if Y then -- # stmt + return X; -- # stmt + else + return X; -- # stmt + end if; + end B; + +begin + I := -- # stmt + B -- # call + (B -- # call + (B), -- # call + False); -- # call + + if I = 42 then -- # if + I := -- # v_stmt + B -- # v_call + (B -- # v_call + (B), -- # v_call + False); -- # v_call + end if; + +end Nested; diff --git a/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb b/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb new file mode 100644 index 000000000..d5c8f75f1 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb @@ -0,0 +1,18 @@ +with Nested; + +-- Check that nested calls are all instrumented and that the correct call +-- violations are reported. Calls made in a function spec as a parameter's +-- default value should never be instrumented. + +procedure Test_Nested is +begin + Nested; +end Test_Nested; + +--# nested.adb +-- /stmt/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /call/ l+ ## 0 +-- /if/ l! ## dT- +-- /v_stmt/ l- ## s- +-- /v_call/ l- ## s=>s-, f=>s-,c- diff --git a/testsuite/tests/287-function_call_cov/nested_calls/test.py b/testsuite/tests/287-function_call_cov/nested_calls/test.py new file mode 100644 index 000000000..0bab4771c --- /dev/null +++ b/testsuite/tests/287-function_call_cov/nested_calls/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, assert_lvl="atc", fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/null_procedures/src/pkg.adb b/testsuite/tests/287-function_call_cov/null_procedures/src/pkg.adb new file mode 100644 index 000000000..1cf6a3c9a --- /dev/null +++ b/testsuite/tests/287-function_call_cov/null_procedures/src/pkg.adb @@ -0,0 +1,4 @@ +package body Pkg is + procedure P1 is null; -- # p + procedure P2 (I : Integer; J : Natural) is null; -- # p +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/null_procedures/src/pkg.ads b/testsuite/tests/287-function_call_cov/null_procedures/src/pkg.ads new file mode 100644 index 000000000..29dce71dc --- /dev/null +++ b/testsuite/tests/287-function_call_cov/null_procedures/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + procedure P1; + procedure P2 (I : Integer; J : Natural); + procedure P3 is null; -- # p +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/null_procedures/src/test_called.adb b/testsuite/tests/287-function_call_cov/null_procedures/src/test_called.adb new file mode 100644 index 000000000..3447c0082 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/null_procedures/src/test_called.adb @@ -0,0 +1,13 @@ +with Pkg; use Pkg; + +procedure Test_Not_Called is +begin + P1; + P2 (1, 2); + P3; +end Test_Not_Called; + +--# pkg.adb +-- /p/ l+ ## 0 +--# pkg.ads +-- /p/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/null_procedures/src/test_not_called.adb b/testsuite/tests/287-function_call_cov/null_procedures/src/test_not_called.adb new file mode 100644 index 000000000..923faeb0e --- /dev/null +++ b/testsuite/tests/287-function_call_cov/null_procedures/src/test_not_called.adb @@ -0,0 +1,11 @@ +with Pkg; use Pkg; + +procedure Test_Not_Called is +begin + null; +end Test_Not_Called; + +--# pkg.adb +-- /p/ l- ## s=>s-, f=>s-,f- +--# pkg.ads +-- /p/ l- ## s=>s-, f=>s-,f- diff --git a/testsuite/tests/287-function_call_cov/null_procedures/test.py b/testsuite/tests/287-function_call_cov/null_procedures/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/null_procedures/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/protected_body/src/foo.adb b/testsuite/tests/287-function_call_cov/protected_body/src/foo.adb new file mode 100644 index 000000000..6ed38862b --- /dev/null +++ b/testsuite/tests/287-function_call_cov/protected_body/src/foo.adb @@ -0,0 +1,26 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; + +package body Foo is + + protected body Obj_Type is + + function F return Integer is -- # fun + begin + return 8; -- # stmt + end F; + + function E (I : Integer) return Boolean is (True); -- # expr_fun + + procedure P (S : String) is -- # fun + begin + Put_Line (S); -- # call_stmt + null; -- # stmt + end P; + + procedure NP is -- # fun + null; -- # stmt + end Obj_Type; + +end Foo; diff --git a/testsuite/tests/287-function_call_cov/protected_body/src/foo.ads b/testsuite/tests/287-function_call_cov/protected_body/src/foo.ads new file mode 100644 index 000000000..b0f5ef620 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/protected_body/src/foo.ads @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package Foo is + + protected type Obj_Type is + function F return Integer; + function E (I : Integer) return Boolean; + procedure P (S : String); + procedure NP; + + end Obj_Type; + + Obj : Obj_Type; -- # decl + +end Foo; diff --git a/testsuite/tests/287-function_call_cov/protected_body/src/test_called.adb b/testsuite/tests/287-function_call_cov/protected_body/src/test_called.adb new file mode 100644 index 000000000..b063752a6 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/protected_body/src/test_called.adb @@ -0,0 +1,26 @@ +pragma Ada_2012; + +with Foo; use Foo; + +-- Check that function coverage violations are correctly reported for a +-- function, an expression function, a procedure and a null procedure inside +-- a protected body. + +procedure Test_Not_Called +is + I : Integer := 42; +begin + I := Obj.F; + if Obj.E (I) then + Obj.P ("Hello"); + end if; + Obj.NP; +end Test_Not_Called; + +--# foo.ads +-- /decl/ l+ ## 0 +--# foo.adb +-- /fun/ l+ ## 0 +-- /expr_fun/ l+ ## 0 +-- /call_stmt/ l+ ## 0 +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/protected_body/src/test_not_called.adb b/testsuite/tests/287-function_call_cov/protected_body/src/test_not_called.adb new file mode 100644 index 000000000..0eeca46e0 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/protected_body/src/test_not_called.adb @@ -0,0 +1,20 @@ +pragma Ada_2012; + +with Foo; use Foo; + +-- Check that function coverage violations are correctly reported for a +-- function, an expression function, a procedure and a null procedure inside +-- a protected body. + +procedure Test_Not_Called is +begin + null; +end Test_Not_Called; + +--# foo.ads +-- /decl/ l+ ## 0 +--# foo.adb +-- /fun/ l- ## f- +-- /expr_fun/ l- ## s=>s-, f=>s-,f-,c- +-- /call_stmt/ f=>l- ## s=>s-, f=>s-,c- +-- /stmt/ l- ## s- diff --git a/testsuite/tests/287-function_call_cov/protected_body/test.py b/testsuite/tests/287-function_call_cov/protected_body/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/protected_body/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_called.adb new file mode 100644 index 000000000..fa5cebc11 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_called.adb @@ -0,0 +1,109 @@ +pragma Ada_2012; + +procedure No_Decls_Called is -- # p + + I : Integer := 8; + + function Func return Integer is -- # fun + begin + return 42; -- # stmt + end Func; + + procedure Proc is -- # fun + begin + I := I + 1 - 1; -- # stmt + end Proc; + + function Fun_Param (X : Integer := 1) return Integer -- # fun + is + begin + return X; -- # stmt + end Fun_Param; + + procedure Proc_Param (X : out Integer; Y : Boolean := True) -- # fun + is + begin + X := (if Y then 5 else 6); -- # stmt + end Proc_Param; + + function Expr_Func return Integer -- # fun + is (42); -- # stmt + + function Expr_Func_Param (X : Integer := 1) return Integer -- # fun + is (X); -- # stmt + + function Over (A : Integer) return Integer is -- # fun + begin + return A; -- # stmt + end Over; + + function Over (A, B : Integer) return Boolean is -- # fun + begin + return A /= B; -- # stmt + end Over; + + procedure Over (A : Integer) is -- # fun + begin + I := A; -- # stmt + end Over; + + procedure Over (A, B : Integer) is -- # fun + begin + I := A + B; -- # stmt + end Over; + + Dummy : Integer := 0; -- # decl + F : Boolean := False; -- # decl +begin + -- For each subprogram, make one call executed and another not + + -------------------- + -- Executed calls -- + -------------------- + + -- Functions + Dummy := Func -- # call + + Fun_Param (8) -- # call + + Fun_Param; -- # call + Dummy := Expr_Func -- # call + - Expr_Func_Param -- # call + - Expr_Func_Param (-100); -- # call + Dummy := Over (1); -- # call + F := Over (10, 2); -- # call + + -- Procedures + Proc; -- # call + Proc_Param (Dummy); -- # call + Proc_Param (Dummy, False); -- # call + Over (5); -- # call + Over (1, 2); -- # call + + ------------------------ + -- Non-executed calls -- + ------------------------ + + F := False and then F; -- # set_f + if F then -- # if_cond + -- Functions + Dummy := -- # v_dummy + Func -- # v_call + + Fun_Param (8) -- # v_call + + Fun_Param; -- # v_call + Dummy := -- # v_dummy + Expr_Func -- # v_call + - Expr_Func_Param -- # v_call + - Expr_Func_Param (-100); -- # v_call + Dummy := Over (1); -- # v_scall + F := Over (10, 2); -- # v_scall + + -- Procedures + -- Call statements that are not executed are simply reported as + -- statement violations. + Proc; -- # v_stmt + Proc_Param (Dummy); -- # v_stmt + Proc_Param (Dummy, False); -- # v_cstmt + Over (5); -- # v_stmt + Over (1, 2); -- # v_stmt + end if; + +end No_Decls_Called; diff --git a/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_not_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_not_called.adb new file mode 100644 index 000000000..8f5d77ec9 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_not_called.adb @@ -0,0 +1,57 @@ +pragma Ada_2012; + +procedure No_Decls_Not_Called is -- # p + + I : Integer := 8; -- # stmt + + function Func return Integer is -- # fun + begin + return 42; -- # stmt + end Func; + + procedure Proc is -- # fun + begin + I := I + 1 - 1; -- # stmt + end Proc; + + function Fun_Param (X : Integer := 1) return Integer -- # fun + is + begin + return X; -- # stmt + end Fun_Param; + + procedure Proc_Param (X : out Integer; Y : Boolean := True) -- # fun + is + begin + X := (if Y then 5 else 6); -- # stmt + end Proc_Param; + + function Expr_Func return Integer -- # fun + is (42); -- # stmt + + function Expr_Func_Param (X : Integer := 1) return Integer -- # fun + is (X); -- # stmt + + function Over (A : Integer) return Integer is -- # fun + begin + return A; -- # stmt + end Over; + + function Over (A, B : Integer) return Boolean is -- # fun + begin + return A /= B; -- # stmt + end Over; + + procedure Over (A : Integer) is -- # fun + begin + I := A; -- # stmt + end Over; + + procedure Over (A, B : Integer) is -- # fun + begin + I := A + B; -- # stmt + end Over; + +begin + null; -- # stmt +end No_Decls_Not_Called; diff --git a/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_called.adb new file mode 100644 index 000000000..4cfc67160 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_called.adb @@ -0,0 +1,22 @@ +with No_Decls_Called; + +-- Call the subprograms which have a previous declaration. + +procedure Test_No_Decls_Called is +begin + No_Decls_Called; +end Test_No_Decls_Called; + +--# no_decls_called.adb +-- /p/ l+ ## 0 +-- /decl/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /stmt/ l+ ## 0 +-- /call/ l+ ## 0 +-- /set_f/ l+ ## 0 +-- /if_cond/ l! ## dT- +-- /v_dummy/ l- ## s- +-- /v_stmt/ l- ## s-,c- +-- /v_cstmt/ l- ## s-,c-,c- +-- /v_call/ l- ## c- +-- /v_scall/ l- ## s=>s-, f=>s-,c- diff --git a/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_not_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_not_called.adb new file mode 100644 index 000000000..238d6d2de --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_not_called.adb @@ -0,0 +1,16 @@ +with No_Decls_Not_Called; + +-- Import subprograms which all have a previous declarations. +-- None of the subprograms in the imported package are called here, so all of +-- them should have function coverage violations. + +procedure Test_No_Decls_Not_Called is +begin + null; +end Test_No_Decls_Not_Called; + +--# no_decls_not_called.adb +-- /p/ l- ## f- +-- /decl/ l+ ## 0 +-- /stmt/ l- ## s- +-- /fun/ l- ## f- diff --git a/testsuite/tests/287-function_call_cov/subp_kinds/test.py b/testsuite/tests/287-function_call_cov/subp_kinds/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/call_with_decls.adb b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/call_with_decls.adb new file mode 100644 index 000000000..c2a41f8ba --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/call_with_decls.adb @@ -0,0 +1,61 @@ +pragma Ada_2012; + +with With_Decls; use With_Decls; + +procedure Call_With_Decls +is + Dummy : Integer := 0; -- # stmt + F : Boolean := False; -- # stmt +begin + -- For each subprogram, make one call executed and another not + + -------------------- + -- Executed calls -- + -------------------- + + -- Functions + Dummy := Func -- # fun + + Fun_Param (8) -- # fun + + Fun_Param; -- # fun + Dummy := Expr_Func -- # fun + - Expr_Func_Param -- # fun + - Expr_Func_Param (-100); -- # fun + Dummy := Over (1); -- # fun + F := Over (10, 2); -- # fun + + -- Procedures + Proc; -- # fun + Proc_Param (Dummy); -- # fun + Proc_Param (Dummy, False); -- # fun + Over (5); -- # fun + Over (1, 2); -- # fun + + ------------------------ + -- Non-executed calls -- + ------------------------ + + F := False and then F; -- # set_f + if F then -- # if_cond + -- Functions + Dummy := -- # v_stmt + Func -- # v_fun + + Fun_Param (8) -- # v_fun + + Fun_Param; -- # v_fun + Dummy := -- # v_stmt + Expr_Func -- # v_fun + - Expr_Func_Param -- # v_fun + - Expr_Func_Param (-100); -- # v_fun + Dummy := Over (1); -- # v_sfun + F := Over (10, 2); -- # v_sfun + + -- Procedures + -- Call statements that are not executed are simply reported as + -- statement violations. + Proc; -- # v_cstmt + Proc_Param (Dummy); -- # v_cstmt + Proc_Param (Dummy, False); -- # v_false + Over (5); -- # v_cstmt + Over (1, 2); -- # v_cstmt + end if; + +end Call_With_Decls; diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_called.adb new file mode 100644 index 000000000..7dc24d6fb --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_called.adb @@ -0,0 +1,24 @@ +with Call_With_Decls; + +-- Call the subprograms which have a previous declaration. + +procedure Test_With_Decls_Called is +begin + Call_With_Decls; +end Test_With_Decls_Called; + +--# call_with_decls.adb +-- /stmt/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /set_f/ l+ ## 0 +-- /if_cond/ l! ## dT- +-- /v_stmt/ l- ## s- +-- /v_fun/ l- ## c- +-- /v_sfun/ l- ## s-,c- +-- /v_cstmt/ l- ## s-,c- +-- /v_false/ l- ## s-,c-,c- +--# with_decls.ads +-- /stmt/ l+ ## 0 +--# with_decls.adb +-- /fun/ l+ ## 0 +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_not_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_not_called.adb new file mode 100644 index 000000000..647500691 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_not_called.adb @@ -0,0 +1,16 @@ +with With_Decls; + +-- Import subprograms which all have a previous declarations. +-- None of the subprograms in the imported package are called here, so all of +-- them should have function coverage violations. + +procedure Test_With_Decls_Not_Called is +begin + null; +end Test_With_Decls_Not_Called; + +--# with_decls.ads +-- /stmt/ l+ ## 0 +--# with_decls.adb +-- /stmt/ l- ## s- +-- /fun/ l- ## f- diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.adb b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.adb new file mode 100644 index 000000000..4430c632c --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.adb @@ -0,0 +1,53 @@ +pragma Ada_2012; + +package body With_Decls is + + function Func return Integer is -- # fun + begin + return 42; -- # stmt + end Func; + + procedure Proc is -- # fun + begin + I := I + 1 - 1; -- # stmt + end Proc; + + function Fun_Param (X : Integer := 1) return Integer -- # fun + is + begin + return X; -- # stmt + end Fun_Param; + + procedure Proc_Param (X : out Integer; Y : Boolean := True) -- # fun + is + begin + X := (if Y then 5 else 6); -- # stmt + end Proc_Param; + + function Expr_Func return Integer -- # fun + is (42); -- # stmt + + function Expr_Func_Param (X : Integer := 1) return Integer -- # fun + is (X); -- # stmt + + function Over (A : Integer) return Integer is -- # fun + begin + return A; -- # stmt + end Over; + + function Over (A, B : Integer) return Boolean is -- # fun + begin + return A /= B; -- # stmt + end Over; + + procedure Over (A : Integer) is -- # fun + begin + I := A; -- # stmt + end Over; + + procedure Over (A, B : Integer) is -- # fun + begin + I := A + B; -- # stmt + end Over; + +end With_Decls; diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.ads b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.ads new file mode 100644 index 000000000..16d7cc42f --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/with_decls.ads @@ -0,0 +1,25 @@ +pragma Ada_2012; + +package With_Decls is + + I : Integer := 1; -- # stmt + + -- No parameters + function Func return Integer; + procedure Proc; + + -- With parameters + function Fun_Param (X : Integer := 1) return Integer; + procedure Proc_Param (X : out Integer; Y : Boolean := True); + + -- Expression function + function Expr_Func return Integer; + function Expr_Func_Param (X : Integer := 1) return Integer; + + -- Overloaded + function Over (A : Integer) return Integer; + function Over (A, B : Integer) return Boolean; + procedure Over (A : Integer); + procedure Over (A, B : Integer); + +end With_Decls; diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/test.py b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() From ed32124e2ffa10f71da65112c7974dacb8ad64f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Thu, 22 Aug 2024 10:27:00 +0200 Subject: [PATCH 0903/1483] Adapt tests following addition of fun_call cov * 207-srctrace-version: update sids --- .../tests/207-srctrace-version/foo.c.sid | Bin 1195 -> 1198 bytes testsuite/tests/207-srctrace-version/main.sid | Bin 1431 -> 1432 bytes .../207-srctrace-version/reference.srctrace | Bin 336 -> 336 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid index bf7313e5187484f56706fdb85eaeb26e732eef65..ec5d138afc8be4380cc612ba3be1d2d741dbc495 100644 GIT binary patch delta 53 zcmZ3@xsG#!;zosJCN>cUAYhujkx^muN+xkeF=rrGKO;XkRX;tkD783Mza&3Dr+D%e G=Ia1&i_@% delta 50 ucmbQiJ)L`k;zp%hW=5gO6PR7Vr26D@Oq`QhSssCT29qUNMWEs#tS$g=9}T_$ diff --git a/testsuite/tests/207-srctrace-version/reference.srctrace b/testsuite/tests/207-srctrace-version/reference.srctrace index 9a72425837fa4bf7d40d1928c0367d006d118f6e..210609fe5f901a06a753bb9c8399e9ca72ae3dc3 100644 GIT binary patch delta 14 Vcmcb>bb)Dt1M}3vGaH?G838M^1xx?{ delta 14 Vcmcb>bb)Dt1M?yO{TrQm838Nd1xf$_ From bbe77feefcbde57aad90fc8bf5628efa5f944f11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Mon, 26 Aug 2024 16:45:10 +0200 Subject: [PATCH 0904/1483] Add function and call coverage documentation --- doc/gnatcov/cov_source.rst | 41 +++++++++++++++++++++++++++++ tools/gnatcov/annotations-sarif.adb | 4 ++- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index 76f2d92de..c132d2eaf 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -1540,6 +1540,47 @@ When a trailing `+` is added to the format passed to :cmd-option:`--annotate` available for each line in addition to the annotation. The :cmd-option:`=html` provides it by default. +.. _scov-fun_call: + +Function and Call Coverage (FUN_CALL) analysis (experimental) +============================================================= + +|gcv| can also provide an analysis of the coverage of subprograms and calls for +Ada source traces. + +If such coverage analysis is needed, it should always be activated along one of +the non-assertion coverage levels previously described. In this section on +function and call coverage, the associated command line option will be written +as `--level=...+fun_call` where `...` is one of `stmt`, `stmt+decision`, +`stmt+mcdc` and `stmt+uc_mcdc`. Assertion coverage can also be activated at the +same time. + +Core notions and Reporting (:cmd-option:`--level=...+fun_call`) +---------------------------------------------------------- + +|gcv| performs Function and Call Coverage assessments with the +:cmd-option:`--level=...+fun_call` command line option. The assessment +determines the status of subprograms and call coverage obligations out of the +tests execution, considering that: + +* A subprogram is :dfn:`covered`, and the obligation :dfn:`discharged`, + as soon as the execution as entered it at least once. + +* A subprogram is :dfn:`uncovered` otherwise. + +* A call is :dfn:`covered`, and the obligation :dfn:`discharged`, if it has + been executed at least once. + +* A call is :dfn:`uncovered` otherwise. + +In synthetic :cmd-option:`=report` outputs, uncovered source subprograms and +calls are listed as FUN_CALL Coverage violations in the dedicated report +section. + +It is important to note that for an :dfn:`uncovered` statement which happens +to be a call statement, only a statement violation will be emitted in +coverage reports. + .. _synthetic-metrics: Synthetic metrics diff --git a/tools/gnatcov/annotations-sarif.adb b/tools/gnatcov/annotations-sarif.adb index 15b67af9e..640868c9d 100644 --- a/tools/gnatcov/annotations-sarif.adb +++ b/tools/gnatcov/annotations-sarif.adb @@ -195,7 +195,9 @@ package body Annotations.Sarif is Short_Descr => (+"The subprogram was entered at least once or the call" & " was executed at least once"), - Help_Uri => +"FIXME", + Help_Uri => +Doc_Link + & "gnatcov/cov_source.html#function-and-call-coverage-fun-call-" + & "analysis-experimental", Config => +"error"), Undet_Rule => (Id => +"UNDET", From 0bb608bdabcbd1b649a4c272db3c8b38ad434fde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 2 Sep 2024 10:55:17 +0200 Subject: [PATCH 0905/1483] Update arch-mix test --- .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 668 -> 1508 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2036 -> 2596 bytes .../gen/arm-elf-linux/main_1.sid | Bin 446 -> 447 bytes .../gen/arm-elf-linux/main_2.sid | Bin 446 -> 447 bytes .../gen/arm-elf-linux/pkg.sid | Bin 1135 -> 1136 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1919 -> 1925 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1929 -> 1935 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 2152 -> 2159 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 2083 -> 2090 bytes .../gen/x86_64-windows/main_1.sid | Bin 448 -> 449 bytes .../gen/x86_64-windows/main_2.sid | Bin 448 -> 449 bytes .../gen/x86_64-windows/pkg.sid | Bin 1139 -> 1140 bytes 12 files changed, 0 insertions(+), 0 deletions(-) diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index 5c5bff2c03eeb11b054484df81c5058276939645..904fd75753f3f28dfc5705bdc9b3d93305e713e9 100644 GIT binary patch literal 1508 zcmYk6Pe@cz7{$Mtrtv8fy;np@iwnAt&>E+4QgI{X9^~U^@ z-aB`n#^MRHdNcgD0LNZMWjx59uo%v(a6In2f97HDy+^m3%#z4FT+_KsI%QUY^CLLY zsdT0>)!LX!yHrbCbEYlb?8mBPZzh{(0X3SrIz=DK@wp?LB+?>7l zjBEu=Ag?KZ00ZO=<)VB^`Lp+tZTswONA+FsutoOM`_Kvj=LxL=^BzO}JXnofW@J}< zJ+whEf*%C~_%b7#MCN+eJ)IRjBP)SPtZz$s8$6BcahpK{>J4B5IR)bBcrs^v-C2u# zyF5wXA)iz3lqc!CnGWt^K{m!+y(OY zmUG@&)B7Fo$*S zD1QMvvHp4NFYXI`90G^y9N34xQD2X29OV6x9Cs27z-f^Ce#SGhm-2I-p}p|?DYP6u zQ-?5q9e5J#207nRko&g>JdW{(z$9`(^-Ylb{~K6?dP|JsM0OG6Ixc}VU_V$54ubqH zjDvhH`?&5DI1n#i_Z+N4UIqDGm{WZL3)=P?V?&wFBj_t>CKfUZ<5ymW^%;>2-;X(A5LU~RT0ID=wJ55il3(%v{@R)Tr3YeCl9N9fF_YrSIn2W=Xz+g+F)p0u z-V^*em_;Y_WGVJ@(t#fFZK!z(J=sNT{ZrT^PFr*2KrZjl>9B2 zM(7&w2mk9Fa;OkGuVPz*n#?v9jJS|BX0_Bx=CIame40q_tdlgFR1l? z!x5NhM{cZt8~eVvcE87H&A)~&_lI#jC(r4t{!jYqJA9~fytDei?&A<@ybtyL_pCZW A`~Uy| diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_2.trace b/testsuite/tests/U204-026-arch-mix/bin-main_2.trace index e863c76b1b7bb3bd2a83ca8c276d8f62e1b4cbcb..b7bfe9c107d699bab0e36b5ab17fdd488b0b0b40 100644 GIT binary patch delta 690 zcmeyuzeHq$94jXihndtwWhEm+V>5OJ1_oguHZm|W(KWEtH84^zu&^>Uu`)7a-~ftq z1F?d!nYpE@rKN?X@y7C0)_MU31)wMc!vT;a5U?-^f$1Y~z5p;U-pi&D1?9ku41gH{wZedW`N{X$Lb;LjPu6Ew|R5T^j~6wU|^1qMN|asb#}7m)w} diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index 4708c617687ec39a6caa21ba1f8ff7ef47cc7977..2b2c925358393250b046889deb939f20a792de77 100644 GIT binary patch delta 16 XcmdnTyq|f3;zk7nMn;jzfsDBTEQ$o4 delta 27 hcmdnbypMT;;zlKXMm8Y^AYhvKPeX9-sT delta 26 ecmeys@t$LX;zp%5W=5gO@0ismUtpF6vzh>eZV6Wa diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt index 7a1889f46a14049be47f4266b5957e0ecbd8536d..ad078c916ca0c737b39bd1c06f3f186c85dd2e8d 100644 GIT binary patch delta 122 zcmey**UCRZaic;83!}*7P8Js+c@9kGF{@9uVwDB*L9BXKlgXP{MJFF)HRWSwWMBXy zFlJz$%+97TS&c20-Qmsd?^)kvCU>!2RI$`GFj6oyurf8VGBQ=rHZZa>FaT)*0T>Mc DZv7gz delta 94 zcmZqW|Iar;aidZ?3!~8FE*2Lcc^*vWGpkRwW|alrx_Jo4Gh2m$$Cr@Cz$ZMf%Xr^FjYGq(#Wo$e-k6j!9{%aaR diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index abfe1aacc27c34a4575647e8343d60cdbc9b1093..0e3d50f67ff61148c37ea58ba3d5245faacb07d6 100644 GIT binary patch delta 118 zcmeC=@8_SOxKW{ig;8YkL>3nyc@0b^u&PgXVwDB*6Ii49m>C%v7#SECn1GmpdGc{q zo5@UUqLamdSc@%@y`ufHYW8=T$&=VFt61t97%3PUSecqw8JQ_)8yHy`7=W~b0E`9z DNR$`I delta 134 zcmeC@@8qALxKSyeg-wWwfq{W>@*NiC$-7u&7=SXr^FjYGq(#Wo)9L O4WtYVz$#%nfHVMlYZ-X} diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 520943c838f06096f59d01382548dfb34b9ba62b..22764270ad3cd420df47a2fa2ae34c8f7ceb383e 100644 GIT binary patch delta 102 zcmaDM@Lpho;zor{%#0$F3s^NK|7Ml}vkW$Su&6VFnJ!>beexaFS(8iIL?=IG6Xj!O uWMp7uU|?VZVg}~PtJrKn!jpfpC9p^M)<<3WAu~CFU6k3l3t2TL|6!H^vkW$SvZynHnJ!>beezw_S(7W+M0gk(7=Q?j z879wSlbO7o%>-5OCtJFF!|UzMj%USBf|LpXv5~2sLAip4k%5tkfrX*zl1z9vEe_@tk6xuAv63z$~Fqk}(RRqjZpL~^d*5oH_B9mL$ nM0gk(85kKD7?^;VVe)b|8?eMrws`i4|7jWGXT>MSv!4b4S@an& diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid index 56db5bf555e9a0779c08b1ec0573398110a54fc0..7816da56176b634a3d2a0da9e2afbfeccfa1a6b1 100644 GIT binary patch delta 27 hcmX@We2{s9;zk7{Mm7-!AYhvKP-fx>mdO>29sp`J2fzRT delta 24 ecmX@ee1Lg^;zlJyMm8Y^AYhvKPmdO>29sp`J2fzRT delta 24 ecmX@ee1Lg^;zlJyMm8Y^AYhvKPf+X-&~ delta 26 ecmeyu@tI?S;zp$|W=5gOYnffZr21q@mS_NdPY5dj From 28b22f372dbaf8c93bc896b6c58086a2a45671d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 2 Sep 2024 15:06:23 +0200 Subject: [PATCH 0906/1483] Kill fun_call tests not viable on light runtimes --- testsuite/tests/287-function_call_cov/access_to_subp/test.opt | 1 + testsuite/tests/287-function_call_cov/protected_body/test.opt | 1 + 2 files changed, 2 insertions(+) create mode 100644 testsuite/tests/287-function_call_cov/access_to_subp/test.opt create mode 100644 testsuite/tests/287-function_call_cov/protected_body/test.opt diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/test.opt b/testsuite/tests/287-function_call_cov/access_to_subp/test.opt new file mode 100644 index 000000000..b69bc20bd --- /dev/null +++ b/testsuite/tests/287-function_call_cov/access_to_subp/test.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD test uses dynamic code, incompatible with light RTS diff --git a/testsuite/tests/287-function_call_cov/protected_body/test.opt b/testsuite/tests/287-function_call_cov/protected_body/test.opt new file mode 100644 index 000000000..6a8d1597d --- /dev/null +++ b/testsuite/tests/287-function_call_cov/protected_body/test.opt @@ -0,0 +1 @@ +RTS_ZFP DEAD Test uses tasking constructs, not available on light RTS From f693a8cf53bff9a2fa8439b54dde9be6b47a0967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 3 Sep 2024 14:53:37 +0200 Subject: [PATCH 0907/1483] .gitlab.ci.yaml: Add optionnal test jobs --- .gitlab-ci.yml | 61 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d54b9f397..00644a348 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -232,3 +232,64 @@ stylechecks: - pre-commit run -a --show-diff-on-failure - python .check-formatting.py --force-colors + +################# +# Optional jobs # +################# + +# Optional job for block instrumentation. +# +# To be run when Ada or C instrumentation is modified to ensure the new +# changes are also compatible with block instrumentation. +test_block_instr: + interruptible: true + services: + - image:e3 + - cpu:16 + - mem:16 + stage: test + when: manual + script: + - *basic_test_setup + + # Test using anod + - anod test gnatcov --minimal -Qsrc-traces,instr,block $ACI_TRACK_QUALIFIER + - TEST_BSN=$(anod eval --primitive=test gnatcov -Qsrc-traces,instr,block $ACI_TRACK_QUALIFIER build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - e3-testsuite-report + --failure-exit-code 1 + --xunit-output $CI_PROJECT_DIR/xunit_output.xml + --xunit-name src-traces + $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/results/new/ + + <<: *artifacts + +# Optional job for light runtime testing on source traces. Dump trigger +# strategies differ on that runtime, and not all tests are compatible with +# this runtime depending on the needed features (e.g. --dump-channel=bin-file) +# or the test sources make use of Ada features not available on this runtime. +# +# Only needs to be run when large batches of src-trace specific tests are added, +# or if instrumentation code related to buffer dump is modified. +test_src_light: + interruptible: true + services: + - image:e3 + - cpu:16 + - mem:16 + stage: test + when: manual + script: + - *basic_test_setup + + # Test using anod + - anod test gnatcov --minimal -Qsrc-traces,instr,RTS=light-stm32f4 --target=arm-elf,,qemu-stm32 $ACI_TRACK_QUALIFIER + - TEST_BSN=$(anod eval --primitive=test gnatcov -Qsrc-traces,instr,RTS=light-stm32f4 --target=arm-elf,,qemu-stm32 $ACI_TRACK_QUALIFIER build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml + - e3-testsuite-report + --failure-exit-code 1 + --xunit-output $CI_PROJECT_DIR/xunit_output.xml + --xunit-name src-traces + $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/results/new/ + + <<: *artifacts From 1fe9729f5add2722f69e65d71c6d4331024c6443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 3 Sep 2024 14:09:10 +0200 Subject: [PATCH 0908/1483] Coverage.Source: Fix processing of block coverage The introduction of function and call coverage added new SCO types that are discharged by bits in the statement buffer, but which were not part of any block. This change properly ignores the buffer bits that are not part of any block when processing the block information at coverage time. --- tools/gnatcov/coverage-source.adb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 4ccc775b9..d3141813e 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -2250,6 +2250,16 @@ package body Coverage.Source is if not Stmt_Blocks.Is_Empty then Block_Index := Stmt_Blocks.First_Index; for J in Stmt_Buffer'Range loop + + -- Skip buffer bits corresponding to fun_call SCOs + -- + -- TODO??? Investigate if having a separate buffer for calls + -- makes more sense, and/or yields a cleaner implementation. + + if Kind (BM.Statement_Bits (J)) not in Statement then + goto Continue; + end if; + if Stmt_Buffer (J) then for SCO of Stmt_Blocks.Element (Block_Index) loop Update_SCI_Wrapper @@ -2259,6 +2269,7 @@ package body Coverage.Source is end loop; end if; Block_Index := Block_Index + 1; + <> end loop; end if; end; @@ -2583,6 +2594,12 @@ package body Coverage.Source is for Bit in Stmt_Bit_Map'Range loop + -- Skip bits corresponding to fun_call obligations + + if Kind (Stmt_Bit_Map (Bit)) in Fun_Call_SCO_Kind then + goto Continue; + end if; + -- Assert that the SCO corresponding to the current bit -- corresponds to the last statement SCO of the current block. @@ -2601,6 +2618,7 @@ package body Coverage.Source is Process => Process_SCI'Access); end loop; Block_Index := Block_Index + 1; + <> end loop; end if; end; From 1f55dfcd2c952ea556e499b6fad0047c5afd7798 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 3 Sep 2024 14:27:28 +0200 Subject: [PATCH 0909/1483] instrument-ada_unit.adb: fix wrong use of Insertion_Info_Ref Some parts of the instrumentation used to make a copy of the referenced insertion info in the instrumentation context when processing nested entites, thus losing the reference to the insertion information referenced by the block stack. This resulted in access to invalid insertion information. Now only references to insertion info are saved / restored when processing nested entities, thus ensuring proper preservation of the insertion information across the instrumentation context, and the block stack. --- tools/gnatcov/instrument-ada_unit.adb | 101 +++++++++++++------------- 1 file changed, 51 insertions(+), 50 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 6b9afc076..8ff4bffe8 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -567,9 +567,8 @@ package body Instrument.Ada_Unit is procedure Fill_Expression_Insertion_Info (UIC : in out Ada_Unit_Inst_Context; - Bit : Any_Bit_Id; - Insert_Info : out Insertion_Info); - -- Fill Insertion_Info with new witness formal and actual + Bit : Any_Bit_Id); + -- Fill UIC.Current_Insertion_Info with new witness formal and actual procedure Ensure_With (UIC : in out Ada_Unit_Inst_Context'Class; Unit : Text_Type); @@ -4172,11 +4171,13 @@ package body Instrument.Ada_Unit is -- Local contexts for statement and MC/DC instrumentation -- ------------------------------------------------------------ - New_Insertion_Info : aliased Insertion_Info; + New_Insertion_Info : Insertion_Info_Ref; -- Witness insertion info for statements (for both null procedures -- and expression functions). New_Fun_Insertion_Info : aliased Insertion_Info; - -- Witness insertion info for function SCO + -- Witness insertion info for function SCO. This is never used + -- outside of this subprogram (in particular, not stored in UIC), so + -- we don't need to create a ref. Save_Disable_Instrumentation : constant Boolean := UIC.Disable_Instrumentation; @@ -4438,10 +4439,11 @@ package body Instrument.Ada_Unit is -- The statement instrumentation below will take care of assigning -- .Witness_* components to their definitive values. - New_Insertion_Info := - (Method => Expression_Function, - Witness_Actual => No_Node_Rewriting_Handle, - Witness_Formal => No_Node_Rewriting_Handle); + New_Insertion_Info.Set + (Insertion_Info' + (Method => Expression_Function, + Witness_Actual => No_Node_Rewriting_Handle, + Witness_Formal => No_Node_Rewriting_Handle)); if Is_Expr_Function and then Fun_Cov then New_Fun_Insertion_Info := @@ -4482,26 +4484,25 @@ package body Instrument.Ada_Unit is -- Allow witness insertion for the "null" statement in the generic -- procedure (NP_Nodes.Null_Stmt). - New_Insertion_Info := - (Method => Statement, - RH_List => NP_Nodes.Stmt_List, - - -- Even if the current package has elaboration restrictions, - -- this Insertion_Info is used to insert a witness call in the - -- procedure in the generic body: the elaboration restriction - -- does not apply there. + New_Insertion_Info.Set + (Insertion_Info' + (Method => Statement, + RH_List => NP_Nodes.Stmt_List, - Preelab => False, + -- Even if the current package has elaboration restrictions, + -- this Insertion_Info is used to insert a witness call in + -- the procedure in the generic body: the elaboration + -- restriction does not apply there. - Parent => null); + Preelab => False, + Parent => null)); end if; ---------------------------------- -- 2. Statement instrumentation -- ---------------------------------- - Insertion_Info_SP.Set - (UIC.Current_Insertion_Info, New_Insertion_Info); + UIC.Current_Insertion_Info := New_Insertion_Info; UIC.MCDC_State_Inserter := EF_Inserter'Unchecked_Access; @@ -4537,7 +4538,7 @@ package body Instrument.Ada_Unit is -- The insertion info has been completed by calls to -- Insert_Stmt_Witness. - New_Insertion_Info := UIC.Current_Insertion_Info.Get; + New_Insertion_Info := UIC.Current_Insertion_Info; if Fun_Cov then @@ -4586,7 +4587,8 @@ package body Instrument.Ada_Unit is -- function. if Call_Params /= No_Node_Rewriting_Handle then - Insert_Last (Call_Params, New_Insertion_Info.Witness_Actual); + Insert_Last + (Call_Params, New_Insertion_Info.Get.Witness_Actual); -- If function coverage is needed, pass a second witness call -- as argument. This one is responsible for discharging the @@ -4598,7 +4600,8 @@ package body Instrument.Ada_Unit is end if; if Formal_Params /= No_Node_Rewriting_Handle then - Insert_Last (Formal_Params, New_Insertion_Info.Witness_Formal); + Insert_Last + (Formal_Params, New_Insertion_Info.Get.Witness_Formal); if Fun_Cov then Insert_Last @@ -6237,8 +6240,7 @@ package body Instrument.Ada_Unit is (UIC, Allocate_Statement_Bit (UIC.Unit_Bits, - SCOs.SCO_Table.Last), - UIC.Current_Insertion_Info.Get); + SCOs.SCO_Table.Last)); Replace (Orig_Handle, Dummy_Handle); @@ -6292,8 +6294,8 @@ package body Instrument.Ada_Unit is end Aux_Process_Call_Expression; - Saved_Insertion_Info : constant Insertion_Info := - UIC.Current_Insertion_Info.Get; + Saved_Insertion_Info : constant Insertion_Info_Ref := + UIC.Current_Insertion_Info; Local_Insertion_Info : constant Insertion_Info (Expression_Function) := @@ -6309,8 +6311,7 @@ package body Instrument.Ada_Unit is N.Traverse (Aux_Process_Call_Expression'Access); - Insertion_Info_SP.Set - (UIC.Current_Insertion_Info, Saved_Insertion_Info); + UIC.Current_Insertion_Info := Saved_Insertion_Info; end Process_Call_Expression; ----------------------- @@ -7042,8 +7043,7 @@ package body Instrument.Ada_Unit is procedure Fill_Expression_Insertion_Info (UIC : in out Ada_Unit_Inst_Context; - Bit : Any_Bit_Id; - Insert_Info : out Insertion_Info) + Bit : Any_Bit_Id) is Formal_Name : constant Node_Rewriting_Handle := Make_Identifier (UIC, "Dummy_Witness_Result"); @@ -7057,21 +7057,22 @@ package body Instrument.Ada_Unit is -- Create both the witness call and a formal parameter to -- accept it as an actual. - Insert_Info.Witness_Actual := Make_Statement_Witness + UIC.Current_Insertion_Info.Get.Witness_Actual := Make_Statement_Witness (UIC, Bit => Bit, Flavor => Function_Call, In_Generic => UIC.In_Generic, In_Decl_Expr => UIC.In_Decl_Expr); - Insert_Info.Witness_Formal := Create_Param_Spec - (UIC.Rewriting_Context, - F_Ids => Formal_Def_Id, - F_Has_Aliased => No_Node_Rewriting_Handle, - F_Mode => No_Node_Rewriting_Handle, - F_Type_Expr => Make_Std_Ref (UIC, "Boolean"), - F_Default_Expr => No_Node_Rewriting_Handle, - F_Aspects => No_Node_Rewriting_Handle); + UIC.Current_Insertion_Info.Get.Witness_Formal := + Create_Param_Spec + (UIC.Rewriting_Context, + F_Ids => Formal_Def_Id, + F_Has_Aliased => No_Node_Rewriting_Handle, + F_Mode => No_Node_Rewriting_Handle, + F_Type_Expr => Make_Std_Ref (UIC, "Boolean"), + F_Default_Expr => No_Node_Rewriting_Handle, + F_Aspects => No_Node_Rewriting_Handle); end Fill_Expression_Insertion_Info; @@ -7781,14 +7782,14 @@ package body Instrument.Ada_Unit is Stmt_Instr_Info.Insertion_N; Instrument_Location : Instrument_Location_Type renames Stmt_Instr_Info.Instrument_Location; - Insert_Info : Insertion_Info renames - Stmt_Instr_Info.Insert_Info_Ref.Get; + Insert_Info : Insertion_Info_Ref renames + Stmt_Instr_Info.Insert_Info_Ref; begin -- Create an artificial internal error, if requested Raise_Stub_Internal_Error_For (Ada_Instrument_Insert_Stmt_Witness); - case Insert_Info.Method is + case Insert_Info.Get.Method is when Statement | Declaration => @@ -7908,15 +7909,15 @@ package body Instrument.Ada_Unit is case Instrument_Location is when Before => Is_Before := True; - Ref_List := Insert_Info.RH_List; + Ref_List := Insert_Info.Get.RH_List; when Before_Parent => Is_Before := True; - Ref_List := Insert_Info.Parent.RH_List; + Ref_List := Insert_Info.Get.Parent.RH_List; when After => Is_Before := False; - Ref_List := Insert_Info.RH_List; + Ref_List := Insert_Info.Get.RH_List; -- The cases where we need to instrument -- inside an expression are handled before, @@ -7940,7 +7941,7 @@ package body Instrument.Ada_Unit is (UIC, Bit => Bit, Flavor => - (case Insert_Info.Method is + (case Insert_Info.Get.Method is when Statement => Procedure_Call, when Declaration => Declaration, when Expression_Function | None => @@ -7977,14 +7978,14 @@ package body Instrument.Ada_Unit is Children => (1 => Create_Defining_Name (RC, Formal_Name))); begin - Insert_Info.Witness_Actual := Make_Statement_Witness + Insert_Info.Get.Witness_Actual := Make_Statement_Witness (UIC, Bit => Bit, Flavor => Function_Call, In_Generic => UIC.In_Generic, In_Decl_Expr => Stmt_Instr_Info.In_Decl_Expr); - Insert_Info.Witness_Formal := Create_Param_Spec + Insert_Info.Get.Witness_Formal := Create_Param_Spec (RC, F_Ids => Formal_Def_Id, F_Has_Aliased => No_Node_Rewriting_Handle, From ad29cc5039f51176ce67a7bbeb101bc4b8b99d39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 3 Sep 2024 14:55:28 +0200 Subject: [PATCH 0910/1483] Adapt test to remove dynamic code The test used dynamic code, which is not supported on light-* runtimes. Remove it as the dynamic code is not the tested entity here, to make the test runnable on all our configurations. --- .../access_to_subp/src/access_to_subp.adb | 9 ++------- .../access_to_subp/src/pkg.ads | 13 +++++++++++++ .../access_to_subp/src/test_called.adb | 6 +++++- .../access_to_subp/src/test_not_called.adb | 5 ++++- .../287-function_call_cov/access_to_subp/test.opt | 1 - 5 files changed, 24 insertions(+), 10 deletions(-) create mode 100644 testsuite/tests/287-function_call_cov/access_to_subp/src/pkg.ads delete mode 100644 testsuite/tests/287-function_call_cov/access_to_subp/test.opt diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/src/access_to_subp.adb b/testsuite/tests/287-function_call_cov/access_to_subp/src/access_to_subp.adb index 7f3da15c1..8a924bd0e 100644 --- a/testsuite/tests/287-function_call_cov/access_to_subp/src/access_to_subp.adb +++ b/testsuite/tests/287-function_call_cov/access_to_subp/src/access_to_subp.adb @@ -1,14 +1,9 @@ pragma Ada_2012; +with Pkg; use Pkg; + procedure Access_To_Subp -- # fun is - type Point is record -- # decl - X, Y : Float; -- # dstmt - end record; -- # dstmt - - function Set (X, Y : Float) return Point is (X, Y); -- # stmt - - function Reset (X, Y : Float) return Point is (0.0, 0.0); -- # stmt type Pt_Acc is access function (X, Y : Float) return Point; -- # decl diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/src/pkg.ads b/testsuite/tests/287-function_call_cov/access_to_subp/src/pkg.ads new file mode 100644 index 000000000..5e855cf8f --- /dev/null +++ b/testsuite/tests/287-function_call_cov/access_to_subp/src/pkg.ads @@ -0,0 +1,13 @@ +pragma Ada_2012; + +package Pkg is + + type Point is record -- # decl + X, Y : Float; -- # decl + end record; -- # decl + + function Set (X, Y : Float) return Point is (X, Y); -- # stmt + + function Reset (X, Y : Float) return Point is (0.0, 0.0); -- # stmt + +end Pkg; diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb index 8b2c3db43..1dff085f1 100644 --- a/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb +++ b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb @@ -11,6 +11,10 @@ end; --# access_to_subp.adb -- /decl/ l+ ## 0 -- /dstmt/ l+ ## 0 --- /stmt/ l+ ## 0 -- /fun/ l+ ## 0 -- /call/ l+ ## 0 + +--# pkg.ads +-- /decl/ l+ ## 0 +-- /dstmt/ l+ ## 0 +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/src/test_not_called.adb b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_not_called.adb index a4c7d7833..acbad33b9 100644 --- a/testsuite/tests/287-function_call_cov/access_to_subp/src/test_not_called.adb +++ b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_not_called.adb @@ -12,6 +12,9 @@ end; --# access_to_subp.adb -- /decl/ l- ## s- -- /dstmt/ l- ## 0 --- /stmt/ l- ## s=><-, f=>s-,f- -- /fun/ l- ## f- -- /call/ l- ## s=>s-, f=>s-,c- + +--# pkg.ads +-- /decl/ l+ ## 0 +-- /stmt/ l- ## s=><-, f=>s-,f- diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/test.opt b/testsuite/tests/287-function_call_cov/access_to_subp/test.opt deleted file mode 100644 index b69bc20bd..000000000 --- a/testsuite/tests/287-function_call_cov/access_to_subp/test.opt +++ /dev/null @@ -1 +0,0 @@ -RTS_ZFP DEAD test uses dynamic code, incompatible with light RTS From 467adea98d5c38a8980dbf96dd7d619191d4961f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 4 Sep 2024 15:32:29 +0000 Subject: [PATCH 0911/1483] instrument-ada_unit.adb: workaround a GNAT bug on overriding null proc --- .../323-overriding-null-proc/main.adb | 9 ++ .../323-overriding-null-proc/pkg.adb | 6 ++ .../323-overriding-null-proc/pkg.ads | 13 +++ .../323-overriding-null-proc/test.py | 29 +++++++ tools/gnatcov/instrument-ada_unit.adb | 83 +++++++++++++------ 5 files changed, 115 insertions(+), 25 deletions(-) create mode 100644 testsuite/tests/instr-cov/323-overriding-null-proc/main.adb create mode 100644 testsuite/tests/instr-cov/323-overriding-null-proc/pkg.adb create mode 100644 testsuite/tests/instr-cov/323-overriding-null-proc/pkg.ads create mode 100644 testsuite/tests/instr-cov/323-overriding-null-proc/test.py diff --git a/testsuite/tests/instr-cov/323-overriding-null-proc/main.adb b/testsuite/tests/instr-cov/323-overriding-null-proc/main.adb new file mode 100644 index 000000000..bdd8e75a0 --- /dev/null +++ b/testsuite/tests/instr-cov/323-overriding-null-proc/main.adb @@ -0,0 +1,9 @@ +with Pkg; use Pkg; + +procedure Main is + Arg : aliased Arg_Type (1); + Object : T; +begin + Object.P1 (Arg); + Object.P2 (Arg'Access); +end Main; diff --git a/testsuite/tests/instr-cov/323-overriding-null-proc/pkg.adb b/testsuite/tests/instr-cov/323-overriding-null-proc/pkg.adb new file mode 100644 index 000000000..84ff70874 --- /dev/null +++ b/testsuite/tests/instr-cov/323-overriding-null-proc/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + + overriding procedure P1 (Self : T; Arg : Arg_Type'Class) is null; + overriding procedure P2 (Self : T; Arg : access Arg_Type'Class) is null; + +end Pkg; diff --git a/testsuite/tests/instr-cov/323-overriding-null-proc/pkg.ads b/testsuite/tests/instr-cov/323-overriding-null-proc/pkg.ads new file mode 100644 index 000000000..864bb9040 --- /dev/null +++ b/testsuite/tests/instr-cov/323-overriding-null-proc/pkg.ads @@ -0,0 +1,13 @@ +package Pkg is + + type Arg_Type (I : Integer) is tagged limited null record; + + type I_Type is interface; + procedure P1 (Self : I_Type; Arg : Arg_Type'Class) is abstract; + procedure P2 (Self : I_Type; Arg : access Arg_Type'Class) is abstract; + + type T is new I_Type with null record; + overriding procedure P1 (Self : T; Arg : Arg_Type'Class); + overriding procedure P2 (Self : T; Arg : access Arg_Type'Class); + +end Pkg; diff --git a/testsuite/tests/instr-cov/323-overriding-null-proc/test.py b/testsuite/tests/instr-cov/323-overriding-null-proc/test.py new file mode 100644 index 000000000..f51c472c7 --- /dev/null +++ b/testsuite/tests/instr-cov/323-overriding-null-proc/test.py @@ -0,0 +1,29 @@ +""" +Check that GNAT can compile instrumented code for overriding null procedures +that have a separate declaration. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {4, 5, 7, 8}}, + "pkg.ads.xcov": {"+": {3, 5, 6, 7, 9}}, + "pkg.adb.xcov": {"+": {3, 4}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 8ff4bffe8..a3255be00 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -81,6 +81,13 @@ package body Instrument.Ada_Unit is when LALCO.Unit_Body => GNATCOLL.Projects.Unit_Body, when LALCO.Unit_Specification => GNATCOLL.Projects.Unit_Spec); + function Referenced_Attribute (N : Ada_Node'Class) return Text_Type + is (if N.Kind = Ada_Attribute_Ref + then Canonicalize (N.As_Attribute_Ref.F_Attribute.Text).Symbol + else ""); + -- If ``N`` is an attribute reference, return the canonicalized name for + -- that attribute. Return the empty string otherwise. + ------------------------------- -- Create_Context_Instrument -- ------------------------------- @@ -2127,33 +2134,60 @@ package body Instrument.Ada_Unit is -- not null access function -- (Line : in out [formalX]) -- return [formalY]; + -- + -- As a workaround for a GNAT bug (see eng/toolchain/gnat#1048), we + -- also need to turn X'Class into [formalX]'Class. - if TE.Kind = Ada_Anonymous_Type then - declare - TD : constant Type_Def := - TE.As_Anonymous_Type.F_Type_Decl.F_Type_Def; - begin - -- There are two kinds of anonymous types: "simple" access - -- types, and access to subprogram types. + case TE.Kind is + when Ada_Anonymous_Type => + declare + TD : constant Type_Def := + TE.As_Anonymous_Type.F_Type_Decl.F_Type_Def; + begin + -- There are two kinds of anonymous types: "simple" access + -- types, and access to subprogram types. - case TD.Kind is - when Ada_Type_Access_Def => - return Gen_Type_Expr_For_Simple_Access_Type - (TD.As_Type_Access_Def); + case TD.Kind is + when Ada_Type_Access_Def => + return Gen_Type_Expr_For_Simple_Access_Type + (TD.As_Type_Access_Def); - when Ada_Access_To_Subp_Def => - return Gen_Type_Expr_For_Access_To_Subp - (TD.As_Access_To_Subp_Def); + when Ada_Access_To_Subp_Def => + return Gen_Type_Expr_For_Access_To_Subp + (TD.As_Access_To_Subp_Def); - when others => - raise Program_Error with - "unexpected anonymous type definition: " & TD.Kind'Image; - end case; - end; + when others => + raise Program_Error with + "unexpected anonymous type definition: " + & TD.Kind'Image; + end case; + end; - else - return Make_Formal_Type (TE); - end if; + when Ada_Subtype_Indication => + declare + SI : constant Subtype_Indication := TE.As_Subtype_Indication; + begin + if Referenced_Attribute (SI.F_Name) = "class" then + declare + Result : constant Node_Rewriting_Handle := + Clone (Handle (SI)); + Attr_Prefix : constant Node_Rewriting_Handle := + Child + (Result, + (Member_Refs.Subtype_Indication_F_Name, + Member_Refs.Attribute_Ref_F_Prefix)); + begin + Replace (Attr_Prefix, Make_Formal_Type (SI)); + return Result; + end; + end if; + end; + + when others => + null; + end case; + + return Make_Formal_Type (TE); end Gen_Type_Expr; ------------------------------------------ @@ -3077,9 +3111,8 @@ package body Instrument.Ada_Unit is function Process_Node (N : Ada_Node'Class) return Visit_Status is begin - if N.Kind = Ada_Attribute_Ref - and then Canonicalize (N.As_Attribute_Ref.F_Attribute.Text).Symbol - in "access" | "unchecked_access" | "unrestricted_access" + if Referenced_Attribute (N) + in "access" | "unchecked_access" | "unrestricted_access" then return Stop; end if; From 002eddad48aa836d85bab89a4970cdf18a717387 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 6 Sep 2024 08:04:22 +0000 Subject: [PATCH 0912/1483] instr-cov/323-overriding-null-proc: adjust expectations for bin traces --- testsuite/tests/instr-cov/323-overriding-null-proc/test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/instr-cov/323-overriding-null-proc/test.py b/testsuite/tests/instr-cov/323-overriding-null-proc/test.py index f51c472c7..af7c09c28 100644 --- a/testsuite/tests/instr-cov/323-overriding-null-proc/test.py +++ b/testsuite/tests/instr-cov/323-overriding-null-proc/test.py @@ -21,9 +21,10 @@ "xcov", { "main.adb.xcov": {"+": {4, 5, 7, 8}}, - "pkg.ads.xcov": {"+": {3, 5, 6, 7, 9}}, + "pkg.ads.xcov": {}, "pkg.adb.xcov": {"+": {3, 4}}, }, + discard_empty=False, ) thistest.result() From 73405bc08043815cb61afd24ce3fc49ff088b52c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 5 Sep 2024 13:43:03 +0000 Subject: [PATCH 0913/1483] Add support for --print-gpr-registry --- .../tests/308-print-gpr-registry/test.py | 100 +++++++++++++ tools/gnatcov/command_line.ads | 59 ++++++-- tools/gnatcov/gnatcov_bits_specific.adb | 21 +++ tools/gnatcov/project.adb | 137 ++++++++++++++++++ 4 files changed, 303 insertions(+), 14 deletions(-) create mode 100644 testsuite/tests/308-print-gpr-registry/test.py diff --git a/testsuite/tests/308-print-gpr-registry/test.py b/testsuite/tests/308-print-gpr-registry/test.py new file mode 100644 index 000000000..30b3b2e24 --- /dev/null +++ b/testsuite/tests/308-print-gpr-registry/test.py @@ -0,0 +1,100 @@ +""" +Check that the special --print-gpr-registry command line switch works as +expected. + +Specifically, run "gnatcov --print-gpr-registry" with the 4 possible format +options and check that they have roughly the same content (same summary: list +of attributes). +""" + +import json + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import xcov + + +tmp = Wdir("tmp_") + + +def summarize_json(f): + result = [] + doc = json.load(f) + for pkg in doc["packages"]: + for attr in pkg["attributes"]: + result.append(f"{pkg['package_name']}.{attr['attribute_name']}") + result.sort() + return "\n".join(result) + + +def summarize_text(f): + result = [] + for line in f: + line = line.strip() + if not line: + continue + elif " " not in line: + pkg = line + elif ( + line.endswith(": list") + or line.endswith(": single") + or line.endswith(": list, indexed") + or line.endswith(": single, indexed") + ): + attr = line.split()[0][:-1] + result.append(f"{pkg}.{attr}") + result.sort() + return "\n".join(result) + + +baseline = ( + "Coverage.Excluded_Routines" + "\nCoverage.Excluded_Routines_List" + "\nCoverage.Excluded_Units" + "\nCoverage.Excluded_Units_List" + "\nCoverage.Ignored_Source_Files" + "\nCoverage.Ignored_Source_Files_List" + "\nCoverage.Routines" + "\nCoverage.Routines_List" + "\nCoverage.Switches" + "\nCoverage.Units" + "\nCoverage.Units_List" +) + + +for fmt, summarize in [ + (None, summarize_json), + ("text", summarize_text), + ("json", summarize_json), + ("json-compact", summarize_json), +]: + thistest.log(f"== {fmt} ==") + + args = ["--print-gpr-registry"] + if fmt is None: + out_filename = "default.txt" + else: + args.append(f"--gpr-registry-format={fmt}") + out_filename = f"{fmt}.txt" + + xcov(args, out=out_filename, auto_target_args=False) + + with open(out_filename) as f: + actual = summarize(f) + thistest.fail_if_not_equal("Output of " + " ".join(args), baseline, actual) + + +thistest.log("== invalid ==") +args = ["--print-gpr-registry", "--gpr-registry-format=invalid"] +p = xcov( + args, out="invalid.txt", auto_target_args=False, register_failure=False +) +thistest.fail_if_not_equal("gnatcov exit code", 1, p.status) +thistest.fail_if_no_match( + "Output of " + " ".join(args), + "^.*gnatcov.*: Bad GPR registry format: invalid$", + contents_of("invalid.txt").strip(), +) + + +thistest.result() diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index fc82d4271..129a8cf3f 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -16,6 +16,8 @@ -- of the license. -- ------------------------------------------------------------------------------ +with GPR2.Options; + with Argparse; with Coverage_Options; use Coverage_Options; @@ -29,6 +31,7 @@ package Command_Line is Cmd_Version, Cmd_List_Logs, + Cmd_Print_GPR_Registry, Cmd_Run, Cmd_Convert, @@ -143,7 +146,8 @@ package Command_Line is Opt_Ada_Preprocessor_Data, Opt_Project_Name, Opt_Source_Root, - Opt_Db); + Opt_Db, + Opt_GPR_Registry_Format); -- Set of string options we support. More complete descriptions below. type String_List_Options is @@ -205,12 +209,17 @@ package Command_Line is Description => "Display the version.", Internal => False), - Cmd_List_Logs => Create + Cmd_List_Logs => Create (Name => "list-logs", Pattern => "", Description => "Dump the list of GNATcov available logs (GNATCOLL traces).", Internal => True), + Cmd_Print_GPR_Registry => Create + (Name => GPR2.Options.Print_GPR_Registry_Option, + Pattern => "", + Description => "Print the GPR registry.", + Internal => True), Cmd_Run => Create (Name => "run", @@ -608,7 +617,8 @@ package Command_Line is (Long_Name => "--relocate-build-tree", Help => "Relocate object, library and exec directories in the" & " current directory.", - Commands => (Cmd_All_Setups => False, others => True), + Commands => (Cmd_All_Setups | Cmd_Print_GPR_Registry => False, + others => True), Internal => False), Opt_Warnings_As_Errors => Create @@ -633,7 +643,8 @@ package Command_Line is Pattern => "[GPR]", Help => "Use GPR as root project to locate SCOs, select" & " units to analyze and find default options.", - Commands => (Cmd_Setup + Commands => (Cmd_Print_GPR_Registry + | Cmd_Setup | Cmd_Setup_Integration | Cmd_Instrument_Source | Cmd_Instrument_Main => False, @@ -647,7 +658,9 @@ package Command_Line is & " designates the topmost directory of the tree of" & " projects. By default the root project's directory" & " is used.", - Commands => (Cmd_All_Setups => False, others => True), + Commands => (Cmd_Print_GPR_Registry + | Cmd_All_Setups => False, + others => True), At_Most_Once => True, Internal => False), Opt_Subdirs => Create @@ -656,7 +669,9 @@ package Command_Line is Help => "When using project files, look for ALI/SID files in" & " the provided SUBDIR of the projects' build" & " directory.", - Commands => (Cmd_All_Setups => False, others => True), + Commands => (Cmd_Print_GPR_Registry + | Cmd_All_Setups => False, + others => True), At_Most_Once => False, Internal => False), Opt_Target => Create @@ -673,7 +688,9 @@ package Command_Line is & " ""Target""/""Runtime"" attributes. It is also" & " needed for ""run"" commands without a project" & " file.", - Commands => (Cmd_Setup_Integration => False, others => True), + Commands => (Cmd_Print_GPR_Registry + | Cmd_Setup_Integration => False, + others => True), At_Most_Once => True, Internal => False), Opt_Runtime => Create @@ -683,7 +700,9 @@ package Command_Line is & " to build the analyzed programs. If project files" & " don't already set the runtime, this is required" & " for correct project files processing.", - Commands => (Cmd_Setup_Integration => False, others => True), + Commands => (Cmd_Print_GPR_Registry + | Cmd_Setup_Integration => False, + others => True), At_Most_Once => True, Internal => False), Opt_Config => Create @@ -692,6 +711,7 @@ package Command_Line is Help => "Specify a configuration project file name. If" & " passed, this file must exist and neither --target" & " nor --RTS must be present.", + Commands => (Cmd_Print_GPR_Registry => False, others => True), At_Most_Once => True, Internal => False), Opt_Output => Create @@ -1171,12 +1191,20 @@ package Command_Line is Pattern => "DIR", Help => "Parse DIR as an additional GPR knowledge base directory.", - Commands => (Cmd_Setup_Integration + Commands => (Cmd_Print_GPR_Registry + | Cmd_Setup_Integration | Cmd_Instrument_Source | Cmd_Instrument_Main => False, others => True), At_Most_Once => True, - Internal => False) - ); + Internal => False), + + Opt_GPR_Registry_Format => Create + (Long_Name => "--gpr-registry-format", + Pattern => "FORMAT", + Help => "Format for the printed GPR registry.", + Commands => (Cmd_Print_GPR_Registry => True, others => False), + At_Most_Once => False, + Internal => True)); String_List_Infos : constant String_List_Option_Info_Array := (Opt_Log => Create @@ -1191,7 +1219,8 @@ package Command_Line is Pattern => "[GPR|@LISTFILE]", Help => "Focus on specific projects within the transitive" & " closure reachable from the root designated by -P.", - Commands => (Cmd_Setup + Commands => (Cmd_Print_GPR_Registry + | Cmd_Setup | Cmd_Setup_Integration | Cmd_Instrument_Source | Cmd_Instrument_Main => False, @@ -1211,7 +1240,9 @@ package Command_Line is (Short_Name => "-X", Pattern => "[NAME]=[VALUE]", Help => "Define a scenario variable for project files.", - Commands => (Cmd_All_Setups => False, others => True), + Commands => (Cmd_Print_GPR_Registry + | Cmd_All_Setups => False, + others => True), Internal => False), Opt_Cargs => Create (Long_Name => "--cargs", @@ -1452,7 +1483,7 @@ package Command_Line is Help => "List of compiler drivers for which we should generate wrappers." & " Supported compilers are: gcc, g++.", - Commands => (others => True), + Commands => (Cmd_Print_GPR_Registry => False, others => True), Internal => True) ); diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 215eb5f3b..1edb50f54 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -30,6 +30,8 @@ with GNAT.Strings; use GNAT.Strings; with System.Multiprocessors; +with GPR2.Project.Registry.Exchange; + with Snames; with Annotations.Cobertura; @@ -1236,6 +1238,25 @@ begin when Cmd_List_Logs => Logging.Print_List; + when Cmd_Print_GPR_Registry => + declare + use GPR2.Project.Registry.Exchange; + Format_Arg : constant String := + Value (Args, Opt_GPR_Registry_Format, "json"); + Format : Export_Format; + begin + if Format_Arg = "text" then + Format := K_TEXT; + elsif Format_Arg = "json" then + Format := K_JSON; + elsif Format_Arg = "json-compact" then + Format := K_JSON_COMPACT; + else + Fatal_Error ("Bad GPR registry format: " & Format_Arg); + end if; + Export (Format => Format, Output => Put'Access); + end; + when Cmd_Disp_Routines => declare Mode_Exclude : Boolean := False; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index b280659e4..a3e7c97be 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -28,6 +28,10 @@ with GNAT.Regexp; with GNATCOLL.Traces; with GNATCOLL.Projects.Aux; with GNATCOLL.VFS; use GNATCOLL.VFS; +with GPR2.Project.Registry.Attribute; +with GPR2.Project.Registry.Attribute.Description; +with GPR2.Project.Registry.Pack; +with GPR2.Project.Registry.Pack.Description; with Inputs; use Inputs; with Instrument; use Instrument; @@ -47,6 +51,8 @@ package body Project is Coverage_Package : aliased String := "coverage"; Coverage_Package_List : aliased String_List := (1 => Coverage_Package'Access); + GPR2_Coverage_Package : constant GPR2.Package_Id := + GPR2."+" (GPR2.Name_Type (Coverage_Package)); type Attribute is (Units, @@ -70,6 +76,7 @@ package body Project is function "+" (A : Attribute) return String; function "+" (A : String_Attribute) return Attribute_Pkg_String; function "+" (A : List_Attribute) return Attribute_Pkg_List; + function "+" (A : Attribute) return GPR2.Q_Attribute_Id; -- Build identifiers for attributes in package Coverage procedure Iterate_Source_Files @@ -305,6 +312,11 @@ package body Project is return Build (Coverage_Package, A'Img); end "+"; + function "+" (A : Attribute) return GPR2.Q_Attribute_Id is + begin + return (GPR2_Coverage_Package, GPR2."+" (GPR2.Name_Type (A'Image))); + end "+"; + -------------- -- Add_Unit -- -------------- @@ -1716,4 +1728,129 @@ package body Project is end case; end Source_Suffix; + -- Register the Coverage package and its attributes to GPR2 + + package GPR2_RP renames GPR2.Project.Registry.Pack; + package GPR2_RA renames GPR2.Project.Registry.Attribute; +begin + GPR2_RP.Add (GPR2_Coverage_Package, GPR2_RP.Everywhere); + GPR2_RP.Description.Set_Package_Description + (GPR2_Coverage_Package, + "Specifies options used when calling the 'gnatcov' program."); + + GPR2_RA.Add + (Name => +Units, + Index_Type => GPR2_RA.No_Index, + Value => GPR2_RA.List, + Value_Case_Sensitive => True, + Is_Allowed_In => GPR2_RA.Everywhere); + GPR2_RA.Description.Set_Attribute_Description + (+Units, + "Names of units of interest to include in source coverage analysis."); + + GPR2_RA.Add + (Name => +Excluded_Units, + Index_Type => GPR2_RA.No_Index, + Value => GPR2_RA.List, + Value_Case_Sensitive => True, + Is_Allowed_In => GPR2_RA.Everywhere); + GPR2_RA.Description.Set_Attribute_Description + (+Excluded_Units, + "Names of units of interest to exclude from source coverage analysis."); + + GPR2_RA.Add + (Name => +Routines, + Index_Type => GPR2_RA.No_Index, + Value => GPR2_RA.List, + Value_Case_Sensitive => True, + Is_Allowed_In => GPR2_RA.Everywhere); + GPR2_RA.Description.Set_Attribute_Description + (+Routines, + "Symbol names for the routines to include in object coverage."); + + GPR2_RA.Add + (Name => +Excluded_Routines, + Index_Type => GPR2_RA.No_Index, + Value => GPR2_RA.List, + Value_Case_Sensitive => True, + Is_Allowed_In => GPR2_RA.Everywhere); + GPR2_RA.Description.Set_Attribute_Description + (+Excluded_Routines, + "Symbol names for the routines to exclude from object coverage."); + + GPR2_RA.Add + (Name => +Ignored_Source_Files, + Index_Type => GPR2_RA.No_Index, + Value => GPR2_RA.List, + Value_Case_Sensitive => True, + Is_Allowed_In => GPR2_RA.Everywhere); + GPR2_RA.Description.Set_Attribute_Description + (+Ignored_Source_Files, + "Source file names to exclude from source coverage analysis."); + + GPR2_RA.Add + (Name => +Switches, + Index_Type => GPR2_RA.String_Index, + Value => GPR2_RA.List, + Value_Case_Sensitive => True, + Is_Allowed_In => GPR2_RA.Everywhere); + GPR2_RA.Description.Set_Attribute_Description + (+Switches, + "Command line switches to automatically include when running 'gnatcov'," + & " indexed by gnatcov sub-command (""instrument"", ""coverage"", ...)"); + + GPR2_RA.Add + (Name => +Units_List, + Index_Type => GPR2_RA.No_Index, + Value => GPR2_RA.Single, + Value_Case_Sensitive => True, + Is_Allowed_In => GPR2_RA.Everywhere); + GPR2_RA.Description.Set_Attribute_Description + (+Units_List, + "Text file that contains names of units of interest to include in source" + & " coverage analysis."); + + GPR2_RA.Add + (Name => +Excluded_Units_List, + Index_Type => GPR2_RA.No_Index, + Value => GPR2_RA.Single, + Value_Case_Sensitive => True, + Is_Allowed_In => GPR2_RA.Everywhere); + GPR2_RA.Description.Set_Attribute_Description + (+Excluded_Units_List, + "Text file that contains names of units of interest to exclude from" + & " source coverage analysis."); + + GPR2_RA.Add + (Name => +Routines_List, + Index_Type => GPR2_RA.No_Index, + Value => GPR2_RA.Single, + Value_Case_Sensitive => True, + Is_Allowed_In => GPR2_RA.Everywhere); + GPR2_RA.Description.Set_Attribute_Description + (+Routines_List, + "Text file that contains symbol names for the routines to include in" + & " object coverage."); + + GPR2_RA.Add + (Name => +Excluded_Routines_List, + Index_Type => GPR2_RA.No_Index, + Value => GPR2_RA.Single, + Value_Case_Sensitive => True, + Is_Allowed_In => GPR2_RA.Everywhere); + GPR2_RA.Description.Set_Attribute_Description + (+Excluded_Routines_List, + "Text file that contains symbol names for the routines to exclude from" + & " object coverage."); + + GPR2_RA.Add + (Name => +Ignored_Source_Files_List, + Index_Type => GPR2_RA.No_Index, + Value => GPR2_RA.Single, + Value_Case_Sensitive => True, + Is_Allowed_In => GPR2_RA.Everywhere); + GPR2_RA.Description.Set_Attribute_Description + (+Ignored_Source_Files_List, + "Text file that contains source file names to exclude from source" + & " coverage analysis."); end Project; From f884b607973504f9bf0e095d835be3532a15e481 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 16 Sep 2024 16:36:19 +0200 Subject: [PATCH 0914/1483] setup-integration: disable Ada Disable Ada for integrated instrumentation as this is not supported. --- .../integrated_instrumentation/setup/Makefile | 11 +++ .../integrated_instrumentation/setup/pkg.c | 5 ++ .../integrated_instrumentation/setup/test.c | 8 +++ .../integrated_instrumentation/setup/test.py | 72 +++++++++++++++++++ tools/gnatcov/gnatcov_bits_specific.adb | 6 ++ 5 files changed, 102 insertions(+) create mode 100644 testsuite/tests/integrated_instrumentation/setup/Makefile create mode 100644 testsuite/tests/integrated_instrumentation/setup/pkg.c create mode 100644 testsuite/tests/integrated_instrumentation/setup/test.c create mode 100644 testsuite/tests/integrated_instrumentation/setup/test.py diff --git a/testsuite/tests/integrated_instrumentation/setup/Makefile b/testsuite/tests/integrated_instrumentation/setup/Makefile new file mode 100644 index 000000000..303dc65f8 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/setup/Makefile @@ -0,0 +1,11 @@ +CC=gcc +OBJ = pkg.o test.o + +%.o: %.c + $(CC) -c -o $@ $< + +test: $(OBJ) + $(CC) -o $@ $^ + +clean: + rm -f *.o test diff --git a/testsuite/tests/integrated_instrumentation/setup/pkg.c b/testsuite/tests/integrated_instrumentation/setup/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/setup/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/setup/test.c b/testsuite/tests/integrated_instrumentation/setup/test.c new file mode 100644 index 000000000..84fcd4703 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/setup/test.c @@ -0,0 +1,8 @@ +extern int foo (); + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/setup/test.py b/testsuite/tests/integrated_instrumentation/setup/test.py new file mode 100644 index 000000000..7cf2cf9f8 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/setup/test.py @@ -0,0 +1,72 @@ +""" +Regression test for integrated instrumentation approach, using an +instrumentation runtime build and installed with `gnatcov setup +--restricted-to-languages=c` prior. The setup-integration command used to crash +with a `Could not load the coverage runtime project gnatcov_rts` message. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "pkg.c"), ".") + +# Install the instrumentation runtime with `--restricted-to-languages=C` +xcov( + [ + "setup", + "--prefix=install", + "--restricted-to-languages=c", + "--install-name=gnatcov_rts_c", + ] +) +env.add_search_path("GPR_PROJECT_PATH", "install/share/gpr") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'pkg.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + "--runtime-project=gnatcov_rts_c", + ], + auto_config_args=False, +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make", "test"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=pkg.c.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports(".", {"pkg.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 1edb50f54..1ed979b3f 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1391,6 +1391,12 @@ begin end; when Cmd_Setup_Integration => + + -- The integrated instrumentation scheme does not support Ada, so + -- disable it. + + Src_Enabled_Languages (Ada_Language) := False; + declare -- Try to load the setup config from metadata installed with -- instrumentation runtime, and from there, decode the --dump-* From a9ceaf51dfe6288eea21e5029812557b7c24fb2e Mon Sep 17 00:00:00 2001 From: Rowan Walshe Date: Tue, 17 Sep 2024 15:43:38 +0100 Subject: [PATCH 0915/1483] Fix doc build warnings Relates to: eng/das/fuzz/gnatfuzz#798 --- doc/gnatcov/cov_source.rst | 2 +- doc/gnatcov/disable_cov.rst | 4 ++-- doc/gnatcov/gnatcov_part.rst | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index c132d2eaf..ac04ba195 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -1556,7 +1556,7 @@ as `--level=...+fun_call` where `...` is one of `stmt`, `stmt+decision`, same time. Core notions and Reporting (:cmd-option:`--level=...+fun_call`) ----------------------------------------------------------- +--------------------------------------------------------------- |gcv| performs Function and Call Coverage assessments with the :cmd-option:`--level=...+fun_call` command line option. The assessment diff --git a/doc/gnatcov/disable_cov.rst b/doc/gnatcov/disable_cov.rst index b71bd3000..a7735533e 100644 --- a/doc/gnatcov/disable_cov.rst +++ b/doc/gnatcov/disable_cov.rst @@ -14,8 +14,8 @@ that may or may not expand according to the build configuration at use. This mechanism only works when using source traces. -Defining :term:`Disabled Coverage Regions ` -===================================================================== +Defining Disabled Coverage Regions +================================== :dfn:`Disabled Coverage Regions` are lexical sections of sources in which coverage analysis is fully disabled. diff --git a/doc/gnatcov/gnatcov_part.rst b/doc/gnatcov/gnatcov_part.rst index 8c03e8529..4b3f0e1e7 100644 --- a/doc/gnatcov/gnatcov_part.rst +++ b/doc/gnatcov/gnatcov_part.rst @@ -16,3 +16,4 @@ GNATcoverage User's Guide gpr gps glossary + appendix From 31b79b7f9179ca4aea0d2393f9adf6d9c1a41259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 18 Sep 2024 09:44:11 +0200 Subject: [PATCH 0916/1483] Doc: Move bin-traces specific apendix to the bin-traces appendix --- doc/gnatcov/appendix.rst | 105 ------------------------------- doc/gnatcov/bin_limitations.rst | 103 ++++++++++++++++++++++++++++++ doc/gnatcov/gnatcov_bin_part.rst | 1 + 3 files changed, 104 insertions(+), 105 deletions(-) create mode 100644 doc/gnatcov/bin_limitations.rst diff --git a/doc/gnatcov/appendix.rst b/doc/gnatcov/appendix.rst index 0a26607e4..34f5509b0 100644 --- a/doc/gnatcov/appendix.rst +++ b/doc/gnatcov/appendix.rst @@ -17,108 +17,3 @@ Sample html annotated source .. image:: sample_sc_html_unit.png :scale: 80% - - -.. _target_specific_notes: - -Target specific points of note with Binary traces -================================================= - -The following list summarizes points of note for each target where some -aspects of the build/execution/analysis process depart from the general -instructions. - -For **cross** configurations in general: - -- Need to convey the target to |gcvrun|, either with a :cmd-option:`--target` - switch or a ``Target`` project file attribute; - -- Need to convey the target and Ada runtime when using project files - to state units of interest, for |gcvcov|, |gcvins| or |gcvrun|. See - :ref:`sunits`, :ref:`gpr_context`. - -For **powerpc-vxworks6**: - -- Need to compile with -gno-strict-dwarf -mlongcall for source coverage - analysis; - -- Need to add a --kernel argument on |gcvrun|; - -- The provided kernel has to be augmented with a specific module - for gnatcov purposes. Please refer to the |gem| documentation for this - part of the process; - -- Support for the ``kernel`` Ada RTS and Downloadable Kernel Modules only. - -.. _known_limitations: - -Known Limitations with Binary traces -==================================== - -Incomplete statement coverage on lines with multiple statements ---------------------------------------------------------------- - -On lines with multiple statements, the tool may not be able to infer -accurate statement coverage results for each individual statement. The -tool emits explicit diagnostics in this case. - -In :cmd-option:`=report` outputs (with :cmd-option:`--annotate=report`), this -translates as a statement coverage violation like:: - - : multiple statements on line, unable to establish full statement coverage - -where is a source-filename:line:column source location of the -problematic line. - -In annotated sources kinds of outputs, this materializes as '!' note indicating -partial coverage on the affected lines, with the :cmd-option:`=report` violation -text quoted above available as part of the line extra-details expanded on demand -(:cmd-option:`=html` and :cmd-option:`xcov+` output formats). - -.. _mcdc-limitations: - -MCDC inaccuracies with interrupts and multi-threaded applications ------------------------------------------------------------------ - -There is one limitation in |gcp| with respect to MCDC assessments from binary -traces: potential inaccuracies in results reported for particular decisions -when these decisions are evaluated concurrently by different threads or mixed -with interrupt processing in bareboard configurations. - -Technically, the decisions of concern are those for which the associated -binary decision diagram is not a tree, that is, those with at least one -condition node joining several possible evaluation paths. - -The code sample below illustrates the simplest possible problematic decision -and the following figure depicts the corresponding Binary Decision Diagram -(commonly abbreviated as *BDD*), which states how sequence of operand -evaluations, starting from the left, eventually lead to the expression -outcome, here on the right: - -.. code-block:: ada - - function Mp (A, B, C : Boolean) return Boolean is - begin - return (A or else B) and then C; - end; - -.. figure:: fig_multipath-bdd.* - :align: center - - BDD for ``(A or else B) and then C``, not a tree - -The expression BDD is indeed not a tree, as the node representing the -evaluation of C is reachable either directly from A, when A is True, or -via B when A is False. - -According to measures performed on a few large real code bases, occurrences of -such decisions are statistically rare. |gcv| can report about them on demand, -thanks to the :command:`scan-decisions` command together with the the set of -coverage obligations to examine. Below is an excerpt of a an execution for a -project which encompasses this function, where we see that |gcv| provides the -source location of conditions rechable through multiple paths:: - - gnatcov scan-decisions -Pmytest.gpr - ... - *** mp.adb:4:33: warning: condition is reachable through multiple paths - diff --git a/doc/gnatcov/bin_limitations.rst b/doc/gnatcov/bin_limitations.rst new file mode 100644 index 000000000..4365c2cb2 --- /dev/null +++ b/doc/gnatcov/bin_limitations.rst @@ -0,0 +1,103 @@ + +.. _target_specific_notes: + +Target specific points of note with Binary traces +================================================= + +The following list summarizes points of note for each target where some +aspects of the build/execution/analysis process depart from the general +instructions. + +For **cross** configurations in general: + +- Need to convey the target to |gcvrun|, either with a :cmd-option:`--target` + switch or a ``Target`` project file attribute; + +- Need to convey the target and Ada runtime when using project files + to state units of interest, for |gcvcov|, |gcvins| or |gcvrun|. See + :ref:`sunits`, :ref:`gpr_context`. + +For **powerpc-vxworks6**: + +- Need to compile with -gno-strict-dwarf -mlongcall for source coverage + analysis; + +- Need to add a --kernel argument on |gcvrun|; + +- The provided kernel has to be augmented with a specific module + for gnatcov purposes. Please refer to the |gem| documentation for this + part of the process; + +- Support for the ``kernel`` Ada RTS and Downloadable Kernel Modules only. + +.. _known_limitations: + +Known Limitations with Binary traces +==================================== + +Incomplete statement coverage on lines with multiple statements +--------------------------------------------------------------- + +On lines with multiple statements, the tool may not be able to infer +accurate statement coverage results for each individual statement. The +tool emits explicit diagnostics in this case. + +In :cmd-option:`=report` outputs (with :cmd-option:`--annotate=report`), this +translates as a statement coverage violation like:: + + : multiple statements on line, unable to establish full statement coverage + +where is a source-filename:line:column source location of the +problematic line. + +In annotated sources kinds of outputs, this materializes as '!' note indicating +partial coverage on the affected lines, with the :cmd-option:`=report` violation +text quoted above available as part of the line extra-details expanded on demand +(:cmd-option:`=html` and :cmd-option:`xcov+` output formats). + +.. _mcdc-limitations: + +MCDC inaccuracies with interrupts and multi-threaded applications +----------------------------------------------------------------- + +There is one limitation in |gcp| with respect to MCDC assessments from binary +traces: potential inaccuracies in results reported for particular decisions +when these decisions are evaluated concurrently by different threads or mixed +with interrupt processing in bareboard configurations. + +Technically, the decisions of concern are those for which the associated +binary decision diagram is not a tree, that is, those with at least one +condition node joining several possible evaluation paths. + +The code sample below illustrates the simplest possible problematic decision +and the following figure depicts the corresponding Binary Decision Diagram +(commonly abbreviated as *BDD*), which states how sequence of operand +evaluations, starting from the left, eventually lead to the expression +outcome, here on the right: + +.. code-block:: ada + + function Mp (A, B, C : Boolean) return Boolean is + begin + return (A or else B) and then C; + end; + +.. figure:: fig_multipath-bdd.* + :align: center + + BDD for ``(A or else B) and then C``, not a tree + +The expression BDD is indeed not a tree, as the node representing the +evaluation of C is reachable either directly from A, when A is True, or +via B when A is False. + +According to measures performed on a few large real code bases, occurrences of +such decisions are statistically rare. |gcv| can report about them on demand, +thanks to the :command:`scan-decisions` command together with the the set of +coverage obligations to examine. Below is an excerpt of a an execution for a +project which encompasses this function, where we see that |gcv| provides the +source location of conditions rechable through multiple paths:: + + gnatcov scan-decisions -Pmytest.gpr + ... + *** mp.adb:4:33: warning: condition is reachable through multiple paths diff --git a/doc/gnatcov/gnatcov_bin_part.rst b/doc/gnatcov/gnatcov_bin_part.rst index 34dfeb1b8..e9c3a9e8c 100644 --- a/doc/gnatcov/gnatcov_bin_part.rst +++ b/doc/gnatcov/gnatcov_bin_part.rst @@ -11,3 +11,4 @@ Appendix A. Using GNATcoverage Binary Traces cov_metrics bin_gps bin_convert + bin_limitations From 59d818445fdc5cbf998011cf7f68f7e196bf10f4 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 17 Sep 2024 14:34:39 +0000 Subject: [PATCH 0917/1483] integrated_instrumentation/setup: fix a typo --- testsuite/tests/integrated_instrumentation/setup/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/integrated_instrumentation/setup/test.py b/testsuite/tests/integrated_instrumentation/setup/test.py index 7cf2cf9f8..1c698d09e 100644 --- a/testsuite/tests/integrated_instrumentation/setup/test.py +++ b/testsuite/tests/integrated_instrumentation/setup/test.py @@ -1,6 +1,6 @@ """ Regression test for integrated instrumentation approach, using an -instrumentation runtime build and installed with `gnatcov setup +instrumentation runtime built and installed with `gnatcov setup --restricted-to-languages=c` prior. The setup-integration command used to crash with a `Could not load the coverage runtime project gnatcov_rts` message. """ From be9733289ef289d1539575d122970fe983ba0448 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 17 Sep 2024 14:34:55 +0000 Subject: [PATCH 0918/1483] integrated_instrumentation/setup: adjust for x86-linux Not passing --config to "gnatcov setup-integration" is necessary to trigger the original bug, however this command does not accept --target: let GPR code automatically guess the native target (32bit vs 64bit) from the toolchain available in the environment. --- testsuite/tests/integrated_instrumentation/setup/test.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/integrated_instrumentation/setup/test.py b/testsuite/tests/integrated_instrumentation/setup/test.py index 1c698d09e..8725f1b4f 100644 --- a/testsuite/tests/integrated_instrumentation/setup/test.py +++ b/testsuite/tests/integrated_instrumentation/setup/test.py @@ -35,7 +35,11 @@ ) env.add_search_path("GPR_PROJECT_PATH", "install/share/gpr") -# Then, setup the instrumentation process +# Then, setup the instrumentation process. Do not pass --config, as that this +# was necessary to reproduce the original bug. Do not pass --target neither, as +# "gnatcov setup-integration" does not support it: let GPR code pick up the +# right native compiler from the environment and thus correctly guess the +# target. xcov( [ "setup-integration", @@ -46,6 +50,7 @@ "--runtime-project=gnatcov_rts_c", ], auto_config_args=False, + auto_target_args=False, ) # Shadow the compiler driver with the generated wrapper From 447df797989e6a266906b753c85022071a17fe1d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 11 Sep 2024 14:50:15 +0200 Subject: [PATCH 0919/1483] examples/support/Makefile.common: minor reformatting --- tools/gnatcov/examples/support/Makefile.common | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/gnatcov/examples/support/Makefile.common b/tools/gnatcov/examples/support/Makefile.common index c9340cd95..13c33cb2f 100644 --- a/tools/gnatcov/examples/support/Makefile.common +++ b/tools/gnatcov/examples/support/Makefile.common @@ -1,4 +1,3 @@ - # This file contains the common definitions used by all other Makefiles. # ========================================================== @@ -82,4 +81,3 @@ BUILDER=gprbuild -aP ../support $(GPRBUILD_TARGETARGS) MKDIR=mkdir -p RM=rm CP=cp - From f97e328e1039ea0528cc9d46e714a163063f9d5c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 18 Sep 2024 15:41:27 +0200 Subject: [PATCH 0920/1483] Remove the "branch_traces" example This example exercises object coverage: there is no known use of this feature outside of AdaCore, and it is not supported with source traces. --- tools/gnatcov/examples/branch_traces/Makefile | 9 ------- .../examples/branch_traces/branch_traces.gpr | 6 ----- .../examples/branch_traces/src/robot.adb | 25 ------------------- .../examples/branch_traces/src/robot.ads | 19 -------------- .../examples/branch_traces/src/support.adb | 16 ------------ .../examples/branch_traces/src/support.ads | 11 -------- .../branch_traces/src/test_clear_step.adb | 14 ----------- .../branch_traces/src/test_pit_step.adb | 14 ----------- .../branch_traces/src/test_rock_wait.adb | 14 ----------- 9 files changed, 128 deletions(-) delete mode 100644 tools/gnatcov/examples/branch_traces/Makefile delete mode 100644 tools/gnatcov/examples/branch_traces/branch_traces.gpr delete mode 100644 tools/gnatcov/examples/branch_traces/src/robot.adb delete mode 100644 tools/gnatcov/examples/branch_traces/src/robot.ads delete mode 100644 tools/gnatcov/examples/branch_traces/src/support.adb delete mode 100644 tools/gnatcov/examples/branch_traces/src/support.ads delete mode 100644 tools/gnatcov/examples/branch_traces/src/test_clear_step.adb delete mode 100644 tools/gnatcov/examples/branch_traces/src/test_pit_step.adb delete mode 100644 tools/gnatcov/examples/branch_traces/src/test_rock_wait.adb diff --git a/tools/gnatcov/examples/branch_traces/Makefile b/tools/gnatcov/examples/branch_traces/Makefile deleted file mode 100644 index 253f4d0a3..000000000 --- a/tools/gnatcov/examples/branch_traces/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# This is a example demonstrating branch coverage on a source featuring a -# decision with 3 conditions. The topology of the decision is such that we can -# achieve branch coverage with 3 tests only, while mcdc would require 4. - -TESTS=test_clear_step test_pit_step test_rock_wait -XCOVLEVEL=branch -CONSOLIDATE=traces - -include ../support/Makefile.examples diff --git a/tools/gnatcov/examples/branch_traces/branch_traces.gpr b/tools/gnatcov/examples/branch_traces/branch_traces.gpr deleted file mode 100644 index 17312aa2b..000000000 --- a/tools/gnatcov/examples/branch_traces/branch_traces.gpr +++ /dev/null @@ -1,6 +0,0 @@ -with "conf.gpr"; - -project branch_traces extends "base" is - for Source_Dirs use ("src"); - for Object_Dir use "obj/" & Conf.Target; -end branch_traces; diff --git a/tools/gnatcov/examples/branch_traces/src/robot.adb b/tools/gnatcov/examples/branch_traces/src/robot.adb deleted file mode 100644 index ee0095352..000000000 --- a/tools/gnatcov/examples/branch_traces/src/robot.adb +++ /dev/null @@ -1,25 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- Couverture -- --- -- --- Copyright (C) 2008-2024, AdaCore -- --- -- ------------------------------------------------------------------------------- - -package body Robot is - - ---------- - -- Eval -- - ---------- - - function Eval (Cmd : Command; Obs : Obstacle) return Status is - begin - -- Stepping forward into a rock or into a pit is unsafe - - if (Obs = Pit or else Obs = Rock) and then Cmd = Step then - return Unsafe; - else - return Safe; - end if; - end Eval; -end Robot; diff --git a/tools/gnatcov/examples/branch_traces/src/robot.ads b/tools/gnatcov/examples/branch_traces/src/robot.ads deleted file mode 100644 index f4e00b354..000000000 --- a/tools/gnatcov/examples/branch_traces/src/robot.ads +++ /dev/null @@ -1,19 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- Couverture -- --- -- --- Copyright (C) 2008-2024, AdaCore -- --- -- ------------------------------------------------------------------------------- - -package Robot is - - type Command is (Step, Wait); - type Obstacle is (Rock, Pit, None); - - type Status is (Safe, Unsafe); - - function Eval (Cmd : Command; Obs : Obstacle) return Status; - -- How is it to run command CMD in front of obstacle OBS ? - -end Robot; diff --git a/tools/gnatcov/examples/branch_traces/src/support.adb b/tools/gnatcov/examples/branch_traces/src/support.adb deleted file mode 100644 index 31e4f1b6a..000000000 --- a/tools/gnatcov/examples/branch_traces/src/support.adb +++ /dev/null @@ -1,16 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- Couverture -- --- -- --- Copyright (C) 2008-2024, AdaCore -- --- -- ------------------------------------------------------------------------------- - -package body Support is - procedure Assert (Cond : Boolean) is - begin - if not Cond then - raise Program_Error; - end if; - end Assert; -end Support; diff --git a/tools/gnatcov/examples/branch_traces/src/support.ads b/tools/gnatcov/examples/branch_traces/src/support.ads deleted file mode 100644 index 19d4f8543..000000000 --- a/tools/gnatcov/examples/branch_traces/src/support.ads +++ /dev/null @@ -1,11 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- Couverture -- --- -- --- Copyright (C) 2008-2024, AdaCore -- --- -- ------------------------------------------------------------------------------- - -package Support is - procedure Assert (Cond : Boolean); -end Support; diff --git a/tools/gnatcov/examples/branch_traces/src/test_clear_step.adb b/tools/gnatcov/examples/branch_traces/src/test_clear_step.adb deleted file mode 100644 index cc022acbb..000000000 --- a/tools/gnatcov/examples/branch_traces/src/test_clear_step.adb +++ /dev/null @@ -1,14 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- Couverture -- --- -- --- Copyright (C) 2008-2024, AdaCore -- --- -- ------------------------------------------------------------------------------- - -with Support, Robot; use Support, Robot; - -procedure Test_Clear_Step is -begin - Assert (Eval (Cmd => Step, Obs => None) = Safe); -end Test_Clear_Step; diff --git a/tools/gnatcov/examples/branch_traces/src/test_pit_step.adb b/tools/gnatcov/examples/branch_traces/src/test_pit_step.adb deleted file mode 100644 index 3811ae52b..000000000 --- a/tools/gnatcov/examples/branch_traces/src/test_pit_step.adb +++ /dev/null @@ -1,14 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- Couverture -- --- -- --- Copyright (C) 2008-2024, AdaCore -- --- -- ------------------------------------------------------------------------------- - -with Support, Robot; use Support, Robot; - -procedure Test_Pit_Step is -begin - Assert (Eval (Cmd => Step, Obs => Pit) = Unsafe); -end Test_Pit_Step; diff --git a/tools/gnatcov/examples/branch_traces/src/test_rock_wait.adb b/tools/gnatcov/examples/branch_traces/src/test_rock_wait.adb deleted file mode 100644 index 77e80a890..000000000 --- a/tools/gnatcov/examples/branch_traces/src/test_rock_wait.adb +++ /dev/null @@ -1,14 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- Couverture -- --- -- --- Copyright (C) 2008-2024, AdaCore -- --- -- ------------------------------------------------------------------------------- - -with Support, Robot; use Support, Robot; - -procedure Test_Rock_Wait is -begin - Assert (Eval (Cmd => Wait, Obs => Rock) = Safe); -end Test_Rock_Wait; From ec7c96a0bdf509d1aed46072572523df984a2c50 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 18 Sep 2024 15:44:00 +0200 Subject: [PATCH 0921/1483] aunit_variant: update project name "explore" to "aunit_variant" The name for the project file in this example has been incompletely renamed a long time ago (PC20-006). --- tools/gnatcov/examples/aunit_variant/harness.gpr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/examples/aunit_variant/harness.gpr b/tools/gnatcov/examples/aunit_variant/harness.gpr index b7b026ac0..36c99f085 100644 --- a/tools/gnatcov/examples/aunit_variant/harness.gpr +++ b/tools/gnatcov/examples/aunit_variant/harness.gpr @@ -1,6 +1,6 @@ with "conf"; with "aunit"; -with "explore"; +with "aunit_variant"; project Harness is From 3f42d1d424ce01c68a89b22b9807eb3033dadbdf Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 18 Sep 2024 15:12:49 +0200 Subject: [PATCH 0922/1483] Transition all examples to source traces Nowadays, what we really want to promote is source traces. The documentation was reworked with that perspective some time ago: do the same for examples. --- .../mcdc_checkpoints/mcdc_checkpoints.gpr | 5 + .../examples/spark_instrumentation/Makefile | 20 +-- .../spark_instrumentation.gpr | 11 ++ .../spark_instrumentation/spark_project.gpr | 10 -- .../gnatcov/examples/support/Makefile.common | 31 +++- .../examples/support/Makefile.examples | 151 ++++++++---------- .../examples/support/Makefile.libsupport | 22 +-- 7 files changed, 121 insertions(+), 129 deletions(-) create mode 100644 tools/gnatcov/examples/spark_instrumentation/spark_instrumentation.gpr delete mode 100644 tools/gnatcov/examples/spark_instrumentation/spark_project.gpr diff --git a/tools/gnatcov/examples/mcdc_checkpoints/mcdc_checkpoints.gpr b/tools/gnatcov/examples/mcdc_checkpoints/mcdc_checkpoints.gpr index 9137e3a02..48f872069 100644 --- a/tools/gnatcov/examples/mcdc_checkpoints/mcdc_checkpoints.gpr +++ b/tools/gnatcov/examples/mcdc_checkpoints/mcdc_checkpoints.gpr @@ -3,4 +3,9 @@ with "conf.gpr"; project MCDC_checkpoints extends "base" is for Source_Dirs use ("src"); for Object_Dir use "obj/" & Conf.Target; + + package Coverage is + for Excluded_Units use + ("test_stable", "test_unstable_p", "test_unstable_t"); + end Coverage; end MCDC_checkpoints; diff --git a/tools/gnatcov/examples/spark_instrumentation/Makefile b/tools/gnatcov/examples/spark_instrumentation/Makefile index de3bde4bb..4996f2379 100644 --- a/tools/gnatcov/examples/spark_instrumentation/Makefile +++ b/tools/gnatcov/examples/spark_instrumentation/Makefile @@ -6,20 +6,8 @@ # when building instrumented sources, to avoid running into SPARK constraints # violations. -# The sequence used here illustrates the steps for a native environment, -# assuming a gnatcov runtime has been set up already. -# -# Cross configurations would require only the usual adjustments (build with -# --target/--RTS, probably use a more suitable gnatcov_rts, execute in the -# cross environment, ...). The "handling spark" specific part of the process -# remains the same. - -all: - gnatcov instrument -P spark_project.gpr --level=stmt+mcdc --dump-trigger=main-end --dump-channel=base64-stdout - echo $(CURDIR) - gprbuild -f -c -P spark_project.gpr --target=c --implicit-with=gnatcov_rts --src-subdirs=gnatcov-instr -gnatec="$(CURDIR)/../support/instrument-spark.adc" -cargs -gnatp - GNATCOV_TRACE_FILE="main.srctrace" ./obj/main - gnatcov coverage -P spark_project.gpr --level=stmt+mcdc --annotate=dhtml --output-dir=report main.srctrace +TESTS=main +XCOVLEVEL=stmt+mcdc +EXTRA_CARGS=-gnatec="$(CURDIR)/../support/instrument-spark.adc" -clean: - rm -rf report main.srctrace obj +include ../support/Makefile.examples diff --git a/tools/gnatcov/examples/spark_instrumentation/spark_instrumentation.gpr b/tools/gnatcov/examples/spark_instrumentation/spark_instrumentation.gpr new file mode 100644 index 000000000..7719ec969 --- /dev/null +++ b/tools/gnatcov/examples/spark_instrumentation/spark_instrumentation.gpr @@ -0,0 +1,11 @@ +with "conf.gpr"; + +project SPARK_Instrumentation extends "base" is + + for Source_Dirs use ("src"); + for Object_Dir use "obj/" & Conf.Target; + + package Builder is + for Global_Configuration_Pragmas use "spark.adc"; + end Builder; +end SPARK_Instrumentation; diff --git a/tools/gnatcov/examples/spark_instrumentation/spark_project.gpr b/tools/gnatcov/examples/spark_instrumentation/spark_project.gpr deleted file mode 100644 index ef99373eb..000000000 --- a/tools/gnatcov/examples/spark_instrumentation/spark_project.gpr +++ /dev/null @@ -1,10 +0,0 @@ -project Spark_Project is - - for Source_Dirs use ("src"); - for Object_Dir use "obj"; - for Main use ("main.adb"); - - package Builder is - for Global_Configuration_Pragmas use "spark.adc"; - end Builder; -end Spark_Project; diff --git a/tools/gnatcov/examples/support/Makefile.common b/tools/gnatcov/examples/support/Makefile.common index 13c33cb2f..99f498270 100644 --- a/tools/gnatcov/examples/support/Makefile.common +++ b/tools/gnatcov/examples/support/Makefile.common @@ -44,6 +44,13 @@ SUPPORT_SRC_DIR = $(SUPPORT_DIR)/src SUPPORT_TARGET_SRC_DIR = $(SUPPORT_DIR)/src/$(TARGET) +# ======================================================= +# Temporary directories +# ======================================================= + +# Installation prefix for the coverage runtime (gnatcov_rts.gpr) +RTS_DIR=rts-install + # ======================================================= # CROSS toolchain prefix and target related arguments to # gprbuild: @@ -54,14 +61,28 @@ SUPPORT_TARGET_SRC_DIR = $(SUPPORT_DIR)/src/$(TARGET) # from the BSP including in the Ada library. ifneq ($(RTS),) - GPRBUILD_TARGETARGS += --RTS=$(RTS) + GPR_ARGS += --RTS=$(RTS) endif ifneq ($(TARGET),) - GPRBUILD_TARGETARGS += --target=$(TARGET) -XTARGET=$(TARGET) + GPR_ARGS += --target=$(TARGET) + GPRBUILD_TARGETARGS += -XTARGET=$(TARGET) endif ifneq ($(BOARD),) GPRBUILD_TARGETARGS += -XBOARD=$(BOARD) endif +GPRBUILD_TARGETARGS += $(GPR_ARGS) +XCOV_TARGETARGS = $(GPRBUILD_TARGETARGS) + +# ======================================================= +# Environment variable updates +# ======================================================= + +# Examples need to update the GPR_PROJECT_PATH environment variable to make +# both the support projects and the coverage runtime available to gprbuild and +# gnatcov. +ENV_UPDATE= \ + export GPR_PROJECT_PATH=../support:$$GPR_PROJECT_PATH; \ + export GPR_PROJECT_PATH=$(RTS_DIR)/share/gpr:$$GPR_PROJECT_PATH; # ========= # Commands: @@ -73,7 +94,11 @@ XCOV=gnatcov # This name remains a proper abstraction of a an actual name that we # don't really care about. -BUILDER=gprbuild -aP ../support $(GPRBUILD_TARGETARGS) +GNATEMU=$(TARGET)-gnatemu +# Name of the GNATemulator executable, used to run programs in non-native +# configurations. + +BUILDER=gprbuild $(GPRBUILD_TARGETARGS) # The common way to invoke gprbuild, providing direct access to the # support subdir so example projects can just do 'with "common.gpr";' # and 'extends "base"'. diff --git a/tools/gnatcov/examples/support/Makefile.examples b/tools/gnatcov/examples/support/Makefile.examples index 9374e07e2..e2ed49c6a 100644 --- a/tools/gnatcov/examples/support/Makefile.examples +++ b/tools/gnatcov/examples/support/Makefile.examples @@ -21,9 +21,10 @@ # The basic idea is, first for each test driver, to: # -# 1/ Build the program binary executable from the sources -# 2/ Run it through "gnatcov run" to get an execution trace -# 3/ Use "gnatcov coverage" to produce a report out of the trace +# 1/ Instrument the source code +# 2/ Build the program binary executable from the instrumented sources +# 3/ Run it (possibly through GNATemulator) to get an execution trace +# 4/ Use "gnatcov coverage" to produce a report out of the trace # # Then, optionally, as determined by the CONSOLIDATE variable value # for the example as a whole: @@ -47,84 +48,35 @@ XCOVLEVEL?=stmt+decision include ../support/Makefile.common -# ---------------------------------------------------------------------------- -# Object vs source coverage action variants for common rules -# ---------------------------------------------------------------------------- - -# We're only interested in results for our applicative units, not for test -# drivers or for the test-harness code in the Aunit case. We expect the list -# of units of interest to remain the same across all the tests participating -# in a given example. - -ALIS_LIST=alis.list -ROUTINES_LIST=routines.list - # Beware that these actions may be involved in different rules, so some # automatic variables like $< don't expand the same across actions. -OBJECT_LEVELS=branch insn SOURCE_LEVELS=stmt stmt+decision stmt+mcdc BINDIR = obj/$(TARGET) BASEDIR = $(notdir $(CURDIR)) -ifneq ($(filter $(OBJECT_LEVELS), $(XCOVLEVEL)),) - - # Object coverage: use --routines to filter. Compile with -g to - # allow annotated-source report formats. - - INTERNALBUILDFLAGS = -g - XCOVFILTER_LIST=$(ROUTINES_LIST) - XCOVFILTER=--routines=@$(XCOVFILTER_LIST) - XCOVRUN=$(XCOV) run \ - $(XCOVTARGET) --level=$(XCOVLEVEL) $(BINDIR)/$* -o $*.trace - -else -ifneq ($(filter $(SOURCE_LEVELS), $(XCOVLEVEL)),) - - # Source coverage: force -g -fdump-scos -fpreserve-control-flow, use --scos - # to filter and pass the filter to xcov run so that it has visibility on - # decision locations - - INTERNALBUILDFLAGS = -cargs -g -fdump-scos -fpreserve-control-flow - XCOVFILTER_LIST=$(ALIS_LIST) - XCOVFILTER=--scos=@$(XCOVFILTER_LIST) - XCOVRUN=$(XCOV) run \ - $(XCOVTARGET) --level=$(XCOVLEVEL) $(XCOVFILTER) $(BINDIR)/$* -o $*.trace -endif -endif +# Source coverage: pass --src-subdirs and --implicit-with. +INTERNALBUILDFLAGS = --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts # Argument we will pass to the builder eventually -BUILDERFLAGS=$(INTERNALBUILDFLAGS) $(BUILDFLAGS) +BUILDERFLAGS=$(INTERNALBUILDFLAGS) $(BUILDFLAGS) $(EXTRA_CARGS) ALL_TESTS=$(TESTS) $(AUNIT_TESTS) .PRECIOUS: %.trace -all: build $(XCOVFILTER_LIST) trace analyze consolidate-$(CONSOLIDATE) +all: build trace analyze consolidate-$(CONSOLIDATE) announce-%: force @echo "--------------" $* "--------------" -# ------------------------------------------------------------------------- -# routines or alis list construction targets -# ------------------------------------------------------------------------- - -# This is part of the early "all" prerequisites, built once for all the -# tests attached to a given example. - -$(ALIS_LIST): announce-alis-list force - ls $(wildcard $(BINDIR)/*.ali) | grep -v test_ > $@ - -$(ROUTINES_LIST): announce-routines-list force - $(XCOV) disp-routines $(wildcard $(BINDIR)/*.o) | grep -v test_ > $@ - # ------------------------------------------------------------------------- # consolidation targets # ------------------------------------------------------------------------- ALL_CHECKPOINTS=$(ALL_TESTS:%=%.ckpt) -ALL_TRACES=$(ALL_TESTS:%=%.trace) +ALL_TRACES=$(ALL_TESTS:%=%.srctrace) consolidate-: @@ -136,19 +88,22 @@ ckpt.list: force for ckpt in $(ALL_CHECKPOINTS); do echo $$ckpt >> $@; done out-all-checkpoints/index.html: out-all-checkpoints $(ALL_CHECKPOINTS) ckpt.list - $(XCOV) coverage --level=$(XCOVLEVEL) \ + $(XCOV) coverage $(XCOV_TARGETARGS) --level=$(XCOVLEVEL) \ --checkpoint=@ckpt.list \ - --annotate=html --output-dir=$(dir $@) + --annotate=html \ + --output-dir=$(dir $@) -%.ckpt: %.trace - $(XCOV) coverage $(XCOVFILTER) --level=$(XCOVLEVEL) \ - --save-checkpoint=$@ $*.trace +%.ckpt: %.srctrace + $(ENV_UPDATE) $(XCOV) coverage $(XCOV_TARGETARGS) -P$(BASEDIR).gpr \ + --level=$(XCOVLEVEL) \ + --save-checkpoint=$@ $*.srctrace consolidate-traces: announce-consolidate-traces consolidate-traces: out-all-traces/index.html out-all-traces/index.html: out-all-traces $(ALL_TRACES) - $(XCOV) coverage $(XCOVFILTER) --level=$(XCOVLEVEL) \ + $(ENV_UPDATE) $(XCOV) coverage $(XCOV_TARGETARGS) -P$(BASEDIR).gpr \ + --level=$(XCOVLEVEL) \ --annotate=html $(ALL_TRACES) \ --output-dir $(dir $@) @@ -166,17 +121,25 @@ out-%: force $(RM) -rf $@ $(MKDIR) $@ -out-%/index.html: out-% %.trace - $(XCOV) coverage $(XCOVFILTER) \ - --level=$(XCOVLEVEL) --annotate=html $*.trace --output-dir $(dir $@) - -out-%/index.xml: out-% %.trace - $(XCOV) coverage $(XCOVFILTER) \ - --level=$(XCOVLEVEL) --annotate=xml $*.trace --output-dir $(dir $@) +out-%/index.html: out-% %.srctrace + $(ENV_UPDATE) $(XCOV) coverage $(XCOV_TARGETARGS) -P$(BASEDIR).gpr \ + --level=$(XCOVLEVEL) \ + --annotate=html \ + --output-dir $(dir $@) \ + $*.srctrace + +out-%/index.xml: out-% %.srctrace + $(ENV_UPDATE) $(XCOV) coverage $(XCOV_TARGETARGS) -P$(BASEDIR).gpr \ + --level=$(XCOVLEVEL) \ + --annotate=xml $*.srctrace \ + --output-dir $(dir $@) -out-%/report.txt: out-% %.trace - $(XCOV) coverage $(XCOVFILTER) \ - --level=$(XCOVLEVEL) --annotate=report $*.trace -o $@ +out-%/report.txt: out-% %.srctrace + $(ENV_UPDATE) $(XCOV) coverage $(XCOV_TARGETARGS) -P$(BASEDIR).gpr \ + --level=$(XCOVLEVEL) \ + --annotate=report \ + -o $@ \ + $*.srctrace # ----------------------------------------------------------------------- # trace: produce execution trace from executable program execution @@ -184,10 +147,15 @@ out-%/report.txt: out-% %.trace # ----------------------------------------------------------------------- trace: announce-trace -trace: $(ALL_TESTS:%=%.trace) +trace: $(ALL_TESTS:%=%.srctrace) -%.trace: % force - $(XCOVRUN) +%.srctrace: % force +ifneq ($(XCOVTARGET),) + $(GNATEMU) $(BINDIR)/$* > $*.b64trace + $(XCOV) extract-base64-trace $*.b64trace $*.srctrace +else + GNATCOV_TRACE_FILE=$*.srctrace $(BINDIR)/$* +endif # ----------------------------------------------------------------------- # build: produce executable program from sources + target bsp @@ -197,14 +165,27 @@ build: $(ALL_TESTS) $(ALL_TESTS): announce-build-tests -$(TESTS): libsupport force - $(BUILDER) -q -f -p $@.adb -P$(BASEDIR).gpr $(BUILDERFLAGS) +$(TESTS): libsupport gnatcov_rts force + $(ENV_UPDATE) $(XCOV) instrument -q -P$(BASEDIR).gpr $(XCOV_TARGETARGS) \ + --level=$(XCOVLEVEL) $@.adb + $(ENV_UPDATE) $(BUILDER) -q -f -p $@.adb -P$(BASEDIR).gpr $(BUILDERFLAGS) + +$(AUNIT_TESTS): libsupport gnatcov_rts force + $(ENV_UPDATE) $(XCOV) instrument -q $(XCOV_TARGETARGS) -Pharness.gpr \ + --level=$(XCOVLEVEL) \ + -XUNITTEST=yes \ + -XPLATFORM=$(TARGET) + $(ENV_UPDATE) $(BUILDER) -q -f -p $@.adb -Pharness.gpr \ + -XUNITTEST=yes \ + -XPLATFORM=$(TARGET) \ + $(BUILDERFLAGS) -$(AUNIT_TESTS): libsupport force - $(BUILDER) -q -f -p $@.adb -Pharness.gpr \ - -XUNITTEST=yes -XPLATFORM=$(TARGET) $(BUILDERFLAGS) +MKSUPPORT=$(MAKE) -C $(SUPPORT_DIR) -f Makefile.libsupport \ + TARGET=$(TARGET) RTS=$(RTS) BOARD=$(BOARD) -MKSUPPORT=$(MAKE) -C $(SUPPORT_DIR) -f Makefile.libsupport +gnatcov_rts: announce-gnatcov-setup force + rm -rf $(RTS_DIR) + $(XCOV) setup -q --prefix=$(RTS_DIR) $(GPR_ARGS) libsupport: announce-build-libsupport $(MKSUPPORT) all @@ -215,9 +196,9 @@ libsupport: announce-build-libsupport clean: $(MKSUPPORT) clean - $(RM) -rf obj lib out-* - $(RM) -f *.bin *.dmap *.cgpr *.trace.* *.trace *~ \ + $(RM) -rf obj lib out-* $(RTS_DIR) + $(RM) -f *.bin *.dmap *.cgpr *.srctrace *.b64trace *~ \ *.xcov *.html *.css *.xml $(TESTS) \ - *.list + *.list *.ckpt .PHONY: force clean diff --git a/tools/gnatcov/examples/support/Makefile.libsupport b/tools/gnatcov/examples/support/Makefile.libsupport index c08b4d3e6..29ad9caab 100644 --- a/tools/gnatcov/examples/support/Makefile.libsupport +++ b/tools/gnatcov/examples/support/Makefile.libsupport @@ -2,14 +2,6 @@ include Makefile.common -# Tailored compilation options for libsupport. Allow source -# coverage analysis with binary traces by default, cross only -# at this stage. - -ifneq ($(TARGET),) -LIBSUPPORT_CFLAGS:=-fdump-scos -fpreserve-control-flow -g $(LIBSUPPORT_CFLAGS) -endif - all: $(SUPPORT_TARGET_SRC_DIR) $(LIBSUPPORT_DIR) LIBSUPPORT LCH # ---------------------------------------------------------------------------- @@ -40,15 +32,15 @@ $(SUPPORT_TARGET_SRC_DIR) $(LIBSUPPORT_DIR): mkdir -p $@ LIBSUPPORT: conf.gpr force - $(BUILDER) -XLIBSUPPORT_BUILD=yes -p -Plibsupport.gpr -f \ - -cargs $(LIBSUPPORT_CFLAGS) - $(BUILDER) -XLIBSUPPORT_BUILD=yes -p -Plibsupport.gpr -f \ - -XUNITTEST=yes \ - -cargs $(LIBSUPPORT_CFLAGS) + $(BUILDER) $(GPRBUILD_TARGETARGS) -XLIBSUPPORT_BUILD=yes \ + -p -Plibsupport.gpr -f + $(BUILDER) $(GPRBUILD_TARGETARGS) -XLIBSUPPORT_BUILD=yes \ + -p -Plibsupport.gpr -f \ + -XUNITTEST=yes LCH: conf.gpr force - $(BUILDER) -XLIBSUPPORT_BUILD=yes -p -Plch.gpr -f \ - -cargs $(LIBSUPPORT_CFLAGS) + $(BUILDER) $(GPRBUILD_TARGETARGS) -XLIBSUPPORT_BUILD=yes \ + -p -Plch.gpr -f clean: $(RM) -rf lib obj From d2d1c19c61e688445162e27332f056febcdf3c3f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 29 Apr 2024 11:53:01 +0200 Subject: [PATCH 0923/1483] Use the testsuite_reports ci fragment --- .gitlab-ci.yml | 28 ++++++---------------------- 1 file changed, 6 insertions(+), 22 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 00644a348..46eb5cb80 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -95,11 +95,11 @@ build_community: .common_artifacts_bits: &artifacts artifacts: paths: - - xunit_output.xml + - xunit-*.xml - coverage/cobertura.xml reports: - junit: xunit_output.xml + junit: xunit-*.xml coverage_report: coverage_format: cobertura path: coverage/cobertura.xml @@ -118,11 +118,7 @@ test_bin_traces: - anod test gnatcov --minimal --target=leon3-elf,,qemu -QRTS=embedded-leon3,-O0,instr $ACI_TRACK_QUALIFIER - TEST_BSN=$(anod eval --primitive=test gnatcov --target=leon3-elf,,qemu -QRTS=embedded-leon3,-O0,instr $ACI_TRACK_QUALIFIER build_space_name) - mv $ANOD_DEFAULT_SANDBOX_DIR/leon3-elf-linux64/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - - e3-testsuite-report - --failure-exit-code 1 - --xunit-output $CI_PROJECT_DIR/xunit_output.xml - --xunit-name bin-traces - $ANOD_DEFAULT_SANDBOX_DIR/leon3-elf-linux64/$TEST_BSN/results/new/ + - testsuite_reports <<: *artifacts @@ -140,11 +136,7 @@ test_src_traces: - anod test gnatcov --minimal -Qsrc-traces,instr $ACI_TRACK_QUALIFIER - TEST_BSN=$(anod eval --primitive=test gnatcov -Qsrc-traces,instr $ACI_TRACK_QUALIFIER build_space_name) - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - - e3-testsuite-report - --failure-exit-code 1 - --xunit-output $CI_PROJECT_DIR/xunit_output.xml - --xunit-name src-traces - $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/results/new/ + - testsuite_reports <<: *artifacts @@ -171,11 +163,7 @@ test_5.04a1_src_traces: - anod test gnatcov --minimal -Q5.04a1,src-traces,instr $ACI_TRACK_QUALIFIER - TEST_BSN=$(anod eval --primitive=test gnatcov -Q5.04a1,src-traces,instr $ACI_TRACK_QUALIFIER build_space_name) - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - - e3-testsuite-report - --failure-exit-code 1 - --xunit-output $CI_PROJECT_DIR/xunit_output.xml - --xunit-name src-traces - $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/results/new/ + - testsuite_reports <<: *artifacts @@ -193,11 +181,7 @@ test_spark: - anod test gnatcov --minimal -Qspark-tests,src-traces,instr $ACI_TRACK_QUALIFIER - TEST_BSN=$(anod eval --primitive=test gnatcov -Qspark-tests,src-traces,instr $ACI_TRACK_QUALIFIER build_space_name) - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - - e3-testsuite-report - --failure-exit-code 1 - --xunit-output $CI_PROJECT_DIR/xunit_output.xml - --xunit-name spark - $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/results/new/ + - testsuite_reports <<: *artifacts From c110700157638c926b302bf810b5ffacfce18961 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Thu, 19 Sep 2024 11:22:46 +0200 Subject: [PATCH 0924/1483] Fix instrumentation crash for user op calls gnatcov used to crash when attempting to instrument a user-defined operator call. Now, a proper warning is raised and the call is not instrumented as it is a limitation. --- .../user_operator/src/op.adb | 13 ++++++++++++ .../user_operator/src/test_op.adb | 16 +++++++++++++++ .../user_operator/test.py | 10 ++++++++++ tools/gnatcov/instrument-ada_unit.adb | 20 +++++++++++++++---- 4 files changed, 55 insertions(+), 4 deletions(-) create mode 100644 testsuite/tests/287-function_call_cov/user_operator/src/op.adb create mode 100644 testsuite/tests/287-function_call_cov/user_operator/src/test_op.adb create mode 100644 testsuite/tests/287-function_call_cov/user_operator/test.py diff --git a/testsuite/tests/287-function_call_cov/user_operator/src/op.adb b/testsuite/tests/287-function_call_cov/user_operator/src/op.adb new file mode 100644 index 000000000..e7f427a6a --- /dev/null +++ b/testsuite/tests/287-function_call_cov/user_operator/src/op.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; + +procedure Op +is + function "+" (L, R : Boolean) return String is ("Executed"); -- # fun + + T : Boolean := True; -- # t_decl + S : constant String := T + T; -- # op_call +begin + Put_Line (S); -- # put_line +end Op; diff --git a/testsuite/tests/287-function_call_cov/user_operator/src/test_op.adb b/testsuite/tests/287-function_call_cov/user_operator/src/test_op.adb new file mode 100644 index 000000000..176ce749c --- /dev/null +++ b/testsuite/tests/287-function_call_cov/user_operator/src/test_op.adb @@ -0,0 +1,16 @@ +with Op; + +-- LIMITATION +-- For now, gnatcov should not instrument calls to user-defined operators. +-- Check that this is true and that the proper warning is emitted. + +procedure Test_Op is +begin + Op; +end Test_Op; + +--# op.adb +-- /fun/ l+ ## 0 +-- /t_decl/ l+ ## 0 +-- /op_call/ l? ## c? +-- /put_line/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/user_operator/test.py b/testsuite/tests/287-function_call_cov/user_operator/test.py new file mode 100644 index 000000000..226fb54d3 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/user_operator/test.py @@ -0,0 +1,10 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase( + category=CAT.mcdc, + fun_call_lvl=True, + tolerate_messages="cannot instrument calls to user-defined operators", +).run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index a3255be00..f3cdc4f07 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6257,7 +6257,9 @@ package body Instrument.Ada_Unit is Do_Not_Instrument := True; end; - -- TODO: LIMITATION + -- TODO: LIMITATIONS + -- + -- NON-IMPORTED TYPES -- Currently, gnatcov is unable to determine if the full -- name of a type is visible and can be explicitely used in -- a unit. For this reason, we cannot currently turn @@ -6265,8 +6267,14 @@ package body Instrument.Ada_Unit is -- need for call the are in the middle of a dotted name. -- For now, do not instrument calls that wouls require such -- an instrumentation. + -- + -- USER-DEFINED OPERATORS + -- gnatcov does not handle calls to user-defined operators + -- as the current instrumentation is not suited to it. - Do_Not_Instrument := Needs_Qualified_Expr; + Do_Not_Instrument := + Needs_Qualified_Expr + or else Node.Kind in Ada_Op; if not Do_Not_Instrument then Fill_Expression_Insertion_Info @@ -6303,6 +6311,8 @@ package body Instrument.Ada_Unit is Create_Paren_Expr (UIC.Rewriting_Context, If_Expression)) else No_Node_Rewriting_Handle); + Dummy : constant Wide_Wide_String := + Unparse (If_Expression); begin if Needs_Qualified_Expr then Replace (Dummy_Handle, Qualified_Expr); @@ -6314,8 +6324,10 @@ package body Instrument.Ada_Unit is Report (UIC, Full_Call_Node, - "gnatcov limitation: cannot instrument calls within" - & " dotted names", + "gnatcov limitation: cannot instrument calls " + & (if Needs_Qualified_Expr + then "within dotted names" + else "to user-defined operators"), Warning); UIC.Non_Instr_LL_SCOs.Include (SCO_Id (SCOs.SCO_Table.Last)); From a15aabea9237cd67dd9792d208e24b834f3443cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Thu, 19 Sep 2024 11:30:02 +0200 Subject: [PATCH 0925/1483] Mention fun/call limitations in documentation --- doc/gnatcov/cov_source.rst | 3 +++ doc/gnatcov/src_traces.rst | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index ac04ba195..1dec52edc 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -1581,6 +1581,9 @@ It is important to note that for an :dfn:`uncovered` statement which happens to be a call statement, only a statement violation will be emitted in coverage reports. +The limitations of this coverage level are detailed in the +:ref:`instr-limitations` section. + .. _synthetic-metrics: Synthetic metrics diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index b761251e5..caf52586f 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -583,6 +583,18 @@ it is required to remove any :cmd-option:`-include` switch that is passed to the compiler invocation, by having a dedicated scenario variable for a coverage build for instance. +Function and call coverage limitations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Function and call coverage is only available for Ada. Currently, gnatcov is +unable to provided coverage information for: + +* Call expressions part of the prefix of a dotted name + +* Calls to user-defined operators + +The coverage state of these cases will be reported as undetermined. + .. _instr-build: Building instrumented components From 321133e52c19470a6fc2f4f0b46b5ce7bed201f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 19 Sep 2024 11:50:22 +0200 Subject: [PATCH 0926/1483] CI: Generalize use of ci fragments for testsuite reports --- .gitlab-ci.yml | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 46eb5cb80..910083ba1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -240,11 +240,7 @@ test_block_instr: - anod test gnatcov --minimal -Qsrc-traces,instr,block $ACI_TRACK_QUALIFIER - TEST_BSN=$(anod eval --primitive=test gnatcov -Qsrc-traces,instr,block $ACI_TRACK_QUALIFIER build_space_name) - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - - e3-testsuite-report - --failure-exit-code 1 - --xunit-output $CI_PROJECT_DIR/xunit_output.xml - --xunit-name src-traces - $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/results/new/ + - testsuite_reports <<: *artifacts @@ -270,10 +266,6 @@ test_src_light: - anod test gnatcov --minimal -Qsrc-traces,instr,RTS=light-stm32f4 --target=arm-elf,,qemu-stm32 $ACI_TRACK_QUALIFIER - TEST_BSN=$(anod eval --primitive=test gnatcov -Qsrc-traces,instr,RTS=light-stm32f4 --target=arm-elf,,qemu-stm32 $ACI_TRACK_QUALIFIER build_space_name) - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/test/coverage/cobertura.xml $CI_PROJECT_DIR/coverage/cobertura.xml - - e3-testsuite-report - --failure-exit-code 1 - --xunit-output $CI_PROJECT_DIR/xunit_output.xml - --xunit-name src-traces - $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$TEST_BSN/results/new/ + - testsuite_reports <<: *artifacts From dc7ea205a4464284a3b283ca3887c0db457b23da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 19 Sep 2024 14:28:06 +0200 Subject: [PATCH 0927/1483] CI: Update image from e3 to pe-base --- .gitlab-ci.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 910083ba1..51f327ca4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ stages: build: interruptible: true services: - - image:e3 + - image:pe-base - cpu:16 - mem:16 stage: build @@ -47,7 +47,7 @@ build: build_docs: stage: build services: - - image:e3 + - image:pe-base needs: [] rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event" || ($CI_PIPELINE_SOURCE == "push" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH) @@ -68,7 +68,7 @@ build_docs: build_community: interruptible: true services: - - image:e3 + - image:pe-base - cpu:8 - mem:16 stage: test @@ -107,7 +107,7 @@ build_community: test_bin_traces: interruptible: true services: - - image:e3 + - image:pe-base - cpu:16 - mem:16 stage: test @@ -125,7 +125,7 @@ test_bin_traces: test_src_traces: interruptible: true services: - - image:e3 + - image:pe-base - cpu:16 - mem:16 stage: test @@ -143,7 +143,7 @@ test_src_traces: test_5.04a1_src_traces: interruptible: true services: - - image:e3 + - image:pe-base - cpu:16 - mem:16 stage: test @@ -170,7 +170,7 @@ test_5.04a1_src_traces: test_spark: interruptible: true services: - - image:e3 + - image:pe-base - cpu:16 - mem:16 stage: test @@ -189,7 +189,7 @@ stylechecks: interruptible: true stage: test services: - - image:e3 + - image:pe-base - run_as_root:false needs: [] script: @@ -228,7 +228,7 @@ stylechecks: test_block_instr: interruptible: true services: - - image:e3 + - image:pe-base - cpu:16 - mem:16 stage: test @@ -254,7 +254,7 @@ test_block_instr: test_src_light: interruptible: true services: - - image:e3 + - image:pe-base - cpu:16 - mem:16 stage: test From 4c408ae787c08cba6b860372e2e5d44f57ea99ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 19 Sep 2024 16:34:38 +0200 Subject: [PATCH 0928/1483] CI: Remove duplicate track qualifier --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 51f327ca4..9b74ea2f1 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -75,7 +75,7 @@ build_community: script: - *basic_setup # Build using anod - - anod build --minimal gnatcov -Qno-c $ACI_TRACK_QUALIFIER $ACI_TRACK_QUALIFIER + - anod build --minimal gnatcov -Qno-c $ACI_TRACK_QUALIFIER .common_test_bits: &basic_test_setup # Setup the sandbox From 5d8f68c59c49e53759ab498ad044ce6cf34d860f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 19 Sep 2024 11:51:03 +0200 Subject: [PATCH 0929/1483] CI: Use smart rebuild instead of minimal rebuild in anod This allows the CI to build some of the dependencies of gnatcov to test breaking changes, instead of systematically using the components for cathod. --- .gitlab-ci.yml | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9b74ea2f1..43b8fdb2b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -29,8 +29,18 @@ build: script: - require_issue - *basic_setup - # Build using anod + + # 1. Install / build the dependencies of gnatcov using the smart rebuilder + # to allow testing of breaking changes. Do not use the -Qinstr qualifier + # as this would trigger a rebuild of the vanilla gnatcov. + - anod build --smart-rebuild --deps-only gnatcov $ACI_TRACK_QUALIFIER + + # 2. Install vanilla gnatcov from cathod - anod install gnatcov $ACI_TRACK_QUALIFIER --latest + + # 3. Build using anod, but minimally as all dependencies are supposed to be + # already built/installed via 1, but we don't want to re-build the + # gnatcov installed via 2 with --smart-rebuild. - anod build --minimal gnatcov -Qinstr $ACI_TRACK_QUALIFIER # Package all components created so far @@ -74,8 +84,9 @@ build_community: stage: test script: - *basic_setup - # Build using anod - - anod build --minimal gnatcov -Qno-c $ACI_TRACK_QUALIFIER + # Build using anod, we can use the smart rebuilder here as gnatcov does not + # depend on itself in this case. + - anod build --smart-rebuild gnatcov -Qno-c $ACI_TRACK_QUALIFIER .common_test_bits: &basic_test_setup # Setup the sandbox From 320db2333d71cefae323ee2ac8d66b587bb31b74 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 20 Sep 2024 14:53:05 +0200 Subject: [PATCH 0930/1483] Update documentation regarding the --dump-trigger option --- doc/gnatcov/src_traces.rst | 6 +++--- tools/gnatcov/command_line.ads | 14 +++++++------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index caf52586f..f8dbc2b07 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -234,9 +234,9 @@ units, if any are designated by the root project: :cmd-option:`--dump-trigger` selects the execution point at which the output of coverage data should be - injected in main units. This is ``manual`` by default, leaving to users the - responsibility to emit the coverage data as they see fit. Other possible - choices are ``atexit``, ``main-end`` and ``ravenscar-task-termination``. + injected in main units. The default is inferred from the installed + instrumentation runtime. The possible choices are ``manual``, ``atexit``, + ``main-end`` and ``ravenscar-task-termination``. :cmd-option:`--dump-channel` selects the mechanism used to output coverage data at the selected diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 129a8cf3f..fa12092c4 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -865,13 +865,13 @@ package Command_Line is Help => "Select a trigger to dump coverage buffers in the" & " instrumented program." & ASCII.LF & ASCII.LF - & """manual"" (the default) does nothing specific," - & " leaving the responsibility to schedule the dump" - & " when appropriate, as specified in the" - & " documentation. A list of files containing the" - & " manual indications can be optionally specified." - & " If not, gnatcov processes every file of the" - & " project." + & """manual"" searches for user-written dump" + & " indication in all the project sources (the search" + & " is restricted to FILES if specified) and replaces" + & " such indications with a call to the subprogram" + & " responsible for dumping the coverage buffers. A" + & " warning is emitted if no dump indications were" + & " found. See the user manual for more information." & ASCII.LF & ASCII.LF & """atexit"" uses the libc's atexit() routine to" & " schedule the dump." From c2631ae868cdbc6c9aecb0ac12f2945286e9938e Mon Sep 17 00:00:00 2001 From: Rowan Walshe Date: Tue, 17 Sep 2024 17:08:03 +0100 Subject: [PATCH 0931/1483] Build docs with warnings marked as errors in CI Relates to eng/das/fuzz/gnatfuzz#798 --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 43b8fdb2b..9b06dba95 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -66,7 +66,7 @@ build_docs: when: always script: - *basic_setup - - anod build gnatdas-doc --latest + - anod build gnatdas-doc --qualifier warn-errors --latest - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/gnatdas-doc/install/share/doc/gnatdas/ $CI_PROJECT_DIR artifacts: when: From aee92bad67ea59c76be379486dadcfa95460a8cd Mon Sep 17 00:00:00 2001 From: Jerome Lambourg Date: Tue, 2 Jul 2024 13:34:35 +0200 Subject: [PATCH 0932/1483] Adjust Setup_RTS to libgpr2-next API Part of eng/gpr/gpr-issues#317 (cherry picked from commit 01d52fae5ce1420462398abf90082461706c04fe) --- tools/gnatcov/gnatcov.gpr | 2 +- tools/gnatcov/setup_rts.adb | 140 ++++++++++++++++-------------------- 2 files changed, 61 insertions(+), 81 deletions(-) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 45c6194a4..018f2080e 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -150,7 +150,7 @@ project Gnatcov is -- only in stubs. case Part is - when "lib32" | "lib64" | "driver" | "gnatcov32" => + when "lib32" | "lib64" | "driver" | "gnatcov32" | "compiler" => Gnatcoverage_Excluded_Units := Gnatcoverage_Excluded_Units & ("instrument*"); when "gnatcov64" => diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 86964bca4..6976471d3 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -19,6 +19,7 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Directories; use Ada.Directories; with Ada.Environment_Variables; +with Ada.Strings.Fixed; with Ada.Text_IO; use Ada.Text_IO; with GNAT.OS_Lib; @@ -27,9 +28,9 @@ with GNAT.Regexp; with GNATCOLL.JSON; use GNATCOLL.JSON; with GNATCOLL.VFS; use GNATCOLL.VFS; with GPR2.Context; -with GPR2.Containers; with GPR2.KB; with GPR2.Log; +with GPR2.Options; with GPR2.Path_Name; with GPR2.Project.Attribute; with GPR2.Project.Attribute_Index; @@ -49,8 +50,6 @@ with Text_Files; package body Setup_RTS is - use type GPR2.Filename_Optional; - type Library_Support is (None, Static_Only, Full); -- Support for libraries in the given target/runtime configuration, as -- defined in GPR configuration files (see the Library_Support GPR @@ -66,18 +65,16 @@ package body Setup_RTS is Ravenscar_RTS_Regexp : constant GNAT.Regexp.Regexp := GNAT.Regexp.Compile (".*(ravenscar|light-tasking|embedded).*"); - procedure Load_Project + function Load_Project (Project : in out GPR2.Project.Tree.Object; Project_File : String; Target : String; RTS : String; Config_File : String; - Context : GPR2.Context.Object := GPR2.Context.Empty); + Context : GPR2.Context.Object := GPR2.Context.Empty) return Boolean; -- Load Project_File for the given Target/RTS/Config_File/Context. -- - -- This does not raise an exception in case of project loading failure: - -- callers are supposed to check Project.Log_Messages to handle possible - -- errors. + -- Returns true upon success. Note that logs are automatically displayed. function Setup_Project (Temp_Dir : Temporary_Directory; @@ -192,18 +189,17 @@ package body Setup_RTS is -- Load_Project -- ------------------ - procedure Load_Project + function Load_Project (Project : in out GPR2.Project.Tree.Object; Project_File : String; Target : String; RTS : String; Config_File : String; - Context : GPR2.Context.Object := GPR2.Context.Empty) + Context : GPR2.Context.Object := GPR2.Context.Empty) return Boolean is - PF : constant GPR2.Path_Name.Object := - GPR2.Path_Name.Create_File - (GPR2.Filename_Type (Project_File), GPR2.Path_Name.No_Resolution); + Opts : GPR2.Options.Object; begin + -- According to the documentation, an error message is recorded in -- Project when Load and Load_Autoconf raise GPR2.Project_Error -- exceptions, so we can just ignore this exception and let callers deal @@ -212,51 +208,30 @@ package body Setup_RTS is -- If a configuration project file is provided, just load it to create -- the configuration. + Opts.Add_Switch (GPR2.Options.P, Project_File); + if Config_File /= "" then - declare - F : constant GPR2.Path_Name.Object := - GPR2.Path_Name.Create_File (GPR2.Filename_Type (Config_File)); - Config : constant GPR2.Project.Configuration.Object := - GPR2.Project.Configuration.Load (F); - begin - Project.Load - (Filename => PF, - Context => Context, - Absent_Dir_Error => GPR2.Project.Tree.No_Error, - Config => Config); - exception - when GPR2.Project_Error => - null; - end; + Opts.Add_Switch (GPR2.Options.Config, Config_File); + end if; - -- Otherwise, use the "auto configuration" mode that will use the - -- optional target and RTS information. Always require C (needed for the - -- core coverage runtime) and require the Ada language only if enabled. + for C in Context.Iterate loop + Opts.Add_Switch (GPR2.Options.X, + String (GPR2.Context.Key_Value.Key (C)) & '=' & + String (GPR2.Context.Key_Value.Element (C))); + end loop; - else - declare - RTS_Map : GPR2.Containers.Lang_Value_Map; - Actual_Target : constant GPR2.Optional_Name_Type := - GPR2.Optional_Name_Type (Target); - begin - RTS_Map.Include (GPR2.C_Language, RTS); - if Src_Enabled_Languages (Ada_Language) then - RTS_Map.Include (GPR2.Ada_Language, RTS); - end if; + if RTS /= "" then + Opts.Add_Switch (GPR2.Options.RTS, RTS, "Ada"); + end if; - begin - Project.Load_Autoconf - (Filename => PF, - Context => Context, - Absent_Dir_Error => GPR2.Project.Tree.No_Error, - Target => Actual_Target, - Language_Runtimes => RTS_Map); - exception - when GPR2.Project_Error => - null; - end; - end; + if Target /= "" and then Config_File = "" then + Opts.Add_Switch (GPR2.Options.Target, Target); end if; + + return Project.Load + (Opts, + With_Runtime => True, + Absent_Dir_Error => GPR2.No_Error); end Load_Project; ----------- @@ -433,8 +408,9 @@ package body Setup_RTS is then GPR2.Ada_Language else GPR2.C_Language); - Ctx : GPR2.Context.Object; - Prj : GPR2.Project.Tree.Object; + Ctx : GPR2.Context.Object; + Prj : GPR2.Project.Tree.Object; + Has_Error : Boolean; begin -- Compute scenario variables that determine the set of languages, as we -- may not be able to load the full Ada+C project if there is no Ada @@ -446,7 +422,8 @@ package body Setup_RTS is -- Now load the project - Load_Project (Prj, Project_File, Target, RTS, Config_File, Ctx); + Has_Error := + not Load_Project (Prj, Project_File, Target, RTS, Config_File, Ctx); -- Print all messages in verbose mode, and all but the Information ones -- otherwise. Abort on error, or if we failed to get a runtime project @@ -455,11 +432,11 @@ package body Setup_RTS is -- C-only projects do not require a runtime, so do not complain if there -- is no runtime project in this case. + Has_Error := Has_Error + or else (Has_Ada and then not Prj.Has_Runtime_Project); + declare - Logs : constant access GPR2.Log.Object := Prj.Log_Messages; - Has_Error : constant Boolean := - Logs.Has_Error - or else (Has_Ada and then not Prj.Has_Runtime_Project); + Logs : constant access GPR2.Log.Object := Prj.Log_Messages; begin if Logs.Has_Element (Information => False, @@ -504,26 +481,30 @@ package body Setup_RTS is Auto_RTS_Profile := Embedded; if Has_Ada then - for F of Prj.Runtime_Project.Sources loop - if F.Path_Name.Simple_Name = "g-os_lib.ads" then - Auto_RTS_Profile := Full; - exit; - end if; - end loop; + Prj.Update_Sources (GPR2.Sources_Only); + + if Prj.Runtime_Project.Has_Source ("g-os_lib.ads") then + Auto_RTS_Profile := Full; + end if; else declare - use GPR2; - Tool_Name : constant Name_Type := "gcc"; + Driver : constant GPR2.Project.Attribute.Object := + Prj.Root_Project.Attribute + (GPR2.Project.Registry.Attribute.Compiler.Driver, + GPR2.Project.Attribute_Index.Create + (GPR2.C_Language)); begin - -- Add_Tool_Prefix's documentation states that the tool name is - -- returned unchanged for native compilation, so use this as a - -- proxy to determine if we are setting up the gnatcov RTS for - -- a cross target or not. - - Auto_RTS_Profile := - (if Tool_Name = Prj.Add_Tool_Prefix (Tool_Name) - then Full - else Embedded); + -- If C's compiler driver is defined, and contains a dash, we + -- can only suppose it's a cross compiler with an executable of + -- the form -. + + if Driver.Is_Defined + and then Ada.Strings.Fixed.Index (Driver.Value.Text, "-") > 0 + then + Auto_RTS_Profile := Embedded; + else + Auto_RTS_Profile := Full; + end if; end; end if; @@ -1083,8 +1064,7 @@ package body Setup_RTS is -- been installed: do not print any error message, and if the project -- fails to load, just return the default setup config. - Load_Project (Prj, Prj_Filename, Target, RTS, Config_File); - if Prj.Log_Messages.Has_Error + if not Load_Project (Prj, Prj_Filename, Target, RTS, Config_File) or else (Src_Enabled_Languages (Ada_Language) and then not Prj.Has_Runtime_Project) then @@ -1098,7 +1078,7 @@ package body Setup_RTS is -- The project file is in $PREFIX/share/gpr, so get $PREFIX first and -- then look for the config file under it. - Project_File := Create (+Prj.Root_Project.Path_Name.Value); + Project_File := Create (+Prj.Root_Project.Path_Name.String_Value); Setup_RTS_Trace.Trace ("Loaded the coverage runtime project at: " & (+Project_File.Full_Name)); From 1c9b78de70989da0d4ef5ba81fceb99292593882 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 3 Jul 2024 11:54:19 +0000 Subject: [PATCH 0933/1483] integrated_instrumentation/168-rts_error_msg: baseline update The order for error messages in case the runtime project cannot be loaded has changed since the transition to GPR2-next. Update the baseline, as the change is fine. (cherry picked from commit 16946ad1a17b38843fd4c394cd072636f41e0e29) --- .../integrated_instrumentation/168-rts_error_msg/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py index eeffaca35..46073e130 100644 --- a/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py +++ b/testsuite/tests/integrated_instrumentation/168-rts_error_msg/test.py @@ -29,9 +29,9 @@ thistest.fail_if_no_match( what="gnatcov error message", regexp=( - ".*gnatcov.*: Could not load the coverage runtime project" + 'no_such_gnatcov_rts\\.gpr: error: project file ".*" not found' + "\n.*gnatcov.*: Could not load the coverage runtime project" " no_such_gnatcov_rts" - '\nno_such_gnatcov_rts\\.gpr: error: project file ".*" not found' ), actual=contents_of(integration_log).strip(), ) From 1201abac5dd8e50d076f9c7a3f12b5c281008b44 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 3 Jul 2024 12:12:01 +0000 Subject: [PATCH 0934/1483] setup_rts.adb: fix cross C toolchain detection The "-" heuristic must apply to the *basename* of the C compiler executable, not its full name: dashes in the parent directory are irrelevant. This fixes current U211-014-setup testcase regressions on all native platforms. (cherry picked from commit fd99d10d57393d58855228c25e47d1fb155a551d) --- tools/gnatcov/setup_rts.adb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 6976471d3..6bb67d11c 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -493,13 +493,16 @@ package body Setup_RTS is (GPR2.Project.Registry.Attribute.Compiler.Driver, GPR2.Project.Attribute_Index.Create (GPR2.C_Language)); + + Driver_Fullname : constant String := Driver.Value.Text; + Driver_Basename : constant String := Simple_Name (Driver_Fullname); begin -- If C's compiler driver is defined, and contains a dash, we -- can only suppose it's a cross compiler with an executable of -- the form -. if Driver.Is_Defined - and then Ada.Strings.Fixed.Index (Driver.Value.Text, "-") > 0 + and then Ada.Strings.Fixed.Index (Driver_Basename, "-") > 0 then Auto_RTS_Profile := Embedded; else From 03e830c5add09574ff5ebbeaa7826db275273380 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 9 Jul 2024 09:01:25 +0000 Subject: [PATCH 0935/1483] SC_Obligations: add support for pragma No_Raise (cherry picked from commit 83f1e39c332cf2b06a9f8e723e229713662d7591) --- tools/gnatcov/sc_obligations.ads | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index b36808daa..89d1fcd9e 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -1086,6 +1086,7 @@ package SC_Obligations is Pragma_No_Elaboration_Code_All, Pragma_No_Heap_Finalization, Pragma_No_Inline, + Pragma_No_Raise, Pragma_No_Return, Pragma_No_Run_Time, Pragma_No_Strict_Aliasing, @@ -1390,6 +1391,7 @@ package SC_Obligations is Pragma_No_Body => False, Pragma_No_Caching => False, Pragma_No_Elaboration_Code_All => False, + Pragma_No_Raise => False, Pragma_No_Inline => False, Pragma_No_Return => False, Pragma_No_Tagged_Streams => False, From 86845e6f3f8c97cb594cfb89633e421d4ac994d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 30 Jul 2024 13:48:04 +0200 Subject: [PATCH 0936/1483] SCOV: allow different options for the instrument and coverage commands (cherry picked from commit e0be91292396e2b014bb5f26d90dd8c72738cd5f) --- testsuite/SCOV/internals/driver.py | 4 +++- testsuite/SCOV/tctl.py | 11 ++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 4651678ad..2a712415b 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -1465,7 +1465,9 @@ def mode_build(self): xcov_instrument( covlevel=self.xcovlevel, - extra_args=to_list(self.covctl.covoptions) if self.covctl else [], + extra_args=( + to_list(self.covctl.instroptions) if self.covctl else [] + ), dump_channel=self.dump_channel, dump_trigger=self.dump_trigger, gprsw=instrument_gprsw, diff --git a/testsuite/SCOV/tctl.py b/testsuite/SCOV/tctl.py index 89add4ab5..8beae0902 100644 --- a/testsuite/SCOV/tctl.py +++ b/testsuite/SCOV/tctl.py @@ -25,7 +25,9 @@ class CovControl: (gprsw). * Influence the non-GPR related command line options to gnatcov coverage - (covoptions). + (covoptions), and gnatcov instrument (instroptions). + If instroption is equal to "same" (the default), then it is set to the + value of covoption, to avoid the need to duplicate options. """ def __init__( @@ -38,6 +40,7 @@ def __init__( xreports=None, gprsw=None, covoptions="", + instroptions="same", ): # To control "with" dependencies (set of projects that will be withed # by the one we will be generating for the testcase): @@ -50,6 +53,12 @@ def __init__( # Extra options to gnatcov coverage only, typically for "-S" variants. self.covoptions = covoptions + # Extra options to gnatcov instrument only, potentially to be copied + # from covoptions + self.instroptions = ( + covoptions if instroptions == "same" else instroptions + ) + # To control Units related attributes in the GPR Coverage package. # # None is taken to mean "no attribute at all", which differs from From c9c912352e7d341b27b4a876e7427b95bbb8aaf1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 30 Jul 2024 16:14:26 +0200 Subject: [PATCH 0937/1483] First integration work for external annotations through Stable_Sloc This change adds a new units meant to be the interface between gnatcov internal types and Stable_Sloc. It also adds support for external exemptions, which can be loaded either during instrumentation, or when generating a coverage report. (cherry picked from commit 8de1f653d145e39678ee7dcd1e12ec10fc7e9b1f) --- .../exemptions/exemptions.toml | 81 ++++ .../ext_annotations/exemptions/src/foo.c | 9 + .../ext_annotations/exemptions/src/foo.h | 7 + .../ext_annotations/exemptions/src/pkg.adb | 18 + .../ext_annotations/exemptions/src/pkg.ads | 7 + .../exemptions/src/test_exempt.adb | 38 ++ .../tests/ext_annotations/exemptions/test.opt | 0 .../tests/ext_annotations/exemptions/test.py | 28 ++ tools/gnatcov/annotations.adb | 37 +- tools/gnatcov/command_line.ads | 13 +- tools/gnatcov/files_table.adb | 2 +- tools/gnatcov/gnatcov.gpr | 2 +- tools/gnatcov/gnatcov_bits_specific.adb | 5 + tools/gnatcov/instrument-ada_unit.adb | 9 +- tools/gnatcov/instrument-c.adb | 8 +- tools/gnatcov/instrument-common.ads | 37 ++ tools/gnatcov/instrument.ads | 8 + tools/gnatcov/sc_obligations.adb | 15 + tools/gnatcov/sc_obligations.ads | 35 +- tools/gnatcov/ss_annotations.adb | 410 ++++++++++++++++++ tools/gnatcov/ss_annotations.ads | 76 ++++ 21 files changed, 824 insertions(+), 21 deletions(-) create mode 100644 testsuite/tests/ext_annotations/exemptions/exemptions.toml create mode 100644 testsuite/tests/ext_annotations/exemptions/src/foo.c create mode 100644 testsuite/tests/ext_annotations/exemptions/src/foo.h create mode 100644 testsuite/tests/ext_annotations/exemptions/src/pkg.adb create mode 100644 testsuite/tests/ext_annotations/exemptions/src/pkg.ads create mode 100644 testsuite/tests/ext_annotations/exemptions/src/test_exempt.adb create mode 100644 testsuite/tests/ext_annotations/exemptions/test.opt create mode 100644 testsuite/tests/ext_annotations/exemptions/test.py create mode 100644 tools/gnatcov/ss_annotations.adb create mode 100644 tools/gnatcov/ss_annotations.ads diff --git a/testsuite/tests/ext_annotations/exemptions/exemptions.toml b/testsuite/tests/ext_annotations/exemptions/exemptions.toml new file mode 100644 index 000000000..3434605b8 --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/exemptions.toml @@ -0,0 +1,81 @@ +# Basic exemptions for pkg.adb + +[on] +file="pkg.adb" +kind="absolute" +[on.matcher] +start_line=6 +start_col=7 +# End line annotations does not matter for exempt_on +end_line=6 +end_col=7 +[[on.annotations]] +purpose="xcov.exempt.on" +justification="defensive code, not to be triggered (on)" + + +[off] +file="pkg.adb" +kind="absolute" +[off.matcher] +start_line=8 +start_col=14 +# End line annotations does not matter for exempt_off +end_line=8 +end_col=14 +[[off.annotations]] +purpose="xcov.exempt.off" + + +[region] +file="pkg.adb" +kind="absolute" +[region.matcher] +start_line=10 +start_col=7 +end_line=12 +end_col=14 +[[region.annotations]] +purpose="xcov.exempt.region" +justification="defensive code, not to be triggered (region)" + +# Basic exemption for foo.h + +[region_c] +file="foo.h" +kind="absolute" +[region_c.matcher] +start_line=4 +start_col=3 +end_line=5 +end_col=14 +[[region_c.annotations]] +purpose="xcov.exempt.region" +justification="defensive code, not to be triggered (region)" + +# Basic exemption for foo.c + +[on_c] +file="foo.c" +kind="absolute" +[on_c.matcher] +start_line=6 +start_col=3 +# End line annotations does not matter for exempt_on +end_line=6 +end_col=3 +[[on_c.annotations]] +purpose="xcov.exempt.on" +justification="garbage code, not to be triggered (on)" + +[off_c] +file="foo.c" +kind="absolute" +[off_c.matcher] +start_line=7 +start_col=15 +# End line annotations does not matter for exempt_off +end_line=7 +end_col=15 +[[off_c.annotations]] +purpose="xcov.exempt.off" diff --git a/testsuite/tests/ext_annotations/exemptions/src/foo.c b/testsuite/tests/ext_annotations/exemptions/src/foo.c new file mode 100644 index 000000000..9abb32441 --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/src/foo.c @@ -0,0 +1,9 @@ +#include "foo.h" + +int +ident (int x) +{ + if (x == 0) + return -1; + return static_helper (&x); +} diff --git a/testsuite/tests/ext_annotations/exemptions/src/foo.h b/testsuite/tests/ext_annotations/exemptions/src/foo.h new file mode 100644 index 000000000..91d414838 --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/src/foo.h @@ -0,0 +1,7 @@ +static int +static_helper (int *x) +{ + if (!x) // # exempt_h_d + return 0; // # exempt_h_s + return *x; // # ok +} diff --git a/testsuite/tests/ext_annotations/exemptions/src/pkg.adb b/testsuite/tests/ext_annotations/exemptions/src/pkg.adb new file mode 100644 index 000000000..9270d2cf7 --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/src/pkg.adb @@ -0,0 +1,18 @@ +package body Pkg is + + procedure Swap (X, Y : Bool_Acc) is + Tmp : Boolean; + begin + if X = null then -- # exempt_1_d + raise Program_Error; -- # exempt_1_s + end if; -- # exempt_1 + + if Y = null then -- # exempt_2_d + raise Program_Error; -- # exempt_2_s + end if; -- # exempt_2 + Tmp := X.all; -- # ok + X.all := Y.all; -- # ok + Y.all := Tmp; -- # ok + end Swap; + +end Pkg; diff --git a/testsuite/tests/ext_annotations/exemptions/src/pkg.ads b/testsuite/tests/ext_annotations/exemptions/src/pkg.ads new file mode 100644 index 000000000..4db6d0bf0 --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/src/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + type Bool_Acc is access all Boolean; + + procedure Swap (X, Y : Bool_Acc); + +end Pkg; diff --git a/testsuite/tests/ext_annotations/exemptions/src/test_exempt.adb b/testsuite/tests/ext_annotations/exemptions/src/test_exempt.adb new file mode 100644 index 000000000..45578d29d --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/src/test_exempt.adb @@ -0,0 +1,38 @@ +with Pkg; + +with Support; + +with Interfaces.C; + +procedure Test_Exempt is + use type Interfaces.C.int; + X : aliased Boolean := True; + Y : aliased Boolean := False; + X_Acc : Pkg.Bool_Acc := X'Unchecked_Access; + Y_Acc : Pkg.Bool_Acc := Y'Unchecked_Access; + function Ident (X : Interfaces.C.int) return Interfaces.C.int; + pragma Import (C, Ident, "ident"); +begin + Pkg.Swap (X_Acc, Y_Acc); + Support.Assert (Y and then not X); + Support.Assert (Ident (1) = 1); +end Test_Exempt; + +--# pkg.adb +-- +-- /exempt_1/ l* ## x+ +-- /exempt_1_d/ l= ## XoT- +-- /exempt_1_s/ l= ## Xs- +-- /exempt_2/ l* ## x+ +-- /exempt_2_d/ l= ## XoT- +-- /exempt_2_s/ l= ## Xs- +-- /ok/ l+ ## 0 + +--# foo.h +-- +--%opts: --trace-mode=src +-- +-- /exempt_h/ l* ## x+ +-- /exempt_h_d/ l= ## XoT- +-- /exempt_h_s/ l= ## Xs- +-- /ok/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/exemptions/test.opt b/testsuite/tests/ext_annotations/exemptions/test.opt new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/ext_annotations/exemptions/test.py b/testsuite/tests/ext_annotations/exemptions/test.py new file mode 100644 index 000000000..d2299206f --- /dev/null +++ b/testsuite/tests/ext_annotations/exemptions/test.py @@ -0,0 +1,28 @@ +""" +Basic test to ensure exemptions are properly imported by gnatcov +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + +# Run the same test but passing the annotations either at instrumentation time +# or at coverage time. This should yield the same results. + +TestCase(category=CAT.decision).run( + CovControl( + covoptions="--external-annotations=../exemptions.toml", + instroptions="", + ), + subdirhint="cov_", +) + +if thistest.options.trace_mode == "src": + TestCase(category=CAT.decision).run( + CovControl( + instroptions="--external-annotations=../exemptions.toml", + ), + subdirhint="instr_", + ) + +thistest.result() diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index bc8722e6c..7e40dd18b 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -31,6 +31,7 @@ with Coverage.Source; use Coverage.Source; with Coverage.Tags; with Instrument; with Outputs; use Outputs; +with SS_Annotations; use SS_Annotations; with Subprocesses; with Switches; use Switches; with Traces_Disa; @@ -437,6 +438,8 @@ package body Annotations is return; end if; + Import_External_Exemptions (File_Index); + Populate_Annotations (File_Index, Exemption); Populate_Annotations (File_Index, Disable_Coverage); ST := Scope_Traversal (Comp_Unit (File_Index)); @@ -531,9 +534,16 @@ package body Annotations is ----------------------------------- function Get_Exemption_Violation_Count - (Sloc : Source_Location) return Natural is + (Sloc : Source_Location) return Natural + is + use ALI_Annotation_Maps; + Cur : constant Cursor := Get_Annotation (Sloc); begin - return Get_Annotations (Sloc.Source_File).Element (Sloc).Violation_Count; + if Has_Element (Cur) then + return Element (Cur).Violation_Count; + else + return 0; + end if; end Get_Exemption_Violation_Count; ----------------------------------- @@ -541,10 +551,16 @@ package body Annotations is ----------------------------------- function Get_Exemption_Undet_Cov_Count - (Sloc : Source_Location) return Natural is + (Sloc : Source_Location) return Natural + is + use ALI_Annotation_Maps; + Cur : constant Cursor := Get_Annotation (Sloc); begin - return Get_Annotations (Sloc.Source_File) - .Element (Sloc).Undetermined_Cov_Count; + if Has_Element (Cur) then + return Element (Cur).Undetermined_Cov_Count; + else + return 0; + end if; end Get_Exemption_Undet_Cov_Count; --------------------------- @@ -552,9 +568,16 @@ package body Annotations is --------------------------- function Get_Exemption_Message - (Sloc : Source_Location) return String_Access is + (Sloc : Source_Location) return String_Access + is + use ALI_Annotation_Maps; + Cur : constant Cursor := Get_Annotation (Sloc); begin - return Get_Annotations (Sloc.Source_File).Element (Sloc).Message; + if Has_Element (Cur) then + return Element (Cur).Message; + else + return null; + end if; end Get_Exemption_Message; ------------------------ diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index fa12092c4..d42c77b7b 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -176,7 +176,8 @@ package Command_Line is Opt_CPP_Opts, Opt_Files, Opt_Runtime_Dir, - Opt_Compiler_Wrappers); + Opt_Compiler_Wrappers, + Opt_Ext_Annotations); -- Set of string list options we support. More complete descriptions below. subtype Cmd_Instrument is Command_Type @@ -1484,7 +1485,15 @@ package Command_Line is "List of compiler drivers for which we should generate wrappers." & " Supported compilers are: gcc, g++.", Commands => (Cmd_Print_GPR_Registry => False, others => True), - Internal => True) + Internal => True), + + Opt_Ext_Annotations => Create + (Long_Name => "--external-annotations", + Help => "Specify external annotation files", + Commands => + (Cmd_Instrument | Cmd_Coverage => True, others => False), + Pattern => "FILENAME|@LISTFILE", + Internal => True) ); procedure Bool_Callback diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 3d2f897d1..246ca65bf 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -1731,7 +1731,7 @@ package body Files_Table is Current_Annot_Sloc : Source_Location; Current_Annotation : ALI_Annotation; - Start_Annotation : constant ALI_Annotation_Kind := + Start_Annotation : constant Src_Annotation_Kind := (case Kind is when Exemption => Exempt_On, when Disable_Coverage => Cov_Off); diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 018f2080e..96e80c35c 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -1,4 +1,4 @@ -with "gnat_util", "gnatcoll", "gpr2", "libadalang", "libclang"; +with "gnat_util", "gnatcoll", "gpr2", "libadalang", "libclang", "stable_sloc"; project Gnatcov is diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 1ed979b3f..5adb8b689 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -79,6 +79,7 @@ with Qemu_Traces; with Rundrv; use Rundrv; with SC_Obligations; use SC_Obligations; with Setup_RTS; use Setup_RTS; +with SS_Annotations; use SS_Annotations; with Strings; use Strings; with Switches; use Switches; with Temp_Dirs; use Temp_Dirs; @@ -830,6 +831,10 @@ procedure GNATcov_Bits_Specific is end; end if; + for Arg of Args.String_List_Args (Opt_Ext_Annotations) loop + Load_Ext_Annotations (Arg); + end loop; + -- ... then, handle remaning arguments, which have subcommand-specific -- meanings. diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index f3cdc4f07..61b7da70f 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -53,6 +53,7 @@ with Project; with SCOs; with Slocs; with Snames; use Snames; +with SS_Annotations; use SS_Annotations; with Table; with Text_Files; use Text_Files; @@ -3860,7 +3861,7 @@ package body Instrument.Ada_Unit is Kind := Get_Arg (Prag_Args, 2); begin - Result.Kind := ALI_Annotation_Kind'Value (Image (Kind)); + Result.Kind := Src_Annotation_Kind'Value (Image (Kind)); exception when Constraint_Error => Report @@ -9647,6 +9648,12 @@ package body Instrument.Ada_Unit is UIC.Import_Annotations (Created_Units); + -- Import external exemption annotations + + for Cur in Created_Units.Iterate loop + Import_External_Exemptions (Created_Unit_Maps.Key (Cur)); + end loop; + -- Import non-instrumented SCOs in the internal tables Import_Non_Instrumented_LL_SCOs (UIC, SCO_Map); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index ceb2d5184..a5d2a2468 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -41,6 +41,7 @@ with Hex_Images; use Hex_Images; with Outputs; use Outputs; with Paths; use Paths; with SCOs; +with SS_Annotations; use SS_Annotations; with System; use System; with Table; with Text_Files; use Text_Files; @@ -3491,10 +3492,13 @@ package body Instrument.C is end; end loop; - -- Import annotations in our internal tables + -- Import Annots in our internal tables Filter_Annotations (UIC); - Import_Annotations (UIC, UIC.CUs); + UIC.Import_Annotations (UIC.CUs); + for Cur in UIC.CUs.Iterate loop + Import_External_Exemptions (Created_Unit_Maps.Key (Cur)); + end loop; Import_Non_Instrumented_LL_SCOs (UIC, SCO_Map); for Cur in UIC.Instrumented_Entities.Iterate loop diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index ff8a8a09d..62b8a6294 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -663,4 +663,41 @@ package Instrument.Common is -- Extract analysis options from the Args command line arguments and update -- Self accordingly. + subtype Instr_Annotation_Kind is Any_Annotation_Kind range + Dump_Buffers .. Any_Annotation_Kind'Last; + -- Annotation kinds that are relevant for the instrumentation step + + type Instr_Annotation (Kind : Instr_Annotation_Kind := Dump_Buffers) is + record + + Insert_After : Boolean := False; + -- For instrumenters where this is applicable, consider that the + -- annotation should apply after the designated entity rather than + -- before. + + -- Explicitly list all annotation kinds to get a compilation warning + -- when adding new annotation kind in ALI_Files but not here. + + case Kind is + when Dump_Buffers => + Trace_Prefix : Unbounded_String; + -- Optional trace prefix for the buffer dump, left empty if not + -- specified. + + when Cov_Off => + Justification : Unbounded_String; + -- Justification for why the region is disabled for coverage + + when Reset_Buffers | Cov_On => + null; + end case; + end record; + -- Represents one annotation, with all the relevant information needed by + -- the instrumenters. + + package Instr_Annotation_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Local_Source_Location, + Element_Type => Instr_Annotation); + subtype Instr_Annotation_Map is Instr_Annotation_Maps.Map; + end Instrument.Common; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 146ae0fdb..bbf443028 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -171,6 +171,14 @@ package Instrument is -- Example: passing the qualified name Foo.Bar will return the string -- "foo_bar". + function Has_Prefix (Name, Prefix : Ada_Qualified_Name) return Boolean is + (Prefix.Last_Index <= Name.Last_Index + and then + (for all I in 1 .. Prefix.Last_Index + => Prefix.Constant_Reference (I) = Name.Constant_Reference (I))); + -- Returns whether Name starts with the same identifiers as Prefix, case + -- sensitive. + function CU_Name_For_Unit (Unit : Ada_Qualified_Name; Part : Unit_Parts) return Compilation_Unit_Part; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 19f354285..2258228e6 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -5353,6 +5353,21 @@ package body SC_Obligations is return Get_Annotations (Comp_Unit (SFI)); end Get_Annotations; + -------------------- + -- Get_Annotation -- + -------------------- + + function Get_Annotation + (Sloc : Source_Location) return ALI_Annotation_Maps.Cursor + is + CU : constant CU_Id := Comp_Unit (Sloc.Source_File); + begin + if CU = No_CU_Id then + return ALI_Annotation_Maps.No_Element; + end if; + return CU_Vector.Constant_Reference (CU).ALI_Annotations.Find (Sloc); + end Get_Annotation; + ------------------------- -- Get_All_Annotations -- ------------------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 89d1fcd9e..0064e83aa 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -153,15 +153,31 @@ package SC_Obligations is -- Emit an error message for any unit of interest for which no object code -- has been seen. - --------------- - -- ALI files -- - --------------- - - type ALI_Annotation_Kind is - (Exempt_On, Exempt_Off, Dump_Buffers, Reset_Buffers, Cov_On, Cov_Off); + ------------------------------- + -- ALI files and annotations -- + ------------------------------- + + type Any_Annotation_Kind is + (Unknown, + Exempt_Region, + Exempt_On, + Exempt_Off, + Dump_Buffers, + Reset_Buffers, + Cov_On, + Cov_Off); + + subtype Src_Annotation_Kind is Any_Annotation_Kind range + Exempt_On .. Cov_Off; + -- All annotation kind that can be found in pragma Annotate / comments + -- supported by gnatcov. + + subtype ALI_Annotation_Kind is Any_Annotation_Kind range + Exempt_On .. Exempt_Off; + -- Annotation kinds that can be found in ALI files type ALI_Annotation is record - Kind : ALI_Annotation_Kind; + Kind : Src_Annotation_Kind; -- On or Off, Dump or Reset coverage buffers Message : String_Access; @@ -201,6 +217,11 @@ package SC_Obligations is -- Return the set of annotations for the given compilation unit / source -- file index. + function Get_Annotation + (Sloc : Source_Location) return ALI_Annotation_Maps.Cursor; + -- Accessor for the ALI_Annotation_Map, to avoid copying the entire map + -- when only a single annotation is needed. + function Get_All_Annotations return ALI_Annotation_Maps.Map; -- Return all annotations diff --git a/tools/gnatcov/ss_annotations.adb b/tools/gnatcov/ss_annotations.adb new file mode 100644 index 000000000..80278855f --- /dev/null +++ b/tools/gnatcov/ss_annotations.adb @@ -0,0 +1,410 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 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.Directories; + +with GNATCOLL.VFS; use GNATCOLL.VFS; + +with TOML; + +with Stable_Sloc; use Stable_Sloc; +with Stable_Sloc.TOML_Utils; use Stable_Sloc.TOML_Utils; + +with Files_Table; use Files_Table; +with Instrument; use Instrument; +with Outputs; use Outputs; + +package body SS_Annotations is + use type Unbounded_String; + + Xcov_Namespace : constant Ada_Qualified_Name := To_Qualified_Name ("xcov"); + -- Common prefix for all stable_sloc purposes that gnatcov recognizes + + Exemption_Namespace : constant Ada_Qualified_Name := + Xcov_Namespace & To_Qualified_Name ("exempt"); + -- Common prefix for all exemption related annotations + + Exempt_On_Purpose : constant Ada_Qualified_Name := + Exemption_Namespace & To_Qualified_Name ("on"); + Exempt_Off_Purpose : constant Ada_Qualified_Name := + Exemption_Namespace & To_Qualified_Name ("off"); + Exempt_Region_Purpose : constant Ada_Qualified_Name := + Exemption_Namespace & To_Qualified_Name ("region"); + + Buffers_Namespace : constant Ada_Qualified_Name := + Xcov_Namespace & To_Qualified_Name ("buffers"); + -- Common prefix for all buffer manipulation related annotations + + Buffers_Dump_Purpose : constant Ada_Qualified_Name := + Buffers_Namespace & To_Qualified_Name ("dump"); + Buffers_Reset_Purpose : constant Ada_Qualified_Name := + Buffers_Namespace & To_Qualified_Name ("reset"); + + Coverage_Namespace : constant Ada_Qualified_Name := + Xcov_Namespace & To_Qualified_Name ("cov"); + -- Common prefix to instruct gnatcov to enable or disable coverage on a + -- given location + + Cov_Off_Purpose : constant Ada_Qualified_Name := + Coverage_Namespace & To_Qualified_Name ("off"); + Cov_On_Purpose : constant Ada_Qualified_Name := + Coverage_Namespace & To_Qualified_Name ("on"); + + function Annotation_Kind + (Match : Match_Result) return Any_Annotation_Kind; + -- Convert the purpose string in Match.Annotation into one of the + -- recognized annotation kinds, based on the purpose strings defined above. + -- + -- Return Unknown if there is no "purpose" field in the annotation, or if + -- it is empty or unknown. + + procedure Report_Failed (Match : Match_Result) with + Pre => not Match.Success; + -- Report the diagnostics for Match + + function "+" + (Sloc : TOML.Source_Location) return Slocs.Local_Source_Location is + (Line => Sloc.Line, Column => Sloc.Column) with Unreferenced; + + --------------------- + -- Annotation_Kind -- + --------------------- + + function Annotation_Kind + (Match : Match_Result) return Any_Annotation_Kind + is + Purpose : constant Ada_Qualified_Name := + To_Qualified_Name + (+Get_Or_Null (Match.Annotation, "purpose")); + + begin + if Purpose.Is_Empty + or else Purpose.Element (1) /= Xcov_Namespace.Last_Element + or else Purpose.Last_Index < 2 + then + return Unknown; + end if; + + if Purpose.Element (2) = Exemption_Namespace.Last_Element then + + -- Convert exemption annotation kind + + if Purpose.Last_Index < 3 then + return Unknown; + elsif Purpose.Element (3) = Exempt_On_Purpose.Last_Element then + return Exempt_On; + elsif Purpose.Element (3) = Exempt_Off_Purpose.Last_Element then + return Exempt_Off; + elsif Purpose.Element (3) = Exempt_Region_Purpose.Last_Element then + return Exempt_Region; + end if; + elsif Purpose.Element (2) = Buffers_Namespace.Last_Element then + + -- Convert buffer annotation kind + + if Purpose.Last_Index < 3 then + return Unknown; + elsif Purpose.Element (3) = Buffers_Dump_Purpose.Last_Element then + return Dump_Buffers; + elsif Purpose.Element (3) = Buffers_Reset_Purpose.Last_Element then + return Reset_Buffers; + end if; + + elsif Purpose.Element (2) = Coverage_Namespace.Last_Element then + if Purpose.Last_Index < 3 then + return Unknown; + elsif Purpose.Element (3) = Cov_Off_Purpose.Last_Element then + return Cov_Off; + elsif Purpose.Element (3) = Cov_On_Purpose.Last_Element then + return Cov_On; + end if; + end if; + + return Unknown; + end Annotation_Kind; + + ------------------- + -- Report_Failed -- + ------------------- + + procedure Report_Failed (Match : Match_Result) is + begin + Warn + (Match.File.Display_Full_Name & ": " & (+Match.Identifier) & ": " + & (+Match.Diagnostic)); + end Report_Failed; + + -------------------------- + -- Load_Ext_Annotations -- + -------------------------- + + procedure Load_Ext_Annotations (Annotation_File : Unbounded_String) is + Load_Diags : constant Load_Diagnostic_Arr := Load_Entries + (GNATCOLL.VFS.Create (+US.To_String (Annotation_File)), + DB => Ext_Annotation_DB); + begin + Ext_Annotation_Trace.Trace + ("Loading external annotations from " & (+Annotation_File)); + for Diag of Load_Diags loop + Warn (Format_Diagnostic (Diag)); + end loop; + end Load_Ext_Annotations; + + -------------------------------- + -- Import_External_Exemptions -- + -------------------------------- + + procedure Import_External_Exemptions (FI : Source_File_Index) + is + File : Virtual_File; + Matches : Match_Result_Vec; + Justification : Unbounded_String; + Kind : Any_Annotation_Kind; + New_Annotations : ALI_Annotation_Maps.Map; + begin + -- Exit early if there are no external annotations + + if Is_Empty (Ext_Annotation_DB) then + return; + end if; + + -- Match the entries on FI + + File := Create (+Get_Full_Name (FI)); + Matches := Match_Entries + ((1 => File), + Ext_Annotation_DB, + Purpose_Prefix => To_Ada (Exemption_Namespace)); + + -- Process each match result + + for Match of Matches loop + Kind := Annotation_Kind (Match); + + -- Filter unknown annotations first + + if Kind not in Exempt_Region .. Exempt_Off then + Warn + ("Unexpected or unknown annotation kind for annotation """ + & (+Match.Identifier) & """: " + & (+Get_Or_Null (Match.Annotation, "purpose"))); + + -- Then failed matches + + elsif not Match.Success then + Report_Failed (Match); + else + -- Exempt_Region will insert an Exempt_On / Exempt_Off couple of + -- annotations. + + if Kind in Exempt_Region | Exempt_On then + Justification := TOML_Utils.Get_Or_Null + (Match.Annotation, "justification"); + if Justification = Null_Unbounded_String then + Warn + (Slocs.Image (To_Sloc (Match.Location.Start_Sloc, FI)) + & ": Missing or empty justification for external" + & " exemption annotation """ & (+Match.Identifier) + & """"); + else + declare + use ALI_Annotation_Maps; + Annot : constant ALI_Annotation := + (Kind => Exempt_On, + Message => new String'(+Justification), + others => <>); + + Sloc : constant Slocs.Source_Location := + To_Sloc (Match.Location.Start_Sloc, FI); + Cur : Cursor := Get_Annotation (Sloc); + Existing_Annot : ALI_Annotation; + begin + if not Has_Element (Cur) then + Cur := New_Annotations.Find (Sloc); + end if; + + if Has_Element (Cur) then + Existing_Annot := Element (Cur); + + -- Do not warn if the annotation is of the same + -- kind and identical message, as this could simply + -- be a case of external annotations passed both + -- during instrumentation and coverage report + -- computation. + + if Existing_Annot.Kind /= Annot.Kind + or else Existing_Annot.Message.all + /= Annot.Message.all + then + Warn + (Slocs.Image (Sloc) + & ": Conflicting annotations for this line," + & " ignoring the external annotation """ + & (+Match.Identifier) & """"); + end if; + else + New_Annotations.Insert (Sloc, Annot); + end if; + end; + end if; + end if; + + if Kind in Exempt_Region | Exempt_Off then + declare + use ALI_Annotation_Maps; + Annot : constant ALI_Annotation := + (Kind => Exempt_Off, + Message => new String'(+Justification), + others => <>); + + Sloc : constant Slocs.Source_Location := + To_Sloc (Match.Location.End_Sloc, FI); + Cur : Cursor := Get_Annotation (Sloc); + Existing_Annot : ALI_Annotation; + begin + -- Also check if the new annotations don't already contain + -- an annotation for this sloc. + + if not Has_Element (Cur) then + Cur := New_Annotations.Find (Sloc); + end if; + + if Has_Element (Cur) then + Existing_Annot := Element (Cur); + + -- Same for Exempt_Off, except the message isn't + -- relevant here. + + if Existing_Annot.Kind /= Annot.Kind then + Warn + (Slocs.Image (Sloc) + & ": Conflicting annotations for this line," + & " ignoring the external annotation """ + & (+Match.Identifier) & """"); + end if; + else + New_Annotations.Insert (Sloc, Annot); + end if; + end; + end if; + end if; + end loop; + Set_Annotations (New_Annotations); + end Import_External_Exemptions; + + ---------------------------- + -- Get_Buffer_Annotations -- + ---------------------------- + + function Get_Buffer_Annotations + (Filename : String) return Instrument.Common.Instr_Annotation_Map + is + use Instrument.Common; + VF : constant Virtual_File := Create (+Filename); + Matches : Match_Result_Vec; + Kind : Any_Annotation_Kind; + Result : Instr_Annotation_Map; + begin + -- Exit early if there are no external annotations + + if Is_Empty (Ext_Annotation_DB) then + return Instr_Annotation_Maps.Empty_Map; + end if; + + Matches := Match_Entries + ((1 => VF), + Ext_Annotation_DB, + Purpose_Prefix => To_Ada (Buffers_Namespace)); + + -- Process each annotation result + + for Match of Matches loop + if not Match.Success then + Report_Failed (Match); + goto Continue; + end if; + + Kind := Annotation_Kind (Match); + if Kind not in Dump_Buffers | Reset_Buffers then + Warn + ("Unexpected or unknown annotation kind for annotation """ + & (+Match.Identifier) & """: " + & (+Get_Or_Null (Match.Annotation, "purpose"))); + goto Continue; + end if; + declare + Start_Loc : constant Slocs.Local_Source_Location := + +Match.Location.Start_Sloc; + -- We only use the start location to represent buffer dump / reset + -- annotations, as a range is ill-defined for those. + + New_Annotation : Instr_Annotation (Kind); + Cur : Instr_Annotation_Maps.Cursor; + Inserted : Boolean; + begin + -- Explicitly inspect each annotation kind to get a warning if a + -- new annotation kind is added in Instrument.Common but not here. + + case New_Annotation.Kind is + when Dump_Buffers => + New_Annotation.Trace_Prefix := + Get_Or_Null (Match.Annotation, "trace_prefix"); + + when Reset_Buffers => + null; + + when Cov_On | Cov_Off => + raise Program_Error with "unreachable"; + end case; + New_Annotation.Insert_After := False; + declare + use TOML; + begin + if Match.Annotation.Has ("insert_after") then + if Match.Annotation.Get ("insert_after").Kind /= TOML_Boolean + then + Warn + ("Invalid type for ""insert_after"" field in annotation" + & """" & (+Match.Identifier) & """, should be" + & " TOML_BOOLEAN."); + else + New_Annotation.Insert_After := + Match.Annotation.Get ("insert_after").As_Boolean; + end if; + end if; + end; + Result.Insert (Start_Loc, New_Annotation, Cur, Inserted); + + -- Tolerate duplicate annotations if they are the same + + if not Inserted and then Result.Reference (Cur) /= New_Annotation + then + Warn + (Ada.Directories.Simple_Name (Filename) & ":" + & Slocs.Image (Start_Loc) + & ": Conflicting annotations for this line, ignoring the" + & " external annotation """ & (+Match.Identifier) & """"); + end if; + end; + <> + end loop; + + return Result; + end Get_Buffer_Annotations; + +end SS_Annotations; diff --git a/tools/gnatcov/ss_annotations.ads b/tools/gnatcov/ss_annotations.ads new file mode 100644 index 000000000..9f7c0a400 --- /dev/null +++ b/tools/gnatcov/ss_annotations.ads @@ -0,0 +1,76 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 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. -- +------------------------------------------------------------------------------ + +-- General interfacing with Stable_Sloc for external annotations + +with Stable_Sloc; + +with Instrument.Common; +with Logging; +with Slocs; +with Strings; use Strings; +with SC_Obligations; use SC_Obligations; +with Types; use Types; + +package SS_Annotations is + + Ext_Annotation_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("EXT_ANNOTATION"); + -- Trace for external annotation handling + + Ext_Annotation_DB : Stable_Sloc.Entry_DB; + -- Database of external annotations entries. + + -- Stable_Sloc sloc type to our sloc type utilities + + function "+" (S : Stable_Sloc.Sloc) return Slocs.Local_Source_Location is + (Line => S.Line, + Column => S.Column); + + function "+" + (S : Stable_Sloc.Sloc_Span) return Slocs.Local_Source_Location_Range is + (First_Sloc => +S.Start_Sloc, + Last_Sloc => +S.End_Sloc); + + function To_Sloc + (S : Stable_Sloc.Sloc; + FI : Source_File_Index) return Slocs.Source_Location is + (Source_File => FI, L => +S); + + function To_Sloc_Range + (SR : Stable_Sloc.Sloc_Span; + FI : Source_File_Index) return Slocs.Source_Location_Range is + (Source_File => FI, L => +SR); + + procedure Load_Ext_Annotations (Annotation_File : Unbounded_String); + -- Load the annotations in Annotation_File into our internal annotation + -- database. + + procedure Import_External_Exemptions + (FI : Source_File_Index); + -- Search for external exemptions in FI, from the annotations loaded in + -- Ext_Annotation_DB. + -- + -- The newly added annotations will include CU in the corresponding CU + -- field. + + function Get_Buffer_Annotations + (Filename : String) return Instrument.Common.Instr_Annotation_Map; + -- Get the buffer annotations relevant to instrumentation for Filename. + +end SS_Annotations; From b9f2c631f3a34093c90394e7aed56927ab161b6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 22 Aug 2024 11:11:19 +0200 Subject: [PATCH 0938/1483] Add support for external insturmenter annotations This includes support for buffer dump/reset and the Cov_On/Cov_Off annotations. External annotations are processed differently between Ada and C-like languages: For Ada, we need to materialize buffer the annotations before the first instrumentation of a source file, as the annotations are given via absolute source locations, which we do not track when instrumenting the sources. Thus the instrumenter inserts the corresponding pragma Annotate for each external annotation for the source being instrumented. the pragmas are then replaced by the "in-source" buffer annotation processing mechanism. If a file is not a unit of interest but still has external annotations attached to it, then the analysis tree is first rewritten to add the annotations pragmas. For C/C++, the external buffer annotations are processed at the same time as in-source annotations, as this is done prior to instrumentation, and are directly transformed into the proper buffer management function call. External Cov_Off/Cov_On annotations for C/C++ are loaded as we traverse the AST, as we do not have an a-priori list of the files which need to be processed. (cherry picked from commit c65217e6156e7b6892a882965cfd7c432c4951d2) --- .../ext_annotations/buffers/ada_no_unit.toml | 25 + .../ext_annotations/buffers/ada_unit.toml | 27 + .../tests/ext_annotations/buffers/c.toml | 27 + .../tests/ext_annotations/buffers/c_unit.c | 5 + .../tests/ext_annotations/buffers/cpp.toml | 26 + .../ext_annotations/buffers/cpp_unit.cpp | 8 + .../tests/ext_annotations/buffers/main.adb | 15 + .../tests/ext_annotations/buffers/pkg.adb | 7 + .../tests/ext_annotations/buffers/pkg.ads | 7 + .../tests/ext_annotations/buffers/pkh.adb | 7 + .../tests/ext_annotations/buffers/pkh.ads | 7 + .../tests/ext_annotations/buffers/test.opt | 1 + .../tests/ext_annotations/buffers/test.py | 85 +++ .../ext_annotations/diagnostics/buffers.toml | 36 + .../ext_annotations/diagnostics/cov_off.toml | 53 ++ .../diagnostics/exemptions.toml | 47 ++ .../ext_annotations/diagnostics/expected.txt | 11 + .../diagnostics/load_fail.toml | 22 + .../ext_annotations/diagnostics/main.adb | 4 + .../ext_annotations/diagnostics/test.opt | 1 + .../tests/ext_annotations/diagnostics/test.py | 41 ++ .../selective_cov/Ada/annotations.toml | 69 ++ .../selective_cov/Ada/src/test_main.adb | 26 + .../ext_annotations/selective_cov/Ada/test.py | 20 + .../selective_cov/C/annotations.toml | 43 ++ .../selective_cov/C/src/cons_a_b.txt | 12 + .../ext_annotations/selective_cov/C/src/pkg.h | 17 + .../selective_cov/C/src/test_a.c | 19 + .../selective_cov/C/src/test_b.c | 19 + .../ext_annotations/selective_cov/C/test.py | 28 + .../ext_annotations/selective_cov/extra.opt | 1 + tools/gnatcov/instrument-ada_unit.adb | 255 ++++++- tools/gnatcov/instrument-c.adb | 666 +++++++++++++----- tools/gnatcov/instrument-c.ads | 7 - tools/gnatcov/instrument-common.adb | 74 ++ tools/gnatcov/instrument-common.ads | 22 +- tools/gnatcov/ss_annotations.adb | 329 +++++++-- tools/gnatcov/ss_annotations.ads | 19 +- 38 files changed, 1841 insertions(+), 247 deletions(-) create mode 100644 testsuite/tests/ext_annotations/buffers/ada_no_unit.toml create mode 100644 testsuite/tests/ext_annotations/buffers/ada_unit.toml create mode 100644 testsuite/tests/ext_annotations/buffers/c.toml create mode 100644 testsuite/tests/ext_annotations/buffers/c_unit.c create mode 100644 testsuite/tests/ext_annotations/buffers/cpp.toml create mode 100644 testsuite/tests/ext_annotations/buffers/cpp_unit.cpp create mode 100644 testsuite/tests/ext_annotations/buffers/main.adb create mode 100644 testsuite/tests/ext_annotations/buffers/pkg.adb create mode 100644 testsuite/tests/ext_annotations/buffers/pkg.ads create mode 100644 testsuite/tests/ext_annotations/buffers/pkh.adb create mode 100644 testsuite/tests/ext_annotations/buffers/pkh.ads create mode 100644 testsuite/tests/ext_annotations/buffers/test.opt create mode 100644 testsuite/tests/ext_annotations/buffers/test.py create mode 100644 testsuite/tests/ext_annotations/diagnostics/buffers.toml create mode 100644 testsuite/tests/ext_annotations/diagnostics/cov_off.toml create mode 100644 testsuite/tests/ext_annotations/diagnostics/exemptions.toml create mode 100644 testsuite/tests/ext_annotations/diagnostics/expected.txt create mode 100644 testsuite/tests/ext_annotations/diagnostics/load_fail.toml create mode 100644 testsuite/tests/ext_annotations/diagnostics/main.adb create mode 100644 testsuite/tests/ext_annotations/diagnostics/test.opt create mode 100644 testsuite/tests/ext_annotations/diagnostics/test.py create mode 100644 testsuite/tests/ext_annotations/selective_cov/Ada/annotations.toml create mode 100644 testsuite/tests/ext_annotations/selective_cov/Ada/src/test_main.adb create mode 100644 testsuite/tests/ext_annotations/selective_cov/Ada/test.py create mode 100644 testsuite/tests/ext_annotations/selective_cov/C/annotations.toml create mode 100644 testsuite/tests/ext_annotations/selective_cov/C/src/cons_a_b.txt create mode 100644 testsuite/tests/ext_annotations/selective_cov/C/src/pkg.h create mode 100644 testsuite/tests/ext_annotations/selective_cov/C/src/test_a.c create mode 100644 testsuite/tests/ext_annotations/selective_cov/C/src/test_b.c create mode 100644 testsuite/tests/ext_annotations/selective_cov/C/test.py create mode 100644 testsuite/tests/ext_annotations/selective_cov/extra.opt diff --git a/testsuite/tests/ext_annotations/buffers/ada_no_unit.toml b/testsuite/tests/ext_annotations/buffers/ada_no_unit.toml new file mode 100644 index 000000000..4ecdf0459 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/ada_no_unit.toml @@ -0,0 +1,25 @@ +# These two entries will reset the buffers before the first statement in +# do_dump then dump them before the end of the procedure. + +[dump_buffs] +kind="absolute" +file="pkh.adb" +[dump_buffs.matcher] +start_line=5 +start_col=11 +end_line=5 +end_col=11 +[[dump_buffs.annotations]] +purpose="xcov.buffers.dump" +insert_after=true + +[dump_reset] +kind="absolute" +file="pkh.adb" +[dump_reset.matcher] +start_line=5 +start_col=7 +end_line=5 +end_col=7 +[[dump_reset.annotations]] +purpose="xcov.buffers.reset" diff --git a/testsuite/tests/ext_annotations/buffers/ada_unit.toml b/testsuite/tests/ext_annotations/buffers/ada_unit.toml new file mode 100644 index 000000000..7e8b6af99 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/ada_unit.toml @@ -0,0 +1,27 @@ +# These two entries will reset the buffers before the first statement in +# do_dump then dump them before the end of the procedure. + +[dump_buffs] +kind="absolute" +file="pkg.adb" +[dump_buffs.matcher] +start_line=5 +start_col=11 +end_line=5 +end_col=11 +[[dump_buffs.annotations]] +purpose="xcov.buffers.dump" +# Use the same trace prefix as the project name to simply test code +trace_prefix='"prj_ada_unit"' +insert_after=true + +[dump_reset] +kind="absolute" +file="pkg.adb" +[dump_reset.matcher] +start_line=5 +start_col=7 +end_line=5 +end_col=7 +[[dump_reset.annotations]] +purpose="xcov.buffers.reset" diff --git a/testsuite/tests/ext_annotations/buffers/c.toml b/testsuite/tests/ext_annotations/buffers/c.toml new file mode 100644 index 000000000..e2389e19e --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/c.toml @@ -0,0 +1,27 @@ +# These two entries will reset the buffers before the first statement in +# do_c_dump then dump them before the end of the function. +# +# The end_* fields do not really matter for buffer annotations, they are +# just set to something valid. + +[dump_buffs] +kind="absolute" +file="c_unit.c" +[dump_buffs.matcher] +start_line=4 +start_col=13 +end_line=4 +end_col=13 +[[dump_buffs.annotations]] +purpose="xcov.buffers.dump" + +[dump_reset] +kind="absolute" +file="c_unit.c" +[dump_reset.matcher] +start_line=4 +start_col=3 +end_line=4 +end_col=3 +[[dump_reset.annotations]] +purpose="xcov.buffers.reset" diff --git a/testsuite/tests/ext_annotations/buffers/c_unit.c b/testsuite/tests/ext_annotations/buffers/c_unit.c new file mode 100644 index 000000000..dbcdac133 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/c_unit.c @@ -0,0 +1,5 @@ +void +do_c_dump () +{ + int x = 0; // Generate an obligation +} diff --git a/testsuite/tests/ext_annotations/buffers/cpp.toml b/testsuite/tests/ext_annotations/buffers/cpp.toml new file mode 100644 index 000000000..27709dda4 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/cpp.toml @@ -0,0 +1,26 @@ +# These two entries will reset the buffers before the first statement in +# do_cpp_dump then dump them before the end of the function. + +[dump_buffs] +kind="absolute" +file="cpp_unit.cpp" +[dump_buffs.matcher] +start_line=6 +start_col=16 +end_line=6 +end_col=16 +[[dump_buffs.annotations]] +purpose="xcov.buffers.dump" +# Use the same trace prefix as the project name to simply test code +trace_prefix='"prj_cpp"' + +[dump_reset] +kind="absolute" +file="cpp_unit.cpp" +[dump_reset.matcher] +start_line=6 +start_col=5 +end_line=6 +end_col=5 +[[dump_reset.annotations]] +purpose="xcov.buffers.reset" diff --git a/testsuite/tests/ext_annotations/buffers/cpp_unit.cpp b/testsuite/tests/ext_annotations/buffers/cpp_unit.cpp new file mode 100644 index 000000000..ae71de2da --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/cpp_unit.cpp @@ -0,0 +1,8 @@ +extern "C" +{ + void + do_cpp_dump () + { + int x = 0; // generate a SCO to check reports + } +} diff --git a/testsuite/tests/ext_annotations/buffers/main.adb b/testsuite/tests/ext_annotations/buffers/main.adb new file mode 100644 index 000000000..2e82f736a --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/main.adb @@ -0,0 +1,15 @@ +with Pkg; +with Pkh; + +procedure Main is + procedure Do_CPP_Dump; + pragma Import (C, Do_CPP_Dump, "do_cpp_dump"); + + procedure Do_C_Dump; + pragma Import (C, Do_C_Dump, "do_c_dump"); +begin + Do_C_Dump; + Do_CPP_Dump; + Pkg.Do_Dump; + Pkh.Do_Dump; +end Main; diff --git a/testsuite/tests/ext_annotations/buffers/pkg.adb b/testsuite/tests/ext_annotations/buffers/pkg.adb new file mode 100644 index 000000000..09f301c93 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/pkg.adb @@ -0,0 +1,7 @@ +package body Pkg is + + procedure Do_Dump is + begin + null; + end Do_Dump; +end Pkg; diff --git a/testsuite/tests/ext_annotations/buffers/pkg.ads b/testsuite/tests/ext_annotations/buffers/pkg.ads new file mode 100644 index 000000000..3969881df --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/pkg.ads @@ -0,0 +1,7 @@ +-- This unit is part of the set of units of interest + +package Pkg is + + procedure Do_Dump; + +end Pkg; diff --git a/testsuite/tests/ext_annotations/buffers/pkh.adb b/testsuite/tests/ext_annotations/buffers/pkh.adb new file mode 100644 index 000000000..54b1a7f0f --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/pkh.adb @@ -0,0 +1,7 @@ +package body Pkh is + + procedure Do_Dump is + begin + null; + end Do_Dump; +end Pkh; diff --git a/testsuite/tests/ext_annotations/buffers/pkh.ads b/testsuite/tests/ext_annotations/buffers/pkh.ads new file mode 100644 index 000000000..603cc7f99 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/pkh.ads @@ -0,0 +1,7 @@ +-- This unit is not part of the set of units of interest + +package Pkh is + + procedure Do_Dump; + +end Pkh; diff --git a/testsuite/tests/ext_annotations/buffers/test.opt b/testsuite/tests/ext_annotations/buffers/test.opt new file mode 100644 index 000000000..7f9195f94 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/test.opt @@ -0,0 +1 @@ +!C++ DEAD Requires C++ compiler diff --git a/testsuite/tests/ext_annotations/buffers/test.py b/testsuite/tests/ext_annotations/buffers/test.py new file mode 100644 index 000000000..dc0f900a8 --- /dev/null +++ b/testsuite/tests/ext_annotations/buffers/test.py @@ -0,0 +1,85 @@ +""" +Test simple external annotations for buffer management, both for +buffer dump and buffer reset. +""" + +from copy import deepcopy + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir() + + +def run_one(tc_id, annotation_file, expected_results): + """ + Run a whole gnatcov source trace workflow, passing the + given annotation_file to the --external-annotation switch + and checking the expected_results. + + tc_id is used to identify the test case (temporary work dir) + """ + thistest.log(f"====== Running test {tc_id} ======") + tmp.to_subdir(f"tmp_{tc_id}") + prjid = f"prj_{tc_id}" + prj = gprfor( + mains=["main.adb"], + srcdirs=[".."], + langs=["Ada", "C", "C++"], + prjid=prjid, + ) + build_run_and_coverage( + gprsw=GPRswitches(prj), + extra_instr_args=[ + f"--external-annotations={annotation_file}", + "--units=Pkg", + "--units=c_unit.c", + "--units=cpp_unit.cpp", + ], + covlevel="stmt", + mains=["main"], + dump_trigger="manual", + manual_prj_name=prjid, + extra_coverage_args=["-axcov"], + ) + check_xcov_reports( + "obj", + expected_results, + ) + + +default_cov = { + "cpp_unit.cpp.xcov": {"-": {6}}, + "c_unit.c.xcov": {"-": {4}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"-": {5}}, +} + +# CPP first, we expect full coverage for the CPP unit as buffers are cleared +# when entering do_cpp_dump, and dumped at the end of that function +expected_cov = deepcopy(default_cov) +expected_cov["cpp_unit.cpp.xcov"] = {"+": {6}} +run_one("cpp", "../cpp.toml", expected_cov) + +# C then, we expect full coverage for the C unit as buffers are cleared +# when entering do_c_dump, and dumped at the end of that function +expected_cov = deepcopy(default_cov) +expected_cov["c_unit.c.xcov"] = {"+": {4}} +run_one("c", "../c.toml", expected_cov) + +# For Ada, first check the annotations when the file is part of the set of +# units of interest. As above, buffers are cleared entering the Do_Dump +# procedure, then dumped at the end. +expected_cov = deepcopy(default_cov) +expected_cov["pkg.adb.xcov"] = {"+": {5}} +run_one("ada_unit", "../ada_unit.toml", expected_cov) + +# Test when the annotations are not part of a unit of interest. As the buffers +# are handled in the same fashion, no code in a unit of interest should be +# executed. +run_one("ada_no_unit", "../ada_no_unit.toml", default_cov) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/diagnostics/buffers.toml b/testsuite/tests/ext_annotations/diagnostics/buffers.toml new file mode 100644 index 000000000..76813540d --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/buffers.toml @@ -0,0 +1,36 @@ +# All these annotations should load fine, but generate a warning + +[unknown_kind_buffers] +kind="absolute" +file="main.adb" +[unknown_kind_buffers.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[unknown_kind_buffers.annotations]] +purpose="xcov.buffers.foo_bar" + +[duplicate_1] +kind="absolute" +file="main.adb" +[duplicate_1.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[duplicate_1.annotations]] +purpose="xcov.buffers.dump" +justification="this entry is duplicated (same sloc)" + +[duplicate_2] +kind="absolute" +file="main.adb" +[duplicate_2.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[duplicate_2.annotations]] +purpose="xcov.buffers.reset" +justification="this entry is duplicated (same sloc)" diff --git a/testsuite/tests/ext_annotations/diagnostics/cov_off.toml b/testsuite/tests/ext_annotations/diagnostics/cov_off.toml new file mode 100644 index 000000000..cbfb3ba66 --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/cov_off.toml @@ -0,0 +1,53 @@ +# All these entries should either fail to load or produce a warning + +# Fail due to unknown annotation kind +[unknown_kind_cov] +kind="absolute" +file="main.adb" +[unknown_kind_cov.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[unknown_kind_cov.annotations]] +purpose="xcov.cov.foo_bar" + +# Rejected because a cov_on annotation cannot appear first +[cov_on_first] +kind="absolute" +file="main.adb" +[cov_on_first.matcher] +start_line=2 +start_col=4 +end_line=3 +end_col=4 +[[cov_on_first.annotations]] +purpose="xcov.cov.on" + +# Ultimately rejected as the next annotation will be ignored, +# and a cov_off annotation cannot be the last one of a file +[duplicate_cov_1] +kind="absolute" +file="main.adb" +[duplicate_cov_1.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[duplicate_cov_1.annotations]] +purpose="xcov.cov.off" +justification="this entry is duplicated (same sloc)" + +# Rejected as this annotates the same location +[duplicate_cov_2] +kind="absolute" +file="main.adb" +[duplicate_cov_2.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[duplicate_cov_2.annotations]] +purpose="xcov.cov.on" + + diff --git a/testsuite/tests/ext_annotations/diagnostics/exemptions.toml b/testsuite/tests/ext_annotations/diagnostics/exemptions.toml new file mode 100644 index 000000000..51714021d --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/exemptions.toml @@ -0,0 +1,47 @@ +# All these annotations should load fine, but generate a warning + +[unknown_kind_exempt] +kind="absolute" +file="main.adb" +[unknown_kind_exempt.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[unknown_kind_exempt.annotations]] +purpose="xcov.exempt.foo_bar" + +[missing_justif] +kind="absolute" +file="main.adb" +[missing_justif.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[missing_justif.annotations]] +purpose="xcov.exempt.on" + +[duplicate_3] +kind="absolute" +file="main.adb" +[duplicate_3.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[duplicate_3.annotations]] +purpose="xcov.exempt.on" +justification="this entry is duplicated (same sloc)" + +[duplicate_4] +kind="absolute" +file="main.adb" +[duplicate_4.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=4 +[[duplicate_4.annotations]] +purpose="xcov.exempt.off" +justification="this entry is duplicated (same sloc)" diff --git a/testsuite/tests/ext_annotations/diagnostics/expected.txt b/testsuite/tests/ext_annotations/diagnostics/expected.txt new file mode 100644 index 000000000..5bafcd55f --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/expected.txt @@ -0,0 +1,11 @@ +warning: ../load_fail.toml:15:1: Error while parsing entry "missing_field": Missing "annotations" field +warning: ../load_fail.toml:18:1: Error while parsing entry "missing_justif": Missing "kind" field +warning: main.adb:3:4: Conflicting annotations for this line, ignoring the external annotation "duplicate_2" +warning: Unexpected or unknown annotation kind for annotation "unknown_kind_buffers": xcov.buffers.foo_bar +warning: main.adb:3:4: Conflicting annotations for this line, ignoring the external annotation "duplicate_cov_2" +warning: Unexpected or unknown annotation kind for annotation "unknown_kind_cov": xcov.cov.foo_bar +warning: main.adb: 2:4: external Cov_On annotation with no previous Cov_Off annotation, ignoring it. +warning: main.adb: 3:4: external COV_OFF annotation with no subsequent COV_ON annotation, ignoring it. +warning: main.adb:3:4: Conflicting annotations for this line, ignoring the external annotation "duplicate_4" +warning: Unexpected or unknown annotation kind for annotation "unknown_kind_exempt": xcov.exempt.foo_bar +warning: main.adb:3:4: Missing or empty justification for external exemption annotation "missing_justif" diff --git a/testsuite/tests/ext_annotations/diagnostics/load_fail.toml b/testsuite/tests/ext_annotations/diagnostics/load_fail.toml new file mode 100644 index 000000000..d1916e41d --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/load_fail.toml @@ -0,0 +1,22 @@ +# A couple of entries that should fail to load, to ensure we properly +# report them. + +[unknown_kind] +kind="no such kind" +file="main.adb" +[unknown_kind.matcher] +start_line=1 +start_col=1 +end_line=1 +end_col=1 +[[unknown_kind.annotations]] +purpose="xcov.exempt.on" + +[missing_field] +kind="absolute" +file="main.adb" +[missing_justif.matcher] +start_line=1 +start_col=1 +[[missing_justif.annotations]] +purpose="xcov.exempt.on" diff --git a/testsuite/tests/ext_annotations/diagnostics/main.adb b/testsuite/tests/ext_annotations/diagnostics/main.adb new file mode 100644 index 000000000..e0d8401fa --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/main.adb @@ -0,0 +1,4 @@ +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/ext_annotations/diagnostics/test.opt b/testsuite/tests/ext_annotations/diagnostics/test.opt new file mode 100644 index 000000000..e3ab1b655 --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/test.opt @@ -0,0 +1 @@ +bin-traces DEAD requires gnatcov instrumentation for some diagnostics diff --git a/testsuite/tests/ext_annotations/diagnostics/test.py b/testsuite/tests/ext_annotations/diagnostics/test.py new file mode 100644 index 000000000..fc39bbe56 --- /dev/null +++ b/testsuite/tests/ext_annotations/diagnostics/test.py @@ -0,0 +1,41 @@ +""" +Test that gnatcov emits the expected diagnostics when loading external +annotations, for unknown annotations kinds or ill-formed annotation +payloads. +""" + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +prj = gprfor(mains=["main.adb"], srcdirs=[".."]) + +log = "instr.log" + +# Instrument the project with all the external exemptions +xcov_instrument( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + dump_trigger="manual", + extra_args=[ + "--external-annotations=../buffers.toml", + "--external-annotations=../exemptions.toml", + "--external-annotations=../load_fail.toml", + "--external-annotations=../cov_off.toml", + ], + tolerate_messages=".*", + out=log, +) + + +thistest.fail_if_diff( + "../expected.txt", + log, + "Unexpected messages for 'gnatcov instrument' output", +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/selective_cov/Ada/annotations.toml b/testsuite/tests/ext_annotations/selective_cov/Ada/annotations.toml new file mode 100644 index 000000000..1bc199463 --- /dev/null +++ b/testsuite/tests/ext_annotations/selective_cov/Ada/annotations.toml @@ -0,0 +1,69 @@ +[cov_off_1] +file="test_main.adb" +kind="absolute" +[cov_off_1.matcher] +start_line=11 +start_col=5 +end_line=11 +end_col=5 +[[cov_off_1.annotations]] +purpose="xcov.cov.off" + +[cov_on_1] +file="test_main.adb" +kind="absolute" +[cov_on_1.matcher] +start_line=11 +start_col=26 +end_line=11 +end_col=26 +[[cov_on_1.annotations]] +purpose="xcov.cov.on" +insert_after=true + +[cov_off_2] +file="test_main.adb" +kind="absolute" +[cov_off_2.matcher] +start_line=15 +start_col=3 +end_line=15 +end_col=3 +[[cov_off_2.annotations]] +purpose="xcov.cov.off" + +[cov_on_2] +file="test_main.adb" +kind="absolute" +[cov_on_2.matcher] +start_line=15 +start_col=26 +end_line=15 +end_col=26 +[[cov_on_2.annotations]] +purpose="xcov.cov.on" +insert_after=true + +[cov_off_3] +file="test_main.adb" +kind="absolute" +[cov_off_3.matcher] +start_line=17 +start_col=3 +end_line=17 +end_col=3 +[[cov_off_3.annotations]] +justification='"coverage is disabled"' +purpose="xcov.cov.off" + +[cov_on_3] +file="test_main.adb" +kind="absolute" +[cov_on_3.matcher] +start_line=17 +start_col=26 +end_line=17 +end_col=26 +[[cov_on_3.annotations]] +purpose="xcov.cov.on" +insert_after=true diff --git a/testsuite/tests/ext_annotations/selective_cov/Ada/src/test_main.adb b/testsuite/tests/ext_annotations/selective_cov/Ada/src/test_main.adb new file mode 100644 index 000000000..6bb878f98 --- /dev/null +++ b/testsuite/tests/ext_annotations/selective_cov/Ada/src/test_main.adb @@ -0,0 +1,26 @@ +procedure Test_Main +is + A, B : Boolean := True; + + procedure Foo (B: Boolean) is null; -- # cov_on + + procedure Uncovered; + + procedure Uncovered is + begin + Foo (A and then B); -- # cov_off + end Uncovered; + +begin + Foo (A and then B); -- # cov_off + + Foo (A and then B); -- # cov_off + + Foo (A and then B); -- # partial_cov_on +end Test_Main; + +--# test_main.adb +-- +-- /cov_off/ lD ## 0 +-- /cov_on/ l+ ## 0 +-- /partial_cov_on/ l! ## eF- diff --git a/testsuite/tests/ext_annotations/selective_cov/Ada/test.py b/testsuite/tests/ext_annotations/selective_cov/Ada/test.py new file mode 100644 index 000000000..73315bd8e --- /dev/null +++ b/testsuite/tests/ext_annotations/selective_cov/Ada/test.py @@ -0,0 +1,20 @@ +""" +Check gnatcov support for selective instrumentation for Ada. + +This variation of the test uses external annotations instead of +in-source pragmas. +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT, CovControl +from SCOV.tc import TestCase + +TestCase( + category=CAT.mcdc, + tolerate_messages=( + r".* Missing or empty justification for external disabled coverage" + r' region annotation ".*"' + ), +).run(CovControl(instroptions="--external-annotations=../annotations.toml")) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/selective_cov/C/annotations.toml b/testsuite/tests/ext_annotations/selective_cov/C/annotations.toml new file mode 100644 index 000000000..16c01fbda --- /dev/null +++ b/testsuite/tests/ext_annotations/selective_cov/C/annotations.toml @@ -0,0 +1,43 @@ +[cov_off_a] +file="pkg.h" +kind="absolute" +[cov_off_a.matcher] +start_line=5 +start_col=3 +end_line=5 +end_col=20 +[[cov_off_a.annotations]] +purpose="xcov.cov.off" + +[cov_off_b] +file="pkg.h" +kind="absolute" +[cov_off_b.matcher] +start_line=11 +start_col=3 +end_line=11 +end_col=20 +[[cov_off_b.annotations]] +purpose="xcov.cov.off" + +[cov_on_a] +file="pkg.h" +kind="absolute" +[cov_on_a.matcher] +start_line=7 +start_col=3 +end_line=7 +end_col=20 +[[cov_on_a.annotations]] +purpose="xcov.cov.on" + +[cov_on_b] +file="pkg.h" +kind="absolute" +[cov_on_b.matcher] +start_line=13 +start_col=3 +end_line=13 +end_col=20 +[[cov_on_b.annotations]] +purpose="xcov.cov.on" diff --git a/testsuite/tests/ext_annotations/selective_cov/C/src/cons_a_b.txt b/testsuite/tests/ext_annotations/selective_cov/C/src/cons_a_b.txt new file mode 100644 index 000000000..b78b04823 --- /dev/null +++ b/testsuite/tests/ext_annotations/selective_cov/C/src/cons_a_b.txt @@ -0,0 +1,12 @@ +drivers=. + +--# pkg.h +-- /cov-off-a/ lD ## dB +-- /cov-off-b/ lD ## dB +-- /cov-on/ l- ## s- +-- +--# test_a.c +-- /covered/ l+ ## 0 +-- +--# test_b.c +-- /covered/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/selective_cov/C/src/pkg.h b/testsuite/tests/ext_annotations/selective_cov/C/src/pkg.h new file mode 100644 index 000000000..5e766d801 --- /dev/null +++ b/testsuite/tests/ext_annotations/selective_cov/C/src/pkg.h @@ -0,0 +1,17 @@ +int +foo (int a, int b) +{ +#ifdef A + /* PLACEHOLDER */ // # cov-off-a + int c = a && b; // # cov-off-a + /* PLACEHOLDER */ // # cov-off-a +#endif + +#ifdef B + /* PLACEHOLDER */ // # cov-off-b + int d = a && b; // # cov-off-b + /* PLACEHOLDER */ // # cov-off-b +#endif + + return 0; // # cov-on +} diff --git a/testsuite/tests/ext_annotations/selective_cov/C/src/test_a.c b/testsuite/tests/ext_annotations/selective_cov/C/src/test_a.c new file mode 100644 index 000000000..4a5e24760 --- /dev/null +++ b/testsuite/tests/ext_annotations/selective_cov/C/src/test_a.c @@ -0,0 +1,19 @@ +#define A + +#include "pkg.h" + +int +main () +{ + return 0; // # covered +} + +//# pkg.h +// +// /cov-off-a/ lD ## dB +// /cov-off-b/ lD ## dB +// /cov-on/ l- ## s- +// +//# test_a.c +// +// /covered/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/selective_cov/C/src/test_b.c b/testsuite/tests/ext_annotations/selective_cov/C/src/test_b.c new file mode 100644 index 000000000..75d7e1f23 --- /dev/null +++ b/testsuite/tests/ext_annotations/selective_cov/C/src/test_b.c @@ -0,0 +1,19 @@ +#define B 1 + +#include "pkg.h" + +int +main () +{ + return 0; // # covered +} + +//# pkg.h +// +// /cov-off-a/ lD ## dB +// /cov-off-b/ lD ## dB +// /cov-on/ l- ## s- +// +//# test_b.c +// +// /covered/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/selective_cov/C/test.py b/testsuite/tests/ext_annotations/selective_cov/C/test.py new file mode 100644 index 000000000..4e4cf6024 --- /dev/null +++ b/testsuite/tests/ext_annotations/selective_cov/C/test.py @@ -0,0 +1,28 @@ +""" +Check gnatcov support for selective instrumentation for C when a file has +various preprocessing configuration resulting in varying preprocessed versions, +and the user has disabled coverage for every code region differing across +preprocessing invocations. + +Note that in this case, the user must use checkpoint consolidation, as there +can only exists one version of the SIDs at a time. + +This version of the test uses external annotations instead of comments, which +are always loaded irrespectively of preprocessing configuration, we thus have +more regions flagged as "disabled coverage" +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT, CovControl +from SCOV.tc import TestCase + +thistest.options.consolidate = "checkpoints" +TestCase( + category=CAT.mcdc, + tolerate_messages=( + r".* Missing or empty justification for external disabled coverage" + r' region annotation ".*"' + ), +).run(CovControl(instroptions="--external-annotations=../annotations.toml")) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/selective_cov/extra.opt b/testsuite/tests/ext_annotations/selective_cov/extra.opt new file mode 100644 index 000000000..ea8a3c8ac --- /dev/null +++ b/testsuite/tests/ext_annotations/selective_cov/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific feature diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 61b7da70f..b7c7465e7 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -111,13 +111,30 @@ package body Instrument.Ada_Unit is return Ada_Qualified_Name; -- Convert a Libadalang fully qualified name into our format - procedure Find_Ada_Units + function Find_Ada_Units (Instrumenter : in out Ada_Instrumenter_Type; - Filename : String; - Process_Unit : access procedure (Filename : String)); + Filename : String) return String_Vectors.Vector; -- Consider that Filename is a source file to instrument (i.e. a unit of - -- interest) and call Process_Unit for all compilation units that must be + -- interest) and return the list of all compilation units that must be -- instrumented with it (i.e. related subunits, if present). + -- + -- The result includes Filename in first position. + + procedure Insert_External_Annotations + (RH : in out Rewriting_Handle; + Unit : Analysis_Unit; + Annotations : Instr_Annotation_Map) + with Pre => RH /= No_Rewriting_Handle; + -- Insert the annotations in Annotations into Unit. + -- + -- For each annotation, the procedure searches the inner-most statement + -- list containing its corresponding source location, and inserts the + -- corresponding pragma right before the statement starting after the + -- designated source location. + -- + -- This expects an active rewriting context, but will apply the rewriting + -- in the LAL tree, so the rewriting session will need to be re-started + -- by the caller if needed. ----------------------- -- To_Qualified_Name -- @@ -3558,7 +3575,9 @@ package body Instrument.Ada_Unit is else Insertion_N); begin - if UIC.Disable_Coverage then + if UIC.Disable_Coverage + or else UIC.Is_Disabled_Region ((UIC.SFI, +From)) + then return; end if; case Kind (N) is @@ -4610,7 +4629,10 @@ package body Instrument.Ada_Unit is -- There is nothing else to do if we gave up instrumenting this -- subprogram. - if UIC.Disable_Instrumentation or else UIC.Disable_Coverage then + if UIC.Disable_Instrumentation + or else UIC.Disable_Coverage + or else UIC.Is_Disabled_Region ((UIC.SFI, +Sloc (N))) + then UIC.Disable_Instrumentation := Save_Disable_Instrumentation; return; end if; @@ -6977,7 +6999,10 @@ package body Instrument.Ada_Unit is -- Start of processing for Process_Decisions begin - if N.Is_Null or else UIC.Disable_Coverage then + if N.Is_Null + or else UIC.Disable_Coverage + or else UIC.Is_Disabled_Region ((UIC.SFI, +Sloc (N))) + then return; end if; Hash_Entries.Init; @@ -9263,8 +9288,8 @@ package body Instrument.Ada_Unit is else Source_Filename); Unit : constant Libadalang.Analysis.Analysis_Unit := Self.Context.Get_From_File (File_To_Search); - Rewriter : Ada_Source_Rewriter; + External_Annotations : Instr_Annotation_Map; Dummy_Ctx : constant Context_Handle := Create_Context ("Searching manual indications in " & Source_Filename); @@ -9407,6 +9432,19 @@ package body Instrument.Ada_Unit is Has_Reset_Indication := False; Rewriter.Handle := No_Rewriting_Handle; + -- Import external annotations if this file was not already processed by + -- the regular instrumentation process. + + if not Instrumented_Exists then + External_Annotations := + SS_Annotations.Get_Buffer_Annotations (Source_Filename); + if not External_Annotations.Is_Empty then + Start_Rewriting (Rewriter, Self, Prj, Unit); + Insert_External_Annotations + (Rewriter.Handle, Unit, External_Annotations); + end if; + end if; + Unit.Root.Traverse (Find_And_Replace_Pragma'Access); if Has_Dump_Indication or else Has_Reset_Indication then @@ -9415,6 +9453,149 @@ package body Instrument.Ada_Unit is end if; end Replace_Manual_Indications; + --------------------------------- + -- Insert_External_Annotations -- + --------------------------------- + + procedure Insert_External_Annotations + (RH : in out Rewriting_Handle; + Unit : Analysis_Unit; + Annotations : Instr_Annotation_Map) + is + procedure Insert_One (Cur : Instr_Annotation_Maps.Cursor); + -- Insert a single annotation into the rewritten unit. + + ---------------- + -- Insert_One -- + ---------------- + + procedure Insert_One (Cur : Instr_Annotation_Maps.Cursor) + is + Loc : constant Slocs.Local_Source_Location := + Instr_Annotation_Maps.Key (Cur); + LAL_Loc : constant Source_Location := + (Line => Langkit_Support.Slocs.Line_Number (Loc.Line), + Column => Langkit_Support.Slocs.Column_Number (Loc.Column)); + Annot : constant Instr_Annotation := + Instr_Annotation_Maps.Element (Cur); + Cur_Node : Ada_Node := Unit.Root.Lookup (LAL_Loc); + + Insert_Child : Node_Rewriting_Handle; + -- Handle of the node before/after which we will insert the pragma + + begin + -- Exit early if the annotation location does not lie within the AST + + if Cur_Node = No_Ada_Node then + Warning_Or_Error + ("Could not find node for source location " & Slocs.Image (Loc) + & " in file " & Unit.Get_Filename & ", external " + & Annot.Kind'Image & "annotation ignored."); + return; + end if; + while Cur_Node /= No_Ada_Node + and then Cur_Node.Kind not in Ada_Stmt_List | Ada_Decl_List + loop + Cur_Node := Cur_Node.Parent; + end loop; + + -- Warn if we haven't found a statement list in which to insert the + -- annotation. + + if Cur_Node = No_Ada_Node then + Warning_Or_Error + ("Could not find statement or declaration list enclosing " + & Slocs.Image (Loc) & " in file " & Unit.Get_Filename + & ", external " & Annot.Kind'Image & " annotation ignored."); + return; + end if; + + -- Find the Decl or statment index which closest matches the + -- annotation location. + + declare + Child : Ada_Node := Cur_Node.First_Child; + begin + while Child /= No_Ada_Node and then + Compare (Child, LAL_Loc) = After + loop + Child := Child.Next_Sibling; + end loop; + + -- We cannot have an empty list, otherwise there would be no + -- source location range associated to it. + + if Child = No_Ada_Node then + Insert_Child := Last_Child (Handle (Cur_Node)); + else + Insert_Child := Handle (Child); + end if; + end; + + declare + Prag_Stmt : Node_Rewriting_Handle; + begin + -- Create the proper pragma based on the annotation + + case Annot.Kind is + when Dump_Buffers => + Prag_Stmt := Create_From_Template + (RH, + "pragma Annotate (Xcov, Dump_Buffers" + & (if Length (Annot.Trace_Prefix) /= 0 + then To_Text (", " & (+Annot.Trace_Prefix)) + else "") & ");", + (1 .. 0 => No_Node_Rewriting_Handle), + Pragma_Rule); + + when Reset_Buffers => + Prag_Stmt := Create_From_Template + (RH, + "pragma Annotate (Xcov, Reset_Buffers);", + (1 .. 0 => No_Node_Rewriting_Handle), + Pragma_Rule); + + when Cov_Off | Cov_On => raise Program_Error with "Unreachable"; + end case; + -- Insert the proper annotation pragma in the statement list, in + -- the right location. + + if Annot.Insert_After then + Insert_After + (Insert_Child, + New_Sibling => Prag_Stmt); + else + Insert_Before + (Insert_Child, + New_Sibling => Prag_Stmt); + end if; + end; + end Insert_One; + + -- Start of processing for Insert_External_Annotations + + begin + Annotations.Iterate (Insert_One'Access); + + -- Apply the rewriting **in the LAL tree** to not mess with rewriting + -- indices in the instrumentation process, and to make the pragmas + -- visible in the analysis tree. + + declare + Apply_Res : constant Apply_Result := Libadalang.Rewriting.Apply (RH); + begin + if not Apply_Res.Success then + Warning_Or_Error + ("Failed to import external buffer annotations for " + & Unit.Get_Filename & ", they will be ignored."); + for D of Apply_Res.Diagnostics loop + Warning_Or_Error (Unit.Format_GNU_Diagnostic (D)); + end loop; + Abort_Rewriting (RH); + end if; + end; + end Insert_External_Annotations; + ------------------------------ -- Insert_With_Dump_Helper -- ------------------------------ @@ -9494,6 +9675,21 @@ package body Instrument.Ada_Unit is Root_Analysis_Unit := Rewriter.Rewritten_Unit; + -- Insert pragmas for the external annotations before doing anything. + -- This will close the rewriting session so we'll need to re start it + -- again if there were any annotations. + + declare + Buffer_Annots : constant Instr_Annotation_Map := + Get_Buffer_Annotations (Filename); + begin + if not Buffer_Annots.Is_Empty then + Insert_External_Annotations + (Rewriter.Handle, Root_Analysis_Unit, Buffer_Annots); + Rewriter.Handle := Start_Rewriting (Instrumenter.Context); + end if; + end; + UIC.Root_Unit := Root_Analysis_Unit.Root.As_Compilation_Unit; UIC.Current_Scope_Entity := UIC.Scope_Entities.Root; @@ -9611,6 +9807,13 @@ package body Instrument.Ada_Unit is Append_Unit (UIC.SFI); + declare + Annots : constant Instr_Annotation_Map := + Get_Disabled_Cov_Annotations (Filename); + begin + UIC.Populate_Ext_Disabled_Cov (Annots, UIC.SFI); + end; + Traverse_Declarations_Or_Statements (UIC => UIC, L => No_Ada_List, @@ -10908,11 +11111,14 @@ package body Instrument.Ada_Unit is for Part in Analysis_Unit_Kind loop if Self.Provider.Has_Unit (Unit_Name, +Part) then - Find_Ada_Units - (Self, - Self.Provider.Get_Unit_Filename - (Langkit_Support.Text.From_UTF8 (Unit_Name), Part), - Instrument_Source_File_Wrapper'Access); + for Filename of Find_Ada_Units + (Self, + Self.Provider.Get_Unit_Filename + (Langkit_Support.Text.From_UTF8 (Unit_Name), + Part)) + loop + Instrument_Source_File_Wrapper (+Filename); + end loop; end if; end loop; @@ -10938,14 +11144,15 @@ package body Instrument.Ada_Unit is -- Find_Ada_Units -- -------------------- - procedure Find_Ada_Units + function Find_Ada_Units (Instrumenter : in out Ada_Instrumenter_Type; - Filename : String; - Process_Unit : access procedure (Filename : String)) + Filename : String) return String_Vectors.Vector is function Process_Node (N : LAL.Ada_Node'Class) return Visit_Status; + Dependent_Comp_Units : String_Vectors.Vector; + ------------------ -- Process_Node -- ------------------ @@ -10962,11 +11169,11 @@ package body Instrument.Ada_Unit is if Subunit_FQN'Length = 0 then raise Property_Error; else - Find_Ada_Units - (Instrumenter, - Instrumenter.Context.Unit_Provider.Get - .Get_Unit_Filename (Subunit_FQN, LALCO.Unit_Body), - Process_Unit); + Dependent_Comp_Units.Append + (Find_Ada_Units + (Instrumenter, + Instrumenter.Context.Unit_Provider.Get + .Get_Unit_Filename (Subunit_FQN, LALCO.Unit_Body))); end if; end; exception @@ -11000,7 +11207,7 @@ package body Instrument.Ada_Unit is -- g-os_lib.adb), so just ignore them. if Unit.Root.Kind = Ada_Pragma_Node_List then - return; + return String_Vectors.Empty_Vector; -- Abort if a source file does not contain exactly one compilation -- unit. @@ -11016,8 +11223,10 @@ package body Instrument.Ada_Unit is declare CU : constant LAL.Compilation_Unit := Unit.Root.As_Compilation_Unit; begin - Process_Unit (Filename); + Dependent_Comp_Units := + String_Vectors.To_Vector (+Filename, Length => 1); CU.Traverse (Process_Node'Access); + return Dependent_Comp_Units; end; end Find_Ada_Units; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index a5d2a2468..4e5020902 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -30,6 +30,7 @@ with GNAT.OS_Lib; use GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; with GNATCOLL.Mmap; +with GNATCOLL.Utils; with Interfaces; use Interfaces; with Interfaces.C; use Interfaces.C; @@ -85,6 +86,40 @@ package body Instrument.C is Buffer_Dump_Prefix_Group : constant := 2; Buffer_Reset_Group : constant := 3; + package Sloc_To_Index_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Local_Source_Location, + Element_Type => Natural); + + procedure Remap_Locations + (Str : String; + Filename : String; + Slocs : in out Sloc_To_Index_Maps.Map); + -- Modify Slocs in place to update the mapped indices to reflect the + -- position of the corresponding key source location in Str. + -- + -- This procedure interprets GNU style line directives, making it usable on + -- a preprocessed file. + -- + -- This is mainly used at the moment to correctly insert buffer annotations + -- at the right position in a preprocessed file: + -- + -- Assuming we have an annotation to dump buffers at location LINE:COL. + -- + -- The Replace_Manual_Indication procedure only works on raw file indices, + -- it has no concept of lines or columns. We thus need to translate the + -- LINE:COL location to an actual character offset after the start of the + -- file. + -- + -- We cannot do this on the original file however, as the + -- Replace_Manual_Indication procedure rewrites a C file that has already + -- been preprocessed. + -- + -- We thus need this procedure to find the offset in Str (the preprocessed + -- file content) that corresponds to line LINE in Filename (the original + -- file) leveraging line directives to do so, then add the column of the + -- location to that offset to obtain the actual offset in Str + -- that corresponds to LINE:COL in Filename. + ------------------------------ -- Preprocessing utilities -- ------------------------------ @@ -111,6 +146,14 @@ package body Instrument.C is -- preprocess the file, assuming that it accepts the -E flag, to preprocess -- a file. + procedure Preprocess_And_Record_Include_Paths + (Source : GNATCOLL.Projects.File_Info; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : in out Prj_Desc; + PP_Filename : out Unbounded_String); + -- Same procedure as above, but automatically record the search paths + -- associated to Source in the project description. + function Common_Parse_TU_Args (Lang : Some_Language) return String_Vectors.Vector; -- Return the list of arguments that should always be passed to @@ -375,11 +418,6 @@ package body Instrument.C is -- fill UIC.Annotations (and also UIC.Disable_Cov_Regions for disabling -- coverage markers) accordingly. - function Is_Disabled_Region - (UIC : C_Unit_Inst_Context'Class; Sloc : Source_Location) return Boolean; - -- Whether coverage is disabled (by GNATCOV_COV_OFF/ON comment markers) - -- for the given Sloc. - ---------------------------- -- Source level rewriting -- ---------------------------- @@ -419,6 +457,12 @@ package body Instrument.C is Instrumenter : C_Family_Instrumenter_Type'Class); -- Check that a compiler driver exists for Instrumenter's language + function Check_Compiler_Driver + (Prj : Prj_Desc; + Instrumenter : C_Family_Instrumenter_Type'Class) return Boolean; + -- Same as above but in function form to allow calling in a declarative + -- region. Always returns False. + procedure Apply (Self : in out C_Source_Rewriter); -- Overwrite the file with the rewritter modifications @@ -2135,15 +2179,15 @@ package body Instrument.C is Append (Trailing_Braces, '}'); end if; + if Is_Null (N) or not Is_Source_Of_Interest (UIC, N) then + return; + end if; + UIC.Disable_Coverage := Is_Disabled_Region (UIC, Start_Sloc (N)); -- If this statement does not belong to a source of interest, skip -- it altogether. - if Is_Null (N) or not Is_Source_Of_Interest (UIC, N) then - return; - end if; - case Kind (N) is when Cursor_Compound_Stmt => @@ -2905,6 +2949,42 @@ package body Instrument.C is Ada.Directories.Delete_File (Preprocessed_Filename); end Preprocess_Source; + ----------------------------------------- + -- Preprocess_And_Record_Include_Paths -- + ----------------------------------------- + + procedure Preprocess_And_Record_Include_Paths + (Source : GNATCOLL.Projects.File_Info; + Instrumenter : C_Family_Instrumenter_Type'Class; + Prj : in out Prj_Desc; + PP_Filename : out Unbounded_String) + is + Options : Analysis_Options; + Filename : constant String := +Source.File.Full_Name; + begin + Preprocess_Source + (Filename, Instrumenter, Prj, PP_Filename, Options); + declare + use Files_Handling.File_To_String_Vectors_Maps; + Cur : Cursor; + Inserted : Boolean; + begin + -- Save the search paths that were used to preprocess the file, as + -- they must be passed on to clang parsing invocations (especially + -- when we are parsing the original file to record preprocessing + -- information). + + for Path of Options.PP_Search_Path loop + Prj.Compiler_Options_Unit.Insert + (Key => Source.File, + New_Item => String_Vectors.Empty_Vector, + Position => Cur, + Inserted => Inserted); + Prj.Compiler_Options_Unit.Reference (Cur).Append ("-I" & Path); + end loop; + end; + end Preprocess_And_Record_Include_Paths; + -------------------------- -- Common_Parse_TU_Args -- -------------------------- @@ -3215,22 +3295,6 @@ package body Instrument.C is Process => Process_Disable_Cov'Access); end Populate_Annotations; - ------------------------ - -- Is_Disabled_Region -- - ------------------------ - - function Is_Disabled_Region - (UIC : C_Unit_Inst_Context'Class; Sloc : Source_Location) return Boolean - is - begin - for Disabled_Region of UIC.Disable_Cov_Regions loop - if In_Range (Sloc, Disabled_Region) then - return True; - end if; - end loop; - return False; - end Is_Disabled_Region; - -------------------- -- Record_PP_Info -- -------------------- @@ -3300,6 +3364,13 @@ package body Instrument.C is UIC.LL_PP_Info_Map := UIC_Copy.LL_PP_Info_Map; + -- Also copy back the annotation map and disabled region vector as well + -- as the info on sources of interest, to avoid double processing. + + UIC.Annotations.Move (UIC_Copy.Annotations); + UIC.Disable_Cov_Regions.Move (UIC_Copy.Disable_Cov_Regions); + UIC.Sources_Of_Interest_Info.Move (UIC_Copy.Sources_Of_Interest_Info); + end Record_PP_Info; --------------------- @@ -3492,7 +3563,7 @@ package body Instrument.C is end; end loop; - -- Import Annots in our internal tables + -- Import annotations in our internal tables Filter_Annotations (UIC); UIC.Import_Annotations (UIC.CUs); @@ -4204,121 +4275,152 @@ package body Instrument.C is Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean) is - Orig_Filename : constant String := +Source.File.Full_Name; + Ignore_Check : constant Boolean := Check_Compiler_Driver (Prj, Self); + PP_Filename : Unbounded_String; + Dummy_Main : Compilation_Unit_Part; + Matches : Match_Array (0 .. 4); + Dump_Procedure : constant String := + Dump_Procedure_Symbol + (Main => Dummy_Main, Manual => True, Prj_Name => Prj.Prj_Name); + Reset_Procedure : constant String := + Reset_Procedure_Symbol (Prj.Prj_Name); + Extern_Prefix : constant String := + C_Family_Instrumenter_Type'Class (Self).Extern_Prefix; + + Annots : constant Instr_Annotation_Map := + Get_Buffer_Annotations (+Source.File.Full_Name); + + Annot_Mapping : Sloc_To_Index_Maps.Map; + -- Mapping from source locations of the annotations in the + -- non-preprocessed file to the index in the preprocessed file buffer. + begin - Check_Compiler_Driver (Prj, Self); + -- Preprocess the source, keeping the comment to look for the manual + -- dump indication later. - declare - Options : Analysis_Options; - PP_Filename : Unbounded_String; - Dummy_Main : Compilation_Unit_Part; - Matches : Match_Array (0 .. 4); - Dump_Procedure : constant String := - Dump_Procedure_Symbol - (Main => Dummy_Main, Manual => True, Prj_Name => Prj.Prj_Name); - Reset_Procedure : constant String := - Reset_Procedure_Symbol (Prj.Prj_Name); + Preprocess_And_Record_Include_Paths (Source, Self, Prj, PP_Filename); + + -- Look for the manual dump indication in the preprocessed file. Use + -- the GNATCOLL.Mmap API to map the file contents in memory, as we + -- may need to rewrite it to the source file, with the manual dump + -- indication replaced by an actual call to the dump buffers + -- function. - Extern_Prefix : constant String := - C_Family_Instrumenter_Type'Class (Self).Extern_Prefix; + declare + use Ada.Streams.Stream_IO; + use GNATCOLL.Mmap; + use Sloc_To_Index_Maps; + File : Mapped_File := Open_Read (To_String (PP_Filename)); + Region : Mapped_Region := Read (File); + Raw_Str : constant Str_Access := Data (Region); + Raw_Str_Last : constant Natural := Last (Region); + Str : String renames Raw_Str (1 .. Raw_Str_Last); + Tmp_Filename : constant String := +PP_Filename & ".tmp"; + + Output_File : Ada.Streams.Stream_IO.File_Type; + S : Ada.Streams.Stream_IO.Stream_Access; + -- Temporary file containing the new version of the original file, + -- with inserted calls to dump buffers. The original file is then + -- overwritten by this temporary file. This file is opened as a + -- binary file, as we are going to write contents retrieved + -- through mmap (thus binary Str) to it. + + Index : Positive := 1; + -- Starting index, or last index of the previous annotation in the + -- original file. + + Next_Ext_Annot : aliased Natural; + Next_Src_Annot : aliased Natural; + -- Next index for each of the annotations. Should be set to + -- Natural'Last if there are no more valid annotations. + + type Idx_Acc is access all Natural; + + Next_Annotation : Idx_Acc; + -- Pointer to the next annotation (in source or external) to be + -- processed. + + Ext_Annot_Cur : Cursor; begin - Preprocess_Source (Orig_Filename, Self, Prj, PP_Filename, Options); - declare - use Files_Handling.File_To_String_Vectors_Maps; - Cur : Cursor; - Inserted : Boolean; - begin - -- We need to save the search paths that were used to preprocess - -- the file, as they must be passed on to clang parsing - -- invocations (especially when we are parsing the original file - -- to record preprocessing information). - - for Path of Options.PP_Search_Path loop - Prj.Compiler_Options_Unit.Insert - (Key => Source.File, - New_Item => String_Vectors.Empty_Vector, - Position => Cur, - Inserted => Inserted); - Prj.Compiler_Options_Unit.Reference (Cur).Append ("-I" & Path); - end loop; - end; + -- Create the sloc to index mapping for external annotations + + for Annot_Cur in Annots.Iterate loop + Annot_Mapping.Insert (Instr_Annotation_Maps.Key (Annot_Cur), 0); + end loop; + Remap_Locations (Str, +Source.File.Full_Name, Annot_Mapping); + Ext_Annot_Cur := Annot_Mapping.First; - -- Look for the manual dump indication in the preprocessed file. Use - -- the GNATCOLL.Mmap API to map the file contents in memory, as we - -- may need to rewrite it to the source file, with the manual dump - -- indication replaced by an actual call to the dump buffers - -- function. + Has_Dump_Indication := False; + Has_Reset_Indication := False; - declare - use Ada.Streams.Stream_IO; - use GNATCOLL.Mmap; - File : Mapped_File := Open_Read (To_String (PP_Filename)); - Region : Mapped_Region := Read (File); - Raw_Str : constant Str_Access := Data (Region); - Raw_Str_Last : constant Natural := Last (Region); - Str : String renames Raw_Str (1 .. Raw_Str_Last); - - Tmp_Filename : constant String := +PP_Filename & ".tmp"; - - Output_File : Ada.Streams.Stream_IO.File_Type; - S : Ada.Streams.Stream_IO.Stream_Access; - -- Temporary file containing the new version of the original file, - -- with inserted calls to dump buffers. The original file is then - -- overwritten by this temporary file. This file is opened as a - -- binary file, as we are going to write contents retrieved - -- through mmap (thus binary content) to it. - - Index : Positive := 1; - -- Starting index, or last index of the previous match in the - -- original file. + Match (Buffer_Command_Pattern, Str (Index .. Str'Last), Matches); - begin - Has_Dump_Indication := False; - Has_Reset_Indication := False; + -- Initialize the indices - -- Iterate on all matches for the command pattern found in Str + Next_Ext_Annot := + (if not Has_Element (Ext_Annot_Cur) + or else Element (Ext_Annot_Cur) = 0 + then Natural'Last + else Element (Ext_Annot_Cur)); + Next_Src_Annot := + (if Matches (0) = No_Match + then Natural'Last + else Matches (0).First); - Match (Buffer_Command_Pattern, Str (Index .. Str'Last), Matches); - while Index in Str'Range and then Matches (0) /= No_Match loop + -- Iterate over all the annotations, forwarding the original text in + -- between. - -- Open the output file if this is the first match we find, - -- then forward the source code that appear before the match - -- unchanged. + while Index in Str'Range loop - if not (Has_Dump_Indication or else Has_Reset_Indication) then - Create (Output_File, Out_File, Tmp_Filename); - S := Stream (Output_File); + -- Find the index of the next annotation to be processed - -- Put an external decl for the buffers dump and reset - -- functions. - -- - -- The external decl for the dump procedure takes a const - -- char * to avoid any warnings when using a string literal - -- as the trace prefix. - - String'Write - (S, - Extern_Prefix & "void " & Dump_Procedure - & "(const char *prefix);"); - String'Write - (S, Extern_Prefix & "void " & Reset_Procedure & "(void);"); - end if; + Next_Annotation := + (if Next_Src_Annot <= Next_Ext_Annot + then Next_Src_Annot'Access + else Next_Ext_Annot'Access); + + -- No matches, and no more or invalid ext annotations, + -- nothing left to do. - -- Forward whatever comes between the last match (or the - -- beginning of the file, if this is the first match) and this - -- match. + exit when Next_Annotation.all = Natural'Last; + + -- Open the output file if this is the first match we find, + -- then forward the source code that appear before the match + -- unchanged. + + if not (Has_Dump_Indication or else Has_Reset_Indication) then + Create (Output_File, Out_File, Tmp_Filename); + S := Stream (Output_File); + + -- Put an external decl for the buffers dump and reset + -- functions. + -- + -- The external decl for the dump procedure takes a const + -- char * to avoid any warnings when using a string literal + -- as the trace prefix. + + String'Write + (S, + Extern_Prefix & "void " & Dump_Procedure + & "(const char *prefix);"); + String'Write + (S, Extern_Prefix & "void " & Reset_Procedure & "(void);"); + end if; - String'Write (S, Str (Index .. Matches (0).First - 1)); + -- Forward the content between the previous annotation and the + -- next one - -- Now insert the substitution for the command we found + String'Write (S, Str (Index .. Next_Annotation.all - 1)); + + -- Process whatever annotation source comes first + + if Next_Annotation = Next_Src_Annot'Access then if Matches (Buffer_Dump_Group) /= No_Match then - if Switches.Misc_Trace.Is_Active then - Switches.Misc_Trace.Trace - ("Found buffer dump indication in file " - & (+Source.File.Base_Name)); - end if; + Switches.Misc_Trace.Trace + ("Found buffer dump indication in file " + & (+Source.File.Base_Name)); -- If we had a prefix specified in the comment, include it -- in the dump procedure call. Use the project name as the @@ -4337,60 +4439,285 @@ package body Instrument.C is else pragma Assert (Matches (Buffer_Reset_Group) /= No_Match); - if Switches.Misc_Trace.Is_Active then - Switches.Misc_Trace.Trace - ("Found buffer reset indication in file " - & (+Source.File.Base_Name)); - end if; + Switches.Misc_Trace.Trace + ("Found buffer reset indication in file " + & (+Source.File.Base_Name)); String'Write (S, Reset_Procedure & "();"); Has_Reset_Indication := True; end if; - -- Search for the next dump indication + -- Move the index forward, and search for the next match Index := Matches (0).Last + 1; Match (Buffer_Command_Pattern, Str (Index .. Str'Last), Matches); - end loop; + Next_Src_Annot := + (if Matches (0) /= No_Match + then Matches (0).First + else Natural'Last); - -- If we had a manual indication, and thus wrote a modified source - -- file, overwrite the original source file with it. + else + declare + Annot : constant Instr_Annotation_Maps + .Constant_Reference_Type := + Annots.Constant_Reference (Key (Ext_Annot_Cur)); + begin + case Annot.Kind is + when Dump_Buffers => + Has_Dump_Indication := True; + String'Write + (S, + Dump_Procedure & "(" + & (if Length (Annot.Trace_Prefix) /= 0 + then +Annot.Trace_Prefix + else """" & To_Ada (Prj.Prj_Name) & """") + & ");"); + when Reset_Buffers => + Has_Reset_Indication := True; + String'Write (S, Reset_Procedure & "();"); + + when Cov_On | Cov_Off => + raise Program_Error with "Not reachable"; + end case; + Next (Ext_Annot_Cur); + Index := Next_Annotation.all; + Next_Ext_Annot := + (if Has_Element (Ext_Annot_Cur) + and then Element (Ext_Annot_Cur) /= 0 + then Element (Ext_Annot_Cur) + else Natural'Last); + end; + end if; + end loop; + + -- If we have some external annotations we were not able to re-locate + -- in the preprocessed file, warn about it. - if Has_Dump_Indication or else Has_Reset_Indication then + if Has_Element (Ext_Annot_Cur) then + Warning_Or_Error + ("Some external annotations could not be re-mapped in the" + & " preprocessed version of " & Source.File.Display_Full_Name + & ", They have been ignored. Use -v for more details."); + while Has_Element (Ext_Annot_Cur) loop declare - PP_File : constant Virtual_File := Create (+(+PP_Filename)); - Tmp_File : constant Virtual_File := Create (+Tmp_Filename); - Success : Boolean; + Annot : constant Instr_Annotation := + Annots.Element (Key (Ext_Annot_Cur)); begin - -- Flush the rest of the file contents + Switches.Misc_Trace.Trace + ("Could not remap " & Annot.Kind'Image & " at " + & Slocs.Image (Key (Ext_Annot_Cur))); + end; + end loop; + end if; - String'Write (S, Str (Index .. Str'Last)); - Close (Output_File); + -- If we had a manual indication, and thus wrote a modified source + -- file, overwrite the original source file with it. - Free (Region); - Close (File); + if Has_Dump_Indication or else Has_Reset_Indication then + declare + PP_File : constant Virtual_File := Create (+(+PP_Filename)); + Tmp_File : constant Virtual_File := Create (+Tmp_Filename); + Success : Boolean; + begin + -- Flush the rest of the file contents - -- Overwrite the original file with its newer version + String'Write (S, Str (Index .. Str'Last)); + Close (Output_File); - PP_File.Delete (Success); - Tmp_File.Rename - (Full_Name => PP_File, - Success => Success); - if not Success then - Outputs.Fatal_Error - ("Failed to replace manual dump indication for Source " - & (+Source.File.Full_Name)); - end if; - end; - else Free (Region); Close (File); - end if; - end; + + -- Overwrite the original file with its newer version + + PP_File.Delete (Success); + Tmp_File.Rename + (Full_Name => PP_File, + Success => Success); + if not Success then + Outputs.Fatal_Error + ("Failed to replace manual dump indication for Source " + & (+Source.File.Full_Name)); + end if; + end; + else + Free (Region); + Close (File); + end if; end; end Replace_Manual_Indications; + Line_Directive_Regexp : constant Pattern_Matcher := + Compile ("# (\d+) ""(\S+)""(?: \d)?"); + -- Pattern matching GNU style line directives, used in Remap_Locations. + + --------------------- + -- Remap_Locations -- + --------------------- + + procedure Remap_Locations + (Str : String; + Filename : String; + Slocs : in out Sloc_To_Index_Maps.Map) + is + use GNATCOLL.Utils; + use Sloc_To_Index_Maps; + Current_Line : Natural := 1; + -- Current line in the file + + Current_Line_Index : Positive := Str'First; + -- Corresponding index of the first character of the line Current_Line + + Next_Line : Natural := 1; + -- Next line in the file. Not all lines from the non-preprocessed file + -- may be present, as the preprocessor may remove empty lines. + + Next_Line_Index : Positive := Str'First; + -- Index of the first character of the line Next_Line. + + Col_Var : Natural; + -- Variable used to get the proper column from the line start index. + + Next_Sloc : Cursor := Slocs.First; + + procedure Get_Next_Line; + -- Update Next_Line and Next_Line index to point to the next line of + -- Filename in Str, based on the current position in Current_Line + -- and Current_Line_Index. + + ------------------- + -- Get_Next_Line -- + ------------------- + + procedure Get_Next_Line is + In_File : Boolean := True; + -- Whether the current line belongs to Filename. Assume this is True + -- when entering this procedure. + + In_Directive : Boolean := False; + -- Whether the current line is a line directive. If so, we need to + -- check the next line. + + Line_Matches : Match_Array (0 .. 2); + begin + Next_Line_Index := Current_Line_Index; + Next_Line := Current_Line; + loop + Next_Line_Index := + GNATCOLL.Utils.Next_Line (Str, Next_Line_Index); + + -- Check if we are on a line directive. If so, parse it. + + if Str (Next_Line_Index) = '#' + and then Next_Line_Index < Str'Last + and then Str (Next_Line_Index + 1) = ' ' + then + Match + (Self => Line_Directive_Regexp, + Data => Str, + Matches => Line_Matches, + Data_First => Next_Line_Index, + Data_Last => Line_End (Str, Next_Line_Index)); + else + Line_Matches := (others => No_Match); + end if; + + if Line_Matches (0) /= No_Match then + In_Directive := True; + + declare + Directive_Filename : String renames + Str (Line_Matches (2).First .. Line_Matches (2).Last); + Directive_Line : constant Natural := + Natural'Value + (Str (Line_Matches (1).First .. Line_Matches (1).Last)); + begin + -- Ignore line directives which state a '0' line, as they + -- don't provide any meaningful insight. + + if Directive_Filename = Filename + and then Directive_Line /= 0 + then + Next_Line := Directive_Line; + In_File := True; + else + In_File := False; + end if; + end; + + -- Otherwise, we only need to bump the line number if in the right + -- file and if the previous line was not a directive. + + else + if In_File and then not In_Directive then + Next_Line := Next_Line + 1; + end if; + In_Directive := False; + end if; + + -- Exit when we found the first line that is not a line + -- directive and that belongs to Filename, or we've reach the end + -- of the file. + + exit when (not In_Directive and then In_File) + or else Next_Line_Index = Str'Last; + end loop; + -- If the line index is Str'Last and Next_Line hasn't been modified, + -- this means there are no more lines. Signal this by setting + -- Next_Line to 0. + + if Next_Line_Index = Str'Last and then Next_Line = Current_Line then + Next_Line := 0; + end if; + end Get_Next_Line; + + begin + if not Has_Element (Next_Sloc) then + return; + end if; + + loop + -- If the next line in the file is the same as the one of Next_Sloc, + -- Compute the index of the corresponding column. + + if Key (Next_Sloc).Line = Next_Line then + Col_Var := Next_Line_Index; + Skip_To_Column (Str, Key (Next_Sloc).Column, Col_Var); + Slocs.Replace_Element (Next_Sloc, Col_Var); + Next (Next_Sloc); + + -- If the next line in the file is past the next source location + -- (e.g. the source location designates a whitespace-only line that + -- got removed by the preprocessor), associate the sloc to the end of + -- the last line we have for this file. + -- + -- This could result in annotations being tied to an earlier location + -- than actually specified, but with no differences in the + -- obligations included in the range. + -- + -- This has not yet been seen in practice. + + elsif Next_Line > Key (Next_Sloc).Line then + Col_Var := Current_Line_Index; + Slocs.Replace_Element (Next_Sloc, Line_End (Str, Col_Var)); + Next (Next_Sloc); + + else + -- Otherwise just move to the next line + Current_Line := Next_Line; + Current_Line_Index := Next_Line_Index; + Get_Next_Line; + end if; + exit when not Has_Element (Next_Sloc) or else Next_Line = 0; + end loop; + -- If there still are Slocs we have not remapped when reaching the end + -- of the file, associate them with index 0. + + while Has_Element (Next_Sloc) loop + Slocs.Replace_Element (Next_Sloc, 0); + end loop; + end Remap_Locations; + ------------------------------- -- Auto_Dump_Buffers_In_Main -- ------------------------------- @@ -4677,9 +5004,9 @@ package body Instrument.C is -- Check_Compiler_Driver -- --------------------------- - procedure Check_Compiler_Driver + function Check_Compiler_Driver (Prj : Prj_Desc; - Instrumenter : C_Family_Instrumenter_Type'Class) + Instrumenter : C_Family_Instrumenter_Type'Class) return Boolean is Compiler_Driver : constant Unbounded_String := Prj.Compiler_Driver (Instrumenter.Language); @@ -4688,6 +5015,21 @@ package body Instrument.C is Outputs.Fatal_Error ("could not find a compiler for " & Image (Instrumenter.Language)); end if; + return True; + end Check_Compiler_Driver; + + --------------------------- + -- Check_Compiler_Driver -- + --------------------------- + + procedure Check_Compiler_Driver + (Prj : Prj_Desc; + Instrumenter : C_Family_Instrumenter_Type'Class) + is + Ignore_Bool_Res : constant Boolean := + Check_Compiler_Driver (Prj, Instrumenter); + begin + null; end Check_Compiler_Driver; ---------------- @@ -5062,6 +5404,16 @@ package body Instrument.C is SFI => SFI, CU_Name => CU_Name_For_File (Full_Name (File))); end; + + -- Import the external disabled regions for this source + + declare + Annots : constant Instr_Annotation_Map := + Get_Disabled_Cov_Annotations (+File.Full_Name); + begin + UIC.Populate_Ext_Disabled_Cov (Annots, SOI.SFI); + end; + else SOI := (Of_Interest => False); end if; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 7938b5dd4..1fc33729c 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -347,9 +347,6 @@ package Instrument.C is -- root of each tree is the scope corresponding to the file itself in which -- all its scopes are stored. - package Sloc_Range_Vectors is new Ada.Containers.Vectors - (Index_Type => Positive, Element_Type => Source_Location_Range); - type C_Unit_Inst_Context is new Instrument.Common.Unit_Inst_Context with record TU : Translation_Unit_T; @@ -408,10 +405,6 @@ package Instrument.C is -- Currently processed blocks (blocks can nest in the source, -- when e.g. we have a lambda expression). - Disable_Cov_Regions : Sloc_Range_Vectors.Vector; - -- List of regions where coverage is disabled, as delimited - -- by GNATCOV_COV_OFF/ON markers. - end record; type C_Source_Rewriter is tagged limited private; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 2c4e6083d..c74578eff 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -704,6 +704,80 @@ package body Instrument.Common is end loop; end Import_From_Args; + ------------------------ + -- Is_Disabled_Region -- + ------------------------ + + function Is_Disabled_Region + (UIC : Unit_Inst_Context; Sloc : Source_Location) return Boolean + is + begin + for Disabled_Region of UIC.Disable_Cov_Regions loop + if In_Range (Sloc, Disabled_Region) then + return True; + end if; + end loop; + return False; + end Is_Disabled_Region; + + ------------------------------- + -- Populate_Ext_Disabled_Cov -- + ------------------------------- + + procedure Populate_Ext_Disabled_Cov + (UIC : in out Unit_Inst_Context; + Annots : Instr_Annotation_Map; + SFI : Source_File_Index) + is + use Instr_Annotation_Maps; + Cur : Instr_Annotation_Maps.Cursor := Annots.First; + begin + while Has_Element (Cur) loop + + declare + Off_Annot : constant Instr_Annotation := Element (Cur); + Off_Sloc : constant Local_Source_Location := Key (Cur); + On_Annot : Instr_Annotation; + begin + + -- First comes the Cov_Off annotation + + pragma Assert (Off_Annot.Kind = Cov_Off); + + UIC.Annotations.Append + (Annotation_Couple' + ((Source_File => SFI, L => Off_Sloc), + (Kind => Cov_Off, + Message => + (if Length (Off_Annot.Justification) /= 0 + then new String'(+Off_Annot.Justification) + else null), + others => <>))); + + -- Then the Cov_On annotation + + Next (Cur); + pragma Assert (Has_Element (Cur)); + On_Annot := Element (Cur); + pragma Assert (On_Annot.Kind = Cov_On); + + UIC.Annotations.Append + (Annotation_Couple' + ((Source_File => SFI, L => Key (Cur)), + (Kind => Cov_On, others => <>))); + + -- And the region annotation + + UIC.Disable_Cov_Regions.Append + (Source_Location_Range' + (SFI, + (First_Sloc => Off_Sloc, + Last_Sloc => Key (Cur)))); + end; + Next (Cur); + end loop; + end Populate_Ext_Disabled_Cov; + begin Sys_Prefix.Append (To_Unbounded_String ("GCVRT")); diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 62b8a6294..f5d13b4c1 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -325,6 +325,9 @@ package Instrument.Common is package Annotation_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Annotation_Couple); + package Sloc_Range_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, Element_Type => Source_Location_Range); + package Nat_Vectors is new Ada.Containers.Vectors (Index_Type => Positive, Element_Type => Nat); @@ -351,7 +354,8 @@ package Instrument.Common is -- rewriting. Disable_Coverage : Boolean := False; - -- Set to True to deactivate instrumentation and SCO emissions + -- Set to True to deactivate instrumentation and SCO emissions, + -- regardless of the contents of Disable_Cov_Region. Non_Instr_LL_SCOs : SCO_Sets.Set; -- Set of low level SCO ids that were not instrumented @@ -359,6 +363,10 @@ package Instrument.Common is Blocks : SCO_Id_Vector_Vector; -- This is used when the block coverage level is enabled: list of blocks + Disable_Cov_Regions : Sloc_Range_Vectors.Vector; + -- List of regions where coverage is disabled, as delimited by + -- GNATCOV_COV_OFF/ON markers or external annotations. + end record; procedure Import_Annotations @@ -372,6 +380,11 @@ package Instrument.Common is -- Import the low level SCO in UIC marked as non-instrumented in the high -- level non-instrumented SCO_Id sets. + function Is_Disabled_Region + (UIC : Unit_Inst_Context; Sloc : Source_Location) return Boolean; + -- Return True if Sloc lies within one of the disabled regions in + -- UIC.Disable_Cov_Region. + function Img (Bit : Any_Bit_Id) return String is (Strings.Img (Integer (Bit))); @@ -700,4 +713,11 @@ package Instrument.Common is Element_Type => Instr_Annotation); subtype Instr_Annotation_Map is Instr_Annotation_Maps.Map; + procedure Populate_Ext_Disabled_Cov + (UIC : in out Unit_Inst_Context; + Annots : Instr_Annotation_Map; + SFI : Source_File_Index); + -- Populate the Annotations and Disabled_Cov_Regions of UIC with the + -- annotations in Annots. The resulting annotations are tied to SFI. + end Instrument.Common; diff --git a/tools/gnatcov/ss_annotations.adb b/tools/gnatcov/ss_annotations.adb index 80278855f..ea017e49a 100644 --- a/tools/gnatcov/ss_annotations.adb +++ b/tools/gnatcov/ss_annotations.adb @@ -25,9 +25,10 @@ with TOML; with Stable_Sloc; use Stable_Sloc; with Stable_Sloc.TOML_Utils; use Stable_Sloc.TOML_Utils; -with Files_Table; use Files_Table; -with Instrument; use Instrument; -with Outputs; use Outputs; +with Files_Table; use Files_Table; +with Instrument; use Instrument; +with Instrument.Common; use Instrument.Common; +with Outputs; use Outputs; package body SS_Annotations is use type Unbounded_String; @@ -81,6 +82,39 @@ package body SS_Annotations is (Sloc : TOML.Source_Location) return Slocs.Local_Source_Location is (Line => Sloc.Line, Column => Sloc.Column) with Unreferenced; + generic + type Expected_Annot_Kind is (<>); + with function Kind + (Match_Res : Match_Result) return Expected_Annot_Kind'Base; + with function Convert + (Kind : Expected_Annot_Kind; + Match_Res : Match_Result; + Success : out Boolean) + return Instrument.Common.Instr_Annotation; + Purpose_Prefix : String; + function Generic_Get_Annotations + (Filename : String) return Instrument.Common.Instr_Annotation_Map; + -- Match the annotations on File for the entries for which the purpose + -- starts with Purpose_Prefix. Warn and discard the match results that + -- either failed, or for which the purpose does not lie in + -- Expected_Annot_Kind after conversion through Kind. + -- Otherwise, each valid annotation is converted and associated to its + -- starting location in the returned map. + + subtype Buffer_Annotation_Kind is + Src_Annotation_Kind range Dump_Buffers .. Reset_Buffers; + + function Convert_Buffer_Annotation + (Kind : Buffer_Annotation_Kind; + Match_Res : Match_Result; + Success : out Boolean) + return Instrument.Common.Instr_Annotation; + -- Convert Match_Res to a buffer annotation, assuming the annotation in + -- Match Res is of kind Kind. + -- + -- Print a warning and set Success to False if there are errors + -- interpreting the TOML annotation. + --------------------- -- Annotation_Kind -- --------------------- @@ -307,18 +341,17 @@ package body SS_Annotations is Set_Annotations (New_Annotations); end Import_External_Exemptions; - ---------------------------- - -- Get_Buffer_Annotations -- - ---------------------------- + ----------------------------- + -- Generic_Get_Annotations -- + ----------------------------- - function Get_Buffer_Annotations + function Generic_Get_Annotations (Filename : String) return Instrument.Common.Instr_Annotation_Map is - use Instrument.Common; - VF : constant Virtual_File := Create (+Filename); - Matches : Match_Result_Vec; - Kind : Any_Annotation_Kind; - Result : Instr_Annotation_Map; + VF : constant Virtual_File := Create (+Filename); + Matches : Match_Result_Vec; + Annot_Kind : Expected_Annot_Kind'Base; + Result : Instr_Annotation_Map; begin -- Exit early if there are no external annotations @@ -329,7 +362,7 @@ package body SS_Annotations is Matches := Match_Entries ((1 => VF), Ext_Annotation_DB, - Purpose_Prefix => To_Ada (Buffers_Namespace)); + Purpose_Prefix); -- Process each annotation result @@ -339,8 +372,8 @@ package body SS_Annotations is goto Continue; end if; - Kind := Annotation_Kind (Match); - if Kind not in Dump_Buffers | Reset_Buffers then + Annot_Kind := Kind (Match); + if Annot_Kind not in Expected_Annot_Kind then Warn ("Unexpected or unknown annotation kind for annotation """ & (+Match.Identifier) & """: " @@ -348,63 +381,247 @@ package body SS_Annotations is goto Continue; end if; declare - Start_Loc : constant Slocs.Local_Source_Location := + use TOML; + Sloc : constant Slocs.Local_Source_Location := +Match.Location.Start_Sloc; - -- We only use the start location to represent buffer dump / reset - -- annotations, as a range is ill-defined for those. - - New_Annotation : Instr_Annotation (Kind); - Cur : Instr_Annotation_Maps.Cursor; - Inserted : Boolean; + Success : Boolean; + Cur : Instr_Annotation_Maps.Cursor; + Annot : Instr_Annotation := + Convert (Annot_Kind, Match, Success); begin - -- Explicitly inspect each annotation kind to get a warning if a - -- new annotation kind is added in Instrument.Common but not here. - - case New_Annotation.Kind is - when Dump_Buffers => - New_Annotation.Trace_Prefix := - Get_Or_Null (Match.Annotation, "trace_prefix"); - - when Reset_Buffers => - null; + if not Success then + goto Continue; + end if; - when Cov_On | Cov_Off => - raise Program_Error with "unreachable"; - end case; - New_Annotation.Insert_After := False; - declare - use TOML; - begin - if Match.Annotation.Has ("insert_after") then - if Match.Annotation.Get ("insert_after").Kind /= TOML_Boolean - then - Warn - ("Invalid type for ""insert_after"" field in annotation" - & """" & (+Match.Identifier) & """, should be" - & " TOML_BOOLEAN."); - else - New_Annotation.Insert_After := - Match.Annotation.Get ("insert_after").As_Boolean; - end if; + Annot.Insert_After := False; + if Match.Annotation.Has ("insert_after") then + if Match.Annotation.Get ("insert_after").Kind /= TOML_Boolean + then + Warn + ("Invalid type for ""insert_after"" field in annotation" + & """" & (+Match.Identifier) & """, should be" + & " TOML_BOOLEAN."); + Success := False; + else + Annot.Insert_After := + Match.Annotation.Get ("insert_after").As_Boolean; end if; - end; - Result.Insert (Start_Loc, New_Annotation, Cur, Inserted); + end if; + + Result.Insert (Sloc, Annot, Cur, Success); -- Tolerate duplicate annotations if they are the same - if not Inserted and then Result.Reference (Cur) /= New_Annotation + if not Success and then Result.Reference (Cur) /= Annot then Warn (Ada.Directories.Simple_Name (Filename) & ":" - & Slocs.Image (Start_Loc) + & Slocs.Image (Sloc) & ": Conflicting annotations for this line, ignoring the" & " external annotation """ & (+Match.Identifier) & """"); end if; + + Ext_Annotation_Trace.Trace + ("Found instrumentation annotation for " + & Slocs.Image (Sloc) & ": " & Annot.Kind'Image); + end; <> end loop; - return Result; - end Get_Buffer_Annotations; + end Generic_Get_Annotations; + + ------------------------------- + -- Convert_Buffer_Annotation -- + ------------------------------- + + function Convert_Buffer_Annotation + (Kind : Buffer_Annotation_Kind; + Match_Res : Match_Result; + Success : out Boolean) + return Instrument.Common.Instr_Annotation + is + use TOML; + New_Annotation : Instr_Annotation (Kind); + begin + Success := True; + case New_Annotation.Kind is + when Dump_Buffers => + New_Annotation.Trace_Prefix := + Get_Or_Null (Match_Res.Annotation, "trace_prefix"); + + when Reset_Buffers => + null; + + when others => + raise Program_Error with "Unreachable"; + end case; + + return New_Annotation; + end Convert_Buffer_Annotation; + + ---------------------------- + -- Get_Buffer_Annotations -- + ---------------------------- + + function Get_Buffer_Annotations_Internal is new Generic_Get_Annotations + (Expected_Annot_Kind => Buffer_Annotation_Kind, + Kind => Annotation_Kind, + Convert => Convert_Buffer_Annotation, + Purpose_Prefix => To_Ada (Buffers_Namespace)); + + function Get_Buffer_Annotations + (Filename : String) return Instr_Annotation_Map is + (Get_Buffer_Annotations_Internal (Filename)); + + ---------------------------------- + -- Get_Disabled_Cov_Annotations -- + ---------------------------------- + + function Get_Disabled_Cov_Annotations + (Filename : String) return Instr_Annotation_Map + is + use Instr_Annotation_Maps; + SFI : constant Source_File_Index := + Get_Index_From_Full_Name (Filename, Source_File); + + subtype Cov_Annotation_Kind is + Src_Annotation_Kind range Cov_On .. Cov_Off; + + function Convert_Cov_Annotation + (Kind : Cov_Annotation_Kind; + Match_Res : Match_Result; + Success : out Boolean) + return Instrument.Common.Instr_Annotation; + -- Convert Match_Res to a Cov_On/Cov_Off annotation, assuming the + -- annotation in Match Res is of kind Kind. + -- + -- Print a warning and set Success to False if there are errors + -- interpreting the TOML annotation. + + function Get_Disabled_Cov_Intl is new Generic_Get_Annotations + (Expected_Annot_Kind => Cov_Annotation_Kind, + Kind => Annotation_Kind, + Convert => Convert_Cov_Annotation, + Purpose_Prefix => To_Ada (Coverage_Namespace)); + + ---------------------------- + -- Convert_Cov_Annotation -- + ---------------------------- + + function Convert_Cov_Annotation + (Kind : Cov_Annotation_Kind; + Match_Res : Match_Result; + Success : out Boolean) + return Instrument.Common.Instr_Annotation + is + use TOML; + New_Annotation : Instr_Annotation (Kind); + begin + Success := True; + case New_Annotation.Kind is + when Cov_Off => + New_Annotation.Justification := + Get_Or_Null (Match_Res.Annotation, "justification"); + if New_Annotation.Justification = Null_Unbounded_String then + Warn + (Slocs.Image (To_Sloc (Match_Res.Location.Start_Sloc, SFI)) + & ": Missing or empty justification for external" + & " disabled coverage region annotation """ + & (+Match_Res.Identifier) & """"); + end if; + + when Cov_On => null; + + when others => + raise Program_Error with "Unreachable"; + + end case; + + -- Filter the annotation if it conflicts with a pre-existing one + -- which is not identical. + + if Success then + declare + use ALI_Annotation_Maps; + Cur : constant ALI_Annotation_Maps.Cursor := Get_Annotation + ((Source_File => SFI, L => +Match_Res.Location.Start_Sloc)); + begin + if Has_Element (Cur) then + if Element (Cur).Kind /= Kind then + Success := False; + elsif Kind = Cov_Off then + Success := + (if Element (Cur).Message in null + then US.Length (New_Annotation.Justification) = 0 + else Element (Cur).Message.all + = (+New_Annotation.Justification)); + end if; + + if not Success then + Warn + (Ada.Directories.Simple_Name (Filename) & ":" + & Image (Match_Res.Location.Start_Sloc) + & ": Conflicting annotations for this line, ignoring" + & " the external annotation """ + & (+Match_Res.Identifier) & """"); + end if; + + end if; + end; + end if; + + return New_Annotation; + end Convert_Cov_Annotation; + + Res : Instr_Annotation_Map := Get_Disabled_Cov_Intl (Filename); + Cur : Instr_Annotation_Maps.Cursor := Res.First; + Aux : Instr_Annotation_Maps.Cursor; + + Expected_Kind, Next_Expected_Kind, Tmp : Src_Annotation_Kind; + + -- Start of processing for Get_Disabled_Cov_Annotations + + begin + -- Filter out any annotations that do not come in pairs, and ensure + -- the map starts with an Cov_Off annotation. + + if Has_Element (Cur) and then Element (Cur).Kind = Cov_On then + Warn + (Ada.Directories.Simple_Name (Filename) & ": " + & Slocs.Image (Key (Cur)) + & ": external Cov_On annotation with no previous Cov_Off" + & " annotation, ignoring it."); + Aux := Cur; + Next (Cur); + Res.Delete (Aux); + end if; + + Expected_Kind := Cov_Off; + Next_Expected_Kind := Cov_On; + + while Has_Element (Cur) loop + pragma Assert (Element (Cur).Kind = Expected_Kind); + Aux := Next (Cur); + if (if Has_Element (Aux) + then Element (Aux).Kind /= Next_Expected_Kind + else Element (Cur).Kind = Cov_Off) + then + Warn + (Ada.Directories.Simple_Name (Filename) & ": " + & Slocs.Image (Key (Cur)) & ": external " + & Expected_Kind'Image & " annotation with no subsequent " + & Next_Expected_Kind'Image & " annotation, ignoring it."); + Res.Delete (Cur); + else + Tmp := Expected_Kind; + Expected_Kind := Next_Expected_Kind; + Next_Expected_Kind := Tmp; + end if; + Cur := Aux; + end loop; + + return Res; + end Get_Disabled_Cov_Annotations; end SS_Annotations; diff --git a/tools/gnatcov/ss_annotations.ads b/tools/gnatcov/ss_annotations.ads index 9f7c0a400..b2287543d 100644 --- a/tools/gnatcov/ss_annotations.ads +++ b/tools/gnatcov/ss_annotations.ads @@ -65,12 +65,25 @@ package SS_Annotations is (FI : Source_File_Index); -- Search for external exemptions in FI, from the annotations loaded in -- Ext_Annotation_DB. - -- - -- The newly added annotations will include CU in the corresponding CU - -- field. function Get_Buffer_Annotations (Filename : String) return Instrument.Common.Instr_Annotation_Map; -- Get the buffer annotations relevant to instrumentation for Filename. + function Get_Disabled_Cov_Annotations + (Filename : String) return Instrument.Common.Instr_Annotation_Map; + -- Return the map of annotations that disable coverage regions for + -- Filename. + -- + -- The resulting map already filters out annotations that do not come in + -- pairs: any Cov_Off annotation immediately following a Cov_Off annotation + -- will be discarded, and likewise for Cov_On annotations. + -- + -- The map is also guaranteed to start with a Cov_Off annotation, and end + -- on a Cov_On annotation, so that regions can always be determined from + -- two subsequent annotations. + -- + -- Finally, the resulting annotations are guaranteed not to conflict with + -- any pre-existing annotations for Filename. + end SS_Annotations; From d45def2dca8c2626a02c957ffcb4722fdb60a4e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 28 Aug 2024 15:31:09 +0200 Subject: [PATCH 0939/1483] Instrument.C: Fix handling of escape sequences in preprocessor output gnatcov interprets line directives emitted by the preprocessor to relocate external annotations. This processing did not account for escape sequences generated by the preprocessor, in particular for escaped '\' characters when the host is Windows, resulting in all buffer annotations being ignored. This also fixes an infinite loop which only appears when some annotations could not be remapped. (cherry picked from commit 3b3d7a41c8bec492b2ccc56880580c8c0df2ed06) --- .../tests/ext_annotations/diagnostics/test.py | 4 ++ tools/gnatcov/instrument-c.adb | 9 +++-- tools/gnatcov/strings.adb | 39 +++++++++++++++++++ tools/gnatcov/strings.ads | 7 ++++ 4 files changed, 56 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/ext_annotations/diagnostics/test.py b/testsuite/tests/ext_annotations/diagnostics/test.py index fc39bbe56..6aaaef7b2 100644 --- a/testsuite/tests/ext_annotations/diagnostics/test.py +++ b/testsuite/tests/ext_annotations/diagnostics/test.py @@ -4,6 +4,8 @@ payloads. """ +from e3.testsuite.driver.diff import Substitute + from SCOV.instr import xcov_instrument from SUITE.context import thistest from SUITE.cutils import Wdir @@ -31,11 +33,13 @@ out=log, ) +refiners = thistest.report_output_refiners() + [Substitute("\\", "/")] thistest.fail_if_diff( "../expected.txt", log, "Unexpected messages for 'gnatcov instrument' output", + refiners, ) thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 4e5020902..a9a707dc8 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -4508,6 +4508,7 @@ package body Instrument.C is ("Could not remap " & Annot.Kind'Image & " at " & Slocs.Image (Key (Ext_Annot_Cur))); end; + Next (Ext_Annot_Cur); end loop; end if; @@ -4626,9 +4627,10 @@ package body Instrument.C is In_Directive := True; declare - Directive_Filename : String renames - Str (Line_Matches (2).First .. Line_Matches (2).Last); - Directive_Line : constant Natural := + Directive_Filename : constant String := + Interpret_Escape_Sequence + (Str (Line_Matches (2).First .. Line_Matches (2).Last)); + Directive_Line : constant Natural := Natural'Value (Str (Line_Matches (1).First .. Line_Matches (1).Last)); begin @@ -4715,6 +4717,7 @@ package body Instrument.C is while Has_Element (Next_Sloc) loop Slocs.Replace_Element (Next_Sloc, 0); + Next (Next_Sloc); end loop; end Remap_Locations; diff --git a/tools/gnatcov/strings.adb b/tools/gnatcov/strings.adb index 35307871d..47a0d350b 100644 --- a/tools/gnatcov/strings.adb +++ b/tools/gnatcov/strings.adb @@ -339,4 +339,43 @@ package body Strings is Vec.Append (Unbounded_Slice (From, Arg_Start_Index, Last)); end Append_From_String; + ------------------------------- + -- Interpret_Escape_Sequence -- + ------------------------------- + + function Interpret_Escape_Sequence (Str : String) return String is + use US; + Res : Unbounded_String; + Index : Positive := Str'First; + C : Character; + begin + while Index <= Str'Last loop + if Str (Index) = '\' then + if Index = Str'Last then + raise Constraint_Error with "stray trailing backslash"; + end if; + C := (case Str (Index + 1) is + when 'a' => ASCII.BEL, + when 'b' => ASCII.BS, + when 'e' => ASCII.ESC, + when 'f' => ASCII.FF, + when 'n' => ASCII.LF, + when 'r' => ASCII.CR, + when 't' => ASCII.HT, + when 'v' => ASCII.VT, + when ''' | '"' | '?' | '\' => Str (Index + 1), + when others => + raise Constraint_Error with + "invalid or unknown escape sequence: " + & Str (Index .. Index + 1)); + Index := Index + 2; + else + C := Str (Index); + Index := Index + 1; + end if; + Append (Res, C); + end loop; + return +Res; + end Interpret_Escape_Sequence; + end Strings; diff --git a/tools/gnatcov/strings.ads b/tools/gnatcov/strings.ads index 5c0b59f13..aee09e316 100644 --- a/tools/gnatcov/strings.ads +++ b/tools/gnatcov/strings.ads @@ -156,6 +156,13 @@ package Strings is -- Process From as if it was a comma separated list, and append each -- element to Vec. + function Interpret_Escape_Sequence (Str : String) return String; + -- Return Str but with every occurrence of an escape sequence + -- replaced by the corresponding character. Only single character sequences + -- are supported (no octal nor hexadecimal escape sequences). + -- + -- Raise Constraint_Error on invalid or unsupported escape sequences. + private pragma Inline (Hash); pragma Inline (Equal); From 60360338b499d2af56ff591ad7a34bc58051c9a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 28 Aug 2024 13:40:48 +0200 Subject: [PATCH 0940/1483] SS_Annotations: Fix external exemption file handling for bin traces The full name of a file is not always known in binary trace mode, in that case, default to a best effort using only the simple name to load external annotations. Also add missing coverage expectations on the C unit in the basic exemption test for external annotations. (cherry picked from commit 9f5f8aea3e065c2c2aefb9cceafa1d63cd279533) --- .../ext_annotations/exemptions/src/foo.c | 6 ++--- .../exemptions/src/test_exempt.adb | 9 ++++++-- .../simple_name_check/annotations.toml | 11 +++++++++ .../simple_name_check/src/reset.adb | 4 ++++ .../simple_name_check/src/reset.ads | 2 ++ .../simple_name_check/src/test_reset.adb | 14 +++++++++++ .../ext_annotations/simple_name_check/test.py | 23 +++++++++++++++++++ tools/gnatcov/ss_annotations.adb | 2 +- 8 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 testsuite/tests/ext_annotations/simple_name_check/annotations.toml create mode 100644 testsuite/tests/ext_annotations/simple_name_check/src/reset.adb create mode 100644 testsuite/tests/ext_annotations/simple_name_check/src/reset.ads create mode 100644 testsuite/tests/ext_annotations/simple_name_check/src/test_reset.adb create mode 100644 testsuite/tests/ext_annotations/simple_name_check/test.py diff --git a/testsuite/tests/ext_annotations/exemptions/src/foo.c b/testsuite/tests/ext_annotations/exemptions/src/foo.c index 9abb32441..6ed0c4700 100644 --- a/testsuite/tests/ext_annotations/exemptions/src/foo.c +++ b/testsuite/tests/ext_annotations/exemptions/src/foo.c @@ -3,7 +3,7 @@ int ident (int x) { - if (x == 0) - return -1; - return static_helper (&x); + if (x == 0) // # exempt_c_d + return -1; // # exempt_c_s + return static_helper (&x); // # ok } diff --git a/testsuite/tests/ext_annotations/exemptions/src/test_exempt.adb b/testsuite/tests/ext_annotations/exemptions/src/test_exempt.adb index 45578d29d..98597a3f1 100644 --- a/testsuite/tests/ext_annotations/exemptions/src/test_exempt.adb +++ b/testsuite/tests/ext_annotations/exemptions/src/test_exempt.adb @@ -30,9 +30,14 @@ end Test_Exempt; --# foo.h -- ---%opts: --trace-mode=src --- -- /exempt_h/ l* ## x+ -- /exempt_h_d/ l= ## XoT- -- /exempt_h_s/ l= ## Xs- -- /ok/ l+ ## 0 + +--# foo.c +-- +-- /exempt_c/ l* ## x+ +-- /exempt_c_d/ l= ## XoT- +-- /exempt_c_s/ l= ## Xs- +-- /ok/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/simple_name_check/annotations.toml b/testsuite/tests/ext_annotations/simple_name_check/annotations.toml new file mode 100644 index 000000000..b4da3534d --- /dev/null +++ b/testsuite/tests/ext_annotations/simple_name_check/annotations.toml @@ -0,0 +1,11 @@ +[region] +file="reset.adb" +kind="absolute" +[region.matcher] +start_line=3 +start_col=4 +end_line=3 +end_col=11 +[[region.annotations]] +purpose="xcov.exempt.region" +justification="dummy exemption" diff --git a/testsuite/tests/ext_annotations/simple_name_check/src/reset.adb b/testsuite/tests/ext_annotations/simple_name_check/src/reset.adb new file mode 100644 index 000000000..115293dd7 --- /dev/null +++ b/testsuite/tests/ext_annotations/simple_name_check/src/reset.adb @@ -0,0 +1,4 @@ +procedure Reset (X : in out Integer) is +begin + X := 0; -- # st +end Reset; diff --git a/testsuite/tests/ext_annotations/simple_name_check/src/reset.ads b/testsuite/tests/ext_annotations/simple_name_check/src/reset.ads new file mode 100644 index 000000000..51b2399e0 --- /dev/null +++ b/testsuite/tests/ext_annotations/simple_name_check/src/reset.ads @@ -0,0 +1,2 @@ +procedure Reset (X : in out Integer); +-- Reset X to 0 diff --git a/testsuite/tests/ext_annotations/simple_name_check/src/test_reset.adb b/testsuite/tests/ext_annotations/simple_name_check/src/test_reset.adb new file mode 100644 index 000000000..dbfad0977 --- /dev/null +++ b/testsuite/tests/ext_annotations/simple_name_check/src/test_reset.adb @@ -0,0 +1,14 @@ +with Reset; + +with Support; + +procedure Test_Reset is + X : Integer := 10; +begin + Reset (X); + Support.Assert (X = 0); +end Test_Reset; + +--# reset.adb +-- +-- /st/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/simple_name_check/test.py b/testsuite/tests/ext_annotations/simple_name_check/test.py new file mode 100644 index 000000000..c7dd490e6 --- /dev/null +++ b/testsuite/tests/ext_annotations/simple_name_check/test.py @@ -0,0 +1,23 @@ +""" +Test that attempting to retrieve external exemptions for a file with +no obligations does not crash on binary traces. This used to happen +because such files were not registered under their full name in the +file table, thus resulting in a crash when attempting to get their +full name. + +In this instance, gnatcov would crash attempting to retrieve the full filename +for reset.ads. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run( + CovControl( + covoptions="--external-annotations=../annotations.toml", + instroptions="", + ), +) + +thistest.result() diff --git a/tools/gnatcov/ss_annotations.adb b/tools/gnatcov/ss_annotations.adb index ea017e49a..617a7fb53 100644 --- a/tools/gnatcov/ss_annotations.adb +++ b/tools/gnatcov/ss_annotations.adb @@ -219,7 +219,7 @@ package body SS_Annotations is -- Match the entries on FI - File := Create (+Get_Full_Name (FI)); + File := Create (+Get_Full_Name (FI, Or_Simple => True)); Matches := Match_Entries ((1 => File), Ext_Annotation_DB, From d1f4b1a00dfda4b520f1c5c861d7b285ca4f5dbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 10 Sep 2024 10:51:28 +0200 Subject: [PATCH 0941/1483] XFail external exemption test on bin-traces,C,-O1 This is pendig investigation of the actual underlying issue. (cherry picked from commit d0983b021be514a6b85db98846540eddbaed5c8d) --- testsuite/tests/ext_annotations/exemptions/test.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/ext_annotations/exemptions/test.opt b/testsuite/tests/ext_annotations/exemptions/test.opt index e69de29bb..a3d0e79c1 100644 --- a/testsuite/tests/ext_annotations/exemptions/test.opt +++ b/testsuite/tests/ext_annotations/exemptions/test.opt @@ -0,0 +1 @@ +bin-traces,CARGS_O1 XFAIL Issues with optimization, see #324 From 8ce06b686188971d7bbfcc2df62ba540678fab14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 12 Sep 2024 12:11:02 +0200 Subject: [PATCH 0942/1483] SC_Obligations: Add support for pragma Simulate_Internal_Error (cherry picked from commit 12f9206a5f22793e78091a8139868cd5d7077924) --- tools/gnatcov/sc_obligations.ads | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 0064e83aa..823e637a7 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -1170,6 +1170,7 @@ package SC_Obligations is Pragma_Short_Descriptors, Pragma_Side_Effects, Pragma_Simple_Storage_Pool_Type, + Pragma_Simulate_Internal_Error, Pragma_Source_File_Name, Pragma_Source_File_Name_Project, Pragma_Source_Reference, @@ -1442,6 +1443,7 @@ package SC_Obligations is Pragma_Shared_Passive => False, Pragma_Side_Effects => False, Pragma_Simple_Storage_Pool_Type => False, + Pragma_Simulate_Internal_Error => False, Pragma_Source_Reference => False, Pragma_Static_Elaboration_Desired => False, Pragma_Stream_Convert => False, From 403777d4b0c466961652a457a2fb45becae6c5e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 27 Aug 2024 14:14:36 +0200 Subject: [PATCH 0943/1483] minicheck.py: Allow inspection of xcov reports with exemptions (cherry picked from commit beea42f5bac3862bea2a89612c43379f79644c79) --- testsuite/SCOV/minicheck.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 0340e0112..7cdd8a9f7 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -497,8 +497,13 @@ def check_xcov_content(filename, expected_cov, trace_mode=None): >>> {'+': {5, 7}, '!': {6}} This is interpreted as: lines 5 and 7 must be fully covered (+), line 6 - must be partially covered (!) and all other lines must be no-code (.), - fully covered (+) or undetermined coverage (?). + must be partially covered (!) and all other lines must be no-code (.) or + fully covered (+). + + The recognized coverage annotation are partially covered (!), + not covered (-), undetermined coverage (?), disabled coverage (D), + exempted with no violations (#) or exempted with at least one + violation (*). """ @@ -511,7 +516,15 @@ def remove_empty_sets(data): } # Check that expected coverage data contain only supported line annotations - invalid_line_annotations = set(expected_cov) - {"+", "!", "-", "?", "D"} + invalid_line_annotations = set(expected_cov) - { + "+", + "!", + "-", + "?", + "D", + "#", + "*", + } assert not invalid_line_annotations, "Invalid line annotations: {}".format( " ".join(sorted(invalid_line_annotations)) ) From f8c6c987f3bd1419914db9cada49fa92dbab40f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 27 Aug 2024 14:16:34 +0200 Subject: [PATCH 0944/1483] Add new commands to manipulate external annotation files The three new commands, add-annotation, delete-annotation and show-annotations allow the user to generate and inspect stable_sloc entry files, without needing to know the syntax nor the expected fields for the annotations recognized by gnatcov. A basic test is added in this commit, more thorough testing will be added in the following commit to simplify the review process. (cherry picked from commit 0e6f90a747dbe72405479de12e34971a6103abaa) --- .../ext_annotations/diagnostics/expected.txt | 8 +- .../exemptions/exemptions.toml | 12 +- .../tests/ext_annotations/gen/basic/foo.c | 5 + .../tests/ext_annotations/gen/basic/main.adb | 16 + .../gen/basic/show_expected.txt | 4 + .../tests/ext_annotations/gen/basic/test.py | 143 ++++ .../gen/invalidation/show_expected.txt | 6 + .../ext_annotations/gen/invalidation/test.py | 114 +++ .../gen/invalidation/v1/main.adb | 11 + .../gen/invalidation/v1/main_c.c | 12 + .../gen/invalidation/v2/main.adb | 13 + .../gen/invalidation/v2/main_c.c | 13 + tools/gnatcov/command_line.ads | 180 +++- tools/gnatcov/coverage_options.adb | 63 ++ tools/gnatcov/coverage_options.ads | 18 + tools/gnatcov/files_table.adb | 17 + tools/gnatcov/files_table.ads | 7 + tools/gnatcov/gnatcov_bits_specific.adb | 14 + tools/gnatcov/instrument-c.adb | 30 +- tools/gnatcov/instrument.ads | 3 +- tools/gnatcov/paths.adb | 16 + tools/gnatcov/paths.ads | 4 + tools/gnatcov/slocs.adb | 40 + tools/gnatcov/slocs.ads | 3 + tools/gnatcov/ss_annotations.adb | 772 +++++++++++++++++- tools/gnatcov/ss_annotations.ads | 22 +- tools/gnatcov/switches.ads | 5 + 27 files changed, 1474 insertions(+), 77 deletions(-) create mode 100644 testsuite/tests/ext_annotations/gen/basic/foo.c create mode 100644 testsuite/tests/ext_annotations/gen/basic/main.adb create mode 100644 testsuite/tests/ext_annotations/gen/basic/show_expected.txt create mode 100644 testsuite/tests/ext_annotations/gen/basic/test.py create mode 100644 testsuite/tests/ext_annotations/gen/invalidation/show_expected.txt create mode 100644 testsuite/tests/ext_annotations/gen/invalidation/test.py create mode 100644 testsuite/tests/ext_annotations/gen/invalidation/v1/main.adb create mode 100644 testsuite/tests/ext_annotations/gen/invalidation/v1/main_c.c create mode 100644 testsuite/tests/ext_annotations/gen/invalidation/v2/main.adb create mode 100644 testsuite/tests/ext_annotations/gen/invalidation/v2/main_c.c diff --git a/testsuite/tests/ext_annotations/diagnostics/expected.txt b/testsuite/tests/ext_annotations/diagnostics/expected.txt index 5bafcd55f..9d347412a 100644 --- a/testsuite/tests/ext_annotations/diagnostics/expected.txt +++ b/testsuite/tests/ext_annotations/diagnostics/expected.txt @@ -1,11 +1,11 @@ warning: ../load_fail.toml:15:1: Error while parsing entry "missing_field": Missing "annotations" field warning: ../load_fail.toml:18:1: Error while parsing entry "missing_justif": Missing "kind" field +warning: Entry "unknown_kind_exempt" has an unknown annotation kind, it will be ignored. +warning: Entry "unknown_kind_cov" has an unknown annotation kind, it will be ignored. +warning: Entry "unknown_kind_buffers" has an unknown annotation kind, it will be ignored. +warning: Missing or empty justification for external exemption annotation "missing_justif", it will be ignored. warning: main.adb:3:4: Conflicting annotations for this line, ignoring the external annotation "duplicate_2" -warning: Unexpected or unknown annotation kind for annotation "unknown_kind_buffers": xcov.buffers.foo_bar warning: main.adb:3:4: Conflicting annotations for this line, ignoring the external annotation "duplicate_cov_2" -warning: Unexpected or unknown annotation kind for annotation "unknown_kind_cov": xcov.cov.foo_bar warning: main.adb: 2:4: external Cov_On annotation with no previous Cov_Off annotation, ignoring it. warning: main.adb: 3:4: external COV_OFF annotation with no subsequent COV_ON annotation, ignoring it. warning: main.adb:3:4: Conflicting annotations for this line, ignoring the external annotation "duplicate_4" -warning: Unexpected or unknown annotation kind for annotation "unknown_kind_exempt": xcov.exempt.foo_bar -warning: main.adb:3:4: Missing or empty justification for external exemption annotation "missing_justif" diff --git a/testsuite/tests/ext_annotations/exemptions/exemptions.toml b/testsuite/tests/ext_annotations/exemptions/exemptions.toml index 3434605b8..7bc7fa519 100644 --- a/testsuite/tests/ext_annotations/exemptions/exemptions.toml +++ b/testsuite/tests/ext_annotations/exemptions/exemptions.toml @@ -46,9 +46,9 @@ file="foo.h" kind="absolute" [region_c.matcher] start_line=4 -start_col=3 +start_col=1 end_line=5 -end_col=14 +end_col=16 [[region_c.annotations]] purpose="xcov.exempt.region" justification="defensive code, not to be triggered (region)" @@ -60,10 +60,10 @@ file="foo.c" kind="absolute" [on_c.matcher] start_line=6 -start_col=3 +start_col=1 # End line annotations does not matter for exempt_on end_line=6 -end_col=3 +end_col=1 [[on_c.annotations]] purpose="xcov.exempt.on" justification="garbage code, not to be triggered (on)" @@ -73,9 +73,9 @@ file="foo.c" kind="absolute" [off_c.matcher] start_line=7 -start_col=15 +start_col=17 # End line annotations does not matter for exempt_off end_line=7 -end_col=15 +end_col=17 [[off_c.annotations]] purpose="xcov.exempt.off" diff --git a/testsuite/tests/ext_annotations/gen/basic/foo.c b/testsuite/tests/ext_annotations/gen/basic/foo.c new file mode 100644 index 000000000..2f8ce7b14 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/basic/foo.c @@ -0,0 +1,5 @@ +int +ident (int x) +{ + return x; +} diff --git a/testsuite/tests/ext_annotations/gen/basic/main.adb b/testsuite/tests/ext_annotations/gen/basic/main.adb new file mode 100644 index 000000000..c8d6cadd6 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/basic/main.adb @@ -0,0 +1,16 @@ +with Interfaces.C; use Interfaces.C; + +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + + function Ident (X : int) return int; + pragma Import(Convention => C, Entity => Ident, External_Name => "ident"); + + X : int := 5; + Res : int := Ident (X); +begin + if X /= Res then + Put_Line ("C really does weird things with their integers"); + end if; +end Main; diff --git a/testsuite/tests/ext_annotations/gen/basic/show_expected.txt b/testsuite/tests/ext_annotations/gen/basic/show_expected.txt new file mode 100644 index 000000000..ac3096f35 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/basic/show_expected.txt @@ -0,0 +1,4 @@ + +main.adb: +- 13:4 - 13:4; id: exempt_on_1; kind: Exempt_On; Justification: unexpected C failure +- 15:11 - 15:11; id: exempt_off_1; kind: Exempt_Off diff --git a/testsuite/tests/ext_annotations/gen/basic/test.py b/testsuite/tests/ext_annotations/gen/basic/test.py new file mode 100644 index 000000000..33343a259 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/basic/test.py @@ -0,0 +1,143 @@ +""" +Simple sanity checking test for the add-annotation, delete-annotation and +show-annotation commands. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +annotation_file = "annotations.toml" + +# Create a simple project to work on +gprsw = GPRswitches( + root_project=gprfor( + srcdirs=[".."], + mains=["main.adb"], + langs=["Ada", "C"], + ) +) + +# Instrument, build and run +cov_args = build_and_run( + gprsw=gprsw, + covlevel="stmt+decision", + mains=["main"], + extra_coverage_args=[ + "-axcov", + f"--external-annotations={annotation_file}", + ], +) + +# Generate some annotations. Only use exemption annotations as they can be +# interpreted at coverage time and do not require a full coverage cycle when +# modified. +# Pass the project file as argument to ensure the annotations only contain the +# required +xcov( + [ + "add-annotation", + "--kind=Exempt_On", + "--justification", + "unexpected C failure", + "--location=13:4", + f"--output={annotation_file}", + "--annotation-id=exempt_on_1", + "../main.adb", + ] + + gprsw.cov_switches, + force_project_args=True, +) +xcov( + [ + "add-annotation", + "--kind=Exempt_Off", + "--location=15:11", + f"--external-annotations={annotation_file}", + f"--output={annotation_file}", + "--annotation-id=exempt_off_1", + "../main.adb", + ] + + gprsw.cov_switches, + force_project_args=True, +) + +# Check we get the intended coverage result +cov_1 = "cov_1" +xcov(cov_args + [f"--output-dir={cov_1}"], out="cov_1.log") +check_xcov_reports( + cov_1, + expected_cov={ + "main.adb.xcov": {"+": {10, 11}, "*": {13, 14, 15}}, + "foo.c.xcov": {"+": {4}}, + }, +) + +show_log = "show.log" + +# Show the annotations and check against a baseline +xcov( + [ + "show-annotations", + f"--external-annotations={annotation_file}", + ] + + gprsw.cov_switches, + out=show_log, +) + +thistest.fail_if_diff( + baseline_file="../show_expected.txt", + actual_file=show_log, + failure_message='Unexpected "gnatcov show-annotations" output', +) + +# Delete the annotations and add a new one +xcov( + [ + "delete-annotation", + f"--external-annotations={annotation_file}", + "--annotation-id=exempt_on_1", + f"--output={annotation_file}", + ], +) +xcov( + [ + "delete-annotation", + f"--external-annotations={annotation_file}", + "--annotation-id=exempt_off_1", + f"--output={annotation_file}", + ], +) +xcov( + [ + "add-annotation", + "--kind=Exempt_Region", + "--justification", + "Useless exemption", + "--start-location=4:3", + "--end-location=4:12", + f"--output={annotation_file}", + "--annotation-id=exempt_region_1", + "../foo.c", + ] + + gprsw.cov_switches, + force_project_args=True, +) + +# Re-compute report to ensure the annotations have indeed been modified +# Check we get the intended coverage result +cov_2 = "cov_2" +xcov(cov_args + [f"--output-dir={cov_2}"]) +check_xcov_reports( + cov_2, + expected_cov={ + "main.adb.xcov": {"+": {10, 11}, "!": {13}, "-": {14}}, + "foo.c.xcov": {"#": {4}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/invalidation/show_expected.txt b/testsuite/tests/ext_annotations/gen/invalidation/show_expected.txt new file mode 100644 index 000000000..aae5b772a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/invalidation/show_expected.txt @@ -0,0 +1,6 @@ + +main.adb: +- STALE ANNOTATION; id: exempt_ada; kind: Exempt_Region; Justification: Useless code; diagnostic: Contents of changed + +main_c.c: +- STALE ANNOTATION; id: exempt_c; kind: Exempt_Region; Justification: Useless code; diagnostic: file has been modified diff --git a/testsuite/tests/ext_annotations/gen/invalidation/test.py b/testsuite/tests/ext_annotations/gen/invalidation/test.py new file mode 100644 index 000000000..8b585e1b1 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/invalidation/test.py @@ -0,0 +1,114 @@ +""" +Basic test concerning invalidation of annotations by gnatcov when the +annotated sources have been modified beyond what stable_sloc can manage. +""" + +import os + +from SCOV.minicheck import ( + build_run_and_coverage, + check_xcov_reports, + contents_of, + xcov, +) +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +annotation_file = "annotations.toml" + +prefix = os.path.join("..", "v1", "") + +# Create annotations for the V1 sources +xcov( + [ + "add-annotation", + "--kind=Exempt_Region", + "--justification", + "Useless code", + "--start-location=4:7", + "--end-location=4:16", + f"--output={annotation_file}", + "--annotation-id=exempt_ada", + f"--source-root={prefix}", + "../v1/main.adb", + ] +) +xcov( + [ + "add-annotation", + "--kind=Exempt_Region", + "--justification", + "Useless code", + "--start-location=5:3", + "--end-location=5:12", + f"--external-annotations={annotation_file}", + f"--output={annotation_file}", + "--annotation-id=exempt_c", + f"--source-root={prefix}", + "../v1/main_c.c", + ] +) + +# Create a project from V2 sources +gprsw = GPRswitches( + root_project=gprfor( + mains=["main.adb"], + srcdirs=["../v2"], + langs=["Ada", "C"], + ) +) + +# Try to show the annotations on the modified sources +show_log = "show.log" +xcov( + [ + "show-annotations", + f"--external-annotations={annotation_file}", + "--quiet", + ] + + gprsw.cov_switches, + out=show_log, +) + +thistest.fail_if_diff( + baseline_file="../show_expected.txt", + actual_file=show_log, + failure_message='Unexpected "gnatcov show-annotations" output', +) + +# Run the coverage workflow, check for expected warnings and that no +# annotations have been taken into acount. Do not consider main_c.c as +# a main to avoid issues with the last_chance_chandler, the coverage results +# are secondary anyways. +coverage_log = "coverage.log" +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_coverage_args=[ + "-axcov", + f"--external-annotations={annotation_file}", + ], + out=coverage_log, +) + +thistest.fail_if_no_match( + "Unexpected 'gnatcov coverage' warnings:", + regexp=r"(\n?warning: Stale annotation for main.*){2}", + actual=contents_of(coverage_log), +) + +# We expect violations and no exempted regions +check_xcov_reports( + reports_dir="obj", + expected_cov={ + "main.adb.xcov": {"+": {6, 9, 12}}, + "main_c.c.xcov": {"-": {6, 12}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/invalidation/v1/main.adb b/testsuite/tests/ext_annotations/gen/invalidation/v1/main.adb new file mode 100644 index 000000000..088538465 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/invalidation/v1/main.adb @@ -0,0 +1,11 @@ +procedure Main is + function Nested (X : Integer) return Integer is + begin + return X; + end Nested; + + Y : Integer; + pragma Volatile (Y); +begin + Y := Nested (2); +end Main; diff --git a/testsuite/tests/ext_annotations/gen/invalidation/v1/main_c.c b/testsuite/tests/ext_annotations/gen/invalidation/v1/main_c.c new file mode 100644 index 000000000..2932e2a43 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/invalidation/v1/main_c.c @@ -0,0 +1,12 @@ + +int +ident (int x) +{ + return x; +} + +int +main () +{ + return 0; +} diff --git a/testsuite/tests/ext_annotations/gen/invalidation/v2/main.adb b/testsuite/tests/ext_annotations/gen/invalidation/v2/main.adb new file mode 100644 index 000000000..a6ca7855f --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/invalidation/v2/main.adb @@ -0,0 +1,13 @@ +procedure Main is + function Nested (X : Integer) return Integer is + begin + -- Useless + + return X; + end Nested; + + Y : Integer; + pragma Volatile (Y); +begin + Y := Nested (2); +end Main; diff --git a/testsuite/tests/ext_annotations/gen/invalidation/v2/main_c.c b/testsuite/tests/ext_annotations/gen/invalidation/v2/main_c.c new file mode 100644 index 000000000..856db0d1d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/invalidation/v2/main_c.c @@ -0,0 +1,13 @@ + +int +ident (int x) +{ + // Useless + return x; +} + +int +main () +{ + return 0; +} diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index d42c77b7b..66f9ab427 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -67,7 +67,11 @@ package Command_Line is Cmd_Instrument_Source, Cmd_Instrument_Main, Cmd_Setup_Integration, - Cmd_Gcc_Wrapper); + Cmd_Gcc_Wrapper, + + Cmd_Add_Annotation, + Cmd_Delete_Annotation, + Cmd_Show_Annotations); -- Set of commands we support. More complete descriptions below. type Bool_Options is @@ -97,7 +101,9 @@ package Command_Line is Opt_Full_Slugs, Opt_Relocate_Build_Tree, Opt_Warnings_As_Errors, - Opt_Instrument_Block); + Opt_Instrument_Block, + Opt_Force, + Opt_Annotate_After); -- Set of boolean options we support. More complete descriptions below. type String_Options is @@ -147,7 +153,14 @@ package Command_Line is Opt_Project_Name, Opt_Source_Root, Opt_Db, - Opt_GPR_Registry_Format); + Opt_GPR_Registry_Format, + Opt_Annotation_Kind, + Opt_Annotation_Id, + Opt_Location, + Opt_Start_Location, + Opt_End_Location, + Opt_Justification, + Opt_SS_Backend); -- Set of string options we support. More complete descriptions below. type String_List_Options is @@ -190,6 +203,9 @@ package Command_Line is with Static_Predicate => Cmd_All_Setups in Cmd_Setup | Cmd_Setup_Integration; + subtype Cmd_All_Annotate is Command_Type + range Cmd_Add_Annotation .. Cmd_Show_Annotations; + package Parser is new Argparse (Command_Type, Bool_Options, String_Options, String_List_Options); use Parser; @@ -428,7 +444,41 @@ package Command_Line is Description => "Implementation of the GCC wrapper for integrated instrumentation.", Pattern => "[JSON-CONFIG-FILE]", - Internal => True)); + Internal => True), + Cmd_Add_Annotation => Create + (Name => "add-annotation", + Description => + "Add an annotation tied to the specified source locations, to" + & " influence the instrumentation of source files or the coverage" + & " analysis. All annotations passed through --external-annotations" + & " are consolidated and written to OUTPUT_FILENAME." + & ASCII.LF & ASCII.LF + & "The relevant switches depend on the annotation KIND:" + & Annot_Kind_Relevant_Switches, + Pattern => + "--kind=KIND [--external-annotations=FILENAME] --output=" + & "OUTPUT_FILENAME [OPTIONS] FILENAME", + Internal => False), + Cmd_Delete_Annotation => Create + (Name => "delete-annotation", + Description => + "Delete the annotation with identifier IDENTIFIER from those stored" + & " in EXT_FILENAMEs, and write back the remaining annotations to" + & " OUTPUT_FILENAME.", + Pattern => + "--annotation-id=IDENTIFIER --external-annotations=EXT_FILENAME" + & "--output=OUTPUT_FILENAME", + Internal => False), + Cmd_Show_Annotations => Create + (Name => "show-annotations", + Description => + "Show the annotations stored in EXT_FILENAME that apply to FILES," + & " if present or to the project sources. Optionally filter the" + & " kind of annotations to show with --kind.", + Pattern => + "--external-annotations=EXT_FILENAME [--kind=KIND] [OPTIONS]" + & " [FILENAME]", + Internal => False)); Bool_Infos : constant Bool_Option_Info_Array := (Opt_Verbose => Create @@ -636,6 +686,24 @@ package Command_Line is & " single instrumentation counter incrementation for a" & " statement block.", Commands => (Cmd_Instrument => True, others => False), + Internal => False), + Opt_Force => Create + (Long_Name => "--force", + Short_Name => "-f", + Help => + "Overwrite preexisting annotations with the same kind matching the" + & " same location, or any preexisting annotation with the same" + & " identifier as the one specified on the command line.", + Commands => (Cmd_Add_Annotation | Cmd_Delete_Annotation => True, + others => False), + Internal => False), + Opt_Annotate_After => Create + (Long_Name => "--annotate-after", + Help => + "Add the annotation after the statement designated by the" + & " --location switch, as opposed to the default behavior which" + & " inserts the annotation before the designated statement.", + Commands => (Cmd_Add_Annotation => True, others => False), Internal => False)); String_Infos : constant String_Option_Info_Array := @@ -719,12 +787,16 @@ package Command_Line is (Long_Name => "--output", Short_Name => "-o", Pattern => "[FILE]", - Help => "Put the report/asm output/trace file into FILE.", + Help => + "Put the report/asm output/trace file/external annotations into" + & " FILE.", Commands => (Cmd_Run | Cmd_Coverage | Cmd_Convert - | Cmd_Dump_CFG => True, - others => False), + | Cmd_Dump_CFG + | Cmd_Add_Annotation + | Cmd_Delete_Annotation => True, + others => False), At_Most_Once => False, Internal => False), Opt_Output_Directory => Create @@ -941,7 +1013,8 @@ package Command_Line is Commands => (Cmd_Setup | Cmd_Instrument_Project | Cmd_Setup_Integration - | Cmd_Instrument_Main => True, + | Cmd_Instrument_Main + | Cmd_Add_Annotation => True, others => False), At_Most_Once => False, Internal => False), @@ -1181,9 +1254,11 @@ package Command_Line is (Long_Name => "--source-root", Pattern => "PATH", Help => - "Option specific to the Cobertura coverage report: remove the" - & " specified prefix from the filenames in the report.", - Commands => (Cmd_Coverage => True, others => False), + "Remove the specified prefix from the filenames in the Cobertura" + & " report (coverage command), or from the generated annotation" + & " files (add-annotation command).", + Commands => + (Cmd_Coverage | Cmd_Add_Annotation => True, others => False), At_Most_Once => True, Internal => False), @@ -1205,6 +1280,74 @@ package Command_Line is Help => "Format for the printed GPR registry.", Commands => (Cmd_Print_GPR_Registry => True, others => False), At_Most_Once => False, + Internal => True), + + Opt_Annotation_Kind => Create + (Long_Name => "--kind", + Pattern => "KIND", + Help => + "Kind of annotation, must be one of: " & Annotation_Kind_Options, + Commands => (Cmd_Add_Annotation + | Cmd_Delete_Annotation + | Cmd_Show_Annotations => True, + others => False), + At_Most_Once => False, + Internal => False), + Opt_Annotation_Id => Create + (Long_Name => "--annotation-id", + Pattern => "IDENTIFIER", + Help => + "Unique identifier for the annotation. Automatically generated if" + & " not specified", + Commands => (Cmd_Add_Annotation | Cmd_Delete_Annotation => True, + others => False), + At_Most_Once => False, + Internal => False), + Opt_Location => Create + (Short_Name => "-l", + Long_Name => "--location", + Pattern => "LINE:COL", + Help => + "Location at which the annotation applies. LINE and COL should be" + & " positive integers.", + Commands => (Cmd_Add_Annotation => True, others => False), + At_Most_Once => False, + Internal => False), + Opt_Start_Location => Create + (Long_Name => "--start-location", + Pattern => "LINE:COL", + Help => + "Location of the beginning of the range to which the annotation" + & " applies. LINE and COL should be positive integers.", + Commands => (Cmd_Add_Annotation => True, others => False), + At_Most_Once => False, + Internal => False), + Opt_End_Location => Create + (Long_Name => "--end-location", + Pattern => "LINE:COL", + Help => + "Location of the end of the range to which the annotation applies." + & " LINE and COL should be positive integers.", + Commands => (Cmd_Add_Annotation => True, others => False), + At_Most_Once => False, + Internal => False), + Opt_Justification => Create + (Long_Name => "--justification", + Pattern => "TEXT", + Help => + "Justification for the exemption annotations. Required for the" + & " ""exempt.on"" and ""exempt.region"" annotation kinds.", + Commands => (Cmd_Add_Annotation => True, others => False), + At_Most_Once => False, + Internal => False), + Opt_SS_Backend => Create + (Long_Name => "--ss_backend", + Pattern => "NAME", + Help => + "Specify the Stable_Sloc backend to be used when creating the" + & " annotation entry", + Commands => (Cmd_Add_Annotation => True, others => False), + At_Most_Once => False, Internal => True)); String_List_Infos : constant String_List_Option_Info_Array := @@ -1489,12 +1632,19 @@ package Command_Line is Opt_Ext_Annotations => Create (Long_Name => "--external-annotations", - Help => "Specify external annotation files", + Help => + "Specify external annotation files. For annotation commands that" + & " modify the set of external annotations (add-annotation," + & " delete-annotation), all the annotations from all files" + & " (after addition / deletion) are written back to the file passed" + & " to --output, effectively combining the input annotation files.", Commands => - (Cmd_Instrument | Cmd_Coverage => True, others => False), + (Cmd_Instrument + | Cmd_Coverage + | Cmd_All_Annotate => True, + others => False), Pattern => "FILENAME|@LISTFILE", - Internal => True) - ); + Internal => False)); procedure Bool_Callback (Result : in out Parsed_Arguments; diff --git a/tools/gnatcov/coverage_options.adb b/tools/gnatcov/coverage_options.adb index d72fd8f2d..b95939c63 100644 --- a/tools/gnatcov/coverage_options.adb +++ b/tools/gnatcov/coverage_options.adb @@ -18,6 +18,8 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; +with SC_Obligations; + package body Coverage_Options is function Level_Options @@ -215,6 +217,67 @@ package body Coverage_Options is end loop; end Add_Source_Coverage_Level_Combinaisons; + function Annotation_Kind_Options return String is + use SC_Obligations; + Res : Unbounded_String := +Kind_Image (Exempt_Region); + begin + for Kind in Exempt_On .. Any_Annotation_Kind'Last loop + Res := Res & ", " & Kind_Image (Kind); + end loop; + return +Res; + end Annotation_Kind_Options; + + ---------------------------------- + -- Annot_Kind_Relevant_Switches -- + ---------------------------------- + + function Annot_Kind_Relevant_Switches return String is + use SC_Obligations; + Res : Unbounded_String; + begin + for Kind in Exempt_Region .. Any_Annotation_Kind'Last loop + Res := Res & + (+(ASCII.LF & ASCII.LF & " " & Kind_Image (Kind) & ": ")); + case Kind is + when Exempt_On => + Res := Res & "--location=LINE:COL --justification=MESSAGE"; + when Exempt_Off => + Res := Res & "--location=LINE:COL"; + when Exempt_Region => + Res := Res + & "--start-location=LINE:COL --end-location=LINE:COL" + & " --justification=MESSAGE"; + when Dump_Buffers => + Res := Res + & "--location=LINE:COL [--annotate-after]" + & " [--dump-filename-prefix=TEXT]"; + when Reset_Buffers => + Res := Res & "--location=LINE:COL [--annotate-after]"; + when Cov_On => + Res := Res & "--location=LINE:COL"; + when Cov_Off => + Res := Res & "--location=LINE:COL [--justification=MESSAGE]"; + end case; + end loop; + return US.To_String (Res); + end Annot_Kind_Relevant_Switches; + + ---------------- + -- Kind_Image -- + ---------------- + + function Kind_Image + (Kind : SC_Obligations.Any_Annotation_Kind) return String is + (case Kind is + when SC_Obligations.Unknown => "Unknown", + when SC_Obligations.Exempt_Region => "Exempt_Region", + when SC_Obligations.Exempt_On => "Exempt_On", + when SC_Obligations.Exempt_Off => "Exempt_Off", + when SC_Obligations.Dump_Buffers => "Dump_Buffers", + when SC_Obligations.Reset_Buffers => "Reset_Buffers", + when SC_Obligations.Cov_Off => "Cov_Off", + when SC_Obligations.Cov_On => "Cov_On"); + begin -- Register command line options for valid combinations of coverage levels diff --git a/tools/gnatcov/coverage_options.ads b/tools/gnatcov/coverage_options.ads index caabdb62c..9c712dbb6 100644 --- a/tools/gnatcov/coverage_options.ads +++ b/tools/gnatcov/coverage_options.ads @@ -20,6 +20,7 @@ with Ada.Containers.Ordered_Maps; with GNAT.Strings; +limited with SC_Obligations; with Strings; use Strings; package Coverage_Options is @@ -90,4 +91,21 @@ package Coverage_Options is -- Return a string expression describing valid --level alternatives -- for object coverage, separated by Separator. + function Annotation_Kind_Options return String; + -- Return the list of accepted values for the --kind switch for the gnatcov + -- annotate command. + + function Annot_Kind_Relevant_Switches return String; + -- Return the switches relevant for each kind, in the form + -- + -- : Required_Switches .. [Optional_Switches] + -- + -- One annotation kind on its own line. + + function Kind_Image + (Kind : SC_Obligations.Any_Annotation_Kind) return String; + -- Return the corresponding enumeration literal string, in usual Ada case. + -- + -- Located here due to elaboration constraints. + end Coverage_Options; diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 246ca65bf..664ee4ea2 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -1674,6 +1674,23 @@ package body Files_Table is end return; end Name_For_Rebase; + ------------------------- + -- Sloc_Intersects_SCO -- + ------------------------- + + function Sloc_Intersects_SCO (Sloc : Source_Location) return SCO_Id is + LI : constant Line_Info_Access := Get_Line (Sloc); + begin + if LI /= null and then LI.SCOs /= null then + for SCO of LI.SCOs.all loop + if Slocs.In_Range (Sloc, Sloc_Range (SCO)) then + return SCO; + end if; + end loop; + end if; + return No_SCO_Id; + end Sloc_Intersects_SCO; + ------------------------------- -- Writeable_Sloc_To_SCO_Map -- ------------------------------- diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 2f9a95a5d..3d5e3fabd 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -513,6 +513,13 @@ package Files_Table is -- Get line info (or text) at File:Index (or at Sloc) + function Sloc_Intersects_SCO (Sloc : Source_Location) return SCO_Id; + -- Returns a SCO_Id in which Sloc lies. If Sloc is not within any SCO, + -- return No_SCO_Id. + -- + -- In case multiple SCOs contain Sloc, the result is the Id of the first + -- SCO registered in the line info corresponding to Sloc. + type ALI_Region_Annotation_Kind is (Exemption, Disable_Coverage); procedure Populate_Annotations diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 5adb8b689..59ddd9223 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -515,6 +515,7 @@ procedure GNATcov_Bits_Specific is Save_Temps := Args.Bool_Args (Opt_Save_Temps); SPARK_Compat := Args.Bool_Args (Opt_SPARK_Compat); Use_Full_Slugs := Args.Bool_Args (Opt_Full_Slugs); + Force := Args.Bool_Args (Opt_Force); if Args.Bool_Args (Opt_Recursive) then Warn ("--recursive is deprecated. Recursive is now the default" @@ -831,9 +832,14 @@ procedure GNATcov_Bits_Specific is end; end if; + -- Import all external annotation files (this does not yet match the + -- entries on actual source files) and validate that the annotations + -- relevant to gnatcov are well formed. + for Arg of Args.String_List_Args (Opt_Ext_Annotations) loop Load_Ext_Annotations (Arg); end loop; + Validate_Annotations; -- ... then, handle remaning arguments, which have subcommand-specific -- meanings. @@ -2535,6 +2541,14 @@ begin (Input_File => +Args.Remaining_Args (0), Output_File => +Args.Remaining_Args (1)); + when Cmd_Add_Annotation => + SS_Annotations.Add_Annotation (Args); + + when Cmd_Delete_Annotation => + SS_Annotations.Delete_Annotation (Args); + + when Cmd_Show_Annotations => + SS_Annotations.Show_Annotations (Args); end case; if Misc_Trace.Is_Active then diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index a9a707dc8..3cdcf8c0a 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -596,27 +596,14 @@ package body Instrument.C is begin for Ann of UIC.Annotations loop declare - Sloc : constant Source_Location := Ann.Sloc; - LI : constant Line_Info_Access := Get_Line (Sloc); - Deleted : Boolean := False; + Sloc : Source_Location renames Ann.Sloc; + SCO : constant SCO_Id := Sloc_Intersects_SCO (Sloc); begin - -- Check that no SCOs on the line of the annotation intersect - -- the annotation Sloc. If one does, discard the annotation and - -- warn the user as this is not a supported use case. - - if LI /= null and then LI.SCOs /= null - then - for SCO of LI.SCOs.all loop - if Slocs.In_Range (Sloc, Sloc_Range (SCO)) then - Warn ("Exemption annotation at " & Slocs.Image (Sloc) - & " intersects a coverage obligation (" - & Image (SCO, True) & "), ignoring it"); - Deleted := True; - exit; - end if; - end loop; - end if; - if not Deleted then + if SCO /= No_SCO_Id then + Warn ("Exemption annotation at " & Slocs.Image (Sloc) + & " intersects a coverage obligation (" + & Image (SCO, True) & "), ignoring it"); + else Filtered_Annotations.Append (Ann); end if; end; @@ -3568,7 +3555,8 @@ package body Instrument.C is Filter_Annotations (UIC); UIC.Import_Annotations (UIC.CUs); for Cur in UIC.CUs.Iterate loop - Import_External_Exemptions (Created_Unit_Maps.Key (Cur)); + Import_External_Exemptions + (Created_Unit_Maps.Key (Cur), Filter => True); end loop; Import_Non_Instrumented_LL_SCOs (UIC, SCO_Map); diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index bbf443028..da5d77c1c 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -72,8 +72,7 @@ package Instrument is function "&" (Left, Right : Ada_Qualified_Name) return Ada_Qualified_Name renames Ada_Identifier_Vectors."&"; - function To_Ada (Name : Ada_Qualified_Name) return String - with Pre => not Name.Is_Empty; + function To_Ada (Name : Ada_Qualified_Name) return String; -- Turn the given qualified name into Ada syntax procedure Read is new Read_Vector diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index 276a1f55a..8612cda21 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -335,4 +335,20 @@ package body Paths is return Path; end Workaround_Simple_Name; + ---------------------------- + -- Has_Relative_Component -- + ---------------------------- + + function Has_Relative_Component (Path : String) return Boolean is + begin + for I in Path'First .. Path'Last - 1 loop + if Path (I) = '.' + and then Path (I + 1) in '.' | GNAT.OS_Lib.Directory_Separator + then + return False; + end if; + end loop; + return True; + end Has_Relative_Component; + end Paths; diff --git a/tools/gnatcov/paths.ads b/tools/gnatcov/paths.ads index 93c0e8ae0..508311119 100644 --- a/tools/gnatcov/paths.ads +++ b/tools/gnatcov/paths.ads @@ -71,4 +71,8 @@ package Paths is -- Unix systems: Ada.Directories.Simple_Name misbehaves in the presence of -- backslashes. Provide our own implementation as a workaround. + function Has_Relative_Component (Path : String) return Boolean; + -- Returns whether Path contains relative components, i.e. './' or '../', + -- adjusted for the platform directory separator. + end Paths; diff --git a/tools/gnatcov/slocs.adb b/tools/gnatcov/slocs.adb index e80d0a0e0..cb3b8e006 100644 --- a/tools/gnatcov/slocs.adb +++ b/tools/gnatcov/slocs.adb @@ -18,6 +18,8 @@ -- Source locations +with Ada.Strings.Fixed; + with Files_Table; use Files_Table; with Strings; use Strings; @@ -172,6 +174,44 @@ package body Slocs is end if; end Image; + ----------- + -- Value -- + ----------- + + function Value (Str : String) return Local_Source_Location is + use Ada.Strings.Fixed; + Trimmed : constant String := Trim (Str, Ada.Strings.Both); + Col_Index : constant Natural := Index (Trimmed, ":"); + Res : Local_Source_Location; + begin + if Col_Index = 0 then + raise Constraint_Error with + "Missing ':' character in source location string"; + end if; + -- Parse the line number + + begin + Res.Line := Positive'Value (Trimmed (Trimmed'First .. Col_Index - 1)); + exception + when Constraint_Error => + raise Constraint_Error with + "Expected a positive integer for LINE, but got """ + & Trimmed (Trimmed'First .. Col_Index - 1) & """"; + end; + -- Parse the column number + + begin + Res.Column := + Positive'Value (Trimmed (Col_Index + 1 .. Trimmed'Last)); + exception + when Constraint_Error => + raise Constraint_Error with + "Expected a positive integer for COL, but got """ + & Trimmed (Col_Index + 1 .. Trimmed'Last) & """"; + end; + return Res; + end Value; + -------------- -- In_Range -- -------------- diff --git a/tools/gnatcov/slocs.ads b/tools/gnatcov/slocs.ads index 57d004c7a..b787dd8cc 100644 --- a/tools/gnatcov/slocs.ads +++ b/tools/gnatcov/slocs.ads @@ -38,6 +38,9 @@ package Slocs is function "<=" (L, R : Local_Source_Location) return Boolean; function Image (Sloc : Local_Source_Location) return String; + function Value (Str : String) return Local_Source_Location; + -- Attempt to interpret Str as a LINE:COL local source location string. + -- Raise Constraint_Error if not possible. No_Local_Location : constant Local_Source_Location := (0, 0); diff --git a/tools/gnatcov/ss_annotations.adb b/tools/gnatcov/ss_annotations.adb index 617a7fb53..402ac07be 100644 --- a/tools/gnatcov/ss_annotations.adb +++ b/tools/gnatcov/ss_annotations.adb @@ -17,18 +17,31 @@ ------------------------------------------------------------------------------ with Ada.Directories; +with Ada.Exceptions; +with Ada.Strings; +with Ada.Strings.Hash; +with Ada.Text_IO; -with GNATCOLL.VFS; use GNATCOLL.VFS; +with Interfaces; use Interfaces; + +with GNATCOLL.Projects; +with GNATCOLL.VFS; use GNATCOLL.VFS; with TOML; with Stable_Sloc; use Stable_Sloc; with Stable_Sloc.TOML_Utils; use Stable_Sloc.TOML_Utils; +with Coverage_Options; use Coverage_Options; +with Command_Line; use Command_Line; with Files_Table; use Files_Table; +with Hex_Images; use Hex_Images; with Instrument; use Instrument; with Instrument.Common; use Instrument.Common; with Outputs; use Outputs; +with Paths; use Paths; +with Project; use Project; +with Switches; use Switches; package body SS_Annotations is use type Unbounded_String; @@ -66,17 +79,37 @@ package body SS_Annotations is Cov_On_Purpose : constant Ada_Qualified_Name := Coverage_Namespace & To_Qualified_Name ("on"); + Valid_Annotation_DB : Stable_Sloc.Entry_DB; + -- Copy of the Ext_Annotation_DB, but filtering out the entries with + -- invalid annotations. This DB should be used when matching to avoid + -- searching for annotations which we won't be able to import anyways. + -- + -- We still need to keep the Ext_Annotation_DB at hand in case we are + -- writing back the annotations to file, in order not to delete the user's + -- data. + function Annotation_Kind - (Match : Match_Result) return Any_Annotation_Kind; + (Annot : TOML.TOML_Value) return Any_Annotation_Kind; -- Convert the purpose string in Match.Annotation into one of the -- recognized annotation kinds, based on the purpose strings defined above. -- -- Return Unknown if there is no "purpose" field in the annotation, or if -- it is empty or unknown. + function Annotation_Kind + (Str : String) return Any_Annotation_Kind; + -- Try to interpret Str as an annotation kind, return Unknown if Str does + -- not match with any valid annotation kind. + + function Purpose + (Kind : Any_Annotation_Kind) return Ada_Qualified_Name; + -- Return the qualified name to be used as purpose for the given annotation + -- kind. + procedure Report_Failed (Match : Match_Result) with Pre => not Match.Success; - -- Report the diagnostics for Match + -- Report the diagnostics for Match. Consider all failed matches as stale + -- annotations that need to be re-generated. function "+" (Sloc : TOML.Source_Location) return Slocs.Local_Source_Location is @@ -85,7 +118,7 @@ package body SS_Annotations is generic type Expected_Annot_Kind is (<>); with function Kind - (Match_Res : Match_Result) return Expected_Annot_Kind'Base; + (Match_Res : TOML.TOML_Value) return Expected_Annot_Kind'Base; with function Convert (Kind : Expected_Annot_Kind; Match_Res : Match_Result; @@ -115,16 +148,32 @@ package body SS_Annotations is -- Print a warning and set Success to False if there are errors -- interpreting the TOML annotation. + function Get_Or_Error + (Str : String; Sw : String) return Slocs.Local_Source_Location; + -- Parse a local source location from Str, or exit with a fatal error if + -- parsing fails. Sw represents the switch name for which Str represents + -- the value. + -- + -- An empty Str value is interpreted as a missing switch value. + + function Guess_Lang (File : Virtual_File) return Any_Language; + -- Try to guess the language of file based on its extension. + + procedure Validate_Annotation + (Identifier : Unbounded_String; Entr : Entry_View); + -- Helper for the above procedure, validate a single entry, if it is ok + -- then copy it in Valid_Annotation_DB, otherwise emit a warning. + --------------------- -- Annotation_Kind -- --------------------- function Annotation_Kind - (Match : Match_Result) return Any_Annotation_Kind + (Annot : TOML.TOML_Value) return Any_Annotation_Kind is Purpose : constant Ada_Qualified_Name := To_Qualified_Name - (+Get_Or_Null (Match.Annotation, "purpose")); + (+Get_Or_Null (Annot, "purpose")); begin if Purpose.Is_Empty @@ -172,6 +221,44 @@ package body SS_Annotations is return Unknown; end Annotation_Kind; + function Annotation_Kind + (Str : String) return Any_Annotation_Kind + is + begin + return Any_Annotation_Kind'Value (Str); + exception + when Constraint_Error => + return Unknown; + end Annotation_Kind; + + ------------- + -- Purpose -- + ------------- + + function Purpose + (Kind : Any_Annotation_Kind) return Ada_Qualified_Name + is + begin + case Kind is + when Exempt_Region => + return Exempt_Region_Purpose; + when Exempt_On => + return Exempt_On_Purpose; + when Exempt_Off => + return Exempt_Off_Purpose; + when Dump_Buffers => + return Buffers_Dump_Purpose; + when Reset_Buffers => + return Buffers_Reset_Purpose; + when Cov_Off => + return Cov_Off_Purpose; + when Cov_On => + return Cov_On_Purpose; + when Unknown => + return Ada_Identifier_Vectors.Empty_Vector; + end case; + end Purpose; + ------------------- -- Report_Failed -- ------------------- @@ -179,10 +266,30 @@ package body SS_Annotations is procedure Report_Failed (Match : Match_Result) is begin Warn - (Match.File.Display_Full_Name & ": " & (+Match.Identifier) & ": " - & (+Match.Diagnostic)); + ("Stale annotation for " & Match.File.Display_Base_Name & ". id:" + & (+Match.Identifier) & "; reason: " & (+Match.Diagnostic)); end Report_Failed; + ------------------ + -- Get_Or_Error -- + ------------------ + + function Get_Or_Error + (Str : String; Sw : String) return Slocs.Local_Source_Location + is + begin + if Str'Length = 0 then + Fatal_Error ("Missing " & Sw & " on the command line"); + end if; + + return Slocs.Value (Str); + exception + when Exc : Constraint_Error => + Fatal_Error + ("Wrong value for " & Sw & ": " + & Ada.Exceptions.Exception_Message (Exc)); + end Get_Or_Error; + -------------------------- -- Load_Ext_Annotations -- -------------------------- @@ -203,7 +310,8 @@ package body SS_Annotations is -- Import_External_Exemptions -- -------------------------------- - procedure Import_External_Exemptions (FI : Source_File_Index) + procedure Import_External_Exemptions + (FI : Source_File_Index; Filter : Boolean := False) is File : Virtual_File; Matches : Match_Result_Vec; @@ -211,9 +319,10 @@ package body SS_Annotations is Kind : Any_Annotation_Kind; New_Annotations : ALI_Annotation_Maps.Map; begin - -- Exit early if there are no external annotations + -- Exit early if there are no external annotations. + -- Validate them if needed. - if Is_Empty (Ext_Annotation_DB) then + if Is_Empty (Valid_Annotation_DB) then return; end if; @@ -222,25 +331,15 @@ package body SS_Annotations is File := Create (+Get_Full_Name (FI, Or_Simple => True)); Matches := Match_Entries ((1 => File), - Ext_Annotation_DB, + Valid_Annotation_DB, Purpose_Prefix => To_Ada (Exemption_Namespace)); -- Process each match result for Match of Matches loop - Kind := Annotation_Kind (Match); + Kind := Annotation_Kind (Match.Annotation); - -- Filter unknown annotations first - - if Kind not in Exempt_Region .. Exempt_Off then - Warn - ("Unexpected or unknown annotation kind for annotation """ - & (+Match.Identifier) & """: " - & (+Get_Or_Null (Match.Annotation, "purpose"))); - - -- Then failed matches - - elsif not Match.Success then + if not Match.Success then Report_Failed (Match); else -- Exempt_Region will insert an Exempt_On / Exempt_Off couple of @@ -292,7 +391,23 @@ package body SS_Annotations is & (+Match.Identifier) & """"); end if; else - New_Annotations.Insert (Sloc, Annot); + if Filter then + declare + SCO : constant SCO_Id := + Sloc_Intersects_SCO (Sloc); + begin + if SCO /= No_SCO_Id then + Warn ("Exemption annotation at " + & Slocs.Image (Sloc) + & " intersects a coverage obligation (" + & Image (SCO, True) & "), ignoring it"); + else + New_Annotations.Insert (Sloc, Annot); + end if; + end; + else + New_Annotations.Insert (Sloc, Annot); + end if; end if; end; end if; @@ -355,13 +470,13 @@ package body SS_Annotations is begin -- Exit early if there are no external annotations - if Is_Empty (Ext_Annotation_DB) then + if Is_Empty (Valid_Annotation_DB) then return Instr_Annotation_Maps.Empty_Map; end if; Matches := Match_Entries ((1 => VF), - Ext_Annotation_DB, + Valid_Annotation_DB, Purpose_Prefix); -- Process each annotation result @@ -372,7 +487,7 @@ package body SS_Annotations is goto Continue; end if; - Annot_Kind := Kind (Match); + Annot_Kind := Kind (Match.Annotation); if Annot_Kind not in Expected_Annot_Kind then Warn ("Unexpected or unknown annotation kind for annotation """ @@ -624,4 +739,605 @@ package body SS_Annotations is return Res; end Get_Disabled_Cov_Annotations; + -------------------- + -- Add_Annotation -- + -------------------- + + procedure Add_Annotation (Args : Command_Line.Parser.Parsed_Arguments) is + use TOML; + + Annot_Kind : Any_Annotation_Kind; + Start_Sloc : Slocs.Local_Source_Location; + End_Sloc : Slocs.Local_Source_Location; + Target_File : Virtual_File; + Output_File : Virtual_File; + Language : Any_Language := All_Languages; + Justification : Unbounded_String; + + function "+" (Opt : Command_Line.String_Options) return Unbounded_String + is (Parser.Value_Or_Null (Args.String_Args (Opt))); + + New_Annot_DB : Entry_DB; + Entry_Purpose : Ada_Qualified_Name; + Entry_Id : Unbounded_String := +Opt_Annotation_Id; + Annotation : constant TOML_Value := Create_Table; + SS_Backend : Unbounded_String := +Opt_SS_Backend; + File_Prefix : Unbounded_String := +Opt_Source_Root; + Info : GNATCOLL.Projects.File_Info; + + begin + -- First, determine the kind of annotation we'll be generating + + Annot_Kind := Annotation_Kind (US.To_String (+Opt_Annotation_Kind)); + + -- We always need a valid filename to generate an annotation. More than + -- one is ambiguous however, so only consider the last one as an input. + + if Annot_Kind = Unknown then + Fatal_Error + ("Invalid annotation kind (--kind): " & (+(+Opt_Annotation_Kind)) + & ASCII.LF & "Must be one of " + & Coverage_Options.Annotation_Kind_Options); + end if; + + if Args.Remaining_Args.Is_Empty then + Fatal_Error + ("Missing FILE to which the annotation should apply on the command" + & " line"); + end if; + + Target_File := Create (+(+Args.Remaining_Args.Last_Element)); + + if Is_Project_Loaded then + Info := Project.Project.Info (Target_File); + end if; + + if not Target_File.Is_Regular_File then + Fatal_Error (Target_File.Display_Full_Name & ": no such file"); + end if; + + -- Require the -o/--output switch to be present + + if not Args.String_Args (Opt_Output).Present then + Fatal_Error ("Missing --output switch"); + else + Output_File := Create (+US.To_String ((+Opt_Output))); + end if; + + -- Validate the arguments depending on the requested annotation kind + + case Annot_Kind is + when Exempt_Region => + Start_Sloc := + Get_Or_Error (+(+Opt_Start_Location), "--start-location"); + End_Sloc := Get_Or_Error (+(+Opt_End_Location), "--end-location"); + + if not Args.String_Args (Opt_Justification).Present then + Warn + ("--justification missing for an --kind=" + & Kind_Image (Annot_Kind) & " annotation"); + end if; + Justification := + Parser.Value_Or_Null (Args.String_Args (Opt_Justification)); + + when Exempt_On | Cov_Off => + + -- Accept either the --location or --start-location switches + + if Args.String_Args (Opt_Location).Present then + Start_Sloc := Get_Or_Error (+(+Opt_Location), "--location"); + else + Start_Sloc := + Get_Or_Error (+(+Opt_Start_Location), "--start-location"); + end if; + + if not Args.String_Args (Opt_Justification).Present then + Warn + ("--justification missing for a --kind=" + & Kind_Image (Annot_Kind) & " annotation"); + end if; + Justification := + Parser.Value_Or_Null (Args.String_Args (Opt_Justification)); + End_Sloc := Start_Sloc; + + when Exempt_Off .. Cov_On => + + -- Accept either the --location or --start-location switches + + if Args.String_Args (Opt_Location).Present then + Start_Sloc := Get_Or_Error (+(+Opt_Location), "--location"); + else + Start_Sloc := + Get_Or_Error (+(+Opt_Start_Location), "--start-location"); + end if; + End_Sloc := Start_Sloc; + + when Unknown => + raise Program_Error with "Unreachable"; + end case; + + -- Generate the annotation in isolation and report if there are any + -- issues. + -- + -- First, generate an entry identifier if not specified, from the + -- annotation kind and original source location range. + + if US.Length (Entry_Id) = 0 then + Entry_Id := +Kind_Image (Annot_Kind); + Entry_Id := Entry_Id & "-" & Hex_Image + (Unsigned_32 (Ada.Strings.Hash (Target_File.Display_Full_Name + & Slocs.Image (Start_Sloc) + & Slocs.Image (End_Sloc)))); + end if; + + Entry_Purpose := Purpose (Annot_Kind); + Annotation.Set ("purpose", Create_String (To_Ada (Entry_Purpose))); + + -- Add annotation kind specific fields + + case Annot_Kind is + when Exempt_On | Exempt_Region | Cov_Off => + Annotation.Set ("justification", Create_String (Justification)); + + when Dump_Buffers | Reset_Buffers => + Annotation.Set + ("insert_after", + Create_Boolean (Args.Bool_Args (Opt_Annotate_After))); + + if Annot_Kind = Dump_Buffers + and then Args.String_Args (Opt_Dump_Filename_Prefix).Present + then + Annotation.Set + ("trace_prefix", + Create_String + (Args.String_Args (Opt_Dump_Filename_Prefix).Value)); + end if; + + when Exempt_Off | Cov_On => null; + + when Unknown => + raise Program_Error with "Unreachable"; + end case; + + -- Determine the backend to be used depending on the language, if not + -- specified on the command line. + + if US.Length (SS_Backend) = 0 then + + -- If we have a project loaded, use it to determine the file language + + if Is_Project_Loaded then + Language := To_Language_Or_All (Info.Language); + end if; + + -- If this failed or we have no project at hand, revert to simple + -- heuristics. + + if Language = All_Languages then + Language := Guess_Lang (Target_File); + end if; + + case Language is + when Ada_Language => SS_Backend := +"lal_context"; + + -- Stable_Sloc is missing a stable backend for C/C++, so default + -- to an absolute entry. + + when All_Languages | C_Language | CPP_Language => + SS_Backend := +"absolute"; + end case; + end if; + + -- Compute a File prefix if there isn't one already specified, and we + -- have a project at hand. + + if US.Length (File_Prefix) = 0 and then Is_Project_Loaded then + case To_Language_Or_All (Info.Language) is + when Ada_Language => + + -- Ada source files are guaranteed to be unique in a project, + -- so use the directory name as file prefix to end-up with only + -- the base name. + + File_Prefix := US.To_Unbounded_String (+Target_File.Dir_Name); + + when others => + -- For other sources, check if the source is unique in the + -- tree, if so, do the same thing. + + declare + Ambiguous : Boolean; + File_From_Prj : Virtual_File; + Rel_Path : constant String := + +Create + (Relative_Path + (Target_File, Info.Project.Project_Path.Dir)) + .Dir_Name; + begin + Project.Project.Create + (Name => Target_File.Base_Name, + Project => GNATCOLL.Projects.No_Project, + Ambiguous => Ambiguous, + File => File_From_Prj); + + -- If the basename is ambiguous, use the relative path from + -- the project to the file, if it has no relative path + -- components (./ or ..). + + if Ambiguous then + if Has_Relative_Component (Rel_Path) then + Warn + ("Could not generate adequate file prefix from" + & " project, use --source-root if necessary."); + else + File_Prefix := US.To_Unbounded_String (Rel_Path); + end if; + else + File_Prefix := + US.To_Unbounded_String (+Target_File.Dir_Name); + end if; + end; + end case; + end if; + + declare + Diags : constant Load_Diagnostic_Arr := + Add_Or_Update_Entry + (DB => New_Annot_DB, + Identifier => Entry_Id, + Annotation => Annotation, + Kind => SS_Backend, + File => Target_File, + Span => (+Start_Sloc, +End_Sloc), + File_Prefix => File_Prefix); + begin + if Diags'Length /= 0 then + Outputs.Error ("Error while generating annotation:"); + for Diag of Diags loop + Outputs.Error (Format_Diagnostic (Diag)); + end loop; + raise Xcov_Exit_Exc; + end if; + end; + + -- Check if there already is an entry with the same identifier in the + -- loaded entries. If so, either error out if we cannot overwrite it. + + declare + Entr : constant Entry_View := + Query_Entry (Ext_Annotation_DB, Entry_Id); + begin + if Entr /= No_Entry_View and then not Args.Bool_Args (Opt_Force) then + Outputs.Fatal_Error + ("Annotation with identifier " & (+Entry_Id) + & "already exists. Use -f to overwrite it"); + end if; + end; + + -- Now check whether there is an entry matching the same region, for the + -- same purpose. If so, warn about it so the user doesn't get a surprise + -- at coverage time. + + declare + Matches : constant Match_Result_Vec := + Match_Entries + ((1 => Target_File), Valid_Annotation_DB, To_Ada (Entry_Purpose)); + begin + for Match of Matches loop + if Match.Success + and then Match.Location = (+Start_Sloc, +End_Sloc) + then + Outputs.Warn + ("Pre-existing annotation with identifier " + & (+Match.Identifier) & "matches the same region."); + end if; + end loop; + end; + + -- Finally, import the new entry and write everything to disk + + Replace_Entry (Ext_Annotation_DB, New_Annot_DB, Entry_Id, Entry_Id); + Write_Entries (Ext_Annotation_DB, Output_File); + end Add_Annotation; + + procedure Delete_Annotation (Args : Command_Line.Parser.Parsed_Arguments) is + Output_File : Virtual_File; + Identifier : Unbounded_String; + begin + -- Require an external annotation file. They have already been loaded + -- if present, but we still need to check. + + if Args.String_List_Args (Opt_Ext_Annotations).Is_Empty then + Fatal_Error ("missing --external-annotations switch"); + end if; + + -- Require a file in which to store the amended entries + + if not Args.String_Args (Opt_Output).Present then + Fatal_Error ("missing --output switch"); + else + Output_File := + Create (+US.To_String (Args.String_Args (Opt_Output).Value)); + end if; + + -- Require an entry identifier + + if not Args.String_Args (Opt_Annotation_Id).Present then + Fatal_Error ("Missing --annotation-id switch"); + else + Identifier := Args.String_Args (Opt_Annotation_Id).Value; + end if; + + -- Check wether there actually is an entry associated with Identifier + + if not Switches.Force then + declare + Entr : constant Entry_View := + Query_Entry (Ext_Annotation_DB, Identifier); + begin + if Entr = No_Entry_View then + Fatal_Error + ("No annotation associated with identifier """ + & (+Identifier) & """"); + end if; + end; + end if; + + -- Delete the entry and write the remaining entries back to file + + Delete_Entry (Ext_Annotation_DB, Identifier); + Write_Entries (Ext_Annotation_DB, Output_File); + end Delete_Annotation; + + procedure Show_Annotations (Args : Command_Line.Parser.Parsed_Arguments) is + Purpose_Filter : Unbounded_String; + Match_Results : Match_Result_Vec; + begin + -- Require an external annotation file. They have already been loaded + -- if present, but we still need to check. + + if Args.String_List_Args (Opt_Ext_Annotations).Is_Empty then + Fatal_Error ("missing --external-annotations switch"); + end if; + + -- Require either a project or some files on the command line + + if not Project.Is_Project_Loaded and then Args.Remaining_Args.Is_Empty + then + Fatal_Error ("Missing -P switch or positional FILES"); + end if; + + -- Check the annotation purpose if specified + + if Args.String_Args (Opt_Annotation_Kind).Present then + declare + Annot_Kind_Str : constant String := + +Args.String_Args (Opt_Annotation_Kind).Value; + Annot_Kind : constant Any_Annotation_Kind := + Annotation_Kind (Annot_Kind_Str); + begin + if Annot_Kind in Unknown then + Fatal_Error + ("Unknown annotation kind (--kind): """ & Annot_Kind_Str + & """, must be one of " + & Coverage_Options.Annotation_Kind_Options); + else + Purpose_Filter := +To_Ada (Purpose (Annot_Kind)); + end if; + end; + else + Purpose_Filter := +To_Ada (Xcov_Namespace); + end if; + + -- Build the file list. Use all the project source files if no files + -- have been explicitly requested on the command line + + if Args.Remaining_Args.Is_Empty then + declare + Files : File_Array_Access := + Project.Project.Root_Project.Source_Files + (Recursive => True, + Include_Externally_Built => + Project.Externally_Built_Projects_Processing_Enabled); + begin + Match_Results := Match_Entries + (Files.all, Ext_Annotation_DB, +Purpose_Filter); + GNATCOLL.VFS.Unchecked_Free (Files); + end; + else + declare + Files : File_Array (1 .. Positive (Args.Remaining_Args.Length)); + begin + for I in 1 .. Files'Last loop + Files (I) := + Create (+(US.To_String (Args.Remaining_Args.Element (I)))); + end loop; + Match_Results := + Match_Entries (Files, Valid_Annotation_DB, +Purpose_Filter); + end; + end if; + + -- Post-process the match results and display the annotations + + Sort (Match_Results); + declare + Current_File : Virtual_File; + begin + for Match of Match_Results loop + if Match.File /= Current_File then + Current_File := Match.File; + if Current_File /= No_File then + Ada.Text_IO.New_Line; + end if; + Ada.Text_IO.Put_Line (Current_File.Display_Base_Name & ":"); + end if; + declare + Annot_Kind : constant Any_Annotation_Kind := + Annotation_Kind (Match.Annotation); + begin + if Match.Success then + Ada.Text_IO.Put ("- " & Image (Match.Location) & "; "); + else + Ada.Text_IO.Put ("- STALE ANNOTATION; "); + end if; + + Ada.Text_IO.Put + ("id: " & (+Match.Identifier) & "; kind: " + & Kind_Image (Annot_Kind)); + + case Annot_Kind is + when Exempt_On | Exempt_Region | Cov_Off => + Ada.Text_IO.Put + ("; Justification: " + & (+Get_Or_Null (Match.Annotation, "justification"))); + + when Dump_Buffers | Reset_Buffers => + Ada.Text_IO.Put + ("; annotate after statement: " + & Boolean'Image + (Get_Or_Default + (Match.Annotation, "insert_after", False))); + if Annot_Kind = Dump_Buffers + and then Match.Annotation.Has ("trace_prefix") + then + Ada.Text_IO.Put + ("; trace filename prefix: " + & (+Get_Or_Null + (Match.Annotation, "trace_prefix"))); + end if; + + when Unknown | Exempt_Off | Cov_On => + null; + end case; + if not Match.Success then + Ada.Text_IO.Put ("; diagnostic: " & (+Match.Diagnostic)); + end if; + end; + Ada.Text_IO.New_Line; + end loop; + end; + + end Show_Annotations; + + ---------------- + -- Guess_Lang -- + ---------------- + + function Guess_Lang (File : Virtual_File) return Any_Language is + Ext : constant String := +File.File_Extension; + begin + if Ext = ".h" or else Ext = ".c" then + return C_Language; + elsif Ext = ".hh" + or else Ext = ".cc" + or else Ext = ".hpp" + or else Ext = ".cpp" + then + return CPP_Language; + elsif Ext = ".adb" + or else Ext = ".ads" + or else File.Has_Suffix (".1.ada") + or else File.Has_Suffix (".2.ada") + then + return Ada_Language; + else + return All_Languages; + end if; + end Guess_Lang; + + -------------------------- + -- Validate_Annotations -- + -------------------------- + + procedure Validate_Annotations is + begin + Clear_DB (Valid_Annotation_DB); + Iterate_Entries (Ext_Annotation_DB, Validate_Annotation'Access); + end Validate_Annotations; + + procedure Validate_Annotation + (Identifier : Unbounded_String; Entr : Entry_View) + is + All_Ok : Boolean := True; + -- Wether all relevant annotations are valid. We reject the entry as + -- soon as one of the annotations is invalid. + + Some_Relevant : Boolean := False; + -- Wether some of the annotations are relevant to gnatcov (purpose + -- starts with xcov.) + + begin + if Entr.Annotations.Length = 0 then + Warn + ("Entry """ & (+Identifier) + & """ has no annotations, it will be ignored."); + return; + end if; + -- Check each annotation associated with the entry + + for I in 1 .. Entr.Annotations.Length loop + declare + use TOML; + Annot : constant TOML_Value := Entr.Annotations.Item (I); + Annot_Kind : constant Any_Annotation_Kind := + Annotation_Kind (Annot); + begin + case Annot_Kind is + when Unknown => + + -- Only warn about unknown annotations that start with + -- "xcov." + + if Has_Prefix (+Get_Or_Null (Annot, "purpose"), "xcov.") then + Warn + ("Entry """ & (+Identifier) + & """ has an unknown annotation kind, it will be" + & " ignored."); + All_Ok := False; + end if; + + when Exempt_On | Exempt_Region => + Some_Relevant := True; + if Get_Or_Null (Annot, "justification") + = Null_Unbounded_String + then + Warn + ("Missing or empty justification for external" + & " exemption annotation """ & (+Identifier) + & """, it will be ignored."); + All_Ok := False; + end if; + + when Dump_Buffers | Reset_Buffers => + Some_Relevant := True; + if Annot.Has ("insert_after") + and then Annot.Get ("insert_after").Kind /= TOML_Boolean + then + Warn + ("Wrong type for ""insert_after"" flag in entry """ + & (+Identifier) & """, it will be ignored."); + All_Ok := False; + end if; + if Annot_Kind in Dump_Buffers + and then Annot.Has ("trace_prefix") + and then Annot.Get ("trace_prefix").Kind /= TOML_String + then + Warn + ("Wrong type for ""trace_prefix"" in entry """ + & (+Identifier) & """, it will be ignored."); + All_Ok := False; + end if; + + when Exempt_Off | Cov_Off | Cov_On => + Some_Relevant := True; + + end case; + end; + end loop; + if All_Ok and then Some_Relevant then + Replace_Entry + (Valid_Annotation_DB, Ext_Annotation_DB, Identifier, Identifier); + end if; + end Validate_Annotation; + end SS_Annotations; diff --git a/tools/gnatcov/ss_annotations.ads b/tools/gnatcov/ss_annotations.ads index b2287543d..500e1ba36 100644 --- a/tools/gnatcov/ss_annotations.ads +++ b/tools/gnatcov/ss_annotations.ads @@ -20,6 +20,7 @@ with Stable_Sloc; +with Command_Line; with Instrument.Common; with Logging; with Slocs; @@ -42,6 +43,10 @@ package SS_Annotations is (Line => S.Line, Column => S.Column); + function "+" (S : Slocs.Local_Source_Location) return Stable_Sloc.Sloc is + (Line => S.Line, + Column => S.Column); + function "+" (S : Stable_Sloc.Sloc_Span) return Slocs.Local_Source_Location_Range is (First_Sloc => +S.Start_Sloc, @@ -61,10 +66,16 @@ package SS_Annotations is -- Load the annotations in Annotation_File into our internal annotation -- database. + procedure Validate_Annotations; + -- Iterate over the loaded entries, and validate the TOML annotations. + -- Warn about the invalid annotations. + procedure Import_External_Exemptions - (FI : Source_File_Index); + (FI : Source_File_Index; Filter : Boolean := False); -- Search for external exemptions in FI, from the annotations loaded in -- Ext_Annotation_DB. + -- + -- If Filter is True, reject annotations that lie within a statement SCO. function Get_Buffer_Annotations (Filename : String) return Instrument.Common.Instr_Annotation_Map; @@ -86,4 +97,13 @@ package SS_Annotations is -- Finally, the resulting annotations are guaranteed not to conflict with -- any pre-existing annotations for Filename. + procedure Add_Annotation (Args : Command_Line.Parser.Parsed_Arguments); + -- Generate the annotation corresponding to the given Args + + procedure Delete_Annotation (Args : Command_Line.Parser.Parsed_Arguments); + -- Delete the annotations corresponding to the given Args + + procedure Show_Annotations (Args : Command_Line.Parser.Parsed_Arguments); + -- List the entries and corresponding matches from the options in Args + end SS_Annotations; diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 5ff3612fa..bde47f86f 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -170,6 +170,11 @@ package Switches is Instrument_Block : Boolean := False; -- When True, instrument statement blocks instead of statements + Force : Boolean := False; + -- When True, overwrite annotations of the same kind and same location, or + -- of the same identifier if specified on the command line. Only relevant + -- for the annotate command. + type Separated_Source_Coverage_Type is (None, Routines, Instances); Separated_Source_Coverage : Separated_Source_Coverage_Type := None; From 681ab12557e3e0df2aadb14fdc1bbd7a891b0ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 27 Aug 2024 14:43:47 +0200 Subject: [PATCH 0945/1483] Add new tests for external annotation generation The new tests are copies of pre-existing tests concerning in-source annotations, that have been modified to neutralize the existing annotations. Instead, invocation of "gnatcov add-annotation" are used prior to the original test script to generate external equivalent annotations. The results are supposed to be identical. This has been split as a separate commit from the previous one to facilitate review. (cherry picked from commit 86fc4f0b5d48251ba84fa8bec0cf19135efd5ce2) --- testsuite/SUITE/tutils.py | 192 ++++++++++++++++++ .../gen/ada_ex/MixInUnits/src/exemptions.adb | 79 +++++++ .../gen/ada_ex/MixInUnits/src/exemptions.ads | 26 +++ .../MixInUnits/src/test_all_exempted.adb | 48 +++++ .../MixInUnits/src/test_all_non_exempted.adb | 54 +++++ .../ada_ex/MixInUnits/src/test_exempted.adb | 51 +++++ .../gen/ada_ex/MixInUnits/src/test_no.adb | 42 ++++ .../MixInUnits/src/test_non_exempted.adb | 53 +++++ .../gen/ada_ex/MixInUnits/tc.rst | 6 + .../gen/ada_ex/MixInUnits/test.py | 50 +++++ .../gen/ada_ex/StmtsInBody/src/stacks.adb | 51 +++++ .../gen/ada_ex/StmtsInBody/src/stacks.ads | 17 ++ .../gen/ada_ex/StmtsInBody/src/test_0.adb | 26 +++ .../gen/ada_ex/StmtsInBody/src/test_pop_u.adb | 27 +++ .../ada_ex/StmtsInBody/src/test_push_0.adb | 27 +++ .../ada_ex/StmtsInBody/src/test_push_o.adb | 30 +++ .../ada_ex/StmtsInBody/src/test_pushpop_0.adb | 34 ++++ .../ada_ex/StmtsInBody/src/test_pushpop_o.adb | 32 +++ .../StmtsInBody/src/test_pushpop_ou.adb | 37 ++++ .../ada_ex/StmtsInBody/src/test_pushpop_u.adb | 30 +++ .../gen/ada_ex/StmtsInBody/tc.rst | 5 + .../gen/ada_ex/StmtsInBody/test.py | 29 +++ .../gen/ada_ex/StmtsInElab/src/com.adb | 24 +++ .../gen/ada_ex/StmtsInElab/src/com.ads | 16 ++ .../gen/ada_ex/StmtsInElab/src/comi_init.ads | 6 + .../ada_ex/StmtsInElab/src/comi_noinit.ads | 6 + .../gen/ada_ex/StmtsInElab/src/gcom.adb | 21 ++ .../gen/ada_ex/StmtsInElab/src/gcom.ads | 6 + .../gen/ada_ex/StmtsInElab/src/test_com.adb | 15 ++ .../ada_ex/StmtsInElab/src/test_gcom_f.adb | 13 ++ .../ada_ex/StmtsInElab/src/test_gcom_t.adb | 12 ++ .../ada_ex/StmtsInElab/src/test_gcom_tf.adb | 13 ++ .../gen/ada_ex/StmtsInElab/tc.rst | 7 + .../gen/ada_ex/StmtsInElab/test.opt | 1 + .../gen/ada_ex/StmtsInElab/test.py | 29 +++ .../gen/ada_ex/StmtsInHandler/src/stacks.adb | 51 +++++ .../gen/ada_ex/StmtsInHandler/src/stacks.ads | 17 ++ .../gen/ada_ex/StmtsInHandler/src/test_0.adb | 25 +++ .../ada_ex/StmtsInHandler/src/test_pop_u.adb | 26 +++ .../ada_ex/StmtsInHandler/src/test_push_0.adb | 27 +++ .../ada_ex/StmtsInHandler/src/test_push_o.adb | 30 +++ .../StmtsInHandler/src/test_pushpop_0.adb | 35 ++++ .../StmtsInHandler/src/test_pushpop_o.adb | 33 +++ .../StmtsInHandler/src/test_pushpop_ou.adb | 39 ++++ .../StmtsInHandler/src/test_pushpop_u.adb | 31 +++ .../gen/ada_ex/StmtsInHandler/tc.rst | 5 + .../gen/ada_ex/StmtsInHandler/test.py | 18 ++ .../src/multiple_exemptions.adb | 69 +++++++ .../gen/ada_ex/StmtsInSubprog/src/mx.adb | 38 ++++ .../gen/ada_ex/StmtsInSubprog/src/mx.ads | 20 ++ .../gen/ada_ex/StmtsInSubprog/src/test_0.adb | 31 +++ .../StmtsInSubprog/src/test_exempt_0.adb | 26 +++ .../StmtsInSubprog/src/test_exempt_all.adb | 31 +++ .../StmtsInSubprog/src/test_exempt_xr12.adb | 30 +++ .../StmtsInSubprog/src/test_exempt_xr13.adb | 30 +++ .../StmtsInSubprog/src/test_exempt_xr23.adb | 31 +++ .../gen/ada_ex/StmtsInSubprog/tc.rst | 6 + .../gen/ada_ex/StmtsInSubprog/test.py | 36 ++++ .../gen/ada_ex/SubprogsInUnit/src/stacks.adb | 56 +++++ .../gen/ada_ex/SubprogsInUnit/src/stacks.ads | 17 ++ .../gen/ada_ex/SubprogsInUnit/src/test_0.adb | 28 +++ .../ada_ex/SubprogsInUnit/src/test_pop_u.adb | 26 +++ .../ada_ex/SubprogsInUnit/src/test_push_0.adb | 26 +++ .../ada_ex/SubprogsInUnit/src/test_push_o.adb | 28 +++ .../SubprogsInUnit/src/test_pushpop_0.adb | 31 +++ .../SubprogsInUnit/src/test_pushpop_o.adb | 28 +++ .../SubprogsInUnit/src/test_pushpop_ou.adb | 33 +++ .../SubprogsInUnit/src/test_pushpop_u.adb | 26 +++ .../gen/ada_ex/SubprogsInUnit/tc.rst | 6 + .../gen/ada_ex/SubprogsInUnit/test.py | 19 ++ .../gen/ada_ex/WholeBody/src/test_tipos_0.adb | 12 ++ .../ada_ex/WholeBody/src/test_tipos_all.adb | 10 + .../ada_ex/WholeBody/src/test_tipos_other.adb | 10 + .../ada_ex/WholeBody/src/test_tipos_pos.adb | 10 + .../gen/ada_ex/WholeBody/src/tipos.adb | 13 ++ .../gen/ada_ex/WholeBody/src/tipos.ads | 2 + .../gen/ada_ex/WholeBody/tc.rst | 5 + .../gen/ada_ex/WholeBody/test.py | 17 ++ .../ext_annotations/gen/ada_ex/extra.opt | 1 + .../gen/buf_dump/ada_only/src-lib1/lib1.adb | 9 + .../gen/buf_dump/ada_only/src-lib1/lib1.ads | 3 + .../gen/buf_dump/ada_only/src-lib2/lib2.adb | 9 + .../gen/buf_dump/ada_only/src-lib2/lib2.ads | 3 + .../gen/buf_dump/ada_only/src/main.adb | 30 +++ .../gen/buf_dump/ada_only/src/manual_dump.adb | 6 + .../gen/buf_dump/ada_only/src/manual_dump.ads | 3 + .../gen/buf_dump/ada_only/test.opt | 2 + .../gen/buf_dump/ada_only/test.py | 103 ++++++++++ .../gen/buf_dump/ada_subprj/src-lib1/lib1.adb | 12 ++ .../gen/buf_dump/ada_subprj/src-lib1/lib1.ads | 3 + .../ada_subprj/src-lib1/src-lib2/lib2.adb | 8 + .../ada_subprj/src-lib1/src-lib2/lib2.ads | 3 + .../gen/buf_dump/ada_subprj/src/main.adb | 18 ++ .../gen/buf_dump/ada_subprj/test.py | 98 +++++++++ .../gen/buf_dump/c_only/src-lib/foo.c | 9 + .../gen/buf_dump/c_only/src-lib/foo.h | 1 + .../gen/buf_dump/c_only/src/main.c | 27 +++ .../gen/buf_dump/c_only/test.py | 91 +++++++++ .../gen/buf_dump/cpp_only/src-lib/foo.cpp | 9 + .../gen/buf_dump/cpp_only/src-lib/foo.h | 1 + .../gen/buf_dump/cpp_only/src/main.cpp | 27 +++ .../gen/buf_dump/cpp_only/test.opt | 1 + .../gen/buf_dump/cpp_only/test.py | 93 +++++++++ .../ext_annotations/gen/buf_dump/extra.opt | 1 + .../gen/buf_dump/mixed_all/main_ada.adb | 7 + .../gen/buf_dump/mixed_all/main_c.c | 9 + .../gen/buf_dump/mixed_all/main_cpp.cpp | 9 + .../gen/buf_dump/mixed_all/test.opt | 3 + .../gen/buf_dump/mixed_all/test.py | 79 +++++++ .../gen/buffer_reset/.clang-format | 7 + .../gen/buffer_reset/main_ada.adb | 15 ++ .../ext_annotations/gen/buffer_reset/main_c.c | 17 ++ .../ext_annotations/gen/buffer_reset/pkg.adb | 8 + .../ext_annotations/gen/buffer_reset/pkg.ads | 5 + .../ext_annotations/gen/buffer_reset/pkh.c | 7 + .../ext_annotations/gen/buffer_reset/test.opt | 3 + .../ext_annotations/gen/buffer_reset/test.py | 174 ++++++++++++++++ .../ext_annotations/gen/c_ex/Invalid/main.c | 21 ++ .../ext_annotations/gen/c_ex/Invalid/test.py | 44 ++++ .../gen/c_ex/Nominal/src/pkg.c | 35 ++++ .../gen/c_ex/Nominal/src/pkg.h | 12 ++ .../gen/c_ex/Nominal/src/test_exemptions.c | 20 ++ .../ext_annotations/gen/c_ex/Nominal/test.py | 37 ++++ .../tests/ext_annotations/gen/c_ex/extra.opt | 1 + testsuite/tests/ext_annotations/gen/readme.md | 22 ++ .../selective_cov/Ada/annotations.toml | 0 .../selective_cov/Ada/src/test_main.adb | 0 .../{ => gen}/selective_cov/Ada/test.py | 0 .../selective_cov/C/src/cons_a_b.txt | 0 .../{ => gen}/selective_cov/C/src/pkg.h | 0 .../{ => gen}/selective_cov/C/src/test_a.c | 0 .../{ => gen}/selective_cov/C/src/test_b.c | 0 .../{ => gen}/selective_cov/C/test.py | 14 +- .../{ => gen}/selective_cov/extra.opt | 0 .../selective_cov/C/annotations.toml | 43 ---- 135 files changed, 3322 insertions(+), 44 deletions(-) create mode 100755 testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.adb create mode 100755 testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.ads create mode 100755 testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_exempted.adb create mode 100755 testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_non_exempted.adb create mode 100755 testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_exempted.adb create mode 100755 testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_no.adb create mode 100755 testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_non_exempted.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/tc.rst create mode 100755 testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/test.py create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.ads create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_0.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pop_u.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_0.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_o.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_0.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_o.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_ou.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_u.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/tc.rst create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/test.py create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.ads create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_init.ads create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_noinit.ads create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.ads create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_com.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_f.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_t.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_tf.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/tc.rst create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.opt create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.py create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.ads create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_0.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pop_u.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_0.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_o.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_0.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_o.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_ou.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_u.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/tc.rst create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/test.py create mode 100755 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/multiple_exemptions.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.ads create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_0.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_0.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_all.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr12.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr13.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr23.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/tc.rst create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/test.py create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.ads create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_0.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pop_u.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_0.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_o.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_0.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_o.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_ou.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_u.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/tc.rst create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/test.py create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_0.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_all.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_other.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_pos.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.adb create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.ads create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/tc.rst create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/test.py create mode 100644 testsuite/tests/ext_annotations/gen/ada_ex/extra.opt create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.adb create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.ads create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.adb create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.ads create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/main.adb create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.adb create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.ads create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.opt create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.py create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.adb create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.ads create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.adb create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.ads create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src/main.adb create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/test.py create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.c create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.h create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/c_only/src/main.c create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/c_only/test.py create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.cpp create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.h create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src/main.cpp create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.opt create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.py create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/extra.opt create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_ada.adb create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_c.c create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_cpp.cpp create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.opt create mode 100644 testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.py create mode 100644 testsuite/tests/ext_annotations/gen/buffer_reset/.clang-format create mode 100644 testsuite/tests/ext_annotations/gen/buffer_reset/main_ada.adb create mode 100644 testsuite/tests/ext_annotations/gen/buffer_reset/main_c.c create mode 100644 testsuite/tests/ext_annotations/gen/buffer_reset/pkg.adb create mode 100644 testsuite/tests/ext_annotations/gen/buffer_reset/pkg.ads create mode 100644 testsuite/tests/ext_annotations/gen/buffer_reset/pkh.c create mode 100644 testsuite/tests/ext_annotations/gen/buffer_reset/test.opt create mode 100644 testsuite/tests/ext_annotations/gen/buffer_reset/test.py create mode 100644 testsuite/tests/ext_annotations/gen/c_ex/Invalid/main.c create mode 100644 testsuite/tests/ext_annotations/gen/c_ex/Invalid/test.py create mode 100644 testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.c create mode 100644 testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.h create mode 100644 testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/test_exemptions.c create mode 100644 testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py create mode 100644 testsuite/tests/ext_annotations/gen/c_ex/extra.opt create mode 100644 testsuite/tests/ext_annotations/gen/readme.md rename testsuite/tests/ext_annotations/{ => gen}/selective_cov/Ada/annotations.toml (100%) rename testsuite/tests/ext_annotations/{ => gen}/selective_cov/Ada/src/test_main.adb (100%) rename testsuite/tests/ext_annotations/{ => gen}/selective_cov/Ada/test.py (100%) rename testsuite/tests/ext_annotations/{ => gen}/selective_cov/C/src/cons_a_b.txt (100%) rename testsuite/tests/ext_annotations/{ => gen}/selective_cov/C/src/pkg.h (100%) rename testsuite/tests/ext_annotations/{ => gen}/selective_cov/C/src/test_a.c (100%) rename testsuite/tests/ext_annotations/{ => gen}/selective_cov/C/src/test_b.c (100%) rename testsuite/tests/ext_annotations/{ => gen}/selective_cov/C/test.py (68%) rename testsuite/tests/ext_annotations/{ => gen}/selective_cov/extra.opt (100%) delete mode 100644 testsuite/tests/ext_annotations/selective_cov/C/annotations.toml diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index cf816df06..79ba7dbc4 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -8,6 +8,7 @@ # *************************************************************************** +from dataclasses import dataclass import glob import os import re @@ -42,6 +43,7 @@ text_to_file, to_list, unhandled_exception_in, + Wdir, ) @@ -1102,3 +1104,193 @@ def __init__(self, text, char="o", pre=1, post=1): self.lines = text.split("\n") for text in self.lines: self.register(text) + + +@dataclass +class Ext_Annotation: + """Base external annotation""" + + # File to which the annotation applies + source_file: str + + # Start location for the annotation + start_sloc: str + + # End location for the annotation, if relevant + end_sloc: str | None + + def __init__(self, start_sloc, source_file, end_sloc=None): + self.start_sloc = start_sloc + self.source_file = source_file + self.end_sloc = end_sloc + + # Use the local directory separator if we are dealing with a relative + # source file path. + if not os.path.isabs(self.source_file): + self.source_file = self.source_file.replace("/", os.path.sep) + self.source_file = self.source_file.replace("\\", os.path.sep) + + def cmd_line_args(self): + args = [self.source_file] + args.append(f"--kind={self.__class__.__name__}") + if self.end_sloc: + args.append(f"--start-location={self.start_sloc}") + args.append(f"--end-location={self.end_sloc}") + else: + args.append(f"--location={self.start_sloc}") + return args + + +@dataclass +class Exempt_On(Ext_Annotation): + """Represents an external Exempt_On annotation""" + + # Justification for the exempted region + justification: str | None = None + + def cmd_line_args(self): + return super().cmd_line_args() + ( + [f"--justification={self.justification}"] + if self.justification + else [] + ) + + +@dataclass +class Exempt_Region(Exempt_On): + """ + Represents an external Exempt_Region annotation + + Requires end_sloc to be specified + """ + + def __post_init__(self): + assert self.end_sloc + + +@dataclass +class Exempt_Off(Ext_Annotation): + """Represents an external Exempt_Off annotation""" + + pass + + +@dataclass +class Cov_Off(Exempt_On): + """Represents an external Cov_Off annotation""" + + pass + + +@dataclass +class Cov_On(Ext_Annotation): + """Represents an external Cov_On annotation""" + + pass + + +@dataclass +class Reset_Buffers(Ext_Annotation): + """Represents an external Reset_Buffer annotation""" + + # Whether the annotation should be inserted before or after the + # statement designated by start_sloc + insert_after: bool = False + + def cmd_line_args(self): + return super().cmd_line_args() + ( + ["--annotate-after"] if self.insert_after else [] + ) + + +@dataclass +class Dump_Buffers(Reset_Buffers): + """Represents an external Dump_Buffers annotation""" + + # Optionnal trace prefix to be used when dumping the coverage buffers + trace_prefix: str | None = None + + def cmd_line_args(self): + return super().cmd_line_args() + ( + [f"--dump-filename-prefix={self.trace_prefix}"] + if self.trace_prefix + else [] + ) + + +def xcov_annotate( + annotation: Ext_Annotation, + annot_out_file: str, + annot_in_files: list[str] | None = None, + extra_args: list[str] | None = None, + out=None, + env=None, + register_failure=True, + auto_config_args=True, + auto_target_args=True, +): + """ + Invoke "gnatcov annotate" with the correct arguments to generate + an external annotation. + + No validation is performed on the function arguments before being + transformed to a command line. + + :param Ext_Annotation) annotation: Annotation to be generated by gnatcov + :param str source_file: source file to be annotated + :param str annot_out_file: File to which the annotations should be written. + This will overwrite any pre-existing file. + :param list[str] | None annot_in_files : List of filenames containing + pre-existing annotations, to be loaded and to which the new annotation + will be added. Defaults to None. + :param list[str] | None extra_args: extra arguments passed on the command + line. Defaults to None. + """ + args = ["add-annotation"] + args.extend(annotation.cmd_line_args()) + args.append(f"--output={annot_out_file}") + if annot_in_files: + args.extend( + [f"--external-annotations={file}" for file in annot_in_files] + ) + if extra_args: + args.extend(extra_args) + + xcov( + args, + out=out, + env=env, + register_failure=register_failure, + auto_config_args=auto_config_args, + auto_target_args=auto_target_args, + ) + + +def generate_annotations(annotations, subdir=""): + """ + Setup a temporary working directory in which an annotation file + will be generated from annotations, using gnatcov add-annotation + invocations. + Returns the absolute path to the annotation file + + :param list[Ext_Annotation] annotations: List of annotation to be generated + through the gnatcov add-annotation command + """ + # Create a common temporary working dir in which the annotations will be + # generated. + tmp = Wdir(subdir if subdir else "tmp_annotations") + + # Create an empty annotation file, to simplify command line generation + annot_file = os.path.abspath("annotations.toml") + touch(annot_file) + + # Move to the home dir so that annotations are relative to the home + # directory of the test. + tmp.to_homedir() + + # Generate the annotations + for annotation in annotations: + xcov_annotate( + annotation, annot_in_files=[annot_file], annot_out_file=annot_file + ) + return annot_file diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.adb b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.adb new file mode 100755 index 000000000..9c6c26779 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.adb @@ -0,0 +1,79 @@ +package body Exemptions is + + procedure Swap (I, J : in out Integer) is + + -- Exemption for a local declaration + + pragma Annotate -- # xswap + (Xxxx, Exempt_On, "exemption on declarations"); -- # xswap + Tmp : Integer := J; -- # xswap_vio + pragma Annotate (Xxxx, Exempt_Off); -- # xswap + begin + J := I; -- # swap_stmt + I := Tmp; -- # swap_stmt + end Swap; + + function Factorial (X : Natural) return Positive is + begin + if X = 1 then -- # factorial + return 1; -- # 1_factorial + elsif X >= Positive'Last / 1000 then -- # elsif_factorial + + -- Exemption for a conditioned set of statements + + pragma Annotate -- # xfactorial + (Xxxx, Exempt_On, -- # xfactorial + "exemption on statements in function"); -- # xfactorial + return Positive'Last; -- # xfactorial_vio + pragma Annotate (Xxxx, Exempt_Off); -- # xfactorial + else + return X * Factorial (X - 1); -- # rec_factorial + end if; + end Factorial; + + -- No exemption in the couple of subprograms below + + procedure Another_Swap (I, J : in out Integer) is + Tmp : Integer := J; -- # another_swap + begin + J := I; -- # another_swap + I := Tmp; -- # another_swap + end Another_Swap; + + function Another_Factorial (X : Natural) return Positive is + Result : Positive := 1; -- # another_factorial + begin + for J in 1 .. X loop -- # another_factorial + if Result > Positive'Last / J then -- # in_loop_a_f + raise Constraint_Error; -- # in_if_a_f + end if; + + Result := Result * J; -- # in_loop_a_f + end loop; + + return Result; -- # another_factorial + exception + when Constraint_Error => + return Positive'Last; -- # handler_a_f + end Another_Factorial; + + +begin + + -- Mix of exempted and non-exempted statements in the package + -- elaboration sequence + + pragma Annotate -- # xelab_1 + (Xxxx, Exempt_On, -- # xelab_1 + "exemption on elaboration code - 1"); -- # xelab_1 + Z := Identity (3); -- # xelab_1_vio + pragma Annotate (Xxxx, Exempt_Off); -- # xelab_1 + + Another_Swap (X, Y); -- # elab + + pragma Annotate -- # xelab_2 + (Xxxx, Exempt_On, -- # xelab_2 + "exemption on elaboration code - 2"); -- # xelab_2_vio + Another_Swap (Z, X); -- # xelab_2 + pragma Annotate (Xxxx, Exempt_Off); -- # xelab_2 +end Exemptions; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.ads b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.ads new file mode 100755 index 000000000..300ed769a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/exemptions.ads @@ -0,0 +1,26 @@ +with Support; use Support; +package Exemptions is + + procedure Swap (I, J : in out Integer); + -- Body contains exemption section for a declaration + + function Factorial (X : Natural) return Positive; + -- Body contains exemption section for a statement + + procedure Another_Swap (I, J : in out Integer) ; + -- No exemption section in the body + + function Another_Factorial (X : Natural) return Positive; + -- No exemption section in the body + + -- Mix of exempted and non-exempted declarations + + X : Integer := Identity (1); -- # decl + + pragma Annotate -- # xdecl + (No_Such_Tool, No); -- # xdecl + Y : Integer := Identity (2); -- # xdecl_vio + pragma Annotate (No_Such_Tool, No); -- # xdecl + + Z : Integer := 1; +end Exemptions; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_exempted.adb b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_exempted.adb new file mode 100755 index 000000000..a6ecbe190 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_exempted.adb @@ -0,0 +1,48 @@ +-- Test driver for exemptions. It calls subprograms from the functional +-- code, and it executes all the code in all the exempted sections. + +with Exemptions; +with Support; use Support; + +procedure Test_All_Exempted is + I : Integer := 1; + J : Integer := 2; + K : Integer := 3; +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); + + Exemptions.Swap (I, J); + Assert (I = 2 and then J = 1); + + Assert (Exemptions.Factorial (Positive'Last) = Positive'Last); + -- Code in exemption section is executed + +end Test_All_Exempted; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l# ## x0 +-- /swap_stmt/ l+ ## 0 + +-- /factorial/ l+ ## 0 +-- /1_factorial/ l- ## s- +-- /xfactorial/ l# ## x0 +-- /elsif_factorial/ l+ ## 0 +-- /rec_factorial/ l- ## s- + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l- ## s- +-- /in_loop_a_f/ l- ## s- +-- /in_if_a_f/ l- ## s- +-- /handler_a_f/ l- ## s- + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_non_exempted.adb b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_non_exempted.adb new file mode 100755 index 000000000..ea83b13b3 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_all_non_exempted.adb @@ -0,0 +1,54 @@ +-- Test driver for exemptions. It calls subprograms from the functional +-- code, but these calls do not execute/elaborate exempted code. So the only +-- exempted construct that are expected to be reported as covered are those +-- that are executed/elaborated when the spec and body of the package +-- Exemptions are elaborated +-- +-- This driver executes all the non-exempted code. + +with Exemptions; +with Support; use Support; + +procedure Test_All_Non_Exempted is + I, J, K : Integer := 1; +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); + + Assert (Exemptions.Factorial (3) = 6); + -- No exempted code is executed + + Assert (Exemptions.Another_Factorial (3) = 6); + Assert (Exemptions.Another_Factorial (Positive'Last) = Positive'Last); + -- No exempted code in this function + +end Test_All_Non_Exempted; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l* ## x+ +-- /xswap_vio/ l= ## Xs- +-- /swap_stmt/ l- ## s- + +-- /factorial/ l+ ## 0 +-- /1_factorial/ l+ ## 0 +-- /xfactorial/ l* ## x+ +-- /xfactorial_vio/ l= ## Xs- +-- /elsif_factorial/ l+ ## 0 +-- /rec_factorial/ l+ ## 0 + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l+ ## 0 +-- /in_loop_a_f/ l+ ## 0 +-- /in_if_a_f/ l+ ## 0 +-- /handler_a_f/ l+ ## 0 + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_exempted.adb b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_exempted.adb new file mode 100755 index 000000000..424491b5a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_exempted.adb @@ -0,0 +1,51 @@ +-- Test driver for exemptions. It calls subprograms from the functional +-- code, and it executes a part of the code in a part of the exempted +-- sections. +-- +-- This driver executes not all but only a part of exempted code. + +with Exemptions; +with Support; use Support; + +procedure Test_Exempted is + I : Integer := 1; + J : Integer := 2; + K : Integer := 3; +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); + + Exemptions.Swap (I, J); + Assert (I = 2 and then J = 1); + + Assert (Exemptions.Factorial (Positive'Last) = Positive'Last); + -- Code in exemption section is executed + +end Test_Exempted; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l# ## x0 +-- /swap_stmt/ l+ ## 0 + +-- /factorial/ l+ ## 0 +-- /1_factorial/ l- ## s- +-- /xfactorial/ l# ## x0 +-- /elsif_factorial/ l+ ## 0 +-- /rec_factorial/ l- ## s- + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l- ## s- +-- /in_loop_a_f/ l- ## s- +-- /in_if_a_f/ l- ## s- +-- /handler_a_f/ l- ## s- + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_no.adb b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_no.adb new file mode 100755 index 000000000..06125fd6b --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_no.adb @@ -0,0 +1,42 @@ +-- Test driver for exemptions. It only "withes" the functional code, so the +-- only constructs that are expected to be reported as covered are those that +-- are executed/elaborated when the spec and body of the package Exemptions +-- are elaborated + +with Exemptions; +with Support; use Support; + +procedure Test_No is +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); +end Test_No; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l* ## x+ +-- /xswap_vio/ l= ## Xs- +-- /swap_stmt/ l- ## s- + +-- /factorial/ l- ## s- +-- /1_factorial/ l- ## s- +-- /xfactorial/ l* ## x+ +-- /xfactorial_vio/ l= ## Xs- +-- /elsif_factorial/ l- ## s- +-- /rec_factorial/ l- ## s- + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l- ## s- +-- /in_loop_a_f/ l- ## s- +-- /in_if_a_f/ l- ## s- +-- /handler_a_f/ l- ## s- + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_non_exempted.adb b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_non_exempted.adb new file mode 100755 index 000000000..0f7bc7b5e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/src/test_non_exempted.adb @@ -0,0 +1,53 @@ +-- Test driver for exemptions. It calls subprograms from the functional +-- code, but these calls do not execute/elaborate exempted code. So the only +-- exempted construct that are expected to be reported as covered are those +-- that are executed/elaborated when the spec and body of the package +-- Exemptions are elaborated +-- +-- This driver executes not all but only a part of non-exempted code. + +with Exemptions; +with Support; use Support; + +procedure Test_Non_Exempted is + I, J, K : Integer := 1; +begin + Assert (Exemptions.X = 3); + Assert (Exemptions.Y = 1); + Assert (Exemptions.Z = 2); + + Assert (Exemptions.Factorial (3) = 6); + -- No exempted code is executed + + Assert (Exemptions.Another_Factorial (3) = 6); + -- No exempted code in this function + +end Test_Non_Exempted; + +--# exemptions.ads +-- /decl/ l+ ## 0 +-- /xdecl/ l# ## x0 +-- /negI/ l+ ## 0 + +--# exemptions.adb +-- /xswap/ l* ## x+ +-- /xswap_vio/ l= ## Xs- +-- /swap_stmt/ l- ## s- + +-- /factorial/ l+ ## 0 +-- /1_factorial/ l+ ## 0 +-- /xfactorial/ l* ## x+ +-- /xfactorial_vio/ l= ## Xs- +-- /elsif_factorial/ l+ ## 0 +-- /rec_factorial/ l+ ## 0 + +-- /another_swap/ l+ ## 0 + +-- /another_factorial/ l+ ## 0 +-- /in_loop_a_f/ l+ ## 0 +-- /in_if_a_f/ l- ## s- +-- /handler_a_f/ l- ## s- + +-- /xelab_1/ l# ## x0 +-- /elab/ l+ ## 0 +-- /xelab_2/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/tc.rst new file mode 100644 index 000000000..5a1985437 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/tc.rst @@ -0,0 +1,6 @@ +**Exercise exemptions over a mix of statements and declarations in several units** + +Exercise a package that contains non-exempted code and several exemption +regions, for a combination of statements and declarations in subprogram bodies, +in the package specification, and in the package body. + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/test.py new file mode 100755 index 000000000..9ba9845bd --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/MixInUnits/test.py @@ -0,0 +1,50 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import ( + Exempt_On, + Exempt_Off, + Exempt_Region, + generate_annotations, +) + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = [ + Exempt_Region( + "src/exemptions.adb", "7:7", "10:42", "exemption on declarations" + ), + Exempt_Region( + "src/exemptions.adb", + "24:10", + "28:45", + "exemption on statements in function", + ), + Exempt_On( + "src/exemptions.adb", + "66:4", + None, + "exemption on elaboration code - 1", + ), + Exempt_Off("src/exemptions.adb", "70:39", None), + Exempt_Region( + "src/exemptions.adb", + "74:4", + "78:39", + "exemption on elaboration code - 2", + ), + Exempt_Region( + "src/exemptions.ads", + "20:4", + "23:39", + "exemption on global declaration", + ), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.adb new file mode 100644 index 000000000..9be392893 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.adb @@ -0,0 +1,51 @@ +package body Stacks is + + procedure On (S : in out Stack; Op : Op_Kind; V : in out Integer) is + begin + case Op is -- # op_case + when Push => + pragma Annotate -- # op_oflow + (Xxxx, Exempt_On, "no overflow"); -- # op_oflow + if S.Vcount = S.Size then -- # op_oflow_v1 + raise Constraint_Error; -- # op_oflow_v2 + end if; -- # op_oflow + pragma Annotate (Xxxx, Exempt_Off); -- # op_oflow + + S.Vcount := S.Vcount + 1; -- # op_push + S.Values (S.Vcount) := V; -- # op_push + + when Pop => + pragma Annotate -- # op_uflow + (Xxxx, Exempt_On, "no underflow"); -- # op_uflow + if S.Vcount = 0 then -- # op_uflow_v1 + raise Constraint_Error; -- # op_uflow_v2 + end if; -- # op_uflow + pragma Annotate (Xxxx, Exempt_Off); -- # op_uflow + + V := S.Values (S.Vcount); -- # op_pop + S.Vcount := S.Vcount - 1; -- # op_pop + end case; + exception + when Constraint_Error => + S.Ecount := S.Ecount + 1; -- # op_handler + end; + + procedure Push (S : in out Stack; Value : Integer) is + V : Integer := Value; -- # push_decl + begin + On (S, Op => Push, V => V); -- # push_body + end; + + procedure Pop (S : in out Stack; Value : out Integer) is + V : Integer := 0; -- # pop_decl + begin + On (S, Op => Pop, V => V); -- # pop_body + Value := V; -- # pop_body + end; + + function Errcount (S : in Stack) return Natural is + begin + return S.Ecount; -- # err_body + end; + +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.ads new file mode 100644 index 000000000..6f81d9042 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/stacks.ads @@ -0,0 +1,17 @@ +package Stacks is + + type Varray is array (Natural range <>) of Integer; + + type Stack (Size : Natural) is record + Vcount : Natural := 0; + Values : Varray (1 .. Size); + Ecount : Natural := 0; + end record; + + type Op_Kind is (Push, Pop); + + procedure Push (S : in out Stack; Value : Integer); + procedure Pop (S : in out Stack; Value : out Integer); + + function Errcount (S : in Stack) return Natural; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_0.adb new file mode 100644 index 000000000..9867b0aca --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_0.adb @@ -0,0 +1,26 @@ +with Stacks, Support; use Stacks, Support; + +-- Call nothing, no overflow, no underflow - Both exempted. + +procedure Test_0 is +begin + null; +end; + +--# stacks.adb +-- /op_case/ l- ## s- +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /op_oflow/ l* ## x+ +-- /op_oflow_v1/ l= ## Xs- +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l* ## x+ +-- /op_uflow_v1/ l= ## Xs- +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l- ## s- + +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l- ## s- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pop_u.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pop_u.adb new file mode 100644 index 000000000..c77127091 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pop_u.adb @@ -0,0 +1,27 @@ +with Stacks, Support; use Stacks, Support; + +-- Pop only, immediate underflow. Overflow uncovered/exempted only. +-- No pop operation performed. + +procedure Test_Pop_U is + S : Stack (Size => 2); + V : Integer; +begin + Pop (S, V); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /op_oflow/ l* ## x+ +-- /op_oflow_v1/ l= ## Xs- +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l# ## x0 +-- /op_handler/ l+ ## 0 + +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_0.adb new file mode 100644 index 000000000..353642beb --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_0.adb @@ -0,0 +1,27 @@ +with Stacks, Support; use Stacks, Support; + +-- Push only, no overflow. Underflow & overflow both uncovered/exempted. + +procedure Test_Push_0 is + S : Stack (Size => 5); + +begin + Push (S, 3); + Assert (Errcount (S) = 0); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /op_oflow/ l* ## x+ +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l* ## x+ +-- /op_uflow_v1/ l= ## Xs- +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l- ## s- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_o.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_o.adb new file mode 100644 index 000000000..8bb76caf7 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_push_o.adb @@ -0,0 +1,30 @@ +with Stacks, Support; use Stacks, Support; + +-- Push only, until overflow. Underflow uncovered/exempted only. + +procedure Test_Push_O is + S : Stack (Size => 2); + +begin + Push (S, 1); + Push (S, 3); + Assert (Errcount (S) = 0); + + Push (S, 4); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /op_oflow/ l# ## x0 +-- /op_uflow/ l* ## x+ +-- /op_uflow_v1/ l= ## Xs- +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l+ ## 0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_0.adb new file mode 100644 index 000000000..249586671 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_0.adb @@ -0,0 +1,34 @@ +with Stacks, Support; use Stacks, Support; + +-- Push and Pop, no overflow, no underflow - Both exempted. + +procedure Test_PushPop_0 is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + + Pop (S, V); + Assert (V = 2); + + Pop (S, V); + Assert (V = 1); + + Assert (Errcount (S) = 0); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l* ## x+ +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l* ## x+ +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l- ## s- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_o.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_o.adb new file mode 100644 index 000000000..373cceb08 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_o.adb @@ -0,0 +1,32 @@ +with Stacks, Support; use Stacks, Support; + +-- Push until overflow, then Pop. Underflow uncovered/exempted only. + +procedure Test_PushPop_O is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + Assert (Errcount (S) = 0); + + Push (S, 3); + Assert (Errcount (S) = 1); + + Pop (S, V); + Assert (V = 2); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l# ## x0 +-- /op_uflow/ l* ## x+ +-- /op_uflow_v2/ l= ## Xs- +-- /op_handler/ l+ ## 0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_ou.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_ou.adb new file mode 100644 index 000000000..5469640b3 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_ou.adb @@ -0,0 +1,37 @@ +with Stacks, Support; use Stacks, Support; + +-- Push until overflow, then Pop until underflow. Nothing exempted. + +procedure Test_PushPop_OU is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + Assert (Errcount (S) = 0); + + Push (S, 3); + Assert (Errcount (S) = 1); + + Pop (S, V); + Assert (V = 2); + + Pop (S, V); + Assert (V = 1); + + Pop (S, V); + Assert (Errcount (S) = 2); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l# ## x0 +-- /op_uflow/ l# ## x0 +-- /op_handler/ l+ ## 0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_u.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_u.adb new file mode 100644 index 000000000..9c50e1bab --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/src/test_pushpop_u.adb @@ -0,0 +1,30 @@ +with Stacks, Support; use Stacks, Support; + +-- Push, then Pop until underflow. Overflow uncovered/exempted only. + +procedure Test_PushPop_U is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Pop (S, V); + Assert (V = 1); + Assert (Errcount (S) = 0); + + Pop (S, V); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /op_oflow/ l* ## x+ +-- /op_oflow_v2/ l= ## Xs- +-- /op_uflow/ l# ## x0 +-- /op_handler/ l+ ## 0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/tc.rst new file mode 100644 index 000000000..1b6c991f6 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/tc.rst @@ -0,0 +1,5 @@ +**Exercise exemptions over groups of statements within a subprogram body** + +Exercise non-exempted code and several exemption regions within a +subprogram body, all protected by a local exception handler. + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/test.py new file mode 100644 index 000000000..af8a189ae --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInBody/test.py @@ -0,0 +1,29 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import ( + Exempt_On, + Exempt_Off, + Exempt_Region, + generate_annotations, +) + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = [ + Exempt_Region("src/stacks.adb", "7:13", "12:48", "no overflow"), + Exempt_On("src/stacks.adb", "18:13", None, "no underflow"), + Exempt_Off( + "src/stacks.adb", + "23:38", + None, + ), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.adb new file mode 100644 index 000000000..4ced376ed --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.adb @@ -0,0 +1,24 @@ + +package body Com is + + -- Non-exempted subprogram body + + procedure Initialize is + begin + Current_State := Idle; -- # init_body + Initialized := True; -- # init_body + end; + +begin + + if Auto_Initialize then + + -- Exempted sequence nested within a conditional, part of + -- a non-generic package body elaboration sequence + + pragma Annotate -- # init_call + (Xxxx, Exempt_On, "auto init off"); -- # init_call + Initialize; -- # init_call_violation + pragma Annotate (Xxxx, Exempt_Off); -- # init_call + end if; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.ads new file mode 100644 index 000000000..825492be4 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/com.ads @@ -0,0 +1,16 @@ +package Com is + pragma Elaborate_Body; + + type State is (RX, TX, Idle); + Current_State : State; + + Initialized : Boolean := False; + procedure Initialize; + + Auto_Initialize : Boolean := False; + -- Variable to prevent obvious constant folding and absence of + -- code in conditioned sequences, which we test for coverage + + -- The package elaboration body calls Initialize if Auto_Initialize + -- is True, which can never happen. +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_init.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_init.ads new file mode 100644 index 000000000..23125d760 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_init.ads @@ -0,0 +1,6 @@ +-- Instantiate Gcom with auto-init True. Identity prevents variations in +-- results from possible constant folding otherwise, irrelevant for the test +-- purposes. + +with Support, Gcom; use Support; +package Comi_Init is new Gcom (Auto_Init => Identity(True)); diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_noinit.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_noinit.ads new file mode 100644 index 000000000..6ec75025a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/comi_noinit.ads @@ -0,0 +1,6 @@ +-- Instantiate Gcom with auto-init False. Identity prevents variations in +-- results from possible constant folding otherwise, irrelevant for the test +-- purposes. + +with Support, Gcom; use Support; +package Comi_NoInit is new Gcom (Auto_Init => Identity(False)); diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.adb new file mode 100644 index 000000000..a396faae4 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.adb @@ -0,0 +1,21 @@ +package body Gcom is + + -- Non-exempted subprogram body + + procedure Initialize is + begin + Initialized := True; -- # init_body + end; + +begin + if Auto_Init then + + -- Exempted sequence nested within a conditional, part of + -- a generic package body elaboration sequence + + pragma Annotate -- # init_call + (Xxxx, Exempt_On, "auto init off"); -- # init_call + Initialize; -- # init_call_violation + pragma Annotate (Xxxx, Exempt_Off); -- # init_call + end if; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.ads new file mode 100644 index 000000000..1e068af1e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/gcom.ads @@ -0,0 +1,6 @@ +generic + Auto_Init : Boolean; +package Gcom is + Initialized : Boolean := False; + procedure Initialize; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_com.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_com.adb new file mode 100644 index 000000000..d1c453f5d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_com.adb @@ -0,0 +1,15 @@ +with Support, Com; use Support, Com; + +-- The functional package is withed - it's elaboration body is covered with +-- auto_init off, so the init body is not executed and the call to init gets +-- exempted. + +procedure Test_Com is +begin + Assert (Com.Initialized = False); +end; + +--# com.adb +-- /init_body/ l- ## s- +-- /init_call/ l* ## x+ +-- /init_call_violation/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_f.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_f.adb new file mode 100644 index 000000000..eaaed1e0a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_f.adb @@ -0,0 +1,13 @@ +with Support, Comi_Noinit; use Support; + +-- Reach gcom with auto-init False - call not covered => exempted. + +procedure Test_Gcom_F is +begin + Assert (Comi_Noinit.Initialized = False); +end; + +--# gcom.adb +-- /init_body/ l- ## s- +-- /init_call/ l* ## x+ +-- /init_call_violation/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_t.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_t.adb new file mode 100644 index 000000000..df4a78f3d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_t.adb @@ -0,0 +1,12 @@ +with Support, Comi_Init; use Support; + +-- Reach gcom with auto-init True - call covered => no exemption + +procedure Test_Gcom_T is +begin + Assert (Comi_Init.Initialized = True); +end; + +--# gcom.adb +-- /init_body/ l+ ## 0 +-- /init_call/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_tf.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_tf.adb new file mode 100644 index 000000000..69267c79f --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/src/test_gcom_tf.adb @@ -0,0 +1,13 @@ +with Support, Comi_Init, Comi_Noinit; use Support; + +-- Reach gcom with auto-init both False and True - call covered => exempted + +procedure Test_Gcom_TF is +begin + Assert (Comi_Init.Initialized = True); + Assert (Comi_Noinit.Initialized = False); +end; + +--# gcom.adb +-- /init_body/ l+ ## 0 +-- /init_call/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/tc.rst new file mode 100644 index 000000000..62165ecd6 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/tc.rst @@ -0,0 +1,7 @@ +**Exercise exemptions over groups of statements within a package body elaboration sequence** + +Exercise a regular package and a generic package instance +containing a non-exempted subprogram and an exemption region +for a conditional set of statements within the package body +elaboration sequence. + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.opt b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.opt new file mode 100644 index 000000000..00dc3ce12 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.opt @@ -0,0 +1 @@ +src-traces,gnatcov-22,DOA XFAIL test with liblevel decision, requires gnatcov >= 23 for instrumentation diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.py new file mode 100644 index 000000000..7de0c0f89 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInElab/test.py @@ -0,0 +1,29 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import ( + Exempt_On, + Exempt_Off, + Exempt_Region, + generate_annotations, +) + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = [ + Exempt_Region("src/com.adb", "19:7", "22:42", "auto init off"), + Exempt_On("src/gcom.adb", "16:7", None, "auto init off"), + Exempt_Off( + "src/gcom.adb", + "19:42", + None, + ), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.adb new file mode 100644 index 000000000..414b3ee20 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.adb @@ -0,0 +1,51 @@ +package body Stacks is + + procedure On (S : in out Stack; Op : Op_Kind; V : in out Integer) is + begin + case Op is -- # op_case + when Push => + if S.Vcount = S.Size then -- # test_oflow + raise Constraint_Error; -- # op_oflow + end if; + + S.Vcount := S.Vcount + 1; -- # op_push + S.Values (S.Vcount) := V; -- # op_push + + when Pop => + if S.Vcount = 0 then -- # test_uflow + raise Constraint_Error; -- # op_uflow + end if; + + V := S.Values (S.Vcount); -- # op_pop + S.Vcount := S.Vcount - 1; -- # op_pop + end case; + exception + when Constraint_Error => + + -- Exemption region in local handler here + + pragma Annotate -- # op_handler + (Xxxx, Exempt_On, "exception handler"); -- # op_handler + S.Ecount := S.Ecount + 1; -- # op_handler_stmt + pragma Annotate (Xxxx, Exempt_Off); -- # op_handler + end; + + procedure Push (S : in out Stack; Value : Integer) is + V : Integer := Value; -- # push_decl + begin + On (S, Op => Push, V => V); -- # push_body + end; + + procedure Pop (S : in out Stack; Value : out Integer) is + V : Integer := 0; -- # pop_decl + begin + On (S, Op => Pop, V => V); -- # pop_body + Value := V; -- # pop_body + end; + + function Errcount (S : in Stack) return Natural is + begin + return S.Ecount; -- # err_body + end; + +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.ads new file mode 100644 index 000000000..6f81d9042 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/stacks.ads @@ -0,0 +1,17 @@ +package Stacks is + + type Varray is array (Natural range <>) of Integer; + + type Stack (Size : Natural) is record + Vcount : Natural := 0; + Values : Varray (1 .. Size); + Ecount : Natural := 0; + end record; + + type Op_Kind is (Push, Pop); + + procedure Push (S : in out Stack; Value : Integer); + procedure Pop (S : in out Stack; Value : out Integer); + + function Errcount (S : in Stack) return Natural; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_0.adb new file mode 100644 index 000000000..50faca385 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_0.adb @@ -0,0 +1,25 @@ +with Stacks, Support; use Stacks, Support; + +-- Call nothing, no overflow, no underflow - handler exempted. + +procedure Test_0 is +begin + null; +end; + +--# stacks.adb +-- /op_case/ l- ## s- +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /test_oflow/ l- ## s- +-- /op_oflow/ l- ## s- +-- /test_uflow/ l- ## s- +-- /op_uflow/ l- ## s- +-- /op_handler/ l* ## x+ +-- /op_handler_stmt/ l= ## Xs- + +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l- ## s- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pop_u.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pop_u.adb new file mode 100644 index 000000000..23cc089d8 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pop_u.adb @@ -0,0 +1,26 @@ +with Stacks, Support; use Stacks, Support; + +-- Pop only, immediate underflow. Handler covered. + +procedure Test_Pop_U is + S : Stack (Size => 2); + V : Integer; +begin + Pop (S, V); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /op_push/ l- ## s- +-- /op_pop/ l- ## s- +-- /test_oflow/ l- ## s- +-- /op_oflow/ l- ## s- +-- /test_uflow/ l+ ## 0 +-- /op_uflow/ l+ ## 0 +-- /op_handler/ l# ## x0 + +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_0.adb new file mode 100644 index 000000000..347eee539 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_0.adb @@ -0,0 +1,27 @@ +with Stacks, Support; use Stacks, Support; + +-- Push only, no overflow, no underflow. Handler exempted. + +procedure Test_Push_0 is + S : Stack (Size => 5); + +begin + Push (S, 3); + Assert (Errcount (S) = 0); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l- ## s- +-- /test_uflow/ l- ## s- +-- /op_uflow/ l- ## s- +-- /op_handler/ l* ## x+ +-- /op_handler_stmt/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_o.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_o.adb new file mode 100644 index 000000000..b81f4a95e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_push_o.adb @@ -0,0 +1,30 @@ +with Stacks, Support; use Stacks, Support; + +-- Push only, until overflow. Handler covered. + +procedure Test_Push_O is + S : Stack (Size => 2); + +begin + Push (S, 1); + Push (S, 3); + Assert (Errcount (S) = 0); + + Push (S, 4); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l- ## s- +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l+ ## 0 +-- /test_uflow/ l- ## s- +-- /op_uflow/ l- ## s- +-- /op_handler/ l# ## x0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_0.adb new file mode 100644 index 000000000..2a09c98fa --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_0.adb @@ -0,0 +1,35 @@ +with Stacks, Support; use Stacks, Support; + +-- Push and Pop, no overflow, no underflow. Handler exempted. + +procedure Test_PushPop_0 is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + + Pop (S, V); + Assert (V = 2); + + Pop (S, V); + Assert (V = 1); + + Assert (Errcount (S) = 0); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l- ## s- +-- /test_uflow/ l+ ## 0 +-- /op_uflow/ l- ## s- +-- /op_handler/ l* ## x+ +-- /op_handler_stmt/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_o.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_o.adb new file mode 100644 index 000000000..4f41dc49a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_o.adb @@ -0,0 +1,33 @@ +with Stacks, Support; use Stacks, Support; + +-- Push until overflow, then Pop. Handler covered. + +procedure Test_PushPop_O is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + Assert (Errcount (S) = 0); + + Push (S, 3); + Assert (Errcount (S) = 1); + + Pop (S, V); + Assert (V = 2); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l+ ## 0 +-- /test_uflow/ l+ ## 0 +-- /op_uflow/ l- ## s- +-- /op_handler/ l# ## x0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_ou.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_ou.adb new file mode 100644 index 000000000..5012ce38d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_ou.adb @@ -0,0 +1,39 @@ +with Stacks, Support; use Stacks, Support; + +-- Push until overflow, then Pop until underflow. Handler covered. + +procedure Test_PushPop_OU is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + Assert (Errcount (S) = 0); + + Push (S, 3); + Assert (Errcount (S) = 1); + + Pop (S, V); + Assert (V = 2); + + Pop (S, V); + Assert (V = 1); + + Pop (S, V); + Assert (Errcount (S) = 2); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l+ ## 0 +-- /test_uflow/ l+ ## 0 +-- /op_uflow/ l+ ## 0 +-- /op_handler/ l# ## x0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_u.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_u.adb new file mode 100644 index 000000000..3d31e2be3 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/src/test_pushpop_u.adb @@ -0,0 +1,31 @@ +with Stacks, Support; use Stacks, Support; + +-- Push, then Pop until underflow. Handler covered. + +procedure Test_PushPop_U is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Pop (S, V); + Assert (V = 1); + Assert (Errcount (S) = 0); + + Pop (S, V); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /op_push/ l+ ## 0 +-- /op_pop/ l+ ## 0 +-- /test_oflow/ l+ ## 0 +-- /op_oflow/ l- ## s- +-- /test_uflow/ l+ ## 0 +-- /op_uflow/ l+ ## 0 +-- /op_handler/ l# ## x0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/tc.rst new file mode 100644 index 000000000..104c89499 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/tc.rst @@ -0,0 +1,5 @@ +**Exercise exemptions over groups of statements within local exception handlers** + +Exercise non-exempted code and an exemption region for a short sequence of +statements within a local exception handler. + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/test.py new file mode 100644 index 000000000..4a726f9fe --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInHandler/test.py @@ -0,0 +1,18 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import Exempt_Region, generate_annotations + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = [ + Exempt_Region("src/stacks.adb", "27:10", "30:45", "exception handler"), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/multiple_exemptions.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/multiple_exemptions.adb new file mode 100755 index 000000000..2f9229d02 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/multiple_exemptions.adb @@ -0,0 +1,69 @@ +-- This procedure performs completely meaningless computations, its goal is +-- to create a natural context for several exemption sections + +with MX; use MX; + +-- I, J, and K are functional parameters. Xf.(X1, X2, X3) tell if we went +-- into the exempted regions 1, 2, and 3 respectively. Xf.Xh tells if we went +-- into the exempted handler. + +procedure Multiple_Exemptions + (I, J, K : in out Integer; Xf : access Xflags) +is + Tmp : Integer := I; -- # dcl +begin + + Xf.X1 := False; -- # stmt + Xf.X2 := False; -- # stmt + Xf.X3 := False; -- # stmt + Xf.Xh := False; -- # stmt + + -- A few exemption regions within conditionals in a sequence. Getting + -- into the first one raises an exception, caught by a local handler. + + if I = 0 and then J = 0 and then K = 0 then -- # 1_if + Xf.X1 := True; -- # 1_flag + pragma Annotate -- # 1_exem + (Xxxx, Exempt_On, "exemption section #1"); -- # 1_exem + raise Constraint_Error; -- # 1_exem_v1 + pragma Annotate (Xxxx, Exempt_Off); -- # 1_exem + end if; + + I := (I + J + K) / 3; -- # stmt + if I > 0 then -- # stmt + if J < 0 then -- # 2_if + Xf.X2 := True; -- # 2_flag + pragma Annotate -- # 2_exem + (Xxxx, Exempt_On, "exemption section #2"); -- # 2_exem + J := -J; -- # 2_exem_v1 + pragma Annotate (Xxxx, Exempt_Off); -- # 2_exem + end if; + I := Tmp; -- # 2_if + end if; + + J := J + K; -- # stmt + if K < 0 then -- # stmt + if J = 0 then -- # 3_if + Xf.X3 := True; -- # 3_flag + pragma Annotate -- # 3_exem + (Xxxx, Exempt_On, "exemption section #3"); -- # 3_exem + J := 1; -- # 3_exem_v1 + pragma Annotate (Xxxx, Exempt_Off); -- # 3_exem + end if; + K := K + I; -- # 3_if + end if; + +exception + when Constraint_Error => + Xf.Xh := True; -- # h_flag + + -- Here, an exemption region within an exception handler + + pragma Annotate -- # h_exem + (Xxxx, Exempt_On, "exemption section in handler"); -- # h_exem + Tmp := I + J + K; -- # h_exem_v1 + I := Tmp; -- # h_exem_v2 + J := Tmp + 1; -- # h_exem_v3 + K := Tmp + 2; -- # h_exem_v4 + pragma Annotate (Xxxx, Exempt_Off); -- # h_exem +end Multiple_Exemptions; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.adb new file mode 100644 index 000000000..8b94c8feb --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.adb @@ -0,0 +1,38 @@ +with Multiple_Exemptions, Support; use Support; + +package body MX is + I, J, K : Integer; + Xf : aliased Xflags; + + procedure Trigger_0XR is + begin + I := 1; J := 1; K := 1; + Multiple_Exemptions (I, J, K, Xf'Access); + Assert (not Xf.X1 and then not Xf.X2 + and then not Xf.X3 and then not Xf.Xh); + end; + + procedure Trigger_XR1 is + begin + I := 0; J := 0; K := 0; + Multiple_Exemptions (I, J, K, Xf'Access); + Assert (Xf.X1 and then not Xf.X2 + and then not Xf.X3 and then Xf.Xh); + end; + + procedure Trigger_XR2 is + begin + I := 3; J := -1; K := 1; + Multiple_Exemptions (I, J, K, Xf'Access); + Assert (not Xf.X1 and then Xf.X2 + and then not Xf.X3 and then not Xf.Xh); + end; + + procedure Trigger_XR3 is + begin + I := 10; J := 1; K := -1; + Multiple_Exemptions (I, J, K, Xf'Access); + Assert (not Xf.X1 and then not Xf.X2 + and then Xf.X3 and then not Xf.Xh); + end; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.ads b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.ads new file mode 100644 index 000000000..193d6e2d1 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/mx.ads @@ -0,0 +1,20 @@ +package MX is + + type Xflags is record + X1, X2, X3, Xh : Boolean; + end record; + + procedure Trigger_0XR; + -- Call into the functional code, arranging to get into none of the + -- exempted regions + + procedure Trigger_XR1; + procedure Trigger_XR2; + procedure Trigger_XR3; + -- Call into the functional code, arranging to get into the exempted + -- region 1, 2 or 3 only + + -- This unit is a helper to trigger some pieces of the functional code by + -- calling into it with well chosen set of arguments. It is not subject to + -- coverage expectations. +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_0.adb new file mode 100644 index 000000000..d40658d42 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_0.adb @@ -0,0 +1,31 @@ +with MX; + +-- Do nothing, so statement gets covered at all, and all the exemption +-- regions do exempt their statements. + +procedure Test_0 is +begin + null; +end Test_0; + +--# multiple_exemptions.adb +-- /dcl/ l- ## s- +-- /1_if/ l- ## s- +-- /1_flag/ l- ## s- +-- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- +-- /stmt/ l- ## s- +-- /2_if/ l- ## s- +-- /2_flag/ l- ## s- +-- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- +-- /3_if/ l- ## s- +-- /3_flag/ l- ## s- +-- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- +-- /h_flag/ l- ## s- +-- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_0.adb new file mode 100644 index 000000000..08e0e68c1 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_0.adb @@ -0,0 +1,26 @@ +-- Call into the functional code, arranging to execute all the code in all +-- the exempted sections, so no violation gets exempted. + +with MX, Support; use MX, Support; + +procedure Test_Exempt_0 is +begin + Trigger_XR1; + Trigger_XR2; + Trigger_XR3; +end; + +--# multiple_exemptions.adb +-- /dcl/ l+ ## 0 +-- /1_if/ l+ ## 0 +-- /1_flag/ l+ ## 0 +-- /1_exem/ l# ## x0 +-- /stmt/ l+ ## 0 +-- /2_if/ l+ ## 0 +-- /2_flag/ l+ ## 0 +-- /2_exem/ l# ## x0 +-- /3_if/ l+ ## 0 +-- /3_flag/ l+ ## 0 +-- /3_exem/ l# ## x0 +-- /h_flag/ l+ ## 0 +-- /h_exem/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_all.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_all.adb new file mode 100644 index 000000000..632346ad6 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_all.adb @@ -0,0 +1,31 @@ +-- Call into the functional code, arranging not to execute any exempted +-- region, so all the regions do exempt statements. + +with MX; use MX; + +procedure Test_Exempt_All is +begin + Trigger_0XR; +end; + +--# multiple_exemptions.adb +-- /dcl/ l+ ## 0 +-- /1_if/ l+ ## 0 +-- /1_flag/ l- ## s- +-- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- +-- /stmt/ l+ ## 0 +-- /2_if/ l+ ## 0 +-- /2_flag/ l- ## s- +-- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- +-- /3_if/ l- ## s- +-- /3_flag/ l- ## s- +-- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- +-- /h_flag/ l- ## s- +-- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr12.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr12.adb new file mode 100644 index 000000000..a6088e071 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr12.adb @@ -0,0 +1,30 @@ +with MX; use MX; + +-- Call functional code arranging to get into exempted region 3 only, +-- hence exempt violations from regions 1 and 2. + +procedure Test_Exempt_XR12 is +begin + Trigger_XR3; +end; + +--# multiple_exemptions.adb +-- /dcl/ l+ ## 0 +-- /1_if/ l+ ## 0 +-- /1_flag/ l- ## s- +-- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- +-- /stmt/ l+ ## 0 +-- /2_if/ l+ ## 0 +-- /2_flag/ l- ## s- +-- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- +-- /3_if/ l+ ## 0 +-- /3_flag/ l+ ## 0 +-- /3_exem/ l# ## x0 +-- /h_flag/ l- ## s- +-- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr13.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr13.adb new file mode 100644 index 000000000..174224dba --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr13.adb @@ -0,0 +1,30 @@ +with MX; use MX; + +-- Call functional code arranging to get into exempted region 2 only, +-- hence exempt violations from regions 1 and 3. + +procedure Test_Exempt_XR13 is +begin + Trigger_XR2; +end; + +--# multiple_exemptions.adb +-- /dcl/ l+ ## 0 +-- /1_if/ l+ ## 0 +-- /1_flag/ l- ## s- +-- /1_exem/ l* ## x+ +-- /1_exem_v1/ l= ## Xs- +-- /stmt/ l+ ## 0 +-- /2_if/ l+ ## 0 +-- /2_flag/ l+ ## 0 +-- /2_exem/ l# ## x0 +-- /3_if/ l- ## s- +-- /3_flag/ l- ## s- +-- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- +-- /h_flag/ l- ## s- +-- /h_exem/ l* ## x+ +-- /h_exem_v1/ l= ## Xs- +-- /h_exem_v2/ l= ## Xs- +-- /h_exem_v3/ l= ## Xs- +-- /h_exem_v4/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr23.adb b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr23.adb new file mode 100644 index 000000000..72be78090 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/src/test_exempt_xr23.adb @@ -0,0 +1,31 @@ +with MX; use MX; + +-- Call functional code arranging to get into exempted region 1 only, +-- hence exempt violations from regions 2 and 3. + +procedure Test_Exempt_XR23 is +begin + Trigger_XR1; + + -- Region 1 raises an exception, force running the other blocks + -- without the exempted regions. + + Trigger_0XR; +end; + +--# multiple_exemptions.adb +-- /dcl/ l+ ## 0 +-- /1_if/ l+ ## 0 +-- /1_flag/ l+ ## 0 +-- /1_exem/ l# ## x0 +-- /stmt/ l+ ## 0 +-- /2_if/ l+ ## 0 +-- /2_flag/ l- ## s- +-- /2_exem/ l* ## x+ +-- /2_exem_v1/ l= ## Xs- +-- /3_if/ l- ## s- +-- /3_flag/ l- ## s- +-- /3_exem/ l* ## x+ +-- /3_exem_v1/ l= ## Xs- +-- /h_flag/ l+ ## 0 +-- /h_exem/ l# ## x0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/tc.rst new file mode 100644 index 000000000..18a80a776 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/tc.rst @@ -0,0 +1,6 @@ +**Exercise exemptions over a mix of statements and declarations in several regions of a subprogram body** + +Exercise a subprogram containing non-exempted code and several disjoint +exemption regions, in both the top-level sequence of statements and a local +exception handler. + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/test.py new file mode 100644 index 000000000..8522e7bea --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/StmtsInSubprog/test.py @@ -0,0 +1,36 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import ( + Exempt_On, + Exempt_Off, + Exempt_Region, + generate_annotations, +) + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = [ + Exempt_Region( + "src/multiple_exemptions.adb", "26:7", "29:42", "exemption section #1" + ), + Exempt_Region( + "src/multiple_exemptions.adb", "36:10", "39:45", "exemption section #2" + ), + Exempt_On( + "src/multiple_exemptions.adb", "48:10", None, "exemption section #3" + ), + Exempt_Off("src/multiple_exemptions.adb", "51:45", None), + Exempt_On( + "src/multiple_exemptions.adb", "62:7", None, "exemption section #4" + ), + Exempt_Off("src/multiple_exemptions.adb", "68:42", None), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.adb new file mode 100644 index 000000000..852466775 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.adb @@ -0,0 +1,56 @@ +package body Stacks is + + -- Single exemption region for a couple of entire subprogram definitions + + pragma Annotate -- # xregion + (Xxxx, Exempt_On, "we only care about push and pop"); -- # xregion + -- # xregion + procedure On -- # xregion + (S : in out Stack; Op : Op_Kind; V : in out Integer) -- # xregion + is -- # xregion + begin -- # xregion + case Op is -- # xregion_01 + when Push => -- # xregion + if S.Vcount = S.Size then -- # xregion_02 + raise Constraint_Error; -- # xregion_03 + end if; -- # xregion + -- # xregion + S.Vcount := S.Vcount + 1; -- # xregion_04 + S.Values (S.Vcount) := V; -- # xregion_05 + -- # xregion + when Pop => -- # xregion + if S.Vcount = 0 then -- # xregion_06 + raise Constraint_Error; -- # xregion_07 + end if; -- # xregion + -- # xregion + V := S.Values (S.Vcount); -- # xregion_08 + S.Vcount := S.Vcount - 1; -- # xregion_09 + end case; -- # xregion + exception -- # xregion + when Constraint_Error => -- # xregion + S.Ecount := S.Ecount + 1; -- # xregion_10 + end; -- # xregion + -- # xregion + function Errcount (S : in Stack) return Natural is -- # xregion + begin -- # xregion + return S.Ecount; -- # xregion_11 + end; -- # xregion + -- # xregion + pragma Annotate (Xxxx, Exempt_Off); -- # xregion + + -- Then a couple of subprograms without any exemption + + procedure Push (S : in out Stack; Value : Integer) is + V : Integer := Value; -- # push_decl + begin + On (S, Op => Push, V => V); -- # push_body + end; + + procedure Pop (S : in out Stack; Value : out Integer) is + V : Integer := 0; -- # pop_decl + begin + On (S, Op => Pop, V => V); -- # pop_body + Value := V; -- # pop_body + end; + +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.ads b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.ads new file mode 100644 index 000000000..6f81d9042 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/stacks.ads @@ -0,0 +1,17 @@ +package Stacks is + + type Varray is array (Natural range <>) of Integer; + + type Stack (Size : Natural) is record + Vcount : Natural := 0; + Values : Varray (1 .. Size); + Ecount : Natural := 0; + end record; + + type Op_Kind is (Push, Pop); + + procedure Push (S : in out Stack; Value : Integer); + procedure Pop (S : in out Stack; Value : out Integer); + + function Errcount (S : in Stack) return Natural; +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_0.adb new file mode 100644 index 000000000..3186da809 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_0.adb @@ -0,0 +1,28 @@ +with Stacks, Support; use Stacks, Support; + +-- Call nothing, no overflow, no underflow - region exempted. + +procedure Test_0 is +begin + null; +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_01/ l= ## Xs- +-- /xregion_02/ l= ## Xs- +-- /xregion_03/ l= ## Xs- +-- /xregion_04/ l= ## Xs- +-- /xregion_05/ l= ## Xs- +-- /xregion_06/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- +-- /xregion_10/ l= ## Xs- +-- /xregion_11/ l= ## Xs- + +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l- ## s- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pop_u.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pop_u.adb new file mode 100644 index 000000000..02a4911e0 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pop_u.adb @@ -0,0 +1,26 @@ +with Stacks, Support; use Stacks, Support; + +-- Pop only, immediate underflow. Region exempted. + +procedure Test_Pop_U is + S : Stack (Size => 2); + V : Integer; +begin + Pop (S, V); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_02/ l= ## Xs- +-- /xregion_03/ l= ## Xs- +-- /xregion_04/ l= ## Xs- +-- /xregion_05/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- + +-- /push_decl/ l- ## s- +-- /push_body/ l- ## s- +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_0.adb new file mode 100644 index 000000000..54f9fed66 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_0.adb @@ -0,0 +1,26 @@ +with Stacks, Support; use Stacks, Support; + +-- Push only, no overflow, no underflow. Region exempted. + +procedure Test_Push_0 is + S : Stack (Size => 5); + +begin + Push (S, 3); + Assert (Errcount (S) = 0); +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_03/ l= ## Xs- +-- /xregion_06/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- +-- /xregion_10/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_o.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_o.adb new file mode 100644 index 000000000..6d871a716 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_push_o.adb @@ -0,0 +1,28 @@ +with Stacks, Support; use Stacks, Support; + +-- Push only, until overflow. Region exempted. + +procedure Test_Push_O is + S : Stack (Size => 2); + +begin + Push (S, 1); + Push (S, 3); + Assert (Errcount (S) = 0); + + Push (S, 4); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_06/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_08/ l= ## Xs- +-- /xregion_09/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l- ## s- +-- /pop_body/ l- ## s- +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_0.adb new file mode 100644 index 000000000..af94531be --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_0.adb @@ -0,0 +1,31 @@ +with Stacks, Support; use Stacks, Support; + +-- Push and Pop, no overflow, no underflow. Region exempted. + +procedure Test_PushPop_0 is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + + Pop (S, V); + Assert (V = 2); + + Pop (S, V); + Assert (V = 1); + + Assert (Errcount (S) = 0); +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_03/ l= ## Xs- +-- /xregion_07/ l= ## Xs- +-- /xregion_10/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_o.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_o.adb new file mode 100644 index 000000000..9f37a886d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_o.adb @@ -0,0 +1,28 @@ +with Stacks, Support; use Stacks, Support; + +-- Push until overflow, then Pop. Region exempted. + +procedure Test_PushPop_O is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + Assert (Errcount (S) = 0); + + Push (S, 3); + Assert (Errcount (S) = 1); + + Pop (S, V); + Assert (V = 2); +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_07/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_ou.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_ou.adb new file mode 100644 index 000000000..93c23ba23 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_ou.adb @@ -0,0 +1,33 @@ +with Stacks, Support; use Stacks, Support; + +-- Push until overflow, then Pop until underflow. Region covered. + +procedure Test_PushPop_OU is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Push (S, 2); + Assert (Errcount (S) = 0); + + Push (S, 3); + Assert (Errcount (S) = 1); + + Pop (S, V); + Assert (V = 2); + + Pop (S, V); + Assert (V = 1); + + Pop (S, V); + Assert (Errcount (S) = 2); +end; + +--# stacks.adb +-- /xregion/ l# ## x0 + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_u.adb b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_u.adb new file mode 100644 index 000000000..0d0c5cef3 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/src/test_pushpop_u.adb @@ -0,0 +1,26 @@ +with Stacks, Support; use Stacks, Support; + +-- Push, then Pop until underflow. Region exempted. + +procedure Test_PushPop_U is + S : Stack (Size => 2); + V : Integer; +begin + Push (S, 1); + Pop (S, V); + Assert (V = 1); + Assert (Errcount (S) = 0); + + Pop (S, V); + Assert (Errcount (S) = 1); +end; + +--# stacks.adb +-- /xregion/ l* ## x+ +-- /xregion_03/ l= ## Xs- + +-- /push_decl/ l+ ## 0 +-- /push_body/ l+ ## 0 +-- /pop_decl/ l+ ## 0 +-- /pop_body/ l+ ## 0 +-- /err_body/ l+ ## 0 diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/tc.rst new file mode 100644 index 000000000..7dde4dc8e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/tc.rst @@ -0,0 +1,6 @@ +**Exercise exemptions over groups of entire subprograms** + +Exercise a package that declares some non-exempted subprogram bodies as +well as an exemption region encompassing several other subprograms. + + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/test.py new file mode 100644 index 000000000..2b87406ba --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/SubprogsInUnit/test.py @@ -0,0 +1,19 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import Exempt_Region, generate_annotations + +annotations = [ + Exempt_Region( + "src/stacks.adb", "5:4", "39:40", "we only care about push and pop" + ), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_0.adb b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_0.adb new file mode 100644 index 000000000..c4c40190a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_0.adb @@ -0,0 +1,12 @@ +with Support, Tipos; use Support; + +procedure Test_Tipos_0 is +begin + null; +end; + +--# tipos.adb +-- /xblock/ l* ## x+:"test exempting all" +-- /xblock_if/ l= ## Xs- +-- /xblock_r1/ l= ## Xs- +-- /xblock_r2/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_all.adb b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_all.adb new file mode 100644 index 000000000..dea643efc --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_all.adb @@ -0,0 +1,10 @@ +with Support, Tipos; use Support; + +procedure Test_Tipos_All is +begin + Assert (Tipos (5) = 10); + Assert (Tipos (-2) = -2); +end; + +--# tipos.adb +-- /xblock/ l# ## x0:"test exempting all" diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_other.adb b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_other.adb new file mode 100644 index 000000000..7e377b1f7 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_other.adb @@ -0,0 +1,10 @@ +with Support, Tipos; use Support; + +procedure Test_Tipos_Other is +begin + Assert (Tipos (-2) = -2); +end; + +--# tipos.adb +-- /xblock/ l* ## x+:"test exempting all" +-- /xblock_r1/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_pos.adb b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_pos.adb new file mode 100644 index 000000000..c3b785427 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/test_tipos_pos.adb @@ -0,0 +1,10 @@ +with Support, Tipos; use Support; + +procedure Test_Tipos_Pos is +begin + Assert (Tipos (5) = 10); +end; + +--# tipos.adb +-- /xblock/ l* ## x+:"test exempting all" +-- /xblock_r2/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.adb b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.adb new file mode 100644 index 000000000..8ee02dfa0 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.adb @@ -0,0 +1,13 @@ +function Tipos (X : Integer) return Integer is +begin + -- Full sequence exempted below + + pragma Annotate (Xxxx, Exempt_On, -- # xblock + "test exempting all"); -- # xblock + if X > 0 then -- # xblock_if + return X * 2; -- # xblock_r1 + else -- # xblock + return X; -- # xblock_r2 + end if; -- # xblock + pragma Annotate (Xxxx, Exempt_Off); -- # xblock +end; diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.ads b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.ads new file mode 100644 index 000000000..68d462531 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/src/tipos.ads @@ -0,0 +1,2 @@ +function Tipos (X : Integer) return Integer; +-- Twice_If_Pos: x * 2 if x positive, x otherwise. diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/tc.rst b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/tc.rst new file mode 100644 index 000000000..2fd022a0f --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/tc.rst @@ -0,0 +1,5 @@ +**Exercise exemptions over entire subprogram bodies** + +Exercise a subprogram in which all the statements are part of a single +exemption region. + diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/test.py b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/test.py new file mode 100644 index 000000000..1b95170f6 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/WholeBody/test.py @@ -0,0 +1,17 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import Exempt_Region, generate_annotations + +annotations = [ + Exempt_Region("src/tipos.adb", "5:4", "12:39", "test exempting all"), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/ada_ex/extra.opt b/testsuite/tests/ext_annotations/gen/ada_ex/extra.opt new file mode 100644 index 000000000..596c843db --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/ada_ex/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD Test uses pragma not recognized by compiler diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.adb new file mode 100644 index 000000000..4c46e1ef0 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.adb @@ -0,0 +1,9 @@ +package body Lib1 is + function Foo return Integer + is + Res : constant Integer := 1; + begin + pragma Annotate (Xxxx, Dump_Buffers); + return Res; + end Foo; +end Lib1; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.ads b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.ads new file mode 100644 index 000000000..aaa69a16f --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib1/lib1.ads @@ -0,0 +1,3 @@ +package Lib1 is + function Foo return Integer; +end Lib1; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.adb new file mode 100644 index 000000000..3aea37455 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.adb @@ -0,0 +1,9 @@ +package body Lib2 is + function Bar return Integer + is + Res : constant Integer := 1; + begin + pragma Annotate (Xxxx, Dump_Buffers); + return Res; + end Bar; +end Lib2; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.ads b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.ads new file mode 100644 index 000000000..7968b33bf --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src-lib2/lib2.ads @@ -0,0 +1,3 @@ +package Lib2 is + function Bar return Integer; +end Lib2; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/main.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/main.adb new file mode 100644 index 000000000..6242717d5 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/main.adb @@ -0,0 +1,30 @@ +pragma Ada_2012; + +with Lib1; +with Lib2; +with Manual_Dump; + +procedure Main is + + procedure Increment (J : in out Integer) + is + begin + J := J + 1; + end Increment; + + I : Integer := 1; +begin + -- The only call that should not count as a violation when never executed + -- is that of the dump buffers procedure. + if 1 = I + 1 then + pragma Annotate (Xcov, Dump_Buffers); + I := I+ 1; + end if; + + Increment (I); + pragma Annotate (Xcov, Dump_Buffers); + I := I + Lib1.Foo; + I := I + Lib2.Bar; + Manual_Dump.Dump; + Increment (I); +end Main; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.adb new file mode 100644 index 000000000..cde653702 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.adb @@ -0,0 +1,6 @@ +package body Manual_Dump is + procedure Dump is + begin + pragma Annotate (Xxxx, Dump_Buffers); + end Dump; +end Manual_Dump; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.ads b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.ads new file mode 100644 index 000000000..898439fa6 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/src/manual_dump.ads @@ -0,0 +1,3 @@ +package Manual_Dump is + procedure Dump; +end Manual_Dump; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.opt b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.opt new file mode 100644 index 000000000..da87b2710 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.opt @@ -0,0 +1,2 @@ +block DEAD Manual dump wrapped in procedure call (unsupported when using block coverage) +5.04a1 DEAD Uses pragma unknown to compiler diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.py b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.py new file mode 100644 index 000000000..16298244e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_only/test.py @@ -0,0 +1,103 @@ +""" +Test that when using manual dump trigger in Ada with a specific pragma +indicating where to dump the coverage buffers, gnatcov is able to replace it +with a call to the dump buffers procedure and output correct traces. +""" + +import glob + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import ( + Dump_Buffers, + generate_annotations, + gprfor, + srctrace_pattern_for, +) + +# Generate annotations out of the temp dir to avoid having relative path +# components in the entries + +annotations = generate_annotations( + [ + Dump_Buffers("src/manual_dump.adb", "4:7", None, insert_after=True), + Dump_Buffers("src-lib1/lib1.adb", "6:9", None, insert_after=True), + Dump_Buffers("src-lib2/lib2.adb", "6:9", None, insert_after=True), + ] +) + +tmp = Wdir("tmp_") + +lib1_p = gprfor( + mains=[], + prjid="lib1", + srcdirs="../src-lib1", + objdir="obj-lib1", + langs=["Ada"], +) + +lib2_p = gprfor( + mains=[], + prjid="lib2", + srcdirs="../src-lib2", + objdir="obj-lib2", + langs=["Ada"], +) + +p = gprfor( + prjid="gen", + mains=["main.adb"], + srcdirs=["../src"], + objdir="obj", + deps=["lib1", "lib2"], +) + +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) + +cov_args = build_and_run( + gprsw=GPRswitches(root_project=p, units=["lib1", "main"]), + covlevel="stmt", + mains=["main"], + extra_instr_args=[f"--external-annotations={annotations}"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + dump_trigger="manual", + manual_prj_name="gen", + tolerate_instrument_messages=instr_warning, +) + +# Check that gnatcov inserted the call to the dump buffers procedure in the +# lib2.adb which is not a unit of interest + + +def check_call(file): + thistest.fail_if_no_match( + "missing dump buffers procedure call", + "(\n|.)*GCVRT.DB_manual_lib2.Dump_Buffers(.*);" "(\n|.)*", + contents_of(file), + ) + + +check_call("obj-lib2/lib2-gnatcov-instr/lib2.adb") + +# Generate and check coverage reports, using the last trace generated for the +# root project. +trace_file = sorted( + glob.glob(srctrace_pattern_for("main", manual=True, manual_prj_name="gen")) +)[-1] + +xcov(cov_args + [trace_file], out="coverage.log") +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {12, 15, 19, 24, 26, 27, 28}, "-": {21, 29}}, + "lib1.adb.xcov": {"+": {4, 7}}, + "lib1.ads.xcov": {}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.adb new file mode 100644 index 000000000..83adfaee4 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.adb @@ -0,0 +1,12 @@ +with Lib2; + +package body Lib1 is + function Foo return Integer + is + Res : Integer := 1; + begin + Res := Res + Lib2.Bar; + pragma Annotate (Xcov, Dump_Buffers); + return Res; + end Foo; +end Lib1; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.ads b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.ads new file mode 100644 index 000000000..aaa69a16f --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/lib1.ads @@ -0,0 +1,3 @@ +package Lib1 is + function Foo return Integer; +end Lib1; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.adb new file mode 100644 index 000000000..dac52ea6c --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.adb @@ -0,0 +1,8 @@ +package body Lib2 is + function Bar return Integer + is + Res : constant Integer := 1; + begin + return Res; + end Bar; +end Lib2; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.ads b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.ads new file mode 100644 index 000000000..7968b33bf --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src-lib1/src-lib2/lib2.ads @@ -0,0 +1,3 @@ +package Lib2 is + function Bar return Integer; +end Lib2; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src/main.adb b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src/main.adb new file mode 100644 index 000000000..d52e99f7a --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/src/main.adb @@ -0,0 +1,18 @@ +pragma Ada_2012; + +with Lib1; + +procedure Main is + + procedure Increment (J : in out Integer) + is + begin + J := J + 1; + end Increment; + + I : Integer := 1; +begin + Increment (I); + I := I + Lib1.Foo; + Increment (I); +end Main; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/test.py b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/test.py new file mode 100644 index 000000000..2c3f42e1f --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/ada_subprj/test.py @@ -0,0 +1,98 @@ +""" +Test that when using manual dump trigger in Ada with the appropriate buffers +dump pragma only in a subproject itself dependent on another subproject +gnatcov is able to provide the correct coverage analysis. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import Dump_Buffers, generate_annotations, gprfor + +# Generate annotations out of the temp dir to avoid having relative path +# components in the entries + +annotations = generate_annotations( + [Dump_Buffers("src-lib1/lib1.adb", "9:9", None, insert_after=True)] +) + + +def make_lib_gpr(name, srcdirs, deps): + return gprfor( + mains=[], + prjid=name, + srcdirs=srcdirs, + objdir="obj-" + name, + langs=["Ada"], + deps=deps, + ) + + +def check_one(with_units): + """ + Do a build, run, coverage, and report-check workflow, ensuring we get the + expected warnings and coverage results. + + with_units controls wether the --units option is passed + to gnatcov instrument to restrict analysis to the units in the projects + where the manual dump indication has visibility. + """ + + suffix = "units" if with_units else "no_units" + tmp = Wdir("tmp_" + suffix) + + make_lib_gpr("lib1", "../src-lib1", ["lib2"]) + make_lib_gpr("lib2", "../src-lib1/src-lib2", None) + + p = gprfor( + mains=["main.adb"], + srcdirs=["../src"], + objdir="obj", + deps=["lib1", "lib2"], + ) + + # Check that we get the expected coverage reports + + # Running gnatcov natively allows to have one source trace file per + # project. + instr_warning = ( + r"warning: Manual buffer dump/reset indications were" r" found in.*" + ) + + build_run_and_coverage( + gprsw=GPRswitches( + root_project=p, units=["lib1", "lib2"] if with_units else None + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=[f"--external-annotations={annotations}"], + extra_coverage_args=["-axcov", "--output-dir=xcov_" + suffix], + trace_mode="src", + dump_trigger="manual", + manual_prj_name="lib1", + tolerate_instrument_messages=instr_warning, + ) + + # If with_units is False, we expect coverage violations for main.adb + check_xcov_reports( + "xcov_" + suffix, + { + "lib1.adb.xcov": {"+": {6, 8}, "-": {10}}, + "lib1.ads.xcov": {}, + "lib2.adb.xcov": {"+": {4, 6}}, + "lib2.ads.xcov": {}, + } + | ( + {} + if with_units + else {"main.adb.xcov": {"-": {10, 13, 15, 16, 17}}} + ), + ) + tmp.to_homedir() + + +check_one(with_units=False) +check_one(with_units=True) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.c b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.c new file mode 100644 index 000000000..d51660a01 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.c @@ -0,0 +1,9 @@ +int +foo () +{ + int res = 1; + // This is a comment + /* *******_DUMP_BUFFERS */ + // This is another comment + return res; +} diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.h b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.h new file mode 100644 index 000000000..a4536647c --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src-lib/foo.h @@ -0,0 +1 @@ +int foo (); diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src/main.c b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src/main.c new file mode 100644 index 000000000..abbbb22c8 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/src/main.c @@ -0,0 +1,27 @@ +#include "foo.h" + +void +increment (int *x) +{ + (*x)++; +} + +int +main () +{ + int x = 1; + // The only call that should not count as a violation when never executed + // is that of the dump buffers procedure. + if (1 == 2) + { + /* *******_DUMP_BUFFERS */ + return 0; + } + increment (&x); + + x += foo (); + + /* *******_DUMP_BUFFERS */ + + return 0; +} diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/c_only/test.py b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/test.py new file mode 100644 index 000000000..f9208e92e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/test.py @@ -0,0 +1,91 @@ +""" +Test that when using manual dump trigger in C with a specific comment +indicating where to dump the coverage buffers, gnatcov is able to replace it +with a call to the dump buffers procedure and output correct traces. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import Dump_Buffers, generate_annotations, gprfor +from SUITE.gprutils import GPRswitches + +# Generate annotations out of the temp dir to avoid having relative path +# components in the entries + +annotations = generate_annotations( + [ + Dump_Buffers("src/main.c", "17:7", None), + Dump_Buffers("src/main.c", "24:3", None), + Dump_Buffers("src-lib/foo.c", "6:3", None), + ] +) + +tmp = Wdir("tmp_") + +# Create the GPR file for the root project +src_gpr = gprfor( + mains=["main.c"], + prjid="main", + srcdirs="../src", + objdir="obj", + langs=["C"], + deps=["lib"], +) + +# Create the GPR files for the library +lib_gpr = gprfor( + mains=[], + prjid="lib", + srcdirs="../src-lib", + langs=["C"], + extra=""" + for Library_Name use "lib"; + for Library_Dir use "lib"; + """, +) + +gprsw = GPRswitches(root_project=src_gpr) + +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) + +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_instr_args=[f"--external-annotations={annotations}"], + extra_coverage_args=["-axcov"], + dump_trigger="manual", + manual_prj_name="main", + tolerate_instrument_messages=instr_warning, +) + +thistest.fail_if_not_equal( + what="gprbuild output not empty", + expected="", + actual=contents_of("gprbuild.out").strip(), +) + +# Check that that the dump call indication was correctly replaced in the sub +# project + +lib_file = "obj/lib-gnatcov-instr/foo.c" +thistest.fail_if_no_match( + "missing Dump_Buffers call", + r"(\n|.)*gnatcov_rts_manual_dump_buffers_lib\(.*\);(\n|.)*", + contents_of(lib_file), +) + +# Check that we got the expected coverage report + +check_xcov_reports( + "obj", + { + "main.c.xcov": {"+": {6, 12, 15, 20, 22}, "-": {18, 26}}, + "foo.c.xcov": {"+": {4, 8}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.cpp b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.cpp new file mode 100644 index 000000000..d51660a01 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.cpp @@ -0,0 +1,9 @@ +int +foo () +{ + int res = 1; + // This is a comment + /* *******_DUMP_BUFFERS */ + // This is another comment + return res; +} diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.h b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.h new file mode 100644 index 000000000..a4536647c --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src-lib/foo.h @@ -0,0 +1 @@ +int foo (); diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src/main.cpp b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src/main.cpp new file mode 100644 index 000000000..abbbb22c8 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/src/main.cpp @@ -0,0 +1,27 @@ +#include "foo.h" + +void +increment (int *x) +{ + (*x)++; +} + +int +main () +{ + int x = 1; + // The only call that should not count as a violation when never executed + // is that of the dump buffers procedure. + if (1 == 2) + { + /* *******_DUMP_BUFFERS */ + return 0; + } + increment (&x); + + x += foo (); + + /* *******_DUMP_BUFFERS */ + + return 0; +} diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.opt b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.opt new file mode 100644 index 000000000..5a8819395 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.opt @@ -0,0 +1 @@ +!C++ DEAD test specific to C++ handling diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.py b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.py new file mode 100644 index 000000000..5c969ee27 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.py @@ -0,0 +1,93 @@ +""" +Test that when using manual dump trigger in C++ with a specific comment +indicating where to dump the coverage buffers, gnatcov is able to replace it +with a call to the dump buffers procedure and output correct traces. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import Dump_Buffers, generate_annotations, gprfor +from SUITE.gprutils import GPRswitches + +# Generate annotations out of the temp dir to avoid having relative path +# components in the entries + +annotations = generate_annotations( + [ + Dump_Buffers("src/main.cpp", "17:7", None), + Dump_Buffers("src/main.cpp", "24:3", None), + Dump_Buffers("src-lib/foo.cpp", "6:3", None), + ] +) + +tmp = Wdir("tmp_") + +# Create the GPR file for the root project +src_gpr = gprfor( + mains=["main.cpp"], + prjid="main", + srcdirs="../src", + objdir="obj", + langs=["C++"], + deps=["lib"], +) + +# Create the GPR files for the library +lib_gpr = gprfor( + mains=[], + prjid="lib", + srcdirs="../src-lib", + langs=["C++"], + extra=""" + for Library_Name use "lib"; + for Library_Dir use "lib"; + """, +) + +gprsw = GPRswitches(root_project=src_gpr) + +instr_warning = ( + r"warning: Manual buffer dump/reset indications were found" r" in.*" +) + +build_run_and_coverage( + gprsw=gprsw, + covlevel="stmt", + mains=["main"], + extra_instr_args=[f"--external-annotations={annotations}"], + extra_coverage_args=["-axcov"], + dump_trigger="manual", + manual_prj_name="main", + tolerate_instrument_messages=instr_warning, +) + +# Ensure we get no compilation warnings, this used to be the case without the +# proper dump function declaration. +thistest.fail_if_not_equal( + what="gprbuild output not empty", + expected="", + actual=contents_of("gprbuild.out").strip(), +) + +# Check that that the dump call indication was correctly replaced in the sub +# project + +lib_file = "obj/lib-gnatcov-instr/foo.cpp" +thistest.fail_if_no_match( + "missing Dump_Buffers call", + r"(\n|.)*gnatcov_rts_manual_dump_buffers_lib\(.*\);(\n|.)*", + contents_of(lib_file), +) + +# Check that we got the expected coverage report + +check_xcov_reports( + "obj", + { + "main.cpp.xcov": {"+": {6, 12, 15, 20, 22}, "-": {18, 26}}, + "foo.cpp.xcov": {"+": {4, 8}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/extra.opt b/testsuite/tests/ext_annotations/gen/buf_dump/extra.opt new file mode 100644 index 000000000..ff4943776 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD src-trace only feature tests diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_ada.adb b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_ada.adb new file mode 100644 index 000000000..837c15a87 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_ada.adb @@ -0,0 +1,7 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_Ada is +begin + Put_Line ("Hello Ada world!"); + pragma Annotate (Xxxx, Dump_Buffers); +end Main_Ada; diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_c.c b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_c.c new file mode 100644 index 000000000..c12408cbb --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_c.c @@ -0,0 +1,9 @@ +#include + +int +main (void) +{ + printf ("Hello C world!\n"); + /* *******_DUMP_BUFFERS */ + return 0; +} diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_cpp.cpp b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_cpp.cpp new file mode 100644 index 000000000..3086d2ec2 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/main_cpp.cpp @@ -0,0 +1,9 @@ +#include + +int +main (void) +{ + std::cout << "hello C++ world!" << std::endl; + /* *******_DUMP_BUFFERS */ + return 0; +} diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.opt b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.opt new file mode 100644 index 000000000..ab2120f34 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.opt @@ -0,0 +1,3 @@ +RTS_ZFP DEAD test uses stdio +!C++ DEAD test requires C++ compiler +!native XFAIL Build failure with mixed language mains. See #212 diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.py b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.py new file mode 100644 index 000000000..696e636e8 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buf_dump/mixed_all/test.py @@ -0,0 +1,79 @@ +""" +Check that using --dump-trigger=manual works correctly in projects where a +manual dump indication is present in an Ada source and in all supported C-like +sources. + +This is a regression test, gnatcov used to emit helper units with colliding +object filenames, resulting in the instrumented sources failing to build. +""" + +import os + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import ( + Dump_Buffers, + generate_annotations, + gprfor, + run_cov_program, + exepath_to, +) + +# Generate annotations out of the temp dir to avoid having relative path +# components in the entries + +annotations = generate_annotations( + [ + Dump_Buffers("main_ada.adb", "6:5", None, insert_after=True), + Dump_Buffers("main_c.c", "7:3", None), + Dump_Buffers("main_cpp.cpp", "7:3", None), + ] +) + +Wdir("tmp_") + +# Name for the main_c and main_cpp executable traces +c_trace_name = "main_c.srctrace" +cpp_trace_name = "main_cpp.srctrace" + +# We can't build_run_and_coverage as the default trace name only depends on the +# project name so all mains would dump a trace with the same name (execution +# last less than a second). Instead, instrument and execute the first main +# through build_and_run, then run the other mains manually. +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid="p", + srcdirs=[".."], + mains=["main_ada.adb", "main_c.c", "main_cpp.cpp"], + langs=["Ada", "C", "C++"], + ) + ), + covlevel="stmt", + mains=["main_ada"], + dump_trigger="manual", + manual_prj_name="p", + extra_instr_args=[f"--external-annotations={annotations}"], + extra_coverage_args=["-axcov", c_trace_name, cpp_trace_name], +) + +env = dict(os.environ) +env["GNATCOV_TRACE_FILE"] = c_trace_name +run_cov_program(exepath_to("main_c"), env=env) + +env["GNATCOV_TRACE_FILE"] = cpp_trace_name +run_cov_program(exepath_to("main_cpp"), env=env) + +xcov(cov_args) +check_xcov_reports( + "obj", + { + "main_ada.adb.xcov": {"+": {5}}, + "main_c.c.xcov": {"+": {6}, "-": {8}}, + "main_cpp.cpp.xcov": {"+": {6}, "-": {8}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/.clang-format b/testsuite/tests/ext_annotations/gen/buffer_reset/.clang-format new file mode 100644 index 000000000..74b68f75d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/.clang-format @@ -0,0 +1,7 @@ +BasedOnStyle: GNU +ColumnLimit: 80 +ContinuationIndentWidth: 2 +IndentWidth: 2 +ReflowComments: true +SortIncludes: Never +UseTab: Never diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/main_ada.adb b/testsuite/tests/ext_annotations/gen/buffer_reset/main_ada.adb new file mode 100644 index 000000000..68f88cd34 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/main_ada.adb @@ -0,0 +1,15 @@ +with Support; use Support; + +with Pkg; use Pkg; + +procedure Main_Ada is +begin + Assert (not Or_Else (False, False)); + pragma Annotate (Xxxx, Dump_Buffers, "ada-0"); + pragma Annotate (Xxxx, Reset_Buffers); + Assert (Or_Else (True, False)); + pragma Annotate (Xxxx, Dump_Buffers, "ada-1"); + pragma Annotate (Xxxx, Reset_Buffers); + Assert (Or_Else (False, True)); + pragma Annotate (Xxxx, Dump_Buffers, "ada-2"); +end Main_Ada; diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/main_c.c b/testsuite/tests/ext_annotations/gen/buffer_reset/main_c.c new file mode 100644 index 000000000..88c95920c --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/main_c.c @@ -0,0 +1,17 @@ +#include + +extern bool and_then (bool left, bool right); + +int +main (void) +{ + and_then (true, true); + /* *******_DUMP_BUFFERS ("c-0") */ + /* *******_RESET_BUFFERS */ + and_then (true, false); + /* *******_DUMP_BUFFERS ("c-1") */ + /* *******_RESET_BUFFERS */ + and_then (false, true); + /* *******_DUMP_BUFFERS ("c-2") */ + return 0; +} diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/pkg.adb b/testsuite/tests/ext_annotations/gen/buffer_reset/pkg.adb new file mode 100644 index 000000000..de46c9e85 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + function Or_Else (L, R : Boolean) return Boolean is + begin + return L or else R; + end Or_Else; + +end Pkg; diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/pkg.ads b/testsuite/tests/ext_annotations/gen/buffer_reset/pkg.ads new file mode 100644 index 000000000..2bedb4461 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Or_Else (L, R : Boolean) return Boolean; + +end Pkg; diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/pkh.c b/testsuite/tests/ext_annotations/gen/buffer_reset/pkh.c new file mode 100644 index 000000000..016dfffad --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/pkh.c @@ -0,0 +1,7 @@ +#include + +bool +and_then (bool left, bool right) +{ + return left && right; +} diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/test.opt b/testsuite/tests/ext_annotations/gen/buffer_reset/test.opt new file mode 100644 index 000000000..4f6c15e13 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/test.opt @@ -0,0 +1,3 @@ +bin-traces DEAD Test specific to src trace feature +!native DEAD Test requires bin-file dump channel +5.04a1 DEAD Uses pragmas unknown to the compiler diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/test.py b/testsuite/tests/ext_annotations/gen/buffer_reset/test.py new file mode 100644 index 000000000..76e6aa253 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/test.py @@ -0,0 +1,174 @@ +""" +Test basic functionality of the buffer reset mechanism, in both C and Ada +source files. +""" + +import glob +import re + +from SCOV.minicheck import build_and_run, check_xcov_reports, xcov +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import ( + Dump_Buffers, + generate_annotations, + gprfor, + Reset_Buffers, +) + +annotations = generate_annotations( + [ + Dump_Buffers("main_c.c", "9:3", None, trace_prefix='"c-0"'), + Reset_Buffers("main_c.c", "10:3", None), + Dump_Buffers("main_c.c", "12:3", None, trace_prefix='"c-1"'), + Reset_Buffers("main_c.c", "13:3", None), + Dump_Buffers("main_c.c", "15:3", None, trace_prefix='"c-2"'), + Dump_Buffers("main_ada.adb", "8:5", None, trace_prefix='"ada-0"'), + Reset_Buffers("main_ada.adb", "9:5", None, insert_after=True), + Dump_Buffers("main_ada.adb", "11:5", None, trace_prefix='"ada-1"'), + Reset_Buffers("main_ada.adb", "12:5", None, insert_after=True), + Dump_Buffers("main_ada.adb", "14:5", None, trace_prefix='"ada-2"'), + ] +) + +tmp = Wdir("tmp_") + +# Map from language to the corresponding main report name, and lines with +# coverage obligations. +main_lines = { + "ada": ("main_ada.adb.xcov", [7, 10, 13]), + "c": ("main_c.c.xcov", [8, 11, 14, 16]), +} + +# Units which will only have a partial coverage result in them, regardless of +# the trace. +default_part_cov = { + "ada": {"pkg.adb.xcov": {"!": {5}}, "pkg.ads.xcov": {}}, + "c": {"pkh.c.xcov": {"!": {6}}}, +} + +# Default "nothing executed" expected result for each unit +default_no_cov = { + "ada": { + "main_ada.adb.xcov": {"-": {7, 10, 13}}, + "pkg.adb.xcov": {"-": {5}}, + "pkg.ads.xcov": {}, + }, + "c": { + "main_c.c.xcov": {"-": {8, 11, 14, 16}}, + "pkh.c.xcov": {"-": {6}}, + }, +} + + +def get_expected_cov(trace_name): + """ + Generate an expected coverage results based on the prefix of the trace + indicating which main was executed, and its index. + """ + match = re.match(pattern=r"(.*)-(\d)\.srctrace", string=trace_name) + thistest.fail_if( + not match, comment="trace name not in expected format: " + trace_name + ) + trace_lang = match.group(1) + idx = int(match.group(2)) + expected_cov = {} + + lines = main_lines[trace_lang][1] + for lang in ("ada", "c"): + if lang == trace_lang: + expected_cov.update( + { + main_lines[lang][0]: { + "+": {lines[idx]}, + "-": {lines[i] for i in range(len(lines)) if i != idx}, + } + } + ) + expected_cov.update(default_part_cov[lang]) + else: + expected_cov.update(default_no_cov[lang]) + return expected_cov + + +def check_one_exec(cov_args, lang): + """ + Find the traces generated by the lang executable, assuming the trace prefix + is lang. Then create a coverage report from each trace, checking the + expected coverage report. + """ + + thistest.log(f"======== Checking {lang} traces =========") + + # We expect the trace to be in the format + # {lang}-{index}.srctrace: + traces = glob.glob(f"{lang}-[0-9].srctrace") + + # There is three dump indications in each main, we should thus have the + # same number of traces. + thistest.fail_if( + len(traces) != 3, comment=f"expected 3 traces, found {len(traces)}" + ) + traces.sort() + + for i in range(len(traces)): + thistest.log(f"-- {i+1}. --") + output_dir = f"output_{lang}_{i}/" + xcov( + cov_args + [f"--output-dir={output_dir}", traces[i]], + out=f"coverage_{lang}_{i}.log", + ) + check_xcov_reports(output_dir, get_expected_cov(traces[i])) + + +prj_id = "p" + +# Instrument build and run +cov_args = build_and_run( + gprsw=GPRswitches( + gprfor( + prjid=prj_id, + srcdirs=[".."], + mains=["main_ada.adb", "main_c.c"], + ) + ), + covlevel="stmt+mcdc", + mains=["main_ada", "main_c"], + dump_trigger="manual", + manual_prj_name=prj_id, + extra_coverage_args=["-axcov+"], + extra_instr_args=[ + "--dump-filename-simple", + f"--external-annotations={annotations}", + ], +) + +# Check the individual trace contents for each executable +for lang in ["c", "ada"]: + check_one_exec(cov_args, lang) + +# Do a consolidated check with all the traces. We expect exactly six traces and +# no coverage violations except for the final return statement in the c main. +thistest.log("========== global consolidated check =========") +all_traces = glob.glob("*.srctrace") +thistest.fail_if( + len(all_traces) != 6, comment=f"expected 6 traces, got {len(all_traces)}" +) +output_dir = "consolidated/" +xcov( + cov_args + [f"--output-dir={output_dir}"] + all_traces, + out="consolidated.log", +) +check_xcov_reports( + output_dir, + { + "main_ada.adb.xcov": {"+": {7, 10, 13}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {5}}, + "main_c.c.xcov": {"+": {8, 11, 14}, "-": {16}}, + "pkh.c.xcov": {"+": {6}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Invalid/main.c b/testsuite/tests/ext_annotations/gen/c_ex/Invalid/main.c new file mode 100644 index 000000000..ed78da614 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/Invalid/main.c @@ -0,0 +1,21 @@ + +int +fact (int n) +{ + if (n == 0) + { + return 1; + } + return n * fact (n - 1); +} + +int +main (void) +{ + return + /* ***************ON "In statement"*/ + fact (0) == 1 + /* ***************OFF)*/ + ? 0 + : 1; +} diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Invalid/test.py b/testsuite/tests/ext_annotations/gen/c_ex/Invalid/test.py new file mode 100644 index 000000000..b92f74288 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/Invalid/test.py @@ -0,0 +1,44 @@ +""" +Check that gnatcov correctly rejects exemption markers intersecting SCOs. +""" + +# TODO: This may need to be moved to a Robustness chapter instead when +# proper qualification tests are written for C. + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, Exempt_Region, generate_annotations +from SUITE.gprutils import GPRswitches + +# Generate external annotations, they will be generated in a dedicated +# temporary directory +annotations = generate_annotations( + [Exempt_Region("main.c", "16:5", "18:31", "In statement")] +) + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.c"], srcdirs=[".."])), + extra_coverage_args=["--annotate=xcov"], + extra_instr_args=[f"--external-annotations={annotations}"], + covlevel="stmt+mcdc", + mains=["main"], + trace_mode="src", + tolerate_instrument_messages="Exemption .* intersects", +) + +check_xcov_reports( + "obj", + {"main.c.xcov": {"+": {7, 15}, "!": {5, 17}, "-": {9}}}, +) + +thistest.fail_if_no_match( + what="Unexpected instrument output", + regexp=r"(warning: Exemption annotation at main\.c:\d+:\d+ intersects a" + r" coverage obligation \(.*\), ignoring it\n)+", + actual=contents_of("instrument.log"), +) + +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.c b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.c new file mode 100644 index 000000000..6bdd7e67e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.c @@ -0,0 +1,35 @@ +#include "pkg.h" +#include + +#define NOT(A) !A + +// ***************** "whole function single line comment" // # exempt_at +bool // # exempt_at +andThen (bool a, bool b) // # exempt_at +{ // # exempt_at + return a && b; // # exempt_at +} // # exempt_at +// ****************** // # exempt_at + +bool +orElse (bool a, bool b) +{ + // ***************** "if stmt" // # exempt_oe + if (a || b) // # exempt_oe_v1 + { // # exempt_oe + // ****************** // # exempt_oe + return true; + } + else + { + return false; + } +} + +bool +negation (bool a) +{ + /* ***************** "single statement, multiline comment"*/ // # exempt_neg + return NOT (a); // # exempt_neg_v1 + /* ****************** */ // # exempt_neg +} diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.h b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.h new file mode 100644 index 000000000..419e178b8 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/pkg.h @@ -0,0 +1,12 @@ +#ifndef PKG_H +#define PKG_H + +#include + +extern bool andThen (bool a, bool b); + +extern bool orElse (bool a, bool b); + +extern bool negation (bool a); + +#endif diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/test_exemptions.c b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/test_exemptions.c new file mode 100644 index 000000000..10627e6ab --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/src/test_exemptions.c @@ -0,0 +1,20 @@ +#include "pkg.h" + +int +main (void) +{ + volatile bool x = orElse (false, true); + x = orElse (false, false); + x = andThen (true, true); + x = andThen (true, false); + x = andThen (false, false); + return 0; +} + +//# pkg.c +// +// /exempt_at/ l# ## x0 +// /exempt_oe/ l* ## x+ +// /exempt_oe_v1/ l= ## Xc! +// /exempt_neg/ l* ## x+ +// /exempt_neg_v1/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py new file mode 100644 index 000000000..7952ccf62 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py @@ -0,0 +1,37 @@ +""" +Test simple exemption cases in C sources. This is a copy of +tests/C/mcdc/Exemptions/Nominal, with the comments modified +to not be recognized, and external annotations being generated +instead. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest + +from SUITE.tutils import ( + Exempt_On, + Exempt_Off, + Exempt_Region, + generate_annotations, +) + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = [ + Exempt_Region( + "src/pkg.c", "6:4", "12:22", "whole function single line comment" + ), + Exempt_On("src/pkg.c", "17:4", None, "if stmt"), + Exempt_Off("src/pkg.c", "20:7", None), + Exempt_Region( + "src/pkg.c", "32:3", "34:24", "whole function single line comment" + ), +] + +annot_file = generate_annotations(annotations) + +# Check we get the expected results +TestCase(category=CAT.mcdc).run( + covcontrol=CovControl(covoptions=[f"--external-annotations={annot_file}"]) +) +thistest.result() diff --git a/testsuite/tests/ext_annotations/gen/c_ex/extra.opt b/testsuite/tests/ext_annotations/gen/c_ex/extra.opt new file mode 100644 index 000000000..25d72a22d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/c_ex/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD exemptions not supported in bin traces for C diff --git a/testsuite/tests/ext_annotations/gen/readme.md b/testsuite/tests/ext_annotations/gen/readme.md new file mode 100644 index 000000000..85272418d --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/readme.md @@ -0,0 +1,22 @@ +This directory contains a copy of a subset of some tests related to exemptions, +and buffer annotations. The modifications compared to the original tests is +that the annotations in sources (pragmas and comments) have been neutralized, +and the test.py scripts have been augmented to include invocations to the +gnatcov add-annotation command to generate equivalent annotations. + +The test results are supposed to be equivalent. + +The purpose of these tests is to ensure that using external annotation file and +the "gnatcov add-annotation" command can be used in place of in-source +annotations. + + +Test directory names may have been shortened to avoid path limit issues in +Windows configs. + +Ada pragmas for exemptions and coverage disabling are replaced by an annotate +pragma for a fictional tool so that the pragmas still generates a SCO + +C/C++ exemption comments are simply emptied. + +Buffer dump comments / pragmas are entirely removed. diff --git a/testsuite/tests/ext_annotations/selective_cov/Ada/annotations.toml b/testsuite/tests/ext_annotations/gen/selective_cov/Ada/annotations.toml similarity index 100% rename from testsuite/tests/ext_annotations/selective_cov/Ada/annotations.toml rename to testsuite/tests/ext_annotations/gen/selective_cov/Ada/annotations.toml diff --git a/testsuite/tests/ext_annotations/selective_cov/Ada/src/test_main.adb b/testsuite/tests/ext_annotations/gen/selective_cov/Ada/src/test_main.adb similarity index 100% rename from testsuite/tests/ext_annotations/selective_cov/Ada/src/test_main.adb rename to testsuite/tests/ext_annotations/gen/selective_cov/Ada/src/test_main.adb diff --git a/testsuite/tests/ext_annotations/selective_cov/Ada/test.py b/testsuite/tests/ext_annotations/gen/selective_cov/Ada/test.py similarity index 100% rename from testsuite/tests/ext_annotations/selective_cov/Ada/test.py rename to testsuite/tests/ext_annotations/gen/selective_cov/Ada/test.py diff --git a/testsuite/tests/ext_annotations/selective_cov/C/src/cons_a_b.txt b/testsuite/tests/ext_annotations/gen/selective_cov/C/src/cons_a_b.txt similarity index 100% rename from testsuite/tests/ext_annotations/selective_cov/C/src/cons_a_b.txt rename to testsuite/tests/ext_annotations/gen/selective_cov/C/src/cons_a_b.txt diff --git a/testsuite/tests/ext_annotations/selective_cov/C/src/pkg.h b/testsuite/tests/ext_annotations/gen/selective_cov/C/src/pkg.h similarity index 100% rename from testsuite/tests/ext_annotations/selective_cov/C/src/pkg.h rename to testsuite/tests/ext_annotations/gen/selective_cov/C/src/pkg.h diff --git a/testsuite/tests/ext_annotations/selective_cov/C/src/test_a.c b/testsuite/tests/ext_annotations/gen/selective_cov/C/src/test_a.c similarity index 100% rename from testsuite/tests/ext_annotations/selective_cov/C/src/test_a.c rename to testsuite/tests/ext_annotations/gen/selective_cov/C/src/test_a.c diff --git a/testsuite/tests/ext_annotations/selective_cov/C/src/test_b.c b/testsuite/tests/ext_annotations/gen/selective_cov/C/src/test_b.c similarity index 100% rename from testsuite/tests/ext_annotations/selective_cov/C/src/test_b.c rename to testsuite/tests/ext_annotations/gen/selective_cov/C/src/test_b.c diff --git a/testsuite/tests/ext_annotations/selective_cov/C/test.py b/testsuite/tests/ext_annotations/gen/selective_cov/C/test.py similarity index 68% rename from testsuite/tests/ext_annotations/selective_cov/C/test.py rename to testsuite/tests/ext_annotations/gen/selective_cov/C/test.py index 4e4cf6024..6557a72ba 100644 --- a/testsuite/tests/ext_annotations/selective_cov/C/test.py +++ b/testsuite/tests/ext_annotations/gen/selective_cov/C/test.py @@ -16,6 +16,18 @@ from SCOV.tctl import CAT, CovControl from SCOV.tc import TestCase +from SUITE.tutils import Cov_Off, Cov_On, generate_annotations + +# Annotations to be used, use a mix of Exempt_Region an Exempt_On/Off +annotations = generate_annotations( + [ + Cov_Off("src/pkg.h", "5:3", None), + Cov_On("src/pkg.h", "7:3", None), + Cov_Off("src/pkg.h", "11:3", None), + Cov_On("src/pkg.h", "13:3", None), + ] +) + thistest.options.consolidate = "checkpoints" TestCase( category=CAT.mcdc, @@ -23,6 +35,6 @@ r".* Missing or empty justification for external disabled coverage" r' region annotation ".*"' ), -).run(CovControl(instroptions="--external-annotations=../annotations.toml")) +).run(CovControl(instroptions=f"--external-annotations={annotations}")) thistest.result() diff --git a/testsuite/tests/ext_annotations/selective_cov/extra.opt b/testsuite/tests/ext_annotations/gen/selective_cov/extra.opt similarity index 100% rename from testsuite/tests/ext_annotations/selective_cov/extra.opt rename to testsuite/tests/ext_annotations/gen/selective_cov/extra.opt diff --git a/testsuite/tests/ext_annotations/selective_cov/C/annotations.toml b/testsuite/tests/ext_annotations/selective_cov/C/annotations.toml deleted file mode 100644 index 16c01fbda..000000000 --- a/testsuite/tests/ext_annotations/selective_cov/C/annotations.toml +++ /dev/null @@ -1,43 +0,0 @@ -[cov_off_a] -file="pkg.h" -kind="absolute" -[cov_off_a.matcher] -start_line=5 -start_col=3 -end_line=5 -end_col=20 -[[cov_off_a.annotations]] -purpose="xcov.cov.off" - -[cov_off_b] -file="pkg.h" -kind="absolute" -[cov_off_b.matcher] -start_line=11 -start_col=3 -end_line=11 -end_col=20 -[[cov_off_b.annotations]] -purpose="xcov.cov.off" - -[cov_on_a] -file="pkg.h" -kind="absolute" -[cov_on_a.matcher] -start_line=7 -start_col=3 -end_line=7 -end_col=20 -[[cov_on_a.annotations]] -purpose="xcov.cov.on" - -[cov_on_b] -file="pkg.h" -kind="absolute" -[cov_on_b.matcher] -start_line=13 -start_col=3 -end_line=13 -end_col=20 -[[cov_on_b.annotations]] -purpose="xcov.cov.on" From aae7f42bf93168bbc6fb9372b1d9d3b4b3e8d7a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 11 Sep 2024 15:44:42 +0200 Subject: [PATCH 0946/1483] Document external annotation interface (cherry picked from commit def792f12cc13fe8279589a7e0321a0db65f6906) --- doc/conf.py | 3 + doc/gnatcov/disable_cov.rst | 3 + doc/gnatcov/exemptions.rst | 3 + doc/gnatcov/external_annotations.rst | 401 +++++++++++++++++++++++++++ doc/gnatcov/gnatcov_part.rst | 1 + doc/gnatcov/src_traces.rst | 6 + 6 files changed, 417 insertions(+) create mode 100644 doc/gnatcov/external_annotations.rst diff --git a/doc/conf.py b/doc/conf.py index 462ce446c..c4f1bfdbf 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -72,6 +72,9 @@ .. |gcvcnv| replace:: :command:`gnatcov` :command:`convert` .. |gcvdsp| replace:: :command:`gnatcov` :command:`disp-routines` .. |gcvmap| replace:: :command:`gnatcov` :command:`map-routines` +.. |gcvaddan| replace:: :command:`gnatcov` :command:`add-annotation` +.. |gcvdelan| replace:: :command:`gnatcov` :command:`delete-annotation` +.. |gcvshoan| replace:: :command:`gnatcov` :command:`show-annotations` .. |gdas| replace:: {} .. |gcp| replace:: GNATcoverage diff --git a/doc/gnatcov/disable_cov.rst b/doc/gnatcov/disable_cov.rst index a7735533e..5c996ceae 100644 --- a/doc/gnatcov/disable_cov.rst +++ b/doc/gnatcov/disable_cov.rst @@ -67,6 +67,9 @@ region: // GNATCOV_COV_ON } +It is also possible to define disabled coverage regions from external annotation +files, see :ref:`ext_annot` for more information. + Consolidating traces with varying disabled coverage regions =========================================================== diff --git a/doc/gnatcov/exemptions.rst b/doc/gnatcov/exemptions.rst index ea8753a64..103d5d0e1 100644 --- a/doc/gnatcov/exemptions.rst +++ b/doc/gnatcov/exemptions.rst @@ -83,6 +83,9 @@ to exempt a decision only partially: Such markers are ignored by |gcvins|, after emitting a warning. +It is also possible to define exemption regions trough external annotation +files, see :ref:`ext_annot` for more information. + Reporting about coverage exemptions =================================== diff --git a/doc/gnatcov/external_annotations.rst b/doc/gnatcov/external_annotations.rst new file mode 100644 index 000000000..5dd6359e6 --- /dev/null +++ b/doc/gnatcov/external_annotations.rst @@ -0,0 +1,401 @@ +.. _ext_annot: + +########################### +External source annotations +########################### + +In case modifying the sources is not possible or desirable, it is possible to +generate annotations in separate files, which can be passed to |gcvins| or +|gcvcov| to modify the behavior of the instrumenter or of the coverage +analysis. + +Annotations loaded from an external file can be used along in-source +annotations, however in case of conflicts, the annotations defined in the +sources will always be prioritized. + +External annotations are stored in TOML files, which can be manipulated through +three |gcv| commands, |gcvaddan|, |gcvdelan| and |gcvshoan|, to respectively +add a new annotations, delete an existing annotation from the files, or show +the annotations that are stored in the files. + +Once generated, annotation files should be passed to the |gcvins| or |gcvcov| +commands with the :cmd-option:`--external-annotations` switch for them to be +taken into account by |gcv|. + +.. _gen_ext: + +Generating external annotations +############################### + +The |gcvaddan| command can be used to create an annotation, tied to a specific +source location. + +The help section for the |gcvaddan| command can be displayed by running +``gnatcov add-annotation --help``. Its synopsis is:: + + gnatcov add-annotation --kind=KIND [--external-annotations=FILENAME] --output=OUTPUT_FILENAME [OPTIONS] FILENAME + +Some notable command line options are: + +:cmd-option:`--output`: + Name of the file to the newly created annotation will be written. If there + already is a file, it will be overwritten. + +:cmd-option:`--external-annotations`, |rarg|: + Loads pre-existing annotations from `FILENAME`. They are used to check that + the new annotation does not conflict with any pre-existing one. The loaded + annotations are all written to the output file specified through + :cmd-option:`--output`. + +:cmd-option:`FILENAME`, positional: + Filename to which the new annotation should apply. There are special + considerations to keep in mind when specifying the name of the file to be + annotated, see :ref:`ext_annot_relocs` + +:cmd-option:`--annotation-id=IDENTIFIER`, optional: + Unique identifier for the new annotation. If not specified, |gcv| will + generate one based on the kind of annotation and the designated location. + + This identifier must be unique across all external annotation files passed to + any |gcv| invocation, and is used in diagnostics, or in the other annotation + manipulation commands, |gcvdelan| and |gcvshoan| to uniquely designate an + annotation. + +:cmd-option:`--force`, optional: + Force overwriting of a pre-existing annotation for the same location, or + with the same identifier. If not specified, gnatcov will emit an error and + abort the annotation generation. The output file will not be modified. + +The required command line switches depend on the value of the +:cmd-option:`--kind`, conveying the kind annotation to be generated, which +correspond to the annotations kinds supported in +``pragma Annotate (Xcov, KIND, ..)``. The required switches are detailed in the +help text for the |gcvaddan| command, and are detailed bellow. A switch in +brackets signifies that the switch is optional, otherwise the switch is required +and |gcvaddan| will emit an error if not found on the command line. + +* :cmd-option:`--kind=Exempt_On`: + Generate an annotation symbolizing the beginning of an + :ref:`exempted region `. + + :cmd-option:`--location=LINE:COL`: + Source location for the beginning of the exempted region. + + :cmd-option:`--justification=MESSAGE`: + Justification message to be displayed in the coverage reports for the + exempted region. + +* :cmd-option:`--kind=Exempt_Off`: + Generate an annotation symbolizing the end of an exempted region. + + :cmd-option:`--location=LINE:COL`: + Source location for the end of the exempted region. + +* :cmd-option:`--kind=Exempt_Region`: + Generate an annotation symbolizing an entire exempted region. + + :cmd-option:`--start-location=LINE:COL`: + Source location for the beginning of the exempted region. + + :cmd-option:`--end-location=LINE:COL`: + Source location for the end of the exempted region. + + :cmd-option:`--justification=MESSAGE`: + Justification message to be displayed in the coverage reports for the + exempted region. + +* :cmd-option:`--kind=Cov_Off`: + Generate an annotation symbolizing the beginning of a :ref:`disabled + coverage region `. + + :cmd-option:`--location=LINE:COL`: + Source location for the beginning of the disabled coverage region. + + :cmd-option:`--justification=MESSAGE`: + Justification message for the disabled coverage region, to be displayed + in the coverage reports. + +* :cmd-option:`--kind=Cov_On`: + Generate an annotation symbolizing the end of a disabled coverage region. + + :cmd-option:`--location=LINE:COL`: + Location for the end of the disabled coverage region. + +* :cmd-option:`--kind=Dump_Buffers`: + Generate an annotation instructing |gcv| to insert a + :ref:`buffer dump procedure call ` at the specified location. + This is only taken into account when the selected dump trigger is + ``manual``, see :ref:`Dump_Triggers` for more information concerning the + dump triggers. + + :cmd-option:`--location=LINE:COL`: + Source location at which the buffer dump procedure call should be + inserted. + + :cmd-option:`[--dump-filename-prefix=TEXT]`: + Optional trace filename prefix to be passed to the buffer dump procedure + call. This will be textually passed as argument to the buffer dump, and + must be an expression evaluating to a null-terminated ``char *``. As + such, if the prefix to be used is a literal string, the argument passed + to ``--dump-filename-prefix`` must contain quotes + (e.g. ``--dump-filename-prefix='"my_trace"'``). + + :cmd-option:`[--annotate-after]`: + If specified, instruct |gcv| to insert the buffer dump procedure + **after** the statement designated by the annotation. See + :ref:`buf_semantics` for more details on the meaning of this option. + +* :cmd-option:`--kind=Reset_Buffers`: + Generate an annotation instructing gnatcov to insert a :ref:`coverage buffer + reset procedure call ` at the specified location. This is only + taken into account when the selected dump trigger is ``manual``, see + :ref:`Dump_Triggers` for more information concerning the dump triggers. + + :cmd-option:`--location=LINE:COL`: + Location at which the buffer reset procedure call should be inserted. + + :cmd-option:`[--annotate-after]`: + If specified, instruct |gcv| to insert the buffer reset procedure + **after** the statement designated by the annotation. See + :ref:`buf_semantics` for more details on the meaning of this option. + +.. _buf_semantics: + +Semantics of buffer manipulation annotations +-------------------------------------------- + +Due to the differences in instrumentation technology used by |gcv| for C/C++ and +Ada, the external annotations concerning buffer dump/reset have different +semantics that need to be taken into account when first annotation sources. + +For C and C++ sources, |gcv| will insert the buffer dump/reset call at the exact +location designated by the annotation, without validating if the resulting code +is legal. It is thus recommended to choose a location corresponding to a +whitespace character, immediately before or after a statement. + +For instance, starting from the following source file: + +.. code-block:: C + :linenos: + + int main(){ + // Execute the core program + do_stuff(); + + // Cleanup temp files + cleanup(); + } + +Creating an annotation as follows:: + + gnatcov add-annotation --kind=Dump_Buffers -o annotations.toml --location=6:3 main.c + +would result in the following invalid code to be generated: + +.. code-block:: C + :linenos: + :emphasize-lines: 6 + + int main(){ + //Execute the core program + do_stuff(); + + // Cleanup temp files + cgnatcov_dump_buffers();leanup(); + } + +Instead, it is better to target any whitespace character before the statement, +as in ``--location=6:2``. + +For Ada sources, |gcv| will locate the inner-most statement list that encloses +the designated location, and insert the procedure call immediately **before** +this statement by default. The ``--annotate-after`` switch can be used to +instruct gnatcov to instead insert the procedure call **after** the designated +statement. This in particular is necessary to add a buffer dump annotation after +the last statement of a list. + +If gnatcov cannot locate a statement list enclosing the designated location, a +warning will be emitted and the annotations will be ignored. + +For instance, starting from the following source file: + +.. code-block:: Ada + :linenos: + + procedure Main is + begin + -- Run the actual program + + Do_Processing; + + -- Cleanup temp files + + Do_Cleanup; + end Main; + +Generating an annotation with:: + + gnatcov add-annotation --kind=Dump_Buffers -o annotations.toml --location=9:15 main.adb + +results in the following source, despite the source location pointing at the end +of the Do_Cleanup procedure call: + +.. code-block:: Ada + :linenos: + :emphasize-lines: 9 + + procedure Main is + begin + -- Run the actual program + + Do_Processing; + + -- Cleanup temp files + + GNATCov_RTS_Dump_Buffers; Do_Cleanup; + end Main; + +To ensure the buffer dump procedure is inserted after the Do_Cleanup call, it is +necessary to pass the ``--annotate-after`` command line switch. + + +.. _ext_annot_relocs: + +File relocation considerations +------------------------------ + +The external file annotation mechanism stores the filename passed to the +|gcvaddan| command in the generated annotation file. When the annotations are +loaded by a |gcvins| or |gcvcov| command invocation, to determine if an +annotation is relevant for any of the processed files, |gcv| checks whether the +full filename of the file being processed ends with the annotation target +filename. It is thus important to only store in the annotation the part of the +filename that will not change between the different |gcv| command invocations. + +This means that relative paths components (e.g. ``./`` or ``../``), and absolute +paths are likely to not be properly recognized. + +The |gcvaddan| command accepts a ``--source-root=PREFIX`` option that will strip +``PREFIX`` from the target filename when generating the annotations. As such, it +is possible to generate an annotation for a file located in a parent directory, +while ensuring the generated annotation will correctly be taken into account in +subsequent |gcv| invocations with the following command line:: + + gnatcov add-annotation [OPTIONS] --source-root="../" ../src/file.adb + +|gcv| can also automatically deduce the appropriate prefix to be stripped from +the filename if a project file is passed to |gcvaddan| with the ``-P`` option. +Note that this only works if the file is unique in the project tree, or if the +file is located in a sub-directory of its project root directory. + + +Deleting a pre-existing annotation +################################## + +The |gcvdelan| command can be used to remove a pre-existing annotation from an +external annotation file. + +The help section for the |gcvaddan| command can be displayed by running +``gnatcov delete-annotation --help``. Its synopsis is:: + + gnatcov delete-annotation --external-annotations=FILENAME --output=OUTPUT_FILENAME --annotation-id=IDENTIFIER + +The semantics of each command line switch is: + +:cmd-option:`--annotation-id=IDENTIFIER`: + Unique IDENTIFIER of the annotation to be deleted.`` + +:cmd-option:`--external-annotations=FILENAME`, |rarg|: + External annotation files from which the annotation will be loaded. + If multiple files are passed to |gcv|, the annotations will be consolidated + together and all written to the output file. + +:cmd-option:`--output=OUTPUT_FILENAME`: + Name of the file where the annotations will be written back after deletion + of the designated annotation. This will overwrite any pre-existing file with + the same OUTPUT_FILENAME. + +Displaying the annotations contained in annotation files +######################################################## + +The command |gcvshoan| can be used to display the annotations contained in +annotation files in a more user-friendly manner. + +The help section for the |gcvaddan| command can be displayed by running +``gnatcov show-annotations --help``. Its synopsis is:: + + gnatcov show-annotations --external-annotations=FILENAME [--kind=KIND] [-P PROJECT] [FILENAMES] + +The semantics of the command line switches are as follow: + +:cmd-option:`--external-annotations=FILENAME`, |rarg|: + External annotation files from which annotations will be loaded + +:cmd-option:`--kind=KIND`, optional: + Only display the annotations of kind KIND. + +:cmd-option:`-P PROJECT`, optional: + Show all annotations applicable to all source files of the project tree + rooted at PROJECT. + +:cmd-option:`FILENAMES`, positional: + Only show the annotations applicable to the listed files. + +Either the ``-P`` command line option or positional filenames must be specified. + +The output format is as follows: + +.. code-block:: + + BASENAME_1: + - START_LOCATION - END_LOCATION; id: IDENTIFIER; kind: KIND; [EXTRA_FIELDS] + - ... + + BASENAME_2: + - ... + +``BASENAME_i`` corresponds to the basename of each file for which there is an +annotation. The each annotation is displayed on each line, starting by the +location range for the annotation. If the annotation only concerns a single +location, the ``END_LOCATION`` field will be identical to the +``START_LOCATION``. The unique identifier of the annotation is then displayed in +place of ``IDENTIFIER``, and the annotation kind is displayed in place of +``KIND``. The ``EXTRA_FIELDS`` concerns options specific to each annotation +kind, and are displayed as a semi-column separated list. See :ref:`gen_ext` for +more details on the extra fields that each annotation kind supports. + +Annotation stability through file modifications +############################################### + +The external annotations generated by the |gcvaddan| command embed varying +levels of information so that the source location designated on the command +line option can be remapped when possible, or invalidated otherwise. + +This depends mainly on the language of the file to be annotated: + +- For Ada sources, the annotation is tied to the inner-most enclosing named + construct, such as a subprogram or a package. If the file is modified outside + of that construct the annotation will be remapped properly. If the enclosing + construct is modified, the annotation will be invalidated. + +- For C sources, the annotations are currently not stable through modifications. + Any modification to the annotated source file will invalidate the annotations. + +If an annotation is invalidated gnatcov will emit a warning stating that the +annotation was ignored, along with its unique identifier. + +The output of the |gcvshoan| command will also display stale annotations, the +format for those annotations will be: + +.. code-block:: + + - STALE ANNOTATION; id: IDENTIFIER; kind: KIND; [EXTRA_FIELDS]; diagnostic: DIAGNOSTIC + +where ``DIAGNOSTIC`` will contain a short explanation of why the entry is stale. + +To fix this, simply replace the entry with an invocation of |gcvaddan|, +specifying the annotation identifier to be replaced, and forcing the +replacement:: + + gnatcov add-annotation --annotation-id=IDENTIFIER --force [OPTIONS] + diff --git a/doc/gnatcov/gnatcov_part.rst b/doc/gnatcov/gnatcov_part.rst index 4b3f0e1e7..51edc9dc9 100644 --- a/doc/gnatcov/gnatcov_part.rst +++ b/doc/gnatcov/gnatcov_part.rst @@ -13,6 +13,7 @@ GNATcoverage User's Guide consolidation exemptions disable_cov + external_annotations gpr gps glossary diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index f8dbc2b07..44299d719 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -287,6 +287,8 @@ For more restricted environments where, say, there is limited file IO available to the program, a ``--dump-channel=base64-stdout`` kind of output is needed in association with the restricted coverage runtime. +.. _manual_dump: + If none of the available automatic triggering option work out well, full control is offered by the ``--dump-trigger=manual`` policy where the instrumenter doesn't actually add any code to main units for emitting the @@ -377,6 +379,7 @@ distinguish between each trace: /* GNATCOV_DUMP_BUFFERS (Undefined) */ } +.. _buff_reset: Resetting coverage information during the execution --------------------------------------------------- @@ -414,6 +417,9 @@ section of the instrumented code runs concurrently to the buffer clear procedure, otherwise the correctness of the corresponding coverage report cannot be guaranteed.** +Both buffer dump indications and buffer reset indications can be specified in +external annotation files, see :ref:`ext_annot` for more information. + .. _instr-tracename: Controlling trace file names From b3515e106702b99b3ee2afc633cdf01c20fcb6fd Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 25 Sep 2024 11:39:11 +0200 Subject: [PATCH 0947/1483] Integrated instrumentation: make sure the library path is valid --- tools/gnatcov/instrument-gcc_wrapper.adb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 488031a77..4bedcb419 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -1072,7 +1072,13 @@ begin & ". Add its directory to the" & " LD_LIBRARY_PATH if this is an" & " instrumented library."); - else + + -- Check if this is an actual path, to safeguard + -- against cases displayed as: + -- + -- => () + + elsif Exists (Lib_Filename) then Add_Coverage_Buffer_Symbols (Create (+Lib_Filename)); end if; From ee288b48346b7adcd9f1f24c7c1952fe26694f18 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 26 Sep 2024 14:41:06 +0200 Subject: [PATCH 0948/1483] gnatcov doc: clarify use of --src-subdirs in the Getting Started section --- doc/gnatcov/getting_started.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/doc/gnatcov/getting_started.rst b/doc/gnatcov/getting_started.rst index 4faa5b3c7..2272c433b 100644 --- a/doc/gnatcov/getting_started.rst +++ b/doc/gnatcov/getting_started.rst @@ -222,8 +222,11 @@ Building the instrumented program then goes like:: This is the same command as for the regular build, with a couple of additional switches to: - * Instruct the builder to search for the instrumented versions of the - sources (``--src-subdirs``), + * Instruct the builder to search for the instrumented versions of the sources + (``--src-subdirs``). Note that, due to the way ``--src-subdirs`` works in + ``gprbuild``, even though |gcvins| creates directories with names derived + from ``*-gnatcov-instr``, the argument to pass to GPRbuild must always be + exactly ``--src-subdirs=gnatcov-instr``. * Provide visibility to the builder over the coverage runtime referenced by the instrumented sources (``--implicit-with``). From 54956f2b4aab074c545f4ec7c9cd0506445db726 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 26 Sep 2024 15:33:37 +0200 Subject: [PATCH 0949/1483] CI: fix the build space in build_docs Recent work that added the "warn-errors" qualifier to the build of gnatdas-doc also implicitly changed the name of its build space, so commands using a hardcoded build space name were broken since then. Use the automatically computed build space name to avoid this problem in the future. --- .gitlab-ci.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9b06dba95..81eb1efac 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -66,8 +66,9 @@ build_docs: when: always script: - *basic_setup - - anod build gnatdas-doc --qualifier warn-errors --latest - - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/gnatdas-doc/install/share/doc/gnatdas/ $CI_PROJECT_DIR + - anod build gnatdas-doc -Qwarn-errors --latest + - DOC_BSN=$(anod eval gnatdas-doc -Qwarn-errors build_space_name) + - mv $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$DOC_BSN/install/share/doc/gnatdas/ $CI_PROJECT_DIR artifacts: when: always From 25cfaedc9f6d873926eccdb8d63768c4b682de4f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 27 Sep 2024 08:02:29 +0000 Subject: [PATCH 0950/1483] Build all gnatcov parts with debug information --- tools/gnatcov/gnatcov.gpr | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index 96e80c35c..ea2765b19 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -202,10 +202,10 @@ project Gnatcov is package Compiler is Ada_Common_Switches := - ("-gnat12", "-gnatwa", "-gnatyg"); + ("-gnat12", "-gnatwa", "-gnatyg", "-g"); C_Common_Switches := - ("-DTARGET_BITS=" & Bits, "-Wall", "-Wextra", "-std=c99"); + ("-DTARGET_BITS=" & Bits, "-Wall", "-Wextra", "-std=c99", "-g"); Mode_Switches := (); Ada_Mode_Switches := (); @@ -214,7 +214,7 @@ project Gnatcov is case Build_Mode is when "dev" => - Mode_Switches := ("-O0", "-g"); + Mode_Switches := ("-O0"); Ada_Mode_Switches := ("-gnata", "-gnatwe"); C_Mode_Switches := ("-Werror"); CPP_Mode_Switches := ("-Werror"); @@ -226,7 +226,7 @@ project Gnatcov is when "boot" => Mode_Switches := - ("-O1", "-fdump-scos", "-fpreserve-control-flow", "-g"); + ("-O1", "-fdump-scos", "-fpreserve-control-flow"); C_Mode_Switches := ("-DNDEBUG"); CPP_Mode_Switches := ("-DNDEBUG"); end case; From 35002544f17534a1e134f510d854345f33d30a64 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 24 Sep 2024 08:34:20 +0000 Subject: [PATCH 0951/1483] sc_obligations.adb: minor reformattings --- tools/gnatcov/sc_obligations.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 2258228e6..6174d413d 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -5390,7 +5390,7 @@ package body SC_Obligations is ----------------------------------- procedure Inc_Violation_Exemption_Count (Sloc : Source_Location) is - E : ALI_Annotation renames + E : ALI_Annotation renames CU_Vector.Reference (Comp_Unit (Sloc.Source_File)) .ALI_Annotations.Reference (Sloc); begin @@ -5402,7 +5402,7 @@ package body SC_Obligations is ----------------------------------- procedure Inc_Undet_Cov_Exemption_Count (Sloc : Source_Location) is - E : ALI_Annotation renames + E : ALI_Annotation renames CU_Vector.Reference (Comp_Unit (Sloc.Source_File)) .ALI_Annotations.Reference (Sloc); begin From f33a030cec108ae09bd027c932956355c44c0657 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 24 Sep 2024 08:35:27 +0000 Subject: [PATCH 0952/1483] Fix handling of exemption violations for report + another format Exemption violations are handled differently when generating a "report" format. To achieve this, conditional code checks this case with a "not Annotation (Annotate_Report)" condition. That condition was fine at the time when "gnatcov coverage" could generate only one annotation format at a time, however nowadays a single invocation can generate multiple annotation formats, so multiple booleans in the "Annotation" array can be set to True simultaneously: "Annotation (Annotate_Report)" may be True even when we are generating a non-"report" format such as "xcov". As a consequence, code that is meant to be executed only when generating a non-"report" format is skipped at the wrong time, and so exemption violations are incorrectly processed. This commit introduces a new Pretty_Printer primitive so that conditional code can check the format that is currently generated (instead of the formats that will eventually be generated throughout the execution of "gnatcov coverage") and uses it to fix the handling of exemption violations when multiple reports are generated. --- .../tests/334-unexpected-exemption/main.adb | 6 ++++ .../tests/334-unexpected-exemption/proc.adb | 16 +++++++++ .../tests/334-unexpected-exemption/test.opt | 1 + .../tests/334-unexpected-exemption/test.py | 35 +++++++++++++++++++ tools/gnatcov/annotations-cobertura.adb | 4 +++ tools/gnatcov/annotations-dynamic_html.adb | 4 +++ tools/gnatcov/annotations-html.adb | 4 +++ tools/gnatcov/annotations-report.adb | 4 +++ tools/gnatcov/annotations-sarif.adb | 4 +++ tools/gnatcov/annotations-xcov.adb | 4 +++ tools/gnatcov/annotations-xml.adb | 4 +++ tools/gnatcov/annotations.adb | 2 +- tools/gnatcov/annotations.ads | 15 ++++++++ 13 files changed, 102 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/334-unexpected-exemption/main.adb create mode 100644 testsuite/tests/334-unexpected-exemption/proc.adb create mode 100644 testsuite/tests/334-unexpected-exemption/test.opt create mode 100644 testsuite/tests/334-unexpected-exemption/test.py diff --git a/testsuite/tests/334-unexpected-exemption/main.adb b/testsuite/tests/334-unexpected-exemption/main.adb new file mode 100644 index 000000000..aab012f4a --- /dev/null +++ b/testsuite/tests/334-unexpected-exemption/main.adb @@ -0,0 +1,6 @@ +with Proc; + +procedure Main is +begin + Proc (0); +end Main; diff --git a/testsuite/tests/334-unexpected-exemption/proc.adb b/testsuite/tests/334-unexpected-exemption/proc.adb new file mode 100644 index 000000000..1a74dd145 --- /dev/null +++ b/testsuite/tests/334-unexpected-exemption/proc.adb @@ -0,0 +1,16 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Proc (N : Natural) is +begin + if N = 1 then + Put_Line ("got one argument"); + elsif N in 2 .. 10 then + pragma Annotate (Xcov, Exempt_On, "2 .. 10"); + Put_Line ("got between 2 and 10 arguments"); + pragma Annotate (Xcov, Exempt_Off); + else + pragma Annotate (Xcov, Exempt_On, "others"); + Put_Line ("other cases"); + pragma Annotate (Xcov, Exempt_Off); + end if; +end Proc; diff --git a/testsuite/tests/334-unexpected-exemption/test.opt b/testsuite/tests/334-unexpected-exemption/test.opt new file mode 100644 index 000000000..d53c552fd --- /dev/null +++ b/testsuite/tests/334-unexpected-exemption/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Cannot compile pragmas marking begin and end of exempted regions diff --git a/testsuite/tests/334-unexpected-exemption/test.py b/testsuite/tests/334-unexpected-exemption/test.py new file mode 100644 index 000000000..80ffb13ce --- /dev/null +++ b/testsuite/tests/334-unexpected-exemption/test.py @@ -0,0 +1,35 @@ +""" +Check that --annotate=xcov,report produces expected '*' lines for +exempted-and-uncovered code. It used to generate '#' lines +(exempte-and-covered) instead. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov,report", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5}}, + "proc.adb.xcov": { + "+": {5, 7}, + "-": {6}, + "#": {12, 13, 14}, + "*": {8, 9, 10}, + }, + }, +) + +thistest.result() diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb index e568ad580..14bc43f10 100644 --- a/tools/gnatcov/annotations-cobertura.adb +++ b/tools/gnatcov/annotations-cobertura.adb @@ -66,6 +66,10 @@ package body Annotations.Cobertura is end record; -- Pretty printer type for the Cobertura annotation format + overriding function Format + (Pp : Cobertura_Pretty_Printer) return Annotation_Format_Family + is (Annotate_Cobertura); + type Rate_Type is digits 3; function Img (R : Rate_Type) return String; diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 299ee9472..69c6d462d 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -130,6 +130,10 @@ package body Annotations.Dynamic_Html is end record; + overriding function Format + (Pp : Dynamic_Html) return Annotation_Format_Family + is (Annotate_Html); + ----------------------------------------- -- Dynamic_Html's primitive operations -- -- (inherited from Pretty_Printer) -- diff --git a/tools/gnatcov/annotations-html.adb b/tools/gnatcov/annotations-html.adb index 38e68d16a..e6bdfc4e8 100644 --- a/tools/gnatcov/annotations-html.adb +++ b/tools/gnatcov/annotations-html.adb @@ -64,6 +64,10 @@ package body Annotations.Html is -- Prefix to use for titles in generated HTML documents end record; + overriding function Format + (Pp : Html_Pretty_Printer) return Annotation_Format_Family + is (Annotate_Html); + ------------------------------------------------ -- Html_Pretty_Printer's primitive operations -- -- (inherited from Pretty_Printer) -- diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 3654ac26b..32e025bbb 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -119,6 +119,10 @@ package body Annotations.Report is -- Whether to add a section for the list of names for units of interest end record; + overriding function Format + (Pp : Report_Pretty_Printer) return Annotation_Format_Family + is (Annotate_Report); + procedure Chapter (Pp : in out Report_Pretty_Printer'Class; Title : String); diff --git a/tools/gnatcov/annotations-sarif.adb b/tools/gnatcov/annotations-sarif.adb index 640868c9d..6fd0a7fa1 100644 --- a/tools/gnatcov/annotations-sarif.adb +++ b/tools/gnatcov/annotations-sarif.adb @@ -74,6 +74,10 @@ package body Annotations.Sarif is end record; -- Pretty printer for the SARIF annotation format + overriding function Format + (Pp : Sarif_Pretty_Printer) return Annotation_Format_Family + is (Annotate_Sarif); + ------------------------------------------------- -- Sarif_Pretty_Printer's primitive operations -- -- (inherited from Pretty_Printer) -- diff --git a/tools/gnatcov/annotations-xcov.adb b/tools/gnatcov/annotations-xcov.adb index e064843cf..e49578153 100644 --- a/tools/gnatcov/annotations-xcov.adb +++ b/tools/gnatcov/annotations-xcov.adb @@ -35,6 +35,10 @@ package body Annotations.Xcov is -- e.g. hello.adb.xcov for hello.adb. end record; + overriding function Format + (Pp : Xcov_Pretty_Printer) return Annotation_Format_Family + is (Annotate_Xcov); + ------------------------------------------------ -- Xcov_Pretty_Printer's primitive operations -- -- (inherited from Pretty_Printer) -- diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index afa2f53ed..187513d90 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -68,6 +68,10 @@ package body Annotations.Xml is -- for the forthcoming lines end record; + overriding function Format + (Pp : Xml_Pretty_Printer) return Annotation_Format_Family + is (Annotate_Xml); + -------------------- -- XML generation -- -------------------- diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 7e40dd18b..e52525f53 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -422,7 +422,7 @@ package body Annotations is -- specifically in Annotation.Report. if LI.Exemption /= Slocs.No_Location - and then not Annotation (Annotate_Report) + and then Pp.Format /= Annotate_Report then if S in Not_Covered .. Partially_Covered then Inc_Violation_Exemption_Count (LI.Exemption); diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 6b5e1b8ac..0edcdd82c 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -53,6 +53,17 @@ package Annotations is Annotate_Report, Annotate_Sarif, Annotate_Unknown); + subtype Annotation_Format_Family is Annotation_Format + with Static_Predicate => + Annotation_Format_Family in + Annotate_Asm + | Annotate_Xcov + | Annotate_Static_Html + | Annotate_Html + | Annotate_Cobertura + | Annotate_Xml + | Annotate_Report + | Annotate_Sarif; function To_Annotation_Format (Option : String) return Annotation_Format; -- Convert annotation format option to Annotation_Format value @@ -126,6 +137,10 @@ private Context : Coverage.Context_Access; end record; + function Format (Pp : Pretty_Printer) return Annotation_Format_Family + is abstract; + -- Return the family of annotation formats that Pp generates + procedure Pretty_Print_Start (Pp : in out Pretty_Printer) is null; -- Called once at the beginning of the process From a7e0891760ce9254955bab2217fd24276fcfe105 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 24 Sep 2024 08:54:50 +0000 Subject: [PATCH 0953/1483] Reset exemption counters between each report generation --- .../tests/334-unexpected-exemption/test.py | 24 +++++++++++++++++-- tools/gnatcov/annotations.adb | 5 ++++ tools/gnatcov/sc_obligations.adb | 19 +++++++++++++++ tools/gnatcov/sc_obligations.ads | 5 ++++ 4 files changed, 51 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/334-unexpected-exemption/test.py b/testsuite/tests/334-unexpected-exemption/test.py index 80ffb13ce..9e93dca0c 100644 --- a/testsuite/tests/334-unexpected-exemption/test.py +++ b/testsuite/tests/334-unexpected-exemption/test.py @@ -6,7 +6,7 @@ from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest -from SUITE.cutils import Wdir +from SUITE.cutils import Wdir, lines_of from SUITE.tutils import gprfor from SUITE.gprutils import GPRswitches @@ -17,8 +17,15 @@ gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), covlevel="stmt", mains=["main"], - extra_coverage_args=["-axcov,report", "--output-dir=xcov"], + extra_coverage_args=[ + "-axcov,report", + "--output-dir=xcov", + "-o", + "report.txt", + ], ) + +# Check that the xcov report contains the expected '*' and '#' lines check_xcov_reports( "xcov", { @@ -32,4 +39,17 @@ }, ) +# Check that the "report" report has the right count for exempted violations +lines = [ + line + for line in lines_of("report.txt") + if line.startswith("proc.adb:") and "exempted violation" in line +] +thistest.fail_if_not_equal( + 'Exempted violations in the "report" report', + "proc.adb:8:7-10:7: 1 exempted violation, justification:" + "\nproc.adb:12:7-14:7: 0 exempted violation, justification:", + "\n".join(lines), +) + thistest.result() diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index e52525f53..d51780795 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -486,6 +486,11 @@ package body Annotations is -- Start of processing for Generate_Report begin + -- Report generation increments counters for exemptions. Reset them + -- before generating a report so that we do not start with counter + -- values from a previously generated report. + + Reset_Exemption_Counters; if Clean_Pattern /= No_Cleaning then Clean_Dir (Get_Output_Dir, Clean_Pattern); diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 6174d413d..1b1486782 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -5409,6 +5409,25 @@ package body SC_Obligations is E.Undetermined_Cov_Count := E.Undetermined_Cov_Count + 1; end Inc_Undet_Cov_Exemption_Count; + ------------------------------ + -- Reset_Exemption_Counters -- + ------------------------------ + + procedure Reset_Exemption_Counters is + use ALI_Annotation_Maps; + begin + for CU of CU_Vector loop + for Cur in CU.ALI_Annotations.Iterate loop + declare + A : ALI_Annotation renames CU.ALI_Annotations.Reference (Cur); + begin + A.Violation_Count := 0; + A.Undetermined_Cov_Count := 0; + end; + end loop; + end loop; + end Reset_Exemption_Counters; + -------------- -- Load_ALI -- -------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 823e637a7..048ff93f4 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -233,6 +233,11 @@ package SC_Obligations is -- Increment the exempted line/message undetermined coverage items counter -- for exemption at Sloc. + procedure Reset_Exemption_Counters; + -- Reset all exemption-related counters in all known compilation units. + -- Since these counters are computed during report generation, we need to + -- reset the counters between each generated report. + procedure Load_ALI (ALI_Filename : String); -- Load ALI information for Filename, without SCOs From 6d88d79cfd6400fc73abf6768ee7e2a169b96d04 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 24 Sep 2024 09:51:34 +0000 Subject: [PATCH 0954/1483] .gitignore: add ddecision_* temporary directories --- testsuite/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/.gitignore b/testsuite/.gitignore index 37d8630f9..5f8c3ed1b 100644 --- a/testsuite/.gitignore +++ b/testsuite/.gitignore @@ -1,6 +1,7 @@ d_* datc_* datcc_* +ddecision_* m_* s_* u_* From 5ea1fc52f43d9cc3cb90491a7bf2c4a8b3d597fb Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 25 Sep 2024 17:57:54 +0000 Subject: [PATCH 0955/1483] Refactor exception message formatting Create a function to generalize the inclusion of extra exception information (like call stacks) to formatted exception messages to be conditionned to the activation of the MISC trace and refactor the codebase to use this function. --- tools/gnatcov/gnatcov_bits_specific.adb | 5 ++-- tools/gnatcov/instrument-ada_unit.adb | 39 ++++++++++++------------- tools/gnatcov/sc_obligations.adb | 4 +-- tools/gnatcov/ss_annotations.adb | 4 +-- tools/gnatcov/switches.adb | 26 +++++++++++++++-- tools/gnatcov/switches.ads | 6 ++++ 6 files changed, 51 insertions(+), 33 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 59ddd9223..706b9e79f 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -18,7 +18,6 @@ with Ada.Containers; use Ada.Containers; with Ada.Directories; use Ada.Directories; -with Ada.Exceptions; with Ada.IO_Exceptions; with Ada.Strings.Fixed; with Ada.Strings.Maps; @@ -1894,7 +1893,7 @@ begin when E : Binary_Files.Error => Fatal_Error ("Cannot open ELF file " & Exe_Name & " for trace file " & Trace_File_Name & ": " - & Ada.Exceptions.Exception_Message (E)); + & Switches.Exception_Info (E)); end Open_Exec_For_Trace; ------------------ @@ -2563,7 +2562,7 @@ exception when Error : Binary_Files.Error | Ada.IO_Exceptions.Name_Error => - Outputs.Error (Ada.Exceptions.Exception_Message (Error)); + Outputs.Error (Switches.Exception_Info (Error)); Project.Finalize; -- Each chunk of code with "raise" statements for Xcov_Exit_Exc exceptions diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index b7c7465e7..13c2093c1 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -20,7 +20,6 @@ with Ada.Characters.Conversions; use Ada.Characters.Conversions; with Ada.Characters.Handling; with Ada.Directories; with Ada.Containers; use Ada.Containers; -with Ada.Exceptions; with Ada.Finalization; with Ada.Strings.Wide_Wide_Fixed; pragma Warnings (Off, "* is an internal GNAT unit"); @@ -2842,7 +2841,7 @@ package body Instrument.Ada_Unit is Report (Node => Common_Nodes.N, Msg => "Could not find previous declaration for the" & " expression function: " - & Ada.Exceptions.Exception_Information (Exc), + & Switches.Exception_Info (Exc), Kind => Low_Warning); end; else @@ -2970,7 +2969,7 @@ package body Instrument.Ada_Unit is Report (Node => N, Msg => "Could not determine if expression function is a" & " primitive: " - & Ada.Exceptions.Exception_Information (Exc), + & Switches.Exception_Info (Exc), Kind => Warning); return False; end; @@ -3004,7 +3003,7 @@ package body Instrument.Ada_Unit is Msg => "Could not determine the semantic parent of the" & " expression function or the semantic parent of its" & " previous declaration: " - & Ada.Exceptions.Exception_Information (Exc), + & Switches.Exception_Info (Exc), Kind => Warning); return False; end; @@ -3031,7 +3030,7 @@ package body Instrument.Ada_Unit is Report (Node => Common_Nodes.N, Msg => "Could not determine the return type of the" & " expression function: " - & Ada.Exceptions.Exception_Information (Exc), + & Switches.Exception_Info (Exc), Kind => Warning); return False; end Augmented_EF_Needs_Wrapper_Package; @@ -3073,7 +3072,7 @@ package body Instrument.Ada_Unit is (UIC, EF, "failed to determine referenced declaration: " - & Ada.Exceptions.Exception_Information (Exc), + & Switches.Exception_Info (Exc), Warning); return Into; end Process_Node; @@ -3106,9 +3105,7 @@ package body Instrument.Ada_Unit is Report (UIC, Common_Nodes.N, "failed to determine return type of expression function: " - & (if Switches.Misc_Trace.Is_Active - then Ada.Exceptions.Exception_Message (Exc) - else Ada.Exceptions.Exception_Information (Exc)), + & Switches.Exception_Info (Exc), Low_Warning); return False; end Return_Type_Is_Controlling; @@ -3197,7 +3194,7 @@ package body Instrument.Ada_Unit is Report (Node => Ret_Node, Msg => "Unable to determine to which body this return statment" - & "applies: " & Ada.Exceptions.Exception_Information (Exc), + & "applies: " & Switches.Exception_Info (Exc), Kind => Low_Warning); -- Inserting an extranous Dump_Buffer call isn't really a problem @@ -3224,7 +3221,7 @@ package body Instrument.Ada_Unit is Report (Node => Decl, Msg => "Could not find the parent package: " - & Ada.Exceptions.Exception_Information (Exc), + & Switches.Exception_Info (Exc), Kind => Warning); return No_Basic_Decl; end Parent_Decl; @@ -7365,7 +7362,7 @@ package body Instrument.Ada_Unit is when E : Property_Error => Report (Node => N, Msg => "Could not determine if decl is ghost: " - & Ada.Exceptions.Exception_Information (E), + & Switches.Exception_Info (E), Kind => Low_Warning); return False; @@ -7378,7 +7375,7 @@ package body Instrument.Ada_Unit is when E : Property_Error => Report (Node => N, Msg => "Could not determine if stmt is ghost: " - & Ada.Exceptions.Exception_Information (E), + & Switches.Exception_Info (E), Kind => Low_Warning); return False; @@ -7397,7 +7394,7 @@ package body Instrument.Ada_Unit is when E : Property_Error => Report (Node => N, Msg => "Could not resolve the previous declaration: " - & Ada.Exceptions.Exception_Information (E), + & Switches.Exception_Info (E), Kind => Warning); return No_Basic_Decl; end Safe_Previous_Part_For_Decl; @@ -7589,7 +7586,7 @@ package body Instrument.Ada_Unit is Report (UIC, E, "failed to determine expression type: " - & Ada.Exceptions.Exception_Information (Exc), + & Switches.Exception_Info (Exc), Warning); end; @@ -7612,7 +7609,7 @@ package body Instrument.Ada_Unit is Report (E, "failed to determine whether this is a static expression: " - & Ada.Exceptions.Exception_Information (Exc), + & Switches.Exception_Info (Exc), Low_Warning); return False; end Is_Static_Expr; @@ -7630,7 +7627,7 @@ package body Instrument.Ada_Unit is Report (E, "failed to evaluate the expression: " - & Ada.Exceptions.Exception_Information (Exc), + & Switches.Exception_Info (Exc), Low_Warning); return ""; end Bool_Expr_Eval; @@ -7656,7 +7653,7 @@ package body Instrument.Ada_Unit is Report (UIC, Decl, "Failed to look for a previous declaration of this expression" - & " function" & Ada.Exceptions.Exception_Information (Exc), + & " function" & Switches.Exception_Info (Exc), Warning); end; @@ -7667,7 +7664,7 @@ package body Instrument.Ada_Unit is Report (UIC, Decl, "Failed to look for a Ghost aspect for this declaration" - & Ada.Exceptions.Exception_Information (Exc), + & Switches.Exception_Info (Exc), Warning); return False; end; @@ -7693,7 +7690,7 @@ package body Instrument.Ada_Unit is Report (UIC, Decl, "Failed to look for a canonical part of this declaration" - & Ada.Exceptions.Exception_Information (Exc), + & Switches.Exception_Info (Exc), Warning); end; @@ -9772,7 +9769,7 @@ package body Instrument.Ada_Unit is (UIC, UIC.Root_Unit, "Could not determine pragmas of the compilation unit: " - & Ada.Exceptions.Exception_Information (Exc), + & Switches.Exception_Info (Exc), Kind => Low_Warning); Has_Pragma_SCAO := False; end; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 1b1486782..21bc57f84 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -19,7 +19,6 @@ -- Source Coverage Obligations with Ada.Characters.Handling; use Ada.Characters.Handling; -with Ada.Exceptions; with Ada.Strings.Fixed; use Ada.Strings.Fixed; with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Deallocation; @@ -5140,8 +5139,7 @@ package body SC_Obligations is Scope_Entities_Trace.Trace ("The following tree of scopes breaks the nesting/ordering" & " invariant:"); - Scope_Entities_Trace.Trace - (Ada.Exceptions.Exception_Message (Exc)); + Scope_Entities_Trace.Trace (Switches.Exception_Info (Exc)); Dump (Tree, "| "); end if; return False; diff --git a/tools/gnatcov/ss_annotations.adb b/tools/gnatcov/ss_annotations.adb index 402ac07be..9720a3da1 100644 --- a/tools/gnatcov/ss_annotations.adb +++ b/tools/gnatcov/ss_annotations.adb @@ -17,7 +17,6 @@ ------------------------------------------------------------------------------ with Ada.Directories; -with Ada.Exceptions; with Ada.Strings; with Ada.Strings.Hash; with Ada.Text_IO; @@ -286,8 +285,7 @@ package body SS_Annotations is exception when Exc : Constraint_Error => Fatal_Error - ("Wrong value for " & Sw & ": " - & Ada.Exceptions.Exception_Message (Exc)); + ("Wrong value for " & Sw & ": " & Switches.Exception_Info (Exc)); end Get_Or_Error; -------------------------- diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 5e71db7ce..3f96c8ec7 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -20,7 +20,6 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Command_Line; with Ada.Containers; use Ada.Containers; with Ada.Directories; -with Ada.Exceptions; with Ada.Strings.Fixed; with Ada.Text_IO; use Ada.Text_IO; @@ -196,7 +195,7 @@ package body Switches is Dump_Channel := Value (+Dump_Channel_Opt.Value); exception when Exc : Constraint_Error => - Fatal_Error (Ada.Exceptions.Exception_Message (Exc)); + Fatal_Error (Exception_Info (Exc)); end; end if; @@ -262,7 +261,7 @@ package body Switches is end if; exception when Exc : Constraint_Error => - Fatal_Error (Ada.Exceptions.Exception_Message (Exc)); + Fatal_Error (Exception_Info (Exc)); end; end if; @@ -659,6 +658,27 @@ package body Switches is return Result; end Parse; + -------------------- + -- Exception_Info -- + -------------------- + + function Exception_Info + (Exc : Ada.Exceptions.Exception_Occurrence) return String is + begin + if Misc_Trace.Is_Active then + return Ada.Exceptions.Exception_Information (Exc); + end if; + + declare + Name : constant String := Ada.Exceptions.Exception_Name (Exc); + Msg : constant String := Ada.Exceptions.Exception_Message (Exc); + begin + return (if Msg = "" + then Name + else Name & ": " & Msg); + end; + end Exception_Info; + --------------------- -- Parse_Arguments -- --------------------- diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index bde47f86f..c41764e1c 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -17,6 +17,7 @@ ------------------------------------------------------------------------------ with Ada.Containers.Indefinite_Ordered_Maps; +with Ada.Exceptions; with GNAT.Strings; use GNAT.Strings; @@ -34,6 +35,11 @@ package Switches is -- Trace to log all messages for which creating a dedicated trace was not -- worth it. + function Exception_Info + (Exc : Ada.Exceptions.Exception_Occurrence) return String; + -- Helper to display the right amount of exception information depending on + -- enabled traces. + procedure Parse_Arguments (From_Driver : Boolean); -- Load arguments from command-line and from the project file (if any) into -- Args (see below). Print usage and exit if there is no argument. From 087bf1351d4203ce696648c272c6c1aabbfce147 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 25 Sep 2024 18:00:06 +0000 Subject: [PATCH 0956/1483] instr-cov/218-missing-pkg-spec: adapt the testcase for --all-warnings --- testsuite/tests/instr-cov/218-missing-pkg-spec/test.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py b/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py index d09c4e7e2..d3848f51a 100644 --- a/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py +++ b/testsuite/tests/instr-cov/218-missing-pkg-spec/test.py @@ -31,7 +31,14 @@ actual_warnings = set() others = [] for line in lines_of(filename): - if line.startswith("warning: ") or line.startswith("*** warning:"): + if ( + line.startswith("warning: ") + or line.startswith("*** warning:") + or line.startswith( + "*** main.adb:5:4: low_warning: Could not determine if stmt is" + " ghost" + ) + ): actual_warnings.add(line) else: others.append(line) From 2f4884b7162f097cbbf4869b9c7b8dc68bb78452 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 26 Sep 2024 11:55:11 +0000 Subject: [PATCH 0957/1483] instr-cov/gpr-complex: refactor testcase logic No change of behavior expected. --- testsuite/tests/instr-cov/gpr-complex/test.py | 95 ++++++++++--------- 1 file changed, 49 insertions(+), 46 deletions(-) diff --git a/testsuite/tests/instr-cov/gpr-complex/test.py b/testsuite/tests/instr-cov/gpr-complex/test.py index 1b4de7717..32d35310c 100644 --- a/testsuite/tests/instr-cov/gpr-complex/test.py +++ b/testsuite/tests/instr-cov/gpr-complex/test.py @@ -13,7 +13,7 @@ from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.control import env -from SUITE.cutils import no_ext, Wdir +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprbuild, gprinstall @@ -46,36 +46,45 @@ ) -def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): +def check(label, name, expected_xcov): + """ + Copy the "name" project from the test directory to the current directory + and run it through the instrument/build/run/coverage steps. Check that the + coverage report produced matches "expected_cov". + """ + thistest.log(f"== {label} ({name}) ==") + + main_prj = f"{name}.gpr" + obj_dir = f"obj-{name}" + cp(os.path.join("..", main_prj), ".", recursive=True) - cp(os.path.join("..", f"src-{no_ext(main_prj)}"), ".", recursive=True) + cp(os.path.join("..", f"src-{name}"), ".", recursive=True) + build_run_and_coverage( gprsw=GPRswitches(root_project=os.path.join(main_prj)), covlevel="stmt", mains=["main"], - gpr_obj_dir=main_prj_obj_dir, - gpr_exe_dir=main_prj_obj_dir, + gpr_obj_dir=obj_dir, + gpr_exe_dir=obj_dir, extra_coverage_args=[ "--annotate=xcov", "--externally-built-projects", "--units=pkg", ], ) - check_xcov_reports(main_prj_obj_dir, expected_xcov) + check_xcov_reports(obj_dir, expected_xcov) # Try the simple case: the main project extends the library, but does not # redefine anything. -thistest.log("== Simple case ==") -expected_xcov = { - "pkg.ads.xcov": {}, - "pkg.adb.xcov": {"+": {5}}, - "pkg-bar.adb.xcov": {"+": {3}}, -} -build_run_cov_and_check( - "main_simple.gpr", - main_prj_obj_dir="obj-main_simple", - expected_xcov=expected_xcov, +check( + "Simple case", + "main_simple", + expected_xcov={ + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {5}}, + "pkg-bar.adb.xcov": {"+": {3}}, + }, ) # Now the main project defines an alternate body. TODO! as we reinstrument the @@ -83,43 +92,37 @@ def build_run_cov_and_check(main_prj, main_prj_obj_dir, expected_xcov): # redefined), we end up instrumenting the instrumented version for sources # belonging to the library. We should fix this (and adjust coverage # expectations) if possible. -thistest.log("== Redefining Pkg body ==") -expected_xcov = { - "pkg.ads.xcov": {}, - "pkg.adb.xcov": {"+": {7}}, - "pkg-bar.adb.xcov": {"+": {3}}, -} -build_run_cov_and_check( - "main_body.gpr", - main_prj_obj_dir="obj-main_body", - expected_xcov=expected_xcov, +check( + "Redefining Pkg body", + "main_body", + expected_xcov={ + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {7}}, + "pkg-bar.adb.xcov": {"+": {3}}, + }, ) # Now the main project defines an alternate separate. -thistest.log("== Redefining Pkg.Bar separate ==") -expected_xcov = { - "pkg.ads.xcov": {}, - "pkg.adb.xcov": {"+": {5}}, - "pkg-bar.adb.xcov": {"+": {5}}, -} -build_run_cov_and_check( - "main_sep.gpr", - main_prj_obj_dir="obj-main_sep", - expected_xcov=expected_xcov, +check( + "Redefining Pkg.Bar separate", + "main_sep", + expected_xcov={ + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {5}}, + "pkg-bar.adb.xcov": {"+": {5}}, + }, ) # Now the main project defines an alternate spec. -thistest.log("== Redefining Pkg spec ==") -expected_xcov = { - "pkg.adb.xcov": {"+": {5}}, - "pkg-bar.adb.xcov": {"+": {3}}, - "pkg.ads.xcov": {"+": {4}}, -} -build_run_cov_and_check( - "main_spec.gpr", - main_prj_obj_dir="obj-main_spec", - expected_xcov=expected_xcov, +check( + "Redefining Pkg spec", + "main_spec", + expected_xcov={ + "pkg.adb.xcov": {"+": {5}}, + "pkg-bar.adb.xcov": {"+": {3}}, + "pkg.ads.xcov": {"+": {4}}, + }, ) thistest.result() From c890a30e5c55fc432fa7c6da474a956f4aff212b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 26 Sep 2024 12:04:30 +0000 Subject: [PATCH 0958/1483] instrument-projects.adb: minor reformatting --- tools/gnatcov/instrument-projects.adb | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 93e6348bf..566141faf 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -251,10 +251,10 @@ is -- externally built, add Source_File to Project_Sources. procedure Insert_Manual_Dump_Trigger - (Language : Src_Supported_Language; - Project_Sources : in out File_Info_Sets.Set; - Instrumenter : in out Language_Instrumenter'Class; - Manual_Dump_Inserted : in out Boolean; + (Language : Src_Supported_Language; + Project_Sources : in out File_Info_Sets.Set; + Instrumenter : in out Language_Instrumenter'Class; + Manual_Dump_Inserted : in out Boolean; Manual_Indication_Files : File_Sets.Set); -- For all sources in Project_Sources of language Language, call -- Replace_Manual_Indications. If a dump procedure call was inserted @@ -846,10 +846,10 @@ is -------------------------------- procedure Insert_Manual_Dump_Trigger - (Language : Src_Supported_Language; - Project_Sources : in out File_Info_Sets.Set; - Instrumenter : in out Language_Instrumenter'Class; - Manual_Dump_Inserted : in out Boolean; + (Language : Src_Supported_Language; + Project_Sources : in out File_Info_Sets.Set; + Instrumenter : in out Language_Instrumenter'Class; + Manual_Dump_Inserted : in out Boolean; Manual_Indication_Files : File_Sets.Set) is From e83ca56bca3e5a3710c3613ea789263611989591 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 26 Sep 2024 13:42:20 +0000 Subject: [PATCH 0959/1483] instr-cov/gpr-complex: add XFAIL for --all-warnings runs --- testsuite/tests/instr-cov/gpr-complex/test.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/instr-cov/gpr-complex/test.opt b/testsuite/tests/instr-cov/gpr-complex/test.opt index 57b6bf345..a1bd93a6f 100644 --- a/testsuite/tests/instr-cov/gpr-complex/test.opt +++ b/testsuite/tests/instr-cov/gpr-complex/test.opt @@ -1 +1,2 @@ !native DEAD hardcoded project files without board information +all-warnings XFAIL Warnings pending resolution of eng/das/cov/gnatcoverage#66 From 565ec16856453830f6954c24f5dc261b7bc7ec8f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 4 Oct 2024 13:11:50 +0000 Subject: [PATCH 0960/1483] Fix the error message for too long buffer unit filenames on Windows Introduce a dedicated exception handler and call to Fatal_Error for the Windows-specific code path exercised by this precise situation. The global exception handler in gnatcov_bits_specific.adb now uses Switches.Exception_Info, which expectedly include the name of the raised exception: this is not appropriate for user-level error messages, as exception names look like crashes when printed. --- testsuite/tests/92-long_slugs/test.py | 6 +++++- tools/gnatcov/instrument-c.adb | 28 +++++++++++++++++---------- tools/gnatcov/switches.adb | 13 +++++++++---- tools/gnatcov/switches.ads | 8 +++++++- 4 files changed, 39 insertions(+), 16 deletions(-) diff --git a/testsuite/tests/92-long_slugs/test.py b/testsuite/tests/92-long_slugs/test.py index 71c3eb075..d0938bd72 100644 --- a/testsuite/tests/92-long_slugs/test.py +++ b/testsuite/tests/92-long_slugs/test.py @@ -37,7 +37,11 @@ thistest.fail_if_no_match( what="Missing or unexpected error message", regexp=( - r'.*/gnatcov\.exe: invalid path name "gcvrt_b_z.*' + ( + r".*/gnatcov\.exe: Could not create the buffer unit for " + ".*overly_long_capitalized_c_unit_that_should_not_triple_in_size" + '_to_avoid_path_name_limit.c: invalid path name "gcvrt_b_z.*' + ) if "windows" in thistest.env.host.platform else r".*/gnatcov: cannot open .*/tests" r"/92-long_slugs/tmp_/obj/gen-gnatcov-instr/gcvrt_b_z.*\.c" diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 3cdcf8c0a..172f97ff0 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -19,6 +19,7 @@ with Ada.Characters.Handling; with Ada.Containers; use Ada.Containers; with Ada.Directories; use Ada.Directories; +with Ada.IO_Exceptions; with Ada.Streams.Stream_IO; with Ada.Text_IO; use Ada.Text_IO; @@ -4906,17 +4907,24 @@ package body Instrument.C is CU : Compilation_Unit; Prj : Prj_Desc) return Compilation_Unit is - Filename : constant String := - New_File - (Prj, - To_Symbol_Name (Sys_Prefix) & "_b_" - & Filename_Slug (+CU.Unit_Name) - & (+Prj.Body_Suffix - (C_Family_Instrumenter_Type'Class (Self).Language))); + Name : constant String := + To_Symbol_Name (Sys_Prefix) & "_b_" + & Filename_Slug (+CU.Unit_Name) + & (+Prj.Body_Suffix + (C_Family_Instrumenter_Type'Class (Self).Language)); begin - return Compilation_Unit' - (Language => File_Based_Language, - Unit_Name => +Filename); + declare + Filename : constant String := New_File (Prj, Name); + begin + return Compilation_Unit' + (Language => File_Based_Language, + Unit_Name => +Filename); + end; + exception + when Exc : Ada.IO_Exceptions.Name_Error => + Fatal_Error + ("Could not create the buffer unit for " & Image (CU) & ": " + & Switches.Exception_Info (Exc, Discard_Name => True)); end Buffer_Unit; ----------------------------- diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 3f96c8ec7..f643dc13f 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -663,7 +663,8 @@ package body Switches is -------------------- function Exception_Info - (Exc : Ada.Exceptions.Exception_Occurrence) return String is + (Exc : Ada.Exceptions.Exception_Occurrence; + Discard_Name : Boolean := False) return String is begin if Misc_Trace.Is_Active then return Ada.Exceptions.Exception_Information (Exc); @@ -673,9 +674,13 @@ package body Switches is Name : constant String := Ada.Exceptions.Exception_Name (Exc); Msg : constant String := Ada.Exceptions.Exception_Message (Exc); begin - return (if Msg = "" - then Name - else Name & ": " & Msg); + if Msg = "" then + return Name; + elsif Discard_Name then + return Msg; + else + return Name & ": " & Msg; + end if; end; end Exception_Info; diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index c41764e1c..66c861f84 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -36,9 +36,15 @@ package Switches is -- worth it. function Exception_Info - (Exc : Ada.Exceptions.Exception_Occurrence) return String; + (Exc : Ada.Exceptions.Exception_Occurrence; + Discard_Name : Boolean := False) return String; -- Helper to display the right amount of exception information depending on -- enabled traces. + -- + -- If Discard_Name is True, Exc has an exception message and traces are not + -- enabled, do not include the exception name in the error message. Passing + -- True for this is appropriate when formatting a user-level error message + -- (exception names make the error message look like a crash). procedure Parse_Arguments (From_Driver : Boolean); -- Load arguments from command-line and from the project file (if any) into From 79c7531779a19b2f436dcb13b0d1a4401dce7849 Mon Sep 17 00:00:00 2001 From: Olivier Appere Date: Fri, 4 Oct 2024 13:25:35 +0200 Subject: [PATCH 0961/1483] Fix DO-178 version --- doc/conf.py | 1 + doc/gnatcov/cov_source.rst | 6 +++--- doc/gnatcov/getting_started.rst | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index c4f1bfdbf..9fd1e3724 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -63,6 +63,7 @@ docname = "Manuals" rst_epilog = """ +.. |do| replace:: **DO-178C** .. |gcv| replace:: :command:`gnatcov` .. |gcvrun| replace:: :command:`gnatcov` :command:`run` .. |gcvcov| replace:: :command:`gnatcov` :command:`coverage` diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index 1dec52edc..bd1199022 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -7,7 +7,7 @@ Source coverage analysis with |gcvcov| .. _scov-principles: Source coverage analysis computes metrics focused on source programming -language entities such as high level *statements* or *decisions* (DO178 +language entities such as high level *statements* or *decisions* (|do| parlance for boolean expressions), which translate as :term:`Source Coverage Obligations `, or SCOs, in |gcp| terms. @@ -1052,7 +1052,7 @@ Then for all the decisions in the sources of interest: * Testing shall exercise both the True and False outcomes of the expression as a whole and demonstrate the :dfn:`independant influence` of :dfn:`conditions` - in DO-178 parlance, where ... + in |do| parlance, where ... * Separate conditions in a decision are identified as the operands of *short-circuit* operators. @@ -1246,7 +1246,7 @@ Compared to Decision Coverage, achieving MCDC requires tests that demonstrate the independent influence of conditions in decisions. Several variants of the criterion exist. -:dfn:`Unique Cause MCDC` is the original criterion described in the DO178B +:dfn:`Unique Cause MCDC` is the original criterion described in the |do| reference guidelines, where independent influence of a specific condition must be demonstrated by a pair of tests where only that condition changes and the decision value toggles. diff --git a/doc/gnatcov/getting_started.rst b/doc/gnatcov/getting_started.rst index 2272c433b..806be6e65 100644 --- a/doc/gnatcov/getting_started.rst +++ b/doc/gnatcov/getting_started.rst @@ -29,7 +29,7 @@ traces` the coverage traces produced by programs instrumented this way. The set of metrics that the tool can assess from source traces -corresponds to the set defined by the DO-178B certification standard +corresponds to the set defined by the |do| certification standard for civil avionics, that is: - :dfn:`Statement Coverage`, where the tools assesses the coverage @@ -37,12 +37,12 @@ for civil avionics, that is: assignment or a subprogram call; - :dfn:`Decision Coverage`, which, in addition to statement coverage, - evaluates whether Boolean expressions (*decisions* in DO178B + evaluates whether Boolean expressions (*decisions* in |do| parlance) have been exercised both True and False, then - :dfn:`Modified Condition/Decision Coverage`, commonly known as *MCDC*, which requires testing particular variations of individual - Boolean operands (*conditions* in DO178B parlance) within decisions. + Boolean operands (*conditions* in |do| parlance) within decisions. All these metrics are defined with respect to source level entities (statements, decisions, conditions), and we commonly refer to such From 0ea4e46d8c0d08182a307dc0d583b6aad681e7af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 9 Oct 2024 09:23:03 +0200 Subject: [PATCH 0962/1483] Doc: Fix the year in the copyright in the documentation --- doc/conf.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/conf.py b/doc/conf.py index 9fd1e3724..e5a546b20 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -12,6 +12,7 @@ # All configuration values have a default; values that are commented out # serve to show the default. +from datetime import datetime import os import docutils.nodes as nodes @@ -59,7 +60,7 @@ # General information about the project. project = "GNATDAS" -copyright = "2009-2022, AdaCore" # noqa: A001 +copyright = f"2009-{datetime.now().year}, AdaCore" # noqa: A001 docname = "Manuals" rst_epilog = """ From 68480a471348ec26054668b5151d8f2a75422e56 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 9 Oct 2024 17:03:39 +0200 Subject: [PATCH 0963/1483] Use GNATCOLL.VFS API to check if file exists The Ada.Directories API actually crashes on names such as "" which are considered as invalid file names. --- .../fake_ldd/Makefile | 11 +++ .../integrated_instrumentation/fake_ldd/ldd | 11 +++ .../integrated_instrumentation/fake_ldd/pkg.c | 5 ++ .../fake_ldd/test.c | 8 ++ .../fake_ldd/test.py | 74 +++++++++++++++++++ tools/gnatcov/instrument-gcc_wrapper.adb | 4 +- 6 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/integrated_instrumentation/fake_ldd/Makefile create mode 100755 testsuite/tests/integrated_instrumentation/fake_ldd/ldd create mode 100644 testsuite/tests/integrated_instrumentation/fake_ldd/pkg.c create mode 100644 testsuite/tests/integrated_instrumentation/fake_ldd/test.c create mode 100644 testsuite/tests/integrated_instrumentation/fake_ldd/test.py diff --git a/testsuite/tests/integrated_instrumentation/fake_ldd/Makefile b/testsuite/tests/integrated_instrumentation/fake_ldd/Makefile new file mode 100644 index 000000000..303dc65f8 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/fake_ldd/Makefile @@ -0,0 +1,11 @@ +CC=gcc +OBJ = pkg.o test.o + +%.o: %.c + $(CC) -c -o $@ $< + +test: $(OBJ) + $(CC) -o $@ $^ + +clean: + rm -f *.o test diff --git a/testsuite/tests/integrated_instrumentation/fake_ldd/ldd b/testsuite/tests/integrated_instrumentation/fake_ldd/ldd new file mode 100755 index 000000000..e0f18120f --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/fake_ldd/ldd @@ -0,0 +1,11 @@ +#!/usr/bin/env python + +import subprocess +import sys + +with open("ldd.out", "w") as out: + process = subprocess.run(["/usr/bin/ldd", sys.argv[1]], stdout=out) + out.write("\tdummy.so => ()") + +with open("ldd.out", "r") as out: + print(out.read()) diff --git a/testsuite/tests/integrated_instrumentation/fake_ldd/pkg.c b/testsuite/tests/integrated_instrumentation/fake_ldd/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/fake_ldd/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/fake_ldd/test.c b/testsuite/tests/integrated_instrumentation/fake_ldd/test.c new file mode 100644 index 000000000..84fcd4703 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/fake_ldd/test.c @@ -0,0 +1,8 @@ +extern int foo (); + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/fake_ldd/test.py b/testsuite/tests/integrated_instrumentation/fake_ldd/test.py new file mode 100644 index 000000000..d8200888a --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/fake_ldd/test.py @@ -0,0 +1,74 @@ +""" +Regression test for integrated instrumentation, with a fake ldd that yields the +following output: + linux-vdso.so.1 => (0x00007ffda3d11000) + libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007d8894a00000) + /lib64/ld-linux-x86-64.so.2 (0x00007d8894dcc000) + +The difference with ldd is the first line, which is normally displayed as: + linux-vdso.so.1 (0x00007ffda3d11000) + +As gnatcov relies on the contents after the arrow, and before the loading +address to get the library path, it grabbed an invalid name in the former case. +There was no consistency check, which resulted in the compiler wrapper +crashing. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "pkg.c"), ".") + +# Copy the fake ldd in the temporary directory +cp(os.path.join("..", "ldd"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'pkg.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Put the compiler wrapper and the fake ldd on the PATH +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make", "test"], for_pgm=False) + +# Remove our fake ldd to avoid shadowing the system one at execution time +cmdrun(["rm", "ldd"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=pkg.c.sid", + "-axcov", + srctracename_for("test"), + ] +) +check_xcov_reports(".", {"pkg.c.xcov": {"+": {4}}}) + +thistest.result() diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 4bedcb419..64a8d51bd 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -1078,7 +1078,9 @@ begin -- -- => () - elsif Exists (Lib_Filename) then + elsif GNATCOLL.VFS.Is_Regular_File + (GNATCOLL.VFS.Create (+Lib_Filename)) + then Add_Coverage_Buffer_Symbols (Create (+Lib_Filename)); end if; From d58509d725c1f98c91a948e4d98f475b23c80efe Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 14 Oct 2024 14:58:59 +0000 Subject: [PATCH 0964/1483] sc_obligations.adb: fix a new GNAT warning This unit has been "withing" itself for several months. GNAT now warns about it: remove this useless context clause. --- tools/gnatcov/sc_obligations.adb | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 21bc57f84..a00a198d9 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -29,7 +29,6 @@ with Aspects; use Aspects; with Get_SCOs; with GNAT.Regpat; use GNAT.Regpat; with Namet; use Namet; -with SC_Obligations; with SCOs; with Snames; From 580eb4d757460e57ec4c7311e2662e8b81484fe3 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 14 Oct 2024 19:38:11 +0000 Subject: [PATCH 0965/1483] instrument-ada_unit.adb: minor reformatting --- tools/gnatcov/instrument-ada_unit.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 13c2093c1..786d07480 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1234,7 +1234,7 @@ package body Instrument.Ada_Unit is -- Context miscellaneous -- ---------------------------- - Max_Get_From_File_Count : constant := 50; + Max_Get_From_File_Count : constant := 50; -- In addition to nodes and text buffers for each loaded unit, Libadalang -- maintains caches in Analysis_Context objects so that semantic queries -- are fast. This means that if we keep the same context to process a lot From 0b05e69766705758e033d4c6e8b2d54526d25d72 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 15 Oct 2024 14:42:23 +0000 Subject: [PATCH 0966/1483] Fix syntax for comments in "*.opt" files --- testsuite/tests/M625-040-slow_on_windows/test.opt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/M625-040-slow_on_windows/test.opt b/testsuite/tests/M625-040-slow_on_windows/test.opt index 71e7fba49..38cc28767 100644 --- a/testsuite/tests/M625-040-slow_on_windows/test.opt +++ b/testsuite/tests/M625-040-slow_on_windows/test.opt @@ -1,2 +1,2 @@ -# test is there to allow manual investigation of timing issues. +-- Test is there to allow manual investigation of timing issues ALL DEAD test meant to facilitate manual timing investigation From c2584570c2ec94b9ac36d13931f177b52f496269 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 16 Oct 2024 11:20:00 +0200 Subject: [PATCH 0967/1483] Add more log --- tools/gnatcov/coverage-source.adb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index d3141813e..576ef830f 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -2178,6 +2178,8 @@ package body Coverage.Source is -- Start of processing for Compute_Source_Coverage begin + Misc_Trace.Trace ("processing traces for unit " & Unit_Image); + CU := Find_Instrumented_Unit (CU_Name); if CU = No_CU_Id then From 333e2bdfdcc93f154c995e2be13c417f9c6d38bd Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 16 Oct 2024 11:52:05 +0200 Subject: [PATCH 0968/1483] Replace assertion with defensive code --- tools/gnatcov/sc_obligations.adb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index a00a198d9..f4633435a 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -917,7 +917,10 @@ package body SC_Obligations is SCOD : SCO_Descriptor renames SCO_Vector (SCO); begin if SCOD.Kind /= Fun then - pragma Assert (not Is_Root (ST.Cur)); + if Is_Root (ST.Cur) then + raise Program_Error + with "No scope found for " & Image (SCO); + end if; end if; end; end loop; @@ -1740,7 +1743,10 @@ package body SC_Obligations is Available_Subps_Of_Interest.Include (Scope_Ent.Identifier); end loop; - pragma Assert (SCOs_Nested_And_Ordered (CP_CU.Scope_Entities)); + if not SCOs_Nested_And_Ordered (CP_CU.Scope_Entities) then + raise Program_Error + with "Error when loading scopes from checkpoints"; + end if; end if; -- Remap ALI annotations From 8bccf11718c7482738d5d0472af524bc5f725e20 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 17 Oct 2024 11:43:03 +0000 Subject: [PATCH 0969/1483] SC_Obligations: add support for pragma Extended_Access --- tools/gnatcov/sc_obligations.ads | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 048ff93f4..300d08b88 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -1048,6 +1048,7 @@ package SC_Obligations is Pragma_Export_Value, Pragma_Export_Valued_Procedure, Pragma_Extend_System, + Pragma_Extended_Access, Pragma_Extensions_Allowed, Pragma_Extensions_Visible, Pragma_External, @@ -1281,6 +1282,7 @@ package SC_Obligations is Pragma_Eliminate => False, Pragma_Enable_Atomic_Synchronization => False, Pragma_Extend_System => False, + Pragma_Extended_Access => False, Pragma_Extensions_Allowed => False, Pragma_External_Name_Casing => False, Pragma_Favor_Top_Level => False, From 767a4a87cbe567e111660a1c3d694b1d279c73fc Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 22 Oct 2024 11:26:27 +0200 Subject: [PATCH 0970/1483] Scope traversal: remove code no longer needed The scope traversal does not require to traverse SCOs in an ascending order, so remove reinitialization of the Scope_Traversal structure. --- tools/gnatcov/coverage-source.adb | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 576ef830f..f04f0908a 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -2276,7 +2276,6 @@ package body Coverage.Source is end if; end; - ST := Scope_Traversal (CU); for J in Decision_Buffer'Range loop if Decision_Buffer (J) then declare @@ -2307,7 +2306,6 @@ package body Coverage.Source is end if; end loop; - ST := Scope_Traversal (CU); for J in MCDC_Buffer'Range loop if MCDC_Buffer (J) then declare From 2b694708a97fa2d08c8ec9cf76268139866fb62d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 22 Oct 2024 11:28:15 +0200 Subject: [PATCH 0971/1483] Scopes: support protected body as scopes Protected body should be considered as scopes as they can be at the root of a separate unit. --- .../main.adb.xml.expected | 168 +++++++++++------- .../instr-cov/342-protected-body/a-b.adb | 29 +++ .../tests/instr-cov/342-protected-body/a.adb | 3 + .../tests/instr-cov/342-protected-body/a.ads | 9 + .../instr-cov/342-protected-body/main.adb | 9 + .../instr-cov/342-protected-body/test.opt | 2 + .../instr-cov/342-protected-body/test.py | 32 ++++ tools/gnatcov/instrument-ada_unit.adb | 3 + 8 files changed, 195 insertions(+), 60 deletions(-) create mode 100644 testsuite/tests/instr-cov/342-protected-body/a-b.adb create mode 100644 testsuite/tests/instr-cov/342-protected-body/a.adb create mode 100644 testsuite/tests/instr-cov/342-protected-body/a.ads create mode 100644 testsuite/tests/instr-cov/342-protected-body/main.adb create mode 100644 testsuite/tests/instr-cov/342-protected-body/test.opt create mode 100644 testsuite/tests/instr-cov/342-protected-body/test.py diff --git a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected index 8b71fbe1a..42cbb758f 100644 --- a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected +++ b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected @@ -286,9 +286,9 @@ - - - + + + @@ -297,8 +297,8 @@ - - + + @@ -309,43 +309,31 @@ - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - + + @@ -354,31 +342,91 @@ - + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/testsuite/tests/instr-cov/342-protected-body/a-b.adb b/testsuite/tests/instr-cov/342-protected-body/a-b.adb new file mode 100644 index 000000000..748b5d783 --- /dev/null +++ b/testsuite/tests/instr-cov/342-protected-body/a-b.adb @@ -0,0 +1,29 @@ +separate (A) + +protected body B +is + + procedure Foo + is + Decl : Integer; + begin + if Decl = 1 then + null; + else + null; + end if; + end Foo; + + procedure Bar + is + begin + null; + end Bar; + + procedure Baz + is + begin + null; + end Baz; + +end B; diff --git a/testsuite/tests/instr-cov/342-protected-body/a.adb b/testsuite/tests/instr-cov/342-protected-body/a.adb new file mode 100644 index 000000000..cdd0b0b4c --- /dev/null +++ b/testsuite/tests/instr-cov/342-protected-body/a.adb @@ -0,0 +1,3 @@ +package body A is + protected body B is separate; +end A; diff --git a/testsuite/tests/instr-cov/342-protected-body/a.ads b/testsuite/tests/instr-cov/342-protected-body/a.ads new file mode 100644 index 000000000..2e328c3ac --- /dev/null +++ b/testsuite/tests/instr-cov/342-protected-body/a.ads @@ -0,0 +1,9 @@ +package A is + + protected type B is + procedure Foo; + procedure Bar; + procedure Baz; + end B; + +end A; diff --git a/testsuite/tests/instr-cov/342-protected-body/main.adb b/testsuite/tests/instr-cov/342-protected-body/main.adb new file mode 100644 index 000000000..e625a6b04 --- /dev/null +++ b/testsuite/tests/instr-cov/342-protected-body/main.adb @@ -0,0 +1,9 @@ +with A; + +procedure Main is + Obj : A.B; +begin + Obj.Foo; + Obj.Bar; + Obj.Baz; +end Main; diff --git a/testsuite/tests/instr-cov/342-protected-body/test.opt b/testsuite/tests/instr-cov/342-protected-body/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/instr-cov/342-protected-body/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/instr-cov/342-protected-body/test.py b/testsuite/tests/instr-cov/342-protected-body/test.py new file mode 100644 index 000000000..76d22337a --- /dev/null +++ b/testsuite/tests/instr-cov/342-protected-body/test.py @@ -0,0 +1,32 @@ +""" +Check that gnatcov correctly processes compilation units when the root node is +a protected body. It used to not consider it as a scope, which resulted in +declarations scope not having a parent scope, making `gnatcov coverage` crash. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {4, 6, 7, 8}}, + "a.ads.xcov": {"+": {3}}, + "a.adb.xcov": {}, + "a-b.adb.xcov": {"+": {8, 10, 13, 20, 26}, "-": {11}}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 786d07480..579422493 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -5102,8 +5102,11 @@ package body Instrument.Ada_Unit is -- Protected body when Ada_Protected_Body => + Enter_Scope + (UIC, N, Safe_Previous_Part_For_Decl (As_Protected_Body (N))); Traverse_Declarations_Or_Statements (UIC, L => As_Protected_Body (N).F_Decls.F_Decls); + Exit_Scope (UIC); when Ada_Exit_Stmt => Instrument_Statement (UIC, N, 'E'); From 30f242eabf81cf1189034508ab453e9e57d4ba19 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 22 Oct 2024 11:29:29 +0200 Subject: [PATCH 0972/1483] Add a test for separate task body This use case was supported by gnatcov, but add a test for extra safety. --- .../tests/instr-cov/342-task-body/a-b.adb | 33 +++++++++++++++++++ testsuite/tests/instr-cov/342-task-body/a.adb | 3 ++ testsuite/tests/instr-cov/342-task-body/a.ads | 3 ++ .../tests/instr-cov/342-task-body/main.adb | 6 ++++ .../tests/instr-cov/342-task-body/test.opt | 2 ++ .../tests/instr-cov/342-task-body/test.py | 31 +++++++++++++++++ 6 files changed, 78 insertions(+) create mode 100644 testsuite/tests/instr-cov/342-task-body/a-b.adb create mode 100644 testsuite/tests/instr-cov/342-task-body/a.adb create mode 100644 testsuite/tests/instr-cov/342-task-body/a.ads create mode 100644 testsuite/tests/instr-cov/342-task-body/main.adb create mode 100644 testsuite/tests/instr-cov/342-task-body/test.opt create mode 100644 testsuite/tests/instr-cov/342-task-body/test.py diff --git a/testsuite/tests/instr-cov/342-task-body/a-b.adb b/testsuite/tests/instr-cov/342-task-body/a-b.adb new file mode 100644 index 000000000..01aef066b --- /dev/null +++ b/testsuite/tests/instr-cov/342-task-body/a-b.adb @@ -0,0 +1,33 @@ +separate (A) + +task body B +is + + procedure Foo + is + Decl : Integer; + begin + if Decl = 1 then + return; + else + return; + end if; + end Foo; + + procedure Bar + is + begin + return; + end Bar; + + procedure Baz + is + begin + return; + end Baz; + +begin + Foo; + Bar; + Baz; +end B; diff --git a/testsuite/tests/instr-cov/342-task-body/a.adb b/testsuite/tests/instr-cov/342-task-body/a.adb new file mode 100644 index 000000000..9446f0ef2 --- /dev/null +++ b/testsuite/tests/instr-cov/342-task-body/a.adb @@ -0,0 +1,3 @@ +package body A is + task body B is separate; +end A; diff --git a/testsuite/tests/instr-cov/342-task-body/a.ads b/testsuite/tests/instr-cov/342-task-body/a.ads new file mode 100644 index 000000000..80570e679 --- /dev/null +++ b/testsuite/tests/instr-cov/342-task-body/a.ads @@ -0,0 +1,3 @@ +package A is + task B; +end A; diff --git a/testsuite/tests/instr-cov/342-task-body/main.adb b/testsuite/tests/instr-cov/342-task-body/main.adb new file mode 100644 index 000000000..fec42579f --- /dev/null +++ b/testsuite/tests/instr-cov/342-task-body/main.adb @@ -0,0 +1,6 @@ +with A; + +procedure Main is +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/342-task-body/test.opt b/testsuite/tests/instr-cov/342-task-body/test.opt new file mode 100644 index 000000000..0955f0fce --- /dev/null +++ b/testsuite/tests/instr-cov/342-task-body/test.opt @@ -0,0 +1,2 @@ +RTS_FULL +ALL DEAD diff --git a/testsuite/tests/instr-cov/342-task-body/test.py b/testsuite/tests/instr-cov/342-task-body/test.py new file mode 100644 index 000000000..023478a2b --- /dev/null +++ b/testsuite/tests/instr-cov/342-task-body/test.py @@ -0,0 +1,31 @@ +""" +Check that gnatcov correctly processes compilation units when the root node is +a task body. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5}}, + "a.ads.xcov": {"+": {2}}, + "a.adb.xcov": {}, + "a-b.adb.xcov": {"+": {8, 10, 13, 20, 26, 30, 31, 32}, "-": {11}}, + }, + discard_empty=False, +) + +thistest.result() From 629e5199db30a36728970f4d82f36ac0648abcbf Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Oct 2024 08:01:52 +0000 Subject: [PATCH 0973/1483] Do not remove the history map for MC/DC with bin traces if --save-temps Preserving this file after "gnatcov run" has exited is useful for debugging. --- tools/gnatcov/gnatcov_bits_specific.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 706b9e79f..2ab310cfe 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -2494,7 +2494,7 @@ begin -- Now that we are done with the decision map file, make sure -- we remove it to avoid polluting users' filesystems. - if Histmap /= null then + if not Save_Temps and then Histmap /= null then OS.Delete_File (Histmap.all, Success); if not Success then Warn From fe9a7fee2ebd1c756bf409eb045c9e99ed8ed123 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Oct 2024 10:36:55 +0000 Subject: [PATCH 0974/1483] M528-002-transient-finalize: minor reformattings --- .../tests/M528-002-transient-finalize/alternate/src/foo.adb | 2 +- .../tests/M528-002-transient-finalize/alternate/src/foo.ads | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb index 51563b259..50cf57844 100644 --- a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb @@ -31,7 +31,7 @@ package body Foo is procedure Try (V : Integer) is begin - if Val(Make(1)) = V or else Val(Make(2)) = V then -- # eval + if Val (Make (1)) = V or else Val (Make (2)) = V then -- # eval N_Then := N_Then + 1; -- # then else N_Else := N_Else + 1; -- # else diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads index aa7e225ed..aac5f28a9 100644 --- a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.ads @@ -1,4 +1,3 @@ - package Foo is procedure Try (V : Integer); From 2ec29d23c03dc7d2087f1e408bac6b622884e8a9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Oct 2024 10:40:43 +0000 Subject: [PATCH 0975/1483] M528-002-transient-finalize/alternate: cope with return copy elision Recent GNAT improvements allow the compiler to elide copy in aggregate returns for nonlimited types. As a result: return (Controlled with V); No longer triggers a call to the Adjust primitive for Witness. Break this into: Result : constant Witness := (Contolled with V); return Result; To make sure that a copy is made, and thus to make sure that the Adjust primitive is called. --- .../tests/M528-002-transient-finalize/alternate/src/foo.adb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb index 50cf57844..4b1f6d00b 100644 --- a/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb +++ b/testsuite/tests/M528-002-transient-finalize/alternate/src/foo.adb @@ -20,8 +20,9 @@ package body Foo is end Finalize; function Make (V : Integer) return Witness is + Result : constant Witness := (Controlled with V); -- # make begin - return (Controlled with V); -- # make + return Result; -- # make end Make; function Val (X : Witness) return Integer is From 3b4f6b14a6ea60c5c16ee50ef5f3c68acd221e93 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 22 Oct 2024 16:49:23 +0200 Subject: [PATCH 0976/1483] Apply TODO --- tools/gnatcov/subprocesses.adb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index f82902fd3..934f22480 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -359,11 +359,10 @@ package body Subprocesses is begin while Terminated_Process = Invalid_Handle loop - -- Wait until one process terminates. TODO??? W222-016: replace the - -- magic constant with Duration'Last once GNATCOLL.OS.Processes is - -- fixed. + -- Wait until one process terminates - Terminated_Process := Wait_For_Processes (Self.Handles, 1000.0); + Terminated_Process := + Wait_For_Processes (Self.Handles, Duration'Last); end loop; Self.Nb_Running_Processes := Self.Nb_Running_Processes - 1; From b7b6b7f12ed6e62215e81ee66463eac7999a7de1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 8 Oct 2024 14:28:39 +0200 Subject: [PATCH 0977/1483] instrument-ada_unit.adb: process annotations in the unit prelude Annotate pragmas located in the prelude of an analysis unit used to be silently ignored by gnatcov. This change ensures that they are taken into account. --- .../326-prelude-prag/src/exemptions.adb | 8 + .../326-prelude-prag/src/exemptions.ads | 5 + .../326-prelude-prag/src/selective.ads | 8 + .../instr-cov/326-prelude-prag/src/test_0.adb | 16 + .../326-prelude-prag/src/test_full.adb | 16 + .../tests/instr-cov/326-prelude-prag/test.opt | 2 + .../tests/instr-cov/326-prelude-prag/test.py | 12 + tools/gnatcov/instrument-ada_unit.adb | 450 +++++++++--------- 8 files changed, 295 insertions(+), 222 deletions(-) create mode 100644 testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.adb create mode 100644 testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.ads create mode 100644 testsuite/tests/instr-cov/326-prelude-prag/src/selective.ads create mode 100644 testsuite/tests/instr-cov/326-prelude-prag/src/test_0.adb create mode 100644 testsuite/tests/instr-cov/326-prelude-prag/src/test_full.adb create mode 100644 testsuite/tests/instr-cov/326-prelude-prag/test.opt create mode 100644 testsuite/tests/instr-cov/326-prelude-prag/test.py diff --git a/testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.adb b/testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.adb new file mode 100644 index 000000000..7c0e3174a --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.adb @@ -0,0 +1,8 @@ +pragma Annotate (Xcov, Exempt_On, "Useless unit"); -- # exempt + -- # exempt +package body Exemptions is -- # exempt + -- # exempt + procedure Foo is null; -- # exempt_st + -- # exempt +end Exemptions; -- # exempt +pragma Annotate (Xcov, Exempt_Off); -- # exempt diff --git a/testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.ads b/testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.ads new file mode 100644 index 000000000..4e3a09b32 --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/src/exemptions.ads @@ -0,0 +1,5 @@ +package Exemptions is + + procedure Foo; + +end Exemptions; diff --git a/testsuite/tests/instr-cov/326-prelude-prag/src/selective.ads b/testsuite/tests/instr-cov/326-prelude-prag/src/selective.ads new file mode 100644 index 000000000..a09432ba4 --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/src/selective.ads @@ -0,0 +1,8 @@ +pragma Annotate (Xcov, Cov_Off, "Useless unit"); -- # cov + -- # cov +package Selective is -- # cov + -- # cov + procedure Bar is null; -- # cov + -- # cov +end Selective; -- # cov +pragma Annotate (Xcov, Cov_On); -- # cov diff --git a/testsuite/tests/instr-cov/326-prelude-prag/src/test_0.adb b/testsuite/tests/instr-cov/326-prelude-prag/src/test_0.adb new file mode 100644 index 000000000..d033978b2 --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/src/test_0.adb @@ -0,0 +1,16 @@ +with Exemptions; +with Selective; + +procedure Test_0 is +begin + null; +end Test_0; + +--# selective.ads +-- +-- /cov/ lD ## dB + +--# exemptions.adb +-- +-- /exempt/ l* ## x+ +-- /exempt_st/ l= ## Xs- diff --git a/testsuite/tests/instr-cov/326-prelude-prag/src/test_full.adb b/testsuite/tests/instr-cov/326-prelude-prag/src/test_full.adb new file mode 100644 index 000000000..77eb63ed8 --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/src/test_full.adb @@ -0,0 +1,16 @@ +with Exemptions; +with Selective; + +procedure Test_Full is +begin + Exemptions.Foo; + Selective.Bar; +end Test_Full; + +--# selective.ads +-- +-- /cov/ lD ## dB + +--# exemptions.adb +-- +-- /exempt/ l# ## x0 diff --git a/testsuite/tests/instr-cov/326-prelude-prag/test.opt b/testsuite/tests/instr-cov/326-prelude-prag/test.opt new file mode 100644 index 000000000..2a89ffb4a --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD Check instrumentation-specific feature +5.04a1 DEAD pragma Annotate unknown to the compiler diff --git a/testsuite/tests/instr-cov/326-prelude-prag/test.py b/testsuite/tests/instr-cov/326-prelude-prag/test.py new file mode 100644 index 000000000..722840a72 --- /dev/null +++ b/testsuite/tests/instr-cov/326-prelude-prag/test.py @@ -0,0 +1,12 @@ +""" +Test that the instrumentation process correctly takes into account Annotate +pragmas placed in the prelude of a unit. They used to be silently ignored. +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT +from SCOV.tc import TestCase + +TestCase(category=CAT.stmt).run() + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 579422493..74dc82708 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1196,6 +1196,24 @@ package body Instrument.Ada_Unit is (Unit : LAL.Compilation_Unit) return Boolean; -- Return whether the No_Elaboration_Code_All aspect/pragma applies to Unit + function Prag_Arg_Expr (Args : Base_Assoc_List; I : Positive) return Expr is + (Args.Child (I).As_Pragma_Argument_Assoc.F_Expr); + -- Return the expression for the Index'th argument of a pragma's + -- arguments. + + procedure Process_Annotation + (UIC : in out Ada_Unit_Inst_Context; + N : Ada_Node; + Prag_Args : Base_Assoc_List) + with Pre => + N.Kind = Ada_Pragma_Node + and then Pragma_Name (N.As_Pragma_Node) = Name_Annotate; + -- Handle an Annotate pragma. + -- + -- If this is not an Xcov annotation, do nothing. Otherwise, decode it and + -- add it to our internal tables. If the pragma is not correctly formatted + -- (decoding failure) just emit a warning. + -------------------------------- -- Instrumentation extensions -- -------------------------------- @@ -3324,6 +3342,209 @@ package body Instrument.Ada_Unit is return False; end Has_No_Elaboration_Code_All; + ------------------------ + -- Process_Annotation -- + ------------------------ + + procedure Process_Annotation + (UIC : in out Ada_Unit_Inst_Context; + N : Ada_Node; + Prag_Args : Base_Assoc_List) + is + function Get_Arg + (Prag_Args : Base_Assoc_List; + I : Natural) + return Symbol_Type + is + (if Prag_Arg_Expr (Prag_Args, I).Kind = + Libadalang.Common.Ada_Identifier + then As_Symbol (Prag_Arg_Expr (Prag_Args, I).As_Identifier) + else No_Symbol); + -- Attempt to get the pragma's Ith argument as an identifier. If + -- it is not an identifier, return null. Else, return the identifier + -- as a symbol. + + procedure Safe_String_Eval + (E : Expr; + Result : out Unbounded_Text_Type; + Success : out Boolean); + -- Evaluate the given Expr E and set Result to the evaluated string + -- and Success to True if it could be evaluated, otherwise set + -- Success to False. + + ---------------------- + -- Safe_String_Eval -- + ---------------------- + + procedure Safe_String_Eval + (E : Expr; + Result : out Unbounded_Text_Type; + Success : out Boolean) + is + use Libadalang.Expr_Eval; + begin + -- TODO??? Check for P_Is_Static_Expr prior to evaluating + -- when eng/libadalang/libadalang#1359 is implemented instead of + -- using exception handling. + + declare + String_Expr_Eval : constant Eval_Result := Expr_Eval (E); + begin + if String_Expr_Eval.Kind /= String_Lit then + Success := False; + return; + end if; + Result := As_String (String_Expr_Eval); + Success := True; + end; + exception + when Property_Error => + Success := False; + end Safe_String_Eval; + + Nb_Children : constant Natural := Prag_Args.Children_Count; + Kind : Symbol_Type; + Result : ALI_Annotation; + + -- Start of processing for Process_Annotation + + begin + -- Ignore all but Xcov annotations + + if Get_Arg (Prag_Args, 1) /= As_Symbol (Xcov) then + return; + end if; + + -- Decode the annotation kind + + if Nb_Children = 1 then + Report (N, "Xcov annotation kind missing", Warning); + return; + end if; + + Kind := Get_Arg (Prag_Args, 2); + begin + Result.Kind := Src_Annotation_Kind'Value (Image (Kind)); + exception + when Constraint_Error => + Report + (N, + "Invalid Xcov annotation kind" + & (if Kind /= No_Symbol then ": " & Image (Kind) else ""), + Warning); + return; + end; + + -- End the statement block if this is a Dump/Reset_Buffers + -- annotation. + + if Result.Kind in Dump_Buffers | Reset_Buffers then + End_Statement_Block (UIC); + Start_Statement_Block (UIC); + end if; + + -- Now that the annotation kind is known, validate the remaining + -- arguments expected for that kind. + + case Result.Kind is + when Exempt_On | Cov_Off => + + -- Expected formats: + -- * (Xcov, ) + -- * (Xcov, , "Justification") + + if Result.Kind = Cov_Off then + UIC.Disable_Coverage := True; + end if; + case Nb_Children is + when 2 => + if Result.Kind = Exempt_On then + Report + (N, "No justification given for exempted region", + Warning); + elsif Result.Kind = Cov_Off then + Report + (N, + "No justification given for disabled coverage region", + Warning); + end if; + UIC.Annotations.Append + (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); + + when 3 => + declare + String_Value : Unbounded_Text_Type; + Success : Boolean; + begin + Safe_String_Eval + (Prag_Arg_Expr (Prag_Args, 3), String_Value, Success); + if not Success then + Report + (N, + "Invalid justification argument: static string" + & " expression expected", + Warning); + return; + end if; + Result.Message := new String' + (To_UTF8 (To_Text (String_Value))); + + UIC.Annotations.Append + (Annotation_Couple' + ((UIC.SFI, +Sloc (N)), Result)); + end; + + when others => + Report (N, "At most 3 pragma arguments allowed", Warning); + return; + end case; + + when Exempt_Off => + if Nb_Children > 2 then + Report + (N, "At most 2 pragma arguments allowed", Warning); + return; + end if; + UIC.Annotations.Append + (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); + + when Cov_On => + if Nb_Children > 2 then + Report + (N, "At most 2 pragma arguments allowed", Warning); + return; + end if; + UIC.Disable_Coverage := False; + UIC.Annotations.Append + (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); + + when Dump_Buffers => + + -- Expected formats: + -- * (Xcov, Dump_Buffers) + -- * (Xcov, Dump_Buffers, Prefix) + + case Nb_Children is + when 2 | 3 => + + -- TODO??? check that the Prefix expression is a string + -- type when eng/libadalang/libadalang#1360 is dealt + -- with. + null; + + when others => + Report (N, "At most 3 pragma arguments allowed", Warning); + return; + end case; + + when Reset_Buffers => + if Nb_Children /= 2 then + Report (N, "At most 2 pragma arguments allowed", Warning); + return; + end if; + end case; + end Process_Annotation; + ----------------------------------------- -- Traverse_Declarations_Or_Statements -- ----------------------------------------- @@ -3492,24 +3713,6 @@ package body Instrument.Ada_Unit is with Pre => Assertion_Coverage_Enabled; -- Register decision of contrat of name Name of declaration node D - function Prag_Arg_Expr (Args : Base_Assoc_List; I : Positive) return Expr - is - (Args.Child (I).As_Pragma_Argument_Assoc.F_Expr); - -- Return the expression for the Index'th argument of a pragma's - -- arguments. - - procedure Process_Annotation - (N : Ada_Node; - Prag_Args : Base_Assoc_List) - with Pre => - N.Kind = Ada_Pragma_Node - and then Pragma_Name (N.As_Pragma_Node) = Name_Annotate; - -- Handle an Annotate pragma. - -- - -- If this is not an Xcov annotation, do nothing. Otherwise, decode it - -- and add it to our internal tables. If the pragma is not correctly - -- formatted (decoding failure), just emit a warning. - procedure Traverse_One (N : Ada_Node); -- Traverse one declaration or statement @@ -3796,209 +3999,6 @@ package body Instrument.Ada_Unit is 'A'); end Process_Contract; - ------------------------ - -- Process_Annotation -- - ------------------------ - - procedure Process_Annotation - (N : Ada_Node; - Prag_Args : Base_Assoc_List) - is - function Get_Arg - (Prag_Args : Base_Assoc_List; - I : Natural) - return Symbol_Type - is - (if Prag_Arg_Expr (Prag_Args, I).Kind = - Libadalang.Common.Ada_Identifier - then As_Symbol (Prag_Arg_Expr (Prag_Args, I).As_Identifier) - else No_Symbol); - -- Attempt to get the pragma's Ith argument as an identifier. If - -- it is not an identifier, return null. Else, return the identifier - -- as a symbol. - - procedure Safe_String_Eval - (E : Expr; - Result : out Unbounded_Text_Type; - Success : out Boolean); - -- Evaluate the given Expr E and set Result to the evaluated string - -- and Success to True if it could be evaluated, otherwise set - -- Success to False. - - ---------------------- - -- Safe_String_Eval -- - ---------------------- - - procedure Safe_String_Eval - (E : Expr; - Result : out Unbounded_Text_Type; - Success : out Boolean) - is - use Libadalang.Expr_Eval; - begin - -- TODO??? Check for P_Is_Static_Expr prior to evaluating - -- when eng/libadalang/libadalang#1359 is implemented instead of - -- using exception handling. - - declare - String_Expr_Eval : constant Eval_Result := Expr_Eval (E); - begin - if String_Expr_Eval.Kind /= String_Lit then - Success := False; - return; - end if; - Result := As_String (String_Expr_Eval); - Success := True; - end; - exception - when Property_Error => - Success := False; - end Safe_String_Eval; - - Nb_Children : constant Natural := Prag_Args.Children_Count; - Kind : Symbol_Type; - Result : ALI_Annotation; - - -- Start of processing for Process_Annotation - - begin - -- Ignore all but Xcov annotations - - if Get_Arg (Prag_Args, 1) /= As_Symbol (Xcov) then - return; - end if; - - -- Decode the annotation kind - - if Nb_Children = 1 then - Report (N, "Xcov annotation kind missing", Warning); - return; - end if; - - Kind := Get_Arg (Prag_Args, 2); - begin - Result.Kind := Src_Annotation_Kind'Value (Image (Kind)); - exception - when Constraint_Error => - Report - (N, - "Invalid Xcov annotation kind" - & (if Kind /= No_Symbol then ": " & Image (Kind) else ""), - Warning); - return; - end; - - -- End the statement block if this is a Dump/Reset_Buffers - -- annotation. - - if Result.Kind in Dump_Buffers | Reset_Buffers then - End_Statement_Block (UIC); - Start_Statement_Block (UIC); - end if; - - -- Now that the annotation kind is known, validate the remaining - -- arguments expected for that kind. - - case Result.Kind is - when Exempt_On | Cov_Off => - - -- Expected formats: - -- * (Xcov, ) - -- * (Xcov, , "Justification") - - if Result.Kind = Cov_Off then - UIC.Disable_Coverage := True; - end if; - case Nb_Children is - when 2 => - if Result.Kind = Exempt_On then - Report - (N, "No justification given for exempted region", - Warning); - elsif Result.Kind = Cov_Off then - Report - (N, - "No justification given for disabled coverage region", - Warning); - end if; - UIC.Annotations.Append - (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); - - when 3 => - declare - String_Value : Unbounded_Text_Type; - Success : Boolean; - begin - Safe_String_Eval - (Prag_Arg_Expr (Prag_Args, 3), String_Value, Success); - if not Success then - Report - (N, - "Invalid justification argument: static string" - & " expression expected", - Warning); - return; - end if; - Result.Message := new String' - (To_UTF8 (To_Text (String_Value))); - - UIC.Annotations.Append - (Annotation_Couple' - ((UIC.SFI, +Sloc (N)), Result)); - end; - - when others => - Report (N, "At most 3 pragma arguments allowed", Warning); - return; - end case; - - when Exempt_Off => - if Nb_Children > 2 then - Report - (N, "At most 2 pragma arguments allowed", Warning); - return; - end if; - UIC.Annotations.Append - (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); - - when Cov_On => - if Nb_Children > 2 then - Report - (N, "At most 2 pragma arguments allowed", Warning); - return; - end if; - UIC.Disable_Coverage := False; - UIC.Annotations.Append - (Annotation_Couple'((UIC.SFI, +Sloc (N)), Result)); - - when Dump_Buffers => - - -- Expected formats: - -- * (Xcov, Dump_Buffers) - -- * (Xcov, Dump_Buffers, Prefix) - - case Nb_Children is - when 2 | 3 => - - -- TODO??? check that the Prefix expression is a string - -- type when eng/libadalang/libadalang#1360 is dealt - -- with. - - null; - - when others => - Report (N, "At most 3 pragma arguments allowed", Warning); - return; - end case; - - when Reset_Buffers => - if Nb_Children /= 2 then - Report (N, "At most 2 pragma arguments allowed", Warning); - return; - end if; - end case; - end Process_Annotation; - ------------------------------------ -- Traverse_Degenerate_Subprogram -- ------------------------------------ @@ -5480,7 +5480,7 @@ package body Instrument.Ada_Unit is -- If this is a coverage exemption, record it. Raise -- a warning if the annotation could not be processed. - Process_Annotation (N, Prag_Args); + Process_Annotation (UIC, N, Prag_Args); Instrument_Statement (UIC, N, 'P'); -- Even though Compile_Time_* pragmas do contain @@ -5811,6 +5811,12 @@ package body Instrument.Ada_Unit is Kind => Warning); end if; end; + elsif + Instrument.Ada_Unit.Pragma_Name (N.As_Pragma_Node) + = Name_Annotate + then + Process_Annotation + (UIC, N, N.As_Pragma_Node.F_Args); end if; end; end if; From cc999b9883ff57604fc6094cea37b78e2df5401e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 8 Oct 2024 16:19:34 +0200 Subject: [PATCH 0978/1483] instrument-ada_unit.adb: ignore buffer annotations not in statement lists This is to avoid generating invalid code, or messing up the internal insturmented state. --- .../326-pragma-loc-check/src/pkg.adb | 10 +++++++ .../326-pragma-loc-check/src/pkg.ads | 5 ++++ .../326-pragma-loc-check/src/test_pkg.adb | 13 ++++++++ .../instr-cov/326-pragma-loc-check/test.opt | 2 ++ .../instr-cov/326-pragma-loc-check/test.py | 30 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 26 +++++++++++++--- 6 files changed, 82 insertions(+), 4 deletions(-) create mode 100644 testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/326-pragma-loc-check/src/test_pkg.adb create mode 100644 testsuite/tests/instr-cov/326-pragma-loc-check/test.opt create mode 100644 testsuite/tests/instr-cov/326-pragma-loc-check/test.py diff --git a/testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.adb b/testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.adb new file mode 100644 index 000000000..55676c850 --- /dev/null +++ b/testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.adb @@ -0,0 +1,10 @@ +pragma Annotate (Xcov, Dump_Buffers); +package body Pkg is + + procedure Wrong_Do_Dump is + pragma Annotate (Xcov, Dump_Buffers); + begin + null; -- # st + end Wrong_Do_Dump; + +end Pkg; diff --git a/testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.ads b/testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.ads new file mode 100644 index 000000000..11a9a44b9 --- /dev/null +++ b/testsuite/tests/instr-cov/326-pragma-loc-check/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + procedure Wrong_Do_Dump; + +end Pkg; diff --git a/testsuite/tests/instr-cov/326-pragma-loc-check/src/test_pkg.adb b/testsuite/tests/instr-cov/326-pragma-loc-check/src/test_pkg.adb new file mode 100644 index 000000000..b19097822 --- /dev/null +++ b/testsuite/tests/instr-cov/326-pragma-loc-check/src/test_pkg.adb @@ -0,0 +1,13 @@ +with Pkg; + +procedure Test_Pkg is +begin + Pkg.Wrong_Do_Dump; + pragma Annotate (Xcov, Dump_Buffers, "test_pkg"); +end Test_Pkg; + +-- st can only be covered if both buffer annotations have been ignored + +--# pkg.adb +-- +-- /st/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/326-pragma-loc-check/test.opt b/testsuite/tests/instr-cov/326-pragma-loc-check/test.opt new file mode 100644 index 000000000..cead7225e --- /dev/null +++ b/testsuite/tests/instr-cov/326-pragma-loc-check/test.opt @@ -0,0 +1,2 @@ +bin-traces DEAD test concerns src-trace specific feature +5.04a1 DEAD unknown pragma for the compiler diff --git a/testsuite/tests/instr-cov/326-pragma-loc-check/test.py b/testsuite/tests/instr-cov/326-pragma-loc-check/test.py new file mode 100644 index 000000000..fe6246e97 --- /dev/null +++ b/testsuite/tests/instr-cov/326-pragma-loc-check/test.py @@ -0,0 +1,30 @@ +""" +Test that buffer dump/reset annotation pragmas located in a location other than +a statement sequence are reported and ignored. +""" + +import os + +from SUITE.context import thistest +from SUITE.tutils import contents_of +from SCOV.tctl import CAT, CovControl +from SCOV.tc import TestCase + +warning_regexp = ( + r"(\n?\*\*\* pkg\.adb:.*: warning: Incorrect placement" + r" for a buffer dump/reset annotation, the pragma should" + r" be placed in a statement sequence\.)" +) + +TestCase(category=CAT.stmt, tolerate_messages=warning_regexp).run( + CovControl(instroptions="--dump-trigger=manual") +) + +# Actually check that we got the expected messages +thistest.fail_if_no_match( + "missing or unexpected messaged from gnatcov instrument", + regexp=warning_regexp + "+", + actual=contents_of(os.path.join("s_pkg", "xinstr.out")), +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 74dc82708..379bda5c3 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3435,12 +3435,17 @@ package body Instrument.Ada_Unit is return; end; - -- End the statement block if this is a Dump/Reset_Buffers - -- annotation. + -- Check whether the buffer annotations are in a statement sequence. + -- If not, silently ignore it, it will be reported by the pass dedicated + -- to them. Otherwise, end the statement block. if Result.Kind in Dump_Buffers | Reset_Buffers then - End_Statement_Block (UIC); - Start_Statement_Block (UIC); + if N.Parent.Kind in Ada_Stmt_List then + End_Statement_Block (UIC); + Start_Statement_Block (UIC); + else + return; + end if; end if; -- Now that the annotation kind is known, validate the remaining @@ -9335,6 +9340,19 @@ package body Instrument.Ada_Unit is (Is_Expected_Argument (Prag_Args, 2, Dump_Buffers) or else Is_Expected_Argument (Prag_Args, 2, Reset_Buffers)) then + -- First, check that we are in a statement list, no point in + -- generating invalid code. + + if Prag_N.Parent.Kind not in Ada_Stmt_List then + Report + (Prag_N, + "Incorrect placement for a buffer dump/reset" + & " annotation, the pragma should be placed in a" + & " statement sequence.", + Warning); + return Over; + end if; + -- The pragma statement to be replaced by the actual call -- to Dump_Buffers / Reset_Buffers has been found. From ba69ccffbf71ca372aa497f382a82fefb588168a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 23 Oct 2024 16:48:09 +0200 Subject: [PATCH 0979/1483] Add missing parsing case for the -include switch --- testsuite/tests/instr-cov/include_switch/main.c | 1 + testsuite/tests/instr-cov/include_switch/pkg4.h | 7 +++++++ testsuite/tests/instr-cov/include_switch/test.py | 4 +++- .../integrated_instrumentation/include_switch/test.py | 1 + tools/gnatcov/instrument-common.adb | 11 ++++++++--- tools/gnatcov/instrument-gcc_wrapper.adb | 11 ++++++----- 6 files changed, 26 insertions(+), 9 deletions(-) create mode 100644 testsuite/tests/instr-cov/include_switch/pkg4.h diff --git a/testsuite/tests/instr-cov/include_switch/main.c b/testsuite/tests/instr-cov/include_switch/main.c index 82649a864..36cedc329 100644 --- a/testsuite/tests/instr-cov/include_switch/main.c +++ b/testsuite/tests/instr-cov/include_switch/main.c @@ -4,6 +4,7 @@ main (void) hello_from_pkg1 (); hello_from_pkg2 (); hello_from_pkg3 (); + hello_from_pkg4 (); return 0; } diff --git a/testsuite/tests/instr-cov/include_switch/pkg4.h b/testsuite/tests/instr-cov/include_switch/pkg4.h new file mode 100644 index 000000000..8571386eb --- /dev/null +++ b/testsuite/tests/instr-cov/include_switch/pkg4.h @@ -0,0 +1,7 @@ +extern void print_msg (const char *msg); + +void +hello_from_pkg4 (void) +{ + print_msg ("Hello from pkg4\n"); +} diff --git a/testsuite/tests/instr-cov/include_switch/test.py b/testsuite/tests/instr-cov/include_switch/test.py index 4cfb3bc0a..56e9e3f63 100644 --- a/testsuite/tests/instr-cov/include_switch/test.py +++ b/testsuite/tests/instr-cov/include_switch/test.py @@ -17,6 +17,7 @@ ["--include=../pkg1.h"], ["--include", "../pkg2.h"], ["-include", "../pkg3.h"], + ["-include../pkg4.h"], ] build_run_and_coverage( @@ -35,10 +36,11 @@ check_xcov_reports( "xcov", { - "main.c.xcov": {"+": {4, 5, 6, 13}}, + "main.c.xcov": {"+": {4, 5, 6, 7, 8, 14}}, "pkg1.h.xcov": {"+": {6}}, "pkg2.h.xcov": {"+": {6}}, "pkg3.h.xcov": {"+": {6}}, + "pkg4.h.xcov": {"+": {6}}, }, ) diff --git a/testsuite/tests/integrated_instrumentation/include_switch/test.py b/testsuite/tests/integrated_instrumentation/include_switch/test.py index d37055912..722a50312 100644 --- a/testsuite/tests/integrated_instrumentation/include_switch/test.py +++ b/testsuite/tests/integrated_instrumentation/include_switch/test.py @@ -43,6 +43,7 @@ cmdrun(["gcc", "-include", "glob.h", "test.c", "-o", "test"], for_pgm=False) cmdrun(["gcc", "--include", "glob.h", "test.c", "-o", "test"], for_pgm=False) cmdrun(["gcc", "--include=glob.h", "test.c", "-o", "test"], for_pgm=False) +cmdrun(["gcc", "-include./glob.h", "test.c", "-o", "test"], for_pgm=False) # Run the executable cmdrun(["test"], for_pgm=False) diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index c74578eff..991f625f8 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -692,13 +692,18 @@ package body Instrument.Common is then Self.Compiler_Switches.Append (+A); - elsif Has_Prefix (A, "--include=") then - Self.Include_Files.Append (+A (11 .. A'Last)); - elsif A in "-include" | "--include" then Self.Include_Files.Append (Args (I + 1)); I := I + 1; + + elsif Has_Prefix (A, "--include=") then + Self.Include_Files.Append (+A (11 .. A'Last)); + + elsif Has_Prefix (A, "-include") then + Self.Include_Files.Append (+A (9 .. A'Last)); + end if; + I := I + 1; end; end loop; diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 64a8d51bd..6b87b095e 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -625,13 +625,14 @@ is begin while Has_Element (Cur) loop declare - Arg : constant Unbounded_String := Element (Cur); + Arg : constant Unbounded_String := Element (Cur); + Arg_Str : constant String := +Arg; begin - if Starts_With (Arg, "--include=") then - null; - elsif Starts_With (Arg, "-include") - or else Starts_With (Arg, "--include") + if Starts_With (Arg, "--include=") + or else Starts_With (Arg, "-include") then + null; + elsif Arg_Str in "-include" | "--include" then Cur := Next (Cur); else Result.Append (Element (Cur)); From 7f140d132f2689e20708780ea9d1557bcc7f0261 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 11 Oct 2024 11:53:03 +0200 Subject: [PATCH 0980/1483] Makefile: add support to run GNATsas on gnatcov codebase --- tools/gnatcov/Makefile | 22 ++++++++++++++++++++++ tools/gnatcov/gnatcov.gpr | 21 +++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index 98e2128b7..d74a71274 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -360,6 +360,28 @@ gnat_util.gpr: @echo " for source_dirs use (\"$(GU_SUBDIR)\");" >> $@ @echo "end gnat_util;" >> $@ +# GNATsas + +# This is equivalent to the default run performed during CI +GNATSAS_ARGS=-XBUILD_MODE=$(BUILD_MODE) -XPART=gnatcov64 +GNATSAS_OBJ_DIR=obj64/$(BUILD_MODE) +gnatsas: + rm -f $(OBJ_DIR)/results + gnatsas analyze -P gnatcov.gpr $(GNATSAS_ARGS) + gnatsas report text -P gnatcov.gpr $(GNATSAS_ARGS) + if gnatsas report exit-code -P gnatcov.gpr $(GNATSAS_ARGS); then \ + echo "gnatsas:PASSED" >> $(GNATSAS_OBJ_DIR)/results ; \ + else \ + echo "gnatsas:FAILED:unexpected messages" >> $(GNATSAS_OBJ_DIR)/results ; \ + gnatsas report -P gnatcov.gpr -o $(GNATSAS_OBJ_DIR)/gnatsas.out \ + $(GNATSAS_ARGS) ; \ + fi + gnatsas report code-climate -P gnatcov.gpr \ + -o $(GNATSAS_OBJ_DIR)/gnatsas/gnatsas.json $(GNATSAS_ARGS) ; + +bump_baseline: + gnatsas baseline --bump-baseline -P gnatcov.gpr $(GNATSAS_ARGS) + .PHONY: force force: diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index ea2765b19..e4033bc00 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -271,6 +271,27 @@ project Gnatcov is for VCS_Repository_Root use "../.."; end IDE; + package Analyzer is + for Switches ("analyze") use + ("-j0", + "--incrementality-method=minimal", + "--no-subprojects", + "--no-inspector", + "--no-gnat"); + + Filter := ("--show", "age=added+removed"); + for Switches ("report text") use Filter; + for Switches ("report exit-code") use Filter; + for Switches ("report code-climate") use Filter & ("--long-desc"); + + for Review_File use "analyzer/gnatcov.sar"; + + for Output_Dir use "analyzer"; + -- Relocate outputs outside of object directory because that one is + -- cached in CIs and we do not want to store baselines in the cache. + + end Analyzer; + ------------------------------------------- -- Configuration of sources/object files -- ------------------------------------------- From f0cc6fb143c2cd328f77ee3c215a00e42374a5ea Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 11 Oct 2024 12:13:56 +0200 Subject: [PATCH 0981/1483] Add support for GNATSAS job in gitlab CI --- .gitlab-ci.yml | 9 +++++++++ utils/ci/interruptible.yml | 2 ++ 2 files changed, 11 insertions(+) create mode 100644 utils/ci/interruptible.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 81eb1efac..e02224c8f 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -9,6 +9,14 @@ variables: GITLAB_REMOTE: "https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/" PIP_INDEX_URL: "https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.adacore-it.com/api/v4/projects/202/packages/pypi/simple" +include: + #TODO: workaround to allow dynamically setting the interruptible policy until https://gitlab.com/gitlab-org/gitlab/-/issues/194023 is implemented + - local: utils/ci/interruptible.yml + rules: + - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH + - project: eng/codepeer/ci-registry + file: /gnatsas-on-gnatcov.yml + .basic_setup: &basic_setup - unset GITLAB_TOKEN - generic_anod_ci --add-dep eng/das/cov/gnatcoverage-extra @@ -18,6 +26,7 @@ variables: stages: - build - test + - check build: interruptible: true diff --git a/utils/ci/interruptible.yml b/utils/ci/interruptible.yml new file mode 100644 index 000000000..cf6fd95fe --- /dev/null +++ b/utils/ci/interruptible.yml @@ -0,0 +1,2 @@ +default: + interruptible: true From 05ccd3603217b6d24bc175e3c4c44e590d2d46d2 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 11 Oct 2024 12:14:49 +0200 Subject: [PATCH 0982/1483] Add explicit variable initialization This does not fix a bug, but GNATSAS no longer issue validity check messages. --- tools/gnatcov/annotations-report.adb | 4 ++-- tools/gnatcov/decision_map.adb | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 32e025bbb..03f2eacc7 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -290,10 +290,10 @@ package body Annotations.Report is Output : constant File_Access := Get_Output; - Total_Exempted_Regions : Natural; + Total_Exempted_Regions : Natural := 0; Total_Exempted_Violations : Natural := 0; - Total_Disabled_Cov_Regions : Natural; + Total_Disabled_Cov_Regions : Natural := 0; function Has_Exempted_Region return Boolean; -- True iff there's at least one exempted region diff --git a/tools/gnatcov/decision_map.adb b/tools/gnatcov/decision_map.adb index 49f50338e..584647146 100644 --- a/tools/gnatcov/decision_map.adb +++ b/tools/gnatcov/decision_map.adb @@ -1136,7 +1136,7 @@ package body Decision_Map is -- Check that there is a possible outcome from this condition declare - Outcome_Seen : Boolean; + Outcome_Seen : Boolean := False; -- Set True when there is a value of the condition that -- determines an outcome of the decision. From ab9fec023d50833666ad3a2a0c1155b480fc8c76 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 11 Oct 2024 12:16:49 +0200 Subject: [PATCH 0983/1483] Remove uneeded with / use clauses --- tools/gnatcov/instrument-ada_unit.adb | 1 - tools/gnatcov/instrument-c.adb | 2 -- 2 files changed, 3 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 379bda5c3..74133e1b9 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -7633,7 +7633,6 @@ package body Instrument.Ada_Unit is -------------------- function Bool_Expr_Eval (E : Expr) return String is - use Libadalang.Expr_Eval; begin return To_String (Libadalang.Expr_Eval.Expr_Eval (E).Enum_Result.Text); exception diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 172f97ff0..1945a22d3 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2565,8 +2565,6 @@ package body Instrument.C is end case; end Curlify; - use Cursor_Vectors; - -- Start of processing for Traverse_Statements begin From 18b7da615dd2decac9fed4aab51fced444fb45ac Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 11 Oct 2024 12:17:09 +0200 Subject: [PATCH 0984/1483] Remove unused and undocumented option --- testsuite/tests/IA21-003-simple-decision-sco/test.py | 3 ++- tools/gnatcov/command_line.ads | 9 --------- tools/gnatcov/gnatcov_bits_specific.adb | 1 - 3 files changed, 2 insertions(+), 11 deletions(-) diff --git a/testsuite/tests/IA21-003-simple-decision-sco/test.py b/testsuite/tests/IA21-003-simple-decision-sco/test.py index f96ee8e49..dce1fc8fc 100644 --- a/testsuite/tests/IA21-003-simple-decision-sco/test.py +++ b/testsuite/tests/IA21-003-simple-decision-sco/test.py @@ -25,7 +25,8 @@ "--level=stmt", "--annotate=report", "--scos=obj/pack.ali", - "--report=out", + "-o", + "out", tracename_for("p"), ] ) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 66f9ab427..c0a4cbf77 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -120,7 +120,6 @@ package Command_Line is Opt_Coverage_Level, Opt_Text_Start, Opt_Exec_Prefix, - Opt_Final_Report, Opt_HW_Trigger_Traces, Opt_Input, Opt_Separate, @@ -865,14 +864,6 @@ package Command_Line is & " for them in the PREFIX directory.", At_Most_Once => False, Internal => True), - Opt_Final_Report => Create - (Long_Name => "--report", - Pattern => "[FILE]", - Help => "??? This option is redundant with --option and is" - & " not documented in the User Manual.", - Commands => (Cmd_Coverage => True, others => False), - At_Most_Once => False, - Internal => True), Opt_HW_Trigger_Traces => Create (Long_Name => "--hw-trigger-traces", Pattern => "[START_ID],[START_ADDR],[STOP_ID]", diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 2ab310cfe..f646edb4f 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -522,7 +522,6 @@ procedure GNATcov_Bits_Specific is end if; Copy_Arg (Opt_Output, Output); - Copy_Arg (Opt_Final_Report, Output); Copy_Arg (Opt_Tag, Tag); Copy_Arg (Opt_Kernel, Kernel); Copy_Arg (Opt_HW_Trigger_Traces, Convert.HW_Trigger_Arg); From 8177a54bf4a948a6926781303a6679177657212f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 11 Oct 2024 12:18:00 +0200 Subject: [PATCH 0985/1483] Fix memory leaks --- tools/gnatcov/instrument-input_traces.adb | 1 + tools/gnatcov/sc_obligations.adb | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 46eb2811d..1c6cf50a5 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -777,6 +777,7 @@ package body Instrument.Input_Traces is Free (Statement_Buffer); Free (Decision_Buffer); Free (MCDC_Buffer); + Free (Stream.Buffer); Close (Stream.File); end Generic_Read_Source_Trace_File; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index f4633435a..93ed905e7 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -5930,6 +5930,10 @@ package body SC_Obligations is end if; Close (ALI_File); + + if Line /= null then + Free (Line); + end if; return ALI_Index; end Load_ALI; From e55168deafdd3dc94f6543c0742e93ed1bc9a6f0 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 11 Oct 2024 12:18:37 +0200 Subject: [PATCH 0986/1483] Error out on unsupported case --- tools/gnatcov/traces_elf.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/traces_elf.adb b/tools/gnatcov/traces_elf.adb index 2dd1248e1..3dc69dfe4 100644 --- a/tools/gnatcov/traces_elf.adb +++ b/tools/gnatcov/traces_elf.adb @@ -1729,7 +1729,7 @@ package body Traces_Elf is Read_Byte (Base, Off, Ptr_Sz); else - Put_Line ("!! DWARF version not supported: " & Version'Img); + Outputs.Fatal_Error ("Unsupported DWARF version:" & Version'Img); end if; Exec.Addr_Size := Natural (Ptr_Sz); From 7d08672dcce6068bbb6a7c875ded62da7af4753e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 22 Oct 2024 14:06:28 +0200 Subject: [PATCH 0987/1483] Initialize Old_PC --- tools/gnatcov/cfg_dump.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/cfg_dump.adb b/tools/gnatcov/cfg_dump.adb index 0d8f14c29..b9a4702af 100644 --- a/tools/gnatcov/cfg_dump.adb +++ b/tools/gnatcov/cfg_dump.adb @@ -346,7 +346,7 @@ package body CFG_Dump is -- Address of the first byte of the instruction we are about to -- disassemble. - Old_PC : Pc_Type; + Old_PC : Pc_Type := Code.First; -- Likewise for the previous instruction Sym_Cur : Address_Info_Sets.Cursor := From 1f56be1969d173c3e90ad82f7ac40a290fccc646 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 22 Oct 2024 14:28:37 +0200 Subject: [PATCH 0988/1483] Use option type to return values --- tools/gnatcov/mc_dc.adb | 14 ++++++-------- tools/gnatcov/sc_obligations.adb | 13 ++++++------- tools/gnatcov/sc_obligations.ads | 22 ++++++++++++++++------ 3 files changed, 28 insertions(+), 21 deletions(-) diff --git a/tools/gnatcov/mc_dc.adb b/tools/gnatcov/mc_dc.adb index 14da76074..f04574231 100644 --- a/tools/gnatcov/mc_dc.adb +++ b/tools/gnatcov/mc_dc.adb @@ -96,21 +96,19 @@ package body MC_DC is Values : Vector; - C_SCO : SCO_Id; - Prev_C_SCO : SCO_Id; - Prev_C_Value : Boolean; + C_SCO : SCO_Id; + Prev : Maybe_SCO_Value; begin Values := To_Vector (Unknown, Length => Count_Type (Index (Condition))); C_SCO := Condition; loop - Get_Origin (C_SCO, Prev_C_SCO, Prev_C_Value); - exit when Prev_C_SCO = No_SCO_Id; + Prev := Get_Origin (C_SCO); + exit when Prev.Present = False; - Values.Replace_Element - (Index (Prev_C_SCO), To_Tristate (Prev_C_Value)); - C_SCO := Prev_C_SCO; + Values.Replace_Element (Index (Prev.SCO), To_Tristate (Prev.Value)); + C_SCO := Prev.SCO; end loop; return Values; end Infer_Values; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 93ed905e7..080d89c25 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -2663,10 +2663,7 @@ package body SC_Obligations is -- Get_Origin -- ---------------- - procedure Get_Origin - (SCO : SCO_Id; - Prev_SCO : out SCO_Id; - Prev_Value : out Boolean) + function Get_Origin (SCO : SCO_Id) return Maybe_SCO_Value is use BDD; @@ -2674,10 +2671,12 @@ package body SC_Obligations is BDDN : BDD_Node renames BDD_Vector (SCOD.BDD_Node); begin if BDDN.Parent = No_BDD_Node_Id then - Prev_SCO := No_SCO_Id; + return Maybe_SCO_Value'(Present => False); else - Prev_SCO := BDD_Vector.Constant_Reference (BDDN.Parent).C_SCO; - Prev_Value := BDDN.Parent_Value; + return Maybe_SCO_Value' + (Present => True, + SCO => BDD_Vector.Constant_Reference (BDDN.Parent).C_SCO, + Value => BDDN.Parent_Value); end if; end Get_Origin; diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 300d08b88..0209d4805 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -710,13 +710,23 @@ package SC_Obligations is function Offset_For_True (SCO : SCO_Id) return Natural; -- Offset to be added to BDD path index when this condition is True - procedure Get_Origin - (SCO : SCO_Id; - Prev_SCO : out SCO_Id; - Prev_Value : out Boolean); + type Maybe_SCO_Value (Present : Boolean := False) is record + case Present is + when False => + null; + when True => + SCO : SCO_Id; + Value : Boolean; + end case; + end record; + + function Get_Origin (SCO : SCO_Id) return Maybe_SCO_Value; -- For a condition SCO that is part of a decision with no multipath, - -- condition, return the previous tested condition and the value of - -- that condition causing the condition denoted by SCO to be evaluated. + -- condition, return the previous tested condition (Result.SCO) and the + -- value of that condition (Result.Value) causing the condition denoted by + -- SCO to be evaluated. In other cases (the condition can be reached + -- through multiple paths, or it is the root node), return + -- Maybe_SCO_Value'(Present => False). -- Operator SCOs From 741ae69d612b587fc8071d46b83cbabba6adb0b7 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 22 Oct 2024 14:29:04 +0200 Subject: [PATCH 0989/1483] Explicitly mark unreachable code --- tools/gnatcov/annotations.adb | 3 +++ tools/gnatcov/instrument-gcc_wrapper.adb | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index d51780795..cd1d248ca 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -321,6 +321,9 @@ package body Annotations is elsif Coverage.Enabled (Decision) then SCO_State := Get_Line_State (SCO, Decision); + + else + raise Program_Error; end if; Pretty_Print_Start_Decision (Pp, SCO, SCO_State); diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 6b87b095e..26416b024 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -393,6 +393,12 @@ is Result.Language := CPP_Language; elsif Ends_With (Command.First_Element, "cc1") then Result.Language := C_Language; + else + -- Unreachable code. Parse_Compilation_Command is always called with + -- Command's first argument being cc1plus or cc1 (see the if guard + -- around the single calling reference). + + raise Program_Error; end if; -- Skip the first argument as it is the compiler executable, and not From f21ab982bfe8ad686fb8eca97d967aaf0e571d30 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 22 Oct 2024 16:23:08 +0200 Subject: [PATCH 0990/1483] Always set returned value To "no instruction to disassemble" by default. --- tools/gnatcov/elf_disassemblers.adb | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/elf_disassemblers.adb b/tools/gnatcov/elf_disassemblers.adb index caee79b89..6096f54f0 100644 --- a/tools/gnatcov/elf_disassemblers.adb +++ b/tools/gnatcov/elf_disassemblers.adb @@ -211,6 +211,7 @@ package body Elf_Disassemblers is and then I_Range.Insn_Set = Data); begin + Insn_Set := Data; Cache.Cur := Next (Cache.Cur); if Cache.Cur /= No_Element then declare From 822ddf6eedc6dd1c59abf412a66f65ea94e3467c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 22 Oct 2024 16:26:18 +0200 Subject: [PATCH 0991/1483] Use a Program_Error raising procedure rather than a null proc To avoid gnatsas from raising messages about unitialized out parameter values. --- tools/gnatcov/instrument-common.adb | 14 ++++++++++++++ tools/gnatcov/instrument-common.ads | 6 +++++- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 991f625f8..917689e96 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -783,6 +783,20 @@ package body Instrument.Common is end loop; end Populate_Ext_Disabled_Cov; + -------------------------------- + -- Replace_Manual_Indications -- + -------------------------------- + + procedure Replace_Manual_Indications + (Self : in out Language_Instrumenter; + Prj : in out Prj_Desc; + Source : GNATCOLL.Projects.File_Info; + Has_Dump_Indication : out Boolean; + Has_Reset_Indication : out Boolean) is + begin + raise Program_Error; + end Replace_Manual_Indications; + begin Sys_Prefix.Append (To_Unbounded_String ("GCVRT")); diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index f5d13b4c1..59e9f2323 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -528,7 +528,7 @@ package Instrument.Common is Prj : in out Prj_Desc; Source : GNATCOLL.Projects.File_Info; Has_Dump_Indication : out Boolean; - Has_Reset_Indication : out Boolean) is null; + Has_Reset_Indication : out Boolean); -- Look for the pragmas (for Ada) or comments (for C family languages) -- indicating where the user wishes to the buffers to be dumped and/or -- reset in Source. @@ -540,6 +540,10 @@ package Instrument.Common is -- -- Likewise, Has_Reset_Indication indicates whether a manual buffer reset -- indication was found and processed. + -- + -- We expect this primitive to be overridden by actual instrumenters, but + -- not stub instrumenters (e.g. the one declared in instrument-c__stub) in + -- which case it will raise a Program_Error. function New_File (Prj : Prj_Desc; Name : String) return String; From 313980837dc15980f88a1159ec90381ffd149b6a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 11 Oct 2024 14:48:47 +0200 Subject: [PATCH 0992/1483] Add gnatsas baseline --- .../analyzer/gnatcov._no_sub.baseline.sam | 2501 +++++++++++++++++ 1 file changed, 2501 insertions(+) create mode 100644 tools/gnatcov/analyzer/gnatcov._no_sub.baseline.sam diff --git a/tools/gnatcov/analyzer/gnatcov._no_sub.baseline.sam b/tools/gnatcov/analyzer/gnatcov._no_sub.baseline.sam new file mode 100644 index 000000000..6a6fe5b40 --- /dev/null +++ b/tools/gnatcov/analyzer/gnatcov._no_sub.baseline.sam @@ -0,0 +1,2501 @@ +{ + "info": { + "sam_version": 1, + "host": "Unix", + "sar_checksum": [ "db3236eab36625b745cfd5f42eb879d4" ], + "gnatsas_version": "GNATSAS 26.0w (20241010)", + "date": "2024-10-22 16:32:37", + "root_project_name": "gnatcov", + "tools": [ + { + "tool": "Gnat", + "command_line": "codepeer-gprbuild -Pgnatcov.gpr -XPART=gnatcov64 -XBUILD_MODE=dev -ws -j2 -k -s --unchecked-shared-lib-imports -m --db /home/eyraud/sbx/wave/x86_64-linux/gnatsas-edge/install/share/gnatsas/config --target=gnatsas --complete-output --no-object-check --restricted-to-languages=Ada --subdirs=gnatsas/gnatcov.gnat/obj -c -u -gnatc -gnatd.M -gnatef -gnatw.d -gnatj10000 -gnatw.ab.bxwq.r.ir.m.pvm -gnatwn -cargs -fdiagnostics-format=json" + }, + { + "tool": "Infer", + "command_line": "infer --reactive --incremental-analysis --quiet --scheduler=components --no-default-checkers --value --pulse --force-delete-results-dir --results-dir=/home/eyraud/gnatcoverage/tools/gnatcov/obj64/dev/gnatsas/gnatcov.infer/infer.out --report-force-relative-path --project-root=/home/eyraud/gnatcoverage/tools/gnatcov/ --backtrack-level=1000 --jobs=2 --changed-files-index=/home/eyraud/gnatcoverage/tools/gnatcov/obj64/dev/gnatsas/infer_changed_files_index --report-changed-files-only --progress-bar-style plain -- gprbuild -P /home/eyraud/gnatcoverage/tools/gnatcov/gnatcov.gpr -XPART=gnatcov64 -XBUILD_MODE=dev --target gnatsas --files-from /home/eyraud/gnatcoverage/tools/gnatcov/obj64/dev/gnatsas/gnatcov.gnatsas/capture_sources.txt" + }, + { + "tool": "Gnatcheck", + "command_line": "gnatcheck -m0 -q -j2 -l -o /home/eyraud/gnatcoverage/tools/gnatcov/obj64/dev/gnatsas/gnatcov.gnatcheck/gnatcheck.out -ox /home/eyraud/gnatcoverage/tools/gnatcov/obj64/dev/gnatsas/gnatcov.gnatcheck/gnatcheck.xml --subdirs=gnatsas/gnatcov.gnatcheck -Pgnatcov.gpr --no-subprojects -XPART=gnatcov64 -XBUILD_MODE=dev -rules +Rduplicate_branches +Rsame_logic +Rsame_operands +Rsame_tests +Rsuspicious_equalities" + } + ], + "baseline": { + "file": "gnatcov._no_sub.baseline.sam", + "date": "2024-10-15 14:56:39", + "command_line": "gnatsas analyze -P gnatcov.gpr -XBUILD_MODE=dev -XPART=gnatcov64", + "project_switches": "-j0 --incrementality-method=minimal --no-subprojects --no-inspector", + "checksum": "68a94303edb91a387b0c82d7bed2c11d" + }, + "command_line": "gnatsas analyze -P gnatcov.gpr -XBUILD_MODE=dev -XPART=gnatcov64", + "project_switches": "-j2 --incrementality-method=minimal --no-subprojects --no-inspector", + "review_statuses": { + "Uncategorized": "Uncategorized", + "Pending": "Pending", + "Not A Bug": "Not_a_bug", + "Intentional": "Not_a_bug", + "False Positive": "Not_a_bug", + "Bug": "Bug" + } + }, + "prjs": { + "gnatcov.gpr": [ + { + "file_info": { + "basename": "annotations-cobertura.adb", + "path": "annotations-cobertura.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-cobertura.ads", + "path": "annotations-cobertura.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-dynamic_html.adb", + "path": "annotations-dynamic_html.adb" + }, + "subps": { + "annotations.dynamic_html.set_sco_fields": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "8c1b8f3b9d7ab0555d88e7537d6e38be", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `annotations.sco_image` on line 930 is not freed after the last access at line 937, column 23", + "sloc": { "line": 937, "column": 23 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "annotations-dynamic_html.adb", + "loc": { "line": 930, "column": 30 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "annotations-dynamic_html.adb", + "loc": { "line": 930, "column": 30 }, + "text": "when calling `annotations.sco_image` here" + }, + { + "level": 2, + "file": "annotations.adb", + "loc": { "line": 808, "column": 21 }, + "text": "when calling `annotations.sco_text` here" + }, + { + "level": 3, + "file": "annotations.adb", + "loc": { "line": 729, "column": 16 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 4, + "file": "files_table.adb", + "loc": { "line": 966, "column": 14 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 5, + "file": "files_table.adb", + "loc": { "line": 979, "column": 7 }, + "text": "when calling `files_table.fill_line_cache` here" + }, + { + "level": 6, + "file": "files_table.adb", + "loc": { "line": 654, "column": 7 }, + "text": "when calling `files_table.open` here" + }, + { + "level": 7, + "file": "files_table.adb", + "loc": { "line": 1566, "column": 15 }, + "text": "when calling `paths.build_filename` here" + }, + { + "level": 8, + "file": "paths.adb", + "loc": { "line": 62, "column": 14 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "annotations-dynamic_html.adb", + "loc": { "line": 937, "column": 23 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "annotations-dynamic_html.ads", + "path": "annotations-dynamic_html.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-html.adb", + "path": "annotations-html.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-html.ads", + "path": "annotations-html.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-index.adb", + "path": "annotations-index.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-index.ads", + "path": "annotations-index.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-report.adb", + "path": "annotations-report.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-report.ads", + "path": "annotations-report.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-sarif.adb", + "path": "annotations-sarif.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-sarif.ads", + "path": "annotations-sarif.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-xcov.adb", + "path": "annotations-xcov.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-xcov.ads", + "path": "annotations-xcov.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations-xml.adb", + "path": "annotations-xml.adb" + }, + "subps": { + "annotations.xml.pretty_print_condition": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "ea6cd8676ded724f682f2698efcd1bcb", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `annotations.sco_text` on line 327 is not freed after the last access at line 334, column 31", + "sloc": { "line": 334, "column": 31 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "annotations-xml.adb", + "loc": { "line": 327, "column": 27 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "annotations-xml.adb", + "loc": { "line": 327, "column": 27 }, + "text": "when calling `annotations.sco_text` here" + }, + { + "level": 2, + "file": "annotations.adb", + "loc": { "line": 729, "column": 16 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 3, + "file": "files_table.adb", + "loc": { "line": 966, "column": 14 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 4, + "file": "files_table.adb", + "loc": { "line": 979, "column": 7 }, + "text": "when calling `files_table.fill_line_cache` here" + }, + { + "level": 5, + "file": "files_table.adb", + "loc": { "line": 654, "column": 7 }, + "text": "when calling `files_table.open` here" + }, + { + "level": 6, + "file": "files_table.adb", + "loc": { "line": 1566, "column": 15 }, + "text": "when calling `paths.build_filename` here" + }, + { + "level": 7, + "file": "paths.adb", + "loc": { "line": 62, "column": 14 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "annotations-xml.adb", + "loc": { "line": 334, "column": 31 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ], + "annotations.xml.pretty_print_start_decision": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "ea6cd8676ded724f682f2698efcd1bcb", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `annotations.sco_text` on line 521 is not freed after the last access at line 527, column 36", + "sloc": { "line": 527, "column": 36 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "annotations-xml.adb", + "loc": { "line": 521, "column": 27 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "annotations-xml.adb", + "loc": { "line": 521, "column": 27 }, + "text": "when calling `annotations.sco_text` here" + }, + { + "level": 2, + "file": "annotations.adb", + "loc": { "line": 729, "column": 16 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 3, + "file": "files_table.adb", + "loc": { "line": 966, "column": 14 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 4, + "file": "files_table.adb", + "loc": { "line": 979, "column": 7 }, + "text": "when calling `files_table.fill_line_cache` here" + }, + { + "level": 5, + "file": "files_table.adb", + "loc": { "line": 654, "column": 7 }, + "text": "when calling `files_table.open` here" + }, + { + "level": 6, + "file": "files_table.adb", + "loc": { "line": 1566, "column": 15 }, + "text": "when calling `paths.build_filename` here" + }, + { + "level": 7, + "file": "paths.adb", + "loc": { "line": 62, "column": 14 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "annotations-xml.adb", + "loc": { "line": 527, "column": 36 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ], + "annotations.xml.pretty_print_statement": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "ea6cd8676ded724f682f2698efcd1bcb", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `annotations.sco_text` on line 680 is not freed after the last access at line 687, column 31", + "sloc": { "line": 687, "column": 31 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "annotations-xml.adb", + "loc": { "line": 680, "column": 27 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "annotations-xml.adb", + "loc": { "line": 680, "column": 27 }, + "text": "when calling `annotations.sco_text` here" + }, + { + "level": 2, + "file": "annotations.adb", + "loc": { "line": 729, "column": 16 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 3, + "file": "files_table.adb", + "loc": { "line": 966, "column": 14 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 4, + "file": "files_table.adb", + "loc": { "line": 979, "column": 7 }, + "text": "when calling `files_table.fill_line_cache` here" + }, + { + "level": 5, + "file": "files_table.adb", + "loc": { "line": 654, "column": 7 }, + "text": "when calling `files_table.open` here" + }, + { + "level": 6, + "file": "files_table.adb", + "loc": { "line": 1566, "column": 15 }, + "text": "when calling `paths.build_filename` here" + }, + { + "level": 7, + "file": "paths.adb", + "loc": { "line": 62, "column": 14 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "annotations-xml.adb", + "loc": { "line": 687, "column": 31 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "annotations-xml.ads", + "path": "annotations-xml.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "annotations.adb", + "path": "annotations.adb" + }, + "subps": { + "annotations.disp_scos": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "bfc277166e3f1cab1c98959e46a65727", + "key_seq": 1 + }, + "data": { + "msg": "SCO_State might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 326, "column": 22 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Removed" + } + } + ], + "annotations.sco_text": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "8a8bd52eff4074034eb037a2eaee1d92", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `files_table.end_lex_element` on line 652 is not freed after the last access at line 751, column 17", + "sloc": { "line": 751, "column": 17 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "annotations.adb", + "loc": { "line": 652, "column": 39 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "annotations.adb", + "loc": { "line": 652, "column": 39 }, + "text": "when calling `files_table.end_lex_element` here" + }, + { + "level": 2, + "file": "files_table.adb", + "loc": { "line": 433, "column": 35 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 3, + "file": "files_table.adb", + "loc": { "line": 966, "column": 14 }, + "text": "when calling `files_table.get_line` here" + }, + { + "level": 4, + "file": "files_table.adb", + "loc": { "line": 979, "column": 7 }, + "text": "when calling `files_table.fill_line_cache` here" + }, + { + "level": 5, + "file": "files_table.adb", + "loc": { "line": 654, "column": 7 }, + "text": "when calling `files_table.open` here" + }, + { + "level": 6, + "file": "files_table.adb", + "loc": { "line": 1566, "column": 15 }, + "text": "when calling `paths.build_filename` here" + }, + { + "level": 7, + "file": "paths.adb", + "loc": { "line": 62, "column": 14 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "annotations.adb", + "loc": { "line": 751, "column": 17 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "annotations.ads", + "path": "annotations.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "arch__64.ads", "path": "arch__64.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "argparse.adb", "path": "argparse.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "argparse.ads", "path": "argparse.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "binary_files.adb", + "path": "binary_files.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "binary_files.ads", + "path": "binary_files.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "calendar_utils.adb", + "path": "calendar_utils.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "calendar_utils.ads", + "path": "calendar_utils.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "cfg_dump.adb", "path": "cfg_dump.adb" }, + "subps": { + "cfg_dump.collect_instructions": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "4a52176fed41bc065b8a99344885cb4e", + "key_seq": 1 + }, + "data": { + "msg": "Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 528, "column": 26 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "4a52176fed41bc065b8a99344885cb4e", + "key_seq": 2 + }, + "data": { + "msg": "Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 536, "column": 25 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "4a52176fed41bc065b8a99344885cb4e", + "key_seq": 3 + }, + "data": { + "msg": "Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 544, "column": 19 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "4a52176fed41bc065b8a99344885cb4e", + "key_seq": 4 + }, + "data": { + "msg": "Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 642, "column": 56 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "4a52176fed41bc065b8a99344885cb4e", + "key_seq": 5 + }, + "data": { + "msg": "Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 666, "column": 28 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "86f20cfc6181c4829e56de57edad9d59", + "key_seq": 1 + }, + "data": { + "msg": "Last_Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 528, "column": 49 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "86f20cfc6181c4829e56de57edad9d59", + "key_seq": 2 + }, + "data": { + "msg": "Last_Insn.Selected might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 536, "column": 52 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "e3cfb48b116277ba65fdd7a8bee8c0f6", + "key_seq": 1 + }, + "data": { + "msg": "Old_PC might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 717, "column": 20 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Removed" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "08c65a49805954c02d01890fdb7e9c5d", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new` on line 443 is not freed after the last access at line 717, column 20", + "sloc": { "line": 717, "column": 20 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "cfg_dump.adb", + "loc": { "line": 443, "column": 21 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "cfg_dump.adb", + "loc": { "line": 443, "column": 21 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "cfg_dump.adb", + "loc": { "line": 717, "column": 20 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ], + "cfg_dump.collect_instructions(cfg_dump.context_access, traces_elf.address_info_acc)": [] + } + }, + { + "file_info": { "basename": "cfg_dump.ads", "path": "cfg_dump.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "check_scos.adb", + "path": "check_scos.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "check_scos.ads", + "path": "check_scos.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "checkpoints.adb", + "path": "checkpoints.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "checkpoints.ads", + "path": "checkpoints.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "clang-extensions.adb", + "path": "clang-extensions.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "clang-extensions.ads", + "path": "clang-extensions.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "coff.ads", "path": "coff.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "command_line.adb", + "path": "command_line.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "command_line.ads", + "path": "command_line.ads" + }, + "subps": { + "command_line": [ + { + "msg_id": { + "tool_kind": [ "Gnat", "Default_gnat_warnings" ], + "key": "32f47d5e89e388b8a6f8fcc6dbeb5e9a", + "key_seq": 1 + }, + "data": { + "msg": "in instantiation at argparse.ads:200, component of \"Bool_Option_Info_Array\" padded by 8 bits", + "sloc": { "line": 208, "column": 4 }, + "rank": "Medium", + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { "basename": "commands.adb", "path": "commands.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "commands.ads", "path": "commands.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "compiler_wrappers-gcc.adb", + "path": "compiler_wrappers-gcc.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "compiler_wrappers.ads", + "path": "compiler_wrappers.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "convert.adb", "path": "convert.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "convert.ads", "path": "convert.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage-object.adb", + "path": "coverage-object.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage-object.ads", + "path": "coverage-object.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage-source.adb", + "path": "coverage-source.adb" + }, + "subps": { + "coverage.source.compute_atcc_state": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "fbd69b2f7f0cd8aa93f7b5a68c529d73", + "key_seq": 1 + }, + "data": { + "msg": "Last_Cond_Not_Evaluated might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 1474, "column": 24 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + } + ], + "coverage.source.compute_mcdc_state": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "18eb84a06439c4349d5e2227f9e6b1f9", + "key_seq": 1 + }, + "data": { + "msg": "Last_Cond_No_Pair might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 1350, "column": 24 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "coverage-source.ads", + "path": "coverage-source.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage-tags.adb", + "path": "coverage-tags.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage-tags.ads", + "path": "coverage-tags.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "coverage.adb", "path": "coverage.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "coverage.ads", "path": "coverage.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage_options.adb", + "path": "coverage_options.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "coverage_options.ads", + "path": "coverage_options.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "decision_map.adb", + "path": "decision_map.adb" + }, + "subps": { + "decision_map.analyze_routine": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "90d4f86d18540ad03e69f32cf8b264e9", + "key_seq": 1 + }, + "data": { + "msg": "Insn_Len might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 2794, "column": 22 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "decision_map.ads", + "path": "decision_map.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "diagnostics.adb", + "path": "diagnostics.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "diagnostics.ads", + "path": "diagnostics.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "dis_opcodes.ads", + "path": "libopcodes_bind/dis_opcodes.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_aarch64.adb", + "path": "disa_aarch64.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_aarch64.ads", + "path": "disa_aarch64.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "disa_arm.adb", "path": "disa_arm.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "disa_arm.ads", "path": "disa_arm.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_common.adb", + "path": "disa_common.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_common.ads", + "path": "disa_common.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "disa_lmp.adb", "path": "disa_lmp.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "disa_lmp.ads", "path": "disa_lmp.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "disa_ppc.adb", "path": "disa_ppc.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "disa_ppc.ads", "path": "disa_ppc.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_sparc.adb", + "path": "disa_sparc.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_sparc.ads", + "path": "disa_sparc.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_symbolize.adb", + "path": "disa_symbolize.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_symbolize.ads", + "path": "disa_symbolize.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_thumb.adb", + "path": "disa_thumb.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disa_thumb.ads", + "path": "disa_thumb.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "disa_x86.adb", "path": "disa_x86.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "disa_x86.ads", "path": "disa_x86.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "disassemble_insn_properties.adb", + "path": "disassemble_insn_properties.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disassemble_insn_properties.ads", + "path": "disassemble_insn_properties.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disassemblers.adb", + "path": "disassemblers.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "disassemblers.ads", + "path": "disassemblers.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "display.adb", "path": "display.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "display.ads", "path": "display.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "dwarf.ads", "path": "dwarf.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "dwarf_handling.adb", + "path": "dwarf_handling.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "dwarf_handling.ads", + "path": "dwarf_handling.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "elf32.adb", "path": "elf32.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "elf32.ads", "path": "elf32.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "elf64.adb", "path": "elf64.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "elf64.ads", "path": "elf64.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "elf_common.adb", + "path": "elf_common.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "elf_common.ads", + "path": "elf_common.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "elf_disassemblers.adb", + "path": "elf_disassemblers.adb" + }, + "subps": { + "elf_disassemblers.go_to_next_insn": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "87dc423edec3358707a253916c1fcbb9", + "key_seq": 1 + }, + "data": { + "msg": "out parameter Insn_Set might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 225, "column": 7 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Removed" + } + } + ] + } + }, + { + "file_info": { + "basename": "elf_disassemblers.ads", + "path": "elf_disassemblers.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "elf_files.adb", "path": "elf_files.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "elf_files.ads", "path": "elf_files.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "execs_dbase.adb", + "path": "execs_dbase.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "execs_dbase.ads", + "path": "execs_dbase.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "factory_registry.adb", + "path": "factory_registry.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "factory_registry.ads", + "path": "factory_registry.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "files_handling.adb", + "path": "files_handling.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "files_handling.ads", + "path": "files_handling.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "files_table.adb", + "path": "files_table.adb" + }, + "subps": { + "files_table.checkpoint_clear": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Access_check" ], + "key": "a5ab61ae4c450e2549d54916852c2df2", + "key_seq": 1 + }, + "data": { + "msg": "`FI.all` could be null (null value originating from line 1969) and is dereferenced", + "cwe": [ [ 476 ] ], + "sloc": { "line": 1960, "column": 10 }, + "rank": "High", + "analysis": "Pulse", + "backtrace": [ + { + "level": 1, + "file": "files_table.adb", + "loc": { "line": 1969, "column": 10 }, + "text": "is assigned to the null pointer" + }, + { + "level": 1, + "file": "files_table.adb", + "loc": { "line": 1960, "column": 10 }, + "text": "invalid access occurs here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "files_table.ads", + "path": "files_table.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "gnatcov.adb", "path": "gnatcov.adb" }, + "subps": {} + }, + { + "file_info": { + "basename": "gnatcov_bits_specific.adb", + "path": "gnatcov_bits_specific.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "hex_images.adb", + "path": "hex_images.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "hex_images.ads", + "path": "hex_images.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "highlighting.adb", + "path": "highlighting.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "highlighting.ads", + "path": "highlighting.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "inputs.adb", "path": "inputs.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "inputs.ads", "path": "inputs.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-ada_preprocessing.adb", + "path": "instrument-ada_preprocessing.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-ada_preprocessing.ads", + "path": "instrument-ada_preprocessing.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-ada_unit.adb", + "path": "instrument-ada_unit.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-ada_unit.ads", + "path": "instrument-ada_unit.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-ada_unit_provider.adb", + "path": "instrument-ada_unit_provider.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-ada_unit_provider.ads", + "path": "instrument-ada_unit_provider.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-c.adb", + "path": "instrument-c.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-c.ads", + "path": "instrument-c.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-c_utils.adb", + "path": "instrument-c_utils.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-c_utils.ads", + "path": "instrument-c_utils.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-checkpoints.adb", + "path": "instrument-checkpoints.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-checkpoints.ads", + "path": "instrument-checkpoints.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-clean_objdirs.adb", + "path": "instrument-clean_objdirs.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-clean_objdirs.ads", + "path": "instrument-clean_objdirs.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-common.adb", + "path": "instrument-common.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-common.ads", + "path": "instrument-common.ads" + }, + "subps": { + "instrument.common.replace_manual_indications": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "59287a3a858ba0f412ab294538006a2c", + "key_seq": 1 + }, + "data": { + "msg": "out parameter `Has_Reset_Indication` is not initialized at the end of the subprogram", + "cwe": [ [ 457 ] ], + "sloc": { "line": 531, "column": 52 }, + "rank": "High", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "instrument-common.ads", + "loc": { "line": 526, "column": 4 }, + "text": "parameter `Has_Reset_Indication` of instrument.common.replace_manual_indications" + }, + { + "level": 0, + "file": "instrument-common.ads", + "loc": { "line": 531, "column": 52 }, + "text": "end of the subprogram is here" + } + ], + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "f6825e9f92414db4f641a38556d8ee02", + "key_seq": 1 + }, + "data": { + "msg": "out parameter Has_Reset_Indication might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 531, "column": 52 }, + "rank": "Medium", + "analysis": "Mobsfer", + "duplicate_of": [ + "instrument.common.replace_manual_indications", + { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "59287a3a858ba0f412ab294538006a2c", + "key_seq": 1 + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "instrument-config.adb", + "path": "instrument-config.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-gcc_wrapper.adb", + "path": "instrument-gcc_wrapper.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-input_traces.adb", + "path": "instrument-input_traces.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-input_traces.ads", + "path": "instrument-input_traces.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-main.adb", + "path": "instrument-main.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-projects.adb", + "path": "instrument-projects.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-setup_config.adb", + "path": "instrument-setup_config.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-setup_config.ads", + "path": "instrument-setup_config.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument-source.adb", + "path": "instrument-source.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument.adb", + "path": "instrument.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "instrument.ads", + "path": "instrument.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "json.adb", "path": "json.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "json.ads", "path": "json.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "logging.adb", "path": "logging.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "logging.ads", "path": "logging.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "mc_dc.adb", "path": "mc_dc.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "mc_dc.ads", "path": "mc_dc.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "object_locations.adb", + "path": "object_locations.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "object_locations.ads", + "path": "object_locations.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "outputs.adb", "path": "outputs.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "outputs.ads", "path": "outputs.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "paths.adb", "path": "paths.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "paths.ads", "path": "paths.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "pecoff_files.adb", + "path": "pecoff_files.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "pecoff_files.ads", + "path": "pecoff_files.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "perf_counters.adb", + "path": "perf_counters.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "perf_counters.ads", + "path": "perf_counters.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "ppc_descs.adb", "path": "ppc_descs.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "ppc_descs.ads", "path": "ppc_descs.ads" }, + "subps": { + "ppc_descs": [ + { + "msg_id": { + "tool_kind": [ "Gnatcheck", "Same_operands" ], + "key": "772dd957dd1b5c22c9cc7789b160385a", + "key_seq": 1 + }, + "data": { + "msg": "same operands", + "sloc": { "line": 101, "column": 30 }, + "rank": "Medium", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Gnatcheck", "Same_operands" ], + "key": "772dd957dd1b5c22c9cc7789b160385a", + "key_seq": 2 + }, + "data": { + "msg": "same operands", + "sloc": { "line": 103, "column": 30 }, + "rank": "Medium", + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { "basename": "project.adb", "path": "project.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "project.ads", "path": "project.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "qemu_traces.ads", + "path": "qemu_traces.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "qemu_traces_entries__64.ads", + "path": "qemu_traces_entries__64.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "rundrv-config.adb", + "path": "rundrv-config.adb" + }, + "subps": { + "rundrv.config.get_builtin_driver": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "07450640bbbf2f6ae0bf9b8d2ec66542", + "key_seq": 1 + }, + "data": { + "msg": "out parameter Native might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 111, "column": 27 }, + "rank": "Medium", + "analysis": "Mobsfer", + "duplicate_of": [ + "rundrv.config.get_builtin_driver", + { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "6740c98cb45886e3523cc77031a636aa", + "key_seq": 1 + } + ], + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "6740c98cb45886e3523cc77031a636aa", + "key_seq": 1 + }, + "data": { + "msg": "out parameter `Native` is not initialized at the end of the subprogram", + "cwe": [ [ 457 ] ], + "sloc": { "line": 111, "column": 27 }, + "rank": "High", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "rundrv-config.adb", + "loc": { "line": 84, "column": 4 }, + "text": "parameter `Native` of rundrv.config.get_builtin_driver" + }, + { + "level": 0, + "file": "rundrv-config.adb", + "loc": { "line": 111, "column": 27 }, + "text": "end of the subprogram is here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "rundrv-config.ads", + "path": "rundrv-config.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "rundrv-handlers.adb", + "path": "rundrv-handlers.adb" + }, + "subps": { + "rundrv.handlers.get_gnatemu_driver": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "07450640bbbf2f6ae0bf9b8d2ec66542", + "key_seq": 1 + }, + "data": { + "msg": "out parameter Native might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 229, "column": 10 }, + "rank": "Medium", + "analysis": "Mobsfer", + "duplicate_of": [ + "rundrv.handlers.get_gnatemu_driver", + { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "6740c98cb45886e3523cc77031a636aa", + "key_seq": 1 + } + ], + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "6740c98cb45886e3523cc77031a636aa", + "key_seq": 1 + }, + "data": { + "msg": "out parameter `Native` is not initialized at the end of the subprogram", + "cwe": [ [ 457 ] ], + "sloc": { "line": 229, "column": 10 }, + "rank": "High", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "rundrv-handlers.adb", + "loc": { "line": 218, "column": 4 }, + "text": "parameter `Native` of rundrv.handlers.get_gnatemu_driver" + }, + { + "level": 0, + "file": "rundrv-handlers.adb", + "loc": { "line": 229, "column": 10 }, + "text": "end of the subprogram is here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "rundrv-handlers.ads", + "path": "rundrv-handlers.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "rundrv.adb", "path": "rundrv.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "rundrv.ads", "path": "rundrv.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "sc_obligations-bdd.adb", + "path": "sc_obligations-bdd.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "sc_obligations-bdd.ads", + "path": "sc_obligations-bdd.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "sc_obligations.adb", + "path": "sc_obligations.adb" + }, + "subps": { + "sc_obligations.get_origin": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "52cde9cc70750fefd8280ae1fa662e63", + "key_seq": 1 + }, + "data": { + "msg": "out parameter Prev_Value might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 2676, "column": 19 }, + "rank": "Medium", + "analysis": "Mobsfer", + "duplicate_of": [ + "sc_obligations.get_origin", + { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "52f2e1bd10d09e4e51f8afdfc4ded607", + "key_seq": 1 + } + ], + "age": "Removed" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "52f2e1bd10d09e4e51f8afdfc4ded607", + "key_seq": 1 + }, + "data": { + "msg": "out parameter `Prev_Value` is not initialized at the end of the subprogram", + "cwe": [ [ 457 ] ], + "sloc": { "line": 2676, "column": 19 }, + "rank": "High", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "sc_obligations.adb", + "loc": { "line": 2660, "column": 4 }, + "text": "parameter `Prev_Value` of sc_obligations.get_origin" + }, + { + "level": 0, + "file": "sc_obligations.adb", + "loc": { "line": 2676, "column": 19 }, + "text": "end of the subprogram is here" + } + ], + "age": "Removed" + } + } + ], + "sc_obligations.next_bdd_node((sc_obligations.sco_id, standard.boolean) -> sc_obligations.bdd_node_id)": [ + { + "msg_id": { + "tool_kind": [ "Gnat", "Unused_entity" ], + "key": "6418215abbab1632bf5ce16178874fcd", + "key_seq": 1 + }, + "data": { + "msg": "use clause for package \"BDD\" has no effect", + "sloc": { "line": 4585, "column": 7 }, + "rank": "Low", + "age": "Unchanged" + } + } + ], + "sc_obligations.offset_for_true((sc_obligations.sco_id) -> standard.natural)": [ + { + "msg_id": { + "tool_kind": [ "Gnat", "Unused_entity" ], + "key": "6418215abbab1632bf5ce16178874fcd", + "key_seq": 1 + }, + "data": { + "msg": "use clause for package \"BDD\" has no effect", + "sloc": { "line": 4612, "column": 7 }, + "rank": "Low", + "age": "Unchanged" + } + } + ], + "sc_obligations.sloc_to_sco": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "d735d81c314d0204dd60007ccce00fd4", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `files_table.sloc_to_sco_map` on line 5994 is not freed after the last access at line 6076, column 20", + "sloc": { "line": 6076, "column": 20 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "sc_obligations.adb", + "loc": { "line": 5994, "column": 14 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "sc_obligations.adb", + "loc": { "line": 5994, "column": 14 }, + "text": "when calling `files_table.sloc_to_sco_map` here" + }, + { + "level": 2, + "file": "files_table.adb", + "loc": { "line": 1719, "column": 17 }, + "text": "when calling `files_table.writeable_sloc_to_sco_map` here" + }, + { + "level": 3, + "file": "files_table.adb", + "loc": { "line": 1705, "column": 33 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "sc_obligations.adb", + "loc": { "line": 6076, "column": 20 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "d735d81c314d0204dd60007ccce00fd4", + "key_seq": 2 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `files_table.sloc_to_sco_map` on line 6004 is not freed after the last access at line 6076, column 20", + "sloc": { "line": 6076, "column": 20 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "sc_obligations.adb", + "loc": { "line": 6004, "column": 14 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "sc_obligations.adb", + "loc": { "line": 6004, "column": 14 }, + "text": "when calling `files_table.sloc_to_sco_map` here" + }, + { + "level": 2, + "file": "files_table.adb", + "loc": { "line": 1719, "column": 17 }, + "text": "when calling `files_table.writeable_sloc_to_sco_map` here" + }, + { + "level": 3, + "file": "files_table.adb", + "loc": { "line": 1705, "column": 33 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "sc_obligations.adb", + "loc": { "line": 6076, "column": 20 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "sc_obligations.ads", + "path": "sc_obligations.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "setup_rts.adb", "path": "setup_rts.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "setup_rts.ads", "path": "setup_rts.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "slocs.adb", "path": "slocs.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "slocs.ads", "path": "slocs.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "sparc_descs.ads", + "path": "sparc_descs.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "ss_annotations.adb", + "path": "ss_annotations.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "ss_annotations.ads", + "path": "ss_annotations.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "strings.adb", "path": "strings.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "strings.ads", "path": "strings.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "subprocesses.adb", + "path": "subprocesses.adb" + }, + "subps": { + "subprocesses.wait_and_finalize": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "c174c2d3c4d06c9d38c3c19bc5f73688", + "key_seq": 1 + }, + "data": { + "msg": "Id might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 382, "column": 38 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "subprocesses.ads", + "path": "subprocesses.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "support_files.ads", + "path": "support_files.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "swaps.adb", "path": "swaps.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "swaps.ads", "path": "swaps.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "switches.adb", "path": "switches.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "switches.ads", "path": "switches.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "symbols.adb", "path": "symbols.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "symbols.ads", "path": "symbols.ads" }, + "subps": {} + }, + { + "file_info": { "basename": "temp_dirs.adb", "path": "temp_dirs.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "temp_dirs.ads", "path": "temp_dirs.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "text_files.adb", + "path": "text_files.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "text_files.ads", + "path": "text_files.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "traces.adb", "path": "traces.adb" }, + "subps": {} + }, + { + "file_info": { "basename": "traces.ads", "path": "traces.ads" }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_dbase.adb", + "path": "traces_dbase.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_dbase.ads", + "path": "traces_dbase.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_disa.adb", + "path": "traces_disa.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_disa.ads", + "path": "traces_disa.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_dump.adb", + "path": "traces_dump.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_dump.ads", + "path": "traces_dump.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_elf.adb", + "path": "traces_elf.adb" + }, + "subps": { + "traces_elf.read_debug_lines.close_source_line": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "e8031aaabc82b6a3ac7d1dbb070dc6bb", + "key_seq": 1 + }, + "data": { + "msg": "Insn_1_Last_PC might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 2401, "column": 35 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + }, + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "e8031aaabc82b6a3ac7d1dbb070dc6bb", + "key_seq": 2 + }, + "data": { + "msg": "Insn_1_Last_PC might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 2408, "column": 45 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + } + ], + "traces_elf.set_insn_state": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Validity_check" ], + "key": "74bcf79a584b32bc3a3b1e2b4235a049", + "key_seq": 1 + }, + "data": { + "msg": "Last_Insn_1_Len might be uninitialized", + "cwe": [ [ 457 ] ], + "sloc": { "line": 3817, "column": 34 }, + "rank": "Medium", + "analysis": "Mobsfer", + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "traces_elf.ads", + "path": "traces_elf.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_files.adb", + "path": "traces_files.adb" + }, + "subps": { + "traces_files.read_so_info": [ + { + "msg_id": { + "tool_kind": [ "Infer", "Memory_leak" ], + "key": "251d35eeb8dc5fb3d9304dd9e82f5c1f", + "key_seq": 1 + }, + "data": { + "msg": "Memory dynamically allocated by `new`, indirectly via call to `traces_files.read_so_info.read_info_entries` on line 649 is not freed after the last access at line 650, column 10", + "sloc": { "line": 650, "column": 10 }, + "rank": "Medium", + "analysis": "Pulse", + "backtrace": [ + { + "level": 0, + "file": "traces_files.adb", + "loc": { "line": 649, "column": 7 }, + "text": "allocation part of the trace starts here" + }, + { + "level": 1, + "file": "traces_files.adb", + "loc": { "line": 649, "column": 7 }, + "text": "when calling `traces_files.read_so_info.read_info_entries` here" + }, + { + "level": 2, + "file": "traces_files.adb", + "loc": { "line": 847, "column": 13 }, + "text": "when calling `traces_files.read_so_info.process_info_entry` here" + }, + { + "level": 3, + "file": "traces_files.adb", + "loc": { "line": 635, "column": 43 }, + "text": "allocated by `new` here" + }, + { + "level": 0, + "file": "traces_files.adb", + "loc": { "line": 650, "column": 10 }, + "text": "memory becomes unreachable here" + } + ], + "age": "Unchanged" + } + } + ] + } + }, + { + "file_info": { + "basename": "traces_files.ads", + "path": "traces_files.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_files_registry.adb", + "path": "traces_files_registry.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_files_registry.ads", + "path": "traces_files_registry.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_lines.adb", + "path": "traces_lines.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_lines.ads", + "path": "traces_lines.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_names.adb", + "path": "traces_names.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_names.ads", + "path": "traces_names.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_source.adb", + "path": "traces_source.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_source.ads", + "path": "traces_source.ads" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_stats.adb", + "path": "traces_stats.adb" + }, + "subps": {} + }, + { + "file_info": { + "basename": "traces_stats.ads", + "path": "traces_stats.ads" + }, + "subps": {} + }, + { + "file_info": { "basename": "version.ads", "path": "version.ads" }, + "subps": {} + } + ] + } +} From a403b8bb9c2873e6b40ede763ac30dd29123c1e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 16 Oct 2024 14:21:01 +0200 Subject: [PATCH 0993/1483] GNATcov_RTS: Add new configuration suitable for a -nostdlib config This adds a new "minimal" profile to GNATcov_RTS, which makes it possible to link an instrumented project with no Ada runtime library. The change includes a new implementation for gnatcov_rts_put_string, relying on an externally defined putchar-like function to be provided by the user, and some configuration logic to properly select the right unit based on the external variables defined. gnatcov setup has also been enhanced to expose the minimal profile, and configuration options to the user. --- doc/gnatcov/src_traces.rst | 44 ++++- .../tests/instr-cov/339-nostdlib/prj.gpr | 36 +++++ .../tests/instr-cov/339-nostdlib/src/main.c | 26 +++ .../tests/instr-cov/339-nostdlib/src/pkg.adb | 12 ++ .../tests/instr-cov/339-nostdlib/src/pkg.ads | 8 + .../tests/instr-cov/339-nostdlib/test.opt | 4 + .../tests/instr-cov/339-nostdlib/test.py | 150 ++++++++++++++++++ tools/gnatcov/command_line.ads | 13 +- tools/gnatcov/gnatcov_bits_specific.adb | 14 ++ tools/gnatcov/rts/gnatcov_rts.gpr | 85 +++++++--- .../rts/gnatcov_rts_c-base_io_custom.c | 36 +++++ tools/gnatcov/setup_rts.adb | 24 ++- tools/gnatcov/setup_rts.ads | 4 +- 13 files changed, 427 insertions(+), 29 deletions(-) create mode 100644 testsuite/tests/instr-cov/339-nostdlib/prj.gpr create mode 100644 testsuite/tests/instr-cov/339-nostdlib/src/main.c create mode 100644 testsuite/tests/instr-cov/339-nostdlib/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/339-nostdlib/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/339-nostdlib/test.opt create mode 100644 testsuite/tests/instr-cov/339-nostdlib/test.py create mode 100644 tools/gnatcov/rts/gnatcov_rts_c-base_io_custom.c diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 44299d719..a56c6ccdc 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -194,6 +194,46 @@ the options passed to the latter take precedence. For instance: Note that the defaults that |gcvstp| uses for each target platform may change between versions of |gcp|. +Coverage runtime setup for configurations with no Ada runtime +------------------------------------------------------------- + +If the application is not linked against the Ada runtime library (but contains +Ada code), the coverage runtime needs to be setup accordingly, so as not to +rely on any features from the Ada runtime. + +This can be achieved with the :cmd-option:`--no-stdlib` |gcvstp| command line +switch. The resulting coverage runtime only supports a ``manual`` or +``main-end`` dump trigger, and will use a special implementation of the +``base64-stdout`` dump channel, relying on a user-provided function to output +the coverage data. + +The output function expected by the coverage runtime should have the same +signature as the stdlib's ``putchar`` function: + +.. code-block:: C + + extern int gnatcov_rts_putchar(int __c); + +Note that the coverage runtime will ignore the return value. + +In all cases the coverage runtime still requires an implementation of +``memset`` and ``memcpy`` to be provided, either from the C standard library, +or provided by the user. + +.. note:: + This method of providing a function name upon which the coverage library + depends, without adding this information in the project file means that + gprbuild will produce a link command with the assumption that the coverage + runtime does not depend on the instrumented project. This may result in + the executable link failing due to an undefined reference to the output + function symbol name, if the object file is not already pulled in the + executable in a non-instrumented build. + + To work around this, either ensure the output function is defined in a + compilation unit that is part of the executable in a non-coverage build, + or use an extending project to add your own sources to provide the + ``gnatcov_rts_putchar`` symbol, as detailed in the + :ref:`section dedicated to coverage runtime customization`. Instrumenting programs ====================== @@ -1087,6 +1127,8 @@ trace in addition to performing the original functional operations. Coverage runtime customization ============================== +.. _basic_rts_custom: + Basics ------ @@ -1100,7 +1142,7 @@ First, build and install the default coverage runtime (``gnatcov_rts``): .. code-block:: sh - # Add --target and --RTS if needed according to the toolchain to use + # Add --target / --RTS / --no-stdlib if needed according to the toolchain to use gnatcov setup Then create the project extension. The integration with the |gcvstp| workflow diff --git a/testsuite/tests/instr-cov/339-nostdlib/prj.gpr b/testsuite/tests/instr-cov/339-nostdlib/prj.gpr new file mode 100644 index 000000000..8af774f46 --- /dev/null +++ b/testsuite/tests/instr-cov/339-nostdlib/prj.gpr @@ -0,0 +1,36 @@ +project Prj is + + for Languages use ("Ada", "C"); + for Main use ("main.c"); + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + for Exec_Dir use "."; + + for Runtime ("Ada") use "light"; + + -- We can't build an executable with -nostdlib as a top level + -- builder switch, as this also prevents the c standard library from being + -- linked, and does not use the regular start files. Instead, pass the + -- switch on the binder and liker for Ada sources only, to ensure only the + -- Ada runtime is left out of the link. + + type Yes_No is ("yes", "no"); + Use_Nostdlib : Yes_No := external ("USE_NOSTDLIB", "yes"); + + Stdlib_Switches := (); + + case Use_Nostdlib is + when "yes" => + Stdlib_Switches := ("-nostdlib"); + when "no" => null; + end case; + + package Binder is + for Default_Switches ("Ada") use Stdlib_Switches; + end Binder; + + package Linker is + for Default_Switches ("Ada") use Stdlib_Switches; + end Linker; + +end Prj; diff --git a/testsuite/tests/instr-cov/339-nostdlib/src/main.c b/testsuite/tests/instr-cov/339-nostdlib/src/main.c new file mode 100644 index 000000000..91da81393 --- /dev/null +++ b/testsuite/tests/instr-cov/339-nostdlib/src/main.c @@ -0,0 +1,26 @@ +#include + +/* Ada code to be called. */ +extern int do_math (int l, int r); + +/* Although there is no Ada runtime, we still need to provide a last chance + handler. */ +void +__gnat_last_chance_handler (char *source_location, int line) +{ + printf ("EXCEPTION at %s\n", source_location); +} + +/* putchar function provided for the coverage runtime. */ +int +gnatcov_rts_putchar (int c) +{ + return putchar (c); +} + +int +main () +{ + int y = do_math (0, 4); + return 0; +} diff --git a/testsuite/tests/instr-cov/339-nostdlib/src/pkg.adb b/testsuite/tests/instr-cov/339-nostdlib/src/pkg.adb new file mode 100644 index 000000000..3b7238992 --- /dev/null +++ b/testsuite/tests/instr-cov/339-nostdlib/src/pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Do_Math (L, R : int) return int is + begin + if L = 0 and then R = 0 then + return 0; + else + return L + R; + end if; + end Do_Math; + +end Pkg; diff --git a/testsuite/tests/instr-cov/339-nostdlib/src/pkg.ads b/testsuite/tests/instr-cov/339-nostdlib/src/pkg.ads new file mode 100644 index 000000000..0f4eec39b --- /dev/null +++ b/testsuite/tests/instr-cov/339-nostdlib/src/pkg.ads @@ -0,0 +1,8 @@ +with Interfaces.C; use Interfaces.C; + +package Pkg is + + function Do_Math (L, R : int) return int; + pragma Export (C, Do_Math, External_Name => "do_math"); + +end Pkg; diff --git a/testsuite/tests/instr-cov/339-nostdlib/test.opt b/testsuite/tests/instr-cov/339-nostdlib/test.opt new file mode 100644 index 000000000..59b834cde --- /dev/null +++ b/testsuite/tests/instr-cov/339-nostdlib/test.opt @@ -0,0 +1,4 @@ +bin-traces DEAD Test only concerns gnatcov setup & src traces +!native DEAD test bypasses target configuration and assumes native setup +7.1.2 DEAD no light nor zfp runtime support for this compiler version +5.04a1 DEAD no light nor ZFP runtime support for this compiler version diff --git a/testsuite/tests/instr-cov/339-nostdlib/test.py b/testsuite/tests/instr-cov/339-nostdlib/test.py new file mode 100644 index 000000000..ed928ac48 --- /dev/null +++ b/testsuite/tests/instr-cov/339-nostdlib/test.py @@ -0,0 +1,150 @@ +""" +Test that "gnatcov setup" produces a coverage library compatible with the +-nostdlib builder switch, and warns on inappropriate configurations. +""" + +import os.path + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import xcov + + +tmp = Wdir() + + +def error_case(tc_id, args, expected_out, expect_failure): + """ + Run gnatcov setup with the given args, and check that the output matches + expected_out. Additionally, check the return status of the setup command, + which should match expect_failure. + + The command is run in a temporary subdirectory, with --prefix=. added to + the gnatcov setup args to keep each check separate. id is used as a + temporary directory suffix. + + -q is also added to args to filter out the user directions printed at the + end of the process. + """ + thistest.log(f"====================== {tc_id} =====================") + tmp.to_subdir(f"tmp_{tc_id}") + log = "setup.log" + p = xcov( + ["setup"] + args + ["-q", "--prefix=."], + out=log, + register_failure=not expect_failure, + auto_config_args=False, + ) + + thistest.fail_if( + expect_failure and p.status == 0, + "expected 'gnatcov setup' to return a non-zero status code", + ) + + thistest.fail_if_no_match( + "Unexpected 'gnatcov setup' output", + regexp=expected_out, + actual=contents_of(log), + ) + + +# First, test that gnatcov setup correctly warns about suspicious combinations +# of options. + +error_case( + tc_id="profile_incompatibility", + args=["--no-stdlib", "--rts-profile=full"], + expected_out=r'.*: RTS profile "full" not compatible with --no-stdlib', + expect_failure=True, +) + +error_case( + tc_id="suspicious_dump_trigger", + args=["--no-stdlib", "--dump-trigger=atexit"], + expected_out="warning: --dump-trigger=atexit may not be compatible with" + " the selected runtime", + expect_failure=False, +) + +error_case( + tc_id="suspicious_dump_channel", + args=["--no-stdlib", "--dump-channel=bin-file"], + expected_out="warning: --dump-channel=bin-file may not be compatible with" + " the selected runtime", + expect_failure=False, +) + +# Then check that we can actually build and get a trace from a program +# with Ada code but not linked against the Ada runtime. Do it twice, once with +# and once without and Ada runtime. We expect no coverage difference. +# +# In the code bellow, if use_nostdlib is True then the -nostdlib linker switch +# will be used to build the project, and we do not expect to find the Ada +# runtime library in the linker command. + +for tc_id, use_nostdlib in [ + ("no_stdlib", True), + ("with_stdlib", False), +]: + thistest.log(f"=============== Cov {tc_id} ================") + tmp.to_subdir(f"tmp_{tc_id}") + cp(os.path.join("..", "src"), ".", recursive=True) + cp(os.path.join("..", "prj.gpr"), ".") + + xcov( + [ + "setup", + "-q", + "--prefix=cov_rts", + "--RTS=light", + "--no-stdlib", + ], + auto_config_args=False, + out="setup.log", + ) + + build_run_and_coverage( + gprsw=GPRswitches( + root_project="prj.gpr", + xvars=[("USE_NOSTDLIB", "yes" if use_nostdlib else "no")], + ), + covlevel="stmt+mcdc", + mains=["main"], + dump_trigger=None, + dump_channel="base64-stdout", + extra_coverage_args=["-axcov"], + runtime_project=os.path.join( + "cov_rts", "share", "gpr", "gnatcov_rts.gpr" + ), + auto_config_args=False, + extra_gprbuild_args=["-v"], + ) + + # Check whether we have a libgnat in the gprbuild linker command in the + # log, and compare that against the expected value for this run. + found_libgnat = "libgnat.a" in contents_of("gprbuild.out") + if use_nostdlib: + thistest.fail_if( + found_libgnat, + "Found libgnat.a in gprbuild -v output", + ) + else: + thistest.fail_if( + not found_libgnat, + "Missing libgnat.a in gprbuild -v output", + ) + + check_xcov_reports( + "obj", + { + "main.c.xcov": {"-": {11}, "+": {18, 24, 25}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"-": {6}, "+": {8}, "!": {5}}, + }, + ) + +thistest.result() diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index c0a4cbf77..16d25e6e9 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -103,7 +103,8 @@ package Command_Line is Opt_Warnings_As_Errors, Opt_Instrument_Block, Opt_Force, - Opt_Annotate_After); + Opt_Annotate_After, + Opt_No_Stdlib); -- Set of boolean options we support. More complete descriptions below. type String_Options is @@ -703,6 +704,16 @@ package Command_Line is & " --location switch, as opposed to the default behavior which" & " inserts the annotation before the designated statement.", Commands => (Cmd_Add_Annotation => True, others => False), + Internal => False), + Opt_No_Stdlib => Create + (Long_Name => "--no-stdlib", + Help => + "Setup the coverage runtime in a way that is compatible with the" + & " -nostdlib builder switch. This requires that the output" + & " function for the coverage runtime must be provided by the user," + & " see section ""Coverage runtime setup for configurations with no" + & " Ada runtime"" of the User's Guide for more details.", + Commands => (Cmd_Setup => True, others => False), Internal => False)); String_Infos : constant String_Option_Info_Array := diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index f646edb4f..124edc027 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1328,10 +1328,24 @@ begin RTS_Profile := Full; elsif RTS_Profile_Str = "embedded" then RTS_Profile := Embedded; + elsif RTS_Profile_Str = "minimal" then + RTS_Profile := Minimal; else Fatal_Error ("Invalid RTS profile: " & RTS_Profile_Str); end if; + -- Force minimal profile if the user requested compatibility with + -- --no-stdlib. + + if Args.Bool_Args (Opt_No_Stdlib) then + if RTS_Profile not in Minimal | Auto then + Fatal_Error + ("RTS profile """ & RTS_Profile_Str & """ not compatible" + & " with --no-stdlib"); + end if; + RTS_Profile := Minimal; + end if; + Setup (Project_File => Project_File, Target => Target, diff --git a/tools/gnatcov/rts/gnatcov_rts.gpr b/tools/gnatcov/rts/gnatcov_rts.gpr index fa8ddca9d..d928784df 100644 --- a/tools/gnatcov/rts/gnatcov_rts.gpr +++ b/tools/gnatcov/rts/gnatcov_rts.gpr @@ -18,7 +18,7 @@ library project GNATcov_RTS is -- of the extending project. type Boolean is ("false", "true"); - type RTS_Profile_Type is ("full", "embedded"); + type RTS_Profile_Type is ("full", "embedded", "minimal"); -------------------------------- -- Configuration declarations -- @@ -47,11 +47,34 @@ library project GNATcov_RTS is -- Configuration logic -- ------------------------- + + -- Unit Exclusion table + -- "X" mean the file must go in the Excluded_Source_Files attribute; + -- "I" means the file is implicitly excluded by the language choice; + -- + -- Some values for For_CCG are not present in the table, because they + -- correspond to invalid configurations. + -- + -- /=========================================================\ + -- |RTS_Profile | full | embedded | minimal | + -- |-----------------|-----------|-------|-----|-------------| + -- |With_Ada | yes | no | yes | no | yes | no | + -- |-----------------|-----|-----|-------|-----|-------|-----| + -- |For_CCG | no | no | Y | N | no | Y | N | no | + -- |=================|=====|=====|===|===|=====|===|===|=====| + -- |base_io.c | X | | I | X | | I | X | X | + -- |-----------------|-----|-----|---|---|-----|---|---|-----| + -- |base_io_custom.c | X | X | I | X | X | I | | | + -- |-----------------|-----|-----|---|---|-----|---|---|-----| + -- |base_io.ad(b|s) | | I | | | I | X | X | I | + -- |-----------------|-----|-----|---|---|-----|---|---|-----| + -- | File IO units | | | X | X | X | X | X | X | + -- \=========================================================/ + Languages := (); Excluded_Source_Files := (); - -- Compute the set of languages for this project. When Ada is enabled, - -- exclude the C implementation for stdout output primitives. + -- Compute the set of languages for this project case With_Ada is when "false" => @@ -61,32 +84,46 @@ library project GNATcov_RTS is case For_CCG is when "true" => null; when "false" => - Excluded_Source_Files := - Excluded_Source_Files & ("gnatcov_rts_c-base_io.c"); Languages := Languages & ("C"); end case; end case; - -- If the runtime does not have support to create files, exclude units that - -- depend on that feature. + -- Exclude the remaining files based on the profile and CCG support + -- + -- First, exclude File IO units if the profile is not full. case RTS_Profile is - when "embedded" => + when "embedded" | "minimal" => Excluded_Source_Files := Excluded_Source_Files & ("gnatcov_rts-traces-output-files.adb", - "gnatcov_rts-traces-output-files.ads"); - case For_CCG is - when "true" => null; - when "false" => - Excluded_Source_Files := - Excluded_Source_Files - & ("gnatcov_rts_c-os_interface.c", - "gnatcov_rts_c-os_interface.h", - "gnatcov_rts_c-traces-output-files.c", - "gnatcov_rts_c-traces-output-files.h"); + "gnatcov_rts-traces-output-files.ads", + "gnatcov_rts_c-os_interface.c", + "gnatcov_rts_c-os_interface.h", + "gnatcov_rts_c-traces-output-files.c", + "gnatcov_rts_c-traces-output-files.h"); + when others => null; + end case; + + -- Exclude the Ada Stdout IO unit if the profile is minimal, or select the + -- proper implementation based on the active language otherwise. + + case RTS_Profile is + when "minimal" => + Excluded_Source_Files := + Excluded_Source_Files + & ("gnatcov_rts-base_io.ads", + "gnatcov_rts-base_io.adb", + "gnatcov_rts_c-base_io.c"); + when "embedded" | "full" => + Excluded_Source_Files := + Excluded_Source_Files & ("gnatcov_rts_c-base_io_custom.c"); + case With_Ada is + when "true" => + Excluded_Source_Files := + Excluded_Source_Files & ("gnatcov_rts_c-base_io.c"); + when others => null; end case; - when "full" => null; end case; ------------ @@ -111,14 +148,14 @@ library project GNATcov_RTS is package Compiler is C_Extra_Switches := (); case RTS_Profile is - when "embedded" => + when "embedded" | "minimal" => - -- The rts for the embedded profile needs to remain compilable - -- in "freestanding" environments, where we might not have a libc - -- at hand. + -- The rts for the embedded and minimal profiles needs to remain + -- compilable in "freestanding" environments, where we might not + -- have a libc at hand. C_Extra_Switches := ("-ffreestanding"); - when "full" => + when "full" => null; end case; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-base_io_custom.c b/tools/gnatcov/rts/gnatcov_rts_c-base_io_custom.c new file mode 100644 index 000000000..95eb91084 --- /dev/null +++ b/tools/gnatcov/rts/gnatcov_rts_c-base_io_custom.c @@ -0,0 +1,36 @@ +/**************************************************************************** + * * + * GNATcoverage Instrumentation Runtime * + * * + * Copyright (C) 2021-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. * + * * + ****************************************************************************/ + +#include "gnatcov_rts_c-strings.h" + +/* This variation of gnatcov_rts_c-base_io does not rely on stdlib's fwrite + and instead expects the user to define a putchar function through which the + trace's content will be written. */ + +extern int gnatcov_rts_putchar (int c); + +void +gnatcov_rts_put_string (struct gnatcov_rts_string str) +{ + size_t i; + for (i = 0; i < str.length; i++) + { + gnatcov_rts_putchar (str.str[i]); + } +} diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 6bb67d11c..5fde76f5a 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -243,7 +243,8 @@ package body Setup_RTS is return (case Profile is when Auto => "auto", when Full => "full", - when Embedded => "embedded"); + when Embedded => "embedded", + when Minimal => "minimal"); end Image; ----------- @@ -258,6 +259,8 @@ package body Setup_RTS is return Full; elsif Profile = "embedded" then return Embedded; + elsif Profile = "minimal" then + return Minimal; else return (raise Constraint_Error @@ -297,6 +300,18 @@ package body Setup_RTS is else Main_End), Manual_Indication_Files => File_Sets.Empty_Set); + when Minimal => + + -- The minimal configuration cannot rely on any Ada runtime + -- feature, in particular tasking constructs, so only main-end + -- and base64-stdout (with user provided putchar function) is + -- supported. + + return + (Channel => Base64_Standard_Output, + Trigger => Main_End, + Manual_Indication_Files => File_Sets.Empty_Set); + end case; end Default_Dump_Config; @@ -1342,6 +1357,13 @@ package body Setup_RTS is Warn (Dump_Config.Trigger = At_Exit, "--dump-trigger=atexit"); Warn (Dump_Config.Channel = Binary_File, "--dump-channel=bin-file"); + + when Minimal => + Warn (Dump_Config.Trigger = At_Exit, "--dump-trigger=atexit"); + Warn (Dump_Config.Trigger = Ravenscar_Task_Termination, + "--dump-trigger=ravenscar-task-termination"); + Warn (Dump_Config.Channel = Binary_File, + "--dump-channel=bin-file"); end case; return Had_Warnings; diff --git a/tools/gnatcov/setup_rts.ads b/tools/gnatcov/setup_rts.ads index 2fb53dab1..18b2e2d0e 100644 --- a/tools/gnatcov/setup_rts.ads +++ b/tools/gnatcov/setup_rts.ads @@ -27,10 +27,10 @@ package Setup_RTS is Setup_RTS_Trace : constant Logging.GNATCOLL_Trace := Logging.Create_Trace ("SETUP_RTS"); - type Any_RTS_Profile is (Auto, Full, Embedded); + type Any_RTS_Profile is (Auto, Full, Embedded, Minimal); -- See documentation for the --rts-profile option - subtype Resolved_RTS_Profile is Any_RTS_Profile range Full .. Embedded; + subtype Resolved_RTS_Profile is Any_RTS_Profile range Full .. Minimal; -- Serialization/deserialization functions for Any_RTS_Profile. The -- deserialization one raises Constraint_Error exceptions for invalid input From 6545f9ab64721e6a1e1f453ac27d69c23a1055d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 25 Oct 2024 11:45:04 +0200 Subject: [PATCH 0994/1483] rundrv-handlers.adb: restore -a switch for visium-elf-run cmd This parameter was removed in 9ab22d33 due to it no longer being required in gdbsim. The only gdbsim build we maintain for visium-elf is on the 7.2.x setup, which predates that change, so we need to restore the -a parameter in order for gnatcov run to work for that setup. --- tools/gnatcov/rundrv-handlers.adb | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/rundrv-handlers.adb b/tools/gnatcov/rundrv-handlers.adb index 499c5c559..64849d9b9 100644 --- a/tools/gnatcov/rundrv-handlers.adb +++ b/tools/gnatcov/rundrv-handlers.adb @@ -207,6 +207,7 @@ package body Rundrv.Handlers is begin Native := False; Cmd := (Command => +"visium-elf-run", others => <>); + Append_Arg (Cmd, "-a"); Append_Arg (Cmd, "--trace=" & Context.Trace_File.all); Append_Arg (Cmd, Context.Exe_File.all); end Visium_ELF; From f1895731180ebcb43f49c39b564d34fa32cf910a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 30 Oct 2024 18:02:42 +0100 Subject: [PATCH 0995/1483] Pass the buffers list object instead of source file Instead of passing the source file version of the buffers list unit, compile it and then pass the resulting object file. In the former case, we end up reusing compiler switches from the compiler driver original command. This is a twofold issue, as these switches are not needed to compile the buffers list unit, and it can result in symbols clashing when e.g. the user passed a `-include` switch on the compiler driver command line. --- tools/gnatcov/instrument-gcc_wrapper.adb | 94 +++++++++++++++++------- 1 file changed, 67 insertions(+), 27 deletions(-) diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 26416b024..57c027ea0 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -205,6 +205,14 @@ is -- times (e.g. at instrumentation time, and at compile time). A noteworthy -- example is the -include switch. + procedure Emit_Buffers_List_Object + (Context : Parsing_Context; + Instr_Config : Instrumentation_Config; + Prj : Prj_Desc; + Buffers_List_Object : Virtual_File; + Buffer_Symbols : String_Sets.Set); + -- Emit the object file containing the given list of Buffer_Symbols + ---------------- -- Split_Args -- ---------------- @@ -649,6 +657,43 @@ is return Result; end Remove_Pp_Switches; + ------------------------------ + -- Emit_Buffers_List_Object -- + ------------------------------ + + procedure Emit_Buffers_List_Object + (Context : Parsing_Context; + Instr_Config : Instrumentation_Config; + Prj : Prj_Desc; + Buffers_List_Object : Virtual_File; + Buffer_Symbols : String_Sets.Set) + is + Instrumenter : constant Language_Instrumenter'Class := + Create_C_Instrumenter + (Instr_Config.Tag, Integrated_Instrumentation); + -- Emit the buffers list unit as a C compilation unit as it is + -- compilable by a C / C++ compiler, which are the languages + -- supported by the integrated instrumentation scheme. + + Buffers_List_Unit : constant Virtual_File := + Create + (GNATCOLL.VFS."+" + (+Instrumenter.Emit_Buffers_List_Unit + (Buffer_Symbols, Prj).Unit_Name)); + + Args_Compilation : String_Vectors.Vector; + begin + Args_Compilation.Append (+"-c"); + Args_Compilation.Append + ("-I" & Instr_Config.GNATcov_RTS_Include_Dir); + Args_Compilation.Append + (+(GNATCOLL.VFS."+" (Full_Name (Buffers_List_Unit)))); + Args_Compilation.Append (+"-o"); + Args_Compilation.Append + (+(GNATCOLL.VFS."+" (Full_Name (Buffers_List_Object)))); + Run_Original_Compiler (Context, Args_Compilation); + end Emit_Buffers_List_Object; + Compiler_Wrapper_Dir : constant String := Containing_Directory (Config_File); -- Directory that contains the current program @@ -666,9 +711,9 @@ is -- Artificial project description to pass to the various instrumentation -- workflows. - Buffers_List_Unit : Compilation_Unit; - -- Name of the unit holding the buffer list definitions, if this compiler - -- driver invocation expands to a link command. + Buffers_List_Object : Virtual_File := No_File; + -- Name of the object file holding the buffer list definitions, if this + -- compiler driver invocation expands to a link command. Context : Parsing_Context; @@ -812,18 +857,15 @@ begin -- link. if Has_Link_Command then - declare - Instrumenter : constant Language_Instrumenter'Class := - Create_C_Instrumenter - (Instr_Config.Tag, Integrated_Instrumentation); - -- Emit the buffers list unit as a C compilation unit as it is - -- compilable by a C / C++ compiler, which are the languages - -- supported by the integrated instrumentation scheme. - - begin - Buffers_List_Unit := - Instrumenter.Emit_Buffers_List_Unit (String_Sets.Empty_Set, Prj); - end; + Buffers_List_Object := + Create + (GNATCOLL.VFS."+" (New_File (Prj, +"gcvrtc-main" & ".o"))); + Emit_Buffers_List_Object + (Context, + Instr_Config, + Prj, + Buffers_List_Object, + String_Sets.Empty_Set); end if; -- Now that we have all of the instrumentation artifacts, launch the @@ -852,8 +894,9 @@ begin -- Start with adding the buffer list unit (if it was emitted) to the -- compilation closure. - if Length (Buffers_List_Unit.Unit_Name) /= 0 then - New_Args.Prepend (Buffers_List_Unit.Unit_Name); + if GNATCOLL.VFS.Is_Regular_File (Buffers_List_Object) then + New_Args.Prepend + (+(GNATCOLL.VFS."+" (Full_Name (Buffers_List_Object)))); end if; -- Then, substitute files of interest with their instrumented version, @@ -995,13 +1038,6 @@ begin (+Comp_DB.Link_Command.Target.Full_Name) then declare - Instrumenter : constant Language_Instrumenter'Class := - Create_C_Instrumenter - (Instr_Config.Tag, Integrated_Instrumentation); - -- Emit the buffers list unit as a C compilation unit as it is - -- compilable by a C / C++ compiler, which are the languages - -- supported by the integrated instrumentation scheme. - Buffer_Symbols : String_Sets.Set; procedure Add_Coverage_Buffer_Symbols (Symbol_File : Virtual_File); @@ -1098,10 +1134,14 @@ begin Close (Ldd_File); end; - -- Generate the buffers list unit + -- Generate the actual buffers unit list - Buffers_List_Unit := - Instrumenter.Emit_Buffers_List_Unit (Buffer_Symbols, Prj); + Emit_Buffers_List_Object + (Context, + Instr_Config, + Prj, + Buffers_List_Object, + Buffer_Symbols); -- Then, re-run the link with the correct buffers list unit From 1c4f264249c8dd6db0f8134de720d4e7ed9da1dd Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 30 Oct 2024 14:35:23 +0100 Subject: [PATCH 0996/1483] Fix support for the --include switch When using integrated instrumentation, make sure to correctly discard the --include switch (and all of its variations). Introduce a non-regression test using `cmake`, which was the use case this was reported on. --- .../cmake_include_switch/CMakeLists.txt | 4 ++ .../cmake_include_switch/main.c | 7 ++ .../cmake_include_switch/pkg.h | 5 ++ .../cmake_include_switch/test.py | 67 +++++++++++++++++++ tools/gnatcov/instrument-gcc_wrapper.adb | 6 +- 5 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/cmake_include_switch/CMakeLists.txt create mode 100644 testsuite/tests/integrated_instrumentation/cmake_include_switch/main.c create mode 100644 testsuite/tests/integrated_instrumentation/cmake_include_switch/pkg.h create mode 100644 testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py diff --git a/testsuite/tests/integrated_instrumentation/cmake_include_switch/CMakeLists.txt b/testsuite/tests/integrated_instrumentation/cmake_include_switch/CMakeLists.txt new file mode 100644 index 000000000..b5e617d04 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_include_switch/CMakeLists.txt @@ -0,0 +1,4 @@ +project(HelloWorld) +cmake_minimum_required(VERSION 3.0) + +add_executable(hello_world main.c) diff --git a/testsuite/tests/integrated_instrumentation/cmake_include_switch/main.c b/testsuite/tests/integrated_instrumentation/cmake_include_switch/main.c new file mode 100644 index 000000000..257cb6860 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_include_switch/main.c @@ -0,0 +1,7 @@ +int +main () +{ + // Implicitly imported by --include=pkg.h on the command line + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/cmake_include_switch/pkg.h b/testsuite/tests/integrated_instrumentation/cmake_include_switch/pkg.h new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_include_switch/pkg.h @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py b/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py new file mode 100644 index 000000000..be7ef31a3 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py @@ -0,0 +1,67 @@ +""" +Regression test: check that the gcc compiler wrapper correctly discards the +different variations of the include switch when invoking the original compiler +driver command. +""" + +import os +import os.path + +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + + +def process(c_flags, subdir): + # Run the integrated instrumentation process with the given c_flags, and in + # the given subdir + tmp = Wdir(subdir) + cwd = os.getcwd() + # Setup the instrumentation process + xcov( + [ + "setup-integration", + f"--files={os.path.join(cwd, '..', 'main.c')}", + f"--files={os.path.join(cwd, '..','pkg.h')}", + "--compilers=gcc", + ] + ) + # Run the build + coverage process with the given c_flags + compiler_wrapper = os.path.join(cwd, "gcc") + cmdrun( + [ + "cmake", + "..", + f"-DCMAKE_C_COMPILER={compiler_wrapper}", + f'-DCMAKE_C_FLAGS={" ".join(c_flags)}', + ], + for_pgm=False, + ) + cmdrun(["make"], for_pgm=False) + + # Run the executable + cmdrun(["./hello_world"], for_pgm=False) + + # Check coverage expectations + xcov( + [ + "coverage", + "--level=stmt", + "--sid=main.c.sid", + "-axcov", + srctracename_for("main"), + ] + ) + check_xcov_reports( + ".", {"main.c.xcov": {"+": {5, 6}}, "pkg.h.xcov": {"+": {4}}} + ) + tmp.to_homedir() + + +header = os.path.join(os.getcwd(), "pkg.h") +process(["-include", header], "tmp_short_space_arg") +process([f"-include{header}"], "tmp_short_no_space_arg") +process(["--include", header], "tmp_long_space_arg") +process([f"--include={header}"], "tmp_long_eq_arg") + +thistest.result() diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 57c027ea0..efda8bac1 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -642,12 +642,12 @@ is Arg : constant Unbounded_String := Element (Cur); Arg_Str : constant String := +Arg; begin - if Starts_With (Arg, "--include=") + if Arg_Str in "-include" | "--include" then + Cur := Next (Cur); + elsif Starts_With (Arg, "--include=") or else Starts_With (Arg, "-include") then null; - elsif Arg_Str in "-include" | "--include" then - Cur := Next (Cur); else Result.Append (Element (Cur)); end if; From 08946f0a6542ff17542d6242c464c3aa5575bafc Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 4 Nov 2024 12:10:21 +0000 Subject: [PATCH 0997/1483] C/stmt/NA28-015-default-return: add missing stdlib.h include While we used to get a warning because of the call to the undeclared function atoi in this testcase, GCC 14 now emits an error. Add the missing include of stdlib.h to fix it. --- testsuite/tests/C/stmt/NA28-015-default-return/process.c | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/C/stmt/NA28-015-default-return/process.c b/testsuite/tests/C/stmt/NA28-015-default-return/process.c index eda0abf26..f9ded8bef 100644 --- a/testsuite/tests/C/stmt/NA28-015-default-return/process.c +++ b/testsuite/tests/C/stmt/NA28-015-default-return/process.c @@ -1,6 +1,7 @@ #include "process.h" #include #include +#include void process (const char *argv[]) From 3584f548705233cd4b99b2eceb40973cfbc0ebe6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 5 Nov 2024 11:24:27 +0100 Subject: [PATCH 0998/1483] Update tool versions in .pre-commit-config.yaml This fixes known issues, notably in Flake8 with python 3.12 --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1044b9494..bc0658441 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,7 +19,7 @@ repos: } }"] - repo: git@ssh.gitlab.adacore-it.com:it/flake8.git - rev: 6.0.0 + rev: 7.1.1 hooks: - id: flake8 additional_dependencies: @@ -29,7 +29,7 @@ repos: - pygments args: ["--config=.flake8"] - repo: git@ssh.gitlab.adacore-it.com:it/black.git - rev: 23.1.0 + rev: 24.10.0 hooks: - id: black args: ["--line-length=79"] From 4b5366c27889b3ce031ddc1c3d7e049de65d2186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 5 Nov 2024 12:14:06 +0100 Subject: [PATCH 0999/1483] Vairious style fixes following flake88 and balck version bump --- qualification/genbundle.py | 8 +++++--- qualification/qm/qm_plugins/importers.py | 16 +++++++++------- .../GprFacilities/ConfigAttr/Target/test.py | 8 +++++--- testsuite/SCOV/expgen/utils.py | 2 +- testsuite/SCOV/instr.py | 8 +++++--- testsuite/SCOV/internals/driver.py | 8 +++++--- testsuite/SCOV/internals/xnotep.py | 16 ++++++++++------ testsuite/SCOV/tc.py | 8 +++++--- testsuite/STR/genrest.py | 10 ++++++---- testsuite/SUITE/cutils.py | 4 +--- testsuite/SUITE/tutils.py | 4 +--- testsuite/altrun/trace32/crun.py | 4 +--- .../213-sarif-report/ada/no-violations/test.py | 1 + .../all-lang/no-violations/test.py | 1 + .../213-sarif-report/c/no-violations/test.py | 1 + .../213-sarif-report/cpp/no-violations/test.py | 1 + testsuite/tests/24_mixed_c_c++/test.py | 1 - .../tests/Ada2022/aggregates/arrays/test.py | 1 - .../tests/C/mcdc/Exemptions/Nominal/test.py | 1 - .../tests/IA21-003-simple-decision-sco/test.py | 1 + testsuite/tests/IA29-023-source-search/test.py | 1 + .../tests/M726-018-trace-exec-check/test.py | 8 +++++--- testsuite/tests/TB24-022-missing-sid/test.py | 1 + testsuite/tests/U317-004-xml-report/test.py | 1 + testsuite/tests/UA21-030-elab_mcdc_state/test.py | 1 - .../tests/VB07-015-clean-output-dir/test.py | 8 +++++--- testsuite/testsuite.py | 4 +--- tools/gnatcov/scripts/slocinfo.py | 8 +++++--- 28 files changed, 78 insertions(+), 58 deletions(-) diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 49b78635a..2a9865099 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -720,9 +720,11 @@ def __dump_tree_consistency_info(self, log, suite_ctxdata): (first, next_item) = ( (suite_treeref, local_treeref) if merge_base == suite_treeref - else (local_treeref, suite_treeref) - if merge_base == local_treeref - else (None, None) + else ( + (local_treeref, suite_treeref) + if merge_base == local_treeref + else (None, None) + ) ) if first is None: diff --git a/qualification/qm/qm_plugins/importers.py b/qualification/qm/qm_plugins/importers.py index de6eeb078..5926e946d 100644 --- a/qualification/qm/qm_plugins/importers.py +++ b/qualification/qm/qm_plugins/importers.py @@ -213,13 +213,15 @@ def kind_of(artifact): return ( "Requirement Group" if is_reqset(artifact) - else "Requirement" - if is_req(artifact) - else "Testcase Group" - if is_tcset(artifact) - else "Testcase" - if is_tc(artifact) - else "Chapter" + else ( + "Requirement" + if is_req(artifact) + else ( + "Testcase Group" + if is_tcset(artifact) + else "Testcase" if is_tc(artifact) else "Chapter" + ) + ) ) diff --git a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py index 43587a4d8..9b7eee47b 100644 --- a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py +++ b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py @@ -48,9 +48,11 @@ def instantiate_gpr(target): content = gpr_content.replace("%TARGET%", target) content = content.replace( "%RUNTIME%", - 'for Runtime ("Ada") use "{}";'.format(thistest.options.RTS) - if thistest.options.RTS - else "", + ( + 'for Runtime ("Ada") use "{}";'.format(thistest.options.RTS) + if thistest.options.RTS + else "" + ), ) f.write(content) diff --git a/testsuite/SCOV/expgen/utils.py b/testsuite/SCOV/expgen/utils.py index 9da55ecbe..6125317fa 100644 --- a/testsuite/SCOV/expgen/utils.py +++ b/testsuite/SCOV/expgen/utils.py @@ -69,7 +69,7 @@ def add_if_new(type_): def is_topology_equal(topo1, topo2): """Return whether two topologies are equal.""" - if type(topo1) != type(topo2): + if type(topo1) is not type(topo2): return False elif isinstance(topo1, (ast.And, ast.Not, ast.Or)): return all( diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index ed050343b..506401b8f 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -321,9 +321,11 @@ def filename(prefix, ext): # build the new source new_source = "".join( [ - "" - if before_body_token is None - else lal.Token.text_range(unit.first_token, before_body_token), + ( + "" + if before_body_token is None + else lal.Token.text_range(unit.first_token, before_body_token) + ), "with {};".format(handler_unit), lal.Token.text_range(after_body_token, unit.last_token), ] diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 2a712415b..b52c6ad75 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -1164,9 +1164,11 @@ def log(self): os.path.relpath(os.getcwd(), thistest.homedir), [no_ext(main) for main in self.drivers], self.xfile, - self.testcase.category.name - if self.testcase.category - else "generic", + ( + self.testcase.category.name + if self.testcase.category + else "generic" + ), " ".join(self.covoptions), ), char="*", diff --git a/testsuite/SCOV/internals/xnotep.py b/testsuite/SCOV/internals/xnotep.py index f68d80bde..9a90c291e 100644 --- a/testsuite/SCOV/internals/xnotep.py +++ b/testsuite/SCOV/internals/xnotep.py @@ -204,9 +204,11 @@ def instanciate_over(self, tline, block, kind): Segment( tline.lno, bm.start() + 1, - self.__extended_segend_for(bm=bm, tline=tline) - if extend - else bm.end(), + ( + self.__extended_segend_for(bm=bm, tline=tline) + if extend + else bm.end() + ), ) ) @@ -345,9 +347,11 @@ def __init__(self, text, stext=None, stag=None): self.factory = ( _XnoteP_block(notep=self) if block_p(self.kind) - else _XnoteP_line(notep=self) - if not self.stext - else _XnoteP_segment(notep=self, stext=stext) + else ( + _XnoteP_line(notep=self) + if not self.stext + else _XnoteP_segment(notep=self, stext=stext) + ) ) def instantiate_stag(self): diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index 7bbb1164f..2df42b0b2 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -258,9 +258,11 @@ def __run_one_covlevel(self, covlevel, covcontrol, subdirhint): this_scov_helper = ( SCOV_helper_bin_traces if thistest.options.trace_mode == "bin" - else SCOV_helper_src_traces - if thistest.options.trace_mode == "src" - else None + else ( + SCOV_helper_src_traces + if thistest.options.trace_mode == "src" + else None + ) ) # Compute the Working directory base for this level, then run the test diff --git a/testsuite/STR/genrest.py b/testsuite/STR/genrest.py index d4ada784b..7b41dfae6 100644 --- a/testsuite/STR/genrest.py +++ b/testsuite/STR/genrest.py @@ -574,7 +574,7 @@ def __compute_widths(self): # This is useful to align the text of every column, for both # content rows and the ReST table separation lines. - self.width = {col: 0 for col in self.columns} + self.width = dict.fromkeys(self.columns, 0) # Maximize column width over contents entries @@ -1320,9 +1320,11 @@ def switches_with_eq_from(switches_string): { itemno: "s2", item: "runtime profile", - value: literal(("--RTS=%s" % rts)) - if rts - else rest.emph("no --RTS switch"), + value: ( + literal(("--RTS=%s" % rts)) + if rts + else rest.emph("no --RTS switch") + ), } ) diff --git a/testsuite/SUITE/cutils.py b/testsuite/SUITE/cutils.py index bbdea6379..b62239047 100644 --- a/testsuite/SUITE/cutils.py +++ b/testsuite/SUITE/cutils.py @@ -79,9 +79,7 @@ def to_list(blob): return ( list(blob) if isinstance(blob, (list, tuple)) - else blob.split() - if isinstance(blob, str) - else [] + else blob.split() if isinstance(blob, str) else [] ) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 79ba7dbc4..cda83444a 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -267,9 +267,7 @@ def gpr_common_args(project, auto_config_args=True): gproptions.append( # verbose mode for verifiability in qualif mode. # quiet mode for performance (less io) otherwise. - "-v" - if thistest.options.qualif_level - else "-q", + "-v" if thistest.options.qualif_level else "-q", ) if auto_config_args: gproptions.append( diff --git a/testsuite/altrun/trace32/crun.py b/testsuite/altrun/trace32/crun.py index 1dc26b07f..2d7e53ed4 100755 --- a/testsuite/altrun/trace32/crun.py +++ b/testsuite/altrun/trace32/crun.py @@ -36,9 +36,7 @@ def to_list(blob): return ( blob if isinstance(blob, list) - else blob.split() - if isinstance(blob, str) - else [] + else blob.split() if isinstance(blob, str) else [] ) diff --git a/testsuite/tests/213-sarif-report/ada/no-violations/test.py b/testsuite/tests/213-sarif-report/ada/no-violations/test.py index 86b43043a..73a26cae0 100644 --- a/testsuite/tests/213-sarif-report/ada/no-violations/test.py +++ b/testsuite/tests/213-sarif-report/ada/no-violations/test.py @@ -2,6 +2,7 @@ Check the validity of the SARIF report generated for an Ada project in which no coverage violations were found. """ + from SCOV.minicheck import build_run_and_coverage from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py b/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py index ffb1a06eb..9da78785c 100644 --- a/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py @@ -2,6 +2,7 @@ Check the validity of the SARIF report generated for a project in which no coverage violations were found. The project contains Ada, C, and C++ sources. """ + from SCOV.minicheck import build_run_and_coverage from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of diff --git a/testsuite/tests/213-sarif-report/c/no-violations/test.py b/testsuite/tests/213-sarif-report/c/no-violations/test.py index 0371b331f..f1efc6b3d 100644 --- a/testsuite/tests/213-sarif-report/c/no-violations/test.py +++ b/testsuite/tests/213-sarif-report/c/no-violations/test.py @@ -2,6 +2,7 @@ Check the validity of the SARIF report generated for a C project in which no coverage violations were found. """ + from SCOV.minicheck import build_run_and_coverage from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of diff --git a/testsuite/tests/213-sarif-report/cpp/no-violations/test.py b/testsuite/tests/213-sarif-report/cpp/no-violations/test.py index 88eabe92a..0cd2fcdd5 100644 --- a/testsuite/tests/213-sarif-report/cpp/no-violations/test.py +++ b/testsuite/tests/213-sarif-report/cpp/no-violations/test.py @@ -2,6 +2,7 @@ Check the validity of the SARIF report generated for a C++ project in which no coverage violations were found. """ + from SCOV.minicheck import build_run_and_coverage from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of diff --git a/testsuite/tests/24_mixed_c_c++/test.py b/testsuite/tests/24_mixed_c_c++/test.py index 1a0d513b0..25d5f4f68 100644 --- a/testsuite/tests/24_mixed_c_c++/test.py +++ b/testsuite/tests/24_mixed_c_c++/test.py @@ -3,7 +3,6 @@ produce files with the same object name, resulting in an error at build time. """ - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches diff --git a/testsuite/tests/Ada2022/aggregates/arrays/test.py b/testsuite/tests/Ada2022/aggregates/arrays/test.py index e1cd5e58c..10fe9c9a3 100644 --- a/testsuite/tests/Ada2022/aggregates/arrays/test.py +++ b/testsuite/tests/Ada2022/aggregates/arrays/test.py @@ -3,7 +3,6 @@ component associations. """ - from SCOV.tc import TestCase from SCOV.tctl import CAT from SUITE.context import thistest diff --git a/testsuite/tests/C/mcdc/Exemptions/Nominal/test.py b/testsuite/tests/C/mcdc/Exemptions/Nominal/test.py index 405e789c8..0fee72b52 100644 --- a/testsuite/tests/C/mcdc/Exemptions/Nominal/test.py +++ b/testsuite/tests/C/mcdc/Exemptions/Nominal/test.py @@ -2,7 +2,6 @@ Test proper support for exemptions in comments for C. """ - from SCOV.tc import TestCase from SUITE.context import thistest diff --git a/testsuite/tests/IA21-003-simple-decision-sco/test.py b/testsuite/tests/IA21-003-simple-decision-sco/test.py index dce1fc8fc..2dea8fd62 100644 --- a/testsuite/tests/IA21-003-simple-decision-sco/test.py +++ b/testsuite/tests/IA21-003-simple-decision-sco/test.py @@ -1,6 +1,7 @@ """ Check that gnatcov correctly loads and interprets a simple decision SCO. """ + from SUITE.context import thistest from SUITE.cutils import Wdir, match from SUITE.tutils import ( diff --git a/testsuite/tests/IA29-023-source-search/test.py b/testsuite/tests/IA29-023-source-search/test.py index 11889d970..9a49ab51c 100644 --- a/testsuite/tests/IA29-023-source-search/test.py +++ b/testsuite/tests/IA29-023-source-search/test.py @@ -1,6 +1,7 @@ """ Basic test on the --source-search option """ + import os from SCOV.minicheck import build_and_run diff --git a/testsuite/tests/M726-018-trace-exec-check/test.py b/testsuite/tests/M726-018-trace-exec-check/test.py index e4edbf84d..007be7545 100644 --- a/testsuite/tests/M726-018-trace-exec-check/test.py +++ b/testsuite/tests/M726-018-trace-exec-check/test.py @@ -99,9 +99,11 @@ def expected_repr(expected): thistest.fail_if( xcov_warned != case.expect_warning, "{} ({})".format( - "Warnings expected, got no one" - if case.expect_warning - else "Expected no warnings, but got one", + ( + "Warnings expected, got no one" + if case.expect_warning + else "Expected no warnings, but got one" + ), case.label, ), ) diff --git a/testsuite/tests/TB24-022-missing-sid/test.py b/testsuite/tests/TB24-022-missing-sid/test.py index 8bccaf258..62d156efd 100644 --- a/testsuite/tests/TB24-022-missing-sid/test.py +++ b/testsuite/tests/TB24-022-missing-sid/test.py @@ -1,6 +1,7 @@ """ Check that gnatcov correctly detects missing SID. """ + from SCOV.minicheck import build_run_and_coverage from SUITE.context import thistest from SUITE.cutils import contents_of, Wdir diff --git a/testsuite/tests/U317-004-xml-report/test.py b/testsuite/tests/U317-004-xml-report/test.py index ac942986f..bbdd49e46 100644 --- a/testsuite/tests/U317-004-xml-report/test.py +++ b/testsuite/tests/U317-004-xml-report/test.py @@ -2,6 +2,7 @@ Check that the right column numbers are output for a statement coverage obligation in the XML report. """ + from SCOV.minicheck import build_run_and_coverage from SUITE.context import thistest from SUITE.cutils import contents_of, Wdir diff --git a/testsuite/tests/UA21-030-elab_mcdc_state/test.py b/testsuite/tests/UA21-030-elab_mcdc_state/test.py index 4d9cc8388..b4572a02e 100644 --- a/testsuite/tests/UA21-030-elab_mcdc_state/test.py +++ b/testsuite/tests/UA21-030-elab_mcdc_state/test.py @@ -3,7 +3,6 @@ statments) are proprely instrumented for MCDC. """ - from SCOV.tc import TestCase from SUITE.context import thistest from SCOV.tctl import CAT diff --git a/testsuite/tests/VB07-015-clean-output-dir/test.py b/testsuite/tests/VB07-015-clean-output-dir/test.py index 132c79805..4d33ac815 100644 --- a/testsuite/tests/VB07-015-clean-output-dir/test.py +++ b/testsuite/tests/VB07-015-clean-output-dir/test.py @@ -35,9 +35,11 @@ def check_one(units, output_dir, xcov_args): thistest.log(f"inspecting {dirname}") check_xcov_reports( dirname, - {f"{unit}.xcov": expected_cov[unit] for unit in units} - if dirname == output_dir - else {}, + ( + {f"{unit}.xcov": expected_cov[unit] for unit in units} + if dirname == output_dir + else {} + ), ) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 84da16496..8bf8ac158 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1394,9 +1394,7 @@ def _board_discriminants(self): boardname = ( self.main.args.board if self.main.args.board - else self.env.target.machine - if self.env.target.machine - else None + else self.env.target.machine if self.env.target.machine else None ) return ["board", boardname] if boardname else [] diff --git a/tools/gnatcov/scripts/slocinfo.py b/tools/gnatcov/scripts/slocinfo.py index 1e8930a08..a7c66264b 100644 --- a/tools/gnatcov/scripts/slocinfo.py +++ b/tools/gnatcov/scripts/slocinfo.py @@ -25,9 +25,11 @@ def format_sloc(sloc, basename=False): filename, sloc.line, "" if sloc.column is None else ":{}".format(sloc.column), - "" - if sloc.discriminator is None - else " discriminator {}".format(sloc.discriminator), + ( + "" + if sloc.discriminator is None + else " discriminator {}".format(sloc.discriminator) + ), ) From 85fa926e4aed3da4778418302ebc50486c0f09ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 15 Oct 2024 15:03:37 +0200 Subject: [PATCH 1000/1483] Simplify function coverage for subprogram bodies Before, function coverage was performed for subprogram bodies the same way as for expression functions: by adding an auxiliary function responsible for calling the original one. This is more complex than it could be. Now, function coverage for subprogram bodies is done the same way as for generic procedures: as the presence of a declarative part is guaranteed, the witness call respondible for discharging the function SCO is inserted in a dummy variable declaration at the very beginning of the subprogram's declarations. --- tools/gnatcov/instrument-ada_unit.adb | 171 ++++++++------------------ 1 file changed, 48 insertions(+), 123 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 74133e1b9..00db91a66 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1035,9 +1035,7 @@ package body Instrument.Ada_Unit is Call_Params : Node_Rewriting_Handle; Augmented_Function : out Node_Rewriting_Handle; Augmented_Function_Decl : out Node_Rewriting_Handle; - New_Function : out Node_Rewriting_Handle; - Fun_Witness : Node_Rewriting_Handle := - No_Node_Rewriting_Handle); + New_Function : out Node_Rewriting_Handle); -- Create the augmented function from the original one (Augmented_Function) -- and create the new function (New_Function) that will serve as a -- replacement to the original one. Also create a declaration for the @@ -1065,11 +1063,6 @@ package body Instrument.Ada_Unit is -- * New_Function: -- The new intermediate function that replaces the original one. -- Responsible for calling Augmented_Function. - -- * Fun_Witness: - -- Only used for function coverage. It contains the valid witness call - -- to be inserted as needed in New_Function to discharge the function - -- SCO, or is set to No_Node_Rewriting_Handle if function coverage is - -- not needed. function Augmented_Expr_Function_Needs_Decl (N : Expr_Function) return Boolean; @@ -2649,9 +2642,7 @@ package body Instrument.Ada_Unit is Call_Params : Node_Rewriting_Handle; Augmented_Function : out Node_Rewriting_Handle; Augmented_Function_Decl : out Node_Rewriting_Handle; - New_Function : out Node_Rewriting_Handle; - Fun_Witness : Node_Rewriting_Handle := - No_Node_Rewriting_Handle) + New_Function : out Node_Rewriting_Handle) is RC : Rewriting_Handle renames UIC.Rewriting_Context; @@ -2677,13 +2668,8 @@ package body Instrument.Ada_Unit is then "_GNATCOV_Aux" else ""); - Is_Subp_Body : constant Boolean := - Fun_Cov and then Common_Nodes.N.Kind = Ada_Subp_Body; - -- We only need to consider subprogram bodies when function coverage is - -- needed. - - Need_WP : constant Boolean := not Is_Subp_Body - and then Augmented_EF_Needs_Wrapper_Package (Common_Nodes); + Need_WP : constant Boolean := + Augmented_EF_Needs_Wrapper_Package (Common_Nodes); -- Create the expression for New_Expr_Function that will call that -- augmented expression function. @@ -2719,47 +2705,13 @@ package body Instrument.Ada_Unit is begin -- Create the new augmented function - if Is_Subp_Body then - - -- For a regular subrogram needing function coverage, two statements - -- will be inserted in the body of the new function. First the - -- witness call linked to the function SCO, next the return or call - -- statement calling the new augmented function. - - declare - Stmts : constant Node_Rewriting_Handle := - Create_Regular_Node - (Handle => UIC.Rewriting_Context, - Kind => Ada_Stmt_List, - Children => - (1 => Fun_Witness, - 2 => - (if Common_Nodes.N.Kind = Ada_Subp_Body - and then - Common_Nodes.N.As_Subp_Body.F_Subp_Spec.F_Subp_Kind = - Ada_Subp_Kind_Function - then Create_Return_Stmt (RC, Call_Expr) - else Create_Call_Stmt (RC, Call_Expr)))); - begin - New_Function := - Create_Subp_Body - (RC, - F_Overriding => Clone (Common_Nodes.N_Overriding), - F_Subp_Spec => Clone (Common_Nodes.N_Spec), - F_Aspects => No_Node_Rewriting_Handle, - F_Decls => No_Node_Rewriting_Handle, - F_Stmts => Stmts, - F_End_Name => Make_Identifier (UIC, Orig_Name_Text)); - end; - else - New_Function := - Create_Expr_Function - (RC, - F_Overriding => Clone (Common_Nodes.N_Overriding), - F_Subp_Spec => Clone (Common_Nodes.N_Spec), - F_Expr => Create_Paren_Expr (RC, Call_Expr), - F_Aspects => No_Node_Rewriting_Handle); - end if; + New_Function := + Create_Expr_Function + (RC, + F_Overriding => Clone (Common_Nodes.N_Overriding), + F_Subp_Spec => Clone (Common_Nodes.N_Spec), + F_Expr => Create_Paren_Expr (RC, Call_Expr), + F_Aspects => No_Node_Rewriting_Handle); -- The original function becomes the augmented one: @@ -2778,16 +2730,6 @@ package body Instrument.Ada_Unit is (Handle (Common_Nodes.N_Name), Make_Identifier (UIC, Augmented_Func_Name)); - if Is_Subp_Body - and then not Common_Nodes.N.As_Subp_Body.F_End_Name.Is_Null - then - -- For regular subprogram bodies, also change the end name - - Replace - (Handle (Common_Nodes.N.As_Subp_Body.F_End_Name), - Make_Identifier (UIC, Augmented_Func_Name)); - end if; - -- Use the "augmented formal params" (i.e. original formals plus the -- witness one and the MC/DC state holders). @@ -4149,9 +4091,9 @@ package body Instrument.Ada_Unit is UIC.MCDC_State_Inserter := Saved_MCDC_State_Inserter; end To_Regular_Subprogram; - -------------------------- - -- Crete_Witness_Formal -- - -------------------------- + --------------------------- + -- Create_Witness_Formal -- + --------------------------- procedure Create_Witness_Formal (Formal : out Node_Rewriting_Handle; @@ -4178,7 +4120,6 @@ package body Instrument.Ada_Unit is end Create_Witness_Formal; Is_Expr_Function : constant Boolean := N.Kind = Ada_Expr_Function; - Is_Subp_Body : constant Boolean := N.Kind = Ada_Subp_Body; Gen_Names_Prefix : constant Wide_Wide_String := To_Wide_Wide_String @@ -4379,7 +4320,7 @@ package body Instrument.Ada_Unit is & "cannot instrument generic expression functions." & " Consider turning it into a regular function body."); - elsif not Is_Subp_Body then + else -- As Traverse_Degenerate_Subprogram deals only with expression -- functions and null procedures, we are in the case of a -- generic null procedure here. @@ -4470,26 +4411,18 @@ package body Instrument.Ada_Unit is Fun_Witness); end if; - if not Is_Subp_Body then - -- Turn the expression function or null procedure into - -- a regular subprogram. If function coverage is needed, - -- declare a variable in this new subprogram which will - -- be set to a witness call linked to the function SCO. + -- Turn the expression function or null procedure into a + -- regular subprogram. If function coverage is needed, declare + -- a variable in this new subprogram which will be set to a + -- witness call linked to the function SCO. - To_Regular_Subprogram (N.As_Base_Subp_Body, Fun_Witness); - else - if Fun_Witness /= No_Node_Rewriting_Handle then - Insert_First - (Handle (N.As_Subp_Body.F_Decls.F_Decls), - Create_Function_Witness_Var (UIC, Fun_Witness)); - end if; - end if; + To_Regular_Subprogram (N.As_Base_Subp_Body, Fun_Witness); end; return; end if; - if Is_Expr_Function or else Is_Subp_Body then + if Is_Expr_Function then -- The statement instrumentation below will take care of assigning -- .Witness_* components to their definitive values. @@ -4709,12 +4642,11 @@ package body Instrument.Ada_Unit is -- added to the augmented function later on. end if; - if Is_Expr_Function or else Is_Subp_Body then + if Is_Expr_Function then declare Augmented_Function : Node_Rewriting_Handle; Augmented_Function_Decl : Node_Rewriting_Handle; New_Function : Node_Rewriting_Handle; - begin -- Create the augmented expression function and amend the -- original one. @@ -4726,8 +4658,7 @@ package body Instrument.Ada_Unit is Call_Params, Augmented_Function, Augmented_Function_Decl, - New_Function, - Fun_Witness); + New_Function); -- First comes the augmented expression function, then the new -- expression function. @@ -4861,10 +4792,6 @@ package body Instrument.Ada_Unit is elsif N.Kind in Ada_Expr_Function then Process_Contracts (N.As_Expr_Function); - - Traverse_Degenerate_Subprogram (N, N_Spec); - - elsif N.Kind in Ada_Subp_Body and then Enabled (Fun_Call) then Traverse_Degenerate_Subprogram (N, N_Spec); end if; @@ -5047,37 +4974,35 @@ package body Instrument.Ada_Unit is when Ada_Subp_Body | Ada_Task_Body => - declare - Is_Generic_Subp : constant Boolean := - Is_Generic (UIC, N.As_Basic_Decl); + UIC.In_Generic := Is_Generic (UIC, N.As_Basic_Decl); - Fun_Witness : Node_Rewriting_Handle := - No_Node_Rewriting_Handle; - begin - UIC.In_Generic := Is_Generic_Subp; + Traverse_Subprogram_Or_Task_Body (UIC, N); - Traverse_Subprogram_Or_Task_Body (UIC, N); + if Enabled (Fun_Call) then + declare + Fun_Witness : Node_Rewriting_Handle := + No_Node_Rewriting_Handle; + begin + -- Add a function SCO for this subprogram and fill + -- Fun_Witness with a witness call for this new SCO. The + -- witness call is within a dummy variable declaration. - if Enabled (Fun_Call) then - if Is_Generic_Subp - or else - (UIC.Current_Insertion_Info.Get.Method = None - and then N.Kind /= Ada_Null_Subp_Decl) - then - Instrument_For_Function_Coverage - (UIC, - N.As_Subp_Body.F_Subp_Spec, - Function_Call, - Fun_Witness); + Instrument_For_Function_Coverage + (UIC, + N.As_Subp_Body.F_Subp_Spec, + Function_Call, + Fun_Witness); - Insert_First - (Handle (N.As_Subp_Body.F_Decls.F_Decls), - Create_Function_Witness_Var (UIC, Fun_Witness)); - else - Traverse_Subp_Decl_Or_Stub (N.As_Basic_Decl); - end if; - end if; - end; + -- Put the dummy variable containing the witness call + -- at the very top of the declarative part of this + -- subprogram. This way, it will be executed as soon as + -- the function is called. + + Insert_First + (Handle (N.As_Subp_Body.F_Decls.F_Decls), + Create_Function_Witness_Var (UIC, Fun_Witness)); + end; + end if; UIC.In_Generic := Saved_In_Generic; From d423651f64590946baf9004affe701f5f2b6a2cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 8 Nov 2024 10:23:17 +0100 Subject: [PATCH 1001/1483] instr-cov/339-nostdlib: Use light runtime in all gnatcov invocations This ensures that gnatcov setup does not attempt to build a shared library which results in a link failure on windows. Building an instrumented application with a non-light runtime but with the -nostdlib switch doesn't really make any sense, as this would result in references to the runtime (e.g. through elaboration of the non-light versions of the runtime) so not testing this configuration isn't an issue in practice. --- testsuite/tests/instr-cov/339-nostdlib/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/instr-cov/339-nostdlib/test.py b/testsuite/tests/instr-cov/339-nostdlib/test.py index ed928ac48..28f6da794 100644 --- a/testsuite/tests/instr-cov/339-nostdlib/test.py +++ b/testsuite/tests/instr-cov/339-nostdlib/test.py @@ -64,7 +64,7 @@ def error_case(tc_id, args, expected_out, expect_failure): error_case( tc_id="suspicious_dump_trigger", - args=["--no-stdlib", "--dump-trigger=atexit"], + args=["--no-stdlib", "--dump-trigger=atexit", "--RTS=light"], expected_out="warning: --dump-trigger=atexit may not be compatible with" " the selected runtime", expect_failure=False, @@ -72,7 +72,7 @@ def error_case(tc_id, args, expected_out, expect_failure): error_case( tc_id="suspicious_dump_channel", - args=["--no-stdlib", "--dump-channel=bin-file"], + args=["--no-stdlib", "--dump-channel=bin-file", "--RTS=light"], expected_out="warning: --dump-channel=bin-file may not be compatible with" " the selected runtime", expect_failure=False, From 516b5628138813ff8268e74def5e1b773a75c667 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 13 Nov 2024 13:49:21 +0100 Subject: [PATCH 1002/1483] gnatcov_rts: Do not exclude files for which the language is not active This simplifies manual setup of the runtime (e.g. for CCG) as otherwise it is not possible to delete a file present in the Excluded_Source_Files attribute, even if it was not part of the project because its language is disabled. --- tools/gnatcov/rts/gnatcov_rts.gpr | 62 ++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 18 deletions(-) diff --git a/tools/gnatcov/rts/gnatcov_rts.gpr b/tools/gnatcov/rts/gnatcov_rts.gpr index d928784df..17f9c81c6 100644 --- a/tools/gnatcov/rts/gnatcov_rts.gpr +++ b/tools/gnatcov/rts/gnatcov_rts.gpr @@ -50,7 +50,6 @@ library project GNATcov_RTS is -- Unit Exclusion table -- "X" mean the file must go in the Excluded_Source_Files attribute; - -- "I" means the file is implicitly excluded by the language choice; -- -- Some values for For_CCG are not present in the table, because they -- correspond to invalid configurations. @@ -62,17 +61,19 @@ library project GNATcov_RTS is -- |-----------------|-----|-----|-------|-----|-------|-----| -- |For_CCG | no | no | Y | N | no | Y | N | no | -- |=================|=====|=====|===|===|=====|===|===|=====| - -- |base_io.c | X | | I | X | | I | X | X | + -- |base_io.c | X | | X | X | | X | X | X | -- |-----------------|-----|-----|---|---|-----|---|---|-----| - -- |base_io_custom.c | X | X | I | X | X | I | | | + -- |base_io_custom.c | X | X | X | X | X | X | | | -- |-----------------|-----|-----|---|---|-----|---|---|-----| - -- |base_io.ad(b|s) | | I | | | I | X | X | I | + -- |base_io.ad(b|s) | | X | | | X | X | X | X | -- |-----------------|-----|-----|---|---|-----|---|---|-----| -- | File IO units | | | X | X | X | X | X | X | -- \=========================================================/ Languages := (); - Excluded_Source_Files := (); + Excluded_Ada_Source_Files := (); + Excluded_C_Source_Files := (); + All_Excluded_Source_Files := (); -- Compute the set of languages for this project @@ -94,11 +95,13 @@ library project GNATcov_RTS is case RTS_Profile is when "embedded" | "minimal" => - Excluded_Source_Files := - Excluded_Source_Files + Excluded_Ada_Source_Files := + Excluded_Ada_Source_Files & ("gnatcov_rts-traces-output-files.adb", - "gnatcov_rts-traces-output-files.ads", - "gnatcov_rts_c-os_interface.c", + "gnatcov_rts-traces-output-files.ads"); + Excluded_C_Source_Files := + Excluded_C_Source_Files + & ("gnatcov_rts_c-os_interface.c", "gnatcov_rts_c-os_interface.h", "gnatcov_rts_c-traces-output-files.c", "gnatcov_rts_c-traces-output-files.h"); @@ -110,22 +113,45 @@ library project GNATcov_RTS is case RTS_Profile is when "minimal" => - Excluded_Source_Files := - Excluded_Source_Files + Excluded_Ada_Source_Files := + Excluded_Ada_Source_Files & ("gnatcov_rts-base_io.ads", - "gnatcov_rts-base_io.adb", - "gnatcov_rts_c-base_io.c"); + "gnatcov_rts-base_io.adb"); + Excluded_C_Source_Files := + Excluded_C_Source_Files & ("gnatcov_rts_c-base_io.c"); when "embedded" | "full" => - Excluded_Source_Files := - Excluded_Source_Files & ("gnatcov_rts_c-base_io_custom.c"); + Excluded_C_Source_Files := + Excluded_C_Source_Files & ("gnatcov_rts_c-base_io_custom.c"); case With_Ada is when "true" => - Excluded_Source_Files := - Excluded_Source_Files & ("gnatcov_rts_c-base_io.c"); + Excluded_C_Source_Files := + Excluded_C_Source_Files & ("gnatcov_rts_c-base_io.c"); when others => null; end case; end case; + -- Set the Excluded_Source_Files attribute based on the language. + -- + -- While it is possible to have a filename in the attribute corresponding + -- to a language not present in the current configuration, this limits how + -- the runtime can be setup manually (e.g. for use with CCG), as it is not + -- possible to delete the excluded files as the gpr tools will error out if + -- it is not found, despite not being part of the project due to the active + -- languages. + + case With_Ada is + when "true" => + All_Excluded_Source_Files := Excluded_Ada_Source_Files; + when "false" => null; + end case; + + case For_CCG is + when "false" => + All_Excluded_Source_Files := + All_Excluded_Source_Files & Excluded_C_Source_Files; + when "true" => null; + end case; + ------------ -- Common -- ------------ @@ -143,7 +169,7 @@ library project GNATcov_RTS is for Object_Dir use "obj-gnatcov_rts." & Library_Type; for Source_Dirs use ("."); - for Excluded_Source_Files use Excluded_Source_Files; + for Excluded_Source_Files use All_Excluded_Source_Files; package Compiler is C_Extra_Switches := (); From 278db117710cd57e3af4af668e87ae842ff44881 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 13 Nov 2024 13:52:29 +0100 Subject: [PATCH 1003/1483] CCG altrun: extend list of deleted C files after changes in gnatcov_rts A recent change to gnatcov_rts added a new C file which should not be used with the CCG altrun, so modify the altrun pre-testsuite hook to delete it when preparing the coverage runtime. --- testsuite/altrun/ccg_native/pre_testsuite.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/altrun/ccg_native/pre_testsuite.py b/testsuite/altrun/ccg_native/pre_testsuite.py index c7c0e2460..b4366f1a9 100644 --- a/testsuite/altrun/ccg_native/pre_testsuite.py +++ b/testsuite/altrun/ccg_native/pre_testsuite.py @@ -79,10 +79,10 @@ def prepare_rts(): rm(os.path.join(custom_rts_dir, "obj-*"), recursive=True) rm(os.path.join(custom_rts_dir, "lib-*"), recursive=True) - # Remove gnatcov_rts_c-base_io.c as it would interfere with the symbols + # Remove gnatcov_rts_c-base_io*.c as it would interfere with the symbols # defined in gnatcov_rts-base_io.adb, and the C files that should not # be compiled when the RTS profile is "embedded". - rm(os.path.join(custom_rts_dir, "gnatcov_rts_c-base_io.c")) + rm(os.path.join(custom_rts_dir, "gnatcov_rts_c-base_io*.c")) rm(os.path.join(custom_rts_dir, "gnatcov_rts_c-os_interface*")) rm(os.path.join(custom_rts_dir, "gnatcov_rts_c-traces-output-files*")) From 075f3a58fa3b90ff6e9203e0c0afc70e434c55d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 15 Nov 2024 09:00:26 +0000 Subject: [PATCH 1004/1483] Revert "Merge branch 'lmp-elf-sim-fix' into 'master'" This reverts merge request !681 --- tools/gnatcov/rundrv-handlers.adb | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/gnatcov/rundrv-handlers.adb b/tools/gnatcov/rundrv-handlers.adb index 64849d9b9..499c5c559 100644 --- a/tools/gnatcov/rundrv-handlers.adb +++ b/tools/gnatcov/rundrv-handlers.adb @@ -207,7 +207,6 @@ package body Rundrv.Handlers is begin Native := False; Cmd := (Command => +"visium-elf-run", others => <>); - Append_Arg (Cmd, "-a"); Append_Arg (Cmd, "--trace=" & Context.Trace_File.all); Append_Arg (Cmd, Context.Exe_File.all); end Visium_ELF; From fee35f71fa8acd5ad644b593bd32255180405ea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 8 Nov 2024 10:49:21 +0100 Subject: [PATCH 1005/1483] SCOV: Add option in CovControl to override dump trigger choice This adds a new member to CovControl, allowing to override the default dump trigger choice for tests run in source trace mode. The driver is adapted to look for the correct trace pattern for all dump triggers. The last chance handler hook insertion is also adapted to account for the differences in helper unit naming pattern when a manual dump trigger is used. --- testsuite/SCOV/instr.py | 23 +++++++++++++++-------- testsuite/SCOV/internals/driver.py | 27 ++++++++++++++++++++++++--- testsuite/SCOV/tctl.py | 9 +++++++++ 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 506401b8f..f817b0110 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -249,21 +249,26 @@ def add_dumper_lch_hook(project, obj_dir, subdirs, main_unit): # testsuite so there should be no problem using the helper unit of a # different main. - auto_dump_hash = None + auto_dump_suffix = None for _, _, files in os.walk( os.path.join(obj_dir, f"{project}-gnatcov-instr") ): for file in files: - res = re.match(pattern="gcvrt-db_z([0-9a-f]+).adb", string=file) + res = re.match(pattern="gcvrt-db_(.+).adb", string=file) if res: - auto_dump_hash = res.group(1) + auto_dump_suffix = res.group(1) break - if auto_dump_hash: + if auto_dump_suffix: break - assert auto_dump_hash is not None + assert auto_dump_suffix is not None - auto_dump_unit = "GCVRT.DB_z{}".format(auto_dump_hash) + # Determine if the buffer dump helper unit corresponds to a manual buffer + # dump. If so, there is an extra parameter to pass to the call to the + # Dump_Buffers procedure. + is_manual_dump = not re.match("z[0-9a-f]+", auto_dump_suffix) + + auto_dump_unit = "GCVRT.DB_{}".format(auto_dump_suffix) handler_unit = "Last_Chance_Dumper" def filename(prefix, ext): @@ -293,11 +298,13 @@ def filename(prefix, ext): package body {unit_name} is procedure Lch_Enter is begin - {auto_dump_unit}.Dump_Buffers; + {auto_dump_unit}.Dump_Buffers{call_params}; end; end {unit_name}; """.format( - unit_name=handler_unit, auto_dump_unit=auto_dump_unit + unit_name=handler_unit, + auto_dump_unit=auto_dump_unit, + call_params=f' ("{main_unit}")' if is_manual_dump else "", ) ) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index b52c6ad75..6a71bcd3b 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -1431,6 +1431,20 @@ class SCOV_helper_src_traces(SCOV_helper): # in SID files for source traces and in executables (as debug info) for # binary traces. + def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): + super().__init__( + testcase, + drivers, + xfile, + xcovlevel, + covctl, + wdctl, + ) + + # Check wether we need to set the testsuite in manual dump trigger + # mode from the instrumentation options + self.use_manual_dump = self.dump_trigger == "manual" + def mode_build(self): # We first need to instrument, with proper selection of the units of # interest. Expect we are to provide this through a project file as @@ -1528,7 +1542,9 @@ def mode_execute(self, main): # The mode_tracename_for method works only after the trace file has # been created: create a trace file that srctracename_for (called # in mode_tracename_for) will pick up. - trace_file = srctrace_pattern_for(main).replace("*", "unique") + trace_file = srctrace_pattern_for( + main, manual=self.use_manual_dump, manual_prj_name="gen" + ).replace("*", "unique") xcov_convert_base64( out_file, trace_file, register_failure=register_failure ) @@ -1542,7 +1558,9 @@ def mode_scofiles_switch(self): return "--sid" def mode_tracename_for(self, pgm): - return srctracename_for(pgm) + return srctracename_for( + pgm, manual=self.use_manual_dump, manual_prj_name="gen" + ) @property def dump_channel(self): @@ -1552,4 +1570,7 @@ def dump_channel(self): @property def dump_trigger(self): """Return the dump trigger to use when instrumenting programs.""" - return default_dump_trigger(self.drivers) + if self.covctl and self.covctl.dump_trigger: + return self.covctl.dump_trigger + else: + return default_dump_trigger(self.drivers) diff --git a/testsuite/SCOV/tctl.py b/testsuite/SCOV/tctl.py index 8beae0902..4b463e888 100644 --- a/testsuite/SCOV/tctl.py +++ b/testsuite/SCOV/tctl.py @@ -28,6 +28,9 @@ class CovControl: (covoptions), and gnatcov instrument (instroptions). If instroption is equal to "same" (the default), then it is set to the value of covoption, to avoid the need to duplicate options. + + * Influence some instrumentation specific aspects of the test, like forcing + a specific dump trigger (dump_trigger) """ def __init__( @@ -41,6 +44,7 @@ def __init__( gprsw=None, covoptions="", instroptions="same", + dump_trigger=None, ): # To control "with" dependencies (set of projects that will be withed # by the one we will be generating for the testcase): @@ -81,6 +85,11 @@ def __init__( # unexpected. self.xreports = xreports + # Dump trigger to be used in source trace mode. If left to None, the + # testsuite will determine automatically the best candidate based on + # the target and runtime. + self.dump_trigger = dump_trigger + def unexpected(self, source): return self.xreports is not None and source not in self.xreports From 140bdcb618d6a297eb5da7ef805e3ab3d5465464 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 8 Nov 2024 10:50:09 +0100 Subject: [PATCH 1006/1483] instr-cov/326-pragma-loc-check: various adaptations The trace prefix set in the main source interferes with the testsuite mechanism to find the correct trace after execution. Remove it as it is not required for the test to work properly. The test script now uses the new CovControl option to set the dump trigger, instead of relying on the instroption to force the dump trigger. --- testsuite/tests/instr-cov/326-pragma-loc-check/src/test_pkg.adb | 2 +- testsuite/tests/instr-cov/326-pragma-loc-check/test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/instr-cov/326-pragma-loc-check/src/test_pkg.adb b/testsuite/tests/instr-cov/326-pragma-loc-check/src/test_pkg.adb index b19097822..b63f830ec 100644 --- a/testsuite/tests/instr-cov/326-pragma-loc-check/src/test_pkg.adb +++ b/testsuite/tests/instr-cov/326-pragma-loc-check/src/test_pkg.adb @@ -3,7 +3,7 @@ with Pkg; procedure Test_Pkg is begin Pkg.Wrong_Do_Dump; - pragma Annotate (Xcov, Dump_Buffers, "test_pkg"); + pragma Annotate (Xcov, Dump_Buffers); end Test_Pkg; -- st can only be covered if both buffer annotations have been ignored diff --git a/testsuite/tests/instr-cov/326-pragma-loc-check/test.py b/testsuite/tests/instr-cov/326-pragma-loc-check/test.py index fe6246e97..4b07e55eb 100644 --- a/testsuite/tests/instr-cov/326-pragma-loc-check/test.py +++ b/testsuite/tests/instr-cov/326-pragma-loc-check/test.py @@ -17,7 +17,7 @@ ) TestCase(category=CAT.stmt, tolerate_messages=warning_regexp).run( - CovControl(instroptions="--dump-trigger=manual") + CovControl(dump_trigger="manual") ) # Actually check that we got the expected messages From 88392bfbd9098a6d963182f2c40b6b6ed656cd2a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 15 Nov 2024 10:53:12 +0100 Subject: [PATCH 1007/1483] Pass architecture-specific switches to the compiler driver invocations Forward all of the architecture specific switches to the compiler driver invocation to compile and link the instrumentation artifacts. --- .../architecture_switches/pkg.c | 5 +++ .../architecture_switches/test.py | 34 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 4 +-- tools/gnatcov/instrument-gcc_wrapper.adb | 32 ++++++++++++++--- 4 files changed, 68 insertions(+), 7 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/architecture_switches/pkg.c create mode 100644 testsuite/tests/integrated_instrumentation/architecture_switches/test.py diff --git a/testsuite/tests/integrated_instrumentation/architecture_switches/pkg.c b/testsuite/tests/integrated_instrumentation/architecture_switches/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/architecture_switches/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/architecture_switches/test.py b/testsuite/tests/integrated_instrumentation/architecture_switches/test.py new file mode 100644 index 000000000..a24f8842f --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/architecture_switches/test.py @@ -0,0 +1,34 @@ +""" +Regression test: test that gnatcov correctly compile instrumentation artifacts +with the architecture-specific switches (such as -m32) passed to the original +compiler driver invocation. It used not to, which resulted in an error when +linking the instrumentation artifacts with the instrumented source, which was +compiled with them. +""" + +import os +import os.path + +from SUITE.control import env +from SUITE.cutils import Wdir +from SUITE.tutils import cmdrun, thistest, xcov + +Wdir("tmp_") + +# Setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + "--files=../pkg.c", + "--compilers=gcc", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=os.getcwd()) + +# Try to compile the source. The test used to fail there. +cmdrun(["gcc", "-m32", "../pkg.c", "-c"], for_pgm=False) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 1945a22d3..eec7d124c 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3752,8 +3752,8 @@ package body Instrument.C is Emit_Buffer_Unit (UIC, Compilation_Unit' - (Language => File_Based_Language, - Unit_Name => UIC.Fullname), + (Language => File_Based_Language, + Unit_Name => UIC.Fullname), Self, Prj); diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index efda8bac1..126813ad7 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -139,6 +139,10 @@ is -- The Source_Mapping thus maps the temporary object files to the -- original source. + Compiler_Driver_Arch_Switches : String_Sets.Set; + -- List of architecture-specific switches (such as -m32) to pass when + -- compiling instrumentation artifacts. + Instrumentation_Objects : File_To_String_Vectors_Maps.Map; -- Maps the original source name to the instrumentation artifact objects -- (e.g. coverage buffers unit, dump helper unit). @@ -308,9 +312,18 @@ is Commands_Filename : constant String := Tmp_Dir.Directory_Name / "commands"; begin - -- Expand the command line using gcc's -### option. TODO??? Check if the - -- command we are intercepting is a compile / link target and not a - -- preprocessing / -### action. + -- Grab the architecture specific switches. The heuristic is that we + -- consider every switch starting with "-m" as an architecture-specific + -- switch. Note that when they have an argument, it is always specified + -- as e.g. -mabi=. + + for Arg of Args loop + if Starts_With (Arg, "-m") then + Context.Compiler_Driver_Arch_Switches.Include (Arg); + end if; + end loop; + + -- Expand the command line using gcc's -### option Run_Command (+Context.Orig_Compiler_Driver, @@ -691,6 +704,9 @@ is Args_Compilation.Append (+"-o"); Args_Compilation.Append (+(GNATCOLL.VFS."+" (Full_Name (Buffers_List_Object)))); + for Switch of Context.Compiler_Driver_Arch_Switches loop + Args_Compilation.Append (Switch); + end loop; Run_Original_Compiler (Context, Args_Compilation); end Emit_Buffers_List_Object; @@ -956,6 +972,9 @@ begin Args_Compilation.Append (Instr_Artifact); Args_Compilation.Append (+"-o"); Args_Compilation.Append (+Instr_Artifact_Object_Name); + for Switch of Context.Compiler_Driver_Arch_Switches loop + Args_Compilation.Append (Switch); + end loop; Run_Original_Compiler (Context, Args_Compilation); Context.Instrumentation_Objects @@ -999,10 +1018,13 @@ begin Args_Ld.Append (Full_Name (Assembly_Command.Target)); Args_Ld.Append (+"-o"); Args_Ld.Append (+Packaged_Name); + for Switch of Context.Compiler_Driver_Arch_Switches + loop + Args_Ld.Append (Switch); + end loop; Run_Command (Command => - +Instr_Config.Linkers.Element - (Compiler_Exec_Basename), + +Context.Orig_Compiler_Driver, Arguments => Args_Ld, Origin_Command_Name => "compiler wrapper"); From c0186c90aa2494cbd0b9fe6dd9ecb4dcbb7d10a8 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 18 Nov 2024 13:04:25 +0100 Subject: [PATCH 1008/1483] Add support for fun_call for obligation metrics And also improve the support on the HTML reporting side. --- tools/gnatcov/annotations-dynamic_html.adb | 124 +++++++++++++-------- tools/gnatcov/annotations.adb | 37 +++++- tools/gnatcov/annotations.ads | 14 ++- 3 files changed, 128 insertions(+), 47 deletions(-) diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 69c6d462d..7f37cfaab 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -16,7 +16,7 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Characters.Handling; +with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Directories; use Ada.Directories; with Ada.Exceptions; use Ada.Exceptions; with Ada.Text_IO; @@ -77,19 +77,13 @@ package body Annotations.Dynamic_Html is -- the builder. It is stored in the "sources" attributes of the JSON -- root by Pretty_Print_End_File. - Current_Statements : JSON_Array; - -- The statement list attached to the line currently being processed. It - -- is stored in the Current_Mapping by Pretty_Print_End_Line if not - -- empty. + Current_SCOs : JSON_Array; + -- The SCOs list attached to the line currently being processed. It is + -- stored in the Current_Mapping by Pretty_Print_End_Line if not empty. Current_Decision : JSON_Value; -- The current decision being processed by the builder. It is stored in - -- Current_Decisions by the Pretty_Print_End_Decision procedure. - - Current_Decisions : JSON_Array; - -- The decision list attached to the line currently being processed. It - -- is stored in the Current_Mapping by Pretty_Print_End_Line if not - -- empty. + -- Current_SCOs by the Pretty_Print_End_Decision procedure. Current_Conditions : JSON_Array; -- The condition list attached to the line currently being processed. It @@ -163,11 +157,27 @@ package body Annotations.Dynamic_Html is procedure Pretty_Print_End_Line (Pp : in out Dynamic_Html); + procedure Pretty_Print_SCO + (Pp : in out Dynamic_Html'Class; + SCO : SCO_Id; + State : Line_State; + Kind : SCO_Kind); + procedure Pretty_Print_Statement (Pp : in out Dynamic_Html; SCO : SCO_Id; State : Line_State); + procedure Pretty_Print_Fun + (Pp : in out Dynamic_Html; + SCO : SCO_Id; + State : Line_State); + + procedure Pretty_Print_Call + (Pp : in out Dynamic_Html; + SCO : SCO_Id; + State : Line_State); + procedure Pretty_Print_Start_Decision (Pp : in out Dynamic_Html; SCO : SCO_Id; @@ -246,7 +256,8 @@ package body Annotations.Dynamic_Html is procedure Set_SCO_Fields (Obj : JSON_Value; SCO : SCO_Id; - State : Line_State); + State : Line_State; + Kind : SCO_Kind); -- Set the following field to the given JSON object: -- * id -- * text @@ -396,8 +407,7 @@ package body Annotations.Dynamic_Html is begin Clear (Pp.Current_Mappings); - Clear (Pp.Current_Statements); - Clear (Pp.Current_Decisions); + Clear (Pp.Current_SCOs); Clear (Pp.Current_Conditions); Pp.Scope_Metrics := JSON_Null; @@ -641,8 +651,7 @@ package body Annotations.Dynamic_Html is Line_Obj : constant JSON_Value := Create_Object; begin - Clear (Pp.Current_Statements); - Clear (Pp.Current_Decisions); + Clear (Pp.Current_SCOs); Clear (Pp.Current_Conditions); Line_Obj.Set_Field ("lineNumber", Img (Line_Num)); @@ -662,17 +671,28 @@ package body Annotations.Dynamic_Html is procedure Pretty_Print_End_Line (Pp : in out Dynamic_Html) is begin - if not Is_Empty (Pp.Current_Statements) then - Pp.Current_Mapping.Set_Field ("statements", Pp.Current_Statements); - end if; - - if not Is_Empty (Pp.Current_Decisions) then - Pp.Current_Mapping.Set_Field ("decisions", Pp.Current_Decisions); + if not Is_Empty (Pp.Current_SCOs) then + Pp.Current_Mapping.Set_Field ("scos", Pp.Current_SCOs); end if; - Append (Pp.Current_Mappings, Pp.Current_Mapping); end Pretty_Print_End_Line; + ---------------------- + -- Pretty_Print_SCO -- + ---------------------- + + procedure Pretty_Print_SCO + (Pp : in out Dynamic_Html'Class; + SCO : SCO_Id; + State : Line_State; + Kind : SCO_Kind) + is + SCO_JSON : constant JSON_Value := Create_Object; + begin + Set_SCO_Fields (SCO_JSON, SCO, State, Kind); + Append (Pp.Current_SCOs, SCO_JSON); + end Pretty_Print_SCO; + ---------------------------- -- Pretty_Print_Statement -- ---------------------------- @@ -680,15 +700,35 @@ package body Annotations.Dynamic_Html is procedure Pretty_Print_Statement (Pp : in out Dynamic_Html; SCO : SCO_Id; - State : Line_State) - is - Statement : constant JSON_Value := Create_Object; + State : Line_State) is begin - Set_SCO_Fields (Statement, SCO, State); - - Append (Pp.Current_Statements, Statement); + Pretty_Print_SCO (Pp, SCO, State, Statement); end Pretty_Print_Statement; + ---------------------- + -- Pretty_Print_Fun -- + ---------------------- + + procedure Pretty_Print_Fun + (Pp : in out Dynamic_Html; + SCO : SCO_Id; + State : Line_State) is + begin + Pretty_Print_SCO (Pp, SCO, State, Fun); + end Pretty_Print_Fun; + + ----------------------- + -- Pretty_Print_Call -- + ----------------------- + + procedure Pretty_Print_Call + (Pp : in out Dynamic_Html; + SCO : SCO_Id; + State : Line_State) is + begin + Pretty_Print_SCO (Pp, SCO, State, Call); + end Pretty_Print_Call; + --------------------------------- -- Pretty_Print_Start_Decision -- --------------------------------- @@ -698,15 +738,13 @@ package body Annotations.Dynamic_Html is SCO : SCO_Id; State : Line_State) is - Decision : constant JSON_Value := Create_Object; - Conditions : JSON_Array; + Decision_JSON : constant JSON_Value := Create_Object; + Conditions : JSON_Array; begin Clear (Pp.Current_Conditions); - - Set_SCO_Fields (Decision, SCO, State); - + Set_SCO_Fields (Decision_JSON, SCO, State, Decision); Pp.Current_Conditions := Conditions; - Pp.Current_Decision := Decision; + Pp.Current_Decision := Decision_JSON; end Pretty_Print_Start_Decision; ------------------------------- @@ -718,8 +756,7 @@ package body Annotations.Dynamic_Html is if not Is_Empty (Pp.Current_Conditions) then Pp.Current_Decision.Set_Field ("conditions", Pp.Current_Conditions); end if; - - Append (Pp.Current_Decisions, Pp.Current_Decision); + Append (Pp.Current_SCOs, Pp.Current_Decision); end Pretty_Print_End_Decision; ---------------------------- @@ -731,11 +768,10 @@ package body Annotations.Dynamic_Html is SCO : SCO_Id; State : Line_State) is - Condition : constant JSON_Value := Create_Object; + Condition_JSON : constant JSON_Value := Create_Object; begin - Set_SCO_Fields (Condition, SCO, State); - - Append (Pp.Current_Conditions, Condition); + Set_SCO_Fields (Condition_JSON, SCO, State, Condition); + Append (Pp.Current_Conditions, Condition_JSON); end Pretty_Print_Condition; ---------------------------------------- @@ -841,8 +877,6 @@ package body Annotations.Dynamic_Html is (Pp : in out Dynamic_Html; M : Message) is - use Ada.Characters.Handling; - use Hex_Images; use Interfaces; @@ -922,7 +956,8 @@ package body Annotations.Dynamic_Html is procedure Set_SCO_Fields (Obj : JSON_Value; SCO : SCO_Id; - State : Line_State) + State : Line_State; + Kind : SCO_Kind) is JSON_Annotations : JSON_Array; begin @@ -934,6 +969,7 @@ package body Annotations.Dynamic_Html is Append (JSON_Annotations, Create (Annotation)); end loop; Obj.Set_Field ("annotations", JSON_Annotations); + Obj.Set_Field ("kind", To_Lower (Kind'Image)); end Set_SCO_Fields; --------------- diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index cd1d248ca..cf14d6fd5 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -63,6 +63,30 @@ package body Annotations is -- In source coverage, go through source coverage information at line LI -- and let Pp display them + ---------------------- + -- Pretty_Print_Fun -- + ---------------------- + + procedure Pretty_Print_Fun + (Pp : in out Pretty_Printer; + SCO : SCO_Id; + State : Line_State) is + begin + Pp.Pretty_Print_Statement (SCO, State); + end Pretty_Print_Fun; + + ----------------------- + -- Pretty_Print_Call -- + ----------------------- + + procedure Pretty_Print_Call + (Pp : in out Pretty_Printer; + SCO : SCO_Id; + State : Line_State) is + begin + Pp.Pretty_Print_Statement (SCO, State); + end Pretty_Print_Call; + ---------------------- -- Aggregated_State -- ---------------------- @@ -351,10 +375,16 @@ package body Annotations is when Operator => null; - when Fun_Call_SCO_Kind => + when Fun => if Coverage.Enabled (Fun_Call) then SCO_State := Get_Line_State (SCO, Fun_Call); - Pretty_Print_Statement (Pp, SCO, SCO_State); + Pretty_Print_Fun (Pp, SCO, SCO_State); + end if; + + when Call => + if Coverage.Enabled (Fun_Call) then + SCO_State := Get_Line_State (SCO, Fun_Call); + Pretty_Print_Call (Pp, SCO, SCO_State); end if; end case; @@ -991,6 +1021,9 @@ package body Annotations is case Kind (SCO) is when Statement => Update_Level_Stats (SCO, Get_Line_State (SCO, Stmt), Stmt); + when Fun_Call_SCO_Kind => + Update_Level_Stats + (SCO, Get_Line_State (SCO, Fun_Call), Fun_Call); when Decision => if Coverage.Assertion_Coverage_Enabled and then Is_Assertion (SCO) diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 0edcdd82c..4c08b50bb 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -206,7 +206,19 @@ private (Pp : in out Pretty_Printer; SCO : SCO_Id; State : Line_State) is null; - -- Let Pp print the statement whose id is SCO + -- Let Pp print the statement SCO whose id is SCO + + procedure Pretty_Print_Fun + (Pp : in out Pretty_Printer; + SCO : SCO_Id; + State : Line_State); + -- Let Pp print the function SCO whose id is SCO + + procedure Pretty_Print_Call + (Pp : in out Pretty_Printer; + SCO : SCO_Id; + State : Line_State); + -- Let Pp print the call SCO whose id is SCO procedure Pretty_Print_Start_Decision (Pp : in out Pretty_Printer; From e317adf8a8cf07b0c0e0354911f8a9b688eae473 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 14 Nov 2024 15:54:44 +0000 Subject: [PATCH 1009/1483] SUITE.context.fail_if_diff: bind e3.diff.diff(ignore_white_chars) For some tests, it is actually useful to check idendation: these will need to pass ignore_white_chars=False. --- testsuite/SUITE/context.py | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/testsuite/SUITE/context.py b/testsuite/SUITE/context.py index 715da210a..afc80c85f 100644 --- a/testsuite/SUITE/context.py +++ b/testsuite/SUITE/context.py @@ -290,6 +290,7 @@ def fail_if_diff_internal( actual, failure_message="unexpected output", output_refiners=None, + ignore_white_chars=True, ): """Compute the diff between expected and actual outputs. @@ -305,6 +306,7 @@ def fail_if_diff_internal( and the actual output. Refer to the doc in ``e3.testsuite.driver.diff``. If None, use ``self.report_output_refiners()``. + :param ignore_white_chars: See ``e3.diff``. """ if output_refiners is None: @@ -324,7 +326,11 @@ def fail_if_diff_internal( # Compute the diff. If it is empty, return no failure. Otherwise, # include the diff in the test log and return the given failure # message. - d = diff(expected_lines, actual_lines) + d = diff( + expected_lines, + actual_lines, + ignore_white_chars=ignore_white_chars, + ) if not d: return [] @@ -348,6 +354,7 @@ def fail_if_diff( actual_file, failure_message="unexpected output", output_refiners=None, + ignore_white_chars=True, ): """ Wrapper around fail_if_diff_internal, taking an actual_file parameter @@ -355,7 +362,11 @@ def fail_if_diff( """ with open(actual_file, "r") as f: self.fail_if_diff_internal( - baseline_file, f.read(), failure_message, output_refiners + baseline_file, + f.read(), + failure_message, + output_refiners, + ignore_white_chars, ) def result(self): From 235b6422b64658196a24d37be899e9d3b7a7f318 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 15 Nov 2024 10:18:52 +0000 Subject: [PATCH 1010/1483] Rework SARIF tests so that diffs/baseline updates are human friendly --- testsuite/SCOV/sarif.py | 47 + .../tests/213-sarif-report/ada/full/ref.sarif | 547 +++++++++++- .../tests/213-sarif-report/ada/full/test.py | 9 +- .../ada/no-violations/ref.sarif | 40 +- .../ada/no-violations/test.py | 9 +- .../213-sarif-report/all-lang/full/ref.sarif | 841 +++++++++++++++++- .../213-sarif-report/all-lang/full/test.py | 9 +- .../all-lang/no-violations/ref.sarif | 40 +- .../all-lang/no-violations/test.py | 9 +- .../tests/213-sarif-report/c/full/ref.sarif | 337 ++++++- .../tests/213-sarif-report/c/full/test.py | 9 +- .../c/no-violations/ref.sarif | 40 +- .../213-sarif-report/c/no-violations/test.py | 9 +- .../tests/213-sarif-report/cpp/full/ref.sarif | 337 ++++++- .../tests/213-sarif-report/cpp/full/test.py | 9 +- .../cpp/no-violations/ref.sarif | 40 +- .../cpp/no-violations/test.py | 9 +- 17 files changed, 2285 insertions(+), 56 deletions(-) create mode 100644 testsuite/SCOV/sarif.py diff --git a/testsuite/SCOV/sarif.py b/testsuite/SCOV/sarif.py new file mode 100644 index 000000000..ec197484f --- /dev/null +++ b/testsuite/SCOV/sarif.py @@ -0,0 +1,47 @@ +""" +Helpers to check SARIF reports. +""" + +import json +import os.path + +from SUITE.context import thistest + + +def check_sarif_report(baseline_filename: str, actual_filename: str) -> None: + """ + Check that some actual SARIF report matches the corresponding baseline. + """ + + def refine(v): + match v: + case dict(): + if "uri" in v: + v["uri"] = os.path.basename(v["uri"]) + for item in v.values(): + refine(item) + + case list(): + for item in v: + refine(item) + + # Rewrite the actual report so that computing a diff is possible (e.g. + # basenames instead of URIs) and is human friendly (indentation). + modified_actual = f"modified-{os.path.basename(actual_filename)}" + with open(actual_filename) as f: + doc = json.load(f) + refine(doc) + for run in doc["runs"]: + driver = run["tool"]["driver"] + if driver["name"] == "gnatcov": + driver["version"] = "" + with open(modified_actual, "w") as f: + json.dump(doc, f, indent=2) + f.write("\n") + + thistest.fail_if_diff( + baseline_filename, + modified_actual, + failure_message=f"unexpected content for {actual_filename}", + ignore_white_chars=False, + ) diff --git a/testsuite/tests/213-sarif-report/ada/full/ref.sarif b/testsuite/tests/213-sarif-report/ada/full/ref.sarif index e376eafdc..6734e969d 100644 --- a/testsuite/tests/213-sarif-report/ada/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/ada/full/ref.sarif @@ -1 +1,546 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":8,"startLine":5}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":7,"startLine":6}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":9,"startLine":8}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":9,"startLine":10}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"warning","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.ads"},"region":{"startColumn":31,"startLine":8}}}\],"message":{"text":"statement was not instrumented"},"ruleId":"UNDET"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)b\.ads"},"region":{"startColumn":39,"startLine":2}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startColumn":14,"startLine":16}}}\],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startColumn":15,"startLine":17}}}\],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startColumn":44,"startLine":30}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":10,"startLine":14}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":5,"startLine":15}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":8,"startLine":19}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":32,"startLine":21}}}\],"message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"ruleId":"ATCC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":42,"startLine":21}}}\],"message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"ruleId":"ATCC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":22,"startLine":22}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"ATC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.ads"},"region":{"startColumn":42,"startLine":6}}}\],"message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"ruleId":"ATCC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":6,"startLine":10}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":10,"startLine":11}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":6,"startLine":14}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":5,"startLine":15}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":10,"startLine":19}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)ada(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":5,"startLine":20}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"}\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [ + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 8, + "startLine": 5 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 7, + "startLine": 6 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 9, + "startLine": 8 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 9, + "startLine": 10 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.ads" + }, + "region": { + "startColumn": 31, + "startLine": 8 + } + } + } + ], + "message": { + "text": "statement was not instrumented" + }, + "ruleId": "UNDET" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "b.ads" + }, + "region": { + "startColumn": 39, + "startLine": 2 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.adb" + }, + "region": { + "startColumn": 14, + "startLine": 16 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.adb" + }, + "region": { + "startColumn": 15, + "startLine": 17 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.adb" + }, + "region": { + "startColumn": 44, + "startLine": 30 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 10, + "startLine": 14 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 5, + "startLine": 15 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 8, + "startLine": 19 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 32, + "startLine": 21 + } + } + } + ], + "message": { + "text": "condition was never evaluated during an evaluation of the decision to True, ATCC not achieved" + }, + "ruleId": "ATCC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 42, + "startLine": 21 + } + } + } + ], + "message": { + "text": "condition was never evaluated during an evaluation of the decision to True, ATCC not achieved" + }, + "ruleId": "ATCC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 22, + "startLine": 22 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "ATC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "lib.ads" + }, + "region": { + "startColumn": 42, + "startLine": 6 + } + } + } + ], + "message": { + "text": "condition was never evaluated during an evaluation of the decision to True, ATCC not achieved" + }, + "ruleId": "ATCC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 6, + "startLine": 10 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 10, + "startLine": 11 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 6, + "startLine": 14 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 5, + "startLine": 15 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 10, + "startLine": 19 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 5, + "startLine": 20 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + } + ], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#decision-coverage-analysis", + "id": "DECISION", + "name": "Decision Coverage", + "shortDescription": { + "text": "The decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#modified-condition-decision-coverage-analysis", + "id": "MCDC", + "name": "Modified Condition/Decision Coverage", + "shortDescription": { + "text": "The independant effect of the conditions on the enclosing decision was demonstrated by the tests" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-coverage-atc-analysis", + "id": "ATC", + "name": "Assertion True Coverage", + "shortDescription": { + "text": "Control flow should reach the assertion at least once" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-condition-coverage-analysis-atcc", + "id": "ATCC", + "name": "Assertion True Condition Coverage", + "shortDescription": { + "text": "The assertion decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/ada/full/test.py b/testsuite/tests/213-sarif-report/ada/full/test.py index 92730c782..73105c741 100644 --- a/testsuite/tests/213-sarif-report/ada/full/test.py +++ b/testsuite/tests/213-sarif-report/ada/full/test.py @@ -5,8 +5,9 @@ """ from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor @@ -58,10 +59,6 @@ tolerate_instrument_messages=instr_msg, ) -thistest.fail_if_no_match( - "SARIF report", - contents_of("../ref.sarif"), - contents_of("obj/coverage.sarif"), -) +check_sarif_report("../ref.sarif", "obj/coverage.sarif") thistest.result() diff --git a/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif index af298c0be..c20f7bec8 100644 --- a/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif +++ b/testsuite/tests/213-sarif-report/ada/no-violations/ref.sarif @@ -1 +1,39 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/ada/no-violations/test.py b/testsuite/tests/213-sarif-report/ada/no-violations/test.py index 73a26cae0..7cf0dc77e 100644 --- a/testsuite/tests/213-sarif-report/ada/no-violations/test.py +++ b/testsuite/tests/213-sarif-report/ada/no-violations/test.py @@ -4,8 +4,9 @@ """ from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor @@ -21,10 +22,6 @@ extra_coverage_args=["--annotate=sarif"], ) -thistest.fail_if_no_match( - "SARIF report", - contents_of("../ref.sarif"), - contents_of("obj/coverage.sarif"), -) +check_sarif_report("../ref.sarif", "obj/coverage.sarif") thistest.result() diff --git a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif index 2d10f1574..23886181b 100644 --- a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif @@ -1 +1,840 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":8,"startLine":5}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":7,"startLine":6}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":9,"startLine":8}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.adb"},"region":{"startColumn":9,"startLine":10}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"warning","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)a\.ads"},"region":{"startColumn":31,"startLine":8}}}],"message":{"text":"statement was not instrumented"},"ruleId":"UNDET"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)b\.ads"},"region":{"startColumn":39,"startLine":2}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startColumn":14,"startLine":16}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startColumn":15,"startLine":17}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.adb"},"region":{"startColumn":44,"startLine":30}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":13,"startLine":8}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":20,"startLine":8}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":25,"startLine":8}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":7,"startLine":24}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":7,"startLine":27}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":7,"startLine":34}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)c_source\.c"},"region":{"startColumn":7,"startLine":36}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":13,"startLine":9}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":20,"startLine":9}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":25,"startLine":9}}}],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":7,"startLine":24}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":7,"startLine":27}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":7,"startLine":34}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)cpp_source\.cpp"},"region":{"startColumn":7,"startLine":36}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":10,"startLine":14}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":5,"startLine":15}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":8,"startLine":19}}}],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":32,"startLine":21}}}],"message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"ruleId":"ATCC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":42,"startLine":21}}}],"message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"ruleId":"ATCC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.adb"},"region":{"startColumn":22,"startLine":22}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"ATC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.ads"},"region":{"startColumn":42,"startLine":6}}}],"message":{"text":"condition was never evaluated during an evaluation of the decision to True, ATCC not achieved"},"ruleId":"ATCC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":6,"startLine":18}}}],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":10,"startLine":19}}}],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":6,"startLine":22}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":5,"startLine":23}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":10,"startLine":27}}}],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)all-lang(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.adb"},"region":{"startColumn":5,"startLine":28}}}],"message":{"text":"statement not executed"},"ruleId":"STMT"}],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}],"version":".*"}}}],"version":"2\.1\.0"} +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [ + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 8, + "startLine": 5 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 7, + "startLine": 6 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 9, + "startLine": 8 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.adb" + }, + "region": { + "startColumn": 9, + "startLine": 10 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "warning", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "a.ads" + }, + "region": { + "startColumn": 31, + "startLine": 8 + } + } + } + ], + "message": { + "text": "statement was not instrumented" + }, + "ruleId": "UNDET" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "b.ads" + }, + "region": { + "startColumn": 39, + "startLine": 2 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.adb" + }, + "region": { + "startColumn": 14, + "startLine": 16 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.adb" + }, + "region": { + "startColumn": 15, + "startLine": 17 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.adb" + }, + "region": { + "startColumn": 44, + "startLine": 30 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 13, + "startLine": 8 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 20, + "startLine": 8 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 25, + "startLine": 8 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 7, + "startLine": 24 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 7, + "startLine": 27 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 7, + "startLine": 34 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "c_source.c" + }, + "region": { + "startColumn": 7, + "startLine": 36 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 13, + "startLine": 9 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 20, + "startLine": 9 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 25, + "startLine": 9 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 24 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 27 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 34 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "cpp_source.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 36 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 10, + "startLine": 14 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 5, + "startLine": 15 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 8, + "startLine": 19 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 32, + "startLine": 21 + } + } + } + ], + "message": { + "text": "condition was never evaluated during an evaluation of the decision to True, ATCC not achieved" + }, + "ruleId": "ATCC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 42, + "startLine": 21 + } + } + } + ], + "message": { + "text": "condition was never evaluated during an evaluation of the decision to True, ATCC not achieved" + }, + "ruleId": "ATCC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.adb" + }, + "region": { + "startColumn": 22, + "startLine": 22 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "ATC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "lib.ads" + }, + "region": { + "startColumn": 42, + "startLine": 6 + } + } + } + ], + "message": { + "text": "condition was never evaluated during an evaluation of the decision to True, ATCC not achieved" + }, + "ruleId": "ATCC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 6, + "startLine": 18 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 10, + "startLine": 19 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 6, + "startLine": 22 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 5, + "startLine": 23 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 10, + "startLine": 27 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.adb" + }, + "region": { + "startColumn": 5, + "startLine": 28 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + } + ], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#decision-coverage-analysis", + "id": "DECISION", + "name": "Decision Coverage", + "shortDescription": { + "text": "The decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#modified-condition-decision-coverage-analysis", + "id": "MCDC", + "name": "Modified Condition/Decision Coverage", + "shortDescription": { + "text": "The independant effect of the conditions on the enclosing decision was demonstrated by the tests" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-coverage-atc-analysis", + "id": "ATC", + "name": "Assertion True Coverage", + "shortDescription": { + "text": "Control flow should reach the assertion at least once" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-condition-coverage-analysis-atcc", + "id": "ATCC", + "name": "Assertion True Condition Coverage", + "shortDescription": { + "text": "The assertion decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/all-lang/full/test.py b/testsuite/tests/213-sarif-report/all-lang/full/test.py index 7cb4b9d2a..4d74d3d2f 100644 --- a/testsuite/tests/213-sarif-report/all-lang/full/test.py +++ b/testsuite/tests/213-sarif-report/all-lang/full/test.py @@ -5,8 +5,9 @@ """ from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor @@ -59,10 +60,6 @@ tolerate_instrument_messages=instr_msg, ) -thistest.fail_if_no_match( - "SARIF report", - contents_of("../ref.sarif"), - contents_of("obj/coverage.sarif"), -) +check_sarif_report("../ref.sarif", "obj/coverage.sarif") thistest.result() diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif index af298c0be..c20f7bec8 100644 --- a/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/ref.sarif @@ -1 +1,39 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py b/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py index 9da78785c..a8c022da9 100644 --- a/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py +++ b/testsuite/tests/213-sarif-report/all-lang/no-violations/test.py @@ -4,8 +4,9 @@ """ from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor @@ -26,10 +27,6 @@ extra_coverage_args=["--annotate=sarif"], ) -thistest.fail_if_no_match( - "SARIF report", - contents_of("../ref.sarif"), - contents_of("obj/coverage.sarif"), -) +check_sarif_report("../ref.sarif", "obj/coverage.sarif") thistest.result() diff --git a/testsuite/tests/213-sarif-report/c/full/ref.sarif b/testsuite/tests/213-sarif-report/c/full/ref.sarif index 38905f4a6..bdd0c1513 100644 --- a/testsuite/tests/213-sarif-report/c/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/c/full/ref.sarif @@ -1 +1,336 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.c"},"region":{"startColumn":14,"startLine":6}}}\],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.c"},"region":{"startColumn":20,"startLine":6}}}\],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.c"},"region":{"startColumn":7,"startLine":9}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.c"},"region":{"startColumn":7,"startLine":11}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.c"},"region":{"startColumn":7,"startLine":6}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.c"},"region":{"startColumn":7,"startLine":8}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startColumn":7,"startLine":13}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startColumn":11,"startLine":15}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startColumn":7,"startLine":18}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startColumn":7,"startLine":20}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startColumn":7,"startLine":24}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)c(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.c"},"region":{"startColumn":7,"startLine":26}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"}\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [ + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.c" + }, + "region": { + "startColumn": 14, + "startLine": 6 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.c" + }, + "region": { + "startColumn": 20, + "startLine": 6 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.c" + }, + "region": { + "startColumn": 7, + "startLine": 9 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.c" + }, + "region": { + "startColumn": 7, + "startLine": 11 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "lib.c" + }, + "region": { + "startColumn": 7, + "startLine": 6 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "lib.c" + }, + "region": { + "startColumn": 7, + "startLine": 8 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.c" + }, + "region": { + "startColumn": 7, + "startLine": 13 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.c" + }, + "region": { + "startColumn": 11, + "startLine": 15 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.c" + }, + "region": { + "startColumn": 7, + "startLine": 18 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.c" + }, + "region": { + "startColumn": 7, + "startLine": 20 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.c" + }, + "region": { + "startColumn": 7, + "startLine": 24 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.c" + }, + "region": { + "startColumn": 7, + "startLine": 26 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + } + ], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#decision-coverage-analysis", + "id": "DECISION", + "name": "Decision Coverage", + "shortDescription": { + "text": "The decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#modified-condition-decision-coverage-analysis", + "id": "MCDC", + "name": "Modified Condition/Decision Coverage", + "shortDescription": { + "text": "The independant effect of the conditions on the enclosing decision was demonstrated by the tests" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-coverage-atc-analysis", + "id": "ATC", + "name": "Assertion True Coverage", + "shortDescription": { + "text": "Control flow should reach the assertion at least once" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-condition-coverage-analysis-atcc", + "id": "ATCC", + "name": "Assertion True Condition Coverage", + "shortDescription": { + "text": "The assertion decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/c/full/test.py b/testsuite/tests/213-sarif-report/c/full/test.py index 68b9d53a3..2e352a913 100644 --- a/testsuite/tests/213-sarif-report/c/full/test.py +++ b/testsuite/tests/213-sarif-report/c/full/test.py @@ -4,8 +4,9 @@ """ from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor @@ -53,10 +54,6 @@ extra_coverage_args=["--annotate=sarif"], ) -thistest.fail_if_no_match( - "SARIF report", - contents_of("../ref.sarif"), - contents_of("obj/coverage.sarif"), -) +check_sarif_report("../ref.sarif", "obj/coverage.sarif") thistest.result() diff --git a/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif index af298c0be..c20f7bec8 100644 --- a/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif +++ b/testsuite/tests/213-sarif-report/c/no-violations/ref.sarif @@ -1 +1,39 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/c/no-violations/test.py b/testsuite/tests/213-sarif-report/c/no-violations/test.py index f1efc6b3d..26f36b3ce 100644 --- a/testsuite/tests/213-sarif-report/c/no-violations/test.py +++ b/testsuite/tests/213-sarif-report/c/no-violations/test.py @@ -4,8 +4,9 @@ """ from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor @@ -21,10 +22,6 @@ extra_coverage_args=["--annotate=sarif"], ) -thistest.fail_if_no_match( - "SARIF report", - contents_of("../ref.sarif"), - contents_of("obj/coverage.sarif"), -) +check_sarif_report("../ref.sarif", "obj/coverage.sarif") thistest.result() diff --git a/testsuite/tests/213-sarif-report/cpp/full/ref.sarif b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif index 5a97eb0bf..01c84475b 100644 --- a/testsuite/tests/213-sarif-report/cpp/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif @@ -1 +1,336 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.cpp"},"region":{"startColumn":14,"startLine":6}}}\],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)src-bar(\\\\|/)bar\.cpp"},"region":{"startColumn":20,"startLine":6}}}\],"message":{"text":"condition has no independent influence pair, MC(\\\\|/)DC not achieved"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.cpp"},"region":{"startColumn":7,"startLine":9}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)src-foo(\\\\|/)foo\.cpp"},"region":{"startColumn":7,"startLine":11}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.cpp"},"region":{"startColumn":7,"startLine":6}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-lib(\\\\|/)lib\.cpp"},"region":{"startColumn":7,"startLine":8}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startColumn":7,"startLine":13}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startColumn":11,"startLine":15}}}\],"message":{"text":"decision outcome FALSE never exercised"},"ruleId":"MCDC"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startColumn":7,"startLine":18}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"error","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startColumn":7,"startLine":20}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startColumn":7,"startLine":24}}}\],"message":{"text":"decision outcome TRUE never exercised"},"ruleId":"DECISION"},{"kind":"fail","level":"note","locations":\[{"physicalLocation":{"artifactLocation":{"uri":".*(\\\\|/)213-sarif-report(\\\\|/)cpp(\\\\|/)full(\\\\|/)src-root(\\\\|/)main\.cpp"},"region":{"startColumn":7,"startLine":26}}}\],"message":{"text":"statement not executed"},"ruleId":"STMT"}\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#decision-coverage-analysis","id":"DECISION","name":"Decision Coverage","shortDescription":{"text":"The decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#modified-condition-decision-coverage-analysis","id":"MCDC","name":"Modified Condition/Decision Coverage","shortDescription":{"text":"The independant effect of the conditions on the enclosing decision was demonstrated by the tests"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-coverage-atc-analysis","id":"ATC","name":"Assertion True Coverage","shortDescription":{"text":"Control flow should reach the assertion at least once"}},{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#assertion-true-condition-coverage-analysis-atcc","id":"ATCC","name":"Assertion True Condition Coverage","shortDescription":{"text":"The assertion decision has been evaluated at least once to True and once False during program execution"}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [ + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.cpp" + }, + "region": { + "startColumn": 14, + "startLine": 6 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "bar.cpp" + }, + "region": { + "startColumn": 20, + "startLine": 6 + } + } + } + ], + "message": { + "text": "condition has no independent influence pair, MC/DC not achieved" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 9 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "foo.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 11 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "lib.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 6 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "lib.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 8 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 13 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.cpp" + }, + "region": { + "startColumn": 11, + "startLine": 15 + } + } + } + ], + "message": { + "text": "decision outcome FALSE never exercised" + }, + "ruleId": "MCDC" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 18 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "error", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 20 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 24 + } + } + } + ], + "message": { + "text": "decision outcome TRUE never exercised" + }, + "ruleId": "DECISION" + }, + { + "kind": "fail", + "level": "note", + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "main.cpp" + }, + "region": { + "startColumn": 7, + "startLine": 26 + } + } + } + ], + "message": { + "text": "statement not executed" + }, + "ruleId": "STMT" + } + ], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#decision-coverage-analysis", + "id": "DECISION", + "name": "Decision Coverage", + "shortDescription": { + "text": "The decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#modified-condition-decision-coverage-analysis", + "id": "MCDC", + "name": "Modified Condition/Decision Coverage", + "shortDescription": { + "text": "The independant effect of the conditions on the enclosing decision was demonstrated by the tests" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-coverage-atc-analysis", + "id": "ATC", + "name": "Assertion True Coverage", + "shortDescription": { + "text": "Control flow should reach the assertion at least once" + } + }, + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#assertion-true-condition-coverage-analysis-atcc", + "id": "ATCC", + "name": "Assertion True Condition Coverage", + "shortDescription": { + "text": "The assertion decision has been evaluated at least once to True and once False during program execution" + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/cpp/full/test.py b/testsuite/tests/213-sarif-report/cpp/full/test.py index 74fc196b5..a987f8138 100644 --- a/testsuite/tests/213-sarif-report/cpp/full/test.py +++ b/testsuite/tests/213-sarif-report/cpp/full/test.py @@ -4,8 +4,9 @@ """ from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor @@ -53,10 +54,6 @@ extra_coverage_args=["--annotate=sarif"], ) -thistest.fail_if_no_match( - "SARIF report", - contents_of("../ref.sarif"), - contents_of("obj/coverage.sarif"), -) +check_sarif_report("../ref.sarif", "obj/coverage.sarif") thistest.result() diff --git a/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif b/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif index af298c0be..c20f7bec8 100644 --- a/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif +++ b/testsuite/tests/213-sarif-report/cpp/no-violations/ref.sarif @@ -1 +1,39 @@ -{"\$schema":"https://schemastore\.azurewebsites\.net/schemas/json/sarif-2\.1\.0\.json","runs":\[{"results":\[\],"tool":{"driver":{"informationUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov\.html","name":"gnatcov","rules":\[{"defaultConfiguration":{"level":"error"},"helpUri":"https://docs\.adacore\.com/gnatcoverage-docs/html/gnatcov/cov_source\.html#statement-coverage-analysis","id":"STMT","name":"Statement Coverage","shortDescription":{"text":"Control flow should reach the statement at least once\."}},{"defaultConfiguration":{"level":"warning"},"id":"UNDET","name":"Undetermined Coverage","shortDescription":{"text":"Gnatcov was unable to determine the coverage state of the obligation"}}\],"version":".*"}}}\],"version":"2\.1\.0"} +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json", + "runs": [ + { + "results": [], + "tool": { + "driver": { + "informationUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov.html", + "name": "gnatcov", + "rules": [ + { + "defaultConfiguration": { + "level": "error" + }, + "helpUri": "https://docs.adacore.com/gnatcoverage-docs/html/gnatcov/cov_source.html#statement-coverage-analysis", + "id": "STMT", + "name": "Statement Coverage", + "shortDescription": { + "text": "Control flow should reach the statement at least once." + } + }, + { + "defaultConfiguration": { + "level": "warning" + }, + "id": "UNDET", + "name": "Undetermined Coverage", + "shortDescription": { + "text": "Gnatcov was unable to determine the coverage state of the obligation" + } + } + ], + "version": "" + } + } + } + ], + "version": "2.1.0" +} diff --git a/testsuite/tests/213-sarif-report/cpp/no-violations/test.py b/testsuite/tests/213-sarif-report/cpp/no-violations/test.py index 0cd2fcdd5..8586a43fe 100644 --- a/testsuite/tests/213-sarif-report/cpp/no-violations/test.py +++ b/testsuite/tests/213-sarif-report/cpp/no-violations/test.py @@ -4,8 +4,9 @@ """ from SCOV.minicheck import build_run_and_coverage +from SCOV.sarif import check_sarif_report from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of +from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor @@ -21,10 +22,6 @@ extra_coverage_args=["--annotate=sarif"], ) -thistest.fail_if_no_match( - "SARIF report", - contents_of("../ref.sarif"), - contents_of("obj/coverage.sarif"), -) +check_sarif_report("../ref.sarif", "obj/coverage.sarif") thistest.result() From ed0ca9a0d2d54d59991557258a7de2d7191e4f4d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 15 Nov 2024 09:28:37 +0000 Subject: [PATCH 1011/1483] Instrument Ada: adjust sloc range for the SCO stmt. in expr. functions This is preparatory work for upcoming changes, that will create new tests that would show discrepancies between reports produced by binary traces and source traces without this patch. --- testsuite/tests/213-sarif-report/ada/full/ref.sarif | 2 +- .../tests/213-sarif-report/all-lang/full/ref.sarif | 2 +- tools/gnatcov/instrument-ada_unit.adb | 10 +++++++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/213-sarif-report/ada/full/ref.sarif b/testsuite/tests/213-sarif-report/ada/full/ref.sarif index 6734e969d..8fbe45c9e 100644 --- a/testsuite/tests/213-sarif-report/ada/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/ada/full/ref.sarif @@ -118,7 +118,7 @@ "uri": "b.ads" }, "region": { - "startColumn": 39, + "startColumn": 40, "startLine": 2 } } diff --git a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif index 23886181b..39f4563cc 100644 --- a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif @@ -118,7 +118,7 @@ "uri": "b.ads" }, "region": { - "startColumn": 39, + "startColumn": 40, "startLine": 2 } } diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 00db91a66..71d3b62bc 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -4499,8 +4499,16 @@ package body Instrument.Ada_Unit is if Is_Expr_Function then declare - N_Expr : constant Expr := N.As_Expr_Function.F_Expr; + N_Expr : Expr := N.As_Expr_Function.F_Expr; begin + -- Strip the wrapping paren expr so that we consider only the + -- nested expression as a statement: this mirrors what we do + -- for binary traces and yields better coverage reports anyway. + + if N_Expr.Kind = Ada_Paren_Expr then + N_Expr := N_Expr.As_Paren_Expr.F_Expr; + end if; + Instrument_Statement (UIC, N_Expr, 'X'); Process_Expression (UIC, N_Expr, 'X'); end; From d247432a47a885b52cad429f2b8594ab718f7021 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 14 Nov 2024 16:47:49 +0000 Subject: [PATCH 1012/1483] Fix XML report production for non-UTF-8 source code Consider by default that sources are encoded in Latin-1. For the cases they are not, also add a --source-encoding option to allow users to specify which encoding to use. The adaptation of SCO_Text to handle encodings fixed bugs in the truncation logic as a side effect. Adjust the default truncation length to reflect what was implemented (length = 9 instead of 8) to limit the need to adjust baselines. --- .check-formatting.py | 17 +- .../tests/285-violations-display/ref.xcov | 2 +- .../tests/354-source-encoding/latin1.ads | 7 + testsuite/tests/354-source-encoding/main.adb | 11 + testsuite/tests/354-source-encoding/test.opt | 1 + testsuite/tests/354-source-encoding/test.py | 267 ++++++++++++++++++ testsuite/tests/354-source-encoding/utf8.ads | 7 + .../main.adb.xml.expected | 6 +- tools/gnatcov/annotations-xml.adb | 10 +- tools/gnatcov/annotations.adb | 99 +++++-- tools/gnatcov/annotations.ads | 26 +- tools/gnatcov/command_line.ads | 14 +- tools/gnatcov/files_table.adb | 229 ++++++++++++++- tools/gnatcov/files_table.ads | 32 ++- tools/gnatcov/gnatcov_bits_specific.adb | 7 + 15 files changed, 677 insertions(+), 58 deletions(-) create mode 100644 testsuite/tests/354-source-encoding/latin1.ads create mode 100644 testsuite/tests/354-source-encoding/main.adb create mode 100644 testsuite/tests/354-source-encoding/test.opt create mode 100644 testsuite/tests/354-source-encoding/test.py create mode 100644 testsuite/tests/354-source-encoding/utf8.ads diff --git a/.check-formatting.py b/.check-formatting.py index bffe2c63e..f6df24fa8 100644 --- a/.check-formatting.py +++ b/.check-formatting.py @@ -52,6 +52,13 @@ class Checker: List of file extensions that look like source files. """ + ignore_list = [ + "testsuite/tests/354-source-encoding/latin1.ads", + ] + """ + List of files to intentionally ignore for style checking purposes. + """ + def __init__(self, autofix: bool = False, force_colors: bool = False): self.issue_found = False """ @@ -165,6 +172,8 @@ def main(cls, argv: list[str] | None = None): force_colors=args.force_colors, ) + ignore_set = {os.path.realpath(f) for f in checker.ignore_list} + # Process the list of files to check if present, otherwise look for all # source files in the current directory. if args.files: @@ -173,8 +182,12 @@ def main(cls, argv: list[str] | None = None): else: for path, _, filenames in os.walk("."): for f in filenames: - if f.rsplit(".", 1)[-1] in cls.filename_extensions: - checker.process_file(os.path.join(path, f)) + realpath = os.path.realpath(os.path.join(path, f)) + if ( + realpath not in ignore_set + and f.rsplit(".", 1)[-1] in cls.filename_extensions + ): + checker.process_file(realpath) return 1 if checker.issue_found else 0 diff --git a/testsuite/tests/285-violations-display/ref.xcov b/testsuite/tests/285-violations-display/ref.xcov index 3a00e7605..fd4405d10 100644 --- a/testsuite/tests/285-violations-display/ref.xcov +++ b/testsuite/tests/285-violations-display/ref.xcov @@ -28,7 +28,7 @@ condition "F" at 16:25 has no independent influence pair, MC/DC not achieved 18 !: if F 19 !: or else 20 !: F -decision "F\.\.\." at 18:16 outcome TRUE never exercised +decision "F" at 18:16 outcome TRUE never exercised 21 \.: then 22 \.: declare 23 -: Dummy : String := Concat diff --git a/testsuite/tests/354-source-encoding/latin1.ads b/testsuite/tests/354-source-encoding/latin1.ads new file mode 100644 index 000000000..590a15a46 --- /dev/null +++ b/testsuite/tests/354-source-encoding/latin1.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; +package Latin1 is + function Id (V : Boolean) return Boolean is (V); + function F (A, B : Boolean) return Boolean + is (Id (-- ÉaÉ + A) and then B); +end Latin1; diff --git a/testsuite/tests/354-source-encoding/main.adb b/testsuite/tests/354-source-encoding/main.adb new file mode 100644 index 000000000..23d4203b0 --- /dev/null +++ b/testsuite/tests/354-source-encoding/main.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Latin1; +with UTF8; + +procedure Main is +begin + if Latin1.F (True, True) and then UTF8.F (True, True) then + Put_Line ("Hello world!"); + end if; +end Main; diff --git a/testsuite/tests/354-source-encoding/test.opt b/testsuite/tests/354-source-encoding/test.opt new file mode 100644 index 000000000..a9cfee6c3 --- /dev/null +++ b/testsuite/tests/354-source-encoding/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Use of Ada 20212 constructs diff --git a/testsuite/tests/354-source-encoding/test.py b/testsuite/tests/354-source-encoding/test.py new file mode 100644 index 000000000..7f33f2794 --- /dev/null +++ b/testsuite/tests/354-source-encoding/test.py @@ -0,0 +1,267 @@ +"""Check that XML reports are valid for non-ASCII sources.""" + +import xml.dom.minidom as minidom + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import gprfor, xcov + + +def xml_src_summary(filename): + """ + Read the given XML source file coverage report and extract a summary of + the quoted lines it contains. + """ + result = [] + + def append(level, tag, content=None): + prefix = " " * level + tag + result.append( + f"{prefix}: {ascii(content)}" if content is not None else prefix + ) + + def element_nodes(parent): + return [n for n in parent.childNodes if isinstance(n, minidom.Element)] + + def process_src_mapping(n): + assert n.tagName == "src_mapping" + append(0, "src_mapping") + for c in element_nodes(n): + match c.tagName: + case "src": + process_src(c, 1) + case "statement": + process_statement(c, 1) + case "decision": + process_decision(c, 1) + case "message": + pass + case _: + raise AssertionError( + f"unexpected src_mapping child element: {c.tagName}" + ) + + def process_src(n, level): + assert n.tagName == "src" + append(level, "src") + for c in element_nodes(n): + match c.tagName: + case "line": + append( + level + 1, + f"line {c.getAttribute('num')}", + c.getAttribute("src"), + ) + case _: + raise AssertionError( + f"unexpected src child element: {c.tagName}" + ) + + def process_statement(n, level): + append(level, "statement", n.getAttribute("text")) + for c in element_nodes(n): + match c.tagName: + case "src": + process_src(c, level + 1) + case _: + raise AssertionError( + f"unexpected statement child element: {c.tagName}" + ) + + def process_decision(n, level): + append(level, "decision", n.getAttribute("text")) + for c in element_nodes(n): + match c.tagName: + case "src": + process_src(c, level + 1) + case "condition": + process_condition(c, level + 1) + case _: + raise AssertionError( + f"unexpected decision child element: {c.tagName}" + ) + + def process_condition(n, level): + append(level, "condition", n.getAttribute("text")) + for c in element_nodes(n): + match c.tagName: + case "src": + process_src(c, level + 1) + case _: + raise AssertionError( + f"unexpected condition child element: {c.tagName}" + ) + + doc = minidom.parse(filename) + source = doc.documentElement + for n in element_nodes(source): + if n.tagName == "src_mapping": + process_src_mapping(n) + return "\n".join(result) + + +def check_xml_srclines(filename, expected_summary): + """ + Read "filename" using xml_src_summary and check that it yields the given + expected summary. + """ + baseline = "tmp.txt" + with open(baseline, "w") as f: + f.write(expected_summary) + thistest.fail_if_diff_internal( + baseline, + xml_src_summary(filename), + failure_message=f"unexpected source excerpts in {filename}", + ignore_white_chars=False, + ) + + +def create_summary( + name, + full_content, + truncated_content, +): + """ + Create a XML source file summary compatible with xml_src_summary for one of + this testcase's source file. + """ + + # Adjust expectations for binary traces, which provide imprecise slocs + line_6_cond = "A)" if thistest.options.trace_mode == "src" else "A" + + result = [ + "src_mapping", + " src", + " line 1: 'pragma Ada_2012;'", + "src_mapping", + " src", + f" line 2: 'package {name} is'", + "src_mapping", + " src", + " line 3: ' function Id (V : Boolean) return Boolean is (V);'", + " statement: 'V'", + " src", + " line 3: ' V'", + "src_mapping", + " src", + " line 4: ' function F (A, B : Boolean) return Boolean'", + "src_mapping", + " src", + f" line 5: {ascii(f' is (Id (-- {full_content}')}", + f" statement: {ascii(f'Id (-- {truncated_content}...')}", + " src", + f" line 5: {ascii(f' Id (-- {full_content}')}", + " line 6: ' A) and then B'", + f" decision: {ascii(f'Id (-- {truncated_content}...')}", + " src", + f" line 5: {ascii(f' Id (-- {full_content}')}", + " line 6: ' A) and then B'", + f" condition: {ascii(f'Id (-- {truncated_content}...')}", + " src", + f" line 5: {ascii(f' Id (-- {full_content}')}", + f" line 6: ' {line_6_cond}'", + " condition: 'B'", + " src", + " line 6: ' B'", + "src_mapping", + " src", + " line 6: ' A) and then B);'", + "src_mapping", + " src", + f" line 7: 'end {name};'", + ] + return "\n".join(result) + + +tmp = Wdir("tmp_") + +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt+mcdc", + mains=["main"], + extra_coverage_args=["--annotate=xml"], +) + + +def check_report( + label: str, + encoding: str | None, + expected_warnings: list[str], + latin1_summary: str, + utf8_summary: str, +): + """ + Check XML report production. + + :param label: Name for this check. + :param encoding: Optional non-default encoding to pass to "gnatcov + coverage". + :param expected_warnings: Exhaustive list of warnings that are expected + from "gnatcov coverage". + :param latin1_summary: Expected summary of the XML report for latin1.ads. + :param utf8_summary: Expected summary of the XML report for utf8.ads. + """ + thistest.log(f"== {label} ==") + + log_file = f"coverage-{label}.log" + + # Make gnatcov produce the XML report for the given encoding + argv = xcov_args + [f"--output-dir=out-{label}"] + if encoding is not None: + argv.append(f"--source-encoding={encoding}") + xcov(argv, out=log_file) + + # Check that we have exacly the expected warnings + thistest.fail_if_not_equal( + "'gnatcov coverage' output", + "\n".join(expected_warnings), + contents_of(log_file).strip(), + ) + + # Check the content of the XML report for both sources + check_xml_srclines(f"out-{label}/latin1.ads.xml", latin1_summary) + check_xml_srclines(f"out-{label}/utf8.ads.xml", utf8_summary) + + +# By default, all sources are interpreted as Latin-1. Note that truncation +# changes depending on the encoding as the same sequence of bytes may not yield +# the same number of codepoints. +check_report( + label="default", + encoding=None, + expected_warnings=[], + latin1_summary=create_summary("Latin1", "\xc9a\xc9", "\xc9a"), + utf8_summary=create_summary("UTF8", "\xc3\x89a\xc3\x89", "\xc3\x89"), +) + +# Check report production when the same set of sources is interpreted as UTF-8. +# Invalid UTF-8 byte sequences (in latin1.ads) are turned into U+FFFD +# codepoints. +check_report( + label="utf-8", + encoding="utf-8", + expected_warnings=["warning: latin1.ads:5: cannot decode as utf-8"], + latin1_summary=create_summary("Latin1", "\ufffda\ufffd", "\ufffda"), + utf8_summary=create_summary("UTF8", "\xc9a\xc9", "\xc9a"), +) + +# Check that we correctly reject invalid encodings +thistest.log("== invalid ==") +p = xcov( + xcov_args + ["--source-encoding=invalid"], + out="coverage-invalid.log", + register_failure=False, +) +thistest.fail_if( + p.status == 0, + "[invalid] failure expected, but 'gnatcov coverage' succeeded", +) +thistest.fail_if_no_match( + "'gnatcov coverage' output", + ".*gnatcov.*: unsupported encoding for sources: 'invalid'", + contents_of("coverage-invalid.log").strip(), +) + +thistest.result() diff --git a/testsuite/tests/354-source-encoding/utf8.ads b/testsuite/tests/354-source-encoding/utf8.ads new file mode 100644 index 000000000..d57e6cd69 --- /dev/null +++ b/testsuite/tests/354-source-encoding/utf8.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; +package UTF8 is + function Id (V : Boolean) return Boolean is (V); + function F (A, B : Boolean) return Boolean + is (Id (-- ÉaÉ + A) and then B); +end UTF8; diff --git a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected index 42cbb758f..32ac604bf 100644 --- a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected +++ b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected @@ -612,9 +612,9 @@ - + - + @@ -719,7 +719,7 @@ - + diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index 187513d90..566700cb4 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -287,6 +287,7 @@ package body Annotations.Xml is procedure Generate_Report (Context : Coverage.Context_Access) is Pp : Xml_Pretty_Printer := (Need_Sources => True, + Use_UTF8 => True, Context => Context, others => <>); begin @@ -324,7 +325,7 @@ package body Annotations.Xml is begin Pp.ST ("condition", A ("id", Img (Integer (SCO))) - & A ("text", SCO_Text (SCO)) + & A ("text", Pp.SCO_Text (SCO)) & A ("coverage", State_Char (State))); for Annotation of SCO_Annotations (SCO) loop Pp.T ("annotation", A ("text", Annotation)); @@ -518,7 +519,7 @@ package body Annotations.Xml is begin Pp.ST ("decision", A ("id", Img (Integer (SCO))) - & A ("text", SCO_Text (SCO)) + & A ("text", Pp.SCO_Text (SCO)) & A ("coverage", State_Char (State))); for Annotation of SCO_Annotations (SCO) loop Pp.T ("annotation", A ("text", Annotation)); @@ -677,7 +678,7 @@ package body Annotations.Xml is begin Pp.ST ("statement", A ("id", Img (Integer (SCO))) - & A ("text", SCO_Text (SCO)) + & A ("text", Pp.SCO_Text (SCO)) & A ("coverage", State_Char (State))); for Annotation of SCO_Annotations (SCO) loop Pp.T ("annotation", A ("text", Annotation)); @@ -741,7 +742,8 @@ package body Annotations.Xml is declare Attributes : Unbounded_String := +A ("num", Img (Line_Num)); - Line : constant String := Get_Line (Current_Line_Sloc); + Line : constant String := + Get_Line (Current_Line_Sloc, UTF8 => True); Src_Start : Natural := Line'First; Src_End : Natural := Line'Last; begin diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index cf14d6fd5..2ca889720 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -147,7 +147,8 @@ package body Annotations is procedure Process_One_Line (Index : Positive) is LI : constant Line_Info_Access := Get_Line (FI, Index); begin - Pretty_Print_Start_Line (Pp, Index, LI, Get_Line (FI, Index)); + Pretty_Print_Start_Line + (Pp, Index, LI, Get_Line (FI, Index, UTF8 => Pp.Use_UTF8)); if Pp.Show_Details then Disp_Instruction_Sets (Pp, LI.all); @@ -676,14 +677,13 @@ package body Annotations is -- SCO_Text -- -------------- - function SCO_Text (SCO : SCO_Id; Length : Natural := 8) return String is - + function SCO_Text + (SCO : SCO_Id; + Length : Natural := 9; + UTF8 : Boolean := False) return String + is Sloc_Start : Source_Location := First_Sloc (SCO); Sloc_End : Source_Location := End_Lex_Element (Last_Sloc (SCO)); - Sloc_Bound : Source_Location; - Line : Unbounded_String; - Col_Start : Natural; - Col_End : Natural; Desc : Unbounded_String; -- SCO description: shortened view of the SCO tokens, with a macro @@ -756,28 +756,77 @@ package body Annotations is end; end if; - Line := +Get_Line (Sloc_Start); + -- As an approximation (given the diversity of provenance for sloc + -- ranges, we cannot be sure), consider that 1 codepoint equals one + -- column. - if US.Length (Line) < Sloc_Start.L.Column then - return ""; - end if; + declare + Line : constant String := Get_Line (Sloc_Start, UTF8); + Line_Length : Natural := 0; + Index : Natural := Line'First; - Col_Start := Sloc_Start.L.Column; + Sloc_Bound : Source_Location; + Slice_Start : Natural; + Slice_End : Natural; + Slice_Bound : Natural; + begin + if UTF8 then + while Index in Line'Range loop + Move_Forward_UTF8 (Line, Index, 1); + Line_Length := Line_Length + 1; + end loop; + else + Line_Length := Line'Length; + end if; - Sloc_Bound := Sloc_Start; - Sloc_Bound.L.Column := Sloc_Start.L.Column + Length; + if Line_Length < Sloc_Start.L.Column then + return ""; + end if; - -- We will print out a shortened view (8 characters by default) of the - -- SCO tokens. + -- Compute the index of the first byte in Line to include + -- (Slice_Start). - if Sloc_Bound <= Sloc_End then - Col_End := Natural'Min (US.Length (Line), Sloc_Bound.L.Column); - Append (Desc, +Unbounded_Slice (Line, Col_Start, Col_End) & "..."); - else - Col_End := Natural'Min (US.Length (Line), Sloc_End.L.Column); - Append (Desc, Unbounded_Slice (Line, Col_Start, Col_End)); - end if; - return +Desc; + if UTF8 then + Slice_Start := Line'First; + Move_Forward_UTF8 (Line, Slice_Start, Sloc_Start.L.Column - 1); + else + Slice_Start := Sloc_Start.L.Column; + end if; + + -- Compute the index of the last byte in Line that would cover the + -- SCO (Slice_End). If the end of the SCO belongs to a new line, cut + -- at the end of the first line instead (we do not want to return a + -- multiline string). + + Slice_End := + (if Sloc_End.L.Line > Sloc_Start.L.Line + then Line'Last + + elsif UTF8 + then Slice_Last_UTF8 (Line, Sloc_End.L.Column) + + else Natural'Min (Line'Last, Sloc_End.L.Column)); + + -- Compute the index of the last byte in Line to include + -- (Slice_Bound). It's not the same as Slice_End to cap the slice to + -- Length codepoints. + + Sloc_Bound := Sloc_Start; + Sloc_Bound.L.Column := Sloc_Start.L.Column + Length - 1; + Slice_Bound := + (if UTF8 + then Slice_Last_UTF8 (Line, Sloc_Bound.L.Column) + else Sloc_Bound.L.Column); + + -- If the result is shortened, add an ellipsis + + if Slice_Bound < Slice_End then + Append (Desc, Line (Slice_Start .. Slice_Bound) & "..."); + else + Append (Desc, Line (Slice_Start .. Slice_End)); + end if; + return +Desc; + end; end SCO_Text; --------------------- @@ -832,7 +881,7 @@ package body Annotations is -- SCO_Image -- --------------- - function SCO_Image (SCO : SCO_Id; Length : Natural := 8) return String + function SCO_Image (SCO : SCO_Id; Length : Natural := 9) return String is begin return """" & SCO_Text (SCO, Length) & """"; diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 4c08b50bb..fbae014f0 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -104,10 +104,16 @@ package Annotations is private - function SCO_Text (SCO : SCO_Id; Length : Natural := 8) return String; - -- Extract the text of SCO from source file, truncating it to the - -- first source line and the first Length characters. If it has been - -- truncated, the returned value will end with "...". + function SCO_Text + (SCO : SCO_Id; + Length : Natural := 9; + UTF8 : Boolean := False) return String; + -- Extract the text of SCO from source file, truncating it to the first + -- source line and the first Length characters. If it has been truncated, + -- the returned value will end with "...". + -- + -- If UTF8, the source file text is decoded (see Files_Table.Get_Line) and + -- the result is valid UTF-8. function SCO_Annotations (SCO : SCO_Id) return String_Vectors.Vector; -- Return annotations for the SCO. For instance, this will return a list @@ -119,7 +125,7 @@ private Annotations : String_Vectors.Vector); -- Print annotations - function SCO_Image (SCO : SCO_Id; Length : Natural := 8) return String; + function SCO_Image (SCO : SCO_Id; Length : Natural := 9) return String; -- Return a string representation of the annotated SCO function Message_Annotation (M : Message) return String; @@ -134,13 +140,21 @@ private type Pretty_Printer is abstract tagged limited record Need_Sources : Boolean; Show_Details : Boolean; - Context : Coverage.Context_Access; + + Use_UTF8 : Boolean; + -- Whether source excerpts need to be converted to UTF-8 for this format + + Context : Coverage.Context_Access; end record; function Format (Pp : Pretty_Printer) return Annotation_Format_Family is abstract; -- Return the family of annotation formats that Pp generates + function SCO_Text + (Pp : Pretty_Printer; SCO : SCO_Id; Length : Natural := 9) return String + is (SCO_Text (SCO, Length, UTF8 => Pp.Use_UTF8)); + procedure Pretty_Print_Start (Pp : in out Pretty_Printer) is null; -- Called once at the beginning of the process diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 16d25e6e9..00655c215 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -160,7 +160,8 @@ package Command_Line is Opt_Start_Location, Opt_End_Location, Opt_Justification, - Opt_SS_Backend); + Opt_SS_Backend, + Opt_Source_Encoding); -- Set of string options we support. More complete descriptions below. type String_List_Options is @@ -1350,7 +1351,16 @@ package Command_Line is & " annotation entry", Commands => (Cmd_Add_Annotation => True, others => False), At_Most_Once => False, - Internal => True)); + Internal => True), + Opt_Source_Encoding => Create + (Long_Name => "--source-encoding", + Pattern => "ENCODING", + Help => + "Specify the encoding to use to read source files in order to" + & " produce XML coverage reports.", + Commands => (Cmd_Coverage => True, others => False), + At_Most_Once => False, + Internal => False)); String_List_Infos : constant String_List_Option_Info_Array := (Opt_Log => Create diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 664ee4ea2..8c266be0d 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -27,7 +27,9 @@ with GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; with Osint; -with GNATCOLL.VFS; use GNATCOLL.VFS; +with GNATCOLL.Iconv; use GNATCOLL.Iconv; +with GNATCOLL.Utils; use GNATCOLL.Utils; +with GNATCOLL.VFS; use GNATCOLL.VFS; with Checkpoints; use Checkpoints; with Coverage; use Coverage; @@ -213,6 +215,34 @@ package body Files_Table is function Create_Line_Info return Line_Info_Access; -- Return a new Line_Info record + -------------- + -- Encoding -- + -------------- + + Iconv_Initialized : Boolean := False; + -- Whether Set_Encoding was called, and thus whether Iconv_Handle is + -- initialized. + + Iconv_Encoding : Unbounded_String; + -- Last encoding passed to Set_Encoding + + Iconv_Handle : Iconv_T; + -- GNATCOLL.Iconv handle to perform transcoding + + Iconv_Buffer : String_Access; + -- Result buffer for decoded strings + + procedure Transcode_To_UTF8 + (S : String; + Last : out Natural; + On_Error : access procedure); + -- Transcode S to UTF-8 in Iconv_Buffer (Iconv_Buffer'First .. Last), which + -- is (re)allocated as needed. If a transcoding error occurs, it is skipped + -- and On_Error is called. + -- + -- Note that this is intended to be used for fairly small strings only, and + -- we use it to decode source files only one line at a time. + --------------------- -- Append_To_Array -- --------------------- @@ -925,6 +955,149 @@ package body Files_Table is return Result; end Get_Index_From_Generic_Name; + ------------------ + -- Set_Encoding -- + ------------------ + + procedure Set_Encoding (Encoding : String) is + begin + if Iconv_Initialized then + Iconv_Close (Iconv_Handle); + Iconv_Initialized := False; + end if; + Iconv_Handle := Iconv_Open (UTF8, Encoding); + Iconv_Encoding := +Encoding; + Iconv_Initialized := True; + exception + when Unsupported_Conversion => + Outputs.Fatal_Error + ("unsupported encoding for sources: '" & Encoding & "'"); + end Set_Encoding; + + ----------------------- + -- Transcode_To_UTF8 -- + ----------------------- + + procedure Transcode_To_UTF8 + (S : String; + Last : out Natural; + On_Error : access procedure) is + begin + -- Make sure the decoder to UTF-8 is initialized and that we have a + -- buffer big enough to hold all possible decoded content: worse case, + -- each decoded byte in Line yields 4 bytes (biggest UTF-8 + -- representation for a codepoint). + + if not Iconv_Initialized then + Set_Encoding (ISO_8859_1); + end if; + + if Iconv_Buffer = null + or else Iconv_Buffer.all'Length < 4 * S'Length + then + Free (Iconv_Buffer); + Iconv_Buffer := new String (1 .. 4 * S'Length); + end if; + + declare + Inbuf : String renames S; + Input_Index : Positive := Inbuf'First; + Outbuf : String renames Iconv_Buffer.all; + Output_Index : Positive := Outbuf'First; + Result : Iconv_Result; + begin + while Input_Index <= Inbuf'Last loop + Iconv + (Iconv_Handle, + Inbuf, + Input_Index, + Outbuf, + Output_Index, + Result); + case Result is + when Success => + null; + + when Invalid_Multibyte_Sequence + | Incomplete_Multibyte_Sequence + => + -- We could not decode the sequence that starts at + -- Inbuf (Input_Index): append the U+FFFD REPLACEMENT + -- CHARACTER codepoint (EF BF BD in UTF-8) to the output + -- buffer and skip that input byte. + + Outbuf (Output_Index .. Output_Index + 2) := + (Character'Val (16#ef#), + Character'Val (16#bf#), + Character'Val (16#bd#)); + Output_Index := Output_Index + 3; + Input_Index := Input_Index + 1; + Reset (Iconv_Handle); + + if On_Error /= null then + On_Error.all; + end if; + + when Full_Buffer => + + -- We allocate the buffer precisely so that this never + -- happens: this should be dead code. + + raise Program_Error; + end case; + end loop; + Last := Output_Index - 1; + end; + end Transcode_To_UTF8; + + ------------- + -- To_UTF8 -- + ------------- + + function To_UTF8 (S : String) return String is + Last : Natural; + begin + Transcode_To_UTF8 (S, Last, On_Error => null); + return Iconv_Buffer.all (Iconv_Buffer'First .. Last); + end To_UTF8; + + ----------------------- + -- Move_Forward_UTF8 -- + ----------------------- + + procedure Move_Forward_UTF8 + (S : String; Index : in out Natural; Count : Natural) is + begin + for I in 1 .. Count loop + if Index not in S'Range then + return; + end if; + Index := Forward_UTF8_Char (S, Index); + end loop; + end Move_Forward_UTF8; + + --------------------- + -- Slice_Last_UTF8 -- + --------------------- + + function Slice_Last_UTF8 + (S : String; Length : Natural) return Natural + is + Result : Natural := S'First; + begin + if Length = 0 then + return 0; + else + Move_Forward_UTF8 (S, Result, Length); + + -- At this point, Result points to the first byte of the codepoint + -- past the end of the slice: we want to designate the last byte of + -- the previous codepoint. + + return Result - 1; + end if; + end Slice_Last_UTF8; + -------------- -- Get_Line -- -------------- @@ -957,18 +1130,20 @@ package body Files_Table is end if; end Get_Line; - function Get_Line (Sloc : Source_Location) return String is + function Get_Line + (Sloc : Source_Location; UTF8 : Boolean := False) return String is begin if Sloc = Slocs.No_Location then return ""; end if; - return Get_Line (Get_File (Sloc.Source_File), Sloc.L.Line); + return Get_Line (Get_File (Sloc.Source_File), Sloc.L.Line, UTF8); end Get_Line; function Get_Line (File : File_Info_Access; - Index : Positive) return String + Index : Positive; + UTF8 : Boolean := False) return String is Line : String_Access; begin @@ -978,18 +1153,46 @@ package body Files_Table is Fill_Line_Cache (File); - if Index in File.Lines.First_Index .. File.Lines.Last_Index then - Line := File.Lines.Element (Index).Line_Cache; - - if Line /= null then - return Line.all; - else - return ""; - end if; + if Index not in File.Lines.First_Index .. File.Lines.Last_Index then + return ""; + end if; - else + Line := File.Lines.Element (Index).Line_Cache; + if Line = null or else Line.all = "" then return ""; end if; + + -- If were asked bytes, return now + + if not UTF8 then + return Line.all; + end if; + + -- Otherwise, transcode to UTF8 as requested + + declare + procedure On_Error; + -- Warn at most once per source file that there is a decoding error + + Last : Natural; + + -------------- + -- On_Error -- + -------------- + + procedure On_Error is + begin + if not File.Has_Decoding_Error then + Outputs.Warn + (File.Unique_Name.all & ":" & Img (Index) + & ": cannot decode as " & (+Iconv_Encoding)); + File.Has_Decoding_Error := True; + end if; + end On_Error; + begin + Transcode_To_UTF8 (Line.all, Last, On_Error'Access); + return Iconv_Buffer.all (Iconv_Buffer.all'First .. Last); + end; end Get_Line; --------------------- diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 3d5e3fabd..348c9aa3f 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -399,6 +399,10 @@ package Files_Table is Lines : Source_Lines; -- Source file to display in the reports + Has_Decoding_Error : Boolean := False; + -- Whether we got at least one error when decoding a source line + -- to UTF-8. + Sloc_To_SCO_Maps : Sloc_To_SCO_Map_Array_Acc; -- Sloc -> SCO_Id indices for this file @@ -501,12 +505,36 @@ package Files_Table is Sloc = Slocs.No_Location or else Get_File (Sloc.Source_File).Kind in Stub_File | Source_File; + procedure Set_Encoding (Encoding : String); + -- Set the encoding used to interpret source code (this is a global + -- setting). This raises a fatal error if Encoding is not supported. If not + -- called, assume latin-1 (the default for Ada, has the advantage of being + -- able to decode any binary content). + + function To_UTF8 (S : String) return String; + -- Transcode the given string according to the last call to Set_Encoding to + -- UTF-8. Bytes that could not be decoded are turned into replacement + -- codepoints. + + procedure Move_Forward_UTF8 + (S : String; Index : in out Natural; Count : Natural); + -- Assuming that S is a valid UTF-8 string and that Index refers to the + -- first byte of a codepoint in S, increment Index so that it moves forward + -- by Count codepoints. If Index is out of S's range, do nothing. + + function Slice_Last_UTF8 + (S : String; Length : Natural) return Natural; + -- Return the index I that would make S (S'First .. I) a slice that + -- contains Length codepoints. + function Get_Line (File : File_Info_Access; - Index : Positive) return String + Index : Positive; + UTF8 : Boolean := False) return String with Pre => File.Kind = Source_File; - function Get_Line (Sloc : Source_Location) return String + function Get_Line + (Sloc : Source_Location; UTF8 : Boolean := False) return String with Pre => Sloc = Slocs.No_Location or else Get_File (Sloc.Source_File).Kind = Source_File; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 124edc027..c12aa40f7 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -894,6 +894,13 @@ procedure GNATcov_Bits_Specific is " when --cancel-annotate is also specified"); end if; + -- If a source encoding is specified, use it to decode source + -- files. + + if Args.String_Args (Opt_Source_Encoding).Present then + Set_Encoding (+Args.String_Args (Opt_Source_Encoding).Value); + end if; + -- Remaining arguments are supposed to be copied to Opt_Trace, -- which is already handled, so there's nothing left to do with -- them. From cba1add29214850ff16dcdc1209d1b504fede2d5 Mon Sep 17 00:00:00 2001 From: Guillaume Rivier Date: Wed, 20 Nov 2024 10:57:59 +0900 Subject: [PATCH 1013/1483] Fix root directory for GNATSAS report in Gitlab --- tools/gnatcov/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index d74a71274..6e91ce82c 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -376,7 +376,10 @@ gnatsas: gnatsas report -P gnatcov.gpr -o $(GNATSAS_OBJ_DIR)/gnatsas.out \ $(GNATSAS_ARGS) ; \ fi - gnatsas report code-climate -P gnatcov.gpr \ + # GNAT SAS report root should be the repository root so file URIs are + # correctly resolved in GitLab. This is executed from tools/gnatcov in the + # CI. + gnatsas report code-climate -P gnatcov.gpr --root ../.. \ -o $(GNATSAS_OBJ_DIR)/gnatsas/gnatsas.json $(GNATSAS_ARGS) ; bump_baseline: From 69027be40857344e553e479454a5e8ab948f2590 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 22 Nov 2024 16:52:24 +0100 Subject: [PATCH 1014/1483] Xfail test pending resolution of CCG regression --- .../Qualif/Ada/decision/1_Core/Operands/PnestStaType/test.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/test.opt index b057462eb..3a1fbb780 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/test.opt @@ -1,2 +1,3 @@ 7.1.2,bin-traces SKIP bogus sloc info for condition involving packed array, fixed post 7.0 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 +c XFAIL pending resolution of eng/toolchain/gnat-llvm#221 From 5dee9a7ab8d9f86ce55f4c7fb9b015dd24cf5835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 22 Nov 2024 15:16:01 +0100 Subject: [PATCH 1015/1483] insturment-ada_unit.adb: Detect separates Separates used to not be properly detected by the instrumenter, thus resulting in conflicting entities being generated for a body and a separate, leading to the instrumented code failing to compile. This change adds additional checks on the nature of the compilation unit being instrumented. --- .../instr-cov/357-separates/src/pkg-sep.adb | 10 ++++++++++ .../tests/instr-cov/357-separates/src/pkg.adb | 15 +++++++++++++++ .../tests/instr-cov/357-separates/src/pkg.ads | 5 +++++ .../instr-cov/357-separates/src/test_sep.adb | 16 ++++++++++++++++ testsuite/tests/instr-cov/357-separates/test.py | 15 +++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 8 ++++++++ 6 files changed, 69 insertions(+) create mode 100644 testsuite/tests/instr-cov/357-separates/src/pkg-sep.adb create mode 100644 testsuite/tests/instr-cov/357-separates/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/357-separates/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/357-separates/src/test_sep.adb create mode 100644 testsuite/tests/instr-cov/357-separates/test.py diff --git a/testsuite/tests/instr-cov/357-separates/src/pkg-sep.adb b/testsuite/tests/instr-cov/357-separates/src/pkg-sep.adb new file mode 100644 index 000000000..143a59969 --- /dev/null +++ b/testsuite/tests/instr-cov/357-separates/src/pkg-sep.adb @@ -0,0 +1,10 @@ +separate(Pkg) +package body Sep is + + Baz : Boolean := False; -- # decl + function Bar return Boolean is + begin + return Foo or else Baz; -- # eval + end Bar; + +end Sep; diff --git a/testsuite/tests/instr-cov/357-separates/src/pkg.adb b/testsuite/tests/instr-cov/357-separates/src/pkg.adb new file mode 100644 index 000000000..f1fbd2e38 --- /dev/null +++ b/testsuite/tests/instr-cov/357-separates/src/pkg.adb @@ -0,0 +1,15 @@ +package body Pkg is + + package Sep is + Foo : Boolean := True; -- # decl + function Bar return Boolean; + end Sep; + + package body Sep is separate; + + function Qux return Boolean is + begin + return Sep.Bar; -- # eval + end Qux; + +end Pkg; diff --git a/testsuite/tests/instr-cov/357-separates/src/pkg.ads b/testsuite/tests/instr-cov/357-separates/src/pkg.ads new file mode 100644 index 000000000..83a299851 --- /dev/null +++ b/testsuite/tests/instr-cov/357-separates/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Qux return Boolean; + +end Pkg; diff --git a/testsuite/tests/instr-cov/357-separates/src/test_sep.adb b/testsuite/tests/instr-cov/357-separates/src/test_sep.adb new file mode 100644 index 000000000..f3c5fd12b --- /dev/null +++ b/testsuite/tests/instr-cov/357-separates/src/test_sep.adb @@ -0,0 +1,16 @@ +with Pkg; + +with Support; + +procedure Test_Sep is +begin + Support.Assert (Pkg.Qux); +end Test_Sep; + +--# pkg.adb pkg-sep.adb +-- +-- /eval/ l+ ## 0 + +--%opts: --trace-mode=src +-- +-- /decl/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/357-separates/test.py b/testsuite/tests/instr-cov/357-separates/test.py new file mode 100644 index 000000000..90363f7a7 --- /dev/null +++ b/testsuite/tests/instr-cov/357-separates/test.py @@ -0,0 +1,15 @@ +""" +Test that gnatcov does not generate conflicting entities between a package spec +and its separate body. This could happen if the package is a nested package +declared in a body, and the nested package's body is a separate, in which the +suffixes for the entities gnatcov inserts were not different. The instrumented +code used to not compile at all. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT + +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 71d3b62bc..f242fadd9 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -9669,6 +9669,14 @@ package body Instrument.Ada_Unit is -- we can insert witness calls (which are not preelaborable). CU_Name.Part := +UIC.Root_Unit.P_Unit_Kind; + + -- P_Unit_Kind does not detect separates, so manually inspect the + -- compilation unit's contents. + + if UIC.Root_Unit.F_Body.Kind = Ada_Subunit then + CU_Name.Part := GNATCOLL.Projects.Unit_Separate; + end if; + CU_Name.Unit := To_Qualified_Name (UIC.Root_Unit.P_Decl.P_Fully_Qualified_Name_Array); From 20ddf95b65cdaf742c394472602c7e0f4babb30c Mon Sep 17 00:00:00 2001 From: Jerome Lambourg Date: Mon, 16 Sep 2024 18:44:27 +0200 Subject: [PATCH 1016/1483] Adjust to libgpr2 API change for logs For eng/gpr/gpr-issues#354 Depends-on: eng/gpr/gpr!395 Depends-on: eng/libadalang/libadalang!1781 (cherry picked from commit 40abed4578727cb439e2b449277ff7e95358e4fa) --- tools/gnatcov/setup_rts.adb | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 5fde76f5a..dc23a0044 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -37,8 +37,10 @@ with GPR2.Project.Attribute_Index; with GPR2.Project.Configuration; with GPR2.Project.Registry.Attribute; with GPR2.Project.Tree; +with GPR2.Reporter.Console; with Files_Handling; use Files_Handling; +with GPR2.Reporter; with JSON; use JSON; with Outputs; use Outputs; with Paths; use Paths; @@ -230,6 +232,10 @@ package body Setup_RTS is return Project.Load (Opts, + Reporter => GPR2.Reporter.Console.Create + ((if Setup_RTS_Trace.Is_Active + then GPR2.Reporter.Regular + else GPR2.Reporter.No_Warnings)), With_Runtime => True, Absent_Dir_Error => GPR2.No_Error); end Load_Project; @@ -454,16 +460,16 @@ package body Setup_RTS is Logs : constant access GPR2.Log.Object := Prj.Log_Messages; begin if Logs.Has_Element - (Information => False, - Warning => True, - Error => False, - Lint => False, - Read => False, - Unread => False) + (Hint => False, + Warning => True, + Error => False, + End_User => False, + Lint => False, + Read => True, + Unread => True) then Register_Warning; end if; - Logs.Output_Messages (Information => Setup_RTS_Trace.Is_Active); if Has_Error then Fatal_Error ("Could not load the coverage runtime project file"); end if; @@ -1088,8 +1094,6 @@ package body Setup_RTS is then Error ("Could not load the coverage runtime project " & Runtime_Project); - Prj.Log_Messages.Output_Messages - (Information => Setup_RTS_Trace.Is_Active); raise Xcov_Exit_Exc; end if; From 77a72c8bed672f4dcc90e5b1c2ff98b1fb294932 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 14 Oct 2024 19:43:30 +0000 Subject: [PATCH 1017/1483] 138-ada-preprocessing/prep_data: fix preprocessor directives syntax Preprocessor symbol references must not use the '$' prefix, so sources for this testcase are invalid. Libadalang used not to complain about this, so this went unnoticed so far. Libadalang now complains: adjust sources to have the intended meaning. (cherry picked from commit 7c269221f6bf2537891ec885ae77bcd08e927381) --- .../138-ada-preprocessing/prep_data/no_undef_is_false/pkg.adb | 2 +- testsuite/tests/138-ada-preprocessing/prep_data/test.py | 2 +- .../138-ada-preprocessing/prep_data/undef_is_false/pkg.adb | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/pkg.adb index 10d313e2f..388a3eece 100644 --- a/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/pkg.adb +++ b/testsuite/tests/138-ada-preprocessing/prep_data/no_undef_is_false/pkg.adb @@ -4,7 +4,7 @@ package body Pkg is procedure Run is begin -#if $X then +#if X then Put_Line ("X"); #else Put_Line ("not X"); diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/test.py b/testsuite/tests/138-ada-preprocessing/prep_data/test.py index a03c08244..031fc6499 100644 --- a/testsuite/tests/138-ada-preprocessing/prep_data/test.py +++ b/testsuite/tests/138-ada-preprocessing/prep_data/test.py @@ -48,7 +48,7 @@ class ReportTestcase(BaseTestcase): ".*gnatcov.*: instrumentation failed for .*pkg\\.adb" "\n.*gnatcov.*: please make sure the original project can be" " compiled" - '\n.*gnatcov.*: pkg\\.adb:7:5: unknown symbol "\\$X"', + '\n.*gnatcov.*: pkg\\.adb:7:5: unknown symbol "X"', ), ReportTestcase("default_config", {"+": {7}}), ReportTestcase("file_config", {"+": {7}}), diff --git a/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/pkg.adb b/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/pkg.adb index 966f0bfd3..9334c6a0e 100644 --- a/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/pkg.adb +++ b/testsuite/tests/138-ada-preprocessing/prep_data/undef_is_false/pkg.adb @@ -4,13 +4,13 @@ package body Pkg is procedure Run is begin -#if $X then +#if X then Invalid Statement #else Put_Line ("Hello, world!"); #end if; -#if not $X then +#if not X then Put_Line ("Hello, world!"); #else Invalid Statement From 31b7117f06005d1de1adeb717a6d838e4fddf6be Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 4 Nov 2024 12:08:37 +0000 Subject: [PATCH 1018/1483] Migrate calls to the obsolete To_Ada_Time to To_Ada_Time_64 (cherry picked from commit 620770703416246e42a36e9fa830a5083d80eef0) --- tools/gnatcov/annotations-cobertura.adb | 2 +- tools/gnatcov/traces_files_registry.adb | 22 +++++++++------------- 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb index 14bc43f10..1a0431955 100644 --- a/tools/gnatcov/annotations-cobertura.adb +++ b/tools/gnatcov/annotations-cobertura.adb @@ -351,7 +351,7 @@ package body Annotations.Cobertura is Success : Boolean; Timestamp : constant String := Ada.Strings.Fixed.Trim - (long'Image (To_Unix_Time (Pp.Context.Timestamp)), + (long_long'Image (To_Unix_Time_64 (Pp.Context.Timestamp)), Ada.Strings.Left); begin -- Copy the DTD Schema to the output directory diff --git a/tools/gnatcov/traces_files_registry.adb b/tools/gnatcov/traces_files_registry.adb index dfddc9e0e..b17c1a1e3 100644 --- a/tools/gnatcov/traces_files_registry.adb +++ b/tools/gnatcov/traces_files_registry.adb @@ -209,21 +209,17 @@ package body Traces_Files_Registry is Year, Month, Day, Hour, Minute, Second : int; - -- The "long" value we need to craft has to fit both a - -- "long" number of seconds and a "long long" number of - -- nanoseconds, which the runtime library will compute - -- internally. Then "long" and "long long" are not - -- necessarily the same length, in particular on Windows - -- where "long" is 32bit even in the 64bit ABI. - - Nano : constant := 1 * 10**9; - Max_Timestamp : constant Unsigned_64 := - Unsigned_64'Min (Unsigned_64 (long'Last), - Unsigned_64 (long_long'Last / Nano)); + -- Convert the timestamp we got (Unsigned_64) to the + -- corresponding Unix API type (long long). In case we get + -- buggy (too large) values, silently cap them. + + Max_Timestamp : constant Unsigned_64 := + Unsigned_64 (long_long'Last); + Unix_Timestamp : constant long_long := + long_long (Unsigned_64'Min (Timestamp, Max_Timestamp)); begin To_Struct_Tm - (To_Ada_Time - (long (Unsigned_64'Min (Timestamp, Max_Timestamp))), + (To_Ada_Time_64 (Unix_Timestamp), Year, Month, Day, Hour, Minute, Second); Info_Date.Year := Unsigned_16 (1900 + Year); From c82b2a8cdbdf9338760d8c28d3ae6c39fd00a395 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 12 Nov 2024 10:41:20 +0000 Subject: [PATCH 1019/1483] Update after API breaking changes in Libadalang (cherry picked from commit 46d55c0d4183d52d04161fdead2c8e6d7fcf3ce8) --- tools/gnatcov/instrument-ada_unit.adb | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index f242fadd9..5e5690c87 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -5111,9 +5111,11 @@ package body Instrument.Ada_Unit is -- Finally traverse the ELSE statements if present - Traverse_Declarations_Or_Statements - (UIC, - L => If_N.F_Else_Stmts.As_Ada_Node_List); + if not If_N.F_Else_Part.Is_Null then + Traverse_Declarations_Or_Statements + (UIC, + L => If_N.F_Else_Part.F_Stmts.As_Ada_Node_List); + end if; end; -- Start a new statement block for statements after the if @@ -5205,12 +5207,16 @@ package body Instrument.Ada_Unit is -- Note: the sequences of statements for ELSE and ABORT -- do not require the special processing for alternatives. - Traverse_Declarations_Or_Statements - (UIC, - L => Sel_N.F_Else_Stmts.As_Ada_Node_List); - Traverse_Declarations_Or_Statements - (UIC, - L => Sel_N.F_Abort_Stmts.As_Ada_Node_List); + if not Sel_N.F_Else_Part.Is_Null then + Traverse_Declarations_Or_Statements + (UIC, + L => Sel_N.F_Else_Part.F_Stmts.As_Ada_Node_List); + end if; + if not Sel_N.F_Then_Abort_Part.Is_Null then + Traverse_Declarations_Or_Statements + (UIC, + L => Sel_N.F_Then_Abort_Part.F_Stmts.As_Ada_Node_List); + end if; end; -- Open a new statement block for statements after the select From 52723c94df63618456deebad295f69376d19a090 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 27 Nov 2024 15:52:44 +0100 Subject: [PATCH 1020/1483] Attach aspects to new expr function Ensure the aspects of the original expression function are also given to the new intermediary expression function. --- testsuite/tests/358-exprf-aspects/extra.opt | 2 + .../tests/358-exprf-aspects/src/aspect.adb | 14 ++++ .../358-exprf-aspects/src/test_aspect.adb | 15 ++++ testsuite/tests/358-exprf-aspects/test.py | 6 ++ tools/gnatcov/instrument-ada_unit.adb | 77 ++++++------------- 5 files changed, 59 insertions(+), 55 deletions(-) create mode 100644 testsuite/tests/358-exprf-aspects/extra.opt create mode 100644 testsuite/tests/358-exprf-aspects/src/aspect.adb create mode 100644 testsuite/tests/358-exprf-aspects/src/test_aspect.adb create mode 100644 testsuite/tests/358-exprf-aspects/test.py diff --git a/testsuite/tests/358-exprf-aspects/extra.opt b/testsuite/tests/358-exprf-aspects/extra.opt new file mode 100644 index 000000000..6609aef9d --- /dev/null +++ b/testsuite/tests/358-exprf-aspects/extra.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD Requires Ada 2012, unavailable in 5.04a1 +7.1.2 DEAD support for expression functions weak in 7.1.2 diff --git a/testsuite/tests/358-exprf-aspects/src/aspect.adb b/testsuite/tests/358-exprf-aspects/src/aspect.adb new file mode 100644 index 000000000..705138bcf --- /dev/null +++ b/testsuite/tests/358-exprf-aspects/src/aspect.adb @@ -0,0 +1,14 @@ +pragma Ada_2012; + +procedure Aspect is + + function Foo return Integer is (42) -- # expr + with Convention => Stdcall; + + type Foo_Type is access + function return Integer with Convention => Stdcall; -- # type + + Dummy : Foo_Type := Foo'Access; -- # dummy +begin + null; +end Aspect; diff --git a/testsuite/tests/358-exprf-aspects/src/test_aspect.adb b/testsuite/tests/358-exprf-aspects/src/test_aspect.adb new file mode 100644 index 000000000..37071c12b --- /dev/null +++ b/testsuite/tests/358-exprf-aspects/src/test_aspect.adb @@ -0,0 +1,15 @@ +with Aspect; + +-- Check that when instrumenting an expression function with aspects, these +-- aspects are also correctly attached to both the new intermediary function +-- and to the augmented expression function. + +procedure Test_Aspect is +begin + Aspect; +end Test_Aspect; + +--# aspect.adb +-- /expr/ l- ## s- +-- /type/ l+ ## 0 +-- /dummy/ l+ ## 0 diff --git a/testsuite/tests/358-exprf-aspects/test.py b/testsuite/tests/358-exprf-aspects/test.py new file mode 100644 index 000000000..11e55638b --- /dev/null +++ b/testsuite/tests/358-exprf-aspects/test.py @@ -0,0 +1,6 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 5e5690c87..3355c1188 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1035,7 +1035,8 @@ package body Instrument.Ada_Unit is Call_Params : Node_Rewriting_Handle; Augmented_Function : out Node_Rewriting_Handle; Augmented_Function_Decl : out Node_Rewriting_Handle; - New_Function : out Node_Rewriting_Handle); + New_Function : out Node_Rewriting_Handle; + Needs_Aspects : Boolean := False); -- Create the augmented function from the original one (Augmented_Function) -- and create the new function (New_Function) that will serve as a -- replacement to the original one. Also create a declaration for the @@ -2642,7 +2643,8 @@ package body Instrument.Ada_Unit is Call_Params : Node_Rewriting_Handle; Augmented_Function : out Node_Rewriting_Handle; Augmented_Function_Decl : out Node_Rewriting_Handle; - New_Function : out Node_Rewriting_Handle) + New_Function : out Node_Rewriting_Handle; + Needs_Aspects : Boolean := False) is RC : Rewriting_Handle renames UIC.Rewriting_Context; @@ -2703,7 +2705,9 @@ package body Instrument.Ada_Unit is Orig_Aspects : constant Aspect_Spec := Common_Nodes.N.F_Aspects; begin - -- Create the new augmented function + -- Create the new augmented function. Attach the original aspects to + -- it if necessary, i.e. if they were not already attached to a previous + -- decalration of New_Function. New_Function := Create_Expr_Function @@ -2711,7 +2715,10 @@ package body Instrument.Ada_Unit is F_Overriding => Clone (Common_Nodes.N_Overriding), F_Subp_Spec => Clone (Common_Nodes.N_Spec), F_Expr => Create_Paren_Expr (RC, Call_Expr), - F_Aspects => No_Node_Rewriting_Handle); + F_Aspects => + (if Orig_Aspects /= No_Ada_Node and then Needs_Aspects + then Detach (Orig_Aspects) + else No_Node_Rewriting_Handle)); -- The original function becomes the augmented one: @@ -2806,55 +2813,6 @@ package body Instrument.Ada_Unit is end; else Augmented_Function_Decl := No_Node_Rewriting_Handle; - - if not Orig_Aspects.Is_Null then - declare - function Replace_Attr_Subp_Name - (N : Ada_Node'Class) return Visit_Status; - -- Replace all uses of the name of the original expression - -- function in an attribute reference in N with the name of the - -- new augmented expr function. - - function Replace_Attr_Subp_Name - (N : Ada_Node'Class) return Visit_Status is - begin - if N.Kind = Ada_Attribute_Ref - and then N.As_Attribute_Ref.F_Prefix.Text = Orig_Name_Text - then - Replace - (Handle (N.As_Attribute_Ref.F_Prefix), - Make_Identifier (UIC, Augmented_Func_Name)); - end if; - return Into; - end Replace_Attr_Subp_Name; - - Assocs : constant Aspect_Assoc_List := - Orig_Aspects.F_Aspect_Assocs; - Idx : Positive := 1; - Has_Elt : Boolean := Assocs.Aspect_Assoc_List_Has_Element (Idx); - begin - while Has_Elt loop - declare - Aspect_Expr : constant Expr := - Assocs.Aspect_Assoc_List_Element (Idx).F_Expr; - begin - if Aspect_Expr /= No_Expr then - Traverse (Aspect_Expr, Replace_Attr_Subp_Name'Access); - end if; - - Idx := Idx + 1; - Has_Elt := Assocs.Aspect_Assoc_List_Has_Element (Idx); - end; - end loop; - end; - end if; - - -- Attach the aspect specifications of the original expression - -- function to the augmented one. - - Set_Child (Augmented_Function, - Member_Refs.Basic_Decl_F_Aspects, - Detach (Orig_Aspects)); end if; -- If the original expression function is ghost, so must be the @@ -2912,7 +2870,7 @@ package body Instrument.Ada_Unit is function Augmented_Expr_Function_Needs_Decl (N : Expr_Function) return Boolean is - Previous_Decl : Basic_Decl; + Previous_Decl : Basic_Decl; -- Will hold the previous declaration of the expression function, -- if any. @@ -4121,6 +4079,12 @@ package body Instrument.Ada_Unit is Is_Expr_Function : constant Boolean := N.Kind = Ada_Expr_Function; + Needs_Aspects : Boolean := True; + -- If the new expression function required the creation of a previous + -- declaration, then the aspects of the original one have already + -- been attached to it and there is no need to attach them to the + -- body in the call to Create_Augmented_Function. + Gen_Names_Prefix : constant Wide_Wide_String := To_Wide_Wide_String ((if Is_Expr_Function @@ -4648,6 +4612,8 @@ package body Instrument.Ada_Unit is -- For expression functions, the aspects of the subprogram were -- moved to the newly created declaration, so they should not be -- added to the augmented function later on. + + Needs_Aspects := False; end if; if Is_Expr_Function then @@ -4666,7 +4632,8 @@ package body Instrument.Ada_Unit is Call_Params, Augmented_Function, Augmented_Function_Decl, - New_Function); + New_Function, + Needs_Aspects); -- First comes the augmented expression function, then the new -- expression function. From 7aa74701aa0352f989a94095be39b7b6d6a3bb55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 20 Nov 2024 18:34:29 +0100 Subject: [PATCH 1021/1483] SS_Annotations: Reject slocs containing a 0 when generating annotations --- .../gen/340-invalid-sloc/main.adb | 5 ++ .../gen/340-invalid-sloc/test.py | 71 +++++++++++++++++++ tools/gnatcov/ss_annotations.adb | 15 +++- 3 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/ext_annotations/gen/340-invalid-sloc/main.adb create mode 100644 testsuite/tests/ext_annotations/gen/340-invalid-sloc/test.py diff --git a/testsuite/tests/ext_annotations/gen/340-invalid-sloc/main.adb b/testsuite/tests/ext_annotations/gen/340-invalid-sloc/main.adb new file mode 100644 index 000000000..0288bde90 --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/340-invalid-sloc/main.adb @@ -0,0 +1,5 @@ +procedure Main is + Some_Var : Boolean := True; +begin + Some_Var := False; +end Main; diff --git a/testsuite/tests/ext_annotations/gen/340-invalid-sloc/test.py b/testsuite/tests/ext_annotations/gen/340-invalid-sloc/test.py new file mode 100644 index 000000000..4b5bd3c1e --- /dev/null +++ b/testsuite/tests/ext_annotations/gen/340-invalid-sloc/test.py @@ -0,0 +1,71 @@ +""" +Test that gnatcov does not crash when the source locations passed to the +--start-location or --end-location options, and instead exit in an error. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov, contents_of + +tmp = Wdir("tmp_") + + +def check_one(arg_name, invalid_line): + """ + Run gnatcov add-annotation to generate an annotation for main.adb, with + either a line or a column set to 0 in the value passed to arg_name, and + check that gnatcov correctly rejects the argument with an expected error + message. + + arg_name must be one of location, start-location or end-location. + """ + log_filename = arg_name + ("_line" if invalid_line else "_col") + ".log" + + sloc = "0:1" if invalid_line else "1:0" + + # Pass the requested argument to gnatcov. For start/end location arguments, + # also add the complementary argument. + sloc_args = [f"--{arg_name}={sloc}"] + if arg_name != "location": + sloc_args += [ + ( + "--end-location" + if arg_name == "start-location" + else "--start-location" + ), + "1:1", + ] + + p = xcov( + [ + "add-annotation", + "--kind", + "exempt_on" if arg_name == "location" else "exempt_region", + "--justification=dummy", + "--output=dummy.toml", + ] + + sloc_args + + ["../main.adb"], + out=log_filename, + register_failure=False, + ) + thistest.fail_if(p.status == 0, "zero return status not expected") + + expected_err = ( + r".*gnatcov(\.exe)?: " + + ("Line" if invalid_line else "Column") + + f" number in argument to --{arg_name} should not be 0" + ) + + thistest.fail_if_no_match( + what="wrong 'gnatcov add-annotation' error message", + regexp=expected_err, + actual=contents_of(log_filename), + ) + + +for arg_name in ["location", "start-location", "end-location"]: + for invalid_line in [True, False]: + check_one(arg_name, invalid_line) + +thistest.result() diff --git a/tools/gnatcov/ss_annotations.adb b/tools/gnatcov/ss_annotations.adb index 9720a3da1..015a1a57c 100644 --- a/tools/gnatcov/ss_annotations.adb +++ b/tools/gnatcov/ss_annotations.adb @@ -154,6 +154,9 @@ package body SS_Annotations is -- the value. -- -- An empty Str value is interpreted as a missing switch value. + -- + -- This function will reject source locations with a 0 for the line or the + -- column. function Guess_Lang (File : Virtual_File) return Any_Language; -- Try to guess the language of file based on its extension. @@ -276,12 +279,20 @@ package body SS_Annotations is function Get_Or_Error (Str : String; Sw : String) return Slocs.Local_Source_Location is + Res : Slocs.Local_Source_Location; begin if Str'Length = 0 then Fatal_Error ("Missing " & Sw & " on the command line"); end if; - - return Slocs.Value (Str); + Res := Slocs.Value (Str); + if Res.Line = 0 then + Fatal_Error ("Line number in argument to " & Sw & " should not be 0"); + end if; + if Res.Column = 0 then + Fatal_Error + ("Column number in argument to " & Sw & " should not be 0"); + end if; + return Res; exception when Exc : Constraint_Error => Fatal_Error From 18b9326272aba9d6f4ad97cf4128feceb898efd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Mon, 2 Dec 2024 17:34:20 +0100 Subject: [PATCH 1022/1483] Kill expr func aspect instrumentaion test for bin --- testsuite/tests/{ => instr-cov}/358-exprf-aspects/extra.opt | 1 + testsuite/tests/{ => instr-cov}/358-exprf-aspects/src/aspect.adb | 0 .../tests/{ => instr-cov}/358-exprf-aspects/src/test_aspect.adb | 0 testsuite/tests/{ => instr-cov}/358-exprf-aspects/test.py | 0 4 files changed, 1 insertion(+) rename testsuite/tests/{ => instr-cov}/358-exprf-aspects/extra.opt (65%) rename testsuite/tests/{ => instr-cov}/358-exprf-aspects/src/aspect.adb (100%) rename testsuite/tests/{ => instr-cov}/358-exprf-aspects/src/test_aspect.adb (100%) rename testsuite/tests/{ => instr-cov}/358-exprf-aspects/test.py (100%) diff --git a/testsuite/tests/358-exprf-aspects/extra.opt b/testsuite/tests/instr-cov/358-exprf-aspects/extra.opt similarity index 65% rename from testsuite/tests/358-exprf-aspects/extra.opt rename to testsuite/tests/instr-cov/358-exprf-aspects/extra.opt index 6609aef9d..03d283ab0 100644 --- a/testsuite/tests/358-exprf-aspects/extra.opt +++ b/testsuite/tests/instr-cov/358-exprf-aspects/extra.opt @@ -1,2 +1,3 @@ 5.04a1 DEAD Requires Ada 2012, unavailable in 5.04a1 7.1.2 DEAD support for expression functions weak in 7.1.2 +bin-traces DEAD Test for expr func aspect instrumentation diff --git a/testsuite/tests/358-exprf-aspects/src/aspect.adb b/testsuite/tests/instr-cov/358-exprf-aspects/src/aspect.adb similarity index 100% rename from testsuite/tests/358-exprf-aspects/src/aspect.adb rename to testsuite/tests/instr-cov/358-exprf-aspects/src/aspect.adb diff --git a/testsuite/tests/358-exprf-aspects/src/test_aspect.adb b/testsuite/tests/instr-cov/358-exprf-aspects/src/test_aspect.adb similarity index 100% rename from testsuite/tests/358-exprf-aspects/src/test_aspect.adb rename to testsuite/tests/instr-cov/358-exprf-aspects/src/test_aspect.adb diff --git a/testsuite/tests/358-exprf-aspects/test.py b/testsuite/tests/instr-cov/358-exprf-aspects/test.py similarity index 100% rename from testsuite/tests/358-exprf-aspects/test.py rename to testsuite/tests/instr-cov/358-exprf-aspects/test.py From 2639a54ac698d7049250897223c47cf8ec07c365 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Mon, 25 Nov 2024 12:44:59 +0100 Subject: [PATCH 1023/1483] Add gexpr coverage level --- tools/gnatcov/annotations-sarif.adb | 9 ++ tools/gnatcov/annotations.adb | 8 ++ tools/gnatcov/checkpoints.adb | 7 +- tools/gnatcov/checkpoints.ads | 3 +- tools/gnatcov/coverage-source.adb | 37 +++++++- tools/gnatcov/coverage.adb | 3 + tools/gnatcov/coverage.ads | 3 +- tools/gnatcov/coverage_options.adb | 24 ++++- tools/gnatcov/coverage_options.ads | 31 ++++--- tools/gnatcov/files_table.ads | 13 +-- tools/gnatcov/instrument-ada_unit.adb | 122 +++++++++++++++++++++++--- tools/gnatcov/sc_obligations.adb | 54 +++++++++++- tools/gnatcov/sc_obligations.ads | 15 +++- 13 files changed, 286 insertions(+), 43 deletions(-) diff --git a/tools/gnatcov/annotations-sarif.adb b/tools/gnatcov/annotations-sarif.adb index 6fd0a7fa1..db4ea1a78 100644 --- a/tools/gnatcov/annotations-sarif.adb +++ b/tools/gnatcov/annotations-sarif.adb @@ -203,6 +203,15 @@ package body Annotations.Sarif is & "gnatcov/cov_source.html#function-and-call-coverage-fun-call-" & "analysis-experimental", Config => +"error"), + Source_Coverage_Level'Pos (GExpr) => + (Id => +GExpr'Image, + Name => +"Guarded Expression coverage", + Short_Descr => + (+"The expression belongs to a conditional expression structure" + & " and was executed at least once"), + Help_Uri => +Doc_Link + & "gnatcov/cov_source.html#foobar", -- FIXME(dprn): valid URL + Config => +"error"), Undet_Rule => (Id => +"UNDET", Name => +"Undetermined Coverage", diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 2ca889720..7f761ba4f 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -388,6 +388,11 @@ package body Annotations is Pretty_Print_Call (Pp, SCO, SCO_State); end if; + when Guarded_Expr => + if Coverage.Enabled (GExpr) then + SCO_State := Get_Line_State (SCO, GExpr); + Pretty_Print_Statement (Pp, SCO, SCO_State); + end if; end case; end if; end loop; @@ -1245,6 +1250,9 @@ package body Annotations is when Fun_Call_SCO_Kind => return Coverage_Level'Pos (Fun_Call); + when Guarded_Expr => + return Coverage_Level'Pos (GExpr); + when others => return Other_Errors; end case; diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index 1a175217a..a29aead9a 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -503,7 +503,7 @@ package body Checkpoints is Supported_Levels (MCDC_Coverage_Level'Range) := (others => True); Supported_Levels (Decision) := True; end if; - for Level in Insn .. Fun_Call loop + for Level in Insn .. GExpr loop CSS.Write (Supported_Levels (Level)); end loop; @@ -641,7 +641,7 @@ package body Checkpoints is -- reading code. declare - CP_Levels : U8_Array (1 .. 9); + CP_Levels : U8_Array (1 .. 10); Levels : Levels_Type; begin CLS.Read (CP_Levels); @@ -654,7 +654,8 @@ package body Checkpoints is UC_MCDC => Boolean'Val (CP_Levels (6)), ATC => Boolean'Val (CP_Levels (7)), ATCC => Boolean'Val (CP_Levels (8)), - Fun_Call => Boolean'Val (CP_Levels (9))); + Fun_Call => Boolean'Val (CP_Levels (9)), + GExpr => Boolean'Val (CP_Levels (10))); declare Error_Msg : constant String := Coverage.Is_Load_Allowed (Filename, Levels); diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 55ddf4f3e..294eba7f0 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -39,7 +39,7 @@ with Traces_Source; use Traces_Source; package Checkpoints is - subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 16; + subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 17; -- For compatibility with previous Gnatcov versions, the checkpoint -- file format is versioned. -- @@ -60,6 +60,7 @@ package Checkpoints is -- 14 -- Extend CU_Info to implement block coverage -- 15 -- Increase size of Pragma_Id after addition of 255th pragma -- 16 -- Extend Scope_Entity to include the Start/End_Sloc of the scope + -- 17 -- Add support for Fun_Call and Guarded Expression coverage -- -- Note that we always use the last version when creating a checkpoint. -- diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index f04f0908a..78463f30f 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -129,7 +129,11 @@ package body Coverage.Source is when Fun_Call_SCO_Kind => Fun_Call_Executed : Boolean := False; - -- Set to True id this call or function was executed at least once + -- 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; @@ -1179,6 +1183,24 @@ package body Coverage.Source is SCO_State := SCI.State (Fun_Call); Update_Line_State (Line_Info, SCO, SCI.Tag, Fun_Call, SCO_State); + elsif Kind (SCO) = Guarded_Expr + and then Enabled (GExpr) + then + if SCI.GExpr_Executed then + SCO_State := Covered; + else + SCO_State := Not_Covered; + + -- Report a violation on the first line of the SCO to + -- avoid duplicating violations in the report. + + 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, GExpr, SCO_State); end if; end loop; end SCOs_Of_Line; @@ -2142,6 +2164,8 @@ package body Coverage.Source is SCI.Executed := True; elsif SCI.Kind in Fun_Call_SCO_Kind then SCI.Fun_Call_Executed := True; + elsif SCI.Kind = Guarded_Expr then + SCI.GExpr_Executed := True; end if; end Set_Executed; @@ -2596,7 +2620,7 @@ package body Coverage.Source is -- Skip bits corresponding to fun_call obligations - if Kind (Stmt_Bit_Map (Bit)) in Fun_Call_SCO_Kind then + if Kind (Stmt_Bit_Map (Bit)) /= Statement then goto Continue; end if; @@ -2707,7 +2731,7 @@ package body Coverage.Source is CP_SCI.Tag := SC_Tag (CLS.Read_I32); declare - States : array (1 .. 9) of Line_State; + States : array (1 .. 10) of Line_State; begin for I in States'Range loop States (I) := CLS.Read_Line_State; @@ -2721,6 +2745,7 @@ package body Coverage.Source is CP_SCI.State (ATC) := States (7); CP_SCI.State (ATCC) := States (8); CP_SCI.State (Fun_Call) := States (9); + CP_SCI.State (GExpr) := States (10); end; case CP_SCI.Kind is @@ -2740,6 +2765,9 @@ package body Coverage.Source is when Fun_Call_SCO_Kind => CP_SCI.Fun_Call_Executed := CLS.Read_Boolean; + when Guarded_Expr => + CP_SCI.GExpr_Executed := CLS.Read_Boolean; + when others => null; end case; @@ -2783,6 +2811,9 @@ package body Coverage.Source is when Fun_Call_SCO_Kind => CSS.Write (Value.Fun_Call_Executed); + when Guarded_Expr => + CSS.Write (Value.GExpr_Executed); + when others => null; end case; diff --git a/tools/gnatcov/coverage.adb b/tools/gnatcov/coverage.adb index c3240719e..d28ffaacf 100644 --- a/tools/gnatcov/coverage.adb +++ b/tools/gnatcov/coverage.adb @@ -226,6 +226,9 @@ package body Coverage is if Enabled (Fun_Call) then Res.Include (Fun_Call); end if; + if Enabled (GExpr) then + Res.Include (GExpr); + end if; end if; return Res; end Source_Levels_Enabled; diff --git a/tools/gnatcov/coverage.ads b/tools/gnatcov/coverage.ads index 4a179279a..ec0f37420 100644 --- a/tools/gnatcov/coverage.ads +++ b/tools/gnatcov/coverage.ads @@ -43,7 +43,8 @@ package Coverage is when UC_MCDC => "UC_MCDC", when ATC => "ATC", when ATCC => "ATCC", - when Fun_Call => "Function and call"); + when Fun_Call => "Function and call", + when GExpr => "Guarded expression"); -- Case sensitive version of Coverage_Level'Image procedure Set_Coverage_Levels (Opt : String); diff --git a/tools/gnatcov/coverage_options.adb b/tools/gnatcov/coverage_options.adb index b95939c63..8a3f34996 100644 --- a/tools/gnatcov/coverage_options.adb +++ b/tools/gnatcov/coverage_options.adb @@ -133,7 +133,8 @@ package body Coverage_Options is & "+" & Level_Str (UC_MCDC) & ")?" & "(+" & Level_Str (ATC) & "|" & "+" & Level_Str (ATCC) & ")?" - & "(+" & Level_Str (Fun_Call) & ")?"; + & "(+" & Level_Str (Fun_Call) & ")?" + & "(+" & Level_Str (GExpr) & ")?"; end Source_Level_Options; ------------------------------------- @@ -149,6 +150,10 @@ package body Coverage_Options is -- Register the coverage level Combinaison combined with function and -- call coverage. + procedure Add_GExpr_Coverage_Level (Combinaison : Levels_Type); + -- Register the coverage level Combinaison combined with guarded + -- expression coverage. + --------------------------------- -- Add_Fun_Call_Coverage_Level -- --------------------------------- @@ -187,6 +192,21 @@ package body Coverage_Options is end loop; end Add_Assert_Coverage_Levels; + ------------------------------ + -- Add_GExpr_Coverage_Level -- + ------------------------------ + + procedure Add_GExpr_Coverage_Level (Combinaison : Levels_Type) is + Comb : Levels_Type := Combinaison; + begin + -- Activate GExpr to combine it with the levels in Comb + Comb (GExpr) := True; + + Add_Source_Level_Option (Comb); + Add_Fun_Call_Coverage_Level (Comb); + Add_Assert_Coverage_Levels (Comb); + end Add_GExpr_Coverage_Level; + Decision_Levels : constant array (1 .. 3) of Coverage_Level := (Decision, MCDC, UC_MCDC); @@ -199,6 +219,7 @@ package body Coverage_Options is Add_Source_Level_Option (Combinaison); Add_Fun_Call_Coverage_Level (Combinaison); Add_Assert_Coverage_Levels (Combinaison); + Add_GExpr_Coverage_Level (Combinaison); -- Do the same for all other regular source coverage options @@ -210,6 +231,7 @@ package body Coverage_Options is Add_Source_Level_Option (Combinaison); Add_Fun_Call_Coverage_Level (Combinaison); Add_Assert_Coverage_Levels (Combinaison); + Add_GExpr_Coverage_Level (Combinaison); -- Deactivate Lvl to combine the next level with "stmt" Combinaison (Lvl) := False; diff --git a/tools/gnatcov/coverage_options.ads b/tools/gnatcov/coverage_options.ads index 9c712dbb6..6e2f858f0 100644 --- a/tools/gnatcov/coverage_options.ads +++ b/tools/gnatcov/coverage_options.ads @@ -28,19 +28,21 @@ package Coverage_Options is use all type Unbounded_String; type Coverage_Level is - (Insn, Branch, Stmt, Decision, MCDC, UC_MCDC, ATC, ATCC, Fun_Call); + (Insn, Branch, Stmt, Decision, MCDC, UC_MCDC, ATC, ATCC, Fun_Call, + GExpr); -- Coverage objectives supported by xcov. The following values are -- supported: - -- * object coverage at instruction level (Insn); - -- * object coverage at branch level (Branch); - -- * source coverage at statement level (Stmt); - -- * source coverage at decision level (Decision); - -- * source coverage at masking MC/DC level (MCDC); - -- * source coverage at unique cause MC/DC level (UC_MCDC); - -- * source coverage at ATC level (ATC); - -- * source coverage at ATCC level (ATCC). - -- * source coverage at Call level (Fun_Call) + -- * object coverage at instruction level (Insn); + -- * object coverage at branch level (Branch); + -- * source coverage at statement level (Stmt); + -- * source coverage at decision level (Decision); + -- * source coverage at masking MC/DC level (MCDC); + -- * source coverage at unique cause MC/DC level (UC_MCDC); + -- * source coverage at ATC level (ATC); + -- * source coverage at ATCC level (ATCC); + -- * source coverage at Call level (Fun_Call); + -- * source coverage at Guarded Expressions level (GExpr). -- The terms "instruction", "branch", "statement", "decision" and "MCDC" -- should be understood here as they are defined in the DO-178B standard; @@ -63,9 +65,16 @@ package Coverage_Options is -- -- * Call coverage : a call is covered if it was executed as least -- once. + -- + -- The "GExpr" coverage criteria (short for Guarded Expressions) serves the + -- purpose of tracking the exhaustive execution of all branches of + -- conditional expressions (case-expr and if-expr) and to ensure the + -- execution the dependent expression of quantified expressions + -- (for some and for all), which may not run if executed against an empty + -- array. subtype Object_Coverage_Level is Coverage_Level range Insn .. Branch; - subtype Source_Coverage_Level is Coverage_Level range Stmt .. Fun_Call; + subtype Source_Coverage_Level is Coverage_Level range Stmt .. GExpr; subtype MCDC_Coverage_Level is Coverage_Level range MCDC .. UC_MCDC; subtype Contract_Condition_Level is Coverage_Level range ATCC .. ATCC; diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 348c9aa3f..4c8fbb903 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -224,7 +224,7 @@ package Files_Table is -- Exec from where the address range has been extracted end record; - type Line_State_Cell is (Cell_1, Cell_2, Cell_3, Cell_4); + type Line_State_Cell is (Cell_1, Cell_2, Cell_3, Cell_4, Cell_5); Coverage_Level_To_Cell : constant array (Coverage_Level) of Line_State_Cell := @@ -236,13 +236,14 @@ package Files_Table is UC_MCDC => Cell_2, ATC => Cell_3, ATCC => Cell_3, - Fun_Call => Cell_4); + Fun_Call => Cell_4, + GExpr => Cell_5); -- For one specific execution of GNATcov, we know that -- each line needs at most only four states (insn, branch, - -- stmt(+decision|+mcdc|+uc_mcdc)?(+atc|+atcc)?(funcall)?). Thus, there is - -- no need to store the state for all coverage levels at the same time. - -- This table is thus used to convert the coverage level to the appropriate - -- state "storage cell". + -- stmt(+decision|+mcdc|+uc_mcdc)?(+atc|+atcc)?(funcall)?(+gexpr)?). + -- Thus, there is no need to store the state for all coverage levels at the + -- same time. This table is thus used to convert the coverage level to the + -- appropriate state "storage cell". type Line_States is array (Line_State_Cell) of Line_State; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 3355c1188..7571157a6 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -62,6 +62,11 @@ package body Instrument.Ada_Unit is package LAL renames Libadalang.Analysis; package LALCO renames Libadalang.Common; + subtype Decl_Expr_Supported_Versions is Any_Language_Version range + Ada_2022 .. Any_Language_Version'Last; + -- Set of versions of the Ada language that support declare + -- expressions. + function Create_Context_Instrument (N : Libadalang.Analysis.Ada_Node'Class) return Context_Handle; -- Create a context to show that gnatcov is instrumenting the given node @@ -4149,11 +4154,6 @@ package body Instrument.Ada_Unit is -- MC/DC state inserter for this expression function (unused if -- instrumenting a null procedure). - subtype Decl_Expr_Supported_Versions is Any_Language_Version range - Ada_2022 .. Any_Language_Version'Last; - -- Set of versions of the Ada language that support declare - -- expressions. - -- Start of processing for Traverse_Degenerate_Subprogram begin @@ -6088,6 +6088,10 @@ package body Instrument.Ada_Unit is -- instrument each declaration as a statement and process the nested -- expressions. + function Process_Case_Expr (N : Ada_Node'Class) return Visit_Status; + -- Helper to Libadalang's Traverse. Only operates on Case_Exprs, + -- instrument each alternative to individually track their evaluation. + function Process_Raise_Expr (N : Ada_Node'Class) return Visit_Status; -- Helper to Libadalang's Traverse. Only operates on Raise_Exprs, -- ending the current statement block if a raise expression is found. @@ -6332,6 +6336,102 @@ package body Instrument.Ada_Unit is end if; end Process_Decl_Expr; + ----------------------- + -- Process_Case_Expr -- + ----------------------- + + function Process_Case_Expr (N : Ada_Node'Class) return Visit_Status is + procedure Process_Case_Expr_Alt (Alt : Case_Expr_Alternative); + -- Instrument an alternative of a case_expr. + -- > Register a new SCO + -- > Nest the expression of the alt in a decl_expr + -- > Add a witness in the decl_expr's declare body + + procedure Process_Case_Expr_Alt (Alt : Case_Expr_Alternative) is + + procedure Insert_Witness (Alt_Expr : Expr); + + procedure Insert_Witness (Alt_Expr : Expr) is + Bit : constant Bit_Id := + Allocate_Statement_Bit (UIC.Unit_Bits, SCOs.SCO_Table.Last); + Witness_Decl_Handle : constant Node_Rewriting_Handle := + Make_Statement_Witness + (UIC => UIC, + Bit => Bit, + Flavor => Declaration, + In_Generic => UIC.In_Generic, + In_Decl_Expr => True); + Decl_Expr_Handle : constant Node_Rewriting_Handle := + Create_Paren_Expr + (Handle => UIC.Rewriting_Context, + F_Expr => Create_Decl_Expr + (Handle => UIC.Rewriting_Context, + F_Decls => Witness_Decl_Handle, + F_Expr => Detach (Alt_Expr))); + Alt_Handle : constant Node_Rewriting_Handle := + Handle (Alt); + begin + Set_Child + (Alt_Handle, + Member_Refs.Case_Expr_Alternative_F_Expr, + Decl_Expr_Handle); + end Insert_Witness; + + Alt_Expr : Expr renames Alt.F_Expr; + SR : constant Source_Location_Range := Alt.Sloc_Range; + begin + + Append_SCO + (C1 => 'g', + C2 => 'c', + From => +Start_Sloc (SR), + To => +Inclusive_End_Sloc (SR), + SFI => UIC.SFI, + Last => False); + + if UIC.Language_Version in Decl_Expr_Supported_Versions then + Insert_Witness (Alt_Expr); + else + + -- If the language version does not allow declare expressions, + -- do not instrument the expression. + + Report + (UIC => UIC, + Node => Alt, + Msg => "Guarded Expression coverage is not available" + & " before Ada2022", + Kind => Diagnostics.Warning); + UIC.Non_Instr_LL_SCOs.Include (SCO_Id (SCOs.SCO_Table.Last)); + end if; + + Process_Expression (UIC, Alt_Expr, T); + end Process_Case_Expr_Alt; + + -- start processing of Process_Case_Expr + + begin + if N.Kind = Ada_Case_Expr then + declare + Case_Node : constant Case_Expr := N.As_Case_Expr; + Alternatives : constant Case_Expr_Alternative_List := + Case_Node.F_Cases; + begin + for Alt of Alternatives loop + + -- Perform witness insertion + + Process_Case_Expr_Alt (Alt.As_Case_Expr_Alternative); + end loop; + return Over; -- Do not use `Traverse` to recurse into case-exprs + end; + elsif N.Kind = Ada_Decl_Expr then + return Over; + else + return Into; + end if; + end Process_Case_Expr; + ------------------------ -- Process_Raise_Expr -- ------------------------ @@ -6825,13 +6925,10 @@ package body Instrument.Ada_Unit is -- Here for cases that are known to not be logical operators case N.Kind is - -- CASE expression - - -- Really hard to believe this is correct given the special - -- handling for if expressions below ??? + -- CASE expression: processed in Process_Case_Expr when Ada_Case_Expr => - return Into; -- ??? + return (if Enabled (GExpr) then Over else Into); -- IF expression: processed like an if statement @@ -6927,6 +7024,8 @@ package body Instrument.Ada_Unit is Hash_Entries.Free; end Process_Decisions; + -- Start of processing for Process_Expressions + begin if N.Is_Null then return; @@ -6958,6 +7057,9 @@ package body Instrument.Ada_Unit is N.Traverse (Process_Decl_Expr'Access); N.Traverse (Process_Raise_Expr'Access); + if Enabled (GExpr) then + N.Traverse (Process_Case_Expr'Access); + end if; end Process_Expression; ------------------ diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 080d89c25..c503f35a8 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -478,6 +478,9 @@ package body SC_Obligations is Fun_Call_Instrumented : Boolean := True; -- Whether this function or call SCO was instrumented + + when Guarded_Expr => + GExpr_Instrumented : Boolean := True; end case; end case; end record; @@ -1277,6 +1280,9 @@ package body SC_Obligations is when Fun_Call_SCO_Kind => SCOD.Is_Expr := CLS.Read_Boolean; SCOD.Fun_Call_Instrumented := CLS.Read_Boolean; + + when Guarded_Expr => + SCOD.GExpr_Instrumented := CLS.Read_Boolean; end case; Element := SCOD; @@ -1362,6 +1368,11 @@ package body SC_Obligations is SCOD.Fun_Call_Instrumented := True; end if; + when Guarded_Expr => + if Old_SCOD.GExpr_Instrumented then + SCOD.GExpr_Instrumented := True; + end if; + when others => null; end case; @@ -1636,7 +1647,7 @@ package body SC_Obligations is New_SCOD.PC_Set.Clear; - when Fun_Call_SCO_Kind => + when Fun_Call_SCO_Kind | Guarded_Expr => null; end case; @@ -1763,7 +1774,9 @@ package body SC_Obligations is declare SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); begin - if SCOD.Kind in Statement | Decision | Fun_Call_SCO_Kind then + if SCOD.Kind in + Statement | Decision | Fun_Call_SCO_Kind | Guarded_Expr + then Add_SCO_To_Lines (SCO, SCOD); end if; end; @@ -2071,6 +2084,9 @@ package body SC_Obligations is when Fun_Call_SCO_Kind => CSS.Write (Value.Is_Expr); CSS.Write (Value.Fun_Call_Instrumented); + + when Guarded_Expr => + CSS.Write (Value.GExpr_Instrumented); end case; end Write; @@ -2914,6 +2930,16 @@ package body SC_Obligations is SCOD.Fun_Call_Instrumented := False; end Set_Fun_Call_SCO_Non_Instr; + ----------------------------- + -- Set_GExpr_SCO_Non_Instr -- + ----------------------------- + + procedure Set_GExpr_SCO_Non_Instr (SCO : SCO_Id) is + SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); + begin + SCOD.GExpr_Instrumented := False; + end Set_GExpr_SCO_Non_Instr; + --------------------------- -- Stmt_SCO_Instrumented -- --------------------------- @@ -2943,6 +2969,13 @@ package body SC_Obligations is function Fun_Call_SCO_Instrumented (SCO : SCO_Id) return Boolean is (SCO_Vector (SCO).Fun_Call_Instrumented); + ---------------------------- + -- GExpr_SCO_Instrumented -- + ---------------------------- + + function GExpr_SCO_Instrumented (SCO : SCO_Id) return Boolean is + (SCO_Vector (SCO).GExpr_Instrumented); + ----------- -- Image -- ----------- @@ -4050,7 +4083,7 @@ package body SC_Obligations is end case; end if; - when 'S' | 's' | 'C' | 'c' => + when 'S' | 's' | 'C' | 'c' | 'g' => pragma Assert (State.Current_Decision = No_SCO_Id); if SCOE.C1 = 'c' then @@ -4072,6 +4105,13 @@ package body SC_Obligations is Is_Expr => SCOE.C2 = 'E', others => <>)); end if; + elsif SCOE.C1 = 'g' then -- Guarded expression + New_SCO := Add_SCO + (SCO_Descriptor' + (Kind => Guarded_Expr, + Origin => CU, + Sloc_Range => SCO_Range, + others => <>)); else New_SCO := Add_SCO (SCO_Descriptor' @@ -4353,7 +4393,9 @@ package body SC_Obligations is when Fun => True, when Call => - L.Is_Expr = R.Is_Expr + L.Is_Expr = R.Is_Expr, + when Guarded_Expr => + True ); end Equivalent; @@ -4439,6 +4481,10 @@ package body SC_Obligations is SCOD.Parent := Enclosing_SCO; Add_SCO_To_Lines (SCO, SCOD); + when Guarded_Expr => + SCOD.Parent := Enclosing_SCO; + Add_SCO_To_Lines (SCO, SCOD); + end case; declare diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 0209d4805..b5065ec75 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -406,8 +406,9 @@ package SC_Obligations is Identifier => No_Scope_Entity_Identifier); type Any_SCO_Kind is - (Removed, Statement, Decision, Condition, Operator, Fun, Call); - subtype SCO_Kind is Any_SCO_Kind range Statement .. Call; + (Removed, Statement, Decision, Condition, Operator, Fun, Call, + Guarded_Expr); + subtype SCO_Kind is Any_SCO_Kind range Statement .. Guarded_Expr; -- Removed is used for SCOs coming from C code in static inline functions -- present in headers. These SCOs can appear duplicated in multiple -- compilation units and we replace all but one of the duplicated entries @@ -651,7 +652,11 @@ package SC_Obligations is procedure Set_Fun_Call_SCO_Non_Instr (SCO : SCO_Id) with Pre => Kind (SCO) in Fun_Call_SCO_Kind; - -- FIXME + -- Mark SCO as non instrumented for the Fun_Call coverage level + + procedure Set_GExpr_SCO_Non_Instr (SCO : SCO_Id) with + Pre => Kind (SCO) = Guarded_Expr; + -- Mark SCO as non instrumented for the GExpr coverage level function Stmt_SCO_Instrumented (SCO : SCO_Id) return Boolean with Pre => Kind (SCO) = Statement; @@ -670,6 +675,10 @@ package SC_Obligations is Pre => Kind (SCO) in Fun_Call_SCO_Kind; -- Whether this function or call SCO was instrumented + function GExpr_SCO_Instrumented (SCO : SCO_Id) return Boolean with + Pre => Kind (SCO) = Guarded_Expr; + -- Whether this Guarded Expression SCO was instrumented + function Is_Pragma_Pre_Post_Condition (SCO : SCO_Id) return Boolean; -- True if SCO is for a pragma Pre/Postcondition From f93b0d3534900c8bbcef320a50202228b1e00666 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 8 Nov 2024 12:45:03 +0100 Subject: [PATCH 1024/1483] test(gexpr): Add tests for case-expressions --- testsuite/.gitignore | 1 + testsuite/SCOV/internals/cnotes.py | 14 +++- testsuite/SCOV/internals/driver.py | 67 ++++++++++--------- testsuite/SCOV/internals/rnexpanders.py | 10 +++ testsuite/SCOV/internals/xnexpanders.py | 4 ++ testsuite/SCOV/internals/xnotep.py | 4 ++ testsuite/SCOV/tc.py | 8 ++- testsuite/SUITE/cutils.py | 33 +++++++++ .../decision/case-expr-in-if-cond/src/pkg.adb | 15 +++++ .../decision/case-expr-in-if-cond/src/pkg.ads | 5 ++ .../case-expr-in-if-cond/src/test_false.adb | 15 +++++ .../case-expr-in-if-cond/src/test_full.adb | 14 ++++ .../case-expr-in-if-cond/src/test_true.adb | 15 +++++ .../decision/case-expr-in-if-cond/test.py | 10 +++ .../case-expr-in-if-expr/src/life.adb | 14 ++++ .../case-expr-in-if-expr/src/life.ads | 5 ++ .../src/test_all_enum_true_false.adb | 14 ++++ .../case-expr-in-if-expr/src/test_full.adb | 17 +++++ .../src/test_if_false_case_full.adb | 15 +++++ .../src/test_if_false_case_part.adb | 12 ++++ .../case-expr-in-if-expr/src/test_if_true.adb | 13 ++++ .../decision/case-expr-in-if-expr/test.py | 10 +++ .../decision/if-expr-in-case-expr/src/pkg.adb | 11 +++ .../decision/if-expr-in-case-expr/src/pkg.ads | 3 + .../src/test_false_full.adb | 12 ++++ .../if-expr-in-case-expr/src/test_full.adb | 16 +++++ .../src/test_true_full.adb | 11 +++ .../src/test_true_part.adb | 13 ++++ .../decision/if-expr-in-case-expr/test.py | 10 +++ .../tests/instr-cov/guarded-exprs/extra.opt | 3 + .../mcdc/if-expr-in-case-expr/src/pkg.adb | 18 +++++ .../mcdc/if-expr-in-case-expr/src/pkg.ads | 5 ++ .../if-expr-in-case-expr/src/test_full.adb | 21 ++++++ .../src/test_mcdc_not_covered.adb | 20 ++++++ .../mcdc/if-expr-in-case-expr/test.py | 10 +++ .../stmt/case-expr-in-decl-expr/src/life.adb | 16 +++++ .../stmt/case-expr-in-decl-expr/src/life.ads | 5 ++ .../case-expr-in-decl-expr/src/test_full.adb | 22 ++++++ .../case-expr-in-decl-expr/src/test_none.adb | 20 ++++++ .../case-expr-in-decl-expr/src/test_part.adb | 13 ++++ .../stmt/case-expr-in-decl-expr/test.py | 10 +++ .../stmt/minimal-in-decl/src/animal.adb | 13 ++++ .../stmt/minimal-in-decl/src/animal.ads | 5 ++ .../stmt/minimal-in-decl/src/test_full.adb | 15 +++++ .../stmt/minimal-in-decl/src/test_none.adb | 15 +++++ .../stmt/minimal-in-decl/src/test_part.adb | 13 ++++ .../stmt/minimal-in-decl/test.py | 10 +++ .../stmt/minimal-in-stmt/src/animal.adb | 12 ++++ .../stmt/minimal-in-stmt/src/animal.ads | 5 ++ .../stmt/minimal-in-stmt/src/test_full.adb | 15 +++++ .../stmt/minimal-in-stmt/src/test_none.adb | 14 ++++ .../stmt/minimal-in-stmt/src/test_part.adb | 13 ++++ .../stmt/minimal-in-stmt/test.py | 10 +++ .../stmt/nested-case-exprs/src/life.adb | 18 +++++ .../stmt/nested-case-exprs/src/life.ads | 16 +++++ .../stmt/nested-case-exprs/src/test_full.adb | 26 +++++++ .../stmt/nested-case-exprs/src/test_none.adb | 20 ++++++ .../src/test_partial_leaf.adb | 23 +++++++ .../src/test_partial_root.adb | 20 ++++++ .../stmt/nested-case-exprs/test.py | 10 +++ 60 files changed, 791 insertions(+), 36 deletions(-) create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_false.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_true.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/test.py create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.ads create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_all_enum_true_false.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_part.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_true.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/test.py create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_false_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_part.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/test.py create mode 100644 testsuite/tests/instr-cov/guarded-exprs/extra.opt create mode 100644 testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_mcdc_not_covered.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/test.py create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.ads create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_none.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_part.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/test.py create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.ads create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_none.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_part.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/test.py create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.ads create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_none.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_part.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/test.py create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.ads create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_none.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_leaf.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_root.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/test.py diff --git a/testsuite/.gitignore b/testsuite/.gitignore index 5f8c3ed1b..76bf9fdee 100644 --- a/testsuite/.gitignore +++ b/testsuite/.gitignore @@ -2,6 +2,7 @@ d_* datc_* datcc_* ddecision_* +g_* m_* s_* u_* diff --git a/testsuite/SCOV/internals/cnotes.py b/testsuite/SCOV/internals/cnotes.py index ec7ae1a86..81a91eabf 100644 --- a/testsuite/SCOV/internals/cnotes.py +++ b/testsuite/SCOV/internals/cnotes.py @@ -137,6 +137,9 @@ # fUndetCov : subprogram with undetermined coverage state (=report) # cUndetCov : call with undetermined coverage state (=report) +# gNoCov : guarded expression never evaluated (=report) +# gUndetCov : guarded expression with undetermined coverage state (=state) + # xBlock0 : exempted block, 0 deviations (=report) # xBlock1 : exempted block, >0 deviations (=report) # xBlock2 : exempted block, >0 undetermined coverage items (=report) @@ -222,12 +225,14 @@ cNoCov, fUndetCov, cUndetCov, + gNoCov, + gUndetCov, blockNote, xBlock0, xBlock1, xBlock2, dBlock, -) = range(60) +) = range(62) NK_image = { None: "None", @@ -287,6 +292,8 @@ cNoCov: "cNoCov", fUndetCov: "fUndetCov", cUndetCov: "cUndetCov", + gNoCov: "gNoCov", + gUndetCov: "gUndetCov", dBlock: "dBlock", } @@ -342,6 +349,9 @@ # Function and call coverage violations fNoteKinds = (fNoCov, cNoCov, fUndetCov, cUndetCov) +# Guarded expression coverage violations +gNoteKinds = (gNoCov, gUndetCov) + # Exemption regions xNoteKinds = (xBlock0, xBlock1, xBlock2) @@ -379,7 +389,7 @@ + XNoteKinds + disabledNoteKinds ) -erNoteKinds += aNoteKinds + fNoteKinds +erNoteKinds += aNoteKinds + fNoteKinds + gNoteKinds xrNoteKinds = erNoteKinds + rAntiKinds + XrAntiKinds diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 6a71bcd3b..8c9d2bf5d 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -60,6 +60,7 @@ sNoteKinds, dNoteKinds, cNoteKinds, + gNoteKinds, tNoteKinds, fNoteKinds, ) @@ -989,40 +990,35 @@ def check_expectations(self): # determine when we're running some test of a given category with a # stricter --level - strength = { - # Categories - CAT.stmt: 1, - CAT.decision: 2, - CAT.mcdc: 3, - # Context levels - "stmt": 1, - "stmt+decision": 2, - "stmt+mcdc": 3, - "stmt+uc_mcdc": 3, - "stmt+atc": 1, - "stmt+decision+atc": 2, - "stmt+decision+atcc": 2, - "stmt+mcdc+atc": 3, - "stmt+mcdc+atcc": 3, - "stmt+uc_mcdc+atc": 3, - "stmt+uc_mcdc+atcc": 3, - "stmt+fun_call": 1, - "stmt+decision+fun_call": 2, - "stmt+mcdc+fun_call": 3, - "stmt+uc_mcdc+fun_call": 3, - "stmt+atc+fun_call": 1, - "stmt+decision+atc+fun_call": 2, - "stmt+decision+atcc+fun_call": 2, - "stmt+mcdc+atc+fun_call": 3, - "stmt+mcdc+atcc+fun_call": 3, - "stmt+uc_mcdc+atc+fun_call": 3, - "stmt+uc_mcdc+atcc+fun_call": 3, - } + def level_strength(lvl): + """ + The strengh of a level is determined by its base level: + 3 for mcdc + 2 for decision + 1 for stmt + """ + if lvl == CAT.mcdc or ( + isinstance(lvl, str) + and ( + lvl.startswith("stmt+mcdc") + or lvl.startswith("stmt+uc_mcdc") + ) + ): + return 3 + elif lvl == CAT.decision or ( + isinstance(lvl, str) and lvl.startswith("stmt+decision") + ): + return 2 + elif lvl == CAT.stmt or ( + isinstance(lvl, str) and lvl.startswith("stmt") + ): + return 1 + else: + thistest.stop(FatalError("unknwon coverage level: " + lvl)) - stricter_level = ( - self.testcase.category - and strength[self.xcovlevel] > strength[self.testcase.category] - ) + stricter_level = self.testcase.category and level_strength( + self.xcovlevel + ) > level_strength(self.testcase.category) # For tests without a category, we will pick the relevant note # kinds from the strictest category possibly corresponding to the @@ -1134,6 +1130,11 @@ def check_expectations_over( if self.testcase.fun_call_lvl: tc_r_rxp_for += fNoteKinds tc_r_ern_for += fNoteKinds + + if self.testcase.gexpr_lvl: + tc_r_rxp_for += gNoteKinds + tc_r_ern_for += gNoteKinds + strans = self.report_translation_for(source) _Xchecker( report="test.rep", diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index cff0415c0..384bdbd40 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -33,6 +33,8 @@ cNoCov, fUndetCov, cUndetCov, + gNoCov, + gUndetCov, Enote, KnoteDict, erNoteKinds, @@ -689,6 +691,13 @@ def __init__(self): VIOsection(re_start="FUN_CALL COVERAGE", re_notes=fun_call_notes) ) + gexpr_notes = { + "guarded_expr not executed": gNoCov, + } + self.noteblocks.append( + VIOsection(re_start="GEXPR COVERAGE", re_notes=gexpr_notes) + ) + # Non coverable items nc_notes = { @@ -710,6 +719,7 @@ def __init__(self): "decision was not instrumented for MC/DC coverage": eUndetCov, "function was not instrumented": fUndetCov, "call was not instrumented": cUndetCov, + "guarded_expr was not instrumented": gUndetCov, } self.noteblocks.append( diff --git a/testsuite/SCOV/internals/xnexpanders.py b/testsuite/SCOV/internals/xnexpanders.py index 73f91dfe6..6959e5286 100644 --- a/testsuite/SCOV/internals/xnexpanders.py +++ b/testsuite/SCOV/internals/xnexpanders.py @@ -1255,6 +1255,10 @@ def make_new_lvl_combinaison(lvl): level_from_char.update(fun_call_level_from_char) + gexpr_level_from_char = {"g": make_new_lvl_combinaison("gexpr")} + + level_from_char.update(gexpr_level_from_char) + result = text.split("=>") if len(result) == 1: diff --git a/testsuite/SCOV/internals/xnotep.py b/testsuite/SCOV/internals/xnotep.py index 9a90c291e..3b61165f4 100644 --- a/testsuite/SCOV/internals/xnotep.py +++ b/testsuite/SCOV/internals/xnotep.py @@ -72,6 +72,8 @@ cNoCov, fUndetCov, cUndetCov, + gNoCov, + gUndetCov, dBlock, ) from .segments import Line, Section, Segment @@ -273,6 +275,8 @@ class XnoteP: "c-": cNoCov, "f?": fUndetCov, "c?": cUndetCov, + "g-": gNoCov, + "g?": gUndetCov, "x0": xBlock0, "x+": xBlock1, "x?": xBlock2, diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index 2df42b0b2..063d15723 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -138,6 +138,7 @@ def __init__( tolerate_messages=None, assert_lvl=None, fun_call_lvl=False, + gexpr_lvl=False, ): # By default, these test cases expect no error from subprocesses (xrun, # xcov, etc.) @@ -190,6 +191,7 @@ def __init__( self.assert_lvl = assert_lvl self.fun_call_lvl = fun_call_lvl + self.gexpr_lvl = gexpr_lvl # - extra compilation arguments, added to what --cargs was provided to # the testsuite command line: @@ -230,8 +232,12 @@ def __xcovlevels(self): # Append "+fun_call" to activate function and call coverage if needed fclvl = "+fun_call" if self.fun_call_lvl else "" + # Append "+gexpr" to activate guarded expression coverage if needed + glvl = "+gexpr" if self.gexpr_lvl else "" + return [ - d + alvl + fclvl for d in default_xcovlevels_for[self.category] + d + alvl + fclvl + glvl + for d in default_xcovlevels_for[self.category] ] def __register_qde_for(self, drvo): diff --git a/testsuite/SUITE/cutils.py b/testsuite/SUITE/cutils.py index b62239047..fcec46423 100644 --- a/testsuite/SUITE/cutils.py +++ b/testsuite/SUITE/cutils.py @@ -273,6 +273,39 @@ def exit_if(t, comment): exit(1) +def multi_range(*args, minus=None): + """ + Utility function for easily creating sets of numbers from inclusive ranges + or simple numbers. + This function takes any number of arguments, which must either be + integers or integer 2-tuple. + The returned value is a set that contains all single numbers and all the + *INCLUSIVE* ranges + + The named parameter `minus` is a list that follows the same principle, but + its result is removed from the result of the function. + + Example: `multi_range((1,3), 6, (10, 13)) == {1, 2, 3, 6, 10, 11, 12, 13}` + """ + result = set() + for arg in args: + if type(arg) is int: + result |= {arg} + else: + (start, end) = arg + result |= set(range(start, end + 1)) + + minus = minus or [] + for arg in minus: + if type(arg) is int: + result ^= {arg} + else: + (start, end) = arg + result ^= set(range(start, end + 1)) + + return result + + class Identifier: def __init__(self, name): self.name = name diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.adb new file mode 100644 index 000000000..a23fbbfc7 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.adb @@ -0,0 +1,15 @@ +pragma Ada_2022; + +package body Pkg is + function Foo(A : Animal) return String is + begin + if -- # if + (case A is -- # case + when Dog | Cat => True, -- # when_dog_cat + when Cow => False) then -- # when_cow + return "pet"; -- # return_pet + else + return "cattle"; -- # return_cattle + end if; + end Foo; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.ads b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.ads new file mode 100644 index 000000000..c8fd54e02 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + type Animal is (Dog, Cat, Cow); + + function Foo(A : Animal) return String; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_false.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_false.adb new file mode 100644 index 000000000..60fad0146 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_false.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_False is +begin + Put_Line (Foo (Cow)); +end Test_False; + +--# pkg.adb +-- /if/ l+ ## 0 +-- /case/ l! ## dT- +-- /when_dog_cat/ l! ## g- +-- /when_cow/ l! ## 0 +-- /return_pet/ l- ## s- +-- /return_cattle/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_full.adb new file mode 100644 index 000000000..bb260f8ba --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_full.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_Full is +begin + Put_Line (Foo (Dog)); + Put_Line (Foo (Cow)); +end Test_Full; + +--# pkg.adb +-- /if/ l+ ## 0 +-- /case/ l+ ## 0 +-- /when/ l+ ## 0 +-- /return/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_true.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_true.adb new file mode 100644 index 000000000..d38e3d3c0 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/src/test_true.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_True is +begin + Put_Line (Foo (Cat)); +end Test_True; + +--# pkg.adb +-- /if/ l+ ## 0 +-- /case/ l! ## dF- +-- /when_dog_cat/ l! ## 0 +-- /when_cow/ l! ## g- +-- /return_pet/ l+ ## 0 +-- /return_cattle/ l- ## s- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/test.py b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/test.py new file mode 100644 index 000000000..61ce1aba0 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-cond/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure decision coverage is not affected by case-expression +in if conditions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.adb new file mode 100644 index 000000000..12896ad8e --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.adb @@ -0,0 +1,14 @@ +pragma Ada_2022; + +package body Life is + function Scream(A : Animal; Silent : Boolean) return String is + begin + return -- # return + (if not Silent then -- # if_cond + (case A is -- # case + when Dog => "Woof", -- # dog + when Cat => "Meow", -- # cat + when Cow => "Mooo") -- # cow + else "...."); -- # else + end Scream; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.ads b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.ads new file mode 100644 index 000000000..123280c17 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/life.ads @@ -0,0 +1,5 @@ +package Life is + type Animal is (Dog, Cat, Cow); + + function Scream(A : Animal; Silent : Boolean) return String; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_all_enum_true_false.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_all_enum_true_false.adb new file mode 100644 index 000000000..fa2ad84a2 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_all_enum_true_false.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_All_Enum_True_False is +begin + Put_Line (Scream (Dog, True)); + Put_Line (Scream (Cat, False)); + Put_Line (Scream (Cow, False)); +end Test_All_Enum_True_False; + +--# life.adb +-- /dog/ l! ## g- +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_full.adb new file mode 100644 index 000000000..90476354a --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_full.adb @@ -0,0 +1,17 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Full is +begin + Put_Line (Scream (Dog, True)); + Put_Line (Scream (Cat, True)); + Put_Line (Scream (Cow, True)); + Put_Line (Scream (Dog, False)); + Put_Line (Scream (Cat, False)); + Put_Line (Scream (Cow, False)); +end Test_Full; + +--# life.adb +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_full.adb new file mode 100644 index 000000000..ee638c9ff --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_full.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_If_False_Case_Full is +begin + Put_Line (Scream (Dog, False)); + Put_Line (Scream (Cat, False)); + Put_Line (Scream (Cow, False)); +end Test_If_False_Case_Full; + +--# life.adb +-- /if_cond/ l! ## dF- +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_part.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_part.adb new file mode 100644 index 000000000..8ded5d0bd --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_part.adb @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_If_False_Case_Part is +begin + Put_Line (Scream (Cow, False)); +end Test_If_False_Case_Part ; + +--# life.adb +-- /if_cond/ l! ## dF- +-- /dog/ l! ## g- +-- /cat/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_true.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_true.adb new file mode 100644 index 000000000..37c35ac8a --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_true.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_If_True is +begin + Put_Line (Scream (Cow, True)); +end Test_If_True; + +--# life.adb +-- /if_cond/ l! ## dT- +-- /dog/ l! ## g- +-- /cat/ l! ## g- +-- /cow/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/test.py new file mode 100644 index 000000000..d3e676c4f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expression instrumentation is not affected +by nesting in if-expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.adb new file mode 100644 index 000000000..1dfd02e51 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.adb @@ -0,0 +1,11 @@ +pragma Ada_2022; + +package body Pkg is + function If_Expr_In_Case_Expr (A, B : Boolean) return String is + begin + return (case A is -- # ret + when True => -- # case_true + (if B then "TT" else "TF"), -- # if_true + when False => "F."); -- # case_false + end If_Expr_In_Case_Expr; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.ads b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.ads new file mode 100644 index 000000000..444a4f375 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + function If_Expr_In_Case_Expr (A, B : Boolean) return String; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_false_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_false_full.adb new file mode 100644 index 000000000..48f017e84 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_false_full.adb @@ -0,0 +1,12 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_False_Full is +begin + Put_Line (If_Expr_In_Case_Expr (False, True)); + Put_Line (If_Expr_In_Case_Expr (False, False)); +end Test_False_Full; + +--# pkg.adb +-- /case_true/ l! ## g- +-- /if_true/ l! ## d- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_full.adb new file mode 100644 index 000000000..eb6b1998e --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_full.adb @@ -0,0 +1,16 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_Full is +begin + Put_Line (If_Expr_In_Case_Expr (True, True)); + Put_Line (If_Expr_In_Case_Expr (True, False)); + Put_Line (If_Expr_In_Case_Expr (False, True)); + Put_Line (If_Expr_In_Case_Expr (False, False)); +end Test_Full; + +--# pkg.adb +-- /ret/ l+ ## 0 +-- /case_true/ l+ ## 0 +-- /if_true/ l+ ## 0 +-- /case_false/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_full.adb new file mode 100644 index 000000000..8b96031b0 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_full.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_True_Full is +begin + Put_Line (If_Expr_In_Case_Expr (True, True)); + Put_Line (If_Expr_In_Case_Expr (True, False)); +end Test_True_Full; + +--# pkg.adb +-- /case_false/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_part.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_part.adb new file mode 100644 index 000000000..8731702a3 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_part.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_True_Part is +begin + Put_Line (If_Expr_In_Case_Expr (True, True)); +end Test_True_Part; + +--# pkg.adb +-- /return/ l+ ## 0 +-- /case_true/ l+ ## 0 +-- /if_true/ l! ## dF- +-- /case_false/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/test.py new file mode 100644 index 000000000..d3e676c4f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expression instrumentation is not affected +by nesting in if-expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/extra.opt b/testsuite/tests/instr-cov/guarded-exprs/extra.opt new file mode 100644 index 000000000..38e2aab7b --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/extra.opt @@ -0,0 +1,3 @@ +5.04a1 DEAD Requires Ada 2022, unavailable 5.04a1 +7.1.2 DEAD Requires Ada 2022, unavailable in 7.1.2 +bin-traces DEAD coverage level not supported in binary traces diff --git a/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.adb b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.adb new file mode 100644 index 000000000..a619613c2 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.adb @@ -0,0 +1,18 @@ +pragma Ada_2022; + +package body Pkg is + function Foo (A : Animal; B, C : Boolean) return String is + begin + return -- # return + (case A is -- # case + when Dog => "", -- # dog + when Cat => "Meow", -- # cat + when Cow => -- # cow + (if -- # if + B and then C -- # cond + then + "Moooh" -- # true + else + "No Moo :(")); -- # false + end Foo; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.ads b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.ads new file mode 100644 index 000000000..f5e9b9eab --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + type Animal is (Dog, Cat, Cow); + + function Foo (A : Animal; B, C : Boolean) return String; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_full.adb new file mode 100644 index 000000000..4f734bd5e --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_full.adb @@ -0,0 +1,21 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_Full is +begin + Put_Line (Foo (Dog, True, True)); + Put_Line (Foo (Cat, True, True)); + Put_Line (Foo (Cow, True, True)); + Put_Line (Foo (Cow, True, False)); + Put_Line (Foo (Cow, False, False)); +end Test_Full; + +--# pkg.adb +-- /return/ l+ ## 0 +-- /case/ l+ ## 0 +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 +-- /cond/ l+ ## 0 +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_mcdc_not_covered.adb b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_mcdc_not_covered.adb new file mode 100644 index 000000000..667ded0bf --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/src/test_mcdc_not_covered.adb @@ -0,0 +1,20 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_MCDC_Not_Covered is +begin + Put_Line (Foo (Dog, True, True)); + Put_Line (Foo (Cat, True, True)); + Put_Line (Foo (Cow, True, True)); + Put_Line (Foo (Cow, False, False)); +end Test_MCDC_Not_Covered; + +--# pkg.adb +-- /return/ l+ ## 0 +-- /case/ l+ ## 0 +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 +-- /cond/ l! ## c! +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/test.py new file mode 100644 index 000000000..d3e676c4f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/mcdc/if-expr-in-case-expr/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expression instrumentation is not affected +by nesting in if-expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.adb new file mode 100644 index 000000000..0f5315804 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.adb @@ -0,0 +1,16 @@ +pragma Ada_2022; + +package body Life is + function Animal_Is_Meowing (A : Animal) return Boolean is + begin + return -- # return + (declare -- # decl + Sound: constant String := -- # sound + (case A is -- # case + when Dog => "Woof", -- # dog + when Cat => "Meow", -- # cat + when Cow => "Mooo"); -- # cow + begin -- # begin + Sound = "Meow"); -- # cmp + end Animal_Is_Meowing; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.ads new file mode 100644 index 000000000..aed61f294 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/life.ads @@ -0,0 +1,5 @@ +package Life is + type Animal is (Dog, Cat, Cow); + + function Animal_Is_Meowing (A : Animal) return Boolean; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_full.adb new file mode 100644 index 000000000..217375830 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_full.adb @@ -0,0 +1,22 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Full is +begin + Put_Line(Animal_Is_Meowing (Dog)'Image); + Put_Line(Animal_Is_Meowing (Cat)'Image); + Put_Line(Animal_Is_Meowing (Cow)'Image); +end Test_Full; + +--# life.adb +-- /return/ l+ ## 0 +-- /decl/ l+ ## 0 +-- /sound/ l+ ## 0 +-- /case/ l+ ## 0 +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 +-- /begin/ l+ ## 0 +-- /cmp/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_none.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_none.adb new file mode 100644 index 000000000..6c8d256fe --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_none.adb @@ -0,0 +1,20 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_None is +begin + null; +end Test_None; + +--# life.adb +-- /return/ l- ## s- +-- /decl/ l- ## 0 +-- /sound/ l- ## s- +-- /case/ l- ## 0 +-- /dog/ l- ## g- +-- /cat/ l- ## g- +-- /cow/ l- ## g- +-- /begin/ l- ## 0 +-- /cmp/ l- ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_part.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_part.adb new file mode 100644 index 000000000..4ea6c3b2b --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/src/test_part.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Part is +begin + Put_Line(Animal_Is_Meowing (Cat)'Image); +end Test_Part; + +--# life.adb +-- /dog/ l! ## g- +-- /cow/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/test.py new file mode 100644 index 000000000..d3e676c4f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-decl-expr/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expression instrumentation is not affected +by nesting in if-expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.adb new file mode 100644 index 000000000..4b492793c --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.adb @@ -0,0 +1,13 @@ +pragma Ada_2022; + +package body Animal is + function Scream (A : Animal) return String is + Sound : constant String := -- # decl + (case A is -- # case_root + when Dog => "Woof", -- # alt_dog + when Cat => "Meow", -- # alt_cat + when Cow => "Mooo"); -- # alt_cow + begin + return Sound; -- # return + end Scream; +end Animal; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.ads new file mode 100644 index 000000000..4a288112d --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/animal.ads @@ -0,0 +1,5 @@ +package Animal is + type Animal is (Dog, Cat, Cow); + + function Scream (A : Animal) return String; +end Animal; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_full.adb new file mode 100644 index 000000000..b98718479 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_full.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_Case_Expr_Full is +begin + Put_Line (Scream (Dog)); + Put_Line (Scream (Cat)); + Put_Line (Scream (Cow)); +end Test_Case_Expr_Full; + +--# animal.adb +-- /case_root/ l+ ## 0 +-- /alt_dog/ l+ ## 0 +-- /alt_cat/ l+ ## 0 +-- /alt_cow/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_none.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_none.adb new file mode 100644 index 000000000..3882758e2 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_none.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_Case_Expr_None is +begin + null; +end Test_Case_Expr_None; + +--# animal.adb +-- /decl/ l- ## s- +-- /return/ l- ## s- +-- /case_root/ l- ## 0 +-- /alt_dog/ l- ## g- +-- /alt_cat/ l- ## g- +-- /alt_cow/ l- ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_part.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_part.adb new file mode 100644 index 000000000..8b318fbf9 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_part.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_Case_Expr_Part is +begin + Put_Line (Scream (Cat)); +end Test_Case_Expr_Part; + +--# animal.adb +-- /case_root/ l+ ## 0 +-- /alt_dog/ l! ## g- +-- /alt_cat/ l+ ## 0 +-- /alt_cow/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/test.py new file mode 100644 index 000000000..871091395 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expressions in declaration sections are +correctly instrumented. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.adb new file mode 100644 index 000000000..0235f973b --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.adb @@ -0,0 +1,12 @@ +pragma Ada_2022; + +package body Animal is + function Scream (A : Animal) return String is + begin + return -- # return + (case A is -- # case_root + when Dog => "Woof", -- # alt_dog + when Cat => "Meow", -- # alt_cat + when Cow => "Mooo"); -- # alt_cow + end Scream; +end Animal; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.ads new file mode 100644 index 000000000..4a288112d --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/animal.ads @@ -0,0 +1,5 @@ +package Animal is + type Animal is (Dog, Cat, Cow); + + function Scream (A : Animal) return String; +end Animal; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_full.adb new file mode 100644 index 000000000..b98718479 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_full.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_Case_Expr_Full is +begin + Put_Line (Scream (Dog)); + Put_Line (Scream (Cat)); + Put_Line (Scream (Cow)); +end Test_Case_Expr_Full; + +--# animal.adb +-- /case_root/ l+ ## 0 +-- /alt_dog/ l+ ## 0 +-- /alt_cat/ l+ ## 0 +-- /alt_cow/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_none.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_none.adb new file mode 100644 index 000000000..f05e7165c --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_none.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_Case_Expr_None is +begin + null; +end Test_Case_Expr_None; + +--# animal.adb +-- /return/ l- ## s- +-- /case_root/ l- ## 0 +-- /alt_dog/ l- ## g- +-- /alt_cat/ l- ## g- +-- /alt_cow/ l- ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_part.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_part.adb new file mode 100644 index 000000000..8b318fbf9 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_part.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_Case_Expr_Part is +begin + Put_Line (Scream (Cat)); +end Test_Case_Expr_Part; + +--# animal.adb +-- /case_root/ l+ ## 0 +-- /alt_dog/ l! ## g- +-- /alt_cat/ l+ ## 0 +-- /alt_cow/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/test.py new file mode 100644 index 000000000..5cef9ffd0 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expressions in assignation statements are +correctly instrumented. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.adb new file mode 100644 index 000000000..1f2d35dbe --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.adb @@ -0,0 +1,18 @@ +pragma Ada_2022; + +package body Life is + function Scream (A : Animal) return String is + begin + return -- # return + (case A.T is -- # case_animal + when Mammal => -- # when_mammal + (case A.M_Kind is -- # case_mammal + when Dog => "Woof", -- # when_dog + when Cat => "Meow", -- # when_cat + when Cow => "Mooo"), -- # when_cow + when Reptile => -- # when_reptile + (case A.R_Kind is -- # case_reptile + when Snake => "Ssss", -- # when_snake + when Turtle => "....")); -- # when_turtle + end Scream; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.ads new file mode 100644 index 000000000..3105bec63 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/life.ads @@ -0,0 +1,16 @@ +package Life is + type Mammal_Kind is (Dog, Cat, Cow); + type Reptile_Kind is (Snake, Turtle); + type Animal_Kind is (Mammal, Reptile); + + type Animal (T : Animal_Kind) is record + case T is + when Mammal => + M_Kind : Mammal_Kind; + when Reptile => + R_Kind : Reptile_Kind; + end case; + end record; + + function Scream (A : Animal) return String; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_full.adb new file mode 100644 index 000000000..47a732d23 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_full.adb @@ -0,0 +1,26 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Case_Expr_Full is + A_Dog : constant Animal := (T => Mammal, M_Kind => Dog); + A_Cat : constant Animal := (T => Mammal, M_Kind => Cat); + A_Cow : constant Animal := (T => Mammal, M_Kind => Cow); + A_Snake : constant Animal := (T => Reptile, R_Kind => Snake); + A_Turtle : constant Animal := (T => Reptile, R_Kind => Turtle); +begin + Put_Line (Scream (A_Dog)); + Put_Line (Scream (A_Cat)); + Put_Line (Scream (A_Cow)); + Put_Line (Scream (A_Snake)); + Put_Line (Scream (A_Turtle)); +end Test_Case_Expr_Full; + +--# life.adb +-- /return/ l+ ## 0 +-- /when_mammal/ l+ ## 0 +-- /when_dog/ l+ ## 0 +-- /when_cat/ l+ ## 0 +-- /when_cow/ l+ ## 0 +-- /when_reptile/ l+ ## 0 +-- /when_snake/ l+ ## 0 +-- /when_turtle/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_none.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_none.adb new file mode 100644 index 000000000..4e281f986 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_none.adb @@ -0,0 +1,20 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Case_Expr_None is +begin + null; +end Test_Case_Expr_None; + +--# life.adb +-- /return/ l- ## s- +-- /case_animal/ l- ## 0 +-- /when_mammal/ l- ## g- +-- /case_mammal/ l- ## 0 +-- /when_dog/ l- ## g- +-- /when_cat/ l- ## g- +-- /when_cow/ l- ## g- +-- /when_reptile/ l- ## g- +-- /case_reptile/ l- ## 0 +-- /when_snake/ l- ## g- +-- /when_turtle/ l- ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_leaf.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_leaf.adb new file mode 100644 index 000000000..50889f0dd --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_leaf.adb @@ -0,0 +1,23 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Case_Expr_Full is + A_Dog : constant Animal := (T => Mammal, M_Kind => Dog); + A_Cat : constant Animal := (T => Mammal, M_Kind => Cat); + A_Cow : constant Animal := (T => Mammal, M_Kind => Cow); +begin + Put_Line (Scream (A_Dog)); + Put_Line (Scream (A_Cat)); + Put_Line (Scream (A_Cow)); +end Test_Case_Expr_Full; + +--# life.adb +-- /return/ l+ ## 0 +-- /when_mammal/ l+ ## 0 +-- /when_dog/ l+ ## 0 +-- /when_cat/ l+ ## 0 +-- /when_cow/ l+ ## 0 +-- /when_reptile/ l! ## g- +-- /case_reptile/ l! ## 0 +-- /when_snake/ l! ## g- +-- /when_turtle/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_root.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_root.adb new file mode 100644 index 000000000..0e91a1601 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_root.adb @@ -0,0 +1,20 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Case_Expr_Full is + A_Dog : constant Animal := (T => Mammal, M_Kind => Dog); + A_Snake : constant Animal := (T => Reptile, R_Kind => Snake); +begin + Put_Line (Scream (A_Dog)); + Put_Line (Scream (A_Snake)); +end Test_Case_Expr_Full; + +--# life.adb +-- /return/ l+ ## 0 +-- /when_mammal/ l+ ## 0 +-- /when_dog/ l+ ## 0 +-- /when_cat/ l! ## g- +-- /when_cow/ l! ## g- +-- /when_reptile/ l+ ## 0 +-- /when_snake/ l+ ## 0 +-- /when_turtle/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/test.py new file mode 100644 index 000000000..74ff286ee --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that nested case-expressions are correctly +instrumented. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() From be10727c698082b70c504e9b02bfc33c958eab83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 27 Nov 2024 15:07:12 +0100 Subject: [PATCH 1025/1483] tests(gexpr): Adapt coverage format tests after Guarded expressions --- .../tests/207-srctrace-version/foo.c.sid | Bin 1198 -> 1192 bytes testsuite/tests/207-srctrace-version/main.sid | Bin 1432 -> 1433 bytes .../207-srctrace-version/reference.srctrace | Bin 336 -> 336 bytes .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 1508 -> 1508 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2596 -> 2612 bytes .../gen/arm-elf-linux/main_1.sid | Bin 447 -> 448 bytes .../gen/arm-elf-linux/main_2.sid | Bin 447 -> 448 bytes .../gen/arm-elf-linux/pkg.sid | Bin 1136 -> 1137 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1925 -> 1931 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1935 -> 1941 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 2159 -> 2159 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 2090 -> 2097 bytes .../gen/x86_64-windows/main_1.sid | Bin 449 -> 449 bytes .../gen/x86_64-windows/main_2.sid | Bin 449 -> 449 bytes .../gen/x86_64-windows/pkg.sid | Bin 1140 -> 1140 bytes .../update_arch_mix_windows.sh | 4 +++- 16 files changed, 3 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid index ec5d138afc8be4380cc612ba3be1d2d741dbc495..92dadde8dfd08344162c890d6850b978f6726304 100644 GIT binary patch delta 102 zcmZ3-xq?%{-On*3IloLHIU_YWyC6R^uY^I60Rk9-fMKJ2Hxm;R0Rk9-V534e6Vrc&&1;!N8O5A|;`$l+ rxvBc;iAAZ!srn`P`8matFER`B6_+F?<)rGS=OvaT=HyKN#Jmjv&5#_m diff --git a/testsuite/tests/207-srctrace-version/main.sid b/testsuite/tests/207-srctrace-version/main.sid index d63702b35a83cd389aa24b562854b1f69f0f16a8..e8241407654806f21f73d3f22be3723eedd5b466 100644 GIT binary patch delta 83 zcmbQiJ(F9(-On*3IloLHIU_YWyC6R^uY^I60Rk9-fMKJ21`}h_}m!B2HogBjI0svwr69xbP delta 82 zcmbQqJ%d}`-On*3IloLHIU_YWyC6R^uY^H>0Rk9-V533?6Jz4!P9_(o{|uAQGd%}U YJD8n;)aJj;f{Y-p04s<)Ih54}0KZii_5c6? diff --git a/testsuite/tests/207-srctrace-version/reference.srctrace b/testsuite/tests/207-srctrace-version/reference.srctrace index 210609fe5f901a06a753bb9c8399e9ca72ae3dc3..d68d2095d8930d37da2229371a5e741643153aca 100644 GIT binary patch delta 15 Wcmcb>bb)Dt1B<1;NBTw=9!3BvLbb)Dt1IyIHGie)Lco+dP1qHJJ diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index 904fd75753f3f28dfc5705bdc9b3d93305e713e9..aa940e234a18792299ef5860683d35edad4bc9e7 100644 GIT binary patch delta 335 zcmXYsu}T9$6h-eOD;e2?p&4(HzC&AeT_i>D`h@v-*%v(wgvb3hG1gC}#@WjjsVnYYgOJKetP zK{JneY?`}n&u7l(v+J|lml|{h7Oz5sH!`BX2mc^7{WJI?^sC@&=?#9xEjA(lBM)J) zl|I2(m+vGvuR=GO56C)_;z(Vo)Ef53f{oVGGJjLDU6Cm3OzwUTniCw zLI^>EMF^fCtbOeicp}_|k(?5fMk(xdYJ`4RK_>c4kD{+f;$p6TF z7;L3aFx2Hc2~I1}P3Gt1E|TI&NfP>%|Kv#+<}$ mwdEvBUh?vdPXiSd6%!K^ z6%z==#Kc4eVqysuhzjJy1Oi!ss6b3iOiXb5&i9>1j^!mw-f!Red(XMA#m5gGJt?n$ z+{Eysr*#HONO>hYR4w(7RjQs^Ti+VP0GrrW*0Y`|p2WGqx znEA&>{{e2m|5ELxpP(rD0_2}U=Xs>M)Ds%}->}akeyWRo9`>yFGwj)K&-kah_#Z%L ze?w)d|HyF0a8_C7l>=unugK^nFza0bN3efr^tSp-JzX>JaJJn3>EV2K!3FT4;W4-d z{T$5mnkvirq`I)1T^|2%e*b_NZ4`@{N^6KLK-pr>G~7{&&HgPh~L~ zpW}JA!1Uh)hb~GCJE}{*uCnMoWzqY}qHimUz60jI4#55kpX4KFaQ=JHv(WcVyaVG; zrvIVZOZ=g-)brK&lj(n?_Tqo6EdC?oPp1EOwU_yQ!93cSkGr0JP z#|oJH*-%~l_hvtq{^5QP!Mtx1)Dz%5r&^!%^9RiRIDtRs^%G3pFH-VwK3OpP50$09 ziN+Hin|QW98~?v`%`g2H<-hBvPFtTJ$K1$XKVG5V z48TD^TrfAYmpa%5H-#y_wL<=)@w1l>*adgNKH_^|u0K=$IoLx#ojaVL`sslKwpF`*U$aU(+SN=2ji^!krNf?sq^;J;kM6!&ktMze^Go2 zZbEm`kHJ2?Uvuc*KRV6_exBbVIL7(T5YOkE>lELH--mw+e+BjOcv|l;{kZK@fWM{U z^M1*n=cjsI_*W5s0_J%ficbEVDc_m$AE6(P??Epif9|Jz7tnb>vJ1wphxgY*K3;#Q z)|>0p&pveCzrM@^&ELNI-iKhmFAl-n|5x!-zawF)mow=D9?6;b)4s^aR_P{)! z1JRK`{o`sMzK`eN3hIUE$HjVL>5taa1oJ$UupfLr6)@{<@dsJmCn{f8nEDGPAF;3U z>Hc*7|JJ2Gtv42?etPJazrU8!Ux4|%bU&}ePx*VolwYr>ukvjw*7>(2ALZW$^L?Z9 pAFBEK4(9cZF>lOUN}sG`$7=tNqy9}o%=dv0=6NrG`Fmhy{SOPPdhP%K diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index 2b2c925358393250b046889deb939f20a792de77..1b7674b124bcc5520250240f4fe13422c1b2e542 100644 GIT binary patch delta 48 xcmdnbe1KWO-On*3IloLHIU_YWyC6R^uY^I60Rk9-fMKJ21S1m@0Rk9-V533=Bh!C|$yJPQ06*vp@&Et; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid index 06e6a49cc3d4dd469fe553e58313c448ae8bdd08..53e0f176644d81fea3f5d7dccef4e45e59fb0f1c 100644 GIT binary patch delta 48 xcmdnbe1KWO-On*3IloLHIU_YWyC6R^uY^I60Rk9-fMKJ21S1m@0Rk9-V533=Bh!C|$yJPQ06*vp@&Et; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid index d29e34a4fad9a10164cbdde97a0ed0a0891c3c48..d3cbf39c5a09737b8da2e123557fb52acc9e6e17 100644 GIT binary patch delta 63 zcmeys@sUHp-On*3IloLHIU_YWyC6R^uY^I60Rk9-fMKKj9400v#?5<~1Q~(! delta 62 zcmey!@qt6$-On*3IloLHIU_YWyC6R^uY^H>0Rk9-V57nuCZ_)koA)sZG6Lzz7nz+w Ilo(4i06qK>hyVZp diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt index ad078c916ca0c737b39bd1c06f3f186c85dd2e8d..c054459a6d4c56b5ce89b570e9b5c91c61ab2ef0 100644 GIT binary patch delta 757 zcmY*XK}%af5Z>8+``(L{N-&8R!9Yn7k{4eBwtYc`h|pV4g`R|l7-&$NLPAgx^wLu= zhPm{pXm7o>f1AQ3zYO~O-$ui) z6IE175sAwOhFr}d;X|s=x0}6#p;lS|&0VS&jAZb_>{qQgFUk0LJQ*A|dwXL=R(jet z6g1=;+NNmMShKN|@$B=)Zb1^)DzUfM%UiGt;7fqXWNzE>+wuXfKD$9oPd{g#zj+E!VECMf>D64h_}o# z@7PYPiLg54uH8g|=`nvYo9mjiD+G8Uj`4_Pao}zsb^(MoYzg?Esh&M;!+U$fYDG}w z_~t3kk4MC4jd4@a;+iCX#)b$l=8=6WY!s_#%`YMe1Yjs)NgP&kj}Y@ku=3j9Sz!F2 zpdvn_%8Lk9YvObJiWFbkvN1$V;UfRFl{tgIVt)Ty+t7yi%9gkh?nXcV++VBTZ}}qp bUu(6J_Pc7Db=Kc>(yUrfTb(pT7tF^8rISM& delta 724 zcmYjOyGjE=6rGvPZZ;Z?uc(ojtVmRhk##Xbf}&PpqZau9LlW?<5D|nl7FJfv1+lTP z_YeF5t6=K~*jd#SH%{fKRyn=8JifRVLqZ5C z8AAH$IPJ>?Q*lXAL#{^*j`|tH{!?Z!!a=!OUM^SbLYmZ+iG;-^aH5R*ZT-4--tLC| zW;W_Am(Pxsu(@aZ)vS#8O>dx&Gk_Jv3?0ZRnwQQRCwh)9LmusL$FmbABh>K_1jnLJ zRiIa8PiqOT;4c^$sKHwlSA`6Ahb%nM%S64+tn<7PV|)TiU_ccnb-|=fBS~LIG2apj zZ7hM?!2tL;19c4RHiJ_rDutX}?{B!Yz%Z&U15IgY9=(J{cQH(>-SC;P2dv%aAdn4w zm)&5t9>pX)FF)vCXwuSmtLV^7&$T*r?hP_<2>3AuY)r4DsWwxQ+4O8|Ac0CB64erP zXU;|-00??FQ=H+0Y5WU^Ky}PI=f%s7bJd1!3qjzG|97fPa1hEnmFK{P^wsEw9(5(dFP zU?*5uT3Fj!3F2Q6e}eP&Sd9}VGy7)d&D-T}hHi&SYnv-u_10-vKWNksPg>36j+1p9 zM@V-5!307d66zDPnk$Z^6|tI8oWV2Q`$BerllFPL(>R*0?YAAFxw%M>!q*;GJbD&I z;diHIbil`;ySKEP;lzw{tnJs*G3)_22(Z*?oOPP5w8DU?7*!AfS=Mb4IL2MNkd=bw z4BL%lj_G~U4&Z6$yR4LaK0%n(V>`hBomLilT*}J|W!1bzQ{)>;Y}7YFP?t4h;0OgC2319k?OHE`ZR6EiS#P@UnLdZ*C2%9RWqAU-kA` zdPGo5&`siAY-W(-zX=Gjf_^9Fcp}0G5KyES;sioKj+kSI<;-IQ^y!ZO-TlQK^UOkn zODX7Dmz5HNzV&Fx(eUEYSdTTv%s1%Lhn^zO8<9%Tytm_DO+0-$4-0hXy%plPG`ko^ Tm83kM#8Fs`;v|Y75@zEM4_!de delta 721 zcmY*VJxc>Y5Z&3!UOxOt)SN+ydKL#lj9h{VBq(BKrxtcrAqt9M1VtMw!XU6?wtDVz1{Y~QD^_~MCFuHq$L$a zGahfyoRO2#d`?SgN2&qIk?1KHPD|0+X)UyNjujbxp$T%M=K>|8a&;&rmq?PFAFkSX^ zBfyrh10tc100aFV^H}soo$&&kz5m+>n! zZzcTl-?2f^`T?n)4Lr%QJbp-wT|msb9bsC!{FylKPgqGIQtS?AEDg*{ zBJ%dz<0oNj8{E*@h3@a@uyipB{5SghV6NywN=BfS;yY&<2P~DrL3b5jn;O3xFD<{- z+ljx-JO{2v#5p%_Y?GJV?c~|jTX67MQ};MZLwLc`=zkj3`0B#5#u+c Cp+ge@ diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 22764270ad3cd420df47a2fa2ae34c8f7ceb383e..095198c8ada27a3cadc839e3ac642384c693c3e1 100644 GIT binary patch delta 83 zcmaDa@LpiUPi7`2#>u~#ok5fXi!(D5Bhw^Sk;$`I{(wYgu!1Bu-(_uPlz+px;dIJ6 g^OKAW3=9H5Y-FZqP_Ce1WME`sXlP_Uxt{$40O)oWk diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt index df0c66b2a15e7fc8480340dbec7acc4d16d077ea..b7419a00a61fd36b7bea9a9be40bb2dce621b8f0 100644 GIT binary patch delta 641 zcmZWmu}T9$5Z#%*yToWD!6XDM3`Eq3!l{KIMu;eOqG&53K~w@>1W9Y-4;%x6Vv$+| z6$Skb3kxl5Z0xMX#+ltLL|k|`yYt@co14AL++`+LR%@H}s8y=(@75d5=-}{JWtCE3 zAYY|Wg2#aPYb<`t0mfhRpyOx}yf_+-HwFtLGYVU0>lN+bavGTu2$P_D41K%%#F1>b z+GdCJH~`)F<$lmyAV>=68A9Lg0<3_hHVmi5QP3lx8Y}Fs1r_jEQKmL}bfgDD(;KUN zhA}k>cXI7XHJE;B!K)S#&^6!7Oo|~fPnS?MKY?`Xl}@@feayQhc?Du*d~~yI+e3F9gR!zf+j(kv>Zb-$WK=(K)j4`zJytqmhrd-R~Ih(IrXnFsjp7iXr; z_?YXwx3y?C_N>kSJipCSFhS=*Atm>N%o6E|Qy)QrPA#-%*-x;QSi5*_sOwqUPCVwO L=E6|avRwQHjvzx( delta 649 zcmY+AJxc>Y5Qca5<1VLBBIHAeBoW0JN#F?Bs3{bJT|lwaD)<>NLB!VIuo=PsV5Nol z7qrk)unK9##>z78?A?XS!ZI^^&&<5{KBXQ~h27TnLA!fXYM&jqJH77tm?D*oL!EA+^ zS8Qf6Y;jKsB5?qZFy=o*zERcx%K|wtdpG9MR#JDZY!?d|mVa%9F%W2ERp_vlPvUD47OU4*_XFxKo zC=utP@f2w^$+bpPoFGX638FYA4%B?UZk;gw6L$7G zr>3*!+hRM~8ZU8AJ1qlEE diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid index 378bcf96cedebbe85f0a7ab3113d7a647f55601c..ae0c6f89c42698969e28e2996331002aa099a962 100644 GIT binary patch delta 14 VcmX@ee2{rVB_k6P+hRM~8ZU8AJ1qlEE diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid index 104326cf333b01ca527fda7b762dd57c56fb454f..f86c33229b72dab4eb72e40bc153151678fb8253 100644 GIT binary patch delta 29 hcmeyu@r7f44V%!2{Hod$yb=2L6js*Gyt-L3atPD diff --git a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh index 4886d690d..9e2390fb7 100755 --- a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh +++ b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh @@ -1,5 +1,7 @@ # Update windows artifacts for U204-026-arch-mix +set ex + if [ $# -eq 0 ]; then echo "No arguments provided. Please provide the name of the gnatcov branch" exit 1 @@ -20,7 +22,7 @@ cd /Users/itmgr/wave anod vcs --add-repo gnatcoverage /Users/itmgr/gnatcoverage anod build gnatcov --interactive never eval $(anod printenv gnatcov) -eval $(anod printenv stable-gnatall) +eval $(anod printenv gnatall -Qstable) # Then, retrieve the sources of the arch-mix test rm -rf /Users/itmgr/gnatcoverage/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows From 85ea54359e7e777452cd9fec07ace6f8ead65a3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Thu, 28 Nov 2024 12:34:03 +0100 Subject: [PATCH 1026/1483] Rework Process_Case_Expr to prepare for if-exprs' instrumentation --- tools/gnatcov/instrument-ada_unit.adb | 123 ++++++++++++++------------ 1 file changed, 67 insertions(+), 56 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 7571157a6..a3d592701 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -30,6 +30,8 @@ with Ada.Streams.Stream_IO; with Langkit_Support; with Langkit_Support.Slocs; use Langkit_Support.Slocs; with Langkit_Support.Symbols; use Langkit_Support.Symbols; +with Langkit_Support.Generic_API.Introspection; +use Langkit_Support.Generic_API.Introspection; with Libadalang.Common; use Libadalang.Common; with Libadalang.Expr_Eval; with Libadalang.Generic_API; @@ -6088,14 +6090,26 @@ package body Instrument.Ada_Unit is -- instrument each declaration as a statement and process the nested -- expressions. - function Process_Case_Expr (N : Ada_Node'Class) return Visit_Status; - -- Helper to Libadalang's Traverse. Only operates on Case_Exprs, - -- instrument each alternative to individually track their evaluation. - function Process_Raise_Expr (N : Ada_Node'Class) return Visit_Status; -- Helper to Libadalang's Traverse. Only operates on Raise_Exprs, -- ending the current statement block if a raise expression is found. + procedure Instrument_GExpr + (E : Expr; + SR : Source_Location_Range; + Parent_Handle : Node_Rewriting_Handle; + Parent_Member_Ref : Struct_Member_Ref); + -- Instrument a guarded expression. + -- > Register a new SCO + -- > If the detected langage version is < Ada2022 + -- then it will not instrument the expression. + -- > Otherwise, nest the expression inside a decl_expr + -- and set the parent's child to this decl_expr. + + function Process_Case_Expr (N : Ada_Node'Class) return Visit_Status; + -- Helper to Libadalang's Traverse. Only operates on Case_Exprs, + -- instrument each alternative to individually track their evaluation. + procedure Process_Decisions (UIC : in out Ada_Unit_Inst_Context; N : Ada_Node'Class; @@ -6336,22 +6350,27 @@ package body Instrument.Ada_Unit is end if; end Process_Decl_Expr; - ----------------------- - -- Process_Case_Expr -- - ----------------------- - - function Process_Case_Expr (N : Ada_Node'Class) return Visit_Status is - procedure Process_Case_Expr_Alt (Alt : Case_Expr_Alternative); - -- Instrument an alternative of a case_expr. - -- > Register a new SCO - -- > Nest the expression of the alt in a decl_expr - -- > Add a witness in the decl_expr's declare body - - procedure Process_Case_Expr_Alt (Alt : Case_Expr_Alternative) is - - procedure Insert_Witness (Alt_Expr : Expr); + ---------------------- + -- Instrument_Gexpr -- + ---------------------- - procedure Insert_Witness (Alt_Expr : Expr) is + procedure Instrument_GExpr + (E : Expr; + SR : Source_Location_Range; + Parent_Handle : Node_Rewriting_Handle; + Parent_Member_Ref : Struct_Member_Ref) + is + begin + Append_SCO + (C1 => 'g', + C2 => 'c', + From => +Start_Sloc (SR), + To => +Inclusive_End_Sloc (SR), + SFI => UIC.SFI, + Last => False); + + if UIC.Language_Version in Decl_Expr_Supported_Versions then + declare Bit : constant Bit_Id := Allocate_Statement_Bit (UIC.Unit_Bits, SCOs.SCO_Table.Last); Witness_Decl_Handle : constant Node_Rewriting_Handle := @@ -6367,49 +6386,33 @@ package body Instrument.Ada_Unit is F_Expr => Create_Decl_Expr (Handle => UIC.Rewriting_Context, F_Decls => Witness_Decl_Handle, - F_Expr => Detach (Alt_Expr))); - Alt_Handle : constant Node_Rewriting_Handle := - Handle (Alt); + F_Expr => Detach (E))); begin Set_Child - (Alt_Handle, - Member_Refs.Case_Expr_Alternative_F_Expr, + (Parent_Handle, + Parent_Member_Ref, Decl_Expr_Handle); - end Insert_Witness; - - Alt_Expr : Expr renames Alt.F_Expr; - SR : constant Source_Location_Range := Alt.Sloc_Range; - begin - - Append_SCO - (C1 => 'g', - C2 => 'c', - From => +Start_Sloc (SR), - To => +Inclusive_End_Sloc (SR), - SFI => UIC.SFI, - Last => False); - - if UIC.Language_Version in Decl_Expr_Supported_Versions then - Insert_Witness (Alt_Expr); - else + end; + else - -- If the language version does not allow declare expressions, - -- do not instrument the expression. + -- If the language version does not allow declare expressions, + -- do not instrument the expression. - Report - (UIC => UIC, - Node => Alt, - Msg => "Guarded Expression coverage is not available" - & " before Ada2022", - Kind => Diagnostics.Warning); - UIC.Non_Instr_LL_SCOs.Include (SCO_Id (SCOs.SCO_Table.Last)); - end if; - - Process_Expression (UIC, Alt_Expr, T); - end Process_Case_Expr_Alt; + Report + (UIC => UIC, + Node => E, + Msg => "Guarded Expression coverage is not available" + & " before Ada2022", + Kind => Diagnostics.Warning); + UIC.Non_Instr_LL_SCOs.Include (SCO_Id (SCOs.SCO_Table.Last)); + end if; + end Instrument_GExpr; - -- start processing of Process_Case_Expr + ----------------------- + -- Process_Case_Expr -- + ----------------------- + function Process_Case_Expr (N : Ada_Node'Class) return Visit_Status is begin if N.Kind = Ada_Case_Expr then declare @@ -6421,7 +6424,15 @@ package body Instrument.Ada_Unit is -- Perform witness insertion - Process_Case_Expr_Alt (Alt.As_Case_Expr_Alternative); + Instrument_GExpr + (Alt.As_Case_Expr_Alternative.F_Expr, + Alt.Sloc_Range, + Handle (Alt), + Member_Refs.Case_Expr_Alternative_F_Expr); + Process_Expression + (UIC, + Alt.As_Case_Expr_Alternative.F_Expr, + T); end loop; return Over; -- Do not use `Traverse` to recurse into case-exprs end; From e503475ad877f0d730a795d51323a29c9a6d7a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 29 Nov 2024 12:37:06 +0100 Subject: [PATCH 1027/1483] Fix gexpr's undetermined coverage handling --- tools/gnatcov/coverage-source.adb | 9 ++++++++- tools/gnatcov/instrument-common.adb | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 78463f30f..092b3935a 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -1186,7 +1186,14 @@ package body Coverage.Source is elsif Kind (SCO) = Guarded_Expr and then Enabled (GExpr) then - if SCI.GExpr_Executed then + if not GExpr_SCO_Instrumented (SCO) then + SCO_State := Undetermined_Coverage; + Report_Coverage + (SCO, + SCI.Tag, + "was not instrumented", + Kind => Undetermined_Cov); + elsif SCI.GExpr_Executed then SCO_State := Covered; else SCO_State := Not_Covered; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 917689e96..0aba796a4 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -286,6 +286,7 @@ package body Instrument.Common is (Enclosing_Decision (Remapped_SCO)); when Fun_Call_SCO_Kind => Set_Fun_Call_SCO_Non_Instr (Remapped_SCO); + when Guarded_Expr => Set_GExpr_SCO_Non_Instr (Remapped_SCO); when others => null; end case; From 0f898736de49eca1d91de275291648b81138beff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 29 Nov 2024 12:44:08 +0100 Subject: [PATCH 1028/1483] tests(gexpr): Add test for undetermined coverage --- .../stmt/undetermined-coverage/src/animal.adb | 12 ++++++++++++ .../stmt/undetermined-coverage/src/animal.ads | 5 +++++ .../stmt/undetermined-coverage/src/test_full.adb | 15 +++++++++++++++ .../stmt/undetermined-coverage/test.py | 13 +++++++++++++ 4 files changed, 45 insertions(+) create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.ads create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/test_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/test.py diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.adb new file mode 100644 index 000000000..0fbcfbb80 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; + +package body Animal is + function Scream (A : Animal) return String is + begin + return -- # return + (case A is -- # case_root + when Dog => "Woof", -- # alt_dog + when Cat => "Meow", -- # alt_cat + when Cow => "Mooo"); -- # alt_cow + end Scream; +end Animal; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.ads new file mode 100644 index 000000000..4a288112d --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/animal.ads @@ -0,0 +1,5 @@ +package Animal is + type Animal is (Dog, Cat, Cow); + + function Scream (A : Animal) return String; +end Animal; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/test_full.adb new file mode 100644 index 000000000..2d09de4e8 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/test_full.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Animal; use Animal; + +procedure Test_Case_Expr_Full is +begin + Put_Line (Scream (Dog)); + Put_Line (Scream (Cat)); + Put_Line (Scream (Cow)); +end Test_Case_Expr_Full; + +--# animal.adb +-- /case_root/ l+ ## 0 +-- /alt_dog/ l? ## g? +-- /alt_cat/ l? ## g? +-- /alt_cow/ l? ## g? diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/test.py new file mode 100644 index 000000000..775ee0d1b --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/test.py @@ -0,0 +1,13 @@ +""" +Regression test: Check the "undetermined coverage" for guarded expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase( + gexpr_lvl=True, + tolerate_messages="warning: Guarded Expression coverage is not" + " available before Ada2022", +).run() +thistest.result() From 273ecfbd090bc9bdafa650277ac218d46ca60238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Thu, 28 Nov 2024 16:18:37 +0100 Subject: [PATCH 1029/1483] Add if-exprs support to --level=gexpr --- tools/gnatcov/instrument-ada_unit.adb | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index a3d592701..ef102f37f 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6107,8 +6107,8 @@ package body Instrument.Ada_Unit is -- and set the parent's child to this decl_expr. function Process_Case_Expr (N : Ada_Node'Class) return Visit_Status; - -- Helper to Libadalang's Traverse. Only operates on Case_Exprs, - -- instrument each alternative to individually track their evaluation. + -- Helper to Libadalang's Traverse. + -- Only operates on Case_Exprs, call Instrument_GExpr on every case procedure Process_Decisions (UIC : in out Ada_Unit_Inst_Context; @@ -6951,6 +6951,13 @@ package body Instrument.Ada_Unit is begin Process_Decisions (UIC, IEN.F_Cond_Expr, 'I'); Process_Decisions (UIC, IEN.F_Then_Expr, 'X'); + if Enabled (GExpr) then + Instrument_GExpr + (IEN.F_Then_Expr, + IEN.F_Then_Expr.Sloc_Range, + Handle (IEN), + Member_Refs.If_Expr_F_Then_Expr); + end if; for J in 1 .. Alt.Children_Count loop declare @@ -6959,10 +6966,24 @@ package body Instrument.Ada_Unit is begin Process_Decisions (UIC, EIN.F_Cond_Expr, 'I'); Process_Decisions (UIC, EIN.F_Then_Expr, 'X'); + if Enabled (GExpr) then + Instrument_GExpr + (EIN.F_Then_Expr, + EIN.F_Then_Expr.Sloc_Range, + Handle (EIN), + Member_Refs.Elsif_Expr_Part_F_Then_Expr); + end if; end; end loop; Process_Decisions (UIC, IEN.F_Else_Expr, 'X'); + if Enabled (GExpr) then + Instrument_GExpr + (IEN.F_Else_Expr, + IEN.F_Else_Expr.Sloc_Range, + Handle (IEN), + Member_Refs.If_Expr_F_Else_Expr); + end if; return Over; end; From b27ed8c6bd515632df48503d87c6d82e5bcd11b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Thu, 28 Nov 2024 16:19:32 +0100 Subject: [PATCH 1030/1483] tests(gexpr): Update gexpr tests for if-exprs --- .../src/test_if_false_case_full.adb | 1 + .../src/test_if_false_case_part.adb | 1 + .../case-expr-in-if-expr/src/test_if_true.adb | 1 + .../src/test_false_full.adb | 3 ++- .../if-expr-in-case-expr/src/test_true_part.adb | 2 +- .../stmt/case-expr-in-if-expr/src/life.adb | 14 ++++++++++++++ .../stmt/case-expr-in-if-expr/src/life.ads | 5 +++++ .../src/test_all_enum_true_false.adb | 14 ++++++++++++++ .../stmt/case-expr-in-if-expr/src/test_full.adb | 17 +++++++++++++++++ .../src/test_if_false_case_full.adb | 16 ++++++++++++++++ .../src/test_if_false_case_part.adb | 13 +++++++++++++ .../case-expr-in-if-expr/src/test_if_true.adb | 14 ++++++++++++++ .../stmt/case-expr-in-if-expr/test.py | 10 ++++++++++ .../stmt/if-expr-in-case-expr/src/pkg.adb | 11 +++++++++++ .../stmt/if-expr-in-case-expr/src/pkg.ads | 3 +++ .../src/test_false_full.adb | 13 +++++++++++++ .../stmt/if-expr-in-case-expr/src/test_full.adb | 16 ++++++++++++++++ .../if-expr-in-case-expr/src/test_true_full.adb | 11 +++++++++++ .../if-expr-in-case-expr/src/test_true_part.adb | 13 +++++++++++++ .../stmt/if-expr-in-case-expr/test.py | 10 ++++++++++ 20 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.ads create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_all_enum_true_false.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_part.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_true.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/test.py create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_false_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_full.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_part.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/test.py diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_full.adb index ee638c9ff..2146e7550 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_full.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_full.adb @@ -13,3 +13,4 @@ end Test_If_False_Case_Full; -- /dog/ l+ ## 0 -- /cat/ l+ ## 0 -- /cow/ l+ ## 0 +-- /else/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_part.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_part.adb index 8ded5d0bd..372dcbb20 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_part.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_false_case_part.adb @@ -10,3 +10,4 @@ end Test_If_False_Case_Part ; -- /if_cond/ l! ## dF- -- /dog/ l! ## g- -- /cat/ l! ## g- +-- /else/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_true.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_true.adb index 37c35ac8a..3ee3fdd73 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_true.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/case-expr-in-if-expr/src/test_if_true.adb @@ -8,6 +8,7 @@ end Test_If_True; --# life.adb -- /if_cond/ l! ## dT- +-- /case/ l! ## g- -- /dog/ l! ## g- -- /cat/ l! ## g- -- /cow/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_false_full.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_false_full.adb index 48f017e84..158d89f1e 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_false_full.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_false_full.adb @@ -9,4 +9,5 @@ end Test_False_Full; --# pkg.adb -- /case_true/ l! ## g- --- /if_true/ l! ## d- +-- /if_true/ l! ## g-,g-,d- +-- 2 gexpr violations (both branches of the unexecuted if) diff --git a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_part.adb b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_part.adb index 8731702a3..4fe928be6 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_part.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/decision/if-expr-in-case-expr/src/test_true_part.adb @@ -9,5 +9,5 @@ end Test_True_Part; --# pkg.adb -- /return/ l+ ## 0 -- /case_true/ l+ ## 0 --- /if_true/ l! ## dF- +-- /if_true/ l! ## dF-,g- -- /case_false/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.adb new file mode 100644 index 000000000..12896ad8e --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.adb @@ -0,0 +1,14 @@ +pragma Ada_2022; + +package body Life is + function Scream(A : Animal; Silent : Boolean) return String is + begin + return -- # return + (if not Silent then -- # if_cond + (case A is -- # case + when Dog => "Woof", -- # dog + when Cat => "Meow", -- # cat + when Cow => "Mooo") -- # cow + else "...."); -- # else + end Scream; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.ads new file mode 100644 index 000000000..123280c17 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/life.ads @@ -0,0 +1,5 @@ +package Life is + type Animal is (Dog, Cat, Cow); + + function Scream(A : Animal; Silent : Boolean) return String; +end Life; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_all_enum_true_false.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_all_enum_true_false.adb new file mode 100644 index 000000000..fa2ad84a2 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_all_enum_true_false.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_All_Enum_True_False is +begin + Put_Line (Scream (Dog, True)); + Put_Line (Scream (Cat, False)); + Put_Line (Scream (Cow, False)); +end Test_All_Enum_True_False; + +--# life.adb +-- /dog/ l! ## g- +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_full.adb new file mode 100644 index 000000000..90476354a --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_full.adb @@ -0,0 +1,17 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_Full is +begin + Put_Line (Scream (Dog, True)); + Put_Line (Scream (Cat, True)); + Put_Line (Scream (Cow, True)); + Put_Line (Scream (Dog, False)); + Put_Line (Scream (Cat, False)); + Put_Line (Scream (Cow, False)); +end Test_Full; + +--# life.adb +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_full.adb new file mode 100644 index 000000000..e5aed4903 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_full.adb @@ -0,0 +1,16 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_If_False_Case_Full is +begin + Put_Line (Scream (Dog, False)); + Put_Line (Scream (Cat, False)); + Put_Line (Scream (Cow, False)); +end Test_If_False_Case_Full; + +--# life.adb +-- /if_cond/ l+ ## 0 +-- /dog/ l+ ## 0 +-- /cat/ l+ ## 0 +-- /cow/ l+ ## 0 +-- /else/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_part.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_part.adb new file mode 100644 index 000000000..b44453214 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_false_case_part.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_If_False_Case_Part is +begin + Put_Line (Scream (Cow, False)); +end Test_If_False_Case_Part ; + +--# life.adb +-- /if_cond/ l+ ## 0 +-- /dog/ l! ## g- +-- /cat/ l! ## g- +-- /else/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_true.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_true.adb new file mode 100644 index 000000000..2a977b171 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/src/test_if_true.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Life; use Life; + +procedure Test_If_True is +begin + Put_Line (Scream (Cow, True)); +end Test_If_True; + +--# life.adb +-- /if_cond/ l+ ## 0 +-- /case/ l! ## g- +-- /dog/ l! ## g- +-- /cat/ l! ## g- +-- /cow/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/test.py new file mode 100644 index 000000000..d3e676c4f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/case-expr-in-if-expr/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expression instrumentation is not affected +by nesting in if-expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.adb new file mode 100644 index 000000000..1dfd02e51 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.adb @@ -0,0 +1,11 @@ +pragma Ada_2022; + +package body Pkg is + function If_Expr_In_Case_Expr (A, B : Boolean) return String is + begin + return (case A is -- # ret + when True => -- # case_true + (if B then "TT" else "TF"), -- # if_true + when False => "F."); -- # case_false + end If_Expr_In_Case_Expr; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.ads new file mode 100644 index 000000000..444a4f375 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + function If_Expr_In_Case_Expr (A, B : Boolean) return String; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_false_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_false_full.adb new file mode 100644 index 000000000..c2f8b42de --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_false_full.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_False_Full is +begin + Put_Line (If_Expr_In_Case_Expr (False, True)); + Put_Line (If_Expr_In_Case_Expr (False, False)); +end Test_False_Full; + +--# pkg.adb +-- /case_true/ l! ## g- +-- /if_true/ l! ## g-,g- +-- 2 gexpr violations (both branches of the unexecuted if) diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_full.adb new file mode 100644 index 000000000..eb6b1998e --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_full.adb @@ -0,0 +1,16 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_Full is +begin + Put_Line (If_Expr_In_Case_Expr (True, True)); + Put_Line (If_Expr_In_Case_Expr (True, False)); + Put_Line (If_Expr_In_Case_Expr (False, True)); + Put_Line (If_Expr_In_Case_Expr (False, False)); +end Test_Full; + +--# pkg.adb +-- /ret/ l+ ## 0 +-- /case_true/ l+ ## 0 +-- /if_true/ l+ ## 0 +-- /case_false/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_full.adb new file mode 100644 index 000000000..8b96031b0 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_full.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_True_Full is +begin + Put_Line (If_Expr_In_Case_Expr (True, True)); + Put_Line (If_Expr_In_Case_Expr (True, False)); +end Test_True_Full; + +--# pkg.adb +-- /case_false/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_part.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_part.adb new file mode 100644 index 000000000..508c0dfba --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/src/test_true_part.adb @@ -0,0 +1,13 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_True_Part is +begin + Put_Line (If_Expr_In_Case_Expr (True, True)); +end Test_True_Part; + +--# pkg.adb +-- /return/ l+ ## 0 +-- /case_true/ l+ ## 0 +-- /if_true/ l! ## g- +-- /case_false/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/test.py new file mode 100644 index 000000000..d3e676c4f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/if-expr-in-case-expr/test.py @@ -0,0 +1,10 @@ +""" +Regression test: Ensure that case-expression instrumentation is not affected +by nesting in if-expressions. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() From 62e793f5730af4d4d9d3f952c48dc77011dff129 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 29 Nov 2024 11:51:34 +0100 Subject: [PATCH 1031/1483] Add quantified-expr support to --level=gexpr --- tools/gnatcov/instrument-ada_unit.adb | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index ef102f37f..175a3a05f 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6991,6 +6991,14 @@ package body Instrument.Ada_Unit is Process_Decisions (UIC, N.As_Quantified_Expr.F_Loop_Spec, 'X'); Process_Decisions (UIC, N.As_Quantified_Expr.F_Expr, 'W'); + + if Enabled (GExpr) then + Instrument_GExpr + (N.As_Quantified_Expr.F_Expr, + N.As_Quantified_Expr.F_Expr.Sloc_Range, + Handle (N), + Member_Refs.Quantified_Expr_F_Expr); + end if; return Over; when Ada_For_Loop_Spec => From 0101bb1aab4cb77f92f5460294315782eda682d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 29 Nov 2024 14:59:23 +0100 Subject: [PATCH 1032/1483] tests(gexpr): Add tests for quantified expressions --- .../guarded-exprs/stmt/quantified-expr/src/pkg.adb | 8 ++++++++ .../guarded-exprs/stmt/quantified-expr/src/pkg.ads | 3 +++ .../stmt/quantified-expr/src/test_empty.adb | 11 +++++++++++ .../stmt/quantified-expr/src/test_non_empty.adb | 11 +++++++++++ .../guarded-exprs/stmt/quantified-expr/test.py | 9 +++++++++ 5 files changed, 42 insertions(+) create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_empty.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_non_empty.adb create mode 100644 testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/test.py diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.adb new file mode 100644 index 000000000..a07bcf9aa --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.adb @@ -0,0 +1,8 @@ +pragma Ada_2022; + +package body Pkg is + function Foo (A, B : Natural) return Boolean is + begin + return (for some I in A .. B => I = 10); -- # expr + end Foo; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.ads b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.ads new file mode 100644 index 000000000..8545d840f --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + function Foo (A, B : Natural) return Boolean; +end Pkg; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_empty.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_empty.adb new file mode 100644 index 000000000..5d70df138 --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_empty.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_Empty is + result : Boolean := Foo (1, 0); +begin + null; +end Test_Empty; + +--# pkg.adb +-- /expr/ l! ## g- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_non_empty.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_non_empty.adb new file mode 100644 index 000000000..0fdda2cee --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_non_empty.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pkg; use Pkg; + +procedure Test_Empty is + result : Boolean := Foo (1, 5); +begin + null; +end Test_Empty; + +--# pkg.adb +-- /expr/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/test.py b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/test.py new file mode 100644 index 000000000..84cfc812b --- /dev/null +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/test.py @@ -0,0 +1,9 @@ +""" +Regression test: Ensure that quantified-expressions are correctly instrumented. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase(gexpr_lvl=True).run() +thistest.result() From 0799747b4f82cfd566b6fc12193a9ab7cc4077c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 2 Dec 2024 14:17:59 +0000 Subject: [PATCH 1033/1483] fixup! tests(gexpr): Adapt coverage format tests after Guarded expressions --- .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 2159 -> 2166 bytes .../gen/x86_64-windows/main_1.sid | Bin 449 -> 450 bytes .../gen/x86_64-windows/main_2.sid | Bin 449 -> 450 bytes .../gen/x86_64-windows/pkg.sid | Bin 1140 -> 1141 bytes .../update_arch_mix_windows.sh | 5 ++--- 5 files changed, 2 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 095198c8ada27a3cadc839e3ac642384c693c3e1..073dc0e19e4142c0f0d0c4680bd1ff9e1b4df274 100644 GIT binary patch delta 122 zcmaDa@J&G8-On*3IloLHIU_YWyC6R^uY^I6fq{V$j2Rg=%0;nFE@ufq{V$j2Sn|N3l(=ViTSG35b^g@g6o) qFq?xtUj7Z^hSMqQ%uj;Ug7g@f=^2zOXc!q7nHU-xnNMzG{{R58r5ri{ diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid index b52580e3568e9ab3ed0f5008af07f5e32ef643ba..bbe7b83ad0442698633b44d0bc9c04fce0510501 100644 GIT binary patch delta 41 qcmX@ee27`W-On*3IloLHIU_YWyC6R^uY^I60Rk9-fMKKjB1QoGTnX#| delta 40 pcmX@ae2`h*-On*3IloLHIU_YWyC6R^uY^H>0Rk9-V57n!Mga4)3F`m= diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid index ae0c6f89c42698969e28e2996331002aa099a962..4671951f78d8163cfaaf87a85ad4cff110f2760e 100644 GIT binary patch delta 41 qcmX@ee27`W-On*3IloLHIU_YWyC6R^uY^I60Rk9-fMKKjB1QoGTnX#| delta 40 pcmX@ae2`h*-On*3IloLHIU_YWyC6R^uY^H>0Rk9-V57n!Mga4)3F`m= diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid index f86c33229b72dab4eb72e40bc153151678fb8253..fddcb8609e03de33443703b4a22193be70f2619c 100644 GIT binary patch delta 41 qcmeyu@s&ft-On*3IloLHIU_YWyC6R^uY^I60Rk9-fMKJ2C<_1$N(vGH delta 40 pcmey$@r6U)-On*3IloLHIU_YWyC6R^uY^H>0Rk9-V534P3jhQ%3K0MR diff --git a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh index 9e2390fb7..c74eb0a08 100755 --- a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh +++ b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh @@ -1,6 +1,6 @@ # Update windows artifacts for U204-026-arch-mix -set ex +set -ex if [ $# -eq 0 ]; then echo "No arguments provided. Please provide the name of the gnatcov branch" @@ -33,5 +33,4 @@ gnatcov setup ./gen.sh windows # Copy back the generated sources -rm -rf -cp -rf /cygdrive/c/tmp/U204-026-arch-mix/ /Users/itmgr/gnatcoverage/testsuite/tests/ +cp -r /cygdrive/c/tmp/U204-026-arch-mix/gen/* /Users/itmgr/gnatcoverage/testsuite/tests/U204-026-arch-mix/gen/ From 7a4ce7cbc896e007323ebba02717d9f94a12b3be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 24 Sep 2024 17:28:58 +0200 Subject: [PATCH 1034/1483] Fix testsuite and clean tests for assertions The testsuite had some issues collecting expected notes for the new coverage levels ATC, ATCC and FUN_CALL. This is now fixed, along with the incorrect exepected notes in the relevant tests. --- testsuite/SCOV/internals/cnotes.py | 4 ++- testsuite/SCOV/internals/driver.py | 29 +++++++++------- testsuite/SCOV/internals/xnexpanders.py | 6 +++- .../nested_calls/src/test_nested.adb | 2 +- .../atcc-nested}/src/nested.adb | 30 ++++++++--------- .../atcc-nested}/src/nested.ads | 12 +++---- .../atcc-nested/src/test_nested.adb | 21 ++++++++++++ .../atcc-nested}/test.py | 0 .../{ => expr_func}/src/expr_func.adb | 0 .../expr_func/src/test_expr_func.adb | 26 +++++++++++++++ .../{ => expr_func}/test.py | 0 .../{test.opt => extra.opt} | 0 .../src/fail_loop_inv.adb} | 10 +++--- .../fail_loop_inv/src/test_fail_loop_inv.adb | 14 ++++++++ .../O212-062-assertions/fail_loop_inv/test.py | 8 +++++ .../src/fail_but_ok_cond.adb} | 11 +++---- .../others/src/failed_pre.adb | 11 +++++++ .../src/functions.adb} | 4 +-- .../src/functions.ads} | 4 +-- .../src/test_fail_but_ok_cond.adb} | 22 +++++++------ .../src/test_failed_pre.adb} | 30 +++++++++++------ .../src/test_various_tests.adb} | 28 ++++++++-------- .../src/various_tests.adb} | 15 ++++----- .../tests/O212-062-assertions/others/test.py | 8 +++++ .../{ => pragmas}/src/pragmas.adb | 8 +++-- .../pragmas/src/test_pragmas.adb | 23 +++++++++++++ .../tests/O212-062-assertions/pragmas/test.py | 8 +++++ .../O212-062-assertions/src/assertions_2.adb | 12 ------- .../src/catch_assertions_2.adb | 11 ------- .../src/catch_expr_func.adb | 11 ------- .../src/pack_type_invariant.ads | 21 ------------ .../src/test_assertions_3.adb | 13 -------- .../src/test_expr_func.adb | 17 ---------- .../O212-062-assertions/src/test_pragmas.adb | 18 ---------- .../src/test_type_inv_false.adb | 26 --------------- .../src/test_type_inv_null.adb | 11 ------- .../src/test_type_inv_true.adb | 18 ---------- .../type_invariant/src/pkg.ads | 20 +++++++++++ .../type_invariant/src/test_false.adb | 33 +++++++++++++++++++ .../type_invariant/src/test_null.adb | 16 +++++++++ .../type_invariant/src/test_true.adb | 24 ++++++++++++++ .../type_invariant/test.py | 8 +++++ .../O212-062-atcc-nested/src/test_nested.adb | 15 --------- testsuite/tests/O212-062-atcc-nested/test.opt | 3 -- 44 files changed, 339 insertions(+), 272 deletions(-) rename testsuite/tests/{O212-062-atcc-nested => O212-062-assertions/atcc-nested}/src/nested.adb (76%) rename testsuite/tests/{O212-062-atcc-nested => O212-062-assertions/atcc-nested}/src/nested.ads (94%) create mode 100644 testsuite/tests/O212-062-assertions/atcc-nested/src/test_nested.adb rename testsuite/tests/{O212-062-atcc-nested => O212-062-assertions/atcc-nested}/test.py (100%) rename testsuite/tests/O212-062-assertions/{ => expr_func}/src/expr_func.adb (100%) create mode 100644 testsuite/tests/O212-062-assertions/expr_func/src/test_expr_func.adb rename testsuite/tests/O212-062-assertions/{ => expr_func}/test.py (100%) rename testsuite/tests/O212-062-assertions/{test.opt => extra.opt} (100%) rename testsuite/tests/O212-062-assertions/{src/assertions_3.adb => fail_loop_inv/src/fail_loop_inv.adb} (80%) create mode 100644 testsuite/tests/O212-062-assertions/fail_loop_inv/src/test_fail_loop_inv.adb create mode 100644 testsuite/tests/O212-062-assertions/fail_loop_inv/test.py rename testsuite/tests/O212-062-assertions/{src/assertions_1.adb => others/src/fail_but_ok_cond.adb} (51%) create mode 100644 testsuite/tests/O212-062-assertions/others/src/failed_pre.adb rename testsuite/tests/O212-062-assertions/{src/assertions.adb => others/src/functions.adb} (97%) rename testsuite/tests/O212-062-assertions/{src/assertions.ads => others/src/functions.ads} (93%) rename testsuite/tests/O212-062-assertions/{src/test_assertions_1.adb => others/src/test_fail_but_ok_cond.adb} (63%) rename testsuite/tests/O212-062-assertions/{src/test_assertions_2.adb => others/src/test_failed_pre.adb} (51%) rename testsuite/tests/O212-062-assertions/{src/test_assertions_0.adb => others/src/test_various_tests.adb} (56%) rename testsuite/tests/O212-062-assertions/{src/assertions_0.adb => others/src/various_tests.adb} (78%) create mode 100644 testsuite/tests/O212-062-assertions/others/test.py rename testsuite/tests/O212-062-assertions/{ => pragmas}/src/pragmas.adb (75%) create mode 100644 testsuite/tests/O212-062-assertions/pragmas/src/test_pragmas.adb create mode 100644 testsuite/tests/O212-062-assertions/pragmas/test.py delete mode 100644 testsuite/tests/O212-062-assertions/src/assertions_2.adb delete mode 100644 testsuite/tests/O212-062-assertions/src/catch_assertions_2.adb delete mode 100644 testsuite/tests/O212-062-assertions/src/catch_expr_func.adb delete mode 100644 testsuite/tests/O212-062-assertions/src/pack_type_invariant.ads delete mode 100644 testsuite/tests/O212-062-assertions/src/test_assertions_3.adb delete mode 100644 testsuite/tests/O212-062-assertions/src/test_expr_func.adb delete mode 100644 testsuite/tests/O212-062-assertions/src/test_pragmas.adb delete mode 100644 testsuite/tests/O212-062-assertions/src/test_type_inv_false.adb delete mode 100644 testsuite/tests/O212-062-assertions/src/test_type_inv_null.adb delete mode 100644 testsuite/tests/O212-062-assertions/src/test_type_inv_true.adb create mode 100644 testsuite/tests/O212-062-assertions/type_invariant/src/pkg.ads create mode 100644 testsuite/tests/O212-062-assertions/type_invariant/src/test_false.adb create mode 100644 testsuite/tests/O212-062-assertions/type_invariant/src/test_null.adb create mode 100644 testsuite/tests/O212-062-assertions/type_invariant/src/test_true.adb create mode 100644 testsuite/tests/O212-062-assertions/type_invariant/test.py delete mode 100644 testsuite/tests/O212-062-atcc-nested/src/test_nested.adb delete mode 100644 testsuite/tests/O212-062-atcc-nested/test.opt diff --git a/testsuite/SCOV/internals/cnotes.py b/testsuite/SCOV/internals/cnotes.py index 81a91eabf..6979577bc 100644 --- a/testsuite/SCOV/internals/cnotes.py +++ b/testsuite/SCOV/internals/cnotes.py @@ -344,7 +344,9 @@ cNoteKinds = (etNoCov, efNoCov, ePartCov, eNoCov, cPartCov, eUndetCov) # Assertion violations -aNoteKinds = (aNoCov, atNoCov, acPartCov) +atcNoteKinds = (aNoCov, atNoCov) +atccNoteKinds = acPartCov +aNoteKinds = (aNoCov, atNoCov, atccNoteKinds) # Function and call coverage violations fNoteKinds = (fNoCov, cNoCov, fUndetCov, cUndetCov) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 8c9d2bf5d..c6442e832 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -62,6 +62,8 @@ cNoteKinds, gNoteKinds, tNoteKinds, + atcNoteKinds, + aNoteKinds, fNoteKinds, ) from .cnotes import XsNoteKinds, XoNoteKinds, XcNoteKinds @@ -265,15 +267,10 @@ def __discharges(self, en, xn): # The emitted note needs to designate a sloc range within the # expected sloc range and separation tags, when any is expected, # must match. - a = en.segment.within(xn.segment) - b = not xn.stag and not en.stag - c = xn.stag and en.stag - d = c and en.stag.match(xn.stag) - return a and (b or d) - # return en.segment.within(xn.segment) and ( - # (not xn.stag and not en.stag) - # or (xn.stag and en.stag and en.stag.match(xn.stag)) - # ) + return en.segment.within(xn.segment) and ( + (not xn.stag and not en.stag) + or (xn.stag and en.stag and en.stag.match(xn.stag)) + ) def try_sat_over(self, ekind, xn): # See if expected note XN is satisfied by one of the emitted notes of @@ -1127,6 +1124,12 @@ def check_expectations_over( tc_r_rxp_for = r_rxp_for[relevance_cat] tc_r_ern_for = r_ern_for[relevance_cat] + if self.testcase.assert_lvl == "atc": + tc_r_rxp_for += atcNoteKinds + tc_r_ern_for += atcNoteKinds + elif self.testcase.assert_lvl == "atcc": + tc_r_rxp_for += aNoteKinds + tc_r_ern_for += aNoteKinds if self.testcase.fun_call_lvl: tc_r_rxp_for += fNoteKinds tc_r_ern_for += fNoteKinds @@ -1305,8 +1308,12 @@ def wdbase_for(self, covlevel): return "s_" wdbase = levels[1][0] - wdbase += levels[-2] if self.assert_lvl else "" - wdbase += "fc" if self.fun_call_lvl else "" + + if self.assert_lvl: + wdbase += self.assert_lvl + + if self.fun_call_lvl: + wdbase += "fc" return wdbase + "_" diff --git a/testsuite/SCOV/internals/xnexpanders.py b/testsuite/SCOV/internals/xnexpanders.py index 6959e5286..8ede0db28 100644 --- a/testsuite/SCOV/internals/xnexpanders.py +++ b/testsuite/SCOV/internals/xnexpanders.py @@ -1240,7 +1240,11 @@ def make_new_lvl_combinaison(lvl): combinaisons defined in level_from_char. Return the list of combinaisons. """ - return [level_from_char[c][0] + "+" + lvl for c in level_from_char] + res = [] + for char in level_from_char: + for comb in level_from_char[char]: + res.append(comb + "+" + lvl) + return res assert_level_from_char = { "a": make_new_lvl_combinaison("atc"), diff --git a/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb b/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb index d5c8f75f1..32be588b0 100644 --- a/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb +++ b/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb @@ -15,4 +15,4 @@ end Test_Nested; -- /call/ l+ ## 0 -- /if/ l! ## dT- -- /v_stmt/ l- ## s- --- /v_call/ l- ## s=>s-, f=>s-,c- +-- /v_call/ l- ## s=>s-, f=>c- diff --git a/testsuite/tests/O212-062-atcc-nested/src/nested.adb b/testsuite/tests/O212-062-assertions/atcc-nested/src/nested.adb similarity index 76% rename from testsuite/tests/O212-062-atcc-nested/src/nested.adb rename to testsuite/tests/O212-062-assertions/atcc-nested/src/nested.adb index aee4d6849..aafef59db 100644 --- a/testsuite/tests/O212-062-atcc-nested/src/nested.adb +++ b/testsuite/tests/O212-062-assertions/atcc-nested/src/nested.adb @@ -5,11 +5,9 @@ package body Nested is function One return Integer is begin - pragma Assert -- # success - (T and then (F or else -- # fail - (T and then (T -- # fail - or else F)))); -- # fail - return 1; -- # success + pragma Assert -- # success + (T and then (F or else (T and then (T or else F)))); -- # fail + return 1; -- # success end One; -- One of the branches of the if expression is never exercised. @@ -17,21 +15,21 @@ package body Nested is -- decisions in assertions (FIXME: for now) function Two return Integer is begin - pragma Assert -- # success - ((if T then T else F) and then (F or else -- # success - (T and then (if (T and then F) -- # success - then T -- # success - else T)))); -- # success - return 2; -- # success + pragma Assert -- # success + ((if T then T else F) and then (F or else -- # success + (T and then (if (T and then F) -- # success + then T -- # success + else T)))); -- # success + return 2; -- # success end Two; function Three return Integer is begin - pragma Assert (if (T and then (T and then -- # success - (if T then T else F))) -- # success - then (T and then T) -- # success - else T); -- # success - return 3; -- # success + pragma Assert (if (T and then (T and then -- # success + (if T then T else F))) -- # success + then (T and then T) -- # success + else T); -- # success + return 3; -- # success end Three; end nested; diff --git a/testsuite/tests/O212-062-atcc-nested/src/nested.ads b/testsuite/tests/O212-062-assertions/atcc-nested/src/nested.ads similarity index 94% rename from testsuite/tests/O212-062-atcc-nested/src/nested.ads rename to testsuite/tests/O212-062-assertions/atcc-nested/src/nested.ads index 4d4a44b98..cfe105f92 100644 --- a/testsuite/tests/O212-062-atcc-nested/src/nested.ads +++ b/testsuite/tests/O212-062-assertions/atcc-nested/src/nested.ads @@ -7,14 +7,14 @@ package Nested is F : Boolean := False; -- # success function One return Integer - with Pre => (T and then T) or else F, -- # fail - Post => One'Result = 1 and then -- # fail - (T and then -- # fail - (T or else -- # fail - (F or else T))); -- # fail + with Pre => (T and then T) or else F, -- # fail_ac + Post => One'Result = 1 and then -- # fail_part + (T and then -- # fail_part + (T or else -- # fail_part + (F or else T))); -- # fail_2_ac function Two return Integer - with Pre => (T and then (if T then T else T)) or else F, -- # fail + with Pre => (T and then (if T then T else T)) or else F, -- # fail_ac Post => (if Two'Result = 2 and then -- # success (T and then -- # success (F or else (T or else F))) -- # success diff --git a/testsuite/tests/O212-062-assertions/atcc-nested/src/test_nested.adb b/testsuite/tests/O212-062-assertions/atcc-nested/src/test_nested.adb new file mode 100644 index 000000000..ca43ce5ba --- /dev/null +++ b/testsuite/tests/O212-062-assertions/atcc-nested/src/test_nested.adb @@ -0,0 +1,21 @@ +with Nested; use Nested; + +-- Test the behavior of gnatcov when presented with assertions with nested +-- decisions. No violations are expected in nested decisions as gnatcov should +-- not look inside them. (FIXME: for now) + +procedure Test_Nested is + Dummy : Integer := One; +begin + Dummy := Two; + Dummy := Three; +end Test_Nested; + +--# nested.ads +-- /success/ l+ ## 0 +-- /fail_part/ l! ## 0 +-- /fail_ac/ l! ## ac! +-- /fail_2_ac/ l! ## ac!,ac! +--# nested.adb +-- /success/ l+ ## 0 +-- /fail/ l! ## ac! diff --git a/testsuite/tests/O212-062-atcc-nested/test.py b/testsuite/tests/O212-062-assertions/atcc-nested/test.py similarity index 100% rename from testsuite/tests/O212-062-atcc-nested/test.py rename to testsuite/tests/O212-062-assertions/atcc-nested/test.py diff --git a/testsuite/tests/O212-062-assertions/src/expr_func.adb b/testsuite/tests/O212-062-assertions/expr_func/src/expr_func.adb similarity index 100% rename from testsuite/tests/O212-062-assertions/src/expr_func.adb rename to testsuite/tests/O212-062-assertions/expr_func/src/expr_func.adb diff --git a/testsuite/tests/O212-062-assertions/expr_func/src/test_expr_func.adb b/testsuite/tests/O212-062-assertions/expr_func/src/test_expr_func.adb new file mode 100644 index 000000000..93335e1c8 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/expr_func/src/test_expr_func.adb @@ -0,0 +1,26 @@ +with Ada.Assertions; +with Expr_Func; + +-- Test the correct assertion coverage reporting for an expression function +-- with a precondition and a postcondition expressed as aspects. This is +-- tested with and without a prior declaration. + +procedure Test_Expr_Func is +begin + begin + Expr_Func; + exception + when Ada.Assertions.Assertion_Error => null; + end; +end Test_Expr_Func; + +--# expr_func.adb +-- /foo_decl/ l+ ## 0 +-- /foo_pre/ l+ ## 0 +-- /foo_post/ l+ ## 0 +-- /bar_pre/ l+ ## 0 +-- /bar_post/ l- ## aT- +-- /bar_def/ l+ ## 0 +-- /dummy_decl/ l+ ## 0 +-- /foo_call/ l+ ## 0 +-- /bar_call/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/test.py b/testsuite/tests/O212-062-assertions/expr_func/test.py similarity index 100% rename from testsuite/tests/O212-062-assertions/test.py rename to testsuite/tests/O212-062-assertions/expr_func/test.py diff --git a/testsuite/tests/O212-062-assertions/test.opt b/testsuite/tests/O212-062-assertions/extra.opt similarity index 100% rename from testsuite/tests/O212-062-assertions/test.opt rename to testsuite/tests/O212-062-assertions/extra.opt diff --git a/testsuite/tests/O212-062-assertions/src/assertions_3.adb b/testsuite/tests/O212-062-assertions/fail_loop_inv/src/fail_loop_inv.adb similarity index 80% rename from testsuite/tests/O212-062-assertions/src/assertions_3.adb rename to testsuite/tests/O212-062-assertions/fail_loop_inv/src/fail_loop_inv.adb index 116b78d19..18684d117 100644 --- a/testsuite/tests/O212-062-assertions/src/assertions_3.adb +++ b/testsuite/tests/O212-062-assertions/fail_loop_inv/src/fail_loop_inv.adb @@ -2,17 +2,15 @@ pragma Assertion_Policy (Check); with Ada.Assertions; -procedure Assertions_3 is +procedure Fail_Loop_Inv is begin declare High : Integer := 3; -- # high_decl begin - -- Failed loop invariant - - for J in 1 .. High loop -- # loop_3 + for J in 1 .. High loop -- # loop_cond pragma Loop_Invariant (High < 0); -- # loop_inv end loop; exception - when Ada.Assertions.Assertion_Error => null; -- # catch_3 + when Ada.Assertions.Assertion_Error => null; -- # catch end; -end Assertions_3; +end Fail_Loop_Inv; diff --git a/testsuite/tests/O212-062-assertions/fail_loop_inv/src/test_fail_loop_inv.adb b/testsuite/tests/O212-062-assertions/fail_loop_inv/src/test_fail_loop_inv.adb new file mode 100644 index 000000000..9312707c8 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/fail_loop_inv/src/test_fail_loop_inv.adb @@ -0,0 +1,14 @@ +with Fail_Loop_Inv; + +-- Test the coverage state of a failed loop invariant. + +procedure Test_Fail_Loop_Inv is +begin + Fail_Loop_Inv; +end Test_Fail_Loop_Inv; + +--# fail_loop_inv.adb +-- /high_decl/ l+ ## 0 +-- /loop_cond/ l+ ## 0 +-- /loop_inv/ l! ## aT- +-- /catch/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/fail_loop_inv/test.py b/testsuite/tests/O212-062-assertions/fail_loop_inv/test.py new file mode 100644 index 000000000..651d5af35 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/fail_loop_inv/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision, assert_lvl="atc").run() +TestCase(category=CAT.decision, assert_lvl="atcc").run() +thistest.result() diff --git a/testsuite/tests/O212-062-assertions/src/assertions_1.adb b/testsuite/tests/O212-062-assertions/others/src/fail_but_ok_cond.adb similarity index 51% rename from testsuite/tests/O212-062-assertions/src/assertions_1.adb rename to testsuite/tests/O212-062-assertions/others/src/fail_but_ok_cond.adb index 11a1d585b..9cfa8edd1 100644 --- a/testsuite/tests/O212-062-assertions/src/assertions_1.adb +++ b/testsuite/tests/O212-062-assertions/others/src/fail_but_ok_cond.adb @@ -1,18 +1,17 @@ pragma Assertion_Policy (Check); with Ada.Assertions; -with Assertions; use Assertions; +with Functions; use Functions; -procedure Assertions_1 +procedure Fail_But_Ok_Cond is X : Integer := 1; begin begin -- This assertion fails, all conditions are evaluated - pragma Assert (Baz (X) = 1 or else X /= 0); -- # assert_3 - null; -- # null + pragma Assert (Baz (X) /= 1 or else X = 0); -- # assertion exception - when Ada.Assertions.Assertion_Error => null; -- # catch_1 + when Ada.Assertions.Assertion_Error => null; -- # catch end; -end Assertions_1; +end Fail_But_Ok_Cond; diff --git a/testsuite/tests/O212-062-assertions/others/src/failed_pre.adb b/testsuite/tests/O212-062-assertions/others/src/failed_pre.adb new file mode 100644 index 000000000..3c73fbbb1 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/others/src/failed_pre.adb @@ -0,0 +1,11 @@ +with Functions; use Functions; + +procedure Failed_Pre +is + Y : Integer := 2; +begin + -- Call to Foo with a parameter that does not satisfy the + -- precondition. + + Y := Foo (-2); -- # foo_call +end Failed_Pre; diff --git a/testsuite/tests/O212-062-assertions/src/assertions.adb b/testsuite/tests/O212-062-assertions/others/src/functions.adb similarity index 97% rename from testsuite/tests/O212-062-assertions/src/assertions.adb rename to testsuite/tests/O212-062-assertions/others/src/functions.adb index ed646b557..2112d5325 100644 --- a/testsuite/tests/O212-062-assertions/src/assertions.adb +++ b/testsuite/tests/O212-062-assertions/others/src/functions.adb @@ -1,7 +1,7 @@ pragma Assertion_Policy (Check); pragma Ada_2012; -package body Assertions is +package body Functions is --------- -- Foo -- @@ -56,4 +56,4 @@ package body Assertions is return B; -- # same_ret end Same; -end Assertions; +end Functions; diff --git a/testsuite/tests/O212-062-assertions/src/assertions.ads b/testsuite/tests/O212-062-assertions/others/src/functions.ads similarity index 93% rename from testsuite/tests/O212-062-assertions/src/assertions.ads rename to testsuite/tests/O212-062-assertions/others/src/functions.ads index db579b9d6..1e506475a 100644 --- a/testsuite/tests/O212-062-assertions/src/assertions.ads +++ b/testsuite/tests/O212-062-assertions/others/src/functions.ads @@ -1,7 +1,7 @@ pragma Ada_2012; pragma Assertion_Policy (Check); -package Assertions is +package Functions is function Foo (I : Integer) return Integer with Pre => (I >= 0 and then False) or else I >= 0, -- # foo_pre @@ -14,4 +14,4 @@ package Assertions is function Same (A, B : Boolean) return Boolean; -end Assertions; +end Functions; diff --git a/testsuite/tests/O212-062-assertions/src/test_assertions_1.adb b/testsuite/tests/O212-062-assertions/others/src/test_fail_but_ok_cond.adb similarity index 63% rename from testsuite/tests/O212-062-assertions/src/test_assertions_1.adb rename to testsuite/tests/O212-062-assertions/others/src/test_fail_but_ok_cond.adb index fcc020584..559c45d17 100644 --- a/testsuite/tests/O212-062-assertions/src/test_assertions_1.adb +++ b/testsuite/tests/O212-062-assertions/others/src/test_fail_but_ok_cond.adb @@ -1,17 +1,20 @@ -with Assertions_1; +with Fail_But_Ok_Cond; -procedure Test_Assertions_1 is +-- Test the coverage state when all conditions of a failing assertion are +-- executed. + +procedure Test_Fail_But_Ok_Cond is begin - Assertions_1; -end Test_Assertions_1; + Fail_But_Ok_Cond; +end Test_Fail_But_Ok_Cond; ---# assertions.ads +--# functions.ads -- /foo_pre/ l- ## a- -- /foo_post/ l- ## a- -- /bar_expr/ l- ## s- -- /bar_pre/ l- ## a- -- /baz_expr/ l+ ## 0 ---# assertions.adb +--# functions.adb -- /foo_hi_decl/ l- ## s- -- /foo_loop_1/ l- ## s- -- /foo_inv_1/ l- ## s- @@ -25,7 +28,6 @@ end Test_Assertions_1; -- /nested_2/ l- ## s- -- /nested_3/ l- ## s- -- /same_ret/ l- ## s- --- # assertions_1.adb --- /assert_3/ a=>l+, c=>l! ## a=>0, c=>aT- --- /null/ l+ ## 0 --- /catch_1/ l- ## s- +-- # fail_but_ok_cond.adb +-- /assertion/ l! ## aT- +-- /catch/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/test_assertions_2.adb b/testsuite/tests/O212-062-assertions/others/src/test_failed_pre.adb similarity index 51% rename from testsuite/tests/O212-062-assertions/src/test_assertions_2.adb rename to testsuite/tests/O212-062-assertions/others/src/test_failed_pre.adb index f271f4ae9..cdb408044 100644 --- a/testsuite/tests/O212-062-assertions/src/test_assertions_2.adb +++ b/testsuite/tests/O212-062-assertions/others/src/test_failed_pre.adb @@ -1,17 +1,27 @@ -with Catch_Assertions_2; +with Ada.Assertions; +with Silent_Last_Chance; -procedure Test_Assertions_2 is +With Failed_Pre; + +-- Check the coverage states when calling Foo with a parameter not satisfying +-- the its precondition. + +procedure Test_Failed_Pre is begin - Catch_Assertions_2; -end Test_Assertions_2; + begin + Failed_Pre; + exception + when Ada.Assertions.Assertion_Error => null; + end; +end Test_Failed_Pre; ---# assertions.ads --- /foo_pre/ l- ## a- +--# functions.ads +-- /foo_pre/ l- ## aT- -- /foo_post/ l- ## a- -- /bar_expr/ l- ## s- --- /bar_pre/ l- ## aT- +-- /bar_pre/ l- ## a- -- /baz_expr/ l- ## s- ---# assertions.adb +--# functions.adb -- /foo_hi_decl/ l- ## s- -- /foo_loop_1/ l- ## s- -- /foo_inv_1/ l- ## s- @@ -25,5 +35,5 @@ end Test_Assertions_2; -- /nested_2/ l- ## s- -- /nested_3/ l- ## s- -- /same_ret/ l- ## s- ---# assertions_2.adb --- /foo_2/ l+ ## c! +--# failed_pre.adb +-- /foo_call/ l+ ## c! diff --git a/testsuite/tests/O212-062-assertions/src/test_assertions_0.adb b/testsuite/tests/O212-062-assertions/others/src/test_various_tests.adb similarity index 56% rename from testsuite/tests/O212-062-assertions/src/test_assertions_0.adb rename to testsuite/tests/O212-062-assertions/others/src/test_various_tests.adb index c5e94b29b..772ad7d26 100644 --- a/testsuite/tests/O212-062-assertions/src/test_assertions_0.adb +++ b/testsuite/tests/O212-062-assertions/others/src/test_various_tests.adb @@ -1,34 +1,36 @@ -with Assertions_0; +with Various_Tests; -procedure Test_Assertions_0 is +-- Test various assertion scenarios. The details can be found directly in +-- various_tests.adb. + +procedure Test_Various_Tests is begin - Assertions_0; -end Test_Assertions_0; + Various_Tests; +end Test_Various_Tests; ---# assertions.ads +--# functions.ads -- /foo_pre/ l+ ## 0 -- /foo_post/ a=>l+, c=>l! ## a=>0, c=>ac! -- /bar_expr/ l+ ## 0 -- /bar_pre/ a=>l+, c=>l! ## a=>0, c=>ac! -- /baz_expr/ l- ## s- ---# assertions.adb +--# functions.adb -- /foo_hi_decl/ l+ ## 0 -- /foo_loop_1/ l+ ## 0 -- /foo_inv_1/ l+ ## 0 -- /foo_loop_2/ l+ ## 0 -- /foo_inv_2/ a=>l+, c=>l! ## a=>0, c=>ac! -- /foo_return/ l+ ## 0 --- /id_pre/ a=>l+, c=>l! ## a=>0, c=> ac! +-- /id_pre/ a=>l+, c=>l! ## a=>0, c=>ac!,ac! -- /id_post/ l+ ## 0 -- /id_ret/ l+ ## 0 --- /nested_1/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /nested_1/ a=>l+, c=>l! ## a=>0, c=>ac!,ac! -- /nested_2/ a=>l+, c=>l! ## a=>0, c=>ac! -- /nested_3/ l+ ## 0 -- /same_ret/ l+ ## 0 --- # assertions_0.adb --- /assert_1/ a=>l+, c=>l! ## a=>0, c=>ac! --- /foo_0/ l+ ## 0 +-- # various_tests.adb +-- /assert_1/ a=>l+, c=>l! ## a=>0, c=>ac!,ac! +-- /foo/ l+ ## 0 -- /if_false/ l! ## dT- -- /assert_2/ l- ## s- --- /null/ l- ## s- --- /bar_0/ l+ ## 0 +-- /bar/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/assertions_0.adb b/testsuite/tests/O212-062-assertions/others/src/various_tests.adb similarity index 78% rename from testsuite/tests/O212-062-assertions/src/assertions_0.adb rename to testsuite/tests/O212-062-assertions/others/src/various_tests.adb index 9e1643f4c..067b6e712 100644 --- a/testsuite/tests/O212-062-assertions/src/assertions_0.adb +++ b/testsuite/tests/O212-062-assertions/others/src/various_tests.adb @@ -1,39 +1,38 @@ pragma Assertion_Policy (Check); -with Assertions; use Assertions; +with Functions; use Functions; -procedure Assertions_0 +procedure Various_Tests is X : Integer := 0; Y : Integer := X; A : Boolean := True; B : Boolean := False; begin - -- The last condition is not evaluated + -- Only the first condition is evaluated - pragma Assert ((X = 0 or else A) or else X = 0); -- # assert_1 + pragma Assert ((X = 0 or else A) or else X = 8); -- # assert_1 -- Call a function. Evaluate all conditions of the precondition; -- evaluate only the first condition of the postcondition. The first -- loop invariant is entirely covered while the last condition of the -- second loop invariant is not evaluated. - Y := Foo (0); -- # foo_0 + Y := Foo (0); -- # foo -- The if's decision is False, so the statement contained is not executed if X /= 0 then -- # if_false pragma Assert (X /= 0 or else False); -- # assert_2 - null; -- # null end if; -- Call an expression function with a precondition of which the last -- condition is not evaluated. - Y := Bar (0); -- # bar_0 + Y := Bar (0); -- # bar -- Call to function with an aspect defined with the function body. A := Same (A, B); -end Assertions_0; +end Various_Tests; diff --git a/testsuite/tests/O212-062-assertions/others/test.py b/testsuite/tests/O212-062-assertions/others/test.py new file mode 100644 index 000000000..651d5af35 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/others/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision, assert_lvl="atc").run() +TestCase(category=CAT.decision, assert_lvl="atcc").run() +thistest.result() diff --git a/testsuite/tests/O212-062-assertions/src/pragmas.adb b/testsuite/tests/O212-062-assertions/pragmas/src/pragmas.adb similarity index 75% rename from testsuite/tests/O212-062-assertions/src/pragmas.adb rename to testsuite/tests/O212-062-assertions/pragmas/src/pragmas.adb index 128144cf2..a64ae5aeb 100644 --- a/testsuite/tests/O212-062-assertions/src/pragmas.adb +++ b/testsuite/tests/O212-062-assertions/pragmas/src/pragmas.adb @@ -8,7 +8,7 @@ is function Id (B : Boolean) return Boolean is (B); -- # id begin begin - -- Pass + -- No assertion error pragma Assume (T and then (F or else T)); -- # assume pragma Check (Precondition, F or else not T or else T); -- # c_pre @@ -17,9 +17,11 @@ begin pragma Check (Invariant, T); -- # c_inv pragma Check (Assertion, T or else T); -- # c_assert - pragma Assert_And_Cut (T or else (F or else T)); -- # cut + pragma Assert_And_Cut (T -- # cut_1 + or else (F -- # cut_2 + or else T)); -- # cut_3 - -- Fail + -- Assertion error pragma Assume (Id (F) or else F); -- # fail exception when Ada.Assertions.Assertion_Error => null; -- # catch diff --git a/testsuite/tests/O212-062-assertions/pragmas/src/test_pragmas.adb b/testsuite/tests/O212-062-assertions/pragmas/src/test_pragmas.adb new file mode 100644 index 000000000..122c87bc8 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/pragmas/src/test_pragmas.adb @@ -0,0 +1,23 @@ +with Pragmas; + +-- Test the correct reporting of coverage for all supported pragmas. +-- All assertion are executed, some have conditions that are not. + +procedure Test_Pragmas is +begin + Pragmas; +end Test_Pragmas; + +--# pragmas.adb +-- /id/ l+ ## 0 +-- /assume/ l+ ## 0 +-- /c_pre/ l+ ## 0 +-- /c_post/ l+ ## 0 +-- /c_ti/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /c_inv/ l+ ## 0 +-- /c_assert/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /cut_1/ a=>l+, c=>l! ## a=>0, c=>0 +-- /cut_2/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /cut_3/ a=>l+, c=>l! ## a=>0, c=>ac! +-- /fail/ l! ## aT- +-- /catch/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/pragmas/test.py b/testsuite/tests/O212-062-assertions/pragmas/test.py new file mode 100644 index 000000000..651d5af35 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/pragmas/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision, assert_lvl="atc").run() +TestCase(category=CAT.decision, assert_lvl="atcc").run() +thistest.result() diff --git a/testsuite/tests/O212-062-assertions/src/assertions_2.adb b/testsuite/tests/O212-062-assertions/src/assertions_2.adb deleted file mode 100644 index 45f0b01d2..000000000 --- a/testsuite/tests/O212-062-assertions/src/assertions_2.adb +++ /dev/null @@ -1,12 +0,0 @@ -with Assertions; use Assertions; -with Silent_Last_Chance; - -procedure Assertions_2 -is - Y : Integer := 2; -begin - -- Call to Foo with a parameter that does not satisfy the - -- precondition. - - Y := Foo (-2); -- # foo_2 -end Assertions_2; diff --git a/testsuite/tests/O212-062-assertions/src/catch_assertions_2.adb b/testsuite/tests/O212-062-assertions/src/catch_assertions_2.adb deleted file mode 100644 index af280df14..000000000 --- a/testsuite/tests/O212-062-assertions/src/catch_assertions_2.adb +++ /dev/null @@ -1,11 +0,0 @@ -with Ada.Assertions; -with Assertions_2; - -procedure Catch_Assertions_2 is -begin - begin - Assertions_2; - exception - when Ada.Assertions.Assertion_Error => null; - end; -end Catch_Assertions_2; diff --git a/testsuite/tests/O212-062-assertions/src/catch_expr_func.adb b/testsuite/tests/O212-062-assertions/src/catch_expr_func.adb deleted file mode 100644 index 0807c7ac7..000000000 --- a/testsuite/tests/O212-062-assertions/src/catch_expr_func.adb +++ /dev/null @@ -1,11 +0,0 @@ -with Ada.Assertions; -with Expr_Func; - -procedure Catch_Expr_Func is -begin - begin - Expr_Func; - exception - when Ada.Assertions.Assertion_Error => null; - end; -end Catch_Expr_Func; diff --git a/testsuite/tests/O212-062-assertions/src/pack_type_invariant.ads b/testsuite/tests/O212-062-assertions/src/pack_type_invariant.ads deleted file mode 100644 index 3d2eaf4b2..000000000 --- a/testsuite/tests/O212-062-assertions/src/pack_type_invariant.ads +++ /dev/null @@ -1,21 +0,0 @@ -pragma Ada_2012; -pragma Assertion_Policy (Check); - -package Pack_Type_Invariant is - - type Bool_Record_1 is private; -- # type_dec_1 - - function Make_Bool_Record_1 (B : Boolean) return Bool_Record_1; -private - - -- Type invariant as aspect - type Bool_Record_1 is -- # type_def_1 - record -- # rec_1 - B : Boolean := True; -- # rec_1 - end record -- # rec_1 - with Type_Invariant => B; -- # type_inv_1 - - function Make_Bool_Record_1 (B : Boolean) return Bool_Record_1 is - ((B => B)); -- # func_ret_1 - -end Pack_Type_Invariant; diff --git a/testsuite/tests/O212-062-assertions/src/test_assertions_3.adb b/testsuite/tests/O212-062-assertions/src/test_assertions_3.adb deleted file mode 100644 index ea53dbaf0..000000000 --- a/testsuite/tests/O212-062-assertions/src/test_assertions_3.adb +++ /dev/null @@ -1,13 +0,0 @@ -with Assertions_3; - -procedure Test_Assertions_3 is -begin - Assertions_3; -end Test_Assertions_3; - ---# assertions_3.adb --- /high_decl/ l+ ## 0 --- /loop_3/ l+ ## 0 --- /loop_inv/ l! ## 0 --- /null/ l+ ## 0 --- /catch_3/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/test_expr_func.adb b/testsuite/tests/O212-062-assertions/src/test_expr_func.adb deleted file mode 100644 index b3b9663d9..000000000 --- a/testsuite/tests/O212-062-assertions/src/test_expr_func.adb +++ /dev/null @@ -1,17 +0,0 @@ -with Catch_Expr_Func; - -procedure Test_Expr_Func is -begin - Catch_Expr_Func; -end Test_Expr_Func; - ---# expr_func.adb --- /foo_decl/ l+ ## 0 --- /foo_pre/ l+ ## 0 --- /foo_post/ l+ ## 0 --- /bar_pre/ l+ ## 0 --- /bar_post/ l- ## aT- --- /bar_def/ l+ ## 0 --- /dummy_decl/ l+ ## 0 --- /foo_call/ l+ ## 0 --- /bar_call/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/test_pragmas.adb b/testsuite/tests/O212-062-assertions/src/test_pragmas.adb deleted file mode 100644 index 4b6015b8f..000000000 --- a/testsuite/tests/O212-062-assertions/src/test_pragmas.adb +++ /dev/null @@ -1,18 +0,0 @@ -with Pragmas; - -procedure Test_Pragmas is -begin - Pragmas; -end Test_Pragmas; - ---# pragmas.adb --- /id/ l+ ## 0 --- /assume/ l+ ## 0 --- /c_pre/ l+ ## 0 --- /c_post/ l+ ## 0 --- /c_ti/ a=>l+, c=>l! ## a=>0, a=>ac! --- /c_inv/ l+ ## 0 --- /c_assert/ a=>l+, c=>l! ## a=>0, c=>ac! --- /cut/ a=>l+, c=>l! ## a=>0, c=>ac! --- /fail/ l! ## aT- --- /catch/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/test_type_inv_false.adb b/testsuite/tests/O212-062-assertions/src/test_type_inv_false.adb deleted file mode 100644 index 9460d9bcb..000000000 --- a/testsuite/tests/O212-062-assertions/src/test_type_inv_false.adb +++ /dev/null @@ -1,26 +0,0 @@ -with Silent_Last_Chance; -with Pack_Type_Invariant; - -with Ada.Assertions; - -procedure Test_False -is - use Pack_Type_Invariant; - -begin - begin - declare - Dummy_1 : constant Bool_Record_1 := Make_Bool_Record_1 (False); - begin - null; - end; - exception - when Ada.Assertions.Assertion_Error => null; - end; -end Test_False; - ---# pack_type_invariant.ads --- /type_dec_1/ l+ ## 0 --- /type_def_1/ l+ ## 0 --- /type_inv_1/ l! ## aT- --- /func_ret_1/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/src/test_type_inv_null.adb b/testsuite/tests/O212-062-assertions/src/test_type_inv_null.adb deleted file mode 100644 index d684f6eef..000000000 --- a/testsuite/tests/O212-062-assertions/src/test_type_inv_null.adb +++ /dev/null @@ -1,11 +0,0 @@ -procedure Test_Null is -begin - null; -end Test_Null; - ---# pack_type_invariant.ads --- /type_dec_1/ l- ## s- --- /type_def_1/ l- ## s- --- /rec_1/ l- ## 0 --- /type_inv_1/ l- ## 0 --- /func_ret_1/ l- ## s- diff --git a/testsuite/tests/O212-062-assertions/src/test_type_inv_true.adb b/testsuite/tests/O212-062-assertions/src/test_type_inv_true.adb deleted file mode 100644 index bba14630e..000000000 --- a/testsuite/tests/O212-062-assertions/src/test_type_inv_true.adb +++ /dev/null @@ -1,18 +0,0 @@ -with Pack_Type_Invariant; - -procedure Test_Type_Invariant -is - use Pack_Type_Invariant; - - Dummy_1 : Bool_Record_1 := Make_Bool_Record_1 (True); -begin - - null; -end Test_Type_Invariant; - ---# pack_type_invariant.ads --- /type_dec_1/ l+ ## 0 --- /type_def_1/ l+ ## 0 --- /rec_1/ l+ ## 0 --- /type_inv_1/ l+ ## 0 --- /func_ret_1/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/type_invariant/src/pkg.ads b/testsuite/tests/O212-062-assertions/type_invariant/src/pkg.ads new file mode 100644 index 000000000..1c1b08602 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/type_invariant/src/pkg.ads @@ -0,0 +1,20 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Pkg is + + type Rec is private; -- # rec_decl + + function Make_Rec (B : Boolean) return Rec; + +private + + type Rec is record -- # rec_def + B : Boolean := True; -- # rec_b + end record -- # rec_end + with Type_Invariant => B; -- # type_inv + -- Record with a type invariant expressed as an aspect + + function Make_Rec (B : Boolean) return Rec is ((B => B)); -- # return + +end Pkg; diff --git a/testsuite/tests/O212-062-assertions/type_invariant/src/test_false.adb b/testsuite/tests/O212-062-assertions/type_invariant/src/test_false.adb new file mode 100644 index 000000000..dfc4b61a1 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/type_invariant/src/test_false.adb @@ -0,0 +1,33 @@ +with Silent_Last_Chance; +with Ada.Assertions; + +with Pkg; + +-- Assertion test for type invariant of a record. +-- +-- Create a record with a field value that does not respect the type +-- invariant. This raises an assertion error. Test that the coverage state of +-- the type invariant is set to "not covered". + +procedure Test_False +is + use Pkg; +begin + begin + declare + Dummy : constant Rec := Make_Rec (False); + begin + null; + end; + exception + when Ada.Assertions.Assertion_Error => null; + end; +end Test_False; + +--# pkg.ads +-- /rec_decl/ l+ ## 0 +-- /rec_def/ l+ ## 0 +-- /rec_b/ l+ ## 0 +-- /rec_end/ l+ ## 0 +-- /type_inv/ l! ## aT- +-- /return/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/type_invariant/src/test_null.adb b/testsuite/tests/O212-062-assertions/type_invariant/src/test_null.adb new file mode 100644 index 000000000..1a17c7c78 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/type_invariant/src/test_null.adb @@ -0,0 +1,16 @@ +-- Assertion test for type invariant of a record. +-- +-- Test that an non-executed type invariant is reported as such. + +procedure Test_Null is +begin + null; +end Test_Null; + +--# pkg.ads +-- /rec_decl/ l- ## s- +-- /rec_def/ l- ## s- +-- /rec_b/ l- ## 0 +-- /rec_end/ l- ## 0 +-- /type_inv/ l- ## a- +-- /return/ l- ## s- diff --git a/testsuite/tests/O212-062-assertions/type_invariant/src/test_true.adb b/testsuite/tests/O212-062-assertions/type_invariant/src/test_true.adb new file mode 100644 index 000000000..e66343357 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/type_invariant/src/test_true.adb @@ -0,0 +1,24 @@ +with Pkg; + +-- Assertion test for type invariant of a record. +-- +-- Creating a record with a field value that respects the type invariant. +-- This raises no assertion error. Test that the coverage state of the type +-- invariant is set to "covered". + +procedure Test_True +is + use Pkg; + + Dummy : Rec := Make_Rec (True); +begin + null; +end Test_True; + +--# pkg.ads +-- /rec_decl/ l+ ## 0 +-- /rec_def/ l+ ## 0 +-- /rec_b/ l+ ## 0 +-- /rec_end/ l+ ## 0 +-- /type_inv/ l+ ## 0 +-- /return/ l+ ## 0 diff --git a/testsuite/tests/O212-062-assertions/type_invariant/test.py b/testsuite/tests/O212-062-assertions/type_invariant/test.py new file mode 100644 index 000000000..651d5af35 --- /dev/null +++ b/testsuite/tests/O212-062-assertions/type_invariant/test.py @@ -0,0 +1,8 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.decision, assert_lvl="atc").run() +TestCase(category=CAT.decision, assert_lvl="atcc").run() +thistest.result() diff --git a/testsuite/tests/O212-062-atcc-nested/src/test_nested.adb b/testsuite/tests/O212-062-atcc-nested/src/test_nested.adb deleted file mode 100644 index 6af8d40a1..000000000 --- a/testsuite/tests/O212-062-atcc-nested/src/test_nested.adb +++ /dev/null @@ -1,15 +0,0 @@ -with Nested; use Nested; - -procedure Test_Nested is - Dummy : Integer := One; -begin - Dummy := Two; - Dummy := Three; -end Test_Nested; - ---# nested.ads --- /success/ l+ ## 0 --- /fail/ l! ## ac! ---# nested.adb --- /success/ l+ ## 0 --- /fail/ l! ## ac! diff --git a/testsuite/tests/O212-062-atcc-nested/test.opt b/testsuite/tests/O212-062-atcc-nested/test.opt deleted file mode 100644 index 51a393770..000000000 --- a/testsuite/tests/O212-062-atcc-nested/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -bin-traces XFAIL Assertion coverage not yet supported for binary traces -5.04a1 DEAD Test contains Ada_2012 features -7.1.2 DEAD Test contains Ada_2012 features From df09a9e0767bc23eb9386035dc39e25f12e37eba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 16 Oct 2024 15:50:41 +0200 Subject: [PATCH 1035/1483] Add simple test for ATCC and FUN_CALL --- .../contracts/src/contracts.adb | 13 +++++++++++++ .../contracts/src/contracts.ads | 7 +++++++ .../contracts/src/test_contracts.adb | 17 +++++++++++++++++ .../contracts/src/test_contracts_not_called.adb | 16 ++++++++++++++++ .../287-function_call_cov/contracts/test.py | 11 +++++++++++ 5 files changed, 64 insertions(+) create mode 100644 testsuite/tests/287-function_call_cov/contracts/src/contracts.adb create mode 100644 testsuite/tests/287-function_call_cov/contracts/src/contracts.ads create mode 100644 testsuite/tests/287-function_call_cov/contracts/src/test_contracts.adb create mode 100644 testsuite/tests/287-function_call_cov/contracts/src/test_contracts_not_called.adb create mode 100644 testsuite/tests/287-function_call_cov/contracts/test.py diff --git a/testsuite/tests/287-function_call_cov/contracts/src/contracts.adb b/testsuite/tests/287-function_call_cov/contracts/src/contracts.adb new file mode 100644 index 000000000..f7d3cb9c1 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/contracts/src/contracts.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package body Contracts is + + procedure Foo (B : Boolean) -- # foo + is + function T return Boolean is (True); -- # t + begin + pragma Assert (T or else T); -- # assert + null; -- # null + end Foo; +end; diff --git a/testsuite/tests/287-function_call_cov/contracts/src/contracts.ads b/testsuite/tests/287-function_call_cov/contracts/src/contracts.ads new file mode 100644 index 000000000..402909b8c --- /dev/null +++ b/testsuite/tests/287-function_call_cov/contracts/src/contracts.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; +pragma Assertion_Policy (Check); + +package Contracts is + procedure Foo (B : Boolean) + with Pre => B or else B; -- # pre +end; diff --git a/testsuite/tests/287-function_call_cov/contracts/src/test_contracts.adb b/testsuite/tests/287-function_call_cov/contracts/src/test_contracts.adb new file mode 100644 index 000000000..825834140 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/contracts/src/test_contracts.adb @@ -0,0 +1,17 @@ +with Contracts; + +-- Test the absence of crash and the correctness of the coverage report when +-- both assertion and function/call coverage are activated simultaneously +-- when calling a function with a precondition. + +procedure Test_Contracts is +begin + Contracts.Foo (True); +end Test_Contracts; + +--# contracts.ads +-- /pre/ l! ## ac! +--# contracts.adb +-- /t/ l+ ## 0 +-- /assert/ l! ## ac!,c- +-- /null/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/contracts/src/test_contracts_not_called.adb b/testsuite/tests/287-function_call_cov/contracts/src/test_contracts_not_called.adb new file mode 100644 index 000000000..d4a40a87d --- /dev/null +++ b/testsuite/tests/287-function_call_cov/contracts/src/test_contracts_not_called.adb @@ -0,0 +1,16 @@ +-- Test the absence of crash and the correctness of the coverage report when +-- both assertion and function/call coverage are activated simultaneously +-- when never calling a function with a precondition. + +procedure Test_Contracts_Not_Called is +begin + null; +end Test_Contracts_Not_Called; + +--# contracts.ads +-- /pre/ l- ## a- +--# contracts.adb +-- /foo/ l- ## f- +-- /t/ l- ## s-,f-,c- +-- /assert/ l- ## s-,c-,c- +-- /null/ l- ## s- diff --git a/testsuite/tests/287-function_call_cov/contracts/test.py b/testsuite/tests/287-function_call_cov/contracts/test.py new file mode 100644 index 000000000..a29493644 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/contracts/test.py @@ -0,0 +1,11 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase( + category=CAT.mcdc, + assert_lvl="atcc", + fun_call_lvl=True, +).run() +thistest.result() From 7f1ec61b4029587accbe7a14b7c7ae53590db737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 4 Dec 2024 17:03:47 +0100 Subject: [PATCH 1036/1483] Adapt expr func aspect test for light runtimes --- .../instr-cov/358-exprf-aspects/src/aspect.adb | 14 -------------- .../instr-cov/358-exprf-aspects/src/aspect.ads | 11 +++++++++++ .../tests/instr-cov/358-exprf-aspects/src/foo.adb | 8 ++++++++ .../358-exprf-aspects/src/test_aspect.adb | 10 +++++----- 4 files changed, 24 insertions(+), 19 deletions(-) delete mode 100644 testsuite/tests/instr-cov/358-exprf-aspects/src/aspect.adb create mode 100644 testsuite/tests/instr-cov/358-exprf-aspects/src/aspect.ads create mode 100644 testsuite/tests/instr-cov/358-exprf-aspects/src/foo.adb diff --git a/testsuite/tests/instr-cov/358-exprf-aspects/src/aspect.adb b/testsuite/tests/instr-cov/358-exprf-aspects/src/aspect.adb deleted file mode 100644 index 705138bcf..000000000 --- a/testsuite/tests/instr-cov/358-exprf-aspects/src/aspect.adb +++ /dev/null @@ -1,14 +0,0 @@ -pragma Ada_2012; - -procedure Aspect is - - function Foo return Integer is (42) -- # expr - with Convention => Stdcall; - - type Foo_Type is access - function return Integer with Convention => Stdcall; -- # type - - Dummy : Foo_Type := Foo'Access; -- # dummy -begin - null; -end Aspect; diff --git a/testsuite/tests/instr-cov/358-exprf-aspects/src/aspect.ads b/testsuite/tests/instr-cov/358-exprf-aspects/src/aspect.ads new file mode 100644 index 000000000..8b0fbd333 --- /dev/null +++ b/testsuite/tests/instr-cov/358-exprf-aspects/src/aspect.ads @@ -0,0 +1,11 @@ +pragma Ada_2012; + +package Aspect is + + function Foo return Integer is (42) -- # expr + with Convention => Stdcall; + + type Foo_Type is access + function return Integer with Convention => Stdcall; + +end Aspect; diff --git a/testsuite/tests/instr-cov/358-exprf-aspects/src/foo.adb b/testsuite/tests/instr-cov/358-exprf-aspects/src/foo.adb new file mode 100644 index 000000000..fb79f88f0 --- /dev/null +++ b/testsuite/tests/instr-cov/358-exprf-aspects/src/foo.adb @@ -0,0 +1,8 @@ +with Aspect; use Aspect; + +procedure Foo is + + Dummy : Foo_Type := Foo'Access; -- # d +begin + null; +end; diff --git a/testsuite/tests/instr-cov/358-exprf-aspects/src/test_aspect.adb b/testsuite/tests/instr-cov/358-exprf-aspects/src/test_aspect.adb index 37071c12b..a99de6bd5 100644 --- a/testsuite/tests/instr-cov/358-exprf-aspects/src/test_aspect.adb +++ b/testsuite/tests/instr-cov/358-exprf-aspects/src/test_aspect.adb @@ -1,4 +1,4 @@ -with Aspect; +with Foo; -- Check that when instrumenting an expression function with aspects, these -- aspects are also correctly attached to both the new intermediary function @@ -6,10 +6,10 @@ with Aspect; procedure Test_Aspect is begin - Aspect; + Foo; end Test_Aspect; ---# aspect.adb +--# aspect.ads -- /expr/ l- ## s- --- /type/ l+ ## 0 --- /dummy/ l+ ## 0 +--# foo.adb +-- /d/ l+ ## 0 From ddc8d901beee71b636a55358f6b4f38ea4cc9f42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 4 Dec 2024 16:52:47 +0100 Subject: [PATCH 1037/1483] Remove internal URLs --- .gitlab-ci.yml | 1 - qualification/genbundle.py | 9 ++++++--- testsuite/tests/U204-026-arch-mix/update.sh | 2 +- .../tests/U204-026-arch-mix/update_arch_mix_windows.sh | 2 +- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e02224c8f..24a02029c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -7,7 +7,6 @@ variables: PACKAGE_BASE_NAME: gnatcoverage.tar.gz PACKAGE_ABSOLUTE_NAME: $CI_PROJECT_DIR/$PACKAGE_BASE_NAME GITLAB_REMOTE: "https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/" - PIP_INDEX_URL: "https://gitlab-ci-token:${CI_JOB_TOKEN}@gitlab.adacore-it.com/api/v4/projects/202/packages/pypi/simple" include: #TODO: workaround to allow dynamically setting the interruptible policy until https://gitlab.com/gitlab-org/gitlab/-/issues/194023 is implemented diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 2a9865099..6bf1fe46d 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -342,9 +342,7 @@ def current_gitbranch_at(dirname): sphinx_target_for = {"html": "html", "pdf": "latexpdf"} # The master GIT repo where our source artifacts reside -GIT_MASTER = ( - "git@ssh.gitlab.adacore-it.com:eng/das/cov/gnatcoverage-qualification.git" -) +GIT_MASTER = os.environ.get("GIT_MASTER") # The name of the subdir in the working directory where we'll fetch TOR # artifacts from. This would be an image of a "gnatcoverage" repository, from @@ -482,6 +480,11 @@ def git_update(self): os.chdir(self.workdir) gitref = self.o.gitsource if self.o.gitsource else GIT_MASTER + exit_if( + not gitref, + "set the repository source either through the --git-source option" + " or through the GIT_MASTER environment variable", + ) announce("cloning git repository from %s" % gitref) diff --git a/testsuite/tests/U204-026-arch-mix/update.sh b/testsuite/tests/U204-026-arch-mix/update.sh index d31d36544..cfc104be0 100755 --- a/testsuite/tests/U204-026-arch-mix/update.sh +++ b/testsuite/tests/U204-026-arch-mix/update.sh @@ -19,7 +19,7 @@ cd $cwd cp -rf /tmp/U204-026-arch-mix/* . # Then update the windows artifacts -[ ! -d '/tmp/iod-dev' ] && git clone git@ssh.gitlab.adacore-it.com:eng/shared/iod-dev /tmp/iod-dev +[ ! -d '/tmp/iod-dev' ] && git clone git-adacore:eng/shared/iod-dev /tmp/iod-dev /tmp/iod-dev/create-base.py --base-image x86_64-windows-2019 git_branch=$(git rev-parse --abbrev-ref HEAD) sshpass ssh iod 'bash -s' < update_arch_mix_windows.sh $git_branch diff --git a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh index c74eb0a08..8a37894a9 100755 --- a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh +++ b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh @@ -9,7 +9,7 @@ fi # Create a sandbox cd /Users/itmgr -git clone git@ssh.gitlab.adacore-it.com:eng/cov/gnatcoverage +git clone git-adacore:eng/cov/gnatcoverage anod init wave # Checkout the right gnatcov branch From 951f122c60dd0f303a57257caf4f50ad1fc0e9c5 Mon Sep 17 00:00:00 2001 From: Boris Yakobowski Date: Thu, 5 Dec 2024 18:26:43 +0100 Subject: [PATCH 1038/1483] Use git indirections in pre-commit Switch to the template for pre-commit to facilitate this Fixes eng/projects/issues#7 --- .gitlab-ci.yml | 30 ++++++++---------------------- .pre-commit-config.yaml | 6 +++--- 2 files changed, 11 insertions(+), 25 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 24a02029c..6f61c537d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,18 +6,19 @@ workflow: variables: PACKAGE_BASE_NAME: gnatcoverage.tar.gz PACKAGE_ABSOLUTE_NAME: $CI_PROJECT_DIR/$PACKAGE_BASE_NAME - GITLAB_REMOTE: "https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}:${CI_SERVER_PORT}/" include: + - component: $CI_SERVER_FQDN/eng/gitlab-templates/pre-commit@~latest + inputs: + stage: test #TODO: workaround to allow dynamically setting the interruptible policy until https://gitlab.com/gitlab-org/gitlab/-/issues/194023 is implemented - local: utils/ci/interruptible.yml rules: - - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH + - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH - project: eng/codepeer/ci-registry file: /gnatsas-on-gnatcov.yml .basic_setup: &basic_setup - - unset GITLAB_TOKEN - generic_anod_ci --add-dep eng/das/cov/gnatcoverage-extra - cat /tmp/ci_env.sh - . /tmp/ci_env.sh @@ -205,20 +206,10 @@ test_spark: <<: *artifacts -stylechecks: - interruptible: true - stage: test - services: - - image:pe-base - - run_as_root:false - needs: [] - script: - - *basic_setup - - git config --global --add - url."${GITLAB_REMOTE}".insteadOf "git@ssh.gitlab.adacore-it.com:" - - git config --global --add - url."${GITLAB_REMOTE}".insteadOf "ssh://git@ssh.gitlab.adacore-it.com/" +pre-commit: + before_script: + - *basic_setup # Install the clang-format executable and make it available - anod install libclang -Qstable @@ -229,14 +220,9 @@ stylechecks: - . /tmp/venv/bin/activate - python -m pip install colorama pre-commit - - cd $CI_PROJECT_DIR - - - pre-commit install - - pre-commit install-hooks - - pre-commit run -a --show-diff-on-failure - - python .check-formatting.py --force-colors + ################# # Optional jobs # ################# diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bc0658441..6e1b9e5c7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,5 +1,5 @@ repos: - - repo: git@ssh.gitlab.adacore-it.com:eng/shared/mirrors/pre-commit-clang-format + - repo: https://github.com/doublify/pre-commit-clang-format rev: 62302476d0da01515660132d76902359bed0f782 hooks: - id: clang-format @@ -18,7 +18,7 @@ repos: Maximum: -1 } }"] - - repo: git@ssh.gitlab.adacore-it.com:it/flake8.git + - repo: https://github.com/pycqa/flake8 rev: 7.1.1 hooks: - id: flake8 @@ -28,7 +28,7 @@ repos: - flake8-comprehensions - pygments args: ["--config=.flake8"] - - repo: git@ssh.gitlab.adacore-it.com:it/black.git + - repo: https://github.com/psf/black rev: 24.10.0 hooks: - id: black From 740aece73d6f120cd3a637e8a909bf503ceb2396 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 19 Aug 2024 14:38:03 +0200 Subject: [PATCH 1039/1483] Fix detection of non-instrumentable expression function --- .../instr-cov/expr_func/completion/main.adb | 8 ++++ .../instr-cov/expr_func/completion/pak.ads | 19 +++++++++ .../instr-cov/expr_func/completion/test.py | 39 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 9 ++++- 4 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/instr-cov/expr_func/completion/main.adb create mode 100644 testsuite/tests/instr-cov/expr_func/completion/pak.ads create mode 100644 testsuite/tests/instr-cov/expr_func/completion/test.py diff --git a/testsuite/tests/instr-cov/expr_func/completion/main.adb b/testsuite/tests/instr-cov/expr_func/completion/main.adb new file mode 100644 index 000000000..8797d117b --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/completion/main.adb @@ -0,0 +1,8 @@ +pragma Ada_2012; +with Pak; use Pak; + +procedure Main is + T_Instance : T := Make (True); +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/expr_func/completion/pak.ads b/testsuite/tests/instr-cov/expr_func/completion/pak.ads new file mode 100644 index 000000000..ebd847ae8 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/completion/pak.ads @@ -0,0 +1,19 @@ +pragma Ada_2012; + +package Pak is + + type T is private; + + function Make (Cond : Boolean) return T; + +private + type T is tagged record + X : Integer; + end record; + function Make (Cond : Boolean) return T is (T'(X => (if Cond then 1 else 2))); + + type TT is new T with record + Y : Integer; + end record; + overriding function Make (Cond : Boolean) return TT is (TT'(X => 3, Y => 4)); +end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/completion/test.py b/testsuite/tests/instr-cov/expr_func/completion/test.py new file mode 100644 index 000000000..6671f19db --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/completion/test.py @@ -0,0 +1,39 @@ +""" +Regression test: check that gnatcov does not instrument expression function +that are a primitive of a tagged type T when the controlling parameter is the +return type, and when the expression function is a completion. + +gnatcov used to instrument such expression function, which resulted in +introducing a new primitive (the wrapper generated for MC/DC instrumentation), +which was not defined for derived types. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+uc_mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", + tolerate_instrument_messages=( + "cannot instrument an expression function which" + ), +) + +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {5, 7}}, + "pak.ads.xcov": {"+": {5, 10, 11, 12, 15, 16, 17}, "?": {13, 18}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 175a3a05f..2ee5b1458 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3023,8 +3023,13 @@ package body Instrument.Ada_Unit is if Common_Nodes.Ctrl_Type.Is_Null then return False; end if; - return Common_Nodes.N_Spec.F_Subp_Returns.P_Designated_Type_Decl - = Common_Nodes.Ctrl_Type; + + -- Always compare the full views, to avoid an equality mismatch when + -- e.g. comparing the full view against an incomplete view. + + return + Common_Nodes.N_Spec.F_Subp_Returns.P_Designated_Type_Decl.P_Full_View + = Common_Nodes.Ctrl_Type.P_Full_View; exception when Exc : Property_Error => Report (UIC, From 01ec5e4324131eb691142a0fd310c08374024dcc Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 19 Aug 2024 14:41:09 +0200 Subject: [PATCH 1040/1483] Fix expr_func/prim test Update the coverage expectations. Also adapt the test case as gnatcov no longer instrument primitives of a tagged type T when the return type is T. --- .../tests/instr-cov/expr_func/prim/p.gpr | 4 --- .../tests/instr-cov/expr_func/prim/test.opt | 1 - .../tests/instr-cov/expr_func/prim/test.py | 32 ++++++++++--------- 3 files changed, 17 insertions(+), 20 deletions(-) delete mode 100644 testsuite/tests/instr-cov/expr_func/prim/p.gpr delete mode 100644 testsuite/tests/instr-cov/expr_func/prim/test.opt diff --git a/testsuite/tests/instr-cov/expr_func/prim/p.gpr b/testsuite/tests/instr-cov/expr_func/prim/p.gpr deleted file mode 100644 index c96f36767..000000000 --- a/testsuite/tests/instr-cov/expr_func/prim/p.gpr +++ /dev/null @@ -1,4 +0,0 @@ -project P is - for Object_Dir use "obj"; - for Main use ("main.adb"); -end P; diff --git a/testsuite/tests/instr-cov/expr_func/prim/test.opt b/testsuite/tests/instr-cov/expr_func/prim/test.opt deleted file mode 100644 index 08dc59c5a..000000000 --- a/testsuite/tests/instr-cov/expr_func/prim/test.opt +++ /dev/null @@ -1 +0,0 @@ -ALL XFAIL triggers compiler bug T114-003 diff --git a/testsuite/tests/instr-cov/expr_func/prim/test.py b/testsuite/tests/instr-cov/expr_func/prim/test.py index 78df7d726..2b3d868c2 100644 --- a/testsuite/tests/instr-cov/expr_func/prim/test.py +++ b/testsuite/tests/instr-cov/expr_func/prim/test.py @@ -1,37 +1,39 @@ """ -Check that we properly instrument expression functions that are primitives -of tagged types for MC/DC. +Check that gnatcov correctly processes expression functions that are primitives +of tagged types for MC/DC, e.g. it warns about them, and they are reported as +uninstrumented in the coverage report. """ -import os -import os.path - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor -p_gpr = os.path.abspath("p.gpr") -obj_dir = os.path.abspath("obj") - tmp = Wdir("tmp_") build_run_and_coverage( - gprsw=GPRswitches(root_project=p_gpr), + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), covlevel="stmt+uc_mcdc", mains=["main"], extra_coverage_args=["-axcov", "--output-dir=xcov"], - gpr_obj_dir=obj_dir, - gpr_exe_dir=obj_dir, trace_mode="src", + tolerate_instrument_messages=( + "cannot instrument an expression function which" + ), ) -# TODO: update coverage expectations once compiler bug -# has been fixed and XFAIL is removed. - check_xcov_reports( - "xcov", {"main.adb.xcov": {"+": {4, 5, 7, 12, 14, 17, 19, 21, 22, 23, 24}}} + "xcov", + { + "main.adb.xcov": {"+": {6}}, + "pak.ads.xcov": { + "+": {4, 5, 6, 13, 14, 15}, + "-": {8, 10}, + "?": {11, 16}, + }, + }, ) thistest.result() From 01b98187190f8cd68a1500ae77c7a7ac16dc251d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 19 Aug 2024 14:42:18 +0200 Subject: [PATCH 1041/1483] expr_func/prim2: remove test This test is outdated, as gnatcov no longer instrument this kind of constructs. It thus makes this test a duplicate of expr_func/prim. --- .../tests/instr-cov/expr_func/prim2/main.adb | 9 ---- .../tests/instr-cov/expr_func/prim2/p.gpr | 4 -- .../tests/instr-cov/expr_func/prim2/pak.adb | 10 ----- .../tests/instr-cov/expr_func/prim2/pak.ads | 25 ----------- .../tests/instr-cov/expr_func/prim2/test.opt | 1 - .../tests/instr-cov/expr_func/prim2/test.py | 44 ------------------- 6 files changed, 93 deletions(-) delete mode 100644 testsuite/tests/instr-cov/expr_func/prim2/main.adb delete mode 100644 testsuite/tests/instr-cov/expr_func/prim2/p.gpr delete mode 100644 testsuite/tests/instr-cov/expr_func/prim2/pak.adb delete mode 100644 testsuite/tests/instr-cov/expr_func/prim2/pak.ads delete mode 100644 testsuite/tests/instr-cov/expr_func/prim2/test.opt delete mode 100644 testsuite/tests/instr-cov/expr_func/prim2/test.py diff --git a/testsuite/tests/instr-cov/expr_func/prim2/main.adb b/testsuite/tests/instr-cov/expr_func/prim2/main.adb deleted file mode 100644 index f725e2c80..000000000 --- a/testsuite/tests/instr-cov/expr_func/prim2/main.adb +++ /dev/null @@ -1,9 +0,0 @@ -pragma Ada_2012; -with Pak; use Pak; - -procedure Main is - Obj : T := Make (True); - Obj2 : TT := Make (False); -begin - null; -end Main; diff --git a/testsuite/tests/instr-cov/expr_func/prim2/p.gpr b/testsuite/tests/instr-cov/expr_func/prim2/p.gpr deleted file mode 100644 index c96f36767..000000000 --- a/testsuite/tests/instr-cov/expr_func/prim2/p.gpr +++ /dev/null @@ -1,4 +0,0 @@ -project P is - for Object_Dir use "obj"; - for Main use ("main.adb"); -end P; diff --git a/testsuite/tests/instr-cov/expr_func/prim2/pak.adb b/testsuite/tests/instr-cov/expr_func/prim2/pak.adb deleted file mode 100644 index d6062b524..000000000 --- a/testsuite/tests/instr-cov/expr_func/prim2/pak.adb +++ /dev/null @@ -1,10 +0,0 @@ -pragma Ada_2012; - -package body Pak is - - function Make_Internal (Cond : Boolean) return T is - (T'(X => (if Cond then 1 else 2))); - - function Make_Internal (Cond : Boolean) return TT is (TT'(X => 3, Y => 4)); - -end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/prim2/pak.ads b/testsuite/tests/instr-cov/expr_func/prim2/pak.ads deleted file mode 100644 index e243859c2..000000000 --- a/testsuite/tests/instr-cov/expr_func/prim2/pak.ads +++ /dev/null @@ -1,25 +0,0 @@ -pragma Ada_2012; - -package Pak is - type T is tagged record - X : Integer; - end record; - function And_Then (X : T; A, B : Boolean) return Boolean is - (A and then B); - function Or_Else (X : T; A, B : Boolean) return Boolean is - (A or else B); - - function Make_Internal (Cond : Boolean) return T; - - function Make (Cond : Boolean) return T is (Make_Internal (Cond)); - - type TT is new T with record - Y : Integer; - end record; - - overriding function Make_Internal (Cond : Boolean) return TT; - - overriding function Make (Cond : Boolean) return TT is - (Make_Internal (Cond)); - -end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/prim2/test.opt b/testsuite/tests/instr-cov/expr_func/prim2/test.opt deleted file mode 100644 index 41403b657..000000000 --- a/testsuite/tests/instr-cov/expr_func/prim2/test.opt +++ /dev/null @@ -1 +0,0 @@ -ALL XFAIL expr func in test no longer instrumented (U625-016) diff --git a/testsuite/tests/instr-cov/expr_func/prim2/test.py b/testsuite/tests/instr-cov/expr_func/prim2/test.py deleted file mode 100644 index 396673373..000000000 --- a/testsuite/tests/instr-cov/expr_func/prim2/test.py +++ /dev/null @@ -1,44 +0,0 @@ -""" -Check that we properly instrument expression functions that are primitives -of tagged types for MC/DC. The test focuses mainly on primitives where the -tagged type is the return type of the expression function. This variant of -the test does not trigger the compiler bug in T114-003 -""" - -import os -import os.path - -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -from SUITE.context import thistest -from SUITE.cutils import Wdir -from SUITE.gprutils import GPRswitches - - -p_gpr = os.path.abspath("p.gpr") -obj_dir = os.path.abspath("obj") - -tmp = Wdir("tmp_") - -build_run_and_coverage( - gprsw=GPRswitches(root_project=p_gpr), - covlevel="stmt+uc_mcdc", - mains=["main"], - extra_coverage_args=["-axcov", "--output-dir=xcov"], - gpr_obj_dir=obj_dir, - gpr_exe_dir=obj_dir, - trace_mode="src", -) - -# Coverage expectations aren't really important, we want to check that -# the instrumented code is valid. - -check_xcov_reports( - "xcov", - { - "main.adb.xcov": {"+": {6}}, - "pak.ads.xcov": {"+": {4, 5, 6, 14, 16, 17, 18, 23}, "-": {8, 10}}, - "pak.adb.xcov": {"!": {6}, "+": {8}}, - }, -) - -thistest.result() From 9561af471cdfd2e50bf3ecb90ccf51fc1bb69943 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 27 Mar 2024 17:29:39 +0100 Subject: [PATCH 1042/1483] Adapt the testsuite to work with AAMP The testsuite needs some adaptation fixes to work with the AAMP target. Notably, add the support to execute a main through the facade simulator. Also rename gnatcov_rts_aamp.gpr to gnatcov_rts.gpr and make it more generic (remove the AAMP specific switch). --- testsuite/SCOV/instr.py | 23 ++++++- testsuite/SCOV/internals/driver.py | 7 ++- testsuite/SCOV/minicheck.py | 4 ++ testsuite/SUITE/control.py | 10 ++- testsuite/SUITE/cutils.py | 13 +++- testsuite/SUITE/tutils.py | 61 ++++++++++++++----- testsuite/facade.cfg | 30 +++++++++ testsuite/tests/U211-014-setup/test.py | 2 +- .../gen/buf_dump/c_only/test.py | 1 + .../gen/buf_dump/cpp_only/test.py | 1 + .../instr-cov/checks_and_warnings/test.py | 1 + .../instr-cov/manual-dump/c_only/test.py | 1 + .../instr-cov/manual-dump/cpp_only/test.py | 1 + .../{gnatcov_rts_aamp.gpr => gnatcov_rts.gpr} | 14 ++--- tools/gnatcov/examples/support/libsupport.gpr | 45 ++++++++------ 15 files changed, 169 insertions(+), 45 deletions(-) create mode 100644 testsuite/facade.cfg rename tools/gnatcov/ada-rts/{gnatcov_rts_aamp.gpr => gnatcov_rts.gpr} (53%) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index f817b0110..9302be963 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -6,7 +6,8 @@ from e3.fs import mkdir from SUITE.context import thistest -from SUITE.cutils import contents_of, ext, indent +from SUITE.control import env +from SUITE.cutils import contents_of, copy_to_dir, ext, indent from SUITE.tutils import RUNTIME_INFO, GNATCOV_INFO, locate_gpr_file, xcov @@ -356,3 +357,23 @@ def available_ada_dump_triggers(): return ["main-end", "ravenscar-task-termination"] else: return ["main-end"] + + +def maybe_relocate_binaries(object_dir, exe_dir, mains): + """ + Relocate binaries produced in the object_dir to the exe_dir for the AAMP + target. + + :param object_dir: object directory of the main project. + :param exe_dir: executable directory of the main project. + :param mains: main filenames. + """ + # The GNAAMP linker disregards the full name passed to the -o switch but + # only picks the simple name. Thus, the executable ends up in the object + # directory. + # + # Copy it to the executable directory so that the rest of the testsuite + # can assume executables are always there. + if "aamp" in env.target.platform: + for main in mains: + copy_to_dir(object_dir, exe_dir, main) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index c6442e832..f5fd1760d 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -32,6 +32,7 @@ add_dumper_lch_hook, default_dump_channel, default_dump_trigger, + maybe_relocate_binaries, xcov_convert_base64, xcov_instrument, ) @@ -625,12 +626,13 @@ def run(self): this_depth = thistest.depth + 1 if self.covctl else thistest.depth self.gpr_obj_dir = "obj" + self.gpr_exe_dir = self.abdir(attribute=True) self.gpr = gprfor( mains=self.drivers, prjid="gen", objdir=self.gpr_obj_dir, srcdirs=["../" * n + "src" for n in range(1, this_depth)], - exedir=self.abdir(attribute=True), + exedir=self.gpr_exe_dir, main_cargs="-fno-inline", deps=self.covctl.deps if self.covctl else [], extra=self.covctl.gpr() if self.covctl else "", @@ -1533,6 +1535,9 @@ def mode_build(self): extracargs=self.extracargs, gargs=self.common_build_gargs() + ["--src-subdirs=gnatcov-instr"], ) + maybe_relocate_binaries( + self.gpr_obj_dir, self.gpr_exe_dir, [exename_for(self.main())] + ) def mode_execute(self, main): register_failure = not self.testcase.expect_failures diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 7cdd8a9f7..58d4f36af 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -17,11 +17,13 @@ from SCOV.instr import ( default_dump_channel, + maybe_relocate_binaries, xcov_convert_base64, xcov_instrument, ) from SUITE.cutils import contents_of, indent from SUITE.tutils import ( + exename_for, exepath_to, gprbuild, run_cov_program, @@ -353,6 +355,8 @@ def gprbuild_wrapper(root_project): # multiple traces in the current directory. for m in mains: rm(srctrace_pattern_for(m, is_manual, manual_prj_name)) + # Callback to run for each instrumented main + maybe_relocate_binaries(gpr_obj_dir, gpr_exe_dir, [exename_for(m)]) patterns = set() trace_files = [] diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index 34312dd0b..523557124 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -257,7 +257,13 @@ def __init__(self, runtime_name=None): self.has_exception_propagation = True self.discrs = [] - if not self.runtime_name: + # Set specific scenario variables to always pass to any project loading + # command (gnatcov -P or gprbuild / gprinstall) + self.gpr_scenario_vars = [] + + if "aamp" in self.runtime_name: + self.gpr_scenario_vars = ["-XLIBRARY_SUPPORT=no"] + elif not self.runtime_name: self.has_full_runtime = True self.discrs = ["RTS_FULL"] elif "embedded" in self.runtime_name: @@ -349,6 +355,8 @@ def __init__(self, exeext, partiallinks, to_platform_specific_symbol=None): ), # x86_64-windows targets "x86_64.*mingw": TargetInfo(exeext=".exe", partiallinks=False), + # AAMP target + "aamp": TargetInfo(exeext=".axe", partiallinks=False), # default ".": TargetInfo(exeext="", partiallinks=False), } diff --git a/testsuite/SUITE/cutils.py b/testsuite/SUITE/cutils.py index fcec46423..5134090fd 100644 --- a/testsuite/SUITE/cutils.py +++ b/testsuite/SUITE/cutils.py @@ -11,7 +11,7 @@ import sys import tempfile -from e3.fs import mkdir +from e3.fs import cp, mkdir from e3.os.fs import cd, which from e3.os.process import Run @@ -309,3 +309,14 @@ def multi_range(*args, minus=None): class Identifier: def __init__(self, name): self.name = name + + +def copy_to_dir(orig_dir, target_dir, filename): + """ + Copy filename from orig_dir to target_dir. + """ + if os.path.abspath(orig_dir) != os.path.abspath(target_dir): + cp( + os.path.join(orig_dir, filename), + os.path.join(target_dir, filename), + ) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index cda83444a..3b30ad798 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -40,6 +40,7 @@ from SUITE.cutils import ( FatalError, contents_of, + list_to_file, text_to_file, to_list, unhandled_exception_in, @@ -264,11 +265,9 @@ def gpr_common_args(project, auto_config_args=True): """ gproptions = [] - gproptions.append( - # verbose mode for verifiability in qualif mode. - # quiet mode for performance (less io) otherwise. - "-v" if thistest.options.qualif_level else "-q", - ) + # If running in qualif mode, run with the verbose switch for verifiability + if thistest.options.qualif_level: + gproptions.append("-v") if auto_config_args: gproptions.append( "--config={}".format(os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR)) @@ -290,7 +289,8 @@ def gpr_common_args(project, auto_config_args=True): ): gproptions.append("-XLOADER=RAM") - return gproptions + # Add runtime specific scenario variables + return gproptions + RUNTIME_INFO.gpr_scenario_vars def gprbuild( @@ -729,26 +729,28 @@ def xcov_suite_args( or any(arg.startswith("-P") for arg in covargs) ) + result = ( + gpr_common_args(project=None, auto_config_args=auto_config_args) + if project_handling_enabled + else [] + ) + # If --config is asked and project handling is involved, pass it and stop # there. If there is a board, it must be described in the project file # (gnatcov's -P argument). if auto_config_args and project_handling_enabled: - return [ - "--config={}".format(os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR)) - ] + return result - # Nothing to do if the caller does not want automatic --target/--RTS + # Nothing to add if the caller does not want automatic --target/--RTS # arguments. if not auto_target_args: - return [] + return result # Otherwise, handle target and board information. # # Remember that the testsuite determines the target from the machine that # hosts the testsuite and from its own --host/--build/--target arguments... - - result = [] - + # # If we have a specific target board specified with --board, use that: # # --target=p55-elf --board=iSystem-5554 @@ -1015,6 +1017,37 @@ def run_cov_program( exec_args = exec_args or [] inp = None use_pycross = False + if thistest.options.target: + # If we are testing for AAMP, use the facade simulator. It expects a + # configuration file (facade.cfg) in the executable dir, and the + # executable must be run through an executable.sod file, which sets + # up the simulator environment. This .sod file should be in the same + # directory as the executable. + if "aamp" in control.env.target.platform: + args.append("dosfsod.exe") + list_to_file( + [ + "sw tx on", + '$TEXTIO = ""', + "switch batch on", + "fill 0000..ffff 0", + "load " + executable, + "go", + "halt", + ], + "test.sod", + ) + args.append("@test.sod") + cp(os.path.join(ROOT_DIR, "facade.cfg"), "facade.cfg") + args.extend(exec_args) + out = cmdrun( + args, + out=out, + env=env, + register_failure=register_failure, + for_pgm=True, + ) + return out # If we are in a cross configuration, run the program using run-cross2 if thistest.options.target and thistest.env.target.platform != "c": diff --git a/testsuite/facade.cfg b/testsuite/facade.cfg new file mode 100644 index 000000000..453b53408 --- /dev/null +++ b/testsuite/facade.cfg @@ -0,0 +1,30 @@ +[FACADE] ## *MUST* be first line of file + ## switches must begin in column 1 + ## no spaces allowed before the "=" + ## see config.h for valid switches and types + +[T5] ## test equipment section +BASE_ADDR= 0000 # T5 base address (hex) +DHC_BASE_ADDR= 00000 # deep history card base address (hex) +BUS_TIMEOUT= 10 # milliseconds (decimal) +XFR_TIMEOUT= 10 # milliseconds (decimal) +CONS_TIMEOUT= 10 # milliseconds (decimal) +T5_RESET_HOLD= 8 # target clock ticks (decimal) +#TARGET_RESET_HOLD= 40 # target clock ticks (decimal) +#POD_FREQ_SELECT= 20 # pod freq select for AAMP5vr1 pods + # target freq must be in one of following ranges: + # 15-30 MHz (default) + # 30-50 MHz + # 5-15 MHz + +[DBG] ## debug engine section +SHOW_PC= 1 # Update the PC in the console window + +[GUI] ## GUI section +SCREEN_BUFSIZE= 500 # number of lines saved in console window (250-2500) +MAX_SRC_WIN= 1 # specifies the maximum number of source windows + # open at any given time (must be 1, 2, or 3) +TITLE=v3.5 # String to use in the Title bar after Facade +#TMPPATH=C:/TMP # specifies the directory for scratch files + # (history and memory buffers) + # default: working directory specified at installation diff --git a/testsuite/tests/U211-014-setup/test.py b/testsuite/tests/U211-014-setup/test.py index 7a2ce63e5..29b5c3e48 100644 --- a/testsuite/tests/U211-014-setup/test.py +++ b/testsuite/tests/U211-014-setup/test.py @@ -218,7 +218,7 @@ def check_full( ) p = gprbuild( mixed_prj.project_file, - gargs=["--src-subdirs=gnatcov-instr"], + gargs=["--src-subdirs=gnatcov-instr", "-q"], trace_mode="src", runtime_project=rt_prj, out=log_file, diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/c_only/test.py b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/test.py index f9208e92e..61b6d3260 100644 --- a/testsuite/tests/ext_annotations/gen/buf_dump/c_only/test.py +++ b/testsuite/tests/ext_annotations/gen/buf_dump/c_only/test.py @@ -57,6 +57,7 @@ mains=["main"], extra_instr_args=[f"--external-annotations={annotations}"], extra_coverage_args=["-axcov"], + extra_gprbuild_args=["-q"], dump_trigger="manual", manual_prj_name="main", tolerate_instrument_messages=instr_warning, diff --git a/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.py b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.py index 5c969ee27..a84bbcd44 100644 --- a/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.py +++ b/testsuite/tests/ext_annotations/gen/buf_dump/cpp_only/test.py @@ -57,6 +57,7 @@ mains=["main"], extra_instr_args=[f"--external-annotations={annotations}"], extra_coverage_args=["-axcov"], + extra_gprbuild_args=["-q"], dump_trigger="manual", manual_prj_name="main", tolerate_instrument_messages=instr_warning, diff --git a/testsuite/tests/instr-cov/checks_and_warnings/test.py b/testsuite/tests/instr-cov/checks_and_warnings/test.py index 273a15c11..4077a171f 100644 --- a/testsuite/tests/instr-cov/checks_and_warnings/test.py +++ b/testsuite/tests/instr-cov/checks_and_warnings/test.py @@ -24,6 +24,7 @@ extra_coverage_args=["-axcov", "--output-dir=xcov"], gpr_obj_dir=obj_dir, gpr_exe_dir=obj_dir, + extra_gprbuild_args=["-q"], extra_gprbuild_cargs=["-gnatwae"], check_gprbuild_output=True, trace_mode="src", diff --git a/testsuite/tests/instr-cov/manual-dump/c_only/test.py b/testsuite/tests/instr-cov/manual-dump/c_only/test.py index 7a574c391..2579c7014 100644 --- a/testsuite/tests/instr-cov/manual-dump/c_only/test.py +++ b/testsuite/tests/instr-cov/manual-dump/c_only/test.py @@ -45,6 +45,7 @@ covlevel="stmt", mains=["main"], extra_coverage_args=["-axcov"], + extra_gprbuild_args=["-q"], dump_trigger="manual", manual_prj_name="main", tolerate_instrument_messages=instr_warning, diff --git a/testsuite/tests/instr-cov/manual-dump/cpp_only/test.py b/testsuite/tests/instr-cov/manual-dump/cpp_only/test.py index 556ac9297..2ff10fdc2 100644 --- a/testsuite/tests/instr-cov/manual-dump/cpp_only/test.py +++ b/testsuite/tests/instr-cov/manual-dump/cpp_only/test.py @@ -45,6 +45,7 @@ covlevel="stmt", mains=["main"], extra_coverage_args=["-axcov"], + extra_gprbuild_args=["-q"], dump_trigger="manual", manual_prj_name="main", tolerate_instrument_messages=instr_warning, diff --git a/tools/gnatcov/ada-rts/gnatcov_rts_aamp.gpr b/tools/gnatcov/ada-rts/gnatcov_rts.gpr similarity index 53% rename from tools/gnatcov/ada-rts/gnatcov_rts_aamp.gpr rename to tools/gnatcov/ada-rts/gnatcov_rts.gpr index 0bef57a76..5c919b3ef 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts_aamp.gpr +++ b/tools/gnatcov/ada-rts/gnatcov_rts.gpr @@ -1,19 +1,17 @@ --- Ada Instrumentation runtime for gnatcov, for the AAMP target. +-- Ada Instrumentation runtime for gnatcov. It is an Ada-only version of +-- the instrumentation runtime, and is equivalent to the gnatcov_rts.gpr +-- under /share/gnatcoverage/gnatcov_rts. -- -- This project is meant to be built and installed before instrumenting -- projects with "gnatcov instrument", and then to be used when building -- instrumented programs thanks to gprbuild's --implicit-with option. -project GNATcov_RTS_AAMP is +project GNATcov_RTS is for Source_Dirs use ("."); for Object_Dir use "obj-gnatcov_rts"; for Languages use ("Ada"); package Compiler is - - -- Use the universal addressing switch, which is recommended when - -- compiling for the AAMP target (and is only available on this target). - - for Default_Switches ("Ada") use ("-univ"); + for Default_Switches ("Ada") use ("-O2"); end Compiler; -end GNATcov_RTS_AAMP; +end GNATcov_RTS; diff --git a/tools/gnatcov/examples/support/libsupport.gpr b/tools/gnatcov/examples/support/libsupport.gpr index c91f2e044..ce5014104 100644 --- a/tools/gnatcov/examples/support/libsupport.gpr +++ b/tools/gnatcov/examples/support/libsupport.gpr @@ -5,7 +5,10 @@ with "common.gpr", "conf.gpr"; -library project Libsupport is +project Libsupport is + + Library_Support : Common.Yes_No_Type := external ("LIBRARY_SUPPORT", "yes"); + -- Whether the platform supports library projects Do_Build : Common.Yes_No_Type := external ("LIBSUPPORT_BUILD", "no"); -- Whether we're using this file to build the library or to link @@ -15,30 +18,36 @@ library project Libsupport is -- Whether we are building/using for an Aunit context or not, with -- influence on the last_chance handler inclusion. + Langs := ("Ada"); + + for Object_Dir use "obj/" & Conf.Target; + -- Common library attributes: -- ========================== - for Library_Kind use "static"; - for Library_Auto_Init use "False"; + case Library_Support is + when "yes" => + for Library_Dir use "lib/" & Conf.Target; + for Library_Kind use "static"; + for Library_Auto_Init use "False"; - Langs := ("Ada"); + -- We might have needs for both aunit and !aunit libs for a run + -- so pick a different libname for each case: - for Library_Dir use "lib/" & Conf.Target; - for Object_Dir use "obj/" & Conf.Target; + case Use_AUnit is + when "yes" => + for Library_Name use "supportaunit"; + when "no" => + for Library_name use "support"; + end case; - -- We might have needs for both aunit and !aunit libs for a run - -- so pick a different libname for each case: + case Do_Build is + when "no" => for Externally_Built use "true"; + when "yes" => for Externally_Built use "false"; + end case; - case Use_AUnit is - when "yes" => - for Library_Name use "supportaunit"; when "no" => - for Library_name use "support"; - end case; - - case Do_Build is - when "no" => for Externally_Built use "true"; - when "yes" => for Externally_Built use "false"; + null; end case; -- Now compute the set of source directories to use. A common one, @@ -48,7 +57,7 @@ library project Libsupport is Source_Dirs := ("src", "src/helpers"); case Conf.Target is - when "" | "c" => null; + when "" | "c" | "aamp" => null; when others => From de8452122d8804e7764048ce4954d625bca41cae Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 15 May 2024 15:07:01 +0200 Subject: [PATCH 1043/1483] Address new GNAT warning --- tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads index df7631497..fdc040a52 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads @@ -71,6 +71,7 @@ package GNATcov_RTS.Buffers is type Fingerprint_Type is array (1 .. 20) of Unsigned_8; for Fingerprint_Type'Component_Size use 8; for Fingerprint_Type'Size use 20 * 8; + pragma Universal_Aliasing (Fingerprint_Type); type GNATcov_RTS_Coverage_Buffers is record Fingerprint : Fingerprint_Type; From 21c170b259ec424ed22fcb65c5bc727a13018066 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 15 May 2024 15:07:50 +0200 Subject: [PATCH 1044/1483] Add API to reset coverage buffers The Ada API of the Ada instrumentation runtime must be strictly the same as the Ada API of the standard instrumentation runtime. GNATCOV_RTS.Buffers.Lists was missing the Reset_Group_Array_Buffers subprogram which resulted in the manual dump trigger not working. --- .../ada-rts/gnatcov_rts-buffers-lists.adb | 115 ++++++++++++++++++ .../ada-rts/gnatcov_rts-buffers-lists.ads | 5 + 2 files changed, 120 insertions(+) create mode 100644 tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.adb diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.adb b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.adb new file mode 100644 index 000000000..71821e96f --- /dev/null +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.adb @@ -0,0 +1,115 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage Instrumentation Runtime -- +-- -- +-- Copyright (C) 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. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +------------------------------------------------------------------------------ + +with System; use System; + +package body GNATcov_RTS.Buffers.Lists is + + procedure Reset_Buffer + (Buffer_Address : System.Address; Last_Bit_Id : Any_Bit_Id); + -- Reset a coverage buffer + + procedure Reset_Buffers (C_Buffers : Coverage_Buffers_Access); + -- Reset statement, decision, and mcdc coverage buffers + + procedure Reset_Buffers_Group + (C_Buffers_Group : Coverage_Buffers_Group_Access); + -- Reset a buffers group, which consists of all the buffers for a unit, + -- i.e. for its specification, its body, and its separates. + + ------------------ + -- Reset_Buffer -- + ------------------ + + procedure Reset_Buffer + (Buffer_Address : System.Address; Last_Bit_Id : Any_Bit_Id) + is + Buffer : Coverage_Buffer_Type (1 .. Last_Bit_Id); + for Buffer'Address use Buffer_Address; + begin + for I in Buffer'Range loop + Buffer (I) := False; + end loop; + end Reset_Buffer; + + ------------------- + -- Reset_Buffers -- + ------------------- + + procedure Reset_Buffers (C_Buffers : Coverage_Buffers_Access) is + begin + if C_Buffers = null then + return; + end if; + if C_Buffers.Statement /= System.Null_Address then + Reset_Buffer (C_Buffers.Statement, C_Buffers.Statement_Last_Bit); + end if; + if C_Buffers.Decision /= System.Null_Address then + Reset_Buffer (C_Buffers.Decision, C_Buffers.Decision_Last_Bit); + end if; + if C_Buffers.MCDC /= System.Null_Address then + Reset_Buffer (C_Buffers.Statement, C_Buffers.MCDC_Last_Bit); + end if; + end Reset_Buffers; + + ------------------------- + -- Reset_Buffers_Group -- + ------------------------- + + procedure Reset_Buffers_Group + (C_Buffers_Group : Coverage_Buffers_Group_Access) is + begin + if C_Buffers_Group = null then + return; + end if; + declare + Buffers_Group : Coverage_Buffers_Group + (1 .. Integer (C_Buffers_Group.Length)); + pragma Import (C, Buffers_Group); + for Buffers_Group'Address use C_Buffers_Group.Buffers; + begin + for I in Buffers_Group'Range loop + Reset_Buffers (Buffers_Group (I)); + end loop; + end; + end Reset_Buffers_Group; + + ------------------------------- + -- Reset_Group_Array_Buffers -- + ------------------------------- + + procedure Reset_Group_Array_Buffers + (Arr : GNATcov_RTS_Coverage_Buffers_Group_Array) + is + Buffers_Groups : Coverage_Buffers_Group_Array + (1 .. Integer (Arr.Length)); + pragma Import (C, Buffers_Groups); + for Buffers_Groups'Address use Arr.Groups; + begin + for I in Buffers_Groups'Range loop + Reset_Buffers_Group (Buffers_Groups (I)); + end loop; + end Reset_Group_Array_Buffers; + +end GNATcov_RTS.Buffers.Lists; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads index 2c2b4eb2d..ce01651ca 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.ads @@ -59,4 +59,9 @@ package GNATcov_RTS.Buffers.Lists is end record; pragma Convention (C, GNATcov_RTS_Coverage_Buffers_Group_Array); + procedure Reset_Group_Array_Buffers + (Arr : GNATcov_RTS_Coverage_Buffers_Group_Array); + -- Set the components of all the buffers in each group to zero, effectively + -- resetting the coverage state of all obligations to "not covered". + end GNATcov_RTS.Buffers.Lists; From 9b8125849b29484be1458ba12daec732dc6e6de1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 27 Nov 2024 12:25:42 +0100 Subject: [PATCH 1045/1483] Do not instrument static values as calls --- .../src/test_contracts_not_called.adb | 2 +- .../dotted_type/src/make_call.adb | 2 +- .../dotted_type/src/test_dotted_type.adb | 2 +- .../nested_calls/src/nested.adb | 2 +- .../nested_calls/src/test_nested.adb | 13 ++++---- .../protected_body/src/test_not_called.adb | 2 +- .../static_call/src/discriminant.adb | 14 +++++++++ .../static_call/src/enum.adb | 31 +++++++++++++++++++ .../static_call/src/test_discriminant.adb | 14 +++++++++ .../static_call/src/test_enum.adb | 17 ++++++++++ .../287-function_call_cov/static_call/test.py | 7 +++++ .../subp_kinds/src/no_decls_called.adb | 2 +- .../subp_kinds/src/test_no_decls_called.adb | 1 - .../src/call_with_decls.adb | 2 +- .../src/test_with_decls_called.adb | 1 - tools/gnatcov/instrument-ada_unit.adb | 4 ++- 16 files changed, 100 insertions(+), 16 deletions(-) create mode 100644 testsuite/tests/287-function_call_cov/static_call/src/discriminant.adb create mode 100644 testsuite/tests/287-function_call_cov/static_call/src/enum.adb create mode 100644 testsuite/tests/287-function_call_cov/static_call/src/test_discriminant.adb create mode 100644 testsuite/tests/287-function_call_cov/static_call/src/test_enum.adb create mode 100644 testsuite/tests/287-function_call_cov/static_call/test.py diff --git a/testsuite/tests/287-function_call_cov/contracts/src/test_contracts_not_called.adb b/testsuite/tests/287-function_call_cov/contracts/src/test_contracts_not_called.adb index d4a40a87d..969b210ed 100644 --- a/testsuite/tests/287-function_call_cov/contracts/src/test_contracts_not_called.adb +++ b/testsuite/tests/287-function_call_cov/contracts/src/test_contracts_not_called.adb @@ -11,6 +11,6 @@ end Test_Contracts_Not_Called; -- /pre/ l- ## a- --# contracts.adb -- /foo/ l- ## f- --- /t/ l- ## s-,f-,c- +-- /t/ l- ## s-,f- -- /assert/ l- ## s-,c-,c- -- /null/ l- ## s- diff --git a/testsuite/tests/287-function_call_cov/dotted_type/src/make_call.adb b/testsuite/tests/287-function_call_cov/dotted_type/src/make_call.adb index d699a964a..f3609a04b 100644 --- a/testsuite/tests/287-function_call_cov/dotted_type/src/make_call.adb +++ b/testsuite/tests/287-function_call_cov/dotted_type/src/make_call.adb @@ -45,7 +45,7 @@ begin /= 0 -- # deci and then -- # deci Pkg5.F.B) -- # p_pkg5 - and then False -- # p_call + and then False -- # false then null; -- # null end if; diff --git a/testsuite/tests/287-function_call_cov/dotted_type/src/test_dotted_type.adb b/testsuite/tests/287-function_call_cov/dotted_type/src/test_dotted_type.adb index de40b6dd1..a578eff5a 100644 --- a/testsuite/tests/287-function_call_cov/dotted_type/src/test_dotted_type.adb +++ b/testsuite/tests/287-function_call_cov/dotted_type/src/test_dotted_type.adb @@ -21,8 +21,8 @@ end Test_Dotted_Type; -- /d_nf1/ l! ## 0 -- /deci/ l! ## 0 -- /v_dec/ l- ## 0 --- /p_call/ l! ## c- -- /p_pkg5/ l! ## c? +-- /false/ l+ ## 0 -- /null/ l- ## s- --# pkg4.ads -- /decl/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/nested_calls/src/nested.adb b/testsuite/tests/287-function_call_cov/nested_calls/src/nested.adb index f665cfa67..993f35792 100644 --- a/testsuite/tests/287-function_call_cov/nested_calls/src/nested.adb +++ b/testsuite/tests/287-function_call_cov/nested_calls/src/nested.adb @@ -26,7 +26,7 @@ begin B -- # v_call (B -- # v_call (B), -- # v_call - False); -- # v_call + False); -- # v_false end if; end Nested; diff --git a/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb b/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb index 32be588b0..41b5c2847 100644 --- a/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb +++ b/testsuite/tests/287-function_call_cov/nested_calls/src/test_nested.adb @@ -10,9 +10,10 @@ begin end Test_Nested; --# nested.adb --- /stmt/ l+ ## 0 --- /fun/ l+ ## 0 --- /call/ l+ ## 0 --- /if/ l! ## dT- --- /v_stmt/ l- ## s- --- /v_call/ l- ## s=>s-, f=>c- +-- /stmt/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /call/ l+ ## 0 +-- /if/ l! ## dT- +-- /v_stmt/ l- ## s- +-- /v_call/ l- ## f=>c- +-- /v_false/ l- ## 0 diff --git a/testsuite/tests/287-function_call_cov/protected_body/src/test_not_called.adb b/testsuite/tests/287-function_call_cov/protected_body/src/test_not_called.adb index 0eeca46e0..9f264fedc 100644 --- a/testsuite/tests/287-function_call_cov/protected_body/src/test_not_called.adb +++ b/testsuite/tests/287-function_call_cov/protected_body/src/test_not_called.adb @@ -15,6 +15,6 @@ end Test_Not_Called; -- /decl/ l+ ## 0 --# foo.adb -- /fun/ l- ## f- --- /expr_fun/ l- ## s=>s-, f=>s-,f-,c- +-- /expr_fun/ l- ## s=>s-, f=>s-,f- -- /call_stmt/ f=>l- ## s=>s-, f=>s-,c- -- /stmt/ l- ## s- diff --git a/testsuite/tests/287-function_call_cov/static_call/src/discriminant.adb b/testsuite/tests/287-function_call_cov/static_call/src/discriminant.adb new file mode 100644 index 000000000..2c058fd74 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/static_call/src/discriminant.adb @@ -0,0 +1,14 @@ +pragma Ada_2012; + +procedure Discriminant is + type Color is (Red, Green, Blue, Not_On); -- # a + + type Disc_Rec (Disc : Color) is -- # a + record + null; -- # a + end record; + + My_Rec : constant Disc_Rec := (Disc => Red); -- # a +begin + null; +end Discriminant; diff --git a/testsuite/tests/287-function_call_cov/static_call/src/enum.adb b/testsuite/tests/287-function_call_cov/static_call/src/enum.adb new file mode 100644 index 000000000..b7d24e784 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/static_call/src/enum.adb @@ -0,0 +1,31 @@ +pragma Ada_2012; + +procedure Enum is + type Color is (Red, Green, Blue, Not_On); -- # decl + + Pixel_1 : Color := Red; -- # decl + Pixel_2 : Color := Green; -- # decl + Pixel_3 : Color := Blue; -- # decl + + Nb_Red : Integer := 0; -- # decl +begin + + -- In an if statement + if Pixel_1 not in Red then -- # if + Nb_Red := Nb_Red + 1; -- # stmt_no + end if; + + -- In a case expression + Nb_Red := Nb_Red + -- # stmt_yes + (case Pixel_2 is -- # stmt_yes + when Red => 1, -- # stmt_yes + when Green .. Green => 0, -- # stmt_yes + when Blue | Not_On => 0); -- # stmt_yes + + -- In a case statement + case Pixel_3 is -- # stmt_yes + when Red => Nb_Red := Nb_Red + 1; -- # stmt_no + when Green .. Green => null; -- # stmt_no + when Blue | Not_On => null; -- # stmt_yes + end case; +end Enum; diff --git a/testsuite/tests/287-function_call_cov/static_call/src/test_discriminant.adb b/testsuite/tests/287-function_call_cov/static_call/src/test_discriminant.adb new file mode 100644 index 000000000..6b6b9832d --- /dev/null +++ b/testsuite/tests/287-function_call_cov/static_call/src/test_discriminant.adb @@ -0,0 +1,14 @@ +with Discriminant; + +-- Test that the use of enum values, which are calls, are not instrumented as +-- calls. This is checked with an enum value used in a record discriminant +-- that needs it to be a static value. Instrumenting it as a call would +-- result in a compilation error as they would no longer be static. + +procedure Test_Discriminant is +begin + Discriminant; +end Test_Discriminant; + +--# discriminant.adb +-- /a/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/static_call/src/test_enum.adb b/testsuite/tests/287-function_call_cov/static_call/src/test_enum.adb new file mode 100644 index 000000000..1e1825f09 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/static_call/src/test_enum.adb @@ -0,0 +1,17 @@ +with Enum; + +-- Test that the use of enum values, which are calls, are not instrumented as +-- calls. This is checked with enum values used in case statements that need +-- them to be static values. Instrumenting them as calls would result in a +-- compilation error as they would no longer be static. + +procedure Test_Enum is +begin + Enum; +end Test_Enum; + +--# enum.adb +-- /decl/ l+ ## 0 +-- /if/ l! ## dT- +-- /stmt_no/ l- ## s- +-- /stmt_yes/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/static_call/test.py b/testsuite/tests/287-function_call_cov/static_call/test.py new file mode 100644 index 000000000..a1fa74db5 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/static_call/test.py @@ -0,0 +1,7 @@ +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_called.adb index fa5cebc11..ab0bc850a 100644 --- a/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_called.adb +++ b/testsuite/tests/287-function_call_cov/subp_kinds/src/no_decls_called.adb @@ -101,7 +101,7 @@ begin -- statement violations. Proc; -- # v_stmt Proc_Param (Dummy); -- # v_stmt - Proc_Param (Dummy, False); -- # v_cstmt + Proc_Param (Dummy, False); -- # v_stmt Over (5); -- # v_stmt Over (1, 2); -- # v_stmt end if; diff --git a/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_called.adb index 4cfc67160..aa8a55147 100644 --- a/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_called.adb +++ b/testsuite/tests/287-function_call_cov/subp_kinds/src/test_no_decls_called.adb @@ -17,6 +17,5 @@ end Test_No_Decls_Called; -- /if_cond/ l! ## dT- -- /v_dummy/ l- ## s- -- /v_stmt/ l- ## s-,c- --- /v_cstmt/ l- ## s-,c-,c- -- /v_call/ l- ## c- -- /v_scall/ l- ## s=>s-, f=>s-,c- diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/call_with_decls.adb b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/call_with_decls.adb index c2a41f8ba..d12e80d39 100644 --- a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/call_with_decls.adb +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/call_with_decls.adb @@ -53,7 +53,7 @@ begin -- statement violations. Proc; -- # v_cstmt Proc_Param (Dummy); -- # v_cstmt - Proc_Param (Dummy, False); -- # v_false + Proc_Param (Dummy, False); -- # v_cstmt Over (5); -- # v_cstmt Over (1, 2); -- # v_cstmt end if; diff --git a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_called.adb b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_called.adb index 7dc24d6fb..150cbd682 100644 --- a/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_called.adb +++ b/testsuite/tests/287-function_call_cov/subp_kinds_with_decls/src/test_with_decls_called.adb @@ -16,7 +16,6 @@ end Test_With_Decls_Called; -- /v_fun/ l- ## c- -- /v_sfun/ l- ## s-,c- -- /v_cstmt/ l- ## s-,c- --- /v_false/ l- ## s-,c-,c- --# with_decls.ads -- /stmt/ l+ ## 0 --# with_decls.adb diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 2ee5b1458..77723a634 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6145,7 +6145,9 @@ package body Instrument.Ada_Unit is is Full_Call_Node : Ada_Node; begin - if Is_Call_Leaf (Node) then + if Is_Call_Leaf (Node) + and then not Is_Static_Expr (Node.As_Expr) + then Full_Call_Node := Full_Call (Node); -- Skip calls that are direct children of call statements From 423af4587a629f401b7dc6a48461cb1d984a20ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 10 Dec 2024 15:32:28 +0100 Subject: [PATCH 1046/1483] Mark explicit deref as uninstrumented for call cov --- .../dotted_name/src/deref.adb | 19 +++++++++++++++++++ .../dotted_name/src/test_deref.adb | 16 ++++++++++++++++ .../287-function_call_cov/dotted_name/test.py | 6 +++++- .../287-function_call_cov/dotted_type/test.py | 1 - tools/gnatcov/instrument-ada_unit.adb | 3 ++- 5 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/287-function_call_cov/dotted_name/src/deref.adb create mode 100644 testsuite/tests/287-function_call_cov/dotted_name/src/test_deref.adb diff --git a/testsuite/tests/287-function_call_cov/dotted_name/src/deref.adb b/testsuite/tests/287-function_call_cov/dotted_name/src/deref.adb new file mode 100644 index 000000000..d929df0e7 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/src/deref.adb @@ -0,0 +1,19 @@ +pragma Ada_2012; + +-- Dotted_Name in the context of an explicit dereference + +procedure Deref is + + type String_Access is access String; -- # ok + + S : String_Access := new String'("Hello World!"); -- # ok + + Function Id (S : String_Access) return String_Access is (S); -- # ok + + Dummy : String := Id (S).all; -- # deref1 + F : Boolean := False; -- # ok +begin + if F then -- # if + Dummy := Id (S).all; -- # deref2 + end if; +end Deref; diff --git a/testsuite/tests/287-function_call_cov/dotted_name/src/test_deref.adb b/testsuite/tests/287-function_call_cov/dotted_name/src/test_deref.adb new file mode 100644 index 000000000..24fe52633 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/dotted_name/src/test_deref.adb @@ -0,0 +1,16 @@ +with Deref; + +-- LIMITATION +-- For now, gnatcov is unable to instrument calles as prefix of dotted names, +-- which includes explicit dereferences. + +procedure Test_Deref is +begin + Deref; +end Test_Deref; + +--# deref.adb +-- /ok/ l+ ## 0 +-- /deref1/ l? ## c? +-- /if/ l! ## dT- +-- /deref2/ l- ## s-,c? diff --git a/testsuite/tests/287-function_call_cov/dotted_name/test.py b/testsuite/tests/287-function_call_cov/dotted_name/test.py index 9d1fe305b..91e3738b6 100644 --- a/testsuite/tests/287-function_call_cov/dotted_name/test.py +++ b/testsuite/tests/287-function_call_cov/dotted_name/test.py @@ -2,5 +2,9 @@ from SCOV.tctl import CAT from SUITE.context import thistest -TestCase(category=CAT.mcdc, fun_call_lvl=True).run() +TestCase( + category=CAT.mcdc, + fun_call_lvl=True, + tolerate_messages=(r"cannot instrument calls within dotted names"), +).run() thistest.result() diff --git a/testsuite/tests/287-function_call_cov/dotted_type/test.py b/testsuite/tests/287-function_call_cov/dotted_type/test.py index cd617b2ad..91e3738b6 100644 --- a/testsuite/tests/287-function_call_cov/dotted_type/test.py +++ b/testsuite/tests/287-function_call_cov/dotted_type/test.py @@ -2,7 +2,6 @@ from SCOV.tctl import CAT from SUITE.context import thistest - TestCase( category=CAT.mcdc, fun_call_lvl=True, diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 77723a634..03eafde95 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6169,7 +6169,8 @@ package body Instrument.Ada_Unit is Return_Type : Base_Type_Decl := No_Base_Type_Decl; Needs_Qualified_Expr : constant Boolean := - Full_Call_Node.Parent.Kind = Ada_Dotted_Name; + Full_Call_Node.Parent.Kind in + Ada_Dotted_Name | Ada_Explicit_Deref; -- We only need to turn the if-expression into a qualified -- when the parent of the call and its parent are both -- dotted named. For example, with A and B packages, F a From 8c18a2cf1f46eb34082c520d06cae644f2a5a167 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 9 Dec 2024 14:45:35 +0000 Subject: [PATCH 1047/1483] Instrument: add debug traces for objdir cleaning --- .../tests/instr-cov/logging/baseline.txt | 21 ++++++++ testsuite/tests/instr-cov/logging/harness.gpr | 6 +++ testsuite/tests/instr-cov/logging/mylib.gpr | 4 ++ .../instr-cov/logging/mylib_extended.gpr | 4 ++ .../instr-cov/logging/src-harness/harness.adb | 18 +++++++ .../instr-cov/logging/src-harness/harness.ads | 3 ++ .../instr-cov/logging/src-mylib/mylib.adb | 12 +++++ .../instr-cov/logging/src-mylib/mylib.ads | 3 ++ .../logging/src-mylib_extended/mylib.ads | 4 ++ .../instr-cov/logging/src-tests/test1.adb | 8 +++ .../instr-cov/logging/src-tests/test2.adb | 8 +++ testsuite/tests/instr-cov/logging/test.py | 50 +++++++++++++++++++ testsuite/tests/instr-cov/logging/tests.gpr | 8 +++ tools/gnatcov/instrument-clean_objdirs.adb | 32 ++++++++++-- tools/gnatcov/instrument.ads | 6 +++ 15 files changed, 182 insertions(+), 5 deletions(-) create mode 100644 testsuite/tests/instr-cov/logging/baseline.txt create mode 100644 testsuite/tests/instr-cov/logging/harness.gpr create mode 100644 testsuite/tests/instr-cov/logging/mylib.gpr create mode 100644 testsuite/tests/instr-cov/logging/mylib_extended.gpr create mode 100644 testsuite/tests/instr-cov/logging/src-harness/harness.adb create mode 100644 testsuite/tests/instr-cov/logging/src-harness/harness.ads create mode 100644 testsuite/tests/instr-cov/logging/src-mylib/mylib.adb create mode 100644 testsuite/tests/instr-cov/logging/src-mylib/mylib.ads create mode 100644 testsuite/tests/instr-cov/logging/src-mylib_extended/mylib.ads create mode 100644 testsuite/tests/instr-cov/logging/src-tests/test1.adb create mode 100644 testsuite/tests/instr-cov/logging/src-tests/test2.adb create mode 100644 testsuite/tests/instr-cov/logging/test.py create mode 100644 testsuite/tests/instr-cov/logging/tests.gpr diff --git a/testsuite/tests/instr-cov/logging/baseline.txt b/testsuite/tests/instr-cov/logging/baseline.txt new file mode 100644 index 000000000..8f50ca3f9 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/baseline.txt @@ -0,0 +1,21 @@ +info: creating output path [TMP]/obj/tests/ +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Mylib + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/mylib.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/mylib/mylib-gnatcov-instr +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Mylib_Extended + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/mylib_extended.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/mylib_extended/mylib_extended-gnatcov-instr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it does not exist +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Harness + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/harness.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/harness/harness-gnatcov-instr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it is an externally built project +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Tests + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/tests.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/tests/tests-gnatcov-instr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it does not exist +Coverage instrumentation + [Ada] mylib +Main instrumentation + [Ada] test2 + [Ada] test1 diff --git a/testsuite/tests/instr-cov/logging/harness.gpr b/testsuite/tests/instr-cov/logging/harness.gpr new file mode 100644 index 000000000..1bc47f73d --- /dev/null +++ b/testsuite/tests/instr-cov/logging/harness.gpr @@ -0,0 +1,6 @@ +project Harness is + + for Source_Dirs use ("src-harness"); + for Object_Dir use "obj/harness"; + for Externally_Built use external ("HARNESS_BUILT", "true"); +end Harness; diff --git a/testsuite/tests/instr-cov/logging/mylib.gpr b/testsuite/tests/instr-cov/logging/mylib.gpr new file mode 100644 index 000000000..716d847bd --- /dev/null +++ b/testsuite/tests/instr-cov/logging/mylib.gpr @@ -0,0 +1,4 @@ +project Mylib is + for Source_Dirs use ("src-mylib"); + for Object_Dir use "obj/mylib"; +end Mylib; diff --git a/testsuite/tests/instr-cov/logging/mylib_extended.gpr b/testsuite/tests/instr-cov/logging/mylib_extended.gpr new file mode 100644 index 000000000..3d287687d --- /dev/null +++ b/testsuite/tests/instr-cov/logging/mylib_extended.gpr @@ -0,0 +1,4 @@ +project Mylib_Extended extends "mylib.gpr" is + for Source_Dirs use ("src-mylib_extended"); + for Object_Dir use "obj/mylib_extended"; +end Mylib_Extended; diff --git a/testsuite/tests/instr-cov/logging/src-harness/harness.adb b/testsuite/tests/instr-cov/logging/src-harness/harness.adb new file mode 100644 index 000000000..6a7980d9b --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-harness/harness.adb @@ -0,0 +1,18 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Harness is + + ------------------ + -- Assert_Equal -- + ------------------ + + procedure Assert_Equal (Label : String; Expected, Actual : Integer) is + begin + if Expected = Actual then + Put_Line ("OK " & Label); + else + Put_Line ("FAIL " & Label); + end if; + end Assert_Equal; + +end Harness; diff --git a/testsuite/tests/instr-cov/logging/src-harness/harness.ads b/testsuite/tests/instr-cov/logging/src-harness/harness.ads new file mode 100644 index 000000000..233aa8312 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-harness/harness.ads @@ -0,0 +1,3 @@ +package Harness is + procedure Assert_Equal (Label : String; Expected, Actual : Integer); +end Harness; diff --git a/testsuite/tests/instr-cov/logging/src-mylib/mylib.adb b/testsuite/tests/instr-cov/logging/src-mylib/mylib.adb new file mode 100644 index 000000000..60555e524 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-mylib/mylib.adb @@ -0,0 +1,12 @@ +package body Mylib is + + ---------- + -- Next -- + ---------- + + function Next (I : Integer) return Integer is + begin + return I + 1; + end Next; + +end Mylib; diff --git a/testsuite/tests/instr-cov/logging/src-mylib/mylib.ads b/testsuite/tests/instr-cov/logging/src-mylib/mylib.ads new file mode 100644 index 000000000..eaef390b9 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-mylib/mylib.ads @@ -0,0 +1,3 @@ +package Mylib is + function Next (I : Integer) return Integer; +end Mylib; diff --git a/testsuite/tests/instr-cov/logging/src-mylib_extended/mylib.ads b/testsuite/tests/instr-cov/logging/src-mylib_extended/mylib.ads new file mode 100644 index 000000000..4b2928d71 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-mylib_extended/mylib.ads @@ -0,0 +1,4 @@ +package Mylib is + function Next (I : Integer) return Integer; + function Prev (I : Integer) return Integer is (I - 1); +end Mylib; diff --git a/testsuite/tests/instr-cov/logging/src-tests/test1.adb b/testsuite/tests/instr-cov/logging/src-tests/test1.adb new file mode 100644 index 000000000..98c282ae3 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-tests/test1.adb @@ -0,0 +1,8 @@ +with Harness; +with Mylib; + +procedure Test1 is +begin + Harness.Assert_Equal ("Next (0)", 1, Mylib.Next (0)); + Harness.Assert_Equal ("Next (1)", 2, Mylib.Next (1)); +end Test1; diff --git a/testsuite/tests/instr-cov/logging/src-tests/test2.adb b/testsuite/tests/instr-cov/logging/src-tests/test2.adb new file mode 100644 index 000000000..fbd995e98 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-tests/test2.adb @@ -0,0 +1,8 @@ +with Harness; +with Mylib; + +procedure Test2 is +begin + Harness.Assert_Equal ("Prev (1)", 0, Mylib.Prev (1)); + Harness.Assert_Equal ("Prev (2)", 1, Mylib.Prev (2)); +end Test2; diff --git a/testsuite/tests/instr-cov/logging/test.py b/testsuite/tests/instr-cov/logging/test.py new file mode 100644 index 000000000..b1c802cb7 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/test.py @@ -0,0 +1,50 @@ +""" +Check that "gnatcov instrument" produces the expected debug logging. +""" + +import glob +import os.path + +from e3.fs import mkdir, sync_tree +from e3.testsuite.driver.diff import Substitute + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + + +# Copy projects and their sources in a temporary directory +tmp = Wdir("tmp_") +for pattern in ["*.gpr", "src-*"]: + for item in glob.glob(os.path.join("..", pattern)): + sync_tree(item, os.path.basename(item)) + +# Create an instrumentation output directories to exercise +# INSTRUMENT_CLEAN_OBJDIRS variations. +for project in ["mylib", "harness"]: + mkdir(os.path.join("obj", project, f"{project}-gnatcov-instr")) + +# Run "gnatcov instrument" and check its output against our logging baselines +log = "instr.txt" +xcov( + [ + "instrument", + "-Ptests.gpr", + "-cstmt", + "--projects=mylib", + "--log=instrument_clean_objdirs", + ], + out=log, +) +thistest.fail_if_diff( + baseline_file="../baseline.txt", + actual_file=log, + failure_message='"gnatcov instrument" output', + output_refiners=[ + Substitute(os.getcwd(), "[TMP]"), + Substitute("\\", "/"), + ], + ignore_white_chars=False, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/logging/tests.gpr b/testsuite/tests/instr-cov/logging/tests.gpr new file mode 100644 index 000000000..dbb8a33c3 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/tests.gpr @@ -0,0 +1,8 @@ +with "harness"; +with "mylib_extended"; + +project Tests is + for Source_Dirs use ("src-tests"); + for Object_Dir use "obj/tests"; + for Main use ("test1.adb", "test2.adb"); +end Tests; diff --git a/tools/gnatcov/instrument-clean_objdirs.adb b/tools/gnatcov/instrument-clean_objdirs.adb index 6a90bce6d..26138d92b 100644 --- a/tools/gnatcov/instrument-clean_objdirs.adb +++ b/tools/gnatcov/instrument-clean_objdirs.adb @@ -19,6 +19,7 @@ with Ada.Directories; use Ada.Directories; with GNATCOLL.Projects; use GNATCOLL.Projects; +with GNATCOLL.VFS; use GNATCOLL.VFS; with Instrument.Common; use Instrument.Common; with Outputs; use Outputs; @@ -39,15 +40,32 @@ procedure Instrument.Clean_Objdirs is ------------------ procedure Clean_Subdir (Project : Project_Type) is - Output_Dir : constant String := Project_Output_Dir (Project); + Output_Dir : constant String := Project_Output_Dir (Project); + Has_Output_Dir : Boolean := True; begin + Clean_Objdirs_Trace.Increase_Indent ("Processing " & Project.Name); + Clean_Objdirs_Trace.Trace + ("GPR file: " & (+Project.Project_Path.Full_Name)); + -- Some projects don't have an object directory: ignore them as there is -- nothing to do. - if Output_Dir'Length = 0 - or else not Exists (Output_Dir) - or else Kind (Output_Dir) /= Directory - then + if Output_Dir'Length = 0 then + Has_Output_Dir := False; + Clean_Objdirs_Trace.Trace ("no object directory"); + else + Clean_Objdirs_Trace.Trace ("output directory: " & Output_Dir); + if not Exists (Output_Dir) then + Has_Output_Dir := False; + Clean_Objdirs_Trace.Trace ("it does not exist"); + elsif Kind (Output_Dir) /= Directory then + Has_Output_Dir := False; + Clean_Objdirs_Trace.Trace ("it is not a directory"); + end if; + end if; + + if not Has_Output_Dir then + Clean_Objdirs_Trace.Decrease_Indent; return; end if; @@ -70,6 +88,8 @@ procedure Instrument.Clean_Objdirs is -- clear lead on how to address such problems. if Project.Externally_Built then + Clean_Objdirs_Trace.Trace ("it is an externally built project"); + if not Externally_Built_Projects_Processing_Enabled and then Has_Regular_Files (Output_Dir) then @@ -86,10 +106,12 @@ procedure Instrument.Clean_Objdirs is -- We should never try to modify externally built projects, so do not -- remove their instrumented source directory. + Clean_Objdirs_Trace.Decrease_Indent; return; end if; Delete_Tree (Directory => Output_Dir); + Clean_Objdirs_Trace.Decrease_Indent; end Clean_Subdir; ----------------------- diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index da5d77c1c..9da8cd5c2 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -27,6 +27,7 @@ with Types; use Types; with Checkpoints; use Checkpoints; with Files_Handling; +with Logging; with SC_Obligations; use SC_Obligations; with Strings; use Strings; with Subprocesses; use Subprocesses; @@ -35,6 +36,11 @@ with Traces_Source; use Traces_Source; package Instrument is + Clean_Objdirs_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("INSTRUMENT_CLEAN_OBJDIRS"); + -- Trace to show details about how object directories in GPR projects are + -- cleaned. + package GPR renames GNATCOLL.Projects; use type Ada.Containers.Count_Type; From f6040d0bca9097ca0275af4f62b5ce5e73a59503 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 9 Dec 2024 16:00:05 +0000 Subject: [PATCH 1048/1483] insturment-ada-unit.adb: minor reformatting --- tools/gnatcov/instrument-ada_unit.adb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 03eafde95..57d7bc683 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -11144,9 +11144,7 @@ package body Instrument.Ada_Unit is Missing_Src_Reporter_Access (Self.Event_Handler.Unchecked_Get).all; -- Handle to the event handler we use to report missing source files; - Basename : constant String := - Ada.Directories.Simple_Name (Filename); - + Basename : constant String := Ada.Directories.Simple_Name (Filename); begin -- Instrument the file only if it is a file of interest From 338e5cbc0bae37c68d0161cb83e0d20d1a178739 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 9 Dec 2024 16:19:13 +0000 Subject: [PATCH 1049/1483] insturment-c.adb: minor reformattings --- tools/gnatcov/instrument-c.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index eec7d124c..ba17340ce 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -4271,7 +4271,7 @@ package body Instrument.C is (Main => Dummy_Main, Manual => True, Prj_Name => Prj.Prj_Name); Reset_Procedure : constant String := Reset_Procedure_Symbol (Prj.Prj_Name); - Extern_Prefix : constant String := + Extern_Prefix : constant String := C_Family_Instrumenter_Type'Class (Self).Extern_Prefix; Annots : constant Instr_Annotation_Map := @@ -5183,7 +5183,7 @@ package body Instrument.C is Prj : Prj_Desc) return Compilation_Unit is CU_Name : constant Compilation_Unit := - (Language => File_Based_Language, + (Language => File_Based_Language, Unit_Name => +New_File (Prj, From 2220f7e60164e385d11770aec321847bf4e7275b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 9 Dec 2024 20:41:41 +0000 Subject: [PATCH 1050/1483] Instrument: add debug traces for written source files --- .../tests/instr-cov/file-context/test.py | 6 +- .../instr-cov/logging/baseline-my_tool.txt | 19 ++ .../instr-cov/logging/baseline-tests.txt | 58 ++++ .../tests/instr-cov/logging/baseline.txt | 21 -- testsuite/tests/instr-cov/logging/my_tool.gpr | 6 + testsuite/tests/instr-cov/logging/mylib.gpr | 1 + .../instr-cov/logging/src-my_tool/my_tool.cpp | 8 + .../instr-cov/logging/src-mylib/mylib.ads | 5 + .../instr-cov/logging/src-mylib/mylib_ext.c | 5 + .../logging/src-mylib_extended/mylib.ads | 5 + .../tests/instr-cov/logging/src-tests/test3.c | 18 ++ testsuite/tests/instr-cov/logging/test.opt | 1 + testsuite/tests/instr-cov/logging/test.py | 133 ++++++++-- testsuite/tests/instr-cov/logging/tests.gpr | 3 +- tools/gnatcov/instrument-ada_unit.adb | 250 +++++++++++------- tools/gnatcov/instrument-c.adb | 46 +++- tools/gnatcov/instrument-common.ads | 3 + tools/gnatcov/instrument.ads | 4 + 18 files changed, 440 insertions(+), 152 deletions(-) create mode 100644 testsuite/tests/instr-cov/logging/baseline-my_tool.txt create mode 100644 testsuite/tests/instr-cov/logging/baseline-tests.txt delete mode 100644 testsuite/tests/instr-cov/logging/baseline.txt create mode 100644 testsuite/tests/instr-cov/logging/my_tool.gpr create mode 100644 testsuite/tests/instr-cov/logging/src-my_tool/my_tool.cpp create mode 100644 testsuite/tests/instr-cov/logging/src-mylib/mylib_ext.c create mode 100644 testsuite/tests/instr-cov/logging/src-tests/test3.c create mode 100644 testsuite/tests/instr-cov/logging/test.opt diff --git a/testsuite/tests/instr-cov/file-context/test.py b/testsuite/tests/instr-cov/file-context/test.py index c209fe38c..fe6812d99 100644 --- a/testsuite/tests/instr-cov/file-context/test.py +++ b/testsuite/tests/instr-cov/file-context/test.py @@ -56,7 +56,7 @@ def do_instr(label, args): line for line in lines_of(log) if ( - line.startswith("[GNATCOV.MISC] Instrumenting ") + line.startswith("[GNATCOV.INSTRUMENT_SOURCES] Instrumenting ") or line.startswith("warning: ") ) ] @@ -64,10 +64,10 @@ def do_instr(label, args): '"gnatcov instrument" output', "\n".join( [ - "[GNATCOV.MISC] Instrumenting main.adb", + "[GNATCOV.INSTRUMENT_SOURCES] Instrumenting main.adb", "warning: Cannot find required source file: missing_a.ads", "warning: Cannot find required source file: missing_b.ads", - "[GNATCOV.MISC] Instrumenting pkg.ads", + "[GNATCOV.INSTRUMENT_SOURCES] Instrumenting pkg.ads", ] ), "\n".join(actual_lines), diff --git a/testsuite/tests/instr-cov/logging/baseline-my_tool.txt b/testsuite/tests/instr-cov/logging/baseline-my_tool.txt new file mode 100644 index 000000000..c3d1df059 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/baseline-my_tool.txt @@ -0,0 +1,19 @@ +info: creating output path [TMP]/obj/my_tool/ +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing My_Tool + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/my_tool.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/my_tool/my_tool-gnatcov-instr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it does not exist +Coverage instrumentation + [C++] my_tool.cpp +[GNATCOV.INSTRUMENT_SOURCES] Writing C++ buffer unit [TMP]/obj/my_tool/my_tool-gnatcov-instr/gcvrt_b_[HASH#1].cpp + [GNATCOV.INSTRUMENT_SOURCES] Project: My_Tool + [GNATCOV.INSTRUMENT_SOURCES] For files: + [GNATCOV.INSTRUMENT_SOURCES] * [TMP]/src-my_tool/my_tool.cpp +Main instrumentation + [C++] my_tool.cpp +[GNATCOV.INSTRUMENT_SOURCES] Writing C++ dump helper unit [TMP]/obj/my_tool/my_tool-gnatcov-instr/gcvrt_d_[HASH#2].cpp + [GNATCOV.INSTRUMENT_SOURCES] Project: My_Tool + [GNATCOV.INSTRUMENT_SOURCES] Filename: [TMP]/obj/my_tool/my_tool-gnatcov-instr/gcvrt_d_[HASH#2].cpp + [GNATCOV.INSTRUMENT_SOURCES] For main: [TMP]/obj/my_tool/my_tool-gnatcov-instr/my_tool.cpp +[GNATCOV.INSTRUMENT_SOURCES] Writing C++ buffer list unit [TMP]/obj/my_tool/my_tool-gnatcov-instr/gcvrtc-my_tool.cpp + [GNATCOV.INSTRUMENT_SOURCES] Project: My_Tool diff --git a/testsuite/tests/instr-cov/logging/baseline-tests.txt b/testsuite/tests/instr-cov/logging/baseline-tests.txt new file mode 100644 index 000000000..69e788a18 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/baseline-tests.txt @@ -0,0 +1,58 @@ +info: creating output path [TMP]/obj/tests/ +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Mylib + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/mylib.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/mylib/mylib-gnatcov-instr +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Mylib_Extended + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/mylib_extended.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/mylib_extended/mylib_extended-gnatcov-instr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it does not exist +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Harness + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/harness.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/harness/harness-gnatcov-instr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it is an externally built project +[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Tests + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/tests.gpr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/tests/tests-gnatcov-instr + [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it does not exist +Coverage instrumentation + [Ada] mylib +[GNATCOV.INSTRUMENT_SOURCES] Instrumenting mylib.ads +[GNATCOV.INSTRUMENT_SOURCES] Instrumenting mylib.adb +[GNATCOV.INSTRUMENT_SOURCES] Writing Ada buffer unit GCVRT.B[HASH#1] + [GNATCOV.INSTRUMENT_SOURCES] Project: Mylib + [GNATCOV.INSTRUMENT_SOURCES] Filename: gcvrt-b[HASH#1].ads + [GNATCOV.INSTRUMENT_SOURCES] For units: + [GNATCOV.INSTRUMENT_SOURCES] * mylib spec + [GNATCOV.INSTRUMENT_SOURCES] * mylib body +[GNATCOV.INSTRUMENT_SOURCES] Writing pure Ada buffer unit GCVRT.P[HASH#1] + [GNATCOV.INSTRUMENT_SOURCES] Project: Mylib + [GNATCOV.INSTRUMENT_SOURCES] Filename: [TMP]/obj/mylib_extended/mylib_extended-gnatcov-instr/gcvrt-p[HASH#1].ads + [GNATCOV.INSTRUMENT_SOURCES] For units: + [GNATCOV.INSTRUMENT_SOURCES] * mylib spec + [GNATCOV.INSTRUMENT_SOURCES] * mylib body + [C] mylib_ext.c +[GNATCOV.INSTRUMENT_SOURCES] Writing C buffer unit [TMP]/obj/mylib_extended/mylib_extended-gnatcov-instr/gcvrt_b_[HASH#2].c + [GNATCOV.INSTRUMENT_SOURCES] Project: Mylib + [GNATCOV.INSTRUMENT_SOURCES] For files: + [GNATCOV.INSTRUMENT_SOURCES] * [TMP]/src-mylib/mylib_ext.c +Main instrumentation + [Ada] test1 +[GNATCOV.INSTRUMENT_SOURCES] Writing Ada dump helper unit GCVRT.DB_[HASH#3] + [GNATCOV.INSTRUMENT_SOURCES] Project: Tests + [GNATCOV.INSTRUMENT_SOURCES] Spec filename: gcvrt-db_[HASH#3].ads + [GNATCOV.INSTRUMENT_SOURCES] Body filename: gcvrt-db_[HASH#3].adb + [GNATCOV.INSTRUMENT_SOURCES] For main: test1 body + [Ada] test2 +[GNATCOV.INSTRUMENT_SOURCES] Writing Ada dump helper unit GCVRT.DB_[HASH#4] + [GNATCOV.INSTRUMENT_SOURCES] Project: Tests + [GNATCOV.INSTRUMENT_SOURCES] Spec filename: gcvrt-db_[HASH#4].ads + [GNATCOV.INSTRUMENT_SOURCES] Body filename: gcvrt-db_[HASH#4].adb + [GNATCOV.INSTRUMENT_SOURCES] For main: test2 body + [C] test3.c +[GNATCOV.INSTRUMENT_SOURCES] Writing C dump helper unit [TMP]/obj/tests/tests-gnatcov-instr/gcvrt_d_[HASH#5].c + [GNATCOV.INSTRUMENT_SOURCES] Project: Tests + [GNATCOV.INSTRUMENT_SOURCES] Filename: [TMP]/obj/tests/tests-gnatcov-instr/gcvrt_d_[HASH#5].c + [GNATCOV.INSTRUMENT_SOURCES] For main: [TMP]/src-tests/test3.c +[GNATCOV.INSTRUMENT_SOURCES] Writing Ada buffer list unit GCVRT.Tests + [GNATCOV.INSTRUMENT_SOURCES] Project: Tests + [GNATCOV.INSTRUMENT_SOURCES] Filename: gcvrt-tests.ads diff --git a/testsuite/tests/instr-cov/logging/baseline.txt b/testsuite/tests/instr-cov/logging/baseline.txt deleted file mode 100644 index 8f50ca3f9..000000000 --- a/testsuite/tests/instr-cov/logging/baseline.txt +++ /dev/null @@ -1,21 +0,0 @@ -info: creating output path [TMP]/obj/tests/ -[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Mylib - [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/mylib.gpr - [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/mylib/mylib-gnatcov-instr -[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Mylib_Extended - [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/mylib_extended.gpr - [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/mylib_extended/mylib_extended-gnatcov-instr - [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it does not exist -[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Harness - [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/harness.gpr - [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/harness/harness-gnatcov-instr - [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it is an externally built project -[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Tests - [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/tests.gpr - [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/tests/tests-gnatcov-instr - [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] it does not exist -Coverage instrumentation - [Ada] mylib -Main instrumentation - [Ada] test2 - [Ada] test1 diff --git a/testsuite/tests/instr-cov/logging/my_tool.gpr b/testsuite/tests/instr-cov/logging/my_tool.gpr new file mode 100644 index 000000000..6794d38f4 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/my_tool.gpr @@ -0,0 +1,6 @@ +project My_Tool is + for Languages use ("C++"); + for Source_Dirs use ("src-my_tool"); + for Object_Dir use "obj/my_tool"; + for Main use ("my_tool.cpp"); +end My_Tool; diff --git a/testsuite/tests/instr-cov/logging/mylib.gpr b/testsuite/tests/instr-cov/logging/mylib.gpr index 716d847bd..b4f45385e 100644 --- a/testsuite/tests/instr-cov/logging/mylib.gpr +++ b/testsuite/tests/instr-cov/logging/mylib.gpr @@ -1,4 +1,5 @@ project Mylib is + for Languages use ("Ada", "C"); for Source_Dirs use ("src-mylib"); for Object_Dir use "obj/mylib"; end Mylib; diff --git a/testsuite/tests/instr-cov/logging/src-my_tool/my_tool.cpp b/testsuite/tests/instr-cov/logging/src-my_tool/my_tool.cpp new file mode 100644 index 000000000..e815d9e7d --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-my_tool/my_tool.cpp @@ -0,0 +1,8 @@ +#include + +int +main () +{ + std::cout << "Hello world" << std::endl; + return 0; +} diff --git a/testsuite/tests/instr-cov/logging/src-mylib/mylib.ads b/testsuite/tests/instr-cov/logging/src-mylib/mylib.ads index eaef390b9..0d34eadd9 100644 --- a/testsuite/tests/instr-cov/logging/src-mylib/mylib.ads +++ b/testsuite/tests/instr-cov/logging/src-mylib/mylib.ads @@ -1,3 +1,8 @@ package Mylib is + function Next (I : Integer) return Integer; + + function Identity (I : Integer) return Integer + with Import, Convention => C, External_Name => "mylib__identity"; + end Mylib; diff --git a/testsuite/tests/instr-cov/logging/src-mylib/mylib_ext.c b/testsuite/tests/instr-cov/logging/src-mylib/mylib_ext.c new file mode 100644 index 000000000..042960c32 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-mylib/mylib_ext.c @@ -0,0 +1,5 @@ +int +mylib__identity (int i) +{ + return i; +} diff --git a/testsuite/tests/instr-cov/logging/src-mylib_extended/mylib.ads b/testsuite/tests/instr-cov/logging/src-mylib_extended/mylib.ads index 4b2928d71..0350894d6 100644 --- a/testsuite/tests/instr-cov/logging/src-mylib_extended/mylib.ads +++ b/testsuite/tests/instr-cov/logging/src-mylib_extended/mylib.ads @@ -1,4 +1,9 @@ package Mylib is + function Next (I : Integer) return Integer; function Prev (I : Integer) return Integer is (I - 1); + + function Identity (I : Integer) return Integer + with Import, Convention => C, External_Name => "mylib__identity"; + end Mylib; diff --git a/testsuite/tests/instr-cov/logging/src-tests/test3.c b/testsuite/tests/instr-cov/logging/src-tests/test3.c new file mode 100644 index 000000000..c7932deb4 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/src-tests/test3.c @@ -0,0 +1,18 @@ +#include + +extern int mylib__identity (int); + +static void +assert_equal (const char *label, int expected, int actual) +{ + const char *status = (expected == actual) ? "OK " : "FAIL"; + printf ("%s %s\n", status, label); +} + +int +main (void) +{ + assert_equal ("Identity (0)", 0, mylib__identity (0)); + assert_equal ("Identity (1)", 1, mylib__identity (1)); + return 0; +} diff --git a/testsuite/tests/instr-cov/logging/test.opt b/testsuite/tests/instr-cov/logging/test.opt new file mode 100644 index 000000000..4cd5a9881 --- /dev/null +++ b/testsuite/tests/instr-cov/logging/test.opt @@ -0,0 +1 @@ +!C++ DEAD C++ toolchain required to instrument C++ sources diff --git a/testsuite/tests/instr-cov/logging/test.py b/testsuite/tests/instr-cov/logging/test.py index b1c802cb7..c99f36fe9 100644 --- a/testsuite/tests/instr-cov/logging/test.py +++ b/testsuite/tests/instr-cov/logging/test.py @@ -2,11 +2,14 @@ Check that "gnatcov instrument" produces the expected debug logging. """ +from __future__ import annotations + import glob import os.path +import re from e3.fs import mkdir, sync_tree -from e3.testsuite.driver.diff import Substitute +from e3.testsuite.driver.diff import OutputRefiner, Substitute from SUITE.context import thistest from SUITE.cutils import Wdir @@ -24,27 +27,113 @@ for project in ["mylib", "harness"]: mkdir(os.path.join("obj", project, f"{project}-gnatcov-instr")) + +class HashRefiner(OutputRefiner): + """Output refiner to hide hashes from the instrumented files. + + Actual hashes are not portable as they vary depending on the absolute path + for original source files. + """ + + hash_re = re.compile("z([0-9a-f]{8})") + + def __init__(self): + self.map = {} + + def repl(self, match): + hash_value = match.group(0) + try: + return self.map[hash_value] + except KeyError: + result = f"[HASH#{len(self.map) + 1}]" + self.map[hash_value] = result + return result + + def refine(self, output): + return self.hash_re.sub(self.repl, output) + + +class SortByFiles(OutputRefiner): + """Output refiner to sort lines by instrumented source file. + + The order in which "gnatcov instrument" processes units is not specified, + and varies in practice. This refiner reorders logs to have stable + baselines. + """ + + def refine(self, output): + result = [] + + # When processing a section that contains logs for a list of source + # files ("Coverage instrumentation" or "Main instrumentation"), + # "by_file" maps seen filenames to the corresponding list of log lines + # while "current_file" designates the last file seen for that section. + by_file = None + current_file = None + + def flush_files(): + """Append all log lines for files seen so far to result.""" + if by_file is None: + return + for _, lines in sorted(by_file.items()): + result.extend(lines) + + for line in output.splitlines(): + if line in ("Coverage instrumentation", "Main instrumentation"): + # This line starts a new section: flush log lines for the + # previous section (if any) and reset "by_file" and + # "current_file" to be ready for the new section. + flush_files() + by_file = {} + current_file = None + result.append(line) + elif by_file is None: + # No section being processed: just forward this log line + result.append(line) + else: + # If this line marks the start of processing for a new source + # file, set "current_file" accordingly and start a new log line + # for it. + chunks = line.split() + if len(chunks) == 2 and chunks[0] in ("[Ada]", "[C]", "[C++]"): + current_file = chunks[1] + assert current_file not in by_file + by_file[current_file] = [line] + else: + by_file[current_file].append(line) + flush_files() + + return "".join(f"{line}\n" for line in result) + + # Run "gnatcov instrument" and check its output against our logging baselines -log = "instr.txt" -xcov( - [ - "instrument", - "-Ptests.gpr", - "-cstmt", - "--projects=mylib", - "--log=instrument_clean_objdirs", - ], - out=log, -) -thistest.fail_if_diff( - baseline_file="../baseline.txt", - actual_file=log, - failure_message='"gnatcov instrument" output', - output_refiners=[ - Substitute(os.getcwd(), "[TMP]"), - Substitute("\\", "/"), - ], - ignore_white_chars=False, -) +# for all example projects. +for project, subproject in [("tests", "mylib"), ("my_tool", "my_tool")]: + log = f"instr-{project}.txt" + xcov( + [ + "instrument", + f"-P{project}.gpr", + "-cstmt", + f"--projects={subproject}", + "--log=instrument_clean_objdirs", + "--log=instrument_sources", + ], + out=log, + ) + thistest.fail_if_diff( + baseline_file=f"../baseline-{project}.txt", + actual_file=log, + failure_message=f'[{project}] "gnatcov instrument" output', + # To have portable baseline comparison, hide the actual CWD and + # canonicalize directory separators. + output_refiners=[ + Substitute(os.getcwd(), "[TMP]"), + SortByFiles(), + HashRefiner(), + Substitute("\\", "/"), + ], + ignore_white_chars=False, + ) thistest.result() diff --git a/testsuite/tests/instr-cov/logging/tests.gpr b/testsuite/tests/instr-cov/logging/tests.gpr index dbb8a33c3..697814df3 100644 --- a/testsuite/tests/instr-cov/logging/tests.gpr +++ b/testsuite/tests/instr-cov/logging/tests.gpr @@ -2,7 +2,8 @@ with "harness"; with "mylib_extended"; project Tests is + for Languages use ("Ada", "C"); for Source_Dirs use ("src-tests"); for Object_Dir use "obj/tests"; - for Main use ("test1.adb", "test2.adb"); + for Main use ("test1.adb", "test2.adb", "test3.c"); end Tests; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 57d7bc683..a9f45b282 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -64,6 +64,14 @@ package body Instrument.Ada_Unit is package LAL renames Libadalang.Analysis; package LALCO renames Libadalang.Common; + procedure Trace_Buffer_Unit + (Buffer_Unit : String; + Filename : String; + Prj : Prj_Desc; + CU_Names : CU_Name_Vectors.Vector; + Is_Pure : Boolean); + -- Helper to display details about a buffer unit to be emitted + subtype Decl_Expr_Supported_Versions is Any_Language_Version range Ada_2022 .. Any_Language_Version'Last; -- Set of versions of the Ada language that support declare @@ -142,6 +150,35 @@ package body Instrument.Ada_Unit is -- in the LAL tree, so the rewriting session will need to be re-started -- by the caller if needed. + ----------------------- + -- Trace_Buffer_Unit -- + ----------------------- + + procedure Trace_Buffer_Unit + (Buffer_Unit : String; + Filename : String; + Prj : Prj_Desc; + CU_Names : CU_Name_Vectors.Vector; + Is_Pure : Boolean) is + begin + if not Sources_Trace.Is_Active then + return; + end if; + + Sources_Trace.Increase_Indent + ("Writing" + & (if Is_Pure then " pure" else "") + & " Ada buffer unit " + & Buffer_Unit); + Sources_Trace.Trace ("Project: " & To_Ada (Prj.Prj_Name)); + Sources_Trace.Trace ("Filename: " & Filename); + Sources_Trace.Trace ("For units:"); + for CU of CU_Names loop + Sources_Trace.Trace ("* " & Image (CU)); + end loop; + Sources_Trace.Decrease_Indent; + end Trace_Buffer_Unit; + ----------------------- -- To_Qualified_Name -- ----------------------- @@ -10144,10 +10181,14 @@ package body Instrument.Ada_Unit is Pkg_Name : constant String := To_Ada (Buffer_Unit.Unit); -- Package name for the buffer unit + Filename : constant String := + To_Filename (Prj, Ada_Language, Buffer_Unit); + File : Text_Files.File_Type; Last_Buffer_Index : constant Natural := Natural (Unit_Bits.Length); begin - Create_File (Prj, File, To_Filename (Prj, Ada_Language, Buffer_Unit)); + Trace_Buffer_Unit (Pkg_Name, Filename, Prj, CU_Names, Is_Pure => False); + Create_File (Prj, File, Filename); Put_Warnings_And_Style_Checks_Pragmas (File); File.Put_Line ("with System;"); File.Put_Line ("with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers;"); @@ -10354,6 +10395,7 @@ package body Instrument.Ada_Unit is -- Start of processing for Emit_Pure_Buffer_Unit begin + Trace_Buffer_Unit (Pkg_Name, Filename, Prj, CU_Names, Is_Pure => True); File.Create (Filename); Put_Warnings_And_Style_Checks_Pragmas (File); @@ -10543,6 +10585,17 @@ package body Instrument.Ada_Unit is end; declare + Spec_Filename : constant String := + To_Filename + (Prj, + Ada_Language, + CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Spec)); + Body_Filename : constant String := + To_Filename + (Prj, + Ada_Language, + CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Body)); + Helper_Unit_Name : constant String := To_Ada (Helper_Unit); Dump_Procedure : constant String := To_String (Dump_Procedure_Name); Output_Unit_Str : constant String := To_Ada (Output_Unit); @@ -10561,20 +10614,24 @@ package body Instrument.Ada_Unit is begin Sys_Lists.Append (To_Unbounded_String ("Lists")); + if Sources_Trace.Is_Active then + Sources_Trace.Increase_Indent + ("Writing " & Instrumenter.Language_Name & " dump helper unit " + & Helper_Unit_Name); + Sources_Trace.Trace ("Project: " & To_Ada (Prj.Prj_Name)); + Sources_Trace.Trace ("Spec filename: " & Spec_Filename); + Sources_Trace.Trace ("Body filename: " & Body_Filename); + Sources_Trace.Trace ("For main: " & Image (Main)); + Sources_Trace.Decrease_Indent; + end if; + -- Emit the package spec. This includes one Dump_Buffers procedure, -- which dumps all coverage buffers in Main's closure to the source -- trace file, and in the case of manual dump trigger, a -- Reset_Buffers procedure which will resets all coverage buffers in -- the project tree rooted at the project to which Main belongs. - Create_File - (Prj, - File, - Name => - To_Filename - (Prj, - Ada_Language, - CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Spec))); + Create_File (Prj, File, Spec_Filename); Put_Warnings_And_Style_Checks_Pragmas (File); Put_With (Sys_Buffers); @@ -10629,14 +10686,7 @@ package body Instrument.Ada_Unit is -- Emit the package body - Create_File - (Prj, - File, - Name => - To_Filename - (Prj, - Ada_Language, - CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Body))); + Create_File (Prj, File, Body_Filename); Put_Warnings_And_Style_Checks_Pragmas (File); @@ -10878,98 +10928,104 @@ package body Instrument.Ada_Unit is Buffers_CU_Name : constant Compilation_Unit_Part := CU_Name_For_Unit (Buffers_List_Unit (Prj.Prj_Name), GNATCOLL.Projects.Unit_Spec); + Unit_Name : constant String := To_Ada (Buffers_CU_Name.Unit); + Filename : constant String := + To_Filename (Prj, Ada_Language, Buffers_CU_Name); File : Text_Files.File_Type; begin - -- Emit the unit to contain the list of buffers - - declare - Unit_Name : constant String := To_Ada (Buffers_CU_Name.Unit); - begin - Create_File - (Prj, File, To_Filename (Prj, Ada_Language, Buffers_CU_Name)); - Put_Warnings_And_Style_Checks_Pragmas (File); - File.Put_Line - ("with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists;"); + if Sources_Trace.Is_Active then + Sources_Trace.Increase_Indent + ("Writing " & Self.Language_Name & " buffer list unit " + & Unit_Name); + Sources_Trace.Trace ("Project: " & To_Ada (Prj.Prj_Name)); + Sources_Trace.Trace ("Filename: " & Filename); + Sources_Trace.Decrease_Indent; + end if; - for Instr_Unit of Instr_Units loop + -- Emit the unit to contain the list of buffers - -- Even though Ada buffer units are not explicitly referenced in - -- the generated code (we import all the coverage buffers from - -- their C symbol, as we want common processing for all - -- languages), we still need to "with" them. Otherwise, gprbuild - -- would not include them in the link as they would not be in the - -- dependency closure. + Create_File (Prj, File, Filename); + Put_Warnings_And_Style_Checks_Pragmas (File); + File.Put_Line + ("with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists;"); - if Instr_Unit.Language = Unit_Based_Language then - File.Put_Line - ("with " - & To_Ada - (Buffer_Unit (To_Qualified_Name (+Instr_Unit.Unit_Name))) - & ";"); - end if; - end loop; - File.New_Line; - File.Put_Line ("package " & Unit_Name & " is"); - File.New_Line; - File.Put_Line (" pragma Preelaborate;"); - File.New_Line; + for Instr_Unit of Instr_Units loop - -- Import all the coverage buffers + -- Even though Ada buffer units are not explicitly referenced in the + -- generated code (we import all the coverage buffers from their C + -- symbol, as we want common processing for all languages), we still + -- need to "with" them. Otherwise, gprbuild would not include them in + -- the link as they would not be in the dependency closure. - for Instr_Unit of Instr_Units loop - declare - Buffer_Name : constant String := Unit_Buffers_Name (Instr_Unit); - begin - File.Put_Line - (" " & Buffer_Name - & " : aliased constant GNATcov_RTS_Coverage_Buffers_Group;"); - File.Put_Line (" pragma Import (C, " & Buffer_Name & ",""" - & Buffer_Name & """);"); - end; - end loop; - - if Instr_Units.Is_Empty then + if Instr_Unit.Language = Unit_Based_Language then File.Put_Line - (" Dummy : aliased GNATcov_RTS_Coverage_Buffers_Group;"); + ("with " + & To_Ada + (Buffer_Unit (To_Qualified_Name (+Instr_Unit.Unit_Name))) + & ";"); end if; + end loop; + File.New_Line; + File.Put_Line ("package " & Unit_Name & " is"); + File.New_Line; + File.Put_Line (" pragma Preelaborate;"); + File.New_Line; - -- Create the list of coverage buffers + -- Import all the coverage buffers - File.Put_Line (" List : constant GNATcov_RTS.Buffers.Lists" - & ".Coverage_Buffers_Group_Array := ("); + for Instr_Unit of Instr_Units loop declare - Index : Positive := 1; - Last : constant Natural := Natural (Instr_Units.Length); + Buffer_Name : constant String := Unit_Buffers_Name (Instr_Unit); begin - for Instr_Unit of Instr_Units loop - File.Put - (" " & Img (Index) & " => " - & Unit_Buffers_Name (Instr_Unit) & "'Access"); - if Index = Last then - File.Put_Line (");"); - else - File.Put_Line (","); - end if; - Index := Index + 1; - end loop; + File.Put_Line + (" " & Buffer_Name + & " : aliased constant GNATcov_RTS_Coverage_Buffers_Group;"); + File.Put_Line (" pragma Import (C, " & Buffer_Name & ",""" + & Buffer_Name & """);"); end; + end loop; - if Instr_Units.Is_Empty then - File.Put (" 1 => Dummy'Access);"); - end if; - - File.Put_Line (" C_List : constant GNATcov_RTS.Buffers.Lists" - & ".GNATcov_RTS_Coverage_Buffers_Group_Array :="); - File.Put_Line (" (" & Instr_Units.Length'Image - & ", List'Address);"); - + if Instr_Units.Is_Empty then File.Put_Line - (" pragma Export (C, C_List, """ - & Unit_Buffers_Array_Name (Prj.Prj_Name) & """);"); + (" Dummy : aliased GNATcov_RTS_Coverage_Buffers_Group;"); + end if; - File.New_Line; - File.Put_Line ("end " & Unit_Name & ";"); + -- Create the list of coverage buffers + + File.Put_Line (" List : constant GNATcov_RTS.Buffers.Lists" + & ".Coverage_Buffers_Group_Array := ("); + declare + Index : Positive := 1; + Last : constant Natural := Natural (Instr_Units.Length); + begin + for Instr_Unit of Instr_Units loop + File.Put + (" " & Img (Index) & " => " + & Unit_Buffers_Name (Instr_Unit) & "'Access"); + if Index = Last then + File.Put_Line (");"); + else + File.Put_Line (","); + end if; + Index := Index + 1; + end loop; end; + + if Instr_Units.Is_Empty then + File.Put (" 1 => Dummy'Access);"); + end if; + + File.Put_Line (" C_List : constant GNATcov_RTS.Buffers.Lists" + & ".GNATcov_RTS_Coverage_Buffers_Group_Array :="); + File.Put_Line (" (" & Instr_Units.Length'Image + & ", List'Address);"); + + File.Put_Line + (" pragma Export (C, C_List, """ + & Unit_Buffers_Array_Name (Prj.Prj_Name) & """);"); + + File.New_Line; + File.Put_Line ("end " & Unit_Name & ";"); end Emit_Buffers_List_Unit; --------------------------------- @@ -11150,13 +11206,13 @@ package body Instrument.Ada_Unit is if Files_Of_Interest.Contains (Create_Normalized (Filename)) then - -- In verbose mode, always print a notice for the source file - -- that we are about to instrument. In non-verbose mode, just get - -- prepared to print it in case we emit a "source file missing" - -- warning through Libadalang's event handler. + -- In the corresponding trace is active, always print a notice for + -- the source file that we are about to instrument. In non-verbose + -- mode, just get prepared to print it in case we emit a "source + -- file missing" warning through Libadalang's event handler. - if Switches.Misc_Trace.Is_Active then - Switches.Misc_Trace.Trace ("Instrumenting " & Basename); + if Sources_Trace.Is_Active then + Sources_Trace.Trace ("Instrumenting " & Basename); else Event_Handler.Instrumented_File := +Basename; end if; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index ba17340ce..c2bcdd39b 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3852,6 +3852,20 @@ package body Instrument.C is I : Positive := 1; begin + if Sources_Trace.Is_Active then + Sources_Trace.Increase_Indent + ("Writing " & Instrumenter.Language_Name & " buffer unit " + & (+CU_Name.Filename)); + Sources_Trace.Trace ("Project: " & To_Ada (Prj.Prj_Name)); + Sources_Trace.Trace ("For files:"); + for SOI of UIC.Sources_Of_Interest_Info loop + if SOI.Of_Interest then + Sources_Trace.Trace ("* " & Image (SOI.CU_Name)); + end if; + end loop; + Sources_Trace.Decrease_Indent; + end if; + -- Compute Buffers_CUs and Buffers_CU_Names for Cur in UIC.Sources_Of_Interest_Info.Iterate loop @@ -4118,6 +4132,16 @@ package body Instrument.C is Reset_Procedure : constant String := Reset_Procedure_Symbol (Prj.Prj_Name); begin + if Sources_Trace.Is_Active then + Sources_Trace.Increase_Indent + ("Writing " & Instrumenter.Language_Name & " dump helper unit " + & Filename); + Sources_Trace.Trace ("Project: " & To_Ada (Prj.Prj_Name)); + Sources_Trace.Trace ("Filename: " & Filename); + Sources_Trace.Trace ("For main: " & Image (Main)); + Sources_Trace.Decrease_Indent; + end if; + -- Emit the package body Create_File (Prj, File, Filename); @@ -5182,14 +5206,13 @@ package body Instrument.C is Buffer_Symbols : String_Sets.Set; Prj : Prj_Desc) return Compilation_Unit is - CU_Name : constant Compilation_Unit := - (Language => File_Based_Language, - Unit_Name => - +New_File - (Prj, - "gcvrtc-" & To_Symbol_Name (Prj.Prj_Name) - & (+Prj.Body_Suffix - (C_Family_Instrumenter_Type'Class (Self).Language)))); + Filename : constant String := + New_File + (Prj, + "gcvrtc-" & To_Symbol_Name (Prj.Prj_Name) + & (+Prj.Body_Suffix + (C_Family_Instrumenter_Type'Class (Self).Language))); + CU_Name : constant Compilation_Unit := (File_Based_Language, +Filename); CU_File : Text_Files.File_Type; @@ -5199,6 +5222,13 @@ package body Instrument.C is Buffer_Unit_Length : constant String := Count_Type'Image (Buffer_Symbols.Length); begin + if Sources_Trace.Is_Active then + Sources_Trace.Increase_Indent + ("Writing " & Self.Language_Name & " buffer list unit " & Filename); + Sources_Trace.Trace ("Project: " & To_Ada (Prj.Prj_Name)); + Sources_Trace.Decrease_Indent; + end if; + -- Emit the body to contain the list of buffers CU_File.Create (+CU_Name.Unit_Name); diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 59e9f2323..8181477b0 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -446,6 +446,9 @@ package Instrument.Common is (Self : Language_Instrumenter) return Src_Supported_Language is abstract; -- Return the language that this instrumenter is designed to process + function Language_Name (Self : Language_Instrumenter'Class) return String + is (Image (Self.Language)); + procedure Instrument_Unit (Self : in out Language_Instrumenter; Unit_Name : String; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 9da8cd5c2..88115be4b 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -41,6 +41,10 @@ package Instrument is -- Trace to show details about how object directories in GPR projects are -- cleaned. + Sources_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("INSTRUMENT_SOURCES"); + -- Trace to show details about written instrumented sources + package GPR renames GNATCOLL.Projects; use type Ada.Containers.Count_Type; From 4d66db34f71f38a303e13c36e66c1ed675928aad Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 11 Dec 2024 10:09:21 +0000 Subject: [PATCH 1051/1483] instr-cov/expr_func/completion: minor reformatting --- testsuite/tests/instr-cov/expr_func/completion/pak.ads | 9 +++++++-- testsuite/tests/instr-cov/expr_func/completion/test.py | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/instr-cov/expr_func/completion/pak.ads b/testsuite/tests/instr-cov/expr_func/completion/pak.ads index ebd847ae8..d0e492aee 100644 --- a/testsuite/tests/instr-cov/expr_func/completion/pak.ads +++ b/testsuite/tests/instr-cov/expr_func/completion/pak.ads @@ -10,10 +10,15 @@ private type T is tagged record X : Integer; end record; - function Make (Cond : Boolean) return T is (T'(X => (if Cond then 1 else 2))); + + function Make (Cond : Boolean) return T + is (T'(X => (if Cond then 1 else 2))); type TT is new T with record Y : Integer; end record; - overriding function Make (Cond : Boolean) return TT is (TT'(X => 3, Y => 4)); + + overriding function Make (Cond : Boolean) return TT + is (TT'(X => 3, Y => 4)); + end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/completion/test.py b/testsuite/tests/instr-cov/expr_func/completion/test.py index 6671f19db..f35f19ab3 100644 --- a/testsuite/tests/instr-cov/expr_func/completion/test.py +++ b/testsuite/tests/instr-cov/expr_func/completion/test.py @@ -32,7 +32,7 @@ "xcov", { "main.adb.xcov": {"+": {5, 7}}, - "pak.ads.xcov": {"+": {5, 10, 11, 12, 15, 16, 17}, "?": {13, 18}}, + "pak.ads.xcov": {"+": {5, 10, 11, 12, 17, 18, 19}, "?": {15, 22}}, }, ) From 99ea89dbba590bc4a2f7259e4742f63174ed5900 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 11 Dec 2024 10:32:30 +0000 Subject: [PATCH 1052/1483] Fix instrumentation of the "next part" of primitive expression functions When the completion of an expression function is not directly in a package spec declarative part, it is possible to create the augmented expression function in the same scope. --- .../instr-cov/expr_func/completion/pak.adb | 25 ++++++++++++++ .../instr-cov/expr_func/completion/pak.ads | 3 ++ .../instr-cov/expr_func/completion/test.py | 6 +++- tools/gnatcov/instrument-ada_unit.adb | 34 ++++++++++++++++++- 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/instr-cov/expr_func/completion/pak.adb diff --git a/testsuite/tests/instr-cov/expr_func/completion/pak.adb b/testsuite/tests/instr-cov/expr_func/completion/pak.adb new file mode 100644 index 000000000..5327a7bed --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/completion/pak.adb @@ -0,0 +1,25 @@ +pragma Ada_2012; + +package body Pak is + + type BT is tagged record + X : Integer; + end record; + + function Make (Cond : Boolean) return BT + is (BT'(X => (if Cond then 1 else 2))); + + type BTT is new BT with record + Y : Integer; + end record; + + function Make (Cond : Boolean) return BTT + is (BTT'(X => 3, Y => 4)); + + function Exercise_BT (Cond : Boolean) return Integer + is (BT'(Make (Cond)).X); + + function Exercise_BTT (Cond : Boolean) return Integer + is (BTT'(Make (Cond)).Y); + +end Pak; diff --git a/testsuite/tests/instr-cov/expr_func/completion/pak.ads b/testsuite/tests/instr-cov/expr_func/completion/pak.ads index d0e492aee..e9b0b0864 100644 --- a/testsuite/tests/instr-cov/expr_func/completion/pak.ads +++ b/testsuite/tests/instr-cov/expr_func/completion/pak.ads @@ -6,6 +6,9 @@ package Pak is function Make (Cond : Boolean) return T; + function Exercise_BT (Cond : Boolean) return Integer; + function Exercise_BTT (Cond : Boolean) return Integer; + private type T is tagged record X : Integer; diff --git a/testsuite/tests/instr-cov/expr_func/completion/test.py b/testsuite/tests/instr-cov/expr_func/completion/test.py index f35f19ab3..adfa1c90c 100644 --- a/testsuite/tests/instr-cov/expr_func/completion/test.py +++ b/testsuite/tests/instr-cov/expr_func/completion/test.py @@ -6,6 +6,9 @@ gnatcov used to instrument such expression function, which resulted in introducing a new primitive (the wrapper generated for MC/DC instrumentation), which was not defined for derived types. + +This also checks that such expression functions *are* instrumented when they +are not in a package spec: primitives can be declared only in package specs. """ from SCOV.minicheck import build_run_and_coverage, check_xcov_reports @@ -32,7 +35,8 @@ "xcov", { "main.adb.xcov": {"+": {5, 7}}, - "pak.ads.xcov": {"+": {5, 10, 11, 12, 17, 18, 19}, "?": {15, 22}}, + "pak.ads.xcov": {"+": {5, 13, 14, 15, 20, 21, 22}, "?": {18, 25}}, + "pak.adb.xcov": {"+": {5, 6, 7, 12, 13, 14}, "-": {10, 17, 20, 23}}, }, ) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index a9f45b282..9b1dd274e 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -456,6 +456,10 @@ package body Instrument.Ada_Unit is function Unwrap (N : Expr) return Expr; -- Strip Paren_Expr from N + function In_Package_Spec (N : Ada_Node'Class) return Boolean; + -- Return whether N is a direct child of a package specification's + -- declarative part (the public or the private one). + function Inclusive_End_Sloc (SL : Source_Location_Range) return Source_Location; -- End slocs from Libadalang nodes are exclusive: the correspond to the @@ -4343,7 +4347,13 @@ package body Instrument.Ada_Unit is end if; if Is_Expr_Function then - if Return_Type_Is_Controlling (UIC, Common_Nodes) then + + -- If N does not appear in a package spec, creating the augmented + -- expression function for it will not create a new primitive. + + if Return_Type_Is_Controlling (UIC, Common_Nodes) + and then In_Package_Spec (N) + then -- For the moment when an expression function is a primitive of -- a tagged type T, and that T is the return type of the EF, @@ -7654,6 +7664,28 @@ package body Instrument.Ada_Unit is return Unwrapped_N; end Unwrap; + --------------------- + -- In_Package_Spec -- + --------------------- + + function In_Package_Spec (N : Ada_Node'Class) return Boolean is + Decl_Part : Declarative_Part; + begin + if N.Is_Null + or else N.Parent.Is_Null + or else N.Parent.Kind /= Ada_Ada_Node_List + or else N.Parent.Parent.Is_Null + or else N.Parent.Parent.Kind not in Ada_Declarative_Part_Range + then + return False; + end if; + + Decl_Part := N.Parent.Parent.As_Declarative_Part; + return + not Decl_Part.Parent.Is_Null + and then Decl_Part.Parent.Kind = Ada_Package_Decl; + end In_Package_Spec; + ------------------------ -- Inclusive_End_Sloc -- ------------------------ From 70231a352c373affe01f43976399d62e3aadcd3f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 11 Dec 2024 12:54:20 +0100 Subject: [PATCH 1053/1483] Do not use gpr_common_args in xcov_suite_args gpr_common_args passes the -v switch when the testsuite is run in qualification mode, which results in passing `-v` to every gnatcov invocation, yielding regressions. --- testsuite/SUITE/tutils.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 3b30ad798..ca599f594 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -729,11 +729,17 @@ def xcov_suite_args( or any(arg.startswith("-P") for arg in covargs) ) - result = ( - gpr_common_args(project=None, auto_config_args=auto_config_args) - if project_handling_enabled - else [] - ) + result = [] + + # If --config is asked and project handling is involved, pass it and stop + # there. If there is a board, it must be described in the project file + # (gnatcov's -P argument). + if project_handling_enabled and auto_config_args: + result.append( + "--config={}".format(os.path.join(ROOT_DIR, BUILDER.SUITE_CGPR)) + ) + result.extend(RUNTIME_INFO.gpr_scenario_vars) + return result # If --config is asked and project handling is involved, pass it and stop # there. If there is a board, it must be described in the project file From e84b3545ab3bd7bf54bde00e6f485be99bc29c6c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 13 Dec 2024 10:25:36 +0000 Subject: [PATCH 1054/1483] Instrument: do not strip leading zeros from slug hashes The interest to have less digits for slugs is low in practice (most will be 8 bytes long anyway), and this makes hash matching complicated. This fixes the tests/instr-cov/logging failure on some configurations. --- tools/gnatcov/instrument.adb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 58274ee40..c7afa1915 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -35,6 +35,10 @@ with Hex_Images; use Hex_Images; package body Instrument is + function Hash_32_Image (S : String) return String + is (Hex_Image (Unsigned_32 (Ada.Strings.Hash (S)))); + -- Return the 8-bytes image of a hash for S + ------------------- -- Language_Kind -- ------------------- @@ -237,11 +241,7 @@ package body Instrument is -- Prefix the hash with "z" to ensure the unit name slug doesn't -- start with a digit. - return - "z" & Strip_Zero_Padding - (Hex_Image - (Unsigned_32 - (Ada.Strings.Hash (To_String (Result))))); + return "z" & Hash_32_Image (To_String (Result)); else return To_String (Result); end if; @@ -288,9 +288,7 @@ package body Instrument is use Ada.Directories; Result : Ada_Identifier; - Full_Name_Hash : constant String := - Strip_Zero_Padding - (Hex_Image (Unsigned_32 (Ada.Strings.Hash (Fullname)))); + Full_Name_Hash : constant String := Hash_32_Image (Fullname); begin if Use_Hash then From 519da645e2c01d4b8b1653c752a21f8b900fe022 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 16 Dec 2024 10:26:43 +0000 Subject: [PATCH 1055/1483] Doc: Update documentation for aggregate project support in gnattest --- doc/gnattest/gnattest_part.rst | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/doc/gnattest/gnattest_part.rst b/doc/gnattest/gnattest_part.rst index 01b46efc8..bfa9d1a39 100644 --- a/doc/gnattest/gnattest_part.rst +++ b/doc/gnattest/gnattest_part.rst @@ -73,6 +73,9 @@ where specifies the project defining the location of source files. When no file names are provided on the command line, all sources in the project are used as input. This switch is required. + + For the semantics of aggregate project processing by gnattest, see the + :ref:`aggregate_projects` section. * :switch:`{filename}` is the name of the source file containing the library unit package *declaration* @@ -912,6 +915,35 @@ put under version control. Option ``--omit-sloc`` may be useful when putting test packages under version control. +.. _aggregate_projects: + +Aggregate project handling +-------------------------- + +If the project passed to ``gnattest`` with the ``-P`` switch is an aggregate +project, the aggregated projects will be processed sequentially and +independently. This will result in one harness directory being generated by +default, in the object directories of each of the aggregated projects. + +``gnattest`` will not generate any project file or makefile to automate the +build of the harnesses of each of the aggregated project. + +Artifact directories and aggregate projects +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +By default, all artifacts generated by ``gnattest`` are located in +subdirectories of the object directory of each of the aggregated projects. This +in particular means that tests or stubs for a common dependency of two +aggregated projects will be duplicated. In order to avoid this, options such as +``--stubs-dir``., ``--tests-dir`` or ``--subdirs`` can be used, with **relative +paths** so that the artifacts for the common dependencies are generated in the +same location, and re-used across each test harness. + +On the contrary, using ``--harness-dir`` or ``--tests-dir`` with an absolute +path will result in the harness and/or files of a first aggregated project being +overwritten by the generation of the test harness for subsequent aggregated +projects, and should thus be avoided. + .. _Current_Limitations: Current Limitations From d1cdd6c6c2a6ae67535f808bc66c81189ab7f2ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 2 Apr 2024 15:36:50 +0200 Subject: [PATCH 1056/1483] Enhance the doc for coverage reports in gnatstudio Go into more details for how to view coverage reports created outside of gnatstudio through gnattest's integration makefile. --- doc/gnatcov/gps.rst | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/doc/gnatcov/gps.rst b/doc/gnatcov/gps.rst index 034b1d585..b2c971f52 100644 --- a/doc/gnatcov/gps.rst +++ b/doc/gnatcov/gps.rst @@ -72,6 +72,28 @@ directory of the project (), or under /xcov+. Then you can visualize the report by clicking on :menuselection:`Analyze --> Coverage --> Show coverage report`. +Using GNATtest's coverage integration makefile +============================================== + +When using individual test drivers, it is not possible to use the regular +GNATcoverage integration. This is true when GNATtest is called with +:cmd-option:`--separate-drivers` or :cmd-option:`--stub` (as it implies +:cmd-option:`--separate-drivers`), as described in :ref:`Individual Test +Drivers`. In this case, the integration of +GNATcoverage is done through the use of the generated integration makefile. For +details on how to use this makefile, see :ref:`Integration with +GNATcoverage`. + +Producing coverage reports through GNATtest's coverage integration makefile +generates the coverage reports under the test driver's object director by +default. However, these reports contain coverage information not for the test +harness project, but for the project being tested with gnattest. + +If the harness project is opened in GNAT Studio, the coverage data should be +loaded using the actionable `Load Data for All Projects` item. + +Visualization of the reports is then done as previously described. + GNATtest scenario ================= From a8992ffad8ac84d2a351248fc8ec781375835281 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Tue, 10 Dec 2024 14:46:46 +0100 Subject: [PATCH 1057/1483] Add support for user operators for call coverage --- .../user_operator/src/op.adb | 63 ++++++++++++-- .../user_operator/src/reversed.ads | 15 ++++ .../user_operator/src/test_op.adb | 21 +++-- tools/gnatcov/instrument-ada_unit.adb | 83 ++++++++++++++----- 4 files changed, 149 insertions(+), 33 deletions(-) create mode 100644 testsuite/tests/287-function_call_cov/user_operator/src/reversed.ads diff --git a/testsuite/tests/287-function_call_cov/user_operator/src/op.adb b/testsuite/tests/287-function_call_cov/user_operator/src/op.adb index e7f427a6a..723057cc6 100644 --- a/testsuite/tests/287-function_call_cov/user_operator/src/op.adb +++ b/testsuite/tests/287-function_call_cov/user_operator/src/op.adb @@ -1,13 +1,66 @@ pragma Ada_2012; -with Ada.Text_IO; use Ada.Text_IO; +with Reversed; use Reversed; procedure Op is - function "+" (L, R : Boolean) return String is ("Executed"); -- # fun + T : Boolean := True; -- # decl + F : Boolean := False; -- # decl + Dummy : Boolean := True; -- # decl + + function "+" (Left, Right : Boolean) return Boolean -- # fun + is (Left and Right); -- # fun + + function "+" (Arg : Reversed.T) return Reversed.T -- # fun + is (0 - Arg); -- # fun + + function "&" (L,R : Float) return Float -- # fun + is (42.0); -- # fun + + function "&" (L : Integer; R : String) return Integer -- # fun + is (42); -- # fun + + function "&" (L : String; R : Integer) return Integer -- # fun + is (42); -- # fun - T : Boolean := True; -- # t_decl - S : constant String := T + T; -- # op_call begin - Put_Line (S); -- # put_line + Dummy := F + T; -- # ok + Dummy := "+" (T, F); -- # ok + Dummy := F + T + F + T; -- # ok + Dummy := "+" (T, "+" (T, F)); -- # ok + + Dummy := One < Two; -- # ok + Dummy := Reversed."<" (One, Two); -- # ok + + Dummy := +One = -1; -- # ok + Dummy := Reversed.Inner."+" (One) = -1; -- # ok + + Dummy := (40 & "Two") = 42; -- # ok + Dummy := (1.3 & 3.2 & 2.1) = 42.0; -- # ok + + Dummy := F + ("&" ("A", 8) = 42); -- # ok + Dummy := "+" (F, ("&" ("A", 8) = 42)); -- # ok + + Dummy := ("A" & "B" & 42 & "D" & "E") = 42; -- # ok + + if F then -- # if + Dummy := F + T; -- # ko + Dummy := "+" (T, F); -- # ko + Dummy := F + T + F + T; -- # A_ko + Dummy := "+" (T, "+" (T, F)); -- # B_ko + + Dummy := One < Two; -- # ko + Dummy := Reversed."<" (One, Two); -- # ko + + Dummy := +One = -1; -- # ko + Dummy := Reversed.Inner."+" (One) = -1; -- # ko + + Dummy := (40 & "Two") = 42; -- # ko + Dummy := (1.3 & 3.2 & 2.1) = 42.0; -- # C_ko + + Dummy := F + ("&" ("A", 8) = 42); -- # D_ko + Dummy := "+" (F, ("&" ("A", 8) = 42)); -- # E_ko + + Dummy := ("A" & "B" & 42 & "D" & "E") = 42; -- # F_ko + end if; end Op; diff --git a/testsuite/tests/287-function_call_cov/user_operator/src/reversed.ads b/testsuite/tests/287-function_call_cov/user_operator/src/reversed.ads new file mode 100644 index 000000000..d6752c0b2 --- /dev/null +++ b/testsuite/tests/287-function_call_cov/user_operator/src/reversed.ads @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package Reversed is + type T is new Integer; -- # ok + + One : T := 1; -- # ok + Two : T := 2; -- # ok + + -- Let's make it go the other way to keep things interesting + function "<" (L, R : T) return Boolean is (L > R); -- # ok + + package Inner is + function "+" (Arg : T) return T is (0 - Arg); -- # ok + end Inner; +end Reversed; diff --git a/testsuite/tests/287-function_call_cov/user_operator/src/test_op.adb b/testsuite/tests/287-function_call_cov/user_operator/src/test_op.adb index 176ce749c..c6a0bbb40 100644 --- a/testsuite/tests/287-function_call_cov/user_operator/src/test_op.adb +++ b/testsuite/tests/287-function_call_cov/user_operator/src/test_op.adb @@ -1,16 +1,21 @@ with Op; --- LIMITATION --- For now, gnatcov should not instrument calls to user-defined operators. --- Check that this is true and that the proper warning is emitted. - procedure Test_Op is begin Op; end Test_Op; --# op.adb --- /fun/ l+ ## 0 --- /t_decl/ l+ ## 0 --- /op_call/ l? ## c? --- /put_line/ l+ ## 0 +-- /decl/ l+ ## 0 +-- /fun/ l+ ## 0 +-- /ok/ l+ ## 0 +-- /ko/ l- ## s=>s-,f=>s-,c- +-- /A_ko/ l- ## s=>s-,f=>s-,c-,c-,c- +-- /B_ko/ l- ## s=>s-,f=>s-,c-,c- +-- /C_ko/ l- ## s=>s-,f=>s-,c-,c- +-- /D_ko/ l- ## s=>s-,f=>s-,c-,c- +-- /E_ko/ l- ## s=>s-,f=>s-,c-,c- +-- /F_ko/ l- ## s=>s-,f=>s-,c-,c-,c- +-- /if/ l! ## dT- +--# reversed.ads +-- /ok/ l+ ## 0 diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 9b1dd274e..4d23dd910 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3602,9 +3602,7 @@ package body Instrument.Ada_Unit is -- process it once; we choose to do this on the inner-most node. function Full_Call (Node : Ada_Node'Class) return Ada_Node; - -- From an node that is a call, get its parent if it is a - -- Dotted_Name. Return the dotted name if this is a call with no arguments, - -- or the Call_Expr parent if it is a call with arguments. + -- Get the outter-most node that is this call -------------------------- -- Internal Subprograms -- @@ -6190,10 +6188,27 @@ package body Instrument.Ada_Unit is (Node : Ada_Node'Class) return Visit_Status is + Is_Op_String_Call : constant Boolean := + Node.Kind in Ada_String_Literal + and then + (Node.Parent.Kind = Ada_Call_Expr + or else + (Node.Parent.Kind = Ada_Dotted_Name + and then Node.Parent.Parent.Kind = Ada_Call_Expr)); + -- For call of the form "+"(A,B), Node will be a String_Literal + -- inside a Call_Expr. String_Literals are always considered to + -- be static, but we don't want to instrument static expressions. + -- Checking this is thus needed to let calls of this form be + -- seen as calls. + -- TODO: This is a P_Is_Static_Expr bug, reported in issue + -- eng/libadalang/libadalang#1523. Once this is fixed this + -- variable and associated check should be safe to remove. + Full_Call_Node : Ada_Node; begin if Is_Call_Leaf (Node) - and then not Is_Static_Expr (Node.As_Expr) + and then + (not Is_Static_Expr (Node.As_Expr) or else Is_Op_String_Call) then Full_Call_Node := Full_Call (Node); @@ -6239,7 +6254,18 @@ package body Instrument.Ada_Unit is -- site or not. Location : constant Source_Location_Range := - Full_Call_Node.Sloc_Range; + (if Node.Kind = Ada_Op_Concat + then + (Node + .Parent + .As_Concat_Operand.F_Operator.As_Ada_Node.Sloc_Range) + else Full_Call_Node.Sloc_Range); + -- Special case for concatenation operators: Node holds + -- "& " where the call that needs to be monitored + -- is the operator "&". In order to produce valid code, the + -- if-expression holding the witness call is created around + -- the operand, but the location of the SCO should still be + -- the operator's. begin Append_SCO (C1 => 'c', @@ -6280,14 +6306,8 @@ package body Instrument.Ada_Unit is -- need for call the are in the middle of a dotted name. -- For now, do not instrument calls that wouls require such -- an instrumentation. - -- - -- USER-DEFINED OPERATORS - -- gnatcov does not handle calls to user-defined operators - -- as the current instrumentation is not suited to it. - Do_Not_Instrument := - Needs_Qualified_Expr - or else Node.Kind in Ada_Op; + Do_Not_Instrument := Needs_Qualified_Expr; if not Do_Not_Instrument then Fill_Expression_Insertion_Info @@ -6324,8 +6344,7 @@ package body Instrument.Ada_Unit is Create_Paren_Expr (UIC.Rewriting_Context, If_Expression)) else No_Node_Rewriting_Handle); - Dummy : constant Wide_Wide_String := - Unparse (If_Expression); + begin if Needs_Qualified_Expr then Replace (Dummy_Handle, Qualified_Expr); @@ -7186,9 +7205,6 @@ package body Instrument.Ada_Unit is or else (Node.Parent.Kind = Ada_Call_Expr and then Node.Parent.As_Call_Expr.P_Kind = Call)); - -- TODO??? Only process operators if they are **not** predefined - -- operators? - when Ada_Un_Op | Ada_Bin_Op | Ada_Concat_Op => return False; @@ -7205,17 +7221,44 @@ package body Instrument.Ada_Unit is is Call : Ada_Node; begin - -- Ensure Node is the inner-most node identifying a call. pragma Assert (Is_Call_Leaf (Node)); Call := Node.As_Ada_Node; - if Call.Parent.Kind = Ada_Dotted_Name then + -- From a node that is a call, get: + -- + -- * its parent if it is a Dotted_Name or an operator; + -- * its parent's parent if it is an operator called via its string + -- litteral name; + -- * the operand for concatenation operators (it will instrumented to + -- hold the witness statement for the operator). + + if Call.Kind in Ada_String_Literal + and then Call.Parent.Kind in Ada_Dotted_Name + then + Call := Call.Parent.Parent; + end if; + + if Call.Parent.Kind in Ada_Dotted_Name + or else (Call.Kind in Ada_Op + and then Call.Parent.Kind in + Ada_Bin_Op + | Ada_Un_Op + | Ada_Relation_Op) + then Call := Call.Parent; + + elsif Call.Kind = Ada_Op_Concat then + Call := Call.Parent.As_Concat_Operand.F_Operand.As_Ada_Node; end if; - if Call.Parent.Kind = Ada_Call_Expr then + -- Then, if Call's parent is a Call_Expr, it means that the call has + -- arguments. We want to take them into account. Otherwise the call + -- has no arguments and Call is already the outter-most node + -- representing this call. + + if Call.Parent.Kind in Ada_Call_Expr then Call := Call.Parent; end if; From 6ff70636f734e634f8125d2e2209e447aa900ba1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 18 Dec 2024 12:07:33 +0100 Subject: [PATCH 1058/1483] Add .check_formatting.py call to pre-commit-config.yaml --- .check-formatting.py | 38 +++++++++++++++++++++++++++++++------- .gitlab-ci.yml | 9 --------- .pre-commit-config.yaml | 7 +++++++ 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/.check-formatting.py b/.check-formatting.py index f6df24fa8..627499812 100644 --- a/.check-formatting.py +++ b/.check-formatting.py @@ -4,7 +4,18 @@ import os.path import sys -from colorama import Fore, Style +try: + from colorama import Fore, Style + + CYAN = Fore.CYAN + GREEN = Fore.GREEN + MAGENTA = Fore.MAGENTA + RESET_ALL = Style.RESET_ALL +except ImportError: + MAGENTA = "\033[35m" + CYAN = "\033[36m" + GREEN = "\033[32m" + RESET_ALL = "\033[0m" args_parser = argparse.ArgumentParser( @@ -23,6 +34,14 @@ " but still supports ANSI codes." ), ) +args_parser.add_argument( + "--ignore-non-source", + action="store_true", + help=( + "If set, filter the given files to only keep those which would have" + " been detected automatically" + ), +) args_parser.add_argument( "files", nargs="*", @@ -94,20 +113,20 @@ def report( # Build a list of text chunks to print. Put colorama elements in tuples # so that we can keep only text chunks if the output is not a TTY. chunks = [ - (Fore.MAGENTA,), + (MAGENTA,), filename, - (Fore.CYAN,), + (CYAN,), ":", ] if lineno is not None: chunks += [ - (Fore.GREEN,), + (GREEN,), str(lineno), - (Fore.CYAN,), + (CYAN,), ":", ] chunks += [ - (Style.RESET_ALL,), + (RESET_ALL,), " ", message, ] @@ -178,7 +197,12 @@ def main(cls, argv: list[str] | None = None): # source files in the current directory. if args.files: for filename in args.files: - checker.process_file(filename) + realpath = os.path.realpath(filename) + if not args.ignore_non_source or ( + realpath not in ignore_set + and filename.rsplit(".", 1)[-1] in cls.filename_extensions + ): + checker.process_file(filename) else: for path, _, filenames in os.walk("."): for f in filenames: diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6f61c537d..67e84bb02 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -214,15 +214,6 @@ pre-commit: # Install the clang-format executable and make it available - anod install libclang -Qstable - eval `anod printenv libclang -Qstable` - - # Create a virtual env to install our deps - - python -mvenv /tmp/venv - - . /tmp/venv/bin/activate - - python -m pip install colorama pre-commit - - - python .check-formatting.py --force-colors - - ################# # Optional jobs # ################# diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6e1b9e5c7..c4c7640e1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,3 +33,10 @@ repos: hooks: - id: black args: ["--line-length=79"] + - repo: local + hooks: + - id: check-formatting + name: check-formatting + entry: python .check-formatting.py + language: system + args: ["--autofix", "--ignore-non-source"] From d8e3b023b4933b93aa2d109f9773da2e9972856f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 19 Dec 2024 14:54:15 +0100 Subject: [PATCH 1059/1483] gnatcov setup: document shared libraries requirements --- doc/gnatcov/getting_started.rst | 18 +++++++++++++++++- doc/gnatcov/src_traces.rst | 13 +++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/doc/gnatcov/getting_started.rst b/doc/gnatcov/getting_started.rst index 806be6e65..3ba70ad10 100644 --- a/doc/gnatcov/getting_started.rst +++ b/doc/gnatcov/getting_started.rst @@ -198,7 +198,9 @@ commands are going to be installed:: Letting further commands know about the *prefix* location is achieved by adding ``/share/gpr`` to the ``GPR_PROJECT_PATH`` -variable. In a Unix like environment, this would be:: +variable. In a Unix like environment, this would be: + +.. code-block:: sh export GPR_PROJECT_PATH=$GPR_PROJECT_PATH:/path/to/gnatcov-rts/share/gpr @@ -206,6 +208,20 @@ This will both let the ``gprbuild`` command below locate the ``gnatcov_rts.gpr`` project file, and the |gcvins| command find default parameter values. +In addition, when using shared libraries, it is necessary to let the +environment know about the coverage runtime's own shared libraries. The +following command achieves this in a Unix like environment: + +.. code-block:: sh + + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/gnatcov-rts/lib + +The following command performs the corresponding action on Windows systems: + +.. code-block:: bat + + set PATH=%PATH%;C:\path\to\gnatcov-rts\bin\ + Instrumentation is performed by a simple |gcvins| command:: gnatcov instrument -Ptests.gpr --level=stmt diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index a56c6ccdc..5e7a11ee5 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -94,6 +94,19 @@ project file that is installed. To achieve this, update the export GPR_PROJECT_PATH=$GPR_PROJECT_PATH:/usr/custom/share/gpr +In addition, when using shared libraries, the environment needs to be updated +so that instrumented programs can load the coverage runtime's own shared +libraries. The following command achieves this in a Unix like environment: + +.. code-block:: sh + + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/gnatcov-rts/lib + +The following command performs the corresponding action on Windows systems: + +.. code-block:: bat + + set PATH=%PATH%;C:\path\to\gnatcov-rts\bin\ Multiple runtimes in the same prefix ------------------------------------ From 7246fb0ac995204c9abcda217843e44ca513660b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 4 Dec 2024 12:51:05 +0100 Subject: [PATCH 1060/1483] Permit merging of checkpoints with condition SCOs that are partially static --- tools/gnatcov/instrument-ada_unit.adb | 38 +++++++++++++++++---------- tools/gnatcov/instrument-common.ads | 7 +++++ tools/gnatcov/sc_obligations.adb | 28 ++++++++++++++++---- tools/gnatcov/sc_obligations.ads | 16 ++++++++--- 4 files changed, 66 insertions(+), 23 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 4d23dd910..56e4f2a38 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6728,33 +6728,36 @@ package body Instrument.Ada_Unit is procedure Output_Element (N : Ada_Node) is N_SR : constant Source_Location_Range := N.Sloc_Range; - C2 : Character := 'c'; + SCO : SCO_Id; begin + + Append_SCO + (C1 => ' ', + C2 => 'c', + From => +Start_Sloc (N_SR), + To => +Inclusive_End_Sloc (N_SR), + SFI => UIC.SFI, + Last => False); + Hash_Entries.Append ((Start_Sloc (N_SR), SCOs.SCO_Table.Last)); + SCO := SCO_Id (SCOs.SCO_Table.Last); + if Is_Static_Expr (N.As_Expr) then - -- This condition is static: record its value in the SCO + -- This condition is static: record its value declare Eval : constant String := Bool_Expr_Eval (N.As_Expr); begin if Eval = "True" then - C2 := 't'; + UIC.True_Static_LL_SCOs.Include (SCO); elsif Eval = "False" then - C2 := 'f'; + UIC.False_Static_LL_SCOs.Include (SCO); end if; end; end if; - Append_SCO - (C1 => ' ', - C2 => C2, - From => +Start_Sloc (N_SR), - To => +Inclusive_End_Sloc (N_SR), - SFI => UIC.SFI, - Last => False); - Hash_Entries.Append ((Start_Sloc (N_SR), SCOs.SCO_Table.Last)); if UIC.Disable_Instrumentation then - UIC.Non_Instr_LL_SCOs.Include (SCO_Id (SCOs.SCO_Table.Last)); + UIC.Non_Instr_LL_SCOs.Include (SCO); end if; end Output_Element; @@ -9959,6 +9962,9 @@ package body Instrument.Ada_Unit is UIC.Non_Instr_LL_SCOs.Clear; + UIC.True_Static_LL_SCOs.Clear; + UIC.False_Static_LL_SCOs.Clear; + Initialize_Rewriting (UIC, Instrumenter); UIC.Instrumented_Unit := CU_Name; @@ -10039,7 +10045,11 @@ package body Instrument.Ada_Unit is Origin => UIC.SFI, Created_Units => Created_Units, SCO_Map => SCO_Map'Access, - Count_Paths => True); + Count_Paths => True, + Attached_Ctx => Instr_Attached_Ctx' + (True_Static_SCOs => UIC.True_Static_LL_SCOs, + False_Static_SCOs => UIC.False_Static_LL_SCOs) + ); -- In the instrumentation case, the origin of SCO information is -- the original source file. diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 8181477b0..1d8730168 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -360,6 +360,13 @@ package Instrument.Common is Non_Instr_LL_SCOs : SCO_Sets.Set; -- Set of low level SCO ids that were not instrumented + True_Static_LL_SCOs : SCO_Sets.Set; + False_Static_LL_SCOs : SCO_Sets.Set; + -- Keeps track of static decision SCOs. Static SCOs are registered + -- identically as non-static ones, to permit consolidation when + -- an expression is static in some cases only (e.g. endianness + -- depending on system architecture) + Blocks : SCO_Id_Vector_Vector; -- This is used when the block coverage level is enabled: list of blocks diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index c503f35a8..f8737e3e5 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -149,6 +149,9 @@ package body SC_Obligations is Bit_Maps_Fingerprint : Fingerprint_Type; -- Hash of Bit_Maps, for consistency checks with source traces + + True_Static_SCOs : SCO_Sets.Set; + False_Static_SCOs : SCO_Sets.Set; end case; end record; @@ -344,7 +347,8 @@ package body SC_Obligations is Ignored_Slocs : in out Ignored_Slocs_Sets.Set; SCO_Map : access LL_HL_SCO_Map := null; Count_Paths : Boolean; - Provider : SCO_Provider); + Provider : SCO_Provider; + Attached_Ctx : Instr_Attached_Ctx := No_Attached_Ctx); -- Load the low level SCO at SCO_Index into our Internal table, to be part -- of the CU compilation unit. -- @@ -3916,7 +3920,8 @@ package body SC_Obligations is Ignored_Slocs : in out Ignored_Slocs_Sets.Set; SCO_Map : access LL_HL_SCO_Map := null; Count_Paths : Boolean; - Provider : SCO_Provider) + Provider : SCO_Provider; + Attached_Ctx : Instr_Attached_Ctx := No_Attached_Ctx) is Unit : CU_Info renames CU_Vector.Reference (CU); SCOE : SCOs.SCO_Table_Entry renames SCOs.SCO_Table.Table (SCO_Index); @@ -3986,11 +3991,22 @@ package body SC_Obligations is -------------------------- function Make_Condition_Value return Tristate is + use SCO_Sets; begin case SCOE.C2 is + + -- ??? Do we have to keep this ? + when 'f' => return False; when 't' => return True; - when 'c' => return Unknown; + when 'c' => return + (if Attached_Ctx.True_Static_SCOs.Contains + (SCO_Id (SCO_Index)) + then True + elsif Attached_Ctx.False_Static_SCOs.Contains + (SCO_Id (SCO_Index)) + then False + else Unknown); when others => raise Program_Error with "invalid SCO condition value code: " & SCOE.C2; @@ -4233,7 +4249,8 @@ package body SC_Obligations is Deps : SFI_Vector := SFI_Vectors.Empty_Vector; Created_Units : out Created_Unit_Maps.Map; SCO_Map : access LL_HL_SCO_Map := null; - Count_Paths : Boolean) + Count_Paths : Boolean; + Attached_Ctx : Instr_Attached_Ctx := No_Attached_Ctx) is use SCOs; @@ -4289,7 +4306,8 @@ package body SC_Obligations is Ignored_Slocs_Set, SCO_Map, Count_Paths, - Provider); + Provider, + Attached_Ctx); end loop; end loop; diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index b5065ec75..4f135f6c2 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -288,6 +288,9 @@ package SC_Obligations is No_SCO_Id : constant SCO_Id := 0; subtype Valid_SCO_Id is SCO_Id range No_SCO_Id + 1 .. SCO_Id'Last; + package SCO_Sets is + new Ada.Containers.Ordered_Sets (Element_Type => SCO_Id); + type Scope_Entity_Identifier is record Decl_SFI : Source_File_Index; Decl_Line : Natural; @@ -456,13 +459,21 @@ package SC_Obligations is -- contain associations for "foo.ads", "foo.adb" and "foo-subunit.adb", but -- not for "bar.adb". + type Instr_Attached_Ctx is record + True_Static_SCOs : SCO_Sets.Set; + False_Static_SCOs : SCO_Sets.Set; + end record; + No_Attached_Ctx : constant Instr_Attached_Ctx := + (True_Static_SCOs => SCO_Sets.Empty, False_Static_SCOs => SCO_Sets.Empty); + procedure Process_Low_Level_SCOs (Provider : SCO_Provider; Origin : Source_File_Index; Deps : SFI_Vector := SFI_Vectors.Empty_Vector; Created_Units : out Created_Unit_Maps.Map; SCO_Map : access LL_HL_SCO_Map := null; - Count_Paths : Boolean); + Count_Paths : Boolean; + Attached_Ctx : Instr_Attached_Ctx := No_Attached_Ctx); -- Populate high level SCO tables (SC_Vectors, CU_Vector, ... in -- SC_Obligations' body) from low level ones (global tables from the SCOs -- unit). @@ -635,9 +646,6 @@ package SC_Obligations is -- item in the source. The input SCO argument is expected to designate a -- statement SCO. - package SCO_Sets is - new Ada.Containers.Ordered_Sets (Element_Type => SCO_Id); - procedure Set_Stmt_SCO_Non_Instr (SCO : SCO_Id) with Pre => Kind (SCO) = Statement; -- Mark this statment SCO as non-instrumented From 2cf61a917358901a823c668e425bfdef40e98346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 4 Dec 2024 19:12:12 +0100 Subject: [PATCH 1061/1483] Correctly handle static/non-static decisions merging --- tools/gnatcov/checkpoints.ads | 3 +++ tools/gnatcov/coverage-source.adb | 24 +++++++++++++++++ tools/gnatcov/sc_obligations.adb | 44 ++++++++++++++++++++++++++----- 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 294eba7f0..7f0b781d6 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -291,6 +291,9 @@ package Checkpoints is -- Format version for the checkpoint being read Relocations : Checkpoint_Relocations; + + True_Static_SCOs : SCO_Sets.Set; + False_Static_SCOs : SCO_Sets.Set; end record; use type Interfaces.Unsigned_32; diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 092b3935a..65eb83969 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -567,7 +567,31 @@ package body Coverage.Source is 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 (B : Boolean); + + procedure Insert_Extra_Decision_SCI (B : Boolean) is + Inserted_SCI : + constant Source_Coverage_Info := + (Kind => Decision, + Known_Outcome_Taken => + (True => B, False => not B), + others => <>); + begin + Merge_Checkpoint_SCI + (SCO, + Tag_Provider.Map_Tag (Relocs, Inserted_SCI.Tag), + Inserted_SCI, + Relocs); + end Insert_Extra_Decision_SCI; begin + if CLS.True_Static_SCOs.Contains (CP_SCO) then + Insert_Extra_Decision_SCI (True); + end if; + if CLS.False_Static_SCOs.Contains (CP_SCO) then + Insert_Extra_Decision_SCI (False); + end if; + if not Removed then for CP_SCI of Element (SCO_Cur) loop if CP_SCI /= null then diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index f8737e3e5..4869f0b55 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -1348,10 +1348,10 @@ package body SC_Obligations is - CP_CU.First_SCO); declare - Old_SCOD : SCO_Descriptor renames + Old_SCOD : SCO_Descriptor renames CP_Vectors.SCO_Vector (Old_SCO_Id); - SCOD : SCO_Descriptor renames - SCO_Vector (Remap_SCO_Id (Relocs, Old_SCO_Id)); + New_SCO_Id : constant SCO_Id := Remap_SCO_Id (Relocs, Old_SCO_Id); + SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); begin case SCOD.Kind is when Statement => @@ -1367,6 +1367,41 @@ package body SC_Obligations is SCOD.Decision_Instrumented_For_MCDC := True; end if; + if Old_SCOD.Decision_BDD.Reachable_Outcomes (True) then + SCOD.Decision_BDD.Reachable_Outcomes (True) := True; + end if; + if Old_SCOD.Decision_BDD.Reachable_Outcomes (False) then + SCOD.Decision_BDD.Reachable_Outcomes (False) := True; + end if; + + when Condition => + if Old_SCOD.Value /= SCOD.Value then + + -- If the old value does not match the new one, it means + -- that we are consolidating 2 checkpoints where the + -- condition was static in one of them, and non-static + -- in the other. + -- In consequences, we ensure the SCO is flagged as + -- Unknown because some of it was evaluated at run time. + -- Also, we need tp keep a track of the static evaluation + -- to make sure it's accounted for in the runtime + -- coverage computation. + + Misc_Trace.Trace ("Consolidation will merge condition" + & " SCOs that are both static and" + & " non-static at " + & Image (SCOD.Sloc_Range)); + + if Old_SCOD.Value = False or else SCOD.Value = False then + CLS.False_Static_SCOs.Include (Parent (New_SCO_Id)); + end if; + if Old_SCOD.Value = True or else SCOD.Value = True then + CLS.True_Static_SCOs.Include (Parent (New_SCO_Id)); + end if; + + SCOD.Value := Unknown; + end if; + when Fun_Call_SCO_Kind => if Old_SCOD.Fun_Call_Instrumented then SCOD.Fun_Call_Instrumented := True; @@ -3994,9 +4029,6 @@ package body SC_Obligations is use SCO_Sets; begin case SCOE.C2 is - - -- ??? Do we have to keep this ? - when 'f' => return False; when 't' => return True; when 'c' => return From ea37c3a42994e5673f8252f891e7eb94a1c2754a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Mon, 9 Dec 2024 14:18:56 +0100 Subject: [PATCH 1062/1483] Detect decision's outcomes instead of conditions staticness --- tools/gnatcov/sc_obligations.adb | 69 ++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 29 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 4869f0b55..0960343a8 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -1348,6 +1348,8 @@ package body SC_Obligations is - CP_CU.First_SCO); declare + use SC_Obligations.BDD; + Old_SCOD : SCO_Descriptor renames CP_Vectors.SCO_Vector (Old_SCO_Id); New_SCO_Id : constant SCO_Id := Remap_SCO_Id (Relocs, Old_SCO_Id); @@ -1367,39 +1369,48 @@ package body SC_Obligations is SCOD.Decision_Instrumented_For_MCDC := True; end if; - if Old_SCOD.Decision_BDD.Reachable_Outcomes (True) then - SCOD.Decision_BDD.Reachable_Outcomes (True) := True; - end if; - if Old_SCOD.Decision_BDD.Reachable_Outcomes (False) then - SCOD.Decision_BDD.Reachable_Outcomes (False) := True; - end if; + -- If the reachable outcomes of a decision differ, we know + -- these have different staticness. it can be + -- - merging static with non-static decisions + -- - merging true-static with false-static decisions - when Condition => - if Old_SCOD.Value /= SCOD.Value then - - -- If the old value does not match the new one, it means - -- that we are consolidating 2 checkpoints where the - -- condition was static in one of them, and non-static - -- in the other. - -- In consequences, we ensure the SCO is flagged as - -- Unknown because some of it was evaluated at run time. - -- Also, we need tp keep a track of the static evaluation - -- to make sure it's accounted for in the runtime - -- coverage computation. - - Misc_Trace.Trace ("Consolidation will merge condition" - & " SCOs that are both static and" - & " non-static at " + if Old_SCOD.Decision_BDD.Reachable_Outcomes /= + SCOD.Decision_BDD.Reachable_Outcomes + then + Misc_Trace.Trace ("Consolidation encountered a decision" + & " whose staticness differs in" + & " checkpoints at" & Image (SCOD.Sloc_Range)); + declare + Old_Reachable : Reachability renames + Old_SCOD.Decision_BDD.Reachable_Outcomes; + Reachable : Reachability renames + SCOD.Decision_BDD.Reachable_Outcomes; + + Old_Outcome : constant Tristate := + (if Old_Reachable (False) /= Old_Reachable (True) + then To_Tristate (Old_Reachable (True)) + else Unknown); + Outcome : constant Tristate := + (if Reachable (False) /= Reachable (True) + then To_Tristate (Reachable (True)) + else Unknown); + begin + if Old_Outcome = True or else Outcome = True then + CLS.True_Static_SCOs.Include (New_SCO_Id); + end if; - if Old_SCOD.Value = False or else SCOD.Value = False then - CLS.False_Static_SCOs.Include (Parent (New_SCO_Id)); - end if; - if Old_SCOD.Value = True or else SCOD.Value = True then - CLS.True_Static_SCOs.Include (Parent (New_SCO_Id)); - end if; + if Old_Outcome = False or else Outcome = False then + CLS.False_Static_SCOs.Include (New_SCO_Id); + end if; - SCOD.Value := Unknown; + Reachable (True) := Reachable (True) or else + Old_Reachable (True); + + Reachable (False) := Reachable (False) or else + Old_Reachable (False); + + end; end if; when Fun_Call_SCO_Kind => From 77da105350dca20a050cf15722e50795e7eb61af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 11 Dec 2024 11:45:50 +0100 Subject: [PATCH 1063/1483] Create internal functions detached from global variables for some functions in sc_obligations.adb --- tools/gnatcov/sc_obligations.adb | 96 +++++++++++++++++++++++++++----- 1 file changed, 81 insertions(+), 15 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 0960343a8..5ccc69c9c 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -562,6 +562,35 @@ package body SC_Obligations is SCO_Vector : SCO_Vectors.Vector; end record; + function Condition + (Vectors : Source_Coverage_Vectors; + SCO : SCO_Id; + Index : Condition_Index) return SCO_Id; + -- Internal definition of the function free from global variables + + function Enclosing + (Vectors : Source_Coverage_Vectors; + What : SCO_Kind; + SCO : SCO_Id) return SCO_Id; + -- Internal definition of the function free from global variables + + function Next_BDD_Node + (Vectors : Source_Coverage_Vectors; + SCO : SCO_Id; + Value : Boolean) return BDD_Node_Id; + -- Internal definition of the function free from global variables + + function Outcome + (Vectors : Source_Coverage_Vectors; + SCO : SCO_Id; + Value : Boolean) return Tristate; + -- Internal definition of the function free from global variables + + function Value + (Vectors : Source_Coverage_Vectors; + SCO : SCO_Id) return Tristate; + -- Internal definition of the function free from global variables + ----------------------------------------- -- Helper routines for Checkpoint_Load -- ----------------------------------------- @@ -2414,10 +2443,15 @@ package body SC_Obligations is -- Condition -- --------------- - function Condition (SCO : SCO_Id; Index : Condition_Index) return SCO_Id is + function Condition + (Vectors : Source_Coverage_Vectors; + SCO : SCO_Id; + Index : Condition_Index) return SCO_Id + is use BDD; - SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); + SCOD : SCO_Descriptor renames + Vectors.SCO_Vector.Constant_Reference (SCO); First : constant BDD_Node_Id := SCOD.Decision_BDD.First_Node; Last : constant BDD_Node_Id := SCOD.Decision_BDD.Last_Node; @@ -2428,14 +2462,15 @@ package body SC_Obligations is for J in First .. Last loop declare - BDDN : BDD_Node renames BDD_Vector.Constant_Reference (J); + BDDN : BDD_Node renames Vectors.BDD_Vector.Constant_Reference (J); begin if BDDN.Kind = Condition then Current_Condition_Index := Current_Condition_Index + 1; if Current_Condition_Index = Index then return C_SCO : constant SCO_Id := BDDN.C_SCO do - pragma Assert (Enclosing_Decision (C_SCO) = SCO); + pragma Assert + (Enclosing (Vectors, Decision, C_SCO) = SCO); pragma Assert (SC_Obligations.Index (C_SCO) = Index); null; end return; @@ -2446,6 +2481,9 @@ package body SC_Obligations is raise Constraint_Error with "condition index out of range"; end Condition; + function Condition (SCO : SCO_Id; Index : Condition_Index) return SCO_Id is + (Condition (SC_Vectors, SCO, Index)); + ---------------------- -- Condition_Values -- ---------------------- @@ -2626,12 +2664,16 @@ package body SC_Obligations is -- Enclosing -- --------------- - function Enclosing (What : SCO_Kind; SCO : SCO_Id) return SCO_Id is + function Enclosing + (Vectors : Source_Coverage_Vectors; + What : SCO_Kind; + SCO : SCO_Id) return SCO_Id is begin return Result : SCO_Id := SCO do while Result /= No_SCO_Id loop declare - SCOD : SCO_Descriptor renames SCO_Vector.Reference (Result); + SCOD : SCO_Descriptor renames + Vectors.SCO_Vector.Constant_Reference (Result); begin if SCOD.Kind = What then return; @@ -2642,6 +2684,9 @@ package body SC_Obligations is end return; end Enclosing; + function Enclosing (What : SCO_Kind; SCO : SCO_Id) return SCO_Id + is (Enclosing (SC_Vectors, What, SCO)); + ------------ -- Nested -- ------------ @@ -4690,15 +4735,22 @@ package body SC_Obligations is ------------------- function Next_BDD_Node - (SCO : SCO_Id; + (Vectors : Source_Coverage_Vectors; + SCO : SCO_Id; Value : Boolean) return BDD_Node_Id is use BDD; - BDD_Node : constant BDD_Node_Id := SCO_Vector.Reference (SCO).BDD_Node; + BDD_Node : constant BDD_Node_Id := + Vectors.SCO_Vector.Constant_Reference (SCO).BDD_Node; begin - return BDD_Vector.Reference (BDD_Node).Dests (Value); + return Vectors.BDD_Vector.Constant_Reference (BDD_Node).Dests (Value); end Next_BDD_Node; + function Next_BDD_Node + (SCO : SCO_Id; + Value : Boolean) return BDD_Node_Id + is (Next_BDD_Node (SC_Vectors, SCO, Value)); + -------------------- -- Next_Condition -- -------------------- @@ -4749,7 +4801,11 @@ package body SC_Obligations is -- Outcome -- ------------- - function Outcome (SCO : SCO_Id; Value : Boolean) return Tristate is + function Outcome + (Vectors : Source_Coverage_Vectors; + SCO : SCO_Id; + Value : Boolean) return Tristate + is use BDD; Cond_SCO : SCO_Id := SCO; Cond_Value : Boolean := Value; @@ -4757,8 +4813,8 @@ package body SC_Obligations is loop declare BDDN : constant BDD_Node := - BDD_Vector.Constant_Reference - (Next_BDD_Node (Cond_SCO, Cond_Value)); + Vectors.BDD_Vector.Constant_Reference + (Next_BDD_Node (Vectors, Cond_SCO, Cond_Value)); begin case BDDN.Kind is when Outcome => @@ -4767,7 +4823,7 @@ package body SC_Obligations is when Condition => declare Next_Value : constant Tristate := - SC_Obligations.Value (BDDN.C_SCO); + SC_Obligations.Value (Vectors, BDDN.C_SCO); begin if Next_Value = Unknown then return Unknown; @@ -4783,17 +4839,27 @@ package body SC_Obligations is end loop; end Outcome; + function Outcome (SCO : SCO_Id; Value : Boolean) return Tristate + is (Outcome (SC_Vectors, SCO, Value)); + ----------- -- Value -- ----------- - function Value (SCO : SCO_Id) return Tristate is - SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); + function Value + (Vectors : Source_Coverage_Vectors; + SCO : SCO_Id) return Tristate + is + SCOD : SCO_Descriptor renames + Vectors.SCO_Vector.Constant_Reference (SCO); pragma Assert (SCOD.Kind = Condition); begin return SCOD.Value; end Value; + function Value (SCO : SCO_Id) return Tristate + is (Value (SC_Vectors, SCO)); + ------------ -- Parent -- ------------ From 73f13b4021b51455dd933f46e8f123422255f2ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 11 Dec 2024 16:00:08 +0100 Subject: [PATCH 1064/1483] Handle MCDC decisions in static/dynamic decision merging --- tools/gnatcov/checkpoints.ads | 3 +- tools/gnatcov/coverage-source.adb | 87 +++++++--- tools/gnatcov/sc_obligations-bdd.ads | 2 + tools/gnatcov/sc_obligations.adb | 239 +++++++++++++++++++++------ tools/gnatcov/sc_obligations.ads | 19 +++ 5 files changed, 278 insertions(+), 72 deletions(-) diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 7f0b781d6..029384f98 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -292,8 +292,7 @@ package Checkpoints is Relocations : Checkpoint_Relocations; - True_Static_SCOs : SCO_Sets.Set; - False_Static_SCOs : SCO_Sets.Set; + Static_Decision_Evaluations : Static_Decision_Evaluation_Maps.Map; end record; use type Interfaces.Unsigned_32; diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 65eb83969..010e33ce6 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -568,28 +568,77 @@ package body Coverage.Source is SCO : constant SCO_Id := (if Removed then No_SCO_Id else Remap_SCO_Id (Relocs, CP_SCO)); - procedure Insert_Extra_Decision_SCI (B : Boolean); - - procedure Insert_Extra_Decision_SCI (B : Boolean) is - Inserted_SCI : - constant Source_Coverage_Info := - (Kind => Decision, - Known_Outcome_Taken => - (True => B, False => not B), - others => <>); + 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; Eval : Static_Decision_Evaluation) + return Evaluation; + -- Create an `Evaluation` entry from a + -- Static_Decision_Evaluation. + + function To_Evaluation + (SCO : SCO_Id; Eval : Static_Decision_Evaluation) + return Evaluation + is + E : Evaluation := + (Decision => SCO, + Outcome => To_Tristate (Eval.Outcome), + Values => Condition_Evaluation_Vectors.Empty, + Next_Condition => No_Condition_Index); + begin + for B of Eval.Values loop + E.Values.Append (To_Tristate (B)); + end loop; + + return E; + end To_Evaluation; + begin - Merge_Checkpoint_SCI - (SCO, - Tag_Provider.Map_Tag (Relocs, Inserted_SCI.Tag), - Inserted_SCI, - Relocs); + 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.True_Static_SCOs.Contains (CP_SCO) then - Insert_Extra_Decision_SCI (True); - end if; - if CLS.False_Static_SCOs.Contains (CP_SCO) then - Insert_Extra_Decision_SCI (False); + 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 diff --git a/tools/gnatcov/sc_obligations-bdd.ads b/tools/gnatcov/sc_obligations-bdd.ads index 444f87faa..ec3865d2c 100644 --- a/tools/gnatcov/sc_obligations-bdd.ads +++ b/tools/gnatcov/sc_obligations-bdd.ads @@ -92,6 +92,8 @@ private package SC_Obligations.BDD is type Reachability is array (Boolean) of Boolean; + Both_Reachable : constant Reachability := (others => True); + type BDD_Type is record Decision : SCO_Id; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 5ccc69c9c..9cc169b89 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -1350,6 +1350,171 @@ package body SC_Obligations is is Relocs : Checkpoint_Relocations renames CLS.Relocations; Real_CU : CU_Info renames CU_Vector.Reference (Real_CU_Id).Element.all; + + procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) + with pre => Kind (New_SCO_Id) = Decision; + + procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) + is + use SC_Obligations.BDD; + + Old_SCOD : SCO_Descriptor renames CP_Vectors.SCO_Vector (Old_SCO_Id); + New_SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); + + Old_Reachable : Reachability renames + Old_SCOD.Decision_BDD.Reachable_Outcomes; + New_Reachable : Reachability renames + New_SCOD.Decision_BDD.Reachable_Outcomes; + + function Decision_Static_Eval + (Vectors : Source_Coverage_Vectors; + SCO_Dec : SCO_Id; + Eval : out Static_Decision_Evaluation) return Boolean; + + function Decision_Static_Eval + (Vectors : Source_Coverage_Vectors; + SCO_Dec : SCO_Id; + Eval : out Static_Decision_Evaluation) return Boolean + is + SCOD : SCO_Descriptor renames Vectors.SCO_Vector (SCO_Dec); + + Reachable : constant Reachability := + SCOD.Decision_BDD.Reachable_Outcomes; + + Outcome : constant Tristate := + (if Reachable (False) /= Reachable (True) + then To_Tristate (Reachable (True)) + else Unknown); + + E : Static_Decision_Evaluation; + begin + + -- Do not process evaluations if the decision is not at least + -- partially static. + + if Outcome = Unknown then + return False; + end if; + + E.Outcome := To_Boolean (Outcome); + + for J in Condition_Index'First .. SCOD.Last_Cond_Index + loop + declare + SCO_C : constant SCO_Id := + Condition (Vectors, SCO_Dec, J); + SCOD_C : SCO_Descriptor renames + Vectors.SCO_Vector (SCO_C); + begin + + -- If an encountered Condition has no Value, then the + -- Decision is not fully static, abort processing + + if SCOD_C.Value = Unknown then + E.Values.Clear; + return False; + end if; + + E.Values.Append (To_Boolean (SCOD_C.Value)); + end; + end loop; + + Eval := E; + return True; + end Decision_Static_Eval; + + procedure Register_Static_Evaluation + (SCO : SCO_Id; Eval : Static_Decision_Evaluation); + + procedure Register_Static_Evaluation + (SCO : SCO_Id; Eval : Static_Decision_Evaluation) is + begin + if not CLS.Static_Decision_Evaluations.Contains (SCO) + then + CLS.Static_Decision_Evaluations.Insert + (SCO, + Static_Decision_Evaluation_Sets.Empty_Set); + end if; + CLS.Static_Decision_Evaluations + .Reference (SCO) + .Include (Eval); + end Register_Static_Evaluation; + + -- Start processing of Merge_Decision_SCOs + + begin + if Old_SCOD.Decision_Instrumented then + New_SCOD.Decision_Instrumented := True; + end if; + if Old_SCOD.Decision_Instrumented_For_MCDC then + New_SCOD.Decision_Instrumented_For_MCDC := True; + end if; + + -- The following code handles merging Decision SCOs that have a + -- different staticness over the 2 checkpoints that are being merged. + -- + -- If the reachability of the decision in one of the checkpoints + -- differs from `Both_Reachable`, it means that at least one of the + -- two checkpoints has some static conditions and should be handled + -- with a specific treatment. + -- + -- Upon encountering a fully-static decision, we need to register its + -- conditions' values so they can be used as a complementary + -- evaluation for MC/DC analysis. + + if Old_Reachable /= Both_Reachable + or else + New_Reachable /= Both_Reachable + then + SCOs_Trace.Trace ("Consolidation encountered a decision SCO" + & " whose staticness may differ at" + & Image (New_SCOD.Sloc_Range)); + declare + Old_Eval : Static_Decision_Evaluation; + -- Holds the result of the static evaluation of Old_SCO + -- if Old_Static is True. Otherwise, it is invalid. + + New_Eval : Static_Decision_Evaluation; + -- Holds the result of the static evaluation of New_SCO + -- if New_Static is True. Otherwise, it is invalid. + + Old_Static : constant Boolean := + Decision_Static_Eval (CP_Vectors, Old_SCO_Id, Old_Eval); + New_Static : constant Boolean := + Decision_Static_Eval (SC_Vectors, New_SCO_Id, New_Eval); + + begin + + -- No matter the staticness of the SCOs, we update the + -- reachability of each outcome by OR-ing the two checkpoints. + + New_Reachable (True) := New_Reachable (True) or else + Old_Reachable (True); + + New_Reachable (False) := New_Reachable (False) or else + Old_Reachable (False); + + if Old_Static then + + -- If the decision in the Old checkpoint is static, + -- add an evaluation to the SCIs corresponding to it. + + Register_Static_Evaluation (New_SCO_Id, Old_Eval); + end if; + + if New_Static then + + -- If the decision in the New checkpoint is static, + -- add an evaluation to the SCIs corresponding to it. + + Register_Static_Evaluation (New_SCO_Id, New_Eval); + end if; + end; + end if; + end Merge_Decision_SCOs; + + -- Start processing of Checkpoint_Load_Merge_Unit + begin -- Here we already have loaded full SCO information for this CU. There -- are two things to do: @@ -1377,12 +1542,12 @@ package body SC_Obligations is - CP_CU.First_SCO); declare - use SC_Obligations.BDD; Old_SCOD : SCO_Descriptor renames CP_Vectors.SCO_Vector (Old_SCO_Id); New_SCO_Id : constant SCO_Id := Remap_SCO_Id (Relocs, Old_SCO_Id); SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); + begin case SCOD.Kind is when Statement => @@ -1391,56 +1556,7 @@ package body SC_Obligations is end if; when Decision => - if Old_SCOD.Decision_Instrumented then - SCOD.Decision_Instrumented := True; - end if; - if Old_SCOD.Decision_Instrumented_For_MCDC then - SCOD.Decision_Instrumented_For_MCDC := True; - end if; - - -- If the reachable outcomes of a decision differ, we know - -- these have different staticness. it can be - -- - merging static with non-static decisions - -- - merging true-static with false-static decisions - - if Old_SCOD.Decision_BDD.Reachable_Outcomes /= - SCOD.Decision_BDD.Reachable_Outcomes - then - Misc_Trace.Trace ("Consolidation encountered a decision" - & " whose staticness differs in" - & " checkpoints at" - & Image (SCOD.Sloc_Range)); - declare - Old_Reachable : Reachability renames - Old_SCOD.Decision_BDD.Reachable_Outcomes; - Reachable : Reachability renames - SCOD.Decision_BDD.Reachable_Outcomes; - - Old_Outcome : constant Tristate := - (if Old_Reachable (False) /= Old_Reachable (True) - then To_Tristate (Old_Reachable (True)) - else Unknown); - Outcome : constant Tristate := - (if Reachable (False) /= Reachable (True) - then To_Tristate (Reachable (True)) - else Unknown); - begin - if Old_Outcome = True or else Outcome = True then - CLS.True_Static_SCOs.Include (New_SCO_Id); - end if; - - if Old_Outcome = False or else Outcome = False then - CLS.False_Static_SCOs.Include (New_SCO_Id); - end if; - - Reachable (True) := Reachable (True) or else - Old_Reachable (True); - - Reachable (False) := Reachable (False) or else - Old_Reachable (False); - - end; - end if; + Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id); when Fun_Call_SCO_Kind => if Old_SCOD.Fun_Call_Instrumented then @@ -1493,6 +1609,27 @@ package body SC_Obligations is end; end Checkpoint_Load_Merge_Unit; + function "<" (L, R : Static_Decision_Evaluation) return Boolean is + begin + if L.Outcome /= R.Outcome then + return L.Outcome < R.Outcome; + end if; + + for J in R.Values.First_Index .. R.Values.Last_Index loop + if J > L.Values.Last_Index then + return True; + + elsif L.Values.Element (J) < R.Values.Element (J) then + return True; + + elsif L.Values.Element (J) > R.Values.Element (J) then + return False; + end if; + end loop; + + return False; + end "<"; + ------------------------------ -- Checkpoint_Load_New_Unit -- ------------------------------ diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 4f135f6c2..a719fed64 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -552,6 +552,25 @@ package SC_Obligations is type Condition_Values_Array is array (Condition_Index range <>) of Tristate; + package Static_Condition_Values_Vectors is new Ada.Containers.Vectors + (Index_Type => Condition_Index, + Element_Type => Boolean); + + type Static_Decision_Evaluation is record + Values : Static_Condition_Values_Vectors.Vector; + Outcome : Boolean; + end record; + + function "<" (L, R : Static_Decision_Evaluation) return Boolean; + + package Static_Decision_Evaluation_Sets is new Ada.Containers.Ordered_Sets + (Static_Decision_Evaluation); + + package Static_Decision_Evaluation_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => SCO_Id, + Element_Type => Static_Decision_Evaluation_Sets.Set, + "=" => Static_Decision_Evaluation_Sets.Equivalent_Sets); + type Operand_Position is (Left, Right); -- Expose BDD node id type for the benefit of checkpoints From ee109217e0fea0c4346daf5e452ede16ff841a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 13 Dec 2024 16:30:18 +0100 Subject: [PATCH 1065/1483] Fix the special case of a decision being consolidated twice with different static evaluation vectors that still bring to the same outcome --- tools/gnatcov/coverage-source.adb | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 010e33ce6..8e1c14959 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -1005,10 +1005,32 @@ package body Coverage.Source is -- information. if Decision_Outcome (SCO) /= Unknown then - -- Case of a compile time known decision: exclude from + -- Case of a compile time known decision + -- exclude from -- coverage analysis. - if Report_If_Excluded (SCO) then + if SCI.Evaluations.Length > 1 then + -- Case of a compile time known decision that was + -- consolidated with several checkpoints in which + -- the decision had different static conditions, but + -- kept the same outcome anyway. + + -- In this case, we chose to report the violation, + -- because if you have a static decision in your code + -- that may change depending on the build context, + -- then you SHOULD get it covered + + SCO_State := Not_Covered; + Report_Violation + (SCO, + SCI.Tag, + "outcome " + & To_Boolean (Decision_Outcome (SCO))'Image + & " never exercised"); + Update_Line_State + (Line_Info, SCO, SCI.Tag, Decision, SCO_State); + + elsif Report_If_Excluded (SCO) then SCO_State := Not_Coverable; -- Note: we do not report the exclusion of this SCO, From f3b578c2f0c4cb28dffd5d38d060a953c34fbcdc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Tue, 17 Dec 2024 10:58:55 +0100 Subject: [PATCH 1066/1483] Handle short-circuit semantics for merging static MCDC decisions --- tools/gnatcov/coverage-source.adb | 16 ++++---- tools/gnatcov/mc_dc.adb | 20 +--------- tools/gnatcov/mc_dc.ads | 11 ------ tools/gnatcov/sc_obligations.adb | 62 +++++++++++++++++++++++++++++++ tools/gnatcov/sc_obligations.ads | 18 +++++++++ 5 files changed, 88 insertions(+), 39 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 8e1c14959..878138487 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -580,26 +580,24 @@ package body Coverage.Source is (Kind => Decision, others => <>); function To_Evaluation - (SCO : SCO_Id; Eval : Static_Decision_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; Eval : Static_Decision_Evaluation) + (SCO : SCO_Id; Static_Eval : Static_Decision_Evaluation) return Evaluation is - E : Evaluation := + Eval : Evaluation := (Decision => SCO, - Outcome => To_Tristate (Eval.Outcome), + Outcome => To_Tristate (Static_Eval.Outcome), Values => Condition_Evaluation_Vectors.Empty, Next_Condition => No_Condition_Index); begin - for B of Eval.Values loop - E.Values.Append (To_Tristate (B)); - end loop; - - return E; + Populate_From_Static_Eval_Vector + (SCO, Static_Eval.Values, Eval.Values); + return Eval; end To_Evaluation; begin diff --git a/tools/gnatcov/mc_dc.adb b/tools/gnatcov/mc_dc.adb index f04574231..7e844aa04 100644 --- a/tools/gnatcov/mc_dc.adb +++ b/tools/gnatcov/mc_dc.adb @@ -16,6 +16,7 @@ -- of the license. -- ------------------------------------------------------------------------------ +with Ada.Containers; with Ada.Strings.Fixed; use Ada.Strings.Fixed; package body MC_DC is @@ -194,25 +195,6 @@ package body MC_DC is return First_Different; end Is_MC_DC_Pair; - --------------- - -- To_Vector -- - --------------- - - function To_Vector - (Cond_Values : Condition_Values_Array) - return Condition_Evaluation_Vectors.Vector - is - Result : Condition_Evaluation_Vectors.Vector := - Condition_Evaluation_Vectors.To_Vector - (Unknown, Length => Cond_Values'Length); - - begin - for J in Cond_Values'Range loop - Result.Replace_Element (J, Cond_Values (J)); - end loop; - return Result; - end To_Vector; - ---------- -- Read -- ---------- diff --git a/tools/gnatcov/mc_dc.ads b/tools/gnatcov/mc_dc.ads index e8d39ac90..69f957093 100644 --- a/tools/gnatcov/mc_dc.ads +++ b/tools/gnatcov/mc_dc.ads @@ -18,22 +18,11 @@ -- Support for MC/DC coverage analysis -with Ada.Containers.Vectors; - with Checkpoints; use Checkpoints; with SC_Obligations; use SC_Obligations; package MC_DC is - package Condition_Evaluation_Vectors is new Ada.Containers.Vectors - (Index_Type => Condition_Index, - Element_Type => Tristate); - - function To_Vector - (Cond_Values : Condition_Values_Array) - return Condition_Evaluation_Vectors.Vector; - -- Convert Cond_Values to a vector - -- Type Evaluation denotes one evaluation of a decision type Evaluation is record diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 9cc169b89..c2f95d175 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -5194,6 +5194,68 @@ package body SC_Obligations is SCO_Vector.Reference (C_SCO).BDD_Node := BDD_Node; end Set_BDD_Node; + --------------- + -- To_Vector -- + --------------- + + function To_Vector + (Cond_Values : Condition_Values_Array) + return Condition_Evaluation_Vectors.Vector + is + Result : Condition_Evaluation_Vectors.Vector := + Condition_Evaluation_Vectors.To_Vector + (Unknown, Length => Cond_Values'Length); + + begin + for J in Cond_Values'Range loop + Result.Replace_Element (J, Cond_Values (J)); + end loop; + return Result; + end To_Vector; + + -------------------------------------- + -- Populate_From_Static_Eval_Vector -- + -------------------------------------- + + procedure Populate_From_Static_Eval_Vector + (SCO : SCO_Id; + Static_Vec : Static_Condition_Values_Vectors.Vector; + Vec : out Condition_Evaluation_Vectors.Vector) + is + use BDD; -- For using '=' for BDD_Node_Kind + + SCOD : SCO_Descriptor renames SCO_Vector.Constant_Reference (SCO); + D_BDD : constant BDD.BDD_Type := SCOD.Decision_BDD; + + Cur : BDD_Node_Id := D_BDD.Root_Condition; + begin + + -- First, fill the vector with 'unknown' + + Vec := Condition_Evaluation_Vectors.Empty; + for B of Static_Vec loop + Vec.Append (Unknown); + end loop; + + -- Then, walk the BDD from the root and only follow the path of the + -- constant value. Unencountered nodes will stay unknown, to preserve + -- short-circuit semantics of operators when performing MCDC analysis. + + while BDD_Vector.Constant_Reference (Cur).Kind = Condition loop + declare + C_SCO : constant SCO_Id := + BDD_Vector.Constant_Reference (Cur).C_SCO; + Index : constant Condition_Index := + SCO_Vector.Element (C_SCO).Index; + Value : constant Boolean := Static_Vec (Index); + begin + Vec (Index) := To_Tristate (Value); + + Cur := BDD_Vector.Constant_Reference (Cur).Dests (Value); + end; + end loop; + end Populate_From_Static_Eval_Vector; + --------------------------- -- Are_Bit_Maps_In_Range -- --------------------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index a719fed64..1392b5b79 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -552,6 +552,15 @@ package SC_Obligations is type Condition_Values_Array is array (Condition_Index range <>) of Tristate; + package Condition_Evaluation_Vectors is new Ada.Containers.Vectors + (Index_Type => Condition_Index, + Element_Type => Tristate); + + function To_Vector + (Cond_Values : Condition_Values_Array) + return Condition_Evaluation_Vectors.Vector; + -- Convert Cond_Values to a vector + package Static_Condition_Values_Vectors is new Ada.Containers.Vectors (Index_Type => Condition_Index, Element_Type => Boolean); @@ -1583,6 +1592,15 @@ package SC_Obligations is Unknown_Pragma => True); + procedure Populate_From_Static_Eval_Vector + (SCO : SCO_Id; + Static_Vec : Static_Condition_Values_Vectors.Vector; + Vec : out Condition_Evaluation_Vectors.Vector); + -- Given a static evaluation vector, the function fills the condition + -- evaluation vector while letting the un-encountered condition to + -- 'unknown', so the short-circuited conditions don't prevent MCDC + -- coverage of other conditions. + private -- Write accessors for child units From fb8ccc2cf4d1497962df000ba46bbb63eea99b35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 6 Dec 2024 12:21:43 +0100 Subject: [PATCH 1067/1483] Add test for non-static/static simple decision merging --- .../common/src-double/greet.gpr | 34 ++++ .../common/src-double/main.adb | 6 + .../common/src-double/src-greet/df1_pkg.ads | 9 + .../common/src-double/src-greet/df2_pkg.ads | 9 + .../common/src-double/src-greet/dt1_pkg.ads | 9 + .../common/src-double/src-greet/dt2_pkg.ads | 9 + .../common/src-double/src-greet/greet.adb | 13 ++ .../common/src-double/src-greet/greet.ads | 3 + .../common/src-double/src-greet/sf1_pkg.ads | 5 + .../common/src-double/src-greet/sf2_pkg.ads | 5 + .../common/src-double/src-greet/st1_pkg.ads | 5 + .../common/src-double/src-greet/st2_pkg.ads | 5 + .../common/src-simple/greet.gpr | 22 +++ .../common/src-simple/main.adb | 6 + .../common/src-simple/src-greet/df_pkg.ads | 9 + .../common/src-simple/src-greet/dt_pkg.ads | 9 + .../common/src-simple/src-greet/greet.adb | 11 ++ .../common/src-simple/src-greet/greet.ads | 3 + .../common/src-simple/src-greet/sf_pkg.ads | 5 + .../common/src-simple/src-greet/st_pkg.ads | 5 + .../common/test_utils.py | 178 ++++++++++++++++++ .../complex_or-decision/extra.opt | 1 + .../complex_or-decision/test.py | 150 +++++++++++++++ .../complex_or-mcdc/extra.opt | 1 + .../complex_or-mcdc/test.py | 164 ++++++++++++++++ .../simple-decision/extra.opt | 1 + .../simple-decision/test.py | 85 +++++++++ 27 files changed, 762 insertions(+) create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/main.adb create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/df1_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/df2_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/dt1_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/dt2_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.adb create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/sf1_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/sf2_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/st1_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/st2_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/main.adb create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/df_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/dt_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.adb create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/sf_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/st_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/test_utils.py create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/extra.opt create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/test.py create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/extra.opt create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/test.py create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/extra.opt create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/test.py diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr new file mode 100644 index 000000000..23bad9181 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr @@ -0,0 +1,34 @@ +project Greet is + for Source_Dirs use ("src-greet"); + + type Decision_Type is + ("static_true", "static_false", "dynamic_true", "dynamic_false"); + + Val1_Impl : Decision_Type := + external ("DEC1", "static_true"); + Val2_Impl : Decision_Type := + external ("DEC2", "static_true"); + + package Naming is + case Val1_Impl is + when "static_true" => + for Spec ("Pkg1") use "st1_pkg.ads"; + when "static_false" => + for Spec ("Pkg1") use "sf1_pkg.ads"; + when "dynamic_true" => + for Spec ("Pkg1") use "dt1_pkg.ads"; + when "dynamic_false" => + for Spec ("Pkg1") use "df1_pkg.ads"; + end case; + case Val2_Impl is + when "static_true" => + for Spec ("Pkg2") use "st2_pkg.ads"; + when "static_false" => + for Spec ("Pkg2") use "sf2_pkg.ads"; + when "dynamic_true" => + for Spec ("Pkg2") use "dt2_pkg.ads"; + when "dynamic_false" => + for Spec ("Pkg2") use "df2_pkg.ads"; + end case; + end Naming; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/main.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/main.adb new file mode 100644 index 000000000..31993887f --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/main.adb @@ -0,0 +1,6 @@ +with Greet; + +procedure Main is +begin + Greet.Say_Hi; +end Main; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/df1_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/df1_pkg.ads new file mode 100644 index 000000000..c0cecf51a --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/df1_pkg.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +package Pkg1 is + + function Difficult_True (X : Integer) return Boolean is + (if X mod 10 = 0 then (3 * X - 10) mod 10 = 0 else False); + + Val : Boolean := not Difficult_True (30); + +end Pkg1; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/df2_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/df2_pkg.ads new file mode 100644 index 000000000..f5044a218 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/df2_pkg.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +package Pkg2 is + + function Difficult_True (X : Integer) return Boolean is + (if X mod 10 = 0 then (3 * X - 10) mod 10 = 0 else False); + + Val : Boolean := not Difficult_True (30); + +end Pkg2; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/dt1_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/dt1_pkg.ads new file mode 100644 index 000000000..99ee44ed9 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/dt1_pkg.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +package Pkg1 is + + function Difficult_True (X : Integer) return Boolean is + (if X mod 10 = 0 then (3 * X - 10) mod 10 = 0 else False); + + Val : Boolean := Difficult_True (30); + +end Pkg1; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/dt2_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/dt2_pkg.ads new file mode 100644 index 000000000..c9bbc335e --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/dt2_pkg.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +package Pkg2 is + + function Difficult_True (X : Integer) return Boolean is + (if X mod 10 = 0 then (3 * X - 10) mod 10 = 0 else False); + + Val : Boolean := Difficult_True (30); + +end Pkg2; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.adb new file mode 100644 index 000000000..710021cf5 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.adb @@ -0,0 +1,13 @@ +pragma Ada_2012; +with Ada.Text_IO; +with Pkg1; +with Pkg2; + +package body Greet is + procedure Say_Hi is + begin + Ada.Text_IO.Put_Line + ("Pkg.Val: " & + (if Pkg1.Val or else Pkg2.Val then "True" else "False")); + end Say_Hi; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.ads new file mode 100644 index 000000000..5a336e804 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/greet.ads @@ -0,0 +1,3 @@ +package Greet is + procedure Say_Hi; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/sf1_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/sf1_pkg.ads new file mode 100644 index 000000000..88ee3b7d0 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/sf1_pkg.ads @@ -0,0 +1,5 @@ +package Pkg1 is + + Val : constant Boolean := False; + +end Pkg1; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/sf2_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/sf2_pkg.ads new file mode 100644 index 000000000..d11820acb --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/sf2_pkg.ads @@ -0,0 +1,5 @@ +package Pkg2 is + + Val : constant Boolean := False; + +end Pkg2; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/st1_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/st1_pkg.ads new file mode 100644 index 000000000..82fa4f3bb --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/st1_pkg.ads @@ -0,0 +1,5 @@ +package Pkg1 is + + Val : constant Boolean := True; + +end Pkg1; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/st2_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/st2_pkg.ads new file mode 100644 index 000000000..56f4e3083 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/st2_pkg.ads @@ -0,0 +1,5 @@ +package Pkg2 is + + Val : constant Boolean := True; + +end Pkg2; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr new file mode 100644 index 000000000..6d2137c95 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr @@ -0,0 +1,22 @@ +project Greet is + for Source_Dirs use ("src-greet"); + + type Decision_Type is + ("static_true", "static_false", "dynamic_true", "dynamic_false"); + + Val_Impl : Decision_Type := + external ("DECISION_TYPE", "static_true"); + + package Naming is + case Val_Impl is + when "static_true" => + for Spec ("Pkg") use "st_pkg.ads"; + when "static_false" => + for Spec ("Pkg") use "sf_pkg.ads"; + when "dynamic_true" => + for Spec ("Pkg") use "dt_pkg.ads"; + when "dynamic_false" => + for Spec ("Pkg") use "df_pkg.ads"; + end case; + end Naming; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/main.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/main.adb new file mode 100644 index 000000000..31993887f --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/main.adb @@ -0,0 +1,6 @@ +with Greet; + +procedure Main is +begin + Greet.Say_Hi; +end Main; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/df_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/df_pkg.ads new file mode 100644 index 000000000..7c903fe06 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/df_pkg.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +package Pkg is + + function Difficult_True (X : Integer) return Boolean is + (if X mod 10 = 0 then (3 * X - 10) mod 10 = 0 else False); + + Val : Boolean := not Difficult_True (30); + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/dt_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/dt_pkg.ads new file mode 100644 index 000000000..ef5024163 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/dt_pkg.ads @@ -0,0 +1,9 @@ +pragma Ada_2012; +package Pkg is + + function Difficult_True (X : Integer) return Boolean is + (if X mod 10 = 0 then (3 * X - 10) mod 10 = 0 else False); + + Val : Boolean := Difficult_True (30); + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.adb new file mode 100644 index 000000000..2223f6ad2 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.adb @@ -0,0 +1,11 @@ +pragma Ada_2012; +with Ada.Text_IO; +with Pkg; + +package body Greet is + procedure Say_Hi is + begin + Ada.Text_IO.Put_Line + ("Pkg.Val: " & (if Pkg.Val then "True" else "False")); + end Say_Hi; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.ads new file mode 100644 index 000000000..5a336e804 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/greet.ads @@ -0,0 +1,3 @@ +package Greet is + procedure Say_Hi; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/sf_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/sf_pkg.ads new file mode 100644 index 000000000..4fa6bc049 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/sf_pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + Val : constant Boolean := False; + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/st_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/st_pkg.ads new file mode 100644 index 000000000..600efd95c --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/st_pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + Val : constant Boolean := True; + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/test_utils.py b/testsuite/tests/716-static-decision-merging-in-ckpt/common/test_utils.py new file mode 100644 index 000000000..d63d775c3 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/test_utils.py @@ -0,0 +1,178 @@ +from enum import Enum +import os +import os.path +import shutil + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +class PkgType(Enum): + """ + This enum describes the possible values with which we can replace a + condition in a file. + Either the condition is static (known at compile-time), or dynamic. + Each variant is available with True and False for exhaustive tests. + """ + + ST = "static_true" + SF = "static_false" + DT = "dynamic_true" + DF = "dynamic_false" + + def __str__(self): + return self.value + + +class CheckpointBuilder: + """ + This class factorizes the code for producing checkpoints from a function + with a decision whose staticness may be set depending on the test needs. + Sub-classes implement the specific cases and are attached to a specific + project that lives in a src-* folder next to this file. + """ + + _SRC_DIR = None + _MAIN = "main" + + EXPECT_EMPTY = {} + EXPECT_VIOLATION = {} + + def __init__(self, cov_level): + self.cov_level = cov_level + + # Instantiate the right source directory + self._copy_src_dir() + + def _copy_src_dir(self): + """ + Copy the test-case's directory (which is proper to the checkpoint + class) into the test's current dir + """ + src_src = self._SRC_DIR + src_dst = os.path.abspath("src") + if os.path.exists(src_dst): + shutil.rmtree(src_dst) + full_src_src = os.path.abspath(os.path.join(__file__, "..", src_src)) + shutil.copytree(full_src_src, src_dst) + + def make_checkpoint(self, name, xvars, deps=None): + """ + Function in charge of compiling the project with a given combination + of PkgTypes for each condition, and creating a checkpoint from the + program execution. + """ + gpr_obj_dir = "obj" + + prj_file = gprfor( + mains=[f"{self._MAIN}.adb"], + prjid=name, + srcdirs=os.path.join("src"), + objdir=gpr_obj_dir, + deps=[os.path.join("src", "greet.gpr")] + (deps or []), + ) + + ckpt = f"test_{name}.ckpt" + + build_run_and_coverage( + gprsw=GPRswitches( + root_project=prj_file, + units=["greet"], + xvars=xvars, + ), + covlevel=self.cov_level, + mains=[self._MAIN], + gpr_obj_dir=gpr_obj_dir, + extra_instr_args=["-v"], + extra_coverage_args=[ + "-v", + "--units=greet", + f"--save-checkpoint={ckpt}", + ], + ) + return ckpt + + +class SimpleConditionCheckpointBuilder(CheckpointBuilder): + _SRC_DIR = "src-simple" + + EXPECT_EMPTY = {"greet.adb.xcov": {}, "greet.ads.xcov": {}} + EXPECT_VIOLATION = {"greet.adb.xcov": {"!": {9}}, "greet.ads.xcov": {}} + + def new(self, dec_type): + return self.make_checkpoint( + str(dec_type), xvars=[("DECISION_TYPE", dec_type)] + ) + + +class IfStmtCheckpointBuilder(CheckpointBuilder): + _SRC_DIR = "src-if-stmt" + + EXPECT_EMPTY_STMT_COVERED = {"greet.adb.xcov": {}, "greet.ads.xcov": {}} + EXPECT_EMPTY_STMT_NOT_COVERED = { + "greet.adb.xcov": {"-": {9}}, + "greet.ads.xcov": {}, + } + EXPECT_VIOLATION_STMT_COVERED = { + "greet.adb.xcov": {"!": {8}}, + "greet.ads.xcov": {}, + } + EXPECT_VIOLATION_STMT_NOT_COVERED = { + "greet.adb.xcov": {"!": {8}, "-": {9}}, + "greet.ads.xcov": {}, + } + + def new(self, dec_type): + return self.make_checkpoint( + str(dec_type), xvars=[("DECISION_TYPE", dec_type)] + ) + + +class DoubleConditionCheckpointBuilder(CheckpointBuilder): + _SRC_DIR = "src-double" + + EXPECT_EMPTY = {"greet.adb.xcov": {}, "greet.ads.xcov": {}} + EXPECT_VIOLATION = {"greet.adb.xcov": {"!": {11}}, "greet.ads.xcov": {}} + + def new(self, type1, type2): + name = f"{type1}_{type2}" + return self.make_checkpoint( + name, xvars=[("DEC1", type1), ("DEC2", type2)] + ) + + +class TestCaseRunner: + """ + This class eases the verification of checkpoint consolidation results + through the xcov report + """ + + def __init__(self, cov_level): + self.base_cov_args = [ + "coverage", + "--annotate=xcov", + f"--level={cov_level}", + ] + + def run_test_case( + self, name: str, checkpoints, expected_report, verbose=True + ): + thistest.log(f"Test Case {name}") + slug_name = name.lower().replace(" ", "_") + + output_dir = f"testcase-{slug_name}" + + args = self.base_cov_args.copy() + args += [f"--output-dir={output_dir}"] + + if verbose: + args += ["-v"] + + # Add checkpoints + args += [item for ckpt in checkpoints for item in ["-C", ckpt]] + + xcov(args, f"{slug_name}.log") + + check_xcov_reports(output_dir, expected_report) diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/extra.opt b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/extra.opt new file mode 100644 index 000000000..0af3fdd02 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD test uses Ada2012 if-exprs, which are not supported by 5.04a1 diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/test.py b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/test.py new file mode 100644 index 000000000..ee8c0878e --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-decision/test.py @@ -0,0 +1,150 @@ +from pathlib import Path +import sys + +from SUITE.context import thistest +from SUITE.cutils import Wdir + +# Add the path of test utils to import it +sys.path.append( + str(Path(__file__).absolute().parent.parent.joinpath("common").resolve()) +) + +from test_utils import ( + DoubleConditionCheckpointBuilder, + TestCaseRunner, +) +from test_utils import PkgType as PT + +wd = Wdir("tmp_") + +COV_LEVEL = "stmt+decision" + +ckb = DoubleConditionCheckpointBuilder(COV_LEVEL) +tc_runner = TestCaseRunner(COV_LEVEL) + +# Checkpoint naming follows the convention: +# _ + +# Fully static +st_st = ckb.new(PT.ST, PT.ST) # decision is true +st_sf = ckb.new(PT.ST, PT.SF) # decision is true +sf_st = ckb.new(PT.SF, PT.ST) # decision is true +sf_sf = ckb.new(PT.SF, PT.SF) # decision is false +# Fully dynamic +dt_dt = ckb.new(PT.DT, PT.DT) # decision is true +dt_df = ckb.new(PT.DT, PT.DF) # decision is true +df_dt = ckb.new(PT.DF, PT.DT) # decision is true +df_df = ckb.new(PT.DF, PT.DF) # decision is false +# Partly static +dt_sf = ckb.new(PT.DT, PT.SF) # decision is false + +############# +# Test case # +############# +# Fully static decisions alone never raise violations +tc_runner.run_test_case("simple-static-1", [st_st], ckb.EXPECT_EMPTY) +tc_runner.run_test_case("simple-static-2", [st_sf], ckb.EXPECT_EMPTY) +tc_runner.run_test_case("simple-static-3", [sf_st], ckb.EXPECT_EMPTY) +tc_runner.run_test_case("simple-static-4", [sf_sf], ckb.EXPECT_EMPTY) + +############# +# Test case # +############# +# Dynamic decisions alone will raise violations +tc_runner.run_test_case("simple-dynamic-1", [dt_dt], ckb.EXPECT_VIOLATION) +tc_runner.run_test_case("simple-dynamic-2", [dt_df], ckb.EXPECT_VIOLATION) +tc_runner.run_test_case("simple-dynamic-3", [df_dt], ckb.EXPECT_VIOLATION) +tc_runner.run_test_case("simple-dynamic-4", [df_df], ckb.EXPECT_VIOLATION) + +############# +# Test case # +############# +# Partly static non-covering checkpoint raises a violation +tc_runner.run_test_case("simple_partly_static", [dt_sf], ckb.EXPECT_VIOLATION) + +############# +# Test case # +############# +# Ensure consolidating twice the same non-covering static decision evaluation +# does not raise a violation +tc_runner.run_test_case( + "OK_duplicate_static", [sf_sf, sf_sf], ckb.EXPECT_EMPTY +) + +############# +# Test case # +############# +# Consolidating several different static checkpoints that don't cover the +# decision raise a violation +tc_runner.run_test_case("KO_static", [sf_st, st_sf], ckb.EXPECT_VIOLATION) + +############# +# Test case # +############# +# Consolidating several different static checkpoints that don't cover the +# decision pass +tc_runner.run_test_case("OK_static", [sf_sf, sf_st], ckb.EXPECT_EMPTY) + +############# +# Test case # +############# +# Consolidating static and dynamic checkpoints that cover the decision +# raises no violation +tc_runner.run_test_case( + "OK_dynamic_static-1", [dt_df, sf_sf], ckb.EXPECT_EMPTY +) +tc_runner.run_test_case( + "OK_dynamic_static-2", [sf_sf, dt_dt], ckb.EXPECT_EMPTY +) + +############# +# Test case # +############# +# Consolidating static and dynamic checkpoints that don't cover the decision +# raises a violation +tc_runner.run_test_case( + "KO_dynamic_static-1", [dt_df, st_sf], ckb.EXPECT_VIOLATION +) +tc_runner.run_test_case( + "KO_dynamic_static-2", [st_sf, dt_df], ckb.EXPECT_VIOLATION +) + +############# +# Test case # +############# +# Consolidating partly static and static checkpoints +# OK +tc_runner.run_test_case( + "OK_partly_static_static-1", [dt_sf, sf_sf], ckb.EXPECT_EMPTY +) +tc_runner.run_test_case( + "OK_partly_static_static-2", [sf_sf, dt_sf], ckb.EXPECT_EMPTY +) +# KO +tc_runner.run_test_case( + "KO_partly_static_static-1", [dt_sf, st_sf], ckb.EXPECT_VIOLATION +) +tc_runner.run_test_case( + "KO_partly_static_static-2", [st_sf, dt_sf], ckb.EXPECT_VIOLATION +) + +############# +# Test case # +############# +# Consolidating partly static and dynamic checkpoints +# OK +tc_runner.run_test_case( + "OK_partly_static_dynamic-1", [dt_sf, df_df], ckb.EXPECT_EMPTY +) +tc_runner.run_test_case( + "OK_partly_static_dynamic-2", [df_df, dt_sf], ckb.EXPECT_EMPTY +) +# KO +tc_runner.run_test_case( + "KO_partly_static_dynamic-1", [dt_sf, dt_df], ckb.EXPECT_VIOLATION +) +tc_runner.run_test_case( + "KO_partly_static_dynamic-2", [dt_df, dt_sf], ckb.EXPECT_VIOLATION +) + +thistest.result() diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/extra.opt b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/extra.opt new file mode 100644 index 000000000..0af3fdd02 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD test uses Ada2012 if-exprs, which are not supported by 5.04a1 diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/test.py b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/test.py new file mode 100644 index 000000000..5aad2ff3a --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/complex_or-mcdc/test.py @@ -0,0 +1,164 @@ +from pathlib import Path +import sys + +from SUITE.context import thistest +from SUITE.cutils import Wdir + +# Add the path of test utils to import it +sys.path.append( + str(Path(__file__).absolute().parent.parent.joinpath("common").resolve()) +) + +from test_utils import ( + DoubleConditionCheckpointBuilder, + TestCaseRunner, +) +from test_utils import PkgType as PT + +wd = Wdir("tmp_") + +COV_LEVEL = "stmt+mcdc" + +ckb = DoubleConditionCheckpointBuilder(COV_LEVEL) +tc_runner = TestCaseRunner(COV_LEVEL) + +# Checkpoint naming follows the convention: +# _ + +# Fully static +st_st = ckb.new(PT.ST, PT.ST) # decision is true +st_sf = ckb.new(PT.ST, PT.SF) # decision is true +sf_st = ckb.new(PT.SF, PT.ST) # decision is true +sf_sf = ckb.new(PT.SF, PT.SF) # decision is false +# Fully dynamic +dt_dt = ckb.new(PT.DT, PT.DT) # decision is true +dt_df = ckb.new(PT.DT, PT.DF) # decision is true +df_dt = ckb.new(PT.DF, PT.DT) # decision is true +df_df = ckb.new(PT.DF, PT.DF) # decision is false +# Partly static +dt_sf = ckb.new(PT.DT, PT.SF) # decision is false + +############# +# Test case # +############# +# Fully static decisions alone never raise violations +tc_runner.run_test_case("simple-static-1", [st_st], ckb.EXPECT_EMPTY) +tc_runner.run_test_case("simple-static-2", [st_sf], ckb.EXPECT_EMPTY) +tc_runner.run_test_case("simple-static-3", [sf_st], ckb.EXPECT_EMPTY) +tc_runner.run_test_case("simple-static-4", [sf_sf], ckb.EXPECT_EMPTY) + +############# +# Test case # +############# +# Dynamic decisions alone will raise violations +tc_runner.run_test_case("simple-dynamic-1", [dt_dt], ckb.EXPECT_VIOLATION) +tc_runner.run_test_case("simple-dynamic-2", [dt_df], ckb.EXPECT_VIOLATION) +tc_runner.run_test_case("simple-dynamic-3", [df_dt], ckb.EXPECT_VIOLATION) +tc_runner.run_test_case("simple-dynamic-4", [df_df], ckb.EXPECT_VIOLATION) + +############# +# Test case # +############# +# Ensure consolidating twice the same non-covering static decision evaluation +# does not raise a violation +tc_runner.run_test_case( + "OK_duplicate_static", + [sf_sf, sf_sf], + ckb.EXPECT_EMPTY, +) + +############# +# Test case # +############# +# Covers the decision with static checkpoints only +tc_runner.run_test_case( + "OK_static", + [sf_sf, sf_st, st_sf], + ckb.EXPECT_EMPTY, +) + +############# +# Test case # +############# +# MCDC will raise a violation if several different static evaluations are +# merged and don't cover the decision +tc_runner.run_test_case( + "KO_static", + [sf_sf, sf_st], + ckb.EXPECT_VIOLATION, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "OK_dynamic", + [df_df, dt_df, df_dt], + ckb.EXPECT_EMPTY, +) + +############# +# Test case # +############# +# Ensure 'df_df' and 'dt_df' are not enough to cover the decision with MCDC +tc_runner.run_test_case( + "KO_dynamic", + [df_df, dt_df], + ckb.EXPECT_VIOLATION, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "OK_2_dynamic_then_static", + [df_df, dt_df, sf_st], + ckb.EXPECT_EMPTY, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "KO_2_dynamic_then_static", + [df_df, dt_df, st_sf], + ckb.EXPECT_VIOLATION, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "OK_2_dynamic_then_partly_static", + [df_df, df_dt, dt_sf], + ckb.EXPECT_EMPTY, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "KO_2_dynamic_then_partly_static", + [df_df, dt_df, dt_sf], + ckb.EXPECT_VIOLATION, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "OK_2_static_then_dynamic", + [sf_sf, st_sf, df_dt], + ckb.EXPECT_EMPTY, +) + +############# +# Test case # +############# +tc_runner.run_test_case( + "KO_2_static_then_dynamic", + [sf_sf, st_sf, dt_df], + ckb.EXPECT_VIOLATION, +) + +thistest.result() diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/extra.opt b/testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/extra.opt new file mode 100644 index 000000000..0af3fdd02 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD test uses Ada2012 if-exprs, which are not supported by 5.04a1 diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/test.py b/testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/test.py new file mode 100644 index 000000000..d3d085917 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/simple-decision/test.py @@ -0,0 +1,85 @@ +from pathlib import Path +import sys + +from SUITE.context import thistest +from SUITE.cutils import Wdir + +# Add the path of test utils to import it +sys.path.append( + str(Path(__file__).absolute().parent.parent.joinpath("common").resolve()) +) + +from test_utils import ( + SimpleConditionCheckpointBuilder, + TestCaseRunner, +) +from test_utils import PkgType as PT + +wd = Wdir("tmp_") + + +COV_LEVEL = "stmt+decision" + +ckb = SimpleConditionCheckpointBuilder(COV_LEVEL) +tc_runner = TestCaseRunner(COV_LEVEL) + +# Create two checkpoints with different coverage levels +st = ckb.new(PT.ST) +sf = ckb.new(PT.SF) +dt = ckb.new(PT.DT) + +################# +# TEST CASE 1.1 # +################# +# Ensure that making a report from a static checkpoint only does not +# report any violation. +tc_runner.run_test_case("Test Case 1.1", [sf], ckb.EXPECT_EMPTY) + +################# +# TEST CASE 1.2 # +################# +# Ensure that consolidating twice the same static decision does not +# report any violation. +tc_runner.run_test_case("Test Case 1.2", [sf, sf], ckb.EXPECT_EMPTY) + +############### +# TEST CASE 2 # +############### +# Ensure that making a report from a dynamic checkpoint reports a +# decision violation. +tc_runner.run_test_case("Test Case 2", [dt], ckb.EXPECT_VIOLATION) + +############### +# TEST CASE 3 # +############### +# Ensure that making a consolidated report from both static checkpoints +# does not raise any violation +tc_runner.run_test_case("Test Case 3", [sf, st], ckb.EXPECT_EMPTY) + +################# +# TEST CASE 4.1 # +################# +# Ensure that making a consolidated report from the true static checkpoint +# and the dynamic one (which evaluates to True) raises a decision violation +tc_runner.run_test_case("Test Case 4.1", [st, dt], ckb.EXPECT_VIOLATION) + +################# +# TEST CASE 4.2 # +################# +# Ensure the commutativity of checkpoint-loading order +tc_runner.run_test_case("Test Case 4.2", [dt, st], ckb.EXPECT_VIOLATION) + +################# +# TEST CASE 5.1 # +################# +# Ensure that making a consolidated report from the false static checkpoint +# and the dynamic one (which evaluates to True) covers the decision +tc_runner.run_test_case("Test Case 5.1", [sf, dt], ckb.EXPECT_EMPTY) + +################# +# TEST CASE 5.2 # +################# +# Ensure the commutativity of checkpoint-loading order +tc_runner.run_test_case("Test Case 5.2", [dt, sf], ckb.EXPECT_EMPTY) + +thistest.result() From cb1995b18d6446c0a61244d7659ef6827ee3a78b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 18 Dec 2024 17:06:36 +0100 Subject: [PATCH 1068/1483] Add test for 5.04 --- .../5.04a1-if-stmt/test.py | 99 +++++++++++++++++++ .../common/src-if-stmt/greet.gpr | 22 +++++ .../common/src-if-stmt/main.adb | 6 ++ .../common/src-if-stmt/src-greet/df_pkg.adb | 12 +++ .../common/src-if-stmt/src-greet/df_pkg.ads | 7 ++ .../common/src-if-stmt/src-greet/dt_pkg.ads | 6 ++ .../common/src-if-stmt/src-greet/dynamic.adb | 6 ++ .../common/src-if-stmt/src-greet/dynamic.ads | 3 + .../common/src-if-stmt/src-greet/greet.adb | 12 +++ .../common/src-if-stmt/src-greet/greet.ads | 3 + .../common/src-if-stmt/src-greet/sf_pkg.ads | 5 + .../common/src-if-stmt/src-greet/st_pkg.ads | 5 + 12 files changed, 186 insertions(+) create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/5.04a1-if-stmt/test.py create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/main.adb create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/df_pkg.adb create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/df_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dt_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.adb create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.adb create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/sf_pkg.ads create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/st_pkg.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/5.04a1-if-stmt/test.py b/testsuite/tests/716-static-decision-merging-in-ckpt/5.04a1-if-stmt/test.py new file mode 100644 index 000000000..cbabc7195 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/5.04a1-if-stmt/test.py @@ -0,0 +1,99 @@ +from pathlib import Path +import sys + +from SUITE.context import thistest +from SUITE.cutils import Wdir + +# Add the path of test utils to import it +sys.path.append( + str(Path(__file__).absolute().parent.parent.joinpath("common").resolve()) +) + +from test_utils import ( + IfStmtCheckpointBuilder, + TestCaseRunner, +) +from test_utils import PkgType as PT + +wd = Wdir("tmp_") + +# This test replicates the "simple-decision" test but uses an if statement +# instead of an if expression, in order to be runnable with 5.04a1 + +COV_LEVEL = "stmt+decision" + +ckb = IfStmtCheckpointBuilder(COV_LEVEL) +tc_runner = TestCaseRunner(COV_LEVEL) + +# Create two checkpoints with different coverage levels +st = ckb.new(PT.ST) +sf = ckb.new(PT.SF) +dt = ckb.new(PT.DT) + +################# +# TEST CASE 1.1 # +################# +# Ensure that making a report from a static checkpoint only does not +# report any violation. +tc_runner.run_test_case( + "Test Case 1.1", [sf], ckb.EXPECT_EMPTY_STMT_NOT_COVERED +) + +################# +# TEST CASE 1.2 # +################# +# Ensure that consolidating twice the same static decision does not +# report any violation. +tc_runner.run_test_case( + "Test Case 1.2", [sf, sf], ckb.EXPECT_EMPTY_STMT_NOT_COVERED +) + +############### +# TEST CASE 2 # +############### +# Ensure that making a report from a dynamic checkpoint reports a +# decision violation. +tc_runner.run_test_case("Test Case 2", [dt], ckb.EXPECT_VIOLATION_STMT_COVERED) + +############### +# TEST CASE 3 # +############### +# Ensure that making a consolidated report from both static checkpoints +# does not raise any violation +tc_runner.run_test_case("Test Case 3", [sf, st], ckb.EXPECT_EMPTY_STMT_COVERED) + +################# +# TEST CASE 4.1 # +################# +# Ensure that making a consolidated report from the true static checkpoint +# and the dynamic one (which evaluates to True) raises a decision violation +tc_runner.run_test_case( + "Test Case 4.1", [st, dt], ckb.EXPECT_VIOLATION_STMT_COVERED +) + +################# +# TEST CASE 4.2 # +################# +# Ensure the commutativity of checkpoint-loading order +tc_runner.run_test_case( + "Test Case 4.2", [dt, st], ckb.EXPECT_VIOLATION_STMT_COVERED +) + +################# +# TEST CASE 5.1 # +################# +# Ensure that making a consolidated report from the false static checkpoint +# and the dynamic one (which evaluates to True) covers the decision +tc_runner.run_test_case( + "Test Case 5.1", [sf, dt], ckb.EXPECT_EMPTY_STMT_COVERED +) + +################# +# TEST CASE 5.2 # +################# +# Ensure the commutativity of checkpoint-loading order +tc_runner.run_test_case( + "Test Case 5.2", [dt, sf], ckb.EXPECT_EMPTY_STMT_COVERED +) + +thistest.result() diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr new file mode 100644 index 000000000..6d2137c95 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr @@ -0,0 +1,22 @@ +project Greet is + for Source_Dirs use ("src-greet"); + + type Decision_Type is + ("static_true", "static_false", "dynamic_true", "dynamic_false"); + + Val_Impl : Decision_Type := + external ("DECISION_TYPE", "static_true"); + + package Naming is + case Val_Impl is + when "static_true" => + for Spec ("Pkg") use "st_pkg.ads"; + when "static_false" => + for Spec ("Pkg") use "sf_pkg.ads"; + when "dynamic_true" => + for Spec ("Pkg") use "dt_pkg.ads"; + when "dynamic_false" => + for Spec ("Pkg") use "df_pkg.ads"; + end case; + end Naming; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/main.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/main.adb new file mode 100644 index 000000000..31993887f --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/main.adb @@ -0,0 +1,6 @@ +with Greet; + +procedure Main is +begin + Greet.Say_Hi; +end Main; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/df_pkg.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/df_pkg.adb new file mode 100644 index 000000000..f87b2c204 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/df_pkg.adb @@ -0,0 +1,12 @@ +package body Pkg is + + function Difficult_True (X : Integer) return Boolean is + begin + if X mod 10 = 0 then + return (3 * X - 10) mod 10 = 0; + else + return False; + end if; + end Difficult_True; + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/df_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/df_pkg.ads new file mode 100644 index 000000000..6afbf605a --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/df_pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + function Difficult_True (X : Integer) return Boolean; + + Val : Boolean := not Difficult_True (30); + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dt_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dt_pkg.ads new file mode 100644 index 000000000..6b79aebc8 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dt_pkg.ads @@ -0,0 +1,6 @@ +with Dynamic; +package Pkg is + + Val : Boolean := Dynamic.Difficult_True (30); + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.adb new file mode 100644 index 000000000..2bebe1cb4 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.adb @@ -0,0 +1,6 @@ +package body Dynamic is + function Difficult_True (X : Integer) return Boolean is + begin + return True; + end Difficult_True; +end Dynamic; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.ads new file mode 100644 index 000000000..b4fa4889d --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dynamic.ads @@ -0,0 +1,3 @@ +package Dynamic is + function Difficult_True (X : Integer) return Boolean; +end Dynamic; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.adb new file mode 100644 index 000000000..b865f1244 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.adb @@ -0,0 +1,12 @@ +pragma Ada_2012; +with Ada.Text_IO; +with Pkg; + +package body Greet is + procedure Say_Hi is + begin + if Pkg.Val then + Ada.Text_IO.Put_Line ("Pkg.Val: True"); + end if; + end Say_Hi; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.ads new file mode 100644 index 000000000..5a336e804 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/greet.ads @@ -0,0 +1,3 @@ +package Greet is + procedure Say_Hi; +end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/sf_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/sf_pkg.ads new file mode 100644 index 000000000..4fa6bc049 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/sf_pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + Val : constant Boolean := False; + +end Pkg; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/st_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/st_pkg.ads new file mode 100644 index 000000000..600efd95c --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/st_pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + Val : constant Boolean := True; + +end Pkg; From 8bcc23892ebe3ecc0e5208758fbc6bdd5d729b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 13 Dec 2024 17:22:34 +0100 Subject: [PATCH 1069/1483] Do not run tests with bin-traces --- testsuite/tests/716-static-decision-merging-in-ckpt/extra.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/extra.opt diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/extra.opt b/testsuite/tests/716-static-decision-merging-in-ckpt/extra.opt new file mode 100644 index 000000000..b2af095c2 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD feature is not supported in binary traces From 61dd8ec187f5b52b1244aa0fffff064b1d7f0ac4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Tue, 17 Dec 2024 18:03:03 +0100 Subject: [PATCH 1070/1483] Add test to check for short circuit handling on MCDC static decisions --- .../short-circuit-mcdc/extra.opt | 1 + .../short-circuit-mcdc/test.py | 57 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/extra.opt create mode 100644 testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/test.py diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/extra.opt b/testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/extra.opt new file mode 100644 index 000000000..0af3fdd02 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/extra.opt @@ -0,0 +1 @@ +5.04a1 DEAD test uses Ada2012 if-exprs, which are not supported by 5.04a1 diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/test.py b/testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/test.py new file mode 100644 index 000000000..742a1df83 --- /dev/null +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/short-circuit-mcdc/test.py @@ -0,0 +1,57 @@ +from pathlib import Path +import sys + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import xcov + +# Add the path of test utils to import it +sys.path.append( + str(Path(__file__).absolute().parent.parent.joinpath("common").resolve()) +) + +from test_utils import ( + DoubleConditionCheckpointBuilder, + TestCaseRunner, +) +from test_utils import PkgType as PT + +wd = Wdir("tmp_") + +COV_LEVEL = "stmt+mcdc" + +ckb = DoubleConditionCheckpointBuilder(COV_LEVEL) +tc_runner = TestCaseRunner(COV_LEVEL) + +# Fully static +st_st = ckb.new(PT.ST, PT.ST) # decision is true +sf_sf = ckb.new(PT.SF, PT.SF) # decision is false + +############# +# Test case # +############# +# Ensure that when consolidating static `true || true` and `false || false` +# will raise a violation on the second condition but not on the first one +report_file = "report.txt" +args = [ + "coverage", + "--annotate=report", + "-o", + f"{report_file}", + f"--level={COV_LEVEL}", + "-C", + f"{st_st}", + "-C", + f"{sf_sf}", +] +xcov(args, "output.log") + +with open(report_file, "r") as file: + content = file.read() + +# Fail if the first condition is not covered +thistest.fail_if(content.find("greet.adb:11:16: condition") != -1) +# Fail if the second condition is covered +thistest.fail_if(content.find("greet.adb:11:33: condition") == -1) + +thistest.result() From 78b5ced87fb1365fd0077d2288c8672fe30511dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Mon, 23 Dec 2024 11:10:28 +0100 Subject: [PATCH 1071/1483] Search for overriden runtime file in Get_Unit_Filename --- .../gnatcov/instrument-ada_unit_provider.adb | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit_provider.adb b/tools/gnatcov/instrument-ada_unit_provider.adb index 237a66bfe..3ca2b8a9e 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.adb +++ b/tools/gnatcov/instrument-ada_unit_provider.adb @@ -127,14 +127,40 @@ package body Instrument.Ada_Unit_Provider is return Element (Unit_Name_Cur); end if; - -- The requested unit does not belong to the project tree: look for a - -- source file in the runtime. + -- The requested unit is not registered in the project tree under its + -- unit name. Assume it may be an overridden runtime file present + -- in the project tree with a krunched name. declare - Basename : constant String := + Runtime_Basename : constant String := Libadalang.Unit_Files.File_From_Unit (Name, Kind); + -- Finds the krunched name of the corresponding runtime file based + -- on the unit name. + + Unit_Basename : String := + Runtime_Basename (1 .. Runtime_Basename'Length - 4) & Part; + -- Re-use the krunched runtime filename to find the entry under + -- which the overridden runtime file may have been stored. + -- It's basically the runtime filename, but with '%b|%s' instead of + -- the file extension and with dots '.' instead of dashes '-'. + begin - Unit_Name_Cur := Provider.Runtime_Files.Find (Basename); + + for I in 1 .. Unit_Basename'Length loop + if Unit_Basename (I) = '-' then + Unit_Basename (I) := '.'; + end if; + end loop; + + Unit_Name_Cur := Provider.Unit_Map.Find (Unit_Basename); + if Has_Element (Unit_Name_Cur) then + return Element (Unit_Name_Cur); + end if; + + -- The requested unit does not belong to the project tree: look for a + -- source file in the runtime. + + Unit_Name_Cur := Provider.Runtime_Files.Find (Runtime_Basename); if Has_Element (Unit_Name_Cur) then return Element (Unit_Name_Cur); end if; From 551c777cbfe55981ebf7d4f8a232061f25d71bfe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Mon, 23 Dec 2024 14:14:52 +0100 Subject: [PATCH 1072/1483] Add test for checking runtime files override instrumentation --- testsuite/SUITE/context.py | 34 +- .../361-overriden-runtime-specs/extra.opt | 2 + .../src/a-convec.adb | 3366 +++++++++++++++++ .../src/a-convec.ads | 878 +++++ .../361-overriden-runtime-specs/src/main.adb | 11 + .../tests/361-overriden-runtime-specs/test.py | 48 + 6 files changed, 4334 insertions(+), 5 deletions(-) create mode 100644 testsuite/tests/361-overriden-runtime-specs/extra.opt create mode 100644 testsuite/tests/361-overriden-runtime-specs/src/a-convec.adb create mode 100644 testsuite/tests/361-overriden-runtime-specs/src/a-convec.ads create mode 100644 testsuite/tests/361-overriden-runtime-specs/src/main.adb create mode 100644 testsuite/tests/361-overriden-runtime-specs/test.py diff --git a/testsuite/SUITE/context.py b/testsuite/SUITE/context.py index afc80c85f..279b7e60a 100644 --- a/testsuite/SUITE/context.py +++ b/testsuite/SUITE/context.py @@ -235,18 +235,42 @@ def fail_if_not_equal(self, what, expected, actual): "\n{}".format(what, indent(str(expected)), indent(str(actual))), ) - def fail_if_no_match(self, what, regexp, actual): - """Register a check failure when ACTUAL does not match regexp.""" + def _fail_if_regex(self, what, regexp, actual, match_is_fail=False): if isinstance(regexp, str): regexp = re.compile(regexp) # Canonicalize to Unix-style line endings to have cross-platform checks actual = actual.replace("\r\n", "\n") + matching = bool(regexp.match(actual)) self.fail_if( - not regexp.match(actual), - "Unexpected {}. Expected:" + matching == match_is_fail, + "Error {}." + "\n{}:" "\n{}" "\nBut got:" - "\n{}".format(what, indent(regexp.pattern), indent(str(actual))), + "\n{}".format( + what, + "Unexpected" if match_is_fail else "Expected", + indent(regexp.pattern), + indent(str(actual)), + ), + ) + + def fail_if_no_match(self, what, regexp, actual): + """Register a check failure when ACTUAL does not match regexp.""" + self._fail_if_regex( + what, + regexp, + actual, + match_is_fail=False, + ) + + def fail_if_match(self, what, regexp, actual): + """Register a check failure when ACTUAL does match regexp.""" + self._fail_if_regex( + what, + regexp, + actual, + match_is_fail=True, ) def stop(self, exc): diff --git a/testsuite/tests/361-overriden-runtime-specs/extra.opt b/testsuite/tests/361-overriden-runtime-specs/extra.opt new file mode 100644 index 000000000..ac2346ab7 --- /dev/null +++ b/testsuite/tests/361-overriden-runtime-specs/extra.opt @@ -0,0 +1,2 @@ +5.04a1 DEAD 5.04a1 can't compile our custom runtime file, as it is too recent +bin-traces DEAD GPRbuild will fail to compile this project on a leon3 target diff --git a/testsuite/tests/361-overriden-runtime-specs/src/a-convec.adb b/testsuite/tests/361-overriden-runtime-specs/src/a-convec.adb new file mode 100644 index 000000000..429a1b6f7 --- /dev/null +++ b/testsuite/tests/361-overriden-runtime-specs/src/a-convec.adb @@ -0,0 +1,3366 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT LIBRARY COMPONENTS -- +-- -- +-- A D A . C O N T A I N E R S . V E C T O R S -- +-- -- +-- B o d y -- +-- -- +-- Copyright (C) 2004-2024, 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- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-- This unit was originally developed by Matthew J Heaney. -- +------------------------------------------------------------------------------ + +with Ada.Containers.Generic_Array_Sort; +with Ada.Unchecked_Deallocation; + +with Ada.Text_IO; + +with System; use type System.Address; +with System.Put_Images; + +package body Ada.Containers.Vectors with + SPARK_Mode => Off +is + + pragma Warnings (Off, "variable ""Busy*"" is not referenced"); + pragma Warnings (Off, "variable ""Lock*"" is not referenced"); + -- See comment in Ada.Containers.Helpers + + procedure Free is + new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access); + + procedure Append_Slow_Path + (Container : in out Vector; + New_Item : Element_Type; + Count : Count_Type); + -- This is the slow path for Append. This is split out to minimize the size + -- of Append, because we have Inline (Append). + + --------- + -- "&" -- + --------- + + -- We decide that the capacity of the result of "&" is the minimum needed + -- -- the sum of the lengths of the vector parameters. We could decide to + -- make it larger, but we have no basis for knowing how much larger, so we + -- just allocate the minimum amount of storage. + + function "&" (Left, Right : Vector) return Vector is + begin + return Result : Vector do + Reserve_Capacity (Result, Length (Left) + Length (Right)); + Append_Vector (Result, Left); + Append_Vector (Result, Right); + end return; + end "&"; + + function "&" (Left : Vector; Right : Element_Type) return Vector is + begin + return Result : Vector do + Reserve_Capacity (Result, Length (Left) + 1); + Append_Vector (Result, Left); + Append (Result, Right); + end return; + end "&"; + + function "&" (Left : Element_Type; Right : Vector) return Vector is + begin + return Result : Vector do + Reserve_Capacity (Result, 1 + Length (Right)); + Append (Result, Left); + Append_Vector (Result, Right); + end return; + end "&"; + + function "&" (Left, Right : Element_Type) return Vector is + begin + return Result : Vector do + Reserve_Capacity (Result, 1 + 1); + Append (Result, Left); + Append (Result, Right); + end return; + end "&"; + + --------- + -- "=" -- + --------- + + overriding function "=" (Left, Right : Vector) return Boolean is + begin + if Left.Last /= Right.Last then + return False; + end if; + + if Left.Length = 0 then + return True; + end if; + + declare + -- Per AI05-0022, the container implementation is required to detect + -- element tampering by a generic actual subprogram. + + Lock_Left : With_Lock (Left.TC'Unrestricted_Access); + Lock_Right : With_Lock (Right.TC'Unrestricted_Access); + begin + for J in Index_Type range Index_Type'First .. Left.Last loop + if Left.Elements.EA (J) /= Right.Elements.EA (J) then + return False; + end if; + end loop; + end; + + return True; + end "="; + + ------------ + -- Adjust -- + ------------ + + procedure Adjust (Container : in out Vector) is + begin + -- If the counts are nonzero, execution is technically erroneous, but + -- it seems friendly to allow things like concurrent "=" on shared + -- constants. + + Zero_Counts (Container.TC); + + if Container.Last = No_Index then + Container.Elements := null; + return; + end if; + + declare + L : constant Index_Type := Container.Last; + EA : Elements_Array renames + Container.Elements.EA (Index_Type'First .. L); + + begin + Container.Elements := null; + + -- Note: it may seem that the following assignment to Container.Last + -- is useless, since we assign it to L below. However this code is + -- used in case 'new Elements_Type' below raises an exception, to + -- keep Container in a consistent state. + + Container.Last := No_Index; + Container.Elements := new Elements_Type'(L, EA); + Container.Last := L; + end; + end Adjust; + + ------------ + -- Append -- + ------------ + + procedure Append + (Container : in out Vector; + New_Item : Element_Type; + Count : Count_Type) + is + begin + -- In the general case, we take the slow path; for efficiency, + -- we check for the common case where Count = 1 . + + if Count = 1 then + Append (Container, New_Item); + else + Append_Slow_Path (Container, New_Item, Count); + end if; + end Append; + + ------------------- + -- Append_Vector -- + ------------------- + + procedure Append_Vector (Container : in out Vector; New_Item : Vector) is + begin + if Is_Empty (New_Item) then + return; + elsif Checks and then Container.Last = Index_Type'Last then + raise Constraint_Error with "vector is already at its maximum length"; + else + Insert_Vector (Container, Container.Last + 1, New_Item); + end if; + end Append_Vector; + + ------------ + -- Append -- + ------------ + + function Toto (V : Vector) return Vector; + function Toto (V : Vector) return Vector is + begin + Ada.Text_IO.Put_Line ("Toto"); + return V; + end Toto; + + procedure Append (Container : in out Vector; + New_Item : Element_Type) + is + begin + -- For performance, check for the common special case where the + -- container already has room for at least one more element. + -- In the general case, pass the buck to Insert. + + Container := Toto (Container); + + if Container.Elements /= null + and then Container.Last /= Container.Elements.Last + then + TC_Check (Container.TC); + + -- Increment Container.Last after assigning the New_Item, so we + -- leave the Container unmodified in case Finalize/Adjust raises + -- an exception. + + declare + New_Last : constant Index_Type := Container.Last + 1; + begin + Container.Elements.EA (New_Last) := New_Item; + Container.Last := New_Last; + end; + else + Insert (Container, Last_Index (Container) + 1, New_Item, 1); + end if; + end Append; + + ---------------------- + -- Append_Slow_Path -- + ---------------------- + + procedure Append_Slow_Path + (Container : in out Vector; + New_Item : Element_Type; + Count : Count_Type) + is + begin + if Count = 0 then + return; + elsif Checks and then Container.Last = Index_Type'Last then + raise Constraint_Error with "vector is already at its maximum length"; + else + Insert (Container, Container.Last + 1, New_Item, Count); + end if; + end Append_Slow_Path; + + ------------ + -- Assign -- + ------------ + + procedure Assign (Target : in out Vector; Source : Vector) is + begin + if Target'Address = Source'Address then + return; + else + Target.Clear; + Target.Append_Vector (Source); + end if; + end Assign; + + -------------- + -- Capacity -- + -------------- + + function Capacity (Container : Vector) return Count_Type is + begin + if Container.Elements = null then + return 0; + else + return Container.Elements.EA'Length; + end if; + end Capacity; + + ----------- + -- Clear -- + ----------- + + procedure Clear (Container : in out Vector) is + begin + TC_Check (Container.TC); + Container.Last := No_Index; + end Clear; + + ------------------------ + -- Constant_Reference -- + ------------------------ + + function Constant_Reference + (Container : aliased Vector; + Position : Cursor) return Constant_Reference_Type + is + begin + if Checks then + if Position.Container = null then + raise Constraint_Error with "Position cursor has no element"; + end if; + + if Position.Container /= Container'Unrestricted_Access then + raise Program_Error with "Position cursor denotes wrong container"; + end if; + + if Position.Index > Position.Container.Last then + raise Constraint_Error with "Position cursor is out of range"; + end if; + end if; + + declare + TC : constant Tamper_Counts_Access := + Container.TC'Unrestricted_Access; + begin + return R : constant Constant_Reference_Type := + (Element => Container.Elements.EA (Position.Index)'Access, + Control => (Controlled with TC)) + do + Busy (TC.all); + end return; + end; + end Constant_Reference; + + function Constant_Reference + (Container : aliased Vector; + Index : Index_Type) return Constant_Reference_Type + is + begin + if Checks and then Index > Container.Last then + raise Constraint_Error with "Index is out of range"; + end if; + + declare + TC : constant Tamper_Counts_Access := + Container.TC'Unrestricted_Access; + begin + return R : constant Constant_Reference_Type := + (Element => Container.Elements.EA (Index)'Access, + Control => (Controlled with TC)) + do + Busy (TC.all); + end return; + end; + end Constant_Reference; + + -------------- + -- Contains -- + -------------- + + function Contains + (Container : Vector; + Item : Element_Type) return Boolean + is + begin + return Find_Index (Container, Item) /= No_Index; + end Contains; + + ---------- + -- Copy -- + ---------- + + function Copy + (Source : Vector; + Capacity : Count_Type := 0) return Vector + is + C : Count_Type; + + begin + if Capacity >= Source.Length then + C := Capacity; + + else + C := Source.Length; + + if Checks and then Capacity /= 0 then + raise Capacity_Error with + "Requested capacity is less than Source length"; + end if; + end if; + + return Target : Vector do + Target.Reserve_Capacity (C); + Target.Assign (Source); + end return; + end Copy; + + ------------ + -- Delete -- + ------------ + + procedure Delete + (Container : in out Vector; + Index : Extended_Index; + Count : Count_Type := 1) + is + Old_Last : constant Index_Type'Base := Container.Last; + New_Last : Index_Type'Base; + Count2 : Count_Type'Base; -- count of items from Index to Old_Last + J : Index_Type'Base; -- first index of items that slide down + + begin + -- The tampering bits exist to prevent an item from being deleted (or + -- otherwise harmfully manipulated) while it is being visited. Query, + -- Update, and Iterate increment the busy count on entry, and decrement + -- the count on exit. Delete checks the count to determine whether it is + -- being called while the associated callback procedure is executing. + + TC_Check (Container.TC); + + -- Delete removes items from the vector, the number of which is the + -- minimum of the specified Count and the items (if any) that exist from + -- Index to Container.Last. There are no constraints on the specified + -- value of Count (it can be larger than what's available at this + -- position in the vector, for example), but there are constraints on + -- the allowed values of the Index. + + -- As a precondition on the generic actual Index_Type, the base type + -- must include Index_Type'Pred (Index_Type'First); this is the value + -- that Container.Last assumes when the vector is empty. However, we do + -- not allow that as the value for Index when specifying which items + -- should be deleted, so we must manually check. (That the user is + -- allowed to specify the value at all here is a consequence of the + -- declaration of the Extended_Index subtype, which includes the values + -- in the base range that immediately precede and immediately follow the + -- values in the Index_Type.) + + if Checks and then Index < Index_Type'First then + raise Constraint_Error with "Index is out of range (too small)"; + end if; + + -- We do allow a value greater than Container.Last to be specified as + -- the Index, but only if it's immediately greater. This allows the + -- corner case of deleting no items from the back end of the vector to + -- be treated as a no-op. (It is assumed that specifying an index value + -- greater than Last + 1 indicates some deeper flaw in the caller's + -- algorithm, so that case is treated as a proper error.) + + if Index > Old_Last then + if Checks and then Index > Old_Last + 1 then + raise Constraint_Error with "Index is out of range (too large)"; + else + return; + end if; + end if; + + -- Here and elsewhere we treat deleting 0 items from the container as a + -- no-op, even when the container is busy, so we simply return. + + if Count = 0 then + return; + end if; + + -- We first calculate what's available for deletion starting at + -- Index. Here and elsewhere we use the wider of Index_Type'Base and + -- Count_Type'Base as the type for intermediate values. (See function + -- Length for more information.) + + if Count_Type'Base'Last >= Index_Type'Pos (Index_Type'Base'Last) then + Count2 := Count_Type'Base (Old_Last) - Count_Type'Base (Index) + 1; + else + Count2 := Count_Type'Base (Old_Last - Index + 1); + end if; + + -- If more elements are requested (Count) for deletion than are + -- available (Count2) for deletion beginning at Index, then everything + -- from Index is deleted. There are no elements to slide down, and so + -- all we need to do is set the value of Container.Last. + + if Count >= Count2 then + Container.Last := Index - 1; + return; + end if; + + -- There are some elements that aren't being deleted (the requested + -- count was less than the available count), so we must slide them down + -- to Index. We first calculate the index values of the respective array + -- slices, using the wider of Index_Type'Base and Count_Type'Base as the + -- type for intermediate calculations. For the elements that slide down, + -- index value New_Last is the last index value of their new home, and + -- index value J is the first index of their old home. + + if Index_Type'Base'Last >= Count_Type_Last then + New_Last := Old_Last - Index_Type'Base (Count); + J := Index + Index_Type'Base (Count); + else + New_Last := Index_Type'Base (Count_Type'Base (Old_Last) - Count); + J := Index_Type'Base (Count_Type'Base (Index) + Count); + end if; + + -- The internal elements array isn't guaranteed to exist unless we have + -- elements, but we have that guarantee here because we know we have + -- elements to slide. The array index values for each slice have + -- already been determined, so we just slide down to Index the elements + -- that weren't deleted. + + declare + EA : Elements_Array renames Container.Elements.EA; + begin + EA (Index .. New_Last) := EA (J .. Old_Last); + Container.Last := New_Last; + end; + end Delete; + + procedure Delete + (Container : in out Vector; + Position : in out Cursor; + Count : Count_Type := 1) + is + begin + if Checks then + if Position.Container = null then + raise Constraint_Error with "Position cursor has no element"; + + elsif Position.Container /= Container'Unrestricted_Access then + raise Program_Error with "Position cursor denotes wrong container"; + + elsif Position.Index > Container.Last then + raise Program_Error with "Position index is out of range"; + end if; + end if; + + Delete (Container, Position.Index, Count); + Position := No_Element; + end Delete; + + ------------------ + -- Delete_First -- + ------------------ + + procedure Delete_First + (Container : in out Vector; + Count : Count_Type := 1) + is + begin + if Count = 0 then + return; + + elsif Count >= Length (Container) then + Clear (Container); + return; + + else + Delete (Container, Index_Type'First, Count); + end if; + end Delete_First; + + ----------------- + -- Delete_Last -- + ----------------- + + procedure Delete_Last + (Container : in out Vector; + Count : Count_Type := 1) + is + begin + -- It is not permitted to delete items while the container is busy (for + -- example, we're in the middle of a passive iteration). However, we + -- always treat deleting 0 items as a no-op, even when we're busy, so we + -- simply return without checking. + + if Count = 0 then + return; + end if; + + -- The tampering bits exist to prevent an item from being deleted (or + -- otherwise harmfully manipulated) while it is being visited. Query, + -- Update, and Iterate increment the busy count on entry, and decrement + -- the count on exit. Delete_Last checks the count to determine whether + -- it is being called while the associated callback procedure is + -- executing. + + TC_Check (Container.TC); + + -- There is no restriction on how large Count can be when deleting + -- items. If it is equal or greater than the current length, then this + -- is equivalent to clearing the vector. (In particular, there's no need + -- for us to actually calculate the new value for Last.) + + -- If the requested count is less than the current length, then we must + -- calculate the new value for Last. For the type we use the widest of + -- Index_Type'Base and Count_Type'Base for the intermediate values of + -- our calculation. (See the comments in Length for more information.) + + if Count >= Container.Length then + Container.Last := No_Index; + + elsif Index_Type'Base'Last >= Count_Type_Last then + Container.Last := Container.Last - Index_Type'Base (Count); + + else + Container.Last := + Index_Type'Base (Count_Type'Base (Container.Last) - Count); + end if; + end Delete_Last; + + ------------- + -- Element -- + ------------- + + function Element + (Container : Vector; + Index : Index_Type) return Element_Type + is + begin + if Checks and then Index > Container.Last then + raise Constraint_Error with "Index is out of range"; + end if; + + return Container.Elements.EA (Index); + end Element; + + function Element (Position : Cursor) return Element_Type is + begin + if Checks then + if Position.Container = null then + raise Constraint_Error with "Position cursor has no element"; + elsif Position.Index > Position.Container.Last then + raise Constraint_Error with "Position cursor is out of range"; + end if; + end if; + + return Position.Container.Elements.EA (Position.Index); + end Element; + + ----------- + -- Empty -- + ----------- + + function Empty (Capacity : Count_Type := 10) return Vector is + begin + return Result : Vector do + Reserve_Capacity (Result, Capacity); + end return; + end Empty; + + -------------- + -- Finalize -- + -------------- + + procedure Finalize (Container : in out Vector) is + X : Elements_Access := Container.Elements; + + begin + Container.Elements := null; + Container.Last := No_Index; + + Free (X); + + TC_Check (Container.TC); + end Finalize; + + procedure Finalize (Object : in out Iterator) is + begin + Unbusy (Object.Container.TC); + end Finalize; + + ---------- + -- Find -- + ---------- + + function Find + (Container : Vector; + Item : Element_Type; + Position : Cursor := No_Element) return Cursor + is + begin + if Checks and then Position.Container /= null then + if Position.Container /= Container'Unrestricted_Access then + raise Program_Error with "Position cursor denotes wrong container"; + end if; + + if Position.Index > Container.Last then + raise Program_Error with "Position index is out of range"; + end if; + end if; + + -- Per AI05-0022, the container implementation is required to detect + -- element tampering by a generic actual subprogram. + + declare + Lock : With_Lock (Container.TC'Unrestricted_Access); + begin + for J in Position.Index .. Container.Last loop + if Container.Elements.EA (J) = Item then + return Cursor'(Container'Unrestricted_Access, J); + end if; + end loop; + + return No_Element; + end; + end Find; + + ---------------- + -- Find_Index -- + ---------------- + + function Find_Index + (Container : Vector; + Item : Element_Type; + Index : Index_Type := Index_Type'First) return Extended_Index + is + -- Per AI05-0022, the container implementation is required to detect + -- element tampering by a generic actual subprogram. + + Lock : With_Lock (Container.TC'Unrestricted_Access); + begin + for Indx in Index .. Container.Last loop + if Container.Elements.EA (Indx) = Item then + return Indx; + end if; + end loop; + + return No_Index; + end Find_Index; + + ----------- + -- First -- + ----------- + + function First (Container : Vector) return Cursor is + begin + if Is_Empty (Container) then + return No_Element; + end if; + + return (Container'Unrestricted_Access, Index_Type'First); + end First; + + function First (Object : Iterator) return Cursor is + begin + -- The value of the iterator object's Index component influences the + -- behavior of the First (and Last) selector function. + + -- When the Index component is No_Index, this means the iterator + -- object was constructed without a start expression, in which case the + -- (forward) iteration starts from the (logical) beginning of the entire + -- sequence of items (corresponding to Container.First, for a forward + -- iterator). + + -- Otherwise, this is iteration over a partial sequence of items. + -- When the Index component isn't No_Index, the iterator object was + -- constructed with a start expression, that specifies the position + -- from which the (forward) partial iteration begins. + + if Object.Index = No_Index then + return First (Object.Container.all); + else + return Cursor'(Object.Container, Object.Index); + end if; + end First; + + ------------------- + -- First_Element -- + ------------------- + + function First_Element (Container : Vector) return Element_Type is + begin + if Checks and then Container.Last = No_Index then + raise Constraint_Error with "Container is empty"; + else + return Container.Elements.EA (Index_Type'First); + end if; + end First_Element; + + ----------------- + -- First_Index -- + ----------------- + + function First_Index (Container : Vector) return Index_Type is + pragma Unreferenced (Container); + begin + return Index_Type'First; + end First_Index; + + ----------------- + -- New_Vector -- + ----------------- + + function New_Vector (First, Last : Index_Type) return Vector + is + begin + return (To_Vector (Count_Type (Last - First + 1))); + end New_Vector; + + --------------------- + -- Generic_Sorting -- + --------------------- + + package body Generic_Sorting is + + --------------- + -- Is_Sorted -- + --------------- + + function Is_Sorted (Container : Vector) return Boolean is + begin + if Container.Last <= Index_Type'First then + return True; + end if; + + -- Per AI05-0022, the container implementation is required to detect + -- element tampering by a generic actual subprogram. + + declare + Lock : With_Lock (Container.TC'Unrestricted_Access); + EA : Elements_Array renames Container.Elements.EA; + begin + for J in Index_Type'First .. Container.Last - 1 loop + if EA (J + 1) < EA (J) then + return False; + end if; + end loop; + + return True; + end; + end Is_Sorted; + + ----------- + -- Merge -- + ----------- + + procedure Merge (Target, Source : in out Vector) is + I : Index_Type'Base := Target.Last; + J : Index_Type'Base; + + begin + TC_Check (Source.TC); + + -- The semantics of Merge changed slightly per AI05-0021. It was + -- originally the case that if Target and Source denoted the same + -- container object, then the GNAT implementation of Merge did + -- nothing. However, it was argued that RM05 did not precisely + -- specify the semantics for this corner case. The decision of the + -- ARG was that if Target and Source denote the same non-empty + -- container object, then Program_Error is raised. + + if Source.Last < Index_Type'First then -- Source is empty + return; + end if; + + if Checks and then Target'Address = Source'Address then + raise Program_Error with + "Target and Source denote same non-empty container"; + end if; + + if Target.Last < Index_Type'First then -- Target is empty + Move (Target => Target, Source => Source); + return; + end if; + + Target.Set_Length (Length (Target) + Length (Source)); + + -- Per AI05-0022, the container implementation is required to detect + -- element tampering by a generic actual subprogram. + + declare + TA : Elements_Array renames Target.Elements.EA; + SA : Elements_Array renames Source.Elements.EA; + + Lock_Target : With_Lock (Target.TC'Unchecked_Access); + Lock_Source : With_Lock (Source.TC'Unchecked_Access); + begin + J := Target.Last; + while Source.Last >= Index_Type'First loop + pragma Assert (Source.Last <= Index_Type'First + or else not (SA (Source.Last) < + SA (Source.Last - 1))); + + if I < Index_Type'First then + TA (Index_Type'First .. J) := + SA (Index_Type'First .. Source.Last); + + Source.Last := No_Index; + exit; + end if; + + pragma Assert (I <= Index_Type'First + or else not (TA (I) < TA (I - 1))); + + if SA (Source.Last) < TA (I) then + TA (J) := TA (I); + I := I - 1; + + else + TA (J) := SA (Source.Last); + Source.Last := Source.Last - 1; + end if; + + J := J - 1; + end loop; + end; + end Merge; + + ---------- + -- Sort -- + ---------- + + procedure Sort (Container : in out Vector) is + procedure Sort is + new Generic_Array_Sort + (Index_Type => Index_Type, + Element_Type => Element_Type, + Array_Type => Elements_Array, + "<" => "<"); + + begin + -- The exception behavior for the vector container must match that + -- for the list container, so we check for cursor tampering here + -- (which will catch more things) instead of for element tampering + -- (which will catch fewer things). It's true that the elements of + -- this vector container could be safely moved around while (say) an + -- iteration is taking place (iteration only increments the busy + -- counter), and so technically all we would need here is a test for + -- element tampering (indicated by the lock counter), that's simply + -- an artifact of our array-based implementation. Logically Sort + -- requires a check for cursor tampering. + + TC_Check (Container.TC); + + if Container.Last <= Index_Type'First then + return; + end if; + + -- Per AI05-0022, the container implementation is required to detect + -- element tampering by a generic actual subprogram. + + declare + Lock : With_Lock (Container.TC'Unchecked_Access); + begin + Sort (Container.Elements.EA (Index_Type'First .. Container.Last)); + end; + end Sort; + + end Generic_Sorting; + + ------------------------ + -- Get_Element_Access -- + ------------------------ + + function Get_Element_Access + (Position : Cursor) return not null Element_Access is + begin + return Position.Container.Elements.EA (Position.Index)'Access; + end Get_Element_Access; + + ----------------- + -- Has_Element -- + ----------------- + + function Has_Element (Position : Cursor) return Boolean is + begin + return Position /= No_Element; + end Has_Element; + + ------------ + -- Insert -- + ------------ + + procedure Insert + (Container : in out Vector; + Before : Extended_Index; + New_Item : Element_Type; + Count : Count_Type := 1) + is + Old_Length : constant Count_Type := Container.Length; + + Max_Length : Count_Type'Base; -- determined from range of Index_Type + New_Length : Count_Type'Base; -- sum of current length and Count + New_Last : Index_Type'Base; -- last index of vector after insertion + + Index : Index_Type'Base; -- scratch for intermediate values + J : Count_Type'Base; -- scratch + + New_Capacity : Count_Type'Base; -- length of new, expanded array + Dst_Last : Index_Type'Base; -- last index of new, expanded array + Dst : Elements_Access; -- new, expanded internal array + + begin + -- The tampering bits exist to prevent an item from being harmfully + -- manipulated while it is being visited. Query, Update, and Iterate + -- increment the busy count on entry, and decrement the count on + -- exit. Insert checks the count to determine whether it is being called + -- while the associated callback procedure is executing. + + TC_Check (Container.TC); + + if Checks then + -- As a precondition on the generic actual Index_Type, the base type + -- must include Index_Type'Pred (Index_Type'First); this is the value + -- that Container.Last assumes when the vector is empty. However, we + -- do not allow that as the value for Index when specifying where the + -- new items should be inserted, so we must manually check. (That the + -- user is allowed to specify the value at all here is a consequence + -- of the declaration of the Extended_Index subtype, which includes + -- the values in the base range that immediately precede and + -- immediately follow the values in the Index_Type.) + + if Before < Index_Type'First then + raise Constraint_Error with + "Before index is out of range (too small)"; + end if; + + -- We do allow a value greater than Container.Last to be specified as + -- the Index, but only if it's immediately greater. This allows for + -- the case of appending items to the back end of the vector. (It is + -- assumed that specifying an index value greater than Last + 1 + -- indicates some deeper flaw in the caller's algorithm, so that case + -- is treated as a proper error.) + + if Before > Container.Last + 1 then + raise Constraint_Error with + "Before index is out of range (too large)"; + end if; + end if; + + -- We treat inserting 0 items into the container as a no-op, even when + -- the container is busy, so we simply return. + + if Count = 0 then + return; + end if; + + -- There are two constraints we need to satisfy. The first constraint is + -- that a container cannot have more than Count_Type'Last elements, so + -- we must check the sum of the current length and the insertion count. + -- Note: we cannot simply add these values, because of the possibility + -- of overflow. + + if Checks and then Old_Length > Count_Type'Last - Count then + raise Constraint_Error with "Count is out of range"; + end if; + + -- It is now safe compute the length of the new vector, without fear of + -- overflow. + + New_Length := Old_Length + Count; + + -- The second constraint is that the new Last index value cannot exceed + -- Index_Type'Last. In each branch below, we calculate the maximum + -- length (computed from the range of values in Index_Type), and then + -- compare the new length to the maximum length. If the new length is + -- acceptable, then we compute the new last index from that. + + if Index_Type'Base'Last >= Count_Type_Last then + + -- We have to handle the case when there might be more values in the + -- range of Index_Type than in the range of Count_Type. + + if Index_Type'First <= 0 then + + -- We know that No_Index (the same as Index_Type'First - 1) is + -- less than 0, so it is safe to compute the following sum without + -- fear of overflow. We need to suppress warnings, because + -- otherwise we get an error in -gnatwE mode. + + pragma Warnings (Off); + Index := No_Index + Index_Type'Base (Count_Type'Last); + pragma Warnings (On); + + if Index <= Index_Type'Last then + + -- We have determined that range of Index_Type has at least as + -- many values as in Count_Type, so Count_Type'Last is the + -- maximum number of items that are allowed. + + Max_Length := Count_Type'Last; + + else + -- The range of Index_Type has fewer values than in Count_Type, + -- so the maximum number of items is computed from the range of + -- the Index_Type. + + Max_Length := Count_Type'Base (Index_Type'Last - No_Index); + end if; + + else + -- No_Index is equal or greater than 0, so we can safely compute + -- the difference without fear of overflow (which we would have to + -- worry about if No_Index were less than 0, but that case is + -- handled above). + + if Index_Type'Last - No_Index >= Count_Type_Last then + -- We have determined that range of Index_Type has at least as + -- many values as in Count_Type, so Count_Type'Last is the + -- maximum number of items that are allowed. + + Max_Length := Count_Type'Last; + + else + -- The range of Index_Type has fewer values than in Count_Type, + -- so the maximum number of items is computed from the range of + -- the Index_Type. + + Max_Length := Count_Type'Base (Index_Type'Last - No_Index); + end if; + end if; + + elsif Index_Type'First <= 0 then + + -- We know that No_Index (the same as Index_Type'First - 1) is less + -- than 0, so it is safe to compute the following sum without fear of + -- overflow. + + J := Count_Type'Base (No_Index) + Count_Type'Last; + + if J <= Count_Type'Base (Index_Type'Last) then + + -- We have determined that range of Index_Type has at least as + -- many values as in Count_Type, so Count_Type'Last is the maximum + -- number of items that are allowed. + + Max_Length := Count_Type'Last; + + else + -- The range of Index_Type has fewer values than Count_Type does, + -- so the maximum number of items is computed from the range of + -- the Index_Type. + + Max_Length := + Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index); + end if; + + else + -- No_Index is equal or greater than 0, so we can safely compute the + -- difference without fear of overflow (which we would have to worry + -- about if No_Index were less than 0, but that case is handled + -- above). + + Max_Length := + Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index); + end if; + + -- We have just computed the maximum length (number of items). We must + -- now compare the requested length to the maximum length, as we do not + -- allow a vector expand beyond the maximum (because that would create + -- an internal array with a last index value greater than + -- Index_Type'Last, with no way to index those elements). + + if Checks and then New_Length > Max_Length then + raise Constraint_Error with "Count is out of range"; + end if; + + -- New_Last is the last index value of the items in the container after + -- insertion. Use the wider of Index_Type'Base and Count_Type'Base to + -- compute its value from the New_Length. + + if Index_Type'Base'Last >= Count_Type_Last then + New_Last := No_Index + Index_Type'Base (New_Length); + else + New_Last := Index_Type'Base (Count_Type'Base (No_Index) + New_Length); + end if; + + if Container.Elements = null then + pragma Assert (Container.Last = No_Index); + + -- This is the simplest case, with which we must always begin: we're + -- inserting items into an empty vector that hasn't allocated an + -- internal array yet. Note that we don't need to check the busy bit + -- here, because an empty container cannot be busy. + + -- In order to preserve container invariants, we allocate the new + -- internal array first, before setting the Last index value, in case + -- the allocation fails (which can happen either because there is no + -- storage available, or because element initialization fails). + + Container.Elements := new Elements_Type' + (Last => New_Last, + EA => [others => New_Item]); + + -- The allocation of the new, internal array succeeded, so it is now + -- safe to update the Last index, restoring container invariants. + + Container.Last := New_Last; + + return; + end if; + + -- An internal array has already been allocated, so we must determine + -- whether there is enough unused storage for the new items. + + if New_Length <= Container.Elements.EA'Length then + + -- In this case, we're inserting elements into a vector that has + -- already allocated an internal array, and the existing array has + -- enough unused storage for the new items. + + declare + EA : Elements_Array renames Container.Elements.EA; + + begin + if Before > Container.Last then + + -- The new items are being appended to the vector, so no + -- sliding of existing elements is required. + + EA (Before .. New_Last) := [others => New_Item]; + + else + -- The new items are being inserted before some existing + -- elements, so we must slide the existing elements up to their + -- new home. We use the wider of Index_Type'Base and + -- Count_Type'Base as the type for intermediate index values. + + if Index_Type'Base'Last >= Count_Type_Last then + Index := Before + Index_Type'Base (Count); + else + Index := Index_Type'Base (Count_Type'Base (Before) + Count); + end if; + + EA (Index .. New_Last) := EA (Before .. Container.Last); + EA (Before .. Index - 1) := [others => New_Item]; + end if; + end; + + Container.Last := New_Last; + return; + end if; + + -- In this case, we're inserting elements into a vector that has already + -- allocated an internal array, but the existing array does not have + -- enough storage, so we must allocate a new, longer array. In order to + -- guarantee that the amortized insertion cost is O(1), we always + -- allocate an array whose length is some power-of-two factor of the + -- current array length. (The new array cannot have a length less than + -- the New_Length of the container, but its last index value cannot be + -- greater than Index_Type'Last.) + + New_Capacity := Count_Type'Max (1, Container.Elements.EA'Length); + while New_Capacity < New_Length loop + if New_Capacity > Count_Type'Last / 2 then + New_Capacity := Count_Type'Last; + exit; + else + New_Capacity := 2 * New_Capacity; + end if; + end loop; + + if New_Capacity > Max_Length then + + -- We have reached the limit of capacity, so no further expansion + -- will occur. (This is not a problem, as there is never a need to + -- have more capacity than the maximum container length.) + + New_Capacity := Max_Length; + end if; + + -- We have computed the length of the new internal array (and this is + -- what "vector capacity" means), so use that to compute its last index. + + if Index_Type'Base'Last >= Count_Type_Last then + Dst_Last := No_Index + Index_Type'Base (New_Capacity); + else + Dst_Last := + Index_Type'Base (Count_Type'Base (No_Index) + New_Capacity); + end if; + + -- Now we allocate the new, longer internal array. If the allocation + -- fails, we have not changed any container state, so no side-effect + -- will occur as a result of propagating the exception. + + Dst := new Elements_Type (Dst_Last); + + -- We have our new internal array. All that needs to be done now is to + -- copy the existing items (if any) from the old array (the "source" + -- array, object SA below) to the new array (the "destination" array, + -- object DA below), and then deallocate the old array. + + declare + SA : Elements_Array renames Container.Elements.EA; -- source + DA : Elements_Array renames Dst.EA; -- destination + pragma Unreferenced (DA); + + begin + DA (Index_Type'First .. Before - 1) := + SA (Index_Type'First .. Before - 1); + + if Before > Container.Last then + DA (Before .. New_Last) := [others => New_Item]; + + else + -- The new items are being inserted before some existing elements, + -- so we must slide the existing elements up to their new home. + + if Index_Type'Base'Last >= Count_Type_Last then + Index := Before + Index_Type'Base (Count); + else + Index := Index_Type'Base (Count_Type'Base (Before) + Count); + end if; + + DA (Before .. Index - 1) := [others => New_Item]; + DA (Index .. New_Last) := SA (Before .. Container.Last); + end if; + + exception + when others => + Free (Dst); + raise; + end; + + -- We have successfully copied the items onto the new array, so the + -- final thing to do is deallocate the old array. + + declare + X : Elements_Access := Container.Elements; + + begin + -- We first isolate the old internal array, removing it from the + -- container and replacing it with the new internal array, before we + -- deallocate the old array (which can fail if finalization of + -- elements propagates an exception). + + Container.Elements := Dst; + Container.Last := New_Last; + + -- The container invariants have been restored, so it is now safe to + -- attempt to deallocate the old array. + + Free (X); + end; + end Insert; + + procedure Insert_Vector + (Container : in out Vector; + Before : Extended_Index; + New_Item : Vector) + is + N : constant Count_Type := Length (New_Item); + J : Index_Type'Base; + + begin + -- Use Insert_Space to create the "hole" (the destination slice) into + -- which we copy the source items. + + Insert_Space (Container, Before, Count => N); + + if N = 0 then + + -- There's nothing else to do here (vetting of parameters was + -- performed already in Insert_Space), so we simply return. + + return; + end if; + + -- We calculate the last index value of the destination slice using the + -- wider of Index_Type'Base and count_Type'Base. + + if Index_Type'Base'Last >= Count_Type_Last then + J := (Before - 1) + Index_Type'Base (N); + else + J := Index_Type'Base (Count_Type'Base (Before - 1) + N); + end if; + + if Container'Address /= New_Item'Address then + + -- This is the simple case. New_Item denotes an object different + -- from Container, so there's nothing special we need to do to copy + -- the source items to their destination, because all of the source + -- items are contiguous. + + Container.Elements.EA (Before .. J) := + New_Item.Elements.EA (Index_Type'First .. New_Item.Last); + + return; + end if; + + -- New_Item denotes the same object as Container, so an insertion has + -- potentially split the source items. The destination is always the + -- range [Before, J], but the source is [Index_Type'First, Before) and + -- (J, Container.Last]. We perform the copy in two steps, using each of + -- the two slices of the source items. + + declare + L : constant Index_Type'Base := Before - 1; + + subtype Src_Index_Subtype is Index_Type'Base range + Index_Type'First .. L; + + Src : Elements_Array renames + Container.Elements.EA (Src_Index_Subtype); + + K : Index_Type'Base; + + begin + -- We first copy the source items that precede the space we + -- inserted. Index value K is the last index of that portion + -- destination that receives this slice of the source. (If Before + -- equals Index_Type'First, then this first source slice will be + -- empty, which is harmless.) + + if Index_Type'Base'Last >= Count_Type_Last then + K := L + Index_Type'Base (Src'Length); + else + K := Index_Type'Base (Count_Type'Base (L) + Src'Length); + end if; + + Container.Elements.EA (Before .. K) := Src; + + if Src'Length = N then + + -- The new items were effectively appended to the container, so we + -- have already copied all of the items that need to be copied. + -- We return early here, even though the source slice below is + -- empty (so the assignment would be harmless), because we want to + -- avoid computing J + 1, which will overflow if J equals + -- Index_Type'Base'Last. + + return; + end if; + end; + + declare + -- Note that we want to avoid computing J + 1 here, in case J equals + -- Index_Type'Base'Last. We prevent that by returning early above, + -- immediately after copying the first slice of the source, and + -- determining that this second slice of the source is empty. + + F : constant Index_Type'Base := J + 1; + + subtype Src_Index_Subtype is Index_Type'Base range + F .. Container.Last; + + Src : Elements_Array renames + Container.Elements.EA (Src_Index_Subtype); + + K : Index_Type'Base; + + begin + -- We next copy the source items that follow the space we inserted. + -- Index value K is the first index of that portion of the + -- destination that receives this slice of the source. (For the + -- reasons given above, this slice is guaranteed to be non-empty.) + + if Index_Type'Base'Last >= Count_Type_Last then + K := F - Index_Type'Base (Src'Length); + else + K := Index_Type'Base (Count_Type'Base (F) - Src'Length); + end if; + + Container.Elements.EA (K .. J) := Src; + end; + end Insert_Vector; + + procedure Insert_Vector + (Container : in out Vector; + Before : Cursor; + New_Item : Vector) + is + Index : Index_Type'Base; + + begin + if Checks and then Before.Container /= null + and then Before.Container /= Container'Unrestricted_Access + then + raise Program_Error with "Before cursor denotes wrong container"; + end if; + + if Is_Empty (New_Item) then + return; + end if; + + if Before.Container = null or else Before.Index > Container.Last then + if Checks and then Container.Last = Index_Type'Last then + raise Constraint_Error with + "vector is already at its maximum length"; + end if; + + Index := Container.Last + 1; + + else + Index := Before.Index; + end if; + + Insert_Vector (Container, Index, New_Item); + end Insert_Vector; + + procedure Insert_Vector + (Container : in out Vector; + Before : Cursor; + New_Item : Vector; + Position : out Cursor) + is + Index : Index_Type'Base; + + begin + if Checks and then Before.Container /= null + and then Before.Container /= Container'Unrestricted_Access + then + raise Program_Error with "Before cursor denotes wrong container"; + end if; + + if Is_Empty (New_Item) then + if Before.Container = null or else Before.Index > Container.Last then + Position := No_Element; + else + Position := (Container'Unrestricted_Access, Before.Index); + end if; + + return; + end if; + + if Before.Container = null or else Before.Index > Container.Last then + if Checks and then Container.Last = Index_Type'Last then + raise Constraint_Error with + "vector is already at its maximum length"; + end if; + + Index := Container.Last + 1; + + else + Index := Before.Index; + end if; + + Insert_Vector (Container, Index, New_Item); + + Position := (Container'Unrestricted_Access, Index); + end Insert_Vector; + + procedure Insert + (Container : in out Vector; + Before : Cursor; + New_Item : Element_Type; + Count : Count_Type := 1) + is + Index : Index_Type'Base; + + begin + if Checks and then Before.Container /= null + and then Before.Container /= Container'Unrestricted_Access + then + raise Program_Error with "Before cursor denotes wrong container"; + end if; + + if Count = 0 then + return; + end if; + + if Before.Container = null or else Before.Index > Container.Last then + if Checks and then Container.Last = Index_Type'Last then + raise Constraint_Error with + "vector is already at its maximum length"; + else + Index := Container.Last + 1; + end if; + + else + Index := Before.Index; + end if; + + Insert (Container, Index, New_Item, Count); + end Insert; + + procedure Insert + (Container : in out Vector; + Before : Cursor; + New_Item : Element_Type; + Position : out Cursor; + Count : Count_Type := 1) + is + Index : Index_Type'Base; + + begin + if Checks and then Before.Container /= null + and then Before.Container /= Container'Unrestricted_Access + then + raise Program_Error with "Before cursor denotes wrong container"; + end if; + + if Count = 0 then + if Before.Container = null or else Before.Index > Container.Last then + Position := No_Element; + else + Position := (Container'Unrestricted_Access, Before.Index); + end if; + + return; + end if; + + if Before.Container = null or else Before.Index > Container.Last then + if Checks and then Container.Last = Index_Type'Last then + raise Constraint_Error with + "vector is already at its maximum length"; + end if; + + Index := Container.Last + 1; + + else + Index := Before.Index; + end if; + + Insert (Container, Index, New_Item, Count); + + Position := (Container'Unrestricted_Access, Index); + end Insert; + + procedure Insert + (Container : in out Vector; + Before : Extended_Index; + Count : Count_Type := 1) + is + New_Item : Element_Type; -- Default-initialized value + pragma Warnings (Off, New_Item); + + begin + Insert (Container, Before, New_Item, Count); + end Insert; + + procedure Insert + (Container : in out Vector; + Before : Cursor; + Position : out Cursor; + Count : Count_Type := 1) + is + New_Item : Element_Type; -- Default-initialized value + pragma Warnings (Off, New_Item); + begin + Insert (Container, Before, New_Item, Position, Count); + end Insert; + + ------------------ + -- Insert_Space -- + ------------------ + + procedure Insert_Space + (Container : in out Vector; + Before : Extended_Index; + Count : Count_Type := 1) + is + Old_Length : constant Count_Type := Container.Length; + + Max_Length : Count_Type'Base; -- determined from range of Index_Type + New_Length : Count_Type'Base; -- sum of current length and Count + New_Last : Index_Type'Base; -- last index of vector after insertion + + Index : Index_Type'Base; -- scratch for intermediate values + J : Count_Type'Base; -- scratch + + New_Capacity : Count_Type'Base; -- length of new, expanded array + Dst_Last : Index_Type'Base; -- last index of new, expanded array + Dst : Elements_Access; -- new, expanded internal array + + begin + -- The tampering bits exist to prevent an item from being harmfully + -- manipulated while it is being visited. Query, Update, and Iterate + -- increment the busy count on entry, and decrement the count on + -- exit. Insert checks the count to determine whether it is being called + -- while the associated callback procedure is executing. + + TC_Check (Container.TC); + + if Checks then + -- As a precondition on the generic actual Index_Type, the base type + -- must include Index_Type'Pred (Index_Type'First); this is the value + -- that Container.Last assumes when the vector is empty. However, we + -- do not allow that as the value for Index when specifying where the + -- new items should be inserted, so we must manually check. (That the + -- user is allowed to specify the value at all here is a consequence + -- of the declaration of the Extended_Index subtype, which includes + -- the values in the base range that immediately precede and + -- immediately follow the values in the Index_Type.) + + if Before < Index_Type'First then + raise Constraint_Error with + "Before index is out of range (too small)"; + end if; + + -- We do allow a value greater than Container.Last to be specified as + -- the Index, but only if it's immediately greater. This allows for + -- the case of appending items to the back end of the vector. (It is + -- assumed that specifying an index value greater than Last + 1 + -- indicates some deeper flaw in the caller's algorithm, so that case + -- is treated as a proper error.) + + if Before > Container.Last + 1 then + raise Constraint_Error with + "Before index is out of range (too large)"; + end if; + end if; + + -- We treat inserting 0 items into the container as a no-op, even when + -- the container is busy, so we simply return. + + if Count = 0 then + return; + end if; + + -- There are two constraints we need to satisfy. The first constraint is + -- that a container cannot have more than Count_Type'Last elements, so + -- we must check the sum of the current length and the insertion count. + -- Note: we cannot simply add these values, because of the possibility + -- of overflow. + + if Checks and then Old_Length > Count_Type'Last - Count then + raise Constraint_Error with "Count is out of range"; + end if; + + -- It is now safe compute the length of the new vector, without fear of + -- overflow. + + New_Length := Old_Length + Count; + + -- The second constraint is that the new Last index value cannot exceed + -- Index_Type'Last. In each branch below, we calculate the maximum + -- length (computed from the range of values in Index_Type), and then + -- compare the new length to the maximum length. If the new length is + -- acceptable, then we compute the new last index from that. + + if Index_Type'Base'Last >= Count_Type_Last then + -- We have to handle the case when there might be more values in the + -- range of Index_Type than in the range of Count_Type. + + if Index_Type'First <= 0 then + + -- We know that No_Index (the same as Index_Type'First - 1) is + -- less than 0, so it is safe to compute the following sum without + -- fear of overflow. We need to suppress warnings, because + -- otherwise we get an error in -gnatwE mode. + + pragma Warnings (Off); + Index := No_Index + Index_Type'Base (Count_Type'Last); + pragma Warnings (On); + + if Index <= Index_Type'Last then + + -- We have determined that range of Index_Type has at least as + -- many values as in Count_Type, so Count_Type'Last is the + -- maximum number of items that are allowed. + + Max_Length := Count_Type'Last; + + else + -- The range of Index_Type has fewer values than in Count_Type, + -- so the maximum number of items is computed from the range of + -- the Index_Type. + + Max_Length := Count_Type'Base (Index_Type'Last - No_Index); + end if; + + else + -- No_Index is equal or greater than 0, so we can safely compute + -- the difference without fear of overflow (which we would have to + -- worry about if No_Index were less than 0, but that case is + -- handled above). + + if Index_Type'Last - No_Index >= Count_Type_Last then + -- We have determined that range of Index_Type has at least as + -- many values as in Count_Type, so Count_Type'Last is the + -- maximum number of items that are allowed. + + Max_Length := Count_Type'Last; + + else + -- The range of Index_Type has fewer values than in Count_Type, + -- so the maximum number of items is computed from the range of + -- the Index_Type. + + Max_Length := Count_Type'Base (Index_Type'Last - No_Index); + end if; + end if; + + elsif Index_Type'First <= 0 then + + -- We know that No_Index (the same as Index_Type'First - 1) is less + -- than 0, so it is safe to compute the following sum without fear of + -- overflow. + + J := Count_Type'Base (No_Index) + Count_Type'Last; + + if J <= Count_Type'Base (Index_Type'Last) then + + -- We have determined that range of Index_Type has at least as + -- many values as in Count_Type, so Count_Type'Last is the maximum + -- number of items that are allowed. + + Max_Length := Count_Type'Last; + + else + -- The range of Index_Type has fewer values than Count_Type does, + -- so the maximum number of items is computed from the range of + -- the Index_Type. + + Max_Length := + Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index); + end if; + + else + -- No_Index is equal or greater than 0, so we can safely compute the + -- difference without fear of overflow (which we would have to worry + -- about if No_Index were less than 0, but that case is handled + -- above). + + Max_Length := + Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index); + end if; + + -- We have just computed the maximum length (number of items). We must + -- now compare the requested length to the maximum length, as we do not + -- allow a vector expand beyond the maximum (because that would create + -- an internal array with a last index value greater than + -- Index_Type'Last, with no way to index those elements). + + if Checks and then New_Length > Max_Length then + raise Constraint_Error with "Count is out of range"; + end if; + + -- New_Last is the last index value of the items in the container after + -- insertion. Use the wider of Index_Type'Base and Count_Type'Base to + -- compute its value from the New_Length. + + if Index_Type'Base'Last >= Count_Type_Last then + New_Last := No_Index + Index_Type'Base (New_Length); + else + New_Last := Index_Type'Base (Count_Type'Base (No_Index) + New_Length); + end if; + + if Container.Elements = null then + pragma Assert (Container.Last = No_Index); + + -- This is the simplest case, with which we must always begin: we're + -- inserting items into an empty vector that hasn't allocated an + -- internal array yet. Note that we don't need to check the busy bit + -- here, because an empty container cannot be busy. + + -- In order to preserve container invariants, we allocate the new + -- internal array first, before setting the Last index value, in case + -- the allocation fails (which can happen either because there is no + -- storage available, or because default-valued element + -- initialization fails). + + Container.Elements := new Elements_Type (New_Last); + + -- The allocation of the new, internal array succeeded, so it is now + -- safe to update the Last index, restoring container invariants. + + Container.Last := New_Last; + + return; + end if; + + -- An internal array has already been allocated, so we must determine + -- whether there is enough unused storage for the new items. + + if New_Last <= Container.Elements.Last then + + -- In this case, we're inserting space into a vector that has already + -- allocated an internal array, and the existing array has enough + -- unused storage for the new items. + + declare + EA : Elements_Array renames Container.Elements.EA; + + begin + if Before <= Container.Last then + + -- The space is being inserted before some existing elements, + -- so we must slide the existing elements up to their new + -- home. We use the wider of Index_Type'Base and + -- Count_Type'Base as the type for intermediate index values. + + if Index_Type'Base'Last >= Count_Type_Last then + Index := Before + Index_Type'Base (Count); + + else + Index := Index_Type'Base (Count_Type'Base (Before) + Count); + end if; + + EA (Index .. New_Last) := EA (Before .. Container.Last); + end if; + end; + + Container.Last := New_Last; + return; + end if; + + -- In this case, we're inserting space into a vector that has already + -- allocated an internal array, but the existing array does not have + -- enough storage, so we must allocate a new, longer array. In order to + -- guarantee that the amortized insertion cost is O(1), we always + -- allocate an array whose length is some power-of-two factor of the + -- current array length. (The new array cannot have a length less than + -- the New_Length of the container, but its last index value cannot be + -- greater than Index_Type'Last.) + + New_Capacity := Count_Type'Max (1, Container.Elements.EA'Length); + while New_Capacity < New_Length loop + if New_Capacity > Count_Type'Last / 2 then + New_Capacity := Count_Type'Last; + exit; + end if; + + New_Capacity := 2 * New_Capacity; + end loop; + + if New_Capacity > Max_Length then + + -- We have reached the limit of capacity, so no further expansion + -- will occur. (This is not a problem, as there is never a need to + -- have more capacity than the maximum container length.) + + New_Capacity := Max_Length; + end if; + + -- We have computed the length of the new internal array (and this is + -- what "vector capacity" means), so use that to compute its last index. + + if Index_Type'Base'Last >= Count_Type_Last then + Dst_Last := No_Index + Index_Type'Base (New_Capacity); + else + Dst_Last := + Index_Type'Base (Count_Type'Base (No_Index) + New_Capacity); + end if; + + -- Now we allocate the new, longer internal array. If the allocation + -- fails, we have not changed any container state, so no side-effect + -- will occur as a result of propagating the exception. + + Dst := new Elements_Type (Dst_Last); + + -- We have our new internal array. All that needs to be done now is to + -- copy the existing items (if any) from the old array (the "source" + -- array, object SA below) to the new array (the "destination" array, + -- object DA below), and then deallocate the old array. + + declare + SA : Elements_Array renames Container.Elements.EA; -- source + DA : Elements_Array renames Dst.EA; -- destination + pragma Unreferenced (DA); + + begin + DA (Index_Type'First .. Before - 1) := + SA (Index_Type'First .. Before - 1); + + if Before <= Container.Last then + + -- The space is being inserted before some existing elements, so + -- we must slide the existing elements up to their new home. + + if Index_Type'Base'Last >= Count_Type_Last then + Index := Before + Index_Type'Base (Count); + else + Index := Index_Type'Base (Count_Type'Base (Before) + Count); + end if; + + DA (Index .. New_Last) := SA (Before .. Container.Last); + end if; + + exception + when others => + Free (Dst); + raise; + end; + + -- We have successfully copied the items onto the new array, so the + -- final thing to do is restore invariants, and deallocate the old + -- array. + + declare + X : Elements_Access := Container.Elements; + + begin + -- We first isolate the old internal array, removing it from the + -- container and replacing it with the new internal array, before we + -- deallocate the old array (which can fail if finalization of + -- elements propagates an exception). + + Container.Elements := Dst; + Container.Last := New_Last; + + -- The container invariants have been restored, so it is now safe to + -- attempt to deallocate the old array. + + Free (X); + end; + end Insert_Space; + + procedure Insert_Space + (Container : in out Vector; + Before : Cursor; + Position : out Cursor; + Count : Count_Type := 1) + is + Index : Index_Type'Base; + + begin + if Checks and then Before.Container /= null + and then Before.Container /= Container'Unrestricted_Access + then + raise Program_Error with "Before cursor denotes wrong container"; + end if; + + if Count = 0 then + if Before.Container = null or else Before.Index > Container.Last then + Position := No_Element; + else + Position := (Container'Unrestricted_Access, Before.Index); + end if; + + return; + end if; + + if Before.Container = null or else Before.Index > Container.Last then + if Checks and then Container.Last = Index_Type'Last then + raise Constraint_Error with + "vector is already at its maximum length"; + else + Index := Container.Last + 1; + end if; + + else + Index := Before.Index; + end if; + + Insert_Space (Container, Index, Count); + + Position := (Container'Unrestricted_Access, Index); + end Insert_Space; + + -------------- + -- Is_Empty -- + -------------- + + function Is_Empty (Container : Vector) return Boolean is + begin + return Container.Last < Index_Type'First; + end Is_Empty; + + ------------- + -- Iterate -- + ------------- + + procedure Iterate + (Container : Vector; + Process : not null access procedure (Position : Cursor)) + is + Busy : With_Busy (Container.TC'Unrestricted_Access); + begin + for Indx in Index_Type'First .. Container.Last loop + Process (Cursor'(Container'Unrestricted_Access, Indx)); + end loop; + end Iterate; + + function Iterate + (Container : Vector) + return Vector_Iterator_Interfaces.Reversible_Iterator'Class + is + V : constant Vector_Access := Container'Unrestricted_Access; + begin + -- The value of its Index component influences the behavior of the First + -- and Last selector functions of the iterator object. When the Index + -- component is No_Index (as is the case here), this means the iterator + -- object was constructed without a start expression. This is a complete + -- iterator, meaning that the iteration starts from the (logical) + -- beginning of the sequence of items. + + -- Note: For a forward iterator, Container.First is the beginning, and + -- for a reverse iterator, Container.Last is the beginning. + + return It : constant Iterator := + (Limited_Controlled with + Container => V, + Index => No_Index) + do + Busy (Container.TC'Unrestricted_Access.all); + end return; + end Iterate; + + function Iterate + (Container : Vector; + Start : Cursor) + return Vector_Iterator_Interfaces.Reversible_Iterator'Class + is + V : constant Vector_Access := Container'Unrestricted_Access; + begin + -- It was formerly the case that when Start = No_Element, the partial + -- iterator was defined to behave the same as for a complete iterator, + -- and iterate over the entire sequence of items. However, those + -- semantics were unintuitive and arguably error-prone (it is too easy + -- to accidentally create an endless loop), and so they were changed, + -- per the ARG meeting in Denver on 2011/11. However, there was no + -- consensus about what positive meaning this corner case should have, + -- and so it was decided to simply raise an exception. This does imply, + -- however, that it is not possible to use a partial iterator to specify + -- an empty sequence of items. + + if Checks then + if Start.Container = null then + raise Constraint_Error with + "Start position for iterator equals No_Element"; + end if; + + if Start.Container /= V then + raise Program_Error with + "Start cursor of Iterate designates wrong vector"; + end if; + + if Start.Index > V.Last then + raise Constraint_Error with + "Start position for iterator equals No_Element"; + end if; + end if; + + -- The value of its Index component influences the behavior of the First + -- and Last selector functions of the iterator object. When the Index + -- component is not No_Index (as is the case here), it means that this + -- is a partial iteration, over a subset of the complete sequence of + -- items. The iterator object was constructed with a start expression, + -- indicating the position from which the iteration begins. Note that + -- the start position has the same value irrespective of whether this + -- is a forward or reverse iteration. + + return It : constant Iterator := + (Limited_Controlled with + Container => V, + Index => Start.Index) + do + Busy (Container.TC'Unrestricted_Access.all); + end return; + end Iterate; + + ---------- + -- Last -- + ---------- + + function Last (Container : Vector) return Cursor is + begin + if Is_Empty (Container) then + return No_Element; + else + return (Container'Unrestricted_Access, Container.Last); + end if; + end Last; + + function Last (Object : Iterator) return Cursor is + begin + -- The value of the iterator object's Index component influences the + -- behavior of the Last (and First) selector function. + + -- When the Index component is No_Index, this means the iterator + -- object was constructed without a start expression, in which case the + -- (reverse) iteration starts from the (logical) beginning of the entire + -- sequence (corresponding to Container.Last, for a reverse iterator). + + -- Otherwise, this is iteration over a partial sequence of items. + -- When the Index component is not No_Index, the iterator object was + -- constructed with a start expression, that specifies the position + -- from which the (reverse) partial iteration begins. + + if Object.Index = No_Index then + return Last (Object.Container.all); + else + return Cursor'(Object.Container, Object.Index); + end if; + end Last; + + ------------------ + -- Last_Element -- + ------------------ + + function Last_Element (Container : Vector) return Element_Type is + begin + if Checks and then Container.Last = No_Index then + raise Constraint_Error with "Container is empty"; + else + return Container.Elements.EA (Container.Last); + end if; + end Last_Element; + + ---------------- + -- Last_Index -- + ---------------- + + function Last_Index (Container : Vector) return Extended_Index is + begin + return Container.Last; + end Last_Index; + + ------------ + -- Length -- + ------------ + + function Length (Container : Vector) return Count_Type is + L : constant Index_Type'Base := Container.Last; + F : constant Index_Type := Index_Type'First; + + begin + -- The base range of the index type (Index_Type'Base) might not include + -- all values for length (Count_Type). Contrariwise, the index type + -- might include values outside the range of length. Hence we use + -- whatever type is wider for intermediate values when calculating + -- length. Note that no matter what the index type is, the maximum + -- length to which a vector is allowed to grow is always the minimum + -- of Count_Type'Last and (IT'Last - IT'First + 1). + + -- For example, an Index_Type with range -127 .. 127 is only guaranteed + -- to have a base range of -128 .. 127, but the corresponding vector + -- would have lengths in the range 0 .. 255. In this case we would need + -- to use Count_Type'Base for intermediate values. + + -- Another case would be the index range -2**63 + 1 .. -2**63 + 10. The + -- vector would have a maximum length of 10, but the index values lie + -- outside the range of Count_Type (which is only 32 bits). In this + -- case we would need to use Index_Type'Base for intermediate values. + + if Count_Type'Base'Last >= Index_Type'Pos (Index_Type'Base'Last) then + return Count_Type'Base (L) - Count_Type'Base (F) + 1; + else + return Count_Type (L - F + 1); + end if; + end Length; + + ---------- + -- Move -- + ---------- + + procedure Move + (Target : in out Vector; + Source : in out Vector) + is + begin + if Target'Address = Source'Address then + return; + end if; + + TC_Check (Target.TC); + TC_Check (Source.TC); + + declare + Target_Elements : constant Elements_Access := Target.Elements; + begin + Target.Elements := Source.Elements; + Source.Elements := Target_Elements; + end; + + Target.Last := Source.Last; + Source.Last := No_Index; + end Move; + + ---------- + -- Next -- + ---------- + + function Next (Position : Cursor) return Cursor is + begin + if Position.Container = null then + return No_Element; + elsif Position.Index < Position.Container.Last then + return (Position.Container, Position.Index + 1); + else + return No_Element; + end if; + end Next; + + function Next (Object : Iterator; Position : Cursor) return Cursor is + begin + if Position.Container = null then + return No_Element; + elsif Checks and then Position.Container /= Object.Container then + raise Program_Error with + "Position cursor of Next designates wrong vector"; + else + return Next (Position); + end if; + end Next; + + procedure Next (Position : in out Cursor) is + begin + if Position.Container = null then + return; + elsif Position.Index < Position.Container.Last then + Position.Index := Position.Index + 1; + else + Position := No_Element; + end if; + end Next; + + ------------- + -- Prepend -- + ------------- + + procedure Prepend + (Container : in out Vector; + New_Item : Element_Type; + Count : Count_Type := 1) + is + begin + Insert (Container, Index_Type'First, New_Item, Count); + end Prepend; + + -------------------- + -- Prepend_Vector -- + -------------------- + + procedure Prepend_Vector (Container : in out Vector; New_Item : Vector) is + begin + Insert_Vector (Container, Index_Type'First, New_Item); + end Prepend_Vector; + + -------------- + -- Previous -- + -------------- + + function Previous (Position : Cursor) return Cursor is + begin + if Position.Container = null then + return No_Element; + elsif Position.Index > Index_Type'First then + return (Position.Container, Position.Index - 1); + else + return No_Element; + end if; + end Previous; + + function Previous (Object : Iterator; Position : Cursor) return Cursor is + begin + if Position.Container = null then + return No_Element; + elsif Checks and then Position.Container /= Object.Container then + raise Program_Error with + "Position cursor of Previous designates wrong vector"; + else + return Previous (Position); + end if; + end Previous; + + procedure Previous (Position : in out Cursor) is + begin + if Position.Container = null then + return; + elsif Position.Index > Index_Type'First then + Position.Index := Position.Index - 1; + else + Position := No_Element; + end if; + end Previous; + + ---------------------- + -- Pseudo_Reference -- + ---------------------- + + function Pseudo_Reference + (Container : aliased Vector'Class) return Reference_Control_Type + is + TC : constant Tamper_Counts_Access := Container.TC'Unrestricted_Access; + begin + return R : constant Reference_Control_Type := (Controlled with TC) do + Busy (TC.all); + end return; + end Pseudo_Reference; + + --------------- + -- Put_Image -- + --------------- + + procedure Put_Image + (S : in out Ada.Strings.Text_Buffers.Root_Buffer_Type'Class; V : Vector) + is + First_Time : Boolean := True; + use System.Put_Images; + begin + Array_Before (S); + + for X of V loop + if First_Time then + First_Time := False; + else + Simple_Array_Between (S); + end if; + + Element_Type'Put_Image (S, X); + end loop; + + Array_After (S); + end Put_Image; + + ------------------- + -- Query_Element -- + ------------------- + + procedure Query_Element + (Container : Vector; + Index : Index_Type; + Process : not null access procedure (Element : Element_Type)) + is + Lock : With_Lock (Container.TC'Unrestricted_Access); + begin + if Checks and then Index > Container.Last then + raise Constraint_Error with "Index is out of range"; + end if; + + Process (Container.Elements.EA (Index)); + end Query_Element; + + procedure Query_Element + (Position : Cursor; + Process : not null access procedure (Element : Element_Type)) + is + begin + if Checks and then Position.Container = null then + raise Constraint_Error with "Position cursor has no element"; + else + Query_Element (Position.Container.all, Position.Index, Process); + end if; + end Query_Element; + + ---------- + -- Read -- + ---------- + + procedure Read + (Stream : not null access Root_Stream_Type'Class; + Container : out Vector) + is + Length : Count_Type'Base; + Last : Index_Type'Base := No_Index; + + begin + Clear (Container); + + Count_Type'Base'Read (Stream, Length); + + if Length > Capacity (Container) then + Reserve_Capacity (Container, Capacity => Length); + end if; + + for J in Count_Type range 1 .. Length loop + Last := Last + 1; + Element_Type'Read (Stream, Container.Elements.EA (Last)); + Container.Last := Last; + end loop; + end Read; + + procedure Read + (Stream : not null access Root_Stream_Type'Class; + Position : out Cursor) + is + begin + raise Program_Error with "attempt to stream vector cursor"; + end Read; + + procedure Read + (Stream : not null access Root_Stream_Type'Class; + Item : out Reference_Type) + is + begin + raise Program_Error with "attempt to stream reference"; + end Read; + + procedure Read + (Stream : not null access Root_Stream_Type'Class; + Item : out Constant_Reference_Type) + is + begin + raise Program_Error with "attempt to stream reference"; + end Read; + + --------------- + -- Reference -- + --------------- + + function Reference + (Container : aliased in out Vector; + Position : Cursor) return Reference_Type + is + begin + if Checks then + if Position.Container = null then + raise Constraint_Error with "Position cursor has no element"; + end if; + + if Position.Container /= Container'Unrestricted_Access then + raise Program_Error with "Position cursor denotes wrong container"; + end if; + + if Position.Index > Position.Container.Last then + raise Constraint_Error with "Position cursor is out of range"; + end if; + end if; + + declare + TC : constant Tamper_Counts_Access := + Container.TC'Unrestricted_Access; + begin + return R : constant Reference_Type := + (Element => Container.Elements.EA (Position.Index)'Access, + Control => (Controlled with TC)) + do + Busy (TC.all); + end return; + end; + end Reference; + + function Reference + (Container : aliased in out Vector; + Index : Index_Type) return Reference_Type + is + begin + if Checks and then Index > Container.Last then + raise Constraint_Error with "Index is out of range"; + end if; + + declare + TC : constant Tamper_Counts_Access := + Container.TC'Unrestricted_Access; + begin + return R : constant Reference_Type := + (Element => Container.Elements.EA (Index)'Access, + Control => (Controlled with TC)) + do + Busy (TC.all); + end return; + end; + end Reference; + + --------------------- + -- Replace_Element -- + --------------------- + + procedure Replace_Element + (Container : in out Vector; + Index : Index_Type; + New_Item : Element_Type) + is + begin + TE_Check (Container.TC); + + if Checks and then Index > Container.Last then + raise Constraint_Error with "Index is out of range"; + end if; + + Container.Elements.EA (Index) := New_Item; + end Replace_Element; + + procedure Replace_Element + (Container : in out Vector; + Position : Cursor; + New_Item : Element_Type) + is + begin + TE_Check (Container.TC); + + if Checks then + if Position.Container = null then + raise Constraint_Error with "Position cursor has no element"; + + elsif Position.Container /= Container'Unrestricted_Access then + raise Program_Error with "Position cursor denotes wrong container"; + + elsif Position.Index > Container.Last then + raise Constraint_Error with "Position cursor is out of range"; + end if; + end if; + + Container.Elements.EA (Position.Index) := New_Item; + end Replace_Element; + + ---------------------- + -- Reserve_Capacity -- + ---------------------- + + procedure Reserve_Capacity + (Container : in out Vector; + Capacity : Count_Type) + is + N : constant Count_Type := Length (Container); + + Index : Count_Type'Base; + Last : Index_Type'Base; + + begin + -- Reserve_Capacity can be used to either expand the storage available + -- for elements (this would be its typical use, in anticipation of + -- future insertion), or to trim back storage. In the latter case, + -- storage can only be trimmed back to the limit of the container + -- length. Note that Reserve_Capacity neither deletes (active) elements + -- nor inserts elements; it only affects container capacity, never + -- container length. + + if Capacity = 0 then + + -- This is a request to trim back storage, to the minimum amount + -- possible given the current state of the container. + + if N = 0 then + + -- The container is empty, so in this unique case we can + -- deallocate the entire internal array. Note that an empty + -- container can never be busy, so there's no need to check the + -- tampering bits. + + declare + X : Elements_Access := Container.Elements; + + begin + -- First we remove the internal array from the container, to + -- handle the case when the deallocation raises an exception. + + Container.Elements := null; + + -- Container invariants have been restored, so it is now safe + -- to attempt to deallocate the internal array. + + Free (X); + end; + + elsif N < Container.Elements.EA'Length then + + -- The container is not empty, and the current length is less than + -- the current capacity, so there's storage available to trim. In + -- this case, we allocate a new internal array having a length + -- that exactly matches the number of items in the + -- container. (Reserve_Capacity does not delete active elements, + -- so this is the best we can do with respect to minimizing + -- storage). + + TC_Check (Container.TC); + + declare + subtype Src_Index_Subtype is Index_Type'Base range + Index_Type'First .. Container.Last; + + Src : Elements_Array renames + Container.Elements.EA (Src_Index_Subtype); + + X : Elements_Access := Container.Elements; + + begin + -- Although we have isolated the old internal array that we're + -- going to deallocate, we don't deallocate it until we have + -- successfully allocated a new one. If there is an exception + -- during allocation (either because there is not enough + -- storage, or because initialization of the elements fails), + -- we let it propagate without causing any side-effect. + + Container.Elements := new Elements_Type'(Container.Last, Src); + + -- We have successfully allocated a new internal array (with a + -- smaller length than the old one, and containing a copy of + -- just the active elements in the container), so it is now + -- safe to attempt to deallocate the old array. The old array + -- has been isolated, and container invariants have been + -- restored, so if the deallocation fails (because finalization + -- of the elements fails), we simply let it propagate. + + Free (X); + end; + end if; + + return; + end if; + + -- Reserve_Capacity can be used to expand the storage available for + -- elements, but we do not let the capacity grow beyond the number of + -- values in Index_Type'Range. (Were it otherwise, there would be no way + -- to refer to the elements with an index value greater than + -- Index_Type'Last, so that storage would be wasted.) Here we compute + -- the Last index value of the new internal array, in a way that avoids + -- any possibility of overflow. + + if Index_Type'Base'Last >= Count_Type_Last then + + -- We perform a two-part test. First we determine whether the + -- computed Last value lies in the base range of the type, and then + -- determine whether it lies in the range of the index (sub)type. + + -- Last must satisfy this relation: + -- First + Length - 1 <= Last + -- We regroup terms: + -- First - 1 <= Last - Length + -- Which can rewrite as: + -- No_Index <= Last - Length + + if Checks and then + Index_Type'Base'Last - Index_Type'Base (Capacity) < No_Index + then + raise Constraint_Error with "Capacity is out of range"; + end if; + + -- We now know that the computed value of Last is within the base + -- range of the type, so it is safe to compute its value: + + Last := No_Index + Index_Type'Base (Capacity); + + -- Finally we test whether the value is within the range of the + -- generic actual index subtype: + + if Checks and then Last > Index_Type'Last then + raise Constraint_Error with "Capacity is out of range"; + end if; + + elsif Index_Type'First <= 0 then + + -- Here we can compute Last directly, in the normal way. We know that + -- No_Index is less than 0, so there is no danger of overflow when + -- adding the (positive) value of Capacity. + + Index := Count_Type'Base (No_Index) + Capacity; -- Last + + if Checks and then Index > Count_Type'Base (Index_Type'Last) then + raise Constraint_Error with "Capacity is out of range"; + end if; + + -- We know that the computed value (having type Count_Type) of Last + -- is within the range of the generic actual index subtype, so it is + -- safe to convert to Index_Type: + + Last := Index_Type'Base (Index); + + else + -- Here Index_Type'First (and Index_Type'Last) is positive, so we + -- must test the length indirectly (by working backwards from the + -- largest possible value of Last), in order to prevent overflow. + + Index := Count_Type'Base (Index_Type'Last) - Capacity; -- No_Index + + if Checks and then Index < Count_Type'Base (No_Index) then + raise Constraint_Error with "Capacity is out of range"; + end if; + + -- We have determined that the value of Capacity would not create a + -- Last index value outside of the range of Index_Type, so we can now + -- safely compute its value. + + Last := Index_Type'Base (Count_Type'Base (No_Index) + Capacity); + end if; + + -- The requested capacity is non-zero, but we don't know yet whether + -- this is a request for expansion or contraction of storage. + + if Container.Elements = null then + + -- The container is empty (it doesn't even have an internal array), + -- so this represents a request to allocate (expand) storage having + -- the given capacity. + + Container.Elements := new Elements_Type (Last); + return; + end if; + + if Capacity <= N then + + -- This is a request to trim back storage, but only to the limit of + -- what's already in the container. (Reserve_Capacity never deletes + -- active elements, it only reclaims excess storage.) + + if N < Container.Elements.EA'Length then + + -- The container is not empty (because the requested capacity is + -- positive, and less than or equal to the container length), and + -- the current length is less than the current capacity, so + -- there's storage available to trim. In this case, we allocate a + -- new internal array having a length that exactly matches the + -- number of items in the container. + + TC_Check (Container.TC); + + declare + subtype Src_Index_Subtype is Index_Type'Base range + Index_Type'First .. Container.Last; + + Src : Elements_Array renames + Container.Elements.EA (Src_Index_Subtype); + + X : Elements_Access := Container.Elements; + + begin + -- Although we have isolated the old internal array that we're + -- going to deallocate, we don't deallocate it until we have + -- successfully allocated a new one. If there is an exception + -- during allocation (either because there is not enough + -- storage, or because initialization of the elements fails), + -- we let it propagate without causing any side-effect. + + Container.Elements := new Elements_Type'(Container.Last, Src); + + -- We have successfully allocated a new internal array (with a + -- smaller length than the old one, and containing a copy of + -- just the active elements in the container), so it is now + -- safe to attempt to deallocate the old array. The old array + -- has been isolated, and container invariants have been + -- restored, so if the deallocation fails (because finalization + -- of the elements fails), we simply let it propagate. + + Free (X); + end; + end if; + + return; + end if; + + -- The requested capacity is larger than the container length (the + -- number of active elements). Whether this represents a request for + -- expansion or contraction of the current capacity depends on what the + -- current capacity is. + + if Capacity = Container.Elements.EA'Length then + + -- The requested capacity matches the existing capacity, so there's + -- nothing to do here. We treat this case as a no-op, and simply + -- return without checking the busy bit. + + return; + end if; + + -- There is a change in the capacity of a non-empty container, so a new + -- internal array will be allocated. (The length of the new internal + -- array could be less or greater than the old internal array. We know + -- only that the length of the new internal array is greater than the + -- number of active elements in the container.) We must check whether + -- the container is busy before doing anything else. + + TC_Check (Container.TC); + + -- We now allocate a new internal array, having a length different from + -- its current value. + + declare + E : Elements_Access := new Elements_Type (Last); + + begin + -- We have successfully allocated the new internal array. We first + -- attempt to copy the existing elements from the old internal array + -- ("src" elements) onto the new internal array ("tgt" elements). + + declare + subtype Index_Subtype is Index_Type'Base range + Index_Type'First .. Container.Last; + + Src : Elements_Array renames + Container.Elements.EA (Index_Subtype); + + Tgt : Elements_Array renames E.EA (Index_Subtype); + + begin + Tgt := Src; + + exception + when others => + Free (E); + raise; + end; + + -- We have successfully copied the existing elements onto the new + -- internal array, so now we can attempt to deallocate the old one. + + declare + X : Elements_Access := Container.Elements; + + begin + -- First we isolate the old internal array, and replace it in the + -- container with the new internal array. + + Container.Elements := E; + + -- Container invariants have been restored, so it is now safe to + -- attempt to deallocate the old internal array. + + Free (X); + end; + end; + end Reserve_Capacity; + + ---------------------- + -- Reverse_Elements -- + ---------------------- + + procedure Reverse_Elements (Container : in out Vector) is + begin + if Container.Length <= 1 then + return; + end if; + + -- The exception behavior for the vector container must match that for + -- the list container, so we check for cursor tampering here (which will + -- catch more things) instead of for element tampering (which will catch + -- fewer things). It's true that the elements of this vector container + -- could be safely moved around while (say) an iteration is taking place + -- (iteration only increments the busy counter), and so technically + -- all we would need here is a test for element tampering (indicated + -- by the lock counter), that's simply an artifact of our array-based + -- implementation. Logically Reverse_Elements requires a check for + -- cursor tampering. + + TC_Check (Container.TC); + + declare + K : Index_Type; + J : Index_Type; + E : Elements_Type renames Container.Elements.all; + + begin + K := Index_Type'First; + J := Container.Last; + while K < J loop + declare + EK : constant Element_Type := E.EA (K); + begin + E.EA (K) := E.EA (J); + E.EA (J) := EK; + end; + + K := K + 1; + J := J - 1; + end loop; + end; + end Reverse_Elements; + + ------------------ + -- Reverse_Find -- + ------------------ + + function Reverse_Find + (Container : Vector; + Item : Element_Type; + Position : Cursor := No_Element) return Cursor + is + Last : Index_Type'Base; + + begin + if Checks and then Position.Container /= null + and then Position.Container /= Container'Unrestricted_Access + then + raise Program_Error with "Position cursor denotes wrong container"; + end if; + + Last := + (if Position.Container = null or else Position.Index > Container.Last + then Container.Last + else Position.Index); + + -- Per AI05-0022, the container implementation is required to detect + -- element tampering by a generic actual subprogram. + + declare + Lock : With_Lock (Container.TC'Unrestricted_Access); + begin + for Indx in reverse Index_Type'First .. Last loop + if Container.Elements.EA (Indx) = Item then + return Cursor'(Container'Unrestricted_Access, Indx); + end if; + end loop; + + return No_Element; + end; + end Reverse_Find; + + ------------------------ + -- Reverse_Find_Index -- + ------------------------ + + function Reverse_Find_Index + (Container : Vector; + Item : Element_Type; + Index : Index_Type := Index_Type'Last) return Extended_Index + is + -- Per AI05-0022, the container implementation is required to detect + -- element tampering by a generic actual subprogram. + + Lock : With_Lock (Container.TC'Unrestricted_Access); + + Last : constant Index_Type'Base := + Index_Type'Min (Container.Last, Index); + + begin + for Indx in reverse Index_Type'First .. Last loop + if Container.Elements.EA (Indx) = Item then + return Indx; + end if; + end loop; + + return No_Index; + end Reverse_Find_Index; + + --------------------- + -- Reverse_Iterate -- + --------------------- + + procedure Reverse_Iterate + (Container : Vector; + Process : not null access procedure (Position : Cursor)) + is + Busy : With_Busy (Container.TC'Unrestricted_Access); + begin + for Indx in reverse Index_Type'First .. Container.Last loop + Process (Cursor'(Container'Unrestricted_Access, Indx)); + end loop; + end Reverse_Iterate; + + ---------------- + -- Set_Length -- + ---------------- + + procedure Set_Length (Container : in out Vector; Length : Count_Type) is + Count : constant Count_Type'Base := Container.Length - Length; + + begin + -- Set_Length allows the user to set the length explicitly, instead + -- of implicitly as a side-effect of deletion or insertion. If the + -- requested length is less than the current length, this is equivalent + -- to deleting items from the back end of the vector. If the requested + -- length is greater than the current length, then this is equivalent + -- to inserting "space" (nonce items) at the end. + + if Count >= 0 then + Container.Delete_Last (Count); + + elsif Checks and then Container.Last >= Index_Type'Last then + raise Constraint_Error with "vector is already at its maximum length"; + + else + Container.Insert_Space (Container.Last + 1, -Count); + end if; + end Set_Length; + + ---------- + -- Swap -- + ---------- + + procedure Swap (Container : in out Vector; I, J : Index_Type) is + begin + TE_Check (Container.TC); + + if Checks then + if I > Container.Last then + raise Constraint_Error with "I index is out of range"; + end if; + + if J > Container.Last then + raise Constraint_Error with "J index is out of range"; + end if; + end if; + + if I = J then + return; + end if; + + declare + EI_Copy : constant Element_Type := Container.Elements.EA (I); + begin + Container.Elements.EA (I) := Container.Elements.EA (J); + Container.Elements.EA (J) := EI_Copy; + end; + end Swap; + + procedure Swap (Container : in out Vector; I, J : Cursor) is + begin + if Checks then + if I.Container = null then + raise Constraint_Error with "I cursor has no element"; + + elsif J.Container = null then + raise Constraint_Error with "J cursor has no element"; + + elsif I.Container /= Container'Unrestricted_Access then + raise Program_Error with "I cursor denotes wrong container"; + + elsif J.Container /= Container'Unrestricted_Access then + raise Program_Error with "J cursor denotes wrong container"; + end if; + end if; + + Swap (Container, I.Index, J.Index); + end Swap; + + --------------- + -- To_Cursor -- + --------------- + + function To_Cursor + (Container : Vector; + Index : Extended_Index) return Cursor + is + begin + if Index not in Index_Type'First .. Container.Last then + return No_Element; + else + return (Container'Unrestricted_Access, Index); + end if; + end To_Cursor; + + -------------- + -- To_Index -- + -------------- + + function To_Index (Position : Cursor) return Extended_Index is + begin + if Position.Container = null then + return No_Index; + elsif Position.Index <= Position.Container.Last then + return Position.Index; + else + return No_Index; + end if; + end To_Index; + + --------------- + -- To_Vector -- + --------------- + + function To_Vector (Length : Count_Type) return Vector is + Index : Count_Type'Base; + Last : Index_Type'Base; + Elements : Elements_Access; + + begin + if Length = 0 then + return Empty_Vector; + end if; + + -- We create a vector object with a capacity that matches the specified + -- Length, but we do not allow the vector capacity (the length of the + -- internal array) to exceed the number of values in Index_Type'Range + -- (otherwise, there would be no way to refer to those components via an + -- index). We must therefore check whether the specified Length would + -- create a Last index value greater than Index_Type'Last. + + if Index_Type'Base'Last >= Count_Type_Last then + + -- We perform a two-part test. First we determine whether the + -- computed Last value lies in the base range of the type, and then + -- determine whether it lies in the range of the index (sub)type. + + -- Last must satisfy this relation: + -- First + Length - 1 <= Last + -- We regroup terms: + -- First - 1 <= Last - Length + -- Which can rewrite as: + -- No_Index <= Last - Length + + if Checks and then + Index_Type'Base'Last - Index_Type'Base (Length) < No_Index + then + raise Constraint_Error with "Length is out of range"; + end if; + + -- We now know that the computed value of Last is within the base + -- range of the type, so it is safe to compute its value: + + Last := No_Index + Index_Type'Base (Length); + + -- Finally we test whether the value is within the range of the + -- generic actual index subtype: + + if Checks and then Last > Index_Type'Last then + raise Constraint_Error with "Length is out of range"; + end if; + + elsif Index_Type'First <= 0 then + + -- Here we can compute Last directly, in the normal way. We know that + -- No_Index is less than 0, so there is no danger of overflow when + -- adding the (positive) value of Length. + + Index := Count_Type'Base (No_Index) + Length; -- Last + + if Checks and then Index > Count_Type'Base (Index_Type'Last) then + raise Constraint_Error with "Length is out of range"; + end if; + + -- We know that the computed value (having type Count_Type) of Last + -- is within the range of the generic actual index subtype, so it is + -- safe to convert to Index_Type: + + Last := Index_Type'Base (Index); + + else + -- Here Index_Type'First (and Index_Type'Last) is positive, so we + -- must test the length indirectly (by working backwards from the + -- largest possible value of Last), in order to prevent overflow. + + Index := Count_Type'Base (Index_Type'Last) - Length; -- No_Index + + if Checks and then Index < Count_Type'Base (No_Index) then + raise Constraint_Error with "Length is out of range"; + end if; + + -- We have determined that the value of Length would not create a + -- Last index value outside of the range of Index_Type, so we can now + -- safely compute its value. + + Last := Index_Type'Base (Count_Type'Base (No_Index) + Length); + end if; + + Elements := new Elements_Type (Last); + + return Vector'(Controlled with Elements, Last, TC => <>); + end To_Vector; + + function To_Vector + (New_Item : Element_Type; + Length : Count_Type) return Vector + is + Index : Count_Type'Base; + Last : Index_Type'Base; + Elements : Elements_Access; + + begin + if Length = 0 then + return Empty_Vector; + end if; + + -- We create a vector object with a capacity that matches the specified + -- Length, but we do not allow the vector capacity (the length of the + -- internal array) to exceed the number of values in Index_Type'Range + -- (otherwise, there would be no way to refer to those components via an + -- index). We must therefore check whether the specified Length would + -- create a Last index value greater than Index_Type'Last. + + if Index_Type'Base'Last >= Count_Type_Last then + + -- We perform a two-part test. First we determine whether the + -- computed Last value lies in the base range of the type, and then + -- determine whether it lies in the range of the index (sub)type. + + -- Last must satisfy this relation: + -- First + Length - 1 <= Last + -- We regroup terms: + -- First - 1 <= Last - Length + -- Which can rewrite as: + -- No_Index <= Last - Length + + if Checks and then + Index_Type'Base'Last - Index_Type'Base (Length) < No_Index + then + raise Constraint_Error with "Length is out of range"; + end if; + + -- We now know that the computed value of Last is within the base + -- range of the type, so it is safe to compute its value: + + Last := No_Index + Index_Type'Base (Length); + + -- Finally we test whether the value is within the range of the + -- generic actual index subtype: + + if Checks and then Last > Index_Type'Last then + raise Constraint_Error with "Length is out of range"; + end if; + + elsif Index_Type'First <= 0 then + + -- Here we can compute Last directly, in the normal way. We know that + -- No_Index is less than 0, so there is no danger of overflow when + -- adding the (positive) value of Length. + + Index := Count_Type'Base (No_Index) + Length; -- same value as V.Last + + if Checks and then Index > Count_Type'Base (Index_Type'Last) then + raise Constraint_Error with "Length is out of range"; + end if; + + -- We know that the computed value (having type Count_Type) of Last + -- is within the range of the generic actual index subtype, so it is + -- safe to convert to Index_Type: + + Last := Index_Type'Base (Index); + + else + -- Here Index_Type'First (and Index_Type'Last) is positive, so we + -- must test the length indirectly (by working backwards from the + -- largest possible value of Last), in order to prevent overflow. + + Index := Count_Type'Base (Index_Type'Last) - Length; -- No_Index + + if Checks and then Index < Count_Type'Base (No_Index) then + raise Constraint_Error with "Length is out of range"; + end if; + + -- We have determined that the value of Length would not create a + -- Last index value outside of the range of Index_Type, so we can now + -- safely compute its value. + + Last := Index_Type'Base (Count_Type'Base (No_Index) + Length); + end if; + + Elements := new Elements_Type'(Last, EA => [others => New_Item]); + + return (Controlled with Elements, Last, TC => <>); + end To_Vector; + + -------------------- + -- Update_Element -- + -------------------- + + procedure Update_Element + (Container : in out Vector; + Index : Index_Type; + Process : not null access procedure (Element : in out Element_Type)) + is + Lock : With_Lock (Container.TC'Unchecked_Access); + begin + if Checks and then Index > Container.Last then + raise Constraint_Error with "Index is out of range"; + end if; + + Process (Container.Elements.EA (Index)); + end Update_Element; + + procedure Update_Element + (Container : in out Vector; + Position : Cursor; + Process : not null access procedure (Element : in out Element_Type)) + is + begin + if Checks then + if Position.Container = null then + raise Constraint_Error with "Position cursor has no element"; + elsif Position.Container /= Container'Unrestricted_Access then + raise Program_Error with "Position cursor denotes wrong container"; + end if; + end if; + + Update_Element (Container, Position.Index, Process); + end Update_Element; + + ----------- + -- Write -- + ----------- + + procedure Write + (Stream : not null access Root_Stream_Type'Class; + Container : Vector) + is + begin + Count_Type'Base'Write (Stream, Length (Container)); + + for J in Index_Type'First .. Container.Last loop + Element_Type'Write (Stream, Container.Elements.EA (J)); + end loop; + end Write; + + procedure Write + (Stream : not null access Root_Stream_Type'Class; + Position : Cursor) + is + begin + raise Program_Error with "attempt to stream vector cursor"; + end Write; + + procedure Write + (Stream : not null access Root_Stream_Type'Class; + Item : Reference_Type) + is + begin + raise Program_Error with "attempt to stream reference"; + end Write; + + procedure Write + (Stream : not null access Root_Stream_Type'Class; + Item : Constant_Reference_Type) + is + begin + raise Program_Error with "attempt to stream reference"; + end Write; + +end Ada.Containers.Vectors; diff --git a/testsuite/tests/361-overriden-runtime-specs/src/a-convec.ads b/testsuite/tests/361-overriden-runtime-specs/src/a-convec.ads new file mode 100644 index 000000000..bbf57df52 --- /dev/null +++ b/testsuite/tests/361-overriden-runtime-specs/src/a-convec.ads @@ -0,0 +1,878 @@ +------------------------------------------------------------------------------ +-- -- +-- GNAT LIBRARY COMPONENTS -- +-- -- +-- A D A . C O N T A I N E R S . V E C T O R S -- +-- -- +-- S p e c -- +-- -- +-- Copyright (C) 2004-2024, Free Software Foundation, Inc. -- +-- -- +-- This specification is derived from the Ada Reference Manual for use with -- +-- GNAT. The copyright notice above, and the license provisions that follow -- +-- apply solely to the contents of the part following the private keyword. -- +-- -- +-- 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- -- +-- ware Foundation; either version 3, or (at your option) any later ver- -- +-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- +-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- +-- or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- . -- +-- -- +-- This unit was originally developed by Matthew J Heaney. -- +------------------------------------------------------------------------------ + +with Ada.Iterator_Interfaces; + +with Ada.Containers.Helpers; +private with Ada.Finalization; +private with Ada.Streams; +private with Ada.Strings.Text_Buffers; + +-- The language-defined generic package Containers.Vectors provides private +-- types Vector and Cursor, and a set of operations for each type. A vector +-- container allows insertion and deletion at any position, but it is +-- specifically optimized for insertion and deletion at the high end (the end +-- with the higher index) of the container. A vector container also provides +-- random access to its elements. +-- +-- A vector container behaves conceptually as an array that expands as +-- necessary as items are inserted. The length of a vector is the number of +-- elements that the vector contains. The capacity of a vector is the maximum +-- number of elements that can be inserted into the vector prior to it being +-- automatically expanded. +-- +-- Elements in a vector container can be referred to by an index value of a +-- generic formal type. The first element of a vector always has its index +-- value equal to the lower bound of the formal type. +-- +-- A vector container may contain empty elements. Empty elements do not have a +-- specified value. + +generic + type Index_Type is range <>; + type Element_Type is private; + + with function "=" (Left, Right : Element_Type) return Boolean is <>; + -- The actual function for the generic formal function "=" on Element_Type + -- values is expected to define a reflexive and symmetric relationship and + -- return the same result value each time it is called with a particular + -- pair of values. If it behaves in some other manner, the functions + -- defined to use it return an unspecified value. The exact arguments and + -- number of calls of this generic formal function by the functions defined + -- to use it are unspecified. + +package Ada.Containers.Vectors with + SPARK_Mode => Off +is + pragma Annotate (CodePeer, Skip_Analysis); + pragma Preelaborate; + pragma Remote_Types; + + subtype Extended_Index is Index_Type'Base + range Index_Type'First - 1 .. + Index_Type'Min (Index_Type'Base'Last - 1, Index_Type'Last) + 1; + -- The subtype Extended_Index includes the indices covered by Index_Type + -- plus the value No_Index and, if it exists, the successor to the + -- Index_Type'Last. + + No_Index : constant Extended_Index := Extended_Index'First; + -- No_Index represents a position that does not correspond to any element. + + type Vector is tagged private + with + Constant_Indexing => Constant_Reference, + Variable_Indexing => Reference, + Default_Iterator => Iterate, + Iterator_Element => Element_Type, + Aggregate => (Empty => Empty, + Add_Unnamed => Append, + New_Indexed => New_Vector, + Assign_Indexed => Replace_Element); + + pragma Preelaborable_Initialization (Vector); + -- Vector type, to be instantiated by users of this package. If an object + -- of type Vector is not otherwise initialized, it is initialized to + -- Empty_Vector. + + type Cursor is private; + pragma Preelaborable_Initialization (Cursor); + -- Cursor pointing into an instance of vector. If an object of type Cursor + -- is not otherwise initialized, it is initialized to No_Element + + No_Element : constant Cursor; + -- No_Element represents a cursor that designates no element. + + function Has_Element (Position : Cursor) return Boolean; + -- Returns True if Position designates an element, and returns False + -- otherwise. + + package Vector_Iterator_Interfaces is new + Ada.Iterator_Interfaces (Cursor, Has_Element); + + Empty_Vector : constant Vector; + -- Empty_Vector represents the empty vector object. It has a length of 0. + + function Empty (Capacity : Count_Type := 10) return Vector; + + overriding function "=" (Left, Right : Vector) return Boolean; + -- If Left and Right denote the same vector object, then the function + -- returns True. If Left and Right have different lengths, then the + -- function returns False. Otherwise, it compares each element in Left to + -- the corresponding element in Right using the generic formal equality + -- operator. If any such comparison returns False, the function returns + -- False; otherwise it returns True. Any exception raised during evaluation + -- of element equality is propagated. + + function To_Vector (Length : Count_Type) return Vector; + -- Returns a vector with a length of Length, filled with empty elements. + + function To_Vector + (New_Item : Element_Type; + Length : Count_Type) return Vector; + -- Returns a vector with a length of Length, filled with elements + -- initialized to the value New_Item. + + function "&" (Left, Right : Vector) return Vector; + -- Returns a vector comprising the elements of Left followed by the + -- elements of Right. + + function "&" (Left : Vector; Right : Element_Type) return Vector; + -- Returns a vector comprising the elements of Left followed by the element + -- Right. + + function "&" (Left : Element_Type; Right : Vector) return Vector; + -- Returns a vector comprising the element Left followed by the elements of + -- Right. + + function "&" (Left, Right : Element_Type) return Vector; + -- Returns a vector comprising the element Left followed by the element + -- Right. + + function Capacity (Container : Vector) return Count_Type; + -- Returns the capacity of Container. + + procedure Reserve_Capacity + (Container : in out Vector; + Capacity : Count_Type); + -- Reserve_Capacity allocates new internal data structures such that the + -- length of the resulting vector can become at least the value Capacity + -- without requiring an additional call to Reserve_Capacity, and is large + -- enough to hold the current length of Container. Reserve_Capacity then + -- copies the elements into the new data structures and deallocates the old + -- data structures. Any exception raised during allocation is propagated + -- and Container is not modified. + + function Length (Container : Vector) return Count_Type; + -- Returns the number of elements in Container. + + procedure Set_Length + (Container : in out Vector; + Length : Count_Type); + -- If Length is larger than the capacity of Container, Set_Length calls + -- Reserve_Capacity (Container, Length), then sets the length of the + -- Container to Length. If Length is greater than the original length of + -- Container, empty elements are added to Container; otherwise elements are + -- removed from Container. + + function Is_Empty (Container : Vector) return Boolean; + -- Equivalent to Length (Container) = 0. + + procedure Clear (Container : in out Vector); + -- Removes all the elements from Container. The capacity of Container does + -- not change. + + function To_Cursor + (Container : Vector; + Index : Extended_Index) return Cursor; + -- If Index is not in the range First_Index (Container) .. Last_Index + -- (Container), then No_Element is returned. Otherwise, a cursor + -- designating the element at position Index in Container is returned. + + function To_Index (Position : Cursor) return Extended_Index; + -- If Position is No_Element, No_Index is returned. Otherwise, the index + -- (within its containing vector) of the element designated by Position is + -- returned. + + function Element + (Container : Vector; + Index : Index_Type) return Element_Type; + -- If Index is not in the range First_Index (Container) .. Last_Index + -- (Container), then Constraint_Error is propagated. Otherwise, Element + -- returns the element at position Index. + + function Element (Position : Cursor) return Element_Type; + -- If Position equals No_Element, then Constraint_Error is propagated. + -- Otherwise, Element returns the element designated by Position. + + procedure Replace_Element + (Container : in out Vector; + Index : Index_Type; + New_Item : Element_Type); + -- If Index is not in the range First_Index (Container) .. Last_Index + -- (Container), then Constraint_Error is propagated. Otherwise + -- Replace_Element assigns the value New_Item to the element at position + -- Index. Any exception raised during the assignment is propagated. The + -- element at position Index is not an empty element after successful call + -- to Replace_Element. + + procedure Replace_Element + (Container : in out Vector; + Position : Cursor; + New_Item : Element_Type); + -- If Position equals No_Element, then Constraint_Error is propagated; if + -- Position does not designate an element in Container, then Program_Error + -- is propagated. Otherwise Replace_Element assigns New_Item to the element + -- designated by Position. Any exception raised during the assignment is + -- propagated. The element at Position is not an empty element after + -- successful call to Replace_Element. + + procedure Query_Element + (Container : Vector; + Index : Index_Type; + Process : not null access procedure (Element : Element_Type)); + -- If Index is not in the range First_Index (Container) .. Last_Index + -- (Container), then Constraint_Error is propagated. Otherwise, + -- Query_Element calls Process.all with the element at position Index as + -- the argument. Program_Error is propagated if Process.all tampers with + -- the elements of Container. Any exception raised by Process.all is + -- propagated. + + procedure Query_Element + (Position : Cursor; + Process : not null access procedure (Element : Element_Type)); + -- If Position equals No_Element, then Constraint_Error is propagated. + -- Otherwise, Query_Element calls Process.all with the element designated + -- by Position as the argument. Program_Error is propagated if Process.all + -- tampers with the elements of Container. Any exception raised by + -- Process.all is propagated. + + procedure Update_Element + (Container : in out Vector; + Index : Index_Type; + Process : not null access procedure (Element : in out Element_Type)); + -- If Index is not in the range First_Index (Container) .. Last_Index + -- (Container), then Constraint_Error is propagated. Otherwise, + -- Update_Element calls Process.all with the element at position Index as + -- the argument. Program_Error is propagated if Process.all tampers with + -- the elements of Container. Any exception raised by Process.all is + -- propagated. + -- + -- If Element_Type is unconstrained and definite, then the actual Element + -- parameter of Process.all shall be unconstrained. + -- + -- The element at position Index is not an empty element after successful + -- completion of this operation. + + procedure Update_Element + (Container : in out Vector; + Position : Cursor; + Process : not null access procedure (Element : in out Element_Type)); + -- If Position equals No_Element, then Constraint_Error is propagated; if + -- Position does not designate an element in Container, then Program_Error + -- is propagated. Otherwise Update_Element calls Process.all with the + -- element designated by Position as the argument. Program_Error is + -- propagated if Process.all tampers with the elements of Container. Any + -- exception raised by Process.all is propagated. + -- + -- If Element_Type is unconstrained and definite, then the actual Element + -- parameter of Process.all shall be unconstrained. + -- + -- The element designated by Position is not an empty element after + -- successful completion of this operation. + + type Constant_Reference_Type + (Element : not null access constant Element_Type) is + private + with + Implicit_Dereference => Element; + + type Reference_Type (Element : not null access Element_Type) is private + with + Implicit_Dereference => Element; + + function Constant_Reference + (Container : aliased Vector; + Position : Cursor) return Constant_Reference_Type; + pragma Inline (Constant_Reference); + + function Reference + (Container : aliased in out Vector; + Position : Cursor) return Reference_Type; + pragma Inline (Reference); + + function Constant_Reference + (Container : aliased Vector; + Index : Index_Type) return Constant_Reference_Type; + pragma Inline (Constant_Reference); + + function Reference + (Container : aliased in out Vector; + Index : Index_Type) return Reference_Type; + pragma Inline (Reference); + + procedure Assign (Target : in out Vector; Source : Vector); + + function Copy (Source : Vector; Capacity : Count_Type := 0) return Vector; + + procedure Move (Target : in out Vector; Source : in out Vector); + -- If Target denotes the same object as Source, then Move has no effect. + -- Otherwise, Move first calls Clear (Target); then, each element from + -- Source is removed from Source and inserted into Target in the original + -- order. The length of Source is 0 after a successful call to Move. + + function New_Vector (First, Last : Index_Type) return Vector + with Pre => First = Index_Type'First; + -- Ada 2022 aggregate operation. + + procedure Insert_Vector + (Container : in out Vector; + Before : Extended_Index; + New_Item : Vector); + -- If Before is not in the range First_Index (Container) .. Last_Index + -- (Container) + 1, then Constraint_Error is propagated. If + -- Length(New_Item) is 0, then Insert_Vector does nothing. Otherwise, it + -- computes the new length NL as the sum of the current length and Length + -- (New_Item); if the value of Last appropriate for length NL would be + -- greater than Index_Type'Last then Constraint_Error is propagated. + -- + -- If the current vector capacity is less than NL, Reserve_Capacity + -- (Container, NL) is called to increase the vector capacity. Then + -- Insert_Vector slides the elements in the range Before .. Last_Index + -- (Container) up by Length(New_Item) positions, and then copies the + -- elements of New_Item to the positions starting at Before. Any exception + -- raised during the copying is propagated. + + procedure Insert + (Container : in out Vector; + Before : Extended_Index; + New_Item : Vector) renames Insert_Vector; + -- Retained for now for compatibility; AI12-0400 will remove this. + + procedure Insert_Vector + (Container : in out Vector; + Before : Cursor; + New_Item : Vector); + -- If Before is not No_Element, and does not designate an element in + -- Container, then Program_Error is propagated. Otherwise, if + -- Length(New_Item) is 0, then Insert_Vector does nothing. If Before is + -- No_Element, then the call is equivalent to Insert_Vector (Container, + -- Last_Index (Container) + 1, New_Item); otherwise the call is equivalent + -- to Insert_Vector (Container, To_Index (Before), New_Item); + + procedure Insert + (Container : in out Vector; + Before : Cursor; + New_Item : Vector) renames Insert_Vector; + -- Retained for now for compatibility; AI12-0400 will remove this. + + procedure Insert_Vector + (Container : in out Vector; + Before : Cursor; + New_Item : Vector; + Position : out Cursor); + -- If Before is not No_Element, and does not designate an element in + -- Container, then Program_Error is propagated. If Before equals + -- No_Element, then let T be Last_Index (Container) + 1; otherwise, let T + -- be To_Index (Before). Insert_Vector (Container, T, New_Item) is called, + -- and then Position is set to To_Cursor (Container, T). + + procedure Insert + (Container : in out Vector; + Before : Cursor; + New_Item : Vector; + Position : out Cursor) renames Insert_Vector; + -- Retained for now for compatibility; AI12-0400 will remove this. + + procedure Insert + (Container : in out Vector; + Before : Extended_Index; + New_Item : Element_Type; + Count : Count_Type := 1); + -- Equivalent to: + -- Insert_Vector (Container, Before, To_Vector (New_Item, Count)); + + procedure Insert + (Container : in out Vector; + Before : Cursor; + New_Item : Element_Type; + Count : Count_Type := 1); + -- Equivalent to: + -- Insert_Vector (Container, Before, To_Vector (New_Item, Count)); + + procedure Insert + (Container : in out Vector; + Before : Cursor; + New_Item : Element_Type; + Position : out Cursor; + Count : Count_Type := 1); + -- Equivalent to + -- Insert_Vector (Container, Before, To_Vector (New_Item, Count), Position) + + procedure Insert + (Container : in out Vector; + Before : Extended_Index; + Count : Count_Type := 1); + -- If Before is not in the range First_Index (Container) .. Last_Index + -- (Container) + 1, then Constraint_Error is propagated. If Count is 0, + -- then Insert does nothing. Otherwise, it computes the new length NL as + -- the sum of the current length and Count; if the value of Last + -- appropriate for length NL would be greater than Index_Type'Last then + -- Constraint_Error is propagated. + -- + -- If the current vector capacity is less than NL, Reserve_Capacity + -- (Container, NL) is called to increase the vector capacity. Then Insert + -- slides the elements in the range Before .. Last_Index (Container) up by + -- Count positions, and then inserts elements that are initialized by + -- default (see 3.3.1) in the positions starting at Before. + + procedure Insert + (Container : in out Vector; + Before : Cursor; + Position : out Cursor; + Count : Count_Type := 1); + -- If Before is not No_Element, and does not designate an element in + -- Container, then Program_Error is propagated. If Before equals + -- No_Element, then let T be Last_Index (Container) + 1; otherwise, let T + -- be To_Index (Before). Insert (Container, T, Count) is called, and then + -- Position is set to To_Cursor (Container, T). + + procedure Prepend_Vector + (Container : in out Vector; + New_Item : Vector); + -- Equivalent to Insert (Container, First_Index (Container), New_Item). + + procedure Prepend + (Container : in out Vector; + New_Item : Vector) renames Prepend_Vector; + -- Retained for now for compatibility; AI12-0400 will remove this. + + procedure Prepend + (Container : in out Vector; + New_Item : Element_Type; + Count : Count_Type := 1); + -- Equivalent to Insert (Container, First_Index (Container), New_Item, + -- Count). + + procedure Append_Vector + (Container : in out Vector; + New_Item : Vector); + -- Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item). + + procedure Append + (Container : in out Vector; + New_Item : Vector) renames Append_Vector; + -- Retained for now for compatibility; AI12-0400 will remove this. + + procedure Append + (Container : in out Vector; + New_Item : Element_Type; + Count : Count_Type); + -- Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item, + -- Count). + + procedure Append (Container : in out Vector; + New_Item : Element_Type); + + procedure Insert_Space + (Container : in out Vector; + Before : Extended_Index; + Count : Count_Type := 1); + -- If Before is not in the range First_Index (Container) .. Last_Index + -- (Container) + 1, then Constraint_Error is propagated. If Count is 0, + -- then Insert_Space does nothing. Otherwise, it computes the new length NL + -- as the sum of the current length and Count; if the value of Last + -- appropriate for length NL would be greater than Index_Type'Last then + -- Constraint_Error is propagated. + -- + -- If the current vector capacity is less than NL, Reserve_Capacity + -- (Container, NL) is called to increase the vector capacity. Then + -- Insert_Space slides the elements in the range Before .. Last_Index + -- (Container) up by Count positions, and then inserts empty elements in + -- the positions starting at Before. + + procedure Insert_Space + (Container : in out Vector; + Before : Cursor; + Position : out Cursor; + Count : Count_Type := 1); + -- If Before is not No_Element, and does not designate an element in + -- Container, then Program_Error is propagated. If Before equals + -- No_Element, then let T be Last_Index (Container) + 1; otherwise, let T + -- be To_Index (Before). Insert_Space (Container, T, Count) is called, and + -- then Position is set to To_Cursor (Container, T). + + procedure Delete + (Container : in out Vector; + Index : Extended_Index; + Count : Count_Type := 1); + -- If Index is not in the range First_Index (Container) .. Last_Index + -- (Container) + 1, then Constraint_Error is propagated. If Count is 0, + -- Delete has no effect. Otherwise Delete slides the elements (if any) + -- starting at position Index + Count down to Index. Any exception raised + -- during element assignment is propagated. + + procedure Delete + (Container : in out Vector; + Position : in out Cursor; + Count : Count_Type := 1); + -- If Position equals No_Element, then Constraint_Error is propagated. If + -- Position does not designate an element in Container, then Program_Error + -- is propagated. Otherwise, Delete (Container, To_Index (Position), Count) + -- is called, and then Position is set to No_Element. + + procedure Delete_First + (Container : in out Vector; + Count : Count_Type := 1); + -- Equivalent to Delete (Container, First_Index (Container), Count). + + procedure Delete_Last + (Container : in out Vector; + Count : Count_Type := 1); + -- If Length (Container) <= Count then Delete_Last is equivalent to Clear + -- (Container). Otherwise it is equivalent to Delete (Container, + -- Index_Type'Val(Index_Type'Pos(Last_Index (Container)) - Count + 1), + -- Count). + + procedure Reverse_Elements (Container : in out Vector); + -- Reorders the elements of Container in reverse order. + + procedure Swap (Container : in out Vector; I, J : Index_Type); + -- If either I or J is not in the range First_Index (Container) .. + -- Last_Index (Container), then Constraint_Error is propagated. Otherwise, + -- Swap exchanges the values of the elements at positions I and J. + + procedure Swap (Container : in out Vector; I, J : Cursor); + -- If either I or J is No_Element, then Constraint_Error is propagated. If + -- either I or J do not designate an element in Container, then + -- Program_Error is propagated. Otherwise, Swap exchanges the values of the + -- elements designated by I and J. + + function First_Index (Container : Vector) return Index_Type; + -- Returns the value Index_Type'First. + + function First (Container : Vector) return Cursor; + -- If Container is empty, First returns No_Element. Otherwise, it returns a + -- cursor that designates the first element in Container. + + function First_Element (Container : Vector) return Element_Type; + -- Equivalent to Element (Container, First_Index (Container)). + + function Last_Index (Container : Vector) return Extended_Index; + -- If Container is empty, Last_Index returns No_Index. Otherwise, it + -- returns the position of the last element in Container. + + function Last (Container : Vector) return Cursor; + -- If Container is empty, Last returns No_Element. Otherwise, it returns a + -- cursor that designates the last element in Container. + + function Last_Element (Container : Vector) return Element_Type; + -- Equivalent to Element (Container, Last_Index (Container)). + + function Next (Position : Cursor) return Cursor; + -- If Position equals No_Element or designates the last element of the + -- container, then Next returns the value No_Element. Otherwise, it returns + -- a cursor that designates the element with index To_Index (Position) + 1 + -- in the same vector as Position. + + procedure Next (Position : in out Cursor); + -- Equivalent to Position := Next (Position). + + function Previous (Position : Cursor) return Cursor; + -- If Position equals No_Element or designates the first element of the + -- container, then Previous returns the value No_Element. Otherwise, it + -- returns a cursor that designates the element with index To_Index + -- (Position) - 1 in the same vector as Position. + + procedure Previous (Position : in out Cursor); + -- Equivalent to Position := Previous (Position). + + function Find_Index + (Container : Vector; + Item : Element_Type; + Index : Index_Type := Index_Type'First) return Extended_Index; + -- Searches the elements of Container for an element equal to Item (using + -- the generic formal equality operator). The search starts at position + -- Index and proceeds towards Last_Index (Container). If no equal + -- element is found, then Find_Index returns No_Index. Otherwise, it + -- returns the index of the first equal element encountered. + + function Find + (Container : Vector; + Item : Element_Type; + Position : Cursor := No_Element) return Cursor; + -- If Position is not No_Element, and does not designate an element in + -- Container, then Program_Error is propagated. Otherwise Find searches + -- the elements of Container for an element equal to Item (using the + -- generic formal equality operator). The search starts at the first + -- element if Position equals No_Element, and at the element designated + -- by Position otherwise. It proceeds towards the last element of + -- Container. If no equal element is found, then Find returns + -- No_Element. Otherwise, it returns a cursor designating the first + -- equal element encountered. + + function Reverse_Find_Index + (Container : Vector; + Item : Element_Type; + Index : Index_Type := Index_Type'Last) return Extended_Index; + -- Searches the elements of Container for an element equal to Item (using + -- the generic formal equality operator). The search starts at position + -- Index or, if Index is greater than Last_Index (Container), at + -- position Last_Index (Container). It proceeds towards First_Index + -- (Container). If no equal element is found, then Reverse_Find_Index + -- returns No_Index. Otherwise, it returns the index of the first equal + -- element encountered. + + function Reverse_Find + (Container : Vector; + Item : Element_Type; + Position : Cursor := No_Element) return Cursor; + -- If Position is not No_Element, and does not designate an element in + -- Container, then Program_Error is propagated. Otherwise Reverse_Find + -- searches the elements of Container for an element equal to Item + -- (using the generic formal equality operator). The search starts at + -- the last element if Position equals No_Element, and at the element + -- designated by Position otherwise. It proceeds towards the first + -- element of Container. If no equal element is found, then Reverse_Find + -- returns No_Element. Otherwise, it returns a cursor designating the + -- first equal element encountered. + + function Contains + (Container : Vector; + Item : Element_Type) return Boolean; + -- Equivalent to Has_Element (Find (Container, Item)). + + procedure Iterate + (Container : Vector; + Process : not null access procedure (Position : Cursor)); + -- Invokes Process.all with a cursor that designates each element in + -- Container, in index order. Program_Error is propagated if Process.all + -- tampers with the cursors of Container. Any exception raised by Process + -- is propagated. + + procedure Reverse_Iterate + (Container : Vector; + Process : not null access procedure (Position : Cursor)); + -- Iterates over the elements in Container as per Iterate, except that + -- elements are traversed in reverse index order. + -- + + function Iterate (Container : Vector) + return Vector_Iterator_Interfaces.Reversible_Iterator'Class; + + function Iterate (Container : Vector; Start : Cursor) + return Vector_Iterator_Interfaces.Reversible_Iterator'Class; + + generic + with function "<" (Left, Right : Element_Type) return Boolean is <>; + -- The actual function for the generic formal function "<" of + -- Generic_Sorting is expected to return the same value each time it is + -- called with a particular pair of element values. It should define a + -- strict ordering relationship, that is, be irreflexive, asymmetric, + -- and transitive; it should not modify Container. If the actual for "<" + -- behaves in some other manner, the behavior of the subprograms of + -- Generic_Sorting are unspecified. How many times the subprograms of + -- Generic_Sorting call "<" is unspecified. + package Generic_Sorting is + + function Is_Sorted (Container : Vector) return Boolean; + -- Returns True if the elements are sorted smallest first as determined + -- by the generic formal "<" operator; otherwise, Is_Sorted returns + -- False. Any exception raised during evaluation of "<" is propagated. + + procedure Sort (Container : in out Vector); + -- Reorders the elements of Container such that the elements are sorted + -- smallest first as determined by the generic formal "<" operator + -- provided. Any exception raised during evaluation of "<" is + -- propagated. + + procedure Merge (Target : in out Vector; Source : in out Vector); + -- Merge removes elements from Source and inserts them into Target; + -- afterwards, Target contains the union of the elements that were + -- initially in Source and Target; Source is left empty. If Target and + -- Source are initially sorted smallest first, then Target is ordered + -- smallest first as determined by the generic formal "<" operator; + -- otherwise, the order of elements in Target is unspecified. Any + -- exception raised during evaluation of "<" is propagated. + + end Generic_Sorting; + +private + + pragma Inline (Append); + pragma Inline (First_Index); + pragma Inline (Last_Index); + pragma Inline (Element); + pragma Inline (First_Element); + pragma Inline (Last_Element); + pragma Inline (Query_Element); + pragma Inline (Update_Element); + pragma Inline (Replace_Element); + pragma Inline (Is_Empty); + pragma Inline (Contains); + pragma Inline (Next); + pragma Inline (Previous); + + use Ada.Containers.Helpers; + package Implementation is new Generic_Implementation; + use Implementation; + + type Elements_Array is array (Index_Type range <>) of aliased Element_Type; + function "=" (L, R : Elements_Array) return Boolean is abstract; + + type Elements_Type (Last : Extended_Index) is limited record + EA : Elements_Array (Index_Type'First .. Last); + end record; + + type Elements_Access is access all Elements_Type; + + use Finalization; + use Streams; + + type Vector is new Controlled with record + Elements : Elements_Access := null; + Last : Extended_Index := No_Index; + TC : aliased Tamper_Counts; + end record with Put_Image => Put_Image; + + procedure Put_Image + (S : in out Ada.Strings.Text_Buffers.Root_Buffer_Type'Class; V : Vector); + + overriding procedure Adjust (Container : in out Vector); + overriding procedure Finalize (Container : in out Vector); + + procedure Write + (Stream : not null access Root_Stream_Type'Class; + Container : Vector); + + for Vector'Write use Write; + + procedure Read + (Stream : not null access Root_Stream_Type'Class; + Container : out Vector); + + for Vector'Read use Read; + + type Vector_Access is access all Vector; + for Vector_Access'Storage_Size use 0; + + type Cursor is record + Container : Vector_Access; + Index : Index_Type := Index_Type'First; + end record; + + procedure Read + (Stream : not null access Root_Stream_Type'Class; + Position : out Cursor); + + for Cursor'Read use Read; + + procedure Write + (Stream : not null access Root_Stream_Type'Class; + Position : Cursor); + + for Cursor'Write use Write; + + subtype Reference_Control_Type is Implementation.Reference_Control_Type; + -- It is necessary to rename this here, so that the compiler can find it + + type Constant_Reference_Type + (Element : not null access constant Element_Type) is + record + Control : Reference_Control_Type := + raise Program_Error with "uninitialized reference"; + -- The RM says, "The default initialization of an object of + -- type Constant_Reference_Type or Reference_Type propagates + -- Program_Error." + end record; + + procedure Write + (Stream : not null access Root_Stream_Type'Class; + Item : Constant_Reference_Type); + + for Constant_Reference_Type'Write use Write; + + procedure Read + (Stream : not null access Root_Stream_Type'Class; + Item : out Constant_Reference_Type); + + for Constant_Reference_Type'Read use Read; + + type Reference_Type + (Element : not null access Element_Type) is + record + Control : Reference_Control_Type := + raise Program_Error with "uninitialized reference"; + -- The RM says, "The default initialization of an object of + -- type Constant_Reference_Type or Reference_Type propagates + -- Program_Error." + end record; + + procedure Write + (Stream : not null access Root_Stream_Type'Class; + Item : Reference_Type); + + for Reference_Type'Write use Write; + + procedure Read + (Stream : not null access Root_Stream_Type'Class; + Item : out Reference_Type); + + for Reference_Type'Read use Read; + + -- Three operations are used to optimize the expansion of "for ... of" + -- loops: the Next(Cursor) (or Previous) procedure in the visible part, + -- and the following Pseudo_Reference and Get_Element_Access functions. + -- See Exp_Ch5 for details, including the leading underscores here. + + procedure _Next (Position : in out Cursor) renames Next; + procedure _Previous (Position : in out Cursor) renames Previous; + + function Pseudo_Reference + (Container : aliased Vector'Class) return Reference_Control_Type; + pragma Inline (Pseudo_Reference); + -- Creates an object of type Reference_Control_Type pointing to the + -- container, and increments the Lock. Finalization of this object will + -- decrement the Lock. + + type Element_Access is access all Element_Type; + + function Get_Element_Access + (Position : Cursor) return not null Element_Access; + -- Returns a pointer to the element designated by Position. + + No_Element : constant Cursor := Cursor'(null, Index_Type'First); + + Empty_Vector : constant Vector := (Controlled with others => <>); + + type Iterator is new Limited_Controlled and + Vector_Iterator_Interfaces.Reversible_Iterator with + record + Container : Vector_Access; + Index : Index_Type'Base; + end record + with Disable_Controlled => not T_Check; + + overriding procedure Finalize (Object : in out Iterator); + + overriding function First (Object : Iterator) return Cursor; + overriding function Last (Object : Iterator) return Cursor; + + overriding function Next + (Object : Iterator; + Position : Cursor) return Cursor; + + overriding function Previous + (Object : Iterator; + Position : Cursor) return Cursor; + +end Ada.Containers.Vectors; diff --git a/testsuite/tests/361-overriden-runtime-specs/src/main.adb b/testsuite/tests/361-overriden-runtime-specs/src/main.adb new file mode 100644 index 000000000..93b1f559c --- /dev/null +++ b/testsuite/tests/361-overriden-runtime-specs/src/main.adb @@ -0,0 +1,11 @@ +with Ada.Containers.Vectors; + +procedure Main is + package Int_Vectors is new Ada.Containers.Vectors + (Index_Type => Natural, + Element_Type => Integer); + + V : Int_Vectors.Vector; +begin + V.Append (3); +end Main; diff --git a/testsuite/tests/361-overriden-runtime-specs/test.py b/testsuite/tests/361-overriden-runtime-specs/test.py new file mode 100644 index 000000000..cced46315 --- /dev/null +++ b/testsuite/tests/361-overriden-runtime-specs/test.py @@ -0,0 +1,48 @@ +""" +This test checks that we have no warning when instrumenting a project +that redefines some runtime files, here a-convec.ad[sb] +""" + +import re + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +wd = Wdir("tmp_") + +gpr = gprfor(mains=["main.adb"], srcdirs=["../src"]) + +build_and_run( + gprsw=GPRswitches( + root_project=gpr, + ), + mains=["main"], + covlevel="stmt", + extra_coverage_args=["-v"], + quiet=False, +) + +# Ensure `gnatcov instrument` did not confuse runtime files +warn_regexp = re.compile( + r".*Warning: same base name for files:\n.*a-convec\.ads\n.*a-convec\.ads.*", # noqa: E501 + flags=re.S, +) +thistest.fail_if_match( + "Warning found in instrumentation output, gnatcov used both overriden " + "and original runtime files", + warn_regexp, + contents_of("instrument.log"), +) + +# Ensure the overridden runtime file was used +# (i.e. calling Vector.Append prints Toto) +thistest.fail_if_no_match( + "call to Vector.Append shall print 'Toto'", + "Toto", + contents_of("main_output.txt"), +) + +thistest.result() From dc41aba76eb8fa0bb7143640970ddf21e172a4b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 8 Jan 2025 14:33:59 +0100 Subject: [PATCH 1073/1483] issue-361: Fix test for specific runtimes --- .../361-overriden-runtime-specs/extra.opt | 2 - .../src/a-convec.adb | 3366 ----------------- .../src/a-convec.ads | 878 ----- .../src/a-numaux.adb | 6 + .../src/a-numaux.ads | 8 + .../361-overriden-runtime-specs/src/main.adb | 10 +- .../361-overriden-runtime-specs/test.opt | 1 + .../tests/361-overriden-runtime-specs/test.py | 31 +- 8 files changed, 31 insertions(+), 4271 deletions(-) delete mode 100644 testsuite/tests/361-overriden-runtime-specs/extra.opt delete mode 100644 testsuite/tests/361-overriden-runtime-specs/src/a-convec.adb delete mode 100644 testsuite/tests/361-overriden-runtime-specs/src/a-convec.ads create mode 100644 testsuite/tests/361-overriden-runtime-specs/src/a-numaux.adb create mode 100644 testsuite/tests/361-overriden-runtime-specs/src/a-numaux.ads create mode 100644 testsuite/tests/361-overriden-runtime-specs/test.opt diff --git a/testsuite/tests/361-overriden-runtime-specs/extra.opt b/testsuite/tests/361-overriden-runtime-specs/extra.opt deleted file mode 100644 index ac2346ab7..000000000 --- a/testsuite/tests/361-overriden-runtime-specs/extra.opt +++ /dev/null @@ -1,2 +0,0 @@ -5.04a1 DEAD 5.04a1 can't compile our custom runtime file, as it is too recent -bin-traces DEAD GPRbuild will fail to compile this project on a leon3 target diff --git a/testsuite/tests/361-overriden-runtime-specs/src/a-convec.adb b/testsuite/tests/361-overriden-runtime-specs/src/a-convec.adb deleted file mode 100644 index 429a1b6f7..000000000 --- a/testsuite/tests/361-overriden-runtime-specs/src/a-convec.adb +++ /dev/null @@ -1,3366 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT LIBRARY COMPONENTS -- --- -- --- A D A . C O N T A I N E R S . V E C T O R S -- --- -- --- B o d y -- --- -- --- Copyright (C) 2004-2024, 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- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- This unit was originally developed by Matthew J Heaney. -- ------------------------------------------------------------------------------- - -with Ada.Containers.Generic_Array_Sort; -with Ada.Unchecked_Deallocation; - -with Ada.Text_IO; - -with System; use type System.Address; -with System.Put_Images; - -package body Ada.Containers.Vectors with - SPARK_Mode => Off -is - - pragma Warnings (Off, "variable ""Busy*"" is not referenced"); - pragma Warnings (Off, "variable ""Lock*"" is not referenced"); - -- See comment in Ada.Containers.Helpers - - procedure Free is - new Ada.Unchecked_Deallocation (Elements_Type, Elements_Access); - - procedure Append_Slow_Path - (Container : in out Vector; - New_Item : Element_Type; - Count : Count_Type); - -- This is the slow path for Append. This is split out to minimize the size - -- of Append, because we have Inline (Append). - - --------- - -- "&" -- - --------- - - -- We decide that the capacity of the result of "&" is the minimum needed - -- -- the sum of the lengths of the vector parameters. We could decide to - -- make it larger, but we have no basis for knowing how much larger, so we - -- just allocate the minimum amount of storage. - - function "&" (Left, Right : Vector) return Vector is - begin - return Result : Vector do - Reserve_Capacity (Result, Length (Left) + Length (Right)); - Append_Vector (Result, Left); - Append_Vector (Result, Right); - end return; - end "&"; - - function "&" (Left : Vector; Right : Element_Type) return Vector is - begin - return Result : Vector do - Reserve_Capacity (Result, Length (Left) + 1); - Append_Vector (Result, Left); - Append (Result, Right); - end return; - end "&"; - - function "&" (Left : Element_Type; Right : Vector) return Vector is - begin - return Result : Vector do - Reserve_Capacity (Result, 1 + Length (Right)); - Append (Result, Left); - Append_Vector (Result, Right); - end return; - end "&"; - - function "&" (Left, Right : Element_Type) return Vector is - begin - return Result : Vector do - Reserve_Capacity (Result, 1 + 1); - Append (Result, Left); - Append (Result, Right); - end return; - end "&"; - - --------- - -- "=" -- - --------- - - overriding function "=" (Left, Right : Vector) return Boolean is - begin - if Left.Last /= Right.Last then - return False; - end if; - - if Left.Length = 0 then - return True; - end if; - - declare - -- Per AI05-0022, the container implementation is required to detect - -- element tampering by a generic actual subprogram. - - Lock_Left : With_Lock (Left.TC'Unrestricted_Access); - Lock_Right : With_Lock (Right.TC'Unrestricted_Access); - begin - for J in Index_Type range Index_Type'First .. Left.Last loop - if Left.Elements.EA (J) /= Right.Elements.EA (J) then - return False; - end if; - end loop; - end; - - return True; - end "="; - - ------------ - -- Adjust -- - ------------ - - procedure Adjust (Container : in out Vector) is - begin - -- If the counts are nonzero, execution is technically erroneous, but - -- it seems friendly to allow things like concurrent "=" on shared - -- constants. - - Zero_Counts (Container.TC); - - if Container.Last = No_Index then - Container.Elements := null; - return; - end if; - - declare - L : constant Index_Type := Container.Last; - EA : Elements_Array renames - Container.Elements.EA (Index_Type'First .. L); - - begin - Container.Elements := null; - - -- Note: it may seem that the following assignment to Container.Last - -- is useless, since we assign it to L below. However this code is - -- used in case 'new Elements_Type' below raises an exception, to - -- keep Container in a consistent state. - - Container.Last := No_Index; - Container.Elements := new Elements_Type'(L, EA); - Container.Last := L; - end; - end Adjust; - - ------------ - -- Append -- - ------------ - - procedure Append - (Container : in out Vector; - New_Item : Element_Type; - Count : Count_Type) - is - begin - -- In the general case, we take the slow path; for efficiency, - -- we check for the common case where Count = 1 . - - if Count = 1 then - Append (Container, New_Item); - else - Append_Slow_Path (Container, New_Item, Count); - end if; - end Append; - - ------------------- - -- Append_Vector -- - ------------------- - - procedure Append_Vector (Container : in out Vector; New_Item : Vector) is - begin - if Is_Empty (New_Item) then - return; - elsif Checks and then Container.Last = Index_Type'Last then - raise Constraint_Error with "vector is already at its maximum length"; - else - Insert_Vector (Container, Container.Last + 1, New_Item); - end if; - end Append_Vector; - - ------------ - -- Append -- - ------------ - - function Toto (V : Vector) return Vector; - function Toto (V : Vector) return Vector is - begin - Ada.Text_IO.Put_Line ("Toto"); - return V; - end Toto; - - procedure Append (Container : in out Vector; - New_Item : Element_Type) - is - begin - -- For performance, check for the common special case where the - -- container already has room for at least one more element. - -- In the general case, pass the buck to Insert. - - Container := Toto (Container); - - if Container.Elements /= null - and then Container.Last /= Container.Elements.Last - then - TC_Check (Container.TC); - - -- Increment Container.Last after assigning the New_Item, so we - -- leave the Container unmodified in case Finalize/Adjust raises - -- an exception. - - declare - New_Last : constant Index_Type := Container.Last + 1; - begin - Container.Elements.EA (New_Last) := New_Item; - Container.Last := New_Last; - end; - else - Insert (Container, Last_Index (Container) + 1, New_Item, 1); - end if; - end Append; - - ---------------------- - -- Append_Slow_Path -- - ---------------------- - - procedure Append_Slow_Path - (Container : in out Vector; - New_Item : Element_Type; - Count : Count_Type) - is - begin - if Count = 0 then - return; - elsif Checks and then Container.Last = Index_Type'Last then - raise Constraint_Error with "vector is already at its maximum length"; - else - Insert (Container, Container.Last + 1, New_Item, Count); - end if; - end Append_Slow_Path; - - ------------ - -- Assign -- - ------------ - - procedure Assign (Target : in out Vector; Source : Vector) is - begin - if Target'Address = Source'Address then - return; - else - Target.Clear; - Target.Append_Vector (Source); - end if; - end Assign; - - -------------- - -- Capacity -- - -------------- - - function Capacity (Container : Vector) return Count_Type is - begin - if Container.Elements = null then - return 0; - else - return Container.Elements.EA'Length; - end if; - end Capacity; - - ----------- - -- Clear -- - ----------- - - procedure Clear (Container : in out Vector) is - begin - TC_Check (Container.TC); - Container.Last := No_Index; - end Clear; - - ------------------------ - -- Constant_Reference -- - ------------------------ - - function Constant_Reference - (Container : aliased Vector; - Position : Cursor) return Constant_Reference_Type - is - begin - if Checks then - if Position.Container = null then - raise Constraint_Error with "Position cursor has no element"; - end if; - - if Position.Container /= Container'Unrestricted_Access then - raise Program_Error with "Position cursor denotes wrong container"; - end if; - - if Position.Index > Position.Container.Last then - raise Constraint_Error with "Position cursor is out of range"; - end if; - end if; - - declare - TC : constant Tamper_Counts_Access := - Container.TC'Unrestricted_Access; - begin - return R : constant Constant_Reference_Type := - (Element => Container.Elements.EA (Position.Index)'Access, - Control => (Controlled with TC)) - do - Busy (TC.all); - end return; - end; - end Constant_Reference; - - function Constant_Reference - (Container : aliased Vector; - Index : Index_Type) return Constant_Reference_Type - is - begin - if Checks and then Index > Container.Last then - raise Constraint_Error with "Index is out of range"; - end if; - - declare - TC : constant Tamper_Counts_Access := - Container.TC'Unrestricted_Access; - begin - return R : constant Constant_Reference_Type := - (Element => Container.Elements.EA (Index)'Access, - Control => (Controlled with TC)) - do - Busy (TC.all); - end return; - end; - end Constant_Reference; - - -------------- - -- Contains -- - -------------- - - function Contains - (Container : Vector; - Item : Element_Type) return Boolean - is - begin - return Find_Index (Container, Item) /= No_Index; - end Contains; - - ---------- - -- Copy -- - ---------- - - function Copy - (Source : Vector; - Capacity : Count_Type := 0) return Vector - is - C : Count_Type; - - begin - if Capacity >= Source.Length then - C := Capacity; - - else - C := Source.Length; - - if Checks and then Capacity /= 0 then - raise Capacity_Error with - "Requested capacity is less than Source length"; - end if; - end if; - - return Target : Vector do - Target.Reserve_Capacity (C); - Target.Assign (Source); - end return; - end Copy; - - ------------ - -- Delete -- - ------------ - - procedure Delete - (Container : in out Vector; - Index : Extended_Index; - Count : Count_Type := 1) - is - Old_Last : constant Index_Type'Base := Container.Last; - New_Last : Index_Type'Base; - Count2 : Count_Type'Base; -- count of items from Index to Old_Last - J : Index_Type'Base; -- first index of items that slide down - - begin - -- The tampering bits exist to prevent an item from being deleted (or - -- otherwise harmfully manipulated) while it is being visited. Query, - -- Update, and Iterate increment the busy count on entry, and decrement - -- the count on exit. Delete checks the count to determine whether it is - -- being called while the associated callback procedure is executing. - - TC_Check (Container.TC); - - -- Delete removes items from the vector, the number of which is the - -- minimum of the specified Count and the items (if any) that exist from - -- Index to Container.Last. There are no constraints on the specified - -- value of Count (it can be larger than what's available at this - -- position in the vector, for example), but there are constraints on - -- the allowed values of the Index. - - -- As a precondition on the generic actual Index_Type, the base type - -- must include Index_Type'Pred (Index_Type'First); this is the value - -- that Container.Last assumes when the vector is empty. However, we do - -- not allow that as the value for Index when specifying which items - -- should be deleted, so we must manually check. (That the user is - -- allowed to specify the value at all here is a consequence of the - -- declaration of the Extended_Index subtype, which includes the values - -- in the base range that immediately precede and immediately follow the - -- values in the Index_Type.) - - if Checks and then Index < Index_Type'First then - raise Constraint_Error with "Index is out of range (too small)"; - end if; - - -- We do allow a value greater than Container.Last to be specified as - -- the Index, but only if it's immediately greater. This allows the - -- corner case of deleting no items from the back end of the vector to - -- be treated as a no-op. (It is assumed that specifying an index value - -- greater than Last + 1 indicates some deeper flaw in the caller's - -- algorithm, so that case is treated as a proper error.) - - if Index > Old_Last then - if Checks and then Index > Old_Last + 1 then - raise Constraint_Error with "Index is out of range (too large)"; - else - return; - end if; - end if; - - -- Here and elsewhere we treat deleting 0 items from the container as a - -- no-op, even when the container is busy, so we simply return. - - if Count = 0 then - return; - end if; - - -- We first calculate what's available for deletion starting at - -- Index. Here and elsewhere we use the wider of Index_Type'Base and - -- Count_Type'Base as the type for intermediate values. (See function - -- Length for more information.) - - if Count_Type'Base'Last >= Index_Type'Pos (Index_Type'Base'Last) then - Count2 := Count_Type'Base (Old_Last) - Count_Type'Base (Index) + 1; - else - Count2 := Count_Type'Base (Old_Last - Index + 1); - end if; - - -- If more elements are requested (Count) for deletion than are - -- available (Count2) for deletion beginning at Index, then everything - -- from Index is deleted. There are no elements to slide down, and so - -- all we need to do is set the value of Container.Last. - - if Count >= Count2 then - Container.Last := Index - 1; - return; - end if; - - -- There are some elements that aren't being deleted (the requested - -- count was less than the available count), so we must slide them down - -- to Index. We first calculate the index values of the respective array - -- slices, using the wider of Index_Type'Base and Count_Type'Base as the - -- type for intermediate calculations. For the elements that slide down, - -- index value New_Last is the last index value of their new home, and - -- index value J is the first index of their old home. - - if Index_Type'Base'Last >= Count_Type_Last then - New_Last := Old_Last - Index_Type'Base (Count); - J := Index + Index_Type'Base (Count); - else - New_Last := Index_Type'Base (Count_Type'Base (Old_Last) - Count); - J := Index_Type'Base (Count_Type'Base (Index) + Count); - end if; - - -- The internal elements array isn't guaranteed to exist unless we have - -- elements, but we have that guarantee here because we know we have - -- elements to slide. The array index values for each slice have - -- already been determined, so we just slide down to Index the elements - -- that weren't deleted. - - declare - EA : Elements_Array renames Container.Elements.EA; - begin - EA (Index .. New_Last) := EA (J .. Old_Last); - Container.Last := New_Last; - end; - end Delete; - - procedure Delete - (Container : in out Vector; - Position : in out Cursor; - Count : Count_Type := 1) - is - begin - if Checks then - if Position.Container = null then - raise Constraint_Error with "Position cursor has no element"; - - elsif Position.Container /= Container'Unrestricted_Access then - raise Program_Error with "Position cursor denotes wrong container"; - - elsif Position.Index > Container.Last then - raise Program_Error with "Position index is out of range"; - end if; - end if; - - Delete (Container, Position.Index, Count); - Position := No_Element; - end Delete; - - ------------------ - -- Delete_First -- - ------------------ - - procedure Delete_First - (Container : in out Vector; - Count : Count_Type := 1) - is - begin - if Count = 0 then - return; - - elsif Count >= Length (Container) then - Clear (Container); - return; - - else - Delete (Container, Index_Type'First, Count); - end if; - end Delete_First; - - ----------------- - -- Delete_Last -- - ----------------- - - procedure Delete_Last - (Container : in out Vector; - Count : Count_Type := 1) - is - begin - -- It is not permitted to delete items while the container is busy (for - -- example, we're in the middle of a passive iteration). However, we - -- always treat deleting 0 items as a no-op, even when we're busy, so we - -- simply return without checking. - - if Count = 0 then - return; - end if; - - -- The tampering bits exist to prevent an item from being deleted (or - -- otherwise harmfully manipulated) while it is being visited. Query, - -- Update, and Iterate increment the busy count on entry, and decrement - -- the count on exit. Delete_Last checks the count to determine whether - -- it is being called while the associated callback procedure is - -- executing. - - TC_Check (Container.TC); - - -- There is no restriction on how large Count can be when deleting - -- items. If it is equal or greater than the current length, then this - -- is equivalent to clearing the vector. (In particular, there's no need - -- for us to actually calculate the new value for Last.) - - -- If the requested count is less than the current length, then we must - -- calculate the new value for Last. For the type we use the widest of - -- Index_Type'Base and Count_Type'Base for the intermediate values of - -- our calculation. (See the comments in Length for more information.) - - if Count >= Container.Length then - Container.Last := No_Index; - - elsif Index_Type'Base'Last >= Count_Type_Last then - Container.Last := Container.Last - Index_Type'Base (Count); - - else - Container.Last := - Index_Type'Base (Count_Type'Base (Container.Last) - Count); - end if; - end Delete_Last; - - ------------- - -- Element -- - ------------- - - function Element - (Container : Vector; - Index : Index_Type) return Element_Type - is - begin - if Checks and then Index > Container.Last then - raise Constraint_Error with "Index is out of range"; - end if; - - return Container.Elements.EA (Index); - end Element; - - function Element (Position : Cursor) return Element_Type is - begin - if Checks then - if Position.Container = null then - raise Constraint_Error with "Position cursor has no element"; - elsif Position.Index > Position.Container.Last then - raise Constraint_Error with "Position cursor is out of range"; - end if; - end if; - - return Position.Container.Elements.EA (Position.Index); - end Element; - - ----------- - -- Empty -- - ----------- - - function Empty (Capacity : Count_Type := 10) return Vector is - begin - return Result : Vector do - Reserve_Capacity (Result, Capacity); - end return; - end Empty; - - -------------- - -- Finalize -- - -------------- - - procedure Finalize (Container : in out Vector) is - X : Elements_Access := Container.Elements; - - begin - Container.Elements := null; - Container.Last := No_Index; - - Free (X); - - TC_Check (Container.TC); - end Finalize; - - procedure Finalize (Object : in out Iterator) is - begin - Unbusy (Object.Container.TC); - end Finalize; - - ---------- - -- Find -- - ---------- - - function Find - (Container : Vector; - Item : Element_Type; - Position : Cursor := No_Element) return Cursor - is - begin - if Checks and then Position.Container /= null then - if Position.Container /= Container'Unrestricted_Access then - raise Program_Error with "Position cursor denotes wrong container"; - end if; - - if Position.Index > Container.Last then - raise Program_Error with "Position index is out of range"; - end if; - end if; - - -- Per AI05-0022, the container implementation is required to detect - -- element tampering by a generic actual subprogram. - - declare - Lock : With_Lock (Container.TC'Unrestricted_Access); - begin - for J in Position.Index .. Container.Last loop - if Container.Elements.EA (J) = Item then - return Cursor'(Container'Unrestricted_Access, J); - end if; - end loop; - - return No_Element; - end; - end Find; - - ---------------- - -- Find_Index -- - ---------------- - - function Find_Index - (Container : Vector; - Item : Element_Type; - Index : Index_Type := Index_Type'First) return Extended_Index - is - -- Per AI05-0022, the container implementation is required to detect - -- element tampering by a generic actual subprogram. - - Lock : With_Lock (Container.TC'Unrestricted_Access); - begin - for Indx in Index .. Container.Last loop - if Container.Elements.EA (Indx) = Item then - return Indx; - end if; - end loop; - - return No_Index; - end Find_Index; - - ----------- - -- First -- - ----------- - - function First (Container : Vector) return Cursor is - begin - if Is_Empty (Container) then - return No_Element; - end if; - - return (Container'Unrestricted_Access, Index_Type'First); - end First; - - function First (Object : Iterator) return Cursor is - begin - -- The value of the iterator object's Index component influences the - -- behavior of the First (and Last) selector function. - - -- When the Index component is No_Index, this means the iterator - -- object was constructed without a start expression, in which case the - -- (forward) iteration starts from the (logical) beginning of the entire - -- sequence of items (corresponding to Container.First, for a forward - -- iterator). - - -- Otherwise, this is iteration over a partial sequence of items. - -- When the Index component isn't No_Index, the iterator object was - -- constructed with a start expression, that specifies the position - -- from which the (forward) partial iteration begins. - - if Object.Index = No_Index then - return First (Object.Container.all); - else - return Cursor'(Object.Container, Object.Index); - end if; - end First; - - ------------------- - -- First_Element -- - ------------------- - - function First_Element (Container : Vector) return Element_Type is - begin - if Checks and then Container.Last = No_Index then - raise Constraint_Error with "Container is empty"; - else - return Container.Elements.EA (Index_Type'First); - end if; - end First_Element; - - ----------------- - -- First_Index -- - ----------------- - - function First_Index (Container : Vector) return Index_Type is - pragma Unreferenced (Container); - begin - return Index_Type'First; - end First_Index; - - ----------------- - -- New_Vector -- - ----------------- - - function New_Vector (First, Last : Index_Type) return Vector - is - begin - return (To_Vector (Count_Type (Last - First + 1))); - end New_Vector; - - --------------------- - -- Generic_Sorting -- - --------------------- - - package body Generic_Sorting is - - --------------- - -- Is_Sorted -- - --------------- - - function Is_Sorted (Container : Vector) return Boolean is - begin - if Container.Last <= Index_Type'First then - return True; - end if; - - -- Per AI05-0022, the container implementation is required to detect - -- element tampering by a generic actual subprogram. - - declare - Lock : With_Lock (Container.TC'Unrestricted_Access); - EA : Elements_Array renames Container.Elements.EA; - begin - for J in Index_Type'First .. Container.Last - 1 loop - if EA (J + 1) < EA (J) then - return False; - end if; - end loop; - - return True; - end; - end Is_Sorted; - - ----------- - -- Merge -- - ----------- - - procedure Merge (Target, Source : in out Vector) is - I : Index_Type'Base := Target.Last; - J : Index_Type'Base; - - begin - TC_Check (Source.TC); - - -- The semantics of Merge changed slightly per AI05-0021. It was - -- originally the case that if Target and Source denoted the same - -- container object, then the GNAT implementation of Merge did - -- nothing. However, it was argued that RM05 did not precisely - -- specify the semantics for this corner case. The decision of the - -- ARG was that if Target and Source denote the same non-empty - -- container object, then Program_Error is raised. - - if Source.Last < Index_Type'First then -- Source is empty - return; - end if; - - if Checks and then Target'Address = Source'Address then - raise Program_Error with - "Target and Source denote same non-empty container"; - end if; - - if Target.Last < Index_Type'First then -- Target is empty - Move (Target => Target, Source => Source); - return; - end if; - - Target.Set_Length (Length (Target) + Length (Source)); - - -- Per AI05-0022, the container implementation is required to detect - -- element tampering by a generic actual subprogram. - - declare - TA : Elements_Array renames Target.Elements.EA; - SA : Elements_Array renames Source.Elements.EA; - - Lock_Target : With_Lock (Target.TC'Unchecked_Access); - Lock_Source : With_Lock (Source.TC'Unchecked_Access); - begin - J := Target.Last; - while Source.Last >= Index_Type'First loop - pragma Assert (Source.Last <= Index_Type'First - or else not (SA (Source.Last) < - SA (Source.Last - 1))); - - if I < Index_Type'First then - TA (Index_Type'First .. J) := - SA (Index_Type'First .. Source.Last); - - Source.Last := No_Index; - exit; - end if; - - pragma Assert (I <= Index_Type'First - or else not (TA (I) < TA (I - 1))); - - if SA (Source.Last) < TA (I) then - TA (J) := TA (I); - I := I - 1; - - else - TA (J) := SA (Source.Last); - Source.Last := Source.Last - 1; - end if; - - J := J - 1; - end loop; - end; - end Merge; - - ---------- - -- Sort -- - ---------- - - procedure Sort (Container : in out Vector) is - procedure Sort is - new Generic_Array_Sort - (Index_Type => Index_Type, - Element_Type => Element_Type, - Array_Type => Elements_Array, - "<" => "<"); - - begin - -- The exception behavior for the vector container must match that - -- for the list container, so we check for cursor tampering here - -- (which will catch more things) instead of for element tampering - -- (which will catch fewer things). It's true that the elements of - -- this vector container could be safely moved around while (say) an - -- iteration is taking place (iteration only increments the busy - -- counter), and so technically all we would need here is a test for - -- element tampering (indicated by the lock counter), that's simply - -- an artifact of our array-based implementation. Logically Sort - -- requires a check for cursor tampering. - - TC_Check (Container.TC); - - if Container.Last <= Index_Type'First then - return; - end if; - - -- Per AI05-0022, the container implementation is required to detect - -- element tampering by a generic actual subprogram. - - declare - Lock : With_Lock (Container.TC'Unchecked_Access); - begin - Sort (Container.Elements.EA (Index_Type'First .. Container.Last)); - end; - end Sort; - - end Generic_Sorting; - - ------------------------ - -- Get_Element_Access -- - ------------------------ - - function Get_Element_Access - (Position : Cursor) return not null Element_Access is - begin - return Position.Container.Elements.EA (Position.Index)'Access; - end Get_Element_Access; - - ----------------- - -- Has_Element -- - ----------------- - - function Has_Element (Position : Cursor) return Boolean is - begin - return Position /= No_Element; - end Has_Element; - - ------------ - -- Insert -- - ------------ - - procedure Insert - (Container : in out Vector; - Before : Extended_Index; - New_Item : Element_Type; - Count : Count_Type := 1) - is - Old_Length : constant Count_Type := Container.Length; - - Max_Length : Count_Type'Base; -- determined from range of Index_Type - New_Length : Count_Type'Base; -- sum of current length and Count - New_Last : Index_Type'Base; -- last index of vector after insertion - - Index : Index_Type'Base; -- scratch for intermediate values - J : Count_Type'Base; -- scratch - - New_Capacity : Count_Type'Base; -- length of new, expanded array - Dst_Last : Index_Type'Base; -- last index of new, expanded array - Dst : Elements_Access; -- new, expanded internal array - - begin - -- The tampering bits exist to prevent an item from being harmfully - -- manipulated while it is being visited. Query, Update, and Iterate - -- increment the busy count on entry, and decrement the count on - -- exit. Insert checks the count to determine whether it is being called - -- while the associated callback procedure is executing. - - TC_Check (Container.TC); - - if Checks then - -- As a precondition on the generic actual Index_Type, the base type - -- must include Index_Type'Pred (Index_Type'First); this is the value - -- that Container.Last assumes when the vector is empty. However, we - -- do not allow that as the value for Index when specifying where the - -- new items should be inserted, so we must manually check. (That the - -- user is allowed to specify the value at all here is a consequence - -- of the declaration of the Extended_Index subtype, which includes - -- the values in the base range that immediately precede and - -- immediately follow the values in the Index_Type.) - - if Before < Index_Type'First then - raise Constraint_Error with - "Before index is out of range (too small)"; - end if; - - -- We do allow a value greater than Container.Last to be specified as - -- the Index, but only if it's immediately greater. This allows for - -- the case of appending items to the back end of the vector. (It is - -- assumed that specifying an index value greater than Last + 1 - -- indicates some deeper flaw in the caller's algorithm, so that case - -- is treated as a proper error.) - - if Before > Container.Last + 1 then - raise Constraint_Error with - "Before index is out of range (too large)"; - end if; - end if; - - -- We treat inserting 0 items into the container as a no-op, even when - -- the container is busy, so we simply return. - - if Count = 0 then - return; - end if; - - -- There are two constraints we need to satisfy. The first constraint is - -- that a container cannot have more than Count_Type'Last elements, so - -- we must check the sum of the current length and the insertion count. - -- Note: we cannot simply add these values, because of the possibility - -- of overflow. - - if Checks and then Old_Length > Count_Type'Last - Count then - raise Constraint_Error with "Count is out of range"; - end if; - - -- It is now safe compute the length of the new vector, without fear of - -- overflow. - - New_Length := Old_Length + Count; - - -- The second constraint is that the new Last index value cannot exceed - -- Index_Type'Last. In each branch below, we calculate the maximum - -- length (computed from the range of values in Index_Type), and then - -- compare the new length to the maximum length. If the new length is - -- acceptable, then we compute the new last index from that. - - if Index_Type'Base'Last >= Count_Type_Last then - - -- We have to handle the case when there might be more values in the - -- range of Index_Type than in the range of Count_Type. - - if Index_Type'First <= 0 then - - -- We know that No_Index (the same as Index_Type'First - 1) is - -- less than 0, so it is safe to compute the following sum without - -- fear of overflow. We need to suppress warnings, because - -- otherwise we get an error in -gnatwE mode. - - pragma Warnings (Off); - Index := No_Index + Index_Type'Base (Count_Type'Last); - pragma Warnings (On); - - if Index <= Index_Type'Last then - - -- We have determined that range of Index_Type has at least as - -- many values as in Count_Type, so Count_Type'Last is the - -- maximum number of items that are allowed. - - Max_Length := Count_Type'Last; - - else - -- The range of Index_Type has fewer values than in Count_Type, - -- so the maximum number of items is computed from the range of - -- the Index_Type. - - Max_Length := Count_Type'Base (Index_Type'Last - No_Index); - end if; - - else - -- No_Index is equal or greater than 0, so we can safely compute - -- the difference without fear of overflow (which we would have to - -- worry about if No_Index were less than 0, but that case is - -- handled above). - - if Index_Type'Last - No_Index >= Count_Type_Last then - -- We have determined that range of Index_Type has at least as - -- many values as in Count_Type, so Count_Type'Last is the - -- maximum number of items that are allowed. - - Max_Length := Count_Type'Last; - - else - -- The range of Index_Type has fewer values than in Count_Type, - -- so the maximum number of items is computed from the range of - -- the Index_Type. - - Max_Length := Count_Type'Base (Index_Type'Last - No_Index); - end if; - end if; - - elsif Index_Type'First <= 0 then - - -- We know that No_Index (the same as Index_Type'First - 1) is less - -- than 0, so it is safe to compute the following sum without fear of - -- overflow. - - J := Count_Type'Base (No_Index) + Count_Type'Last; - - if J <= Count_Type'Base (Index_Type'Last) then - - -- We have determined that range of Index_Type has at least as - -- many values as in Count_Type, so Count_Type'Last is the maximum - -- number of items that are allowed. - - Max_Length := Count_Type'Last; - - else - -- The range of Index_Type has fewer values than Count_Type does, - -- so the maximum number of items is computed from the range of - -- the Index_Type. - - Max_Length := - Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index); - end if; - - else - -- No_Index is equal or greater than 0, so we can safely compute the - -- difference without fear of overflow (which we would have to worry - -- about if No_Index were less than 0, but that case is handled - -- above). - - Max_Length := - Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index); - end if; - - -- We have just computed the maximum length (number of items). We must - -- now compare the requested length to the maximum length, as we do not - -- allow a vector expand beyond the maximum (because that would create - -- an internal array with a last index value greater than - -- Index_Type'Last, with no way to index those elements). - - if Checks and then New_Length > Max_Length then - raise Constraint_Error with "Count is out of range"; - end if; - - -- New_Last is the last index value of the items in the container after - -- insertion. Use the wider of Index_Type'Base and Count_Type'Base to - -- compute its value from the New_Length. - - if Index_Type'Base'Last >= Count_Type_Last then - New_Last := No_Index + Index_Type'Base (New_Length); - else - New_Last := Index_Type'Base (Count_Type'Base (No_Index) + New_Length); - end if; - - if Container.Elements = null then - pragma Assert (Container.Last = No_Index); - - -- This is the simplest case, with which we must always begin: we're - -- inserting items into an empty vector that hasn't allocated an - -- internal array yet. Note that we don't need to check the busy bit - -- here, because an empty container cannot be busy. - - -- In order to preserve container invariants, we allocate the new - -- internal array first, before setting the Last index value, in case - -- the allocation fails (which can happen either because there is no - -- storage available, or because element initialization fails). - - Container.Elements := new Elements_Type' - (Last => New_Last, - EA => [others => New_Item]); - - -- The allocation of the new, internal array succeeded, so it is now - -- safe to update the Last index, restoring container invariants. - - Container.Last := New_Last; - - return; - end if; - - -- An internal array has already been allocated, so we must determine - -- whether there is enough unused storage for the new items. - - if New_Length <= Container.Elements.EA'Length then - - -- In this case, we're inserting elements into a vector that has - -- already allocated an internal array, and the existing array has - -- enough unused storage for the new items. - - declare - EA : Elements_Array renames Container.Elements.EA; - - begin - if Before > Container.Last then - - -- The new items are being appended to the vector, so no - -- sliding of existing elements is required. - - EA (Before .. New_Last) := [others => New_Item]; - - else - -- The new items are being inserted before some existing - -- elements, so we must slide the existing elements up to their - -- new home. We use the wider of Index_Type'Base and - -- Count_Type'Base as the type for intermediate index values. - - if Index_Type'Base'Last >= Count_Type_Last then - Index := Before + Index_Type'Base (Count); - else - Index := Index_Type'Base (Count_Type'Base (Before) + Count); - end if; - - EA (Index .. New_Last) := EA (Before .. Container.Last); - EA (Before .. Index - 1) := [others => New_Item]; - end if; - end; - - Container.Last := New_Last; - return; - end if; - - -- In this case, we're inserting elements into a vector that has already - -- allocated an internal array, but the existing array does not have - -- enough storage, so we must allocate a new, longer array. In order to - -- guarantee that the amortized insertion cost is O(1), we always - -- allocate an array whose length is some power-of-two factor of the - -- current array length. (The new array cannot have a length less than - -- the New_Length of the container, but its last index value cannot be - -- greater than Index_Type'Last.) - - New_Capacity := Count_Type'Max (1, Container.Elements.EA'Length); - while New_Capacity < New_Length loop - if New_Capacity > Count_Type'Last / 2 then - New_Capacity := Count_Type'Last; - exit; - else - New_Capacity := 2 * New_Capacity; - end if; - end loop; - - if New_Capacity > Max_Length then - - -- We have reached the limit of capacity, so no further expansion - -- will occur. (This is not a problem, as there is never a need to - -- have more capacity than the maximum container length.) - - New_Capacity := Max_Length; - end if; - - -- We have computed the length of the new internal array (and this is - -- what "vector capacity" means), so use that to compute its last index. - - if Index_Type'Base'Last >= Count_Type_Last then - Dst_Last := No_Index + Index_Type'Base (New_Capacity); - else - Dst_Last := - Index_Type'Base (Count_Type'Base (No_Index) + New_Capacity); - end if; - - -- Now we allocate the new, longer internal array. If the allocation - -- fails, we have not changed any container state, so no side-effect - -- will occur as a result of propagating the exception. - - Dst := new Elements_Type (Dst_Last); - - -- We have our new internal array. All that needs to be done now is to - -- copy the existing items (if any) from the old array (the "source" - -- array, object SA below) to the new array (the "destination" array, - -- object DA below), and then deallocate the old array. - - declare - SA : Elements_Array renames Container.Elements.EA; -- source - DA : Elements_Array renames Dst.EA; -- destination - pragma Unreferenced (DA); - - begin - DA (Index_Type'First .. Before - 1) := - SA (Index_Type'First .. Before - 1); - - if Before > Container.Last then - DA (Before .. New_Last) := [others => New_Item]; - - else - -- The new items are being inserted before some existing elements, - -- so we must slide the existing elements up to their new home. - - if Index_Type'Base'Last >= Count_Type_Last then - Index := Before + Index_Type'Base (Count); - else - Index := Index_Type'Base (Count_Type'Base (Before) + Count); - end if; - - DA (Before .. Index - 1) := [others => New_Item]; - DA (Index .. New_Last) := SA (Before .. Container.Last); - end if; - - exception - when others => - Free (Dst); - raise; - end; - - -- We have successfully copied the items onto the new array, so the - -- final thing to do is deallocate the old array. - - declare - X : Elements_Access := Container.Elements; - - begin - -- We first isolate the old internal array, removing it from the - -- container and replacing it with the new internal array, before we - -- deallocate the old array (which can fail if finalization of - -- elements propagates an exception). - - Container.Elements := Dst; - Container.Last := New_Last; - - -- The container invariants have been restored, so it is now safe to - -- attempt to deallocate the old array. - - Free (X); - end; - end Insert; - - procedure Insert_Vector - (Container : in out Vector; - Before : Extended_Index; - New_Item : Vector) - is - N : constant Count_Type := Length (New_Item); - J : Index_Type'Base; - - begin - -- Use Insert_Space to create the "hole" (the destination slice) into - -- which we copy the source items. - - Insert_Space (Container, Before, Count => N); - - if N = 0 then - - -- There's nothing else to do here (vetting of parameters was - -- performed already in Insert_Space), so we simply return. - - return; - end if; - - -- We calculate the last index value of the destination slice using the - -- wider of Index_Type'Base and count_Type'Base. - - if Index_Type'Base'Last >= Count_Type_Last then - J := (Before - 1) + Index_Type'Base (N); - else - J := Index_Type'Base (Count_Type'Base (Before - 1) + N); - end if; - - if Container'Address /= New_Item'Address then - - -- This is the simple case. New_Item denotes an object different - -- from Container, so there's nothing special we need to do to copy - -- the source items to their destination, because all of the source - -- items are contiguous. - - Container.Elements.EA (Before .. J) := - New_Item.Elements.EA (Index_Type'First .. New_Item.Last); - - return; - end if; - - -- New_Item denotes the same object as Container, so an insertion has - -- potentially split the source items. The destination is always the - -- range [Before, J], but the source is [Index_Type'First, Before) and - -- (J, Container.Last]. We perform the copy in two steps, using each of - -- the two slices of the source items. - - declare - L : constant Index_Type'Base := Before - 1; - - subtype Src_Index_Subtype is Index_Type'Base range - Index_Type'First .. L; - - Src : Elements_Array renames - Container.Elements.EA (Src_Index_Subtype); - - K : Index_Type'Base; - - begin - -- We first copy the source items that precede the space we - -- inserted. Index value K is the last index of that portion - -- destination that receives this slice of the source. (If Before - -- equals Index_Type'First, then this first source slice will be - -- empty, which is harmless.) - - if Index_Type'Base'Last >= Count_Type_Last then - K := L + Index_Type'Base (Src'Length); - else - K := Index_Type'Base (Count_Type'Base (L) + Src'Length); - end if; - - Container.Elements.EA (Before .. K) := Src; - - if Src'Length = N then - - -- The new items were effectively appended to the container, so we - -- have already copied all of the items that need to be copied. - -- We return early here, even though the source slice below is - -- empty (so the assignment would be harmless), because we want to - -- avoid computing J + 1, which will overflow if J equals - -- Index_Type'Base'Last. - - return; - end if; - end; - - declare - -- Note that we want to avoid computing J + 1 here, in case J equals - -- Index_Type'Base'Last. We prevent that by returning early above, - -- immediately after copying the first slice of the source, and - -- determining that this second slice of the source is empty. - - F : constant Index_Type'Base := J + 1; - - subtype Src_Index_Subtype is Index_Type'Base range - F .. Container.Last; - - Src : Elements_Array renames - Container.Elements.EA (Src_Index_Subtype); - - K : Index_Type'Base; - - begin - -- We next copy the source items that follow the space we inserted. - -- Index value K is the first index of that portion of the - -- destination that receives this slice of the source. (For the - -- reasons given above, this slice is guaranteed to be non-empty.) - - if Index_Type'Base'Last >= Count_Type_Last then - K := F - Index_Type'Base (Src'Length); - else - K := Index_Type'Base (Count_Type'Base (F) - Src'Length); - end if; - - Container.Elements.EA (K .. J) := Src; - end; - end Insert_Vector; - - procedure Insert_Vector - (Container : in out Vector; - Before : Cursor; - New_Item : Vector) - is - Index : Index_Type'Base; - - begin - if Checks and then Before.Container /= null - and then Before.Container /= Container'Unrestricted_Access - then - raise Program_Error with "Before cursor denotes wrong container"; - end if; - - if Is_Empty (New_Item) then - return; - end if; - - if Before.Container = null or else Before.Index > Container.Last then - if Checks and then Container.Last = Index_Type'Last then - raise Constraint_Error with - "vector is already at its maximum length"; - end if; - - Index := Container.Last + 1; - - else - Index := Before.Index; - end if; - - Insert_Vector (Container, Index, New_Item); - end Insert_Vector; - - procedure Insert_Vector - (Container : in out Vector; - Before : Cursor; - New_Item : Vector; - Position : out Cursor) - is - Index : Index_Type'Base; - - begin - if Checks and then Before.Container /= null - and then Before.Container /= Container'Unrestricted_Access - then - raise Program_Error with "Before cursor denotes wrong container"; - end if; - - if Is_Empty (New_Item) then - if Before.Container = null or else Before.Index > Container.Last then - Position := No_Element; - else - Position := (Container'Unrestricted_Access, Before.Index); - end if; - - return; - end if; - - if Before.Container = null or else Before.Index > Container.Last then - if Checks and then Container.Last = Index_Type'Last then - raise Constraint_Error with - "vector is already at its maximum length"; - end if; - - Index := Container.Last + 1; - - else - Index := Before.Index; - end if; - - Insert_Vector (Container, Index, New_Item); - - Position := (Container'Unrestricted_Access, Index); - end Insert_Vector; - - procedure Insert - (Container : in out Vector; - Before : Cursor; - New_Item : Element_Type; - Count : Count_Type := 1) - is - Index : Index_Type'Base; - - begin - if Checks and then Before.Container /= null - and then Before.Container /= Container'Unrestricted_Access - then - raise Program_Error with "Before cursor denotes wrong container"; - end if; - - if Count = 0 then - return; - end if; - - if Before.Container = null or else Before.Index > Container.Last then - if Checks and then Container.Last = Index_Type'Last then - raise Constraint_Error with - "vector is already at its maximum length"; - else - Index := Container.Last + 1; - end if; - - else - Index := Before.Index; - end if; - - Insert (Container, Index, New_Item, Count); - end Insert; - - procedure Insert - (Container : in out Vector; - Before : Cursor; - New_Item : Element_Type; - Position : out Cursor; - Count : Count_Type := 1) - is - Index : Index_Type'Base; - - begin - if Checks and then Before.Container /= null - and then Before.Container /= Container'Unrestricted_Access - then - raise Program_Error with "Before cursor denotes wrong container"; - end if; - - if Count = 0 then - if Before.Container = null or else Before.Index > Container.Last then - Position := No_Element; - else - Position := (Container'Unrestricted_Access, Before.Index); - end if; - - return; - end if; - - if Before.Container = null or else Before.Index > Container.Last then - if Checks and then Container.Last = Index_Type'Last then - raise Constraint_Error with - "vector is already at its maximum length"; - end if; - - Index := Container.Last + 1; - - else - Index := Before.Index; - end if; - - Insert (Container, Index, New_Item, Count); - - Position := (Container'Unrestricted_Access, Index); - end Insert; - - procedure Insert - (Container : in out Vector; - Before : Extended_Index; - Count : Count_Type := 1) - is - New_Item : Element_Type; -- Default-initialized value - pragma Warnings (Off, New_Item); - - begin - Insert (Container, Before, New_Item, Count); - end Insert; - - procedure Insert - (Container : in out Vector; - Before : Cursor; - Position : out Cursor; - Count : Count_Type := 1) - is - New_Item : Element_Type; -- Default-initialized value - pragma Warnings (Off, New_Item); - begin - Insert (Container, Before, New_Item, Position, Count); - end Insert; - - ------------------ - -- Insert_Space -- - ------------------ - - procedure Insert_Space - (Container : in out Vector; - Before : Extended_Index; - Count : Count_Type := 1) - is - Old_Length : constant Count_Type := Container.Length; - - Max_Length : Count_Type'Base; -- determined from range of Index_Type - New_Length : Count_Type'Base; -- sum of current length and Count - New_Last : Index_Type'Base; -- last index of vector after insertion - - Index : Index_Type'Base; -- scratch for intermediate values - J : Count_Type'Base; -- scratch - - New_Capacity : Count_Type'Base; -- length of new, expanded array - Dst_Last : Index_Type'Base; -- last index of new, expanded array - Dst : Elements_Access; -- new, expanded internal array - - begin - -- The tampering bits exist to prevent an item from being harmfully - -- manipulated while it is being visited. Query, Update, and Iterate - -- increment the busy count on entry, and decrement the count on - -- exit. Insert checks the count to determine whether it is being called - -- while the associated callback procedure is executing. - - TC_Check (Container.TC); - - if Checks then - -- As a precondition on the generic actual Index_Type, the base type - -- must include Index_Type'Pred (Index_Type'First); this is the value - -- that Container.Last assumes when the vector is empty. However, we - -- do not allow that as the value for Index when specifying where the - -- new items should be inserted, so we must manually check. (That the - -- user is allowed to specify the value at all here is a consequence - -- of the declaration of the Extended_Index subtype, which includes - -- the values in the base range that immediately precede and - -- immediately follow the values in the Index_Type.) - - if Before < Index_Type'First then - raise Constraint_Error with - "Before index is out of range (too small)"; - end if; - - -- We do allow a value greater than Container.Last to be specified as - -- the Index, but only if it's immediately greater. This allows for - -- the case of appending items to the back end of the vector. (It is - -- assumed that specifying an index value greater than Last + 1 - -- indicates some deeper flaw in the caller's algorithm, so that case - -- is treated as a proper error.) - - if Before > Container.Last + 1 then - raise Constraint_Error with - "Before index is out of range (too large)"; - end if; - end if; - - -- We treat inserting 0 items into the container as a no-op, even when - -- the container is busy, so we simply return. - - if Count = 0 then - return; - end if; - - -- There are two constraints we need to satisfy. The first constraint is - -- that a container cannot have more than Count_Type'Last elements, so - -- we must check the sum of the current length and the insertion count. - -- Note: we cannot simply add these values, because of the possibility - -- of overflow. - - if Checks and then Old_Length > Count_Type'Last - Count then - raise Constraint_Error with "Count is out of range"; - end if; - - -- It is now safe compute the length of the new vector, without fear of - -- overflow. - - New_Length := Old_Length + Count; - - -- The second constraint is that the new Last index value cannot exceed - -- Index_Type'Last. In each branch below, we calculate the maximum - -- length (computed from the range of values in Index_Type), and then - -- compare the new length to the maximum length. If the new length is - -- acceptable, then we compute the new last index from that. - - if Index_Type'Base'Last >= Count_Type_Last then - -- We have to handle the case when there might be more values in the - -- range of Index_Type than in the range of Count_Type. - - if Index_Type'First <= 0 then - - -- We know that No_Index (the same as Index_Type'First - 1) is - -- less than 0, so it is safe to compute the following sum without - -- fear of overflow. We need to suppress warnings, because - -- otherwise we get an error in -gnatwE mode. - - pragma Warnings (Off); - Index := No_Index + Index_Type'Base (Count_Type'Last); - pragma Warnings (On); - - if Index <= Index_Type'Last then - - -- We have determined that range of Index_Type has at least as - -- many values as in Count_Type, so Count_Type'Last is the - -- maximum number of items that are allowed. - - Max_Length := Count_Type'Last; - - else - -- The range of Index_Type has fewer values than in Count_Type, - -- so the maximum number of items is computed from the range of - -- the Index_Type. - - Max_Length := Count_Type'Base (Index_Type'Last - No_Index); - end if; - - else - -- No_Index is equal or greater than 0, so we can safely compute - -- the difference without fear of overflow (which we would have to - -- worry about if No_Index were less than 0, but that case is - -- handled above). - - if Index_Type'Last - No_Index >= Count_Type_Last then - -- We have determined that range of Index_Type has at least as - -- many values as in Count_Type, so Count_Type'Last is the - -- maximum number of items that are allowed. - - Max_Length := Count_Type'Last; - - else - -- The range of Index_Type has fewer values than in Count_Type, - -- so the maximum number of items is computed from the range of - -- the Index_Type. - - Max_Length := Count_Type'Base (Index_Type'Last - No_Index); - end if; - end if; - - elsif Index_Type'First <= 0 then - - -- We know that No_Index (the same as Index_Type'First - 1) is less - -- than 0, so it is safe to compute the following sum without fear of - -- overflow. - - J := Count_Type'Base (No_Index) + Count_Type'Last; - - if J <= Count_Type'Base (Index_Type'Last) then - - -- We have determined that range of Index_Type has at least as - -- many values as in Count_Type, so Count_Type'Last is the maximum - -- number of items that are allowed. - - Max_Length := Count_Type'Last; - - else - -- The range of Index_Type has fewer values than Count_Type does, - -- so the maximum number of items is computed from the range of - -- the Index_Type. - - Max_Length := - Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index); - end if; - - else - -- No_Index is equal or greater than 0, so we can safely compute the - -- difference without fear of overflow (which we would have to worry - -- about if No_Index were less than 0, but that case is handled - -- above). - - Max_Length := - Count_Type'Base (Index_Type'Last) - Count_Type'Base (No_Index); - end if; - - -- We have just computed the maximum length (number of items). We must - -- now compare the requested length to the maximum length, as we do not - -- allow a vector expand beyond the maximum (because that would create - -- an internal array with a last index value greater than - -- Index_Type'Last, with no way to index those elements). - - if Checks and then New_Length > Max_Length then - raise Constraint_Error with "Count is out of range"; - end if; - - -- New_Last is the last index value of the items in the container after - -- insertion. Use the wider of Index_Type'Base and Count_Type'Base to - -- compute its value from the New_Length. - - if Index_Type'Base'Last >= Count_Type_Last then - New_Last := No_Index + Index_Type'Base (New_Length); - else - New_Last := Index_Type'Base (Count_Type'Base (No_Index) + New_Length); - end if; - - if Container.Elements = null then - pragma Assert (Container.Last = No_Index); - - -- This is the simplest case, with which we must always begin: we're - -- inserting items into an empty vector that hasn't allocated an - -- internal array yet. Note that we don't need to check the busy bit - -- here, because an empty container cannot be busy. - - -- In order to preserve container invariants, we allocate the new - -- internal array first, before setting the Last index value, in case - -- the allocation fails (which can happen either because there is no - -- storage available, or because default-valued element - -- initialization fails). - - Container.Elements := new Elements_Type (New_Last); - - -- The allocation of the new, internal array succeeded, so it is now - -- safe to update the Last index, restoring container invariants. - - Container.Last := New_Last; - - return; - end if; - - -- An internal array has already been allocated, so we must determine - -- whether there is enough unused storage for the new items. - - if New_Last <= Container.Elements.Last then - - -- In this case, we're inserting space into a vector that has already - -- allocated an internal array, and the existing array has enough - -- unused storage for the new items. - - declare - EA : Elements_Array renames Container.Elements.EA; - - begin - if Before <= Container.Last then - - -- The space is being inserted before some existing elements, - -- so we must slide the existing elements up to their new - -- home. We use the wider of Index_Type'Base and - -- Count_Type'Base as the type for intermediate index values. - - if Index_Type'Base'Last >= Count_Type_Last then - Index := Before + Index_Type'Base (Count); - - else - Index := Index_Type'Base (Count_Type'Base (Before) + Count); - end if; - - EA (Index .. New_Last) := EA (Before .. Container.Last); - end if; - end; - - Container.Last := New_Last; - return; - end if; - - -- In this case, we're inserting space into a vector that has already - -- allocated an internal array, but the existing array does not have - -- enough storage, so we must allocate a new, longer array. In order to - -- guarantee that the amortized insertion cost is O(1), we always - -- allocate an array whose length is some power-of-two factor of the - -- current array length. (The new array cannot have a length less than - -- the New_Length of the container, but its last index value cannot be - -- greater than Index_Type'Last.) - - New_Capacity := Count_Type'Max (1, Container.Elements.EA'Length); - while New_Capacity < New_Length loop - if New_Capacity > Count_Type'Last / 2 then - New_Capacity := Count_Type'Last; - exit; - end if; - - New_Capacity := 2 * New_Capacity; - end loop; - - if New_Capacity > Max_Length then - - -- We have reached the limit of capacity, so no further expansion - -- will occur. (This is not a problem, as there is never a need to - -- have more capacity than the maximum container length.) - - New_Capacity := Max_Length; - end if; - - -- We have computed the length of the new internal array (and this is - -- what "vector capacity" means), so use that to compute its last index. - - if Index_Type'Base'Last >= Count_Type_Last then - Dst_Last := No_Index + Index_Type'Base (New_Capacity); - else - Dst_Last := - Index_Type'Base (Count_Type'Base (No_Index) + New_Capacity); - end if; - - -- Now we allocate the new, longer internal array. If the allocation - -- fails, we have not changed any container state, so no side-effect - -- will occur as a result of propagating the exception. - - Dst := new Elements_Type (Dst_Last); - - -- We have our new internal array. All that needs to be done now is to - -- copy the existing items (if any) from the old array (the "source" - -- array, object SA below) to the new array (the "destination" array, - -- object DA below), and then deallocate the old array. - - declare - SA : Elements_Array renames Container.Elements.EA; -- source - DA : Elements_Array renames Dst.EA; -- destination - pragma Unreferenced (DA); - - begin - DA (Index_Type'First .. Before - 1) := - SA (Index_Type'First .. Before - 1); - - if Before <= Container.Last then - - -- The space is being inserted before some existing elements, so - -- we must slide the existing elements up to their new home. - - if Index_Type'Base'Last >= Count_Type_Last then - Index := Before + Index_Type'Base (Count); - else - Index := Index_Type'Base (Count_Type'Base (Before) + Count); - end if; - - DA (Index .. New_Last) := SA (Before .. Container.Last); - end if; - - exception - when others => - Free (Dst); - raise; - end; - - -- We have successfully copied the items onto the new array, so the - -- final thing to do is restore invariants, and deallocate the old - -- array. - - declare - X : Elements_Access := Container.Elements; - - begin - -- We first isolate the old internal array, removing it from the - -- container and replacing it with the new internal array, before we - -- deallocate the old array (which can fail if finalization of - -- elements propagates an exception). - - Container.Elements := Dst; - Container.Last := New_Last; - - -- The container invariants have been restored, so it is now safe to - -- attempt to deallocate the old array. - - Free (X); - end; - end Insert_Space; - - procedure Insert_Space - (Container : in out Vector; - Before : Cursor; - Position : out Cursor; - Count : Count_Type := 1) - is - Index : Index_Type'Base; - - begin - if Checks and then Before.Container /= null - and then Before.Container /= Container'Unrestricted_Access - then - raise Program_Error with "Before cursor denotes wrong container"; - end if; - - if Count = 0 then - if Before.Container = null or else Before.Index > Container.Last then - Position := No_Element; - else - Position := (Container'Unrestricted_Access, Before.Index); - end if; - - return; - end if; - - if Before.Container = null or else Before.Index > Container.Last then - if Checks and then Container.Last = Index_Type'Last then - raise Constraint_Error with - "vector is already at its maximum length"; - else - Index := Container.Last + 1; - end if; - - else - Index := Before.Index; - end if; - - Insert_Space (Container, Index, Count); - - Position := (Container'Unrestricted_Access, Index); - end Insert_Space; - - -------------- - -- Is_Empty -- - -------------- - - function Is_Empty (Container : Vector) return Boolean is - begin - return Container.Last < Index_Type'First; - end Is_Empty; - - ------------- - -- Iterate -- - ------------- - - procedure Iterate - (Container : Vector; - Process : not null access procedure (Position : Cursor)) - is - Busy : With_Busy (Container.TC'Unrestricted_Access); - begin - for Indx in Index_Type'First .. Container.Last loop - Process (Cursor'(Container'Unrestricted_Access, Indx)); - end loop; - end Iterate; - - function Iterate - (Container : Vector) - return Vector_Iterator_Interfaces.Reversible_Iterator'Class - is - V : constant Vector_Access := Container'Unrestricted_Access; - begin - -- The value of its Index component influences the behavior of the First - -- and Last selector functions of the iterator object. When the Index - -- component is No_Index (as is the case here), this means the iterator - -- object was constructed without a start expression. This is a complete - -- iterator, meaning that the iteration starts from the (logical) - -- beginning of the sequence of items. - - -- Note: For a forward iterator, Container.First is the beginning, and - -- for a reverse iterator, Container.Last is the beginning. - - return It : constant Iterator := - (Limited_Controlled with - Container => V, - Index => No_Index) - do - Busy (Container.TC'Unrestricted_Access.all); - end return; - end Iterate; - - function Iterate - (Container : Vector; - Start : Cursor) - return Vector_Iterator_Interfaces.Reversible_Iterator'Class - is - V : constant Vector_Access := Container'Unrestricted_Access; - begin - -- It was formerly the case that when Start = No_Element, the partial - -- iterator was defined to behave the same as for a complete iterator, - -- and iterate over the entire sequence of items. However, those - -- semantics were unintuitive and arguably error-prone (it is too easy - -- to accidentally create an endless loop), and so they were changed, - -- per the ARG meeting in Denver on 2011/11. However, there was no - -- consensus about what positive meaning this corner case should have, - -- and so it was decided to simply raise an exception. This does imply, - -- however, that it is not possible to use a partial iterator to specify - -- an empty sequence of items. - - if Checks then - if Start.Container = null then - raise Constraint_Error with - "Start position for iterator equals No_Element"; - end if; - - if Start.Container /= V then - raise Program_Error with - "Start cursor of Iterate designates wrong vector"; - end if; - - if Start.Index > V.Last then - raise Constraint_Error with - "Start position for iterator equals No_Element"; - end if; - end if; - - -- The value of its Index component influences the behavior of the First - -- and Last selector functions of the iterator object. When the Index - -- component is not No_Index (as is the case here), it means that this - -- is a partial iteration, over a subset of the complete sequence of - -- items. The iterator object was constructed with a start expression, - -- indicating the position from which the iteration begins. Note that - -- the start position has the same value irrespective of whether this - -- is a forward or reverse iteration. - - return It : constant Iterator := - (Limited_Controlled with - Container => V, - Index => Start.Index) - do - Busy (Container.TC'Unrestricted_Access.all); - end return; - end Iterate; - - ---------- - -- Last -- - ---------- - - function Last (Container : Vector) return Cursor is - begin - if Is_Empty (Container) then - return No_Element; - else - return (Container'Unrestricted_Access, Container.Last); - end if; - end Last; - - function Last (Object : Iterator) return Cursor is - begin - -- The value of the iterator object's Index component influences the - -- behavior of the Last (and First) selector function. - - -- When the Index component is No_Index, this means the iterator - -- object was constructed without a start expression, in which case the - -- (reverse) iteration starts from the (logical) beginning of the entire - -- sequence (corresponding to Container.Last, for a reverse iterator). - - -- Otherwise, this is iteration over a partial sequence of items. - -- When the Index component is not No_Index, the iterator object was - -- constructed with a start expression, that specifies the position - -- from which the (reverse) partial iteration begins. - - if Object.Index = No_Index then - return Last (Object.Container.all); - else - return Cursor'(Object.Container, Object.Index); - end if; - end Last; - - ------------------ - -- Last_Element -- - ------------------ - - function Last_Element (Container : Vector) return Element_Type is - begin - if Checks and then Container.Last = No_Index then - raise Constraint_Error with "Container is empty"; - else - return Container.Elements.EA (Container.Last); - end if; - end Last_Element; - - ---------------- - -- Last_Index -- - ---------------- - - function Last_Index (Container : Vector) return Extended_Index is - begin - return Container.Last; - end Last_Index; - - ------------ - -- Length -- - ------------ - - function Length (Container : Vector) return Count_Type is - L : constant Index_Type'Base := Container.Last; - F : constant Index_Type := Index_Type'First; - - begin - -- The base range of the index type (Index_Type'Base) might not include - -- all values for length (Count_Type). Contrariwise, the index type - -- might include values outside the range of length. Hence we use - -- whatever type is wider for intermediate values when calculating - -- length. Note that no matter what the index type is, the maximum - -- length to which a vector is allowed to grow is always the minimum - -- of Count_Type'Last and (IT'Last - IT'First + 1). - - -- For example, an Index_Type with range -127 .. 127 is only guaranteed - -- to have a base range of -128 .. 127, but the corresponding vector - -- would have lengths in the range 0 .. 255. In this case we would need - -- to use Count_Type'Base for intermediate values. - - -- Another case would be the index range -2**63 + 1 .. -2**63 + 10. The - -- vector would have a maximum length of 10, but the index values lie - -- outside the range of Count_Type (which is only 32 bits). In this - -- case we would need to use Index_Type'Base for intermediate values. - - if Count_Type'Base'Last >= Index_Type'Pos (Index_Type'Base'Last) then - return Count_Type'Base (L) - Count_Type'Base (F) + 1; - else - return Count_Type (L - F + 1); - end if; - end Length; - - ---------- - -- Move -- - ---------- - - procedure Move - (Target : in out Vector; - Source : in out Vector) - is - begin - if Target'Address = Source'Address then - return; - end if; - - TC_Check (Target.TC); - TC_Check (Source.TC); - - declare - Target_Elements : constant Elements_Access := Target.Elements; - begin - Target.Elements := Source.Elements; - Source.Elements := Target_Elements; - end; - - Target.Last := Source.Last; - Source.Last := No_Index; - end Move; - - ---------- - -- Next -- - ---------- - - function Next (Position : Cursor) return Cursor is - begin - if Position.Container = null then - return No_Element; - elsif Position.Index < Position.Container.Last then - return (Position.Container, Position.Index + 1); - else - return No_Element; - end if; - end Next; - - function Next (Object : Iterator; Position : Cursor) return Cursor is - begin - if Position.Container = null then - return No_Element; - elsif Checks and then Position.Container /= Object.Container then - raise Program_Error with - "Position cursor of Next designates wrong vector"; - else - return Next (Position); - end if; - end Next; - - procedure Next (Position : in out Cursor) is - begin - if Position.Container = null then - return; - elsif Position.Index < Position.Container.Last then - Position.Index := Position.Index + 1; - else - Position := No_Element; - end if; - end Next; - - ------------- - -- Prepend -- - ------------- - - procedure Prepend - (Container : in out Vector; - New_Item : Element_Type; - Count : Count_Type := 1) - is - begin - Insert (Container, Index_Type'First, New_Item, Count); - end Prepend; - - -------------------- - -- Prepend_Vector -- - -------------------- - - procedure Prepend_Vector (Container : in out Vector; New_Item : Vector) is - begin - Insert_Vector (Container, Index_Type'First, New_Item); - end Prepend_Vector; - - -------------- - -- Previous -- - -------------- - - function Previous (Position : Cursor) return Cursor is - begin - if Position.Container = null then - return No_Element; - elsif Position.Index > Index_Type'First then - return (Position.Container, Position.Index - 1); - else - return No_Element; - end if; - end Previous; - - function Previous (Object : Iterator; Position : Cursor) return Cursor is - begin - if Position.Container = null then - return No_Element; - elsif Checks and then Position.Container /= Object.Container then - raise Program_Error with - "Position cursor of Previous designates wrong vector"; - else - return Previous (Position); - end if; - end Previous; - - procedure Previous (Position : in out Cursor) is - begin - if Position.Container = null then - return; - elsif Position.Index > Index_Type'First then - Position.Index := Position.Index - 1; - else - Position := No_Element; - end if; - end Previous; - - ---------------------- - -- Pseudo_Reference -- - ---------------------- - - function Pseudo_Reference - (Container : aliased Vector'Class) return Reference_Control_Type - is - TC : constant Tamper_Counts_Access := Container.TC'Unrestricted_Access; - begin - return R : constant Reference_Control_Type := (Controlled with TC) do - Busy (TC.all); - end return; - end Pseudo_Reference; - - --------------- - -- Put_Image -- - --------------- - - procedure Put_Image - (S : in out Ada.Strings.Text_Buffers.Root_Buffer_Type'Class; V : Vector) - is - First_Time : Boolean := True; - use System.Put_Images; - begin - Array_Before (S); - - for X of V loop - if First_Time then - First_Time := False; - else - Simple_Array_Between (S); - end if; - - Element_Type'Put_Image (S, X); - end loop; - - Array_After (S); - end Put_Image; - - ------------------- - -- Query_Element -- - ------------------- - - procedure Query_Element - (Container : Vector; - Index : Index_Type; - Process : not null access procedure (Element : Element_Type)) - is - Lock : With_Lock (Container.TC'Unrestricted_Access); - begin - if Checks and then Index > Container.Last then - raise Constraint_Error with "Index is out of range"; - end if; - - Process (Container.Elements.EA (Index)); - end Query_Element; - - procedure Query_Element - (Position : Cursor; - Process : not null access procedure (Element : Element_Type)) - is - begin - if Checks and then Position.Container = null then - raise Constraint_Error with "Position cursor has no element"; - else - Query_Element (Position.Container.all, Position.Index, Process); - end if; - end Query_Element; - - ---------- - -- Read -- - ---------- - - procedure Read - (Stream : not null access Root_Stream_Type'Class; - Container : out Vector) - is - Length : Count_Type'Base; - Last : Index_Type'Base := No_Index; - - begin - Clear (Container); - - Count_Type'Base'Read (Stream, Length); - - if Length > Capacity (Container) then - Reserve_Capacity (Container, Capacity => Length); - end if; - - for J in Count_Type range 1 .. Length loop - Last := Last + 1; - Element_Type'Read (Stream, Container.Elements.EA (Last)); - Container.Last := Last; - end loop; - end Read; - - procedure Read - (Stream : not null access Root_Stream_Type'Class; - Position : out Cursor) - is - begin - raise Program_Error with "attempt to stream vector cursor"; - end Read; - - procedure Read - (Stream : not null access Root_Stream_Type'Class; - Item : out Reference_Type) - is - begin - raise Program_Error with "attempt to stream reference"; - end Read; - - procedure Read - (Stream : not null access Root_Stream_Type'Class; - Item : out Constant_Reference_Type) - is - begin - raise Program_Error with "attempt to stream reference"; - end Read; - - --------------- - -- Reference -- - --------------- - - function Reference - (Container : aliased in out Vector; - Position : Cursor) return Reference_Type - is - begin - if Checks then - if Position.Container = null then - raise Constraint_Error with "Position cursor has no element"; - end if; - - if Position.Container /= Container'Unrestricted_Access then - raise Program_Error with "Position cursor denotes wrong container"; - end if; - - if Position.Index > Position.Container.Last then - raise Constraint_Error with "Position cursor is out of range"; - end if; - end if; - - declare - TC : constant Tamper_Counts_Access := - Container.TC'Unrestricted_Access; - begin - return R : constant Reference_Type := - (Element => Container.Elements.EA (Position.Index)'Access, - Control => (Controlled with TC)) - do - Busy (TC.all); - end return; - end; - end Reference; - - function Reference - (Container : aliased in out Vector; - Index : Index_Type) return Reference_Type - is - begin - if Checks and then Index > Container.Last then - raise Constraint_Error with "Index is out of range"; - end if; - - declare - TC : constant Tamper_Counts_Access := - Container.TC'Unrestricted_Access; - begin - return R : constant Reference_Type := - (Element => Container.Elements.EA (Index)'Access, - Control => (Controlled with TC)) - do - Busy (TC.all); - end return; - end; - end Reference; - - --------------------- - -- Replace_Element -- - --------------------- - - procedure Replace_Element - (Container : in out Vector; - Index : Index_Type; - New_Item : Element_Type) - is - begin - TE_Check (Container.TC); - - if Checks and then Index > Container.Last then - raise Constraint_Error with "Index is out of range"; - end if; - - Container.Elements.EA (Index) := New_Item; - end Replace_Element; - - procedure Replace_Element - (Container : in out Vector; - Position : Cursor; - New_Item : Element_Type) - is - begin - TE_Check (Container.TC); - - if Checks then - if Position.Container = null then - raise Constraint_Error with "Position cursor has no element"; - - elsif Position.Container /= Container'Unrestricted_Access then - raise Program_Error with "Position cursor denotes wrong container"; - - elsif Position.Index > Container.Last then - raise Constraint_Error with "Position cursor is out of range"; - end if; - end if; - - Container.Elements.EA (Position.Index) := New_Item; - end Replace_Element; - - ---------------------- - -- Reserve_Capacity -- - ---------------------- - - procedure Reserve_Capacity - (Container : in out Vector; - Capacity : Count_Type) - is - N : constant Count_Type := Length (Container); - - Index : Count_Type'Base; - Last : Index_Type'Base; - - begin - -- Reserve_Capacity can be used to either expand the storage available - -- for elements (this would be its typical use, in anticipation of - -- future insertion), or to trim back storage. In the latter case, - -- storage can only be trimmed back to the limit of the container - -- length. Note that Reserve_Capacity neither deletes (active) elements - -- nor inserts elements; it only affects container capacity, never - -- container length. - - if Capacity = 0 then - - -- This is a request to trim back storage, to the minimum amount - -- possible given the current state of the container. - - if N = 0 then - - -- The container is empty, so in this unique case we can - -- deallocate the entire internal array. Note that an empty - -- container can never be busy, so there's no need to check the - -- tampering bits. - - declare - X : Elements_Access := Container.Elements; - - begin - -- First we remove the internal array from the container, to - -- handle the case when the deallocation raises an exception. - - Container.Elements := null; - - -- Container invariants have been restored, so it is now safe - -- to attempt to deallocate the internal array. - - Free (X); - end; - - elsif N < Container.Elements.EA'Length then - - -- The container is not empty, and the current length is less than - -- the current capacity, so there's storage available to trim. In - -- this case, we allocate a new internal array having a length - -- that exactly matches the number of items in the - -- container. (Reserve_Capacity does not delete active elements, - -- so this is the best we can do with respect to minimizing - -- storage). - - TC_Check (Container.TC); - - declare - subtype Src_Index_Subtype is Index_Type'Base range - Index_Type'First .. Container.Last; - - Src : Elements_Array renames - Container.Elements.EA (Src_Index_Subtype); - - X : Elements_Access := Container.Elements; - - begin - -- Although we have isolated the old internal array that we're - -- going to deallocate, we don't deallocate it until we have - -- successfully allocated a new one. If there is an exception - -- during allocation (either because there is not enough - -- storage, or because initialization of the elements fails), - -- we let it propagate without causing any side-effect. - - Container.Elements := new Elements_Type'(Container.Last, Src); - - -- We have successfully allocated a new internal array (with a - -- smaller length than the old one, and containing a copy of - -- just the active elements in the container), so it is now - -- safe to attempt to deallocate the old array. The old array - -- has been isolated, and container invariants have been - -- restored, so if the deallocation fails (because finalization - -- of the elements fails), we simply let it propagate. - - Free (X); - end; - end if; - - return; - end if; - - -- Reserve_Capacity can be used to expand the storage available for - -- elements, but we do not let the capacity grow beyond the number of - -- values in Index_Type'Range. (Were it otherwise, there would be no way - -- to refer to the elements with an index value greater than - -- Index_Type'Last, so that storage would be wasted.) Here we compute - -- the Last index value of the new internal array, in a way that avoids - -- any possibility of overflow. - - if Index_Type'Base'Last >= Count_Type_Last then - - -- We perform a two-part test. First we determine whether the - -- computed Last value lies in the base range of the type, and then - -- determine whether it lies in the range of the index (sub)type. - - -- Last must satisfy this relation: - -- First + Length - 1 <= Last - -- We regroup terms: - -- First - 1 <= Last - Length - -- Which can rewrite as: - -- No_Index <= Last - Length - - if Checks and then - Index_Type'Base'Last - Index_Type'Base (Capacity) < No_Index - then - raise Constraint_Error with "Capacity is out of range"; - end if; - - -- We now know that the computed value of Last is within the base - -- range of the type, so it is safe to compute its value: - - Last := No_Index + Index_Type'Base (Capacity); - - -- Finally we test whether the value is within the range of the - -- generic actual index subtype: - - if Checks and then Last > Index_Type'Last then - raise Constraint_Error with "Capacity is out of range"; - end if; - - elsif Index_Type'First <= 0 then - - -- Here we can compute Last directly, in the normal way. We know that - -- No_Index is less than 0, so there is no danger of overflow when - -- adding the (positive) value of Capacity. - - Index := Count_Type'Base (No_Index) + Capacity; -- Last - - if Checks and then Index > Count_Type'Base (Index_Type'Last) then - raise Constraint_Error with "Capacity is out of range"; - end if; - - -- We know that the computed value (having type Count_Type) of Last - -- is within the range of the generic actual index subtype, so it is - -- safe to convert to Index_Type: - - Last := Index_Type'Base (Index); - - else - -- Here Index_Type'First (and Index_Type'Last) is positive, so we - -- must test the length indirectly (by working backwards from the - -- largest possible value of Last), in order to prevent overflow. - - Index := Count_Type'Base (Index_Type'Last) - Capacity; -- No_Index - - if Checks and then Index < Count_Type'Base (No_Index) then - raise Constraint_Error with "Capacity is out of range"; - end if; - - -- We have determined that the value of Capacity would not create a - -- Last index value outside of the range of Index_Type, so we can now - -- safely compute its value. - - Last := Index_Type'Base (Count_Type'Base (No_Index) + Capacity); - end if; - - -- The requested capacity is non-zero, but we don't know yet whether - -- this is a request for expansion or contraction of storage. - - if Container.Elements = null then - - -- The container is empty (it doesn't even have an internal array), - -- so this represents a request to allocate (expand) storage having - -- the given capacity. - - Container.Elements := new Elements_Type (Last); - return; - end if; - - if Capacity <= N then - - -- This is a request to trim back storage, but only to the limit of - -- what's already in the container. (Reserve_Capacity never deletes - -- active elements, it only reclaims excess storage.) - - if N < Container.Elements.EA'Length then - - -- The container is not empty (because the requested capacity is - -- positive, and less than or equal to the container length), and - -- the current length is less than the current capacity, so - -- there's storage available to trim. In this case, we allocate a - -- new internal array having a length that exactly matches the - -- number of items in the container. - - TC_Check (Container.TC); - - declare - subtype Src_Index_Subtype is Index_Type'Base range - Index_Type'First .. Container.Last; - - Src : Elements_Array renames - Container.Elements.EA (Src_Index_Subtype); - - X : Elements_Access := Container.Elements; - - begin - -- Although we have isolated the old internal array that we're - -- going to deallocate, we don't deallocate it until we have - -- successfully allocated a new one. If there is an exception - -- during allocation (either because there is not enough - -- storage, or because initialization of the elements fails), - -- we let it propagate without causing any side-effect. - - Container.Elements := new Elements_Type'(Container.Last, Src); - - -- We have successfully allocated a new internal array (with a - -- smaller length than the old one, and containing a copy of - -- just the active elements in the container), so it is now - -- safe to attempt to deallocate the old array. The old array - -- has been isolated, and container invariants have been - -- restored, so if the deallocation fails (because finalization - -- of the elements fails), we simply let it propagate. - - Free (X); - end; - end if; - - return; - end if; - - -- The requested capacity is larger than the container length (the - -- number of active elements). Whether this represents a request for - -- expansion or contraction of the current capacity depends on what the - -- current capacity is. - - if Capacity = Container.Elements.EA'Length then - - -- The requested capacity matches the existing capacity, so there's - -- nothing to do here. We treat this case as a no-op, and simply - -- return without checking the busy bit. - - return; - end if; - - -- There is a change in the capacity of a non-empty container, so a new - -- internal array will be allocated. (The length of the new internal - -- array could be less or greater than the old internal array. We know - -- only that the length of the new internal array is greater than the - -- number of active elements in the container.) We must check whether - -- the container is busy before doing anything else. - - TC_Check (Container.TC); - - -- We now allocate a new internal array, having a length different from - -- its current value. - - declare - E : Elements_Access := new Elements_Type (Last); - - begin - -- We have successfully allocated the new internal array. We first - -- attempt to copy the existing elements from the old internal array - -- ("src" elements) onto the new internal array ("tgt" elements). - - declare - subtype Index_Subtype is Index_Type'Base range - Index_Type'First .. Container.Last; - - Src : Elements_Array renames - Container.Elements.EA (Index_Subtype); - - Tgt : Elements_Array renames E.EA (Index_Subtype); - - begin - Tgt := Src; - - exception - when others => - Free (E); - raise; - end; - - -- We have successfully copied the existing elements onto the new - -- internal array, so now we can attempt to deallocate the old one. - - declare - X : Elements_Access := Container.Elements; - - begin - -- First we isolate the old internal array, and replace it in the - -- container with the new internal array. - - Container.Elements := E; - - -- Container invariants have been restored, so it is now safe to - -- attempt to deallocate the old internal array. - - Free (X); - end; - end; - end Reserve_Capacity; - - ---------------------- - -- Reverse_Elements -- - ---------------------- - - procedure Reverse_Elements (Container : in out Vector) is - begin - if Container.Length <= 1 then - return; - end if; - - -- The exception behavior for the vector container must match that for - -- the list container, so we check for cursor tampering here (which will - -- catch more things) instead of for element tampering (which will catch - -- fewer things). It's true that the elements of this vector container - -- could be safely moved around while (say) an iteration is taking place - -- (iteration only increments the busy counter), and so technically - -- all we would need here is a test for element tampering (indicated - -- by the lock counter), that's simply an artifact of our array-based - -- implementation. Logically Reverse_Elements requires a check for - -- cursor tampering. - - TC_Check (Container.TC); - - declare - K : Index_Type; - J : Index_Type; - E : Elements_Type renames Container.Elements.all; - - begin - K := Index_Type'First; - J := Container.Last; - while K < J loop - declare - EK : constant Element_Type := E.EA (K); - begin - E.EA (K) := E.EA (J); - E.EA (J) := EK; - end; - - K := K + 1; - J := J - 1; - end loop; - end; - end Reverse_Elements; - - ------------------ - -- Reverse_Find -- - ------------------ - - function Reverse_Find - (Container : Vector; - Item : Element_Type; - Position : Cursor := No_Element) return Cursor - is - Last : Index_Type'Base; - - begin - if Checks and then Position.Container /= null - and then Position.Container /= Container'Unrestricted_Access - then - raise Program_Error with "Position cursor denotes wrong container"; - end if; - - Last := - (if Position.Container = null or else Position.Index > Container.Last - then Container.Last - else Position.Index); - - -- Per AI05-0022, the container implementation is required to detect - -- element tampering by a generic actual subprogram. - - declare - Lock : With_Lock (Container.TC'Unrestricted_Access); - begin - for Indx in reverse Index_Type'First .. Last loop - if Container.Elements.EA (Indx) = Item then - return Cursor'(Container'Unrestricted_Access, Indx); - end if; - end loop; - - return No_Element; - end; - end Reverse_Find; - - ------------------------ - -- Reverse_Find_Index -- - ------------------------ - - function Reverse_Find_Index - (Container : Vector; - Item : Element_Type; - Index : Index_Type := Index_Type'Last) return Extended_Index - is - -- Per AI05-0022, the container implementation is required to detect - -- element tampering by a generic actual subprogram. - - Lock : With_Lock (Container.TC'Unrestricted_Access); - - Last : constant Index_Type'Base := - Index_Type'Min (Container.Last, Index); - - begin - for Indx in reverse Index_Type'First .. Last loop - if Container.Elements.EA (Indx) = Item then - return Indx; - end if; - end loop; - - return No_Index; - end Reverse_Find_Index; - - --------------------- - -- Reverse_Iterate -- - --------------------- - - procedure Reverse_Iterate - (Container : Vector; - Process : not null access procedure (Position : Cursor)) - is - Busy : With_Busy (Container.TC'Unrestricted_Access); - begin - for Indx in reverse Index_Type'First .. Container.Last loop - Process (Cursor'(Container'Unrestricted_Access, Indx)); - end loop; - end Reverse_Iterate; - - ---------------- - -- Set_Length -- - ---------------- - - procedure Set_Length (Container : in out Vector; Length : Count_Type) is - Count : constant Count_Type'Base := Container.Length - Length; - - begin - -- Set_Length allows the user to set the length explicitly, instead - -- of implicitly as a side-effect of deletion or insertion. If the - -- requested length is less than the current length, this is equivalent - -- to deleting items from the back end of the vector. If the requested - -- length is greater than the current length, then this is equivalent - -- to inserting "space" (nonce items) at the end. - - if Count >= 0 then - Container.Delete_Last (Count); - - elsif Checks and then Container.Last >= Index_Type'Last then - raise Constraint_Error with "vector is already at its maximum length"; - - else - Container.Insert_Space (Container.Last + 1, -Count); - end if; - end Set_Length; - - ---------- - -- Swap -- - ---------- - - procedure Swap (Container : in out Vector; I, J : Index_Type) is - begin - TE_Check (Container.TC); - - if Checks then - if I > Container.Last then - raise Constraint_Error with "I index is out of range"; - end if; - - if J > Container.Last then - raise Constraint_Error with "J index is out of range"; - end if; - end if; - - if I = J then - return; - end if; - - declare - EI_Copy : constant Element_Type := Container.Elements.EA (I); - begin - Container.Elements.EA (I) := Container.Elements.EA (J); - Container.Elements.EA (J) := EI_Copy; - end; - end Swap; - - procedure Swap (Container : in out Vector; I, J : Cursor) is - begin - if Checks then - if I.Container = null then - raise Constraint_Error with "I cursor has no element"; - - elsif J.Container = null then - raise Constraint_Error with "J cursor has no element"; - - elsif I.Container /= Container'Unrestricted_Access then - raise Program_Error with "I cursor denotes wrong container"; - - elsif J.Container /= Container'Unrestricted_Access then - raise Program_Error with "J cursor denotes wrong container"; - end if; - end if; - - Swap (Container, I.Index, J.Index); - end Swap; - - --------------- - -- To_Cursor -- - --------------- - - function To_Cursor - (Container : Vector; - Index : Extended_Index) return Cursor - is - begin - if Index not in Index_Type'First .. Container.Last then - return No_Element; - else - return (Container'Unrestricted_Access, Index); - end if; - end To_Cursor; - - -------------- - -- To_Index -- - -------------- - - function To_Index (Position : Cursor) return Extended_Index is - begin - if Position.Container = null then - return No_Index; - elsif Position.Index <= Position.Container.Last then - return Position.Index; - else - return No_Index; - end if; - end To_Index; - - --------------- - -- To_Vector -- - --------------- - - function To_Vector (Length : Count_Type) return Vector is - Index : Count_Type'Base; - Last : Index_Type'Base; - Elements : Elements_Access; - - begin - if Length = 0 then - return Empty_Vector; - end if; - - -- We create a vector object with a capacity that matches the specified - -- Length, but we do not allow the vector capacity (the length of the - -- internal array) to exceed the number of values in Index_Type'Range - -- (otherwise, there would be no way to refer to those components via an - -- index). We must therefore check whether the specified Length would - -- create a Last index value greater than Index_Type'Last. - - if Index_Type'Base'Last >= Count_Type_Last then - - -- We perform a two-part test. First we determine whether the - -- computed Last value lies in the base range of the type, and then - -- determine whether it lies in the range of the index (sub)type. - - -- Last must satisfy this relation: - -- First + Length - 1 <= Last - -- We regroup terms: - -- First - 1 <= Last - Length - -- Which can rewrite as: - -- No_Index <= Last - Length - - if Checks and then - Index_Type'Base'Last - Index_Type'Base (Length) < No_Index - then - raise Constraint_Error with "Length is out of range"; - end if; - - -- We now know that the computed value of Last is within the base - -- range of the type, so it is safe to compute its value: - - Last := No_Index + Index_Type'Base (Length); - - -- Finally we test whether the value is within the range of the - -- generic actual index subtype: - - if Checks and then Last > Index_Type'Last then - raise Constraint_Error with "Length is out of range"; - end if; - - elsif Index_Type'First <= 0 then - - -- Here we can compute Last directly, in the normal way. We know that - -- No_Index is less than 0, so there is no danger of overflow when - -- adding the (positive) value of Length. - - Index := Count_Type'Base (No_Index) + Length; -- Last - - if Checks and then Index > Count_Type'Base (Index_Type'Last) then - raise Constraint_Error with "Length is out of range"; - end if; - - -- We know that the computed value (having type Count_Type) of Last - -- is within the range of the generic actual index subtype, so it is - -- safe to convert to Index_Type: - - Last := Index_Type'Base (Index); - - else - -- Here Index_Type'First (and Index_Type'Last) is positive, so we - -- must test the length indirectly (by working backwards from the - -- largest possible value of Last), in order to prevent overflow. - - Index := Count_Type'Base (Index_Type'Last) - Length; -- No_Index - - if Checks and then Index < Count_Type'Base (No_Index) then - raise Constraint_Error with "Length is out of range"; - end if; - - -- We have determined that the value of Length would not create a - -- Last index value outside of the range of Index_Type, so we can now - -- safely compute its value. - - Last := Index_Type'Base (Count_Type'Base (No_Index) + Length); - end if; - - Elements := new Elements_Type (Last); - - return Vector'(Controlled with Elements, Last, TC => <>); - end To_Vector; - - function To_Vector - (New_Item : Element_Type; - Length : Count_Type) return Vector - is - Index : Count_Type'Base; - Last : Index_Type'Base; - Elements : Elements_Access; - - begin - if Length = 0 then - return Empty_Vector; - end if; - - -- We create a vector object with a capacity that matches the specified - -- Length, but we do not allow the vector capacity (the length of the - -- internal array) to exceed the number of values in Index_Type'Range - -- (otherwise, there would be no way to refer to those components via an - -- index). We must therefore check whether the specified Length would - -- create a Last index value greater than Index_Type'Last. - - if Index_Type'Base'Last >= Count_Type_Last then - - -- We perform a two-part test. First we determine whether the - -- computed Last value lies in the base range of the type, and then - -- determine whether it lies in the range of the index (sub)type. - - -- Last must satisfy this relation: - -- First + Length - 1 <= Last - -- We regroup terms: - -- First - 1 <= Last - Length - -- Which can rewrite as: - -- No_Index <= Last - Length - - if Checks and then - Index_Type'Base'Last - Index_Type'Base (Length) < No_Index - then - raise Constraint_Error with "Length is out of range"; - end if; - - -- We now know that the computed value of Last is within the base - -- range of the type, so it is safe to compute its value: - - Last := No_Index + Index_Type'Base (Length); - - -- Finally we test whether the value is within the range of the - -- generic actual index subtype: - - if Checks and then Last > Index_Type'Last then - raise Constraint_Error with "Length is out of range"; - end if; - - elsif Index_Type'First <= 0 then - - -- Here we can compute Last directly, in the normal way. We know that - -- No_Index is less than 0, so there is no danger of overflow when - -- adding the (positive) value of Length. - - Index := Count_Type'Base (No_Index) + Length; -- same value as V.Last - - if Checks and then Index > Count_Type'Base (Index_Type'Last) then - raise Constraint_Error with "Length is out of range"; - end if; - - -- We know that the computed value (having type Count_Type) of Last - -- is within the range of the generic actual index subtype, so it is - -- safe to convert to Index_Type: - - Last := Index_Type'Base (Index); - - else - -- Here Index_Type'First (and Index_Type'Last) is positive, so we - -- must test the length indirectly (by working backwards from the - -- largest possible value of Last), in order to prevent overflow. - - Index := Count_Type'Base (Index_Type'Last) - Length; -- No_Index - - if Checks and then Index < Count_Type'Base (No_Index) then - raise Constraint_Error with "Length is out of range"; - end if; - - -- We have determined that the value of Length would not create a - -- Last index value outside of the range of Index_Type, so we can now - -- safely compute its value. - - Last := Index_Type'Base (Count_Type'Base (No_Index) + Length); - end if; - - Elements := new Elements_Type'(Last, EA => [others => New_Item]); - - return (Controlled with Elements, Last, TC => <>); - end To_Vector; - - -------------------- - -- Update_Element -- - -------------------- - - procedure Update_Element - (Container : in out Vector; - Index : Index_Type; - Process : not null access procedure (Element : in out Element_Type)) - is - Lock : With_Lock (Container.TC'Unchecked_Access); - begin - if Checks and then Index > Container.Last then - raise Constraint_Error with "Index is out of range"; - end if; - - Process (Container.Elements.EA (Index)); - end Update_Element; - - procedure Update_Element - (Container : in out Vector; - Position : Cursor; - Process : not null access procedure (Element : in out Element_Type)) - is - begin - if Checks then - if Position.Container = null then - raise Constraint_Error with "Position cursor has no element"; - elsif Position.Container /= Container'Unrestricted_Access then - raise Program_Error with "Position cursor denotes wrong container"; - end if; - end if; - - Update_Element (Container, Position.Index, Process); - end Update_Element; - - ----------- - -- Write -- - ----------- - - procedure Write - (Stream : not null access Root_Stream_Type'Class; - Container : Vector) - is - begin - Count_Type'Base'Write (Stream, Length (Container)); - - for J in Index_Type'First .. Container.Last loop - Element_Type'Write (Stream, Container.Elements.EA (J)); - end loop; - end Write; - - procedure Write - (Stream : not null access Root_Stream_Type'Class; - Position : Cursor) - is - begin - raise Program_Error with "attempt to stream vector cursor"; - end Write; - - procedure Write - (Stream : not null access Root_Stream_Type'Class; - Item : Reference_Type) - is - begin - raise Program_Error with "attempt to stream reference"; - end Write; - - procedure Write - (Stream : not null access Root_Stream_Type'Class; - Item : Constant_Reference_Type) - is - begin - raise Program_Error with "attempt to stream reference"; - end Write; - -end Ada.Containers.Vectors; diff --git a/testsuite/tests/361-overriden-runtime-specs/src/a-convec.ads b/testsuite/tests/361-overriden-runtime-specs/src/a-convec.ads deleted file mode 100644 index bbf57df52..000000000 --- a/testsuite/tests/361-overriden-runtime-specs/src/a-convec.ads +++ /dev/null @@ -1,878 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNAT LIBRARY COMPONENTS -- --- -- --- A D A . C O N T A I N E R S . V E C T O R S -- --- -- --- S p e c -- --- -- --- Copyright (C) 2004-2024, Free Software Foundation, Inc. -- --- -- --- This specification is derived from the Ada Reference Manual for use with -- --- GNAT. The copyright notice above, and the license provisions that follow -- --- apply solely to the contents of the part following the private keyword. -- --- -- --- 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- -- --- ware Foundation; either version 3, or (at your option) any later ver- -- --- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- --- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- --- or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- --- This unit was originally developed by Matthew J Heaney. -- ------------------------------------------------------------------------------- - -with Ada.Iterator_Interfaces; - -with Ada.Containers.Helpers; -private with Ada.Finalization; -private with Ada.Streams; -private with Ada.Strings.Text_Buffers; - --- The language-defined generic package Containers.Vectors provides private --- types Vector and Cursor, and a set of operations for each type. A vector --- container allows insertion and deletion at any position, but it is --- specifically optimized for insertion and deletion at the high end (the end --- with the higher index) of the container. A vector container also provides --- random access to its elements. --- --- A vector container behaves conceptually as an array that expands as --- necessary as items are inserted. The length of a vector is the number of --- elements that the vector contains. The capacity of a vector is the maximum --- number of elements that can be inserted into the vector prior to it being --- automatically expanded. --- --- Elements in a vector container can be referred to by an index value of a --- generic formal type. The first element of a vector always has its index --- value equal to the lower bound of the formal type. --- --- A vector container may contain empty elements. Empty elements do not have a --- specified value. - -generic - type Index_Type is range <>; - type Element_Type is private; - - with function "=" (Left, Right : Element_Type) return Boolean is <>; - -- The actual function for the generic formal function "=" on Element_Type - -- values is expected to define a reflexive and symmetric relationship and - -- return the same result value each time it is called with a particular - -- pair of values. If it behaves in some other manner, the functions - -- defined to use it return an unspecified value. The exact arguments and - -- number of calls of this generic formal function by the functions defined - -- to use it are unspecified. - -package Ada.Containers.Vectors with - SPARK_Mode => Off -is - pragma Annotate (CodePeer, Skip_Analysis); - pragma Preelaborate; - pragma Remote_Types; - - subtype Extended_Index is Index_Type'Base - range Index_Type'First - 1 .. - Index_Type'Min (Index_Type'Base'Last - 1, Index_Type'Last) + 1; - -- The subtype Extended_Index includes the indices covered by Index_Type - -- plus the value No_Index and, if it exists, the successor to the - -- Index_Type'Last. - - No_Index : constant Extended_Index := Extended_Index'First; - -- No_Index represents a position that does not correspond to any element. - - type Vector is tagged private - with - Constant_Indexing => Constant_Reference, - Variable_Indexing => Reference, - Default_Iterator => Iterate, - Iterator_Element => Element_Type, - Aggregate => (Empty => Empty, - Add_Unnamed => Append, - New_Indexed => New_Vector, - Assign_Indexed => Replace_Element); - - pragma Preelaborable_Initialization (Vector); - -- Vector type, to be instantiated by users of this package. If an object - -- of type Vector is not otherwise initialized, it is initialized to - -- Empty_Vector. - - type Cursor is private; - pragma Preelaborable_Initialization (Cursor); - -- Cursor pointing into an instance of vector. If an object of type Cursor - -- is not otherwise initialized, it is initialized to No_Element - - No_Element : constant Cursor; - -- No_Element represents a cursor that designates no element. - - function Has_Element (Position : Cursor) return Boolean; - -- Returns True if Position designates an element, and returns False - -- otherwise. - - package Vector_Iterator_Interfaces is new - Ada.Iterator_Interfaces (Cursor, Has_Element); - - Empty_Vector : constant Vector; - -- Empty_Vector represents the empty vector object. It has a length of 0. - - function Empty (Capacity : Count_Type := 10) return Vector; - - overriding function "=" (Left, Right : Vector) return Boolean; - -- If Left and Right denote the same vector object, then the function - -- returns True. If Left and Right have different lengths, then the - -- function returns False. Otherwise, it compares each element in Left to - -- the corresponding element in Right using the generic formal equality - -- operator. If any such comparison returns False, the function returns - -- False; otherwise it returns True. Any exception raised during evaluation - -- of element equality is propagated. - - function To_Vector (Length : Count_Type) return Vector; - -- Returns a vector with a length of Length, filled with empty elements. - - function To_Vector - (New_Item : Element_Type; - Length : Count_Type) return Vector; - -- Returns a vector with a length of Length, filled with elements - -- initialized to the value New_Item. - - function "&" (Left, Right : Vector) return Vector; - -- Returns a vector comprising the elements of Left followed by the - -- elements of Right. - - function "&" (Left : Vector; Right : Element_Type) return Vector; - -- Returns a vector comprising the elements of Left followed by the element - -- Right. - - function "&" (Left : Element_Type; Right : Vector) return Vector; - -- Returns a vector comprising the element Left followed by the elements of - -- Right. - - function "&" (Left, Right : Element_Type) return Vector; - -- Returns a vector comprising the element Left followed by the element - -- Right. - - function Capacity (Container : Vector) return Count_Type; - -- Returns the capacity of Container. - - procedure Reserve_Capacity - (Container : in out Vector; - Capacity : Count_Type); - -- Reserve_Capacity allocates new internal data structures such that the - -- length of the resulting vector can become at least the value Capacity - -- without requiring an additional call to Reserve_Capacity, and is large - -- enough to hold the current length of Container. Reserve_Capacity then - -- copies the elements into the new data structures and deallocates the old - -- data structures. Any exception raised during allocation is propagated - -- and Container is not modified. - - function Length (Container : Vector) return Count_Type; - -- Returns the number of elements in Container. - - procedure Set_Length - (Container : in out Vector; - Length : Count_Type); - -- If Length is larger than the capacity of Container, Set_Length calls - -- Reserve_Capacity (Container, Length), then sets the length of the - -- Container to Length. If Length is greater than the original length of - -- Container, empty elements are added to Container; otherwise elements are - -- removed from Container. - - function Is_Empty (Container : Vector) return Boolean; - -- Equivalent to Length (Container) = 0. - - procedure Clear (Container : in out Vector); - -- Removes all the elements from Container. The capacity of Container does - -- not change. - - function To_Cursor - (Container : Vector; - Index : Extended_Index) return Cursor; - -- If Index is not in the range First_Index (Container) .. Last_Index - -- (Container), then No_Element is returned. Otherwise, a cursor - -- designating the element at position Index in Container is returned. - - function To_Index (Position : Cursor) return Extended_Index; - -- If Position is No_Element, No_Index is returned. Otherwise, the index - -- (within its containing vector) of the element designated by Position is - -- returned. - - function Element - (Container : Vector; - Index : Index_Type) return Element_Type; - -- If Index is not in the range First_Index (Container) .. Last_Index - -- (Container), then Constraint_Error is propagated. Otherwise, Element - -- returns the element at position Index. - - function Element (Position : Cursor) return Element_Type; - -- If Position equals No_Element, then Constraint_Error is propagated. - -- Otherwise, Element returns the element designated by Position. - - procedure Replace_Element - (Container : in out Vector; - Index : Index_Type; - New_Item : Element_Type); - -- If Index is not in the range First_Index (Container) .. Last_Index - -- (Container), then Constraint_Error is propagated. Otherwise - -- Replace_Element assigns the value New_Item to the element at position - -- Index. Any exception raised during the assignment is propagated. The - -- element at position Index is not an empty element after successful call - -- to Replace_Element. - - procedure Replace_Element - (Container : in out Vector; - Position : Cursor; - New_Item : Element_Type); - -- If Position equals No_Element, then Constraint_Error is propagated; if - -- Position does not designate an element in Container, then Program_Error - -- is propagated. Otherwise Replace_Element assigns New_Item to the element - -- designated by Position. Any exception raised during the assignment is - -- propagated. The element at Position is not an empty element after - -- successful call to Replace_Element. - - procedure Query_Element - (Container : Vector; - Index : Index_Type; - Process : not null access procedure (Element : Element_Type)); - -- If Index is not in the range First_Index (Container) .. Last_Index - -- (Container), then Constraint_Error is propagated. Otherwise, - -- Query_Element calls Process.all with the element at position Index as - -- the argument. Program_Error is propagated if Process.all tampers with - -- the elements of Container. Any exception raised by Process.all is - -- propagated. - - procedure Query_Element - (Position : Cursor; - Process : not null access procedure (Element : Element_Type)); - -- If Position equals No_Element, then Constraint_Error is propagated. - -- Otherwise, Query_Element calls Process.all with the element designated - -- by Position as the argument. Program_Error is propagated if Process.all - -- tampers with the elements of Container. Any exception raised by - -- Process.all is propagated. - - procedure Update_Element - (Container : in out Vector; - Index : Index_Type; - Process : not null access procedure (Element : in out Element_Type)); - -- If Index is not in the range First_Index (Container) .. Last_Index - -- (Container), then Constraint_Error is propagated. Otherwise, - -- Update_Element calls Process.all with the element at position Index as - -- the argument. Program_Error is propagated if Process.all tampers with - -- the elements of Container. Any exception raised by Process.all is - -- propagated. - -- - -- If Element_Type is unconstrained and definite, then the actual Element - -- parameter of Process.all shall be unconstrained. - -- - -- The element at position Index is not an empty element after successful - -- completion of this operation. - - procedure Update_Element - (Container : in out Vector; - Position : Cursor; - Process : not null access procedure (Element : in out Element_Type)); - -- If Position equals No_Element, then Constraint_Error is propagated; if - -- Position does not designate an element in Container, then Program_Error - -- is propagated. Otherwise Update_Element calls Process.all with the - -- element designated by Position as the argument. Program_Error is - -- propagated if Process.all tampers with the elements of Container. Any - -- exception raised by Process.all is propagated. - -- - -- If Element_Type is unconstrained and definite, then the actual Element - -- parameter of Process.all shall be unconstrained. - -- - -- The element designated by Position is not an empty element after - -- successful completion of this operation. - - type Constant_Reference_Type - (Element : not null access constant Element_Type) is - private - with - Implicit_Dereference => Element; - - type Reference_Type (Element : not null access Element_Type) is private - with - Implicit_Dereference => Element; - - function Constant_Reference - (Container : aliased Vector; - Position : Cursor) return Constant_Reference_Type; - pragma Inline (Constant_Reference); - - function Reference - (Container : aliased in out Vector; - Position : Cursor) return Reference_Type; - pragma Inline (Reference); - - function Constant_Reference - (Container : aliased Vector; - Index : Index_Type) return Constant_Reference_Type; - pragma Inline (Constant_Reference); - - function Reference - (Container : aliased in out Vector; - Index : Index_Type) return Reference_Type; - pragma Inline (Reference); - - procedure Assign (Target : in out Vector; Source : Vector); - - function Copy (Source : Vector; Capacity : Count_Type := 0) return Vector; - - procedure Move (Target : in out Vector; Source : in out Vector); - -- If Target denotes the same object as Source, then Move has no effect. - -- Otherwise, Move first calls Clear (Target); then, each element from - -- Source is removed from Source and inserted into Target in the original - -- order. The length of Source is 0 after a successful call to Move. - - function New_Vector (First, Last : Index_Type) return Vector - with Pre => First = Index_Type'First; - -- Ada 2022 aggregate operation. - - procedure Insert_Vector - (Container : in out Vector; - Before : Extended_Index; - New_Item : Vector); - -- If Before is not in the range First_Index (Container) .. Last_Index - -- (Container) + 1, then Constraint_Error is propagated. If - -- Length(New_Item) is 0, then Insert_Vector does nothing. Otherwise, it - -- computes the new length NL as the sum of the current length and Length - -- (New_Item); if the value of Last appropriate for length NL would be - -- greater than Index_Type'Last then Constraint_Error is propagated. - -- - -- If the current vector capacity is less than NL, Reserve_Capacity - -- (Container, NL) is called to increase the vector capacity. Then - -- Insert_Vector slides the elements in the range Before .. Last_Index - -- (Container) up by Length(New_Item) positions, and then copies the - -- elements of New_Item to the positions starting at Before. Any exception - -- raised during the copying is propagated. - - procedure Insert - (Container : in out Vector; - Before : Extended_Index; - New_Item : Vector) renames Insert_Vector; - -- Retained for now for compatibility; AI12-0400 will remove this. - - procedure Insert_Vector - (Container : in out Vector; - Before : Cursor; - New_Item : Vector); - -- If Before is not No_Element, and does not designate an element in - -- Container, then Program_Error is propagated. Otherwise, if - -- Length(New_Item) is 0, then Insert_Vector does nothing. If Before is - -- No_Element, then the call is equivalent to Insert_Vector (Container, - -- Last_Index (Container) + 1, New_Item); otherwise the call is equivalent - -- to Insert_Vector (Container, To_Index (Before), New_Item); - - procedure Insert - (Container : in out Vector; - Before : Cursor; - New_Item : Vector) renames Insert_Vector; - -- Retained for now for compatibility; AI12-0400 will remove this. - - procedure Insert_Vector - (Container : in out Vector; - Before : Cursor; - New_Item : Vector; - Position : out Cursor); - -- If Before is not No_Element, and does not designate an element in - -- Container, then Program_Error is propagated. If Before equals - -- No_Element, then let T be Last_Index (Container) + 1; otherwise, let T - -- be To_Index (Before). Insert_Vector (Container, T, New_Item) is called, - -- and then Position is set to To_Cursor (Container, T). - - procedure Insert - (Container : in out Vector; - Before : Cursor; - New_Item : Vector; - Position : out Cursor) renames Insert_Vector; - -- Retained for now for compatibility; AI12-0400 will remove this. - - procedure Insert - (Container : in out Vector; - Before : Extended_Index; - New_Item : Element_Type; - Count : Count_Type := 1); - -- Equivalent to: - -- Insert_Vector (Container, Before, To_Vector (New_Item, Count)); - - procedure Insert - (Container : in out Vector; - Before : Cursor; - New_Item : Element_Type; - Count : Count_Type := 1); - -- Equivalent to: - -- Insert_Vector (Container, Before, To_Vector (New_Item, Count)); - - procedure Insert - (Container : in out Vector; - Before : Cursor; - New_Item : Element_Type; - Position : out Cursor; - Count : Count_Type := 1); - -- Equivalent to - -- Insert_Vector (Container, Before, To_Vector (New_Item, Count), Position) - - procedure Insert - (Container : in out Vector; - Before : Extended_Index; - Count : Count_Type := 1); - -- If Before is not in the range First_Index (Container) .. Last_Index - -- (Container) + 1, then Constraint_Error is propagated. If Count is 0, - -- then Insert does nothing. Otherwise, it computes the new length NL as - -- the sum of the current length and Count; if the value of Last - -- appropriate for length NL would be greater than Index_Type'Last then - -- Constraint_Error is propagated. - -- - -- If the current vector capacity is less than NL, Reserve_Capacity - -- (Container, NL) is called to increase the vector capacity. Then Insert - -- slides the elements in the range Before .. Last_Index (Container) up by - -- Count positions, and then inserts elements that are initialized by - -- default (see 3.3.1) in the positions starting at Before. - - procedure Insert - (Container : in out Vector; - Before : Cursor; - Position : out Cursor; - Count : Count_Type := 1); - -- If Before is not No_Element, and does not designate an element in - -- Container, then Program_Error is propagated. If Before equals - -- No_Element, then let T be Last_Index (Container) + 1; otherwise, let T - -- be To_Index (Before). Insert (Container, T, Count) is called, and then - -- Position is set to To_Cursor (Container, T). - - procedure Prepend_Vector - (Container : in out Vector; - New_Item : Vector); - -- Equivalent to Insert (Container, First_Index (Container), New_Item). - - procedure Prepend - (Container : in out Vector; - New_Item : Vector) renames Prepend_Vector; - -- Retained for now for compatibility; AI12-0400 will remove this. - - procedure Prepend - (Container : in out Vector; - New_Item : Element_Type; - Count : Count_Type := 1); - -- Equivalent to Insert (Container, First_Index (Container), New_Item, - -- Count). - - procedure Append_Vector - (Container : in out Vector; - New_Item : Vector); - -- Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item). - - procedure Append - (Container : in out Vector; - New_Item : Vector) renames Append_Vector; - -- Retained for now for compatibility; AI12-0400 will remove this. - - procedure Append - (Container : in out Vector; - New_Item : Element_Type; - Count : Count_Type); - -- Equivalent to Insert (Container, Last_Index (Container) + 1, New_Item, - -- Count). - - procedure Append (Container : in out Vector; - New_Item : Element_Type); - - procedure Insert_Space - (Container : in out Vector; - Before : Extended_Index; - Count : Count_Type := 1); - -- If Before is not in the range First_Index (Container) .. Last_Index - -- (Container) + 1, then Constraint_Error is propagated. If Count is 0, - -- then Insert_Space does nothing. Otherwise, it computes the new length NL - -- as the sum of the current length and Count; if the value of Last - -- appropriate for length NL would be greater than Index_Type'Last then - -- Constraint_Error is propagated. - -- - -- If the current vector capacity is less than NL, Reserve_Capacity - -- (Container, NL) is called to increase the vector capacity. Then - -- Insert_Space slides the elements in the range Before .. Last_Index - -- (Container) up by Count positions, and then inserts empty elements in - -- the positions starting at Before. - - procedure Insert_Space - (Container : in out Vector; - Before : Cursor; - Position : out Cursor; - Count : Count_Type := 1); - -- If Before is not No_Element, and does not designate an element in - -- Container, then Program_Error is propagated. If Before equals - -- No_Element, then let T be Last_Index (Container) + 1; otherwise, let T - -- be To_Index (Before). Insert_Space (Container, T, Count) is called, and - -- then Position is set to To_Cursor (Container, T). - - procedure Delete - (Container : in out Vector; - Index : Extended_Index; - Count : Count_Type := 1); - -- If Index is not in the range First_Index (Container) .. Last_Index - -- (Container) + 1, then Constraint_Error is propagated. If Count is 0, - -- Delete has no effect. Otherwise Delete slides the elements (if any) - -- starting at position Index + Count down to Index. Any exception raised - -- during element assignment is propagated. - - procedure Delete - (Container : in out Vector; - Position : in out Cursor; - Count : Count_Type := 1); - -- If Position equals No_Element, then Constraint_Error is propagated. If - -- Position does not designate an element in Container, then Program_Error - -- is propagated. Otherwise, Delete (Container, To_Index (Position), Count) - -- is called, and then Position is set to No_Element. - - procedure Delete_First - (Container : in out Vector; - Count : Count_Type := 1); - -- Equivalent to Delete (Container, First_Index (Container), Count). - - procedure Delete_Last - (Container : in out Vector; - Count : Count_Type := 1); - -- If Length (Container) <= Count then Delete_Last is equivalent to Clear - -- (Container). Otherwise it is equivalent to Delete (Container, - -- Index_Type'Val(Index_Type'Pos(Last_Index (Container)) - Count + 1), - -- Count). - - procedure Reverse_Elements (Container : in out Vector); - -- Reorders the elements of Container in reverse order. - - procedure Swap (Container : in out Vector; I, J : Index_Type); - -- If either I or J is not in the range First_Index (Container) .. - -- Last_Index (Container), then Constraint_Error is propagated. Otherwise, - -- Swap exchanges the values of the elements at positions I and J. - - procedure Swap (Container : in out Vector; I, J : Cursor); - -- If either I or J is No_Element, then Constraint_Error is propagated. If - -- either I or J do not designate an element in Container, then - -- Program_Error is propagated. Otherwise, Swap exchanges the values of the - -- elements designated by I and J. - - function First_Index (Container : Vector) return Index_Type; - -- Returns the value Index_Type'First. - - function First (Container : Vector) return Cursor; - -- If Container is empty, First returns No_Element. Otherwise, it returns a - -- cursor that designates the first element in Container. - - function First_Element (Container : Vector) return Element_Type; - -- Equivalent to Element (Container, First_Index (Container)). - - function Last_Index (Container : Vector) return Extended_Index; - -- If Container is empty, Last_Index returns No_Index. Otherwise, it - -- returns the position of the last element in Container. - - function Last (Container : Vector) return Cursor; - -- If Container is empty, Last returns No_Element. Otherwise, it returns a - -- cursor that designates the last element in Container. - - function Last_Element (Container : Vector) return Element_Type; - -- Equivalent to Element (Container, Last_Index (Container)). - - function Next (Position : Cursor) return Cursor; - -- If Position equals No_Element or designates the last element of the - -- container, then Next returns the value No_Element. Otherwise, it returns - -- a cursor that designates the element with index To_Index (Position) + 1 - -- in the same vector as Position. - - procedure Next (Position : in out Cursor); - -- Equivalent to Position := Next (Position). - - function Previous (Position : Cursor) return Cursor; - -- If Position equals No_Element or designates the first element of the - -- container, then Previous returns the value No_Element. Otherwise, it - -- returns a cursor that designates the element with index To_Index - -- (Position) - 1 in the same vector as Position. - - procedure Previous (Position : in out Cursor); - -- Equivalent to Position := Previous (Position). - - function Find_Index - (Container : Vector; - Item : Element_Type; - Index : Index_Type := Index_Type'First) return Extended_Index; - -- Searches the elements of Container for an element equal to Item (using - -- the generic formal equality operator). The search starts at position - -- Index and proceeds towards Last_Index (Container). If no equal - -- element is found, then Find_Index returns No_Index. Otherwise, it - -- returns the index of the first equal element encountered. - - function Find - (Container : Vector; - Item : Element_Type; - Position : Cursor := No_Element) return Cursor; - -- If Position is not No_Element, and does not designate an element in - -- Container, then Program_Error is propagated. Otherwise Find searches - -- the elements of Container for an element equal to Item (using the - -- generic formal equality operator). The search starts at the first - -- element if Position equals No_Element, and at the element designated - -- by Position otherwise. It proceeds towards the last element of - -- Container. If no equal element is found, then Find returns - -- No_Element. Otherwise, it returns a cursor designating the first - -- equal element encountered. - - function Reverse_Find_Index - (Container : Vector; - Item : Element_Type; - Index : Index_Type := Index_Type'Last) return Extended_Index; - -- Searches the elements of Container for an element equal to Item (using - -- the generic formal equality operator). The search starts at position - -- Index or, if Index is greater than Last_Index (Container), at - -- position Last_Index (Container). It proceeds towards First_Index - -- (Container). If no equal element is found, then Reverse_Find_Index - -- returns No_Index. Otherwise, it returns the index of the first equal - -- element encountered. - - function Reverse_Find - (Container : Vector; - Item : Element_Type; - Position : Cursor := No_Element) return Cursor; - -- If Position is not No_Element, and does not designate an element in - -- Container, then Program_Error is propagated. Otherwise Reverse_Find - -- searches the elements of Container for an element equal to Item - -- (using the generic formal equality operator). The search starts at - -- the last element if Position equals No_Element, and at the element - -- designated by Position otherwise. It proceeds towards the first - -- element of Container. If no equal element is found, then Reverse_Find - -- returns No_Element. Otherwise, it returns a cursor designating the - -- first equal element encountered. - - function Contains - (Container : Vector; - Item : Element_Type) return Boolean; - -- Equivalent to Has_Element (Find (Container, Item)). - - procedure Iterate - (Container : Vector; - Process : not null access procedure (Position : Cursor)); - -- Invokes Process.all with a cursor that designates each element in - -- Container, in index order. Program_Error is propagated if Process.all - -- tampers with the cursors of Container. Any exception raised by Process - -- is propagated. - - procedure Reverse_Iterate - (Container : Vector; - Process : not null access procedure (Position : Cursor)); - -- Iterates over the elements in Container as per Iterate, except that - -- elements are traversed in reverse index order. - -- - - function Iterate (Container : Vector) - return Vector_Iterator_Interfaces.Reversible_Iterator'Class; - - function Iterate (Container : Vector; Start : Cursor) - return Vector_Iterator_Interfaces.Reversible_Iterator'Class; - - generic - with function "<" (Left, Right : Element_Type) return Boolean is <>; - -- The actual function for the generic formal function "<" of - -- Generic_Sorting is expected to return the same value each time it is - -- called with a particular pair of element values. It should define a - -- strict ordering relationship, that is, be irreflexive, asymmetric, - -- and transitive; it should not modify Container. If the actual for "<" - -- behaves in some other manner, the behavior of the subprograms of - -- Generic_Sorting are unspecified. How many times the subprograms of - -- Generic_Sorting call "<" is unspecified. - package Generic_Sorting is - - function Is_Sorted (Container : Vector) return Boolean; - -- Returns True if the elements are sorted smallest first as determined - -- by the generic formal "<" operator; otherwise, Is_Sorted returns - -- False. Any exception raised during evaluation of "<" is propagated. - - procedure Sort (Container : in out Vector); - -- Reorders the elements of Container such that the elements are sorted - -- smallest first as determined by the generic formal "<" operator - -- provided. Any exception raised during evaluation of "<" is - -- propagated. - - procedure Merge (Target : in out Vector; Source : in out Vector); - -- Merge removes elements from Source and inserts them into Target; - -- afterwards, Target contains the union of the elements that were - -- initially in Source and Target; Source is left empty. If Target and - -- Source are initially sorted smallest first, then Target is ordered - -- smallest first as determined by the generic formal "<" operator; - -- otherwise, the order of elements in Target is unspecified. Any - -- exception raised during evaluation of "<" is propagated. - - end Generic_Sorting; - -private - - pragma Inline (Append); - pragma Inline (First_Index); - pragma Inline (Last_Index); - pragma Inline (Element); - pragma Inline (First_Element); - pragma Inline (Last_Element); - pragma Inline (Query_Element); - pragma Inline (Update_Element); - pragma Inline (Replace_Element); - pragma Inline (Is_Empty); - pragma Inline (Contains); - pragma Inline (Next); - pragma Inline (Previous); - - use Ada.Containers.Helpers; - package Implementation is new Generic_Implementation; - use Implementation; - - type Elements_Array is array (Index_Type range <>) of aliased Element_Type; - function "=" (L, R : Elements_Array) return Boolean is abstract; - - type Elements_Type (Last : Extended_Index) is limited record - EA : Elements_Array (Index_Type'First .. Last); - end record; - - type Elements_Access is access all Elements_Type; - - use Finalization; - use Streams; - - type Vector is new Controlled with record - Elements : Elements_Access := null; - Last : Extended_Index := No_Index; - TC : aliased Tamper_Counts; - end record with Put_Image => Put_Image; - - procedure Put_Image - (S : in out Ada.Strings.Text_Buffers.Root_Buffer_Type'Class; V : Vector); - - overriding procedure Adjust (Container : in out Vector); - overriding procedure Finalize (Container : in out Vector); - - procedure Write - (Stream : not null access Root_Stream_Type'Class; - Container : Vector); - - for Vector'Write use Write; - - procedure Read - (Stream : not null access Root_Stream_Type'Class; - Container : out Vector); - - for Vector'Read use Read; - - type Vector_Access is access all Vector; - for Vector_Access'Storage_Size use 0; - - type Cursor is record - Container : Vector_Access; - Index : Index_Type := Index_Type'First; - end record; - - procedure Read - (Stream : not null access Root_Stream_Type'Class; - Position : out Cursor); - - for Cursor'Read use Read; - - procedure Write - (Stream : not null access Root_Stream_Type'Class; - Position : Cursor); - - for Cursor'Write use Write; - - subtype Reference_Control_Type is Implementation.Reference_Control_Type; - -- It is necessary to rename this here, so that the compiler can find it - - type Constant_Reference_Type - (Element : not null access constant Element_Type) is - record - Control : Reference_Control_Type := - raise Program_Error with "uninitialized reference"; - -- The RM says, "The default initialization of an object of - -- type Constant_Reference_Type or Reference_Type propagates - -- Program_Error." - end record; - - procedure Write - (Stream : not null access Root_Stream_Type'Class; - Item : Constant_Reference_Type); - - for Constant_Reference_Type'Write use Write; - - procedure Read - (Stream : not null access Root_Stream_Type'Class; - Item : out Constant_Reference_Type); - - for Constant_Reference_Type'Read use Read; - - type Reference_Type - (Element : not null access Element_Type) is - record - Control : Reference_Control_Type := - raise Program_Error with "uninitialized reference"; - -- The RM says, "The default initialization of an object of - -- type Constant_Reference_Type or Reference_Type propagates - -- Program_Error." - end record; - - procedure Write - (Stream : not null access Root_Stream_Type'Class; - Item : Reference_Type); - - for Reference_Type'Write use Write; - - procedure Read - (Stream : not null access Root_Stream_Type'Class; - Item : out Reference_Type); - - for Reference_Type'Read use Read; - - -- Three operations are used to optimize the expansion of "for ... of" - -- loops: the Next(Cursor) (or Previous) procedure in the visible part, - -- and the following Pseudo_Reference and Get_Element_Access functions. - -- See Exp_Ch5 for details, including the leading underscores here. - - procedure _Next (Position : in out Cursor) renames Next; - procedure _Previous (Position : in out Cursor) renames Previous; - - function Pseudo_Reference - (Container : aliased Vector'Class) return Reference_Control_Type; - pragma Inline (Pseudo_Reference); - -- Creates an object of type Reference_Control_Type pointing to the - -- container, and increments the Lock. Finalization of this object will - -- decrement the Lock. - - type Element_Access is access all Element_Type; - - function Get_Element_Access - (Position : Cursor) return not null Element_Access; - -- Returns a pointer to the element designated by Position. - - No_Element : constant Cursor := Cursor'(null, Index_Type'First); - - Empty_Vector : constant Vector := (Controlled with others => <>); - - type Iterator is new Limited_Controlled and - Vector_Iterator_Interfaces.Reversible_Iterator with - record - Container : Vector_Access; - Index : Index_Type'Base; - end record - with Disable_Controlled => not T_Check; - - overriding procedure Finalize (Object : in out Iterator); - - overriding function First (Object : Iterator) return Cursor; - overriding function Last (Object : Iterator) return Cursor; - - overriding function Next - (Object : Iterator; - Position : Cursor) return Cursor; - - overriding function Previous - (Object : Iterator; - Position : Cursor) return Cursor; - -end Ada.Containers.Vectors; diff --git a/testsuite/tests/361-overriden-runtime-specs/src/a-numaux.adb b/testsuite/tests/361-overriden-runtime-specs/src/a-numaux.adb new file mode 100644 index 000000000..2e04cce51 --- /dev/null +++ b/testsuite/tests/361-overriden-runtime-specs/src/a-numaux.adb @@ -0,0 +1,6 @@ +package body Ada.Numerics.Aux is + procedure Dummy is + begin + null; + end Dummy; +end Ada.Numerics.Aux; diff --git a/testsuite/tests/361-overriden-runtime-specs/src/a-numaux.ads b/testsuite/tests/361-overriden-runtime-specs/src/a-numaux.ads new file mode 100644 index 000000000..772e0bdf7 --- /dev/null +++ b/testsuite/tests/361-overriden-runtime-specs/src/a-numaux.ads @@ -0,0 +1,8 @@ +package Ada.Numerics.Aux is + pragma Pure; + pragma Elaborate_Body; + + procedure Dummy; + + Not_Pi : constant := 123456; +end Ada.Numerics.Aux; diff --git a/testsuite/tests/361-overriden-runtime-specs/src/main.adb b/testsuite/tests/361-overriden-runtime-specs/src/main.adb index 93b1f559c..77d8b9b10 100644 --- a/testsuite/tests/361-overriden-runtime-specs/src/main.adb +++ b/testsuite/tests/361-overriden-runtime-specs/src/main.adb @@ -1,11 +1,7 @@ -with Ada.Containers.Vectors; +with Ada.Numerics.Aux; +with Ada.Text_IO; use Ada.Text_IO; procedure Main is - package Int_Vectors is new Ada.Containers.Vectors - (Index_Type => Natural, - Element_Type => Integer); - - V : Int_Vectors.Vector; begin - V.Append (3); + Put_Line (Integer'Image (Ada.Numerics.Aux.Not_Pi)); end Main; diff --git a/testsuite/tests/361-overriden-runtime-specs/test.opt b/testsuite/tests/361-overriden-runtime-specs/test.opt new file mode 100644 index 000000000..ecdddeecc --- /dev/null +++ b/testsuite/tests/361-overriden-runtime-specs/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Compilation can't handle overloaded unit diff --git a/testsuite/tests/361-overriden-runtime-specs/test.py b/testsuite/tests/361-overriden-runtime-specs/test.py index cced46315..b7035dac3 100644 --- a/testsuite/tests/361-overriden-runtime-specs/test.py +++ b/testsuite/tests/361-overriden-runtime-specs/test.py @@ -1,10 +1,8 @@ """ This test checks that we have no warning when instrumenting a project -that redefines some runtime files, here a-convec.ad[sb] +that redefines some runtime files, here a-numaux.ad[sb] """ -import re - from SCOV.minicheck import build_and_run from SUITE.context import thistest from SUITE.cutils import contents_of, Wdir @@ -21,27 +19,24 @@ ), mains=["main"], covlevel="stmt", - extra_coverage_args=["-v"], - quiet=False, + extra_gprbuild_args=["-gnatg"], + extra_coverage_args=[], ) # Ensure `gnatcov instrument` did not confuse runtime files -warn_regexp = re.compile( - r".*Warning: same base name for files:\n.*a-convec\.ads\n.*a-convec\.ads.*", # noqa: E501 - flags=re.S, -) -thistest.fail_if_match( - "Warning found in instrumentation output, gnatcov used both overriden " - "and original runtime files", - warn_regexp, - contents_of("instrument.log"), -) +# (Do not run this check on bin-traces) +if thistest.options.trace_mode != "bin": + thistest.fail_if_not_equal( + "Expected empty instrumentation output, but a warning/error was found", + "", + contents_of("instrument.log"), + ) # Ensure the overridden runtime file was used # (i.e. calling Vector.Append prints Toto) -thistest.fail_if_no_match( - "call to Vector.Append shall print 'Toto'", - "Toto", +thistest.fail_if_not_equal( + "If the right a-numaux.ads is used, it will print 123456", + " 123456\n", contents_of("main_output.txt"), ) From 829fb680da31c2ecab746f304ec5e12d0a2a9020 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 9 Jan 2025 14:07:08 +0000 Subject: [PATCH 1074/1483] instrument-ada_unit.adb: always go through our `Get_From_File` wrapper `Replace_Manual_Indications` and `Insert_With_Dump_Helper` both call `Libadalang.Analysis.Get_From_File` directly, which shortcuts our mechanism to create a fresh context every N parsed source file (which is an attempt to keep memory usage at acceptable levels). Use our `Get_From_File` wrapper instead, like in the rest of the codebase, to always use this mechanism. No change of behavior expected except reducing the memory usage of `gnatcov instrument`. --- tools/gnatcov/instrument-ada_unit.adb | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 56e4f2a38..5654257ee 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -1356,7 +1356,9 @@ package body Instrument.Ada_Unit is function Get_From_File (Instrumenter : in out Ada_Instrumenter_Type'Class; - Filename : String) return Libadalang.Analysis.Analysis_Unit; + Filename : String; + Reparse : Boolean := False) + return Libadalang.Analysis.Analysis_Unit; -- Fetch the analysis unit for the given filename ------------------------- @@ -8412,8 +8414,9 @@ package body Instrument.Ada_Unit is function Get_From_File (Instrumenter : in out Ada_Instrumenter_Type'Class; - Filename : String) return Libadalang.Analysis.Analysis_Unit - is + Filename : String; + Reparse : Boolean := False) + return Libadalang.Analysis.Analysis_Unit is begin -- If we exceeded the maximum number of calls to Get_From_File, start -- with a new context. @@ -8424,7 +8427,7 @@ package body Instrument.Ada_Unit is Instrumenter.Get_From_File_Count := Instrumenter.Get_From_File_Count + 1; - return Instrumenter.Context.Get_From_File (Filename); + return Instrumenter.Context.Get_From_File (Filename, Reparse => Reparse); end Get_From_File; ------------------------------------------- @@ -9468,7 +9471,7 @@ package body Instrument.Ada_Unit is then Instrumented_Filename else Source_Filename); Unit : constant Libadalang.Analysis.Analysis_Unit := - Self.Context.Get_From_File (File_To_Search); + Get_From_File (Self, File_To_Search); Rewriter : Ada_Source_Rewriter; External_Annotations : Instr_Annotation_Map; @@ -9809,7 +9812,7 @@ package body Instrument.Ada_Unit is then Instrumented_Filename else Source_Filename); Unit : constant Libadalang.Analysis.Analysis_Unit := - Self.Context.Get_From_File (File_To_Search, Reparse => True); + Get_From_File (Self, File_To_Search, Reparse => True); Rewriter : Ada_Source_Rewriter; From 162b3927a5c7ecf12ec3c747aeb91371f00ad7ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Mon, 13 Jan 2025 10:59:54 +0100 Subject: [PATCH 1075/1483] issue-361: Fix test for src mode in embedded runtimes --- testsuite/tests/361-overriden-runtime-specs/test.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/361-overriden-runtime-specs/test.py b/testsuite/tests/361-overriden-runtime-specs/test.py index b7035dac3..a565a2d01 100644 --- a/testsuite/tests/361-overriden-runtime-specs/test.py +++ b/testsuite/tests/361-overriden-runtime-specs/test.py @@ -33,10 +33,11 @@ ) # Ensure the overridden runtime file was used -# (i.e. calling Vector.Append prints Toto) -thistest.fail_if_not_equal( +# On embedded targets, a source trace file will be dumped after the expected +# output. That's why we use a regex. +thistest.fail_if_no_match( "If the right a-numaux.ads is used, it will print 123456", - " 123456\n", + r"^ 123456\n(== GNATcoverage source trace file ==.*== End ==\n)?", contents_of("main_output.txt"), ) From dfd55e0cd0e05aa51098705280c5c5d2ce5eaf05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 15 Jan 2025 16:19:26 +0100 Subject: [PATCH 1076/1483] N429-018-c-void-ternary: Fix implicit function declaration The warning has now become a compilation error under gcc-14, thus making the test fail. --- testsuite/tests/N429-018-c-void-ternary/src/test_foo_0.c | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/N429-018-c-void-ternary/src/test_foo_0.c b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_0.c index 61d101f93..caa7e38bf 100644 --- a/testsuite/tests/N429-018-c-void-ternary/src/test_foo_0.c +++ b/testsuite/tests/N429-018-c-void-ternary/src/test_foo_0.c @@ -1,4 +1,5 @@ #include "foo.h" +#include "helpers.h" int main (void) From 8d88767a3902309ef560009b84ce78e66997c89a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Tue, 21 Jan 2025 15:41:22 +0100 Subject: [PATCH 1077/1483] ci: Fix precommit issues --- testsuite/SCOV/expgen/context.py | 61 ++++++++++--------- .../SCOV/expgen/generator/composition.py | 4 +- testsuite/SCOV/expgen/generator/parsing.py | 8 +-- testsuite/SCOV/expgen/language/__init__.py | 6 +- .../SCOV/expgen/language/ada/__init__.py | 44 ++++++------- testsuite/SCOV/expgen/language/ada/context.py | 14 ++--- testsuite/SCOV/expgen/language/c/__init__.py | 44 ++++++------- testsuite/SCOV/expgen/language/c/context.py | 4 +- testsuite/SCOV/expgen/operand.py | 44 ++++++------- testsuite/SCOV/expgen/{ast.py => syntax.py} | 0 testsuite/SCOV/expgen/topology.py | 16 ++--- testsuite/SCOV/expgen/utils.py | 33 +++++----- testsuite/SCOV/internals/rnexpanders.py | 2 +- 13 files changed, 143 insertions(+), 137 deletions(-) rename testsuite/SCOV/expgen/{ast.py => syntax.py} (100%) diff --git a/testsuite/SCOV/expgen/context.py b/testsuite/SCOV/expgen/context.py index a5fedb5e2..bb6c673bd 100644 --- a/testsuite/SCOV/expgen/context.py +++ b/testsuite/SCOV/expgen/context.py @@ -3,7 +3,7 @@ """Expose contexts suitable for decisions.""" -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax class Context(object): @@ -39,15 +39,15 @@ def __init__(self): self.language = self.LANGUAGE def get_program(self, decision_expr): - return ast.Program( - [], [ast.XContext(self.LANGUAGE, self.FORMAT, decision_expr)] + return syntax.Program( + [], [syntax.XContext(self.LANGUAGE, self.FORMAT, decision_expr)] ) # Tag for statements whose execution depends on the outcome of the decision # expression. -ON_TRUE_TAG = ast.Tag("on-true", None, None) -ON_FALSE_TAG = ast.Tag("on-false", None, None) +ON_TRUE_TAG = syntax.Tag("on-true", None, None) +ON_FALSE_TAG = syntax.Tag("on-false", None, None) class Call(Context): @@ -58,22 +58,22 @@ class Call(Context): The user must provide an implementation for this function. """ "" - TAG_CONTEXT = ast.TagTypes.EXPRESSION + TAG_CONTEXT = syntax.TagTypes.EXPRESSION def get_program(self, param): temp_name = "result" - temp_usage = ast.VariableUsage(temp_name) + temp_usage = syntax.VariableUsage(temp_name) - return ast.Program( + return syntax.Program( [ - (temp_name, ast.BooleanType), + (temp_name, syntax.BooleanType), ], [ - ast.Assign( + syntax.Assign( temp_usage, - ast.Call(ast.VariableUsage("identity"), [param]), + syntax.Call(syntax.VariableUsage("identity"), [param]), ), - ast.Return(temp_usage), + syntax.Return(temp_usage), ], ) @@ -84,19 +84,21 @@ class If(Context): statement. """ - TAG_CONTEXT = ast.TagTypes.DECISION + TAG_CONTEXT = syntax.TagTypes.DECISION def get_program(self, condition): - return ast.Program( + return syntax.Program( [], # No local variable [ - ast.If( + syntax.If( condition, - ast.TaggedNode( - ON_TRUE_TAG, ast.Return(ast.LitteralBoolean(True)) + syntax.TaggedNode( + ON_TRUE_TAG, + syntax.Return(syntax.LitteralBoolean(True)), ), - ast.TaggedNode( - ON_FALSE_TAG, ast.Return(ast.LitteralBoolean(False)) + syntax.TaggedNode( + ON_FALSE_TAG, + syntax.Return(syntax.LitteralBoolean(False)), ), ) ], @@ -109,32 +111,33 @@ class While(Context): statement. """ - TAG_CONTEXT = ast.TagTypes.DECISION + TAG_CONTEXT = syntax.TagTypes.DECISION def get_program(self, condition): - return ast.Program( + return syntax.Program( [], # No local variable [ - ast.While( + syntax.While( condition, - ast.TaggedNode( - ON_TRUE_TAG, ast.Return(ast.LitteralBoolean(True)) + syntax.TaggedNode( + ON_TRUE_TAG, + syntax.Return(syntax.LitteralBoolean(True)), ), ), - ast.TaggedNode( - ON_FALSE_TAG, ast.Return(ast.LitteralBoolean(False)) + syntax.TaggedNode( + ON_FALSE_TAG, syntax.Return(syntax.LitteralBoolean(False)) ), ], ) class Return(Context): - TAG_CONTEXT = ast.TagTypes.EXPRESSION + TAG_CONTEXT = syntax.TagTypes.EXPRESSION def get_program(self, condition): - return ast.Program( + return syntax.Program( [], [ - ast.Return(condition), + syntax.Return(condition), ], ) diff --git a/testsuite/SCOV/expgen/generator/composition.py b/testsuite/SCOV/expgen/generator/composition.py index 044fb7388..930997e45 100644 --- a/testsuite/SCOV/expgen/generator/composition.py +++ b/testsuite/SCOV/expgen/generator/composition.py @@ -3,7 +3,7 @@ """Set of composition elements.""" -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.context as context import SCOV.expgen.language as language import SCOV.expgen.language.ada.context as ada_context @@ -17,7 +17,7 @@ operand_kinds = [ operand.Variable(), - operand.IntegerComparison(ast.RelOp.GT, 1), + operand.IntegerComparison(syntax.RelOp.GT, 1), # Ada-specific operands ada_operand.Aggregate(), ada_operand.Component(), diff --git a/testsuite/SCOV/expgen/generator/parsing.py b/testsuite/SCOV/expgen/generator/parsing.py index cb166aa7c..f8dfd5fa2 100644 --- a/testsuite/SCOV/expgen/generator/parsing.py +++ b/testsuite/SCOV/expgen/generator/parsing.py @@ -5,7 +5,7 @@ module provides various helpers to parse them. """ -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.topology as topology from SCOV.expgen.generator.errors import DriverError, BadTopologyError @@ -43,7 +43,7 @@ def parse_or(i): ) i += 2 right, i = parse_and(i) - left = ast.And(left, right) + left = syntax.And(left, right) return left, i def parse_and(i): @@ -56,14 +56,14 @@ def parse_and(i): ) i += 2 right, i = parse_not(i) - left = ast.And(left, right) + left = syntax.And(left, right) return left, i def parse_not(i): check_eof(i) if tokens[i] == "not": expr, i = parse_not(i + 1) - return ast.Not(expr), i + return syntax.Not(expr), i elif tokens[i] == "_": return (topology.OperandPlaceholder(), i + 1) elif tokens[i] == "(": diff --git a/testsuite/SCOV/expgen/language/__init__.py b/testsuite/SCOV/expgen/language/__init__.py index 472e54f89..ea3b3260d 100644 --- a/testsuite/SCOV/expgen/language/__init__.py +++ b/testsuite/SCOV/expgen/language/__init__.py @@ -6,7 +6,7 @@ import io -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.context as context import SCOV.expgen.operand as operand import SCOV.expgen.utils as utils @@ -227,7 +227,7 @@ def handle_language_specific_operand(self, xoperand): self.check_language(xoperand) # Languages can process identifiers in a specific way. formal_name, remaining_tag = self.format_tree( - ast.VariableUsage(xoperand.formal_name) + syntax.VariableUsage(xoperand.formal_name) ) if remaining_tag: self.add_tag(remaining_tag) @@ -291,7 +291,7 @@ def filter_types(self, types): """ Return the subset of `types` that can be used with this language. """ - return self._filter_nodes(ast.XType, types) + return self._filter_nodes(syntax.XType, types) # diff --git a/testsuite/SCOV/expgen/language/ada/__init__.py b/testsuite/SCOV/expgen/language/ada/__init__.py index af8b80a79..427fb1d9c 100644 --- a/testsuite/SCOV/expgen/language/ada/__init__.py +++ b/testsuite/SCOV/expgen/language/ada/__init__.py @@ -1,24 +1,24 @@ # -*- coding: utf-8 -*- -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.utils as utils import SCOV.expgen.language as language # Serialization of relational operators REL_OP = { - ast.RelOp.GT: ">", - ast.RelOp.GE: ">=", - ast.RelOp.LT: ">", - ast.RelOp.LE: ">=", - ast.RelOp.EQ: "=", - ast.RelOp.NE: "/=", + syntax.RelOp.GT: ">", + syntax.RelOp.GE: ">=", + syntax.RelOp.LT: ">", + syntax.RelOp.LE: ">=", + syntax.RelOp.EQ: "=", + syntax.RelOp.NE: "/=", } # Serialization for builtin types BUILTIN_TYPES = { - ast.Types.BOOLEAN: "Boolean", - ast.Types.INTEGER: "Integer", + syntax.Types.BOOLEAN: "Boolean", + syntax.Types.INTEGER: "Integer", } @@ -102,8 +102,8 @@ def serialize_run_module_implementation( self.write("begin") self.newline() with self.indent(self.INDENT): - call_to_run = ast.Call( - ast.VariableUsage(self.ENTRY_POINT_NAME), + call_to_run = syntax.Call( + syntax.VariableUsage(self.ENTRY_POINT_NAME), [ op_kind.actuals[op_truth] for op_kind, op_truth in zip( @@ -112,13 +112,13 @@ def serialize_run_module_implementation( ], ) self.handle( - ast.Call( - ast.VariableUsage(self.ASSERT_PROC_NAME), + syntax.Call( + syntax.VariableUsage(self.ASSERT_PROC_NAME), [ - ast.Comparison( - ast.RelOp.EQ, + syntax.Comparison( + syntax.RelOp.EQ, call_to_run, - ast.LitteralBoolean(truth_vector[-1]), + syntax.LitteralBoolean(truth_vector[-1]), ) ], ) @@ -163,7 +163,7 @@ def serialize_specification_types(self, stream, types): self.set_stream(stream) with PackageGuard(self, True, self.TYPES_MODULE): for type_decl in types: - if not isinstance(type_decl, ast.BuiltinType): + if not isinstance(type_decl, syntax.BuiltinType): self.handle(type_decl, declaration=True) def serialize_specification_program( @@ -177,7 +177,7 @@ def serialize_specification_program( with PackageGuard(self, True, self.COMPUTING_MODULE): self.add_subprogram_signature( self.ENTRY_POINT_NAME, - ast.BooleanType, + syntax.BooleanType, formal_names, formal_types, True, @@ -195,7 +195,7 @@ def serialize_implementation( with PackageGuard(self, False, self.COMPUTING_MODULE): self.add_subprogram_signature( self.ENTRY_POINT_NAME, - ast.BooleanType, + syntax.BooleanType, formal_names, formal_types, False, @@ -369,9 +369,9 @@ def handle_composite_expr(self, expr): is_composite = isinstance( expr, ( - ast.Comparison, - ast.And, - ast.Or, + syntax.Comparison, + syntax.And, + syntax.Or, ), ) diff --git a/testsuite/SCOV/expgen/language/ada/context.py b/testsuite/SCOV/expgen/language/ada/context.py index 20230b40a..aee22cec9 100644 --- a/testsuite/SCOV/expgen/language/ada/context.py +++ b/testsuite/SCOV/expgen/language/ada/context.py @@ -2,7 +2,7 @@ """Ada-specific contexts.""" -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.context as context @@ -13,7 +13,7 @@ class Case(context.LanguageSpecific): """ LANGUAGE = "Ada" - TAG_CONTEXT = ast.TagTypes.EXPRESSION + TAG_CONTEXT = syntax.TagTypes.EXPRESSION FORMAT = [ "case {decision_expr} is", " when True =>", @@ -28,7 +28,7 @@ class DeclarationInitializer(context.LanguageSpecific): """The decision expression is used as a local boolean initializer.""" LANGUAGE = "Ada" - TAG_CONTEXT = ast.TagTypes.EXPRESSION + TAG_CONTEXT = syntax.TagTypes.EXPRESSION FORMAT = [ "declare", " E : Boolean := {decision_expr};" "begin", @@ -41,7 +41,7 @@ class Discriminant(context.LanguageSpecific): """The decision expression is used as a record discriminant.""" LANGUAGE = "Ada" - TAG_CONTEXT = ast.TagTypes.EXPRESSION + TAG_CONTEXT = syntax.TagTypes.EXPRESSION FORMAT = [ "declare", " type My_Type (Value : Boolean) is null record;", @@ -59,7 +59,7 @@ class ExitWhen(context.LanguageSpecific): """ LANGUAGE = "Ada" - TAG_CONTEXT = ast.TagTypes.DECISION + TAG_CONTEXT = syntax.TagTypes.DECISION FORMAT = [ "loop", " exit when {decision_expr};", @@ -76,7 +76,7 @@ class For(context.LanguageSpecific): """ LANGUAGE = "Ada" - TAG_CONTEXT = ast.TagTypes.EXPRESSION + TAG_CONTEXT = syntax.TagTypes.EXPRESSION FORMAT = [ "declare", " E : Boolean := False;", @@ -93,7 +93,7 @@ class Index(context.LanguageSpecific): """The decision expression is used as an array subscript.""" LANGUAGE = "Ada" - TAG_CONTEXT = ast.TagTypes.EXPRESSION + TAG_CONTEXT = syntax.TagTypes.EXPRESSION FORMAT = [ "declare", " Values : array (Boolean) of Boolean := (", diff --git a/testsuite/SCOV/expgen/language/c/__init__.py b/testsuite/SCOV/expgen/language/c/__init__.py index 726cd3851..5dc3f4372 100644 --- a/testsuite/SCOV/expgen/language/c/__init__.py +++ b/testsuite/SCOV/expgen/language/c/__init__.py @@ -1,24 +1,24 @@ # -*- coding: utf-8 -*- -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.utils as utils import SCOV.expgen.language as language # Serialization of relational operators REL_OP = { - ast.RelOp.GT: ">", - ast.RelOp.GE: ">=", - ast.RelOp.LT: ">", - ast.RelOp.LE: ">=", - ast.RelOp.EQ: "==", - ast.RelOp.NE: "!=", + syntax.RelOp.GT: ">", + syntax.RelOp.GE: ">=", + syntax.RelOp.LT: ">", + syntax.RelOp.LE: ">=", + syntax.RelOp.EQ: "==", + syntax.RelOp.NE: "!=", } # Serialization for builtin types BUILTIN_TYPES = { - ast.Types.BOOLEAN: "int", - ast.Types.INTEGER: "int", + syntax.Types.BOOLEAN: "int", + syntax.Types.INTEGER: "int", } @@ -81,8 +81,8 @@ def serialize_run_module_implementation( self.write("{") self.newline() with self.indent(self.INDENT): - call_to_run = ast.Call( - ast.VariableUsage(self.ENTRY_POINT_NAME), + call_to_run = syntax.Call( + syntax.VariableUsage(self.ENTRY_POINT_NAME), [ op_kind.actuals[op_truth] for op_kind, op_truth in zip( @@ -91,13 +91,13 @@ def serialize_run_module_implementation( ], ) self.handle( - ast.Call( - ast.VariableUsage(self.ASSERT_PROC_NAME), + syntax.Call( + syntax.VariableUsage(self.ASSERT_PROC_NAME), [ - ast.Comparison( - ast.RelOp.EQ, + syntax.Comparison( + syntax.RelOp.EQ, call_to_run, - ast.LitteralBoolean(truth_vector[-1]), + syntax.LitteralBoolean(truth_vector[-1]), ) ], ) @@ -111,7 +111,7 @@ def serialize_specification_types(self, stream, types): self.set_stream(stream) with HeaderGuard(self, self.TYPES_MODULE): for type_decl in types: - if not isinstance(type_decl, ast.BuiltinType): + if not isinstance(type_decl, syntax.BuiltinType): self.handle(type_decl, declaration=True) def serialize_specification_program( @@ -124,7 +124,7 @@ def serialize_specification_program( self.add_subprogram_signature( self.ENTRY_POINT_NAME, - ast.BooleanType, + syntax.BooleanType, formal_names, formal_types, True, @@ -144,7 +144,7 @@ def serialize_implementation( self.add_subprogram_signature( self.ENTRY_POINT_NAME, - ast.BooleanType, + syntax.BooleanType, formal_names, formal_types, False, @@ -309,9 +309,9 @@ def handle_composite_expr(self, expr): is_composite = isinstance( expr, ( - ast.Comparison, - ast.And, - ast.Or, + syntax.Comparison, + syntax.And, + syntax.Or, ), ) diff --git a/testsuite/SCOV/expgen/language/c/context.py b/testsuite/SCOV/expgen/language/c/context.py index 47442efd2..c97b41331 100644 --- a/testsuite/SCOV/expgen/language/c/context.py +++ b/testsuite/SCOV/expgen/language/c/context.py @@ -2,7 +2,7 @@ """C-specific contexts""" -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax import SCOV.expgen.context as context @@ -10,7 +10,7 @@ class DeclarationInitializer(context.LanguageSpecific): """The decision expression is used as a local boolean initializer.""" LANGUAGE = "C" - TAG_CONTEXT = ast.TagTypes.EXPRESSION + TAG_CONTEXT = syntax.TagTypes.EXPRESSION FORMAT = [ "int result = {decision_expr};", "return result;", diff --git a/testsuite/SCOV/expgen/operand.py b/testsuite/SCOV/expgen/operand.py index 81e63f273..2e12fe91e 100644 --- a/testsuite/SCOV/expgen/operand.py +++ b/testsuite/SCOV/expgen/operand.py @@ -2,7 +2,7 @@ """Expose operand kinds suitable for condition expressions.""" -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax class Operand(object): @@ -73,14 +73,14 @@ def __init__(self): # Convert ACTUALS to ast.XLitteral nodes. actuals = { - False: ast.XLitteral(self.LANGUAGE, self.ACTUALS[False]), - True: ast.XLitteral(self.LANGUAGE, self.ACTUALS[True]), + False: syntax.XLitteral(self.LANGUAGE, self.ACTUALS[False]), + True: syntax.XLitteral(self.LANGUAGE, self.ACTUALS[True]), } super(LanguageSpecific, self).__init__(xtypes, param_type, actuals) def get_operand(self, param): - return ast.XOperand(self.LANGUAGE, self.FORMAT, param) + return syntax.XOperand(self.LANGUAGE, self.FORMAT, param) # Mapping: type_tuple id -> ast.XType # This is global since a type can be used in more than one operand kind, @@ -94,7 +94,7 @@ def convert_type(self, type_): xtype = self.converted_types[type_id] except KeyError: declaration, usage = type_ - xtype = ast.XType(self.LANGUAGE, declaration, usage) + xtype = syntax.XType(self.LANGUAGE, declaration, usage) self.converted_types[type_id] = xtype return xtype @@ -103,17 +103,17 @@ class Variable(Operand): """The operand is just the usage of a boolean argument.""" ACTUALS = { - False: ast.LitteralBoolean(False), - True: ast.LitteralBoolean(True), + False: syntax.LitteralBoolean(False), + True: syntax.LitteralBoolean(True), } def __init__(self): super(Variable, self).__init__( - (ast.BooleanType,), ast.BooleanType, self.ACTUALS + (syntax.BooleanType,), syntax.BooleanType, self.ACTUALS ) def get_operand(self, param): - return ast.VariableUsage(param) + return syntax.VariableUsage(param) class IntegerComparison(Operand): @@ -123,28 +123,28 @@ class IntegerComparison(Operand): # Each factory takes the compared integer and returns (a false actual, a # true one). ACTUALS_MAKERS = { - ast.RelOp.GT: lambda value: (value - 1, value + 1), - ast.RelOp.GE: lambda value: (value - 1, value + 1), - ast.RelOp.LT: lambda value: (value + 1, value - 2), - ast.RelOp.LE: lambda value: (value + 1, value - 2), - ast.RelOp.EQ: lambda value: (value + 1, value), - ast.RelOp.NE: lambda value: (value, value + 1), + syntax.RelOp.GT: lambda value: (value - 1, value + 1), + syntax.RelOp.GE: lambda value: (value - 1, value + 1), + syntax.RelOp.LT: lambda value: (value + 1, value - 2), + syntax.RelOp.LE: lambda value: (value + 1, value - 2), + syntax.RelOp.EQ: lambda value: (value + 1, value), + syntax.RelOp.NE: lambda value: (value, value + 1), } def __init__(self, operator, value): actual_false, actual_true = self.ACTUALS_MAKERS[operator](value) super(IntegerComparison, self).__init__( - (ast.IntegerType,), - ast.IntegerType, + (syntax.IntegerType,), + syntax.IntegerType, { - False: ast.LitteralInteger(actual_false), - True: ast.LitteralInteger(actual_true), + False: syntax.LitteralInteger(actual_false), + True: syntax.LitteralInteger(actual_true), }, ) self.operator = operator - self.value = ast.LitteralInteger(value) + self.value = syntax.LitteralInteger(value) def get_operand(self, param): - return ast.Comparison( - self.operator, ast.VariableUsage(param), self.value + return syntax.Comparison( + self.operator, syntax.VariableUsage(param), self.value ) diff --git a/testsuite/SCOV/expgen/ast.py b/testsuite/SCOV/expgen/syntax.py similarity index 100% rename from testsuite/SCOV/expgen/ast.py rename to testsuite/SCOV/expgen/syntax.py diff --git a/testsuite/SCOV/expgen/topology.py b/testsuite/SCOV/expgen/topology.py index cb18a0e99..ba6013c13 100644 --- a/testsuite/SCOV/expgen/topology.py +++ b/testsuite/SCOV/expgen/topology.py @@ -11,7 +11,7 @@ expression: to do so, placeholders are replaced by "operand" expressions. """ -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax class OperandPlaceholder(object): @@ -56,8 +56,8 @@ def helper(expression, i): # If we find a placeholder, return the next operand after tagging # it. if isinstance(expression, OperandPlaceholder): - result = ast.TaggedNode( - ast.Tag("eval", formal_names[i], context.TAG_CONTEXT), + result = syntax.TaggedNode( + syntax.Tag("eval", formal_names[i], context.TAG_CONTEXT), operands[i], ) return (result, i + 1) @@ -100,15 +100,15 @@ def helper(expression, i): return (operands[i], i + 1) # Otherwise, evaluate sub-expressions and return the result. - if isinstance(expression, ast.And): + if isinstance(expression, syntax.And): left, i = helper(expression.left, i) right, i = helper(expression.right, i) return (left and right, i) - elif isinstance(expression, ast.Or): + elif isinstance(expression, syntax.Or): left, i = helper(expression.left, i) right, i = helper(expression.right, i) return (left or right, i) - elif isinstance(expression, ast.Not): + elif isinstance(expression, syntax.Not): result, i = helper(expression.expr, i) return (not result, i) else: @@ -133,11 +133,11 @@ def __str__(self): def helper(expr): if isinstance(expr, OperandPlaceholder): return placeholders.pop() - elif isinstance(expr, ast.And): + elif isinstance(expr, syntax.And): return "({} and {})".format( helper(expr.left), helper(expr.right) ) - elif isinstance(expr, ast.Or): + elif isinstance(expr, syntax.Or): return "({} or {})".format( helper(expr.left), helper(expr.right) ) diff --git a/testsuite/SCOV/expgen/utils.py b/testsuite/SCOV/expgen/utils.py index 6125317fa..a79764a89 100644 --- a/testsuite/SCOV/expgen/utils.py +++ b/testsuite/SCOV/expgen/utils.py @@ -2,13 +2,16 @@ """Various helpers used through the whole package.""" -import SCOV.expgen.ast as ast +import SCOV.expgen.syntax as syntax def check_tag(tag): """Assert whether the given `tag` is valid, or not.""" if tag.name == "eval": - assert tag.context in (ast.TagTypes.DECISION, ast.TagTypes.EXPRESSION) + assert tag.context in ( + syntax.TagTypes.DECISION, + syntax.TagTypes.EXPRESSION, + ) assert tag.operand is not None else: assert tag.operand is None @@ -26,7 +29,7 @@ def format_tag(tag): def contains_tag(node): """Return if the given `node` tree contains a tagged node.""" return not isinstance(node, (str, bool, int)) and ( - isinstance(node, ast.TaggedNode) + isinstance(node, syntax.TaggedNode) or any(contains_tag(subnode) for subnode in node) ) @@ -36,17 +39,17 @@ def is_expr(node): return isinstance( node, ( - ast.VariableUsage, - ast.LitteralInteger, - ast.LitteralBoolean, - ast.LitteralRecord, - ast.Comparison, - ast.Call, - ast.XLitteral, - ast.XOperand, - ast.And, - ast.Or, - ast.Not, + syntax.VariableUsage, + syntax.LitteralInteger, + syntax.LitteralBoolean, + syntax.LitteralRecord, + syntax.Comparison, + syntax.Call, + syntax.XLitteral, + syntax.XOperand, + syntax.And, + syntax.Or, + syntax.Not, ), ) @@ -71,7 +74,7 @@ def is_topology_equal(topo1, topo2): """Return whether two topologies are equal.""" if type(topo1) is not type(topo2): return False - elif isinstance(topo1, (ast.And, ast.Not, ast.Or)): + elif isinstance(topo1, (syntax.And, syntax.Not, syntax.Or)): return all( is_topology_equal(sub_topo1, sub_topo2) for sub_topo1, sub_topo2 in zip(topo1, topo2) diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index 384bdbd40..ad6fc02d3 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -525,7 +525,7 @@ def __init__(self, re_start, skeys): self, re_start=re_start, re_end=".. END OF REPORT ..$" ) self.skeys = skeys - self.checked = {sec: False for sec in skeys} + self.checked = dict.fromkeys(skeys, False) def try_match(self, sec, rline): p = re.match(self.skeys[sec], rline) From d33249561c7d6a5d357bcfa08afc03012e39eb50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 22 Jan 2025 10:32:15 +0100 Subject: [PATCH 1078/1483] instr-c: use isThisDeclarationADefinition to check for a function body --- tools/gnatcov/clang-extensions.adb | 15 ++++++ tools/gnatcov/clang-extensions.ads | 6 +++ tools/gnatcov/clang-wrapper.cc | 26 ++++++++++ tools/gnatcov/instrument-c.adb | 81 ++++++++++++++++-------------- 4 files changed, 91 insertions(+), 37 deletions(-) diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index c52da4f5b..808d42777 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -90,6 +90,21 @@ package body Clang.Extensions is return Opcode_Str; end Get_Opcode_Str; + -------------------------------------- + -- Is_This_Declaration_A_Definition -- + -------------------------------------- + + function Is_This_Declaration_A_Definition (C : Cursor_T) return Boolean + is + function Is_This_Declaration_A_Definition_C + (C : Cursor_T) return unsigned + with + Import, Convention => C, + External_Name => "clang_isThisDeclarationADefinition"; + begin + return Is_This_Declaration_A_Definition_C (C) /= 0; + end Is_This_Declaration_A_Definition; + ------------------ -- Is_Constexpr -- ------------------ diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index 5eb1cf7e0..f77a6d333 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -88,6 +88,12 @@ package Clang.Extensions is function Get_Callee_Name_Str (C : Cursor_T) return String with Inline; + function Is_This_Declaration_A_Definition (C : Cursor_T) return Boolean + with Inline; + -- Given a function or function template declaration, return true if + -- the declaration is indeed a definition (i.e. it has a body). + -- Providing another kind of node may return False; + function Is_Constexpr (C : Cursor_T) return Boolean with Inline; function Unwrap (C : Cursor_T) return Cursor_T diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index bcad36f8e..e9a50ac7e 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -508,6 +508,32 @@ clang_getCalleeName (CXCursor C) return createEmpty (); } +extern "C" bool +clang_isThisDeclarationADefinition (CXCursor C) +{ + if (!clang_isDeclaration (C.kind)) + { + return false; + } + + const Decl *D = getCursorDecl (C); + switch (D->getKind ()) + { + case Decl::FunctionTemplate: + return cast (D) + ->getTemplatedDecl () + ->isThisDeclarationADefinition (); + case Decl::Function: + case Decl::CXXMethod: + case Decl::CXXConstructor: + case Decl::CXXDestructor: + case Decl::CXXConversion: + return cast (D)->isThisDeclarationADefinition (); + default: + return false; + } +} + extern "C" unsigned clang_isConstexpr (CXCursor C) { diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index c2bcdd39b..de1ff4e37 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2617,46 +2617,53 @@ package body Instrument.C is | Cursor_Destructor | Cursor_Lambda_Expr => - declare - Fun_Body : constant Cursor_T := Get_Body (N); - Stmts : constant Cursor_Vectors.Vector := - Get_Children (Fun_Body); - -- Get_Body returns a Compound_Stmt, convert it to a list - -- of statements using the Get_Children utility. - - TB : Unbounded_String; - -- Trailing braces that should be inserted at the end - -- of the function body. + -- Only instrument definitions, not declarations. + -- Lambda expressions are always definitions. - begin - if Cursor_Kind /= Cursor_Lambda_Expr then - UIC.Pass.Enter_Scope (UIC, N); - end if; - - -- Do not instrument constexpr function as it would - -- violate the constexpr restrictions. + if Is_This_Declaration_A_Definition (N) or else + Cursor_Kind = Cursor_Lambda_Expr + then + declare + Fun_Body : constant Cursor_T := Get_Body (N); + Stmts : constant Cursor_Vectors.Vector := + Get_Children (Fun_Body); + -- Get_Body returns a Compound_Stmt, convert it to a + -- list of statements using the Get_Children utility. - if Is_Constexpr (N) then - UIC.Pass.Report - (N, - "gnatcov limitation: cannot instrument constexpr" - & " functions."); - UIC.Disable_Instrumentation := True; - end if; + TB : Unbounded_String; + -- Trailing braces that should be inserted at the end + -- of the function body. - if Stmts.Length > 0 then - UIC.MCDC_State_Declaration_Node := - Stmts.First_Element; - Traverse_Statements (UIC, Stmts, TB); - UIC.Pass.Insert_Text_Before_Token - (UIC, End_Sloc (Fun_Body), +TB); - end if; - if Cursor_Kind /= Cursor_Lambda_Expr then - UIC.Pass.Exit_Scope (UIC); - end if; - UIC.Disable_Instrumentation := - Save_Disable_Instrumentation; - end; + begin + if Cursor_Kind /= Cursor_Lambda_Expr then + UIC.Pass.Enter_Scope (UIC, N); + end if; + + -- Do not instrument constexpr function as it would + -- violate the constexpr restrictions. + + if Is_Constexpr (N) then + UIC.Pass.Report + (N, + "gnatcov limitation: cannot instrument constexpr" + & " functions."); + UIC.Disable_Instrumentation := True; + end if; + + if Stmts.Length > 0 then + UIC.MCDC_State_Declaration_Node := + Stmts.First_Element; + Traverse_Statements (UIC, Stmts, TB); + UIC.Pass.Insert_Text_Before_Token + (UIC, End_Sloc (Fun_Body), +TB); + end if; + if Cursor_Kind /= Cursor_Lambda_Expr then + UIC.Pass.Exit_Scope (UIC); + end if; + UIC.Disable_Instrumentation := + Save_Disable_Instrumentation; + end; + end if; -- Traverse the declarations of a namespace / linkage -- specification etc. From d51e6ecb4c726d23676f74b9179d1949352c9875 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 22 Jan 2025 18:08:42 +0100 Subject: [PATCH 1079/1483] test(instr-c++): Check generic/templating functions insntrumentation and coverage --- .../C++/c++_generics/src/main_both.cpp | 8 ++ .../C++/c++_generics/src/main_float.cpp | 7 ++ .../C++/c++_generics/src/main_int.cpp | 7 ++ .../C++/c++_generics/src/main_none.cpp | 7 ++ .../instr-cov/C++/c++_generics/src/pkg.cpp | 23 +++++ .../instr-cov/C++/c++_generics/src/pkg.h | 17 ++++ .../tests/instr-cov/C++/c++_generics/test.py | 98 +++++++++++++++++++ 7 files changed, 167 insertions(+) create mode 100644 testsuite/tests/instr-cov/C++/c++_generics/src/main_both.cpp create mode 100644 testsuite/tests/instr-cov/C++/c++_generics/src/main_float.cpp create mode 100644 testsuite/tests/instr-cov/C++/c++_generics/src/main_int.cpp create mode 100644 testsuite/tests/instr-cov/C++/c++_generics/src/main_none.cpp create mode 100644 testsuite/tests/instr-cov/C++/c++_generics/src/pkg.cpp create mode 100644 testsuite/tests/instr-cov/C++/c++_generics/src/pkg.h create mode 100644 testsuite/tests/instr-cov/C++/c++_generics/test.py diff --git a/testsuite/tests/instr-cov/C++/c++_generics/src/main_both.cpp b/testsuite/tests/instr-cov/C++/c++_generics/src/main_both.cpp new file mode 100644 index 000000000..54e672d1d --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/src/main_both.cpp @@ -0,0 +1,8 @@ +#include "pkg.h" + +int +main (void) +{ + foo_int (); + foo_float (); +} diff --git a/testsuite/tests/instr-cov/C++/c++_generics/src/main_float.cpp b/testsuite/tests/instr-cov/C++/c++_generics/src/main_float.cpp new file mode 100644 index 000000000..06a90381c --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/src/main_float.cpp @@ -0,0 +1,7 @@ +#include "pkg.h" + +int +main (void) +{ + foo_float (); +} diff --git a/testsuite/tests/instr-cov/C++/c++_generics/src/main_int.cpp b/testsuite/tests/instr-cov/C++/c++_generics/src/main_int.cpp new file mode 100644 index 000000000..a49c61e53 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/src/main_int.cpp @@ -0,0 +1,7 @@ +#include "pkg.h" + +int +main (void) +{ + foo_int (); +} diff --git a/testsuite/tests/instr-cov/C++/c++_generics/src/main_none.cpp b/testsuite/tests/instr-cov/C++/c++_generics/src/main_none.cpp new file mode 100644 index 000000000..84a3c635c --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/src/main_none.cpp @@ -0,0 +1,7 @@ +#include "pkg.h" + +int +main (void) +{ + int foo = 0; +} diff --git a/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.cpp b/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.cpp new file mode 100644 index 000000000..50ae2fc0f --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.cpp @@ -0,0 +1,23 @@ +#include "pkg.h" +#include + +template +void +print_point (Point p) +{ + std::cout << p.x << '\n' << p.y << std::endl; +} + +void +foo_int (void) +{ + Point A = Point (1, 2); + print_point (A); +} + +void +foo_float (void) +{ + Point A = Point (1.5f, 2.5f); + print_point (A); +} diff --git a/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.h b/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.h new file mode 100644 index 000000000..2c4f6a86e --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.h @@ -0,0 +1,17 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo_int (void); +void foo_float (void); + +template struct Point +{ + T x; + T y; + + Point (T x, T y) : x (x), y (y) {} +}; + +template void print_point (Point p); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/C++/c++_generics/test.py b/testsuite/tests/instr-cov/C++/c++_generics/test.py new file mode 100644 index 000000000..cf61231a6 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/c++_generics/test.py @@ -0,0 +1,98 @@ +""" +Check that GNATcoverage produces a valid output for generics. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + + +tmp = Wdir("tmp_") + +MAIN_BOTH = "main_both.cpp" +MAIN_INT = "main_int.cpp" +MAIN_FLOAT = "main_float.cpp" +MAIN_NONE = "main_none.cpp" + + +def build_and_run_with_main(main): + build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor( + srcdirs=["../src"], + mains=[main], + ) + ), + covlevel="stmt", + mains=[main.split(".")[0]], + extra_instr_args=["--verbose", "--units=pkg.cpp"], + extra_coverage_args=["-axcov", "--output-dir=xcov", "--units=pkg.cpp"], + extra_gprbuild_args=["-v"], + ) + + +# Testcase both instantiation calls +build_and_run_with_main(MAIN_BOTH) +check_xcov_reports( + "xcov", + { + "pkg.cpp.xcov": { + "+": { + 8, + 14, + 15, + 21, + 22, + } + } + }, +) + +# Testcase only int instantiation call +build_and_run_with_main(MAIN_INT) +check_xcov_reports( + "xcov", + { + "pkg.cpp.xcov": { + "-": { + 21, + 22, + } + } + }, +) + +# Testcase only float instantiation call +build_and_run_with_main(MAIN_FLOAT) +check_xcov_reports( + "xcov", + { + "pkg.cpp.xcov": { + "-": { + 14, + 15, + } + } + }, +) + +# Testcase no instantiation call +build_and_run_with_main(MAIN_NONE) +check_xcov_reports( + "xcov", + { + "pkg.cpp.xcov": { + "-": { + 8, + 14, + 15, + 21, + 22, + } + } + }, +) + +thistest.result() From a1147346726efb030ad299ac3ffbc56638fe0a1e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 22 Jan 2025 09:40:40 +0000 Subject: [PATCH 1080/1483] sc_obligations.adb: fix assertion for the case of SID/checkpoint loading When a SID or checkpoint file is loaded, the coverage obligations it holds are merged into global tables in the Checkpoint_Load_Merge_Unit procedure. This process eventually calls the Condition function (to compute the SCO_Id for a condition from its enclosing decision + its index), which itself calls the Index function (to get the index of a given SCO condition) in an assertion. While the Condition function accepts a Source_Coverage_Vectors argument to operate either on global tables or on tables loaded from a SID/checpoint file, the Index function exclusively work on global tables. As a consequence, in the context of SID/checkpoint loading, the call to Index is meant to operate on SCOs from "loaded tables" but in fact operate on global tables, i.e. on SCOs that may be completely irrelevant. This commit introduces the necessary Index overload for it to be able to work on custom Source_Coverage_Vectors tables and fixes Condition to use that overload. This fixes a crash in TA27-015-ignore-source-files-source-coverage, found during the transition to GPR2. This looks really bad and one might wonder why this was not found before: this code path is exclusive to the processing of decisions whose valuation is statically known, and the global/loaded table disconnect that is needed to trigger the crash, which seems to be extremely rare in practice. The GPR2 transition revealed this issue probably because it changed the order of SID processing, which affects when the global/loaded table disconnect happens. --- tools/gnatcov/sc_obligations.adb | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index c2f95d175..921037d40 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -562,6 +562,10 @@ package body SC_Obligations is SCO_Vector : SCO_Vectors.Vector; end record; + function Index + (Vectors : Source_Coverage_Vectors; SCO : SCO_Id) return Condition_Index; + -- Internal definition of the function free from global variables + function Condition (Vectors : Source_Coverage_Vectors; SCO : SCO_Id; @@ -2576,6 +2580,20 @@ package body SC_Obligations is end if; end Last_SCO; + ----------- + -- Index -- + ----------- + + function Index + (Vectors : Source_Coverage_Vectors; SCO : SCO_Id) return Condition_Index + is + SCOD : SCO_Descriptor renames + Vectors.SCO_Vector.Constant_Reference (SCO); + begin + pragma Assert (SCOD.Kind = Condition); + return SCOD.Index; + end Index; + --------------- -- Condition -- --------------- @@ -2604,12 +2622,11 @@ package body SC_Obligations is if BDDN.Kind = Condition then Current_Condition_Index := Current_Condition_Index + 1; if Current_Condition_Index = Index then - return C_SCO : constant SCO_Id := BDDN.C_SCO - do + return C_SCO : constant SCO_Id := BDDN.C_SCO do pragma Assert (Enclosing (Vectors, Decision, C_SCO) = SCO); - pragma Assert (SC_Obligations.Index (C_SCO) = Index); - null; + pragma Assert + (SC_Obligations.Index (Vectors, C_SCO) = Index); end return; end if; end if; @@ -3313,10 +3330,8 @@ package body SC_Obligations is ----------- function Index (SCO : SCO_Id) return Condition_Index is - SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); begin - pragma Assert (SCOD.Kind = Condition); - return SCOD.Index; + return Index (SC_Vectors, SCO); end Index; ---------------------------- From 73aede5fad6596915f376bf1772ffad306ec4ed9 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 24 Jan 2025 17:09:36 +0100 Subject: [PATCH 1081/1483] instr-cpp: Avoid instrumenting using... clauses test(instr-cpp): add test for not using directive --- .../instr-cov/C++/374-using/src/test_call.cpp | 32 ++++++++++ .../tests/instr-cov/C++/374-using/test.py | 11 ++++ tools/gnatcov/clang-extensions.ads | 3 + tools/gnatcov/clang-wrapper.cc | 14 +++++ tools/gnatcov/instrument-c.adb | 63 +++++++++++++------ 5 files changed, 105 insertions(+), 18 deletions(-) create mode 100644 testsuite/tests/instr-cov/C++/374-using/src/test_call.cpp create mode 100644 testsuite/tests/instr-cov/C++/374-using/test.py diff --git a/testsuite/tests/instr-cov/C++/374-using/src/test_call.cpp b/testsuite/tests/instr-cov/C++/374-using/src/test_call.cpp new file mode 100644 index 000000000..e8cbf3399 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/374-using/src/test_call.cpp @@ -0,0 +1,32 @@ +namespace foo +{ +const float PI = 3.14; +} + +// Purposely not called function. +void +bar () +{ + using namespace foo; // # using + + auto x = PI; // # use_pi +} + +// Purposely not called function. +void +baz () +{ + using foo::PI; // # using + + auto x = PI; // # use_pi +} + +int +main (void) +{ + 0; +} + +//# test_call.cpp +// /using/ l. ## 0 +// /use_pi/ l- ## s- diff --git a/testsuite/tests/instr-cov/C++/374-using/test.py b/testsuite/tests/instr-cov/C++/374-using/test.py new file mode 100644 index 000000000..4b051d37e --- /dev/null +++ b/testsuite/tests/instr-cov/C++/374-using/test.py @@ -0,0 +1,11 @@ +""" +Check that the C++ instrumenter does not consider `using` clauses +as statements. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index f77a6d333..9373123cb 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -82,6 +82,9 @@ package Clang.Extensions is function Get_Operator_Loc (C : Cursor_T) return Source_Location_T with Import, Convention => C, External_Name => "clang_getOperatorLoc"; + function Get_Single_Decl (C : Cursor_T) return Cursor_T + with Import, Convention => C, External_Name => "clang_getSingleDecl"; + function Get_Opcode_Str (C : Cursor_T) return String with Inline; function Get_Decl_Name_Str (C : Cursor_T) return String with Inline; diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index e9a50ac7e..dcbab24bf 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -534,6 +534,20 @@ clang_isThisDeclarationADefinition (CXCursor C) } } +extern "C" CXCursor +clang_getSingleDecl (CXCursor C) +{ + if (clang_isStatement (C.kind)) + { + if (const Stmt *S = getCursorStmt (C)) + { + return MakeCXCursorWithNull ( + llvm::cast_if_present (S)->getSingleDecl (), C); + } + } + return clang_getNullCursor (); +} + extern "C" unsigned clang_isConstexpr (CXCursor C) { diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index de1ff4e37..48b5821d8 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2162,6 +2162,39 @@ package body Instrument.C is UIC.Disable_Instrumentation; Save_Disable_Coverage : constant Boolean := UIC.Disable_Coverage; + + procedure Instrument_Basic_Statement (N : Cursor_T); + + -------------------------------- + -- Instrument_Basic_Statement -- + -------------------------------- + + procedure Instrument_Basic_Statement (N : Cursor_T) is + begin + + -- Determine required type character code, or ASCII.NUL if + -- no SCO should be generated for this node. + + Instrument_Statement (N, ' '); + + -- Process any embedded decisions + + if Is_Constexpr (N) then + UIC.Pass.Report + (N, + "gnatcov limitation: cannot instrument constexpr" + & " variable declarations."); + UIC.Disable_Instrumentation := True; + Process_Expression (UIC, N, 'X'); + UIC.Disable_Instrumentation := + Save_Disable_Instrumentation; + else + Process_Expression (UIC, N, 'X'); + end if; + end Instrument_Basic_Statement; + + -- Start processing of Traverse_One + begin if Curlify (N) then Append (Trailing_Braces, '}'); @@ -2405,27 +2438,21 @@ package body Instrument.C is end if; end if; - when others => + when Cursor_Decl_Stmt => - -- Determine required type character code, or ASCII.NUL if - -- no SCO should be generated for this node. + -- Bail out of any "using" directive, + -- theses are not statements. - Instrument_Statement (N, ' '); + case Kind (Get_Single_Decl (N)) is + when Cursor_Using_Declaration | Cursor_Using_Directive => + null; + when others => + Instrument_Basic_Statement (N); + end case; + + when others => + Instrument_Basic_Statement (N); - -- Process any embedded decisions - - if Is_Constexpr (N) then - UIC.Pass.Report - (N, - "gnatcov limitation: cannot instrument constexpr" - & " variable declarations."); - UIC.Disable_Instrumentation := True; - Process_Expression (UIC, N, 'X'); - UIC.Disable_Instrumentation := - Save_Disable_Instrumentation; - else - Process_Expression (UIC, N, 'X'); - end if; end case; UIC.Disable_Coverage := Save_Disable_Coverage; From 05df15ac13a938ce2df52391522d2759e20d8182 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 23 Jan 2025 18:28:23 +0100 Subject: [PATCH 1082/1483] instr-c: add Insert_Text_In_Brackets function --- tools/gnatcov/clang-extensions.ads | 8 ++++++++ tools/gnatcov/clang-wrapper.cc | 16 ++++++++++++++++ tools/gnatcov/instrument-c_utils.adb | 24 ++++++++++++++++++++++++ tools/gnatcov/instrument-c_utils.ads | 9 +++++++++ 4 files changed, 57 insertions(+) diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index 9373123cb..c8ab31043 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -97,6 +97,14 @@ package Clang.Extensions is -- the declaration is indeed a definition (i.e. it has a body). -- Providing another kind of node may return False; + function Get_LBrac_Loc_Plus_One (C : Cursor_T) return Source_Location_T + with Import, Convention => C, + External_Name => "clang_getLBracLocPlusOne"; + -- Given a clang::CompoundStmt (which is a possibly empty list of + -- statements surrounded by brackets), return the Location just after its + -- opening bracket. Giving another kind of cursor will return a null + -- location. + function Is_Constexpr (C : Cursor_T) return Boolean with Inline; function Unwrap (C : Cursor_T) return Cursor_T diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index dcbab24bf..bf53ca32d 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -335,6 +335,22 @@ clang_getWhileLoc (CXCursor C) return clang_getNullLocation (); } +/* Given a clang::CompoundStmt, return the Location just after its left + bracket. Returns a null Location if the given argument is not as + expected. */ + +extern "C" CXSourceLocation +clang_getLBracLocPlusOne (CXCursor C) +{ + const auto TU = getCursorTU (C); + const CompoundStmt *S + = dyn_cast_if_present (getCursorStmt (C)); + if (!S) + return clang_getNullLocation (); + + return translateSLoc (TU, S->getLBracLoc ().getLocWithOffset (1)); +} + extern "C" CXCursor clang_getSubExpr (CXCursor C) { diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index c6ce6b56a..8dd5b32ca 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -351,6 +351,30 @@ package body Instrument.C_Utils is Insert => Text); end Insert_Text_After_Start_Of; + ----------------------------- + -- Insert_Text_In_Brackets -- + ----------------------------- + + procedure Insert_Text_In_Brackets + (CmpdStmt : Cursor_T; + Text : String; + Rew : Rewriter_T) + is + Location : Source_Location_T; + begin + + -- If the Cursor is not of the right kind, the call to + -- Get_LBrac_Loc_Plus_One will return a null cursor. + + pragma Assert (Kind (CmpdStmt) = Cursor_Compound_Stmt); + + Location := Get_LBrac_Loc_Plus_One (CmpdStmt); + CX_Rewriter_Insert_Text_After + (Rew => Rew, + Loc => Location, + Insert => Text); + end Insert_Text_In_Brackets; + --------------------------------- -- Insert_Text_Before_Start_Of -- --------------------------------- diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 8850ea6fe..71825c142 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -115,6 +115,15 @@ package Instrument.C_Utils is -- If this procedure is called multiple times with the same N as parameter, -- the string will be inserted _after_ any previously inserted string. + procedure Insert_Text_In_Brackets + (CmpdStmt : Cursor_T; + Text : String; + Rew : Rewriter_T); + -- Insert the string Text just after the opening bracket of N. + -- + -- This procedure shall be called with CompoundStmt nodes and will fail + -- otherwise. + procedure Insert_Text_Before_Start_Of (N : Cursor_T; Text : String; From edf920b31bb1b1e713fe10ad1bc0bebd5c6b14c0 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 23 Jan 2025 18:39:42 +0100 Subject: [PATCH 1083/1483] instr-c: fix atexit statement insertion on empty main function --- tools/gnatcov/instrument-c.adb | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 48b5821d8..2b129e4e6 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -4931,21 +4931,11 @@ package body Instrument.C is declare Body_Cursor : constant Cursor_T := Get_Body (Main_Cursor); - - -- The body of a function is a compound statement, so insert - -- the call to atexit before its first statement. - - Body_Stmts : constant Cursor_Vectors.Vector := - Get_Children (Body_Cursor); - First_Stmt : constant Cursor_T := Body_Stmts.First_Element; - - Location : constant Source_Location_T := - Get_Cursor_Location (First_Stmt); begin - CX_Rewriter_Insert_Text_Before - (Rew => Rew.Rewriter, - Loc => Location, - Insert => "atexit (" & Dump_Procedure_Symbol (Main) & ");"); + Insert_Text_In_Brackets + (CmpdStmt => Body_Cursor, + Text => "atexit (" & Dump_Procedure_Symbol (Main) & ");", + Rew => Rew.Rewriter); end; when others => From 181f31fccacc5572f44bbac937d477686c49684c Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 23 Jan 2025 17:27:27 +0100 Subject: [PATCH 1084/1483] test(instr-c): add test for empty main atexit instrumentation --- .../tests/instr-cov/c_empty_main/src/test_main.c | 7 +++++++ testsuite/tests/instr-cov/c_empty_main/test.py | 12 ++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 testsuite/tests/instr-cov/c_empty_main/src/test_main.c create mode 100644 testsuite/tests/instr-cov/c_empty_main/test.py diff --git a/testsuite/tests/instr-cov/c_empty_main/src/test_main.c b/testsuite/tests/instr-cov/c_empty_main/src/test_main.c new file mode 100644 index 000000000..3c521eeb6 --- /dev/null +++ b/testsuite/tests/instr-cov/c_empty_main/src/test_main.c @@ -0,0 +1,7 @@ +int +main () +{ + // Empty main should not make gnatcov instrument crash +} + +//# test_main.c diff --git a/testsuite/tests/instr-cov/c_empty_main/test.py b/testsuite/tests/instr-cov/c_empty_main/test.py new file mode 100644 index 000000000..1b0063e7f --- /dev/null +++ b/testsuite/tests/instr-cov/c_empty_main/test.py @@ -0,0 +1,12 @@ +""" +Regression testcase: checks that gnatcov does not crash when the main that is +to be instrumented for the dump instruction is an empty function (i.e. it +has no statement to insert an instruction before). +""" + +from SCOV.tc import TestCase, CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() + +thistest.result() From 89bc5cdeac4506ed1f9c753cd142dda5bf43c2a6 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 29 Jan 2025 12:05:35 +0100 Subject: [PATCH 1085/1483] instr-cpp: fix invalid Get_Single_Decl call on DeclStmts with multiple declarations --- .../instr-cov/C++/374-using/src/test_call.cpp | 11 +++++++++++ tools/gnatcov/clang-extensions.ads | 6 ++++-- tools/gnatcov/clang-wrapper.cc | 19 ++++++++++++++++--- tools/gnatcov/instrument-c.adb | 2 +- 4 files changed, 32 insertions(+), 6 deletions(-) diff --git a/testsuite/tests/instr-cov/C++/374-using/src/test_call.cpp b/testsuite/tests/instr-cov/C++/374-using/src/test_call.cpp index e8cbf3399..0539f7b93 100644 --- a/testsuite/tests/instr-cov/C++/374-using/src/test_call.cpp +++ b/testsuite/tests/instr-cov/C++/374-using/src/test_call.cpp @@ -1,6 +1,7 @@ namespace foo { const float PI = 3.14; +const float E = 2.72; } // Purposely not called function. @@ -21,6 +22,16 @@ baz () auto x = PI; // # use_pi } +// Purposely not called function. +void +toto () +{ + // importing multiple symbols on the same directive + using foo::PI, foo::E; // # using + + auto x = PI; // # use_pi +} + int main (void) { diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index c8ab31043..4543e149e 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -82,8 +82,10 @@ package Clang.Extensions is function Get_Operator_Loc (C : Cursor_T) return Source_Location_T with Import, Convention => C, External_Name => "clang_getOperatorLoc"; - function Get_Single_Decl (C : Cursor_T) return Cursor_T - with Import, Convention => C, External_Name => "clang_getSingleDecl"; + function Get_First_Decl (C : Cursor_T) return Cursor_T + with Import, Convention => C, External_Name => "clang_getFirstDecl"; + -- Given a Decl_Stmt, return the only declaration if it is a single decl, + -- and the first of the declaration list otherwise. function Get_Opcode_Str (C : Cursor_T) return String with Inline; diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index bf53ca32d..42ef83fc0 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -550,15 +550,28 @@ clang_isThisDeclarationADefinition (CXCursor C) } } +/* Given a Decl_Stmt, return the only declaration if it is a single decl, + and the first of the declaration list otherwise. */ extern "C" CXCursor -clang_getSingleDecl (CXCursor C) +clang_getFirstDecl (CXCursor C) { if (clang_isStatement (C.kind)) { if (const Stmt *S = getCursorStmt (C)) { - return MakeCXCursorWithNull ( - llvm::cast_if_present (S)->getSingleDecl (), C); + if (S->getStmtClass () != Stmt::DeclStmtClass) + return clang_getNullCursor (); + + auto DGR = llvm::cast (S)->getDeclGroup (); + + if (DGR.isSingleDecl ()) + return MakeCXCursorWithNull (DGR.getSingleDecl (), C); + + auto DI = DGR.begin (); + + assert (DI != DGR.end () && "Unexpected empty DeclGroup"); + + return MakeCXCursorWithNull (*DI, C); } } return clang_getNullCursor (); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 2b129e4e6..3a2dcbfd9 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2443,7 +2443,7 @@ package body Instrument.C is -- Bail out of any "using" directive, -- theses are not statements. - case Kind (Get_Single_Decl (N)) is + case Kind (Get_First_Decl (N)) is when Cursor_Using_Declaration | Cursor_Using_Directive => null; when others => From 290918991603410751b2404dc4c8796a098752cb Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 16 Dec 2024 10:30:14 +0000 Subject: [PATCH 1086/1483] SC_Obligations: add support for pragma Exit_Cases (cherry picked from commit 6931faddb4d539f53d231d2146af2c7ce4fc9cf3) --- tools/gnatcov/sc_obligations.ads | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 1392b5b79..a9f73199d 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -1096,6 +1096,7 @@ package SC_Obligations is Pragma_Eliminate, Pragma_Enable_Atomic_Synchronization, Pragma_Exceptional_Cases, + Pragma_Exit_Cases, Pragma_Export, Pragma_Export_Function, Pragma_Export_Object, @@ -1423,6 +1424,7 @@ package SC_Obligations is Pragma_Elaborate_All => False, Pragma_Elaborate_Body => False, Pragma_Exceptional_Cases => False, + Pragma_Exit_Cases => False, Pragma_Export => False, Pragma_Export_Function => False, Pragma_Export_Object => False, From 36efa618efd9c3f54d40312133c8b69aa97177b0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 16 Jan 2025 15:22:29 +0000 Subject: [PATCH 1087/1483] 716-static-decision-merging-in-ckpt: add Object_Dir for convenience --- .../common/src-double/greet.gpr | 1 + .../common/src-if-stmt/greet.gpr | 1 + .../common/src-simple/greet.gpr | 1 + 3 files changed, 3 insertions(+) diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr index 23bad9181..89febd66c 100644 --- a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr @@ -1,5 +1,6 @@ project Greet is for Source_Dirs use ("src-greet"); + for Object_Dir use "obj"; type Decision_Type is ("static_true", "static_false", "dynamic_true", "dynamic_false"); diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr index 6d2137c95..de8e998ac 100644 --- a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr @@ -1,5 +1,6 @@ project Greet is for Source_Dirs use ("src-greet"); + for Object_Dir use "obj"; type Decision_Type is ("static_true", "static_false", "dynamic_true", "dynamic_false"); diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr index 6d2137c95..de8e998ac 100644 --- a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr @@ -1,5 +1,6 @@ project Greet is for Source_Dirs use ("src-greet"); + for Object_Dir use "obj"; type Decision_Type is ("static_true", "static_false", "dynamic_true", "dynamic_false"); From c603e7fd9f7117ea1b293a25411e81e339f51f8a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 16 Jan 2025 15:27:29 +0000 Subject: [PATCH 1088/1483] 716-static-decision-merging-in-ckpt: fix naming conventions Use the pkg__* naming scheme so that GPRbuild does not try to build alternative sources, and thus avoid the "does not match source name" warning. --- .../common/src-double/greet.gpr | 16 ++++++++-------- .../src-greet/{df1_pkg.ads => pkg1__df.ads} | 0 .../src-greet/{dt1_pkg.ads => pkg1__dt.ads} | 0 .../src-greet/{sf1_pkg.ads => pkg1__sf.ads} | 0 .../src-greet/{st1_pkg.ads => pkg1__st.ads} | 0 .../src-greet/{df2_pkg.ads => pkg2__df.ads} | 0 .../src-greet/{dt2_pkg.ads => pkg2__dt.ads} | 0 .../src-greet/{sf2_pkg.ads => pkg2__sf.ads} | 0 .../src-greet/{st2_pkg.ads => pkg2__st.ads} | 0 .../common/src-if-stmt/greet.gpr | 8 ++++---- .../src-greet/{df_pkg.adb => pkg__df.adb} | 0 .../src-greet/{df_pkg.ads => pkg__df.ads} | 0 .../src-greet/{dt_pkg.ads => pkg__dt.ads} | 0 .../src-greet/{sf_pkg.ads => pkg__sf.ads} | 0 .../src-greet/{st_pkg.ads => pkg__st.ads} | 0 .../common/src-simple/greet.gpr | 8 ++++---- .../src-greet/{df_pkg.ads => pkg__df.ads} | 0 .../src-greet/{dt_pkg.ads => pkg__dt.ads} | 0 .../src-greet/{sf_pkg.ads => pkg__sf.ads} | 0 .../src-greet/{st_pkg.ads => pkg__st.ads} | 0 20 files changed, 16 insertions(+), 16 deletions(-) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/{df1_pkg.ads => pkg1__df.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/{dt1_pkg.ads => pkg1__dt.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/{sf1_pkg.ads => pkg1__sf.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/{st1_pkg.ads => pkg1__st.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/{df2_pkg.ads => pkg2__df.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/{dt2_pkg.ads => pkg2__dt.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/{sf2_pkg.ads => pkg2__sf.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/{st2_pkg.ads => pkg2__st.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/{df_pkg.adb => pkg__df.adb} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/{df_pkg.ads => pkg__df.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/{dt_pkg.ads => pkg__dt.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/{sf_pkg.ads => pkg__sf.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/{st_pkg.ads => pkg__st.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/{df_pkg.ads => pkg__df.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/{dt_pkg.ads => pkg__dt.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/{sf_pkg.ads => pkg__sf.ads} (100%) rename testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/{st_pkg.ads => pkg__st.ads} (100%) diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr index 89febd66c..a15a858df 100644 --- a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/greet.gpr @@ -13,23 +13,23 @@ project Greet is package Naming is case Val1_Impl is when "static_true" => - for Spec ("Pkg1") use "st1_pkg.ads"; + for Spec ("Pkg1") use "pkg1__st.ads"; when "static_false" => - for Spec ("Pkg1") use "sf1_pkg.ads"; + for Spec ("Pkg1") use "pkg1__sf.ads"; when "dynamic_true" => - for Spec ("Pkg1") use "dt1_pkg.ads"; + for Spec ("Pkg1") use "pkg1__dt.ads"; when "dynamic_false" => - for Spec ("Pkg1") use "df1_pkg.ads"; + for Spec ("Pkg1") use "pkg1__df.ads"; end case; case Val2_Impl is when "static_true" => - for Spec ("Pkg2") use "st2_pkg.ads"; + for Spec ("Pkg2") use "pkg2__st.ads"; when "static_false" => - for Spec ("Pkg2") use "sf2_pkg.ads"; + for Spec ("Pkg2") use "pkg2__sf.ads"; when "dynamic_true" => - for Spec ("Pkg2") use "dt2_pkg.ads"; + for Spec ("Pkg2") use "pkg2__dt.ads"; when "dynamic_false" => - for Spec ("Pkg2") use "df2_pkg.ads"; + for Spec ("Pkg2") use "pkg2__df.ads"; end case; end Naming; end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/df1_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__df.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/df1_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__df.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/dt1_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__dt.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/dt1_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__dt.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/sf1_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__sf.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/sf1_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__sf.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/st1_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__st.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/st1_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg1__st.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/df2_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__df.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/df2_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__df.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/dt2_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__dt.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/dt2_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__dt.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/sf2_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__sf.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/sf2_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__sf.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/st2_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__st.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/st2_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-double/src-greet/pkg2__st.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr index de8e998ac..aadd50e3f 100644 --- a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/greet.gpr @@ -11,13 +11,13 @@ project Greet is package Naming is case Val_Impl is when "static_true" => - for Spec ("Pkg") use "st_pkg.ads"; + for Spec ("Pkg") use "pkg__st.ads"; when "static_false" => - for Spec ("Pkg") use "sf_pkg.ads"; + for Spec ("Pkg") use "pkg__sf.ads"; when "dynamic_true" => - for Spec ("Pkg") use "dt_pkg.ads"; + for Spec ("Pkg") use "pkg__dt.ads"; when "dynamic_false" => - for Spec ("Pkg") use "df_pkg.ads"; + for Spec ("Pkg") use "pkg__df.ads"; end case; end Naming; end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/df_pkg.adb b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__df.adb similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/df_pkg.adb rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__df.adb diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/df_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__df.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/df_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__df.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dt_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__dt.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/dt_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__dt.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/sf_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__sf.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/sf_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__sf.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/st_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__st.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/st_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-if-stmt/src-greet/pkg__st.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr index de8e998ac..aadd50e3f 100644 --- a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr +++ b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/greet.gpr @@ -11,13 +11,13 @@ project Greet is package Naming is case Val_Impl is when "static_true" => - for Spec ("Pkg") use "st_pkg.ads"; + for Spec ("Pkg") use "pkg__st.ads"; when "static_false" => - for Spec ("Pkg") use "sf_pkg.ads"; + for Spec ("Pkg") use "pkg__sf.ads"; when "dynamic_true" => - for Spec ("Pkg") use "dt_pkg.ads"; + for Spec ("Pkg") use "pkg__dt.ads"; when "dynamic_false" => - for Spec ("Pkg") use "df_pkg.ads"; + for Spec ("Pkg") use "pkg__df.ads"; end case; end Naming; end Greet; diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/df_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__df.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/df_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__df.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/dt_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__dt.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/dt_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__dt.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/sf_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__sf.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/sf_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__sf.ads diff --git a/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/st_pkg.ads b/testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__st.ads similarity index 100% rename from testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/st_pkg.ads rename to testsuite/tests/716-static-decision-merging-in-ckpt/common/src-simple/src-greet/pkg__st.ads From 2c0464043bd3559c65947a33b5fa9ff1a71e9c4a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 16 Jan 2025 08:45:21 +0000 Subject: [PATCH 1089/1483] instr-cov/gpr-complex: remove invalid Library_Dir GPR attribute While Library_Dir attributes in non-library projects were silently ignored with GNATCOLL.Projects, the upcoming GPR2 transition will make gnatcov emit errors for them. --- testsuite/tests/instr-cov/gpr-complex/main_simple.gpr | 1 - 1 file changed, 1 deletion(-) diff --git a/testsuite/tests/instr-cov/gpr-complex/main_simple.gpr b/testsuite/tests/instr-cov/gpr-complex/main_simple.gpr index e2e925761..425fcab8f 100644 --- a/testsuite/tests/instr-cov/gpr-complex/main_simple.gpr +++ b/testsuite/tests/instr-cov/gpr-complex/main_simple.gpr @@ -1,6 +1,5 @@ project Main_Simple extends "lib" is for Source_Dirs use ("src-main_simple"); for Object_Dir use "obj-main_simple"; - for Library_Dir use "lib-main_simple"; for Main use ("main.adb"); end Main_Simple; From ee2f13d74da3a90902f903553c67337e2c71940f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 16 Jan 2025 08:46:09 +0000 Subject: [PATCH 1090/1483] instr-cov/remove_extra_src: fix the dummy project While projects with no sources but with a given language (here: C) were silently ignored with GNATCOLL.Projects, the upcoming GPR2 transition will make gnatcov emit warnings for them. --- .../tests/instr-cov/remove_extra_src/src-dummy/.gitignore | 0 testsuite/tests/instr-cov/remove_extra_src/test.py | 4 ++-- 2 files changed, 2 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/instr-cov/remove_extra_src/src-dummy/.gitignore diff --git a/testsuite/tests/instr-cov/remove_extra_src/src-dummy/.gitignore b/testsuite/tests/instr-cov/remove_extra_src/src-dummy/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/tests/instr-cov/remove_extra_src/test.py b/testsuite/tests/instr-cov/remove_extra_src/test.py index ad0edb00c..2d18f6af0 100644 --- a/testsuite/tests/instr-cov/remove_extra_src/test.py +++ b/testsuite/tests/instr-cov/remove_extra_src/test.py @@ -40,8 +40,8 @@ dummy_gpr = gprfor( prjid="dummy", mains=[], - langs=["C"], - srcdirs=["../src-myprog"], + langs=[], + srcdirs=["../src-dummy"], objdir="obj-myprog", ) myprog_gpr = gprfor( From e34eb24d32db4ae6e362abb4b660aabd052ca855 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 16 Jan 2025 09:52:33 +0000 Subject: [PATCH 1091/1483] instr-cov/logging: improve output refiner for project process. order The upcoming GPR2 transition work reveals that the order of processing for projects to clear their object directories is not defined. Improve this testcase's output refiner so that changing the processing order does not affect the baseline comparison. --- testsuite/tests/instr-cov/logging/test.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/testsuite/tests/instr-cov/logging/test.py b/testsuite/tests/instr-cov/logging/test.py index c99f36fe9..8845ed086 100644 --- a/testsuite/tests/instr-cov/logging/test.py +++ b/testsuite/tests/instr-cov/logging/test.py @@ -87,6 +87,15 @@ def flush_files(): by_file = {} current_file = None result.append(line) + elif line.startswith( + "[GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing " + ): + _, project_name = line.rsplit(None, 1) + if by_file is None: + flush_files() + by_file = {} + by_file[project_name] = [line] + current_file = project_name elif by_file is None: # No section being processed: just forward this log line result.append(line) From d557ec546a4e0b9921116b849db00d2dc68c6414 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 16 Jan 2025 13:45:09 +0000 Subject: [PATCH 1092/1483] Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj: fix for GPR2 Let gprfor compute the set of languages automatically, so that empty.gpr has an empty list of languages. This is in order to avoid the following GPR2 warning: empty.gpr:16:20: warning: there are no sources of language "Ada" in this project --- .../Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py index 629fd7bca..aaaee4e9c 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py @@ -34,7 +34,6 @@ def generate(self, name, deps=(), mains=()): return gprfor( prjid=name, mains=mains, - langs=["Ada"], deps=deps, srcdirs=["../../src-{}".format(name)], objdir="obj-{}".format(name), From 2ca72c04d7cd4f7611db7bf0bdbcd6507b191623 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 16 Jan 2025 08:44:07 +0000 Subject: [PATCH 1093/1483] Testsuite: fix mismatches between main filenames and unit names While these inconsistencies were silently ignored with GNATCOLL.Projects, the upcoming GPR2 transition will make gnatcov emit warnings for them. --- testsuite/tests/131-hidden-bool-exprfunc/src/test_full.adb | 4 ++-- .../287-function_call_cov/access_to_subp/src/test_called.adb | 2 +- testsuite/tests/97-quant_expr_in_decl/src/test_0.adb | 4 ++-- testsuite/tests/97-quant_expr_in_decl/src/test_tf.adb | 4 ++-- testsuite/tests/98-quant_expr_nested/src/test_0.adb | 4 ++-- testsuite/tests/98-quant_expr_nested/src/test_full.adb | 4 ++-- testsuite/tests/Ada2022/raise_expr/src/test_pkg_f.adb | 4 ++-- testsuite/tests/Ada2022/raise_expr/src/test_pkg_raise.adb | 4 ++-- testsuite/tests/Ada2022/raise_expr/src/test_pkg_tfr.adb | 4 ++-- .../tests/Ada2022/reduce_attr/value_seq/src/test_full.adb | 4 ++-- .../tests/Ada2022/reduce_attr/value_seq/src/test_mult.adb | 4 ++-- .../tests/Ada2022/reduce_attr/value_seq/src/test_mult_z.adb | 4 ++-- .../tests/Ada2022/reduce_attr/value_seq/src/test_sum.adb | 4 ++-- .../tests/Ada2022/reduce_attr/value_seq/src/test_sum_z.adb | 4 ++-- testsuite/tests/instr-cov/ext_gpr/src/src-p_ext1/pkg1.ads | 4 ++-- testsuite/tests/instr-cov/ext_gpr/src/src-p_ext2/pkg2.ads | 4 ++-- .../guarded-exprs/stmt/minimal-in-decl/src/test_full.adb | 4 ++-- .../guarded-exprs/stmt/minimal-in-decl/src/test_none.adb | 4 ++-- .../guarded-exprs/stmt/minimal-in-decl/src/test_part.adb | 4 ++-- .../guarded-exprs/stmt/minimal-in-stmt/src/test_full.adb | 4 ++-- .../guarded-exprs/stmt/minimal-in-stmt/src/test_none.adb | 4 ++-- .../guarded-exprs/stmt/minimal-in-stmt/src/test_part.adb | 4 ++-- .../guarded-exprs/stmt/nested-case-exprs/src/test_full.adb | 4 ++-- .../guarded-exprs/stmt/nested-case-exprs/src/test_none.adb | 4 ++-- .../stmt/nested-case-exprs/src/test_partial_leaf.adb | 4 ++-- .../stmt/nested-case-exprs/src/test_partial_root.adb | 4 ++-- .../guarded-exprs/stmt/quantified-expr/src/test_non_empty.adb | 4 ++-- .../stmt/undetermined-coverage/src/test_full.adb | 4 ++-- testsuite/tests/trace_name/main.adb | 4 ++-- 29 files changed, 57 insertions(+), 57 deletions(-) diff --git a/testsuite/tests/131-hidden-bool-exprfunc/src/test_full.adb b/testsuite/tests/131-hidden-bool-exprfunc/src/test_full.adb index 8eaaf10a9..6e9672594 100644 --- a/testsuite/tests/131-hidden-bool-exprfunc/src/test_full.adb +++ b/testsuite/tests/131-hidden-bool-exprfunc/src/test_full.adb @@ -2,10 +2,10 @@ with Support; use Support; with Pkg; use Pkg; -procedure Test_0 is +procedure Test_Full is begin Assert (F (0) = 1); -end Test_0; +end Test_Full; --# pkg.ads -- diff --git a/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb index 1dff085f1..55a2eecb6 100644 --- a/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb +++ b/testsuite/tests/287-function_call_cov/access_to_subp/src/test_called.adb @@ -3,7 +3,7 @@ with Access_To_Subp; -- Check function and call coverage for an acces to a subprogram. -- Here, all calls and functions are executed. -procedure Test_Not_Called is +procedure Test_Called is begin Access_To_Subp; end; diff --git a/testsuite/tests/97-quant_expr_in_decl/src/test_0.adb b/testsuite/tests/97-quant_expr_in_decl/src/test_0.adb index 203d38250..3b4c9adb9 100644 --- a/testsuite/tests/97-quant_expr_in_decl/src/test_0.adb +++ b/testsuite/tests/97-quant_expr_in_decl/src/test_0.adb @@ -1,10 +1,10 @@ with Support; use Support; with Pkg; -procedure Test_No is +procedure Test_0 is begin null; -end Test_No; +end Test_0; --# pkg.adb -- diff --git a/testsuite/tests/97-quant_expr_in_decl/src/test_tf.adb b/testsuite/tests/97-quant_expr_in_decl/src/test_tf.adb index 2136c72e4..2ab906b6b 100644 --- a/testsuite/tests/97-quant_expr_in_decl/src/test_tf.adb +++ b/testsuite/tests/97-quant_expr_in_decl/src/test_tf.adb @@ -1,7 +1,7 @@ with Support; use Support; with Pkg; -procedure Test_T is +procedure Test_TF is All_T : Pkg.My_Arr := (True, True, True); All_F : Pkg.My_Arr := (False, False, False); begin @@ -9,7 +9,7 @@ begin Assert (Pkg.Some_True (All_T)); Assert (not Pkg.All_True (All_F)); Assert (not Pkg.Some_True (All_F)); -end Test_T; +end Test_TF; --# pkg.adb -- diff --git a/testsuite/tests/98-quant_expr_nested/src/test_0.adb b/testsuite/tests/98-quant_expr_nested/src/test_0.adb index 904cef813..b6590435f 100644 --- a/testsuite/tests/98-quant_expr_nested/src/test_0.adb +++ b/testsuite/tests/98-quant_expr_nested/src/test_0.adb @@ -2,10 +2,10 @@ with Support; use Support; with Pkg; use Pkg; -procedure Test_F_F is +procedure Test_0 is begin null; -end Test_F_F; +end Test_0; --# pkg.ads -- diff --git a/testsuite/tests/98-quant_expr_nested/src/test_full.adb b/testsuite/tests/98-quant_expr_nested/src/test_full.adb index 478a0c152..b18774c0d 100644 --- a/testsuite/tests/98-quant_expr_nested/src/test_full.adb +++ b/testsuite/tests/98-quant_expr_nested/src/test_full.adb @@ -2,13 +2,13 @@ with Support; use Support; with Pkg; use Pkg; -procedure Test_T_T is +procedure Test_Full is Arr_Main : My_Arr := (1 .. 10 => -18); Arr_Backup : My_Arr := (1 .. 4 => 4); begin Assert (All_Positive (Arr_Main, Arr_Backup, True)); Assert (not All_Positive (Arr_Main, Arr_Backup, False)); -end Test_T_T; +end Test_Full; --# pkg.ads -- diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_f.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_f.adb index 421e3e629..cb7f9a361 100644 --- a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_f.adb +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_f.adb @@ -2,10 +2,10 @@ with Support; with Pkg; use Pkg; -procedure Test_Pkg_T is +procedure Test_Pkg_F is begin Support.Assert (not Identity (A => False, Do_Raise => False)); -end Test_Pkg_T; +end Test_Pkg_F; --# pkg.adb -- diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_raise.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_raise.adb index 1aa8769bc..4fedea6ba 100644 --- a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_raise.adb +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_raise.adb @@ -2,13 +2,13 @@ with Support; with Pkg; use Pkg; -procedure Test_Pkg_T is +procedure Test_Pkg_Raise is begin Support.Assert (Identity (A => True, Do_Raise => True)); exception when Custom_Error => null; -end Test_Pkg_T; +end Test_Pkg_Raise; --# pkg.adb -- diff --git a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tfr.adb b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tfr.adb index b70147a79..14a17643d 100644 --- a/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tfr.adb +++ b/testsuite/tests/Ada2022/raise_expr/src/test_pkg_tfr.adb @@ -2,7 +2,7 @@ with Support; with Pkg; use Pkg; -procedure Test_Pkg_TF is +procedure Test_Pkg_TFR is begin Support.Assert (Identity (A => True, Do_Raise => False)); Support.Assert (not Identity (A => False, Do_Raise => False)); @@ -10,7 +10,7 @@ begin exception when Custom_Error => null; -end Test_Pkg_TF; +end Test_Pkg_TFR; -- This specific test shows that, despite having a T/F pair for Do_Raise, the -- raise expression evaluation prevents the last evaluation of the decision diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_full.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_full.adb index afe54634f..d78f6a7c3 100644 --- a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_full.adb +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_full.adb @@ -2,11 +2,11 @@ with Support; use Support; with Pkg; use Pkg; -procedure Test_Empty is +procedure Test_Full is Inp : Arr_T := (1, 2, 0, 3); begin Assert (Compute (Inp, Sum) = Compute (Inp, Abs_Mult)); -end Test_Empty; +end Test_Full; --# pkg.adb -- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult.adb index e7cee35db..f22a70b4c 100644 --- a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult.adb +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult.adb @@ -2,11 +2,11 @@ with Support; use Support; with Pkg; use Pkg; -procedure Test_Empty is +procedure Test_Mult is Inp : Arr_T := (1, 2, 3); begin Assert (Compute (Inp, Abs_Mult) = 6); -end Test_Empty; +end Test_Mult; --# pkg.adb -- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult_z.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult_z.adb index a064bb905..3c55f7256 100644 --- a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult_z.adb +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_mult_z.adb @@ -2,11 +2,11 @@ with Support; use Support; with Pkg; use Pkg; -procedure Test_Empty is +procedure Test_Mult_Z is Inp : Arr_T := (1, 2, 0, 3); begin Assert (Compute (Inp, Abs_Mult) = 6); -end Test_Empty; +end Test_Mult_Z; --# pkg.adb -- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum.adb index 86d167b1b..4e1cb1568 100644 --- a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum.adb +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum.adb @@ -2,11 +2,11 @@ with Support; use Support; with Pkg; use Pkg; -procedure Test_Empty is +procedure Test_Sum is Inp : Arr_T := (1, 2, 3); begin Assert (Compute (Inp, Sum) = 6); -end Test_Empty; +end Test_Sum; --# pkg.adb -- diff --git a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum_z.adb b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum_z.adb index 6f6dba7df..08ae83054 100644 --- a/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum_z.adb +++ b/testsuite/tests/Ada2022/reduce_attr/value_seq/src/test_sum_z.adb @@ -2,11 +2,11 @@ with Support; use Support; with Pkg; use Pkg; -procedure Test_Empty is +procedure Test_Sum_Z is Inp : Arr_T := (1, 2, 0, 3); begin Assert (Compute (Inp, Sum) = 6); -end Test_Empty; +end Test_Sum_Z; --# pkg.adb -- diff --git a/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext1/pkg1.ads b/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext1/pkg1.ads index 7b7b3258b..c50ad5356 100644 --- a/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext1/pkg1.ads +++ b/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext1/pkg1.ads @@ -1,3 +1,3 @@ -package Pkg_1 is +package Pkg1 is I : Integer; -end Pkg_1; +end Pkg1; diff --git a/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext2/pkg2.ads b/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext2/pkg2.ads index 36281d26b..5a4613b92 100644 --- a/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext2/pkg2.ads +++ b/testsuite/tests/instr-cov/ext_gpr/src/src-p_ext2/pkg2.ads @@ -1,3 +1,3 @@ -package Pkg_2 is +package Pkg2 is I : Integer; -end Pkg_2; +end Pkg2; diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_full.adb index b98718479..ef149ca67 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_full.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_full.adb @@ -1,12 +1,12 @@ with Ada.Text_IO; use Ada.Text_IO; with Animal; use Animal; -procedure Test_Case_Expr_Full is +procedure Test_Full is begin Put_Line (Scream (Dog)); Put_Line (Scream (Cat)); Put_Line (Scream (Cow)); -end Test_Case_Expr_Full; +end Test_Full; --# animal.adb -- /case_root/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_none.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_none.adb index 3882758e2..724a98b97 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_none.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_none.adb @@ -1,10 +1,10 @@ with Ada.Text_IO; use Ada.Text_IO; with Animal; use Animal; -procedure Test_Case_Expr_None is +procedure Test_None is begin null; -end Test_Case_Expr_None; +end Test_None; --# animal.adb -- /decl/ l- ## s- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_part.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_part.adb index 8b318fbf9..fdcdda275 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_part.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-decl/src/test_part.adb @@ -1,10 +1,10 @@ with Ada.Text_IO; use Ada.Text_IO; with Animal; use Animal; -procedure Test_Case_Expr_Part is +procedure Test_Part is begin Put_Line (Scream (Cat)); -end Test_Case_Expr_Part; +end Test_Part; --# animal.adb -- /case_root/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_full.adb index b98718479..ef149ca67 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_full.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_full.adb @@ -1,12 +1,12 @@ with Ada.Text_IO; use Ada.Text_IO; with Animal; use Animal; -procedure Test_Case_Expr_Full is +procedure Test_Full is begin Put_Line (Scream (Dog)); Put_Line (Scream (Cat)); Put_Line (Scream (Cow)); -end Test_Case_Expr_Full; +end Test_Full; --# animal.adb -- /case_root/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_none.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_none.adb index f05e7165c..cf5e01f44 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_none.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_none.adb @@ -1,10 +1,10 @@ with Ada.Text_IO; use Ada.Text_IO; with Animal; use Animal; -procedure Test_Case_Expr_None is +procedure Test_None is begin null; -end Test_Case_Expr_None; +end Test_None; --# animal.adb -- /return/ l- ## s- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_part.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_part.adb index 8b318fbf9..fdcdda275 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_part.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/minimal-in-stmt/src/test_part.adb @@ -1,10 +1,10 @@ with Ada.Text_IO; use Ada.Text_IO; with Animal; use Animal; -procedure Test_Case_Expr_Part is +procedure Test_Part is begin Put_Line (Scream (Cat)); -end Test_Case_Expr_Part; +end Test_Part; --# animal.adb -- /case_root/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_full.adb index 47a732d23..72634b9df 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_full.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_full.adb @@ -1,7 +1,7 @@ with Ada.Text_IO; use Ada.Text_IO; with Life; use Life; -procedure Test_Case_Expr_Full is +procedure Test_Full is A_Dog : constant Animal := (T => Mammal, M_Kind => Dog); A_Cat : constant Animal := (T => Mammal, M_Kind => Cat); A_Cow : constant Animal := (T => Mammal, M_Kind => Cow); @@ -13,7 +13,7 @@ begin Put_Line (Scream (A_Cow)); Put_Line (Scream (A_Snake)); Put_Line (Scream (A_Turtle)); -end Test_Case_Expr_Full; +end Test_Full; --# life.adb -- /return/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_none.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_none.adb index 4e281f986..9faf73b26 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_none.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_none.adb @@ -1,10 +1,10 @@ with Ada.Text_IO; use Ada.Text_IO; with Life; use Life; -procedure Test_Case_Expr_None is +procedure Test_None is begin null; -end Test_Case_Expr_None; +end Test_None; --# life.adb -- /return/ l- ## s- diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_leaf.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_leaf.adb index 50889f0dd..f45ecd3fe 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_leaf.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_leaf.adb @@ -1,7 +1,7 @@ with Ada.Text_IO; use Ada.Text_IO; with Life; use Life; -procedure Test_Case_Expr_Full is +procedure Test_Partial_Leaf is A_Dog : constant Animal := (T => Mammal, M_Kind => Dog); A_Cat : constant Animal := (T => Mammal, M_Kind => Cat); A_Cow : constant Animal := (T => Mammal, M_Kind => Cow); @@ -9,7 +9,7 @@ begin Put_Line (Scream (A_Dog)); Put_Line (Scream (A_Cat)); Put_Line (Scream (A_Cow)); -end Test_Case_Expr_Full; +end Test_Partial_Leaf; --# life.adb -- /return/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_root.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_root.adb index 0e91a1601..1642bdf5a 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_root.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/nested-case-exprs/src/test_partial_root.adb @@ -1,13 +1,13 @@ with Ada.Text_IO; use Ada.Text_IO; with Life; use Life; -procedure Test_Case_Expr_Full is +procedure Test_Partial_Root is A_Dog : constant Animal := (T => Mammal, M_Kind => Dog); A_Snake : constant Animal := (T => Reptile, R_Kind => Snake); begin Put_Line (Scream (A_Dog)); Put_Line (Scream (A_Snake)); -end Test_Case_Expr_Full; +end Test_Partial_Root; --# life.adb -- /return/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_non_empty.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_non_empty.adb index 0fdda2cee..524e17085 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_non_empty.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/quantified-expr/src/test_non_empty.adb @@ -1,11 +1,11 @@ with Ada.Text_IO; use Ada.Text_IO; with Pkg; use Pkg; -procedure Test_Empty is +procedure Test_Non_Empty is result : Boolean := Foo (1, 5); begin null; -end Test_Empty; +end Test_Non_Empty; --# pkg.adb -- /expr/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/test_full.adb b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/test_full.adb index 2d09de4e8..3ad6e4689 100644 --- a/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/test_full.adb +++ b/testsuite/tests/instr-cov/guarded-exprs/stmt/undetermined-coverage/src/test_full.adb @@ -1,12 +1,12 @@ with Ada.Text_IO; use Ada.Text_IO; with Animal; use Animal; -procedure Test_Case_Expr_Full is +procedure Test_Full is begin Put_Line (Scream (Dog)); Put_Line (Scream (Cat)); Put_Line (Scream (Cow)); -end Test_Case_Expr_Full; +end Test_Full; --# animal.adb -- /case_root/ l+ ## 0 diff --git a/testsuite/tests/trace_name/main.adb b/testsuite/tests/trace_name/main.adb index 3072b68a4..57d139b4a 100644 --- a/testsuite/tests/trace_name/main.adb +++ b/testsuite/tests/trace_name/main.adb @@ -1,6 +1,6 @@ with Ada.Text_IO; use Ada.Text_IO; -procedure Foo is +procedure Main is begin Put_Line ("Hello world!"); -end Foo; +end Main; From 6395a94da526f7d2f71ca5f2e77eead4842afdd8 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 21 Jan 2025 16:04:12 +0000 Subject: [PATCH 1094/1483] 287-function_call_cov: fix unit names --- .../287-function_call_cov/null_procedures/src/test_called.adb | 4 ++-- .../287-function_call_cov/protected_body/src/test_called.adb | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/testsuite/tests/287-function_call_cov/null_procedures/src/test_called.adb b/testsuite/tests/287-function_call_cov/null_procedures/src/test_called.adb index 3447c0082..a757062f8 100644 --- a/testsuite/tests/287-function_call_cov/null_procedures/src/test_called.adb +++ b/testsuite/tests/287-function_call_cov/null_procedures/src/test_called.adb @@ -1,11 +1,11 @@ with Pkg; use Pkg; -procedure Test_Not_Called is +procedure Test_Called is begin P1; P2 (1, 2); P3; -end Test_Not_Called; +end Test_Called; --# pkg.adb -- /p/ l+ ## 0 diff --git a/testsuite/tests/287-function_call_cov/protected_body/src/test_called.adb b/testsuite/tests/287-function_call_cov/protected_body/src/test_called.adb index b063752a6..24798453c 100644 --- a/testsuite/tests/287-function_call_cov/protected_body/src/test_called.adb +++ b/testsuite/tests/287-function_call_cov/protected_body/src/test_called.adb @@ -6,7 +6,7 @@ with Foo; use Foo; -- function, an expression function, a procedure and a null procedure inside -- a protected body. -procedure Test_Not_Called +procedure Test_Called is I : Integer := 42; begin @@ -15,7 +15,7 @@ begin Obj.P ("Hello"); end if; Obj.NP; -end Test_Not_Called; +end Test_Called; --# foo.ads -- /decl/ l+ ## 0 From 95b025f1d6a92e296b0bd5ac02b8c9255a5191a3 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 21 Jan 2025 16:04:59 +0000 Subject: [PATCH 1095/1483] OA27-059-sep-cons-prj*: fix case sensitivity for Switches indexes --- .../tests/OA27-059-sep-cons-prj-override/pkg_under_test.gpr | 4 ++-- testsuite/tests/OA27-059-sep-cons-prj/pkg_under_test.gpr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/testsuite/tests/OA27-059-sep-cons-prj-override/pkg_under_test.gpr b/testsuite/tests/OA27-059-sep-cons-prj-override/pkg_under_test.gpr index e46233907..f917b4339 100644 --- a/testsuite/tests/OA27-059-sep-cons-prj-override/pkg_under_test.gpr +++ b/testsuite/tests/OA27-059-sep-cons-prj-override/pkg_under_test.gpr @@ -5,9 +5,9 @@ project Pkg_Under_Test is for Object_Dir use "obj"; package Coverage is - for Switches ("Coverage") use + for Switches ("coverage") use ("--level=stmt+decision", "--annotate=xcov"); - for Switches ("Instrument") use ("--level=stmt+decision"); + for Switches ("instrument") use ("--level=stmt+decision"); for Units use ("Pkg_Under_Test"); for Ignored_Source_Files use ("pkg_under_test-some_procedure.adb"); end Coverage; diff --git a/testsuite/tests/OA27-059-sep-cons-prj/pkg_under_test.gpr b/testsuite/tests/OA27-059-sep-cons-prj/pkg_under_test.gpr index e6ede6f6c..a23fceecc 100644 --- a/testsuite/tests/OA27-059-sep-cons-prj/pkg_under_test.gpr +++ b/testsuite/tests/OA27-059-sep-cons-prj/pkg_under_test.gpr @@ -5,9 +5,9 @@ project Pkg_Under_Test is for Object_Dir use "obj"; package Coverage is - for Switches ("Coverage") use + for Switches ("coverage") use ("--level=stmt+decision", "--annotate=xcov"); - for Switches ("Instrument") use ("--level=stmt+decision"); + for Switches ("instrument") use ("--level=stmt+decision"); for Units use ("Pkg_Under_Test"); for Ignored_Source_Files use ("pkg_under_test-pkg_test.adb"); end Coverage; From 7a2d9072f7690874fb02dabbac04dfba2457ef62 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 22 Jan 2025 09:50:19 +0000 Subject: [PATCH 1096/1483] VC19-001-origin-prj: fix case sensitivity for Switches indexes --- testsuite/tests/VC19-001-origin-prj/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/VC19-001-origin-prj/test.py b/testsuite/tests/VC19-001-origin-prj/test.py index c42191de7..ce9230429 100644 --- a/testsuite/tests/VC19-001-origin-prj/test.py +++ b/testsuite/tests/VC19-001-origin-prj/test.py @@ -22,7 +22,7 @@ srcdirs=[os.path.join("..", "src_code")], extra="package Coverage is" '\n for Switches ("*") use ("--level=stmt+mcdc");' - '\n for Switches ("Coverage") use ("-axcov", "--output-dir=xcov");' + '\n for Switches ("coverage") use ("-axcov", "--output-dir=xcov");' "\nend Coverage;", ) From 535abe0dff6f1bc35bcd34a373114cc7ee0c06ef Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 22 Jan 2025 10:06:27 +0000 Subject: [PATCH 1097/1483] shared-libs/c-main: fix the 'no sources of language Ada' GPR2 warning Also update the docstring, which did not correctly describe the actual test project sources. --- testsuite/tests/shared-libs/c-main/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/shared-libs/c-main/test.py b/testsuite/tests/shared-libs/c-main/test.py index 666fd359e..b476eea27 100644 --- a/testsuite/tests/shared-libs/c-main/test.py +++ b/testsuite/tests/shared-libs/c-main/test.py @@ -1,6 +1,6 @@ """ Test that we can compute code coverage on Ada code located in a shared library. -Beyond the library, the program is a mix of Ada and C, and the main is in C. +Beyond the library, the program is composed of a C unit. """ import os @@ -31,7 +31,7 @@ main_gpr = gprfor( mains=["main.c"], prjid="main", - langs=["Ada", "C"], + langs=["C"], deps=["mylib"], srcdirs="../src-main", objdir="obj-main", From b151d9e7afa665d8321f21d79d6577346dfa4f3f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 15 Jan 2025 14:00:14 +0000 Subject: [PATCH 1098/1483] examples/support/base.gpr: workaround a GPR2 bug See gpr/gpr-issues#508 --- tools/gnatcov/examples/support/base.gpr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/examples/support/base.gpr b/tools/gnatcov/examples/support/base.gpr index c57b7eee0..b4525c5fa 100644 --- a/tools/gnatcov/examples/support/base.gpr +++ b/tools/gnatcov/examples/support/base.gpr @@ -10,7 +10,7 @@ abstract project Base is Style_Checks := external ("STYLE_CHECKS", "-gnaty"); - for Languages use ("Ada"); + for Languages use (); for Source_Files use (); package Compiler is From 765d9ffb31d036524ea3340de5f1926af5be8af2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 8 Jan 2025 09:23:21 +0000 Subject: [PATCH 1099/1483] Use vectors instead of array accesses to process command line arguments This is just a refactoring: no change of behavior is expected. --- tools/gnatcov/argparse.adb | 39 ++++++++++++--------------- tools/gnatcov/argparse.ads | 4 +-- tools/gnatcov/project.adb | 15 ++++++++--- tools/gnatcov/project.ads | 5 ++-- tools/gnatcov/switches.adb | 55 ++++++++++++++++---------------------- 5 files changed, 55 insertions(+), 63 deletions(-) diff --git a/tools/gnatcov/argparse.adb b/tools/gnatcov/argparse.adb index 16264519e..3448fc1f8 100644 --- a/tools/gnatcov/argparse.adb +++ b/tools/gnatcov/argparse.adb @@ -581,13 +581,13 @@ package body Argparse is function Parse (Parser : Parser_Type; - Args : GNAT.Strings.String_List_Access; + Args : String_Vectors.Vector; With_Command : Command_Type := No_Command; Callback : access procedure (Result : in out Parsed_Arguments; Ref : Option_Reference) := null) return Parsed_Arguments is - I : Positive := Args'First; + I : Natural := Args.First_Index; Result : Parsed_Arguments; function Error (S : String) return Parsed_Arguments is @@ -623,9 +623,7 @@ package body Argparse is -- is no argument left. function Consume_Next_Arg - (For_Arg : Slice; - I : in out Natural) - return GNAT.Strings.String_Access; + (For_Arg : Slice; I : in out Natural) return Unbounded_String; -- Fetch the next argument and return an access to it. Update I -- accordingly. Raise an Arg_Error if there is no argument left. @@ -686,7 +684,7 @@ package body Argparse is J : Natural) return String is - Arg : String renames Args (I).all; + Arg : constant String := +Args (I); begin -- The current short option requires a value: @@ -695,7 +693,7 @@ package body Argparse is -- If this is the last option in this argument, fetch the next -- argument. - return Consume_Next_Arg (For_Arg, I).all; + return +Consume_Next_Arg (For_Arg, I); else -- Otherwise, take the rest of the current argument (stripping the @@ -711,17 +709,14 @@ package body Argparse is ---------------------- function Consume_Next_Arg - (For_Arg : Slice; - I : in out Natural) - return GNAT.Strings.String_Access - is + (For_Arg : Slice; I : in out Natural) return Unbounded_String is begin - if I < Args'Last then + if I < Args.Last_Index then I := I + 1; return Args (I); else raise Arg_Error with - (Args (I).all (For_Arg.First .. For_Arg.Last) + (US.Slice (Args (I), For_Arg.First, For_Arg.Last) & " requires a value"); end if; end Consume_Next_Arg; @@ -795,8 +790,8 @@ package body Argparse is -- Greedy options consume all remaining arguments - for J in I .. Args'Last loop - Str_Vec.Append (+Args (J).all); + for J in I .. Args.Last_Index loop + Str_Vec.Append (Args (J)); end loop; return True; @@ -821,21 +816,21 @@ package body Argparse is if With_Command /= No_Command then Result.Command := With_Command; else - if Args'Length = 0 then + if Args.Is_Empty then return Error ("No command specified."); end if; declare - Command : constant GNAT.Strings.String_Access := Args (Args'First); + Command : constant String := +Args.First_Element; begin for Cmd in Parser.Data.Command_Infos'Range loop - if +Parser.Data.Command_Infos (Cmd).Name = Command.all then + if +Parser.Data.Command_Infos (Cmd).Name = Command then Result.Command := Cmd; exit; elsif Cmd = Command_Type'Last then return Error - ("Bad command: " & Command.all & ". Try option --help"); + ("Bad command: " & Command & ". Try option --help"); end if; end loop; end; @@ -844,9 +839,9 @@ package body Argparse is -- And the parse the arguments that follow - while I <= Args'Last loop + while I <= Args.Last_Index loop declare - Arg : String renames Args (I).all; + Arg : constant String := +Args (I); Option, Value : Slice; J : Natural; Has_Value : Boolean; @@ -908,7 +903,7 @@ package body Argparse is Str : constant Unbounded_String := (if Has_Value then +Arg (Value.First .. Value.Last) - else +Consume_Next_Arg (Option, I).all); + else Consume_Next_Arg (Option, I)); begin if Opt.Kind = String_Opt then if Parser.Data.String_Info diff --git a/tools/gnatcov/argparse.ads b/tools/gnatcov/argparse.ads index 7ff3a35bc..ed7e731ab 100644 --- a/tools/gnatcov/argparse.ads +++ b/tools/gnatcov/argparse.ads @@ -18,8 +18,6 @@ private with Ada.Finalization; -with GNAT.Strings; - with Strings; use Strings; -- This generic package is meant to take care of parsing command-line @@ -335,7 +333,7 @@ package Argparse is function Parse (Parser : Parser_Type; - Args : GNAT.Strings.String_List_Access; + Args : String_Vectors.Vector; With_Command : Command_Type := No_Command; Callback : access procedure (Result : in out Parsed_Arguments; Ref : Option_Reference) := null) diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index a3e7c97be..1dd54eacf 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -1504,16 +1504,25 @@ package body Project is -- Switches -- -------------- - function Switches (Op : String) return String_List_Access is + function Switches (Op : String) return String_Vectors.Vector is Origin_Prj : constant String := Prj_Tree.Root_Project.Attribute_Value (Origin_Project_Attribute); Actual_Prj : constant Project_Type := (if Origin_Prj = "" then Prj_Tree.Root_Project else Lookup_Project (Origin_Prj)); + Raw_Result : String_List_Access; begin - return Attribute_Value - (Actual_Prj, +Switches, Index => Op); + return Result : String_Vectors.Vector do + Raw_Result := Attribute_Value + (Actual_Prj, +Switches, Index => Op); + if Raw_Result /= null then + for S of Raw_Result.all loop + Result.Append (+S.all); + end loop; + Free (Raw_Result); + end if; + end return; end Switches; ----------------- diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index b936345dc..7734d262a 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -198,10 +198,9 @@ package Project is -- -- If no project is loaded, just return null. - function Switches (Op : String) return String_List_Access + function Switches (Op : String) return String_Vectors.Vector with Pre => Is_Project_Loaded; - -- Return a list of gnatcov switches defined by the root project. Caller - -- is responsible for deallocation. + -- Return a list of gnatcov switches defined by the root project function Output_Dir return String with Pre => Is_Project_Loaded; diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index f643dc13f..8070a7bef 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -32,18 +32,17 @@ package body Switches is use type Unbounded_String; use Command_Line.Parser; - function Command_Line_Args return String_List_Access; - -- Return a dynamically alocated list of arguments to hold arguments from - -- Ada.Command_Line. + function Command_Line_Args return String_Vectors.Vector; + -- Return a string vectors to hold arguments from Ada.Command_Line function Parse - (Argv : GNAT.Strings.String_List_Access; + (Argv : String_Vectors.Vector; With_Command : Command_Type := No_Command; Callback : access procedure (Result : in out Parsed_Arguments; Ref : Option_Reference) := null) return Parsed_Arguments; - -- Parse Args using Arg_Parser. Deallocate Args before returning. If there - -- is an error, call Fatal_Error with the error message. + -- Parse Args using Arg_Parser. If there is an error, call Fatal_Error with + -- the error message. procedure Load_Target_Option (Default_Target : Boolean); -- Split the --target option into its family name (Target_Family) and the @@ -402,14 +401,13 @@ package body Switches is -- Command_Line_Args -- ----------------------- - function Command_Line_Args return String_List_Access is - Result : constant String_List_Access := - new String_List (1 .. Ada.Command_Line.Argument_Count); + function Command_Line_Args return String_Vectors.Vector is begin - for I in Result'Range loop - Result (I) := new String'(Ada.Command_Line.Argument (I)); - end loop; - return Result; + return Result : String_Vectors.Vector do + for I in 1 .. Ada.Command_Line.Argument_Count loop + Result.Append (+Ada.Command_Line.Argument (I)); + end loop; + end return; end Command_Line_Args; ------------------------ @@ -584,26 +582,21 @@ package body Switches is declare Command_Name : constant String := Parser.Command_Name (Arg_Parser, Args.Command); - Common_Switches : constant String_List_Access := + Common_Switches : constant String_Vectors.Vector := Project.Switches ("*"); - Command_Switches : constant String_List_Access := + Command_Switches : constant String_Vectors.Vector := Project.Switches (Command_Name); begin - if Common_Switches /= null then - Project_Args := Parse - (Common_Switches, + Project_Args := Parse + (Common_Switches, + With_Command => Args.Command, + Callback => Check_Allowed_Option'Access); + Merge + (Project_Args, + Parse + (Command_Switches, With_Command => Args.Command, - Callback => Check_Allowed_Option'Access); - end if; - - if Command_Switches /= null then - Merge - (Project_Args, - Parse - (Command_Switches, - With_Command => Args.Command, - Callback => Check_Allowed_Option'Access)); - end if; + Callback => Check_Allowed_Option'Access)); -- Project_Args have precedence over Args, so merge in Project_Args -- first. @@ -639,18 +632,16 @@ package body Switches is ----------- function Parse - (Argv : GNAT.Strings.String_List_Access; + (Argv : String_Vectors.Vector; With_Command : Command_Type := No_Command; Callback : access procedure (Result : in out Parsed_Arguments; Ref : Option_Reference) := null) return Parsed_Arguments is - Args_Var : GNAT.Strings.String_List_Access := Argv; Result : constant Parsed_Arguments := Parse (Arg_Parser, Argv, With_Command, Callback); Error : constant String := +Result.Error; begin - Free (Args_Var); if Error'Length /= 0 then Args.Command := Result.Command; Fatal_Error_With_Usage (Error); From ea45c8902727801b9c22a4aad664d28e40010c16 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 16 Jan 2025 13:24:10 +0000 Subject: [PATCH 1100/1483] instrument-projects.adb: minor refactoring --- tools/gnatcov/instrument-projects.adb | 28 ++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 566141faf..c0a048941 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -433,6 +433,22 @@ is use Ada.Directories; procedure Free is new Ada.Unchecked_Deallocation (Project_Info, Project_Info_Access); + + procedure Delete_File_Wrapper (Filename : US.Unbounded_String); + -- Wrapper around Delete_File to ignore non-existing files + + ------------------------- + -- Delete_File_Wrapper -- + ------------------------- + + procedure Delete_File_Wrapper (Filename : US.Unbounded_String) is + F : constant String := +Filename; + begin + if Exists (F) then + Delete_File (F); + end if; + end Delete_File_Wrapper; + begin -- Deallocate all Project_Info in Context, and then clear the hashed -- map, both to avoid dangling pointers and to make Destroy_Context @@ -451,15 +467,9 @@ is -- Cleanup temporary artifacts if not instructed to keep them if not Save_Temps then - if Exists (+Context.Config_Pragmas_Mapping) then - Delete_File (+Context.Config_Pragmas_Mapping); - end if; - if Exists (+Context.Sources_Of_Interest_Response_File) then - Delete_File (+Context.Sources_Of_Interest_Response_File); - end if; - if Exists (+Context.Ada_Preprocessor_Data_File) then - Delete_File (+Context.Ada_Preprocessor_Data_File); - end if; + Delete_File_Wrapper (Context.Config_Pragmas_Mapping); + Delete_File_Wrapper (Context.Sources_Of_Interest_Response_File); + Delete_File_Wrapper (Context.Ada_Preprocessor_Data_File); end if; end Destroy_Context; From ccfe55f9db87c737b46859cb8fd4c98392c3af46 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 22 Jan 2025 09:36:31 +0000 Subject: [PATCH 1101/1483] sc_obligations.adb: minor reformattings --- tools/gnatcov/sc_obligations.adb | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 921037d40..d7e8be54e 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -1358,6 +1358,10 @@ package body SC_Obligations is procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) with pre => Kind (New_SCO_Id) = Decision; + ------------------------- + -- Merge_Decision_SCOs -- + ------------------------- + procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) is use SC_Obligations.BDD; @@ -1375,6 +1379,13 @@ package body SC_Obligations is SCO_Dec : SCO_Id; Eval : out Static_Decision_Evaluation) return Boolean; + procedure Register_Static_Evaluation + (SCO : SCO_Id; Eval : Static_Decision_Evaluation); + + -------------------------- + -- Decision_Static_Eval -- + -------------------------- + function Decision_Static_Eval (Vectors : Source_Coverage_Vectors; SCO_Dec : SCO_Id; @@ -1427,8 +1438,9 @@ package body SC_Obligations is return True; end Decision_Static_Eval; - procedure Register_Static_Evaluation - (SCO : SCO_Id; Eval : Static_Decision_Evaluation); + -------------------------------- + -- Register_Static_Evaluation -- + -------------------------------- procedure Register_Static_Evaluation (SCO : SCO_Id; Eval : Static_Decision_Evaluation) is @@ -1444,7 +1456,7 @@ package body SC_Obligations is .Include (Eval); end Register_Static_Evaluation; - -- Start processing of Merge_Decision_SCOs + -- Start processing of Merge_Decision_SCOs begin if Old_SCOD.Decision_Instrumented then @@ -1517,7 +1529,7 @@ package body SC_Obligations is end if; end Merge_Decision_SCOs; - -- Start processing of Checkpoint_Load_Merge_Unit + -- Start processing of Checkpoint_Load_Merge_Unit begin -- Here we already have loaded full SCO information for this CU. There From b80648b24a5c9260c770a4748bbad09cea7659c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Mon, 13 Jan 2025 13:28:15 +0100 Subject: [PATCH 1102/1483] instr-c: Rename Instrument_Statement to Add_SCO_And_Instrument_Statement To avoid confusion with the UIC.Pass.Instrument_Statement function --- tools/gnatcov/instrument-c.adb | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 3a2dcbfd9..06d2cc801 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2106,7 +2106,7 @@ package body Instrument.C is -- Traverse a statement. Set Trailing_Braces to the list of braces that -- should be inserted after this statement. - procedure Instrument_Statement + procedure Add_SCO_And_Instrument_Statement (N : Cursor_T; Typ : Character; Insertion_N : Cursor_T := Get_Null_Cursor; @@ -2175,7 +2175,7 @@ package body Instrument.C is -- Determine required type character code, or ASCII.NUL if -- no SCO should be generated for this node. - Instrument_Statement (N, ' '); + Add_SCO_And_Instrument_Statement (N, ' '); -- Process any embedded decisions @@ -2216,7 +2216,7 @@ package body Instrument.C is (UIC, Get_Children (N), TB, Is_Block => False); when Cursor_If_Stmt => - Instrument_Statement (N, 'I'); + Add_SCO_And_Instrument_Statement (N, 'I'); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); @@ -2249,7 +2249,7 @@ package body Instrument.C is end; when Cursor_Switch_Stmt => - Instrument_Statement (N, 'C'); + Add_SCO_And_Instrument_Statement (N, 'C'); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); declare @@ -2282,7 +2282,7 @@ package body Instrument.C is -- If the loop condition is a declaration, instrument its -- initialization expression. - Instrument_Statement + Add_SCO_And_Instrument_Statement (N, 'W', Insertion_N => (if Is_Null (Cond_Var) then Cond @@ -2311,7 +2311,7 @@ package body Instrument.C is -- Process the while decision - Instrument_Statement + Add_SCO_And_Instrument_Statement (Do_While, 'W', Instr_Scheme => Instr_Expr); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); @@ -2325,11 +2325,11 @@ package body Instrument.C is For_Inc : constant Cursor_T := Get_For_Inc (N); For_Body : constant Cursor_T := Get_Body (N); begin - Instrument_Statement + Add_SCO_And_Instrument_Statement (For_Init, ' ', Insertion_N => N); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); - Instrument_Statement + Add_SCO_And_Instrument_Statement (For_Cond, 'F', Instr_Scheme => Instr_Expr); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); @@ -2341,7 +2341,7 @@ package body Instrument.C is Traverse_Statements (UIC, To_Vector (For_Body), TB); - Instrument_Statement + Add_SCO_And_Instrument_Statement (For_Inc, ' ', Instr_Scheme => Instr_Expr); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); @@ -2362,7 +2362,7 @@ package body Instrument.C is -- See Fix_CXX_For_Ranges for an explanation of the -- below code. - Instrument_Statement + Add_SCO_And_Instrument_Statement (For_Init_Stmt, ' ', Insertion_N => For_Init_Stmt); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); @@ -2377,7 +2377,7 @@ package body Instrument.C is -- Instrument the range as mentioned above - Instrument_Statement + Add_SCO_And_Instrument_Statement (For_Range_Decl, ' ', Insertion_N => N, Instr_Scheme => Instr_Stmt); @@ -2393,7 +2393,7 @@ package body Instrument.C is end; when Cursor_Goto_Stmt | Cursor_Indirect_Goto_Stmt => - Instrument_Statement (N, ' '); + Add_SCO_And_Instrument_Statement (N, ' '); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); @@ -2404,7 +2404,7 @@ package body Instrument.C is (UIC, Get_Children (N), TB, Is_Block => False); when Cursor_Break_Stmt => - Instrument_Statement (N, ' '); + Add_SCO_And_Instrument_Statement (N, ' '); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); @@ -2432,7 +2432,7 @@ package body Instrument.C is UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); else - Instrument_Statement (N, ' '); + Add_SCO_And_Instrument_Statement (N, ' '); if Has_Decision (N) then Process_Expression (UIC, N, 'X'); end if; @@ -2463,7 +2463,7 @@ package body Instrument.C is -- Instrument_Statement -- -------------------------- - procedure Instrument_Statement + procedure Add_SCO_And_Instrument_Statement (N : Cursor_T; Typ : Character; Insertion_N : Cursor_T := Get_Null_Cursor; @@ -2521,7 +2521,7 @@ package body Instrument.C is LL_SCO => SCOs.SCO_Table.Last, Insertion_N => (if Is_Null (Insertion_N) then N else Insertion_N), Instr_Scheme => Instr_Scheme); - end Instrument_Statement; + end Add_SCO_And_Instrument_Statement; ------------- -- Curlify -- From 8bbb65e2a3cc56c43a96cd416c3866f21578e4fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Mon, 13 Jan 2025 15:59:02 +0100 Subject: [PATCH 1103/1483] instr-c: Instrument functions --- tools/gnatcov/clang-extensions.ads | 8 ++ tools/gnatcov/clang-wrapper.cc | 69 ++++++++++++++++ tools/gnatcov/instrument-c.adb | 125 +++++++++++++++++++---------- tools/gnatcov/instrument-c.ads | 10 ++- 4 files changed, 170 insertions(+), 42 deletions(-) diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index 4543e149e..ea173db58 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -33,6 +33,14 @@ package Clang.Extensions is function Get_Body (C : Cursor_T) return Cursor_T with Import, Convention => C, External_Name => "clang_getBody"; + function Get_Function_Signature_Sloc (C : Cursor_T) return Source_Range_T + with + Import, + Convention => C, + External_Name => "clang_getFunctionSignatureSloc"; + -- Given a FunctionDecl or LambdaExpr, returns the Source Range of the + -- signature, thus excluding the body if there is one. + function Get_Cond (C : Cursor_T) return Cursor_T with Import, Convention => C, External_Name => "clang_getCond"; diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 42ef83fc0..13c158ac3 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -351,6 +351,75 @@ clang_getLBracLocPlusOne (CXCursor C) return translateSLoc (TU, S->getLBracLoc ().getLocWithOffset (1)); } +extern "C" CXSourceRange +clang_getFunctionSignatureSloc (CXCursor C) +{ + SourceLocation Begin (translateSourceLocation (clang_getNullLocation ())); + CompoundStmt *Func_Body = nullptr; + + if (clang_isDeclaration (C.kind)) + { + if (const Decl *D = getCursorDecl (C)) + { + const FunctionDecl *FD = nullptr; + + switch (D->getKind ()) + { + case Decl::Function: + case Decl::CXXMethod: + case Decl::CXXConstructor: + case Decl::CXXDestructor: + case Decl::CXXConversion: + FD = cast (D); + break; + case Decl::FunctionTemplate: + FD = cast (D)->getTemplatedDecl (); + break; + default: + // D is not a function declaration + break; + } + if (FD) + { + const SourceRange SR = FD->getSourceRange (); + Begin = SR.getBegin (); + Func_Body = cast (FD->getBody ()); + } + } + } + else if (clang_isExpression (C.kind)) + { + if (const Expr *E = getCursorExpr (C)) + { + switch (E->getStmtClass ()) + { + case Expr::LambdaExprClass: + { + const LambdaExpr *LE = cast (E); + const SourceRange SR = LE->getSourceRange (); + Begin = SR.getBegin (); + Func_Body = cast (LE->getBody ()); + } + break; + default: + // E is not a lambda expression + break; + } + } + } + + // If Func_Body is still nullptr, the cursor is not a valid function + // declaration. + if (!Func_Body) + return clang_getNullRange (); + + // ??? right now, `Func_Body->getBeginLoc` points on the opening bracket, + // which is not ideal. Ideally, we would cut the Source Range after the + // closing parenthesis (or after the `const`, or `throw` argument). + return translateSourceRange (getContext (C), + SourceRange (Begin, Func_Body->getBeginLoc ())); +} + extern "C" CXCursor clang_getSubExpr (CXCursor C) { diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 06d2cc801..e680b1431 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -1368,6 +1368,12 @@ package body Instrument.C is Text => Make_Statement_Witness (UIC, Buffers_Index, Bit), Rew => UIC.Rewriter); + when Instr_In_Compound => + Insert_Text_In_Brackets + (CmpdStmt => SS.Statement, + Text => Make_Statement_Witness (UIC, Buffers_Index, Bit), + Rew => UIC.Rewriter); + when Instr_Expr => Insert_Text_After_Start_Of (N => SS.Statement, @@ -2647,50 +2653,85 @@ package body Instrument.C is -- Only instrument definitions, not declarations. -- Lambda expressions are always definitions. - if Is_This_Declaration_A_Definition (N) or else - Cursor_Kind = Cursor_Lambda_Expr + if not (Is_This_Declaration_A_Definition (N) or else + Cursor_Kind = Cursor_Lambda_Expr) then - declare - Fun_Body : constant Cursor_T := Get_Body (N); - Stmts : constant Cursor_Vectors.Vector := - Get_Children (Fun_Body); - -- Get_Body returns a Compound_Stmt, convert it to a - -- list of statements using the Get_Children utility. + goto Continue; + end if; + + declare + Fun_Body : constant Cursor_T := Get_Body (N); + Stmts : constant Cursor_Vectors.Vector := + Get_Children (Fun_Body); + -- Get_Body returns a Compound_Stmt, convert it to a + -- list of statements using the Get_Children utility. - TB : Unbounded_String; - -- Trailing braces that should be inserted at the end - -- of the function body. + TB : Unbounded_String; + -- Trailing braces that should be inserted at the end + -- of the function body. - begin - if Cursor_Kind /= Cursor_Lambda_Expr then - UIC.Pass.Enter_Scope (UIC, N); - end if; - - -- Do not instrument constexpr function as it would - -- violate the constexpr restrictions. - - if Is_Constexpr (N) then - UIC.Pass.Report - (N, - "gnatcov limitation: cannot instrument constexpr" - & " functions."); - UIC.Disable_Instrumentation := True; - end if; - - if Stmts.Length > 0 then - UIC.MCDC_State_Declaration_Node := - Stmts.First_Element; - Traverse_Statements (UIC, Stmts, TB); - UIC.Pass.Insert_Text_Before_Token - (UIC, End_Sloc (Fun_Body), +TB); - end if; - if Cursor_Kind /= Cursor_Lambda_Expr then - UIC.Pass.Exit_Scope (UIC); - end if; - UIC.Disable_Instrumentation := - Save_Disable_Instrumentation; - end; - end if; + begin + if Cursor_Kind /= Cursor_Lambda_Expr then + UIC.Pass.Enter_Scope (UIC, N); + end if; + + -- Do not instrument constexpr function as it would + -- violate the constexpr restrictions. + + if Is_Constexpr (N) then + UIC.Pass.Report + (N, + "gnatcov limitation: cannot instrument constexpr" + & " functions."); + UIC.Disable_Instrumentation := True; + end if; + + if Stmts.Length > 0 then + UIC.MCDC_State_Declaration_Node := + Stmts.First_Element; + Traverse_Statements (UIC, Stmts, TB); + UIC.Pass.Insert_Text_Before_Token + (UIC, End_Sloc (Fun_Body), +TB); + end if; + + if Enabled (Coverage_Options.Fun_Call) and then + Fun_Body /= Get_Null_Cursor + then + Sources_Trace.Trace ("Instrument Function at " + & Image + (Start_Sloc (Fun_Body))); + + declare + Signature_SR : constant Source_Range_T := + Get_Function_Signature_Sloc (N); + begin + UIC.Pass.Append_SCO + (UIC => UIC, + N => N, + C1 => 'c', + C2 => 'F', + From => Sloc (Get_Range_Start (Signature_SR)), + To => Sloc (Get_Range_End (Signature_SR)), + Last => True); + end; + + UIC.Pass.Start_Statement_Block (UIC); + + UIC.Pass.Instrument_Statement + (UIC => UIC, + LL_SCO => SCOs.SCO_Table.Last, + Insertion_N => Fun_Body, + Instr_Scheme => Instr_In_Compound); + + UIC.Pass.End_Statement_Block (UIC); + end if; + + if Cursor_Kind /= Cursor_Lambda_Expr then + UIC.Pass.Exit_Scope (UIC); + end if; + UIC.Disable_Instrumentation := + Save_Disable_Instrumentation; + end; -- Traverse the declarations of a namespace / linkage -- specification etc. @@ -2714,6 +2755,8 @@ package body Instrument.C is end case; end if; + + <> end loop; -- Restore previous MCDC_State insertion node: we can have lambda diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 1fc33729c..95b91d863 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -154,7 +154,7 @@ package Instrument.C is -- Create a C++ instrumenter. See the definition of the -- Language_Instrumenter type for the arguments semantic. - type Instr_Scheme_Type is (Instr_Stmt, Instr_Expr); + type Instr_Scheme_Type is (Instr_Stmt, Instr_Expr, Instr_In_Compound); -- Depending on the statement construct, we can instrument it either with -- another statement right before (Instr_Stmt), which is the case for most -- statements: @@ -179,6 +179,14 @@ package Instrument.C is -- very well be a goto pointing inside the loop, making it skip the -- execution of the witness statement, but we would still be executing the -- condition of the loop on the second iteration. + -- + -- The variant Instr_In_Compound shall be used with a Compound Statement + -- only. The specificity of a compound statement is that it is delimited + -- by brackets. Using this scheme, the instrumentation will insert a + -- witness statement *just* after the opening bracket. This is used for + -- Function coverage, and particularly useful for functions with empty + -- bodies in which it is not possible to refer to the body's first + -- statement to insert a witness statement before it. type C_Source_Statement is record LL_SCO : Nat; From 9a640f2e88e2ea820fa4ee867f86e808bbf1d899 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Mon, 13 Jan 2025 10:07:30 +0100 Subject: [PATCH 1104/1483] instr-c: Instrument call expressions and statements --- tools/gnatcov/clang-extensions.adb | 13 ++++ tools/gnatcov/clang-extensions.ads | 15 +++++ tools/gnatcov/clang-wrapper.cc | 31 ++++++++++ tools/gnatcov/instrument-c.adb | 95 ++++++++++++++++++++++++------ 4 files changed, 137 insertions(+), 17 deletions(-) diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index 808d42777..47ca7623c 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -72,6 +72,19 @@ package body Clang.Extensions is return CalleeName; end Get_Callee_Name_Str; + --------------------------------- + -- Is_Instrumentable_Call_Expr -- + --------------------------------- + + function Is_Instrumentable_Call_Expr (C : Cursor_T) return Boolean is + function Is_Instrumentable_Call_Expr_C (C : Cursor_T) return unsigned + with + Import, Convention => C, + External_Name => "clang_isInstrumentableCallExpr"; + begin + return Is_Instrumentable_Call_Expr_C (C) /= 0; + end Is_Instrumentable_Call_Expr; + -------------------- -- Get_Opcode_Str -- -------------------- diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index ea173db58..5b2e6d145 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -115,6 +115,21 @@ package Clang.Extensions is -- opening bracket. Giving another kind of cursor will return a null -- location. + function Is_Instrumentable_Call_Expr (C : Cursor_T) return Boolean + with Inline; + -- Given a cursor C, return True if the cursor kind is CallExpr AND if + -- the underlying C++ statement class is one of: + -- - Stmt::CallExprClass + -- - Stmt::CXXOperatorCallExprClass + -- - Stmt::CXXMemberCallExprClass + -- + -- CXCursor_CallExpr is also used for other kinds of nodes that we do not + -- wish to instrument for function coverage, and that we need to use the + -- C++ API to detect. + -- + -- TODO??? Actually decide what to do for the rest, so Ctor/Dtor call + -- coverage makes sense. + function Is_Constexpr (C : Cursor_T) return Boolean with Inline; function Unwrap (C : Cursor_T) return Cursor_T diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 13c158ac3..b29cb0594 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -351,6 +351,37 @@ clang_getLBracLocPlusOne (CXCursor C) return translateSLoc (TU, S->getLBracLoc ().getLocWithOffset (1)); } +extern "C" bool +clang_isInstrumentableCallExpr (CXCursor C) +{ + if (!clang_isExpression (C.kind)) + return false; + + // return C.kind == CXCursor_CallExpr; + + const Expr *E = getCursorExpr (C); + switch (E->getStmtClass ()) + { + case Stmt::CallExprClass: // Simple call expression + case Stmt::CXXOperatorCallExprClass: // C++ Overloaded operator call + case Stmt::CXXMemberCallExprClass: // C++ Method Call + + // TODO??? All theses classes are regrouped under the CXCursor_Call_Expr + // kind. Decide what to do with them, so the call coverage + // instrumentation of Ctors and Dtors makes sense. + // case Stmt::CUDAKernelCallExprClass: + // case Stmt::CXXConstructExprClass: + // case Stmt::CXXInheritedCtorInitExprClass: + // case Stmt::CXXTemporaryObjectExprClass: + // case Stmt::CXXUnresolvedConstructExprClass: + // case Stmt::UserDefinedLiteralClass: + return true; + + default: + return false; + } +} + extern "C" CXSourceRange clang_getFunctionSignatureSloc (CXCursor C) { diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index e680b1431..ca342e07a 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -1605,6 +1605,53 @@ package body Instrument.C is end if; end Is_Complex_Decision; + ----------------------- + -- Process_Call_Expr -- + ----------------------- + + procedure Process_Call_Expr + (UIC : in out C_Unit_Inst_Context; Cursor : Cursor_T); + + procedure Process_Call_Expr + (UIC : in out C_Unit_Inst_Context; Cursor : Cursor_T) + is + function Visit_Call_Expr (C : Cursor_T) return Child_Visit_Result_T; + + function Visit_Call_Expr (C : Cursor_T) return Child_Visit_Result_T is + begin + if Kind (C) = Cursor_Lambda_Expr then + return Child_Visit_Continue; + end if; + + if Is_Instrumentable_Call_Expr (C) then + Sources_Trace.Trace ("Instrument Call at " + & Image (Start_Sloc (C))); + + UIC.Pass.Append_SCO + (UIC => UIC, + N => C, + C1 => 'c', + C2 => 'S', + From => Start_Sloc (C), + To => End_Sloc (C), + Last => True); + + UIC.Pass.Instrument_Statement + (UIC => UIC, + LL_SCO => SCOs.SCO_Table.Last, + Insertion_N => C, + Instr_Scheme => Instr_Expr); + end if; + + return Child_Visit_Recurse; + end Visit_Call_Expr; + + begin + if Enabled (Coverage_Options.Fun_Call) then + Visit (Cursor, Visit_Call_Expr'Access); + end if; + end Process_Call_Expr; + ------------------------ -- Process_Expression -- ------------------------ @@ -2010,6 +2057,9 @@ package body Instrument.C is end if; Process_Decisions (UIC, N, T); + + Process_Call_Expr (UIC, N); + Visit (N, Process_Lambda_Expr'Access); end Process_Expression; @@ -2114,7 +2164,8 @@ package body Instrument.C is procedure Add_SCO_And_Instrument_Statement (N : Cursor_T; - Typ : Character; + C1 : Character := 'S'; + C2 : Character := ' '; Insertion_N : Cursor_T := Get_Null_Cursor; Instr_Scheme : Instr_Scheme_Type := Instr_Stmt); -- Instrument the statement N. @@ -2181,7 +2232,7 @@ package body Instrument.C is -- Determine required type character code, or ASCII.NUL if -- no SCO should be generated for this node. - Add_SCO_And_Instrument_Statement (N, ' '); + Add_SCO_And_Instrument_Statement (N, C2 => ' '); -- Process any embedded decisions @@ -2222,7 +2273,7 @@ package body Instrument.C is (UIC, Get_Children (N), TB, Is_Block => False); when Cursor_If_Stmt => - Add_SCO_And_Instrument_Statement (N, 'I'); + Add_SCO_And_Instrument_Statement (N, C2 => 'I'); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); @@ -2255,7 +2306,7 @@ package body Instrument.C is end; when Cursor_Switch_Stmt => - Add_SCO_And_Instrument_Statement (N, 'C'); + Add_SCO_And_Instrument_Statement (N, C2 => 'C'); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); declare @@ -2289,7 +2340,8 @@ package body Instrument.C is -- initialization expression. Add_SCO_And_Instrument_Statement - (N, 'W', + (N, + C2 => 'W', Insertion_N => (if Is_Null (Cond_Var) then Cond else Get_Var_Init_Expr (Cond_Var)), @@ -2318,7 +2370,7 @@ package body Instrument.C is -- Process the while decision Add_SCO_And_Instrument_Statement - (Do_While, 'W', Instr_Scheme => Instr_Expr); + (Do_While, C2 => 'W', Instr_Scheme => Instr_Expr); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); Process_Expression (UIC, Do_While, 'W'); @@ -2332,11 +2384,11 @@ package body Instrument.C is For_Body : constant Cursor_T := Get_Body (N); begin Add_SCO_And_Instrument_Statement - (For_Init, ' ', Insertion_N => N); + (For_Init, C2 => ' ', Insertion_N => N); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); Add_SCO_And_Instrument_Statement - (For_Cond, 'F', Instr_Scheme => Instr_Expr); + (For_Cond, C2 => 'F', Instr_Scheme => Instr_Expr); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); @@ -2348,7 +2400,7 @@ package body Instrument.C is Traverse_Statements (UIC, To_Vector (For_Body), TB); Add_SCO_And_Instrument_Statement - (For_Inc, ' ', Instr_Scheme => Instr_Expr); + (For_Inc, C2 => ' ', Instr_Scheme => Instr_Expr); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); end; @@ -2369,7 +2421,9 @@ package body Instrument.C is -- below code. Add_SCO_And_Instrument_Statement - (For_Init_Stmt, ' ', Insertion_N => For_Init_Stmt); + (For_Init_Stmt, + C2 => ' ', + Insertion_N => For_Init_Stmt); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); Process_Expression (UIC, For_Init_Stmt, 'X'); @@ -2384,7 +2438,7 @@ package body Instrument.C is -- Instrument the range as mentioned above Add_SCO_And_Instrument_Statement - (For_Range_Decl, ' ', + (For_Range_Decl, C2 => ' ', Insertion_N => N, Instr_Scheme => Instr_Stmt); UIC.Pass.End_Statement_Block (UIC); @@ -2399,7 +2453,7 @@ package body Instrument.C is end; when Cursor_Goto_Stmt | Cursor_Indirect_Goto_Stmt => - Add_SCO_And_Instrument_Statement (N, ' '); + Add_SCO_And_Instrument_Statement (N, C2 => ' '); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); @@ -2410,7 +2464,7 @@ package body Instrument.C is (UIC, Get_Children (N), TB, Is_Block => False); when Cursor_Break_Stmt => - Add_SCO_And_Instrument_Statement (N, ' '); + Add_SCO_And_Instrument_Statement (N, C2 => ' '); UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); @@ -2438,9 +2492,15 @@ package body Instrument.C is UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); else - Add_SCO_And_Instrument_Statement (N, ' '); + Add_SCO_And_Instrument_Statement (N, C2 => ' '); + + -- Only call Process_Call_Expr if Process_Expression was + -- not called, because it will do it otherwise. + if Has_Decision (N) then Process_Expression (UIC, N, 'X'); + else + Process_Call_Expr (UIC, N); end if; end if; @@ -2471,7 +2531,8 @@ package body Instrument.C is procedure Add_SCO_And_Instrument_Statement (N : Cursor_T; - Typ : Character; + C1 : Character := 'S'; + C2 : Character := ' '; Insertion_N : Cursor_T := Get_Null_Cursor; Instr_Scheme : Instr_Scheme_Type := Instr_Stmt) is @@ -2516,8 +2577,8 @@ package body Instrument.C is UIC.Pass.Append_SCO (UIC => UIC, N => N, - C1 => 'S', - C2 => Typ, + C1 => C1, + C2 => C2, From => F, To => T, Last => True); From 03f18747dfbd01ed923c5e63e5889c4a5c2a6ff3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Tue, 21 Jan 2025 16:40:21 +0100 Subject: [PATCH 1105/1483] instr-c: move the Start_Statement_Block before call to Append_SCO --- tools/gnatcov/instrument-c.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index ca342e07a..b965bdd77 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2762,6 +2762,8 @@ package body Instrument.C is & Image (Start_Sloc (Fun_Body))); + UIC.Pass.Start_Statement_Block (UIC); + declare Signature_SR : constant Source_Range_T := Get_Function_Signature_Sloc (N); @@ -2776,8 +2778,6 @@ package body Instrument.C is Last => True); end; - UIC.Pass.Start_Statement_Block (UIC); - UIC.Pass.Instrument_Statement (UIC => UIC, LL_SCO => SCOs.SCO_Table.Last, From 233536af8dc95c06fb614ebb11108eef7f5da8d8 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 23 Jan 2025 16:47:57 +0100 Subject: [PATCH 1106/1483] instr-c: get rid of Has_Decisions as it is useless --- tools/gnatcov/instrument-c.adb | 59 +--------------------------------- 1 file changed, 1 insertion(+), 58 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index b965bdd77..736f2b73c 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -1574,11 +1574,6 @@ package body Instrument.C is -- Internal Subprograms -- -------------------------- - function Has_Decision (T : Cursor_T) return Boolean; - -- T is the node for a subtree. Returns True if any (sub)expression in T - -- contains a nested decision (i.e. either is a logical operator, or - -- contains a logical operator in its subtree). - function Is_Logical_Operator (N : Cursor_T) return Boolean; -- Return whether N is an operator that can be part of a decision (! or -- && / ||). @@ -2063,51 +2058,6 @@ package body Instrument.C is Visit (N, Process_Lambda_Expr'Access); end Process_Expression; - ------------------ - -- Has_Decision -- - ------------------ - - function Has_Decision (T : Cursor_T) return Boolean is - - function Visitor (N : Cursor_T) return Child_Visit_Result_T; - -- If N's kind indicates the presence of a decision, return - -- Child_Visit_Break, otherwise return Child_Visit_Recurse. - -- - -- We know have a decision as soon as we have a logical operator (by - -- definition). - - Has_Decision : Boolean := False; - - ----------- - -- Visit -- - ----------- - - function Visitor (N : Cursor_T) return Child_Visit_Result_T - is - begin - if (Is_Expression (Kind (N)) and then Is_Complex_Decision (N)) - or else Kind (N) = Cursor_Conditional_Operator - then - Has_Decision := True; - return Child_Visit_Break; - - -- We don't want to visit lambda expressions: we will treat them - -- outside of the current expression. - - elsif Kind (N) = Cursor_Lambda_Expr then - return Child_Visit_Continue; - else - return Child_Visit_Recurse; - end if; - end Visitor; - - -- Start of processing for Has_Decision - - begin - Visit (T, Visitor'Access); - return Has_Decision; - end Has_Decision; - ------------------------- -- Is_Logical_Operator -- ------------------------- @@ -2494,14 +2444,7 @@ package body Instrument.C is else Add_SCO_And_Instrument_Statement (N, C2 => ' '); - -- Only call Process_Call_Expr if Process_Expression was - -- not called, because it will do it otherwise. - - if Has_Decision (N) then - Process_Expression (UIC, N, 'X'); - else - Process_Call_Expr (UIC, N); - end if; + Process_Expression (UIC, N, 'X'); end if; when Cursor_Decl_Stmt => From bf6b00f7dd32de8495d8fa1b9a4fcecf81af139e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 17 Jan 2025 12:17:32 +0100 Subject: [PATCH 1107/1483] tests: Add tests for Fun_Call C/C++ instrumentation --- .../c/calls-in-macros/src/pkg.c | 17 +++++++++ .../c/calls-in-macros/src/pkg.h | 6 ++++ .../c/calls-in-macros/src/test_call.c | 11 ++++++ .../c/calls-in-macros/src/test_no_call.c | 14 ++++++++ .../c/calls-in-macros/test.py | 11 ++++++ .../c/function-pointers/src/pkg.c | 32 +++++++++++++++++ .../c/function-pointers/src/pkg.h | 11 ++++++ .../c/function-pointers/src/test_call_one.c | 13 +++++++ .../c/function-pointers/src/test_call_two.c | 13 +++++++ .../c/function-pointers/src/test_no_call.c | 18 ++++++++++ .../c/function-pointers/test.py | 10 ++++++ .../c/nested-calls/src/pkg.c | 22 ++++++++++++ .../c/nested-calls/src/pkg.h | 6 ++++ .../c/nested-calls/src/test_call.c | 12 +++++++ .../c/nested-calls/src/test_no_call.c | 17 +++++++++ .../c/nested-calls/test.py | 11 ++++++ .../c/regular-functions/src/pkg.c | 36 +++++++++++++++++++ .../c/regular-functions/src/pkg.h | 6 ++++ .../c/regular-functions/src/test_call.c | 11 ++++++ .../c/regular-functions/src/test_no_call.c | 14 ++++++++ .../c/regular-functions/test.py | 10 ++++++ .../c_cpp_function_call_cov/cpp/extra.opt | 1 + .../cpp/generics/src/pkg.cpp | 20 +++++++++++ .../cpp/generics/src/pkg.h | 6 ++++ .../cpp/generics/src/test_call.cpp | 11 ++++++ .../cpp/generics/src/test_no_call.cpp | 14 ++++++++ .../cpp/generics/test.py | 11 ++++++ .../cpp/lambda-functions/src/pkg.cpp | 20 +++++++++++ .../cpp/lambda-functions/src/pkg.h | 6 ++++ .../cpp/lambda-functions/src/test_call.cpp | 11 ++++++ .../cpp/lambda-functions/src/test_no_call.cpp | 18 ++++++++++ .../cpp/lambda-functions/test.py | 11 ++++++ .../cpp/methods-ctors-dtors/src/pkg.cpp | 31 ++++++++++++++++ .../cpp/methods-ctors-dtors/src/pkg.h | 6 ++++ .../cpp/methods-ctors-dtors/src/test_call.cpp | 11 ++++++ .../methods-ctors-dtors/src/test_no_call.cpp | 16 +++++++++ .../cpp/methods-ctors-dtors/test.py | 15 ++++++++ .../cpp/namespaced-functions/src/pkg.cpp | 31 ++++++++++++++++ .../cpp/namespaced-functions/src/pkg.h | 7 ++++ .../namespaced-functions/src/test_call.cpp | 11 ++++++ .../namespaced-functions/src/test_no_call.cpp | 15 ++++++++ .../cpp/namespaced-functions/test.py | 10 ++++++ .../cpp/operator-overloading/src/pkg.cpp | 19 ++++++++++ .../cpp/operator-overloading/src/pkg.h | 15 ++++++++ .../operator-overloading/src/test_call.cpp | 11 ++++++ .../operator-overloading/src/test_no_call.cpp | 16 +++++++++ .../cpp/operator-overloading/test.py | 11 ++++++ .../c_cpp_function_call_cov/extra.opt | 1 + 48 files changed, 656 insertions(+) create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.h create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_call.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_no_call.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/test.py create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.h create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_one.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_two.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_no_call.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/test.py create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.h create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_call.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_no_call.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/test.py create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.h create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_call.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_no_call.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/test.py create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/extra.opt create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.h create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_call.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_no_call.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/test.py create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.h create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_call.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_no_call.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/test.py create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.h create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_call.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_no_call.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/test.py create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.h create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_call.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_no_call.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/test.py create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.h create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_call.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_no_call.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/test.py create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/extra.opt diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.c new file mode 100644 index 000000000..747d82c31 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.c @@ -0,0 +1,17 @@ +#include "pkg.h" +#include + +#define CALL_BAR bar () + +void // # bar_def_1 +bar (void) // # bar_def_2 +{ // # bar_def_2 + puts ("bar"); // # printf_call +} + +void // # foo_def_1 +foo (void) // # foo_def_2 +{ // # foo_def_2 + + CALL_BAR; // # bar_call +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.h new file mode 100644 index 000000000..87eb90dbb --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.h @@ -0,0 +1,6 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (void); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_call.c new file mode 100644 index 000000000..beeb5b999 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_call.c @@ -0,0 +1,11 @@ +#include "pkg.h" + +int +main (void) +{ + foo (); + return 0; +} + +//# pkg.c +// /foo_def_1/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_no_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_no_call.c new file mode 100644 index 000000000..5ca5c8ee8 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/test_no_call.c @@ -0,0 +1,14 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.c +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /.*call/ l- ## s-,c- +// /no-op/ l- ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/test.py new file mode 100644 index 000000000..53fe7465b --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/test.py @@ -0,0 +1,11 @@ +""" +Check that the Fun_Call coverage instrumentation works with functions in +macros. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.c new file mode 100644 index 000000000..235337991 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.c @@ -0,0 +1,32 @@ +#include "pkg.h" +#include + +int // # add_one_def_1 +add_one (int i) // # add_one_def_2 +{ // # add_one_def_2 + return i + 1; // # return_one +} + +int // # add_two_def_1 +add_two (int i) // # add_two_def_2 +{ // # add_two_def_2 + return i + 2; // # return_two +} + +void // # print_result_def_1 +print_result (int i, fun_type f) // # print_result_def_2 +{ // # print_result_def_2 + printf ( // # print_call + "Result: %i", // # print_format + f (i) // # fpointer_use + ); // # parenthesis +} + +void // # foo_def_1 +foo (fun_type f) // # foo_def_2 +{ // # foo_def_2 + + print_result (1, // # print_result_call + f // # fpointer_ref + ); // # parenthesis +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.h new file mode 100644 index 000000000..7207812b5 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.h @@ -0,0 +1,11 @@ +#ifndef _PKG_H +#define _PKG_H + +typedef int (*fun_type) (int); + +int add_one (int i); +int add_two (int i); + +void foo (fun_type); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_one.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_one.c new file mode 100644 index 000000000..592ec02d7 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_one.c @@ -0,0 +1,13 @@ +#include "pkg.h" + +int +main (void) +{ + foo (add_one); + return 0; +} + +//# pkg.c +// /add_two_def_1/ l- ## f- +// /add_two_def_2/ l- ## 0 +// /return_two/ l- ## s- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_two.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_two.c new file mode 100644 index 000000000..c9bf9f790 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_call_two.c @@ -0,0 +1,13 @@ +#include "pkg.h" + +int +main (void) +{ + foo (add_two); + return 0; +} + +//# pkg.c +// /add_one_def_1/ l- ## f- +// /add_one_def_2/ l- ## 0 +// /return_one/ l- ## s- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_no_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_no_call.c new file mode 100644 index 000000000..1ae75909d --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/test_no_call.c @@ -0,0 +1,18 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.c +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /.*call/ l- ## s-,c- +// /no-op/ l- ## s- +// /return_.*/ l- ## s- +// /fpointer_use/ l- ## c- +// /print_format/ l- ## 0 +// /parenthesis/ l- ## 0 +// /fpointer_ref/ l- ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/test.py new file mode 100644 index 000000000..d1c68c5bb --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/test.py @@ -0,0 +1,10 @@ +""" +Check that the Fun_Call coverage instrumentation works with functions pointers. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.c new file mode 100644 index 000000000..96b364689 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.c @@ -0,0 +1,22 @@ +#include "pkg.h" + +int // # add_one_def_1 +add_one (int i) // # add_one_def_2 +{ // # add_one_def_2 + return i + 1; // # return +} + +// Main will be called +int // # foo_def_1 +foo (int i) // # foo_def_2 +{ // # foo_def_2 + int x = // # assignment + add_one ( // # call + add_one ( // # call + add_one ( // # call + add_one ( // # call + add_one (1) // # call + )))); // # parentheses + + return x; // # return +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.h new file mode 100644 index 000000000..1d8ddbd96 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/pkg.h @@ -0,0 +1,6 @@ +#ifndef _PKG_H +#define _PKG_H + +int foo (int i); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_call.c new file mode 100644 index 000000000..65bab67c7 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_call.c @@ -0,0 +1,12 @@ +#include "pkg.h" + +int +main (void) +{ + foo (3); + return 0; +} + +//# pkg.c +// /assignment/ l+ ## 0 +// /call/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_no_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_no_call.c new file mode 100644 index 000000000..886ba7f5b --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/src/test_no_call.c @@ -0,0 +1,17 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.c +// /add_one_def_1/ l- ## f- +// /add_one_def_2/ l- ## 0 +// /foo_def_1/ l- ## f- +// /foo_def_2/ l- ## 0 +// /assignment/ l- ## s- +// /call/ l- ## c- +// /parentheses/ l- ## 0 +// /return/ l- ## s- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/test.py new file mode 100644 index 000000000..f443705a7 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/nested-calls/test.py @@ -0,0 +1,11 @@ +""" +Check that the Fun_Call coverage instrumentation works for nested functions +calls. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.c new file mode 100644 index 000000000..38587c47b --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.c @@ -0,0 +1,36 @@ +#include "pkg.h" +#include + +// A forward declaration should not be instrumented for function coverage. +void bar (void); // # bar_decl + +int // # sends_42_def_1 +sends_42 (void) // # sends_42_def_2 +{ // # sends_42_def_2 + + return 42; // # return +} + +void // # foo_def_1 +foo (void) // # foo_def_2 +{ // # foo_def_2 + + bar (); // # bar_call + + while (sends_42 ()) // # bar_call + break; // # no-op + + if (sends_42 () == 42) // # bar_call + 0; // # no-op + + for (; sends_42 ();) // # bar_call + break; // # no-op +} + +void // # bar_def_1 +bar (void) // # bar_def_2 +{ // # bar_def_2 + + // call of a function that is not in the same file or compilation unit + puts ("bar"); // # printf_call +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.h new file mode 100644 index 000000000..87eb90dbb --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.h @@ -0,0 +1,6 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (void); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_call.c new file mode 100644 index 000000000..beeb5b999 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_call.c @@ -0,0 +1,11 @@ +#include "pkg.h" + +int +main (void) +{ + foo (); + return 0; +} + +//# pkg.c +// /foo_def_1/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_no_call.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_no_call.c new file mode 100644 index 000000000..5ca5c8ee8 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/test_no_call.c @@ -0,0 +1,14 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.c +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /.*call/ l- ## s-,c- +// /no-op/ l- ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/test.py new file mode 100644 index 000000000..417b8c9b5 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/test.py @@ -0,0 +1,10 @@ +""" +Check that the Fun_Call coverage instrumentation works for simple C functions. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/extra.opt b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/extra.opt new file mode 100644 index 000000000..300e53ef2 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/extra.opt @@ -0,0 +1 @@ +!C++ DEAD test requires a supported C++ compiler diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.cpp new file mode 100644 index 000000000..8a9dcb819 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.cpp @@ -0,0 +1,20 @@ +#include "pkg.h" +#include + +template void print_point (T p); + +template +void // # print_point_def_1 +print_point (T p) // # print_point_def_2 +{ // # print_point_def_2 + std::cout << p << std::endl; // # printing +} + +void // # foo_def_1 +foo (void) // # foo_def_2 +{ // # foo_def_2 + + int A = 13; // # var_decl + + print_point (A); // # print_call +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.h new file mode 100644 index 000000000..87eb90dbb --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.h @@ -0,0 +1,6 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (void); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_call.cpp new file mode 100644 index 000000000..76a9defb6 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_call.cpp @@ -0,0 +1,11 @@ +#include "pkg.h" + +int +main (void) +{ + foo (); + return 0; +} + +//# pkg.cpp +// /foo_def_1/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_no_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_no_call.cpp new file mode 100644 index 000000000..36c4d7405 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/test_no_call.cpp @@ -0,0 +1,14 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.cpp +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /printing/ l- ## s- +// /var_decl/ l- ## s- +// /print_call/ l- ## s-,c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/test.py new file mode 100644 index 000000000..8cd26a951 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/test.py @@ -0,0 +1,11 @@ +""" +Check that the Fun_Call coverage instrumentation works for C++ overloaded +operators. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.cpp new file mode 100644 index 000000000..7c145d557 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.cpp @@ -0,0 +1,20 @@ +#include "pkg.h" + +void // # foo_def_1 +foo (int i) // # foo_def_2 +{ // # foo_def_2 + + auto f = // # lambda_assign + [&i] (int x) { // # lambda_def + // # lambda_comment + return x + i; // # lambda_return + }; // # lambda_bracket + + // This should not be instrumented as a call even though under the hood, a + // call to a copy constructor is made for f. + auto f_copy = f; // # assignment + + // A copy of the lambda will cover the lambda for function coverage. + // Also, this call is to be instrumented. + auto y = f_copy (30); // # call_copy +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.h new file mode 100644 index 000000000..37f7a1499 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.h @@ -0,0 +1,6 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (int i); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_call.cpp new file mode 100644 index 000000000..3cf8615c6 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_call.cpp @@ -0,0 +1,11 @@ +#include "pkg.h" + +int +main (void) +{ + foo (4); + return 0; +} + +//# pkg.cpp +// /foo_def_1/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_no_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_no_call.cpp new file mode 100644 index 000000000..4e2be15e3 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/test_no_call.cpp @@ -0,0 +1,18 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.cpp +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /lambda_assign/ l- ## s- +// /lambda_def/ l- ## f- +// /lambda_comment/ l- ## 0 +// /lambda_return/ l- ## s- +// /lambda_bracket/ l- ## 0 +// /assignment/ l- ## s- +// /call_copy/ l- ## s-,c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/test.py new file mode 100644 index 000000000..8cd26a951 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/test.py @@ -0,0 +1,11 @@ +""" +Check that the Fun_Call coverage instrumentation works for C++ overloaded +operators. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.cpp new file mode 100644 index 000000000..9a0050a9e --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.cpp @@ -0,0 +1,31 @@ +#include "pkg.h" + +class Point2D +{ + int x = 0; + int y = 0; + +public: + Point2D () = default; // # default_ctor_def + Point2D (int x, int y) : x (x), y (y){}; // # var_ctor_def + + Point2D add (Point2D &other) const; +}; + +Point2D // # point2d_add_def_1 +Point2D::add (Point2D &other) const // # point2d_add_def_2 +{ // # point2d_add_def_2 + + // This calls a constructor + return Point2D (this->x + other.x, this->y + other.y); // # return +} + +void // # foo_def_1 +foo (void) // # foo_def_2 +{ // # foo_def_2 + + Point2D A; // # point_a + Point2D B = Point2D (1, 3); // # point_b + + auto sum = A.add (B); // # sum +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.h new file mode 100644 index 000000000..87eb90dbb --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.h @@ -0,0 +1,6 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (void); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_call.cpp new file mode 100644 index 000000000..bbbb53ce6 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_call.cpp @@ -0,0 +1,11 @@ +#include "pkg.h" + +int +main (void) +{ + foo (); + return 0; +} + +//# pkg.cpp +// /default_ctor_def/ l? ## f? diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_no_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_no_call.cpp new file mode 100644 index 000000000..8dbcc94f8 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_no_call.cpp @@ -0,0 +1,16 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.cpp +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /default_ctor_def/ l? ## f? +// /var_ctor_def/ l- ## f- +// /return/ l- ## s- +// /point_.*/ l- ## s- +// /sum/ l- ## s-,c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/test.py new file mode 100644 index 000000000..228c2f481 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/test.py @@ -0,0 +1,15 @@ +""" +Check that the Fun_Call coverage instrumentation works for C++ classes. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase( + category=CAT.stmt, + fun_call_lvl=True, + tolerate_messages="cannot instrument constexpr", +).run() + +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.cpp new file mode 100644 index 000000000..e2d288566 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.cpp @@ -0,0 +1,31 @@ +#include "pkg.h" +#include + +namespace sub_module +{ +void hello_world (void); + +void // # hello_def_1 +hello_world (void) // # hello_def_2 +{ // # hello_def_2 + + puts ("Hello"); // # print +} +} + +void // # foo_def_1 +foo (void) // # foo_def_2 +{ // # foo_def_2 + + sub_module:: // # submodule + hello_world (); // # call +} + +void // # bar_def_1 +bar (void) // # bar_def_2 +{ // # bar_def_2 + + using namespace sub_module; // # using_clause + + hello_world (); // # both +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.h new file mode 100644 index 000000000..6eeda0117 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.h @@ -0,0 +1,7 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (void); +void bar (void); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_call.cpp new file mode 100644 index 000000000..edbb3a442 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_call.cpp @@ -0,0 +1,11 @@ +#include "pkg.h" + +int +main (void) +{ + foo (); + bar (); + return 0; +} + +//# pkg.cpp diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_no_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_no_call.cpp new file mode 100644 index 000000000..ee2ed70c2 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/test_no_call.cpp @@ -0,0 +1,15 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.cpp +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /print/ l- ## s-,c- +// /submodule/ l- ## s-,c- +// /call/ l- ## 0 +// /both/ l- ## s-,c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/test.py new file mode 100644 index 000000000..8f48f61cb --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/test.py @@ -0,0 +1,10 @@ +""" +Check that the Fun_Call coverage instrumentation works for C++ namespaces. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.cpp new file mode 100644 index 000000000..fdb5a534c --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.cpp @@ -0,0 +1,19 @@ +#include "pkg.h" + +bool // # operator_def_1 +operator|| (My_Bool L, My_Bool R) // # operator_def_2 +{ // # operator_def_2 + return L == My_Bool::True || R == My_Bool::True; // # return +} + +void // # foo_def_1 +foo (void) // # foo_def_2 +{ // # foo_def_2 + + auto A = My_Bool::True; // # var_decl + auto B = My_Bool::False; // # var_decl + + auto res = // # assignment + A || B // # or_my_bool + || false; // # or_std_bool +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.h new file mode 100644 index 000000000..fe596595a --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/pkg.h @@ -0,0 +1,15 @@ +#ifndef _PKG_H +#define _PKG_H + +void foo (void); + +enum My_Bool +{ + True, + False, +}; + +// Overload the comma operator +bool operator|| (My_Bool L, My_Bool R); + +#endif // _PKG_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_call.cpp new file mode 100644 index 000000000..76a9defb6 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_call.cpp @@ -0,0 +1,11 @@ +#include "pkg.h" + +int +main (void) +{ + foo (); + return 0; +} + +//# pkg.cpp +// /foo_def_1/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_no_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_no_call.cpp new file mode 100644 index 000000000..123c68147 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/src/test_no_call.cpp @@ -0,0 +1,16 @@ +#include "pkg.h" + +int +main (void) +{ + return 0; +} + +//# pkg.cpp +// /.*def_1/ l- ## f- +// /.*def_2/ l- ## 0 +// /return/ l- ## s- +// /var_decl/ l- ## s- +// /assignment/ l- ## s- +// /or_my_bool/ l- ## c- +// /or_std_bool/ l- ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/test.py new file mode 100644 index 000000000..8cd26a951 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/operator-overloading/test.py @@ -0,0 +1,11 @@ +""" +Check that the Fun_Call coverage instrumentation works for C++ overloaded +operators. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/extra.opt b/testsuite/tests/instr-cov/c_cpp_function_call_cov/extra.opt new file mode 100644 index 000000000..a9490dec8 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD Function and call coverage not supported for binary traces From 7b6f5c918c74e8417a5f18b84e378f67a97db924 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 28 Jan 2025 12:04:25 +0100 Subject: [PATCH 1108/1483] report(xml): Use the absolute path of source files in the XML report format --- tools/gnatcov/annotations-xml.adb | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index 566700cb4..9f40d4554 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -486,7 +486,7 @@ package body Annotations.Xml is FI : constant File_Info_Access := Get_File (File_Index); begin if FI.Kind = Source_File and then To_Display (FI) then - Pp.ST ("file", A ("name", FI.Simple_Name.all), Dest_Index); + Pp.ST ("file", A ("name", FI.Full_Name.all), Dest_Index); Print_Coverage_Li_Stats (Pp, FI.Li_Stats, Dest_Index); Print_Coverage_Ob_Stats (Pp, FI.Ob_Stats, Dest_Index); Pp.ET ("file", Dest_Index); @@ -540,9 +540,8 @@ package body Annotations.Xml is -- No stats are emitted in the XML output; the user is supposed -- to compute them by himself by post-processing the output. - Simple_Source_Filename : constant String := Info.Simple_Name.all; - Xml_File_Name : constant String := - Get_Unique_Filename (File, "xml"); + Abs_Filename : constant String := Info.Full_Name.all; + Xml_File_Name : constant String := Get_Unique_Filename (File, "xml"); begin if not Info.Has_Source then Skip := True; @@ -553,7 +552,7 @@ package body Annotations.Xml is Create_Output_File (Pp.Files (Dest_Compilation_Unit), Xml_File_Name); Pp.P (Xml_Header); Pp.ST ("source", - A ("file", Simple_Source_Filename) + A ("file", Abs_Filename) & A ("coverage_level", Coverage_Option_Value)); Pp.T ("xi:include", A ("parse", "xml") & A ("href", Xml_File_Name), From 495901418eb31343c0431dedae6dbadeddf67b5c Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 28 Jan 2025 15:21:58 +0100 Subject: [PATCH 1109/1483] tests: Adapt testsuite to check that XML reports use full path of source files --- testsuite/SUITE/cutils.py | 23 +++++++++++++++++++ .../src-traces-index.xml.expected | 2 +- testsuite/tests/O212-062-xml/test.py | 3 ++- .../main.adb.xml.expected | 2 +- .../tests/R417-010-scope-metrics/test.py | 3 ++- .../bin-traces-index.xml.expected | 7 +++--- .../src-traces-index.xml.expected | 8 +++---- testsuite/tests/R507-027-xml-summary/test.py | 4 +++- 8 files changed, 39 insertions(+), 13 deletions(-) diff --git a/testsuite/SUITE/cutils.py b/testsuite/SUITE/cutils.py index 5134090fd..bcbafaed2 100644 --- a/testsuite/SUITE/cutils.py +++ b/testsuite/SUITE/cutils.py @@ -11,9 +11,12 @@ import sys import tempfile +from typing import AnyStr, Optional + from e3.fs import cp, mkdir from e3.os.fs import cd, which from e3.os.process import Run +from e3.testsuite.driver.diff import OutputRefiner def unhandled_exception_in(log): @@ -306,6 +309,26 @@ def multi_range(*args, minus=None): return result +class FilePathRefiner(OutputRefiner[AnyStr]): + """ + For each tag "@@FILE@@", find the file by looking at src_dir/FILE, and + replace the tag with the absolute path of the file. + """ + + TAG_REGEX = re.compile(r"@@(?P(?:\w|[./])+)@@") + + def __init__(self, src_dir: Optional[AnyStr] = None) -> None: + self.src_dir = src_dir or ".." + + def refine(self, output: AnyStr) -> AnyStr: + def _replace_tag(pat): + filename = pat.group("filename") + path = os.path.abspath(os.path.join(self.src_dir, filename)) + return path + + return re.sub(self.TAG_REGEX, _replace_tag, output) + + class Identifier: def __init__(self, name): self.name = name diff --git a/testsuite/tests/O212-062-xml/src-traces-index.xml.expected b/testsuite/tests/O212-062-xml/src-traces-index.xml.expected index bd43dae9e..c5b89fb57 100644 --- a/testsuite/tests/O212-062-xml/src-traces-index.xml.expected +++ b/testsuite/tests/O212-062-xml/src-traces-index.xml.expected @@ -75,7 +75,7 @@ - + diff --git a/testsuite/tests/O212-062-xml/test.py b/testsuite/tests/O212-062-xml/test.py index be5db73a3..4fd66d1c7 100644 --- a/testsuite/tests/O212-062-xml/test.py +++ b/testsuite/tests/O212-062-xml/test.py @@ -5,7 +5,7 @@ import os from SCOV.minicheck import build_run_and_coverage -from SUITE.cutils import Wdir +from SUITE.cutils import Wdir, FilePathRefiner from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor, thistest @@ -22,6 +22,7 @@ thistest.fail_if_diff( os.path.join("..", "src-traces-index.xml.expected"), os.path.join("obj", "index.xml"), + output_refiners=[FilePathRefiner()], ) thistest.result() diff --git a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected index 32ac604bf..96a156dfb 100644 --- a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected +++ b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected @@ -1,5 +1,5 @@ - + diff --git a/testsuite/tests/R417-010-scope-metrics/test.py b/testsuite/tests/R417-010-scope-metrics/test.py index 72d329b10..ddea1897c 100644 --- a/testsuite/tests/R417-010-scope-metrics/test.py +++ b/testsuite/tests/R417-010-scope-metrics/test.py @@ -7,7 +7,7 @@ import os from SCOV.minicheck import build_run_and_coverage -from SUITE.cutils import Wdir +from SUITE.cutils import Wdir, FilePathRefiner from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor, thistest @@ -27,5 +27,6 @@ thistest.fail_if_diff( os.path.join("..", "main.adb.xml.expected"), os.path.join("obj", "main.adb.xml"), + output_refiners=[FilePathRefiner()], ) thistest.result() diff --git a/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected b/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected index c0182c86b..389c11d9f 100644 --- a/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected +++ b/testsuite/tests/R507-027-xml-summary/bin-traces-index.xml.expected @@ -39,7 +39,7 @@ - + @@ -75,7 +75,7 @@ - + @@ -111,7 +111,7 @@ - + @@ -158,4 +158,3 @@ - diff --git a/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected b/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected index 58e08d1e2..0d35b0972 100644 --- a/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected +++ b/testsuite/tests/R507-027-xml-summary/src-traces-index.xml.expected @@ -39,7 +39,7 @@ - + @@ -75,7 +75,7 @@ - + @@ -111,7 +111,7 @@ - + @@ -147,7 +147,7 @@ - + diff --git a/testsuite/tests/R507-027-xml-summary/test.py b/testsuite/tests/R507-027-xml-summary/test.py index 86415d215..062bc114c 100644 --- a/testsuite/tests/R507-027-xml-summary/test.py +++ b/testsuite/tests/R507-027-xml-summary/test.py @@ -6,7 +6,7 @@ import os from SCOV.minicheck import build_run_and_coverage -from SUITE.cutils import Wdir +from SUITE.cutils import Wdir, FilePathRefiner from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor, thistest @@ -24,12 +24,14 @@ thistest.fail_if_diff( os.path.join("..", "bin-traces-index.xml.expected"), os.path.join("obj", "index.xml"), + output_refiners=[FilePathRefiner()], ) else: assert thistest.options.trace_mode == "src" thistest.fail_if_diff( os.path.join("..", "src-traces-index.xml.expected"), os.path.join("obj", "index.xml"), + output_refiners=[FilePathRefiner()], ) thistest.result() From e9eb123ac10a50db0df4e89701233d11923f5f13 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 11 Feb 2025 12:41:38 +0100 Subject: [PATCH 1110/1483] instr-c: Do not add fun/call SCOs to instrumentation blocks --- tools/gnatcov/instrument-c.adb | 69 ++++++++++++++++++++++++++++++---- tools/gnatcov/instrument-c.ads | 5 ++- 2 files changed, 65 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 736f2b73c..aeef3a19e 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -224,7 +224,8 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; Insertion_N : Cursor_T; - Instr_Scheme : Instr_Scheme_Type); + Instr_Scheme : Instr_Scheme_Type; + Kind : SCO_Kind := Statement); -- Add an entry to UIC.Source_Statements overriding procedure Instrument_Decision @@ -1236,7 +1237,8 @@ package body Instrument.C is UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; Insertion_N : Cursor_T; - Instr_Scheme : Instr_Scheme_Type) is + Instr_Scheme : Instr_Scheme_Type; + Kind : SCO_Kind := Statement) is begin if UIC.Disable_Instrumentation then UIC.Non_Instr_LL_SCOs.Include (SCO_Id (LL_SCO)); @@ -1244,6 +1246,7 @@ package body Instrument.C is UIC.Block_Stack.Reference (UIC.Block_Stack.Last).Append (C_Source_Statement' (LL_SCO => LL_SCO, + Kind => Kind, Instr_Scheme => Instr_Scheme, Statement => Insertion_N)); end if; @@ -1635,7 +1638,8 @@ package body Instrument.C is (UIC => UIC, LL_SCO => SCOs.SCO_Table.Last, Insertion_N => C, - Instr_Scheme => Instr_Expr); + Instr_Scheme => Instr_Expr, + Kind => Call); end if; return Child_Visit_Recurse; @@ -2725,7 +2729,8 @@ package body Instrument.C is (UIC => UIC, LL_SCO => SCOs.SCO_Table.Last, Insertion_N => Fun_Body, - Instr_Scheme => Instr_In_Compound); + Instr_Scheme => Instr_In_Compound, + Kind => Fun); UIC.Pass.End_Statement_Block (UIC); end if; @@ -3660,13 +3665,61 @@ package body Instrument.C is if Switches.Instrument_Block then declare Block_SCOs : SCO_Id_Vectors.Vector; + Last_Stmt_Idx : Natural := Block.Last_Index; begin - Insert_Statement_Witness - (UIC, Ent.Buffers_Index, Block.Last_Element); + + -- The block does not only carry statement SCOs, + -- it also carries the SCOs of coverage levels + -- that rely on stmt-like instrumentation: + -- - FunCall, + -- - Gexpr (albeit not in C/C++) + -- + -- However, when using block instrumentation, + -- we should not consider these not-stmt SCOs + -- and instrument them manually. + + -- Non-statement SCOs are instrumented as usual, + -- but in any case, we need to preserve the order + -- in which each SCO is instrumented. + + -- 1. Search the last Statement SCO in the block, + -- it is the only one we will instrument. + + while Last_Stmt_Idx > Block.First_Index and then + Block.Reference + (Last_Stmt_Idx).Kind /= Statement + loop + Last_Stmt_Idx := Last_Stmt_Idx - 1; + end loop; + + -- 2. Once found, instrument the last stmt SCO + + if Last_Stmt_Idx >= Block.First_Index then + Insert_Statement_Witness + (UIC, + Ent.Buffers_Index, + Block.Reference (Last_Stmt_Idx)); + end if; + + -- 3. Finally, for all the SCOs in the block, either: + -- - Attach them to the block if it's a statement + -- - Or instrument it, + for SS of Block loop - Block_SCOs.Append (SCO_Map (SS.LL_SCO)); + if SS.Kind = Statement then + Block_SCOs.Append (SCO_Map (SS.LL_SCO)); + else + + -- Manually instrument non-statement SCOs + + Insert_Statement_Witness + (UIC, Ent.Buffers_Index, SS); + end if; end loop; - Blocks.Append (Block_SCOs); + + if not Block_SCOs.Is_Empty then + Blocks.Append (Block_SCOs); + end if; end; else for SS of Block loop diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 95b91d863..d288d1fc2 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -192,6 +192,8 @@ package Instrument.C is LL_SCO : Nat; -- Low-level SCO id of statement + Kind : SCO_Kind := Statement; + Instr_Scheme : Instr_Scheme_Type; -- How should the statement be instrumented. See documentation of -- Instr_Scheme_Type. @@ -465,7 +467,8 @@ private UIC : in out C_Unit_Inst_Context'Class; LL_SCO : Nat; Insertion_N : Cursor_T; - Instr_Scheme : Instr_Scheme_Type) is null; + Instr_Scheme : Instr_Scheme_Type; + Kind : SCO_Kind := Statement) is null; procedure Instrument_Decision (Pass : Pass_Kind; From fa5215ba31f2f72470a6991e4254bc1e9a4b581a Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 5 Feb 2025 10:00:42 +0100 Subject: [PATCH 1111/1483] doc: Document Guarded expressions and support of C/C++ for funcall coverage --- doc/gnatcov/cov_source.rst | 63 +++++++++++++++++++++++++++++++++++++- doc/gnatcov/src_traces.rst | 23 +++++++++++--- 2 files changed, 81 insertions(+), 5 deletions(-) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index bd1199022..a3bf92283 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -1546,7 +1546,7 @@ Function and Call Coverage (FUN_CALL) analysis (experimental) ============================================================= |gcv| can also provide an analysis of the coverage of subprograms and calls for -Ada source traces. +Ada, C, and C++ source traces. If such coverage analysis is needed, it should always be activated along one of the non-assertion coverage levels previously described. In this section on @@ -1584,6 +1584,67 @@ coverage reports. The limitations of this coverage level are detailed in the :ref:`instr-limitations` section. +.. _scov-gexpr: + +Guarded Expression Coverage (GEXPR) analysis (experimental) +============================================================ + +For the Ada language, |gcv| can provide an analysis on coverage of guarded +expressions. + +Core notions and Reporting (:cmd-option:`--level=...+gexpr`) +------------------------------------------------------------ + +|gcv| the following syntaxes to be :dfn:`guarded expressions`: + +* Then and Else dependent expressions of :dfn:`if expressions` + +.. code-block:: ada + + procedure Foo (A : Boolean) is + Var : constant String := + (if A + then "True expression" + else "False expression"); + begin + null; + end Foo; + +* Dependent expressions of :dfn:`case expressions` + +.. code-block:: ada + + type Animal is (Cat, Dog, Cow); + + procedure Foo (A : Animal) is + Var : constant String := + (case A + when Cat => "Expression Cat", + when Dog => "Expression Dog", + when others => "Expression other"); + begin + null; + end Foo; + +* Predicate expression of :dfn:`quantified expressions` + +.. code-block:: ada + + function Prime_In_Range (L, R : Natural) return Boolean is + begin + + -- Is_Prime (I) is the child expression that will be analysized. + + return (for some I in (L .. R) => Is_Prime (I)); + end Foo; + +For each of these, we consider the expression to be :dfn:`covered` and the +obligation to be :dfn:`discharged` if the execution flow evaluated it at least +once. + +The limitations of this coverage level are detailed in the +:ref:`instr-limitations` section. + .. _synthetic-metrics: Synthetic metrics diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 5e7a11ee5..458b04578 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -645,15 +645,30 @@ build for instance. Function and call coverage limitations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Function and call coverage is only available for Ada. Currently, gnatcov is -unable to provided coverage information for: +Function and call coverage supports all three Ada, C and C++ languages, +with language-specific limitations. -* Call expressions part of the prefix of a dotted name +For the Ada language, gnatcov is currently unable to provided coverage +information for: -* Calls to user-defined operators +* Call expressions part of the prefix of a dotted name The coverage state of these cases will be reported as undetermined. +For the C++ language, gnatcov will currently not instrument nor provide +coverage information for: + +* Constructor and Destructor functions + +* Constructor and Destructor calls + +Guarded expression coverage limitations +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Guarded expression coverage is only available for the Ada language. +For implementation reasons, it is only available starting from version 2022 of +the language. + .. _instr-build: Building instrumented components From e2879e89a6c8c2b75f0751bf322cf0120f134482 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 10 Feb 2025 16:14:06 +0100 Subject: [PATCH 1112/1483] Fix XML full path casing on Windows - Add a field to File_Info that holds the normalized path that preserve the original casing. - Write the preserved-case full name in checkpoints. - Use the preserved-case name in XML reports. - Change the Canonicalize_Filename function to conditionally disable lowercasing. --- tools/gnatcov/annotations-xml.adb | 5 +-- tools/gnatcov/files_table.adb | 59 ++++++++++++++++++++++++------- tools/gnatcov/files_table.ads | 10 +++++- tools/gnatcov/paths.adb | 27 ++++++++++---- tools/gnatcov/paths.ads | 10 ++++-- tools/gnatcov/traces_elf.adb | 3 +- 6 files changed, 87 insertions(+), 27 deletions(-) diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index 9f40d4554..a21240e6a 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -486,7 +486,8 @@ package body Annotations.Xml is FI : constant File_Info_Access := Get_File (File_Index); begin if FI.Kind = Source_File and then To_Display (FI) then - Pp.ST ("file", A ("name", FI.Full_Name.all), Dest_Index); + Pp.ST + ("file", A ("name", FI.Preserved_Full_Name.all), Dest_Index); Print_Coverage_Li_Stats (Pp, FI.Li_Stats, Dest_Index); Print_Coverage_Ob_Stats (Pp, FI.Ob_Stats, Dest_Index); Pp.ET ("file", Dest_Index); @@ -540,7 +541,7 @@ package body Annotations.Xml is -- No stats are emitted in the XML output; the user is supposed -- to compute them by himself by post-processing the output. - Abs_Filename : constant String := Info.Full_Name.all; + Abs_Filename : constant String := Info.Preserved_Full_Name.all; Xml_File_Name : constant String := Get_Unique_Filename (File, "xml"); begin if not Info.Has_Source then diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 8c266be0d..149c4d62b 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -79,9 +79,9 @@ package body Files_Table is -- Freeze the files table and compute Unique_Name fields for file entries function Create_File_Info - (Kind : File_Kind; - Full_Name, Simple_Name : String_Access; - Indexed_Simple_Name : Boolean) + (Kind : File_Kind; + Full_Name, Preserved_Full_Name, Simple_Name : String_Access; + Indexed_Simple_Name : Boolean) return File_Info_Access; -- Allocate a new File_Info record of type Kind and for the given file -- names. This does not modify Files_Table nor full/simple name maps. @@ -748,9 +748,11 @@ package body Files_Table is use Filename_Rebase_Maps; use Simple_Name_Maps; - Original_Full_Path : constant Virtual_File := - Create (+Canonicalize_Filename (Full_Name)); - Full_Path : Virtual_File := Original_Full_Path; + Preserved_Full_Name : constant String := + Canonicalize_Filename (Full_Name, False); + Original_Full_Path : constant Virtual_File := + Create (+Canonicalize_Filename (Full_Name)); + Full_Path : Virtual_File := Original_Full_Path; -- Full_Path can be modified to hold the result of the source rebase Cur : Filename_Maps.Cursor; @@ -816,6 +818,12 @@ package body Files_Table is Info_Simple.Full_Name := new String'(+GNATCOLL.VFS.Full_Name (Full_Path)); Full_Name_Map.Insert (Full_Path, Res); + + if Info_Simple.Preserved_Full_Name = null then + Info_Simple.Preserved_Full_Name := + new String'(Preserved_Full_Name); + end if; + goto Do_Return; else @@ -842,6 +850,7 @@ package body Files_Table is Files_Table.Append (Create_File_Info (Kind, new String'(+GNATCOLL.VFS.Full_Name (Full_Path)), + new String'(Preserved_Full_Name), new String'(+GNATCOLL.VFS.Full_Name (Simple_Path)), Indexed_Simple_Name)); Res := Files_Table.Last_Index; @@ -911,6 +920,7 @@ package body Files_Table is Files_Table.Append (Create_File_Info (Kind => Kind, Full_Name => null, + Preserved_Full_Name => null, Simple_Name => new String'(+Full_Name (Simple_Path)), Indexed_Simple_Name => True)); Res := Files_Table.Last_Index; @@ -1537,14 +1547,26 @@ package body Files_Table is ---------------------- function Create_File_Info - (Kind : File_Kind; - Full_Name, Simple_Name : String_Access; - Indexed_Simple_Name : Boolean) + (Kind : File_Kind; + Full_Name, Preserved_Full_Name, Simple_Name : String_Access; + Indexed_Simple_Name : Boolean) return File_Info_Access is Result : constant File_Info_Access := new File_Info (Kind); + + function Defer_Or_Null (S : String_Access) return String is + (if S = null then "<>" else "<<" & S.all & ">>"); begin + Files_Table_Trace.Trace ("CFI -> Simple Name:" + & Defer_Or_Null (Simple_Name) + & ASCII.LF + & " Preserved Full Name: " + & Defer_Or_Null (Preserved_Full_Name) + & ASCII.LF + & " Canonical Full Name: " + & Defer_Or_Null (Full_Name)); Result.Full_Name := Full_Name; + Result.Preserved_Full_Name := Preserved_Full_Name; Result.Simple_Name := Simple_Name; Result.Indexed_Simple_Name := Indexed_Simple_Name; if Result.Kind = Source_File then @@ -1591,8 +1613,12 @@ package body Files_Table is declare New_FI : constant File_Info_Access := - Create_File_Info - (Kind, FI.Full_Name, FI.Simple_Name, FI.Indexed_Simple_Name); + Create_File_Info + (Kind, + FI.Full_Name, + FI.Preserved_Full_Name, + FI.Simple_Name, + FI.Indexed_Simple_Name); begin New_FI.Has_Source := FI.Has_Source; Free (FI); @@ -1739,6 +1765,12 @@ package body Files_Table is -- Start of processing for Open begin + Files_Table_Trace.Trace ("Open FILE : " & FI.Simple_Name.all); + if FI.Preserved_Full_Name /= null then + Files_Table_Trace.Trace (" Full name " + & FI.Preserved_Full_Name.all); + end if; + if not FI.Has_Source then Success := False; return; @@ -2129,8 +2161,8 @@ package body Files_Table is CSS.Write_SFI (File_Vectors.To_Index (FI_C)); CSS.Write_Unbounded (String_Access' - (if FI.Full_Name /= null - then FI.Full_Name + (if FI.Preserved_Full_Name /= null + then FI.Preserved_Full_Name else FI.Simple_Name).all); CSS.Write_U8 (File_Kind'Pos (FI.Kind)); CSS.Write (FI.Indexed_Simple_Name); @@ -2161,6 +2193,7 @@ package body Files_Table is Sorted_Files_Table.Clear; for FI of Files_Table loop Free (FI.Full_Name); + Free (FI.Preserved_Full_Name); Free (FI.Simple_Name); if FI.Kind = Source_File then diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 4c8fbb903..bc8df9b74 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -364,7 +364,15 @@ package Files_Table is -- Source file information Full_Name : String_Access; - -- Full path name + -- Full path name. This path is normalized (and lowercased on + -- windows platforms). + + Preserved_Full_Name : String_Access; + -- Full canonicalized path name that inconditionally matches the casing + -- of the original filename that was given to gnatcov. + -- It is used for display purpose. + -- It is also this, instead of Full_Name, that gets saved in + -- checkpoint files. Simple_Name : String_Access; -- File name of the source file, without the path diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index 8612cda21..c5e0a6239 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -32,7 +32,9 @@ package body Paths is function Likely_Windows_Path (Path : String) return Boolean; -- Whether the provided Path features Windows typical markers - function Normalize_Windows_Pattern (Pattern : String) return String; + function Normalize_Windows_Pattern + (Pattern : String; + Lower : Boolean := True) return String; -- Assuming Pattern is a Windows file name or globbing pattern, return a -- minimally normalized version of it, with all chars converted to lower -- case and \ used consistently as the dir separator. Pattern may actually @@ -79,7 +81,10 @@ package body Paths is -- Canonicalize_Filename -- --------------------------- - function Canonicalize_Filename (Filename : String) return String is + function Canonicalize_Filename + (Filename : String; + Lower : Boolean := True) return String + is -- Start with a very basic normalization step as for globbing -- patterns. If we have a Windows path but are not on a Windows @@ -90,7 +95,7 @@ package body Paths is Name : constant String := (if Likely_Windows - then Normalize_Windows_Pattern (Filename) + then Normalize_Windows_Pattern (Filename, Lower) else Filename); begin if Likely_Windows and then not On_Windows then @@ -100,9 +105,11 @@ package body Paths is end if; end Canonicalize_Filename; - function Canonicalize_Filename (Filename : String) return String_Access is + function Canonicalize_Filename + (Filename : String; + Lower : Boolean := True) return String_Access is begin - return new String'(Canonicalize_Filename (Filename)); + return new String'(Canonicalize_Filename (Filename, Lower)); end Canonicalize_Filename; -------------------- @@ -269,7 +276,9 @@ package body Paths is -- Normalize_Windows_Pattern -- ------------------------------- - function Normalize_Windows_Pattern (Pattern : String) return String is + function Normalize_Windows_Pattern + (Pattern : String; + Lower : Boolean := True) return String is -- Force lower case and Backslashify, paying attention not to add -- multiple backslashes in a row. @@ -297,8 +306,12 @@ package body Paths is Newchar := (if Pattern (I) = '/' then '\' else Pattern (I)); New_Is_Sep := Newchar = '\'; + if Lower then + Newchar := To_Lower (Newchar); + end if; + if not New_Is_Sep or else not Last_Was_Sep then - Append (Res, To_Lower (Newchar)); + Append (Res, Newchar); Last_Was_Sep := New_Is_Sep; end if; end loop; diff --git a/tools/gnatcov/paths.ads b/tools/gnatcov/paths.ads index 508311119..b5f9205b8 100644 --- a/tools/gnatcov/paths.ads +++ b/tools/gnatcov/paths.ads @@ -43,11 +43,17 @@ package Paths is -- If this is a Windows host, return the lower-cased filename, otherwise -- leave it unchanged. - function Canonicalize_Filename (Filename : String) return String; - function Canonicalize_Filename (Filename : String) return String_Access; + function Canonicalize_Filename + (Filename : String; + Lower : Boolean := True) return String; + function Canonicalize_Filename + (Filename : String; + Lower : Boolean := True) return String_Access; -- Assuming Filename is a full pathname to a file, return a normalized -- version of it such that different references to the same file map to the -- same canonical string as much as possible. + -- On Windows, if the Lower argument is true, the path will also be + -- lowercased. If it's false, the original case is kept. function Glob_To_Regexp (Pattern : String) return String; -- Convert the provided globbing Pattern to a regular expression. This diff --git a/tools/gnatcov/traces_elf.adb b/tools/gnatcov/traces_elf.adb index 3dc69dfe4..7af26211d 100644 --- a/tools/gnatcov/traces_elf.adb +++ b/tools/gnatcov/traces_elf.adb @@ -2831,8 +2831,7 @@ package body Traces_Elf is then Dw_Filename else Build_Filename (Dir.all, Dw_Filename)); begin - Filenames.Append - (new String'(Canonicalize_Filename (Filename))); + Filenames.Append (Canonicalize_Filename (Filename)); Compute_File_Index (Filenames.Last_Element.all); end Register_Filename; From 700966cc388e7688eb53e9544aebe784092746e3 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 17 Feb 2025 12:26:48 +0100 Subject: [PATCH 1113/1483] tests: Fix instrumentation regressions on embadded targets without printf --- .../c/calls-in-macros/src/message.c | 11 +++++++++++ .../c/calls-in-macros/src/message.h | 8 ++++++++ .../c/calls-in-macros/src/pkg.c | 10 +++++----- .../c/function-pointers/src/message.c | 11 +++++++++++ .../c/function-pointers/src/message.h | 8 ++++++++ .../c/function-pointers/src/pkg.c | 4 ++-- .../c/regular-functions/src/message.c | 11 +++++++++++ .../c/regular-functions/src/message.h | 8 ++++++++ .../c/regular-functions/src/pkg.c | 4 ++-- 9 files changed, 66 insertions(+), 9 deletions(-) create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.h create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.h create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.h diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.c new file mode 100644 index 000000000..9ed5e7f8c --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.c @@ -0,0 +1,11 @@ +#include "message.h" + +void +print_message (const char *str) +{ +} + +void +print_number (const char *str, int n) +{ +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.h new file mode 100644 index 000000000..30d6da408 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/message.h @@ -0,0 +1,8 @@ +#ifndef __MESSAGE_H +#define __MESSAGE_H + +void print_message (const char *str); + +void print_number (const char *str, int n); + +#endif // __MESSAGE_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.c index 747d82c31..182161aee 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.c +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/calls-in-macros/src/pkg.c @@ -1,12 +1,12 @@ #include "pkg.h" -#include +#include "message.h" #define CALL_BAR bar () -void // # bar_def_1 -bar (void) // # bar_def_2 -{ // # bar_def_2 - puts ("bar"); // # printf_call +void // # bar_def_1 +bar (void) // # bar_def_2 +{ // # bar_def_2 + print_message ("bar"); // # printf_call } void // # foo_def_1 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.c new file mode 100644 index 000000000..9ed5e7f8c --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.c @@ -0,0 +1,11 @@ +#include "message.h" + +void +print_message (const char *str) +{ +} + +void +print_number (const char *str, int n) +{ +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.h new file mode 100644 index 000000000..30d6da408 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/message.h @@ -0,0 +1,8 @@ +#ifndef __MESSAGE_H +#define __MESSAGE_H + +void print_message (const char *str); + +void print_number (const char *str, int n); + +#endif // __MESSAGE_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.c index 235337991..84034db39 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.c +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointers/src/pkg.c @@ -1,5 +1,5 @@ #include "pkg.h" -#include +#include "message.h" int // # add_one_def_1 add_one (int i) // # add_one_def_2 @@ -16,7 +16,7 @@ add_two (int i) // # add_two_def_2 void // # print_result_def_1 print_result (int i, fun_type f) // # print_result_def_2 { // # print_result_def_2 - printf ( // # print_call + print_number ( // # print_call "Result: %i", // # print_format f (i) // # fpointer_use ); // # parenthesis diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.c new file mode 100644 index 000000000..9ed5e7f8c --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.c @@ -0,0 +1,11 @@ +#include "message.h" + +void +print_message (const char *str) +{ +} + +void +print_number (const char *str, int n) +{ +} diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.h new file mode 100644 index 000000000..30d6da408 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/message.h @@ -0,0 +1,8 @@ +#ifndef __MESSAGE_H +#define __MESSAGE_H + +void print_message (const char *str); + +void print_number (const char *str, int n); + +#endif // __MESSAGE_H diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.c index 38587c47b..4a4fbdd60 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.c +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/regular-functions/src/pkg.c @@ -1,5 +1,5 @@ #include "pkg.h" -#include +#include "message.h" // A forward declaration should not be instrumented for function coverage. void bar (void); // # bar_decl @@ -32,5 +32,5 @@ bar (void) // # bar_def_2 { // # bar_def_2 // call of a function that is not in the same file or compilation unit - puts ("bar"); // # printf_call + print_message ("bar"); // # printf_call } From f1ccb6a577fde7b0247acd459ef3435073d3f4c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 20 Feb 2025 14:41:19 +0100 Subject: [PATCH 1114/1483] setup_rts.adb: Check that driver attribute is defined before accessing its value --- .../386-setup-invalid-target/test.py | 42 +++++++++++++++++++ tools/gnatcov/setup_rts.adb | 6 +-- 2 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 testsuite/tests/instr-cov/386-setup-invalid-target/test.py diff --git a/testsuite/tests/instr-cov/386-setup-invalid-target/test.py b/testsuite/tests/instr-cov/386-setup-invalid-target/test.py new file mode 100644 index 000000000..111449164 --- /dev/null +++ b/testsuite/tests/instr-cov/386-setup-invalid-target/test.py @@ -0,0 +1,42 @@ +""" +Check that gnatcov does not crash when passing an invalid target value when +only the C language is enabled. +""" + +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import xcov + +tmp = Wdir("tmp_") + +# Run gnatcov setup with an invalid target, while disabling the Ada language +setup_log = "setup.log" +p = xcov( + [ + "setup", + "--target=INVALID", + "--restricted-to-languages=C", + "--prefix", + "dummy", + ], + out=setup_log, + auto_config_args=False, + auto_languages=False, + auto_target_args=False, + register_failure=False, +) + +thistest.fail_if( + p.status == 0, + "'gnatcov setup' did not reject the invalid target", +) +thistest.fail_if_no_match( + "Unexpectect 'gnatcov setup' output", + regexp=( + r".*gnatcov(.exe)?: Cannot get library support for this" + r" configuration" + ), + actual=contents_of(setup_log).strip(), +) + +thistest.result() diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index dc23a0044..0ac23df48 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -514,16 +514,14 @@ package body Setup_RTS is (GPR2.Project.Registry.Attribute.Compiler.Driver, GPR2.Project.Attribute_Index.Create (GPR2.C_Language)); - - Driver_Fullname : constant String := Driver.Value.Text; - Driver_Basename : constant String := Simple_Name (Driver_Fullname); begin -- If C's compiler driver is defined, and contains a dash, we -- can only suppose it's a cross compiler with an executable of -- the form -. if Driver.Is_Defined - and then Ada.Strings.Fixed.Index (Driver_Basename, "-") > 0 + and then Ada.Strings.Fixed.Index + (Simple_Name (Driver.Value.Text), "-") > 0 then Auto_RTS_Profile := Embedded; else From c0c9e8a5b9ae8a1ef7626c698b2e2dbcb88077bb Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 6 Feb 2025 17:21:54 +0100 Subject: [PATCH 1115/1483] instr-c: Do not use c++20 features in generated files and in the runtime --- tools/gnatcov/instrument-c.adb | 71 +++++++++++++++-------- tools/gnatcov/rts/gnatcov_rts_c-strings.h | 7 +++ 2 files changed, 54 insertions(+), 24 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index aeef3a19e..b1364942e 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -4101,17 +4101,21 @@ package body Instrument.C is MCDC_Init.Append (+("&" & MCDC_Buffer_Repr & "[0]")); -- gnatcov_rts_coverage_buffers struct + -- ".field =" identifiers are commented because even though + -- they are valid C99, they are officially not supported before + -- C++20 in C++. + -- Kept as comments for the sake of readability and debugging File.Put_Line ("static const struct gnatcov_rts_coverage_buffers " & Buffers_Struct & " = {" & ASCII.LF - & " .fingerprint = " + & "/* .fingerprint = */ " & Format_Fingerprint (SC_Obligations.Fingerprint (CU)) & "," & ASCII.LF - & " .language_kind = FILE_BASED_LANGUAGE," + & "/* .language_kind = */ FILE_BASED_LANGUAGE," & ASCII.LF - & " .unit_part = NOT_APPLICABLE_PART," + & "/* .unit_part = */ NOT_APPLICABLE_PART," & ASCII.LF -- Old toolchains (for instance GNAT Pro 7.1.2) consider that @@ -4124,18 +4128,18 @@ package body Instrument.C is -- the string, which can appear e.g. in in windows full -- filenames. - & " .unit_name = " - & " {" & C_String_Literal (CU_Filename) & ", " + & "/* .unit_name = */ {" + & C_String_Literal (CU_Filename) & ", " & CU_Filename'Length'Image & "}" & "," & ASCII.LF - & " .bit_maps_fingerprint = " + & "/* .bit_maps_fingerprint = */ " & Format_Fingerprint (SC_Obligations.Bit_Maps_Fingerprint (CU)) & "," & ASCII.LF - & " .annotations_fingerprint = " + & "/* .annotations_fingerprint = */ " & Format_Fingerprint (SC_Obligations.Annotations_Fingerprint (CU)) & "," @@ -4148,20 +4152,25 @@ package body Instrument.C is -- around it, we simply use the original expression instead of -- using a wrapper pointer. - & " .statement = &" & Statement_Buffer_Repr & "[0]," + & "/* .statement = */ &" + & Statement_Buffer_Repr & "[0]," & ASCII.LF - & " .decision = &" & Decision_Buffer_Repr & "[0]," + & "/* .decision = */ &" + & Decision_Buffer_Repr & "[0]," & ASCII.LF - & " .mcdc = &" & MCDC_Buffer_Repr & "[0]," + & "/* .mcdc = */ &" + & MCDC_Buffer_Repr & "[0]," & ASCII.LF - & " .statement_last_bit = " + & "/* .statement_last_bit = */ " & Img (Unit_Bits.Last_Statement_Bit) & "," & ASCII.LF - & " .decision_last_bit = " & Img (Unit_Bits.Last_Outcome_Bit) + & "/* .decision_last_bit = */ " + & Img (Unit_Bits.Last_Outcome_Bit) & "," & ASCII.LF - & " .mcdc_last_bit = " & Img (Unit_Bits.Last_Path_Bit) + & "/* .mcdc_last_bit = */ " + & Img (Unit_Bits.Last_Path_Bit) & ASCII.LF & "};"); Group_Init.Append (+("&" & Buffers_Struct)); @@ -5340,10 +5349,12 @@ package body Instrument.C is CU_File : Text_Files.File_Type; - Buffer_Array_Decl : constant String := + Buffer_Array_Decl : constant String := "const struct gnatcov_rts_coverage_buffers_group_array " & Unit_Buffers_Array_Name (Prj.Prj_Name); - Buffer_Unit_Length : constant String := + Buffer_Group_Var_Name : constant String := + "__gcvrt_internal_buffer_group_" & To_Symbol_Name (Prj.Prj_Name); + Buffer_Unit_Length : constant String := Count_Type'Image (Buffer_Symbols.Length); begin if Sources_Trace.Is_Active then @@ -5373,24 +5384,36 @@ package body Instrument.C is -- C++ to set the C linkage), and finally the definition for that array. CU_File.Put_Line (Self.Extern_Prefix & Buffer_Array_Decl & ";"); - CU_File.Put_Line (Buffer_Array_Decl & " = {"); - CU_File.Put_Line (" " & Buffer_Unit_Length & ","); - if String_Sets.Length (Buffer_Symbols) = 0 then - -- If there are no units of interest, create a NULL pointer to avoid - -- having an empty array. + if String_Sets.Length (Buffer_Symbols) /= 0 then + + -- Create a "temporary" variable to create the buffer group array. + -- We can't create it on the fly because this would create invalid C++ + -- code (compound literals are valid C99, invalid C++ until C++20). - CU_File.Put_Line ("NULL"); - else CU_File.Put_Line - (" (const struct gnatcov_rts_coverage_buffers_group *[]) {"); + ("const struct gnatcov_rts_coverage_buffers_group *" + & Buffer_Group_Var_Name + & "[] = {"); for BS of Buffer_Symbols loop CU_File.Put (" &" & (+BS)); if BS /= Buffer_Symbols.Last_Element then CU_File.Put_Line (","); end if; end loop; - CU_File.Put_Line ("}"); + CU_File.Put_Line ("};"); + end if; + + CU_File.Put_Line (Buffer_Array_Decl & " = {"); + CU_File.Put_Line (" " & Buffer_Unit_Length & ","); + if String_Sets.Length (Buffer_Symbols) = 0 then + + -- If there are no units of interest, create a NULL pointer to avoid + -- having an empty array. + + CU_File.Put_Line ("NULL"); + else + CU_File.Put_Line (Buffer_Group_Var_Name); end if; CU_File.Put_Line ("};"); return CU_Name; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-strings.h b/tools/gnatcov/rts/gnatcov_rts_c-strings.h index 90324f906..598f9f725 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-strings.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-strings.h @@ -35,8 +35,15 @@ extern "C" /* Converts a string litteral to the corresponding gnatcov_rts_string struct value. */ +#ifdef __cplusplus +#define STR(x) \ + { \ + x, sizeof (x) - 1 \ + } // Avoid compound literal which is not valid C++ +#else #define STR(x) \ (struct gnatcov_rts_string) { x, sizeof (x) - 1 } +#endif #ifdef __cplusplus } From f8dc55e94dd7ef6e518e9845857cea6bd61cfe6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 6 Feb 2025 14:17:44 +0100 Subject: [PATCH 1116/1483] Delete pre-existing SID files prior to instrumentation There is no clear benefit to preserving SID files that would not be overwritten by the instrumentation process, and this can lead to fatal errors in gnatcov, e.g. when updating from a previous release. --- .../tests/instr-cov/384-SID-cleanup/main.adb | 10 +++ .../tests/instr-cov/384-SID-cleanup/pkg.adb | 7 ++ .../tests/instr-cov/384-SID-cleanup/pkg.ads | 5 ++ .../tests/instr-cov/384-SID-cleanup/pkh.adb | 7 ++ .../tests/instr-cov/384-SID-cleanup/pkh.ads | 5 ++ .../tests/instr-cov/384-SID-cleanup/test.opt | 1 + .../tests/instr-cov/384-SID-cleanup/test.py | 66 +++++++++++++++++++ tools/gnatcov/instrument-clean_objdirs.adb | 25 ++++++- 8 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/instr-cov/384-SID-cleanup/main.adb create mode 100644 testsuite/tests/instr-cov/384-SID-cleanup/pkg.adb create mode 100644 testsuite/tests/instr-cov/384-SID-cleanup/pkg.ads create mode 100644 testsuite/tests/instr-cov/384-SID-cleanup/pkh.adb create mode 100644 testsuite/tests/instr-cov/384-SID-cleanup/pkh.ads create mode 100644 testsuite/tests/instr-cov/384-SID-cleanup/test.opt create mode 100644 testsuite/tests/instr-cov/384-SID-cleanup/test.py diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/main.adb b/testsuite/tests/instr-cov/384-SID-cleanup/main.adb new file mode 100644 index 000000000..1f4442127 --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/main.adb @@ -0,0 +1,10 @@ +with Pkg; +with Pkh; + +with Support; + +procedure Main is +begin + Support.Assert (Pkg.Foo = 1); + Support.Assert (Pkh.Bar = 2); +end Main; diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/pkg.adb b/testsuite/tests/instr-cov/384-SID-cleanup/pkg.adb new file mode 100644 index 000000000..d507dd4a2 --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/pkg.adb @@ -0,0 +1,7 @@ +package body Pkg is + + function Foo return Integer is begin + return 1; + end Foo; + +end Pkg; diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/pkg.ads b/testsuite/tests/instr-cov/384-SID-cleanup/pkg.ads new file mode 100644 index 000000000..8a49d2fad --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Foo return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/pkh.adb b/testsuite/tests/instr-cov/384-SID-cleanup/pkh.adb new file mode 100644 index 000000000..c27f8a974 --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/pkh.adb @@ -0,0 +1,7 @@ +package body Pkh is + + function Bar return Integer is begin + return 2; + end Bar; + +end Pkh; diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/pkh.ads b/testsuite/tests/instr-cov/384-SID-cleanup/pkh.ads new file mode 100644 index 000000000..5c69eae9a --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/pkh.ads @@ -0,0 +1,5 @@ +package Pkh is + + function Bar return Integer; + +end Pkh; diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/test.opt b/testsuite/tests/instr-cov/384-SID-cleanup/test.opt new file mode 100644 index 000000000..e6c1eea36 --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/test.opt @@ -0,0 +1 @@ +bin-traces DEAD test concerns instrumentation-only feature diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/test.py b/testsuite/tests/instr-cov/384-SID-cleanup/test.py new file mode 100644 index 000000000..da4a5e60b --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/test.py @@ -0,0 +1,66 @@ +""" +Verify that gnatcov cleans up existing SID files during instrumentation. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import contents_of, gprfor + +Wdir("tmp_") + +prj = gprfor(mains=["main.adb"], srcdirs=[".."]) + +expected_cov = { + "main.adb.xcov": {"+": {9, 8}}, + "pkg.adb.xcov": {"+": {4}}, + "pkg.ads.xcov": {}, + "pkh.adb.xcov": {"+": {4}}, + "pkh.ads.xcov": {}, +} + +# Create a first report using all units +thistest.log("=== All units test ===") +output_full = "all_units" +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir", output_full], +) +check_xcov_reports(output_full, expected_cov) + +thistest.log("=== Without Pkh unit test ===") +# Now same but without pkg in the units of interest, at instrumentation time +# Only change the output dir, and not the object dir so that if the pkh.sid +# file remains after instrumentation, it will be picked up and generate a +# report with violations. +# +# In this case, we expect pkh.sid to be deleted, so no report created for this +# unit (and gnatcov coverage should complain that there is no SID for this +# specific unit). + +output_pkg = "only_pkg" + +# Pass the units argument to gnatcov instrument only to ensure the coverage +# command will attempt to pick up all sid files. +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--units", "main", "--units", "pkg"], + extra_coverage_args=["-axcov", "--output-dir", output_pkg], +) +expected_cov.pop("pkh.adb.xcov") +expected_cov.pop("pkh.ads.xcov") +check_xcov_reports(output_pkg, expected_cov) + +# Verify that gnatcov complained that there was no SID file found for Pkh +thistest.fail_if_not_equal( + what="Unexpected 'gnatcov coverage' output", + expected="warning: no SID file found for unit pkh", + actual=contents_of("coverage.log").strip(), +) + +thistest.result() diff --git a/tools/gnatcov/instrument-clean_objdirs.adb b/tools/gnatcov/instrument-clean_objdirs.adb index 26138d92b..5780259c7 100644 --- a/tools/gnatcov/instrument-clean_objdirs.adb +++ b/tools/gnatcov/instrument-clean_objdirs.adb @@ -30,7 +30,8 @@ procedure Instrument.Clean_Objdirs is procedure Clean_Subdir (Project : Project_Type); -- Callback for Project.Iterate_Projects. If Project is not externally -- built, remove all files from the "$project_name-gnatcov-instr" folder in - -- Project's object directory. + -- Project's object directory, and remove all files ending in ".sid" from + -- the object directory. function Has_Regular_Files (Directory : String) return Boolean; -- Return whether Directory contains at least one regular file @@ -42,6 +43,8 @@ procedure Instrument.Clean_Objdirs is procedure Clean_Subdir (Project : Project_Type) is Output_Dir : constant String := Project_Output_Dir (Project); Has_Output_Dir : Boolean := True; + Obj_Dir_Files : File_Array_Access; + Success : Boolean; begin Clean_Objdirs_Trace.Increase_Indent ("Processing " & Project.Name); Clean_Objdirs_Trace.Trace @@ -111,6 +114,26 @@ procedure Instrument.Clean_Objdirs is end if; Delete_Tree (Directory => Output_Dir); + + -- Remove the SID files if any + + Obj_Dir_Files := Project.Object_Dir.Read_Dir (Files_Only); + if Obj_Dir_Files /= null then + for File of Obj_Dir_Files.all loop + if File.File_Extension (Normalize => True) = ".sid" + and then File.Is_Regular_File + then + File.Delete (Success); + if not Success then + Warn + ("Failed to delete old SID file: " + & File.Display_Full_Name); + end if; + end if; + end loop; + Unchecked_Free (Obj_Dir_Files); + end if; + Clean_Objdirs_Trace.Decrease_Indent; end Clean_Subdir; From 40fbe760c0568c935dc0de617109388de322c507 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 28 Feb 2025 17:16:35 +0100 Subject: [PATCH 1117/1483] sc_obligations: Memoize the result of Traverse_SCO to avoid expensive re-computation --- tools/gnatcov/sc_obligations.adb | 116 ++++++++++++++++++------------- 1 file changed, 68 insertions(+), 48 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index d7e8be54e..aaf9d8d0d 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -388,6 +388,13 @@ package body SC_Obligations is -- For a condition or operator, pointer to the enclosing operator, or -- to enclosing decision if at top level. + Scope : Scope_Entities_Trees.Cursor := + Scope_Entities_Trees.No_Element; + -- This fields's purpose is to memoize the result of Traverse_SCO + -- for finding the scope of the given SCO. + -- It should not be used nor modified outside the function. + -- It should not be written to checkpoint files. + case Kind is when Removed => null; @@ -942,64 +949,77 @@ package body SC_Obligations is return; end if; - -- Check whether the current scope covers SCO. If not, find the first - -- one that does in the parent chain. There is always a scope for the - -- compilation unit / file, so this is guaranteed to finish. + declare + SCOD : SCO_Descriptor renames SCO_Vector (SCO); + begin - while not Covers_SCO (ST, SCO) loop - ST.Cur := Parent (ST.Cur); + -- Early return if the SCO's Scope was memoized. - -- If we reach the root of the tree, this means this SCO is not in - -- any scope, which is clearly a bug. Unless this is a function SCO - -- which can be at the root of the tree. + if SCOD.Scope /= No_Element then + ST.Cur := SCOD.Scope; + return; + end if; - declare - SCOD : SCO_Descriptor renames SCO_Vector (SCO); - begin - if SCOD.Kind /= Fun then - if Is_Root (ST.Cur) then - raise Program_Error - with "No scope found for " & Image (SCO); - end if; + -- Check whether the current scope covers SCO. If not, find the first + -- one that does in the parent chain. There is always a scope for the + -- compilation unit / file, so this is guaranteed to finish. + + while not Covers_SCO (ST, SCO) loop + ST.Cur := Parent (ST.Cur); + + -- If we reach the root of the tree, this means this SCO is not in + -- any scope, which is clearly a bug. Unless this is a function + -- SCO which can be at the root of the tree. + + if Is_Root (ST.Cur) and then SCOD.Kind /= Fun then + raise Program_Error + with "No scope found for " & Image (SCO); end if; - end; - end loop; + end loop; - -- Descend into the tree until we are on a leaf, or no child of the - -- current scope entity covers the SCO. + -- Descend into the tree until we are on a leaf, or no child of the + -- current scope entity covers the SCO. - Depth_Descent : - while not Is_Leaf (ST.Cur) loop + Depth_Descent : + while not Is_Leaf (ST.Cur) loop - -- Otherwise, find if there is a child that covers SCO, this is a - -- linear search. We could search by dichotomy as the children are - -- sorted, but this seems overkill. + -- Otherwise, find if there is a child that covers SCO, this is a + -- linear search. We could search by dichotomy as the children are + -- sorted, but this seems overkill. + -- Actually, the Multiway_Tree structure does not allow access + -- to an arbitrary nth_child (children are a linked list), + -- so a binary search would need a rewrite of the Scope handling. - declare - Child : Cursor := First_Child (ST.Cur); - In_Child : Boolean := False; - -- Whether the low bound of Child is lower than SCO (and thus - -- Child covers SCO when exiting the loop). - begin - Child_Search : - while Has_Element (Child) loop - declare - SE : constant Scope_Entity := Element (Child); - begin - In_Child := SE.From <= SCO; - exit Child_Search when SE.To >= SCO; - Child := Next_Sibling (Child); - end; - end loop Child_Search; + declare + Child : Cursor := First_Child (ST.Cur); + In_Child : Boolean := False; + -- Whether the low bound of Child is lower than SCO (and thus + -- Child covers SCO when exiting the loop). + begin + Child_Search : + while Has_Element (Child) loop + declare + SE : constant Scope_Entity := Element (Child); + begin + In_Child := SE.From <= SCO; + exit Child_Search when SE.To >= SCO; + Child := Next_Sibling (Child); + end; + end loop Child_Search; - -- If we found a child containing SCO, keep descending into its - -- children, otherwise we have found the inner most scope. + -- If we found a child containing SCO, keep descending into its + -- children, otherwise we have found the inner most scope. - exit Depth_Descent when not In_Child or else Child = No_Element; - ST.Cur := Child; - pragma Loop_Invariant (Covers_SCO (ST, SCO)); - end; - end loop Depth_Descent; + exit Depth_Descent when not In_Child or else Child = No_Element; + ST.Cur := Child; + pragma Loop_Invariant (Covers_SCO (ST, SCO)); + end; + end loop Depth_Descent; + + -- Memoize the Scope in the SCO descriptor. + + SCOD.Scope := ST.Cur; + end; end Traverse_SCO; -------------------------- From 9df5b62c38eea83ade3e001eee0176f5108be5ac Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 3 Mar 2025 16:41:11 +0100 Subject: [PATCH 1118/1483] sc_obligations: Remove trivial wrapper function for In_Scope_Of_Interest --- tools/gnatcov/coverage-source.adb | 3 +-- tools/gnatcov/sc_obligations.adb | 33 ++++++++++++++++++------------- tools/gnatcov/sc_obligations.ads | 23 +++++---------------- 3 files changed, 25 insertions(+), 34 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 878138487..4a620d9a9 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -2293,8 +2293,7 @@ package body Coverage.Source is Process : access procedure (SCI : in out Source_Coverage_Info)) is begin - Traverse_SCO (ST, SCO); - if In_Scope_Of_Interest (ST) then + if In_Scope_Of_Interest (ST, SCO) then Update_SCI (SCO, Tag, Process); end if; end Update_SCI_Wrapper; diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index aaf9d8d0d..4da2ed387 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -72,6 +72,19 @@ package body SC_Obligations is -- Return whether SCO is covered by that element's SCO range. Id the SCO is -- a function SCO, then the scope can be the root of the tree. + procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) with + Pre => Get_CU (ST) = No_CU_Id + or else SCO in First_SCO (Get_CU (ST)) .. Last_SCO (Get_CU (ST)); + -- Position ST on the inner-most scope that contains SCO. + -- + -- This does nothing on a scope traversal type not initialized, or + -- initialized on a CU with no scopes attached to it. + -- + -- NOTE: Traverse_SCO will browse the scope tree structure at each new + -- given SCO, making it a very EXPENSIVE call. + -- For now, it memoizes the result for each SCO in its SCO descriptor, + -- so the browsing is not duplicated. + --------------- -- Instances -- --------------- @@ -1026,10 +1039,15 @@ package body SC_Obligations is -- In_Scope_Of_Interest -- -------------------------- - function In_Scope_Of_Interest (ST : Scope_Traversal_Type) return Boolean is + function In_Scope_Of_Interest + (ST : in out Scope_Traversal_Type; + SCO : SCO_Id) return Boolean + is use Scope_Entities_Trees; Cur : Cursor; begin + Traverse_SCO (ST, SCO); + -- If no subprogram of interest was requested, consider that they are -- all of interest. @@ -1050,19 +1068,6 @@ package body SC_Obligations is return False; end In_Scope_Of_Interest; - -------------------------- - -- In_Scope_Of_Interest -- - -------------------------- - - function In_Scope_Of_Interest - (ST : in out Scope_Traversal_Type; - SCO : SCO_Id) return Boolean - is - begin - Traverse_SCO (ST, SCO); - return In_Scope_Of_Interest (ST); - end In_Scope_Of_Interest; - ----------------- -- Add_Address -- ----------------- diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index a9f73199d..3c0e2e090 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -379,25 +379,12 @@ package SC_Obligations is function Get_CU (ST : Scope_Traversal_Type) return CU_Id; -- Return the compilation unit id which ST is currently traversing - procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) with - Pre => Get_CU (ST) = No_CU_Id - or else SCO in First_SCO (Get_CU (ST)) .. Last_SCO (Get_CU (ST)); - -- Position ST on the inner-most scope that contains SCO. - -- - -- This does nothing on a scope traversal type not initialized, or - -- initialized on a CU with no scopes attached to it. - - function In_Scope_Of_Interest (ST : Scope_Traversal_Type) return Boolean; - -- Return whether at least one scope in Switches.Subps_Of_Interest contains - -- the last SCO on which Traverse_SCO (ST, ...) was called. Note that this - -- also returns True if Switches.Subps_Of_Interest is empty (i.e. consider - -- that all subprograms are of interest in that case). - function In_Scope_Of_Interest - (ST : in out Scope_Traversal_Type; SCO : SCO_Id) return Boolean with - Pre => Get_CU (ST) = No_CU_Id - or else SCO in First_SCO (Get_CU (ST)) .. Last_SCO (Get_CU (ST)); - -- Shortcut for Traverse_SCO (ST, SCO); return In_Scope_Of_Interest (ST); + (ST : in out Scope_Traversal_Type; SCO : SCO_Id) return Boolean; + -- Return whether at least one scope in Switches.Subps_Of_Interest contains + -- the given SCO. + -- Note that this also returns True if Switches.Subps_Of_Interest is empty + -- (i.e. consider that all subprograms are of interest in that case). No_Scope_Entity : constant Scope_Entity := (From => No_SCO_Id, From 1807bf928ebbcb6b01bc00854ef0df9cccded6e9 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 24 Feb 2025 12:15:50 +0100 Subject: [PATCH 1119/1483] instrument-input_traces.adb: Support Morello's 16 bytes alignment --- testsuite/SUITE/srctracelib.py | 2 +- tools/gnatcov/instrument-input_traces.adb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/SUITE/srctracelib.py b/testsuite/SUITE/srctracelib.py index 47feaa33e..4bf9bf084 100755 --- a/testsuite/SUITE/srctracelib.py +++ b/testsuite/SUITE/srctracelib.py @@ -138,7 +138,7 @@ def read(cls, fp): ) alignment = header["alignment"] - if alignment not in (1, 2, 4, 8): + if alignment not in (1, 2, 4, 8, 16): raise ValueError("Invalid alignment: {}".format(alignment)) info_entries = [] diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 1c6cf50a5..a9eccd02f 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -366,7 +366,7 @@ package body Instrument.Input_Traces is " only."); return; - elsif Raw_Header.Alignment not in 1 | 2 | 4 | 8 then + elsif Raw_Header.Alignment not in 1 | 2 | 4 | 8 | 16 then Create_Error (Result, "invalid alignment"); return; From 2059167fc1e64c587d775a35d3f76f0258755799 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 27 Feb 2025 14:27:17 +0100 Subject: [PATCH 1120/1483] gnatcov.adb: Consider "morello" platforms as 64-bit --- tools/gnatcov/gnatcov.adb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/gnatcov.adb b/tools/gnatcov/gnatcov.adb index 1c2a1ac62..b4a15a7fd 100644 --- a/tools/gnatcov/gnatcov.adb +++ b/tools/gnatcov/gnatcov.adb @@ -65,7 +65,11 @@ begin -- Otherwise, infer the gnatcov executable to use from the target -- option. - or else Index (Target (Target'First .. Last_Before_Dash), "64") /= 0; + or else Index (Target (Target'First .. Last_Before_Dash), "64") /= 0 + + -- morello is 64-bits even though it's not explicitely written. + + or else Index (Target, "morello") /= 0; end; -- Now run the correct arch-specific entry point From b6b75072a32798d125322bf36a748cbf8434f717 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 26 Feb 2025 18:30:12 +0100 Subject: [PATCH 1121/1483] tests: Kill tests that use bin-traces features in src-traces --- testsuite/tests/I511-019-response-files/test.opt | 1 + testsuite/tests/IA16-028-disp-routines/test.opt | 1 + testsuite/tests/KC06-023-list_as_ali/test.opt | 1 + testsuite/tests/O529-021-wrong-elf-class/test.opt | 1 + testsuite/tests/OB23-036/test.opt | 1 + testsuite/tests/QB14-023-stack-overflow/test.opt | 1 + 6 files changed, 6 insertions(+) create mode 100644 testsuite/tests/I511-019-response-files/test.opt create mode 100644 testsuite/tests/IA16-028-disp-routines/test.opt create mode 100644 testsuite/tests/KC06-023-list_as_ali/test.opt create mode 100644 testsuite/tests/O529-021-wrong-elf-class/test.opt create mode 100644 testsuite/tests/OB23-036/test.opt create mode 100644 testsuite/tests/QB14-023-stack-overflow/test.opt diff --git a/testsuite/tests/I511-019-response-files/test.opt b/testsuite/tests/I511-019-response-files/test.opt new file mode 100644 index 000000000..b553eb717 --- /dev/null +++ b/testsuite/tests/I511-019-response-files/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise disp-routines, specific to binary trace mode diff --git a/testsuite/tests/IA16-028-disp-routines/test.opt b/testsuite/tests/IA16-028-disp-routines/test.opt new file mode 100644 index 000000000..b553eb717 --- /dev/null +++ b/testsuite/tests/IA16-028-disp-routines/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise disp-routines, specific to binary trace mode diff --git a/testsuite/tests/KC06-023-list_as_ali/test.opt b/testsuite/tests/KC06-023-list_as_ali/test.opt new file mode 100644 index 000000000..a29228f15 --- /dev/null +++ b/testsuite/tests/KC06-023-list_as_ali/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise map-routines, specific to binary trace mode diff --git a/testsuite/tests/O529-021-wrong-elf-class/test.opt b/testsuite/tests/O529-021-wrong-elf-class/test.opt new file mode 100644 index 000000000..f13339489 --- /dev/null +++ b/testsuite/tests/O529-021-wrong-elf-class/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise disassemble, specific to binary trace mode diff --git a/testsuite/tests/OB23-036/test.opt b/testsuite/tests/OB23-036/test.opt new file mode 100644 index 000000000..b553eb717 --- /dev/null +++ b/testsuite/tests/OB23-036/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise disp-routines, specific to binary trace mode diff --git a/testsuite/tests/QB14-023-stack-overflow/test.opt b/testsuite/tests/QB14-023-stack-overflow/test.opt new file mode 100644 index 000000000..a29228f15 --- /dev/null +++ b/testsuite/tests/QB14-023-stack-overflow/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD Test exercise map-routines, specific to binary trace mode From 5266240cb709794f5b3b4162b7e011b0fec094f6 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 27 Feb 2025 11:43:31 +0100 Subject: [PATCH 1122/1483] test(Qualif-Ada-stmt-Robustness-No_Elab_Inlib): Only use bin-traces flags when testing in binary traces mode --- .../Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr | 11 ++++++++++- .../Qualif/Ada/stmt/Robustness/No_Elab_InLib/test.py | 4 +++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr index 19f25e9e5..156a94465 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr +++ b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/mylib/mylib.gpr @@ -4,7 +4,16 @@ library project mylib is for library_kind use "static"; for library_name use project'name; for library_dir use "lib"; + + type Trace_Mode_Enum is ("src", "bin"); + Trace_Mode : Trace_Mode_Enum := external ("TRACE_MODE"); package compiler is - for switches("ada") use ("-fpreserve-control-flow", "-fdump-scos", "-g"); + case Trace_Mode is + when "bin" => + for switches("ada") use + ("-fpreserve-control-flow", "-fdump-scos", "-g"); + when "src" => + null; + end case; end compiler; end mylib; diff --git a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/test.py b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/test.py index c5294fe74..d38517cd8 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/test.py +++ b/testsuite/Qualif/Ada/stmt/Robustness/No_Elab_InLib/test.py @@ -10,7 +10,9 @@ covcontrol=CovControl( deps=[libdep], gprsw=GPRswitches( - root_project="gen.gpr", units=["foo", "bar", "klunk"] + root_project="gen.gpr", + units=["foo", "bar", "klunk"], + xvars=[("TRACE_MODE", thistest.options.trace_mode)], ), ) ) From 1c16ac60b8997a65abe26067b2ab470a2a9008dd Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 28 Feb 2025 13:49:07 +0100 Subject: [PATCH 1123/1483] libsupport: morello uses "exit" LastChance Handler --- testsuite/testsuite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 8bf8ac158..f189b8ea2 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1150,7 +1150,7 @@ def _build_libsupport(self): # termination, which is not the point of the silent last chance # handler. QNX however does provide the exit function, so use that # instead. - if args.target and "qnx" in args.target: + if args.target and ("qnx" in args.target or "morello" in args.target): libsup_vars.append("SILENT_LCH=exit") logfile = os.path.join(self.output_dir, "build_support.out") From 383dfd7bfbf76a35d3f5cb77f238246a06052f63 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 4 Mar 2025 16:39:31 +0100 Subject: [PATCH 1124/1483] libsupport: morello does not use libsupport's memory unit --- tools/gnatcov/examples/support/libsupport.gpr | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/examples/support/libsupport.gpr b/tools/gnatcov/examples/support/libsupport.gpr index ce5014104..4273342f3 100644 --- a/tools/gnatcov/examples/support/libsupport.gpr +++ b/tools/gnatcov/examples/support/libsupport.gpr @@ -63,7 +63,14 @@ project Libsupport is Langs := Langs & ("C"); - Source_Dirs := Source_Dirs & ("src/memory"); + -- Use libsupport's custom memory functions, except for the + -- morello target, for which they produce unwanted behavior. + + case Conf.Target is + when "morello-elf" => null; + when others => Source_Dirs := Source_Dirs & ("src/memory"); + end case; + Source_Dirs := Source_Dirs & ("src/" & Conf.Target); -- Add whatever we need to find our Last Chance Handler, to From 8c5971cab626f73d5b442e72588af09f83bd6a2c Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 5 Mar 2025 15:50:32 +0100 Subject: [PATCH 1125/1483] testsuite(tutils.py): Use the target version in the name --- testsuite/SUITE/tutils.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index ca599f594..d63fc532f 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -1063,10 +1063,16 @@ def run_cov_program( assert thistest.options.board or thistest.env.target.machine target = thistest.env.target.platform + os_ver = ( + thistest.env.target.os.version if thistest.env.target.os else "" + ) + + target += f",{os_ver}" + if thistest.options.board: - target += f",,{thistest.options.board}" + target += f",{thistest.options.board}" else: - target += f",,{thistest.env.target.machine}" + target += f",{thistest.env.target.machine}" # run-cross2 is a python script. As Windows does not parse shebangs, # use the python executable as main program instead of the script. From 62b645d29b813ee87fd31a9c9a3e147248ec14b9 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 5 Mar 2025 16:01:15 +0100 Subject: [PATCH 1126/1483] test(Qualif-Ada-*-MixedConstructs-While_If4): Kill tests on morello --- testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/test.opt | 1 + testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/test.opt | 1 + testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/test.opt | 1 + 3 files changed, 3 insertions(+) create mode 100644 testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/test.opt create mode 100644 testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/test.opt create mode 100644 testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/test.opt diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/test.opt b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/test.opt new file mode 100644 index 000000000..510071fba --- /dev/null +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/While_If4/test.opt @@ -0,0 +1 @@ +morello DEAD The test uses memory tricks that are prohibited on CHERI platforms diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/test.opt b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/test.opt new file mode 100644 index 000000000..510071fba --- /dev/null +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/While_If4/test.opt @@ -0,0 +1 @@ +morello DEAD The test uses memory tricks that are prohibited on CHERI platforms diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/test.opt b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/test.opt new file mode 100644 index 000000000..510071fba --- /dev/null +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/While_If4/test.opt @@ -0,0 +1 @@ +morello DEAD The test uses memory tricks that are prohibited on CHERI platforms From f370f3c420e829c4a7293a773e3810bf2aef8c59 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 6 Mar 2025 14:01:51 +0100 Subject: [PATCH 1127/1483] Doc: Remove references to bin-traces specific interfaces This removes any remaining references to --scos, and move separate coverage documentation to the binary-traces appendix. --- doc/gnatcov/bin_intro.rst | 2 + doc/gnatcov/cons_checkpoints.rst | 29 ++++---- doc/gnatcov/cov_metrics.rst | 1 - doc/gnatcov/cov_source.rst | 123 ++++--------------------------- doc/gnatcov/gnatcov_bin_part.rst | 1 + doc/gnatcov/separate_cov.rst | 93 +++++++++++++++++++++++ 6 files changed, 126 insertions(+), 123 deletions(-) create mode 100644 doc/gnatcov/separate_cov.rst diff --git a/doc/gnatcov/bin_intro.rst b/doc/gnatcov/bin_intro.rst index 398eebd1b..651a0e6de 100644 --- a/doc/gnatcov/bin_intro.rst +++ b/doc/gnatcov/bin_intro.rst @@ -186,4 +186,6 @@ specific considerations: - :ref:`osmetrics` +- :ref:`generics_sep` + - :ref:`bin_convert` diff --git a/doc/gnatcov/cons_checkpoints.rst b/doc/gnatcov/cons_checkpoints.rst index ef356d479..20140de14 100644 --- a/doc/gnatcov/cons_checkpoints.rst +++ b/doc/gnatcov/cons_checkpoints.rst @@ -164,22 +164,21 @@ sequence of commands such as:: # Process test1.trace, saving the resulting coverage state in a newly # created checkpoint: - gnatcov coverage --level=<> --scos=@alis test1.trace \ + gnatcov coverage --level=<> -P test1.srctrace \ --save-checkpoint=testsuite.ckpt - # Process subsequent test traces test2.trace .. testN.trace, each time + # Process subsequent test traces test2.srctrace .. testN.srctrace, each time # starting with the coverage state reached at the previous iteration, # and saving the resulting coverage state in the same checkpoint file # (overwriting it): - gnatcov coverage --level=<> --scos=@alis test2.trace \ + gnatcov coverage --level=<> -P test2.srctrace \ --checkpoint=testsuite.ckpt --save-checkpoint=testsuite.ckpt ... - gnatcov coverage --level=<> --scos=@alis testN.trace \ + gnatcov coverage --level=<> -P testN.srctrace \ --checkpoint=testsuite.ckpt --save-checkpoint=testsuite.ckpt # Now produce a report from the cumulated results: - gnatcov coverage --level=<> --scos=@alis \ - --checkpoint=testsuite.ckpt --annotate=<> + gnatcov coverage --level=<> --checkpoint=testsuite.ckpt --annotate=<> The big advantage of this approach is that it stores everything in a single @@ -211,9 +210,9 @@ Now suppose that you want to assess the global coverage for a system comprising both unit A and unit B. If the two sets of trace files are consolidated using a single execution of |gcvcov| as in:: - gnatcov coverage --level=stmt --scos=a.ali --scos=b.ali --annotate=report \ - testA1.trace ... testAN.trace \ - testB1.trace ... testBN.trace + gnatcov coverage --level=stmt --units=A --units=B --annotate=report \ + testA1.srctrace ... testAN.srctrace \ + testB1.srctrace ... testBN.srctrace then calls to B made by A while running testsuite A will contribute to discharging coverage obligations for unit B, and the other way round. @@ -229,17 +228,17 @@ interest for that run. A consolidated coverage report can thus be constructed using a two pass analysis:: - # Discharge the coverage obligations for unit A (--scos=a.ali) using + # Discharge the coverage obligations for unit A (--units=A) using # trace files from testsuite A. - gnatcov coverage --level=stmt --scos=a.ali \ - testA1.trace ... testAN.trace \ + gnatcov coverage --level=stmt --units=A \ + testA1.srctrace ... testAN.srctrace \ --save-checkpoint=testsuiteA.ckpt - # Discharge the coverage obligations for unit B (--scos=b.ali) using + # Discharge the coverage obligations for unit B (--units=B) using # trace files from testsuite B, consolidate with previous results from # testsuite A (--checkpoint), and produce a report (--annotate). - gnatcov coverage --level=stmt --scos=b.ali \ - testB1.trace ... testBN.trace --checkpoint=testsuiteA.ckpt \ + gnatcov coverage --level=stmt --units=B \ + testB1.srctrace ... testBN.srctrace --checkpoint=testsuiteA.ckpt \ --annotate=report In a consolidated report produced following this procedure, each set of trace diff --git a/doc/gnatcov/cov_metrics.rst b/doc/gnatcov/cov_metrics.rst index 2a5041e6b..686929827 100644 --- a/doc/gnatcov/cov_metrics.rst +++ b/doc/gnatcov/cov_metrics.rst @@ -173,4 +173,3 @@ solid theoretical grounds established as part of the *Couverture* research project from which |gcp| originates. The core particularity allowing full branch coverage without mcdc is the presence of decisions with BDDs which are not trees, as we have in this specfic case, - diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index a3bf92283..e288b66ba 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -175,18 +175,18 @@ considered as trace file arguments. At least one trace file is required for the command lines to illustrate. Other examples will be exposed along the course of the following sections:: - gnatcov coverage --level=stmt --scos=@alis --annotate=report --trace=prog.trace - # (a) (b) (c) (d) + gnatcov coverage --level=stmt -P ut.gpr --annotate=report --trace=prog.srctrace + # (a) (b) (c) (d) # (a) Request Statement coverage assessment, - # (b) for units associated with the ALI files listed in the "alis" text file, + # (b) for units belonging to the "ut.gpr" project, # (c) producing a synthetic text report on standard output (no -o option), # (d) out of a single execution trace "prog.trace". - gnatcov coverage --level=stmt+decision --scos=@alis --annotate=html t1 t2 + gnatcov coverage --level=stmt+decision -P ut.gpr --annotate=html t1 t2 # Statement and Decision coverage assessments for two traces "t1" and "t2", # producing an html report in the current directory. - gnatcov coverage --level=stmt+decision --scos=@alis --annotate=html @mytraces + gnatcov coverage --level=stmt+decision -P ut.gpr --annotate=html @mytraces # Same report, with t1 and t2 listed in the "mytraces" text file gnatcov coverage --level=stmt -Papp.gpr --annotate=html @mytraces @@ -670,10 +670,11 @@ driver ` in ``test_div1.adb``: Assert (Div_With_Check (X, 1) = X); end; -From a ``test_div1.trace`` obtained with |gcvrun|, we analyze for the -Statement Coverage criterion using the following |gcvcov| invocation:: +From a ``test_div1.srctrace`` obtained by building the instrumented source +produced with |gcvins|, we analyze for the Statement Coverage criterion using +the following |gcvcov| invocation:: - gnatcov coverage --level=stmt --scos=div_with_check.ali --annotate=xcov test_div1.trace + gnatcov coverage --level=stmt -P ut.gpr --annotate=xcov test_div1.srctrace We get an :cmd-option:`=xcov` annotated source result in text format for the functional unit on which the analysis is focused, in @@ -1846,12 +1847,14 @@ where the generic source is considered as the entity of interest, to which all the instances contribute, and one where each instance is considered as a separate entity of interest. -Combined coverage on generics (default behavior) ------------------------------------------------- +.. _generics_cov: + +Combined coverage on generics +----------------------------- -By default, Ada generic units are also uniformly treated as single source -entities, with the coverage achieved by all the instances combined and -reported against the generic source only, not for each individual instance. +Ada generic units are also uniformly treated as single source entities, with +the coverage achieved by all the instances combined and reported against the +generic source only, not for each individual instance. Consider the following functional Ada generic unit for example. It provides a simple vector type abstraction on which two operations are available; ``Inc`` @@ -1933,100 +1936,6 @@ fully covered by default:: 15 .: end; 16 .: end; -Per instance analysis is possible though, as part of what we refer to as -:dfn:`separated coverage` facilities. - -Separated coverage on generics ------------------------------- - -As described above, a single coverage analysis of any source construct is -performed by default, consolidating all code copies generated by this -construct. For subprograms, this means consolidation over all inlined -copies. For generic units, consolidation over all instances. - -A finer-grained analysis is possible, where distinct copies of the code coming -from a given source construct are identified according to some criterion, and -a separate coverage assessment is made for each of these copies. - -In this case, coverage violations carry an additional indication of which code -copy the violation is reported for, available in all but the non-extended -``xcov`` and ``html`` output formats. The non-extended ``xcov`` and ``html`` -formats simply convey partial coverage achievement on a line as soon one -violation get reported for an obligation on that line, regardless of which -copy the violation originates from. - -|gcv| supports different modes for such analyses, detailed in the following -subsections. - - -Separation by instance (:cmd-option:`-S instance`) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In this mode, two code regions coming from the same source construct will -undergo separate coverage analyses if they come from different generic -instances, identified by the instanciation source location. - -For our ``Vops`` example, selecting an output format where the -violations detailed are exposed, this translates as:: - - gnatcov coverage -Pvops.gpr --annotate=report -S instance [...] - ... - vops.adb:5:11: statement not executed (from v8.ads:2:1) - vops.adb:6:10: statement not executed (from v8.ads:2:1) - vops.adb:12:11: statement not executed (from v5.ads:2:1) - vops.adb:13:10: statement not executed (from v5.ads:2:1) - - -We do observe violations on the ``Vops`` generic body, fully covered without -:cmd-option:`-S instance`. This is the outcome of an analysis conducted on the -two generic instances separately, each designated by a ``(from )`` indication. - -|gcv| needs to see the coverage obligations correponding to each instance in -this mode. This is achieved transparently by the use of a project file in the -example command lines we quoted and needs particular care when the Library -Information files are provided manually with :cmd-option:`--scos` instead. - -Indeed, even if we aim at getting coverage results for the ``vops.adb`` source, -passing :cmd-option:`--scos=vops.ali` alone isn't enough when per instance -separate analysis is desired. Separate coverage analysis for the instances -entails coverage obligations for the instances, and this requires the units -where the instantiations occur to be declared of interest as well. In our -example, this means passing :cmd-option:`--scos=v5.ali` and -:cmd-option:`--scos=v8.ali` in addition. - -Separation by instance relies on specific compiler support available in the -GNAT Pro toolchain since the 7.2 release. For older toolchains, another mode -is available which reports separate coverage statuses for copies associated -with distinct symbols of the executable file. As we will describe, this -provides a good approximation of per-instance analysis in absence of inlining, -and becomes inaccurate when inlining comes into play. - -Separation by routine (:cmd-option:`-S routine`, *obsolete*) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In this mode, two code regions coming from the same source construct will -undergo separate coverage analyses if they occur in different symbols of the -executable file. This scheme is obsolete, unreliable in presence of inlining. - -When a given subprogram is inlined in two different calling routines, each -inlined copy thus undergoes a separate coverage assessment. In the absence of -inlining, this will also ensure that different instances of the same generic -unit will have separated coverage analyses, since the compiler generates -different symbol names for different program units. For our ``Vops`` example, -this would be:: - - gnatcov coverage -Pvops.gpr --annotate=report -S routine [...] - ... - vops.adb:5:11: statement not executed (from v8__inc) - vops.adb:6:10: statement not executed (from v8__inc) - vops.adb:12:11: statement not executed (from v5__mult) - vops.adb:13:10: statement not executed (from v5__mult) - - -On the other hand, if two distinct instances of a generic subprogram are -inlined within a single calling routine, they will undergo a single coverage -analysis since they now occur in the same symbol. Handling Ada assertions and contracts ===================================== diff --git a/doc/gnatcov/gnatcov_bin_part.rst b/doc/gnatcov/gnatcov_bin_part.rst index e9c3a9e8c..6a5d1462c 100644 --- a/doc/gnatcov/gnatcov_bin_part.rst +++ b/doc/gnatcov/gnatcov_bin_part.rst @@ -11,4 +11,5 @@ Appendix A. Using GNATcoverage Binary Traces cov_metrics bin_gps bin_convert + separate_cov bin_limitations diff --git a/doc/gnatcov/separate_cov.rst b/doc/gnatcov/separate_cov.rst new file mode 100644 index 000000000..6276c8d2d --- /dev/null +++ b/doc/gnatcov/separate_cov.rst @@ -0,0 +1,93 @@ +.. _generics_sep: + +Separated coverage on generics +------------------------------ + +As described in section :ref:`generics_cov`, a single coverage analysis +of any source construct is performed by default, consolidating all code copies +generated by this construct. For subprograms, this means consolidation over all +inlined copies. For generic units, consolidation over all instances. + +A finer-grained analysis is possible, where distinct copies of the code coming +from a given source construct are identified according to some criterion, and +a separate coverage assessment is made for each of these copies. + +In this case, coverage violations carry an additional indication of which code +copy the violation is reported for, available in all but the non-extended +``xcov`` and ``html`` output formats. The non-extended ``xcov`` and ``html`` +formats simply convey partial coverage achievement on a line as soon one +violation get reported for an obligation on that line, regardless of which +copy the violation originates from. + +|gcv| supports different modes for such analyses, detailed in the following +subsections. + + +Separation by instance (:cmd-option:`-S instance`) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In this mode, two code regions coming from the same source construct will +undergo separate coverage analyses if they come from different generic +instances, identified by the instanciation source location. + +For our ``Vops`` example, selecting an output format where the +violations detailed are exposed, this translates as:: + + gnatcov coverage -Pvops.gpr --annotate=report -S instance [...] + ... + vops.adb:5:11: statement not executed (from v8.ads:2:1) + vops.adb:6:10: statement not executed (from v8.ads:2:1) + vops.adb:12:11: statement not executed (from v5.ads:2:1) + vops.adb:13:10: statement not executed (from v5.ads:2:1) + + +We do observe violations on the ``Vops`` generic body, fully covered without +:cmd-option:`-S instance`. This is the outcome of an analysis conducted on the +two generic instances separately, each designated by a ``(from )`` indication. + +|gcv| needs to see the coverage obligations correponding to each instance in +this mode. This is achieved transparently by the use of a project file in the +example command lines we quoted and needs particular care when the Library +Information files are provided manually with :cmd-option:`--scos` instead. + +Indeed, even if we aim at getting coverage results for the ``vops.adb`` source, +passing :cmd-option:`--scos=vops.ali` alone isn't enough when per instance +separate analysis is desired. Separate coverage analysis for the instances +entails coverage obligations for the instances, and this requires the units +where the instantiations occur to be declared of interest as well. In our +example, this means passing :cmd-option:`--scos=v5.ali` and +:cmd-option:`--scos=v8.ali` in addition. + +Separation by instance relies on specific compiler support available in the +GNAT Pro toolchain since the 7.2 release. For older toolchains, another mode +is available which reports separate coverage statuses for copies associated +with distinct symbols of the executable file. As we will describe, this +provides a good approximation of per-instance analysis in absence of inlining, +and becomes inaccurate when inlining comes into play. + +Separation by routine (:cmd-option:`-S routine`, *obsolete*) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In this mode, two code regions coming from the same source construct will +undergo separate coverage analyses if they occur in different symbols of the +executable file. This scheme is obsolete, unreliable in presence of inlining. + +When a given subprogram is inlined in two different calling routines, each +inlined copy thus undergoes a separate coverage assessment. In the absence of +inlining, this will also ensure that different instances of the same generic +unit will have separated coverage analyses, since the compiler generates +different symbol names for different program units. For our ``Vops`` example, +this would be:: + + gnatcov coverage -Pvops.gpr --annotate=report -S routine [...] + ... + vops.adb:5:11: statement not executed (from v8__inc) + vops.adb:6:10: statement not executed (from v8__inc) + vops.adb:12:11: statement not executed (from v5__mult) + vops.adb:13:10: statement not executed (from v5__mult) + + +On the other hand, if two distinct instances of a generic subprogram are +inlined within a single calling routine, they will undergo a single coverage +analysis since they now occur in the same symbol. From 0270db6f276304a8fb2d1e7ff0433bf64e3d2e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 7 Mar 2025 10:34:47 +0100 Subject: [PATCH 1128/1483] Remove XFAIL for recursive expr func tests in bin-traces --- .../instr-cov/expr_func/aspects/rec_asp_no-prespec/test.opt | 1 - .../tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.opt | 1 - .../instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.opt | 1 - .../instr-cov/expr_func/aspects/rec_no-asp_prespec/test.opt | 1 - 4 files changed, 4 deletions(-) delete mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.opt delete mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.opt delete mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.opt delete mode 100644 testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.opt diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.opt b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.opt deleted file mode 100644 index 13161be34..000000000 --- a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_no-prespec/test.opt +++ /dev/null @@ -1 +0,0 @@ -bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.opt b/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.opt deleted file mode 100644 index 13161be34..000000000 --- a/testsuite/tests/instr-cov/expr_func/aspects/rec_asp_prespec/test.opt +++ /dev/null @@ -1 +0,0 @@ -bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.opt b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.opt deleted file mode 100644 index 13161be34..000000000 --- a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_no-prespec/test.opt +++ /dev/null @@ -1 +0,0 @@ -bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. diff --git a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.opt b/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.opt deleted file mode 100644 index 13161be34..000000000 --- a/testsuite/tests/instr-cov/expr_func/aspects/rec_no-asp_prespec/test.opt +++ /dev/null @@ -1 +0,0 @@ -bin-traces,CARGS_O1,CARGS_gnatp XFAIL U621-007: decision map & recursive inlined expr. func. From 6d3eae493c59950258747bd4885cdd5666de5001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 7 Mar 2025 10:37:36 +0100 Subject: [PATCH 1129/1483] Re-activatre test for CCG The corresponding issue has been resolved in CCG. --- .../Qualif/Ada/decision/1_Core/Operands/PnestStaType/test.opt | 1 - 1 file changed, 1 deletion(-) diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/test.opt index 3a1fbb780..b057462eb 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/test.opt +++ b/testsuite/Qualif/Ada/decision/1_Core/Operands/PnestStaType/test.opt @@ -1,3 +1,2 @@ 7.1.2,bin-traces SKIP bogus sloc info for condition involving packed array, fixed post 7.0 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 -c XFAIL pending resolution of eng/toolchain/gnat-llvm#221 From 3b2a1d853bb344230cf2e6d2f2636dd8162f9c72 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 6 Mar 2025 13:36:26 +0100 Subject: [PATCH 1130/1483] extract-base64-trace: Delete output file if the input digest is invalid --- tools/gnatcov/instrument-input_traces.adb | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index a9eccd02f..0067dc593 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -1114,6 +1114,14 @@ package body Instrument.Input_Traces is if not TIO.End_Of_Line (Input) and then TIO.Col (Input) > 1 then if Started_Trace and then not Ignore_Line then + + -- Remove any corrupted source trace file that + -- started to be generated. + + if Had_One_Trace then + BIO.Delete (Output); + end if; + Outputs.Fatal_Error ("Unexpected long line in Base64 trace"); else @@ -1172,6 +1180,15 @@ package body Instrument.Input_Traces is -- base64 characters. if Buffer (First .. Last)'Length mod 4 /= 0 then + + -- If there is a format error in the base64 encoding, + -- properly exit by removing the output file that may have been + -- created, to avoid leaving a corrupted file to the user. + + if Had_One_Trace then + BIO.Delete (Output); + end if; + Outputs.Fatal_Error ("Invalid Base64 trace: incomplete group of 4 characters"); end if; @@ -1221,7 +1238,7 @@ package body Instrument.Input_Traces is if not Had_One_Trace then Outputs.Fatal_Error ("No Base64 trace found"); elsif Started_Trace then - BIO.Close (Output); + BIO.Delete (Output); Outputs.Fatal_Error ("Incomplete Base64 trace"); end if; end Extract_Base64_Trace; From 973d3266b71041364ce7c9541a13fa11eb0ecae5 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 13 Mar 2025 14:32:35 +0100 Subject: [PATCH 1131/1483] test(extract-base64-trace): Check good behavior upon error --- testsuite/SUITE/cutils.py | 5 ++ .../extract-base64-trace-errors/extra.opt | 1 + .../incomplete-4-characters-group/main.adb | 6 ++ .../incomplete-4-characters-group/test.py | 52 +++++++++++++++ .../incomplete-base64/main.adb | 6 ++ .../incomplete-base64/test.py | 54 +++++++++++++++ .../unexpected-too-long-line/main.adb | 6 ++ .../unexpected-too-long-line/test.py | 66 +++++++++++++++++++ 8 files changed, 196 insertions(+) create mode 100644 testsuite/tests/extract-base64-trace-errors/extra.opt create mode 100644 testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/main.adb create mode 100644 testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/test.py create mode 100644 testsuite/tests/extract-base64-trace-errors/incomplete-base64/main.adb create mode 100644 testsuite/tests/extract-base64-trace-errors/incomplete-base64/test.py create mode 100644 testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/main.adb create mode 100644 testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/test.py diff --git a/testsuite/SUITE/cutils.py b/testsuite/SUITE/cutils.py index bcbafaed2..024f8ca56 100644 --- a/testsuite/SUITE/cutils.py +++ b/testsuite/SUITE/cutils.py @@ -55,6 +55,11 @@ def ext(filename): return os.path.splitext(filename)[1] +def exists(filename): + """Return true if the filename exists""" + return os.path.exists(filename) + + def contents_of(filename): """Return contents of file FILENAME""" with open(filename) as fd: diff --git a/testsuite/tests/extract-base64-trace-errors/extra.opt b/testsuite/tests/extract-base64-trace-errors/extra.opt new file mode 100644 index 000000000..5f2157d55 --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/extra.opt @@ -0,0 +1 @@ +!src-traces DEAD extract-base64-traces is specific to source traces diff --git a/testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/main.adb b/testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/test.py b/testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/test.py new file mode 100644 index 000000000..5c21fc74c --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/incomplete-4-characters-group/test.py @@ -0,0 +1,52 @@ +""" +Make sure that an invalid base64 trace that is missing characters does not +generate a corrupted srctrace file. +""" + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir, contents_of, exists +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + +Wdir("tmp_") + +# First produce a source trace from the test program +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], + trace_mode="src", + dump_channel="base64-stdout", +) + +INVALID_TRACE_FILE = "invalid_trace.b64" +SHOULD_NOT_EXIST_TRACE = "SHOULD_NOT_EXIST.srctrace" +STDERR_EXTRACT = "stderr-extract.txt" + +# Then, modify the trace to make it invalid +with open(INVALID_TRACE_FILE, "w") as f: + original = contents_of("main_output.txt") + f.write(original.replace("AAAA", "AAA")) + +# Try extracting the source trace from base64, but should fail. +xcov( + ["extract-base64-trace", INVALID_TRACE_FILE, SHOULD_NOT_EXIST_TRACE], + register_failure=False, + err=STDERR_EXTRACT, +) + +# Ensure the test failed for the good reason. +thistest.fail_if_no_match( + "Test is expected to fail because we are unable to decode base64 " + "characters 4 by 4", + r".*Invalid Base64 trace: incomplete group of 4 characters", + contents_of(STDERR_EXTRACT), +) + +# Ensure the command did not generate an invalid srctrace file. +thistest.fail_if( + exists(SHOULD_NOT_EXIST_TRACE), "shouldn't have created an srctrace file" +) + +thistest.result() diff --git a/testsuite/tests/extract-base64-trace-errors/incomplete-base64/main.adb b/testsuite/tests/extract-base64-trace-errors/incomplete-base64/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/incomplete-base64/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/extract-base64-trace-errors/incomplete-base64/test.py b/testsuite/tests/extract-base64-trace-errors/incomplete-base64/test.py new file mode 100644 index 000000000..46380d19e --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/incomplete-base64/test.py @@ -0,0 +1,54 @@ +""" +Make sure that an invalid truncated base64 trace (missing '== End ==' suffix) +does not generate a corrupted srctrace file. +""" + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir, contents_of, exists +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + +Wdir("tmp_") + +# First produce a source trace from the test program +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], + trace_mode="src", + dump_channel="base64-stdout", +) + +INVALID_TRACE_FILE = "invalid_trace.b64" +SHOULD_NOT_EXIST_TRACE = "SHOULD_NOT_EXIST.srctrace" +STDERR_EXTRACT = "stderr-extract.txt" + +# Then, modify the trace to make it invalid +with open(INVALID_TRACE_FILE, "w") as f: + original = contents_of("main_output.txt") + + truncated_output = original.replace("\n== End ==", "") + + f.write(truncated_output) + +# Try extracting the source trace from base64, but should fail. +xcov( + ["extract-base64-trace", INVALID_TRACE_FILE, SHOULD_NOT_EXIST_TRACE], + register_failure=False, + err=STDERR_EXTRACT, +) + +# Ensure the test failed for the good reason. +thistest.fail_if_no_match( + "Test is expected to fail because the base64 is truncated", + r".*Incomplete Base64 trace", + contents_of(STDERR_EXTRACT), +) + +# Ensure the command did not generate an invalid srctrace file. +thistest.fail_if( + exists(SHOULD_NOT_EXIST_TRACE), "shouldn't have created an srctrace file" +) + +thistest.result() diff --git a/testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/main.adb b/testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/test.py b/testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/test.py new file mode 100644 index 000000000..b46321722 --- /dev/null +++ b/testsuite/tests/extract-base64-trace-errors/unexpected-too-long-line/test.py @@ -0,0 +1,66 @@ +""" +Make sure that a base64 trace that has a line which is too long does not +generate a corrupted srctrace file. +""" + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir, contents_of, exists +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + +Wdir("tmp_") + +# First produce a source trace from the test program +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], + trace_mode="src", + dump_channel="base64-stdout", +) + +INVALID_TRACE_FILE = "invalid_trace.b64" +SHOULD_NOT_EXIST_TRACE = "SHOULD_NOT_EXIST.srctrace" +STDERR_EXTRACT = "stderr-extract.txt" + +# Then, modify the trace to make it invalid +with open(INVALID_TRACE_FILE, "w") as f: + original = contents_of("main_output.txt") + + b64_digest = original.split("== GNATcoverage source trace file ==\n")[ + 1 + ].split("\n== End ==")[0] + + long_line = "AAAA" * 1000 + digest_with_long_line = f"{b64_digest}\n{long_line}" + + new_b64_trace = ( + "== GNATcoverage source trace file ==\n" + f"\n{digest_with_long_line}\n" + "== End ==" + ) + + f.write(new_b64_trace) + +# Try extracting the source trace from base64, but should fail. +xcov( + ["extract-base64-trace", INVALID_TRACE_FILE, SHOULD_NOT_EXIST_TRACE], + register_failure=False, + err=STDERR_EXTRACT, +) + +# Ensure the test failed for the good reason. +thistest.fail_if_no_match( + "Test is expected to fail because a line is too loong to be " + "valid base64 trace", + r".*Unexpected long line in Base64 trace", + contents_of(STDERR_EXTRACT), +) + +# Ensure the command did not generate an invalid srctrace file. +thistest.fail_if( + exists(SHOULD_NOT_EXIST_TRACE), "shouldn't have created an srctrace file" +) + +thistest.result() From 32704ab958370cf559e5b19377c779448fe7167e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 17 Mar 2025 10:21:30 +0100 Subject: [PATCH 1132/1483] Run the doc sources through a spell checker --- doc/gnatcov/bin_limitations.rst | 2 +- doc/gnatcov/cons_traces.rst | 2 +- doc/gnatcov/cov_metrics.rst | 2 +- doc/gnatcov/cov_object.rst | 10 +++++----- doc/gnatcov/cov_source.rst | 16 ++++++++-------- doc/gnatcov/disable_cov.rst | 2 +- doc/gnatcov/exemptions.rst | 2 +- doc/gnatcov/external_annotations.rst | 1 - doc/gnatcov/gpr.rst | 2 +- doc/gnatcov/separate_cov.rst | 2 +- doc/gnatcov/src_traces.rst | 8 ++++---- doc/gnatcov/units_of_interest.rst | 6 +++--- doc/gnattest/gnattest_part.rst | 2 +- doc/integration/integration_part.rst | 6 +++--- 14 files changed, 31 insertions(+), 32 deletions(-) diff --git a/doc/gnatcov/bin_limitations.rst b/doc/gnatcov/bin_limitations.rst index 4365c2cb2..caa3e16d7 100644 --- a/doc/gnatcov/bin_limitations.rst +++ b/doc/gnatcov/bin_limitations.rst @@ -96,7 +96,7 @@ such decisions are statistically rare. |gcv| can report about them on demand, thanks to the :command:`scan-decisions` command together with the the set of coverage obligations to examine. Below is an excerpt of a an execution for a project which encompasses this function, where we see that |gcv| provides the -source location of conditions rechable through multiple paths:: +source location of conditions reachable through multiple paths:: gnatcov scan-decisions -Pmytest.gpr ... diff --git a/doc/gnatcov/cons_traces.rst b/doc/gnatcov/cons_traces.rst index c11e90be1..ce71799dc 100644 --- a/doc/gnatcov/cons_traces.rst +++ b/doc/gnatcov/cons_traces.rst @@ -242,7 +242,7 @@ Multiple executions of a single program ======================================= Consider the example C program below, offering a simple command line interface -to perform very basic math operations. This is splitted in two main source +to perform very basic math operations. This is split in two main source files: ``process.c`` doing the computation and displaying the result, and ``main.c`` for the main entry point and basic usage control: diff --git a/doc/gnatcov/cov_metrics.rst b/doc/gnatcov/cov_metrics.rst index 686929827..9def98075 100644 --- a/doc/gnatcov/cov_metrics.rst +++ b/doc/gnatcov/cov_metrics.rst @@ -172,4 +172,4 @@ assessments of distinct source and object criteria here, actually based on solid theoretical grounds established as part of the *Couverture* research project from which |gcp| originates. The core particularity allowing full branch coverage without mcdc is the presence of decisions with BDDs which -are not trees, as we have in this specfic case, +are not trees, as we have in this specific case, diff --git a/doc/gnatcov/cov_object.rst b/doc/gnatcov/cov_object.rst index f827c00cb..76fe42660 100644 --- a/doc/gnatcov/cov_object.rst +++ b/doc/gnatcov/cov_object.rst @@ -30,7 +30,7 @@ analyzed. The :ref:`bin_traces` chapter of this document provides details on the trace production interface. The remainder of this chapter explains the -use of |gcvcov| in particular, to analyse traces once they have been +use of |gcvcov| in particular, to analyze traces once they have been produced. The general command line structure is always like:: gnatcov coverage --level= --annotate= @@ -118,7 +118,7 @@ coverage indication attached to every single instruction. This is the base information of interest to object coverage analysis, simply presented in different manners through the other possible output formats. The :cmd-option:`xcov` and :cmd-option:`html` formats produce a set of annotated -source files, in the directory where |gcv| is launched unless overriden with a +source files, in the directory where |gcv| is launched unless overridden with a :cmd-option:`--output-dir` option. Even though presented on sources, the annotations remain representative of object coverage metrics, synthesized for all the instructions associated with each source line. @@ -270,7 +270,7 @@ description of the assessment context (assessed criteria, set of trace files involved, ...) and a summary of the coverage results for all the units, with links to their annotated sources. -Similarily to the :cmd-option:`xcov` format case, :cmd-option:`--annotate=html` +Similarly to the :cmd-option:`xcov` format case, :cmd-option:`--annotate=html` attaches to each line details about the coverage status of all the individual instructions generated for the line. These are folded within the line and expanded when a mouse click hits it. @@ -503,8 +503,8 @@ Inlining & Ada Generic units The generated code for an inlined subprogram call or a generic instantiation materializes two distinct source entities: the expanded source (of the inlined -subprogram or of the instanciated generic body) and the expansion request (the -subprogram call or the generic instanciation). While this is of no consequence +subprogram or of the instantiated generic body) and the expansion request (the +subprogram call or the generic instantiation). While this is of no consequence for :cmd-option:`=asm` outputs, which just report coverage of raw machine instructions within their object level subprograms, regardless of the object code origin, this raises a few points of note for in-source outputs. diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index e288b66ba..d0ee1156c 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -71,7 +71,7 @@ The available options are as follows: :cmd-option:`--non-coverable`: Report about language statements for which no object code could be found in - the surrounding suprogram (typically out of optimization). + the surrounding subprogram (typically out of optimization). :cmd-option:`-P`: Use the indicated project file as the root project to select the units of @@ -221,7 +221,7 @@ Later in this chapter we name output formats by the text to add to :cmd-option:`--annotate=report`". We will illustrate the various formats with samples extracted from outputs -obtained by perfoming coverage analysis of the following example Ada +obtained by performing coverage analysis of the following example Ada application unit: .. code-block:: ada @@ -699,7 +699,7 @@ We can observe that: - The inner ``raise`` and ``return`` statements are marked uncovered and covered respectively, as expected since the function was only called with - arguments for which the ``if`` controling decision evaluates False. + arguments for which the ``if`` controlling decision evaluates False. As a second experiment, we exercise the function for Y = 0 only, using: @@ -1052,7 +1052,7 @@ commands. :dfn:`Decisions` in this context are defined as: Then for all the decisions in the sources of interest: * Testing shall exercise both the True and False outcomes of the expression as - a whole and demonstrate the :dfn:`independant influence` of :dfn:`conditions` + a whole and demonstrate the :dfn:`independent influence` of :dfn:`conditions` in |do| parlance, where ... * Separate conditions in a decision are identified as the operands of @@ -1061,7 +1061,7 @@ Then for all the decisions in the sources of interest: Regarding coverage status definitions: * A condition is :dfn:`covered`, and the obligation discharged, when - the independant effect on the enclosing decision was demonstrated by + the independent effect on the enclosing decision was demonstrated by the tests, * A condition is said :dfn:`uncovered` otherwise. @@ -1070,7 +1070,7 @@ The :ref:`mcdc-decisions` section that follows provides a few examples to illustrate the identification of decisions and conditions. :ref:`non-short-circuit` focuses on the handling of computational Boolean operators, then :ref:`mcdc-variants` expands on the notion of -:dfn:`independant influence` and on possible variations of the MCDC criterion +:dfn:`independent influence` and on possible variations of the MCDC criterion definition. Output-wise, the source annotations for the :cmd-option:`=xcov` or @@ -1094,7 +1094,7 @@ absence of other known violations for that same line. The :cmd-option:`=report` outputs feature an extra MCDC section in the Coverage Violations segment, which holds: -- The condition specific diagnosics (``independent influence not +- The condition specific diagnostics (``independent influence not demonstrated``), as well as - Decision level diagnostics (such as ``decision outcome True not covered`` @@ -1269,7 +1269,7 @@ short-circuited: Each line in such a table is called an :term:`evaluation vector `, and the pairs that demonstrate the independant effect of conditions +Vector>`, and the pairs that demonstrate the independent effect of conditions are known as :term:`independence pairs `. Evaluations 1 + 3 constitute a Unique Cause independence pair for A, where A diff --git a/doc/gnatcov/disable_cov.rst b/doc/gnatcov/disable_cov.rst index 5c996ceae..37a5941bd 100644 --- a/doc/gnatcov/disable_cov.rst +++ b/doc/gnatcov/disable_cov.rst @@ -6,7 +6,7 @@ Disable coverage analysis It is possible to fully disable coverage analysis over a specific region. In contrast to exemption regions, gnatcov skips over disabled coverage region and -treats them similarily as a no code region, e.g. with no source coverage +treats them similarly as a no code region, e.g. with no source coverage obligations. Such a mechanism can typically be used to disable coverage for a code region diff --git a/doc/gnatcov/exemptions.rst b/doc/gnatcov/exemptions.rst index 103d5d0e1..478826dfd 100644 --- a/doc/gnatcov/exemptions.rst +++ b/doc/gnatcov/exemptions.rst @@ -118,7 +118,7 @@ regions in the analysis scope. This section lists the exempted regions, displaying for each the source location span, the number of actually exempted violations in the region, the exemption justification text and the observed exempted violations per regions. It also includes a total count of the number -of exempted regions and another for exempted violations accross all sections at +of exempted regions and another for exempted violations across all sections at the end. The corresponding :cmd-option:`=report` excerpt below illustrates this for the diff --git a/doc/gnatcov/external_annotations.rst b/doc/gnatcov/external_annotations.rst index 5dd6359e6..de54af290 100644 --- a/doc/gnatcov/external_annotations.rst +++ b/doc/gnatcov/external_annotations.rst @@ -398,4 +398,3 @@ specifying the annotation identifier to be replaced, and forcing the replacement:: gnatcov add-annotation --annotation-id=IDENTIFIER --force [OPTIONS] - diff --git a/doc/gnatcov/gpr.rst b/doc/gnatcov/gpr.rst index 3b70815f9..4351389f5 100644 --- a/doc/gnatcov/gpr.rst +++ b/doc/gnatcov/gpr.rst @@ -68,7 +68,7 @@ re-written as:: The ``*`` arguments are always inserted first with respect to the final command line interpretation. In the example above, ``--level`` from the ``*`` -list cumulates before ``--annotate`` for |gcvcov|. Similarily, switches from +list cumulates before ``--annotate`` for |gcvcov|. Similarly, switches from the project file are always processed as if appearing before the others on the command line. diff --git a/doc/gnatcov/separate_cov.rst b/doc/gnatcov/separate_cov.rst index 6276c8d2d..e36839204 100644 --- a/doc/gnatcov/separate_cov.rst +++ b/doc/gnatcov/separate_cov.rst @@ -46,7 +46,7 @@ We do observe violations on the ``Vops`` generic body, fully covered without two generic instances separately, each designated by a ``(from )`` indication. -|gcv| needs to see the coverage obligations correponding to each instance in +|gcv| needs to see the coverage obligations corresponding to each instance in this mode. This is achieved transparently by the use of a project file in the example command lines we quoted and needs particular care when the Library Information files are provided manually with :cmd-option:`--scos` instead. diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 458b04578..337b9ef37 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -805,7 +805,7 @@ And to instrument Ada, C and C++ units: Instrumentation and coverage of SPARK code ========================================== -The instrumentation of a SPARK project requires an additionnal step in order +The instrumentation of a SPARK project requires an additional step in order to make the compiler accept the instrumented code. Additionally, some parts of SPARK sources are not processed by the instrumenter, and thus will not have any coverage obligation attached to them. @@ -813,8 +813,8 @@ any coverage obligation attached to them. Inhibiting SPARK related pragmas --------------------------------- -SPARK introduces a certain number of pragmas and aspects to aid the developper -in writting program contracts and guiding the automatic provers. These are only +SPARK introduces a certain number of pragmas and aspects to aid the developer +in writing program contracts and guiding the automatic provers. These are only useful for static proof purposes, and are not used when assessing the coverage of a project during testing. As such, the instrumenter ignores those pragmas/aspects, and the compiler must be instructed to disregard them when @@ -880,7 +880,7 @@ compiled, and are mainly used to aid the proof of the program. Computing coverage for such source regions isn't meaningful and are thus ignored by the instrumenter. This means that those regions will not have any coverage obligation attached to them in the coverage reports, unless -explicity requested by enabling the coverage of assertions. +explicitly requested by enabling the coverage of assertions. The concerned pieces of code are notably: diff --git a/doc/gnatcov/units_of_interest.rst b/doc/gnatcov/units_of_interest.rst index e62efef43..fb3e00772 100644 --- a/doc/gnatcov/units_of_interest.rst +++ b/doc/gnatcov/units_of_interest.rst @@ -187,7 +187,7 @@ considered of interest within a project are as follows: attributes are removed from the initial set to yield the set to consider. Finally, the list of units of interest for a given execution of |gcv| can also -be overriden from the command line using the :cmd-option:`--units` switch. +be overridden from the command line using the :cmd-option:`--units` switch. When this option is used, the project files attributes are ignored. The switch may appear multiple times. Each occurrence indicates one @@ -251,7 +251,7 @@ as the ``-X`` series setting scenarii variables. In some cases, such as ``--target`` or ``--RTS``, the effect of the command line switch can be achieved with a project file attribute, which |gcp| knows -how to interepret as well. +how to interpret as well. .. _ignore_source_files: @@ -411,7 +411,7 @@ attributes or :cmd-option:`--units` arguments to elaborate the set of This offers a simple and consistent naming basis to users, orthogonal to the unit/source name mapping. Consider, for example, a project file with the set -of declarations below, which parameterizes the source file name to use for the +of declarations below, which parametrizes the source file name to use for the body of a ``Logger`` package depending on the kind of build performed:: type Build_Mode_Type is ("Production", "Debug"); diff --git a/doc/gnattest/gnattest_part.rst b/doc/gnattest/gnattest_part.rst index bfa9d1a39..4b099d7f9 100644 --- a/doc/gnattest/gnattest_part.rst +++ b/doc/gnattest/gnattest_part.rst @@ -390,7 +390,7 @@ Switches for ``gnattest`` in framework generation mode :switch:`--reporter={val}` Use specified reporter in the test driver. ``val`` is expected to be a name of child package of AUnit.Reporter. Test drivers generated with non-default - reporter specified cannot be properly processd by test execution mode of ``gnattest``. + reporter specified cannot be properly processed by test execution mode of ``gnattest``. :switch:`--tests-root`, :switch:`--subdirs` and :switch:`--tests-dir` switches are mutually exclusive. diff --git a/doc/integration/integration_part.rst b/doc/integration/integration_part.rst index 99aee92fe..be5f87335 100644 --- a/doc/integration/integration_part.rst +++ b/doc/integration/integration_part.rst @@ -34,7 +34,7 @@ consists of two files: The makefile also assumes that the |gcp| runtime is already built and installed, and that the path to its project file is in the environment variable -``GPR_PROJECT_PATH`` so it can be automaticaly located by GPRbuild. +``GPR_PROJECT_PATH`` so it can be automatically located by GPRbuild. It is also possible to specify the path to the project file in the ``GNATCOV_RTS`` variable in the ``coverage_settings.mk`` file. See :ref:`instr-rts` for instructions on building and installing the runtime. @@ -74,7 +74,7 @@ the ``Board`` attribute in the package ``Emulator`` needs to be specified in the root project file, or alternatively the ``GNATEMU_BOARD`` variable must be set in the ``coverage_settings.mk`` secondary makefile. -For source traces, the instrumented program will be run using GNATemuator +For source traces, the instrumented program will be run using GNATemulator directly, and assumes that the standard package Ada.GNAT_IO allows data to be output on a serial port. The instrumentation process overrides the two switches :cmd-option:`--dump-trigger` and :cmd-option:`--dump-channel` to the values @@ -291,7 +291,7 @@ example, this would be like: ** END OF REPORT ** The log shows all the steps necessary to obtain coverage results from the -mutliple test drivers, and end with the report. +multiple test drivers, and end with the report. From the coverage report, we see that the only lines not covered are in ``pkg1.adb``, which is expected as the tests corresponding to that unit are From 4899157801583bbd2c959d72cfbe08a26c9d42e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 5 Mar 2025 13:58:37 +0100 Subject: [PATCH 1133/1483] Instrument.C: Do not output clang diagnostics as warnings We currently do not have a good heuristic to determine when a parsing diagnostic emitted by libclang is actually a concern, so diagnostics are suppressed by default. Until now, they were emitted as warnings, only if verbose logging was activated, and contained the severity of the diagnostic text (e.g. error or fatal error), which could be confusing for the user, as it lead to believe there is an error when it is most often not the case. The diagnostic emmission mechanism has been reworked to clarify that the messages are not generated by gnatcov directly, and the severity has been removed. No behavior change expected. --- tools/gnatcov/instrument-c.adb | 26 +++++++++++++++++++------- tools/gnatcov/instrument-c.ads | 6 ++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index b1364942e..eccc3b27a 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2085,15 +2085,27 @@ package body Instrument.C is Get_Diagnostic (Unit => TU, Index => I - 1); Severity : constant Diagnostic_Severity_T := Get_Diagnostic_Severity (Diag); - Str : constant String := - Format_Diagnostic - (Diagnostic => Diag, - Options => Default_Diagnostic_Display_Options); + begin case Severity is when Diagnostic_Error | Diagnostic_Fatal => - Outputs.Warning_Or_Error - ("Error when parsing the file " & Str); + + -- Do not log the current location / entity in the gnatcov + -- executable, the diagnostic string generated by clang + -- already contains all the required information. + -- + -- Do not also use the clang formatting to print the + -- diagnostics as they would contain either "error" or + -- "fatal error", which could trick users into thinking + -- there actually is an error whereas instrumentation was + -- most likely successful. + + Clang_Trace.Trace + (Message => + Image (Sloc (Get_Diagnostic_Location (Diag))) + & ": " & Get_Diagnostic_Spelling (Diag), + Location => "", + Entity => ""); when others => null; end case; @@ -3144,7 +3156,7 @@ package body Instrument.C is & " options is passed to gnatcov instrument"); raise Xcov_Exit_Exc; end if; - if Misc_Trace.Is_Active then + if Clang_Trace.Is_Active then Run_Diagnostics (Self.TU); end if; Free (C_Args); diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index d288d1fc2..79761e8fe 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -35,10 +35,16 @@ with Files_Handling; use Files_Handling; with Files_Table; use Files_Table; with Instrument.C_Utils; use Instrument.C_Utils; with Instrument.Common; use Instrument.Common; +with Logging; with Slocs; use Slocs; package Instrument.C is + Clang_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("CLANG_DIAGNOSTICS"); + -- Trace meant to output diagnostics emitted by clang, for which we don't + -- necessarily want to generate a warning / error. + type C_Family_Instrumenter_Type is abstract new Language_Instrumenter with record From dd46d2405068eca947dc61efd99897295da22483 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 17 Mar 2025 15:56:07 +0100 Subject: [PATCH 1134/1483] Fix help message for -X For consistency with other tools. --- tools/gnatcov/command_line.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 00655c215..deb5bb9f2 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -1395,7 +1395,7 @@ package Command_Line is Opt_Scenario_Var => Create (Short_Name => "-X", Pattern => "[NAME]=[VALUE]", - Help => "Define a scenario variable for project files.", + Help => "Specify an external reference for Project Files.", Commands => (Cmd_Print_GPR_Registry | Cmd_All_Setups => False, others => True), From 1c7d941cd5ce862631acbd1945babb3c1d848d68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 6 Mar 2025 15:19:35 +0100 Subject: [PATCH 1135/1483] Doc: Adapt makefile in the documentation examples for src-traces --- doc/gnatcov/examples/Makefile | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/doc/gnatcov/examples/Makefile b/doc/gnatcov/examples/Makefile index 2c322e407..f608639af 100644 --- a/doc/gnatcov/examples/Makefile +++ b/doc/gnatcov/examples/Makefile @@ -1,12 +1,9 @@ -TARGET=powerpc-elf -RTS=zfp-prep - XCOVLEVEL=stmt ANNOTATE=xcov # unit test name and gpr file -UT= +UT= #test_... GPR=ut.gpr TDIR=_$(UT:test_%=%) OSUBDIR=obj @@ -20,14 +17,12 @@ build: @echo ' for Source_Dirs use ("../src");' >> $(GPR) @echo ' for Object_Dir use "$(OSUBDIR)";' >> $(GPR) @echo 'end UT;' >> $(GPR) - gprbuild -p -f --target=$(TARGET) --RTS=$(TARGET)/$(RTS) -P$(GPR) $(UT).adb \ - -cargs:Ada -gnateS -gnaty -gnatwe -cargs -g -fpreserve-control-flow \ - -bargs -A=$(UT).alis + gnatcov instrument -P$(GPR) --level=$(XCOVLEVEL) --dump-filename-simple \ + --units=$(UT) $(UT).adb + gprbuild -p -f -P$(GPR) $(UT).adb --src-subdirs=gnatcov-instr \ + --implicit-with=gnatcov_rts.gpr run: - gnatcov run $(OSUBDIR)/$(UT) - grep -v xxsupport.ali $(OSUBDIR)/$(UT).alis > alis - gnatcov coverage --level=$(XCOVLEVEL) --scos=@alis \ - --annotate=$(ANNOTATE) $(UT).trace - - + $(OSUBDIR)/$(UT) + gnatcov coverage --level=$(XCOVLEVEL) -P$(GPR) \ + --annotate=$(ANNOTATE) --units=$(UT) $(UT).srctrace From a0378edafe5de472ce12fa0330d614c3e0939933 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 7 Mar 2025 13:26:46 +0100 Subject: [PATCH 1136/1483] Move examples for Getting Started section to the distributed examples dir --- doc/gnatcov/examples/starter/ops.gpr | 5 --- doc/gnatcov/getting_started.rst | 4 +++ tools/gnatcov/examples/README.md | 15 ++++++--- tools/gnatcov/examples/doc/README.examples | 22 +++++++++++++ .../examples/doc/getting_started/Makefile | 32 +++++++++++++++++++ .../examples/doc/getting_started/code.gpr | 4 +++ .../doc/getting_started/opslib}/ops.adb | 2 +- .../doc/getting_started/opslib}/ops.ads | 2 +- .../examples/doc/getting_started/tests.gpr | 8 +++++ .../doc/getting_started/tests}/test_inc.adb | 2 +- .../gnatcov/examples/support/Makefile.common | 2 +- 11 files changed, 84 insertions(+), 14 deletions(-) delete mode 100644 doc/gnatcov/examples/starter/ops.gpr create mode 100644 tools/gnatcov/examples/doc/README.examples create mode 100644 tools/gnatcov/examples/doc/getting_started/Makefile create mode 100644 tools/gnatcov/examples/doc/getting_started/code.gpr rename {doc/gnatcov/examples/starter/src => tools/gnatcov/examples/doc/getting_started/opslib}/ops.adb (88%) rename {doc/gnatcov/examples/starter/src => tools/gnatcov/examples/doc/getting_started/opslib}/ops.ads (85%) create mode 100644 tools/gnatcov/examples/doc/getting_started/tests.gpr rename {doc/gnatcov/examples/starter/src => tools/gnatcov/examples/doc/getting_started/tests}/test_inc.adb (85%) diff --git a/doc/gnatcov/examples/starter/ops.gpr b/doc/gnatcov/examples/starter/ops.gpr deleted file mode 100644 index e6f28e704..000000000 --- a/doc/gnatcov/examples/starter/ops.gpr +++ /dev/null @@ -1,5 +0,0 @@ -project Ops is - for Languages use ("Ada"); - for Source_Dirs use ("src"); - for Object_Dir use "obj"; -end Ops; diff --git a/doc/gnatcov/getting_started.rst b/doc/gnatcov/getting_started.rst index 3ba70ad10..f36c2ee99 100644 --- a/doc/gnatcov/getting_started.rst +++ b/doc/gnatcov/getting_started.rst @@ -114,6 +114,10 @@ time. Sample project -------------- +The sources for this examples are provided under the +`share/examples/gnatcoverage/doc/getting_started/` directory of the GNATDAS +distribution. + We consider an Ada package providing a set of elementary operations over ``Integer`` objects, with a spec and body in source files named ``ops.ads`` and ``ops.adb``: diff --git a/tools/gnatcov/examples/README.md b/tools/gnatcov/examples/README.md index 6675a4da8..fbcab8dd8 100644 --- a/tools/gnatcov/examples/README.md +++ b/tools/gnatcov/examples/README.md @@ -1,10 +1,15 @@ This directory contains a few examples illustrating possible ways to build, run and do coverage analysis with GNAT Pro and GNATcoverage -Except `support`, each subdirectory hosts an example and features a Makefile -that allows launching a complete build/run/analyze sequence for a variety of -targets, assuming you have the corresponding GNAT & GNATemulator products -installed. +Except `support` and `doc`, each subdirectory hosts an example and features a +Makefile that allows launching a complete build/run/analyze sequence for a +variety of targets, assuming you have the corresponding GNAT & GNATemulator +products installed. + +The `doc` subdirectory holds the sources used in the various examples in the +user's manual. Each one also features a Makefile that replicates the commands +demonstrated in the user's manual relevant section. These examples only work +for native targets. The `support` subdirectory is common to all the other ones, and additional information about the general Makefile and project files structure is available @@ -16,7 +21,7 @@ to use by setting the `TARGET` and `RTS` variables explicitly: ```shell make TARGET=powerpc-elf RTS=light-mpc8641 runs on bare PowerPC -make TARGET=leon3-elf RTS=light-leon3 runs on bare LEON2 +make TARGET=leon3-elf RTS=light-leon3 runs on bare LEON3 ``` as well as: diff --git a/tools/gnatcov/examples/doc/README.examples b/tools/gnatcov/examples/doc/README.examples new file mode 100644 index 000000000..3566e9e58 --- /dev/null +++ b/tools/gnatcov/examples/doc/README.examples @@ -0,0 +1,22 @@ +Documentation examples +---------------------- + +This directory contains the sources of the examples used throughout the +GNATcoverage user's manual, Each directory contains the sources and project for +a single example, as well as a Makefile that reproduces (in a linux or cygwin +environment) the commands described in the relevant documentation section. + +The Makefiles start with a comment briefly describing the example, the +demonstrated feature, and referencing the corresponding section in the user's +manual. It is best to go through these examples by following the indications +in the user's manual, as they will be much more detailed, and may provide +additional context. + +When a section name is referenced, either in this document, or in the Makefile +comments, this is always a section within the GNATcoverage manual, which is +itself a subset of the GNATDAS user's manual. + + +- getting_started: A simple project on which the general GNATcoverage workflow +is demonstrated. See section "Getting Started" of the manual for more +information. diff --git a/tools/gnatcov/examples/doc/getting_started/Makefile b/tools/gnatcov/examples/doc/getting_started/Makefile new file mode 100644 index 000000000..c74c3572b --- /dev/null +++ b/tools/gnatcov/examples/doc/getting_started/Makefile @@ -0,0 +1,32 @@ +# Simple project demonstrating the usual GNATcoverage workflow. +# See section "Getting Started" in GNATcoverage's user manual for more +# details. + +RTS_DIR = rts_install + +.PHONY: instrument build run coverage + +default: coverage + +# Only needs to be called once, can be re-used across multiple GNATcov workflows +$(RTS_DIR)/share/gpr/gnatcov_rts.gpr: + gnatcov setup --prefix=$(RTS_DIR) + +instrument: export GPR_PROJECT_PATH := $(shell pwd)/$(RTS_DIR)/share/gpr:$(GPR_PROJECT_PATH) +instrument: $(RTS_DIR)/share/gpr/gnatcov_rts.gpr + @echo 'export GPR_PROJECT_PATH=$$(pwd)/$(RTS_DIR)/share/gpr:$$GPR_PROJECT_PATH' + gnatcov instrument -P tests.gpr --level=stmt + +build: export GPR_PROJECT_PATH := $(shell pwd)/$(RTS_DIR)/share/gpr:$(GPR_PROJECT_PATH) +build: instrument + gprbuild -f -p -P tests.gpr --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts.gpr + +run: build + ./obj-tests/test_inc + +coverage: run + gnatcov coverage -P tests.gpr --level=stmt --annotate=xcov test_inc*.srctrace + cat obj-tests/ops.adb.xcov + +clean: + rm -rf obj-* $(RTS_DIR) test_inc*.srctrace diff --git a/tools/gnatcov/examples/doc/getting_started/code.gpr b/tools/gnatcov/examples/doc/getting_started/code.gpr new file mode 100644 index 000000000..d3bd3ea43 --- /dev/null +++ b/tools/gnatcov/examples/doc/getting_started/code.gpr @@ -0,0 +1,4 @@ +project Code is + for Source_Dirs use ("opslib"); + for Object_Dir use "obj-" & Project'Name; +end Code; diff --git a/doc/gnatcov/examples/starter/src/ops.adb b/tools/gnatcov/examples/doc/getting_started/opslib/ops.adb similarity index 88% rename from doc/gnatcov/examples/starter/src/ops.adb rename to tools/gnatcov/examples/doc/getting_started/opslib/ops.adb index 74f5f6b9a..54f54cc96 100644 --- a/doc/gnatcov/examples/starter/src/ops.adb +++ b/tools/gnatcov/examples/doc/getting_started/opslib/ops.adb @@ -1,6 +1,6 @@ ------------------------------------------------------------------------------ -- GNATcoverage -- --- Copyright (C) 2012-2021, AdaCore -- +-- Copyright (C) 2012-2025, AdaCore -- ------------------------------------------------------------------------------ package body Ops is diff --git a/doc/gnatcov/examples/starter/src/ops.ads b/tools/gnatcov/examples/doc/getting_started/opslib/ops.ads similarity index 85% rename from doc/gnatcov/examples/starter/src/ops.ads rename to tools/gnatcov/examples/doc/getting_started/opslib/ops.ads index 104eaf65a..eb6b58932 100644 --- a/doc/gnatcov/examples/starter/src/ops.ads +++ b/tools/gnatcov/examples/doc/getting_started/opslib/ops.ads @@ -1,6 +1,6 @@ ------------------------------------------------------------------------------ -- GNATcoverage -- --- Copyright (C) 2012-2021, AdaCore -- +-- Copyright (C) 2012-2025, AdaCore -- ------------------------------------------------------------------------------ package Ops is diff --git a/tools/gnatcov/examples/doc/getting_started/tests.gpr b/tools/gnatcov/examples/doc/getting_started/tests.gpr new file mode 100644 index 000000000..0976dc7ce --- /dev/null +++ b/tools/gnatcov/examples/doc/getting_started/tests.gpr @@ -0,0 +1,8 @@ +with "code.gpr"; + +project Tests is + for Source_Dirs use ("tests"); + for Object_Dir use "obj-" & Project'Name; + + for Main use ("test_inc.adb"); +end Tests; diff --git a/doc/gnatcov/examples/starter/src/test_inc.adb b/tools/gnatcov/examples/doc/getting_started/tests/test_inc.adb similarity index 85% rename from doc/gnatcov/examples/starter/src/test_inc.adb rename to tools/gnatcov/examples/doc/getting_started/tests/test_inc.adb index cd4a45acd..f16fe3572 100644 --- a/doc/gnatcov/examples/starter/src/test_inc.adb +++ b/tools/gnatcov/examples/doc/getting_started/tests/test_inc.adb @@ -1,6 +1,6 @@ ------------------------------------------------------------------------------ -- GNATcoverage -- --- Copyright (C) 2012-2021, AdaCore -- +-- Copyright (C) 2012-2025, AdaCore -- ------------------------------------------------------------------------------ with Ops; diff --git a/tools/gnatcov/examples/support/Makefile.common b/tools/gnatcov/examples/support/Makefile.common index 99f498270..11b6dc1f3 100644 --- a/tools/gnatcov/examples/support/Makefile.common +++ b/tools/gnatcov/examples/support/Makefile.common @@ -14,7 +14,7 @@ TARGET = BOARD = # ========================================================== -# What --target will we pass to XCOV run +# What --target will we pass to gnatcov # ========================================================== # gnatcov doesn't support a separate notion of board vs From 5b479ea51483b78d8141cc977974e796ff215a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 7 Mar 2025 15:13:52 +0100 Subject: [PATCH 1137/1483] Add sources for the example concerning handling of subunits --- doc/gnatcov/units_of_interest.rst | 29 +++++++++------ tools/gnatcov/examples/doc/subunits/Makefile | 36 +++++++++++++++++++ .../examples/doc/subunits/ignore-list.txt | 2 ++ tools/gnatcov/examples/doc/subunits/p.gpr | 16 +++++++++ .../subunits/src/data_processing-test1.adb | 13 +++++++ .../subunits/src/data_processing-test2.adb | 13 +++++++ .../doc/subunits/src/data_processing.adb | 20 +++++++++++ .../doc/subunits/src/data_processing.ads | 12 +++++++ .../examples/doc/subunits/src/run_all.adb | 10 ++++++ 9 files changed, 141 insertions(+), 10 deletions(-) create mode 100644 tools/gnatcov/examples/doc/subunits/Makefile create mode 100644 tools/gnatcov/examples/doc/subunits/ignore-list.txt create mode 100644 tools/gnatcov/examples/doc/subunits/p.gpr create mode 100644 tools/gnatcov/examples/doc/subunits/src/data_processing-test1.adb create mode 100644 tools/gnatcov/examples/doc/subunits/src/data_processing-test2.adb create mode 100644 tools/gnatcov/examples/doc/subunits/src/data_processing.adb create mode 100644 tools/gnatcov/examples/doc/subunits/src/data_processing.ads create mode 100644 tools/gnatcov/examples/doc/subunits/src/run_all.adb diff --git a/doc/gnatcov/units_of_interest.rst b/doc/gnatcov/units_of_interest.rst index fb3e00772..73884648a 100644 --- a/doc/gnatcov/units_of_interest.rst +++ b/doc/gnatcov/units_of_interest.rst @@ -266,6 +266,10 @@ unit of interest encompass some of its testing sources, for example when parts of the testing code is implemented with ``separate`` subunits in Ada. +The sources for the following example can be found under the +`share/examples/gnatcoverage/doc/subunits/` directory of the GNATDAS +distribution. + The dummy example below shows a possible organization of this kind, with a ``Data_Processing`` package to be tested which contains a ``Test`` procedure declared as a ``separate`` entity:: @@ -312,10 +316,23 @@ one or the other based on a scenario variable:: pragma Assert (Internal_Data < 0); end; + -- run_all.adb; main file to run the test + + with Data_Processing; + procedure Run_All is + begin + Data_Processing.Test; + end; + -- Project file with a Body source file name selection in a -- Naming project package: project P is + + for Object_Dir use "obj"; + for Source_Dirs use ("src"); + for Main use ("run_all.adb"); + TEST := external ("TEST"); package Naming is for Body ("data_processing.test") use "data_processing-" & TEST & ".adb"; @@ -324,16 +341,8 @@ one or the other based on a scenario variable:: Then we can build one variant or the other with:: - -- run_all.adb - - with Data_Processing; - procedure Run_All is - begin - Data_Processing.Test; - end; - - $ gprbuild -Pp.gpr -XTEST=test1 run_all.adb - $ gprbuild -Pp.gpr -XTEST=test2 run_all.adb + $ gprbuild -Pp.gpr -XTEST=test1 + $ gprbuild -Pp.gpr -XTEST=test2 ... As any testing code, such subunits usually need to be excluded from diff --git a/tools/gnatcov/examples/doc/subunits/Makefile b/tools/gnatcov/examples/doc/subunits/Makefile new file mode 100644 index 000000000..cf9f83e8d --- /dev/null +++ b/tools/gnatcov/examples/doc/subunits/Makefile @@ -0,0 +1,36 @@ +# This example showcases how to exclude testing subunits (a.k.a. separates) +# from coverage analysis, to be able to combine the coverage on a single unit, +# of multiple test subprograms. +# +# More information is available in section +# "Conveying source files to ignore / handling Ada subunits" in the +# GNATcoverage user's manual. + +RTS_DIR = rts_install + +default: coverage + +# Only needs to be called once, can be re-used across multiple GNATcov workflows +$(RTS_DIR)/share/gpr/gnatcov_rts.gpr: + gnatcov setup --prefix=$(RTS_DIR) + +instrument-%: export GPR_PROJECT_PATH := $(shell pwd)/$(RTS_DIR)/share/gpr:$(GPR_PROJECT_PATH) +instrument-%: $(RTS_DIR)/share/gpr/gnatcov_rts.gpr + @echo 'export GPR_PROJECT_PATH=$$(pwd)/$(RTS_DIR)/share/gpr:$$GPR_PROJECT_PATH' + gnatcov instrument -P p.gpr --level=stmt+decision -XTEST="$*" \ + --ignore-source-files=@ignore-list.txt + +build-%: export GPR_PROJECT_PATH := $(shell pwd)/$(RTS_DIR)/share/gpr:$(GPR_PROJECT_PATH) +build-%: instrument-% + gprbuild -f -p -P p.gpr --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts.gpr -XTEST="$*" + +run-%: build-% + GNATCOV_TRACE_FILE=$*.srctrace ./obj/run_all + +coverage: run-test1 run-test2 + gnatcov coverage -P p.gpr --level=stmt+decision --annotate=xcov \ + -XTEST="test1" --units=data_processing test1.srctrace test2.srctrace + cat obj/data_processing.adb.xcov + +clean: + rm -rf obj/ $(RTS_DIR) *.srctrace diff --git a/tools/gnatcov/examples/doc/subunits/ignore-list.txt b/tools/gnatcov/examples/doc/subunits/ignore-list.txt new file mode 100644 index 000000000..2286fc977 --- /dev/null +++ b/tools/gnatcov/examples/doc/subunits/ignore-list.txt @@ -0,0 +1,2 @@ +*-test*.adb +run_all.adb diff --git a/tools/gnatcov/examples/doc/subunits/p.gpr b/tools/gnatcov/examples/doc/subunits/p.gpr new file mode 100644 index 000000000..591de1dc8 --- /dev/null +++ b/tools/gnatcov/examples/doc/subunits/p.gpr @@ -0,0 +1,16 @@ +-- Project file with a Body source file name selection in a +-- Naming project package: + +project P is + + for Object_Dir use "obj"; + for Source_Dirs use ("src"); + for Main use ("run_all.adb"); + + TEST := external ("TEST"); + + package Naming is + for Body ("data_processing.test") use "data_processing-" & TEST & ".adb"; + end Naming; + +end P; diff --git a/tools/gnatcov/examples/doc/subunits/src/data_processing-test1.adb b/tools/gnatcov/examples/doc/subunits/src/data_processing-test1.adb new file mode 100644 index 000000000..ca8f7bfa8 --- /dev/null +++ b/tools/gnatcov/examples/doc/subunits/src/data_processing-test1.adb @@ -0,0 +1,13 @@ +------------------------------------------------------------------------------ +-- GNATcoverage -- +-- Copyright (C) 2012-2025, AdaCore -- +------------------------------------------------------------------------------ + +-- data_processing-test1.adb; test variation #1 + +separate (Data_Processing) +procedure Test is +begin + Process (X => 12); + pragma Assert (Internal_Data > 0); +end; diff --git a/tools/gnatcov/examples/doc/subunits/src/data_processing-test2.adb b/tools/gnatcov/examples/doc/subunits/src/data_processing-test2.adb new file mode 100644 index 000000000..1800a8f3a --- /dev/null +++ b/tools/gnatcov/examples/doc/subunits/src/data_processing-test2.adb @@ -0,0 +1,13 @@ +------------------------------------------------------------------------------ +-- GNATcoverage -- +-- Copyright (C) 2012-2025, AdaCore -- +------------------------------------------------------------------------------ + +-- data_processing-test2.adb; test variation #2 + +separate (Data_Processing) +procedure Test is +begin + Process (X => -8); + pragma Assert (Internal_Data < 0); +end; diff --git a/tools/gnatcov/examples/doc/subunits/src/data_processing.adb b/tools/gnatcov/examples/doc/subunits/src/data_processing.adb new file mode 100644 index 000000000..739803881 --- /dev/null +++ b/tools/gnatcov/examples/doc/subunits/src/data_processing.adb @@ -0,0 +1,20 @@ +------------------------------------------------------------------------------ +-- GNATcoverage -- +-- Copyright (C) 2012-2025, AdaCore -- +------------------------------------------------------------------------------ + +package body Data_Processing is + + Internal_Data : Integer := 0; + + procedure Process (X : Integer) is + begin + if X < 0 then + Internal_Data := -1; + else + Internal_Data := 1; + end if; + end; + + procedure Test is separate; -- subunit declaration here +end; diff --git a/tools/gnatcov/examples/doc/subunits/src/data_processing.ads b/tools/gnatcov/examples/doc/subunits/src/data_processing.ads new file mode 100644 index 000000000..26a6b904d --- /dev/null +++ b/tools/gnatcov/examples/doc/subunits/src/data_processing.ads @@ -0,0 +1,12 @@ +------------------------------------------------------------------------------ +-- GNATcoverage -- +-- Copyright (C) 2012-2025, AdaCore -- +------------------------------------------------------------------------------ + +-- Simple unit that embeds a test procedure stub + +package Data_Processing is + procedure Process (X : Integer); + + procedure Test; +end; diff --git a/tools/gnatcov/examples/doc/subunits/src/run_all.adb b/tools/gnatcov/examples/doc/subunits/src/run_all.adb new file mode 100644 index 000000000..20cf557e6 --- /dev/null +++ b/tools/gnatcov/examples/doc/subunits/src/run_all.adb @@ -0,0 +1,10 @@ +------------------------------------------------------------------------------ +-- GNATcoverage -- +-- Copyright (C) 2012-2025, AdaCore -- +------------------------------------------------------------------------------ + +with Data_Processing; +procedure Run_All is +begin + Data_Processing.Test; +end; From 2ed411d3aa5ad927b51df0275ec0897956fd2d62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 7 Mar 2025 15:23:04 +0100 Subject: [PATCH 1138/1483] Doc: Mention source location for spark insturmentation example --- doc/gnatcov/src_traces.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 337b9ef37..a3a716e3e 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -844,6 +844,10 @@ Its contents are: pragma Ignore_Pragma (Refined_Global); pragma Ignore_Pragma (Refined_Depends); +The source for the following example can be found under the +`share/examples/gnatcoverage/spark_instrumentation/` directory of the GNATDAS +distribution. + The configuration pragma file can be passed to the compiler either by specifying it on the gprbuild command line with the ``-gnatec`` switch:: From ea4137c887de036ec4f4f2ccefd07c2d350bf8ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 10 Mar 2025 12:31:56 +0100 Subject: [PATCH 1139/1483] Add sources for cross-example in source-traces section --- doc/gnatcov/src_traces.rst | 4 ++ .../examples/doc/cross_example/Makefile | 55 +++++++++++++++++++ .../examples/doc/cross_example/monitor.gpr | 5 ++ .../doc/cross_example/src/monitor.adb | 21 +++++++ .../doc/cross_example/src/sensors.adb | 20 +++++++ .../doc/cross_example/src/sensors.ads | 12 ++++ 6 files changed, 117 insertions(+) create mode 100644 tools/gnatcov/examples/doc/cross_example/Makefile create mode 100644 tools/gnatcov/examples/doc/cross_example/monitor.gpr create mode 100644 tools/gnatcov/examples/doc/cross_example/src/monitor.adb create mode 100644 tools/gnatcov/examples/doc/cross_example/src/sensors.adb create mode 100644 tools/gnatcov/examples/doc/cross_example/src/sensors.ads diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index a3a716e3e..93e51f470 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -912,6 +912,10 @@ Here we will consider examining the coverage achieved by the execution of the very basic sample program below, assuming the existence of a ``Sensors`` source unit providing access to some sensor values. +The sources for this example can be found under the +`share/examples/gnatcoverage/doc/cross_example` directory of the GNATDAS +disctribution. + .. code-block:: ada with Sensors; use Sensors; diff --git a/tools/gnatcov/examples/doc/cross_example/Makefile b/tools/gnatcov/examples/doc/cross_example/Makefile new file mode 100644 index 000000000..f34ae4aca --- /dev/null +++ b/tools/gnatcov/examples/doc/cross_example/Makefile @@ -0,0 +1,55 @@ +# Example demonstrating how to instrument a project for a cross configuration, +# with a restricted runtime. By default the example runs on a native target, as +# the binary execution step differs for each target. + +RTS?=light +TARGET?= + +# target & runtime options to be passed to all gnatcov & gprbuild commands +GPR_ARGS= + +ifneq ($(TARGET),) +GPR_ARGS = --target=$(TARGET) +endif + +ifneq ($(RTS),) +GPR_ARGS := $(GPR_ARGS) --RTS=$(RTS) +endif + +RTS_DIR = rts_install + +.PHONY: instrument build run coverage + +default: coverage + +# Only needs to be called once, can be re-used across multiple GNATcov workflows +$(RTS_DIR)/share/gpr/gnatcov_rts.gpr: + gnatcov setup $(GPR_ARGS) --prefix=$(RTS_DIR) + +insturment: export GPR_PROJECT_PATH := $(shell pwd)/$(RTS_DIR)/share/gpr:$(GPR_PROJECT_PATH) +instrument: $(RTS_DIR)/share/gpr/gnatcov_rts.gpr + @echo 'export GPR_PROJECT_PATH=$$(pwd)/$(RTS_DIR)/share/gpr:$$GPR_PROJECT_PATH' + gnatcov instrument -P monitor.gpr $(GPR_ARGS) --level=stmt+decision \ + --dump-channel=base64-stdout --dump-trigger=main-end + +build: export GPR_PROJECT_PATH := $(shell pwd)/$(RTS_DIR)/share/gpr:$(GPR_PROJECT_PATH) +build: instrument + gprbuild -f -p -P monitor.gpr $(GPR_ARGS) --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts.gpr + +ifeq ($(TARGET),) +run: build + ./obj/monitor > monitor.stdout + @cat monitor.stdout +else +run: build + @echo I don't know how to execute a binary for $(TARGET), please modify line 40 of the Makefile,\n\ + the output of the program should be captured in the monitor.stdout file. && false +endif + +coverage: run + gnatcov extract-base64-trace monitor.stdout monitor.srctrace + gnatcov coverage -P monitor.gpr $(GPR_ARGS) --level=stmt+decision --annotate=xcov monitor.srctrace + cat obj/monitor.adb.xcov + +clean: + rm -rf obj $(RTS_DIR) monitor.srctrace monitor.stdout diff --git a/tools/gnatcov/examples/doc/cross_example/monitor.gpr b/tools/gnatcov/examples/doc/cross_example/monitor.gpr new file mode 100644 index 000000000..9f0b09e3b --- /dev/null +++ b/tools/gnatcov/examples/doc/cross_example/monitor.gpr @@ -0,0 +1,5 @@ +project Monitor is + for Object_Dir use "obj"; + for Source_Dirs use ("src"); + for Main use ("monitor.adb"); +end Monitor; diff --git a/tools/gnatcov/examples/doc/cross_example/src/monitor.adb b/tools/gnatcov/examples/doc/cross_example/src/monitor.adb new file mode 100644 index 000000000..e6f1ea428 --- /dev/null +++ b/tools/gnatcov/examples/doc/cross_example/src/monitor.adb @@ -0,0 +1,21 @@ +------------------------------------------------------------------------------ +-- GNATcoverage -- +-- Copyright (C) 2012-2025, AdaCore -- +------------------------------------------------------------------------------ + +with Sensors; use Sensors; +with Ada.Text_IO; use Ada.Text_IO; + +procedure Monitor is + Sensor_Value : Integer; +begin + for Sensor_Index in Sensor_Index_Range loop + Sensor_Value := Sensors.Value (Sensor_Index); + Put ("Sensor(" & Sensor_Index'Img & ") = " & Sensor_Value'Img & " "); + if (Sensor_Value > 1000) then + Put_Line ("!Alarm!"); + else + Put_Line ("!Ok!"); + end if; + end loop; +end; diff --git a/tools/gnatcov/examples/doc/cross_example/src/sensors.adb b/tools/gnatcov/examples/doc/cross_example/src/sensors.adb new file mode 100644 index 000000000..f991e735f --- /dev/null +++ b/tools/gnatcov/examples/doc/cross_example/src/sensors.adb @@ -0,0 +1,20 @@ +------------------------------------------------------------------------------ +-- GNATcoverage -- +-- Copyright (C) 2012-2025, AdaCore -- +------------------------------------------------------------------------------ + +package body Sensors is + + function Value (Index : Sensor_Index_Range) return Integer is + begin + -- Dummy implementation, for demonstration purposes + + case Index is + when 1 => return 1; + when 2 => return 5; + when 3 => return 3; + when 4 => return 7; + end case; + end Value; + +end Sensors; diff --git a/tools/gnatcov/examples/doc/cross_example/src/sensors.ads b/tools/gnatcov/examples/doc/cross_example/src/sensors.ads new file mode 100644 index 000000000..1764d421c --- /dev/null +++ b/tools/gnatcov/examples/doc/cross_example/src/sensors.ads @@ -0,0 +1,12 @@ +------------------------------------------------------------------------------ +-- GNATcoverage -- +-- Copyright (C) 2012-2025, AdaCore -- +------------------------------------------------------------------------------ + +package Sensors is + + type Sensor_Index_Range is range 1 .. 4; + + function Value (Index : Sensor_Index_Range) return Integer; + +end Sensors; From 6eda5721a5893330d33d45b950a8f4c3923a2198 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 14 Mar 2025 11:32:55 +0100 Subject: [PATCH 1140/1483] Add sources for the src-trace library instrumentation example --- doc/gnatcov/src_traces.rst | 4 ++ .../examples/doc/library_instr/Makefile | 44 +++++++++++++++++++ .../examples/doc/library_instr/code.gpr | 18 ++++++++ .../examples/doc/library_instr/code/ops.adb | 14 ++++++ .../examples/doc/library_instr/code/ops.ads | 9 ++++ .../examples/doc/library_instr/tests.gpr | 12 +++++ .../doc/library_instr/tests/test_inc.adb | 13 ++++++ 7 files changed, 114 insertions(+) create mode 100644 tools/gnatcov/examples/doc/library_instr/Makefile create mode 100644 tools/gnatcov/examples/doc/library_instr/code.gpr create mode 100644 tools/gnatcov/examples/doc/library_instr/code/ops.adb create mode 100644 tools/gnatcov/examples/doc/library_instr/code/ops.ads create mode 100644 tools/gnatcov/examples/doc/library_instr/tests.gpr create mode 100644 tools/gnatcov/examples/doc/library_instr/tests/test_inc.adb diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 93e51f470..f50d87b5a 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -1038,6 +1038,10 @@ For the sake of the example, we will consider that by each new test individually or for the current set of tests at a given point in time. +The sources for this example can be found under the +`share/examples/gnatcoverage/doc/library_instr/` directory of the GNATDAS +distribution. + Setting up the coverage runtime ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tools/gnatcov/examples/doc/library_instr/Makefile b/tools/gnatcov/examples/doc/library_instr/Makefile new file mode 100644 index 000000000..c708aec6f --- /dev/null +++ b/tools/gnatcov/examples/doc/library_instr/Makefile @@ -0,0 +1,44 @@ +# Project demonstrating how to instrument and get coverage over a library, and +# distribute the instrumented library independently, leveraging the +# Externally_Built GPR attribute. +# +# See paragraph "Example use cases" of the +# "Producing source traces with gnatcov instrument" section for more details + +RTS_DIR = rts_install + +.PHONY: instrument build run coverage + +default: coverage + +# Only needs to be called once, can be re-used across multiple GNATcov workflows +$(RTS_DIR)/share/gpr/gnatcov_rts.gpr: + gnatcov setup --prefix=$(RTS_DIR) + +instrument-lib: export GPR_PROJECT_PATH := $(shell pwd)/$(RTS_DIR)/share/gpr:$(GPR_PROJECT_PATH) +instrument-lib: $(RTS_DIR)/share/gpr/gnatcov_rts.gpr + @echo 'export GPR_PROJECT_PATH=$$(pwd)/$(RTS_DIR)/share/gpr:$$GPR_PROJECT_PATH' + gnatcov instrument -P code.gpr --level=stmt -XCODE_LIBMODE=instrument + +build-lib: export GPR_PROJECT_PATH := $(shell pwd)/$(RTS_DIR)/share/gpr:$(GPR_PROJECT_PATH) +build-lib: instrument + gprbuild -f -p -P code.gpr --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts.gpr \ + -XCODE_LIBMODE=build + +instrument-test: export GPR_PROJECT_PATH := $(shell pwd)/$(RTS_DIR)/share/gpr:$(GPR_PROJECT_PATH) +instrument-test: instrument-lib + gnatcov instrument -P tests.gpr --level=stmt --externally-built-projects --dump-trigger=atexit + +build-test: export GPR_PROJECT_PATH := $(shell pwd)/$(RTS_DIR)/share/gpr:$(GPR_PROJECT_PATH) +build-test: instrument-test build-lib + gprbuild -P tests.gpr --src-subdirs=gnatcov-instr --implicit-with=gnatcov_rts.gpr + +run: build-test + ./obj-tests/test_inc + +coverage: run + gnatcov coverage -P tests.gpr --level=stmt --annotate=xcov test_inc*.srctrace --externally-built-projects + cat obj-tests/ops.adb.xcov + +clean: + rm -rf obj-* $(RTS_DIR) test_inc*.srctrace lib-* diff --git a/tools/gnatcov/examples/doc/library_instr/code.gpr b/tools/gnatcov/examples/doc/library_instr/code.gpr new file mode 100644 index 000000000..1054e1de3 --- /dev/null +++ b/tools/gnatcov/examples/doc/library_instr/code.gpr @@ -0,0 +1,18 @@ +library project Code is + for Source_Dirs use ("code"); + for Object_Dir use "obj-" & Project'Name; + + for Library_Dir use "lib-" & project'Name; + for Library_Kind use "static"; + for Library_Name use "code"; + + type Mode is ("build", "instrument", "use"); + LIB_MODE : Mode := external ("CODE_LIBMODE", "use"); + + case LIB_MODE is + when "build" => for Externally_Built use "False"; + when "instrument" => for Externally_Built use "False"; + when "use" => for Externally_Built use "True"; + end case; + +end Code; diff --git a/tools/gnatcov/examples/doc/library_instr/code/ops.adb b/tools/gnatcov/examples/doc/library_instr/code/ops.adb new file mode 100644 index 000000000..54f54cc96 --- /dev/null +++ b/tools/gnatcov/examples/doc/library_instr/code/ops.adb @@ -0,0 +1,14 @@ +------------------------------------------------------------------------------ +-- GNATcoverage -- +-- Copyright (C) 2012-2025, AdaCore -- +------------------------------------------------------------------------------ + +package body Ops is + procedure Apply (Op : Op_Kind; X : in out Integer) is + begin + case Op is + when Increment => X := X + 1; + when Decrement => X := X - 1; + end case; + end Apply; +end Ops; diff --git a/tools/gnatcov/examples/doc/library_instr/code/ops.ads b/tools/gnatcov/examples/doc/library_instr/code/ops.ads new file mode 100644 index 000000000..eb6b58932 --- /dev/null +++ b/tools/gnatcov/examples/doc/library_instr/code/ops.ads @@ -0,0 +1,9 @@ +------------------------------------------------------------------------------ +-- GNATcoverage -- +-- Copyright (C) 2012-2025, AdaCore -- +------------------------------------------------------------------------------ + +package Ops is + type Op_Kind is (Increment, Decrement); + procedure Apply (Op : Op_Kind; X : in out Integer); +end Ops; diff --git a/tools/gnatcov/examples/doc/library_instr/tests.gpr b/tools/gnatcov/examples/doc/library_instr/tests.gpr new file mode 100644 index 000000000..9f584aeb3 --- /dev/null +++ b/tools/gnatcov/examples/doc/library_instr/tests.gpr @@ -0,0 +1,12 @@ +with "code.gpr"; + +project Tests is + for Source_Dirs use ("tests"); + for Object_Dir use "obj-" & Project'Name; + + for Main use ("test_inc.adb"); + + package Coverage is + for Units use (); + end Coverage; +end Tests; diff --git a/tools/gnatcov/examples/doc/library_instr/tests/test_inc.adb b/tools/gnatcov/examples/doc/library_instr/tests/test_inc.adb new file mode 100644 index 000000000..f16fe3572 --- /dev/null +++ b/tools/gnatcov/examples/doc/library_instr/tests/test_inc.adb @@ -0,0 +1,13 @@ +------------------------------------------------------------------------------ +-- GNATcoverage -- +-- Copyright (C) 2012-2025, AdaCore -- +------------------------------------------------------------------------------ + +with Ops; + +procedure Test_Inc is + X : Integer := 4; +begin + Ops.Apply (Ops.Increment, X); + pragma Assert (X = 5); +end Test_Inc; From 8f5a832e83a95cfa59a9105d8d2ec610f7c1be5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 17 Mar 2025 15:43:39 +0100 Subject: [PATCH 1141/1483] Doc: Add sources for integrated instrumentation examples --- doc/gnatcov/integrated_instr.rst | 12 ++++- .../gnatcov/examples/doc/integrated/Makefile | 45 +++++++++++++++++++ .../doc/integrated/hello_world/CMakeLists.txt | 4 ++ .../doc/integrated/hello_world/Makefile | 8 ++++ .../doc/integrated/hello_world/main.cpp | 13 ++++++ 5 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 tools/gnatcov/examples/doc/integrated/Makefile create mode 100644 tools/gnatcov/examples/doc/integrated/hello_world/CMakeLists.txt create mode 100644 tools/gnatcov/examples/doc/integrated/hello_world/Makefile create mode 100644 tools/gnatcov/examples/doc/integrated/hello_world/main.cpp diff --git a/doc/gnatcov/integrated_instr.rst b/doc/gnatcov/integrated_instr.rst index 4bc3459fe..9ab1081e6 100644 --- a/doc/gnatcov/integrated_instr.rst +++ b/doc/gnatcov/integrated_instr.rst @@ -62,6 +62,10 @@ generated compiler wrapper instead of the original compiler. A simple Makefile example ========================= +The sources for the following example can be found under the +``share/examples/gnatcoverage/doc/integrated`` directory of the GNATDAS +distribution. + The following considers that the instrumentation runtime was previously installed with ``gnatcov setup``, and that the ``GPR_PROJECT_PATH`` variable contains its installed location. See :ref:`instr-rts`. @@ -111,6 +115,12 @@ when run, that can be analyzed with ``gnatcov coverage``. A simple CMake example ====================== +The sources for the following example can be found under the +``share/examples/gnatcoverage/doc/integrated`` directory of the GNATDAS +distribution. To ensure that the Makefile provided with the example sources +uses CMake as a build system, specify ``BUILD_SYSTEM=CMake`` on the `make` +invocation. + The following considers that the instrumentation runtime was installed through the use of ``gnatcov setup``. @@ -129,8 +139,8 @@ The CMakeLists.txt file to be used to compile the main.cpp file is : .. code-block:: cmake + cmake_minimum_required(VERSION 3.5) project(HelloWorld) - cmake_minimum_required(VERSION 3.0) add_executable(hello_world main.cpp) diff --git a/tools/gnatcov/examples/doc/integrated/Makefile b/tools/gnatcov/examples/doc/integrated/Makefile new file mode 100644 index 000000000..c359c5f6e --- /dev/null +++ b/tools/gnatcov/examples/doc/integrated/Makefile @@ -0,0 +1,45 @@ +# This showcases how to use the integrated instrumentation mode with a Makefile +# or a CMake build system. For more details see subsections "A simple Makefile +# example" and "A simple CMake example" of section "Producing source traces +# with integrated instrumentation". + +RTS_DIR = rts_install +ARTIFACTS_DIR = gnatcov_artifacts + +.PHONY: setup-instr build run coverage clean + +# Set this variable to either Makefile or CMake to select the desired build system +BUILD_SYSTEM ?= Makefile + +default: coverage + +# Only needs to be called once, can be re-used across multiple GNATcov workflows +$(RTS_DIR)/share/gpr/gnatcov_rts.gpr: + gnatcov setup --prefix=$(RTS_DIR) + +setup-instr: export GPR_PROJECT_PATH := $(shell pwd)/$(RTS_DIR)/share/gpr:$(GPR_PROJECT_PATH) +setup-instr: $(RTS_DIR)/share/gpr/gnatcov_rts.gpr + gnatcov setup-integration --files=hello_world/main.cpp --compilers=g++ \ + --level=stmt --output-dir=$(ARTIFACTS_DIR) + +build-Makefile: export PATH:=$(shell pwd)/$(ARTIFACTS_DIR):$(PATH) +build-Makefile: setup-instr + make -C hello_world test + cp hello_world/test . + +build-CMake: setup-instr + cmake hello_world -B cmake_build -DCMAKE_CXX_COMPILER=$(shell pwd)/$(ARTIFACTS_DIR)/g++ + cmake --build cmake_build + cp cmake_build/test . + +run: build-$(BUILD_SYSTEM) + ./test + +coverage: run + gnatcov coverage --sid $(ARTIFACTS_DIR)/main.cpp.sid --level=stmt \ + --annotate=xcov *.srctrace + cat main.cpp.xcov + +clean: + rm -rf $(ARTIFACTS_DIR) $(RTS_DIR) main*.srctrace hello_world/main.o \ + hello_world/test stats *.xcov CMakeFiles CMakeCache.txt cmake_* test diff --git a/tools/gnatcov/examples/doc/integrated/hello_world/CMakeLists.txt b/tools/gnatcov/examples/doc/integrated/hello_world/CMakeLists.txt new file mode 100644 index 000000000..186f49fe7 --- /dev/null +++ b/tools/gnatcov/examples/doc/integrated/hello_world/CMakeLists.txt @@ -0,0 +1,4 @@ +cmake_minimum_required(VERSION 3.5) +project(HelloWorld) + +add_executable(test main.cpp) diff --git a/tools/gnatcov/examples/doc/integrated/hello_world/Makefile b/tools/gnatcov/examples/doc/integrated/hello_world/Makefile new file mode 100644 index 000000000..8f374441a --- /dev/null +++ b/tools/gnatcov/examples/doc/integrated/hello_world/Makefile @@ -0,0 +1,8 @@ +CC=g++ +OBJ = main.o + +%.o: %.c + $(CC) -c -o $@ $< + +test: $(OBJ) + $(CC) -o $@ $^ diff --git a/tools/gnatcov/examples/doc/integrated/hello_world/main.cpp b/tools/gnatcov/examples/doc/integrated/hello_world/main.cpp new file mode 100644 index 000000000..59f4cb27b --- /dev/null +++ b/tools/gnatcov/examples/doc/integrated/hello_world/main.cpp @@ -0,0 +1,13 @@ +/****************************************************** + * GNATcoverage * + * Copyright (C) 2012-2025, AdaCore * + ******************************************************/ + +#include + +int +main (int argc, char **argv) +{ + std::cout << "Hello World" << std::endl; + return 0; +} From c77978e5339f2f9c4d1bb8045005638895c66e23 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 17 Mar 2025 15:48:15 +0100 Subject: [PATCH 1142/1483] Document block instrumentation --- doc/gnatcov/src_traces.rst | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index f50d87b5a..9c21f270f 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -669,6 +669,25 @@ Guarded expression coverage is only available for the Ada language. For implementation reasons, it is only available starting from version 2022 of the language. +.. _instr-opti: + +Optimizing the execution of instrumented programs +================================================= + +To monitor the execution of statement obligations, gnatcov instruments the code +which results in an execution overhead. + +To mitigate the performance impact, one can use the +:cmd-option:`--instrument-block switch`. Instead of instrumenting for the +execution of one statement, gnatcov instrument the code for the execution of a +block of statements, greatly reducing the execution overhead. The coverage +report is left unchanged, only the way coverage obligation are discarded is. + +It is important to note that this could result in *false negatives* (i.e. +covered code reported as uncovered) when exceptions are used as a control flow +mechanism, and do not necessarily signal an abnormal termination of the program. +The tool will never report false positives (uncovered code reported as covered). + .. _instr-build: Building instrumented components From b4d86d08c004fbf63d2a1df4475867f5576a53ba Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 17 Mar 2025 16:07:06 +0100 Subject: [PATCH 1143/1483] traces_files: Rework Read_Result type --- tools/gnatcov/gnatcov_bits_specific.adb | 12 ++++---- tools/gnatcov/instrument-input_traces.adb | 37 ++++++++++++----------- tools/gnatcov/traces_files.adb | 28 +++++++++-------- tools/gnatcov/traces_files.ads | 25 +++++++++++---- 4 files changed, 60 insertions(+), 42 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index c12aa40f7..89150e54f 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -190,7 +190,7 @@ procedure GNATcov_Bits_Specific is -- or all explicitly passed SID files. procedure Report_Bad_Trace (Trace_Filename : String; Result : Read_Result) - with Pre => not Result.Success; + with Pre => not Is_Success (Result); -- Emit the error corresponding to Result with Outputs. If -- Keep_Reading_Tracess is false, this is a fatal error. @@ -1944,7 +1944,7 @@ begin end if; Probe_Trace_File (Trace_File_Name, Kind, Result); - if not Result.Success then + if not Is_Success (Result) then Report_Bad_Trace (Trace_File_Name, Result); end if; @@ -2006,7 +2006,7 @@ begin -- We can now read it and import its data Read_Source_Trace_File (Trace_File_Name, Result); - if not Result.Success then + if not Is_Success (Result) then Report_Bad_Trace (Trace_File_Name, Result); end if; @@ -2076,7 +2076,7 @@ begin TF : Trace_File_Type; begin Read_Trace_File (Trace_Filename, TF, Result, Base); - if not Result.Success then + if not Is_Success (Result) then Report_Bad_Trace (Trace_Filename, Result); return; end if; @@ -2156,7 +2156,7 @@ begin Result : out Read_Result) is begin Check_Trace_File_From_Exec (TF, Result); - if not Result.Success then + if not Is_Success (Result) then return; end if; Exe_File := Open_Exec_For_Trace @@ -2248,7 +2248,7 @@ begin Result : Read_Result; begin Read_Trace_File (Trace_Filename, TF, Result); - if not Result.Success then + if not Is_Success (Result) then Report_Bad_Trace (Trace_Filename, Result); return; end if; diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 0067dc593..44eca3dca 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -31,6 +31,7 @@ with GNAT.Byte_Swapping; use GNAT.Byte_Swapping; with Hex_Images; with Outputs; +with Traces_Files; use Traces_Files; package body Instrument.Input_Traces is @@ -103,7 +104,7 @@ package body Instrument.Input_Traces is EOF : out Boolean; Result : in out Read_Result; Error_If_EOF : Boolean := True) - with Pre => Result.Success; + with Pre => Is_Success (Result); -- Try to read Size bytes from Stream. Put the result in Stream.Buffer and -- Stream.Buffer_Last. By default, set EOF to False (see below). -- @@ -141,7 +142,7 @@ package body Instrument.Input_Traces is (Stream : in out Binary_Stream; File_Header : out Trace_File_Header; Result : in out Read_Result) - with Pre => Result.Success; + with Pre => Is_Success (Result); -- Read a trace file header from Stream and store it in File_Header. Set -- Result to an error if something wrong happened. @@ -151,7 +152,7 @@ package body Instrument.Input_Traces is Kind : out Supported_Info_Kind; Data : out GNAT.OS_Lib.String_Access; Result : in out Read_Result) - with Pre => Result.Success; + with Pre => Is_Success (Result); -- Read a trace info entry from Stream. Return an error if something wrong -- happened, otherwise put its kind in Kind and allocate a string in Data -- to hold the data associated to this entry. @@ -162,7 +163,7 @@ package body Instrument.Input_Traces is Entry_Header : out Trace_Entry_Header; Trace_Entry : out Trace_Entry_Elements; Result : in out Read_Result) return Boolean - with Pre => Result.Success; + with Pre => Is_Success (Result); -- Try to read a trace entry header from Stream. -- -- If Stream already reached EOF, just return False. Otherwise, decode it @@ -178,7 +179,7 @@ package body Instrument.Input_Traces is Raw_Buffer : Bytes_Array; Buffer : out Coverage_Buffer; Result : in out Read_Result) - with Pre => Result.Success; + with Pre => Is_Success (Result); -- Decode the given Raw_Buffer according to the given Encoding, and but the -- result in Buffer. If all goes well, keep Result as it is, otherwise set -- it to the corresponding error information. @@ -328,7 +329,7 @@ package body Instrument.Input_Traces is begin Read_Bytes (Stream, File_Header'Size / 8, Ignored_EOF, Result); - if not Result.Success then + if not Is_Success (Result) then return; end if; @@ -401,7 +402,7 @@ package body Instrument.Input_Traces is Read_Bytes (Stream, Trace_Info_Header'Size / 8, Ignored_EOF, Result); - if not Result.Success then + if not Is_Success (Result) then return; end if; @@ -444,7 +445,7 @@ package body Instrument.Input_Traces is begin Read_Bytes (Stream, Read_Size, Ignored_EOF, Result); end; - if not Result.Success then + if not Is_Success (Result) then Free (Data); return; end if; @@ -473,7 +474,7 @@ package body Instrument.Input_Traces is Read_Bytes (Stream, Entry_Header'Size / 8, EOF, Result, Error_If_EOF => False); - if EOF or else not Result.Success then + if EOF or else not Is_Success (Result) then return False; end if; @@ -558,7 +559,7 @@ package body Instrument.Input_Traces is System.Storage_Elements.Storage_Offset (Offset))); begin Read_Bytes (Stream, Data_Size, EOF, Result); - if not Result.Success then + if not Is_Success (Result) then return False; end if; @@ -625,13 +626,13 @@ package body Instrument.Input_Traces is Decision_Buffer : Coverage_Buffer_Access; MCDC_Buffer : Coverage_Buffer_Access; begin - Result := (Success => True); + Result := (Kind => Success); -- Try to open the file Stream.File := Open_Read (Filename, Binary); if Stream.File = Invalid_FD then - Create_Error (Result, "cannot open " & Filename); + Create_Error (Result, Filename); return; end if; Stream.Offset := 0; @@ -639,7 +640,7 @@ package body Instrument.Input_Traces is -- Read the trace file header Read_Trace_File_Header (Stream, File_Header, Result); - if not Result.Success then + if not Is_Success (Result) then goto Cleanup_And_Exit; end if; @@ -651,7 +652,7 @@ package body Instrument.Input_Traces is Data : GNAT.OS_Lib.String_Access; begin Read_Trace_Info (Stream, File_Header, Kind, Data, Result); - if not Result.Success then + if not Is_Success (Result) then goto Cleanup_And_Exit; end if; @@ -726,7 +727,7 @@ package body Instrument.Input_Traces is Statement_Buffer (0 .. Last_Bit (Entry_Header.Statement_Bit_Count)), Result); - if not Result.Success then + if not Is_Success (Result) then goto Cleanup_And_Exit; end if; @@ -736,7 +737,7 @@ package body Instrument.Input_Traces is Decision_Buffer (0 .. Last_Bit (Entry_Header.Decision_Bit_Count)), Result); - if not Result.Success then + if not Is_Success (Result) then goto Cleanup_And_Exit; end if; @@ -745,7 +746,7 @@ package body Instrument.Input_Traces is Raw_MCDC_Buffer, MCDC_Buffer (0 .. Last_Bit (Entry_Header.MCDC_Bit_Count)), Result); - if not Result.Success then + if not Is_Success (Result) then goto Cleanup_And_Exit; end if; @@ -917,7 +918,7 @@ package body Instrument.Input_Traces is begin Read_Source_Trace_File (Filename, Result); - if not Result.Success then + if not Is_Success (Result) then Outputs.Fatal_Error (+Result.Error); end if; end Dump_Source_Trace_File; diff --git a/tools/gnatcov/traces_files.adb b/tools/gnatcov/traces_files.adb index 0e0de600e..6f2d5cf91 100644 --- a/tools/gnatcov/traces_files.adb +++ b/tools/gnatcov/traces_files.adb @@ -287,7 +287,7 @@ package body Traces_Files is procedure Success_Or_Fatal_Error (Filename : String; Result : Read_Result) is begin - if not Result.Success then + if not Is_Success (Result) then Fatal_Error (Filename & ": " & (+Result.Error)); end if; end Success_Or_Fatal_Error; @@ -385,7 +385,7 @@ package body Traces_Files is -- Return whether the given Magic matches the first bytes in Buffer begin - Result := (Success => True); + Result := (Kind => Success); Kind := Binary_Trace_File; if Fd = Invalid_FD then @@ -461,7 +461,7 @@ package body Traces_Files is -- there. Check_Header (Desc, Hdr, Result); - if not Result.Success then + if not Is_Success (Result) then return; end if; @@ -481,7 +481,7 @@ package body Traces_Files is else Decode_Trace_Header (Hdr.all, Trace_File, Desc, Result); - if not Result.Success then + if not Is_Success (Result) then return; end if; end if; @@ -497,12 +497,12 @@ package body Traces_Files is -- kind as a second header. Append_Info_Entries_From_Descriptor (Desc, Trace_File, Result); - if For_Trace_Output or else not Result.Success then + if For_Trace_Output or else not Is_Success (Result) then return; end if; Check_Header (Desc, Hdr, Result); - if not Result.Success then + if not Is_Success (Result) then return; end if; @@ -647,7 +647,7 @@ package body Traces_Files is Result := Read_Success; Read_Info_Entries (Desc, Result); - if not Result.Success then + if not Is_Success (Result) then return; end if; @@ -927,7 +927,7 @@ package body Traces_Files is Open_Trace_File (Filename, Desc, Trace_File); Trace_File.Filename := +Filename; Process_Info_Entries (Trace_File, Result); - if not Result.Success then + if not Is_Success (Result) then return; end if; @@ -942,7 +942,7 @@ package body Traces_Files is loop Read_Trace_Entry (Desc, EOF, Raw_Entry, Result); - if not Result.Success then + if not Is_Success (Result) then return; elsif EOF then Create_Error (Result, "No 'loadaddr' special trace entry"); @@ -986,7 +986,7 @@ package body Traces_Files is loop Read_Trace_Entry (Desc, EOF, Raw_Entry, Result); - if not Result.Success then + if not Is_Success (Result) then return; end if; exit when EOF; @@ -1012,7 +1012,7 @@ package body Traces_Files is First, Last : Pc_Type; begin Read_SO_Info (Desc, Filename, Sig, Code_Size, Result); - if not Result.Success then + if not Is_Success (Result) then return; end if; First := Raw_Entry.Pc; @@ -1770,7 +1770,11 @@ package body Traces_Files is procedure Create_Error (Result : out Read_Result; Error : String) is begin - Result := (Success => False, Error => +Error); + Result := (Kind => Other_Error, Error => +Error); end Create_Error; + procedure Create_Open_Error (Result : out Read_Result; Filename : String) is + begin + Result := (Kind => Open_Error, Error => +("cannot open " & Filename)); + end Create_Open_Error; end Traces_Files; diff --git a/tools/gnatcov/traces_files.ads b/tools/gnatcov/traces_files.ads index 0bad472eb..ac555d9af 100644 --- a/tools/gnatcov/traces_files.ads +++ b/tools/gnatcov/traces_files.ads @@ -32,12 +32,21 @@ with Traces; package Traces_Files is - type Read_Result (Success : Boolean := True) is record - case Success is - when False => - Error : Unbounded_String; - when True => + type Read_Result_Kind is (Success, Open_Error, Other_Error); + + subtype Error_Read_Result_Kind is + Read_Result_Kind range Open_Error .. Other_Error; + + subtype Recoverable_Read_Result_Kind is + Read_Result_Kind range Open_Error .. Open_Error; + -- Errors that are actually recoverable which should only trigger a warning + + type Read_Result (Kind : Read_Result_Kind := Success) is record + case Kind is + when Success => null; + when others => + Error : Unbounded_String; end case; end record; -- Description of the result of a trace read operation: either it was @@ -48,6 +57,9 @@ package Traces_Files is -- following procedure enables to probe a trace file in order to determine -- if it's a binary trace file or a source trace file. + function Is_Success (R : Read_Result) return Boolean is + (R.Kind = Success); + type Any_Accepted_Trace_Kind is (Unknown, Binary_Trace_File, Source_Trace_File, All_Trace_Files); -- We normally do not allow to mix trace kinds, but in case this should be @@ -87,9 +99,10 @@ package Traces_Files is type Trace_File_Descriptor is limited private; -- Descriptor to read or write a trace file - Read_Success : constant Read_Result := (Success => True); + Read_Success : constant Read_Result := (Kind => Success); procedure Create_Error (Result : out Read_Result; Error : String); + procedure Create_Open_Error (Result : out Read_Result; Filename : String); -- Shortcut to create a Read_Result that contains an error procedure Success_Or_Fatal_Error (Filename : String; Result : Read_Result); From ddef2ca33135ef5e9d0cf38d0b879c585f50a15c Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 17 Mar 2025 17:14:47 +0100 Subject: [PATCH 1144/1483] traces_files: Emit a warning when a trace file is not found --- tools/gnatcov/gnatcov_bits_specific.adb | 11 ++++++++++- tools/gnatcov/traces_files.adb | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 89150e54f..a98bbbffe 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1184,7 +1184,9 @@ procedure GNATcov_Bits_Specific is is Message : constant String := Trace_Filename & ": " & (+Result.Error); begin - if Keep_Reading_Traces then + if Result.Kind in Recoverable_Read_Result_Kind then + Outputs.Warn (Message); + elsif Keep_Reading_Traces then Outputs.Error (Message); else Outputs.Fatal_Error (Message); @@ -1946,6 +1948,13 @@ begin Probe_Trace_File (Trace_File_Name, Kind, Result); if not Is_Success (Result) then Report_Bad_Trace (Trace_File_Name, Result); + + -- If the file does not exist, do not try to Process it + -- further. + + if Result.Kind = Open_Error then + return; + end if; end if; case Kind is diff --git a/tools/gnatcov/traces_files.adb b/tools/gnatcov/traces_files.adb index 6f2d5cf91..b5f596639 100644 --- a/tools/gnatcov/traces_files.adb +++ b/tools/gnatcov/traces_files.adb @@ -389,7 +389,7 @@ package body Traces_Files is Kind := Binary_Trace_File; if Fd = Invalid_FD then - Create_Error (Result, "cannot open " & Filename); + Create_Open_Error (Result, Filename); return; end if; From 7e89ab96673f9ca4e954728ad85e1e0dce86d656 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 18 Mar 2025 11:56:50 +0100 Subject: [PATCH 1145/1483] test(trace_files): Add test for non-existing trace skip --- .../main.adb | 6 ++ .../test.opt | 1 + .../test.py | 57 +++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 testsuite/tests/400-recover-from-non-existing-trace/main.adb create mode 100644 testsuite/tests/400-recover-from-non-existing-trace/test.opt create mode 100644 testsuite/tests/400-recover-from-non-existing-trace/test.py diff --git a/testsuite/tests/400-recover-from-non-existing-trace/main.adb b/testsuite/tests/400-recover-from-non-existing-trace/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/400-recover-from-non-existing-trace/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/400-recover-from-non-existing-trace/test.opt b/testsuite/tests/400-recover-from-non-existing-trace/test.opt new file mode 100644 index 000000000..c7a7b22c6 --- /dev/null +++ b/testsuite/tests/400-recover-from-non-existing-trace/test.opt @@ -0,0 +1 @@ +!src-traces DEAD test needs source traces diff --git a/testsuite/tests/400-recover-from-non-existing-trace/test.py b/testsuite/tests/400-recover-from-non-existing-trace/test.py new file mode 100644 index 000000000..c74bd893f --- /dev/null +++ b/testsuite/tests/400-recover-from-non-existing-trace/test.py @@ -0,0 +1,57 @@ +""" +This test ensures that when one of the trace files given to `gnatcov coverage` +does not exist, a warning is emitted but the process is not aborted. +""" + +import glob +import re + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir, contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + +Wdir("tmp_") + +# First produce a source trace from the test program +xcov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + extra_coverage_args=[], + mains=["main"], +) + +LIST_FILE = "traces.txt" +NOT_FOUND_SRCTRACE = "not_found.srctrace" +REAL_SRCTRACE = glob.glob("main-*.srctrace")[0] +COV_OUT = "cov_out.txt" +COV_ERR = "cov_err.txt" + +# Make a tracefile list file +with open(LIST_FILE, "w") as f: + f.write(f"{NOT_FOUND_SRCTRACE}\n{REAL_SRCTRACE}") + +# Run the coverage command +xcov( + ["coverage", "-P", "gen.gpr", "--level=stmt", "-areport", f"@{LIST_FILE}"], + register_failure=True, + out=COV_OUT, + err=COV_ERR, +) + +# Ensure a warning was emitted +thistest.fail_if_not_equal( + "Missing warning to say that a trace file was not found", + f"warning: {NOT_FOUND_SRCTRACE}: cannot open {NOT_FOUND_SRCTRACE}\n", + contents_of(COV_ERR), +) + +# Ensure the coverage was correctly handled after the encounter with the +# missing file. +thistest.fail_if_no_match( + "There should be no violation in the report", + re.compile(r".*No STMT violation\..*", flags=re.S), + contents_of(COV_OUT), +) + +thistest.result() From a22245dabdfc26563950d5341abad946fdcb9a02 Mon Sep 17 00:00:00 2001 From: Joao Azevedo Date: Thu, 20 Mar 2025 11:24:10 +0000 Subject: [PATCH 1146/1483] Package the src directory with GNATfuzz Python sources --- tools/gnatcov/doinstall.tmplt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/doinstall.tmplt b/tools/gnatcov/doinstall.tmplt index ed15ffb8d..25908905e 100755 --- a/tools/gnatcov/doinstall.tmplt +++ b/tools/gnatcov/doinstall.tmplt @@ -87,7 +87,8 @@ standard_installation () { # only contains the new sources. mkdir -p "$prefix" rm -rf "$prefix/share/gnatcoverage/gnatcov_rts/" - (tar cf - bin lib libexec share \ + rm -rf "$prefix/src/gnatfuzz/" + (tar cf - bin lib libexec share src \ | (cd "$prefix"; tar xf -)) 2>&1 | tee $tmpout # Check that installation was OK From ba74a21d39d537d3113f5966c108954daee70350 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 20 Mar 2025 11:14:01 +0100 Subject: [PATCH 1147/1483] Revert !787: peron/recover-from-unexisting-tracefile --- .../main.adb | 6 -- .../test.opt | 1 - .../test.py | 57 ------------------- tools/gnatcov/gnatcov_bits_specific.adb | 23 +++----- tools/gnatcov/instrument-input_traces.adb | 37 ++++++------ tools/gnatcov/traces_files.adb | 30 +++++----- tools/gnatcov/traces_files.ads | 25 ++------ 7 files changed, 44 insertions(+), 135 deletions(-) delete mode 100644 testsuite/tests/400-recover-from-non-existing-trace/main.adb delete mode 100644 testsuite/tests/400-recover-from-non-existing-trace/test.opt delete mode 100644 testsuite/tests/400-recover-from-non-existing-trace/test.py diff --git a/testsuite/tests/400-recover-from-non-existing-trace/main.adb b/testsuite/tests/400-recover-from-non-existing-trace/main.adb deleted file mode 100644 index 3373e6745..000000000 --- a/testsuite/tests/400-recover-from-non-existing-trace/main.adb +++ /dev/null @@ -1,6 +0,0 @@ -with Ada.Text_IO; use Ada.Text_IO; - -procedure Main is -begin - Put_Line ("Hello, world!"); -end Main; diff --git a/testsuite/tests/400-recover-from-non-existing-trace/test.opt b/testsuite/tests/400-recover-from-non-existing-trace/test.opt deleted file mode 100644 index c7a7b22c6..000000000 --- a/testsuite/tests/400-recover-from-non-existing-trace/test.opt +++ /dev/null @@ -1 +0,0 @@ -!src-traces DEAD test needs source traces diff --git a/testsuite/tests/400-recover-from-non-existing-trace/test.py b/testsuite/tests/400-recover-from-non-existing-trace/test.py deleted file mode 100644 index c74bd893f..000000000 --- a/testsuite/tests/400-recover-from-non-existing-trace/test.py +++ /dev/null @@ -1,57 +0,0 @@ -""" -This test ensures that when one of the trace files given to `gnatcov coverage` -does not exist, a warning is emitted but the process is not aborted. -""" - -import glob -import re - -from SCOV.minicheck import build_and_run -from SUITE.cutils import Wdir, contents_of -from SUITE.gprutils import GPRswitches -from SUITE.tutils import gprfor, thistest, xcov - -Wdir("tmp_") - -# First produce a source trace from the test program -xcov_args = build_and_run( - gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), - covlevel="stmt", - extra_coverage_args=[], - mains=["main"], -) - -LIST_FILE = "traces.txt" -NOT_FOUND_SRCTRACE = "not_found.srctrace" -REAL_SRCTRACE = glob.glob("main-*.srctrace")[0] -COV_OUT = "cov_out.txt" -COV_ERR = "cov_err.txt" - -# Make a tracefile list file -with open(LIST_FILE, "w") as f: - f.write(f"{NOT_FOUND_SRCTRACE}\n{REAL_SRCTRACE}") - -# Run the coverage command -xcov( - ["coverage", "-P", "gen.gpr", "--level=stmt", "-areport", f"@{LIST_FILE}"], - register_failure=True, - out=COV_OUT, - err=COV_ERR, -) - -# Ensure a warning was emitted -thistest.fail_if_not_equal( - "Missing warning to say that a trace file was not found", - f"warning: {NOT_FOUND_SRCTRACE}: cannot open {NOT_FOUND_SRCTRACE}\n", - contents_of(COV_ERR), -) - -# Ensure the coverage was correctly handled after the encounter with the -# missing file. -thistest.fail_if_no_match( - "There should be no violation in the report", - re.compile(r".*No STMT violation\..*", flags=re.S), - contents_of(COV_OUT), -) - -thistest.result() diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index a98bbbffe..c12aa40f7 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -190,7 +190,7 @@ procedure GNATcov_Bits_Specific is -- or all explicitly passed SID files. procedure Report_Bad_Trace (Trace_Filename : String; Result : Read_Result) - with Pre => not Is_Success (Result); + with Pre => not Result.Success; -- Emit the error corresponding to Result with Outputs. If -- Keep_Reading_Tracess is false, this is a fatal error. @@ -1184,9 +1184,7 @@ procedure GNATcov_Bits_Specific is is Message : constant String := Trace_Filename & ": " & (+Result.Error); begin - if Result.Kind in Recoverable_Read_Result_Kind then - Outputs.Warn (Message); - elsif Keep_Reading_Traces then + if Keep_Reading_Traces then Outputs.Error (Message); else Outputs.Fatal_Error (Message); @@ -1946,15 +1944,8 @@ begin end if; Probe_Trace_File (Trace_File_Name, Kind, Result); - if not Is_Success (Result) then + if not Result.Success then Report_Bad_Trace (Trace_File_Name, Result); - - -- If the file does not exist, do not try to Process it - -- further. - - if Result.Kind = Open_Error then - return; - end if; end if; case Kind is @@ -2015,7 +2006,7 @@ begin -- We can now read it and import its data Read_Source_Trace_File (Trace_File_Name, Result); - if not Is_Success (Result) then + if not Result.Success then Report_Bad_Trace (Trace_File_Name, Result); end if; @@ -2085,7 +2076,7 @@ begin TF : Trace_File_Type; begin Read_Trace_File (Trace_Filename, TF, Result, Base); - if not Is_Success (Result) then + if not Result.Success then Report_Bad_Trace (Trace_Filename, Result); return; end if; @@ -2165,7 +2156,7 @@ begin Result : out Read_Result) is begin Check_Trace_File_From_Exec (TF, Result); - if not Is_Success (Result) then + if not Result.Success then return; end if; Exe_File := Open_Exec_For_Trace @@ -2257,7 +2248,7 @@ begin Result : Read_Result; begin Read_Trace_File (Trace_Filename, TF, Result); - if not Is_Success (Result) then + if not Result.Success then Report_Bad_Trace (Trace_Filename, Result); return; end if; diff --git a/tools/gnatcov/instrument-input_traces.adb b/tools/gnatcov/instrument-input_traces.adb index 44eca3dca..0067dc593 100644 --- a/tools/gnatcov/instrument-input_traces.adb +++ b/tools/gnatcov/instrument-input_traces.adb @@ -31,7 +31,6 @@ with GNAT.Byte_Swapping; use GNAT.Byte_Swapping; with Hex_Images; with Outputs; -with Traces_Files; use Traces_Files; package body Instrument.Input_Traces is @@ -104,7 +103,7 @@ package body Instrument.Input_Traces is EOF : out Boolean; Result : in out Read_Result; Error_If_EOF : Boolean := True) - with Pre => Is_Success (Result); + with Pre => Result.Success; -- Try to read Size bytes from Stream. Put the result in Stream.Buffer and -- Stream.Buffer_Last. By default, set EOF to False (see below). -- @@ -142,7 +141,7 @@ package body Instrument.Input_Traces is (Stream : in out Binary_Stream; File_Header : out Trace_File_Header; Result : in out Read_Result) - with Pre => Is_Success (Result); + with Pre => Result.Success; -- Read a trace file header from Stream and store it in File_Header. Set -- Result to an error if something wrong happened. @@ -152,7 +151,7 @@ package body Instrument.Input_Traces is Kind : out Supported_Info_Kind; Data : out GNAT.OS_Lib.String_Access; Result : in out Read_Result) - with Pre => Is_Success (Result); + with Pre => Result.Success; -- Read a trace info entry from Stream. Return an error if something wrong -- happened, otherwise put its kind in Kind and allocate a string in Data -- to hold the data associated to this entry. @@ -163,7 +162,7 @@ package body Instrument.Input_Traces is Entry_Header : out Trace_Entry_Header; Trace_Entry : out Trace_Entry_Elements; Result : in out Read_Result) return Boolean - with Pre => Is_Success (Result); + with Pre => Result.Success; -- Try to read a trace entry header from Stream. -- -- If Stream already reached EOF, just return False. Otherwise, decode it @@ -179,7 +178,7 @@ package body Instrument.Input_Traces is Raw_Buffer : Bytes_Array; Buffer : out Coverage_Buffer; Result : in out Read_Result) - with Pre => Is_Success (Result); + with Pre => Result.Success; -- Decode the given Raw_Buffer according to the given Encoding, and but the -- result in Buffer. If all goes well, keep Result as it is, otherwise set -- it to the corresponding error information. @@ -329,7 +328,7 @@ package body Instrument.Input_Traces is begin Read_Bytes (Stream, File_Header'Size / 8, Ignored_EOF, Result); - if not Is_Success (Result) then + if not Result.Success then return; end if; @@ -402,7 +401,7 @@ package body Instrument.Input_Traces is Read_Bytes (Stream, Trace_Info_Header'Size / 8, Ignored_EOF, Result); - if not Is_Success (Result) then + if not Result.Success then return; end if; @@ -445,7 +444,7 @@ package body Instrument.Input_Traces is begin Read_Bytes (Stream, Read_Size, Ignored_EOF, Result); end; - if not Is_Success (Result) then + if not Result.Success then Free (Data); return; end if; @@ -474,7 +473,7 @@ package body Instrument.Input_Traces is Read_Bytes (Stream, Entry_Header'Size / 8, EOF, Result, Error_If_EOF => False); - if EOF or else not Is_Success (Result) then + if EOF or else not Result.Success then return False; end if; @@ -559,7 +558,7 @@ package body Instrument.Input_Traces is System.Storage_Elements.Storage_Offset (Offset))); begin Read_Bytes (Stream, Data_Size, EOF, Result); - if not Is_Success (Result) then + if not Result.Success then return False; end if; @@ -626,13 +625,13 @@ package body Instrument.Input_Traces is Decision_Buffer : Coverage_Buffer_Access; MCDC_Buffer : Coverage_Buffer_Access; begin - Result := (Kind => Success); + Result := (Success => True); -- Try to open the file Stream.File := Open_Read (Filename, Binary); if Stream.File = Invalid_FD then - Create_Error (Result, Filename); + Create_Error (Result, "cannot open " & Filename); return; end if; Stream.Offset := 0; @@ -640,7 +639,7 @@ package body Instrument.Input_Traces is -- Read the trace file header Read_Trace_File_Header (Stream, File_Header, Result); - if not Is_Success (Result) then + if not Result.Success then goto Cleanup_And_Exit; end if; @@ -652,7 +651,7 @@ package body Instrument.Input_Traces is Data : GNAT.OS_Lib.String_Access; begin Read_Trace_Info (Stream, File_Header, Kind, Data, Result); - if not Is_Success (Result) then + if not Result.Success then goto Cleanup_And_Exit; end if; @@ -727,7 +726,7 @@ package body Instrument.Input_Traces is Statement_Buffer (0 .. Last_Bit (Entry_Header.Statement_Bit_Count)), Result); - if not Is_Success (Result) then + if not Result.Success then goto Cleanup_And_Exit; end if; @@ -737,7 +736,7 @@ package body Instrument.Input_Traces is Decision_Buffer (0 .. Last_Bit (Entry_Header.Decision_Bit_Count)), Result); - if not Is_Success (Result) then + if not Result.Success then goto Cleanup_And_Exit; end if; @@ -746,7 +745,7 @@ package body Instrument.Input_Traces is Raw_MCDC_Buffer, MCDC_Buffer (0 .. Last_Bit (Entry_Header.MCDC_Bit_Count)), Result); - if not Is_Success (Result) then + if not Result.Success then goto Cleanup_And_Exit; end if; @@ -918,7 +917,7 @@ package body Instrument.Input_Traces is begin Read_Source_Trace_File (Filename, Result); - if not Is_Success (Result) then + if not Result.Success then Outputs.Fatal_Error (+Result.Error); end if; end Dump_Source_Trace_File; diff --git a/tools/gnatcov/traces_files.adb b/tools/gnatcov/traces_files.adb index b5f596639..0e0de600e 100644 --- a/tools/gnatcov/traces_files.adb +++ b/tools/gnatcov/traces_files.adb @@ -287,7 +287,7 @@ package body Traces_Files is procedure Success_Or_Fatal_Error (Filename : String; Result : Read_Result) is begin - if not Is_Success (Result) then + if not Result.Success then Fatal_Error (Filename & ": " & (+Result.Error)); end if; end Success_Or_Fatal_Error; @@ -385,11 +385,11 @@ package body Traces_Files is -- Return whether the given Magic matches the first bytes in Buffer begin - Result := (Kind => Success); + Result := (Success => True); Kind := Binary_Trace_File; if Fd = Invalid_FD then - Create_Open_Error (Result, Filename); + Create_Error (Result, "cannot open " & Filename); return; end if; @@ -461,7 +461,7 @@ package body Traces_Files is -- there. Check_Header (Desc, Hdr, Result); - if not Is_Success (Result) then + if not Result.Success then return; end if; @@ -481,7 +481,7 @@ package body Traces_Files is else Decode_Trace_Header (Hdr.all, Trace_File, Desc, Result); - if not Is_Success (Result) then + if not Result.Success then return; end if; end if; @@ -497,12 +497,12 @@ package body Traces_Files is -- kind as a second header. Append_Info_Entries_From_Descriptor (Desc, Trace_File, Result); - if For_Trace_Output or else not Is_Success (Result) then + if For_Trace_Output or else not Result.Success then return; end if; Check_Header (Desc, Hdr, Result); - if not Is_Success (Result) then + if not Result.Success then return; end if; @@ -647,7 +647,7 @@ package body Traces_Files is Result := Read_Success; Read_Info_Entries (Desc, Result); - if not Is_Success (Result) then + if not Result.Success then return; end if; @@ -927,7 +927,7 @@ package body Traces_Files is Open_Trace_File (Filename, Desc, Trace_File); Trace_File.Filename := +Filename; Process_Info_Entries (Trace_File, Result); - if not Is_Success (Result) then + if not Result.Success then return; end if; @@ -942,7 +942,7 @@ package body Traces_Files is loop Read_Trace_Entry (Desc, EOF, Raw_Entry, Result); - if not Is_Success (Result) then + if not Result.Success then return; elsif EOF then Create_Error (Result, "No 'loadaddr' special trace entry"); @@ -986,7 +986,7 @@ package body Traces_Files is loop Read_Trace_Entry (Desc, EOF, Raw_Entry, Result); - if not Is_Success (Result) then + if not Result.Success then return; end if; exit when EOF; @@ -1012,7 +1012,7 @@ package body Traces_Files is First, Last : Pc_Type; begin Read_SO_Info (Desc, Filename, Sig, Code_Size, Result); - if not Is_Success (Result) then + if not Result.Success then return; end if; First := Raw_Entry.Pc; @@ -1770,11 +1770,7 @@ package body Traces_Files is procedure Create_Error (Result : out Read_Result; Error : String) is begin - Result := (Kind => Other_Error, Error => +Error); + Result := (Success => False, Error => +Error); end Create_Error; - procedure Create_Open_Error (Result : out Read_Result; Filename : String) is - begin - Result := (Kind => Open_Error, Error => +("cannot open " & Filename)); - end Create_Open_Error; end Traces_Files; diff --git a/tools/gnatcov/traces_files.ads b/tools/gnatcov/traces_files.ads index ac555d9af..0bad472eb 100644 --- a/tools/gnatcov/traces_files.ads +++ b/tools/gnatcov/traces_files.ads @@ -32,21 +32,12 @@ with Traces; package Traces_Files is - type Read_Result_Kind is (Success, Open_Error, Other_Error); - - subtype Error_Read_Result_Kind is - Read_Result_Kind range Open_Error .. Other_Error; - - subtype Recoverable_Read_Result_Kind is - Read_Result_Kind range Open_Error .. Open_Error; - -- Errors that are actually recoverable which should only trigger a warning - - type Read_Result (Kind : Read_Result_Kind := Success) is record - case Kind is - when Success => - null; - when others => + type Read_Result (Success : Boolean := True) is record + case Success is + when False => Error : Unbounded_String; + when True => + null; end case; end record; -- Description of the result of a trace read operation: either it was @@ -57,9 +48,6 @@ package Traces_Files is -- following procedure enables to probe a trace file in order to determine -- if it's a binary trace file or a source trace file. - function Is_Success (R : Read_Result) return Boolean is - (R.Kind = Success); - type Any_Accepted_Trace_Kind is (Unknown, Binary_Trace_File, Source_Trace_File, All_Trace_Files); -- We normally do not allow to mix trace kinds, but in case this should be @@ -99,10 +87,9 @@ package Traces_Files is type Trace_File_Descriptor is limited private; -- Descriptor to read or write a trace file - Read_Success : constant Read_Result := (Kind => Success); + Read_Success : constant Read_Result := (Success => True); procedure Create_Error (Result : out Read_Result; Error : String); - procedure Create_Open_Error (Result : out Read_Result; Filename : String); -- Shortcut to create a Read_Result that contains an error procedure Success_Or_Fatal_Error (Filename : String; Result : Read_Result); From 12b7600253c851f49bf771c2329ba2f4b50a18fa Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 20 Mar 2025 11:31:03 +0100 Subject: [PATCH 1148/1483] traces_files: Make --keep-reading-traces raise a warning instead of error --- testsuite/tests/RC04-030-bad-trace/test.py | 15 +++++++++++---- tools/gnatcov/command_line.ads | 3 ++- tools/gnatcov/gnatcov_bits_specific.adb | 2 +- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/testsuite/tests/RC04-030-bad-trace/test.py b/testsuite/tests/RC04-030-bad-trace/test.py index 02c3388ed..bfbd2886a 100644 --- a/testsuite/tests/RC04-030-bad-trace/test.py +++ b/testsuite/tests/RC04-030-bad-trace/test.py @@ -74,15 +74,22 @@ def gnatcov_coverage(keep_reading_traces): argv.append("--keep-reading-traces") p = xcov(argv + tracefiles, out=log_file, register_failure=False) - thistest.fail_if( - p.status == 0, '"gnatcov coverage" status code is 0 (error expected)' - ) + if keep_reading_traces: + thistest.fail_if( + p.status != 0, '"gnatcov coverage" status code is non-zero.' + ) + else: + thistest.fail_if( + p.status == 0, + '"gnatcov coverage" status code is zero (expected error).', + ) coverage_log = contents_of(log_file).strip() + diag = "warning" if keep_reading_traces else "gnatcov" expected_log = re.compile( # Regexp to accommodate output differences between the various # supported platforms. - "[^\n]*gnatcov[^\n]*: traces[/\\\\]main_b[^\n]*.trace: file truncated" + f"[^\n]*{diag}[^\n]*: traces[/\\\\]main_b[^\n]*.trace: file truncated" ) thistest.fail_if( not expected_log.match(coverage_log), diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index deb5bb9f2..f758887b1 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -564,7 +564,8 @@ package Command_Line is Help => "When an error occurs while reading a trace file," & " skip it and keep reading other trace files until a" & " coverage report can be produced. Note that this" - & " makes gnatcov exit with an error status.", + & " raises a warning, but does not make gnatcov exit" + & " with an error status.", Commands => (Cmd_Coverage => True, others => False), Internal => False), diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index c12aa40f7..11463671a 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1185,7 +1185,7 @@ procedure GNATcov_Bits_Specific is Message : constant String := Trace_Filename & ": " & (+Result.Error); begin if Keep_Reading_Traces then - Outputs.Error (Message); + Outputs.Warn (Message); else Outputs.Fatal_Error (Message); end if; From 517924d5c3f86130cca8c9916c0fd6c1d46cf744 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 14 Mar 2025 12:42:08 +0100 Subject: [PATCH 1149/1483] rts: Create observability function in the runtime --- tools/gnatcov/rts/gnatcov_rts_c-buffers.c | 54 +++++++++++++++++++++++ tools/gnatcov/rts/gnatcov_rts_c-buffers.h | 9 ++++ 2 files changed, 63 insertions(+) diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c index 2a6a32e32..f97e1f229 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.c +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.c @@ -22,6 +22,60 @@ #include #include +uint64_t +gnatcov_rts_sum_buffer_bits ( + const struct gnatcov_rts_coverage_buffers_group_array *arr) +{ + if (arr == NULL) + return 0; + + unsigned i, j, sum = 0; + int x; + for (i = 0; i < arr->length; i++) + { + const struct gnatcov_rts_coverage_buffers_group *buf_grp + = arr->groups[i]; + + if (buf_grp == NULL) + return 0; + + for (j = 0; j < buf_grp->length; j++) + { + const struct gnatcov_rts_coverage_buffers *unit_bufs + = buf_grp->buffers[j]; + + /* Statement buffer */ + if (unit_bufs->statement != NULL) + { + for (x = 0; x < unit_bufs->statement_last_bit + 1; x++) + { + sum += unit_bufs->statement[x]; + } + } + + /* Decision buffer */ + if (unit_bufs->decision != NULL) + { + for (x = 0; x < unit_bufs->decision_last_bit + 1; x++) + { + sum += unit_bufs->decision[x]; + } + } + + /* MCDC buffer */ + if (unit_bufs->mcdc != NULL) + { + for (x = 0; x < unit_bufs->mcdc_last_bit + 1; x++) + { + sum += unit_bufs->mcdc[x]; + } + } + } + } + + return sum; +} + void gnatcov_rts_reset_buffers (const struct gnatcov_rts_coverage_buffers *buffs) { diff --git a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h index cdb6f57df..5684a9ba1 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-buffers.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-buffers.h @@ -130,6 +130,15 @@ extern "C" const struct gnatcov_rts_coverage_buffers_group **groups; }; + /*****************/ + /* Observability */ + /*****************/ + + /* Return the sum of all bits in the given buffers. + A higher number means a higher coverage. */ + uint64_t gnatcov_rts_sum_buffer_bits ( + const struct gnatcov_rts_coverage_buffers_group_array *arr); + /*********************/ /* Clear subprograms */ /*********************/ From 2b6b3d65e131dc81cca35f25bb56c5da923e8fef Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 14 Mar 2025 12:44:25 +0100 Subject: [PATCH 1150/1483] instr(ada): Generate observability hook files --- tools/gnatcov/instrument-ada_unit.adb | 61 +++++++++++++++++++++++++++ tools/gnatcov/instrument-ada_unit.ads | 4 ++ tools/gnatcov/instrument-common.ads | 6 +++ tools/gnatcov/instrument-projects.adb | 3 ++ 4 files changed, 74 insertions(+) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 5654257ee..059f9f937 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -11116,6 +11116,67 @@ package body Instrument.Ada_Unit is File.Put_Line ("end " & Unit_Name & ";"); end Emit_Buffers_List_Unit; + ----------------------------- + -- Emit_Observability_Unit -- + ----------------------------- + + overriding procedure Emit_Observability_Unit + (Self : in out Ada_Instrumenter_Type; + Prj : in out Prj_Desc) + is + + pragma Unreferenced (Self); + + Buf_List_Unit : constant Ada_Qualified_Name := CU_Name_For_Unit + (Buffers_List_Unit (Prj.Prj_Name), GNATCOLL.Projects.Unit_Spec).Unit; + Buf_List_Unit_Name : constant String := To_Ada (Buf_List_Unit); + + Obs_Unit : constant Ada_Qualified_Name := + Buf_List_Unit & Ada_Identifier_Vectors.To_Vector + (To_Unbounded_String ("Observe"), 1); + Obs_Unit_Name : constant String := To_Ada (Obs_Unit); + + Obs_Spec_Filename : constant String := To_Filename + (Prj, + Ada_Language, + CU_Name_For_Unit (Obs_Unit, GNATCOLL.Projects.Unit_Spec)); + Obs_Body_Filename : constant String := To_Filename + (Prj, + Ada_Language, + CU_Name_For_Unit (Obs_Unit, GNATCOLL.Projects.Unit_Body)); + + Spec_File : Text_Files.File_Type; + Body_File : Text_Files.File_Type; + begin + Create_File (Prj, Spec_File, Obs_Spec_Filename); + Create_File (Prj, Body_File, Obs_Body_Filename); + + Spec_File.Put_Line ("package " & Obs_Unit_Name & " is"); + Spec_File.Put_Line (" function Sum_Buffer_Bits return Positive;"); + Spec_File.Put_Line ("end " & Obs_Unit_Name & ";"); + + Body_File.Put_Line ("with Interfaces.C;"); + Body_File.Put_Line + ("with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists;"); + Body_File.New_Line; + Body_File.Put_Line ("package body " & Obs_Unit_Name & " is"); + Body_File.Put_Line (" function Sum_Buffer_Bits return Positive is"); + Body_File.Put_Line (" function Sum_Buffer_Bits_C"); + Body_File.Put_Line + (" (C_List : GNATcov_RTS_Coverage_Buffers_Group_Array)"); + Body_File.Put_Line (" return Interfaces.C.unsigned_long;"); + Body_File.Put_Line + ("pragma Import (C, Sum_Buffer_Bits_C," + & " ""gnatcov_rts_sum_buffer_bits"");"); + Body_File.Put_Line (" begin"); + Body_File.Put_Line + (" return Positive(Sum_Buffer_Bits_C (" + & Buf_List_Unit_Name & ".C_List));"); + Body_File.Put_Line (" end;"); + Body_File.Put_Line ("end " & Obs_Unit_Name & ";"); + + end Emit_Observability_Unit; + --------------------------------- -- Save_Config_Pragmas_Mapping -- --------------------------------- diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index 53d54d188..f9abb2fbf 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -135,6 +135,10 @@ package Instrument.Ada_Unit is Instr_Units : Unit_Sets.Set; Prj : Prj_Desc); + overriding procedure Emit_Observability_Unit + (Self : in out Ada_Instrumenter_Type; + Prj : in out Prj_Desc); + procedure Save_Config_Pragmas_Mapping (Filename : String); -- Create a configuration pragmas mapping for the loaded project and write -- a JSON description file of it to Filename. diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 1d8730168..84f7c393b 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -555,6 +555,12 @@ package Instrument.Common is -- not stub instrumenters (e.g. the one declared in instrument-c__stub) in -- which case it will raise a Program_Error. + procedure Emit_Observability_Unit + (Self : in out Language_Instrumenter; + Prj : in out Prj_Desc) is null; + -- Emit in the root project a file that exposes live coverage observability + -- features, such as the number of bits set in the buffers. + function New_File (Prj : Prj_Desc; Name : String) return String; -- Compute the path to the file to create in Self.Output_Dir diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index c0a048941..acaff44e4 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -1571,6 +1571,9 @@ begin then Instrumenters (Lang).Emit_Buffers_List_Unit (Instr_Units, Root_Project_Info.Desc); + + Instrumenters (Lang).Emit_Observability_Unit + (Root_Project_Info.Desc); exit; end if; end loop; From c906f85fdbfde987ebfa7cb3f21e004b646d572a Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 19 Mar 2025 12:55:43 +0100 Subject: [PATCH 1151/1483] test: Add test for live-observability feature --- .../tests/345-live-observability/src/main.adb | 26 ++++++++++++ .../tests/345-live-observability/test.opt | 1 + .../tests/345-live-observability/test.py | 41 +++++++++++++++++++ testsuite/tests/instr-cov/ext_gpr/test.py | 2 + 4 files changed, 70 insertions(+) create mode 100644 testsuite/tests/345-live-observability/src/main.adb create mode 100644 testsuite/tests/345-live-observability/test.opt create mode 100644 testsuite/tests/345-live-observability/test.py diff --git a/testsuite/tests/345-live-observability/src/main.adb b/testsuite/tests/345-live-observability/src/main.adb new file mode 100644 index 000000000..de698ed8b --- /dev/null +++ b/testsuite/tests/345-live-observability/src/main.adb @@ -0,0 +1,26 @@ +with Ada.Text_IO; use Ada.Text_IO; +with GCVRT.Gen.Observe; use GCVRT.Gen.Observe; + +procedure Main is + N : Integer; +begin + -- Two statements executed + -- - the one for the declaration of N + -- - the one for this specific statement + Put_Line ("First: " & Positive'Image (Sum_Buffer_Bits)); + + N := 5; + + -- 2 two statements were executed since last call. + Put_Line ("Second: " & Positive'Image (Sum_Buffer_Bits)); + + if N > 3 then + Put_Line ("Foo"); + Put_Line ("Bar"); + else + Put_Line ("Baz"); + end if; + + -- 4 more statements were executed (including the if stmt). + Put_Line ("Third: " & Positive'Image (Sum_Buffer_Bits)); +end Main; diff --git a/testsuite/tests/345-live-observability/test.opt b/testsuite/tests/345-live-observability/test.opt new file mode 100644 index 000000000..31322518a --- /dev/null +++ b/testsuite/tests/345-live-observability/test.opt @@ -0,0 +1 @@ +!src-traces DEAD Test is specific to source traces diff --git a/testsuite/tests/345-live-observability/test.py b/testsuite/tests/345-live-observability/test.py new file mode 100644 index 000000000..1a9dbb847 --- /dev/null +++ b/testsuite/tests/345-live-observability/test.py @@ -0,0 +1,41 @@ +""" +This test ensures that the live observability of coverage data provides +sound data. +""" + +import re + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +wd = Wdir("tmp_") + + +build_and_run( + gprsw=GPRswitches( + root_project=gprfor(mains=["main.adb"], srcdirs=["../src"]), + ), + mains=["main"], + covlevel="stmt", + extra_gprbuild_args=[], + extra_coverage_args=[], +) + +OUTPUT = contents_of("main_output.txt") + +thistest.fail_if_no_match( + "Wrong first buffer sum", re.compile(r".*First: *2.*", re.S), OUTPUT +) + +thistest.fail_if_no_match( + "Wrong second buffer sum", re.compile(r".*Second: *4.*", re.S), OUTPUT +) + +thistest.fail_if_no_match( + "Wrong third buffer sum", re.compile(r".*Third: *8.*", re.S), OUTPUT +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/ext_gpr/test.py b/testsuite/tests/instr-cov/ext_gpr/test.py index accfeb5a2..42f9ff842 100644 --- a/testsuite/tests/instr-cov/ext_gpr/test.py +++ b/testsuite/tests/instr-cov/ext_gpr/test.py @@ -29,6 +29,8 @@ r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-bz[a-f0-9]{8}\.ads", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-p_ext2-observe\.adb", + r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-p_ext2-observe\.ads", r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-p_ext2\.ads", r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", r"obj-p_ext2/p_ext2-gnatcov-instr/gcvrt-pz[a-f0-9]{8}\.ads", From 6eb0c63c839032f4dc537e246cdf05bb3c164015 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 31 Jul 2024 11:59:49 +0200 Subject: [PATCH 1152/1483] Make runtime code warning-free with -std=c89 The endif-labels warning warns on this code excerpt, so remove the tokens after the endif directive. --- tools/gnatcov/rts/gnatcov_rts_c-memory.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/rts/gnatcov_rts_c-memory.h b/tools/gnatcov/rts/gnatcov_rts_c-memory.h index da4e72875..f9652a0ab 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-memory.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-memory.h @@ -41,4 +41,4 @@ extern "C" #ifdef __cplusplus } #endif -#endif // GNATCOV_RTS_C_MEMORY_H +#endif From ba060bf5c3cce774dfa5cc10a30616f61b6c8f5c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 29 Jul 2024 13:38:03 +0200 Subject: [PATCH 1153/1483] testsuite: check warnings in gnatcov output Check warnings for every gnatcov command rather than for "gnatcov instrument" only. Fix the fallout regressions by adapting the testcases. Also remove unused auto_languages parameter from the xcov function. --- .../GPR/Robustness/BadUnitInAttr/test.py | 3 +- .../GPR/Robustness/BadUnitInSwitch/test.py | 3 +- .../GPR/Robustness/MissingLI/test.py | 2 +- .../GPR/Robustness/NoContribPrj/test.py | 3 +- .../GPR/Robustness/SourcesAttr/test.py | 1 + .../GPR/Robustness/UnitNotInProjects/test.py | 3 +- testsuite/SCOV/instr.py | 57 +++---------- testsuite/SCOV/minicheck.py | 9 ++- testsuite/SUITE/tutils.py | 81 +++++++++++++++---- .../14-unused-separate/uncompilable/test.py | 1 + testsuite/tests/15-non-instr-cons/test.py | 8 +- testsuite/tests/354-source-encoding/test.py | 6 +- testsuite/tests/IA21-009-nested-scos/test.opt | 1 + testsuite/tests/IA21-009-nested-scos/test.py | 2 +- testsuite/tests/L613-012/test.opt | 1 + testsuite/tests/L613-012/test.py | 8 +- testsuite/tests/Q327-016-glob-ignore/test.py | 1 + .../tests/S527-004-ckpt-no-level/test.py | 1 + .../S619-014-tag-provider-mismatch/test.py | 1 + testsuite/tests/TB24-022-missing-sid/test.py | 1 + .../U204-029-source-rebase/test_support.py | 1 + testsuite/tests/VB18-035-default-opts/test.py | 6 +- .../VB21-022-sid-srctrace-mismatch/test.py | 2 +- .../tests/excluded_unit_imported_prj/test.py | 1 + .../tests/ext_annotations/buffers/test.py | 2 + .../ext_annotations/gen/invalidation/test.py | 1 + .../gen/selective_cov/C/test.py | 3 +- testsuite/tests/ignored-c-header/test.py | 1 + .../223-selective-instr/unsupported/test.py | 1 + .../tests/instr-cov/339-nostdlib/test.py | 1 + .../tests/instr-cov/384-SID-cleanup/test.py | 1 + .../386-setup-invalid-target/test.py | 1 - .../tests/instr-cov/base64_prefix/test.py | 3 +- testsuite/tests/instr-cov/consistency/test.py | 4 + .../main_autodump/disabled_lang/test.py | 2 - testsuite/tests/instr-cov/orphan-unit/test.py | 1 + .../basic_cmake/test.py | 1 + .../cmake_include_switch/test.py | 1 + .../cmake_lib/test.py | 1 + 39 files changed, 147 insertions(+), 80 deletions(-) create mode 100644 testsuite/tests/IA21-009-nested-scos/test.opt create mode 100644 testsuite/tests/L613-012/test.opt diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py index 0781acae8..18deed2ea 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py @@ -21,8 +21,9 @@ ), covlevel="stmt", mains=["main"], - tolerate_instrument_messages="no unit.*in project", + tolerate_instrument_messages="no unit .* in project", extra_coverage_args=["-axcov"], + tolerate_coverage_messages="no unit .* in project", ) log_file = ( diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py index 4e17fc823..ed8b714a5 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py @@ -18,8 +18,9 @@ ), covlevel="stmt", mains=["main"], - tolerate_instrument_messages="no unit.*in the projects of interest", + tolerate_instrument_messages="no unit .* in the projects of interest", extra_coverage_args=["-axcov"], + tolerate_coverage_messages="no unit .* in the projects of interest", ) log_file = ( diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py index 379c18e97..176780fc8 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py @@ -41,7 +41,7 @@ what = "ALI" log_file = "coverage.log" -xcov(xcov_args, out=log_file) +xcov(xcov_args, out=log_file, tolerate_messages=".") thistest.fail_if_not_equal( "gnatcov output", "warning: no {} file found for unit helper".format(what), diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py index aaaee4e9c..05f288ed9 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py @@ -103,8 +103,9 @@ def run_test( covlevel="stmt", mains=["main"], gpr_obj_dir="obj-main", - tolerate_instrument_messages="project.*provides no unit", + tolerate_instrument_messages="project .* provides no unit", extra_coverage_args=["-axcov"], + tolerate_coverage_messages="project .* provides no unit", ) log_file = ( diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py index 9a709f28a..19d529234 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py @@ -44,6 +44,7 @@ def try_one(subdir, extra_covargs, xreports, xwarnings): covlevel="stmt", mains=["test_t"], extra_coverage_args=["--annotate=xcov"] + extra_covargs, + tolerate_coverage_messages=".", ) check_xcov_reports("obj", xreports) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py index 2c1057944..bd18cb2f2 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py @@ -43,8 +43,9 @@ covlevel="stmt", mains=["main"], gpr_obj_dir="obj-main", - tolerate_instrument_messages="no unit.*in the projects", + tolerate_instrument_messages="no unit .* in the projects", extra_coverage_args=["-axcov"], + tolerate_coverage_messages="no unit .* in the projects", ) log_file = ( diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 9302be963..67452651f 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -7,7 +7,7 @@ from SUITE.context import thistest from SUITE.control import env -from SUITE.cutils import contents_of, copy_to_dir, ext, indent +from SUITE.cutils import contents_of, ext, copy_to_dir from SUITE.tutils import RUNTIME_INFO, GNATCOV_INFO, locate_gpr_file, xcov @@ -58,7 +58,6 @@ def xcov_instrument( register_failure=True, auto_config_args=True, auto_target_args=True, - auto_languages=True, ): """ Run "gnatcov instrument" on a project. @@ -87,7 +86,6 @@ def xcov_instrument( :param bool register_failure: See SUITE.tutils.xcov. :param bool auto_config_args: See SUITE.tutils.xcov. :param bool auto_target_args: See SUITE.tutils.xcov. - :param bool auto_languages: See SUITE.tutils.xcov. See SUITE.tutils.xcov for the other supported options. """ @@ -137,20 +135,9 @@ def xcov_instrument( if thistest.options.block: args.append("--instrument-block") - out = out or "instrument.log" - result = xcov( - args, - out=out, - err=err, - register_failure=register_failure, - auto_config_args=auto_config_args, - auto_target_args=auto_target_args, - auto_languages=auto_languages, - ) - # When no message is to be tolerated, fallback to an actual regexp # that will never match: - re_tolerate_messages = tolerate_messages or "__NEVER_IN_A_WARNING___" + re_tolerate_messages = tolerate_messages or "" # For qualification purposes, tolerate possible warnings about # inexistant object dirs from older gnatcov versions, typically @@ -163,36 +150,16 @@ def xcov_instrument( for mre in ["object directory.*not found", re_tolerate_messages] ) - if register_failure: - output = contents_of(out) - - # Check for unexpected messages. Beware that the "warning:" - # indication at least is not necessarily at the beginning of - # a line, as in - # - # app.gpr:4:23: warning: object directory "obj" not found - - messages = re.findall( - pattern=r"(?:!!!|\*\*\*|warning:).*$", - string=output, - flags=re.MULTILINE, - ) - - unexpected_messages = [ - w - for w in messages - if not re.search(pattern=re_tolerate_messages, string=w) - ] - thistest.fail_if( - unexpected_messages, - f"Unexpected messages in the output of 'gnatcov instrument':" - f"\n{indent(output)}" - + ( - f"\n(allowed: {tolerate_messages})" - if tolerate_messages - else "" - ), - ) + out = out or "instrument.log" + result = xcov( + args, + out=out, + err=err, + register_failure=register_failure, + auto_config_args=auto_config_args, + auto_target_args=auto_target_args, + tolerate_messages=re_tolerate_messages, + ) return result diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 58d4f36af..712107116 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -68,7 +68,6 @@ def build_and_run( program_env=None, tolerate_instrument_messages=None, exec_args=None, - auto_languages=True, manual_prj_name=None, auto_config_args=True, ): @@ -142,7 +141,6 @@ def build_and_run( output. :param None|list[str] exec_args: List of arguments to pass to the executable. This will only work for native configurations. - :param bool auto_languages: See SUITE.tutils.xcov. :param None|str manual_prj_name: When the dump trigger is manual, several traces files (one per project) can be emitted if there are dump buffers procedure calls in at least two distinct projects. This is the name of @@ -283,7 +281,6 @@ def gprbuild_wrapper(root_project): out="instrument.log", register_failure=register_failure, tolerate_messages=tolerate_instrument_messages, - auto_languages=auto_languages, auto_config_args=auto_config_args, ) gprbuild_wrapper(gprsw.root_project) @@ -431,6 +428,7 @@ def build_run_and_coverage( err=None, register_failure=True, auto_config_args=True, + tolerate_coverage_messages=None, **kwargs, ): """ @@ -442,6 +440,10 @@ def build_run_and_coverage( `out` and `err` are forwarded to `xcov`, `register_failure` and `auto_config_args` are reported to `xcov` and `build_and_run`, other arguments are forwarded to `build_and_run`. + + If tolerate_coverage_messages is not None, filter out error or warning + messages from the "gnatcov coverage" output matching the regular + expression. """ xcov_args = build_and_run( register_failure=register_failure, @@ -454,6 +456,7 @@ def build_run_and_coverage( out=out, err=err, register_failure=register_failure, + tolerate_messages=tolerate_coverage_messages, ) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index d63fc532f..472376d2a 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -34,12 +34,12 @@ ) from SUITE.context import ROOT_DIR, thistest - # Then mind our own business from SUITE.cutils import ( FatalError, contents_of, + indent, list_to_file, text_to_file, to_list, @@ -874,20 +874,27 @@ def xcov( auto_config_args=True, auto_target_args=True, force_project_args=False, - auto_languages=True, + tolerate_messages=None, ): """ - Run xcov with arguments ARGS, timeout control, valgrind control if - available and enabled, output directed to OUT and failure registration if - register_failure is True. Return the process status descriptor. ARGS may be - a list or a whitespace separated strings. - - If AUTO_LANGUAGES is True, the gnatcov sub-command is "instrument" and the - testsuite is not in qualification mode, automatically pass the - --restricted-to-languages argument to enable all the languages to test. - - See xcov_suite_args for the meaning of AUTO_*_ARGS and FORCE_PROJECT_ARGS - arguments. + Run "gnatcov". + + :param list[str] args: arguments to pass to gnatcov. + :param None|str out: if not None, redirect gnatcov output to out. + :param None|str err: if not None, redirect gnatcov error output to err. + :param None|str inp: if not None, redirect gnatcov input to inp. + :param None|dict[str, str] env: If not none, environment variables for the + program to run. + :param bool register_failure: If True, register execution failure. + :param bool auto_config_args: see xcov_suite_args. + :param bool auto_target_args: see xcov_suite_args. + :param bool force_project_args: see xcov_suite_args. + :param None|str tolerate_messages: If not None, a re pattern of warning + or error messsages tolerated in the tool output. Messages not matching + this pattern will cause a test failure when register_failure is True. + + :rtype: Run + :return: Process status descriptor for the gnatcov invocation. """ # Defensive code: running "gnatcov setup" with no prefix will install @@ -941,6 +948,43 @@ def xcov( for_pgm=(covcmd == "run"), ) + # When no message is to be tolerated, fallback to an actual regexp + # that will never match: + re_tolerate_messages = tolerate_messages or "__NEVER_IN_A_WARNING___" + + # Do not check warnings when running the testsuite in binary traces mode, + # as it would require modifying / adapting too many tests. + if register_failure and thistest.options.trace_mode == "src": + output = contents_of(out) if out else p.out + + # Check for unexpected messages. Beware that the "warning:" + # indication at least is not necessarily at the beginning of + # a line, as in + # + # app.gpr:4:23: warning: object directory "obj" not found + + messages = re.findall( + pattern=r"(?:!!!|\*\*\*|warning:).*$", + string=output, + flags=re.MULTILINE, + ) + + unexpected_messages = [ + w + for w in messages + if not re.search(pattern=re_tolerate_messages, string=w) + ] + thistest.fail_if( + unexpected_messages, + f"Unexpected messages in the output of 'gnatcov {covcmd}':" + f"\n{indent(output)}" + + ( + f"\n(allowed: {tolerate_messages})" + if tolerate_messages + else "" + ), + ) + if thistest.options.enable_valgrind == "memcheck": memcheck_log = contents_of(MEMCHECK_LOG) thistest.fail_if( @@ -1008,6 +1052,7 @@ def xrun( register_failure=register_failure, auto_config_args=auto_config_args, auto_target_args=auto_target_args, + tolerate_messages=".", ) @@ -1271,6 +1316,7 @@ def xcov_annotate( register_failure=True, auto_config_args=True, auto_target_args=True, + tolerate_messages=None, ): """ Invoke "gnatcov annotate" with the correct arguments to generate @@ -1288,6 +1334,7 @@ def xcov_annotate( will be added. Defaults to None. :param list[str] | None extra_args: extra arguments passed on the command line. Defaults to None. + :param str | None tolerate_messages: see documentation of xcov. """ args = ["add-annotation"] args.extend(annotation.cmd_line_args()) @@ -1306,10 +1353,11 @@ def xcov_annotate( register_failure=register_failure, auto_config_args=auto_config_args, auto_target_args=auto_target_args, + tolerate_messages=tolerate_messages, ) -def generate_annotations(annotations, subdir=""): +def generate_annotations(annotations, subdir="", tolerate_messages=None): """ Setup a temporary working directory in which an annotation file will be generated from annotations, using gnatcov add-annotation @@ -1334,6 +1382,9 @@ def generate_annotations(annotations, subdir=""): # Generate the annotations for annotation in annotations: xcov_annotate( - annotation, annot_in_files=[annot_file], annot_out_file=annot_file + annotation, + annot_in_files=[annot_file], + annot_out_file=annot_file, + tolerate_messages=tolerate_messages, ) return annot_file diff --git a/testsuite/tests/14-unused-separate/uncompilable/test.py b/testsuite/tests/14-unused-separate/uncompilable/test.py index 89f6a7073..6f49980cc 100644 --- a/testsuite/tests/14-unused-separate/uncompilable/test.py +++ b/testsuite/tests/14-unused-separate/uncompilable/test.py @@ -22,6 +22,7 @@ covlevel="stmt", mains=["main"], extra_coverage_args=["--annotate=xcov"], + tolerate_coverage_messages="no ALI file found for unit pkg.bar", ) thistest.fail_if( diff --git a/testsuite/tests/15-non-instr-cons/test.py b/testsuite/tests/15-non-instr-cons/test.py index 50c57c057..9df736242 100644 --- a/testsuite/tests/15-non-instr-cons/test.py +++ b/testsuite/tests/15-non-instr-cons/test.py @@ -40,7 +40,13 @@ xcov(xcov_args + ["--save-checkpoint=test_f.ckpt", trace_f]) # Try to consolidate the checkpoint -xcov(xcov_args + ["-Ctest_t.ckpt", "-Ctest_f.ckpt", "-axcov"]) +xcov( + xcov_args + ["-Ctest_t.ckpt", "-Ctest_f.ckpt", "-axcov"], + tolerate_messages=( + "warning: Specifying units of interest through --units" + " has no effect on checkpoints" + ), +) check_xcov_reports("obj", {"pkg.ads.xcov": {"?": {10}, "+": {5, 6, 7}}}) diff --git a/testsuite/tests/354-source-encoding/test.py b/testsuite/tests/354-source-encoding/test.py index 7f33f2794..6bd3041c2 100644 --- a/testsuite/tests/354-source-encoding/test.py +++ b/testsuite/tests/354-source-encoding/test.py @@ -211,7 +211,11 @@ def check_report( argv = xcov_args + [f"--output-dir=out-{label}"] if encoding is not None: argv.append(f"--source-encoding={encoding}") - xcov(argv, out=log_file) + + tolerate_messages = ( + "|".join(expected_warnings) if expected_warnings else None + ) + xcov(argv, out=log_file, tolerate_messages=tolerate_messages) # Check that we have exacly the expected warnings thistest.fail_if_not_equal( diff --git a/testsuite/tests/IA21-009-nested-scos/test.opt b/testsuite/tests/IA21-009-nested-scos/test.opt new file mode 100644 index 000000000..d05c6047b --- /dev/null +++ b/testsuite/tests/IA21-009-nested-scos/test.opt @@ -0,0 +1 @@ +src-traces DEAD Test specific to binary traces diff --git a/testsuite/tests/IA21-009-nested-scos/test.py b/testsuite/tests/IA21-009-nested-scos/test.py index 80cf80068..b64d2441f 100644 --- a/testsuite/tests/IA21-009-nested-scos/test.py +++ b/testsuite/tests/IA21-009-nested-scos/test.py @@ -5,5 +5,5 @@ Wdir("tmp_") gprbuild(gprfor(["nested_same_sloc.adb"], srcdirs="../src")) -xcov(["map-routines", "--scos=obj/nested_same_sloc.ali"]) +xcov(["map-routines", "--scos=obj/nested_same_sloc.ali", "nested_same_sloc"]) thistest.result() diff --git a/testsuite/tests/L613-012/test.opt b/testsuite/tests/L613-012/test.opt new file mode 100644 index 000000000..d05c6047b --- /dev/null +++ b/testsuite/tests/L613-012/test.opt @@ -0,0 +1 @@ +src-traces DEAD Test specific to binary traces diff --git a/testsuite/tests/L613-012/test.py b/testsuite/tests/L613-012/test.py index 746b67b67..068f94870 100644 --- a/testsuite/tests/L613-012/test.py +++ b/testsuite/tests/L613-012/test.py @@ -6,7 +6,13 @@ wd = Wdir("tmp_") gprbuild("../app.gpr") -xcov(args="map-routines -P../app", out="xcov.out") +xcov( + args="map-routines -P../app ../obj/pak1.o", + out="xcov.out", + tolerate_messages=( + r"no unit PAK2 in project App \(coverage.units attribute\)" + ), +) output = contents_of("xcov.out") thistest.fail_if( diff --git a/testsuite/tests/Q327-016-glob-ignore/test.py b/testsuite/tests/Q327-016-glob-ignore/test.py index 8a7d56608..b8c2d0cd9 100644 --- a/testsuite/tests/Q327-016-glob-ignore/test.py +++ b/testsuite/tests/Q327-016-glob-ignore/test.py @@ -24,6 +24,7 @@ mains=["main"], ignored_source_files=["@" + ignore_list], extra_coverage_args=["-a", "xcov", "--output-dir=."], + tolerate_coverage_messages="no SID file found for unit", ) # Check we have the expected reports diff --git a/testsuite/tests/S527-004-ckpt-no-level/test.py b/testsuite/tests/S527-004-ckpt-no-level/test.py index b25540b79..72ae42210 100644 --- a/testsuite/tests/S527-004-ckpt-no-level/test.py +++ b/testsuite/tests/S527-004-ckpt-no-level/test.py @@ -28,6 +28,7 @@ p = xcov( ["coverage", "--annotate=xcov", "--checkpoint=my_checkpoint.ckpt"], out=log_file, + tolerate_messages="Coverage level not specified on the command line.*", ) diff --git a/testsuite/tests/S619-014-tag-provider-mismatch/test.py b/testsuite/tests/S619-014-tag-provider-mismatch/test.py index c0a0e94c9..196cb4f5d 100644 --- a/testsuite/tests/S619-014-tag-provider-mismatch/test.py +++ b/testsuite/tests/S619-014-tag-provider-mismatch/test.py @@ -36,6 +36,7 @@ "--output-dir=.", ], out="consolidate.log", + tolerate_messages=".", ) expected = ( diff --git a/testsuite/tests/TB24-022-missing-sid/test.py b/testsuite/tests/TB24-022-missing-sid/test.py index 62d156efd..74c123fd8 100644 --- a/testsuite/tests/TB24-022-missing-sid/test.py +++ b/testsuite/tests/TB24-022-missing-sid/test.py @@ -33,6 +33,7 @@ "-v", ], trace_mode="src", + tolerate_coverage_messages="no SID file found for unit p2", ) thistest.fail_if( diff --git a/testsuite/tests/U204-029-source-rebase/test_support.py b/testsuite/tests/U204-029-source-rebase/test_support.py index 7c6c23c79..15c0995a1 100644 --- a/testsuite/tests/U204-029-source-rebase/test_support.py +++ b/testsuite/tests/U204-029-source-rebase/test_support.py @@ -65,6 +65,7 @@ def consolidate_and_check( + [f"-C{checkpoint}" for checkpoint in checkpoints] + rebase_opts, out=log_filename, + tolerate_messages=".", ) if expect_failure: diff --git a/testsuite/tests/VB18-035-default-opts/test.py b/testsuite/tests/VB18-035-default-opts/test.py index 601dd6c84..a7ebddb4b 100644 --- a/testsuite/tests/VB18-035-default-opts/test.py +++ b/testsuite/tests/VB18-035-default-opts/test.py @@ -41,7 +41,11 @@ def check_log(command, log_file): # 2. Check the output of the coverage command while specifying an annotation # format, and check that the coverage report corresponds to a stmt level. cov_log = "coverage_no_level.log" -xcov(cov_args + ["-axcov"], out=cov_log) +xcov( + cov_args + ["-axcov"], + out=cov_log, + tolerate_messages="Coverage level not specified", +) check_log("coverage", cov_log) check_xcov_reports("obj", {"main.adb.xcov": {"+": {2, 5, 6}, "-": {8}}}) diff --git a/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py b/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py index bdf830005..f2b176db9 100644 --- a/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py +++ b/testsuite/tests/VB21-022-sid-srctrace-mismatch/test.py @@ -34,7 +34,7 @@ # info (i.e. code not covered). level_arg = xcov_args.index("--level=stmt+mcdc") xcov_args[level_arg] = "--level=stmt" -xcov(xcov_args, out="coverage.log") +xcov(xcov_args, out="coverage.log", tolerate_messages=".") thistest.fail_if_no_match( "'gnatcov coverage' output", r"warning: traces for body of main \(from main.*\.srctrace\) are" diff --git a/testsuite/tests/excluded_unit_imported_prj/test.py b/testsuite/tests/excluded_unit_imported_prj/test.py index cbfecd34b..7a007f7cf 100644 --- a/testsuite/tests/excluded_unit_imported_prj/test.py +++ b/testsuite/tests/excluded_unit_imported_prj/test.py @@ -27,6 +27,7 @@ mains=["test"], extra_coverage_args=["--annotate=xcov"], tolerate_instrument_messages="no unit .* in project", + tolerate_coverage_messages="no unit .* in project", ) warning_file = ( "coverage.log" diff --git a/testsuite/tests/ext_annotations/buffers/test.py b/testsuite/tests/ext_annotations/buffers/test.py index dc0f900a8..5ef7d4744 100644 --- a/testsuite/tests/ext_annotations/buffers/test.py +++ b/testsuite/tests/ext_annotations/buffers/test.py @@ -35,6 +35,8 @@ def run_one(tc_id, annotation_file, expected_results): gprsw=GPRswitches(prj), extra_instr_args=[ f"--external-annotations={annotation_file}", + ], + extra_args=[ "--units=Pkg", "--units=c_unit.c", "--units=cpp_unit.cpp", diff --git a/testsuite/tests/ext_annotations/gen/invalidation/test.py b/testsuite/tests/ext_annotations/gen/invalidation/test.py index 8b585e1b1..ffa90d1a5 100644 --- a/testsuite/tests/ext_annotations/gen/invalidation/test.py +++ b/testsuite/tests/ext_annotations/gen/invalidation/test.py @@ -93,6 +93,7 @@ "-axcov", f"--external-annotations={annotation_file}", ], + tolerate_coverage_messages="Stale annotation for main.*", out=coverage_log, ) diff --git a/testsuite/tests/ext_annotations/gen/selective_cov/C/test.py b/testsuite/tests/ext_annotations/gen/selective_cov/C/test.py index 6557a72ba..f22b89bc9 100644 --- a/testsuite/tests/ext_annotations/gen/selective_cov/C/test.py +++ b/testsuite/tests/ext_annotations/gen/selective_cov/C/test.py @@ -25,7 +25,8 @@ Cov_On("src/pkg.h", "7:3", None), Cov_Off("src/pkg.h", "11:3", None), Cov_On("src/pkg.h", "13:3", None), - ] + ], + tolerate_messages="--justification missing", ) thistest.options.consolidate = "checkpoints" diff --git a/testsuite/tests/ignored-c-header/test.py b/testsuite/tests/ignored-c-header/test.py index 4e3dfb1e6..30606b0dc 100644 --- a/testsuite/tests/ignored-c-header/test.py +++ b/testsuite/tests/ignored-c-header/test.py @@ -23,6 +23,7 @@ # "identity.c" includes "identity.h". "--ignore-source-files=identity.c", ], + tolerate_coverage_messages=".", ) expected_coverage = { diff --git a/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py b/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py index 3f675bb31..53e115dcc 100644 --- a/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py +++ b/testsuite/tests/instr-cov/223-selective-instr/unsupported/test.py @@ -58,6 +58,7 @@ ["coverage"] + gprsw.cov_switches + ["-axcov", "--output-dir=xcov", "--level=stmt", trace_a, trace_b], + tolerate_messages="traces for .* are inconsistent", out="cov.out", ) diff --git a/testsuite/tests/instr-cov/339-nostdlib/test.py b/testsuite/tests/instr-cov/339-nostdlib/test.py index 28f6da794..7c2b7319e 100644 --- a/testsuite/tests/instr-cov/339-nostdlib/test.py +++ b/testsuite/tests/instr-cov/339-nostdlib/test.py @@ -38,6 +38,7 @@ def error_case(tc_id, args, expected_out, expect_failure): out=log, register_failure=not expect_failure, auto_config_args=False, + tolerate_messages=".", ) thistest.fail_if( diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/test.py b/testsuite/tests/instr-cov/384-SID-cleanup/test.py index da4a5e60b..58c03194b 100644 --- a/testsuite/tests/instr-cov/384-SID-cleanup/test.py +++ b/testsuite/tests/instr-cov/384-SID-cleanup/test.py @@ -51,6 +51,7 @@ mains=["main"], extra_instr_args=["--units", "main", "--units", "pkg"], extra_coverage_args=["-axcov", "--output-dir", output_pkg], + tolerate_coverage_messages="no SID file found for unit pkh", ) expected_cov.pop("pkh.adb.xcov") expected_cov.pop("pkh.ads.xcov") diff --git a/testsuite/tests/instr-cov/386-setup-invalid-target/test.py b/testsuite/tests/instr-cov/386-setup-invalid-target/test.py index 111449164..18f8ab077 100644 --- a/testsuite/tests/instr-cov/386-setup-invalid-target/test.py +++ b/testsuite/tests/instr-cov/386-setup-invalid-target/test.py @@ -21,7 +21,6 @@ ], out=setup_log, auto_config_args=False, - auto_languages=False, auto_target_args=False, register_failure=False, ) diff --git a/testsuite/tests/instr-cov/base64_prefix/test.py b/testsuite/tests/instr-cov/base64_prefix/test.py index cead60290..69305923e 100644 --- a/testsuite/tests/instr-cov/base64_prefix/test.py +++ b/testsuite/tests/instr-cov/base64_prefix/test.py @@ -86,14 +86,13 @@ xcov( [ "coverage", - "-P", - p.root_project, "--level=stmt", "--annotate=xcov", "--output-dir", xcov_dir, trace_filename, ] + + p.cov_switches ) check_xcov_reports(xcov_dir, cov, discard_empty=False) diff --git a/testsuite/tests/instr-cov/consistency/test.py b/testsuite/tests/instr-cov/consistency/test.py index e7eaf0ae4..d476cdd05 100644 --- a/testsuite/tests/instr-cov/consistency/test.py +++ b/testsuite/tests/instr-cov/consistency/test.py @@ -81,6 +81,10 @@ srctrace, ], out=out_file, + tolerate_messages=( + r"traces for body of main \(from .*\) are" + r" inconsistent with the corresponding Source Instrumentation Data" + ), ) # Check that gnatcov warns about inconsistent fingerprints diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py b/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py index 4970a9bac..3a64688d8 100644 --- a/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py @@ -24,7 +24,6 @@ extra_instr_args=["--restricted-to-languages=C"], extra_coverage_args=["-axcov", "--output-dir=xcov"], trace_mode="src", - auto_languages=False, ) check_xcov_reports("xcov", {"tested.c.xcov": {"+": {5}, "-": {7}}}) tmp.to_homedir() @@ -42,7 +41,6 @@ extra_instr_args=["--restricted-to-languages=Ada"], extra_coverage_args=["-axcov", "--output-dir=xcov"], trace_mode="src", - auto_languages=False, ) check_xcov_reports( "xcov", diff --git a/testsuite/tests/instr-cov/orphan-unit/test.py b/testsuite/tests/instr-cov/orphan-unit/test.py index dc9185aa7..85d9f390e 100644 --- a/testsuite/tests/instr-cov/orphan-unit/test.py +++ b/testsuite/tests/instr-cov/orphan-unit/test.py @@ -22,6 +22,7 @@ mains=["main"], tolerate_instrument_messages=".", extra_coverage_args=["--annotate=xcov"], + tolerate_coverage_messages="no ALI file found for unit pkg.child", ) if thistest.options.trace_mode == "src": diff --git a/testsuite/tests/integrated_instrumentation/basic_cmake/test.py b/testsuite/tests/integrated_instrumentation/basic_cmake/test.py index cf894a5b4..00ab4be79 100644 --- a/testsuite/tests/integrated_instrumentation/basic_cmake/test.py +++ b/testsuite/tests/integrated_instrumentation/basic_cmake/test.py @@ -22,6 +22,7 @@ "setup-integration", f"--files={os.path.join(cwd, '..', 'main.c')}", "--compilers=gcc", + "--level=stmt", ] ) diff --git a/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py b/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py index be7ef31a3..281bff3ce 100644 --- a/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py +++ b/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py @@ -21,6 +21,7 @@ def process(c_flags, subdir): xcov( [ "setup-integration", + "--level=stmt", f"--files={os.path.join(cwd, '..', 'main.c')}", f"--files={os.path.join(cwd, '..','pkg.h')}", "--compilers=gcc", diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/test.py b/testsuite/tests/integrated_instrumentation/cmake_lib/test.py index 1a921d870..ac33a6a75 100644 --- a/testsuite/tests/integrated_instrumentation/cmake_lib/test.py +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/test.py @@ -24,6 +24,7 @@ f"--files={os.path.join(cwd, '..', 'src', 'main.c')}", f"--files={os.path.join(cwd, '..', 'src', 'lib.c')}", "--compilers=gcc", + "--level=stmt", ] ) From 8de347f79c825d9b4fcf8512cd7d84647dca3f55 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 29 Jul 2024 18:04:53 +0200 Subject: [PATCH 1154/1483] Do not check for object code when processing source traces --- tools/gnatcov/gnatcov_bits_specific.adb | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 11463671a..2ba0c2011 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -2323,7 +2323,10 @@ begin end if; end if; - if Source_Coverage_Enabled and then SCOs_Trace.Is_Active then + if Source_Coverage_Enabled + and then SCOs_Trace.Is_Active + and then Currently_Accepted_Trace_Kind = Binary_Trace_File + then SC_Obligations.Report_Units_Without_Code; end if; From 2119a1c3b273d5846892aabbef3987a36d75943e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 31 Jul 2024 10:13:29 +0200 Subject: [PATCH 1155/1483] Add support for --restricted-to-languages to gnatcov coverage To avoid spurious warnings such as "no SID file found for unit " at gnatcov coverage time for units in a language that was ignored at instrumentation time by using the --restricted-to-languages switch. --- .../instr-cov/main_autodump/disabled_lang/test.py | 12 ++++++++++-- tools/gnatcov/command_line.ads | 3 ++- tools/gnatcov/project.adb | 5 +++++ tools/gnatcov/setup_rts.adb | 3 ++- tools/gnatcov/switches.ads | 4 ++-- 5 files changed, 21 insertions(+), 6 deletions(-) diff --git a/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py b/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py index 3a64688d8..d8abb1fa2 100644 --- a/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py +++ b/testsuite/tests/instr-cov/main_autodump/disabled_lang/test.py @@ -22,7 +22,11 @@ covlevel="stmt", mains=["main"], extra_instr_args=["--restricted-to-languages=C"], - extra_coverage_args=["-axcov", "--output-dir=xcov"], + extra_coverage_args=[ + "-axcov", + "--output-dir=xcov", + "--restricted-to-languages=C", + ], trace_mode="src", ) check_xcov_reports("xcov", {"tested.c.xcov": {"+": {5}, "-": {7}}}) @@ -39,7 +43,11 @@ covlevel="stmt", mains=["main"], extra_instr_args=["--restricted-to-languages=Ada"], - extra_coverage_args=["-axcov", "--output-dir=xcov"], + extra_coverage_args=[ + "-axcov", + "--output-dir=xcov", + "--restricted-to-languages=Ada", + ], trace_mode="src", ) check_xcov_reports( diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index f758887b1..9802f7d56 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -1586,7 +1586,8 @@ package Command_Line is & " C and C++. Note that main units of other languages may still be" & " instrumented to dump the coverage state to trace files.", Commands => (Cmd_Setup - | Cmd_Instrument_Project => True, + | Cmd_Instrument_Project + | Cmd_Coverage => True, others => False), Internal => False, Accepts_Comma_Separator => True), diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 1dd54eacf..c1223091e 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -366,6 +366,11 @@ package body Project is if Unit.Warned_About_Missing_Info or else (Currently_Accepted_Trace_Kind = Binary_Trace_File and then Unit.Language = CPP_Language) + + -- Ignore units in a language that is ignored through the + -- --restricted-to-languages switch. + + or else not Src_Enabled_Languages (Unit.Language) then return; end if; diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 0ac23df48..b3f23454c 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -121,7 +121,8 @@ package body Setup_RTS is -- Load the project file at Project_File using the Target/RTS/Config_File -- parameters, then try to guess the profile of the actual runtime in -- effect (Auto_RTS_Profile) and determine the support for libraries for - -- this configuration (Lib_Support). + -- this configuration (Lib_Support). Pass Db_Dir as an additional knowledge + -- base. when creating the configuration file. -- -- Set Actual_Target, Actual_RTS_Dir and Actual_RTS_Name to the actual -- target/RTS names for the loaded project: they can be different from diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 66c861f84..bcc8b832f 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -223,8 +223,8 @@ package Switches is Src_Enabled_Languages : array (Src_Supported_Language) of Boolean := (others => False); - -- List of languages for which source files should be instrumented. - -- Initialized during command line arguments parsing. + -- List of languages for which coverage analysis is enabled. Initialized + -- during command line arguments parsing. Builtin_Support : array (Src_Supported_Language) of Boolean := (others => True); From 30f795a1b4e5bbff214b2076562ddf3edd2ff5a7 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 26 Mar 2025 16:04:04 +0100 Subject: [PATCH 1156/1483] Fix live-observability regressions for block instrumentation --- .../tests/345-live-observability/test.py | 19 ++++++++++++++++--- tools/gnatcov/instrument-ada_unit.adb | 6 +++--- 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/testsuite/tests/345-live-observability/test.py b/testsuite/tests/345-live-observability/test.py index 1a9dbb847..00c8f5620 100644 --- a/testsuite/tests/345-live-observability/test.py +++ b/testsuite/tests/345-live-observability/test.py @@ -24,18 +24,31 @@ extra_coverage_args=[], ) +# In case block instrumentation is enabled, the number of bits set to 1 in the +# buffers is not equivalent to the number of statements executed. +if thistest.options.block: + counts = [0, 0, 3] +else: + counts = [2, 4, 8] + OUTPUT = contents_of("main_output.txt") thistest.fail_if_no_match( - "Wrong first buffer sum", re.compile(r".*First: *2.*", re.S), OUTPUT + "Wrong first buffer sum", + re.compile(f".*First: *{counts[0]}.*", re.S), + OUTPUT, ) thistest.fail_if_no_match( - "Wrong second buffer sum", re.compile(r".*Second: *4.*", re.S), OUTPUT + "Wrong second buffer sum", + re.compile(f".*Second: *{counts[1]}.*", re.S), + OUTPUT, ) thistest.fail_if_no_match( - "Wrong third buffer sum", re.compile(r".*Third: *8.*", re.S), OUTPUT + "Wrong third buffer sum", + re.compile(f".*Third: *{counts[2]}.*", re.S), + OUTPUT, ) thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 059f9f937..4348cb18f 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -11152,7 +11152,7 @@ package body Instrument.Ada_Unit is Create_File (Prj, Body_File, Obs_Body_Filename); Spec_File.Put_Line ("package " & Obs_Unit_Name & " is"); - Spec_File.Put_Line (" function Sum_Buffer_Bits return Positive;"); + Spec_File.Put_Line (" function Sum_Buffer_Bits return Natural;"); Spec_File.Put_Line ("end " & Obs_Unit_Name & ";"); Body_File.Put_Line ("with Interfaces.C;"); @@ -11160,7 +11160,7 @@ package body Instrument.Ada_Unit is ("with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists;"); Body_File.New_Line; Body_File.Put_Line ("package body " & Obs_Unit_Name & " is"); - Body_File.Put_Line (" function Sum_Buffer_Bits return Positive is"); + Body_File.Put_Line (" function Sum_Buffer_Bits return Natural is"); Body_File.Put_Line (" function Sum_Buffer_Bits_C"); Body_File.Put_Line (" (C_List : GNATcov_RTS_Coverage_Buffers_Group_Array)"); @@ -11170,7 +11170,7 @@ package body Instrument.Ada_Unit is & " ""gnatcov_rts_sum_buffer_bits"");"); Body_File.Put_Line (" begin"); Body_File.Put_Line - (" return Positive(Sum_Buffer_Bits_C (" + (" return Natural(Sum_Buffer_Bits_C (" & Buf_List_Unit_Name & ".C_List));"); Body_File.Put_Line (" end;"); Body_File.Put_Line ("end " & Obs_Unit_Name & ";"); From 44576fb1457d62ffdf9b6ade64e82cb352294a6d Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 21 Mar 2025 17:59:30 +0100 Subject: [PATCH 1157/1483] instr-c: Simplify declaration of Make_(Stmt|Expr)_Witness functions --- tools/gnatcov/instrument-c.adb | 62 ++++++++++++---------------------- 1 file changed, 21 insertions(+), 41 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index eccc3b27a..96da02b5a 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -305,20 +305,6 @@ package body Instrument.C is -- Note that while Buffers_Index is 1-based, C arrays are 0-based, hence -- the index "off-by-1" conversion. - function Make_Expr_Witness - (UIC : C_Unit_Inst_Context; - Buffer_Index : Positive; - Bit : Bit_Id) return String; - -- Create a procedure call expression on to witness execution of the low - -- level SCO with the given Bit id in the statement buffer at Buffer_Index. - - function Make_Statement_Witness - (UIC : C_Unit_Inst_Context; - Buffer_Index : Positive; - Bit : Bit_Id) return String; - -- Create a procedure call statement to witness execution of the low level - -- SCO with the given Bit id in the statement buffer at Buffer_Index. - procedure Insert_Statement_Witness (UIC : in out C_Unit_Inst_Context; Buffers_Index : Positive; @@ -1317,33 +1303,6 @@ package body Instrument.C is Kind); end Report; - ----------------------- - -- Make_Expr_Witness -- - ----------------------- - - function Make_Expr_Witness - (UIC : C_Unit_Inst_Context; - Buffer_Index : Positive; - Bit : Bit_Id) return String is - begin - return - "gnatcov_rts_witness (" - & Statement_Buffer_Symbol (UIC.Instrumented_Unit) - & Buffers_Subscript (Buffer_Index) & ", " & Img (Bit) & ")"; - end Make_Expr_Witness; - - ---------------------------- - -- Make_Statement_Witness -- - ---------------------------- - - function Make_Statement_Witness - (UIC : C_Unit_Inst_Context; - Buffer_Index : Positive; - Bit : Bit_Id) return String is - begin - return Make_Expr_Witness (UIC, Buffer_Index, Bit) & ";"; - end Make_Statement_Witness; - ------------------------------ -- Insert_Statement_Witness -- ------------------------------ @@ -1359,6 +1318,27 @@ package body Instrument.C is Bit : constant Bit_Id := Allocate_Statement_Bit (Unit_Bits, SS.LL_SCO); + + function Make_Expr_Witness + (UIC : C_Unit_Inst_Context; + Buffer_Index : Positive; + Bit : Bit_Id) return String + is ("gnatcov_rts_witness (" + & Statement_Buffer_Symbol (UIC.Instrumented_Unit) + & Buffers_Subscript (Buffer_Index) & ", " & Img (Bit) & ")"); + -- Create a procedure call expression on to witness execution of the low + -- level SCO with the given Bit id in the statement buffer at + -- Buffer_Index. + + function Make_Statement_Witness + (UIC : C_Unit_Inst_Context; + Buffer_Index : Positive; + Bit : Bit_Id) return String + is (Make_Expr_Witness (UIC, Buffer_Index, Bit) & ";"); + -- Create a procedure call statement to witness execution of the low + -- level SCO with the given Bit id in the statement buffer at + -- Buffer_Index. + begin -- Insert the call to the witness function: as a foregoing statement if -- SS.Statement is a statement, or as a previous expression (using the From 0d8b3aef73b6dc876f59e3af3aaea450916f6496 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 21 Mar 2025 16:17:52 +0100 Subject: [PATCH 1158/1483] instr-c: Introduce a generic witness to instrument C++ call chains --- tools/gnatcov/clang-extensions.adb | 13 ++ tools/gnatcov/clang-extensions.ads | 27 ++++ tools/gnatcov/clang-wrapper.cc | 75 ++++++++++- tools/gnatcov/instrument-c.adb | 146 ++++++++++++++-------- tools/gnatcov/instrument-c.ads | 12 +- tools/gnatcov/rts/gnatcov_rts_c-witness.h | 13 ++ 6 files changed, 235 insertions(+), 51 deletions(-) diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index 47ca7623c..da73d1e65 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -85,6 +85,19 @@ package body Clang.Extensions is return Is_Instrumentable_Call_Expr_C (C) /= 0; end Is_Instrumentable_Call_Expr; + ------------------------------- + -- Is_CXX_Member_Call_Expr -- + ------------------------------- + + function Is_Prefixed_CXX_Member_Call_Expr (C : Cursor_T) return Boolean is + function Is_CXX_Member_Call_Expr_C (C : Cursor_T) return unsigned + with + Import, Convention => C, + External_Name => "clang_isPrefixedCXXMemberCallExpr"; + begin + return Is_CXX_Member_Call_Expr_C (C) /= 0; + end Is_Prefixed_CXX_Member_Call_Expr; + -------------------- -- Get_Opcode_Str -- -------------------- diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index 5b2e6d145..73d5f8aa1 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -130,6 +130,33 @@ package Clang.Extensions is -- TODO??? Actually decide what to do for the rest, so Ctor/Dtor call -- coverage makes sense. + function Is_Prefixed_CXX_Member_Call_Expr (C : Cursor_T) return Boolean + with Inline; + -- Return True if the given cursor is a statement with type + -- Stmt::CXXMemberCallExprClass, and if it is a prefixed method call + -- (meaning not a method that is called from the body of another method + -- in which it is possible to simply omit `this->`). + + function Get_CXX_Member_Call_Expr_SCO_Sloc_Range + (C : Cursor_T) return Source_Range_T + with + Import, + Convention => C, + External_Name => "clang_getCXXMemberCallExprSCOSlocRange"; + -- Assume the given cursor is a Stmt::CXXMemberCallExprClass. + -- Given the expression is `Foo.Bar(Baz)`, it will return a source range + -- containing `.Bar`. + + function Get_CXX_Member_Call_Expr_Base_Sloc_Range + (C : Cursor_T) return Source_Range_T + with + Import, + Convention => C, + External_Name => "clang_getCXXMemberCallExprBaseSlocRange"; + -- Assume the given cursor is a Stmt::CXXMemberCallExprClass. + -- Given the expression is `Foo.Bar(Baz)`, it will return the source + -- range of `Foo`. + function Is_Constexpr (C : Cursor_T) return Boolean with Inline; function Unwrap (C : Cursor_T) return Cursor_T diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index b29cb0594..c9d3b848a 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -20,6 +20,8 @@ /* Make sure we refer to the static version of symbols on Windows, not to DLL importers. */ +#include "clang-c/CXSourceLocation.h" +#include "clang/AST/Expr.h" #define CINDEX_NO_EXPORTS #include "libclang/CXCursor.h" @@ -33,6 +35,7 @@ #include "clang/AST/ExprCXX.h" #include "clang/AST/ParentMapContext.h" #include "clang/AST/StmtCXX.h" +#include "clang/Basic/CharInfo.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/ASTUnit.h" @@ -351,7 +354,7 @@ clang_getLBracLocPlusOne (CXCursor C) return translateSLoc (TU, S->getLBracLoc ().getLocWithOffset (1)); } -extern "C" bool +extern "C" unsigned clang_isInstrumentableCallExpr (CXCursor C) { if (!clang_isExpression (C.kind)) @@ -382,6 +385,76 @@ clang_isInstrumentableCallExpr (CXCursor C) } } +// Return true if the cursor is C++ Method Call with an explicit base. +extern "C" unsigned +clang_isPrefixedCXXMemberCallExpr (CXCursor C) +{ + if (!clang_isExpression (C.kind)) + return false; + + const Expr *E = getCursorExpr (C); + if (E->getStmtClass () != Stmt::CXXMemberCallExprClass) + return false; + + const CXXMemberCallExpr *MCE = cast (E); + const MemberExpr *ME = cast (MCE->getCallee ()); + + return !ME->isImplicitAccess (); +} + +extern "C" CXSourceRange +clang_getCXXMemberCallExprSCOSlocRange (CXCursor C) +{ + if (!clang_isExpression (C.kind)) + return clang_getNullRange (); + + const Expr *E = getCursorExpr (C); + if (E->getStmtClass () != Stmt::CXXMemberCallExprClass) + return clang_getNullRange (); + + const CXXMemberCallExpr *MCE = cast (E); + const MemberExpr *ME = cast (MCE->getCallee ()); + + ASTContext &ctx = getContext (C); + + const SourceLocation start_loc = ME->getOperatorLoc (); + const SourceLocation end_loc = ME->getMemberLoc ().getLocWithOffset ( + ((long) ME->getMemberDecl ()->getName ().size ()) - 1); + + // Check for validity on both sides. + // Specifically, start loc can fail if there is no operator, if the method + // call is made from another method and thus not prefixed by `object.` or + // `object->` + if (start_loc.isInvalid () || end_loc.isInvalid ()) + return clang_getNullRange (); + + // Do not use the translateSourceRange wrapper because the token + // delimitation is not right for us. + return translateSourceRange ( + ctx.getSourceManager (), ctx.getLangOpts (), + CharSourceRange::getCharRange (SourceRange (start_loc, end_loc))); +} + +extern "C" CXSourceRange +clang_getCXXMemberCallExprBaseSlocRange (CXCursor C) +{ + if (!clang_isExpression (C.kind)) + return clang_getNullRange (); + + const Expr *E = getCursorExpr (C); + if (E->getStmtClass () != Stmt::CXXMemberCallExprClass) + return clang_getNullRange (); + + const CXXMemberCallExpr *MCE = cast (E); + const MemberExpr *ME = cast (MCE->getCallee ()); + + const SourceLocation start_loc = ME->getBase ()->getBeginLoc (); + const SourceLocation end_loc = ME->getBase ()->getEndLoc (); + + return translateSourceRange (getContext (C), + SourceRange (start_loc, end_loc)); +} + extern "C" CXSourceRange clang_getFunctionSignatureSloc (CXCursor C) { diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 96da02b5a..017f306ca 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -1367,6 +1367,35 @@ package body Instrument.C is (N => SS.Statement, Text => ")", Rew => UIC.Rewriter); + + when Instr_Prefixed_CXXMemberCallExpr => + + -- In case we are instrumenting a C++ method call `foo.bar()` + -- we wrap the base in a generic witness which is an identity + -- function and call the method on the witness like so : + -- + -- `witness_generic(buf, id, foo).bar()` + + declare + Base_Sloc_Range : constant Source_Range_T := + Get_CXX_Member_Call_Expr_Base_Sloc_Range (SS.Statement); + Witness_Params : constant String := + Statement_Buffer_Symbol (UIC.Instrumented_Unit) + & Buffers_Subscript (Buffers_Index) & ", " & Img (Bit); + begin + CX_Rewriter_Insert_Text_After + (Rew => UIC.Rewriter, + Loc => Get_Range_Start (Base_Sloc_Range), + Insert => "gnatcov_rts_witness_generic (" + & Witness_Params & ", "); + + CX_Rewriter_Insert_Text_Before + (Rew => UIC.Rewriter, + Loc => Get_Range_End (Base_Sloc_Range), + Insert => ")"); + end; + + null; end case; end Insert_Statement_Witness; @@ -1583,54 +1612,6 @@ package body Instrument.C is end if; end Is_Complex_Decision; - ----------------------- - -- Process_Call_Expr -- - ----------------------- - - procedure Process_Call_Expr - (UIC : in out C_Unit_Inst_Context; Cursor : Cursor_T); - - procedure Process_Call_Expr - (UIC : in out C_Unit_Inst_Context; Cursor : Cursor_T) - is - function Visit_Call_Expr (C : Cursor_T) return Child_Visit_Result_T; - - function Visit_Call_Expr (C : Cursor_T) return Child_Visit_Result_T is - begin - if Kind (C) = Cursor_Lambda_Expr then - return Child_Visit_Continue; - end if; - - if Is_Instrumentable_Call_Expr (C) then - Sources_Trace.Trace ("Instrument Call at " - & Image (Start_Sloc (C))); - - UIC.Pass.Append_SCO - (UIC => UIC, - N => C, - C1 => 'c', - C2 => 'S', - From => Start_Sloc (C), - To => End_Sloc (C), - Last => True); - - UIC.Pass.Instrument_Statement - (UIC => UIC, - LL_SCO => SCOs.SCO_Table.Last, - Insertion_N => C, - Instr_Scheme => Instr_Expr, - Kind => Call); - end if; - - return Child_Visit_Recurse; - end Visit_Call_Expr; - - begin - if Enabled (Coverage_Options.Fun_Call) then - Visit (Cursor, Visit_Call_Expr'Access); - end if; - end Process_Call_Expr; - ------------------------ -- Process_Expression -- ------------------------ @@ -1650,6 +1631,8 @@ package body Instrument.C is N : Cursor_T; T : Character); + function Process_Call_Expr (C : Cursor_T) return Child_Visit_Result_T; + ------------------------- -- Process_Lambda_Expr -- ------------------------- @@ -2030,6 +2013,69 @@ package body Instrument.C is Hash_Entries.Free; end Process_Decisions; + ------------------------- + -- Process_Call_Expr -- + ------------------------- + + function Process_Call_Expr (C : Cursor_T) return Child_Visit_Result_T is + begin + + -- Lambda functions are handled in Process_Lambda_Expr + + if Kind (C) = Cursor_Lambda_Expr then + return Child_Visit_Continue; + end if; + + if Is_Instrumentable_Call_Expr (C) then + Sources_Trace.Trace ("Instrument Call at " + & Image (Start_Sloc (C))); + + declare + From : Source_Location := Start_Sloc (C); + To : Source_Location := End_Sloc (C); + Instr_Scheme : Instr_Scheme_Type := Instr_Expr; + begin + if Is_Prefixed_CXX_Member_Call_Expr (C) then + + -- If we are instrumenting a method call like `foo.bar()`, + -- adjust the SCO to `.bar`, and set a specific + -- instrumentation scheme. + -- + -- This does not apply to un-prefixed method calls (in other + -- method calls), which are instrumented as regular + -- functions. + + declare + CX_Source_Range : constant Source_Range_T := + Get_CXX_Member_Call_Expr_SCO_Sloc_Range (C); + begin + From := Sloc (Get_Range_Start (CX_Source_Range)); + To := Sloc (Get_Range_End (CX_Source_Range)); + Instr_Scheme := Instr_Prefixed_CXXMemberCallExpr; + end; + end if; + + UIC.Pass.Append_SCO + (UIC => UIC, + N => C, + C1 => 'c', + C2 => 'E', + From => From, + To => To, + Last => True); + + UIC.Pass.Instrument_Statement + (UIC => UIC, + LL_SCO => SCOs.SCO_Table.Last, + Insertion_N => C, + Instr_Scheme => Instr_Scheme, + Kind => Call); + end; + end if; + + return Child_Visit_Recurse; + end Process_Call_Expr; + begin if UIC.Disable_Coverage then return; @@ -2037,7 +2083,9 @@ package body Instrument.C is Process_Decisions (UIC, N, T); - Process_Call_Expr (UIC, N); + if Enabled (Coverage_Options.Fun_Call) then + Visit (N, Process_Call_Expr'Access); + end if; Visit (N, Process_Lambda_Expr'Access); end Process_Expression; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 79761e8fe..95629ada4 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -160,7 +160,11 @@ package Instrument.C is -- Create a C++ instrumenter. See the definition of the -- Language_Instrumenter type for the arguments semantic. - type Instr_Scheme_Type is (Instr_Stmt, Instr_Expr, Instr_In_Compound); + type Instr_Scheme_Type is + (Instr_Stmt, + Instr_Expr, + Instr_In_Compound, + Instr_Prefixed_CXXMemberCallExpr); -- Depending on the statement construct, we can instrument it either with -- another statement right before (Instr_Stmt), which is the case for most -- statements: @@ -193,6 +197,12 @@ package Instrument.C is -- Function coverage, and particularly useful for functions with empty -- bodies in which it is not possible to refer to the body's first -- statement to insert a witness statement before it. + -- + -- The variant Instr_Prefixed_CXXMemberCallExpr is expected to be used on + -- C++ prefixed method calls like `foo.bar()` or `foo->bar()`. + -- It will be instrumented using a generic templated witness to conserve + -- the execution order of witnesses in method call chains. + -- Note that NON-prefixed method calls are handled like simple functions. type C_Source_Statement is record LL_SCO : Nat; diff --git a/tools/gnatcov/rts/gnatcov_rts_c-witness.h b/tools/gnatcov/rts/gnatcov_rts_c-witness.h index 1193daa25..6e789ab93 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-witness.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-witness.h @@ -35,6 +35,19 @@ gnatcov_rts_witness (unsigned char *buffer, unsigned bit_id) return 1; } +#ifdef __cplusplus + +template +T +gnatcov_rts_witness_generic (unsigned char *buffer, unsigned int bit_id, + T value) +{ + gnatcov_rts_witness (buffer, bit_id); + return value; +} + +#endif /* __cplusplus */ + /* Decisions */ /* If VALUE is false, set the boolean corresponding to FALSE_BIT to true in From 91963dfcdc881a93b5d143f2a52ee490c53217cb Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 24 Mar 2025 12:57:27 +0100 Subject: [PATCH 1159/1483] test(instr-c): Add tests for C++ method call chain instrumentation --- .../cpp/nested-method-calls/src/pkg.h | 33 +++++++++++++++++++ .../src/test_exiting_method.cpp | 19 +++++++++++ .../src/test_shortcut_method_chain.cpp | 21 ++++++++++++ .../src/test_simple_call.cpp | 17 ++++++++++ .../cpp/nested-method-calls/test.py | 13 ++++++++ .../src/test_non_prefix.cpp | 29 ++++++++++++++++ .../cpp/non-prefixed-method-calls/test.py | 11 +++++++ 7 files changed, 143 insertions(+) create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/pkg.h create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_exiting_method.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_shortcut_method_chain.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_simple_call.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.py create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/src/test_non_prefix.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/test.py diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/pkg.h new file mode 100644 index 000000000..c29793170 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/pkg.h @@ -0,0 +1,33 @@ +#pragma once +#include + +class A +{ + int _x; + +public: + A (int x) : _x (x){}; + + int + get_x () const + { + return this->_x; + } +}; + +class B +{ + A _a; + +public: + B (A a) : _a (a){}; + + A + get_a () const + { + // Purposely exit early after dumping the buffers. + /* GNATCOV_DUMP_BUFFERS */ + exit (0); + return this->_a; + } +}; diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_exiting_method.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_exiting_method.cpp new file mode 100644 index 000000000..9508f93c2 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_exiting_method.cpp @@ -0,0 +1,19 @@ +#include "pkg.h" + +int +main (void) +{ + A a (5); // # var-decl + B b (a); // # var-decl + + // .get_a() exits the program with 0 status code. + b // # var-ref + .get_a (); // # method-call + + // Program should not reach this point. +} + +//# test_exiting_method.cpp +// /var-decl/ l+ ## 0 +// /var-ref/ l+ ## 0 +// /method-call/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_shortcut_method_chain.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_shortcut_method_chain.cpp new file mode 100644 index 000000000..8b0308653 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_shortcut_method_chain.cpp @@ -0,0 +1,21 @@ +#include "pkg.h" + +int +main (void) +{ + A a (5); // # var-decl + B b (a); // # var-decl + + // .get_a() exits the program with 0 status code. + b // # var-ref + .get_a () // # method-call + .get_x (); // # not-reached + + /* GNATCOV_DUMP_BUFFERS */ +} + +//# test_shortcut_method_chain.cpp +// /var-decl/ l+ ## 0 +// /var-ref/ l+ ## 0 +// /method-call/ l+ ## 0 +// /not-reached/ l! ## c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_simple_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_simple_call.cpp new file mode 100644 index 000000000..0dc5ffed4 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/test_simple_call.cpp @@ -0,0 +1,17 @@ +#include "pkg.h" + +int +main (void) +{ + A a (5); // # var-decl + + a // # var-ref + .get_x (); // # method-call + + /* GNATCOV_DUMP_BUFFERS */ +} + +//# test_simple_call.cpp +// /var-decl/ l+ ## 0 +// /var-ref/ l+ ## 0 +// /method-call/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.py new file mode 100644 index 000000000..d72409884 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.py @@ -0,0 +1,13 @@ +""" +This test ensures that method call instrumentation behaves correctly and +produces the expected coverage. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run( + covcontrol=CovControl(dump_trigger="manual") +) +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/src/test_non_prefix.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/src/test_non_prefix.cpp new file mode 100644 index 000000000..5f31e58ec --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/src/test_non_prefix.cpp @@ -0,0 +1,29 @@ +class A +{ + int _x; + +public: + A (int x) : _x (x){}; + + int + get_x () const + { + return this->_x; + } + + int + get_x_plus_one () const + { + return get_x () + 1; // # non-prefix-call + } +}; + +int +main (void) +{ + A (5).get_x_plus_one (); // # method-call +} + +//# test_non_prefix.cpp +// /non-prefix-call/ l+ ## 0 +// /method-call/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/test.py new file mode 100644 index 000000000..aa54dd7e8 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/test.py @@ -0,0 +1,11 @@ +""" +This test makes sure that the instrumentation of non-prefixed method calls +works correctly. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run() +thistest.result() From 0ea09b49b978b889e826de58daf36ba32a35e78b Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 27 Mar 2025 10:03:57 +0100 Subject: [PATCH 1160/1483] Add tolerated coverage message --- testsuite/tests/R404-023-object-stats/test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/R404-023-object-stats/test.py b/testsuite/tests/R404-023-object-stats/test.py index 47c516f88..9abe3f0cf 100644 --- a/testsuite/tests/R404-023-object-stats/test.py +++ b/testsuite/tests/R404-023-object-stats/test.py @@ -19,6 +19,7 @@ "../main.trace.asset", ], out="asm-report.txt", + tolerate_messages="executable file .* does not seem to match trace file", ) lines = lines_of("asm-report.txt") From d6211f28ca4882f7935d1d4497d1748ec52614c6 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 26 Mar 2025 15:59:14 +0100 Subject: [PATCH 1161/1483] Fix coverage crash when generating a HTML report with missing sources --- .../instr-cov/363-annot-crash/src/pkg.adb | 6 +++ .../instr-cov/363-annot-crash/src/pkg.ads | 3 ++ .../instr-cov/363-annot-crash/src/test.adb | 6 +++ .../tests/instr-cov/363-annot-crash/test.py | 38 +++++++++++++++++++ tools/gnatcov/annotations.adb | 19 ++++++++-- 5 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/instr-cov/363-annot-crash/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/363-annot-crash/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/363-annot-crash/src/test.adb create mode 100644 testsuite/tests/instr-cov/363-annot-crash/test.py diff --git a/testsuite/tests/instr-cov/363-annot-crash/src/pkg.adb b/testsuite/tests/instr-cov/363-annot-crash/src/pkg.adb new file mode 100644 index 000000000..d23d45788 --- /dev/null +++ b/testsuite/tests/instr-cov/363-annot-crash/src/pkg.adb @@ -0,0 +1,6 @@ +package body Pkg is + procedure Foo is + begin + null; + end Foo; +end Pkg; diff --git a/testsuite/tests/instr-cov/363-annot-crash/src/pkg.ads b/testsuite/tests/instr-cov/363-annot-crash/src/pkg.ads new file mode 100644 index 000000000..d91f3ae51 --- /dev/null +++ b/testsuite/tests/instr-cov/363-annot-crash/src/pkg.ads @@ -0,0 +1,3 @@ +package Pkg is + procedure Foo; +end Pkg; diff --git a/testsuite/tests/instr-cov/363-annot-crash/src/test.adb b/testsuite/tests/instr-cov/363-annot-crash/src/test.adb new file mode 100644 index 000000000..e75f2cda7 --- /dev/null +++ b/testsuite/tests/instr-cov/363-annot-crash/src/test.adb @@ -0,0 +1,6 @@ +with Pkg; + +procedure Test is +begin + Pkg.Foo; +end Test; diff --git a/testsuite/tests/instr-cov/363-annot-crash/test.py b/testsuite/tests/instr-cov/363-annot-crash/test.py new file mode 100644 index 000000000..9e627d5e9 --- /dev/null +++ b/testsuite/tests/instr-cov/363-annot-crash/test.py @@ -0,0 +1,38 @@ +""" +Regression test: check that gnatcov does not crash when generating a XML / HTML +report with missing sources. It used to crash when trying to compute scope +metrics. +""" + +from e3.fs import mv, sync_tree + +import os + +from SCOV.minicheck import build_and_run +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest, xcov + +tmp = Wdir("tmp_") + +sync_tree(os.path.join("..", "src"), "src") + +xcov_args = build_and_run( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["src"], mains=["test.adb"]) + ), + covlevel="stmt", + mains=["test"], + extra_coverage_args=[], + trace_mode="src", +) + +# Then hide the sources +os.mkdir("src_hidden") +mv(os.path.join("src", "pkg.adb"), "src_hidden") + +# Try to generate a HTML, and an XML report +xcov(xcov_args + ["-axml"], tolerate_messages="warning: can't open") +xcov(xcov_args + ["-ahtml"], tolerate_messages="warning: can't open") + +thistest.result() diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 7f761ba4f..df0adf463 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -996,11 +996,24 @@ package body Annotations is (FI : File_Info_Access; From, To : Natural) return Li_Stat_Array is - Result : Li_Stat_Array := (others => 0); + Result : Li_Stat_Array := (others => 0); + Actual_To : Natural := To; + Last_Loaded_Line : Natural renames Last_Line (FI); begin - for L in From .. To loop + -- Do not try to retrieve a line that was not loaded (which has an index + -- superior to Last_Line (FI)). This can happen when the sources are not + -- available. In that case, only loop until the last loaded line is + -- reached (it actually corresponds to the last SCO line), and consider + -- the subsequent lines as no code. + + if To > Last_Loaded_Line then + Result (No_Code) := To - Last_Loaded_Line; + Actual_To := Last_Loaded_Line; + end if; + + for L in From .. Actual_To loop declare - LI : constant Line_Info_Access := Get_Line (FI, L); + LI : constant Line_Info_Access := Get_Line (FI, L); S : constant Any_Line_State := Aggregated_State (LI.all); begin -- Update counts. Note that No_Code lines are always counted as From aa58c73da0f4c943989fa1bcc5e3a84a365e6487 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 14 Feb 2025 12:51:25 +0000 Subject: [PATCH 1162/1483] O302-015-src-path-in-project: improve logging --- testsuite/tests/O302-015-src-path-in-project/test.py | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/O302-015-src-path-in-project/test.py b/testsuite/tests/O302-015-src-path-in-project/test.py index 042f5d0aa..718bad33d 100644 --- a/testsuite/tests/O302-015-src-path-in-project/test.py +++ b/testsuite/tests/O302-015-src-path-in-project/test.py @@ -49,6 +49,7 @@ def try_coverage(xcov_args, use_project): + thistest.log(f"== try_coverage(use_project={use_project})") rm(pkg_ads_report_path) if not use_project: From 1092826f20fdbd9370ef67d5fb918f4cc3e50f8b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 18 Mar 2025 14:14:10 +0000 Subject: [PATCH 1163/1483] Project: remove the Include_Stubs formal Callers always pass True to `Include_Stubs`, so just remove this formal and simplify the implemenation logic. --- tools/gnatcov/coverage-source.adb | 5 ++- tools/gnatcov/instrument-projects.adb | 8 ++--- tools/gnatcov/project.adb | 46 +++++++++------------------ tools/gnatcov/project.ads | 4 --- 4 files changed, 19 insertions(+), 44 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 4a620d9a9..d0a08d297 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -376,9 +376,8 @@ package body Coverage.Source is begin Enumerate_Sources (Callback'Access, - Include_Stubs => True, - Language => All_Languages, - Only_UOIs => True); + Language => All_Languages, + Only_UOIs => True); end Compute_Unit_Name_For_Ignored_Sources; ------------------------- diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index acaff44e4..94d9dc9b1 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -1118,18 +1118,14 @@ begin for Lang in Src_Supported_Language loop if Src_Enabled_Languages (Lang) then Project.Enumerate_Sources - (Add_Instrumented_Unit'Access, - Lang, - Include_Stubs => True, - Only_UOIs => True); + (Add_Instrumented_Unit'Access, Lang, Only_UOIs => True); if Dump_Config.Trigger = Manual then -- The expected manual dump indication can be located in any -- source file, not only in sources of interest. - Project.Enumerate_Sources - (Add_Project_Source'Access, Lang, Include_Stubs => True); + Project.Enumerate_Sources (Add_Project_Source'Access, Lang); end if; end if; end loop; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index c1223091e..cfae6353d 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -80,19 +80,15 @@ package body Project is -- Build identifiers for attributes in package Coverage procedure Iterate_Source_Files - (Root_Project : Project_Type; - Process : access procedure + (Root_Project : Project_Type; + Process : access procedure (Info : File_Info; Unit_Name : String); - Recursive : Boolean; - Include_Stubs : Boolean := False); + Recursive : Boolean); -- Call Process on all source files in Root_Project (recursively -- considering source files of sub-projects if Recursive is true). -- -- This passes the name of the unit as Unit_Name for languages featuring -- this notion (Ada) and the base file name otherwise (i.e. for C sources). - -- - -- If Include_Stubs is false (the default) then Callback will skip - -- sources files that are subunits (Ada) or headers (C/C++). Env : Project_Environment_Access; -- Environment in which we load the project tree @@ -437,11 +433,10 @@ package body Project is -------------------------- procedure Iterate_Source_Files - (Root_Project : Project_Type; - Process : access procedure + (Root_Project : Project_Type; + Process : access procedure (Info : File_Info; Unit_Name : String); - Recursive : Boolean; - Include_Stubs : Boolean := False) + Recursive : Boolean) is -- If Root_Project is extending some project P, consider for coverage -- purposes that source files in P also belong to Root_Project. For @@ -479,12 +474,9 @@ package body Project is Info : constant File_Info := File_Info (Abstract_Info); begin -- Process only source files in supported languages (Ada, - -- C and C++), and include subunits only if requested. + -- C and C++): - if To_Lower (Info.Language) in "ada" | "c" | "c++" - and then (Include_Stubs - or else Info.Unit_Part /= Unit_Separate) - then + if To_Lower (Info.Language) in "ada" | "c" | "c++" then Process.all (Info => Info, Unit_Name => (if Info.Unit_Name = "" @@ -580,12 +572,11 @@ package body Project is ----------------------- procedure Enumerate_Sources - (Callback : access procedure + (Callback : access procedure (Project : GNATCOLL.Projects.Project_Type; File : GNATCOLL.Projects.File_Info); - Language : Any_Language; - Include_Stubs : Boolean := False; - Only_UOIs : Boolean := False) + Language : Any_Language; + Only_UOIs : Boolean := False) is procedure Process_Source_File (Info : File_Info; Unit_Name : String); -- Callback for Iterate_Source_File. If Only_UOIs is set to true, call @@ -613,11 +604,8 @@ package body Project is -- Otherwise, check if the unit is in the units of interest -- map - or else (Only_UOIs - and then (Unit_Map.Contains (To_Compilation_Unit (Info)) - and then (Info.Unit_Part /= Unit_Separate - or else Include_Stubs))) or else not Only_UOIs + or else Unit_Map.Contains (To_Compilation_Unit (Info)) then Callback (Info.Project, Info); end if; @@ -631,8 +619,7 @@ package body Project is Iterate_Source_Files (Prj_Info.Project, Process_Source_File'Access, - Recursive => False, - Include_Stubs => Include_Stubs); + Recursive => False); end loop; end Enumerate_Sources; @@ -984,9 +971,7 @@ package body Project is -- Units attributes only apply to the project itself. Iterate_Source_Files - (Project, Process_Source_File'Access, - Recursive => False, - Include_Stubs => True); + (Project, Process_Source_File'Access, Recursive => False); Inc_Units_Defined := True; end; end if; @@ -1265,8 +1250,7 @@ package body Project is -- source file name. Iterate_Source_Files - (Prj, Process_Source_File'Access, - Recursive => False, Include_Stubs => True); + (Prj, Process_Source_File'Access, Recursive => False); for Pattern of Patterns_Not_Covered loop Warn ("no unit " & (+Pattern) & " in project " & Prj.Name & " (" diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 7734d262a..c813028a5 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -159,16 +159,12 @@ package Project is (Project : GNATCOLL.Projects.Project_Type; File : GNATCOLL.Projects.File_Info); Language : Any_Language; - Include_Stubs : Boolean := False; Only_UOIs : Boolean := False) with Pre => Is_Project_Loaded; -- Call Callback once for every source file of the given language -- mentionned in a previous Add_Project call. If Only_UOIs is set to True, -- only call Callback on sources that are units of interest. Override_Units -- has the same semantics as in Enumerate_LIs. - -- - -- If Include_Stubs is false (the default) then Callback will skip - -- sources files that are subunits (Ada) or headers (C/C++). type Main_Source_File is record File : GNATCOLL.VFS.Virtual_File; From bfae98accf8f4c9bb2aca8e918a148d9372c551c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 18 Mar 2025 15:32:44 +0000 Subject: [PATCH 1164/1483] Instrument: remove dead code --- tools/gnatcov/instrument.adb | 21 --------------------- tools/gnatcov/instrument.ads | 7 ------- 2 files changed, 28 deletions(-) diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index c7afa1915..a97c2ee9e 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -437,27 +437,6 @@ package body Instrument is end case; end To_Compilation_Unit_Name; - ----------------- - -- To_Filename -- - ----------------- - - function To_Filename - (Project : Project_Type; - CU_Name : Compilation_Unit_Part; - Language : Any_Language) return String is - begin - case CU_Name.Language_Kind is - when Unit_Based_Language => - return +Project.File_From_Unit - (Unit_Name => To_Ada (CU_Name.Unit), - Part => CU_Name.Part, - Language => Image (Language), - File_Must_Exist => False); - when File_Based_Language => - return +CU_Name.Filename; - end case; - end To_Filename; - ---------------------------- -- Find_Instrumented_Unit -- ---------------------------- diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 88115be4b..da6ad33dd 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -204,13 +204,6 @@ package Instrument is -- Return the compilation unit name corresponding to the unit in -- Source_File. - function To_Filename - (Project : Project_Type; - CU_Name : Compilation_Unit_Part; - Language : Any_Language) return String; - -- Return the name of the file to contain the given compilation unit, - -- according to Project's naming scheme. - package Instrumented_Unit_To_CU_Maps is new Ada.Containers.Ordered_Maps (Key_Type => Compilation_Unit_Part, Element_Type => CU_Id); From 1a5f19ad3277f4ae0c119cb0dc10b4ff91c140fc Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 25 Mar 2025 13:03:16 +0000 Subject: [PATCH 1165/1483] Instrument.Common.To_Filename: remove the language argument Ada is the only supported languages that is unit-based, so hardcode it for now. The upcoming transition to GPR2 will delegate the handling of unit-based languages to the GPR2 project (Ada projects are always instrumented using a GPR file). --- tools/gnatcov/instrument-ada_unit.adb | 21 ++++--------- tools/gnatcov/instrument-common.adb | 45 ++++++++++++++------------- tools/gnatcov/instrument-common.ads | 4 +-- 3 files changed, 30 insertions(+), 40 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 4348cb18f..c86a322b7 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -10269,8 +10269,7 @@ package body Instrument.Ada_Unit is Pkg_Name : constant String := To_Ada (Buffer_Unit.Unit); -- Package name for the buffer unit - Filename : constant String := - To_Filename (Prj, Ada_Language, Buffer_Unit); + Filename : constant String := To_Filename (Prj, Buffer_Unit); File : Text_Files.File_Type; Last_Buffer_Index : constant Natural := Natural (Unit_Bits.Length); @@ -10456,8 +10455,7 @@ package body Instrument.Ada_Unit is is Last_Buffer_Index : constant Natural := Natural (CU_Names.Length); Pkg_Name : constant String := To_Ada (PB_Unit.Unit); - Filename : constant String := - New_File (Prj, To_Filename (Prj, Ada_Language, PB_Unit)); + Filename : constant String := New_File (Prj, To_Filename (Prj, PB_Unit)); File : Text_Files.File_Type; procedure Put_Language_Version_Pragma; @@ -10551,7 +10549,7 @@ package body Instrument.Ada_Unit is Unit => PB_Unit.Unit, Part => GNATCOLL.Projects.Unit_Body); PB_Filename : constant String := - New_File (Prj, To_Filename (Prj, Ada_Language, PB_Unit_Body)); + New_File (Prj, To_Filename (Prj, PB_Unit_Body)); begin File.Create (PB_Filename); @@ -10676,12 +10674,10 @@ package body Instrument.Ada_Unit is Spec_Filename : constant String := To_Filename (Prj, - Ada_Language, CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Spec)); Body_Filename : constant String := To_Filename (Prj, - Ada_Language, CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Body)); Helper_Unit_Name : constant String := To_Ada (Helper_Unit); @@ -11017,8 +11013,7 @@ package body Instrument.Ada_Unit is CU_Name_For_Unit (Buffers_List_Unit (Prj.Prj_Name), GNATCOLL.Projects.Unit_Spec); Unit_Name : constant String := To_Ada (Buffers_CU_Name.Unit); - Filename : constant String := - To_Filename (Prj, Ada_Language, Buffers_CU_Name); + Filename : constant String := To_Filename (Prj, Buffers_CU_Name); File : Text_Files.File_Type; begin if Sources_Trace.Is_Active then @@ -11137,13 +11132,9 @@ package body Instrument.Ada_Unit is Obs_Unit_Name : constant String := To_Ada (Obs_Unit); Obs_Spec_Filename : constant String := To_Filename - (Prj, - Ada_Language, - CU_Name_For_Unit (Obs_Unit, GNATCOLL.Projects.Unit_Spec)); + (Prj, CU_Name_For_Unit (Obs_Unit, GNATCOLL.Projects.Unit_Spec)); Obs_Body_Filename : constant String := To_Filename - (Prj, - Ada_Language, - CU_Name_For_Unit (Obs_Unit, GNATCOLL.Projects.Unit_Body)); + (Prj, CU_Name_For_Unit (Obs_Unit, GNATCOLL.Projects.Unit_Body)); Spec_File : Text_Files.File_Type; Body_File : Text_Files.File_Type; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 0aba796a4..cc70ccb3c 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -427,33 +427,34 @@ package body Instrument.Common is ----------------- function To_Filename - (Prj : Prj_Desc; - Lang : Src_Supported_Language; - CU_Name : Compilation_Unit_Part) return String - is - Filename : Unbounded_String; + (Prj : Prj_Desc; CU_Name : Compilation_Unit_Part) return String is begin case CU_Name.Language_Kind is when Unit_Based_Language => - for Id of CU_Name.Unit loop - if Filename /= "" then - Append (Filename, Prj.Dot_Replacement); - end if; - Append (Filename, To_Lower (To_String (Id))); - end loop; - - case CU_Name.Part is - when GNATCOLL.Projects.Unit_Body - | GNATCOLL.Projects.Unit_Separate - => - Append (Filename, Prj.Body_Suffix (Lang)); - when GNATCOLL.Projects.Unit_Spec => - Append (Filename, Prj.Spec_Suffix (Lang)); - end case; + declare + Filename : Unbounded_String; + begin + for Id of CU_Name.Unit loop + if Filename /= "" then + Append (Filename, Prj.Dot_Replacement); + end if; + Append (Filename, To_Lower (To_String (Id))); + end loop; + + case CU_Name.Part is + when GNATCOLL.Projects.Unit_Body + | GNATCOLL.Projects.Unit_Separate + => + Append (Filename, Prj.Body_Suffix (Ada_Language)); + when GNATCOLL.Projects.Unit_Spec => + Append (Filename, Prj.Spec_Suffix (Ada_Language)); + end case; + + return +Filename; + end; when File_Based_Language => - Filename := CU_Name.Filename; + return +CU_Name.Filename; end case; - return +Filename; end To_Filename; ----------------- diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 84f7c393b..d5e987d0f 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -576,9 +576,7 @@ package Instrument.Common is -- cases, the basename is taken and the file is created in Prj.Output_Dir. function To_Filename - (Prj : Prj_Desc; - Lang : Src_Supported_Language; - CU_Name : Compilation_Unit_Part) return String; + (Prj : Prj_Desc; CU_Name : Compilation_Unit_Part) return String; -- Convert a Compilation_Unit_Name to a file basename, using the body / -- spec suffix and dot replacement (for unit based languages) defined in -- Prj. From 8ed5f4d9454e0f47ce4095f02ce49b853b07e5d8 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 28 Mar 2025 11:27:03 +0100 Subject: [PATCH 1166/1483] Fix windows build regressions introduced in !790 --- tools/gnatcov/clang-wrapper.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index c9d3b848a..6d1ce4b49 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -20,8 +20,6 @@ /* Make sure we refer to the static version of symbols on Windows, not to DLL importers. */ -#include "clang-c/CXSourceLocation.h" -#include "clang/AST/Expr.h" #define CINDEX_NO_EXPORTS #include "libclang/CXCursor.h" From 25f9673e8328eec7c4d9f47af4c8682cff55fcec Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 19 Mar 2025 11:12:03 +0100 Subject: [PATCH 1167/1483] Support passing directory arguments For the switches accepting files as arguments, i.e. --trace and --sid. --- .../tests/instr-cov/399-dir-arg/test.opt | 1 + testsuite/tests/instr-cov/399-dir-arg/test.py | 49 ++++++++++++++ .../tests/instr-cov/399-dir-arg/test_1.adb | 4 ++ .../tests/instr-cov/399-dir-arg/test_2.adb | 4 ++ tools/gnatcov/command_line.ads | 5 +- tools/gnatcov/gnatcov_bits_specific.adb | 67 +++++++++++++++++-- tools/gnatcov/switches.adb | 56 +++++++++++++++- tools/gnatcov/switches.ads | 20 ++++++ 8 files changed, 198 insertions(+), 8 deletions(-) create mode 100644 testsuite/tests/instr-cov/399-dir-arg/test.opt create mode 100644 testsuite/tests/instr-cov/399-dir-arg/test.py create mode 100644 testsuite/tests/instr-cov/399-dir-arg/test_1.adb create mode 100644 testsuite/tests/instr-cov/399-dir-arg/test_2.adb diff --git a/testsuite/tests/instr-cov/399-dir-arg/test.opt b/testsuite/tests/instr-cov/399-dir-arg/test.opt new file mode 100644 index 000000000..f4513c683 --- /dev/null +++ b/testsuite/tests/instr-cov/399-dir-arg/test.opt @@ -0,0 +1 @@ +!native DEAD Use GNATCOV_TRACE_FILE feature only available with the binary file dump-channel diff --git a/testsuite/tests/instr-cov/399-dir-arg/test.py b/testsuite/tests/instr-cov/399-dir-arg/test.py new file mode 100644 index 000000000..6b26aa433 --- /dev/null +++ b/testsuite/tests/instr-cov/399-dir-arg/test.py @@ -0,0 +1,49 @@ +""" +Check that gnatcov accepts directory arguments for the --trace and +--sid switches. +""" + +import os +import os.path + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + +Wdir("tmp_") + +os.mkdir("traces-dir") +env = dict(os.environ) +env.update({"GNATCOV_TRACE_FILE": "traces-dir/"}) +build_and_run( + gprsw=GPRswitches(gprfor(srcdirs=[".."], mains=["test_1", "test_2"])), + covlevel="stmt", + mains=["test_1", "test_2"], + extra_coverage_args=[], + trace_mode="src", + program_env=env, +) +xcov( + [ + "coverage", + "--level=stmt", + "--annotate=xcov", + "--sid", + "obj/", + "--trace", + "traces-dir/", + ] +) + +# Check that the coverage report is as expected +check_xcov_reports( + ".", + { + "test_1.adb.xcov": {"+": {3}}, + "test_2.adb.xcov": {"+": {3}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/399-dir-arg/test_1.adb b/testsuite/tests/instr-cov/399-dir-arg/test_1.adb new file mode 100644 index 000000000..130d8e00f --- /dev/null +++ b/testsuite/tests/instr-cov/399-dir-arg/test_1.adb @@ -0,0 +1,4 @@ +procedure Test_1 is +begin + null; +end Test_1; diff --git a/testsuite/tests/instr-cov/399-dir-arg/test_2.adb b/testsuite/tests/instr-cov/399-dir-arg/test_2.adb new file mode 100644 index 000000000..1023c044d --- /dev/null +++ b/testsuite/tests/instr-cov/399-dir-arg/test_2.adb @@ -0,0 +1,4 @@ +procedure Test_2 is +begin + null; +end Test_2; diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 9802f7d56..5e5154d9a 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -1519,7 +1519,10 @@ package Command_Line is (Long_Name => "--trace", Short_Name => "-T", Pattern => "[TRACE|@LISTFILE]", - Help => "Specify trace files to read.", + Help => + "Specify trace files to read. If the path ends with a directory " + & " separator, consider it is a directory path containing the list" + & " of traces to be read.", Commands => (Cmd_Coverage | Cmd_Dump_Trace | Cmd_Dump_Trace_Raw diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 2ba0c2011..11329a5ba 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -533,7 +533,37 @@ procedure GNATcov_Bits_Specific is Invalidate_Unit_List ("--scos is present"); end if; - Copy_Arg_List (Opt_SID, SID_Inputs); + declare + procedure Process_Dir_Entry (Dir_Entry : Directory_Entry_Type); + + procedure Process_Arg (Exp_Arg : String); + + ----------------------- + -- Process_Dir_Entry -- + ----------------------- + + procedure Process_Dir_Entry (Dir_Entry : Directory_Entry_Type) is + begin + SID_Inputs.Append (+Full_Name (Dir_Entry)); + end Process_Dir_Entry; + + ----------------- + -- Process_Arg -- + ----------------- + + procedure Process_Arg (Exp_Arg : String) is + begin + SID_Inputs.Append (+Exp_Arg); + end Process_Arg; + + begin + Switches.Process_File_Or_Dir_Switch + (Args => Args.String_List_Args (Opt_SID), + Orig_Switch => "--sid", + Process_Dir_Entry => Process_Dir_Entry'Access, + Process_Arg => Process_Arg'Access, + Pattern => "*.sid"); + end; if not SID_Inputs.Is_Empty then Invalidate_Unit_List ("--sid is present"); end if; @@ -681,11 +711,36 @@ procedure GNATcov_Bits_Specific is (+Args.String_Args (Opt_Output_Directory).Value); end if; - for Arg of Args.String_List_Args (Opt_Trace) loop - for Exp_Arg of Expand_Argument (+Arg) loop - Handle_Trace_List_Element (+Exp_Arg); - end loop; - end loop; + declare + procedure Process_Dir_Entry (Dir_Entry : Directory_Entry_Type); + + procedure Process_Arg (Exp_Arg : String); + + ----------------------- + -- Process_Dir_Entry -- + ----------------------- + + procedure Process_Dir_Entry (Dir_Entry : Directory_Entry_Type) is + begin + Trace_Inputs.Append ((+Full_Name (Dir_Entry), Current_Exec)); + end Process_Dir_Entry; + + ----------------- + -- Process_Arg -- + ----------------- + + procedure Process_Arg (Exp_Arg : String) is + begin + Handle_Trace_List_Element (Exp_Arg); + end Process_Arg; + + begin + Switches.Process_File_Or_Dir_Switch + (Args => Args.String_List_Args (Opt_Trace), + Orig_Switch => "--trace", + Process_Dir_Entry => Process_Dir_Entry'Access, + Process_Arg => Process_Arg'Access); + end; if Args.String_Args (Opt_Trace_Source).Present then Convert.Set_Trace_Source (+Args.String_Args (Opt_Trace_Source).Value); diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 8070a7bef..02c928061 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -19,7 +19,6 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Command_Line; with Ada.Containers; use Ada.Containers; -with Ada.Directories; with Ada.Strings.Fixed; with Ada.Text_IO; use Ada.Text_IO; @@ -158,6 +157,61 @@ package body Switches is end loop; end Copy_Arg_List; + -------------------------------- + -- Process_File_Or_Dir_Switch -- + -------------------------------- + + procedure Process_File_Or_Dir_Switch + (Args : String_Vectors.Vector; + Orig_Switch : String; + Process_Dir_Entry : access procedure + (Dir : Ada.Directories.Directory_Entry_Type); + Process_Arg : access procedure (Exp_Arg : String); + Pattern : String := "") + is + use Ada.Directories; + use US; + begin + for Arg of Args loop + + -- The argument is either a directory or a file / response file when + -- prefixed with a '@'. + + -- First, deal with the case when it is a directory. + + if US.Element (Arg, Length (Arg)) in '/' | '\' then + declare + Path : constant String := +Arg; + S : Search_Type; + Dir_Entry : Directory_Entry_Type; + begin + if Kind (Path) = Directory then + Start_Search + (Search => S, + Directory => Path, + Pattern => Pattern, + Filter => (Ordinary_File => True, others => False)); + + while More_Entries (S) loop + Get_Next_Entry (S, Dir_Entry); + Process_Dir_Entry (Dir_Entry); + end loop; + End_Search (S); + else + Outputs.Warn + ("Skipping processing of " & Orig_Switch & " argument " + & Path & ". Expecting a directory but got a " + & Ada.Directories.File_Kind'Image (Kind (Path)) & "."); + end if; + end; + else + for Exp_Arg of Expand_Argument (+Arg) loop + Process_Arg (+Exp_Arg); + end loop; + end if; + end loop; + end Process_File_Or_Dir_Switch; + ---------------------- -- Load_Dump_Config -- ---------------------- diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index bcc8b832f..9a3e3a608 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -17,6 +17,7 @@ ------------------------------------------------------------------------------ with Ada.Containers.Indefinite_Ordered_Maps; +with Ada.Directories; with Ada.Exceptions; with GNAT.Strings; use GNAT.Strings; @@ -99,6 +100,25 @@ package Switches is -- expanding arguments that start with '@' according to rules described in -- Inputs.Expand_Argument. + procedure Process_File_Or_Dir_Switch + (Args : String_Vectors.Vector; + Orig_Switch : String; + Process_Dir_Entry : access procedure + (Dir : Ada.Directories.Directory_Entry_Type); + Process_Arg : access procedure (Exp_Arg : String); + Pattern : String := ""); + -- This procedure is dedicated to switches accepting a list of files, e.g. + -- --trace, which are either to be passed as an explicit list of files / + -- response file, or as a directory (thus ending with a directory + -- separator) containing a list of files. + -- + -- Args is the list of arguments, Orig_Switch is the name of the switch + -- for proper error messaging. Process_Dir_Entry processes a directory + -- entry belonging to one of the directory arguments. Process_Arg processes + -- a file explicitly passed on the command line / response file (expanded). + -- If not empty, Pattern is the file pattern to look for in directory + -- arguments. + ---------------------------- -- Miscellaneous switches -- ---------------------------- From ace318cce5948f788163e15658367fc985b7aefc Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 31 Mar 2025 12:02:17 +0200 Subject: [PATCH 1168/1483] Instrument(observability): Fix endianness/integer casting bug in observability --- tools/gnatcov/instrument-ada_unit.adb | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index c86a322b7..5ff3127c8 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -11146,7 +11146,7 @@ package body Instrument.Ada_Unit is Spec_File.Put_Line (" function Sum_Buffer_Bits return Natural;"); Spec_File.Put_Line ("end " & Obs_Unit_Name & ";"); - Body_File.Put_Line ("with Interfaces.C;"); + Body_File.Put_Line ("with Interfaces;"); Body_File.Put_Line ("with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists;"); Body_File.New_Line; @@ -11155,14 +11155,17 @@ package body Instrument.Ada_Unit is Body_File.Put_Line (" function Sum_Buffer_Bits_C"); Body_File.Put_Line (" (C_List : GNATcov_RTS_Coverage_Buffers_Group_Array)"); - Body_File.Put_Line (" return Interfaces.C.unsigned_long;"); + Body_File.Put_Line (" return Interfaces.Unsigned_64;"); Body_File.Put_Line ("pragma Import (C, Sum_Buffer_Bits_C," & " ""gnatcov_rts_sum_buffer_bits"");"); Body_File.Put_Line (" begin"); Body_File.Put_Line - (" return Natural(Sum_Buffer_Bits_C (" - & Buf_List_Unit_Name & ".C_List));"); + (" return Natural" & ASCII.LF & + " (Interfaces.Unsigned_64'Min" & ASCII.LF & + " (Sum_Buffer_Bits_C (" & Buf_List_Unit_Name & ".C_List)," + & ASCII.LF & + " Interfaces.Unsigned_64 (Natural'Last)));"); Body_File.Put_Line (" end;"); Body_File.Put_Line ("end " & Obs_Unit_Name & ";"); From c86f33da3ca23b8c0aed3bb6669cfcdef03a50f1 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 31 Mar 2025 12:26:42 +0200 Subject: [PATCH 1169/1483] Add explicit warning tolerance to tests Now that the testsuite check for warnings in all of gnatcov commands, rather than only instrumentation. --- testsuite/tests/IA22-004-same-basename/test.py | 4 +++- testsuite/tests/L929-006/test.py | 8 ++++++-- .../tests/U211-014-setup/ext_rt/gnatcov_rts-base_io.adb | 2 ++ 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/IA22-004-same-basename/test.py b/testsuite/tests/IA22-004-same-basename/test.py index d35340357..3d4b2f481 100644 --- a/testsuite/tests/IA22-004-same-basename/test.py +++ b/testsuite/tests/IA22-004-same-basename/test.py @@ -63,7 +63,9 @@ def hostify(path): "main.elf.trace", "--output-dir=tmp", ] - + rebase_args + + rebase_args, + # The files generated by the binder are not available at coverage time + tolerate_messages="warning: can't open", ) for slug in ("d1-func.c", "d2-func.c"): diff --git a/testsuite/tests/L929-006/test.py b/testsuite/tests/L929-006/test.py index c6589c644..987697d50 100644 --- a/testsuite/tests/L929-006/test.py +++ b/testsuite/tests/L929-006/test.py @@ -25,14 +25,18 @@ def to_object(sfile): out_actual = target + "-actual.out" out_expected = "../" + target + "-expected.out" - xcov(["scan-objects"] + ofiles, out=out_actual) + xcov(["scan-objects"] + ofiles, out=out_actual, tolerate_messages=".") thistest.fail_if( diff(out_actual, out_expected), "%s != %s, using explicit list" % (out_actual, out_expected), ) - xcov(["scan-objects", "@" + list_to_file(ofiles)], out=out_actual) + xcov( + ["scan-objects", "@" + list_to_file(ofiles)], + out=out_actual, + tolerate_messages=".", + ) thistest.fail_if( diff(out_actual, out_expected), diff --git a/testsuite/tests/U211-014-setup/ext_rt/gnatcov_rts-base_io.adb b/testsuite/tests/U211-014-setup/ext_rt/gnatcov_rts-base_io.adb index 4e0b62c37..5991c02cd 100644 --- a/testsuite/tests/U211-014-setup/ext_rt/gnatcov_rts-base_io.adb +++ b/testsuite/tests/U211-014-setup/ext_rt/gnatcov_rts-base_io.adb @@ -37,8 +37,10 @@ package body GNATcov_RTS.Base_Io is --------- procedure Put (S : GNATcov_RTS_String) is + pragma Warnings (Off); Str : String (1 .. Integer (S.Length)); for Str'Address use S.Str; + pragma Warning (On); begin Print_Tag; GNAT.IO.Put_Line (Str); From 91c42a58cfbdec2d141251f6d2f8e75f0d41d9fd Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 2 Apr 2025 11:57:27 +0200 Subject: [PATCH 1170/1483] testsuite.py: fix style warnings --- testsuite/tests/ext_annotations/gen/buffer_reset/test.py | 2 +- testsuite/tests/instr-cov/buffer_reset/test.py | 2 +- .../integrated_instrumentation/cmake_include_switch/test.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/ext_annotations/gen/buffer_reset/test.py b/testsuite/tests/ext_annotations/gen/buffer_reset/test.py index 76e6aa253..af8324cb8 100644 --- a/testsuite/tests/ext_annotations/gen/buffer_reset/test.py +++ b/testsuite/tests/ext_annotations/gen/buffer_reset/test.py @@ -113,7 +113,7 @@ def check_one_exec(cov_args, lang): traces.sort() for i in range(len(traces)): - thistest.log(f"-- {i+1}. --") + thistest.log(f"-- {i + 1}. --") output_dir = f"output_{lang}_{i}/" xcov( cov_args + [f"--output-dir={output_dir}", traces[i]], diff --git a/testsuite/tests/instr-cov/buffer_reset/test.py b/testsuite/tests/instr-cov/buffer_reset/test.py index c2d966026..be2244ded 100644 --- a/testsuite/tests/instr-cov/buffer_reset/test.py +++ b/testsuite/tests/instr-cov/buffer_reset/test.py @@ -93,7 +93,7 @@ def check_one_exec(cov_args, lang): traces.sort() for i in range(len(traces)): - thistest.log(f"-- {i+1}. --") + thistest.log(f"-- {i + 1}. --") output_dir = f"output_{lang}_{i}/" xcov( cov_args + [f"--output-dir={output_dir}", traces[i]], diff --git a/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py b/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py index 281bff3ce..9f44f8387 100644 --- a/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py +++ b/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.py @@ -23,7 +23,7 @@ def process(c_flags, subdir): "setup-integration", "--level=stmt", f"--files={os.path.join(cwd, '..', 'main.c')}", - f"--files={os.path.join(cwd, '..','pkg.h')}", + f"--files={os.path.join(cwd, '..', 'pkg.h')}", "--compilers=gcc", ] ) From 5adc3144bf094278c80a0d9ae5df4b3e82d05be6 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 9 Apr 2025 12:14:00 +0200 Subject: [PATCH 1171/1483] doc(gnattest): Document recursive stubbing --- doc/gnattest/gnattest_part.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/gnattest/gnattest_part.rst b/doc/gnattest/gnattest_part.rst index 4b099d7f9..09437a53b 100644 --- a/doc/gnattest/gnattest_part.rst +++ b/doc/gnattest/gnattest_part.rst @@ -250,6 +250,13 @@ Switches for ``gnattest`` in framework generation mode code under test. + .. index:: --recursive-stub (gnattest) + +:switch:`--recursive-stub` + Used along --stub, indicates gnattest to generate stubs for all the packages + that are withed by the stubbed units, recursively. + + .. index:: --harness-dir (gnattest) :switch:`--harness-dir={dirname}` From c2097fa1e61350f2aca45b3096c7e98c725dce12 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 28 Feb 2025 09:55:45 +0000 Subject: [PATCH 1172/1483] sc_obligations.ads: add handling for the new Program_Exit pragma/aspect (cherry picked from commit c87a046d628ba0ecf746f341fc4b5578cb8e3900) --- tools/gnatcov/sc_obligations.ads | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 3c0e2e090..24bcdea5e 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -1190,6 +1190,7 @@ package SC_Obligations is Pragma_Profile, Pragma_Profile_Warnings, Pragma_Propagate_Exceptions, + Pragma_Program_Exit, Pragma_Provide_Shift_Operators, Pragma_Psect_Object, Pragma_Pure, @@ -1540,15 +1541,17 @@ package SC_Obligations is Pragma_Storage_Size => False, Pragma_Storage_Unit => False, - -- Special case for pre/postcondition: these do not generate code - -- at their normal point of occurrence in the instruction flow, - -- and in the case of instrumentation based coverage, they cannot - -- be instrumented because of their special placement rules. So, - -- we mark them as generating no code, and we treat them as - -- "free-standing" decisions (outside of statement context). + -- Special case for pre/postconditions (Program_Exit is processed + -- like a postcondition): these do not generate code at their normal + -- point of occurrence in the instruction flow, and in the case of + -- instrumentation based coverage, they cannot be instrumented + -- because of their special placement rules. So, we mark them as + -- generating no code, and we treat them as "free-standing" + -- decisions (outside of statement context). Pragma_Postcondition => False, Pragma_Precondition => False, + Pragma_Program_Exit => False, -- Now pragmas which might generate code. This is an explicit list -- instead of a mere "others" fallback to make sure we notice when From 9831288c42e51655e9c1ff0e6e6dcbb2a7ee4838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 5 Mar 2025 09:29:54 +0100 Subject: [PATCH 1173/1483] Add missing language version pragma to UIndexed test The language configuration pragmas do not propagate from spec to body, we thus need to have one in the fuor.adb file as well to use custom indexing. This was not caught before by gnat due to a bug. (cherry picked from commit aff42434386c6876aeb802feec6b2c5fb7b683d6) --- testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor.adb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor.adb b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor.adb index e2f187b43..6337f3936 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor.adb +++ b/testsuite/Qualif/Ada/mcdc/1_Core/Operands/Uindexed/src/fuor.adb @@ -1,3 +1,5 @@ +pragma Ada_2012; + package body FUOR is function Orelse (Ops : Operands) return Boolean is From 96faf07099d16cfebd9dd1c134be719f9b62709d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 10 Mar 2025 14:50:50 +0000 Subject: [PATCH 1174/1483] instr-cov/386-setup-invalid-target: update baseline Update the baseline for the output of "gnatcov setup" after a change in GPR2. (cherry picked from commit 2c26a1c0bc815c61d93494904502e0ef0f817fc6) --- testsuite/tests/instr-cov/386-setup-invalid-target/test.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/instr-cov/386-setup-invalid-target/test.py b/testsuite/tests/instr-cov/386-setup-invalid-target/test.py index 18f8ab077..75e110663 100644 --- a/testsuite/tests/instr-cov/386-setup-invalid-target/test.py +++ b/testsuite/tests/instr-cov/386-setup-invalid-target/test.py @@ -32,8 +32,11 @@ thistest.fail_if_no_match( "Unexpectect 'gnatcov setup' output", regexp=( - r".*gnatcov(.exe)?: Cannot get library support for this" - r" configuration" + "kb: warning: can't find a toolchain for the following configuration:" + " language 'Ada', target 'INVALID', default runtime\n" + "kb: warning: can't find a toolchain for the following configuration:" + " language 'C', target 'INVALID', default runtime\n" + ".*gnatcov(.exe)?: Cannot get library support for this configuration" ), actual=contents_of(setup_log).strip(), ) From cbafde16796864df7c7ee1bcd92095bc43229274 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 12 Mar 2025 16:25:13 +0000 Subject: [PATCH 1175/1483] instr-cov/386-setup-invalid-target: update baseline (again) (cherry picked from commit 09a93af0f581ffc461abf9e4eb171d91aed3696a) --- testsuite/tests/instr-cov/386-setup-invalid-target/test.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/instr-cov/386-setup-invalid-target/test.py b/testsuite/tests/instr-cov/386-setup-invalid-target/test.py index 75e110663..1425bef11 100644 --- a/testsuite/tests/instr-cov/386-setup-invalid-target/test.py +++ b/testsuite/tests/instr-cov/386-setup-invalid-target/test.py @@ -32,9 +32,9 @@ thistest.fail_if_no_match( "Unexpectect 'gnatcov setup' output", regexp=( - "kb: warning: can't find a toolchain for the following configuration:" + "kb: info: can't find a toolchain for the following configuration:" " language 'Ada', target 'INVALID', default runtime\n" - "kb: warning: can't find a toolchain for the following configuration:" + "kb: info: can't find a toolchain for the following configuration:" " language 'C', target 'INVALID', default runtime\n" ".*gnatcov(.exe)?: Cannot get library support for this configuration" ), From ee9c683ae798ea2ff27ab4bfe1fb5b5e1f22b92c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 16 Jan 2025 13:28:17 +0000 Subject: [PATCH 1176/1483] Transition uses of GNATCOLL.Projects to GPR2 --- .../{missing-srcdir => regular}/main.adb | 0 .../tests/255-warnings-as-errors/test.py | 42 +- .../tests/P913-011-invalid-project/test.py | 24 +- .../instr-cov/logging/baseline-my_tool.txt | 2 +- .../instr-cov/logging/baseline-tests.txt | 8 +- tools/gnatcov/annotations-dynamic_html.adb | 26 +- tools/gnatcov/coverage-source.adb | 26 +- tools/gnatcov/gnatcov.adb | 3 +- tools/gnatcov/gnatcov_bits_specific.adb | 5 +- .../gnatcov/instrument-ada_preprocessing.adb | 2 +- tools/gnatcov/instrument-ada_unit.adb | 57 +- tools/gnatcov/instrument-ada_unit.ads | 10 +- tools/gnatcov/instrument-ada_unit__stub.ads | 1 - .../gnatcov/instrument-ada_unit_provider.adb | 173 +-- .../gnatcov/instrument-ada_unit_provider.ads | 29 +- tools/gnatcov/instrument-c.adb | 22 +- tools/gnatcov/instrument-c.ads | 3 +- tools/gnatcov/instrument-clean_objdirs.adb | 61 +- tools/gnatcov/instrument-common.adb | 53 +- tools/gnatcov/instrument-common.ads | 5 +- tools/gnatcov/instrument-config.adb | 2 - tools/gnatcov/instrument-projects.adb | 437 +++--- tools/gnatcov/instrument.adb | 50 +- tools/gnatcov/instrument.ads | 27 +- tools/gnatcov/project.adb | 1190 +++++++++-------- tools/gnatcov/project.ads | 105 +- tools/gnatcov/rundrv-handlers.adb | 4 +- tools/gnatcov/ss_annotations.adb | 79 +- tools/gnatcov/switches.adb | 49 +- tools/gnatcov/switches.ads | 12 + tools/gnatcov/traces_source.ads | 18 +- 31 files changed, 1312 insertions(+), 1213 deletions(-) rename testsuite/tests/255-warnings-as-errors/{missing-srcdir => regular}/main.adb (100%) diff --git a/testsuite/tests/255-warnings-as-errors/missing-srcdir/main.adb b/testsuite/tests/255-warnings-as-errors/regular/main.adb similarity index 100% rename from testsuite/tests/255-warnings-as-errors/missing-srcdir/main.adb rename to testsuite/tests/255-warnings-as-errors/regular/main.adb diff --git a/testsuite/tests/255-warnings-as-errors/test.py b/testsuite/tests/255-warnings-as-errors/test.py index e151b53e0..b373ab86a 100644 --- a/testsuite/tests/255-warnings-as-errors/test.py +++ b/testsuite/tests/255-warnings-as-errors/test.py @@ -4,8 +4,6 @@ import re -from e3.fs import mkdir, rm - from SCOV.instr import xcov_instrument from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of @@ -16,7 +14,7 @@ tmp = Wdir("tmp_") -def check(slug, project, warning): +def check(slug, project, warning, extra_args): """ Check that "gnatcov instrument" on the given project yields the expected warning, and that it exits with an error when --warnings-as-errors is @@ -29,6 +27,7 @@ def check(slug, project, warning): log = f"{slug}-sc.txt" process = xcov_instrument( gprsw=GPRswitches(root_project=project), + extra_args=extra_args, covlevel="stmt", register_failure=False, out=log, @@ -44,7 +43,7 @@ def check(slug, project, warning): process = xcov_instrument( gprsw=GPRswitches(root_project=project), covlevel="stmt", - extra_args=["--warnings-as-errors"], + extra_args=["--warnings-as-errors"] + extra_args, register_failure=False, out=log, ) @@ -57,37 +56,33 @@ def check(slug, project, warning): # Check the handling of warnings emitted before command line options (including -# --warnings-as-errors) are fully loaded. It also happens to be emitted by -# LibGPR. -# -# To achieve that, create a project with one listed source directory that does -# not exist and run "gnatcov instrument" on it: we expect a warning that -# complains about the missing directory. Note that we expect the warning twice: -# once for the wrapper gnatcov program, and one for the gnatcov64 program (both -# need to load the project). +# --warnings-as-errors) are fully loaded: this happens for warnings emitted by +# LibGPR2. # -# In order to create that project, we need to temporarily create that source -# directory so that gprfor does not strip it automagically. -missing_dir = "foobar" -mkdir(missing_dir) +# To trigger them, just try to load a project with both --target and --config +# arguments. Note that we expect the warning twice: once for the wrapper +# gnatcov program, and one for the gnatcov64 program (both need to load the +# project). project = gprfor( - prjid="missing_srcdir", + prjid="regular", mains=["main.adb"], - srcdirs=["../missing-srcdir", missing_dir], + srcdirs=["../regular"], ) -rm(missing_dir, recursive=True) check( - "missing-srcdir", + "project-warning", project, - '.*warning: "foobar" is not a valid directory' - '\n\n.*warning: "foobar" is not a valid directory\n', + "suite.cgpr:.*: error: --target: 'foo' is different from the target value" + " in the configuration project '.*'" + "\nsuite.cgpr:.*: error: --target: 'foo' is different from the target" + " value in the configuration project '.*'", + extra_args=["--target=foo"], ) # Create a project with a missing source file, on which the Ada instrumenter # will complain. This checks the handling of warnings emitted after command # line options are fully loaded. check( - "missing-srcfile", + "instrumenter-warning", gprfor( prjid="missing_srcfile", mains=["main.adb"], @@ -97,6 +92,7 @@ def check(slug, project, warning): "warning: While instrumenting main.adb..." "\nwarning: Cannot find required source file: pkg.ads" ), + extra_args=[], ) thistest.result() diff --git a/testsuite/tests/P913-011-invalid-project/test.py b/testsuite/tests/P913-011-invalid-project/test.py index 2e6ee8dad..b8a23e768 100644 --- a/testsuite/tests/P913-011-invalid-project/test.py +++ b/testsuite/tests/P913-011-invalid-project/test.py @@ -1,5 +1,3 @@ -import re - from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of from SUITE.tutils import exename_for, gprbuild, gprfor, xcov @@ -15,25 +13,19 @@ register_failure=False, ) -out_content = contents_of("gnatcov-run.out") -err_content = contents_of("gnatcov-run.err") -expected_err = re.compile( - "^does_not_exist.gpr is not a regular file\n" - "[^\n]*gnatcov(\\.exe)?: Could not load the project file, aborting.\n$" -) - thistest.fail_if( p.status != 1, "gnatcov returned status code {}, but 1 expected".format(p.status), ) -thistest.fail_if( - out_content, "gnatcov output not empty:\n" "\n{}\n".format(out_content) +thistest.fail_if_not_equal( + "'gnatcov run' output", "", contents_of("gnatcov-run.out") ) -thistest.fail_if( - not expected_err.match(err_content), - "gnatcov error output mismatch:\n" - "Expected pattern:\n{!r}\n\n" - "Got:\n{}".format(expected_err.pattern, err_content), +thistest.fail_if_no_match( + "'gnatcov run' error output", + 'does_not_exist\\.gpr: error: project file ".*[/\\\\]does_not_exist\\.gpr"' + " not found\n" + ".*gnatcov.*: Could not load the project file, aborting.\n$", + contents_of("gnatcov-run.err"), ) thistest.result() diff --git a/testsuite/tests/instr-cov/logging/baseline-my_tool.txt b/testsuite/tests/instr-cov/logging/baseline-my_tool.txt index c3d1df059..9a276ad33 100644 --- a/testsuite/tests/instr-cov/logging/baseline-my_tool.txt +++ b/testsuite/tests/instr-cov/logging/baseline-my_tool.txt @@ -1,4 +1,4 @@ -info: creating output path [TMP]/obj/my_tool/ +info: creating output path [TMP]/obj/my_tool [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing My_Tool [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/my_tool.gpr [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/my_tool/my_tool-gnatcov-instr diff --git a/testsuite/tests/instr-cov/logging/baseline-tests.txt b/testsuite/tests/instr-cov/logging/baseline-tests.txt index 69e788a18..6debef3d4 100644 --- a/testsuite/tests/instr-cov/logging/baseline-tests.txt +++ b/testsuite/tests/instr-cov/logging/baseline-tests.txt @@ -1,4 +1,4 @@ -info: creating output path [TMP]/obj/tests/ +info: creating output path [TMP]/obj/tests [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] Processing Mylib [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] GPR file: [TMP]/mylib.gpr [GNATCOV.INSTRUMENT_CLEAN_OBJDIRS] output directory: [TMP]/obj/mylib/mylib-gnatcov-instr @@ -19,20 +19,20 @@ Coverage instrumentation [GNATCOV.INSTRUMENT_SOURCES] Instrumenting mylib.ads [GNATCOV.INSTRUMENT_SOURCES] Instrumenting mylib.adb [GNATCOV.INSTRUMENT_SOURCES] Writing Ada buffer unit GCVRT.B[HASH#1] - [GNATCOV.INSTRUMENT_SOURCES] Project: Mylib + [GNATCOV.INSTRUMENT_SOURCES] Project: Mylib_Extended [GNATCOV.INSTRUMENT_SOURCES] Filename: gcvrt-b[HASH#1].ads [GNATCOV.INSTRUMENT_SOURCES] For units: [GNATCOV.INSTRUMENT_SOURCES] * mylib spec [GNATCOV.INSTRUMENT_SOURCES] * mylib body [GNATCOV.INSTRUMENT_SOURCES] Writing pure Ada buffer unit GCVRT.P[HASH#1] - [GNATCOV.INSTRUMENT_SOURCES] Project: Mylib + [GNATCOV.INSTRUMENT_SOURCES] Project: Mylib_Extended [GNATCOV.INSTRUMENT_SOURCES] Filename: [TMP]/obj/mylib_extended/mylib_extended-gnatcov-instr/gcvrt-p[HASH#1].ads [GNATCOV.INSTRUMENT_SOURCES] For units: [GNATCOV.INSTRUMENT_SOURCES] * mylib spec [GNATCOV.INSTRUMENT_SOURCES] * mylib body [C] mylib_ext.c [GNATCOV.INSTRUMENT_SOURCES] Writing C buffer unit [TMP]/obj/mylib_extended/mylib_extended-gnatcov-instr/gcvrt_b_[HASH#2].c - [GNATCOV.INSTRUMENT_SOURCES] Project: Mylib + [GNATCOV.INSTRUMENT_SOURCES] Project: Mylib_Extended [GNATCOV.INSTRUMENT_SOURCES] For files: [GNATCOV.INSTRUMENT_SOURCES] * [TMP]/src-mylib/mylib_ext.c Main instrumentation diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 7f37cfaab..758ceeb2e 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -23,7 +23,6 @@ with Ada.Text_IO; with Ada.Text_IO.Unbounded_IO; with GNATCOLL.JSON; use GNATCOLL.JSON; -with GNATCOLL.VFS; use GNATCOLL.VFS; with GNAT.OS_Lib; with GNAT.Regpat; use GNAT.Regpat; @@ -449,21 +448,16 @@ package body Annotations.Dynamic_Html is -- If the project was loaded, get the language information from it - declare - Lang : constant String := - Project.Project.Info (Create (+Info.Full_Name.all)).Language; - begin - case To_Language_Or_All (Lang) is - when Ada_Language => - Source.Set_Field ("language", "ada"); - when C_Language => - Source.Set_Field ("language", "c"); - when CPP_Language => - Source.Set_Field ("language", "cpp"); - when All_Languages => - null; - end case; - end; + case Language (Info.Full_Name.all) is + when Ada_Language => + Source.Set_Field ("language", "ada"); + when C_Language => + Source.Set_Field ("language", "c"); + when CPP_Language => + Source.Set_Field ("language", "cpp"); + when All_Languages => + null; + end case; else -- If no project was loaded, infer the language from the -- source extension. diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index d0a08d297..ee144d356 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -25,8 +25,8 @@ with Ada.Unchecked_Deallocation; with Interfaces; -with GNATCOLL.Projects; -with GNATCOLL.VFS; +with GPR2.Build.Source; +with GPR2.Project.View; with Binary_Files; use Binary_Files; with Coverage.Tags; use Coverage.Tags; @@ -340,8 +340,8 @@ package body Coverage.Source is use Types; procedure Callback - (Project : GNATCOLL.Projects.Project_Type; - File : GNATCOLL.Projects.File_Info); + (Project : GPR2.Project.View.Object; + File : GPR2.Build.Source.Object); -- If the file is a (sometimes) ignored file, compute its unit name and -- store it in the file table. @@ -350,13 +350,12 @@ package body Coverage.Source is -------------- procedure Callback - (Project : GNATCOLL.Projects.Project_Type; - File : GNATCOLL.Projects.File_Info) + (Project : GPR2.Project.View.Object; + File : GPR2.Build.Source.Object) 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); + (String (File.Path_Name.Value), Source_File, Insert => False); FI : constant File_Info_Access := (if SFI /= No_Source_File then Get_File (SFI) else null); @@ -2237,7 +2236,7 @@ package body Coverage.Source is procedure Set_Executed (SCI : in out Source_Coverage_Info); -- Mark SCI as executed - function Part_Image (Part : GNATCOLL.Projects.Unit_Parts) return String; + function Part_Image (Part : GPR2.Valid_Unit_Kind) return String; -- Helper to include Part in an error message function Unit_Image return String is @@ -2273,13 +2272,12 @@ package body Coverage.Source is -- Part_Image -- ---------------- - function Part_Image (Part : GNATCOLL.Projects.Unit_Parts) return String - is + function Part_Image (Part : GPR2.Valid_Unit_Kind) return String is begin return (case Part is - when GNATCOLL.Projects.Unit_Body => "body of", - when GNATCOLL.Projects.Unit_Spec => "spec of", - when GNATCOLL.Projects.Unit_Separate => "separate"); + when GPR2.S_Body => "body of", + when GPR2.S_Spec => "spec of", + when GPR2.S_Separate => "separate"); end Part_Image; ------------------------ diff --git a/tools/gnatcov/gnatcov.adb b/tools/gnatcov/gnatcov.adb index b4a15a7fd..ebe229f3b 100644 --- a/tools/gnatcov/gnatcov.adb +++ b/tools/gnatcov/gnatcov.adb @@ -25,7 +25,6 @@ with GNAT.Strings; use GNAT.Strings; with Command_Line; use Command_Line; with Outputs; use Outputs; -with Project; with Support_Files; with Switches; use Switches; @@ -122,5 +121,5 @@ exception when Xcov_Exit_Exc => -- An error message has already been displayed - Project.Finalize; + null; end GNATcov; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 11329a5ba..b6f5b764b 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -2632,8 +2632,6 @@ begin Perf_Counters.Display; end if; - Project.Finalize; - exception -- The following handler is for files that gnatcov could not locate or -- open. Display the corresponding error message. @@ -2641,12 +2639,11 @@ exception when Error : Binary_Files.Error | Ada.IO_Exceptions.Name_Error => Outputs.Error (Switches.Exception_Info (Error)); - Project.Finalize; -- Each chunk of code with "raise" statements for Xcov_Exit_Exc exceptions -- is supposed to print an error message and set a failure exit status -- before raising the exception. when Xcov_Exit_Exc => - Project.Finalize; + null; end GNATcov_Bits_Specific; diff --git a/tools/gnatcov/instrument-ada_preprocessing.adb b/tools/gnatcov/instrument-ada_preprocessing.adb index 9e3b418e7..03b1e3cb2 100644 --- a/tools/gnatcov/instrument-ada_preprocessing.adb +++ b/tools/gnatcov/instrument-ada_preprocessing.adb @@ -106,7 +106,7 @@ package body Instrument.Ada_Preprocessing is begin Extract_Preprocessor_Data_From_Project - (Tree => Project.Project.all, + (Tree => Project.Project, Default_Config => Default_Config, File_Configs => File_Configs); exception diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 5ff3127c8..0ba84c113 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -60,7 +60,6 @@ with Text_Files; use Text_Files; package body Instrument.Ada_Unit is - package GPR renames GNATCOLL.Projects; package LAL renames Libadalang.Analysis; package LALCO renames Libadalang.Common; @@ -91,10 +90,10 @@ package body Instrument.Ada_Unit is is (Instrument.Common.Format_Fingerprint (Fingerprint, "(", ")")); -- Helper to format a String literal for a fingerprint - function "+" (Part : Analysis_Unit_Kind) return GNATCOLL.Projects.Unit_Parts + function "+" (Part : Analysis_Unit_Kind) return GPR2.Valid_Unit_Kind is (case Part is - when LALCO.Unit_Body => GNATCOLL.Projects.Unit_Body, - when LALCO.Unit_Specification => GNATCOLL.Projects.Unit_Spec); + when LALCO.Unit_Body => GPR2.S_Body, + when LALCO.Unit_Specification => GPR2.S_Spec); function Referenced_Attribute (N : Ada_Node'Class) return Text_Type is (if N.Kind = Ada_Attribute_Ref @@ -202,9 +201,9 @@ package body Instrument.Ada_Unit is when Ada_Single_Tok_Node => declare - -- ??? GNATCOLL.Projects does not specify how to encode - -- Unicode unit names as strings, so for now, assume that we - -- process only codepoints in the ASCII range and thus use + -- ??? GPR2 does not specify how to encode Unicode unit + -- names as strings, so for now, assume that we process only + -- codepoints in the ASCII range and thus use -- Langkit_Support.Text.Image. Identifier : constant Ada_Identifier := @@ -8519,7 +8518,7 @@ package body Instrument.Ada_Unit is Main : Compilation_Unit_Part (Unit_Based_Language) := (Language_Kind => Unit_Based_Language, - Part => GNATCOLL.Projects.Unit_Body, + Part => GPR2.S_Body, others => <>); -- Note that we can't get the compilation unit name using the -- To_Compilation_Unit_Name overload taking a File_Info parameter, @@ -9457,14 +9456,14 @@ package body Instrument.Ada_Unit is overriding procedure Replace_Manual_Indications (Self : in out Ada_Instrumenter_Type; Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info; + Source : GPR2.Build.Source.Object; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean) is Instrumented_Filename : constant String := - +(Prj.Output_Dir & "/" & GNATCOLL.VFS."+" (Source.File.Base_Name)); + +(Prj.Output_Dir & "/" & String (Source.Path_Name.Simple_Name)); Source_Filename : constant String := - GNATCOLL.VFS."+" (Source.File.Full_Name); + String (Source.Path_Name.Value); Instrumented_Exists : constant Boolean := Ada.Directories.Exists (Instrumented_Filename); File_To_Search : constant String := (if Instrumented_Exists @@ -9915,7 +9914,7 @@ package body Instrument.Ada_Unit is -- compilation unit's contents. if UIC.Root_Unit.F_Body.Kind = Ada_Subunit then - CU_Name.Part := GNATCOLL.Projects.Unit_Separate; + CU_Name.Part := GPR2.S_Separate; end if; CU_Name.Unit := To_Qualified_Name @@ -10302,9 +10301,9 @@ package body Instrument.Ada_Unit is Unit_Part : constant String := (case CU_Name.Part is - when GPR.Unit_Spec => "Unit_Spec", - when GPR.Unit_Body => "Unit_Body", - when GPR.Unit_Separate => "Unit_Separate"); + when GPR2.S_Spec => "Unit_Spec", + when GPR2.S_Body => "Unit_Body", + when GPR2.S_Separate => "Unit_Separate"); -- Do not use 'Image so that we use the original casing for the -- enumerators, and thus avoid compilation warnings/errors. @@ -10547,7 +10546,7 @@ package body Instrument.Ada_Unit is PB_Unit_Body : constant Compilation_Unit_Part := (Language_Kind => Unit_Based_Language, Unit => PB_Unit.Unit, - Part => GNATCOLL.Projects.Unit_Body); + Part => GPR2.S_Body); PB_Filename : constant String := New_File (Prj, To_Filename (Prj, PB_Unit_Body)); begin @@ -10672,13 +10671,9 @@ package body Instrument.Ada_Unit is declare Spec_Filename : constant String := - To_Filename - (Prj, - CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Spec)); + To_Filename (Prj, CU_Name_For_Unit (Helper_Unit, GPR2.S_Spec)); Body_Filename : constant String := - To_Filename - (Prj, - CU_Name_For_Unit (Helper_Unit, GNATCOLL.Projects.Unit_Body)); + To_Filename (Prj, CU_Name_For_Unit (Helper_Unit, GPR2.S_Body)); Helper_Unit_Name : constant String := To_Ada (Helper_Unit); Dump_Procedure : constant String := To_String (Dump_Procedure_Name); @@ -11011,7 +11006,7 @@ package body Instrument.Ada_Unit is is Buffers_CU_Name : constant Compilation_Unit_Part := CU_Name_For_Unit - (Buffers_List_Unit (Prj.Prj_Name), GNATCOLL.Projects.Unit_Spec); + (Buffers_List_Unit (Prj.Prj_Name), GPR2.S_Spec); Unit_Name : constant String := To_Ada (Buffers_CU_Name.Unit); Filename : constant String := To_Filename (Prj, Buffers_CU_Name); File : Text_Files.File_Type; @@ -11123,7 +11118,7 @@ package body Instrument.Ada_Unit is pragma Unreferenced (Self); Buf_List_Unit : constant Ada_Qualified_Name := CU_Name_For_Unit - (Buffers_List_Unit (Prj.Prj_Name), GNATCOLL.Projects.Unit_Spec).Unit; + (Buffers_List_Unit (Prj.Prj_Name), GPR2.S_Spec).Unit; Buf_List_Unit_Name : constant String := To_Ada (Buf_List_Unit); Obs_Unit : constant Ada_Qualified_Name := @@ -11132,9 +11127,9 @@ package body Instrument.Ada_Unit is Obs_Unit_Name : constant String := To_Ada (Obs_Unit); Obs_Spec_Filename : constant String := To_Filename - (Prj, CU_Name_For_Unit (Obs_Unit, GNATCOLL.Projects.Unit_Spec)); + (Prj, CU_Name_For_Unit (Obs_Unit, GPR2.S_Spec)); Obs_Body_Filename : constant String := To_Filename - (Prj, CU_Name_For_Unit (Obs_Unit, GNATCOLL.Projects.Unit_Body)); + (Prj, CU_Name_For_Unit (Obs_Unit, GPR2.S_Body)); Spec_File : Text_Files.File_Type; Body_File : Text_Files.File_Type; @@ -11188,7 +11183,7 @@ package body Instrument.Ada_Unit is Context : constant Analysis_Context := Create_Context; Mapping : constant Config_Pragmas_Mapping := - Import_From_Project (Context, Project.Project.all); + Import_From_Project (Context, Project.Project); -- Then, turn this mapping into a JSON description @@ -11274,7 +11269,6 @@ package body Instrument.Ada_Unit is (Tag : Unbounded_String; Config_Pragmas_Mapping : String; Mapping_Filename : String; - Predefined_Source_Dirs : String_Vectors.Vector; Preprocessor_Data_Filename : String) return Ada_Instrumenter_Type is @@ -11285,8 +11279,7 @@ package body Instrument.Ada_Unit is -- First create the context for Libadalang Instrumenter.Provider := - Instrument.Ada_Unit_Provider.Create_Provider - (Predefined_Source_Dirs, Mapping_Filename); + Instrument.Ada_Unit_Provider.Create_Provider (Mapping_Filename); -- Create a file reader, to let Libadalang preprocess source files that -- need it. @@ -11379,10 +11372,10 @@ package body Instrument.Ada_Unit is UIC.Buffer_Unit := CU_Name_For_Unit - (Buffer_Unit (To_Qualified_Name (Unit_Name)), GPR.Unit_Spec); + (Buffer_Unit (To_Qualified_Name (Unit_Name)), GPR2.S_Spec); UIC.Pure_Buffer_Unit := CU_Name_For_Unit - (Pure_Buffer_Unit (To_Qualified_Name (Unit_Name)), GPR.Unit_Spec); + (Pure_Buffer_Unit (To_Qualified_Name (Unit_Name)), GPR2.S_Spec); -- We consider that theer is no No_Elaboration_Code_All pragma/aspect -- until we see one. diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index f9abb2fbf..c50aaf673 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -98,7 +98,7 @@ package Instrument.Ada_Unit is overriding procedure Replace_Manual_Indications (Self : in out Ada_Instrumenter_Type; Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info; + Source : GPR2.Build.Source.Object; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean); -- Once the instrumentation has finished, if the dump trigger is "manual" @@ -155,7 +155,6 @@ package Instrument.Ada_Unit is (Tag : Unbounded_String; Config_Pragmas_Mapping : String; Mapping_Filename : String; - Predefined_Source_Dirs : String_Vectors.Vector; Preprocessor_Data_Filename : String) return Ada_Instrumenter_Type; -- Create an Ada instrumenter. @@ -166,11 +165,8 @@ package Instrument.Ada_Unit is -- Mapping_Filename is the fullname to the mapping file, which maps unit -- names to file fullnames. -- - -- Predefined_Source_Dirs is the list of directories hosting runtime files. - -- - -- Both Mapping_Filename and Predefined_Source_Dirs are used to instantiate - -- our custom unit provider, which does not rely on project files (see - -- Instrument.Ada_Unit_Provider). + -- Mapping_Filename is used to instantiate our custom unit provider, which + -- does not rely on project files (see Instrument.Ada_Unit_Provider). -- -- Preprocessor_Data_Filename is the name of the file that contains -- preprocessor configuration data (see Instrument.Ada_Preprocessing). diff --git a/tools/gnatcov/instrument-ada_unit__stub.ads b/tools/gnatcov/instrument-ada_unit__stub.ads index 9f6424fee..0fd098539 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.ads +++ b/tools/gnatcov/instrument-ada_unit__stub.ads @@ -39,7 +39,6 @@ package Instrument.Ada_Unit is (Tag : Unbounded_String; Config_Pragmas_Mapping : String; Mapping_Filename : String; - Predefined_Source_Dirs : String_Vectors.Vector; Preprocessor_Data_Filename : String) return Ada_Instrumenter_Type is (Ada_Instrumenter_Type'(others => <>)); diff --git a/tools/gnatcov/instrument-ada_unit_provider.adb b/tools/gnatcov/instrument-ada_unit_provider.adb index 3ca2b8a9e..76f612eea 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.adb +++ b/tools/gnatcov/instrument-ada_unit_provider.adb @@ -19,32 +19,65 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Text_IO; use Ada.Text_IO; +with GPR2.Build.Unit_Info; +with GPR2.Path_Name; with Libadalang.Unit_Files; with Outputs; +with Project; +with Text_Files; package body Instrument.Ada_Unit_Provider is + use type GPR2.Language_Id; + package LALCO renames Libadalang.Common; + function Unit_Key + (Name : String; Part : GPR2.Valid_Unit_Kind) return String + is (To_Lower (Name) + & '%' + & (case Part is + when GPR2.S_Spec => 's', + when others => 'b')); + -- Key used to find a source file in the provider map + + ------------------------- + -- Create_Mapping_File -- + ------------------------- + + procedure Create_Mapping_File (Filename : String) is + F : Text_Files.File_Type; + begin + F.Create (Filename); + for Source of Project.Source_Closure + (View => Project.Project.Root_Project, + With_Externally_Built => True, + With_Runtime => True) + loop + if Source.Language = GPR2.Ada_Language then + for Unit of Source.Units loop + if Unit.Kind in GPR2.Valid_Unit_Kind then + F.Put_Line (Unit_Key (String (Unit.Full_Name), Unit.Kind)); + F.Put_Line (String (Source.Path_Name.Simple_Name)); + F.Put_Line (String (Source.Path_Name.Value)); + end if; + end loop; + end if; + end loop; + end Create_Mapping_File; + --------------------- -- Create_Provider -- --------------------- - function Create_Provider - (Runtime_Directories : String_Vectors.Vector; - Dependencies_Filename : String) return Provider_Type - is - use GNATCOLL.VFS; - + function Create_Provider (Mapping_File : String) return Provider_Type is Provider : Provider_Type; - - Dependencies_File : File_Type; - + F : File_Type; begin -- Parse the mapping file and fill Provider.Unit_Map - Open (Dependencies_File, In_File, Dependencies_Filename); + Open (F, In_File, Mapping_File); -- The mapping file is a succession of triplets as such: -- {%b,%s} @@ -52,53 +85,21 @@ package body Instrument.Ada_Unit_Provider is -- begin - while not End_Of_File (Dependencies_File) loop + while not End_Of_File (F) loop declare - Unit_Name : constant String := - Get_Line (Dependencies_File); - Dummy_Basename : constant String := - Get_Line (Dependencies_File); - File_Fullname : constant String := - Get_Line (Dependencies_File); + Unit_Name : constant String := Get_Line (F); + Dummy_Basename : constant String := Get_Line (F); + File_Fullname : constant String := Get_Line (F); begin - Provider.Unit_Map.Insert (To_Lower (Unit_Name), File_Fullname); + Provider.Unit_Map.Include (To_Lower (Unit_Name), File_Fullname); end; end loop; exception when End_Error => - Outputs.Warn ("mapping file """ & Dependencies_Filename - & " "" is truncated"); + Outputs.Warn + ("mapping file """ & Mapping_File & " "" is truncated"); end; - Close (Dependencies_File); - - -- Read the runtime files and fill Provider.Runtime_Files. - -- - -- Note that the GPR system does not ensure that all runtime directories - -- actually exist, so do not crash in this case. - - for Dirname of Runtime_Directories loop - declare - Runtime_Dir : constant Virtual_File := Create (+(+Dirname)); - Files : File_Array_Access; - begin - if Runtime_Dir.Is_Directory then - Files := Runtime_Dir.Read_Dir; - for File of Files.all loop - - -- It is allowed to have multiple version of the same file - -- in a project: the builder will pick the first one found. - -- Apply the same semantics here, and ignore all later - -- occurrences of a file already encountered. - - if not Provider.Runtime_Files.Contains (+File.Base_Name) then - Provider.Runtime_Files.Insert - (+File.Base_Name, +File.Full_Name); - end if; - end loop; - Unchecked_Free (Files); - end if; - end; - end loop; + Close (F); return Provider; end Create_Provider; @@ -114,61 +115,17 @@ package body Instrument.Ada_Unit_Provider is is use String_Maps; - Part : constant String := + Part : constant GPR2.Valid_Unit_Kind := (case Kind is - when Libadalang.Common.Unit_Body => "%b", - when Libadalang.Common.Unit_Specification => "%s"); - Unit_Name : constant String := - Libadalang.Unit_Files.Unit_String_Name (Name) & Part; - - Unit_Name_Cur : Cursor := Provider.Unit_Map.Find (Unit_Name); + when Libadalang.Common.Unit_Body => GPR2.S_Body, + when Libadalang.Common.Unit_Specification => GPR2.S_Spec); + Key : constant String := + Unit_Key (Libadalang.Unit_Files.Unit_String_Name (Name), Part); + Unit_Name_Cur : constant Cursor := Provider.Unit_Map.Find (Key); begin - if Has_Element (Unit_Name_Cur) then - return Element (Unit_Name_Cur); - end if; - - -- The requested unit is not registered in the project tree under its - -- unit name. Assume it may be an overridden runtime file present - -- in the project tree with a krunched name. - - declare - Runtime_Basename : constant String := - Libadalang.Unit_Files.File_From_Unit (Name, Kind); - -- Finds the krunched name of the corresponding runtime file based - -- on the unit name. - - Unit_Basename : String := - Runtime_Basename (1 .. Runtime_Basename'Length - 4) & Part; - -- Re-use the krunched runtime filename to find the entry under - -- which the overridden runtime file may have been stored. - -- It's basically the runtime filename, but with '%b|%s' instead of - -- the file extension and with dots '.' instead of dashes '-'. - - begin - - for I in 1 .. Unit_Basename'Length loop - if Unit_Basename (I) = '-' then - Unit_Basename (I) := '.'; - end if; - end loop; - - Unit_Name_Cur := Provider.Unit_Map.Find (Unit_Basename); - if Has_Element (Unit_Name_Cur) then - return Element (Unit_Name_Cur); - end if; - - -- The requested unit does not belong to the project tree: look for a - -- source file in the runtime. - - Unit_Name_Cur := Provider.Runtime_Files.Find (Runtime_Basename); - if Has_Element (Unit_Name_Cur) then - return Element (Unit_Name_Cur); - end if; - end; - - -- The unit could not be found. Return an empty string - - return ""; + return (if Has_Element (Unit_Name_Cur) + then Element (Unit_Name_Cur) + else ""); end Get_Unit_Filename; -------------- @@ -212,15 +169,9 @@ package body Instrument.Ada_Unit_Provider is function Has_Unit (Provider : Provider_Type; Unit_Name : String; - Unit_Part : Unit_Parts) return Boolean - is - Unit_Name_And_Part : constant String := - To_Lower (Unit_Name) - & (case Unit_Part is - when GNATCOLL.Projects.Unit_Spec => "%s", - when others => "%b"); + Unit_Part : GPR2.Valid_Unit_Kind) return Boolean is begin - return Provider.Unit_Map.Contains (Unit_Name_And_Part); + return Provider.Unit_Map.Contains (Unit_Key (Unit_Name, Unit_Part)); end Has_Unit; end Instrument.Ada_Unit_Provider; diff --git a/tools/gnatcov/instrument-ada_unit_provider.ads b/tools/gnatcov/instrument-ada_unit_provider.ads index 693a74b2b..0e5c02c7d 100644 --- a/tools/gnatcov/instrument-ada_unit_provider.ads +++ b/tools/gnatcov/instrument-ada_unit_provider.ads @@ -19,12 +19,10 @@ with Ada.Containers.Indefinite_Hashed_Maps; with Ada.Strings.Hash; -with GNATCOLL.VFS; - +with GPR2; with Langkit_Support.Text; use Langkit_Support.Text; - -with Libadalang.Analysis; use Libadalang.Analysis; -with Libadalang.Common; use Libadalang.Common; +with Libadalang.Analysis; use Libadalang.Analysis; +with Libadalang.Common; use Libadalang.Common; -- Custom implementation of a libadalang unit provider, using the mapping -- file produced from the project file (that is passed to the compiler through @@ -32,15 +30,18 @@ with Libadalang.Common; use Libadalang.Common; package Instrument.Ada_Unit_Provider is + procedure Create_Mapping_File (Filename : String); + -- Write a mapping for all Ada sources in the currently loaded project. + -- This mapping file is intended to be passed as Dependencies_Filename to + -- Create_Provider. + type Provider_Type is new Libadalang.Analysis.Unit_Provider_Interface with private; function Create_Provider - (Runtime_Directories : String_Vectors.Vector; - Dependencies_Filename : String) return Provider_Type; - -- Create a unit provider, from a list of predefined directories passed - -- through Runtime_Directories, and from a mapping file in the same format - -- as the file passed through -gnatem in the compiler invocation. + (Mapping_File : String) return Provider_Type; + -- Create a unit provider from a mapping file in the same format as the + -- file passed through -gnatem in the compiler invocation. overriding function Get_Unit_Filename (Provider : Provider_Type; @@ -64,13 +65,11 @@ package Instrument.Ada_Unit_Provider is function Has_Unit (Provider : Provider_Type; Unit_Name : String; - Unit_Part : Unit_Parts) return Boolean; + Unit_Part : GPR2.Valid_Unit_Kind) return Boolean; -- Returns whether given unit is in the provider unit closure private - use type GNATCOLL.VFS.Virtual_File; - package String_Maps is new Ada.Containers.Indefinite_Hashed_Maps (Key_Type => String, Element_Type => String, @@ -81,10 +80,6 @@ private with record Unit_Map : String_Maps.Map; -- Mapping from unit name to file fullnames - - Runtime_Files : String_Maps.Map; - -- Mapping from a runtime file basename to its fullname - end record; end Instrument.Ada_Unit_Provider; diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 017f306ca..fdfd3c967 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -148,7 +148,7 @@ package body Instrument.C is -- a file. procedure Preprocess_And_Record_Include_Paths - (Source : GNATCOLL.Projects.File_Info; + (Source : GPR2.Build.Source.Object; Instrumenter : C_Family_Instrumenter_Type'Class; Prj : in out Prj_Desc; PP_Filename : out Unbounded_String); @@ -3066,13 +3066,13 @@ package body Instrument.C is ----------------------------------------- procedure Preprocess_And_Record_Include_Paths - (Source : GNATCOLL.Projects.File_Info; + (Source : GPR2.Build.Source.Object; Instrumenter : C_Family_Instrumenter_Type'Class; Prj : in out Prj_Desc; PP_Filename : out Unbounded_String) is Options : Analysis_Options; - Filename : constant String := +Source.File.Full_Name; + Filename : constant String := String (Source.Path_Name.Value); begin Preprocess_Source (Filename, Instrumenter, Prj, PP_Filename, Options); @@ -3088,7 +3088,7 @@ package body Instrument.C is for Path of Options.PP_Search_Path loop Prj.Compiler_Options_Unit.Insert - (Key => Source.File, + (Key => Create (+String (Source.Path_Name.Value)), New_Item => String_Vectors.Empty_Vector, Position => Cur, Inserted => Inserted); @@ -4465,7 +4465,7 @@ package body Instrument.C is overriding procedure Replace_Manual_Indications (Self : in out C_Family_Instrumenter_Type; Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info; + Source : GPR2.Build.Source.Object; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean) is @@ -4482,7 +4482,7 @@ package body Instrument.C is C_Family_Instrumenter_Type'Class (Self).Extern_Prefix; Annots : constant Instr_Annotation_Map := - Get_Buffer_Annotations (+Source.File.Full_Name); + Get_Buffer_Annotations (String (Source.Path_Name.Value)); Annot_Mapping : Sloc_To_Index_Maps.Map; -- Mapping from source locations of the annotations in the @@ -4542,7 +4542,7 @@ package body Instrument.C is for Annot_Cur in Annots.Iterate loop Annot_Mapping.Insert (Instr_Annotation_Maps.Key (Annot_Cur), 0); end loop; - Remap_Locations (Str, +Source.File.Full_Name, Annot_Mapping); + Remap_Locations (Str, String (Source.Path_Name.Value), Annot_Mapping); Ext_Annot_Cur := Annot_Mapping.First; Has_Dump_Indication := False; @@ -4614,7 +4614,7 @@ package body Instrument.C is if Matches (Buffer_Dump_Group) /= No_Match then Switches.Misc_Trace.Trace ("Found buffer dump indication in file " - & (+Source.File.Base_Name)); + & String (Source.Path_Name.Simple_Name)); -- If we had a prefix specified in the comment, include it -- in the dump procedure call. Use the project name as the @@ -4635,7 +4635,7 @@ package body Instrument.C is pragma Assert (Matches (Buffer_Reset_Group) /= No_Match); Switches.Misc_Trace.Trace ("Found buffer reset indication in file " - & (+Source.File.Base_Name)); + & String (Source.Path_Name.Simple_Name)); String'Write (S, Reset_Procedure & "();"); Has_Reset_Indication := True; @@ -4691,7 +4691,7 @@ package body Instrument.C is if Has_Element (Ext_Annot_Cur) then Warning_Or_Error ("Some external annotations could not be re-mapped in the" - & " preprocessed version of " & Source.File.Display_Full_Name + & " preprocessed version of " & String (Source.Path_Name.Value) & ", They have been ignored. Use -v for more details."); while Has_Element (Ext_Annot_Cur) loop declare @@ -4732,7 +4732,7 @@ package body Instrument.C is if not Success then Outputs.Fatal_Error ("Failed to replace manual dump indication for Source " - & (+Source.File.Full_Name)); + & String (Source.Path_Name.Value)); end if; end; else diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 95629ada4..6a4483d2d 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -25,6 +25,7 @@ with Ada.Finalization; with Namet; use Namet; with GNATCOLL.VFS; use GNATCOLL.VFS; +with GPR2.Build.Source; with Clang.CX_Source_Location; use Clang.CX_Source_Location; with Clang.Index; use Clang.Index; @@ -67,7 +68,7 @@ package Instrument.C is overriding procedure Replace_Manual_Indications (Self : in out C_Family_Instrumenter_Type; Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info; + Source : GPR2.Build.Source.Object; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean); -- Preprocess Source and look through the text content of the preprocessed diff --git a/tools/gnatcov/instrument-clean_objdirs.adb b/tools/gnatcov/instrument-clean_objdirs.adb index 5780259c7..276089fd2 100644 --- a/tools/gnatcov/instrument-clean_objdirs.adb +++ b/tools/gnatcov/instrument-clean_objdirs.adb @@ -18,8 +18,8 @@ with Ada.Directories; use Ada.Directories; -with GNATCOLL.Projects; use GNATCOLL.Projects; -with GNATCOLL.VFS; use GNATCOLL.VFS; +with GNATCOLL.VFS; use GNATCOLL.VFS; +with GPR2.Path_Name; with Instrument.Common; use Instrument.Common; with Outputs; use Outputs; @@ -27,7 +27,7 @@ with Project; use Project; procedure Instrument.Clean_Objdirs is - procedure Clean_Subdir (Project : Project_Type); + procedure Clean_Subdir (Project : GPR2.Project.View.Object); -- Callback for Project.Iterate_Projects. If Project is not externally -- built, remove all files from the "$project_name-gnatcov-instr" folder in -- Project's object directory, and remove all files ending in ".sid" from @@ -40,15 +40,14 @@ procedure Instrument.Clean_Objdirs is -- Clean_Subdir -- ------------------ - procedure Clean_Subdir (Project : Project_Type) is + procedure Clean_Subdir (Project : GPR2.Project.View.Object) is Output_Dir : constant String := Project_Output_Dir (Project); Has_Output_Dir : Boolean := True; - Obj_Dir_Files : File_Array_Access; - Success : Boolean; begin - Clean_Objdirs_Trace.Increase_Indent ("Processing " & Project.Name); + Clean_Objdirs_Trace.Increase_Indent + ("Processing " & String (Project.Name)); Clean_Objdirs_Trace.Trace - ("GPR file: " & (+Project.Project_Path.Full_Name)); + ("GPR file: " & String (Project.Path_Name.Value)); -- Some projects don't have an object directory: ignore them as there is -- nothing to do. @@ -90,7 +89,7 @@ procedure Instrument.Clean_Objdirs is -- To avoid confusion, warn about such cases now, so that users have a -- clear lead on how to address such problems. - if Project.Externally_Built then + if Project.Is_Externally_Built then Clean_Objdirs_Trace.Trace ("it is an externally built project"); if not Externally_Built_Projects_Processing_Enabled @@ -101,9 +100,9 @@ procedure Instrument.Clean_Objdirs is -- Output_Dir would be considered as sources with --src-subdirs: -- consider that all files there could be sources. - Warn ("Project """ & Project.Name & """ is externally built and" - & " does not contain units of interest, however it contains" - & " instrumented sources"); + Warn ("Project """ & String (Project.Name) & """ is externally" + & " built and does not contain units of interest, however it" + & " contains instrumented sources"); end if; -- We should never try to modify externally built projects, so do not @@ -117,21 +116,31 @@ procedure Instrument.Clean_Objdirs is -- Remove the SID files if any - Obj_Dir_Files := Project.Object_Dir.Read_Dir (Files_Only); - if Obj_Dir_Files /= null then - for File of Obj_Dir_Files.all loop - if File.File_Extension (Normalize => True) = ".sid" - and then File.Is_Regular_File - then - File.Delete (Success); - if not Success then - Warn - ("Failed to delete old SID file: " - & File.Display_Full_Name); - end if; + if Project.Kind in GPR2.With_Object_Dir_Kind then + declare + Obj_Dir : constant GPR2.Path_Name.Object := + Project.Object_Directory; + Obj_Dir_Files : File_Array_Access; + Success : Boolean; + begin + Obj_Dir_Files := + Create (Filesystem_String (Obj_Dir.Value)).Read_Dir (Files_Only); + if Obj_Dir_Files /= null then + for File of Obj_Dir_Files.all loop + if File.File_Extension (Normalize => True) = ".sid" + and then File.Is_Regular_File + then + File.Delete (Success); + if not Success then + Warn + ("Failed to delete old SID file: " + & File.Display_Full_Name); + end if; + end if; + end loop; + Unchecked_Free (Obj_Dir_Files); end if; - end loop; - Unchecked_Free (Obj_Dir_Files); + end; end if; Clean_Objdirs_Trace.Decrease_Indent; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index cc70ccb3c..538fafc96 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -19,7 +19,7 @@ with Ada.Containers; use Ada.Containers; with Ada.Directories; -with GNATCOLL.VFS; +with GPR2.Path_Name; with Coverage; with Diagnostics; @@ -121,20 +121,23 @@ package body Instrument.Common is -- Project_Output_Dir -- ------------------------ - function Project_Output_Dir (Project : Project_Type) return String is - use type GNATCOLL.VFS.Filesystem_String; - Obj_Dir : constant String := +Project.Object_Dir.Full_Name; + function Project_Output_Dir + (Project : GPR2.Project.View.Object) return String is begin - if Obj_Dir'Length = 0 then + if Project.Kind not in GPR2.With_Object_Dir_Kind then return ""; - else - declare - Prj_Name : constant String := - Ada.Characters.Handling.To_Lower (Project.Name); - begin - return Obj_Dir / Prj_Name & "-gnatcov-instr"; - end; end if; + + declare + Obj_Dir : constant GPR2.Path_Name.Object := Project.Object_Directory; + Prj_Name : constant String := + Ada.Characters.Handling.To_Lower (String (Project.Name)); + begin + return String + (Obj_Dir + .Compose (GPR2.Simple_Name (Prj_Name & "-gnatcov-instr")) + .Value); + end; end Project_Output_Dir; ------------------------ @@ -431,27 +434,9 @@ package body Instrument.Common is begin case CU_Name.Language_Kind is when Unit_Based_Language => - declare - Filename : Unbounded_String; - begin - for Id of CU_Name.Unit loop - if Filename /= "" then - Append (Filename, Prj.Dot_Replacement); - end if; - Append (Filename, To_Lower (To_String (Id))); - end loop; - - case CU_Name.Part is - when GNATCOLL.Projects.Unit_Body - | GNATCOLL.Projects.Unit_Separate - => - Append (Filename, Prj.Body_Suffix (Ada_Language)); - when GNATCOLL.Projects.Unit_Spec => - Append (Filename, Prj.Spec_Suffix (Ada_Language)); - end case; - - return +Filename; - end; + return String + (Prj.View.Filename_For_Unit + (GPR2.Name_Type (To_Ada (CU_Name.Unit)), CU_Name.Part)); when File_Based_Language => return +CU_Name.Filename; end case; @@ -792,7 +777,7 @@ package body Instrument.Common is procedure Replace_Manual_Indications (Self : in out Language_Instrumenter; Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info; + Source : GPR2.Build.Source.Object; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean) is begin diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index d5e987d0f..e7311f971 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -167,7 +167,8 @@ package Instrument.Common is -- gives the possibility to link two separately-instrumented libraries in -- the same executable. - function Project_Output_Dir (Project : Project_Type) return String; + function Project_Output_Dir + (Project : GPR2.Project.View.Object) return String; -- Return the directory in which we must create instrumented sources for -- Project. This returns an empty string for projects that do not have an -- object directory. @@ -536,7 +537,7 @@ package Instrument.Common is procedure Replace_Manual_Indications (Self : in out Language_Instrumenter; Prj : in out Prj_Desc; - Source : GNATCOLL.Projects.File_Info; + Source : GPR2.Build.Source.Object; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean); -- Look for the pragmas (for Ada) or comments (for C family languages) diff --git a/tools/gnatcov/instrument-config.adb b/tools/gnatcov/instrument-config.adb index 1ded3ee63..768496f44 100644 --- a/tools/gnatcov/instrument-config.adb +++ b/tools/gnatcov/instrument-config.adb @@ -40,8 +40,6 @@ begin +Args.String_Args (Opt_Config_Pragmas_Mapping).Value, Mapping_Filename => +Args.String_Args (Opt_Gnatem).Value, - Predefined_Source_Dirs => - Args.String_List_Args (Opt_Runtime_Dir), Preprocessor_Data_Filename => +Args.String_Args (Opt_Ada_Preprocessor_Data).Value); when C_Language => diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 94d9dc9b1..a08d15045 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -32,18 +32,24 @@ with GNAT.Exception_Actions; with GNAT.OS_Lib; with GNAT.Regexp; -with GNAT.Strings; with GNATCOLL.JSON; use GNATCOLL.JSON; with GNATCOLL.VFS; use GNATCOLL.VFS; -with GNATCOLL.Projects.Aux; use GNATCOLL.Projects.Aux; +with GPR2.Build.Compilation_Unit; +with GPR2.Build.Source; +with GPR2.Containers; +with GPR2.Path_Name; +with GPR2.Project.Attribute; +with GPR2.Project.Attribute_Index; +with GPR2.Project.Registry.Attribute; with Binary_Files; with Command_Line; use Command_Line; with Files_Handling; use Files_Handling; with Files_Table; -with Instrument.Ada_Unit; use Instrument.Ada_Unit; with Instrument.Ada_Preprocessing; +with Instrument.Ada_Unit; use Instrument.Ada_Unit; +with Instrument.Ada_Unit_Provider; with Instrument.C; use Instrument.C; with Instrument.Clean_Objdirs; with Instrument.Common; use Instrument.Common; @@ -80,8 +86,11 @@ procedure Instrument.Projects Ignored_Source_Files : access GNAT.Regexp.Regexp; Mains : String_Vectors.Vector) is + use type GPR2.Path_Name.Object; + use type GPR2.Unit_Kind; + type Project_Info is record - Project : Project_Type; + Project : GPR2.Project.View.Object; -- Project that this record describes Externally_Built : Boolean; @@ -122,20 +131,20 @@ is package Main_To_Instrument_Vectors is new Ada.Containers.Vectors (Positive, Main_To_Instrument); - function Less (L, R : File_Info) return Boolean is - (L.File.Full_Name < R.File.Full_Name); - function Equal (L, R : File_Info) return Boolean is - (Equal (L.File.Full_Name, R.File.Full_Name)); + function Less (L, R : GPR2.Build.Source.Object) return Boolean is + (L.Path_Name < R.Path_Name); + function Equal (L, R : GPR2.Build.Source.Object) return Boolean is + (L.Path_Name = R.Path_Name); package File_Info_Sets is new Ada.Containers.Indefinite_Ordered_Sets - (Element_Type => File_Info, "<" => Less, "=" => Equal); + (Element_Type => GPR2.Build.Source.Object, "<" => Less, "=" => Equal); type Library_Unit_Info is record Unit_Name : Unbounded_String; -- Name of this unit: unit name for unit-based languages, simple name -- for file-based languages. - Instr_Project : GPR.Project_Type; + Instr_Project : GPR2.Project.View.Object; -- Project in which instrumentation artifacts for this unit are -- generated. @@ -169,8 +178,6 @@ is -- Load_Config_Pragmas_Mapping procedures in Instrument.Ada_Unit for -- more information. - Predefined_Source_Dirs : String_Vectors.Vector; - Sources_Of_Interest_Response_File : Unbounded_String; -- File containing the list of units of interest, identified by their -- fullname. This is passed on to gnatcov instrument-source invokations @@ -210,18 +217,16 @@ is function Get_Or_Create_Project_Info (Context : in out Inst_Context; - Project : Project_Type) return Project_Info_Access; + Project : GPR2.Project.View.Object) return Project_Info_Access; -- Return the Project_Info record corresponding to Project. Create it if it -- does not exist. procedure Register_Main_To_Instrument (Context : in out Inst_Context; Mains : in out Main_To_Instrument_Vectors.Vector; - File : GNATCOLL.VFS.Virtual_File; - Project : Project_Type); - -- Register in Mains a main to be instrumented so that it dumps coverage - -- buffers. File is the source file for this main, and Project is the - -- project that owns this main. + Main : GPR2.Build.Compilation_Unit.Unit_Location); + -- Register Main (a main source to be instrumented) into Mains so that it + -- dumps coverage buffers. procedure Prepare_Output_Dirs (IC : Inst_Context); -- Make sure we have the expected tree of directories for the @@ -230,11 +235,11 @@ is function SID_Filename (LU_Info : Library_Unit_Info; In_Library_Dir : Boolean) return String; -- Return the filename of the SID file to create for the given library - -- unit. If In_Library_Dir is true, then return a filename located in the - -- project library directory. Otherwise, the filename is located in the - -- object directory. + -- unit. If In_Library_Dir is True and LU_Info lives in a library project, + -- then return a filename located in the project library directory. + -- Otherwise, the filename is located in the object directory. - function Load_From_Project (Prj : Project_Type) return Prj_Desc; + function Load_From_Project (Prj : GPR2.Project.View.Object) return Prj_Desc; -- Load the project description from the given project function Compilation_Unit_Options @@ -246,7 +251,8 @@ is -- LU_Info, belonging to the project Prj. procedure Add_Project_Source - (Project : GPR.Project_Type; Source_File : GPR.File_Info); + (Project : GPR2.Project.View.Object; + Source_File : GPR2.Build.Source.Object); -- If an instrumenter supports Source_File's language and if Project is not -- externally built, add Source_File to Project_Sources. @@ -266,7 +272,8 @@ is -- empty. procedure Add_Instrumented_Unit - (Project : GPR.Project_Type; Source_File : GPR.File_Info); + (Project : GPR2.Project.View.Object; + Source_File : GPR2.Build.Source.Object); -- Add this source file to the list of units to instrument procedure Clean_And_Print (Exc : Ada.Exceptions.Exception_Occurrence); @@ -281,20 +288,25 @@ is -- Load_From_Project -- ----------------------- - function Load_From_Project (Prj : Project_Type) return Prj_Desc + function Load_From_Project (Prj : GPR2.Project.View.Object) return Prj_Desc is + package R renames GPR2.Project.Registry.Attribute; + + Languages : constant GPR2.Containers.Language_Set := + Prj.Language_Ids; Dot_Replacement : constant String := - Prj.Attribute_Value - (Attribute => Build ("Naming", "Dot_Replacement")); + Prj.Attribute (Name => R.Naming.Dot_Replacement).Value.Text; Result : Prj_Desc; begin for Lang in Some_Language loop - if Builtin_Support (Lang) then + if Builtin_Support (Lang) + and then Languages.Contains (To_Language_Id (Lang)) + then declare Body_Suffix : constant String := - Project.Source_Suffix (Lang, GPR.Unit_Body, Prj); + Project.Source_Suffix (Lang, GPR2.S_Body, Prj); Spec_Suffix : constant String := - Project.Source_Suffix (Lang, GPR.Unit_Spec, Prj); + Project.Source_Suffix (Lang, GPR2.S_Spec, Prj); begin Result.Body_Suffix (Lang) := +Body_Suffix; Result.Spec_Suffix (Lang) := +Spec_Suffix; @@ -302,14 +314,15 @@ is end if; end loop; - Result.Prj_Name := To_Qualified_Name (Prj.Name); + Result.Prj_Name := To_Qualified_Name (String (Prj.Name)); + Result.View := Prj; Result.Dot_Replacement := +Dot_Replacement; -- Register the source directories of the project tree declare procedure Register_Source_Dirs - (P : GNATCOLL.Projects.Project_Type); + (P : GPR2.Project.View.Object); -- Add the source directories of P's project file to the search -- paths to be passed as -I arguments later. The order in which -- the paths are added to the search paths vector is the same @@ -322,11 +335,10 @@ is -------------------------- procedure Register_Source_Dirs - (P : GNATCOLL.Projects.Project_Type) is + (P : GPR2.Project.View.Object) is begin - for Dir of P.Source_Dirs loop - Result.Search_Paths.Append - ("-I" & (+GNATCOLL.VFS."+" (GNATCOLL.VFS.Dir_Name (Dir)))); + for Dir of P.Source_Directories loop + Result.Search_Paths.Append (+("-I" & String (Dir.Dir_Name))); end loop; end Register_Source_Dirs; begin @@ -351,60 +363,68 @@ is -- Load the set of compiler switches for languages requiring it for Lang in C_Family_Language loop - declare - use type GNAT.Strings.String_List_Access; - Options : Analysis_Options; - Compiler_Opts : String_Vectors.Vector; - Switches : GNAT.Strings.String_List_Access; - Compiler_Driver : constant String := - GNATCOLL.Projects.Attribute_Value - (Prj, - GPR.Compiler_Driver_Attribute, - Image (Lang)); + if Languages.Contains (To_Language_Id (Lang)) then + declare + Lang_Index : constant GPR2.Project.Attribute_Index.Object := + GPR2.Project.Attribute_Index.Create (Image (Lang)); - begin - -- Get the compiler switches from the project file. When - -- registering a compilation unit for instrumentation, we also - -- fill the compilation unit specific switches that will override - -- the project defaults, if there are any (see - -- Add_Instrumented_Unit). - -- - -- Language specific switches can be specified through the - -- Compiler.Switches or the Compiler.Default_Switches attribute, - -- the former being prioritized over the latter. + package R renames GPR2.Project.Registry.Attribute; - Switches := - Prj.Attribute_Value - (Attribute => GPR.Build ("compiler", "switches"), - Index => Image (Lang)); + Options : Analysis_Options; + Compiler_Opts : String_Vectors.Vector; + Switches : GPR2.Project.Attribute.Object; + Compiler_Driver : constant GPR2.Project.Attribute.Object := + Prj.Attribute + (Name => R.Compiler.Driver, Index => Lang_Index); + + begin + -- Get the compiler switches from the project file. When + -- registering a compilation unit for instrumentation, we also + -- fill the compilation unit specific switches that will + -- override the project defaults, if there are any (see + -- Add_Instrumented_Unit). + -- + -- Language specific switches can be specified through the + -- Compiler.Switches or the Compiler.Default_Switches + -- attribute, the former being prioritized over the latter. - if Switches = null then Switches := - Prj.Attribute_Value - (Attribute => GPR.Compiler_Default_Switches_Attribute, - Index => Image (Lang)); - end if; + Prj.Attribute + (Name => R.Compiler.Switches, Index => Lang_Index); + + if not Switches.Is_Defined then + Switches := + Prj.Attribute + (Name => R.Compiler.Default_Switches, + Index => Lang_Index); + end if; - -- If we manage to find appropriate switches, convert them to a - -- string vector import the switches. + -- If we manage to find appropriate switches, convert them to a + -- string vector import the switches. + + if Switches.Is_Defined then + declare + Args : String_Vectors.Vector; + begin + for S of Switches.Values loop + Args.Append (+S.Text); + end loop; + Import_From_Args (Options, Args); + end; + end if; - if Switches /= null then - declare - Args : String_Vectors.Vector; - begin - for S of Switches.all loop - Args.Append (+S.all); - end loop; - GNAT.Strings.Free (Switches); - Import_From_Args (Options, Args); - end; - end if; + Add_Options (Compiler_Opts, Options, Pass_Builtins => False); - Add_Options (Compiler_Opts, Options, Pass_Builtins => False); + -- If we could not find a C compiler, stay silent at this + -- point: the C instrumenter will complain if needed. - Result.Compiler_Options (Lang) := Compiler_Opts; - Result.Compiler_Driver (Lang) := +Compiler_Driver; - end; + Result.Compiler_Options (Lang) := Compiler_Opts; + Result.Compiler_Driver (Lang) := + +(if Compiler_Driver.Is_Defined + then Compiler_Driver.Value.Text + else ""); + end; + end if; end loop; return Result; @@ -467,6 +487,7 @@ is -- Cleanup temporary artifacts if not instructed to keep them if not Save_Temps then + Delete_File_Wrapper (Context.Mapping_File); Delete_File_Wrapper (Context.Config_Pragmas_Mapping); Delete_File_Wrapper (Context.Sources_Of_Interest_Response_File); Delete_File_Wrapper (Context.Ada_Preprocessor_Data_File); @@ -494,13 +515,13 @@ is function Get_Or_Create_Project_Info (Context : in out Inst_Context; - Project : Project_Type) return Project_Info_Access + Project : GPR2.Project.View.Object) return Project_Info_Access is use Project_Info_Maps; -- Look for an existing Project_Info record corresponding to Project - Project_Name : constant Unbounded_String := +Project.Name; + Project_Name : constant Unbounded_String := +String (Project.Name); Position : constant Cursor := Context.Project_Info_Map.Find (Project_Name); begin @@ -512,8 +533,8 @@ is -- register it and return it. declare - Storage_Project : constant Project_Type := - Project.Extending_Project (Recurse => True); + Storage_Project : constant GPR2.Project.View.Object := + Most_Extending (Project); -- Actual project that will host instrumented sources: even when -- we instrument an extended project, the resulting instrumented -- sources must go to the ultimate extending project's object @@ -523,7 +544,7 @@ is Result : constant Project_Info_Access := new Project_Info' (Project => Project, - Externally_Built => Project.Externally_Built, + Externally_Built => Project.Is_Externally_Built, Output_Dir => +Project_Output_Dir (Storage_Project), Desc => Load_From_Project (Project)); begin @@ -566,20 +587,17 @@ is procedure Register_Main_To_Instrument (Context : in out Inst_Context; Mains : in out Main_To_Instrument_Vectors.Vector; - File : GNATCOLL.VFS.Virtual_File; - Project : Project_Type) + Main : GPR2.Build.Compilation_Unit.Unit_Location) is - File_Info : constant GNATCOLL.Projects.File_Info := - Standard.Project.Project.Info (File); CU_Name : constant Compilation_Unit_Part := - To_Compilation_Unit_Name (File_Info); + To_Compilation_Unit_Name (Main.View.Source (Main.Source.Simple_Name)); Prj_Info : constant Project_Info_Access := - Get_Or_Create_Project_Info (Context, Project); + Get_Or_Create_Project_Info (Context, Main.View); begin Mains.Append (Main_To_Instrument' (CU_Name => CU_Name, - File => File, + File => Create (+String (Main.Source.Value)), Prj_Info => Prj_Info)); end Register_Main_To_Instrument; @@ -600,35 +618,26 @@ is SID_Basename : Unbounded_String; - Project : constant GPR.Project_Type := - GPR.Extending_Project - (Project => LU_Info.Instr_Project, - Recurse => True); - pragma Assert (Project /= GPR.No_Project); + Project : constant GPR2.Project.View.Object := + Most_Extending (LU_Info.Instr_Project); - Output_Directory : constant Virtual_File := - (if In_Library_Dir + Output_Directory : constant GPR2.Path_Name.Object := + (if In_Library_Dir and then Project.Is_Library then Project.Library_Ali_Directory - else Project.Object_Dir); + else Project.Object_Directory); begin case Language_Kind (LU_Info.Language) is when Unit_Based_Language => declare - Src_Body_Basename : constant String := +Project.File_From_Unit - (Unit_Name => +LU_Info.Unit_Name, - Part => GNATCOLL.Projects.Unit_Body, - Language => Image (LU_Info.Language), - File_Must_Exist => True); - Src_Spec_Basename : constant String := +Project.File_From_Unit - (Unit_Name => +LU_Info.Unit_Name, - Part => GNATCOLL.Projects.Unit_Spec, - Language => Image (LU_Info.Language), - File_Must_Exist => True); - Src_Basename : constant String := - (if Src_Body_Basename = "" - then Src_Spec_Basename - else Src_Body_Basename); - Src_Ext_Index : constant Positive := + Unit : constant GPR2.Build.Compilation_Unit.Object := + Project.Namespace_Roots.First_Element + .Unit (GPR2.Name_Type (+LU_Info.Unit_Name)); + Src_Basename : constant String := + String + (if Unit.Has_Part (GPR2.S_Body) + then Unit.Main_Body.Source.Simple_Name + else Unit.Spec.Source.Simple_Name); + Src_Ext_Index : constant Positive := Ada.Strings.Fixed.Index (Src_Basename, ".", Ada.Strings.Backward); begin @@ -641,7 +650,7 @@ is +Ada.Directories.Simple_Name (+LU_Info.Unit_Name) & ".sid"; end case; - return String'(+Output_Directory.Full_Name) / (+SID_Basename); + return String (Output_Directory.Value) / (+SID_Basename); end SID_Filename; ------------------------------ @@ -665,12 +674,6 @@ is Result.Append ("--ada-preprocessor-data=" & IC.Ada_Preprocessor_Data_File); - -- Load the predefined source directories - - for Dir of IC.Predefined_Source_Dirs loop - Result.Append ("--runtime-dir=" & Dir); - end loop; - when others => null; end case; @@ -730,10 +733,11 @@ is ------------------------ procedure Add_Project_Source - (Project : GPR.Project_Type; Source_File : GPR.File_Info) is + (Project : GPR2.Project.View.Object; + Source_File : GPR2.Build.Source.Object) is begin if Builtin_Support (To_Language (Source_File.Language)) - and then not Project.Externally_Built + and then not Project.Is_Externally_Built then Project_Sources.Insert (Source_File); end if; @@ -744,7 +748,8 @@ is --------------------------- procedure Add_Instrumented_Unit - (Project : GPR.Project_Type; Source_File : GPR.File_Info) + (Project : GPR2.Project.View.Object; + Source_File : GPR2.Build.Source.Object) is Language : constant Src_Supported_Language := To_Language (Source_File.Language); @@ -753,12 +758,11 @@ is use Unit_Maps; Unit_Name : constant String := (case Lang_Kind is - when Unit_Based_Language => Owning_Unit_Name (Source_File), - when File_Based_Language => - GNATCOLL.VFS."+" (Source_File.File.Full_Name)); + when Unit_Based_Language => Get_Unit_Name (Source_File), + when File_Based_Language => String (Source_File.Path_Name.Value)); Prj_Info : constant Project_Info_Access := - Get_Or_Create_Project_Info (IC, Source_File.Project); + Get_Or_Create_Project_Info (IC, Source_File.Owning_View); LU_Info : constant Library_Unit_Info := (Unit_Name => +Unit_Name, @@ -770,7 +774,9 @@ is begin -- Check if this is an ignored source file - if Is_Ignored_Source_File (IC, +Source_File.File.Base_Name) then + if Is_Ignored_Source_File + (IC, String (Source_File.Path_Name.Simple_Name)) + then return; end if; @@ -784,13 +790,21 @@ is -- Otherwise, this is a source of interest Files_Of_Interest_Info.Insert (Source_File); - Files_Of_Interest.Insert (Source_File.File); + Files_Of_Interest.Insert + (Create (+String (Source_File.Path_Name.Value))); + + if + -- Headers are not instrumented by themselves, so exit early as soon + -- as they have been added to the sources of interest. - -- Headers are not instrumented by themselves, so exit early as soon - -- as they have been added to the sources of interest. + (Language in C_Family_Language + and then Source_File.Kind = GPR2.S_Spec) - if Language in C_Family_Language - and then Source_File.Unit_Part = GNATCOLL.Projects.Unit_Spec + -- Ada bodies that just contain the No_Body pragmas cannot be + -- instrumented (not worthwhile anyway): just skip them. + + or else (Language = Ada_Language + and then First_Unit (Source_File).Kind = GPR2.S_No_Body) then return; end if; @@ -813,7 +827,7 @@ is -- in the current instrumentation run, so there is no need to grab -- information useful for instrumentation purposes. - if Source_File.Project.Externally_Built + if Source_File.Owning_View.Is_Externally_Built then return; end if; @@ -823,24 +837,25 @@ is if Language in C_Family_Language then declare - use type GNAT.Strings.String_List_Access; + package R renames GPR2.Project.Registry.Attribute; + Options : Analysis_Options; Compiler_Opts : String_Vectors.Vector; - Switches : GNAT.Strings.String_List_Access; - Basename : constant String := +Source_File.File.Base_Name; + Switches : GPR2.Project.Attribute.Object; + Basename : constant String := + String (Source_File.Path_Name.Simple_Name); begin Switches := - Project.Attribute_Value - (Attribute => GPR.Build ("compiler", "switches"), - Index => Basename); - if Switches /= null then + Project.Attribute + (Name => R.Compiler.Switches, + Index => GPR2.Project.Attribute_Index.Create (Basename)); + if Switches.Is_Defined then declare Args : String_Vectors.Vector; begin - for S of Switches.all loop - Args.Append (+S.all); + for S of Switches.Values loop + Args.Append (+S.Text); end loop; - GNAT.Strings.Free (Switches); Import_From_Args (Options, Args); end; Add_Options (Compiler_Opts, Options, Pass_Builtins => False); @@ -881,9 +896,11 @@ is for Source of Project_Sources loop if To_Language (Source.Language) = Language - and then Source.Unit_Part = GNATCOLL.Projects.Unit_Body - and then (Manual_Indication_Files.Is_Empty - or else Manual_Indication_Files.Contains (Source.File)) + and then Source.Kind = GPR2.S_Body + and then + (Manual_Indication_Files.Is_Empty + or else Manual_Indication_Files.Contains + (Create (+String (Source.Path_Name.Value)))) then Processed_Files.Include (Source); end if; @@ -901,12 +918,12 @@ is Prj_Info : constant Project_Info_Access := Get_Or_Create_Project_Info - (IC, Source.Project.Extending_Project (Recurse => True)); + (IC, Most_Extending (Source.Owning_View)); Prj : Prj_Desc renames Prj_Info.Desc; Is_Root_Prj : constant Boolean := - To_Ada (Prj.Prj_Name) = Root_Project_Info.Project.Name; + To_Ada (Prj.Prj_Name) = String (Root_Project_Info.Project.Name); Source_Name : constant String := - GNATCOLL.VFS."+" (Source.File.Full_Name); + String (Source.Path_Name.Value); Helper_Unit_Name : constant Unbounded_String := Instrumenter.Dump_Manual_Helper_Unit (Prj).Unit_Name; Had_Dump_Indication : Boolean := False; @@ -945,21 +962,18 @@ is declare use Files_Table; Instr_Units : Unit_Sets.Set; - Source_Files : GNATCOLL.VFS.File_Array_Access := - Source.Project.Source_Files - (Recursive => True, - Include_Externally_Built => - Externally_Built_Projects_Processing_Enabled); begin - for S of Source_Files.all loop - + for S of Source_Closure + (View => Source.Owning_View, + With_Externally_Built => + Externally_Built_Projects_Processing_Enabled, + With_Runtime => False) + loop -- First, check if S is even a source of a language we -- recognize. If not, it can't have been instrumented -- so skip it. - if To_Language_Or_All - (Project.Project.Info (S).Language) = All_Languages - then + if To_Language_Or_All (S.Language) = All_Languages then goto Skip_File; end if; @@ -967,8 +981,7 @@ is use Unit_Maps; Unit_C : constant Unit_Maps.Cursor := Instrumented_Sources.Find - (+To_Compilation_Unit - (Project.Project.Info (S)).Unit_Name); + (+To_Compilation_Unit (S).Unit_Name); begin if Unit_C /= Unit_Maps.No_Element then declare @@ -995,8 +1008,6 @@ is if not Is_Root_Prj then Instrumenter.Emit_Buffers_List_Unit (Instr_Units, Prj); end if; - - GNATCOLL.VFS.Unchecked_Free (Source_Files); end; Emitted_Manual_Helpers.Insert (Helper_Unit_Name); @@ -1068,12 +1079,13 @@ is Put (Filename_Indentation); -- To keep progress logs readable, use source basenames for - -- file-based languages. + -- file-based languages. Fold actual unit names to lower case for + -- readability. if Language_Kind (Language) = File_Based_Language then Put_Line (Ada.Directories.Simple_Name (Unit_Name)); else - Put_Line (Unit_Name); + Put_Line (To_Lower (Unit_Name)); end if; end; end Show_Progress; @@ -1134,13 +1146,18 @@ begin -- this is not supported. TODO??? We should probably issue a warning there. for Source of Files_Of_Interest_Info.Copy loop - if Source.Unit_Part = GNATCOLL.Projects.Unit_Separate then + if Source.Has_Units and then First_Unit (Source).Kind = GPR2.S_Separate + then declare - Parent_Unit : constant GNATCOLL.Projects.File_Info := - Project.Project.Info - (Project.Project.Other_File (Source.File)); + Parent_Unit : constant GPR2.Build.Compilation_Unit.Unit_Location := + Source.Owning_View.Namespace_Roots.First_Element + .Unit (Source.Unit.Name).Main_Body; + Parent_File : constant GPR2.Path_Name.Object := + Parent_Unit.Source; + Parent_Source : constant GPR2.Build.Source.Object := + Parent_Unit.View.Source (Parent_File.Simple_Name); begin - if not Files_Of_Interest_Info.Contains (Parent_Unit) then + if not Files_Of_Interest_Info.Contains (Parent_Source) then Files_Of_Interest_Info.Delete (Source); end if; end; @@ -1159,8 +1176,7 @@ begin if Mains.Is_Empty then for Lang in Src_Supported_Language loop for Main of Project.Enumerate_Mains (Lang) loop - Register_Main_To_Instrument - (IC, Mains_To_Instrument (Lang), Main.File, Main.Project); + Register_Main_To_Instrument (IC, Mains_To_Instrument (Lang), Main); end loop; end loop; @@ -1171,18 +1187,16 @@ begin else for Filename of Mains loop declare - F : constant String := +Filename; - Info : constant File_Info := - Project.Project.Root_Project.Create_From_Project (+F); - File : constant Virtual_File := Info.File; - Project : constant Project_Type := Info.Project; - Lang : Any_Language; + F : constant String := +Filename; + Source : constant GPR2.Build.Source.Object := + Project.Project.Root_Project.Source (GPR2.Simple_Name (F)); + Lang : Any_Language; begin - if File = No_File or else Project = No_Project then + if not Source.Is_Defined then Outputs.Fatal_Error ("No such source file: " & F); end if; - Lang := To_Language_Or_All (Info.Language); + Lang := To_Language_Or_All (Source.Language); if Lang not in Src_Supported_Language or else not Builtin_Support (Lang) then @@ -1192,7 +1206,11 @@ begin end if; Register_Main_To_Instrument - (IC, Mains_To_Instrument (Lang), File, Project); + (Context => IC, + Mains => Mains_To_Instrument (Lang), + Main => (Source.Owning_View, + Source.Path_Name, + others => <>)); end; end loop; end if; @@ -1223,7 +1241,7 @@ begin -- coverage data is in including bodies' coverage buffers). IC.Mapping_File := - +Create_Ada_Mapping_File (Project.Project.Root_Project); + +(+Root_Project_Info.all.Output_Dir) / ".ada-src-mapping"; IC.Config_Pragmas_Mapping := +(+Root_Project_Info.all.Output_Dir) / "config-pragmas.json"; IC.Sources_Of_Interest_Response_File := @@ -1231,20 +1249,14 @@ begin IC.Ada_Preprocessor_Data_File := +(+Root_Project_Info.all.Output_Dir) / "prep-data.json"; + Instrument.Ada_Unit_Provider.Create_Mapping_File (+IC.Mapping_File); + Instrument.Ada_Unit.Save_Config_Pragmas_Mapping (+IC.Config_Pragmas_Mapping); Instrument.Ada_Preprocessing.Create_Preprocessor_Data_File (+IC.Ada_Preprocessor_Data_File); - -- Set the runtime directories - - for Dir of - Project.Project.Root_Project.Get_Environment.Predefined_Source_Path - loop - IC.Predefined_Source_Dirs.Append (Full_Name (Dir)); - end loop; - -- Initialize the instrumenters: we will use them when parallelization is -- disabled, but also to generate the unit holding the list of buffers, -- in one of the supported languages. @@ -1254,7 +1266,6 @@ begin (Tag => IC.Tag, Config_Pragmas_Mapping => +IC.Config_Pragmas_Mapping, Mapping_Filename => +IC.Mapping_File, - Predefined_Source_Dirs => IC.Predefined_Source_Dirs, Preprocessor_Data_Filename => +IC.Ada_Preprocessor_Data_File); C_Instrumenter := Create_C_Instrumenter (IC.Tag, Project_Instrumentation); CPP_Instrumenter := @@ -1285,7 +1296,7 @@ begin Sources_Of_Interest_File.Create (+IC.Sources_Of_Interest_Response_File); for Source of Files_Of_Interest_Info loop - Sources_Of_Interest_File.Put_Line (+Source.File.Full_Name); + Sources_Of_Interest_File.Put_Line (String (Source.Path_Name.Value)); end loop; Sources_Of_Interest_File.Close; end; @@ -1319,9 +1330,10 @@ begin Obj_SID : constant String := SID_Filename (LU_Info, In_Library_Dir => False); - Prj : constant Project_Type := LU_Info.Instr_Project; + Prj : constant GPR2.Project.View.Object := + LU_Info.Instr_Project; Desc : constant Prj_Desc := - IC.Project_Info_Map.Element (+Prj.Name).Desc; + IC.Project_Info_Map.Element (+String (Prj.Name)).Desc; begin -- Skip instrumentation of the unit if it was already -- instrumented. @@ -1377,7 +1389,10 @@ begin SID_Filename (LU_Info, In_Library_Dir => True); Success : Boolean; begin - if not LU_Info.All_Externally_Built and then Obj_SID /= Lib_SID then + if not LU_Info.All_Externally_Built + and then Lib_SID /= "" + and then Obj_SID /= Lib_SID + then -- Unlike the object directory, which GNATCOLL.Project -- creates automatically, the library directory may not @@ -1432,7 +1447,7 @@ begin -- coverage buffers is defined accordingly. Instrument_Main_Args.Append - (+"--project-name=" & Root_Project_Info.Project.Name); + (+"--project-name=" & String (Root_Project_Info.Project.Name)); Instrument_Main_Args.Append (Common_Switches (Cmd_Instrument_Main)); @@ -1465,11 +1480,14 @@ begin -- here: we use the executable name, that is retrieved from -- the project. - if Dump_Config.Filename_Prefix = "" then - Explicit_Dump_Config.Filename_Prefix := - +(+Root_Project_Info.Project.Executable_Name - (Main.File.Full_Name, Include_Suffix => True)); - end if; + if Dump_Config.Filename_Prefix = "" then + Explicit_Dump_Config.Filename_Prefix := + +String + (Root_Project_Info.Project.Executable + (Source => GPR2.Simple_Name (Main.File.Base_Name), + At_Pos => 0) + .Simple_Name); + end if; end if; end; @@ -1519,7 +1537,8 @@ begin Instr_Units : String_Sets.Set; begin for Source of Files_Of_Interest_Info loop - Instr_Units.Insert (Full_Name (Source.File)); + Instr_Units.Insert + (+String (Source.Path_Name.Value)); end loop; Instrument.Main (Instrumenter => Instrumenters (Language).all, @@ -1556,6 +1575,8 @@ begin declare use Files_Table; Instr_Units : Unit_Sets.Set; + Langs : constant GPR2.Containers.Language_Set := + Root_Project_Info.Project.Language_Ids; begin for LU_Info of Instrumented_Sources loop Instr_Units.Insert @@ -1563,7 +1584,7 @@ begin end loop; for Lang in Src_Supported_Language loop if Builtin_Support (Lang) - and then Root_Project_Info.Project.Has_Language (Image (Lang)) + and then Langs.Contains (To_Language_Id (Lang)) then Instrumenters (Lang).Emit_Buffers_List_Unit (Instr_Units, Root_Project_Info.Desc); diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index a97c2ee9e..2a2af3834 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -28,6 +28,13 @@ with GNAT.OS_Lib; with Interfaces; use Interfaces; with GNATCOLL.VFS; use GNATCOLL.VFS; +with GPR2.Build.Unit_Info; + +-- ??? Remove pragma Warnings once eng/toolchain/gnat#1283 is fixed + +pragma Warnings (Off, "not referenced"); +with GPR2.Project.View.Set; +pragma Warnings (On, "not referenced"); with Command_Line; use Command_Line; with Files_Handling; use Files_Handling; @@ -35,6 +42,8 @@ with Hex_Images; use Hex_Images; package body Instrument is + use type GPR2.Unit_Kind; + function Hash_32_Image (S : String) return String is (Hex_Image (Unsigned_32 (Ada.Strings.Hash (S)))); -- Return the 8-bytes image of a hash for S @@ -89,7 +98,11 @@ package body Instrument is case CUP.Language_Kind is when Unit_Based_Language => Read (CLS, CUP.Unit); - CUP.Part := Unit_Parts'Val (CLS.Read_U8); + CUP.Part := (case CLS.Read_U8 is + when 0 => GPR2.S_Body, + when 1 => GPR2.S_Spec, + when 2 => GPR2.S_Separate, + when others => raise Constraint_Error); when File_Based_Language => CUP.Filename := CLS.Read_Unbounded_String; @@ -117,7 +130,11 @@ package body Instrument is case Value.Language_Kind is when Unit_Based_Language => Write (CSS, Value.Unit); - CSS.Write_U8 (Unit_Parts'Pos (Value.Part)); + CSS.Write_U8 + (case Value.Part is + when GPR2.S_Spec => 1, + when GPR2.S_Body => 0, + when GPR2.S_Separate => 2); when File_Based_Language => CSS.Write (Value.Filename); @@ -338,9 +355,9 @@ package body Instrument is return To_Ada (CU_Name.Unit) & " " & (case CU_Name.Part is - when GNATCOLL.Projects.Unit_Spec => "spec", - when GNATCOLL.Projects.Unit_Body => "body", - when GNATCOLL.Projects.Unit_Separate => "subunit"); + when GPR2.S_Spec => "spec", + when GPR2.S_Body => "body", + when GPR2.S_Separate => "subunit"); when File_Based_Language => return +CU_Name.Filename; end case; @@ -402,15 +419,15 @@ package body Instrument is function CU_Name_For_Unit (Unit : Ada_Qualified_Name; - Part : Unit_Parts) return Compilation_Unit_Part + Part : GPR2.Valid_Unit_Kind) return Compilation_Unit_Part is begin return (Unit_Based_Language, Unit, Part); end CU_Name_For_Unit; - ----------------------------- + ---------------------- -- CU_Name_For_File -- - ----------------------------- + ---------------------- function CU_Name_For_File (Filename : Unbounded_String) return Compilation_Unit_Part is @@ -423,17 +440,20 @@ package body Instrument is ------------------------------ function To_Compilation_Unit_Name - (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Part - is + (Source : GPR2.Build.Source.Object) return Compilation_Unit_Part is begin - case Language_Kind (To_Language (Source_File.Language)) is + case Language_Kind (To_Language (Source.Language)) is when Unit_Based_Language => - return CU_Name_For_Unit - (Unit => To_Qualified_Name (Source_File.Unit_Name), - Part => Source_File.Unit_Part); + declare + Unit : constant GPR2.Build.Unit_Info.Object := Source.Unit; + begin + return CU_Name_For_Unit + (Unit => To_Qualified_Name (To_Lower (String (Unit.Name))), + Part => Unit.Kind); + end; when File_Based_Language => return CU_Name_For_File - (Filename => +(+Source_File.File.Full_Name)); + (Filename => +String (Source.Path_Name.Value)); end case; end To_Compilation_Unit_Name; diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index da6ad33dd..33cb7a92f 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -21,7 +21,8 @@ with Ada.Containers.Ordered_Maps; with Ada.Containers.Vectors; -with GNATCOLL.Projects; use GNATCOLL.Projects; +with GPR2.Build.Source; +with GPR2.Project.View; with Types; use Types; @@ -45,8 +46,6 @@ package Instrument is Logging.Create_Trace ("INSTRUMENT_SOURCES"); -- Trace to show details about written instrumented sources - package GPR renames GNATCOLL.Projects; - use type Ada.Containers.Count_Type; use all type Unbounded_String; @@ -103,8 +102,8 @@ package Instrument is case Language_Kind is when Unit_Based_Language => - Unit : Ada_Qualified_Name := Ada_Identifier_Vectors.Empty_Vector; - Part : Unit_Parts := GNATCOLL.Projects.Unit_Body; + Unit : Ada_Qualified_Name := Ada_Identifier_Vectors.Empty_Vector; + Part : GPR2.Valid_Unit_Kind := GPR2.S_Body; -- Identifies an Ada compilation unit (unit-based) when File_Based_Language => @@ -126,10 +125,10 @@ package Instrument is Value : Compilation_Unit_Part); -- Write a Compilation_Unit_Part to CSS - Part_Tags : constant array (Unit_Parts) of Character := - (GNATCOLL.Projects.Unit_Spec => 'S', - GNATCOLL.Projects.Unit_Body => 'B', - GNATCOLL.Projects.Unit_Separate => 'U'); + Part_Tags : constant array (GPR2.Valid_Unit_Kind) of Character := + (GPR2.S_Spec => 'S', + GPR2.S_Body => 'B', + GPR2.S_Separate => 'U'); function "=" (Left, Right : Compilation_Unit_Part) return Boolean; @@ -190,7 +189,7 @@ package Instrument is function CU_Name_For_Unit (Unit : Ada_Qualified_Name; - Part : Unit_Parts) return Compilation_Unit_Part; + Part : GPR2.Valid_Unit_Kind) return Compilation_Unit_Part; -- Return the compilation unit name for the Ada compilation unit -- corresponding to the unit name and the unit part parameters. @@ -200,9 +199,8 @@ package Instrument is -- corresponding to the filename parameter. function To_Compilation_Unit_Name - (Source_File : GNATCOLL.Projects.File_Info) return Compilation_Unit_Part; - -- Return the compilation unit name corresponding to the unit in - -- Source_File. + (Source : GPR2.Build.Source.Object) return Compilation_Unit_Part; + -- Return the compilation unit name corresponding to the unit in Source package Instrumented_Unit_To_CU_Maps is new Ada.Containers.Ordered_Maps (Key_Type => Compilation_Unit_Part, @@ -274,6 +272,9 @@ package Instrument is Prj_Name : Ada_Qualified_Name; -- Name for the project + View : GPR2.Project.View.Object; + -- GPR2 view for the project, if this is backed by an actual GPR project + Output_Dir : Unbounded_String; -- Where the instrumented sources and coverage buffer units are -- generated. diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index cfae6353d..9bd749ebc 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -18,20 +18,30 @@ with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Containers.Indefinite_Ordered_Sets; -with Ada.Containers.Vectors; with Ada.Directories; use Ada.Directories; -with Ada.Tags; with GNAT.OS_Lib; with GNAT.Regexp; with GNATCOLL.Traces; -with GNATCOLL.Projects.Aux; with GNATCOLL.VFS; use GNATCOLL.VFS; -with GPR2.Project.Registry.Attribute; + +-- ??? Remove pragma Warnings once eng/toolchain/gnat#1283 is fixed + +pragma Warnings (Off, "not referenced"); +with GPR2.Build.Source.Sets; +pragma Warnings (On, "not referenced"); +with GPR2.Message; +with GPR2.Options; +with GPR2.Path_Name; +with GPR2.Path_Name.Set; +with GPR2.Project.Attribute; +with GPR2.Project.Attribute_Index; with GPR2.Project.Registry.Attribute.Description; -with GPR2.Project.Registry.Pack; +with GPR2.Project.Registry.Attribute; with GPR2.Project.Registry.Pack.Description; +with GPR2.Project.Registry.Pack; +with GPR2.Reporter.Console; with Inputs; use Inputs; with Instrument; use Instrument; @@ -41,16 +51,24 @@ with Traces_Source; package body Project is + use type Ada.Containers.Count_Type; use type Unbounded_String; + use type GPR2.Filename_Type; + use type GPR2.Language_Id; + use type GPR2.Path_Name.Object; + use type GPR2.Project.View.Object; + use type GPR2.Project_Kind; + use type GPR2.Unit_Kind; + subtype Compilation_Unit is Files_Table.Compilation_Unit; use type Compilation_Unit; use type Traces_Source.Supported_Language_Kind; - Coverage_Package : aliased String := "coverage"; - Coverage_Package_List : aliased String_List := - (1 => Coverage_Package'Access); + Project_File_Extension : constant String := ".gpr"; + + Coverage_Package : constant String := "coverage"; GPR2_Coverage_Package : constant GPR2.Package_Id := GPR2."+" (GPR2.Name_Type (Coverage_Package)); @@ -74,15 +92,13 @@ package body Project is Attribute range Units_List .. Ignored_Source_Files_List; function "+" (A : Attribute) return String; - function "+" (A : String_Attribute) return Attribute_Pkg_String; - function "+" (A : List_Attribute) return Attribute_Pkg_List; function "+" (A : Attribute) return GPR2.Q_Attribute_Id; -- Build identifiers for attributes in package Coverage procedure Iterate_Source_Files - (Root_Project : Project_Type; + (Root_Project : GPR2.Project.View.Object; Process : access procedure - (Info : File_Info; Unit_Name : String); + (Source : GPR2.Build.Source.Object; Unit_Name : String); Recursive : Boolean); -- Call Process on all source files in Root_Project (recursively -- considering source files of sub-projects if Recursive is true). @@ -90,10 +106,15 @@ package body Project is -- This passes the name of the unit as Unit_Name for languages featuring -- this notion (Ada) and the base file name otherwise (i.e. for C sources). - Env : Project_Environment_Access; - -- Environment in which we load the project tree + function SCO_Filename + (Source : GPR2.Build.Source.Object; + Kind : Trace_File_Kind) + return GPR2.Path_Name.Object; + -- Return the SCO absolute filename corresponding to the given source file + -- and the given trace kind (.ali/.gli for binary traces, .sid for source + -- traces). Return ``Undefined`` if none can be found. - Prj_Tree : Project_Tree_Access; + Prj_Tree : GPR2.Project.Tree.Object; -- Loaded project tree Obj_Subdir : Unbounded_String; @@ -108,7 +129,7 @@ package body Project is -- set. type Project_Info is record - Project : Project_Type; + Project : GPR2.Project.View.Object; -- The project this info relates to Has_Units_Of_Interest : Boolean; @@ -163,11 +184,11 @@ package body Project is (Units : in out Unit_Maps.Map; Cur : out Unit_Maps.Cursor; Original_Name : String; - Info : File_Info; + Source : GPR2.Build.Source.Object; Language : Some_Language); -- Add a Unit_Info entry to Units. The key for this new entry (which is a - -- Compilation_Unit) is computed using the Original_Name, and the - -- Info.Project_Name if the unit is of a file-based language. + -- Compilation_Unit) is computed using the Original_Name, and Source's + -- project name if the unit is of a file-based language. procedure Warn_Missing_Info (What_Info : String; Unit : in out Unit_Info); -- If we haven't already, warn that we miss information (ALI or SID) about @@ -178,14 +199,7 @@ package body Project is -- interest. This map contains header files (C/C++) but does not contain -- separate (Ada) units. - procedure Initialize - (Target, Runtime, CGPR_File : GNAT.Strings.String_Access) - with Pre => (Target = null and then Runtime = null) - or else CGPR_File = null; - -- Initialize project environment. Formals have the same semantics as in - -- Load_Root_Project. - - function Lookup_Project (Prj_Name : String) return Project_Type; + function Lookup_Project (Prj_Name : String) return GPR2.Project.View.Object; -- Look for the project in Prj_Tree whose name matches Prj_Name and return -- it. Emit a fatal error if there is no such project. @@ -196,7 +210,7 @@ package body Project is -- Add entries in Unit_Map for all units of interest procedure List_From_Project - (Prj : Project_Type; + (Prj : GPR2.Project.View.Object; List_Attr : List_Attribute; List_File_Attr : String_Attribute; Process_Item : access procedure (Attr, Item : String); @@ -209,7 +223,7 @@ package body Project is -- defined. procedure Units_From_Project - (Prj : Project_Type; + (Prj : GPR2.Project.View.Object; List_Attr : List_Attribute; List_File_Attr : String_Attribute; Units : out Unit_Maps.Map; @@ -225,8 +239,9 @@ package body Project is -- and fill Units with one entry per unit. Set Defined to False otherwise. function Enumerate_Mains - (Root_Project : Project_Type; - Language : Any_Language) return Main_Source_File_Array; + (Root_Project : GPR2.Project.View.Object; + Language : Any_Language) + return GPR2.Build.Compilation_Unit.Unit_Location_Vector; -- Return the list of all main source files recursively found in the -- Root_Project for the given Language, or for all languages if Language is -- All_Languages. @@ -234,57 +249,43 @@ package body Project is -- Note that this also returns source files for mains that are not units of -- interest. - ---------------------- - -- Owning_Unit_Name -- - ---------------------- + type Reporter is new GPR2.Reporter.Object with record + Inner : GPR2.Reporter.Console.Object; + end record; - function Owning_Unit_Name (Info : File_Info) return String is - begin - if Info.Unit_Part = Unit_Separate then - declare - Other : constant File_Info := - Prj_Tree.Info (Prj_Tree.Other_File (Info.File)); - begin - -- TODO??? (eng/das/cov/gnatcoverage#217) - -- GNATCOLL.Projects.Other_File misbehaves for some subunits in - -- the Ada runtime: work around this bug here until it is fixed. + overriding function Verbosity + (Self : Reporter) return GPR2.Reporter.Verbosity_Level; - if Other.Unit_Name /= "" then - return Other.Unit_Name; - end if; + overriding procedure Internal_Report + (Self : in out Reporter; Message : GPR2.Message.Object); - declare - Unit_Name : constant String := Info.Unit_Name; - begin - if Unit_Name in "s.tpopsp" | "s.tporft" then - return "s.taprop"; - end if; + ------------------- + -- Get_Unit_Name -- + ------------------- - raise Program_Error with - "cannot determine owning unit for separate " & Unit_Name; - end; - end; - else - return Info.Unit_Name; - end if; - end Owning_Unit_Name; + function Get_Unit_Name (Source : GPR2.Build.Source.Object) return String is + begin + return (if Source.Has_Units + then To_Lower (String (First_Unit (Source).Name)) + else String (Source.Path_Name.Simple_Name)); + end Get_Unit_Name; ------------------------- -- To_Compilation_Unit -- ------------------------- function To_Compilation_Unit - (Info : File_Info) return Files_Table.Compilation_Unit + (Source : GPR2.Build.Source.Object) return Files_Table.Compilation_Unit is - Language : constant Some_Language := To_Language (Info.Language); + Language : constant Some_Language := To_Language (Source.Language); U : Compilation_Unit; begin U.Language := Language_Kind (Language); case U.Language is when Traces_Source.File_Based_Language => - U.Unit_Name := +(+Info.File.Full_Name); + U.Unit_Name := +String (Source.Path_Name.Value); when Traces_Source.Unit_Based_Language => - U.Unit_Name := +Owning_Unit_Name (Info); + U.Unit_Name := +To_Lower (String (First_Unit (Source).Name)); end case; return U; end To_Compilation_Unit; @@ -298,16 +299,6 @@ package body Project is return Coverage_Package & "." & To_Lower (A'Image); end "+"; - function "+" (A : String_Attribute) return Attribute_Pkg_String is - begin - return Build (Coverage_Package, A'Img); - end "+"; - - function "+" (A : List_Attribute) return Attribute_Pkg_List is - begin - return Build (Coverage_Package, A'Img); - end "+"; - function "+" (A : Attribute) return GPR2.Q_Attribute_Id is begin return (GPR2_Coverage_Package, GPR2."+" (GPR2.Name_Type (A'Image))); @@ -321,12 +312,12 @@ package body Project is (Units : in out Unit_Maps.Map; Cur : out Unit_Maps.Cursor; Original_Name : String; - Info : File_Info; + Source : GPR2.Build.Source.Object; Language : Some_Language) is Orig_Name : constant Unbounded_String := +Fold_Filename_Casing (Original_Name); - Unit_Name : constant Compilation_Unit := To_Compilation_Unit (Info); + Unit_Name : constant Compilation_Unit := To_Compilation_Unit (Source); Ignored_Inserted : Boolean; Is_Header : Boolean := False; @@ -334,7 +325,7 @@ package body Project is -- Disable warnings for header files as they do not have a corresponding -- library file. - if Language in C_Family_Language and then Info.Unit_Part = Unit_Spec then + if Language in C_Family_Language and then Source.Kind = GPR2.S_Spec then Is_Header := True; end if; @@ -381,51 +372,78 @@ package body Project is ---------------------- procedure Iterate_Projects - (Root_Project : GNATCOLL.Projects.Project_Type; + (Root_Project : GPR2.Project.View.Object; Process : access procedure - (Prj : GNATCOLL.Projects.Project_Type); + (Prj : GPR2.Project.View.Object); Recursive : Boolean; Include_Extended : Boolean := False; Include_Externally_Built : Boolean := Externally_Built_Projects_Processing_Enabled) is - Iter : Project_Iterator := Start - (Root_Project => Root_Project, - Recursive => Recursive, - Include_Extended => Include_Extended); + procedure Process_Candidate (Project : GPR2.Project.View.Object); + -- Process Project, one project in the closure of Root_Project, + -- according to the requested iteration settings. + Visited_Projects : Project_Sets.Set; - Project : Project_Type; - begin - loop - Project := Current (Iter); - exit when Project = No_Project; + -- Set of already visited projects, used to make sure each project is + -- visited at most once. + + ----------------------- + -- Process_Candidate -- + ----------------------- + + procedure Process_Candidate (Project : GPR2.Project.View.Object) is + P : GPR2.Project.View.Object := Project; + begin + -- We never want to consider the runtime project as a project of + -- interest. As a subtle nuance, it is still possible to do coverage + -- on runtime sources, but in this case the corresponding project + -- must be loaded the usual way (i.e. not as a runtime project: + -- --RTS, "for Runtime", ...). + + if Project.Is_Runtime then + return; + end if; -- If requested, go to the ultimate extending project: this is the -- "reference" project for chains of project extension (we care about -- the Coverage package of extending projects, their object dirs, - -- etc.). + -- etc.). Otherwise, also process extended projects. if not Include_Extended then - Project := Extending_Project (Project, Recurse => True); + P := Most_Extending (P); + elsif P.Is_Extending then + for EP of P.Extended loop + Process_Candidate (EP); + end loop; end if; declare - Name : constant String := Project.Name; + Name : constant String := String (P.Name); begin -- Skip externally built projects unless they are explicitly -- requested. if (Include_Externally_Built - or else not Project.Externally_Built) + or else not P.Is_Externally_Built) and then not Visited_Projects.Contains (Name) then - Process (Project); + Process (P); Visited_Projects.Insert (Name); end if; end; + end Process_Candidate; - Next (Iter); - end loop; + -- Start of processing for Iterate_Projects + + begin + if Recursive then + for Project of Root_Project.Closure (Include_Self => True) loop + Process_Candidate (Project); + end loop; + else + Process_Candidate (Root_Project); + end if; end Iterate_Projects; -------------------------- @@ -433,62 +451,47 @@ package body Project is -------------------------- procedure Iterate_Source_Files - (Root_Project : Project_Type; + (Root_Project : GPR2.Project.View.Object; Process : access procedure - (Info : File_Info; Unit_Name : String); + (Source : GPR2.Build.Source.Object; Unit_Name : String); Recursive : Boolean) is - -- If Root_Project is extending some project P, consider for coverage - -- purposes that source files in P also belong to Root_Project. For - -- instance, if Root_Project extends P only to replace some of P's units - -- with stubs, users most likely want to compute the coverage of other - -- units in P. - -- - -- When Recursive is true, there is nothing specific to do, as - -- Source_Files will go through extended projects. However, when - -- recursive is False, use Extended_Projects_Source_Files to go through - -- them. - - Source_Files : File_Array_Access := - (if Recursive - then Root_Project.Source_Files (Recursive => True) - else Root_Project.Extended_Projects_Source_Files); - begin - for F of Source_Files.all loop - declare - use type Ada.Tags.Tag; + procedure Process_Project (Prj : GPR2.Project.View.Object); + -- Invoke Process on relevant sources in Prj - Infos : constant File_Info_Set := Prj_Tree.Info_Set (F); - begin - for Abstract_Info of Infos loop + --------------------- + -- Process_Project -- + --------------------- - -- ??? It seems that GNATCOLL.Projects.Info_Set always put - -- File_Info records in File_Info_Sets.Set containers, so it's - -- not clear why File_Info_Sets.Set contains - -- File_Info_Abstract'Class objects instead. Anyway, put - -- defensive code here to avoid constraint errors if that is - -- not true one day. + procedure Process_Project (Prj : GPR2.Project.View.Object) is + begin + for Source of Prj.Sources loop - if Abstract_Info'Tag = File_Info'Tag then - declare - Info : constant File_Info := File_Info (Abstract_Info); - begin - -- Process only source files in supported languages (Ada, - -- C and C++): - - if To_Lower (Info.Language) in "ada" | "c" | "c++" then - Process.all - (Info => Info, - Unit_Name => (if Info.Unit_Name = "" - then +F.Base_Name - else Info.Unit_Name)); - end if; - end; - end if; - end loop; - end; - end loop; - Unchecked_Free (Source_Files); + -- Process only source files in supported languages (Ada, C and + -- C++). Never include Ada's "No_Body" units, as we cannot do + -- anything useful with them, and GPR2 pretends they do not belong + -- to any unit. + + if Source.Language in + GPR2.Ada_Language | GPR2.C_Language | GPR2.CPP_Language + and then (not Source.Has_Units + or else First_Unit (Source).Kind /= GPR2.S_No_Body) + then + Process.all (Source, Get_Unit_Name (Source)); + end if; + end loop; + end Process_Project; + + -- Start of processing for Iterate_Source_Files + + begin + -- Iterate on all the projects implied by our arguments: Root_Project, + -- possibly with its closure. + + Iterate_Projects + (Root_Project => Root_Project, + Process => Process_Project'Access, + Recursive => Recursive); end Iterate_Source_Files; ----------------- @@ -514,6 +517,51 @@ package body Project is end loop; end Enumerate_Units_Of_Interest; + ------------------ + -- SCO_Filename -- + ------------------ + + function SCO_Filename + (Source : GPR2.Build.Source.Object; + Kind : Trace_File_Kind) + return GPR2.Path_Name.Object + is + Is_Ada : constant Boolean := Source.Language = GPR2.Ada_Language; + Prefix : GPR2.Simple_Name := + (if Is_Ada + then Source.Path_Name.Base_Filename + else Source.Path_Name.Simple_Name); + Extension : constant GPR2.Simple_Name := + (case Kind is + when Binary_Trace_File => (if Is_Ada + then ".ali" + else ".gli"), + when Source_Trace_File => ".sid"); + Basename : constant GPR2.Simple_Name := Prefix & Extension; + + -- Depending on whether this unit belongs to a library project and + -- whether it was installed, the SID file can be in the library + -- directory or in the object directory: check the library directory and + -- fallback to the object directory. + + View : constant GPR2.Project.View.Object := Source.Owning_View; + Result : GPR2.Path_Name.Object; + begin + if View.Is_Library then + Result := View.Library_Directory.Compose (Basename); + if Result.Exists then + return Result; + end if; + end if; + + Result := View.Object_Directory.Compose (Basename); + if Result.Exists then + return Result; + end if; + + return GPR2.Path_Name.Undefined; + end SCO_Filename; + ------------------------- -- Enumerate_SCO_Files -- ------------------------- @@ -522,35 +570,61 @@ package body Project is (Callback : access procedure (Lib_Name : String); Kind : Trace_File_Kind) is - Ext_Regexp : constant GNATCOLL.VFS.Filesystem_String := - (case Kind is - when Binary_Trace_File => "^.*\.[ag]li$", - when Source_Trace_File => "^.*\.sid$"); - Lib_Info : Library_Info_List; + Files_Found : String_Sets.Set; begin - -- Go through all SCOs files in all projects of interest + -- Go through all sources in all projects of interest for Prj_Info of Prj_Map loop - Prj_Info.Project.Library_Files - (List => Lib_Info, ALI_Ext => Ext_Regexp); - for LI of Lib_Info loop - - -- If the unit for this SCO file is in Unit_Map, this is a - -- unit of interest, so use it. + for Source of Prj_Info.Project.Sources loop - declare - use Unit_Maps; + -- Skip sources for languages unknown to gnatcov. Also skip + -- No_Body Ada unit, which cannot have SCOs by themselves, and + -- GPR2 treats them as having no unit name, so we need to + -- explicitly ignore them. - Cur : constant Cursor := - Unit_Map.Find (To_Compilation_Unit (LI.Source.all)); - begin - if Has_Element (Cur) then - Callback.all (+LI.Library_File.Full_Name); - Unit_Map.Reference (Cur).LI_Seen := True; - end if; - end; + if To_Language_Or_All (Source.Language) /= All_Languages + and then (not Source.Has_Units + or else First_Unit (Source).Kind /= GPR2.S_No_Body) + then + declare + use Unit_Maps; + Cur : constant Cursor := + Unit_Map.Find (To_Compilation_Unit (Source)); + begin + if Has_Element (Cur) then + + -- If Sources belongs to a unit of interest, look for its + -- info file (ALI/SID). + + declare + Info_File : constant GPR2.Path_Name.Object := + SCO_Filename (Source, Kind); + Unused_Cur : String_Sets.Cursor; + Inserted : Boolean; + begin + if Info_File.Is_Defined then + + -- The same SCO file may cover multiple source + -- files: invoke the callback only once per SCO + -- file. + + declare + Filename : constant String := + String (Info_File.Value); + begin + Files_Found.Insert + (+Filename, Unused_Cur, Inserted); + if Inserted then + Callback.all (Filename); + Unit_Map.Reference (Cur).LI_Seen := True; + end if; + end; + end if; + end; + end if; + end; + end if; end loop; - Lib_Info.Clear; end loop; -- Now warn about units of interest that have no SCOs file @@ -573,12 +647,13 @@ package body Project is procedure Enumerate_Sources (Callback : access procedure - (Project : GNATCOLL.Projects.Project_Type; - File : GNATCOLL.Projects.File_Info); + (Project : GPR2.Project.View.Object; + File : GPR2.Build.Source.Object); Language : Any_Language; Only_UOIs : Boolean := False) is - procedure Process_Source_File (Info : File_Info; Unit_Name : String); + procedure Process_Source_File + (Source : GPR2.Build.Source.Object; Unit_Name : String); -- Callback for Iterate_Source_File. If Only_UOIs is set to true, call -- Callback the Unit_Name file is it a unit of interest. If Only_UOIs is -- set to False, call Callback on all sources. @@ -587,28 +662,31 @@ package body Project is -- Process_Source_File -- ------------------------- - procedure Process_Source_File (Info : File_Info; Unit_Name : String) + procedure Process_Source_File + (Source : GPR2.Build.Source.Object; Unit_Name : String) is pragma Unreferenced (Unit_Name); - Info_Lang : constant Some_Language := To_Language (Info.Language); + Info_Lang : constant Some_Language := + To_Language_Or_All (Source.Language); begin - if Language = All_Languages or else Language = Info_Lang then + -- If only sources for a specific language are requested and this + -- is not the language for Source, skip it. - -- If this is a header, consider it a unit of interest. For now, - -- they can only be ignored through the --ignore-source-files - -- switch. + if Language /= All_Languages and then Language /= Info_Lang then + return; + end if; - if (Language_Kind (Info_Lang) = Traces_Source.File_Based_Language - and then Info.Unit_Part = Unit_Spec) + -- If this is a header, consider it a unit of interest. For now, they + -- can only be ignored through the --ignore-source-files switch. - -- Otherwise, check if the unit is in the units of interest - -- map + if (not Source.Has_Units and then Source.Kind = GPR2.S_Spec) - or else not Only_UOIs - or else Unit_Map.Contains (To_Compilation_Unit (Info)) - then - Callback (Info.Project, Info); - end if; + -- Otherwise, check if the unit is in the units of interest map + + or else not Only_UOIs + or else Unit_Map.Contains (To_Compilation_Unit (Source)) + then + Callback (Source.Owning_View, Source); end if; end Process_Source_File; @@ -631,160 +709,55 @@ package body Project is return GNAT.Strings.String_Access is begin - if Prj_Tree = null then + if not Prj_Tree.Is_Defined then return null; end if; declare - Result : constant Virtual_File := GNATCOLL.Projects.Create - (Self => Prj_Tree.all, - Name => +Simple_Name, - Use_Object_Path => False); + Result : constant GPR2.Build.Source.Object := + Prj_Tree.Root_Project.Visible_Source + (GPR2.Simple_Name (Simple_Name)); begin - if Result = No_File then - return null; - else - return new String'(+Full_Name (Result)); - end if; + return (if Result.Is_Defined + then new String'(String (Result.Path_Name.Value)) + else null); end; end Find_Source_File; - ---------------- - -- Initialize -- - ---------------- + -------------------- + -- Lookup_Project -- + -------------------- - procedure Initialize - (Target, Runtime, CGPR_File : GNAT.Strings.String_Access) + function Lookup_Project (Prj_Name : String) return GPR2.Project.View.Object is - use Key_Element_Maps; + Lower_Basename : constant String := To_Lower (Simple_Name (Prj_Name)); + Result : GPR2.Project.View.Object; begin - Initialize (Env); - - -- If no configuration project file is passed, automatically generate - -- one so that we extract the same information from user project files - -- as GPRbuild does, like precise executable names. - - if CGPR_File = null then - Env.Set_Automatic_Config_File; - else - Env.Set_Config_File (Create (+CGPR_File.all)); - end if; - - -- Prepare for C units handling (by default, only Ada units are handled - -- in projects). - - Register_Default_Language_Extension - (Self => Env.all, - Language_Name => "C", - Default_Spec_Suffix => ".h", - Default_Body_Suffix => ".c", - Obj_Suffix => ".o"); - - -- Register attributes of package Coverage - - for A in Attribute'Range loop - declare - Err : constant String := - Register_New_Attribute - (Name => A'Img, - Pkg => Coverage_Package, - Is_List => A in List_Attribute, - Indexed => (A = Switches)); - begin - if Err /= "" then - Fatal_Error (Err); - end if; - end; - end loop; - - -- If provided, override the project target - - if Target /= null or else Runtime /= null then - Env.Set_Target_And_Runtime - (Target => (if Target = null then "" else Target.all), - Runtime => (if Runtime = null then "" else Runtime.all)); - end if; - - -- Set project search path for target - declare - Gnatls_Version : GNAT.Strings.String_Access; + -- Strip optional Project_File_Extension + + Name : constant String := + (if Has_Suffix (Lower_Basename, Project_File_Extension) + then Lower_Basename + (Lower_Basename'First + .. Lower_Basename'Last - Project_File_Extension'Length) + else Lower_Basename); begin - Env.Set_Path_From_Gnatls - (Gnatls => - (if Target = null then "gnatls" - elsif Target.all = "aamp" then "gnaampls" - else Target.all & "-gnatls"), - GNAT_Version => Gnatls_Version, - Errors => null); - if Gnatls_Version /= null then - Misc_Trace.Trace - ("default paths set from GNATLS " & Gnatls_Version.all); - end if; - Free (Gnatls_Version); - end; - - -- Set scenario variables - - for Scv_C in S_Variables.Iterate loop - Change_Environment (Env.all, Key (Scv_C), Element (Scv_C)); - end loop; - - -- Make sure GPR_TOOL is initalized. There are several ways to - -- initialize it: by decreasing order of precedence: - -- - -- * explicitly set through a -X option; - -- * set through an environment variable; - -- * implicitly initialized by GNATcoverage. - - if S_Variables.Contains ("GPR_TOOL") then - null; + -- Look for a view in the project tree whose name matches the request - else - declare - GPR_Tool_Env_Var : GNAT.Strings.String_Access := - GNAT.OS_Lib.Getenv ("GPR_TOOL"); - GPR_Tool_Value : constant String := - (if GPR_Tool_Env_Var.all = "" - then "gnatcoverage" - else GPR_Tool_Env_Var.all); - begin - Change_Environment (Env.all, "GPR_TOOL", GPR_Tool_Value); - Free (GPR_Tool_Env_Var); - end; - end if; - end Initialize; - - -------------------- - -- Lookup_Project -- - -------------------- - - function Lookup_Project (Prj_Name : String) return Project_Type is - Prj_Name_FS : constant GNATCOLL.VFS.Filesystem_String := - +Simple_Name (Prj_Name); - Last : Integer; - begin - -- Strip optional Project_File_Extension + for P of Prj_Tree loop + if To_Lower (String (P.Name)) = Name then + Result := P; + exit; + end if; + end loop; + end; - if Prj_Name_FS'Length >= Project_File_Extension'Length - and then - Prj_Name_FS (Prj_Name_FS'Last - Project_File_Extension'Length + 1 - .. Prj_Name_FS'Last) = Project_File_Extension - then - Last := Prj_Name_FS'Last - Project_File_Extension'Length; + if Result.Is_Defined then + return Result; else - Last := Prj_Name_FS'Last; + Fatal_Error ("project " & Prj_Name & " not found"); end if; - - -- Look up project from project tree - - return Result : constant Project_Type := Prj_Tree.Project_From_Name - (+Prj_Name_FS (Prj_Name_FS'First .. Last)) - do - if Result = No_Project then - Fatal_Error ("project " & Prj_Name & " not found"); - end if; - end return; end Lookup_Project; ------------------- @@ -793,14 +766,14 @@ package body Project is procedure Build_Prj_Map is - procedure Process_Project (Project : Project_Type); + procedure Process_Project (Project : GPR2.Project.View.Object); -- Callback for Iterate_Projects: add an entry in Prj_Map for Project --------------------- -- Process_Project -- --------------------- - procedure Process_Project (Project : Project_Type) is + procedure Process_Project (Project : GPR2.Project.View.Object) is use Project_Maps; Success : Boolean; @@ -812,14 +785,14 @@ package body Project is -- have a unique name, though: check this. Prj_Map.Insert - (Project.Name, + (String (Project.Name), (Project => Project, others => False), Cur, Success); if not Success and then Prj_Map.Reference (Cur).Project /= Project then raise Program_Error with - "homonym projects detected: " & Project.Name; + "homonym projects detected: " & String (Project.Name); end if; end Process_Project; @@ -832,13 +805,13 @@ package body Project is if Requested_Projects.Is_Empty then declare - Origin_Prj : constant String := - Prj_Tree.Root_Project.Attribute_Value - (Origin_Project_Attribute); - Prj_Name : constant String := - (if Origin_Prj = "" - then Prj_Tree.Root_Project.Name - else Origin_Prj); + Origin_Attr : constant GPR2.Project.Attribute.Object := + Prj_Tree.Root_Project.Attribute + (GPR2.Project.Registry.Attribute.Origin_Project); + Prj_Name : constant String := + (if Origin_Attr.Is_Defined + then Origin_Attr.Value.Text + else String (Prj_Tree.Root_Project.Name)); begin Requested_Projects.Insert (Prj_Name); end; @@ -846,7 +819,7 @@ package body Project is for Prj_Name of Requested_Projects loop Iterate_Projects - (Lookup_Project (Prj_Name), + (Most_Extending (Lookup_Project (Prj_Name)), Process_Project'Access, Standard.Switches.Recursive_Projects); end loop; @@ -868,7 +841,7 @@ package body Project is Has_Matcher : Boolean; -- Matcher for the list of units of interest - procedure Process_Project (Project : Project_Type); + procedure Process_Project (Project : GPR2.Project.View.Object); -- Compute the list of units of interest in Project and call -- Enumerate_In_Single_Projects for Project. @@ -876,7 +849,7 @@ package body Project is -- Process_Project -- --------------------- - procedure Process_Project (Project : Project_Type) is + procedure Process_Project (Project : GPR2.Project.View.Object) is Inc_Units : Unit_Maps.Map; Inc_Units_Defined : Boolean := False; -- Units to be included, as specified in project @@ -925,7 +898,7 @@ package body Project is if not Inc_Units_Defined then declare procedure Process_Source_File - (Info : File_Info; Unit_Name : String); + (Source : GPR2.Build.Source.Object; Unit_Name : String); -- Add Unit_Name to Inc_Units ------------------------- @@ -933,20 +906,16 @@ package body Project is ------------------------- procedure Process_Source_File - (Info : File_Info; Unit_Name : String) + (Source : GPR2.Build.Source.Object; Unit_Name : String) is - Cur : Unit_Maps.Cursor; - Actual_Unit_Name : constant String := - (if Info.Unit_Part = Unit_Separate - then Owning_Unit_Name (Info) - else Unit_Name); + Cur : Unit_Maps.Cursor; begin -- Never try to perform coverage on our coverage runtime -- library (in one of the gnatcov_rts*.gpr projects) or on -- our coverage buffer units (in user projects). - if Strings.Has_Prefix (Actual_Unit_Name, "gnatcov_rts.") - or else Strings.Has_Prefix (Actual_Unit_Name, "gcvrt") + if Strings.Has_Prefix (Unit_Name, "gnatcov_rts.") + or else Strings.Has_Prefix (Unit_Name, "gcvrt") then return; end if; @@ -954,15 +923,15 @@ package body Project is if not Units_Specified or else (Has_Matcher and then GNAT.Regexp.Match - (To_Lower (Actual_Unit_Name), + (To_Lower (Unit_Name), Units_Specified_Matcher)) then Add_Unit (Inc_Units, Cur, Unit_Name, - Info, - To_Language (Info.Language)); + Source, + To_Language (Source.Language)); end if; end Process_Source_File; @@ -999,7 +968,7 @@ package body Project is -- Compute whether this project contributes to the selection of units -- of interest. - Prj_Map.Reference (Project.Name).Has_Units_Of_Interest := + Prj_Map.Reference (String (Project.Name)).Has_Units_Of_Interest := (Has_One_Unit_Of_Interest or else (not Units_Specified and then Has_Unit_Selection_Attributes)); @@ -1086,7 +1055,7 @@ package body Project is if not Standard.Switches.Recursive_Projects then for Prj_Info of Prj_Map loop if not Prj_Info.Has_Units_Of_Interest then - Warn ("project " & Prj_Info.Project.Name + Warn ("project " & String (Prj_Info.Project.Name) & " provides no unit of interest"); end if; end loop; @@ -1098,41 +1067,39 @@ package body Project is ----------------------- procedure List_From_Project - (Prj : Project_Type; + (Prj : GPR2.Project.View.Object; List_Attr : List_Attribute; List_File_Attr : String_Attribute; Process_Item : access procedure (Attr, Item : String); Defined : out Boolean) is - LA : constant Attribute_Pkg_List := +List_Attr; - LFA : constant Attribute_Pkg_String := +List_File_Attr; + LA : constant GPR2.Q_Attribute_Id := +List_Attr; + LFA : constant GPR2.Q_Attribute_Id := +List_File_Attr; + + A : GPR2.Project.Attribute.Object; begin -- We check each attribute in sequence and the set we're filling -- is "defined" as soon as one is set explicitly. Defined := False; - if Has_Attribute (Prj, LA) then + A := Prj.Attribute (LA); + if A.Is_Defined then Defined := True; declare - Attr : constant String := +List_Attr; - List_Attr_Value : String_List_Access := - Attribute_Value (Prj, LA); + Attr : constant String := +List_Attr; begin - for J in List_Attr_Value'Range loop - Process_Item (Attr, List_Attr_Value (J).all); - Free (List_Attr_Value (J)); + for Value of A.Values loop + Process_Item (Attr, Value.Text); end loop; - Free (List_Attr_Value); end; end if; - if Has_Attribute (Prj, LFA) then + A := Prj.Attribute (LFA); + if A.Is_Defined then Defined := True; declare - Attr : constant String := +List_File_Attr; - List_File_Attr_Value : constant String := - Attribute_Value (Prj, LFA); + Attr : constant String := +List_File_Attr; procedure Process_Item_Wrapper (Item : String); -- Wrapper around Process_Item for each file item @@ -1150,8 +1117,8 @@ package body Project is Read_List_From_File (+Full_Name (Create_From_Base - (Base_Name => +List_File_Attr_Value, - Base_Dir => Dir_Name (Project_Path (Prj)))), + (Base_Name => +A.Value.Text, + Base_Dir => +String (Prj.Dir_Name.Value))), Process_Item_Wrapper'Access); end; end if; @@ -1162,7 +1129,7 @@ package body Project is ------------------------ procedure Units_From_Project - (Prj : Project_Type; + (Prj : GPR2.Project.View.Object; List_Attr : List_Attribute; List_File_Attr : String_Attribute; Units : out Unit_Maps.Map; @@ -1182,7 +1149,8 @@ package body Project is -- Add Item to Unit_Patterns. Also save from which project attribute -- (Attr) the pattern comes from in Attr_For_Pattern. - procedure Process_Source_File (Info : File_Info; Unit_Name : String); + procedure Process_Source_File + (Source : GPR2.Build.Source.Object; Unit_Name : String); -- Add Unit_Name to Units_Present ----------------- @@ -1199,15 +1167,11 @@ package body Project is -- Process_Source_File -- ------------------------- - procedure Process_Source_File (Info : File_Info; Unit_Name : String) is - use type Ada.Containers.Count_Type; - use String_Vectors; - Actual_Unit_Name : Vector := - To_Vector - (+(if Info.Unit_Part = Unit_Separate - then Owning_Unit_Name (Info) - else Unit_Name), - 1); + procedure Process_Source_File + (Source : GPR2.Build.Source.Object; Unit_Name : String) + is + Actual_Unit_Name : String_Vectors.Vector := + String_Vectors.To_Vector (+Get_Unit_Name (Source), 1); begin Match_Pattern_List (Patterns_List => Unit_Patterns, @@ -1218,14 +1182,9 @@ package body Project is if not Actual_Unit_Name.Is_Empty then declare - Lang : constant Some_Language := To_Language (Info.Language); + Lang : constant Some_Language := To_Language (Source.Language); begin - Add_Unit - (Units, - Cur, - Unit_Name, - Info, - Lang); + Add_Unit (Units, Cur, Unit_Name, Source, Lang); end; end if; end Process_Source_File; @@ -1253,8 +1212,9 @@ package body Project is (Prj, Process_Source_File'Access, Recursive => False); for Pattern of Patterns_Not_Covered loop - Warn ("no unit " & (+Pattern) & " in project " & Prj.Name & " (" - & (+Attr_For_Pattern.Element (Pattern)) & " attribute)"); + Warn + ("no unit " & (+Pattern) & " in project " & String (Prj.Name) + & " (" & (+Attr_For_Pattern.Element (Pattern)) & " attribute)"); end loop; end Units_From_Project; @@ -1268,8 +1228,9 @@ package body Project is DB_Dir : String; From_Driver : Boolean := False) is + Opts : GPR2.Options.Object; begin - if Prj_Tree /= null then + if Prj_Tree.Is_Defined then Fatal_Error ("only one root project can be specified"); end if; @@ -1278,56 +1239,80 @@ package body Project is GNATCOLL.Traces.Parse_Config_File (Filename => No_File); - pragma Assert (Env = null); - Initialize (Target, Runtime, CGPR_File); - pragma Assert (Env /= null); - - -- Include the additional knowledge base - + Opts.Add_Switch (GPR2.Options.P, Prj_Name); + if Target /= null then + Opts.Add_Switch (GPR2.Options.Target, Target.all); + end if; + if Runtime /= null then + Opts.Add_Switch (GPR2.Options.RTS, Runtime.all); + end if; + if CGPR_File /= null then + Opts.Add_Switch (GPR2.Options.Config, CGPR_File.all); + end if; if DB_Dir /= "" then - Env.Add_Config_Dir (Create (+DB_Dir)); + Opts.Add_Switch (GPR2.Options.Db, DB_Dir); end if; - if Obj_Subdir /= "" then - Env.Set_Object_Subdir (+(+Obj_Subdir)); + Opts.Add_Switch (GPR2.Options.Subdirs, +Obj_Subdir); end if; - if Build_Tree_Dir /= No_File then - Env.Set_Build_Tree_Dir (Build_Tree_Dir.Full_Name); + Opts.Add_Switch + (GPR2.Options.Relocate_Build_Tree, +Build_Tree_Dir.Full_Name); -- When the build tree directory is set, the root directory may be -- specified explicitly from the command line. Otherwise, the project -- file directory is used. if Root_Dir /= No_File then - Env.Set_Root_Dir (Root_Dir.Full_Name); + Opts.Add_Switch (GPR2.Options.Root_Dir, +Root_Dir.Full_Name); end if; end if; - Prj_Tree := new Project_Tree; - begin - Prj_Tree.Load - (Root_Project_Path => Create (+Prj_Name), - Env => Env, - Packages_To_Check => Coverage_Package_List'Access, - Errors => Outputs.Warning_Or_Error'Access, - Report_Missing_Dirs => False); - exception - when Invalid_Project => - Free (Prj_Tree); - Fatal_Error ("Could not load the project file, aborting."); - end; + for Scv_C in S_Variables.Iterate loop + Opts.Add_Switch + (GPR2.Options.X, + Key_Element_Maps.Key (Scv_C) + & "=" + & Key_Element_Maps.Element (Scv_C)); + end loop; - if Obj_Subdir /= "" then - Env.Set_Object_Subdir (+(+Obj_Subdir)); + -- Make sure GPR_TOOL is initalized. There are several ways to + -- initialize it: by decreasing order of precedence: + -- + -- * explicitly set through a -X option; + -- * set through an environment variable; + -- * implicitly initialized by GNATcoverage. + + if S_Variables.Contains ("GPR_TOOL") then + null; + else + declare + GPR_Tool_Env_Var : GNAT.Strings.String_Access := + GNAT.OS_Lib.Getenv ("GPR_TOOL"); + GPR_Tool_Value : constant String := + (if GPR_Tool_Env_Var.all = "" + then "gnatcoverage" + else GPR_Tool_Env_Var.all); + begin + Opts.Add_Switch (GPR2.Options.X, "GPR_TOOL=" & GPR_Tool_Value); + Free (GPR_Tool_Env_Var); + end; + end if; + + if not Prj_Tree.Load + (Opts, + With_Runtime => True, + Reporter => Create_Reporter, + Artifacts_Info_Level => GPR2.Sources_Units, + Absent_Dir_Error => GPR2.No_Error) + then + Fatal_Error ("Could not load the project file, aborting."); end if; -- We do not support non-library aggregate projects, no need to go -- further. - if Prj_Tree.Root_Project.Is_Aggregate_Project and then - not Prj_Tree.Root_Project.Is_Aggregate_Library - then + if Prj_Tree.Root_Project.Kind = GPR2.K_Aggregate then Fatal_Error ("non-library aggregate projects are not supported"); end if; @@ -1339,7 +1324,7 @@ package body Project is end if; if not Externally_Built_Projects_Processing_Enabled - and then Prj_Tree.Root_Project.Externally_Built + and then Prj_Tree.Root_Project.Is_Externally_Built then Fatal_Error ("Root project is marked as externally built, while externally" @@ -1365,7 +1350,7 @@ package body Project is function Is_Project_Loaded return Boolean is begin - return Prj_Tree /= null; + return Prj_Tree.Is_Defined; end Is_Project_Loaded; ------------------------------ @@ -1383,7 +1368,7 @@ package body Project is function Root_Project_Filename return String is begin - return +Prj_Tree.Root_Project.Project_Path.Full_Name; + return String (Prj_Tree.Root_Project.Path_Name.Value); end Root_Project_Filename; -------------------------------- @@ -1391,25 +1376,12 @@ package body Project is -------------------------------- function Get_Single_Main_Executable return String is - Mains : constant Main_Source_File_Array := - Enumerate_Mains - (GNATCOLL.Projects.Root_Project (Prj_Tree.all), All_Languages); + Execs : constant GPR2.Path_Name.Set.Object := + Prj_Tree.Root_Project.Executables; begin - if Mains'Length /= 1 then - return ""; - end if; - - declare - M : Main_Source_File renames Mains (Mains'First); - Exec_Name : constant Filesystem_String := M.Project.Executable_Name - (File => M.File.Base_Name, Include_Suffix => True); - Exec_Dir : constant Virtual_File := - M.Project.Executables_Directory; - Result : constant Virtual_File := - Create_From_Dir (Exec_Dir, Exec_Name); - begin - return +Full_Name (Result); - end; + return (if Execs.Length = 1 + then String (Execs.First_Element.Value) + else ""); end Get_Single_Main_Executable; --------------------- @@ -1417,46 +1389,30 @@ package body Project is --------------------- function Enumerate_Mains - (Root_Project : Project_Type; - Language : Any_Language) return Main_Source_File_Array + (Root_Project : GPR2.Project.View.Object; + Language : Any_Language) + return GPR2.Build.Compilation_Unit.Unit_Location_Vector is - Lower_Language : constant String := - (case Language is - when All_Languages => "", - when Ada_Language => "ada", - when C_Language => "c", - when CPP_Language => "c++"); + Result : GPR2.Build.Compilation_Unit.Unit_Location_Vector; - package Main_Source_File_Vectors is new Ada.Containers.Vectors - (Positive, Main_Source_File); - Mains : Main_Source_File_Vectors.Vector; - - procedure Enumerate_Mains (Project : Project_Type); - -- Append to Mains the list of main source files found in Project + procedure Enumerate_Mains (Project : GPR2.Project.View.Object); + -- Append the list of main source files found in Project to Result --------------------- -- Enumerate_Mains -- --------------------- - procedure Enumerate_Mains (Project : Project_Type) is - Src_Files : File_Array_Access := - Project.Extended_Projects_Source_Files; + procedure Enumerate_Mains (Project : GPR2.Project.View.Object) is begin - for F of Src_Files.all loop - declare - Name : constant Filesystem_String := Base_Name (F); - begin - if Project.Is_Main_File (Name) - and then (Language = All_Languages - or else To_Lower (Prj_Tree.Info (F).Language) - = Lower_Language) - then - Mains.Append - (Main_Source_File'(File => F, Project => Project)); - end if; - end; + for Main of Project.Mains loop + if Language = All_Languages + or else Language + = To_Language_Or_All + (Project.Source (Main.Source.Simple_Name).Language) + then + Result.Append (Main); + end if; end loop; - Unchecked_Free (Src_Files); end Enumerate_Mains; -- Start of processing for Enumerate_Mains @@ -1464,18 +1420,12 @@ package body Project is begin Iterate_Projects (Root_Project, Enumerate_Mains'Access, Recursive => False); - return Result : Main_Source_File_Array (Mains.First_Index - .. Mains.Last_Index) - do - for I in Result'Range loop - Result (I) := Mains.Element (I); - end loop; - end return; + return Result; end Enumerate_Mains; function Enumerate_Mains - (Language : Any_Language) return Main_Source_File_Array - is + (Language : Any_Language) + return GPR2.Build.Compilation_Unit.Unit_Location_Vector is begin return Enumerate_Mains (Prj_Tree.Root_Project, Language); end Enumerate_Mains; @@ -1486,7 +1436,7 @@ package body Project is function Output_Dir return String is begin - return +Prj_Tree.Root_Project.Object_Dir.Full_Name; + return String (Prj_Tree.Root_Project.Object_Directory.Value); end Output_Dir; -------------- @@ -1494,22 +1444,23 @@ package body Project is -------------- function Switches (Op : String) return String_Vectors.Vector is - Origin_Prj : constant String := - Prj_Tree.Root_Project.Attribute_Value (Origin_Project_Attribute); - Actual_Prj : constant Project_Type := - (if Origin_Prj = "" - then Prj_Tree.Root_Project - else Lookup_Project (Origin_Prj)); - Raw_Result : String_List_Access; + Origin_Attr : constant GPR2.Project.Attribute.Object := + Prj_Tree.Root_Project.Attribute + (GPR2.Project.Registry.Attribute.Origin_Project); + Actual_Prj : constant GPR2.Project.View.Object := + (if Origin_Attr.Is_Defined + then Most_Extending (Lookup_Project (Origin_Attr.Value.Text)) + else Prj_Tree.Root_Project); + Attr : GPR2.Project.Attribute.Object; begin return Result : String_Vectors.Vector do - Raw_Result := Attribute_Value - (Actual_Prj, +Switches, Index => Op); - if Raw_Result /= null then - for S of Raw_Result.all loop - Result.Append (+S.all); + Attr := Actual_Prj.Attribute + (Name => +Switches, + Index => GPR2.Project.Attribute_Index.Create (Op)); + if Attr.Is_Defined then + for S of Attr.Values loop + Result.Append (+String (S.Text)); end loop; - Free (Raw_Result); end if; end return; end Switches; @@ -1521,14 +1472,6 @@ package body Project is procedure Set_Subdirs (Subdir : String) is begin Obj_Subdir := +Subdir; - - -- The --subdirs switch is relevant only if projects are used, otherwise - -- it can safely be ignored. If projects are not loaded yet, the - -- subdirectory will be used anyway thanks to Obj_Subdir. - - if Env /= null then - Env.Set_Object_Subdir (+Subdir); - end if; end Set_Subdirs; ------------------------------------------------- @@ -1548,11 +1491,6 @@ package body Project is begin Build_Tree_Dir := Get_Current_Dir; Build_Tree_Dir.Normalize_Path; - - if Env /= null then - Env.Set_Build_Tree_Dir - (Build_Tree_Dir.Full_Name); - end if; end Set_Build_Tree_Dir_To_Current; ------------------ @@ -1563,30 +1501,39 @@ package body Project is begin Root_Dir := Create (+Dir); Root_Dir.Normalize_Path; - - if Env /= null then - Env.Set_Root_Dir (Root_Dir.Full_Name); - end if; end Set_Root_Dir; ------------------ -- Project_Name -- ------------------ - function Project_Name (Source_Name : String) return String is - F_Info : constant File_Info := Prj_Tree.Info (Create (+Source_Name)); - Prj : constant Project_Type := F_Info.Project; + function Project_Name (Full_Name : String) return String is + Source : constant GPR2.Build.Source.Object := Lookup_Source (Full_Name); begin - return (if Prj /= No_Project then Prj.Name else ""); + return (if Source.Is_Defined + then String (Source.Owning_View.Name) + else ""); end Project_Name; + -------------- + -- Language -- + -------------- + + function Language (Full_Name : String) return Any_Language is + Source : constant GPR2.Build.Source.Object := Lookup_Source (Full_Name); + begin + return (if Source.Is_Defined + then To_Language_Or_All (Source.Language) + else All_Languages); + end Language; + ------------ -- Target -- ------------ function Target return String is begin - return Get_Target (Prj_Tree.Root_Project); + return String (Prj_Tree.Target); end Target; ------------- @@ -1595,7 +1542,20 @@ package body Project is function Runtime return String is begin - return Get_Runtime (Prj_Tree.Root_Project); + -- gnatcov is able to request only one runtime for all languages + -- (--RTS: is not available), so looking for the first language + -- that has a runtime should be fine. + + for L of Prj_Tree.Languages loop + declare + Result : constant String := String (Prj_Tree.Runtime (L)); + begin + if Result /= "" then + return Result; + end if; + end; + end loop; + return ""; end Runtime; ------------------------------------ @@ -1605,7 +1565,7 @@ package body Project is procedure Enumerate_Ignored_Source_Files (Process : access procedure (Source_File : String)) is - procedure Enumerate (Prj : Project_Type); + procedure Enumerate (Prj : GPR2.Project.View.Object); -- Call Process on all ignored source files referenced by the -- Ignored_Source_Files(_List) project attributes. @@ -1618,7 +1578,7 @@ package body Project is -- Enumerate -- --------------- - procedure Enumerate (Prj : Project_Type) is + procedure Enumerate (Prj : GPR2.Project.View.Object) is begin List_From_Project (Prj, @@ -1655,31 +1615,22 @@ package body Project is function Runtime_Dirs return String_Vectors.Vector is - Result : String_Vectors.Vector; + Runtime : constant GPR2.Project.View.Object := Prj_Tree.Runtime_Project; begin - for Dir of Project.Root_Project.Get_Environment.Predefined_Source_Path - loop - Result.Append (+(+Dir.Full_Name)); - end loop; - return Result; + return Result : String_Vectors.Vector do + if Runtime.Is_Defined then + for Dir of Prj_Tree.Runtime_Project.Source_Directories loop + Result.Append (+String (Dir.Value)); + end loop; + end if; + end return; end Runtime_Dirs; - -------------- - -- Finalize -- - -------------- - - procedure Finalize is - begin - if Prj_Tree /= null and then not Save_Temps then - GNATCOLL.Projects.Aux.Delete_All_Temp_Files (Prj_Tree.Root_Project); - end if; - end Finalize; - ------------- -- Project -- ------------- - function Project return GNATCOLL.Projects.Project_Tree_Access is + function Project return GPR2.Project.Tree.Object is begin return Prj_Tree; end Project; @@ -1690,42 +1641,145 @@ package body Project is function Source_Suffix (Lang : Src_Supported_Language; - Part : GNATCOLL.Projects.Unit_Parts; - Project : GNATCOLL.Projects.Project_Type) return String + Part : GPR2.Valid_Unit_Kind; + Project : GPR2.Project.View.Object) return String is - Attr : constant Attribute_Pkg_String := - Build - (Package_Name => "Naming", - Attribute_Name => - (case Part is - when Unit_Body => "Body_Suffix", - when Unit_Spec => "Spec_Suffix", - when Unit_Separate => raise Program_Error)); + L : constant GPR2.Language_Id := To_Language_Id (Lang); begin + -- ??? Simplify once eng/gpr/gpr-issues#494 is implemented + case Part is - when Unit_Body => - return Project.Attribute_Value - (Attribute => Attr, - Index => Image (Lang), - Default => (case Lang is - when Ada_Language => ".adb", - when C_Language => ".c", - when CPP_Language => ".cc")); - - when Unit_Spec => - return Project.Attribute_Value - (Attribute => Attr, - Index => Image (Lang), - Default => (case Lang is - when Ada_Language => ".ads", - when C_Language => ".h", - when CPP_Language => ".hh")); - - when Unit_Separate => - return (raise Program_Error); + when GPR2.S_Spec => + return Project.Spec_Suffix (L).Value.Text; + + when GPR2.S_Body => + return Project.Body_Suffix (L).Value.Text; + + when GPR2.S_Separate => + return Project.Separate_Suffix.Value.Text; end case; end Source_Suffix; + ------------------- + -- Lookup_Source -- + ------------------- + + function Lookup_Source + (Full_Name : String) return GPR2.Build.Source.Object + is + Basename : constant GPR2.Simple_Name := + GPR2.Simple_Name (Simple_Name (Full_Name)); + Resolved : constant GPR2.Path_Name.Object := + GPR2.Path_Name.Create_File (GPR2.Filename_Type (Full_Name)); + begin + for P of Prj_Tree.Root_Project.Closure (Include_Self => True) loop + declare + Source : constant GPR2.Build.Source.Object := P.Source (Basename); + begin + if Source.Is_Defined and then Source.Path_Name = Resolved then + return Source; + end if; + end; + end loop; + + return GPR2.Build.Source.Undefined; + end Lookup_Source; + + --------------- + -- Verbosity -- + --------------- + + overriding function Verbosity + (Self : Reporter) return GPR2.Reporter.Verbosity_Level is + begin + return Self.Inner.Verbosity; + end Verbosity; + + --------------------- + -- Internal_Report -- + --------------------- + + overriding procedure Internal_Report + (Self : in out Reporter; Message : GPR2.Message.Object) is + begin + if Message.Level in GPR2.Message.Warning | GPR2.Message.Error then + Register_Warning; + end if; + Self.Inner.Internal_Report (Message); + end Internal_Report; + + --------------------- + -- Create_Reporter -- + --------------------- + + function Create_Reporter return GPR2.Reporter.Object'Class is + Result : constant Reporter := + (GPR2.Reporter.Object with + Inner => GPR2.Reporter.Console.Create); + begin + return Result; + end Create_Reporter; + + -------------------- + -- Most_Extending -- + -------------------- + + function Most_Extending + (View : GPR2.Project.View.Object) return GPR2.Project.View.Object + is + Result : GPR2.Project.View.Object := View; + begin + while Result.Is_Extended loop + Result := Result.Extending; + end loop; + return Result; + end Most_Extending; + + -------------------- + -- Source_Closure -- + -------------------- + + function Source_Closure + (View : GPR2.Project.View.Object; + With_Externally_Built : Boolean; + With_Runtime : Boolean) return Source_Vectors.Vector + is + Result : Source_Vectors.Vector; + -- List of sources found so far + begin + for Source of View.Visible_Sources loop + declare + View : constant GPR2.Project.View.Object := Source.Owning_View; + begin + -- If we were asked to include this view in the closure, add its + -- sources to Result. Note also that we need to ignore extended + -- projects: only the sources of the corresponding extending + -- project matter. + + if not View.Is_Extended + and then (With_Externally_Built + or else not View.Is_Externally_Built) + and then (With_Runtime or else not View.Is_Runtime) + then + Result.Append (Source); + end if; + end; + end loop; + return Result; + end Source_Closure; + + ---------------- + -- First_Unit -- + ---------------- + + function First_Unit + (Source : GPR2.Build.Source.Object) return GPR2.Build.Unit_Info.Object is + begin + return (if Source.Has_Single_Unit + then Source.Unit + else Source.Unit (Index => 1)); + end First_Unit; + -- Register the Coverage package and its attributes to GPR2 package GPR2_RP renames GPR2.Project.Registry.Pack; diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index c813028a5..244ab4252 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -19,11 +19,16 @@ -- GNAT projects support with Ada.Characters.Handling; use Ada.Characters.Handling; +with Ada.Containers.Vectors; with GNAT.Strings; use GNAT.Strings; -with GNATCOLL.Projects; use GNATCOLL.Projects; -with GNATCOLL.VFS; +with GPR2.Build.Compilation_Unit; +with GPR2.Build.Source; +with GPR2.Build.Unit_Info; +with GPR2.Project.Tree; +with GPR2.Project.View; +with GPR2.Reporter; with Files_Table; with Strings; use Strings; @@ -46,10 +51,6 @@ package Project is -- Return whether the set of units of interest has been computed by calling -- the Compute_Units_Of_Interest procedure. - procedure Finalize; - -- Release all resources allocated by project handling. Must be called - -- before leaving gnatcov. - ------------------------------- -- Pre-loading configuration -- ------------------------------- @@ -88,9 +89,7 @@ package Project is Target, Runtime, CGPR_File : GNAT.Strings.String_Access; DB_Dir : String; From_Driver : Boolean := False) - with Pre => not Is_Project_Loaded - and then ((Target = null and then Runtime = null) - or else CGPR_File = null), + with Pre => not Is_Project_Loaded, Post => Is_Project_Loaded; -- Load the project tree rooted at Prj_Name (with optional -- Project_File_Extension). Target is the target prefix, or NULL in the @@ -99,9 +98,6 @@ package Project is -- if any. DB_Dir is the path to the additional knowledge base directory, -- if any. -- - -- Note that Target/Runtime must not be provided if a configuration project - -- file is provided, and reciprocally. - -- -- If From_Driver is True, do not compute the list of projects/units of -- interest. This is meant to be used only in the gnatcov driver, where we -- just need to determine the target. @@ -129,13 +125,13 @@ package Project is -- path of its main executable (including its suffix, for instance ".exe"). -- Otherwise, return an empty string. - function Owning_Unit_Name (Info : File_Info) return String - with Pre => Is_Project_Loaded; - -- Return the owning unit name meaning the unit name if this is a body / - -- specification, and the top parent unit name if this is a separate. + function Get_Unit_Name (Source : GPR2.Build.Source.Object) return String; + -- Return the gnatcov-style unit name for the given source. For Ada, it is + -- the actual unit name (same meaning as in GPR2), but for other languages, + -- it is the file basename. function To_Compilation_Unit - (Info : File_Info) return Files_Table.Compilation_Unit; + (Source : GPR2.Build.Source.Object) return Files_Table.Compilation_Unit; -- Return the Compilation_Unit for Info -------------------------------------- @@ -156,8 +152,8 @@ package Project is procedure Enumerate_Sources (Callback : access procedure - (Project : GNATCOLL.Projects.Project_Type; - File : GNATCOLL.Projects.File_Info); + (Project : GPR2.Project.View.Object; + File : GPR2.Build.Source.Object); Language : Any_Language; Only_UOIs : Boolean := False) with Pre => Is_Project_Loaded; @@ -166,19 +162,9 @@ package Project is -- only call Callback on sources that are units of interest. Override_Units -- has the same semantics as in Enumerate_LIs. - type Main_Source_File is record - File : GNATCOLL.VFS.Virtual_File; - -- Base name for the source file - - Project : GNATCOLL.Projects.Project_Type; - -- The project this source files comes from - end record; - - type Main_Source_File_Array is - array (Positive range <>) of Main_Source_File; - function Enumerate_Mains - (Language : Any_Language) return Main_Source_File_Array + (Language : Any_Language) + return GPR2.Build.Compilation_Unit.Unit_Location_Vector with Pre => Is_Project_Loaded; -- Return the list of all main source files found in the project tree for -- the given Language, or for all languages if Language is All_Languages. @@ -202,12 +188,17 @@ package Project is with Pre => Is_Project_Loaded; -- Return the output directory of the root project - function Project_Name (Source_Name : String) return String + function Project_Name (Full_Name : String) return String with Pre => Is_Project_Loaded; -- Return the name of the project containing the given source file. Return -- the empty string if Source_Name cannot be associated with a project -- name. This can happen for sources that belong eg. to the runtime. + function Language (Full_Name : String) return Any_Language + with Pre => Is_Project_Loaded; + -- Return the language for the given source file, or All_Languages if the + -- file is unknown. + function Target return String with Pre => Is_Project_Loaded; -- Return the target in the root project, if any, and the empty string @@ -230,13 +221,13 @@ package Project is -- Raw accessors for the project tree -- ---------------------------------------- - function Project return GNATCOLL.Projects.Project_Tree_Access + function Project return GPR2.Project.Tree.Object with Pre => Is_Project_Loaded; procedure Iterate_Projects - (Root_Project : GNATCOLL.Projects.Project_Type; + (Root_Project : GPR2.Project.View.Object; Process : access procedure - (Prj : GNATCOLL.Projects.Project_Type); + (Prj : GPR2.Project.View.Object); Recursive : Boolean; Include_Extended : Boolean := False; Include_Externally_Built : Boolean := @@ -251,8 +242,48 @@ package Project is function Source_Suffix (Lang : Src_Supported_Language; - Part : GNATCOLL.Projects.Unit_Parts; - Project : GNATCOLL.Projects.Project_Type) return String; + Part : GPR2.Valid_Unit_Kind; + Project : GPR2.Project.View.Object) return String; -- Return the filename suffix corresponding for Part files and Lang + function Lookup_Source + (Full_Name : String) return GPR2.Build.Source.Object; + -- Look for a source file by full name in the loaded project tree + + ------------------- + -- GPR2 reporter -- + ------------------- + + function Create_Reporter return GPR2.Reporter.Object'Class; + -- Returns a wrapper around GPR2.Reporter.Console so that we detect when + -- warnings are emitted, allowing us to implement --warning-as-errors. + + --------------------- + -- GPR2 extensions -- + --------------------- + + function Most_Extending + (View : GPR2.Project.View.Object) return GPR2.Project.View.Object; + -- If View is an extended project, return Most_Extending (View.Extending). + -- Return View itself otherwise. + -- + -- ??? Remove once eng/gpr/gpr-issues#501 is implemented. + + package Source_Vectors is new Ada.Containers.Vectors + (Positive, GPR2.Build.Source.Object, "=" => GPR2.Build.Source."="); + + function Source_Closure + (View : GPR2.Project.View.Object; + With_Externally_Built : Boolean; + With_Runtime : Boolean) return Source_Vectors.Vector; + -- Return the set of all sources in the closure of View (its own sources + -- included). Include sources from externally built projects iff + -- With_Externally_Built is True, include sources from the runtime iff + -- With_Runtime is True. + + function First_Unit + (Source : GPR2.Build.Source.Object) return GPR2.Build.Unit_Info.Object; + -- Assuming that Source has a unit-based language, return the first unit it + -- contains. + end Project; diff --git a/tools/gnatcov/rundrv-handlers.adb b/tools/gnatcov/rundrv-handlers.adb index 499c5c559..765aedda8 100644 --- a/tools/gnatcov/rundrv-handlers.adb +++ b/tools/gnatcov/rundrv-handlers.adb @@ -22,8 +22,6 @@ with Ada.Directories; use Ada.Directories; with Ada.Strings; use Ada.Strings; with Ada.Strings.Fixed; use Ada.Strings.Fixed; -with GNATCOLL.VFS; use GNATCOLL.VFS; - with Arch; with Coverage; use Coverage; with Paths; use Paths; @@ -250,7 +248,7 @@ package body Rundrv.Handlers is if Project.Is_Project_Loaded then Append_Arg - (Cmd, "-P", +Project.Project.Root_Project.Project_Path.Full_Name); + (Cmd, "-P", String (Project.Project.Root_Project.Path_Name.Value)); declare use Key_Element_Maps; diff --git a/tools/gnatcov/ss_annotations.adb b/tools/gnatcov/ss_annotations.adb index 015a1a57c..e55db643f 100644 --- a/tools/gnatcov/ss_annotations.adb +++ b/tools/gnatcov/ss_annotations.adb @@ -23,8 +23,9 @@ with Ada.Text_IO; with Interfaces; use Interfaces; -with GNATCOLL.Projects; with GNATCOLL.VFS; use GNATCOLL.VFS; +with GPR2.Build.Source; +with GPR2.Project.View; with TOML; @@ -772,7 +773,7 @@ package body SS_Annotations is Annotation : constant TOML_Value := Create_Table; SS_Backend : Unbounded_String := +Opt_SS_Backend; File_Prefix : Unbounded_String := +Opt_Source_Root; - Info : GNATCOLL.Projects.File_Info; + Source : GPR2.Build.Source.Object; begin -- First, determine the kind of annotation we'll be generating @@ -798,7 +799,12 @@ package body SS_Annotations is Target_File := Create (+(+Args.Remaining_Args.Last_Element)); if Is_Project_Loaded then - Info := Project.Project.Info (Target_File); + Source := Project.Lookup_Source (+Target_File.Full_Name); + if not Source.Is_Defined then + Fatal_Error + (Target_File.Display_Full_Name + & ": no such file in the project"); + end if; end if; if not Target_File.Is_Regular_File then @@ -916,7 +922,7 @@ package body SS_Annotations is -- If we have a project loaded, use it to determine the file language if Is_Project_Loaded then - Language := To_Language_Or_All (Info.Language); + Language := To_Language_Or_All (Source.Language); end if; -- If this failed or we have no project at hand, revert to simple @@ -941,7 +947,7 @@ package body SS_Annotations is -- have a project at hand. if US.Length (File_Prefix) = 0 and then Is_Project_Loaded then - case To_Language_Or_All (Info.Language) is + case To_Language_Or_All (Source.Language) is when Ada_Language => -- Ada source files are guaranteed to be unique in a project, @@ -955,25 +961,30 @@ package body SS_Annotations is -- tree, if so, do the same thing. declare - Ambiguous : Boolean; - File_From_Prj : Virtual_File; - Rel_Path : constant String := - +Create - (Relative_Path - (Target_File, Info.Project.Project_Path.Dir)) - .Dir_Name; + Count : Natural := 0; + Basename : constant GPR2.Simple_Name := + Source.Path_Name.Simple_Name; + Prj_Dir : constant Virtual_File := + Create (+String (Source.Owning_View.Dir_Name.Value)); + Rel_Path : constant String := + +Create (Relative_Path (Target_File, Prj_Dir)).Dir_Name; begin - Project.Project.Create - (Name => Target_File.Base_Name, - Project => GNATCOLL.Projects.No_Project, - Ambiguous => Ambiguous, - File => File_From_Prj); + for View of Project.Project loop + declare + S : constant GPR2.Build.Source.Object := + View.Source (Basename); + begin + if S.Is_Defined then + Count := Count + 1; + end if; + end; + end loop; -- If the basename is ambiguous, use the relative path from -- the project to the file, if it has no relative path -- components (./ or ..). - if Ambiguous then + if Count > 1 then if Has_Relative_Component (Rel_Path) then Warn ("Could not generate adequate file prefix from" @@ -1143,12 +1154,34 @@ package body SS_Annotations is if Args.Remaining_Args.Is_Empty then declare - Files : File_Array_Access := - Project.Project.Root_Project.Source_Files - (Recursive => True, - Include_Externally_Built => - Project.Externally_Built_Projects_Processing_Enabled); + Source_Files : String_Vectors.Vector; + Files : File_Array_Access; + I : Positive := 1; + + procedure Add_File + (Project : GPR2.Project.View.Object; + File : GPR2.Build.Source.Object); + -- Callabck for Enumerate_Sources: append File to Source_Files + + -------------- + -- Add_File -- + -------------- + + procedure Add_File + (Project : GPR2.Project.View.Object; + File : GPR2.Build.Source.Object) + is + pragma Unreferenced (Project); + begin + Source_Files.Append (+String (File.Path_Name.Value)); + end Add_File; begin + Project.Enumerate_Sources (Add_File'Access, All_Languages); + Files := new File_Array (1 .. Positive (Source_Files.Length)); + for F of Source_Files loop + Files.all (I) := Create (+(+F)); + I := I + 1; + end loop; Match_Results := Match_Entries (Files.all, Ext_Annotation_DB, +Purpose_Filter); GNATCOLL.VFS.Unchecked_Free (Files); diff --git a/tools/gnatcov/switches.adb b/tools/gnatcov/switches.adb index 02c928061..314ac92a3 100644 --- a/tools/gnatcov/switches.adb +++ b/tools/gnatcov/switches.adb @@ -421,6 +421,16 @@ package body Switches is end if; end To_Language; + function To_Language (Id : GPR2.Language_Id) return Some_Language is + Result : constant Any_Language := To_Language_Or_All (Id); + begin + if Result = All_Languages then + Fatal_Error ("Unsupported language: " & String (GPR2.Name (Id))); + else + return Result; + end if; + end To_Language; + ------------------------ -- To_Language_Or_All -- ------------------------ @@ -439,6 +449,20 @@ package body Switches is end if; end To_Language_Or_All; + function To_Language_Or_All (Id : GPR2.Language_Id) return Any_Language is + use type GPR2.Language_Id; + begin + if Id = GPR2.Ada_Language then + return Ada_Language; + elsif Id = GPR2.C_Language then + return C_Language; + elsif Id = GPR2.CPP_Language then + return CPP_Language; + else + return All_Languages; + end if; + end To_Language_Or_All; + ----------- -- Image -- ----------- @@ -451,6 +475,19 @@ package body Switches is when CPP_Language => "C++"); end Image; + -------------------- + -- To_Language_Id -- + -------------------- + + function To_Language_Id (Language : Some_Language) return GPR2.Language_Id + is + begin + return (case Language is + when Ada_Language => GPR2.Ada_Language, + when C_Language => GPR2.C_Language, + when CPP_Language => GPR2.CPP_Language); + end To_Language_Id; + ----------------------- -- Command_Line_Args -- ----------------------- @@ -598,10 +635,6 @@ package body Switches is if Args.String_Args (Opt_Root_Dir).Present then Set_Root_Dir (+Args.String_Args (Opt_Root_Dir).Value); end if; - - elsif Args.String_Args (Opt_Root_Dir).Present then - Fatal_Error - ("--root-dir cannot be used without --relocate-build-tree"); end if; -- If the project file does not define a target, loading it needs the @@ -609,14 +642,6 @@ package body Switches is Load_Target_Option (Default_Target => False); Copy_Arg (Opt_Runtime, Runtime); - - if Args.String_Args (Opt_Config).Present - and then - (Args.String_Args (Opt_Target).Present - or else Args.String_Args (Opt_Runtime).Present) - then - Fatal_Error ("--config cannot be used with --target and --RTS"); - end if; Copy_Arg (Opt_Config, CGPR_File); -- All -X command line switches have now been processed: initialize the diff --git a/tools/gnatcov/switches.ads b/tools/gnatcov/switches.ads index 9a3e3a608..bb4c72921 100644 --- a/tools/gnatcov/switches.ads +++ b/tools/gnatcov/switches.ads @@ -21,6 +21,7 @@ with Ada.Directories; with Ada.Exceptions; with GNAT.Strings; use GNAT.Strings; +with GPR2; with Calendar_Utils; use Calendar_Utils; with Command_Line; use Command_Line; @@ -228,12 +229,23 @@ package Switches is -- Convert a human-readable language name to the corresponding enumeration -- value. Abort with a fatal error if Name is invalid. + function To_Language (Id : GPR2.Language_Id) return Some_Language; + -- Convert a GPR2 lanugage ID to our enumeration value. Abort with a fatal + -- error if Name is invalid. + function To_Language_Or_All (Name : String) return Any_Language; -- Like To_Language, but return All_Languages if Name is invalid + function To_Language_Or_All (Id : GPR2.Language_Id) return Any_Language; + -- Like To_Language, but return All_Languages if Name is invalid + function Image (Language : Some_Language) return String; -- Return a human-readable name for the given language + function To_Language_Id (Language : Some_Language) return GPR2.Language_Id; + -- Convert our enumeration value for languages to the corresponding GPR2 + -- language ID. + subtype Bin_Supported_Language is Some_Language range Ada_Language .. C_Language; subtype Src_Supported_Language is diff --git a/tools/gnatcov/traces_source.ads b/tools/gnatcov/traces_source.ads index fa060891c..2af906fd3 100644 --- a/tools/gnatcov/traces_source.ads +++ b/tools/gnatcov/traces_source.ads @@ -24,7 +24,7 @@ with Interfaces; use Interfaces; -with GNATCOLL.Projects; +with GPR2; -- Describes the content of a source trace file. Should be kept up to date -- when the trace format is modified. It is notably used to parse source @@ -88,17 +88,17 @@ package Traces_Source is -- Describe the kind of unit referenced by a trace entry function "+" - (Part : Supported_Unit_Part) return GNATCOLL.Projects.Unit_Parts + (Part : Supported_Unit_Part) return GPR2.Valid_Unit_Kind is (case Part is - when Unit_Body => GNATCOLL.Projects.Unit_Body, - when Unit_Spec => GNATCOLL.Projects.Unit_Spec, - when Unit_Separate => GNATCOLL.Projects.Unit_Separate); + when Unit_Body => GPR2.S_Body, + when Unit_Spec => GPR2.S_Spec, + when Unit_Separate => GPR2.S_Separate); function "+" - (Part : GNATCOLL.Projects.Unit_Parts) return Supported_Unit_Part + (Part : GPR2.Valid_Unit_Kind) return Supported_Unit_Part is (case Part is - when GNATCOLL.Projects.Unit_Body => Unit_Body, - when GNATCOLL.Projects.Unit_Spec => Unit_Spec, - when GNATCOLL.Projects.Unit_Separate => Unit_Separate); + when GPR2.S_Body => Unit_Body, + when GPR2.S_Spec => Unit_Spec, + when GPR2.S_Separate => Unit_Separate); type Any_Bit_Count is new Unsigned_32; -- Number of bits contained in a coverage buffer From 7549e05904a6f32677454da333690a99f9f16545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viviane=20Gar=C3=A8se?= Date: Wed, 26 Mar 2025 15:55:49 +0100 Subject: [PATCH 1177/1483] Update gnattest doc for "--exit-status" --- doc/gnattest/gnattest_part.rst | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/gnattest/gnattest_part.rst b/doc/gnattest/gnattest_part.rst index 09437a53b..0ae9f618b 100644 --- a/doc/gnattest/gnattest_part.rst +++ b/doc/gnattest/gnattest_part.rst @@ -367,7 +367,9 @@ Switches for ``gnattest`` in framework generation mode :switch:`--exit-status={val}` Specifies whether or not generated test driver should return failure exit status if at least one test fails or crashes. ``val`` can be either - "on" or "off", "off" being the default. + "on" or "off", "off" being the default. If ``--exit-status=on`` is used to + generate the test harness, it should also be used if running the test + drivers via the ``gnattest test_drivers.list`` command. .. index:: --omit-sloc (gnattest) @@ -415,6 +417,12 @@ Switches for ``gnattest`` in test execution mode Specifies whether or not passed tests should be shown. ``val`` can be either "show" or "hide", "show" being the default. +:switch:`--exit-status={val}` + Specifies whether or not generated test driver should return failure exit + status if at least one test fails or crashes. ``val`` can be either + "on" or "off", "off" being the default. The switch ``--exit-status=on`` + should be used both when generating the test harness and when running the + test drivers via the ``gnattest test_drivers.list`` command. .. index:: --queues (gnattest) .. index:: -j (gnattest) From 59e1d4a359321ce954d800d98cd5b7d2e658818d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 17 Apr 2025 09:03:38 +0000 Subject: [PATCH 1178/1483] support/libsupport.gpr: add the C language only for leon targets --- tools/gnatcov/examples/support/libsupport.gpr | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/examples/support/libsupport.gpr b/tools/gnatcov/examples/support/libsupport.gpr index 4273342f3..fad3549d7 100644 --- a/tools/gnatcov/examples/support/libsupport.gpr +++ b/tools/gnatcov/examples/support/libsupport.gpr @@ -61,7 +61,17 @@ project Libsupport is when others => - Langs := Langs & ("C"); + -- To avoid "warning: there are no sources of language "C" in this + -- project" messages from LibGPR2, add the C language only for target + -- specific directories that really needed it: the leon ones. + + case Conf.Target is + when "leon-elf" | "leon3-elf" => + Langs := Langs & ("C"); + when others => + null; + end case; + -- Use libsupport's custom memory functions, except for the -- morello target, for which they produce unwanted behavior. From c44afac0fa0ce7c3610b60d69c30ae7dd70cd8c4 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 18 Apr 2025 08:43:59 +0000 Subject: [PATCH 1179/1483] Refactor storage for project naming scheme information Also introduce a helper in `instrument-c.adb` to factorize common logic. --- tools/gnatcov/instrument-c.adb | 104 +++++++++++++---------- tools/gnatcov/instrument-gcc_wrapper.adb | 10 ++- tools/gnatcov/instrument-projects.adb | 48 ++++++----- tools/gnatcov/instrument.adb | 42 +++++---- tools/gnatcov/instrument.ads | 17 ++-- 5 files changed, 128 insertions(+), 93 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index fdfd3c967..b6284d372 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -421,6 +421,19 @@ package body Instrument.C is -- Source instrumentation -- ---------------------------- + function New_Body_File + (Prj : Prj_Desc; + Instrumenter : C_Family_Instrumenter_Type'Class; + Slug : String; + With_Language_Suffix : Boolean := False) return String; + -- Wrapper around Instrument.Common.New_File to generate a file in the + -- given project output directory with a filename that matches: + -- + -- {Sys_Suffix}{Slug}{Body_Suffix} + -- + -- If With_Language_Suffix is True, append a language-specific suffix to + -- Slug. + procedure Emit_Buffer_Unit (UIC : C_Unit_Inst_Context'Class; Unit : Compilation_Unit; @@ -3975,6 +3988,33 @@ package body Instrument.C is return (+Result); end Format_Array_Init_Expr; + ------------------- + -- New_Body_File -- + ------------------- + + function New_Body_File + (Prj : Prj_Desc; + Instrumenter : C_Family_Instrumenter_Type'Class; + Slug : String; + With_Language_Suffix : Boolean := False) return String + is + Language : constant C_Family_Language := Instrumenter.Language; + Language_Suffix : constant String := + (if With_Language_Suffix + then (case Language is + when C_Language => "_c", + when CPP_Language => "_cpp") + else ""); + begin + return + New_File + (Prj, + To_Symbol_Name (Sys_Prefix) + & Slug + & Language_Suffix + & (+Prj.Naming_Scheme.Body_Suffix (Language))); + end New_Body_File; + ---------------------- -- Emit_Buffer_Unit -- ---------------------- @@ -5100,21 +5140,12 @@ package body Instrument.C is function Buffer_Unit (Self : C_Family_Instrumenter_Type; CU : Compilation_Unit; - Prj : Prj_Desc) return Compilation_Unit - is - Name : constant String := - To_Symbol_Name (Sys_Prefix) & "_b_" - & Filename_Slug (+CU.Unit_Name) - & (+Prj.Body_Suffix - (C_Family_Instrumenter_Type'Class (Self).Language)); + Prj : Prj_Desc) return Compilation_Unit is begin - declare - Filename : constant String := New_File (Prj, Name); - begin - return Compilation_Unit' - (Language => File_Based_Language, - Unit_Name => +Filename); - end; + return Compilation_Unit' + (Language => File_Based_Language, + Unit_Name => +New_Body_File + (Prj, Self, "_b_" & Filename_Slug (+CU.Unit_Name))); exception when Exc : Ada.IO_Exceptions.Name_Error => Fatal_Error @@ -5128,23 +5159,20 @@ package body Instrument.C is overriding function Dump_Manual_Helper_Unit (Self : C_Family_Instrumenter_Type; - Prj : Prj_Desc) return Compilation_Unit - is - Lang : Src_Supported_Language renames - C_Family_Instrumenter_Type'Class (Self).Language; - Filename : constant String := - New_File - (Prj, - To_Symbol_Name (Sys_Prefix) - & "_d_b_" & To_Symbol_Name (Prj.Prj_Name) - & (if Lang = CPP_Language then "_cpp" else "_c") - & (+Prj.Body_Suffix (Lang))); - -- The _cpp or _c suffix is required so that in case both C and C++ - -- helper units are generated, they don't have homonym object filenames. + Prj : Prj_Desc) return Compilation_Unit is begin + -- Add a language specific suffix so that in case both C and C++ helper + -- units are generated for this project, they don't have homonym object + -- filenames. + return Compilation_Unit' (Language => File_Based_Language, - Unit_Name => +Filename); + Unit_Name => + +New_Body_File + (Prj, + Self, + "_d_b_" & To_Symbol_Name (Prj.Prj_Name), + With_Language_Suffix => True)); end Dump_Manual_Helper_Unit; ---------------------- @@ -5154,20 +5182,12 @@ package body Instrument.C is overriding function Dump_Helper_Unit (Self : C_Family_Instrumenter_Type; CU : Compilation_Unit; - Prj : Prj_Desc) return Compilation_Unit - is - Filename : constant String := - New_File - (Prj, - To_Symbol_Name (Sys_Prefix) - & "_d_" - & Filename_Slug (+CU.Unit_Name) - & (+Prj.Body_Suffix - (C_Family_Instrumenter_Type'Class (Self).Language))); + Prj : Prj_Desc) return Compilation_Unit is begin return Compilation_Unit' (Language => File_Based_Language, - Unit_Name => +Filename); + Unit_Name => +New_Body_File + (Prj, Self, "_d_" & Filename_Slug (+CU.Unit_Name))); end Dump_Helper_Unit; -------------- @@ -5380,11 +5400,7 @@ package body Instrument.C is Prj : Prj_Desc) return Compilation_Unit is Filename : constant String := - New_File - (Prj, - "gcvrtc-" & To_Symbol_Name (Prj.Prj_Name) - & (+Prj.Body_Suffix - (C_Family_Instrumenter_Type'Class (Self).Language))); + New_Body_File (Prj, Self, "c-" & To_Symbol_Name (Prj.Prj_Name)); CU_Name : constant Compilation_Unit := (File_Based_Language, +Filename); CU_File : Text_Files.File_Type; diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 126813ad7..2e53ebb4d 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -782,10 +782,12 @@ begin Prj.Prj_Name := To_Qualified_Name ("main"); Prj.Output_Dir := +Instr_Dir.Directory_Name; - Prj.Spec_Suffix := - (C_Language => +".h", CPP_Language => +".hh", others => <>); - Prj.Body_Suffix := - (C_Language => +".c", CPP_Language => +".cc", others => <>); + Prj.Naming_Scheme := + (Spec_Suffix => + (C_Language => +".h", CPP_Language => +".hh", others => <>), + Body_Suffix => + (C_Language => +".c", CPP_Language => +".cc", others => <>), + Dot_Replacement => +"-"); -- Then, invoke the right set of gnatcov commands diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index a08d15045..f16ae0ca3 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -292,31 +292,35 @@ is is package R renames GPR2.Project.Registry.Attribute; - Languages : constant GPR2.Containers.Language_Set := - Prj.Language_Ids; - Dot_Replacement : constant String := - Prj.Attribute (Name => R.Naming.Dot_Replacement).Value.Text; - Result : Prj_Desc; + Languages : constant GPR2.Containers.Language_Set := Prj.Language_Ids; + Result : Prj_Desc; begin - for Lang in Some_Language loop - if Builtin_Support (Lang) - and then Languages.Contains (To_Language_Id (Lang)) - then - declare - Body_Suffix : constant String := - Project.Source_Suffix (Lang, GPR2.S_Body, Prj); - Spec_Suffix : constant String := - Project.Source_Suffix (Lang, GPR2.S_Spec, Prj); - begin - Result.Body_Suffix (Lang) := +Body_Suffix; - Result.Spec_Suffix (Lang) := +Spec_Suffix; - end; - end if; - end loop; - Result.Prj_Name := To_Qualified_Name (String (Prj.Name)); Result.View := Prj; - Result.Dot_Replacement := +Dot_Replacement; + + -- Load the naming scheme from project attributes + + declare + NS : Naming_Scheme_Desc renames Result.Naming_Scheme; + begin + for Lang in Some_Language loop + if Builtin_Support (Lang) + and then Languages.Contains (To_Language_Id (Lang)) + then + declare + Body_Suffix : constant String := + Project.Source_Suffix (Lang, GPR2.S_Body, Prj); + Spec_Suffix : constant String := + Project.Source_Suffix (Lang, GPR2.S_Spec, Prj); + begin + NS.Body_Suffix (Lang) := +Body_Suffix; + NS.Spec_Suffix (Lang) := +Spec_Suffix; + end; + end if; + end loop; + NS.Dot_Replacement := + +Prj.Attribute (Name => R.Naming.Dot_Replacement).Value.Text; + end; -- Register the source directories of the project tree diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 2a2af3834..88f64e823 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -513,13 +513,17 @@ package body Instrument is (Opt_Compiler_Driver, Result.Compiler_Driver (Language)); end if; Fill_If_Present (Opt_Output_Directory, Result.Output_Dir); - Fill_If_Present (Opt_Spec_Suffix, Result.Spec_Suffix (Language)); - Fill_If_Present (Opt_Body_Suffix, Result.Body_Suffix (Language)); Fill_If_Present (Opt_Project_Name, Prj_Name); - Fill_If_Present (Opt_Dot_Replacement, Result.Dot_Replacement); - Result.Prj_Name := To_Qualified_Name (+Prj_Name); + declare + NS : Naming_Scheme_Desc renames Result.Naming_Scheme; + begin + Fill_If_Present (Opt_Spec_Suffix, NS.Spec_Suffix (Language)); + Fill_If_Present (Opt_Body_Suffix, NS.Body_Suffix (Language)); + Fill_If_Present (Opt_Dot_Replacement, NS.Dot_Replacement); + end; + -- Compiler options are loaded through the --c/c++-opts switch return Result; @@ -537,22 +541,26 @@ package body Instrument is Result : String_Vectors.Vector; Compiler_Opts : String_Vectors.Vector; begin - -- Pass the right body / spec suffixes + -- Pass naming scheme settings - if Desc.Body_Suffix (Lang) /= "" then - Result.Append (+"--body-suffix"); - Result.Append (Desc.Body_Suffix (Lang)); - end if; + declare + NS : Naming_Scheme_Desc renames Desc.Naming_Scheme; + begin + if NS.Body_Suffix (Lang) /= "" then + Result.Append (+"--body-suffix"); + Result.Append (NS.Body_Suffix (Lang)); + end if; - if Desc.Spec_Suffix (Lang) /= "" then - Result.Append (+"--spec-suffix"); - Result.Append (Desc.Spec_Suffix (Lang)); - end if; + if NS.Spec_Suffix (Lang) /= "" then + Result.Append (+"--spec-suffix"); + Result.Append (NS.Spec_Suffix (Lang)); + end if; - if Desc.Dot_Replacement /= "" then - Result.Append (+"--dot-replacement"); - Result.Append (Desc.Dot_Replacement); - end if; + if NS.Dot_Replacement /= "" then + Result.Append (+"--dot-replacement"); + Result.Append (NS.Dot_Replacement); + end if; + end; if Lang in C_Family_Language then Compiler_Opts.Append (Desc.Search_Paths); diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 33cb7a92f..8a0dcd02a 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -268,6 +268,15 @@ package Instrument is of Unbounded_String; type C_Lang_Array_Vec is array (C_Family_Language) of String_Vectors.Vector; + type Naming_Scheme_Desc is record + Spec_Suffix, Body_Suffix : Lang_Array (Src_Supported_Language); + -- Suffixes for the body and the spec + + Dot_Replacement : Unbounded_String; + -- Character to use as identifier separator for file naming (used for + -- unit-based languages). + end record; + type Prj_Desc is record Prj_Name : Ada_Qualified_Name; -- Name for the project @@ -279,12 +288,8 @@ package Instrument is -- Where the instrumented sources and coverage buffer units are -- generated. - Spec_Suffix, Body_Suffix : Lang_Array (Src_Supported_Language); - -- Suffixes for the body and the spec - - Dot_Replacement : Unbounded_String; - -- Character to use as identifier separator for file naming (used for - -- unit-based languages). + Naming_Scheme : Naming_Scheme_Desc; + -- Naming scheme for this project Compiler_Driver : Lang_Array (C_Family_Language); -- Compiler used to compile the sources From 5e8bf5aff2c90565ffc418d92e54e17ff7f54b7b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 18 Apr 2025 09:05:28 +0000 Subject: [PATCH 1180/1483] Fix instrumentation of Ada sources in parallel mode --- .../instr-cov/parallel-sanity-check/main.adb | 8 ++++ .../instr-cov/parallel-sanity-check/test.py | 28 ++++++++++++ .../instr-cov/parallel-sanity-check/utils.c | 5 +++ tools/gnatcov/instrument-common.adb | 43 +++++++++++++++++-- tools/gnatcov/instrument-projects.adb | 1 - tools/gnatcov/instrument.ads | 3 -- 6 files changed, 81 insertions(+), 7 deletions(-) create mode 100644 testsuite/tests/instr-cov/parallel-sanity-check/main.adb create mode 100644 testsuite/tests/instr-cov/parallel-sanity-check/test.py create mode 100644 testsuite/tests/instr-cov/parallel-sanity-check/utils.c diff --git a/testsuite/tests/instr-cov/parallel-sanity-check/main.adb b/testsuite/tests/instr-cov/parallel-sanity-check/main.adb new file mode 100644 index 000000000..b8aeb491d --- /dev/null +++ b/testsuite/tests/instr-cov/parallel-sanity-check/main.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is + function Identity (I : Integer) return Integer; + pragma Import (C, Identity, "identity"); +begin + Put_Line (Integer'Image (Identity (1))); +end Main; diff --git a/testsuite/tests/instr-cov/parallel-sanity-check/test.py b/testsuite/tests/instr-cov/parallel-sanity-check/test.py new file mode 100644 index 000000000..f51c4816b --- /dev/null +++ b/testsuite/tests/instr-cov/parallel-sanity-check/test.py @@ -0,0 +1,28 @@ +""" +Check that "gnatcov instrument" works correctly when run with more than one +job. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(mains=["main.adb"], srcdirs=[".."]), + ), + covlevel="stmt", + mains=["main"], + extra_instr_args=["-j2"], + extra_coverage_args=["--annotate=xcov"], +) +check_xcov_reports( + "obj", {"main.adb.xcov": {"+": {7}}, "utils.c.xcov": {"+": {4}}} +) + +thistest.result() diff --git a/testsuite/tests/instr-cov/parallel-sanity-check/utils.c b/testsuite/tests/instr-cov/parallel-sanity-check/utils.c new file mode 100644 index 000000000..c5582d06a --- /dev/null +++ b/testsuite/tests/instr-cov/parallel-sanity-check/utils.c @@ -0,0 +1,5 @@ +int +identity (int i) +{ + return i; +} diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 538fafc96..16d979c37 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -434,9 +434,46 @@ package body Instrument.Common is begin case CU_Name.Language_Kind is when Unit_Based_Language => - return String - (Prj.View.Filename_For_Unit - (GPR2.Name_Type (To_Ada (CU_Name.Unit)), CU_Name.Part)); + + -- It is tempting here to fetch the answer from the best source of + -- truth: the GPR library for the given project. Unfortunately + -- this is not always possible: this function may be called in a + -- subprocess for the parallel instrumentation, and no GPR project + -- is loaded in this context. + -- + -- Fortunately, this function is called only to create new sources + -- (i.e. not instrumented sources, but extra helpers): all we have + -- to do in principle is to follow the general purpose naming + -- scheme directives (dot replacement and body/spec sufifxes), as + -- project files are very unlikely to contain naming exceptions + -- for extra helpers, which are sources that do not exist before + -- instrumentation. + + declare + -- Do the same assumption as GPR2: the only unit-based language + -- is Ada. + + Language : constant Src_Supported_Language := Ada_Language; + + NS : Naming_Scheme_Desc renames Prj.Naming_Scheme; + Filename : Unbounded_String; + begin + for Id of CU_Name.Unit loop + if Filename /= "" then + Append (Filename, NS.Dot_Replacement); + end if; + Append (Filename, To_Lower (To_String (Id))); + end loop; + + case CU_Name.Part is + when GPR2.S_Body | GPR2.S_Separate => + Append (Filename, NS.Body_Suffix (Language)); + when GPR2.S_Spec => + Append (Filename, NS.Spec_Suffix (Language)); + end case; + return +Filename; + end; + when File_Based_Language => return +CU_Name.Filename; end case; diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index f16ae0ca3..0f50f2da2 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -296,7 +296,6 @@ is Result : Prj_Desc; begin Result.Prj_Name := To_Qualified_Name (String (Prj.Name)); - Result.View := Prj; -- Load the naming scheme from project attributes diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 8a0dcd02a..934d35586 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -281,9 +281,6 @@ package Instrument is Prj_Name : Ada_Qualified_Name; -- Name for the project - View : GPR2.Project.View.Object; - -- GPR2 view for the project, if this is backed by an actual GPR project - Output_Dir : Unbounded_String; -- Where the instrumented sources and coverage buffer units are -- generated. From 8b7877a4a924af4c98ade488aa5e33726daffc0e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 18 Apr 2025 09:33:02 +0000 Subject: [PATCH 1181/1483] Add the missing handling of casing settings from project files --- .../tests/T825-010-naming-scheme/main.adb | 4 +- .../{p.1.ada => pkg.1.ada} | 4 +- .../{p.2.ada => pkg.2.ada} | 4 +- .../{p__q.1.ada => pkg__child.1.ada} | 4 +- .../{p__q.2.ada => pkg__child.2.ada} | 4 +- .../tests/T825-010-naming-scheme/test.py | 88 ++++++++++++------- tools/gnatcov/command_line.ads | 13 +++ tools/gnatcov/instrument-common.adb | 9 +- tools/gnatcov/instrument-gcc_wrapper.adb | 3 +- tools/gnatcov/instrument-projects.adb | 3 + tools/gnatcov/instrument.adb | 30 ++++++- tools/gnatcov/instrument.ads | 13 +++ 12 files changed, 134 insertions(+), 45 deletions(-) rename testsuite/tests/T825-010-naming-scheme/{p.1.ada => pkg.1.ada} (75%) rename testsuite/tests/T825-010-naming-scheme/{p.2.ada => pkg.2.ada} (76%) rename testsuite/tests/T825-010-naming-scheme/{p__q.1.ada => pkg__child.1.ada} (64%) rename testsuite/tests/T825-010-naming-scheme/{p__q.2.ada => pkg__child.2.ada} (74%) diff --git a/testsuite/tests/T825-010-naming-scheme/main.adb b/testsuite/tests/T825-010-naming-scheme/main.adb index 66acef3b1..5a9eb3e67 100644 --- a/testsuite/tests/T825-010-naming-scheme/main.adb +++ b/testsuite/tests/T825-010-naming-scheme/main.adb @@ -1,6 +1,6 @@ -with P.Q; +with Pkg.Child; procedure Main is begin - P.Q.Proc (1); + Pkg.Child.Proc (1); end Main; diff --git a/testsuite/tests/T825-010-naming-scheme/p.1.ada b/testsuite/tests/T825-010-naming-scheme/pkg.1.ada similarity index 75% rename from testsuite/tests/T825-010-naming-scheme/p.1.ada rename to testsuite/tests/T825-010-naming-scheme/pkg.1.ada index c8ef9f5c5..4b917c5d4 100644 --- a/testsuite/tests/T825-010-naming-scheme/p.1.ada +++ b/testsuite/tests/T825-010-naming-scheme/pkg.1.ada @@ -1,4 +1,4 @@ -package P is +package Pkg is type Int is new Integer; function Identity (Value : Int) return Int; -end P; +end Pkg; diff --git a/testsuite/tests/T825-010-naming-scheme/p.2.ada b/testsuite/tests/T825-010-naming-scheme/pkg.2.ada similarity index 76% rename from testsuite/tests/T825-010-naming-scheme/p.2.ada rename to testsuite/tests/T825-010-naming-scheme/pkg.2.ada index b07cb8a29..a9963c839 100644 --- a/testsuite/tests/T825-010-naming-scheme/p.2.ada +++ b/testsuite/tests/T825-010-naming-scheme/pkg.2.ada @@ -1,6 +1,6 @@ -package body P is +package body Pkg is function Identity (Value : Int) return Int is begin return Value; end Identity; -end P; +end Pkg; diff --git a/testsuite/tests/T825-010-naming-scheme/p__q.1.ada b/testsuite/tests/T825-010-naming-scheme/pkg__child.1.ada similarity index 64% rename from testsuite/tests/T825-010-naming-scheme/p__q.1.ada rename to testsuite/tests/T825-010-naming-scheme/pkg__child.1.ada index c8ae1e709..93791744a 100644 --- a/testsuite/tests/T825-010-naming-scheme/p__q.1.ada +++ b/testsuite/tests/T825-010-naming-scheme/pkg__child.1.ada @@ -1,4 +1,4 @@ -package P.Q is +package Pkg.Child is procedure Proc (I : Int); V : constant Int := Identity (2); -end P.Q; +end Pkg.Child; diff --git a/testsuite/tests/T825-010-naming-scheme/p__q.2.ada b/testsuite/tests/T825-010-naming-scheme/pkg__child.2.ada similarity index 74% rename from testsuite/tests/T825-010-naming-scheme/p__q.2.ada rename to testsuite/tests/T825-010-naming-scheme/pkg__child.2.ada index 85c318345..9cac4e4cf 100644 --- a/testsuite/tests/T825-010-naming-scheme/p__q.2.ada +++ b/testsuite/tests/T825-010-naming-scheme/pkg__child.2.ada @@ -1,8 +1,8 @@ with Ada.Text_IO; use Ada.Text_IO; -package body P.Q is +package body Pkg.Child is procedure Proc (I : Int) is begin Put_Line (Int'Image (I)); end Proc; -end P.Q; +end Pkg.Child; diff --git a/testsuite/tests/T825-010-naming-scheme/test.py b/testsuite/tests/T825-010-naming-scheme/test.py index 48f990391..7e60255a2 100644 --- a/testsuite/tests/T825-010-naming-scheme/test.py +++ b/testsuite/tests/T825-010-naming-scheme/test.py @@ -2,6 +2,8 @@ Check that gnatcov works fine on projects using non-standard naming schemes. """ +from e3.fs import cp + from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir @@ -9,37 +11,59 @@ from SUITE.gprutils import GPRswitches -tmp = Wdir("tmp_") - -p = gprfor( - mains=["main.adb"], - prjid="p", - srcdirs=[".."], - extra=""" - package Naming is - for Spec_Suffix ("Ada") use ".1.ada"; - for Body_Suffix ("Ada") use ".2.ada"; - for Dot_Replacement use "__"; - for Body ("main") use "main.adb"; - end Naming; - """, -) -build_run_and_coverage( - gprsw=GPRswitches(root_project=p), - covlevel="stmt", - mains=["main"], - extra_coverage_args=["-axcov", "--output-dir=report"], -) -check_xcov_reports( - "report", - { - "main.adb.xcov": {"+": {5}}, - "p.1.ada.xcov": {}, - "p.2.ada.xcov": {"+": {4}}, - "p__q.1.ada.xcov": {"+": {3}}, - "p__q.2.ada.xcov": {"+": {6}}, - }, - discard_empty=False, -) +spec_suffix = ".1.ada" +body_suffix = ".2.ada" + +for casing, converter in [ + ("lowercase", str.lower), + ("uppercase", str.upper), + ("mixedcase", str), +]: + tmp = Wdir(f"tmp_{casing}") + + pkg_spec = converter("Pkg") + spec_suffix + pkg_body = converter("Pkg") + body_suffix + child_spec = converter("Pkg__Child") + spec_suffix + child_body = converter("Pkg__Child") + body_suffix + + cp("../main.adb", "main.adb") + cp("../pkg.1.ada", pkg_spec) + cp("../pkg.2.ada", pkg_body) + cp("../pkg__child.1.ada", child_spec) + cp("../pkg__child.2.ada", child_body) + + p = gprfor( + mains=["main.adb"], + prjid="p", + srcdirs=["."], + extra=f""" + package Naming is + for Spec_Suffix ("Ada") use "{spec_suffix}"; + for Body_Suffix ("Ada") use "{body_suffix}"; + for Dot_Replacement use "__"; + for Body ("main") use "main.adb"; + for Casing use "{casing}"; + end Naming; + """, + ) + build_run_and_coverage( + gprsw=GPRswitches(root_project=p), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=report"], + ) + check_xcov_reports( + "report", + { + "main.adb.xcov": {"+": {5}}, + f"{pkg_spec}.xcov": {}, + f"{pkg_body}.xcov": {"+": {4}}, + f"{child_spec}.xcov": {"+": {3}}, + f"{child_body}.xcov": {"+": {6}}, + }, + discard_empty=False, + ) + + tmp.to_homedir() thistest.result() diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 5e5154d9a..2088a30ac 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -147,6 +147,7 @@ package Command_Line is Opt_Spec_Suffix, Opt_Body_Suffix, Opt_Dot_Replacement, + Opt_Casing, Opt_Gnatem, Opt_Config_Pragmas_Mapping, Opt_Ada_Preprocessor_Data, @@ -1209,6 +1210,18 @@ package Command_Line is At_Most_Once => False, Internal => True), + Opt_Casing => Create + (Long_Name => "--casing", + Pattern => "CASING", + Help => + "Casing for source files created by the instrumenter for the" + & " instrumentation of a source.", + Commands => + (Cmd_Instrument_Source | Cmd_Instrument_Main => True, + others => False), + At_Most_Once => False, + Internal => True), + Opt_Gnatem => Create (Long_Name => "--gnatem", Pattern => "NAME", diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 16d979c37..37f0917e1 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -462,7 +462,14 @@ package body Instrument.Common is if Filename /= "" then Append (Filename, NS.Dot_Replacement); end if; - Append (Filename, To_Lower (To_String (Id))); + case NS.Casing is + when Lowercase => + Append (Filename, To_Lower (To_String (Id))); + when Uppercase => + Append (Filename, To_Upper (To_String (Id))); + when Mixedcase => + Append (Filename, To_String (Id)); + end case; end loop; case CU_Name.Part is diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 2e53ebb4d..8e1631f1d 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -787,7 +787,8 @@ begin (C_Language => +".h", CPP_Language => +".hh", others => <>), Body_Suffix => (C_Language => +".c", CPP_Language => +".cc", others => <>), - Dot_Replacement => +"-"); + Dot_Replacement => +"-", + Casing => Mixedcase); -- Then, invoke the right set of gnatcov commands diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 0f50f2da2..921ca5596 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -319,6 +319,9 @@ is end loop; NS.Dot_Replacement := +Prj.Attribute (Name => R.Naming.Dot_Replacement).Value.Text; + NS.Casing := Casing_From_String + (Prj.Attribute (Name => R.Naming.Casing).Value.Text, + "project " & String (Prj.Name)); end; -- Register the source directories of the project tree diff --git a/tools/gnatcov/instrument.adb b/tools/gnatcov/instrument.adb index 88f64e823..91273b245 100644 --- a/tools/gnatcov/instrument.adb +++ b/tools/gnatcov/instrument.adb @@ -39,6 +39,7 @@ pragma Warnings (On, "not referenced"); with Command_Line; use Command_Line; with Files_Handling; use Files_Handling; with Hex_Images; use Hex_Images; +with Outputs; package body Instrument is @@ -475,6 +476,23 @@ package body Instrument is end if; end Find_Instrumented_Unit; + ------------------------ + -- Casing_From_String -- + ------------------------ + + function Casing_From_String (Value, Context : String) return Casing_Type is + begin + if Value = "lowercase" then + return Lowercase; + elsif Value = "uppercase" then + return Uppercase; + elsif Value = "mixedcase" then + return Mixedcase; + else + Outputs.Fatal_Error ("Invalid casing from " & Context & ": " & Value); + end if; + end Casing_From_String; + ---------------------------- -- Load_From_Command_Line -- ---------------------------- @@ -517,11 +535,18 @@ package body Instrument is Result.Prj_Name := To_Qualified_Name (+Prj_Name); declare - NS : Naming_Scheme_Desc renames Result.Naming_Scheme; + NS : Naming_Scheme_Desc renames Result.Naming_Scheme; + Casing : String_Option renames Args.String_Args (Opt_Casing); begin Fill_If_Present (Opt_Spec_Suffix, NS.Spec_Suffix (Language)); Fill_If_Present (Opt_Body_Suffix, NS.Body_Suffix (Language)); Fill_If_Present (Opt_Dot_Replacement, NS.Dot_Replacement); + if Casing.Present then + NS.Casing := + Casing_From_String (+Casing.Value, "argument --casing"); + else + NS.Casing := Lowercase; + end if; end; -- Compiler options are loaded through the --c/c++-opts switch @@ -560,6 +585,9 @@ package body Instrument is Result.Append (+"--dot-replacement"); Result.Append (NS.Dot_Replacement); end if; + + Result.Append (+"--casing"); + Result.Append (+To_Lower (NS.Casing'Image)); end; if Lang in C_Family_Language then diff --git a/tools/gnatcov/instrument.ads b/tools/gnatcov/instrument.ads index 934d35586..fd0e9592c 100644 --- a/tools/gnatcov/instrument.ads +++ b/tools/gnatcov/instrument.ads @@ -268,6 +268,16 @@ package Instrument is of Unbounded_String; type C_Lang_Array_Vec is array (C_Family_Language) of String_Vectors.Vector; + type Casing_Type is (Lowercase, Uppercase, Mixedcase); + -- Casing for source files in projects + + function Casing_From_String (Value, Context : String) return Casing_Type; + -- Convert Value to the corresponding Casing_Type value. + -- + -- If Value is an invalid name for a casing, raise a fatal error, using + -- Context to specify in the error message where the casing value comes + -- from. + type Naming_Scheme_Desc is record Spec_Suffix, Body_Suffix : Lang_Array (Src_Supported_Language); -- Suffixes for the body and the spec @@ -275,6 +285,9 @@ package Instrument is Dot_Replacement : Unbounded_String; -- Character to use as identifier separator for file naming (used for -- unit-based languages). + + Casing : Casing_Type; + -- Casing conversion for unit names to file names end record; type Prj_Desc is record From 8baa23b24d538b64b47e726f4eeb5ed837368305 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 18 Apr 2025 09:40:38 +0000 Subject: [PATCH 1182/1483] CI: use a pre-GPR2 transition gnatcov for self-instrumentation The transition of gnatcov to GPR2 broke the instrumentation of Ada sources in parallel mode. As a workaround, use a pre-GPR2 transition wavefront for now to restore the CI. We should revert this once the GPR2 transition is fixed. --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 67e84bb02..b4ddd866b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -45,7 +45,7 @@ build: - anod build --smart-rebuild --deps-only gnatcov $ACI_TRACK_QUALIFIER # 2. Install vanilla gnatcov from cathod - - anod install gnatcov $ACI_TRACK_QUALIFIER --latest + - anod install gnatcov $ACI_TRACK_QUALIFIER --build-date=20250415 # 3. Build using anod, but minimally as all dependencies are supposed to be # already built/installed via 1, but we don't want to re-build the From 1bec3191a5608c47c5833244355dfeb577d783cb Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 3 Apr 2025 11:13:40 +0200 Subject: [PATCH 1183/1483] instr-c(funcall): Handle call of function pointer as struct field for CXX Make use of the generic witness like for CXX class methods --- tools/gnatcov/clang-extensions.adb | 13 ++++ tools/gnatcov/clang-extensions.ads | 22 ++++++ tools/gnatcov/clang-wrapper.cc | 111 ++++++++++++++++++++++++++--- tools/gnatcov/instrument-c.adb | 65 ++++++++++++----- tools/gnatcov/instrument-c.ads | 3 +- 5 files changed, 183 insertions(+), 31 deletions(-) diff --git a/tools/gnatcov/clang-extensions.adb b/tools/gnatcov/clang-extensions.adb index da73d1e65..8db13a3c3 100644 --- a/tools/gnatcov/clang-extensions.adb +++ b/tools/gnatcov/clang-extensions.adb @@ -98,6 +98,19 @@ package body Clang.Extensions is return Is_CXX_Member_Call_Expr_C (C) /= 0; end Is_Prefixed_CXX_Member_Call_Expr; + ---------------------------------- + -- Is_Struct_Field_Call_Expr -- + ---------------------------------- + + function Is_Struct_Field_Call_Expr (C : Cursor_T) return Boolean is + function Is_Struct_Field_Call_Expr_C (C : Cursor_T) return unsigned + with + Import, Convention => C, + External_Name => "clang_isStructFieldCallExpr"; + begin + return Is_Struct_Field_Call_Expr_C (C) /= 0; + end Is_Struct_Field_Call_Expr; + -------------------- -- Get_Opcode_Str -- -------------------- diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index 73d5f8aa1..974bbc85e 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -137,6 +137,10 @@ package Clang.Extensions is -- (meaning not a method that is called from the body of another method -- in which it is possible to simply omit `this->`). + function Is_Struct_Field_Call_Expr (C : Cursor_T) return Boolean; + -- Return true if the cursor points to a CallExpr, whose callee is a + -- MemberExpr. + function Get_CXX_Member_Call_Expr_SCO_Sloc_Range (C : Cursor_T) return Source_Range_T with @@ -157,6 +161,24 @@ package Clang.Extensions is -- Given the expression is `Foo.Bar(Baz)`, it will return the source -- range of `Foo`. + function Get_Struct_Field_Call_Expr_SCO_Sloc_Range + (C : Cursor_T) return Source_Range_T + with + Import, + Convention => C, + External_Name => "clang_getStructFieldCallExprSCOSlocRange"; + -- Given the expression is `Foo.Bar(Baz)`, it will return the source range + -- for `.Bar(Baz)`. + + function Get_Struct_Field_Call_Expr_Base_Sloc_Range + (C : Cursor_T) return Source_Range_T + with + Import, + Convention => C, + External_Name => "clang_getStructFieldCallExprBaseSlocRange"; + -- Given the expression is `Foo.Bar(Baz)`, it will return the source range + -- for `Foo`. + function Is_Constexpr (C : Cursor_T) return Boolean with Inline; function Unwrap (C : Cursor_T) return Cursor_T diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 6d1ce4b49..7a2577f0a 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -400,6 +400,64 @@ clang_isPrefixedCXXMemberCallExpr (CXCursor C) return !ME->isImplicitAccess (); } +/* A struct field call expr is a call expression whose callee is a function + pointer stored as a member of a struct. This function detects such a + construction. Note that for compilation reasons, clang wraps the callee + in an `ImplicitCastExpr` we need to handle. */ +extern "C" unsigned +clang_isStructFieldCallExpr (CXCursor C) +{ + if (!clang_isExpression (C.kind)) + return false; + + const Expr *E = getCursorExpr (C); + if (E->getStmtClass () != Stmt::CallExprClass) + return false; + + const Expr *callee = cast (E)->getCallee (); + + // Skip implicit LValueToRValue cast that is not relevant for us. + if (callee->getStmtClass () == Stmt::ImplicitCastExprClass) + callee = cast (callee)->getSubExpr (); + + return callee->getStmtClass () == Stmt::MemberExprClass; +} + +/* Given a Member expression, return a CharSourceRange that wraps the accessing + operator (. or ->) and the member name. */ +static CharSourceRange +getMemberSloc (const MemberExpr *ME) +{ + const SourceLocation start_loc = ME->getOperatorLoc (); + const SourceLocation end_loc = ME->getMemberLoc ().getLocWithOffset ( + ((long) ME->getMemberDecl ()->getName ().size ()) - 1); + + // Check for validity on both sides. + // Specifically, start loc can fail if there is no operator, if the member + // reference is made from a method and thus not prefixed by `object.` or + // `object->` (implicit `this->`). + if (start_loc.isInvalid () || end_loc.isInvalid ()) + return CharSourceRange (); + + return CharSourceRange::getCharRange (SourceRange (start_loc, end_loc)); +} + +static const MemberExpr * +getMemberExprFromCallExpr (const CallExpr *CE) +{ + const Expr *callee = CE->getCallee (); + + // Skip implicit LValueToRValue cast that is not relevant for us. + if (callee->getStmtClass () == Stmt::ImplicitCastExprClass) + callee = cast (callee)->getSubExpr (); + + // We should have a member expr here. + if (callee->getStmtClass () != Stmt::MemberExprClass) + return nullptr; + + return cast (callee); +} + extern "C" CXSourceRange clang_getCXXMemberCallExprSCOSlocRange (CXCursor C) { @@ -415,22 +473,32 @@ clang_getCXXMemberCallExprSCOSlocRange (CXCursor C) ASTContext &ctx = getContext (C); - const SourceLocation start_loc = ME->getOperatorLoc (); - const SourceLocation end_loc = ME->getMemberLoc ().getLocWithOffset ( - ((long) ME->getMemberDecl ()->getName ().size ()) - 1); + // Do not use the translateSourceRange wrapper because the token + // delimitation is not right for us. + return translateSourceRange (ctx.getSourceManager (), ctx.getLangOpts (), + getMemberSloc (ME)); +} - // Check for validity on both sides. - // Specifically, start loc can fail if there is no operator, if the method - // call is made from another method and thus not prefixed by `object.` or - // `object->` - if (start_loc.isInvalid () || end_loc.isInvalid ()) +extern "C" CXSourceRange +clang_getStructFieldCallExprSCOSlocRange (CXCursor C) +{ + if (!clang_isExpression (C.kind)) + return clang_getNullRange (); + + const Expr *E = getCursorExpr (C); + if (E->getStmtClass () != Stmt::CallExprClass) + return clang_getNullRange (); + + const MemberExpr *ME = getMemberExprFromCallExpr (cast (E)); + if (ME == nullptr) return clang_getNullRange (); + ASTContext &ctx = getContext (C); + // Do not use the translateSourceRange wrapper because the token // delimitation is not right for us. - return translateSourceRange ( - ctx.getSourceManager (), ctx.getLangOpts (), - CharSourceRange::getCharRange (SourceRange (start_loc, end_loc))); + return translateSourceRange (ctx.getSourceManager (), ctx.getLangOpts (), + getMemberSloc (ME)); } extern "C" CXSourceRange @@ -453,6 +521,27 @@ clang_getCXXMemberCallExprBaseSlocRange (CXCursor C) SourceRange (start_loc, end_loc)); } +extern "C" CXSourceRange +clang_getStructFieldCallExprBaseSlocRange (CXCursor C) +{ + if (!clang_isExpression (C.kind)) + return clang_getNullRange (); + + const Expr *E = getCursorExpr (C); + if (E->getStmtClass () != Stmt::CallExprClass) + return clang_getNullRange (); + + const MemberExpr *ME = getMemberExprFromCallExpr (cast (E)); + if (ME == nullptr) + return clang_getNullRange (); + + const SourceLocation start_loc = ME->getBase ()->getBeginLoc (); + const SourceLocation end_loc = ME->getBase ()->getEndLoc (); + + return translateSourceRange (getContext (C), + SourceRange (start_loc, end_loc)); +} + extern "C" CXSourceRange clang_getFunctionSignatureSloc (CXCursor C) { diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index b6284d372..68d8adc0e 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -1352,6 +1352,32 @@ package body Instrument.C is -- level SCO with the given Bit id in the statement buffer at -- Buffer_Index. + procedure Wrap_In_CXX_Generic_Witness (SR : Source_Range_T); + -- Wraps the given source range inside a generic witness function like + -- so: `foo` becomes `gnatcov_rts_witness_generic(buffer, sco_id, foo)`. + + --------------------------------- + -- Wrap_In_CXX_Generic_Witness -- + --------------------------------- + + procedure Wrap_In_CXX_Generic_Witness (SR : Source_Range_T) + is + Witness_Params : constant String := + Statement_Buffer_Symbol (UIC.Instrumented_Unit) + & Buffers_Subscript (Buffers_Index) & ", " & Img (Bit); + begin + CX_Rewriter_Insert_Text_After + (Rew => UIC.Rewriter, + Loc => Get_Range_Start (SR), + Insert => "gnatcov_rts_witness_generic (" + & Witness_Params & ", "); + + CX_Rewriter_Insert_Text_Before + (Rew => UIC.Rewriter, + Loc => Get_Range_End (SR), + Insert => ")"); + end Wrap_In_CXX_Generic_Witness; + begin -- Insert the call to the witness function: as a foregoing statement if -- SS.Statement is a statement, or as a previous expression (using the @@ -1389,26 +1415,16 @@ package body Instrument.C is -- -- `witness_generic(buf, id, foo).bar()` - declare - Base_Sloc_Range : constant Source_Range_T := - Get_CXX_Member_Call_Expr_Base_Sloc_Range (SS.Statement); - Witness_Params : constant String := - Statement_Buffer_Symbol (UIC.Instrumented_Unit) - & Buffers_Subscript (Buffers_Index) & ", " & Img (Bit); - begin - CX_Rewriter_Insert_Text_After - (Rew => UIC.Rewriter, - Loc => Get_Range_Start (Base_Sloc_Range), - Insert => "gnatcov_rts_witness_generic (" - & Witness_Params & ", "); - - CX_Rewriter_Insert_Text_Before - (Rew => UIC.Rewriter, - Loc => Get_Range_End (Base_Sloc_Range), - Insert => ")"); - end; + Wrap_In_CXX_Generic_Witness + (Get_CXX_Member_Call_Expr_Base_Sloc_Range (SS.Statement)); - null; + when Instr_StructField_CallExpr => + + -- In case we are instrumenting the call from a function pointer + -- that is a field from a struct. + + Wrap_In_CXX_Generic_Witness + (Get_Struct_Field_Call_Expr_Base_Sloc_Range (SS.Statement)); end case; end Insert_Statement_Witness; @@ -2050,6 +2066,7 @@ package body Instrument.C is begin if Is_Prefixed_CXX_Member_Call_Expr (C) then + -- C++ only. -- If we are instrumenting a method call like `foo.bar()`, -- adjust the SCO to `.bar`, and set a specific -- instrumentation scheme. @@ -2066,6 +2083,16 @@ package body Instrument.C is To := Sloc (Get_Range_End (CX_Source_Range)); Instr_Scheme := Instr_Prefixed_CXXMemberCallExpr; end; + elsif Is_Struct_Field_Call_Expr (C) then + + declare + CX_Source_Range : constant Source_Range_T := + Get_Struct_Field_Call_Expr_SCO_Sloc_Range (C); + begin + From := Sloc (Get_Range_Start (CX_Source_Range)); + To := Sloc (Get_Range_End (CX_Source_Range)); + Instr_Scheme := Instr_StructField_CallExpr; + end; end if; UIC.Pass.Append_SCO diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 6a4483d2d..7d58eebea 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -165,7 +165,8 @@ package Instrument.C is (Instr_Stmt, Instr_Expr, Instr_In_Compound, - Instr_Prefixed_CXXMemberCallExpr); + Instr_Prefixed_CXXMemberCallExpr, + Instr_StructField_CallExpr); -- Depending on the statement construct, we can instrument it either with -- another statement right before (Instr_Stmt), which is the case for most -- statements: From e8584d9d2f01b068dfabcf11015ba0a2fec6a3d4 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 3 Apr 2025 12:46:08 +0200 Subject: [PATCH 1184/1483] instr-c(funcall): Handle call of function pointer as struct field for C Implementation uses a statement expression, which is a non standard gcc/clang extension. --- tools/gnatcov/clang-extensions.ads | 10 ++++ tools/gnatcov/clang-wrapper.cc | 42 +++++++++++----- tools/gnatcov/instrument-c.adb | 78 ++++++++++++++++++++++++++++-- 3 files changed, 115 insertions(+), 15 deletions(-) diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index 974bbc85e..5caacd3d2 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -179,6 +179,16 @@ package Clang.Extensions is -- Given the expression is `Foo.Bar(Baz)`, it will return the source range -- for `Foo`. + function Get_Struct_Field_Call_Expr_Base_Expr + (C : Cursor_T) return Cursor_T + with + Import, + Convention => C, + External_Name => "clang_getStructFieldCallExprBaseExpr"; + -- Given the expression is `Foo.Bar(Baz)`, it will return the Base + -- expression of the MemberExpr underlying the call, meaning the `Foo` + -- expression. + function Is_Constexpr (C : Cursor_T) return Boolean with Inline; function Unwrap (C : Cursor_T) return Cursor_T diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index 7a2577f0a..cdd4f6bc0 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -458,6 +458,23 @@ getMemberExprFromCallExpr (const CallExpr *CE) return cast (callee); } +static const Expr * +getBaseExprFromStructFieldCallExpr (CXCursor C) +{ + if (!clang_isExpression (C.kind)) + return nullptr; + + const Expr *E = getCursorExpr (C); + if (E->getStmtClass () != Stmt::CallExprClass) + return nullptr; + + const MemberExpr *ME = getMemberExprFromCallExpr (cast (E)); + if (ME == nullptr) + return nullptr; + + return ME->getBase (); +} + extern "C" CXSourceRange clang_getCXXMemberCallExprSCOSlocRange (CXCursor C) { @@ -524,24 +541,27 @@ clang_getCXXMemberCallExprBaseSlocRange (CXCursor C) extern "C" CXSourceRange clang_getStructFieldCallExprBaseSlocRange (CXCursor C) { - if (!clang_isExpression (C.kind)) + const Expr *base = getBaseExprFromStructFieldCallExpr (C); + if (base == nullptr) return clang_getNullRange (); - const Expr *E = getCursorExpr (C); - if (E->getStmtClass () != Stmt::CallExprClass) - return clang_getNullRange (); - - const MemberExpr *ME = getMemberExprFromCallExpr (cast (E)); - if (ME == nullptr) - return clang_getNullRange (); - - const SourceLocation start_loc = ME->getBase ()->getBeginLoc (); - const SourceLocation end_loc = ME->getBase ()->getEndLoc (); + const SourceLocation start_loc = base->getBeginLoc (); + const SourceLocation end_loc = base->getEndLoc (); return translateSourceRange (getContext (C), SourceRange (start_loc, end_loc)); } +extern "C" CXCursor +clang_getStructFieldCallExprBaseExpr (CXCursor C) +{ + const Expr *base = getBaseExprFromStructFieldCallExpr (C); + if (base == nullptr) + return clang_getNullCursor (); + + return MakeCXCursorWithNull (base, C); +} + extern "C" CXSourceRange clang_getFunctionSignatureSloc (CXCursor C) { diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 68d8adc0e..17fa80e72 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -1356,6 +1356,18 @@ package body Instrument.C is -- Wraps the given source range inside a generic witness function like -- so: `foo` becomes `gnatcov_rts_witness_generic(buffer, sco_id, foo)`. + procedure Wrap_Struct_Call_In_Stmt_Expr (C : Cursor_T); + -- In C, transform a `foo->bar(args)` struct field call expr into + -- + -- ({ + -- tmp = ; + -- witness(bar); + -- tmp->bar(); + -- }) + -- + -- NOTE: this creates a statement expression construct, which is a GCC + -- extension (clang supports it too) not defined by ISO nor ANSI C. + --------------------------------- -- Wrap_In_CXX_Generic_Witness -- --------------------------------- @@ -1378,6 +1390,49 @@ package body Instrument.C is Insert => ")"); end Wrap_In_CXX_Generic_Witness; + ----------------------------------- + -- Wrap_Struct_Call_In_Stmt_Expr -- + ----------------------------------- + + procedure Wrap_Struct_Call_In_Stmt_Expr (C : Cursor_T) is + Base_SR : constant Source_Range_T := + Get_Struct_Field_Call_Expr_Base_Sloc_Range (C); + + Cursor_Type : constant String := + Get_Type_Spelling (Get_Cursor_Type + (Get_Struct_Field_Call_Expr_Base_Expr (C))); + -- Eventually get rid of this if we plan to only support + -- language version over C23, as we can just use "auto" as + -- in C++ in this case. + + begin + CX_Rewriter_Insert_Text_After + (Rew => UIC.Rewriter, + Loc => Get_Range_Start (Base_SR), + Insert => "__extension__ ({ " & Cursor_Type & " tmp = "); + -- `__extension__` at the beginning of the rewrite mentions to the + -- compiler that this is an expected language extension + -- (statement expression). This prevents `-pedantic` from raising the + -- error. The extension has been supported by gcc, clang and msvc + -- for many years, so that should not cause any problem. + + CX_Rewriter_Insert_Text_Before + (Rew => UIC.Rewriter, + Loc => Get_Range_End (Base_SR), + Insert => + "; " + & Make_Statement_Witness (UIC, Buffers_Index, Bit) + & " tmp" + ); + + CX_Rewriter_Insert_Text_Before + (Rew => UIC.Rewriter, + Loc => End_Sloc (C), + Insert => ";})"); + end Wrap_Struct_Call_In_Stmt_Expr; + + -- Start processing of Instrument_Statement_Witness + begin -- Insert the call to the witness function: as a foregoing statement if -- SS.Statement is a statement, or as a previous expression (using the @@ -1421,10 +1476,19 @@ package body Instrument.C is when Instr_StructField_CallExpr => -- In case we are instrumenting the call from a function pointer - -- that is a field from a struct. - - Wrap_In_CXX_Generic_Witness - (Get_Struct_Field_Call_Expr_Base_Sloc_Range (SS.Statement)); + -- that is a field from a struct, the instrumentation depends + -- on whether we are in C or C++. + -- For C++, we use the same generic witness instrumentation as for + -- member call exprs. + -- For C, we wrap the base of the member expression in a statement + -- expression. + + if Get_Cursor_Language (SS.Statement) = Language_C_Plus_Plus then + Wrap_In_CXX_Generic_Witness + (Get_Struct_Field_Call_Expr_Base_Sloc_Range (SS.Statement)); + else + Wrap_Struct_Call_In_Stmt_Expr (SS.Statement); + end if; end case; end Insert_Statement_Witness; @@ -2085,6 +2149,12 @@ package body Instrument.C is end; elsif Is_Struct_Field_Call_Expr (C) then + -- C and C++. + -- We are instrumenting a function call whose callee is + -- a member from a struct, as function pointer. + -- This language feature can lead to call chains as well, + -- which we need to handle properly. + declare CX_Source_Range : constant Source_Range_T := Get_Struct_Field_Call_Expr_SCO_Sloc_Range (C); From 9ba40355cf7a775af6927d7fab6472cf5c7db40f Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 3 Apr 2025 14:27:02 +0200 Subject: [PATCH 1185/1483] test(instr-c): Add tests for call of function pointer as struct field in C/C++ --- .../src/test_abort.c | 44 +++++++++++++++++++ .../c/function-pointer-call-chain/test.py | 13 ++++++ .../src/test_abort.cpp | 44 +++++++++++++++++++ .../cpp/function-pointer-call-chain/test.py | 13 ++++++ 4 files changed, 114 insertions(+) create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.py create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/src/test_abort.cpp create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.py diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c new file mode 100644 index 000000000..7f16f7fe3 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c @@ -0,0 +1,44 @@ +#include + +struct list; + +typedef struct list *(*fct_type) (); + +struct list +{ + struct list *next; + int data; + fct_type get_head; +}; + +static struct list *HEAD = (struct list *) 0; + +struct list * +head_abort () +{ + /* GNATCOV_DUMP_BUFFERS */ + exit (0); // # not-call + return HEAD; // # not-reached +} + +int +main (void) +{ + struct list end = { .next = (struct list *) 0, .data = 1, .get_head = NULL }; + + struct list start = { .next = &end, .data = 1, .get_head = head_abort }; + + HEAD = &start; + + int x = (*HEAD) // # statement + .get_head () // # first_call + ->get_head () // # second_call + ->data; +} + +//# test_abort.c +// /statement/ l+ ## 0 +// /first_call/ l+ ## 0 +// /second_call/ l! ## c- +// /not-reached/ l- ## s- +// /not-call/ l- ## s-,c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.py new file mode 100644 index 000000000..98209dcc0 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.py @@ -0,0 +1,13 @@ +""" +Make sure that the instrumentation of calls of a struct member function pointer +is correctly instrumented in C. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run( + covcontrol=CovControl(dump_trigger="manual") +) +thistest.result() diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/src/test_abort.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/src/test_abort.cpp new file mode 100644 index 000000000..ec1be9d57 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/src/test_abort.cpp @@ -0,0 +1,44 @@ +#include + +struct list; + +typedef struct list *(*fct_type) (); + +struct list +{ + struct list *next; + int data; + fct_type get_head; +}; + +static struct list *HEAD = (struct list *) 0; + +struct list * +head_abort () +{ + /* GNATCOV_DUMP_BUFFERS */ + exit (0); // # not-call + return HEAD; // # not-reached +} + +int +main (void) +{ + struct list end = { .next = (struct list *) 0, .data = 1, .get_head = NULL }; + + struct list start = { .next = &end, .data = 1, .get_head = head_abort }; + + HEAD = &start; + + int x = (*HEAD) // # statement + .get_head () // # first_call + ->get_head () // # second_call + ->data; +} + +//# test_abort.cpp +// /statement/ l+ ## 0 +// /first_call/ l+ ## 0 +// /second_call/ l! ## c- +// /not-reached/ l- ## s- +// /not-call/ l- ## s-,c- diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.py new file mode 100644 index 000000000..811552264 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.py @@ -0,0 +1,13 @@ +""" +Make sure that the instrumentation of calls of a struct member function pointer +is correctly instrumented in C++. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT, CovControl +from SUITE.context import thistest + +TestCase(category=CAT.stmt, fun_call_lvl=True).run( + covcontrol=CovControl(dump_trigger="manual") +) +thistest.result() From bf2845126483d65e7d624ce2a79900173009af20 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Apr 2025 11:42:32 +0200 Subject: [PATCH 1186/1483] Revert "CI: use a pre-GPR2 transition gnatcov for self-instrumentation" This reverts commit 8baa23b24d538b64b47e726f4eeb5ed837368305. --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b4ddd866b..67e84bb02 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -45,7 +45,7 @@ build: - anod build --smart-rebuild --deps-only gnatcov $ACI_TRACK_QUALIFIER # 2. Install vanilla gnatcov from cathod - - anod install gnatcov $ACI_TRACK_QUALIFIER --build-date=20250415 + - anod install gnatcov $ACI_TRACK_QUALIFIER --latest # 3. Build using anod, but minimally as all dependencies are supposed to be # already built/installed via 1, but we don't want to re-build the From 35d46082a40383b2fd561e6e620dcf13bc69d5e3 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Apr 2025 13:48:25 +0000 Subject: [PATCH 1187/1483] paths.ads/paths.adb: minor reformattings --- tools/gnatcov/paths.adb | 5 ++--- tools/gnatcov/paths.ads | 5 +++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index c5e0a6239..5985245be 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -83,9 +83,8 @@ package body Paths is function Canonicalize_Filename (Filename : String; - Lower : Boolean := True) return String + Lower : Boolean := True) return String is - -- Start with a very basic normalization step as for globbing -- patterns. If we have a Windows path but are not on a Windows -- host, stop there as there's not much more we can reasonably @@ -107,7 +106,7 @@ package body Paths is function Canonicalize_Filename (Filename : String; - Lower : Boolean := True) return String_Access is + Lower : Boolean := True) return String_Access is begin return new String'(Canonicalize_Filename (Filename, Lower)); end Canonicalize_Filename; diff --git a/tools/gnatcov/paths.ads b/tools/gnatcov/paths.ads index b5f9205b8..cc0c85726 100644 --- a/tools/gnatcov/paths.ads +++ b/tools/gnatcov/paths.ads @@ -45,13 +45,14 @@ package Paths is function Canonicalize_Filename (Filename : String; - Lower : Boolean := True) return String; + Lower : Boolean := True) return String; function Canonicalize_Filename (Filename : String; - Lower : Boolean := True) return String_Access; + Lower : Boolean := True) return String_Access; -- Assuming Filename is a full pathname to a file, return a normalized -- version of it such that different references to the same file map to the -- same canonical string as much as possible. + -- -- On Windows, if the Lower argument is true, the path will also be -- lowercased. If it's false, the original case is kept. From 190c88f90019a203932d76a7d8f69e4198c56368 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Apr 2025 14:18:09 +0000 Subject: [PATCH 1188/1483] Preserve the original source filename casing in reports Enhance the computation of `Unique_Name` components in `files_table.adb` so that, when using only the source file basename (i.e. the most common case), the original source file casing is preserved. This unique name is used to generate source-specific files in annotated source reports (xcov, html, ...). --- tools/gnatcov/files_table.adb | 18 ++++++++++++++++-- tools/gnatcov/paths.adb | 18 ++++++++++++++++++ tools/gnatcov/paths.ads | 5 +++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 149c4d62b..6e081902a 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -1304,7 +1304,7 @@ package body Files_Table is ---------------------- procedure Grow_Unique_Name (File : File_Info_Access) is - Full : String renames File.Full_Name.all; + Full : String renames File.Preserved_Full_Name.all; procedure Get_Previous_Separator (Index : in out Positive); -- Assuming index is a valid index in Full, decrease it until either @@ -1433,8 +1433,22 @@ package body Files_Table is if Alias_Set.Length = 1 then declare File : File_Info renames Alias_Set.First_Element.all; + + -- If available, extract the basename from the preserved full + -- name so that the original casing is preserved (.Simple_Name + -- is case folded on Windows). Since that preserved name may be + -- a Windows absolute name while we are running on a Unix + -- system, using the regular filename manipulation functions + -- will not always work: implement basename extraction to + -- handle both. + + Name : constant String_Access := + (if File.Preserved_Full_Name = null + then File.Simple_Name + else File.Preserved_Full_Name); begin - File.Unique_Name := new String'(File.Simple_Name.all); + File.Unique_Name := + new String'(Platform_Independent_Basename (Name.all)); end; end if; diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index 5985245be..50ccce78a 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -262,6 +262,24 @@ package body Paths is or else Is_Absolute_Windows_Path (Path); end Is_Absolute_Path; + ----------------------------------- + -- Platform_Independent_Basename -- + ----------------------------------- + + function Platform_Independent_Basename (Filename : String) return String is + Likely_Windows : constant Boolean := Likely_Windows_Path (Filename); + First : Natural := Filename'Last; + begin + while Filename'First < First + and then Filename (First - 1) /= '/' + and then (not Likely_Windows or else Filename (First - 1) /= '\') + loop + First := First - 1; + end loop; + + return Filename (First .. Filename'Last); + end Platform_Independent_Basename; + ------------------------- -- Likely_Windows_Path -- ------------------------- diff --git a/tools/gnatcov/paths.ads b/tools/gnatcov/paths.ads index cc0c85726..e93acf22d 100644 --- a/tools/gnatcov/paths.ads +++ b/tools/gnatcov/paths.ads @@ -71,6 +71,11 @@ package Paths is -- of the service, this one always matches both Windows or Unix file path -- flavors. + function Platform_Independent_Basename (Filename : String) return String; + -- Regardless of the platfrom on which gnatcov runs, extract the basename + -- of the given absolute filename, which may be a Windows-style filename or + -- a Unix-style one. + -- TODO??? Handle Unicode file names function Workaround_Simple_Name (Path : String) return String; From 8de4547cf511c7a6fe8bce0ba523454faa98a68d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Apr 2025 15:48:28 +0000 Subject: [PATCH 1189/1483] 92-long_slugs: update now that report use original sources casing --- testsuite/tests/92-long_slugs/test.py | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/testsuite/tests/92-long_slugs/test.py b/testsuite/tests/92-long_slugs/test.py index d0938bd72..3501e0a8b 100644 --- a/testsuite/tests/92-long_slugs/test.py +++ b/testsuite/tests/92-long_slugs/test.py @@ -66,16 +66,7 @@ # have the same case as the original filename. check_xcov_reports( - "obj", - { - "main.c.xcov": {"+": {6}}, - ( - unit_name.lower() - if "windows" in thistest.env.host.platform - else unit_name - ) - + ".c.xcov": {"+": {6}}, - }, + "obj", {"main.c.xcov": {"+": {6}}, f"{unit_name}.c.xcov": {"+": {6}}} ) thistest.result() From aa75020e8688e56c0c736af1013feb2c4fca79b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 15 May 2024 14:56:31 +0000 Subject: [PATCH 1190/1483] Add command line argument for LLVM JSON checkpoint files --- tools/gnatcov/command_line.ads | 8 +++ tools/gnatcov/gnatcov_bits_specific.adb | 66 ++++++++++++++----------- tools/gnatcov/llvm_json_checkpoints.adb | 28 +++++++++++ tools/gnatcov/llvm_json_checkpoints.ads | 25 ++++++++++ 4 files changed, 99 insertions(+), 28 deletions(-) create mode 100644 tools/gnatcov/llvm_json_checkpoints.adb create mode 100644 tools/gnatcov/llvm_json_checkpoints.ads diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 2088a30ac..5e3ca7226 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -183,6 +183,7 @@ package Command_Line is Opt_Source_Search, Opt_Trace, Opt_Checkpoint, + Opt_LLVM_JSON_Checkpoint, Opt_Ignore_Source_Files, Opt_Shared_Object, Opt_Restricted_To_Languages, @@ -1552,6 +1553,13 @@ package Command_Line is Help => "Specify checkpointed coverage information to load.", Commands => (Cmd_Coverage => True, others => False), Internal => False), + Opt_LLVM_JSON_Checkpoint => Create + (Long_Name => "--llvm-json-checkpoint", + Pattern => "[CHECKPOINT|@LISTFILE]", + Help => "Specify a list of json files containing" + & "LLVM coverage information to load.", + Commands => (Cmd_Coverage => True, others => False), + Internal => False), Opt_Ignore_Source_Files => Create (Long_Name => "--ignore-source-files", Pattern => "[FILE|@LISTFILE]", diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index b6f5b764b..535404536 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -47,6 +47,7 @@ with CFG_Dump; with Calendar_Utils; with Check_SCOs; with Checkpoints; +with LLVM_JSON_Checkpoints; with Command_Line; use Command_Line; use Command_Line.Parser; with Convert; @@ -104,34 +105,35 @@ procedure GNATcov_Bits_Specific is -- Results of the command line processing. It is filled by -- Process_Arguments once Switches.Args reached its final state. - Annotation : Annotation_Formats_Arr renames + Annotation : Annotation_Formats_Arr renames Annotations.Annotation; - Trace_Inputs : Requested_Trace_Vectors.Vector; - Exe_Inputs : String_Vectors.Vector; - Obj_Inputs : String_Vectors.Vector; - ALIs_Inputs : String_Vectors.Vector; - Routines_Inputs : String_Vectors.Vector; - Checkpoints_Inputs : String_Vectors.Vector; - SID_Inputs : String_Vectors.Vector; - Ignored_Source_Files : String_Vectors.Vector; - Files_Of_Interest : String_Vectors.Vector; - Compiler_Drivers : String_Vectors.Vector; - Source_Rebase_Inputs : String_Vectors.Vector; - Source_Search_Inputs : String_Vectors.Vector; - Subprograms_Inputs : String_Vectors.Vector; - Text_Start : Pc_Type := 0; - Output : String_Access := null; - Tag : String_Access := null; - Kernel : String_Access := null; - Save_Checkpoint : String_Access := null; - Eargs : String_Vectors.Vector; - Executable_Path : String_Access := null; - Locations_Inputs : Object_Locations.User_Locations; - CFG_Output_Format : CFG_Dump.Output_Format := CFG_Dump.None; - Keep_Edges : Boolean := False; - SO_Inputs : SO_Set_Type; - Keep_Reading_Traces : Boolean := False; - Emit_Report : Boolean := True; + Trace_Inputs : Requested_Trace_Vectors.Vector; + Exe_Inputs : String_Vectors.Vector; + Obj_Inputs : String_Vectors.Vector; + ALIs_Inputs : String_Vectors.Vector; + Routines_Inputs : String_Vectors.Vector; + Checkpoints_Inputs : String_Vectors.Vector; + LLVM_JSON_Ckpt_Inputs : String_Vectors.Vector; + SID_Inputs : String_Vectors.Vector; + Ignored_Source_Files : String_Vectors.Vector; + Files_Of_Interest : String_Vectors.Vector; + Compiler_Drivers : String_Vectors.Vector; + Source_Rebase_Inputs : String_Vectors.Vector; + Source_Search_Inputs : String_Vectors.Vector; + Subprograms_Inputs : String_Vectors.Vector; + Text_Start : Pc_Type := 0; + Output : String_Access := null; + Tag : String_Access := null; + Kernel : String_Access := null; + Save_Checkpoint : String_Access := null; + Eargs : String_Vectors.Vector; + Executable_Path : String_Access := null; + Locations_Inputs : Object_Locations.User_Locations; + CFG_Output_Format : CFG_Dump.Output_Format := CFG_Dump.None; + Keep_Edges : Boolean := False; + SO_Inputs : SO_Set_Type; + Keep_Reading_Traces : Boolean := False; + Emit_Report : Boolean := True; Dump_Units_Filename : String_Access := null; -- If null, dump the list of units of interest as a section in the report @@ -248,6 +250,7 @@ procedure GNATcov_Bits_Specific is if Source_Coverage_Enabled and then Checkpoints_Inputs.Is_Empty + and then LLVM_JSON_Ckpt_Inputs.Is_Empty and then SID_Inputs.Is_Empty and then ALIs_Inputs.Is_Empty and then not Args.String_Args (Opt_Project).Present @@ -579,6 +582,7 @@ procedure GNATcov_Bits_Specific is end if; Copy_Arg_List (Opt_Checkpoint, Checkpoints_Inputs); + Copy_Arg_List (Opt_LLVM_JSON_Checkpoint, LLVM_JSON_Ckpt_Inputs); Copy_Arg_List (Opt_Ignore_Source_Files, Ignored_Source_Files); Copy_Arg_List (Opt_Files, Files_Of_Interest); @@ -2314,7 +2318,9 @@ begin end Process_Trace_For_Src_Coverage; begin - if Checkpoints_Inputs.Is_Empty then + if Checkpoints_Inputs.Is_Empty + and then LLVM_JSON_Ckpt_Inputs.Is_Empty + then Check_Traces_Available; end if; for Filename of Exe_Inputs loop @@ -2366,6 +2372,10 @@ begin Checkpoints.Checkpoint_Load (+Filename); end loop; + for Filename of LLVM_JSON_Ckpt_Inputs loop + LLVM_JSON_Checkpoints.JSON_Load (+Filename); + end loop; + -- Now determine coverage according to the requested metric (for -- source coverage, complete coverage information has been determined -- when loading traces above). diff --git a/tools/gnatcov/llvm_json_checkpoints.adb b/tools/gnatcov/llvm_json_checkpoints.adb new file mode 100644 index 000000000..12c21e4da --- /dev/null +++ b/tools/gnatcov/llvm_json_checkpoints.adb @@ -0,0 +1,28 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2025, 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.Text_IO; use Ada.Text_IO; + +package body LLVM_JSON_Checkpoints is + + procedure JSON_Load (Filename : String) is + begin + Put_Line ("[DEBUG(dprn)] Loading " & Filename); + end JSON_Load; + +end LLVM_JSON_Checkpoints; \ No newline at end of file diff --git a/tools/gnatcov/llvm_json_checkpoints.ads b/tools/gnatcov/llvm_json_checkpoints.ads new file mode 100644 index 000000000..b564feaf5 --- /dev/null +++ b/tools/gnatcov/llvm_json_checkpoints.ads @@ -0,0 +1,25 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2025, 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. -- +------------------------------------------------------------------------------ + +package LLVM_JSON_Checkpoints is + + procedure JSON_Load (Filename : String); + -- Read a JSON file containing LLVM coverage data + -- and populate internal structures with it. + +end LLVM_JSON_Checkpoints; From 356ff1c00495cf23e19f56b192171aa39fce878a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 17 May 2024 08:28:01 +0000 Subject: [PATCH 1191/1483] coverage-source: Move "Evaluation_(Vector|Set)" declarations to the spec --- tools/gnatcov/coverage-source.adb | 9 --------- tools/gnatcov/coverage-source.ads | 9 +++++++++ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index ee144d356..f6ba33de8 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -16,8 +16,6 @@ -- 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; @@ -33,7 +31,6 @@ 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; @@ -61,12 +58,6 @@ package body Coverage.Source is -- 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, diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 4a8417564..8b86a86f5 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -16,6 +16,8 @@ -- of the license. -- ------------------------------------------------------------------------------ +with Ada.Containers.Ordered_Sets; +with Ada.Containers.Vectors; with Ada.Text_IO; use Ada.Text_IO; with Checkpoints; use Checkpoints; @@ -23,6 +25,7 @@ with Files_Table; use Files_Table; with Instrument; use Instrument; with Instrument.Input_Traces; use Instrument.Input_Traces; with Logging; +with MC_DC; use MC_DC; with SC_Obligations; use SC_Obligations; with Traces; use Traces; with Traces_Names; use Traces_Names; @@ -30,6 +33,12 @@ with Traces_Lines; use Traces_Lines; package Coverage.Source is + package Evaluation_Vectors is new Ada.Containers.Vectors + (Index_Type => Natural, + Element_Type => Evaluation); + + package Evaluation_Sets is new Ada.Containers.Ordered_Sets (Evaluation); + Ignore_Exemptions_Trace : constant Logging.GNATCOLL_Trace := Logging.Create_Trace ("IGNORE_EXEMPTIONS"); -- Note that enabling this trace will make gnatcov ignore source coverage From 1a012297cbc284465a9c5bda65d617e1b1d15450 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Mon, 3 Jun 2024 15:57:57 +0000 Subject: [PATCH 1192/1483] json: Add Reading utility functions which abort the program when failing --- tools/gnatcov/json.adb | 104 +++++++++++++++++++++++++++++++++++++++++ tools/gnatcov/json.ads | 20 ++++++++ 2 files changed, 124 insertions(+) diff --git a/tools/gnatcov/json.adb b/tools/gnatcov/json.adb index aca40ae1c..caabd73de 100644 --- a/tools/gnatcov/json.adb +++ b/tools/gnatcov/json.adb @@ -16,8 +16,11 @@ -- of the license. -- ------------------------------------------------------------------------------ +with Ada.Exceptions; + with GNAT.Strings; use GNAT.Strings; +with Outputs; use Outputs; with Strings; use Strings; with Text_Files; @@ -50,11 +53,112 @@ package body JSON is function Read (File : Virtual_File) return Read_Result is Content : String_Access := File.Read_File; begin + if Content = null then + Fatal_Error ("Could not read file '" + & Display_Full_Name (File) & "'"); + end if; return Parsed_JSON : constant Read_Result := GNATCOLL.JSON.Read (Content.all) do Free (Content); end return; + exception + when ex : Constraint_Error => + Fatal_Error (Ada.Exceptions.Exception_Message (ex)); end Read; + --------------- + -- Read_File -- + --------------- + + function Read_File (Filename : String) return JSON_Value is + Parsed_JSON : constant Read_Result := JSON.Read (Filename); + begin + if not Parsed_JSON.Success then + Fatal_Error + ("Parsing error: " & Format_Parsing_Error (Parsed_JSON.Error)); + end if; + return Parsed_JSON.Value; + end Read_File; + + ------------------------------- + -- JSON_Value Read Utilities -- + ------------------------------- + + function Get_Child (Value : JSON_Value; Field : String) + return JSON_Value; + + function Get_Child (Value : JSON_Value; Field : String) + return JSON_Value is + begin + if not Value.Has_Field (Field) then + Fatal_Error ("Expected field '" & Field & "' is missing."); + end if; + return Value.Get (Field); + end Get_Child; + + --------------- + -- Child_Int -- + --------------- + + function Child_Int (Value : JSON_Value; Field : String) + return Integer is + Child : constant JSON_Value := Get_Child (Value, Field); + begin + if Child.Kind /= JSON_Int_Type then + Fatal_Error + ("Field is expected to be of type " + & JSON_Value_Type'Image (JSON_Int_Type)); + end if; + return Child.Get; + end Child_Int; + + ------------------ + -- Child_String -- + ------------------ + + function Child_String (Value : JSON_Value; Field : String) + return UTF8_String is + Child : constant JSON_Value := Get_Child (Value, Field); + begin + if Child.Kind /= JSON_String_Type then + Fatal_Error + ("Field is expected to be of type " + & JSON_Value_Type'Image (JSON_String_Type)); + end if; + return Child.Get; + end Child_String; + + ------------------ + -- Child_Array -- + ------------------ + + function Child_Array (Value : JSON_Value; Field : String) + return JSON_Array is + Child : constant JSON_Value := Get_Child (Value, Field); + begin + if Child.Kind /= JSON_Array_Type then + Fatal_Error + ("Field is expected to be of type " + & JSON_Value_Type'Image (JSON_Array_Type)); + end if; + return Child.Get; + end Child_Array; + + ----------------------- + -- Array_Nth_Integer -- + ----------------------- + + function Array_Nth_Integer (List : JSON_Array; N : Integer) + return Integer is + Child : constant JSON_Value := Get (List, N); + begin + if Child.Kind /= JSON_Int_Type then + Fatal_Error + ("Field is expected to be of type " + & JSON_Value_Type'Image (JSON_Int_Type)); + end if; + return Child.Get; + end Array_Nth_Integer; + end JSON; diff --git a/tools/gnatcov/json.ads b/tools/gnatcov/json.ads index a9fedfcc2..93caae71f 100644 --- a/tools/gnatcov/json.ads +++ b/tools/gnatcov/json.ads @@ -35,4 +35,24 @@ package JSON is function Read (File : Virtual_File) return Read_Result; -- Likewise, but starting from a Virtual_File + function Read_File (Filename : String) return JSON_Value; + -- Read and parse a JSON filename. Exit with Fatal_Error in case of fail. + -- Return the top-level JSON value. + + ------------------------------- + -- JSON_Value Read Utilities -- + ------------------------------- + + -- The following functions get internal fields and abort the program if + -- The value does not exist, of if it is of the wrong type. + + function Child_Int (Value : JSON_Value; Field : String) return Integer; + + function Child_String + (Value : JSON_Value; Field : String) return UTF8_String; + + function Child_Array (Value : JSON_Value; Field : String) return JSON_Array; + + function Array_Nth_Integer (List : JSON_Array; N : Integer) return Integer; + end JSON; From 4f3e92e147a955a032713657a1e601fd4e4a7b30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 29 May 2024 09:55:52 +0000 Subject: [PATCH 1193/1483] slocs: Add helper functions for Local_Source_Location_Range - Add Contained_In function to check for Sloc inclusion - Add Image function --- tools/gnatcov/slocs.adb | 19 +++++++++++++++++++ tools/gnatcov/slocs.ads | 7 +++++++ 2 files changed, 26 insertions(+) diff --git a/tools/gnatcov/slocs.adb b/tools/gnatcov/slocs.adb index cb3b8e006..22a4c73c9 100644 --- a/tools/gnatcov/slocs.adb +++ b/tools/gnatcov/slocs.adb @@ -68,6 +68,25 @@ package body Slocs is and then not (L.Last_Sloc <= R.Last_Sloc))); + ----------- + -- Image -- + ----------- + + function Image (SLOC : Local_Source_Location_Range) return String + is + Result : constant Unbounded_String := + +("(" & Image (SLOC.First_Sloc) & " -> " + & Image (SLOC.Last_Sloc) & ")"); + begin + return +Result; + end Image; + + function Contained_In (C, P : Local_Source_Location_Range) return Boolean is + begin + return P.First_Sloc <= C.First_Sloc + and then C.Last_Sloc <= P.Last_Sloc; + end Contained_In; + function "<" (L, R : Source_Location) return Boolean is begin -- Note: No_Location must sort higher than any specific source location, diff --git a/tools/gnatcov/slocs.ads b/tools/gnatcov/slocs.ads index b787dd8cc..9656d2144 100644 --- a/tools/gnatcov/slocs.ads +++ b/tools/gnatcov/slocs.ads @@ -52,6 +52,13 @@ package Slocs is -- Sort on lower bound first, then REVERSED on higher bound, so that -- for two nested ranges, the innermost one always sorts higher. + function Image (SLOC : Local_Source_Location_Range) return String; + -- Return a string in the form `(LL:CC -> LL:CC)`. + + function Contained_In (C, P : Local_Source_Location_Range) return Boolean; + -- Return True if C(hild) bounds are contained in P(arent). + -- The relation is reflexive : `Contained_In (X, X)` is always true. + No_Local_Range : constant Local_Source_Location_Range := (No_Local_Location, No_Local_Location); From a1886bdd82f19203e906b5e2df6ad636d16b1506 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Thu, 16 May 2024 10:37:11 +0000 Subject: [PATCH 1194/1483] llvm-json: Parse the JSON file into a Report object --- tools/gnatcov/llvm_json_checkpoints.adb | 622 +++++++++++++++++++++++- tools/gnatcov/llvm_json_checkpoints.ads | 71 ++- 2 files changed, 688 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/llvm_json_checkpoints.adb b/tools/gnatcov/llvm_json_checkpoints.adb index 12c21e4da..2dcd1d900 100644 --- a/tools/gnatcov/llvm_json_checkpoints.adb +++ b/tools/gnatcov/llvm_json_checkpoints.adb @@ -14,15 +14,629 @@ -- 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. -- +-- -- +-- LLVM coverage report interface. Relies on the LLVM_JSON trace adapter. -- ------------------------------------------------------------------------------ -with Ada.Text_IO; use Ada.Text_IO; +with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; + +with GNATCOLL.JSON; use GNATCOLL.JSON; +with GNATCOLL.Traces; use GNATCOLL.Traces; + +with JSON; +with MC_DC; +with Outputs; use Outputs; + +-- The exporter tool dumps JSON files that have the following architecture: +-- { +-- "data": [ +-- { +-- "filename": str, +-- "functions": [ +-- { +-- "name": str, +-- "demangled_name": str, +-- "code_regions": [ +-- { +-- "count": int, +-- "kind": str, +-- "span": [start_line, start_col, end_line, end_col] +-- }* +-- ], +-- "branch_regions": [ +-- { +-- "true_count": int, +-- "false_count": int, +-- "kind": str, +-- "span": [start_line, start_col, end_line, end_col] +-- }* +-- ], +-- "mcdc_records": [ +-- { +-- "span": [start_line, start_col, end_line, end_col], +-- "num_conditions": int, +-- "test_vectors": [ +-- { +-- "result": (0, 1) for False or True, +-- "vector": +-- list of (-1, 0, 1) for DontCare, False, True +-- }* +-- ] +-- }* +-- ] +-- }* +-- ] +-- }* +-- ] +-- } package body LLVM_JSON_Checkpoints is - procedure JSON_Load (Filename : String) is + type Parsed_MCDC_Record is record + Span : Local_Source_Location_Range; + Num_Conditions : Natural; + Test_Vectors : Evaluation_Vectors.Vector; + end record; + + type Parsed_Branch_Region is record + Span : Local_Source_Location_Range; + T_Exec_Count : Natural; + F_Exec_Count : Natural; + end record; + + type Parsed_Code_Region is record + Span : Local_Source_Location_Range; + Execution_Count : Natural; + end record; + + -------------------------- + -- Forward declarations -- + -------------------------- + + function Count_Cond_For_Dec + (Regions : LLVM_Region_Vector.Vector; + Dec_Id : Valid_LLVM_Region_Id) return Natural; + -- Helper function for the Post-Condition of Build_Ckpt_From_JSON. + + function Build_Ckpt_From_JSON + (JSON_Root : JSON_Value) return LLVM_Coverage_Ckpt; + + procedure Print_Report (Ckpt : LLVM_Coverage_Ckpt); + -- Print the Report on STDOUT. + -- This is a debug helper function only. + + procedure Add_MCDC_To_Regions + (MCDC_Record : Parsed_MCDC_Record; + Regions : in out LLVM_Region_Vector.Vector); + + procedure Add_Branch_Region_To_Regions + (Branch_Region : Parsed_Branch_Region; + Regions : in out LLVM_Region_Vector.Vector); + + procedure Add_Code_Region_To_Regions + (Code_Region : Parsed_Code_Region; + Regions : in out LLVM_Region_Vector.Vector); + + function Find_Parent_Decision + (Regions : LLVM_Region_Vector.Vector; + Span : Local_Source_Location_Range; + Id : out LLVM_Region_Id) return Boolean; + -- Search for an already existing region in Regions which + -- has the Decision kind and which Span includes the given span. + -- Return True if such element is found, and sets Id accordingly. + + function Parse_MCDC_Record + (JSON_MCDC_Record : JSON_Value) return Parsed_MCDC_Record; + + function Parse_Branch_Region + (JSON_Branch_Region : JSON_Value) return Parsed_Branch_Region; + + function Parse_Code_Region + (JSON_Code_Region : JSON_Value) return Parsed_Code_Region; + + function Parse_Test_Vector + (JSON_Test_Vector : JSON_Value) return MC_DC.Evaluation; + + function Parse_SLOC_Range + (Sloc_Array : JSON_Array) return Local_Source_Location_Range; + -- Given a JSON_Value, checks that the value is a 4 long array of integers + -- [a b c d] and return a Local_Source_Location_Range ((a, b), (c, d)) + + --------------- + -- JSON_Load -- + --------------- + + procedure JSON_Load (JSON_Filename : String) is + Ckpt : aliased LLVM_Coverage_Ckpt := + Build_Ckpt_From_JSON (JSON.Read_File (JSON_Filename)); begin - Put_Line ("[DEBUG(dprn)] Loading " & Filename); + LLVM_Trace.Trace ("Report generated"); + if LLVM_Trace.Is_Active then + Print_Report (Ckpt); + end if; end JSON_Load; -end LLVM_JSON_Checkpoints; \ No newline at end of file + -------------------------- + -- Build_Ckpt_From_JSON -- + -------------------------- + + function Build_Ckpt_From_JSON + (JSON_Root : JSON_Value) return LLVM_Coverage_Ckpt + is + JSON_Files : constant JSON_Array := JSON.Child_Array (JSON_Root, "data"); + + Report : LLVM_Coverage_Ckpt; + begin + for JSON_File of JSON_Files loop + declare + Functions : constant JSON_Array := + JSON.Child_Array (JSON_File, "functions"); + + File_Report : LLVM_Coverage_File_Ckpt := + (Filename => +JSON.Child_String (JSON_File, "filename"), + others => <>); + begin + for Fct of Functions loop + declare + MCDC_Records : constant JSON_Array := + JSON.Child_Array (Fct, "mcdc_records"); + Code_Regions : constant JSON_Array := + JSON.Child_Array (Fct, "code_regions"); + Branch_Regions : constant JSON_Array := + JSON.Child_Array (Fct, "branch_regions"); + + Function_Report : LLVM_Coverage_Function_Ckpt := + (Name => + +JSON.Child_String (Fct, "demangled_name"), + Mangled_Name => + +JSON.Child_String (Fct, "name"), + others => <>); + begin + -- Load MCDC records + -- It is important to load MCDC records BEFORE code regions. + -- That way, decision regions (and thus decision SCOs + -- later on) are inserted in the vector BEFORE their + -- conditions which are populated when loading code regions. + -- + -- We rely on this assumption to more efficiently build + -- the SCO descriptors. + + LLVM_Trace.Trace ("Build_Ckpt_From_JSON: handle function '" + & (+Function_Report.Name) & "'"); + + for MCDC_Record of MCDC_Records loop + Add_MCDC_To_Regions + (Parse_MCDC_Record (MCDC_Record), + Function_Report.Regions); + end loop; + + -- Complete decision regions with branch regions. + -- Branches may be conditions of an existing decision. + -- (1-condition decisions are not registered through MCDC) + + for Branch_Region of Branch_Regions loop + Add_Branch_Region_To_Regions + (Parse_Branch_Region (Branch_Region), + Function_Report.Regions); + end loop; + + -- Load code regions + + for Code_Region of Code_Regions loop + Add_Code_Region_To_Regions + (Parse_Code_Region (Code_Region), + Function_Report.Regions); + end loop; + + File_Report.Functions.Append (Function_Report); + end; + end loop; + + Report.File_Reports.Append (File_Report); + end; + end loop; + + -- Ensure the Report is well-formed (check that we found all the + -- conditions from each decision). + + for File of Report.File_Reports loop + for Fct of File.Functions loop + for Reg of Fct.Regions loop + if Reg.Kind = Decision then + if Reg.Num_Conditions = 0 then + Fatal_Error ("Invalid JSON: Decision with 0 condition " + & "found in function: " + & (+Fct.Name)); + end if; + declare + Count : constant Natural := + Count_Cond_For_Dec (Fct.Regions, Reg.Id); + begin + if Reg.Num_Conditions /= Count + then + Fatal_Error ("Invalid JSON: Decision declares " + & Natural'Image (Reg.Num_Conditions) + & " conditions, but " + & Natural'Image (Count) + & " found in function: " + & (+Fct.Name)); + end if; + end; + end if; + end loop; + end loop; + end loop; + + return Report; + end Build_Ckpt_From_JSON; + + ------------------------ + -- Count_Cond_For_Dec -- + ------------------------ + + function Count_Cond_For_Dec + (Regions : LLVM_Region_Vector.Vector; + Dec_Id : Valid_LLVM_Region_Id) return Natural + is + Count : Natural := 0; + begin + for Region of Regions loop + if Region.Kind = Condition and then Region.Parent_Id = Dec_Id then + Count := Count + 1; + end if; + end loop; + return Count; + end Count_Cond_For_Dec; + + ------------------ + -- Print_Report -- + ------------------ + + procedure Print_Report (Ckpt : LLVM_Coverage_Ckpt) is + begin + for File of Ckpt.File_Reports loop + LLVM_Trace.Trace ("file: " & (+File.Filename)); + LLVM_Trace.Increase_Indent; + for Fct of File.Functions loop + LLVM_Trace.Trace ("function: " & (+Fct.Name) & " (mangled: " + & (+Fct.Mangled_Name) & ")"); + LLVM_Trace.Increase_Indent; + for Region of Fct.Regions loop + case Region.Kind is + when Statement => null; + LLVM_Trace.Trace ("[" & LLVM_Region_Id'Image (Region.Id) + & "] STATEMENT " + & Image (Region.Span) & ":"); + LLVM_Trace.Trace (" Count: " & Natural'Image + (Region.Execution_Count)); + when Decision => null; + LLVM_Trace.Trace ("[" & LLVM_Region_Id'Image (Region.Id) + & "] DECISION " + & Image (Region.Span) & ":"); + + for TV of Region.Test_Vectors loop + declare + Buffer : Strings.US.Unbounded_String := +" { "; + begin + for Eval of TV.Values loop + Append (Buffer, (case Eval is + when Unknown => "-, ", + when False => "F, ", + when True => "T, " + )); + end loop; + Append (Buffer, "} -> "); + Append (Buffer, (case TV.Outcome is + when Unknown => "X", + when False => "F", + when True => "T" + )); + + LLVM_Trace.Trace (+Buffer); + end; + end loop; + when Condition => null; + LLVM_Trace.Trace ("[" & LLVM_Region_Id'Image (Region.Id) + & "] CONDITION " + & Image (Region.Span) & ": parent " + & LLVM_Region_Id'Image + (Region.Parent_Id)); + end case; + end loop; + LLVM_Trace.Decrease_Indent; + end loop; + LLVM_Trace.Decrease_Indent; + end loop; + end Print_Report; + + ------------------------- + -- Add_MCDC_To_Regions -- + ------------------------- + + procedure Add_MCDC_To_Regions + (MCDC_Record : Parsed_MCDC_Record; + Regions : in out LLVM_Region_Vector.Vector) + is + Region : constant LLVM_Region := + (Kind => Decision, + Span => MCDC_Record.Span, + Id => Regions.Last_Index + 1, + Num_Conditions => MCDC_Record.Num_Conditions, + Test_Vectors => MCDC_Record.Test_Vectors, + others => <>); + begin + LLVM_Trace.Trace ("Add_MCDC_Region: " & Image (MCDC_Record.Span)); + + Regions.Append (Region); + end Add_MCDC_To_Regions; + + ---------------------------------- + -- Add_Branch_Region_To_Regions -- + ---------------------------------- + + procedure Add_Branch_Region_To_Regions + (Branch_Region : Parsed_Branch_Region; + Regions : in out LLVM_Region_Vector.Vector) + is + Cond_Region : LLVM_Region; + Dec_Region : LLVM_Region; + Parent_Id : LLVM_Region_Id; + begin + -- Branch regions are used to find 1-condition decisions, which are not + -- instrumented for MCDC. + -- If a Decision already exist, drop the branch. + -- Otherwise, build a decision AND a condition Regions corresponding to + -- the decision. + + LLVM_Trace.Trace ("Add_Branch_Region " & Image (Branch_Region.Span)); + + if Find_Parent_Decision (Regions, Branch_Region.Span, Parent_Id) then + pragma Assert (Parent_Id /= No_LLVM_Region_Id); + LLVM_Trace.Trace ("Add_Branch_Region: Parent decision found. " + & "Adding as a condition"); + declare + Parent_Region : LLVM_Region renames Regions.Reference (Parent_Id); + begin + Cond_Region := + (Kind => Condition, + Span => Branch_Region.Span, + Id => Regions.Last_Index + 1, + Parent_Id => Parent_Id, + Index => Parent_Region.Next_Condition, + others => <>); + Parent_Region.Next_Condition := Parent_Region.Next_Condition + 1; + end; + Regions.Append (Cond_Region); + else + declare + TVs : Evaluation_Vectors.Vector; + begin + -- Build True and False Test vectors. + -- We only keep track of 1 execution, because we are not + -- interested in knowing how many times these were executed. + + LLVM_Trace.Trace ("Add_Branch_Region: No parent decision. " + & "Create a 1-condition decision."); + + if Branch_Region.T_Exec_Count > 0 then + declare + Cond_Vec : Condition_Evaluation_Vectors.Vector; + begin + Cond_Vec.Append (True); + TVs.Append ((Decision => No_SCO_Id, + Values => Cond_Vec, + Outcome => True, + Next_Condition => No_Condition_Index)); + end; + end if; + if Branch_Region.F_Exec_Count > 0 then + declare + Cond_Vec : Condition_Evaluation_Vectors.Vector; + begin + Cond_Vec.Append (False); + TVs.Append ((Decision => No_SCO_Id, + Values => Cond_Vec, + Outcome => False, + Next_Condition => No_Condition_Index)); + end; + end if; + + Dec_Region := + (Kind => Decision, + Span => Branch_Region.Span, + Id => Regions.Last_Index + 1, + Num_Conditions => 1, + Test_Vectors => TVs, + others => <>); + Regions.Append (Dec_Region); + + Cond_Region := + (Kind => Condition, + Span => Branch_Region.Span, + Id => Regions.Last_Index + 1, + Parent_Id => Regions.Last_Index, -- Previous Decision. + Index => Condition_Index'First, + others => <>); + Regions.Append (Cond_Region); + end; + end if; + end Add_Branch_Region_To_Regions; + + -------------------------------- + -- Add_Code_Region_To_Regions -- + -------------------------------- + + procedure Add_Code_Region_To_Regions + (Code_Region : Parsed_Code_Region; + Regions : in out LLVM_Region_Vector.Vector) + is + Region : LLVM_Region; + Parent_Id : LLVM_Region_Id; + begin + LLVM_Trace.Trace ("Add_Code_Region: " & Image (Code_Region.Span)); + + if not Find_Parent_Decision (Regions, Code_Region.Span, Parent_Id) then + pragma Assert (Parent_Id = No_LLVM_Region_Id); + LLVM_Trace.Trace ("Add_Code_Region: No parent decision found. " + & "Adding as a Statement"); + + Region := + (Kind => Statement, + Span => Code_Region.Span, + Id => Regions.Last_Index + 1, + Execution_Count => Code_Region.Execution_Count, + others => <>); + Regions.Append (Region); + end if; + end Add_Code_Region_To_Regions; + + -------------------------- + -- Find_Parent_Decision -- + -------------------------- + + function Find_Parent_Decision + (Regions : LLVM_Region_Vector.Vector; + Span : Local_Source_Location_Range; + Id : out LLVM_Region_Id) return Boolean + is + begin + for Index in Regions.First_Index .. Regions.Last_Index loop + declare + Region : constant LLVM_Region := + Regions.Constant_Reference (Index); + begin + if Region.Kind = Decision and then Contained_In (Span, Region.Span) + then + Id := Region.Id; + return True; + end if; + end; + end loop; + + return False; + end Find_Parent_Decision; + + ----------------------- + -- Parse_MCDC_Record -- + ----------------------- + + function Parse_MCDC_Record + (JSON_MCDC_Record : JSON_Value) return Parsed_MCDC_Record + is + JSON_Evaluation_Array : constant JSON_Array := + JSON.Child_Array (JSON_MCDC_Record, "test_vectors"); + + Parsed : Parsed_MCDC_Record := + (Span => + Parse_SLOC_Range (JSON.Child_Array (JSON_MCDC_Record, "span")), + Num_Conditions => + JSON.Child_Int (JSON_MCDC_Record, "num_conditions"), + others => <>); + begin + for JSON_Evaluation of JSON_Evaluation_Array loop + Parsed.Test_Vectors.Append (Parse_Test_Vector (JSON_Evaluation)); + end loop; + return Parsed; + end Parse_MCDC_Record; + + ------------------------- + -- Parse_Branch_Region -- + ------------------------- + + function Parse_Branch_Region + (JSON_Branch_Region : JSON_Value) return Parsed_Branch_Region + is + Branch_Region : constant Parsed_Branch_Region := + (Span => + Parse_SLOC_Range (JSON.Child_Array (JSON_Branch_Region, "span")), + T_Exec_Count => + JSON.Child_Int (JSON_Branch_Region, "true_count"), + F_Exec_Count => + JSON.Child_Int (JSON_Branch_Region, "false_count")); + begin + return Branch_Region; + end Parse_Branch_Region; + + ----------------------- + -- Parse_Code_Region -- + ----------------------- + + function Parse_Code_Region + (JSON_Code_Region : JSON_Value) return Parsed_Code_Region + is + Code_Region : constant Parsed_Code_Region := + (Span => + Parse_SLOC_Range (JSON.Child_Array (JSON_Code_Region, "span")), + Execution_Count => JSON.Child_Int (JSON_Code_Region, "count")); + begin + return Code_Region; + end Parse_Code_Region; + + ----------------------- + -- Parse_Test_Vector -- + ----------------------- + + function Parse_Test_Vector + (JSON_Test_Vector : JSON_Value) return MC_DC.Evaluation + is + Result_Int : constant Integer := + JSON.Child_Int (JSON_Test_Vector, "decision_outcome"); + Vector : constant JSON_Array := + JSON.Child_Array (JSON_Test_Vector, "vector"); + Size : constant Integer := Length (Vector); + + Outcome : Tristate; + Cond_Vec : Condition_Evaluation_Vectors.Vector; + Result : MC_DC.Evaluation; + begin + if Result_Int = 1 then + Outcome := True; + elsif Result_Int = 0 then + Outcome := False; + else + Fatal_Error ("Expected 0 or 1, got " & Integer'Image (Result_Int)); + end if; + + for I in 1 .. Size loop + declare + Cond_Int : constant Integer := JSON.Array_Nth_Integer (Vector, I); + begin + if Cond_Int = -1 then + Cond_Vec.Append (Unknown); + elsif Cond_Int = 0 then + Cond_Vec.Append (False); + elsif Cond_Int = 1 then + Cond_Vec.Append (True); + else + Fatal_Error ("Expected one of (-1,0,1), got " + & Integer'Image (Cond_Int)); + end if; + end; + end loop; + + Result.Decision := No_SCO_Id; + Result.Values := Cond_Vec; + Result.Outcome := Outcome; + Result.Next_Condition := No_Condition_Index; + return Result; + end Parse_Test_Vector; + + ---------------------- + -- Parse_SLOC_Range -- + ---------------------- + + function Parse_SLOC_Range + (Sloc_Array : JSON_Array) return Local_Source_Location_Range + is + begin + if Length (Sloc_Array) /= 4 then + Fatal_Error ("'span' array should be 4 integers"); + end if; + + return ((JSON.Array_Nth_Integer (Sloc_Array, 1), + JSON.Array_Nth_Integer (Sloc_Array, 2)), + (JSON.Array_Nth_Integer (Sloc_Array, 3), + JSON.Array_Nth_Integer (Sloc_Array, 4))); + end Parse_SLOC_Range; + +end LLVM_JSON_Checkpoints; diff --git a/tools/gnatcov/llvm_json_checkpoints.ads b/tools/gnatcov/llvm_json_checkpoints.ads index b564feaf5..e91937470 100644 --- a/tools/gnatcov/llvm_json_checkpoints.ads +++ b/tools/gnatcov/llvm_json_checkpoints.ads @@ -16,9 +16,78 @@ -- of the license. -- ------------------------------------------------------------------------------ +with Ada.Containers.Vectors; + +with Coverage.Source; use Coverage.Source; +with Logging; +with SC_Obligations; use SC_Obligations; +with Slocs; use Slocs; +with Strings; use Strings; + package LLVM_JSON_Checkpoints is - procedure JSON_Load (Filename : String); + LLVM_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("LLVM-JSON"); + -- Trace to log LLVM JSON Trace Adapter messages. + + type LLVM_Region_Kind is (Statement, Decision, Condition); + + type LLVM_Region_Id is new Natural; + No_LLVM_Region_Id : constant LLVM_Region_Id := 0; + subtype Valid_LLVM_Region_Id is LLVM_Region_Id + range No_LLVM_Region_Id + 1 .. LLVM_Region_Id'Last; + + type LLVM_Region (Kind : LLVM_Region_Kind := Statement) is record + Span : Local_Source_Location_Range; + Id : Valid_LLVM_Region_Id; + SCO : SCO_Id := No_SCO_Id; + -- SCO_Id is meant to be set by the SC_obligations pass when + -- registering SCOs. + + case Kind is + when Statement => + Execution_Count : Natural; + + when Decision => + Num_Conditions : Natural; + Test_Vectors : Evaluation_Vectors.Vector; + Next_Condition : Condition_Index := Condition_Index'First; + -- Used for assigning a condition index to its conditions + + when Condition => + Parent_Id : Valid_LLVM_Region_Id; + Index : Condition_Index; + end case; + end record; + + package LLVM_Region_Vector is new Ada.Containers.Vectors + (Index_Type => Valid_LLVM_Region_Id, + Element_Type => LLVM_Region); + + type LLVM_Coverage_Function_Ckpt is record + Name : Unbounded_String; + Mangled_Name : Unbounded_String; + Regions : LLVM_Region_Vector.Vector; + end record; + + package LLVM_Coverage_Function_Ckpt_Vector is new Ada.Containers.Vectors + (Index_Type => Natural, + Element_Type => LLVM_Coverage_Function_Ckpt); + + type LLVM_Coverage_File_Ckpt is record + Filename : Unbounded_String; + Functions : LLVM_Coverage_Function_Ckpt_Vector.Vector; + end record; + + package LLVM_Coverage_File_Ckpt_Vector is new Ada.Containers.Vectors + (Index_Type => Natural, + Element_Type => LLVM_Coverage_File_Ckpt); + + type LLVM_Coverage_Ckpt is record + File_Reports : LLVM_Coverage_File_Ckpt_Vector.Vector; + end record; + + procedure JSON_Load (JSON_Filename : String); -- Read a JSON file containing LLVM coverage data -- and populate internal structures with it. From 823389799253eece403f0df4f407c3ddddb194c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Tue, 21 May 2024 09:16:03 +0000 Subject: [PATCH 1195/1483] files-table(llvm-json): Load File Table entries from LLVM JSON --- tools/gnatcov/files_table.adb | 31 ++++++++++++++++++++++--- tools/gnatcov/files_table.ads | 5 ++++ tools/gnatcov/llvm_json_checkpoints.adb | 3 +++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index 6e081902a..b2441d295 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -31,10 +31,11 @@ with GNATCOLL.Iconv; use GNATCOLL.Iconv; with GNATCOLL.Utils; use GNATCOLL.Utils; with GNATCOLL.VFS; use GNATCOLL.VFS; -with Checkpoints; use Checkpoints; -with Coverage; use Coverage; +with Checkpoints; use Checkpoints; +with Coverage; use Coverage; +with LLVM_JSON_Checkpoints; use LLVM_JSON_Checkpoints; with Outputs; -with Perf_Counters; use Perf_Counters; +with Perf_Counters; use Perf_Counters; with Project; package body Files_Table is @@ -2471,6 +2472,30 @@ package body Files_Table is end loop; end Checkpoint_Load; + -------------------- + -- LLVM_JSON_Load -- + -------------------- + + procedure LLVM_JSON_Load + (Ckpt : access constant LLVM_Coverage_Ckpt) + is + begin + LLVM_Trace.Trace ("Files_Table.LLVM_JSON_Load"); + + for File_Report of Ckpt.File_Reports loop + declare + SFI : constant Source_File_Index := + Get_Index_From_Full_Name (+File_Report.Filename, Source_File); + CU : Compilation_Unit; + begin + CU.Language := File_Based_Language; + CU.Unit_Name := File_Report.Filename; + Consolidate_Ignore_Status (SFI, Never); + Consolidate_Source_File_Unit (SFI, CU); + end; + end loop; + end LLVM_JSON_Load; + ------------------------ -- Postprocess_Source -- ------------------------ diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index bc8df9b74..f5b73c8e1 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -25,6 +25,7 @@ with GNAT.Strings; use GNAT.Strings; with GNAT.Regexp; limited with Checkpoints; +limited with LLVM_JSON_Checkpoints; with Coverage_Options; use Coverage_Options; with Diagnostics; use Diagnostics; with Logging; @@ -632,6 +633,10 @@ package Files_Table is -- Ignore_Source_Files should be null if the checkpoint purpose is -- Consolidation. + procedure LLVM_JSON_Load + (Ckpt : access constant LLVM_JSON_Checkpoints.LLVM_Coverage_Ckpt); + -- Use the JSON loaded checkpoint to create file tables, + procedure Postprocess_Source (Preprocessed_Filename : String; Postprocessed_Filename : String); diff --git a/tools/gnatcov/llvm_json_checkpoints.adb b/tools/gnatcov/llvm_json_checkpoints.adb index 2dcd1d900..eacee644f 100644 --- a/tools/gnatcov/llvm_json_checkpoints.adb +++ b/tools/gnatcov/llvm_json_checkpoints.adb @@ -23,6 +23,7 @@ with Ada.Strings.Unbounded; use Ada.Strings.Unbounded; with GNATCOLL.JSON; use GNATCOLL.JSON; with GNATCOLL.Traces; use GNATCOLL.Traces; +with Files_Table; with JSON; with MC_DC; with Outputs; use Outputs; @@ -154,6 +155,8 @@ package body LLVM_JSON_Checkpoints is if LLVM_Trace.Is_Active then Print_Report (Ckpt); end if; + + Files_Table.LLVM_JSON_Load (Ckpt'Access); end JSON_Load; -------------------------- From 2ad06ce2af78f5eb1d8aa3a220eae062d4b90775 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 22 May 2024 10:00:35 +0000 Subject: [PATCH 1196/1483] sc-obligations(llvm-json): Register SCOs from LLVM JSON --- tools/gnatcov/llvm_json_checkpoints.adb | 1 + tools/gnatcov/sc_obligations.adb | 157 ++++++++++++++++++++++-- tools/gnatcov/sc_obligations.ads | 7 ++ 3 files changed, 156 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/llvm_json_checkpoints.adb b/tools/gnatcov/llvm_json_checkpoints.adb index eacee644f..606657faf 100644 --- a/tools/gnatcov/llvm_json_checkpoints.adb +++ b/tools/gnatcov/llvm_json_checkpoints.adb @@ -157,6 +157,7 @@ package body LLVM_JSON_Checkpoints is end if; Files_Table.LLVM_JSON_Load (Ckpt'Access); + SC_Obligations.LLVM_JSON_Load (Ckpt'Access); end JSON_Load; -------------------------- diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 4da2ed387..23cf0e7a5 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -32,16 +32,17 @@ with Namet; use Namet; with SCOs; with Snames; -with Checkpoints; use Checkpoints; +with Checkpoints; use Checkpoints; with Coverage.Source; -with Coverage.Tags; use Coverage, Coverage.Tags; -with Diagnostics; use Diagnostics; -with Files_Table; use Files_Table; -with Inputs; use Inputs; -with Outputs; use Outputs; +with Coverage.Tags; use Coverage, Coverage.Tags; +with Diagnostics; use Diagnostics; +with Files_Table; use Files_Table; +with Inputs; use Inputs; +with LLVM_JSON_Checkpoints; use LLVM_JSON_Checkpoints; +with Outputs; use Outputs; with SC_Obligations.BDD; -with Switches; use Switches; -with Traces_Elf; use Traces_Elf; +with Switches; use Switches; +with Traces_Elf; use Traces_Elf; with Traces_Files; package body SC_Obligations is @@ -454,7 +455,7 @@ package body SC_Obligations is -- Index of this condition in the decision when Decision => - Expression : SCO_Id; + Expression : SCO_Id := No_SCO_Id; -- Top expression node for this decision D_Kind : Decision_Kind; @@ -2506,6 +2507,141 @@ package body SC_Obligations is end Checkpoint_Load; + -------------------- + -- LLVM_JSON_Load -- + -------------------- + + procedure LLVM_JSON_Load + (Ckpt : access LLVM_Coverage_Ckpt) + is + begin + LLVM_Trace.Trace ("SC_Obligations.LLVM_JSON_Load"); + + for File_Report_Cur in Ckpt.File_Reports.Iterate loop + declare + use LLVM_Coverage_File_Ckpt_Vector; + File_Report : LLVM_Coverage_File_Ckpt renames + Ckpt.File_Reports.Reference (File_Report_Cur); + + Created_Units : Created_Unit_Maps.Map; + + SFI : constant Source_File_Index := + Get_Index_From_Full_Name + (+File_Report.Filename, Source_File); + CUID : constant CU_Id := + Allocate_CU + (Provider => Compiler, + Origin => No_Source_File, + Main_Source => SFI, + Fingerprint => No_Fingerprint, + Created_Units => Created_Units); + First_SCO : constant Valid_SCO_Id := + SCO_Vector.Last_Index + 1; + + Last_SCO : Valid_SCO_Id; + begin + + -- If a compilation unit was already registered for this file, + -- skip it. It is expected that only 1 JSON file is given to + -- gnatcov. Aggregating source files should be done beforehand, + -- at the LLVM level. + + if CUID = No_CU_Id then + Warn ("[LLVM-JSON] A compilation unit already exists for " + & (+File_Report.Filename) & "."); + return; + end if; + + -- Register the SCOs + + for Fct_Cur in File_Report.Functions.Iterate loop + declare + use LLVM_Coverage_Function_Ckpt_Vector; + Fct : LLVM_Coverage_Function_Ckpt renames + File_Report.Functions.Reference (Fct_Cur); + begin + for Region_Cur in Fct.Regions.Iterate loop + declare + use LLVM_Region_Vector; + Region : LLVM_Region renames + Fct.Regions.Reference (Region_Cur); + + Location : constant Source_Location_Range := + (Source_File => SFI, L => Region.Span); + + SCOD : SCO_Descriptor; + MCDC_Num_Conditions : Any_Condition_Index; + SCO : SCO_Id; + begin + case Region.Kind is + when Decision => + MCDC_Num_Conditions := + Any_Condition_Index + (Region.Num_Conditions - 1); + SCOD := + (Kind => Decision, + Origin => CUID, + Sloc_Range => Location, + D_Kind => If_Statement, + Last_Cond_Index => MCDC_Num_Conditions, + others => <>); + when Condition => + pragma Assert + (Fct.Regions (Region.Parent_Id).SCO + /= No_SCO_Id); + SCOD := + (Kind => Condition, + Origin => CUID, + Sloc_Range => Location, + Value => Unknown, + BDD_Node => No_BDD_Node_Id, + Parent => + Fct.Regions (Region.Parent_Id).SCO, + Index => Region.Index, + others => <>); + when Statement => + SCOD := + (Kind => Statement, + Origin => CUID, + Sloc_Range => Location, + S_Kind => Other_Statement, + others => <>); + end case; + SCO_Vector.Append (SCOD); + SCO := SCO_Vector.Last_Index; + + -- Keep a reference to the just added SCO id. + -- Useful for condition -> decision referencing. + + Region.SCO := SCO; + + if SCOD.Kind /= Condition then + Add_SCO_To_Lines (SCO, SCOD); + end if; + end; + end loop; + end; + end loop; + + if SCO_Vector.Last_Index = No_SCO_Id then + return; -- The SCO vector is completely empty. + end if; + + -- Check that Last_SCO >= First_SCO. + -- otherwise there were no regions in the report. + + Last_SCO := SCO_Vector.Last_Index; + + if Last_SCO < First_SCO then + Warn ("[LLVM-JSON] No regions to process"); + else + CU_Vector (CUID).First_SCO := First_SCO; + CU_Vector (CUID).Last_SCO := Last_SCO; + end if; + end; + end loop; + end LLVM_JSON_Load; + ---------------------- -- Checkpoint_Clear -- ---------------------- @@ -2796,6 +2932,9 @@ package body SC_Obligations is function Expression_Image (Op_SCO : SCO_Id) return Unbounded_String is begin + if Op_SCO = No_SCO_Id then + return (+""); + end if; case Kind (Op_SCO) is when Condition => return +('C' & Img (Integer (Index (Op_SCO)))); diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 24bcdea5e..9c54db846 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -34,6 +34,7 @@ with Namet; with Types; use Types; limited with Checkpoints; +limited with LLVM_JSON_Checkpoints; with Logging; with Slocs; use Slocs; with Strings; use Strings; @@ -994,6 +995,12 @@ package SC_Obligations is procedure Checkpoint_Load (CLS : in out Checkpoints.Checkpoint_Load_State); -- Load checkpointed SCOs from stream and merge them in current state + procedure LLVM_JSON_Load + (Ckpt : access LLVM_JSON_Checkpoints.LLVM_Coverage_Ckpt); + -- Use the JSON loaded checkpoint to create SCOs. + -- Note that for each Region Vector, Decision regions referenced by + -- their Condition regions must appear before them in the vector. + --------------------------- -- Accessors for CU_Info -- --------------------------- From 301f7d694d6403552d63b9df19393f6276f645d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 22 May 2024 14:14:00 +0000 Subject: [PATCH 1197/1483] coverage-source(llvm-json): Register SCI MCDC Evaluations and Executed Code Regions --- tools/gnatcov/coverage-source.adb | 97 ++++++++++++++++++++++--- tools/gnatcov/coverage-source.ads | 5 ++ tools/gnatcov/llvm_json_checkpoints.adb | 1 + 3 files changed, 91 insertions(+), 12 deletions(-) diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index f6ba33de8..881576c48 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -26,18 +26,19 @@ with Interfaces; with GPR2.Build.Source; with GPR2.Project.View; -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 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 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 LLVM_JSON_Checkpoints; use LLVM_JSON_Checkpoints; +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 @@ -676,6 +677,78 @@ package body Coverage.Source is end if; end Checkpoint_Load; + -------------------- + -- LLVM_JSON_Load -- + -------------------- + + procedure LLVM_JSON_Load + (Ckpt : access constant LLVM_Coverage_Ckpt) + is + Rep_SCI : Source_Coverage_Info; + begin + LLVM_Trace.Trace ("Coverage.Source.LLVM_JSON_Load"); + + -- Extend the SCI vector to accomodate for the SCOs. + + Initialize_SCI; + + for File_Report of Ckpt.File_Reports loop + for Fct_Report of File_Report.Functions loop + for Region of Fct_Report.Regions loop + if Region.Kind = Statement then + Rep_SCI := + (Kind => Statement, + Basic_Block_Has_Code => True, + Executed => Region.Execution_Count > 0, + others => <>); + elsif Region.Kind = Decision then + declare + Eval_Set : Evaluation_Sets.Set; + T_Executed : Boolean := False; + F_Executed : Boolean := False; + begin + + -- Convert an evaluation vector to a set, + -- and check True/False_executed accordingly. + + for Eval of Region.Test_Vectors loop + declare + Eval_Cpy : Evaluation := Eval; + begin + -- Reassign the Decision to set it to the right + -- SCO, and insert it in the set. + + Eval_Cpy.Decision := Region.SCO; + if not Eval_Set.Contains (Eval_Cpy) then + Eval_Set.Insert (Eval_Cpy); + end if; + end; + case Eval.Outcome is + when True => T_Executed := True; + when False => F_Executed := True; + when others => null; + end case; + end loop; + + Rep_SCI := + (Kind => Decision, + Outcome_Taken => + (True => T_Executed, False => F_Executed), + Evaluations => Eval_Set, + others => <>); + end; + end if; + + if Region.Kind /= Condition then + SCI_Vector (Region.SCO).Append + (new Source_Coverage_Info'(Rep_SCI)); + end if; + end loop; + end loop; + end loop; + + end LLVM_JSON_Load; + ------------------------ -- Compute_Line_State -- ------------------------ diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index 8b86a86f5..d66549304 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -20,6 +20,7 @@ with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; with Ada.Text_IO; use Ada.Text_IO; +limited with LLVM_JSON_Checkpoints; with Checkpoints; use Checkpoints; with Files_Table; use Files_Table; with Instrument; use Instrument; @@ -174,4 +175,8 @@ package Coverage.Source is procedure Checkpoint_Load (CLS : in out Checkpoint_Load_State); -- Load checkpointed coverage state from S and merge into current state + procedure LLVM_JSON_Load + (Ckpt : access constant LLVM_JSON_Checkpoints.LLVM_Coverage_Ckpt); + -- Register statement counters and MC/DC evaluations from Report. + end Coverage.Source; diff --git a/tools/gnatcov/llvm_json_checkpoints.adb b/tools/gnatcov/llvm_json_checkpoints.adb index 606657faf..d736f653e 100644 --- a/tools/gnatcov/llvm_json_checkpoints.adb +++ b/tools/gnatcov/llvm_json_checkpoints.adb @@ -158,6 +158,7 @@ package body LLVM_JSON_Checkpoints is Files_Table.LLVM_JSON_Load (Ckpt'Access); SC_Obligations.LLVM_JSON_Load (Ckpt'Access); + Coverage.Source.LLVM_JSON_Load (Ckpt'Access); end JSON_Load; -------------------------- From 5e99be85595de640cc8e9ee7c133ab86f0b83660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Thu, 23 May 2024 10:06:47 +0000 Subject: [PATCH 1198/1483] sc-obligations: Add 'LLVM' Provider --- tools/gnatcov/sc_obligations.adb | 13 +++++++------ tools/gnatcov/sc_obligations.ads | 2 +- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 23cf0e7a5..dad8253b6 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -154,7 +154,7 @@ package body SC_Obligations is -- Hash of ALI_Annotations, for consistency checks with source traces case Provider is - when Compiler => + when Compiler | LLVM => null; when Instrumenter => @@ -1214,7 +1214,7 @@ package body SC_Obligations is Value.Annotations_Fingerprint := CLS.Read_Fingerprint; case Value.Provider is - when Compiler => + when Compiler | LLVM => null; when Instrumenter => @@ -2132,7 +2132,8 @@ package body SC_Obligations is function Provider_Image (Provider : SCO_Provider) return String is (case Provider is when Compiler => "ALI file", - when Instrumenter => "instrumentation"); + when Instrumenter => "instrumentation", + when LLVM => "LLVM dump"); -- Helper to designate SCO providers in an error message function CU_Image return String is @@ -2249,7 +2250,7 @@ package body SC_Obligations is CSS.Write (Value.Annotations_Fingerprint); case Value.Provider is - when Compiler => + when Compiler | LLVM => null; when Instrumenter => @@ -2530,7 +2531,7 @@ package body SC_Obligations is (+File_Report.Filename, Source_File); CUID : constant CU_Id := Allocate_CU - (Provider => Compiler, + (Provider => LLVM, Origin => No_Source_File, Main_Source => SFI, Fingerprint => No_Fingerprint, @@ -4286,7 +4287,7 @@ package body SC_Obligations is Origin_Action : constant String := (case CU.Provider is - when Compiler => "loading", + when Compiler | LLVM => "loading", when Instrumenter => "instrumenting"); begin Warn ("ignoring duplicate SCOs for " diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 9c54db846..f4e310214 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -113,7 +113,7 @@ package SC_Obligations is -- unit maps to a source file, regardless of the language for this -- source file, and there is at most one unit for a given source file. - type SCO_Provider is (Compiler, Instrumenter); + type SCO_Provider is (Compiler, Instrumenter, LLVM); type CU_Id is new Natural; No_CU_Id : constant CU_Id := 0; From a267623b5e4055c1754b1acd7c897bd84cd2b282 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 24 May 2024 13:29:34 +0000 Subject: [PATCH 1199/1483] sc-obligations: Avoid browsing the BDD to find conditions for LLVM SCOs --- tools/gnatcov/sc_obligations.adb | 69 +++++++++++++++++++++++++++++++- 1 file changed, 67 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index dad8253b6..146862cfb 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -2779,14 +2779,72 @@ package body SC_Obligations is is use BDD; - SCOD : SCO_Descriptor renames - Vectors.SCO_Vector.Constant_Reference (SCO); + SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); + First : constant BDD_Node_Id := SCOD.Decision_BDD.First_Node; Last : constant BDD_Node_Id := SCOD.Decision_BDD.Last_Node; + CU : constant CU_Id := Comp_Unit (SCO); Current_Condition_Index : Any_Condition_Index := No_Condition_Index; begin + -- Do not check the BDD if the SCO was provided by LLVM. + + if Provider (CU) = LLVM then + + -- TODO??? Make this search more efficient. + -- (For now it just browse all SCOs of the CU). + -- Ideas : + -- - Ensure both invariants always hold. That way, we can get rid + -- of the double while loop. + -- - Find a way to reference the SCO_ID of the first condition in + -- the SCOD of the decision, so we just have to add the SCO_ID + -- with the index. + + declare + C_SCO : SCO_Id := SCO + 1; + -- Condition SCOs are always after their Decision, and all the + -- condition SCOs of a decision should appear consecutively. + -- + -- The second invariant may not hold in the case of + -- nested decisions. + + Index_Mut : Condition_Index := Index; + begin + -- Search for the first Condition of the Decision. + + while C_SCO <= Last_SCO (CU) + and then + (Kind (C_SCO) /= Condition + or else Parent (C_SCO) /= SCO) loop + C_SCO := C_SCO + 1; + end loop; + + -- Search for the Index-th Condition. + -- We need a loop because the invariant may not hold with + -- nested decisions. + + while Index_Mut > 0 loop + Index_Mut := Index_Mut - 1; + loop + C_SCO := C_SCO + 1; + exit when C_SCO > Last_SCO (CU); + exit when Kind (C_SCO) = Condition + and then Parent (C_SCO) = SCO; + end loop; + end loop; + + if C_SCO > Last_SCO (CU) then + Fatal_Error ("Malformed SCO Vector, a condition SCO" + & " is missing"); + end if; + + pragma Assert (Kind (C_SCO) = Condition); + pragma Assert (Parent (C_SCO) = SCO); + return C_SCO; + end; + end if; + -- Find J'th (0-based) condition in decision by scanning the BDD vector for J in First .. Last loop @@ -3528,6 +3586,13 @@ package body SC_Obligations is return True; end if; + -- Assume that LLVM SCO decisions always have influence. + -- Also, for LLVM SCOs, the BDD is not populated, so we can't browse it. + + if Provider (Comp_Unit (SCO)) = LLVM then + return True; + end if; + -- Iterate over all BDD nodes to more efficiently iterate over the -- condition SCOs, and record whether we have found a branch for it. From 49a4b692952e05053ed5ab30c33fe33ca2d80fae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 29 May 2024 10:32:57 +0000 Subject: [PATCH 1200/1483] llvm-json: work-around to handle nested conditions --- tools/gnatcov/llvm_json_checkpoints.adb | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/llvm_json_checkpoints.adb b/tools/gnatcov/llvm_json_checkpoints.adb index d736f653e..d9dac92d6 100644 --- a/tools/gnatcov/llvm_json_checkpoints.adb +++ b/tools/gnatcov/llvm_json_checkpoints.adb @@ -504,6 +504,7 @@ package body LLVM_JSON_Checkpoints is Span : Local_Source_Location_Range; Id : out LLVM_Region_Id) return Boolean is + Current_Best : LLVM_Region_Id := No_LLVM_Region_Id; begin for Index in Regions.First_Index .. Regions.Last_Index loop declare @@ -512,13 +513,31 @@ package body LLVM_JSON_Checkpoints is begin if Region.Kind = Decision and then Contained_In (Span, Region.Span) then - Id := Region.Id; - return True; + if Current_Best /= No_LLVM_Region_Id then + + -- A matching decision region was already found. + + if Contained_In (Region.Span, Regions (Current_Best).Span) + then + -- The new region is smaller. + + Current_Best := Region.Id; + end if; + else + -- It is the first matching region. + + Current_Best := Region.Id; + end if; end if; end; end loop; - return False; + Id := Current_Best; + if Current_Best = No_LLVM_Region_Id then + return False; + else + return True; + end if; end Find_Parent_Decision; ----------------------- From 78c6bc80fe7a8fa6f0a016fa8eddc407ab6c30fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Wed, 12 Jun 2024 08:19:00 +0000 Subject: [PATCH 1201/1483] llvm-json: Include the JSON dump filename in the report structure to create a Source_File_Index for it --- tools/gnatcov/llvm_json_checkpoints.adb | 12 +++++++----- tools/gnatcov/llvm_json_checkpoints.ads | 3 ++- tools/gnatcov/sc_obligations.adb | 5 ++++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/tools/gnatcov/llvm_json_checkpoints.adb b/tools/gnatcov/llvm_json_checkpoints.adb index d9dac92d6..3fbca2a1c 100644 --- a/tools/gnatcov/llvm_json_checkpoints.adb +++ b/tools/gnatcov/llvm_json_checkpoints.adb @@ -100,7 +100,7 @@ package body LLVM_JSON_Checkpoints is -- Helper function for the Post-Condition of Build_Ckpt_From_JSON. function Build_Ckpt_From_JSON - (JSON_Root : JSON_Value) return LLVM_Coverage_Ckpt; + (JSON_Filename : String) return LLVM_Coverage_Ckpt; procedure Print_Report (Ckpt : LLVM_Coverage_Ckpt); -- Print the Report on STDOUT. @@ -149,7 +149,7 @@ package body LLVM_JSON_Checkpoints is procedure JSON_Load (JSON_Filename : String) is Ckpt : aliased LLVM_Coverage_Ckpt := - Build_Ckpt_From_JSON (JSON.Read_File (JSON_Filename)); + Build_Ckpt_From_JSON (JSON_Filename); begin LLVM_Trace.Trace ("Report generated"); if LLVM_Trace.Is_Active then @@ -166,11 +166,13 @@ package body LLVM_JSON_Checkpoints is -------------------------- function Build_Ckpt_From_JSON - (JSON_Root : JSON_Value) return LLVM_Coverage_Ckpt + (JSON_Filename : String) return LLVM_Coverage_Ckpt is - JSON_Files : constant JSON_Array := JSON.Child_Array (JSON_Root, "data"); + JSON_Files : constant JSON_Array := + JSON.Child_Array (JSON.Read_File (JSON_Filename), "data"); - Report : LLVM_Coverage_Ckpt; + Report : LLVM_Coverage_Ckpt := + (JSON_Filename => +JSON_Filename, others => <>); begin for JSON_File of JSON_Files loop declare diff --git a/tools/gnatcov/llvm_json_checkpoints.ads b/tools/gnatcov/llvm_json_checkpoints.ads index e91937470..a7ada98a6 100644 --- a/tools/gnatcov/llvm_json_checkpoints.ads +++ b/tools/gnatcov/llvm_json_checkpoints.ads @@ -84,7 +84,8 @@ package LLVM_JSON_Checkpoints is Element_Type => LLVM_Coverage_File_Ckpt); type LLVM_Coverage_Ckpt is record - File_Reports : LLVM_Coverage_File_Ckpt_Vector.Vector; + JSON_Filename : Unbounded_String; + File_Reports : LLVM_Coverage_File_Ckpt_Vector.Vector; end record; procedure JSON_Load (JSON_Filename : String); diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 146862cfb..b13dd973f 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -2529,10 +2529,13 @@ package body SC_Obligations is SFI : constant Source_File_Index := Get_Index_From_Full_Name (+File_Report.Filename, Source_File); + JSON_FI : constant Source_File_Index := + Get_Index_From_Full_Name + (+Ckpt.JSON_Filename, Library_File); CUID : constant CU_Id := Allocate_CU (Provider => LLVM, - Origin => No_Source_File, + Origin => JSON_FI, Main_Source => SFI, Fingerprint => No_Fingerprint, Created_Units => Created_Units); From d0ead5860447c724d6da193fe29a1d9699a2681a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Tue, 18 Jun 2024 12:58:51 +0000 Subject: [PATCH 1202/1483] tests(llvm-json): Add tests --- testsuite/SUITE/llvmutils.py | 34 + testsuite/tests/llvm/rust/basic/coverage.json | 733 +++++++++++++++ .../tests/llvm/rust/basic/src/mcdc_basic.rs | 66 ++ testsuite/tests/llvm/rust/basic/test.py | 40 + .../tests/llvm/rust/closures/coverage.json | 165 ++++ .../tests/llvm/rust/closures/src/closures.rs | 30 + testsuite/tests/llvm/rust/closures/test.py | 28 + .../llvm/rust/diff_formatting/coverage.json | 187 ++++ .../diff_formatting/src/diff_formatting.rs | 27 + .../tests/llvm/rust/diff_formatting/test.py | 53 ++ testsuite/tests/llvm/rust/impl/coverage.json | 171 ++++ testsuite/tests/llvm/rust/impl/src/impl.rs | 59 ++ testsuite/tests/llvm/rust/impl/test.py | 38 + .../tests/llvm/rust/mcdc_nested/coverage.json | 846 ++++++++++++++++++ .../llvm/rust/mcdc_nested/src/mcdc_nested.rs | 75 ++ testsuite/tests/llvm/rust/mcdc_nested/test.py | 35 + .../rust/mcdc_non_control_flow/coverage.json | 822 +++++++++++++++++ .../mcdc_non_control_flow/src/mcdc_assign.rs | 63 ++ .../llvm/rust/mcdc_non_control_flow/test.py | 40 + 19 files changed, 3512 insertions(+) create mode 100644 testsuite/SUITE/llvmutils.py create mode 100644 testsuite/tests/llvm/rust/basic/coverage.json create mode 100644 testsuite/tests/llvm/rust/basic/src/mcdc_basic.rs create mode 100644 testsuite/tests/llvm/rust/basic/test.py create mode 100644 testsuite/tests/llvm/rust/closures/coverage.json create mode 100644 testsuite/tests/llvm/rust/closures/src/closures.rs create mode 100644 testsuite/tests/llvm/rust/closures/test.py create mode 100644 testsuite/tests/llvm/rust/diff_formatting/coverage.json create mode 100644 testsuite/tests/llvm/rust/diff_formatting/src/diff_formatting.rs create mode 100644 testsuite/tests/llvm/rust/diff_formatting/test.py create mode 100644 testsuite/tests/llvm/rust/impl/coverage.json create mode 100644 testsuite/tests/llvm/rust/impl/src/impl.rs create mode 100644 testsuite/tests/llvm/rust/impl/test.py create mode 100644 testsuite/tests/llvm/rust/mcdc_nested/coverage.json create mode 100644 testsuite/tests/llvm/rust/mcdc_nested/src/mcdc_nested.rs create mode 100644 testsuite/tests/llvm/rust/mcdc_nested/test.py create mode 100644 testsuite/tests/llvm/rust/mcdc_non_control_flow/coverage.json create mode 100644 testsuite/tests/llvm/rust/mcdc_non_control_flow/src/mcdc_assign.rs create mode 100644 testsuite/tests/llvm/rust/mcdc_non_control_flow/test.py diff --git a/testsuite/SUITE/llvmutils.py b/testsuite/SUITE/llvmutils.py new file mode 100644 index 000000000..2083300ae --- /dev/null +++ b/testsuite/SUITE/llvmutils.py @@ -0,0 +1,34 @@ +"""LLVM trace utils functions. + +This modules exposes common utility functions specifically for testing the +handling of LLVM Trace Adapter inputs into GNATcov. +""" + +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import xcov + + +def check_llvm_reports( + json_file, expected_report, cov_level="stmt", path_prefix=".." +): + """ + Check that GNATcov produces the right report when given a JSON file + generated with the LLVM trace adapter. + + The test case should have this architecture : + testcase + +-- src + | +-- *.rs + +-- + +-- test.py + """ + xcov( + [ + "coverage", + f"--level={cov_level}", + f"--llvm-json-checkpoint=../{json_file}", + "--source-search=../src", + "-axcov", + ] + ) + check_xcov_reports(".", expected_report) diff --git a/testsuite/tests/llvm/rust/basic/coverage.json b/testsuite/tests/llvm/rust/basic/coverage.json new file mode 100644 index 000000000..9e2032f4b --- /dev/null +++ b/testsuite/tests/llvm/rust/basic/coverage.json @@ -0,0 +1,733 @@ +{ + "data": [ + { + "filename": "/home/peron/playground/RUST_TESTS/basic/src/mcdc_basic.rs", + "functions": [ + { + "branch_regions": [ + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 8, + 48, + 9 + ], + "true_count": 1 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 13, + 48, + 14 + ], + "true_count": 1 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 18, + 48, + 19 + ], + "true_count": 0 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 23, + 48, + 24 + ], + "true_count": 0 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 28, + 48, + 29 + ], + "true_count": 0 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 33, + 48, + 34 + ], + "true_count": 0 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 48, + 38, + 48, + 39 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 44, + 1, + 48, + 9 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 48, + 13, + 48, + 14 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 48, + 18, + 48, + 19 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 48, + 23, + 48, + 24 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 48, + 28, + 48, + 29 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 48, + 33, + 48, + 34 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 48, + 38, + 48, + 39 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 48, + 40, + 50, + 6 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 50, + 5, + 50, + 6 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 51, + 1, + 51, + 2 + ] + } + ], + "demangled_name": "mcdc_basic::condition_too_long", + "mcdc_records": [ + { + "num_conditions": 7, + "span": [ + 48, + 8, + 48, + 39 + ], + "test_vectors": [ + { + "decision_outcome": 1, + "vector": [ + 1, + 1, + -1, + -1, + -1, + -1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsdqkxZy5KxpN_10mcdc_basic18condition_too_long" + }, + { + "branch_regions": [ + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 36, + 9, + 36, + 10 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 36, + 14, + 36, + 15 + ], + "true_count": 1 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 36, + 19, + 36, + 20 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 34, + 1, + 36, + 10 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 36, + 14, + 36, + 15 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 36, + 19, + 36, + 20 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 37, + 5, + 39, + 6 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 39, + 12, + 41, + 6 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 42, + 1, + 42, + 2 + ] + } + ], + "demangled_name": "mcdc_basic::simple_not_covered", + "mcdc_records": [ + { + "num_conditions": 3, + "span": [ + 36, + 9, + 36, + 20 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 1, + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsdqkxZy5KxpN_10mcdc_basic18simple_not_covered" + }, + { + "branch_regions": [ + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 16, + 9, + 16, + 10 + ], + "true_count": 5 + }, + { + "false_count": 3, + "kind": "MCDCBranchRegion", + "span": [ + 16, + 15, + 16, + 16 + ], + "true_count": 2 + }, + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 16, + 20, + 16, + 21 + ], + "true_count": 1 + }, + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 10, + 24, + 11 + ], + "true_count": 5 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 15, + 24, + 16 + ], + "true_count": 1 + }, + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 22, + 24, + 23 + ], + "true_count": 4 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 27, + 24, + 28 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 7, + "kind": "CodeRegion", + "span": [ + 11, + 1, + 16, + 10 + ] + }, + { + "count": 5, + "kind": "CodeRegion", + "span": [ + 16, + 15, + 16, + 16 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 16, + 20, + 16, + 21 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 17, + 5, + 19, + 6 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 19, + 12, + 21, + 6 + ] + }, + { + "count": 7, + "kind": "CodeRegion", + "span": [ + 24, + 10, + 24, + 11 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 24, + 15, + 24, + 16 + ] + }, + { + "count": 6, + "kind": "CodeRegion", + "span": [ + 24, + 22, + 24, + 23 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 24, + 27, + 24, + 28 + ] + }, + { + "count": 5, + "kind": "CodeRegion", + "span": [ + 25, + 5, + 27, + 6 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 27, + 12, + 29, + 6 + ] + }, + { + "count": 7, + "kind": "CodeRegion", + "span": [ + 31, + 5, + 32, + 2 + ] + } + ], + "demangled_name": "mcdc_basic::several_decisions_in_one_fct", + "mcdc_records": [ + { + "num_conditions": 3, + "span": [ + 16, + 9, + 16, + 22 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 0, + 1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1, + -1 + ] + } + ] + }, + { + "num_conditions": 4, + "span": [ + 24, + 9, + 24, + 29 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + 0, + -1, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + -1, + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 0, + 1, + 1, + -1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1, + 0, + 1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1, + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsdqkxZy5KxpN_10mcdc_basic28several_decisions_in_one_fct" + }, + { + "branch_regions": [ + { + "false_count": 3, + "kind": "BranchRegion", + "span": [ + 4, + 8, + 4, + 13 + ], + "true_count": 4 + } + ], + "code_regions": [ + { + "count": 7, + "kind": "CodeRegion", + "span": [ + 3, + 1, + 4, + 13 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 4, + 14, + 6, + 6 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 6, + 12, + 8, + 6 + ] + }, + { + "count": 7, + "kind": "CodeRegion", + "span": [ + 9, + 1, + 9, + 2 + ] + } + ], + "demangled_name": "mcdc_basic::bar", + "mcdc_records": [], + "name": "_RNvCsdqkxZy5KxpN_10mcdc_basic3bar" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 53, + 1, + 66, + 2 + ] + } + ], + "demangled_name": "mcdc_basic::main", + "mcdc_records": [], + "name": "_RNvCsdqkxZy5KxpN_10mcdc_basic4main" + } + ] + } + ] +} diff --git a/testsuite/tests/llvm/rust/basic/src/mcdc_basic.rs b/testsuite/tests/llvm/rust/basic/src/mcdc_basic.rs new file mode 100644 index 000000000..3f99df4d5 --- /dev/null +++ b/testsuite/tests/llvm/rust/basic/src/mcdc_basic.rs @@ -0,0 +1,66 @@ +use std::hint::black_box; + +fn bar(b: u32) { + if b > 6 { + black_box("yes"); + } else { + black_box("no"); + } +} + +fn several_decisions_in_one_fct(a: bool, b: bool, c: bool, + d: bool, e: bool) { + let mut x = 0; + + if + a && (b || c) + { + x = 3; + } else { + x = 8; + } + + if + (a || d) && (e || b) + { + x += 3; + } else { + x += 8; + } + + bar(x); +} + +fn simple_not_covered(a: bool, b: bool, c: bool) { + if + a && b || c + { + black_box("yes"); + } else { + black_box("no"); + } +} + +fn condition_too_long(a: bool, b: bool, c: bool, d: bool, + e: bool, f: bool, g: bool) { + // This condition should not be instrumented by the + // current implementation, because it is too long + if a && b || c || d && e || f && g { + black_box(33); + } +} + +fn main() { + several_decisions_in_one_fct(true, false, false, true, true); + several_decisions_in_one_fct(true, true, false, true, true); + several_decisions_in_one_fct(true, false, true, true, true); + several_decisions_in_one_fct(false, false, true, true, true); + several_decisions_in_one_fct(false, false, false, false, false); + several_decisions_in_one_fct(true, false, false, false, false); + several_decisions_in_one_fct(true, true, false, false, false); + + simple_not_covered(true, true, false); + simple_not_covered(true, false, false); + + condition_too_long(true, true, true, true, true, true, false); +} diff --git a/testsuite/tests/llvm/rust/basic/test.py b/testsuite/tests/llvm/rust/basic/test.py new file mode 100644 index 000000000..2406bf45d --- /dev/null +++ b/testsuite/tests/llvm/rust/basic/test.py @@ -0,0 +1,40 @@ +""" +Check the correct loading of JSON files generated with the LLVM trace adapter. +This test checks simple constructions : several decisions in one function, +a non covered case, and a decision not instrumented because of its too +many conditions. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, multi_range +from SUITE.llvmutils import check_llvm_reports + +_wd = Wdir("tmp_") + +incomplete = {36, 48, 50} + +uncovered = set() # foo + +covered = ( + multi_range( + (3, 9), # bar + (11, 32), # several_decisions_in_one_fct + (34, 42), # simple_not_covered + (53, 66), # condition_too_long + minus=[14, 22, 23, 30], + ) + - uncovered + - incomplete +) + +expected_report = { + "mcdc_basic.rs.xcov": { + "+": covered, + "!": incomplete, + "-": uncovered, + } +} + +check_llvm_reports("coverage.json", expected_report, cov_level="stmt+mcdc") + +thistest.result() diff --git a/testsuite/tests/llvm/rust/closures/coverage.json b/testsuite/tests/llvm/rust/closures/coverage.json new file mode 100644 index 000000000..bee3adaf1 --- /dev/null +++ b/testsuite/tests/llvm/rust/closures/coverage.json @@ -0,0 +1,165 @@ +{ + "data": [ + { + "filename": "/home/peron/playground/RUST_TESTS/closures/src/closures.rs", + "functions": [ + { + "branch_regions": [], + "code_regions": [ + { + "count": 35, + "kind": "CodeRegion", + "span": [ + 14, + 27, + 14, + 39 + ] + } + ], + "demangled_name": "closures::closure_imm::{closure#0}", + "mcdc_records": [], + "name": "_RNCNvCseR1raopjrvP_8closures11closure_imm0B3_" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 35, + "kind": "CodeRegion", + "span": [ + 4, + 29, + 4, + 41 + ] + } + ], + "demangled_name": "closures::closure_in_var::{closure#0}", + "mcdc_records": [], + "name": "_RNCNvCseR1raopjrvP_8closures14closure_in_var0B3_" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 21, + 27, + 21, + 39 + ] + } + ], + "demangled_name": "closures::closure_uncovered::{closure#0}", + "mcdc_records": [], + "name": "_RNCNvCseR1raopjrvP_8closures17closure_uncovered0B3_" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 12, + 1, + 14, + 17 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 14, + 39, + 17, + 2 + ] + } + ], + "demangled_name": "closures::closure_imm", + "mcdc_records": [], + "name": "_RNvCseR1raopjrvP_8closures11closure_imm" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 3, + 1, + 4, + 16 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 6, + 9, + 10, + 2 + ] + } + ], + "demangled_name": "closures::closure_in_var", + "mcdc_records": [], + "name": "_RNvCseR1raopjrvP_8closures14closure_in_var" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 19, + 1, + 21, + 17 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 21, + 39, + 24, + 2 + ] + } + ], + "demangled_name": "closures::closure_uncovered", + "mcdc_records": [], + "name": "_RNvCseR1raopjrvP_8closures17closure_uncovered" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 26, + 1, + 30, + 2 + ] + } + ], + "demangled_name": "closures::main", + "mcdc_records": [], + "name": "_RNvCseR1raopjrvP_8closures4main" + } + ] + } + ] +} diff --git a/testsuite/tests/llvm/rust/closures/src/closures.rs b/testsuite/tests/llvm/rust/closures/src/closures.rs new file mode 100644 index 000000000..a7c944971 --- /dev/null +++ b/testsuite/tests/llvm/rust/closures/src/closures.rs @@ -0,0 +1,30 @@ +use std::hint::black_box; + +fn closure_in_var(x: u32) { + let is_even = |n: &u32| (n & 1) == 0; + + let res: Vec<_> = (0..x) + .filter(is_even) + .collect(); + black_box(res); +} + +fn closure_imm(x: u32) { + let res: Vec<_> = (0..x) + .filter(|n: &u32| (n & 1) == 0) + .collect(); + black_box(res); +} + +fn closure_uncovered(_: u32) { + let res: Vec<_> = (0..0) + .filter(|n: &u32| (n & 1) == 0) + .collect(); + black_box(res); +} + +fn main() { + closure_in_var(35); + closure_imm(35); + closure_uncovered(35); +} diff --git a/testsuite/tests/llvm/rust/closures/test.py b/testsuite/tests/llvm/rust/closures/test.py new file mode 100644 index 000000000..7ca6848e5 --- /dev/null +++ b/testsuite/tests/llvm/rust/closures/test.py @@ -0,0 +1,28 @@ +""" +Check the processing of coverage reports generated from LLVM trace adapter. +This test checks the handling of closures' coverage. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, multi_range +from SUITE.llvmutils import check_llvm_reports + +_wd = Wdir("tmp_") + +incomplete = {21} + +uncovered = set() + +expected_report = { + "closures.rs.xcov": { + "+": multi_range((3, 10), (12, 17), (19, 24), (26, 30), minus=[5]) + - incomplete + - uncovered, + "!": incomplete, + "-": uncovered, + } +} + +check_llvm_reports("coverage.json", expected_report) + +thistest.result() diff --git a/testsuite/tests/llvm/rust/diff_formatting/coverage.json b/testsuite/tests/llvm/rust/diff_formatting/coverage.json new file mode 100644 index 000000000..7588328de --- /dev/null +++ b/testsuite/tests/llvm/rust/diff_formatting/coverage.json @@ -0,0 +1,187 @@ +{ + "data": [ + { + "filename": "/home/peron/playground/RUST_TESTS/diff_formatting/src/diff_formatting.rs", + "functions": [ + { + "branch_regions": [ + { + "false_count": 1, + "kind": "BranchRegion", + "span": [ + 19, + 16, + 19, + 26 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 18, + 1, + 18, + 17 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 19, + 9, + 19, + 10 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 19, + 16, + 19, + 26 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 19, + 29, + 19, + 46 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 19, + 56, + 19, + 72 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 21, + 5, + 22, + 2 + ] + } + ], + "demangled_name": "diff_formatting::bar", + "mcdc_records": [], + "name": "_RNvCs4ofb7EzyXpa_15diff_formatting3bar" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "BranchRegion", + "span": [ + 5, + 12, + 7, + 14 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 3, + 1, + 3, + 17 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 4, + 9, + 4, + 10 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 5, + 12, + 7, + 14 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 9, + 13, + 9, + 30 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 11, + 13, + 11, + 29 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 14, + 5, + 15, + 2 + ] + } + ], + "demangled_name": "diff_formatting::foo", + "mcdc_records": [], + "name": "_RNvCs4ofb7EzyXpa_15diff_formatting3foo" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 24, + 1, + 27, + 2 + ] + } + ], + "demangled_name": "diff_formatting::main", + "mcdc_records": [], + "name": "_RNvCs4ofb7EzyXpa_15diff_formatting4main" + } + ] + } + ] +} diff --git a/testsuite/tests/llvm/rust/diff_formatting/src/diff_formatting.rs b/testsuite/tests/llvm/rust/diff_formatting/src/diff_formatting.rs new file mode 100644 index 000000000..1d98f3ca5 --- /dev/null +++ b/testsuite/tests/llvm/rust/diff_formatting/src/diff_formatting.rs @@ -0,0 +1,27 @@ +use std::hint::black_box; + +fn foo(x : u32) { + let y = + if x % 2 + == + 0 + { + black_box("even") + } else { + black_box("odd") + }; + + black_box(y); +} + +// bar is the same as foo, but formatted differently +fn bar(x : u32) { + let y = if x % 2 == 0 { black_box("even") } else { black_box("odd") }; + + black_box(y); +} + +fn main() { + foo(3); + bar(3); +} diff --git a/testsuite/tests/llvm/rust/diff_formatting/test.py b/testsuite/tests/llvm/rust/diff_formatting/test.py new file mode 100644 index 000000000..24565bf0e --- /dev/null +++ b/testsuite/tests/llvm/rust/diff_formatting/test.py @@ -0,0 +1,53 @@ +""" +Check the processing of coverage reports generated from LLVM trace adapter. +This test checks the handling of identical code that is formatted differently. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, multi_range +from SUITE.llvmutils import check_llvm_reports + +_wd = Wdir("tmp_") + +incomplete = {19} # bar + +uncovered = {9} # foo + +covered = multi_range(3, 4, 11, 14, 15, 18, 21, 22, (24, 27)) + + +expected_report = { + "diff_formatting.rs.xcov": { + "+": covered, + "!": incomplete, + "-": uncovered, + } +} + +check_llvm_reports("coverage.json", expected_report) + +# With MCDC + +mcdc_incomplete = { + 5, # foo + 19, # bar +} + +mcdc_uncovered = {6, 7, 9} # foo + +mcdc_covered = multi_range(3, 4, 11, 14, 15, 18, 21, 22, (24, 27)) + +mcdc_expected_report = { + "diff_formatting.rs.xcov": { + "+": mcdc_covered, + "!": mcdc_incomplete, + "-": mcdc_uncovered, + } +} + + +check_llvm_reports( + "coverage.json", mcdc_expected_report, cov_level="stmt+mcdc" +) + +thistest.result() diff --git a/testsuite/tests/llvm/rust/impl/coverage.json b/testsuite/tests/llvm/rust/impl/coverage.json new file mode 100644 index 000000000..30cd35456 --- /dev/null +++ b/testsuite/tests/llvm/rust/impl/coverage.json @@ -0,0 +1,171 @@ +{ + "data": [ + { + "filename": "/home/peron/playground/RUST_TESTS/impl/src/impl.rs", + "functions": [ + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 49, + 1, + 58, + 2 + ] + } + ], + "demangled_name": "impl::main", + "mcdc_records": [], + "name": "_RNvCslINASTaKc5F_4impl4main" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 8, + 5, + 12, + 6 + ] + } + ], + "demangled_name": "::new", + "mcdc_records": [], + "name": "_RNvMCslINASTaKc5F_4implNtB2_3Foo3new" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 14, + 5, + 16, + 6 + ] + } + ], + "demangled_name": "::print", + "mcdc_records": [], + "name": "_RNvMCslINASTaKc5F_4implNtB2_3Foo5print" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 44, + 5, + 46, + 6 + ] + } + ], + "demangled_name": "::hello", + "mcdc_records": [], + "name": "_RNvXs0_CslINASTaKc5F_4implNtB5_3BarNtB5_5Hello5hello" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 38, + 5, + 40, + 6 + ] + } + ], + "demangled_name": "::hello", + "mcdc_records": [], + "name": "_RNvXs_CslINASTaKc5F_4implNtB4_3FooNtB4_5Hello5hello" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 24, + 5, + 26, + 6 + ] + } + ], + "demangled_name": "::say_hello", + "mcdc_records": [], + "name": "_RNvYNtCslINASTaKc5F_4impl3BarNtB4_5Hello9say_helloB4_" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 28, + 5, + 30, + 6 + ] + } + ], + "demangled_name": "::say_bye", + "mcdc_records": [], + "name": "_RNvYNtCslINASTaKc5F_4impl3FooNtB4_5Hello7say_byeB4_" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 24, + 5, + 26, + 6 + ] + } + ], + "demangled_name": "::say_hello", + "mcdc_records": [], + "name": "_RNvYNtCslINASTaKc5F_4impl3FooNtB4_5Hello9say_helloB4_" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 32, + 5, + 34, + 6 + ] + } + ], + "demangled_name": "<_ as impl::Hello>::say_nothing", + "mcdc_records": [], + "name": "_RNvYpNtCslINASTaKc5F_4impl5Hello11say_nothingB5_" + } + ] + } + ] +} diff --git a/testsuite/tests/llvm/rust/impl/src/impl.rs b/testsuite/tests/llvm/rust/impl/src/impl.rs new file mode 100644 index 000000000..cb5d0c392 --- /dev/null +++ b/testsuite/tests/llvm/rust/impl/src/impl.rs @@ -0,0 +1,59 @@ +use std::hint::black_box; + +struct Foo { + x: u32 +} + +impl Foo { + fn new(x: u32) -> Self { + Self { + x + } + } + + fn print(&self) { + black_box(self.x); + } +} + +struct Bar; + +trait Hello { + fn hello(&self) -> &'static str; + + fn say_hello(&self) { + black_box(self.hello()); + } + + fn say_bye(&self) { + black_box("Bye"); + } + + fn say_nothing(&self) { + black_box("nothing"); + } +} + +impl Hello for Foo { + fn hello(&self) -> &'static str { + "Hola" + } +} + +impl Hello for Bar { + fn hello(&self) -> &'static str { + "Hallo" + } +} + +fn main() { + let foo = Foo::new(15); + foo.print(); + + foo.say_hello(); + Bar.say_hello(); + + foo.say_bye(); + +} + diff --git a/testsuite/tests/llvm/rust/impl/test.py b/testsuite/tests/llvm/rust/impl/test.py new file mode 100644 index 000000000..64d8aa8aa --- /dev/null +++ b/testsuite/tests/llvm/rust/impl/test.py @@ -0,0 +1,38 @@ +""" +Check the processing of coverage reports generated from LLVM trace adapter. +This test checks the handling of struct impls and trait implementations. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, multi_range +from SUITE.llvmutils import check_llvm_reports + +_wd = Wdir("tmp_") + +incomplete = {} + +uncovered = multi_range((32, 34)) + +expected_report = { + "impl.rs.xcov": { + "+": multi_range( + (8, 12), # Foo::new + (14, 16), # Foo::print + (24, 26), # Trait::say_hello + (28, 30), # Trait::say_bye + (38, 40), # ::hello + (44, 46), # ::hello + (49, 51), + 53, + 54, + 56, + 58, # main + ), + "!": incomplete, + "-": uncovered, + } +} + +check_llvm_reports("coverage.json", expected_report) + +thistest.result() diff --git a/testsuite/tests/llvm/rust/mcdc_nested/coverage.json b/testsuite/tests/llvm/rust/mcdc_nested/coverage.json new file mode 100644 index 000000000..d6ebd152d --- /dev/null +++ b/testsuite/tests/llvm/rust/mcdc_nested/coverage.json @@ -0,0 +1,846 @@ +{ + "data": [ + { + "filename": "/home/peron/playground/RUST_TESTS/mcdc_nested/src/mcdc_nested.rs", + "functions": [ + { + "branch_regions": [ + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 20, + 8, + 20, + 9 + ], + "true_count": 3 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 20, + 13, + 20, + 46 + ], + "true_count": 2 + }, + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 20, + 16, + 20, + 17 + ], + "true_count": 1 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 20, + 21, + 20, + 22 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 19, + 1, + 20, + 9 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 20, + 16, + 20, + 17 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 20, + 21, + 20, + 22 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 20, + 25, + 20, + 29 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 20, + 39, + 20, + 44 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 20, + 47, + 22, + 6 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 22, + 12, + 24, + 6 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 25, + 1, + 25, + 2 + ] + } + ], + "demangled_name": "mcdc_nested::foo_uncovered_root", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 20, + 8, + 20, + 46 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 1, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1 + ] + } + ] + }, + { + "num_conditions": 2, + "span": [ + 20, + 16, + 20, + 22 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 0, + 1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsaVIxtEfs9wh_11mcdc_nested18foo_uncovered_root" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 12, + 8, + 12, + 9 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 12, + 13, + 12, + 46 + ], + "true_count": 1 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 12, + 16, + 12, + 17 + ], + "true_count": 1 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 12, + 21, + 12, + 22 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 11, + 1, + 12, + 9 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 12, + 16, + 12, + 17 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 12, + 21, + 12, + 22 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 12, + 25, + 12, + 29 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 12, + 39, + 12, + 44 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 12, + 47, + 14, + 6 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 14, + 12, + 16, + 6 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 17, + 1, + 17, + 2 + ] + } + ], + "demangled_name": "mcdc_nested::foo_uncovered_nested", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 12, + 8, + 12, + 46 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1 + ] + } + ] + }, + { + "num_conditions": 2, + "span": [ + 12, + 16, + 12, + 22 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsaVIxtEfs9wh_11mcdc_nested20foo_uncovered_nested" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 4, + 8, + 4, + 9 + ], + "true_count": 3 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 4, + 13, + 4, + 46 + ], + "true_count": 2 + }, + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 4, + 16, + 4, + 17 + ], + "true_count": 1 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 4, + 21, + 4, + 22 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 3, + 1, + 4, + 9 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 4, + 16, + 4, + 17 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 4, + 21, + 4, + 22 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 4, + 25, + 4, + 29 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 4, + 39, + 4, + 44 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 4, + 47, + 6, + 6 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 6, + 12, + 8, + 6 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 9, + 1, + 9, + 2 + ] + } + ], + "demangled_name": "mcdc_nested::foo", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 4, + 8, + 4, + 46 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1 + ] + } + ] + }, + { + "num_conditions": 2, + "span": [ + 4, + 16, + 4, + 22 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 0, + 1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsaVIxtEfs9wh_11mcdc_nested3foo" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 51, + 1, + 75, + 2 + ] + } + ], + "demangled_name": "mcdc_nested::main", + "mcdc_records": [], + "name": "_RNvCsaVIxtEfs9wh_11mcdc_nested4main" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 28, + 8, + 28, + 9 + ], + "true_count": 4 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 29, + 9, + 32, + 32 + ], + "true_count": 4 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 29, + 12, + 29, + 13 + ], + "true_count": 4 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 30, + 13, + 31, + 36 + ], + "true_count": 0 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 30, + 16, + 30, + 17 + ], + "true_count": 0 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 30, + 21, + 30, + 22 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 5, + "kind": "CodeRegion", + "span": [ + 27, + 1, + 28, + 9 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 29, + 12, + 29, + 13 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 30, + 16, + 30, + 17 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 30, + 21, + 30, + 22 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 31, + 15, + 31, + 19 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 31, + 29, + 31, + 34 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 32, + 11, + 32, + 15 + ] + }, + { + "count": 0, + "kind": "CodeRegion", + "span": [ + 32, + 25, + 32, + 30 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 33, + 5, + 35, + 6 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 35, + 12, + 37, + 6 + ] + }, + { + "count": 5, + "kind": "CodeRegion", + "span": [ + 38, + 1, + 38, + 2 + ] + } + ], + "demangled_name": "mcdc_nested::nested_3", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 28, + 8, + 32, + 32 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1 + ] + } + ] + }, + { + "num_conditions": 2, + "span": [ + 29, + 12, + 31, + 36 + ], + "test_vectors": [ + { + "decision_outcome": 1, + "vector": [ + 1, + -1 + ] + } + ] + }, + { + "num_conditions": 2, + "span": [ + 30, + 16, + 30, + 22 + ], + "test_vectors": [] + } + ], + "name": "_RNvCsaVIxtEfs9wh_11mcdc_nested8nested_3" + } + ] + } + ] +} diff --git a/testsuite/tests/llvm/rust/mcdc_nested/src/mcdc_nested.rs b/testsuite/tests/llvm/rust/mcdc_nested/src/mcdc_nested.rs new file mode 100644 index 000000000..7a23627ac --- /dev/null +++ b/testsuite/tests/llvm/rust/mcdc_nested/src/mcdc_nested.rs @@ -0,0 +1,75 @@ +use std::hint::black_box; + +fn foo(a: bool, b: bool, c: bool) { + if a && if b || c { true } else { false } { + black_box("yes"); + } else { + black_box("no"); + } +} + +fn foo_uncovered_nested(a: bool, b: bool, c: bool) { + if a && if b || c { true } else { false } { + black_box("yes"); + } else { + black_box("no"); + } +} + +fn foo_uncovered_root(a: bool, b: bool, c: bool) { + if a && if b || c { true } else { false } { + black_box("yes"); + } else { + black_box("no"); + } +} + +fn nested_3(a: bool, b: bool, c: bool, d: bool) { + if a && + if b || + if c && d + { true } else { false } + { true } else { false } + { + black_box("yes"); + } else { + black_box("no"); + } +} + +// This test currently make llvm utility functions fail. +// (See https://github.com/llvm/llvm-project/pull/91600) +// +// fn nested_first(a: bool, b: bool, c: bool) { +// if if b || c { true } else { false } && a { +// black_box("yes"); +// } else { +// black_box("no"); +// } +// } + +fn main() { + foo(true, false, false); + foo(true, true, true); + foo(true, false, true); + foo(false, true, true); + + foo_uncovered_nested(false, true, true); + foo_uncovered_nested(true, true, false); + foo_uncovered_nested(true, false, false); + + foo_uncovered_root(true, false, false); + foo_uncovered_root(true, true, false); + foo_uncovered_root(true, false, true); + + nested_3(true, true, true, true); + nested_3(false, true, true, true); + nested_3(true, true, false, true); + nested_3(true, true, false, false); + nested_3(true, true, true, false); + + // nested_first(true, false, false); + // nested_first(true, true, true); + // nested_first(true, false, true); + // nested_first(false, true, true); +} diff --git a/testsuite/tests/llvm/rust/mcdc_nested/test.py b/testsuite/tests/llvm/rust/mcdc_nested/test.py new file mode 100644 index 000000000..042a00e20 --- /dev/null +++ b/testsuite/tests/llvm/rust/mcdc_nested/test.py @@ -0,0 +1,35 @@ +""" +Check the processing of coverage reports generated from LLVM trace adapter. +This test checks the handling of MCDC instrumentation of nested decisions. + +Note: For now, there is a construct (see mcdc_nested.rs) that make the trace\ +adapter crash when trying to build the mappings' representation from the +profdata file. +This is an LLVM issue, see https://github.com/llvm/llvm-project/pull/91600 +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, multi_range +from SUITE.llvmutils import check_llvm_reports + +_wd = Wdir("tmp_") + +uncovered_mcdc_decisions = multi_range(12, 20, (28, 32)) # nested_3 + +expected_report = { + "mcdc_nested.rs.xcov": { + "+": multi_range( + (3, 9), # foo + (11, 17), # foo_uncovered_nested + (19, 25), # foo_uncovered_root + (27, 38), # nested_3 + (51, 75), # main + ) + - uncovered_mcdc_decisions, + "!": uncovered_mcdc_decisions, + } +} + +check_llvm_reports("coverage.json", expected_report, cov_level="stmt+mcdc") + +thistest.result() diff --git a/testsuite/tests/llvm/rust/mcdc_non_control_flow/coverage.json b/testsuite/tests/llvm/rust/mcdc_non_control_flow/coverage.json new file mode 100644 index 000000000..b98b3b5de --- /dev/null +++ b/testsuite/tests/llvm/rust/mcdc_non_control_flow/coverage.json @@ -0,0 +1,822 @@ +{ + "data": [ + { + "filename": "/home/peron/playground/RUST_TESTS/mcdc_non_control_flow/src/mcdc_assign.rs", + "functions": [ + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 4, + 13, + 4, + 14 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 4, + 18, + 4, + 19 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 3, + 1, + 3, + 33 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 4, + 9, + 4, + 10 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 4, + 13, + 4, + 14 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 4, + 18, + 4, + 19 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 5, + 5, + 6, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::assign_and", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 4, + 13, + 4, + 19 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1 + ] + } + ] + } + ], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign10assign_and" + }, + { + "branch_regions": [ + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 19, + 13, + 19, + 14 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 19, + 18, + 19, + 19 + ], + "true_count": 1 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 19, + 23, + 19, + 24 + ], + "true_count": 2 + } + ], + "code_regions": [ + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 18, + 1, + 18, + 44 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 19, + 9, + 19, + 10 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 19, + 13, + 19, + 14 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 19, + 18, + 19, + 19 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 19, + 23, + 19, + 24 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 20, + 5, + 21, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::assign_3_bis", + "mcdc_records": [ + { + "num_conditions": 3, + "span": [ + 19, + 13, + 19, + 24 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 1, + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 0, + -1, + 1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign12assign_3_bis" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 13, + 24, + 14 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 19, + 24, + 20 + ], + "true_count": 1 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 25, + 24, + 26 + ], + "true_count": 1 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 31, + 24, + 32 + ], + "true_count": 1 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 24, + 36, + 24, + 39 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 23, + 1, + 23, + 65 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 24, + 9, + 24, + 10 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 24, + 13, + 24, + 14 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 24, + 19, + 24, + 20 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 24, + 25, + 24, + 26 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 24, + 31, + 24, + 32 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 24, + 36, + 24, + 39 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 25, + 5, + 26, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::right_comb_tree", + "mcdc_records": [ + { + "num_conditions": 5, + "span": [ + 24, + 13, + 24, + 42 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1, + -1, + -1, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + 0, + -1, + -1, + -1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1, + 1, + 1, + 1 + ] + } + ] + } + ], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign15right_comb_tree" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 28, + 1, + 30, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::foo", + "mcdc_records": [], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign3foo" + }, + { + "branch_regions": [], + "code_regions": [ + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 36, + 1, + 62, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::main", + "mcdc_records": [], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign4main" + }, + { + "branch_regions": [ + { + "false_count": 2, + "kind": "MCDCBranchRegion", + "span": [ + 14, + 13, + 14, + 14 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 14, + 18, + 14, + 19 + ], + "true_count": 1 + }, + { + "false_count": 0, + "kind": "MCDCBranchRegion", + "span": [ + 14, + 23, + 14, + 24 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 13, + 1, + 13, + 40 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 14, + 9, + 14, + 10 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 14, + 13, + 14, + 14 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 14, + 18, + 14, + 19 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 14, + 23, + 14, + 24 + ] + }, + { + "count": 4, + "kind": "CodeRegion", + "span": [ + 15, + 5, + 16, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::assign_3", + "mcdc_records": [ + { + "num_conditions": 3, + "span": [ + 14, + 13, + 14, + 24 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + 0, + -1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 0, + 1, + 1 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign8assign_3" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 9, + 13, + 9, + 14 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 9, + 18, + 9, + 19 + ], + "true_count": 0 + } + ], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 8, + 1, + 8, + 32 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 9, + 9, + 9, + 10 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 9, + 13, + 9, + 14 + ] + }, + { + "count": 1, + "kind": "CodeRegion", + "span": [ + 9, + 18, + 9, + 19 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 10, + 5, + 11, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::assign_or", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 9, + 13, + 9, + 19 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + -1 + ] + } + ] + } + ], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign9assign_or" + }, + { + "branch_regions": [ + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 33, + 9, + 33, + 10 + ], + "true_count": 2 + }, + { + "false_count": 1, + "kind": "MCDCBranchRegion", + "span": [ + 33, + 14, + 33, + 15 + ], + "true_count": 1 + } + ], + "code_regions": [ + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 32, + 1, + 33, + 10 + ] + }, + { + "count": 2, + "kind": "CodeRegion", + "span": [ + 33, + 14, + 33, + 15 + ] + }, + { + "count": 3, + "kind": "CodeRegion", + "span": [ + 34, + 1, + 34, + 2 + ] + } + ], + "demangled_name": "mcdc_assign::func_call", + "mcdc_records": [ + { + "num_conditions": 2, + "span": [ + 33, + 9, + 33, + 15 + ], + "test_vectors": [ + { + "decision_outcome": 0, + "vector": [ + 0, + -1 + ] + }, + { + "decision_outcome": 0, + "vector": [ + 1, + 0 + ] + }, + { + "decision_outcome": 1, + "vector": [ + 1, + 1 + ] + } + ] + } + ], + "name": "_RNvCsec1j5E2arBH_11mcdc_assign9func_call" + } + ] + } + ] +} diff --git a/testsuite/tests/llvm/rust/mcdc_non_control_flow/src/mcdc_assign.rs b/testsuite/tests/llvm/rust/mcdc_non_control_flow/src/mcdc_assign.rs new file mode 100644 index 000000000..85aa5e4d4 --- /dev/null +++ b/testsuite/tests/llvm/rust/mcdc_non_control_flow/src/mcdc_assign.rs @@ -0,0 +1,63 @@ +use std::hint::black_box; + +fn assign_and(a: bool, b: bool) { + let x = a && b; + black_box(x); +} + +fn assign_or(a: bool, b: bool) { + let x = a || b; + black_box(x); +} + +fn assign_3(a: bool, b: bool, c: bool) { + let x = a || b && c; + black_box(x); +} + +fn assign_3_bis(a: bool, b: bool, c: bool) { + let x = a && b || c; + black_box(x); +} + +fn right_comb_tree(a: bool, b: bool, c: bool, d: bool, e: bool) { + let x = a && (b && (c && (d && (e)))); + black_box(x); +} + +fn foo(a: bool) -> bool { + black_box(a) +} + +fn func_call(a: bool, b: bool) { + foo(a && b); +} + +fn main() { + assign_and(true, false); + assign_and(true, true); + assign_and(false, false); + + assign_or(true, false); + assign_or(true, true); + assign_or(false, false); + + assign_3(true, false, false); + assign_3(true, true, false); + assign_3(false, false, true); + assign_3(false, true, true); + + assign_3_bis(true, false, false); + assign_3_bis(true, true, false); + assign_3_bis(false, false, true); + assign_3_bis(false, true, true); + + right_comb_tree(false, false, false, true, true); + right_comb_tree(true, false, false, true, true); + right_comb_tree(true, true, true, true, true); + + func_call(true, false); + func_call(true, true); + func_call(false, false); +} + diff --git a/testsuite/tests/llvm/rust/mcdc_non_control_flow/test.py b/testsuite/tests/llvm/rust/mcdc_non_control_flow/test.py new file mode 100644 index 000000000..73e1ba32f --- /dev/null +++ b/testsuite/tests/llvm/rust/mcdc_non_control_flow/test.py @@ -0,0 +1,40 @@ +""" +Check the processing of coverage reports generated from LLVM trace adapter. +This test checksthe handling of MCDC instrumentation in non-control flow +decisions. +Specifically, it checks that the last operand was successfully instrumented. +""" + +from SUITE.context import thistest +from SUITE.cutils import Wdir, multi_range +from SUITE.llvmutils import check_llvm_reports + +_wd = Wdir("tmp_") + +uncovered_mcdc_decisions = { + 9, # assign_or + 14, # assign_3 + 19, # assign_3_bis + 24, # right_comb_tree +} + +expected_report = { + "mcdc_assign.rs.xcov": { + "+": multi_range( + (3, 6), # assign_and + (8, 11), # assign_or + (13, 16), # assign_3 + (18, 21), # assign_3_bis + (23, 26), # right_comb_tree + (28, 30), # foo + (32, 34), # func_call + (36, 62), # main + ) + - uncovered_mcdc_decisions, + "!": uncovered_mcdc_decisions, + } +} + +check_llvm_reports("coverage.json", expected_report, cov_level="stmt+mcdc") + +thistest.result() From edb999ab040feedbd1847b239a4fb3707acf259a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 24 Apr 2025 12:58:32 +0000 Subject: [PATCH 1203/1483] SS_Annotations.Add_Annotation: fix the call to Project.Lookup_Source This function expects an absolute filename: normalize the filename coming from the command-line argument to respect this contract. While this went unnoticed so far, this will be necessary once `Project.Lookup_Source` starts using `Paths.Platform_Independent_Basename`, which can deal only with absolute filenames. --- tools/gnatcov/ss_annotations.adb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/ss_annotations.adb b/tools/gnatcov/ss_annotations.adb index e55db643f..43be452d3 100644 --- a/tools/gnatcov/ss_annotations.adb +++ b/tools/gnatcov/ss_annotations.adb @@ -799,7 +799,12 @@ package body SS_Annotations is Target_File := Create (+(+Args.Remaining_Args.Last_Element)); if Is_Project_Loaded then - Source := Project.Lookup_Source (+Target_File.Full_Name); + declare + Normalized : constant Virtual_File := + Create (Target_File.Full_Name, Normalize => True); + begin + Source := Project.Lookup_Source (Normalized.Display_Full_Name); + end; if not Source.Is_Defined then Fatal_Error (Target_File.Display_Full_Name From 036d097adf3acc65356344cb34d6573f5cb2baee Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 24 Apr 2025 08:13:05 +0000 Subject: [PATCH 1204/1483] project.adb: use a failsafe file basename extracting function This fixes the remaining Windows-specific regressions that started after the GPR2 transition, due to calling `Ada.Directories.Simple_Path` on an invalid filename (`...`). --- tools/gnatcov/project.adb | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 9bd749ebc..863bd84d3 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -1667,20 +1667,37 @@ package body Project is function Lookup_Source (Full_Name : String) return GPR2.Build.Source.Object is - Basename : constant GPR2.Simple_Name := - GPR2.Simple_Name (Simple_Name (Full_Name)); - Resolved : constant GPR2.Path_Name.Object := - GPR2.Path_Name.Create_File (GPR2.Filename_Type (Full_Name)); + -- Full_Name can come from debug info or from another OS, so it may be + -- an invalid filename for the current host OS (for instance + -- ""). Because of this, calling Ada.Directories.Simple_Name + -- to extract the basename may trigger an exception. Use our own + -- extraction helper (Platform_Independent_Basename) that will not crash + -- in these legitimate cases. + + Basename : constant String := Platform_Independent_Basename (Full_Name); begin - for P of Prj_Tree.Root_Project.Closure (Include_Self => True) loop + -- Likewise, GPR2 has restrictions on what a "Simple_Name" can be: do + -- not bother performing a GPR lookup if the basename we have is invalid + -- according to GPR2. + + if GPR2.Is_Simple_Name (GPR2.Filename_Type (Basename)) then declare - Source : constant GPR2.Build.Source.Object := P.Source (Basename); + Resolved : constant GPR2.Path_Name.Object := + GPR2.Path_Name.Create_File (GPR2.Filename_Type (Full_Name)); begin - if Source.Is_Defined and then Source.Path_Name = Resolved then - return Source; - end if; + for P of Prj_Tree.Root_Project.Closure (Include_Self => True) loop + declare + Source : constant GPR2.Build.Source.Object := + P.Source (GPR2.Simple_Name (Basename)); + begin + if Source.Is_Defined and then Source.Path_Name = Resolved + then + return Source; + end if; + end; + end loop; end; - end loop; + end if; return GPR2.Build.Source.Undefined; end Lookup_Source; From 84abc268e83469dd3306533a6a07bec02b315295 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 25 Apr 2025 12:41:49 +0000 Subject: [PATCH 1205/1483] SC_Obligations.Condition: subscript to the correct SCO vector --- .../414-sid-cons-static-cond-diff/main.adb | 14 ++++ .../414-sid-cons-static-cond-diff/pkg__v1.ads | 3 + .../414-sid-cons-static-cond-diff/pkg__v2.ads | 3 + .../414-sid-cons-static-cond-diff/prelude.adb | 9 +++ .../414-sid-cons-static-cond-diff/test.opt | 1 + .../414-sid-cons-static-cond-diff/test.py | 77 +++++++++++++++++++ tools/gnatcov/sc_obligations.adb | 3 +- 7 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/414-sid-cons-static-cond-diff/main.adb create mode 100644 testsuite/tests/414-sid-cons-static-cond-diff/pkg__v1.ads create mode 100644 testsuite/tests/414-sid-cons-static-cond-diff/pkg__v2.ads create mode 100644 testsuite/tests/414-sid-cons-static-cond-diff/prelude.adb create mode 100644 testsuite/tests/414-sid-cons-static-cond-diff/test.opt create mode 100644 testsuite/tests/414-sid-cons-static-cond-diff/test.py diff --git a/testsuite/tests/414-sid-cons-static-cond-diff/main.adb b/testsuite/tests/414-sid-cons-static-cond-diff/main.adb new file mode 100644 index 000000000..a93975682 --- /dev/null +++ b/testsuite/tests/414-sid-cons-static-cond-diff/main.adb @@ -0,0 +1,14 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; +with Prelude; + +procedure Main is +begin + Prelude; + if Pkg.B then + Put_Line ("B is True"); + else + Put_Line ("B is False"); + end if; +end Main; diff --git a/testsuite/tests/414-sid-cons-static-cond-diff/pkg__v1.ads b/testsuite/tests/414-sid-cons-static-cond-diff/pkg__v1.ads new file mode 100644 index 000000000..08a184067 --- /dev/null +++ b/testsuite/tests/414-sid-cons-static-cond-diff/pkg__v1.ads @@ -0,0 +1,3 @@ +package Pkg is + B : constant Boolean := False; +end Pkg; diff --git a/testsuite/tests/414-sid-cons-static-cond-diff/pkg__v2.ads b/testsuite/tests/414-sid-cons-static-cond-diff/pkg__v2.ads new file mode 100644 index 000000000..a0a811c22 --- /dev/null +++ b/testsuite/tests/414-sid-cons-static-cond-diff/pkg__v2.ads @@ -0,0 +1,3 @@ +package Pkg is + B : constant Boolean := True; +end Pkg; diff --git a/testsuite/tests/414-sid-cons-static-cond-diff/prelude.adb b/testsuite/tests/414-sid-cons-static-cond-diff/prelude.adb new file mode 100644 index 000000000..4e1b6c3e8 --- /dev/null +++ b/testsuite/tests/414-sid-cons-static-cond-diff/prelude.adb @@ -0,0 +1,9 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Prelude is +begin + Put_Line ("This"); + Put_Line ("is"); + Put_Line ("the"); + Put_Line ("prelude"); +end Prelude; diff --git a/testsuite/tests/414-sid-cons-static-cond-diff/test.opt b/testsuite/tests/414-sid-cons-static-cond-diff/test.opt new file mode 100644 index 000000000..40a7e7cb0 --- /dev/null +++ b/testsuite/tests/414-sid-cons-static-cond-diff/test.opt @@ -0,0 +1 @@ +!src-traces DEAD diff --git a/testsuite/tests/414-sid-cons-static-cond-diff/test.py b/testsuite/tests/414-sid-cons-static-cond-diff/test.py new file mode 100644 index 000000000..7a4fd76d8 --- /dev/null +++ b/testsuite/tests/414-sid-cons-static-cond-diff/test.py @@ -0,0 +1,77 @@ +""" +Regression test: ensure that "gnatcov coverage" can load alternative SIDs for +the same unit (here: Main) when it contains a SCO condition that has different +static evaluations in both SIDs. +""" + +from e3.fs import cp, mkdir + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, xcov + + +tmp = Wdir("tmp_") + +# Create a project with two alternative sources for one unit (Pkg) depending on +# a GPR external. +gpr = gprfor( + mains=["main.adb"], + srcdirs=[".."], + extra=""" + type Pkg_Version_Type is ("v1", "v2"); + Pkg_Version : Pkg_Version_Type := external("PKG_VERSION"); + package Naming is + for Spec ("Pkg") use "pkg__" & Pkg_Version & ".ads"; + end Naming; + """, +) + +# Create subdirectories to group the SID and trace files for "gnatcov coverage" +# to load. +mkdir("sids") +mkdir("traces") + +# In order to reproduce the crash, it was necessary to first load a SID with N +# SCO statements (here: prelude.sid, which is the same regardless of the +# selected Pkg variant), and then load the two SIDs (here: for the Main unit) +# that contain the SCO condition with different static evaluations ("if Pkg.B" +# in main.adb). Consolidation code used to use the condition SCO index from the +# SID to load (likely 2 here, SCO 1 being the statement call to Prelude) to +# wrongly subscript gnatcov's interned SCO table (SCO 2 being the second +# Put_Line statement call in prelude.adb). +sids = ["obj/prelude.sid"] +traces = [] +for v in ["v1", "v2"]: + cov_args = build_and_run( + gprsw=GPRswitches(root_project=gpr, xvars=[("PKG_VERSION", v)]), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], + ) + + # Keep a side copy of the trace file and the SID for main.adb + trace_copy = f"traces/main-{v}.srctrace" + cp(cov_args[-1], trace_copy) + traces.append(trace_copy) + + sid_copy = f"sids/main-{v}.sid" + cp("obj/main.sid", sid_copy) + sids.append(sid_copy) + +sid_args = [f"--sid={f}" for f in sids] +xcov( + ["coverage", "-cstmt", "-axcov", "--output-dir=xcov", *sid_args, *traces], + out="coverage.log", +) +check_xcov_reports( + "xcov", + { + "prelude.adb.xcov": {"+": {5, 6, 7, 8}}, + "main.adb.xcov": {"+": {8, 9, 12}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index b13dd973f..ad19a3e2a 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -2782,7 +2782,8 @@ package body SC_Obligations is is use BDD; - SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); + SCOD : SCO_Descriptor renames + Vectors.SCO_Vector.Constant_Reference (SCO); First : constant BDD_Node_Id := SCOD.Decision_BDD.First_Node; Last : constant BDD_Node_Id := SCOD.Decision_BDD.Last_Node; From 69e1dbf894e10dd428c758b011e03163cdc33fb6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 25 Apr 2025 08:44:14 +0000 Subject: [PATCH 1206/1483] T825-010-naming-scheme: add special handling for a tool limitation This fixes the remaining regressions for this testcase (binary traces mode on Windows). --- testsuite/tests/T825-010-naming-scheme/test.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/testsuite/tests/T825-010-naming-scheme/test.py b/testsuite/tests/T825-010-naming-scheme/test.py index 7e60255a2..4d01b879e 100644 --- a/testsuite/tests/T825-010-naming-scheme/test.py +++ b/testsuite/tests/T825-010-naming-scheme/test.py @@ -52,6 +52,18 @@ mains=["main"], extra_coverage_args=["-axcov", "--output-dir=report"], ) + + # On Windows, GNAT stores sources file basenames in ALI files as lowercase, + # so for binary traces, gnatcov has no way to find out the original casing + # for source files that are not mentionned in the debug info (in our test + # project: spec files). + if ( + thistest.options.trace_mode == "bin" + and thistest.env.build.os.name == "windows" + ): + pkg_spec = pkg_spec.lower() + child_spec = child_spec.lower() + check_xcov_reports( "report", { From 8081b755f2598cab224e60aa2e146665a2cda3b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 25 Apr 2025 10:39:53 +0200 Subject: [PATCH 1207/1483] GNATcov_RTS: Add import clause for buffer in Witness procedure This ensure that the compiler does not insert initialization code for the overlay, which can happen with the Normalize_Scalars or Initialize_Scalars configuration pragmas. --- tools/gnatcov/rts/gnatcov_rts-buffers.adb | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.adb b/tools/gnatcov/rts/gnatcov_rts-buffers.adb index a38584946..aa4751120 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.adb +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.adb @@ -33,6 +33,7 @@ package body GNATcov_RTS.Buffers is procedure Witness (Buffer_Address : System.Address; Bit : Bit_Id) is Buffer : Coverage_Buffer_Type (0 .. Bit); for Buffer'Address use Buffer_Address; + pragma Import (Ada, Buffer); begin -- Here and below: deactivate warnings about possible exception -- propagation under light runtimes. From b20ef65d07f78b901a8b20c5488eef2d2e630654 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 23 Apr 2025 17:58:52 +0200 Subject: [PATCH 1208/1483] tests: Add a parameter to TestCase to explicitely expect a non-zero exit code --- testsuite/SCOV/internals/driver.py | 5 +++- testsuite/SCOV/tc.py | 4 ++++ testsuite/SUITE/tutils.py | 37 +++++++++++++++++++++++++++--- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index f5fd1760d..8407888c5 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -1546,7 +1546,10 @@ def mode_execute(self, main): out_file = "cmdrun_{}.out".format(main) main_path = os.path.join(self.abdir_for(main), exename_for(main)) run_cov_program( - main_path, out=out_file, register_failure=register_failure + main_path, + out=out_file, + register_failure=register_failure, + expect_non_zero_code=self.testcase.expect_non_zero_code, ) # If the dump channel just writes text on stdout, extract traces from diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index 063d15723..5e7bb23f1 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -136,6 +136,7 @@ def __init__( extracargs="", category=CAT.auto, tolerate_messages=None, + expect_non_zero_code=False, assert_lvl=None, fun_call_lvl=False, gexpr_lvl=False, @@ -143,6 +144,9 @@ def __init__( # By default, these test cases expect no error from subprocesses (xrun, # xcov, etc.) self.expect_failures = False + # Specifically expect the test binary (eventually run in a + # cross environment) to return a non-zero exit code. + self.expect_non_zero_code = expect_non_zero_code # Pass tolerate_messages to gnatcov instrument invocations (see the doc # for xcov_instrument). diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 472376d2a..a15fed9cd 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -804,7 +804,14 @@ def xcov_suite_args( def cmdrun( - cmd, for_pgm, inp=None, out=None, err=None, env=None, register_failure=True + cmd, + for_pgm, + inp=None, + out=None, + err=None, + env=None, + register_failure=True, + expect_non_zero_code=False, ): """ Execute the command+args list in CMD, redirecting its input, output and @@ -818,6 +825,11 @@ def cmdrun( REGISTER_FAILURE) also check the program's output for an occurrence of unhandled exception in cross configurations. + In case EXPECT_NON_ZERO_CODE is True, and the command runs successfully + and returns a null exit code, will stop the test with FatalError. + + EXPECT_NON_ZERO_CODE=True overrides REGISTER_FAILURE=False + In absence of fatal error, return the process descriptor. """ @@ -840,7 +852,15 @@ def cmdrun( # Check for FatalError conditions. Minimize the situations where we look # into the program's output as this is a central spot. - if register_failure and p.status != 0: + if expect_non_zero_code: + if p.status == 0: + thistest.stop( + FatalError( + '"%s"' % " ".join(cmd) + ": expected non-zero exit code", + outfile=out, + ) + ) + elif register_failure and p.status != 0: output = contents_of(out) if out else p.out thistest.stop( FatalError( @@ -1057,7 +1077,12 @@ def xrun( def run_cov_program( - executable, out=None, env=None, exec_args=None, register_failure=True + executable, + out=None, + env=None, + exec_args=None, + register_failure=True, + expect_non_zero_code=False, ): """ Assuming that `executable` was instrumented, run it according to the @@ -1130,6 +1155,11 @@ def run_cov_program( # where the source trace may be created (see below). "--save-temps", ] + + # pycross might obfuscate the error exit code in light runtime cases. + expect_non_zero_code = ( + expect_non_zero_code and not RUNTIME_INFO.has_light_runtime + ) else: # Native programs using a light runtime can't set the exit code, and # will often terminate with a non-zero status code even though nothing @@ -1147,6 +1177,7 @@ def run_cov_program( inp=inp, env=env, register_failure=register_failure, + expect_non_zero_code=expect_non_zero_code, for_pgm=True, ) From 997022da67d9a299c4282393bdae80cce0280400 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 23 Apr 2025 18:02:06 +0200 Subject: [PATCH 1209/1483] test(funcall-c): Fix usage of `exit()` in light-stm32f4 context --- .../c/function-pointer-call-chain/src/test_abort.c | 2 +- .../c/function-pointer-call-chain/test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c index 7f16f7fe3..c887dca8d 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c @@ -17,7 +17,7 @@ struct list * head_abort () { /* GNATCOV_DUMP_BUFFERS */ - exit (0); // # not-call + abort (); // # not-call return HEAD; // # not-reached } diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.py b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.py index 98209dcc0..0952c6194 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.py +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.py @@ -7,7 +7,7 @@ from SCOV.tctl import CAT, CovControl from SUITE.context import thistest -TestCase(category=CAT.stmt, fun_call_lvl=True).run( +TestCase(category=CAT.stmt, fun_call_lvl=True, expect_non_zero_code=True).run( covcontrol=CovControl(dump_trigger="manual") ) thistest.result() From 745f04937689268b6caa10975921070455be26a9 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 28 Apr 2025 15:21:25 +0200 Subject: [PATCH 1210/1483] test(345-live-observability): Adapt test to actual usecase - Do not instrument the main file - Check that going twice in the same code behaves as expected --- .../tests/345-live-observability/libpkg.gpr | 7 +++++ .../345-live-observability/src-lib/pkg.adb | 21 +++++++++++++ .../345-live-observability/src-lib/pkg.ads | 7 +++++ .../tests/345-live-observability/src/main.adb | 30 +++++++++++-------- .../tests/345-live-observability/test.py | 21 +++++++++++-- 5 files changed, 70 insertions(+), 16 deletions(-) create mode 100644 testsuite/tests/345-live-observability/libpkg.gpr create mode 100644 testsuite/tests/345-live-observability/src-lib/pkg.adb create mode 100644 testsuite/tests/345-live-observability/src-lib/pkg.ads diff --git a/testsuite/tests/345-live-observability/libpkg.gpr b/testsuite/tests/345-live-observability/libpkg.gpr new file mode 100644 index 000000000..8b72adf89 --- /dev/null +++ b/testsuite/tests/345-live-observability/libpkg.gpr @@ -0,0 +1,7 @@ +library project LibPkg is + for Source_Dirs use ("src-lib"); + for Object_Dir use "obj-lib"; + + for Library_Name use "pkg"; + for Library_Dir use "lib"; +end LibPkg; diff --git a/testsuite/tests/345-live-observability/src-lib/pkg.adb b/testsuite/tests/345-live-observability/src-lib/pkg.adb new file mode 100644 index 000000000..57f409981 --- /dev/null +++ b/testsuite/tests/345-live-observability/src-lib/pkg.adb @@ -0,0 +1,21 @@ +with Ada.Text_IO; use Ada.Text_IO; + +package body Pkg is + + procedure Foo (B : Boolean) is + begin + if B then -- if-stmt is 1 SCO + Put_Line("B is True"); -- 1 SCO, unless --block + Put_Line("I swear it is True"); -- 1 SCO + else + Put_Line("B is False :("); -- 1 SCO + end if; + end Foo; + + procedure Bar (A : Integer) is + I : Integer := 155 + A; -- 1 SCO, unless --block + begin + Put_Line (Integer'Image (I)); -- 1 SCO + end Bar; + +end Pkg; diff --git a/testsuite/tests/345-live-observability/src-lib/pkg.ads b/testsuite/tests/345-live-observability/src-lib/pkg.ads new file mode 100644 index 000000000..45f0bfb96 --- /dev/null +++ b/testsuite/tests/345-live-observability/src-lib/pkg.ads @@ -0,0 +1,7 @@ +package Pkg is + + procedure Foo (B : Boolean); + + procedure Bar (A : Integer); + +end Pkg; diff --git a/testsuite/tests/345-live-observability/src/main.adb b/testsuite/tests/345-live-observability/src/main.adb index de698ed8b..32a450257 100644 --- a/testsuite/tests/345-live-observability/src/main.adb +++ b/testsuite/tests/345-live-observability/src/main.adb @@ -1,26 +1,30 @@ with Ada.Text_IO; use Ada.Text_IO; with GCVRT.Gen.Observe; use GCVRT.Gen.Observe; +with Pkg; procedure Main is - N : Integer; begin - -- Two statements executed - -- - the one for the declaration of N - -- - the one for this specific statement + -- No statement should be covered yet here. Put_Line ("First: " & Positive'Image (Sum_Buffer_Bits)); - N := 5; + Pkg.Foo (False); - -- 2 two statements were executed since last call. + -- 2 statements were executed since last call. + -- (if stmt + False Put_Line) Put_Line ("Second: " & Positive'Image (Sum_Buffer_Bits)); - if N > 3 then - Put_Line ("Foo"); - Put_Line ("Bar"); - else - Put_Line ("Baz"); - end if; + Pkg.Foo (True); - -- 4 more statements were executed (including the if stmt). + -- 2 statements were executed since last call. + -- (if stmt is already covered, + 2 Put_Lines) Put_Line ("Third: " & Positive'Image (Sum_Buffer_Bits)); + + -- No change since last call + Put_Line ("Third-bis: " & Positive'Image (Sum_Buffer_Bits)); + + Pkg.Bar (42); + + -- 2 more statements covered + -- (Integer declaration, Put_Line) + Put_Line ("Fourth: " & Positive'Image (Sum_Buffer_Bits)); end Main; diff --git a/testsuite/tests/345-live-observability/test.py b/testsuite/tests/345-live-observability/test.py index 00c8f5620..e6c952c33 100644 --- a/testsuite/tests/345-live-observability/test.py +++ b/testsuite/tests/345-live-observability/test.py @@ -16,7 +16,10 @@ build_and_run( gprsw=GPRswitches( - root_project=gprfor(mains=["main.adb"], srcdirs=["../src"]), + root_project=gprfor( + mains=["main.adb"], srcdirs=["../src"], deps=["../libpkg.gpr"] + ), + projects=["libpkg"], ), mains=["main"], covlevel="stmt", @@ -27,9 +30,9 @@ # In case block instrumentation is enabled, the number of bits set to 1 in the # buffers is not equivalent to the number of statements executed. if thistest.options.block: - counts = [0, 0, 3] + counts = [0, 2, 3, 4] else: - counts = [2, 4, 8] + counts = [0, 2, 4, 6] OUTPUT = contents_of("main_output.txt") @@ -51,4 +54,16 @@ OUTPUT, ) +thistest.fail_if_no_match( + "Wrong third-bis buffer sum", + re.compile(f".*Third-bis: *{counts[2]}.*", re.S), + OUTPUT, +) + +thistest.fail_if_no_match( + "Wrong fourth buffer sum", + re.compile(f".*Fourth: *{counts[3]}.*", re.S), + OUTPUT, +) + thistest.result() From eefd969c2a6d7b8b8e332d585d9decfa951e43bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 28 Apr 2025 15:47:18 +0200 Subject: [PATCH 1211/1483] Instrument.Ada_Unit: Propagate calling convention to null procedure wrappers Null procedures are instrumented by instantiating a generic procedure to host the witness call. This instance should be subtype conformant with the procedure that renames it, according to RM 8.5.4 (5/3). This includes matching calling conventions, the calling convention of the original null procedure must thus also be applied to the instance. --- .../408-null-proc-convention/src/pkg.adb | 28 ++++++ .../408-null-proc-convention/src/pkg.ads | 15 +++ .../408-null-proc-convention/src/test_0.adb | 11 +++ .../src/test_full.adb | 14 +++ .../408-null-proc-convention/test.opt | 1 + .../408-null-proc-convention/test.py | 11 +++ tools/gnatcov/instrument-ada_unit.adb | 95 ++++++++++++++++++- 7 files changed, 174 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/408-null-proc-convention/src/test_0.adb create mode 100644 testsuite/tests/instr-cov/408-null-proc-convention/src/test_full.adb create mode 100644 testsuite/tests/instr-cov/408-null-proc-convention/test.opt create mode 100644 testsuite/tests/instr-cov/408-null-proc-convention/test.py diff --git a/testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.adb b/testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.adb new file mode 100644 index 000000000..244590709 --- /dev/null +++ b/testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.adb @@ -0,0 +1,28 @@ +pragma Ada_2012; + +package body Pkg is + procedure Foo (X : Integer) is null; -- # st + + procedure Bar (X : Integer) is null; -- # st + + procedure Qux (X : Integer) is null; -- # st + pragma Convention (C, Qux); + + procedure Corge (X : Integer) is null with Convention => C; -- # st + + procedure Clip (X : Integer) is null; -- # st + pragma Export + (Convention => C, + Entity => Clip, + External_Name => "clip"); + + procedure Baz (X : Integer) is + begin + Qux (X); -- # st + Corge (X); -- # st + Clip (X); -- # st + end Baz; + + procedure Blop (X : Integer) is null; -- # st + +end Pkg; diff --git a/testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.ads b/testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.ads new file mode 100644 index 000000000..69c296397 --- /dev/null +++ b/testsuite/tests/instr-cov/408-null-proc-convention/src/pkg.ads @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package Pkg is + procedure Foo (X : Integer); + pragma Convention (C, Foo); + + procedure Bar (X : Integer) with + Convention => C; + + procedure Baz (X : Integer); + + procedure Blop (X : Integer); + pragma Export (C, Blop, "blop"); + +end Pkg; diff --git a/testsuite/tests/instr-cov/408-null-proc-convention/src/test_0.adb b/testsuite/tests/instr-cov/408-null-proc-convention/src/test_0.adb new file mode 100644 index 000000000..740ac29bc --- /dev/null +++ b/testsuite/tests/instr-cov/408-null-proc-convention/src/test_0.adb @@ -0,0 +1,11 @@ +with Pkg; + +procedure Test_0 is +begin + null; +end Test_0; + + +--# pkg.adb +-- +-- /st/ l- ## s- diff --git a/testsuite/tests/instr-cov/408-null-proc-convention/src/test_full.adb b/testsuite/tests/instr-cov/408-null-proc-convention/src/test_full.adb new file mode 100644 index 000000000..680f51e5b --- /dev/null +++ b/testsuite/tests/instr-cov/408-null-proc-convention/src/test_full.adb @@ -0,0 +1,14 @@ +with Pkg; + +procedure Test_Full is +begin + Pkg.Foo (0); + Pkg.Bar (0); + Pkg.Baz (0); + Pkg.Blop (0); +end Test_Full; + + +--# pkg.adb +-- +-- /st/ l+ ## 0 diff --git a/testsuite/tests/instr-cov/408-null-proc-convention/test.opt b/testsuite/tests/instr-cov/408-null-proc-convention/test.opt new file mode 100644 index 000000000..6077b379b --- /dev/null +++ b/testsuite/tests/instr-cov/408-null-proc-convention/test.opt @@ -0,0 +1 @@ +5.04a1 DEAD Test requires Ada 2012 features diff --git a/testsuite/tests/instr-cov/408-null-proc-convention/test.py b/testsuite/tests/instr-cov/408-null-proc-convention/test.py new file mode 100644 index 000000000..121c49643 --- /dev/null +++ b/testsuite/tests/instr-cov/408-null-proc-convention/test.py @@ -0,0 +1,11 @@ +""" +Check that gnatcov can instrument null procedures that specify a calling +convention, either through the Convention aspect or through the Export aspect. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 0ba84c113..792b26e79 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -251,6 +251,7 @@ package body Instrument.Ada_Unit is -- Pragmas + Convention, Profile, Restrictions, @@ -293,6 +294,7 @@ package body Instrument.Ada_Unit is Predicate => Precompute_Symbol (Predicate), Static_Predicate => Precompute_Symbol (Static_Predicate), Type_Invariant => Precompute_Symbol (Type_Invariant), + Convention => Precompute_Symbol (Convention), Profile => Precompute_Symbol (Profile), Restrictions => Precompute_Symbol (Restrictions), No_Dependence => Precompute_Symbol (No_Dependence), @@ -1242,6 +1244,11 @@ package body Instrument.Ada_Unit is -- Return the expression for the Index'th argument of a pragma's -- arguments. + function Get_Convention (Decl : Basic_Decl) return Identifier; + -- Return the convention associated with Decl, either from the Convention + -- aspect or from the convention specified in the Export aspect. If no + -- convention is defined, return No_Identifier. + procedure Process_Annotation (UIC : in out Ada_Unit_Inst_Context; N : Ada_Node; @@ -3296,6 +3303,71 @@ package body Instrument.Ada_Unit is return False; end Has_No_Elaboration_Code_All; + -------------------- + -- Get_Convention -- + -------------------- + + function Get_Convention (Decl : Basic_Decl) return Identifier is + Convention_Aspect : constant Libadalang.Analysis.Aspect := + Decl.P_Get_Aspect (To_Unbounded_Text ("convention")); + Export_Aspect : constant Libadalang.Analysis.Aspect := + Decl.P_Get_Aspect (To_Unbounded_Text ("export")); + begin + if Exists (Convention_Aspect) then + return Value (Convention_Aspect).As_Identifier; + elsif Exists (Export_Aspect) + and then Node (Export_Aspect).Kind = Ada_Pragma_Node + then + + -- If the export aspect is present as an aspect, the convention will + -- also be specified as a standalone aspect and/or pragma, so it will + -- have been picked up by the previous branch. + + -- Either we have a named association ... + + for Assoc_Item of Node (Export_Aspect).As_Pragma_Node.F_Args loop + declare + Prag_Assoc : constant Pragma_Argument_Assoc := + Assoc_Item.As_Pragma_Argument_Assoc; + begin + if not Prag_Assoc.F_Name.Is_Null + and then Prag_Assoc.F_Name.Kind in LALCO.Ada_Identifier + and then + As_Symbol (Prag_Assoc.F_Name.As_Identifier) + = Precomputed_Symbols (Convention) + then + return Prag_Assoc.F_Expr.As_Identifier; + end if; + end; + end loop; + + -- ... Otherwise for a positional association the convention comes + -- first. + + declare + First_Child : constant Ada_Node'Class := + Node (Export_Aspect).As_Pragma_Node.F_Args.Child (1); + begin + case First_Child.Kind is + when Ada_Pragma_Argument_Assoc => + return First_Child.As_Pragma_Argument_Assoc.F_Expr + .As_Identifier; + + when LALCO.Ada_Identifier => return First_Child.As_Identifier; + + when others => + Report (Node => First_Child, + Msg => "Unexpected kind for a convention name: " + & First_Child.Kind_Name, + Kind => Low_Warning); + return No_Identifier; + end case; + end; + end if; + + return No_Identifier; + end Get_Convention; + ------------------------ -- Process_Annotation -- ------------------------ @@ -4736,10 +4808,31 @@ package body Instrument.Ada_Unit is then Fun_Witness else No_Node_Rewriting_Handle)); - -- Insert the renaming in the wrapper package + -- Insert the instance in the wrapper package Insert_Last (Common_Nodes.Wrapper_Pkg_Decls, Instance); + -- Check if there is a convention aspect on the null procedure, + -- in which case we need to match it in the instance so that + -- the renaming is subtype conformant. + + declare + Convention_Id : constant Identifier := + Get_Convention (Common_Nodes.N); + begin + if not Convention_Id.Is_Null then + Insert_Last + (Common_Nodes.Wrapper_Pkg_Decls, + Create_Pragma_Node + (RC, + F_Id => Create_Identifier (RC, "Convention"), + F_Args => Create_Regular_Node + (RC, Ada_Assoc_List, + (1 => Clone (Convention_Id), + 2 => Clone (Common_Nodes.N_Name))))); + end if; + end; + -- Push the wrapper package and the renaming down to the end of -- the current list of declarations. From 252590004f190e329263e214e2247e016f94b5d7 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 2 May 2025 13:01:08 +0200 Subject: [PATCH 1212/1483] testsuite: fix `expect_non_zero_code` for embedded-leon3 --- testsuite/SUITE/tutils.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index a15fed9cd..1743eb215 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -1156,9 +1156,11 @@ def run_cov_program( "--save-temps", ] - # pycross might obfuscate the error exit code in light runtime cases. - expect_non_zero_code = ( - expect_non_zero_code and not RUNTIME_INFO.has_light_runtime + # pycross might obfuscate the error exit code in light runtime cases + # and for embedded-leon3. + expect_non_zero_code = expect_non_zero_code and not ( + RUNTIME_INFO.has_light_runtime + or RUNTIME_INFO.runtime_name == "embedded-leon3" ) else: # Native programs using a light runtime can't set the exit code, and From ce9eefc4550a2be95b527a7d4f82ac581eef7237 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 25 Apr 2025 13:33:45 +0000 Subject: [PATCH 1213/1483] Emit warnings in gnatcov run|coverage when binary traces are involved --- .../tests/411-bin-traces-warning/main.adb | 6 ++ .../tests/411-bin-traces-warning/test.opt | 1 + .../tests/411-bin-traces-warning/test.py | 88 +++++++++++++++++++ testsuite/testsuite.py | 4 + tools/gnatcov/gnatcov_bits_specific.adb | 4 + tools/gnatcov/rundrv.adb | 27 ++++-- tools/gnatcov/rundrv.ads | 5 ++ 7 files changed, 126 insertions(+), 9 deletions(-) create mode 100644 testsuite/tests/411-bin-traces-warning/main.adb create mode 100644 testsuite/tests/411-bin-traces-warning/test.opt create mode 100644 testsuite/tests/411-bin-traces-warning/test.py diff --git a/testsuite/tests/411-bin-traces-warning/main.adb b/testsuite/tests/411-bin-traces-warning/main.adb new file mode 100644 index 000000000..3373e6745 --- /dev/null +++ b/testsuite/tests/411-bin-traces-warning/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello, world!"); +end Main; diff --git a/testsuite/tests/411-bin-traces-warning/test.opt b/testsuite/tests/411-bin-traces-warning/test.opt new file mode 100644 index 000000000..44f772ebe --- /dev/null +++ b/testsuite/tests/411-bin-traces-warning/test.opt @@ -0,0 +1 @@ +!bin-traces DEAD diff --git a/testsuite/tests/411-bin-traces-warning/test.py b/testsuite/tests/411-bin-traces-warning/test.py new file mode 100644 index 000000000..d03bb2434 --- /dev/null +++ b/testsuite/tests/411-bin-traces-warning/test.py @@ -0,0 +1,88 @@ +""" +Check that gnatcov emits the expected warning when binary traces are involved. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of, lines_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import ( + exepath_to, + gprbuild, + gprfor, + tracename_for, + xcov, + xrun, +) + + +tmp = Wdir("tmp_") + +warning = ( + "warning: Support for coverage of non-instrumented programs is deprecated" + " and will disappear after GNATcoverage 26 releases. You are encouraged to" + " migrate to instrumentation-based coverage: you can read more about it in" + " our documentation: " +) + + +def check_warning(output_file): + """Check the presence of the expecetd warning in the given text file.""" + thistest.fail_if( + warning not in lines_of(output_file), + f"Missing expected warning in {output_file}", + ) + + +# Remove the warning-disabling env var that we set at the testsuite level, +# since our goal here is precisely to check that it is emitted. +os.environ.pop("GNATCOV_NO_BINARY_TRACES_WARNING") + +gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) +gprbuild(gpr) + +# Check that we have the expecetd warning both in "gnatcov run" and "gnatcov +# coverage" for binary traces. +xrun(exepath_to("main"), out="run.txt") +check_warning("run.txt") + +xcov( + [ + "coverage", + "-P", + gpr, + "-cstmt", + "-axcov", + "--output-dir=xcov-bin", + tracename_for("main"), + ], + out="coverage-bin.txt", +) +check_warning("coverage-bin.txt") +check_xcov_reports("xcov-bin", {"main.adb.xcov": {"+": {5}}}) + +# Check that we do not have it in "gnatcov instrument" nor "gnatcov coverage" +# for source traces. +build_run_and_coverage( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov", "--output-dir=xcov-src"], + trace_mode="src", +) +thistest.fail_if_not_equal( + "output of 'gnatcov instrument' (instrument.log)", + "", + contents_of("instrument.log"), +) +thistest.fail_if_not_equal( + "output of 'gnatcov coverage' for src traces (coverage.log)", + "", + contents_of("coverage.log"), +) +check_xcov_reports("xcov-src", {"main.adb.xcov": {"+": {5}}}) + +thistest.result() diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index f189b8ea2..8211f101f 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -627,6 +627,10 @@ def set_up(self): self.testcase_cmd = testcase_cmd self.testcase_timeout = timeout + # Disable the warning about usage of binary traces in gnatcov 26.* by + # default: it is irrelevant here. + os.environ["GNATCOV_NO_BINARY_TRACES_WARNING"] = "yes" + def maybe_exec(self, binfile, args=None, edir=None): """ Shortcut for the global maybe_exec. Log the result in diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 535404536..df7a799a7 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1021,6 +1021,7 @@ procedure GNATcov_Bits_Specific is Copy_Arg_List (Args.Remaining_Args, Exe_Inputs); when Cmd_Run => + Rundrv.Emit_Deprecation_Warning; -- Sort out what to use as the executable name and what EARGS to -- forward to our Eargs local, depending on whether we have an @@ -2085,6 +2086,9 @@ begin -- Record we are loading a binary trace Update_Current_Trace_Kind (Binary_Trace_File); + if not Bin_Traces_Present then + Rundrv.Emit_Deprecation_Warning; + end if; Bin_Traces_Present := True; Load_All_ALIs (Check_SCOs => False); diff --git a/tools/gnatcov/rundrv.adb b/tools/gnatcov/rundrv.adb index 29cf5ebe3..d4131da72 100644 --- a/tools/gnatcov/rundrv.adb +++ b/tools/gnatcov/rundrv.adb @@ -37,15 +37,16 @@ package body Rundrv is package Env renames Ada.Environment_Variables; - Native_Warning : constant String := - "Support for coverage of non-instrumented native programs is deprecated" - & " and will disappear after GNATcoverage 21 releases. You are" + Warning : constant String := + "Support for coverage of non-instrumented programs is deprecated" + & " and will disappear after GNATcoverage 26 releases. You are" & " encouraged to migrate to instrumentation-based coverage: you can" & " read more about it in our documentation:" - & " "; - -- Warning to emit when running native programs + & " "; + -- Warning to emit when using binary traces - Native_Warning_Envvar : constant String := "GNATCOV_NO_NATIVE_WARNING"; + Warning_Envvar : constant String := "GNATCOV_NO_BINARY_TRACES_WARNING"; -- Name of the environment variable to define in order to disable this -- warning. @@ -116,9 +117,6 @@ package body Rundrv is ("No builtin or GNATemulator execution driver found for" & " target: " & Context.Target_Family.all); return; - - elsif Native and then Env.Value (Native_Warning_Envvar, "") = "" then - Outputs.Warn (Native_Warning); end if; -- And now create the trace file itself. @@ -175,4 +173,15 @@ package body Rundrv is end if; end Driver; + ------------------------------ + -- Emit_Deprecation_Warning -- + ------------------------------ + + procedure Emit_Deprecation_Warning is + begin + if Env.Value (Warning_Envvar, "") = "" then + Outputs.Warn (Warning); + end if; + end Emit_Deprecation_Warning; + end Rundrv; diff --git a/tools/gnatcov/rundrv.ads b/tools/gnatcov/rundrv.ads index 726c4d1fd..b9c94ecb1 100644 --- a/tools/gnatcov/rundrv.ads +++ b/tools/gnatcov/rundrv.ads @@ -53,4 +53,9 @@ package Rundrv is -- command-line arguments for Exe_File. Write traces in the Output trace -- file. If Tag is not null, append it to the trace header. + procedure Emit_Deprecation_Warning; + -- Unless the GNATCOV_NO_BINARY_TRACES_WARNING environment variable is set, + -- emit a warning to say that support for coverage of non-instrumented + -- programs is deprecated. + end Rundrv; From ac378657eb084683188eee64da0e0b4568b1b5ad Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 2 Apr 2025 10:39:09 +0000 Subject: [PATCH 1214/1483] Adapt llvm_json trace_adapter Makefile Make it similar to the trace32 trace_adapter. --- tools/gnatcov/Makefile | 9 +++-- .../gnatcov/trace_adapters/llvm_json/Makefile | 37 +++++++++++++------ .../llvm_json/gnatcov_llvm_exporter.gpr | 7 +++- 3 files changed, 36 insertions(+), 17 deletions(-) diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index 6e91ce82c..8a00a2b75 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -105,7 +105,7 @@ include architecture.mk ifeq ($(HOST_OS), windows) ifeq ($(BITS_ARCH), 32) -DEFAULT_ADAPTERS = trace32 +DEFAULT_ADAPTERS = trace32 llvm_json else DEFAULT_ADAPTERS = endif @@ -115,11 +115,11 @@ ifeq ($(HOST_OS), linux) ifeq ($(BITS_ARCH), 32) DEFAULT_ADAPTERS = else -DEFAULT_ADAPTERS = trace32 +DEFAULT_ADAPTERS = trace32 llvm_json endif endif -ADAPTERS_LIST=$(DEFAULT_ADAPTERS) +ADAPTERS_LIST ?= $(DEFAULT_ADAPTERS) PROCESSORS=0 BUILD_MODE=dev @@ -128,8 +128,9 @@ BUILD_MODE=dev # == Variables to pass down to sub-makefiles for trace adapters == # ================================================================ -# The Trace32 adapter use the same prefix as GNATcov +# The trace adapters use the same prefix as GNATcov trace32_ADAPTER_INSTALL_VARS=PREFIX=$(PREFIX) +llvm_json_ADAPTER_INSTALL_VARS=PREFIX=$(PREFIX) .PHONY: default all adapters bin $(PGMPATH) diff --git a/tools/gnatcov/trace_adapters/llvm_json/Makefile b/tools/gnatcov/trace_adapters/llvm_json/Makefile index 944921d45..746ab89ad 100644 --- a/tools/gnatcov/trace_adapters/llvm_json/Makefile +++ b/tools/gnatcov/trace_adapters/llvm_json/Makefile @@ -1,21 +1,30 @@ +PREFIX=install +PARALLEL_BUILD=0 +include ../../host.mk + LLVM_CXXFLAGS := $(shell llvm-config --cxxflags) LLVM_LDFLAGS := $(shell llvm-config --ldflags) LLVM_LIBS := $(shell llvm-config --libs --system-libs) -# Set this to the right path for you. +# Set this to the right path for you LIBSTD_PATH := "$(dir $(shell which gnat))../lib64/" +EXENAME=gnatcov_llvm_exporter +DIRNAME=gnatcoverage + GPRBUILD_FLAGS := \ - -cargs:c++ ${LLVM_CXXFLAGS} -g \ + -cargs:c++ $(LLVM_CXXFLAGS) -g \ -largs \ --verbose \ -fuse-ld=lld \ - -L ${LIBSTD_PATH} \ - ${LLVM_LDFLAGS} \ - ${LLVM_LIBS} + -L $(LIBSTD_PATH) \ + $(LLVM_LDFLAGS) \ + $(LLVM_LIBS) + +.PHONY: force -gprbuild: - @gprbuild -v ${GPRBUILD_FLAGS} +bin: force + gprbuild -j$(PARALLEL_BUILD) $(GPRBUILD_FLAGS) cmake: mkdir -p build @@ -23,13 +32,19 @@ cmake: -B build \ -DCMAKE_C_COMPILER=clang \ -DCMAKE_CXX_COMPILER=clang++ \ - -DCMAKE_CXX_FLAGS="${LLVM_CXXFLAGS}" \ - -DCMAKE_EXE_LINKER_FLAGS="-L ${LIBSTD_PATH}" + -DCMAKE_CXX_FLAGS="$(LLVM_CXXFLAGS)" \ + -DCMAKE_EXE_LINKER_FLAGS="-L $(LIBSTD_PATH)" cd build && make .PHONY: clean clean: gprclean - ${RM} -rf obj - ${RM} -rf build + $(RM) -rf obj + $(RM) -rf build + +.PHONY: install + +install: + $(MKDIR) $(PREFIX)/libexec/$(DIRNAME) + $(CP) $(EXENAME) $(PREFIX)/libexec/$(DIRNAME) diff --git a/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr b/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr index f0a244b36..1b8f8ad49 100644 --- a/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr +++ b/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr @@ -1,10 +1,13 @@ project GNATcov_LLVM_exporter is for Languages use ("C++"); - for Source_Dirs use ("src"); for Main use ("main.cpp"); - for Object_Dir use "obj"; + for Exec_Dir use "."; + + package Builder is + for Executable ("main.cpp") use "gnatcov_llvm_exporter"; + end Builder; end GNATcov_LLVM_exporter; From 8f2b7e14ec2db1cbcbe51a41e741ff293b0b4f79 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 5 May 2025 13:21:10 +0000 Subject: [PATCH 1215/1483] annotations.ads: add a default value for Pretty_Printer.Use_UTF8 This boolean component is used regardless of whether the `Need_Sources` component is set to True, so it must be initialized in all cases. The only known issue caused by this was a Valgrind diagnostic, so no testcase added (no observed bug). --- tools/gnatcov/annotations.ads | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index fbae014f0..a88432b67 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -141,7 +141,7 @@ private Need_Sources : Boolean; Show_Details : Boolean; - Use_UTF8 : Boolean; + Use_UTF8 : Boolean := False; -- Whether source excerpts need to be converted to UTF-8 for this format Context : Coverage.Context_Access; From dc5e9adba8a851a28f305a7b455be5f93c3bbcc0 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 7 May 2025 11:49:09 +0200 Subject: [PATCH 1216/1483] llvm_trace_adapter: use gcc instead of clang --- tools/gnatcov/trace_adapters/llvm_json/Makefile | 8 ++++---- .../trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/trace_adapters/llvm_json/Makefile b/tools/gnatcov/trace_adapters/llvm_json/Makefile index 746ab89ad..291d0bc4c 100644 --- a/tools/gnatcov/trace_adapters/llvm_json/Makefile +++ b/tools/gnatcov/trace_adapters/llvm_json/Makefile @@ -7,7 +7,8 @@ LLVM_LDFLAGS := $(shell llvm-config --ldflags) LLVM_LIBS := $(shell llvm-config --libs --system-libs) # Set this to the right path for you -LIBSTD_PATH := "$(dir $(shell which gnat))../lib64/" +GCC_TOOLCHAIN := "$(dir $(shell which gnat)).." +LIBSTD_PATH := "$GCC_TOOLCHAIN/lib64/" EXENAME=gnatcov_llvm_exporter DIRNAME=gnatcoverage @@ -15,7 +16,6 @@ DIRNAME=gnatcoverage GPRBUILD_FLAGS := \ -cargs:c++ $(LLVM_CXXFLAGS) -g \ -largs \ - --verbose \ -fuse-ld=lld \ -L $(LIBSTD_PATH) \ $(LLVM_LDFLAGS) \ @@ -30,8 +30,8 @@ cmake: mkdir -p build cmake \ -B build \ - -DCMAKE_C_COMPILER=clang \ - -DCMAKE_CXX_COMPILER=clang++ \ + -DCMAKE_C_COMPILER=gcc \ + -DCMAKE_CXX_COMPILER=g++ \ -DCMAKE_CXX_FLAGS="$(LLVM_CXXFLAGS)" \ -DCMAKE_EXE_LINKER_FLAGS="-L $(LIBSTD_PATH)" cd build && make diff --git a/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr b/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr index 1b8f8ad49..b7f35a42f 100644 --- a/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr +++ b/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr @@ -10,4 +10,9 @@ project GNATcov_LLVM_exporter is for Executable ("main.cpp") use "gnatcov_llvm_exporter"; end Builder; + package Compiler is + for Driver ("C") use "gcc"; + for Driver ("C++") use "g++"; + end Compiler; + end GNATcov_LLVM_exporter; From 7d7ee9b165547b63279ff1ade623414a39fe1dbb Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 13 May 2025 11:31:36 +0200 Subject: [PATCH 1217/1483] llvm_trace_adapter: Remove uneeded Driver and Linker options --- tools/gnatcov/trace_adapters/llvm_json/Makefile | 1 - .../trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr | 5 ----- 2 files changed, 6 deletions(-) diff --git a/tools/gnatcov/trace_adapters/llvm_json/Makefile b/tools/gnatcov/trace_adapters/llvm_json/Makefile index 291d0bc4c..205a0b6b2 100644 --- a/tools/gnatcov/trace_adapters/llvm_json/Makefile +++ b/tools/gnatcov/trace_adapters/llvm_json/Makefile @@ -16,7 +16,6 @@ DIRNAME=gnatcoverage GPRBUILD_FLAGS := \ -cargs:c++ $(LLVM_CXXFLAGS) -g \ -largs \ - -fuse-ld=lld \ -L $(LIBSTD_PATH) \ $(LLVM_LDFLAGS) \ $(LLVM_LIBS) diff --git a/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr b/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr index b7f35a42f..1b8f8ad49 100644 --- a/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr +++ b/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr @@ -10,9 +10,4 @@ project GNATcov_LLVM_exporter is for Executable ("main.cpp") use "gnatcov_llvm_exporter"; end Builder; - package Compiler is - for Driver ("C") use "gcc"; - for Driver ("C++") use "g++"; - end Compiler; - end GNATcov_LLVM_exporter; From 4f653fbd2a3fcfaf6ecb8dd6b00adc13c43f74e5 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 14 May 2025 07:32:09 +0000 Subject: [PATCH 1218/1483] U204-026-arch-mix/update.sh: do not use sshpass This program is not installed in most configurations, and nowadays connections to IOD are password-less, so using sshpass does not bring any value. --- testsuite/tests/U204-026-arch-mix/update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/U204-026-arch-mix/update.sh b/testsuite/tests/U204-026-arch-mix/update.sh index cfc104be0..8ff6f3ca4 100755 --- a/testsuite/tests/U204-026-arch-mix/update.sh +++ b/testsuite/tests/U204-026-arch-mix/update.sh @@ -22,5 +22,5 @@ cp -rf /tmp/U204-026-arch-mix/* . [ ! -d '/tmp/iod-dev' ] && git clone git-adacore:eng/shared/iod-dev /tmp/iod-dev /tmp/iod-dev/create-base.py --base-image x86_64-windows-2019 git_branch=$(git rev-parse --abbrev-ref HEAD) -sshpass ssh iod 'bash -s' < update_arch_mix_windows.sh $git_branch +ssh iod 'bash -s' < update_arch_mix_windows.sh $git_branch rsync -av iod:/cygdrive/c/tmp/U204-026-arch-mix/gen/* gen/ From 4e16671732358378454d3afbc4282845de8f37a4 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 14 May 2025 07:37:29 +0000 Subject: [PATCH 1219/1483] U204-026-arch-mix/update_arch_mix_windows.sh: add missing gnatall dep `anod build gnatcov` no longer installs the `gnatall -Qstable` dependency (it uses `gcc -Qstable` directly instead). Install it manually before running the rest of the update script to have access to both GNAT and gprbuild. --- testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh index 8a37894a9..3550d92bf 100755 --- a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh +++ b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh @@ -21,6 +21,7 @@ git checkout origin/$1 cd /Users/itmgr/wave anod vcs --add-repo gnatcoverage /Users/itmgr/gnatcoverage anod build gnatcov --interactive never +anod install gnatall -Qstable eval $(anod printenv gnatcov) eval $(anod printenv gnatall -Qstable) From 8600c49efd20b0c4e7ea8fe553005a18385baf31 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 14 May 2025 09:02:00 +0000 Subject: [PATCH 1220/1483] U204-026-arch-mix: make update scripts re-runnable Avoid implicit assumptions that these scripts run on "fresh state" (no IOD instance started, no directory copies already made, ...) so that one can re-run the update script after a previous (failed) attempt. --- testsuite/tests/U204-026-arch-mix/update.sh | 22 ++++++++++++++---- .../update_arch_mix_windows.sh | 23 +++++++++++++------ 2 files changed, 33 insertions(+), 12 deletions(-) diff --git a/testsuite/tests/U204-026-arch-mix/update.sh b/testsuite/tests/U204-026-arch-mix/update.sh index 8ff6f3ca4..d9fbba85e 100755 --- a/testsuite/tests/U204-026-arch-mix/update.sh +++ b/testsuite/tests/U204-026-arch-mix/update.sh @@ -12,15 +12,27 @@ fi # Update the linux artifacts cd .. -cp -rf U204-026-arch-mix /tmp/ +rsync -ar U204-026-arch-mix/ /tmp/U204-026-arch-mix cd /tmp/U204-026-arch-mix ./gen.sh linux cd $cwd -cp -rf /tmp/U204-026-arch-mix/* . +rsync -ar /tmp/U204-026-arch-mix/ . + +# Then update the Windows artifacts using an IOD machine. Do not create the IOD +# instance if one already exists +IOD_DEV_DIR=/tmp/iod-dev +INSTANCES_FILE="$IOD_DEV_DIR/instances.txt" +if ! [ -d "$IOD_DEV_DIR" ] +then + git clone git-adacore:eng/shared/iod-dev "$IOD_DEV_DIR" +fi +iod list --instances > "$INSTANCES_FILE" 2>&1 +if ! grep "You have some running instance" "$INSTANCES_FILE" \ + > /dev/null +then + "$IOD_DEV_DIR/create-base.py" --base-image x86_64-windows-2019 +fi -# Then update the windows artifacts -[ ! -d '/tmp/iod-dev' ] && git clone git-adacore:eng/shared/iod-dev /tmp/iod-dev -/tmp/iod-dev/create-base.py --base-image x86_64-windows-2019 git_branch=$(git rev-parse --abbrev-ref HEAD) ssh iod 'bash -s' < update_arch_mix_windows.sh $git_branch rsync -av iod:/cygdrive/c/tmp/U204-026-arch-mix/gen/* gen/ diff --git a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh index 3550d92bf..02d04a38b 100755 --- a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh +++ b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh @@ -9,8 +9,14 @@ fi # Create a sandbox cd /Users/itmgr -git clone git-adacore:eng/cov/gnatcoverage -anod init wave +if ! [ -d gnatcoverage ] +then + git clone git-adacore:eng/cov/gnatcoverage +fi +if ! [ -d wave ] +then + anod init wave +fi # Checkout the right gnatcov branch cd /Users/itmgr/gnatcoverage @@ -19,19 +25,22 @@ git checkout origin/$1 # Build gnatcov cd /Users/itmgr/wave +anod vcs --reset anod vcs --add-repo gnatcoverage /Users/itmgr/gnatcoverage -anod build gnatcov --interactive never +anod build gnatcov --smart anod install gnatall -Qstable eval $(anod printenv gnatcov) eval $(anod printenv gnatall -Qstable) # Then, retrieve the sources of the arch-mix test -rm -rf /Users/itmgr/gnatcoverage/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows -cp -r /Users/itmgr/gnatcoverage/testsuite/tests/U204-026-arch-mix /cygdrive/c/tmp -cd /cygdrive/c/tmp/U204-026-arch-mix +SRC_DIR=/Users/itmgr/gnatcoverage/testsuite/tests/U204-026-arch-mix +BUILD_DIR=/cygdrive/c/tmp/U204-026-arch-mix +rm -rf "$SRC_DIR/gen/x86_64-windows" +rsync -ar "$SRC_DIR/" "$BUILD_DIR" +cd "$BUILD_DIR" chmod +x gen.sh gnatcov setup ./gen.sh windows # Copy back the generated sources -cp -r /cygdrive/c/tmp/U204-026-arch-mix/gen/* /Users/itmgr/gnatcoverage/testsuite/tests/U204-026-arch-mix/gen/ +rsync -ar "$BUILD_DIR/gen/" "$SRC_DIR/gen" From e521d913a075dcd1bedf5a1b37727410dec2cb54 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 14 May 2025 12:09:10 +0000 Subject: [PATCH 1221/1483] U204-026-arch-mix/update.sh: do not assume dev branch is pushed Rework the update scripts so that they work even when the gnatcoverage repository changes are only local (but still committed). The scripts used to assume that the currently checked out branch was also pushed upstream. --- testsuite/tests/U204-026-arch-mix/update.sh | 5 +++-- .../U204-026-arch-mix/update_arch_mix_windows.sh | 12 +----------- .../tests/U204-026-arch-mix/update_win_setup_git.sh | 9 +++++++++ 3 files changed, 13 insertions(+), 13 deletions(-) create mode 100644 testsuite/tests/U204-026-arch-mix/update_win_setup_git.sh diff --git a/testsuite/tests/U204-026-arch-mix/update.sh b/testsuite/tests/U204-026-arch-mix/update.sh index d9fbba85e..916101bdf 100755 --- a/testsuite/tests/U204-026-arch-mix/update.sh +++ b/testsuite/tests/U204-026-arch-mix/update.sh @@ -33,6 +33,7 @@ then "$IOD_DEV_DIR/create-base.py" --base-image x86_64-windows-2019 fi -git_branch=$(git rev-parse --abbrev-ref HEAD) -ssh iod 'bash -s' < update_arch_mix_windows.sh $git_branch +ssh iod 'bash -s' < update_win_setup_git.sh +git push -f iod:gnatcoverage HEAD:wip +ssh iod 'bash -s' < update_arch_mix_windows.sh rsync -av iod:/cygdrive/c/tmp/U204-026-arch-mix/gen/* gen/ diff --git a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh index 02d04a38b..003a1e126 100755 --- a/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh +++ b/testsuite/tests/U204-026-arch-mix/update_arch_mix_windows.sh @@ -2,17 +2,8 @@ set -ex -if [ $# -eq 0 ]; then - echo "No arguments provided. Please provide the name of the gnatcov branch" - exit 1 -fi - # Create a sandbox cd /Users/itmgr -if ! [ -d gnatcoverage ] -then - git clone git-adacore:eng/cov/gnatcoverage -fi if ! [ -d wave ] then anod init wave @@ -20,8 +11,7 @@ fi # Checkout the right gnatcov branch cd /Users/itmgr/gnatcoverage -git fetch origin -git checkout origin/$1 +git reset --hard wip # Build gnatcov cd /Users/itmgr/wave diff --git a/testsuite/tests/U204-026-arch-mix/update_win_setup_git.sh b/testsuite/tests/U204-026-arch-mix/update_win_setup_git.sh new file mode 100644 index 000000000..5ccb3cadf --- /dev/null +++ b/testsuite/tests/U204-026-arch-mix/update_win_setup_git.sh @@ -0,0 +1,9 @@ +# Set up the gnatcoverage repositoy on the Windows IOD machie + +set -ex + +cd /Users/itmgr +if ! [ -d gnatcoverage ] +then + git clone git-adacore:eng/cov/gnatcoverage +fi From eec351e12a777886fb4b95b381fec7b990cae31d Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 7 May 2025 09:51:28 +0200 Subject: [PATCH 1222/1483] Fix timestamp writing --- .../gnatcov/ada-rts/gnatcov_rts-traces-output.adb | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb index 83e40180d..4ee1ddef9 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb @@ -305,7 +305,20 @@ package body GNATcov_RTS.Traces.Output is begin Write_Header (Output); Write_Info (Output, Info_Program_Name, Program_Name); - Write_Info (Output, Info_Exec_Date, String'(1 .. 8 => 'A')); + + -- Write the exec date + + declare + Timestamp : Interfaces.Unsigned_64 := Exec_Date; + Bytes : Uint8_Array := (1 => 0); + begin + for I in 1 .. 8 loop + Bytes (1) := Interfaces.Unsigned_8 (Timestamp mod 8); + Timestamp := Shift_Right (Timestamp, 8); + Write_Bytes (Output, Bytes); + end loop; + end; + Write_Info (Output, Info_User_Data, User_Data); Write_Info (Output, Info_End, ""); for I in Buffers_Groups'Range loop From cf749142f2ef847df940d851edaae5946f196dc1 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 19 May 2025 12:13:00 +0200 Subject: [PATCH 1223/1483] AAMP: copy the runtime to the test directory As AAMP does not support library project, always copy the instrumentation runtime to the test directory as building an instrumented program builds it. --- testsuite/SCOV/instr.py | 21 ++++++++++++++++++++- testsuite/SCOV/internals/driver.py | 6 ++++++ testsuite/SCOV/minicheck.py | 6 ++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 67452651f..850c274d8 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -2,8 +2,9 @@ import os.path import re +import shutil -from e3.fs import mkdir +from e3.fs import mkdir, sync_tree from SUITE.context import thistest from SUITE.control import env @@ -344,3 +345,21 @@ def maybe_relocate_binaries(object_dir, exe_dir, mains): if "aamp" in env.target.platform: for main in mains: copy_to_dir(object_dir, exe_dir, main) + + +def maybe_copy_runtime(test_dir): + """ + Copy the Ada instrumentation runtime in test_dir for the AAMP target. + """ + if "aamp" in env.target.platform: + rts_path = os.path.join( + os.path.dirname(shutil.which("gnatcov")), + "..", + "share", + "gnatcoverage", + "gnatcov_ada_rts", + ) + rts_dest_path = os.path.join(test_dir, "rts") + mkdir(rts_dest_path) + sync_tree(rts_path, rts_dest_path) + env.add_search_path(env_var="GPR_PROJECT_PATH", path=rts_dest_path) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 8407888c5..dac12c3da 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -32,6 +32,7 @@ add_dumper_lch_hook, default_dump_channel, default_dump_trigger, + maybe_copy_runtime, maybe_relocate_binaries, xcov_convert_base64, xcov_instrument, @@ -1484,6 +1485,11 @@ def mode_build(self): subdirs = None instrument_gprsw = GPRswitches(root_project=self.gpr) + # The AAMP target does not support library project and requires + # rebuilding the instrumentation runtime: copy it in the test + # directory. + maybe_copy_runtime(os.getcwd()) + # Instrument now, requesting the propagation of instrumentation # issues on the test status. Note that we expect this to include # a check on instrumentation warnings. diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index 712107116..a52648727 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -17,6 +17,7 @@ from SCOV.instr import ( default_dump_channel, + maybe_copy_runtime, maybe_relocate_binaries, xcov_convert_base64, xcov_instrument, @@ -267,6 +268,11 @@ def gprbuild_wrapper(root_project): if dump_channel == "auto": dump_channel = default_dump_channel() + # The AAMP target does not support library project and requires + # rebuilding the instrumentation runtime: copy it in the test + # directory. + maybe_copy_runtime(os.getcwd()) + # Instrument the project and build the result extra_instr_args = cov_or_instr_args + list(extra_instr_args or []) xcov_instrument( From 606fe972452554587810be8f8392d6accd672677 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 19 May 2025 10:59:21 +0000 Subject: [PATCH 1224/1483] Fix timestamp writing --- tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb index 4ee1ddef9..9e467febf 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb @@ -310,13 +310,16 @@ package body GNATcov_RTS.Traces.Output is declare Timestamp : Interfaces.Unsigned_64 := Exec_Date; - Bytes : Uint8_Array := (1 => 0); + Bytes : Uint8_Array (1 .. 8); + Bytes_Str : String (1 .. 8); + for Bytes_Str'Address use Bytes'Address; + pragma Import (Ada, Bytes_Str); begin for I in 1 .. 8 loop - Bytes (1) := Interfaces.Unsigned_8 (Timestamp mod 8); + Bytes (I) := Interfaces.Unsigned_8 (Timestamp mod 8); Timestamp := Shift_Right (Timestamp, 8); - Write_Bytes (Output, Bytes); end loop; + Write_Info (Output, Info_Exec_Date, Bytes_Str); end; Write_Info (Output, Info_User_Data, User_Data); From 10bd0b85fe5fb85272f324bcd207007d41f6aab1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 19 May 2025 14:10:21 +0200 Subject: [PATCH 1225/1483] Instrument.C: Fix pre-processing of sources where comments cannot be preserved Some macros can perform token concatenation, but do not allow concatenating comments with other tokens. The comments are normally replaced by white spaces before macro expansion, but gnatcov needs to preserve comments to process annotations. In this case the preprocessor will error out when asked to preserve the comments. To fix this, this change introduces a retry without the -C argument. This allows gnatcov to properly instrument the source, but annotations will be ignored. --- .../419-comment-preprocessing/src/pkg.h | 9 ++ .../419-comment-preprocessing/src/test_pkg.c | 16 ++++ .../419-comment-preprocessing/test.opt | 1 + .../419-comment-preprocessing/test.py | 34 ++++++++ tools/gnatcov/instrument-c.adb | 83 ++++++++++++++++--- 5 files changed, 132 insertions(+), 11 deletions(-) create mode 100644 testsuite/tests/instr-cov/419-comment-preprocessing/src/pkg.h create mode 100644 testsuite/tests/instr-cov/419-comment-preprocessing/src/test_pkg.c create mode 100644 testsuite/tests/instr-cov/419-comment-preprocessing/test.opt create mode 100644 testsuite/tests/instr-cov/419-comment-preprocessing/test.py diff --git a/testsuite/tests/instr-cov/419-comment-preprocessing/src/pkg.h b/testsuite/tests/instr-cov/419-comment-preprocessing/src/pkg.h new file mode 100644 index 000000000..c457e8ab2 --- /dev/null +++ b/testsuite/tests/instr-cov/419-comment-preprocessing/src/pkg.h @@ -0,0 +1,9 @@ +#define CONCAT(X, Y) X##Y + +inline int +ident (int x) +{ + /* GNATCOV_EXEMPT_ON unused*/ + return 0; // # noeval + /*GNATCOV_EXEMPT_OFF */ +} diff --git a/testsuite/tests/instr-cov/419-comment-preprocessing/src/test_pkg.c b/testsuite/tests/instr-cov/419-comment-preprocessing/src/test_pkg.c new file mode 100644 index 000000000..6457fb92c --- /dev/null +++ b/testsuite/tests/instr-cov/419-comment-preprocessing/src/test_pkg.c @@ -0,0 +1,16 @@ +#include "pkg.h" + +int +main () +{ + int CONCAT (/*empty*/, my_var) = 0; // # st + return CONCAT (/*something else*/, my_var); // # st +} + +//# test_pkg.c +// +// /st/ l+ ## 0 + +//# pkg.h +// +// /noeval/ l- ## s- diff --git a/testsuite/tests/instr-cov/419-comment-preprocessing/test.opt b/testsuite/tests/instr-cov/419-comment-preprocessing/test.opt new file mode 100644 index 000000000..796388e67 --- /dev/null +++ b/testsuite/tests/instr-cov/419-comment-preprocessing/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Check instrumentation-specific behavior diff --git a/testsuite/tests/instr-cov/419-comment-preprocessing/test.py b/testsuite/tests/instr-cov/419-comment-preprocessing/test.py new file mode 100644 index 000000000..a27cb79cf --- /dev/null +++ b/testsuite/tests/instr-cov/419-comment-preprocessing/test.py @@ -0,0 +1,34 @@ +""" +Test that gnatcov does not crash when instrumenting a source that cannot be +preprocessed while preserving comments, and instead emits a warning stating +that annotations are ignored. +""" + +import os + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest +from SUITE.cutils import contents_of + +wd = "s_pkg" + +warning_pat = ( + r"warning: Could not preserve comments while pre-processing .*test_pkg\.c" + r", annotations in comments within this file or included headers will not" + r" be taken into account" +) + +TestCase( + category=CAT.stmt, + tolerate_messages=warning_pat, +).run() + +# Actually check that the warning got emitted +thistest.fail_if_no_match( + what="missing warning in the output of 'gnatcov instrument'", + regexp=warning_pat, + actual=contents_of(os.path.join(wd, "xinstr.out")), +) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 17fa80e72..1ef750475 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -3019,8 +3019,11 @@ package body Instrument.C is PP_Filename : out Unbounded_String; Options : in out Analysis_Options) is + Base_Cmd : Command_Type; + -- The command to preprocess the file that we save + Cmd : Command_Type; - -- The command to preprocess the file + -- The actual command to preprocess the file Success : Boolean; -- Whether this command is successful @@ -3050,25 +3053,20 @@ package body Instrument.C is return; end if; - Cmd := + Base_Cmd := (Command => Prj.Compiler_Driver (Instrumenter.Language), others => <>); -- Add the preprocessing flag - Append_Arg (Cmd, "-E"); - - -- Keep the code comments as they may contain exemption / coverage - -- disabling markers. - - Append_Arg (Cmd, "-C"); + Append_Arg (Base_Cmd, "-E"); -- Add all of the compiler / compiler driver options to the -- preprocessing command line. - Append_Args (Cmd, Options.Raw_Switches); + Append_Args (Base_Cmd, Options.Raw_Switches); - Append_Arg (Cmd, Filename); + Append_Arg (Base_Cmd, Filename); -- Register the preprocessing command. We need it to preprocess the file -- when producing the report, and getting the text of macro expansions. @@ -3076,12 +3074,21 @@ package body Instrument.C is -- for the instrumentation process (and we do not want to pass a -o -- option, as it would make paths too opaque at gnatcov coverage time). + -- Keep the code comments as they may contain exemption / coverage + -- disabling markers. This argument needs to be kept last in Base_Cmd as + -- we may need to remove it later if preprocessing with comments + -- preserved fails. + + Append_Arg (Base_Cmd, "-C"); + PP_Cmds.Insert (Get_Index_From_Generic_Name (Filename, Kind => Files_Table.Source_File, Indexed_Simple_Name => True), - Cmd); + Base_Cmd); + + Cmd := Base_Cmd; -- To get the include paths, we use the verbose output of cpp -E @@ -3098,6 +3105,60 @@ package body Instrument.C is Output_File => Preprocessor_Output_Filename, Ignore_Error => True); + if not Success then + + -- If it did not succeed, it might be due to comment preservation + -- (-C), which can result in invalid tokens being generated by + -- token-manipulating macros. E.G: + -- + -- #define FOO (X, Y) X ## Y + -- + -- int FOO(/*my*/, integer); + -- + -- Without preserving comments the above declaration expands to int + -- integer; + -- + -- But preserving comments makes the preprocessor error out as a + -- comment token is concatenated to something else, which is not + -- allowed. + -- + -- In that case, retry preprocessing without preserving comment, but + -- emit a warning as we'll loose any annotations in the preprocessed + -- files or included headers. + + Base_Cmd.Arguments.Delete_Last; + + PP_Cmds.Replace + (Get_Index_From_Generic_Name + (Filename, + Kind => Files_Table.Source_File, + Indexed_Simple_Name => True), + Base_Cmd); + + Cmd := Base_Cmd; + + Append_Arg (Cmd, "-v"); + Append_Arg (Cmd, "-o"); + Append_Arg (Cmd, Preprocessed_Filename); + + Success := + Run_Command + (Command => Cmd, + Origin_Command_Name => "Preprocessing", + Output_File => Preprocessor_Output_Filename, + Ignore_Error => True); + + -- If this preprocessing command succeeded, warn the user that we + -- will not be able to process in-source annotations for this file + -- and included headers. + + if Success then + Warn + ("Could not preserve comments while pre-processing " & Filename + & ", annotations in comments within this file or included" + & " headers will not be taken into account"); + end if; + end if; -- Clear the search path so that we populate it from the include search -- paths in the logs. From 36db09a4b857a3bd553a05ff2b694276f65bbe98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 19 May 2025 14:21:17 +0200 Subject: [PATCH 1226/1483] Doc: document limitation concerning token concatenation during pre-processing --- doc/gnatcov/src_traces.rst | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 9c21f270f..ca9f873c5 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -642,6 +642,13 @@ it is required to remove any :cmd-option:`-include` switch that is passed to the compiler invocation, by having a dedicated scenario variable for a coverage build for instance. +To support annotations such as :ref:`exemptions` or :ref:`buffer +output indications`, the |gcvins| attempts to preserve comments +when preprocessing the sources. If this is not possible (e.g. due to illegal +concatenation of a comment with another token), the tool will emit a warning +and ignore any in-source annotation for the mentioned file, as well as any +other transitively included file. + Function and call coverage limitations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 0a36626871915e3a1ade038aafe84913e21eb28f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 26 Mar 2025 17:03:19 +0100 Subject: [PATCH 1227/1483] Integrated instr: Properly handle -M family of switches These preprocessor flags imply -E, so there is nothing to do on the gnatcov side. --- .../401-M-flags/special_0.h | 1 + .../401-M-flags/test.c | 7 +++ .../401-M-flags/test.py | 60 +++++++++++++++++++ tools/gnatcov/instrument-gcc_wrapper.adb | 18 +++++- 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/integrated_instrumentation/401-M-flags/special_0.h create mode 100644 testsuite/tests/integrated_instrumentation/401-M-flags/test.c create mode 100644 testsuite/tests/integrated_instrumentation/401-M-flags/test.py diff --git a/testsuite/tests/integrated_instrumentation/401-M-flags/special_0.h b/testsuite/tests/integrated_instrumentation/401-M-flags/special_0.h new file mode 100644 index 000000000..d0e7c1eea --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/401-M-flags/special_0.h @@ -0,0 +1 @@ +const int special_0 = 0; diff --git a/testsuite/tests/integrated_instrumentation/401-M-flags/test.c b/testsuite/tests/integrated_instrumentation/401-M-flags/test.c new file mode 100644 index 000000000..dddbe4dda --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/401-M-flags/test.c @@ -0,0 +1,7 @@ +#include "special_0.h" + +int +main () +{ + return special_0; +} diff --git a/testsuite/tests/integrated_instrumentation/401-M-flags/test.py b/testsuite/tests/integrated_instrumentation/401-M-flags/test.py new file mode 100644 index 000000000..b6dec82f5 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/401-M-flags/test.py @@ -0,0 +1,60 @@ +""" +Test that the output of the -M family of flags of the GCC preprocessor is not +clobbered with references to instrumentation artifacts. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import contents_of, Wdir +from SUITE.tutils import cmdrun, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources in the temporary directory +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "special_0.h"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'test.c')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) +baseline_dep_file = "test.dep.expected" +compile_cmd = [ + "gcc", + "test.c", + "-MM", + "-MF", + baseline_dep_file, +] + +# Generate the baseline dep file with the regular compiler +cmdrun(compile_cmd, for_pgm=False) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Ask gcc to produce a dep file, using the gnatcov wrapper this time +dep_file = "test.dep.actual" +compile_cmd.pop() +compile_cmd.append(dep_file) +cmdrun(compile_cmd, for_pgm=False) + +thistest.fail_if_not_equal( + what="Difference in generated dep file", + expected=contents_of(baseline_dep_file), + actual=contents_of(dep_file), +) + +thistest.result() diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 8e1631f1d..6fcd96791 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -655,12 +655,24 @@ is Arg : constant Unbounded_String := Element (Cur); Arg_Str : constant String := +Arg; begin + -- Include family switches will have already had an effect during + -- the initial preprocessing, skip them here + if Arg_Str in "-include" | "--include" then Cur := Next (Cur); elsif Starts_With (Arg, "--include=") or else Starts_With (Arg, "-include") then null; + + -- The -M family of switches should not be propagated as it + -- otherwise leads to the inclusion of coverage artifacts in the + -- generated dependency files. + + elsif Arg_Str in "-MF" | "-MT" | "-MQ" then + Next (Cur); + elsif Starts_With (Arg, "-M") then + null; else Result.Append (Element (Cur)); end if; @@ -758,9 +770,13 @@ begin -- If this driver invocation is not meant to compile a source file, there -- is no instrumentation to do: just run the original driver and exit. + -- + -- The -M family of flags imply -E, so there nothing to do for us in that + -- case too, EXCEPT FOR -MD and -MMD, which do not imply -E. See section + -- 13 of the C preprocessor manual. for Arg of Cargs loop - if +Arg in "-###" | "-E" then + if +Arg in "-###" | "-E" | "-M" | "-MM" then Run_Original_Compiler (Context, Cargs); return; end if; From 3e12ffeb252972d70517dcbeeb4f1a7e068c86e5 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 22 May 2025 16:31:25 +0200 Subject: [PATCH 1228/1483] instrument.ada_unit: Deduplicate Create_Identifier function --- tools/gnatcov/instrument-ada_unit.adb | 60 +++++++++++++-------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 792b26e79..d1c0b0b41 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -417,10 +417,6 @@ package body Instrument.Ada_Unit is | Ada_Decl_Expr); -- Whether nodes of type Kind must be wrapped with parens - function Create_Identifier - (RH : Rewriting_Handle; Text : Text_Type) return Node_Rewriting_Handle - is (Create_Token_Node (RH, Libadalang.Common.Ada_Identifier, Text)); - function Expression_Type (UIC : Ada_Unit_Inst_Context; E : Expr) return Base_Type_Decl; @@ -488,17 +484,15 @@ package body Instrument.Ada_Unit is -- Shortcut to create a node of the given kind function Make_Identifier - (UIC : Ada_Unit_Inst_Context'Class; - Id : Wide_Wide_String) return Node_Rewriting_Handle - is (Create_Token_Node - (UIC.Rewriting_Context, Libadalang.Common.Ada_Identifier, Id)); + (RH : Rewriting_Handle; Id : Text_Type) return Node_Rewriting_Handle + is (Create_Token_Node (RH, Libadalang.Common.Ada_Identifier, Id)); -- Shortcut to create an identifier node function Make_Defining_Name (UIC : Ada_Unit_Inst_Context'Class; D_Name : Wide_Wide_String) return Node_Rewriting_Handle is (Create_Defining_Name (UIC.Rewriting_Context, - Make_Identifier (UIC, D_Name))); + Make_Identifier (UIC.Rewriting_Context, D_Name))); -- Shortcut to create a defining identifier tree function Make_Std_Ref @@ -1691,7 +1685,7 @@ package body Instrument.Ada_Unit is .P_Top_Level_Decl (To_Type.Unit) .P_Canonical_Fully_Qualified_Name); To_Type_Indentifier := - Create_Identifier + Make_Identifier (IC.Rewriting_Context, To_Type.P_Canonical_Fully_Qualified_Name); else @@ -2050,7 +2044,7 @@ package body Instrument.Ada_Unit is else Insert_Info.RH_List); Result.Wrapper_Pkg_Name := - Make_Identifier (UIC, Gen_Names_Prefix & "Pkg"); + Make_Identifier (UIC.Rewriting_Context, Gen_Names_Prefix & "Pkg"); Result.Wrapper_Pkg_Decls := Create_Regular_Node (RC, Ada_Ada_Node_List, No_Children); @@ -2081,7 +2075,8 @@ package body Instrument.Ada_Unit is No_Param : constant Boolean := N_Spec.F_Subp_Params.Is_Null; begin - Nodes.Name := Make_Identifier (UIC, Gen_Names_Prefix & "Gen"); + Nodes.Name := Make_Identifier + (UIC.Rewriting_Context, Gen_Names_Prefix & "Gen"); Nodes.Formals := Make (UIC, Ada_Ada_Node_List); @@ -2456,7 +2451,7 @@ package body Instrument.Ada_Unit is -- Return a reference to this formal - return Make_Identifier (UIC, Formal_Type_Name); + return Make_Identifier (UIC.Rewriting_Context, Formal_Type_Name); end Make_Formal_Type; -- Start of processing for Collect_Null_Proc_Formals @@ -2577,7 +2572,7 @@ package body Instrument.Ada_Unit is "GNATcov_RTS.Buffers.MCDC_State_Holder"; State_Identifier : constant Node_Rewriting_Handle := - Make_Identifier (UIC, To_Wide_Wide_String (Name)); + Make_Identifier (UIC.Rewriting_Context, To_Wide_Wide_String (Name)); State_Formal : constant Node_Rewriting_Handle := Create_Defining_Name (RC, State_Identifier); @@ -2592,14 +2587,15 @@ package body Instrument.Ada_Unit is Children => (1 => State_Formal)), F_Has_Aliased => No_Node_Rewriting_Handle, F_Mode => No_Node_Rewriting_Handle, - F_Type_Expr => Make_Identifier (UIC, Holder_Type), + F_Type_Expr => Make_Identifier + (UIC.Rewriting_Context, Holder_Type), F_Default_Expr => No_Node_Rewriting_Handle, F_Aspects => No_Node_Rewriting_Handle); State_Actual : constant Node_Rewriting_Handle := Create_Qual_Expr (RC, - F_Prefix => Make_Identifier (UIC, Holder_Type), + F_Prefix => Make_Identifier (UIC.Rewriting_Context, Holder_Type), F_Suffix => Create_Aggregate (RC, @@ -2737,11 +2733,8 @@ package body Instrument.Ada_Unit is then Create_Dotted_Name (RC, F_Prefix => Clone (Common_Nodes.Wrapper_Pkg_Name), - F_Suffix => Create_Identifier - (RC, - Text => Augmented_Func_Name)) - else Create_Identifier - (RC, Text => Augmented_Func_Name)); + F_Suffix => Make_Identifier (RC, Augmented_Func_Name)) + else Make_Identifier (RC, Augmented_Func_Name)); Call_Expr : constant Node_Rewriting_Handle := (if Call_Params = No_Node_Rewriting_Handle @@ -2791,7 +2784,7 @@ package body Instrument.Ada_Unit is Replace (Handle (Common_Nodes.N_Name), - Make_Identifier (UIC, Augmented_Func_Name)); + Make_Identifier (UIC.Rewriting_Context, Augmented_Func_Name)); -- Use the "augmented formal params" (i.e. original formals plus the -- witness one and the MC/DC state holders). @@ -2838,7 +2831,8 @@ package body Instrument.Ada_Unit is if not Fun_Cov then Set_Child (New_Spec, Member_Refs.Subp_Spec_F_Subp_Name, - Make_Identifier (UIC, Augmented_Func_Name)); + Make_Identifier (UIC.Rewriting_Context, + Augmented_Func_Name)); end if; -- Add the augmented params to this spec as well @@ -2884,7 +2878,7 @@ package body Instrument.Ada_Unit is Ghost_Aspect : constant Node_Rewriting_Handle := Create_Aspect_Assoc (RC, - Make_Identifier (UIC, "Ghost"), + Make_Identifier (UIC.Rewriting_Context, "Ghost"), No_Node_Rewriting_Handle); Aspects : constant Node_Rewriting_Handle := @@ -4037,7 +4031,7 @@ package body Instrument.Ada_Unit is N_Spec : Subp_Spec) is Stub : constant Node_Rewriting_Handle := - Make_Identifier (UIC, "Stub"); + Make_Identifier (UIC.Rewriting_Context, "Stub"); -- Placeholder for the the degenerate subprogram node while it is -- rewritten. @@ -4182,7 +4176,7 @@ package body Instrument.Ada_Unit is Formal_Name : Wide_Wide_String) is Formal_Id : constant Node_Rewriting_Handle := - Make_Identifier (UIC, Formal_Name); + Make_Identifier (UIC.Rewriting_Context, Formal_Name); Formal_Def_Id : constant Node_Rewriting_Handle := Create_Regular_Node (UIC.Rewriting_Context, @@ -4542,7 +4536,8 @@ package body Instrument.Ada_Unit is .As_Param_Spec.F_Ids.Children loop Insert_Last - (Call_Params, Make_Identifier (UIC, Id.Text)); + (Call_Params, + Make_Identifier (UIC.Rewriting_Context, Id.Text)); end loop; end loop; end if; @@ -4825,7 +4820,7 @@ package body Instrument.Ada_Unit is (Common_Nodes.Wrapper_Pkg_Decls, Create_Pragma_Node (RC, - F_Id => Create_Identifier (RC, "Convention"), + F_Id => Make_Identifier (RC, "Convention"), F_Args => Create_Regular_Node (RC, Ada_Assoc_List, (1 => Clone (Convention_Id), @@ -7371,7 +7366,7 @@ package body Instrument.Ada_Unit is Bit : Any_Bit_Id) is Formal_Name : constant Node_Rewriting_Handle := - Make_Identifier (UIC, "Dummy_Witness_Result"); + Make_Identifier (UIC.Rewriting_Context, "Dummy_Witness_Result"); Formal_Def_Id : constant Node_Rewriting_Handle := Create_Regular_Node (UIC.Rewriting_Context, @@ -7776,7 +7771,7 @@ package body Instrument.Ada_Unit is begin for Id of Name loop declare - Id_Node : constant Node_Rewriting_Handle := Create_Identifier + Id_Node : constant Node_Rewriting_Handle := Make_Identifier (Handle, To_Text (To_String (Id))); begin if Result = No_Node_Rewriting_Handle then @@ -8189,7 +8184,7 @@ package body Instrument.Ada_Unit is Old_Cond := Create_Call_Expr (RC, - F_Name => Create_Identifier + F_Name => Make_Identifier (RC, To_Text ("GNATcov_RTS.Std.Boolean")), F_Suffix => Create_Regular_Node (RC, @@ -8316,7 +8311,8 @@ package body Instrument.Ada_Unit is RC : constant Rewriting_Handle := UIC.Rewriting_Context; Formal_Name : constant Node_Rewriting_Handle := - Make_Identifier (UIC, "Dummy_Witness_Result"); + Make_Identifier + (UIC.Rewriting_Context, "Dummy_Witness_Result"); Formal_Def_Id : constant Node_Rewriting_Handle := Create_Regular_Node (RC, From 9d45951e11c053b3e86954ac8dac7b03a165b988 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 14 May 2025 07:53:10 +0000 Subject: [PATCH 1229/1483] checkpoints.adb: mention the SID/checkpoint in case of invalid version Knowing which SID/checkpoint has an invalid version is necessary in order to investiate what is wrong. --- tools/gnatcov/checkpoints.adb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index a29aead9a..27f42796e 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -601,7 +601,8 @@ package body Checkpoints is CLS.Version := CLS.Read_U32; if CLS.Version /= Checkpoint_Version'Last then - Fatal_Error ("invalid checkpoint version" & CLS.Version'Img); + Fatal_Error + (Filename & ": invalid checkpoint version" & CLS.Version'Img); end if; -- Check that we are loading the kind of checkpoint we are From 94a7712fe0b4ccb1bcb32e0d07a665c365a9e28c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 20 May 2025 09:53:45 +0000 Subject: [PATCH 1230/1483] checkpoints.ads: remove the Version_Less function The current policy is not reject checkpoint/SID files whose format is not the current one: remove support code whose only purpose was to accept old formats. --- tools/gnatcov/checkpoints.ads | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 029384f98..1506bdd51 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -295,14 +295,6 @@ package Checkpoints is Static_Decision_Evaluations : Static_Decision_Evaluation_Maps.Map; end record; - use type Interfaces.Unsigned_32; - function Version_Less - (CLS : Checkpoint_Load_State; Than : Checkpoint_Version) return Boolean - is (CLS.Version < Than) - with Inline; - -- This is provided as a function to prevent the compiler from generating - -- "can never be greater than" warnings. - procedure Checkpoint_Save (Filename : String; Context : access Coverage.Context; From 651248c072c012585496412b817076def2443fde Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 14 May 2025 16:35:23 +0000 Subject: [PATCH 1231/1483] Remove support for separated coverage on generics --- doc/gnatcov/bin_intro.rst | 2 - doc/gnatcov/gnatcov_bin_part.rst | 1 - doc/gnatcov/separate_cov.rst | 93 -- .../Variants_ByConstruct/src/check_g.adb | 10 - .../Variants_ByConstruct/src/check_g.ads | 10 - .../Variants_ByConstruct/src/sensors.adb | 13 - .../Variants_ByConstruct/src/sensors.ads | 15 - .../Variants_ByConstruct/src/test_cbfn.adb | 45 - .../Variants_ByConstruct/src/test_cifn.adb | 38 - .../Variants_ByConstruct/src/test_cifo.adb | 44 - .../Variants_ByConstruct/src/test_cnfn.adb | 27 - .../Variants_ByConstruct/src/test_cnfo.adb | 29 - .../Variants_ByConstruct/tc.rst | 9 - .../Variants_ByConstruct/test.opt | 3 - .../Variants_ByConstruct/test.py | 8 - .../Variants_BySubprogram/src/test_5i_8m.adb | 30 - .../Variants_BySubprogram/src/test_5m_8i.adb | 30 - .../Variants_BySubprogram/src/test_6i_9i.adb | 25 - .../Variants_BySubprogram/src/test_6i_9m.adb | 25 - .../Variants_BySubprogram/src/test_6m_9i.adb | 25 - .../Variants_BySubprogram/src/test_6m_9m.adb | 25 - .../Variants_BySubprogram/src/test_6mi_9m.adb | 25 - .../src/test_6mi_9mi.adb | 25 - .../Variants_BySubprogram/src/v5.ads | 2 - .../Variants_BySubprogram/src/v6or9.adb | 31 - .../Variants_BySubprogram/src/v6or9.ads | 3 - .../Variants_BySubprogram/src/v8.ads | 2 - .../Variants_BySubprogram/src/vops.adb | 17 - .../Variants_BySubprogram/src/vops.ads | 11 - .../Variants_BySubprogram/tc.rst | 9 - .../Variants_BySubprogram/test.opt | 3 - .../Variants_BySubprogram/test.py | 8 - .../tests/207-srctrace-version/foo.c.sid | Bin 1192 -> 1191 bytes testsuite/tests/207-srctrace-version/main.sid | Bin 1433 -> 1418 bytes .../207-srctrace-version/reference.srctrace | Bin 336 -> 336 bytes .../Mode_Variants_MCDC/src/check_g.adb | 10 - .../Mode_Variants_MCDC/src/check_g.ads | 10 - .../Mode_Variants_MCDC/src/sensors.adb | 13 - .../Mode_Variants_MCDC/src/sensors.ads | 15 - .../Mode_Variants_MCDC/src/test_cbfn.adb | 54 - .../Mode_Variants_MCDC/src/test_cifn.adb | 47 - .../Mode_Variants_MCDC/src/test_cifo.adb | 55 - .../Mode_Variants_MCDC/src/test_cnfn.adb | 37 - .../Mode_Variants_MCDC/src/test_cnfo.adb | 38 - .../tests/Generics/Mode_Variants_MCDC/tc.txt | 100 -- .../Generics/Mode_Variants_MCDC/test.opt | 3 - .../tests/Generics/Mode_Variants_MCDC/test.py | 25 - .../Mode_Variants_STMT/src/test_v5_reset.adb | 29 - .../Generics/Mode_Variants_STMT/src/v5.ads | 2 - .../Mode_Variants_STMT/src/vectors.adb | 30 - .../Mode_Variants_STMT/src/vectors.ads | 10 - .../Generics/Mode_Variants_STMT/test.opt | 1 - .../tests/Generics/Mode_Variants_STMT/test.py | 16 - .../generic_hello.adb | 6 - .../generic_hello.ads | 3 - .../S619-014-tag-provider-mismatch/main.adb | 13 - .../S619-014-tag-provider-mismatch/test.py | 64 - .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 1508 -> 1508 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2612 -> 2580 bytes .../gen/arm-elf-linux/gcvrt-foo-observe.adb | 16 + .../gen/arm-elf-linux/gcvrt-foo-observe.ads | 3 + .../gen/arm-elf-linux/main_1.sid | Bin 448 -> 433 bytes .../gen/arm-elf-linux/main_2.sid | Bin 448 -> 433 bytes .../gen/arm-elf-linux/pkg.sid | Bin 1137 -> 1122 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1931 -> 1907 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1941 -> 1917 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 2166 -> 2124 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 2097 -> 2055 bytes .../gen/x86_64-windows/gcvrt-foo-observe.adb | 16 + .../gen/x86_64-windows/gcvrt-foo-observe.ads | 3 + .../gen/x86_64-windows/main_1.sid | Bin 450 -> 435 bytes .../gen/x86_64-windows/main_2.sid | Bin 450 -> 435 bytes .../gen/x86_64-windows/pkg.sid | Bin 1141 -> 1126 bytes tools/gnatcov/annotations-report.adb | 19 +- tools/gnatcov/annotations.adb | 5 - tools/gnatcov/checkpoints.ads | 3 +- tools/gnatcov/command_line.ads | 9 - tools/gnatcov/coverage-source.adb | 1404 ++++++----------- tools/gnatcov/coverage-source.ads | 13 +- tools/gnatcov/coverage-tags.adb | 106 -- tools/gnatcov/coverage-tags.ads | 136 -- tools/gnatcov/coverage.ads | 7 - tools/gnatcov/decision_map.adb | 47 +- tools/gnatcov/diagnostics.adb | 37 +- tools/gnatcov/diagnostics.ads | 12 +- tools/gnatcov/gnatcov_bits_specific.adb | 25 - tools/gnatcov/instrument-gcc_wrapper.adb | 2 - tools/gnatcov/sc_obligations.adb | 147 +- tools/gnatcov/traces_elf.adb | 8 +- tools/gnatcov/traces_names.adb | 115 +- tools/gnatcov/traces_names.ads | 7 +- 91 files changed, 604 insertions(+), 2760 deletions(-) delete mode 100644 doc/gnatcov/separate_cov.rst delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.ads delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.ads delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cbfn.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifn.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifo.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfn.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfo.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/tc.rst delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.opt delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.py delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5i_8m.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5m_8i.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9i.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9m.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9i.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9m.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9m.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9mi.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v5.ads delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.ads delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v8.ads delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.adb delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.ads delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/tc.rst delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.opt delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.py delete mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/check_g.adb delete mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/check_g.ads delete mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.adb delete mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.ads delete mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cbfn.adb delete mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifn.adb delete mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifo.adb delete mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfn.adb delete mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfo.adb delete mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/tc.txt delete mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/test.opt delete mode 100644 testsuite/tests/Generics/Mode_Variants_MCDC/test.py delete mode 100644 testsuite/tests/Generics/Mode_Variants_STMT/src/test_v5_reset.adb delete mode 100644 testsuite/tests/Generics/Mode_Variants_STMT/src/v5.ads delete mode 100644 testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.adb delete mode 100644 testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.ads delete mode 100644 testsuite/tests/Generics/Mode_Variants_STMT/test.opt delete mode 100644 testsuite/tests/Generics/Mode_Variants_STMT/test.py delete mode 100644 testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.adb delete mode 100644 testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.ads delete mode 100644 testsuite/tests/S619-014-tag-provider-mismatch/main.adb delete mode 100644 testsuite/tests/S619-014-tag-provider-mismatch/test.py create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo-observe.adb create mode 100644 testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-foo-observe.ads create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo-observe.adb create mode 100644 testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-foo-observe.ads delete mode 100644 tools/gnatcov/coverage-tags.adb delete mode 100644 tools/gnatcov/coverage-tags.ads diff --git a/doc/gnatcov/bin_intro.rst b/doc/gnatcov/bin_intro.rst index 651a0e6de..398eebd1b 100644 --- a/doc/gnatcov/bin_intro.rst +++ b/doc/gnatcov/bin_intro.rst @@ -186,6 +186,4 @@ specific considerations: - :ref:`osmetrics` -- :ref:`generics_sep` - - :ref:`bin_convert` diff --git a/doc/gnatcov/gnatcov_bin_part.rst b/doc/gnatcov/gnatcov_bin_part.rst index 6a5d1462c..e9c3a9e8c 100644 --- a/doc/gnatcov/gnatcov_bin_part.rst +++ b/doc/gnatcov/gnatcov_bin_part.rst @@ -11,5 +11,4 @@ Appendix A. Using GNATcoverage Binary Traces cov_metrics bin_gps bin_convert - separate_cov bin_limitations diff --git a/doc/gnatcov/separate_cov.rst b/doc/gnatcov/separate_cov.rst deleted file mode 100644 index e36839204..000000000 --- a/doc/gnatcov/separate_cov.rst +++ /dev/null @@ -1,93 +0,0 @@ -.. _generics_sep: - -Separated coverage on generics ------------------------------- - -As described in section :ref:`generics_cov`, a single coverage analysis -of any source construct is performed by default, consolidating all code copies -generated by this construct. For subprograms, this means consolidation over all -inlined copies. For generic units, consolidation over all instances. - -A finer-grained analysis is possible, where distinct copies of the code coming -from a given source construct are identified according to some criterion, and -a separate coverage assessment is made for each of these copies. - -In this case, coverage violations carry an additional indication of which code -copy the violation is reported for, available in all but the non-extended -``xcov`` and ``html`` output formats. The non-extended ``xcov`` and ``html`` -formats simply convey partial coverage achievement on a line as soon one -violation get reported for an obligation on that line, regardless of which -copy the violation originates from. - -|gcv| supports different modes for such analyses, detailed in the following -subsections. - - -Separation by instance (:cmd-option:`-S instance`) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In this mode, two code regions coming from the same source construct will -undergo separate coverage analyses if they come from different generic -instances, identified by the instanciation source location. - -For our ``Vops`` example, selecting an output format where the -violations detailed are exposed, this translates as:: - - gnatcov coverage -Pvops.gpr --annotate=report -S instance [...] - ... - vops.adb:5:11: statement not executed (from v8.ads:2:1) - vops.adb:6:10: statement not executed (from v8.ads:2:1) - vops.adb:12:11: statement not executed (from v5.ads:2:1) - vops.adb:13:10: statement not executed (from v5.ads:2:1) - - -We do observe violations on the ``Vops`` generic body, fully covered without -:cmd-option:`-S instance`. This is the outcome of an analysis conducted on the -two generic instances separately, each designated by a ``(from )`` indication. - -|gcv| needs to see the coverage obligations corresponding to each instance in -this mode. This is achieved transparently by the use of a project file in the -example command lines we quoted and needs particular care when the Library -Information files are provided manually with :cmd-option:`--scos` instead. - -Indeed, even if we aim at getting coverage results for the ``vops.adb`` source, -passing :cmd-option:`--scos=vops.ali` alone isn't enough when per instance -separate analysis is desired. Separate coverage analysis for the instances -entails coverage obligations for the instances, and this requires the units -where the instantiations occur to be declared of interest as well. In our -example, this means passing :cmd-option:`--scos=v5.ali` and -:cmd-option:`--scos=v8.ali` in addition. - -Separation by instance relies on specific compiler support available in the -GNAT Pro toolchain since the 7.2 release. For older toolchains, another mode -is available which reports separate coverage statuses for copies associated -with distinct symbols of the executable file. As we will describe, this -provides a good approximation of per-instance analysis in absence of inlining, -and becomes inaccurate when inlining comes into play. - -Separation by routine (:cmd-option:`-S routine`, *obsolete*) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -In this mode, two code regions coming from the same source construct will -undergo separate coverage analyses if they occur in different symbols of the -executable file. This scheme is obsolete, unreliable in presence of inlining. - -When a given subprogram is inlined in two different calling routines, each -inlined copy thus undergoes a separate coverage assessment. In the absence of -inlining, this will also ensure that different instances of the same generic -unit will have separated coverage analyses, since the compiler generates -different symbol names for different program units. For our ``Vops`` example, -this would be:: - - gnatcov coverage -Pvops.gpr --annotate=report -S routine [...] - ... - vops.adb:5:11: statement not executed (from v8__inc) - vops.adb:6:10: statement not executed (from v8__inc) - vops.adb:12:11: statement not executed (from v5__mult) - vops.adb:13:10: statement not executed (from v5__mult) - - -On the other hand, if two distinct instances of a generic subprogram are -inlined within a single calling routine, they will undergo a single coverage -analysis since they now occur in the same symbol. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.adb deleted file mode 100644 index bb514d75b..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.adb +++ /dev/null @@ -1,10 +0,0 @@ -package body Check_G is - procedure Test (Value : T) is - begin - if Low > Value or else High < Value then -- # test-out - Out_Of_Range_Count := Out_Of_Range_Count + 1; -- # out-range - else - In_Range_Count := In_Range_Count + 1; -- # in-range - end if; - end Test; -end Check_G; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.ads deleted file mode 100644 index 6c18d8129..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/check_g.ads +++ /dev/null @@ -1,10 +0,0 @@ -generic - type T is new Float; - Low, High : T; -package Check_G is - procedure Test (Value : T); - pragma Inline (Test); - - In_Range_Count : Natural := 0; - Out_Of_Range_Count : Natural := 0; -end Check_G; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.adb deleted file mode 100644 index 7bb9a328d..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.adb +++ /dev/null @@ -1,13 +0,0 @@ -package body Sensors is - - procedure Test (Value : Float; Unit : Temp_Unit) is - begin - if Unit = C then -- # check-test-c - N_Tests_C := N_Tests_C + 1; -- # check-do-c - RC.Test (Temp_C (Value)); -- # check-do-c - else - N_Tests_F := N_Tests_F + 1; -- # check-do-f - RF.Test (Temp_F (Value)); -- # check-do-f - end if; - end Test; -end Sensors; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.ads deleted file mode 100644 index 1047d0237..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/sensors.ads +++ /dev/null @@ -1,15 +0,0 @@ -with Check_G; - -package Sensors is - type Temp_C is new Float range -273.15 .. Float'Last; - package RC is new Check_G (Temp_C, 0.0, 100.0); -- # i:RC - - type Temp_F is new Float range -459.67 .. Float'Last; - package RF is new Check_G (Temp_F, 32.0, 212.0);-- # i:RF - - type Temp_Unit is (C, F); - - procedure Test (Value : Float; Unit : Temp_Unit); - - N_Tests_C, N_Tests_F : Natural := 0; -end Sensors; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cbfn.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cbfn.adb deleted file mode 100644 index 24b22303f..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cbfn.adb +++ /dev/null @@ -1,45 +0,0 @@ -with Sensors, Support; use Sensors, Support; - --- CBFN : Invoking Both in and out of range for unit "C". None for unit "F". - -procedure Test_CBFN is -begin - -- C in range (!low !high => Out-False) - - Sensors.Test (37.0, C); - - -- C out of range (!low, high => Out-True) - - Sensors.Test (200.0, C); - - Assert (Sensors.N_Tests_C = 2); - Assert (Sensors.N_Tests_F = 0); - - Assert (RC.In_Range_Count = 1); - Assert (RC.Out_Of_Range_Count = 1); - Assert (RF.In_Range_Count = 0); - Assert (RF.Out_Of_Range_Count = 0); - -end Test_CBFN; - ---# sensors.adb --- /check-test-c/ l+ ## 0 --- /check-do-c/ l+ ## 0 --- /check-do-f/ l- ## s- - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- /test-out/ l+ ## 0 --- /in-range/ l+ ## 0 --- /out-range/ l+ ## 0 - --- %cov: -S instance --- =/test-out/ l! ## s-@(i:RF) --- =/in-range/ l! ## s-@(i:RF) --- =/out-range/ l! ## s-@(i:RF) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifn.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifn.adb deleted file mode 100644 index cec25a425..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifn.adb +++ /dev/null @@ -1,38 +0,0 @@ -with Support, Sensors; use Support, Sensors; - -procedure Test_CIFN is -begin - -- C in range - - Sensors.Test (37.0, C); - - Assert (Sensors.N_Tests_C = 1); - Assert (Sensors.N_Tests_F = 0); - - Assert (RC.In_Range_Count = 1); - Assert (RC.Out_Of_Range_Count = 0); - Assert (RF.In_Range_Count = 0); - Assert (RF.Out_Of_Range_Count = 0); -end Test_CIFN; - ---# sensors.adb --- /check-test-c/ l+ ## 0 --- /check-do-c/ l+ ## 0 --- /check-do-f/ l- ## s- - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- /test-out/ l+ ## 0 --- /in-range/ l+ ## 0 --- /out-range/ l- ## s- - --- %cov: -S instance --- =/test-out/ l! ## s-@(i:RF) --- =/in-range/ l! ## s-@(i:RF) --- =/out-range/ l- ## s-@(i:RF), s-@(i:RC) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifo.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifo.adb deleted file mode 100644 index e752e0476..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cifo.adb +++ /dev/null @@ -1,44 +0,0 @@ -with Sensors, Support; use Sensors, Support; - -procedure Test_CIFO is -begin - -- C in range - - Sensors.Test (37.0, C); - - -- F out of range - - Sensors.Test (0.0, F); - - Assert (Sensors.N_Tests_C = 1); - Assert (Sensors.N_Tests_F = 1); - - Assert (RC.In_Range_Count = 1); - Assert (RC.Out_Of_Range_Count = 0); - Assert (RF.In_Range_Count = 0); - Assert (RF.Out_Of_Range_Count = 1); - -end Test_CIFO; - ---# sensors.adb --- /check-test-c/ l+ ## 0 --- /check-do-c/ l+ ## 0 --- /check-do-f/ l+ ## 0 - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- defaults, for instances conslidated: --- /test-out/ l+ ## 0 --- /in-range/ l+ ## 0 --- /out-range/ l+ ## 0 - --- %cov: -S instance --- =/test-out/ s=>l+, dmu=>l! ## dT-@(i:RC), dF-@(i:RF) --- =/in-range/ l! ## s-@(i:RF) --- =/out-range/ l! ## s-@(i:RC) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfn.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfn.adb deleted file mode 100644 index 73b77d250..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfn.adb +++ /dev/null @@ -1,27 +0,0 @@ -with Sensors; use Sensors; -procedure Test_CNFN is -begin - null; -end Test_CNFN; - ---# sensors.adb --- /check-test-c/ l- ## s- --- /check-do-c/ l- ## s- --- /check-do-f/ l- ## s- - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- /test-out/ l- ## s- --- /in-range/ l- ## s- --- /out-range/ l- ## s- - --- %cov: -S instance --- =/test-out/ l- ## s-@(i:RF), s-@(i:RC) --- =/in-range/ l- ## s-@(i:RF), s-@(i:RC) --- =/out-range/ l- ## s-@(i:RF), s-@(i:RC) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfo.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfo.adb deleted file mode 100644 index 9383e29a2..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/src/test_cnfo.adb +++ /dev/null @@ -1,29 +0,0 @@ -with Sensors; use Sensors; -procedure Test_CNFO is -begin - -- F out of range - - Sensors.Test (0.0, F); -end Test_CNFO; - ---# sensors.adb --- /check-test-c/ l+ ## 0 --- /check-do-c/ l- ## s- --- /check-do-f/ l+ ## 0 - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- /test-out/ l+ ## 0 --- /in-range/ l- ## s- --- /out-range/ l+ ## 0 - --- %cov: -S instance --- =/test-out/ l! ## s-@(i:RC) --- =/in-range/ l- ## s-@(i:RF), s-@(i:RC) --- =/out-range/ l! ## s-@(i:RC) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/tc.rst deleted file mode 100644 index 9081d5cb7..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/tc.rst +++ /dev/null @@ -1,9 +0,0 @@ -**Exercise SC on multiple generic instances, triggering different paths** - -Exercise Statement Coverage on multiple instances -of generic packages provided either as local packages within another package -spec. Enforce coverage variations by calling subprograms with arguments values -controlling different paths within the subprograms thanks to conditional -constructs. - -LRMREF: 12.3 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.opt deleted file mode 100644 index 71da06bed..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -7.1.2 DEAD testing per-instance analysis of generics, implemented post 7.0.3 -src-traces XFAIL S628-011: src-traces and per-instance coverage of generics -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.py b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.py deleted file mode 100644 index 3803d3a25..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_ByConstruct/test.py +++ /dev/null @@ -1,8 +0,0 @@ -from SCOV.tc import TestCase -from SCOV.tctl import CovControl -from SUITE.context import thistest - -tc = TestCase() -tc.run() -tc.run(covcontrol=CovControl(covoptions="-S instance"), subdirhint="i_") -thistest.result() diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5i_8m.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5i_8m.adb deleted file mode 100644 index d8f3b46d6..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5i_8m.adb +++ /dev/null @@ -1,30 +0,0 @@ -with V5, V8; use V5, V8; -with Support; use Support; - --- Call inc only on the v5 instance and mult only on the v8 instance. - -procedure Test_5i_8m is - V5o : V5.Vector_Type := (others => 1); - V8o : V8.Vector_Type := (others => 2); -begin - V5.Inc (V5o, 3); - Assert (V5o(1) = 4); - - V8.Mult (V8o, 2); - Assert (V5o(2) = 4); -end; - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l+ ## 0 --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l! ## s-@(i:V5) --- =/inc/ l! ## s-@(i:V8) - --- -S instance needs to see the instantiation ALIs as well: - ---# v5.ads - ---# v8.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5m_8i.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5m_8i.adb deleted file mode 100644 index 1b1a1ea71..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_5m_8i.adb +++ /dev/null @@ -1,30 +0,0 @@ -with V5, V8; use V5, V8; -with Support; use Support; - --- Call mult only on the v5 instance and inc only on the v8 instance. - -procedure Test_5m_8i is - V5o : V5.Vector_Type := (others => 1); - V8o : V8.Vector_Type := (others => 2); -begin - V5.Inc (V5o, 3); - Assert (V5o(1) = 4); - - V8.Mult (V8o, 2); - Assert (V5o(2) = 4); -end; - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l+ ## 0 --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l! ## s-@(i:V5) --- =/inc/ l! ## s-@(i:V8) - --- -S instance needs to see the instantiation ALIs as well: - ---# v5.ads - ---# v8.ads diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9i.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9i.adb deleted file mode 100644 index f614767a8..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9i.adb +++ /dev/null @@ -1,25 +0,0 @@ -with V6or9; - -procedure Test_6i_9i is -begin - V6or9.Check (V6inc => True, - V6mult => False, - V9inc => True, - V9mult => False); -end; - ---# v6or9.adb --- /stmt/ l+ ## 0 --- /6i/ l+ ## 0 --- /6m/ l- ## s- --- /9i/ l+ ## 0 --- /9m/ l- ## s- - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l- ## s- --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l- ## s-@(i:V6), s-@(i:V9) --- =/inc/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9m.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9m.adb deleted file mode 100644 index ca98e0483..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6i_9m.adb +++ /dev/null @@ -1,25 +0,0 @@ -with V6or9; - -procedure Test_6i_9m is -begin - V6or9.Check (V6inc => True, - V6mult => False, - V9inc => False, - V9mult => True); -end; - ---# v6or9.adb --- /stmt/ l+ ## 0 --- /6i/ l+ ## 0 --- /6m/ l- ## s- --- /9i/ l- ## s- --- /9m/ l+ ## 0 - ---# vops.adb --- defaults, for instances consolidated: --- /mult/ l+ ## 0 --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l! ## s-@(i:V6) --- =/inc/ l! ## s-@(i:V9) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9i.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9i.adb deleted file mode 100644 index 04da01f4c..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9i.adb +++ /dev/null @@ -1,25 +0,0 @@ -with V6or9; - -procedure Test_6m_9i is -begin - V6or9.Check (V6inc => False, - V6mult => True, - V9inc => True, - V9mult => False); -end; - ---# v6or9.adb --- /stmt/ l+ ## 0 --- /6i/ l- ## s- --- /6m/ l+ ## 0 --- /9i/ l+ ## 0 --- /9m/ l- ## s- - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l+ ## 0 --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l! ## s-@(i:V9) --- =/inc/ l! ## s-@(i:V6) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9m.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9m.adb deleted file mode 100644 index 37781bd82..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6m_9m.adb +++ /dev/null @@ -1,25 +0,0 @@ -with V6or9; - -procedure Test_6m_9m is -begin - V6or9.Check (V6inc => False, - V6mult => True, - V9inc => False, - V9mult => True); -end; - ---# v6or9.adb --- /stmt/ l+ ## 0 --- /6i/ l- ## s- --- /6m/ l+ ## 0 --- /9i/ l- ## s- --- /9m/ l+ ## 0 - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l+ ## 0 --- /inc/ l- ## s- - --- %cov: -S instance --- =/mult/ l+ ## 0 --- =/inc/ l- ## s-@(i:V6), s-@(i:V9) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9m.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9m.adb deleted file mode 100644 index 50dea2942..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9m.adb +++ /dev/null @@ -1,25 +0,0 @@ -with V6or9; - -procedure Test_6mi_9m is -begin - V6or9.Check (V6inc => True, - V6mult => True, - V9inc => False, - V9mult => True); -end; - ---# v6or9.adb --- /stmt/ l+ ## 0 --- /6i/ l+ ## 0 --- /6m/ l+ ## 0 --- /9i/ l- ## s- --- /9m/ l+ ## 0 - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l+ ## 0 --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l+ ## 0 --- =/inc/ l! ## s-@(i:V9) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9mi.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9mi.adb deleted file mode 100644 index c0bdd76d5..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/test_6mi_9mi.adb +++ /dev/null @@ -1,25 +0,0 @@ -with V6or9; - -procedure Test_6mi_9mi is -begin - V6or9.Check (V6inc => True, - V6mult => True, - V9inc => True, - V9mult => True); -end; - ---# v6or9.adb --- /stmt/ l+ ## 0 --- /6i/ l+ ## 0 --- /6m/ l+ ## 0 --- /9i/ l+ ## 0 --- /9m/ l+ ## 0 - ---# vops.adb --- defaults, for instances conslidated: --- /mult/ l+ ## 0 --- /inc/ l+ ## 0 - --- %cov: -S instance --- =/mult/ l+ ## 0 --- =/inc/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v5.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v5.ads deleted file mode 100644 index 567d5a77e..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v5.ads +++ /dev/null @@ -1,2 +0,0 @@ -with Vops; -package v5 is new Vops (Size => 5); -- # i:V5 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.adb deleted file mode 100644 index 998bf5e3a..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.adb +++ /dev/null @@ -1,31 +0,0 @@ -with Vops, Support; use Support; - -package body V6or9 is - - procedure Check (V6inc, V6mult, V9inc, V9mult : Boolean) is - package V6 is new Vops (Size => 6); -- # i:V6 - V6i : V6.Vector_Type := (others => 2); - V6m : V6.Vector_Type := (others => 2); - - package V9 is new Vops (Size => 9); -- # i:V9 - V9i : V9.Vector_Type := (others => 3); - V9m : V9.Vector_Type := (others => 3); - begin - if V6inc then -- # stmt - V6.Inc (V6i, 1); -- # 6i - Assert (V6i(1) = 3); -- # 6i - end if; - if V6mult then -- # stmt - V6.Mult (V6m, 2); -- # 6m - Assert (V6m(1) = 4); -- # 6m - end if; - if V9inc then -- # stmt - V9.Inc (V9i, 1); -- # 9i - Assert (V9i(1) = 4); -- # 9i - end if; - if V9mult then -- # stmt - V9.Mult (V9m, 2); -- # 9m - Assert (V9m(1) = 6); -- # 9m - end if; - end; -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.ads deleted file mode 100644 index 6a8adb5a8..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v6or9.ads +++ /dev/null @@ -1,3 +0,0 @@ -package V6or9 is - procedure Check (V6inc, V6mult, V9inc, V9mult : Boolean); -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v8.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v8.ads deleted file mode 100644 index 0b51f83ad..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/v8.ads +++ /dev/null @@ -1,2 +0,0 @@ -with Vops; -package v8 is new Vops (Size => 8); -- # i:V8 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.adb b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.adb deleted file mode 100644 index 11e51fb0c..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.adb +++ /dev/null @@ -1,17 +0,0 @@ -package body Vops is - - procedure Inc (V : in out Vector_Type; Amount : Integer) is - begin - for I in V'Range loop -- # inc - V(I) := V(I) + Amount; -- # inc - end loop; - end; - - procedure Mult (V : in out Vector_Type; Amount : Integer) is - begin - for I in V'Range loop -- # mult - V(I) := V(I) * Amount; -- # mult - end loop; - end; - -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.ads b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.ads deleted file mode 100644 index f68701fe6..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/src/vops.ads +++ /dev/null @@ -1,11 +0,0 @@ --- This can be instantiated multiple times e.g. for different vector sizes, --- and different instances may call different sets of subprograms. - -generic - Size : in Integer; -package Vops is - type Vector_Type is array (1 .. Size) of Integer; - - procedure Inc (V : in out Vector_Type; Amount : Integer); - procedure Mult (V : in out Vector_Type; Amount : Integer); -end; diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/tc.rst b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/tc.rst deleted file mode 100644 index 969bebc33..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/tc.rst +++ /dev/null @@ -1,9 +0,0 @@ -**Exercise SC on multiple generic instances, triggering different subprograms** - -Exercise Statement Coverage on multiple instances -of generic packages provided either as independant compilation units or as -local packages within a subprogram body. Enforce coverage variations by -calling different subsets of subprograms exposed by each instance and going -through different paths in each subprogram. - -LRMREF: 12.3 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.opt deleted file mode 100644 index 71da06bed..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -7.1.2 DEAD testing per-instance analysis of generics, implemented post 7.0.3 -src-traces XFAIL S628-011: src-traces and per-instance coverage of generics -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.py b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.py deleted file mode 100644 index 3803d3a25..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/Variants_BySubprogram/test.py +++ /dev/null @@ -1,8 +0,0 @@ -from SCOV.tc import TestCase -from SCOV.tctl import CovControl -from SUITE.context import thistest - -tc = TestCase() -tc.run() -tc.run(covcontrol=CovControl(covoptions="-S instance"), subdirhint="i_") -thistest.result() diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid index 92dadde8dfd08344162c890d6850b978f6726304..bb34af6790d7bbe92f9aef8facf142998a8876d3 100644 GIT binary patch delta 88 zcmZ3%xtvqP-On*3IloLHIU_YWyC6R^uY^HpqsVk7MwZQMn8X;Bycif5^fU5vQ}t6) mi}F(vOZ1aUGjme()AJHbfco@{lO|td-p&J5#lQ$6fB*o&Tp0%d delta 89 zcmZ3^xq?%~-On*3IloLHIU_YWyC6R^uY^HxqsVk7MyAbcn8X-GY#10A^fU5vQ}qi{ ki}LgI%M;5|CqH4{F3kv(Ub%7 diff --git a/testsuite/tests/207-srctrace-version/main.sid b/testsuite/tests/207-srctrace-version/main.sid index e8241407654806f21f73d3f22be3723eedd5b466..3df21e8297b685bd6c7a9bd8734e430ed6833b3f 100644 GIT binary patch delta 79 zcmbQq-Nh~9?&lbioL{DpoRONGU67xdSHd8)QKW>4F?n()lM5ru&Abay4 XW+6r(ho2QB5yGm)!vF+~AOZ*gq(c(p delta 94 zcmeC;p2;oZ?&lbioL{DpoRONGU67xdSHd8;QKW>4F==uqlM5r$&Abay4 kW+6r(ho2QB5yGk^&B(yOzz)PIscDI&IVC_A14sx20PTkr(*OVf diff --git a/testsuite/tests/207-srctrace-version/reference.srctrace b/testsuite/tests/207-srctrace-version/reference.srctrace index d68d2095d8930d37da2229371a5e741643153aca..8da91906d78a46343cb58d4c0977ce2fb52b5474 100644 GIT binary patch delta 15 Wcmcb>bb)Dt151d7O2$SP9!3Bvhy;@W delta 15 Wcmcb>bb)Dt1B<1;NBTw=9!3BvL Value or else High < Value then -- # test-out - Out_Of_Range_Count := Out_Of_Range_Count + 1; -- # out-range - else - In_Range_Count := In_Range_Count + 1; -- # in-range - end if; - end Test; -end Check_G; diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/check_g.ads b/testsuite/tests/Generics/Mode_Variants_MCDC/src/check_g.ads deleted file mode 100644 index 6c18d8129..000000000 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/src/check_g.ads +++ /dev/null @@ -1,10 +0,0 @@ -generic - type T is new Float; - Low, High : T; -package Check_G is - procedure Test (Value : T); - pragma Inline (Test); - - In_Range_Count : Natural := 0; - Out_Of_Range_Count : Natural := 0; -end Check_G; diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.adb deleted file mode 100644 index 7bb9a328d..000000000 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.adb +++ /dev/null @@ -1,13 +0,0 @@ -package body Sensors is - - procedure Test (Value : Float; Unit : Temp_Unit) is - begin - if Unit = C then -- # check-test-c - N_Tests_C := N_Tests_C + 1; -- # check-do-c - RC.Test (Temp_C (Value)); -- # check-do-c - else - N_Tests_F := N_Tests_F + 1; -- # check-do-f - RF.Test (Temp_F (Value)); -- # check-do-f - end if; - end Test; -end Sensors; diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.ads b/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.ads deleted file mode 100644 index 1047d0237..000000000 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/src/sensors.ads +++ /dev/null @@ -1,15 +0,0 @@ -with Check_G; - -package Sensors is - type Temp_C is new Float range -273.15 .. Float'Last; - package RC is new Check_G (Temp_C, 0.0, 100.0); -- # i:RC - - type Temp_F is new Float range -459.67 .. Float'Last; - package RF is new Check_G (Temp_F, 32.0, 212.0);-- # i:RF - - type Temp_Unit is (C, F); - - procedure Test (Value : Float; Unit : Temp_Unit); - - N_Tests_C, N_Tests_F : Natural := 0; -end Sensors; diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cbfn.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cbfn.adb deleted file mode 100644 index d2ee1721e..000000000 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cbfn.adb +++ /dev/null @@ -1,54 +0,0 @@ -with Sensors, Support; use Sensors, Support; - --- CBFN : Invoking Both in and out of range for unit "C". None for unit "F". - -procedure Test_CBFN is -begin - -- C in range (!low !high => Out-False) - - Sensors.Test (37.0, C); - - -- C out of range (!low, high => Out-True) - - Sensors.Test (200.0, C); - - Assert (Sensors.N_Tests_C = 2); - Assert (Sensors.N_Tests_F = 0); - - Assert (RC.In_Range_Count = 1); - Assert (RC.Out_Of_Range_Count = 1); - Assert (RF.In_Range_Count = 0); - Assert (RF.Out_Of_Range_Count = 0); - -end Test_CBFN; - ---# sensors.adb --- /check-test-c/ s=>l+, dmu=>l! ## s=>0, dmu=>dF- --- /check-do-c/ l+ ## 0 --- /check-do-f/ l- ## s- - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - --- %cov: -S routine --- =/check-test-c/ s=>l+, dmu=>l! ## s=>0, dmu=>dF-@(sensors__test) --- =/check-do-f/ l- ## s-@(sensors__test) - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- /test-out/ ds=>l+, mu=>l! ## c!:"Low" --- /in-range/ l+ ## 0 --- /out-range/ l+ ## 0 - --- %cov: -S instance --- =/test-out/ l! ## s-@(i:RF), c!:"Low"@(i:RC) --- =/in-range/ l! ## s-@(i:RF) --- =/out-range/ l! ## s-@(i:RF) - --- %cov: -S routine %cargs: !-gnatn --- =/test-out/ l! ## s-@(sensors__rf__test), c!:"Low"@(sensors__rc__test) --- =/in-range/ l! ## s-@(sensors__rf__test) --- =/out-range/ l! ## s-@(sensors__rf__test) diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifn.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifn.adb deleted file mode 100644 index 610fa1cdc..000000000 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifn.adb +++ /dev/null @@ -1,47 +0,0 @@ -with Support, Sensors; use Support, Sensors; - -procedure Test_CIFN is -begin - -- C in range - - Sensors.Test (37.0, C); - - Assert (Sensors.N_Tests_C = 1); - Assert (Sensors.N_Tests_F = 0); - - Assert (RC.In_Range_Count = 1); - Assert (RC.Out_Of_Range_Count = 0); - Assert (RF.In_Range_Count = 0); - Assert (RF.Out_Of_Range_Count = 0); -end Test_CIFN; - ---# sensors.adb --- /check-test-c/ s=>l+, dmu=>l! ## s=>0, dmu=>dF- --- /check-do-c/ l+ ## 0 --- /check-do-f/ l- ## s- - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - --- %cov: -S routine --- =/check-test-c/ s=>l+, dmu=>l! ## s=>0, dmu=>dF-@(sensors__test) --- =/check-do-f/ l- ## s-@(sensors__test) - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- /test-out/ s=>l+, dmu=>l! ## s=>0, dmu=>dT- --- /in-range/ l+ ## 0 --- /out-range/ l- ## s- - --- %cov: -S instance --- =/test-out/ l! ## s-@(i:RF), dT-@(i:RC) --- =/in-range/ l! ## s-@(i:RF) --- =/out-range/ l- ## s-@(i:RF), s-@(i:RC) - --- %cov: -S routine %cargs: !-gnatn --- =/test-out/ l! ## s-@(sensors__rf__test), dT-@(sensors__rc__test) --- =/in-range/ l! ## s-@(sensors__rf__test) --- =/out-range/ l- ## s-@(sensors__rf__test), s-@(sensors__rc__test) diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifo.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifo.adb deleted file mode 100644 index 787f4cbdf..000000000 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cifo.adb +++ /dev/null @@ -1,55 +0,0 @@ -with Sensors, Support; use Sensors, Support; - -procedure Test_CIFO is -begin - -- C in range - - Sensors.Test (37.0, C); - - -- F out of range - - Sensors.Test (0.0, F); - - Assert (Sensors.N_Tests_C = 1); - Assert (Sensors.N_Tests_F = 1); - - Assert (RC.In_Range_Count = 1); - Assert (RC.Out_Of_Range_Count = 0); - Assert (RF.In_Range_Count = 0); - Assert (RF.Out_Of_Range_Count = 1); - -end Test_CIFO; - ---# sensors.adb --- /check-test-c/ l+ ## 0 --- /check-do-c/ l+ ## 0 --- /check-do-f/ l+ ## 0 - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - --- %cov: -S routine --- =/check-test-c/ l+ ## 0 --- =/check-do-f/ l+ ## 0 - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- defaults, for instances conslidated: --- /test-out/ l+, mu=>l! ## c!:"High" --- /in-range/ l+ ## 0 --- /out-range/ l+ ## 0 - --- %cov: -S instance --- =/test-out/ s=>l+, dmu=>l! ## dT-@(i:RC), dF-@(i:RF) --- =/in-range/ l! ## s-@(i:RF) --- =/out-range/ l! ## s-@(i:RC) - --- %cov: -S routine %cargs: !-gnatn --- =/test-out/ s=>l+, dmu=>l! ## dT-@(sensors__rc__test), dF-@(sensors__rf__test) --- =/in-range/ l! ## s-@(sensors__rf__test) --- =/out-range/ l! ## s-@(sensors__rc__test) - --- %cov: -S routine %cargs: -gnatn %cancel: diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfn.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfn.adb deleted file mode 100644 index 704413886..000000000 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfn.adb +++ /dev/null @@ -1,37 +0,0 @@ -with Sensors; use Sensors; -procedure Test_CNFN is -begin - null; -end Test_CNFN; - ---# sensors.adb --- /check-test-c/ l- ## s- --- /check-do-c/ l- ## s- --- /check-do-f/ l- ## s- - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - --- %cov: -S routine --- =/check-test-c/ l- ## s-@(sensors__test) --- =/check-do-c/ l- ## s-@(sensors__test) --- =/check-do-f/ l- ## s-@(sensors__test) - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- /test-out/ l- ## s- --- /in-range/ l- ## s- --- /out-range/ l- ## s- - --- %cov: -S instance --- =/test-out/ l- ## s-@(i:RF), s-@(i:RC) --- =/in-range/ l- ## s-@(i:RF), s-@(i:RC) --- =/out-range/ l- ## s-@(i:RF), s-@(i:RC) - --- %cov: -S routine %cargs: !-gnatn --- =/test-out/ l- ## s-@(sensors__rf__test), s-@(sensors__rc__test) --- =/in-range/ l- ## s-@(sensors__rf__test), s-@(sensors__rc__test) --- =/out-range/ l- ## s-@(sensors__rc__test), s-@(sensors__rf__test) diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfo.adb b/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfo.adb deleted file mode 100644 index c53fe94e0..000000000 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/src/test_cnfo.adb +++ /dev/null @@ -1,38 +0,0 @@ -with Sensors; use Sensors; -procedure Test_CNFO is -begin - -- F out of range - - Sensors.Test (0.0, F); -end Test_CNFO; - ---# sensors.adb --- /check-test-c/ s=>l+, dmu=>l! ## s=>0, dmu=>dT- --- /check-do-c/ l- ## s- --- /check-do-f/ l+ ## 0 - --- %cov: -S instance --- Not a generic body, so no possible instance tag. - --- %cov: -S routine --- =/check-test-c/ s=>l+, dmu=>l! ## s=>0, dmu=>dT-@(sensors__test) --- =/check-do-c/ l- ## s-@(sensors__test) - ---# sensors.ads --- No expectation for this unit. Reference is needed here, still, to --- get visibility on generic instantiations in this source. - ---# check_g.adb --- /test-out/ s=>l+, dmu=>l! ## s=>0, dmu=>dF- --- /in-range/ l- ## s- --- /out-range/ l+ ## 0 - --- %cov: -S instance --- =/test-out/ l! ## s-@(i:RC), dF-@(i:RF) --- =/in-range/ l- ## s-@(i:RF), s-@(i:RC) --- =/out-range/ l! ## s-@(i:RC) - --- %cov: -S routine %cargs: !-gnatn --- =/test-out/ l! ## s-@(sensors__rc__test), dF-@(sensors__rf__test) --- =/in-range/ l- ## s-@(sensors__rf__test), s-@(sensors__rc__test) --- =/out-range/ l! ## s-@(sensors__rc__test) diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/tc.txt b/testsuite/tests/Generics/Mode_Variants_MCDC/tc.txt deleted file mode 100644 index bf1644cb4..000000000 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/tc.txt +++ /dev/null @@ -1,100 +0,0 @@ -We consider a general program construction like -one sketched below: - - generic - package G is - procedure Test is - begin -- slocs below designated as - if For_I1 then -- "test_in_g" - stmt_1_here; -- "stmt1_in_g" - else - stmt_2_here; -- "stmt2_in_g" - end if; - end; - end; - - package Sensors is - package I1 is new G (For_I1); - package I2 is new G (For_I2); - - procedure Dispatch; - end; - - package body Sensors is - procedure Dispatch is - begin -- slocs below designated as - if Do_I1 then -- "test_in_dispatch" - I1.Test; -- "call1_in_dispatch" - else - I2.Test; -- "call2_in_dispatch" - end if; - end; - - -- The generated code for this body includes the code for - -- the generic instances, as two low level routines: - -- - -- sensors__i1__test and sensors__i2__test. - - end; - -For -S routine, special care needs to be observed regarding inlining. - -WITHOUT inlining, we have machine code like: - - sensors__i1__test: ## slocs referenced by machine instructions - if for_i1: -> test_in_g - insns for stmt_1 -> stmt1_in_g - else: - insns for stmt_2 -> stmt2_in_g - - sensors__i2__test: - if for_i1: -> test_in_g - insns for stmt_1 -> stmt1_in_g - else: - insns for stmt_2 -> stmt2_in_g - - sensors_dispatch - test i1: -> test_in_dispatch - call sensors_i1_test -> call1_in_dispatch - else: - call sensors_i2_test -> call2_in_dispatch - -WITH inlining, the same except for: - - sensors_dispatch - test i1: -> test_in_dispatch - insns for stmt_1 -> stmt1_in_g - insns for stmt_2 -> stmt2_in_g - [insns for arg setup] -> call1_in_dispatch - else: - insns for stmt_1 -> stmt1_in_g - insns for stmt_2 -> stmt2_in_g - [insns for arg setup] -> call2_in_dispatch - -Whether instructions for the call statements and for other parts of the -inlined-instanciated code remain in each branch depends on the generic source -code structure and on how much optimization is performed. In general, the call -and the pieces corresponding to the other instances might for example entirely -disappear when the call arguments are constant. In this particular testcase, -the generic source code is structured to make sure that insns for both cases -remain in each inlined copy. - -Note that in addition to having references to "g" slocs from -"sensors__dispatch", if all the calls are inlined, no code from the original -instance subpgrograms is executed at all any more. - -In expectations, we distinguish four different cases: - --- /stmt1_in_g/ ... (No separation tag, cflags irrelevant) - --- %cov: -S instance --- =/stmt1_in_g/ ... (Separation on instance, cflags irrelevant) - --- %cov: -S routine %cargs: -O1, -gnatn --- =/stmt1_in_g/ ... (Separation on routine name, with inlining) - --- %cov: -S routine %cargs: !-gnatn --- =/stmt1_in_g/ ... (Separation on routine name, without inlining) - -CB - testing for "C" temp unit, Both in range and out of range - diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/test.opt b/testsuite/tests/Generics/Mode_Variants_MCDC/test.opt deleted file mode 100644 index c6c004f52..000000000 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/test.opt +++ /dev/null @@ -1,3 +0,0 @@ -7.0.3 DEAD testing per-instance analysis of generics, implemented post 7.0.3 -src-traces XFAIL S628-011: src-traces and per-instance coverage of generics -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/Generics/Mode_Variants_MCDC/test.py b/testsuite/tests/Generics/Mode_Variants_MCDC/test.py deleted file mode 100644 index 9088d338c..000000000 --- a/testsuite/tests/Generics/Mode_Variants_MCDC/test.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -This is a complement to the existing tests for generics in the Qualif part of -the testsuite. These are grouped in the stmt coverage part and focus on the -distinction between the default mode and -S instance, assuming that the -combination circuits are orthogonal to the criteria. - -Here we mean to test -S routine as well, and take the opportunity to test with -a different criterion while we're at it. -""" - -from SCOV.tc import TestCase -from SCOV.tctl import CAT, CovControl -from SUITE.context import thistest - - -tc = TestCase(category=CAT.mcdc) - -tc.run() -tc.run(covcontrol=CovControl(covoptions="-S instance"), subdirhint="r_") - -# -S routine is intractable with inlining -if "-gnatn" not in thistest.suite_cargs_for("Ada"): - tc.run(covcontrol=CovControl(covoptions="-S routine"), subdirhint="r_") - -thistest.result() diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/src/test_v5_reset.adb b/testsuite/tests/Generics/Mode_Variants_STMT/src/test_v5_reset.adb deleted file mode 100644 index eaa198c01..000000000 --- a/testsuite/tests/Generics/Mode_Variants_STMT/src/test_v5_reset.adb +++ /dev/null @@ -1,29 +0,0 @@ -with V5; use V5; - -procedure Test_V5_Reset is - V : V5.Vector; -begin - V5.Apply (Op=>Reset, V=>V); -end; - ---# vectors.adb --- /apply_op/ l+ ## 0 --- /apply_reset/ l+ ## 0 --- /iterate/ l+ ## 0 --- /do_reset/ l+ ## 0 - --- /do_bump/ l- ## s- --- /apply_bump/ l- ## s- - --- %cov: -S instance --- =/do_bump/ l- ## s-@(i:V5) --- =/apply_bump/ l- ## s-@(i:V5) - --- %cov: -S routine --- =/apply_bump/ l- ## s-@(v5__apply) --- =/do_bump/ l- ## s-@(v5__do_bump) - --- -S instance needs visibility on ALIs where --- instances of interest are - ---# v5.ads diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/src/v5.ads b/testsuite/tests/Generics/Mode_Variants_STMT/src/v5.ads deleted file mode 100644 index bfdb37907..000000000 --- a/testsuite/tests/Generics/Mode_Variants_STMT/src/v5.ads +++ /dev/null @@ -1,2 +0,0 @@ -with Vectors; -package V5 is new Vectors (Size => 5); -- # i:V5 diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.adb b/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.adb deleted file mode 100644 index 4570bc363..000000000 --- a/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.adb +++ /dev/null @@ -1,30 +0,0 @@ -package body Vectors is - - function Do_Reset (I : Integer) return Integer is - begin - return 0; -- # do_reset - end; - - function Do_Bump (I : Integer) return Integer is - begin - return I + 1; -- # do_bump - end; - - type Operator is access function (X : Integer) return Integer; - - procedure Iterate_On (V : in out Vector; Op : Operator) is - begin - for I in V'Range loop -- # iterate - V(I) := Op (V (I)); -- # iterate - end loop; - end; - - procedure Apply (Op : Opkind; V : in out Vector) is - begin - case Op is -- # apply_op - when Reset => Iterate_On (V, Do_Reset'Access); -- # apply_reset - when Bump => Iterate_On (V, Do_Bump'Access); -- # apply_bump - end case; - end; - -end; diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.ads b/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.ads deleted file mode 100644 index fc2f29262..000000000 --- a/testsuite/tests/Generics/Mode_Variants_STMT/src/vectors.ads +++ /dev/null @@ -1,10 +0,0 @@ -generic - Size : Natural; -package Vectors is - - type Vector is array (1 .. Size) of Integer; - - type Opkind is (Reset, Bump); - - procedure Apply (Op : Opkind; V : in out Vector); -end; diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/test.opt b/testsuite/tests/Generics/Mode_Variants_STMT/test.opt deleted file mode 100644 index ebe705ffc..000000000 --- a/testsuite/tests/Generics/Mode_Variants_STMT/test.opt +++ /dev/null @@ -1 +0,0 @@ -src-traces XFAIL S628-011: src-traces and per-instance coverage of generics diff --git a/testsuite/tests/Generics/Mode_Variants_STMT/test.py b/testsuite/tests/Generics/Mode_Variants_STMT/test.py deleted file mode 100644 index 1d6930b7e..000000000 --- a/testsuite/tests/Generics/Mode_Variants_STMT/test.py +++ /dev/null @@ -1,16 +0,0 @@ -from SCOV.tc import TestCase -from SCOV.tctl import CAT, CovControl -from SUITE.context import thistest - - -tc = TestCase(category=CAT.stmt) - -tc.run() - -tc.run(covcontrol=CovControl(covoptions="-S instance"), subdirhint="i_") - -# -S routine is intractable with inlining -if "-gnatn" not in thistest.suite_cargs_for("Ada"): - tc.run(covcontrol=CovControl(covoptions="-S routine"), subdirhint="r_") - -thistest.result() diff --git a/testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.adb b/testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.adb deleted file mode 100644 index b0dc586ab..000000000 --- a/testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.adb +++ /dev/null @@ -1,6 +0,0 @@ -with Ada.Text_IO; - -procedure Generic_Hello is -begin - Ada.Text_IO.Put_Line ("Hello " & Who & "!"); -end Generic_Hello; diff --git a/testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.ads b/testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.ads deleted file mode 100644 index 4645e28d6..000000000 --- a/testsuite/tests/S619-014-tag-provider-mismatch/generic_hello.ads +++ /dev/null @@ -1,3 +0,0 @@ -generic - Who : String; -procedure Generic_Hello; diff --git a/testsuite/tests/S619-014-tag-provider-mismatch/main.adb b/testsuite/tests/S619-014-tag-provider-mismatch/main.adb deleted file mode 100644 index d832a4a2b..000000000 --- a/testsuite/tests/S619-014-tag-provider-mismatch/main.adb +++ /dev/null @@ -1,13 +0,0 @@ -with Generic_Hello; - -procedure Main is - procedure Hello_World is new Generic_Hello ("world"); - procedure Hello_There is new Generic_Hello ("there"); - - S : constant String := "hello"; -begin - Hello_World; - if S = "never-going-to-be-true" then - Hello_There; - end if; -end Main; diff --git a/testsuite/tests/S619-014-tag-provider-mismatch/test.py b/testsuite/tests/S619-014-tag-provider-mismatch/test.py deleted file mode 100644 index 196cb4f5d..000000000 --- a/testsuite/tests/S619-014-tag-provider-mismatch/test.py +++ /dev/null @@ -1,64 +0,0 @@ -""" -Check that "gnatcov coverage" complains when loading a checkpoint created with -a different tag provider, i.e. asking for inconsistent separate coverage. Also -check that the coverage report correctly disregards coverage data from the -loaded checkpoint. -""" - -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of, indent -from SUITE.gprutils import GPRswitches -from SUITE.tutils import gprfor, xcov - - -wd = Wdir("tmp_") - -# First, create a checkpoint using the default tag provider -ckpt = "c.ckpt" -build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(["main.adb"], srcdirs="..")), - covlevel="stmt+decision", - mains=["main"], - extra_coverage_args=["--save-checkpoint", ckpt], -) - -# Now try to load it while asking for the non-default tag provider. Don't pass -# the trace file, as we are interested only in checkpoint processing. -xcov( - [ - "coverage", - "-cstmt+decision", - "-axcov", - "-Sinstance", - "-C", - ckpt, - "--output-dir=.", - ], - out="consolidate.log", - tolerate_messages=".", -) - -expected = ( - "warning: -S is deprecated. This option will be removed in release 26." - "\nwarning: cannot merge coverage information from {} as it is separated" - " by default".format(ckpt) -) -actual = contents_of("consolidate.log").strip() -thistest.fail_if( - expected != actual, - 'Unexpected output for "gnatcov coverage". Expected:\n' - "{}\n" - "but got:\n" - "{}".format(indent(expected), indent(actual)), -) - -expected_cov = { - "main.adb.xcov": {}, - "generic_hello.adb.xcov": {}, -} -if thistest.options.trace_mode == "src": - expected_cov["generic_hello.ads.xcov"] = {} -check_xcov_reports(".", expected_cov, discard_empty=False) - -thistest.result() diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index aa940e234a18792299ef5860683d35edad4bc9e7..6eb1ddba3f37ff88210738fdeddcaba27e2c6188 100644 GIT binary patch delta 73 zcmaFD{e*jh4EsxVRz5C6=84LR#wHdF4D1XH48lNcWME{fYhbEtXrf?fU}a)yWnjd> Y0Tkx~Vg(ap6C)!tQzJu$jpezl0QWx(s{jB1 delta 73 zcmaFD{e*jh4EqaqZW#^>&WXy3#s&rq4D1XH48lNcWME{XYiOuzWT9YSVP$G&Wnjs` Y0Tky3Vg*BU12antBLfTbjpezl0RHC<4gdfE diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_2.trace b/testsuite/tests/U204-026-arch-mix/bin-main_2.trace index 0254a167642153a90384fb49b28cb9a8ac52bcf2..687e518a4d340ffcaec81da80f278afcd98342bc 100644 GIT binary patch literal 2580 zcmbuBFKkm$7{%{M#~!001u7~k-sr@{7GBFMZAZlfBo&a1WF&|sZ2U>a!k+{X6Nrk5 z3d96r0#PwBF;TIE3B<$%0#PwhftZ*fK};YfdF?spd*oVP(&YVi&iCiu@4lOr9^QNK zXm07<>a!Q`$1ViUeRVG5oJ-!^uZi(1ljV#XOWr4w-`l6_H(#&5eDkE@+(mlAxYDSV zYquv7zMlLlQKdQ;Rp-iaSdQl7#(Wfya$Qceuu^YCm0IIgqnZ$&(!ceG&ZNGcjJrB| z-5keX+T<_<=iRl@OH2;PO=HA2r{FKR+~{SA9FUjEs`t~=Psv%tNBkCb zt#8{H{dYY+v;F1zj4>Zaf0pyfT0HbTS^XBsA^mkvZ(2O+t+1Zr-8}YdgZr~VE|Ncc z+#|=-Ps!S^fid+k8z&{LCHno1_1Ty3Su3kM+h)`1AA^y!fN<}t_9I@PUS$5%kNQ38+K(giLq9Pc^->)?>(zU1 z^T&BwBWpbyzek-ue( ze(rnmV#P0-AMs1Zh=1(Gixt0Ye$21Vc`R~1U9$E+AnSYTk#%4EAZIy`f$7K}ah|%5 zTV#D-ZT1szKRebR*7J$1^YM!Dn%4)i^sf1_KYL!jo-z7sTR!lLm(TCd&;Q@L)yH}} z#^~pe{px$%^7MVO=H>TuV1DF3G)8`ZJ>R{2+aCM*zgRxx-y!S!_VfSY`B1<4;XhN! fqxBW3i+4Q!HU+=p4{KoE4}G%E`!QMHvsn6HW%`7~ literal 2612 zcmbuAFKkm$6vppJVUMli0TmS$Z*-z!4ed*z?SiNwnSi7uBbgv!gOC8>PXiSd6%!K^ z6%z==#Kc4eVqysuhzjJy1Oi!ss6b3iOiXb5&i9>1j^!mw-f!Red(XMA#m5gGJt?n$ z+{Eysr*#HONO>hYR4w(7RjQs^Ti+VP0GrrW*0Y`|p2WGqx znEA&>{{e2m|5ELxpP(rD0_2}U=Xs>M)Ds%}->}akeyWRo9`>yFGwj)K&-kah_#Z%L ze?w)d|HyF0a8_C7l>=unugK^nFza0bN3efr^tSp-JzX>JaJJn3>EV2K!3FT4;W4-d z{T$5mnkvirq`I)1T^|2%e*b_NZ4`@{N^6KLK-pr>G~7{&&HgPh~L~ zpW}JA!1Uh)hb~GCJE}{*uCnMoWzqY}qHimUz60jI4#55kpX4KFaQ=JHv(WcVyaVG; zrvIVZOZ=g-)brK&lj(n?_Tqo6EdC?oPp1EOwU_yQ!93cSkGr0JP z#|oJH*-%~l_hvtq{^5QP!Mtx1)Dz%5r&^!%^9RiRIDtRs^%G3pFH-VwK3OpP50$09 ziN+Hin|QW98~?v`%`g2Y_Steg#b^(&2EDDo- SS$HRFv54?600AS200IEnEf5d@ delta 80 zcmaFF@sUHs-On*3IloLHIU_YWyC6R^uY^HxqsR&-MyAbsnS>Y_nI>Ogb^(&2EDDo- dSvV)FvB-$CGcYiuq^2d7=9BWm5#`?GkAAo6TLakhym+LPTGFHSCFGMntjq%m0nNUvdf$;dK!8nX+KybU5ZE3im0 z0y);KE{-f9<4^!6kjKaj2aJr!JPbLe$#+>54OrmHaWIe#1R6hClP!&XMc|`Gk*`^k kr?H(=H`O&T)ipFxFf_0-v9vNUR?s#uure@!ISxhx0KF$HGynhq delta 317 zcmey&*Uc~D?&lbioL{DpoRONGU67xdSHd7TQN(4k03$mq69WSS(_|S&?TO2>L=5#3 zb26D2*nnan%m~DalLHu~CblU|c4xdexs1tdvLBPiWChUq0E)8uK)EbH_9$`?9O;`av77^WIra2$r3<%4bw|TmdVqYU4Z0mFsZ;Y zm+1uC?gV9wRdxpz;_Qk>!9qrpZrP6%AP6%5gA| z3CKCe_0|OW{0%^s`0gO_U z)fp8g_Gj@JLgd+i;%pOBv?seWUYuOUWH#B4Nn^4EkY2;|l96fhG-ekdc^gbBu*_xB z;GDdl#em6#bMi-)K%k5>t4kac$ZQk<5?}}7l+?7u(wq`bAQL16R>uqnj1Ya;Wk8}J zw=+yW!K$bYV!!}y^5Fs{kwjPi^Wycu0nUnD& z6C=yy-^?yR(t*W=nT3&QG9#8LfFd(kLE?8=B`3SEiA?^)>Q&Flz`(%B342-g=`s67vtoAY?<;oYmUnmf6Y1xGEe}B Yjm-26$`v$>42(<-Obv}Ex3PZ!0ER*?z5oCK delta 276 zcmX>j@J&F(-On*3IloLHIU_YWyC6R^uY^HxqKGzQ=|l$?5Fs{kwjPi^Wye^$nUnD& z6C=~)-^?yR(t*W=8N_2`6`4Gn zKqey;GcdyeBO_K(d}^71rZ7xyW>eG#F<=0j*+`~LzQUF%e?;+C#py2=CqZfjfY``P V&!AjE!^ptM#L&pVaB>X$2LO|5F0TLp diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt index b7419a00a61fd36b7bea9a9be40bb2dce621b8f0..aac41ce9e8206ad7ab77cf56d936baac2e6452dd 100644 GIT binary patch delta 743 zcmY*WJxc>Y5Y6oFc{!sJ<&2`BCx{v)cnCIP3Io9|pjc`Z{0x{BVw=)>GlIXu!ovTc zjejB7ij9S}&dhz}Zn(WS@AmD?+qswWL)kxU9h|hg_d)yWyxr+_uW#=PGu996PhdY5 zLD{bcXj|I{V{03B;8zM1h86(7l7*)#bcCT*Rmn6S>E$U_rp+svu##usc&RufBH4Uztpr1W9kr9dOdAmkisJFjyO#qp=O01ps=__jjUhv@3HV$F8%mvFlWSG`r!>&1VhFe<9RLjM*U8oC@ zRJph$iOHM@0lFq%Zj%fQV2u%XsO;LM%1oAux8!f7guufCbc3)uLRf?q>;bJX!w8*8 zEZ*kAJH)rPGe4qNf6Hac3lek$N-mcIO{j@q__Hrq5bR>bfz!-v8!qH;& z=h)!2l`9W#fBn|KGW71tNGf#)PVR@3xMJIWEcT)d^lr2z2oMPh84^$`7F9qkk?4&FjUstH(X)fPz=BK>gZAR0fT47vgor=}C`LWqBnT7M@|Xt0{0+D{3i=? z)?S$R`FT_BWJDAWi#n9Z2q=Zae-I(W8WEWzLRNdMjn*KpH!DSyi30P(#Nv4oO_Ejyk85lA?LlSD=WU?*QA7fnz&f8 zef1gk8nR{=rEcVBJx@2By6^hqu2XPy!>HR0X{>*!kD)MCG{WNa{r2@X&7cO(B7))> fPI?~H5#sEToN1U@`srr&sAkk3_!pLB7gt@ DrTGi{ delta 68 zcmdnYe27`Z-On*3IloLHIU_YWyC6R^uY^HxqKGzQ=|%@DMnmQj0_A6>_D87 QnwD6aQvzf$fP_E*0FGr36aWAK diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid index 4671951f78d8163cfaaf87a85ad4cff110f2760e..dbd583dd3301a3013ba96dcad92c64b3f889997e 100644 GIT binary patch delta 53 zcmX@ayqQ_V-On*3IloLHIU_YWyC6R^uY^HpqKGzQ=tc)CMn;y&)r>kk3_!pLB7gt@ DrTGi{ delta 68 zcmdnYe27`Z-On*3IloLHIU_YWyC6R^uY^HxqKGzQ=|%@DMnmQj0_A6>_D87 QnwD6aQvzf$fP_E*0FGr36aWAK diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid index fddcb8609e03de33443703b4a22193be70f2619c..5c9df2b2287438668f69de01e3bc78a8e34f2abc 100644 GIT binary patch delta 104 zcmey$@r*;n-On*3IloLHIU_YWyC6R^uY^HpqKGzQ=tKv7#?Xxg0Zfc6n-4MxF*34D izQXJRBqdoCbQu{LAOJ*zFf$MrWT!JQL4?61Obq~9nG#9> delta 86 zcmaFH@s&fw-On*3IloLHIU_YWyC6R^uY^HxqKGzQ=|l&8#?p-i0Zfccn-4MxF)}hu jzQXJRBqdoCCM&Y2inB8?Fr=iWC6?xt09g!-AOZ*gT51&Q diff --git a/tools/gnatcov/annotations-report.adb b/tools/gnatcov/annotations-report.adb index 03f2eacc7..a2907e1ee 100644 --- a/tools/gnatcov/annotations-report.adb +++ b/tools/gnatcov/annotations-report.adb @@ -21,13 +21,12 @@ with Ada.Containers.Vectors; with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Text_IO; use Ada.Text_IO; -with Calendar_Utils; use Calendar_Utils; -with Coverage; use Coverage; -with Coverage.Source; use Coverage.Source; -with Coverage.Tags; use Coverage.Tags; +with Calendar_Utils; use Calendar_Utils; +with Coverage; use Coverage; +with Coverage.Source; use Coverage.Source; with SC_Obligations; with Switches; -with Traces_Files; use Traces_Files; +with Traces_Files; use Traces_Files; package body Annotations.Report is @@ -440,11 +439,6 @@ package body Annotations.Report is (Output => Output.all, Text => Msg (First .. Msg'Last)); - if M.SCO /= No_SCO_Id and then M.Tag /= No_SC_Tag then - Put (Output.all, - " (from " & Tag_Provider.Tag_Name (M.Tag) & ")"); - end if; - New_Line (Output.all); Output_Annotations (Output.all, SCO_Annotations (M.SCO)); end Output_Message; @@ -656,11 +650,6 @@ package body Annotations.Report is (Output => Output.all, Text => Msg (First .. Msg'Last)); - if M.SCO /= No_SCO_Id and then M.Tag /= No_SC_Tag then - Put (Output.all, - " (from " & Tag_Provider.Tag_Name (M.Tag) & ")"); - end if; - New_Line (Output.all); if M.SCO /= No_SCO_Id then Output_Annotations (Output.all, SCO_Annotations (M.SCO)); diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index df0adf463..0dd05164a 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -28,7 +28,6 @@ with Calendar_Utils; with Coverage; with Coverage.Object; with Coverage.Source; use Coverage.Source; -with Coverage.Tags; with Instrument; with Outputs; use Outputs; with SS_Annotations; use SS_Annotations; @@ -629,7 +628,6 @@ package body Annotations is ------------------------ function Message_Annotation (M : Message) return String is - use Coverage, Coverage.Tags; begin if M.SCO /= No_SCO_Id then return SCO_Kind_Image (M.SCO) @@ -647,9 +645,6 @@ package body Annotations is and then Kind (M.SCO) = Condition then ")" else "") - & (if M.Tag = No_SC_Tag - then "" - else " (from " & Tag_Provider.Tag_Name (M.Tag) & ")") & " " & (+M.Msg); else return Image (M.Sloc, Unique_Name => True) & ": " & (+M.Msg); diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 1506bdd51..ff6f0adc2 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -39,7 +39,7 @@ with Traces_Source; use Traces_Source; package Checkpoints is - subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 17; + subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 18; -- For compatibility with previous Gnatcov versions, the checkpoint -- file format is versioned. -- @@ -61,6 +61,7 @@ package Checkpoints is -- 15 -- Increase size of Pragma_Id after addition of 255th pragma -- 16 -- Extend Scope_Entity to include the Start/End_Sloc of the scope -- 17 -- Add support for Fun_Call and Guarded Expression coverage + -- 18 -- Removed support for tags (separate coverage) -- -- Note that we always use the last version when creating a checkpoint. -- diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 5e3ca7226..90099f044 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -123,7 +123,6 @@ package Command_Line is Opt_Exec_Prefix, Opt_HW_Trigger_Traces, Opt_Input, - Opt_Separate, Opt_Output_Format, Opt_Trace_Source, Opt_Save_Checkpoint, @@ -894,14 +893,6 @@ package Command_Line is Commands => (Cmd_Convert => True, others => False), At_Most_Once => False, Internal => False), - Opt_Separate => Create - (Short_Name => "-S", - Pattern => "[TAG]", - Help => "Perform separate source coverage analysis.", - Commands => (Cmd_Coverage | Cmd_Instrument => True, - others => False), - At_Most_Once => False, - Internal => False), Opt_Output_Format => Create (Short_Name => "-f", Pattern => "[FORMAT]", diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 881576c48..af3c1ca5e 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -18,7 +18,6 @@ with Ada.Containers.Ordered_Maps; with Ada.Directories; -with Ada.Streams; use Ada.Streams; with Ada.Unchecked_Deallocation; with Interfaces; @@ -27,7 +26,6 @@ with GPR2.Build.Source; with GPR2.Project.View; 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; @@ -82,10 +80,6 @@ package body Coverage.Source is 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 @@ -131,80 +125,34 @@ package body Coverage.Source is 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."="); + Element_Type => Source_Coverage_Info); procedure Read (CLS : in out Checkpoint_Load_State; - Value : out RW_Source_Coverage_Info_Access); - -- Allocate a new SCI initialized from CLS + Value : out Source_Coverage_Info); + -- Read a SCI initialized from CLS procedure Write (CSS : in out Checkpoint_Save_State; - Value : RW_Source_Coverage_Info_Access); + Value : Source_Coverage_Info); -- 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, + Element_Type => Source_Coverage_Info, + Vectors => SCI_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, + Element_Type => Source_Coverage_Info, + Vectors => SCI_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 + SCI_Vector : SCI_Vectors.Vector; -- MC/DC evaluation stack @@ -238,7 +186,6 @@ package body Coverage.Source is 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 @@ -247,7 +194,6 @@ package body Coverage.Source is 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 @@ -255,7 +201,6 @@ package body Coverage.Source is 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 @@ -279,9 +224,9 @@ package body Coverage.Source is -- Basic_Block_Has_Code -- -------------------------- - function Basic_Block_Has_Code (SCO : SCO_Id; Tag : SC_Tag) return Boolean is + function Basic_Block_Has_Code (SCO : SCO_Id) return Boolean is begin - return Get_SCI (SCO, Tag).Basic_Block_Has_Code; + return SCI_Vector.Constant_Reference (SCO).Basic_Block_Has_Code; end Basic_Block_Has_Code; ------------------------ @@ -483,7 +428,6 @@ package body Coverage.Source is 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 @@ -515,28 +459,11 @@ package body Coverage.Source is --------------------- 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; + use SCI_Vectors; + CP_SCI_Vector : SCI_Vectors.Vector; + Relocs : Checkpoint_Relocations renames CLS.Relocations; 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. @@ -547,10 +474,6 @@ package body Coverage.Source is 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); @@ -613,11 +536,7 @@ package body Coverage.Source is end; end loop; - Merge_Checkpoint_SCI - (SCO, - Tag_Provider.Map_Tag (Relocs, Inserted_SCI.Tag), - Inserted_SCI, - Relocs); + Merge_Checkpoint_SCI (SCO, Inserted_SCI, Relocs); end Insert_Extra_Decision_SCI; begin if CLS.Static_Decision_Evaluations.Contains (CP_SCO) then @@ -630,28 +549,13 @@ package body Coverage.Source is 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; + declare + CP_SCI : Source_Coverage_Info renames + CP_SCI_Vector.Reference (SCO_Cur); + begin + Merge_Checkpoint_SCI (SCO, CP_SCI, Relocs); + end; 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; @@ -740,8 +644,7 @@ package body Coverage.Source is end if; if Region.Kind /= Condition then - SCI_Vector (Region.SCO).Append - (new Source_Coverage_Info'(Rep_SCI)); + SCI_Vector (Region.SCO) := Rep_SCI; end if; end loop; end loop; @@ -762,7 +665,7 @@ package body Coverage.Source is (SCO : SCO_Id; SCO_State : Line_State; Line_Info : Line_Info_Access; - SCI : RW_Source_Coverage_Info_Access; + SCI : in out Source_Coverage_Info; Level : Coverage_Level) with Pre => Level in MCDC | UC_MCDC | ATCC; -- Complete computation of Level coverage state if SCO is covered for @@ -776,8 +679,7 @@ package body Coverage.Source is procedure Report_Insufficiently_Instrumented (SCO : SCO_Id; Level : Coverage_Level; - Line_Info : Line_Info_Access; - SCI : RW_Source_Coverage_Info_Access); + Line_Info : Line_Info_Access); -- Appropriately report the case in which a SCO is not sufficiently -- instrumented to compute its coverage for MCDC or ATCC level. @@ -789,7 +691,7 @@ package body Coverage.Source is (SCO : SCO_Id; SCO_State : Line_State; Line_Info : Line_Info_Access; - SCI : RW_Source_Coverage_Info_Access; + SCI : in out Source_Coverage_Info; Level : Coverage_Level) is begin @@ -799,16 +701,15 @@ package body Coverage.Source is -- is covered for decision/ATC coverage. if not Decision_SCO_Instrumented_For_MCDC (SCO) then - Report_Insufficiently_Instrumented (SCO, Level, Line_Info, SCI); + Report_Insufficiently_Instrumented (SCO, Level, Line_Info); 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))); + then Compute_MCDC_State (SCO, SCI) + else Compute_ATCC_State (SCO, SCI))); end if; elsif SCO_State not in No_Code | Undetermined_Coverage then @@ -818,7 +719,7 @@ package body Coverage.Source is -- 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); + Update_Line_State (Line_Info, SCO, Level, Not_Covered); end if; end Compute_Condition_Level_Line_State; @@ -829,8 +730,7 @@ package body Coverage.Source is procedure Report_Insufficiently_Instrumented (SCO : SCO_Id; Level : Coverage_Level; - Line_Info : Line_Info_Access; - SCI : RW_Source_Coverage_Info_Access) + Line_Info : Line_Info_Access) is begin -- This decision was not instrumented for Level, so report only @@ -841,16 +741,14 @@ package body Coverage.Source is 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); + Update_Line_State (Line_Info, SCO, Level, Covered); Report_Coverage (SCO, - SCI.Tag, "was not instrumented for " & Image (Level), Undetermined_Cov); end Report_Insufficiently_Instrumented; @@ -900,471 +798,428 @@ package body Coverage.Source is SCOs_Of_Line : declare SCO_State : Line_State := No_Code; + SCI : Source_Coverage_Info renames + SCI_Vector.Reference (SCO); begin - -- Make sure we have at least one SCI for this SCO + if Kind (SCO) = Statement then - 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; + -- Statement coverage: line is covered if any associated + -- statement is executed. - -- Iterate over all SCIs for this SCO + if Ignore_SCO (SCO) then - for SCI of SCI_Vector.Element (SCO) loop - if Kind (SCO) = Statement then - -- Statement coverage: line is covered if any associated - -- statement is executed. + -- They are neither covered nor not-covered, and need not be + -- reported as bona fide statements excluded from coverage + -- analysis either (see below case). - 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; + null; - elsif Unit_Has_Code (SCO) - and then not Basic_Block_Has_Code (SCO, SCI.Tag) + elsif Unit_Has_Code (SCO) + and then not Basic_Block_Has_Code (SCO) + 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 - -- 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. + SCO_State := Undetermined_Coverage; + Report_Coverage + (SCO, + "was not instrumented", + Kind => Undetermined_Cov); - if not Stmt_SCO_Instrumented (SCO) - and then S_Kind (SCO) in Ada_Statement_Kind - then + elsif Report_If_Excluded (SCO) then + SCO_State := Not_Coverable; + Report_Exclusion (SCO, "has no object code"); + end if; - SCO_State := Undetermined_Coverage; - Report_Coverage - (SCO, - SCI.Tag, - "was not instrumented", - Kind => Undetermined_Cov); + 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. - elsif Report_If_Excluded (SCO) then - SCO_State := Not_Coverable; - Report_Exclusion (SCO, SCI.Tag, "has no object code"); + if not Multiple_Statements_Reported then + Multiple_Statements_Reported := True; + Report_Violation + (SCO, + Msg => "^multiple statements on line, unable to " + & "establish full statement coverage"); end if; + SCO_State := Partially_Covered; - elsif SCI.Executed then + 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; - elsif SCI.Line_Executed then - if Is_Multistatement_Line (Line_Info.all) then + else + SCO_State := Not_Covered; - -- 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. + -- Generate violation message on first line of SCO - 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; + if Line_Num = First_Sloc (SCO).L.Line then + Report_Violation (SCO, "not executed"); + end if; + end if; - 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. + Update_Line_State (Line_Info, SCO, Stmt, SCO_State); - SCI.Executed := True; - SCO_State := Covered; - end if; + 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. - else - SCO_State := Not_Covered; + if Decision_Requires_Assertion_Coverage (SCO) then - -- Generate violation message on first line of SCO + SCO_State := SCI.State (ATC); + Update_Line_State (Line_Info, SCO, ATC, SCO_State); - if Line_Num = First_Sloc (SCO).L.Line then - Report_Violation (SCO, SCI.Tag, "not executed"); - end if; + if Assertion_Condition_Coverage_Enabled then + SCO_State := SCI.State (ATCC); + Update_Line_State (Line_Info, SCO, ATCC, SCO_State); + end if; + else + if Enabled (Decision) then + SCO_State := SCI.State (Decision); + Update_Line_State (Line_Info, SCO, Decision, SCO_State); + end if; + + if MCDC_Coverage_Enabled then + SCO_State := SCI.State (MCDC_Level); + Update_Line_State (Line_Info, SCO, MCDC_Level, SCO_State); end if; + end if; - Update_Line_State (Line_Info, SCO, SCI.Tag, Stmt, SCO_State); + 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 that + -- the decision coverage information is also included in MC/DC + -- coverage. The same goes for ATC and ATCC information. - 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_Outcome (SCO) /= Unknown then - if Decision_Requires_Assertion_Coverage (SCO) then + -- Case of a compile time known decision exclude from + -- coverage analysis. + + if SCI.Evaluations.Length > 1 then - SCO_State := SCI.State (ATC); + -- Case of a compile time known decision that was + -- consolidated with several checkpoints in which the + -- decision had different static conditions, but kept the + -- same outcome anyway. + -- + -- In this case, we chose to report the violation, + -- because if you have a static decision in your code + -- that may change depending on the build context, then + -- you SHOULD get it covered + + SCO_State := Not_Covered; + Report_Violation + (SCO, + "outcome " + & To_Boolean (Decision_Outcome (SCO))'Image + & " never exercised"); Update_Line_State - (Line_Info, SCO, SCI.Tag, ATC, SCO_State); + (Line_Info, SCO, Decision, 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; + elsif Report_If_Excluded (SCO) then + SCO_State := Not_Coverable; - 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; + -- Note: we do not report the exclusion of this SCO, + -- because if it is in an IF statement, then the IF + -- statement could be covered by back propagation, and it + -- would be confusing to see a line marked + in annotated + -- sources in conjunction with a message mentioning an + -- uncoverable construct in the report output. 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)) + elsif SCI.Outcome_Taken = Both_Outcomes_Taken + or else + SCI.Known_Outcome_Taken = Both_Outcomes_Taken + then + -- Here for a decision whose both outcomes have been + -- exercised. + + SCO_State := Covered; + + elsif SCI.Outcome_Taken /= No_Outcome_Taken + or else + SCI.Known_Outcome_Taken /= No_Outcome_Taken then - -- Compute decision coverage state for this decision. Note - -- that the decision coverage information is also included - -- in MC/DC coverage. The same goes for ATC and ATCC - -- information. - - if Decision_Outcome (SCO) /= Unknown then - -- Case of a compile time known decision - -- exclude from - -- coverage analysis. - - if SCI.Evaluations.Length > 1 then - -- Case of a compile time known decision that was - -- consolidated with several checkpoints in which - -- the decision had different static conditions, but - -- kept the same outcome anyway. - - -- In this case, we chose to report the violation, - -- because if you have a static decision in your code - -- that may change depending on the build context, - -- then you SHOULD get it covered + -- Assertion coverage + if Decision_Requires_Assertion_Coverage (SCO) then + -- Contract coverage level "Assertion True Coverage" + + -- Assertions are never supposed to be evaluated to + -- False. Therefore once they have been exercised and + -- found to be True, they are covered. + + if SCI.Outcome_Taken (True) + or else SCI.Known_Outcome_Taken (True) + then + SCO_State := Covered; + else SCO_State := Not_Covered; Report_Violation - (SCO, - SCI.Tag, - "outcome " - & To_Boolean (Decision_Outcome (SCO))'Image - & " never exercised"); - Update_Line_State - (Line_Info, SCO, SCI.Tag, Decision, SCO_State); - - elsif Report_If_Excluded (SCO) then - SCO_State := Not_Coverable; - - -- Note: we do not report the exclusion of this SCO, - -- because if it is in an IF statement, then the IF - -- statement could be covered by back propagation, and - -- it would be confusing to see a line marked + in - -- annotated sources in conjunction with a message - -- mentioning an uncoverable construct in the - -- report output. + (SCO, "outcome TRUE never exercised"); end if; - elsif SCI.Outcome_Taken = Both_Outcomes_Taken - or else - SCI.Known_Outcome_Taken = Both_Outcomes_Taken - then - -- Here for a decision whose both outcomes have been - -- exercised. + else + -- Here if at least one outcome has been exercised, + -- determined either by conditional branch instructions + -- (Outcome_Taken) or dominance (Known_Outcome_Taken). - SCO_State := Covered; + SCO_State := Partially_Covered; - elsif SCI.Outcome_Taken /= No_Outcome_Taken - or else - SCI.Known_Outcome_Taken /= No_Outcome_Taken - then - -- Assertion coverage + declare + Missing_Outcome : Tristate := Unknown; + begin + -- Indicate which outcome has never been taken: if + -- FALSE has been taken then this is outcome TRUE, + -- else FALSE. - if Decision_Requires_Assertion_Coverage (SCO) then - -- Contract coverage level "Assertion True - -- Coverage" + if SCI.Known_Outcome_Taken (False) + /= SCI.Known_Outcome_Taken (True) + then + Missing_Outcome := + To_Tristate (SCI.Known_Outcome_Taken (False)); - -- Assertions are never supposed to be evaluated - -- to False. Therefore once they have been - -- exercised and found to be True, they are - -- covered. + elsif not Degraded_Origins (SCO) then + Missing_Outcome := + To_Tristate (SCI.Outcome_Taken (False)); + end if; + + if Missing_Outcome = Unknown then + Report_Violation + (SCO, "not exercised in both directions"); - if SCI.Outcome_Taken (True) - or else SCI.Known_Outcome_Taken (True) - then - SCO_State := Covered; else - SCO_State := Not_Covered; Report_Violation (SCO, - SCI.Tag, - "outcome TRUE never exercised"); + "outcome " + & Missing_Outcome'Img & " never exercised"); end if; + end; + end if; - else - -- Here if at least one outcome has been exercised, - -- determined either by conditional branch - -- instructions (Outcome_Taken) or dominance - -- (Known_Outcome_Taken). - - SCO_State := Partially_Covered; - - declare - Missing_Outcome : Tristate := Unknown; - begin - -- Indicate which outcome has never been taken: if - -- FALSE has been taken then this is outcome TRUE, - -- else FALSE. - - if SCI.Known_Outcome_Taken (False) - /= SCI.Known_Outcome_Taken (True) - then - Missing_Outcome := - To_Tristate (SCI.Known_Outcome_Taken (False)); - - elsif not Degraded_Origins (SCO) then - Missing_Outcome := - To_Tristate (SCI.Outcome_Taken (False)); - end if; + elsif Enclosing_Statement (SCO) = No_SCO_Id + or else (Basic_Block_Has_Code (Enclosing_Statement (SCO)) + and then Stmt_SCO_Instrumented + (Enclosing_Statement (SCO))) + then + -- Similar to the above for statement coverage: a decision + -- that cannot ever be executed is reported as No_Code, not + -- Not_Covered. Note: the enclosing statement may be covered + -- even though the decision has never been evaluated (case + -- e.g. of an exception being raised before any outcome is + -- reached, or of a condition for which we fail to identify + -- the corresponding conditional branch instruction). We + -- report the coverage failure for the decision in that case + -- only; if the statement was not executed, we report only + -- the statement failure. If there is no enclosing + -- statement, or there is an ignored SCO (e.g. case of a + -- pragma that generates freestanding decisions) then we + -- always report the coverage status. - if Missing_Outcome = Unknown then - Report_Violation - (SCO, SCI.Tag, - "not exercised in both directions"); + declare + S_SCO : constant SCO_Id := Enclosing_Statement (SCO); + begin + SCO_State := Not_Covered; + if S_SCO = No_SCO_Id + or else SCI_Vector (S_SCO).Executed + or else SCI_Vector (S_SCO).Line_Executed + or else Ignore_SCO (S_SCO) + then + -- Decision_SCO_Instrumented (SCO) is False iff the + -- unit was instrumented, but not that particular + -- decision. + if not Decision_SCO_Instrumented (SCO) then + SCO_State := Undetermined_Coverage; + Report_Coverage + (SCO, + "was not instrumented for decision coverage", + Kind => Undetermined_Cov); + + -- If the decision has not conditional branches at + -- all, mark it as uncoverable and report it. We + -- should already have leveraged back-propagation, at + -- this point, so a decision with no outcomes taken is + -- either never evaluated, or has no branches to track + -- the evaluation. + + elsif not Decision_Has_Influence (SCO) then + if Report_If_Excluded (SCO) then + SCO_State := Not_Coverable; + Report_Exclusion + (SCO, Msg => "has no object code"); else - Report_Violation - (SCO, - SCI.Tag, - "outcome " - & Missing_Outcome'Img & " never exercised"); + -- Mark the SCO as no code if not reporting it, + -- to avoid having a violation in the reports. + + SCO_State := No_Code; end if; - end; + else + Report_Violation (SCO, "never evaluated"); + end if; end if; + end; + end if; - elsif Enclosing_Statement (SCO) = No_SCO_Id - or else (Basic_Block_Has_Code - (Enclosing_Statement (SCO), SCI.Tag) - and then Stmt_SCO_Instrumented - (Enclosing_Statement (SCO))) - then - -- Similar to the above for statement coverage: a - -- decision that cannot ever be executed is reported - -- as No_Code, not Not_Covered. Note: the enclosing - -- statement may be covered even though the decision - -- has never been evaluated (case e.g. of an exception - -- being raised before any outcome is reached, or - -- of a condition for which we fail to identify the - -- corresponding conditional branch instruction). We - -- report the coverage failure for the decision in that - -- case only; if the statement was not executed, we - -- report only the statement failure. If there is no - -- enclosing statement, or there is an ignored SCO - -- (e.g. case of a pragma that generates freestanding - -- decisions) then we always report the coverage status. - declare - S_SCO : constant SCO_Id := Enclosing_Statement (SCO); - S_SCI : constant Source_Coverage_Info_Access := - (if S_SCO = No_SCO_Id - then null - else Get_SCI (S_SCO, SCI.Tag)); - begin - SCO_State := Not_Covered; - if S_SCI = null - or else S_SCI.Executed - or else S_SCI.Line_Executed - or else Ignore_SCO (S_SCO) - then + -- Update the state of the line for all enabled source coverage + -- levels. - -- Decision_SCO_Instrumented (SCO) is False iff the - -- unit was instrumented, but not that particular - -- decision. - - if not Decision_SCO_Instrumented (SCO) then - SCO_State := Undetermined_Coverage; - Report_Coverage - (SCO, - SCI.Tag, - "was not instrumented for decision coverage", - Kind => Undetermined_Cov); - - -- If the decision has not conditional branches at - -- all, mark it as uncoverable and report it. We - -- should already have leveraged back-propagation, - -- at this point, so a decision with no outcomes - -- taken is either never evaluated, or has no - -- branches to track the evaluation. - - elsif not Decision_Has_Influence (SCO) then - if Report_If_Excluded (SCO) then - SCO_State := Not_Coverable; - Report_Exclusion - (SCO, SCI.Tag, Msg => "has no object code"); - else - -- Mark the SCO as no code if not reporting - -- it, to avoid having a violation in the - -- reports. - - SCO_State := No_Code; - end if; - else - Report_Violation - (SCO, SCI.Tag, "never evaluated"); - end if; - end if; - end; - end if; + if Decision_Requires_Assertion_Coverage (SCO) then - -- Update the state of the line for all enabled source - -- coverage levels. + -- If the SCO is in an assertion, update its state for the + -- relevant assertion coverage levels... - if Decision_Requires_Assertion_Coverage (SCO) then - -- If the SCO is in an assertion, update its state for - -- the relevant assertion coverage levels... + Update_Line_State (Line_Info, SCO, ATC, SCO_State); - Update_Line_State - (Line_Info, SCO, SCI.Tag, ATC, SCO_State); + if Enabled (ATCC) then + Compute_Condition_Level_Line_State + (SCO, SCO_State, Line_Info, SCI, ATCC); + end if; - if Enabled (ATCC) then - Compute_Condition_Level_Line_State - (SCO, SCO_State, Line_Info, SCI, ATCC); - end if; + elsif Decision_Requires_Coverage (SCO) then - elsif Decision_Requires_Coverage (SCO) then - -- ...otherwise update the SCO state for the regular - -- source coverage levels. + -- ...otherwise update the SCO state for the regular source + -- coverage levels. - -- Update the SCO state for decision level + -- Update the SCO state for decision level - Update_Line_State - (Line_Info, SCO, SCI.Tag, Decision, SCO_State); + Update_Line_State (Line_Info, SCO, Decision, SCO_State); - -- Compute and update the SCO state for MCDC level + -- Compute and update the SCO state for MCDC level - if MCDC_Coverage_Enabled - and then not Decision_Requires_Assertion_Coverage (SCO) - then - Compute_Condition_Level_Line_State - (SCO, SCO_State, Line_Info, SCI, MCDC_Level); - end if; + if MCDC_Coverage_Enabled + and then not Decision_Requires_Assertion_Coverage (SCO) + then + Compute_Condition_Level_Line_State + (SCO, SCO_State, Line_Info, SCI, MCDC_Level); end if; + end if; - -- For fun_call coverage, only compute the SCO state on the - -- first line, and re-use the SCI cache to set the line state - -- on subprograms or calls spanning multiple lines. + -- For fun_call coverage, only compute the SCO state on the first + -- line, and re-use the SCI cache to set the line state on + -- subprograms or calls spanning multiple lines. - elsif Kind (SCO) in Fun_Call_SCO_Kind - and then Enabled (Fun_Call) - and then First_Sloc (SCO).L.Line = Line_Num - then - if not Fun_Call_SCO_Instrumented (SCO) then - SCO_State := Undetermined_Coverage; - Report_Coverage - (SCO, - SCI.Tag, - "was not instrumented", - Kind => Undetermined_Cov); + elsif Kind (SCO) in Fun_Call_SCO_Kind + and then Enabled (Fun_Call) + and then First_Sloc (SCO).L.Line = Line_Num + then + if not Fun_Call_SCO_Instrumented (SCO) then + SCO_State := Undetermined_Coverage; + Report_Coverage + (SCO, + "was not instrumented", + Kind => Undetermined_Cov); - -- For call statements, we only need to rely on the state - -- of the enclosing statement. + -- For call statements, we only need to rely on the state of + -- the enclosing statement. - elsif Is_Call_Stmt (SCO) then - declare - S_SCO : constant SCO_Id := Enclosing_Statement (SCO); - S_SCI : constant Source_Coverage_Info_Access := - (if S_SCO = No_SCO_Id - then null - else Get_SCI (S_SCO, SCI.Tag)); - begin - SCO_State := - (if S_SCI /= null and then S_SCI.Executed - then Covered - else Not_Covered); - end; - else + elsif Is_Call_Stmt (SCO) then + declare + S_SCO : constant SCO_Id := Enclosing_Statement (SCO); + begin SCO_State := - (if SCI.Fun_Call_Executed + (if S_SCO /= No_SCO_Id + and then SCI_Vector (S_SCO).Executed then Covered else Not_Covered); - end if; + end; + else + SCO_State := + (if SCI.Fun_Call_Executed + then Covered + else Not_Covered); + end if; - if SCO_State = Not_Covered then - Report_Violation (SCO, SCI.Tag, "not executed"); - end if; + if SCO_State = Not_Covered then + Report_Violation (SCO, "not executed"); + end if; - Update_Line_State - (Line_Info, SCO, SCI.Tag, Fun_Call, SCO_State); + Update_Line_State (Line_Info, SCO, Fun_Call, SCO_State); - elsif Kind (SCO) in Fun_Call_SCO_Kind - and then Enabled (Fun_Call) - then - SCO_State := SCI.State (Fun_Call); - Update_Line_State - (Line_Info, SCO, SCI.Tag, Fun_Call, SCO_State); - elsif Kind (SCO) = Guarded_Expr - and then Enabled (GExpr) - then - if not GExpr_SCO_Instrumented (SCO) then - SCO_State := Undetermined_Coverage; - Report_Coverage - (SCO, - SCI.Tag, - "was not instrumented", - Kind => Undetermined_Cov); - elsif SCI.GExpr_Executed then - SCO_State := Covered; - else - SCO_State := Not_Covered; + elsif Kind (SCO) in Fun_Call_SCO_Kind + and then Enabled (Fun_Call) + then + SCO_State := SCI.State (Fun_Call); + Update_Line_State (Line_Info, SCO, Fun_Call, SCO_State); + elsif Kind (SCO) = Guarded_Expr + and then Enabled (GExpr) + then + if not GExpr_SCO_Instrumented (SCO) then + SCO_State := Undetermined_Coverage; + Report_Coverage + (SCO, + "was not instrumented", + Kind => Undetermined_Cov); + elsif SCI.GExpr_Executed then + SCO_State := Covered; + else + SCO_State := Not_Covered; - -- Report a violation on the first line of the SCO to - -- avoid duplicating violations in the report. + -- Report a violation on the first line of the SCO to avoid + -- duplicating violations in the report. - if Line_Num = First_Sloc (SCO).L.Line then - Report_Violation (SCO, SCI.Tag, "not executed"); - end if; + if Line_Num = First_Sloc (SCO).L.Line then + Report_Violation (SCO, "not executed"); end if; - - Update_Line_State - (Line_Info, SCO, SCI.Tag, GExpr, SCO_State); end if; - end loop; + + Update_Line_State (Line_Info, SCO, GExpr, SCO_State); + end if; end SCOs_Of_Line; <> null; @@ -1522,11 +1377,10 @@ package body Coverage.Source is if not Indep (J) then Update_State (SCO_State, - Condition (SCO, J), SCI.Tag, + Condition (SCO, J), MCDC_Level, Not_Covered); Report_Violation (SCO => Condition (SCO, J), - Tag => SCI.Tag, Msg => "has no independent influence pair, MC/DC not achieved"); if (Switches.Show_MCDC_Vectors @@ -1548,7 +1402,6 @@ package body Coverage.Source is -- SCO is a condition. Report_Coverage (SCO => Condition (SCO, J), - Tag => SCI.Tag, Msg => Emit_Evaluation_Vector_Message, Kind => Info); end if; @@ -1556,7 +1409,7 @@ package body Coverage.Source is else Update_State (SCO_State, - Condition (SCO, J), SCI.Tag, + Condition (SCO, J), MCDC_Level, Covered); end if; end loop; @@ -1647,10 +1500,9 @@ package body Coverage.Source is for I in Condition_Evaluated_Array'Range loop if not Condition_Evaluated (I) then Update_State - (SCO_State, Condition (SCO, I), SCI.Tag, ATCC, Not_Covered); + (SCO_State, Condition (SCO, I), ATCC, Not_Covered); Report_Violation (SCO => Condition (SCO, I), - Tag => SCI.Tag, Msg => "was never evaluated during an evaluation of the " & "decision to True, ATCC not achieved"); @@ -1662,13 +1514,11 @@ package body Coverage.Source is -- violation of the decision. Report_Coverage (SCO => Condition (SCO, I), - Tag => SCI.Tag, Msg => Emit_Evaluation_Vector_Message, Kind => Info); end if; else - Update_State - (SCO_State, Condition (SCO, I), SCI.Tag, ATCC, Covered); + Update_State (SCO_State, Condition (SCO, I), ATCC, Covered); end if; end loop; @@ -1696,17 +1546,16 @@ package body Coverage.Source is Exe : Exe_File_Acc renames Subp_Info.Exec; PC : Pc_Type; Insn_Len : Natural; - Tag : SC_Tag; procedure Discharge_SCO (SCO : SCO_Id; - Tsloc : Tagged_Sloc; + Sloc : Source_Location; Empty_Range : Boolean; Multistatement_Line : Boolean); -- Discharge the coverage obligation denoted by SCO using the current - -- execution trace for an instruction at PC, with the given tagged - -- sloc. Empty_Range is True if the sloc for PC that is associated with - -- SCO has an empty PC range. + -- execution trace for an instruction at PC, with the given sloc. + -- Empty_Range is True if the sloc for PC that is associated with SCO + -- has an empty PC range. ------------------- -- Discharge_SCO -- @@ -1714,7 +1563,7 @@ package body Coverage.Source is procedure Discharge_SCO (SCO : SCO_Id; - Tsloc : Tagged_Sloc; + Sloc : Source_Location; Empty_Range : Boolean; Multistatement_Line : Boolean) is @@ -1724,51 +1573,11 @@ package body Coverage.Source is Dom_SCO : SCO_Id; Dom_Val : Boolean; - Precise : constant Boolean := Tsloc.Sloc.L.Column /= 0; + Precise : constant Boolean := Sloc.L.Column /= 0; Line_Executed : Boolean; -- Set True if we are discharging from a trace with imprecise sloc -- that has line information only (column unknown). - - Tag_Suffix : constant String := - (if Tag = No_SC_Tag - then "" - else ", tag=" & Tag_Provider.Tag_Name (Tag)); - -- Suffix identifying tag for sloc in debug message - - procedure Set_Executed (SCI : in out Source_Coverage_Info); - -- Set Executed (if Line_Executed is False) or Line_Executed (if it - -- is True) to True. - - procedure Set_Known_Outcome_Taken (SCI : in out Source_Coverage_Info); - -- Set SCI.Known_Outcome_Taken (Dom_Val) to True - - ------------------ - -- Set_Executed -- - ------------------ - - procedure Set_Executed (SCI : in out Source_Coverage_Info) is - begin - if Line_Executed then - SCI.Line_Executed := True; - else - SCI.Executed := True; - end if; - end Set_Executed; - - ----------------------------- - -- Set_Known_Outcome_Taken -- - ----------------------------- - - procedure Set_Known_Outcome_Taken - (SCI : in out Source_Coverage_Info) - is - begin - SCI.Known_Outcome_Taken (Dom_Val) := True; - end Set_Known_Outcome_Taken; - - -- Start of processing for Discharge_SCO - begin -- Find enclosing statement SCO (if any) and mark it as executed @@ -1787,12 +1596,12 @@ package body Coverage.Source is S_SCO_First : constant Source_Location := First_Sloc (S_SCO); S_SCO_Last : constant Source_Location := Last_Sloc (S_SCO); - Cur_SCI : constant Source_Coverage_Info_Access := - Get_SCI (S_SCO, Tag); + Cur_SCI : Source_Coverage_Info renames + SCI_Vector.Constant_Reference (S_SCO); begin Line_Executed := not Precise - and then Tsloc.Sloc.Source_File = S_SCO_First.Source_File - and then Tsloc.Sloc.L.Line + and then Sloc.Source_File = S_SCO_First.Source_File + and then Sloc.L.Line in S_SCO_First.L.Line .. S_SCO_Last.L.Line; exit when Cur_SCI.Executed @@ -1813,14 +1622,23 @@ package body Coverage.Source is Report ((if Line_Executed then "line " else "") - & "executed" & Tag_Suffix + & "executed" & (if Propagating then " (propagating)" else ""), SCO => S_SCO, Exe => Exe, PC => PC, Kind => Notice); - Update_SCI (S_SCO, Tag, Set_Executed'Access); + declare + SCI : Source_Coverage_Info renames + SCI_Vector.Reference (S_SCO); + begin + if Line_Executed then + SCI.Line_Executed := True; + else + SCI.Executed := True; + end if; + end; end if; exit when not Propagating and No_Propagation; @@ -1833,17 +1651,17 @@ package body Coverage.Source is Dominant (S_SCO, Dom_SCO, Dom_Val); if Dom_SCO /= No_SCO_Id and then Kind (Dom_SCO) = Decision - and then not Get_SCI (Dom_SCO, Tag).Known_Outcome_Taken (Dom_Val) + and then not SCI_Vector (Dom_SCO).Known_Outcome_Taken (Dom_Val) then Report - ("outcome " & Dom_Val'Img & " taken" & Tag_Suffix - & " (propagating)", + ("outcome " & Dom_Val'Img & " taken (propagating)", SCO => Dom_SCO, Exe => Exe, PC => PC, Kind => Notice); - Update_SCI (Dom_SCO, Tag, Set_Known_Outcome_Taken'Access); + SCI_Vector.Reference (Dom_SCO).Known_Outcome_Taken (Dom_Val) := + True; end if; S_SCO := Enclosing_Statement (Dom_SCO); @@ -1880,16 +1698,14 @@ package body Coverage.Source is procedure Edge_Taken (E : Edge_Kind) is CBE : constant Cond_Edge_Info := CBI.Edges (E); - procedure Set_Outcome_Taken - (SCI : in out Source_Coverage_Info); + procedure Set_Outcome_Taken (SCI : in out Source_Coverage_Info); -- Mark as taken the decision outcome corresponding to CBE ----------------------- -- Set_Outcome_Taken -- ----------------------- - procedure Set_Outcome_Taken - (SCI : in out Source_Coverage_Info) + procedure Set_Outcome_Taken (SCI : in out Source_Coverage_Info) is use Condition_Evaluation_Vectors; @@ -1971,7 +1787,6 @@ package body Coverage.Source is if Eval.Values /= Inferred_Values then Report_Violation (D_SCO, - SCI.Tag, "^inferred values mismatch: expected " & Image (Inferred_Values) & ", got " & Image (Eval.Values)); @@ -2044,8 +1859,7 @@ package body Coverage.Source is -- evaluation. if CBE.Dest_Kind = Outcome then - Update_SCI - (D_SCO, Tag, Set_Outcome_Taken'Access); + Set_Outcome_Taken (SCI_Vector.Reference (D_SCO)); end if; end if; end Edge_Taken; @@ -2106,10 +1920,6 @@ package body Coverage.Source is -- Start of processing for Compute_Source_Coverage begin - -- Set current subprogram for separated source coverage analysis - - Tag_Provider.Enter_Routine (Subp_Info); - -- Iterate over trace for this routine PC := T.First + Subp_Info.Offset; @@ -2125,8 +1935,13 @@ package body Coverage.Source is -- instruction. declare - SL : constant Tagged_Slocs := - Tag_Provider.Get_Slocs_And_Tags (PC); + Routine : constant Address_Info_Acc := + Get_Address_Info + (Exec => Subp_Info.Exec.all, + Kind => Subprogram_Addresses, + PC => Subp_Info.Insns.First); + SL : constant Source_Locations := + Get_Slocs (Routine.Lines, PC); SCOs : access SCO_Id_Array; Single_SCO : aliased SCO_Id_Array := (0 => No_SCO_Id); @@ -2136,15 +1951,13 @@ package body Coverage.Source is begin for J in SL'Range loop - Tag := SL (J).Tag; - Multistatement_Line := False; Single_SCO (Single_SCO'First) := No_SCO_Id; SCOs := null; - if SL (J).Sloc.L.Column = 0 then + if SL (J).L.Column = 0 then declare - LI : constant Line_Info_Access := Get_Line (SL (J).Sloc); + LI : constant Line_Info_Access := Get_Line (SL (J)); begin if LI /= null and then LI.SCOs /= null then SCOs := LI.SCOs.all'Access; @@ -2162,7 +1975,7 @@ package body Coverage.Source is -- If we have column-accurate sloc information, then there -- is at most a single SCO to discharge. - Single_SCO (Single_SCO'First) := Sloc_To_SCO (SL (J).Sloc); + Single_SCO (Single_SCO'First) := Sloc_To_SCO (SL (J)); end if; if SCOs = null then @@ -2182,7 +1995,7 @@ package body Coverage.Source is Discharge_SCO (SCO, Empty_Range => J > SL'First, - Tsloc => SL (J), + Sloc => SL (J), Multistatement_Line => Multistatement_Line); end if; end loop; @@ -2214,9 +2027,6 @@ package body Coverage.Source is -- -- This configuration allows us to conclude that the "not V" outcome of -- SCO#2 is covered: set Known_Outcome_Taken accordingly. - -- - -- TODO??? If separate instance coverage is maintained eventually - -- (#258), deal with SCI tags. ----------------- -- Process_SCO -- @@ -2224,7 +2034,6 @@ package body Coverage.Source is procedure Process_SCO (SCO : SCO_Id) is - SCI : Source_Coverage_Info_Access; Dom_SCO : SCO_Id; Dom_Val : Boolean; begin @@ -2238,51 +2047,42 @@ package body Coverage.Source is -- Also skip it if it has no associated SCI, or if this is not a -- coverable SCO. - SCI := Get_SCI (SCO, No_SC_Tag); - if SCI = null - or else not SCI.Basic_Block_Has_Code - or else SCI.Executed - then - return; - end if; + declare + SCI : Source_Coverage_Info renames + SCI_Vector.Constant_Reference (SCO); + begin + if not SCI.Basic_Block_Has_Code or else SCI.Executed then + return; + end if; + end; Dominant (SCO, Dom_SCO, Dom_Val); if Dom_SCO = No_SCO_Id or else Kind (Dom_SCO) /= Decision then return; end if; - -- We deliberately ignore handling of separate instances coverage - -- (with a Tag that is not No_SCO_Tag), to avoid complexifying the - -- implementation. - - SCI := Get_SCI (Dom_SCO, No_SC_Tag); - if SCI /= null then + declare + SCI : Source_Coverage_Info renames + SCI_Vector.Constant_Reference (Dom_SCO); + begin if SCI.Outcome_Taken (True) or else SCI.Outcome_Taken (False) then declare - procedure Set_Known_Outcome_Taken - (SCI : in out Source_Coverage_Info); - - ----------------------------- - -- Set_Known_Outcome_Taken -- - ----------------------------- - - procedure Set_Known_Outcome_Taken - (SCI : in out Source_Coverage_Info) is - begin - SCI.Known_Outcome_Taken (not Dom_Val) := True; - end Set_Known_Outcome_Taken; - + SCI : Source_Coverage_Info renames + SCI_Vector.Reference (Dom_SCO); begin - Update_SCI - (Dom_SCO, No_SC_Tag, Set_Known_Outcome_Taken'Access); + SCI.Known_Outcome_Taken (not Dom_Val) := True; end; end if; - end if; + end; end Process_SCO; begin SC_Obligations.Iterate (Process_SCO'Access); end Refine_Source_Coverage; + ----------------------------- + -- Compute_Source_Coverage -- + ----------------------------- + procedure Compute_Source_Coverage (Filename : String; Fingerprint : SC_Obligations.Fingerprint_Type; @@ -2310,11 +2110,10 @@ package body Coverage.Source is when File_Based_Language => +CU_Name.Filename); -- Helper to refer to the instrumented unit in an error message - procedure Update_SCI_Wrapper + 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 + -- Execute Process on the SCI for the given SCO ------------------ -- Set_Executed -- @@ -2344,20 +2143,19 @@ package body Coverage.Source is when GPR2.S_Separate => "separate"); end Part_Image; - ------------------------ - -- Update_SCI_Wrapper -- - ------------------------ + ---------------- + -- Update_SCI -- + ---------------- - procedure Update_SCI_Wrapper + procedure Update_SCI (SCO : SCO_Id; - Tag : SC_Tag; Process : access procedure (SCI : in out Source_Coverage_Info)) is begin if In_Scope_Of_Interest (ST, SCO) then - Update_SCI (SCO, Tag, Process); + Process.all (SCI_Vector.Reference (SCO)); end if; - end Update_SCI_Wrapper; + end Update_SCI; -- Start of processing for Compute_Source_Coverage @@ -2421,8 +2219,7 @@ package body Coverage.Source is -- If bit is set, statement has been executed if Stmt_Buffer (J) then - Update_SCI_Wrapper - (BM.Statement_Bits (J), No_SC_Tag, Set_Executed'Access); + Update_SCI (BM.Statement_Bits (J), Set_Executed'Access); end if; end loop; @@ -2448,9 +2245,8 @@ package body Coverage.Source is if Stmt_Buffer (J) then for SCO of Stmt_Blocks.Element (Block_Index) loop - Update_SCI_Wrapper + Update_SCI (SCO => SCO, - Tag => No_SC_Tag, Process => Set_Executed'Access); end loop; end if; @@ -2480,12 +2276,7 @@ package body Coverage.Source is end Set_Known_Outcome_Taken; begin - Update_SCI_Wrapper - (Outcome_Info.D_SCO, No_SC_Tag, - Set_Known_Outcome_Taken'Access); - - -- TODO??? Currently we hard-code No_SC_Tag. - -- Need to add support for per-instance coverage + Update_SCI (Outcome_Info.D_SCO, Set_Known_Outcome_Taken'Access); end; end if; end loop; @@ -2516,8 +2307,7 @@ package body Coverage.Source is end Add_Evaluation; begin - Update_SCI_Wrapper - (MCDC_Info.D_SCO, No_SC_Tag, Add_Evaluation'Access); + Update_SCI (MCDC_Info.D_SCO, Add_Evaluation'Access); end; end if; end loop; @@ -2653,79 +2443,33 @@ package body Coverage.Source is function Get_Line_State (SCO : SCO_Id; - Level : Coverage_Level) return SCO_State - is - Result : SCO_State := No_Code; + Level : Coverage_Level) return SCO_State is begin - -- Aggregate SCI state for each SCI of the SCO - - for SCI of SCI_Vector.Element (SCO) loop - Result := Result * SCI.State (Level); - end loop; - return Result; + return SCI_Vector (SCO).State (Level); end Get_Line_State; - ------------- - -- Get_SCI -- - ------------- - - function Get_SCI - (SCO : SCO_Id; Tag : SC_Tag) return Source_Coverage_Info_Access - is - Result : RW_Source_Coverage_Info_Access; - begin - -- Look for a SCI that matches both SCO and Tag and assign it to Result - - if SCO in SCI_Vector.First_Index .. SCI_Vector.Last_Index then - - declare - SCIV : SCI_Vectors.Vector renames SCI_Vector.Reference (SCO); - begin - for J in SCIV.First_Index .. SCIV.Last_Index loop - declare - SCI : constant RW_Source_Coverage_Info_Access := - SCIV.Element (J); - begin - if SCI.Tag = Tag then - Result := SCI; - exit; - end if; - end; - end loop; - end; - end if; - - -- If we found one, return its source coverage info, otherwise return - -- the default SCI for this kind of SCO. - - return - (if Result /= null - then Source_Coverage_Info_Access (Result) - else Default_SCIs (Kind (SCO))); - end Get_SCI; - -------------------- -- Initialize_SCI -- -------------------- - Default_SCIs_Initialized : Boolean := False; - procedure Initialize_SCI is Last_SCO : constant SCO_Id := SC_Obligations.Last_SCO; + Last_SCI : constant SCO_Id := SCI_Vector.Last_Index; begin if Last_SCO > SCI_Vector.Last_Index then - SCI_Vector.Set_Length (Ada.Containers.Count_Type (Last_SCO)); - pragma Assert (SCI_Vector.Last_Index = Last_SCO); - end if; - - if not Default_SCIs_Initialized then - for K in Default_SCIs'Range loop - Default_SCIs (K) := - Source_Coverage_Info_Access - (RW_Source_Coverage_Info_Access' - (new Source_Coverage_Info (Kind => K))); + SCI_Vector.Reserve_Capacity (Ada.Containers.Count_Type (Last_SCO)); + for SCO in Last_SCI + 1 .. Last_SCO loop + declare + SCI : Source_Coverage_Info (Kind (SCO)); + begin + SCI_Vector.Append (SCI); + end; end loop; - Default_SCIs_Initialized := True; + + -- Make sure the above logic got index computations correct: we + -- should have exactly one SCI per SCO. + + pragma Assert (SCI_Vector.Last_Index = Last_SCO); end if; end Initialize_SCI; @@ -2735,20 +2479,20 @@ package body Coverage.Source is procedure Initialize_SCI_For_Instrumented_CU (CU : CU_Id) is - procedure Process_SCI (SCI : in out Source_Coverage_Info); - -- Callback for Update_SCI. Set SCI (assumed to be a statement SCI) as - -- having code. + procedure Set_Has_Code (SCO : SCO_Id); + -- If SCO is a statement, mark it as having code - ----------------- - -- Process_SCI -- - ----------------- + ------------------ + -- Set_Has_Code -- + ------------------ - procedure Process_SCI (SCI : in out Source_Coverage_Info) is + procedure Set_Has_Code (SCO : SCO_Id) is + SCI : Source_Coverage_Info renames SCI_Vector.Reference (SCO); begin if SCI.Kind = Statement then SCI.Basic_Block_Has_Code := True; end if; - end Process_SCI; + end Set_Has_Code; Stmt_Bit_Map : Statement_Bit_Map renames Bit_Maps (CU).Statement_Bits.all; @@ -2756,14 +2500,9 @@ package body Coverage.Source is -- Start of processing for Initialize_SCI_For_Instrumented_CU begin - -- Only create tag-less SCIs (No_SC_Tag) as per-instance coverage of - -- generics is not supported (see S628-011). - Initialize_SCI; for Bit in Stmt_Bit_Map'Range loop - Update_SCI (SCO => Stmt_Bit_Map (Bit), - Tag => No_SC_Tag, - Process => Process_SCI'Access); + Set_Has_Code (Stmt_Bit_Map (Bit)); end loop; -- If statements were instrumented as blocks, also process the non- @@ -2796,10 +2535,7 @@ package body Coverage.Source is end if; for SCO of Stmt_Blocks.Element (Block_Index) loop - Update_SCI - (SCO => SCO, - Tag => No_SC_Tag, - Process => Process_SCI'Access); + Set_Has_Code (SCO); end loop; Block_Index := Block_Index + 1; <> @@ -2814,68 +2550,53 @@ package body Coverage.Source is procedure Merge_Checkpoint_SCI (SCO : SCO_Id; - Tag : SC_Tag; CP_SCI : Source_Coverage_Info; Relocs : Checkpoint_Relocations) is - procedure Merge_SCI (SCI : in out Source_Coverage_Info); - -- Merge coverage information from checkpointed CP_SCI into SCI + SCI : Source_Coverage_Info renames SCI_Vector.Reference (SCO); + begin + pragma Assert (SCI.Kind = CP_SCI.Kind); - --------------- - -- Merge_SCI -- - --------------- + -- Merge raw coverage information from checkpoint. SCI.Line_State will + -- be recomputed later on, once traces for this increment have been + -- processed. - procedure Merge_SCI (SCI : in out Source_Coverage_Info) is - begin - pragma Assert (SCI.Kind = CP_SCI.Kind); - - -- Merge raw coverage information from checkpoint. SCI.Line_State - -- will be recomputed later on, once traces for this increment have - -- been processed. - - case SCI.Kind is - when Statement => - SCI.Basic_Block_Has_Code := - SCI.Basic_Block_Has_Code or CP_SCI.Basic_Block_Has_Code; - SCI.Executed := SCI.Executed or CP_SCI.Executed; - SCI.Line_Executed := SCI.Line_Executed or CP_SCI.Line_Executed; - - when Decision => - SCI.Known_Outcome_Taken := - SCI.Known_Outcome_Taken or CP_SCI.Known_Outcome_Taken; - - -- Note: if checkpoint has only one Outcome_Taken, and the SCO - -- has degraded origins, then we can't take advantage of it, - -- because it might be negated compared to the current context. - - if not Degraded_Origins (SCO) - or else - CP_SCI.Outcome_Taken (False) = CP_SCI.Outcome_Taken (True) - then - SCI.Outcome_Taken := - SCI.Outcome_Taken or CP_SCI.Outcome_Taken; - end if; + case SCI.Kind is + when Statement => + SCI.Basic_Block_Has_Code := + SCI.Basic_Block_Has_Code or CP_SCI.Basic_Block_Has_Code; + SCI.Executed := SCI.Executed or CP_SCI.Executed; + SCI.Line_Executed := SCI.Line_Executed or CP_SCI.Line_Executed; - -- Merge evaluation vectors from checkpoint + when Decision => + SCI.Known_Outcome_Taken := + SCI.Known_Outcome_Taken or CP_SCI.Known_Outcome_Taken; - for Cur in CP_SCI.Evaluations.Iterate loop - declare - E : Evaluation := Evaluation_Sets.Element (Cur); - begin - E.Decision := Remap_SCO_Id (Relocs, E.Decision); - SCI.Evaluations.Include (E); - end; - end loop; + -- Note: if checkpoint has only one Outcome_Taken, and the SCO has + -- degraded origins, then we can't take advantage of it, because + -- it might be negated compared to the current context. - when others => - null; - end case; - end Merge_SCI; + if not Degraded_Origins (SCO) + or else + CP_SCI.Outcome_Taken (False) = CP_SCI.Outcome_Taken (True) + then + SCI.Outcome_Taken := SCI.Outcome_Taken or CP_SCI.Outcome_Taken; + end if; - -- Start of processing for Merge_Checkpoint_SCI + -- Merge evaluation vectors from checkpoint - begin - Update_SCI (SCO, Tag, Merge_SCI'Access); + for Cur in CP_SCI.Evaluations.Iterate loop + declare + E : Evaluation := Evaluation_Sets.Element (Cur); + begin + E.Decision := Remap_SCO_Id (Relocs, E.Decision); + SCI.Evaluations.Include (E); + end; + end loop; + + when others => + null; + end case; end Merge_Checkpoint_SCI; ---------- @@ -2884,12 +2605,10 @@ package body Coverage.Source is procedure Read (CLS : in out Checkpoint_Load_State; - Value : out RW_Source_Coverage_Info_Access) + Value : out Source_Coverage_Info) is CP_SCI : Source_Coverage_Info (SCO_Kind'Val (CLS.Read_U8)); begin - CP_SCI.Tag := SC_Tag (CLS.Read_I32); - declare States : array (1 .. 10) of Line_State; begin @@ -2932,11 +2651,7 @@ package body Coverage.Source is null; end case; - if CP_SCI = Default_SCIs (CP_SCI.Kind).all then - Value := null; - else - Value := new Source_Coverage_Info'(CP_SCI); - end if; + Value := Source_Coverage_Info'(CP_SCI); end Read; ----------- @@ -2945,10 +2660,9 @@ package body Coverage.Source is procedure Write (CSS : in out Checkpoint_Save_State; - Value : RW_Source_Coverage_Info_Access) is + Value : Source_Coverage_Info) is begin CSS.Write_U8 (SCO_Kind'Pos (Value.Kind)); - CSS.Write_I32 (Interfaces.Integer_32 (Value.Tag)); for S of Value.State loop CSS.Write (S); end loop; @@ -2998,23 +2712,11 @@ package body Coverage.Source is -- Set_Basic_Block_Has_Code -- ------------------------------ - procedure Set_Basic_Block_Has_Code (SCO : SCO_Id; Tag : SC_Tag) is + procedure Set_Basic_Block_Has_Code (SCO : SCO_Id) is S_SCO : SCO_Id := SCO; pragma Assert (Kind (S_SCO) = Statement); - procedure Set_SCI_BB_Has_Code (SCI : in out Source_Coverage_Info); - -- Set SCI.Basic_Block_Has_Code - - ------------------------- - -- Set_SCI_BB_Has_Code -- - ------------------------- - - procedure Set_SCI_BB_Has_Code (SCI : in out Source_Coverage_Info) is - begin - SCI.Basic_Block_Has_Code := True; - end Set_SCI_BB_Has_Code; - Propagating, No_Propagation : Boolean; -- Start of processing for Set_Basic_Block_Has_Code @@ -3032,7 +2734,7 @@ package body Coverage.Source is No_Propagation := Is_Pragma_Pre_Post_Condition (S_SCO); if not (Propagating and No_Propagation) then - Update_SCI (S_SCO, Tag, Set_SCI_BB_Has_Code'Access); + SCI_Vector.Reference (S_SCO).Basic_Block_Has_Code := True; end if; exit when not Propagating and No_Propagation; @@ -3040,7 +2742,7 @@ package body Coverage.Source is Propagating := True; S_SCO := Previous (S_SCO); exit when S_SCO = No_SCO_Id - or else Get_SCI (S_SCO, Tag).Basic_Block_Has_Code; + or else SCI_Vector (S_SCO).Basic_Block_Has_Code; end loop; end Set_Basic_Block_Has_Code; @@ -3051,52 +2753,14 @@ package body Coverage.Source is procedure Update_Line_State (Line : Line_Info_Access; SCO : SCO_Id; - Tag : SC_Tag; Level : Coverage_Level; State : Line_State) is Cell : constant Line_State_Cell := Coverage_Level_To_Cell (Level); begin - Update_State (Line.State (Cell), SCO, Tag, Level, State); + Update_State (Line.State (Cell), SCO, Level, State); end Update_Line_State; - ---------------- - -- Update_SCI -- - ---------------- - - procedure Update_SCI - (SCO : SCO_Id; - Tag : SC_Tag; - Process : access procedure (SCI : in out Source_Coverage_Info)) - is - SCIV : SCI_Vectors.Vector renames SCI_Vector.Reference (SCO); - begin - -- Look for a SCI whose tag matches Tag. If we find one, call Process - -- on it and return. - - for J in SCIV.First_Index .. SCIV.Last_Index loop - declare - SCI : Source_Coverage_Info renames SCIV.Element (J).all; - begin - if SCI.Tag = Tag then - Process (SCI); - return; - end if; - end; - end loop; - - -- Otherwise, create a new SCI for this tag and call Process on it - - declare - New_SCI : constant RW_Source_Coverage_Info_Access := - new Source_Coverage_Info (Kind (SCO)); - begin - New_SCI.Tag := Tag; - Process (New_SCI.all); - SCIV.Append (New_SCI); - end; - end Update_SCI; - ------------------ -- Update_State -- ------------------ @@ -3104,39 +2768,11 @@ package body Coverage.Source is procedure Update_State (Prev_State : in out Line_State; SCO : SCO_Id; - Tag : SC_Tag; Level : Coverage_Level; - State : Line_State) - is - procedure Update_SCO_Line_State (SCI : in out Source_Coverage_Info); - -- Set SCI's coverage state for Level to State - - --------------------------- - -- Update_SCO_Line_State -- - --------------------------- - - procedure Update_SCO_Line_State (SCI : in out Source_Coverage_Info) is - begin - SCI.State (Level) := State; - end Update_SCO_Line_State; - - -- Start of processing for Update_State - + State : Line_State) is begin - Update_SCI (SCO, Tag, Update_SCO_Line_State'Access); + SCI_Vector.Reference (SCO).State (Level) := State; Prev_State := Prev_State * State; end Update_State; - --------------- - -- Write_SCI -- - --------------- - - procedure Write_SCI - (S : access Root_Stream_Type'Class; - SCI : RW_Source_Coverage_Info_Access) - is - begin - Source_Coverage_Info'Output (S, SCI.all); - end Write_SCI; - end Coverage.Source; diff --git a/tools/gnatcov/coverage-source.ads b/tools/gnatcov/coverage-source.ads index d66549304..12a91b43a 100644 --- a/tools/gnatcov/coverage-source.ads +++ b/tools/gnatcov/coverage-source.ads @@ -102,17 +102,14 @@ package Coverage.Source is (SCO : SCO_Id; Level : Coverage_Level) return SCO_State; -- Return SCO's contribution to the state of the enclosing line, i.e. - -- SCO's specific coverage state, ignoring any exemptions. This coverage - -- is cumulative over all SCIs for this SCO, for the case of a SCO that - -- has multiple tags (i.e. multiple, distinct coverage analyses). + -- SCO's specific coverage state, ignoring any exemptions. - function Basic_Block_Has_Code (SCO : SCO_Id; Tag : SC_Tag) return Boolean; - -- True if any SCO in basic block has associated object code with then - -- given tag. + function Basic_Block_Has_Code (SCO : SCO_Id) return Boolean; + -- True if any SCO in basic block has associated object code - procedure Set_Basic_Block_Has_Code (SCO : SCO_Id; Tag : SC_Tag); + procedure Set_Basic_Block_Has_Code (SCO : SCO_Id); -- Set Basic_Block_Has_Code for SCO (a Statement SCO) as well as all - -- previous SCOs in its basic block, for the given tag. + -- previous SCOs in its basic block. --------------------------------------------------------- -- Handling of the list of names for units of interest -- diff --git a/tools/gnatcov/coverage-tags.adb b/tools/gnatcov/coverage-tags.adb deleted file mode 100644 index 6099d034c..000000000 --- a/tools/gnatcov/coverage-tags.adb +++ /dev/null @@ -1,106 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- 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. -- ------------------------------------------------------------------------------- - -package body Coverage.Tags is - - ------------------- - -- Enter_Routine -- - ------------------- - - procedure Enter_Routine - (TP : access Tag_Provider_Type; - Subp_Info : Traces_Names.Subprogram_Info) - is - Subprogram_Info : constant Address_Info_Acc := - Get_Address_Info - (Exec => Subp_Info.Exec.all, - Kind => Subprogram_Addresses, - PC => Subp_Info.Insns.First); - begin - TP.Current_Routine := Subp_Info; - TP.Current_Subp := Subprogram_Info; - end Enter_Routine; - - ------------------------ - -- Get_Slocs_And_Tags -- - ------------------------ - - overriding function Get_Slocs_And_Tags - (TP : access Default_Tag_Provider_Type; - PC : Pc_Type) return Tagged_Slocs - is - begin - return Get_Slocs_With_Tag (TP.Current_Subp.Lines, PC, No_SC_Tag); - end Get_Slocs_And_Tags; - - ------------------------ - -- Get_Slocs_With_Tag -- - ------------------------ - - function Get_Slocs_With_Tag - (Set : Address_Info_Sets.Set; - PC : Pc_Type; - Tag : SC_Tag) return Tagged_Slocs - is - Slocs : constant Source_Locations := Get_Slocs (Set, PC); - begin - return Tslocs : Tagged_Slocs (Slocs'Range) do - for J in Slocs'Range loop - Tslocs (J) := (Sloc => Slocs (J), Tag => Tag); - end loop; - end return; - end Get_Slocs_With_Tag; - - ------------- - -- Map_Tag -- - ------------- - - overriding function Map_Tag - (TP : access Default_Tag_Provider_Type; - Relocs : Checkpoints.Checkpoint_Relocations; - CP_Tag : SC_Tag) return SC_Tag - is - pragma Unreferenced (TP, Relocs, CP_Tag); - begin - return No_SC_Tag; - end Map_Tag; - - -------------- - -- Tag_Name -- - -------------- - - overriding function Tag_Name - (TP : access Default_Tag_Provider_Type; - Tag : SC_Tag) return String - is - pragma Unreferenced (TP); - pragma Assert (Tag = No_SC_Tag); - begin - return ""; - end Tag_Name; - - ----------------------- - -- Tag_Provider_Name -- - ----------------------- - - function Tag_Provider_Name return String is - begin - return Tag_Providers.Name (Tag_Provider'Tag); - end Tag_Provider_Name; - -end Coverage.Tags; diff --git a/tools/gnatcov/coverage-tags.ads b/tools/gnatcov/coverage-tags.ads deleted file mode 100644 index b40e6622d..000000000 --- a/tools/gnatcov/coverage-tags.ads +++ /dev/null @@ -1,136 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- 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 Checkpoints; - -with Factory_Registry; -with Slocs; use Slocs; -with Traces; use Traces; -with Traces_Elf; use Traces_Elf; -with Traces_Names; use Traces_Names; - -package Coverage.Tags is - - -------------------------- - -- Source coverage tags -- - -------------------------- - - -- In some contexts, several distinct coverage analyses must be conducted - -- in parallel for a given SCO (e.g. when separately assessing coverage on - -- different instances of the same generic unit). In such cases, each - -- separate analysis is assigned a specific tag. The special value - -- No_SC_Tag denotes the default cumulative analysis made for a SCO when - -- no such distinction exists. - - type Tag_Provider_Type is abstract tagged limited record - Current_Routine : Subprogram_Info; - Current_Subp : Address_Info_Acc; - end record; - - type Tagged_Sloc is record - Sloc : Source_Location; - Tag : SC_Tag; - end record; - - type Tagged_Slocs is array (Positive range <>) of Tagged_Sloc; - -- Note: must have the same index base subtype as Slocs.Source_Locations - - function Get_Slocs_And_Tags - (TP : access Tag_Provider_Type; - PC : Pc_Type) return Tagged_Slocs is abstract; - -- Return a list of (sloc; tag) pairs for the given executable location. - -- Note that for PC that is associated with more than one sloc (i.e. more - -- than one SCO), the relevant tag may be different for each sloc/SCO. - -- Enter_Routine must have been called previously to identify the - -- enclosing subprogram; code outside of a subprogram is defined to - -- always have No_SCO_Tag. - - function Tag_Name - (TP : access Tag_Provider_Type; - Tag : SC_Tag) return String is abstract; - -- Return a user readable name for the given tag - - procedure Enter_Routine - (TP : access Tag_Provider_Type; - Subp_Info : Traces_Names.Subprogram_Info); - -- Record Subp_Info as the subprogram information for the routine being - -- analyzed (sets TP.Current_Routine). - - function Map_Tag - (TP : access Tag_Provider_Type; - Relocs : Checkpoints.Checkpoint_Relocations; - CP_Tag : SC_Tag) return SC_Tag is abstract; - -- Convert a tag from a checkpoint to the corresponding one in the - -- current context. Note: caller must ensure that TP is either a - -- Default_Tag_Provider_Type, or the same tag provider type as when - -- the checkpoint was produced. - - package Tag_Providers is - new Factory_Registry (Tag_Provider_Type); - - subtype Tag_Provider_Access is Tag_Providers.RT_Access; - - ---------------------------- - -- Default tag repository -- - ---------------------------- - - -- This repository does not assign any tags - - type Default_Tag_Provider_Type is new Tag_Provider_Type with private; - - overriding function Get_Slocs_And_Tags - (TP : access Default_Tag_Provider_Type; - PC : Pc_Type) return Tagged_Slocs; - -- Return all slocs for PC tagged with No_SC_Tag - - overriding function Tag_Name - (TP : access Default_Tag_Provider_Type; - Tag : SC_Tag) return String; - -- Return the empty string - - overriding function Map_Tag - (TP : access Default_Tag_Provider_Type; - Relocs : Checkpoints.Checkpoint_Relocations; - CP_Tag : SC_Tag) return SC_Tag; - -- Return No_SC_Tag - - Tag_Provider : Tag_Provider_Access; - Default_Tag_Provider_Name : constant String := "default"; - - function Tag_Provider_Name return String; - -- Return the name of Tag_Provider - - ---------------------- - -- Utility routines -- - ---------------------- - - function Get_Slocs_With_Tag - (Set : Address_Info_Sets.Set; - PC : Pc_Type; - Tag : SC_Tag) return Tagged_Slocs; - -- Return all slocs for PC, tagged with Tag - -private - - type Default_Tag_Provider_Type is new Tag_Provider_Type with null record; - - package R is new Tag_Providers.Register_Factory - (Name => Default_Tag_Provider_Name, - T => Default_Tag_Provider_Type); - -end Coverage.Tags; diff --git a/tools/gnatcov/coverage.ads b/tools/gnatcov/coverage.ads index ec0f37420..d9d6586a4 100644 --- a/tools/gnatcov/coverage.ads +++ b/tools/gnatcov/coverage.ads @@ -110,13 +110,6 @@ package Coverage is -- levels for the current enabled levels is allowed, return an empty -- string. Otherwise, return an error message. - type SC_Tag is new Natural; - No_SC_Tag : constant SC_Tag := 0; - subtype Valid_SC_Tag is SC_Tag range No_SC_Tag + 1 .. SC_Tag'Last; - -- Several separated source coverage analyses may be simultaneously - -- performed on a given source construct, in which case each analysis is - -- identified by a different SC_Tag. - ---------------------- -- Coverage context -- ---------------------- diff --git a/tools/gnatcov/decision_map.adb b/tools/gnatcov/decision_map.adb index 584647146..3093df177 100644 --- a/tools/gnatcov/decision_map.adb +++ b/tools/gnatcov/decision_map.adb @@ -27,7 +27,6 @@ with System.Storage_Elements; with Binary_Files; use Binary_Files; with Coverage.Source; use Coverage.Source; -with Coverage.Tags; use Coverage.Tags; with Coverage_Options; use Coverage_Options; with Diagnostics; use Diagnostics; with Elf_Common; @@ -124,9 +123,7 @@ package body Decision_Map is -- If this is a conditional branch testing a condition, identifies it Branch_SCO : SCO_Id := No_SCO_Id; - Branch_SCO_Tag : SC_Tag := No_SC_Tag; - -- Condition or Statement SCO for To_PC, with corresponding tag, for - -- statistics purposes. + -- Condition or Statement SCO for To_PC, for statistics purposes -- If multiple SCOs are associated with this PC: -- - if one of them is a Condition, it is selected (in which case @@ -224,7 +221,6 @@ package body Decision_Map is procedure Analyze_Conditional_Branch (Exec : Exe_File_Acc; Insn : Binary_Content; - Tag : SC_Tag; C_SCO : SCO_Id; Branch_Dest : Dest; FT_Dest : Dest; @@ -352,7 +348,6 @@ package body Decision_Map is -- Process the reference instance of the routine if First_Symbol_Occurrence then - Tag_Provider.Enter_Routine (Subp_Info); -- Map routine instructions to SCOs @@ -433,7 +428,6 @@ package body Decision_Map is procedure Analyze_Conditional_Branch (Exec : Exe_File_Acc; Insn : Binary_Content; - Tag : SC_Tag; C_SCO : SCO_Id; Branch_Dest : Dest; FT_Dest : Dest; @@ -555,10 +549,6 @@ package body Decision_Map is +("unexpected condition" & CI'Img & " in decision " & Image (DS_Top.Decision)); - if Tag /= No_SC_Tag then - Append (Msg, ", tag=" & Tag_Provider.Tag_Name (Tag)); - end if; - -- This could correspond to some finalization code, that has -- a debug info code location corresponding to a condition. -- We will silence it unless explicitely requested with a @@ -2469,7 +2459,6 @@ package body Decision_Map is Exe => Exec, PC => BB.To_PC, Sloc => First_Sloc (BB.Branch_SCO), - Tag => BB.Branch_SCO_Tag, Kind => Warning); end Report_Non_Traceable; @@ -2483,7 +2472,6 @@ package body Decision_Map is Insn_First, Insn_Last : Pc_Type; -- Conditional branch instruction PC range in Insns - Tag : SC_Tag; C_SCO : SCO_Id; -- SCO and sloc information for this instruction @@ -2550,16 +2538,16 @@ package body Decision_Map is Flag_Cond : Boolean; Branch_Dest : Dest; FT_Dest : Dest; - Tslocs : constant Tagged_Slocs := - Tag_Provider.Get_Slocs_And_Tags (PC); + Slocs : constant Source_Locations := + Get_Slocs (Context.Subprg.Lines, PC); -- Properties of Insn begin -- Check if this is a thunk if PC = Insns.First and then Match (Subp_Name, Thunk_Matcher) then - for Tsloc of Tslocs loop - LI := Get_Line (Tsloc.Sloc); + for Sloc of Slocs loop + LI := Get_Line (Sloc); if LI /= null and then LI.SCOs /= null then for SCO of LI.SCOs.all loop if Kind (SCO) = Statement @@ -2581,8 +2569,8 @@ package body Decision_Map is -- is done for all SCOs on the line, else only for those that -- contain that column number. - for Tsloc of Tslocs loop - LI := Get_Line (Tsloc.Sloc); + for Sloc of Slocs loop + LI := Get_Line (Sloc); if LI /= null and then LI.SCOs /= null then -- Record presence of code for all Statement SCOs on line @@ -2591,16 +2579,16 @@ package body Decision_Map is if Kind (SCO) = Statement and then - (Tsloc.Sloc.L.Column = 0 - or else In_Range (Tsloc.Sloc, Sloc_Range (SCO))) + (Sloc.L.Column = 0 + or else In_Range (Sloc, Sloc_Range (SCO))) then - Set_Basic_Block_Has_Code (SCO, Tsloc.Tag); + Set_Basic_Block_Has_Code (SCO); end if; end loop; -- Record presence of code for compilation unit - Set_Unit_Has_Code (Comp_Unit (Tsloc.Sloc.Source_File)); + Set_Unit_Has_Code (Comp_Unit (Sloc.Source_File)); end if; end loop; @@ -2681,10 +2669,7 @@ package body Decision_Map is if Branch /= Br_None then Analyze_Branch : declare SCO : SCO_Id; - Tag : SC_Tag; - Branch_SCO : SCO_Id renames BB.Branch_SCO; - Branch_SCO_Tag : SC_Tag renames BB.Branch_SCO_Tag; -- Start of processing for Analyze_Branch @@ -2710,9 +2695,8 @@ package body Decision_Map is and then BB.Branch = Br_Jmp and then BB.From = BB.To_PC; - for Tsloc of Tslocs loop - SCO := Sloc_To_SCO (Tsloc.Sloc); - Tag := Tsloc.Tag; + for Sloc of Slocs loop + SCO := Sloc_To_SCO (Sloc); if Flag_Cond then if Branch = Br_Jmp or else Branch = Br_Ret then @@ -2747,7 +2731,6 @@ package body Decision_Map is (Pending_Cond_Branch' (Insn_First => Insn.First, Insn_Last => Insn.Last, - Tag => Tsloc.Tag, C_SCO => SCO, Branch_Dest => Branch_Dest, FT_Dest => FT_Dest, @@ -2766,8 +2749,7 @@ package body Decision_Map is end if; if Branch_SCO = No_SCO_Id and then SCO /= No_SCO_Id then - Branch_SCO := SCO; - Branch_SCO_Tag := Tag; + Branch_SCO := SCO; end if; end loop; @@ -2821,7 +2803,6 @@ package body Decision_Map is (Exec => Exec, Insn => Slice (Insns, Cond_Branch.Insn_First, Cond_Branch.Insn_Last), - Tag => Cond_Branch.Tag, C_SCO => Cond_Branch.C_SCO, Branch_Dest => Cond_Branch.Branch_Dest, FT_Dest => Cond_Branch.FT_Dest, diff --git a/tools/gnatcov/diagnostics.adb b/tools/gnatcov/diagnostics.adb index 1e30687ee..c0df4efd0 100644 --- a/tools/gnatcov/diagnostics.adb +++ b/tools/gnatcov/diagnostics.adb @@ -20,12 +20,11 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Directories; with Ada.Text_IO; use Ada.Text_IO; -with Command_Line; use Command_Line; -with Coverage.Tags; use Coverage.Tags; -with Files_Table; use Files_Table; -with Hex_Images; use Hex_Images; +with Command_Line; use Command_Line; +with Files_Table; use Files_Table; +with Hex_Images; use Hex_Images; with Outputs; -with Switches; use Switches; +with Switches; use Switches; package body Diagnostics is @@ -66,9 +65,6 @@ package body Diagnostics is function Sloc_Image return String; -- Image of Sloc, null string for the value No_Location - function Tag_Image return String; - -- Tag indication, null string for the value No_SC_Tag - ---------------- -- Kind_Image -- ---------------- @@ -128,19 +124,6 @@ package body Diagnostics is end if; end SCO_Image; - --------------- - -- Tag_Image -- - --------------- - - function Tag_Image return String is - begin - if M.Tag /= No_SC_Tag then - return " (from " & Tag_Provider.Tag_Name (M.Tag) & ")"; - else - return ""; - end if; - end Tag_Image; - Msg : constant String := +M.Msg; First : Natural := Msg'First; @@ -157,7 +140,7 @@ package body Diagnostics is Sloc_Image & " " & Kind_Image & - SCO_Image & Msg (First .. Msg'Last) & Tag_Image; + SCO_Image & Msg (First .. Msg'Last); end Image; ------------ @@ -203,7 +186,6 @@ package body Diagnostics is Sloc : Source_Location := No_Location; Violation_Sloc : Source_Location := No_Location; SCO : SCO_Id := No_SCO_Id; - Tag : SC_Tag := No_SC_Tag; Kind : Report_Kind := Error) is M : constant Message := @@ -215,7 +197,6 @@ package body Diagnostics is then Sloc else Violation_Sloc), SCO => SCO, - Tag => Tag, Msg => +Msg); begin Output_Message (M); @@ -228,7 +209,6 @@ package body Diagnostics is procedure Report_Coverage (SCO : SCO_Id; - Tag : SC_Tag; Msg : String; Kind : Coverage_Kind) is @@ -253,7 +233,6 @@ package body Diagnostics is Sloc => Sloc, Violation_Sloc => Violation_Sloc, SCO => SCO, - Tag => Tag, Kind => Kind); end Report_Coverage; @@ -263,11 +242,10 @@ package body Diagnostics is procedure Report_Exclusion (SCO : SCO_Id; - Tag : SC_Tag; Msg : String) is begin - Report_Coverage (SCO, Tag, Msg, Kind => Exclusion); + Report_Coverage (SCO, Msg, Kind => Exclusion); end Report_Exclusion; ---------------------- @@ -276,11 +254,10 @@ package body Diagnostics is procedure Report_Violation (SCO : SCO_Id; - Tag : SC_Tag; Msg : String) is begin - Report_Coverage (SCO, Tag, Msg, Kind => Violation); + Report_Coverage (SCO, Msg, Kind => Violation); end Report_Violation; -------------------- diff --git a/tools/gnatcov/diagnostics.ads b/tools/gnatcov/diagnostics.ads index 13501f857..84a63a90e 100644 --- a/tools/gnatcov/diagnostics.ads +++ b/tools/gnatcov/diagnostics.ads @@ -35,7 +35,6 @@ with Ada.Containers.Vectors; -with Coverage; use Coverage; with Logging; with SC_Obligations; use SC_Obligations; with Slocs; use Slocs; @@ -66,7 +65,6 @@ package Diagnostics is Sloc : Source_Location; Violation_Sloc : Source_Location; SCO : SCO_Id; - Tag : SC_Tag; Msg : Unbounded_String; end record; @@ -87,7 +85,6 @@ package Diagnostics is procedure Report_Coverage (SCO : SCO_Id; - Tag : SC_Tag; Msg : String; Kind : Coverage_Kind); -- Report coverage messages. Common processing for Report_Violation and @@ -95,7 +92,6 @@ package Diagnostics is procedure Report_Violation (SCO : SCO_Id; - Tag : SC_Tag; Msg : String); -- Report a violation of a source coverage obligation. Note: the SCO kind -- will be prepended to Msg in reports, unless Msg starts with ^ (caret). @@ -103,12 +99,11 @@ package Diagnostics is procedure Report_Exclusion (SCO : SCO_Id; - Tag : SC_Tag; Msg : String); -- Report exclusion of a SCO from coverage analysis. No coverage status - -- will be reported for SCO/Tag. Note: the SCO kind will be prepended to - -- Msg in reports, unless Msg starts with ^ (caret). A violation message - -- has message kind Exclusion. + -- will be reported for SCO. Note: the SCO kind will be prepended to Msg in + -- reports, unless Msg starts with ^ (caret). A violation message has + -- message kind Exclusion. procedure Report (Msg : String; @@ -117,7 +112,6 @@ package Diagnostics is Sloc : Source_Location := No_Location; Violation_Sloc : Source_Location := No_Location; SCO : SCO_Id := No_SCO_Id; - Tag : SC_Tag := No_SC_Tag; Kind : Report_Kind := Error); -- Output diagnostic message during coverage analysis. Messages with Notice -- kind are omitted unless global flag Verbose is set. A prefix is diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index df7a799a7..6b6f89148 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -52,7 +52,6 @@ with Command_Line; use Command_Line; use Command_Line.Parser; with Convert; with Coverage.Source; use Coverage.Source; -with Coverage.Tags; use Coverage.Tags; with Coverage; use Coverage; with Coverage_Options; use Coverage_Options; with Decision_Map; use Decision_Map; @@ -750,20 +749,6 @@ procedure GNATcov_Bits_Specific is Convert.Set_Trace_Source (+Args.String_Args (Opt_Trace_Source).Value); end if; - if Args.String_Args (Opt_Separate).Present then - Warn ("-S is deprecated. This option will be removed in release 26."); - declare - Name : constant String := +Args.String_Args (Opt_Separate).Value; - begin - Tag_Provider := Tag_Providers.Create (Name); - exception - when Constraint_Error => - Fatal_Error ("Invalid separated coverage analysis mode: " - & Name & " (available: " - & Tag_Providers.Registered_Names (", ") & ")"); - end; - end if; - if Args.String_Args (Opt_Output_Format).Present then declare Arg : constant String := @@ -1224,16 +1209,6 @@ procedure GNATcov_Bits_Specific is Enumerate_Ignored_Source_Files (Add_Source_File'Access); end; end if; - - -- Set defaults for options not specified so far - - declare - use type Tag_Provider_Access; - begin - if Tag_Provider = null then - Tag_Provider := Tag_Providers.Create (Default_Tag_Provider_Name); - end if; - end; end Process_Arguments; ---------------------- diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 6fcd96791..22ec40ae4 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -27,7 +27,6 @@ with GNATCOLL.VFS; use GNATCOLL.VFS; with GNAT.OS_Lib; -with Coverage.Tags; use Coverage.Tags; with Files_Handling; use Files_Handling; with Files_Table; use Files_Table; with Instrument.C; use Instrument.C; @@ -762,7 +761,6 @@ begin -- Set things that must be set as we don't go through gnatcov_bits_specific - Tag_Provider := Tag_Providers.Create (Default_Tag_Provider_Name); Traces_Files.Update_Current_Trace_Kind (Traces_Files.Source_Trace_File); Context.Orig_Compiler_Driver := diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index ad19a3e2a..c99bda33c 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -33,8 +33,8 @@ with SCOs; with Snames; with Checkpoints; use Checkpoints; +with Coverage; use Coverage; with Coverage.Source; -with Coverage.Tags; use Coverage, Coverage.Tags; with Diagnostics; use Diagnostics; with Files_Table; use Files_Table; with Inputs; use Inputs; @@ -213,10 +213,6 @@ package body SC_Obligations is -- Register CU in Origin_To_CUs_Map. This assumes that CU's Origin is -- properly initialized. - function Instance_Loc (Inst_Index : Inst_Id) return String; - -- Return a string representation of the instantiation location denoted - -- by Inst_Index, which must be in Comp_Unit's instance range. - ----------------------------------- -- Low level SCO tables handling -- ----------------------------------- @@ -550,29 +546,6 @@ package body SC_Obligations is procedure Add_SCO_To_Lines (SCO : SCO_Id; SCOD : SCO_Descriptor); -- Link the given SCO and SCOD to the corresponding entries in line tables - ----------------------- - -- Instance coverage -- - ----------------------- - - type Instance_Tag_Provider_Type is new Tag_Provider_Type with null record; - - overriding function Get_Slocs_And_Tags - (TP : access Instance_Tag_Provider_Type; - PC : Pc_Type) return Tagged_Slocs; - - overriding function Tag_Name - (TP : access Instance_Tag_Provider_Type; - Tag : SC_Tag) return String; - - overriding function Map_Tag - (TP : access Instance_Tag_Provider_Type; - Relocs : Checkpoint_Relocations; - CP_Tag : SC_Tag) return SC_Tag; - - package R is new Tag_Providers.Register_Factory - (Name => "instance", T => Instance_Tag_Provider_Type); - pragma Unreferenced (R); - -- Source_Coverage_Vectors holds all SCO-related data. This holder can -- contain data loaded from a checkpoint. @@ -3184,75 +3157,6 @@ package body SC_Obligations is end if; end Get_Origin; - ------------- - -- Get_Tag -- - ------------- - - overriding function Get_Slocs_And_Tags - (TP : access Instance_Tag_Provider_Type; - PC : Pc_Type) return Tagged_Slocs - is - use type Pc_Type; - use type Interfaces.Unsigned_32; - - Line_Infos : constant Address_Info_Arr := - Get_Address_Infos (TP.Current_Subp.Lines, Line_Addresses, PC); - - Tslocs : Tagged_Slocs (1 .. Integer (Line_Infos'Length)); - Last : Natural := Tslocs'First - 1; - - Global_Instance_Index : Inst_Id; - - CU : CU_Id renames TP.Current_Subp.Subprogram_CU; - CUI : CU_Info; - Has_Instances : Boolean; - - begin - pragma Assert - (PC in TP.Current_Routine.Insns.First + TP.Current_Routine.Offset - .. TP.Current_Routine.Insns.Last + TP.Current_Routine.Offset); - - if CU /= No_CU_Id then - CUI := CU_Vector.Constant_Reference (CU); - Has_Instances := CUI.First_Instance <= CUI.Last_Instance; - else - Has_Instances := False; - end if; - - for Line_Info of Line_Infos loop - if Line_Info.Last >= Line_Info.First then - Last := Last + 1; - Tslocs (Last).Sloc := Line_Info.Sloc; - - -- Discriminator is an instance index if instance table is present - -- (SCOs loaded) and not empty. - - if Has_Instances and then Line_Info.Disc /= 0 then - - -- Non-zero discriminator found: it is an instance index within - -- the current compilation unit. Convert it to a global - -- instance index, and cast to tag. - - Global_Instance_Index := - CUI.First_Instance + Inst_Id (Line_Info.Disc - 1); - - pragma Assert - (Global_Instance_Index <= CUI.Last_Instance); - - pragma Assert - (Inst_Vector.Constant_Reference - (Global_Instance_Index).Comp_Unit - = TP.Current_Subp.Subprogram_CU); - - Tslocs (Last).Tag := Valid_SC_Tag (Global_Instance_Index); - else - Tslocs (Last).Tag := No_SC_Tag; - end if; - end if; - end loop; - return Tslocs (Tslocs'First .. Last); - end Get_Slocs_And_Tags; - ------------------- -- Handler_Range -- ------------------- @@ -3650,21 +3554,6 @@ package body SC_Obligations is Origin_To_CUs_Map.Reference (Cur).Insert (CU); end Register_CU; - ------------------ - -- Instance_Loc -- - ------------------ - - function Instance_Loc (Inst_Index : Inst_Id) return String - is - II : Inst_Info renames Inst_Vector.Constant_Reference (Inst_Index); - begin - return - Image (II.Sloc) - & (if II.Enclosing_Instance = No_Inst_Id - then "" - else " [" & Instance_Loc (II.Enclosing_Instance) & "]"); - end Instance_Loc; - ------------------ -- Is_Assertion -- ------------------ @@ -5107,27 +4996,6 @@ package body SC_Obligations is end loop; end Process_Low_Level_SCOs; - ------------- - -- Map_Tag -- - ------------- - - overriding function Map_Tag - (TP : access Instance_Tag_Provider_Type; - Relocs : Checkpoint_Relocations; - CP_Tag : SC_Tag) return SC_Tag - is - pragma Unreferenced (TP); - begin - -- Remap CP_Tag interpreted as a global instance id. No remapping is - -- needed for No_SC_Tag as it designates the absence of instance. - - if CP_Tag = No_SC_Tag then - return No_SC_Tag; - else - return SC_Tag (Remap_Inst_Id (Relocs, Inst_Id (CP_Tag))); - end if; - end Map_Tag; - ------------------- -- Next_BDD_Node -- ------------------- @@ -6712,19 +6580,6 @@ package body SC_Obligations is return SCO; end Sloc_To_SCO; - -------------- - -- Tag_Name -- - -------------- - - overriding function Tag_Name - (TP : access Instance_Tag_Provider_Type; - Tag : SC_Tag) return String - is - pragma Unreferenced (TP); - begin - return Instance_Loc (Inst_Id (Tag)); - end Tag_Name; - ---------------------- -- To_Decision_Kind -- ---------------------- diff --git a/tools/gnatcov/traces_elf.adb b/tools/gnatcov/traces_elf.adb index 7af26211d..7caa4086d 100644 --- a/tools/gnatcov/traces_elf.adb +++ b/tools/gnatcov/traces_elf.adb @@ -33,7 +33,6 @@ with Coverage_Options; use Coverage_Options; with Coverage; use Coverage; with Coverage.Object; use Coverage.Object; with Coverage.Source; -with Coverage.Tags; use Coverage.Tags; with Diagnostics; with Disa_Ppc; with Disassemblers; use Disassemblers; @@ -2706,12 +2705,10 @@ package body Traces_Elf is -- If the code maps to source code targetted by SCOs, -- tag the SCOs as having code so that we will emit a - -- coverage violation for it. We have no symbol and no - -- subprogram, thus we cannot get a tag for this code. + -- coverage violation for it. if SCO /= No_SCO_Id then - Coverage.Source.Set_Basic_Block_Has_Code - (SCO, No_SC_Tag); + Coverage.Source.Set_Basic_Block_Has_Code (SCO); end if; end if; @@ -4788,7 +4785,6 @@ package body Traces_Elf is pragma Unreferenced (Key); begin if Info.Exec /= null and then Is_Loaded (Info.Insns) then - Tag_Provider.Enter_Routine (Info); Build_Debug_Lines (Info.Exec.all); Build_Source_Lines_For_Section (Info.Exec, Info.Traces, Info.Insns); diff --git a/tools/gnatcov/traces_names.adb b/tools/gnatcov/traces_names.adb index 509fc30f8..472eb7b6a 100644 --- a/tools/gnatcov/traces_names.adb +++ b/tools/gnatcov/traces_names.adb @@ -24,16 +24,13 @@ with Ada.Text_IO; use Ada.Text_IO; with Interfaces; -with GNAT.Strings; use GNAT.Strings; +with GNAT.Strings; use GNAT.Strings; -with Checkpoints; -with Coverage.Object; use Coverage.Object; -with Coverage.Tags; use Coverage.Tags; -with Inputs; use Inputs; -with Outputs; use Outputs; +with Coverage.Object; use Coverage.Object; +with Inputs; use Inputs; +with Outputs; use Outputs; with Paths; -with Switches; use Switches; -with Symbols; use Symbols; +with Symbols; use Symbols; package body Traces_Names is @@ -49,31 +46,6 @@ package body Traces_Names is "<" => "<", "=" => "="); - package Routine_Tag_Vectors is new Ada.Containers.Vectors - (Index_Type => Valid_SC_Tag, - Element_Type => Cst_String_Access); - - type Routine_Tag_Provider_Type is new Tag_Provider_Type with record - Routine_Tags : Routine_Tag_Vectors.Vector; - end record; - - overriding function Get_Slocs_And_Tags - (TP : access Routine_Tag_Provider_Type; - PC : Pc_Type) return Tagged_Slocs; - - overriding function Tag_Name - (TP : access Routine_Tag_Provider_Type; - Tag : SC_Tag) return String; - - overriding function Map_Tag - (TP : access Routine_Tag_Provider_Type; - Relocs : Checkpoints.Checkpoint_Relocations; - CP_Tag : SC_Tag) return SC_Tag; - - package R is new Tag_Providers.Register_Factory - (Name => "routine", T => Routine_Tag_Provider_Type); - pragma Unreferenced (R); - package Routines_Maps is new Ada.Containers.Ordered_Maps (Key_Type => Subprogram_Key, Element_Type => Subprogram_Info, @@ -173,10 +145,7 @@ package body Traces_Names is Section : Section_Index) is use Routines_Maps; - TP : Tag_Provider_Access renames Tag_Provider; Cur : Cursor; - Tag : SC_Tag; - begin -- If the routine has no compile unit, it must not be consolidated, so -- it is made unique using its Origin member. @@ -194,22 +163,6 @@ package body Traces_Names is Cur := Routines.Find (Key); if Cur = No_Element then - - -- If doing routine-based separated coverage analysis, record name in - -- routine tags table. - - if TP.all in Routine_Tag_Provider_Type'Class then - declare - RTags : Routine_Tag_Vectors.Vector - renames Routine_Tag_Provider_Type (TP.all).Routine_Tags; - begin - RTags.Append (Key_To_Name (Key)); - Tag := RTags.Last_Index; - end; - else - Tag := No_SC_Tag; - end if; - Routines.Insert (Key, Subprogram_Info'(Exec => Exec, @@ -217,18 +170,7 @@ package body Traces_Names is Padding_Stripped => <>, Insns => Invalid_Binary_Content, Traces => null, - Offset => 0, - Routine_Tag => Tag)); - else - -- If doing routine-based separated coverage analysis, take the tag - -- of the consolidated subprogram. - - Tag := Element (Cur).Routine_Tag; - end if; - - if Tag /= No_SC_Tag then - Misc_Trace.Trace - ("Routine tag" & Tag'Img & ": " & Key_To_Name (Key).all); + Offset => 0)); end if; end Add_Routine; @@ -612,51 +554,6 @@ package body Traces_Names is return False; end Equal; - ------------------------ - -- Get_Slocs_And_Tags -- - ------------------------ - - overriding function Get_Slocs_And_Tags - (TP : access Routine_Tag_Provider_Type; - PC : Pc_Type) return Tagged_Slocs - is - use type Pc_Type; - begin - pragma Assert - (PC in TP.Current_Routine.Insns.First + TP.Current_Routine.Offset - .. TP.Current_Routine.Insns.Last + TP.Current_Routine.Offset); - return Get_Slocs_With_Tag - (TP.Current_Subp.Lines, PC, TP.Current_Routine.Routine_Tag); - end Get_Slocs_And_Tags; - - -------------- - -- Tag_Name -- - -------------- - - overriding function Tag_Name - (TP : access Routine_Tag_Provider_Type; - Tag : SC_Tag) return String - is - begin - return TP.Routine_Tags.Element (Tag).all; - end Tag_Name; - - ------------- - -- Map_Tag -- - ------------- - - overriding function Map_Tag - (TP : access Routine_Tag_Provider_Type; - Relocs : Checkpoints.Checkpoint_Relocations; - CP_Tag : SC_Tag) return SC_Tag - is - pragma Unreferenced (TP, Relocs, CP_Tag); - begin - Fatal_Error ("cannot perform incremental coverage with " - & "routines-based separation"); - return No_SC_Tag; - end Map_Tag; - ---------------------------------- -- Read_Routine_Names_From_Text -- ---------------------------------- diff --git a/tools/gnatcov/traces_names.ads b/tools/gnatcov/traces_names.ads index e98c61184..695a7caa6 100644 --- a/tools/gnatcov/traces_names.ads +++ b/tools/gnatcov/traces_names.ads @@ -22,7 +22,6 @@ with GNATCOLL.Symbols; use GNATCOLL.Symbols; with GNATCOLL.Utils; use GNATCOLL.Utils; with Binary_Files; use Binary_Files; -with Coverage; use Coverage; with Traces; use Traces; with Traces_Dbase; use Traces_Dbase; with Traces_Lines; use Traces_Lines; @@ -82,10 +81,6 @@ package Traces_Names is -- Offset to be added to trace PCs to rebase them for the reference -- code in Insns. Updated each time Add_Code is used to register a new -- instance of the code for this routine. - - Routine_Tag : SC_Tag := No_SC_Tag; - -- Routine tag used when doing source coverage analysis with per-routine - -- tagging. end record; function Key_To_Name (Key : Subprogram_Key) return Cst_String_Access; @@ -197,4 +192,6 @@ package Traces_Names is Consolidation_Error : exception; -- Raised if consolidation is not possible (eg different code for a -- function). + + Current_Routine : Subprogram_Info; end Traces_Names; From a829058d37c57609314c654090416bb73c507b5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 26 May 2025 17:07:29 +0200 Subject: [PATCH 1232/1483] Instrument.Clean_Objdirs: Also remove SID files from the library dir --- .../tests/instr-cov/384-SID-cleanup/lib.gpr | 10 +++++ .../tests/instr-cov/384-SID-cleanup/test.py | 18 ++++++++- tools/gnatcov/instrument-clean_objdirs.adb | 39 ++++++------------- 3 files changed, 39 insertions(+), 28 deletions(-) create mode 100644 testsuite/tests/instr-cov/384-SID-cleanup/lib.gpr diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/lib.gpr b/testsuite/tests/instr-cov/384-SID-cleanup/lib.gpr new file mode 100644 index 000000000..fdd6d1c25 --- /dev/null +++ b/testsuite/tests/instr-cov/384-SID-cleanup/lib.gpr @@ -0,0 +1,10 @@ +library project Lib is + + for Library_Dir use "lib"; + for Object_Dir use "obj_lib"; + for Source_Dirs use (".."); + for Excluded_Source_Files use ("main.adb"); + for Library_Kind use "static"; + for Library_Name use "lib"; + +end Lib; diff --git a/testsuite/tests/instr-cov/384-SID-cleanup/test.py b/testsuite/tests/instr-cov/384-SID-cleanup/test.py index 58c03194b..ba00b219a 100644 --- a/testsuite/tests/instr-cov/384-SID-cleanup/test.py +++ b/testsuite/tests/instr-cov/384-SID-cleanup/test.py @@ -2,6 +2,9 @@ Verify that gnatcov cleans up existing SID files during instrumentation. """ +from e3.fs import cp +import glob + from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir @@ -9,8 +12,14 @@ from SUITE.tutils import contents_of, gprfor Wdir("tmp_") +cp("../lib.gpr", ".") -prj = gprfor(mains=["main.adb"], srcdirs=[".."]) +prj = gprfor( + mains=["main.adb"], + srcdirs=[".."], + deps=["lib.gpr"], + extra='for Source_Files use ("main.adb");', +) expected_cov = { "main.adb.xcov": {"+": {9, 8}}, @@ -64,4 +73,11 @@ actual=contents_of("coverage.log").strip(), ) +# Check that there is indeed no sid file for Pkh +thistest.fail_if_not_equal( + what="Found an SID file for Pkh", + expected=[], + actual=glob.glob("**/pkh.sid"), +) + thistest.result() diff --git a/tools/gnatcov/instrument-clean_objdirs.adb b/tools/gnatcov/instrument-clean_objdirs.adb index 276089fd2..cc38f29f6 100644 --- a/tools/gnatcov/instrument-clean_objdirs.adb +++ b/tools/gnatcov/instrument-clean_objdirs.adb @@ -18,7 +18,6 @@ with Ada.Directories; use Ada.Directories; -with GNATCOLL.VFS; use GNATCOLL.VFS; with GPR2.Path_Name; with Instrument.Common; use Instrument.Common; @@ -31,7 +30,7 @@ procedure Instrument.Clean_Objdirs is -- Callback for Project.Iterate_Projects. If Project is not externally -- built, remove all files from the "$project_name-gnatcov-instr" folder in -- Project's object directory, and remove all files ending in ".sid" from - -- the object directory. + -- the object and library directory, if applicable. function Has_Regular_Files (Directory : String) return Boolean; -- Return whether Directory contains at least one regular file @@ -116,31 +115,17 @@ procedure Instrument.Clean_Objdirs is -- Remove the SID files if any - if Project.Kind in GPR2.With_Object_Dir_Kind then - declare - Obj_Dir : constant GPR2.Path_Name.Object := - Project.Object_Directory; - Obj_Dir_Files : File_Array_Access; - Success : Boolean; - begin - Obj_Dir_Files := - Create (Filesystem_String (Obj_Dir.Value)).Read_Dir (Files_Only); - if Obj_Dir_Files /= null then - for File of Obj_Dir_Files.all loop - if File.File_Extension (Normalize => True) = ".sid" - and then File.Is_Regular_File - then - File.Delete (Success); - if not Success then - Warn - ("Failed to delete old SID file: " - & File.Display_Full_Name); - end if; - end if; - end loop; - Unchecked_Free (Obj_Dir_Files); - end if; - end; + if Project.Kind in GPR2.With_Object_Dir_Kind + and then Project.Object_Directory.Exists + then + Clean_Dir + (Project.Object_Directory.String_Value, Pattern => "*.sid"); + end if; + if Project.Kind in GPR2.Library_Kind + and then Project.Library_Directory.Exists + then + Clean_Dir + (Project.Library_Directory.String_Value, Pattern => "*.sid"); end if; Clean_Objdirs_Trace.Decrease_Indent; From e0a34524740c4a9c630389dc1d1d51c69513c475 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 26 Mar 2025 17:02:58 +0100 Subject: [PATCH 1233/1483] Integrated instrumentation: Add support for cross targets The test added for this relies on the C BSP distributed with gnat, but there are some inconsistencies in the exposed symbols in each BSP. So far, it seems to work ok only for ppc-elf and aarch64-elf, but this is good enough to validate the gnatcov changes. --- testsuite/SUITE/tutils.py | 62 ++++++++++ .../integrated_instr_cross/basic_C/main.c | 15 +++ .../integrated_instr_cross/basic_C/test.opt | 1 + .../integrated_instr_cross/basic_C/test.py | 107 ++++++++++++++++++ .../tests/integrated_instr_cross/extra.opt | 1 + tools/gnatcov/command_line.ads | 6 +- tools/gnatcov/gnatcov_bits_specific.adb | 7 +- tools/gnatcov/instrument-gcc_wrapper.adb | 54 +++++++-- 8 files changed, 236 insertions(+), 17 deletions(-) create mode 100644 testsuite/tests/integrated_instr_cross/basic_C/main.c create mode 100644 testsuite/tests/integrated_instr_cross/basic_C/test.opt create mode 100644 testsuite/tests/integrated_instr_cross/basic_C/test.py create mode 100644 testsuite/tests/integrated_instr_cross/extra.opt diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 1743eb215..52b47a609 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -1421,3 +1421,65 @@ def generate_annotations(annotations, subdir="", tolerate_messages=None): tolerate_messages=tolerate_messages, ) return annot_file + + +def driver_for_lang(lang: str) -> str | None: + """ + Inspect the contents of suite.cgpr to determine what the compiler driver + for the given language is. lang is case sensitive. This returns None if + the driver was not found. + """ + driver_match = re.search( + r'for Driver *\("' + lang + r'"\) use "(.*)";', + contents_of(os.path.join(ROOT_DIR, "suite.cgpr")), + ) + + return driver_match.group(1) if driver_match else None + + +# Mapping from the CPU name to the C BSP example in the gnat installation tree +BSP_MAP = { + "zynqmp": "zcu102", + "stm32f4": "stm32f429disco", + "leon3": "leon3", + "mpc8641": "mpc8641", +} + + +def bsp_project(cpu): + """ + Return the name of the bsp project (without extension) for the given cpu + """ + return BSP_MAP.get(cpu, None) + + +def get_c_bsp(rts, destdir): + """ + Build & install the C BSP project that is shipped with gnat. The BSP + exposes a subset of stdio that can be used to dump traces. + + RTS is used to locate the correct BSP, we assume that: + - RTS is of the form - + - in the gnat installation tree there is a /share/examples/gnat-c/ directory, in which there is a + bsp_map[].gpr project (see above for bsp_map). + + This function will copy destdir, and return the name of the project. + """ + + cpu_name = rts.split("-")[-1] + + thistest.fail_if( + not cpu_name, + f"Could not deduce CPU name from RTS: {rts}", + ) + + gcc = driver_for_lang("C") + thistest.fail_if(not gcc, "Could not locate gcc executable") + + bsp_original_location = os.path.join( + os.path.dirname(gcc), "..", "share", "examples", "gnat-c", cpu_name + ) + cp(os.path.join(bsp_original_location, "*"), destdir, recursive=True) + + return bsp_project(cpu_name) diff --git a/testsuite/tests/integrated_instr_cross/basic_C/main.c b/testsuite/tests/integrated_instr_cross/basic_C/main.c new file mode 100644 index 000000000..10cdcd956 --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/basic_C/main.c @@ -0,0 +1,15 @@ +#include +#include + +int +main () +{ + bool all_good = true; + bool all_good_really = true; + printf ("Hello "); + if (all_good && all_good_really) + printf ("world!\n"); + else + printf ("... actually no"); + return 0; +} diff --git a/testsuite/tests/integrated_instr_cross/basic_C/test.opt b/testsuite/tests/integrated_instr_cross/basic_C/test.opt new file mode 100644 index 000000000..1bcfeb91b --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/basic_C/test.opt @@ -0,0 +1 @@ +!ppc-elf XFAIL there are various issues with the other BSPs diff --git a/testsuite/tests/integrated_instr_cross/basic_C/test.py b/testsuite/tests/integrated_instr_cross/basic_C/test.py new file mode 100644 index 000000000..e7fba5293 --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/basic_C/test.py @@ -0,0 +1,107 @@ +""" +Simple sanity check test for integrated instrumentation for cross targets +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env, GPRBUILD +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import ( + get_c_bsp, + cmdrun, + driver_for_lang, + run_cov_program, + thistest, + xcov, +) + +Wdir("tmp_") + +# We need to setup the coverage runtime with no Ada support as otherwise we'll +# get undefined references to GNAT.IO + +gcvrt_prefix = "gcvrt" +xcov(["setup", f"--prefix={gcvrt_prefix}", "--restricted-to-languages=C"]) +env.add_search_path( + "GPR_PROJECT_PATH", + os.path.join(gcvrt_prefix, "share", "gpr"), +) + +cwd = os.getcwd() + +cp("../main.c", ".") + +# Build the C BSP +bsp_root = "bsp_root" +bsp_prj_name = get_c_bsp(thistest.options.RTS, bsp_root) + +bsp_prj = os.path.join(bsp_root, f"{bsp_prj_name}.gpr") + +# Generate a simple project +main_prj = "prj.gpr" +with open(main_prj, "w") as prj_file: + print(f'with "{bsp_prj}";', file=prj_file) + print("project Prj is", file=prj_file) + print( + f' for Target use "{thistest.env.target.platform}";', + file=prj_file, + ) + print(' for Languages use ("C");', file=prj_file) + print(' for Source_Dirs use (".");', file=prj_file) + print(' for Main use ("main.c");', file=prj_file) + print(' for Object_Dir use "obj";', file=prj_file) + print( + f" package Compiler renames {bsp_prj_name}.Compiler;", + file=prj_file, + ) + print(" package Linker is", file=prj_file) + print( + f' for Switches ("C") use {bsp_prj_name}.Linker_Switches;', + file=prj_file, + ) + print(" end Linker;", file=prj_file) + print("end Prj;", file=prj_file) + +# Setup the integrated instrumentation +compiler = driver_for_lang("C") +gnatcov_artifact_dir = "gcv_artifacts" +xcov( + [ + "setup-integration", + "--level=stmt+mcdc", + f"--files={os.path.join(cwd, 'main.c')}", + f"--compilers={os.path.basename(compiler)}", + f"--output-dir={gnatcov_artifact_dir}", + ] +) +env.add_path(gnatcov_artifact_dir) + +# Build our simple C main and execute it +cmdrun([GPRBUILD, "-P", main_prj], for_pgm=False) +run_log = "run.log" +run_cov_program("./obj/main", out=run_log) + +trace_name = "main.srctrace" +xcov(["extract-base64-trace", run_log, trace_name]) +xcov( + [ + "coverage", + "--sid", + os.path.join(gnatcov_artifact_dir, "main.c.sid"), + "-axcov", + "-cstmt+mcdc", + trace_name, + ] +) +check_xcov_reports( + reports_dir=".", + expected_cov={ + "main.c.xcov": {"+": {7, 8, 9, 11, 14}, "!": {10}, "-": {13}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/integrated_instr_cross/extra.opt b/testsuite/tests/integrated_instr_cross/extra.opt new file mode 100644 index 000000000..a69bb239b --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/extra.opt @@ -0,0 +1 @@ +native DEAD test meant specifically for cross targets diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 90099f044..7f607a91a 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -770,8 +770,7 @@ package Command_Line is & " ""Target""/""Runtime"" attributes. It is also" & " needed for ""run"" commands without a project" & " file.", - Commands => (Cmd_Print_GPR_Registry - | Cmd_Setup_Integration => False, + Commands => (Cmd_Print_GPR_Registry => False, others => True), At_Most_Once => True, Internal => False), @@ -782,8 +781,7 @@ package Command_Line is & " to build the analyzed programs. If project files" & " don't already set the runtime, this is required" & " for correct project files processing.", - Commands => (Cmd_Print_GPR_Registry - | Cmd_Setup_Integration => False, + Commands => (Cmd_Print_GPR_Registry => False, others => True), At_Most_Once => True, Internal => False), diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 6b6f89148..07c7254ca 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1471,8 +1471,11 @@ begin Value (Args, Opt_Runtime_Project, "gnatcov_rts"); Setup_Cfg : constant Setup_Config := Load - (Target => "", - RTS => "", + (Target => + (if Switches.Target_Family /= null + then Switches.Target_Family.all + else ""), + RTS => Value (Args, Opt_Runtime), Config_File => Value (Args, Opt_Config), Runtime_Project => Runtime_Project); -- TODO??? We should not leave the target and runtime empty, but diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 22ec40ae4..688a6ba20 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -1083,6 +1083,8 @@ begin -- Add the coverage buffers symbols referenced in the Symbol_File -- to Buffer_Symbols. + procedure Inspect_Dynamic_Deps; + --------------------------------- -- Add_Coverage_Buffer_Symbols -- --------------------------------- @@ -1098,30 +1100,50 @@ begin Config => Instr_Config)); end Add_Coverage_Buffer_Symbols; - begin - -- Grab the buffer symbols in the link closure - - Add_Coverage_Buffer_Symbols (Comp_DB.Link_Command.Target); - - -- Get the buffer symbols in the dynamic libraries the executable - -- depends on. + -------------------------- + -- Inspect_Dynamic_Deps -- + -------------------------- - declare + procedure Inspect_Dynamic_Deps is Args : String_Vectors.Vector; Ldd_Filename : constant String := (+Prj.Output_Dir) / ("ldd_" & Filename_Slug (+Comp_DB.Link_Command.Target.Full_Name)); Ldd_File : File_Type; + Success : Boolean; begin Args.Append (+(+Comp_DB.Link_Command.Target.Full_Name)); - Run_Command + Success := Run_Command (Command => +"ldd", Arguments => Args, Origin_Command_Name => "compiler wrapper", - Output_File => Ldd_Filename); + Output_File => Ldd_Filename, + Ignore_Error => True); Open (Ldd_File, In_File, Ldd_Filename); + if not Success then + + if Ada.Strings.Fixed.Trim + (Get_Line (Ldd_File), Ada.Strings.Both) /= + "not a dynamic executable" + then + -- The executable does not depend on any dynamic library, + -- nothing to do here. + + Close (Ldd_File); + return; + end if; + + -- Otherwise, something went wrong in the ldd call, abort. + + Close (Ldd_File); + Outputs.Fatal_Error + ("Error while running LDD on the instrumented executable"); + end if; + + -- Inspect the output of lld to find the dependencies + while not End_Of_File (Ldd_File) loop declare use Ada.Strings.Fixed; @@ -1171,7 +1193,17 @@ begin end; end loop; Close (Ldd_File); - end; + end Inspect_Dynamic_Deps; + + begin + -- Grab the buffer symbols in the link closure + + Add_Coverage_Buffer_Symbols (Comp_DB.Link_Command.Target); + + -- Get the buffer symbols in the dynamic libraries the executable + -- depends on. + + Inspect_Dynamic_Deps; -- Generate the actual buffers unit list From b3cd84ad8f7545fa1cab85114eb2b8ef8b40de3d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 30 May 2025 09:16:04 +0000 Subject: [PATCH 1234/1483] integrated_instr_cross/basic_C: add missing BSP root dir creation It is necessary to create the target directory before calling `e3.fs.cp`. --- testsuite/tests/integrated_instr_cross/basic_C/test.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/integrated_instr_cross/basic_C/test.py b/testsuite/tests/integrated_instr_cross/basic_C/test.py index e7fba5293..560ac9dfc 100644 --- a/testsuite/tests/integrated_instr_cross/basic_C/test.py +++ b/testsuite/tests/integrated_instr_cross/basic_C/test.py @@ -5,7 +5,7 @@ import os import os.path -from e3.fs import cp +from e3.fs import cp, mkdir from SUITE.control import env, GPRBUILD from SUITE.cutils import Wdir @@ -37,6 +37,7 @@ # Build the C BSP bsp_root = "bsp_root" +mkdir(bsp_root) bsp_prj_name = get_c_bsp(thistest.options.RTS, bsp_root) bsp_prj = os.path.join(bsp_root, f"{bsp_prj_name}.gpr") From 7ebbffd6fc56f7e2fc83c68d0f9c19e7246c4e15 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 2 Jun 2025 14:21:07 +0000 Subject: [PATCH 1235/1483] Instrument.Gcc_Wrapper: close files when done with them On Windows, leaving files open makes it impossible to remove them. Leaving the commands text file open thus prevents the cleanup of the temporary directory. --- tools/gnatcov/instrument-gcc_wrapper.adb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 688a6ba20..dcb9ced53 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -376,6 +376,7 @@ is -- that's not the case, error out. if Parsed_Link_Command then + Close (Commands_File); Outputs.Fatal_Error ("The compiler driver invocation yielded several link" & " commands, which is not supported"); @@ -387,6 +388,7 @@ is <> end; end loop; + Close (Commands_File); end; return Result; end Parse_Compiler_Driver_Command; From 16f3a54ccc4d8a8471469f7cf3260a535c4bd143 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 2 Jun 2025 14:56:41 +0000 Subject: [PATCH 1236/1483] setup-integration: fix the GCC wrapper basename on Windows It is called "compiler_wrappers-gcc.exe" on that platform (the `.exe` part was missing so far). --- tools/gnatcov/files_handling.adb | 16 ++++++++++++++++ tools/gnatcov/files_handling.ads | 4 ++++ tools/gnatcov/instrument-setup_config.adb | 7 +++++-- 3 files changed, 25 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/files_handling.adb b/tools/gnatcov/files_handling.adb index 884a95b3f..730d2aa47 100644 --- a/tools/gnatcov/files_handling.adb +++ b/tools/gnatcov/files_handling.adb @@ -16,8 +16,24 @@ -- of the license. -- ------------------------------------------------------------------------------ +with GNAT.OS_Lib; + package body Files_Handling is + ----------------------- + -- Executable_Suffix -- + ----------------------- + + function Executable_Suffix return String is + use GNAT.OS_Lib; + + Value : String_Access := Get_Executable_Suffix; + begin + return Result : constant String := Value.all do + Free (Value); + end return; + end Executable_Suffix; + ----------------------- -- Create_Normalized -- ----------------------- diff --git a/tools/gnatcov/files_handling.ads b/tools/gnatcov/files_handling.ads index e825748a1..ac0ed4d62 100644 --- a/tools/gnatcov/files_handling.ads +++ b/tools/gnatcov/files_handling.ads @@ -27,6 +27,10 @@ with Strings; use Strings; package Files_Handling is + function Executable_Suffix return String; + -- Wrapper around GNAT.OS_Lib.Get_Executable_Suffix to return the string + -- by-value. + function Create_Normalized (Filename : String) return Virtual_File; -- Wrapper around GNATCOLL.VFS.Create_From_Base, that normalizes by -- default the Virtual_File. diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index 96674dcb9..d677261c7 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -122,6 +122,7 @@ package body Instrument.Setup_Config is Nms : constant JSON_Value := Create_Object; -- For each compiler driver, location of the nm executable + Exec_Suffix : constant String := Executable_Suffix; begin -- Find the installed coverage runtime, using gprls. TODO??? Deal with -- cross cases. @@ -252,8 +253,10 @@ package body Instrument.Setup_Config is end; GNAT.OS_Lib.Copy_File - (Support_Files.Libexec_Dir - / ("compiler_wrappers-" & (+Compiler_Identifier)), + (Name => Support_Files.Libexec_Dir + / ("compiler_wrappers-" + & (+Compiler_Identifier) + & Exec_Suffix), Pathname => Output_Dir / (+Compiler_Driver), Success => Success, Mode => GNAT.OS_Lib.Overwrite, From b00e8f98f2783cfdf190c7d2d6b7f60fcb12b418 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 2 Jun 2025 14:58:41 +0000 Subject: [PATCH 1237/1483] gcc-wrapper: fix toolchain exec basenames on Windows Add the `.exe` suffix to the `cc1`/`cc1plus`/`as`/`collect2` executable names on that plaform to reflect their actual name on the filesystem and in analyzed logs. --- tools/gnatcov/instrument-gcc_wrapper.adb | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index dcb9ced53..694f128bc 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -52,6 +52,14 @@ is Compiler_Exec_Basename : constant Unbounded_String := +Simple_Name (Compiler_Exec); + -- Host-dependent names for toolchain executables + + Exec_Suffix : constant String := Executable_Suffix; + Cc1_Name : constant String := "cc1" & Exec_Suffix; + Cc1plus_Name : constant String := "cc1plus" & Exec_Suffix; + As_Name : constant String := "as" & Exec_Suffix; + Collect2_Name : constant String := "collect2" & Exec_Suffix; + type Compilation_Command_Type is record Language : Any_Language; -- Language of the file that is compiled @@ -350,8 +358,8 @@ is if Line = "" then goto Continue; end if; - if Ends_With (Command.First_Element, "cc1") - or else Ends_With (Command.First_Element, "cc1plus") + if Ends_With (Command.First_Element, Cc1_Name) + or else Ends_With (Command.First_Element, Cc1plus_Name) then declare CC_Command : constant Compilation_Command_Type := @@ -361,7 +369,7 @@ is Result.Compilation_Commands.Append (CC_Command); end if; end; - elsif Ends_With (Command.First_Element, "as") then + elsif Ends_With (Command.First_Element, As_Name) then declare As_Command : constant Assembly_Command_Type := Parse_Assembly_Command (Context, Command); @@ -370,7 +378,7 @@ is Result.Assembly_Commands.Append (As_Command); end if; end; - elsif Ends_With (Command.First_Element, "collect2") then + elsif Ends_With (Command.First_Element, Collect2_Name) then -- Assume that we can only have a single link command. If -- that's not the case, error out. @@ -411,9 +419,9 @@ is Result : Compilation_Command_Type; Cur : Cursor := First (Command); begin - if Ends_With (Command.First_Element, "cc1plus") then + if Ends_With (Command.First_Element, Cc1plus_Name) then Result.Language := CPP_Language; - elsif Ends_With (Command.First_Element, "cc1") then + elsif Ends_With (Command.First_Element, Cc1_Name) then Result.Language := C_Language; else -- Unreachable code. Parse_Compilation_Command is always called with From ed133d5cd6fd5ff61717b772bd6f10116516919b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 2 Jun 2025 15:01:38 +0000 Subject: [PATCH 1238/1483] gcc-wrapper: use full basename as key to fetch the `nm` executable In the instrumenatation configuration maps, toolchain executables are indexed by compiler basename with extension (`Ada.Directories.Simple_Name`, not `.Base_Name`). On Unix systems, both are the same (`gcc`, `powerpc-elf-gcc`, ...), but on Windows hosts, compiler executables have the`.exe` suffix, so the difference matters. --- tools/gnatcov/instrument-gcc_wrapper.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 694f128bc..c8376622d 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -599,7 +599,7 @@ is Args.Append (Full_Name (Symbol_File)); Run_Command (Command => - +Config.Nms.Element (+Base_Name (Compiler_Driver)), + +Config.Nms.Element (+Simple_Name (Compiler_Driver)), Arguments => Args, Origin_Command_Name => "compiler wrapper", Output_File => Output_Filename); From e5726725a627bb30b26edead3d52c4e3ee3ccb23 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 2 Jun 2025 15:11:52 +0000 Subject: [PATCH 1239/1483] gcc-wrapper: do not crash on args that are invalid filenames on Windows --- tools/gnatcov/instrument-gcc_wrapper.adb | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index c8376622d..333fb76f3 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -948,8 +948,22 @@ begin for I in 0 .. Natural (String_Vectors.Length (New_Args) - 1) loop declare Arg : constant Unbounded_String := New_Args.Element (I); + + -- In order to check if Arg designates an existing file, get ready + -- for Name_Error exceptions on Windows, as Ada.Directories.Exists + -- will raise this exception on this platform when Arg is not a + -- correctly formatted path, which is the case for most arguments + -- (e.g. -I). + + Exists : Boolean; begin - if Ada.Directories.Exists (+Arg) then + begin + Exists := Ada.Directories.Exists (+Arg); + exception + when Ada.Directories.Name_Error => + Exists := False; + end; + if Exists then declare Base : constant String := Simple_Name (+Arg); Fullname : constant String := Full_Name (+Arg); From 59cc25308d545d118fbd40ddd7ca065ff12a356f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 5 Jun 2025 14:54:32 +0000 Subject: [PATCH 1240/1483] doc/gnatcov/integrated_instr.rst: minor editoral fixes --- doc/conf.py | 1 + doc/gnatcov/integrated_instr.rst | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 14 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index e5a546b20..668ac9602 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -69,6 +69,7 @@ .. |gcvrun| replace:: :command:`gnatcov` :command:`run` .. |gcvcov| replace:: :command:`gnatcov` :command:`coverage` .. |gcvstp| replace:: :command:`gnatcov` :command:`setup` +.. |gcvsti| replace:: :command:`gnatcov` :command:`setup-integration` .. |gcvins| replace:: :command:`gnatcov` :command:`instrument` .. |gcvxtr| replace:: :command:`gnatcov` :command:`extract-base64-trace` .. |gcvcnv| replace:: :command:`gnatcov` :command:`convert` diff --git a/doc/gnatcov/integrated_instr.rst b/doc/gnatcov/integrated_instr.rst index 9ab1081e6..44f451ccf 100644 --- a/doc/gnatcov/integrated_instr.rst +++ b/doc/gnatcov/integrated_instr.rst @@ -12,8 +12,8 @@ build systems so far. As with the workflow involving a separate instrumentation, a :term:`coverage runtime ` to be used by the instrumented code needs to be setup as a required prerequisite. Refer to the :ref:`instr-rts` section of this -manual for a description of this step. The installed instrumentation runtime -must be visible on the ``GPR_PROJECT_PATH``. +manual for a description of this step. The installed coverage runtime must be +visible on the ``GPR_PROJECT_PATH``. Then the process essentially goes like: @@ -31,11 +31,11 @@ environment (e.g. the path for the original compiler) changes. Specifying instrumentation switches =================================== -The user specifies the switches through the ``gnatcov setup-integration`` -command, which accepts any option accepted by ``gnatcov instrument``, except the -ones using project mechanisms to filter out units of interest: ``--units`` and -``--projects``. Refer to :ref:`src_traces` for more information regarding the -source instrumentation specific switches. +The user specifies the switches through the |gcvsti| command, which accepts any +option accepted by |gcvins|, except the ones using project mechanisms to filter +out units of interest: ``--units`` and ``--projects``. Refer to +:ref:`src_traces` for more information regarding the source instrumentation +specific switches. As there is no project acting as a units of interest provider, the user must explicitly pass files of interest through the ``--files`` switch, which expects @@ -66,9 +66,9 @@ The sources for the following example can be found under the ``share/examples/gnatcoverage/doc/integrated`` directory of the GNATDAS distribution. -The following considers that the instrumentation runtime was previously -installed with ``gnatcov setup``, and that the ``GPR_PROJECT_PATH`` variable -contains its installed location. See :ref:`instr-rts`. +The following considers that the coverage runtime was previously installed with +|gcvstp|, and that the ``GPR_PROJECT_PATH`` variable contains its installed +location. See :ref:`instr-rts`. Let's consider a simple ``main.cpp`` file: @@ -110,7 +110,7 @@ on the path: make This will produce an instrumented executable, that will produce a source trace -when run, that can be analyzed with ``gnatcov coverage``. +when run, that can be analyzed with |gcvstp|. A simple CMake example ====================== @@ -121,8 +121,8 @@ distribution. To ensure that the Makefile provided with the example sources uses CMake as a build system, specify ``BUILD_SYSTEM=CMake`` on the `make` invocation. -The following considers that the instrumentation runtime was installed through -the use of ``gnatcov setup``. +The following considers that the coverage runtime was installed through the use +of |gcvstp|. Let's consider a simple ``main.cpp`` file @@ -166,4 +166,4 @@ directory: The default generator for CMake is "Unix Makefiles", so we can then run the build process with ``make``, and our executable which will produce a source trace -that can be analyzed by ``gnatcov coverage``. +that can be analyzed by |gcvcov|. From a328f434dae800b75866ae7c776c4f692cbd0f5b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 5 Jun 2025 14:55:17 +0000 Subject: [PATCH 1241/1483] doc/gnatcov/integrated_instr.rst: clarify for absent Ada toolchains --- doc/gnatcov/integrated_instr.rst | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/gnatcov/integrated_instr.rst b/doc/gnatcov/integrated_instr.rst index 44f451ccf..8b7b03550 100644 --- a/doc/gnatcov/integrated_instr.rst +++ b/doc/gnatcov/integrated_instr.rst @@ -13,7 +13,14 @@ As with the workflow involving a separate instrumentation, a :term:`coverage runtime ` to be used by the instrumented code needs to be setup as a required prerequisite. Refer to the :ref:`instr-rts` section of this manual for a description of this step. The installed coverage runtime must be -visible on the ``GPR_PROJECT_PATH``. +visible on the ``GPR_PROJECT_PATH``. Note that, by default, |gcvstp| sets up +the coverage runtime for Ada and C/C++. If no Ada toolchain is available, its +support should be explicitly disabled. For instance: + +.. code-block:: sh + + gnatcov setup --restricted-to-languages=C,C++ --prefix=/usr/custom + export GPR_PROJECT_PATH=$GPR_PROJECT_PATH:/usr/custom/share/gpr Then the process essentially goes like: From 2662a4cf0cebe4207989442a45b535613d1fef26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 11 Jun 2025 11:25:11 +0200 Subject: [PATCH 1242/1483] Work around gpr2clean behavior change Some discussions are still ongoing as to whether gpr2clean should delete or not sid files. In the meantime, move the gprclean invocation before the gnatcov instrument invocation. This patch may be reverted if the previous behavior of gprclean is restored. --- testsuite/SCOV/instr.py | 17 ++++++++++++++++- testsuite/SUITE/tutils.py | 20 ++++++++++++++++++-- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index 850c274d8..eeb5ea816 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -9,7 +9,13 @@ from SUITE.context import thistest from SUITE.control import env from SUITE.cutils import contents_of, ext, copy_to_dir -from SUITE.tutils import RUNTIME_INFO, GNATCOV_INFO, locate_gpr_file, xcov +from SUITE.tutils import ( + RUNTIME_INFO, + GNATCOV_INFO, + gpr_common_args, + locate_gpr_file, + xcov, +) def default_dump_trigger(mains): @@ -136,6 +142,15 @@ def xcov_instrument( if thistest.options.block: args.append("--instrument-block") + # TODO (gpr-issues#241) temporary workaround. + # Since gpr2clean deletes .sid files for the moment, we need to + # clean the project before instrumenting (this used to be done before the + # invocation of gprbuild). + thistest.cleanup( + gprsw.root_project, + gpr_common_args(gprsw.root_project, auto_config_args), + ) + # When no message is to be tolerated, fallback to an actual regexp # that will never match: re_tolerate_messages = tolerate_messages or "" diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 52b47a609..f2666b5ac 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -139,6 +139,17 @@ def run_and_log(*args, **kwargs): return p +def effective_trace_mode(override_trace_mode): + """ + Compute the effective trace mode to be used from override_trace_mode + if available, or from the testsuite options otherwise. + """ + if override_trace_mode is None: + return thistest.options.trace_mode + else: + return override_trace_mode + + def gprbuild_gargs_with(thisgargs, trace_mode=None, runtime_project=None): """ Compute and return all the toplevel gprbuild arguments to pass. Account for @@ -150,7 +161,7 @@ def gprbuild_gargs_with(thisgargs, trace_mode=None, runtime_project=None): If RUNTIME_PROJECT is not null, it will be used as the name of the instrumentation runtime project in source trace mode. """ - trace_mode = trace_mode or thistest.options.trace_mode + trace_mode = effective_trace_mode(trace_mode) # Force a few bits useful for practical reasons and without influence on # code generation @@ -342,7 +353,12 @@ def gprbuild( common_args = gpr_common_args(project, auto_config_args) # Now cleanup, do build and check status - thistest.cleanup(project, common_args) + + # TODO (gpr-issues#241) Temporary workaround for the gprclean problem + # As gpr2clean currently deletes .sid files, we should not call + # gprclean between the instrumentation and the build. + if effective_trace_mode(trace_mode) == "bin": + thistest.cleanup(project, common_args) # lookup the hook for the executable name without extension builder = thistest.suite_gprpgm_for( From 84843be2380ef0349b0c50cd103d99347e8f1f08 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 3 Jun 2025 08:36:16 +0000 Subject: [PATCH 1243/1483] RTS: make all Ada units preelaborated Since pure units are implicitly preelaborated, there is no need to add `pragma Preelaborate;` to them. --- tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads | 2 ++ tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.ads | 2 ++ tools/gnatcov/ada-rts/gnatcov_rts-traces-output-text_io.ads | 2 ++ tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads | 2 ++ tools/gnatcov/ada-rts/gnatcov_rts-traces.ads | 2 ++ tools/gnatcov/rts/gnatcov_rts-base_io.ads | 2 ++ tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads | 2 ++ tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads | 2 ++ 8 files changed, 16 insertions(+) diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads index a3d3dbda9..051048cd0 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.ads @@ -26,6 +26,8 @@ package GNATcov_RTS.Traces.Output.Base64 is + pragma Preelaborate; + procedure Write_Trace_File (Buffers_Groups : Coverage_Buffers_Group_Array; Program_Name : String; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.ads index c84b49590..b31751672 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-bytes_io.ads @@ -40,6 +40,8 @@ with GNAT.OS_Lib; private package GNATcov_RTS.Traces.Output.Bytes_IO is + pragma Preelaborate; + package OSLIB renames GNAT.OS_Lib; use type OSLIB.File_Descriptor; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-text_io.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-text_io.ads index df45056f8..e5f9bd6b2 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-text_io.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-text_io.ads @@ -39,6 +39,8 @@ with GNAT.IO; private package GNATcov_RTS.Traces.Output.Text_IO is + pragma Preelaborate; + procedure New_Line (N : Positive := 1) renames GNAT.IO.New_Line; procedure Put (S : String) renames GNAT.IO.Put; procedure Put_Line (S : String) renames GNAT.IO.Put_Line; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads index fcbe14c73..af15fc85a 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads @@ -28,6 +28,8 @@ with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; package GNATcov_RTS.Traces.Output is + pragma Preelaborate; + subtype Serialized_Timestamp is String (1 .. 8); -- Little-endian 64-bit unsigned integer. Represents a date/time as the -- number of seconds that passed since the Unix Epoch. In other words, a diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads index 1f73839f8..51a1de424 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads @@ -32,6 +32,8 @@ with GNATcov_RTS.Buffers; use GNATcov_RTS.Buffers; package GNATcov_RTS.Traces is + pragma Preelaborate; + type Uint8_Array is array (Positive range <>) of Interfaces.Unsigned_8; pragma Pack (Uint8_Array); diff --git a/tools/gnatcov/rts/gnatcov_rts-base_io.ads b/tools/gnatcov/rts/gnatcov_rts-base_io.ads index 591cc051e..0ab8c83ee 100644 --- a/tools/gnatcov/rts/gnatcov_rts-base_io.ads +++ b/tools/gnatcov/rts/gnatcov_rts-base_io.ads @@ -28,6 +28,8 @@ with GNATcov_RTS.Strings; use GNATcov_RTS.Strings; package GNATcov_RTS.Base_IO is + pragma Preelaborate; + -- See the comment in gnatcov_rts_c-base_io.h for more information about -- this package. diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads index fcd11d2c6..8b3f63737 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads @@ -29,6 +29,8 @@ with GNATcov_RTS.Types; use GNATcov_RTS.Types; package GNATcov_RTS.Traces.Output.Base64 is + pragma Preelaborate; + procedure Write_Trace_File (Buffers_Groups : Coverage_Buffers_Group_Array; Program_Name : String; diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads index cd46d2721..2128d8c80 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads @@ -31,6 +31,8 @@ with GNATcov_RTS.Buffers.Lists; use GNATcov_RTS.Buffers.Lists; package GNATcov_RTS.Traces.Output.Files is + pragma Preelaborate; + type Time is new Interfaces.Unsigned_64; -- Derived type to represent timestamps (as a number of seconds elapsed) From 42db48d0550fb2bf8d0c33b3cb287343849912bb Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 3 Jun 2025 09:11:18 +0000 Subject: [PATCH 1244/1483] Add support for coverage state reset/dump from preelaborated units --- .../instr-cov/preelaborated_units/main.adb | 11 ++++++ .../instr-cov/preelaborated_units/pkg.adb | 34 +++++++++++++++++++ .../instr-cov/preelaborated_units/pkg.ads | 9 +++++ .../instr-cov/preelaborated_units/test.py | 34 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 6 ++++ 5 files changed, 94 insertions(+) create mode 100644 testsuite/tests/instr-cov/preelaborated_units/main.adb create mode 100644 testsuite/tests/instr-cov/preelaborated_units/pkg.adb create mode 100644 testsuite/tests/instr-cov/preelaborated_units/pkg.ads create mode 100644 testsuite/tests/instr-cov/preelaborated_units/test.py diff --git a/testsuite/tests/instr-cov/preelaborated_units/main.adb b/testsuite/tests/instr-cov/preelaborated_units/main.adb new file mode 100644 index 000000000..a93934020 --- /dev/null +++ b/testsuite/tests/instr-cov/preelaborated_units/main.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Pkg; use Pkg; + +procedure Main is +begin + Put_Line ("Fact (1) = " & Integer'Image (Pkg.Fact (1))); + Pkg.Reset_Coverage; + Put_Line ("Fact (0) = " & Integer'Image (Pkg.Fact (0))); + Pkg.Dump_Coverage; +end Main; diff --git a/testsuite/tests/instr-cov/preelaborated_units/pkg.adb b/testsuite/tests/instr-cov/preelaborated_units/pkg.adb new file mode 100644 index 000000000..95292e23d --- /dev/null +++ b/testsuite/tests/instr-cov/preelaborated_units/pkg.adb @@ -0,0 +1,34 @@ +package body Pkg is + + -------------------- + -- Reset_Coverage -- + -------------------- + + procedure Reset_Coverage is + begin + pragma Annotate (Xcov, Reset_Buffers); + end Reset_Coverage; + + ------------------- + -- Dump_Coverage -- + ------------------- + + procedure Dump_Coverage is + begin + pragma Annotate (Xcov, Dump_Buffers); + end Dump_Coverage; + + ---------- + -- Fact -- + ---------- + + function Fact (I : Integer) return Integer is + begin + if I < 2 then + return 1; + else + return I * Fact (I - 1); + end if; + end Fact; + +end Pkg; diff --git a/testsuite/tests/instr-cov/preelaborated_units/pkg.ads b/testsuite/tests/instr-cov/preelaborated_units/pkg.ads new file mode 100644 index 000000000..c4dfb4fdf --- /dev/null +++ b/testsuite/tests/instr-cov/preelaborated_units/pkg.ads @@ -0,0 +1,9 @@ +package Pkg is + + pragma Preelaborate; + + procedure Reset_Coverage; + procedure Dump_Coverage; + function Fact (I : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/instr-cov/preelaborated_units/test.py b/testsuite/tests/instr-cov/preelaborated_units/test.py new file mode 100644 index 000000000..ecae16f6f --- /dev/null +++ b/testsuite/tests/instr-cov/preelaborated_units/test.py @@ -0,0 +1,34 @@ +""" +Check that we can compute code coverage for preelaborated units and reset/dump +coverage state from them. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + dump_trigger="manual", + manual_prj_name="gen", + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {9, 10}, "-": {7, 8}}, + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {27, 28}, "-": {30}}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index d1c0b0b41..bdfbd9089 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -10809,6 +10809,12 @@ package body Instrument.Ada_Unit is File.Put_Line ("package " & Helper_Unit_Name & " is"); File.New_Line; + -- Make this unit preelaborated, so that it is possible to reset/dump + -- coverage state from preelaborated units. + + File.Put_Line (" pragma Preelaborate;"); + File.New_Line; + -- Do not generate routines to deal with streaming attributes in this -- helper unit: we do not need them, and they can bring in the -- secondary stack, which may in turn violate the No_Secondary_Stack From 9ed7817cd3eaf6b9e605e5027b011005d1cd805d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 5 Jun 2025 13:54:26 +0000 Subject: [PATCH 1245/1483] User's Guide: document how to handle elaboration in custom cvg. runtimes --- doc/gnatcov/src_traces.rst | 102 +++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index ca9f873c5..ca5c57b7a 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -1305,6 +1305,108 @@ file so that it implements the interface described in the (unmodified) size_t length; }; +When the customized runtime needs elaboration +--------------------------------------------- + +Ada units in the coverage runtime are all required to be either pure or +preelaborated (``pragma Pure;`` or ``pragma Preelaborate;``). This requirement +is essential for the instrumenter to generate compilable code for manual +reset/dump of coverage buffers in instrumented Ada units that are themselves +preelaborated: these units will need to have the coverage runtime in their +closure, and it is illegal for a preelaborated unit to have in its closure a +unit that is not either preelaborated or pure. + +This requirement is however impractical in some cases: for instance, on some +targets, coverage buffers may need to be dumped on a custom stream that needs +to be initialized at elaboration time: running initialization code during the +elaboration of the coverage runtime would be handy, but it unfortunately +violates the preelaborated requirement mentionned above. + +Ultimately, it is necessary for this case to work around compiler-enforced +elaboration constraints using interfacing pragmas (``pragma Import``/``pragma +Export``). Assuming that the IO handling code is self-contained and is already +present in the closure of the project to analyze, the following example +demonstrates how to handle this case. + +First, move the IO handling code to an independent library project: + +.. code-block:: ada + + -- stateful_io.gpr + library project Stateful_IO is + type Any_Library_Type is ("static", "relocatable", "static-pic"); + Library_Type : Any_Library_Type := external ("LIBRARY_TYPE", "static"); + + for Library_Name use "stateful_io"; + for Library_Kind use Library_Type; + for Library_Dir use "lib." & Library_Type; + for Object_Dir use "obj." & Library_Type; + end Stateful_IO; + + -- stateful_io.ads + package Stateful_IO is + procedure Put (S : String); + pragma Export (Ada, Put, "stateful_io_put"); + end Stateful_IO;package Stateful_IO is + + -- stateful_io.adb + with GNAT.IO; + + package body Stateful_IO is + + -- Since we are short-circuiting the Ada compiler's elaboration checks, + -- preserve a manual guard to detect attempts to send data to the IO + -- channel before elaboration has occurred. + + Initialized : Boolean := False; + + procedure Put (S : String) is + begin + if not Initialized then + raise Program_Error with + "attempt to call Stateful_IO.Put before elaboration"; + end if; + + -- Replace the following with the actual code to send data to the IO + -- stream used by coverage data. + + GNAT.IO.Put (S); + end Put; + + begin + -- Here, do whatever necessary to initialize the IO stream + + Initialized := True; + end Stateful_IO; + +Then, bind this code (non preelaborated) to the customized coverage runtime +(``my_rts.gpr`` as in the previous section, preelaborated) using the +interfacing pragmas: + +.. code-block:: ada + + -- gnatcov_rts-base_io.adb + package body GNATcov_RTS.Base_IO is + + procedure Stateful_IO_Put (S : String); + pragma Import (Ada, Stateful_IO_Put, "stateful_io_put"); + + procedure Put (S : GNATcov_RTS_String) is + Str : String (1 .. Integer (S.Length)); + for Str'Address use S.Str; + pragma Import (Ada, Str); + begin + Stateful_IO_Put (Str); + end Put; + + end GNATcov_RTS.Base_IO; + +Finally, make sure that the project file for the instrumented codebase contains +a ``with "stateful_io";`` clause and that at least one of its unit has a ``with +Stateful_IO;`` clause, so that the ``Stateful_IO`` library gets included during +the build of the instrumented project. + + Building instrumented programs with CCG ======================================= From 8e371d23f3b744e5a10603eb7538a87bae4a9a36 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 16 Jun 2025 08:12:33 +0000 Subject: [PATCH 1246/1483] instr-cov/preelaborated_units: adjust expectations for block coverage --- .../instr-cov/preelaborated_units/test.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/testsuite/tests/instr-cov/preelaborated_units/test.py b/testsuite/tests/instr-cov/preelaborated_units/test.py index ecae16f6f..dc364242b 100644 --- a/testsuite/tests/instr-cov/preelaborated_units/test.py +++ b/testsuite/tests/instr-cov/preelaborated_units/test.py @@ -21,14 +21,15 @@ manual_prj_name="gen", trace_mode="src", ) -check_xcov_reports( - "xcov", - { - "main.adb.xcov": {"+": {9, 10}, "-": {7, 8}}, - "pkg.ads.xcov": {}, - "pkg.adb.xcov": {"+": {27, 28}, "-": {30}}, - }, - discard_empty=False, -) +expected_report = { + "main.adb.xcov": ( + {"+": {7, 8, 9, 10}} + if thistest.options.block + else {"+": {9, 10}, "-": {7, 8}} + ), + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"+": {27, 28}, "-": {30}}, +} +check_xcov_reports("xcov", expected_report, discard_empty=False) thistest.result() From 6a3ea4b252384442ac374369d86d2fb4fc84b61b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 16 Jun 2025 14:49:48 +0000 Subject: [PATCH 1247/1483] CCG: fix doc and testsuite scripts for the preelaborated cov. runtime --- doc/gnatcov/src_traces.rst | 20 ++++++++++++++++---- testsuite/altrun/ccg_native/pre_testsuite.py | 20 ++++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index ca5c57b7a..698536f73 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -1447,10 +1447,22 @@ must be deleted: Finally, it is necessary to modify the contents of ``ccg_gnatcov_rts/gnatcov_rts-base_io.adb`` to use an alternate medium on which the execution trace will be output. By default this relies on ``GNAT.IO``, -which is not available in the CCG runtime. It is possible to replace occurrences -of this unit by ``Ada.Text_IO``, which is supported by CCG, but which relies on -the C standard function ``putchar``. Otherwise, see :ref:`custom_base_64` for -more details on the expected interface to dump the coverage trace information. +which is not available in the CCG runtime. One way to modify it is to implement it on top of the ``putchar`` libc function: + +.. code-block:: ada + + declare + function Putchar (C : Integer) return Integer; + pragma Import (C, Putchar); + Ignored : Integer; + begin + for C of Str loop + Ignored := Putchar (Character'Pos (C)); + end loop; + end; + +Otherwise, see :ref:`custom_base_64` for more details on the expected interface +to dump the coverage trace information. Building an instrumented program with CCG ----------------------------------------- diff --git a/testsuite/altrun/ccg_native/pre_testsuite.py b/testsuite/altrun/ccg_native/pre_testsuite.py index b4366f1a9..0c43bd137 100644 --- a/testsuite/altrun/ccg_native/pre_testsuite.py +++ b/testsuite/altrun/ccg_native/pre_testsuite.py @@ -86,13 +86,25 @@ def prepare_rts(): rm(os.path.join(custom_rts_dir, "gnatcov_rts_c-os_interface*")) rm(os.path.join(custom_rts_dir, "gnatcov_rts_c-traces-output-files*")) - # Amend gnatcov_rts-base_io.adb to change the dependency on GNAT.IO to - # Ada.Text_IO, the former not being available in the CCG runtime. + # Amend gnatcov_rts-base_io.adb to remove the dependency on GNAT.IO (it is + # not available in the CCG runtime) and to directly use the libc instead. amend_file( os.path.join(custom_rts_dir, "gnatcov_rts-base_io.adb"), substs=[ - ("with GNAT.IO;", "with Ada.Text_IO;"), - ("GNAT.IO.Put (Str);", " Ada.Text_IO.Put (Str);"), + ("with GNAT.IO;", ""), + ( + "pragma Warnings (On);", + " pragma Warnings (On);" + "\n function Putchar (C : Integer) return Integer;" + "\n pragma Import (C, Putchar);" + "\n Ignored : Integer;", + ), + ( + "GNAT.IO.Put (Str);", + " for C of Str loop" + "\n Ignored := Putchar (Character'Pos (C));" + "\n end loop;", + ), ], ) From f59cfcd7a2ba9e1cfb0d4e53116d60ce5ad3a20c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 12 Jun 2025 18:39:58 +0200 Subject: [PATCH 1248/1483] Test/instr-cov/c_special_names: XFail pending GPR2 bug resolution The generate project makes GPR2 crash, whereas it loads and compiles correctly with legacy gprbuild. (cherry picked from commit eaf284d9433b9f83c276dc7f8d1ff6a7190e5554) --- testsuite/tests/instr-cov/c_special_filenames/test.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/instr-cov/c_special_filenames/test.opt b/testsuite/tests/instr-cov/c_special_filenames/test.opt index 195e6c2d4..ce5f4954f 100644 --- a/testsuite/tests/instr-cov/c_special_filenames/test.opt +++ b/testsuite/tests/instr-cov/c_special_filenames/test.opt @@ -1 +1,2 @@ +ALL XFAIL Source naming makes GPR2 crash (eng/gpr/gpr-issues#624) !C++ DEAD test requires C++ compiler From 1f451e5577954f402557febc88ae8ae5bb667f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 12 Jun 2025 15:41:51 +0200 Subject: [PATCH 1249/1483] Tests/S506-014-mix-providers: Work around SID deletion in GPR2 (cherry picked from commit e32641363612ac8df4a825e4e91b7db952a37f98) --- .../tests/S506-014-mix-providers/test.py | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/testsuite/tests/S506-014-mix-providers/test.py b/testsuite/tests/S506-014-mix-providers/test.py index 61936835f..84a937064 100644 --- a/testsuite/tests/S506-014-mix-providers/test.py +++ b/testsuite/tests/S506-014-mix-providers/test.py @@ -5,6 +5,8 @@ Also check that passing both kind of traces is rejected by gnatcov. """ +from e3.fs import cp, mkdir + from SCOV.minicheck import build_and_run from SUITE.cutils import Wdir, contents_of from SUITE.gprutils import GPRswitches @@ -50,6 +52,13 @@ def check(tc_name, coverage_args, expected_results, expect_failure): trace_mode="src", )[-1] +# The build_and_run invocation bellow implicitly invokes gprclean which will +# delete the SID files, so we need to copy them elsewhere to avoid having them +# be deleted. +sids_dir = "sids" +mkdir(sids_dir) +cp("obj/*.sid", sids_dir) + # Second, build and run the program to produce SCOs (ALIs) and a binary trace bin_trace = build_and_run( gprsw=GPRswitches(root_project=prj), @@ -90,7 +99,7 @@ def check(tc_name, coverage_args, expected_results, expect_failure): "--scos", "obj/main.ali", "--sid", - "obj/main.sid", + f"{sids_dir}/main.sid", src_trace, bin_trace, ], @@ -107,7 +116,7 @@ def check(tc_name, coverage_args, expected_results, expect_failure): "--scos", "obj/main.ali", "--sid", - "obj/main.sid", + f"{sids_dir}/main.sid", src_trace, bin_trace, ], @@ -125,7 +134,7 @@ def check(tc_name, coverage_args, expected_results, expect_failure): "--scos", "obj/main.ali", "--sid", - "obj/main.sid", + f"{sids_dir}/main.sid", "--save-checkpoint=src.ckpt", src_trace, ], @@ -147,7 +156,7 @@ def check(tc_name, coverage_args, expected_results, expect_failure): "--scos", "obj/main.ali", "--sid", - "obj/main.sid", + f"{sids_dir}/main.sid", "--save-checkpoint=bin.ckpt", bin_trace, ], @@ -160,7 +169,7 @@ def check(tc_name, coverage_args, expected_results, expect_failure): expect_failure=False, ) -# Check that mixing tarce kinds through checkpoints is rejected +# Check that mixing trace kinds through checkpoints is rejected check( "mixed_checkpoint", From 6f5f35742c686a471074d2c24603a2f981573b4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 28 May 2025 14:56:11 +0200 Subject: [PATCH 1250/1483] Add test ensuring the add-annotation command does not crash Specifically check that the add-annotation command does not crash when the designated regions has a column number smaller than the enclosing named body. (cherry picked from commit 8b79ad874a19618668e875f685a5388217f6e095) --- .../422-negative-rel-offset/src/pkg.adb | 15 +++++++++++++ .../422-negative-rel-offset/src/pkg.ads | 5 +++++ .../422-negative-rel-offset/src/test_pkg.adb | 14 +++++++++++++ .../422-negative-rel-offset/test.opt | 1 + .../422-negative-rel-offset/test.py | 21 +++++++++++++++++++ 5 files changed, 56 insertions(+) create mode 100644 testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.adb create mode 100644 testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.ads create mode 100644 testsuite/tests/ext_annotations/422-negative-rel-offset/src/test_pkg.adb create mode 100644 testsuite/tests/ext_annotations/422-negative-rel-offset/test.opt create mode 100644 testsuite/tests/ext_annotations/422-negative-rel-offset/test.py diff --git a/testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.adb b/testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.adb new file mode 100644 index 000000000..8593db67b --- /dev/null +++ b/testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.adb @@ -0,0 +1,15 @@ +with Ada.Text_IO; + +package body Pkg is + + procedure Check_Ok is + Val : Boolean := False; -- # ok_st + begin + if Val then -- # ex_dc + raise Program_Error; -- # ex_st + else + Ada.Text_IO.Put_Line ("All ok"); -- # ok_st + end if; + end Check_Ok; + +end Pkg; diff --git a/testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.ads b/testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.ads new file mode 100644 index 000000000..c18de71e3 --- /dev/null +++ b/testsuite/tests/ext_annotations/422-negative-rel-offset/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + procedure Check_Ok; + +end Pkg; diff --git a/testsuite/tests/ext_annotations/422-negative-rel-offset/src/test_pkg.adb b/testsuite/tests/ext_annotations/422-negative-rel-offset/src/test_pkg.adb new file mode 100644 index 000000000..806be74bd --- /dev/null +++ b/testsuite/tests/ext_annotations/422-negative-rel-offset/src/test_pkg.adb @@ -0,0 +1,14 @@ +with Pkg; + +procedure Test_Pkg is +begin + Pkg.Check_Ok; +end Test_Pkg; + + +--# pkg.adb +-- +-- /ok_st/ l+ ## 0 +-- /ex/ l* ## x+ +-- /ex_dc/ l= ## XoT- +-- /ex_st/ l= ## Xs- diff --git a/testsuite/tests/ext_annotations/422-negative-rel-offset/test.opt b/testsuite/tests/ext_annotations/422-negative-rel-offset/test.opt new file mode 100644 index 000000000..1572a45d8 --- /dev/null +++ b/testsuite/tests/ext_annotations/422-negative-rel-offset/test.opt @@ -0,0 +1 @@ +bin-traces DEAD test uses constructions that are optimized out diff --git a/testsuite/tests/ext_annotations/422-negative-rel-offset/test.py b/testsuite/tests/ext_annotations/422-negative-rel-offset/test.py new file mode 100644 index 000000000..fc9c575cc --- /dev/null +++ b/testsuite/tests/ext_annotations/422-negative-rel-offset/test.py @@ -0,0 +1,21 @@ +""" +Check that gnatcov add-annotation does not crash when the designated region +has columns that are smaller than the starting column of the enclosing named +declaration. This used to make stable_sloc (and thus gnatcov) crash. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CovControl, CAT +from SUITE.context import thistest +from SUITE.tutils import Exempt_Region, generate_annotations + +annotations = [ + Exempt_Region("src/pkg.adb", "8:1", "9:30", "Unreachable"), +] + +annot_file = generate_annotations(annotations) + +TestCase(category=CAT.stmt).run( + covcontrol=CovControl(covoptions=f"--external-annotations={annot_file}") +) +thistest.result() From 1959a17acf76ad153dad5bac72c975bd4e7bfa77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 28 May 2025 15:00:52 +0200 Subject: [PATCH 1251/1483] Doc: Remove trailing ':' in command line options for external annotations These can be ambiguous as the same character is used as separator when writing a source location for instance. (cherry picked from commit 0857d76692f88077f4255a07302b060c8d265d79) --- doc/gnatcov/external_annotations.rst | 52 ++++++++++++++-------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/doc/gnatcov/external_annotations.rst b/doc/gnatcov/external_annotations.rst index de54af290..4ca33393d 100644 --- a/doc/gnatcov/external_annotations.rst +++ b/doc/gnatcov/external_annotations.rst @@ -37,22 +37,22 @@ The help section for the |gcvaddan| command can be displayed by running Some notable command line options are: -:cmd-option:`--output`: +:cmd-option:`--output` Name of the file to the newly created annotation will be written. If there already is a file, it will be overwritten. -:cmd-option:`--external-annotations`, |rarg|: +:cmd-option:`--external-annotations`, |rarg| Loads pre-existing annotations from `FILENAME`. They are used to check that the new annotation does not conflict with any pre-existing one. The loaded annotations are all written to the output file specified through :cmd-option:`--output`. -:cmd-option:`FILENAME`, positional: +:cmd-option:`FILENAME`, positional Filename to which the new annotation should apply. There are special considerations to keep in mind when specifying the name of the file to be annotated, see :ref:`ext_annot_relocs` -:cmd-option:`--annotation-id=IDENTIFIER`, optional: +:cmd-option:`--annotation-id=IDENTIFIER`, optional Unique identifier for the new annotation. If not specified, |gcv| will generate one based on the kind of annotation and the designated location. @@ -61,7 +61,7 @@ Some notable command line options are: manipulation commands, |gcvdelan| and |gcvshoan| to uniquely designate an annotation. -:cmd-option:`--force`, optional: +:cmd-option:`--force`, optional Force overwriting of a pre-existing annotation for the same location, or with the same identifier. If not specified, gnatcov will emit an error and abort the annotation generation. The output file will not be modified. @@ -74,65 +74,65 @@ help text for the |gcvaddan| command, and are detailed bellow. A switch in brackets signifies that the switch is optional, otherwise the switch is required and |gcvaddan| will emit an error if not found on the command line. -* :cmd-option:`--kind=Exempt_On`: +* :cmd-option:`--kind=Exempt_On` Generate an annotation symbolizing the beginning of an :ref:`exempted region `. - :cmd-option:`--location=LINE:COL`: + :cmd-option:`--location=LINE:COL` Source location for the beginning of the exempted region. - :cmd-option:`--justification=MESSAGE`: + :cmd-option:`--justification=MESSAGE` Justification message to be displayed in the coverage reports for the exempted region. -* :cmd-option:`--kind=Exempt_Off`: +* :cmd-option:`--kind=Exempt_Off` Generate an annotation symbolizing the end of an exempted region. - :cmd-option:`--location=LINE:COL`: + :cmd-option:`--location=LINE:COL` Source location for the end of the exempted region. -* :cmd-option:`--kind=Exempt_Region`: +* :cmd-option:`--kind=Exempt_Region` Generate an annotation symbolizing an entire exempted region. - :cmd-option:`--start-location=LINE:COL`: + :cmd-option:`--start-location=LINE:COL` Source location for the beginning of the exempted region. - :cmd-option:`--end-location=LINE:COL`: + :cmd-option:`--end-location=LINE:COL` Source location for the end of the exempted region. - :cmd-option:`--justification=MESSAGE`: + :cmd-option:`--justification=MESSAGE` Justification message to be displayed in the coverage reports for the exempted region. -* :cmd-option:`--kind=Cov_Off`: +* :cmd-option:`--kind=Cov_Off` Generate an annotation symbolizing the beginning of a :ref:`disabled coverage region `. - :cmd-option:`--location=LINE:COL`: + :cmd-option:`--location=LINE:COL` Source location for the beginning of the disabled coverage region. - :cmd-option:`--justification=MESSAGE`: + :cmd-option:`--justification=MESSAGE` Justification message for the disabled coverage region, to be displayed in the coverage reports. -* :cmd-option:`--kind=Cov_On`: +* :cmd-option:`--kind=Cov_On` Generate an annotation symbolizing the end of a disabled coverage region. - :cmd-option:`--location=LINE:COL`: + :cmd-option:`--location=LINE:COL` Location for the end of the disabled coverage region. -* :cmd-option:`--kind=Dump_Buffers`: +* :cmd-option:`--kind=Dump_Buffers` Generate an annotation instructing |gcv| to insert a :ref:`buffer dump procedure call ` at the specified location. This is only taken into account when the selected dump trigger is ``manual``, see :ref:`Dump_Triggers` for more information concerning the dump triggers. - :cmd-option:`--location=LINE:COL`: + :cmd-option:`--location=LINE:COL` Source location at which the buffer dump procedure call should be inserted. - :cmd-option:`[--dump-filename-prefix=TEXT]`: + :cmd-option:`[--dump-filename-prefix=TEXT]` Optional trace filename prefix to be passed to the buffer dump procedure call. This will be textually passed as argument to the buffer dump, and must be an expression evaluating to a null-terminated ``char *``. As @@ -140,21 +140,21 @@ and |gcvaddan| will emit an error if not found on the command line. to ``--dump-filename-prefix`` must contain quotes (e.g. ``--dump-filename-prefix='"my_trace"'``). - :cmd-option:`[--annotate-after]`: + :cmd-option:`[--annotate-after]` If specified, instruct |gcv| to insert the buffer dump procedure **after** the statement designated by the annotation. See :ref:`buf_semantics` for more details on the meaning of this option. -* :cmd-option:`--kind=Reset_Buffers`: +* :cmd-option:`--kind=Reset_Buffers` Generate an annotation instructing gnatcov to insert a :ref:`coverage buffer reset procedure call ` at the specified location. This is only taken into account when the selected dump trigger is ``manual``, see :ref:`Dump_Triggers` for more information concerning the dump triggers. - :cmd-option:`--location=LINE:COL`: + :cmd-option:`--location=LINE:COL` Location at which the buffer reset procedure call should be inserted. - :cmd-option:`[--annotate-after]`: + :cmd-option:`[--annotate-after]` If specified, instruct |gcv| to insert the buffer reset procedure **after** the statement designated by the annotation. See :ref:`buf_semantics` for more details on the meaning of this option. From 192c620582d8e4a9560fe9c3a2980c82c5da7a80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 18 Jun 2025 10:02:41 +0200 Subject: [PATCH 1252/1483] C Instrumentation: Detect when the compiler is native 32bit The preprocessing of sources and libclang need to use the same set of option when processing sources, which is not the case when using a native x86 compiler, as libclang is not aware that it needs to process the sources as if targeting a 32bit executable. This change adds an explicit -m32 switch to the compiler command lines when detecting that the compiler targets i686-pc-linux-gnu. We may need to make this heuristic a bit broader in the future if we also have issues with embedded 32bit targets (e.g. riscv32-elf or arm-elf). (cherry picked from commit f599a4fa4e6078917e7394d1db66594f534ccfbd) --- .../427-initializer-list/test.py | 56 ++++++++++++ .../427-initializer-list/test_for_range.cpp | 12 +++ tools/gnatcov/instrument-c.adb | 91 ++++++++++++++++--- tools/gnatcov/instrument-c.ads | 7 ++ tools/gnatcov/instrument-c__stub.adb | 7 ++ tools/gnatcov/instrument-c__stub.ads | 3 + tools/gnatcov/instrument-common.adb | 8 ++ tools/gnatcov/instrument-common.ads | 4 + tools/gnatcov/instrument-gcc_wrapper.adb | 16 +++- 9 files changed, 187 insertions(+), 17 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/427-initializer-list/test.py create mode 100644 testsuite/tests/integrated_instrumentation/427-initializer-list/test_for_range.cpp diff --git a/testsuite/tests/integrated_instrumentation/427-initializer-list/test.py b/testsuite/tests/integrated_instrumentation/427-initializer-list/test.py new file mode 100644 index 000000000..18c7001f1 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/427-initializer-list/test.py @@ -0,0 +1,56 @@ +""" +Test the integrated instrumentation on an initializer list, to verify that, on +native x86 compiler this doesn't cause parsing errors in libclang and we get +the expected coverage results. +""" + +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "test_for_range.cpp"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + f"--files={os.path.join(cwd, 'test_for_range.cpp')}", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Compile our simple program +cmdrun(["gcc", "test_for_range.cpp", "-o", "test_for_range"], for_pgm=False) + +# Run the executable +cmdrun(["test_for_range"], for_pgm=True) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=test_for_range.cpp.sid", + "-axcov", + srctracename_for("test_for_range"), + ] +) +check_xcov_reports(".", {"test_for_range.cpp.xcov": {"+": {6, 7, 9, 11}}}) + +thistest.result() diff --git a/testsuite/tests/integrated_instrumentation/427-initializer-list/test_for_range.cpp b/testsuite/tests/integrated_instrumentation/427-initializer-list/test_for_range.cpp new file mode 100644 index 000000000..2650762fa --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/427-initializer-list/test_for_range.cpp @@ -0,0 +1,12 @@ +#include + +int +main (void) +{ + int sum = 0; + for (auto i : { 1, 2, 3 }) + { + sum += i; + } + return 0; +} diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 1ef750475..fbeac4e02 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -21,6 +21,7 @@ with Ada.Containers; use Ada.Containers; with Ada.Directories; use Ada.Directories; with Ada.IO_Exceptions; with Ada.Streams.Stream_IO; +with Ada.Strings.Fixed; with Ada.Text_IO; use Ada.Text_IO; with Clang.CX_Diagnostic; use Clang.CX_Diagnostic; @@ -44,6 +45,7 @@ with Outputs; use Outputs; with Paths; use Paths; with SCOs; with SS_Annotations; use SS_Annotations; +with Switches; with System; use System; with Table; with Text_Files; use Text_Files; @@ -471,9 +473,11 @@ package body Instrument.C is (Self : out C_Source_Rewriter; Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc); + Prj : Prj_Desc; + Options : out Analysis_Options); -- Start a rewriting session for the given file identified by its full - -- name. If not already done, preprocess it beforehand. + -- name. If not already done, preprocess it beforehand and record + -- information from the preprocessing stage in Options. procedure Run_Diagnostics (TU : Translation_Unit_T); -- Output clang diagnostics on the given translation unit @@ -562,6 +566,51 @@ package body Instrument.C is Func_Args : String := ""); -- Like Format_Extern_Decl, but write the definition to File + --------------------- + -- Compiler_Is_X86 -- + --------------------- + + function Compiler_Is_X86 + (Compiler_Driver : Unbounded_String) return Boolean + is + Cmd : constant Command_Type := + (Command => Compiler_Driver, + Arguments => String_Vectors.To_Vector (+"-dumpmachine", 1), + others => <>); + Basename_Suffix : constant String := "compiler_target.txt"; + Filename : constant String := + (+Compiler_Driver) & "_" + & Hex_Image (Unsigned_64 (Pid_To_Integer (Current_Process_Id))) + & "_" & Basename_Suffix; + File : Ada.Text_IO.File_Type; + Res : Boolean := False; + begin + Run_Command + (Command => Cmd, + Origin_Command_Name => "gnatcov insturment", + Output_File => Filename); + Open (File, In_File, Filename); + + -- We only expect one line in the output file, with only the triplet + -- in it. Check it against a ground truth string, and if it matches + -- and we don't expect a non-native target, assume we need to forward + -- -m32 to libclang. + + if Ada.Strings.Fixed.Index (Get_Line (File), "i686-pc") = 1 then + Res := True; + end if; + Close (File); + Delete_File (Filename); + return Res; + exception + when others => + if Is_Open (File) then + Close (File); + Delete_File (Filename); + end if; + raise; + end Compiler_Is_X86; + ------------------------ -- To_Chars_Ptr_Array -- ------------------------ @@ -3311,11 +3360,11 @@ package body Instrument.C is (Self : out C_Source_Rewriter; Filename : String; Instrumenter : C_Family_Instrumenter_Type'Class; - Prj : Prj_Desc) + Prj : Prj_Desc; + Options : out Analysis_Options) is PP_Filename : Unbounded_String; - Options : Analysis_Options; Args : String_Vectors.Vector; begin Preprocess_Source @@ -3671,8 +3720,6 @@ package body Instrument.C is CU_Name_For_File (+Unit_Name); Orig_Filename : constant String := Unit_Name; - PP_Filename : Unbounded_String; - -- Respectively original, and preprocessed filename Buffer_Filename : constant String := +Self.Buffer_Unit @@ -3744,17 +3791,15 @@ package body Instrument.C is UIC.Files_Of_Interest := Files_Of_Interest; -- Run the preprocessor (this also takes care of importing the - -- preprocessor options into UIC.Options). - - Preprocess_Source (Orig_Filename, Self, Prj, PP_Filename, UIC.Options); - - -- Parse the preprocessed version of the file + -- preprocessor options into UIC.Options) and parse the preprocessed + -- version of the file. Start_Rewriting (Self => Rewriter, - Filename => +PP_Filename, + Filename => Orig_Filename, Instrumenter => Self, - Prj => Prj); + Prj => Prj, + Options => UIC.Options); UIC.TU := Rewriter.TU; UIC.Rewriter := Rewriter.Rewriter; @@ -5136,10 +5181,12 @@ package body Instrument.C is Main_Cursor : Cursor_T; -- Cursor of the main declaration + + Dummy_Options : Analysis_Options; begin Check_Compiler_Driver (Prj, Self); - Rew.Start_Rewriting (Filename, Self, Prj); + Rew.Start_Rewriting (Filename, Self, Prj, Dummy_Options); Insert_Extern_Location := Start_Sloc (Get_Translation_Unit_Cursor (Rew.TU)); @@ -5362,8 +5409,10 @@ package body Instrument.C is Main_Cursor : Cursor_T; -- Cursor of the main declaration + Dummy_Options : Analysis_Options; + begin - Rew.Start_Rewriting (Filename, Self, Prj); + Rew.Start_Rewriting (Filename, Self, Prj, Dummy_Options); Main_Cursor := Get_Main (Rew.TU); if Main_Cursor = Get_Null_Cursor then return False; @@ -5742,6 +5791,18 @@ package body Instrument.C is Self.Compiler_Switches, Instrumenter.Instr_Mode, Self.Builtin_Macros); + + -- Deptermine if the compiler is an x86 32bit compiler. The integrated + -- instrumentation process only forwards the actual compiler, not the + -- driver to the instrumentation process, so only perform this check for + -- project based instrumentation, the compiler wrapper is responsible + -- for adding -m32 if needed to the compiler switches. + if Instrumenter.Instr_Mode = Project_Instrumentation + and then Compiler_Is_X86 (Prj.Compiler_Driver (Instrumenter.Language)) + then + Self.Clang_Needs_M32 := True; + end if; + end Import_Options; --------------------------- diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 7d58eebea..cc6e57dae 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -452,6 +452,13 @@ package Instrument.C is -- C_String_Literal ("a\b") = """a\\b""" -- C_String_Literal ("a""b") = """a\""b""" + function Compiler_Is_X86 + (Compiler_Driver : Unbounded_String) return Boolean; + -- Check wether the compiler designated by Compiler_Driver is a native x86 + -- 32 bit compiler. This function will only work if Compiler_Driver + -- designates an actual driver (e.g. gcc or clang) and not a compiler (e.g. + -- cc1, cc1plus). + private function Find_Instrumented_Entities diff --git a/tools/gnatcov/instrument-c__stub.adb b/tools/gnatcov/instrument-c__stub.adb index 638a3be11..c8974b9bb 100644 --- a/tools/gnatcov/instrument-c__stub.adb +++ b/tools/gnatcov/instrument-c__stub.adb @@ -17,6 +17,13 @@ ------------------------------------------------------------------------------ package body Instrument.C is + function Compiler_Is_X86 + (Compiler_Driver : Unbounded_String) return Boolean is + pragma Unreferenced (Compiler_Driver); + begin + raise Program_Error; + return False; + end Compiler_Is_X86; begin Builtin_Support (C_Language) := False; Builtin_Support (CPP_Language) := False; diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index 95a53c33a..1a0dc1f38 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -58,4 +58,7 @@ package Instrument.C is (Preprocessed_Filename : String; Postprocessed_Filename : String) is null; + function Compiler_Is_X86 + (Compiler_Driver : Unbounded_String) return Boolean; + end Instrument.C; diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 37f0917e1..2b9491fbe 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -549,6 +549,11 @@ package body Instrument.Common is Args.Append (Options.Compiler_Switches); + -- Add -m32 if needed + + if Options.Clang_Needs_M32 then + Args.Append (+"-m32"); + end if; end Add_Options; ---------------------------- @@ -733,6 +738,9 @@ package body Instrument.Common is elsif Has_Prefix (A, "-include") then Self.Include_Files.Append (+A (9 .. A'Last)); + elsif A = "-m32" then + Self.Compiler_Switches.Append (+A); + end if; I := I + 1; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index e7311f971..f0708f048 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -631,6 +631,10 @@ package Instrument.Common is Raw_Switches : String_Vectors.Vector; -- List of switches passed to the compiler driver without filtering + Clang_Needs_M32 : Boolean := False; + -- Wether we need to pass -m32 to libclang's parsing commands. This is + -- only the case when the compiler driver is a native 32 bit compiler. + end record; -- Options to analyze (preprocess and/or parse) a compilation unit diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 333fb76f3..48444c19f 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -318,6 +318,8 @@ is Parsed_Link_Command : Boolean := False; Commands_Filename : constant String := Tmp_Dir.Directory_Name / "commands"; + Additional_Args : String_Vectors.Vector := + String_Vectors.To_Vector (+"-###", 1); begin -- Grab the architecture specific switches. The heuristic is that we -- consider every switch starting with "-m" as an architecture-specific @@ -330,11 +332,21 @@ is end if; end loop; - -- Expand the command line using gcc's -### option + -- Check if we shouldn't add -m32 so that clang correctly interprets the + -- sources. Adding this switch on the gcc command line should not change + -- anything. + + if Compiler_Is_X86 (Context.Orig_Compiler_Driver) then + Additional_Args.Append (+"-m32"); + end if; + + -- Expand the command line using gcc's -### option, and the addition + -- -m32 flag, if any. Putting the additional args first ensures we don't + -- override a potential (but unlikely) -m16 flag. Run_Command (+Context.Orig_Compiler_Driver, - String_Vectors.To_Vector (+"-###", 1) & Args, + Additional_Args & Args, "gnatcov", Output_File => Commands_Filename); From a0c69c8b472d1fb6fca40fa13b661ff992410ea5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 20 Jun 2025 16:46:55 +0200 Subject: [PATCH 1253/1483] Instrument.C: Fix filename computation for 32bit check The filename used to include the full compiler driver name, which could be a full path, resulting in writes in a directory where we potentially did not have permissions. Only used the compiler simple name instead, and ensure the output file is created in a directory where we can put artifacts. (cherry picked from commit d57a04d60ad96aab8e05b8e81687437ba5a94f4a) --- tools/gnatcov/instrument-c.adb | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index fbeac4e02..604e966ec 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -573,15 +573,20 @@ package body Instrument.C is function Compiler_Is_X86 (Compiler_Driver : Unbounded_String) return Boolean is + Driver_Basename : constant String := + Ada.Directories.Simple_Name (+Compiler_Driver); Cmd : constant Command_Type := (Command => Compiler_Driver, Arguments => String_Vectors.To_Vector (+"-dumpmachine", 1), others => <>); Basename_Suffix : constant String := "compiler_target.txt"; Filename : constant String := - (+Compiler_Driver) & "_" - & Hex_Image (Unsigned_64 (Pid_To_Integer (Current_Process_Id))) - & "_" & Basename_Suffix; + Ada.Directories.Compose + (Containing_Directory => Get_Output_Dir, + Name => + Driver_Basename & "_" + & Hex_Image (Unsigned_64 (Pid_To_Integer (Current_Process_Id))) + & "_" & Basename_Suffix); File : Ada.Text_IO.File_Type; Res : Boolean := False; begin From ae0d469956e6174f688d1127c326dfea07a39e5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 20 Jun 2025 17:09:06 +0200 Subject: [PATCH 1254/1483] Insturment.C_Utils: Fix Get_Main heuristic in 32bit mode The mangling differs by an underscore when clang is passed -m32 on the command line. This seems to only impact windows hosted clang. (cherry picked from commit ce04fa570056a2c606b1c2f0341c5f0baedbc5a7) --- tools/gnatcov/instrument-c_utils.adb | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index 8dd5b32ca..4c2bdde01 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -278,7 +278,13 @@ package body Instrument.C_Utils is then return Child_Visit_Recurse; end if; - if Cursor_Get_Mangling (Cursor) = "main" then + + -- Clang will append an underscore to the mangled names of entities + -- when -m32 is passed, so we also need to check for this case. + + if Cursor_Get_Mangling (Cursor) = "main" + or else Cursor_Get_Mangling (Cursor) = "_main" + then Result := Cursor; return Child_Visit_Break; end if; From ab36dfca5dfa1d659458685e14646a5a97cc4f5a Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 24 Jun 2025 11:38:44 +0200 Subject: [PATCH 1255/1483] fix precommit --- .../tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.cpp | 2 +- .../tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.cpp | 2 +- .../C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp | 10 +++++----- .../cpp/lambda-functions/src/pkg.cpp | 2 +- .../cpp/methods-ctors-dtors/src/pkg.cpp | 4 ++-- .../cpp/nested-method-calls/src/pkg.h | 4 ++-- .../non-prefixed-method-calls/src/test_non_prefix.cpp | 2 +- tools/gnatcov/rts/gnatcov_rts_c-strings.h | 7 ++----- 8 files changed, 15 insertions(+), 18 deletions(-) diff --git a/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.cpp index e77247ae6..7491a1abe 100644 --- a/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.cpp +++ b/testsuite/tests/C++/mcdc/AandB/As_LambdaValue/src/tryme.cpp @@ -8,7 +8,7 @@ tryme (bool aa, bool bb, bool skip) auto AndExpr = [] (int aa, int bb) { // # other return aa > 0 && bb > 0; // # eval :o/e: - }; // # lambda_other + }; // # lambda_other volatile bool b = AndExpr (aa, bb); // # other } diff --git a/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.cpp index 7f1c2adfe..be1a4d032 100644 --- a/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.cpp +++ b/testsuite/tests/C++/mcdc/AandB/In_LambdaBody/src/tryme.cpp @@ -11,7 +11,7 @@ tryme (bool aa, bool bb, bool skip) return true; // # lambda_true else // # lambda_other return false; // # lambda_false - }; // # lambda_other + }; // # lambda_other volatile bool b = AndExpr (aa, bb); // # other } diff --git a/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp index 8cc5c4037..2488e0053 100644 --- a/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp +++ b/testsuite/tests/C++/mcdc/AandB/Lambda_Robustness/src/tryme.cpp @@ -11,8 +11,8 @@ tryme (bool aa, bool bb, bool skip) return true; // # lambda_true else // # lambda_other return false; // # lambda_false - }; // # lambda_other - volatile bool a = InCompound (aa, bb); // # other + }; // # lambda_other + volatile bool a = InCompound (aa, bb); // # other } // A lambda function in a for statement @@ -23,7 +23,7 @@ tryme (bool aa, bool bb, bool skip) return true; // # lambda_true else // # lambda_other return false; // # lambda_false - }(aa, bb); // # lambda_other + }(aa, bb); // # lambda_other // A nested lambda [] (int aa, int bb) { // # other @@ -32,6 +32,6 @@ tryme (bool aa, bool bb, bool skip) return true; // # lambda_true else // # lambda_other return false; // # lambda_false - }(aa, bb); // # lambda_other - }(aa, bb); // # lambda_other + }(aa, bb); // # lambda_other + }(aa, bb); // # lambda_other } diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.cpp index 7c145d557..22b4cea5a 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.cpp +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/lambda-functions/src/pkg.cpp @@ -8,7 +8,7 @@ foo (int i) // # foo_def_2 [&i] (int x) { // # lambda_def // # lambda_comment return x + i; // # lambda_return - }; // # lambda_bracket + }; // # lambda_bracket // This should not be instrumented as a call even though under the hood, a // call to a copy constructor is made for f. diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.cpp index 9a0050a9e..362ecb440 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.cpp +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/pkg.cpp @@ -6,8 +6,8 @@ class Point2D int y = 0; public: - Point2D () = default; // # default_ctor_def - Point2D (int x, int y) : x (x), y (y){}; // # var_ctor_def + Point2D () = default; // # default_ctor_def + Point2D (int x, int y) : x (x), y (y) {}; // # var_ctor_def Point2D add (Point2D &other) const; }; diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/pkg.h index c29793170..03915b4cb 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/pkg.h +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/src/pkg.h @@ -6,7 +6,7 @@ class A int _x; public: - A (int x) : _x (x){}; + A (int x) : _x (x) {}; int get_x () const @@ -20,7 +20,7 @@ class B A _a; public: - B (A a) : _a (a){}; + B (A a) : _a (a) {}; A get_a () const diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/src/test_non_prefix.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/src/test_non_prefix.cpp index 5f31e58ec..1a7cc4801 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/src/test_non_prefix.cpp +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/non-prefixed-method-calls/src/test_non_prefix.cpp @@ -3,7 +3,7 @@ class A int _x; public: - A (int x) : _x (x){}; + A (int x) : _x (x) {}; int get_x () const diff --git a/tools/gnatcov/rts/gnatcov_rts_c-strings.h b/tools/gnatcov/rts/gnatcov_rts_c-strings.h index 598f9f725..1d6942f20 100644 --- a/tools/gnatcov/rts/gnatcov_rts_c-strings.h +++ b/tools/gnatcov/rts/gnatcov_rts_c-strings.h @@ -37,12 +37,9 @@ extern "C" value. */ #ifdef __cplusplus #define STR(x) \ - { \ - x, sizeof (x) - 1 \ - } // Avoid compound literal which is not valid C++ + { x, sizeof (x) - 1 } // Avoid compound literal which is not valid C++ #else -#define STR(x) \ - (struct gnatcov_rts_string) { x, sizeof (x) - 1 } +#define STR(x) (struct gnatcov_rts_string){ x, sizeof (x) - 1 } #endif #ifdef __cplusplus From 1eb62dcb776efee9a362ea9560560dbdc13fd25b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 25 Jun 2025 11:58:11 +0200 Subject: [PATCH 1256/1483] Use the actual project designated by Origin_Project when loading switches Gnatcov used to lookup switches in the most-extending project of the one designated by Origin_Project, which does not correspond to the intended semantics of the attribute. --- .../431-origin-prj-stub/code/src/pkg.adb | 14 +++++ .../431-origin-prj-stub/code/src/pkg.ads | 5 ++ .../431-origin-prj-stub/code/src/pkh.adb | 8 +++ .../431-origin-prj-stub/code/src/pkh.ads | 5 ++ .../431-origin-prj-stub/code/stub_src/pkh.adb | 8 +++ .../tests/431-origin-prj-stub/code/stubs.gpr | 13 +++++ .../tests/431-origin-prj-stub/code/user.gpr | 11 ++++ testsuite/tests/431-origin-prj-stub/test.py | 54 +++++++++++++++++++ .../431-origin-prj-stub/test/pkg-test.adb | 9 ++++ tools/gnatcov/project.adb | 13 ++++- 10 files changed, 138 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/431-origin-prj-stub/code/src/pkg.adb create mode 100644 testsuite/tests/431-origin-prj-stub/code/src/pkg.ads create mode 100644 testsuite/tests/431-origin-prj-stub/code/src/pkh.adb create mode 100644 testsuite/tests/431-origin-prj-stub/code/src/pkh.ads create mode 100644 testsuite/tests/431-origin-prj-stub/code/stub_src/pkh.adb create mode 100644 testsuite/tests/431-origin-prj-stub/code/stubs.gpr create mode 100644 testsuite/tests/431-origin-prj-stub/code/user.gpr create mode 100644 testsuite/tests/431-origin-prj-stub/test.py create mode 100644 testsuite/tests/431-origin-prj-stub/test/pkg-test.adb diff --git a/testsuite/tests/431-origin-prj-stub/code/src/pkg.adb b/testsuite/tests/431-origin-prj-stub/code/src/pkg.adb new file mode 100644 index 000000000..9086121d4 --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/src/pkg.adb @@ -0,0 +1,14 @@ +with Pkh; + +package body Pkg is + + function Foo (X : Integer) return Integer is + begin + if Pkh.Bar (X) = 0 then + return 0; + else + return 1; + end if; + end Foo; + +end Pkg; diff --git a/testsuite/tests/431-origin-prj-stub/code/src/pkg.ads b/testsuite/tests/431-origin-prj-stub/code/src/pkg.ads new file mode 100644 index 000000000..a608851f6 --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/src/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Foo (X : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/431-origin-prj-stub/code/src/pkh.adb b/testsuite/tests/431-origin-prj-stub/code/src/pkh.adb new file mode 100644 index 000000000..a7e9936fc --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/src/pkh.adb @@ -0,0 +1,8 @@ +package body Pkh is + + function Bar (X : Integer) return Integer is + begin + return X; + end Bar; + +end Pkh; diff --git a/testsuite/tests/431-origin-prj-stub/code/src/pkh.ads b/testsuite/tests/431-origin-prj-stub/code/src/pkh.ads new file mode 100644 index 000000000..6bb9c9d2d --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/src/pkh.ads @@ -0,0 +1,5 @@ +package Pkh is + + function Bar (X : Integer) return Integer; + +end Pkh; diff --git a/testsuite/tests/431-origin-prj-stub/code/stub_src/pkh.adb b/testsuite/tests/431-origin-prj-stub/code/stub_src/pkh.adb new file mode 100644 index 000000000..51f8cd772 --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/stub_src/pkh.adb @@ -0,0 +1,8 @@ +package body Pkh is + + function Bar (X : Integer) return Integer is + begin + return 0; + end Bar; + +end Pkh; diff --git a/testsuite/tests/431-origin-prj-stub/code/stubs.gpr b/testsuite/tests/431-origin-prj-stub/code/stubs.gpr new file mode 100644 index 000000000..582519d56 --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/stubs.gpr @@ -0,0 +1,13 @@ +project Stubs extends "user.gpr" is + + for Object_Dir use "obj_stubs"; + for Source_Dirs use ("stub_src"); + + package Coverage is + + -- Pkh is stubbed, do not compute coverage over it. + + for Excluded_Units use ("Pkh"); + end Coverage; + +end stubs; diff --git a/testsuite/tests/431-origin-prj-stub/code/user.gpr b/testsuite/tests/431-origin-prj-stub/code/user.gpr new file mode 100644 index 000000000..c3971542c --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/code/user.gpr @@ -0,0 +1,11 @@ +project User is + + for Source_Dirs use ("src"); + for Object_Dir use "obj"; + + package Coverage is + for Switches ("*") use ("--level=stmt+decision"); + for Switches ("coverage") use ("--annotate=xcov", "--output-dir=xcov"); + end Coverage; + +end User; diff --git a/testsuite/tests/431-origin-prj-stub/test.py b/testsuite/tests/431-origin-prj-stub/test.py new file mode 100644 index 000000000..e857a0e6a --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/test.py @@ -0,0 +1,54 @@ +""" +Ensure that gnatcov loads switches from the project designated by the +Origin_Project attribute, and not from any extending project. This is required +for the gnattest-gnatcov integration to work properly, as gnattest +systematically generates an extending project of the user project when stubbing +is enabled. + +The sources in the code and test directories are made to mimic the structure of +the harnesses generated by gnattest +""" + +from e3.fs import cp + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +# Copy the test material in the temp dir +cp("../test", ".", recursive=True) +cp("../code", ".", recursive=True) + +# Generate a project for the test driver, "withing" the stub project and +# referencing the user project through the Origin_Project attribute +test_prj = gprfor( + mains=["pkg-test.adb"], + prjid="test", + srcdirs="test", + deps=["code/stubs.gpr"], + extra='for Origin_Project use "code/user.gpr";', +) + +# No level or annotation format provided, everything should be loaded from +# the Origin_Project (user.gpr). +build_run_and_coverage( + gprsw=GPRswitches(root_project=test_prj), + covlevel=None, + extra_coverage_args=[], + mains=["pkg-test"], +) + +check_xcov_reports( + "xcov", + { + "pkg.ads.xcov": {}, + "pkg.adb.xcov": {"!": {7}, "+": {8}, "-": {10}}, + }, +) + +thistest.result() diff --git a/testsuite/tests/431-origin-prj-stub/test/pkg-test.adb b/testsuite/tests/431-origin-prj-stub/test/pkg-test.adb new file mode 100644 index 000000000..5948221fe --- /dev/null +++ b/testsuite/tests/431-origin-prj-stub/test/pkg-test.adb @@ -0,0 +1,9 @@ +with Support; + +procedure Pkg.Test is +begin + -- We are using the stub version of Pkh, which always returns 0, so expect + -- Pkg to return 0. + + Support.Assert (Pkg.Foo (3) = 0); +end Pkg.Test; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 863bd84d3..14dcb995a 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -1449,9 +1449,18 @@ package body Project is (GPR2.Project.Registry.Attribute.Origin_Project); Actual_Prj : constant GPR2.Project.View.Object := (if Origin_Attr.Is_Defined - then Most_Extending (Lookup_Project (Origin_Attr.Value.Text)) + then Lookup_Project (Origin_Attr.Value.Text) else Prj_Tree.Root_Project); - Attr : GPR2.Project.Attribute.Object; + -- This intentionally does not use the most-extending view, as the + -- origin project is supposed to be the root project of the user, and + -- any extension is a tooling artifact. + -- + -- In the case of gnattest, an extending project is used to override + -- some source when generating stubs, still the user coverage + -- preferences are to be loaded from the project designated by + -- Origin_Project. + + Attr : GPR2.Project.Attribute.Object; begin return Result : String_Vectors.Vector do Attr := Actual_Prj.Attribute From 493507a5c685e72c6be9196007b1ae14ff264980 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 23 Jun 2025 08:00:40 +0000 Subject: [PATCH 1257/1483] Remove obsolete support for instance IDs in SIDs/checkpoints Now that separate coverage is no longer supported, all the instance IDs are supposed to be 0: remove the corresponding data types and data structure components, and remove them from the SID/checkpoint format. --- .../tests/207-srctrace-version/foo.c.sid | Bin 1191 -> 1179 bytes testsuite/tests/207-srctrace-version/main.sid | Bin 1418 -> 1406 bytes .../207-srctrace-version/reference.srctrace | Bin 336 -> 336 bytes .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 1508 -> 1508 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2580 -> 2580 bytes .../gen/arm-elf-linux/gcvrt-db_z794ac68b.ads | 2 + .../gen/arm-elf-linux/gcvrt-db_z794ac68c.ads | 2 + .../gen/arm-elf-linux/main_1.sid | Bin 433 -> 421 bytes .../gen/arm-elf-linux/main_2.sid | Bin 433 -> 421 bytes .../gen/arm-elf-linux/pkg.sid | Bin 1122 -> 1102 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1907 -> 1879 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1917 -> 1889 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 2124 -> 2088 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 2055 -> 2019 bytes .../gen/x86_64-windows/gcvrt-db_z794ac68b.ads | 2 + .../gen/x86_64-windows/gcvrt-db_z794ac68c.ads | 2 + .../gen/x86_64-windows/main_1.sid | Bin 435 -> 423 bytes .../gen/x86_64-windows/main_2.sid | Bin 435 -> 423 bytes .../gen/x86_64-windows/pkg.sid | Bin 1126 -> 1106 bytes tools/gnatcov/checkpoints.adb | 64 ------ tools/gnatcov/checkpoints.ads | 34 +-- tools/gnatcov/sc_obligations.adb | 207 +----------------- 22 files changed, 25 insertions(+), 288 deletions(-) diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid index bb34af6790d7bbe92f9aef8facf142998a8876d3..962ac59626d19df2295dbccc0a39174f7277e75a 100644 GIT binary patch delta 72 zcmZ3^Ih#|&-On*3IloLHIU_YWyC6R^uY^H(qDaEVn$?V(wVA#%P7YvE0b+M4Mg|53 PCLq>z1`=QZ5&;1K1FsLW delta 75 zcmbQuxtvqP-On*3IloLHIU_YWyC6R^uY^HpqDTTOBLfg@EL_L9S(@oLBO4Qtr|Ue~ Tj74Lz6^pw7ND>6Vs(>^A`vDJg diff --git a/testsuite/tests/207-srctrace-version/main.sid b/testsuite/tests/207-srctrace-version/main.sid index 3df21e8297b685bd6c7a9bd8734e430ed6833b3f..64111790433a5122d7b93aad01b097da48ed576e 100644 GIT binary patch delta 37 scmeC;{>LTa?&lbioL{DpoRONGU67xdSHd7XQ6za|eKzCfcZ_qG0r&t7WB>pF delta 43 xcmeyz)x|C1?&lbioL{DpoRONGU67xdSHd7PQ6!m_kpT!cmgF&RzQ?$L82~Zr4OIXD diff --git a/testsuite/tests/207-srctrace-version/reference.srctrace b/testsuite/tests/207-srctrace-version/reference.srctrace index 8da91906d78a46343cb58d4c0977ce2fb52b5474..bfcd9c40fd3c01a71ac32e6537d5536da80c652a 100644 GIT binary patch delta 14 Vcmcb>bb)Dt1G52Vbb)Dt19OOl%0_2iMgS#F1S$Xk diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index 6eb1ddba3f37ff88210738fdeddcaba27e2c6188..0b910a88605bc3f6631834b619c3a63b87379961 100644 GIT binary patch literal 1508 zcmYk6K}b|l6o${drsr!C={=*uT3k>f0%>L(ok?7@un4iJFqwsvnnej&6okuY;XgEk_w*QK9?5=B%pX#Q64?6~wmg#KJySXvF+FNNNq^k@m!@Bt zPtu<<|F!8i=9Bc_ng8DO2e2LU^ljgzz>ApwvTE!runu)aup4=E8joZix} zLW1K&at>slHn0Zl11rJ%AkT#%&_n(f>P~{Uy}0fX=%8moo(rQEp9DGHG{|vcoseCN zdw7l%p1(>N$_(PH-voJ%{Q*7=_;%$MGT}-CIORiw|@mp*1s&W#U3&3JHr6ixxsw1{VEDMYwPwAt5n{ zgo_~}T7*c5M1)94h)7683yBDcRxK)8yJ*!p@0_54JI_7u^ZnhQ?>3(~cJgfd!0n5d zuiQzcGiI%3__qkh&$`;i`h1P0a9)q&)}?C)Zd|;2^FrP%i_9bB4;PD_W_38+VjPb&vg}#bma;@7W;?d!D69ssH1@X|9;K?&(E1Le`}3J8H??CokeL2Hs?%i z9?T#wC@+E$@{;nh{EG5h_ldpp9Bf1N_uvjoY|DLY6A|Z$tqt?;M*S$*fLvu_r@S89 zD44+C2P60@6MKlv^{zUDtveIj0JB)%N99d$Kl=Q@&fC zr08Iq&$}?aI>-?nr z1?x^yM_fu>oe5M*P zehau4><2mDE|B|o2;775#=tCcS@jPf_y1S03H8nt$4Trs$aS0mo4{eP0UQPSU3dWU zxoo4~K5!&m?RO7sL0$s+U3jeeJjn4Dz^!3Ec_Y delta 53 zcmbOtGDT#994jjymm$kUWn)ECT|*NELjx-lODh8t1`Y-W25ul$FtV^TFfz9^wlv*X HK9>^!2?PoP diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads index aa7c96670..59172a575 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68b.ads @@ -2,6 +2,8 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Buffers; package GCVRT.DB_z794ac68b is + pragma Preelaborate; + pragma No_Tagged_Streams; procedure Dump_Buffers; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads index 3d79c2f4f..34440e9db 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-db_z794ac68c.ads @@ -2,6 +2,8 @@ pragma Style_Checks (Off); pragma Warnings (Off); with GNATcov_RTS.Buffers; package GCVRT.DB_z794ac68c is + pragma Preelaborate; + pragma No_Tagged_Streams; procedure Dump_Buffers; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index 5119bec10e11e06af2577ce3534b0c0621ac3e26..9c449e8dac8e7c2b81706e0b2add8352c68c6338 100644 GIT binary patch delta 35 qcmdnUyp&nQ-On*3IloLHIU_YWyC6R^uY^H(qDa!jy7iL{85;o9^bAM< delta 41 vcmZ3=ypdVN-On*3IloLHIU_YWyC6R^uY^HpqDT@eBLfgjEZ#I(k+B5;3}y^D diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid index d2ed828c2972cac32b5b76066d368f55f7e1cb46..08849a8e97de946c831d85de84fdc02880083395 100644 GIT binary patch delta 35 qcmdnUyp&nQ-On*3IloLHIU_YWyC6R^uY^H(qDa!jy7iL{85;o9^bAM< delta 41 vcmZ3=ypdVN-On*3IloLHIU_YWyC6R^uY^HpqDT@eBLfgjEZ#I(k+B5;3}y^D diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid index 6240287ec9b125c68ec027ec8abf1193d709fdb8..c1f72df6195d71afe8f5ec83b29080a3e60f6b74 100644 GIT binary patch delta 41 xcmaFFagIa8-On*3IloLHIU_YWyC6R^uY^H(qDb$=l~tRy8F?8u+c2py0RS@=4UPZ+ delta 47 zcmX@d@rXmj-On*3IloLHIU_YWyC6R^uY^HpqDb$=nN6&W3_!41f>D5RvkH?I699JL B4QBuV diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt index 4d0716d16febbdd76e84049f6a77486ed7f98706..3f2e2f96ef23270a97d8168ce0704f50ebe555b8 100644 GIT binary patch delta 95 zcmey&cb!kf-On*3IloLHIU_YWyC6R^uY^H(qsSY^$s9~!lhc6s2$Sz-QRXCOc8OhX nm5L_ilk3R=8nOIsG7*BR!7Y6`;kQ-b8 diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index 1b32d162043b5a6e9d035a566fc0be176c6df029..38ab0fe4a6444433dddc4c6c153fdcaf7fae31f2 100644 GIT binary patch delta 95 zcmey%_mEG--On*3IloLHIU_YWyC6R^uY^H(qsSY^$s9~!lhc6s2$Sz-QRXaWb_3p1 ne-%y2C%3U(Rx#5xGFC9Kurjo?GO|?AHZZUR=8nOIsGm?&r)7+4t?fQjutGq@-On*3IloLHIU_YWyC6R^uY^H(qlhKra7IAH-On*3IloLHIU_YWyC6R^uY^HpqlhIVDBP_ZRU kn False); end Allocate_CU_Id_Maps; - --------------------------- - -- Allocate_Inst_Id_Maps -- - --------------------------- - - procedure Allocate_Inst_Id_Map - (Relocs : in out Checkpoint_Relocations; - First, Last : Inst_Id) - is - begin - pragma Assert (Relocs.Inst_Map = null); - Relocs.Inst_Map := - new Inst_Id_Map_Array'(First .. Last => No_Inst_Id); - end Allocate_Inst_Id_Map; - ------------------------------- -- Allocate_BDD_Node_Id_Maps -- ------------------------------- @@ -291,18 +275,6 @@ package body Checkpoints is Relocs.CU_Map (Source_CU_Id) := Target_CU_Id; end Set_CU_Id_Map; - --------------------- - -- Set_Inst_Id_Map -- - --------------------- - - procedure Set_Inst_Id_Map - (Relocs : in out Checkpoint_Relocations; - Source_Inst_Id, Target_Inst_Id : Valid_Inst_Id) - is - begin - Relocs.Inst_Map (Source_Inst_Id) := Target_Inst_Id; - end Set_Inst_Id_Map; - ------------------------- -- Set_BDD_Node_Id_Map -- ------------------------- @@ -374,22 +346,6 @@ package body Checkpoints is return CP_CU_Id; end Remap_CU_Id; - ------------------- - -- Remap_Inst_Id -- - ------------------- - - function Remap_Inst_Id - (Relocs : Checkpoint_Relocations; - CP_Inst_Id : Inst_Id) return Inst_Id - is - begin - if CP_Inst_Id /= No_Inst_Id then - pragma Assert (Relocs.Inst_Map (CP_Inst_Id) /= No_Inst_Id); - return Relocs.Inst_Map (CP_Inst_Id); - end if; - return CP_Inst_Id; - end Remap_Inst_Id; - ----------------------- -- Remap_BDD_Node_Id -- ----------------------- @@ -703,7 +659,6 @@ package body Checkpoints is begin Free (Relocs.SFI_Map); Free (Relocs.CU_Map); - Free (Relocs.Inst_Map); Free (Relocs.BDD_Map); Free (Relocs.SCO_Map); Free (Relocs.Ignored_SFIs); @@ -831,15 +786,6 @@ package body Checkpoints is return Integer (Self.Read_I32); end Read_Integer; - --------------- - -- Read_Inst -- - --------------- - - function Read_Inst (Self : in out Checkpoint_Load_State) return Inst_Id is - begin - return Inst_Id (Self.Read_I32); - end Read_Inst; - ------------------------ -- Read_Language_Kind -- ------------------------ @@ -1287,16 +1233,6 @@ package body Checkpoints is Interfaces.Integer_32'Write (Self.Stream, Value); end Write_I32; - ---------------- - -- Write_Inst -- - ---------------- - - procedure Write_Inst (Self : in out Checkpoint_Save_State; Value : Inst_Id) - is - begin - Self.Write_I32 (Interfaces.Integer_32 (Value)); - end Write_Inst; - ------------------- -- Write_Integer -- ------------------- diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index ff6f0adc2..7725c3fd0 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -39,7 +39,7 @@ with Traces_Source; use Traces_Source; package Checkpoints is - subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 18; + subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 19; -- For compatibility with previous Gnatcov versions, the checkpoint -- file format is versioned. -- @@ -62,6 +62,7 @@ package Checkpoints is -- 16 -- Extend Scope_Entity to include the Start/End_Sloc of the scope -- 17 -- Add support for Fun_Call and Guarded Expression coverage -- 18 -- Removed support for tags (separate coverage) + -- 19 -- Removed support for instance ids (separate coverage) -- -- Note that we always use the last version when creating a checkpoint. -- @@ -93,9 +94,6 @@ package Checkpoints is procedure Allocate_CU_Id_Maps (Relocs : in out Checkpoint_Relocations; First, Last : CU_Id); - procedure Allocate_Inst_Id_Map - (Relocs : in out Checkpoint_Relocations; - First, Last : Inst_Id); procedure Allocate_BDD_Node_Id_Map (Relocs : in out Checkpoint_Relocations; First, Last : BDD_Node_Id); @@ -167,11 +165,6 @@ package Checkpoints is -- Source_CU_Id must not have been previously marked as ignored with -- Ignore_CU_Id. - procedure Set_Inst_Id_Map - (Relocs : in out Checkpoint_Relocations; - Source_Inst_Id, Target_Inst_Id : Valid_Inst_Id); - -- Associate Source_Inst_Id to Target_Inst_Id in the relocations map - procedure Set_BDD_Node_Id_Map (Relocs : in out Checkpoint_Relocations; Source_BDD_Node_Id, Target_BDD_Node_Id : Valid_BDD_Node_Id); @@ -206,15 +199,6 @@ package Checkpoints is -- any other value, then it is remapped to the corresponding value in -- the current run. - function Remap_Inst_Id - (Relocs : Checkpoint_Relocations; - CP_Inst_Id : Inst_Id) return Inst_Id; - -- Remap one Inst_Id. - -- - -- If CP_Inst_Id is No_Inst_Id then it's returned unchanged. If it is - -- any other value, then it is remapped to the corresponding value in - -- the current run. - function Remap_BDD_Node_Id (Relocs : Checkpoint_Relocations; CP_BDD_Node_Id : BDD_Node_Id) return BDD_Node_Id; @@ -382,7 +366,6 @@ package Checkpoints is return SC_Obligations.Fingerprint_Type; function Read_I32 (Self : in out Checkpoint_Load_State) return Interfaces.Integer_32; - function Read_Inst (Self : in out Checkpoint_Load_State) return Inst_Id; function Read_Integer (Self : in out Checkpoint_Load_State) return Integer; function Read_Language_Kind (Self : in out Checkpoint_Load_State) return Supported_Language_Kind; @@ -515,7 +498,6 @@ package Checkpoints is (Self : in out Checkpoint_Save_State; Value : Count_Type); procedure Write_I32 (Self : in out Checkpoint_Save_State; Value : Interfaces.Integer_32); - procedure Write_Inst (Self : in out Checkpoint_Save_State; Value : Inst_Id); procedure Write_Integer (Self : in out Checkpoint_Save_State; Value : Integer); procedure Write_PC (Self : in out Checkpoint_Save_State; Value : Pc_Type); @@ -638,9 +620,6 @@ private type CU_Id_Map_Array is array (CU_Id range <>) of CU_Id; type CU_Id_Map_Acc is access all CU_Id_Map_Array; - type Inst_Id_Map_Array is array (Inst_Id range <>) of Inst_Id; - type Inst_Id_Map_Acc is access all Inst_Id_Map_Array; - type BDD_Node_Id_Map_Array is array (BDD_Node_Id range <>) of BDD_Node_Id; type BDD_Node_Id_Map_Acc is access all BDD_Node_Id_Map_Array; @@ -661,11 +640,10 @@ private type SFI_Simple_Name_Map_Access is access all SFI_Simple_Name_Map_Array; type Checkpoint_Relocations is record - SFI_Map : SFI_Map_Acc; - CU_Map : CU_Id_Map_Acc; - Inst_Map : Inst_Id_Map_Acc; - BDD_Map : BDD_Node_Id_Map_Acc; - SCO_Map : SCO_Id_Map_Acc; + SFI_Map : SFI_Map_Acc; + CU_Map : CU_Id_Map_Acc; + BDD_Map : BDD_Node_Id_Map_Acc; + SCO_Map : SCO_Id_Map_Acc; -- Maps to replace checkpoint identifiers with local table identifiers -- after merging the checkpoint in local tables. diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index c99bda33c..c9710c4c6 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -86,26 +86,6 @@ package body SC_Obligations is -- For now, it memoizes the result for each SCO in its SCO descriptor, -- so the browsing is not duplicated. - --------------- - -- Instances -- - --------------- - - type Inst_Info is record - Sloc : Source_Location; - -- Instantiation location - - Enclosing_Instance : Inst_Id; - -- Index of enclosing instance, or No_Inst_Id if instance is not nested - - Comp_Unit : CU_Id; - -- Originating compilation unit, for sanity checking purposes - end record; - - package Inst_Info_Vectors is - new Ada.Containers.Vectors - (Index_Type => Valid_Inst_Id, - Element_Type => Inst_Info); - ------------------------ -- Source units table -- ------------------------ @@ -124,9 +104,6 @@ package body SC_Obligations is First_SCO, Last_SCO : SCO_Id := No_SCO_Id; -- First and last SCO ids for this unit - First_Instance, Last_Instance : Inst_Id := No_Inst_Id; - -- First and last index of Inst_Vector entries for this unit - Deps : SFI_Vector; -- Mapping of this unit's dependency numbers to source file indices @@ -550,10 +527,9 @@ package body SC_Obligations is -- contain data loaded from a checkpoint. type Source_Coverage_Vectors is record - CU_Vector : CU_Info_Vectors.Vector; - Inst_Vector : Inst_Info_Vectors.Vector; - BDD_Vector : BDD.BDD_Vectors.Vector; - SCO_Vector : SCO_Vectors.Vector; + CU_Vector : CU_Info_Vectors.Vector; + BDD_Vector : BDD.BDD_Vectors.Vector; + SCO_Vector : SCO_Vectors.Vector; end record; function Index @@ -633,17 +609,6 @@ package body SC_Obligations is (Valid_CU_Id, CU_Info, "=", CU_Info_Vectors, Read); -- Read a vector of CU_Info records from CLS and append them to CU_Vector - procedure Read - (CLS : in out Checkpoint_Load_State; Element : out Inst_Info); - -- Read an Inst_Info from CLS - - procedure Read is new Read_Vector - (Index_Type => Valid_Inst_Id, - Element_Type => Inst_Info, - "=" => "=", - Vectors => Inst_Info_Vectors, - Read_Element => Read); - procedure Read is new Read_Set (Element_Type => Pc_Type, Set_Type => PC_Sets.Set, @@ -708,7 +673,6 @@ package body SC_Obligations is (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; - CP_CU_Id : CU_Id; New_CU_Id : out CU_Id); -- Load CU from checkpoint that does not correspond to a current unit of -- interest. The newly assigned CU_Id is returned in New_CU_Id. @@ -717,7 +681,6 @@ package body SC_Obligations is (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; - CP_CU_Id : CU_Id; New_CU_Id : out CU_Id); -- Process one compilation unit from a checkpoint. -- CP_CU_Id is the CU_Id in the checkpoint. @@ -770,16 +733,6 @@ package body SC_Obligations is (Valid_CU_Id, CU_Info, "=", CU_Info_Vectors, Write); -- Write a vector of CU_Info records to CSS - procedure Write (CSS : in out Checkpoint_Save_State; Value : Inst_Info); - -- Write an Inst_Info to CSS - - procedure Write is new Write_Vector - (Index_Type => Valid_Inst_Id, - Element_Type => Inst_Info, - "=" => "=", - Vectors => Inst_Info_Vectors, - Write_Element => Write); - procedure Write is new Write_Set (Element_Type => Pc_Type, Set_Type => PC_Sets.Set, @@ -852,9 +805,6 @@ package body SC_Obligations is -- ranges. This is true by construction, as we remap SCOs while we load -- new units. - Inst_Vector : Inst_Info_Vectors.Vector renames SC_Vectors.Inst_Vector; - -- Vector of info for generic instantiations - BDD_Vector : BDD.BDD_Vectors.Vector renames SC_Vectors.BDD_Vector; -- Vector for BDD nodes (one per BDD node, all BDDs considered) @@ -1176,8 +1126,6 @@ package body SC_Obligations is Value.Main_Source := CLS.Read_SFI; Value.First_SCO := CLS.Read_SCO; Value.Last_SCO := CLS.Read_SCO; - Value.First_Instance := CLS.Read_Inst; - Value.Last_Instance := CLS.Read_Inst; Read (CLS, Value.Deps); Value.Has_Code := CLS.Read_Boolean; Value.Fingerprint := CLS.Read_Fingerprint; @@ -1239,14 +1187,6 @@ package body SC_Obligations is end case; end Read; - procedure Read (CLS : in out Checkpoint_Load_State; Element : out Inst_Info) - is - begin - Element.Sloc := CLS.Read_Source_Location; - Element.Enclosing_Instance := CLS.Read_Inst; - Element.Comp_Unit := CLS.Read_CU; - end Read; - procedure Read (CLS : in out Checkpoint_Load_State; Element : out SCO_Descriptor) is @@ -1534,9 +1474,9 @@ package body SC_Obligations is -- Here we already have loaded full SCO information for this CU. There -- are two things to do: -- - -- * Populate the tables mapping the SCO and instance IDs for this unit - -- in the checkpoint to their counterparts in the current context, and - -- merge non-instrumented SCO information if available. + -- * Populate the tables mapping the SCO for this unit in the checkpoint + -- to their counterparts in the current context, and merge + -- non-instrumented SCO information if available. -- -- * Merge the annotations -- @@ -1589,22 +1529,6 @@ package body SC_Obligations is end; end loop; - -- Instances - - pragma Assert - (CP_CU.Last_Instance - CP_CU.First_Instance - = - Real_CU.Last_Instance - Real_CU.First_Instance); - - for Old_Inst_Id in CP_CU.First_Instance - .. CP_CU.Last_Instance - loop - Set_Inst_Id_Map (Relocs, Old_Inst_Id, - Old_Inst_Id - + Real_CU.First_Instance - - CP_CU.First_Instance); - end loop; - -- Has_Code indication Real_CU.Has_Code := Real_CU.Has_Code or CP_CU.Has_Code; @@ -1653,13 +1577,11 @@ package body SC_Obligations is (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; - CP_CU_Id : CU_Id; New_CU_Id : out CU_Id) is Relocs : Checkpoint_Relocations renames CLS.Relocations; - New_First_Instance : Inst_Id; - New_First_SCO : SCO_Id; + New_First_SCO : SCO_Id; Cur_Source_File : Source_File_Index := No_Source_File; Last_Line : Natural := 0; @@ -1773,46 +1695,6 @@ package body SC_Obligations is CU_Map.Insert (CP_CU.Main_Source, New_CU_Id); - -- Remap instance ids - - New_First_Instance := Inst_Vector.Last_Index + 1; - for Old_Inst_Id - in CP_CU.First_Instance .. CP_CU.Last_Instance - loop - Remap_Inst : declare - New_Inst : Inst_Info := - CP_Vectors.Inst_Vector.Element (Old_Inst_Id); - - procedure Remap_Inst_Id (S : in out Inst_Id); - -- Remap an Inst_Id. Note: this assumes possible - -- forward references, and does not rely on Inst_Map. - - ------------------- - -- Remap_Inst_Id -- - ------------------- - - procedure Remap_Inst_Id (S : in out Inst_Id) is - begin - if S /= No_Inst_Id then - S := New_First_Instance - + S - - CP_CU.First_Instance; - end if; - end Remap_Inst_Id; - - -- Start of processing for Remap_Inst - - begin - Remap_SFI (Relocs, New_Inst.Sloc.Source_File); - Remap_Inst_Id (New_Inst.Enclosing_Instance); - pragma Assert (New_Inst.Comp_Unit = CP_CU_Id); - New_Inst.Comp_Unit := New_CU_Id; - - Inst_Vector.Append (New_Inst); - Set_Inst_Id_Map (Relocs, Old_Inst_Id, Inst_Vector.Last_Index); - end Remap_Inst; - end loop; - -- Remap SCO ids. Note that BDD nodes are imported (and remapped) as -- needed during the process. @@ -2015,12 +1897,6 @@ package body SC_Obligations is -- Perform final fixups and insert CU - CP_CU.Last_Instance := - New_First_Instance - + CP_CU.Last_Instance - - CP_CU.First_Instance; - CP_CU.First_Instance := New_First_Instance; - CP_CU.Last_SCO := New_First_SCO + CP_CU.Last_SCO @@ -2048,7 +1924,6 @@ package body SC_Obligations is (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; - CP_CU_Id : CU_Id; New_CU_Id : out CU_Id) is Relocs : Checkpoint_Relocations renames CLS.Relocations; @@ -2090,13 +1965,11 @@ package body SC_Obligations is (CLS, CP_Vectors, CP_CU, - CP_CU_Id => CP_CU_Id, New_CU_Id => New_CU_Id); -- Case 2: CU already loaded from LI info. Perform consistency checks, -- skipping the checkpointed unit altogether and emitting a warning if - -- there is a mismatch. Record mapping of checkpoint identifiers (SCOs - -- and instances) otherwise. + -- there is a mismatch. Record mapping of checkpoint SCOs otherwise. else declare @@ -2212,8 +2085,6 @@ package body SC_Obligations is CSS.Write_SFI (Value.Main_Source); CSS.Write_SCO (Value.First_SCO); CSS.Write_SCO (Value.Last_SCO); - CSS.Write_Inst (Value.First_Instance); - CSS.Write_Inst (Value.Last_Instance); Write (CSS, Value.Deps); CSS.Write (Value.Has_Code); CSS.Write (Value.Fingerprint); @@ -2258,14 +2129,6 @@ package body SC_Obligations is end Write; - procedure Write - (CSS : in out Checkpoint_Save_State; Value : Inst_Info) is - begin - CSS.Write (Value.Sloc); - CSS.Write_Inst (Value.Enclosing_Instance); - CSS.Write_CU (Value.Comp_Unit); - end Write; - procedure Write (CSS : in out Checkpoint_Save_State; Value : SCO_Descriptor) is begin @@ -2363,7 +2226,6 @@ package body SC_Obligations is -- This part must be kept consistent with Checkpoint_Save Read (CLS, CP_Vectors.CU_Vector); - Read (CLS, CP_Vectors.Inst_Vector); SC_Obligations.BDD.Read (CLS, CP_Vectors.BDD_Vector); Read (CLS, CP_Vectors.SCO_Vector); @@ -2411,7 +2273,7 @@ package body SC_Obligations is end loop; end; - -- Allocate mapping tables for SCOs, instance identifiers and BDD nodes + -- Allocate mapping tables for SCOs and BDD nodes Allocate_CU_Id_Maps (Relocs, CP_Vectors.CU_Vector.First_Index, @@ -2419,9 +2281,6 @@ package body SC_Obligations is Allocate_SCO_Id_Map (Relocs, CP_Vectors.SCO_Vector.First_Index, CP_Vectors.SCO_Vector.Last_Index); - Allocate_Inst_Id_Map (Relocs, - CP_Vectors.Inst_Vector.First_Index, - CP_Vectors.Inst_Vector.Last_Index); Allocate_BDD_Node_Id_Map (Relocs, CP_Vectors.BDD_Vector.First_Index, CP_Vectors.BDD_Vector.Last_Index); @@ -2472,7 +2331,6 @@ package body SC_Obligations is (CLS, CP_Vectors, CP_CU, - CP_CU_Id => CP_CU_Id, New_CU_Id => New_CU_Id); Set_CU_Id_Map (Relocs, CP_CU_Id, New_CU_Id); end if; @@ -2631,7 +2489,6 @@ package body SC_Obligations is CU_Map.Clear; Origin_To_CUs_Map.Clear; CU_Vector.Clear; - Inst_Vector.Clear; BDD_Vector.Clear; SCO_Vector.Clear; end Checkpoint_Clear; @@ -2643,7 +2500,6 @@ package body SC_Obligations is procedure Checkpoint_Save (CSS : access Checkpoint_Save_State) is begin Write (CSS.all, CU_Vector); - Write (CSS.all, Inst_Vector); BDD.Write (CSS.all, BDD_Vector); Write (CSS.all, SCO_Vector); @@ -3909,7 +3765,7 @@ package body SC_Obligations is ALI_Index : constant Source_File_Index := Load_ALI (ALI_Filename, Ignored_Source_Files, Units, Deps, Temp_ALI_Annotations, With_SCOs => True); - -- Load ALI file and update the last SCO and instance indices + -- Load ALI file and update the last SCO index begin if ALI_Index = No_Source_File then @@ -4263,8 +4119,6 @@ package body SC_Obligations is New_CU_Info.Main_Source := Main_Source; New_CU_Info.First_SCO := Valid_SCO_Id'First; New_CU_Info.Last_SCO := No_SCO_Id; - New_CU_Info.First_Instance := Valid_Inst_Id'First; - New_CU_Info.Last_Instance := No_Inst_Id; New_CU_Info.Fingerprint := Fingerprint; CU_Vector.Append (New_CU_Info); @@ -4627,8 +4481,6 @@ package body SC_Obligations is Count_Paths : Boolean; Attached_Ctx : Instr_Attached_Ctx := No_Attached_Ctx) is - use SCOs; - LI_First_SCO : constant SCO_Id := SCO_Vector.Last_Index + 1; -- Index of the first high level SCO we are going to create @@ -4644,8 +4496,7 @@ package body SC_Obligations is declare -- Record entry high water mark in high level SCO tables - First_SCO : constant SCO_Id := SCO_Vector.Last_Index + 1; - First_Instance : constant Inst_Id := Inst_Vector.Last_Index + 1; + First_SCO : constant SCO_Id := SCO_Vector.Last_Index + 1; Fingerprint : constant Fingerprint_Type := Fingerprint_Type (GNAT.SHA1.Binary_Message_Digest' @@ -4690,39 +4541,6 @@ package body SC_Obligations is Prealloc_Lines (Info.Source_File, State.Last_Line); - -- Import unit instance table into global table. Even though all - -- units created for this LI file have in principle the same - -- instance, it is necessary to duplicate them in our internal - -- tables so that they can be filtered out/consolidated - -- separately later on. - - for LL_Inst_Id in SCO_Instance_Table.First - .. SCO_Instance_Table.Last - loop - declare - SIE : SCO_Instance_Table_Entry renames - SCO_Instance_Table.Table (LL_Inst_Id); - - Sloc : constant Source_Location := - (Source_File => Deps.Element (SIE.Inst_Dep_Num), - L => (Line => Natural (SIE.Inst_Loc.Line), - Column => Natural (SIE.Inst_Loc.Col))); - - Enclosing_Inst : Inst_Id := No_Inst_Id; - -- Index of the enclosing instance for SIE - begin - -- If there is an enclosing instance, compute the index of - -- the high-level one from the index of the low-level one. - - if SIE.Enclosing_Instance /= 0 then - Enclosing_Inst := - First_Instance + Inst_Id (SIE.Enclosing_Instance) - 1; - end if; - - Inst_Vector.Append (Inst_Info'(Sloc, Enclosing_Inst, CU)); - end; - end loop; - -- Finally update CU info declare @@ -4732,9 +4550,6 @@ package body SC_Obligations is Unit.First_SCO := First_SCO; Unit.Last_SCO := SCO_Vector.Last_Index; - - Unit.First_Instance := First_Instance; - Unit.Last_Instance := Inst_Vector.Last_Index; end; end; From faa9d0aca611798f1a88938b8088ee03b548bec1 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 26 Jun 2025 11:00:59 +0200 Subject: [PATCH 1258/1483] Revert "Emit warnings in gnatcov run|coverage when binary traces are involved" This reverts commit ce9eefc4550a2be95b527a7d4f82ac581eef7237. --- .../tests/411-bin-traces-warning/main.adb | 6 -- .../tests/411-bin-traces-warning/test.opt | 1 - .../tests/411-bin-traces-warning/test.py | 88 ------------------- testsuite/testsuite.py | 4 - tools/gnatcov/gnatcov_bits_specific.adb | 4 - tools/gnatcov/rundrv.adb | 27 ++---- tools/gnatcov/rundrv.ads | 5 -- 7 files changed, 9 insertions(+), 126 deletions(-) delete mode 100644 testsuite/tests/411-bin-traces-warning/main.adb delete mode 100644 testsuite/tests/411-bin-traces-warning/test.opt delete mode 100644 testsuite/tests/411-bin-traces-warning/test.py diff --git a/testsuite/tests/411-bin-traces-warning/main.adb b/testsuite/tests/411-bin-traces-warning/main.adb deleted file mode 100644 index 3373e6745..000000000 --- a/testsuite/tests/411-bin-traces-warning/main.adb +++ /dev/null @@ -1,6 +0,0 @@ -with Ada.Text_IO; use Ada.Text_IO; - -procedure Main is -begin - Put_Line ("Hello, world!"); -end Main; diff --git a/testsuite/tests/411-bin-traces-warning/test.opt b/testsuite/tests/411-bin-traces-warning/test.opt deleted file mode 100644 index 44f772ebe..000000000 --- a/testsuite/tests/411-bin-traces-warning/test.opt +++ /dev/null @@ -1 +0,0 @@ -!bin-traces DEAD diff --git a/testsuite/tests/411-bin-traces-warning/test.py b/testsuite/tests/411-bin-traces-warning/test.py deleted file mode 100644 index d03bb2434..000000000 --- a/testsuite/tests/411-bin-traces-warning/test.py +++ /dev/null @@ -1,88 +0,0 @@ -""" -Check that gnatcov emits the expected warning when binary traces are involved. -""" - -import os - -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of, lines_of -from SUITE.gprutils import GPRswitches -from SUITE.tutils import ( - exepath_to, - gprbuild, - gprfor, - tracename_for, - xcov, - xrun, -) - - -tmp = Wdir("tmp_") - -warning = ( - "warning: Support for coverage of non-instrumented programs is deprecated" - " and will disappear after GNATcoverage 26 releases. You are encouraged to" - " migrate to instrumentation-based coverage: you can read more about it in" - " our documentation: " -) - - -def check_warning(output_file): - """Check the presence of the expecetd warning in the given text file.""" - thistest.fail_if( - warning not in lines_of(output_file), - f"Missing expected warning in {output_file}", - ) - - -# Remove the warning-disabling env var that we set at the testsuite level, -# since our goal here is precisely to check that it is emitted. -os.environ.pop("GNATCOV_NO_BINARY_TRACES_WARNING") - -gpr = gprfor(mains=["main.adb"], srcdirs=[".."]) -gprbuild(gpr) - -# Check that we have the expecetd warning both in "gnatcov run" and "gnatcov -# coverage" for binary traces. -xrun(exepath_to("main"), out="run.txt") -check_warning("run.txt") - -xcov( - [ - "coverage", - "-P", - gpr, - "-cstmt", - "-axcov", - "--output-dir=xcov-bin", - tracename_for("main"), - ], - out="coverage-bin.txt", -) -check_warning("coverage-bin.txt") -check_xcov_reports("xcov-bin", {"main.adb.xcov": {"+": {5}}}) - -# Check that we do not have it in "gnatcov instrument" nor "gnatcov coverage" -# for source traces. -build_run_and_coverage( - gprsw=GPRswitches(root_project=gpr), - covlevel="stmt", - mains=["main"], - extra_coverage_args=["--annotate=xcov", "--output-dir=xcov-src"], - trace_mode="src", -) -thistest.fail_if_not_equal( - "output of 'gnatcov instrument' (instrument.log)", - "", - contents_of("instrument.log"), -) -thistest.fail_if_not_equal( - "output of 'gnatcov coverage' for src traces (coverage.log)", - "", - contents_of("coverage.log"), -) -check_xcov_reports("xcov-src", {"main.adb.xcov": {"+": {5}}}) - -thistest.result() diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 8211f101f..f189b8ea2 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -627,10 +627,6 @@ def set_up(self): self.testcase_cmd = testcase_cmd self.testcase_timeout = timeout - # Disable the warning about usage of binary traces in gnatcov 26.* by - # default: it is irrelevant here. - os.environ["GNATCOV_NO_BINARY_TRACES_WARNING"] = "yes" - def maybe_exec(self, binfile, args=None, edir=None): """ Shortcut for the global maybe_exec. Log the result in diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 07c7254ca..0aedc2391 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -1006,7 +1006,6 @@ procedure GNATcov_Bits_Specific is Copy_Arg_List (Args.Remaining_Args, Exe_Inputs); when Cmd_Run => - Rundrv.Emit_Deprecation_Warning; -- Sort out what to use as the executable name and what EARGS to -- forward to our Eargs local, depending on whether we have an @@ -2064,9 +2063,6 @@ begin -- Record we are loading a binary trace Update_Current_Trace_Kind (Binary_Trace_File); - if not Bin_Traces_Present then - Rundrv.Emit_Deprecation_Warning; - end if; Bin_Traces_Present := True; Load_All_ALIs (Check_SCOs => False); diff --git a/tools/gnatcov/rundrv.adb b/tools/gnatcov/rundrv.adb index d4131da72..29cf5ebe3 100644 --- a/tools/gnatcov/rundrv.adb +++ b/tools/gnatcov/rundrv.adb @@ -37,16 +37,15 @@ package body Rundrv is package Env renames Ada.Environment_Variables; - Warning : constant String := - "Support for coverage of non-instrumented programs is deprecated" - & " and will disappear after GNATcoverage 26 releases. You are" + Native_Warning : constant String := + "Support for coverage of non-instrumented native programs is deprecated" + & " and will disappear after GNATcoverage 21 releases. You are" & " encouraged to migrate to instrumentation-based coverage: you can" & " read more about it in our documentation:" - & " "; - -- Warning to emit when using binary traces + & " "; + -- Warning to emit when running native programs - Warning_Envvar : constant String := "GNATCOV_NO_BINARY_TRACES_WARNING"; + Native_Warning_Envvar : constant String := "GNATCOV_NO_NATIVE_WARNING"; -- Name of the environment variable to define in order to disable this -- warning. @@ -117,6 +116,9 @@ package body Rundrv is ("No builtin or GNATemulator execution driver found for" & " target: " & Context.Target_Family.all); return; + + elsif Native and then Env.Value (Native_Warning_Envvar, "") = "" then + Outputs.Warn (Native_Warning); end if; -- And now create the trace file itself. @@ -173,15 +175,4 @@ package body Rundrv is end if; end Driver; - ------------------------------ - -- Emit_Deprecation_Warning -- - ------------------------------ - - procedure Emit_Deprecation_Warning is - begin - if Env.Value (Warning_Envvar, "") = "" then - Outputs.Warn (Warning); - end if; - end Emit_Deprecation_Warning; - end Rundrv; diff --git a/tools/gnatcov/rundrv.ads b/tools/gnatcov/rundrv.ads index b9c94ecb1..726c4d1fd 100644 --- a/tools/gnatcov/rundrv.ads +++ b/tools/gnatcov/rundrv.ads @@ -53,9 +53,4 @@ package Rundrv is -- command-line arguments for Exe_File. Write traces in the Output trace -- file. If Tag is not null, append it to the trace header. - procedure Emit_Deprecation_Warning; - -- Unless the GNATCOV_NO_BINARY_TRACES_WARNING environment variable is set, - -- emit a warning to say that support for coverage of non-instrumented - -- programs is deprecated. - end Rundrv; From 4a0ea493ba6b42dcc5020d5e7566bc733c4203da Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 27 May 2025 12:31:28 +0200 Subject: [PATCH 1259/1483] instr-ada_unit: create a 'Rewriting_Utils' unit to abstract AST rewritings --- .../instrument-ada_unit-rewriting_utils.adb | 73 +++++++++++++++++++ .../instrument-ada_unit-rewriting_utils.ads | 55 ++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 7 +- 3 files changed, 130 insertions(+), 5 deletions(-) create mode 100644 tools/gnatcov/instrument-ada_unit-rewriting_utils.adb create mode 100644 tools/gnatcov/instrument-ada_unit-rewriting_utils.ads diff --git a/tools/gnatcov/instrument-ada_unit-rewriting_utils.adb b/tools/gnatcov/instrument-ada_unit-rewriting_utils.adb new file mode 100644 index 000000000..3404e4585 --- /dev/null +++ b/tools/gnatcov/instrument-ada_unit-rewriting_utils.adb @@ -0,0 +1,73 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2008-2025, 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. -- +------------------------------------------------------------------------------ + +package body Instrument.Ada_Unit.Rewriting_Utils is + + ----------------------- + -- Wrap_In_Call_Expr -- + ----------------------- + + procedure Wrap_In_Call_Expr + (RH : Rewriting_Handle; + Prefix : Text_Type; + Node : in out Node_Rewriting_Handle) is + begin + Node := Create_Call_Expr + (RH, + F_Name => Make_Identifier (RH, Prefix), + F_Suffix => Create_Regular_Node + (RH, + Ada_Assoc_List, + (1 => Create_Param_Assoc + (RH, + F_Designator => No_Node_Rewriting_Handle, + F_R_Expr => Node)))); + end Wrap_In_Call_Expr; + + ------------------------- + -- Wrap_In_Parentheses -- + ------------------------- + + procedure Wrap_In_Parentheses + (RH : Rewriting_Handle; + Node : in out Node_Rewriting_Handle) is + begin + Node := Create_Paren_Expr (RH, F_Expr => Node); + end Wrap_In_Parentheses; + + --------------------- + -- Wrap_In_If_Expr -- + --------------------- + + procedure Wrap_In_If_Expr + (RH : Rewriting_Handle; + Node : in out Node_Rewriting_Handle) is + begin + Node := Create_If_Expr + (RH, + F_Cond_Expr => Node, + F_Then_Expr => + Make_Identifier (RH, To_Text ("True")), + F_Alternatives => No_Node_Rewriting_Handle, + F_Else_Expr => + Make_Identifier (RH, To_Text ("False"))); + + Wrap_In_Parentheses (RH, Node); + end Wrap_In_If_Expr; + +end Instrument.Ada_Unit.Rewriting_Utils; diff --git a/tools/gnatcov/instrument-ada_unit-rewriting_utils.ads b/tools/gnatcov/instrument-ada_unit-rewriting_utils.ads new file mode 100644 index 000000000..254b520c4 --- /dev/null +++ b/tools/gnatcov/instrument-ada_unit-rewriting_utils.ads @@ -0,0 +1,55 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2008-2025, 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 Libadalang.Common; use Libadalang.Common; + +private package Instrument.Ada_Unit.Rewriting_Utils is + + -- This unit is meant to abstract the AST handling from the logic. + -- Ideally, we should follow guidelines to make sure it does not become + -- unmanageable in the future: + -- + -- 1. All subprograms should either be named `Make_...` or `Wrap_In_...` + -- (this can evolve if needed). + -- 2. The first argument of each subprogram should be the Rewriting_Handle. + -- 3. `Make_...` subprograms should be FUNCTIONS that return a Node. + -- 4. `Wrap_In_...` subprograms should be PROCEDURES to which we pass an + -- "in out Node" argument. + + function Make_Identifier + (RH : Rewriting_Handle; Id : Text_Type) return Node_Rewriting_Handle + is (Create_Token_Node (RH, Libadalang.Common.Ada_Identifier, Id)); + -- Shortcut to create an identifier node + + procedure Wrap_In_Call_Expr + (RH : Rewriting_Handle; + Prefix : Text_Type; + Node : in out Node_Rewriting_Handle); + -- Change "Node" into "Prefix(Node)" + + procedure Wrap_In_Parentheses + (RH : Rewriting_Handle; + Node : in out Node_Rewriting_Handle); + -- Change "Node" into "(Node)" + + procedure Wrap_In_If_Expr + (RH : Rewriting_Handle; + Node : in out Node_Rewriting_Handle); + -- Change "Node" into "(if Node then True else False)" + +end Instrument.Ada_Unit.Rewriting_Utils; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index bdfbd9089..3762a45d9 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -46,6 +46,8 @@ with Coverage_Options; use Coverage_Options; with Coverage; use Coverage; with Diagnostics; use Diagnostics; with Instrument.Ada_Preprocessing; +with Instrument.Ada_Unit.Rewriting_Utils; +use Instrument.Ada_Unit.Rewriting_Utils; with JSON; use JSON; with Namet; use Namet; with Outputs; use Outputs; @@ -483,11 +485,6 @@ package body Instrument.Ada_Unit is is (Create_Node (UIC.Rewriting_Context, K)); -- Shortcut to create a node of the given kind - function Make_Identifier - (RH : Rewriting_Handle; Id : Text_Type) return Node_Rewriting_Handle - is (Create_Token_Node (RH, Libadalang.Common.Ada_Identifier, Id)); - -- Shortcut to create an identifier node - function Make_Defining_Name (UIC : Ada_Unit_Inst_Context'Class; D_Name : Wide_Wide_String) return Node_Rewriting_Handle From d218f2fe38e80efcd50a4e9bb96c373c9bf3b95b Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 22 May 2025 16:22:27 +0200 Subject: [PATCH 1260/1483] instr-ada_unit: If Ada>2012, replace boolean cast with if-expr wrapping --- tools/gnatcov/instrument-ada_unit.adb | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 3762a45d9..70fee2881 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -78,6 +78,10 @@ package body Instrument.Ada_Unit is -- Set of versions of the Ada language that support declare -- expressions. + subtype If_Expr_Supported_Versions is Any_Language_Version range + Ada_2012 .. Any_Language_Version'Last; + -- Set of versions of the Ada language that support if expressions. + function Create_Context_Instrument (N : Libadalang.Analysis.Ada_Node'Class) return Context_Handle; -- Create a context to show that gnatcov is instrumenting the given node @@ -8179,17 +8183,14 @@ package body Instrument.Ada_Unit is -- we can simply convert the original expression to -- Standard.Boolean. - Old_Cond := Create_Call_Expr - (RC, - F_Name => Make_Identifier - (RC, To_Text ("GNATcov_RTS.Std.Boolean")), - F_Suffix => Create_Regular_Node + if UIC.Language_Version in If_Expr_Supported_Versions then + Wrap_In_If_Expr (RC, Old_Cond); + else + Wrap_In_Call_Expr (RC, - Ada_Assoc_List, - (1 => Create_Param_Assoc - (RC, - F_Designator => No_Node_Rewriting_Handle, - F_R_Expr => Old_Cond)))); + Prefix => To_Text ("GNATcov_RTS.Std.Boolean"), + Node => Old_Cond); + end if; Set_Child (New_Cond, Member_Refs.Bin_Op_F_Right, Old_Cond); From e6accc16d00a2a99a5e656631dffd4084a4b43d8 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 27 May 2025 12:19:19 +0200 Subject: [PATCH 1261/1483] testsuite: Pass `--ada` flag to gnatcov instrument depending on `-gnat....` flag --- testsuite/SCOV/instr.py | 4 +++ testsuite/SUITE/context.py | 6 +++++ testsuite/SUITE/control.py | 2 +- testsuite/testsuite.py | 55 ++++++++++++++++++++++++++++++++++++-- 4 files changed, 64 insertions(+), 3 deletions(-) diff --git a/testsuite/SCOV/instr.py b/testsuite/SCOV/instr.py index eeb5ea816..7f77781c0 100644 --- a/testsuite/SCOV/instr.py +++ b/testsuite/SCOV/instr.py @@ -142,6 +142,10 @@ def xcov_instrument( if thistest.options.block: args.append("--instrument-block") + # Get the Ada version from the test framework + if thistest.options.ada_version: + args += ["--ada", thistest.options.ada_version] + # TODO (gpr-issues#241) temporary workaround. # Since gpr2clean deletes .sid files for the moment, we need to # clean the project before instrumenting (this used to be done before the diff --git a/testsuite/SUITE/context.py b/testsuite/SUITE/context.py index 279b7e60a..978187d78 100644 --- a/testsuite/SUITE/context.py +++ b/testsuite/SUITE/context.py @@ -457,6 +457,12 @@ def __cmdline_options(self): parser.add_argument("--tags", default="") + parser.add_argument( + "--ada-version", + help="Ada version that is passed to gnatcov instrument", + default="", + ) + control.add_shared_options_to(parser, toplevel=False) main.parse_args() diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index 523557124..ed74ea7fb 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -618,7 +618,7 @@ def add_shared_options_to(parser, toplevel): dest="spark_tests", metavar="SPARK_TESTSUITE_PATH", help="Path to the SPARK testsuite. Activate SPARK-specific" - " tests. Implicitly appends -gnat12 to Ada cargs.", + " tests. Implicitly appends -gnat2022 to Ada cargs.", ) # --all-warnings diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index f189b8ea2..e6ecc79ce 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -7,6 +7,7 @@ See ./testsuite.py -h for more help """ +import logging import time import os import re @@ -582,6 +583,9 @@ def set_up(self): if mopt.block: testcase_cmd.append("--block") + if mopt.ada_version: + testcase_cmd.append(f"--ada-version={mopt.ada_version}") + # --gnatcov_ family for pgm, cmd in control.ALTRUN_GNATCOV_PAIRS: @@ -1183,23 +1187,70 @@ def set_up(self): # running for qualification, making sure we know what target language # we're qualifying for. + def _get_canonical_ada_version(ada_ver: str) -> str: + if ada_ver in ["83", "95"]: + # For Ada 1983 and 1995, only -gnatYY is correct + return ada_ver + elif ada_ver in ["05", "2005"]: + # For Ada 2005, use "05" to make sure all compilers get it. + return "05" + elif ada_ver[-2:] in ["12", "22"]: + # Since Ada 2012, -gnatYY and -gnatYYYY are accepted + # For Ada 2022, -gnatYYYY is mandatory + return "20" + ada_ver[-2:] + raise FatalError(f"Unable to retrieve Ada version from {ada_ver}") + attr_cargs_ada = cargs_attr_for("Ada") cargs_ada = getattr(args, attr_cargs_ada) attr_cargs = cargs_attr_for("") cargs = getattr(args, attr_cargs) - if not re.search("-gnat95|-gnat05|-gnat12", cargs_ada + cargs): + + gnatcov_instr_ada_version = None + qualifiable_ada_versions = ["95", "05", "12"] + qav_str = "|".join(qualifiable_ada_versions) + ada_version_match = re.match( + r"-gnat(95|(?:20)?(?:05|12)|2022)", cargs_ada + cargs + ) + + if ada_version_match: + ada_version = _get_canonical_ada_version( + ada_version_match.groups()[0] + ) + + if ( + args.qualif_level + and ada_version[-2:] not in qualifiable_ada_versions + ): + raise FatalError( + f"-gnat{ada_version} is invalid for qualification. " + f"Allowed versions are -gnat<{qav_str}>" + ) + + logging.debug( + f"Setting Ada version to Ada {ada_version} from cargs" + ) + gnatcov_instr_ada_version = ada_version + else: if args.qualif_level: raise FatalError( - "Missing -gnat<95|05|12> in cargs:Ada for qualification" + f"Missing -gnat<{qav_str}> in cargs:Ada for qualification" ) else: + logging.debug("Setting default Ada version to Ada 05") + gnatcov_instr_ada_version = "05" setattr(args, attr_cargs_ada, cargs_ada + " -gnat05") # Most SPARK testcases require Ada 2022 if args.spark_tests: + logging.debug("Setting Ada version to Ada 2022 for SPARK") + gnatcov_instr_ada_version = "2022" setattr(args, attr_cargs_ada, cargs_ada + " -gnat2022") + # Make sure gnatcov instrument is called with the same Ada version as + # the one passed to gnat afterwards + args.ada_version = gnatcov_instr_ada_version + # Expect an explicit -gnatec if we're running for qualification if args.qualif_level and "-gnatec" not in cargs_ada: From 746e5b358af6133e8e18f56e360e97566b87acd3 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 27 May 2025 12:20:32 +0200 Subject: [PATCH 1262/1483] instr-ada_unit: Reset Language_Version before instrumenting a file To avoid propagating a language version pragma from spec to body --- tools/gnatcov/instrument-ada_unit.adb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 70fee2881..93e0297de 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -9954,6 +9954,11 @@ package body Instrument.Ada_Unit is -- Whether there is a pragma Short_Circuit_And_Or that applies to this -- unit. begin + -- Reset the language version to the default of the program to avoid + -- a 'pragma ' to be propagated from the spec to body. + + UIC.Language_Version := Switches.Global_Language_Version; + Start_Rewriting (Rewriter, Instrumenter, Prj, Filename); Root_Analysis_Unit := Rewriter.Rewritten_Unit; From 1ecee4740ef25c03b7206078348f945f9b321223 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 27 May 2025 11:52:14 +0200 Subject: [PATCH 1263/1483] tests: Add a check for if-expr/cast usage and another test to replicate issue #409 --- .../src/main_with_pragma.adb | 19 ++++++ .../src/main_without_pragma.adb | 17 ++++++ .../409-ambiguous-operand/src/pref.ads | 15 +++++ .../instr-cov/409-ambiguous-operand/test.opt | 5 ++ .../instr-cov/409-ambiguous-operand/test.py | 60 +++++++++++++++++++ 5 files changed, 116 insertions(+) create mode 100644 testsuite/tests/instr-cov/409-ambiguous-operand/src/main_with_pragma.adb create mode 100644 testsuite/tests/instr-cov/409-ambiguous-operand/src/main_without_pragma.adb create mode 100644 testsuite/tests/instr-cov/409-ambiguous-operand/src/pref.ads create mode 100644 testsuite/tests/instr-cov/409-ambiguous-operand/test.opt create mode 100644 testsuite/tests/instr-cov/409-ambiguous-operand/test.py diff --git a/testsuite/tests/instr-cov/409-ambiguous-operand/src/main_with_pragma.adb b/testsuite/tests/instr-cov/409-ambiguous-operand/src/main_with_pragma.adb new file mode 100644 index 000000000..c8a0ef4ba --- /dev/null +++ b/testsuite/tests/instr-cov/409-ambiguous-operand/src/main_with_pragma.adb @@ -0,0 +1,19 @@ +pragma Ada_2012; + +with Ada.Text_IO; use Ada.Text_IO; +with Pref; use Pref; + +procedure Main_With_Pragma is + procedure Foo (B: Boolean) is + BB : Preference := Preference(B); + begin + if B then + Put_Line ("Coucou"); + elsif Get_Pref (BB) then + Put_Line ("test"); + end if; + end Foo; +begin + Put_Line ("Hello World"); + Foo (True); +end Main_With_Pragma; diff --git a/testsuite/tests/instr-cov/409-ambiguous-operand/src/main_without_pragma.adb b/testsuite/tests/instr-cov/409-ambiguous-operand/src/main_without_pragma.adb new file mode 100644 index 000000000..8a0640000 --- /dev/null +++ b/testsuite/tests/instr-cov/409-ambiguous-operand/src/main_without_pragma.adb @@ -0,0 +1,17 @@ +with Ada.Text_IO; use Ada.Text_IO; +with Pref; use Pref; + +procedure Main_Without_Pragma is + procedure Foo (B: Boolean) is + BB : Preference := Preference(B); + begin + if B then + Put_Line ("Coucou"); + elsif Get_Pref (BB) then + Put_Line ("test"); + end if; + end Foo; +begin + Put_Line ("Hello World"); + Foo (True); +end Main_Without_Pragma; diff --git a/testsuite/tests/instr-cov/409-ambiguous-operand/src/pref.ads b/testsuite/tests/instr-cov/409-ambiguous-operand/src/pref.ads new file mode 100644 index 000000000..ca6f0d238 --- /dev/null +++ b/testsuite/tests/instr-cov/409-ambiguous-operand/src/pref.ads @@ -0,0 +1,15 @@ +pragma Ada_2012; + +package Pref is + + type Preference is new Boolean; + + function Get_Pref (P : Preference) return Preference is ((case P is + when True => True, + when False => False)); + + function Get_Pref (P : Preference) return String + is ((case P is + when True => "TRUE", + when False => "FALSE")); +end Pref; diff --git a/testsuite/tests/instr-cov/409-ambiguous-operand/test.opt b/testsuite/tests/instr-cov/409-ambiguous-operand/test.opt new file mode 100644 index 000000000..2f0d6368e --- /dev/null +++ b/testsuite/tests/instr-cov/409-ambiguous-operand/test.opt @@ -0,0 +1,5 @@ +!src-traces DEAD instrumentation-related test +5.04a1 DEAD Test requires Ada 2012 support +7.1.2 DEAD Test requires Ada 2012 support +CARGS_gnat2012 DEAD The test is expected to run on Ada 2005 or lower +CARGS_gnat2022 DEAD The test is expected to run on Ada 2005 or lower diff --git a/testsuite/tests/instr-cov/409-ambiguous-operand/test.py b/testsuite/tests/instr-cov/409-ambiguous-operand/test.py new file mode 100644 index 000000000..094e6993f --- /dev/null +++ b/testsuite/tests/instr-cov/409-ambiguous-operand/test.py @@ -0,0 +1,60 @@ +""" +Check that when the language version permits it, use an if-expr instead of a +Boolean type conversion to avoid the "ambiguous operand" error. + +Otherwise, the instrumentation may produce code that is not compilable. +Workarounds include manually qualifying the type to disambigue the expression, +or removing the problematic unit from coverage analysis + +NOTE: Assume that the testsuite is run with -gnat05 by default +""" + +import re + +from SCOV.minicheck import build_and_run +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.dutils import contents_of +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, gprbuild + +_wd = Wdir("tmp_") + +gpr = gprfor( + mains=["main_with_pragma.adb"], + srcdirs=["../src"], +) + +# Should work +result = build_and_run( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt", + mains=["main_with_pragma"], + register_failure=True, + extra_coverage_args=[], +) + +# Do the same but without the version pragma. +gpr_without = gprfor( + mains=["main_without_pragma.adb"], + srcdirs=["../src"], +) +gprsw = GPRswitches(root_project=gpr_without) + +xcov_instrument( + gprsw=gprsw, + covlevel="stmt", +) +build_p = gprbuild( + gprsw.root_project, gargs=gprsw.build_switches, register_failure=False +) + +thistest.fail_if(build_p.status == 0, "Compilation should have failed") +thistest.fail_if_no_match( + "Compilation should fail with 'ambiguous operand'", + re.compile(r".*ambiguous operand.*", flags=re.S), + contents_of("gprbuild.out"), +) + +thistest.result() From a89cff8582408d03424e4691b370dfc284f8b955 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 9 Jun 2025 12:46:37 +0200 Subject: [PATCH 1264/1483] tests: Add a check to ensure `pragma ` is not propagated from spec to body --- .../pragma_no_propagate/src/main.adb | 8 +++++ .../instr-cov/pragma_no_propagate/src/pkg.adb | 21 +++++++++++++ .../instr-cov/pragma_no_propagate/src/pkg.ads | 7 +++++ .../instr-cov/pragma_no_propagate/test.opt | 2 ++ .../instr-cov/pragma_no_propagate/test.py | 31 +++++++++++++++++++ 5 files changed, 69 insertions(+) create mode 100644 testsuite/tests/instr-cov/pragma_no_propagate/src/main.adb create mode 100644 testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.adb create mode 100644 testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.ads create mode 100644 testsuite/tests/instr-cov/pragma_no_propagate/test.opt create mode 100644 testsuite/tests/instr-cov/pragma_no_propagate/test.py diff --git a/testsuite/tests/instr-cov/pragma_no_propagate/src/main.adb b/testsuite/tests/instr-cov/pragma_no_propagate/src/main.adb new file mode 100644 index 000000000..07a2d970a --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_propagate/src/main.adb @@ -0,0 +1,8 @@ +with Pkg; use Pkg; + +procedure Main is +begin + if Is_Space ('C') then + null; + end if; +end Main; diff --git a/testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.adb b/testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.adb new file mode 100644 index 000000000..bf91d8818 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.adb @@ -0,0 +1,21 @@ +package body Pkg is + + function Is_Space (C : Character) return Boolean is + begin + if C = ' ' then + return True; + + -- If gnatcov instrument wrongly propagates `pragma Ada_2012` from + -- the spec to this body, it will create an if-expression here. + -- This would make the instrumented sources fail to compile when gnat + -- is invoked with -gnat05 or lower. + + elsif C = ASCII.HT then + + return True; + end if; + + return False; + end Is_Space; + +end Pkg; diff --git a/testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.ads b/testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.ads new file mode 100644 index 000000000..e5efe936b --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_propagate/src/pkg.ads @@ -0,0 +1,7 @@ +pragma Ada_2012; + +package Pkg is + + function Is_Space (C : Character) return Boolean; + +end Pkg; diff --git a/testsuite/tests/instr-cov/pragma_no_propagate/test.opt b/testsuite/tests/instr-cov/pragma_no_propagate/test.opt new file mode 100644 index 000000000..bd27d7482 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_propagate/test.opt @@ -0,0 +1,2 @@ +CARGS_gnat2012 DEAD The test is expected to run on Ada 2005 or lower +CARGS_gnat2022 DEAD The test is expected to run on Ada 2005 or lower diff --git a/testsuite/tests/instr-cov/pragma_no_propagate/test.py b/testsuite/tests/instr-cov/pragma_no_propagate/test.py new file mode 100644 index 000000000..23660ef52 --- /dev/null +++ b/testsuite/tests/instr-cov/pragma_no_propagate/test.py @@ -0,0 +1,31 @@ +""" +Ensure that a `Pragma Ada_` in a unit's spec does not propagate to its +body at instrumentation. +To do so, use the alternative instrumentation of elsifs, which uses if exprs +with Ada>=2012, and casts otherwise. + +Note: The test is supposed to run on a Ada 2005 or below +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + +_wd = Wdir("tmp_") + +gpr = gprfor( + mains=["main.adb"], + srcdirs=["../src"], +) + +result = build_and_run( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt+gexpr", + mains=["main"], + register_failure=True, + extra_coverage_args=[], +) + +thistest.result() From c63b61489cb74b6d4c0cb10aacf2f17566c49529 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 13 Jun 2025 12:10:38 +0200 Subject: [PATCH 1265/1483] doc: Document the instrumentation differences depending on Ada language version --- doc/gnatcov/src_traces.rst | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 698536f73..cb5f79e2b 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -566,6 +566,13 @@ Below are listed the limitations associated with general Ada sources. Coverage of SPARK sources require additional considerations, detailed in section :ref:`spark_instr`. +|gcvins| limitations are inherently bound to the version of the Ada language +used. The version is indicated to the tool via the ``--ada`` command line +switch, which is set to ``2012`` by default. Additionally, |gcvins| can also +retrieve the langage version for a specific source file which contains a +``pragma Ada_nnnn;`` directive. The pragma prevails on the command line +argument. + Unsupported source constructs ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -582,10 +589,8 @@ The list of unsupported constructs is as follows: * Protected bodies entry guards when the ``Simple_Barriers`` restriction or the ``Pure_Barriers`` one apply. -Additionally, if the Ada language version in use, indicated to the tool by -either a ``pragma Ada_nnnn`` pragma in the sources or through the ``--ada`` -command line switch, is less or equal to Ada 2012, the following constructs are -also unsupported: +Additionally, if the Ada language version in use, is less or equal to Ada 2012, +the following constructs are also unsupported: * Generic expression functions, * Recursive expression functions which are primitives of some tagged type, @@ -626,6 +631,14 @@ whole: - Separate analysis of generic package instances is not supported. +Additionally, the detected Ada language version can also alter the way some +constructs are instrumented, to use new language features and make the +instrumentation more robust. + +This limitation happens on the decision coverage level, which makes use of +if-expressions to instrument ``elsif`` decisions when the language version is +2012 or above. + Toolchain-specific limitations ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From a38558e9d08450204fd865f157c58555e0d51b42 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 29 Apr 2025 14:00:19 +0200 Subject: [PATCH 1266/1483] Add LLVM_Trace_File Kind --- tools/gnatcov/checkpoints.adb | 6 ++++-- tools/gnatcov/gnatcov_bits_specific.adb | 3 +++ tools/gnatcov/project.adb | 6 +++--- tools/gnatcov/project.ads | 2 +- tools/gnatcov/traces_files.adb | 23 +++++++++++++++++++---- tools/gnatcov/traces_files.ads | 6 +++++- 6 files changed, 35 insertions(+), 11 deletions(-) diff --git a/tools/gnatcov/checkpoints.adb b/tools/gnatcov/checkpoints.adb index 9a6755b76..073fee638 100644 --- a/tools/gnatcov/checkpoints.adb +++ b/tools/gnatcov/checkpoints.adb @@ -444,8 +444,10 @@ package body Checkpoints is declare Bits : constant Binary_Traces_Bits := (case Currently_Accepted_Trace_Kind is - when Unknown | Source_Trace_File => Undetermined, - when Binary_Trace_File | All_Trace_Files => Supported_Bits); + when Unknown | Source_Trace_File | LLVM_Trace_File => + Undetermined, + when Binary_Trace_File | All_Trace_Files => + Supported_Bits); begin CSS.Write_U8 (Binary_Traces_Bits'Pos (Bits)); end; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 0aedc2391..ac7c1a0a7 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -252,6 +252,7 @@ procedure GNATcov_Bits_Specific is and then LLVM_JSON_Ckpt_Inputs.Is_Empty and then SID_Inputs.Is_Empty and then ALIs_Inputs.Is_Empty + and then Args.String_List_Args (Opt_Exec).Is_Empty and then not Args.String_Args (Opt_Project).Present then Report_Missing_Argument @@ -1991,6 +1992,8 @@ begin (Trace_File_Name, Exec_Name_Override); when Source_Trace_File => Process_Source_Trace (Trace_File_Name); + when LLVM_Trace_File => + Outputs.Fatal_Error ("LLVM trace file not implemented"); end case; end Process_Trace; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 14dcb995a..7c4869c2b 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -108,7 +108,7 @@ package body Project is function SCO_Filename (Source : GPR2.Build.Source.Object; - Kind : Trace_File_Kind) + Kind : GNATcov_Trace_File_Kind) return GPR2.Path_Name.Object; -- Return the SCO absolute filename corresponding to the given source file -- and the given trace kind (.ali/.gli for binary traces, .sid for source @@ -523,7 +523,7 @@ package body Project is function SCO_Filename (Source : GPR2.Build.Source.Object; - Kind : Trace_File_Kind) + Kind : GNATcov_Trace_File_Kind) return GPR2.Path_Name.Object is Is_Ada : constant Boolean := Source.Language = GPR2.Ada_Language; @@ -568,7 +568,7 @@ package body Project is procedure Enumerate_SCOs_Files (Callback : access procedure (Lib_Name : String); - Kind : Trace_File_Kind) + Kind : GNATcov_Trace_File_Kind) is Files_Found : String_Sets.Set; begin diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 244ab4252..7f6398076 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -144,7 +144,7 @@ package Project is procedure Enumerate_SCOs_Files (Callback : access procedure (Lib_Name : String); - Kind : Traces_Files.Trace_File_Kind) + Kind : Traces_Files.GNATcov_Trace_File_Kind) with Pre => Is_Project_Loaded; -- Invoke Callback once for every SCOs file (SID / ALI depending on the -- trace mode) corresponding to a unit of interest. This emits a warning diff --git a/tools/gnatcov/traces_files.adb b/tools/gnatcov/traces_files.adb index 0e0de600e..2bbe9055e 100644 --- a/tools/gnatcov/traces_files.adb +++ b/tools/gnatcov/traces_files.adb @@ -258,7 +258,7 @@ package body Traces_Files is case Current_Trace_Kind is when Unknown => Current_Trace_Kind := New_Kind; - when Source_Trace_File | Binary_Trace_File => + when GNATcov_Trace_File_Kind => if Current_Trace_Kind /= New_Kind then -- Warn or emit an error message if we have inconsistent @@ -271,6 +271,14 @@ package body Traces_Files is end if; Current_Trace_Kind := All_Trace_Files; end if; + when LLVM_Trace_File => + + -- ??? Review the possibility of merging LLVM traces with others + -- when everything works. + + if Current_Trace_Kind /= New_Kind then + Fatal_Error (Trace_Mix_Error_Msg); + end if; when All_Trace_Files => -- We cannot accept more trace kinds than All_Trace_File, @@ -303,6 +311,8 @@ package body Traces_Files is return "binary"; when Source_Trace_File => return "source"; + when LLVM_Trace_File => + return "LLVM"; end case; end Image; @@ -373,11 +383,14 @@ package body Traces_Files is is Fd : constant File_Descriptor := Open_Read (Filename, Binary); - Binary_Magic : String renames Qemu_Trace_Magic; - Source_Magic : String renames Traces_Source.Trace_File_Magic; + Binary_Magic : String renames Qemu_Trace_Magic; + Source_Magic : String renames Traces_Source.Trace_File_Magic; + LLVM_Raw_Magic : constant String := + String'(Character'Val (16#81#) & "rforpl" & Character'Val (16#FF#)); Magic_Max_Size : constant Natural := Integer'Max - (Binary_Magic'Length, Source_Magic'Length); + (LLVM_Raw_Magic'Length, + Integer'Max (Binary_Magic'Length, Source_Magic'Length)); Buffer : String (1 .. Magic_Max_Size); function Magic_Matches (Magic : String) return Boolean @@ -399,6 +412,8 @@ package body Traces_Files is Kind := Binary_Trace_File; elsif Magic_Matches (Source_Magic) then Kind := Source_Trace_File; + elsif Magic_Matches (LLVM_Raw_Magic) then + Kind := LLVM_Trace_File; else Create_Error (Result, "invalid trace file: " & Filename); end if; diff --git a/tools/gnatcov/traces_files.ads b/tools/gnatcov/traces_files.ads index 0bad472eb..db03b0967 100644 --- a/tools/gnatcov/traces_files.ads +++ b/tools/gnatcov/traces_files.ads @@ -49,7 +49,8 @@ package Traces_Files is -- if it's a binary trace file or a source trace file. type Any_Accepted_Trace_Kind is - (Unknown, Binary_Trace_File, Source_Trace_File, All_Trace_Files); + (Unknown, Binary_Trace_File, Source_Trace_File, + LLVM_Trace_File, All_Trace_Files); -- We normally do not allow to mix trace kinds, but in case this should be -- supported in the future we have "All_Trace_File" to represent that -- gnatcov accepts both kinds of traces. @@ -64,6 +65,9 @@ package Traces_Files is -- only emit a warning and not an error. subtype Trace_File_Kind + is Any_Accepted_Trace_Kind range Binary_Trace_File .. LLVM_Trace_File; + + subtype GNATcov_Trace_File_Kind is Any_Accepted_Trace_Kind range Binary_Trace_File .. Source_Trace_File; function Image (Kind : Trace_File_Kind) return String; From 9ddf6f9ee31594bbcec838563bc47dfa7a59ab4c Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 30 Apr 2025 15:22:52 +0200 Subject: [PATCH 1267/1483] Move part of coverage in function --- tools/gnatcov/gnatcov_bits_specific.adb | 981 ++++++++++++------------ 1 file changed, 497 insertions(+), 484 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index ac7c1a0a7..09a0971e8 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -195,6 +195,495 @@ procedure GNATcov_Bits_Specific is -- Emit the error corresponding to Result with Outputs. If -- Keep_Reading_Tracess is false, this is a fatal error. + procedure Read_And_Process_GNATcov_Traces (Base_Acc : access Traces_Base); + -- Part of `gnatcov coverage` that handles reading trace files and loading + -- them in the internal structures. + + ------------------------------------- + -- Read_And_Process_GNATcov_Traces -- + ------------------------------------- + + procedure Read_And_Process_GNATcov_Traces (Base_Acc : access Traces_Base) is + Bin_Traces_Present : Boolean := False; + Src_Traces_Present : Boolean := False; + + procedure Process_Exec (Exec_Name : String); + -- Load a consolidated executable + + procedure Process_Trace + (Trace_File_Name : String; + Exec_Name_Override : String); + -- Try to read Trace_File_Name. Depending on the probed trace file + -- kind, dispatch to Process_Binary_Trace or Process_Source_Trace. + -- If Trace_File_Name is an empty string, just dispatch to + -- Process_Binary_Trace (case of forcing the load of a program). + + procedure Process_Source_Trace (Trace_File_Name : String); + -- Process the given source trace file, discharging SCIs + -- referenced by its coverage buffers. + + procedure Process_Binary_Trace + (Trace_File_Name : String; + Exec_Name_Override : String); + -- Common dispatching point for object and source coverage: + -- process one trace file (with optional override of exec file + -- name), or load one consolidated executable (if Trace_File_Name + -- is an empty string, in which case Exec_Name_Override is not + -- allowed to be null). + + procedure Process_Trace_For_Obj_Coverage + (Trace_File : Trace_File_Element_Acc; + Exec_Name_Override : String); + -- Open Trace_File and merge it into the trace database + + procedure Process_Trace_For_Src_Coverage + (Trace_File : Trace_File_Element_Acc; + Exec_Name_Override : String); + -- Process Trace_File for source coverage. No trace database is + -- used. + + function Open_Exec_For_Trace + (Trace_File_Name : String; + Trace_File : Trace_File_Type; + Exec_Name_Override : String) return Exe_File_Acc; + -- Open the executable for TF, taking into account a possible + -- command line override of the executable file name. The opened + -- exec file is entered in the global execs list. + + ------------------------- + -- Open_Exec_For_Trace -- + ------------------------- + + function Open_Exec_For_Trace + (Trace_File_Name : String; + Trace_File : Trace_File_Type; + Exec_Name_Override : String) return Exe_File_Acc + is + use Qemu_Traces; + + function Get_Exe_Name return String; + -- Executable name as determined from trace file or overridden + + ------------------ + -- Get_Exe_Name -- + ------------------ + + function Get_Exe_Name return String is + begin + if Exec_Name_Override /= "" then + return Exec_Name_Override; + end if; + + declare + Exec_Name_From_Trace : constant String := + Get_Info (Trace_File, Exec_File_Name); + begin + if Exec_Name_From_Trace = "" then + Fatal_Error + ("Cannot find executable filename in trace file " + & Trace_File_Name); + end if; + + return Exec_Name_From_Trace; + end; + end Get_Exe_Name; + + Exe_Name : constant String := Get_Exe_Name; + + -- Start of processing for Open_Exec_For_Trace + + begin + return Exe_File : Exe_File_Acc do + Execs_Dbase.Open_Exec_For_Trace + (Exe_Name, Text_Start, + Trace_File_Name, Get_Signature (Trace_File), + Exe_File); + end return; + exception + when E : Binary_Files.Error => + Fatal_Error ("Cannot open ELF file " & Exe_Name + & " for trace file " & Trace_File_Name & ": " + & Switches.Exception_Info (E)); + end Open_Exec_For_Trace; + + ------------------ + -- Process_Exec -- + ------------------ + + procedure Process_Exec (Exec_Name : String) is + begin + Load_All_ALIs (Check_SCOs => False); + Process_Trace + (Trace_File_Name => "", Exec_Name_Override => Exec_Name); + end Process_Exec; + + ------------------- + -- Process_Trace -- + ------------------- + + procedure Process_Trace + (Trace_File_Name : String; + Exec_Name_Override : String) + is + Kind : Trace_File_Kind; + Result : Read_Result; + begin + if Trace_File_Name = "" then + Process_Binary_Trace (Trace_File_Name, Exec_Name_Override); + return; + end if; + + Probe_Trace_File (Trace_File_Name, Kind, Result); + if not Result.Success then + Report_Bad_Trace (Trace_File_Name, Result); + end if; + + case Kind is + when Binary_Trace_File => + Process_Binary_Trace + (Trace_File_Name, Exec_Name_Override); + when Source_Trace_File => + Process_Source_Trace (Trace_File_Name); + when LLVM_Trace_File => + Outputs.Fatal_Error ("LLVM trace file not implemented"); + end case; + end Process_Trace; + + -------------------------- + -- Process_Source_Trace -- + -------------------------- + + procedure Process_Source_Trace (Trace_File_Name : String) is + procedure On_Trace_Info + (Kind : Traces_Source.Supported_Info_Kind; Data : String); + -- Callback for Read_Source_Trace_File + + procedure Read_Source_Trace_File is new + Instrument.Input_Traces.Generic_Read_Source_Trace_File + (On_Trace_Info => On_Trace_Info, + On_Trace_Entry => Compute_Source_Coverage); + + Trace_File : Trace_File_Element_Acc; + Result : Read_Result; + + ------------------- + -- On_Trace_Info -- + ------------------- + + procedure On_Trace_Info + (Kind : Traces_Source.Supported_Info_Kind; Data : String) is + begin + Update_From_Source_Trace (Trace_File.all, Kind, Data); + end On_Trace_Info; + + -- Start of processing for Process_Source_Trace + + begin + -- Reccord we are loading a source trace + + Update_Current_Trace_Kind (Source_Trace_File); + Src_Traces_Present := True; + + -- Make sure SID files (to decode source trace files) are + -- loaded. + + Load_All_SIDs; + + -- Register the trace file, so it is included in coverage + -- reports. + + Trace_File := Create_Trace_File_Element + (Trace_File_Name, Source_Trace_File); + + -- We can now read it and import its data + + Read_Source_Trace_File (Trace_File_Name, Result); + if not Result.Success then + Report_Bad_Trace (Trace_File_Name, Result); + end if; + + Add_Traces_File (Trace_File); + end Process_Source_Trace; + + -------------------------- + -- Process_Binary_Trace -- + -------------------------- + + procedure Process_Binary_Trace + (Trace_File_Name : String; + Exec_Name_Override : String) + is + Trace_File : Trace_File_Element_Acc; + begin + -- Record we are loading a binary trace + + Update_Current_Trace_Kind (Binary_Trace_File); + Bin_Traces_Present := True; + + Load_All_ALIs (Check_SCOs => False); + + if Trace_File_Name /= "" then + Trace_File := Create_Trace_File_Element + (Trace_File_Name, Binary_Trace_File); + else + pragma Assert (Exec_Name_Override /= ""); + end if; + + if Object_Coverage_Enabled then + Process_Trace_For_Obj_Coverage + (Trace_File, Exec_Name_Override); + else + Process_Trace_For_Src_Coverage + (Trace_File, Exec_Name_Override); + end if; + + if Trace_File /= null then + Add_Traces_File (Trace_File); + end if; + end Process_Binary_Trace; + + ------------------------------------ + -- Process_Trace_For_Obj_Coverage -- + ------------------------------------ + + procedure Process_Trace_For_Obj_Coverage + (Trace_File : Trace_File_Element_Acc; + Exec_Name_Override : String) + is + -- TODO??? Handle shared objects + + Trace_Filename : constant String := + (if Trace_File = null + then "" + else +Trace_File.Filename); + Exe_File : Exe_File_Acc; + begin + Init_Base (Base_Acc.all); + + if Trace_File = null then + Open_Exec (Exec_Name_Override, Text_Start, Exe_File); + else + declare + Result : Read_Result; + TF : Trace_File_Type; + begin + Read_Trace_File (Trace_Filename, TF, Result, Base_Acc.all); + if not Result.Success then + Report_Bad_Trace (Trace_Filename, Result); + return; + end if; + Update_From_Binary_Trace (Trace_File.all, TF); + Exe_File := Open_Exec_For_Trace + (Trace_Filename, TF, Exec_Name_Override); + Free (TF); + end; + end if; + + -- If there is no routine in list, get routine names from the + -- first executable. A test earlier allows this only if there + -- is one trace file. + + if Routines_Inputs.Is_Empty then + Read_Routine_Names (Exe_File.all, Exclude => False); + end if; + + Build_Debug_Compile_Units (Exe_File.all); + + if Trace_File /= null then + Misc_Trace.Trace + ("Processing traces from " & Trace_Filename); + end if; + + Load_Code_And_Traces (Exe_File, Base_Acc); + end Process_Trace_For_Obj_Coverage; + + ------------------------------------ + -- Process_Trace_For_Src_Coverage -- + ------------------------------------ + + procedure Process_Trace_For_Src_Coverage + (Trace_File : Trace_File_Element_Acc; + Exec_Name_Override : String) + is + Exe_File : Exe_File_Acc; + -- Executable this trace file refers to + + Trace_Filename : constant String := + (if Trace_File = null + then "" + else +Trace_File.Filename); + + Current_Exec : Exe_File_Acc; + Current_Sym : Address_Info_Acc; + Current_Subp_Key : Subprogram_Key; + Current_Subp_Info : aliased Subprogram_Info; + Current_Subp_Info_Valid : Boolean; + + procedure Process_Info_Entries + (TF : Trace_File_Type; + Result : out Read_Result); + + function Load_Shared_Object + (TF : Trace_File_Type; + Filename : String; + Signature : Binary_Files.Binary_File_Signature; + First, Last : Traces.Pc_Type) return Exe_File_Acc; + + procedure Process_Trace_Entry + (TF : Trace_File_Type; SO : Exe_File_Acc; E : Trace_Entry); + + procedure Read_Trace_File is new Read_Trace_File_Gen + (Shared_Object_Type => Exe_File_Acc, + No_Shared_Object => null, + Process_Info_Entries => Process_Info_Entries, + Load_Shared_Object => Load_Shared_Object, + Process_Trace_Entry => Process_Trace_Entry); + + -------------------------- + -- Process_Info_Entries -- + -------------------------- + + procedure Process_Info_Entries + (TF : Trace_File_Type; + Result : out Read_Result) is + begin + Check_Trace_File_From_Exec (TF, Result); + if not Result.Success then + return; + end if; + Exe_File := Open_Exec_For_Trace + (Trace_Filename, TF, Exec_Name_Override); + Decision_Map.Analyze (Exe_File); + end Process_Info_Entries; + + ------------------------ + -- Load_Shared_Object -- + ------------------------ + + function Load_Shared_Object + (TF : Trace_File_Type; + Filename : String; + Signature : Binary_Files.Binary_File_Signature; + First, Last : Traces.Pc_Type) return Exe_File_Acc + is + pragma Unreferenced (TF); + pragma Unreferenced (First); + pragma Unreferenced (Last); + Result : Exe_File_Acc; + begin + Open_Exec_For_Trace + (Filename, 0, Trace_Filename, Signature, Result); + Decision_Map.Analyze (Result); + return Result; + end Load_Shared_Object; + + ------------------------- + -- Process_Trace_Entry -- + ------------------------- + + procedure Process_Trace_Entry + (TF : Trace_File_Type; SO : Exe_File_Acc; E : Trace_Entry) + is + pragma Unreferenced (TF); + + Exe : constant Exe_File_Acc := + (if SO = null then Exe_File else SO); + begin + -- Get the symbol the trace entry is in + + if Current_Sym = null or else Current_Exec /= Exe + or else + E.First not in Current_Sym.First .. Current_Sym.Last + then + Current_Exec := Exe; + Current_Sym := + Get_Address_Info + (Exe.all, Symbol_Addresses, E.First); + + if Current_Sym = null then + Current_Subp_Info_Valid := False; + else + Key_From_Symbol + (Exe, Current_Sym, Current_Subp_Key); + Current_Subp_Info_Valid := + Is_In (Current_Subp_Key); + end if; + + if Current_Subp_Info_Valid then + Current_Subp_Info := + Get_Subp_Info (Current_Subp_Key); + end if; + end if; + + if Current_Subp_Info_Valid then + Compute_Source_Coverage + (Current_Subp_Key, Current_Subp_Info, E); + end if; + end Process_Trace_Entry; + + -- Start of processing for Process_Trace_For_Src_Coverage + + begin + -- Whether we have a trace file or just an executable, load + -- symbols from executable (sets the rebase offset for each + -- symbol) and perform static analysis. + -- + -- If this is a trace file, also make it contribute to coverage + -- state. + + if Trace_File = null then + Open_Exec (Exec_Name_Override, Text_Start, Exe_File); + Decision_Map.Analyze (Exe_File); + else + declare + TF : Trace_File_Type; + Result : Read_Result; + begin + Read_Trace_File (Trace_Filename, TF, Result); + if not Result.Success then + Report_Bad_Trace (Trace_Filename, Result); + return; + end if; + Update_From_Binary_Trace (Trace_File.all, TF); + Free (TF); + end; + end if; + end Process_Trace_For_Src_Coverage; + + begin + for Filename of Exe_Inputs loop + Process_Exec (+Filename); + end loop; + for RT of Trace_Inputs loop + Process_Trace (+RT.Filename, +RT.Executable); + end loop; + + -- Use dominant information to refine decision coverage + -- information wrt. outcomes taken. This is a binary information + -- specificity as we always know which outcomes were taken in the + -- context of source traces. + + if Currently_Accepted_Trace_Kind = Binary_Trace_File then + Refine_Source_Coverage; + end if; + + -- Warn when using --scos with source traces or --sid with bin + -- traces. + + if not SID_Inputs.Is_Empty and then Bin_Traces_Present then + Warn ("Using option --sid with binary trace files has no" + & " effect." & ASCII.LF & "Please consider using option" + & " --scos or -P in conjunction with" + & " --units to specify units of interest."); + end if; + if not ALIs_Inputs.Is_Empty and then Src_Traces_Present then + Warn ("Using option --scos with source trace files has no" + & " effect." & ASCII.LF & "Please consider using option" + & " --sid or -P in conjunction with --units" + & " to specify units of interest."); + end if; + end Read_And_Process_GNATcov_Traces; + ----------------------------- -- Report_Missing_Argument -- ----------------------------- @@ -1849,493 +2338,17 @@ begin end if; end if; - -- Read and process traces - - declare - Bin_Traces_Present : Boolean := False; - Src_Traces_Present : Boolean := False; - - procedure Process_Exec (Exec_Name : String); - -- Load a consolidated executable - - procedure Process_Trace - (Trace_File_Name : String; - Exec_Name_Override : String); - -- Try to read Trace_File_Name. Depending on the probed trace file - -- kind, dispatch to Process_Binary_Trace or Process_Source_Trace. - -- If Trace_File_Name is an empty string, just dispatch to - -- Process_Binary_Trace (case of forcing the load of a program). - - procedure Process_Source_Trace (Trace_File_Name : String); - -- Process the given source trace file, discharging SCIs - -- referenced by its coverage buffers. - - procedure Process_Binary_Trace - (Trace_File_Name : String; - Exec_Name_Override : String); - -- Common dispatching point for object and source coverage: - -- process one trace file (with optional override of exec file - -- name), or load one consolidated executable (if Trace_File_Name - -- is an empty string, in which case Exec_Name_Override is not - -- allowed to be null). - - procedure Process_Trace_For_Obj_Coverage - (Trace_File : Trace_File_Element_Acc; - Exec_Name_Override : String); - -- Open Trace_File and merge it into the trace database - - procedure Process_Trace_For_Src_Coverage - (Trace_File : Trace_File_Element_Acc; - Exec_Name_Override : String); - -- Process Trace_File for source coverage. No trace database is - -- used. - - function Open_Exec_For_Trace - (Trace_File_Name : String; - Trace_File : Trace_File_Type; - Exec_Name_Override : String) return Exe_File_Acc; - -- Open the executable for TF, taking into account a possible - -- command line override of the executable file name. The opened - -- exec file is entered in the global execs list. - - ------------------------- - -- Open_Exec_For_Trace -- - ------------------------- - - function Open_Exec_For_Trace - (Trace_File_Name : String; - Trace_File : Trace_File_Type; - Exec_Name_Override : String) return Exe_File_Acc - is - use Qemu_Traces; - - function Get_Exe_Name return String; - -- Executable name as determined from trace file or overridden - - ------------------ - -- Get_Exe_Name -- - ------------------ - - function Get_Exe_Name return String is - begin - if Exec_Name_Override /= "" then - return Exec_Name_Override; - end if; - - declare - Exec_Name_From_Trace : constant String := - Get_Info (Trace_File, Exec_File_Name); - begin - if Exec_Name_From_Trace = "" then - Fatal_Error - ("Cannot find executable filename in trace file " - & Trace_File_Name); - end if; - - return Exec_Name_From_Trace; - end; - end Get_Exe_Name; - - Exe_Name : constant String := Get_Exe_Name; - - -- Start of processing for Open_Exec_For_Trace - - begin - return Exe_File : Exe_File_Acc do - Execs_Dbase.Open_Exec_For_Trace - (Exe_Name, Text_Start, - Trace_File_Name, Get_Signature (Trace_File), - Exe_File); - end return; - exception - when E : Binary_Files.Error => - Fatal_Error ("Cannot open ELF file " & Exe_Name - & " for trace file " & Trace_File_Name & ": " - & Switches.Exception_Info (E)); - end Open_Exec_For_Trace; - - ------------------ - -- Process_Exec -- - ------------------ - - procedure Process_Exec (Exec_Name : String) is - begin - Load_All_ALIs (Check_SCOs => False); - Process_Trace - (Trace_File_Name => "", Exec_Name_Override => Exec_Name); - end Process_Exec; - - ------------------- - -- Process_Trace -- - ------------------- - - procedure Process_Trace - (Trace_File_Name : String; - Exec_Name_Override : String) - is - Kind : Trace_File_Kind; - Result : Read_Result; - begin - if Trace_File_Name = "" then - Process_Binary_Trace (Trace_File_Name, Exec_Name_Override); - return; - end if; - - Probe_Trace_File (Trace_File_Name, Kind, Result); - if not Result.Success then - Report_Bad_Trace (Trace_File_Name, Result); - end if; - - case Kind is - when Binary_Trace_File => - Process_Binary_Trace - (Trace_File_Name, Exec_Name_Override); - when Source_Trace_File => - Process_Source_Trace (Trace_File_Name); - when LLVM_Trace_File => - Outputs.Fatal_Error ("LLVM trace file not implemented"); - end case; - end Process_Trace; - - -------------------------- - -- Process_Source_Trace -- - -------------------------- - - procedure Process_Source_Trace (Trace_File_Name : String) is - procedure On_Trace_Info - (Kind : Traces_Source.Supported_Info_Kind; Data : String); - -- Callback for Read_Source_Trace_File - - procedure Read_Source_Trace_File is new - Instrument.Input_Traces.Generic_Read_Source_Trace_File - (On_Trace_Info => On_Trace_Info, - On_Trace_Entry => Compute_Source_Coverage); - - Trace_File : Trace_File_Element_Acc; - Result : Read_Result; - - ------------------- - -- On_Trace_Info -- - ------------------- - - procedure On_Trace_Info - (Kind : Traces_Source.Supported_Info_Kind; Data : String) is - begin - Update_From_Source_Trace (Trace_File.all, Kind, Data); - end On_Trace_Info; - - -- Start of processing for Process_Source_Trace - - begin - -- Reccord we are loading a source trace - - Update_Current_Trace_Kind (Source_Trace_File); - Src_Traces_Present := True; - - -- Make sure SID files (to decode source trace files) are - -- loaded. - - Load_All_SIDs; - - -- Register the trace file, so it is included in coverage - -- reports. - - Trace_File := Create_Trace_File_Element - (Trace_File_Name, Source_Trace_File); - - -- We can now read it and import its data - - Read_Source_Trace_File (Trace_File_Name, Result); - if not Result.Success then - Report_Bad_Trace (Trace_File_Name, Result); - end if; - - Add_Traces_File (Trace_File); - end Process_Source_Trace; - - -------------------------- - -- Process_Binary_Trace -- - -------------------------- - - procedure Process_Binary_Trace - (Trace_File_Name : String; - Exec_Name_Override : String) - is - Trace_File : Trace_File_Element_Acc; - begin - -- Record we are loading a binary trace - - Update_Current_Trace_Kind (Binary_Trace_File); - Bin_Traces_Present := True; - - Load_All_ALIs (Check_SCOs => False); - - if Trace_File_Name /= "" then - Trace_File := Create_Trace_File_Element - (Trace_File_Name, Binary_Trace_File); - else - pragma Assert (Exec_Name_Override /= ""); - end if; - - if Object_Coverage_Enabled then - Process_Trace_For_Obj_Coverage - (Trace_File, Exec_Name_Override); - else - Process_Trace_For_Src_Coverage - (Trace_File, Exec_Name_Override); - end if; - - if Trace_File /= null then - Add_Traces_File (Trace_File); - end if; - end Process_Binary_Trace; - - ------------------------------------ - -- Process_Trace_For_Obj_Coverage -- - ------------------------------------ - - procedure Process_Trace_For_Obj_Coverage - (Trace_File : Trace_File_Element_Acc; - Exec_Name_Override : String) - is - -- TODO??? Handle shared objects - - Trace_Filename : constant String := - (if Trace_File = null - then "" - else +Trace_File.Filename); - Exe_File : Exe_File_Acc; - begin - Init_Base (Base); - - if Trace_File = null then - Open_Exec (Exec_Name_Override, Text_Start, Exe_File); - else - declare - Result : Read_Result; - TF : Trace_File_Type; - begin - Read_Trace_File (Trace_Filename, TF, Result, Base); - if not Result.Success then - Report_Bad_Trace (Trace_Filename, Result); - return; - end if; - Update_From_Binary_Trace (Trace_File.all, TF); - Exe_File := Open_Exec_For_Trace - (Trace_Filename, TF, Exec_Name_Override); - Free (TF); - end; - end if; - - -- If there is no routine in list, get routine names from the - -- first executable. A test earlier allows this only if there - -- is one trace file. - - if Routines_Inputs.Is_Empty then - Read_Routine_Names (Exe_File.all, Exclude => False); - end if; - - Build_Debug_Compile_Units (Exe_File.all); - - if Trace_File /= null then - Misc_Trace.Trace - ("Processing traces from " & Trace_Filename); - end if; - - Load_Code_And_Traces (Exe_File, Base'Access); - end Process_Trace_For_Obj_Coverage; - - ------------------------------------ - -- Process_Trace_For_Src_Coverage -- - ------------------------------------ - - procedure Process_Trace_For_Src_Coverage - (Trace_File : Trace_File_Element_Acc; - Exec_Name_Override : String) - is - Exe_File : Exe_File_Acc; - -- Executable this trace file refers to - - Trace_Filename : constant String := - (if Trace_File = null - then "" - else +Trace_File.Filename); - - Current_Exec : Exe_File_Acc; - Current_Sym : Address_Info_Acc; - Current_Subp_Key : Subprogram_Key; - Current_Subp_Info : aliased Subprogram_Info; - Current_Subp_Info_Valid : Boolean; - - procedure Process_Info_Entries - (TF : Trace_File_Type; - Result : out Read_Result); - - function Load_Shared_Object - (TF : Trace_File_Type; - Filename : String; - Signature : Binary_Files.Binary_File_Signature; - First, Last : Traces.Pc_Type) return Exe_File_Acc; - - procedure Process_Trace_Entry - (TF : Trace_File_Type; SO : Exe_File_Acc; E : Trace_Entry); - - procedure Read_Trace_File is new Read_Trace_File_Gen - (Shared_Object_Type => Exe_File_Acc, - No_Shared_Object => null, - Process_Info_Entries => Process_Info_Entries, - Load_Shared_Object => Load_Shared_Object, - Process_Trace_Entry => Process_Trace_Entry); - - -------------------------- - -- Process_Info_Entries -- - -------------------------- - - procedure Process_Info_Entries - (TF : Trace_File_Type; - Result : out Read_Result) is - begin - Check_Trace_File_From_Exec (TF, Result); - if not Result.Success then - return; - end if; - Exe_File := Open_Exec_For_Trace - (Trace_Filename, TF, Exec_Name_Override); - Decision_Map.Analyze (Exe_File); - end Process_Info_Entries; - - ------------------------ - -- Load_Shared_Object -- - ------------------------ - - function Load_Shared_Object - (TF : Trace_File_Type; - Filename : String; - Signature : Binary_Files.Binary_File_Signature; - First, Last : Traces.Pc_Type) return Exe_File_Acc - is - pragma Unreferenced (TF); - pragma Unreferenced (First); - pragma Unreferenced (Last); - Result : Exe_File_Acc; - begin - Open_Exec_For_Trace - (Filename, 0, Trace_Filename, Signature, Result); - Decision_Map.Analyze (Result); - return Result; - end Load_Shared_Object; - - ------------------------- - -- Process_Trace_Entry -- - ------------------------- - - procedure Process_Trace_Entry - (TF : Trace_File_Type; SO : Exe_File_Acc; E : Trace_Entry) - is - pragma Unreferenced (TF); - - Exe : constant Exe_File_Acc := - (if SO = null then Exe_File else SO); - begin - -- Get the symbol the trace entry is in - - if Current_Sym = null or else Current_Exec /= Exe - or else - E.First not in Current_Sym.First .. Current_Sym.Last - then - Current_Exec := Exe; - Current_Sym := - Get_Address_Info - (Exe.all, Symbol_Addresses, E.First); - - if Current_Sym = null then - Current_Subp_Info_Valid := False; - else - Key_From_Symbol - (Exe, Current_Sym, Current_Subp_Key); - Current_Subp_Info_Valid := - Is_In (Current_Subp_Key); - end if; - - if Current_Subp_Info_Valid then - Current_Subp_Info := - Get_Subp_Info (Current_Subp_Key); - end if; - end if; - - if Current_Subp_Info_Valid then - Compute_Source_Coverage - (Current_Subp_Key, Current_Subp_Info, E); - end if; - end Process_Trace_Entry; - - -- Start of processing for Process_Trace_For_Src_Coverage + -- If no checkpoint is provided, expect at least 1 TRACE_FILE. - begin - -- Whether we have a trace file or just an executable, load - -- symbols from executable (sets the rebase offset for each - -- symbol) and perform static analysis. - -- - -- If this is a trace file, also make it contribute to coverage - -- state. - - if Trace_File = null then - Open_Exec (Exec_Name_Override, Text_Start, Exe_File); - Decision_Map.Analyze (Exe_File); - else - declare - TF : Trace_File_Type; - Result : Read_Result; - begin - Read_Trace_File (Trace_Filename, TF, Result); - if not Result.Success then - Report_Bad_Trace (Trace_Filename, Result); - return; - end if; - Update_From_Binary_Trace (Trace_File.all, TF); - Free (TF); - end; - end if; - end Process_Trace_For_Src_Coverage; - - begin - if Checkpoints_Inputs.Is_Empty - and then LLVM_JSON_Ckpt_Inputs.Is_Empty - then - Check_Traces_Available; - end if; - for Filename of Exe_Inputs loop - Process_Exec (+Filename); - end loop; - for RT of Trace_Inputs loop - Process_Trace (+RT.Filename, +RT.Executable); - end loop; - - -- Use dominant information to refine decision coverage - -- information wrt. outcomes taken. This is a binary information - -- specificity as we always know which outcomes were taken in the - -- context of source traces. - - if Currently_Accepted_Trace_Kind = Binary_Trace_File then - Refine_Source_Coverage; - end if; + if Checkpoints_Inputs.Is_Empty + and then LLVM_JSON_Ckpt_Inputs.Is_Empty + then + Check_Traces_Available; + end if; - -- Warn when using --scos with source traces or --sid with bin - -- traces. + -- Read and process traces - if not SID_Inputs.Is_Empty and then Bin_Traces_Present then - Warn ("Using option --sid with binary trace files has no" - & " effect." & ASCII.LF & "Please consider using option" - & " --scos or -P in conjunction with" - & " --units to specify units of interest."); - end if; - if not ALIs_Inputs.Is_Empty and then Src_Traces_Present then - Warn ("Using option --scos with source trace files has no" - & " effect." & ASCII.LF & "Please consider using option" - & " --sid or -P in conjunction with --units" - & " to specify units of interest."); - end if; - end; + Read_And_Process_GNATcov_Traces (Base'Access); -- Reconstruct unit names for ignored source files. This is done -- before loading checkpoints, because this will already have been From ed5a04bf5555ab7efdf83234007fd2de9c8824d3 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 30 Apr 2025 17:55:26 +0200 Subject: [PATCH 1268/1483] Detect LLVM traces in `gnatcov coverage` --- tools/gnatcov/gnatcov_bits_specific.adb | 41 ++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 09a0971e8..3bbe2bc35 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -2347,8 +2347,47 @@ begin end if; -- Read and process traces + -- In case there is as least one, probe it to decide if it is + -- a gnatcov trace or an LLVM one. - Read_And_Process_GNATcov_Traces (Base'Access); + declare + Has_Traces : constant Boolean := not Trace_Inputs.Is_Empty; + Trace_Kind : Any_Accepted_Trace_Kind := Unknown; + Result : Read_Result; + begin + if Has_Traces then + declare + Trace_File : constant String := + +Trace_Inputs.First_Element.Filename; + begin + Probe_Trace_File (Trace_File, Trace_Kind, Result); + + if not Result.Success then + Report_Bad_Trace (Trace_File, Result); + end if; + end; + end if; + + if Trace_Kind /= LLVM_Trace_File then + + -- Process classic GNATcov traces + + Read_And_Process_GNATcov_Traces (Base'Access); + else + + -- ??? Ensure an exec file was passed + + -- ??? Validate all traces (or let llvm-profdata figure out ?) + + -- ??? Aggregate profraws using llvm-profdata + + -- ??? Convert the profdata into a JSON using trace adapter + + -- ??? Add the generated JSON to the list of LLVM JSON CKPTs + + Outputs.Fatal_Error ("Not yet implemented"); + end if; + end; -- Reconstruct unit names for ignored source files. This is done -- before loading checkpoints, because this will already have been From 6967ef229fab3ed90dc2b797e37c2bb3f624e41f Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 2 May 2025 17:16:49 +0200 Subject: [PATCH 1269/1483] subprocesses: Fix Run_Command returning true if executable is not found --- tools/gnatcov/subprocesses.adb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 934f22480..ce80b693c 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -228,7 +228,8 @@ package body Subprocesses is Out_To_Null, In_To_Null, Ignore_Error); - Success : constant Boolean := Wait (Handle) = 0; + Success : constant Boolean := + Wait (Handle) = 0 and then Handle /= Invalid_Handle; begin Check_Status (Success, Ignore_Error, Command, Origin_Command_Name); return Success; From c3b8180fbbca68c475ab9b5704aa9ae0e21681ab Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 2 May 2025 17:19:50 +0200 Subject: [PATCH 1270/1483] Process LLVM traces in gnatcov coverage --- tools/gnatcov/gnatcov_bits_specific.adb | 66 +++++++++++++++-- tools/gnatcov/llvm.adb | 96 +++++++++++++++++++++++++ tools/gnatcov/llvm.ads | 15 ++++ 3 files changed, 170 insertions(+), 7 deletions(-) create mode 100644 tools/gnatcov/llvm.adb create mode 100644 tools/gnatcov/llvm.ads diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 3bbe2bc35..64191bba2 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -69,6 +69,7 @@ with Instrument.Main; with Instrument.Projects; with Instrument.Setup_Config; with Instrument.Source; +with LLVM; with Logging; with Object_Locations; with Outputs; use Outputs; @@ -741,7 +742,7 @@ procedure GNATcov_Bits_Specific is and then LLVM_JSON_Ckpt_Inputs.Is_Empty and then SID_Inputs.Is_Empty and then ALIs_Inputs.Is_Empty - and then Args.String_List_Args (Opt_Exec).Is_Empty + and then Exe_Inputs.Is_Empty and then not Args.String_Args (Opt_Project).Present then Report_Missing_Argument @@ -2375,17 +2376,68 @@ begin Read_And_Process_GNATcov_Traces (Base'Access); else - -- ??? Ensure an exec file was passed + -- Process LLVM traces (.profraw files) + -- + -- The pipeline is the following: + -- 1. Aggregate the profraw files into a single profdata + -- using llvm-profdata. + -- 2. Use the llvm-json-exporter trace adapter to translate + -- the profdata file into a LLVM JSON checkpoint file. + -- 3. Add the checkpoint file to the LLVM checkpoints so + -- gnatcov loads it. - -- ??? Validate all traces (or let llvm-profdata figure out ?) + declare + LLVM_Profdata_File : constant String := "output.profdata"; + LLVM_JSON_File : constant String := "llvm-ckpt.json"; + begin + + -- Ensure an exec file was passed + + if Exe_Inputs.Is_Empty then + Outputs.Fatal_Error ("LLVM coverage needs an executable" + & " file to retrieve coverage" + & " mappings. Use --exec"); + end if; + + -- Probe and validate all traces but the first one that was + -- already validated. - -- ??? Aggregate profraws using llvm-profdata + for Trace in + Trace_Inputs.First_Index + 1 .. Trace_Inputs.Last_Index + loop + declare + Trace_Name : constant String := + +Trace_Inputs.Element (Trace).Filename; + begin + Probe_Trace_File (Trace_Name, Trace_Kind, Result); + + if not Result.Success then + Outputs.Fatal_Error + (Trace_Name & ": " & (+Result.Error)); + elsif Trace_Kind /= LLVM_Trace_File then + Outputs.Fatal_Error + (Trace_Name + & ": Invalid .profraw file (bad magic)"); + end if; + end; + end loop; + + -- Aggregate profraws using llvm-profdata - -- ??? Convert the profdata into a JSON using trace adapter + LLVM.Make_Profdata_From_Traces + (Trace_Inputs, LLVM_Profdata_File); - -- ??? Add the generated JSON to the list of LLVM JSON CKPTs + -- Convert the profdata into a JSON using trace adapter - Outputs.Fatal_Error ("Not yet implemented"); + LLVM.Make_LLVM_Checkpoint_From_Profdata + (LLVM_Profdata_File, + +Exe_Inputs.First_Element, + LLVM_JSON_File); + + -- Add the generated JSON to the list of LLVM JSON CKPTs + + LLVM_JSON_Ckpt_Inputs.Prepend (+LLVM_JSON_File); + end; end if; end; diff --git a/tools/gnatcov/llvm.adb b/tools/gnatcov/llvm.adb new file mode 100644 index 000000000..5d2c171b4 --- /dev/null +++ b/tools/gnatcov/llvm.adb @@ -0,0 +1,96 @@ +with Ada.Environment_Variables; + +with Outputs; +with Strings; use Strings; +with Subprocesses; use Subprocesses; +with Support_Files; + +package body LLVM is + + function Get_LLVM_Profdata_Exe return String; + -- Find the llvm-profdata from the `LLVM_PROFDATA_EXE` environment variable + -- Or expect `llvm-prodata` to be on the PATH. + + function Get_LLVM_Trace_Adapter_Exe return String; + -- Find the trace adapter binary, it should be in the libexec folder of + -- gnatcov. + + --------------------------- + -- Get_LLVM_Profdata_Exe -- + --------------------------- + + function Get_LLVM_Profdata_Exe return String is + package EV renames Ada.Environment_Variables; + Var_Name : constant String := "LLVM_PROFDATA_EXE"; + begin + if EV.Exists (Var_Name) then + return EV.Value (Var_Name); + else + return Support_Files.In_Libexec_Dir ("llvm-profdata"); + end if; + end Get_LLVM_Profdata_Exe; + + -------------------------------- + -- Get_LLVM_Trace_Adapter_Exe -- + -------------------------------- + + function Get_LLVM_Trace_Adapter_Exe return String is + (Support_Files.In_Libexec_Dir ("gnatcov_llvm_exporter")); + + ------------------------------- + -- Make_Profdata_From_Traces -- + ------------------------------- + + procedure Make_Profdata_From_Traces + (Traces : Requested_Trace_Vectors.Vector; Output_File : String) + is + LLVM_Profdata_Cmd : Command_Type := + (+Get_LLVM_Profdata_Exe, others => <>); + begin + Subprocesses.Append_Arg (LLVM_Profdata_Cmd, "merge"); + Subprocesses.Append_Arg (LLVM_Profdata_Cmd, "-sparse"); + Subprocesses.Append_Arg (LLVM_Profdata_Cmd, "-o", Output_File); + + for RT of Traces loop + Subprocesses.Append_Arg (LLVM_Profdata_Cmd, +RT.Filename); + end loop; + + if not Subprocesses.Run_Command + (Command => LLVM_Profdata_Cmd, + Origin_Command_Name => "gnatcov coverage", + Err_To_Out => True, + In_To_Null => True) + then + Outputs.Fatal_Error + ("Call to `llvm-profdata` didn't succeed."); + end if; + end Make_Profdata_From_Traces; + + ---------------------------------------- + -- Make_LLVM_Checkpoint_From_Profdata -- + ---------------------------------------- + + procedure Make_LLVM_Checkpoint_From_Profdata + (Profdata_File, Exe_File, Output_File : String) + is + Trace_Adapter_Cmd : Command_Type := + (+Get_LLVM_Trace_Adapter_Exe, others => <>); + begin + + Subprocesses.Append_Arg (Trace_Adapter_Cmd, "--instr-prof"); + Subprocesses.Append_Arg (Trace_Adapter_Cmd, Profdata_File); + Subprocesses.Append_Arg (Trace_Adapter_Cmd, Exe_File); + + if not Subprocesses.Run_Command + (Command => Trace_Adapter_Cmd, + Origin_Command_Name => "gnatcov coverage", + Output_File => Output_File, + In_To_Null => True) + then + Outputs.Fatal_Error + ("Call to llvm trace adapter didn't succeed." + & " See `" & Output_File & "` for details."); + end if; + end Make_LLVM_Checkpoint_From_Profdata; + +end LLVM; diff --git a/tools/gnatcov/llvm.ads b/tools/gnatcov/llvm.ads new file mode 100644 index 000000000..357d5e794 --- /dev/null +++ b/tools/gnatcov/llvm.ads @@ -0,0 +1,15 @@ +with Traces_Files; use Traces_Files; + +package LLVM is + + procedure Make_Profdata_From_Traces + (Traces : Requested_Trace_Vectors.Vector; Output_File : String); + -- Builds the call to the `llvm-profdata` command, and saves the output + -- profdata file in `Output_File`. + + procedure Make_LLVM_Checkpoint_From_Profdata + (Profdata_File, Exe_File, Output_File : String); + -- Builds the call to the LLVM trace adapter and saves the JSON result to + -- `Output_File`. + +end LLVM; From 4bab1f725c69f91f15b1d60d505d73ec0736efa7 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 21 May 2025 15:17:54 +0200 Subject: [PATCH 1271/1483] llvm: Create intermediate files in a temp directory --- tools/gnatcov/gnatcov_bits_specific.adb | 83 ++++++++---------- tools/gnatcov/llvm.adb | 109 ++++++++++++++++++++---- tools/gnatcov/llvm.ads | 16 ++-- 3 files changed, 135 insertions(+), 73 deletions(-) diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 64191bba2..20cf6aef7 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -2376,6 +2376,37 @@ begin Read_And_Process_GNATcov_Traces (Base'Access); else + -- Ensure an exec file was passed + + if Exe_Inputs.Is_Empty then + Outputs.Fatal_Error ("LLVM coverage needs an executable" + & " file to retrieve coverage" + & " mappings. Use --exec"); + end if; + + -- Probe and validate all traces but the first one that was + -- already validated. + + for Trace in + Trace_Inputs.First_Index + 1 .. Trace_Inputs.Last_Index + loop + declare + Trace_Name : constant String := + +Trace_Inputs.Element (Trace).Filename; + begin + Probe_Trace_File (Trace_Name, Trace_Kind, Result); + + if not Result.Success then + Outputs.Fatal_Error + (Trace_Name & ": " & (+Result.Error)); + elsif Trace_Kind /= LLVM_Trace_File then + Outputs.Fatal_Error + (Trace_Name + & ": Invalid .profraw file (bad magic)"); + end if; + end; + end loop; + -- Process LLVM traces (.profraw files) -- -- The pipeline is the following: @@ -2387,56 +2418,14 @@ begin -- gnatcov loads it. declare - LLVM_Profdata_File : constant String := "output.profdata"; - LLVM_JSON_File : constant String := "llvm-ckpt.json"; + LLVM_JSON_Ckpt : Unbounded_String; begin + LLVM.Create_LLVM_Temp_Dir (Auto_Delete => not Save_Temps); - -- Ensure an exec file was passed - - if Exe_Inputs.Is_Empty then - Outputs.Fatal_Error ("LLVM coverage needs an executable" - & " file to retrieve coverage" - & " mappings. Use --exec"); - end if; - - -- Probe and validate all traces but the first one that was - -- already validated. - - for Trace in - Trace_Inputs.First_Index + 1 .. Trace_Inputs.Last_Index - loop - declare - Trace_Name : constant String := - +Trace_Inputs.Element (Trace).Filename; - begin - Probe_Trace_File (Trace_Name, Trace_Kind, Result); - - if not Result.Success then - Outputs.Fatal_Error - (Trace_Name & ": " & (+Result.Error)); - elsif Trace_Kind /= LLVM_Trace_File then - Outputs.Fatal_Error - (Trace_Name - & ": Invalid .profraw file (bad magic)"); - end if; - end; - end loop; - - -- Aggregate profraws using llvm-profdata - - LLVM.Make_Profdata_From_Traces - (Trace_Inputs, LLVM_Profdata_File); - - -- Convert the profdata into a JSON using trace adapter - - LLVM.Make_LLVM_Checkpoint_From_Profdata - (LLVM_Profdata_File, - +Exe_Inputs.First_Element, - LLVM_JSON_File); - - -- Add the generated JSON to the list of LLVM JSON CKPTs + LLVM_JSON_Ckpt := LLVM.Make_LLVM_Checkpoint_From_Traces + (Trace_Inputs, +Exe_Inputs.First_Element); - LLVM_JSON_Ckpt_Inputs.Prepend (+LLVM_JSON_File); + LLVM_JSON_Ckpt_Inputs.Prepend (LLVM_JSON_Ckpt); end; end if; end; diff --git a/tools/gnatcov/llvm.adb b/tools/gnatcov/llvm.adb index 5d2c171b4..bc50bcf79 100644 --- a/tools/gnatcov/llvm.adb +++ b/tools/gnatcov/llvm.adb @@ -1,11 +1,17 @@ with Ada.Environment_Variables; +with Logging; with Outputs; -with Strings; use Strings; +with Paths; use Paths; with Subprocesses; use Subprocesses; with Support_Files; +with Temp_Dirs; use Temp_Dirs; package body LLVM is + LLVM_Artifacts_Temp_Dir : Temporary_Directory; + + LLVM_Trace : constant Logging.GNATCOLL_Trace := + Logging.Create_Trace ("LLVM"); function Get_LLVM_Profdata_Exe return String; -- Find the llvm-profdata from the `LLVM_PROFDATA_EXE` environment variable @@ -15,6 +21,19 @@ package body LLVM is -- Find the trace adapter binary, it should be in the libexec folder of -- gnatcov. + function Make_Profdata_From_Traces + (Traces : Requested_Trace_Vectors.Vector; + Output_File : String) return String; + -- Builds the call to the `llvm-profdata` command, and saves the output + -- profdata file in `Output_File`. + -- Return the expanded the absolute path of `Output_File`. + + function Make_LLVM_Checkpoint_From_Profdata + (Profdata_File, Exe_File, Output_File : String) return String; + -- Builds the call to the LLVM trace adapter and saves the JSON result to + -- `Output_File`. + -- Return the expanded the absolute path of `Output_File`. + --------------------------- -- Get_LLVM_Profdata_Exe -- --------------------------- @@ -34,47 +53,67 @@ package body LLVM is -- Get_LLVM_Trace_Adapter_Exe -- -------------------------------- - function Get_LLVM_Trace_Adapter_Exe return String is - (Support_Files.In_Libexec_Dir ("gnatcov_llvm_exporter")); + function Get_LLVM_Trace_Adapter_Exe return String + is (Support_Files.In_Libexec_Dir ("gnatcov_llvm_exporter")); + + -------------------------- + -- Create_LLVM_Temp_Dir -- + -------------------------- + + procedure Create_LLVM_Temp_Dir (Auto_Delete : Boolean) is + begin + Create_Temporary_Directory + (LLVM_Artifacts_Temp_Dir, "gnatcov_llvm_artifacts", Auto_Delete); + + LLVM_Trace.Trace + ("Created LLVM artifacts tempdir: " + & LLVM_Artifacts_Temp_Dir.Directory_Name); + end Create_LLVM_Temp_Dir; ------------------------------- -- Make_Profdata_From_Traces -- ------------------------------- - procedure Make_Profdata_From_Traces + function Make_Profdata_From_Traces (Traces : Requested_Trace_Vectors.Vector; Output_File : String) + return String is LLVM_Profdata_Cmd : Command_Type := (+Get_LLVM_Profdata_Exe, others => <>); + Output_Path : constant String := + LLVM_Artifacts_Temp_Dir.Directory_Name / Output_File; begin Subprocesses.Append_Arg (LLVM_Profdata_Cmd, "merge"); Subprocesses.Append_Arg (LLVM_Profdata_Cmd, "-sparse"); - Subprocesses.Append_Arg (LLVM_Profdata_Cmd, "-o", Output_File); + Subprocesses.Append_Arg (LLVM_Profdata_Cmd, "-o", Output_Path); for RT of Traces loop Subprocesses.Append_Arg (LLVM_Profdata_Cmd, +RT.Filename); end loop; if not Subprocesses.Run_Command - (Command => LLVM_Profdata_Cmd, - Origin_Command_Name => "gnatcov coverage", - Err_To_Out => True, - In_To_Null => True) + (Command => LLVM_Profdata_Cmd, + Origin_Command_Name => "gnatcov coverage", + Err_To_Out => True, + In_To_Null => True) then - Outputs.Fatal_Error - ("Call to `llvm-profdata` didn't succeed."); + Outputs.Fatal_Error ("Call to `llvm-profdata` didn't succeed."); end if; + + return Output_Path; end Make_Profdata_From_Traces; ---------------------------------------- -- Make_LLVM_Checkpoint_From_Profdata -- ---------------------------------------- - procedure Make_LLVM_Checkpoint_From_Profdata - (Profdata_File, Exe_File, Output_File : String) + function Make_LLVM_Checkpoint_From_Profdata + (Profdata_File, Exe_File, Output_File : String) return String is Trace_Adapter_Cmd : Command_Type := (+Get_LLVM_Trace_Adapter_Exe, others => <>); + Output_Path : constant String := + LLVM_Artifacts_Temp_Dir.Directory_Name / Output_File; begin Subprocesses.Append_Arg (Trace_Adapter_Cmd, "--instr-prof"); @@ -82,15 +121,49 @@ package body LLVM is Subprocesses.Append_Arg (Trace_Adapter_Cmd, Exe_File); if not Subprocesses.Run_Command - (Command => Trace_Adapter_Cmd, - Origin_Command_Name => "gnatcov coverage", - Output_File => Output_File, - In_To_Null => True) + (Command => Trace_Adapter_Cmd, + Origin_Command_Name => "gnatcov coverage", + Output_File => Output_Path, + In_To_Null => True) then Outputs.Fatal_Error ("Call to llvm trace adapter didn't succeed." - & " See `" & Output_File & "` for details."); + & " See `" + & Output_Path + & "` for details."); end if; + + return Output_Path; end Make_LLVM_Checkpoint_From_Profdata; + -------------------------------------- + -- Make_LLVM_Checkpoint_From_Traces -- + -------------------------------------- + + function Make_LLVM_Checkpoint_From_Traces + (Trace_Inputs : Requested_Trace_Vectors.Vector; + Exe_File : String) return Unbounded_String + is + LLVM_Profdata_File : constant String := "output.profdata"; + LLVM_JSON_File : constant String := "llvm-ckpt.json"; + + LLVM_Profdata_Path : Unbounded_String; + LLVM_JSON_Path : Unbounded_String; + begin + + -- Aggregate profraws using llvm-profdata + + LLVM_Profdata_Path := + +LLVM.Make_Profdata_From_Traces (Trace_Inputs, LLVM_Profdata_File); + + -- Convert the profdata into a JSON using trace adapter + + LLVM_JSON_Path := + +LLVM.Make_LLVM_Checkpoint_From_Profdata + (+LLVM_Profdata_Path, Exe_File, LLVM_JSON_File); + + return LLVM_JSON_Path; + + end Make_LLVM_Checkpoint_From_Traces; + end LLVM; diff --git a/tools/gnatcov/llvm.ads b/tools/gnatcov/llvm.ads index 357d5e794..35190d70c 100644 --- a/tools/gnatcov/llvm.ads +++ b/tools/gnatcov/llvm.ads @@ -1,15 +1,15 @@ with Traces_Files; use Traces_Files; +with Strings; use Strings; package LLVM is - procedure Make_Profdata_From_Traces - (Traces : Requested_Trace_Vectors.Vector; Output_File : String); - -- Builds the call to the `llvm-profdata` command, and saves the output - -- profdata file in `Output_File`. + procedure Create_LLVM_Temp_Dir (Auto_Delete : Boolean); - procedure Make_LLVM_Checkpoint_From_Profdata - (Profdata_File, Exe_File, Output_File : String); - -- Builds the call to the LLVM trace adapter and saves the JSON result to - -- `Output_File`. + function Make_LLVM_Checkpoint_From_Traces + (Trace_Inputs : Requested_Trace_Vectors.Vector; + Exe_File : String) return Unbounded_String; + -- Use `llvm-profdata` and the gnatcov LLVM trace adapter to convert the + -- trace inputs into an LLVM JSON checkpoint. + -- Return the expanded the absolute path of the JSON file. end LLVM; From edccd89095de60335c422c16482e094e39998b52 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 19 May 2025 16:33:50 +0200 Subject: [PATCH 1272/1483] tests: Add full pipeline rust test --- .../tests/llvm/rust-full-pipeline/extra.opt | 2 ++ .../stmt/hello-world/Cargo.lock | 7 ++++ .../stmt/hello-world/Cargo.toml | 6 ++++ .../stmt/hello-world/src/main.rs | 7 ++++ .../stmt/hello-world/test.py | 33 +++++++++++++++++++ testsuite/testsuite.py | 9 +++++ 6 files changed, 64 insertions(+) create mode 100644 testsuite/tests/llvm/rust-full-pipeline/extra.opt create mode 100644 testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.lock create mode 100644 testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.toml create mode 100644 testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/src/main.rs create mode 100644 testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/test.py diff --git a/testsuite/tests/llvm/rust-full-pipeline/extra.opt b/testsuite/tests/llvm/rust-full-pipeline/extra.opt new file mode 100644 index 000000000..97aa56ccd --- /dev/null +++ b/testsuite/tests/llvm/rust-full-pipeline/extra.opt @@ -0,0 +1,2 @@ +!rust DEAD Rust tests need a rust toolchain +5.04a1 DEAD Rust toolchain needs gcc >= 4.2 diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.lock b/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.lock new file mode 100644 index 000000000..07ce0fdf8 --- /dev/null +++ b/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "hello-world" +version = "0.1.0" diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.toml b/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.toml new file mode 100644 index 000000000..5d3471414 --- /dev/null +++ b/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "hello-world" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/src/main.rs b/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/src/main.rs new file mode 100644 index 000000000..c77152e58 --- /dev/null +++ b/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/src/main.rs @@ -0,0 +1,7 @@ +fn say_bye() { + println!("Good bye!"); +} + +fn main() { + println!("Hello, world!"); +} diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/test.py b/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/test.py new file mode 100644 index 000000000..7aaa26e96 --- /dev/null +++ b/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/test.py @@ -0,0 +1,33 @@ +""" +Ensure a simple hello-world program is correctly covered +""" + +from SCOV.minicheck import check_xcov_content +from SUITE.context import thistest +from SUITE.cutils import exists, Wdir +from SUITE.tutils import run_and_log, xcov + +_tmp = Wdir("tmp_") + +PROFRAW_FILE = "out.profraw" +EXEC_FILE = "target/debug/hello-world" + +p = run_and_log( + ["cargo", "build", "--manifest-path=../Cargo.toml"], + env={"RUSTFLAGS": "-Cinstrument-coverage", "CARGO_TARGET_DIR": "./target"}, + ignore_environ=False, +) +thistest.fail_if(p.status != 0, f"cargo build failed: {p.err}") + +p = run_and_log([EXEC_FILE], env={"LLVM_PROFILE_FILE": PROFRAW_FILE}) +thistest.fail_if(p.status != 0, f"exe failed: {p.err}") + +thistest.fail_if( + not exists(PROFRAW_FILE), f"trace file '{PROFRAW_FILE}' not found" +) + +xcov(["coverage", "--level=stmt", "-axcov", "--exec", EXEC_FILE, PROFRAW_FILE]) + +check_xcov_content("main.rs.xcov", {"+": {5, 6, 7}, "-": {1, 2, 3}}) + +thistest.result() diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index e6ecc79ce..eb305b142 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1394,6 +1394,7 @@ def _discriminants(self): + self._rts_discriminants() + self._toolchain_discriminants() + self._gnatcov_discriminants() + + self._rust_toolchain_discriminants() ) def _base_discriminants(self): @@ -1524,6 +1525,14 @@ def _gnatcov_discriminants(self): else [] ) + def _rust_toolchain_discriminants(self): + """ + Compute the discriminant that reflects the presence of a rust + toolchain. + """ + + return ["rust"] if which("cargo") else [] + # -------------------------- # -- Command-line options -- # -------------------------- From 0a5962bb52f41906bbd574a7834bd1096756b0b0 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 3 Jul 2025 11:23:34 +0200 Subject: [PATCH 1273/1483] Add documentation excerpt for C/C++ support --- doc/gnatcov/getting_started.rst | 3 ++- doc/gnatcov/src_traces.rst | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/doc/gnatcov/getting_started.rst b/doc/gnatcov/getting_started.rst index f36c2ee99..a9a46dc55 100644 --- a/doc/gnatcov/getting_started.rst +++ b/doc/gnatcov/getting_started.rst @@ -8,7 +8,8 @@ General notions |gcp| is a code coverage analysis tool offering support for a range of coverage metrics and output formats associated with powerful :dfn:`consolidation` features letting users assess the combined -coverage achievements of multiple program executions. +coverage achievements of multiple program executions. It supports Ada, C +and C++. The set of compilation units for which a user needs to assess coverage is commonly designated as the set of :dfn:`units of interest`. This is a diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index cb5f79e2b..e3aa10562 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -556,6 +556,26 @@ preserved during preprocessing, column numbers may be different between the original code and the preprocessed code and thus the coverage report. +.. _instr-c_cpp: + +Instrumentation of C and C++ code +--------------------------------- + +If the project contains C, and C++ sources (meaning the project Language +attributes contains C and/or C++), |gcvins| will instrument them. + +As |gcvins| preprocesses the C/C++ source prior to instrumenting it, it supports +a variety of flags dedicated to C/C++ instrumentation, and some flags passed to +:command:`gprbuild` must also be passed to |gcvins|. Generally speaking, all of +the switches that could impact the preprocessing of the source (e.g. macro +definitions/undefinitions, explicit include paths ...) should be added to the +|gcvins| command line. + +To pass these switches, use the :cmd-option:`-c-opts` and +:cmd-option:`-c++-opts` command line switches. They expect a list of +comma-separated arguments that are forwarded to the preprocessing invocation. + + .. _instr-limitations: |gcvins| limitations From bd2563ad17d144c7a858c08e5eb817090cd4d212 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 7 Jul 2025 11:21:30 +0200 Subject: [PATCH 1274/1483] Document gnatcov setup -gargs option --- doc/gnatcov/src_traces.rst | 4 +++- tools/gnatcov/command_line.ads | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index e3aa10562..a5fffe2c0 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -67,7 +67,9 @@ of this project. Just like :command:`gprbuild`, |gcvstp| accept the :cmd-option:`--RTS`, :cmd-option:`--config` and :cmd-option:`--target` command line options: you need to build the coverage runtime with the same toolchain and runtime as the -ones used to build the application code. For instance: +ones used to build the application code. It also supports a +:cmd-option:`--gargs` option to pass arguments to the :command:`gprbuild` +invocation. For instance: .. code-block:: sh diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index 7f607a91a..a706a5301 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -1428,7 +1428,7 @@ package Command_Line is Pattern => "[GARGS ...]", Help => "Pass GARGS arguments to gprbuild.", Commands => (Cmd_Setup => True, others => False), - Internal => True, + Internal => False, Greedy => True), Opt_Scos => Create (Long_Name => "--scos|--alis", From f27ecca5538381284655c2004821b81bee1654e2 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 2 Jul 2025 16:45:52 +0200 Subject: [PATCH 1275/1483] testsuite: recognize rust source files --- testsuite/SCOV/tc.py | 6 +++--- testsuite/SUITE/control.py | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index 5e7bb23f1..f499cefe2 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -58,10 +58,10 @@ def __with_extensions(self, pattern): return a string listing PATTERN with all the possible language extensions we expect for drivers.""" - # We expect .adb for Ada bodies, .c for C sources and .cpp - # for C++ sources. + # We expect .adb for Ada bodies, .c for C sources, .cpp + # for C++ sources and .rs for Rust sources. return " ".join( - "%s%s" % (pattern, ext) for ext in [".adb", ".c", ".cpp"] + "%s%s" % (pattern, ext) for ext in [".adb", ".c", ".cpp", ".rs"] ) def __expand_shared_controllers(self, drivers, cspecs): diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index ed74ea7fb..362fedae4 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -98,6 +98,9 @@ def __init__(self, name, src_ext, comment, scofile_for, sidfile_for=None): scofile_for=None, sidfile_for=lambda source: source + ".sid", ), + "Rust": LangInfo( + name="Rust", src_ext=[".rs"], comment="//", scofile_for=None + ), "Asm": LangInfo(name="Asm", src_ext=[".s"], comment="#", scofile_for=None), "Cons": LangInfo( name="Consolidation", src_ext=[".txt"], comment="--", scofile_for=None From 3bda98245956fe74749675c35f845d0e2da59342 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 3 Jul 2025 10:49:39 +0200 Subject: [PATCH 1276/1483] SCOV: add cargo.py --- testsuite/SUITE/cargo_utils.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 testsuite/SUITE/cargo_utils.py diff --git a/testsuite/SUITE/cargo_utils.py b/testsuite/SUITE/cargo_utils.py new file mode 100644 index 000000000..5c3abc4f1 --- /dev/null +++ b/testsuite/SUITE/cargo_utils.py @@ -0,0 +1,34 @@ +import os + +from SUITE.cutils import no_ext + +CARGO_TEMPLATE = """[package] +name = "{pkg_name}" +edition = "2024" + +[[bin]] +name = "{bin_name}" +path = "{main_path}" +""" + + +def cargo_for(prjid: str, main: str, src_dir: str, cargo_dir: str) -> str: + """ + Generate a Cargo.toml manifest + + - prjid : Name of the Cargo project + - main : Source simple filename which contains the main function + - src_dir : Directory where `main` lives + - cargo_dir : Directory to generate the Cargo.toml + """ + path = os.path.join(cargo_dir, "Cargo.toml") + with open(path, "w") as f: + f.write( + CARGO_TEMPLATE.format( + pkg_name=prjid, + bin_name=no_ext(main), + main_path=os.path.join(src_dir, main), + ) + ) + + return path From f1e2841abe81484b126d9d585cd714476e488e37 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 3 Jul 2025 11:18:33 +0200 Subject: [PATCH 1277/1483] SCOV: add Rust SCO helper --- testsuite/SCOV/internals/driver.py | 462 ++++++++++++++++++----------- testsuite/SCOV/tc.py | 24 +- 2 files changed, 306 insertions(+), 180 deletions(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index dac12c3da..cc38f28b9 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -44,7 +44,7 @@ from SUITE.cutils import contents_of, lines_of, unhandled_exception_in from SUITE.gprutils import GPRswitches from SUITE.tutils import gprbuild, gprfor, xrun, xcov, frame -from SUITE.tutils import gprbuild_cargs_with +from SUITE.tutils import gprbuild_cargs_with, run_and_log from SUITE.tutils import exename_for from SUITE.tutils import ( srctrace_pattern_for, @@ -53,6 +53,7 @@ ckptname_for, run_cov_program, ) +from SUITE.cargo_utils import cargo_for from .cnotes import r0, r0c, xBlock0, xBlock1, lx0, lx1, lFullCov, lPartCov from .cnotes import Xr0, Xr0c @@ -234,6 +235,17 @@ def __init__(self, wdbase, bdbase, subdirhint): } +def strictest_cat_for(level: str): + if level.startswith("stmt+mcdc"): + return CAT.mcdc + elif level.startswith("stmt+decision"): + return CAT.decision + elif level.startswith("stmt"): + return CAT.stmt + else: + thistest.stop(FatalError("unknwon coverage level: " + level)) + + class _Xchecker: """Internal eXpectation marks checker class. This is used by SCOV_helper to compare sets of lines where coverage marks are expected with sets of @@ -414,45 +426,13 @@ def run(self, discharge_kdict): class SCOV_helper: """Helper class for source coverage activities.""" + def sources_of_interest(self): + """List of sources for which we have expectations to match.""" + return self.xrnotes.keys() + # The differences between the different kinds of traces (binary or source) # are handled by specializing a few operations. - def mode_build(self): - """For a single test (not consolidation), build the program to run - out of the test sources. - """ - raise NotImplementedError - - def mode_execute(self, main): - """Execute the program designated by MAIN, arranging to produce an - execution trace. Return the name of a file containing the execution - output. - """ - raise NotImplementedError - - def mode_scofile_for(self, source): - """The _base_ file name of a file that would contain SCOs for the - provide source file name. This is used as a candidate file name to - be searched in a set of possible object directories for the current - test. - """ - raise NotImplementedError - - def mode_scofiles_switch(self): - """The command line switch to pass to convey the name of a file - containing SCOs, expected to support the '@' response file syntax - as well. This would be passed to gnatcov coverage when units of - interest are not to be conveyed by way of project files. - """ - raise NotImplementedError - - def mode_tracename_for(self, pgm): - """Name of the trace file for the given program name. - - Due to specificities of the source trace files in native contexts, this - method should be called only once the trace file has been created.""" - raise NotImplementedError - def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): # The TESTCASE object that delegates the hard work to us :-) self.testcase = testcase @@ -530,48 +510,6 @@ def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): thistest.fail_if(not self.xlnotes, "empty xlnotes from %s !!" % xfile) thistest.fail_if(not self.xrnotes, "empty xrnotes from %s !!" % xfile) - def sources_of_interest(self): - """List of sources for which we have expectations to match.""" - return self.xrnotes.keys() - - def is_subunit(self, soi): - """Determine whether the input Source Of Interest name denotes - a subunit, assuming source file names obey the standard GNAT naming - convention. - """ - - # There has to be a '-' in the source file name, which could also - # be for a child unit. Check if we also have a line starting with - # "separate" to disambiguate. - - return "-" in os.path.basename(soi) and any( - line.lstrip().lower().startswith("separate") - for line in lines_of(self.abspaths[soi]) - ) - - def units_of_interest(self): - """Set of units for which we have expectations to match, based - on the list of sources for which we have expectations and assuming - standard use of '-' in filenames for child units or subunits - (foo-bar.ads for package Foo.Bar). Subunits are excluded from this - set.. - - ??? If a project has an instrument-c ada unit and an instrument.c - C source file, the representative string will be the same for both. - """ - - uoi = set() - - for soi in self.sources_of_interest(): - extension = ext(soi) - if extension == ".adb" or extension == ".ads": - if not self.is_subunit(soi): - uoi.add(no_ext(os.path.basename(soi)).replace("-", ".")) - else: - uoi.add(os.path.basename(soi)) - - return uoi - def programs(self): """List of base binary file names for the test drivers we are given to exercise. @@ -592,81 +530,12 @@ def singletest(self): """Whether SELF instantiates a single test.""" return len(self.drivers) == 1 - def run(self): - """Evaluate source coverage as exercised by self.drivers""" - - self.log() - - # Whatever the kind of test, we get to a Working Directory and - # switch back when done: - self.to_workdir(self.rwdir()) - - # If we are requested to convey units of interest through a project - # file and don't have a coverage control object to obey, build one to - # convey the units of interest: - - if thistest.options.gprmode and not self.covctl: - self.covctl = CovControl(units_in=self.units_of_interest()) - - # Assess whether we should be using a project file to convey units of - # interest, either requested from the command line or for specific - # test purposes: - - self.gprmode = thistest.options.gprmode or ( - self.covctl and self.covctl.requires_gpr() - ) - - # Compute our GPR now, which we will need for build of single tests - # and/or analysis later on if in gprmode. Turn inlining off for the - # driver unit, so we exercise the functional code as separately - # compiled, not as an inlined version of it in a non-representative - # driver context. - - # Most of the tests with coverage control operate within - # an extra subdir level - this_depth = thistest.depth + 1 if self.covctl else thistest.depth - - self.gpr_obj_dir = "obj" - self.gpr_exe_dir = self.abdir(attribute=True) - self.gpr = gprfor( - mains=self.drivers, - prjid="gen", - objdir=self.gpr_obj_dir, - srcdirs=["../" * n + "src" for n in range(1, this_depth)], - exedir=self.gpr_exe_dir, - main_cargs="-fno-inline", - deps=self.covctl.deps if self.covctl else [], - extra=self.covctl.gpr() if self.covctl else "", - ) - - # For single tests (no consolidation), we first need to build, then - # to execute to get an execution trace. All these we already have for - # consolidation tests, and there's actually no need to build if we - # were provided a bin directory to reuse: - - if self.singletest() and not self.wdctl.reuse_bin: - self.mode_build() - - # Do gnatcov run now unless we're consolidating. We'll just reuse - # traces from previous executions in the latter case. - - if self.singletest(): - self.run_test(main=no_ext(self.drivers[0])) - - # At this point, we have everything we need for the analysis. Either - # from the just done build+run in the single test case, or from - # previous such sequences in the consolidation case. Run gnatcov - # coverage to get actual coverage reports and check against our - # Xpectation specs. - - self.gen_xcov_reports() - self.check_expectations() - - self.to_homedir() - thistest.flush() - - # Let callers retrieve execution data at will - return self + def run(): + """Main driver procedure, which is responsible for generating the + environment, building the test and checking the coverage result against + the expected SCOs. + """ + raise NotImplementedError # ------------------------- # -- working directories -- @@ -778,10 +647,10 @@ def run_test(self, main): "exception raised while running '%s'." % main, ) - def gen_one_xcov_report(self, inputs, report_format, options=""): + def gen_one_xcov_report(self, trace, report_format, options=""): """ Helper for gen_xcov_reports, to produce one specific report for a - particular REPORT_FORMAT, from provided INPUTS. The command output is + particular REPORT_FORMAT, from provided TRACE. The command output is saved in a file named REPORT_FORMAT.out. """ @@ -795,7 +664,7 @@ def gen_one_xcov_report(self, inputs, report_format, options=""): # descriptions. covargs = ( - ["--annotate=" + report_format, inputs] + ["--annotate=" + report_format, trace] + self.covoptions + to_list(options) ) @@ -820,8 +689,8 @@ def gen_one_xcov_report(self, inputs, report_format, options=""): output_lines = lines_of(ofile) for i, line in reversed(list(enumerate(output_lines))): if line == ( - "warning: -S is deprecated. This option will be removed in" - " release 26." + "warning: -S is deprecated. " + "This option will be removed in release 26." ): output_lines.pop(i) output = "\n".join(output_lines) @@ -1024,16 +893,6 @@ def level_strength(lvl): # kinds from the strictest category possibly corresponding to the # xcov-level. - def strictest_cat_for(level: str): - if level.startswith("stmt+mcdc"): - return CAT.mcdc - elif level.startswith("stmt+decision"): - return CAT.decision - elif level.startswith("stmt"): - return CAT.stmt - else: - thistest.stop(FatalError("unknwon coverage level: " + level)) - relevance_cat = ( self.testcase.category if self.testcase.category @@ -1339,7 +1198,161 @@ def xcovlevel_for(self, wdname): return res -class SCOV_helper_bin_traces(SCOV_helper): +class SCOV_helper_gpr(SCOV_helper): + """Helper class for GPR-based tests.""" + + def mode_build(self): + """For a single test (not consolidation), build the program to run + out of the test sources. + """ + raise NotImplementedError + + def mode_execute(self, main): + """Execute the program designated by MAIN, arranging to produce an + execution trace. Return the name of a file containing the execution + output. + """ + raise NotImplementedError + + def mode_scofile_for(self, source): + """The _base_ file name of a file that would contain SCOs for the + provide source file name. This is used as a candidate file name to + be searched in a set of possible object directories for the current + test. + """ + raise NotImplementedError + + def mode_scofiles_switch(self): + """The command line switch to pass to convey the name of a file + containing SCOs, expected to support the '@' response file syntax + as well. This would be passed to gnatcov coverage when units of + interest are not to be conveyed by way of project files. + """ + raise NotImplementedError + + def mode_tracename_for(self, pgm): + """Name of the trace file for the given program name. + + Due to specificities of the source trace files in native contexts, this + method should be called only once the trace file has been created.""" + raise NotImplementedError + + def run(self): + """Evaluate source coverage as exercised by self.drivers""" + + self.log() + + # Whatever the kind of test, we get to a Working Directory and + # switch back when done: + self.to_workdir(self.rwdir()) + + # If we are requested to convey units of interest through a project + # file and don't have a coverage control object to obey, build one to + # convey the units of interest: + + if thistest.options.gprmode and not self.covctl: + self.covctl = CovControl(units_in=self.units_of_interest()) + + # Assess whether we should be using a project file to convey units of + # interest, either requested from the command line or for specific + # test purposes: + + self.gprmode = thistest.options.gprmode or ( + self.covctl and self.covctl.requires_gpr() + ) + + # Compute our GPR now, which we will need for build of single tests + # and/or analysis later on if in gprmode. Turn inlining off for the + # driver unit, so we exercise the functional code as separately + # compiled, not as an inlined version of it in a non-representative + # driver context. + + # Most of the tests with coverage control operate within + # an extra subdir level + this_depth = thistest.depth + 1 if self.covctl else thistest.depth + + self.gpr_obj_dir = "obj" + self.gpr_exe_dir = self.abdir(attribute=True) + self.gpr = gprfor( + mains=self.drivers, + prjid="gen", + objdir=self.gpr_obj_dir, + srcdirs=["../" * n + "src" for n in range(1, this_depth)], + exedir=self.gpr_exe_dir, + main_cargs="-fno-inline", + deps=self.covctl.deps if self.covctl else [], + extra=self.covctl.gpr() if self.covctl else "", + ) + + # For single tests (no consolidation), we first need to build, then + # to execute to get an execution trace. All these we already have for + # consolidation tests, and there's actually no need to build if we + # were provided a bin directory to reuse: + + if self.singletest() and not self.wdctl.reuse_bin: + self.mode_build() + + # Do gnatcov run now unless we're consolidating. We'll just reuse + # traces from previous executions in the latter case. + + if self.singletest(): + self.run_test(main=no_ext(self.drivers[0])) + + # At this point, we have everything we need for the analysis. Either + # from the just done build+run in the single test case, or from + # previous such sequences in the consolidation case. Run gnatcov + # coverage to get actual coverage reports and check against our + # Xpectation specs. + + self.gen_xcov_reports() + self.check_expectations() + + self.to_homedir() + thistest.flush() + + # Let callers retrieve execution data at will + return self + + def is_subunit(self, soi): + """Determine whether the input Source Of Interest name denotes + a subunit, assuming source file names obey the standard GNAT naming + convention. + """ + + # There has to be a '-' in the source file name, which could also + # be for a child unit. Check if we also have a line starting with + # "separate" to disambiguate. + + return "-" in os.path.basename(soi) and any( + line.lstrip().lower().startswith("separate") + for line in lines_of(self.abspaths[soi]) + ) + + def units_of_interest(self): + """Set of units for which we have expectations to match, based + on the list of sources for which we have expectations and assuming + standard use of '-' in filenames for child units or subunits + (foo-bar.ads for package Foo.Bar). Subunits are excluded from this + set.. + + If a project has an instrument-c ada unit and an instrument.c + C source file, the representative string will be the same for both. + """ + + uoi = set() + + for soi in self.sources_of_interest(): + extension = ext(soi) + if extension == ".adb" or extension == ".ads": + if not self.is_subunit(soi): + uoi.add(no_ext(os.path.basename(soi)).replace("-", ".")) + else: + uoi.add(os.path.basename(soi)) + + return uoi + + +class SCOV_helper_bin_traces(SCOV_helper_gpr): """SCOV_helper specialization for the binary execution trace based mode.""" # Outline of the binary trace based scheme: @@ -1404,7 +1417,7 @@ def mode_tracename_for(self, pgm): return tracename_for(pgm) -class SCOV_helper_src_traces(SCOV_helper): +class SCOV_helper_src_traces(SCOV_helper_gpr): """SCOV_helper specialization for the source instrumentation mode.""" # Outline of the source instrumentation based scheme: @@ -1596,3 +1609,110 @@ def dump_trigger(self): return self.covctl.dump_trigger else: return default_dump_trigger(self.drivers) + + +class SCOV_helper_rust(SCOV_helper): + """Helper class for Rust-based tests.""" + + PROFRAW_FILE = "out.profraw" + + def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): + assert len(drivers) == 1, "Multi-driver test is not supported in Rust" + + super().__init__( + testcase, + drivers, + xfile, + xcovlevel, + covctl, + wdctl, + ) + + self.gprmode = False + + def run(self): + self.log() + + # Whatever the kind of test, we get to a Working Directory and + # switch back when done: + self.to_workdir(self.rwdir()) + + # Build the cargo file + cargo_for( + prjid="cargo-gen", + main=self.drivers[0], + src_dir=os.path.join("..", "src"), + cargo_dir=self.awdir(), + ) + + # Build the project cargo + p = run_and_log( + ["cargo", "build", "-v"], + env=self.cargo_environment(), + ignore_environ=False, + ) + if p.status != 0: + thistest.stop(FatalError("cargo build failed", outstr=p.err)) + + # Run the program + p = run_and_log( + [self.get_executable()], + env={"LLVM_PROFILE_FILE": self.PROFRAW_FILE}, + ) + + # At this point, we have everything we need for the analysis. Run + # gnatcov coverage to get actual coverage reports and check against our + # Xpectation specs. + + # Generate report file + self.gen_one_xcov_report( + trace=self.PROFRAW_FILE, + report_format="report", + options=f"--exec {self.get_executable()} -o test.rep", + ) + # Generate xcov file + self.gen_one_xcov_report( + trace=self.PROFRAW_FILE, + report_format="xcov", + options=f"--exec {self.get_executable()}", + ) + self.check_expectations() + + self.to_homedir() + thistest.flush() + + # Let callers retrieve execution data at will + return self + + def _covlevel_to_rust_args(self) -> str: + cov_category = ( + self.testcase.category + if self.testcase.category + else strictest_cat_for(self.xcovlevel) + ) + + if cov_category == CAT.mcdc: + return ["-Cinstrument-coverage", "-Ccoverage-options=mcdc"] + elif cov_category == CAT.decision: + # decision coverage uses Rust's MCDC instrumentation + return ["-Cinstrument-coverage", "-Ccoverage-options=mcdc"] + elif cov_category == CAT.stmt: + return ["-Cinstrument-coverage"] + else: + thistest.stop( + FatalError(f"Unknown coverage level '{cov_category}'") + ) + + def cargo_environment(self) -> dict[str, str]: + return {"RUSTFLAGS": " ".join(self._covlevel_to_rust_args())} + + def get_executable(self): + return os.path.join( + self.abdir(), + "target", + "debug", + exename_for(no_ext(self.drivers[0])), + ) + + def mode_tracename_for(self, _pgm): + return self.PROFRAW_FILE diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index f499cefe2..6c777842c 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -30,11 +30,12 @@ from SCOV.internals.driver import ( SCOV_helper_bin_traces, SCOV_helper_src_traces, + SCOV_helper_rust, ) from SCOV.internals.driver import WdirControl from SCOV.tctl import CAT from SUITE.context import thistest -from SUITE.cutils import to_list, contents_of, FatalError +from SUITE.cutils import to_list, contents_of, FatalError, ext from SUITE.qdata import Qdata, QDentry @@ -265,16 +266,21 @@ def __run_one_covlevel(self, covlevel, covcontrol, subdirhint): requesting SUBDIRHINT to be part of temp dir names. """ - this_scov_helper = ( - SCOV_helper_bin_traces - if thistest.options.trace_mode == "bin" - else ( - SCOV_helper_src_traces - if thistest.options.trace_mode == "src" - else None - ) + rust_test = any(ext(drv) == ".rs" for drv in self.all_drivers) + thistest.stop_if( + rust_test + and not all(ext(drv) == ".rs" for drv in self.all_drivers), + "Rust drivers with other drivers is not yet supported", ) + this_scov_helper = None + if rust_test: + this_scov_helper = SCOV_helper_rust + elif thistest.options.trace_mode == "bin": + this_scov_helper = SCOV_helper_bin_traces + elif thistest.options.trace_mode == "src": + this_scov_helper = SCOV_helper_src_traces + # Compute the Working directory base for this level, then run the test # for each indivdual driver. this_wdbase = this_scov_helper.wdbase_for(self, covlevel) From 665edd335a32cb98fc28169d5d3e8cbef40e427c Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 2 Jul 2025 16:38:47 +0200 Subject: [PATCH 1278/1483] tests: add scov Rust test --- testsuite/SCOV/internals/driver.py | 219 +++++++++--------- .../stmt/hello-world/Cargo.lock | 7 - .../stmt/hello-world/Cargo.toml | 6 - .../stmt/hello-world/src/main.rs | 7 - .../stmt/hello-world/test.py | 33 --- .../stmt/simple-stmt/src/foo.rs | 3 + .../stmt/simple-stmt/src/test_call_foo.rs | 8 + .../stmt/simple-stmt/src/test_no_call_foo.rs | 7 + .../stmt/simple-stmt/test.py | 9 + 9 files changed, 135 insertions(+), 164 deletions(-) delete mode 100644 testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.lock delete mode 100644 testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.toml delete mode 100644 testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/src/main.rs delete mode 100644 testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/test.py create mode 100644 testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/foo.rs create mode 100644 testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/test_call_foo.rs create mode 100644 testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/test_no_call_foo.rs create mode 100644 testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/test.py diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index cc38f28b9..5c61bb20e 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -1055,105 +1055,6 @@ def to_homedir(self): """Switch to this test's homedir.""" cd(self.homedir) - # ----------------------- - # - common_build_gargs -- - # ----------------------- - def common_build_gargs(self): - """Mode agnostic gargs switches to pass to gprbuild commands.""" - - gargs = [] - - # If we have general options to honor when interpreting - # project files for coverage purposes (e.g. --subdirs or -X), - # the builds must be performed accordingly: - if self.covctl and self.covctl.gprsw: - gargs.extend(self.covctl.gprsw.build_switches) - - return gargs - - # -------------------------- - # -- coverage_sco_options -- - # -------------------------- - def coverage_sco_options(self): - """The list of options to pass to gnatcov coverage to convey - SCOs to be discharged for the test at hand.""" - - # If we have a request for specific options, honor that. - - if self.covctl and self.covctl.gprsw: - return self.covctl.gprsw.cov_switches - - # Otherwise, if we are requested to convey unit of interest through - # project file attributes and this is not a consolidation test, use - # our build project file which has been amended for that. - - # ??? Situations where we need to reuse artifacts from the object - # directory of previous tests (e.g. for consolidation or mcdc - # variation tests) would require crafting a project file referring to - # the projects of interest for those previous tests, which isn't - # implemented yet. - - elif self.gprmode and self.singletest() and not self.wdctl.reuse_bin: - return ["-P%s" % self.gpr] - - # Fallback to --scos/--sid with a list of files we compute here: - - else: - return [ - "%s=@%s" - % ( - self.mode_scofiles_switch(), - list_to_file(self._scofiles_list(), "scos.list"), - ) - ] - - def _locate_scofile(self, source): - """Return the fullpath of the ali file corresponding to the given - SOURCE file. Return None if none was found. - """ - - # Whatever the kind of test we are (single or consolidation), we - # expect every ALI file of interest to be associated with at least - # one single test, and to be present in the "obj" subdirectory of - # the associated binary dir. - - # Compute the local path from single test bindir and iterate over - # binary dir for all our drivers until we find. There might actually - # be several instances in the consolidation case. We assume they are - # all identical, and they should be for typical situations where the - # same sources were exercised by multiple drivers: - - lpath = os.path.join("obj", self.mode_scofile_for(source)) - for main in self.drivers: - tloc = os.path.join(self.abdir_for(no_ext(main)), lpath) - if os.path.exists(tloc): - return tloc - - return None - - def _scofiles_list(self): - """Return a set of ali or sid files corresponding to the list of - sources specified in this tests's UXset. - """ - - # It is legitimate for some sources to not have an associated ali, for - # example Ada separate sub-units compiled as part of their parent. We - # just skip those and will fail matching expectations if the SCOs are - # nowhere else. - - # We might also have expectations for different sources that map to - # the same ali, as for example with the spec and body of the same - # package. We make our result a set to prevent duplicates and xcov - # warnings later on. - - return { - scof - for scof in ( - self._locate_scofile(soi) for soi in self.sources_of_interest() - ) - if scof - } - def wdbase_for(self, covlevel): """ Compute a short base prefix for the working directory that will @@ -1197,6 +1098,11 @@ def xcovlevel_for(self, wdname): return res + def coverage_sco_options(self) -> list[str]: + """The list of options to pass to gnatcov coverage to convey + SCOs to be discharged for the test at hand.""" + raise NotImplementedError + class SCOV_helper_gpr(SCOV_helper): """Helper class for GPR-based tests.""" @@ -1351,6 +1257,105 @@ def units_of_interest(self): return uoi + # ----------------------- + # - common_build_gargs -- + # ----------------------- + def common_build_gargs(self): + """Mode agnostic gargs switches to pass to gprbuild commands.""" + + gargs = [] + + # If we have general options to honor when interpreting + # project files for coverage purposes (e.g. --subdirs or -X), + # the builds must be performed accordingly: + if self.covctl and self.covctl.gprsw: + gargs.extend(self.covctl.gprsw.build_switches) + + return gargs + + # -------------------------- + # -- coverage_sco_options -- + # -------------------------- + def coverage_sco_options(self): + """The list of options to pass to gnatcov coverage to convey + SCOs to be discharged for the test at hand.""" + + # If we have a request for specific options, honor that. + + if self.covctl and self.covctl.gprsw: + return self.covctl.gprsw.cov_switches + + # Otherwise, if we are requested to convey unit of interest through + # project file attributes and this is not a consolidation test, use + # our build project file which has been amended for that. + + # ??? Situations where we need to reuse artifacts from the object + # directory of previous tests (e.g. for consolidation or mcdc + # variation tests) would require crafting a project file referring to + # the projects of interest for those previous tests, which isn't + # implemented yet. + + elif self.gprmode and self.singletest() and not self.wdctl.reuse_bin: + return ["-P%s" % self.gpr] + + # Fallback to --scos/--sid with a list of files we compute here: + + else: + return [ + "%s=@%s" + % ( + self.mode_scofiles_switch(), + list_to_file(self._scofiles_list(), "scos.list"), + ) + ] + + def _locate_scofile(self, source): + """Return the fullpath of the ali file corresponding to the given + SOURCE file. Return None if none was found. + """ + + # Whatever the kind of test we are (single or consolidation), we + # expect every ALI file of interest to be associated with at least + # one single test, and to be present in the "obj" subdirectory of + # the associated binary dir. + + # Compute the local path from single test bindir and iterate over + # binary dir for all our drivers until we find. There might actually + # be several instances in the consolidation case. We assume they are + # all identical, and they should be for typical situations where the + # same sources were exercised by multiple drivers: + + lpath = os.path.join("obj", self.mode_scofile_for(source)) + for main in self.drivers: + tloc = os.path.join(self.abdir_for(no_ext(main)), lpath) + if os.path.exists(tloc): + return tloc + + return None + + def _scofiles_list(self): + """Return a set of ali or sid files corresponding to the list of + sources specified in this tests's UXset. + """ + + # It is legitimate for some sources to not have an associated ali, for + # example Ada separate sub-units compiled as part of their parent. We + # just skip those and will fail matching expectations if the SCOs are + # nowhere else. + + # We might also have expectations for different sources that map to + # the same ali, as for example with the spec and body of the same + # package. We make our result a set to prevent duplicates and xcov + # warnings later on. + + return { + scof + for scof in ( + self._locate_scofile(soi) for soi in self.sources_of_interest() + ) + if scof + } + class SCOV_helper_bin_traces(SCOV_helper_gpr): """SCOV_helper specialization for the binary execution trace based mode.""" @@ -1630,6 +1635,9 @@ def __init__(self, testcase, drivers, xfile, xcovlevel, covctl, wdctl): self.gprmode = False + def coverage_sco_options(self) -> list[str]: + return ["--exec", self.get_executable()] + def run(self): self.log() @@ -1664,18 +1672,7 @@ def run(self): # gnatcov coverage to get actual coverage reports and check against our # Xpectation specs. - # Generate report file - self.gen_one_xcov_report( - trace=self.PROFRAW_FILE, - report_format="report", - options=f"--exec {self.get_executable()} -o test.rep", - ) - # Generate xcov file - self.gen_one_xcov_report( - trace=self.PROFRAW_FILE, - report_format="xcov", - options=f"--exec {self.get_executable()}", - ) + self.gen_xcov_reports() self.check_expectations() self.to_homedir() diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.lock b/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.lock deleted file mode 100644 index 07ce0fdf8..000000000 --- a/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.lock +++ /dev/null @@ -1,7 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "hello-world" -version = "0.1.0" diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.toml b/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.toml deleted file mode 100644 index 5d3471414..000000000 --- a/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "hello-world" -version = "0.1.0" -edition = "2024" - -[dependencies] diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/src/main.rs b/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/src/main.rs deleted file mode 100644 index c77152e58..000000000 --- a/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/src/main.rs +++ /dev/null @@ -1,7 +0,0 @@ -fn say_bye() { - println!("Good bye!"); -} - -fn main() { - println!("Hello, world!"); -} diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/test.py b/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/test.py deleted file mode 100644 index 7aaa26e96..000000000 --- a/testsuite/tests/llvm/rust-full-pipeline/stmt/hello-world/test.py +++ /dev/null @@ -1,33 +0,0 @@ -""" -Ensure a simple hello-world program is correctly covered -""" - -from SCOV.minicheck import check_xcov_content -from SUITE.context import thistest -from SUITE.cutils import exists, Wdir -from SUITE.tutils import run_and_log, xcov - -_tmp = Wdir("tmp_") - -PROFRAW_FILE = "out.profraw" -EXEC_FILE = "target/debug/hello-world" - -p = run_and_log( - ["cargo", "build", "--manifest-path=../Cargo.toml"], - env={"RUSTFLAGS": "-Cinstrument-coverage", "CARGO_TARGET_DIR": "./target"}, - ignore_environ=False, -) -thistest.fail_if(p.status != 0, f"cargo build failed: {p.err}") - -p = run_and_log([EXEC_FILE], env={"LLVM_PROFILE_FILE": PROFRAW_FILE}) -thistest.fail_if(p.status != 0, f"exe failed: {p.err}") - -thistest.fail_if( - not exists(PROFRAW_FILE), f"trace file '{PROFRAW_FILE}' not found" -) - -xcov(["coverage", "--level=stmt", "-axcov", "--exec", EXEC_FILE, PROFRAW_FILE]) - -check_xcov_content("main.rs.xcov", {"+": {5, 6, 7}, "-": {1, 2, 3}}) - -thistest.result() diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/foo.rs b/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/foo.rs new file mode 100644 index 000000000..81f164b05 --- /dev/null +++ b/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/foo.rs @@ -0,0 +1,3 @@ +pub fn foo() { // # foo-1 + println!("hello-world"); // # foo-2 +} // # foo-3 diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/test_call_foo.rs b/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/test_call_foo.rs new file mode 100644 index 000000000..81fc88849 --- /dev/null +++ b/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/test_call_foo.rs @@ -0,0 +1,8 @@ +mod foo; + +fn main() { + foo::foo(); +} + +//# foo.rs +// /foo/ l+ ## 0 diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/test_no_call_foo.rs b/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/test_no_call_foo.rs new file mode 100644 index 000000000..6aa5c3c1e --- /dev/null +++ b/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/test_no_call_foo.rs @@ -0,0 +1,7 @@ +mod foo; + +fn main() {} + +//# foo.rs +// /foo-1/ l- ## s- +// /foo-[23]/ l- ## 0 diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/test.py b/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/test.py new file mode 100644 index 000000000..8e5fc2289 --- /dev/null +++ b/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/test.py @@ -0,0 +1,9 @@ +""" +Ensure a simple 1 statement function is correctly covered. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() From dd5e2ff9da62f3731c5e81d48fe7b62921c55a6e Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 4 Jul 2025 12:30:11 +0200 Subject: [PATCH 1279/1483] testsuite: Fix rust discriminant to only be enabled in native --- testsuite/testsuite.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index eb305b142..c2e207866 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1531,7 +1531,12 @@ def _rust_toolchain_discriminants(self): toolchain. """ - return ["rust"] if which("cargo") else [] + # Enable the rust discriminant when on native run and a rust toolchain + # is found + if self.env.host == self.env.target and which("cargo"): + return ["rust"] + else: + return [] # -------------------------- # -- Command-line options -- From 41879624ea801349442b6bbe1e5745ec1f9fbae5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 25 Jun 2025 17:18:46 +0200 Subject: [PATCH 1280/1483] Doc: Clarify Ada runtime dependency for the minimal runtime profile The minimal runtime profile does not depend on any function or object from the Ada runtime, but runtime checks generate a reference on the last chance handler symbol. On light runtime, the default implementation uses the IO units to output an error message, thus forcing dependencies on some runtime units. --- doc/gnatcov/src_traces.rst | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index a5fffe2c0..118bcfb37 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -250,6 +250,21 @@ or provided by the user. ``gnatcov_rts_putchar`` symbol, as detailed in the :ref:`section dedicated to coverage runtime customization`. +.. note:: + While the coverage runtime does not explicitly depend on any object or function + from the Ada runtime, runtime checks added by the compiler will produce a + reference to the ``__gnat_last_chance_handler`` symbol on configurations that + do not support exception propagation. This in turn means that for + configurations that provide a default implementation of the last chance handler, + such as light runtimes, the runtime checks will implicitly depend on some Ada + runtime symbols. + + To avoid this, it is necessary to provide a user defined + last chance handler, as detailed in the + `GNAT's users guide supplement for cross platforms `_. + Instrumenting programs ====================== From 1e2962624522b7b4ba05549e31392cfb7fb889b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 25 Jun 2025 17:18:46 +0200 Subject: [PATCH 1281/1483] Doc: Clarify Ada runtime dependency for the minimal runtime profile The minimal runtime profile does not depend on any function or object from the Ada runtime, but runtime checks generate a reference on the last chance handler symbol. On light runtime, the default implementation uses the IO units to output an error message, thus forcing dependencies on some runtime units. --- doc/gnatcov/src_traces.rst | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 118bcfb37..8d1b81fc3 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -259,11 +259,16 @@ or provided by the user. such as light runtimes, the runtime checks will implicitly depend on some Ada runtime symbols. - To avoid this, it is necessary to provide a user defined - last chance handler, as detailed in the + If this dependency is a problem, it can be avoided by either providing a user + defined last chance handler, as detailed in the `GNAT's users guide supplement for cross platforms `_. + chance-handler>`_, or by disabling runtime checks during the coverage runtime + setup: + + .. code-block:: + + gnatcov setup --no-stdlib -gargs -gnatp Instrumenting programs ====================== From b6d70b93a01021be41af03362459f800a6cd45cd Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 16 Jul 2025 12:32:03 +0200 Subject: [PATCH 1282/1483] Merge the C/C++ doc section with the support for preprocessing The C/C++ doc section is almost exclusively dedicated to preprocessing, so merge it with the section right above dedicated to it. --- doc/gnatcov/src_traces.rst | 33 ++++++++++++++------------------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 8d1b81fc3..7b4236866 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -578,25 +578,20 @@ preserved during preprocessing, column numbers may be different between the original code and the preprocessed code and thus the coverage report. -.. _instr-c_cpp: - -Instrumentation of C and C++ code ---------------------------------- - -If the project contains C, and C++ sources (meaning the project Language -attributes contains C and/or C++), |gcvins| will instrument them. - -As |gcvins| preprocesses the C/C++ source prior to instrumenting it, it supports -a variety of flags dedicated to C/C++ instrumentation, and some flags passed to -:command:`gprbuild` must also be passed to |gcvins|. Generally speaking, all of -the switches that could impact the preprocessing of the source (e.g. macro -definitions/undefinitions, explicit include paths ...) should be added to the -|gcvins| command line. - -To pass these switches, use the :cmd-option:`-c-opts` and -:cmd-option:`-c++-opts` command line switches. They expect a list of -comma-separated arguments that are forwarded to the preprocessing invocation. - +C/C++ pecularities +^^^^^^^^^^^^^^^^^^ + +As a wide variety of compiler switches impacts the preprocessing configuration, +gnatcov supports passing compiler switches to the compiler preprocessor +invocation through the :cmd-option:`-c-opts` and :cmd-option:`-c++-opts`. +Generally speaking, any switch that could impact the preprocessing of the source +(e.g. macro definitions / undefinitions, explicit include paths ...) must be +added to the |gcvins| command line. + +Coverage obligations resulting from macro expansions are designated as such in +detailed (e.g. HTML and XML) coverage reports and their expansions chain is +reported. Note that contrarily to Ada, line and column numbers are preserved in +the coverage report. .. _instr-limitations: From 7f6fc6552d6a18a4bfd7c7de226f44f1cc78eb94 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 10 Jul 2025 06:07:23 +0000 Subject: [PATCH 1283/1483] Adapt srctrace pattern for integrated instrumentation --- testsuite/SUITE/tutils.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index f2666b5ac..1e73d4c80 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -598,7 +598,10 @@ def srctrace_pattern_for(pgmname, manual=False, manual_prj_name=None): mode contain the name of the relevant project in their name. manual_prj_name is the name of the project which trace we want to find. """ - return (manual_prj_name if manual else exename_for(pgmname)) + "*.srctrace" + # Do not take into account the executable extension as under some + # configurations (e.g. integrated instrumentation), we use the main + # basename. + return (manual_prj_name if manual else pgmname) + "*.srctrace" def srctracename_for( From 66bc26e4202df9c08680b1266700894375b3d4cc Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 10 Jul 2025 06:08:08 +0000 Subject: [PATCH 1284/1483] Disable CMake tests not working on Windows --- testsuite/tests/integrated_instrumentation/basic_cmake/test.opt | 1 + .../integrated_instrumentation/cmake_include_switch/test.opt | 1 + testsuite/tests/integrated_instrumentation/cmake_lib/test.opt | 1 + 3 files changed, 3 insertions(+) create mode 100644 testsuite/tests/integrated_instrumentation/basic_cmake/test.opt create mode 100644 testsuite/tests/integrated_instrumentation/cmake_include_switch/test.opt create mode 100644 testsuite/tests/integrated_instrumentation/cmake_lib/test.opt diff --git a/testsuite/tests/integrated_instrumentation/basic_cmake/test.opt b/testsuite/tests/integrated_instrumentation/basic_cmake/test.opt new file mode 100644 index 000000000..41b867856 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/basic_cmake/test.opt @@ -0,0 +1 @@ +windows DEAD CMake builds with gcc not working on windows diff --git a/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.opt b/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.opt new file mode 100644 index 000000000..439c70b1c --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_include_switch/test.opt @@ -0,0 +1 @@ +windows DEAD CMake builds with gcc not supported on windows diff --git a/testsuite/tests/integrated_instrumentation/cmake_lib/test.opt b/testsuite/tests/integrated_instrumentation/cmake_lib/test.opt new file mode 100644 index 000000000..439c70b1c --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/cmake_lib/test.opt @@ -0,0 +1 @@ +windows DEAD CMake builds with gcc not supported on windows From 46676355b294917aa361203b7a1e626d2431e40f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 10 Jul 2025 06:09:03 +0000 Subject: [PATCH 1285/1483] integrated instrumentation: adapt warning message for windows --- .../duplicated_symbols_in_libraries/test.py | 19 ++++++++++----- .../integrated_instrumentation/extra.opt | 4 ++-- .../shared_lib/Makefile | 6 +++-- .../shared_lib/lib/Makefile | 6 +++-- .../shared_lib/lib/common.mk | 5 ++++ .../shared_lib/test.py | 18 +++++++++++---- tools/gnatcov/instrument-gcc_wrapper.adb | 23 ++++++++++++------- tools/gnatcov/paths.adb | 3 --- tools/gnatcov/paths.ads | 3 +++ 9 files changed, 59 insertions(+), 28 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/shared_lib/lib/common.mk diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py index 712be42d1..dff02ab33 100644 --- a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py @@ -71,14 +71,21 @@ # TODO: the warnings regarding homonym filenames are unexpected but they do not # affect the testcase. +expected_warning = ("Warning: same base name for files:" + '\r?\n {libfoo_foo}' + '\r?\n {libbar_foo}' + "\r?\nWarning: same base name for files:" + '\r?\n {libfoo_bar}' + '\r?\n {libbar_bar}').format( + libfoo_foo=os.path.join(cwd, "libfoo", "foo.c"), + libbar_foo=os.path.join(cwd, "libbar", "foo.c"), + libfoo_bar=os.path.join(cwd, "libfoo", "bar.c"), + libbar_bar=os.path.join(cwd, "libbar", "bar.c"), + ) + thistest.fail_if_no_match( '"gnatcov output" ({})'.format(log_file), - "Warning: same base name for files:" - f'\r?\n {os.path.join(cwd, "libfoo", "foo.c")}' - f'\r?\n {os.path.join(cwd, "libbar", "foo.c")}' - "\r?\nWarning: same base name for files:" - f'\r?\n {os.path.join(cwd, "libfoo", "bar.c")}' - f'\r?\n {os.path.join(cwd, "libbar", "bar.c")}', + expected_warning, contents_of(log_file), ) check_xcov_reports( diff --git a/testsuite/tests/integrated_instrumentation/extra.opt b/testsuite/tests/integrated_instrumentation/extra.opt index f38570883..9307e7866 100644 --- a/testsuite/tests/integrated_instrumentation/extra.opt +++ b/testsuite/tests/integrated_instrumentation/extra.opt @@ -1,2 +1,2 @@ -native,linux,src-traces,!5.04a1,!7.1.2,!RTS_ZFP -ALL DEAD Prototype for integrated instrumentation functional for native linux +native,src-traces,!5.04a1,!7.1.2,!RTS_ZFP +ALL DEAD Prototype for integrated instrumentation functional for native diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/Makefile b/testsuite/tests/integrated_instrumentation/shared_lib/Makefile index 0c83caa56..527ff9c30 100644 --- a/testsuite/tests/integrated_instrumentation/shared_lib/Makefile +++ b/testsuite/tests/integrated_instrumentation/shared_lib/Makefile @@ -1,7 +1,9 @@ -main: main.o lib/libfoobar.so +include lib/common.mk + +main: main.o lib/$(LIB) gcc -o main main.o -Llib/ -lfoobar -lib/libfoobar.so: +lib/$(LIB): $(MAKE) -C lib %.o: %.c diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/lib/Makefile b/testsuite/tests/integrated_instrumentation/shared_lib/lib/Makefile index b17460389..1e94beb96 100644 --- a/testsuite/tests/integrated_instrumentation/shared_lib/lib/Makefile +++ b/testsuite/tests/integrated_instrumentation/shared_lib/lib/Makefile @@ -1,8 +1,10 @@ -libfoobar.so: foo.o bar.o +include common.mk + +$(LIB): foo.o bar.o gcc -shared -o $@ $^ %.o: %.c gcc -c -fpic $< -o $@ clean: - rm -f foo.o bar.o libfoobar.so + rm -f foo.o bar.o $(LIB) diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/lib/common.mk b/testsuite/tests/integrated_instrumentation/shared_lib/lib/common.mk new file mode 100644 index 000000000..378147cca --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/shared_lib/lib/common.mk @@ -0,0 +1,5 @@ +ifeq ($(OS),Windows_NT) + LIB := libfoobar.dll +else + LIB := libfoobar.so +endif diff --git a/testsuite/tests/integrated_instrumentation/shared_lib/test.py b/testsuite/tests/integrated_instrumentation/shared_lib/test.py index b2b5da519..e112885be 100644 --- a/testsuite/tests/integrated_instrumentation/shared_lib/test.py +++ b/testsuite/tests/integrated_instrumentation/shared_lib/test.py @@ -39,22 +39,30 @@ # Shadow the compiler driver with the generated wrapper env.add_search_path(env_var="PATH", path=cwd) +# For windows, the OS looks for the DLL in the PATH, and for Linux, it looks +# in the LD_LIBRARY_PATH. +if thistest.env.target.os.name == "windows": + so_path = "PATH" + so_name = "libfoobar.dll" +else: + so_path = "LD_LIBRARY_PATH" + so_name = "libfoobar.so" + # Check that when running the build process without LD_LIBRARY_PATH set, # gnatcov warns that it cannot find the shared library dependency (because it # relies on ldd, which looks at the LD_LIBRARY_PATH to know the shared library # location). cmdrun(["make"], out="make.out", for_pgm=False) thistest.fail_if( - "warning: Could not find library libfoobar.so. Add its directory to" - " the LD_LIBRARY_PATH if this is an instrumented library." + f"warning: Could not find library {so_name}. Add its directory to" + f" the {so_path} if this is an instrumented library." not in contents_of("make.out"), "Missing warning in make output", ) - -# Then, run the build process with LD_LIBRARY_PATH properly set +# Then, run the build process env.add_search_path( - "LD_LIBRARY_PATH", + so_path, os.path.join(cwd, "lib"), ) cmdrun(["make", "clean"], for_pgm=False) diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 48444c19f..e331c4d59 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -1199,19 +1199,26 @@ begin Lib_Filename : constant String := Line (Arrow_Index + 3 .. Filename_End); begin - -- If the library is not on the LD_LIBRARY_PATH, - -- it will be displayed as: + -- If the library is not on the PATH/ + -- LD_LIBRARY_PATH, it will be displayed as: -- -- => not found if Line (Arrow_Index + 3 .. Line'Last) = "not found" then - Outputs.Warn - ("Could not find library " - & Line (Line'First + 1 .. Arrow_Index - 2) - & ". Add its directory to the" - & " LD_LIBRARY_PATH if this is an" - & " instrumented library."); + declare + Path : String := + (if Paths.On_Windows + then "PATH" + else "LD_LIBRARY_PATH"); + begin + Outputs.Warn + ("Could not find library " + & Line (Line'First + 1 .. Arrow_Index - 2) + & ". Add its directory to the " + & Path + & " if this is an instrumented library."); + end; -- Check if this is an actual path, to safeguard -- against cases displayed as: diff --git a/tools/gnatcov/paths.adb b/tools/gnatcov/paths.adb index 50ccce78a..cab270ea2 100644 --- a/tools/gnatcov/paths.adb +++ b/tools/gnatcov/paths.adb @@ -18,7 +18,6 @@ with Ada.Characters.Handling; -with GNAT.OS_Lib; with GNAT.Regpat; with Strings; use Strings; @@ -27,8 +26,6 @@ package body Paths is use all type Unbounded_String; - On_Windows : constant Boolean := GNAT.OS_Lib.Directory_Separator = '\'; - function Likely_Windows_Path (Path : String) return Boolean; -- Whether the provided Path features Windows typical markers diff --git a/tools/gnatcov/paths.ads b/tools/gnatcov/paths.ads index e93acf22d..befcce8dd 100644 --- a/tools/gnatcov/paths.ads +++ b/tools/gnatcov/paths.ads @@ -18,10 +18,13 @@ with Ada.Directories; +with GNAT.OS_Lib; with GNAT.Strings; use GNAT.Strings; package Paths is + On_Windows : constant Boolean := GNAT.OS_Lib.Directory_Separator = '\'; + subtype File_Name is String_Access; function Build_Filename From 8c7f60bc5950abf279dde016d1bd1585e5d4f946 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 10 Jul 2025 08:49:05 +0200 Subject: [PATCH 1286/1483] Integrated instrumentation: remove warning check It is not needed for the test, and it is tedious to compare regexp with paths on windows. --- .../duplicated_symbols_in_libraries/test.py | 21 +------------------ 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py index dff02ab33..45afcaffe 100644 --- a/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py +++ b/testsuite/tests/integrated_instrumentation/duplicated_symbols_in_libraries/test.py @@ -17,7 +17,7 @@ from SCOV.minicheck import check_xcov_reports from SUITE.control import env -from SUITE.cutils import contents_of, Wdir +from SUITE.cutils import Wdir from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov Wdir("tmp_") @@ -69,25 +69,6 @@ out=log_file, ) -# TODO: the warnings regarding homonym filenames are unexpected but they do not -# affect the testcase. -expected_warning = ("Warning: same base name for files:" - '\r?\n {libfoo_foo}' - '\r?\n {libbar_foo}' - "\r?\nWarning: same base name for files:" - '\r?\n {libfoo_bar}' - '\r?\n {libbar_bar}').format( - libfoo_foo=os.path.join(cwd, "libfoo", "foo.c"), - libbar_foo=os.path.join(cwd, "libbar", "foo.c"), - libfoo_bar=os.path.join(cwd, "libfoo", "bar.c"), - libbar_bar=os.path.join(cwd, "libbar", "bar.c"), - ) - -thistest.fail_if_no_match( - '"gnatcov output" ({})'.format(log_file), - expected_warning, - contents_of(log_file), -) check_xcov_reports( ".", { From 770049e9de92526fe17e276f5060acf268e9a089 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 17 Jul 2025 15:14:06 +0200 Subject: [PATCH 1287/1483] integrated_instrumentation: re-disable tests on Windows Most tests fail on this platform currently. Disable them until the correspondings bugs are fixed. --- testsuite/tests/integrated_instrumentation/extra.opt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/integrated_instrumentation/extra.opt b/testsuite/tests/integrated_instrumentation/extra.opt index 9307e7866..f38570883 100644 --- a/testsuite/tests/integrated_instrumentation/extra.opt +++ b/testsuite/tests/integrated_instrumentation/extra.opt @@ -1,2 +1,2 @@ -native,src-traces,!5.04a1,!7.1.2,!RTS_ZFP -ALL DEAD Prototype for integrated instrumentation functional for native +native,linux,src-traces,!5.04a1,!7.1.2,!RTS_ZFP +ALL DEAD Prototype for integrated instrumentation functional for native linux From 50522ec69d75da7b2d42a58891c17ba67d47f95c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 17 Jul 2025 14:55:36 +0000 Subject: [PATCH 1288/1483] Testsuite: include all cargot outputs in error logs --- testsuite/SCOV/internals/driver.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 5c61bb20e..d52a7878b 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -1660,7 +1660,9 @@ def run(self): ignore_environ=False, ) if p.status != 0: - thistest.stop(FatalError("cargo build failed", outstr=p.err)) + thistest.stop( + FatalError("cargo build failed", outstr=p.out + p.err) + ) # Run the program p = run_and_log( From a7432a83856bc38f74d5c437e8a17ee6d1efa7d9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 17 Jul 2025 14:56:04 +0000 Subject: [PATCH 1289/1483] Testsuite: escape backslashes for paths in generated Cargo.toml files --- testsuite/SUITE/cargo_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/SUITE/cargo_utils.py b/testsuite/SUITE/cargo_utils.py index 5c3abc4f1..5361f00f3 100644 --- a/testsuite/SUITE/cargo_utils.py +++ b/testsuite/SUITE/cargo_utils.py @@ -27,7 +27,7 @@ def cargo_for(prjid: str, main: str, src_dir: str, cargo_dir: str) -> str: CARGO_TEMPLATE.format( pkg_name=prjid, bin_name=no_ext(main), - main_path=os.path.join(src_dir, main), + main_path=os.path.join(src_dir, main).replace("\\", "\\\\"), ) ) From ba46c5b7c3dbf6bf5d17f73758928411ec166166 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 17 Jul 2025 14:19:32 +0000 Subject: [PATCH 1290/1483] Testsuite: enable the "rust" discr. only on supported configs --- .../tests/llvm/rust-full-pipeline/extra.opt | 3 +-- testsuite/testsuite.py | 19 +++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/testsuite/tests/llvm/rust-full-pipeline/extra.opt b/testsuite/tests/llvm/rust-full-pipeline/extra.opt index 97aa56ccd..3e3475d67 100644 --- a/testsuite/tests/llvm/rust-full-pipeline/extra.opt +++ b/testsuite/tests/llvm/rust-full-pipeline/extra.opt @@ -1,2 +1 @@ -!rust DEAD Rust tests need a rust toolchain -5.04a1 DEAD Rust toolchain needs gcc >= 4.2 +!rust DEAD Rust support not available in this configuration diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index c2e207866..5da32bf7e 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1531,12 +1531,19 @@ def _rust_toolchain_discriminants(self): toolchain. """ - # Enable the rust discriminant when on native run and a rust toolchain - # is found - if self.env.host == self.env.target and which("cargo"): - return ["rust"] - else: - return [] + # Enable the rust discriminant when: + # * targeting a native platform; + # * gcc is recent enough (>= 4.2); + # * a Rust toolchain is found. + return ( + ["rust"] + if ( + not self.env.is_cross + and "5.04a1" not in self._toolchain_discriminants() + and which("cargo") + ) + else [] + ) # -------------------------- # -- Command-line options -- From b23e3f6937b1b6bef8ef65bef58b01a403f9c2b1 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 17 Jul 2025 15:02:35 +0000 Subject: [PATCH 1291/1483] llvm/rust-full-pipeline/extra.opt: set XFAIL on Windows --- testsuite/tests/llvm/rust-full-pipeline/extra.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/llvm/rust-full-pipeline/extra.opt b/testsuite/tests/llvm/rust-full-pipeline/extra.opt index 3e3475d67..fa8e9e274 100644 --- a/testsuite/tests/llvm/rust-full-pipeline/extra.opt +++ b/testsuite/tests/llvm/rust-full-pipeline/extra.opt @@ -1 +1,2 @@ !rust DEAD Rust support not available in this configuration +windows XFAIL Infra. issues investigated under eng/das/cov/gnatcoverage#416 From e9ded3037e34301a94f6703a3401238fd330c1e9 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 11 Jul 2025 09:02:48 +0200 Subject: [PATCH 1292/1483] Fix typo --- tools/gnatcov/instrument-ada_unit.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 93e0297de..6c91cd89b 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6369,7 +6369,7 @@ package body Instrument.Ada_Unit is -- Pre-compute the return type of the expression if we -- need to generate a qualified expression. -- - -- If we cannot determine it, do not insturment the call. + -- If we cannot determine it, do not instrument the call. begin if Needs_Qualified_Expr then From 595cd9f3005bfb7759f4f80e38f54337518d24a4 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 11 Jul 2025 09:16:31 +0200 Subject: [PATCH 1293/1483] Do not generate coverage obligations for static expr func --- .../tests/Ada2022/static_expr_func/src/test_1.adb | 12 ++++++++++++ testsuite/tests/Ada2022/static_expr_func/test.py | 11 +++++++++++ tools/gnatcov/instrument-ada_unit.adb | 8 ++++++++ 3 files changed, 31 insertions(+) create mode 100644 testsuite/tests/Ada2022/static_expr_func/src/test_1.adb create mode 100644 testsuite/tests/Ada2022/static_expr_func/test.py diff --git a/testsuite/tests/Ada2022/static_expr_func/src/test_1.adb b/testsuite/tests/Ada2022/static_expr_func/src/test_1.adb new file mode 100644 index 000000000..df667356e --- /dev/null +++ b/testsuite/tests/Ada2022/static_expr_func/src/test_1.adb @@ -0,0 +1,12 @@ +pragma Ada_2022; + +procedure Test_1 is + function Foo return Integer is (42) with Static; -- # expr +begin + null; -- # stmt +end Test_1; + +--# test_1.adb +-- +-- /expr/ l. ## 0 +-- /stmt/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/static_expr_func/test.py b/testsuite/tests/Ada2022/static_expr_func/test.py new file mode 100644 index 000000000..c7bdc091a --- /dev/null +++ b/testsuite/tests/Ada2022/static_expr_func/test.py @@ -0,0 +1,11 @@ +""" +Test checking that gnatcov correctly instruments static expression functions +(annotated with the static aspect). +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + +TestCase(category=CAT.stmt).run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 6c91cd89b..0ff8c2803 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -4285,6 +4285,14 @@ package body Instrument.Ada_Unit is return; end if; + -- Do not create coverage obligations for static expression functions + + if Is_Expr_Function + and then N.P_Has_Aspect (To_Unbounded_Text ("Static")) + then + return; + end if; + UIC.Degenerate_Subprogram_Index := UIC.Degenerate_Subprogram_Index + 1; From cf7e00477682dc4e87fe4ac0d2b8cdb04915ff71 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 11 Jul 2025 09:25:29 +0200 Subject: [PATCH 1294/1483] Do not generate coverage obligations for C++ constexpr Similarly to what is done in Ada with static expressions. --- .../C++/mcdc/ConstExpr/src/test_constexpr.cpp | 8 ++-- tools/gnatcov/instrument-c.adb | 43 +++++-------------- 2 files changed, 14 insertions(+), 37 deletions(-) diff --git a/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp b/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp index 9ed547eba..cf461fb6c 100644 --- a/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp +++ b/testsuite/tests/C++/mcdc/ConstExpr/src/test_constexpr.cpp @@ -23,9 +23,9 @@ main () //# test_constexpr.cpp // -// /ce-body/ l? ## s? -// /single-ce-decl/ l? ## d? -// /double-ce-decl/ l? ## d?, d? -// /if-ce/ l? ## d? +// /ce-body/ l. ## 0 +// /single-ce-decl/ l+ ## 0 +// /double-ce-decl/ l+ ## 0 +// /if-ce/ l+ ## 0 // /if-rt/ l- ## s- // /rt/ l+ ## 0 diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 604e966ec..b06322c95 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -2373,8 +2373,6 @@ package body Instrument.C is -- being done with the instrumentation of the function (see the body -- of Traverse_Declarations). - Save_Disable_Instrumentation : constant Boolean := - UIC.Disable_Instrumentation; Save_Disable_Coverage : constant Boolean := UIC.Disable_Coverage; @@ -2395,14 +2393,7 @@ package body Instrument.C is -- Process any embedded decisions if Is_Constexpr (N) then - UIC.Pass.Report - (N, - "gnatcov limitation: cannot instrument constexpr" - & " variable declarations."); - UIC.Disable_Instrumentation := True; - Process_Expression (UIC, N, 'X'); - UIC.Disable_Instrumentation := - Save_Disable_Instrumentation; + return; else Process_Expression (UIC, N, 'X'); end if; @@ -2439,15 +2430,9 @@ package body Instrument.C is Then_Part : constant Cursor_T := Get_Then (N); Else_Part : constant Cursor_T := Get_Else (N); begin - if Is_Constexpr (N) then - UIC.Pass.Report - (N, - "gnatcov limitation: cannot instrument constexpr if" - & " statement."); - UIC.Disable_Instrumentation := True; + if not Is_Constexpr (N) then + Process_Expression (UIC, Get_Cond (N), 'I'); end if; - Process_Expression (UIC, Get_Cond (N), 'I'); - UIC.Disable_Instrumentation := Save_Disable_Instrumentation; Traverse_Statements (UIC, To_Vector (Then_Part), TB); -- Traverse the ELSE statements if present @@ -2840,8 +2825,6 @@ package body Instrument.C is use Cursor_Vectors; Saved_MCDC_State_Declaration_Node : constant Cursor_T := UIC.MCDC_State_Declaration_Node; - Save_Disable_Instrumentation : constant Boolean := - UIC.Disable_Instrumentation; Cursor_Kind : Cursor_Kind_T; begin for N of L loop @@ -2883,19 +2866,15 @@ package body Instrument.C is -- of the function body. begin - if Cursor_Kind /= Cursor_Lambda_Expr then - UIC.Pass.Enter_Scope (UIC, N); - end if; - - -- Do not instrument constexpr function as it would - -- violate the constexpr restrictions. + -- Do not instrument constexpr functions similarly to + -- Ada static expression functions. if Is_Constexpr (N) then - UIC.Pass.Report - (N, - "gnatcov limitation: cannot instrument constexpr" - & " functions."); - UIC.Disable_Instrumentation := True; + goto Continue; + end if; + + if Cursor_Kind /= Cursor_Lambda_Expr then + UIC.Pass.Enter_Scope (UIC, N); end if; if Stmts.Length > 0 then @@ -2942,8 +2921,6 @@ package body Instrument.C is if Cursor_Kind /= Cursor_Lambda_Expr then UIC.Pass.Exit_Scope (UIC); end if; - UIC.Disable_Instrumentation := - Save_Disable_Instrumentation; end; -- Traverse the declarations of a namespace / linkage From af3dcab705c764520fab8cb5d66bce819cb52327 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 16 Jul 2025 11:28:46 +0200 Subject: [PATCH 1295/1483] Fix coverage expectations for constexpr constructors As constexpr are now marked as no code. --- .../cpp/methods-ctors-dtors/src/test_call.cpp | 1 - .../cpp/methods-ctors-dtors/src/test_no_call.cpp | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_call.cpp index bbbb53ce6..172cc279f 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_call.cpp +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_call.cpp @@ -8,4 +8,3 @@ main (void) } //# pkg.cpp -// /default_ctor_def/ l? ## f? diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_no_call.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_no_call.cpp index 8dbcc94f8..9ae415f1d 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_no_call.cpp +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/methods-ctors-dtors/src/test_no_call.cpp @@ -9,7 +9,7 @@ main (void) //# pkg.cpp // /.*def_1/ l- ## f- // /.*def_2/ l- ## 0 -// /default_ctor_def/ l? ## f? +// /default_ctor_def/ l. ## 0 // /var_ctor_def/ l- ## f- // /return/ l- ## s- // /point_.*/ l- ## s- From 6a81fbd374209e16e1ac70c3398a096bc5c9ef1b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 18 Jul 2025 08:43:19 +0000 Subject: [PATCH 1296/1483] gnatcov_llvm_exporter: add missing line break after error message --- tools/gnatcov/trace_adapters/llvm_json/src/main.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/trace_adapters/llvm_json/src/main.cpp b/tools/gnatcov/trace_adapters/llvm_json/src/main.cpp index 0549865dd..c600458a8 100644 --- a/tools/gnatcov/trace_adapters/llvm_json/src/main.cpp +++ b/tools/gnatcov/trace_adapters/llvm_json/src/main.cpp @@ -182,7 +182,8 @@ main (int argc, const char *argv[]) if (Error e = coverage_or_err.takeError ()) { - errs () << "Failed to load coverage: " << toString (std::move (e)); + errs () << "Failed to load coverage: " << toString (std::move (e)) + << '\n'; return EXIT_FAILURE; } From bb71f0daf9d8bde700f39873916c5665aa068fe6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 18 Jul 2025 08:44:42 +0000 Subject: [PATCH 1297/1483] gnatcov_llvm_adapter: write JSON to a file Change the gnatcov LLVM trace adapter so that it writes its JSON output to a file directly rather than on its standard output. This allows gnatcov to run it without redirecting its output streams, providing quick and simple feedback to users in case of error. Before this change, users would only get a mysterious `gnatcov coverage failed: aborting` message. --- tools/gnatcov/llvm.adb | 33 +++++++------------ .../trace_adapters/llvm_json/src/main.cpp | 19 ++++++++--- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/tools/gnatcov/llvm.adb b/tools/gnatcov/llvm.adb index bc50bcf79..1741a3b8a 100644 --- a/tools/gnatcov/llvm.adb +++ b/tools/gnatcov/llvm.adb @@ -112,28 +112,19 @@ package body LLVM is is Trace_Adapter_Cmd : Command_Type := (+Get_LLVM_Trace_Adapter_Exe, others => <>); - Output_Path : constant String := - LLVM_Artifacts_Temp_Dir.Directory_Name / Output_File; begin - - Subprocesses.Append_Arg (Trace_Adapter_Cmd, "--instr-prof"); - Subprocesses.Append_Arg (Trace_Adapter_Cmd, Profdata_File); - Subprocesses.Append_Arg (Trace_Adapter_Cmd, Exe_File); - - if not Subprocesses.Run_Command - (Command => Trace_Adapter_Cmd, - Origin_Command_Name => "gnatcov coverage", - Output_File => Output_Path, - In_To_Null => True) - then - Outputs.Fatal_Error - ("Call to llvm trace adapter didn't succeed." - & " See `" - & Output_Path - & "` for details."); - end if; - - return Output_Path; + return Output_Path : constant String := + LLVM_Artifacts_Temp_Dir.Directory_Name / Output_File + do + Subprocesses.Append_Arg (Trace_Adapter_Cmd, "--instr-prof"); + Subprocesses.Append_Arg (Trace_Adapter_Cmd, Profdata_File); + Subprocesses.Append_Arg (Trace_Adapter_Cmd, Output_Path); + Subprocesses.Append_Arg (Trace_Adapter_Cmd, Exe_File); + Subprocesses.Run_Command + (Command => Trace_Adapter_Cmd, + Origin_Command_Name => "gnatcov coverage", + In_To_Null => True); + end return; end Make_LLVM_Checkpoint_From_Profdata; -------------------------------------- diff --git a/tools/gnatcov/trace_adapters/llvm_json/src/main.cpp b/tools/gnatcov/trace_adapters/llvm_json/src/main.cpp index c600458a8..b17dff64d 100644 --- a/tools/gnatcov/trace_adapters/llvm_json/src/main.cpp +++ b/tools/gnatcov/trace_adapters/llvm_json/src/main.cpp @@ -170,13 +170,25 @@ main (int argc, const char *argv[]) { cl::opt profdata_filename ( "instr-prof", cl::Required, cl::desc (".profdata file location")); + cl::opt json_filename (cl::Positional, cl::Required, + cl::desc ("output JSON file location")); cl::opt object_filename (cl::Positional, cl::Required, cl::desc ("object file location")); cl::ParseCommandLineOptions (argc, argv, "GNATcov LLVM profiling data exporting tool"); - auto FS = vfs::getRealFileSystem (); + // Open the JSON output file + std::error_code EC; + raw_fd_ostream json_file (json_filename, EC); + if (EC) + { + errs () << "Failed to open the JSON output file: " << EC.message () + << '\n'; + return EXIT_FAILURE; + } + // Load the coverage data + auto FS = vfs::getRealFileSystem (); auto coverage_or_err = coverage::CoverageMapping::load ( { object_filename }, profdata_filename, *FS); @@ -187,11 +199,10 @@ main (int argc, const char *argv[]) return EXIT_FAILURE; } + // Convert the coverage data to JSON and write it to the output file auto coverage = std::move (coverage_or_err->get ()); - auto json_export = dump_coverage (*coverage); - - outs () << std::move (json_export); + json_file << std::move (json_export); return EXIT_SUCCESS; } From e614e64dd7d124c39223a7aecba239c921febf3f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 18 Jul 2025 08:48:55 +0000 Subject: [PATCH 1298/1483] trace_adapters/llvm_json: add a .gitignore --- tools/gnatcov/trace_adapters/llvm_json/.gitignore | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 tools/gnatcov/trace_adapters/llvm_json/.gitignore diff --git a/tools/gnatcov/trace_adapters/llvm_json/.gitignore b/tools/gnatcov/trace_adapters/llvm_json/.gitignore new file mode 100644 index 000000000..617381e01 --- /dev/null +++ b/tools/gnatcov/trace_adapters/llvm_json/.gitignore @@ -0,0 +1,2 @@ +obj +gnatcov_llvm_exporter From f0d343a5eb9d27e71adbd6d4aac425f75e3e6eb9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 18 Jul 2025 08:53:33 +0000 Subject: [PATCH 1299/1483] gnatcov_llvm_json: statically link libstdc++ and libgcc This aligns the build of `gnatcov_llvm_json` with the builds of the rest of our tools. Doing so is necessary for this trace adapter to work in contexts where the environment does not provide these shared libraries, or when they provide outdated ones (for instance when using GNAT 7.1.2, which provides a fairly old libstdc++). --- .../trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr b/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr index 1b8f8ad49..543c64a83 100644 --- a/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr +++ b/tools/gnatcov/trace_adapters/llvm_json/gnatcov_llvm_exporter.gpr @@ -10,4 +10,8 @@ project GNATcov_LLVM_exporter is for Executable ("main.cpp") use "gnatcov_llvm_exporter"; end Builder; + package Linker is + for Required_Switches use ("-static-libstdc++", "-static-libgcc"); + end Linker; + end GNATcov_LLVM_exporter; From 30085b3080471a55ed91fdac5eb5c3e735082b3b Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 21 Jul 2025 18:27:36 +0200 Subject: [PATCH 1300/1483] libsupport: Add a last chance handler for aarch64-qnx to flush stdout, and patch funcall C test --- .../src/test_abort.c | 9 ++- .../simple_last_chance_handler.adb | 55 +++++++++++++++++++ .../simple_last_chance_handler.ads | 55 +++++++++++++++++++ 3 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.adb create mode 100644 tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.ads diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c index c887dca8d..6e984780e 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/src/test_abort.c @@ -1,4 +1,7 @@ -#include +#include + +// Calls abort after the last chance handler from libsupport. +void __gnat_last_chance_handler (void); struct list; @@ -17,8 +20,8 @@ struct list * head_abort () { /* GNATCOV_DUMP_BUFFERS */ - abort (); // # not-call - return HEAD; // # not-reached + __gnat_last_chance_handler (); // # not-call + return HEAD; // # not-reached } int diff --git a/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.adb b/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.adb new file mode 100644 index 000000000..edafff410 --- /dev/null +++ b/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.adb @@ -0,0 +1,55 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2024, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with GNAT.IO; +with System; + +package body Simple_Last_Chance_Handler is + + ------------------------- + -- Last_Chance_Handler -- + ------------------------- + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer) is + pragma Unreferenced (Msg, Line); + + procedure C_Abort; + pragma Import (C, C_Abort, "abort"); + pragma No_Return (C_Abort); + + procedure Lch_Enter; + pragma Import (Ada, Lch_Enter, "__lch_enter"); + + procedure Fflush (File : System.Address); + pragma Import (C, Fflush, "fflush"); + + Stdout : System.Address; + pragma Import (C, Stdout, "stdout"); + begin + Lch_Enter; + + -- In QNX, QEMU does not flush the stdout buffer before aborting, + -- so we do it. + Fflush (Stdout); + + -- No return procedure. + C_Abort; + end Last_Chance_Handler; + +end Simple_Last_Chance_Handler; diff --git a/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.ads b/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.ads new file mode 100644 index 000000000..2f6a3c7bd --- /dev/null +++ b/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.ads @@ -0,0 +1,55 @@ +------------------------------------------------------------------------------ +-- -- +-- Couverture -- +-- -- +-- Copyright (C) 2008-2024, AdaCore -- +-- -- +-- Couverture 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 2, or (at your option) any later -- +-- version. Couverture 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 GNAT; see file COPYING. If not, -- +-- write to the Free Software Foundation, 59 Temple Place - Suite 330, -- +-- Boston, MA 02111-1307, USA. -- +-- -- +------------------------------------------------------------------------------ + +with System; + +package Simple_Last_Chance_Handler is + + Unexpected_Last_Chance_Call : Integer := 0; + pragma Export (Ada, Unexpected_Last_Chance_Call, + "__gnat_unexpected_last_chance_call"); + -- This declaration and comment should appear in all of the Ada + -- specs defining __gnat_last_chance_handler, and being used by + -- the GNATcoverage testsuite. Even if the value is not modified + -- in the body of Last_Chance_Handler, there may be procedures + -- that look for this variable's symbol in the executable file, + -- and which will cause errors if the symbol is not found. + -- + -- In most programs, reaching __gnat_last_chance_handler is + -- unexpected. In such cases, the implementation of the body of + -- Last_Chance_Handler that is linked into the program, contains + -- code to indicate that it (Last_Chance_Handler) was called. + -- The body that is linked in the case of a target system with the + -- capability of producing output on Standard_Output, will generate + -- a message using Put calls. If the target does not have output + -- capability, this variable is set to a non-zero value in the body + -- of Last_Chance_Handler, and the final value of + -- Unexpected_Last_Chance_Call is inspected by external means + -- after execution has completed (e.g. by a probe attached to the + -- target board). + -- + -- In programs for which a call to Last_Chance_Handler are expected, + -- a version of the body will be used which neither outputs the + -- error message, nor modifies the value of this variable. + + procedure Last_Chance_Handler (Msg : System.Address; Line : Integer); + pragma Export (C, Last_Chance_Handler, "__gnat_last_chance_handler"); + pragma No_Return (Last_Chance_Handler); + +end Simple_Last_Chance_Handler; From 9234e4a03f40c57e96a91ed99926b9b82764f648 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 15:48:21 +0000 Subject: [PATCH 1301/1483] Kill tests in bin-traces mode when they compute C++ coverage --- testsuite/tests/24_mixed_c_c++/test.opt | 1 + testsuite/tests/ext_annotations/buffers/test.opt | 1 + 2 files changed, 2 insertions(+) diff --git a/testsuite/tests/24_mixed_c_c++/test.opt b/testsuite/tests/24_mixed_c_c++/test.opt index 195e6c2d4..2313ab6b6 100644 --- a/testsuite/tests/24_mixed_c_c++/test.opt +++ b/testsuite/tests/24_mixed_c_c++/test.opt @@ -1 +1,2 @@ !C++ DEAD test requires C++ compiler +bin-traces DEAD Test requires support for C++ source coverage diff --git a/testsuite/tests/ext_annotations/buffers/test.opt b/testsuite/tests/ext_annotations/buffers/test.opt index 7f9195f94..2427c8fc1 100644 --- a/testsuite/tests/ext_annotations/buffers/test.opt +++ b/testsuite/tests/ext_annotations/buffers/test.opt @@ -1 +1,2 @@ !C++ DEAD Requires C++ compiler +bin-traces DEAD Test requires support for C++ source coverage From e36ec5a6ad049c64a155631f0bf9f1c2bfbbcf11 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 14:19:23 +0000 Subject: [PATCH 1302/1483] Q224-032-several-out-of-line: adapt for cross targets --- testsuite/tests/Q224-032-several-out-of-line/shared.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/Q224-032-several-out-of-line/shared.hpp b/testsuite/tests/Q224-032-several-out-of-line/shared.hpp index 804108221..638c8baec 100644 --- a/testsuite/tests/Q224-032-several-out-of-line/shared.hpp +++ b/testsuite/tests/Q224-032-several-out-of-line/shared.hpp @@ -1,7 +1,6 @@ -#include - +extern "C" void bar(); extern void shared(); inline void shared() { - std::cout << "Hello, world!" << std::endl; + bar(); } From 001d416fcdb7b0e14c5dc3df34fd3b2a9a57e70f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 15:34:56 +0000 Subject: [PATCH 1303/1483] 129-instr-progress: adapt for cross targets --- testsuite/tests/129-instr-progress/c_unit.c | 5 ++--- testsuite/tests/129-instr-progress/cpp_unit.cpp | 5 ++--- testsuite/tests/129-instr-progress/print.c | 4 ++++ testsuite/tests/129-instr-progress/test.py | 7 ++++--- 4 files changed, 12 insertions(+), 9 deletions(-) create mode 100644 testsuite/tests/129-instr-progress/print.c diff --git a/testsuite/tests/129-instr-progress/c_unit.c b/testsuite/tests/129-instr-progress/c_unit.c index c3737dc54..60583b508 100644 --- a/testsuite/tests/129-instr-progress/c_unit.c +++ b/testsuite/tests/129-instr-progress/c_unit.c @@ -1,10 +1,9 @@ -#include - extern void cpp_func (void); +extern void print_msg (const char *); void c_func (void) { - puts ("c:c_func"); + print_msg ("c:c_func"); cpp_func (); } diff --git a/testsuite/tests/129-instr-progress/cpp_unit.cpp b/testsuite/tests/129-instr-progress/cpp_unit.cpp index 32833a39b..4b539078f 100644 --- a/testsuite/tests/129-instr-progress/cpp_unit.cpp +++ b/testsuite/tests/129-instr-progress/cpp_unit.cpp @@ -1,12 +1,11 @@ -#include - extern "C" { + extern void print_msg (const char *); extern void cpp_func (void); } void cpp_func (void) { - std::cout << "cpp:cpp_func" << std::endl; + print_msg ("cpp:cpp_func"); } diff --git a/testsuite/tests/129-instr-progress/print.c b/testsuite/tests/129-instr-progress/print.c new file mode 100644 index 000000000..46c10c20c --- /dev/null +++ b/testsuite/tests/129-instr-progress/print.c @@ -0,0 +1,4 @@ +void +print_msg (const char *) +{ +} diff --git a/testsuite/tests/129-instr-progress/test.py b/testsuite/tests/129-instr-progress/test.py index a4eb82a7b..a269042d9 100644 --- a/testsuite/tests/129-instr-progress/test.py +++ b/testsuite/tests/129-instr-progress/test.py @@ -20,7 +20,8 @@ langs=["Ada", "C", "C++"], mains=["main.adb"], srcdirs=[".."], - ) + ), + units=["main", "c_unit.c", "cpp_unit.cpp"], ), covlevel="stmt", mains=["main"], @@ -35,8 +36,8 @@ "xcov", { "main.adb.xcov": {"+": {7, 8}}, - "c_unit.c.xcov": {"+": {8}}, - "cpp_unit.cpp.xcov": {"+": {11}}, + "c_unit.c.xcov": {"+": {7, 8}}, + "cpp_unit.cpp.xcov": {"+": {10}}, }, ) From 87404cafe6490d65d23f2f1292e6d02789ce8b56 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 16:08:00 +0000 Subject: [PATCH 1304/1483] instr-cov/logging: adapt for cross targets --- testsuite/tests/instr-cov/logging/src-my_tool/my_tool.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/instr-cov/logging/src-my_tool/my_tool.cpp b/testsuite/tests/instr-cov/logging/src-my_tool/my_tool.cpp index e815d9e7d..f951746e3 100644 --- a/testsuite/tests/instr-cov/logging/src-my_tool/my_tool.cpp +++ b/testsuite/tests/instr-cov/logging/src-my_tool/my_tool.cpp @@ -1,4 +1,7 @@ -#include +void +print_msg (const char *) +{ +} int main () From 1a4790f5dc72854ceb79d8974db8b120da1b97a4 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 13:01:23 +0000 Subject: [PATCH 1305/1483] N321-039-disas-wrapping: rework for arm-elf compatibility --- testsuite/tests/N321-039-disas-wrapping/foo.s | 10 +++-- .../tests/N321-039-disas-wrapping/test.opt | 3 +- .../tests/N321-039-disas-wrapping/test.py | 43 ++++++++++--------- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/testsuite/tests/N321-039-disas-wrapping/foo.s b/testsuite/tests/N321-039-disas-wrapping/foo.s index 910228d0b..42bc95c1c 100644 --- a/testsuite/tests/N321-039-disas-wrapping/foo.s +++ b/testsuite/tests/N321-039-disas-wrapping/foo.s @@ -1,6 +1,10 @@ +.cpu cortex-m4 +.arch armv7e-m +.fpu fpv4-sp-d16 +.file "foo.c" .text -.globl _start -.type _start, @function +.align 2 +.type _start, %function _start: - nop +.word 0 .size _start, .-_start diff --git a/testsuite/tests/N321-039-disas-wrapping/test.opt b/testsuite/tests/N321-039-disas-wrapping/test.opt index 9feabe86d..11de9f8f2 100644 --- a/testsuite/tests/N321-039-disas-wrapping/test.opt +++ b/testsuite/tests/N321-039-disas-wrapping/test.opt @@ -1,3 +1,2 @@ -x86-linux,bin-traces -x86_64-linux,bin-traces +arm-elf ALL DEAD diff --git a/testsuite/tests/N321-039-disas-wrapping/test.py b/testsuite/tests/N321-039-disas-wrapping/test.py index 7ed4ed5af..ee3f705af 100644 --- a/testsuite/tests/N321-039-disas-wrapping/test.py +++ b/testsuite/tests/N321-039-disas-wrapping/test.py @@ -3,32 +3,33 @@ well instructions at the end of the address space. """ +from e3.os.process import Run + from SUITE.context import thistest -from SUITE.cutils import Wdir -from SUITE.tutils import gprfor, gprbuild, xcov +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import xcov tmp_ = Wdir("tmp_") -# We want to link the code at the end of the address space, so get the correct -# upper address depending on the architecture. - -address = 2**32 - 1 if "32bits" in thistest.options.tags else 2**64 - 1 - -gprfile = gprfor( - ["foo.s"], - srcdirs="..", - langs=("Asm"), - extra=""" - package Linker is - for Default_Switches ("Asm") use ("-nostdlib", "-Ttext={}"); - end Linker; -""".format( - address - ), -) -exefile = "foo" +# We want to link the code (4 bytes) at the end of the address space, so get +# the correct upper address depending on the architecture. -gprbuild(gprfile) +address = (2**32 if "32bits" in thistest.options.tags else 2**64) - 4 + +exefile = "foo" +log_file = "gcc.log" +p = Run( + [ + "arm-eabi-gcc", + "-o", + exefile, + "../foo.s", + "-nostdlib", + f"-Ttext={hex(address)}", + ], + output=log_file, +) +thistest.fail_if(p.status != 0, "gcc failed:\n" + contents_of(log_file)) for subcmd in ("dump-cfg", "disassemble-insn-properties"): # As long as GNATcov do not crash/hangs, everything is fine! From e630fa41d6598100f1d38845f2b29159cc57fdfe Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 13:14:06 +0000 Subject: [PATCH 1306/1483] N411-046-asm-consolidation: make it work for all platforms --- .../N411-046-asm-consolidation/p-default.s | 8 ------- .../N411-046-asm-consolidation/p-win32.s | 11 ---------- .../N411-046-asm-consolidation/p-win64.s | 11 ---------- .../tests/N411-046-asm-consolidation/p.c | 5 +++++ .../tests/N411-046-asm-consolidation/test.opt | 6 ++--- .../tests/N411-046-asm-consolidation/test.py | 22 +++++++++++-------- 6 files changed, 20 insertions(+), 43 deletions(-) delete mode 100644 testsuite/tests/N411-046-asm-consolidation/p-default.s delete mode 100644 testsuite/tests/N411-046-asm-consolidation/p-win32.s delete mode 100644 testsuite/tests/N411-046-asm-consolidation/p-win64.s create mode 100644 testsuite/tests/N411-046-asm-consolidation/p.c diff --git a/testsuite/tests/N411-046-asm-consolidation/p-default.s b/testsuite/tests/N411-046-asm-consolidation/p-default.s deleted file mode 100644 index 731b897b9..000000000 --- a/testsuite/tests/N411-046-asm-consolidation/p-default.s +++ /dev/null @@ -1,8 +0,0 @@ - .text - .align 2 - .globl p - .type p, @function -p: - ret - - .size p, .-p diff --git a/testsuite/tests/N411-046-asm-consolidation/p-win32.s b/testsuite/tests/N411-046-asm-consolidation/p-win32.s deleted file mode 100644 index c76b463b5..000000000 --- a/testsuite/tests/N411-046-asm-consolidation/p-win32.s +++ /dev/null @@ -1,11 +0,0 @@ - .text - .align 2 - .globl _p - .def _p; .scl 2; .type 32; .endef -_p: - ret - - .globl _dummy - .def _dummy; .scl 2; .type 32; .endef -_dummy: - ret diff --git a/testsuite/tests/N411-046-asm-consolidation/p-win64.s b/testsuite/tests/N411-046-asm-consolidation/p-win64.s deleted file mode 100644 index b9d2cdf38..000000000 --- a/testsuite/tests/N411-046-asm-consolidation/p-win64.s +++ /dev/null @@ -1,11 +0,0 @@ - .text - .align 2 - .globl p - .def p; .scl 2; .type 32; .endef -p: - ret - - .globl dummy - .def dummy; .scl 2; .type 32; .endef -dummy: - ret diff --git a/testsuite/tests/N411-046-asm-consolidation/p.c b/testsuite/tests/N411-046-asm-consolidation/p.c new file mode 100644 index 000000000..f89e9a25e --- /dev/null +++ b/testsuite/tests/N411-046-asm-consolidation/p.c @@ -0,0 +1,5 @@ +void +p (void) +{ + return; +} diff --git a/testsuite/tests/N411-046-asm-consolidation/test.opt b/testsuite/tests/N411-046-asm-consolidation/test.opt index f07cdbf24..c194a3994 100644 --- a/testsuite/tests/N411-046-asm-consolidation/test.opt +++ b/testsuite/tests/N411-046-asm-consolidation/test.opt @@ -1,4 +1,2 @@ --- Binary traces specific testcase -bin-traces,x86 -bin-traces,x86_64 -ALL DEAD Embeds x86* assembly sources +bin-traces +ALL DEAD Binary traces specific testcase diff --git a/testsuite/tests/N411-046-asm-consolidation/test.py b/testsuite/tests/N411-046-asm-consolidation/test.py index 49ec8619c..a68ae4a1b 100644 --- a/testsuite/tests/N411-046-asm-consolidation/test.py +++ b/testsuite/tests/N411-046-asm-consolidation/test.py @@ -10,9 +10,10 @@ import shutil from OCOV.tc import TestCase -from SUITE.context import env, thistest +from SUITE.context import thistest from SUITE.cutils import Wdir -from SUITE.tutils import tracename_for +from SUITE.tutils import gprbuild, gprfor, tracename_for + test_drivers = { "test": {"p.s": ["-g"]}, @@ -24,15 +25,18 @@ "p": {"-": 0, "!": 0, "+": 1}, } -tmp = Wdir("tmp_") +# Generate a project just so that we use the C toolchain in order to generate +# the assembly sources (-save-temps). Make sure we do not generate debug info +# in the assembly code (-g0). +tmp = Wdir("tmp_asm") +prj = gprfor(mains=[], srcdirs=[".."], langs=["C"]) +gprbuild(prj, gargs=["-c", "-u", "p.c"], extracargs=["-save-temps", "-g0"]) +tmp.to_homedir() +# Run the consolidation check +tmp = Wdir("tmp_") shutil.copy(os.path.join("..", "test.c"), "test.c") - -# Select an assembly source that fits the build platform -variant = "default" -if env.build.os.name == "windows": - variant = "win32" if env.build.cpu.bits == 32 else "win64" -shutil.copy(os.path.join("..", "p-{}.s".format(variant)), "p.s") +shutil.copy(os.path.join("..", "tmp_asm", "obj", "p.s"), "p.s") TestCase( test_drivers, From 628fdcd7bc9eceda37f9e22f6c0beca3d46b28d5 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 13:22:49 +0000 Subject: [PATCH 1307/1483] N429-018-c-assert/ToMultiStmts: adapt for cross targets --- .../ToMultiStmts/src/test_assert.c | 20 +++++++++++++++---- .../N429-018-c-assert/ToMultiStmts/test.opt | 1 - 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/testsuite/tests/N429-018-c-assert/ToMultiStmts/src/test_assert.c b/testsuite/tests/N429-018-c-assert/ToMultiStmts/src/test_assert.c index 9ceab8ba5..935c9b727 100644 --- a/testsuite/tests/N429-018-c-assert/ToMultiStmts/src/test_assert.c +++ b/testsuite/tests/N429-018-c-assert/ToMultiStmts/src/test_assert.c @@ -1,4 +1,17 @@ -#include +#include + +void +write_error (const char *) +{ +} + +// Dummy implementation of assert that expands to multiple statements. +#define assert(expr) \ + ({ \ + int _result = expr; \ + if (!_result) \ + write_error ("assertion failure: " #expr); \ + }) int main (int argc, char *argv[]) @@ -11,6 +24,5 @@ main (int argc, char *argv[]) //# test_assert.c // /stmt-simple/ l+ ## 0 // /stmt-assert/ l! ## s- -// On GNU/Linux, "assert" is usually implemented as a macro which, after -// expansion, yields multiple statements. Given the current state of the -// technology, one of them is expected not to be covered. See NB17-025. +// Given the current state of the technology, one of the expanded +// statements is expected not to be covered. See NB17-025. diff --git a/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.opt b/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.opt index 5954ef81d..55366c383 100644 --- a/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.opt +++ b/testsuite/tests/N429-018-c-assert/ToMultiStmts/test.opt @@ -1,3 +1,2 @@ -!native DEAD Test relies on host standard header files !bin-traces DEAD Coverage for C supported only with binary traces windows DEAD This test variant has platform-specific expectations From cf7c2c9f8e19f73e40af9870928278b24d6796b2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 13:24:20 +0000 Subject: [PATCH 1308/1483] N429-020-loop-on-line: adapt for cross targets --- testsuite/tests/N429-020-loop-on-line/main.c | 2 -- testsuite/tests/N429-020-loop-on-line/test.opt | 1 - 2 files changed, 3 deletions(-) diff --git a/testsuite/tests/N429-020-loop-on-line/main.c b/testsuite/tests/N429-020-loop-on-line/main.c index 3aeb7d1d7..564499405 100644 --- a/testsuite/tests/N429-020-loop-on-line/main.c +++ b/testsuite/tests/N429-020-loop-on-line/main.c @@ -1,5 +1,3 @@ -#include - #define MAX_FD 32 #define NULL ((void *) 0) diff --git a/testsuite/tests/N429-020-loop-on-line/test.opt b/testsuite/tests/N429-020-loop-on-line/test.opt index d2ab6f91b..7d9cc4034 100644 --- a/testsuite/tests/N429-020-loop-on-line/test.opt +++ b/testsuite/tests/N429-020-loop-on-line/test.opt @@ -1,2 +1 @@ -!native DEAD !bin-traces DEAD test with map-routines From 8d67d626adfe91ce0b554af8d96c7ff3a1656fec Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 13:58:24 +0000 Subject: [PATCH 1309/1483] OA16-009-windows-suffix: adapt for cross targets --- testsuite/tests/OA16-009-windows-suffix/test.opt | 2 +- testsuite/tests/OA16-009-windows-suffix/test.py | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/OA16-009-windows-suffix/test.opt b/testsuite/tests/OA16-009-windows-suffix/test.opt index 8a957cb72..1c3d0106a 100644 --- a/testsuite/tests/OA16-009-windows-suffix/test.opt +++ b/testsuite/tests/OA16-009-windows-suffix/test.opt @@ -1,2 +1,2 @@ -bin-traces,windows +bin-traces,windows-host ALL DEAD This test variant has platform specific expectations and checks "gnatcov run" (bin traces specific) diff --git a/testsuite/tests/OA16-009-windows-suffix/test.py b/testsuite/tests/OA16-009-windows-suffix/test.py index 9c1bb1b35..0cf25b6fc 100644 --- a/testsuite/tests/OA16-009-windows-suffix/test.py +++ b/testsuite/tests/OA16-009-windows-suffix/test.py @@ -10,7 +10,11 @@ # We want to check that "gnatcov run" will find the executable even though the # input casing is different and even though it misses the ".exe" suffix. -os.rename("foo.exe", "Foo.Exe") +# +# This test runs only on Windows, and binary traces support for Windows is not +# supported anymore, so executables produced by gprbuild by default never have +# the "exe" extension. +os.rename("foo", "Foo.Exe") xrun("foo") # Here, we also want to check that the default filename for the trace file is From f136ce62f1d4f1e1ab9d8fc865d881cd5c15c6da Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 14:29:07 +0000 Subject: [PATCH 1310/1483] Q308-041-crash-on-generic-in-lib: adapt for cross targets --- .../app/default.gpr | 5 -- .../libfoo/libfoo.gpr | 7 -- .../Q308-041-crash-on-generic-in-lib/test.opt | 2 +- .../Q308-041-crash-on-generic-in-lib/test.py | 81 +++++++++---------- 4 files changed, 39 insertions(+), 56 deletions(-) delete mode 100644 testsuite/tests/Q308-041-crash-on-generic-in-lib/app/default.gpr delete mode 100644 testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/libfoo.gpr diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/app/default.gpr b/testsuite/tests/Q308-041-crash-on-generic-in-lib/app/default.gpr deleted file mode 100644 index ab744582e..000000000 --- a/testsuite/tests/Q308-041-crash-on-generic-in-lib/app/default.gpr +++ /dev/null @@ -1,5 +0,0 @@ -with "../libfoo/install/gpr/libfoo.gpr"; -project Default is - for Main use ("main.adb"); - for Object_Dir use "obj"; -end Default; diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/libfoo.gpr b/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/libfoo.gpr deleted file mode 100644 index 457330ac2..000000000 --- a/testsuite/tests/Q308-041-crash-on-generic-in-lib/libfoo/libfoo.gpr +++ /dev/null @@ -1,7 +0,0 @@ -library project Libfoo is - for Library_Kind use "static"; - for Library_Name use "foo"; - for Object_Dir use "obj"; - for Library_Dir use "lib"; - -end Libfoo; diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.opt b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.opt index 63306d93b..80db95e5d 100644 --- a/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.opt +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.opt @@ -1,2 +1,2 @@ -bin-traces,native,linux +bin-traces ALL DEAD diff --git a/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py index 8b7aa4ddc..77e64c56f 100644 --- a/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py +++ b/testsuite/tests/Q308-041-crash-on-generic-in-lib/test.py @@ -7,58 +7,53 @@ DW_TAG_compilation_unit entry (.debug_info). """ -import os - -from e3.fs import rm -from e3.os.process import Run - -from SUITE.tutils import thistest - - -def try_run(cmd): - p = Run(cmd) - thistest.fail_if( - p.status != 0, - "Unexpected failure.\n" - "Command was:\n" - "%s\n" - "Output was:\n" - "%s" % (" ".join(cmd), p.out), - ) - - -home = os.getcwd() - -os.chdir("%s/libfoo" % home) -rm("install", recursive=True) - -try_run(["gprbuild", "-f", "-Plibfoo.gpr", "-p"]) -try_run( - [ - "gprinstall", - "-f", - "-Plibfoo.gpr", - "-p", - "--prefix=install", - "--project-subdir=gpr", - ] +import os.path + +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, gprbuild, gprinstall, xrun, xcov + + +# Build libfoo and install it in some prefix, then make the installed project +# available through the GPR_PROJECT_PATH environment variable. +tmp = Wdir("tmp_libfoo") +install_dir = os.path.abspath("install") +libfoo_gpr = gprfor( + prjid="libfoo", + mains=[], + srcdirs=["../libfoo"], + langs=["Ada"], + extra=""" + for Library_Kind use "static"; + for Library_Name use "foo"; + for Library_Dir use "lib"; + """, ) - -os.chdir("%s/app" % home) - -try_run(["gprbuild", "-f", "-Pdefault.gpr", "-p"]) -try_run(["gnatcov", "run", "obj/main"]) +gprbuild(libfoo_gpr) +gprinstall(libfoo_gpr, gargs=[f"--prefix={install_dir}"]) +os.environ["GPR_PROJECT_PATH"] = os.path.join(install_dir, "share", "gpr") +tmp.to_homedir() + +# Now, in another directory (so that we are sure it is the installed libfoo +# that is used), build the main application, then generate a binary trace for +# it. +tmp = Wdir("tmp_app") +app_gpr = gprfor( + prjid="app", mains=["main.adb"], srcdirs=["../app"], deps=["libfoo"] +) +gprbuild(app_gpr) +xrun("./main") # The very goal of this testcase is to compute code coverage for a unit that # belongs to a project installed with gprinstall, so we need to enable the # processing of externally built projects. -try_run( +xcov( [ - "gnatcov", "coverage", "--annotate=xcov", "--level=stmt", - "-Pdefault", + "-P", + app_gpr, "--projects=libfoo", "--externally-built-projects", "main.trace", From 17a583982a2c9f399157aafcd7b00e230372387f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 15:21:16 +0000 Subject: [PATCH 1311/1483] SB06-033-homonyms: adapt for cross targets --- .../tests/SB06-033-homonyms/app/default.gpr | 8 -- .../tests/SB06-033-homonyms/libfoo/lib.adb | 2 + .../tests/SB06-033-homonyms/libfoo/lib.ads | 2 + .../tests/SB06-033-homonyms/libfoo/libfoo.gpr | 11 --- testsuite/tests/SB06-033-homonyms/test.opt | 4 - testsuite/tests/SB06-033-homonyms/test.py | 94 ++++++++----------- 6 files changed, 43 insertions(+), 78 deletions(-) delete mode 100644 testsuite/tests/SB06-033-homonyms/app/default.gpr delete mode 100644 testsuite/tests/SB06-033-homonyms/libfoo/libfoo.gpr diff --git a/testsuite/tests/SB06-033-homonyms/app/default.gpr b/testsuite/tests/SB06-033-homonyms/app/default.gpr deleted file mode 100644 index 08e41a7d5..000000000 --- a/testsuite/tests/SB06-033-homonyms/app/default.gpr +++ /dev/null @@ -1,8 +0,0 @@ -with "../libfoo/install/gpr/libfoo.gpr"; -project Default is - for Main use ("main.adb"); - for Object_Dir use "obj"; - package Compiler is - for Switches ("Ada") use ("-g", "-fpreserve-control-flow", "-fdump-scos"); - end Compiler; -end Default; diff --git a/testsuite/tests/SB06-033-homonyms/libfoo/lib.adb b/testsuite/tests/SB06-033-homonyms/libfoo/lib.adb index ab47e2689..27321e3d5 100644 --- a/testsuite/tests/SB06-033-homonyms/libfoo/lib.adb +++ b/testsuite/tests/SB06-033-homonyms/libfoo/lib.adb @@ -1,3 +1,5 @@ +pragma Ada_2012; + package body Lib is function First return Integer is (1); function Next (I : Integer) return Integer is (I + 1); diff --git a/testsuite/tests/SB06-033-homonyms/libfoo/lib.ads b/testsuite/tests/SB06-033-homonyms/libfoo/lib.ads index d37d29aeb..29e7795cd 100644 --- a/testsuite/tests/SB06-033-homonyms/libfoo/lib.ads +++ b/testsuite/tests/SB06-033-homonyms/libfoo/lib.ads @@ -1,3 +1,5 @@ +pragma Ada_2012; + package Lib is function First return Integer; function Next (I : Integer) return Integer diff --git a/testsuite/tests/SB06-033-homonyms/libfoo/libfoo.gpr b/testsuite/tests/SB06-033-homonyms/libfoo/libfoo.gpr deleted file mode 100644 index e87f208cb..000000000 --- a/testsuite/tests/SB06-033-homonyms/libfoo/libfoo.gpr +++ /dev/null @@ -1,11 +0,0 @@ -library project Libfoo is - for Library_Kind use "static"; - for Library_Name use "foo"; - for Object_Dir use "obj"; - for Library_Dir use "lib"; - - package Compiler is - for Switches ("Ada") use - ("-g", "-O0", "-fpreserve-control-flow", "-fdump-scos"); - end Compiler; -end Libfoo; diff --git a/testsuite/tests/SB06-033-homonyms/test.opt b/testsuite/tests/SB06-033-homonyms/test.opt index a22f4846b..54c050461 100644 --- a/testsuite/tests/SB06-033-homonyms/test.opt +++ b/testsuite/tests/SB06-033-homonyms/test.opt @@ -1,5 +1 @@ --- This test checks the processing of gnatcov on externally built projects, --- which is supported only on native targets and with binary traces. -!native DEAD -!linux DEAD src-traces DEAD S918-031: src-traces and externally built projects diff --git a/testsuite/tests/SB06-033-homonyms/test.py b/testsuite/tests/SB06-033-homonyms/test.py index 4f0ea5de7..d306b673a 100644 --- a/testsuite/tests/SB06-033-homonyms/test.py +++ b/testsuite/tests/SB06-033-homonyms/test.py @@ -6,75 +6,59 @@ mapping (.debug_lines). """ -import os - -from e3.fs import rm -from e3.os.process import Run +import os.path from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of - - -wd = Wdir("tmp_") -log_dir = os.getcwd() -wd.to_homedir() - - -def in_home(*args): - return os.path.join(wd.homedir, *args) - - -def try_run(cmd, out_file): - out_file = os.path.join(log_dir, out_file) - p = Run(cmd, output=out_file) - out = contents_of(out_file) - thistest.fail_if( - p.status != 0, - "Unexpected failure.\n" - "Command was:\n" - "%s\n" - "Output was:\n" - "%s" % (" ".join(cmd), out), - ) - return out - - -os.chdir(in_home("libfoo")) -rm("install", recursive=True) - -try_run(["gprbuild", "-f", "-Plibfoo.gpr", "-p"], "gprbuild-libfoo.txt") -try_run( - [ - "gprinstall", - "-f", - "-Plibfoo.gpr", - "-p", - "--prefix=install", - "--project-subdir=gpr", - ], - "gprinstall.txt", +from SUITE.tutils import gprbuild, gprfor, gprinstall, xcov, xrun + + +# Build libfoo and install it in some prefix, then make the installed project +# available through the GPR_PROJECT_PATH environment variable. +tmp = Wdir("tmp_libfoo") +install_dir = os.path.abspath("install") +libfoo_gpr = gprfor( + prjid="libfoo", + mains=[], + srcdirs=["../libfoo"], + langs=["Ada"], + extra=""" + for Library_Kind use "static"; + for Library_Name use "foo"; + for Library_Dir use "lib"; + """, ) - -os.chdir(in_home("app")) - -try_run(["gprbuild", "-f", "-Pdefault.gpr", "-p"], "gprbuild-app.txt") -try_run(["gnatcov", "run", "obj/main"], "gnatcov-run.txt") +gprbuild(libfoo_gpr) +gprinstall(libfoo_gpr, gargs=[f"--prefix={install_dir}"]) +os.environ["GPR_PROJECT_PATH"] = os.path.join(install_dir, "share", "gpr") +tmp.to_homedir() + +# Now, in another directory (so that we are sure it is the installed libfoo +# that is used), build the main application, then generate a binary trace for +# it. +tmp = Wdir("tmp_app") +app_gpr = gprfor( + prjid="app", mains=["main.adb"], srcdirs=["../app"], deps=["libfoo"] +) +gprbuild(app_gpr) +xrun("./main") # The very goal of this testcase is to compute code coverage for a unit that # belongs to a project installed with gprinstall, so we need to enable the # processing of externally built projects. log_file = "gnatcov-coverage.txt" -log = try_run( +xcov( [ - "gnatcov", "coverage", "--annotate=xcov", "--level=stmt", - "-Pdefault", + "-P", + app_gpr, + "--projects=app", "--externally-built-projects", "main.trace", ], - log_file, + out=log_file, ) thistest.fail_if_no_match( '"gnatcov output" ({})'.format(log_file), @@ -83,7 +67,7 @@ def try_run(cmd, out_file): "\r?\n [^\n]+{}".format( os.path.join( "SB06-033-homonyms", - "libfoo", + "tmp_libfoo", "install", "include", "libfoo", @@ -91,7 +75,7 @@ def try_run(cmd, out_file): ), os.path.join("SB06-033-homonyms", "libfoo", "lib.adb"), ), - log, + contents_of(log_file), ) thistest.result() From 85cb564c754e744c88b4e98e4de6ddad5a5efd23 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 13:26:27 +0000 Subject: [PATCH 1312/1483] OA05-051-sharedobjs*: remove obsolete tests These synthetic tests were added to check that `gnatcov coverage` supported correctly new (binary) trace entry kinds designed to support shared objects correctly. No producer of binary trace files ever had support to generate them, and likely none ever will (shared objects are a native concept, and native targets are not supported anymore with binary traces; support for binary traces will likely soon be removed, too). Remove these tests. --- .../tests/OA05-051-sharedobjs-opt/foo.adb | 4 - .../tests/OA05-051-sharedobjs-opt/test.opt | 2 - .../tests/OA05-051-sharedobjs-opt/test.py | 48 ---- .../tests/OA05-051-sharedobjs/mylib1.gpr | 10 - .../tests/OA05-051-sharedobjs/mylib2.gpr | 10 - .../tests/OA05-051-sharedobjs/myprog.gpr | 11 - .../OA05-051-sharedobjs/src-mylib1/mylib1.adb | 8 - .../OA05-051-sharedobjs/src-mylib1/mylib1.ads | 5 - .../OA05-051-sharedobjs/src-mylib2/mylib2.adb | 8 - .../OA05-051-sharedobjs/src-mylib2/mylib2.ads | 5 - .../OA05-051-sharedobjs/src-myprog/myprog.adb | 13 - testsuite/tests/OA05-051-sharedobjs/test.opt | 2 - testsuite/tests/OA05-051-sharedobjs/test.py | 223 ------------------ 13 files changed, 349 deletions(-) delete mode 100644 testsuite/tests/OA05-051-sharedobjs-opt/foo.adb delete mode 100644 testsuite/tests/OA05-051-sharedobjs-opt/test.opt delete mode 100644 testsuite/tests/OA05-051-sharedobjs-opt/test.py delete mode 100644 testsuite/tests/OA05-051-sharedobjs/mylib1.gpr delete mode 100644 testsuite/tests/OA05-051-sharedobjs/mylib2.gpr delete mode 100644 testsuite/tests/OA05-051-sharedobjs/myprog.gpr delete mode 100644 testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.adb delete mode 100644 testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.ads delete mode 100644 testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.adb delete mode 100644 testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.ads delete mode 100644 testsuite/tests/OA05-051-sharedobjs/src-myprog/myprog.adb delete mode 100644 testsuite/tests/OA05-051-sharedobjs/test.opt delete mode 100644 testsuite/tests/OA05-051-sharedobjs/test.py diff --git a/testsuite/tests/OA05-051-sharedobjs-opt/foo.adb b/testsuite/tests/OA05-051-sharedobjs-opt/foo.adb deleted file mode 100644 index f7b0acefa..000000000 --- a/testsuite/tests/OA05-051-sharedobjs-opt/foo.adb +++ /dev/null @@ -1,4 +0,0 @@ -procedure Foo is -begin - null; -end Foo; diff --git a/testsuite/tests/OA05-051-sharedobjs-opt/test.opt b/testsuite/tests/OA05-051-sharedobjs-opt/test.opt deleted file mode 100644 index b22c473a1..000000000 --- a/testsuite/tests/OA05-051-sharedobjs-opt/test.opt +++ /dev/null @@ -1,2 +0,0 @@ -!bin-traces DEAD Binary traces specific testcase -!linux DEAD Testcase written for Linux diff --git a/testsuite/tests/OA05-051-sharedobjs-opt/test.py b/testsuite/tests/OA05-051-sharedobjs-opt/test.py deleted file mode 100644 index b7b9468e5..000000000 --- a/testsuite/tests/OA05-051-sharedobjs-opt/test.py +++ /dev/null @@ -1,48 +0,0 @@ -"""Test validation of --shared-object command-line option usage.""" - -import re - -from SUITE.cutils import Wdir, indent -from SUITE.tutils import exepath_to, gprbuild, gprfor, thistest, xrun - - -wdir = Wdir("tmp_") - - -gprbuild(gprfor(["foo.adb"], srcdirs="..")) -exe = exepath_to("foo") - -for opt, err_msg in [ - ("none", None), - ("all", None), - ("foo.so", None), - ("foo.so bar.so", None), - ("none all", '"none" and "all" cannot be used at the same time'), - ("all none", '"none" and "all" cannot be used at the same time'), - ("none foo.so", 'cannot provide shared objects with "none"'), - ("foo.so none", 'cannot provide shared objects with "none"'), - ("all foo.so", 'cannot provide shared objects with "all"'), - ("foo.so all", 'cannot provide shared objects with "all"'), -]: - args = [] - for arg in opt.split(): - args.extend(["-L", arg]) - args.append(exe) - p = xrun(args, register_failure=err_msg is None) - if err_msg: - pattern = r".*gnatcov.*: --shared-object\|-L: {}".format( - re.escape(err_msg) - ) - thistest.fail_if( - p.status == 0, - '"{}" was expected to fail, but it did not'.format(" ".join(args)), - ) - thistest.fail_if( - not re.match(pattern, p.out.strip()), - "\nError mesage:" - "\n{}" - "\nDoes not match the expected pattern:" - "\n{}".format(indent(p.out), indent(pattern)), - ) - -thistest.result() diff --git a/testsuite/tests/OA05-051-sharedobjs/mylib1.gpr b/testsuite/tests/OA05-051-sharedobjs/mylib1.gpr deleted file mode 100644 index be784ec15..000000000 --- a/testsuite/tests/OA05-051-sharedobjs/mylib1.gpr +++ /dev/null @@ -1,10 +0,0 @@ -library project Mylib1 is - - for Library_Name use "mylib1"; - for Library_Kind use "relocatable"; - - for Source_Dirs use ("src-mylib1"); - for Library_Dir use "tmp/lib"; - for Object_Dir use "tmp/obj"; - -end Mylib1; diff --git a/testsuite/tests/OA05-051-sharedobjs/mylib2.gpr b/testsuite/tests/OA05-051-sharedobjs/mylib2.gpr deleted file mode 100644 index 99e73cb26..000000000 --- a/testsuite/tests/OA05-051-sharedobjs/mylib2.gpr +++ /dev/null @@ -1,10 +0,0 @@ -library project Mylib2 is - - for Library_Name use "mylib2"; - for Library_Kind use "relocatable"; - - for Source_Dirs use ("src-mylib2"); - for Library_Dir use "tmp/lib"; - for Object_Dir use "tmp/obj"; - -end Mylib2; diff --git a/testsuite/tests/OA05-051-sharedobjs/myprog.gpr b/testsuite/tests/OA05-051-sharedobjs/myprog.gpr deleted file mode 100644 index 98f2c3107..000000000 --- a/testsuite/tests/OA05-051-sharedobjs/myprog.gpr +++ /dev/null @@ -1,11 +0,0 @@ -with "mylib1"; -with "mylib2"; - -project Myprog is - - for Source_Dirs use ("src-myprog"); - for Object_Dir use "tmp/obj"; - for Exec_Dir use "tmp/bin"; - for Main use ("myprog"); - -end Myprog; diff --git a/testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.adb b/testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.adb deleted file mode 100644 index e418498f5..000000000 --- a/testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.adb +++ /dev/null @@ -1,8 +0,0 @@ -package body Mylib1 is - - function F (I : Integer) return Integer is - begin - return I / 2; - end F; - -end Mylib1; diff --git a/testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.ads b/testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.ads deleted file mode 100644 index 070e481d5..000000000 --- a/testsuite/tests/OA05-051-sharedobjs/src-mylib1/mylib1.ads +++ /dev/null @@ -1,5 +0,0 @@ -package Mylib1 is - - function F (I : Integer) return Integer; - -end Mylib1; diff --git a/testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.adb b/testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.adb deleted file mode 100644 index fa3cc6cfd..000000000 --- a/testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.adb +++ /dev/null @@ -1,8 +0,0 @@ -package body Mylib2 is - - function F (I : Integer) return Integer is - begin - return ((I / 3) + 1) * 2; - end F; - -end Mylib2; diff --git a/testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.ads b/testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.ads deleted file mode 100644 index 68fc9bb85..000000000 --- a/testsuite/tests/OA05-051-sharedobjs/src-mylib2/mylib2.ads +++ /dev/null @@ -1,5 +0,0 @@ -package Mylib2 is - - function F (I : Integer) return Integer; - -end Mylib2; diff --git a/testsuite/tests/OA05-051-sharedobjs/src-myprog/myprog.adb b/testsuite/tests/OA05-051-sharedobjs/src-myprog/myprog.adb deleted file mode 100644 index dd00a9422..000000000 --- a/testsuite/tests/OA05-051-sharedobjs/src-myprog/myprog.adb +++ /dev/null @@ -1,13 +0,0 @@ -with Ada.Text_IO; use Ada.Text_IO; - -with GNAT.OS_Lib; use GNAT.OS_Lib; - -with Mylib1; -with Mylib2; - -procedure Myprog is -begin - Put_Line ("Hello, world!"); - Put_Line ("-> " & Natural'Image (Mylib1.F (1))); - Put_Line ("-> " & Natural'Image (Mylib2.F (2))); -end Myprog; diff --git a/testsuite/tests/OA05-051-sharedobjs/test.opt b/testsuite/tests/OA05-051-sharedobjs/test.opt deleted file mode 100644 index b22c473a1..000000000 --- a/testsuite/tests/OA05-051-sharedobjs/test.opt +++ /dev/null @@ -1,2 +0,0 @@ -!bin-traces DEAD Binary traces specific testcase -!linux DEAD Testcase written for Linux diff --git a/testsuite/tests/OA05-051-sharedobjs/test.py b/testsuite/tests/OA05-051-sharedobjs/test.py deleted file mode 100644 index f79fb3eaf..000000000 --- a/testsuite/tests/OA05-051-sharedobjs/test.py +++ /dev/null @@ -1,223 +0,0 @@ -""" -This peculiar testcase attemps to test shared objects support in source -coverage in "gnatcov" without the corresponding handling in trace producers. - -In order to do this, it crafts multiple "artificial" trace files with various -trace entries and checks that "gnatcov coverage" produces the reports we expect -for each trace file. -""" - -import os.path -import struct -import subprocess - -from e3.fs import mkdir, rm - -from SUITE.cutils import lines_of -from SUITE.tutils import gprbuild, thistest, xcov - -from SUITE.tracelib import ( - TraceEntry, - TraceSpecial, - TraceFile, - TraceOp, - TraceKind, - create_exec_infos, - create_trace_header, -) - - -# Clean artifaacts from previous runs -if os.path.exists("tmp"): - rm("tmp", recursive=True) -mkdir("tmp") - - -def in_tmp(*elts): - return os.path.join("tmp", *elts) - - -# Build the program along with the shared libraries. Since we build with shared -# libraries, set LIBRARY_TYPE accordingly so that the implict with of -# gnatcov_rts_full works fine. -gprbuild("myprog", gargs=["-XLIBRARY_TYPE=relocatable"]) -myprog_filename = in_tmp("bin", "myprog") - - -# And now create a set of traces we'll use to test "gnatcov coverage" - - -class Symbol(object): - def __init__(self, addr, size): - self.addr = addr - self.size = size - - @property - def first(self): - return self.addr - - @property - def last(self): - return self.addr + self.size - 1 - - -def get_symbol(filename, symbol): - for line in ( - subprocess.check_output(["nm", "-S", filename]) - .decode("utf-8") - .splitlines() - ): - if line.endswith(symbol): - addr, size, _ = line.split(None, 2) - return Symbol(int(addr, 16), int(size, 16)) - raise ValueError("Could not find symbol {} in {}".format(symbol, filename)) - - -ELFHeader = struct.Struct("<16s" "H" "H") # e_ident # e_type # e_machine -EI_CLASS = 4 -ELFCLASS32 = 1 -ELFCLASS64 = 2 - -EI_DATA = 5 -ELFDATA2LSB = 1 -ELFDATA2MSB = 2 - -# Get architecture properties from the ELF we just built -with open(myprog_filename, "rb") as f: - hdr = ELFHeader.unpack(f.read(ELFHeader.size)) - e_ident = hdr[0] - e_type = hdr[1] - e_machine = hdr[2] - - bits = {ELFCLASS32: 32, ELFCLASS64: 64}[e_ident[EI_CLASS]] - big_endian = e_ident[EI_DATA] == ELFDATA2MSB - machine = ( - ((e_machine & 0xFF) << 8) | (e_machine >> 8) - if big_endian - else e_machine - ) - -so_load_addr = 0xCCFF0000 - -trace_file_info = create_exec_infos(myprog_filename) - -libnames = ("mylib1", "mylib2") -libfiles = { - libname: in_tmp("lib", "lib{}.so".format(libname)) for libname in libnames -} -syms = { - libname: get_symbol(libfile, "{}__f".format(libname)) - for libname, libfile in libfiles.items() -} - -load_events = { - libname: TraceEntry( - bits, - so_load_addr, - TraceSpecial.LoadSharedObject, - TraceOp.Special, - create_exec_infos(libfiles[libname], code_size=sym.last + 1), - ) - for libname, sym in syms.items() -} -unload_event = TraceEntry( - bits, so_load_addr, TraceSpecial.UnloadSharedObject, TraceOp.Special -) - - -def write_traces(trace_filename, executed_libs): - entries = [] - for libname in libnames: - entries.append(load_events[libname]) - if libname in executed_libs: - sym = syms[libname] - entries.append( - TraceEntry( - bits, so_load_addr + sym.addr, sym.size, TraceOp.Block - ) - ) - entries.append(unload_event) - - tf = TraceFile( - create_trace_header(TraceKind.Info, bits // 8, big_endian, machine), - trace_file_info, - create_trace_header(TraceKind.Flat, bits // 8, big_endian, machine), - entries, - ) - - with open(trace_filename, "wb") as f: - tf.write(f) - - -for trace_filename, executed_libs in [ - ("myprog_0.trace", []), - ("myprog_1.trace", ["mylib1"]), - ("myprog_2.trace", ["mylib2"]), - ("myprog_12.trace", ["mylib1", "mylib2"]), -]: - write_traces(in_tmp(trace_filename), executed_libs) - - -# Traces are ready: let's see how coverage goes! - - -def cov_report_summary(output_dir): - summary = [] - for cov_file in os.listdir(output_dir): - cov_set = set() - cov_filepath = os.path.join(output_dir, cov_file) - assert cov_file.endswith(".xcov") - cov_file = cov_file[:-5] - for line in lines_of(cov_filepath): - try: - prefix, _ = line.split(":", 1) - _, prefix = prefix.rsplit(" ", 1) - except ValueError: - continue - if prefix in "+-": - cov_set.add(prefix) - summary.append((cov_file, "".join(sorted(cov_set)))) - return sorted(summary) - - -def format_summary(summary, indent=""): - return "\n".join( - "{}{}: {}".format(indent, cov_file, cov_set) - for cov_file, cov_set in summary - ) - - -expectations = { - "0": [("mylib1.adb", "-"), ("mylib2.adb", "-"), ("myprog.adb", "-")], - "1": [("mylib1.adb", "+"), ("mylib2.adb", "-"), ("myprog.adb", "-")], - "2": [("mylib1.adb", "-"), ("mylib2.adb", "+"), ("myprog.adb", "-")], - "12": [("mylib1.adb", "+"), ("mylib2.adb", "+"), ("myprog.adb", "-")], -} - -for tag, exp in expectations.items(): - output_dir = in_tmp("report-{}".format(tag)) - if os.path.exists(in_tmp(output_dir)): - rm(output_dir, recursive=True) - mkdir(output_dir) - - xcov( - [ - "coverage", - "-Pmyprog", - "--level=stmt", - "--annotate=xcov", - "--output-dir", - output_dir, - in_tmp("myprog_{}.trace".format(tag)), - ] - ) - summary = cov_report_summary(output_dir) - thistest.fail_if( - summary != exp, - "Expected the following coverage report:\n" - "{}\n" - "But got the following one instead:\n" - "{}".format(format_summary(exp, " "), format_summary(summary, " ")), - ) - -thistest.result() From 133c68424699024ac6c396b1b6a94dbd87826ed2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 12:43:51 +0000 Subject: [PATCH 1313/1483] M625-040-slow_on_windows: remove obsolete testcase The point of this testcasae was to compare its execution time from one config to another, not really to test a feature/bug. It was for a config that no longer exists (native Windows), so remove it. --- .../tests/M625-040-slow_on_windows/p.adb | 16 ------ .../tests/M625-040-slow_on_windows/test.opt | 2 - .../tests/M625-040-slow_on_windows/test.py | 54 ------------------- 3 files changed, 72 deletions(-) delete mode 100644 testsuite/tests/M625-040-slow_on_windows/p.adb delete mode 100644 testsuite/tests/M625-040-slow_on_windows/test.opt delete mode 100644 testsuite/tests/M625-040-slow_on_windows/test.py diff --git a/testsuite/tests/M625-040-slow_on_windows/p.adb b/testsuite/tests/M625-040-slow_on_windows/p.adb deleted file mode 100644 index c46cc9260..000000000 --- a/testsuite/tests/M625-040-slow_on_windows/p.adb +++ /dev/null @@ -1,16 +0,0 @@ - -procedure P is - X : Integer := 0; - pragma Volatile (X); - - N_Increments : Integer := 5000; - pragma Volatile (N_increments); - -begin - for I in 1 .. N_Increments loop - X := X + 1; - end loop; - if X /= N_Increments then - raise Program_Error; - end if; -end; diff --git a/testsuite/tests/M625-040-slow_on_windows/test.opt b/testsuite/tests/M625-040-slow_on_windows/test.opt deleted file mode 100644 index 38cc28767..000000000 --- a/testsuite/tests/M625-040-slow_on_windows/test.opt +++ /dev/null @@ -1,2 +0,0 @@ --- Test is there to allow manual investigation of timing issues -ALL DEAD test meant to facilitate manual timing investigation diff --git a/testsuite/tests/M625-040-slow_on_windows/test.py b/testsuite/tests/M625-040-slow_on_windows/test.py deleted file mode 100644 index 5bb4c9501..000000000 --- a/testsuite/tests/M625-040-slow_on_windows/test.py +++ /dev/null @@ -1,54 +0,0 @@ -import cProfile -import pstats -import time - -from SUITE.context import thistest -from SUITE.cutils import Wdir -from SUITE.tutils import exename_for, gprbuild, gprfor, xrun - - -Wdir("tmp_") -gpr = gprfor(srcdirs=[".."], mains=["p.adb"]) - - -def run(action, repeat, tag): - start = time.clock() - for _ in range(repeat): - action() - end = time.clock() - print("%s: %2.5f" % (tag, end - start)) - - -def eval_gprbuild(): - run(action=lambda: gprbuild(gpr), repeat=50, tag="gprbuild") - - -def eval_xrun(): - run(action=lambda: xrun(exename_for("p")), repeat=50, tag="xrun") - - -def profile(what): - profiler = cProfile.Profile() - profiler.run("eval_%s()" % what) - - ps = pstats.Stats(profiler) - ps.strip_dirs() - ps.sort_stats("time") - - print("===================") - print("== %s ==" % what) - - print("-- profiling stats --") - ps.print_stats() - - print("-- callers --") - ps.print_callers() - - print("-- callees --") - ps.print_callees() - - -profile("gprbuild") -profile("xrun") - -thistest.result() From b2659bfbc035d746fe699835b5df702287f63d50 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 12:41:28 +0000 Subject: [PATCH 1314/1483] M531-035-3264-ld_preload: remove Valgrind-specific testcase --- .../tests/M531-035-3264-ld_preload/sls.c | 8 ----- .../tests/M531-035-3264-ld_preload/test.opt | 2 -- .../tests/M531-035-3264-ld_preload/test.py | 29 ------------------- 3 files changed, 39 deletions(-) delete mode 100644 testsuite/tests/M531-035-3264-ld_preload/sls.c delete mode 100644 testsuite/tests/M531-035-3264-ld_preload/test.opt delete mode 100644 testsuite/tests/M531-035-3264-ld_preload/test.py diff --git a/testsuite/tests/M531-035-3264-ld_preload/sls.c b/testsuite/tests/M531-035-3264-ld_preload/sls.c deleted file mode 100644 index c5512d4bc..000000000 --- a/testsuite/tests/M531-035-3264-ld_preload/sls.c +++ /dev/null @@ -1,8 +0,0 @@ -#include - -int -main () -{ - system ("ls"); - return 0; -} diff --git a/testsuite/tests/M531-035-3264-ld_preload/test.opt b/testsuite/tests/M531-035-3264-ld_preload/test.opt deleted file mode 100644 index 7810bf39c..000000000 --- a/testsuite/tests/M531-035-3264-ld_preload/test.opt +++ /dev/null @@ -1,2 +0,0 @@ -!x86-linux,!x86_64-linux DEAD test behavior on program using "system" -!bin-traces DEAD Binary traces specific testcase diff --git a/testsuite/tests/M531-035-3264-ld_preload/test.py b/testsuite/tests/M531-035-3264-ld_preload/test.py deleted file mode 100644 index fd54d91a7..000000000 --- a/testsuite/tests/M531-035-3264-ld_preload/test.py +++ /dev/null @@ -1,29 +0,0 @@ -import re - -from SUITE.context import thistest -from SUITE.cutils import Wdir -from SUITE.tutils import exepath_to, gprbuild, gprfor, xrun - -Wdir("tmp_") - -# Point of this test is to check that the execution of a program using the -# "system" function works fine, without triggering LD_PRELOAD warning from -# valgrind when this happens to be our underlying execution engine. - -# We build and check the output of a program doing system("ls") - -gprbuild(gprfor(mains=["sls.c"], srcdirs="..")) - -p = xrun(exepath_to("sls")) - -thistest.fail_if( - re.search(pattern="LD_PRELOAD", string=p.out), - "spurious occurrence of LD_PRELOAD in the gnatcov run output", -) - -thistest.fail_if( - not re.search(pattern="gen.gpr", string=p.out), - "missing expected nls.c from the program output", -) - -thistest.result() From eef5e9a77a79f5aed028c6252f8ad73a94d1a74c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 21 Jul 2025 14:42:12 +0000 Subject: [PATCH 1315/1483] R521-002-profile-arcs: remove obsolete test `-fprofile-arcs` is not supported for any cross target, so it is impossible to use it in configurations where binary traces are available. Thus, remove this testcase. --- .../tests/R521-002-profile-arcs/main.adb | 8 ---- .../tests/R521-002-profile-arcs/test.opt | 4 -- testsuite/tests/R521-002-profile-arcs/test.py | 44 ------------------- testsuite/tests/R521-002-profile-arcs/util.c | 7 --- 4 files changed, 63 deletions(-) delete mode 100644 testsuite/tests/R521-002-profile-arcs/main.adb delete mode 100644 testsuite/tests/R521-002-profile-arcs/test.opt delete mode 100644 testsuite/tests/R521-002-profile-arcs/test.py delete mode 100644 testsuite/tests/R521-002-profile-arcs/util.c diff --git a/testsuite/tests/R521-002-profile-arcs/main.adb b/testsuite/tests/R521-002-profile-arcs/main.adb deleted file mode 100644 index 1dd86779e..000000000 --- a/testsuite/tests/R521-002-profile-arcs/main.adb +++ /dev/null @@ -1,8 +0,0 @@ -with Ada.Text_IO; use Ada.Text_IO; - -procedure Main is - function Compute return Integer; - pragma Import (C, Compute); -begin - Put_Line ("Hello, world!" & Integer'Image (Compute)); -end Main; diff --git a/testsuite/tests/R521-002-profile-arcs/test.opt b/testsuite/tests/R521-002-profile-arcs/test.opt deleted file mode 100644 index a8ec33335..000000000 --- a/testsuite/tests/R521-002-profile-arcs/test.opt +++ /dev/null @@ -1,4 +0,0 @@ -7.0.2 DEAD Test relies on a compiler change introduced on 2018-06, not in 7.0.2 -!native DEAD Test relies on a working gcov setup, which we only have with native toolchains -!bin-traces DEAD Test makes sense only with compiler SCOs -5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 diff --git a/testsuite/tests/R521-002-profile-arcs/test.py b/testsuite/tests/R521-002-profile-arcs/test.py deleted file mode 100644 index 8fb2aaacf..000000000 --- a/testsuite/tests/R521-002-profile-arcs/test.py +++ /dev/null @@ -1,44 +0,0 @@ -import re - -from SUITE.cutils import Wdir, lines_of -from SUITE.tutils import ( - exepath_to, - gprfor, - gprbuild, - thistest, - tracename_for, - xcov, - xrun, -) - - -wd = Wdir("tmp_") -main = exepath_to("main") -main_trace = tracename_for("main") - -gpr = gprfor(["main.adb"], srcdirs="..", langs=("Ada", "C")) -gprbuild( - gpr, extracargs="-fprofile-arcs", largs="-fprofile-arcs -ftest-coverage" -) - -xrun(main) -xcov( - ["coverage", "-P", gpr, "-cstmt+decision", "-axml", main_trace], - out="coverage.log", -) - -warning_template = ( - r"warning: .*{}: unit compiled with instrumentation" r" \(-fprofile-arcs\)" -) - -for unit in ("main.ali", "util.c.gli"): - thistest.fail_if( - not any( - re.match(warning_template.format(re.escape(unit)), line) - for line in lines_of("coverage.log") - ), - "Warning about -fprofile-arcs for {} not found in output of" - ' "gnatcov coverage"'.format(unit), - ) - -thistest.result() diff --git a/testsuite/tests/R521-002-profile-arcs/util.c b/testsuite/tests/R521-002-profile-arcs/util.c deleted file mode 100644 index add85606c..000000000 --- a/testsuite/tests/R521-002-profile-arcs/util.c +++ /dev/null @@ -1,7 +0,0 @@ -extern int compute (void); - -int -compute (void) -{ - return 1; -} From 273949102a39a46c84b398153aed66d93a2756ee Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 22 Jul 2025 09:13:02 +0000 Subject: [PATCH 1316/1483] R507-014-trailing-byte-insn: adapt to work in src-traces mode This checks that `gnatcov coverage` correctly handles blocks (in binary traces) whose size is exactly one byte. Now that binary traces support no longer covers native targets (x86* architectures), there is no supported architecture (AArch64, ARM, Leon3, PowerPC) that has 1-byte long instructions, so this is a case we cannot hit anymore in practice. To still be able to check that binary trace handling code is correct, synthetize traces instead, so that we can still run this testcase on x86_64-linux. --- .../R507-014-trailing-byte-insn/test.opt | 1 - .../tests/R507-014-trailing-byte-insn/test.py | 120 ++++++++++++------ 2 files changed, 82 insertions(+), 39 deletions(-) diff --git a/testsuite/tests/R507-014-trailing-byte-insn/test.opt b/testsuite/tests/R507-014-trailing-byte-insn/test.opt index 2a96f27e2..1432b0f0b 100644 --- a/testsuite/tests/R507-014-trailing-byte-insn/test.opt +++ b/testsuite/tests/R507-014-trailing-byte-insn/test.opt @@ -1,3 +1,2 @@ 5.04a1 DEAD Requires assembly features not in 5.04a1 -!bin-traces DEAD Binary traces specific testcase !x86_64-linux DEAD Contains assembly code for x86_64-linux diff --git a/testsuite/tests/R507-014-trailing-byte-insn/test.py b/testsuite/tests/R507-014-trailing-byte-insn/test.py index e2f2324a7..247082932 100644 --- a/testsuite/tests/R507-014-trailing-byte-insn/test.py +++ b/testsuite/tests/R507-014-trailing-byte-insn/test.py @@ -1,14 +1,25 @@ -import re +""" +Check that gnatcov produces expected assembly coverage reports for single-byte +instructions covered by a single-byte trace entry. +""" from SUITE.context import thistest -from SUITE.cutils import Wdir, contents_of, indent +from SUITE.cutils import Wdir, contents_of +from SUITE.tracelib import ( + TraceEntry, + TraceFile, + TraceOp, + TraceKind, + create_exec_infos, + create_trace_header, +) from SUITE.tutils import ( + do, exepath_to, gprbuild, gprfor, tracename_for, xcov, - xrun, ) @@ -16,57 +27,90 @@ main = exepath_to("main") main_trace = tracename_for("main") +# Build the 'main' executable gpr = gprfor(["main.c"], srcdirs="..", langs=("C", "Asm")) gprbuild(gpr) -xrun(main) +# Get the address of the 'f' symbol in it +for line in do(["nm", main]).splitlines(): + parts = line.split() + name = parts[-1] + if name == "f": + f_addr = int(parts[0], 16) + break +else: + thistest.failed("Cannot find symbol 'f' in executable 'main'") + +# Create a dummy binary trace from it, including a trace block that covers only +# the 1-byte trailing "ret" instruction. +EM_X86_64 = 62 +bits = 64 +pc_size = bits // 8 +tf = TraceFile( + first_header=create_trace_header( + TraceKind.Info, pc_size, big_endian=False, machine=EM_X86_64 + ), + infos=create_exec_infos(main), + second_header=create_trace_header( + TraceKind.Flat, pc_size, big_endian=False, machine=EM_X86_64 + ), + entries=[ + TraceEntry(bits, f_addr + start_off, end_off - start_off, op) + for start_off, end_off, op in [ + (0x0, 0x4, TraceOp.Block | TraceOp.Br1), + (0x4, 0x1C, TraceOp.Block | TraceOp.Br1), + (0x1C, 0x1E, TraceOp.Block), + (0x20, 0x21, TraceOp.Block), + ] + ], +) +with open(main_trace, "wb") as f: + tf.write(f) + +# Make sure we get the expected coverage report xcov( ["coverage", "-cbranch", "-aasm", main_trace, "--routines=f"], out="coverage.log", ) +actual_report = contents_of("coverage.log").splitlines() -pattern = """\ + +def fmt(offset): + return hex(f_addr + offset)[2:].rjust(16, "0") + + +expected_report = f"""\ Coverage level: branch -f !: [0-9a-f]+-[0-9a-f]+ -[0-9a-f]+ \\+: 85 ff test %edi,%edi -[0-9a-f]+ v: 7e 1a jle 0x[0-9a-f]+ -[0-9a-f]+ \\+: 31 c9 xor %ecx,%ecx -[0-9a-f]+ \\+: 31 c0 xor %eax,%eax -[0-9a-f]+ \\+: 0f 1f 84 00 00 00 00 00 nopl 0x0\\(%rax,%rax,1\\) -[0-9a-f]+ \\+: 89 ca mov %ecx,%edx -[0-9a-f]+ \\+: 21 fa and %edi,%edx -[0-9a-f]+ \\+: 01 d0 add %edx,%eax -[0-9a-f]+ \\+: ff c1 inc %ecx -[0-9a-f]+ \\+: 39 cf cmp %ecx,%edi -[0-9a-f]+ v: 75 f4 jne 0x[0-9a-f]+ -[0-9a-f]+ \\+: eb 02 jmp 0x[0-9a-f]+ -[0-9a-f]+ -: 31 c0 xor %eax,%eax -[0-9a-f]+ \\+: c3 ret +f !: {fmt(0)}-{fmt(0x20)} +{fmt(0x00)} +: 85 ff test %edi,%edi +{fmt(0x02)} v: 7e 1a jle {hex(f_addr + 0x1e)} +{fmt(0x04)} +: 31 c9 xor %ecx,%ecx +{fmt(0x06)} +: 31 c0 xor %eax,%eax +{fmt(0x08)} +: 0f 1f 84 00 00 00 00 00 nopl 0x0(%rax,%rax,1) +{fmt(0x10)} +: 89 ca mov %ecx,%edx +{fmt(0x12)} +: 21 fa and %edi,%edx +{fmt(0x14)} +: 01 d0 add %edx,%eax +{fmt(0x16)} +: ff c1 inc %ecx +{fmt(0x18)} +: 39 cf cmp %ecx,%edi +{fmt(0x1a)} v: 75 f4 jne {hex(f_addr + 0x10)} +{fmt(0x1c)} +: eb 02 jmp {hex(f_addr + 0x20)} +{fmt(0x1e)} -: 31 c0 xor %eax,%eax +{fmt(0x20)} +: c3 ret 14 instructions analyzed: 13 covered 1 not executed 2 conditional branches analyzed: 0 fully covered 2 partially covered - 0 not executed""" + 0 not executed +""" +with open("expected.txt", "w") as f: + f.write(expected_report) -pattern_lines = pattern.splitlines() -log_lines = contents_of("coverage.log").splitlines() - -thistest.fail_if( - len(pattern_lines) != len(log_lines), - 'The output of "gnatcov coverage" is {} lines long, {} expected'.format( - len(log_lines), len(pattern_lines) - ), +thistest.fail_if_diff( + baseline_file="expected.txt", + actual_file="coverage.log", + failure_message="unexpected coverage report", ) -for pat, log in zip(pattern_lines, log_lines): - thistest.fail_if( - not re.match(pat, log), - 'Could not match "gnatcov coverage" output:\n' - "{}\n" - "against the expected pattern:\n" - "{}\n".format(indent(log), indent(pat)), - ) - thistest.result() From 5188687654109febf58a57bc30686990f7be3016 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 22 Jul 2025 12:18:17 +0000 Subject: [PATCH 1317/1483] instr-cov/logging: avoid 'gnatcov instrument' warning with Ravenscar RTS --- testsuite/tests/instr-cov/logging/test.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/testsuite/tests/instr-cov/logging/test.py b/testsuite/tests/instr-cov/logging/test.py index 8845ed086..49fccb8d1 100644 --- a/testsuite/tests/instr-cov/logging/test.py +++ b/testsuite/tests/instr-cov/logging/test.py @@ -127,6 +127,12 @@ def flush_files(): f"--projects={subproject}", "--log=instrument_clean_objdirs", "--log=instrument_sources", + # Some automatic dump triggers (ravenscar-task-termination) are not + # available for all languages: instrumenting a C/C++ project with + # the default dump trigger in some configurations yields a warning. + # Explicitly ask for a dump trigger that is always supported to + # avoid this warning. + "--dump-trigger=main-end", ], out=log, ) From ef8fbaee08febfc70f424b0c16ed99f670708baf Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 22 Jul 2025 19:15:30 +0000 Subject: [PATCH 1318/1483] Ada2022/aggregates/containers: fix illegal/incorrect Ada sources --- .../tests/Ada2022/aggregates/containers/src/pkg.adb | 9 ++++++--- .../Ada2022/aggregates/containers/src/test_empty.adb | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb index d923cb57c..233ebf474 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb +++ b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb @@ -11,9 +11,12 @@ package body Pkg is if Input = [] then -- # empty_aggr_guard return []; -- # empty_aggr_st elsif Input.Length = 1 then -- # single_elt_guard - return -- # single_elt_st - (declare Elt : Integer renames Input.First_Element; -- # single_elt_st - begin [(If Elt > 0 then Elt else Elt)]); -- # single_elt_dc + declare + Elt : constant Integer := Input.First_Element; -- # single_elt_st + begin + return [(if Elt > 0 then Elt else Elt) => -- # single_elt_dc + (if Elt > 0 then Elt else Elt)]; -- # single_elt_dc + end; else return [for Elt of Input use -- # multi_elt_st (if Elt > 0 then Elt else Elt) => -- # multi_elt_dc diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb index 39c73ae6a..100c9db9e 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb @@ -3,11 +3,11 @@ pragma Ada_2022; with Pkg; use Pkg; with Check; -procedure Test_Single is +procedure Test_Empty is use Int_Sets; begin Check ([]); -end Test_Single; +end Test_Empty; --# pkg.adb -- From 4d09d9e5e7b6902859b8adadb928328745aed123 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 22 Jul 2025 19:16:15 +0000 Subject: [PATCH 1319/1483] Ada2022/aggregates/containers: update XFAIL message --- testsuite/tests/Ada2022/aggregates/containers/test.opt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/Ada2022/aggregates/containers/test.opt b/testsuite/tests/Ada2022/aggregates/containers/test.opt index 9009419d6..acbe4e495 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/test.opt +++ b/testsuite/tests/Ada2022/aggregates/containers/test.opt @@ -1,2 +1,2 @@ RTS_ZFP DEAD Test instantiates containers -all XFAIL Support for [use key_expression] not yet available in LAL (libadalang#1062) +all XFAIL Compiler crash (eng/toolchain/gnat#1516) From ad8ea53404a02a4da9ec9198acbdba4264f3c83f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 22 Jul 2025 14:56:10 +0000 Subject: [PATCH 1320/1483] integrated_instr_cross/basic_C: minor refactoring --- testsuite/tests/integrated_instr_cross/basic_C/test.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/testsuite/tests/integrated_instr_cross/basic_C/test.py b/testsuite/tests/integrated_instr_cross/basic_C/test.py index 560ac9dfc..237f5f095 100644 --- a/testsuite/tests/integrated_instr_cross/basic_C/test.py +++ b/testsuite/tests/integrated_instr_cross/basic_C/test.py @@ -31,8 +31,6 @@ os.path.join(gcvrt_prefix, "share", "gpr"), ) -cwd = os.getcwd() - cp("../main.c", ".") # Build the C BSP @@ -74,7 +72,7 @@ [ "setup-integration", "--level=stmt+mcdc", - f"--files={os.path.join(cwd, 'main.c')}", + f"--files={os.path.abspath('main.c')}", f"--compilers={os.path.basename(compiler)}", f"--output-dir={gnatcov_artifact_dir}", ] From 8ccb841c569bb74051cece7e962e93a6cf59caf1 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 22 Jul 2025 15:14:41 +0000 Subject: [PATCH 1321/1483] integrated_instr_cross/basic_C: adjust test.opt This is test for bareboard targets: do not run it for native/cross configs. Also set XFAIL for leon3-elf for the time being, while the linker failure is sorted out. --- testsuite/tests/integrated_instr_cross/basic_C/test.opt | 3 ++- testsuite/tests/integrated_instr_cross/basic_C/test.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/integrated_instr_cross/basic_C/test.opt b/testsuite/tests/integrated_instr_cross/basic_C/test.opt index 1bcfeb91b..eeb5746be 100644 --- a/testsuite/tests/integrated_instr_cross/basic_C/test.opt +++ b/testsuite/tests/integrated_instr_cross/basic_C/test.opt @@ -1 +1,2 @@ -!ppc-elf XFAIL there are various issues with the other BSPs +!bareboard DEAD This test relies on examples specific to bareboard targets +leon3-elf XFAIL Linker cannot find fwrite (to be investigated) diff --git a/testsuite/tests/integrated_instr_cross/basic_C/test.py b/testsuite/tests/integrated_instr_cross/basic_C/test.py index 237f5f095..6b6562eb7 100644 --- a/testsuite/tests/integrated_instr_cross/basic_C/test.py +++ b/testsuite/tests/integrated_instr_cross/basic_C/test.py @@ -1,5 +1,5 @@ """ -Simple sanity check test for integrated instrumentation for cross targets +Simple sanity check test for integrated instrumentation for bareboard targets. """ import os From bb0d568c703ae2610552dd50df16450c82684ffd Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 22 Jul 2025 14:28:52 +0000 Subject: [PATCH 1322/1483] TC03-012-objcov-line-state: retarget for AArch64 ELF This testcase for object coverage (binary traces) is hardwired for x86_64-linux. Since we no longer support binary traces for that platform, this test never runs in practice. Retarget it for AArch64 ELF so that we can run it again. The original problem (instruction reported as covered even when not executed) reproduces if the fix in `coverage`-object.adb is reverted. --- .../tests/TC03-012-objcov-line-state/fact.c | 10 + .../tests/TC03-012-objcov-line-state/fact.s | 206 ++++++++++++ .../tests/TC03-012-objcov-line-state/main.c | 15 +- .../tests/TC03-012-objcov-line-state/main.s | 304 ------------------ .../tests/TC03-012-objcov-line-state/test.opt | 3 +- .../tests/TC03-012-objcov-line-state/test.py | 44 ++- 6 files changed, 252 insertions(+), 330 deletions(-) create mode 100644 testsuite/tests/TC03-012-objcov-line-state/fact.c create mode 100644 testsuite/tests/TC03-012-objcov-line-state/fact.s delete mode 100644 testsuite/tests/TC03-012-objcov-line-state/main.s diff --git a/testsuite/tests/TC03-012-objcov-line-state/fact.c b/testsuite/tests/TC03-012-objcov-line-state/fact.c new file mode 100644 index 000000000..c1df045dd --- /dev/null +++ b/testsuite/tests/TC03-012-objcov-line-state/fact.c @@ -0,0 +1,10 @@ +int +fact (int n) +{ + if (n == 0) + return 1; + else if (n < 2) + return 1; + else + return n * fact (n - 1); +} diff --git a/testsuite/tests/TC03-012-objcov-line-state/fact.s b/testsuite/tests/TC03-012-objcov-line-state/fact.s new file mode 100644 index 000000000..c44665a57 --- /dev/null +++ b/testsuite/tests/TC03-012-objcov-line-state/fact.s @@ -0,0 +1,206 @@ + .arch armv8-a+crc + .file "fact.c" + .text +.Ltext0: + .cfi_sections .debug_frame + .align 2 + .global fact + .type fact, %function +fact: +.LFB0: + .file 1 "fact.c" + .loc 1 3 1 + .cfi_startproc + stp x29, x30, [sp, -32]! + .cfi_def_cfa_offset 32 + .cfi_offset 29, -32 + .cfi_offset 30, -24 + mov x29, sp + str w0, [sp, 28] + .loc 1 4 9 + ldr w0, [sp, 28] + cmp w0, 0 + bne .L2 +# The following instruction (mov w0, 1) was manually inserted so that we have +# an instruction that is assigned the same sloc as the conditional branch above +# (bne, line 4), but that will not be executed even though the branch is +# executed. Because of this, the coverage report is expected to report line 4 +# as partially covered (it used to wrongly report it as fully covered). + mov w0, 1 + .loc 1 5 12 + mov w0, 1 + b .L3 +.L2: + .loc 1 6 14 + ldr w0, [sp, 28] + cmp w0, 1 + bgt .L4 + .loc 1 7 12 + mov w0, 1 + b .L3 +.L4: + .loc 1 9 16 + ldr w0, [sp, 28] + sub w0, w0, #1 + bl fact + mov w1, w0 + .loc 1 9 14 discriminator 1 + ldr w0, [sp, 28] + mul w0, w1, w0 +.L3: + .loc 1 10 1 + nop + ldp x29, x30, [sp], 32 + .cfi_restore 30 + .cfi_restore 29 + .cfi_def_cfa_offset 0 + ret + .cfi_endproc +.LFE0: + .size fact, .-fact +.Letext0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .4byte 0x62 + .2byte 0x5 + .byte 0x1 + .byte 0x8 + .4byte .Ldebug_abbrev0 + .uleb128 0x1 + .4byte .LASF2 + .byte 0x1d + .4byte .LASF0 + .4byte .LASF1 + .8byte .Ltext0 + .8byte .Letext0-.Ltext0 + .4byte .Ldebug_line0 + .uleb128 0x2 + .4byte .LASF3 + .byte 0x1 + .byte 0x2 + .byte 0x1 + .4byte 0x5e + .8byte .LFB0 + .8byte .LFE0-.LFB0 + .uleb128 0x1 + .byte 0x9c + .4byte 0x5e + .uleb128 0x3 + .string "n" + .byte 0x1 + .byte 0x2 + .byte 0xb + .4byte 0x5e + .uleb128 0x2 + .byte 0x91 + .sleb128 -4 + .byte 0 + .uleb128 0x4 + .byte 0x4 + .byte 0x5 + .string "int" + .byte 0 + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .uleb128 0x1 + .uleb128 0x11 + .byte 0x1 + .uleb128 0x25 + .uleb128 0xe + .uleb128 0x13 + .uleb128 0xb + .uleb128 0x3 + .uleb128 0x1f + .uleb128 0x1b + .uleb128 0x1f + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x7 + .uleb128 0x10 + .uleb128 0x17 + .byte 0 + .byte 0 + .uleb128 0x2 + .uleb128 0x2e + .byte 0x1 + .uleb128 0x3f + .uleb128 0x19 + .uleb128 0x3 + .uleb128 0xe + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x39 + .uleb128 0xb + .uleb128 0x27 + .uleb128 0x19 + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x11 + .uleb128 0x1 + .uleb128 0x12 + .uleb128 0x7 + .uleb128 0x40 + .uleb128 0x18 + .uleb128 0x7c + .uleb128 0x19 + .uleb128 0x1 + .uleb128 0x13 + .byte 0 + .byte 0 + .uleb128 0x3 + .uleb128 0x5 + .byte 0 + .uleb128 0x3 + .uleb128 0x8 + .uleb128 0x3a + .uleb128 0xb + .uleb128 0x3b + .uleb128 0xb + .uleb128 0x39 + .uleb128 0xb + .uleb128 0x49 + .uleb128 0x13 + .uleb128 0x2 + .uleb128 0x18 + .byte 0 + .byte 0 + .uleb128 0x4 + .uleb128 0x24 + .byte 0 + .uleb128 0xb + .uleb128 0xb + .uleb128 0x3e + .uleb128 0xb + .uleb128 0x3 + .uleb128 0x8 + .byte 0 + .byte 0 + .byte 0 + .section .debug_aranges,"",@progbits + .4byte 0x2c + .2byte 0x2 + .4byte .Ldebug_info0 + .byte 0x8 + .byte 0 + .2byte 0 + .2byte 0 + .8byte .Ltext0 + .8byte .Letext0-.Ltext0 + .8byte 0 + .8byte 0 + .section .debug_line,"",@progbits +.Ldebug_line0: + .section .debug_str,"MS",@progbits,1 +.LASF3: + .string "fact" +.LASF2: + .string "GNU C17 14.3.1 20250720 (for GNAT Pro 26.0w 20250720) -mcpu=cortex-a53 -mlittle-endian -mabi=lp64 -g -fno-tree-loop-distribute-patterns -fpreserve-control-flow -fpreserve-decisions-generic" + .section .debug_line_str,"MS",@progbits,1 +.LASF0: + .string "fact.c" +.LASF1: + .string ".." + .ident "GCC: (GNU) 14.3.1 20250720 (for GNAT Pro 26.0w 20250720)" diff --git a/testsuite/tests/TC03-012-objcov-line-state/main.c b/testsuite/tests/TC03-012-objcov-line-state/main.c index 6c9ca81b7..bfb3dcc6d 100644 --- a/testsuite/tests/TC03-012-objcov-line-state/main.c +++ b/testsuite/tests/TC03-012-objcov-line-state/main.c @@ -1,16 +1,7 @@ -int -add_n (int a, int b) -{ - int res = b; - for (int x = 0; x < a; x++) - { - res += 1; - } - return res; -} +extern int fact (int n); int -main () +main (void) { - return add_n (0, 0); + return fact (2); } diff --git a/testsuite/tests/TC03-012-objcov-line-state/main.s b/testsuite/tests/TC03-012-objcov-line-state/main.s deleted file mode 100644 index 457b39b09..000000000 --- a/testsuite/tests/TC03-012-objcov-line-state/main.s +++ /dev/null @@ -1,304 +0,0 @@ - .file "main.c" - .text -.Ltext0: - .globl add_n - .type add_n, @function -add_n: -.LFB0: - .file 1 "main.c" - .loc 1 1 24 - .cfi_startproc - pushq %rbp - .cfi_def_cfa_offset 16 - .cfi_offset 6, -16 - movq %rsp, %rbp - .cfi_def_cfa_register 6 - movl %edi, -20(%rbp) - movl %esi, -24(%rbp) - .loc 1 2 7 - movl -24(%rbp), %eax - movl %eax, -4(%rbp) -.LBB2: - .loc 1 3 11 - movl $0, -8(%rbp) - .loc 1 3 3 - jmp .L2 -.L3: - addl $1, -8(%rbp) - .loc 1 4 8 discriminator 3 - addl $1, -4(%rbp) -.L2: - .loc 1 3 20 discriminator 1 - movl -8(%rbp), %eax - cmpl -20(%rbp), %eax - jl .L3 -.LBE2: - .loc 1 6 10 - movl -4(%rbp), %eax - nop - .loc 1 7 1 - popq %rbp - .cfi_def_cfa 7, 8 - ret - .cfi_endproc -.LFE0: - .size add_n, .-add_n - .globl main - .type main, @function -main: -.LFB1: - .loc 1 9 12 - .cfi_startproc - pushq %rbp - .cfi_def_cfa_offset 16 - .cfi_offset 6, -16 - movq %rsp, %rbp - .cfi_def_cfa_register 6 - .loc 1 10 10 - movl $0, %esi - movl $0, %edi - call add_n - .loc 1 11 1 - nop - popq %rbp - .cfi_def_cfa 7, 8 - ret - .cfi_endproc -.LFE1: - .size main, .-main -.Letext0: - .section .debug_info,"",@progbits -.Ldebug_info0: - .long 0xb6 - .value 0x4 - .long .Ldebug_abbrev0 - .byte 0x8 - .uleb128 0x1 - .long .LASF0 - .byte 0xc - .long .LASF1 - .long .LASF2 - .quad .Ltext0 - .quad .Letext0-.Ltext0 - .long .Ldebug_line0 - .uleb128 0x2 - .long .LASF3 - .byte 0x1 - .byte 0x9 - .byte 0x5 - .long 0x4b - .quad .LFB1 - .quad .LFE1-.LFB1 - .uleb128 0x1 - .byte 0x9c - .uleb128 0x3 - .byte 0x4 - .byte 0x5 - .string "int" - .uleb128 0x4 - .long .LASF4 - .byte 0x1 - .byte 0x1 - .byte 0x5 - .long 0x4b - .quad .LFB0 - .quad .LFE0-.LFB0 - .uleb128 0x1 - .byte 0x9c - .uleb128 0x5 - .string "a" - .byte 0x1 - .byte 0x1 - .byte 0xf - .long 0x4b - .uleb128 0x2 - .byte 0x91 - .sleb128 -36 - .uleb128 0x5 - .string "b" - .byte 0x1 - .byte 0x1 - .byte 0x16 - .long 0x4b - .uleb128 0x2 - .byte 0x91 - .sleb128 -40 - .uleb128 0x6 - .string "res" - .byte 0x1 - .byte 0x2 - .byte 0x7 - .long 0x4b - .uleb128 0x2 - .byte 0x91 - .sleb128 -20 - .uleb128 0x7 - .quad .LBB2 - .quad .LBE2-.LBB2 - .uleb128 0x6 - .string "x" - .byte 0x1 - .byte 0x3 - .byte 0xb - .long 0x4b - .uleb128 0x2 - .byte 0x91 - .sleb128 -24 - .byte 0 - .byte 0 - .byte 0 - .section .debug_abbrev,"",@progbits -.Ldebug_abbrev0: - .uleb128 0x1 - .uleb128 0x11 - .byte 0x1 - .uleb128 0x25 - .uleb128 0xe - .uleb128 0x13 - .uleb128 0xb - .uleb128 0x3 - .uleb128 0xe - .uleb128 0x1b - .uleb128 0xe - .uleb128 0x11 - .uleb128 0x1 - .uleb128 0x12 - .uleb128 0x7 - .uleb128 0x10 - .uleb128 0x17 - .byte 0 - .byte 0 - .uleb128 0x2 - .uleb128 0x2e - .byte 0 - .uleb128 0x3f - .uleb128 0x19 - .uleb128 0x3 - .uleb128 0xe - .uleb128 0x3a - .uleb128 0xb - .uleb128 0x3b - .uleb128 0xb - .uleb128 0x39 - .uleb128 0xb - .uleb128 0x49 - .uleb128 0x13 - .uleb128 0x11 - .uleb128 0x1 - .uleb128 0x12 - .uleb128 0x7 - .uleb128 0x40 - .uleb128 0x18 - .uleb128 0x2116 - .uleb128 0x19 - .byte 0 - .byte 0 - .uleb128 0x3 - .uleb128 0x24 - .byte 0 - .uleb128 0xb - .uleb128 0xb - .uleb128 0x3e - .uleb128 0xb - .uleb128 0x3 - .uleb128 0x8 - .byte 0 - .byte 0 - .uleb128 0x4 - .uleb128 0x2e - .byte 0x1 - .uleb128 0x3f - .uleb128 0x19 - .uleb128 0x3 - .uleb128 0xe - .uleb128 0x3a - .uleb128 0xb - .uleb128 0x3b - .uleb128 0xb - .uleb128 0x39 - .uleb128 0xb - .uleb128 0x27 - .uleb128 0x19 - .uleb128 0x49 - .uleb128 0x13 - .uleb128 0x11 - .uleb128 0x1 - .uleb128 0x12 - .uleb128 0x7 - .uleb128 0x40 - .uleb128 0x18 - .uleb128 0x2117 - .uleb128 0x19 - .byte 0 - .byte 0 - .uleb128 0x5 - .uleb128 0x5 - .byte 0 - .uleb128 0x3 - .uleb128 0x8 - .uleb128 0x3a - .uleb128 0xb - .uleb128 0x3b - .uleb128 0xb - .uleb128 0x39 - .uleb128 0xb - .uleb128 0x49 - .uleb128 0x13 - .uleb128 0x2 - .uleb128 0x18 - .byte 0 - .byte 0 - .uleb128 0x6 - .uleb128 0x34 - .byte 0 - .uleb128 0x3 - .uleb128 0x8 - .uleb128 0x3a - .uleb128 0xb - .uleb128 0x3b - .uleb128 0xb - .uleb128 0x39 - .uleb128 0xb - .uleb128 0x49 - .uleb128 0x13 - .uleb128 0x2 - .uleb128 0x18 - .byte 0 - .byte 0 - .uleb128 0x7 - .uleb128 0xb - .byte 0x1 - .uleb128 0x11 - .uleb128 0x1 - .uleb128 0x12 - .uleb128 0x7 - .byte 0 - .byte 0 - .byte 0 - .section .debug_aranges,"",@progbits - .long 0x2c - .value 0x2 - .long .Ldebug_info0 - .byte 0x8 - .byte 0 - .value 0 - .value 0 - .quad .Ltext0 - .quad .Letext0-.Ltext0 - .quad 0 - .quad 0 - .section .debug_line,"",@progbits -.Ldebug_line0: - .section .debug_str,"MS",@progbits,1 -.LASF4: - .string "add_n" -.LASF1: - .string "main.c" -.LASF2: - .string ".." -.LASF3: - .string "main" -.LASF0: - .string "GNU C17 10.2.1 20210111 (for GNAT Pro 22.0w 20210111) -mtune=generic -march=x86-64 -g" - .ident "GCC: (GNU) 10.2.1 20210111 (for GNAT Pro 22.0w 20210111)" - .section .note.GNU-stack,"",@progbits diff --git a/testsuite/tests/TC03-012-objcov-line-state/test.opt b/testsuite/tests/TC03-012-objcov-line-state/test.opt index f5b84ac3c..cffec28fb 100644 --- a/testsuite/tests/TC03-012-objcov-line-state/test.opt +++ b/testsuite/tests/TC03-012-objcov-line-state/test.opt @@ -1,2 +1 @@ -!bin-traces DEAD Binary traces specific testcase -!x86_64-linux DEAD Embeds x86_64 assembly sources for Linux +!aarch64-elf DEAD Embeds x86_64 assembly sources for Linux diff --git a/testsuite/tests/TC03-012-objcov-line-state/test.py b/testsuite/tests/TC03-012-objcov-line-state/test.py index 7f6da16ba..2289101ef 100644 --- a/testsuite/tests/TC03-012-objcov-line-state/test.py +++ b/testsuite/tests/TC03-012-objcov-line-state/test.py @@ -1,35 +1,55 @@ """ -Testcase for TC03-012: Check that line coverage state is correctly computed, -even if some debug information is missing from the executable. +Testcase for TC03-012: check that gnatcov reports as uncovered an instruction +that is not executed, but that follows an executed instruction and has the same +sloc. """ -import os -from e3.os.process import Run +from e3.fs import cp, mkdir from SCOV.minicheck import check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir from SUITE.tutils import ( exepath_to, - exename_for, + gprbuild, gprfor, xcov, xrun, tracename_for, ) -Wdir("tmp") +Wdir("tmp_") -prj = gprfor(srcdirs=[".."], objdir=".", mains=["main.c"], prjid="gen") +# Compile all C sources +original_prj = gprfor( + srcdirs=[".."], + mains=["main.c"], + objdir="obj-original", + prjid="original", + langs=["C"], +) +gprbuild(original_prj, extracargs=["-save-temps"]) -# Compile assembly -Run(["gcc", "-o", exename_for("main"), os.path.join("..", "main.s")]) +# Use our custom assembly source for fact.c +mkdir("src") +cp("../main.c", "src/main.c") +cp("../fact.s", "src/fact.s") +prj = gprfor(srcdirs=["src"], mains=["main.c"], prjid="gen") +gprbuild(prj) -# Run and coverage +# Run and compute the XCOV coverage report xrun(["-cinsn", exepath_to("main")]) xcov(["coverage", "-cinsn", "-axcov", "-Pgen", tracename_for("main")]) -# Check that line 3 is correctly marked as partially covered -check_xcov_reports(".", {"main.c.xcov": {"-": {4}, "!": {3}}}) +# Check that line 4 is correctly marked as partially covered, as it contains +# an uncovered instruction that follows an (always taken) branch (see the +# comment in fact.s). +check_xcov_reports( + "obj", + { + "fact.c.xcov": {"+": {6, 7, 9}, "-": {5}, "!": {4}}, + "main.c.xcov": {"+": {6}}, + }, +) thistest.result() From a00c43cf24c6673e8c052e64cc85ea1dd10e5bff Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 22 Jul 2025 14:32:41 +0000 Subject: [PATCH 1323/1483] branch-cond/IB13-014-const-instances: remove obsolete tests These tests never ran (they are incomplete, have been for 16 years!), and are just representatives of a problem that is specific to binary traces. Binary traces are on their way out, and no customer ever reported them, so just remove these tests. --- .../IB13-014-const-instances/services.adb | 6 ------ .../IB13-014-const-instances/services.ads | 5 ----- .../branch-cond/IB13-014-const-instances/test.opt | 1 - .../branch-cond/IB13-014-const-instances/test.py | 10 ---------- .../IB13-014-const-instances/test_services.adb | 14 -------------- .../branch-cond/IB19-001-precond-false/check.adb | 4 ---- .../branch-cond/IB19-001-precond-false/check.ads | 2 -- .../branch-cond/IB19-001-precond-false/test.opt | 1 - .../branch-cond/IB19-001-precond-false/test.py | 6 ------ 9 files changed, 49 deletions(-) delete mode 100644 testsuite/tests/branch-cond/IB13-014-const-instances/services.adb delete mode 100644 testsuite/tests/branch-cond/IB13-014-const-instances/services.ads delete mode 100644 testsuite/tests/branch-cond/IB13-014-const-instances/test.opt delete mode 100644 testsuite/tests/branch-cond/IB13-014-const-instances/test.py delete mode 100644 testsuite/tests/branch-cond/IB13-014-const-instances/test_services.adb delete mode 100644 testsuite/tests/branch-cond/IB19-001-precond-false/check.adb delete mode 100644 testsuite/tests/branch-cond/IB19-001-precond-false/check.ads delete mode 100644 testsuite/tests/branch-cond/IB19-001-precond-false/test.opt delete mode 100644 testsuite/tests/branch-cond/IB19-001-precond-false/test.py diff --git a/testsuite/tests/branch-cond/IB13-014-const-instances/services.adb b/testsuite/tests/branch-cond/IB13-014-const-instances/services.adb deleted file mode 100644 index 5b8a62fb0..000000000 --- a/testsuite/tests/branch-cond/IB13-014-const-instances/services.adb +++ /dev/null @@ -1,6 +0,0 @@ -package body Services is - function Has_Mid_Precision (N : Number) return Boolean is - begin - return Number'Digits >= 6 and then Number'Digits <= 12; - end; -end; diff --git a/testsuite/tests/branch-cond/IB13-014-const-instances/services.ads b/testsuite/tests/branch-cond/IB13-014-const-instances/services.ads deleted file mode 100644 index ab6d0a5cc..000000000 --- a/testsuite/tests/branch-cond/IB13-014-const-instances/services.ads +++ /dev/null @@ -1,5 +0,0 @@ -generic - type Number is digits <>; -package Services is - function Has_Mid_Precision (N : Number) return Boolean; -end; diff --git a/testsuite/tests/branch-cond/IB13-014-const-instances/test.opt b/testsuite/tests/branch-cond/IB13-014-const-instances/test.opt deleted file mode 100644 index 6843f4505..000000000 --- a/testsuite/tests/branch-cond/IB13-014-const-instances/test.opt +++ /dev/null @@ -1 +0,0 @@ -ALL DEAD !! decisions const in instances IB13-014 diff --git a/testsuite/tests/branch-cond/IB13-014-const-instances/test.py b/testsuite/tests/branch-cond/IB13-014-const-instances/test.py deleted file mode 100644 index 7215f7151..000000000 --- a/testsuite/tests/branch-cond/IB13-014-const-instances/test.py +++ /dev/null @@ -1,10 +0,0 @@ -from SUITE.context import thistest -from SCOV.map import MapChecker - - -MapChecker( - sources=["services.adb", "test_services.adb"], - execs=["test_services"], - alis="obj/services.ali", -).run() -thistest.result() diff --git a/testsuite/tests/branch-cond/IB13-014-const-instances/test_services.adb b/testsuite/tests/branch-cond/IB13-014-const-instances/test_services.adb deleted file mode 100644 index b9b1a1dc5..000000000 --- a/testsuite/tests/branch-cond/IB13-014-const-instances/test_services.adb +++ /dev/null @@ -1,14 +0,0 @@ -with Services; - -procedure Test_Services is - type T1 is digits 1; - package P1 is new Services (Number => T1); - - type T8 is digits 8; - package P8 is new Services (number => T8); - - B1, B8 : Boolean; -begin - B1 := P1.Has_Mid_Precision (1.0); - B8 := P8.Has_Mid_Precision (2.0); -end; diff --git a/testsuite/tests/branch-cond/IB19-001-precond-false/check.adb b/testsuite/tests/branch-cond/IB19-001-precond-false/check.adb deleted file mode 100644 index 979fdb757..000000000 --- a/testsuite/tests/branch-cond/IB19-001-precond-false/check.adb +++ /dev/null @@ -1,4 +0,0 @@ -procedure Check is -begin - null; -end; diff --git a/testsuite/tests/branch-cond/IB19-001-precond-false/check.ads b/testsuite/tests/branch-cond/IB19-001-precond-false/check.ads deleted file mode 100644 index 06c3dd06e..000000000 --- a/testsuite/tests/branch-cond/IB19-001-precond-false/check.ads +++ /dev/null @@ -1,2 +0,0 @@ -procedure Check; -pragma Precondition (False); diff --git a/testsuite/tests/branch-cond/IB19-001-precond-false/test.opt b/testsuite/tests/branch-cond/IB19-001-precond-false/test.opt deleted file mode 100644 index 357adb47e..000000000 --- a/testsuite/tests/branch-cond/IB19-001-precond-false/test.opt +++ /dev/null @@ -1 +0,0 @@ -ALL DEAD !! no branch for condition False IB19-001 diff --git a/testsuite/tests/branch-cond/IB19-001-precond-false/test.py b/testsuite/tests/branch-cond/IB19-001-precond-false/test.py deleted file mode 100644 index db1abbcae..000000000 --- a/testsuite/tests/branch-cond/IB19-001-precond-false/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from SUITE.context import thistest -from SCOV.map import MapChecker - - -MapChecker("check.adb", options="-gnata -save-temps").run() -thistest.result() From c0a2c6a3c4047ace73dbe459a417707a0d660ea1 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 22 Jul 2025 18:38:21 +0000 Subject: [PATCH 1324/1483] OA27-059-separate-consolidation: remove XFAIL and adapt for src-traces --- .../OA27-059-separate-consolidation/test.opt | 1 - .../OA27-059-separate-consolidation/test.py | 31 ++++++++++++++----- 2 files changed, 24 insertions(+), 8 deletions(-) delete mode 100644 testsuite/tests/OA27-059-separate-consolidation/test.opt diff --git a/testsuite/tests/OA27-059-separate-consolidation/test.opt b/testsuite/tests/OA27-059-separate-consolidation/test.opt deleted file mode 100644 index f99af998d..000000000 --- a/testsuite/tests/OA27-059-separate-consolidation/test.opt +++ /dev/null @@ -1 +0,0 @@ -!bin-traces XFAIL SB12-022: trouble with GPR's Main attribute diff --git a/testsuite/tests/OA27-059-separate-consolidation/test.py b/testsuite/tests/OA27-059-separate-consolidation/test.py index 4d02afd45..aeb8685b9 100644 --- a/testsuite/tests/OA27-059-separate-consolidation/test.py +++ b/testsuite/tests/OA27-059-separate-consolidation/test.py @@ -12,7 +12,7 @@ from SCOV.minicheck import build_and_run, checked_xcov, check_xcov_reports from SUITE.context import thistest from SUITE.gprutils import GPRswitches -from SUITE.cutils import Wdir +from SUITE.cutils import Wdir, contents_of from SUITE.tutils import xcov @@ -70,6 +70,7 @@ def build_and_run_tests(ignored_source_files=None): ignored_source_files=ignored_source_files, gpr_obj_dir=testcase.obj_dir(), gpr_exe_dir=testcase.exe_dir(), + extra_instr_args=["--dump-filename-simple"], extra_coverage_args=["--annotate=xcov", "--output-dir=output"], scos_for_run=False, ) @@ -82,12 +83,22 @@ def build_and_run_tests(ignored_source_files=None): # consolidation error by default. clean_output_directory() xcov_args = build_and_run_tests() +bin_traces = thistest.options.trace_mode == "bin" p = xcov(xcov_args, out="cons-1.log", register_failure=False) -thistest.fail_if( - p.status == 0, - '"gnatcov coverage" is supposed to complain about different symbols during' - " consolidation, but it did not.", -) +if bin_traces: + thistest.fail_if( + p.status == 0, + '"gnatcov coverage" is supposed to complain about different symbols' + " during consolidation, but it did not.", + ) +else: + thistest.fail_if_not_equal( + "'gnatcov coverage' output (cons-1.log)", + "warning: traces for separate pkg_under_test.pkg_test (from" + " main_test1.srctrace) are inconsistent with the corresponding Source" + " Instrumentation Data", + contents_of("cons-1.log").strip(), + ) # Build and run tests with ignored source files. Check that the new option # makes it ignore the problematic symbols, and succeeds to create a report with @@ -95,6 +106,12 @@ def build_and_run_tests(ignored_source_files=None): clean_output_directory() xcov_args = build_and_run_tests(["pkg_under_test-pkg_test.adb"]) p = checked_xcov(xcov_args, "cons-2.log") -check_xcov_reports("output", {"pkg_under_test.adb.xcov": {"+": {7, 8, 10}}}) +check_xcov_reports( + "output", + { + "pkg_under_test.adb.xcov": {"+": {7, 8, 10}}, + "pkg_under_test.ads.xcov": {}, + }, +) thistest.result() From edabb5f400794edace3a022f22dfec6369bb13d9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 22 Jul 2025 15:40:21 +0000 Subject: [PATCH 1325/1483] Instrument: fix the handling of special chars in C filenames --- .../instr-cov/c_special_filenames/ada_main.adb | 5 ++++- .../tests/instr-cov/c_special_filenames/main.c | 9 --------- .../tests/instr-cov/c_special_filenames/test.opt | 2 -- .../tests/instr-cov/c_special_filenames/test.py | 10 +++++----- tools/gnatcov/instrument-projects.adb | 14 ++++++++++++-- 5 files changed, 21 insertions(+), 19 deletions(-) delete mode 100644 testsuite/tests/instr-cov/c_special_filenames/main.c delete mode 100644 testsuite/tests/instr-cov/c_special_filenames/test.opt diff --git a/testsuite/tests/instr-cov/c_special_filenames/ada_main.adb b/testsuite/tests/instr-cov/c_special_filenames/ada_main.adb index 6fe842a78..468fc16f4 100644 --- a/testsuite/tests/instr-cov/c_special_filenames/ada_main.adb +++ b/testsuite/tests/instr-cov/c_special_filenames/ada_main.adb @@ -4,7 +4,10 @@ procedure Ada_Main is function Foo (I : int) return int; pragma Import (C, Foo, "foo"); - I : constant int := Foo (1); + function Bar (A, B, C : int) return int; + pragma Import (C, Bar, "bar"); + + I : constant int := Foo (1) + Bar (1, 0, 2); begin null; end Ada_Main; diff --git a/testsuite/tests/instr-cov/c_special_filenames/main.c b/testsuite/tests/instr-cov/c_special_filenames/main.c deleted file mode 100644 index 2c284257d..000000000 --- a/testsuite/tests/instr-cov/c_special_filenames/main.c +++ /dev/null @@ -1,9 +0,0 @@ -extern int foo (int i); -extern int bar (int a, int b, int c); - -int -main (void) -{ - int result = foo (0) + bar (1, 0, 2); - return result; -} diff --git a/testsuite/tests/instr-cov/c_special_filenames/test.opt b/testsuite/tests/instr-cov/c_special_filenames/test.opt deleted file mode 100644 index ce5f4954f..000000000 --- a/testsuite/tests/instr-cov/c_special_filenames/test.opt +++ /dev/null @@ -1,2 +0,0 @@ -ALL XFAIL Source naming makes GPR2 crash (eng/gpr/gpr-issues#624) -!C++ DEAD test requires C++ compiler diff --git a/testsuite/tests/instr-cov/c_special_filenames/test.py b/testsuite/tests/instr-cov/c_special_filenames/test.py index 332ab0f05..846032457 100644 --- a/testsuite/tests/instr-cov/c_special_filenames/test.py +++ b/testsuite/tests/instr-cov/c_special_filenames/test.py @@ -24,7 +24,6 @@ "ada_main.adb": "ada_main.adb", "bar.c": "src bar.c" if env.build.os.name == "windows" else 'src\\"bar.c', "foo.c": "src foo$@.c", - "main.c": "main.c", } for src, dest in copy_map.items(): cp(os.path.join("..", src), dest) @@ -34,10 +33,9 @@ # path separator canonicalization) and then the unique filename machinery turns # '/' to '-'. coverage_data = { - "ada_main.adb": {"+": {7, 9}}, + "ada_main.adb": {"+": {10, 12}}, "bar.c": {"+": {4, 5}, "-": {7}}, "foo.c": {"+": {4}}, - "main.c": {"+": {7, 8}}, } expected_report = { "{}.xcov".format(copy_map[filename].replace("\\", "-")): report @@ -46,10 +44,12 @@ build_run_and_coverage( gprsw=GPRswitches( - root_project=gprfor(srcdirs=["."], mains=["main.c", "ada_main.adb"]) + root_project=gprfor( + srcdirs=["."], mains=["ada_main.adb"], langs=["Ada", "C"] + ) ), covlevel="stmt", - mains=["main", "ada_main"], + mains=["ada_main"], extra_coverage_args=["-axcov", "--output-dir=xcov"], trace_mode="src", ) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 921ca5596..7713a4951 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -652,8 +652,18 @@ is & "sid"); end; when File_Based_Language => - SID_Basename := - +Ada.Directories.Simple_Name (+LU_Info.Unit_Name) & ".sid"; + + -- TODO (eng/toolchain/gnat#603)??? Ada.Directories.Simple_Name + -- fails in edge cases. Use GNATCOLL.VFS instead for more reliable + -- results. + + declare + File : constant Virtual_File := + Create (+(+LU_Info.Unit_Name)); + Basename : constant String := +File.Base_Name; + begin + SID_Basename := +Basename & ".sid"; + end; end case; return String (Output_Directory.Value) / (+SID_Basename); From f1565f22528e9b2b960f4b8ab3e557a70834731d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 15:05:21 +0000 Subject: [PATCH 1326/1483] C++/stmt/ForRange/WithInitializerRange: XFAIL for bareboard+src-traces --- testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.opt diff --git a/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.opt b/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.opt new file mode 100644 index 000000000..16851dbd2 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.opt @@ -0,0 +1 @@ +bareboard,src-traces XFAIL eng/das/cov/gnatcoverage#442 From 91244490da14b8f318afc68032d97ef6131a8bee Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 22 Jul 2025 20:11:21 +0000 Subject: [PATCH 1327/1483] 106-externally-built-header: remove obsolete XFAIL --- testsuite/tests/106-externally-built-header/test.opt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 testsuite/tests/106-externally-built-header/test.opt diff --git a/testsuite/tests/106-externally-built-header/test.opt b/testsuite/tests/106-externally-built-header/test.opt deleted file mode 100644 index 4f2a3ffe1..000000000 --- a/testsuite/tests/106-externally-built-header/test.opt +++ /dev/null @@ -1 +0,0 @@ -5.04a1 XFAIL Incompatibility between gnatls and GNATCOLL.Projects From 3a59c61ef5d1b7bac31b0ec680c8561fad707206 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 07:24:22 +0000 Subject: [PATCH 1328/1483] SB06-033-homonyms: escape paths in pattern interpolation On Windows, paths use backslashes for the directory separator, which is interpreted as an escape sequence in regexps. Use `re.escape` to avoid that. --- testsuite/tests/SB06-033-homonyms/test.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/testsuite/tests/SB06-033-homonyms/test.py b/testsuite/tests/SB06-033-homonyms/test.py index d306b673a..1e9d7a4cb 100644 --- a/testsuite/tests/SB06-033-homonyms/test.py +++ b/testsuite/tests/SB06-033-homonyms/test.py @@ -7,6 +7,7 @@ """ import os.path +import re from SUITE.context import thistest from SUITE.cutils import Wdir, contents_of @@ -65,15 +66,17 @@ "Warning: same base name for files:" "\r?\n [^\n]+{}" "\r?\n [^\n]+{}".format( - os.path.join( - "SB06-033-homonyms", - "tmp_libfoo", - "install", - "include", - "libfoo", - "lib.adb", + re.escape( + os.path.join( + "SB06-033-homonyms", + "tmp_libfoo", + "install", + "include", + "libfoo", + "lib.adb", + ) ), - os.path.join("SB06-033-homonyms", "libfoo", "lib.adb"), + re.escape(os.path.join("SB06-033-homonyms", "libfoo", "lib.adb")), ), contents_of(log_file), ) From 5cc82f94d3d953897109bfdd2f1c0b7009b30baa Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 07:34:48 +0000 Subject: [PATCH 1329/1483] Fix the warning for homonym filenames to use preserved casing This fixes SB06-033-homonyms on Windows: the testcase (rightfully) expect preserved casing for full names of conflicting filenames, but gnatcov used to include (before this patch) lower cased full names instead. This bug fix also removes Windows-specific behavior, which was actually not due to a fundamental problem. --- testsuite/tests/T825-010-naming-scheme/test.py | 11 ----------- tools/gnatcov/files_table.adb | 4 ++-- tools/gnatcov/traces_elf.adb | 2 +- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/testsuite/tests/T825-010-naming-scheme/test.py b/testsuite/tests/T825-010-naming-scheme/test.py index 4d01b879e..96ff3a2ed 100644 --- a/testsuite/tests/T825-010-naming-scheme/test.py +++ b/testsuite/tests/T825-010-naming-scheme/test.py @@ -53,17 +53,6 @@ extra_coverage_args=["-axcov", "--output-dir=report"], ) - # On Windows, GNAT stores sources file basenames in ALI files as lowercase, - # so for binary traces, gnatcov has no way to find out the original casing - # for source files that are not mentionned in the debug info (in our test - # project: spec files). - if ( - thistest.options.trace_mode == "bin" - and thistest.env.build.os.name == "windows" - ): - pkg_spec = pkg_spec.lower() - child_spec = child_spec.lower() - check_xcov_reports( "report", { diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index b2441d295..c7ca599a4 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -830,8 +830,8 @@ package body Files_Table is else if Create (+Info_Simple.Full_Name.all) /= Full_Path then Put_Line ("Warning: same base name for files:"); - Put_Line (" " & (+GNATCOLL.VFS.Full_Name (Full_Path))); - Put_Line (" " & Info_Simple.Full_Name.all); + Put_Line (" " & Preserved_Full_Name); + Put_Line (" " & Info_Simple.Preserved_Full_Name.all); end if; end if; diff --git a/tools/gnatcov/traces_elf.adb b/tools/gnatcov/traces_elf.adb index 7caa4086d..7e54e33ab 100644 --- a/tools/gnatcov/traces_elf.adb +++ b/tools/gnatcov/traces_elf.adb @@ -2828,7 +2828,7 @@ package body Traces_Elf is then Dw_Filename else Build_Filename (Dir.all, Dw_Filename)); begin - Filenames.Append (Canonicalize_Filename (Filename)); + Filenames.Append (new String'(Filename)); Compute_File_Index (Filenames.Last_Element.all); end Register_Filename; From 1a1767dcf0adda0214c8e88194e6c073b7724219 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 24 Jul 2025 08:28:02 +0000 Subject: [PATCH 1330/1483] N321-039-disas-wrapping: fix ASM code to avoid gnatcov warnings These warnings are ignored in binary traces mode, but cause the test to fail in source traces mode. --- testsuite/tests/N321-039-disas-wrapping/foo.s | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/N321-039-disas-wrapping/foo.s b/testsuite/tests/N321-039-disas-wrapping/foo.s index 42bc95c1c..e510c949c 100644 --- a/testsuite/tests/N321-039-disas-wrapping/foo.s +++ b/testsuite/tests/N321-039-disas-wrapping/foo.s @@ -4,7 +4,11 @@ .file "foo.c" .text .align 2 +.syntax unified +.thumb +.thumb_func .type _start, %function _start: -.word 0 +mov r0, r1 +mov r0, r1 .size _start, .-_start From 13a407d27ab539c9836fbaa71d253505f11661d0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 24 Jul 2025 09:48:15 +0000 Subject: [PATCH 1331/1483] TC03-012-objcov-line-state: fix for source traces mode --- .../tests/TC03-012-objcov-line-state/test.py | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/testsuite/tests/TC03-012-objcov-line-state/test.py b/testsuite/tests/TC03-012-objcov-line-state/test.py index 2289101ef..9992b0ea1 100644 --- a/testsuite/tests/TC03-012-objcov-line-state/test.py +++ b/testsuite/tests/TC03-012-objcov-line-state/test.py @@ -30,16 +30,30 @@ ) gprbuild(original_prj, extracargs=["-save-temps"]) -# Use our custom assembly source for fact.c +# Use our custom assembly source for fact.c. Explicitly ask for debug info so +# that "gnatcov covearge" can generate XCOV reports. mkdir("src") cp("../main.c", "src/main.c") cp("../fact.s", "src/fact.s") prj = gprfor(srcdirs=["src"], mains=["main.c"], prjid="gen") -gprbuild(prj) +gprbuild(prj, extracargs=["-g"]) -# Run and compute the XCOV coverage report -xrun(["-cinsn", exepath_to("main")]) -xcov(["coverage", "-cinsn", "-axcov", "-Pgen", tracename_for("main")]) +# Run and compute the XCOV coverage report. Restrict the set of routines +# considered for object coverage so that gnatcov does not try to look for the +# source files used to implement the RTS. +routines = ["--routines=main", "--routines=fact"] +xrun(["-cinsn", exepath_to("main"), *routines]) +xcov( + [ + "coverage", + "-cinsn", + "-axcov", + "-Pgen", + *routines, + "--source-search=..", + tracename_for("main"), + ] +) # Check that line 4 is correctly marked as partially covered, as it contains # an uncovered instruction that follows an (always taken) branch (see the From c6ef07748c66a0098acf7bbd938556144f362546 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 24 Jul 2025 09:40:05 +0000 Subject: [PATCH 1332/1483] instr-cov/compiler_switches_gpr_opts: avoid warning with Ravenscar RTS --- .../tests/instr-cov/compiler_switches_gpr_opts/test.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.py b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.py index 35c74eaea..ce87cfaf7 100644 --- a/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.py +++ b/testsuite/tests/instr-cov/compiler_switches_gpr_opts/test.py @@ -10,7 +10,12 @@ from SUITE.tutils import gprfor tmp = Wdir("tmp_") -xcov_args = ["instrument", "--level=stmt"] + +# Some automatic dump triggers (ravenscar-task-termination) are not available +# for all languages: instrumenting a C/C++ project with the default dump +# trigger in some configurations yields a warning. Explicitly ask for a dump +# trigger that is always supported to avoid this warning. +xcov_args = ["instrument", "--level=stmt", "--dump-trigger=main-end"] def check_lang(lang, file_ext): From f230f462a53c6e8a1fb966bc23a73b176eb10027 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 24 Jul 2025 12:57:56 +0000 Subject: [PATCH 1333/1483] OA27-059-separate-consolidation: fix for native/src-traces runs The previous change on this testcase forgot to account for this specific setup. --- .../tests/OA27-059-separate-consolidation/test.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/OA27-059-separate-consolidation/test.py b/testsuite/tests/OA27-059-separate-consolidation/test.py index aeb8685b9..c9298a07a 100644 --- a/testsuite/tests/OA27-059-separate-consolidation/test.py +++ b/testsuite/tests/OA27-059-separate-consolidation/test.py @@ -70,11 +70,17 @@ def build_and_run_tests(ignored_source_files=None): ignored_source_files=ignored_source_files, gpr_obj_dir=testcase.obj_dir(), gpr_exe_dir=testcase.exe_dir(), - extra_instr_args=["--dump-filename-simple"], extra_coverage_args=["--annotate=xcov", "--output-dir=output"], scos_for_run=False, ) - trace_files.append(xcov_args.pop()) + + # Rename the trace file so that 1) the next iteration does not + # overwrite it if trace filenames are stable and 2) we get + # deterministic filenames, useful for warning baselines below. + filename = xcov_args.pop() + renamed = f"t-{testcase.name}.srctrace" + os.rename(filename, renamed) + trace_files.append(renamed) return xcov_args + trace_files @@ -95,7 +101,7 @@ def build_and_run_tests(ignored_source_files=None): thistest.fail_if_not_equal( "'gnatcov coverage' output (cons-1.log)", "warning: traces for separate pkg_under_test.pkg_test (from" - " main_test1.srctrace) are inconsistent with the corresponding Source" + " t-test1.srctrace) are inconsistent with the corresponding Source" " Instrumentation Data", contents_of("cons-1.log").strip(), ) From 4cbb57c398ecafb626244f2bc1b91d72aed11373 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 15:48:04 +0000 Subject: [PATCH 1334/1483] instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain: skip ... on bareboard targets. As other tests that fundamentally rely on abortion/exception propagation, we cannot run them on bareboard configurations. Also add the call to fflush so that the output does not get truncated during the abort when running under QNX. --- .../c/function-pointer-call-chain/test.opt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.opt diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.opt b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.opt new file mode 100644 index 000000000..ff2263e82 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/c/function-pointer-call-chain/test.opt @@ -0,0 +1,4 @@ +-- Technically, it could be possible to use exception propagation instead of +-- the exit system call for this test, but this would not help to support this +-- on cross targets. +!native DEAD Tested features requires program abortion From caf8004ede6099be5cef0ea69fa77007df0fcddd Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 20:16:11 +0000 Subject: [PATCH 1335/1483] libsupport: add missing exception message in last chance handler for QNX The last chance handler introduced recently violates the principle that last chance handlers must output the special `!!! EXCEPTION RAISED !!!` message (usually done in libsupport's default last chance handler, in `support/src/last_chance_/simple_last_chance_handler.adb`). This commit adds this message back for QNX, which fixes the current regression in `Qualif/Appendix/Testsuite/Selftest/assert-failure`. --- .../src/aarch64-nto-qnx/simple_last_chance_handler.adb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.adb b/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.adb index edafff410..beac8dd13 100644 --- a/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.adb +++ b/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.adb @@ -18,7 +18,6 @@ ------------------------------------------------------------------------------ with GNAT.IO; -with System; package body Simple_Last_Chance_Handler is @@ -44,6 +43,11 @@ package body Simple_Last_Chance_Handler is begin Lch_Enter; + GNAT.IO.New_Line; + GNAT.IO.Put_Line ("!!!!!!!!!!!!!!!!!!!!!!!!"); + GNAT.IO.Put_Line ("!!! EXCEPTION RAISED !!!"); + GNAT.IO.Put_Line ("!!!!!!!!!!!!!!!!!!!!!!!!"); + -- In QNX, QEMU does not flush the stdout buffer before aborting, -- so we do it. Fflush (Stdout); From 9949b5b018fb772606e431e99f3155cae77e267d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 11:23:49 +0000 Subject: [PATCH 1336/1483] C++/mcdc/AandB/In_Dtor: remove useless dynamic allocation --- testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.cpp b/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.cpp index cb87053ef..ca7d4f9b4 100644 --- a/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.cpp +++ b/testsuite/tests/C++/mcdc/AandB/In_Dtor/src/tryme.cpp @@ -30,6 +30,5 @@ tryme (bool aa, bool bb, bool skip) if (skip) // # test_skip return; // # skip - AndExpr *e = new AndExpr (aa, bb); // # other - delete e; // # other + AndExpr e (aa, bb); // # other } From 35f02b609cd01f6cba2432543736951c8c5e143c Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 11:24:22 +0000 Subject: [PATCH 1337/1483] C++/stmt/ForRange/WithInit: skip when exception propagation not avail. --- testsuite/tests/C++/stmt/ForRange/WithInit/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/C++/stmt/ForRange/WithInit/test.opt diff --git a/testsuite/tests/C++/stmt/ForRange/WithInit/test.opt b/testsuite/tests/C++/stmt/ForRange/WithInit/test.opt new file mode 100644 index 000000000..ecaecfaa9 --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/WithInit/test.opt @@ -0,0 +1 @@ +bareboard DEAD Exception propagation support required From a488e5d80344c3b25eb00b9699a3d57f6affe711 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 11:25:15 +0000 Subject: [PATCH 1338/1483] C++/stmt/ForRange/WithoutInit: adapt for bareboard targets --- .../C++/stmt/ForRange/WithoutInit/src/sum.cpp | 8 +-- .../C++/stmt/ForRange/WithoutInit/src/sum.hh | 4 +- .../stmt/ForRange/WithoutInit/src/test_0.cpp | 2 +- .../WithoutInit/src/test_early_exit.cpp | 4 +- .../ForRange/WithoutInit/src/test_empty.cpp | 2 +- .../ForRange/WithoutInit/src/test_full.cpp | 2 +- .../C++/stmt/ForRange/src/range_iterable.hh | 60 +++++++++++++++++++ 7 files changed, 71 insertions(+), 11 deletions(-) create mode 100644 testsuite/tests/C++/stmt/ForRange/src/range_iterable.hh diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.cpp index a3292f62d..d86b3ffd7 100644 --- a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.cpp +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.cpp @@ -1,12 +1,12 @@ #include "sum.hh" int -sum (std::vector ints) +sum (const RangeIterable &r) { - int result = 0; // # init - for (const int &i : ints) // # for-range + int result = 0; // # init + for (int i : r) // # for-range { - if (i == 0) // # if-cond + if (i == 10) // # if-cond return 0; // # if-return result += i; // # if-add } diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.hh b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.hh index 1e4dd32b0..d22ef5369 100644 --- a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.hh +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/sum.hh @@ -1,3 +1,3 @@ -#include +#include "range_iterable.hh" -extern int sum (std::vector ints); +extern int sum (const RangeIterable &r); diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_0.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_0.cpp index a584fc402..aa86977dd 100644 --- a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_0.cpp +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_0.cpp @@ -4,7 +4,7 @@ int main (void) { volatile bool b = false; - return b && sum ({ 0, 1 }); + return b && sum (RangeIterable (1)); } //# sum.cpp diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_early_exit.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_early_exit.cpp index d4a1ede07..7ebc04713 100644 --- a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_early_exit.cpp +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_early_exit.cpp @@ -3,7 +3,7 @@ int main (void) { - if (sum ({ 0, 1 }) != 0) + if (sum (RangeIterable (10)) != 0) return 1; return 0; } @@ -14,5 +14,5 @@ main (void) // /for-range/ l+ ## 0 // /if-cond/ l+ ## 0 // /if-return/ l+ ## 0 -// /if-add/ l- ## s- +// /if-add/ l+ ## 0 // /return/ l- ## s- diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_empty.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_empty.cpp index 8e68d5def..9db3c36d5 100644 --- a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_empty.cpp +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_empty.cpp @@ -3,7 +3,7 @@ int main (void) { - if (sum ({}) != 0) + if (sum (RangeIterable (-1)) != 0) return 1; return 0; } diff --git a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_full.cpp b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_full.cpp index ffd905de3..cf8343f01 100644 --- a/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_full.cpp +++ b/testsuite/tests/C++/stmt/ForRange/WithoutInit/src/test_full.cpp @@ -3,7 +3,7 @@ int main (void) { - if (sum ({ 1, 2 }) != 3) + if (sum (RangeIterable (2)) != 3) return 1; return 0; } diff --git a/testsuite/tests/C++/stmt/ForRange/src/range_iterable.hh b/testsuite/tests/C++/stmt/ForRange/src/range_iterable.hh new file mode 100644 index 000000000..efd524e5b --- /dev/null +++ b/testsuite/tests/C++/stmt/ForRange/src/range_iterable.hh @@ -0,0 +1,60 @@ +#ifndef RANGE_ITERABLE_HH +#define RANGE_ITERABLE_HH + +class RangeCursor +{ + int max; + int current; + +public: + RangeCursor (int max, int current) : max (max), current (current) {} + + int + operator* () const + { + return current; + } + + RangeCursor & + operator++ () + { + current += 1; + return *this; + } + + static inline bool + equals (const RangeCursor &lhs, const RangeCursor &rhs) + { + return lhs.current == rhs.current; + } +}; + +inline bool +operator!= (const RangeCursor &lhs, const RangeCursor &rhs) +{ + return !RangeCursor::equals (lhs, rhs); +} + +class RangeIterable +{ + int max; + +public: + RangeIterable (int max) : max (max) {} + + RangeIterable (const RangeIterable &&r) : max (r.max) {} + + RangeCursor + begin () const + { + return RangeCursor (max, 0); + } + + RangeCursor + end () const + { + return RangeCursor (max, max + 1); + } +}; + +#endif From 056402677902357f8cdb04f3d2052eb28e44e0c2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 11:29:38 +0000 Subject: [PATCH 1339/1483] instr-cov/C++/68-lambda-decisions: adapt for bareboard targets --- .../instr-cov/C++/68-lambda-decisions/src/test_pkg.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/test_pkg.cpp b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/test_pkg.cpp index 107377e28..d8bf064a4 100644 --- a/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/test_pkg.cpp +++ b/testsuite/tests/instr-cov/C++/68-lambda-decisions/src/test_pkg.cpp @@ -1,11 +1,13 @@ #include "pkg.hh" -#include int main () { - assert (overly_complex_fact (2) == 2); - assert (overly_complex_fact (0) == 1); + if (!overly_complex_fact (2) == 2) + return 1; + if (!overly_complex_fact (0) == 1) + return 1; + return 0; } //# pkg.cpp From fe2f4dd7823298e7d502f363b8b6ada163196e95 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 11:33:35 +0000 Subject: [PATCH 1340/1483] instr-cov/C++/c++_generics: adapt for bareboard targets --- .../instr-cov/C++/c++_generics/src/pkg.cpp | 3 +- .../tests/instr-cov/C++/c++_generics/test.py | 54 ++----------------- 2 files changed, 5 insertions(+), 52 deletions(-) diff --git a/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.cpp b/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.cpp index 50ae2fc0f..c3ab7092e 100644 --- a/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.cpp +++ b/testsuite/tests/instr-cov/C++/c++_generics/src/pkg.cpp @@ -1,11 +1,10 @@ #include "pkg.h" -#include template void print_point (Point p) { - std::cout << p.x << '\n' << p.y << std::endl; + (void) p; } void diff --git a/testsuite/tests/instr-cov/C++/c++_generics/test.py b/testsuite/tests/instr-cov/C++/c++_generics/test.py index cf61231a6..31e60085a 100644 --- a/testsuite/tests/instr-cov/C++/c++_generics/test.py +++ b/testsuite/tests/instr-cov/C++/c++_generics/test.py @@ -35,64 +35,18 @@ def build_and_run_with_main(main): # Testcase both instantiation calls build_and_run_with_main(MAIN_BOTH) -check_xcov_reports( - "xcov", - { - "pkg.cpp.xcov": { - "+": { - 8, - 14, - 15, - 21, - 22, - } - } - }, -) +check_xcov_reports("xcov", {"pkg.cpp.xcov": {"+": {7, 13, 14, 20, 21}}}) # Testcase only int instantiation call build_and_run_with_main(MAIN_INT) -check_xcov_reports( - "xcov", - { - "pkg.cpp.xcov": { - "-": { - 21, - 22, - } - } - }, -) +check_xcov_reports("xcov", {"pkg.cpp.xcov": {"-": {20, 21}}}) # Testcase only float instantiation call build_and_run_with_main(MAIN_FLOAT) -check_xcov_reports( - "xcov", - { - "pkg.cpp.xcov": { - "-": { - 14, - 15, - } - } - }, -) +check_xcov_reports("xcov", {"pkg.cpp.xcov": {"-": {13, 14}}}) # Testcase no instantiation call build_and_run_with_main(MAIN_NONE) -check_xcov_reports( - "xcov", - { - "pkg.cpp.xcov": { - "-": { - 8, - 14, - 15, - 21, - 22, - } - } - }, -) +check_xcov_reports("xcov", {"pkg.cpp.xcov": {"-": {7, 13, 14, 20, 21}}}) thistest.result() From a467bf4ba1723b73e97a6a683d46267b7d38eda6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 11:34:06 +0000 Subject: [PATCH 1341/1483] instr-cov/C++/explicit_lang: adapt for bareboard targets --- testsuite/tests/instr-cov/C++/explicit_lang/main.c | 14 +++++++++++--- .../tests/instr-cov/C++/explicit_lang/test.py | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/testsuite/tests/instr-cov/C++/explicit_lang/main.c b/testsuite/tests/instr-cov/C++/explicit_lang/main.c index ba8918dc9..b91c64636 100644 --- a/testsuite/tests/instr-cov/C++/explicit_lang/main.c +++ b/testsuite/tests/instr-cov/C++/explicit_lang/main.c @@ -1,8 +1,16 @@ -#include +class C +{ +public: + int + get_zero () + { + return 0; + } +}; int main () { - std::cout << "Hello World!"; - return 0; + C c; + return c.get_zero (); } diff --git a/testsuite/tests/instr-cov/C++/explicit_lang/test.py b/testsuite/tests/instr-cov/C++/explicit_lang/test.py index 1dc226e0e..aaa7254da 100644 --- a/testsuite/tests/instr-cov/C++/explicit_lang/test.py +++ b/testsuite/tests/instr-cov/C++/explicit_lang/test.py @@ -32,6 +32,6 @@ trace_mode="src", ) -check_xcov_reports("xcov", {"main.c.xcov": {"+": {6, 7}}}) +check_xcov_reports("xcov", {"main.c.xcov": {"+": {7, 14, 15}}}) thistest.result() From 443768c6065520ed052539c042d977323e27af4a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 12:50:18 +0000 Subject: [PATCH 1342/1483] instr-cov/C++/std-c++20: adapt for bareboard targets --- .../tests/instr-cov/C++/std-c++20/cmdline.cpp | 28 ------------------- .../tests/instr-cov/C++/std-c++20/cmdline.hh | 7 ----- .../tests/instr-cov/C++/std-c++20/main.cpp | 17 +++++++---- .../tests/instr-cov/C++/std-c++20/test.py | 6 +--- 4 files changed, 13 insertions(+), 45 deletions(-) delete mode 100644 testsuite/tests/instr-cov/C++/std-c++20/cmdline.cpp delete mode 100644 testsuite/tests/instr-cov/C++/std-c++20/cmdline.hh diff --git a/testsuite/tests/instr-cov/C++/std-c++20/cmdline.cpp b/testsuite/tests/instr-cov/C++/std-c++20/cmdline.cpp deleted file mode 100644 index 0ed5edbc3..000000000 --- a/testsuite/tests/instr-cov/C++/std-c++20/cmdline.cpp +++ /dev/null @@ -1,28 +0,0 @@ -#include "cmdline.hh" - -std::vector -add_dashes (std::string name) -{ - // Multi-letter linker options can be preceded by either a single - // dash or double dashes except ones starting with "o", which must - // be preceded by double dashes. For example, "-omagic" is - // interpreted as "-o magic". If you really want to specify the - // "omagic" option, you have to pass "--omagic". - if (name[0] == 'o') - return { "--" + name }; - return { "-" + name, "--" + name }; -} - -bool -read_flag (std::span &args, std::string name) -{ - for (std::string opt : add_dashes (name)) - { - if (args[0] == opt) - { - args = args.subspan (1); - return true; - } - } - return false; -} diff --git a/testsuite/tests/instr-cov/C++/std-c++20/cmdline.hh b/testsuite/tests/instr-cov/C++/std-c++20/cmdline.hh deleted file mode 100644 index 1a3e157e6..000000000 --- a/testsuite/tests/instr-cov/C++/std-c++20/cmdline.hh +++ /dev/null @@ -1,7 +0,0 @@ -#include -#include -#include - -extern std::vector add_dashes (std::string name); - -extern bool read_flag (std::span &args, std::string name); diff --git a/testsuite/tests/instr-cov/C++/std-c++20/main.cpp b/testsuite/tests/instr-cov/C++/std-c++20/main.cpp index e4b09704d..252ef50c8 100644 --- a/testsuite/tests/instr-cov/C++/std-c++20/main.cpp +++ b/testsuite/tests/instr-cov/C++/std-c++20/main.cpp @@ -1,10 +1,17 @@ -#include "cmdline.hh" +#include int main (int argc, char **argv) { - std::vector args_vec (argv, argv + argc); - std::span args = args_vec; - read_flag (args, "output"); - read_flag (args, "version"); + int a[]{ 0, 1, 2 }; + std::span s_all (a); + std::span s_0 = s_all.subspan (0, 1); + std::span s_2 = s_all.subspan (2, 1); + + if (s_0[0] != 0) + return 1; + if (s_2[0] != 2) + return 1; + + return 0; } diff --git a/testsuite/tests/instr-cov/C++/std-c++20/test.py b/testsuite/tests/instr-cov/C++/std-c++20/test.py index 6c3b49738..520f3ada9 100644 --- a/testsuite/tests/instr-cov/C++/std-c++20/test.py +++ b/testsuite/tests/instr-cov/C++/std-c++20/test.py @@ -31,11 +31,7 @@ def gen_prj(): ) check_xcov_reports( - "xcov", - { - "main.cpp.xcov": {"+": {6, 7, 8, 9}}, - "cmdline.cpp.xcov": {"+": {11, 12, 13, 21, 27}, "-": {23, 24}}, - }, + "xcov", {"main.cpp.xcov": {"+": {6, 7, 8, 9, 11, 13, 16}, "-": {12, 14}}} ) tmp.to_homedir() From 523495912e288d6a25e88b653c3b384d01efd3fc Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 13:06:11 +0000 Subject: [PATCH 1343/1483] instr-cov/C++/std-cond-code: adapt for bareboard targets --- .../instr-cov/C++/std-cond-code/main.cpp | 11 +++--- .../tests/instr-cov/C++/std-cond-code/test.py | 35 ++++++++++--------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp b/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp index 84f4d82b9..611409f21 100644 --- a/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp +++ b/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp @@ -1,16 +1,19 @@ -#include +void +print_msg (const char *) +{ +} int main () { #if defined(__STDC_VERSION__) // This is true if the code is preprocessed as C code - std::cout << "This is C code" << std::endl; + print_msg ("This is C code"); #elif __cplusplus == 202002L // This is true if the code is preprocessed as C++20 code - std::cout << "This is C++20 code" << std::endl; + print_msg ("This is C++20 code"); #else - std::cout << "This is C++ code" << std::endl; + print_msg ("This is C++ code"); #endif return 0; } diff --git a/testsuite/tests/instr-cov/C++/std-cond-code/test.py b/testsuite/tests/instr-cov/C++/std-cond-code/test.py index 6d1964aff..a84d656da 100644 --- a/testsuite/tests/instr-cov/C++/std-cond-code/test.py +++ b/testsuite/tests/instr-cov/C++/std-cond-code/test.py @@ -3,11 +3,11 @@ with the right preprocessor configuration. """ -from SCOV.minicheck import build_and_run +from SCOV.instr import xcov_instrument from SUITE.context import thistest -from SUITE.cutils import contents_of, Wdir -from SUITE.tutils import gprfor +from SUITE.cutils import Wdir, contents_of from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprbuild, gprfor def run_variant( @@ -16,6 +16,7 @@ def run_variant( extra_gprbuild_cargs, tolerate_instrument_messages=None, pred=lambda: True, + skip_build=False, ): """ Build and run the project with the given arguments, and check the predicate @@ -25,23 +26,22 @@ def run_variant( :param extra_instr_cpp_args: Args passed to gnatcov instrument --c++-opts. :param extra_gprbuild_cargs: Args passed to gprbuild -cargs. :param pred: Predicate checked after building and running. + :param skip_build: Whether to skip the build of the instrumented sources. """ tmp = Wdir(f"tmp_{variant_name}") - build_and_run( - gprsw=GPRswitches( - root_project=gprfor(srcdirs=[".."], mains=["main.cpp"]) - ), + prj = gprfor(srcdirs=[".."], mains=["main.cpp"]) + xcov_instrument( + gprsw=GPRswitches(root_project=prj), covlevel="stmt", - mains=["main"], - extra_instr_args=[f"--c++-opts={','.join(extra_instr_cppargs)}"], - extra_gprbuild_cargs=extra_gprbuild_cargs, - trace_mode="src", - tolerate_instrument_messages=tolerate_instrument_messages, - extra_coverage_args=[], + extra_args=[f"--c++-opts={','.join(extra_instr_cppargs)}"], + tolerate_messages=tolerate_instrument_messages, register_failure=False, ) + if not skip_build: + gprbuild(prj, extracargs=extra_gprbuild_cargs, trace_mode="src") + thistest.fail_if( not pred(), f"Unexpected assertion failure for variant {variant_name}" ) @@ -52,8 +52,8 @@ def run_variant( run_variant( variant_name="gprbuild-c++20", extra_instr_cppargs=[], - extra_gprbuild_cargs=["-std=c++20"], - pred=lambda: "This is C++ code" in contents_of("main_output.txt"), + extra_gprbuild_cargs=["-std=c++20", "-save-temps"], + pred=lambda: "This is C++ code" in contents_of("obj/main.s"), ) run_variant( variant_name="instr-c89", @@ -61,12 +61,13 @@ def run_variant( extra_gprbuild_cargs=[], tolerate_instrument_messages="Failed to parse", pred=lambda: "Failed to parse" in contents_of("instrument.log"), + skip_build=True, ) run_variant( variant_name="instr-gprbuild-c++20", extra_instr_cppargs=["-std=c++20"], - extra_gprbuild_cargs=["-std=c++20"], - pred=lambda: "This is C++20 code" in contents_of("main_output.txt"), + extra_gprbuild_cargs=["-std=c++20", "-save-temps"], + pred=lambda: "This is C++20 code" in contents_of("obj/main.s"), ) thistest.result() From c30d1def6ef2a90be26df4188c7524099421658a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 13:08:27 +0000 Subject: [PATCH 1344/1483] instr-cov/manual-dump/pragma_once_in_spec: adapt for bareboard targets --- .../instr-cov/manual-dump/pragma_once_in_spec/src/main.cpp | 7 +++++-- .../instr-cov/manual-dump/pragma_once_in_spec/test.py | 5 +---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/main.cpp b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/main.cpp index 1cc378426..850a19c37 100644 --- a/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/main.cpp +++ b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/src/main.cpp @@ -1,6 +1,9 @@ #include "stuff.hpp" -#include +void +print_int (int) +{ +} int main (int argc, char **argv) @@ -11,7 +14,7 @@ main (int argc, char **argv) Stuff a = { 5 }; - std::cout << a.data << "\n"; + print_int (a.data); /* GNATCOV_DUMP_BUFFERS */ diff --git a/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.py b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.py index 62568ea3e..10ef871cc 100644 --- a/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.py +++ b/testsuite/tests/instr-cov/manual-dump/pragma_once_in_spec/test.py @@ -44,10 +44,7 @@ # Check that we got the expected coverage report check_xcov_reports( - "obj", - { - "main.cpp.xcov": {"+": {9, 10, 12, 14}, "-": {18}}, - }, + "obj", {"main.cpp.xcov": {"+": {12, 13, 15, 17}, "-": {21}}} ) thistest.result() From 0cf64b058d311b8e99f89c9e466fddb5405177db Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 13:22:25 +0000 Subject: [PATCH 1345/1483] instr-cov/manual-dump/files_specified/test.py: minor refactoring --- .../manual-dump/files_specified/test.py | 119 +++++++++--------- 1 file changed, 61 insertions(+), 58 deletions(-) diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/test.py b/testsuite/tests/instr-cov/manual-dump/files_specified/test.py index 5a8ed0e2b..8da96c3d1 100644 --- a/testsuite/tests/instr-cov/manual-dump/files_specified/test.py +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/test.py @@ -12,7 +12,6 @@ from SUITE.gprutils import GPRswitches from SUITE.tutils import gprfor -test_dir = os.getcwd() # Expected xcov report expected_xcov = { @@ -25,10 +24,19 @@ "foo_skipped_cpp.cpp.xcov": {"-": {4}}, } +# Source files in which to process manual directives +manual_files = [ + "../main.adb", + "../foo.adb", + "../foo_c.c", + "../foo_cpp.cpp", +] -def GPRswitches_wrapper(): + +def get_gprsw(): """ Generate a project file in the current directory and return the GPRswitches + instance. """ return GPRswitches( gprfor( @@ -40,32 +48,30 @@ def GPRswitches_wrapper(): ) +# +# Regular cases +# + thistest.log("====== Pass filenames on the command line ======") tmp = Wdir("tmp_simple") - -# Check by passing a simple filename build_run_and_coverage( - gprsw=GPRswitches_wrapper(), + gprsw=get_gprsw(), covlevel="stmt", mains=["main"], extra_coverage_args=["--annotate=xcov", "--output-dir=xcov"], - dump_trigger="manual,../main.adb,../foo.adb,../foo_c.c,../foo_cpp.cpp", + dump_trigger=",".join(["manual"] + manual_files), manual_prj_name="main", ) check_xcov_reports("xcov", expected_xcov) +tmp.to_homedir() -# Check by passing a response file thistest.log("====== Pass filenames through a response file ======") -tmp.to_homedir() tmp = Wdir("tmp_resp") - -with open("resp", "w") as resp_file: - resp_file.write(os.path.join(test_dir, "main.adb") + "\n") - resp_file.write(os.path.join(test_dir, "foo.adb") + "\n") - resp_file.write(os.path.join(test_dir, "foo_c.c") + "\n") - resp_file.write(os.path.join(test_dir, "foo_cpp.cpp") + "\n") +with open("resp", "w") as f: + for filename in manual_files: + print(os.path.abspath(filename), file=f) build_run_and_coverage( - gprsw=GPRswitches_wrapper(), + gprsw=get_gprsw(), covlevel="stmt", mains=["main"], extra_coverage_args=["--annotate=xcov", "--output-dir=xcov"], @@ -73,52 +79,49 @@ def GPRswitches_wrapper(): manual_prj_name="main", ) check_xcov_reports("xcov", expected_xcov) +tmp.to_homedir() + +# +# Error cases +# -# Check error cases thistest.log("====== Check error cases ======") -tmp.to_homedir() tmp = Wdir("tmp_err") -GPRswitches_wrapper() - -# Check that gnatcov exits with an error when passing a file that does not -# exist. -instr_out = "instr_wrong_file.out" -xcov( - [ - "instrument", - "-Pmain", - "--level=stmt", - "--dump-trigger=manual,unknown", - "--quiet", - ], - out=instr_out, - register_failure=False, -) -thistest.fail_if_no_match( - "missing error in gnatcov instrument output", - r".*gnatcov(\.exe)?: File unknown does not exist", - contents_of(instr_out), -) +get_gprsw() -# Check that gnatcov exits with an error when passing -# --dump-trigger=atexit,file. -instr_out = "instr_wrong_trigger.out" -xcov( - [ - "instrument", - "-Pmain", - "--level=stmt", - "--dump-trigger=atexit,../main.adb", - "--quiet", - ], - out=instr_out, - register_failure=False, -) -thistest.fail_if_no_match( - "missing error in gnatcov instrument output", - r".*gnatcov(\.exe)?: --dump-trigger=atexit|main-end accepts a single" - " argument", - contents_of(instr_out), -) +for label, dump_trigger, error in [ + ( + # Check that gnatcov exits with an error when passing a file that does + # not exist. + "instr_wrong_file", + "manual,unknown", + r".*gnatcov(\.exe)?: File unknown does not exist", + ), + ( + # Check that gnatcov exits with an error when passing + # --dump-trigger=atexit,file. + "instr_wrong_trigger", + "atexit,../main.adb", + r".*gnatcov(\.exe)?: --dump-trigger=atexit|main-end accepts a single" + " argument", + ), +]: + instr_out = f"{label}.out" + xcov( + [ + "instrument", + "-Pmain", + "--level=stmt", + f"--dump-trigger={dump_trigger}", + "--quiet", + ], + out=instr_out, + register_failure=False, + ) + thistest.fail_if_no_match( + "missing error in gnatcov instrument output", + error, + contents_of(instr_out), + ) thistest.result() From a4209d768b7b24b8481fe455007c00ace967eef6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 14:55:08 +0000 Subject: [PATCH 1346/1483] SCOV.minicheck: fix handling of multiple mains with base64-stdout When running `xcov_convert_base64`, pick a different source trace filename for each main, so that we do not overwrite a single source trace file for each main. --- testsuite/SCOV/minicheck.py | 2 +- testsuite/tests/instr-cov/manual-dump/ext_prj/test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/SCOV/minicheck.py b/testsuite/SCOV/minicheck.py index a52648727..ec8b3e7e2 100644 --- a/testsuite/SCOV/minicheck.py +++ b/testsuite/SCOV/minicheck.py @@ -401,7 +401,7 @@ def gprbuild_wrapper(root_project): m, is_manual, manual_prj_name ) patterns.add(src_pattern) - trace_file = src_pattern.replace("*", "unique") + trace_file = src_pattern.replace("*", "-" + m) # Here we're really supposed to have a trace in the output # so we can be a tad stricter on the conversion outcome. diff --git a/testsuite/tests/instr-cov/manual-dump/ext_prj/test.py b/testsuite/tests/instr-cov/manual-dump/ext_prj/test.py index c58144dd5..316097f46 100644 --- a/testsuite/tests/instr-cov/manual-dump/ext_prj/test.py +++ b/testsuite/tests/instr-cov/manual-dump/ext_prj/test.py @@ -35,7 +35,7 @@ mains=["main"], gpr_obj_dir="obj_ext", dump_trigger="manual", - manual_prj_name="", + manual_prj_name="P_Ext", extra_coverage_args=["-axcov"], ) From 4696a6c58896384451f2f356954c12177a0dafcb Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 14:56:04 +0000 Subject: [PATCH 1347/1483] instr-cov/manual-dump/files_specified: adapt for bareboard targets --- .../manual-dump/files_specified/c_print.h | 4 ++ .../manual-dump/files_specified/foo.adb | 7 -- .../manual-dump/files_specified/foo_c.c | 6 -- .../manual-dump/files_specified/foo_cpp.cpp | 6 -- .../files_specified/foo_skipped.adb | 7 -- .../files_specified/foo_skipped_c.c | 6 -- .../files_specified/foo_skipped_cpp.cpp | 6 -- .../manual-dump/files_specified/main.adb | 30 --------- .../files_specified/main_ada_process.adb | 11 ++++ .../files_specified/main_ada_skipped.adb | 11 ++++ .../files_specified/main_c_process.adb | 11 ++++ .../files_specified/main_c_skipped.adb | 11 ++++ .../manual-dump/files_specified/test.opt | 1 - .../manual-dump/files_specified/test.py | 64 ++++++++++++------- .../files_specified/unit_ada_process.adb | 8 +++ .../files_specified/unit_ada_skipped.adb | 8 +++ .../files_specified/unit_c_process.c | 9 +++ .../files_specified/unit_c_skipped.c | 9 +++ 18 files changed, 124 insertions(+), 91 deletions(-) create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/c_print.h delete mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/foo.adb delete mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/foo_c.c delete mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/foo_cpp.cpp delete mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped.adb delete mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_c.c delete mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_cpp.cpp delete mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/main.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_process.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_skipped.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/main_c_process.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/main_c_skipped.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_process.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_skipped.adb create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_process.c create mode 100644 testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_skipped.c diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/c_print.h b/testsuite/tests/instr-cov/manual-dump/files_specified/c_print.h new file mode 100644 index 000000000..586ab1103 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/c_print.h @@ -0,0 +1,4 @@ +static inline void +print_msg (const char *msg) +{ +} diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/foo.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/foo.adb deleted file mode 100644 index f885b4f2b..000000000 --- a/testsuite/tests/instr-cov/manual-dump/files_specified/foo.adb +++ /dev/null @@ -1,7 +0,0 @@ -with Ada.Text_IO; - -procedure Foo is -begin - Ada.Text_IO.Put_Line ("Hello world!"); - pragma Annotate (Xcov, Dump_Buffers); -end Foo; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_c.c b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_c.c deleted file mode 100644 index 4c8ae8bfd..000000000 --- a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_c.c +++ /dev/null @@ -1,6 +0,0 @@ -void -foo_c () -{ - int a = 0; - /* GNATCOV_DUMP_BUFFERS */ -} diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_cpp.cpp b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_cpp.cpp deleted file mode 100644 index 28ab55088..000000000 --- a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_cpp.cpp +++ /dev/null @@ -1,6 +0,0 @@ -extern "C" void -foo_cpp () -{ - int ret = 0; - /* GNATCOV_DUMP_BUFFERS */ -} diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped.adb deleted file mode 100644 index c5c13aacd..000000000 --- a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped.adb +++ /dev/null @@ -1,7 +0,0 @@ -with Ada.Text_IO; - -procedure Foo_Skipped is -begin - Ada.Text_IO.Put_Line ("Hello world!"); - pragma Annotate (Xcov, Dump_Buffers); -end Foo_Skipped; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_c.c b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_c.c deleted file mode 100644 index 36d55c5e5..000000000 --- a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_c.c +++ /dev/null @@ -1,6 +0,0 @@ -void -foo_skipped_c () -{ - int a = 0; - /* GNATCOV_DUMP_BUFFERS */ -} diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_cpp.cpp b/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_cpp.cpp deleted file mode 100644 index e8611fc8e..000000000 --- a/testsuite/tests/instr-cov/manual-dump/files_specified/foo_skipped_cpp.cpp +++ /dev/null @@ -1,6 +0,0 @@ -extern "C" void -foo_skipped_cpp () -{ - int a = 0; - /* GNATCOV_DUMP_BUFFERS */ -} diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/main.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/main.adb deleted file mode 100644 index 2073a499a..000000000 --- a/testsuite/tests/instr-cov/manual-dump/files_specified/main.adb +++ /dev/null @@ -1,30 +0,0 @@ -with Foo; -with Foo_Skipped; - -procedure Main is - procedure Foo_C; - pragma Import (C, Foo_C, "foo_c"); - - procedure Foo_Skipped_C; - pragma Import (C, Foo_Skipped_C, "foo_skipped_c"); - - procedure Foo_Cpp; - pragma Import (CPP, Foo_Cpp, "foo_cpp"); - - procedure Foo_Skipped_Cpp; - pragma Import (CPP, Foo_Skipped_CPP, "foo_skipped_cpp"); - -begin - Foo; - pragma Annotate (Xcov, Reset_Buffers); - Foo_Skipped; - pragma Annotate (Xcov, Reset_Buffers); - Foo_C; - pragma Annotate (Xcov, Reset_Buffers); - Foo_Skipped_C; - pragma Annotate (Xcov, Reset_Buffers); - Foo_Cpp; - pragma Annotate (Xcov, Reset_Buffers); - Foo_Skipped_Cpp; - pragma Annotate (Xcov, Reset_Buffers); -end Main; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_process.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_process.adb new file mode 100644 index 000000000..f64863d5c --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_process.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Unit_Ada_Process; + +procedure Main_Ada_Process is +begin + Put_Line ("Start main"); + Unit_Ada_Process; + Put_Line ("End main"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_Ada_Process; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_skipped.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_skipped.adb new file mode 100644 index 000000000..a5fe5f131 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/main_ada_skipped.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +with Unit_Ada_Skipped; + +procedure Main_Ada_Skipped is +begin + Put_Line ("Start main"); + Unit_Ada_Skipped; + Put_Line ("End main"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_Ada_Skipped; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/main_c_process.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/main_c_process.adb new file mode 100644 index 000000000..5022d04a9 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/main_c_process.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_C_Process is + procedure Unit_C_Process; + pragma Import (C, Unit_C_Process, "unit_c_process"); +begin + Put_Line ("Start main"); + Unit_C_Process; + Put_Line ("End main"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_C_Process; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/main_c_skipped.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/main_c_skipped.adb new file mode 100644 index 000000000..09e0ba55b --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/main_c_skipped.adb @@ -0,0 +1,11 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main_C_Skipped is + procedure Unit_C_Skipped; + pragma Import (C, Unit_C_Skipped, "unit_c_skipped"); +begin + Put_Line ("Start main"); + Unit_C_Skipped; + Put_Line ("End main"); + pragma Annotate (Xcov, Dump_Buffers); +end Main_C_Skipped; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/test.opt b/testsuite/tests/instr-cov/manual-dump/files_specified/test.opt index c1c6553e7..faf04374b 100644 --- a/testsuite/tests/instr-cov/manual-dump/files_specified/test.opt +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/test.opt @@ -1,2 +1 @@ 5.04a1 DEAD GNAT 5.04a1 crashes on unrecognized pragmas -!C++ DEAD Test requires a C++ compiler diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/test.py b/testsuite/tests/instr-cov/manual-dump/files_specified/test.py index 8da96c3d1..fa7a98bd8 100644 --- a/testsuite/tests/instr-cov/manual-dump/files_specified/test.py +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/test.py @@ -13,23 +13,50 @@ from SUITE.tutils import gprfor -# Expected xcov report +# Expected xcov report. We have 4 main closures with always the same structure: + +# [main] print 1 +# [main] call unit procedure +# [main] print 2 +# [main] dump buffers +# +# [unit] print 3 +# [unit] reset buffers +# [unit] print 4 +# +# We will always process manual annotations in mains (to dump buffers), but the +# annotations in units (to reset buffers) will be ignored in "unit_*_skipped*" +# sources. As a result, the coverage of: +# +# [main] print 1 +# [main] call unit procedure +# [unit] print 3 +# +# will be 1) covered when unit annotations are ignored and 2) uncovered +# otherwise. expected_xcov = { - "main.adb.xcov": {"+": {18, 22, 26}, "-": {20, 24, 28}}, - "foo.adb.xcov": {"+": {5}}, - "foo_skipped.adb.xcov": {"-": {5}}, - "foo_c.c.xcov": {"+": {4}}, - "foo_skipped_c.c.xcov": {"-": {4}}, - "foo_cpp.cpp.xcov": {"+": {4}}, - "foo_skipped_cpp.cpp.xcov": {"-": {4}}, + "main_ada_process.adb.xcov": {"+": {9}, "-": {7, 8}}, + "main_ada_skipped.adb.xcov": {"+": {7, 8, 9}}, + "unit_ada_process.adb.xcov": {"+": {7}, "-": {5}}, + "unit_ada_skipped.adb.xcov": {"+": {5, 7}}, + "main_c_process.adb.xcov": {"+": {9}, "-": {7, 8}}, + "main_c_skipped.adb.xcov": {"+": {7, 8, 9}}, + "unit_c_process.c.xcov": {"+": {8}, "-": {6}}, + "unit_c_skipped.c.xcov": {"+": {6, 8}}, } +# List of source files, as well as the mains in the generated project +source_files = [os.path.splitext(filename)[0] for filename in expected_xcov] +mains_files = [ + filename for filename in source_files if filename.startswith("main_") +] +mains_exe = [os.path.splitext(filename)[0] for filename in mains_files] + # Source files in which to process manual directives manual_files = [ - "../main.adb", - "../foo.adb", - "../foo_c.c", - "../foo_cpp.cpp", + os.path.abspath(filename) + for filename in source_files + if filename.startswith("main_") or "_skipped" not in filename ] @@ -38,14 +65,7 @@ def get_gprsw(): Generate a project file in the current directory and return the GPRswitches instance. """ - return GPRswitches( - gprfor( - prjid="main", - srcdirs=[".."], - mains=["main.adb"], - langs=["Ada", "C", "C++"], - ), - ) + return GPRswitches(gprfor(prjid="main", srcdirs=[".."], mains=mains_files)) # @@ -57,7 +77,7 @@ def get_gprsw(): build_run_and_coverage( gprsw=get_gprsw(), covlevel="stmt", - mains=["main"], + mains=mains_exe, extra_coverage_args=["--annotate=xcov", "--output-dir=xcov"], dump_trigger=",".join(["manual"] + manual_files), manual_prj_name="main", @@ -73,7 +93,7 @@ def get_gprsw(): build_run_and_coverage( gprsw=get_gprsw(), covlevel="stmt", - mains=["main"], + mains=mains_exe, extra_coverage_args=["--annotate=xcov", "--output-dir=xcov"], dump_trigger="manual,@resp", manual_prj_name="main", diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_process.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_process.adb new file mode 100644 index 000000000..05826d0b6 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_process.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Unit_Ada_Process is +begin + Put_Line ("Start unit"); + pragma Annotate (Xcov, Reset_Buffers); + Put_Line ("End unit"); +end Unit_Ada_Process; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_skipped.adb b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_skipped.adb new file mode 100644 index 000000000..ff30f2b0d --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_ada_skipped.adb @@ -0,0 +1,8 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Unit_Ada_Skipped is +begin + Put_Line ("Start unit"); + pragma Annotate (Xcov, Reset_Buffers); + Put_Line ("End unit"); +end Unit_Ada_Skipped; diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_process.c b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_process.c new file mode 100644 index 000000000..ccc1e6d48 --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_process.c @@ -0,0 +1,9 @@ +#include "c_print.h" + +void +unit_c_process (void) +{ + print_msg ("Start unit"); + /* GNATCOV_RESET_BUFFERS */ + print_msg ("End unit"); +} diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_skipped.c b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_skipped.c new file mode 100644 index 000000000..0b9d8fb0a --- /dev/null +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/unit_c_skipped.c @@ -0,0 +1,9 @@ +#include "c_print.h" + +void +unit_c_skipped (void) +{ + print_msg ("Start unit"); + /* GNATCOV_RESET_BUFFERS */ + print_msg ("End unit"); +} From 6cce1e42a8ddb8441f172cbaddd4743b0962af9b Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 15:18:45 +0000 Subject: [PATCH 1348/1483] instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain: skip ... on non-native platforms. --- .../cpp/function-pointer-call-chain/test.opt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.opt diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.opt b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.opt new file mode 100644 index 000000000..ff2263e82 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/function-pointer-call-chain/test.opt @@ -0,0 +1,4 @@ +-- Technically, it could be possible to use exception propagation instead of +-- the exit system call for this test, but this would not help to support this +-- on cross targets. +!native DEAD Tested features requires program abortion From 4041a8a843c8635a5e216c83d14a48485caff6cb Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 15:21:18 +0000 Subject: [PATCH 1349/1483] instr-cov/c_cpp_function_call_cov/cpp/generics: adapt for cross targets --- .../c_cpp_function_call_cov/cpp/generics/src/pkg.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.cpp index 8a9dcb819..22d95ca93 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.cpp +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/generics/src/pkg.cpp @@ -1,13 +1,12 @@ #include "pkg.h" -#include template void print_point (T p); template -void // # print_point_def_1 -print_point (T p) // # print_point_def_2 -{ // # print_point_def_2 - std::cout << p << std::endl; // # printing +void // # print_point_def_1 +print_point (T p) // # print_point_def_2 +{ // # print_point_def_2 + (void) p; // # printing } void // # foo_def_1 From 0aeed8688361345b196ec9ad70214b41fb2393d8 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 15:25:08 +0000 Subject: [PATCH 1350/1483] instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions: adapt ... for cross targets. --- .../cpp/namespaced-functions/src/pkg.cpp | 10 ++++------ .../cpp/namespaced-functions/src/pkg.h | 5 +++++ 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.cpp b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.cpp index e2d288566..b2e625f72 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.cpp +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.cpp @@ -1,15 +1,13 @@ #include "pkg.h" -#include namespace sub_module { void hello_world (void); -void // # hello_def_1 -hello_world (void) // # hello_def_2 -{ // # hello_def_2 - - puts ("Hello"); // # print +void // # hello_def_1 +hello_world (void) // # hello_def_2 +{ // # hello_def_2 + print_msg ("Hello"); // # print } } diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.h b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.h index 6eeda0117..903a1a9b4 100644 --- a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.h +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/namespaced-functions/src/pkg.h @@ -4,4 +4,9 @@ void foo (void); void bar (void); +static inline void +print_msg (const char *) +{ +} + #endif // _PKG_H From 0d15a2209396f520d4f5c41c6d2e2c6aba708801 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 23 Jul 2025 15:26:16 +0000 Subject: [PATCH 1351/1483] instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls: skip ... on non-native platforms. --- .../c_cpp_function_call_cov/cpp/nested-method-calls/test.opt | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.opt diff --git a/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.opt b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.opt new file mode 100644 index 000000000..ff2263e82 --- /dev/null +++ b/testsuite/tests/instr-cov/c_cpp_function_call_cov/cpp/nested-method-calls/test.opt @@ -0,0 +1,4 @@ +-- Technically, it could be possible to use exception propagation instead of +-- the exit system call for this test, but this would not help to support this +-- on cross targets. +!native DEAD Tested features requires program abortion From 6a34e6b645374b49658e32183ada14c2b7292a46 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 25 Jul 2025 08:30:36 +0000 Subject: [PATCH 1352/1483] instr-cov/manual-dump/files_specified: fix for block coverage --- .../tests/instr-cov/manual-dump/files_specified/test.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/testsuite/tests/instr-cov/manual-dump/files_specified/test.py b/testsuite/tests/instr-cov/manual-dump/files_specified/test.py index fa7a98bd8..dc09cae87 100644 --- a/testsuite/tests/instr-cov/manual-dump/files_specified/test.py +++ b/testsuite/tests/instr-cov/manual-dump/files_specified/test.py @@ -45,6 +45,13 @@ "unit_c_skipped.c.xcov": {"+": {6, 8}}, } +# Mains always have their first statement covered, so in block coverage, we +# expect the whole statement sequence to be covered. +if thistest.options.block: + for filename, report in expected_xcov.items(): + if filename.startswith("main_") and "-" in report: + report["+"].update(report.pop("-")) + # List of source files, as well as the mains in the generated project source_files = [os.path.splitext(filename)[0] for filename in expected_xcov] mains_files = [ From 53c8788fa608f765833343779cc785a767f3b083 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 25 Jul 2025 08:37:05 +0000 Subject: [PATCH 1353/1483] instr-cov/C++/std-cond-code: fix with optimizations enabled When optimizations are enabled, the call to `print_msg` is inlined, and thus the string literal (unused in `print_msg`) is optimized aways, not present in the output assembly code. This testcase relies on that string literal to perform its check. Move `print_msg` to a separate source file to avoid inlining, and thus this optimization. --- testsuite/tests/instr-cov/C++/std-cond-code/main.cpp | 5 +---- testsuite/tests/instr-cov/C++/std-cond-code/print_msg.c | 5 +++++ testsuite/tests/instr-cov/C++/std-cond-code/test.py | 6 +++--- 3 files changed, 9 insertions(+), 7 deletions(-) create mode 100644 testsuite/tests/instr-cov/C++/std-cond-code/print_msg.c diff --git a/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp b/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp index 611409f21..42d987a81 100644 --- a/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp +++ b/testsuite/tests/instr-cov/C++/std-cond-code/main.cpp @@ -1,7 +1,4 @@ -void -print_msg (const char *) -{ -} +extern "C" void print_msg (const char *msg); int main () diff --git a/testsuite/tests/instr-cov/C++/std-cond-code/print_msg.c b/testsuite/tests/instr-cov/C++/std-cond-code/print_msg.c new file mode 100644 index 000000000..2a2cd1bd8 --- /dev/null +++ b/testsuite/tests/instr-cov/C++/std-cond-code/print_msg.c @@ -0,0 +1,5 @@ +void +print_msg (const char *msg) +{ + (void) msg; +} diff --git a/testsuite/tests/instr-cov/C++/std-cond-code/test.py b/testsuite/tests/instr-cov/C++/std-cond-code/test.py index a84d656da..cc7507009 100644 --- a/testsuite/tests/instr-cov/C++/std-cond-code/test.py +++ b/testsuite/tests/instr-cov/C++/std-cond-code/test.py @@ -30,7 +30,7 @@ def run_variant( """ tmp = Wdir(f"tmp_{variant_name}") - prj = gprfor(srcdirs=[".."], mains=["main.cpp"]) + prj = gprfor(srcdirs=[".."], mains=["main.cpp"], langs=["C", "C++"]) xcov_instrument( gprsw=GPRswitches(root_project=prj), covlevel="stmt", @@ -52,7 +52,7 @@ def run_variant( run_variant( variant_name="gprbuild-c++20", extra_instr_cppargs=[], - extra_gprbuild_cargs=["-std=c++20", "-save-temps"], + extra_gprbuild_cargs=["-cargs:C++", "-std=c++20", "-save-temps"], pred=lambda: "This is C++ code" in contents_of("obj/main.s"), ) run_variant( @@ -66,7 +66,7 @@ def run_variant( run_variant( variant_name="instr-gprbuild-c++20", extra_instr_cppargs=["-std=c++20"], - extra_gprbuild_cargs=["-std=c++20", "-save-temps"], + extra_gprbuild_cargs=["-cargs:C++", "-std=c++20", "-save-temps"], pred=lambda: "This is C++20 code" in contents_of("obj/main.s"), ) From 68ced780074c910907c3dead17fd9a0471874f0a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 25 Jul 2025 08:42:15 +0000 Subject: [PATCH 1354/1483] OA27-059-separate-consolidation: fix Windows-hosted runs On Windows, Python's `os.rename()` function raises an exception if the destination file already exists. Clean up source traces from object directories to avoid that. --- testsuite/tests/OA27-059-separate-consolidation/test.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/testsuite/tests/OA27-059-separate-consolidation/test.py b/testsuite/tests/OA27-059-separate-consolidation/test.py index c9298a07a..760c59998 100644 --- a/testsuite/tests/OA27-059-separate-consolidation/test.py +++ b/testsuite/tests/OA27-059-separate-consolidation/test.py @@ -5,6 +5,7 @@ separate itself. """ +import glob import os import os.path import shutil @@ -44,10 +45,12 @@ def exe_dir(self, *args): return os.path.join("..", "bin", *args) -def clean_output_directory(): +def clean_objdir(): if os.path.exists("output"): shutil.rmtree("output") os.mkdir("output") + for t in glob.glob("*.srctrace"): + os.unlink(t) test1 = Testcase("test1", "obj1") @@ -87,7 +90,7 @@ def build_and_run_tests(ignored_source_files=None): # Build and run tests without ignored source files. Check that we indeed have a # consolidation error by default. -clean_output_directory() +clean_objdir() xcov_args = build_and_run_tests() bin_traces = thistest.options.trace_mode == "bin" p = xcov(xcov_args, out="cons-1.log", register_failure=False) @@ -109,7 +112,7 @@ def build_and_run_tests(ignored_source_files=None): # Build and run tests with ignored source files. Check that the new option # makes it ignore the problematic symbols, and succeeds to create a report with # the expected coverage data. -clean_output_directory() +clean_objdir() xcov_args = build_and_run_tests(["pkg_under_test-pkg_test.adb"]) p = checked_xcov(xcov_args, "cons-2.log") check_xcov_reports( From 3d1cf37d1f0e95b2db784b6e0029dee8ef4dba1f Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 25 Jul 2025 10:02:52 +0000 Subject: [PATCH 1355/1483] instr-cov/239-qnx-bin-file: add XFAIL --- testsuite/tests/instr-cov/239-qnx-bin-file/test.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt b/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt index 1dedc665b..083fe6f22 100644 --- a/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt +++ b/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt @@ -4,3 +4,4 @@ -- target. src-traces,qnx,RTS_LIGHT_TASKING ALL DEAD +src-traces,qnx,RTS_LIGHT_TASKING XFAIL See eng/toolchain/pycross#227 From 1e9e948b24d25893d9799db7476fb6630fa58414 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 8 Jul 2025 17:57:54 +0200 Subject: [PATCH 1356/1483] SCOV: print stdout and stderr upon cargo error --- testsuite/SCOV/internals/driver.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index d52a7878b..cec0ea80e 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -1661,7 +1661,10 @@ def run(self): ) if p.status != 0: thistest.stop( - FatalError("cargo build failed", outstr=p.out + p.err) + FatalError( + "cargo build failed", + outstr=f"stdout:\n{p.out}\n\nstderr:\n{p.err}", + ) ) # Run the program From e4123568e13551c9409f9016732518c4069d8049 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 9 Jul 2025 17:27:45 +0200 Subject: [PATCH 1357/1483] tests: Move old rust tests to free 'llvm/rust/' --- .../tests/llvm/{rust => rust-llvm-reports}/basic/coverage.json | 0 .../llvm/{rust => rust-llvm-reports}/basic/src/mcdc_basic.rs | 0 testsuite/tests/llvm/{rust => rust-llvm-reports}/basic/test.py | 0 .../tests/llvm/{rust => rust-llvm-reports}/closures/coverage.json | 0 .../llvm/{rust => rust-llvm-reports}/closures/src/closures.rs | 0 testsuite/tests/llvm/{rust => rust-llvm-reports}/closures/test.py | 0 .../{rust => rust-llvm-reports}/diff_formatting/coverage.json | 0 .../diff_formatting/src/diff_formatting.rs | 0 .../llvm/{rust => rust-llvm-reports}/diff_formatting/test.py | 0 .../tests/llvm/{rust => rust-llvm-reports}/impl/coverage.json | 0 testsuite/tests/llvm/{rust => rust-llvm-reports}/impl/src/impl.rs | 0 testsuite/tests/llvm/{rust => rust-llvm-reports}/impl/test.py | 0 .../llvm/{rust => rust-llvm-reports}/mcdc_nested/coverage.json | 0 .../{rust => rust-llvm-reports}/mcdc_nested/src/mcdc_nested.rs | 0 .../tests/llvm/{rust => rust-llvm-reports}/mcdc_nested/test.py | 0 .../mcdc_non_control_flow/coverage.json | 0 .../mcdc_non_control_flow/src/mcdc_assign.rs | 0 .../{rust => rust-llvm-reports}/mcdc_non_control_flow/test.py | 0 18 files changed, 0 insertions(+), 0 deletions(-) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/basic/coverage.json (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/basic/src/mcdc_basic.rs (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/basic/test.py (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/closures/coverage.json (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/closures/src/closures.rs (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/closures/test.py (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/diff_formatting/coverage.json (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/diff_formatting/src/diff_formatting.rs (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/diff_formatting/test.py (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/impl/coverage.json (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/impl/src/impl.rs (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/impl/test.py (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/mcdc_nested/coverage.json (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/mcdc_nested/src/mcdc_nested.rs (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/mcdc_nested/test.py (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/mcdc_non_control_flow/coverage.json (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/mcdc_non_control_flow/src/mcdc_assign.rs (100%) rename testsuite/tests/llvm/{rust => rust-llvm-reports}/mcdc_non_control_flow/test.py (100%) diff --git a/testsuite/tests/llvm/rust/basic/coverage.json b/testsuite/tests/llvm/rust-llvm-reports/basic/coverage.json similarity index 100% rename from testsuite/tests/llvm/rust/basic/coverage.json rename to testsuite/tests/llvm/rust-llvm-reports/basic/coverage.json diff --git a/testsuite/tests/llvm/rust/basic/src/mcdc_basic.rs b/testsuite/tests/llvm/rust-llvm-reports/basic/src/mcdc_basic.rs similarity index 100% rename from testsuite/tests/llvm/rust/basic/src/mcdc_basic.rs rename to testsuite/tests/llvm/rust-llvm-reports/basic/src/mcdc_basic.rs diff --git a/testsuite/tests/llvm/rust/basic/test.py b/testsuite/tests/llvm/rust-llvm-reports/basic/test.py similarity index 100% rename from testsuite/tests/llvm/rust/basic/test.py rename to testsuite/tests/llvm/rust-llvm-reports/basic/test.py diff --git a/testsuite/tests/llvm/rust/closures/coverage.json b/testsuite/tests/llvm/rust-llvm-reports/closures/coverage.json similarity index 100% rename from testsuite/tests/llvm/rust/closures/coverage.json rename to testsuite/tests/llvm/rust-llvm-reports/closures/coverage.json diff --git a/testsuite/tests/llvm/rust/closures/src/closures.rs b/testsuite/tests/llvm/rust-llvm-reports/closures/src/closures.rs similarity index 100% rename from testsuite/tests/llvm/rust/closures/src/closures.rs rename to testsuite/tests/llvm/rust-llvm-reports/closures/src/closures.rs diff --git a/testsuite/tests/llvm/rust/closures/test.py b/testsuite/tests/llvm/rust-llvm-reports/closures/test.py similarity index 100% rename from testsuite/tests/llvm/rust/closures/test.py rename to testsuite/tests/llvm/rust-llvm-reports/closures/test.py diff --git a/testsuite/tests/llvm/rust/diff_formatting/coverage.json b/testsuite/tests/llvm/rust-llvm-reports/diff_formatting/coverage.json similarity index 100% rename from testsuite/tests/llvm/rust/diff_formatting/coverage.json rename to testsuite/tests/llvm/rust-llvm-reports/diff_formatting/coverage.json diff --git a/testsuite/tests/llvm/rust/diff_formatting/src/diff_formatting.rs b/testsuite/tests/llvm/rust-llvm-reports/diff_formatting/src/diff_formatting.rs similarity index 100% rename from testsuite/tests/llvm/rust/diff_formatting/src/diff_formatting.rs rename to testsuite/tests/llvm/rust-llvm-reports/diff_formatting/src/diff_formatting.rs diff --git a/testsuite/tests/llvm/rust/diff_formatting/test.py b/testsuite/tests/llvm/rust-llvm-reports/diff_formatting/test.py similarity index 100% rename from testsuite/tests/llvm/rust/diff_formatting/test.py rename to testsuite/tests/llvm/rust-llvm-reports/diff_formatting/test.py diff --git a/testsuite/tests/llvm/rust/impl/coverage.json b/testsuite/tests/llvm/rust-llvm-reports/impl/coverage.json similarity index 100% rename from testsuite/tests/llvm/rust/impl/coverage.json rename to testsuite/tests/llvm/rust-llvm-reports/impl/coverage.json diff --git a/testsuite/tests/llvm/rust/impl/src/impl.rs b/testsuite/tests/llvm/rust-llvm-reports/impl/src/impl.rs similarity index 100% rename from testsuite/tests/llvm/rust/impl/src/impl.rs rename to testsuite/tests/llvm/rust-llvm-reports/impl/src/impl.rs diff --git a/testsuite/tests/llvm/rust/impl/test.py b/testsuite/tests/llvm/rust-llvm-reports/impl/test.py similarity index 100% rename from testsuite/tests/llvm/rust/impl/test.py rename to testsuite/tests/llvm/rust-llvm-reports/impl/test.py diff --git a/testsuite/tests/llvm/rust/mcdc_nested/coverage.json b/testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/coverage.json similarity index 100% rename from testsuite/tests/llvm/rust/mcdc_nested/coverage.json rename to testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/coverage.json diff --git a/testsuite/tests/llvm/rust/mcdc_nested/src/mcdc_nested.rs b/testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/src/mcdc_nested.rs similarity index 100% rename from testsuite/tests/llvm/rust/mcdc_nested/src/mcdc_nested.rs rename to testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/src/mcdc_nested.rs diff --git a/testsuite/tests/llvm/rust/mcdc_nested/test.py b/testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/test.py similarity index 100% rename from testsuite/tests/llvm/rust/mcdc_nested/test.py rename to testsuite/tests/llvm/rust-llvm-reports/mcdc_nested/test.py diff --git a/testsuite/tests/llvm/rust/mcdc_non_control_flow/coverage.json b/testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/coverage.json similarity index 100% rename from testsuite/tests/llvm/rust/mcdc_non_control_flow/coverage.json rename to testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/coverage.json diff --git a/testsuite/tests/llvm/rust/mcdc_non_control_flow/src/mcdc_assign.rs b/testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/src/mcdc_assign.rs similarity index 100% rename from testsuite/tests/llvm/rust/mcdc_non_control_flow/src/mcdc_assign.rs rename to testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/src/mcdc_assign.rs diff --git a/testsuite/tests/llvm/rust/mcdc_non_control_flow/test.py b/testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/test.py similarity index 100% rename from testsuite/tests/llvm/rust/mcdc_non_control_flow/test.py rename to testsuite/tests/llvm/rust-llvm-reports/mcdc_non_control_flow/test.py From 71e231b2192abb96b5375a953cadd11e6f4052e5 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 8 Jul 2025 17:58:44 +0200 Subject: [PATCH 1358/1483] tests: add rust test for statement coverage over if expr --- .../{rust-full-pipeline => rust}/extra.opt | 0 .../llvm/rust/stmt/block-expr/src/foo.rs | 15 +++++++++ .../rust/stmt/block-expr/src/test_let_else.rs | 9 ++++++ .../block-expr/src/test_let_else_in_else.rs | 9 ++++++ .../tests/llvm/rust/stmt/block-expr/test.py | 9 ++++++ .../llvm/rust/stmt/break-block/src/foo.rs | 12 +++++++ .../stmt/break-block/src/test_break_block.rs | 8 +++++ .../break-block/src/test_break_block_exit.rs | 9 ++++++ .../tests/llvm/rust/stmt/break-block/test.py | 9 ++++++ .../tests/llvm/rust/stmt/closure/src/foo.rs | 14 ++++++++ .../stmt/closure/src/test_closure_called.rs | 12 +++++++ .../closure/src/test_closure_not_called.rs | 15 +++++++++ .../tests/llvm/rust/stmt/closure/test.py | 9 ++++++ .../tests/llvm/rust/stmt/if-expr/src/foo.rs | 12 +++++++ .../llvm/rust/stmt/if-expr/src/test_both.rs | 9 ++++++ .../llvm/rust/stmt/if-expr/src/test_false.rs | 10 ++++++ .../llvm/rust/stmt/if-expr/src/test_none.rs | 7 ++++ .../llvm/rust/stmt/if-expr/src/test_true.rs | 10 ++++++ .../tests/llvm/rust/stmt/if-expr/test.py | 9 ++++++ .../tests/llvm/rust/stmt/let-else/src/foo.rs | 19 +++++++++++ .../rust/stmt/let-else/src/test_let_else.rs | 9 ++++++ .../let-else/src/test_let_else_in_else.rs | 10 ++++++ .../tests/llvm/rust/stmt/let-else/test.py | 9 ++++++ .../tests/llvm/rust/stmt/let-stmt/src/foo.rs | 3 ++ .../rust/stmt/let-stmt/src/test_let_stmt.rs | 8 +++++ .../stmt/let-stmt}/test.py | 0 .../llvm/rust/stmt/loops/for-loop/src/foo.rs | 32 +++++++++++++++++++ .../for-loop/src/test_for_loop_entered.rs | 9 ++++++ .../for-loop/src/test_for_loop_not_entered.rs | 12 +++++++ .../for-loop/src/test_for_loop_not_reached.rs | 14 ++++++++ .../llvm/rust/stmt/loops/for-loop/test.py | 9 ++++++ .../rust/stmt/loops/named-loop/src/foo.rs | 14 ++++++++ .../named-loop/src/test_named_loop_entered.rs | 8 +++++ .../src/test_named_loop_not_entered.rs | 10 ++++++ .../src/test_named_loop_not_reached.rs | 12 +++++++ .../llvm/rust/stmt/loops/named-loop/test.py | 9 ++++++ .../rust/stmt/loops/while-loop/src/foo.rs | 12 +++++++ .../while-loop/src/test_while_loop_entered.rs | 8 +++++ .../src/test_while_loop_not_entered.rs | 10 ++++++ .../src/test_while_loop_not_reached.rs | 11 +++++++ .../llvm/rust/stmt/loops/while-loop/test.py | 9 ++++++ .../llvm/rust/stmt/match-expr/src/foo.rs | 14 ++++++++ .../stmt/match-expr/src/test_match_binding.rs | 9 ++++++ .../stmt/match-expr/src/test_match_literal.rs | 11 +++++++ .../stmt/match-expr/src/test_match_none.rs | 10 ++++++ .../stmt/match-expr/src/test_match_range.rs | 11 +++++++ .../tests/llvm/rust/stmt/match-expr/test.py | 9 ++++++ .../stmt/simple-stmt/src/foo.rs | 0 .../stmt/simple-stmt/src/test_call_foo.rs | 0 .../stmt/simple-stmt/src/test_no_call_foo.rs | 0 .../tests/llvm/rust/stmt/simple-stmt/test.py | 9 ++++++ .../llvm/rust/stmt/try-operator/src/foo.rs | 9 ++++++ .../stmt/try-operator/src/test_try_op_none.rs | 10 ++++++ .../stmt/try-operator/src/test_try_op_some.rs | 8 +++++ .../tests/llvm/rust/stmt/try-operator/test.py | 9 ++++++ 55 files changed, 533 insertions(+) rename testsuite/tests/llvm/{rust-full-pipeline => rust}/extra.opt (100%) create mode 100644 testsuite/tests/llvm/rust/stmt/block-expr/src/foo.rs create mode 100644 testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else.rs create mode 100644 testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else_in_else.rs create mode 100644 testsuite/tests/llvm/rust/stmt/block-expr/test.py create mode 100644 testsuite/tests/llvm/rust/stmt/break-block/src/foo.rs create mode 100644 testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block.rs create mode 100644 testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block_exit.rs create mode 100644 testsuite/tests/llvm/rust/stmt/break-block/test.py create mode 100644 testsuite/tests/llvm/rust/stmt/closure/src/foo.rs create mode 100644 testsuite/tests/llvm/rust/stmt/closure/src/test_closure_called.rs create mode 100644 testsuite/tests/llvm/rust/stmt/closure/src/test_closure_not_called.rs create mode 100644 testsuite/tests/llvm/rust/stmt/closure/test.py create mode 100644 testsuite/tests/llvm/rust/stmt/if-expr/src/foo.rs create mode 100644 testsuite/tests/llvm/rust/stmt/if-expr/src/test_both.rs create mode 100644 testsuite/tests/llvm/rust/stmt/if-expr/src/test_false.rs create mode 100644 testsuite/tests/llvm/rust/stmt/if-expr/src/test_none.rs create mode 100644 testsuite/tests/llvm/rust/stmt/if-expr/src/test_true.rs create mode 100644 testsuite/tests/llvm/rust/stmt/if-expr/test.py create mode 100644 testsuite/tests/llvm/rust/stmt/let-else/src/foo.rs create mode 100644 testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else.rs create mode 100644 testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else_in_else.rs create mode 100644 testsuite/tests/llvm/rust/stmt/let-else/test.py create mode 100644 testsuite/tests/llvm/rust/stmt/let-stmt/src/foo.rs create mode 100644 testsuite/tests/llvm/rust/stmt/let-stmt/src/test_let_stmt.rs rename testsuite/tests/llvm/{rust-full-pipeline/stmt/simple-stmt => rust/stmt/let-stmt}/test.py (100%) create mode 100644 testsuite/tests/llvm/rust/stmt/loops/for-loop/src/foo.rs create mode 100644 testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_entered.rs create mode 100644 testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_entered.rs create mode 100644 testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_reached.rs create mode 100644 testsuite/tests/llvm/rust/stmt/loops/for-loop/test.py create mode 100644 testsuite/tests/llvm/rust/stmt/loops/named-loop/src/foo.rs create mode 100644 testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_entered.rs create mode 100644 testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_entered.rs create mode 100644 testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_reached.rs create mode 100644 testsuite/tests/llvm/rust/stmt/loops/named-loop/test.py create mode 100644 testsuite/tests/llvm/rust/stmt/loops/while-loop/src/foo.rs create mode 100644 testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_entered.rs create mode 100644 testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_entered.rs create mode 100644 testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_reached.rs create mode 100644 testsuite/tests/llvm/rust/stmt/loops/while-loop/test.py create mode 100644 testsuite/tests/llvm/rust/stmt/match-expr/src/foo.rs create mode 100644 testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_binding.rs create mode 100644 testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_literal.rs create mode 100644 testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_none.rs create mode 100644 testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_range.rs create mode 100644 testsuite/tests/llvm/rust/stmt/match-expr/test.py rename testsuite/tests/llvm/{rust-full-pipeline => rust}/stmt/simple-stmt/src/foo.rs (100%) rename testsuite/tests/llvm/{rust-full-pipeline => rust}/stmt/simple-stmt/src/test_call_foo.rs (100%) rename testsuite/tests/llvm/{rust-full-pipeline => rust}/stmt/simple-stmt/src/test_no_call_foo.rs (100%) create mode 100644 testsuite/tests/llvm/rust/stmt/simple-stmt/test.py create mode 100644 testsuite/tests/llvm/rust/stmt/try-operator/src/foo.rs create mode 100644 testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_none.rs create mode 100644 testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_some.rs create mode 100644 testsuite/tests/llvm/rust/stmt/try-operator/test.py diff --git a/testsuite/tests/llvm/rust-full-pipeline/extra.opt b/testsuite/tests/llvm/rust/extra.opt similarity index 100% rename from testsuite/tests/llvm/rust-full-pipeline/extra.opt rename to testsuite/tests/llvm/rust/extra.opt diff --git a/testsuite/tests/llvm/rust/stmt/block-expr/src/foo.rs b/testsuite/tests/llvm/rust/stmt/block-expr/src/foo.rs new file mode 100644 index 000000000..9cbe62183 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/block-expr/src/foo.rs @@ -0,0 +1,15 @@ +pub fn let_else(input: Option) { + + // Let statements is covered if the assignement happens, meaning it was not + // short-circuited by a an error in the expression evaluation. + // + // In the `let-else` case, the statement is covered if the pattern matching + // succeeds. In that case, it means the else block is not executed, thus + // not covered. In the other case, the else block shall be executed (and + // covered), whereas the let statement won't. + + let Some(_x) = input else { // # let + println!("No input"); // # in-else-1 + return; // # in-else + }; +} diff --git a/testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else.rs b/testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else.rs new file mode 100644 index 000000000..dd691d9fd --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + let _ = foo::let_else(Some(42)); +} + +//# foo.rs +// /in-else-1/ l= ## s- +// /in-else/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else_in_else.rs b/testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else_in_else.rs new file mode 100644 index 000000000..19cadd2c4 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/block-expr/src/test_let_else_in_else.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + let _ = foo::let_else(None); +} + +//# foo.rs +// /let/ l! ## s- +// /in-else/ l+ ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/block-expr/test.py b/testsuite/tests/llvm/rust/stmt/block-expr/test.py new file mode 100644 index 000000000..51f041da9 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/block-expr/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for a simple code block +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/break-block/src/foo.rs b/testsuite/tests/llvm/rust/stmt/break-block/src/foo.rs new file mode 100644 index 000000000..133060596 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/break-block/src/foo.rs @@ -0,0 +1,12 @@ +use std::hint::black_box; + +pub fn foo(input: u32) { + 'named_block: { + let _ = black_box(1); + if input == 42 { + break 'named_block; // # break + } // # bb2-1 + let _ = black_box(2); // # bb2 + } + let _ = black_box(3); +} diff --git a/testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block.rs b/testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block.rs new file mode 100644 index 000000000..14796a87d --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block.rs @@ -0,0 +1,8 @@ +mod foo; + +fn main() { + let _ = foo::foo(0); +} + +//# foo.rs +// /break/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block_exit.rs b/testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block_exit.rs new file mode 100644 index 000000000..e5b75ad07 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/break-block/src/test_break_block_exit.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + let _ = foo::foo(42); +} + +//# foo.rs +// /bb2-1/ l= ## s- +// /bb2/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/break-block/test.py b/testsuite/tests/llvm/rust/stmt/break-block/test.py new file mode 100644 index 000000000..86e6827eb --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/break-block/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for break in named blocks +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/closure/src/foo.rs b/testsuite/tests/llvm/rust/stmt/closure/src/foo.rs new file mode 100644 index 000000000..22ab0c56c --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/closure/src/foo.rs @@ -0,0 +1,14 @@ +use std::hint::black_box; + +pub fn foo(input: u32) { + let print_even = // # var + |i| { // # closure-arg + if i % 2 == 0 { // # closure-if-guard + black_box(i); // # closure-body + } // # closure-else + }; // # closure-end + + if input < 10 { // # if-guard + print_even(input); // # call + } // # else +} diff --git a/testsuite/tests/llvm/rust/stmt/closure/src/test_closure_called.rs b/testsuite/tests/llvm/rust/stmt/closure/src/test_closure_called.rs new file mode 100644 index 000000000..a947c51fb --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/closure/src/test_closure_called.rs @@ -0,0 +1,12 @@ +mod foo; + +fn main() { + let _ = foo::foo(5); +} + +//# foo.rs +// /closure-arg/ l= ## 0 +// /closure-if-guard/ l! ## s- +// /closure-else/ l! ## 0 +// /closure-body/ l- ## 0 +// /else/ l! ## s- diff --git a/testsuite/tests/llvm/rust/stmt/closure/src/test_closure_not_called.rs b/testsuite/tests/llvm/rust/stmt/closure/src/test_closure_not_called.rs new file mode 100644 index 000000000..2461f06a9 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/closure/src/test_closure_not_called.rs @@ -0,0 +1,15 @@ +mod foo; + +fn main() { + let _ = foo::foo(42); +} + +//# foo.rs +// /closure-arg/ l= ## s- +// /closure-if-guard/ l= ## s- +// /closure-else/ l= ## s- +// /closure-end/ l= ## s- +// /closure/ l- ## 0 +// /if-guard/ l! ## s- +// /call/ l- ## 0 +// /else/ l! ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/closure/test.py b/testsuite/tests/llvm/rust/stmt/closure/test.py new file mode 100644 index 000000000..8455ea09c --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/closure/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for closures +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/if-expr/src/foo.rs b/testsuite/tests/llvm/rust/stmt/if-expr/src/foo.rs new file mode 100644 index 000000000..a3da6ddb3 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/if-expr/src/foo.rs @@ -0,0 +1,12 @@ +use std::hint::black_box; + +pub fn foo(b: bool) { // # decl-1 + if b // # condition + { // # if-1 + black_box(1); // # if + } // # if + else + { // # else-1 + black_box(2); // # else + } // # else +} // # end-1 diff --git a/testsuite/tests/llvm/rust/stmt/if-expr/src/test_both.rs b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_both.rs new file mode 100644 index 000000000..2b33a73a6 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_both.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + foo::foo(true); + foo::foo(false); +} + +//# foo.rs +// /.*/ l+ ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/if-expr/src/test_false.rs b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_false.rs new file mode 100644 index 000000000..6f8a2029e --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_false.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + foo::foo(false); +} + +//# foo.rs +// /if-1/ l= ## s- +// /if/ l- ## 0 +// /(?!if)/ l+ ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/if-expr/src/test_none.rs b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_none.rs new file mode 100644 index 000000000..628a3c822 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_none.rs @@ -0,0 +1,7 @@ +mod foo; + +fn main() {} + +//# foo.rs +// /.*-1/ l= ## s- +// /.*/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/if-expr/src/test_true.rs b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_true.rs new file mode 100644 index 000000000..984ee261c --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/if-expr/src/test_true.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + foo::foo(true); +} + +//# foo.rs +// /else-1/ l= ## s- +// /else/ l- ## 0 +// /(?!else)/ l+ ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/if-expr/test.py b/testsuite/tests/llvm/rust/stmt/if-expr/test.py new file mode 100644 index 000000000..1fd448fe8 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/if-expr/test.py @@ -0,0 +1,9 @@ +""" +Check behavior for the coverage of an if expression +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/let-else/src/foo.rs b/testsuite/tests/llvm/rust/stmt/let-else/src/foo.rs new file mode 100644 index 000000000..421926f79 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/let-else/src/foo.rs @@ -0,0 +1,19 @@ +use std::hint::black_box; + +pub fn let_else(input: Option) { + + // Let statements is covered if the assignement happens, meaning it was not + // short-circuited by a an error in the expression evaluation. + // + // In the `let-else` case, the statement is covered if the pattern matching + // succeeds. In that case, it means the else block is not executed, thus + // not covered. In the other case, the else block shall be executed (and + // covered), whereas the let statement won't. + + let Some(x) = input else { // # let + println!("No input"); // # in-else-1 + return; // # in-else + }; + + black_box(x); // # black-box +} diff --git a/testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else.rs b/testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else.rs new file mode 100644 index 000000000..dd691d9fd --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + let _ = foo::let_else(Some(42)); +} + +//# foo.rs +// /in-else-1/ l= ## s- +// /in-else/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else_in_else.rs b/testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else_in_else.rs new file mode 100644 index 000000000..a5e897e5a --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/let-else/src/test_let_else_in_else.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + let _ = foo::let_else(None); +} + +//# foo.rs +// /let/ l! ## s- +// /in-else/ l+ ## 0 +// /black-box/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/let-else/test.py b/testsuite/tests/llvm/rust/stmt/let-else/test.py new file mode 100644 index 000000000..faf4bd337 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/let-else/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for let-else construct +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/let-stmt/src/foo.rs b/testsuite/tests/llvm/rust/stmt/let-stmt/src/foo.rs new file mode 100644 index 000000000..e54e7764e --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/let-stmt/src/foo.rs @@ -0,0 +1,3 @@ +pub fn let_stmt() { // # let_stmt-1 + let x: u32 = 42; // # let_stmt +} // # let_stmt diff --git a/testsuite/tests/llvm/rust/stmt/let-stmt/src/test_let_stmt.rs b/testsuite/tests/llvm/rust/stmt/let-stmt/src/test_let_stmt.rs new file mode 100644 index 000000000..d397e0681 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/let-stmt/src/test_let_stmt.rs @@ -0,0 +1,8 @@ +mod foo; + +fn main() { + foo::let_stmt(); +} + +//# foo.rs +// /let_stmt/ l+ ## 0 diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/test.py b/testsuite/tests/llvm/rust/stmt/let-stmt/test.py similarity index 100% rename from testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/test.py rename to testsuite/tests/llvm/rust/stmt/let-stmt/test.py diff --git a/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/foo.rs b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/foo.rs new file mode 100644 index 000000000..adad1d1f8 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/foo.rs @@ -0,0 +1,32 @@ +use std::hint::black_box; + +// In for loops, the variable has its own SCO, which is covered by assignment. +// In case the iterator given to the loop is empty, this SCO is never covered. +// However, if the variable name is `_`, meaning the value produced by the +// iterator is unbound, there is no associated SCO. +// Additionally, if the variable is bound, a SCO is made for the iterator. +// Otherwise, it is attached in the SCO preceding the for loop. + +pub fn foo(input: u32) { + if input > 10 { + return; // # return + } // # after-if-1 + for // # after-if + _ // # after-if + in 0 .. input // # after-if + { // # body-1 + black_box(1); // # body + } // # body +} + +pub fn bar(input: u32) { + if input > 10 { + return; // # return + } // # after-if-1 + for + i // # var + in 0 .. input // # guard + { // # body-1 + black_box(i); // # body + } // # body +} diff --git a/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_entered.rs b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_entered.rs new file mode 100644 index 000000000..939da805a --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_entered.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + let _ = foo::foo(5); + let _ = foo::bar(5); +} + +//# foo.rs +// /return/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_entered.rs b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_entered.rs new file mode 100644 index 000000000..5a1eb05a7 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_entered.rs @@ -0,0 +1,12 @@ +mod foo; + +fn main() { + let _ = foo::foo(0); + let _ = foo::bar(0); +} + +//# foo.rs +// /return/ l- ## s- +// /var/ l- ## s- +// /body-1/ l= ## s- +// /body/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_reached.rs b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_reached.rs new file mode 100644 index 000000000..86997058a --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/for-loop/src/test_for_loop_not_reached.rs @@ -0,0 +1,14 @@ +mod foo; + +fn main() { + let _ = foo::foo(11); + let _ = foo::bar(11); +} + +//# foo.rs +// /after-if-1/ l= ## s- +// /after-if/ l- ## 0 +// /var/ l- ## s- +// /guard/ l- ## s- +// /body-1/ l= ## s- +// /body/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/loops/for-loop/test.py b/testsuite/tests/llvm/rust/stmt/loops/for-loop/test.py new file mode 100644 index 000000000..2345940f4 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/for-loop/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for for loops +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/foo.rs b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/foo.rs new file mode 100644 index 000000000..0d37caf90 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/foo.rs @@ -0,0 +1,14 @@ +use std::hint::black_box; + +pub fn foo(mut input: u32) { + if input > 10 { + return; // # return + } // # after-if-1 + 'named: loop { + if input == 0 { // # if + break 'named; // # break + } // # body-1 + black_box(input); // # body + input -= 1; // # body + } +} diff --git a/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_entered.rs b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_entered.rs new file mode 100644 index 000000000..f7a8f120e --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_entered.rs @@ -0,0 +1,8 @@ +mod foo; + +fn main() { + let _ = foo::foo(5); +} + +//# foo.rs +// /return/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_entered.rs b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_entered.rs new file mode 100644 index 000000000..78b042904 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_entered.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + let _ = foo::foo(0); +} + +//# foo.rs +// /return/ l- ## s- +// /body-1/ l= ## s- +// /body/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_reached.rs b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_reached.rs new file mode 100644 index 000000000..3a94065c4 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/named-loop/src/test_named_loop_not_reached.rs @@ -0,0 +1,12 @@ +mod foo; + +fn main() { + let _ = foo::foo(11); +} + +//# foo.rs +// /after-if-1/ l- ## s- +// /if/ l- ## s- +// /break/ l- ## s- +// /body-1/ l= ## s- +// /body/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/loops/named-loop/test.py b/testsuite/tests/llvm/rust/stmt/loops/named-loop/test.py new file mode 100644 index 000000000..47d14d5b7 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/named-loop/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for named loops +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/foo.rs b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/foo.rs new file mode 100644 index 000000000..305030ffb --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/foo.rs @@ -0,0 +1,12 @@ +use std::hint::black_box; + +pub fn foo(mut input: u32) { + if input > 10 { + return; // # return + } // # after-if-1 + while input > 0 // # guard + { // # body-1 + black_box(input); // # body + input -= 1; // # body + } // # body +} diff --git a/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_entered.rs b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_entered.rs new file mode 100644 index 000000000..f7a8f120e --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_entered.rs @@ -0,0 +1,8 @@ +mod foo; + +fn main() { + let _ = foo::foo(5); +} + +//# foo.rs +// /return/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_entered.rs b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_entered.rs new file mode 100644 index 000000000..78b042904 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_entered.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + let _ = foo::foo(0); +} + +//# foo.rs +// /return/ l- ## s- +// /body-1/ l= ## s- +// /body/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_reached.rs b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_reached.rs new file mode 100644 index 000000000..6a7930c41 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/while-loop/src/test_while_loop_not_reached.rs @@ -0,0 +1,11 @@ +mod foo; + +fn main() { + let _ = foo::foo(11); +} + +//# foo.rs +// /after-if-1/ l- ## s- +// /guard/ l- ## s- +// /body-1/ l= ## s- +// /body/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/loops/while-loop/test.py b/testsuite/tests/llvm/rust/stmt/loops/while-loop/test.py new file mode 100644 index 000000000..9af6a8dc1 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/loops/while-loop/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for while loops +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/match-expr/src/foo.rs b/testsuite/tests/llvm/rust/stmt/match-expr/src/foo.rs new file mode 100644 index 000000000..33634a1f0 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/match-expr/src/foo.rs @@ -0,0 +1,14 @@ +use std::hint::black_box; + +pub fn foo(input: Option) { + let _ = match input { + Some(5) => // # some-5 + black_box(5), // # body-some-5 + Some(0..=4) => // # some-range + black_box(1), // # body-some-range + Some(i) => // # some-i + black_box(i), // # body-some-i + None => // # none + black_box(1) // # body-none + }; +} diff --git a/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_binding.rs b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_binding.rs new file mode 100644 index 000000000..664437e0c --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_binding.rs @@ -0,0 +1,9 @@ +mod foo; + +fn main() { + let _ = foo::foo(Some(30)); +} + +//# foo.rs +// /body-some-[^i]/ l- ## s- +// /body-none/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_literal.rs b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_literal.rs new file mode 100644 index 000000000..436f55e01 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_literal.rs @@ -0,0 +1,11 @@ +mod foo; + +fn main() { + let _ = foo::foo(Some(5)); +} + +//# foo.rs +// /some-\D/ l- ## s- +// /body-some-range/ l- ## s- +// /body-some-i/ l- ## 0 +// /body-none/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_none.rs b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_none.rs new file mode 100644 index 000000000..68e63c35e --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_none.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + let _ = foo::foo(None); +} + +//# foo.rs +// /some-\D/ l- ## s- +// /body-some-[^i]/ l= ## s- +// /body-some/ l- ## 0 diff --git a/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_range.rs b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_range.rs new file mode 100644 index 000000000..89b823df8 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/match-expr/src/test_match_range.rs @@ -0,0 +1,11 @@ +mod foo; + +fn main() { + let _ = foo::foo(Some(3)); +} + +//# foo.rs +// /body-some-5/ l- ## s- +// /some-i/ l- ## s- +// /body-some-i/ l- ## 0 +// /body-none/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/match-expr/test.py b/testsuite/tests/llvm/rust/stmt/match-expr/test.py new file mode 100644 index 000000000..5cbbdbdd4 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/match-expr/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for match expressions +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/foo.rs b/testsuite/tests/llvm/rust/stmt/simple-stmt/src/foo.rs similarity index 100% rename from testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/foo.rs rename to testsuite/tests/llvm/rust/stmt/simple-stmt/src/foo.rs diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/test_call_foo.rs b/testsuite/tests/llvm/rust/stmt/simple-stmt/src/test_call_foo.rs similarity index 100% rename from testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/test_call_foo.rs rename to testsuite/tests/llvm/rust/stmt/simple-stmt/src/test_call_foo.rs diff --git a/testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/test_no_call_foo.rs b/testsuite/tests/llvm/rust/stmt/simple-stmt/src/test_no_call_foo.rs similarity index 100% rename from testsuite/tests/llvm/rust-full-pipeline/stmt/simple-stmt/src/test_no_call_foo.rs rename to testsuite/tests/llvm/rust/stmt/simple-stmt/src/test_no_call_foo.rs diff --git a/testsuite/tests/llvm/rust/stmt/simple-stmt/test.py b/testsuite/tests/llvm/rust/stmt/simple-stmt/test.py new file mode 100644 index 000000000..8e5fc2289 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/simple-stmt/test.py @@ -0,0 +1,9 @@ +""" +Ensure a simple 1 statement function is correctly covered. +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/testsuite/tests/llvm/rust/stmt/try-operator/src/foo.rs b/testsuite/tests/llvm/rust/stmt/try-operator/src/foo.rs new file mode 100644 index 000000000..a0db67940 --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/try-operator/src/foo.rs @@ -0,0 +1,9 @@ +// The try '?' operator induces an implicit break of the control flow. +// Therefore, at instrumentation, Rust inserts a counter at the beginning of +// the function, one for the short-circuit of `?`, and one after the evaluation +// of '?'. + +pub fn foo(input: Option) -> Option { // # fn + let number = input?; // # try + return Some(number.to_string()); // # return +} diff --git a/testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_none.rs b/testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_none.rs new file mode 100644 index 000000000..fa7ab7c5e --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_none.rs @@ -0,0 +1,10 @@ +mod foo; + +fn main() { + let _ = foo::foo(None); +} + +//# foo.rs +// /fn/ l+ ## 0 +// /try/ l! ## s- +// /return/ l- ## s- diff --git a/testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_some.rs b/testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_some.rs new file mode 100644 index 000000000..1b1b49e4a --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/try-operator/src/test_try_op_some.rs @@ -0,0 +1,8 @@ +mod foo; + +fn main() { + let _ = foo::foo(Some(42)); +} + +//# foo.rs +// /try/ l! ## s- diff --git a/testsuite/tests/llvm/rust/stmt/try-operator/test.py b/testsuite/tests/llvm/rust/stmt/try-operator/test.py new file mode 100644 index 000000000..bd7d9d3fd --- /dev/null +++ b/testsuite/tests/llvm/rust/stmt/try-operator/test.py @@ -0,0 +1,9 @@ +""" +Check coverage behavior for try operators +""" + +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() From ec81e9c264dc9c7d59c78783a08a4cb720f5227f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 10 Jul 2025 09:06:38 +0200 Subject: [PATCH 1359/1483] Add a test for the Ada 2022 @ lhs reference shortcut --- .../tests/Ada2022/lhs-shortcut/src/foo.adb | 9 +++++++++ .../tests/Ada2022/lhs-shortcut/src/test_0.adb | 10 ++++++++++ .../Ada2022/lhs-shortcut/src/test_full.adb | 14 ++++++++++++++ .../Ada2022/lhs-shortcut/src/test_part.adb | 13 +++++++++++++ testsuite/tests/Ada2022/lhs-shortcut/test.py | 17 +++++++++++++++++ 5 files changed, 63 insertions(+) create mode 100644 testsuite/tests/Ada2022/lhs-shortcut/src/foo.adb create mode 100644 testsuite/tests/Ada2022/lhs-shortcut/src/test_0.adb create mode 100644 testsuite/tests/Ada2022/lhs-shortcut/src/test_full.adb create mode 100644 testsuite/tests/Ada2022/lhs-shortcut/src/test_part.adb create mode 100644 testsuite/tests/Ada2022/lhs-shortcut/test.py diff --git a/testsuite/tests/Ada2022/lhs-shortcut/src/foo.adb b/testsuite/tests/Ada2022/lhs-shortcut/src/foo.adb new file mode 100644 index 000000000..349ad50c9 --- /dev/null +++ b/testsuite/tests/Ada2022/lhs-shortcut/src/foo.adb @@ -0,0 +1,9 @@ +pragma Ada_2022; + +procedure Foo (B, C : Boolean) is + A : Boolean := B; -- # stmt +begin + A := @; -- # stmt + A := (if @ then @ else @) ; -- # dec + A := (if @ or else C then @ else @); -- # mcdc +end Foo; diff --git a/testsuite/tests/Ada2022/lhs-shortcut/src/test_0.adb b/testsuite/tests/Ada2022/lhs-shortcut/src/test_0.adb new file mode 100644 index 000000000..1ce9b62c3 --- /dev/null +++ b/testsuite/tests/Ada2022/lhs-shortcut/src/test_0.adb @@ -0,0 +1,10 @@ +procedure Test_0 is +begin + null; +end Test_0; + +--# foo.adb +-- +-- /stmt/ l- ## s- +-- /dec/ l- ## s- +-- /mcdc/ l- ## s- diff --git a/testsuite/tests/Ada2022/lhs-shortcut/src/test_full.adb b/testsuite/tests/Ada2022/lhs-shortcut/src/test_full.adb new file mode 100644 index 000000000..887345df1 --- /dev/null +++ b/testsuite/tests/Ada2022/lhs-shortcut/src/test_full.adb @@ -0,0 +1,14 @@ +with Foo; + +procedure Test_Full is +begin + Foo (False, False); + Foo (True, False); + Foo (False, True); +end Test_Full; + +--# foo.adb +-- +-- /stmt/ l+ ## 0 +-- /dec/ l+ ## 0 +-- /mcdc/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/lhs-shortcut/src/test_part.adb b/testsuite/tests/Ada2022/lhs-shortcut/src/test_part.adb new file mode 100644 index 000000000..293f6fea6 --- /dev/null +++ b/testsuite/tests/Ada2022/lhs-shortcut/src/test_part.adb @@ -0,0 +1,13 @@ +with Foo; + +procedure Test_Part is +begin + Foo (False, False); + Foo (True, False); +end Test_Part; + +--# foo.adb +-- +-- /stmt/ l+ ## 0 +-- /dec/ l+ ## 0 +-- /mcdc/ l! ## c! diff --git a/testsuite/tests/Ada2022/lhs-shortcut/test.py b/testsuite/tests/Ada2022/lhs-shortcut/test.py new file mode 100644 index 000000000..81234afa2 --- /dev/null +++ b/testsuite/tests/Ada2022/lhs-shortcut/test.py @@ -0,0 +1,17 @@ +""" +Test correct support for @, the LHS reference shortcut: + - It is correctly instrumented when it is in an expression operand of an + initialization statement, without control flow. + - It is correctly instrumented when featured as the decision of an if + expression. + - It is correctly instrumented when featured as a boolean operand of an if + expression. +""" + +from SCOV.tc import TestCase +from SCOV.tctl import CAT +from SUITE.context import thistest + + +TestCase(category=CAT.mcdc).run() +thistest.result() From 27c0fbc028c97ecd07980493bf62f0e4e9217df6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 18 Aug 2025 11:18:22 +0200 Subject: [PATCH 1360/1483] Revert "instr-cov/239-qnx-bin-file: add XFAIL" This reverts commit 3d1cf37d1f0e95b2db784b6e0029dee8ef4dba1f. --- testsuite/tests/instr-cov/239-qnx-bin-file/test.opt | 1 - 1 file changed, 1 deletion(-) diff --git a/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt b/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt index 083fe6f22..1dedc665b 100644 --- a/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt +++ b/testsuite/tests/instr-cov/239-qnx-bin-file/test.opt @@ -4,4 +4,3 @@ -- target. src-traces,qnx,RTS_LIGHT_TASKING ALL DEAD -src-traces,qnx,RTS_LIGHT_TASKING XFAIL See eng/toolchain/pycross#227 From fa2f75268880c66078be3a3617766de391774fd0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 19 Aug 2025 08:48:42 +0000 Subject: [PATCH 1361/1483] integrated_instr_cross/basic_C: kill for morello-elf --- testsuite/tests/integrated_instr_cross/basic_C/test.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/integrated_instr_cross/basic_C/test.opt b/testsuite/tests/integrated_instr_cross/basic_C/test.opt index eeb5746be..1ddcc4440 100644 --- a/testsuite/tests/integrated_instr_cross/basic_C/test.opt +++ b/testsuite/tests/integrated_instr_cross/basic_C/test.opt @@ -1,2 +1,3 @@ !bareboard DEAD This test relies on examples specific to bareboard targets +morello-elf DEAD No BSP provided with this toolchain leon3-elf XFAIL Linker cannot find fwrite (to be investigated) From 37a6da5becfc3b3cef68f231394bd2d641941cf6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 19 Aug 2025 12:24:35 +0000 Subject: [PATCH 1362/1483] Ada2022/aggregates/containers: adjust test.opt to kill for RTS_ZFP `ALL XFAIL` takes precedence over ` DEAD`, whereas here we meant the DEAD to take precedence for non-ZFP platforms. --- testsuite/tests/Ada2022/aggregates/containers/test.opt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/Ada2022/aggregates/containers/test.opt b/testsuite/tests/Ada2022/aggregates/containers/test.opt index acbe4e495..a1cf1aaea 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/test.opt +++ b/testsuite/tests/Ada2022/aggregates/containers/test.opt @@ -1,2 +1,2 @@ RTS_ZFP DEAD Test instantiates containers -all XFAIL Compiler crash (eng/toolchain/gnat#1516) +!RTS_ZFP XFAIL Compiler crash (eng/toolchain/gnat#1516) From f1d4c0052d786f1045fe859a5dbf96d75c51a6ca Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 19 Aug 2025 12:26:23 +0000 Subject: [PATCH 1363/1483] Ada2022/aggregates/containers: adjust GNAT bug reference --- testsuite/tests/Ada2022/aggregates/containers/test.opt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/Ada2022/aggregates/containers/test.opt b/testsuite/tests/Ada2022/aggregates/containers/test.opt index a1cf1aaea..84bd4b77f 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/test.opt +++ b/testsuite/tests/Ada2022/aggregates/containers/test.opt @@ -1,2 +1,2 @@ RTS_ZFP DEAD Test instantiates containers -!RTS_ZFP XFAIL Compiler crash (eng/toolchain/gnat#1516) +!RTS_ZFP XFAIL Compiler crash (eng/toolchain/gnat#1543) From 691cbc0046eeaa817fa485f582a7172951ceb9d6 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 19 Aug 2025 11:58:28 +0000 Subject: [PATCH 1364/1483] Rework tests for inhibited code in source traces mode Remove XFAILs and adjust coverage expectations to match the current behavior: in source traces specifically, there is no violation for static decisions, but there are violations for statements disabled by static decisions. --- .../Robustness/InhibitedCode/src/test_ops_0.adb | 10 +++++++++- .../Robustness/InhibitedCode/src/test_ops_inc.adb | 10 +++++++++- .../Ada/decision/Robustness/InhibitedCode/test.opt | 1 - .../mcdc/Robustness/InhibitedCode/src/test_ops_0.adb | 10 +++++++++- .../mcdc/Robustness/InhibitedCode/src/test_ops_inc.adb | 10 +++++++++- .../Qualif/Ada/mcdc/Robustness/InhibitedCode/test.opt | 1 - .../stmt/Robustness/InhibitedCode/src/test_ops_0.adb | 10 +++++++++- .../stmt/Robustness/InhibitedCode/src/test_ops_inc.adb | 10 +++++++++- .../Qualif/Ada/stmt/Robustness/InhibitedCode/test.opt | 1 - testsuite/tests/MB15-040-if-cst/src/monitor.adb | 2 +- .../tests/MB15-040-if-cst/src/test_ifcst_call.adb | 8 +++++++- .../tests/MB15-040-if-cst/src/test_ifcst_none.adb | 8 +++++++- testsuite/tests/MB15-040-if-cst/test.opt | 1 - 13 files changed, 69 insertions(+), 13 deletions(-) delete mode 100644 testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/test.opt delete mode 100644 testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/test.opt delete mode 100644 testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/test.opt diff --git a/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_0.adb b/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_0.adb index caf3118c4..c442f6695 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_0.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_0.adb @@ -7,8 +7,16 @@ end; --# ops.adb -- /incOp/ l- ## s- +-- /elabOp/ l+ ## 0 +-- +--%opts: --trace-mode=bin -- /incCheck/ l. ## 0 -- /incCount/ l. ## 0 --- /elabOp/ l+ ## 0 -- /elabCheck/ l. ## 0 -- /elabCount/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /incCheck/ l- ## s- +-- /incCount/ l- ## s- +-- /elabCheck/ l+ ## 0 +-- /elabCount/ l- ## s- diff --git a/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_inc.adb b/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_inc.adb index 8383e906d..5d61738de 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_inc.adb +++ b/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/src/test_ops_inc.adb @@ -9,8 +9,16 @@ end; --# ops.adb -- /incOp/ l+ ## 0 +-- /elabOp/ l+ ## 0 +-- +--%opts: --trace-mode=bin -- /incCheck/ l. ## 0 -- /incCount/ l. ## 0 --- /elabOp/ l+ ## 0 -- /elabCheck/ l. ## 0 -- /elabCount/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /incCheck/ l+ ## 0 +-- /incCount/ l- ## s- +-- /elabCheck/ l+ ## 0 +-- /elabCount/ l- ## s- diff --git a/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/test.opt b/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/test.opt deleted file mode 100644 index f10d6338c..000000000 --- a/testsuite/Qualif/Ada/decision/Robustness/InhibitedCode/test.opt +++ /dev/null @@ -1 +0,0 @@ -src-traces XFAIL S628-012: src-traces and inhibited code diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_0.adb b/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_0.adb index caf3118c4..c442f6695 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_0.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_0.adb @@ -7,8 +7,16 @@ end; --# ops.adb -- /incOp/ l- ## s- +-- /elabOp/ l+ ## 0 +-- +--%opts: --trace-mode=bin -- /incCheck/ l. ## 0 -- /incCount/ l. ## 0 --- /elabOp/ l+ ## 0 -- /elabCheck/ l. ## 0 -- /elabCount/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /incCheck/ l- ## s- +-- /incCount/ l- ## s- +-- /elabCheck/ l+ ## 0 +-- /elabCount/ l- ## s- diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_inc.adb b/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_inc.adb index 8383e906d..5d61738de 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_inc.adb +++ b/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/src/test_ops_inc.adb @@ -9,8 +9,16 @@ end; --# ops.adb -- /incOp/ l+ ## 0 +-- /elabOp/ l+ ## 0 +-- +--%opts: --trace-mode=bin -- /incCheck/ l. ## 0 -- /incCount/ l. ## 0 --- /elabOp/ l+ ## 0 -- /elabCheck/ l. ## 0 -- /elabCount/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /incCheck/ l+ ## 0 +-- /incCount/ l- ## s- +-- /elabCheck/ l+ ## 0 +-- /elabCount/ l- ## s- diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/test.opt b/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/test.opt deleted file mode 100644 index f10d6338c..000000000 --- a/testsuite/Qualif/Ada/mcdc/Robustness/InhibitedCode/test.opt +++ /dev/null @@ -1 +0,0 @@ -src-traces XFAIL S628-012: src-traces and inhibited code diff --git a/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_0.adb b/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_0.adb index caf3118c4..c442f6695 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_0.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_0.adb @@ -7,8 +7,16 @@ end; --# ops.adb -- /incOp/ l- ## s- +-- /elabOp/ l+ ## 0 +-- +--%opts: --trace-mode=bin -- /incCheck/ l. ## 0 -- /incCount/ l. ## 0 --- /elabOp/ l+ ## 0 -- /elabCheck/ l. ## 0 -- /elabCount/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /incCheck/ l- ## s- +-- /incCount/ l- ## s- +-- /elabCheck/ l+ ## 0 +-- /elabCount/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_inc.adb b/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_inc.adb index 8383e906d..5d61738de 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_inc.adb +++ b/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/src/test_ops_inc.adb @@ -9,8 +9,16 @@ end; --# ops.adb -- /incOp/ l+ ## 0 +-- /elabOp/ l+ ## 0 +-- +--%opts: --trace-mode=bin -- /incCheck/ l. ## 0 -- /incCount/ l. ## 0 --- /elabOp/ l+ ## 0 -- /elabCheck/ l. ## 0 -- /elabCount/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /incCheck/ l+ ## 0 +-- /incCount/ l- ## s- +-- /elabCheck/ l+ ## 0 +-- /elabCount/ l- ## s- diff --git a/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/test.opt b/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/test.opt deleted file mode 100644 index f10d6338c..000000000 --- a/testsuite/Qualif/Ada/stmt/Robustness/InhibitedCode/test.opt +++ /dev/null @@ -1 +0,0 @@ -src-traces XFAIL S628-012: src-traces and inhibited code diff --git a/testsuite/tests/MB15-040-if-cst/src/monitor.adb b/testsuite/tests/MB15-040-if-cst/src/monitor.adb index 2aa57f820..1ad4d8e9e 100644 --- a/testsuite/tests/MB15-040-if-cst/src/monitor.adb +++ b/testsuite/tests/MB15-040-if-cst/src/monitor.adb @@ -7,7 +7,7 @@ package body Monitor is procedure Op is begin if Count_Ops then -- # called - Opcount := Opcount + 1; + Opcount := Opcount + 1; -- # cond-stmt end if; Moncalls := Moncalls + 1; -- # called end; diff --git a/testsuite/tests/MB15-040-if-cst/src/test_ifcst_call.adb b/testsuite/tests/MB15-040-if-cst/src/test_ifcst_call.adb index 1d849d342..e4a954430 100644 --- a/testsuite/tests/MB15-040-if-cst/src/test_ifcst_call.adb +++ b/testsuite/tests/MB15-040-if-cst/src/test_ifcst_call.adb @@ -8,4 +8,10 @@ begin end; --# monitor.adb --- /called/ l+ ## 0 +-- /called/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /cond-stmt/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /cond-stmt/ l- ## s- diff --git a/testsuite/tests/MB15-040-if-cst/src/test_ifcst_none.adb b/testsuite/tests/MB15-040-if-cst/src/test_ifcst_none.adb index 34746842f..10dd454ee 100644 --- a/testsuite/tests/MB15-040-if-cst/src/test_ifcst_none.adb +++ b/testsuite/tests/MB15-040-if-cst/src/test_ifcst_none.adb @@ -7,4 +7,10 @@ begin end; --# monitor.adb --- /called/ l- ## s- +-- /called/ l- ## s- +-- +--%opts: --trace-mode=bin +-- /cond-stmt/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /cond-stmt/ l- ## s- diff --git a/testsuite/tests/MB15-040-if-cst/test.opt b/testsuite/tests/MB15-040-if-cst/test.opt index 1ab8d0b6c..e06a09849 100644 --- a/testsuite/tests/MB15-040-if-cst/test.opt +++ b/testsuite/tests/MB15-040-if-cst/test.opt @@ -1,4 +1,3 @@ 7.0.3 DEAD constant conditions, compiler change on 2013-11-18, not in 7.0.3 7.2.2 DEAD constant conditions, compiler change on 2013-11-18, not in 7.2.2 -src-traces XFAIL S628-012: src-traces and inhibited code 5.04a1 DEAD requires bug fix or language/feature support lacking in 5.04 From bbe3582381bde9e0b6c02c44246c3e525e0e1869 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 20 Aug 2025 10:54:38 +0200 Subject: [PATCH 1365/1483] Fix misplacement of documentation section --- doc/gnatcov/cov_source.rst | 143 ++++++++++++++++++------------------- 1 file changed, 71 insertions(+), 72 deletions(-) diff --git a/doc/gnatcov/cov_source.rst b/doc/gnatcov/cov_source.rst index d0ee1156c..a4b65f084 100644 --- a/doc/gnatcov/cov_source.rst +++ b/doc/gnatcov/cov_source.rst @@ -344,78 +344,6 @@ of-interest for the reported assessment, as well as the list of source files individually ignored with the ``Ignored_Source_Files`` project attribute and corresponding command-line option. - -Annotated sources, text (:cmd-option:`=xcov[+]`) ------------------------------------------------- - -For source coverage criteria, |gcvcov| :cmd-option:`--annotate=xcov` produces -an annotated version of each source file, in text format, named after the -original source with an extra ``.xcov`` extension at the end (``x.ext.xcov`` -for a source named ``x.ext``). - -Each annotated source contains a global summary of the assessment results -followed by the original source lines, all numbered and marked with a coverage -annotation next to the line number. The annotation on a line always consists -in a single character, which may be one of the following: - -.. tabularcolumns:: cl -.. csv-table:: - :delim: | - :widths: 10, 80 - :header: Annotation, Meaning - - ``.`` | No coverage obligation is attached to the line - ``-`` | Coverage obligations attached to the line, none satisfied - ``!`` | Coverage obligations attached to the line, some satisfied - ``?`` | Coverage obligations attached to the line, undetermined coverage state (*) - ``+`` | Coverage obligations attached to the line, all satisfied - -(*) The Undetermined Coverage state (``?``) is only shown on the line in the -absence of other known violations for that same line. - -Here is, to illustrate, the full statement coverage report produced for our -example unit when the ``Between`` function was called so that the ``if`` -control evaluated True only. The function is actually part of an Ada package, -called Ranges, with an original body source file named ``ranges.adb``: - -.. code-block:: - - examples/src/ranges.adb: - 67% of 3 lines covered - Coverage level: stmt - 1 .: package body Ranges is - 2 .: function Between (X1, X2, V : Integer) return Boolean is - 3 .: begin - 4 +: if X1 < X2 then - 5 +: return V >= X1 and then V <= X2; - 6 .: else - 7 -: return V >= X2 and then V <= X1; - 8 .: end if; - 9 .: end; - 10 .: end; - -:cmd-option:`--annotate=xcov+` (with a trailing +) works the same, only -providing extra details below lines with improperly satisfied obligations. The -available details consists in the list of :term:`coverage violations ` diagnosed for the line, which depends on the coverage criteria -involved. Here is an excerpt for our previous example, where the only -improperly satisfied obligation is an uncovered statement on line 7:: - - 7 -: return V >= X2 and then V <= X1; - STATEMENT "return V ..." at 7:10 not executed - - -XML report, xml (:cmd-option:`=xml`) ------------------------------------- - -:cmd-option:`--annotate=xml` produces a coverage report in the XML format, as -specified per the ``gnatcov-xml-report.xsd`` (XML schema description) that is -generated alongside. - -This report format is on par with the HTML report in terms of features, and it -is the preferred choice for programmatically accessing the coverage results. - - Assessment Context ^^^^^^^^^^^^^^^^^^ @@ -559,6 +487,77 @@ level is fully satisfied, with details available from the per criterion sections that precede. +Annotated sources, text (:cmd-option:`=xcov[+]`) +------------------------------------------------ + +For source coverage criteria, |gcvcov| :cmd-option:`--annotate=xcov` produces +an annotated version of each source file, in text format, named after the +original source with an extra ``.xcov`` extension at the end (``x.ext.xcov`` +for a source named ``x.ext``). + +Each annotated source contains a global summary of the assessment results +followed by the original source lines, all numbered and marked with a coverage +annotation next to the line number. The annotation on a line always consists +in a single character, which may be one of the following: + +.. tabularcolumns:: cl +.. csv-table:: + :delim: | + :widths: 10, 80 + :header: Annotation, Meaning + + ``.`` | No coverage obligation is attached to the line + ``-`` | Coverage obligations attached to the line, none satisfied + ``!`` | Coverage obligations attached to the line, some satisfied + ``?`` | Coverage obligations attached to the line, undetermined coverage state (*) + ``+`` | Coverage obligations attached to the line, all satisfied + +(*) The Undetermined Coverage state (``?``) is only shown on the line in the +absence of other known violations for that same line. + +Here is, to illustrate, the full statement coverage report produced for our +example unit when the ``Between`` function was called so that the ``if`` +control evaluated True only. The function is actually part of an Ada package, +called Ranges, with an original body source file named ``ranges.adb``: + +.. code-block:: + + examples/src/ranges.adb: + 67% of 3 lines covered + Coverage level: stmt + 1 .: package body Ranges is + 2 .: function Between (X1, X2, V : Integer) return Boolean is + 3 .: begin + 4 +: if X1 < X2 then + 5 +: return V >= X1 and then V <= X2; + 6 .: else + 7 -: return V >= X2 and then V <= X1; + 8 .: end if; + 9 .: end; + 10 .: end; + +:cmd-option:`--annotate=xcov+` (with a trailing +) works the same, only +providing extra details below lines with improperly satisfied obligations. The +available details consists in the list of :term:`coverage violations ` diagnosed for the line, which depends on the coverage criteria +involved. Here is an excerpt for our previous example, where the only +improperly satisfied obligation is an uncovered statement on line 7:: + + 7 -: return V >= X2 and then V <= X1; + STATEMENT "return V ..." at 7:10 not executed + + +XML report, xml (:cmd-option:`=xml`) +------------------------------------ + +:cmd-option:`--annotate=xml` produces a coverage report in the XML format, as +specified per the ``gnatcov-xml-report.xsd`` (XML schema description) that is +generated alongside. + +This report format is on par with the HTML report in terms of features, and it +is the preferred choice for programmatically accessing the coverage results. + + .. _scov-stmt: Statement Coverage analysis From eb50fd97b9a59af91fac5d1a490ac0a9d3afe17e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 20 Aug 2025 14:45:14 +0000 Subject: [PATCH 1366/1483] Instrument Ada: fix formatting for warning messages --- tools/gnatcov/instrument-ada_unit.adb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 0ff8c2803..4a5f012e5 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -7935,7 +7935,7 @@ package body Instrument.Ada_Unit is Report (UIC, Decl, "Failed to look for a previous declaration of this expression" - & " function" & Switches.Exception_Info (Exc), + & " function: " & Switches.Exception_Info (Exc), Warning); end; @@ -7945,7 +7945,7 @@ package body Instrument.Ada_Unit is when Exc : Property_Error => Report (UIC, Decl, - "Failed to look for a Ghost aspect for this declaration" + "Failed to look for a Ghost aspect for this declaration: " & Switches.Exception_Info (Exc), Warning); return False; @@ -7971,7 +7971,7 @@ package body Instrument.Ada_Unit is when Exc : Property_Error => Report (UIC, Decl, - "Failed to look for a canonical part of this declaration" + "Failed to look for a canonical part of this declaration: " & Switches.Exception_Info (Exc), Warning); end; From db4f08b195b49518c759d0a68b6bd3a1dff48cd5 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 20 Aug 2025 14:46:04 +0000 Subject: [PATCH 1367/1483] Instrument Ada: fix various crashes when LAL cannot resolve entities --- .../instr-cov/449-aggregate-crash/pkg.adb | 8 ++++++++ .../instr-cov/449-aggregate-crash/pkg.ads | 4 ++++ .../instr-cov/449-aggregate-crash/test.py | 20 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 6 ++++-- 4 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 testsuite/tests/instr-cov/449-aggregate-crash/pkg.adb create mode 100644 testsuite/tests/instr-cov/449-aggregate-crash/pkg.ads create mode 100644 testsuite/tests/instr-cov/449-aggregate-crash/test.py diff --git a/testsuite/tests/instr-cov/449-aggregate-crash/pkg.adb b/testsuite/tests/instr-cov/449-aggregate-crash/pkg.adb new file mode 100644 index 000000000..62be95641 --- /dev/null +++ b/testsuite/tests/instr-cov/449-aggregate-crash/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + function F return T is + begin + return null; + end F; + +end Pkg; diff --git a/testsuite/tests/instr-cov/449-aggregate-crash/pkg.ads b/testsuite/tests/instr-cov/449-aggregate-crash/pkg.ads new file mode 100644 index 000000000..a57c3625c --- /dev/null +++ b/testsuite/tests/instr-cov/449-aggregate-crash/pkg.ads @@ -0,0 +1,4 @@ +package Pkg is + subtype T is Unknown_Type; + function F return T; +end Pkg; diff --git a/testsuite/tests/instr-cov/449-aggregate-crash/test.py b/testsuite/tests/instr-cov/449-aggregate-crash/test.py new file mode 100644 index 000000000..2affc51c1 --- /dev/null +++ b/testsuite/tests/instr-cov/449-aggregate-crash/test.py @@ -0,0 +1,20 @@ +""" +Regression test: "gnatcov instrument" used to crash when trying to instrument a +function whose return type is an unresolvable subtype. +""" + +from SCOV.instr import xcov_instrument +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +xcov_instrument( + gprsw=GPRswitches(root_project=gprfor(mains=[], srcdirs=[".."])), + covlevel="stmt", + tolerate_messages=r"\*\*\* pkg\.adb:\d+:\d+: warning: .*", +) +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 4a5f012e5..7b46d4306 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -4726,7 +4726,7 @@ package body Instrument.Ada_Unit is -- be legal Ada. if Kind (N) in Ada_Base_Subp_Body - and then N.As_Base_Subp_Body.P_Previous_Part.Is_Null + and then Safe_Previous_Part_For_Decl (N.As_Base_Subp_Body).Is_Null and then (not Is_Expr_Function or else Is_Self_Referencing (UIC, N.As_Expr_Function)) then @@ -6156,7 +6156,8 @@ package body Instrument.Ada_Unit is end case; declare - Previous_Part : constant Basic_Decl := N.As_Body_Node.P_Previous_Part; + Previous_Part : constant Basic_Decl := + Safe_Previous_Part_For_Decl (N.As_Body_Node); Decl : constant Basic_Decl := (if Previous_Part.Is_Null then N.As_Body_Node.P_Subp_Spec_Or_Null.P_Parent_Basic_Decl @@ -7974,6 +7975,7 @@ package body Instrument.Ada_Unit is "Failed to look for a canonical part of this declaration: " & Switches.Exception_Info (Exc), Warning); + return False; end; return Canonical_Decl.Kind in From bc4d10ed2f1f7aabe9bc079ca8cc4fd99cb2e5ed Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 13 Aug 2025 12:09:30 +0200 Subject: [PATCH 1368/1483] Generate a report with only violations when no traces are specified --- testsuite/tests/124-no-trace/main.adb | 6 +++++ testsuite/tests/124-no-trace/test.py | 33 +++++++++++++++++++++++++ tools/gnatcov/gnatcov_bits_specific.adb | 32 +++++++++++++++++++++--- tools/gnatcov/project.adb | 1 + tools/gnatcov/project.ads | 5 ++++ 5 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 testsuite/tests/124-no-trace/main.adb create mode 100644 testsuite/tests/124-no-trace/test.py diff --git a/testsuite/tests/124-no-trace/main.adb b/testsuite/tests/124-no-trace/main.adb new file mode 100644 index 000000000..6e16d750d --- /dev/null +++ b/testsuite/tests/124-no-trace/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello world"); +end Main; diff --git a/testsuite/tests/124-no-trace/test.py b/testsuite/tests/124-no-trace/test.py new file mode 100644 index 000000000..ebd87f6b6 --- /dev/null +++ b/testsuite/tests/124-no-trace/test.py @@ -0,0 +1,33 @@ +""" +Check that gnatcov coverage produces a report even when the user did not +specify traces or checkpoints. Also check that the tool warns in this case. +""" + +from SCOV.minicheck import build_and_run, check_xcov_reports +from SUITE.cutils import contents_of, Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import thistest, gprfor, xcov + +Wdir("tmp_") + +cov_args = build_and_run( + gprsw=GPRswitches(root_project=gprfor(mains=["main.adb"], srcdirs=[".."])), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["--annotate=xcov"], +) + +# Do not pass the trace to the gnatcov coverage invocation +print("cov args are " + str(cov_args[:-1])) +xcov(cov_args[:-1], tolerate_messages=".*", out="coverage.log") + +thistest.fail_if_not_equal( + '"gnatcov coverage" output', + "warning: No trace files specified. GNATcoverage will still generate a" + " report", + contents_of("coverage.log").strip(), +) + +check_xcov_reports("obj", {"main.adb.xcov": {"-": {5}}}) + +thistest.result() diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 20cf6aef7..402cff2e3 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -659,6 +659,29 @@ procedure GNATcov_Bits_Specific is Process_Trace (+RT.Filename, +RT.Executable); end loop; + -- Try loading SCOs if no executable or traces were passed, to generate + -- a report with only violations. + + if Checkpoints_Inputs.Is_Empty + and then LLVM_JSON_Ckpt_Inputs.Is_Empty + and then SID_Inputs.Is_Empty + and then ALIs_Inputs.Is_Empty + and then Exe_Inputs.Is_Empty + and then Trace_Inputs.Is_Empty + then + Project.Warn_About_Missing_Info := False; + + -- Try loading SIDs first (as source traces are more widely used) + + Load_All_SIDs; + + -- If no SID files were found, try loading ALIs + + if SID_Inputs.Is_Empty then + Load_All_ALIs (Check_SCOs => False); + end if; + end if; + -- Use dominant information to refine decision coverage -- information wrt. outcomes taken. This is a binary information -- specificity as we always know which outcomes were taken in the @@ -2339,12 +2362,15 @@ begin end if; end if; - -- If no checkpoint is provided, expect at least 1 TRACE_FILE. + -- Warn if the user provided no checkpoints or traces if Checkpoints_Inputs.Is_Empty - and then LLVM_JSON_Ckpt_Inputs.Is_Empty + and then LLVM_JSON_Ckpt_Inputs.Is_Empty + and then Trace_Inputs.Is_Empty then - Check_Traces_Available; + Outputs.Warn + ("No trace files specified. GNATcoverage will still generate a" + & " report"); end if; -- Read and process traces diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 7c4869c2b..d552e9685 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -358,6 +358,7 @@ package body Project is -- --restricted-to-languages switch. or else not Src_Enabled_Languages (Unit.Language) + or else not Warn_About_Missing_Info then return; end if; diff --git a/tools/gnatcov/project.ads b/tools/gnatcov/project.ads index 7f6398076..1c96aa69e 100644 --- a/tools/gnatcov/project.ads +++ b/tools/gnatcov/project.ads @@ -40,6 +40,11 @@ package Project is Externally_Built_Projects_Processing_Enabled : Boolean := False; -- Whether to include projects marked as externally built to processings + Warn_About_Missing_Info : Boolean := True; + -- Whether to warn about missing coverage information for units of + -- interest. Set to False when generating a report without traces or + -- checkpoints specified. + ----------------------- -- Lifetime handling -- ----------------------- From e639cf9bf9ddfc06efcc1d922b6ed0b0ab5fb133 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 12 Aug 2025 12:07:17 +0200 Subject: [PATCH 1369/1483] Integrated instrumentation: consider every file of interest by default If the user did not specify files of interest through the --files switch, consider every file that is not a system header a file of interest. --- doc/gnatcov/integrated_instr.rst | 13 ++-- .../every_uoi/Makefile | 11 ++++ .../every_uoi/pkg.c | 5 ++ .../every_uoi/test.c | 8 +++ .../every_uoi/test.py | 60 +++++++++++++++++++ tools/gnatcov/instrument-c.adb | 19 ++++++ tools/gnatcov/instrument-gcc_wrapper.adb | 56 ++++++++++------- tools/gnatcov/instrument-setup_config.adb | 3 + tools/gnatcov/instrument-setup_config.ads | 4 ++ tools/gnatcov/strings.adb | 6 ++ tools/gnatcov/strings.ads | 3 +- 11 files changed, 160 insertions(+), 28 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/every_uoi/Makefile create mode 100644 testsuite/tests/integrated_instrumentation/every_uoi/pkg.c create mode 100644 testsuite/tests/integrated_instrumentation/every_uoi/test.c create mode 100644 testsuite/tests/integrated_instrumentation/every_uoi/test.py diff --git a/doc/gnatcov/integrated_instr.rst b/doc/gnatcov/integrated_instr.rst index 8b7b03550..3d31c15f5 100644 --- a/doc/gnatcov/integrated_instr.rst +++ b/doc/gnatcov/integrated_instr.rst @@ -44,10 +44,11 @@ out units of interest: ``--units`` and ``--projects``. Refer to :ref:`src_traces` for more information regarding the source instrumentation specific switches. -As there is no project acting as a units of interest provider, the user must -explicitly pass files of interest through the ``--files`` switch, which expects -a list of full filenames that can be passed through the command line, or using a -response file. +As there is no project acting as a units of interest provider, every file that +is not a system header is considered as a file of interest. The user can +explicitly specify files of interest through the ``--files`` switch, which +expects a list of full filenames that can be passed through the command line, or +using a response file. To generate a compiler wrapper, use the ``--compilers`` switch. The list of supported compilers is ``gcc`` and ``g++``. @@ -56,7 +57,9 @@ This will generate in the current directory, or in the directory specified by the ``--output-dir`` switch an executable compiler wrapper and a ``gnatcov_config.json`` file along. Note that this configuration file is used to configure various instrumentation options: it is thus very important that it -resides in the same directory as the compiler wrapper. +resides in the same directory as the compiler wrapper. Note that all of the +instrumentation artifacts, notably SID files that must be passed later to +|gcvcov|, are also generated in the current or specified output directory. Building an instrumented executable diff --git a/testsuite/tests/integrated_instrumentation/every_uoi/Makefile b/testsuite/tests/integrated_instrumentation/every_uoi/Makefile new file mode 100644 index 000000000..303dc65f8 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/every_uoi/Makefile @@ -0,0 +1,11 @@ +CC=gcc +OBJ = pkg.o test.o + +%.o: %.c + $(CC) -c -o $@ $< + +test: $(OBJ) + $(CC) -o $@ $^ + +clean: + rm -f *.o test diff --git a/testsuite/tests/integrated_instrumentation/every_uoi/pkg.c b/testsuite/tests/integrated_instrumentation/every_uoi/pkg.c new file mode 100644 index 000000000..8f8b1830b --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/every_uoi/pkg.c @@ -0,0 +1,5 @@ +int +foo () +{ + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/every_uoi/test.c b/testsuite/tests/integrated_instrumentation/every_uoi/test.c new file mode 100644 index 000000000..84fcd4703 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/every_uoi/test.c @@ -0,0 +1,8 @@ +extern int foo (); + +int +main () +{ + foo (); + return 0; +} diff --git a/testsuite/tests/integrated_instrumentation/every_uoi/test.py b/testsuite/tests/integrated_instrumentation/every_uoi/test.py new file mode 100644 index 000000000..d0dea20b5 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/every_uoi/test.py @@ -0,0 +1,60 @@ +""" +Check that every file is of interest by default when using integrated +instrumentation without the `--files` switch of the gnatcov setup-integration +command. +""" + +import glob +import os +import os.path + +from e3.fs import cp + +from SUITE.control import env +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +cwd = os.getcwd() + +# Copy the sources and the Makefile in the temporary directory +cp(os.path.join("..", "Makefile"), ".") +cp(os.path.join("..", "test.c"), ".") +cp(os.path.join("..", "pkg.c"), ".") + +# Then, setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + "--compilers=gcc", + f"--output-dir={cwd}", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=cwd) + +# Then, run the build process unchanged +cmdrun(["make", "test"], for_pgm=False) + +# Run the executable +cmdrun(["test"], for_pgm=False) + +# Check coverage expectations. +xcov( + [ + "coverage", + "--level=stmt", + "-axcov", + srctracename_for("test"), + ] + + [f"--sid={sid}" for sid in glob.glob("*.sid")] +) +check_xcov_reports( + ".", {"pkg.c.xcov": {"+": {4}}, "test.c.xcov": {"+": {6, 7}}} +) + +thistest.result() diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index b06322c95..89ad5aea7 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -34,6 +34,7 @@ with GNAT.Regpat; use GNAT.Regpat; with GNATCOLL.Mmap; with GNATCOLL.Utils; +with Instrument.Setup_Config; with Interfaces; use Interfaces; with Interfaces.C; use Interfaces.C; with Interfaces.C.Strings; use Interfaces.C.Strings; @@ -5808,6 +5809,24 @@ package body Instrument.C is Column => Column'Access); File := Create_Normalized (Get_C_String (C_File)); + -- If every file is of interest, ignore code from system headers and + -- consider everything else as of interest. TODO??? we could add a + -- switch for users who want to cover the runtime. + + if Instrument.Setup_Config.Every_File_Of_Interest then + if Location_Is_In_System_Header (Loc) then + return False; + else + -- If this source is of interest, and if it was not done yet, + -- record it in UIC.Files_Of_Interest and + -- UIC.Sources_Of_Interest_Info. + + if not UIC.Files_Of_Interest.Contains (File) then + UIC.Files_Of_Interest.Insert (File); + end if; + end if; + end if; + -- Look for a corresponding entry in UIC.Sources_Of_Interest, create one -- if it is missing. diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index e331c4d59..6526a0d4d 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -853,33 +853,45 @@ begin Fullname : constant String := +Comp_Command.File.Full_Name; Simple_Name : constant String := +Comp_Command.File.Base_Name; Instr_Name : constant String := (+Prj.Output_Dir) / Simple_Name; - - FI : constant File_To_String_Maps.Cursor := - Instr_Config.File_To_SID.Find (Comp_Command.File); begin -- Start by instrumenting the file as a source, if it is a unit of -- interest. - if File_To_String_Maps.Has_Element (FI) then - - -- Pass the compiler switches through the project description - - Instrument.Source - (Unit_Name => Fullname, - SID_Name => - Compiler_Wrapper_Dir / - (+File_To_String_Maps.Element (FI)), - Instrumenter => Instrumenter, - Files_Of_Interest => Files_Of_Interest, - Prj => Prj); + if Every_File_Of_Interest + or else Instr_Config.File_To_SID.Contains (Comp_Command.File) + then + declare + -- If every file is of interest, then compute the SID name + -- according to the basename + the hash of the fullname. + -- This has the downside of making the SID name system- + -- dependent, but a typical use case across systems would + -- involve using checkpoint, thus removing this worry. + + SID_Name : constant String := + (if Every_File_Of_Interest + then Ada.Directories.Base_Name (Fullname) + & Img (Full_Name_Hash (Comp_Command.File)) + & Ada.Directories.Extension (Fullname) & ".sid" + else +Instr_Config.File_To_SID.Element (Comp_Command.File)); + begin - Comp_Command_Ref.Instrumentation_Sources.Append - (Instrumenter.Buffer_Unit - (Compilation_Unit' - (File_Based_Language, Full_Name (Comp_Command.File)), - Prj) - .Unit_Name); - Instrumented_Files.Include (+Fullname); + -- Pass the compiler switches through the project description + + Instrument.Source + (Unit_Name => Fullname, + SID_Name => Compiler_Wrapper_Dir / SID_Name, + Instrumenter => Instrumenter, + Files_Of_Interest => Files_Of_Interest, + Prj => Prj); + + Comp_Command_Ref.Instrumentation_Sources.Append + (Instrumenter.Buffer_Unit + (Compilation_Unit' + (File_Based_Language, Full_Name (Comp_Command.File)), + Prj) + .Unit_Name); + Instrumented_Files.Include (+Fullname); + end; end if; -- Then, instrument it as a main if it is one diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index d677261c7..e40083aa4 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -409,6 +409,9 @@ package body Instrument.Setup_Config is FOI_JSON : constant JSON_Array := Config_JSON.Get ("files-of-interest"); begin + if Is_Empty (FOI_JSON) then + Every_File_Of_Interest := True; + end if; for FOI of FOI_JSON loop Result.File_To_SID.Insert (Create_Normalized (FOI.Get ("source-file")), diff --git a/tools/gnatcov/instrument-setup_config.ads b/tools/gnatcov/instrument-setup_config.ads index ff7a6e72c..493601823 100644 --- a/tools/gnatcov/instrument-setup_config.ads +++ b/tools/gnatcov/instrument-setup_config.ads @@ -54,6 +54,10 @@ package Instrument.Setup_Config is Instrumentation_Config_Filename : constant String := "gnatcov_config.json"; -- Simple name of the file containing the instrumentation configuration + Every_File_Of_Interest : Boolean := False; + -- Whether every file is of interest or if it the list of files of + -- interest was specified by the user (using the --files switch). + procedure Generate_Config (Files_Of_Interest : File_Sets.Set; Coverage_Level : String; diff --git a/tools/gnatcov/strings.adb b/tools/gnatcov/strings.adb index 47a0d350b..adfa4f8a8 100644 --- a/tools/gnatcov/strings.adb +++ b/tools/gnatcov/strings.adb @@ -61,6 +61,12 @@ package body Strings is return Result (First .. Result'Last); end Img; + function Img (H : Ada.Containers.Hash_Type) return String is + Result : constant String := Ada.Containers.Hash_Type'Image (H); + begin + return Result (Result'First + 1 .. Result'Last); + end Img; + --------- -- "<" -- --------- diff --git a/tools/gnatcov/strings.ads b/tools/gnatcov/strings.ads index aee09e316..acd6e25f0 100644 --- a/tools/gnatcov/strings.ads +++ b/tools/gnatcov/strings.ads @@ -59,7 +59,8 @@ package Strings is -- Assuming that L and R are not null, return true iff L.all < R.all function Img (I : Integer) return String; - -- Same as Integer'Image without the starting space character + function Img (H : Ada.Containers.Hash_Type) return String; + -- Same as 'Image without the starting space character function Has_Prefix (S : String; Prefix : String) return Boolean; -- True if S starts with Prefix From ce588911b253718eb8cc0651aeefa0ae186d9683 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 12 Aug 2025 12:12:43 +0200 Subject: [PATCH 1370/1483] Instrument.C: remove outdated comment --- tools/gnatcov/instrument-c.adb | 4 ---- 1 file changed, 4 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 89ad5aea7..a6a05abae 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -5840,10 +5840,6 @@ package body Instrument.C is return UIC.Sources_Of_Interest_Info.Reference (Cur).Of_Interest; end if; - -- Consider that File is of interest iff it belongs to a loaded - -- project. TODO??? This should also consider units of interest - -- switches. - if UIC.Files_Of_Interest.Contains (File) then declare SFI : constant Source_File_Index := From 31d660b52155f5b0748fe290154a75ba3fa3a256 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 22 Aug 2025 11:30:06 +0200 Subject: [PATCH 1371/1483] GNATcov: fix instrumentation of overriding expr function GNATcoverage used to create an overriding auxiliary expression function (the _With_State_ subprogram) when instrumenting an overriding expression function, because the Index used to create the name of the auxiliary expression function was reset between the package specification and package body instrumentation. --- .../expr_func/410-overriding/main.adb | 10 ++++++ .../expr_func/410-overriding/pkg.adb | 8 +++++ .../expr_func/410-overriding/pkg.ads | 13 ++++++++ .../expr_func/410-overriding/test.py | 33 +++++++++++++++++++ tools/gnatcov/instrument-ada_unit.adb | 1 - 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/instr-cov/expr_func/410-overriding/main.adb create mode 100644 testsuite/tests/instr-cov/expr_func/410-overriding/pkg.adb create mode 100644 testsuite/tests/instr-cov/expr_func/410-overriding/pkg.ads create mode 100644 testsuite/tests/instr-cov/expr_func/410-overriding/test.py diff --git a/testsuite/tests/instr-cov/expr_func/410-overriding/main.adb b/testsuite/tests/instr-cov/expr_func/410-overriding/main.adb new file mode 100644 index 000000000..317629809 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/410-overriding/main.adb @@ -0,0 +1,10 @@ +pragma Ada_2012; +with Pkg; + +procedure Main +is + Obj : Pkg.T_Child; + B : Boolean := Obj.T_Prim (True, False); +begin + null; +end Main; diff --git a/testsuite/tests/instr-cov/expr_func/410-overriding/pkg.adb b/testsuite/tests/instr-cov/expr_func/410-overriding/pkg.adb new file mode 100644 index 000000000..98662c39d --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/410-overriding/pkg.adb @@ -0,0 +1,8 @@ +pragma Ada_2012; + +package body Pkg is + + overriding function T_Prim (Obj : T_Child; A, B : Boolean) return Boolean + is (A and then B); + +end Pkg; diff --git a/testsuite/tests/instr-cov/expr_func/410-overriding/pkg.ads b/testsuite/tests/instr-cov/expr_func/410-overriding/pkg.ads new file mode 100644 index 000000000..a233bc545 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/410-overriding/pkg.ads @@ -0,0 +1,13 @@ +pragma Ada_2012; + +package Pkg is + + type T is tagged null record; + function T_Prim (Obj : T; A, B : Boolean) return Boolean is (A or else B); + + type T_Child is new T with record + X : Integer; + end record; + overriding function T_Prim (Obj : T_Child; A, B : Boolean) return Boolean; + +end Pkg; diff --git a/testsuite/tests/instr-cov/expr_func/410-overriding/test.py b/testsuite/tests/instr-cov/expr_func/410-overriding/test.py new file mode 100644 index 000000000..8cb2b2495 --- /dev/null +++ b/testsuite/tests/instr-cov/expr_func/410-overriding/test.py @@ -0,0 +1,33 @@ +""" +Regression test: GNATcoverage used to create an overriding expression function +when instrumenting an overriding expression function in a package body. This +overriding was declared too late, which resulted in a compilation error. +""" + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["main.adb"])), + covlevel="stmt+uc_mcdc", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) + +check_xcov_reports( + "xcov", + { + "main.adb.xcov": {"+": {6, 7, 9}}, + "pkg.ads.xcov": {"+": {5, 8, 9, 10}, "-": {6}}, + "pkg.adb.xcov": {"!": {6}}, + }, +) + +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 7b46d4306..1bc16d054 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -10047,7 +10047,6 @@ package body Instrument.Ada_Unit is UIC.Annotations.Clear; UIC.Scope_Entities := Scope_Entities_Trees.Empty_Tree; UIC.Current_Scope_Entity := UIC.Scope_Entities.Root; - UIC.Degenerate_Subprogram_Index := 0; UIC.Source_Decisions := Source_Decision_Vectors.Empty; UIC.Source_Conditions := Source_Condition_Vectors.Empty; UIC.Unit_Bits.Last_Statement_Bit := No_Bit_Id; From 62afebbf85556fdbf37d19ac17f5d3e047087c30 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 7 Aug 2025 12:43:45 +0200 Subject: [PATCH 1372/1483] Add tolerate_cov_messages formal to TestCase API Similar to tolerate_messages for gnatcov instrument. Note that this is only supported for source instrumentation as the xcov function does not check error messages when using binary traces. --- testsuite/SCOV/internals/driver.py | 50 +++++++++++++++++------------- testsuite/SCOV/tc.py | 5 +++ 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index cec0ea80e..6405debbf 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -676,29 +676,37 @@ def gen_one_xcov_report(self, trace, report_format, options=""): # return. ofile = report_format + ".out" - xcov(args=["coverage"] + covargs, out=ofile) - - # Standard output might typically contain labeling warnings issued - # by the static analysis phase, or error messages issued when a trace - # indicates that some unlabeled edge was taken. None of this should - # happen so we simply fail as soon as the output file is not empty. - # Note that we do this in qualification mode as well, even though what - # we're looking at is not stricly part of the qualified interface. - - # Warnings about -S being deprecated are expected: just ignore them - output_lines = lines_of(ofile) - for i, line in reversed(list(enumerate(output_lines))): - if line == ( - "warning: -S is deprecated. " - "This option will be removed in release 26." - ): - output_lines.pop(i) - output = "\n".join(output_lines) - - thistest.fail_if( - output, f"xcov standard output not empty ({ofile}:\n--\n{output}" + xcov( + args=["coverage"] + covargs, + tolerate_messages=self.testcase.tolerate_cov_messages, + out=ofile, ) + # Only check the output when running with binary traces, as this is + # done in xcov for source traces. + if thistest.options.trace_mode == "bin": + # Standard output might typically contain labeling warnings issued + # by the static analysis phase, or error messages issued when a + # trace indicates that some unlabeled edge was taken. None of this + # should happen so we simply fail as soon as the output file is not + # empty. Note that we do this in qualification mode as well, even + # though what we're looking at is not stricly part of the qualified + # interface. + + # Warnings about -S being deprecated are expected: just ignore them + output_lines = lines_of(ofile) + for i, line in reversed(list(enumerate(output_lines))): + if line == ( + "warning: -S is deprecated. " + "This option will be removed in release 26." + ): + output_lines.pop(i) + output = "\n".join(output_lines) + + thistest.fail_if( + output, f"xcov standard output not empty ({ofile}:\n--\n{output}" + ) + def force_xcov_report(self, source): filename = self.xcov_translation_for(source) + ".xcov" diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index 6c777842c..bac14825f 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -137,6 +137,7 @@ def __init__( extracargs="", category=CAT.auto, tolerate_messages=None, + tolerate_cov_messages=None, expect_non_zero_code=False, assert_lvl=None, fun_call_lvl=False, @@ -153,6 +154,10 @@ def __init__( # for xcov_instrument). self.tolerate_messages = tolerate_messages + # Pass tolerate_cov_messages to gnatcov coverage invocations (only when + # using source traces). + self.tolerate_cov_messages = tolerate_cov_messages + # Step 1: Compute the list of drivers and consolidation specs # to exercise # ------------------------------------------------------------ From bffe20ac48f87bbd7c2bb1a90824e16a50f0900a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 18 Dec 2024 15:45:00 +0100 Subject: [PATCH 1373/1483] Implement support for compilation units with varying SCOs --- .../tests/207-srctrace-version/foo.c.sid | Bin 1179 -> 1186 bytes testsuite/tests/207-srctrace-version/main.sid | Bin 1406 -> 1422 bytes .../207-srctrace-version/reference.srctrace | Bin 336 -> 336 bytes .../320-varying-scos/varying_source/test.py | 71 + .../main.adb.xml.expected | 36 +- .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 1508 -> 1508 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2580 -> 2580 bytes .../gen/arm-elf-linux/main_1.sid | Bin 421 -> 445 bytes .../gen/arm-elf-linux/main_2.sid | Bin 421 -> 445 bytes .../gen/arm-elf-linux/pkg.sid | Bin 1102 -> 1150 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1879 -> 1831 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1889 -> 1841 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 2088 -> 2422 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 2019 -> 2353 bytes .../gen/x86_64-windows/main_1.sid | Bin 423 -> 447 bytes .../gen/x86_64-windows/main_2.sid | Bin 423 -> 447 bytes .../gen/x86_64-windows/pkg.sid | Bin 1106 -> 1154 bytes tools/gnatcov/annotations-dynamic_html.adb | 10 +- tools/gnatcov/annotations-xml.adb | 6 +- tools/gnatcov/annotations.adb | 34 +- tools/gnatcov/annotations.ads | 4 +- tools/gnatcov/checkpoints.ads | 6 +- tools/gnatcov/coverage-source.adb | 48 +- tools/gnatcov/files_table.adb | 29 + tools/gnatcov/files_table.ads | 19 +- tools/gnatcov/gnatcov_bits_specific.adb | 8 + tools/gnatcov/instrument-ada_unit.adb | 79 +- tools/gnatcov/instrument-c.adb | 98 +- tools/gnatcov/instrument-common.adb | 19 - tools/gnatcov/instrument-common.ads | 6 - tools/gnatcov/instrument-projects.adb | 27 +- tools/gnatcov/sc_obligations.adb | 2179 +++++++++++------ tools/gnatcov/sc_obligations.ads | 116 +- tools/gnatcov/slocs.ads | 7 +- 34 files changed, 1715 insertions(+), 1087 deletions(-) create mode 100644 testsuite/tests/320-varying-scos/varying_source/test.py diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid index 962ac59626d19df2295dbccc0a39174f7277e75a..d0ecec554373ef0e8806b3be7e5dd46d7ea16d47 100644 GIT binary patch delta 176 zcmbQuxrkH5-On*3IloLHIU_YWyC6R^uY^HlqDTZQ0|-p)-NM5NW-&1Q|Np;!av-DT z@$HesPk1g@swXnTc*rW?pFpSUfQ&XYv>3bpSy$D(e6M diff --git a/testsuite/tests/207-srctrace-version/main.sid b/testsuite/tests/207-srctrace-version/main.sid index 64111790433a5122d7b93aad01b097da48ed576e..ca05865ae1cfd0c6780f9b69299bfeeb12057b87 100644 GIT binary patch delta 112 zcmeyz)yFO3?&lbioL{DpoRONGU67xdSHd7NQ6yT30S1_X3`P*1xX_r9apFx=M#jm) zjMlthF`zgvSgulfauQ?16z#_Vq=Jj6CXVw}Sa0L1Yf AiU0rr delta 113 zcmeC<{>LTa?&lbioL{DpoRONGU67xdSHd7XQ6$=kk%57M7l^^&{~B@q_a<&-p&t|z zPP$!Zd$+5v8YICC#2|%W#Sbb)Dt19QAd>PBZ?MgS(r1abfX delta 14 Vcmcb>bb)Dt1G52V - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index 0b910a88605bc3f6631834b619c3a63b87379961..8d65dbe4b94a5d8e0b66773112166929960175d1 100644 GIT binary patch delta 71 zcmaFD{e*jh94k9ByAj_+Wkq8{GX@5B1_lOUAT}~EGSxLO*EKL!Ffg|=HLx-?Vc-CY Wa|5x0vAMCKk+HFng~`V9Tvh=gEdZO^C6)jH delta 97 zcmdnXyp&nQ-On*3IloLHIU_YWyC6R^uY^H(qDYh)BLf2i2!lbbG(+K@p4YSY)oyv$ k9iMaTsmDETkObqz64%KxjGU7d7+H}p%fy!klWiFr0Ch$4V2eE5iK ly}KoX1-OI#<*Fmg^-U}QzYEE8WEOtxig003A|8$$p9 diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid index c1f72df6195d71afe8f5ec83b29080a3e60f6b74..49d156be429897c0a3ec5e4525ea72703ced3d24 100644 GIT binary patch delta 183 zcmX@d@sC5q-On*3IloLHIU_YWyC6R^uY^HlqDbq+BZ4Z73=9k)3<4l}O?yRipyR4r zbHZoIDZ3{u<6BsJW8yWFiAM$W->7|2R9D?4=-hhBW$U8*M~Z*{W?*Cj>H%Rm0C7MD zF->-5G-70$T*GL^3$uhBBsW=>QF`(z#yFsnBJ0_nsQ+3Vr1o(|-m>8R_5S+ZuMTe3 IU{YfO05}LV#{d8T delta 122 zcmeyzagIa8-On*3IloLHIU_YWyC6R^uY^H(qDU(jBLfUf+%7*^l0|&-1t!*s*K~v# ynSc@?3{t@kRy27xqckr}2rN9=kU2GTDKNW%4b?sLc^fYD@rpEf=!@ diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt index 3f2e2f96ef23270a97d8168ce0704f50ebe555b8..d01ce8c959310edfdc0079e589d5b4757387aaf0 100644 GIT binary patch delta 254 zcmcc4x13MJ-On*3IloLHIU_YWyC6R^uY^HlqsS9RO=boL1|}c|(JVmB2*hvz;=u4^ zK_*deR-gbI5Q9|1Xpk-x0MY?65`=e5)A{&m+J)ECcr-h|#oIiwU~Hekzz&q)n7oon zMhD1%1CTb5xtu^8ckXv})z)AW*e b>lzp<7+6}F8dw>cDrg%RSs56>Tmqv3Uui7r delta 227 zcmdnU_mEG--On*3IloLHIU_YWyC6R^uY^H(qsS9RF-8Uk1`uWjVkRif!Z2BmNn&y_ zv-D&KW>!;HpfDR$8m0uq2WepeV#XcQbUuEXcH#9j9?i~g@itE^7~5w|E@YMk>Sp0( z2ddzJs^*;B$Rr~YckXv})z=^7a;7+6>tT3Q)dDrg%RSQ!|A91H?58UU>zFy{aO diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 3ce172c4b5218d2c180120df0108517ff5b0342e..309ed84ff45210f78dda60cbd59cb5d97dee8d76 100644 GIT binary patch delta 605 zcmZ1>@J&d>-On*3IloLHIU_YWyC6R^uY^Hlqlh6R8v_t9GEB~9bd6vHGeKMku9ape z+|%=V_P*LJ@4Dl2jy?6b#|=^r10Z!E@E-_ZG~b0){@2dDKbG0F?U&Pm{4BSuJ?)bX znMAaozLNN)eeeDhtCL6HKD2TwViUgJ!^i~G2Erf!HVtg`w^+7V~BB#lF{1lx)McJpSOhVU}7$Ko>=8^#gCC0Xc7p6 z0ORBa77>>|j;n6X37;jW?4GcUZ(;2Xh&-yNL1G|#h4#ER%b%lH^&u+#k$9DI z_?(@+hd`d!f1~zAQC)SHpmXafm#vHLA1VI*n}Lx9s0)Na0PJ~?7eEY_$rqW77+EHB zFk1!+W8p@^?0^Y^XpmL%>?JM@Ik~?R z7uo)Q_j{2AyVAQkAlHhlXM3XlYjKd;#}#?Yg7??^>vz98xH*jZFf)6KzQTt$E>)8i O*hQJl4JMnje*^&Q(XLkj delta 286 zcmew+v_e3{-On*3IloLHIU_YWyC6R^uY^H(qlh6RFCzm30|DOXp26AB- zWDW>0u4%7m4s={~YfktqIc4{RWqb>3Z%kgureMv;0+a?}kQPoL1_8#E9?9Dm@yC49 zyZG6BLy(}|KcATfAPJCpAnU-2C-*WNu|ik}n5`!Bvx;n9!g82dZo=$~8gop_Pl6N* Y0I`voobhmi@W4TM1eY#PjJrpft?3X{c|B*Bh?DFexV zdaKA^xjt*b#D|Z#)(f1!FC{HK1*{)Rz>FitQD#PKzw1gAS$*CTwu6be;CW(|#}z+D zW}rzR3<5AOLU>St$x%!)8p!5@WI=qPJ@3u(=jc^^h)RDXUZos9XJ_vru;<^XeNj|b z-6iPUddg+%qWedRfB$A+WC7{|VGsb@19Ccu!7}+IlMy4!Bxb965EtYYPN>vMkL2x( z_+vilUHojmAxO~fpU+GKpcEK@w1d=g05M2C2!M?PF+diu@UYvl~B3=DusLEFFxNP(?`Sqr2AUwN;Z delta 278 zcmdle^q617-On*3IloLHIU_YWyC6R^uY^H(qlhM>8Y2S(0|$4V2eE5iK ky}KoX1-%UmbdFmg?9U}S^giLVVN+cP!*01U+(8vpv-}7e#f|U4qW7r(Cu!x__kj_iqM9CZHM+h64}>q?u{5C!-M~)8qz5E4YE|Ai2qk ojM9_OF~$Ln6j{&qME%#|AhnMx@|FefulLvQesyrO4wD)a00adrNdN!< delta 122 zcmZqTyu=~m?&lbioL{DpoRONGU67xdSHd7XQKXZLkpTuK?v|f?lUZ!?1tzwMw{(OV ynSc@?3{t@kRy27(qckr}2rN9=mC=Y5!m41jnk>&EI@ywud-5~Jpv^H%YD@rxDHt9A diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 758ceeb2e..27ae7f6e4 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -600,14 +600,14 @@ package body Annotations.Dynamic_Html is Line_Stats : constant Li_Stat_Array := Line_Metrics (File_Info, - Scope_Ent.Start_Sloc.Line, + Scope_Ent.Source_Range.L.First_Sloc.Line, (if Is_Root then Last_Line (File_Info) - else Scope_Ent.End_Sloc.Line)); + else Scope_Ent.Source_Range.L.Last_Sloc.Line)); -- Adjust Scope_Ent.End_Sloc for the root node as it is - -- No_Local_Location by default. + -- No_Local_Location by default. TODO??? - Ob_Stats : constant Ob_Stat_Array := - Obligation_Metrics (Scope_Ent.From, Scope_Ent.To); + Ob_Stats : constant Ob_Stat_Array := + Obligation_Metrics (Get_SCOs (Scope_Ent.Source_Range)); begin Scope_Metrics_JSON.Set_Field ("scopeName", Scope_Ent.Name); Scope_Metrics_JSON.Set_Field ("scopeLine", Scope_Ent.Sloc.Line); diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index a21240e6a..fe30b0996 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -586,9 +586,9 @@ package body Annotations.Xml is Line_Stats : constant Li_Stat_Array := Line_Metrics (File_Info, - Scope_Ent.Start_Sloc.Line, + Scope_Ent.Source_Range.L.First_Sloc.Line, (if Is_Root then Last_Line (File_Info) - else Scope_Ent.End_Sloc.Line)); + else Scope_Ent.Source_Range.L.Last_Sloc.Line)); -- Adjust Scope_Ent.End_Sloc for the root node as it is -- No_Local_Location by default. begin @@ -598,7 +598,7 @@ package body Annotations.Xml is Print_Coverage_Li_Stats (Pp, Line_Stats, Dest_Compilation_Unit); Print_Coverage_Ob_Stats (Pp, - Obligation_Metrics (Scope_Ent.From, Scope_Ent.To), + Obligation_Metrics (Get_SCOs (Scope_Ent.Source_Range)), Dest_Compilation_Unit); while Has_Element (Child) loop Pp_Scope_Entity (Child); diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 0dd05164a..c3a5ec1ea 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -488,10 +488,17 @@ package body Annotations is -- because this depends on violation count for each exempted region. FI.Li_Stats := Line_Metrics (FI, 1, Last_Line (FI)); - FI.Ob_Stats := - Obligation_Metrics - (First_SCO (Comp_Unit (File_Index)), - Last_SCO (Comp_Unit (File_Index))); + + declare + SCOs : SCO_Sets.Set; + begin + for SCO_Range of SCO_Ranges (Comp_Unit (File_Index)) loop + for SCO in SCO_Range.First .. SCO_Range.Last loop + SCOs.Include (SCO); + end loop; + end loop; + FI.Ob_Stats := Obligation_Metrics (SCOs); + end; for J in Global_Stats'Range loop Global_Stats (J) := Global_Stats (J) + FI.Li_Stats (J); @@ -1030,7 +1037,7 @@ package body Annotations is -- Obligation_Metrics -- ------------------------ - function Obligation_Metrics (From, To : SCO_Id) return Ob_Stat_Array + function Obligation_Metrics (SCOs : SCO_Sets.Set) return Ob_Stat_Array is Result : Ob_Stat_Array; @@ -1076,10 +1083,7 @@ package body Annotations is end Update_Level_Stats; begin - if From = No_SCO_Id then - return Result; - end if; - for SCO in From .. To loop + for SCO of SCOs loop case Kind (SCO) is when Statement => Update_Level_Stats (SCO, Get_Line_State (SCO, Stmt), Stmt); @@ -1102,7 +1106,8 @@ package body Annotations is Coverage.Assertion_Condition_Coverage_Enabled and then Is_Assertion (SCO); begin - if Coverage.MCDC_Coverage_Enabled or else Assertion_Decision + if Coverage.MCDC_Coverage_Enabled + or else Assertion_Decision then declare Condition_Level : constant Coverage_Level := @@ -1110,7 +1115,6 @@ package body Annotations is then Coverage.Assertion_Condition_Level else Coverage.MCDC_Level); begin - -- Conditions in that decision for J in @@ -1126,11 +1130,11 @@ package body Annotations is then ATCC else MCDC)); -- If the parent decision is partially covered, - -- then the SCO_State for each condition will be - -- No_Code, and the SCO_State for the + -- then the SCO_State for each condition + -- will be No_Code, and the SCO_State for the -- MCDC/Assertion condition Coverage_Level - -- associated to the parent decision SCO will be - -- Not_Covered. + -- associated to the parent decision SCO will + -- be Not_Covered. Condition_State : SCO_State; diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index a88432b67..9365a5db1 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -319,8 +319,8 @@ private From, To : Natural) return Li_Stat_Array; -- Return line metrics for the given line range - function Obligation_Metrics (From, To : SCO_Id) return Ob_Stat_Array; - -- Return obligation metrics for the given SCO range + function Obligation_Metrics (SCOs : SCO_Sets.Set) return Ob_Stat_Array; + -- Return obligation metrics for the given SCO ranges function SCO_Kind_Image (SCO : SCO_Id) return String; -- Get the string representation of the SCO_Kind of SCO. A special diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 7725c3fd0..551a0c59a 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -39,7 +39,7 @@ with Traces_Source; use Traces_Source; package Checkpoints is - subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 19; + subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 20; -- For compatibility with previous Gnatcov versions, the checkpoint -- file format is versioned. -- @@ -63,6 +63,8 @@ package Checkpoints is -- 17 -- Add support for Fun_Call and Guarded Expression coverage -- 18 -- Removed support for tags (separate coverage) -- 19 -- Removed support for instance ids (separate coverage) + -- 20 -- Rework Scope_Entity to identify scopes by their Start/End_Sloc + -- rather than their Start/End_Scope. -- -- Note that we always use the last version when creating a checkpoint. -- @@ -115,7 +117,7 @@ package Checkpoints is (Relocs : in out Checkpoint_Relocations; CP_CU_Id : CU_Id); -- Mark the source file index or compilation unit as ignored in the - -- checkpoint relocation. Tying to remap that source file index or + -- checkpoint relocation. Trying to remap that source file index or -- compilation unit will result in an error. procedure Ignore_SCO diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index af3c1ca5e..9fa7dcf80 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -220,6 +220,13 @@ package body Coverage.Source is Ignored_SF_Map : Unit_To_Ignored_Maps.Map; -- Map units of interest to the list of associated ignored source files + procedure Initialize_SCI_For_SID + (CU : CU_Id; + SCOs_Fingerprint : SC_Obligations.Fingerprint_Type); + -- Initialize source coverage information vectors for obligations in CU, + -- for SCOs_Fingerprint version, assumed to come from source + -- instrumentation. + -------------------------- -- Basic_Block_Has_Code -- -------------------------- @@ -2192,12 +2199,11 @@ package body Coverage.Source is -- Sanity check that Fingerprint is consistent with what the -- instrumenter recorded in the CU info. - if Fingerprint /= SC_Obligations.Fingerprint (CU) - or else - Bit_Maps_Fingerprint /= SC_Obligations.Bit_Maps_Fingerprint (CU) - or else - Annotations_Fingerprint /= - SC_Obligations.Annotations_Fingerprint (CU) + if not Has_Fingerprint (CU, Fingerprint) + or else Bit_Maps_Fingerprint /= + SC_Obligations.Bit_Maps_Fingerprint (CU, Fingerprint) + or else Annotations_Fingerprint /= + SC_Obligations.Annotations_Fingerprint (CU, Fingerprint) then Warn ("traces for " & Unit_Image & " (from " & Filename & ") are" & " inconsistent with the corresponding Source Instrumentation" @@ -2211,7 +2217,7 @@ package body Coverage.Source is -- Discharge SCOs based on source traces - BM := Bit_Maps (CU); + BM := Bit_Maps (CU, Fingerprint); ST := Scope_Traversal (CU); for J in Stmt_Buffer'Range loop @@ -2227,7 +2233,7 @@ package body Coverage.Source is -- when one of them (which actually is the last) is covered. declare - Stmt_Blocks : SCO_Id_Vector_Vector renames Blocks (CU); + Stmt_Blocks : SCO_Id_Vector_Vector renames Blocks (CU, Fingerprint); Block_Index : Positive; begin if not Stmt_Blocks.Is_Empty then @@ -2473,11 +2479,13 @@ package body Coverage.Source is end if; end Initialize_SCI; - ---------------------------------------- - -- Initialize_SCI_For_Instrumented_CU -- - ---------------------------------------- + ---------------------------- + -- Initialize_SCI_For_SID -- + ---------------------------- - procedure Initialize_SCI_For_Instrumented_CU (CU : CU_Id) is + procedure Initialize_SCI_For_SID + (CU : CU_Id; + SCOs_Fingerprint : SC_Obligations.Fingerprint_Type) is procedure Set_Has_Code (SCO : SCO_Id); -- If SCO is a statement, mark it as having code @@ -2495,7 +2503,7 @@ package body Coverage.Source is end Set_Has_Code; Stmt_Bit_Map : Statement_Bit_Map renames - Bit_Maps (CU).Statement_Bits.all; + Bit_Maps (CU, SCOs_Fingerprint).Statement_Bits.all; -- Start of processing for Initialize_SCI_For_Instrumented_CU @@ -2509,7 +2517,8 @@ package body Coverage.Source is -- instrumented statement SCOs in blocks. declare - Stmt_Blocks : SCO_Id_Vector_Vector renames Blocks (CU); + Stmt_Blocks : SCO_Id_Vector_Vector renames + Blocks (CU, SCOs_Fingerprint); Block_Index : Positive; begin if not Stmt_Blocks.Is_Empty then @@ -2542,6 +2551,17 @@ package body Coverage.Source is end loop; end if; end; + end Initialize_SCI_For_SID; + + ---------------------------------------- + -- Initialize_SCI_For_Instrumented_CU -- + ---------------------------------------- + + procedure Initialize_SCI_For_Instrumented_CU (CU : CU_Id) is + begin + for Fingerprint of SC_Obligations.Fingerprints (CU) loop + Initialize_SCI_For_SID (CU, Fingerprint); + end loop; end Initialize_SCI_For_Instrumented_CU; -------------------------- diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index c7ca599a4..ea1a96e43 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -1206,6 +1206,35 @@ package body Files_Table is end; end Get_Line; + -------------- + -- Get_SCOs -- + -------------- + + function Get_SCOs + (Source_Range : Source_Location_Range) return SCO_Sets.Set + is + Result : SCO_Sets.Set; + FI : constant File_Info_Access := + Get_File (Source_Range.Source_File); + Last : constant Positive := Last_Line (FI); + begin + for Line in + Source_Range.L.First_Sloc.Line .. Source_Range.L.Last_Sloc.Line + loop + exit when Line > Last; + declare + SCOs : constant SCO_Id_Array_Acc := Get_Line (FI, Line).SCOs; + begin + if SCOs /= null then + for SCO of SCOs.all loop + Result.Include (SCO); + end loop; + end if; + end; + end loop; + return Result; + end Get_SCOs; + --------------------- -- Get_Simple_Name -- --------------------- diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index f5b73c8e1..5749e6624 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -319,7 +319,12 @@ package Files_Table is type Line_Info_Access is access all Line_Info; Empty_Line_Info : constant Line_Info_Access; - type Source_Lines is private; + -- Describe a source file - one element per line + + package Source_Line_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, + Element_Type => Line_Info_Access); + type Source_Lines is new Source_Line_Vectors.Vector with null record; type Any_Ignore_Status is (Unknown, Always, Sometimes, Never); -- Represents the different states a source file can be regarding the @@ -513,7 +518,11 @@ package Files_Table is function Get_Line (Sloc : Source_Location) return Line_Info_Access with Pre => Sloc = Slocs.No_Location - or else Get_File (Sloc.Source_File).Kind in Stub_File | Source_File; + or else Get_File (Sloc.Source_File).Kind in Stub_File | Source_File; + + function Get_SCOs + (Source_Range : Source_Location_Range) return SCO_Sets.Set; + -- Return all of the SCOs under the given Source_Range procedure Set_Encoding (Encoding : String); -- Set the encoding used to interpret source code (this is a global @@ -676,12 +685,6 @@ package Files_Table is -- "-Wimplicit-fallthrough" private - -- Describe a source file - one element per line - - package Source_Line_Vectors is new Ada.Containers.Vectors - (Index_Type => Positive, - Element_Type => Line_Info_Access); - type Source_Lines is new Source_Line_Vectors.Vector with null record; Empty_Line_Info : constant Line_Info_Access := new Line_Info; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 402cff2e3..b4272f616 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -898,6 +898,14 @@ procedure GNATcov_Bits_Specific is (+Filename, (if Has_Matcher then Matcher'Access else null)); end loop; + -- Then, create source coverage data structure for each loaded unit. + -- Note that this must be done after having loaded every version of + -- the compilation unit, which can be found across SID files. + + for CU in Valid_CU_Id'First .. Last_CU loop + Coverage.Source.Initialize_SCI_For_Instrumented_CU (CU); + end loop; + -- Now that all the scope entities that can be referenced by -- --subprograms are known, dump them if requested. diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 1bc16d054..dc37f7f34 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8017,16 +8017,18 @@ package body Instrument.Ada_Unit is Kind => Files_Table.Source_File, Indexed_Simple_Name => True); New_Scope_Ent : constant Scope_Entity := - (From => SCO_Id (SCOs.SCO_Table.Last + 1), - To => No_SCO_Id, - Start_Sloc => Local_Sloc (Start_Sloc (N.Sloc_Range)), - End_Sloc => Local_Sloc (End_Sloc (N.Sloc_Range)), - Name => + (Source_Range => Slocs.Source_Location_Range' + (Source_File => UIC.SFI, + L => Slocs.Local_Source_Location_Range' + (First_Sloc => Local_Sloc (Start_Sloc (N.Sloc_Range)), + Last_Sloc => Local_Sloc (End_Sloc (N.Sloc_Range)))), + Name => +Langkit_Support.Text.To_UTF8 (Decl.P_Defining_Name.F_Name.Text), - Sloc => Local_Sloc (Sloc (N)), - Identifier => + Sloc => Local_Sloc (Sloc (N)), + Identifier => (Decl_SFI => Decl_SFI, - Decl_Line => Natural (Decl.Sloc_Range.Start_Line))); + Decl_Line => Natural (Decl.Sloc_Range.Start_Line)), + Start_SCO => SCO_Id (SCOs.SCO_Table.Last + 1)); Inserted : Scope_Entities_Trees.Cursor; begin UIC.Scope_Entities.Insert_Child @@ -8044,20 +8046,16 @@ package body Instrument.Ada_Unit is procedure Exit_Scope (UIC : in out Ada_Unit_Inst_Context) is use Scope_Entities_Trees; + Cur_Scope : Scope_Entity renames + Scope_Entities_Trees.Element (UIC.Current_Scope_Entity); Parent_Scope : constant Cursor := Parent (UIC.Current_Scope_Entity); -- Latch the parent value before UIC.Current_Scope_Entity is freed - Scope : constant Reference_Type := - UIC.Scope_Entities.Reference (UIC.Current_Scope_Entity); begin - -- Update the last SCO for this scope entity - - Scope.To := SCO_Id (SCOs.SCO_Table.Last); - -- If the scope has no SCO (it could be possible for a package spec with -- only subprogram declarations for instance), discard it. - if Scope.To < Scope.From then + if SCO_Id (SCOs.SCO_Table.Last) < Cur_Scope.Start_SCO then UIC.Scope_Entities.Delete_Leaf (UIC.Current_Scope_Entity); end if; @@ -10277,11 +10275,6 @@ package body Instrument.Ada_Unit is end loop; Set_Bit_Maps (UIC.CU, Bit_Maps); - - -- Remap low level SCOS in Scope_Entity records to high-level SCOs. - -- See the comment for Scope_Entity.From/To. - - Remap_Scope_Entities (UIC.Scope_Entities, SCO_Map); Set_Scope_Entities (UIC.CU, UIC.Scope_Entities); -- Remap low level SCOs in blocks to high level SCOs @@ -10393,9 +10386,6 @@ package body Instrument.Ada_Unit is CU_Name : constant Compilation_Unit_Part := CU_Names.Element (I); CU : constant CU_Id := CUs.Element (I); - Fingerprint : Unbounded_String; - -- Fingerprint for the instrumented unit - Unit_Name : constant String := Ada.Characters.Handling.To_Lower (To_Ada (CU_Name.Unit)); -- Lower-case name for the instrumented unit @@ -10417,24 +10407,10 @@ package body Instrument.Ada_Unit is Suffix : constant String := "_" & Img (I); - begin - -- Turn the fingerprint value into the corresponding Ada literal - - declare - First : Boolean := True; - begin - Append (Fingerprint, "("); - for Byte of SC_Obligations.Fingerprint (CU) loop - if First then - First := False; - else - Append (Fingerprint, ", "); - end if; - Append (Fingerprint, Strings.Img (Integer (Byte))); - end loop; - Append (Fingerprint, ")"); - end; + SCOs_Fingerprint : constant SC_Obligations.Fingerprint_Type := + SC_Obligations.Fingerprint (CU); + begin -- Create declarations for individual buffers (statement, decision -- and MC/DC) as well as their exported addresses. Put this in -- an individual package, to avoid having to suffix each @@ -10484,24 +10460,25 @@ package body Instrument.Ada_Unit is File.Put_Line (" Buffers : aliased constant" & " GNATcov_RTS_Coverage_Buffers :="); File.Put_Line (" (Fingerprint => " - & Format_Fingerprint - (SC_Obligations.Fingerprint (CU)) - & ","); + & Format_Fingerprint (SCOs_Fingerprint) & ","); File.Put_Line (" Language => Unit_Based_Language,"); File.Put_Line (" Unit_Part => " & Unit_Part & ","); File.Put_Line (" Unit_Name =>" & " (Unit_Name'Address, Unit_Name'Length),"); - File.Put_Line (" Bit_Maps_Fingerprint => " - & Format_Fingerprint - (SC_Obligations.Bit_Maps_Fingerprint (CU)) - & ","); + File.Put_Line + (" Bit_Maps_Fingerprint => " + & Format_Fingerprint + (SC_Obligations.Bit_Maps_Fingerprint (CU, SCOs_Fingerprint)) + & ","); - File.Put_Line (" Annotations_Fingerprint => " - & Format_Fingerprint - (SC_Obligations.Annotations_Fingerprint (CU)) - & ","); + File.Put_Line + (" Annotations_Fingerprint => " + & Format_Fingerprint + (SC_Obligations.Annotations_Fingerprint + (CU, SCOs_Fingerprint)) + & ","); File.Put_Line (" Statement => Statement_Buffer'Address,"); File.Put_Line (" Decision => Decision_Buffer'Address,"); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index a6a05abae..1fb6a3723 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -202,15 +202,6 @@ package body Instrument.C is -- generated SCO (SCOs.SCO_Table.Last) is the last SCO for the current -- scope. - procedure Remap_Scopes - (Scopes : in out Scopes_In_Files_Map.Map; - SCO_Map : LL_HL_SCO_Map); - -- Convert low level SCOs in each scope for each file to high-level SCOs - -- using the mapping in SCO_Map. Set the file's SCO range to cover all of - -- its scopes' SCO ranges. - -- - -- Also remove from the Scopes map empty file scopes. - overriding procedure Append_SCO (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; @@ -709,13 +700,17 @@ package body Instrument.C is File_Scope : constant Scopes_In_Files_Map.Reference_Type := UIC.Scopes.Reference (File_Scope_Position); New_Scope_Ent : constant Scope_Entity := - (From => SCO_Id (SCOs.SCO_Table.Last + 1), - To => No_SCO_Id, - Start_Sloc => (Line => 1, Column => 0), - End_Sloc => No_Local_Location, - Name => +Get_Simple_Name (SFI), - Sloc => (Line => 1, Column => 0), - Identifier => (Decl_SFI => SFI, Decl_Line => 0)); + (Source_Range => Source_Location_Range' + (Source_File => SFI, + L => Local_Source_Location_Range' + (First_Sloc => (Line => 1, Column => 0), + Last_Sloc => (Line => Natural'Last, Column => 0))), + Name => +Get_Simple_Name (SFI), + Sloc => (Line => 1, Column => 0), + Identifier => (Decl_SFI => SFI, Decl_Line => 0), + Start_SCO => No_SCO_Id); + -- Set Last_Sloc to Natural'Last so that it defaults to the + -- whole file as long as the scope is not closed. Scope_Entity_Position : Scope_Entities_Trees.Cursor; begin @@ -753,13 +748,15 @@ package body Instrument.C is File_Scope : constant Scopes_In_Files_Map.Reference_Type := UIC.Scopes.Reference (C); New_Scope_Ent : constant Scope_Entity := - (From => SCO_Id (SCOs.SCO_Table.Last + 1), - To => No_SCO_Id, - Start_Sloc => Sloc.L, - End_Sloc => End_Sloc (N).L, + (Source_Range => Source_Location_Range' + (Source_File => File, + L => Local_Source_Location_Range' + (First_Sloc => Sloc.L, + Last_Sloc => End_Sloc (N).L)), Name => +Get_Decl_Name_Str (N), Sloc => Sloc.L, - Identifier => (Decl_SFI => File, Decl_Line => Sloc.L.Line)); + Identifier => (Decl_SFI => File, Decl_Line => Sloc.L.Line), + Start_SCO => No_SCO_Id); Inserted : Scope_Entities_Trees.Cursor; begin -- Add New_Scope_Ent to the children of the last open scope in the @@ -787,59 +784,14 @@ package body Instrument.C is is File_Scope_Ref : constant Scopes_In_Files_Map.Reference_Type := UIC.Scopes.Reference (UIC.Current_File_Scope); - Scope_Entity_Ref : constant Scope_Entities_Trees.Reference_Type := - File_Scope_Ref.Scope_Entities.Reference - (File_Scope_Ref.Current_Scope_Entity); Parent : constant Scope_Entities_Trees.Cursor := Scope_Entities_Trees.Parent (File_Scope_Ref.Current_Scope_Entity); begin - Scope_Entity_Ref.To := SCO_Id (SCOs.SCO_Table.Last); - - -- Discard the scope entity if it has no associated SCOs - - if Scope_Entity_Ref.To < Scope_Entity_Ref.From then - File_Scope_Ref.Scope_Entities.Delete_Leaf - (File_Scope_Ref.Current_Scope_Entity); - else - -- Update the last SCO for the file scope - - File_Scope_Ref.Scope_Entities.Reference - (File_Scope_Ref.File_Scope_Entity).To := Scope_Entity_Ref.To; - end if; - -- Go back to the parent scope entity File_Scope_Ref.Current_Scope_Entity := Parent; end Exit_Scope; - ------------------ - -- Remap_Scopes -- - ------------------ - - procedure Remap_Scopes - (Scopes : in out Scopes_In_Files_Map.Map; - SCO_Map : LL_HL_SCO_Map) - is - Res : Scopes_In_Files_Map.Map; - begin - for Cur in Scopes.Iterate loop - declare - File_Scope : File_Scope_Type := - Scopes_In_Files_Map.Element (Cur); - File_Scope_Entity : Scope_Entity renames - Scope_Entities_Trees.Element (File_Scope.File_Scope_Entity); - begin - -- If the file scope is empty, do not add it to the resulting map - - if File_Scope_Entity.To >= File_Scope_Entity.From then - Remap_Scope_Entities (File_Scope.Scope_Entities, SCO_Map); - Res.Insert (Scopes_In_Files_Map.Key (Cur), File_Scope); - end if; - end; - end loop; - Scopes := Res; - end Remap_Scopes; - ---------------- -- Append_SCO -- ---------------- @@ -4058,8 +4010,6 @@ package body Instrument.C is -- Iterate through the package level body entities - Remap_Scopes (UIC.Scopes, SCO_Map); - for C in UIC.Scopes.Iterate loop declare CU : constant Created_Unit_Maps.Cursor := @@ -4343,6 +4293,10 @@ package body Instrument.C is -- Name of the gnatcov_rts_coverage_buffers struct for this -- source file. + SCOs_Fingerprint : constant SC_Obligations.Fingerprint_Type := + SC_Obligations.Fingerprint (CU); + -- SCOs fingerprint for the unit + begin File.Put_Line ("/* Buffers for " & Get_Full_Name (SFI) & " */"); @@ -4377,7 +4331,7 @@ package body Instrument.C is & Buffers_Struct & " = {" & ASCII.LF & "/* .fingerprint = */ " - & Format_Fingerprint (SC_Obligations.Fingerprint (CU)) & "," + & Format_Fingerprint (SCOs_Fingerprint) & "," & ASCII.LF & "/* .language_kind = */ FILE_BASED_LANGUAGE," & ASCII.LF @@ -4401,13 +4355,15 @@ package body Instrument.C is & ASCII.LF & "/* .bit_maps_fingerprint = */ " - & Format_Fingerprint (SC_Obligations.Bit_Maps_Fingerprint (CU)) + & Format_Fingerprint + (SC_Obligations.Bit_Maps_Fingerprint (CU, SCOs_Fingerprint)) & "," & ASCII.LF & "/* .annotations_fingerprint = */ " & Format_Fingerprint - (SC_Obligations.Annotations_Fingerprint (CU)) + (SC_Obligations.Annotations_Fingerprint + (CU, SCOs_Fingerprint)) & "," & ASCII.LF diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 2b9491fbe..17ec3d141 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -355,25 +355,6 @@ package body Instrument.Common is SCOs.SCO_Table.Last; end Append_SCO; - ------------------------ - -- Remap_Scope_Entity -- - ------------------------ - - procedure Remap_Scope_Entities - (Scope_Entities : in out Scope_Entities_Tree; - SCO_Map : LL_HL_SCO_Map) is - begin - for Scope_Entity in Scope_Entities.Iterate loop - declare - Ref : constant Scope_Entities_Trees.Reference_Type := - Scope_Entities.Reference (Scope_Entity); - begin - Ref.From := SCO_Map (Nat (Ref.From)); - Ref.To := SCO_Map (Nat (Ref.To)); - end; - end loop; - end Remap_Scope_Entities; - ------------------ -- Remap_Blocks -- ------------------ diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index f0708f048..7eebcc511 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -422,12 +422,6 @@ package Instrument.Common is -- source file, also append a new entry to the SCO_Unit_Table, otherwise -- complete its last entry. - procedure Remap_Scope_Entities - (Scope_Entities : in out Scope_Entities_Tree; - SCO_Map : LL_HL_SCO_Map); - -- Convert low level SCOs in Scope_Entity to high-level SCOs using the - -- mapping in SCO_Map. - procedure Remap_Blocks (Blocks : in out SCO_Id_Vector_Vector; SCO_Map : LL_HL_SCO_Map); diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 7713a4951..704c34416 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -256,7 +256,7 @@ is -- If an instrumenter supports Source_File's language and if Project is not -- externally built, add Source_File to Project_Sources. - procedure Insert_Manual_Dump_Trigger + procedure Replace_Manual_Indications (Language : Src_Supported_Language; Project_Sources : in out File_Info_Sets.Set; Instrumenter : in out Language_Instrumenter'Class; @@ -883,14 +883,14 @@ is end Add_Instrumented_Unit; -------------------------------- - -- Insert_Manual_Dump_Trigger -- + -- Replace_Manual_Indications -- -------------------------------- - procedure Insert_Manual_Dump_Trigger - (Language : Src_Supported_Language; - Project_Sources : in out File_Info_Sets.Set; - Instrumenter : in out Language_Instrumenter'Class; - Manual_Dump_Inserted : in out Boolean; + procedure Replace_Manual_Indications + (Language : Src_Supported_Language; + Project_Sources : in out File_Info_Sets.Set; + Instrumenter : in out Language_Instrumenter'Class; + Manual_Dump_Inserted : in out Boolean; Manual_Indication_Files : File_Sets.Set) is @@ -1062,7 +1062,7 @@ is & " from a source in a parent project."); end; end if; - end Insert_Manual_Dump_Trigger; + end Replace_Manual_Indications; --------------------- -- Clean_And_Print -- @@ -1292,13 +1292,20 @@ begin -- Replace manual dump indications for C-like languages for Lang in C_Family_Language loop - Insert_Manual_Dump_Trigger + Replace_Manual_Indications (Lang, Project_Sources, Instrumenters (Lang).all, Manual_Dump_Inserted, Dump_Config.Manual_Indication_Files); end loop; + + -- The replacement of manual indications may incur filling of e.g. + -- the files table, which is then dumped into the first written + -- checkpoint before being cleared out. Preemptively clear it to avoid + -- that. + + Checkpoints.Checkpoint_Clear; end if; -- Write the files of interest to temporary files in the instrumentation @@ -1613,7 +1620,7 @@ begin end; if Dump_Config.Trigger = Manual then - Insert_Manual_Dump_Trigger + Replace_Manual_Indications (Ada_Language, Project_Sources, Ada_Instrumenter, diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index c9710c4c6..94c32b45d 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -23,6 +23,7 @@ with Ada.Strings.Fixed; use Ada.Strings.Fixed; with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Deallocation; +with GNATCOLL.VFS; with Interfaces; with Aspects; use Aspects; @@ -34,7 +35,6 @@ with Snames; with Checkpoints; use Checkpoints; with Coverage; use Coverage; -with Coverage.Source; with Diagnostics; use Diagnostics; with Files_Table; use Files_Table; with Inputs; use Inputs; @@ -64,8 +64,13 @@ package body SC_Obligations is -- * properly ordered: if E1 and E2 are consecutive siblings, E1.To must be -- smaller than E2.From. + function Floor + (Tree : Scope_Entities_Trees.Tree; + Sloc : Source_Location) return Scope_Entities_Trees.Cursor; + -- Return the innermost scope containing Sloc + function Covers_SCO (SE : Scope_Entity; SCO : SCO_Id) return Boolean - is (SCO in SE.From .. SE.To); + is (In_Range (First_Sloc (SCO), SE.Source_Range)); -- Return whether SCO is covered by SE's SCO range function Covers_SCO @@ -73,9 +78,12 @@ package body SC_Obligations is -- Return whether SCO is covered by that element's SCO range. Id the SCO is -- a function SCO, then the scope can be the root of the tree. - procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) with - Pre => Get_CU (ST) = No_CU_Id - or else SCO in First_SCO (Get_CU (ST)) .. Last_SCO (Get_CU (ST)); + function Contains_SCO (SCO : SCO_Id; CU : CU_Id) return Boolean; + -- Return whether the given CU contains the given SCO + + procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) + with Pre => Get_CU (ST) = No_CU_Id + or else Contains_SCO (SCO, Get_CU (ST)); -- Position ST on the inner-most scope that contains SCO. -- -- This does nothing on a scope traversal type not initialized, or @@ -90,6 +98,29 @@ package body SC_Obligations is -- Source units table -- ------------------------ + type SID_Info is record + Blocks : SCO_Id_Vector_Vector; + -- List of blocks. A block is a list of statement SCOs. Note that + -- this is specific to source instrumentation, but a container cannot + -- be a discriminant-dependent component. + + Bit_Maps : CU_Bit_Maps; + -- Mapping of bits in coverage buffers to SCOs + + Bit_Maps_Fingerprint : Fingerprint_Type; + -- Hash of Bit_Maps, for consistency checks with source traces + + Annotations_Fingerprint : Fingerprint_Type := No_Fingerprint; + -- Hash of ALI_Annotations, for consistency checks with source traces + + end record; + -- Part of the information stored in a SID file, and needed to compute + -- coverage results. + + package SID_Info_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Fingerprint_Type, + Element_Type => SID_Info); + type CU_Info (Provider : SCO_Provider := SCO_Provider'First) is record Origin : Source_File_Index; -- File from which this unit's SCO info comes from. @@ -101,56 +132,63 @@ package body SC_Obligations is -- For Ada this is a simple name; for C this is either a simple name -- or full name, depending on whether the information is available. - First_SCO, Last_SCO : SCO_Id := No_SCO_Id; - -- First and last SCO ids for this unit - Deps : SFI_Vector; -- Mapping of this unit's dependency numbers to source file indices Has_Code : Boolean := False; -- Set True when object code for some source file in this unit is seen - Fingerprint : Fingerprint_Type; - -- Hash of SCO info in ALI, for incremental coverage consistency check - PP_Info_Map : SCO_PP_Info_Maps.Map; -- Information about preprocessing Scope_Entities : Scope_Entities_Tree := Scope_Entities_Trees.Empty_Tree; -- Scope tree, used to output e.g. subprogram metrics - Blocks : SCO_Id_Vector_Vector; - -- List of blocks. A block is a list of statement SCOs. Note that this - -- is specific to source instrumentation, but a container cannot be - -- a discriminant-dependent component. - ALI_Annotations : ALI_Annotation_Maps.Map; -- List of annotations for the unit - Annotations_Fingerprint : Fingerprint_Type := No_Fingerprint; - -- Hash of ALI_Annotations, for consistency checks with source traces + SCOs : SCO_Range_Vectors.Vector; + -- List of SCOs for this unit + + SIDs_Info : SID_Info_Maps.Map; + -- Mapping from SCOs fingerprint to SID information. A compilation + -- unit has various SID versions when it has varying SCOs: this can + -- happen when including a header file with varying inclusion + -- contexts (e.g. macro definition varying at the inclusion point). + -- Note that this is exclusively computing coverage results (e.g. + -- analyzing a trace along with SID files). + -- + -- Note that we only use the SID_Info when computing coverage results + -- resulting from instrumentation (and thus analyzing traces with SID + -- files). When retrieving coverage results from checkpoint, we only + -- need the list of SCOs fingerprints for quicker consolidation, so + -- this map elements will be empty. case Provider is when Compiler | LLVM => - null; + SCOs_Fingerprint : Fingerprint_Type; + -- Hash of SCO info in checkpoint, for incremental coverage + -- consistency check. when Instrumenter => - Bit_Maps : CU_Bit_Maps; - -- Mapping of bits in coverage buffers to SCOs - - Bit_Maps_Fingerprint : Fingerprint_Type; - -- Hash of Bit_Maps, for consistency checks with source traces + Source_Fingerprint : Fingerprint_Type; + -- Hash of source code in checkpoint, for incremental coverage + -- consistency check. Note that contrarily to binary traces, we + -- can have a varying set of SCOs from a checkpoint to another, + -- so we rely on the source code fingerprint rather than the + -- SCOs. True_Static_SCOs : SCO_Sets.Set; False_Static_SCOs : SCO_Sets.Set; - end case; + end case; end record; procedure Free (CU : in out CU_Info); function Has_SCOs (CUI : CU_Info) return Boolean is - (CUI.First_SCO <= CUI.Last_SCO); + (CUI.SCOs.Length > 0 + and then CUI.SCOs.First_Element.First <= CUI.SCOs.First_Element.Last); function Are_Bit_Maps_In_Range (Bit_Maps : CU_Bit_Maps; CU : CU_Info) return Boolean; @@ -429,7 +467,8 @@ package body SC_Obligations is when Decision => Expression : SCO_Id := No_SCO_Id; - -- Top expression node for this decision + -- Top expression node for this decision. This refers to the first + -- condition SCO of the decision. D_Kind : Decision_Kind; -- Decision kind indication @@ -527,9 +566,9 @@ package body SC_Obligations is -- contain data loaded from a checkpoint. type Source_Coverage_Vectors is record - CU_Vector : CU_Info_Vectors.Vector; - BDD_Vector : BDD.BDD_Vectors.Vector; - SCO_Vector : SCO_Vectors.Vector; + CU_Vector : CU_Info_Vectors.Vector; + BDD_Vector : BDD.BDD_Vectors.Vector; + SCO_Vector : SCO_Vectors.Vector; end record; function Index @@ -583,6 +622,11 @@ package body SC_Obligations is procedure Read (CLS : in out Checkpoint_Load_State; Value : out PP_Info); -- Read a PP_Info from CLS + procedure Read + (CLS : in out Checkpoint_Load_State; Fingerprint : out Fingerprint_Type); + -- Wrapper around CLS.Read_Fingerprint to accomodate for the Read_Map + -- instantiation below. + procedure Read is new Read_Map (Key_Type => SCO_Id, Element_Type => PP_Info, @@ -590,7 +634,7 @@ package body SC_Obligations is Clear => SCO_PP_Info_Maps.Clear, Insert => SCO_PP_Info_Maps.Insert, Read_Key => Read, - Read_element => Read); + Read_Element => Read); procedure Read (CLS : in out Checkpoint_Load_State; Value : out Scope_Entity); @@ -602,6 +646,29 @@ package body SC_Obligations is Multiway_Trees => Scope_Entities_Trees, Read_Element => Read); + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out SCO_Range); + -- Read a SCO_Range from CLS + + procedure Read is new Read_Vector + (Index_Type => Positive, + Element_Type => SCO_Range, + "=" => "=", + Vectors => SCO_Range_Vectors, + Read_Element => Read); + + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out SID_Info); + -- Read a SID_Info from CLS + + procedure Read is new Read_Map + (Key_Type => Fingerprint_Type, + Element_Type => SID_Info, + Map_Type => SID_Info_Maps.Map, + Clear => SID_Info_Maps.Clear, + Insert => SID_Info_Maps.Insert, + Read_Key => Read, + Read_Element => Read); procedure Read (CLS : in out Checkpoint_Load_State; Value : out CU_Info); -- Read a CU_Info from CLS @@ -661,32 +728,68 @@ package body SC_Obligations is Read_Element => Read); -- Read a ALI_Annotation_Maps.Map from CLS - procedure Checkpoint_Load_Merge_Unit - (CLS : in out Checkpoint_Load_State; - CP_Vectors : Source_Coverage_Vectors; + procedure Remap_BDD + (CP_Vectors : Source_Coverage_Vectors; + Relocs : in out Checkpoint_Relocations; + Decision_BDD : in out BDD.BDD_Type); + -- Remap a sequence of BDD nodes, for a whole decision BDD + + procedure Remap_BDD_Node + (Relocs : Checkpoint_Relocations; + B : in out BDD_Node_Id); + -- Remap a BDD node id + + procedure Remap_SCO_Id + (Relocs : Checkpoint_Relocations; + S : in out SCO_Id); + -- Remap a SCO_Id. Note: this assumes possible forward references, and + -- does not rely on SCO_Map. + + procedure Remap_SCO_Descriptor + (CP_Vectors : Source_Coverage_Vectors; CP_CU : CU_Info; - Real_CU_Id : CU_Id); - -- Load CU from checkpoint that corresponds to a current unit of interest - -- whose ID is Real_CU_Id. + Relocs : in out Checkpoint_Relocations; + SCOD : in out SCO_Descriptor); + -- Remap one SCO_Descriptor. Note that this assumes that + -- SCOD.Sloc_Range.Source_File has already been remapped. + -- + -- Note that this expects condition SCOs of a decision to have been + -- remapped calling Remap_SCO_Descriptor - procedure Checkpoint_Load_New_Unit + procedure Checkpoint_Load_SCOs (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; - New_CU_Id : out CU_Id); - -- Load CU from checkpoint that does not correspond to a current unit of - -- interest. The newly assigned CU_Id is returned in New_CU_Id. + Real_CU : in out CU_Info; + Real_CU_Id : CU_Id); + -- Load the SCOs in CP_CU and add them to Real_CU, which is the CU entry + -- for Real_CU_Id. + + procedure Checkpoint_Load_SID_Info + (CLS : in out Checkpoint_Load_State; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info); + -- Load the SID information entries in SIDs_Info and add them to Real_CU + + procedure Checkpoint_Load_PP_Info + (CLS : in out Checkpoint_Load_State; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info); + -- Load the preprocessing information in CP_CU and add them to Real_CU + + procedure Checkpoint_Load_Scopes + (CLS : in out Checkpoint_Load_State; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info); + -- Load the scopes in CP_CU and add them to Real_CU procedure Checkpoint_Load_Unit (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; - New_CU_Id : out CU_Id); + CP_CU_Id : CU_Id); -- Process one compilation unit from a checkpoint. -- CP_CU_Id is the CU_Id in the checkpoint. - -- New_CU_Id is the corresponding CU_Id in the current context, and is - -- either an already existing CU_Id (if the unit was already known), - -- or a newly assigned one (if not). ----------------------------------------- -- Helper routines for Checkpoint_Save -- @@ -726,6 +829,33 @@ package body SC_Obligations is Multiway_Trees => Scope_Entities_Trees, Write_Element => Write); + procedure Write + (CSS : in out Checkpoint_Save_State; Value : SID_Info); + -- Write a SID_Info to CSS + + procedure Write is new Write_Map + (Key_Type => Fingerprint_Type, + Element_Type => SID_Info, + Map_Type => SID_Info_Maps.Map, + Cursor_Type => SID_Info_Maps.Cursor, + Length => SID_Info_Maps.Length, + Iterate => SID_Info_Maps.Iterate, + Query_Element => SID_Info_Maps.Query_Element, + Write_Key => Write, + Write_Element => Write); + -- Write a vector of SID_Info records to CSS + + procedure Write (CSS : in out Checkpoint_Save_State; Value : SCO_Range); + -- Write a SCO_Range to CSS + + procedure Write is new Write_Vector + (Index_Type => Positive, + Element_Type => SCO_Range, + "=" => "=", + Vectors => SCO_Range_Vectors, + Write_Element => Write); + -- Write a vector of SCO_Range records to CSS + procedure Write (CSS : in out Checkpoint_Save_State; Value : CU_Info); -- Write a CU_Info to CSS @@ -845,9 +975,9 @@ package body SC_Obligations is SE : Scope_Entity renames Scope_Entities.Constant_Reference (Cur); begin - Put_Line (Prefix & Image (SE)); - Put_Line (Prefix & "... from " & Image (SE.From)); - Put_Line (Prefix & " to " & Image (SE.To)); + Put_Line + (Prefix & Image (SE) & " source range " + & Image (SE.Source_Range)); end; end loop; end Dump; @@ -877,8 +1007,10 @@ package body SC_Obligations is -- Traverse_SCO -- ------------------ - procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) is + procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) + is use Scope_Entities_Trees; + SCO_Sloc : constant Local_Source_Location := First_Sloc (SCO).L; begin -- Don't do anything if there is no scope attached to ST. @@ -938,8 +1070,9 @@ package body SC_Obligations is declare SE : constant Scope_Entity := Element (Child); begin - In_Child := SE.From <= SCO; - exit Child_Search when SE.To >= SCO; + In_Child := SE.Source_Range.L.First_Sloc <= SCO_Sloc; + exit Child_Search when + SCO_Sloc <= SE.Source_Range.L.Last_Sloc; Child := Next_Sibling (Child); end; end loop Child_Search; @@ -1015,22 +1148,78 @@ package body SC_Obligations is end loop; end Add_SCO_To_Lines; + --------------------- + -- Has_Fingerprint -- + --------------------- + + function Has_Fingerprint + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return Boolean is + begin + return + CU_Vector.Constant_Reference (CU).SIDs_Info.Contains (SCO_Fingerprint); + end Has_Fingerprint; + + ------------------ + -- Fingerprints -- + ------------------ + + function Fingerprints (CU : CU_Id) return Fingerprint_Vectors.Vector + is + Result : Fingerprint_Vectors.Vector; + begin + for Cur in CU_Vector.Reference (CU).SIDs_Info.Iterate loop + Result.Append (SID_Info_Maps.Key (Cur)); + end loop; + return Result; + end Fingerprints; + -------------- -- Bit_Maps -- -------------- - function Bit_Maps (CU : CU_Id) return CU_Bit_Maps is + function Bit_Maps + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return CU_Bit_Maps is begin - return CU_Vector.Reference (CU).Element.Bit_Maps; + return CU_Vector.Reference (CU) + .SIDs_Info.Element (SCO_Fingerprint).Bit_Maps; end Bit_Maps; + -------------------------- + -- Bit_Maps_Fingerprint -- + -------------------------- + + function Bit_Maps_Fingerprint + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return Fingerprint_Type is + begin + return CU_Vector.Constant_Reference (CU) + .SIDs_Info.Element (SCO_Fingerprint).Bit_Maps_Fingerprint; + end Bit_Maps_Fingerprint; + + ----------------------------- + -- Annotations_Fingerprint -- + ----------------------------- + + function Annotations_Fingerprint + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return Fingerprint_Type is + begin + return CU_Vector.Constant_Reference (CU) + .SIDs_Info.Element (SCO_Fingerprint).Annotations_Fingerprint; + end Annotations_Fingerprint; + ------------ -- Blocks -- ------------ - function Blocks (CU : CU_Id) return SCO_Id_Vector_Vector is + function Blocks + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return SCO_Id_Vector_Vector is begin - return CU_Vector.Reference (CU).Element.Blocks; + return CU_Vector.Reference (CU) + .SIDs_Info.Element (SCO_Fingerprint).Blocks; end Blocks; ----------------- @@ -1098,14 +1287,58 @@ package body SC_Obligations is end Read; procedure Read - (CLS : in out Checkpoint_Load_State; Value : out Scope_Entity) + (CLS : in out Checkpoint_Load_State; Fingerprint : out Fingerprint_Type) + is + begin + Fingerprint := CLS.Read_Fingerprint; + end Read; + + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out SID_Info) is + Stmt_First, DC_First, MCDC_First : Bit_Id; + Stmt_Last, DC_Last, MCDC_Last : Any_Bit_Id; begin - Value.From := CLS.Read_SCO; - Value.To := CLS.Read_SCO; + -- Read block information + + Read (CLS, Value.Blocks); + + -- Read bit maps + + Stmt_First := CLS.Read_Bit_Id; + Stmt_Last := CLS.Read_Bit_Id; + Value.Bit_Maps.Statement_Bits := + new Statement_Bit_Map (Stmt_First .. Stmt_Last); + for SCO of Value.Bit_Maps.Statement_Bits.all loop + SCO := CLS.Read_SCO; + end loop; + + DC_First := CLS.Read_Bit_Id; + DC_Last := CLS.Read_Bit_Id; + Value.Bit_Maps.Decision_Bits := + new Decision_Bit_Map (DC_First .. DC_Last); + for Info of Value.Bit_Maps.Decision_Bits.all loop + Info.D_SCO := CLS.Read_SCO; + Info.Outcome := CLS.Read_Boolean; + end loop; + + MCDC_First := CLS.Read_Bit_Id; + MCDC_Last := CLS.Read_Bit_Id; + Value.Bit_Maps.MCDC_Bits := + new MCDC_Bit_Map (MCDC_First .. MCDC_Last); + for Info of Value.Bit_Maps.MCDC_Bits.all loop + Info.D_SCO := CLS.Read_SCO; + Info.Path_Index := CLS.Read_Integer; + end loop; + Value.Bit_Maps_Fingerprint := CLS.Read_Fingerprint; + Value.Annotations_Fingerprint := CLS.Read_Fingerprint; + end Read; - Value.Start_Sloc := CLS.Read_Local_Source_Location; - Value.End_Sloc := CLS.Read_Local_Source_Location; + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out Scope_Entity) + is + begin + Value.Source_Range := CLS.Read_Source_Location_Range; Value.Name := CLS.Read_Unbounded_String; Value.Sloc := CLS.Read_Local_Source_Location; @@ -1114,76 +1347,33 @@ package body SC_Obligations is Value.Identifier.Decl_Line := CLS.Read_Integer; end Read; + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out SCO_Range) + is + begin + Value.First := CLS.Read_SCO; + Value.Last := CLS.Read_SCO; + end Read; + procedure Read (CLS : in out Checkpoint_Load_State; Value : out CU_Info) is Element_Template : CU_Info (SCO_Provider'Val (CLS.Read_U8)); begin Value := Element_Template; - - -- Checkpoint version 1 data - Value.Origin := CLS.Read_SFI; Value.Main_Source := CLS.Read_SFI; - Value.First_SCO := CLS.Read_SCO; - Value.Last_SCO := CLS.Read_SCO; Read (CLS, Value.Deps); Value.Has_Code := CLS.Read_Boolean; - Value.Fingerprint := CLS.Read_Fingerprint; Read (CLS, Value.PP_Info_Map); Read (CLS, Value.Scope_Entities); Read (CLS, Value.ALI_Annotations); - Value.Annotations_Fingerprint := CLS.Read_Fingerprint; - - case Value.Provider is + Read (CLS, Value.SCOs); + case Element_Template.Provider is when Compiler | LLVM => - null; + Value.SCOs_Fingerprint := CLS.Read_Fingerprint; when Instrumenter => - - -- By default, use "no fingerprint" for buffer bit maps - -- fingerprints: by design checkpoints contains neither bit maps - -- nor their fingerprints (all source traces are processed before - -- loading checkpoints, and bit maps are needed only to interpret - -- source traces). - - Value.Bit_Maps_Fingerprint := No_Fingerprint; - - if Purpose_Of (CLS) = Instrumentation then - declare - Stmt_First, DC_First, MCDC_First : Bit_Id; - Stmt_Last, DC_Last, MCDC_Last : Any_Bit_Id; - begin - Stmt_First := CLS.Read_Bit_Id; - Stmt_Last := CLS.Read_Bit_Id; - Value.Bit_Maps.Statement_Bits := - new Statement_Bit_Map (Stmt_First .. Stmt_Last); - for SCO of Value.Bit_Maps.Statement_Bits.all loop - SCO := CLS.Read_SCO; - end loop; - - DC_First := CLS.Read_Bit_Id; - DC_Last := CLS.Read_Bit_Id; - Value.Bit_Maps.Decision_Bits := - new Decision_Bit_Map (DC_First .. DC_Last); - for Info of Value.Bit_Maps.Decision_Bits.all loop - Info.D_SCO := CLS.Read_SCO; - Info.Outcome := CLS.Read_Boolean; - end loop; - - MCDC_First := CLS.Read_Bit_Id; - MCDC_Last := CLS.Read_Bit_Id; - Value.Bit_Maps.MCDC_Bits := - new MCDC_Bit_Map (MCDC_First .. MCDC_Last); - for Info of Value.Bit_Maps.MCDC_Bits.all loop - Info.D_SCO := CLS.Read_SCO; - Info.Path_Index := CLS.Read_Integer; - end loop; - end; - Value.Bit_Maps_Fingerprint := CLS.Read_Fingerprint; - - -- Read block information - - Read (CLS, Value.Blocks); - end if; + Read (CLS, Value.SIDs_Info); + Value.Source_Fingerprint := CLS.Read_Fingerprint; end case; end Read; @@ -1281,652 +1471,783 @@ package body SC_Obligations is Value.Undetermined_Cov_Count := 0; end Read; - -------------------------------- - -- Checkpoint_Load_Merge_Unit -- - -------------------------------- + function "<" (L, R : Static_Decision_Evaluation) return Boolean is + begin + if L.Outcome /= R.Outcome then + return L.Outcome < R.Outcome; + end if; + + for J in R.Values.First_Index .. R.Values.Last_Index loop + if J > L.Values.Last_Index then + return True; + + elsif L.Values.Element (J) < R.Values.Element (J) then + return True; - procedure Checkpoint_Load_Merge_Unit + elsif L.Values.Element (J) > R.Values.Element (J) then + return False; + end if; + end loop; + + return False; + end "<"; + + -------------------------- + -- Checkpoint_Load_SCOs -- + -------------------------- + + procedure Checkpoint_Load_SCOs (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; - CP_CU : CU_Info; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info; Real_CU_Id : CU_Id) is Relocs : Checkpoint_Relocations renames CLS.Relocations; - Real_CU : CU_Info renames CU_Vector.Reference (Real_CU_Id).Element.all; - procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) - with pre => Kind (New_SCO_Id) = Decision; + Cur_Source_File : Source_File_Index := No_Source_File; + Last_Line : Natural := 0; - ------------------------- - -- Merge_Decision_SCOs -- - ------------------------- + New_First_SCO : constant SCO_Id := SCO_Vector.Last_Index + 1; + begin + -- When loading a SCO, we check if it already exists: + -- * If it is the case, merge it and adequately set the bit map + -- relocation to the existing SCO. + -- * Otherwise, create it. + -- + -- The heuristic to consider that a SCO already exists or not is to + -- check for a SCO with the exact same source location. - procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) - is - use SC_Obligations.BDD; + for SCO_Range of CP_CU.SCOs loop + for Old_SCO_Id in SCO_Range.First .. SCO_Range.Last loop + declare + New_SCOD : SCO_Descriptor := + CP_Vectors.SCO_Vector.Element (Old_SCO_Id); - Old_SCOD : SCO_Descriptor renames CP_Vectors.SCO_Vector (Old_SCO_Id); - New_SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); + Real_SCO : SCO_Id := No_SCO_Id; + -- Value of the SCO if it already exists, otherwise left to + -- No_SCO_Id. To check if the SCO already exists, we use the + -- Sloc_To_SCO_Map and look for an existing SCO with the exact + -- same source range. - Old_Reachable : Reachability renames - Old_SCOD.Decision_BDD.Reachable_Outcomes; - New_Reachable : Reachability renames - New_SCOD.Decision_BDD.Reachable_Outcomes; + begin + if New_SCOD.Kind = Removed then + Ignore_SCO (Relocs, Old_SCO_Id); + goto Next_SCO; + end if; - function Decision_Static_Eval - (Vectors : Source_Coverage_Vectors; - SCO_Dec : SCO_Id; - Eval : out Static_Decision_Evaluation) return Boolean; + -- Remap SFIs in all source locations - procedure Register_Static_Evaluation - (SCO : SCO_Id; Eval : Static_Decision_Evaluation); + Remap_SFI (Relocs, New_SCOD.Sloc_Range.Source_File); - -------------------------- - -- Decision_Static_Eval -- - -------------------------- + -- Try to find if the SCO already exists - function Decision_Static_Eval - (Vectors : Source_Coverage_Vectors; - SCO_Dec : SCO_Id; - Eval : out Static_Decision_Evaluation) return Boolean - is - SCOD : SCO_Descriptor renames Vectors.SCO_Vector (SCO_Dec); + declare + use Sloc_To_SCO_Maps; + Cur : constant Cursor := + Files_Table.Sloc_To_SCO_Map + (New_SCOD.Sloc_Range.Source_File, + New_SCOD.Kind).Find (New_SCOD.Sloc_Range.L); + begin + if Has_Element (Cur) then + Real_SCO := Element (Cur); + end if; + end; - Reachable : constant Reachability := - SCOD.Decision_BDD.Reachable_Outcomes; + if Real_SCO /= No_SCO_Id then + loop + declare + Real_SCOD : constant SCO_Vectors.Reference_Type := + SCO_Vector.Reference (Real_SCO); + begin + exit when + Real_SCOD.Kind = New_SCOD.Kind + and then Real_SCOD.Sloc_Range = New_SCOD.Sloc_Range; + Real_SCO := Parent (Real_SCO); + exit when Real_SCO = No_SCO_Id; + end; + end loop; - Outcome : constant Tristate := - (if Reachable (False) /= Reachable (True) - then To_Tristate (Reachable (True)) - else Unknown); + -- If the SCO already exist, only add an entry to remap the + -- Old_SCO_Id to the actual SCO. - E : Static_Decision_Evaluation; - begin + if Real_SCO /= No_SCO_Id then + Set_SCO_Id_Map (Relocs, Old_SCO_Id, Real_SCO); + goto Next_SCO; + end if; + end if; - -- Do not process evaluations if the decision is not at least - -- partially static. + -- At this point, if Real_SCO is No_SCO_Id, this is a new SCO - if Outcome = Unknown then - return False; - end if; + if Real_SCO = No_SCO_Id then + Set_SCO_Id_Map + (Relocs, Old_SCO_Id, SCO_Vector.Last_Index + 1); - E.Outcome := To_Boolean (Outcome); + -- Append new SCOD and record mapping - for J in Condition_Index'First .. SCOD.Last_Cond_Index - loop - declare - SCO_C : constant SCO_Id := - Condition (Vectors, SCO_Dec, J); - SCOD_C : SCO_Descriptor renames - Vectors.SCO_Vector (SCO_C); - begin + Remap_SCO_Descriptor + (CP_Vectors, + CP_CU, + Relocs, + New_SCOD); - -- If an encountered Condition has no Value, then the - -- Decision is not fully static, abort processing + -- Preallocate line table entries for previous unit - if SCOD_C.Value = Unknown then - E.Values.Clear; - return False; + if New_SCOD.Sloc_Range.Source_File /= Cur_Source_File then + Prealloc_Lines (Cur_Source_File, Last_Line); + Cur_Source_File := New_SCOD.Sloc_Range.Source_File; + CU_Map.Include (Cur_Source_File, Real_CU_Id); + end if; + if New_SCOD.Kind in + Statement | Decision | Fun_Call_SCO_Kind | Guarded_Expr + then + Add_SCO_To_Lines (SCO_Vector.Last_Index + 1, New_SCOD); end if; - E.Values.Append (To_Boolean (SCOD_C.Value)); - end; - end loop; + Last_Line := Natural'Max + (Get_File (Cur_Source_File).Lines.Last_Index, + New_SCOD.Sloc_Range.L.Last_Sloc.Line); + SCO_Vector.Append (New_SCOD); - Eval := E; - return True; - end Decision_Static_Eval; + -- Add it into the Sloc_To_SCO_Map - -------------------------------- - -- Register_Static_Evaluation -- - -------------------------------- + declare + Map : constant access Sloc_To_SCO_Maps.Map := + Writeable_Sloc_To_SCO_Map + (New_SCOD.Sloc_Range.Source_File, + New_SCOD.Kind); + begin + Map.Insert (New_SCOD.Sloc_Range.L, SCO_Vector.Last_Index); + end; - procedure Register_Static_Evaluation - (SCO : SCO_Id; Eval : Static_Decision_Evaluation) is - begin - if not CLS.Static_Decision_Evaluations.Contains (SCO) - then - CLS.Static_Decision_Evaluations.Insert - (SCO, - Static_Decision_Evaluation_Sets.Empty_Set); - end if; - CLS.Static_Decision_Evaluations - .Reference (SCO) - .Include (Eval); - end Register_Static_Evaluation; + if SCOs_Trace.Is_Active then + SCOs_Trace.Trace + ("Loaded from checkpoint: " + & Image (SCO_Vector.Last_Index) + & " (was #" + & Trim (Old_SCO_Id'Img, Side => Ada.Strings.Both) + & " in checkpoint)"); + end if; + end if; + end; + <> + end loop; + end loop; - -- Start processing of Merge_Decision_SCOs + -- Add the newly created SCOs to Real_CU.SCOs - begin - if Old_SCOD.Decision_Instrumented then - New_SCOD.Decision_Instrumented := True; - end if; - if Old_SCOD.Decision_Instrumented_For_MCDC then - New_SCOD.Decision_Instrumented_For_MCDC := True; - end if; + if SCO_Vector.Last_Index >= New_First_SCO then + Real_CU.SCOs.Append + (SCO_Range'(First => New_First_SCO, Last => SCO_Vector.Last_Index)); + end if; + end Checkpoint_Load_SCOs; - -- The following code handles merging Decision SCOs that have a - -- different staticness over the 2 checkpoints that are being merged. - -- - -- If the reachability of the decision in one of the checkpoints - -- differs from `Both_Reachable`, it means that at least one of the - -- two checkpoints has some static conditions and should be handled - -- with a specific treatment. - -- - -- Upon encountering a fully-static decision, we need to register its - -- conditions' values so they can be used as a complementary - -- evaluation for MC/DC analysis. + ------------------------------ + -- Checkpoint_Load_SID_Info -- + ------------------------------ - if Old_Reachable /= Both_Reachable - or else - New_Reachable /= Both_Reachable - then - SCOs_Trace.Trace ("Consolidation encountered a decision SCO" - & " whose staticness may differ at" - & Image (New_SCOD.Sloc_Range)); - declare - Old_Eval : Static_Decision_Evaluation; - -- Holds the result of the static evaluation of Old_SCO - -- if Old_Static is True. Otherwise, it is invalid. + procedure Checkpoint_Load_SID_Info + (CLS : in out Checkpoint_Load_State; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info) + is + Relocs : Checkpoint_Relocations renames CLS.Relocations; + begin + for Cur in CP_CU.SIDs_Info.Iterate loop + declare + SID_Fingerprint : constant Fingerprint_Type := + SID_Info_Maps.Key (Cur); + SID_Version : SID_Info := SID_Info_Maps.Element (Cur); + begin + if not Real_CU.SIDs_Info.Contains (SID_Fingerprint) then - New_Eval : Static_Decision_Evaluation; - -- Holds the result of the static evaluation of New_SCO - -- if New_Static is True. Otherwise, it is invalid. + -- Remap bit map buffers - Old_Static : constant Boolean := - Decision_Static_Eval (CP_Vectors, Old_SCO_Id, Old_Eval); - New_Static : constant Boolean := - Decision_Static_Eval (SC_Vectors, New_SCO_Id, New_Eval); + if SID_Version.Bit_Maps.Statement_Bits /= null then + for S_SCO of SID_Version.Bit_Maps.Statement_Bits.all loop + Remap_SCO_Id (Relocs, S_SCO); + end loop; + end if; - begin + if SID_Version.Bit_Maps.Decision_Bits /= null then + for D_Outcome of SID_Version.Bit_Maps.Decision_Bits.all + loop + Remap_SCO_Id (Relocs, D_Outcome.D_SCO); + end loop; + end if; - -- No matter the staticness of the SCOs, we update the - -- reachability of each outcome by OR-ing the two checkpoints. + if SID_Version.Bit_Maps.MCDC_Bits /= null then + for D_Path of SID_Version.Bit_Maps.MCDC_Bits.all loop + Remap_SCO_Id (Relocs, D_Path.D_SCO); + end loop; + end if; - New_Reachable (True) := New_Reachable (True) or else - Old_Reachable (True); + -- Remap blocks information - New_Reachable (False) := New_Reachable (False) or else - Old_Reachable (False); + for Block_Cur in SID_Version.Blocks.Iterate loop + declare + Block_Ref : constant + SCO_Id_Vector_Vectors.Reference_Type := + SID_Version.Blocks.Reference (Block_Cur); + begin + for SCO_Cur in Block_Ref.Iterate loop + Remap_SCO_Id (Relocs, Block_Ref.Reference (SCO_Cur)); + end loop; + end; + end loop; - if Old_Static then + Real_CU.SIDs_Info.Insert (SID_Fingerprint, SID_Version); + end if; + end; + end loop; + end Checkpoint_Load_SID_Info; - -- If the decision in the Old checkpoint is static, - -- add an evaluation to the SCIs corresponding to it. + ----------------------------- + -- Checkpoint_Load_PP_Info -- + ----------------------------- - Register_Static_Evaluation (New_SCO_Id, Old_Eval); + procedure Checkpoint_Load_PP_Info + (CLS : in out Checkpoint_Load_State; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info) + is + use SCO_PP_Info_Maps; + Relocs : Checkpoint_Relocations renames CLS.Relocations; + begin + for Cur in CP_CU.PP_Info_Map.Iterate loop + declare + SCO : SCO_Id := Key (Cur); + Info : PP_Info := Element (Cur); + begin + if not Real_CU.PP_Info_Map.Contains (SCO) then + if Info.Kind = In_Expansion then + for Expansion of Info.Expansion_Stack loop + Remap_SFI + (Relocs, + Expansion.Sloc.Source_File); + end loop; + Remap_SFI + (Relocs, + Info.Definition_Loc.Sloc.Source_File); end if; + Remap_SCO_Id (Relocs, SCO); + Real_CU.PP_Info_Map.Insert (SCO, Info); + end if; + end; + end loop; + end Checkpoint_Load_PP_Info; - if New_Static then + ---------------------------- + -- Checkpoint_Load_Scopes -- + ---------------------------- - -- If the decision in the New checkpoint is static, - -- add an evaluation to the SCIs corresponding to it. + procedure Checkpoint_Load_Scopes + (CLS : in out Checkpoint_Load_State; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info) + is + Relocs : Checkpoint_Relocations renames CLS.Relocations; + begin + -- For scope entities, only add those that do not violate the + -- nesting and ordering of the structure - Register_Static_Evaluation (New_SCO_Id, New_Eval); - end if; - end; + for Scope_Ent of CP_CU.Scope_Entities loop + + -- Scopes whose identifier references ignored source files will + -- lose their identifier: such scopes will remain, but users + -- will not be able to mark them of interest. + + if SFI_Ignored (Relocs, Scope_Ent.Identifier.Decl_SFI) then + Scope_Ent.Identifier := No_Scope_Entity_Identifier; + else + Remap_SFI (Relocs, Scope_Ent.Identifier.Decl_SFI); end if; - end Merge_Decision_SCOs; - -- Start processing of Checkpoint_Load_Merge_Unit + Remap_SFI (Relocs, Scope_Ent.Source_Range.Source_File); - begin - -- Here we already have loaded full SCO information for this CU. There - -- are two things to do: - -- - -- * Populate the tables mapping the SCO for this unit in the checkpoint - -- to their counterparts in the current context, and merge - -- non-instrumented SCO information if available. - -- - -- * Merge the annotations - -- - -- * Merge the information about non instrumented SCOs. We consider that - -- a SCO was instrumented iff at least one merged unit has it - -- instrumented. + declare + use Scope_Entities_Trees; - -- SCOs + Real_Scope : constant Cursor := + Floor + (Real_CU.Scope_Entities, + Source_Location' + (Source_File => Scope_Ent.Source_Range.Source_File, + L => Scope_Ent.Source_Range.L.First_Sloc)); - pragma Assert (CP_CU.Last_SCO - CP_CU.First_SCO - = - Real_CU.Last_SCO - Real_CU.First_SCO); + Added_Scope : Boolean := False; + -- Whether the current Scope_Ent was added to the list of scopes + -- (it is a new scope that does not clash with existing scopes). - for Old_SCO_Id in CP_CU.First_SCO .. CP_CU.Last_SCO loop - Set_SCO_Id_Map (Relocs, Old_SCO_Id, - Old_SCO_Id - + Real_CU.First_SCO - - CP_CU.First_SCO); + begin + if not Scope_Entities_Trees.Has_Element (Real_Scope) then - declare + -- This is a new scope that do not nest with an existing + -- scope (basically the case of a new compilation unit). - Old_SCOD : SCO_Descriptor renames - CP_Vectors.SCO_Vector (Old_SCO_Id); - New_SCO_Id : constant SCO_Id := Remap_SCO_Id (Relocs, Old_SCO_Id); - SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); + Real_CU.Scope_Entities.Insert_Child + (Parent => Real_CU.Scope_Entities.Root, + Before => No_Element, + New_Item => Scope_Ent); + Added_Scope := True; + else + declare + Found_Scope_Ent : constant Scope_Entity := + Real_CU.Scope_Entities.Reference (Real_Scope); + Child : Cursor := + First_Child (Real_Scope); + Src_Range : constant Source_Location_Range := + Found_Scope_Ent.Source_Range; + begin - begin - case SCOD.Kind is - when Statement => - if Old_SCOD.Stmt_Instrumented then - SCOD.Stmt_Instrumented := True; - end if; + if Scope_Ent.Source_Range = Src_Range then - when Decision => - Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id); + -- The scope already exists: do nothing - when Fun_Call_SCO_Kind => - if Old_SCOD.Fun_Call_Instrumented then - SCOD.Fun_Call_Instrumented := True; - end if; + null; - when Guarded_Expr => - if Old_SCOD.GExpr_Instrumented then - SCOD.GExpr_Instrumented := True; - end if; + elsif Src_Range.L.First_Sloc < + Scope_Ent.Source_Range.L.First_Sloc + and then + Scope_Ent.Source_Range.L.Last_Sloc < + Src_Range.L.Last_Sloc + then + -- Check if it nests with the innermost scope entity. If + -- this is the case, insert it as a child. - when others => - null; - end case; - end; - end loop; + while Has_Element (Child) + and then Element (Child).Source_Range.L.First_Sloc + < Scope_Ent.Source_Range.L.First_Sloc + loop + Child := Next_Sibling (Child); + end loop; + Added_Scope := True; - -- Has_Code indication + if not Has_Element (Child) then - Real_CU.Has_Code := Real_CU.Has_Code or CP_CU.Has_Code; + -- Insert it as the last children - -- Remap ALI annotations and then merge them + Real_CU.Scope_Entities.Insert_Child + (Parent => Real_Scope, + Before => No_Element, + New_Item => Scope_Ent); - declare - Remapped_Annotations : ALI_Annotation_Maps.Map := - CP_CU.ALI_Annotations; - begin - Remap_ALI_Annotations (Relocs, Remapped_Annotations); - for Cur in Remapped_Annotations.Iterate loop - Real_CU.ALI_Annotations.Include - (ALI_Annotation_Maps.Key (Cur), - ALI_Annotation_Maps.Element (Cur)); - end loop; - end; - end Checkpoint_Load_Merge_Unit; + else + -- Insert it before the identified child - function "<" (L, R : Static_Decision_Evaluation) return Boolean is - begin - if L.Outcome /= R.Outcome then - return L.Outcome < R.Outcome; - end if; + Real_CU.Scope_Entities.Insert_Child + (Parent => Real_Scope, + Before => Child, + New_Item => Scope_Ent); - for J in R.Values.First_Index .. R.Values.Last_Index loop - if J > L.Values.Last_Index then - return True; + end if; + else + -- Discard overlapping cases + + Outputs.Fatal_Error + ("Scope " + & (+Scope_Ent.Name) + & " at source location: " + & Image (Scope_Ent.Source_Range) + & " clashes with scope " + & (+Found_Scope_Ent.Name) + & " at location: " + & Image (Found_Scope_Ent.Source_Range)); + end if; + end; + end if; - elsif L.Values.Element (J) < R.Values.Element (J) then - return True; + -- Register each scope identifiers to make them available to + -- users on the command line. - elsif L.Values.Element (J) > R.Values.Element (J) then - return False; - end if; + if Added_Scope then + Available_Subps_Of_Interest.Include (Scope_Ent.Identifier); + end if; + end; end loop; + pragma Assert (SCOs_Nested_And_Ordered (Real_CU.Scope_Entities)); + end Checkpoint_Load_Scopes; - return False; - end "<"; - - ------------------------------ - -- Checkpoint_Load_New_Unit -- - ------------------------------ + --------------- + -- Remap_BDD -- + --------------- - procedure Checkpoint_Load_New_Unit - (CLS : in out Checkpoint_Load_State; - CP_Vectors : Source_Coverage_Vectors; - CP_CU : in out CU_Info; - New_CU_Id : out CU_Id) + procedure Remap_BDD + (CP_Vectors : Source_Coverage_Vectors; + Relocs : in out Checkpoint_Relocations; + Decision_BDD : in out BDD.BDD_Type) is - Relocs : Checkpoint_Relocations renames CLS.Relocations; + CP_First : constant BDD_Node_Id := Decision_BDD.First_Node; + CP_Last : constant BDD_Node_Id := Decision_BDD.Last_Node; + New_First : constant BDD_Node_Id := BDD_Vector.Last_Index + 1; + begin + -- Import the relevant BDD nodes from CP_Vectors.BDD_Vector - New_First_SCO : SCO_Id; + for Old_BDD_Node_Id in CP_First .. CP_Last loop + declare + -- We are supposed to remap individual BDD nodes only once - Cur_Source_File : Source_File_Index := No_Source_File; - Last_Line : Natural := 0; + New_BDD_Node : BDD.BDD_Node := + CP_Vectors.BDD_Vector.Element (Old_BDD_Node_Id); - procedure Remap_BDD (Decision_BDD : in out BDD.BDD_Type); - -- Remap a sequence of BDD nodes, for a whole decision BDD + procedure Remap_BDD_Node_Id (S : in out BDD_Node_Id); + -- Remap a BDD node id - procedure Remap_BDD_Node (B : in out BDD_Node_Id); - -- Remap a BDD node id + ----------------------- + -- Remap_BDD_Node_Id -- + ----------------------- - procedure Remap_SCO_Id (S : in out SCO_Id); - -- Remap a SCO_Id. Note: this assumes possible forward references, and - -- does not rely on SCO_Map. + procedure Remap_BDD_Node_Id (S : in out BDD_Node_Id) is + begin + if S /= No_BDD_Node_Id then + S := S - CP_First + New_First; + end if; + end Remap_BDD_Node_Id; - --------------- - -- Remap_BDD -- - --------------- + begin + case New_BDD_Node.Kind is + when BDD.Condition => + Remap_BDD_Node_Id (New_BDD_Node.Parent); + for Valuation in New_BDD_Node.Dests'Range loop + Remap_BDD_Node_Id + (New_BDD_Node.Dests (Valuation)); + end loop; - procedure Remap_BDD (Decision_BDD : in out BDD.BDD_Type) is - CP_First : constant BDD_Node_Id := Decision_BDD.First_Node; - CP_Last : constant BDD_Node_Id := Decision_BDD.Last_Node; - New_First : constant BDD_Node_Id := BDD_Vector.Last_Index + 1; - begin - -- Import the relevant BDD nodes from CP_Vectors.BDD_Vector + -- Note that we leave New_BDD_Node.C_SCO unremapped here: + -- the loading of the corresponding SCO condition will + -- take care of it (see below). - for Old_BDD_Node_Id in CP_First .. CP_Last loop - declare - -- We are supposed to remap individual BDD nodes only once + when BDD.Jump => + Remap_BDD_Node_Id (New_BDD_Node.Dest); - New_BDD_Node : BDD.BDD_Node := - CP_Vectors.BDD_Vector.Element (Old_BDD_Node_Id); + when others => + null; + end case; - procedure Remap_BDD_Node_Id (S : in out BDD_Node_Id); - -- Remap a BDD node id + BDD_Vector.Append (New_BDD_Node); + Set_BDD_Node_Id_Map + (Relocs, Old_BDD_Node_Id, BDD_Vector.Last_Index); + end; + end loop; - ----------------------- - -- Remap_BDD_Node_Id -- - ----------------------- + -- Remap IDs in Decision_BDD - procedure Remap_BDD_Node_Id (S : in out BDD_Node_Id) is - begin - if S /= No_BDD_Node_Id then - S := S - CP_First + New_First; - end if; - end Remap_BDD_Node_Id; + Remap_SCO_Id (Relocs, Decision_BDD.Decision); - begin - case New_BDD_Node.Kind is - when BDD.Condition => - Remap_BDD_Node_Id (New_BDD_Node.Parent); - for Valuation in New_BDD_Node.Dests'Range loop - Remap_BDD_Node_Id - (New_BDD_Node.Dests (Valuation)); - end loop; + Remap_BDD_Node (Relocs, Decision_BDD.Root_Condition); + Remap_BDD_Node (Relocs, Decision_BDD.First_Node); + Remap_BDD_Node (Relocs, Decision_BDD.Last_Node); + Remap_BDD_Node (Relocs, Decision_BDD.First_Multipath_Condition); + end Remap_BDD; - -- Note that we leave New_BDD_Node.C_SCO unremapped here: - -- the loading of the corresponding SCO condition will - -- take care of it (see below). + -------------------- + -- Remap_BDD_Node -- + -------------------- - when BDD.Jump => - Remap_BDD_Node_Id (New_BDD_Node.Dest); + procedure Remap_BDD_Node + (Relocs : Checkpoint_Relocations; + B : in out BDD_Node_Id) is + begin + if B /= No_BDD_Node_Id then + B := Remap_BDD_Node_Id (Relocs, B); + pragma Assert (B /= No_BDD_Node_Id); + end if; + end Remap_BDD_Node; - when others => - null; - end case; + ------------------ + -- Remap_SCO_Id -- + ------------------ - BDD_Vector.Append (New_BDD_Node); - Set_BDD_Node_Id_Map - (Relocs, Old_BDD_Node_Id, BDD_Vector.Last_Index); - end; - end loop; + procedure Remap_SCO_Id + (Relocs : Checkpoint_Relocations; + S : in out SCO_Id) is + begin + S := Checkpoints.Remap_SCO_Id (Relocs, S); + end Remap_SCO_Id; - -- Remap IDs in Decision_BDD + -------------------------- + -- Remap_SCO_Descriptor -- + -------------------------- - Remap_SCO_Id (Decision_BDD.Decision); + procedure Remap_SCO_Descriptor + (CP_Vectors : Source_Coverage_Vectors; + CP_CU : CU_Info; + Relocs : in out Checkpoint_Relocations; + SCOD : in out SCO_Descriptor) + is + pragma Unreferenced (CP_CU); + New_First_SCO : SCO_Id := SCO_Vector.Last_Index + 1; + begin + -- If this is a decision, start by recording all of the operator + -- and condition SCOs in the relocation map, before relocating all + -- of the components of the SCO_Descriptor. - Remap_BDD_Node (Decision_BDD.Root_Condition); - Remap_BDD_Node (Decision_BDD.First_Node); - Remap_BDD_Node (Decision_BDD.Last_Node); - Remap_BDD_Node (Decision_BDD.First_Multipath_Condition); - end Remap_BDD; + case SCOD.Kind is + when Decision => + declare + Expr_SCO : SCO_Id := SCOD.Expression - 1; + Expr_SCOD : SCO_Descriptor := + CP_Vectors.SCO_Vector.Element (Expr_SCO); + begin + loop + Expr_SCO := Expr_SCO + 1; + exit when Expr_SCO > CP_Vectors.SCO_Vector.Last_Index; + Expr_SCOD := CP_Vectors.SCO_Vector.Element (Expr_SCO); + exit when Expr_SCOD.Kind not in Condition | Operator; + New_First_SCO := New_First_SCO + 1; + Set_SCO_Id_Map (Relocs, Expr_SCO, New_First_SCO); + end loop; + end; + when others => + null; + end case; - -------------------- - -- Remap_BDD_Node -- - -------------------- + SCOD.Origin := Remap_CU_Id (Relocs, SCOD.Origin); - procedure Remap_BDD_Node (B : in out BDD_Node_Id) is - begin - if B /= No_BDD_Node_Id then - B := Remap_BDD_Node_Id (Relocs, B); - pragma Assert (B /= No_BDD_Node_Id); - end if; - end Remap_BDD_Node; + -- Remap SCO_Ids - ------------------ - -- Remap_SCO_Id -- - ------------------ + Remap_SCO_Id (Relocs, SCOD.Parent); - procedure Remap_SCO_Id (S : in out SCO_Id) is - begin - if S /= No_SCO_Id then - S := New_First_SCO + S - CP_CU.First_SCO; - pragma Assert (S /= No_SCO_Id); - end if; - end Remap_SCO_Id; + -- Make further adjustments based on SCO kind + -- In particular reset all components that reference + -- data that is not saved to checkpoint files (such as + -- BDD information). - -- Start of processing for Checkpoint_Load_New_Unit + case SCO_Kind (SCOD.Kind) is + when Statement => + Remap_SFI (Relocs, SCOD.Dominant_Sloc.Source_File); + Remap_SFI (Relocs, SCOD.Handler_Range.Source_File); - begin - New_CU_Id := CU_Vector.Last_Index + 1; + Remap_SCO_Id (Relocs, SCOD.Dominant); - CU_Map.Insert (CP_CU.Main_Source, New_CU_Id); + when Decision => + Remap_SCO_Id (Relocs, SCOD.Expression); + Remap_SFI (Relocs, SCOD.Control_Location.Source_File); + Remap_BDD (CP_Vectors, Relocs, SCOD.Decision_BDD); - -- Remap SCO ids. Note that BDD nodes are imported (and remapped) as - -- needed during the process. + when Operator => + for Op_SCO in SCOD.Operands'Range loop + Remap_SCO_Id (Relocs, SCOD.Operands (Op_SCO)); + end loop; - New_First_SCO := SCO_Vector.Last_Index + 1; - for Old_SCO_Id in CP_CU.First_SCO .. CP_CU.Last_SCO loop - declare - New_SCOD : SCO_Descriptor := - CP_Vectors.SCO_Vector.Element (Old_SCO_Id); - begin - if New_SCOD.Kind = Removed then - Ignore_SCO (Relocs, Old_SCO_Id); - goto Next_SCO; - end if; + when Condition => + Remap_BDD_Node (Relocs, SCOD.BDD_Node); + Remap_SCO_Id + (Relocs, BDD_Vector.Reference (SCOD.BDD_Node).C_SCO); - New_SCOD.Origin := New_CU_Id; + SCOD.PC_Set.Clear; - -- Remap SFIs in all source locations + when Fun_Call_SCO_Kind | Guarded_Expr => + null; - Remap_SFI (Relocs, New_SCOD.Sloc_Range.Source_File); + end case; + end Remap_SCO_Descriptor; - -- Preallocate line table entries for previous unit + -------------------------- + -- Checkpoint_Load_Unit -- + -------------------------- - if New_SCOD.Sloc_Range.Source_File /= Cur_Source_File then - Prealloc_Lines (Cur_Source_File, Last_Line); - Cur_Source_File := New_SCOD.Sloc_Range.Source_File; - CU_Map.Include (Cur_Source_File, New_CU_Id); - end if; + procedure Checkpoint_Load_Unit + (CLS : in out Checkpoint_Load_State; + CP_Vectors : Source_Coverage_Vectors; + CP_CU : in out CU_Info; + CP_CU_Id : CU_Id) + is + Relocs : Checkpoint_Relocations renames CLS.Relocations; - Last_Line := Natural'Max - (Last_Line, - New_SCOD.Sloc_Range.L.Last_Sloc.Line); + procedure Ignore_SCOs; + -- Mark all the SCOs in CP_CU as being ignored. This is useful when + -- skipping coverage information for a unit because the consistency + -- checks failed. - -- Remap SCO_Ids + procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) + with Pre => Kind (New_SCO_Id) = Decision; - Remap_SCO_Id (New_SCOD.Parent); + ------------------------- + -- Merge_Decision_SCOs -- + ------------------------- - -- Make further adjustments based on SCO kind - -- In particular reset all components that reference - -- data that is not saved to checkpoint files (such as - -- BDD information). + procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) + is + use SC_Obligations.BDD; - case SCO_Kind (New_SCOD.Kind) is - when Statement => - Remap_SFI (Relocs, New_SCOD.Dominant_Sloc.Source_File); - Remap_SFI (Relocs, New_SCOD.Handler_Range.Source_File); + Old_SCOD : SCO_Descriptor renames CP_Vectors.SCO_Vector (Old_SCO_Id); + New_SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); - Remap_SCO_Id (New_SCOD.Dominant); + Old_Reachable : Reachability renames + Old_SCOD.Decision_BDD.Reachable_Outcomes; + New_Reachable : Reachability renames + New_SCOD.Decision_BDD.Reachable_Outcomes; - when Decision => - Remap_SCO_Id (New_SCOD.Expression); - Remap_SFI (Relocs, New_SCOD.Control_Location.Source_File); - Remap_BDD (New_SCOD.Decision_BDD); + function Decision_Static_Eval + (Vectors : Source_Coverage_Vectors; + SCO_Dec : SCO_Id; + Eval : out Static_Decision_Evaluation) return Boolean; - when Operator => - for Op_SCO in New_SCOD.Operands'Range loop - Remap_SCO_Id (New_SCOD.Operands (Op_SCO)); - end loop; + procedure Register_Static_Evaluation + (SCO : SCO_Id; Eval : Static_Decision_Evaluation); - when Condition => - Remap_BDD_Node (New_SCOD.BDD_Node); - Remap_SCO_Id - (BDD_Vector.Reference (New_SCOD.BDD_Node).C_SCO); + -------------------------- + -- Decision_Static_Eval -- + -------------------------- - New_SCOD.PC_Set.Clear; + function Decision_Static_Eval + (Vectors : Source_Coverage_Vectors; + SCO_Dec : SCO_Id; + Eval : out Static_Decision_Evaluation) return Boolean + is + SCOD : SCO_Descriptor renames Vectors.SCO_Vector (SCO_Dec); - when Fun_Call_SCO_Kind | Guarded_Expr => - null; + Reachable : constant Reachability := + SCOD.Decision_BDD.Reachable_Outcomes; - end case; + Outcome : constant Tristate := + (if Reachable (False) /= Reachable (True) + then To_Tristate (Reachable (True)) + else Unknown); - -- Append new SCOD and record mapping + E : Static_Decision_Evaluation; + begin - SCO_Vector.Append (New_SCOD); - Set_SCO_Id_Map (Relocs, Old_SCO_Id, SCO_Vector.Last_Index); - if SCOs_Trace.Is_Active then - SCOs_Trace.Trace - ("Loaded from checkpoint: " - & Image (SCO_Vector.Last_Index) - & " (was #" & Trim (Old_SCO_Id'Img, Side => Ada.Strings.Both) - & " in checkpoint)"); + -- Do not process evaluations if the decision is not at least + -- partially static. + + if Outcome = Unknown then + return False; end if; - end; - <> null; - end loop; + E.Outcome := To_Boolean (Outcome); - -- Remap SCO_Ids in source trace bit maps + for J in Condition_Index'First .. SCOD.Last_Cond_Index + loop + declare + SCO_C : constant SCO_Id := + Condition (Vectors, SCO_Dec, J); + SCOD_C : SCO_Descriptor renames + Vectors.SCO_Vector (SCO_C); + begin - if CP_CU.Provider = Instrumenter then - if CP_CU.Bit_Maps.Statement_Bits /= null then - for S_SCO of CP_CU.Bit_Maps.Statement_Bits.all loop - Remap_SCO_Id (S_SCO); - end loop; - end if; + -- If an encountered Condition has no Value, then the + -- Decision is not fully static, abort processing - if CP_CU.Bit_Maps.Decision_Bits /= null then - for D_Outcome of CP_CU.Bit_Maps.Decision_Bits.all loop - Remap_SCO_Id (D_Outcome.D_SCO); - end loop; - end if; + if SCOD_C.Value = Unknown then + E.Values.Clear; + return False; + end if; - if CP_CU.Bit_Maps.MCDC_Bits /= null then - for D_Path of CP_CU.Bit_Maps.MCDC_Bits.all loop - Remap_SCO_Id (D_Path.D_SCO); + E.Values.Append (To_Boolean (SCOD_C.Value)); + end; end loop; - end if; - - -- Remap blocks information - for Block_Cur in CP_CU.Blocks.Iterate loop - declare - Block_Ref : constant SCO_Id_Vector_Vectors.Reference_Type := - CP_CU.Blocks.Reference (Block_Cur); - begin - for SCO_Cur in Block_Ref.Iterate loop - Remap_SCO_Id (Block_Ref.Reference (SCO_Cur)); - end loop; - end; - end loop; + Eval := E; + return True; + end Decision_Static_Eval; - -- Remap macro information + -------------------------------- + -- Register_Static_Evaluation -- + -------------------------------- - declare - use SCO_PP_Info_Maps; - Remapped_PP_Info_Map : SCO_PP_Info_Maps.Map; + procedure Register_Static_Evaluation + (SCO : SCO_Id; Eval : Static_Decision_Evaluation) is begin - for Cur in CP_CU.PP_Info_Map.Iterate loop - declare - Info : PP_Info := Element (Cur); - begin - if Info.Kind = In_Expansion then - for Expansion of Info.Expansion_Stack loop - Remap_SFI - (Relocs, - Expansion.Sloc.Source_File); - end loop; - Remap_SFI - (Relocs, - Info.Definition_Loc.Sloc.Source_File); - end if; - declare - SCO : SCO_Id := Key (Cur); - begin - Remap_SCO_Id (SCO); - Remapped_PP_Info_Map.Insert (SCO, Info); - end; - end; - end loop; - CP_CU.PP_Info_Map := Remapped_PP_Info_Map; - end; - - -- Remap SCOs span for scope entities + if not CLS.Static_Decision_Evaluations.Contains (SCO) + then + CLS.Static_Decision_Evaluations.Insert + (SCO, + Static_Decision_Evaluation_Sets.Empty_Set); + end if; + CLS.Static_Decision_Evaluations + .Reference (SCO) + .Include (Eval); + end Register_Static_Evaluation; - for Scope_Ent of CP_CU.Scope_Entities loop - Remap_SCO_Id (Scope_Ent.From); - Remap_SCO_Id (Scope_Ent.To); + -- Start processing of Merge_Decision_SCOs - -- Scopes whose identifier references ignored source files will - -- lose their identifier: such scopes will remain, but users will - -- not be able to mark them of interest. + begin + if Old_SCOD.Decision_Instrumented then + New_SCOD.Decision_Instrumented := True; + end if; + if Old_SCOD.Decision_Instrumented_For_MCDC then + New_SCOD.Decision_Instrumented_For_MCDC := True; + end if; - if SFI_Ignored (Relocs, Scope_Ent.Identifier.Decl_SFI) then - Scope_Ent.Identifier := No_Scope_Entity_Identifier; - else - Remap_SFI (Relocs, Scope_Ent.Identifier.Decl_SFI); - end if; + -- The following code handles merging Decision SCOs that have a + -- different staticness over the 2 checkpoints that are being merged. + -- + -- If the reachability of the decision in one of the checkpoints + -- differs from `Both_Reachable`, it means that at least one of the + -- two checkpoints has some static conditions and should be handled + -- with a specific treatment. + -- + -- Upon encountering a fully-static decision, we need to register its + -- conditions' values so they can be used as a complementary + -- evaluation for MC/DC analysis. - -- Register each scope identifiers to make them available to users - -- on the command line. + if Old_Reachable /= Both_Reachable + or else + New_Reachable /= Both_Reachable + then + SCOs_Trace.Trace ("Consolidation encountered a decision SCO" + & " whose staticness may differ at" + & Image (New_SCOD.Sloc_Range)); + declare + Old_Eval : Static_Decision_Evaluation; + -- Holds the result of the static evaluation of Old_SCO + -- if Old_Static is True. Otherwise, it is invalid. - Available_Subps_Of_Interest.Include (Scope_Ent.Identifier); - end loop; - if not SCOs_Nested_And_Ordered (CP_CU.Scope_Entities) then - raise Program_Error - with "Error when loading scopes from checkpoints"; - end if; - end if; + New_Eval : Static_Decision_Evaluation; + -- Holds the result of the static evaluation of New_SCO + -- if New_Static is True. Otherwise, it is invalid. - -- Remap ALI annotations + Old_Static : constant Boolean := + Decision_Static_Eval (CP_Vectors, Old_SCO_Id, Old_Eval); + New_Static : constant Boolean := + Decision_Static_Eval (SC_Vectors, New_SCO_Id, New_Eval); - Remap_ALI_Annotations (Relocs, CP_CU.ALI_Annotations); + begin - -- Preallocate line table entries for last file + -- No matter the staticness of the SCOs, we update the + -- reachability of each outcome by OR-ing the two checkpoints. - Prealloc_Lines (Cur_Source_File, Last_Line); + New_Reachable (True) := New_Reachable (True) or else + Old_Reachable (True); - -- Link new SCOs to source line tables + New_Reachable (False) := New_Reachable (False) or else + Old_Reachable (False); - for SCO in New_First_SCO .. SCO_Vector.Last_Index loop - declare - SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); - begin - if SCOD.Kind in - Statement | Decision | Fun_Call_SCO_Kind | Guarded_Expr - then - Add_SCO_To_Lines (SCO, SCOD); - end if; - end; - end loop; + if Old_Static then - -- Perform final fixups and insert CU + -- If the decision in the Old checkpoint is static, + -- add an evaluation to the SCIs corresponding to it. - CP_CU.Last_SCO := - New_First_SCO - + CP_CU.Last_SCO - - CP_CU.First_SCO; - CP_CU.First_SCO := New_First_SCO; + Register_Static_Evaluation (New_SCO_Id, Old_Eval); + end if; - CU_Vector.Append (CP_CU); - Register_CU (New_CU_Id); + if New_Static then - -- If we are loading a SID file, create source coverage data structures. - -- There is no need to do it when loading a checkpoint: that checkpoint - -- was created loading a SID file, and thus already has the - -- corresponding SCI tables populated. + -- If the decision in the New checkpoint is static, + -- add an evaluation to the SCIs corresponding to it. - if CLS.Purpose = Instrumentation then - Coverage.Source.Initialize_SCI_For_Instrumented_CU (New_CU_Id); - end if; - end Checkpoint_Load_New_Unit; + Register_Static_Evaluation (New_SCO_Id, New_Eval); + end if; + end; + end if; + end Merge_Decision_SCOs; - -------------------------- - -- Checkpoint_Load_Unit -- - -------------------------- + ----------------- + -- Ignore_SCOs -- + ----------------- - procedure Checkpoint_Load_Unit - (CLS : in out Checkpoint_Load_State; - CP_Vectors : Source_Coverage_Vectors; - CP_CU : in out CU_Info; - New_CU_Id : out CU_Id) - is - Relocs : Checkpoint_Relocations renames CLS.Relocations; + procedure Ignore_SCOs is + begin + for SCO_Range of CP_CU.SCOs loop + for SCO in SCO_Range.First .. SCO_Range.Last loop + Ignore_SCO (Relocs, SCO); + end loop; + end loop; + end Ignore_SCOs; + + Actual_CU_Id : CU_Id; begin if CP_CU.Provider = Instrumenter then Instrumented_Units_Present := True; @@ -1938,11 +2259,11 @@ package body SC_Obligations is Remap_SFI (Relocs, CP_CU.Main_Source); for Dep_SFI of CP_CU.Deps loop - -- Units of interest can depend on units outside of the - -- scope of code coverage analysis. Keeping track of these - -- introduces clashes between stubbed units and the real - -- one, so they are excluded from checkpoints. Hence, allow - -- them to be missing here. + -- Units of interest can depend on units outside of the scope of + -- code coverage analysis. Keeping track of these introduces clashes + -- between stubbed units and the real one, so they are excluded from + -- checkpoints. Hence, allow them to be missing here. + if not SFI_Ignored (Relocs, Dep_SFI) then Remap_SFI (Relocs, Dep_SFI); end if; @@ -1950,30 +2271,19 @@ package body SC_Obligations is -- Next check whether this unit is already known - New_CU_Id := Comp_Unit (CP_CU.Main_Source); + Actual_CU_Id := Comp_Unit (CP_CU.Main_Source); SCOs_Trace.Trace - ("Remapped CU: id " & New_CU_Id'Img + ("Remapped CU: id " & Actual_CU_Id'Img & ", main source" & CP_CU.Main_Source'Img & " " & Get_Full_Name (CP_CU.Main_Source, Or_Simple => True)); - -- Case 1: CU not already present. Load all SCO information - -- from checkpoint. + -- If the CU was already loaded, perform consistency checks prior to + -- loading it. - if New_CU_Id = No_CU_Id then - Checkpoint_Load_New_Unit - (CLS, - CP_Vectors, - CP_CU, - New_CU_Id => New_CU_Id); - - -- Case 2: CU already loaded from LI info. Perform consistency checks, - -- skipping the checkpointed unit altogether and emitting a warning if - -- there is a mismatch. Record mapping of checkpoint SCOs otherwise. - - else + if Actual_CU_Id /= No_CU_Id then declare - CU_Record : CU_Info renames CU_Vector.Reference (New_CU_Id); + CU_Record : CU_Info renames CU_Vector.Reference (Actual_CU_Id); function Provider_Image (Provider : SCO_Provider) return String is (case Provider is @@ -1988,6 +2298,8 @@ package body SC_Obligations is -- Helper to refer to the compilation unit in an error message begin + Set_CU_Id_Map (Relocs, CP_CU_Id, Actual_CU_Id); + -- Ignore CU when the provenance of SCOs is inconsistent if CP_CU.Provider /= CU_Record.Provider then @@ -1995,40 +2307,204 @@ package body SC_Obligations is Warn ("SCOs for this unit come from both " & Provider_Image (CP_CU.Provider) & " and from " & Provider_Image (CU_Record.Provider)); + Ignore_SCOs; + return; - -- Ignore also when the fingerprints do not match. - -- - -- Note that only recent enough SID files contain buffer bit maps - -- and their fingerprints. Bit_Maps_Fingerprint is left to - -- No_Fingerprint for checkpoints. Skip the consistency check for - -- these cases, and if the loaded CU has these fingerprints, - -- record them for later consistency checks. + -- Ignore also when the fingerprints do not match - elsif CP_CU.Fingerprint /= CU_Record.Fingerprint + elsif (CP_CU.Provider = Compiler + and then CP_CU.SCOs_Fingerprint + /= CU_Record.SCOs_Fingerprint) or else (CP_CU.Provider = Instrumenter - and then CP_CU.Bit_Maps_Fingerprint /= No_Fingerprint - and then CU_Record.Bit_Maps_Fingerprint /= No_Fingerprint - and then CP_CU.Bit_Maps_Fingerprint - /= CU_Record.Bit_Maps_Fingerprint) + and then CP_CU.Source_Fingerprint + /= CU_Record.Source_Fingerprint) then Warn ("unexpected fingerprint, cannot merge coverage" & " information for " & CU_Image); + Ignore_SCOs; + return; + end if; + end; + end if; - else - if CU_Record.Provider = Instrumenter - and then CU_Record.Bit_Maps_Fingerprint = No_Fingerprint + -- Load the checkpointed information + + declare + Relocs : Checkpoint_Relocations renames CLS.Relocations; + + Is_New_CU : constant Boolean := + not CU_Map.Contains (CP_CU.Main_Source); + -- Whether this is a new compilation unit + + Has_New_SCOs : Boolean; + -- Whether the loaded checkpoint contains additional SCOs for the CU. + -- In this case, load SCOs and scopes from the loaded checkpoint. + + Real_CU_Id : constant CU_Id := + (if Is_New_CU + then CU_Vector.Last_Index + 1 + else CU_Map.Element (CP_CU.Main_Source)); + + type CU_Info_Access is access all CU_Info; + Real_CU : CU_Info_Access; + -- Pointer to the update CU_Info in CU_Vector. This is a new entry + -- into CU_Vector if Is_New_CU, otherwise an existing one. + + begin + Set_CU_Id_Map (Relocs, CP_CU_Id, Real_CU_Id); + + -- If this is a new compilation unit, add a new entry into the + -- CU_Vector. + + if Is_New_CU then + declare + New_CU : CU_Info (CP_CU.Provider); + begin + CU_Vector.Append (New_CU); + end; + end if; + + -- Then, retrieve the newly created (or existing) CU + + Real_CU := + CU_Info_Access (CU_Vector.Reference (Real_CU_Id).Element); + + -- Check if the unit has new SCOs + + Has_New_SCOs := Is_New_CU; + if not Is_New_CU then + for SID_Info in CP_CU.SIDs_Info.Iterate loop + if not Real_CU.SIDs_Info.Contains (SID_Info_Maps.Key (SID_Info)) then - CU_Record.Bit_Maps_Fingerprint := CP_CU.Bit_Maps_Fingerprint; + Has_New_SCOs := True; + exit; end if; - Checkpoint_Load_Merge_Unit - (CLS, - CP_CU => CP_CU, - CP_Vectors => CP_Vectors, - Real_CU_Id => New_CU_Id); - end if; + end loop; + end if; + + -- If this is a new CU, initialize the CU fields shared for all + -- versions. + + if Is_New_CU then + Real_CU.Origin := CP_CU.Origin; + Real_CU.Main_Source := CP_CU.Main_Source; + case Real_CU.Provider is + when Compiler | LLVM => + Real_CU.SCOs_Fingerprint := CP_CU.SCOs_Fingerprint; + when Instrumenter => + Real_CU.Source_Fingerprint := CP_CU.Source_Fingerprint; + end case; + CU_Map.Insert (CP_CU.Main_Source, Real_CU_Id); + for Dep_SFI of Real_CU.Deps loop + + -- Units of interest can depend on units outside of the + -- scope of code coverage analysis. Keeping track of these + -- introduces clashes between stubbed units and the real + -- one, so they are excluded from checkpoints. Hence, allow + -- them to be missing here. + + if not SFI_Ignored (Relocs, Dep_SFI) then + Remap_SFI (Relocs, Dep_SFI); + end if; + end loop; + Register_CU (Real_CU_Id); + end if; + + -- In all cases, load the SCOs: if they already exist in Real_CU, + -- we will remap the SCOs in the loaded checkpoint to the already + -- existing ones. + + Checkpoint_Load_SCOs + (CLS => CLS, + CP_Vectors => CP_Vectors, + CP_CU => CP_CU, + Real_CU => Real_CU.all, + Real_CU_Id => Real_CU_Id); + + -- If this is a new unit / it contains new SCOs, load additional + -- information (SID information, preprocessing information, and + -- copes). + + if Has_New_SCOs then + + -- Process SID information + + Checkpoint_Load_SID_Info + (CLS => CLS, + CP_CU => CP_CU, + Real_CU => Real_CU.all); + + -- Process macro information + + Checkpoint_Load_PP_Info + (CLS => CLS, + CP_CU => CP_CU, + Real_CU => Real_CU.all); + + -- Process scopes + + Checkpoint_Load_Scopes + (CLS => CLS, + CP_CU => CP_CU, + Real_CU => Real_CU.all); + end if; + + -- Read uninstrumented SCOs for stmt/decision + + for SCO_Range of CP_CU.SCOs loop + for Old_SCO_Id in SCO_Range.First .. SCO_Range.Last loop + declare + Old_SCOD : SCO_Descriptor renames + CP_Vectors.SCO_Vector (Old_SCO_Id); + New_SCO_Id : constant SCO_Id := + Remap_SCO_Id (Relocs, Old_SCO_Id); + SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); + begin + case SCOD.Kind is + when Statement => + if Old_SCOD.Stmt_Instrumented then + SCOD.Stmt_Instrumented := True; + end if; + + when Decision => + Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id); + + when Fun_Call_SCO_Kind => + if Old_SCOD.Fun_Call_Instrumented then + SCOD.Fun_Call_Instrumented := True; + end if; + + when Guarded_Expr => + if Old_SCOD.GExpr_Instrumented then + SCOD.GExpr_Instrumented := True; + end if; + + when others => + null; + end case; + end; + end loop; + end loop; + + -- Has_Code indication + + Real_CU.Has_Code := Real_CU.Has_Code or CP_CU.Has_Code; + + -- Remap ALI annotations and then merge them + + declare + Remapped_Annotations : ALI_Annotation_Maps.Map := + CP_CU.ALI_Annotations; + begin + Remap_ALI_Annotations (Relocs, Remapped_Annotations); + for Cur in Remapped_Annotations.Iterate loop + Real_CU.ALI_Annotations.Include + (ALI_Annotation_Maps.Key (Cur), + ALI_Annotation_Maps.Element (Cur)); + end loop; end; - end if; + end; end Checkpoint_Load_Unit; ----------- @@ -2065,11 +2541,7 @@ package body SC_Obligations is procedure Write (CSS : in out Checkpoint_Save_State; Value : Scope_Entity) is begin - CSS.Write_SCO (Value.From); - CSS.Write_SCO (Value.To); - - CSS.Write (Value.Start_Sloc); - CSS.Write (Value.End_Sloc); + CSS.Write (Value.Source_Range); CSS.Write (Value.Name); CSS.Write (Value.Sloc); @@ -2078,55 +2550,59 @@ package body SC_Obligations is CSS.Write_Integer (Value.Identifier.Decl_Line); end Write; + procedure Write (CSS : in out Checkpoint_Save_State; Value : SCO_Range) is + begin + CSS.Write_SCO (Value.First); + CSS.Write_SCO (Value.Last); + end Write; + + procedure Write + (CSS : in out Checkpoint_Save_State; Value : SID_Info) is + begin + Write (CSS, Value.Blocks); + CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'First); + CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'Last); + for SCO of Value.Bit_Maps.Statement_Bits.all loop + CSS.Write_SCO (SCO); + end loop; + + CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'First); + CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'Last); + for Info of Value.Bit_Maps.Decision_Bits.all loop + CSS.Write_SCO (Info.D_SCO); + CSS.Write (Info.Outcome); + end loop; + + CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'First); + CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'Last); + for Info of Value.Bit_Maps.MCDC_Bits.all loop + CSS.Write_SCO (Info.D_SCO); + CSS.Write_Integer (Info.Path_Index); + end loop; + + CSS.Write (Value.Bit_Maps_Fingerprint); + CSS.Write (Value.Annotations_Fingerprint); + end Write; + procedure Write (CSS : in out Checkpoint_Save_State; Value : CU_Info) is begin CSS.Write_U8 (SCO_Provider'Pos (Value.Provider)); CSS.Write_SFI (Value.Origin); CSS.Write_SFI (Value.Main_Source); - CSS.Write_SCO (Value.First_SCO); - CSS.Write_SCO (Value.Last_SCO); Write (CSS, Value.Deps); CSS.Write (Value.Has_Code); - CSS.Write (Value.Fingerprint); Write (CSS, Value.PP_Info_Map); Write (CSS, Value.Scope_Entities); Write (CSS, Value.ALI_Annotations); - CSS.Write (Value.Annotations_Fingerprint); + Write (CSS, Value.SCOs); case Value.Provider is - when Compiler | LLVM => - null; - + when Compiler | LLVM => + CSS.Write (Value.SCOs_Fingerprint); when Instrumenter => - if CSS.Purpose_Of = Instrumentation then - CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'First); - CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'Last); - for SCO of Value.Bit_Maps.Statement_Bits.all loop - CSS.Write_SCO (SCO); - end loop; - - CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'First); - CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'Last); - for Info of Value.Bit_Maps.Decision_Bits.all loop - CSS.Write_SCO (Info.D_SCO); - CSS.Write (Info.Outcome); - end loop; - - CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'First); - CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'Last); - for Info of Value.Bit_Maps.MCDC_Bits.all loop - CSS.Write_SCO (Info.D_SCO); - CSS.Write_Integer (Info.Path_Index); - end loop; - - CSS.Write (Value.Bit_Maps_Fingerprint); - - -- Write the blocks information - - Write (CSS, Value.Blocks); - end if; + Write (CSS, Value.SIDs_Info); + CSS.Write (Value.Source_Fingerprint); end case; - end Write; procedure Write @@ -2207,11 +2683,11 @@ package body SC_Obligations is procedure Free is new Ada.Unchecked_Deallocation (MCDC_Bit_Map, MCDC_Bit_Map_Access); begin - if CU.Provider = Instrumenter then - Free (CU.Bit_Maps.Statement_Bits); - Free (CU.Bit_Maps.Decision_Bits); - Free (CU.Bit_Maps.MCDC_Bits); - end if; + for SID_Info of CU.SIDs_Info loop + Free (SID_Info.Bit_Maps.Statement_Bits); + Free (SID_Info.Bit_Maps.Decision_Bits); + Free (SID_Info.Bit_Maps.MCDC_Bits); + end loop; end Free; --------------------- @@ -2291,9 +2767,8 @@ package body SC_Obligations is declare use CU_Info_Vectors; - CP_CU_Id : constant CU_Id := To_Index (Cur); - CP_CU : CU_Info := Element (Cur); - New_CU_Id : CU_Id := No_CU_Id; + CP_CU_Id : constant CU_Id := To_Index (Cur); + CP_CU : CU_Info := Element (Cur); -- If the CU Origin or its Main_Source files are ignored, we -- cannot load this CU. @@ -2331,8 +2806,7 @@ package body SC_Obligations is (CLS, CP_Vectors, CP_CU, - New_CU_Id => New_CU_Id); - Set_CU_Id_Map (Relocs, CP_CU_Id, New_CU_Id); + CP_CU_Id => CP_CU_Id); end if; end; end loop; @@ -2470,8 +2944,8 @@ package body SC_Obligations is if Last_SCO < First_SCO then Warn ("[LLVM-JSON] No regions to process"); else - CU_Vector (CUID).First_SCO := First_SCO; - CU_Vector (CUID).Last_SCO := Last_SCO; + CU_Vector (CUID).SCOs.Append + (SCO_Range'(First => First_SCO, Last => Last_SCO)); end if; end; end loop; @@ -2560,31 +3034,32 @@ package body SC_Obligations is end if; end Comp_Unit; - --------------- - -- First_SCO -- - --------------- + ---------------- + -- SCO_Ranges -- + ---------------- - function First_SCO (CU : CU_Id) return SCO_Id is + function SCO_Ranges (CU : CU_Id) return SCO_Range_Vectors.Vector is begin if CU = No_CU_Id then - return No_SCO_Id; + return SCO_Range_Vectors.Empty_Vector; else - return CU_Vector.Constant_Reference (CU).First_SCO; + return CU_Vector.Constant_Reference (CU).SCOs; end if; - end First_SCO; + end SCO_Ranges; - -------------- - -- Last_SCO -- - -------------- + ----------- + -- In_CU -- + ----------- - function Last_SCO (CU : CU_Id) return SCO_Id is + function In_CU (CU : CU_Id; SCO : SCO_Id) return Boolean is begin - if CU = No_CU_Id then - return No_SCO_Id; - else - return CU_Vector.Constant_Reference (CU).Last_SCO; - end if; - end Last_SCO; + for SCO_Range of SCO_Ranges (CU) loop + if SCO >= SCO_Range.First and then SCO <= SCO_Range.Last then + return True; + end if; + end loop; + return False; + end In_CU; ----------- -- Index -- @@ -2646,7 +3121,7 @@ package body SC_Obligations is begin -- Search for the first Condition of the Decision. - while C_SCO <= Last_SCO (CU) + while In_CU (CU, C_SCO) and then (Kind (C_SCO) /= Condition or else Parent (C_SCO) /= SCO) loop @@ -2661,13 +3136,13 @@ package body SC_Obligations is Index_Mut := Index_Mut - 1; loop C_SCO := C_SCO + 1; - exit when C_SCO > Last_SCO (CU); + exit when not In_CU (CU, C_SCO); exit when Kind (C_SCO) = Condition and then Parent (C_SCO) = SCO; end loop; end loop; - if C_SCO > Last_SCO (CU) then + if not In_CU (CU, C_SCO) then Fatal_Error ("Malformed SCO Vector, a condition SCO" & " is missing"); end if; @@ -3063,8 +3538,8 @@ package body SC_Obligations is use Sloc_To_SCO_Maps; Position : Cursor := - Sloc_To_SCO_Map (Sloc_End.Source_File, Kind).Floor - ((Sloc_End.L, No_Local_Location)); + Sloc_To_SCO_Map (Sloc_End.Source_File, Kind).Floor + ((Sloc_End.L, No_Local_Location)); begin while Position /= No_Element loop declare @@ -3299,25 +3774,15 @@ package body SC_Obligations is --------------- function Comp_Unit (SCO : SCO_Id) return CU_Id is - LB, UB, Middle : Valid_CU_Id; begin - -- Assume that compilation units in CU_Vector are ordered by SCO range - -- to look up efficiently (by dichotomy) the compilation unit for the - -- SCO. + -- TODO??? we are losing the logarithmic complexity - LB := CU_Vector.First_Index; - UB := CU_Vector.Last_Index; - while LB <= UB loop - Middle := LB + (UB - LB) / 2; + for Cur in CU_Vector.Iterate loop declare - CU : CU_Info renames CU_Vector.Constant_Reference (Middle); + CU : constant CU_Id := CU_Info_Vectors.To_Index (Cur); begin - if SCO in CU.First_SCO .. CU.Last_SCO then - return Middle; - elsif SCO < CU.First_SCO then - UB := Middle - 1; - else - LB := Middle + 1; + if In_CU (CU, SCO) then + return CU; end if; end; end loop; @@ -3723,29 +4188,15 @@ package body SC_Obligations is -- Fingerprint -- ----------------- - function Fingerprint (CU : CU_Id) return Fingerprint_Type is + function Fingerprint (CU : CU_Id) return Fingerprint_Type + is + SID_Infos : constant SID_Info_Maps.Map := + CU_Vector.Element (CU).SIDs_Info; begin - return CU_Vector.Reference (CU).Fingerprint; + pragma Assert (SID_Infos.Length = 1); + return SID_Infos.First_Key; end Fingerprint; - -------------------------- - -- Bit_Maps_Fingerprint -- - -------------------------- - - function Bit_Maps_Fingerprint (CU : CU_Id) return Fingerprint_Type is - begin - return CU_Vector.Reference (CU).Bit_Maps_Fingerprint; - end Bit_Maps_Fingerprint; - - ----------------------------- - -- Annotations_Fingerprint -- - ----------------------------- - - function Annotations_Fingerprint (CU : CU_Id) return Fingerprint_Type is - begin - return CU_Vector.Reference (CU).Annotations_Fingerprint; - end Annotations_Fingerprint; - --------------- -- Load_SCOs -- --------------- @@ -3765,7 +4216,7 @@ package body SC_Obligations is ALI_Index : constant Source_File_Index := Load_ALI (ALI_Filename, Ignored_Source_Files, Units, Deps, Temp_ALI_Annotations, With_SCOs => True); - -- Load ALI file and update the last SCO index + -- Load ALI file and update the last SCO begin if ALI_Index = No_Source_File then @@ -4050,11 +4501,14 @@ package body SC_Obligations is Created_Units : in out Created_Unit_Maps.Map) return CU_Id is use Created_Unit_Maps; + use GNATCOLL.VFS; New_CU_Info : CU_Info (Provider); - CU_Index : constant CU_Id := Comp_Unit (Main_Source); - Cur : constant Cursor := Created_Units.Find (Main_Source); + CU_Index : constant CU_Id := Comp_Unit (Main_Source); + CU_Version : SID_Info; + Cur : constant Cursor := Created_Units.Find (Main_Source); + begin -- Check whether there is already a compilation unit for this main -- source. @@ -4074,7 +4528,7 @@ package body SC_Obligations is -- this duplicate, and return no CU to signify to the caller that we -- must abort the loading. - if CU_Vector.Reference (CU_Index).Fingerprint = Fingerprint then + if SC_Obligations.Fingerprint (CU_Index) = Fingerprint then return No_CU_Id; end if; @@ -4117,9 +4571,30 @@ package body SC_Obligations is New_CU_Info.Origin := Origin; New_CU_Info.Main_Source := Main_Source; - New_CU_Info.First_SCO := Valid_SCO_Id'First; - New_CU_Info.Last_SCO := No_SCO_Id; - New_CU_Info.Fingerprint := Fingerprint; + New_CU_Info.SIDs_Info.Insert (Fingerprint, CU_Version); + + -- Also create the fingerprint: the SCOs fingerprint for binary traces, + -- which is still used for consistency checks, and the source + -- fingerprint for source traces. + + case Provider is + when Compiler | LLVM => + New_CU_Info.SCOs_Fingerprint := Fingerprint; + when Instrumenter => + declare + Source_Fingerprint_Context : GNAT.SHA1.Context; + Contents : GNAT.Strings.String_Access := + Read_File (Create (+Get_Full_Name (Main_Source))); + begin + GNAT.SHA1.Update (Source_Fingerprint_Context, Contents.all); + Free (Contents); + New_CU_Info.Source_Fingerprint := + Fingerprint_Type + (GNAT.SHA1.Binary_Message_Digest' + (GNAT.SHA1.Digest (Source_Fingerprint_Context))); + end; + end case; + CU_Vector.Append (New_CU_Info); return Result : constant CU_Id := CU_Vector.Last_Index do @@ -4548,8 +5023,10 @@ package body SC_Obligations is begin Unit.Deps := Deps; - Unit.First_SCO := First_SCO; - Unit.Last_SCO := SCO_Vector.Last_Index; + Unit.SCOs.Append + (SCO_Range' + (First => First_SCO, + Last => SCO_Vector.Last_Index)); end; end; @@ -5207,7 +5684,8 @@ package body SC_Obligations is function Are_Bit_Maps_In_Range (Bit_Maps : CU_Bit_Maps; CU : CU_Info) return Boolean is - subtype SCO_Range is SCO_Id range CU.First_SCO .. CU.Last_SCO; + subtype SCO_Range is + SCO_Id range CU.SCOs.First_Element.First .. CU.SCOs.First_Element.Last; begin return (for all SCO of Bit_Maps.Statement_Bits.all => SCO in SCO_Range) @@ -5225,6 +5703,8 @@ package body SC_Obligations is use GNAT.SHA1; Info : CU_Info renames CU_Vector.Reference (CU); + CU_Version : SID_Info renames + Info.SIDs_Info.Reference (Info.SIDs_Info.First); Ctx : GNAT.SHA1.Context; LF : constant String := (1 => ASCII.LF); @@ -5253,7 +5733,7 @@ package body SC_Obligations is ------------ procedure Update (SCO : SCO_Id) is - Relative_SCO : constant SCO_Id := SCO - Info.First_SCO; + Relative_SCO : constant SCO_Id := SCO - Info.SCOs.First_Element.First; begin Update (Ctx, Relative_SCO'Image); end Update; @@ -5261,7 +5741,7 @@ package body SC_Obligations is begin pragma Assert (Are_Bit_Maps_In_Range (Bit_Maps, Info)); - Info.Bit_Maps := Bit_Maps; + CU_Version.Bit_Maps := Bit_Maps; -- Compute the fingerprint for these bit maps @@ -5285,7 +5765,7 @@ package body SC_Obligations is end loop; Update (Ctx, LF); - Info.Bit_Maps_Fingerprint := Fingerprint_Type + CU_Version.Bit_Maps_Fingerprint := Fingerprint_Type (GNAT.SHA1.Binary_Message_Digest'(GNAT.SHA1.Digest (Ctx))); end Set_Bit_Maps; @@ -5295,8 +5775,10 @@ package body SC_Obligations is procedure Set_Blocks (CU : CU_Id; Blocks : SCO_Id_Vector_Vector) is Info : CU_Info renames CU_Vector.Reference (CU); + CU_Version : SID_Info renames + Info.SIDs_Info.Reference (Info.SIDs_Info.First); begin - Info.Blocks := Blocks; + CU_Version.Blocks := Blocks; end Set_Blocks; --------------------- @@ -5312,6 +5794,31 @@ package body SC_Obligations is Current_Ctx : GNAT.SHA1.Context := Initial_Context; -- Current file being processed + procedure Set_Annotations_Fingerprint; + -- Set the annotations fingerprint for Current_CU if it is not null, + -- stored in Current_Ctx. + + --------------------------------- + -- Set_Annotations_Fingerprint -- + --------------------------------- + + procedure Set_Annotations_Fingerprint is + begin + if Current_CU /= No_CU_Id then + declare + SID_Maps : SID_Info_Maps.Map renames + CU_Vector.Reference (Current_CU).SIDs_Info; + SID : SID_Info renames + SID_Maps.Reference (SID_Maps.First); + begin + SID.Annotations_Fingerprint := + Fingerprint_Type + (GNAT.SHA1.Binary_Message_Digest' + (GNAT.SHA1.Digest (Current_Ctx))); + end; + end if; + end Set_Annotations_Fingerprint; + begin -- As a reminder, Source_Location sort on the file index first, so we -- are guaranteed to have annotations grouped by source files. @@ -5326,12 +5833,7 @@ package body SC_Obligations is -- dump the annotations fingerprint that was processed. if Sloc.Source_File /= Current_SFI then - if Current_CU /= No_CU_Id then - CU_Vector.Reference (Current_CU).Annotations_Fingerprint := - Fingerprint_Type - (GNAT.SHA1.Binary_Message_Digest' - (GNAT.SHA1.Digest (Current_Ctx))); - end if; + Set_Annotations_Fingerprint; Current_Ctx := Initial_Context; Current_SFI := Sloc.Source_File; Current_CU := Comp_Unit (Current_SFI); @@ -5345,12 +5847,7 @@ package body SC_Obligations is (Sloc, Ann); end; end loop; - if Current_CU /= No_CU_Id then - CU_Vector.Reference (Current_CU).Annotations_Fingerprint := - Fingerprint_Type - (GNAT.SHA1.Binary_Message_Digest' - (GNAT.SHA1.Digest (Current_Ctx))); - end if; + Set_Annotations_Fingerprint; end Set_Annotations; ------------------------ @@ -5378,9 +5875,11 @@ package body SC_Obligations is -- Exception raised when the nesting/ordering invariant is found to be -- broken. - Lower_Bound : SCO_Id := No_SCO_Id; - -- At every step of the check, this designates the minimum possible SCO - -- value for the .From component for the next element to inspect. + Lower_Bound : Local_Source_Location := + Local_Source_Location'(Line => 1, Column => 0); + -- At every step of the check, this designates the minimum possible + -- source location value for the .Source_Range.L.First_Sloc component + -- for the next element to inspect. procedure Check_Element (Cur : Cursor); -- Check that Cur's From/To SCOs range is not empty and @@ -5394,14 +5893,14 @@ package body SC_Obligations is SE : Scope_Entity renames Tree.Constant_Reference (Cur); Child : Cursor := First_Child (Cur); - Last : SCO_Id; - -- SCO range upper bound for Cur's last child, or SE.From if there is - -- no child. + Last : Local_Source_Location; + -- Source_Location upper bound for Cur's last child, or + -- SE.Source_Range.First_Sloc if there is no child. begin - -- Check that SCO ranges are never empty + -- Check that source ranges are never empty - if SE.From > SE.To then - raise Failure with "empty SCO range for " & Image (SE); + if SE.Source_Range.L.Last_Sloc < SE.Source_Range.L.First_Sloc then + raise Failure with "empty source range for " & Image (SE); end if; -- Check that the SCO range lower bound is both: @@ -5412,11 +5911,12 @@ package body SC_Obligations is -- * greater than the previous sibling (if any: this checks the -- ordering). - if SE.From < Lower_Bound then - raise Failure with "SCO lower bound too low for " & Image (SE); + if SE.Source_Range.L.First_Sloc < Lower_Bound then + raise Failure with + "source range lower bound too low for " & Image (SE); end if; - Lower_Bound := SE.From; - Last := SE.From; + Lower_Bound := SE.Source_Range.L.First_Sloc; + Last := SE.Source_Range.L.First_Sloc; while Has_Element (Child) loop Check_Element (Child); @@ -5425,17 +5925,21 @@ package body SC_Obligations is -- The next sibling's SCO range cannot overlap with the current's - Lower_Bound := Lower_Bound + 1; + Lower_Bound := + Local_Source_Location' + (Line => Lower_Bound.Line, + Column => Lower_Bound.Column + 1); end loop; -- Check that the SCO range upper bound is greater or equal to -- the upper bound of the last child's upper bound (this is the -- second half of the nesting check). - if SE.To < Last then - raise Failure with "SCO higher bound too low for " & Image (SE); + if SE.Source_Range.L.Last_Sloc < Last then + raise Failure with + "Source location bound too low for " & Image (SE); end if; - Lower_Bound := SE.To; + Lower_Bound := SE.Source_Range.L.Last_Sloc; end Check_Element; Cur : Cursor := First_Child (Tree.Root); @@ -5465,6 +5969,37 @@ package body SC_Obligations is return False; end SCOs_Nested_And_Ordered; + ----------- + -- Floor -- + ----------- + + function Floor + (Tree : Scope_Entities_Trees.Tree; + Sloc : Source_Location) return Scope_Entities_Trees.Cursor + is + use Scope_Entities_Trees; + + Result : Scope_Entities_Trees.Cursor := Scope_Entities_Trees.No_Element; + + procedure Process_Node (Cur : Cursor); + + ------------------ + -- Process_Node -- + ------------------ + + procedure Process_Node (Cur : Cursor) is + begin + if In_Range (Sloc, Element (Cur).Source_Range) then + Result := Cur; + Iterate_Children (Cur, Process_Node'Access); + end if; + end Process_Node; + + begin + Iterate_Children (Tree.Root, Process_Node'Access); + return Result; + end Floor; + ---------------- -- Covers_SCO -- ---------------- @@ -5476,6 +6011,22 @@ package body SC_Obligations is and then Scope_Entities_Trees.Is_Root (ST.Cur)) or else Covers_SCO (Scope_Entities_Trees.Element (ST.Cur), SCO)); + ------------------ + -- Contains_SCO -- + ------------------ + + function Contains_SCO (SCO : SCO_Id; CU : CU_Id) return Boolean + is + Unit : CU_Info renames CU_Vector.Reference (CU); + begin + for SCO_Range of Unit.SCOs loop + if SCO in SCO_Range.First .. SCO_Range.Last then + return True; + end if; + end loop; + return False; + end Contains_SCO; + ------------------------ -- Set_Scope_Entities -- ------------------------ @@ -6285,7 +6836,7 @@ package body SC_Obligations is -- operand, if it is a condition. Cur := Sloc_To_SCO_Map (Sloc.Source_File, Operator).Find - ((Sloc.L, No_Local_Location)); + ((Sloc.L, No_Local_Location)); if Cur /= No_Element then SCO := Element (Cur); while Kind (SCO) = Operator and then Op_Kind (SCO) = Op_Not loop @@ -6377,9 +6928,7 @@ package body SC_Obligations is Cur := Sloc_To_SCO_Map (Sloc.Source_File, Decision) .Find ((Sloc.L, No_Local_Location)); - if Cur = No_Element then - SCO := No_SCO_Id; - else + if Cur /= No_Element then pragma Assert (SCO = No_SCO_Id or else SCO = Enclosing_Statement (Element (Cur))); diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index f4e310214..cafa9da99 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -133,13 +133,8 @@ package SC_Obligations is No_Fingerprint : constant Fingerprint_Type := (others => 0); function Fingerprint (CU : CU_Id) return Fingerprint_Type; - -- Hash of SCO info in ALI, for incremental coverage consistency check - - function Bit_Maps_Fingerprint (CU : CU_Id) return Fingerprint_Type; - -- Hash of buffer bit mappings in CU - - function Annotations_Fingerprint (CU : CU_Id) return Fingerprint_Type; - -- Hash of annotations in CU + -- Assuming the CU has only one SID version, return its fingerprint. See + -- CU_Info.SID_Info for more information. function Comp_Unit (Src_File : Source_File_Index) return CU_Id; -- Return the identifier for the compilation unit containing the given @@ -260,14 +255,6 @@ package SC_Obligations is -- -- Deps are the dependencies of the compilation. - --------------- - -- Instances -- - --------------- - - type Inst_Id is new Natural; - No_Inst_Id : constant Inst_Id := 0; - subtype Valid_Inst_Id is Inst_Id range No_Inst_Id + 1 .. Inst_Id'Last; - --------------------------------- -- Source Coverage Obligations -- --------------------------------- @@ -309,15 +296,10 @@ package SC_Obligations is else L.Decl_SFI < R.Decl_SFI); type Scope_Entity is record - From, To : SCO_Id; - -- SCO range for this scope. As scope entities are computed during - -- instrumentation, From and To designate low level SCOs that are then - -- converted to high level SCOs after processing the low level SCOs. - - Start_Sloc, End_Sloc : Local_Source_Location; - -- Start/End_Sloc for this scope. This is more precise than the SCO - -- range as the SCO range may skip over lines with disabled coverage, - -- which we want to report on. + Source_Range : Source_Location_Range; + -- Source_Location_Range for this scope. This is more precise than the + -- SCO range as the SCO range may skip over lines with disabled + -- coverage, which we want to report on. Name : Unbounded_String; Sloc : Local_Source_Location; @@ -325,6 +307,14 @@ package SC_Obligations is Identifier : Scope_Entity_Identifier; -- Identifier for this scope entity + + -- Below are the fields only used when instrumenting and not stored in + -- checkpoints. + + Start_SCO : SCO_Id; + -- Index of the expected start SCO. This is used to discard scopes + -- without any SCOs at instrumentation time. + end record; -- Scope_Entity (SE) stores the SCO range, the name and the sloc of a SE. -- Note that we assume that the SCOs of a SE can be designated by a range. @@ -367,12 +357,6 @@ package SC_Obligations is -- Utilities type to efficiently traverse the scopes in a compilation unit. -- This is a tree-like data structure, with an iterator pointing to the -- currently traversed inner scope. - -- - -- The intended use is to create a Scope_Traversal_Type using the - -- Scope_Traversal function, and then call Traverse_SCO every time - -- we traverse a SCO to update the scope traversal iterator, and call - -- Is_Active to know whether a given scope is active in the given - -- traversal. function Scope_Traversal (CU : CU_Id) return Scope_Traversal_Type; -- Return a scope traversal for the given compilation unit @@ -388,13 +372,11 @@ package SC_Obligations is -- (i.e. consider that all subprograms are of interest in that case). No_Scope_Entity : constant Scope_Entity := - (From => No_SCO_Id, - To => No_SCO_Id, - Start_Sloc => No_Local_Location, - End_Sloc => No_Local_Location, - Name => +"", - Sloc => No_Local_Location, - Identifier => No_Scope_Entity_Identifier); + (Source_Range => No_Range, + Name => +"", + Sloc => No_Local_Location, + Identifier => No_Scope_Entity_Identifier, + Start_SCO => No_SCO_Id); type Any_SCO_Kind is (Removed, Statement, Decision, Condition, Operator, Fun, Call, @@ -906,13 +888,46 @@ package SC_Obligations is "=" => SCO_Id_Vectors."="); subtype SCO_Id_Vector_Vector is SCO_Id_Vector_Vectors.Vector; - function Bit_Maps (CU : CU_Id) return CU_Bit_Maps; + function Has_Fingerprint + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return Boolean; + -- Return whether there is a match for the given CU and SCO_Fingerprint + + package Fingerprint_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, + Element_Type => Fingerprint_Type); + + function Fingerprints (CU : CU_Id) return Fingerprint_Vectors.Vector; + -- Return the fingerprints for all the different versions of the + -- compilation unit identified by CU. + + function Bit_Maps + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return CU_Bit_Maps; + -- For a unit whose coverage is assessed through source code + -- instrumentation, return bit maps for the version of the compilation unit + -- denoted by SCO_Fingerprint. + + function Bit_Maps_Fingerprint + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return Fingerprint_Type; + -- For a unit whose coverage is assessed through source code + -- instrumentation, return the bit maps fingerprint for the version of the + -- compilation unit denoted by SCO_Fingerprint. + + function Annotations_Fingerprint + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return Fingerprint_Type; -- For a unit whose coverage is assessed through source code - -- instrumentation, return bit maps. + -- instrumentation, return the annotations fingerprint for the version of + -- the compilation unit denoted by SCO_Fingerprint. - function Blocks (CU : CU_Id) return SCO_Id_Vector_Vector; + function Blocks + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return SCO_Id_Vector_Vector; -- For a unit whose coverage is assessed through source code - -- instrumentation, return blocks information. + -- instrumentation, return blocks information for the version of the + -- compilation unit denoted by SCO_Fingerprint. procedure Set_Bit_Maps (CU : CU_Id; Bit_Maps : CU_Bit_Maps); -- Set the tables mapping source trace bit indices to SCO discharge info @@ -1005,11 +1020,22 @@ package SC_Obligations is -- Accessors for CU_Info -- --------------------------- - function First_SCO (CU : CU_Id) return SCO_Id; - -- Return the first SCO of the compilation unit + type SCO_Range is record + First, Last : SCO_Id; + end record; + + function "=" (L, R : SCO_Range) return Boolean + is (L.First = R.First and then R.Last = L.Last); + + package SCO_Range_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, + Element_Type => SCO_Range); + + function SCO_Ranges (CU : CU_Id) return SCO_Range_Vectors.Vector; + -- Return the list of SCOs for the compilation unit - function Last_SCO (CU : CU_Id) return SCO_Id; - -- Return the last SCO of the compilation unit + function In_CU (CU : CU_Id; SCO : SCO_Id) return Boolean; + -- Return whether SCO pertain to CU ------------- -- Pragmas -- diff --git a/tools/gnatcov/slocs.ads b/tools/gnatcov/slocs.ads index 9656d2144..c4cb0bca5 100644 --- a/tools/gnatcov/slocs.ads +++ b/tools/gnatcov/slocs.ads @@ -74,9 +74,10 @@ package Slocs is function "<" (L, R : Source_Location) return Boolean; function "<=" (L, R : Source_Location) return Boolean; - No_Location : constant Source_Location := - (No_Source_File, No_Local_Location); - -- Note: No_Location must sort higher than any non-null location + No_Location : constant Source_Location := + (No_Source_File, No_Local_Location); + -- Note: No_Location must sort higher than any non-null location. TODO??? + -- clarify this comment. function Image (Sloc : Source_Location; From 6172cbfce1a9548e323b30325ab068f473dce2d2 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 7 Aug 2025 12:43:01 +0200 Subject: [PATCH 1374/1483] fixup! Implement support for compilation units with varying SCOs --- testsuite/tests/320-varying-scos/extra.opt | 1 + .../320-varying-scos/varying_header/src/bar.c | 2 + .../320-varying-scos/varying_header/src/foo.c | 2 + .../320-varying-scos/varying_header/src/foo.h | 13 ++ .../varying_header/src/main.c | 4 + .../320-varying-scos/varying_header/test.py | 32 ++++ .../varying_in_scope/src/bar.c | 2 + .../varying_in_scope/src/foo.c | 2 + .../varying_in_scope/src/foo.h | 9 + .../varying_in_scope/src/main.c | 4 + .../320-varying-scos/varying_in_scope/test.py | 54 ++++++ .../320-varying-scos/varying_meta/src/bar.c | 2 + .../320-varying-scos/varying_meta/src/foo.c | 2 + .../320-varying-scos/varying_meta/src/foo.h | 4 + .../varying_meta/src/test_1.c | 11 ++ .../320-varying-scos/varying_meta/test.py | 19 +++ .../varying_source/src1/main.adb | 6 + .../varying_source/src2/main.adb | 6 + .../varying_source_ckpt/main.c | 9 + .../varying_source_ckpt/test.py | 50 ++++++ tools/gnatcov/annotations.ads | 2 +- tools/gnatcov/sc_obligations.adb | 157 ++++++++++++++---- 22 files changed, 357 insertions(+), 36 deletions(-) create mode 100644 testsuite/tests/320-varying-scos/extra.opt create mode 100644 testsuite/tests/320-varying-scos/varying_header/src/bar.c create mode 100644 testsuite/tests/320-varying-scos/varying_header/src/foo.c create mode 100644 testsuite/tests/320-varying-scos/varying_header/src/foo.h create mode 100644 testsuite/tests/320-varying-scos/varying_header/src/main.c create mode 100644 testsuite/tests/320-varying-scos/varying_header/test.py create mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/src/bar.c create mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/src/foo.c create mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h create mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/src/main.c create mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/test.py create mode 100644 testsuite/tests/320-varying-scos/varying_meta/src/bar.c create mode 100644 testsuite/tests/320-varying-scos/varying_meta/src/foo.c create mode 100644 testsuite/tests/320-varying-scos/varying_meta/src/foo.h create mode 100644 testsuite/tests/320-varying-scos/varying_meta/src/test_1.c create mode 100644 testsuite/tests/320-varying-scos/varying_meta/test.py create mode 100644 testsuite/tests/320-varying-scos/varying_source/src1/main.adb create mode 100644 testsuite/tests/320-varying-scos/varying_source/src2/main.adb create mode 100644 testsuite/tests/320-varying-scos/varying_source_ckpt/main.c create mode 100644 testsuite/tests/320-varying-scos/varying_source_ckpt/test.py diff --git a/testsuite/tests/320-varying-scos/extra.opt b/testsuite/tests/320-varying-scos/extra.opt new file mode 100644 index 000000000..53cb5a548 --- /dev/null +++ b/testsuite/tests/320-varying-scos/extra.opt @@ -0,0 +1 @@ +bin-traces DEAD Tests specific to source traces diff --git a/testsuite/tests/320-varying-scos/varying_header/src/bar.c b/testsuite/tests/320-varying-scos/varying_header/src/bar.c new file mode 100644 index 000000000..fbe564ba3 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_header/src/bar.c @@ -0,0 +1,2 @@ +#define B +#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_header/src/foo.c b/testsuite/tests/320-varying-scos/varying_header/src/foo.c new file mode 100644 index 000000000..355ae477a --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_header/src/foo.c @@ -0,0 +1,2 @@ +#define A +#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_header/src/foo.h b/testsuite/tests/320-varying-scos/varying_header/src/foo.h new file mode 100644 index 000000000..3182ff51d --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_header/src/foo.h @@ -0,0 +1,13 @@ +#ifdef A +int foo() +{ + return 0; +} +#endif + +#ifdef B +int bar() +{ + return 0; +} +#endif; diff --git a/testsuite/tests/320-varying-scos/varying_header/src/main.c b/testsuite/tests/320-varying-scos/varying_header/src/main.c new file mode 100644 index 000000000..f8b643afb --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_header/src/main.c @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/testsuite/tests/320-varying-scos/varying_header/test.py b/testsuite/tests/320-varying-scos/varying_header/test.py new file mode 100644 index 000000000..f508972d5 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_header/test.py @@ -0,0 +1,32 @@ +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["main.c"]), + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "--output-dir=xcov"], + trace_mode="src", +) +check_xcov_reports( + "xcov", + { + "bar.c.xcov": {}, + "foo.c.xcov": {}, + "foo.h.xcov": {"-": {4, 11}}, + "main.c.xcov": {"+": {3}}, + }, + discard_empty=False, +) + +thistest.result() diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/bar.c b/testsuite/tests/320-varying-scos/varying_in_scope/src/bar.c new file mode 100644 index 000000000..fbe564ba3 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_in_scope/src/bar.c @@ -0,0 +1,2 @@ +#define B +#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.c b/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.c new file mode 100644 index 000000000..355ae477a --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.c @@ -0,0 +1,2 @@ +#define A +#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h b/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h new file mode 100644 index 000000000..3ecbaa9ea --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h @@ -0,0 +1,9 @@ +int foo() +{ +#ifdef A + return 0; +#endif +#ifdef B + return 1; +#endif; +} diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/main.c b/testsuite/tests/320-varying-scos/varying_in_scope/src/main.c new file mode 100644 index 000000000..f8b643afb --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_in_scope/src/main.c @@ -0,0 +1,4 @@ +int main() +{ + return 0; +} diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/test.py b/testsuite/tests/320-varying-scos/varying_in_scope/test.py new file mode 100644 index 000000000..9cf9be916 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_in_scope/test.py @@ -0,0 +1,54 @@ +""" +Check that gnatcov correctly load checkpoints when a source has a version that +varies across runs, and when the varying part is in the same scope for both +versions. Check that the scope metrics are as expected by inspecting the XML +report. +""" + +import os +import os.path + +from lxml import etree + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +build_run_and_coverage( + gprsw=GPRswitches( + root_project=gprfor(srcdirs=["../src"], mains=["main.c"]), + ), + covlevel="stmt", + mains=["main"], + extra_coverage_args=["-axcov", "-axml", "--output-dir=report"], + trace_mode="src", +) +check_xcov_reports( + "report/xcov", + { + "bar.c.xcov": {}, + "foo.c.xcov": {}, + "foo.h.xcov": {"-": {4, 7}}, + "main.c.xcov": {"+": {3}}, + }, + discard_empty=False, +) + +# Check scope metrics +xml = etree.parse("report/xml/foo.h.xml") +xpath_query = './/scope_metric/obligation_stats/metric[@kind="total_obligations_of_relevance"]' + +# Find all matching metrics +metrics = xml.xpath(xpath_query) + +# We expect 2 statement violations for the header and the associated function +thistest.fail_if( + int(metrics[0].get("count")) != 2 or int(metrics[1].get("count")) != 2, + "unexpected scope metrics" +) + +thistest.result() diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/bar.c b/testsuite/tests/320-varying-scos/varying_meta/src/bar.c new file mode 100644 index 000000000..289891d9f --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_meta/src/bar.c @@ -0,0 +1,2 @@ +#define NAME bcd +#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/foo.c b/testsuite/tests/320-varying-scos/varying_meta/src/foo.c new file mode 100644 index 000000000..ac771fcbc --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_meta/src/foo.c @@ -0,0 +1,2 @@ +#define NAME a +#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/foo.h b/testsuite/tests/320-varying-scos/varying_meta/src/foo.h new file mode 100644 index 000000000..010abc271 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_meta/src/foo.h @@ -0,0 +1,4 @@ +int foo() { + int NAME; // # foo-decl + return 0; // # foo-return +} diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/test_1.c b/testsuite/tests/320-varying-scos/varying_meta/src/test_1.c new file mode 100644 index 000000000..bfa3b7a28 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_meta/src/test_1.c @@ -0,0 +1,11 @@ +int main() +{ + return 0; +} + +//# foo.h +// /foo-decl/ l- ## s- +// /foo-return/ l- ## s- +// +//# foo.c +//# bar.c diff --git a/testsuite/tests/320-varying-scos/varying_meta/test.py b/testsuite/tests/320-varying-scos/varying_meta/test.py new file mode 100644 index 000000000..9aa7ba2fb --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_meta/test.py @@ -0,0 +1,19 @@ +""" +Check that gnatcov correctly discards coverage data for a compilation unit +version that conflicts with a previously loaded version. +""" + +from SUITE.context import thistest +from SCOV.tctl import CAT, CovControl +from SCOV.tc import TestCase + +tolerate_cov_messages = "|".join([ + r"warning: Discarding source coverage data for unit .*foo.h \(from .*bar.c\)", + r"warning: traces for .*foo.h .* are inconsistent .*", +]) +TestCase( + category=CAT.stmt, + tolerate_cov_messages=tolerate_cov_messages, +).run() + +thistest.result() diff --git a/testsuite/tests/320-varying-scos/varying_source/src1/main.adb b/testsuite/tests/320-varying-scos/varying_source/src1/main.adb new file mode 100644 index 000000000..f50295f3a --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_source/src1/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("World"); +end Main; \ No newline at end of file diff --git a/testsuite/tests/320-varying-scos/varying_source/src2/main.adb b/testsuite/tests/320-varying-scos/varying_source/src2/main.adb new file mode 100644 index 000000000..9a5292157 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_source/src2/main.adb @@ -0,0 +1,6 @@ +with Ada.Text_IO; use Ada.Text_IO; + +procedure Main is +begin + Put_Line ("Hello"); +end Main; \ No newline at end of file diff --git a/testsuite/tests/320-varying-scos/varying_source_ckpt/main.c b/testsuite/tests/320-varying-scos/varying_source_ckpt/main.c new file mode 100644 index 000000000..1d3e16c85 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_source_ckpt/main.c @@ -0,0 +1,9 @@ +int main() +{ +#ifdef A + return 0; +#endif +#ifdef B + return 0; +#endif +} diff --git a/testsuite/tests/320-varying-scos/varying_source_ckpt/test.py b/testsuite/tests/320-varying-scos/varying_source_ckpt/test.py new file mode 100644 index 000000000..db384ee57 --- /dev/null +++ b/testsuite/tests/320-varying-scos/varying_source_ckpt/test.py @@ -0,0 +1,50 @@ +""" +Check that gnatcov coverage correctly aggregates coverage data of a file that +has various version according to the preprocessing configuration. +""" + +import os +import os.path + +from SCOV.minicheck import build_run_and_coverage, check_xcov_reports +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.tutils import gprfor, xcov +from SUITE.gprutils import GPRswitches + +tmp = Wdir("tmp_") + +prj = gprfor(srcdirs=[".."], mains=["main.c"]) + +# Compute coverage data with the A configuration +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--c-opts=-DA"], + extra_coverage_args=["--cancel-annotate", "--save-checkpoint", "a.ckpt"], + trace_mode="src", +) + +# Compute coverage data for the B configuration +build_run_and_coverage( + gprsw=GPRswitches(root_project=prj), + covlevel="stmt", + mains=["main"], + extra_instr_args=["--c-opts=-DB"], + extra_coverage_args=["--cancel-annotate", "--save-checkpoint", "b.ckpt"], + trace_mode="src", +) + +# Aggregate the coverage data to produce an xcov report +xcov( + ["coverage", "-P", prj, "--level=stmt", "-axcov", "-Ca.ckpt", "-Cb.ckpt"], + tolerate_messages="warning: inconsistent preprocessing information.*", +) + +check_xcov_reports( + "obj", {"main.c.xcov": {"+": {4, 7}}}, + discard_empty=False, +) + +thistest.result() diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 9365a5db1..8854c6f4b 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -320,7 +320,7 @@ private -- Return line metrics for the given line range function Obligation_Metrics (SCOs : SCO_Sets.Set) return Ob_Stat_Array; - -- Return obligation metrics for the given SCO ranges + -- Return obligation metrics for the given SCO set function SCO_Kind_Image (SCO : SCO_Id) return String; -- Get the string representation of the SCO_Kind of SCO. A special diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 94c32b45d..ea1f4ccd4 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -747,7 +747,6 @@ package body SC_Obligations is procedure Remap_SCO_Descriptor (CP_Vectors : Source_Coverage_Vectors; - CP_CU : CU_Info; Relocs : in out Checkpoint_Relocations; SCOD : in out SCO_Descriptor); -- Remap one SCO_Descriptor. Note that this assumes that @@ -756,6 +755,16 @@ package body SC_Obligations is -- Note that this expects condition SCOs of a decision to have been -- remapped calling Remap_SCO_Descriptor + function Check_SCOs_Consistency + (CLS : in out Checkpoint_Load_State; + CP_Vectors : Source_Coverage_Vectors; + CP_CU : in out CU_Info) return Boolean; + -- Check the consistency of the SCO in CP_CU wrt. SCOs previously loaded + -- for the a different version of the same unit. When a new SCO overlaps + -- with an existing one, this breaks the consistency of SCOs. Note that we + -- accept no SCO overlaps (thus no nesting) across compilation unit + -- versions. + procedure Checkpoint_Load_SCOs (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; @@ -1492,6 +1501,93 @@ package body SC_Obligations is return False; end "<"; + ---------------------------- + -- Check_SCOs_Consistency -- + ---------------------------- + + function Check_SCOs_Consistency + (CLS : in out Checkpoint_Load_State; + CP_Vectors : Source_Coverage_Vectors; + CP_CU : in out CU_Info) return Boolean is + begin + for SCO_Range of CP_CU.SCOs loop + for Old_SCO_Id in SCO_Range.First .. SCO_Range.Last loop + declare + New_SCOD : constant SCO_Descriptor := + CP_Vectors.SCO_Vector.Element (Old_SCO_Id); + Kind : Any_SCO_Kind renames New_SCOD.Kind; + + Sloc_Range : Source_Location_Range := New_SCOD.Sloc_Range; + + Real_SCO : SCO_Id := No_SCO_Id; + -- Value of the SCO if it already exists, otherwise left to + -- No_SCO_Id. + + begin + -- This is specific to binary traces: decision issued from + -- control expressions are actually located at the range + -- (SCOD.Control_Location, No_Location) in the Sloc_To_SCO_Map. + + if New_SCOD.Kind = Decision + and then New_SCOD.Control_Location /= No_Location + then + Sloc_Range := + To_Range (New_SCOD.Control_Location, No_Location); + end if; + + -- Remap SFIs in all source locations + + Remap_SFI (CLS.Relocations, Sloc_Range.Source_File); + + -- Only consider statement / decision / condition coverage + -- obligations as other SCO kinds are not considered by + -- Sloc_To_SCO and this is a good enough condition to ensure + -- SCOs consistency. + + if Kind not in Statement .. Condition then + goto Continue; + end if; + + -- Try to find if the SCO already exists, or if there is an + -- existing SCO at the same location but not with the same + -- source range. + + -- First, try to find if we have a SCO of the exact same kind + -- and range. + + declare + use Sloc_To_SCO_Maps; + Cur : constant Cursor := + Sloc_To_SCO_Map + (Sloc_Range.Source_File, Kind).Find (Sloc_Range.L); + begin + if Has_Element (Cur) + and then SCO_Vector.Element (Element (Cur)).Kind = Kind + then + goto Continue; + end if; + end; + + -- If we did not find a SCO with the exact same range, check + -- whether there is an overlapping SCO. + + Real_SCO := + Sloc_To_SCO + (Slocs.Source_Location' + (Source_File => Sloc_Range.Source_File, + L => New_SCOD.Sloc_Range.L.First_Sloc), + Include_Decisions => True); + + if Real_SCO /= No_SCO_Id then + return False; + end if; + end; + <> + end loop; + end loop; + return True; + end Check_SCOs_Consistency; + -------------------------- -- Checkpoint_Load_SCOs -- -------------------------- @@ -1526,9 +1622,7 @@ package body SC_Obligations is Real_SCO : SCO_Id := No_SCO_Id; -- Value of the SCO if it already exists, otherwise left to - -- No_SCO_Id. To check if the SCO already exists, we use the - -- Sloc_To_SCO_Map and look for an existing SCO with the exact - -- same source range. + -- No_SCO_Id. begin if New_SCOD.Kind = Removed then @@ -1545,7 +1639,7 @@ package body SC_Obligations is declare use Sloc_To_SCO_Maps; Cur : constant Cursor := - Files_Table.Sloc_To_SCO_Map + Sloc_To_SCO_Map (New_SCOD.Sloc_Range.Source_File, New_SCOD.Kind).Find (New_SCOD.Sloc_Range.L); begin @@ -1554,30 +1648,17 @@ package body SC_Obligations is end if; end; - if Real_SCO /= No_SCO_Id then - loop - declare - Real_SCOD : constant SCO_Vectors.Reference_Type := - SCO_Vector.Reference (Real_SCO); - begin - exit when - Real_SCOD.Kind = New_SCOD.Kind - and then Real_SCOD.Sloc_Range = New_SCOD.Sloc_Range; - Real_SCO := Parent (Real_SCO); - exit when Real_SCO = No_SCO_Id; - end; - end loop; - - -- If the SCO already exist, only add an entry to remap the - -- Old_SCO_Id to the actual SCO. + -- If the SCO already exists, only add an entry to remap the + -- Old_SCO_Id to the actual SCO. - if Real_SCO /= No_SCO_Id then - Set_SCO_Id_Map (Relocs, Old_SCO_Id, Real_SCO); - goto Next_SCO; - end if; + if Real_SCO /= No_SCO_Id then + Set_SCO_Id_Map (Relocs, Old_SCO_Id, Real_SCO); + goto Next_SCO; end if; - -- At this point, if Real_SCO is No_SCO_Id, this is a new SCO + -- At this point, if Real_SCO is No_SCO_Id, this is a new SCO: + -- it cannot overlap with an existing SCO as this was checked + -- by Check_SCOs_Consistency. if Real_SCO = No_SCO_Id then Set_SCO_Id_Map @@ -1585,11 +1666,7 @@ package body SC_Obligations is -- Append new SCOD and record mapping - Remap_SCO_Descriptor - (CP_Vectors, - CP_CU, - Relocs, - New_SCOD); + Remap_SCO_Descriptor (CP_Vectors, Relocs, New_SCOD); -- Preallocate line table entries for previous unit @@ -1605,9 +1682,9 @@ package body SC_Obligations is end if; Last_Line := Natural'Max - (Get_File (Cur_Source_File).Lines.Last_Index, + (Files_Table.Last_Line (Get_File (Cur_Source_File)), New_SCOD.Sloc_Range.L.Last_Sloc.Line); - SCO_Vector.Append (New_SCOD); + SCO_Vector.Append (New_SCOD); -- Add it into the Sloc_To_SCO_Map @@ -1971,11 +2048,9 @@ package body SC_Obligations is procedure Remap_SCO_Descriptor (CP_Vectors : Source_Coverage_Vectors; - CP_CU : CU_Info; Relocs : in out Checkpoint_Relocations; SCOD : in out SCO_Descriptor) is - pragma Unreferenced (CP_CU); New_First_SCO : SCO_Id := SCO_Vector.Last_Index + 1; begin -- If this is a decision, start by recording all of the operator @@ -2409,6 +2484,18 @@ package body SC_Obligations is end if; end loop; Register_CU (Real_CU_Id); + + else + -- Otherwise, check that the SCOs in the new version are + -- consistent with those previously loaded. + + if not Check_SCOs_Consistency (CLS, CP_Vectors, CP_CU) then + Outputs.Warn + ("Discarding source coverage data for unit " + & Get_Full_Name (Real_CU.Main_Source) & " (from " + & Get_Full_Name (Real_CU.Origin) & ")"); + return; + end if; end if; -- In all cases, load the SCOs: if they already exist in Real_CU, From 1b2a5bc9330970715a288359bc9ff912bad9212c Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 13 Aug 2025 14:59:38 +0200 Subject: [PATCH 1375/1483] fixup! Implement support for compilation units with varying SCOs --- .../varying_header/src/main.c | 3 +- .../320-varying-scos/varying_header/test.py | 5 +- .../varying_in_scope/src/main.c | 3 +- .../320-varying-scos/varying_in_scope/test.py | 12 ++-- .../varying_meta/src/test_1.c | 3 +- .../320-varying-scos/varying_meta/test.py | 13 +++-- .../varying_source_ckpt/main.c | 3 +- .../varying_source_ckpt/test.py | 6 +- tools/gnatcov/sc_obligations.adb | 58 ++++++++++++------- 9 files changed, 62 insertions(+), 44 deletions(-) diff --git a/testsuite/tests/320-varying-scos/varying_header/src/main.c b/testsuite/tests/320-varying-scos/varying_header/src/main.c index f8b643afb..a9bce4a14 100644 --- a/testsuite/tests/320-varying-scos/varying_header/src/main.c +++ b/testsuite/tests/320-varying-scos/varying_header/src/main.c @@ -1,4 +1,5 @@ -int main() +int +main () { return 0; } diff --git a/testsuite/tests/320-varying-scos/varying_header/test.py b/testsuite/tests/320-varying-scos/varying_header/test.py index f508972d5..f23ab19b2 100644 --- a/testsuite/tests/320-varying-scos/varying_header/test.py +++ b/testsuite/tests/320-varying-scos/varying_header/test.py @@ -1,6 +1,3 @@ -import os -import os.path - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir @@ -24,7 +21,7 @@ "bar.c.xcov": {}, "foo.c.xcov": {}, "foo.h.xcov": {"-": {4, 11}}, - "main.c.xcov": {"+": {3}}, + "main.c.xcov": {"+": {4}}, }, discard_empty=False, ) diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/main.c b/testsuite/tests/320-varying-scos/varying_in_scope/src/main.c index f8b643afb..a9bce4a14 100644 --- a/testsuite/tests/320-varying-scos/varying_in_scope/src/main.c +++ b/testsuite/tests/320-varying-scos/varying_in_scope/src/main.c @@ -1,4 +1,5 @@ -int main() +int +main () { return 0; } diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/test.py b/testsuite/tests/320-varying-scos/varying_in_scope/test.py index 9cf9be916..12718c34d 100644 --- a/testsuite/tests/320-varying-scos/varying_in_scope/test.py +++ b/testsuite/tests/320-varying-scos/varying_in_scope/test.py @@ -5,9 +5,6 @@ report. """ -import os -import os.path - from lxml import etree from SCOV.minicheck import build_run_and_coverage, check_xcov_reports @@ -33,14 +30,17 @@ "bar.c.xcov": {}, "foo.c.xcov": {}, "foo.h.xcov": {"-": {4, 7}}, - "main.c.xcov": {"+": {3}}, + "main.c.xcov": {"+": {4}}, }, discard_empty=False, ) # Check scope metrics xml = etree.parse("report/xml/foo.h.xml") -xpath_query = './/scope_metric/obligation_stats/metric[@kind="total_obligations_of_relevance"]' +xpath_query = ( + ".//scope_metric/obligation_stats/metric" + '[@kind="total_obligations_of_relevance"]' +) # Find all matching metrics metrics = xml.xpath(xpath_query) @@ -48,7 +48,7 @@ # We expect 2 statement violations for the header and the associated function thistest.fail_if( int(metrics[0].get("count")) != 2 or int(metrics[1].get("count")) != 2, - "unexpected scope metrics" + "unexpected scope metrics", ) thistest.result() diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/test_1.c b/testsuite/tests/320-varying-scos/varying_meta/src/test_1.c index bfa3b7a28..b14025e4a 100644 --- a/testsuite/tests/320-varying-scos/varying_meta/src/test_1.c +++ b/testsuite/tests/320-varying-scos/varying_meta/src/test_1.c @@ -1,4 +1,5 @@ -int main() +int +main () { return 0; } diff --git a/testsuite/tests/320-varying-scos/varying_meta/test.py b/testsuite/tests/320-varying-scos/varying_meta/test.py index 9aa7ba2fb..dd6a2893a 100644 --- a/testsuite/tests/320-varying-scos/varying_meta/test.py +++ b/testsuite/tests/320-varying-scos/varying_meta/test.py @@ -4,13 +4,16 @@ """ from SUITE.context import thistest -from SCOV.tctl import CAT, CovControl +from SCOV.tctl import CAT from SCOV.tc import TestCase -tolerate_cov_messages = "|".join([ - r"warning: Discarding source coverage data for unit .*foo.h \(from .*bar.c\)", - r"warning: traces for .*foo.h .* are inconsistent .*", -]) +tolerate_cov_messages = "|".join( + [ + r"warning: Discarding source coverage data for unit" + r".*foo.h \(from .*bar.c\)", + r"warning: traces for .*foo.h .* are inconsistent .*", + ] +) TestCase( category=CAT.stmt, tolerate_cov_messages=tolerate_cov_messages, diff --git a/testsuite/tests/320-varying-scos/varying_source_ckpt/main.c b/testsuite/tests/320-varying-scos/varying_source_ckpt/main.c index 1d3e16c85..f14f9e495 100644 --- a/testsuite/tests/320-varying-scos/varying_source_ckpt/main.c +++ b/testsuite/tests/320-varying-scos/varying_source_ckpt/main.c @@ -1,4 +1,5 @@ -int main() +int +main () { #ifdef A return 0; diff --git a/testsuite/tests/320-varying-scos/varying_source_ckpt/test.py b/testsuite/tests/320-varying-scos/varying_source_ckpt/test.py index db384ee57..59b831a4c 100644 --- a/testsuite/tests/320-varying-scos/varying_source_ckpt/test.py +++ b/testsuite/tests/320-varying-scos/varying_source_ckpt/test.py @@ -3,9 +3,6 @@ has various version according to the preprocessing configuration. """ -import os -import os.path - from SCOV.minicheck import build_run_and_coverage, check_xcov_reports from SUITE.context import thistest from SUITE.cutils import Wdir @@ -43,7 +40,8 @@ ) check_xcov_reports( - "obj", {"main.c.xcov": {"+": {4, 7}}}, + "obj", + {"main.c.xcov": {"+": {5, 8}}}, discard_empty=False, ) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index ea1f4ccd4..3941c7740 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -755,6 +755,14 @@ package body SC_Obligations is -- Note that this expects condition SCOs of a decision to have been -- remapped calling Remap_SCO_Descriptor + function Sloc_Range_For_SCO + (SCOD : SCO_Descriptor) return Source_Location_Range; + -- Get the Source_Location_Range to search for in the Sloc_To_SCO map for + -- the given SCO, accounting for the specific case of decision with + -- a control location (when using binary traces): in this case, the + -- decision are located at their control location rather than the actual + -- decision location. + function Check_SCOs_Consistency (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; @@ -1501,6 +1509,22 @@ package body SC_Obligations is return False; end "<"; + ------------------------ + -- Sloc_Range_For_SCO -- + ------------------------ + + function Sloc_Range_For_SCO + (SCOD : SCO_Descriptor) return Source_Location_Range + is + Sloc_Range : Source_Location_Range := SCOD.Sloc_Range; + begin + if SCOD.Kind = Decision and then SCOD.Control_Location /= No_Location + then + Sloc_Range := To_Range (SCOD.Control_Location, No_Location); + end if; + return Sloc_Range; + end Sloc_Range_For_SCO; + ---------------------------- -- Check_SCOs_Consistency -- ---------------------------- @@ -1517,24 +1541,14 @@ package body SC_Obligations is CP_Vectors.SCO_Vector.Element (Old_SCO_Id); Kind : Any_SCO_Kind renames New_SCOD.Kind; - Sloc_Range : Source_Location_Range := New_SCOD.Sloc_Range; + Sloc_Range : Source_Location_Range := + Sloc_Range_For_SCO (New_SCOD); Real_SCO : SCO_Id := No_SCO_Id; -- Value of the SCO if it already exists, otherwise left to -- No_SCO_Id. begin - -- This is specific to binary traces: decision issued from - -- control expressions are actually located at the range - -- (SCOD.Control_Location, No_Location) in the Sloc_To_SCO_Map. - - if New_SCOD.Kind = Decision - and then New_SCOD.Control_Location /= No_Location - then - Sloc_Range := - To_Range (New_SCOD.Control_Location, No_Location); - end if; - -- Remap SFIs in all source locations Remap_SFI (CLS.Relocations, Sloc_Range.Source_File); @@ -1617,10 +1631,11 @@ package body SC_Obligations is for SCO_Range of CP_CU.SCOs loop for Old_SCO_Id in SCO_Range.First .. SCO_Range.Last loop declare - New_SCOD : SCO_Descriptor := + New_SCOD : SCO_Descriptor := CP_Vectors.SCO_Vector.Element (Old_SCO_Id); - - Real_SCO : SCO_Id := No_SCO_Id; + Sloc_Range : Source_Location_Range := + Sloc_Range_For_SCO (New_SCOD); + Real_SCO : SCO_Id := No_SCO_Id; -- Value of the SCO if it already exists, otherwise left to -- No_SCO_Id. @@ -1632,7 +1647,7 @@ package body SC_Obligations is -- Remap SFIs in all source locations - Remap_SFI (Relocs, New_SCOD.Sloc_Range.Source_File); + Remap_SFI (Relocs, Sloc_Range.Source_File); -- Try to find if the SCO already exists @@ -1640,8 +1655,8 @@ package body SC_Obligations is use Sloc_To_SCO_Maps; Cur : constant Cursor := Sloc_To_SCO_Map - (New_SCOD.Sloc_Range.Source_File, - New_SCOD.Kind).Find (New_SCOD.Sloc_Range.L); + (Sloc_Range.Source_File, + New_SCOD.Kind).Find (Sloc_Range.L); begin if Has_Element (Cur) then Real_SCO := Element (Cur); @@ -1691,10 +1706,9 @@ package body SC_Obligations is declare Map : constant access Sloc_To_SCO_Maps.Map := Writeable_Sloc_To_SCO_Map - (New_SCOD.Sloc_Range.Source_File, - New_SCOD.Kind); + (Sloc_Range.Source_File, New_SCOD.Kind); begin - Map.Insert (New_SCOD.Sloc_Range.L, SCO_Vector.Last_Index); + Map.Insert (Sloc_Range.L, SCO_Vector.Last_Index); end; if SCOs_Trace.Is_Active then @@ -2053,6 +2067,8 @@ package body SC_Obligations is is New_First_SCO : SCO_Id := SCO_Vector.Last_Index + 1; begin + Remap_SFI (Relocs, SCOD.Sloc_Range.Source_File); + -- If this is a decision, start by recording all of the operator -- and condition SCOs in the relocation map, before relocating all -- of the components of the SCO_Descriptor. From 814cec80c917900062b959e6793cb9e89329860f Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 19 Aug 2025 15:20:27 +0200 Subject: [PATCH 1376/1483] fixup! Implement support for compilation units with varying SCOs --- testsuite/SCOV/internals/driver.py | 9 +++++---- .../320-varying-scos/varying_header/src/foo.h | 6 ++++-- .../320-varying-scos/varying_header/test.py | 2 +- .../320-varying-scos/varying_in_scope/src/foo.h | 3 ++- .../320-varying-scos/varying_in_scope/test.py | 2 +- .../320-varying-scos/varying_meta/src/foo.h | 4 +++- .../tests/320-varying-scos/varying_meta/test.py | 17 +++++++++++++++-- .../varying_source/src1/main.adb | 2 +- .../varying_source/src2/main.adb | 2 +- tools/gnatcov/annotations-dynamic_html.adb | 2 +- tools/gnatcov/checkpoints.ads | 2 +- tools/gnatcov/sc_obligations.adb | 10 ++++++++-- tools/gnatcov/slocs.ads | 3 +-- 13 files changed, 44 insertions(+), 20 deletions(-) diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 6405debbf..85682af2a 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -697,14 +697,15 @@ def gen_one_xcov_report(self, trace, report_format, options=""): output_lines = lines_of(ofile) for i, line in reversed(list(enumerate(output_lines))): if line == ( - "warning: -S is deprecated. " - "This option will be removed in release 26." + "warning: -S is deprecated. " + "This option will be removed in release 26." ): output_lines.pop(i) output = "\n".join(output_lines) - + thistest.fail_if( - output, f"xcov standard output not empty ({ofile}:\n--\n{output}" + output, + f"xcov standard output not empty ({ofile}:\n--\n{output}", ) def force_xcov_report(self, source): diff --git a/testsuite/tests/320-varying-scos/varying_header/src/foo.h b/testsuite/tests/320-varying-scos/varying_header/src/foo.h index 3182ff51d..76a1e6520 100644 --- a/testsuite/tests/320-varying-scos/varying_header/src/foo.h +++ b/testsuite/tests/320-varying-scos/varying_header/src/foo.h @@ -1,12 +1,14 @@ #ifdef A -int foo() +int +foo () { return 0; } #endif #ifdef B -int bar() +int +bar () { return 0; } diff --git a/testsuite/tests/320-varying-scos/varying_header/test.py b/testsuite/tests/320-varying-scos/varying_header/test.py index f23ab19b2..de5644023 100644 --- a/testsuite/tests/320-varying-scos/varying_header/test.py +++ b/testsuite/tests/320-varying-scos/varying_header/test.py @@ -20,7 +20,7 @@ { "bar.c.xcov": {}, "foo.c.xcov": {}, - "foo.h.xcov": {"-": {4, 11}}, + "foo.h.xcov": {"-": {5, 13}}, "main.c.xcov": {"+": {4}}, }, discard_empty=False, diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h b/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h index 3ecbaa9ea..e36a63966 100644 --- a/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h +++ b/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h @@ -1,4 +1,5 @@ -int foo() +int +foo () { #ifdef A return 0; diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/test.py b/testsuite/tests/320-varying-scos/varying_in_scope/test.py index 12718c34d..487e4ab1b 100644 --- a/testsuite/tests/320-varying-scos/varying_in_scope/test.py +++ b/testsuite/tests/320-varying-scos/varying_in_scope/test.py @@ -29,7 +29,7 @@ { "bar.c.xcov": {}, "foo.c.xcov": {}, - "foo.h.xcov": {"-": {4, 7}}, + "foo.h.xcov": {"-": {5, 8}}, "main.c.xcov": {"+": {4}}, }, discard_empty=False, diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/foo.h b/testsuite/tests/320-varying-scos/varying_meta/src/foo.h index 010abc271..959587eeb 100644 --- a/testsuite/tests/320-varying-scos/varying_meta/src/foo.h +++ b/testsuite/tests/320-varying-scos/varying_meta/src/foo.h @@ -1,4 +1,6 @@ -int foo() { +int +foo () +{ int NAME; // # foo-decl return 0; // # foo-return } diff --git a/testsuite/tests/320-varying-scos/varying_meta/test.py b/testsuite/tests/320-varying-scos/varying_meta/test.py index dd6a2893a..b7842ac2c 100644 --- a/testsuite/tests/320-varying-scos/varying_meta/test.py +++ b/testsuite/tests/320-varying-scos/varying_meta/test.py @@ -1,16 +1,22 @@ """ Check that gnatcov correctly discards coverage data for a compilation unit -version that conflicts with a previously loaded version. +version that conflicts with a previously loaded version. Note: the use of the +TestCase driver framework matters here, as if we do not discard source coverage +obligations (those coming from bar.h, or foo.h: it does not really matter +which), we end up with four coverage obligations in foo.h, and thus four +violations. This is actually checked through the report format check by the +TestCase framework. """ from SUITE.context import thistest +from SUITE.cutils import contents_of from SCOV.tctl import CAT from SCOV.tc import TestCase tolerate_cov_messages = "|".join( [ r"warning: Discarding source coverage data for unit" - r".*foo.h \(from .*bar.c\)", + r".*foo.h \(from .*bar.c\), loaded from .*foo.c.sid", r"warning: traces for .*foo.h .* are inconsistent .*", ] ) @@ -19,4 +25,11 @@ tolerate_cov_messages=tolerate_cov_messages, ).run() +# Check that gnatcov output contains the expected error messages +thistest.fail_if_no_match( + "gnatcov coverage output", + tolerate_cov_messages, + contents_of("s_1/xcov.out").strip(), +) + thistest.result() diff --git a/testsuite/tests/320-varying-scos/varying_source/src1/main.adb b/testsuite/tests/320-varying-scos/varying_source/src1/main.adb index f50295f3a..05ad557f7 100644 --- a/testsuite/tests/320-varying-scos/varying_source/src1/main.adb +++ b/testsuite/tests/320-varying-scos/varying_source/src1/main.adb @@ -3,4 +3,4 @@ with Ada.Text_IO; use Ada.Text_IO; procedure Main is begin Put_Line ("World"); -end Main; \ No newline at end of file +end Main; diff --git a/testsuite/tests/320-varying-scos/varying_source/src2/main.adb b/testsuite/tests/320-varying-scos/varying_source/src2/main.adb index 9a5292157..78cf5e255 100644 --- a/testsuite/tests/320-varying-scos/varying_source/src2/main.adb +++ b/testsuite/tests/320-varying-scos/varying_source/src2/main.adb @@ -3,4 +3,4 @@ with Ada.Text_IO; use Ada.Text_IO; procedure Main is begin Put_Line ("Hello"); -end Main; \ No newline at end of file +end Main; diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 27ae7f6e4..08c56eeae 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -604,7 +604,7 @@ package body Annotations.Dynamic_Html is (if Is_Root then Last_Line (File_Info) else Scope_Ent.Source_Range.L.Last_Sloc.Line)); -- Adjust Scope_Ent.End_Sloc for the root node as it is - -- No_Local_Location by default. TODO??? + -- No_Local_Location by default. Ob_Stats : constant Ob_Stat_Array := Obligation_Metrics (Get_SCOs (Scope_Ent.Source_Range)); diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 551a0c59a..5c259b2e0 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -64,7 +64,7 @@ package Checkpoints is -- 18 -- Removed support for tags (separate coverage) -- 19 -- Removed support for instance ids (separate coverage) -- 20 -- Rework Scope_Entity to identify scopes by their Start/End_Sloc - -- rather than their Start/End_Scope. + -- rather than their Start/End_SCO. -- -- Note that we always use the last version when creating a checkpoint. -- diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 3941c7740..6cad5f7db 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -2509,7 +2509,8 @@ package body SC_Obligations is Outputs.Warn ("Discarding source coverage data for unit " & Get_Full_Name (Real_CU.Main_Source) & " (from " - & Get_Full_Name (Real_CU.Origin) & ")"); + & Get_Full_Name (Real_CU.Origin) & "), loaded from " + & (+CLS.Filename)); return; end if; end if; @@ -2527,7 +2528,7 @@ package body SC_Obligations is -- If this is a new unit / it contains new SCOs, load additional -- information (SID information, preprocessing information, and - -- copes). + -- scopes). if Has_New_SCOs then @@ -4296,6 +4297,11 @@ package body SC_Obligations is SID_Infos : constant SID_Info_Maps.Map := CU_Vector.Element (CU).SIDs_Info; begin + if SID_Infos.Length /= 1 then + Outputs.Fatal_Error + ("Found multiple versions for " + & Get_Full_Name (CU_Vector.Element (CU).Main_Source)); + end if; pragma Assert (SID_Infos.Length = 1); return SID_Infos.First_Key; end Fingerprint; diff --git a/tools/gnatcov/slocs.ads b/tools/gnatcov/slocs.ads index c4cb0bca5..eb46e1917 100644 --- a/tools/gnatcov/slocs.ads +++ b/tools/gnatcov/slocs.ads @@ -76,8 +76,7 @@ package Slocs is No_Location : constant Source_Location := (No_Source_File, No_Local_Location); - -- Note: No_Location must sort higher than any non-null location. TODO??? - -- clarify this comment. + -- Note: No_Location must sort higher than any non-null location function Image (Sloc : Source_Location; From d9a5f0b663e24636b4b9eacdafe091cd26439091 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 22 Aug 2025 13:00:29 +0000 Subject: [PATCH 1377/1483] instr-cov/449-aggregate-crash: extend tolerated msgs for --all-warnings --- testsuite/tests/instr-cov/449-aggregate-crash/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/instr-cov/449-aggregate-crash/test.py b/testsuite/tests/instr-cov/449-aggregate-crash/test.py index 2affc51c1..0997910fc 100644 --- a/testsuite/tests/instr-cov/449-aggregate-crash/test.py +++ b/testsuite/tests/instr-cov/449-aggregate-crash/test.py @@ -15,6 +15,6 @@ xcov_instrument( gprsw=GPRswitches(root_project=gprfor(mains=[], srcdirs=[".."])), covlevel="stmt", - tolerate_messages=r"\*\*\* pkg\.adb:\d+:\d+: warning: .*", + tolerate_messages=r"\*\*\* pkg\.(adb|ads):\d+:\d+: (low_)?warning: .*", ) thistest.result() From e1c32df46d7201cceb31593c69e8c11dadc4980a Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 26 Aug 2025 15:20:10 +0200 Subject: [PATCH 1378/1483] Revert "Merge branch 'eyraud/320' into 'master'" This reverts commit dcd68684c742d55f2d9d5cec568f030fd0016d4a, reversing changes made to 1a99ecdb92a0d1b5046f5cce6fc92ab7bcc43733. --- testsuite/SCOV/internals/driver.py | 51 +- testsuite/SCOV/tc.py | 5 - .../tests/207-srctrace-version/foo.c.sid | Bin 1186 -> 1179 bytes testsuite/tests/207-srctrace-version/main.sid | Bin 1422 -> 1406 bytes .../207-srctrace-version/reference.srctrace | Bin 336 -> 336 bytes testsuite/tests/320-varying-scos/extra.opt | 1 - .../320-varying-scos/varying_header/src/bar.c | 2 - .../320-varying-scos/varying_header/src/foo.c | 2 - .../320-varying-scos/varying_header/src/foo.h | 15 - .../varying_header/src/main.c | 5 - .../320-varying-scos/varying_header/test.py | 29 - .../varying_in_scope/src/bar.c | 2 - .../varying_in_scope/src/foo.c | 2 - .../varying_in_scope/src/foo.h | 10 - .../varying_in_scope/src/main.c | 5 - .../320-varying-scos/varying_in_scope/test.py | 54 - .../320-varying-scos/varying_meta/src/bar.c | 2 - .../320-varying-scos/varying_meta/src/foo.c | 2 - .../320-varying-scos/varying_meta/src/foo.h | 6 - .../varying_meta/src/test_1.c | 12 - .../320-varying-scos/varying_meta/test.py | 35 - .../varying_source/src1/main.adb | 6 - .../varying_source/src2/main.adb | 6 - .../320-varying-scos/varying_source/test.py | 71 - .../varying_source_ckpt/main.c | 10 - .../varying_source_ckpt/test.py | 48 - .../main.adb.xml.expected | 36 +- .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 1508 -> 1508 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2580 -> 2580 bytes .../gen/arm-elf-linux/main_1.sid | Bin 445 -> 421 bytes .../gen/arm-elf-linux/main_2.sid | Bin 445 -> 421 bytes .../gen/arm-elf-linux/pkg.sid | Bin 1150 -> 1102 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1831 -> 1879 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1841 -> 1889 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 2422 -> 2088 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 2353 -> 2019 bytes .../gen/x86_64-windows/main_1.sid | Bin 447 -> 423 bytes .../gen/x86_64-windows/main_2.sid | Bin 447 -> 423 bytes .../gen/x86_64-windows/pkg.sid | Bin 1154 -> 1106 bytes tools/gnatcov/annotations-dynamic_html.adb | 8 +- tools/gnatcov/annotations-xml.adb | 6 +- tools/gnatcov/annotations.adb | 34 +- tools/gnatcov/annotations.ads | 4 +- tools/gnatcov/checkpoints.ads | 6 +- tools/gnatcov/coverage-source.adb | 48 +- tools/gnatcov/files_table.adb | 29 - tools/gnatcov/files_table.ads | 19 +- tools/gnatcov/gnatcov_bits_specific.adb | 8 - tools/gnatcov/instrument-ada_unit.adb | 79 +- tools/gnatcov/instrument-c.adb | 98 +- tools/gnatcov/instrument-common.adb | 19 + tools/gnatcov/instrument-common.ads | 6 + tools/gnatcov/instrument-projects.adb | 27 +- tools/gnatcov/sc_obligations.adb | 2288 ++++++----------- tools/gnatcov/sc_obligations.ads | 116 +- tools/gnatcov/slocs.ads | 4 +- 56 files changed, 1106 insertions(+), 2110 deletions(-) delete mode 100644 testsuite/tests/320-varying-scos/extra.opt delete mode 100644 testsuite/tests/320-varying-scos/varying_header/src/bar.c delete mode 100644 testsuite/tests/320-varying-scos/varying_header/src/foo.c delete mode 100644 testsuite/tests/320-varying-scos/varying_header/src/foo.h delete mode 100644 testsuite/tests/320-varying-scos/varying_header/src/main.c delete mode 100644 testsuite/tests/320-varying-scos/varying_header/test.py delete mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/src/bar.c delete mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/src/foo.c delete mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h delete mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/src/main.c delete mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/test.py delete mode 100644 testsuite/tests/320-varying-scos/varying_meta/src/bar.c delete mode 100644 testsuite/tests/320-varying-scos/varying_meta/src/foo.c delete mode 100644 testsuite/tests/320-varying-scos/varying_meta/src/foo.h delete mode 100644 testsuite/tests/320-varying-scos/varying_meta/src/test_1.c delete mode 100644 testsuite/tests/320-varying-scos/varying_meta/test.py delete mode 100644 testsuite/tests/320-varying-scos/varying_source/src1/main.adb delete mode 100644 testsuite/tests/320-varying-scos/varying_source/src2/main.adb delete mode 100644 testsuite/tests/320-varying-scos/varying_source/test.py delete mode 100644 testsuite/tests/320-varying-scos/varying_source_ckpt/main.c delete mode 100644 testsuite/tests/320-varying-scos/varying_source_ckpt/test.py diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index 85682af2a..cec0ea80e 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -676,37 +676,28 @@ def gen_one_xcov_report(self, trace, report_format, options=""): # return. ofile = report_format + ".out" - xcov( - args=["coverage"] + covargs, - tolerate_messages=self.testcase.tolerate_cov_messages, - out=ofile, - ) - - # Only check the output when running with binary traces, as this is - # done in xcov for source traces. - if thistest.options.trace_mode == "bin": - # Standard output might typically contain labeling warnings issued - # by the static analysis phase, or error messages issued when a - # trace indicates that some unlabeled edge was taken. None of this - # should happen so we simply fail as soon as the output file is not - # empty. Note that we do this in qualification mode as well, even - # though what we're looking at is not stricly part of the qualified - # interface. - - # Warnings about -S being deprecated are expected: just ignore them - output_lines = lines_of(ofile) - for i, line in reversed(list(enumerate(output_lines))): - if line == ( - "warning: -S is deprecated. " - "This option will be removed in release 26." - ): - output_lines.pop(i) - output = "\n".join(output_lines) + xcov(args=["coverage"] + covargs, out=ofile) + + # Standard output might typically contain labeling warnings issued + # by the static analysis phase, or error messages issued when a trace + # indicates that some unlabeled edge was taken. None of this should + # happen so we simply fail as soon as the output file is not empty. + # Note that we do this in qualification mode as well, even though what + # we're looking at is not stricly part of the qualified interface. + + # Warnings about -S being deprecated are expected: just ignore them + output_lines = lines_of(ofile) + for i, line in reversed(list(enumerate(output_lines))): + if line == ( + "warning: -S is deprecated. " + "This option will be removed in release 26." + ): + output_lines.pop(i) + output = "\n".join(output_lines) - thistest.fail_if( - output, - f"xcov standard output not empty ({ofile}:\n--\n{output}", - ) + thistest.fail_if( + output, f"xcov standard output not empty ({ofile}:\n--\n{output}" + ) def force_xcov_report(self, source): filename = self.xcov_translation_for(source) + ".xcov" diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index bac14825f..6c777842c 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -137,7 +137,6 @@ def __init__( extracargs="", category=CAT.auto, tolerate_messages=None, - tolerate_cov_messages=None, expect_non_zero_code=False, assert_lvl=None, fun_call_lvl=False, @@ -154,10 +153,6 @@ def __init__( # for xcov_instrument). self.tolerate_messages = tolerate_messages - # Pass tolerate_cov_messages to gnatcov coverage invocations (only when - # using source traces). - self.tolerate_cov_messages = tolerate_cov_messages - # Step 1: Compute the list of drivers and consolidation specs # to exercise # ------------------------------------------------------------ diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid index d0ecec554373ef0e8806b3be7e5dd46d7ea16d47..962ac59626d19df2295dbccc0a39174f7277e75a 100644 GIT binary patch delta 151 zcmZ3)Ih#|&-On*3IloLHIU_YWyC6R^uY^H(qDTZ6BLf2iD-bg@$HesPk1g@swXnTc*rW?pFpSUfQ&XYv>3bpSy$D(e6M delta 176 zcmbQuxrkH5-On*3IloLHIU_YWyC6R^uY^HlqDTZQ0|-p)-NM5NW-&1Q|Np;!av-DT zLTa?&lbioL{DpoRONGU67xdSHd7XQ6$=kk%57M7l^^&{~B@q_a<&-p&t|z zPP$!Zd$+5v8YICC#2|%W#S6z#_Vq=Jj6CXVw}Sa0L1Yf AiU0rr diff --git a/testsuite/tests/207-srctrace-version/reference.srctrace b/testsuite/tests/207-srctrace-version/reference.srctrace index c715c37e58b235d44df560ea3d9e4990c02029bb..bfcd9c40fd3c01a71ac32e6537d5536da80c652a 100644 GIT binary patch delta 14 Vcmcb>bb)Dt1G52Vbb)Dt19QAd>PBZ?MgS(r1abfX diff --git a/testsuite/tests/320-varying-scos/extra.opt b/testsuite/tests/320-varying-scos/extra.opt deleted file mode 100644 index 53cb5a548..000000000 --- a/testsuite/tests/320-varying-scos/extra.opt +++ /dev/null @@ -1 +0,0 @@ -bin-traces DEAD Tests specific to source traces diff --git a/testsuite/tests/320-varying-scos/varying_header/src/bar.c b/testsuite/tests/320-varying-scos/varying_header/src/bar.c deleted file mode 100644 index fbe564ba3..000000000 --- a/testsuite/tests/320-varying-scos/varying_header/src/bar.c +++ /dev/null @@ -1,2 +0,0 @@ -#define B -#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_header/src/foo.c b/testsuite/tests/320-varying-scos/varying_header/src/foo.c deleted file mode 100644 index 355ae477a..000000000 --- a/testsuite/tests/320-varying-scos/varying_header/src/foo.c +++ /dev/null @@ -1,2 +0,0 @@ -#define A -#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_header/src/foo.h b/testsuite/tests/320-varying-scos/varying_header/src/foo.h deleted file mode 100644 index 76a1e6520..000000000 --- a/testsuite/tests/320-varying-scos/varying_header/src/foo.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifdef A -int -foo () -{ - return 0; -} -#endif - -#ifdef B -int -bar () -{ - return 0; -} -#endif; diff --git a/testsuite/tests/320-varying-scos/varying_header/src/main.c b/testsuite/tests/320-varying-scos/varying_header/src/main.c deleted file mode 100644 index a9bce4a14..000000000 --- a/testsuite/tests/320-varying-scos/varying_header/src/main.c +++ /dev/null @@ -1,5 +0,0 @@ -int -main () -{ - return 0; -} diff --git a/testsuite/tests/320-varying-scos/varying_header/test.py b/testsuite/tests/320-varying-scos/varying_header/test.py deleted file mode 100644 index de5644023..000000000 --- a/testsuite/tests/320-varying-scos/varying_header/test.py +++ /dev/null @@ -1,29 +0,0 @@ -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -from SUITE.context import thistest -from SUITE.cutils import Wdir -from SUITE.tutils import gprfor -from SUITE.gprutils import GPRswitches - -tmp = Wdir("tmp_") - -build_run_and_coverage( - gprsw=GPRswitches( - root_project=gprfor(srcdirs=["../src"], mains=["main.c"]), - ), - covlevel="stmt", - mains=["main"], - extra_coverage_args=["-axcov", "--output-dir=xcov"], - trace_mode="src", -) -check_xcov_reports( - "xcov", - { - "bar.c.xcov": {}, - "foo.c.xcov": {}, - "foo.h.xcov": {"-": {5, 13}}, - "main.c.xcov": {"+": {4}}, - }, - discard_empty=False, -) - -thistest.result() diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/bar.c b/testsuite/tests/320-varying-scos/varying_in_scope/src/bar.c deleted file mode 100644 index fbe564ba3..000000000 --- a/testsuite/tests/320-varying-scos/varying_in_scope/src/bar.c +++ /dev/null @@ -1,2 +0,0 @@ -#define B -#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.c b/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.c deleted file mode 100644 index 355ae477a..000000000 --- a/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.c +++ /dev/null @@ -1,2 +0,0 @@ -#define A -#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h b/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h deleted file mode 100644 index e36a63966..000000000 --- a/testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h +++ /dev/null @@ -1,10 +0,0 @@ -int -foo () -{ -#ifdef A - return 0; -#endif -#ifdef B - return 1; -#endif; -} diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/src/main.c b/testsuite/tests/320-varying-scos/varying_in_scope/src/main.c deleted file mode 100644 index a9bce4a14..000000000 --- a/testsuite/tests/320-varying-scos/varying_in_scope/src/main.c +++ /dev/null @@ -1,5 +0,0 @@ -int -main () -{ - return 0; -} diff --git a/testsuite/tests/320-varying-scos/varying_in_scope/test.py b/testsuite/tests/320-varying-scos/varying_in_scope/test.py deleted file mode 100644 index 487e4ab1b..000000000 --- a/testsuite/tests/320-varying-scos/varying_in_scope/test.py +++ /dev/null @@ -1,54 +0,0 @@ -""" -Check that gnatcov correctly load checkpoints when a source has a version that -varies across runs, and when the varying part is in the same scope for both -versions. Check that the scope metrics are as expected by inspecting the XML -report. -""" - -from lxml import etree - -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -from SUITE.context import thistest -from SUITE.cutils import Wdir -from SUITE.tutils import gprfor -from SUITE.gprutils import GPRswitches - -tmp = Wdir("tmp_") - -build_run_and_coverage( - gprsw=GPRswitches( - root_project=gprfor(srcdirs=["../src"], mains=["main.c"]), - ), - covlevel="stmt", - mains=["main"], - extra_coverage_args=["-axcov", "-axml", "--output-dir=report"], - trace_mode="src", -) -check_xcov_reports( - "report/xcov", - { - "bar.c.xcov": {}, - "foo.c.xcov": {}, - "foo.h.xcov": {"-": {5, 8}}, - "main.c.xcov": {"+": {4}}, - }, - discard_empty=False, -) - -# Check scope metrics -xml = etree.parse("report/xml/foo.h.xml") -xpath_query = ( - ".//scope_metric/obligation_stats/metric" - '[@kind="total_obligations_of_relevance"]' -) - -# Find all matching metrics -metrics = xml.xpath(xpath_query) - -# We expect 2 statement violations for the header and the associated function -thistest.fail_if( - int(metrics[0].get("count")) != 2 or int(metrics[1].get("count")) != 2, - "unexpected scope metrics", -) - -thistest.result() diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/bar.c b/testsuite/tests/320-varying-scos/varying_meta/src/bar.c deleted file mode 100644 index 289891d9f..000000000 --- a/testsuite/tests/320-varying-scos/varying_meta/src/bar.c +++ /dev/null @@ -1,2 +0,0 @@ -#define NAME bcd -#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/foo.c b/testsuite/tests/320-varying-scos/varying_meta/src/foo.c deleted file mode 100644 index ac771fcbc..000000000 --- a/testsuite/tests/320-varying-scos/varying_meta/src/foo.c +++ /dev/null @@ -1,2 +0,0 @@ -#define NAME a -#include "foo.h" diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/foo.h b/testsuite/tests/320-varying-scos/varying_meta/src/foo.h deleted file mode 100644 index 959587eeb..000000000 --- a/testsuite/tests/320-varying-scos/varying_meta/src/foo.h +++ /dev/null @@ -1,6 +0,0 @@ -int -foo () -{ - int NAME; // # foo-decl - return 0; // # foo-return -} diff --git a/testsuite/tests/320-varying-scos/varying_meta/src/test_1.c b/testsuite/tests/320-varying-scos/varying_meta/src/test_1.c deleted file mode 100644 index b14025e4a..000000000 --- a/testsuite/tests/320-varying-scos/varying_meta/src/test_1.c +++ /dev/null @@ -1,12 +0,0 @@ -int -main () -{ - return 0; -} - -//# foo.h -// /foo-decl/ l- ## s- -// /foo-return/ l- ## s- -// -//# foo.c -//# bar.c diff --git a/testsuite/tests/320-varying-scos/varying_meta/test.py b/testsuite/tests/320-varying-scos/varying_meta/test.py deleted file mode 100644 index b7842ac2c..000000000 --- a/testsuite/tests/320-varying-scos/varying_meta/test.py +++ /dev/null @@ -1,35 +0,0 @@ -""" -Check that gnatcov correctly discards coverage data for a compilation unit -version that conflicts with a previously loaded version. Note: the use of the -TestCase driver framework matters here, as if we do not discard source coverage -obligations (those coming from bar.h, or foo.h: it does not really matter -which), we end up with four coverage obligations in foo.h, and thus four -violations. This is actually checked through the report format check by the -TestCase framework. -""" - -from SUITE.context import thistest -from SUITE.cutils import contents_of -from SCOV.tctl import CAT -from SCOV.tc import TestCase - -tolerate_cov_messages = "|".join( - [ - r"warning: Discarding source coverage data for unit" - r".*foo.h \(from .*bar.c\), loaded from .*foo.c.sid", - r"warning: traces for .*foo.h .* are inconsistent .*", - ] -) -TestCase( - category=CAT.stmt, - tolerate_cov_messages=tolerate_cov_messages, -).run() - -# Check that gnatcov output contains the expected error messages -thistest.fail_if_no_match( - "gnatcov coverage output", - tolerate_cov_messages, - contents_of("s_1/xcov.out").strip(), -) - -thistest.result() diff --git a/testsuite/tests/320-varying-scos/varying_source/src1/main.adb b/testsuite/tests/320-varying-scos/varying_source/src1/main.adb deleted file mode 100644 index 05ad557f7..000000000 --- a/testsuite/tests/320-varying-scos/varying_source/src1/main.adb +++ /dev/null @@ -1,6 +0,0 @@ -with Ada.Text_IO; use Ada.Text_IO; - -procedure Main is -begin - Put_Line ("World"); -end Main; diff --git a/testsuite/tests/320-varying-scos/varying_source/src2/main.adb b/testsuite/tests/320-varying-scos/varying_source/src2/main.adb deleted file mode 100644 index 78cf5e255..000000000 --- a/testsuite/tests/320-varying-scos/varying_source/src2/main.adb +++ /dev/null @@ -1,6 +0,0 @@ -with Ada.Text_IO; use Ada.Text_IO; - -procedure Main is -begin - Put_Line ("Hello"); -end Main; diff --git a/testsuite/tests/320-varying-scos/varying_source/test.py b/testsuite/tests/320-varying-scos/varying_source/test.py deleted file mode 100644 index 3e5f31ea8..000000000 --- a/testsuite/tests/320-varying-scos/varying_source/test.py +++ /dev/null @@ -1,71 +0,0 @@ -""" -Check that gnatcov rejects the checkpoint information for different source -versions. -""" - -from e3.fs import mkdir - -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -from SUITE.context import thistest -from SUITE.cutils import contents_of, Wdir -from SUITE.tutils import gprfor, xcov -from SUITE.gprutils import GPRswitches - -tmp = Wdir("tmp_") - -root_project = gprfor(srcdirs=["."], langs=["ada"], mains=["main.adb"]) - - -def generate_checkpoint(source_body, ckpt_name): - - with open("main.adb", "w+") as f: - f.write( - f"""procedure Main is - begin - {source_body} - end Main;""" - ) - - build_run_and_coverage( - gprsw=GPRswitches(root_project=root_project), - covlevel="stmt", - mains=["main"], - extra_coverage_args=[ - "--cancel-annotate", - "--save-checkpoint", - ckpt_name, - ], - trace_mode="src", - ) - - -generate_checkpoint("null;", "v1.ckpt") -generate_checkpoint("null;\nnull;", "v2.ckpt") - -coverage_log = "coverage.log" -mkdir("xcov") -p = xcov( - [ - "coverage", - "-P", - root_project, - "--level=stmt", - "-Cv1.ckpt", - "-Cv2.ckpt", - "-axcov", - "--output-dir", - "xcov", - ], - out=coverage_log, - register_failure=False, -) - -thistest.fail_if_no_match( - "Unexpected error message from 'gnatcov coverage'.", - regexp=r"warning: unexpected fingerprint, cannot merge coverage" - r" information for main.adb \(from v2.ckpt\)", - actual=contents_of(coverage_log), -) - -check_xcov_reports("xcov", {"main.adb.xcov": {"+": {3}}}) -thistest.result() diff --git a/testsuite/tests/320-varying-scos/varying_source_ckpt/main.c b/testsuite/tests/320-varying-scos/varying_source_ckpt/main.c deleted file mode 100644 index f14f9e495..000000000 --- a/testsuite/tests/320-varying-scos/varying_source_ckpt/main.c +++ /dev/null @@ -1,10 +0,0 @@ -int -main () -{ -#ifdef A - return 0; -#endif -#ifdef B - return 0; -#endif -} diff --git a/testsuite/tests/320-varying-scos/varying_source_ckpt/test.py b/testsuite/tests/320-varying-scos/varying_source_ckpt/test.py deleted file mode 100644 index 59b831a4c..000000000 --- a/testsuite/tests/320-varying-scos/varying_source_ckpt/test.py +++ /dev/null @@ -1,48 +0,0 @@ -""" -Check that gnatcov coverage correctly aggregates coverage data of a file that -has various version according to the preprocessing configuration. -""" - -from SCOV.minicheck import build_run_and_coverage, check_xcov_reports -from SUITE.context import thistest -from SUITE.cutils import Wdir -from SUITE.tutils import gprfor, xcov -from SUITE.gprutils import GPRswitches - -tmp = Wdir("tmp_") - -prj = gprfor(srcdirs=[".."], mains=["main.c"]) - -# Compute coverage data with the A configuration -build_run_and_coverage( - gprsw=GPRswitches(root_project=prj), - covlevel="stmt", - mains=["main"], - extra_instr_args=["--c-opts=-DA"], - extra_coverage_args=["--cancel-annotate", "--save-checkpoint", "a.ckpt"], - trace_mode="src", -) - -# Compute coverage data for the B configuration -build_run_and_coverage( - gprsw=GPRswitches(root_project=prj), - covlevel="stmt", - mains=["main"], - extra_instr_args=["--c-opts=-DB"], - extra_coverage_args=["--cancel-annotate", "--save-checkpoint", "b.ckpt"], - trace_mode="src", -) - -# Aggregate the coverage data to produce an xcov report -xcov( - ["coverage", "-P", prj, "--level=stmt", "-axcov", "-Ca.ckpt", "-Cb.ckpt"], - tolerate_messages="warning: inconsistent preprocessing information.*", -) - -check_xcov_reports( - "obj", - {"main.c.xcov": {"+": {5, 8}}}, - discard_empty=False, -) - -thistest.result() diff --git a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected index 452f30727..96a156dfb 100644 --- a/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected +++ b/testsuite/tests/R417-010-scope-metrics/main.adb.xml.expected @@ -403,27 +403,27 @@ - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index 8d65dbe4b94a5d8e0b66773112166929960175d1..0b910a88605bc3f6631834b619c3a63b87379961 100644 GIT binary patch delta 71 zcmaFD{e*jh94nhRhp_ZSWkq8X3kC*u1_lOUAT}~EGSxLO(={?yFtD&Pw6roZXW#&e Wa|5x0v5C2=gEdZO^C6)jH diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid index 7323a92fefb9207223f3a92132b9facd0336c31e..08849a8e97de946c831d85de84fdc02880083395 100644 GIT binary patch delta 97 zcmdnXyp&nQ-On*3IloLHIU_YWyC6R^uY^H(qDYh)BLf2i2!p|=w~G9g>$4V2eE5iK ly}KoX1-OI#<*Fmg^-U}QzYEE8WEOtxig003A|8$$p9 delta 106 zcmZ3=yq8(T-On*3IloLHIU_YWyC6R^uY^HlqDT}Q0~k!4;;O<3WFg~EZx#6~*Jmx5 x`0x?edV%xzrKF{&OnhlG@g|Rm(c1625=B;@w}kCrVlH@|SmklWZ?Ym|3jkJkB4_{r diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid index 49d156be429897c0a3ec5e4525ea72703ced3d24..c1f72df6195d71afe8f5ec83b29080a3e60f6b74 100644 GIT binary patch delta 122 zcmeyzagIa8-On*3IloLHIU_YWyC6R^uY^H(qDU(jBLfUf+%7*^l0|&-1t!*s*K~v# ynSc@?3{t@kRy27xqckr}2rN9=kU2GTDKNW%4b?sLc^fYD@rpEf=!@ delta 183 zcmX@d@sC5q-On*3IloLHIU_YWyC6R^uY^HlqDbq+BZ4Z73=9k)3<4l}O?yRipyR4r zbHZoIDZ3{u<6BsJW8yWFiAM$W->7|2R9D?4=-hhBW$U8*M~Z*{W?*Cj>H%Rm0C7MD zF->-5G-70$T*GL^3$uhBBsW=>QF`(z#yFsnBJ0_nsQ+3Vr1o(|-m>8R_5S+ZuMTe3 IU{YfO05}LV#{d8T diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt index d01ce8c959310edfdc0079e589d5b4757387aaf0..3f2e2f96ef23270a97d8168ce0704f50ebe555b8 100644 GIT binary patch delta 230 zcmZ3^cb!kf-On*3IloLHIU_YWyC6R^uY^H(qsS9RNk#?+1`uWjVkRif0ur07$Rs+s zm|1$V12d~BD^P?Dssg48#0TjDsb<(QP3PmMX%}8k!;HpfDR$8m0uq2WepeV#XcQbUuEXcH#9j9?i~g@itE^7~5w|E@YMk>Sp0( z2ddzJs^*;B$Rr~YckXv})z=^7a;7+6>tT3Q)dDrg%RSQ!|A91H?58UU>zFy{aO delta 251 zcmaFJw~)AW*e b>lzp<7+6}F8dw>cDrg%RSs56>Tmqv3Uui7r diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 309ed84ff45210f78dda60cbd59cb5d97dee8d76..3ce172c4b5218d2c180120df0108517ff5b0342e 100644 GIT binary patch delta 286 zcmew+v_e3{-On*3IloLHIU_YWyC6R^uY^H(qlh6RFCzm30|DOXp26AB- zWDW>0u4%7m4s={~YfktqIc4{RWqb>3Z%kgureMv;0+a?}kQPoL1_8#E9?9Dm@yC49 zyZG6BLy(}|KcATfAPJCpAnU-2C-*WNu|ik}n5`!Bvx;n9!g82dZo=$~8gop_Pl6N* Y0I`voo@J&d>-On*3IloLHIU_YWyC6R^uY^Hlqlh6R8v_t9GEB~9bd6vHGeKMku9ape z+|%=V_P*LJ@4Dl2jy?6b#|=^r10Z!E@E-_ZG~b0){@2dDKbG0F?U&Pm{4BSuJ?)bX znMAaozLNN)eeeDhtCL6HKD2TwViUgJ!^i~G2Erf!HVtg`w^+7V~BB#lF{1lx)McJpSOhVU}7$Ko>=8^#gCC0Xc7p6 z0ORBa77>>|j;n6X37;jW?4GcUZ(;2Xh&-yNL1G|#h4#ER%b%lH^&u+#k$9DI z_?(@+hd`d!f1~zAQC)SHpmXafm#vHLA1VI*n}Lx9s0)Na0PJ~?7eEY_$rqW77+EHB zFk1!+W8p@^?0^Y^XpmL%>?JM@Ik~?R z7uo)Q_j{2AyVAQkAlHhlXM3XlYjKd;#}#?Yg7??^>vz98xH*jZFf)6KzQTt$E>)8i O*hQJl4JMnje*^&Q(XLkj diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt index 2b340c9cf09791bc5897a700b538781ba3eadf9f..26c3561cc377f0fdb02ad3c8f383db42db96c6b4 100644 GIT binary patch delta 278 zcmdle^q617-On*3IloLHIU_YWyC6R^uY^H(qlhM>8Y2S(0|bhmi@W4TM1eY#PjJrpft?3X{c|B*Bh?DFexV zdaKA^xjt*b#D|Z#)(f1!FC{HK1*{)Rz>FitQD#PKzw1gAS$*CTwu6be;CW(|#}z+D zW}rzR3<5AOLU>St$x%!)8p!5@WI=qPJ@3u(=jc^^h)RDXUZos9XJ_vru;<^XeNj|b z-6iPUddg+%qWedRfB$A+WC7{|VGsb@19Ccu!7}+IlMy4!Bxb965EtYYPN>vMkL2x( z_+vilUHojmAxO~fpU+GKpcEK@w1d=g05M2C2!M?PF+diu@UYvl~B3=DusLEFFxNP(?`Sqr2AUwN;Z diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid index c15c782f198c6dc4d6084f2a00fa285a3931b817..9ea2fefd5d3336ffca28eed4ed8ef663652c4e67 100644 GIT binary patch delta 93 zcmdnbyqsCY-On*3IloLHIU_YWyC6R^uY^H(qDYJyBLf2i2!lbbG(+K@p4YSY)oyv$ j9iMaTsmDETkObqzGS|s9j9il&7};QW;%kG+_KXbxCFdOx delta 75 zcmZ3^yq{Ub-On*3IloLHIU_YWyC6R^uY^HlqDTxI0~k!4<~nhzz{FaKiSI2Y-sBN^ d`by%H_PzU4tWF+%`_Rg%h)wu<&tzrB7695a9Pj`D diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid index 4d89b525b304ae68e888d097f98b44f1d7754491..fc93ad22dfd9ba018c8ea5938ec5479f73de1a4e 100644 GIT binary patch delta 93 zcmdnbyqsCY-On*3IloLHIU_YWyC6R^uY^H(qDYJyBLf2i2!p|=w~G9g>$4V2eE5iK ky}KoX1-%UmbdFmg?9U}S^giLVVN+cP!*01U+(8vp&EI@ywud-5~Jpv^H%YD@rxDHt9A delta 163 zcmcb_(Zng@?&lbioL{DpoRONGU67xdSHd7NQKWO?5kX!?1_lNY1_8#2%jG9N(wTTv zK>v-}7e#f|U4qW7r(Cu!x__kj_iqM9CZHM+h64}>q?u{5C!-M~)8qz5E4YE|Ai2qk ojM9_OF~$Ln6j{&qME%#|AhnMx@|FefulLvQesyrO4wD)a00adrNdN!< diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 08c56eeae..758ceeb2e 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -600,14 +600,14 @@ package body Annotations.Dynamic_Html is Line_Stats : constant Li_Stat_Array := Line_Metrics (File_Info, - Scope_Ent.Source_Range.L.First_Sloc.Line, + Scope_Ent.Start_Sloc.Line, (if Is_Root then Last_Line (File_Info) - else Scope_Ent.Source_Range.L.Last_Sloc.Line)); + else Scope_Ent.End_Sloc.Line)); -- Adjust Scope_Ent.End_Sloc for the root node as it is -- No_Local_Location by default. - Ob_Stats : constant Ob_Stat_Array := - Obligation_Metrics (Get_SCOs (Scope_Ent.Source_Range)); + Ob_Stats : constant Ob_Stat_Array := + Obligation_Metrics (Scope_Ent.From, Scope_Ent.To); begin Scope_Metrics_JSON.Set_Field ("scopeName", Scope_Ent.Name); Scope_Metrics_JSON.Set_Field ("scopeLine", Scope_Ent.Sloc.Line); diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index fe30b0996..a21240e6a 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -586,9 +586,9 @@ package body Annotations.Xml is Line_Stats : constant Li_Stat_Array := Line_Metrics (File_Info, - Scope_Ent.Source_Range.L.First_Sloc.Line, + Scope_Ent.Start_Sloc.Line, (if Is_Root then Last_Line (File_Info) - else Scope_Ent.Source_Range.L.Last_Sloc.Line)); + else Scope_Ent.End_Sloc.Line)); -- Adjust Scope_Ent.End_Sloc for the root node as it is -- No_Local_Location by default. begin @@ -598,7 +598,7 @@ package body Annotations.Xml is Print_Coverage_Li_Stats (Pp, Line_Stats, Dest_Compilation_Unit); Print_Coverage_Ob_Stats (Pp, - Obligation_Metrics (Get_SCOs (Scope_Ent.Source_Range)), + Obligation_Metrics (Scope_Ent.From, Scope_Ent.To), Dest_Compilation_Unit); while Has_Element (Child) loop Pp_Scope_Entity (Child); diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index c3a5ec1ea..0dd05164a 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -488,17 +488,10 @@ package body Annotations is -- because this depends on violation count for each exempted region. FI.Li_Stats := Line_Metrics (FI, 1, Last_Line (FI)); - - declare - SCOs : SCO_Sets.Set; - begin - for SCO_Range of SCO_Ranges (Comp_Unit (File_Index)) loop - for SCO in SCO_Range.First .. SCO_Range.Last loop - SCOs.Include (SCO); - end loop; - end loop; - FI.Ob_Stats := Obligation_Metrics (SCOs); - end; + FI.Ob_Stats := + Obligation_Metrics + (First_SCO (Comp_Unit (File_Index)), + Last_SCO (Comp_Unit (File_Index))); for J in Global_Stats'Range loop Global_Stats (J) := Global_Stats (J) + FI.Li_Stats (J); @@ -1037,7 +1030,7 @@ package body Annotations is -- Obligation_Metrics -- ------------------------ - function Obligation_Metrics (SCOs : SCO_Sets.Set) return Ob_Stat_Array + function Obligation_Metrics (From, To : SCO_Id) return Ob_Stat_Array is Result : Ob_Stat_Array; @@ -1083,7 +1076,10 @@ package body Annotations is end Update_Level_Stats; begin - for SCO of SCOs loop + if From = No_SCO_Id then + return Result; + end if; + for SCO in From .. To loop case Kind (SCO) is when Statement => Update_Level_Stats (SCO, Get_Line_State (SCO, Stmt), Stmt); @@ -1106,8 +1102,7 @@ package body Annotations is Coverage.Assertion_Condition_Coverage_Enabled and then Is_Assertion (SCO); begin - if Coverage.MCDC_Coverage_Enabled - or else Assertion_Decision + if Coverage.MCDC_Coverage_Enabled or else Assertion_Decision then declare Condition_Level : constant Coverage_Level := @@ -1115,6 +1110,7 @@ package body Annotations is then Coverage.Assertion_Condition_Level else Coverage.MCDC_Level); begin + -- Conditions in that decision for J in @@ -1130,11 +1126,11 @@ package body Annotations is then ATCC else MCDC)); -- If the parent decision is partially covered, - -- then the SCO_State for each condition - -- will be No_Code, and the SCO_State for the + -- then the SCO_State for each condition will be + -- No_Code, and the SCO_State for the -- MCDC/Assertion condition Coverage_Level - -- associated to the parent decision SCO will - -- be Not_Covered. + -- associated to the parent decision SCO will be + -- Not_Covered. Condition_State : SCO_State; diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index 8854c6f4b..a88432b67 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -319,8 +319,8 @@ private From, To : Natural) return Li_Stat_Array; -- Return line metrics for the given line range - function Obligation_Metrics (SCOs : SCO_Sets.Set) return Ob_Stat_Array; - -- Return obligation metrics for the given SCO set + function Obligation_Metrics (From, To : SCO_Id) return Ob_Stat_Array; + -- Return obligation metrics for the given SCO range function SCO_Kind_Image (SCO : SCO_Id) return String; -- Get the string representation of the SCO_Kind of SCO. A special diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 5c259b2e0..7725c3fd0 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -39,7 +39,7 @@ with Traces_Source; use Traces_Source; package Checkpoints is - subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 20; + subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 19; -- For compatibility with previous Gnatcov versions, the checkpoint -- file format is versioned. -- @@ -63,8 +63,6 @@ package Checkpoints is -- 17 -- Add support for Fun_Call and Guarded Expression coverage -- 18 -- Removed support for tags (separate coverage) -- 19 -- Removed support for instance ids (separate coverage) - -- 20 -- Rework Scope_Entity to identify scopes by their Start/End_Sloc - -- rather than their Start/End_SCO. -- -- Note that we always use the last version when creating a checkpoint. -- @@ -117,7 +115,7 @@ package Checkpoints is (Relocs : in out Checkpoint_Relocations; CP_CU_Id : CU_Id); -- Mark the source file index or compilation unit as ignored in the - -- checkpoint relocation. Trying to remap that source file index or + -- checkpoint relocation. Tying to remap that source file index or -- compilation unit will result in an error. procedure Ignore_SCO diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index 9fa7dcf80..af3c1ca5e 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -220,13 +220,6 @@ package body Coverage.Source is Ignored_SF_Map : Unit_To_Ignored_Maps.Map; -- Map units of interest to the list of associated ignored source files - procedure Initialize_SCI_For_SID - (CU : CU_Id; - SCOs_Fingerprint : SC_Obligations.Fingerprint_Type); - -- Initialize source coverage information vectors for obligations in CU, - -- for SCOs_Fingerprint version, assumed to come from source - -- instrumentation. - -------------------------- -- Basic_Block_Has_Code -- -------------------------- @@ -2199,11 +2192,12 @@ package body Coverage.Source is -- Sanity check that Fingerprint is consistent with what the -- instrumenter recorded in the CU info. - if not Has_Fingerprint (CU, Fingerprint) - or else Bit_Maps_Fingerprint /= - SC_Obligations.Bit_Maps_Fingerprint (CU, Fingerprint) - or else Annotations_Fingerprint /= - SC_Obligations.Annotations_Fingerprint (CU, Fingerprint) + if Fingerprint /= SC_Obligations.Fingerprint (CU) + or else + Bit_Maps_Fingerprint /= SC_Obligations.Bit_Maps_Fingerprint (CU) + or else + Annotations_Fingerprint /= + SC_Obligations.Annotations_Fingerprint (CU) then Warn ("traces for " & Unit_Image & " (from " & Filename & ") are" & " inconsistent with the corresponding Source Instrumentation" @@ -2217,7 +2211,7 @@ package body Coverage.Source is -- Discharge SCOs based on source traces - BM := Bit_Maps (CU, Fingerprint); + BM := Bit_Maps (CU); ST := Scope_Traversal (CU); for J in Stmt_Buffer'Range loop @@ -2233,7 +2227,7 @@ package body Coverage.Source is -- when one of them (which actually is the last) is covered. declare - Stmt_Blocks : SCO_Id_Vector_Vector renames Blocks (CU, Fingerprint); + Stmt_Blocks : SCO_Id_Vector_Vector renames Blocks (CU); Block_Index : Positive; begin if not Stmt_Blocks.Is_Empty then @@ -2479,13 +2473,11 @@ package body Coverage.Source is end if; end Initialize_SCI; - ---------------------------- - -- Initialize_SCI_For_SID -- - ---------------------------- + ---------------------------------------- + -- Initialize_SCI_For_Instrumented_CU -- + ---------------------------------------- - procedure Initialize_SCI_For_SID - (CU : CU_Id; - SCOs_Fingerprint : SC_Obligations.Fingerprint_Type) is + procedure Initialize_SCI_For_Instrumented_CU (CU : CU_Id) is procedure Set_Has_Code (SCO : SCO_Id); -- If SCO is a statement, mark it as having code @@ -2503,7 +2495,7 @@ package body Coverage.Source is end Set_Has_Code; Stmt_Bit_Map : Statement_Bit_Map renames - Bit_Maps (CU, SCOs_Fingerprint).Statement_Bits.all; + Bit_Maps (CU).Statement_Bits.all; -- Start of processing for Initialize_SCI_For_Instrumented_CU @@ -2517,8 +2509,7 @@ package body Coverage.Source is -- instrumented statement SCOs in blocks. declare - Stmt_Blocks : SCO_Id_Vector_Vector renames - Blocks (CU, SCOs_Fingerprint); + Stmt_Blocks : SCO_Id_Vector_Vector renames Blocks (CU); Block_Index : Positive; begin if not Stmt_Blocks.Is_Empty then @@ -2551,17 +2542,6 @@ package body Coverage.Source is end loop; end if; end; - end Initialize_SCI_For_SID; - - ---------------------------------------- - -- Initialize_SCI_For_Instrumented_CU -- - ---------------------------------------- - - procedure Initialize_SCI_For_Instrumented_CU (CU : CU_Id) is - begin - for Fingerprint of SC_Obligations.Fingerprints (CU) loop - Initialize_SCI_For_SID (CU, Fingerprint); - end loop; end Initialize_SCI_For_Instrumented_CU; -------------------------- diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index ea1a96e43..c7ca599a4 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -1206,35 +1206,6 @@ package body Files_Table is end; end Get_Line; - -------------- - -- Get_SCOs -- - -------------- - - function Get_SCOs - (Source_Range : Source_Location_Range) return SCO_Sets.Set - is - Result : SCO_Sets.Set; - FI : constant File_Info_Access := - Get_File (Source_Range.Source_File); - Last : constant Positive := Last_Line (FI); - begin - for Line in - Source_Range.L.First_Sloc.Line .. Source_Range.L.Last_Sloc.Line - loop - exit when Line > Last; - declare - SCOs : constant SCO_Id_Array_Acc := Get_Line (FI, Line).SCOs; - begin - if SCOs /= null then - for SCO of SCOs.all loop - Result.Include (SCO); - end loop; - end if; - end; - end loop; - return Result; - end Get_SCOs; - --------------------- -- Get_Simple_Name -- --------------------- diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index 5749e6624..f5b73c8e1 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -319,12 +319,7 @@ package Files_Table is type Line_Info_Access is access all Line_Info; Empty_Line_Info : constant Line_Info_Access; - -- Describe a source file - one element per line - - package Source_Line_Vectors is new Ada.Containers.Vectors - (Index_Type => Positive, - Element_Type => Line_Info_Access); - type Source_Lines is new Source_Line_Vectors.Vector with null record; + type Source_Lines is private; type Any_Ignore_Status is (Unknown, Always, Sometimes, Never); -- Represents the different states a source file can be regarding the @@ -518,11 +513,7 @@ package Files_Table is function Get_Line (Sloc : Source_Location) return Line_Info_Access with Pre => Sloc = Slocs.No_Location - or else Get_File (Sloc.Source_File).Kind in Stub_File | Source_File; - - function Get_SCOs - (Source_Range : Source_Location_Range) return SCO_Sets.Set; - -- Return all of the SCOs under the given Source_Range + or else Get_File (Sloc.Source_File).Kind in Stub_File | Source_File; procedure Set_Encoding (Encoding : String); -- Set the encoding used to interpret source code (this is a global @@ -685,6 +676,12 @@ package Files_Table is -- "-Wimplicit-fallthrough" private + -- Describe a source file - one element per line + + package Source_Line_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, + Element_Type => Line_Info_Access); + type Source_Lines is new Source_Line_Vectors.Vector with null record; Empty_Line_Info : constant Line_Info_Access := new Line_Info; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index b4272f616..402cff2e3 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -898,14 +898,6 @@ procedure GNATcov_Bits_Specific is (+Filename, (if Has_Matcher then Matcher'Access else null)); end loop; - -- Then, create source coverage data structure for each loaded unit. - -- Note that this must be done after having loaded every version of - -- the compilation unit, which can be found across SID files. - - for CU in Valid_CU_Id'First .. Last_CU loop - Coverage.Source.Initialize_SCI_For_Instrumented_CU (CU); - end loop; - -- Now that all the scope entities that can be referenced by -- --subprograms are known, dump them if requested. diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index dc37f7f34..1bc16d054 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8017,18 +8017,16 @@ package body Instrument.Ada_Unit is Kind => Files_Table.Source_File, Indexed_Simple_Name => True); New_Scope_Ent : constant Scope_Entity := - (Source_Range => Slocs.Source_Location_Range' - (Source_File => UIC.SFI, - L => Slocs.Local_Source_Location_Range' - (First_Sloc => Local_Sloc (Start_Sloc (N.Sloc_Range)), - Last_Sloc => Local_Sloc (End_Sloc (N.Sloc_Range)))), - Name => + (From => SCO_Id (SCOs.SCO_Table.Last + 1), + To => No_SCO_Id, + Start_Sloc => Local_Sloc (Start_Sloc (N.Sloc_Range)), + End_Sloc => Local_Sloc (End_Sloc (N.Sloc_Range)), + Name => +Langkit_Support.Text.To_UTF8 (Decl.P_Defining_Name.F_Name.Text), - Sloc => Local_Sloc (Sloc (N)), - Identifier => + Sloc => Local_Sloc (Sloc (N)), + Identifier => (Decl_SFI => Decl_SFI, - Decl_Line => Natural (Decl.Sloc_Range.Start_Line)), - Start_SCO => SCO_Id (SCOs.SCO_Table.Last + 1)); + Decl_Line => Natural (Decl.Sloc_Range.Start_Line))); Inserted : Scope_Entities_Trees.Cursor; begin UIC.Scope_Entities.Insert_Child @@ -8046,16 +8044,20 @@ package body Instrument.Ada_Unit is procedure Exit_Scope (UIC : in out Ada_Unit_Inst_Context) is use Scope_Entities_Trees; - Cur_Scope : Scope_Entity renames - Scope_Entities_Trees.Element (UIC.Current_Scope_Entity); Parent_Scope : constant Cursor := Parent (UIC.Current_Scope_Entity); -- Latch the parent value before UIC.Current_Scope_Entity is freed + Scope : constant Reference_Type := + UIC.Scope_Entities.Reference (UIC.Current_Scope_Entity); begin + -- Update the last SCO for this scope entity + + Scope.To := SCO_Id (SCOs.SCO_Table.Last); + -- If the scope has no SCO (it could be possible for a package spec with -- only subprogram declarations for instance), discard it. - if SCO_Id (SCOs.SCO_Table.Last) < Cur_Scope.Start_SCO then + if Scope.To < Scope.From then UIC.Scope_Entities.Delete_Leaf (UIC.Current_Scope_Entity); end if; @@ -10275,6 +10277,11 @@ package body Instrument.Ada_Unit is end loop; Set_Bit_Maps (UIC.CU, Bit_Maps); + + -- Remap low level SCOS in Scope_Entity records to high-level SCOs. + -- See the comment for Scope_Entity.From/To. + + Remap_Scope_Entities (UIC.Scope_Entities, SCO_Map); Set_Scope_Entities (UIC.CU, UIC.Scope_Entities); -- Remap low level SCOs in blocks to high level SCOs @@ -10386,6 +10393,9 @@ package body Instrument.Ada_Unit is CU_Name : constant Compilation_Unit_Part := CU_Names.Element (I); CU : constant CU_Id := CUs.Element (I); + Fingerprint : Unbounded_String; + -- Fingerprint for the instrumented unit + Unit_Name : constant String := Ada.Characters.Handling.To_Lower (To_Ada (CU_Name.Unit)); -- Lower-case name for the instrumented unit @@ -10407,10 +10417,24 @@ package body Instrument.Ada_Unit is Suffix : constant String := "_" & Img (I); - SCOs_Fingerprint : constant SC_Obligations.Fingerprint_Type := - SC_Obligations.Fingerprint (CU); - begin + -- Turn the fingerprint value into the corresponding Ada literal + + declare + First : Boolean := True; + begin + Append (Fingerprint, "("); + for Byte of SC_Obligations.Fingerprint (CU) loop + if First then + First := False; + else + Append (Fingerprint, ", "); + end if; + Append (Fingerprint, Strings.Img (Integer (Byte))); + end loop; + Append (Fingerprint, ")"); + end; + -- Create declarations for individual buffers (statement, decision -- and MC/DC) as well as their exported addresses. Put this in -- an individual package, to avoid having to suffix each @@ -10460,25 +10484,24 @@ package body Instrument.Ada_Unit is File.Put_Line (" Buffers : aliased constant" & " GNATcov_RTS_Coverage_Buffers :="); File.Put_Line (" (Fingerprint => " - & Format_Fingerprint (SCOs_Fingerprint) & ","); + & Format_Fingerprint + (SC_Obligations.Fingerprint (CU)) + & ","); File.Put_Line (" Language => Unit_Based_Language,"); File.Put_Line (" Unit_Part => " & Unit_Part & ","); File.Put_Line (" Unit_Name =>" & " (Unit_Name'Address, Unit_Name'Length),"); - File.Put_Line - (" Bit_Maps_Fingerprint => " - & Format_Fingerprint - (SC_Obligations.Bit_Maps_Fingerprint (CU, SCOs_Fingerprint)) - & ","); + File.Put_Line (" Bit_Maps_Fingerprint => " + & Format_Fingerprint + (SC_Obligations.Bit_Maps_Fingerprint (CU)) + & ","); - File.Put_Line - (" Annotations_Fingerprint => " - & Format_Fingerprint - (SC_Obligations.Annotations_Fingerprint - (CU, SCOs_Fingerprint)) - & ","); + File.Put_Line (" Annotations_Fingerprint => " + & Format_Fingerprint + (SC_Obligations.Annotations_Fingerprint (CU)) + & ","); File.Put_Line (" Statement => Statement_Buffer'Address,"); File.Put_Line (" Decision => Decision_Buffer'Address,"); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 1fb6a3723..a6a05abae 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -202,6 +202,15 @@ package body Instrument.C is -- generated SCO (SCOs.SCO_Table.Last) is the last SCO for the current -- scope. + procedure Remap_Scopes + (Scopes : in out Scopes_In_Files_Map.Map; + SCO_Map : LL_HL_SCO_Map); + -- Convert low level SCOs in each scope for each file to high-level SCOs + -- using the mapping in SCO_Map. Set the file's SCO range to cover all of + -- its scopes' SCO ranges. + -- + -- Also remove from the Scopes map empty file scopes. + overriding procedure Append_SCO (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; @@ -700,17 +709,13 @@ package body Instrument.C is File_Scope : constant Scopes_In_Files_Map.Reference_Type := UIC.Scopes.Reference (File_Scope_Position); New_Scope_Ent : constant Scope_Entity := - (Source_Range => Source_Location_Range' - (Source_File => SFI, - L => Local_Source_Location_Range' - (First_Sloc => (Line => 1, Column => 0), - Last_Sloc => (Line => Natural'Last, Column => 0))), - Name => +Get_Simple_Name (SFI), - Sloc => (Line => 1, Column => 0), - Identifier => (Decl_SFI => SFI, Decl_Line => 0), - Start_SCO => No_SCO_Id); - -- Set Last_Sloc to Natural'Last so that it defaults to the - -- whole file as long as the scope is not closed. + (From => SCO_Id (SCOs.SCO_Table.Last + 1), + To => No_SCO_Id, + Start_Sloc => (Line => 1, Column => 0), + End_Sloc => No_Local_Location, + Name => +Get_Simple_Name (SFI), + Sloc => (Line => 1, Column => 0), + Identifier => (Decl_SFI => SFI, Decl_Line => 0)); Scope_Entity_Position : Scope_Entities_Trees.Cursor; begin @@ -748,15 +753,13 @@ package body Instrument.C is File_Scope : constant Scopes_In_Files_Map.Reference_Type := UIC.Scopes.Reference (C); New_Scope_Ent : constant Scope_Entity := - (Source_Range => Source_Location_Range' - (Source_File => File, - L => Local_Source_Location_Range' - (First_Sloc => Sloc.L, - Last_Sloc => End_Sloc (N).L)), + (From => SCO_Id (SCOs.SCO_Table.Last + 1), + To => No_SCO_Id, + Start_Sloc => Sloc.L, + End_Sloc => End_Sloc (N).L, Name => +Get_Decl_Name_Str (N), Sloc => Sloc.L, - Identifier => (Decl_SFI => File, Decl_Line => Sloc.L.Line), - Start_SCO => No_SCO_Id); + Identifier => (Decl_SFI => File, Decl_Line => Sloc.L.Line)); Inserted : Scope_Entities_Trees.Cursor; begin -- Add New_Scope_Ent to the children of the last open scope in the @@ -784,14 +787,59 @@ package body Instrument.C is is File_Scope_Ref : constant Scopes_In_Files_Map.Reference_Type := UIC.Scopes.Reference (UIC.Current_File_Scope); + Scope_Entity_Ref : constant Scope_Entities_Trees.Reference_Type := + File_Scope_Ref.Scope_Entities.Reference + (File_Scope_Ref.Current_Scope_Entity); Parent : constant Scope_Entities_Trees.Cursor := Scope_Entities_Trees.Parent (File_Scope_Ref.Current_Scope_Entity); begin + Scope_Entity_Ref.To := SCO_Id (SCOs.SCO_Table.Last); + + -- Discard the scope entity if it has no associated SCOs + + if Scope_Entity_Ref.To < Scope_Entity_Ref.From then + File_Scope_Ref.Scope_Entities.Delete_Leaf + (File_Scope_Ref.Current_Scope_Entity); + else + -- Update the last SCO for the file scope + + File_Scope_Ref.Scope_Entities.Reference + (File_Scope_Ref.File_Scope_Entity).To := Scope_Entity_Ref.To; + end if; + -- Go back to the parent scope entity File_Scope_Ref.Current_Scope_Entity := Parent; end Exit_Scope; + ------------------ + -- Remap_Scopes -- + ------------------ + + procedure Remap_Scopes + (Scopes : in out Scopes_In_Files_Map.Map; + SCO_Map : LL_HL_SCO_Map) + is + Res : Scopes_In_Files_Map.Map; + begin + for Cur in Scopes.Iterate loop + declare + File_Scope : File_Scope_Type := + Scopes_In_Files_Map.Element (Cur); + File_Scope_Entity : Scope_Entity renames + Scope_Entities_Trees.Element (File_Scope.File_Scope_Entity); + begin + -- If the file scope is empty, do not add it to the resulting map + + if File_Scope_Entity.To >= File_Scope_Entity.From then + Remap_Scope_Entities (File_Scope.Scope_Entities, SCO_Map); + Res.Insert (Scopes_In_Files_Map.Key (Cur), File_Scope); + end if; + end; + end loop; + Scopes := Res; + end Remap_Scopes; + ---------------- -- Append_SCO -- ---------------- @@ -4010,6 +4058,8 @@ package body Instrument.C is -- Iterate through the package level body entities + Remap_Scopes (UIC.Scopes, SCO_Map); + for C in UIC.Scopes.Iterate loop declare CU : constant Created_Unit_Maps.Cursor := @@ -4293,10 +4343,6 @@ package body Instrument.C is -- Name of the gnatcov_rts_coverage_buffers struct for this -- source file. - SCOs_Fingerprint : constant SC_Obligations.Fingerprint_Type := - SC_Obligations.Fingerprint (CU); - -- SCOs fingerprint for the unit - begin File.Put_Line ("/* Buffers for " & Get_Full_Name (SFI) & " */"); @@ -4331,7 +4377,7 @@ package body Instrument.C is & Buffers_Struct & " = {" & ASCII.LF & "/* .fingerprint = */ " - & Format_Fingerprint (SCOs_Fingerprint) & "," + & Format_Fingerprint (SC_Obligations.Fingerprint (CU)) & "," & ASCII.LF & "/* .language_kind = */ FILE_BASED_LANGUAGE," & ASCII.LF @@ -4355,15 +4401,13 @@ package body Instrument.C is & ASCII.LF & "/* .bit_maps_fingerprint = */ " - & Format_Fingerprint - (SC_Obligations.Bit_Maps_Fingerprint (CU, SCOs_Fingerprint)) + & Format_Fingerprint (SC_Obligations.Bit_Maps_Fingerprint (CU)) & "," & ASCII.LF & "/* .annotations_fingerprint = */ " & Format_Fingerprint - (SC_Obligations.Annotations_Fingerprint - (CU, SCOs_Fingerprint)) + (SC_Obligations.Annotations_Fingerprint (CU)) & "," & ASCII.LF diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 17ec3d141..2b9491fbe 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -355,6 +355,25 @@ package body Instrument.Common is SCOs.SCO_Table.Last; end Append_SCO; + ------------------------ + -- Remap_Scope_Entity -- + ------------------------ + + procedure Remap_Scope_Entities + (Scope_Entities : in out Scope_Entities_Tree; + SCO_Map : LL_HL_SCO_Map) is + begin + for Scope_Entity in Scope_Entities.Iterate loop + declare + Ref : constant Scope_Entities_Trees.Reference_Type := + Scope_Entities.Reference (Scope_Entity); + begin + Ref.From := SCO_Map (Nat (Ref.From)); + Ref.To := SCO_Map (Nat (Ref.To)); + end; + end loop; + end Remap_Scope_Entities; + ------------------ -- Remap_Blocks -- ------------------ diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 7eebcc511..f0708f048 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -422,6 +422,12 @@ package Instrument.Common is -- source file, also append a new entry to the SCO_Unit_Table, otherwise -- complete its last entry. + procedure Remap_Scope_Entities + (Scope_Entities : in out Scope_Entities_Tree; + SCO_Map : LL_HL_SCO_Map); + -- Convert low level SCOs in Scope_Entity to high-level SCOs using the + -- mapping in SCO_Map. + procedure Remap_Blocks (Blocks : in out SCO_Id_Vector_Vector; SCO_Map : LL_HL_SCO_Map); diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 704c34416..7713a4951 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -256,7 +256,7 @@ is -- If an instrumenter supports Source_File's language and if Project is not -- externally built, add Source_File to Project_Sources. - procedure Replace_Manual_Indications + procedure Insert_Manual_Dump_Trigger (Language : Src_Supported_Language; Project_Sources : in out File_Info_Sets.Set; Instrumenter : in out Language_Instrumenter'Class; @@ -883,14 +883,14 @@ is end Add_Instrumented_Unit; -------------------------------- - -- Replace_Manual_Indications -- + -- Insert_Manual_Dump_Trigger -- -------------------------------- - procedure Replace_Manual_Indications - (Language : Src_Supported_Language; - Project_Sources : in out File_Info_Sets.Set; - Instrumenter : in out Language_Instrumenter'Class; - Manual_Dump_Inserted : in out Boolean; + procedure Insert_Manual_Dump_Trigger + (Language : Src_Supported_Language; + Project_Sources : in out File_Info_Sets.Set; + Instrumenter : in out Language_Instrumenter'Class; + Manual_Dump_Inserted : in out Boolean; Manual_Indication_Files : File_Sets.Set) is @@ -1062,7 +1062,7 @@ is & " from a source in a parent project."); end; end if; - end Replace_Manual_Indications; + end Insert_Manual_Dump_Trigger; --------------------- -- Clean_And_Print -- @@ -1292,20 +1292,13 @@ begin -- Replace manual dump indications for C-like languages for Lang in C_Family_Language loop - Replace_Manual_Indications + Insert_Manual_Dump_Trigger (Lang, Project_Sources, Instrumenters (Lang).all, Manual_Dump_Inserted, Dump_Config.Manual_Indication_Files); end loop; - - -- The replacement of manual indications may incur filling of e.g. - -- the files table, which is then dumped into the first written - -- checkpoint before being cleared out. Preemptively clear it to avoid - -- that. - - Checkpoints.Checkpoint_Clear; end if; -- Write the files of interest to temporary files in the instrumentation @@ -1620,7 +1613,7 @@ begin end; if Dump_Config.Trigger = Manual then - Replace_Manual_Indications + Insert_Manual_Dump_Trigger (Ada_Language, Project_Sources, Ada_Instrumenter, diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 6cad5f7db..c9710c4c6 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -23,7 +23,6 @@ with Ada.Strings.Fixed; use Ada.Strings.Fixed; with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Deallocation; -with GNATCOLL.VFS; with Interfaces; with Aspects; use Aspects; @@ -35,6 +34,7 @@ with Snames; with Checkpoints; use Checkpoints; with Coverage; use Coverage; +with Coverage.Source; with Diagnostics; use Diagnostics; with Files_Table; use Files_Table; with Inputs; use Inputs; @@ -64,13 +64,8 @@ package body SC_Obligations is -- * properly ordered: if E1 and E2 are consecutive siblings, E1.To must be -- smaller than E2.From. - function Floor - (Tree : Scope_Entities_Trees.Tree; - Sloc : Source_Location) return Scope_Entities_Trees.Cursor; - -- Return the innermost scope containing Sloc - function Covers_SCO (SE : Scope_Entity; SCO : SCO_Id) return Boolean - is (In_Range (First_Sloc (SCO), SE.Source_Range)); + is (SCO in SE.From .. SE.To); -- Return whether SCO is covered by SE's SCO range function Covers_SCO @@ -78,12 +73,9 @@ package body SC_Obligations is -- Return whether SCO is covered by that element's SCO range. Id the SCO is -- a function SCO, then the scope can be the root of the tree. - function Contains_SCO (SCO : SCO_Id; CU : CU_Id) return Boolean; - -- Return whether the given CU contains the given SCO - - procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) - with Pre => Get_CU (ST) = No_CU_Id - or else Contains_SCO (SCO, Get_CU (ST)); + procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) with + Pre => Get_CU (ST) = No_CU_Id + or else SCO in First_SCO (Get_CU (ST)) .. Last_SCO (Get_CU (ST)); -- Position ST on the inner-most scope that contains SCO. -- -- This does nothing on a scope traversal type not initialized, or @@ -98,29 +90,6 @@ package body SC_Obligations is -- Source units table -- ------------------------ - type SID_Info is record - Blocks : SCO_Id_Vector_Vector; - -- List of blocks. A block is a list of statement SCOs. Note that - -- this is specific to source instrumentation, but a container cannot - -- be a discriminant-dependent component. - - Bit_Maps : CU_Bit_Maps; - -- Mapping of bits in coverage buffers to SCOs - - Bit_Maps_Fingerprint : Fingerprint_Type; - -- Hash of Bit_Maps, for consistency checks with source traces - - Annotations_Fingerprint : Fingerprint_Type := No_Fingerprint; - -- Hash of ALI_Annotations, for consistency checks with source traces - - end record; - -- Part of the information stored in a SID file, and needed to compute - -- coverage results. - - package SID_Info_Maps is new Ada.Containers.Ordered_Maps - (Key_Type => Fingerprint_Type, - Element_Type => SID_Info); - type CU_Info (Provider : SCO_Provider := SCO_Provider'First) is record Origin : Source_File_Index; -- File from which this unit's SCO info comes from. @@ -132,63 +101,56 @@ package body SC_Obligations is -- For Ada this is a simple name; for C this is either a simple name -- or full name, depending on whether the information is available. + First_SCO, Last_SCO : SCO_Id := No_SCO_Id; + -- First and last SCO ids for this unit + Deps : SFI_Vector; -- Mapping of this unit's dependency numbers to source file indices Has_Code : Boolean := False; -- Set True when object code for some source file in this unit is seen + Fingerprint : Fingerprint_Type; + -- Hash of SCO info in ALI, for incremental coverage consistency check + PP_Info_Map : SCO_PP_Info_Maps.Map; -- Information about preprocessing Scope_Entities : Scope_Entities_Tree := Scope_Entities_Trees.Empty_Tree; -- Scope tree, used to output e.g. subprogram metrics + Blocks : SCO_Id_Vector_Vector; + -- List of blocks. A block is a list of statement SCOs. Note that this + -- is specific to source instrumentation, but a container cannot be + -- a discriminant-dependent component. + ALI_Annotations : ALI_Annotation_Maps.Map; -- List of annotations for the unit - SCOs : SCO_Range_Vectors.Vector; - -- List of SCOs for this unit - - SIDs_Info : SID_Info_Maps.Map; - -- Mapping from SCOs fingerprint to SID information. A compilation - -- unit has various SID versions when it has varying SCOs: this can - -- happen when including a header file with varying inclusion - -- contexts (e.g. macro definition varying at the inclusion point). - -- Note that this is exclusively computing coverage results (e.g. - -- analyzing a trace along with SID files). - -- - -- Note that we only use the SID_Info when computing coverage results - -- resulting from instrumentation (and thus analyzing traces with SID - -- files). When retrieving coverage results from checkpoint, we only - -- need the list of SCOs fingerprints for quicker consolidation, so - -- this map elements will be empty. + Annotations_Fingerprint : Fingerprint_Type := No_Fingerprint; + -- Hash of ALI_Annotations, for consistency checks with source traces case Provider is when Compiler | LLVM => - SCOs_Fingerprint : Fingerprint_Type; - -- Hash of SCO info in checkpoint, for incremental coverage - -- consistency check. + null; when Instrumenter => - Source_Fingerprint : Fingerprint_Type; - -- Hash of source code in checkpoint, for incremental coverage - -- consistency check. Note that contrarily to binary traces, we - -- can have a varying set of SCOs from a checkpoint to another, - -- so we rely on the source code fingerprint rather than the - -- SCOs. + Bit_Maps : CU_Bit_Maps; + -- Mapping of bits in coverage buffers to SCOs + + Bit_Maps_Fingerprint : Fingerprint_Type; + -- Hash of Bit_Maps, for consistency checks with source traces True_Static_SCOs : SCO_Sets.Set; False_Static_SCOs : SCO_Sets.Set; - end case; + end record; procedure Free (CU : in out CU_Info); function Has_SCOs (CUI : CU_Info) return Boolean is - (CUI.SCOs.Length > 0 - and then CUI.SCOs.First_Element.First <= CUI.SCOs.First_Element.Last); + (CUI.First_SCO <= CUI.Last_SCO); function Are_Bit_Maps_In_Range (Bit_Maps : CU_Bit_Maps; CU : CU_Info) return Boolean; @@ -467,8 +429,7 @@ package body SC_Obligations is when Decision => Expression : SCO_Id := No_SCO_Id; - -- Top expression node for this decision. This refers to the first - -- condition SCO of the decision. + -- Top expression node for this decision D_Kind : Decision_Kind; -- Decision kind indication @@ -566,9 +527,9 @@ package body SC_Obligations is -- contain data loaded from a checkpoint. type Source_Coverage_Vectors is record - CU_Vector : CU_Info_Vectors.Vector; - BDD_Vector : BDD.BDD_Vectors.Vector; - SCO_Vector : SCO_Vectors.Vector; + CU_Vector : CU_Info_Vectors.Vector; + BDD_Vector : BDD.BDD_Vectors.Vector; + SCO_Vector : SCO_Vectors.Vector; end record; function Index @@ -622,11 +583,6 @@ package body SC_Obligations is procedure Read (CLS : in out Checkpoint_Load_State; Value : out PP_Info); -- Read a PP_Info from CLS - procedure Read - (CLS : in out Checkpoint_Load_State; Fingerprint : out Fingerprint_Type); - -- Wrapper around CLS.Read_Fingerprint to accomodate for the Read_Map - -- instantiation below. - procedure Read is new Read_Map (Key_Type => SCO_Id, Element_Type => PP_Info, @@ -634,7 +590,7 @@ package body SC_Obligations is Clear => SCO_PP_Info_Maps.Clear, Insert => SCO_PP_Info_Maps.Insert, Read_Key => Read, - Read_Element => Read); + Read_element => Read); procedure Read (CLS : in out Checkpoint_Load_State; Value : out Scope_Entity); @@ -646,29 +602,6 @@ package body SC_Obligations is Multiway_Trees => Scope_Entities_Trees, Read_Element => Read); - procedure Read - (CLS : in out Checkpoint_Load_State; Value : out SCO_Range); - -- Read a SCO_Range from CLS - - procedure Read is new Read_Vector - (Index_Type => Positive, - Element_Type => SCO_Range, - "=" => "=", - Vectors => SCO_Range_Vectors, - Read_Element => Read); - - procedure Read - (CLS : in out Checkpoint_Load_State; Value : out SID_Info); - -- Read a SID_Info from CLS - - procedure Read is new Read_Map - (Key_Type => Fingerprint_Type, - Element_Type => SID_Info, - Map_Type => SID_Info_Maps.Map, - Clear => SID_Info_Maps.Clear, - Insert => SID_Info_Maps.Insert, - Read_Key => Read, - Read_Element => Read); procedure Read (CLS : in out Checkpoint_Load_State; Value : out CU_Info); -- Read a CU_Info from CLS @@ -728,85 +661,32 @@ package body SC_Obligations is Read_Element => Read); -- Read a ALI_Annotation_Maps.Map from CLS - procedure Remap_BDD - (CP_Vectors : Source_Coverage_Vectors; - Relocs : in out Checkpoint_Relocations; - Decision_BDD : in out BDD.BDD_Type); - -- Remap a sequence of BDD nodes, for a whole decision BDD - - procedure Remap_BDD_Node - (Relocs : Checkpoint_Relocations; - B : in out BDD_Node_Id); - -- Remap a BDD node id - - procedure Remap_SCO_Id - (Relocs : Checkpoint_Relocations; - S : in out SCO_Id); - -- Remap a SCO_Id. Note: this assumes possible forward references, and - -- does not rely on SCO_Map. - - procedure Remap_SCO_Descriptor - (CP_Vectors : Source_Coverage_Vectors; - Relocs : in out Checkpoint_Relocations; - SCOD : in out SCO_Descriptor); - -- Remap one SCO_Descriptor. Note that this assumes that - -- SCOD.Sloc_Range.Source_File has already been remapped. - -- - -- Note that this expects condition SCOs of a decision to have been - -- remapped calling Remap_SCO_Descriptor - - function Sloc_Range_For_SCO - (SCOD : SCO_Descriptor) return Source_Location_Range; - -- Get the Source_Location_Range to search for in the Sloc_To_SCO map for - -- the given SCO, accounting for the specific case of decision with - -- a control location (when using binary traces): in this case, the - -- decision are located at their control location rather than the actual - -- decision location. - - function Check_SCOs_Consistency + procedure Checkpoint_Load_Merge_Unit (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; - CP_CU : in out CU_Info) return Boolean; - -- Check the consistency of the SCO in CP_CU wrt. SCOs previously loaded - -- for the a different version of the same unit. When a new SCO overlaps - -- with an existing one, this breaks the consistency of SCOs. Note that we - -- accept no SCO overlaps (thus no nesting) across compilation unit - -- versions. - - procedure Checkpoint_Load_SCOs + CP_CU : CU_Info; + Real_CU_Id : CU_Id); + -- Load CU from checkpoint that corresponds to a current unit of interest + -- whose ID is Real_CU_Id. + + procedure Checkpoint_Load_New_Unit (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; - Real_CU : in out CU_Info; - Real_CU_Id : CU_Id); - -- Load the SCOs in CP_CU and add them to Real_CU, which is the CU entry - -- for Real_CU_Id. - - procedure Checkpoint_Load_SID_Info - (CLS : in out Checkpoint_Load_State; - CP_CU : in out CU_Info; - Real_CU : in out CU_Info); - -- Load the SID information entries in SIDs_Info and add them to Real_CU - - procedure Checkpoint_Load_PP_Info - (CLS : in out Checkpoint_Load_State; - CP_CU : in out CU_Info; - Real_CU : in out CU_Info); - -- Load the preprocessing information in CP_CU and add them to Real_CU - - procedure Checkpoint_Load_Scopes - (CLS : in out Checkpoint_Load_State; - CP_CU : in out CU_Info; - Real_CU : in out CU_Info); - -- Load the scopes in CP_CU and add them to Real_CU + New_CU_Id : out CU_Id); + -- Load CU from checkpoint that does not correspond to a current unit of + -- interest. The newly assigned CU_Id is returned in New_CU_Id. procedure Checkpoint_Load_Unit (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; - CP_CU_Id : CU_Id); + New_CU_Id : out CU_Id); -- Process one compilation unit from a checkpoint. -- CP_CU_Id is the CU_Id in the checkpoint. + -- New_CU_Id is the corresponding CU_Id in the current context, and is + -- either an already existing CU_Id (if the unit was already known), + -- or a newly assigned one (if not). ----------------------------------------- -- Helper routines for Checkpoint_Save -- @@ -846,33 +726,6 @@ package body SC_Obligations is Multiway_Trees => Scope_Entities_Trees, Write_Element => Write); - procedure Write - (CSS : in out Checkpoint_Save_State; Value : SID_Info); - -- Write a SID_Info to CSS - - procedure Write is new Write_Map - (Key_Type => Fingerprint_Type, - Element_Type => SID_Info, - Map_Type => SID_Info_Maps.Map, - Cursor_Type => SID_Info_Maps.Cursor, - Length => SID_Info_Maps.Length, - Iterate => SID_Info_Maps.Iterate, - Query_Element => SID_Info_Maps.Query_Element, - Write_Key => Write, - Write_Element => Write); - -- Write a vector of SID_Info records to CSS - - procedure Write (CSS : in out Checkpoint_Save_State; Value : SCO_Range); - -- Write a SCO_Range to CSS - - procedure Write is new Write_Vector - (Index_Type => Positive, - Element_Type => SCO_Range, - "=" => "=", - Vectors => SCO_Range_Vectors, - Write_Element => Write); - -- Write a vector of SCO_Range records to CSS - procedure Write (CSS : in out Checkpoint_Save_State; Value : CU_Info); -- Write a CU_Info to CSS @@ -992,9 +845,9 @@ package body SC_Obligations is SE : Scope_Entity renames Scope_Entities.Constant_Reference (Cur); begin - Put_Line - (Prefix & Image (SE) & " source range " - & Image (SE.Source_Range)); + Put_Line (Prefix & Image (SE)); + Put_Line (Prefix & "... from " & Image (SE.From)); + Put_Line (Prefix & " to " & Image (SE.To)); end; end loop; end Dump; @@ -1024,10 +877,8 @@ package body SC_Obligations is -- Traverse_SCO -- ------------------ - procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) - is + procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) is use Scope_Entities_Trees; - SCO_Sloc : constant Local_Source_Location := First_Sloc (SCO).L; begin -- Don't do anything if there is no scope attached to ST. @@ -1087,9 +938,8 @@ package body SC_Obligations is declare SE : constant Scope_Entity := Element (Child); begin - In_Child := SE.Source_Range.L.First_Sloc <= SCO_Sloc; - exit Child_Search when - SCO_Sloc <= SE.Source_Range.L.Last_Sloc; + In_Child := SE.From <= SCO; + exit Child_Search when SE.To >= SCO; Child := Next_Sibling (Child); end; end loop Child_Search; @@ -1165,78 +1015,22 @@ package body SC_Obligations is end loop; end Add_SCO_To_Lines; - --------------------- - -- Has_Fingerprint -- - --------------------- - - function Has_Fingerprint - (CU : CU_Id; - SCO_Fingerprint : Fingerprint_Type) return Boolean is - begin - return - CU_Vector.Constant_Reference (CU).SIDs_Info.Contains (SCO_Fingerprint); - end Has_Fingerprint; - - ------------------ - -- Fingerprints -- - ------------------ - - function Fingerprints (CU : CU_Id) return Fingerprint_Vectors.Vector - is - Result : Fingerprint_Vectors.Vector; - begin - for Cur in CU_Vector.Reference (CU).SIDs_Info.Iterate loop - Result.Append (SID_Info_Maps.Key (Cur)); - end loop; - return Result; - end Fingerprints; - -------------- -- Bit_Maps -- -------------- - function Bit_Maps - (CU : CU_Id; - SCO_Fingerprint : Fingerprint_Type) return CU_Bit_Maps is + function Bit_Maps (CU : CU_Id) return CU_Bit_Maps is begin - return CU_Vector.Reference (CU) - .SIDs_Info.Element (SCO_Fingerprint).Bit_Maps; + return CU_Vector.Reference (CU).Element.Bit_Maps; end Bit_Maps; - -------------------------- - -- Bit_Maps_Fingerprint -- - -------------------------- - - function Bit_Maps_Fingerprint - (CU : CU_Id; - SCO_Fingerprint : Fingerprint_Type) return Fingerprint_Type is - begin - return CU_Vector.Constant_Reference (CU) - .SIDs_Info.Element (SCO_Fingerprint).Bit_Maps_Fingerprint; - end Bit_Maps_Fingerprint; - - ----------------------------- - -- Annotations_Fingerprint -- - ----------------------------- - - function Annotations_Fingerprint - (CU : CU_Id; - SCO_Fingerprint : Fingerprint_Type) return Fingerprint_Type is - begin - return CU_Vector.Constant_Reference (CU) - .SIDs_Info.Element (SCO_Fingerprint).Annotations_Fingerprint; - end Annotations_Fingerprint; - ------------ -- Blocks -- ------------ - function Blocks - (CU : CU_Id; - SCO_Fingerprint : Fingerprint_Type) return SCO_Id_Vector_Vector is + function Blocks (CU : CU_Id) return SCO_Id_Vector_Vector is begin - return CU_Vector.Reference (CU) - .SIDs_Info.Element (SCO_Fingerprint).Blocks; + return CU_Vector.Reference (CU).Element.Blocks; end Blocks; ----------------- @@ -1303,59 +1097,15 @@ package body SC_Obligations is Value := Result; end Read; - procedure Read - (CLS : in out Checkpoint_Load_State; Fingerprint : out Fingerprint_Type) - is - begin - Fingerprint := CLS.Read_Fingerprint; - end Read; - - procedure Read - (CLS : in out Checkpoint_Load_State; Value : out SID_Info) - is - Stmt_First, DC_First, MCDC_First : Bit_Id; - Stmt_Last, DC_Last, MCDC_Last : Any_Bit_Id; - begin - -- Read block information - - Read (CLS, Value.Blocks); - - -- Read bit maps - - Stmt_First := CLS.Read_Bit_Id; - Stmt_Last := CLS.Read_Bit_Id; - Value.Bit_Maps.Statement_Bits := - new Statement_Bit_Map (Stmt_First .. Stmt_Last); - for SCO of Value.Bit_Maps.Statement_Bits.all loop - SCO := CLS.Read_SCO; - end loop; - - DC_First := CLS.Read_Bit_Id; - DC_Last := CLS.Read_Bit_Id; - Value.Bit_Maps.Decision_Bits := - new Decision_Bit_Map (DC_First .. DC_Last); - for Info of Value.Bit_Maps.Decision_Bits.all loop - Info.D_SCO := CLS.Read_SCO; - Info.Outcome := CLS.Read_Boolean; - end loop; - - MCDC_First := CLS.Read_Bit_Id; - MCDC_Last := CLS.Read_Bit_Id; - Value.Bit_Maps.MCDC_Bits := - new MCDC_Bit_Map (MCDC_First .. MCDC_Last); - for Info of Value.Bit_Maps.MCDC_Bits.all loop - Info.D_SCO := CLS.Read_SCO; - Info.Path_Index := CLS.Read_Integer; - end loop; - Value.Bit_Maps_Fingerprint := CLS.Read_Fingerprint; - Value.Annotations_Fingerprint := CLS.Read_Fingerprint; - end Read; - procedure Read (CLS : in out Checkpoint_Load_State; Value : out Scope_Entity) is begin - Value.Source_Range := CLS.Read_Source_Location_Range; + Value.From := CLS.Read_SCO; + Value.To := CLS.Read_SCO; + + Value.Start_Sloc := CLS.Read_Local_Source_Location; + Value.End_Sloc := CLS.Read_Local_Source_Location; Value.Name := CLS.Read_Unbounded_String; Value.Sloc := CLS.Read_Local_Source_Location; @@ -1364,33 +1114,76 @@ package body SC_Obligations is Value.Identifier.Decl_Line := CLS.Read_Integer; end Read; - procedure Read - (CLS : in out Checkpoint_Load_State; Value : out SCO_Range) - is - begin - Value.First := CLS.Read_SCO; - Value.Last := CLS.Read_SCO; - end Read; - procedure Read (CLS : in out Checkpoint_Load_State; Value : out CU_Info) is Element_Template : CU_Info (SCO_Provider'Val (CLS.Read_U8)); begin Value := Element_Template; + + -- Checkpoint version 1 data + Value.Origin := CLS.Read_SFI; Value.Main_Source := CLS.Read_SFI; + Value.First_SCO := CLS.Read_SCO; + Value.Last_SCO := CLS.Read_SCO; Read (CLS, Value.Deps); Value.Has_Code := CLS.Read_Boolean; + Value.Fingerprint := CLS.Read_Fingerprint; Read (CLS, Value.PP_Info_Map); Read (CLS, Value.Scope_Entities); Read (CLS, Value.ALI_Annotations); - Read (CLS, Value.SCOs); - case Element_Template.Provider is + Value.Annotations_Fingerprint := CLS.Read_Fingerprint; + + case Value.Provider is when Compiler | LLVM => - Value.SCOs_Fingerprint := CLS.Read_Fingerprint; + null; when Instrumenter => - Read (CLS, Value.SIDs_Info); - Value.Source_Fingerprint := CLS.Read_Fingerprint; + + -- By default, use "no fingerprint" for buffer bit maps + -- fingerprints: by design checkpoints contains neither bit maps + -- nor their fingerprints (all source traces are processed before + -- loading checkpoints, and bit maps are needed only to interpret + -- source traces). + + Value.Bit_Maps_Fingerprint := No_Fingerprint; + + if Purpose_Of (CLS) = Instrumentation then + declare + Stmt_First, DC_First, MCDC_First : Bit_Id; + Stmt_Last, DC_Last, MCDC_Last : Any_Bit_Id; + begin + Stmt_First := CLS.Read_Bit_Id; + Stmt_Last := CLS.Read_Bit_Id; + Value.Bit_Maps.Statement_Bits := + new Statement_Bit_Map (Stmt_First .. Stmt_Last); + for SCO of Value.Bit_Maps.Statement_Bits.all loop + SCO := CLS.Read_SCO; + end loop; + + DC_First := CLS.Read_Bit_Id; + DC_Last := CLS.Read_Bit_Id; + Value.Bit_Maps.Decision_Bits := + new Decision_Bit_Map (DC_First .. DC_Last); + for Info of Value.Bit_Maps.Decision_Bits.all loop + Info.D_SCO := CLS.Read_SCO; + Info.Outcome := CLS.Read_Boolean; + end loop; + + MCDC_First := CLS.Read_Bit_Id; + MCDC_Last := CLS.Read_Bit_Id; + Value.Bit_Maps.MCDC_Bits := + new MCDC_Bit_Map (MCDC_First .. MCDC_Last); + for Info of Value.Bit_Maps.MCDC_Bits.all loop + Info.D_SCO := CLS.Read_SCO; + Info.Path_Index := CLS.Read_Integer; + end loop; + end; + Value.Bit_Maps_Fingerprint := CLS.Read_Fingerprint; + + -- Read block information + + Read (CLS, Value.Blocks); + end if; end case; end Read; @@ -1488,857 +1281,652 @@ package body SC_Obligations is Value.Undetermined_Cov_Count := 0; end Read; - function "<" (L, R : Static_Decision_Evaluation) return Boolean is - begin - if L.Outcome /= R.Outcome then - return L.Outcome < R.Outcome; - end if; + -------------------------------- + -- Checkpoint_Load_Merge_Unit -- + -------------------------------- - for J in R.Values.First_Index .. R.Values.Last_Index loop - if J > L.Values.Last_Index then - return True; + procedure Checkpoint_Load_Merge_Unit + (CLS : in out Checkpoint_Load_State; + CP_Vectors : Source_Coverage_Vectors; + CP_CU : CU_Info; + Real_CU_Id : CU_Id) + is + Relocs : Checkpoint_Relocations renames CLS.Relocations; + Real_CU : CU_Info renames CU_Vector.Reference (Real_CU_Id).Element.all; - elsif L.Values.Element (J) < R.Values.Element (J) then - return True; + procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) + with pre => Kind (New_SCO_Id) = Decision; - elsif L.Values.Element (J) > R.Values.Element (J) then - return False; - end if; - end loop; + ------------------------- + -- Merge_Decision_SCOs -- + ------------------------- - return False; - end "<"; + procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) + is + use SC_Obligations.BDD; - ------------------------ - -- Sloc_Range_For_SCO -- - ------------------------ + Old_SCOD : SCO_Descriptor renames CP_Vectors.SCO_Vector (Old_SCO_Id); + New_SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); - function Sloc_Range_For_SCO - (SCOD : SCO_Descriptor) return Source_Location_Range - is - Sloc_Range : Source_Location_Range := SCOD.Sloc_Range; - begin - if SCOD.Kind = Decision and then SCOD.Control_Location /= No_Location - then - Sloc_Range := To_Range (SCOD.Control_Location, No_Location); - end if; - return Sloc_Range; - end Sloc_Range_For_SCO; + Old_Reachable : Reachability renames + Old_SCOD.Decision_BDD.Reachable_Outcomes; + New_Reachable : Reachability renames + New_SCOD.Decision_BDD.Reachable_Outcomes; - ---------------------------- - -- Check_SCOs_Consistency -- - ---------------------------- + function Decision_Static_Eval + (Vectors : Source_Coverage_Vectors; + SCO_Dec : SCO_Id; + Eval : out Static_Decision_Evaluation) return Boolean; - function Check_SCOs_Consistency - (CLS : in out Checkpoint_Load_State; - CP_Vectors : Source_Coverage_Vectors; - CP_CU : in out CU_Info) return Boolean is - begin - for SCO_Range of CP_CU.SCOs loop - for Old_SCO_Id in SCO_Range.First .. SCO_Range.Last loop - declare - New_SCOD : constant SCO_Descriptor := - CP_Vectors.SCO_Vector.Element (Old_SCO_Id); - Kind : Any_SCO_Kind renames New_SCOD.Kind; + procedure Register_Static_Evaluation + (SCO : SCO_Id; Eval : Static_Decision_Evaluation); - Sloc_Range : Source_Location_Range := - Sloc_Range_For_SCO (New_SCOD); + -------------------------- + -- Decision_Static_Eval -- + -------------------------- - Real_SCO : SCO_Id := No_SCO_Id; - -- Value of the SCO if it already exists, otherwise left to - -- No_SCO_Id. + function Decision_Static_Eval + (Vectors : Source_Coverage_Vectors; + SCO_Dec : SCO_Id; + Eval : out Static_Decision_Evaluation) return Boolean + is + SCOD : SCO_Descriptor renames Vectors.SCO_Vector (SCO_Dec); - begin - -- Remap SFIs in all source locations + Reachable : constant Reachability := + SCOD.Decision_BDD.Reachable_Outcomes; - Remap_SFI (CLS.Relocations, Sloc_Range.Source_File); + Outcome : constant Tristate := + (if Reachable (False) /= Reachable (True) + then To_Tristate (Reachable (True)) + else Unknown); - -- Only consider statement / decision / condition coverage - -- obligations as other SCO kinds are not considered by - -- Sloc_To_SCO and this is a good enough condition to ensure - -- SCOs consistency. + E : Static_Decision_Evaluation; + begin - if Kind not in Statement .. Condition then - goto Continue; - end if; + -- Do not process evaluations if the decision is not at least + -- partially static. - -- Try to find if the SCO already exists, or if there is an - -- existing SCO at the same location but not with the same - -- source range. + if Outcome = Unknown then + return False; + end if; - -- First, try to find if we have a SCO of the exact same kind - -- and range. + E.Outcome := To_Boolean (Outcome); + for J in Condition_Index'First .. SCOD.Last_Cond_Index + loop declare - use Sloc_To_SCO_Maps; - Cur : constant Cursor := - Sloc_To_SCO_Map - (Sloc_Range.Source_File, Kind).Find (Sloc_Range.L); + SCO_C : constant SCO_Id := + Condition (Vectors, SCO_Dec, J); + SCOD_C : SCO_Descriptor renames + Vectors.SCO_Vector (SCO_C); begin - if Has_Element (Cur) - and then SCO_Vector.Element (Element (Cur)).Kind = Kind - then - goto Continue; + + -- If an encountered Condition has no Value, then the + -- Decision is not fully static, abort processing + + if SCOD_C.Value = Unknown then + E.Values.Clear; + return False; end if; + + E.Values.Append (To_Boolean (SCOD_C.Value)); end; + end loop; - -- If we did not find a SCO with the exact same range, check - -- whether there is an overlapping SCO. + Eval := E; + return True; + end Decision_Static_Eval; - Real_SCO := - Sloc_To_SCO - (Slocs.Source_Location' - (Source_File => Sloc_Range.Source_File, - L => New_SCOD.Sloc_Range.L.First_Sloc), - Include_Decisions => True); + -------------------------------- + -- Register_Static_Evaluation -- + -------------------------------- - if Real_SCO /= No_SCO_Id then - return False; - end if; - end; - <> - end loop; - end loop; - return True; - end Check_SCOs_Consistency; + procedure Register_Static_Evaluation + (SCO : SCO_Id; Eval : Static_Decision_Evaluation) is + begin + if not CLS.Static_Decision_Evaluations.Contains (SCO) + then + CLS.Static_Decision_Evaluations.Insert + (SCO, + Static_Decision_Evaluation_Sets.Empty_Set); + end if; + CLS.Static_Decision_Evaluations + .Reference (SCO) + .Include (Eval); + end Register_Static_Evaluation; - -------------------------- - -- Checkpoint_Load_SCOs -- - -------------------------- + -- Start processing of Merge_Decision_SCOs - procedure Checkpoint_Load_SCOs - (CLS : in out Checkpoint_Load_State; - CP_Vectors : Source_Coverage_Vectors; - CP_CU : in out CU_Info; - Real_CU : in out CU_Info; - Real_CU_Id : CU_Id) - is - Relocs : Checkpoint_Relocations renames CLS.Relocations; - - Cur_Source_File : Source_File_Index := No_Source_File; - Last_Line : Natural := 0; + begin + if Old_SCOD.Decision_Instrumented then + New_SCOD.Decision_Instrumented := True; + end if; + if Old_SCOD.Decision_Instrumented_For_MCDC then + New_SCOD.Decision_Instrumented_For_MCDC := True; + end if; - New_First_SCO : constant SCO_Id := SCO_Vector.Last_Index + 1; - begin - -- When loading a SCO, we check if it already exists: - -- * If it is the case, merge it and adequately set the bit map - -- relocation to the existing SCO. - -- * Otherwise, create it. - -- - -- The heuristic to consider that a SCO already exists or not is to - -- check for a SCO with the exact same source location. + -- The following code handles merging Decision SCOs that have a + -- different staticness over the 2 checkpoints that are being merged. + -- + -- If the reachability of the decision in one of the checkpoints + -- differs from `Both_Reachable`, it means that at least one of the + -- two checkpoints has some static conditions and should be handled + -- with a specific treatment. + -- + -- Upon encountering a fully-static decision, we need to register its + -- conditions' values so they can be used as a complementary + -- evaluation for MC/DC analysis. - for SCO_Range of CP_CU.SCOs loop - for Old_SCO_Id in SCO_Range.First .. SCO_Range.Last loop + if Old_Reachable /= Both_Reachable + or else + New_Reachable /= Both_Reachable + then + SCOs_Trace.Trace ("Consolidation encountered a decision SCO" + & " whose staticness may differ at" + & Image (New_SCOD.Sloc_Range)); declare - New_SCOD : SCO_Descriptor := - CP_Vectors.SCO_Vector.Element (Old_SCO_Id); - Sloc_Range : Source_Location_Range := - Sloc_Range_For_SCO (New_SCOD); - Real_SCO : SCO_Id := No_SCO_Id; - -- Value of the SCO if it already exists, otherwise left to - -- No_SCO_Id. - - begin - if New_SCOD.Kind = Removed then - Ignore_SCO (Relocs, Old_SCO_Id); - goto Next_SCO; - end if; - - -- Remap SFIs in all source locations - - Remap_SFI (Relocs, Sloc_Range.Source_File); - - -- Try to find if the SCO already exists - - declare - use Sloc_To_SCO_Maps; - Cur : constant Cursor := - Sloc_To_SCO_Map - (Sloc_Range.Source_File, - New_SCOD.Kind).Find (Sloc_Range.L); - begin - if Has_Element (Cur) then - Real_SCO := Element (Cur); - end if; - end; + Old_Eval : Static_Decision_Evaluation; + -- Holds the result of the static evaluation of Old_SCO + -- if Old_Static is True. Otherwise, it is invalid. - -- If the SCO already exists, only add an entry to remap the - -- Old_SCO_Id to the actual SCO. + New_Eval : Static_Decision_Evaluation; + -- Holds the result of the static evaluation of New_SCO + -- if New_Static is True. Otherwise, it is invalid. - if Real_SCO /= No_SCO_Id then - Set_SCO_Id_Map (Relocs, Old_SCO_Id, Real_SCO); - goto Next_SCO; - end if; + Old_Static : constant Boolean := + Decision_Static_Eval (CP_Vectors, Old_SCO_Id, Old_Eval); + New_Static : constant Boolean := + Decision_Static_Eval (SC_Vectors, New_SCO_Id, New_Eval); - -- At this point, if Real_SCO is No_SCO_Id, this is a new SCO: - -- it cannot overlap with an existing SCO as this was checked - -- by Check_SCOs_Consistency. + begin - if Real_SCO = No_SCO_Id then - Set_SCO_Id_Map - (Relocs, Old_SCO_Id, SCO_Vector.Last_Index + 1); + -- No matter the staticness of the SCOs, we update the + -- reachability of each outcome by OR-ing the two checkpoints. - -- Append new SCOD and record mapping + New_Reachable (True) := New_Reachable (True) or else + Old_Reachable (True); - Remap_SCO_Descriptor (CP_Vectors, Relocs, New_SCOD); + New_Reachable (False) := New_Reachable (False) or else + Old_Reachable (False); - -- Preallocate line table entries for previous unit + if Old_Static then - if New_SCOD.Sloc_Range.Source_File /= Cur_Source_File then - Prealloc_Lines (Cur_Source_File, Last_Line); - Cur_Source_File := New_SCOD.Sloc_Range.Source_File; - CU_Map.Include (Cur_Source_File, Real_CU_Id); - end if; - if New_SCOD.Kind in - Statement | Decision | Fun_Call_SCO_Kind | Guarded_Expr - then - Add_SCO_To_Lines (SCO_Vector.Last_Index + 1, New_SCOD); - end if; + -- If the decision in the Old checkpoint is static, + -- add an evaluation to the SCIs corresponding to it. - Last_Line := Natural'Max - (Files_Table.Last_Line (Get_File (Cur_Source_File)), - New_SCOD.Sloc_Range.L.Last_Sloc.Line); - SCO_Vector.Append (New_SCOD); + Register_Static_Evaluation (New_SCO_Id, Old_Eval); + end if; - -- Add it into the Sloc_To_SCO_Map + if New_Static then - declare - Map : constant access Sloc_To_SCO_Maps.Map := - Writeable_Sloc_To_SCO_Map - (Sloc_Range.Source_File, New_SCOD.Kind); - begin - Map.Insert (Sloc_Range.L, SCO_Vector.Last_Index); - end; + -- If the decision in the New checkpoint is static, + -- add an evaluation to the SCIs corresponding to it. - if SCOs_Trace.Is_Active then - SCOs_Trace.Trace - ("Loaded from checkpoint: " - & Image (SCO_Vector.Last_Index) - & " (was #" - & Trim (Old_SCO_Id'Img, Side => Ada.Strings.Both) - & " in checkpoint)"); - end if; + Register_Static_Evaluation (New_SCO_Id, New_Eval); end if; end; - <> - end loop; - end loop; - - -- Add the newly created SCOs to Real_CU.SCOs - - if SCO_Vector.Last_Index >= New_First_SCO then - Real_CU.SCOs.Append - (SCO_Range'(First => New_First_SCO, Last => SCO_Vector.Last_Index)); - end if; - end Checkpoint_Load_SCOs; + end if; + end Merge_Decision_SCOs; - ------------------------------ - -- Checkpoint_Load_SID_Info -- - ------------------------------ + -- Start processing of Checkpoint_Load_Merge_Unit - procedure Checkpoint_Load_SID_Info - (CLS : in out Checkpoint_Load_State; - CP_CU : in out CU_Info; - Real_CU : in out CU_Info) - is - Relocs : Checkpoint_Relocations renames CLS.Relocations; begin - for Cur in CP_CU.SIDs_Info.Iterate loop - declare - SID_Fingerprint : constant Fingerprint_Type := - SID_Info_Maps.Key (Cur); - SID_Version : SID_Info := SID_Info_Maps.Element (Cur); - begin - if not Real_CU.SIDs_Info.Contains (SID_Fingerprint) then + -- Here we already have loaded full SCO information for this CU. There + -- are two things to do: + -- + -- * Populate the tables mapping the SCO for this unit in the checkpoint + -- to their counterparts in the current context, and merge + -- non-instrumented SCO information if available. + -- + -- * Merge the annotations + -- + -- * Merge the information about non instrumented SCOs. We consider that + -- a SCO was instrumented iff at least one merged unit has it + -- instrumented. - -- Remap bit map buffers + -- SCOs - if SID_Version.Bit_Maps.Statement_Bits /= null then - for S_SCO of SID_Version.Bit_Maps.Statement_Bits.all loop - Remap_SCO_Id (Relocs, S_SCO); - end loop; - end if; + pragma Assert (CP_CU.Last_SCO - CP_CU.First_SCO + = + Real_CU.Last_SCO - Real_CU.First_SCO); - if SID_Version.Bit_Maps.Decision_Bits /= null then - for D_Outcome of SID_Version.Bit_Maps.Decision_Bits.all - loop - Remap_SCO_Id (Relocs, D_Outcome.D_SCO); - end loop; - end if; + for Old_SCO_Id in CP_CU.First_SCO .. CP_CU.Last_SCO loop + Set_SCO_Id_Map (Relocs, Old_SCO_Id, + Old_SCO_Id + + Real_CU.First_SCO + - CP_CU.First_SCO); - if SID_Version.Bit_Maps.MCDC_Bits /= null then - for D_Path of SID_Version.Bit_Maps.MCDC_Bits.all loop - Remap_SCO_Id (Relocs, D_Path.D_SCO); - end loop; - end if; + declare - -- Remap blocks information + Old_SCOD : SCO_Descriptor renames + CP_Vectors.SCO_Vector (Old_SCO_Id); + New_SCO_Id : constant SCO_Id := Remap_SCO_Id (Relocs, Old_SCO_Id); + SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); - for Block_Cur in SID_Version.Blocks.Iterate loop - declare - Block_Ref : constant - SCO_Id_Vector_Vectors.Reference_Type := - SID_Version.Blocks.Reference (Block_Cur); - begin - for SCO_Cur in Block_Ref.Iterate loop - Remap_SCO_Id (Relocs, Block_Ref.Reference (SCO_Cur)); - end loop; - end; - end loop; + begin + case SCOD.Kind is + when Statement => + if Old_SCOD.Stmt_Instrumented then + SCOD.Stmt_Instrumented := True; + end if; - Real_CU.SIDs_Info.Insert (SID_Fingerprint, SID_Version); - end if; - end; - end loop; - end Checkpoint_Load_SID_Info; + when Decision => + Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id); - ----------------------------- - -- Checkpoint_Load_PP_Info -- - ----------------------------- + when Fun_Call_SCO_Kind => + if Old_SCOD.Fun_Call_Instrumented then + SCOD.Fun_Call_Instrumented := True; + end if; - procedure Checkpoint_Load_PP_Info - (CLS : in out Checkpoint_Load_State; - CP_CU : in out CU_Info; - Real_CU : in out CU_Info) - is - use SCO_PP_Info_Maps; - Relocs : Checkpoint_Relocations renames CLS.Relocations; - begin - for Cur in CP_CU.PP_Info_Map.Iterate loop - declare - SCO : SCO_Id := Key (Cur); - Info : PP_Info := Element (Cur); - begin - if not Real_CU.PP_Info_Map.Contains (SCO) then - if Info.Kind = In_Expansion then - for Expansion of Info.Expansion_Stack loop - Remap_SFI - (Relocs, - Expansion.Sloc.Source_File); - end loop; - Remap_SFI - (Relocs, - Info.Definition_Loc.Sloc.Source_File); - end if; - Remap_SCO_Id (Relocs, SCO); - Real_CU.PP_Info_Map.Insert (SCO, Info); - end if; + when Guarded_Expr => + if Old_SCOD.GExpr_Instrumented then + SCOD.GExpr_Instrumented := True; + end if; + + when others => + null; + end case; end; end loop; - end Checkpoint_Load_PP_Info; - ---------------------------- - -- Checkpoint_Load_Scopes -- - ---------------------------- + -- Has_Code indication - procedure Checkpoint_Load_Scopes - (CLS : in out Checkpoint_Load_State; - CP_CU : in out CU_Info; - Real_CU : in out CU_Info) - is - Relocs : Checkpoint_Relocations renames CLS.Relocations; - begin - -- For scope entities, only add those that do not violate the - -- nesting and ordering of the structure + Real_CU.Has_Code := Real_CU.Has_Code or CP_CU.Has_Code; - for Scope_Ent of CP_CU.Scope_Entities loop + -- Remap ALI annotations and then merge them - -- Scopes whose identifier references ignored source files will - -- lose their identifier: such scopes will remain, but users - -- will not be able to mark them of interest. + declare + Remapped_Annotations : ALI_Annotation_Maps.Map := + CP_CU.ALI_Annotations; + begin + Remap_ALI_Annotations (Relocs, Remapped_Annotations); + for Cur in Remapped_Annotations.Iterate loop + Real_CU.ALI_Annotations.Include + (ALI_Annotation_Maps.Key (Cur), + ALI_Annotation_Maps.Element (Cur)); + end loop; + end; + end Checkpoint_Load_Merge_Unit; - if SFI_Ignored (Relocs, Scope_Ent.Identifier.Decl_SFI) then - Scope_Ent.Identifier := No_Scope_Entity_Identifier; - else - Remap_SFI (Relocs, Scope_Ent.Identifier.Decl_SFI); - end if; + function "<" (L, R : Static_Decision_Evaluation) return Boolean is + begin + if L.Outcome /= R.Outcome then + return L.Outcome < R.Outcome; + end if; - Remap_SFI (Relocs, Scope_Ent.Source_Range.Source_File); + for J in R.Values.First_Index .. R.Values.Last_Index loop + if J > L.Values.Last_Index then + return True; - declare - use Scope_Entities_Trees; + elsif L.Values.Element (J) < R.Values.Element (J) then + return True; - Real_Scope : constant Cursor := - Floor - (Real_CU.Scope_Entities, - Source_Location' - (Source_File => Scope_Ent.Source_Range.Source_File, - L => Scope_Ent.Source_Range.L.First_Sloc)); + elsif L.Values.Element (J) > R.Values.Element (J) then + return False; + end if; + end loop; - Added_Scope : Boolean := False; - -- Whether the current Scope_Ent was added to the list of scopes - -- (it is a new scope that does not clash with existing scopes). + return False; + end "<"; - begin - if not Scope_Entities_Trees.Has_Element (Real_Scope) then + ------------------------------ + -- Checkpoint_Load_New_Unit -- + ------------------------------ - -- This is a new scope that do not nest with an existing - -- scope (basically the case of a new compilation unit). + procedure Checkpoint_Load_New_Unit + (CLS : in out Checkpoint_Load_State; + CP_Vectors : Source_Coverage_Vectors; + CP_CU : in out CU_Info; + New_CU_Id : out CU_Id) + is + Relocs : Checkpoint_Relocations renames CLS.Relocations; - Real_CU.Scope_Entities.Insert_Child - (Parent => Real_CU.Scope_Entities.Root, - Before => No_Element, - New_Item => Scope_Ent); - Added_Scope := True; - else - declare - Found_Scope_Ent : constant Scope_Entity := - Real_CU.Scope_Entities.Reference (Real_Scope); - Child : Cursor := - First_Child (Real_Scope); - Src_Range : constant Source_Location_Range := - Found_Scope_Ent.Source_Range; - begin + New_First_SCO : SCO_Id; - if Scope_Ent.Source_Range = Src_Range then + Cur_Source_File : Source_File_Index := No_Source_File; + Last_Line : Natural := 0; - -- The scope already exists: do nothing + procedure Remap_BDD (Decision_BDD : in out BDD.BDD_Type); + -- Remap a sequence of BDD nodes, for a whole decision BDD - null; + procedure Remap_BDD_Node (B : in out BDD_Node_Id); + -- Remap a BDD node id - elsif Src_Range.L.First_Sloc < - Scope_Ent.Source_Range.L.First_Sloc - and then - Scope_Ent.Source_Range.L.Last_Sloc < - Src_Range.L.Last_Sloc - then - -- Check if it nests with the innermost scope entity. If - -- this is the case, insert it as a child. + procedure Remap_SCO_Id (S : in out SCO_Id); + -- Remap a SCO_Id. Note: this assumes possible forward references, and + -- does not rely on SCO_Map. - while Has_Element (Child) - and then Element (Child).Source_Range.L.First_Sloc - < Scope_Ent.Source_Range.L.First_Sloc - loop - Child := Next_Sibling (Child); - end loop; - Added_Scope := True; + --------------- + -- Remap_BDD -- + --------------- - if not Has_Element (Child) then + procedure Remap_BDD (Decision_BDD : in out BDD.BDD_Type) is + CP_First : constant BDD_Node_Id := Decision_BDD.First_Node; + CP_Last : constant BDD_Node_Id := Decision_BDD.Last_Node; + New_First : constant BDD_Node_Id := BDD_Vector.Last_Index + 1; + begin + -- Import the relevant BDD nodes from CP_Vectors.BDD_Vector - -- Insert it as the last children + for Old_BDD_Node_Id in CP_First .. CP_Last loop + declare + -- We are supposed to remap individual BDD nodes only once - Real_CU.Scope_Entities.Insert_Child - (Parent => Real_Scope, - Before => No_Element, - New_Item => Scope_Ent); + New_BDD_Node : BDD.BDD_Node := + CP_Vectors.BDD_Vector.Element (Old_BDD_Node_Id); - else - -- Insert it before the identified child + procedure Remap_BDD_Node_Id (S : in out BDD_Node_Id); + -- Remap a BDD node id - Real_CU.Scope_Entities.Insert_Child - (Parent => Real_Scope, - Before => Child, - New_Item => Scope_Ent); + ----------------------- + -- Remap_BDD_Node_Id -- + ----------------------- - end if; - else - -- Discard overlapping cases - - Outputs.Fatal_Error - ("Scope " - & (+Scope_Ent.Name) - & " at source location: " - & Image (Scope_Ent.Source_Range) - & " clashes with scope " - & (+Found_Scope_Ent.Name) - & " at location: " - & Image (Found_Scope_Ent.Source_Range)); + procedure Remap_BDD_Node_Id (S : in out BDD_Node_Id) is + begin + if S /= No_BDD_Node_Id then + S := S - CP_First + New_First; end if; - end; - end if; - - -- Register each scope identifiers to make them available to - -- users on the command line. - - if Added_Scope then - Available_Subps_Of_Interest.Include (Scope_Ent.Identifier); - end if; - end; - end loop; - pragma Assert (SCOs_Nested_And_Ordered (Real_CU.Scope_Entities)); - end Checkpoint_Load_Scopes; + end Remap_BDD_Node_Id; - --------------- - -- Remap_BDD -- - --------------- - - procedure Remap_BDD - (CP_Vectors : Source_Coverage_Vectors; - Relocs : in out Checkpoint_Relocations; - Decision_BDD : in out BDD.BDD_Type) - is - CP_First : constant BDD_Node_Id := Decision_BDD.First_Node; - CP_Last : constant BDD_Node_Id := Decision_BDD.Last_Node; - New_First : constant BDD_Node_Id := BDD_Vector.Last_Index + 1; - begin - -- Import the relevant BDD nodes from CP_Vectors.BDD_Vector - - for Old_BDD_Node_Id in CP_First .. CP_Last loop - declare - -- We are supposed to remap individual BDD nodes only once - - New_BDD_Node : BDD.BDD_Node := - CP_Vectors.BDD_Vector.Element (Old_BDD_Node_Id); - - procedure Remap_BDD_Node_Id (S : in out BDD_Node_Id); - -- Remap a BDD node id - - ----------------------- - -- Remap_BDD_Node_Id -- - ----------------------- - - procedure Remap_BDD_Node_Id (S : in out BDD_Node_Id) is begin - if S /= No_BDD_Node_Id then - S := S - CP_First + New_First; - end if; - end Remap_BDD_Node_Id; - - begin - case New_BDD_Node.Kind is - when BDD.Condition => - Remap_BDD_Node_Id (New_BDD_Node.Parent); - for Valuation in New_BDD_Node.Dests'Range loop - Remap_BDD_Node_Id - (New_BDD_Node.Dests (Valuation)); - end loop; + case New_BDD_Node.Kind is + when BDD.Condition => + Remap_BDD_Node_Id (New_BDD_Node.Parent); + for Valuation in New_BDD_Node.Dests'Range loop + Remap_BDD_Node_Id + (New_BDD_Node.Dests (Valuation)); + end loop; - -- Note that we leave New_BDD_Node.C_SCO unremapped here: - -- the loading of the corresponding SCO condition will - -- take care of it (see below). + -- Note that we leave New_BDD_Node.C_SCO unremapped here: + -- the loading of the corresponding SCO condition will + -- take care of it (see below). - when BDD.Jump => - Remap_BDD_Node_Id (New_BDD_Node.Dest); + when BDD.Jump => + Remap_BDD_Node_Id (New_BDD_Node.Dest); - when others => - null; - end case; + when others => + null; + end case; - BDD_Vector.Append (New_BDD_Node); - Set_BDD_Node_Id_Map - (Relocs, Old_BDD_Node_Id, BDD_Vector.Last_Index); - end; - end loop; + BDD_Vector.Append (New_BDD_Node); + Set_BDD_Node_Id_Map + (Relocs, Old_BDD_Node_Id, BDD_Vector.Last_Index); + end; + end loop; - -- Remap IDs in Decision_BDD + -- Remap IDs in Decision_BDD - Remap_SCO_Id (Relocs, Decision_BDD.Decision); + Remap_SCO_Id (Decision_BDD.Decision); - Remap_BDD_Node (Relocs, Decision_BDD.Root_Condition); - Remap_BDD_Node (Relocs, Decision_BDD.First_Node); - Remap_BDD_Node (Relocs, Decision_BDD.Last_Node); - Remap_BDD_Node (Relocs, Decision_BDD.First_Multipath_Condition); - end Remap_BDD; + Remap_BDD_Node (Decision_BDD.Root_Condition); + Remap_BDD_Node (Decision_BDD.First_Node); + Remap_BDD_Node (Decision_BDD.Last_Node); + Remap_BDD_Node (Decision_BDD.First_Multipath_Condition); + end Remap_BDD; - -------------------- - -- Remap_BDD_Node -- - -------------------- + -------------------- + -- Remap_BDD_Node -- + -------------------- - procedure Remap_BDD_Node - (Relocs : Checkpoint_Relocations; - B : in out BDD_Node_Id) is - begin - if B /= No_BDD_Node_Id then - B := Remap_BDD_Node_Id (Relocs, B); - pragma Assert (B /= No_BDD_Node_Id); - end if; - end Remap_BDD_Node; + procedure Remap_BDD_Node (B : in out BDD_Node_Id) is + begin + if B /= No_BDD_Node_Id then + B := Remap_BDD_Node_Id (Relocs, B); + pragma Assert (B /= No_BDD_Node_Id); + end if; + end Remap_BDD_Node; - ------------------ - -- Remap_SCO_Id -- - ------------------ + ------------------ + -- Remap_SCO_Id -- + ------------------ - procedure Remap_SCO_Id - (Relocs : Checkpoint_Relocations; - S : in out SCO_Id) is - begin - S := Checkpoints.Remap_SCO_Id (Relocs, S); - end Remap_SCO_Id; + procedure Remap_SCO_Id (S : in out SCO_Id) is + begin + if S /= No_SCO_Id then + S := New_First_SCO + S - CP_CU.First_SCO; + pragma Assert (S /= No_SCO_Id); + end if; + end Remap_SCO_Id; - -------------------------- - -- Remap_SCO_Descriptor -- - -------------------------- + -- Start of processing for Checkpoint_Load_New_Unit - procedure Remap_SCO_Descriptor - (CP_Vectors : Source_Coverage_Vectors; - Relocs : in out Checkpoint_Relocations; - SCOD : in out SCO_Descriptor) - is - New_First_SCO : SCO_Id := SCO_Vector.Last_Index + 1; begin - Remap_SFI (Relocs, SCOD.Sloc_Range.Source_File); + New_CU_Id := CU_Vector.Last_Index + 1; - -- If this is a decision, start by recording all of the operator - -- and condition SCOs in the relocation map, before relocating all - -- of the components of the SCO_Descriptor. + CU_Map.Insert (CP_CU.Main_Source, New_CU_Id); - case SCOD.Kind is - when Decision => - declare - Expr_SCO : SCO_Id := SCOD.Expression - 1; - Expr_SCOD : SCO_Descriptor := - CP_Vectors.SCO_Vector.Element (Expr_SCO); - begin - loop - Expr_SCO := Expr_SCO + 1; - exit when Expr_SCO > CP_Vectors.SCO_Vector.Last_Index; - Expr_SCOD := CP_Vectors.SCO_Vector.Element (Expr_SCO); - exit when Expr_SCOD.Kind not in Condition | Operator; - New_First_SCO := New_First_SCO + 1; - Set_SCO_Id_Map (Relocs, Expr_SCO, New_First_SCO); - end loop; - end; - when others => - null; - end case; - - SCOD.Origin := Remap_CU_Id (Relocs, SCOD.Origin); - - -- Remap SCO_Ids + -- Remap SCO ids. Note that BDD nodes are imported (and remapped) as + -- needed during the process. - Remap_SCO_Id (Relocs, SCOD.Parent); + New_First_SCO := SCO_Vector.Last_Index + 1; + for Old_SCO_Id in CP_CU.First_SCO .. CP_CU.Last_SCO loop + declare + New_SCOD : SCO_Descriptor := + CP_Vectors.SCO_Vector.Element (Old_SCO_Id); + begin + if New_SCOD.Kind = Removed then + Ignore_SCO (Relocs, Old_SCO_Id); + goto Next_SCO; + end if; - -- Make further adjustments based on SCO kind - -- In particular reset all components that reference - -- data that is not saved to checkpoint files (such as - -- BDD information). + New_SCOD.Origin := New_CU_Id; - case SCO_Kind (SCOD.Kind) is - when Statement => - Remap_SFI (Relocs, SCOD.Dominant_Sloc.Source_File); - Remap_SFI (Relocs, SCOD.Handler_Range.Source_File); + -- Remap SFIs in all source locations - Remap_SCO_Id (Relocs, SCOD.Dominant); + Remap_SFI (Relocs, New_SCOD.Sloc_Range.Source_File); - when Decision => - Remap_SCO_Id (Relocs, SCOD.Expression); - Remap_SFI (Relocs, SCOD.Control_Location.Source_File); - Remap_BDD (CP_Vectors, Relocs, SCOD.Decision_BDD); + -- Preallocate line table entries for previous unit - when Operator => - for Op_SCO in SCOD.Operands'Range loop - Remap_SCO_Id (Relocs, SCOD.Operands (Op_SCO)); - end loop; + if New_SCOD.Sloc_Range.Source_File /= Cur_Source_File then + Prealloc_Lines (Cur_Source_File, Last_Line); + Cur_Source_File := New_SCOD.Sloc_Range.Source_File; + CU_Map.Include (Cur_Source_File, New_CU_Id); + end if; - when Condition => - Remap_BDD_Node (Relocs, SCOD.BDD_Node); - Remap_SCO_Id - (Relocs, BDD_Vector.Reference (SCOD.BDD_Node).C_SCO); + Last_Line := Natural'Max + (Last_Line, + New_SCOD.Sloc_Range.L.Last_Sloc.Line); - SCOD.PC_Set.Clear; + -- Remap SCO_Ids - when Fun_Call_SCO_Kind | Guarded_Expr => - null; + Remap_SCO_Id (New_SCOD.Parent); - end case; - end Remap_SCO_Descriptor; + -- Make further adjustments based on SCO kind + -- In particular reset all components that reference + -- data that is not saved to checkpoint files (such as + -- BDD information). - -------------------------- - -- Checkpoint_Load_Unit -- - -------------------------- + case SCO_Kind (New_SCOD.Kind) is + when Statement => + Remap_SFI (Relocs, New_SCOD.Dominant_Sloc.Source_File); + Remap_SFI (Relocs, New_SCOD.Handler_Range.Source_File); - procedure Checkpoint_Load_Unit - (CLS : in out Checkpoint_Load_State; - CP_Vectors : Source_Coverage_Vectors; - CP_CU : in out CU_Info; - CP_CU_Id : CU_Id) - is - Relocs : Checkpoint_Relocations renames CLS.Relocations; + Remap_SCO_Id (New_SCOD.Dominant); - procedure Ignore_SCOs; - -- Mark all the SCOs in CP_CU as being ignored. This is useful when - -- skipping coverage information for a unit because the consistency - -- checks failed. + when Decision => + Remap_SCO_Id (New_SCOD.Expression); + Remap_SFI (Relocs, New_SCOD.Control_Location.Source_File); + Remap_BDD (New_SCOD.Decision_BDD); - procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) - with Pre => Kind (New_SCO_Id) = Decision; + when Operator => + for Op_SCO in New_SCOD.Operands'Range loop + Remap_SCO_Id (New_SCOD.Operands (Op_SCO)); + end loop; - ------------------------- - -- Merge_Decision_SCOs -- - ------------------------- + when Condition => + Remap_BDD_Node (New_SCOD.BDD_Node); + Remap_SCO_Id + (BDD_Vector.Reference (New_SCOD.BDD_Node).C_SCO); - procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) - is - use SC_Obligations.BDD; + New_SCOD.PC_Set.Clear; - Old_SCOD : SCO_Descriptor renames CP_Vectors.SCO_Vector (Old_SCO_Id); - New_SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); + when Fun_Call_SCO_Kind | Guarded_Expr => + null; - Old_Reachable : Reachability renames - Old_SCOD.Decision_BDD.Reachable_Outcomes; - New_Reachable : Reachability renames - New_SCOD.Decision_BDD.Reachable_Outcomes; + end case; - function Decision_Static_Eval - (Vectors : Source_Coverage_Vectors; - SCO_Dec : SCO_Id; - Eval : out Static_Decision_Evaluation) return Boolean; + -- Append new SCOD and record mapping - procedure Register_Static_Evaluation - (SCO : SCO_Id; Eval : Static_Decision_Evaluation); + SCO_Vector.Append (New_SCOD); + Set_SCO_Id_Map (Relocs, Old_SCO_Id, SCO_Vector.Last_Index); + if SCOs_Trace.Is_Active then + SCOs_Trace.Trace + ("Loaded from checkpoint: " + & Image (SCO_Vector.Last_Index) + & " (was #" & Trim (Old_SCO_Id'Img, Side => Ada.Strings.Both) + & " in checkpoint)"); + end if; + end; - -------------------------- - -- Decision_Static_Eval -- - -------------------------- + <> null; + end loop; - function Decision_Static_Eval - (Vectors : Source_Coverage_Vectors; - SCO_Dec : SCO_Id; - Eval : out Static_Decision_Evaluation) return Boolean - is - SCOD : SCO_Descriptor renames Vectors.SCO_Vector (SCO_Dec); + -- Remap SCO_Ids in source trace bit maps - Reachable : constant Reachability := - SCOD.Decision_BDD.Reachable_Outcomes; + if CP_CU.Provider = Instrumenter then + if CP_CU.Bit_Maps.Statement_Bits /= null then + for S_SCO of CP_CU.Bit_Maps.Statement_Bits.all loop + Remap_SCO_Id (S_SCO); + end loop; + end if; - Outcome : constant Tristate := - (if Reachable (False) /= Reachable (True) - then To_Tristate (Reachable (True)) - else Unknown); + if CP_CU.Bit_Maps.Decision_Bits /= null then + for D_Outcome of CP_CU.Bit_Maps.Decision_Bits.all loop + Remap_SCO_Id (D_Outcome.D_SCO); + end loop; + end if; - E : Static_Decision_Evaluation; - begin + if CP_CU.Bit_Maps.MCDC_Bits /= null then + for D_Path of CP_CU.Bit_Maps.MCDC_Bits.all loop + Remap_SCO_Id (D_Path.D_SCO); + end loop; + end if; - -- Do not process evaluations if the decision is not at least - -- partially static. + -- Remap blocks information - if Outcome = Unknown then - return False; - end if; + for Block_Cur in CP_CU.Blocks.Iterate loop + declare + Block_Ref : constant SCO_Id_Vector_Vectors.Reference_Type := + CP_CU.Blocks.Reference (Block_Cur); + begin + for SCO_Cur in Block_Ref.Iterate loop + Remap_SCO_Id (Block_Ref.Reference (SCO_Cur)); + end loop; + end; + end loop; - E.Outcome := To_Boolean (Outcome); + -- Remap macro information - for J in Condition_Index'First .. SCOD.Last_Cond_Index - loop + declare + use SCO_PP_Info_Maps; + Remapped_PP_Info_Map : SCO_PP_Info_Maps.Map; + begin + for Cur in CP_CU.PP_Info_Map.Iterate loop declare - SCO_C : constant SCO_Id := - Condition (Vectors, SCO_Dec, J); - SCOD_C : SCO_Descriptor renames - Vectors.SCO_Vector (SCO_C); + Info : PP_Info := Element (Cur); begin - - -- If an encountered Condition has no Value, then the - -- Decision is not fully static, abort processing - - if SCOD_C.Value = Unknown then - E.Values.Clear; - return False; + if Info.Kind = In_Expansion then + for Expansion of Info.Expansion_Stack loop + Remap_SFI + (Relocs, + Expansion.Sloc.Source_File); + end loop; + Remap_SFI + (Relocs, + Info.Definition_Loc.Sloc.Source_File); end if; - - E.Values.Append (To_Boolean (SCOD_C.Value)); + declare + SCO : SCO_Id := Key (Cur); + begin + Remap_SCO_Id (SCO); + Remapped_PP_Info_Map.Insert (SCO, Info); + end; end; - end loop; - - Eval := E; - return True; - end Decision_Static_Eval; - - -------------------------------- - -- Register_Static_Evaluation -- - -------------------------------- - - procedure Register_Static_Evaluation - (SCO : SCO_Id; Eval : Static_Decision_Evaluation) is - begin - if not CLS.Static_Decision_Evaluations.Contains (SCO) - then - CLS.Static_Decision_Evaluations.Insert - (SCO, - Static_Decision_Evaluation_Sets.Empty_Set); - end if; - CLS.Static_Decision_Evaluations - .Reference (SCO) - .Include (Eval); - end Register_Static_Evaluation; - - -- Start processing of Merge_Decision_SCOs - - begin - if Old_SCOD.Decision_Instrumented then - New_SCOD.Decision_Instrumented := True; - end if; - if Old_SCOD.Decision_Instrumented_For_MCDC then - New_SCOD.Decision_Instrumented_For_MCDC := True; - end if; - - -- The following code handles merging Decision SCOs that have a - -- different staticness over the 2 checkpoints that are being merged. - -- - -- If the reachability of the decision in one of the checkpoints - -- differs from `Both_Reachable`, it means that at least one of the - -- two checkpoints has some static conditions and should be handled - -- with a specific treatment. - -- - -- Upon encountering a fully-static decision, we need to register its - -- conditions' values so they can be used as a complementary - -- evaluation for MC/DC analysis. - - if Old_Reachable /= Both_Reachable - or else - New_Reachable /= Both_Reachable - then - SCOs_Trace.Trace ("Consolidation encountered a decision SCO" - & " whose staticness may differ at" - & Image (New_SCOD.Sloc_Range)); - declare - Old_Eval : Static_Decision_Evaluation; - -- Holds the result of the static evaluation of Old_SCO - -- if Old_Static is True. Otherwise, it is invalid. + end loop; + CP_CU.PP_Info_Map := Remapped_PP_Info_Map; + end; - New_Eval : Static_Decision_Evaluation; - -- Holds the result of the static evaluation of New_SCO - -- if New_Static is True. Otherwise, it is invalid. + -- Remap SCOs span for scope entities - Old_Static : constant Boolean := - Decision_Static_Eval (CP_Vectors, Old_SCO_Id, Old_Eval); - New_Static : constant Boolean := - Decision_Static_Eval (SC_Vectors, New_SCO_Id, New_Eval); + for Scope_Ent of CP_CU.Scope_Entities loop + Remap_SCO_Id (Scope_Ent.From); + Remap_SCO_Id (Scope_Ent.To); - begin + -- Scopes whose identifier references ignored source files will + -- lose their identifier: such scopes will remain, but users will + -- not be able to mark them of interest. - -- No matter the staticness of the SCOs, we update the - -- reachability of each outcome by OR-ing the two checkpoints. + if SFI_Ignored (Relocs, Scope_Ent.Identifier.Decl_SFI) then + Scope_Ent.Identifier := No_Scope_Entity_Identifier; + else + Remap_SFI (Relocs, Scope_Ent.Identifier.Decl_SFI); + end if; - New_Reachable (True) := New_Reachable (True) or else - Old_Reachable (True); + -- Register each scope identifiers to make them available to users + -- on the command line. - New_Reachable (False) := New_Reachable (False) or else - Old_Reachable (False); + Available_Subps_Of_Interest.Include (Scope_Ent.Identifier); + end loop; + if not SCOs_Nested_And_Ordered (CP_CU.Scope_Entities) then + raise Program_Error + with "Error when loading scopes from checkpoints"; + end if; + end if; - if Old_Static then + -- Remap ALI annotations - -- If the decision in the Old checkpoint is static, - -- add an evaluation to the SCIs corresponding to it. + Remap_ALI_Annotations (Relocs, CP_CU.ALI_Annotations); - Register_Static_Evaluation (New_SCO_Id, Old_Eval); - end if; + -- Preallocate line table entries for last file - if New_Static then + Prealloc_Lines (Cur_Source_File, Last_Line); - -- If the decision in the New checkpoint is static, - -- add an evaluation to the SCIs corresponding to it. + -- Link new SCOs to source line tables - Register_Static_Evaluation (New_SCO_Id, New_Eval); - end if; - end; - end if; - end Merge_Decision_SCOs; + for SCO in New_First_SCO .. SCO_Vector.Last_Index loop + declare + SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); + begin + if SCOD.Kind in + Statement | Decision | Fun_Call_SCO_Kind | Guarded_Expr + then + Add_SCO_To_Lines (SCO, SCOD); + end if; + end; + end loop; - ----------------- - -- Ignore_SCOs -- - ----------------- + -- Perform final fixups and insert CU - procedure Ignore_SCOs is - begin - for SCO_Range of CP_CU.SCOs loop - for SCO in SCO_Range.First .. SCO_Range.Last loop - Ignore_SCO (Relocs, SCO); - end loop; - end loop; - end Ignore_SCOs; + CP_CU.Last_SCO := + New_First_SCO + + CP_CU.Last_SCO + - CP_CU.First_SCO; + CP_CU.First_SCO := New_First_SCO; + + CU_Vector.Append (CP_CU); + Register_CU (New_CU_Id); + + -- If we are loading a SID file, create source coverage data structures. + -- There is no need to do it when loading a checkpoint: that checkpoint + -- was created loading a SID file, and thus already has the + -- corresponding SCI tables populated. + + if CLS.Purpose = Instrumentation then + Coverage.Source.Initialize_SCI_For_Instrumented_CU (New_CU_Id); + end if; + end Checkpoint_Load_New_Unit; + + -------------------------- + -- Checkpoint_Load_Unit -- + -------------------------- - Actual_CU_Id : CU_Id; + procedure Checkpoint_Load_Unit + (CLS : in out Checkpoint_Load_State; + CP_Vectors : Source_Coverage_Vectors; + CP_CU : in out CU_Info; + New_CU_Id : out CU_Id) + is + Relocs : Checkpoint_Relocations renames CLS.Relocations; begin if CP_CU.Provider = Instrumenter then Instrumented_Units_Present := True; @@ -2350,11 +1938,11 @@ package body SC_Obligations is Remap_SFI (Relocs, CP_CU.Main_Source); for Dep_SFI of CP_CU.Deps loop - -- Units of interest can depend on units outside of the scope of - -- code coverage analysis. Keeping track of these introduces clashes - -- between stubbed units and the real one, so they are excluded from - -- checkpoints. Hence, allow them to be missing here. - + -- Units of interest can depend on units outside of the + -- scope of code coverage analysis. Keeping track of these + -- introduces clashes between stubbed units and the real + -- one, so they are excluded from checkpoints. Hence, allow + -- them to be missing here. if not SFI_Ignored (Relocs, Dep_SFI) then Remap_SFI (Relocs, Dep_SFI); end if; @@ -2362,19 +1950,30 @@ package body SC_Obligations is -- Next check whether this unit is already known - Actual_CU_Id := Comp_Unit (CP_CU.Main_Source); + New_CU_Id := Comp_Unit (CP_CU.Main_Source); SCOs_Trace.Trace - ("Remapped CU: id " & Actual_CU_Id'Img + ("Remapped CU: id " & New_CU_Id'Img & ", main source" & CP_CU.Main_Source'Img & " " & Get_Full_Name (CP_CU.Main_Source, Or_Simple => True)); - -- If the CU was already loaded, perform consistency checks prior to - -- loading it. + -- Case 1: CU not already present. Load all SCO information + -- from checkpoint. - if Actual_CU_Id /= No_CU_Id then + if New_CU_Id = No_CU_Id then + Checkpoint_Load_New_Unit + (CLS, + CP_Vectors, + CP_CU, + New_CU_Id => New_CU_Id); + + -- Case 2: CU already loaded from LI info. Perform consistency checks, + -- skipping the checkpointed unit altogether and emitting a warning if + -- there is a mismatch. Record mapping of checkpoint SCOs otherwise. + + else declare - CU_Record : CU_Info renames CU_Vector.Reference (Actual_CU_Id); + CU_Record : CU_Info renames CU_Vector.Reference (New_CU_Id); function Provider_Image (Provider : SCO_Provider) return String is (case Provider is @@ -2389,8 +1988,6 @@ package body SC_Obligations is -- Helper to refer to the compilation unit in an error message begin - Set_CU_Id_Map (Relocs, CP_CU_Id, Actual_CU_Id); - -- Ignore CU when the provenance of SCOs is inconsistent if CP_CU.Provider /= CU_Record.Provider then @@ -2398,217 +1995,40 @@ package body SC_Obligations is Warn ("SCOs for this unit come from both " & Provider_Image (CP_CU.Provider) & " and from " & Provider_Image (CU_Record.Provider)); - Ignore_SCOs; - return; - -- Ignore also when the fingerprints do not match + -- Ignore also when the fingerprints do not match. + -- + -- Note that only recent enough SID files contain buffer bit maps + -- and their fingerprints. Bit_Maps_Fingerprint is left to + -- No_Fingerprint for checkpoints. Skip the consistency check for + -- these cases, and if the loaded CU has these fingerprints, + -- record them for later consistency checks. - elsif (CP_CU.Provider = Compiler - and then CP_CU.SCOs_Fingerprint - /= CU_Record.SCOs_Fingerprint) + elsif CP_CU.Fingerprint /= CU_Record.Fingerprint or else (CP_CU.Provider = Instrumenter - and then CP_CU.Source_Fingerprint - /= CU_Record.Source_Fingerprint) + and then CP_CU.Bit_Maps_Fingerprint /= No_Fingerprint + and then CU_Record.Bit_Maps_Fingerprint /= No_Fingerprint + and then CP_CU.Bit_Maps_Fingerprint + /= CU_Record.Bit_Maps_Fingerprint) then Warn ("unexpected fingerprint, cannot merge coverage" & " information for " & CU_Image); - Ignore_SCOs; - return; - end if; - end; - end if; - - -- Load the checkpointed information - - declare - Relocs : Checkpoint_Relocations renames CLS.Relocations; - - Is_New_CU : constant Boolean := - not CU_Map.Contains (CP_CU.Main_Source); - -- Whether this is a new compilation unit - - Has_New_SCOs : Boolean; - -- Whether the loaded checkpoint contains additional SCOs for the CU. - -- In this case, load SCOs and scopes from the loaded checkpoint. - - Real_CU_Id : constant CU_Id := - (if Is_New_CU - then CU_Vector.Last_Index + 1 - else CU_Map.Element (CP_CU.Main_Source)); - - type CU_Info_Access is access all CU_Info; - Real_CU : CU_Info_Access; - -- Pointer to the update CU_Info in CU_Vector. This is a new entry - -- into CU_Vector if Is_New_CU, otherwise an existing one. - - begin - Set_CU_Id_Map (Relocs, CP_CU_Id, Real_CU_Id); - - -- If this is a new compilation unit, add a new entry into the - -- CU_Vector. - if Is_New_CU then - declare - New_CU : CU_Info (CP_CU.Provider); - begin - CU_Vector.Append (New_CU); - end; - end if; - - -- Then, retrieve the newly created (or existing) CU - - Real_CU := - CU_Info_Access (CU_Vector.Reference (Real_CU_Id).Element); - - -- Check if the unit has new SCOs - - Has_New_SCOs := Is_New_CU; - if not Is_New_CU then - for SID_Info in CP_CU.SIDs_Info.Iterate loop - if not Real_CU.SIDs_Info.Contains (SID_Info_Maps.Key (SID_Info)) + else + if CU_Record.Provider = Instrumenter + and then CU_Record.Bit_Maps_Fingerprint = No_Fingerprint then - Has_New_SCOs := True; - exit; - end if; - end loop; - end if; - - -- If this is a new CU, initialize the CU fields shared for all - -- versions. - - if Is_New_CU then - Real_CU.Origin := CP_CU.Origin; - Real_CU.Main_Source := CP_CU.Main_Source; - case Real_CU.Provider is - when Compiler | LLVM => - Real_CU.SCOs_Fingerprint := CP_CU.SCOs_Fingerprint; - when Instrumenter => - Real_CU.Source_Fingerprint := CP_CU.Source_Fingerprint; - end case; - CU_Map.Insert (CP_CU.Main_Source, Real_CU_Id); - for Dep_SFI of Real_CU.Deps loop - - -- Units of interest can depend on units outside of the - -- scope of code coverage analysis. Keeping track of these - -- introduces clashes between stubbed units and the real - -- one, so they are excluded from checkpoints. Hence, allow - -- them to be missing here. - - if not SFI_Ignored (Relocs, Dep_SFI) then - Remap_SFI (Relocs, Dep_SFI); + CU_Record.Bit_Maps_Fingerprint := CP_CU.Bit_Maps_Fingerprint; end if; - end loop; - Register_CU (Real_CU_Id); - - else - -- Otherwise, check that the SCOs in the new version are - -- consistent with those previously loaded. - - if not Check_SCOs_Consistency (CLS, CP_Vectors, CP_CU) then - Outputs.Warn - ("Discarding source coverage data for unit " - & Get_Full_Name (Real_CU.Main_Source) & " (from " - & Get_Full_Name (Real_CU.Origin) & "), loaded from " - & (+CLS.Filename)); - return; + Checkpoint_Load_Merge_Unit + (CLS, + CP_CU => CP_CU, + CP_Vectors => CP_Vectors, + Real_CU_Id => New_CU_Id); end if; - end if; - - -- In all cases, load the SCOs: if they already exist in Real_CU, - -- we will remap the SCOs in the loaded checkpoint to the already - -- existing ones. - - Checkpoint_Load_SCOs - (CLS => CLS, - CP_Vectors => CP_Vectors, - CP_CU => CP_CU, - Real_CU => Real_CU.all, - Real_CU_Id => Real_CU_Id); - - -- If this is a new unit / it contains new SCOs, load additional - -- information (SID information, preprocessing information, and - -- scopes). - - if Has_New_SCOs then - - -- Process SID information - - Checkpoint_Load_SID_Info - (CLS => CLS, - CP_CU => CP_CU, - Real_CU => Real_CU.all); - - -- Process macro information - - Checkpoint_Load_PP_Info - (CLS => CLS, - CP_CU => CP_CU, - Real_CU => Real_CU.all); - - -- Process scopes - - Checkpoint_Load_Scopes - (CLS => CLS, - CP_CU => CP_CU, - Real_CU => Real_CU.all); - end if; - - -- Read uninstrumented SCOs for stmt/decision - - for SCO_Range of CP_CU.SCOs loop - for Old_SCO_Id in SCO_Range.First .. SCO_Range.Last loop - declare - Old_SCOD : SCO_Descriptor renames - CP_Vectors.SCO_Vector (Old_SCO_Id); - New_SCO_Id : constant SCO_Id := - Remap_SCO_Id (Relocs, Old_SCO_Id); - SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); - begin - case SCOD.Kind is - when Statement => - if Old_SCOD.Stmt_Instrumented then - SCOD.Stmt_Instrumented := True; - end if; - - when Decision => - Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id); - - when Fun_Call_SCO_Kind => - if Old_SCOD.Fun_Call_Instrumented then - SCOD.Fun_Call_Instrumented := True; - end if; - - when Guarded_Expr => - if Old_SCOD.GExpr_Instrumented then - SCOD.GExpr_Instrumented := True; - end if; - - when others => - null; - end case; - end; - end loop; - end loop; - - -- Has_Code indication - - Real_CU.Has_Code := Real_CU.Has_Code or CP_CU.Has_Code; - - -- Remap ALI annotations and then merge them - - declare - Remapped_Annotations : ALI_Annotation_Maps.Map := - CP_CU.ALI_Annotations; - begin - Remap_ALI_Annotations (Relocs, Remapped_Annotations); - for Cur in Remapped_Annotations.Iterate loop - Real_CU.ALI_Annotations.Include - (ALI_Annotation_Maps.Key (Cur), - ALI_Annotation_Maps.Element (Cur)); - end loop; end; - end; + end if; end Checkpoint_Load_Unit; ----------- @@ -2645,7 +2065,11 @@ package body SC_Obligations is procedure Write (CSS : in out Checkpoint_Save_State; Value : Scope_Entity) is begin - CSS.Write (Value.Source_Range); + CSS.Write_SCO (Value.From); + CSS.Write_SCO (Value.To); + + CSS.Write (Value.Start_Sloc); + CSS.Write (Value.End_Sloc); CSS.Write (Value.Name); CSS.Write (Value.Sloc); @@ -2654,59 +2078,55 @@ package body SC_Obligations is CSS.Write_Integer (Value.Identifier.Decl_Line); end Write; - procedure Write (CSS : in out Checkpoint_Save_State; Value : SCO_Range) is - begin - CSS.Write_SCO (Value.First); - CSS.Write_SCO (Value.Last); - end Write; - - procedure Write - (CSS : in out Checkpoint_Save_State; Value : SID_Info) is - begin - Write (CSS, Value.Blocks); - CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'First); - CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'Last); - for SCO of Value.Bit_Maps.Statement_Bits.all loop - CSS.Write_SCO (SCO); - end loop; - - CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'First); - CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'Last); - for Info of Value.Bit_Maps.Decision_Bits.all loop - CSS.Write_SCO (Info.D_SCO); - CSS.Write (Info.Outcome); - end loop; - - CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'First); - CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'Last); - for Info of Value.Bit_Maps.MCDC_Bits.all loop - CSS.Write_SCO (Info.D_SCO); - CSS.Write_Integer (Info.Path_Index); - end loop; - - CSS.Write (Value.Bit_Maps_Fingerprint); - CSS.Write (Value.Annotations_Fingerprint); - end Write; - procedure Write (CSS : in out Checkpoint_Save_State; Value : CU_Info) is begin CSS.Write_U8 (SCO_Provider'Pos (Value.Provider)); CSS.Write_SFI (Value.Origin); CSS.Write_SFI (Value.Main_Source); + CSS.Write_SCO (Value.First_SCO); + CSS.Write_SCO (Value.Last_SCO); Write (CSS, Value.Deps); CSS.Write (Value.Has_Code); + CSS.Write (Value.Fingerprint); Write (CSS, Value.PP_Info_Map); Write (CSS, Value.Scope_Entities); Write (CSS, Value.ALI_Annotations); - Write (CSS, Value.SCOs); + CSS.Write (Value.Annotations_Fingerprint); case Value.Provider is - when Compiler | LLVM => - CSS.Write (Value.SCOs_Fingerprint); + when Compiler | LLVM => + null; + when Instrumenter => - Write (CSS, Value.SIDs_Info); - CSS.Write (Value.Source_Fingerprint); + if CSS.Purpose_Of = Instrumentation then + CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'First); + CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'Last); + for SCO of Value.Bit_Maps.Statement_Bits.all loop + CSS.Write_SCO (SCO); + end loop; + + CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'First); + CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'Last); + for Info of Value.Bit_Maps.Decision_Bits.all loop + CSS.Write_SCO (Info.D_SCO); + CSS.Write (Info.Outcome); + end loop; + + CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'First); + CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'Last); + for Info of Value.Bit_Maps.MCDC_Bits.all loop + CSS.Write_SCO (Info.D_SCO); + CSS.Write_Integer (Info.Path_Index); + end loop; + + CSS.Write (Value.Bit_Maps_Fingerprint); + + -- Write the blocks information + + Write (CSS, Value.Blocks); + end if; end case; + end Write; procedure Write @@ -2787,11 +2207,11 @@ package body SC_Obligations is procedure Free is new Ada.Unchecked_Deallocation (MCDC_Bit_Map, MCDC_Bit_Map_Access); begin - for SID_Info of CU.SIDs_Info loop - Free (SID_Info.Bit_Maps.Statement_Bits); - Free (SID_Info.Bit_Maps.Decision_Bits); - Free (SID_Info.Bit_Maps.MCDC_Bits); - end loop; + if CU.Provider = Instrumenter then + Free (CU.Bit_Maps.Statement_Bits); + Free (CU.Bit_Maps.Decision_Bits); + Free (CU.Bit_Maps.MCDC_Bits); + end if; end Free; --------------------- @@ -2871,8 +2291,9 @@ package body SC_Obligations is declare use CU_Info_Vectors; - CP_CU_Id : constant CU_Id := To_Index (Cur); - CP_CU : CU_Info := Element (Cur); + CP_CU_Id : constant CU_Id := To_Index (Cur); + CP_CU : CU_Info := Element (Cur); + New_CU_Id : CU_Id := No_CU_Id; -- If the CU Origin or its Main_Source files are ignored, we -- cannot load this CU. @@ -2910,7 +2331,8 @@ package body SC_Obligations is (CLS, CP_Vectors, CP_CU, - CP_CU_Id => CP_CU_Id); + New_CU_Id => New_CU_Id); + Set_CU_Id_Map (Relocs, CP_CU_Id, New_CU_Id); end if; end; end loop; @@ -3048,8 +2470,8 @@ package body SC_Obligations is if Last_SCO < First_SCO then Warn ("[LLVM-JSON] No regions to process"); else - CU_Vector (CUID).SCOs.Append - (SCO_Range'(First => First_SCO, Last => Last_SCO)); + CU_Vector (CUID).First_SCO := First_SCO; + CU_Vector (CUID).Last_SCO := Last_SCO; end if; end; end loop; @@ -3138,32 +2560,31 @@ package body SC_Obligations is end if; end Comp_Unit; - ---------------- - -- SCO_Ranges -- - ---------------- + --------------- + -- First_SCO -- + --------------- - function SCO_Ranges (CU : CU_Id) return SCO_Range_Vectors.Vector is + function First_SCO (CU : CU_Id) return SCO_Id is begin if CU = No_CU_Id then - return SCO_Range_Vectors.Empty_Vector; + return No_SCO_Id; else - return CU_Vector.Constant_Reference (CU).SCOs; + return CU_Vector.Constant_Reference (CU).First_SCO; end if; - end SCO_Ranges; + end First_SCO; - ----------- - -- In_CU -- - ----------- + -------------- + -- Last_SCO -- + -------------- - function In_CU (CU : CU_Id; SCO : SCO_Id) return Boolean is + function Last_SCO (CU : CU_Id) return SCO_Id is begin - for SCO_Range of SCO_Ranges (CU) loop - if SCO >= SCO_Range.First and then SCO <= SCO_Range.Last then - return True; - end if; - end loop; - return False; - end In_CU; + if CU = No_CU_Id then + return No_SCO_Id; + else + return CU_Vector.Constant_Reference (CU).Last_SCO; + end if; + end Last_SCO; ----------- -- Index -- @@ -3225,7 +2646,7 @@ package body SC_Obligations is begin -- Search for the first Condition of the Decision. - while In_CU (CU, C_SCO) + while C_SCO <= Last_SCO (CU) and then (Kind (C_SCO) /= Condition or else Parent (C_SCO) /= SCO) loop @@ -3240,13 +2661,13 @@ package body SC_Obligations is Index_Mut := Index_Mut - 1; loop C_SCO := C_SCO + 1; - exit when not In_CU (CU, C_SCO); + exit when C_SCO > Last_SCO (CU); exit when Kind (C_SCO) = Condition and then Parent (C_SCO) = SCO; end loop; end loop; - if not In_CU (CU, C_SCO) then + if C_SCO > Last_SCO (CU) then Fatal_Error ("Malformed SCO Vector, a condition SCO" & " is missing"); end if; @@ -3642,8 +3063,8 @@ package body SC_Obligations is use Sloc_To_SCO_Maps; Position : Cursor := - Sloc_To_SCO_Map (Sloc_End.Source_File, Kind).Floor - ((Sloc_End.L, No_Local_Location)); + Sloc_To_SCO_Map (Sloc_End.Source_File, Kind).Floor + ((Sloc_End.L, No_Local_Location)); begin while Position /= No_Element loop declare @@ -3878,15 +3299,25 @@ package body SC_Obligations is --------------- function Comp_Unit (SCO : SCO_Id) return CU_Id is + LB, UB, Middle : Valid_CU_Id; begin - -- TODO??? we are losing the logarithmic complexity + -- Assume that compilation units in CU_Vector are ordered by SCO range + -- to look up efficiently (by dichotomy) the compilation unit for the + -- SCO. - for Cur in CU_Vector.Iterate loop + LB := CU_Vector.First_Index; + UB := CU_Vector.Last_Index; + while LB <= UB loop + Middle := LB + (UB - LB) / 2; declare - CU : constant CU_Id := CU_Info_Vectors.To_Index (Cur); + CU : CU_Info renames CU_Vector.Constant_Reference (Middle); begin - if In_CU (CU, SCO) then - return CU; + if SCO in CU.First_SCO .. CU.Last_SCO then + return Middle; + elsif SCO < CU.First_SCO then + UB := Middle - 1; + else + LB := Middle + 1; end if; end; end loop; @@ -4292,20 +3723,29 @@ package body SC_Obligations is -- Fingerprint -- ----------------- - function Fingerprint (CU : CU_Id) return Fingerprint_Type - is - SID_Infos : constant SID_Info_Maps.Map := - CU_Vector.Element (CU).SIDs_Info; + function Fingerprint (CU : CU_Id) return Fingerprint_Type is begin - if SID_Infos.Length /= 1 then - Outputs.Fatal_Error - ("Found multiple versions for " - & Get_Full_Name (CU_Vector.Element (CU).Main_Source)); - end if; - pragma Assert (SID_Infos.Length = 1); - return SID_Infos.First_Key; + return CU_Vector.Reference (CU).Fingerprint; end Fingerprint; + -------------------------- + -- Bit_Maps_Fingerprint -- + -------------------------- + + function Bit_Maps_Fingerprint (CU : CU_Id) return Fingerprint_Type is + begin + return CU_Vector.Reference (CU).Bit_Maps_Fingerprint; + end Bit_Maps_Fingerprint; + + ----------------------------- + -- Annotations_Fingerprint -- + ----------------------------- + + function Annotations_Fingerprint (CU : CU_Id) return Fingerprint_Type is + begin + return CU_Vector.Reference (CU).Annotations_Fingerprint; + end Annotations_Fingerprint; + --------------- -- Load_SCOs -- --------------- @@ -4325,7 +3765,7 @@ package body SC_Obligations is ALI_Index : constant Source_File_Index := Load_ALI (ALI_Filename, Ignored_Source_Files, Units, Deps, Temp_ALI_Annotations, With_SCOs => True); - -- Load ALI file and update the last SCO + -- Load ALI file and update the last SCO index begin if ALI_Index = No_Source_File then @@ -4610,14 +4050,11 @@ package body SC_Obligations is Created_Units : in out Created_Unit_Maps.Map) return CU_Id is use Created_Unit_Maps; - use GNATCOLL.VFS; New_CU_Info : CU_Info (Provider); - CU_Index : constant CU_Id := Comp_Unit (Main_Source); - CU_Version : SID_Info; - Cur : constant Cursor := Created_Units.Find (Main_Source); - + CU_Index : constant CU_Id := Comp_Unit (Main_Source); + Cur : constant Cursor := Created_Units.Find (Main_Source); begin -- Check whether there is already a compilation unit for this main -- source. @@ -4637,7 +4074,7 @@ package body SC_Obligations is -- this duplicate, and return no CU to signify to the caller that we -- must abort the loading. - if SC_Obligations.Fingerprint (CU_Index) = Fingerprint then + if CU_Vector.Reference (CU_Index).Fingerprint = Fingerprint then return No_CU_Id; end if; @@ -4680,30 +4117,9 @@ package body SC_Obligations is New_CU_Info.Origin := Origin; New_CU_Info.Main_Source := Main_Source; - New_CU_Info.SIDs_Info.Insert (Fingerprint, CU_Version); - - -- Also create the fingerprint: the SCOs fingerprint for binary traces, - -- which is still used for consistency checks, and the source - -- fingerprint for source traces. - - case Provider is - when Compiler | LLVM => - New_CU_Info.SCOs_Fingerprint := Fingerprint; - when Instrumenter => - declare - Source_Fingerprint_Context : GNAT.SHA1.Context; - Contents : GNAT.Strings.String_Access := - Read_File (Create (+Get_Full_Name (Main_Source))); - begin - GNAT.SHA1.Update (Source_Fingerprint_Context, Contents.all); - Free (Contents); - New_CU_Info.Source_Fingerprint := - Fingerprint_Type - (GNAT.SHA1.Binary_Message_Digest' - (GNAT.SHA1.Digest (Source_Fingerprint_Context))); - end; - end case; - + New_CU_Info.First_SCO := Valid_SCO_Id'First; + New_CU_Info.Last_SCO := No_SCO_Id; + New_CU_Info.Fingerprint := Fingerprint; CU_Vector.Append (New_CU_Info); return Result : constant CU_Id := CU_Vector.Last_Index do @@ -5132,10 +4548,8 @@ package body SC_Obligations is begin Unit.Deps := Deps; - Unit.SCOs.Append - (SCO_Range' - (First => First_SCO, - Last => SCO_Vector.Last_Index)); + Unit.First_SCO := First_SCO; + Unit.Last_SCO := SCO_Vector.Last_Index; end; end; @@ -5793,8 +5207,7 @@ package body SC_Obligations is function Are_Bit_Maps_In_Range (Bit_Maps : CU_Bit_Maps; CU : CU_Info) return Boolean is - subtype SCO_Range is - SCO_Id range CU.SCOs.First_Element.First .. CU.SCOs.First_Element.Last; + subtype SCO_Range is SCO_Id range CU.First_SCO .. CU.Last_SCO; begin return (for all SCO of Bit_Maps.Statement_Bits.all => SCO in SCO_Range) @@ -5812,8 +5225,6 @@ package body SC_Obligations is use GNAT.SHA1; Info : CU_Info renames CU_Vector.Reference (CU); - CU_Version : SID_Info renames - Info.SIDs_Info.Reference (Info.SIDs_Info.First); Ctx : GNAT.SHA1.Context; LF : constant String := (1 => ASCII.LF); @@ -5842,7 +5253,7 @@ package body SC_Obligations is ------------ procedure Update (SCO : SCO_Id) is - Relative_SCO : constant SCO_Id := SCO - Info.SCOs.First_Element.First; + Relative_SCO : constant SCO_Id := SCO - Info.First_SCO; begin Update (Ctx, Relative_SCO'Image); end Update; @@ -5850,7 +5261,7 @@ package body SC_Obligations is begin pragma Assert (Are_Bit_Maps_In_Range (Bit_Maps, Info)); - CU_Version.Bit_Maps := Bit_Maps; + Info.Bit_Maps := Bit_Maps; -- Compute the fingerprint for these bit maps @@ -5874,7 +5285,7 @@ package body SC_Obligations is end loop; Update (Ctx, LF); - CU_Version.Bit_Maps_Fingerprint := Fingerprint_Type + Info.Bit_Maps_Fingerprint := Fingerprint_Type (GNAT.SHA1.Binary_Message_Digest'(GNAT.SHA1.Digest (Ctx))); end Set_Bit_Maps; @@ -5884,10 +5295,8 @@ package body SC_Obligations is procedure Set_Blocks (CU : CU_Id; Blocks : SCO_Id_Vector_Vector) is Info : CU_Info renames CU_Vector.Reference (CU); - CU_Version : SID_Info renames - Info.SIDs_Info.Reference (Info.SIDs_Info.First); begin - CU_Version.Blocks := Blocks; + Info.Blocks := Blocks; end Set_Blocks; --------------------- @@ -5903,31 +5312,6 @@ package body SC_Obligations is Current_Ctx : GNAT.SHA1.Context := Initial_Context; -- Current file being processed - procedure Set_Annotations_Fingerprint; - -- Set the annotations fingerprint for Current_CU if it is not null, - -- stored in Current_Ctx. - - --------------------------------- - -- Set_Annotations_Fingerprint -- - --------------------------------- - - procedure Set_Annotations_Fingerprint is - begin - if Current_CU /= No_CU_Id then - declare - SID_Maps : SID_Info_Maps.Map renames - CU_Vector.Reference (Current_CU).SIDs_Info; - SID : SID_Info renames - SID_Maps.Reference (SID_Maps.First); - begin - SID.Annotations_Fingerprint := - Fingerprint_Type - (GNAT.SHA1.Binary_Message_Digest' - (GNAT.SHA1.Digest (Current_Ctx))); - end; - end if; - end Set_Annotations_Fingerprint; - begin -- As a reminder, Source_Location sort on the file index first, so we -- are guaranteed to have annotations grouped by source files. @@ -5942,7 +5326,12 @@ package body SC_Obligations is -- dump the annotations fingerprint that was processed. if Sloc.Source_File /= Current_SFI then - Set_Annotations_Fingerprint; + if Current_CU /= No_CU_Id then + CU_Vector.Reference (Current_CU).Annotations_Fingerprint := + Fingerprint_Type + (GNAT.SHA1.Binary_Message_Digest' + (GNAT.SHA1.Digest (Current_Ctx))); + end if; Current_Ctx := Initial_Context; Current_SFI := Sloc.Source_File; Current_CU := Comp_Unit (Current_SFI); @@ -5956,7 +5345,12 @@ package body SC_Obligations is (Sloc, Ann); end; end loop; - Set_Annotations_Fingerprint; + if Current_CU /= No_CU_Id then + CU_Vector.Reference (Current_CU).Annotations_Fingerprint := + Fingerprint_Type + (GNAT.SHA1.Binary_Message_Digest' + (GNAT.SHA1.Digest (Current_Ctx))); + end if; end Set_Annotations; ------------------------ @@ -5984,11 +5378,9 @@ package body SC_Obligations is -- Exception raised when the nesting/ordering invariant is found to be -- broken. - Lower_Bound : Local_Source_Location := - Local_Source_Location'(Line => 1, Column => 0); - -- At every step of the check, this designates the minimum possible - -- source location value for the .Source_Range.L.First_Sloc component - -- for the next element to inspect. + Lower_Bound : SCO_Id := No_SCO_Id; + -- At every step of the check, this designates the minimum possible SCO + -- value for the .From component for the next element to inspect. procedure Check_Element (Cur : Cursor); -- Check that Cur's From/To SCOs range is not empty and @@ -6002,14 +5394,14 @@ package body SC_Obligations is SE : Scope_Entity renames Tree.Constant_Reference (Cur); Child : Cursor := First_Child (Cur); - Last : Local_Source_Location; - -- Source_Location upper bound for Cur's last child, or - -- SE.Source_Range.First_Sloc if there is no child. + Last : SCO_Id; + -- SCO range upper bound for Cur's last child, or SE.From if there is + -- no child. begin - -- Check that source ranges are never empty + -- Check that SCO ranges are never empty - if SE.Source_Range.L.Last_Sloc < SE.Source_Range.L.First_Sloc then - raise Failure with "empty source range for " & Image (SE); + if SE.From > SE.To then + raise Failure with "empty SCO range for " & Image (SE); end if; -- Check that the SCO range lower bound is both: @@ -6020,12 +5412,11 @@ package body SC_Obligations is -- * greater than the previous sibling (if any: this checks the -- ordering). - if SE.Source_Range.L.First_Sloc < Lower_Bound then - raise Failure with - "source range lower bound too low for " & Image (SE); + if SE.From < Lower_Bound then + raise Failure with "SCO lower bound too low for " & Image (SE); end if; - Lower_Bound := SE.Source_Range.L.First_Sloc; - Last := SE.Source_Range.L.First_Sloc; + Lower_Bound := SE.From; + Last := SE.From; while Has_Element (Child) loop Check_Element (Child); @@ -6034,21 +5425,17 @@ package body SC_Obligations is -- The next sibling's SCO range cannot overlap with the current's - Lower_Bound := - Local_Source_Location' - (Line => Lower_Bound.Line, - Column => Lower_Bound.Column + 1); + Lower_Bound := Lower_Bound + 1; end loop; -- Check that the SCO range upper bound is greater or equal to -- the upper bound of the last child's upper bound (this is the -- second half of the nesting check). - if SE.Source_Range.L.Last_Sloc < Last then - raise Failure with - "Source location bound too low for " & Image (SE); + if SE.To < Last then + raise Failure with "SCO higher bound too low for " & Image (SE); end if; - Lower_Bound := SE.Source_Range.L.Last_Sloc; + Lower_Bound := SE.To; end Check_Element; Cur : Cursor := First_Child (Tree.Root); @@ -6078,37 +5465,6 @@ package body SC_Obligations is return False; end SCOs_Nested_And_Ordered; - ----------- - -- Floor -- - ----------- - - function Floor - (Tree : Scope_Entities_Trees.Tree; - Sloc : Source_Location) return Scope_Entities_Trees.Cursor - is - use Scope_Entities_Trees; - - Result : Scope_Entities_Trees.Cursor := Scope_Entities_Trees.No_Element; - - procedure Process_Node (Cur : Cursor); - - ------------------ - -- Process_Node -- - ------------------ - - procedure Process_Node (Cur : Cursor) is - begin - if In_Range (Sloc, Element (Cur).Source_Range) then - Result := Cur; - Iterate_Children (Cur, Process_Node'Access); - end if; - end Process_Node; - - begin - Iterate_Children (Tree.Root, Process_Node'Access); - return Result; - end Floor; - ---------------- -- Covers_SCO -- ---------------- @@ -6120,22 +5476,6 @@ package body SC_Obligations is and then Scope_Entities_Trees.Is_Root (ST.Cur)) or else Covers_SCO (Scope_Entities_Trees.Element (ST.Cur), SCO)); - ------------------ - -- Contains_SCO -- - ------------------ - - function Contains_SCO (SCO : SCO_Id; CU : CU_Id) return Boolean - is - Unit : CU_Info renames CU_Vector.Reference (CU); - begin - for SCO_Range of Unit.SCOs loop - if SCO in SCO_Range.First .. SCO_Range.Last then - return True; - end if; - end loop; - return False; - end Contains_SCO; - ------------------------ -- Set_Scope_Entities -- ------------------------ @@ -6945,7 +6285,7 @@ package body SC_Obligations is -- operand, if it is a condition. Cur := Sloc_To_SCO_Map (Sloc.Source_File, Operator).Find - ((Sloc.L, No_Local_Location)); + ((Sloc.L, No_Local_Location)); if Cur /= No_Element then SCO := Element (Cur); while Kind (SCO) = Operator and then Op_Kind (SCO) = Op_Not loop @@ -7037,7 +6377,9 @@ package body SC_Obligations is Cur := Sloc_To_SCO_Map (Sloc.Source_File, Decision) .Find ((Sloc.L, No_Local_Location)); - if Cur /= No_Element then + if Cur = No_Element then + SCO := No_SCO_Id; + else pragma Assert (SCO = No_SCO_Id or else SCO = Enclosing_Statement (Element (Cur))); diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index cafa9da99..f4e310214 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -133,8 +133,13 @@ package SC_Obligations is No_Fingerprint : constant Fingerprint_Type := (others => 0); function Fingerprint (CU : CU_Id) return Fingerprint_Type; - -- Assuming the CU has only one SID version, return its fingerprint. See - -- CU_Info.SID_Info for more information. + -- Hash of SCO info in ALI, for incremental coverage consistency check + + function Bit_Maps_Fingerprint (CU : CU_Id) return Fingerprint_Type; + -- Hash of buffer bit mappings in CU + + function Annotations_Fingerprint (CU : CU_Id) return Fingerprint_Type; + -- Hash of annotations in CU function Comp_Unit (Src_File : Source_File_Index) return CU_Id; -- Return the identifier for the compilation unit containing the given @@ -255,6 +260,14 @@ package SC_Obligations is -- -- Deps are the dependencies of the compilation. + --------------- + -- Instances -- + --------------- + + type Inst_Id is new Natural; + No_Inst_Id : constant Inst_Id := 0; + subtype Valid_Inst_Id is Inst_Id range No_Inst_Id + 1 .. Inst_Id'Last; + --------------------------------- -- Source Coverage Obligations -- --------------------------------- @@ -296,10 +309,15 @@ package SC_Obligations is else L.Decl_SFI < R.Decl_SFI); type Scope_Entity is record - Source_Range : Source_Location_Range; - -- Source_Location_Range for this scope. This is more precise than the - -- SCO range as the SCO range may skip over lines with disabled - -- coverage, which we want to report on. + From, To : SCO_Id; + -- SCO range for this scope. As scope entities are computed during + -- instrumentation, From and To designate low level SCOs that are then + -- converted to high level SCOs after processing the low level SCOs. + + Start_Sloc, End_Sloc : Local_Source_Location; + -- Start/End_Sloc for this scope. This is more precise than the SCO + -- range as the SCO range may skip over lines with disabled coverage, + -- which we want to report on. Name : Unbounded_String; Sloc : Local_Source_Location; @@ -307,14 +325,6 @@ package SC_Obligations is Identifier : Scope_Entity_Identifier; -- Identifier for this scope entity - - -- Below are the fields only used when instrumenting and not stored in - -- checkpoints. - - Start_SCO : SCO_Id; - -- Index of the expected start SCO. This is used to discard scopes - -- without any SCOs at instrumentation time. - end record; -- Scope_Entity (SE) stores the SCO range, the name and the sloc of a SE. -- Note that we assume that the SCOs of a SE can be designated by a range. @@ -357,6 +367,12 @@ package SC_Obligations is -- Utilities type to efficiently traverse the scopes in a compilation unit. -- This is a tree-like data structure, with an iterator pointing to the -- currently traversed inner scope. + -- + -- The intended use is to create a Scope_Traversal_Type using the + -- Scope_Traversal function, and then call Traverse_SCO every time + -- we traverse a SCO to update the scope traversal iterator, and call + -- Is_Active to know whether a given scope is active in the given + -- traversal. function Scope_Traversal (CU : CU_Id) return Scope_Traversal_Type; -- Return a scope traversal for the given compilation unit @@ -372,11 +388,13 @@ package SC_Obligations is -- (i.e. consider that all subprograms are of interest in that case). No_Scope_Entity : constant Scope_Entity := - (Source_Range => No_Range, - Name => +"", - Sloc => No_Local_Location, - Identifier => No_Scope_Entity_Identifier, - Start_SCO => No_SCO_Id); + (From => No_SCO_Id, + To => No_SCO_Id, + Start_Sloc => No_Local_Location, + End_Sloc => No_Local_Location, + Name => +"", + Sloc => No_Local_Location, + Identifier => No_Scope_Entity_Identifier); type Any_SCO_Kind is (Removed, Statement, Decision, Condition, Operator, Fun, Call, @@ -888,46 +906,13 @@ package SC_Obligations is "=" => SCO_Id_Vectors."="); subtype SCO_Id_Vector_Vector is SCO_Id_Vector_Vectors.Vector; - function Has_Fingerprint - (CU : CU_Id; - SCO_Fingerprint : Fingerprint_Type) return Boolean; - -- Return whether there is a match for the given CU and SCO_Fingerprint - - package Fingerprint_Vectors is new Ada.Containers.Vectors - (Index_Type => Positive, - Element_Type => Fingerprint_Type); - - function Fingerprints (CU : CU_Id) return Fingerprint_Vectors.Vector; - -- Return the fingerprints for all the different versions of the - -- compilation unit identified by CU. - - function Bit_Maps - (CU : CU_Id; - SCO_Fingerprint : Fingerprint_Type) return CU_Bit_Maps; - -- For a unit whose coverage is assessed through source code - -- instrumentation, return bit maps for the version of the compilation unit - -- denoted by SCO_Fingerprint. - - function Bit_Maps_Fingerprint - (CU : CU_Id; - SCO_Fingerprint : Fingerprint_Type) return Fingerprint_Type; - -- For a unit whose coverage is assessed through source code - -- instrumentation, return the bit maps fingerprint for the version of the - -- compilation unit denoted by SCO_Fingerprint. - - function Annotations_Fingerprint - (CU : CU_Id; - SCO_Fingerprint : Fingerprint_Type) return Fingerprint_Type; + function Bit_Maps (CU : CU_Id) return CU_Bit_Maps; -- For a unit whose coverage is assessed through source code - -- instrumentation, return the annotations fingerprint for the version of - -- the compilation unit denoted by SCO_Fingerprint. + -- instrumentation, return bit maps. - function Blocks - (CU : CU_Id; - SCO_Fingerprint : Fingerprint_Type) return SCO_Id_Vector_Vector; + function Blocks (CU : CU_Id) return SCO_Id_Vector_Vector; -- For a unit whose coverage is assessed through source code - -- instrumentation, return blocks information for the version of the - -- compilation unit denoted by SCO_Fingerprint. + -- instrumentation, return blocks information. procedure Set_Bit_Maps (CU : CU_Id; Bit_Maps : CU_Bit_Maps); -- Set the tables mapping source trace bit indices to SCO discharge info @@ -1020,22 +1005,11 @@ package SC_Obligations is -- Accessors for CU_Info -- --------------------------- - type SCO_Range is record - First, Last : SCO_Id; - end record; - - function "=" (L, R : SCO_Range) return Boolean - is (L.First = R.First and then R.Last = L.Last); - - package SCO_Range_Vectors is new Ada.Containers.Vectors - (Index_Type => Positive, - Element_Type => SCO_Range); - - function SCO_Ranges (CU : CU_Id) return SCO_Range_Vectors.Vector; - -- Return the list of SCOs for the compilation unit + function First_SCO (CU : CU_Id) return SCO_Id; + -- Return the first SCO of the compilation unit - function In_CU (CU : CU_Id; SCO : SCO_Id) return Boolean; - -- Return whether SCO pertain to CU + function Last_SCO (CU : CU_Id) return SCO_Id; + -- Return the last SCO of the compilation unit ------------- -- Pragmas -- diff --git a/tools/gnatcov/slocs.ads b/tools/gnatcov/slocs.ads index eb46e1917..9656d2144 100644 --- a/tools/gnatcov/slocs.ads +++ b/tools/gnatcov/slocs.ads @@ -74,8 +74,8 @@ package Slocs is function "<" (L, R : Source_Location) return Boolean; function "<=" (L, R : Source_Location) return Boolean; - No_Location : constant Source_Location := - (No_Source_File, No_Local_Location); + No_Location : constant Source_Location := + (No_Source_File, No_Local_Location); -- Note: No_Location must sort higher than any non-null location function Image From 5c59bc18c7cd77b156ddea101ed6cc4f0d3d9aa1 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 27 Aug 2025 11:34:38 +0200 Subject: [PATCH 1379/1483] Fix instrumentation of assert-like pragmas when using atcc --- .../tests/O212-062-assertions/others/src/various_tests.adb | 2 +- tools/gnatcov/instrument-ada_unit.adb | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/testsuite/tests/O212-062-assertions/others/src/various_tests.adb b/testsuite/tests/O212-062-assertions/others/src/various_tests.adb index 067b6e712..9dbd6bbf4 100644 --- a/testsuite/tests/O212-062-assertions/others/src/various_tests.adb +++ b/testsuite/tests/O212-062-assertions/others/src/various_tests.adb @@ -11,7 +11,7 @@ is begin -- Only the first condition is evaluated - pragma Assert ((X = 0 or else A) or else X = 8); -- # assert_1 + pragma Assert ((X = 0 or else A) or else X = 8, "msg"); -- # assert_1 -- Call a function. Evaluate all conditions of the precondition; -- evaluate only the first condition of the postcondition. The first diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 1bc16d054..6f0e90338 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -5500,17 +5500,16 @@ package body Instrument.Ada_Unit is if Assertion_Coverage_Enabled then Instrument_Statement (UIC, N, 'P'); declare - Index : Positive := + Index : constant Positive := (case Nam is when Name_Check => 2, when others => 1); begin - while not Is_Null (Prag_Args.Child (Index)) loop + if not Is_Null (Prag_Args.Child (Index)) then Process_Expression (UIC, Prag_Arg_Expr (Prag_Args, Index), 'P'); - Index := Index + 1; - end loop; + end if; end; else Instrument_Statement (UIC, N, 'p'); From 63ea8a772d3c9ccba4b33fac483eb3a09329d77d Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 27 Aug 2025 08:50:44 +0000 Subject: [PATCH 1380/1483] Testsuite: do not mention the fake "Consolidation" language in GPR files Recent versions of LibGPR2 emit warnings for this language: warning: no compiler driver defined for language 'Consolidation' This warning is probably fair, and we have no good reason to pretend that "Consolidation" is a valid lanugage in GPR files, to just avoid mentionning it. --- testsuite/SUITE/control.py | 20 ++++++++++++++++++-- testsuite/SUITE/tutils.py | 2 +- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index 362fedae4..12c6e5af2 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -61,14 +61,26 @@ class LangInfo: sidfile_for: A function which returns the name of the SID file for a given SOURCE file name. This is, for example, "x.sid" for "x.adb". + + in_gpr: + Whether this language can be mentionned in project files. """ - def __init__(self, name, src_ext, comment, scofile_for, sidfile_for=None): + def __init__( + self, + name, + src_ext, + comment, + scofile_for, + sidfile_for=None, + in_gpr=True, + ): self.name = name self.src_ext = src_ext self.comment = comment self.scofile_for = scofile_for self.sidfile_for = sidfile_for + self.in_gpr = in_gpr # A dictionary mapping a LangInfo instance to each known language. @@ -103,7 +115,11 @@ def __init__(self, name, src_ext, comment, scofile_for, sidfile_for=None): ), "Asm": LangInfo(name="Asm", src_ext=[".s"], comment="#", scofile_for=None), "Cons": LangInfo( - name="Consolidation", src_ext=[".txt"], comment="--", scofile_for=None + name="Consolidation", + src_ext=[".txt"], + comment="--", + scofile_for=None, + in_gpr=False, ), } diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 1e73d4c80..98aa8c247 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -491,7 +491,7 @@ def gprfor( for srcdir in srcdirs_list for src in os.listdir(os.path.join(cwd, srcdir)) ] - langs = {li.name for li in lang_infos if li} + langs = {li.name for li in lang_infos if li and li.in_gpr} srcdirs = ", ".join('"%s"' % d for d in srcdirs_list) languages = ", ".join('"%s"' % lang for lang in langs) From e8c011aec67786cda6de4284623d0890e0ed8136 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 22 Aug 2025 08:45:29 +0000 Subject: [PATCH 1381/1483] instrument-ada_unit.adb: minor refactoring --- tools/gnatcov/instrument-ada_unit.adb | 90 +++++++++++++++------------ 1 file changed, 49 insertions(+), 41 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 6f0e90338..7182aec6b 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -446,7 +446,7 @@ package body Instrument.Ada_Unit is function Is_Generic (UIC : Ada_Unit_Inst_Context; - Decl : Basic_Decl) return Boolean; + Decl : Basic_Decl'Class) return Boolean; -- Return whether the given declaration is generic (its canonical part is -- generic). @@ -3633,7 +3633,7 @@ package body Instrument.Ada_Unit is procedure Traverse_Subprogram_Or_Task_Body (UIC : in out Ada_Unit_Inst_Context; - N : Ada_Node); + N : Body_Node'Class); procedure Traverse_Sync_Definition (UIC : in out Ada_Unit_Inst_Context; @@ -4398,7 +4398,7 @@ package body Instrument.Ada_Unit is end; end if; - if Is_Generic (UIC, N.As_Basic_Decl) then + if Is_Generic (UIC, N) then if Is_Expr_Function then UIC.Disable_Instrumentation := True; Report (UIC, N, @@ -5061,9 +5061,13 @@ package body Instrument.Ada_Unit is -- Package body when Ada_Package_Body => - UIC.In_Generic := Is_Generic (UIC, N.As_Basic_Decl); - Traverse_Package_Body (UIC, N.As_Package_Body, Preelab); - UIC.In_Generic := Saved_In_Generic; + declare + PB : constant Package_Body := N.As_Package_Body; + begin + UIC.In_Generic := Is_Generic (UIC, PB); + Traverse_Package_Body (UIC, PB, Preelab); + UIC.In_Generic := Saved_In_Generic; + end; -- Subprogram declaration or subprogram body stub @@ -5098,44 +5102,48 @@ package body Instrument.Ada_Unit is when Ada_Subp_Body | Ada_Task_Body - => - UIC.In_Generic := Is_Generic (UIC, N.As_Basic_Decl); - - Traverse_Subprogram_Or_Task_Body (UIC, N); + => + declare + B : constant Body_Node := N.As_Body_Node; + begin + UIC.In_Generic := Is_Generic (UIC, B); - if Enabled (Fun_Call) then - declare - Fun_Witness : Node_Rewriting_Handle := - No_Node_Rewriting_Handle; - begin - -- Add a function SCO for this subprogram and fill - -- Fun_Witness with a witness call for this new SCO. The - -- witness call is within a dummy variable declaration. + Traverse_Subprogram_Or_Task_Body (UIC, B); - Instrument_For_Function_Coverage - (UIC, - N.As_Subp_Body.F_Subp_Spec, - Function_Call, - Fun_Witness); - - -- Put the dummy variable containing the witness call - -- at the very top of the declarative part of this - -- subprogram. This way, it will be executed as soon as - -- the function is called. - - Insert_First - (Handle (N.As_Subp_Body.F_Decls.F_Decls), - Create_Function_Witness_Var (UIC, Fun_Witness)); - end; - end if; + if B.Kind = Ada_Subp_Body and then Enabled (Fun_Call) then + declare + SB : constant Subp_Body := N.As_Subp_Body; + Fun_Witness : Node_Rewriting_Handle := + No_Node_Rewriting_Handle; + begin + -- Add a function SCO for this subprogram and fill + -- Fun_Witness with a witness call for this new SCO. + -- The witness call is within a dummy variable + -- declaration. + + Instrument_For_Function_Coverage + (UIC, SB.F_Subp_Spec, Function_Call, Fun_Witness); + + -- Put the dummy variable containing the witness call + -- at the very top of the declarative part of this + -- subprogram. This way, it will be executed as soon + -- as the function is called. + + Insert_First + (Handle (SB.F_Decls.F_Decls), + Create_Function_Witness_Var (UIC, Fun_Witness)); + end; + end if; - UIC.In_Generic := Saved_In_Generic; + UIC.In_Generic := Saved_In_Generic; + end; -- Entry body when Ada_Entry_Body => declare - Cond : constant Expr := As_Entry_Body (N).F_Barrier; + EB : constant Entry_Body := N.As_Entry_Body; + Cond : constant Expr := EB.F_Barrier; Unit : LAL.Analysis_Unit; Save_Disable_Instrumentation : constant Boolean := @@ -5151,7 +5159,7 @@ package body Instrument.Ada_Unit is Save_Disable_Instrumentation; end if; - Traverse_Subprogram_Or_Task_Body (UIC, N); + Traverse_Subprogram_Or_Task_Body (UIC, EB); end; -- Protected body @@ -6114,7 +6122,7 @@ package body Instrument.Ada_Unit is procedure Traverse_Subprogram_Or_Task_Body (UIC : in out Ada_Unit_Inst_Context; - N : Ada_Node) + N : Body_Node'Class) is Decls : Declarative_Part; HSS : Handled_Stmts; @@ -6156,10 +6164,10 @@ package body Instrument.Ada_Unit is declare Previous_Part : constant Basic_Decl := - Safe_Previous_Part_For_Decl (N.As_Body_Node); + Safe_Previous_Part_For_Decl (N); Decl : constant Basic_Decl := (if Previous_Part.Is_Null - then N.As_Body_Node.P_Subp_Spec_Or_Null.P_Parent_Basic_Decl + then N.P_Subp_Spec_Or_Null.P_Parent_Basic_Decl else Previous_Part); begin Enter_Scope @@ -7958,7 +7966,7 @@ package body Instrument.Ada_Unit is function Is_Generic (UIC : Ada_Unit_Inst_Context; - Decl : Basic_Decl) return Boolean + Decl : Basic_Decl'Class) return Boolean is Canonical_Decl : Basic_Decl; begin From 33c313ad62d08d673c709aedf0200413dbfb9f77 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 27 Aug 2025 10:15:34 +0000 Subject: [PATCH 1382/1483] instrument-ada_unit.adb: minor reformattings --- tools/gnatcov/instrument-ada_unit.adb | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 7182aec6b..3c3a5e7bc 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -6978,8 +6978,8 @@ package body Instrument.Ada_Unit is end if; -- Do not instrument this decision if we have already - -- determined from the context that instrumenting it - -- could produce invalid code. + -- determined from the context that instrumenting it could + -- produce invalid code. -- -- Instrumenting static decisions would make them non-static by -- wrapping them in a Witness call. This transformation would @@ -10187,7 +10187,7 @@ package body Instrument.Ada_Unit is then for SD of UIC.Source_Decisions loop declare - HL_SCO : constant SCO_Id := SCO_Map (SD.LL_SCO); + HL_SCO : constant SCO_Id := SCO_Map (SD.LL_SCO); Should_Instrument : constant Boolean := ((not SD.Is_Contract and then (Coverage.Enabled (Decision) @@ -10204,7 +10204,6 @@ package body Instrument.Ada_Unit is if MCDC_Coverage_Enabled or else Assertion_Condition_Coverage_Enabled then - -- As high-level SCO tables have been populated, we have built -- BDDs for each decision, and we can now set the correct MC/DC -- path offset for each condition. From 6ceb64ce60bf812d2045522a08ca7caf604338cd Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 25 Aug 2025 09:15:35 +0000 Subject: [PATCH 1383/1483] instrument-ada_unit.adb: factor out Assertion_Coverage_Enabled checks --- tools/gnatcov/instrument-ada_unit.adb | 28 +++++++++++++-------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 3c3a5e7bc..b437761e7 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3733,9 +3733,9 @@ package body Instrument.Ada_Unit is procedure Process_Contract (UIC : in out Ada_Unit_Inst_Context; D : Basic_Decl'Class; - Name : Text_Type) - with Pre => Assertion_Coverage_Enabled; - -- Register decision of contrat of name Name of declaration node D + Name : Text_Type); + -- If Assertion_Coverage_Enabled is False, do nothing. Otherwise, + -- register decision of contrat of name Name of declaration node D procedure Traverse_One (N : Ada_Node); -- Traverse one declaration or statement @@ -4017,10 +4017,12 @@ package body Instrument.Ada_Unit is D : Basic_Decl'Class; Name : Text_Type) is begin - Process_Expression - (UIC, - P_Get_Aspect_Spec_Expr (D, To_Unbounded_Text (Name)), - 'A'); + if Assertion_Coverage_Enabled then + Process_Expression + (UIC, + P_Get_Aspect_Spec_Expr (D, To_Unbounded_Text (Name)), + 'A'); + end if; end Process_Contract; ------------------------------------ @@ -4879,10 +4881,8 @@ package body Instrument.Ada_Unit is procedure Process_Contracts (D : Basic_Decl'Class) is begin - if Assertion_Coverage_Enabled then - Process_Contract (UIC, D, "Pre"); - Process_Contract (UIC, D, "Post"); - end if; + Process_Contract (UIC, D, "Pre"); + Process_Contract (UIC, D, "Post"); end Process_Contracts; Dummy_Ctx : constant Context_Handle := Create_Context_Instrument (N); @@ -5662,10 +5662,8 @@ package body Instrument.Ada_Unit is Typ := 's'; else Typ := 't'; - if Assertion_Coverage_Enabled then - Process_Contract - (UIC, N.As_Basic_Decl, "Type_Invariant"); - end if; + Process_Contract + (UIC, N.As_Basic_Decl, "Type_Invariant"); end if; -- Entity declaration nodes that may also be used From 5e59963b658dc93447e6eaaf2342543b0f8c1731 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 22 Aug 2025 10:04:37 +0000 Subject: [PATCH 1384/1483] Instrument Ada: fix instrumentation of decisions in formal decls Because default expressions in formal declarations are executed only when their owning subprogram is called (instead of during the elaboration of that subprogram), it is incorrect to use the declarative region that contains the subprogram in order to insert MC/DC state variables for decisions in default expressions. Report a gnatcov limitation instead in that case. In addition, subprogram spec can be duplicated (one occurrence for a subprogram declaration, another for the body). Right not it is not possible to use the same instrumentation (same bit in buffer coverage) for both, so decision coverage is also impossible. The existing (disabled) test for this is repurposed to check this case. --- doc/gnatcov/src_traces.rst | 2 ++ .../Andthen/IB19_019-FormalDefault/test.opt | 1 - .../Andthen/IB19_019-FormalDefault/test.py | 6 ---- .../IB19_019-FormalDefault/src/andthen.adb | 6 +++- .../IB19_019-FormalDefault/src/andthen.ads | 3 ++ .../src/test_single.adb | 17 ++++++++++ .../Andthen/IB19_019-FormalDefault/test.py | 13 ++++++++ tools/gnatcov/instrument-ada_unit.adb | 31 ++++++++++++++++--- 8 files changed, 66 insertions(+), 13 deletions(-) delete mode 100644 testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.opt delete mode 100644 testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.py rename testsuite/tests/limits/Ada/{decision => mcdc}/Andthen/IB19_019-FormalDefault/src/andthen.adb (72%) create mode 100644 testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/andthen.ads create mode 100644 testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/test_single.adb create mode 100644 testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/test.py diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 7b4236866..24f06fa20 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -625,6 +625,8 @@ The list of unsupported constructs is as follows: * Generic null procedures, * Protected bodies entry guards when the ``Simple_Barriers`` restriction or the ``Pure_Barriers`` one apply. +* Decisions in default expressions of subprogram formals (for all + decision-related coverage criteria). Additionally, if the Ada language version in use, is less or equal to Ada 2012, the following constructs are also unsupported: diff --git a/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.opt b/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.opt deleted file mode 100644 index 16000abf6..000000000 --- a/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.opt +++ /dev/null @@ -1 +0,0 @@ -ALL DEAD diff --git a/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.py b/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.py deleted file mode 100644 index 1cad9a009..000000000 --- a/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from SCOV.tc import TestCase -from SUITE.context import thistest - - -TestCase().run() -thistest.result() diff --git a/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/src/andthen.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/andthen.adb similarity index 72% rename from testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/src/andthen.adb rename to testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/andthen.adb index b8c8e10ba..8f753bfd8 100644 --- a/testsuite/tests/limits/Ada/decision/Andthen/IB19_019-FormalDefault/src/andthen.adb +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/andthen.adb @@ -2,12 +2,16 @@ package body Andthen is AA, BB : Boolean; + function Expr + (Value : Boolean := AA and then BB) -- # andthen + return Boolean; + function Expr (Value : Boolean := AA and then BB) -- # andthen return Boolean is begin - return Value; + return Value; -- # retVal end; function And_Then (A, B : Boolean) return Boolean is diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/andthen.ads b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/andthen.ads new file mode 100644 index 000000000..087fa3b2c --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/andthen.ads @@ -0,0 +1,3 @@ +package Andthen is + function And_Then (A, B : Boolean) return Boolean; +end; diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/test_single.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/test_single.adb new file mode 100644 index 000000000..2d9b08a86 --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/src/test_single.adb @@ -0,0 +1,17 @@ +with Support, Andthen; use Support, Andthen; + +procedure Test_Single is +begin + Assert (not And_Then (False, False)); +end; + +--# andthen.adb +-- /retTrue/ l+ ## 0 +-- /retFalse/ l+ ## 0 +-- /retVal/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l? ## d? diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/test.py b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/test.py new file mode 100644 index 000000000..b6309b0a7 --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/IB19_019-FormalDefault/test.py @@ -0,0 +1,13 @@ +import re + +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase( + tolerate_messages=re.escape( + "!!! andthen.adb:6:26: gnatcov limitation: cannot find local" + " declarative part for MC/DC" + ) +).run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index b437761e7..8530d711c 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3660,6 +3660,10 @@ package body Instrument.Ada_Unit is -- -- This also processes any nested declare expressions. + procedure Process_Formal_Default_Exprs + (UIC : in out Ada_Unit_Inst_Context; N_Spec : Subp_Spec); + -- Process default expressions for formals in N_Spec + function Is_Call_Leaf (Node : Ada_Node'Class) return Boolean; -- Return True if Node is the leaf of a call expression, that is there are -- no nodes in the children of Node identifying the same call. @@ -4894,11 +4898,7 @@ package body Instrument.Ada_Unit is -- a previous declaration that must be used as scope identifier. begin - -- Process decisions nested in formal parameters - - if not N_Spec.Is_Null then - Process_Expression (UIC, N_Spec.F_Subp_Params, 'X'); - end if; + Process_Formal_Default_Exprs (UIC, N_Spec); Enter_Scope (UIC => UIC, @@ -6174,6 +6174,8 @@ package body Instrument.Ada_Unit is Decl => Decl); end; + Process_Formal_Default_Exprs (UIC, N.P_Subp_Spec_Or_Null.As_Subp_Spec); + -- If assertion coverage is enabled, process the decisions in the -- contracts. This is needed in the case of a subprogram body with -- aspect with no prior declaration. @@ -7283,6 +7285,25 @@ package body Instrument.Ada_Unit is end if; end Process_Expression; + ---------------------------------- + -- Process_Formal_Default_Exprs -- + ---------------------------------- + + procedure Process_Formal_Default_Exprs + (UIC : in out Ada_Unit_Inst_Context; N_Spec : Subp_Spec) + is + Saved_Disable_Instrumentation : constant Boolean := + UIC.Disable_Instrumentation; + begin + if N_Spec.Is_Null then + return; + end if; + + UIC.Disable_Instrumentation := True; + Process_Expression (UIC, N_Spec.F_Subp_Params, 'X'); + UIC.Disable_Instrumentation := Saved_Disable_Instrumentation; + end Process_Formal_Default_Exprs; + ------------------ -- Is_Call_Leaf -- ------------------ From 59d1eee9438193ce6bd1928a231259918ca96bbe Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 27 Aug 2025 10:34:30 +0000 Subject: [PATCH 1385/1483] SCOV.internal.rnexpanders: fix matchers for eUndetCov These violation matchers probably never worked as expected, as their formatting has not changed on gnatcov's side recently. --- testsuite/SCOV/internals/rnexpanders.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testsuite/SCOV/internals/rnexpanders.py b/testsuite/SCOV/internals/rnexpanders.py index ad6fc02d3..27e0f7ec7 100644 --- a/testsuite/SCOV/internals/rnexpanders.py +++ b/testsuite/SCOV/internals/rnexpanders.py @@ -716,7 +716,8 @@ def __init__(self): "statement was not instrumented": sUndetCov, "decision was not instrumented" " for decision coverage": dUndetCov, - "decision was not instrumented for MC/DC coverage": eUndetCov, + "decision was not instrumented for MCDC": eUndetCov, + "decision was not instrumented for UC_MCDC": eUndetCov, "function was not instrumented": fUndetCov, "call was not instrumented": cUndetCov, "guarded_expr was not instrumented": gUndetCov, From b61afde6cbb89a421cfe6faabb3df2c4c3fb188e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 22 Aug 2025 12:32:17 +0000 Subject: [PATCH 1386/1483] Instrument Ada: fix instrumentation of decisions in component decls Because default expressions in component declarations are executed only when a record object/aggregate is declared (instead of during the elaboration of the record type), it is incorrect to use the declarative region that contains the record type declaration in order to insert MC/DC state variables for decisions in default expressions. Report a gnatcov limitation instead in that case. The existing (disabled) test for this is repurposed to check this case. --- doc/gnatcov/src_traces.rst | 2 + .../JC16_008-ComponentDefault/src/andthen.adb | 12 -- .../JC16_008-ComponentDefault/test.opt | 1 - .../Andthen/JC16_008-ComponentDefault/test.py | 6 - .../JC16_008-ComponentDefault/src/andthen.adb | 12 ++ .../src/andthen.ads | 0 .../src/test_andthen_0.adb | 7 +- .../src/test_andthen_a.adb | 7 +- .../src/test_andthen_ab.adb | 7 +- .../src/test_andthen_b.adb | 7 +- .../src/test_andthen_f.adb | 7 +- .../src/test_andthen_t.adb | 7 +- .../Andthen/JC16_008-ComponentDefault/test.py | 13 ++ tools/gnatcov/instrument-ada_unit.adb | 131 ++++++++++++++++-- 14 files changed, 184 insertions(+), 35 deletions(-) delete mode 100644 testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/src/andthen.adb delete mode 100644 testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.opt delete mode 100644 testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.py create mode 100644 testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/andthen.adb rename testsuite/tests/limits/Ada/{decision/Andthen => mcdc/Andthen/JC16_008-ComponentDefault}/src/andthen.ads (100%) rename testsuite/tests/limits/Ada/{decision/Andthen => mcdc/Andthen/JC16_008-ComponentDefault}/src/test_andthen_0.adb (64%) rename testsuite/tests/limits/Ada/{decision/Andthen => mcdc/Andthen/JC16_008-ComponentDefault}/src/test_andthen_a.adb (70%) rename testsuite/tests/limits/Ada/{decision/Andthen => mcdc/Andthen/JC16_008-ComponentDefault}/src/test_andthen_ab.adb (74%) rename testsuite/tests/limits/Ada/{decision/Andthen => mcdc/Andthen/JC16_008-ComponentDefault}/src/test_andthen_b.adb (70%) rename testsuite/tests/limits/Ada/{decision/Andthen => mcdc/Andthen/JC16_008-ComponentDefault}/src/test_andthen_f.adb (71%) rename testsuite/tests/limits/Ada/{decision/Andthen => mcdc/Andthen/JC16_008-ComponentDefault}/src/test_andthen_t.adb (66%) create mode 100644 testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/test.py diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 24f06fa20..9f2300a31 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -627,6 +627,8 @@ The list of unsupported constructs is as follows: the ``Pure_Barriers`` one apply. * Decisions in default expressions of subprogram formals (for all decision-related coverage criteria). +* Decisions in default expressions of record component declarations (for MC/DC + coverage criteria). Additionally, if the Ada language version in use, is less or equal to Ada 2012, the following constructs are also unsupported: diff --git a/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/src/andthen.adb b/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/src/andthen.adb deleted file mode 100644 index 06cfd8814..000000000 --- a/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/src/andthen.adb +++ /dev/null @@ -1,12 +0,0 @@ -package body Andthen is - - type Expr (A, B : Boolean) is record - Value : Boolean := A and then B; -- # andthen - end record; - - function And_Then (A, B : Boolean) return Boolean is - E : Expr (A, B); - begin - return E.Value; -- # retVal - end; -end; diff --git a/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.opt b/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.opt deleted file mode 100644 index 16000abf6..000000000 --- a/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.opt +++ /dev/null @@ -1 +0,0 @@ -ALL DEAD diff --git a/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.py b/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.py deleted file mode 100644 index 1cad9a009..000000000 --- a/testsuite/tests/limits/Ada/decision/Andthen/JC16_008-ComponentDefault/test.py +++ /dev/null @@ -1,6 +0,0 @@ -from SCOV.tc import TestCase -from SUITE.context import thistest - - -TestCase().run() -thistest.result() diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/andthen.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/andthen.adb new file mode 100644 index 000000000..3a6008e03 --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/andthen.adb @@ -0,0 +1,12 @@ +package body Andthen is + + type Expr (AA, BB : Boolean) is record + Value : Boolean := AA and then BB; -- # andthen + end record; + + function And_Then (A, B : Boolean) return Boolean is + E : Expr (A, B); -- # retVal + begin + return E.Value; -- # retVal + end; +end; diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/andthen.ads b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/andthen.ads similarity index 100% rename from testsuite/tests/limits/Ada/decision/Andthen/src/andthen.ads rename to testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/andthen.ads diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_0.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_0.adb similarity index 64% rename from testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_0.adb rename to testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_0.adb index bf3770488..087fb52f8 100644 --- a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_0.adb +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_0.adb @@ -6,7 +6,12 @@ begin end; --# andthen.adb --- /andthen/ l- ## s- -- /retTrue/ l- ## s- -- /retFalse/ l- ## s- -- /retVal/ l- ## s- +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l! ## e- diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_a.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_a.adb similarity index 70% rename from testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_a.adb rename to testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_a.adb index 0bb327f84..f80767cca 100644 --- a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_a.adb +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_a.adb @@ -7,7 +7,12 @@ begin end; --# andthen.adb --- /andthen/ l+ ## 0 -- /retTrue/ l+ ## 0 -- /retFalse/ l+ ## 0 -- /retVal/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l? ## e? diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_ab.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_ab.adb similarity index 74% rename from testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_ab.adb rename to testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_ab.adb index ae1f17976..b5d1b8cb8 100644 --- a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_ab.adb +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_ab.adb @@ -8,7 +8,12 @@ begin end; --# andthen.adb --- /andthen/ l+ ## 0 -- /retTrue/ l+ ## 0 -- /retFalse/ l+ ## 0 -- /retVal/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l? ## e? diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_b.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_b.adb similarity index 70% rename from testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_b.adb rename to testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_b.adb index 90e057226..20fabb13d 100644 --- a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_b.adb +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_b.adb @@ -7,7 +7,12 @@ begin end; --# andthen.adb --- /andthen/ l+ ## 0 -- /retTrue/ l+ ## 0 -- /retFalse/ l+ ## 0 -- /retVal/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l? ## e? diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_f.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_f.adb similarity index 71% rename from testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_f.adb rename to testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_f.adb index ec6fae2cd..9824883e7 100644 --- a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_f.adb +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_f.adb @@ -7,7 +7,12 @@ begin end; --# andthen.adb --- /andthen/ l! ## dT- -- /retTrue/ l- ## s- -- /retFalse/ l+ ## 0 -- /retVal/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l! ## eT- diff --git a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_t.adb b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_t.adb similarity index 66% rename from testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_t.adb rename to testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_t.adb index 6c8fa7db4..e2b3d9865 100644 --- a/testsuite/tests/limits/Ada/decision/Andthen/src/test_andthen_t.adb +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/src/test_andthen_t.adb @@ -6,7 +6,12 @@ begin end; --# andthen.adb --- /andthen/ l! ## dF- -- /retTrue/ l+ ## 0 -- /retFalse/ l- ## s- -- /retVal/ l+ ## 0 +-- +--%opts: --trace-mode=bin +-- /andthen/ l. ## 0 +-- +--%opts: --trace-mode=src +-- /andthen/ l! ## eF- diff --git a/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/test.py b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/test.py new file mode 100644 index 000000000..13284503b --- /dev/null +++ b/testsuite/tests/limits/Ada/mcdc/Andthen/JC16_008-ComponentDefault/test.py @@ -0,0 +1,13 @@ +import re + +from SCOV.tc import TestCase +from SUITE.context import thistest + + +TestCase( + tolerate_messages=re.escape( + "!!! andthen.adb:4:26: gnatcov limitation: cannot find local" + " declarative part for MC/DC" + ) +).run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 8530d711c..ce035f9e3 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -3660,6 +3660,13 @@ package body Instrument.Ada_Unit is -- -- This also processes any nested declare expressions. + procedure Process_Expression_No_MCDC + (UIC : in out Ada_Unit_Inst_Context; N : Ada_Node'Class; T : Character); + -- Wrapper around Process_Expression that temporarily removes the MCDC + -- state inserter. This convenience function allows to process expressions + -- in contexts where we know that we cannot insert MCDC state variables + -- (instrumenter limitation). + procedure Process_Formal_Default_Exprs (UIC : in out Ada_Unit_Inst_Context; N_Spec : Subp_Spec); -- Process default expressions for formals in N_Spec @@ -3755,6 +3762,9 @@ package body Instrument.Ada_Unit is -- Additional specific processing for the case of degenerate -- subprograms (null procedures and expression functions). + procedure Traverse_Component_List (CL : Component_List); + -- Traverse a list of components (if a type declaration) + ------------------------------------------ -- Utility functions for node synthesis -- ------------------------------------------ @@ -4870,6 +4880,40 @@ package body Instrument.Ada_Unit is Remove_Child (Stub); end Traverse_Degenerate_Subprogram; + ----------------------------- + -- Traverse_Component_List -- + ----------------------------- + + procedure Traverse_Component_List (CL : Component_List) is + begin + for N of CL.F_Components loop + if N.Kind = Ada_Component_Decl then + declare + C : constant Component_Decl := N.As_Component_Decl; + begin + -- The component definition may contain an arbitrary + -- expression in its type expression. This expression is + -- evaluated as part as the type elaboration, so its MC/DC + -- coverage can be computed using a variable in the local + -- context. + -- + -- However, the default expression is evaluated when + -- creating a record value, so there is no appropriate room + -- to insert the MC/DC local state variable. + + Process_Expression (UIC, C.F_Component_Def.As_Ada_Node, 'X'); + Process_Expression_No_MCDC (UIC, C.F_Default_Expr, 'X'); + end; + end if; + end loop; + + if not CL.F_Variant_Part.Is_Null then + for V of CL.F_Variant_Part.F_Variant loop + Traverse_Component_List (V.F_Components); + end loop; + end if; + end Traverse_Component_List; + -------------------------------- -- Traverse_Subp_Decl_Or_Stub -- -------------------------------- @@ -5044,6 +5088,11 @@ package body Instrument.Ada_Unit is end; end; + when Ada_Ada_Node_List => + for Child of N.As_Ada_Node_List loop + Traverse_One (Child.As_Ada_Node); + end loop; + -- Package declaration when Ada_Package_Decl => @@ -5610,6 +5659,57 @@ package body Instrument.Ada_Unit is Traverse_Sync_Definition (UIC, N); + when Ada_Base_Subtype_Decl + | Ada_Incomplete_Type_Decl + | Ada_Type_Decl + => + -- Instrument the type declaration itself as a statement + + declare + Typ : Character; + begin + if N.Kind = Ada_Subtype_Decl then + Typ := 's'; + else + Typ := 't'; + Process_Contract (UIC, N.As_Basic_Decl, "Type_Invariant"); + end if; + + Instrument_Statement (UIC, N, Typ); + end; + + -- Process any embedded decisions + + if N.Kind /= Ada_Concrete_Type_Decl then + Process_Expression (UIC, N, 'X'); + return; + end if; + + declare + TD : constant Concrete_Type_Decl := N.As_Concrete_Type_Decl; + begin + -- For concrete type declarations, the discriminant default + -- expression may contain decisions, but is not evaluated + -- during the type elaboration, so we cannot insert a MC/DC + -- state variable here. + + Process_Expression_No_MCDC (UIC, TD.F_Discriminants, 'X'); + + -- Default expressions for regular components behave the + -- same: process them accordingly. + + if TD.F_Type_Def.Kind = Ada_Record_Type_Def then + Traverse_Component_List + (TD + .F_Type_Def + .As_Record_Type_Def + .F_Record_Def + .F_Components); + else + Process_Expression (UIC, TD.F_Type_Def, 'X'); + end if; + end; + when Ada_Named_Stmt => Traverse_One (N.As_Named_Stmt.F_Stmt.As_Ada_Node); @@ -5657,14 +5757,6 @@ package body Instrument.Ada_Unit is Typ : Character; begin case N.Kind is - when Ada_Base_Type_Decl => - if N.Kind = Ada_Subtype_Decl then - Typ := 's'; - else - Typ := 't'; - Process_Contract - (UIC, N.As_Basic_Decl, "Type_Invariant"); - end if; -- Entity declaration nodes that may also be used -- for entity renamings. @@ -7285,6 +7377,21 @@ package body Instrument.Ada_Unit is end if; end Process_Expression; + -------------------------------- + -- Process_Expression_No_MCDC -- + -------------------------------- + + procedure Process_Expression_No_MCDC + (UIC : in out Ada_Unit_Inst_Context; N : Ada_Node'Class; T : Character) + is + UIC_SI : Any_MCDC_State_Inserter renames UIC.MCDC_State_Inserter; + Saved_SI : constant Any_MCDC_State_Inserter := UIC_SI; + begin + UIC_SI := null; + Process_Expression (UIC, N, T); + UIC_SI := Saved_SI; + end Process_Expression_No_MCDC; + ---------------------------------- -- Process_Formal_Default_Exprs -- ---------------------------------- @@ -10242,9 +10349,13 @@ package body Instrument.Ada_Unit is Enclosing_Decision (Condition); begin -- If the number of paths in the decision binary diagram - -- exceeds the path count limit, we do not instrument it. + -- exceeds the path count limit or if we could not find a + -- way to create a MC/DC state local variable to track + -- the path, we do not instrument the condition. - if Path_Count (Decision) > Get_Path_Count_Limit then + if SC.State = "" + or else Path_Count (Decision) > Get_Path_Count_Limit + then Set_Decision_SCO_Non_Instr_For_MCDC (Decision); else Insert_Condition_Witness From bb2b948cc984993279545d5ee63e0844618c6bd9 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 22 Aug 2025 18:06:11 +0200 Subject: [PATCH 1387/1483] instr-setup_config: Save Manual_Indication_Files in dump_config.json --- tools/gnatcov/instrument-setup_config.adb | 29 ++++++++++++++++++++++- 1 file changed, 28 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/instrument-setup_config.adb b/tools/gnatcov/instrument-setup_config.adb index e40083aa4..5b4245be0 100644 --- a/tools/gnatcov/instrument-setup_config.adb +++ b/tools/gnatcov/instrument-setup_config.adb @@ -311,11 +311,26 @@ package body Instrument.Setup_Config is -- command line. declare - Dump_Config_JSON : constant JSON_Value := Create_Object; + Dump_Config_JSON : constant JSON_Value := Create_Object; + Manual_Dump_Files_JSON : JSON_Array; begin case Dump_Config.Trigger is when Manual => Dump_Config_JSON.Set_Field ("dump-trigger", "manual"); + if Dump_Config.Manual_Indication_Files.Is_Empty then + Outputs.Fatal_Error + ("Manual dump trigger FILES indication is missing," + & " mandatory in integrated instrumentation mode:" + & " --dump-trigger=manual,FILES"); + else + for Manual_Dump_File of Dump_Config.Manual_Indication_Files + loop + Append (Manual_Dump_Files_JSON, + Create (Display_Full_Name (Manual_Dump_File))); + end loop; + Dump_Config_JSON.Set_Field ("manual-dump-files", + Manual_Dump_Files_JSON); + end if; when At_Exit => Dump_Config_JSON.Set_Field ("dump-trigger", "atexit"); when Ravenscar_Task_Termination => @@ -449,6 +464,18 @@ package body Instrument.Setup_Config is Dump_Config.Trigger := Ravenscar_Task_Termination; elsif Dump_Trigger_Str = "manual" then Dump_Config.Trigger := Manual; + if Dump_Config_JSON.Has_Field ("manual-dump-files") then + declare + Manual_Dump_Files_JSON : constant JSON_Array := + Dump_Config_JSON.Get ("manual-dump-files"); + begin + for Manual_Dump_File_JSON of Manual_Dump_Files_JSON loop + Dump_Config.Manual_Indication_Files.Include + (Create_From_UTF8 + (String'(Get (Manual_Dump_File_JSON)))); + end loop; + end; + end if; else Outputs.Fatal_Error ("unsupported dump trigger"); end if; From 3864031be09b24bdf0af9d7175bfbe4c8c08f6af Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 26 Aug 2025 12:46:17 +0200 Subject: [PATCH 1388/1483] instr: Change Replace_Manual_Indications spec to use Virtual_File instead of GPR2.Source object --- tools/gnatcov/instrument-ada_unit.adb | 18 +++++++++++------- tools/gnatcov/instrument-ada_unit.ads | 4 ++-- tools/gnatcov/instrument-c.adb | 22 +++++++++++----------- tools/gnatcov/instrument-c.ads | 3 +-- tools/gnatcov/instrument-common.adb | 2 +- tools/gnatcov/instrument-common.ads | 3 ++- tools/gnatcov/instrument-projects.adb | 2 +- 7 files changed, 29 insertions(+), 25 deletions(-) diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index ce035f9e3..fc6b8199b 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -9686,14 +9686,13 @@ package body Instrument.Ada_Unit is overriding procedure Replace_Manual_Indications (Self : in out Ada_Instrumenter_Type; Prj : in out Prj_Desc; - Source : GPR2.Build.Source.Object; + Source : Virtual_File; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean) is Instrumented_Filename : constant String := - +(Prj.Output_Dir & "/" & String (Source.Path_Name.Simple_Name)); - Source_Filename : constant String := - String (Source.Path_Name.Value); + +(Prj.Output_Dir & "/" & (+Source.Base_Name)); + Source_Filename : constant String := +Source.Full_Name; Instrumented_Exists : constant Boolean := Ada.Directories.Exists (Instrumented_Filename); File_To_Search : constant String := (if Instrumented_Exists @@ -10455,7 +10454,8 @@ package body Instrument.Ada_Unit is Qualified_Name_Slug (Project_Name, Use_Hash => False); begin return Ada_Identifier_Vectors."&" - (Sys_Prefix, Instrument.Ada_Identifier (+Project_Name_Slug)); + (Sys_Prefix, + Ada_Identifier (Unbounded_String'(+Project_Name_Slug))); end Buffers_List_Unit; ----------------- @@ -10468,7 +10468,9 @@ package body Instrument.Ada_Unit is Simple_Name : Ada_Identifier; begin Append (Simple_Name, "B"); - Append (Simple_Name, Ada_Identifier (+Qualified_Name_Slug (Unit_Name))); + Append + (Simple_Name, + Ada_Identifier (Unbounded_String'(+Qualified_Name_Slug (Unit_Name)))); return CU_Name : Ada_Qualified_Name := Sys_Prefix do CU_Name.Append (Simple_Name); end return; @@ -10484,7 +10486,9 @@ package body Instrument.Ada_Unit is Simple_Name : Instrument.Ada_Identifier; begin Append (Simple_Name, 'P'); - Append (Simple_Name, Ada_Identifier (+Qualified_Name_Slug (Unit_Name))); + Append + (Simple_Name, + Ada_Identifier (Unbounded_String'(+Qualified_Name_Slug (Unit_Name)))); return CU_Name : Ada_Qualified_Name := Sys_Prefix do CU_Name.Append (Simple_Name); end return; diff --git a/tools/gnatcov/instrument-ada_unit.ads b/tools/gnatcov/instrument-ada_unit.ads index c50aaf673..e8dd5f488 100644 --- a/tools/gnatcov/instrument-ada_unit.ads +++ b/tools/gnatcov/instrument-ada_unit.ads @@ -30,7 +30,7 @@ with Libadalang.Config_Pragmas; use Libadalang.Config_Pragmas; with Libadalang.Rewriting; use Libadalang.Rewriting; with GNATCOLL.Refcount; use GNATCOLL.Refcount; -with GNATCOLL.VFS; +with GNATCOLL.VFS; use GNATCOLL.VFS; with Files_Handling; use Files_Handling; with Files_Table; use Files_Table; @@ -98,7 +98,7 @@ package Instrument.Ada_Unit is overriding procedure Replace_Manual_Indications (Self : in out Ada_Instrumenter_Type; Prj : in out Prj_Desc; - Source : GPR2.Build.Source.Object; + Source : Virtual_File; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean); -- Once the instrumentation has finished, if the dump trigger is "manual" diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index a6a05abae..3f6a61341 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -151,7 +151,7 @@ package body Instrument.C is -- a file. procedure Preprocess_And_Record_Include_Paths - (Source : GPR2.Build.Source.Object; + (Source : Virtual_File; Instrumenter : C_Family_Instrumenter_Type'Class; Prj : in out Prj_Desc; PP_Filename : out Unbounded_String); @@ -3269,13 +3269,13 @@ package body Instrument.C is ----------------------------------------- procedure Preprocess_And_Record_Include_Paths - (Source : GPR2.Build.Source.Object; + (Source : Virtual_File; Instrumenter : C_Family_Instrumenter_Type'Class; Prj : in out Prj_Desc; PP_Filename : out Unbounded_String) is Options : Analysis_Options; - Filename : constant String := String (Source.Path_Name.Value); + Filename : constant String := +Source.Full_Name; begin Preprocess_Source (Filename, Instrumenter, Prj, PP_Filename, Options); @@ -3291,7 +3291,7 @@ package body Instrument.C is for Path of Options.PP_Search_Path loop Prj.Compiler_Options_Unit.Insert - (Key => Create (+String (Source.Path_Name.Value)), + (Key => Source, New_Item => String_Vectors.Empty_Vector, Position => Cur, Inserted => Inserted); @@ -4691,7 +4691,7 @@ package body Instrument.C is overriding procedure Replace_Manual_Indications (Self : in out C_Family_Instrumenter_Type; Prj : in out Prj_Desc; - Source : GPR2.Build.Source.Object; + Source : Virtual_File; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean) is @@ -4708,7 +4708,7 @@ package body Instrument.C is C_Family_Instrumenter_Type'Class (Self).Extern_Prefix; Annots : constant Instr_Annotation_Map := - Get_Buffer_Annotations (String (Source.Path_Name.Value)); + Get_Buffer_Annotations (+Source.Full_Name); Annot_Mapping : Sloc_To_Index_Maps.Map; -- Mapping from source locations of the annotations in the @@ -4768,7 +4768,7 @@ package body Instrument.C is for Annot_Cur in Annots.Iterate loop Annot_Mapping.Insert (Instr_Annotation_Maps.Key (Annot_Cur), 0); end loop; - Remap_Locations (Str, String (Source.Path_Name.Value), Annot_Mapping); + Remap_Locations (Str, +Source.Full_Name, Annot_Mapping); Ext_Annot_Cur := Annot_Mapping.First; Has_Dump_Indication := False; @@ -4840,7 +4840,7 @@ package body Instrument.C is if Matches (Buffer_Dump_Group) /= No_Match then Switches.Misc_Trace.Trace ("Found buffer dump indication in file " - & String (Source.Path_Name.Simple_Name)); + & String (Source.Base_Name)); -- If we had a prefix specified in the comment, include it -- in the dump procedure call. Use the project name as the @@ -4861,7 +4861,7 @@ package body Instrument.C is pragma Assert (Matches (Buffer_Reset_Group) /= No_Match); Switches.Misc_Trace.Trace ("Found buffer reset indication in file " - & String (Source.Path_Name.Simple_Name)); + & (+Source.Full_Name)); String'Write (S, Reset_Procedure & "();"); Has_Reset_Indication := True; @@ -4917,7 +4917,7 @@ package body Instrument.C is if Has_Element (Ext_Annot_Cur) then Warning_Or_Error ("Some external annotations could not be re-mapped in the" - & " preprocessed version of " & String (Source.Path_Name.Value) + & " preprocessed version of " & (+Source.Full_Name) & ", They have been ignored. Use -v for more details."); while Has_Element (Ext_Annot_Cur) loop declare @@ -4958,7 +4958,7 @@ package body Instrument.C is if not Success then Outputs.Fatal_Error ("Failed to replace manual dump indication for Source " - & String (Source.Path_Name.Value)); + & (+Source.Full_Name)); end if; end; else diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index cc6e57dae..6a3c07e88 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -25,7 +25,6 @@ with Ada.Finalization; with Namet; use Namet; with GNATCOLL.VFS; use GNATCOLL.VFS; -with GPR2.Build.Source; with Clang.CX_Source_Location; use Clang.CX_Source_Location; with Clang.Index; use Clang.Index; @@ -68,7 +67,7 @@ package Instrument.C is overriding procedure Replace_Manual_Indications (Self : in out C_Family_Instrumenter_Type; Prj : in out Prj_Desc; - Source : GPR2.Build.Source.Object; + Source : Virtual_File; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean); -- Preprocess Source and look through the text content of the preprocessed diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 2b9491fbe..77abd34a3 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -829,7 +829,7 @@ package body Instrument.Common is procedure Replace_Manual_Indications (Self : in out Language_Instrumenter; Prj : in out Prj_Desc; - Source : GPR2.Build.Source.Object; + Source : Virtual_File; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean) is begin diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index f0708f048..e8820311e 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -57,6 +57,7 @@ with Ada.Containers.Vectors; with GNAT.Regpat; use GNAT.Regpat; with GNATCOLL.JSON; use GNATCOLL.JSON; +with GNATCOLL.VFS; use GNATCOLL.VFS; with Files_Handling; use Files_Handling; with Files_Table; use Files_Table; @@ -537,7 +538,7 @@ package Instrument.Common is procedure Replace_Manual_Indications (Self : in out Language_Instrumenter; Prj : in out Prj_Desc; - Source : GPR2.Build.Source.Object; + Source : Virtual_File; Has_Dump_Indication : out Boolean; Has_Reset_Indication : out Boolean); -- Look for the pragmas (for Ada) or comments (for C family languages) diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 7713a4951..0f800f246 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -947,7 +947,7 @@ is begin Instrumenter.Replace_Manual_Indications (Prj_Info.Desc, - Source, + Source.Path_Name.Virtual_File, Had_Dump_Indication, Had_Reset_Indication); From 9b64b0fd6fbf6f4b9405a8eb8ec70a05392851a9 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 25 Aug 2025 10:48:12 +0200 Subject: [PATCH 1389/1483] instr-gcc-wrapper: Handle manual-dump-trigger in integrated mode --- tools/gnatcov/command_line.ads | 5 +- tools/gnatcov/instrument-gcc_wrapper.adb | 75 +++++++++++++++++++++--- 2 files changed, 71 insertions(+), 9 deletions(-) diff --git a/tools/gnatcov/command_line.ads b/tools/gnatcov/command_line.ads index a706a5301..b8dd06e0b 100644 --- a/tools/gnatcov/command_line.ads +++ b/tools/gnatcov/command_line.ads @@ -958,7 +958,10 @@ package Command_Line is & " determines the dump procedure." & ASCII.LF & ASCII.LF & "Only the last occurrence of" & " the switch is taken into account.", - Commands => (Cmd_Setup | Cmd_Instrument => True, others => False), + Commands => (Cmd_Setup + | Cmd_Setup_Integration + | Cmd_Instrument => True, + others => False), At_Most_Once => False, Pattern => "manual[,FILES]|atexit|main-end", Internal => False), diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 6526a0d4d..a86731289 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -775,6 +775,15 @@ is Has_Link_Command : Boolean := False; -- Indicates whether the compiler driver command creates an executable + Manual_Dump_Helper_Generated : Boolean := False; + -- When in manual dump trigger mode, true if we instrumented a file with a + -- dump or reset indication. + + Manual_Dump_Helper_Unit_Name : Unbounded_String; + -- When in manual dump trigger mode, holds the name of the manual dump + -- helper unit. It is only generated and valid when + -- `Manual_Dump_Helper_Generated` is True. + -- Start of processing for Compiler_Wrappers.GCC begin @@ -894,9 +903,54 @@ begin end; end if; - -- Then, instrument it as a main if it is one + if Instr_Config.Dump_Config.Trigger = Manual then + -- When in manual dump trigger mode, check if the current file is + -- expected to contain a manual dump/reset indication. + + declare + V_File : constant Virtual_File := Create_From_UTF8 (Fullname); + Has_Dump_Indication : Boolean := False; + Has_Reset_Indication : Boolean := False; + begin + if Instr_Config.Dump_Config.Manual_Indication_Files + .Contains (V_File) + then + -- If the file is expected to contain indications, run the + -- substitution engine and find out if substitutions where + -- indeed made. + + Instrumenter.Replace_Manual_Indications + (Prj, V_File, Has_Dump_Indication, Has_Reset_Indication); - if Instrumenter.Has_Main (Fullname, Prj) then + if Has_Dump_Indication or else Has_Reset_Indication then + if not Manual_Dump_Helper_Generated then + + -- Compute the dump helper file name. + + Manual_Dump_Helper_Unit_Name := + Instrumenter.Dump_Manual_Helper_Unit + (Prj).Unit_Name; + + -- Generate the dump helper file. + + Instrumenter.Emit_Dump_Helper_Unit_Manual + (Instr_Config.Dump_Config, Prj); + + -- Set the Manual_Dump_Helper_Generated flag to avoid + -- re-emitting the dump helper. + + Manual_Dump_Helper_Generated := True; + end if; + + Comp_Command_Ref.Instrumentation_Sources.Append + (Manual_Dump_Helper_Unit_Name); + end if; + + Instrumented_Files.Include (+Fullname); + end if; + end; + elsif Instrumenter.Has_Main (Fullname, Prj) then + -- Then, instrument it as a main if it is one -- Pick as the trace name prefix the base name of the main -- filename @@ -908,13 +962,18 @@ begin Instrumenter.Auto_Dump_Buffers_In_Main (Instr_Name, Instr_Config.Dump_Config, Prj); - Comp_Command_Ref.Instrumentation_Sources.Append - (Instrumenter.Dump_Helper_Unit - (Compilation_Unit' - (File_Based_Language, +Instr_Name), - Prj) - .Unit_Name); + + declare + Unit_Name : constant Unbounded_String := + Instrumenter.Dump_Helper_Unit + (Compilation_Unit'(File_Based_Language, +Instr_Name), + Prj).Unit_Name; + begin + Comp_Command_Ref.Instrumentation_Sources.Append (Unit_Name); + end; + Instrumented_Files.Include (+Fullname); + end if; end; end loop; From 23b256852f7597361241057bc94fdcd4e9757fa1 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Tue, 26 Aug 2025 19:21:46 +0200 Subject: [PATCH 1390/1483] tests: Add tests for manual dump trigger in integrated instrumentation --- .../manual_dump/foo.cpp | 22 ++++++ .../manual_dump/foo.hh | 7 ++ .../manual_dump/main.cpp | 11 +++ .../manual_dump/test.py | 68 +++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 testsuite/tests/integrated_instrumentation/manual_dump/foo.cpp create mode 100644 testsuite/tests/integrated_instrumentation/manual_dump/foo.hh create mode 100644 testsuite/tests/integrated_instrumentation/manual_dump/main.cpp create mode 100644 testsuite/tests/integrated_instrumentation/manual_dump/test.py diff --git a/testsuite/tests/integrated_instrumentation/manual_dump/foo.cpp b/testsuite/tests/integrated_instrumentation/manual_dump/foo.cpp new file mode 100644 index 000000000..b8f3853fe --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/manual_dump/foo.cpp @@ -0,0 +1,22 @@ +#include "foo.hh" + +#include +#include + +void +foo_dump (void) +{ + /* GNATCOV_DUMP_BUFFERS */ +} + +void +foo_warn (const char *s) +{ + std::cout << "WARN :" << s << std::endl; +} + +void +foo_error (const char *s) +{ + std::cout << "ERROR:" << s << std::endl; +} diff --git a/testsuite/tests/integrated_instrumentation/manual_dump/foo.hh b/testsuite/tests/integrated_instrumentation/manual_dump/foo.hh new file mode 100644 index 000000000..1387c9932 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/manual_dump/foo.hh @@ -0,0 +1,7 @@ +#pragma once + +void foo_dump (void); + +void foo_warn (const char *s); + +void foo_error (const char *s); diff --git a/testsuite/tests/integrated_instrumentation/manual_dump/main.cpp b/testsuite/tests/integrated_instrumentation/manual_dump/main.cpp new file mode 100644 index 000000000..9cee91bd4 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/manual_dump/main.cpp @@ -0,0 +1,11 @@ +#include + +#include "foo.hh" + +int +main () +{ + foo_warn ("Hello there"); + foo_dump (); + foo_error ("General Kenobi"); +} diff --git a/testsuite/tests/integrated_instrumentation/manual_dump/test.py b/testsuite/tests/integrated_instrumentation/manual_dump/test.py new file mode 100644 index 000000000..03fc285c4 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/manual_dump/test.py @@ -0,0 +1,68 @@ +""" +Ensure the manual dump trigger flag works as expected in integrated +instrumentation mode. +""" + +import os + +from SCOV.minicheck import check_xcov_reports +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import cmdrun, srctracename_for, thistest, xcov + +Wdir("tmp_") + +CXX = "g++" +CXX_OUTPUT = "cc.out" +BIN = "main" + +# Setup the instrumentation process +xcov( + [ + "setup-integration", + "--level=stmt", + "--files=../foo.cpp", + f"--compilers={CXX}", + "--dump-trigger=manual,../foo.cpp", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=os.getcwd()) + +cmdrun( + [ + CXX, + "-o", + BIN, + os.path.join("..", "main.cpp"), + os.path.join("..", "foo.cpp"), + "-I../", + ], + out=CXX_OUTPUT, + for_pgm=False, +) + + +thistest.fail_if_not_equal( + "compiler output", + "", + contents_of(CXX_OUTPUT), +) + +# Run the executable +cmdrun([BIN], for_pgm=False) + +# Check coverage expectations +xcov( + [ + "coverage", + "--level=stmt", + "--sid=foo.cpp.sid", + "-axcov", + srctracename_for(BIN), + ] +) +check_xcov_reports(".", {"foo.cpp.xcov": {"-": {21}}}) + +thistest.result() From 5fd3bda373252ab12d997acf0386df5c4958b2e9 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 27 Aug 2025 13:45:04 +0000 Subject: [PATCH 1391/1483] Qualif/Ada/stmt/1_Core/13_.../OpAttributes/Read_Write: remove XFAIL --- .../1_Core/13_Representation/OpAttributes/Read_Write/test.opt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/test.opt diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/test.opt b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/test.opt deleted file mode 100644 index de636efbf..000000000 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/Read_Write/test.opt +++ /dev/null @@ -1 +0,0 @@ -all-warnings XFAIL U916-020: bug in libadalang From fa393f016d5d58a3de4c85b3cbaea9787dd3f8ab Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 22 Aug 2025 14:29:00 +0200 Subject: [PATCH 1392/1483] Merge branch 'eyraud/320' into 'master' Support compilation units with varying SCOs See merge request eng/das/cov/gnatcoverage!711 For eng/das/cov/gnatcoverage#320 --- testsuite/SCOV/internals/driver.py | 51 +- testsuite/SCOV/tc.py | 5 + .../tests/207-srctrace-version/foo.c.sid | Bin 1179 -> 1186 bytes testsuite/tests/207-srctrace-version/main.sid | Bin 1406 -> 1422 bytes .../207-srctrace-version/reference.srctrace | Bin 336 -> 336 bytes testsuite/tests/320-varying-scos/extra.opt | 1 + .../320-varying-scos/varying_header/src/bar.c | 2 + .../320-varying-scos/varying_header/src/foo.c | 2 + .../320-varying-scos/varying_header/src/foo.h | 15 + .../varying_header/src/main.c | 5 + .../320-varying-scos/varying_header/test.py | 29 + .../varying_in_scope/src/bar.c | 2 + .../varying_in_scope/src/foo.c | 2 + .../varying_in_scope/src/foo.h | 10 + .../varying_in_scope/src/main.c | 5 + .../320-varying-scos/varying_in_scope/test.py | 54 + .../320-varying-scos/varying_meta/src/bar.c | 2 + .../320-varying-scos/varying_meta/src/foo.c | 2 + .../320-varying-scos/varying_meta/src/foo.h | 6 + .../varying_meta/src/test_1.c | 12 + .../320-varying-scos/varying_meta/test.py | 35 + .../varying_source/src1/main.adb | 6 + .../varying_source/src2/main.adb | 6 + .../320-varying-scos/varying_source/test.py | 71 + .../varying_source_ckpt/main.c | 10 + .../varying_source_ckpt/test.py | 48 + .../main.adb.xml.expected | 36 +- .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 1508 -> 1508 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2580 -> 2580 bytes .../gen/arm-elf-linux/main_1.sid | Bin 421 -> 445 bytes .../gen/arm-elf-linux/main_2.sid | Bin 421 -> 445 bytes .../gen/arm-elf-linux/pkg.sid | Bin 1102 -> 1150 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1879 -> 1831 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1889 -> 1841 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 2088 -> 2422 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 2019 -> 2353 bytes .../gen/x86_64-windows/main_1.sid | Bin 423 -> 447 bytes .../gen/x86_64-windows/main_2.sid | Bin 423 -> 447 bytes .../gen/x86_64-windows/pkg.sid | Bin 1106 -> 1154 bytes tools/gnatcov/annotations-dynamic_html.adb | 8 +- tools/gnatcov/annotations-xml.adb | 6 +- tools/gnatcov/annotations.adb | 34 +- tools/gnatcov/annotations.ads | 4 +- tools/gnatcov/checkpoints.ads | 6 +- tools/gnatcov/coverage-source.adb | 48 +- tools/gnatcov/files_table.adb | 29 + tools/gnatcov/files_table.ads | 19 +- tools/gnatcov/gnatcov_bits_specific.adb | 8 + tools/gnatcov/instrument-ada_unit.adb | 79 +- tools/gnatcov/instrument-c.adb | 98 +- tools/gnatcov/instrument-common.adb | 19 - tools/gnatcov/instrument-common.ads | 6 - tools/gnatcov/instrument-projects.adb | 27 +- tools/gnatcov/sc_obligations.adb | 2278 +++++++++++------ tools/gnatcov/sc_obligations.ads | 116 +- tools/gnatcov/slocs.ads | 4 +- 56 files changed, 2105 insertions(+), 1101 deletions(-) create mode 100644 testsuite/tests/320-varying-scos/extra.opt create mode 100644 testsuite/tests/320-varying-scos/varying_header/src/bar.c create mode 100644 testsuite/tests/320-varying-scos/varying_header/src/foo.c create mode 100644 testsuite/tests/320-varying-scos/varying_header/src/foo.h create mode 100644 testsuite/tests/320-varying-scos/varying_header/src/main.c create mode 100644 testsuite/tests/320-varying-scos/varying_header/test.py create mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/src/bar.c create mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/src/foo.c create mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/src/foo.h create mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/src/main.c create mode 100644 testsuite/tests/320-varying-scos/varying_in_scope/test.py create mode 100644 testsuite/tests/320-varying-scos/varying_meta/src/bar.c create mode 100644 testsuite/tests/320-varying-scos/varying_meta/src/foo.c create mode 100644 testsuite/tests/320-varying-scos/varying_meta/src/foo.h create mode 100644 testsuite/tests/320-varying-scos/varying_meta/src/test_1.c create mode 100644 testsuite/tests/320-varying-scos/varying_meta/test.py create mode 100644 testsuite/tests/320-varying-scos/varying_source/src1/main.adb create mode 100644 testsuite/tests/320-varying-scos/varying_source/src2/main.adb create mode 100644 testsuite/tests/320-varying-scos/varying_source/test.py create mode 100644 testsuite/tests/320-varying-scos/varying_source_ckpt/main.c create mode 100644 testsuite/tests/320-varying-scos/varying_source_ckpt/test.py diff --git a/testsuite/SCOV/internals/driver.py b/testsuite/SCOV/internals/driver.py index cec0ea80e..85682af2a 100644 --- a/testsuite/SCOV/internals/driver.py +++ b/testsuite/SCOV/internals/driver.py @@ -676,29 +676,38 @@ def gen_one_xcov_report(self, trace, report_format, options=""): # return. ofile = report_format + ".out" - xcov(args=["coverage"] + covargs, out=ofile) - - # Standard output might typically contain labeling warnings issued - # by the static analysis phase, or error messages issued when a trace - # indicates that some unlabeled edge was taken. None of this should - # happen so we simply fail as soon as the output file is not empty. - # Note that we do this in qualification mode as well, even though what - # we're looking at is not stricly part of the qualified interface. - - # Warnings about -S being deprecated are expected: just ignore them - output_lines = lines_of(ofile) - for i, line in reversed(list(enumerate(output_lines))): - if line == ( - "warning: -S is deprecated. " - "This option will be removed in release 26." - ): - output_lines.pop(i) - output = "\n".join(output_lines) - - thistest.fail_if( - output, f"xcov standard output not empty ({ofile}:\n--\n{output}" + xcov( + args=["coverage"] + covargs, + tolerate_messages=self.testcase.tolerate_cov_messages, + out=ofile, ) + # Only check the output when running with binary traces, as this is + # done in xcov for source traces. + if thistest.options.trace_mode == "bin": + # Standard output might typically contain labeling warnings issued + # by the static analysis phase, or error messages issued when a + # trace indicates that some unlabeled edge was taken. None of this + # should happen so we simply fail as soon as the output file is not + # empty. Note that we do this in qualification mode as well, even + # though what we're looking at is not stricly part of the qualified + # interface. + + # Warnings about -S being deprecated are expected: just ignore them + output_lines = lines_of(ofile) + for i, line in reversed(list(enumerate(output_lines))): + if line == ( + "warning: -S is deprecated. " + "This option will be removed in release 26." + ): + output_lines.pop(i) + output = "\n".join(output_lines) + + thistest.fail_if( + output, + f"xcov standard output not empty ({ofile}:\n--\n{output}", + ) + def force_xcov_report(self, source): filename = self.xcov_translation_for(source) + ".xcov" diff --git a/testsuite/SCOV/tc.py b/testsuite/SCOV/tc.py index 6c777842c..bac14825f 100644 --- a/testsuite/SCOV/tc.py +++ b/testsuite/SCOV/tc.py @@ -137,6 +137,7 @@ def __init__( extracargs="", category=CAT.auto, tolerate_messages=None, + tolerate_cov_messages=None, expect_non_zero_code=False, assert_lvl=None, fun_call_lvl=False, @@ -153,6 +154,10 @@ def __init__( # for xcov_instrument). self.tolerate_messages = tolerate_messages + # Pass tolerate_cov_messages to gnatcov coverage invocations (only when + # using source traces). + self.tolerate_cov_messages = tolerate_cov_messages + # Step 1: Compute the list of drivers and consolidation specs # to exercise # ------------------------------------------------------------ diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid index 962ac59626d19df2295dbccc0a39174f7277e75a..d0ecec554373ef0e8806b3be7e5dd46d7ea16d47 100644 GIT binary patch delta 176 zcmbQuxrkH5-On*3IloLHIU_YWyC6R^uY^HlqDTZQ0|-p)-NM5NW-&1Q|Np;!av-DT z@$HesPk1g@swXnTc*rW?pFpSUfQ&XYv>3bpSy$D(e6M diff --git a/testsuite/tests/207-srctrace-version/main.sid b/testsuite/tests/207-srctrace-version/main.sid index 64111790433a5122d7b93aad01b097da48ed576e..ca05865ae1cfd0c6780f9b69299bfeeb12057b87 100644 GIT binary patch delta 112 zcmeyz)yFO3?&lbioL{DpoRONGU67xdSHd7NQ6yT30S1_X3`P*1xX_r9apFx=M#jm) zjMlthF`zgvSgulfauQ?16z#_Vq=Jj6CXVw}Sa0L1Yf AiU0rr delta 113 zcmeC<{>LTa?&lbioL{DpoRONGU67xdSHd7XQ6$=kk%57M7l^^&{~B@q_a<&-p&t|z zPP$!Zd$+5v8YICC#2|%W#Sbb)Dt19QAd>PBZ?MgS(r1abfX delta 14 Vcmcb>bb)Dt1G52V - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index 0b910a88605bc3f6631834b619c3a63b87379961..8d65dbe4b94a5d8e0b66773112166929960175d1 100644 GIT binary patch delta 71 zcmaFD{e*jh94k9ByAj_+Wkq8{GX@5B1_lOUAT}~EGSxLO*EKL!Ffg|=HLx-?Vc-CY Wa|5x0vAMCKk+HFng~`V9Tvh=gEdZO^C6)jH delta 97 zcmdnXyp&nQ-On*3IloLHIU_YWyC6R^uY^H(qDYh)BLf2i2!lbbG(+K@p4YSY)oyv$ k9iMaTsmDETkObqz64%KxjGU7d7+H}p%fy!klWiFr0Ch$4V2eE5iK ly}KoX1-OI#<*Fmg^-U}QzYEE8WEOtxig003A|8$$p9 diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid index c1f72df6195d71afe8f5ec83b29080a3e60f6b74..49d156be429897c0a3ec5e4525ea72703ced3d24 100644 GIT binary patch delta 183 zcmX@d@sC5q-On*3IloLHIU_YWyC6R^uY^HlqDbq+BZ4Z73=9k)3<4l}O?yRipyR4r zbHZoIDZ3{u<6BsJW8yWFiAM$W->7|2R9D?4=-hhBW$U8*M~Z*{W?*Cj>H%Rm0C7MD zF->-5G-70$T*GL^3$uhBBsW=>QF`(z#yFsnBJ0_nsQ+3Vr1o(|-m>8R_5S+ZuMTe3 IU{YfO05}LV#{d8T delta 122 zcmeyzagIa8-On*3IloLHIU_YWyC6R^uY^H(qDU(jBLfUf+%7*^l0|&-1t!*s*K~v# ynSc@?3{t@kRy27xqckr}2rN9=kU2GTDKNW%4b?sLc^fYD@rpEf=!@ diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt index 3f2e2f96ef23270a97d8168ce0704f50ebe555b8..d01ce8c959310edfdc0079e589d5b4757387aaf0 100644 GIT binary patch delta 254 zcmcc4x13MJ-On*3IloLHIU_YWyC6R^uY^HlqsS9RO=boL1|}c|(JVmB2*hvz;=u4^ zK_*deR-gbI5Q9|1Xpk-x0MY?65`=e5)A{&m+J)ECcr-h|#oIiwU~Hekzz&q)n7oon zMhD1%1CTb5xtu^8ckXv})z)AW*e b>lzp<7+6}F8dw>cDrg%RSs56>Tmqv3Uui7r delta 227 zcmdnU_mEG--On*3IloLHIU_YWyC6R^uY^H(qsS9RF-8Uk1`uWjVkRif!Z2BmNn&y_ zv-D&KW>!;HpfDR$8m0uq2WepeV#XcQbUuEXcH#9j9?i~g@itE^7~5w|E@YMk>Sp0( z2ddzJs^*;B$Rr~YckXv})z=^7a;7+6>tT3Q)dDrg%RSQ!|A91H?58UU>zFy{aO diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 3ce172c4b5218d2c180120df0108517ff5b0342e..309ed84ff45210f78dda60cbd59cb5d97dee8d76 100644 GIT binary patch delta 605 zcmZ1>@J&d>-On*3IloLHIU_YWyC6R^uY^Hlqlh6R8v_t9GEB~9bd6vHGeKMku9ape z+|%=V_P*LJ@4Dl2jy?6b#|=^r10Z!E@E-_ZG~b0){@2dDKbG0F?U&Pm{4BSuJ?)bX znMAaozLNN)eeeDhtCL6HKD2TwViUgJ!^i~G2Erf!HVtg`w^+7V~BB#lF{1lx)McJpSOhVU}7$Ko>=8^#gCC0Xc7p6 z0ORBa77>>|j;n6X37;jW?4GcUZ(;2Xh&-yNL1G|#h4#ER%b%lH^&u+#k$9DI z_?(@+hd`d!f1~zAQC)SHpmXafm#vHLA1VI*n}Lx9s0)Na0PJ~?7eEY_$rqW77+EHB zFk1!+W8p@^?0^Y^XpmL%>?JM@Ik~?R z7uo)Q_j{2AyVAQkAlHhlXM3XlYjKd;#}#?Yg7??^>vz98xH*jZFf)6KzQTt$E>)8i O*hQJl4JMnje*^&Q(XLkj delta 286 zcmew+v_e3{-On*3IloLHIU_YWyC6R^uY^H(qlh6RFCzm30|DOXp26AB- zWDW>0u4%7m4s={~YfktqIc4{RWqb>3Z%kgureMv;0+a?}kQPoL1_8#E9?9Dm@yC49 zyZG6BLy(}|KcATfAPJCpAnU-2C-*WNu|ik}n5`!Bvx;n9!g82dZo=$~8gop_Pl6N* Y0I`voobhmi@W4TM1eY#PjJrpft?3X{c|B*Bh?DFexV zdaKA^xjt*b#D|Z#)(f1!FC{HK1*{)Rz>FitQD#PKzw1gAS$*CTwu6be;CW(|#}z+D zW}rzR3<5AOLU>St$x%!)8p!5@WI=qPJ@3u(=jc^^h)RDXUZos9XJ_vru;<^XeNj|b z-6iPUddg+%qWedRfB$A+WC7{|VGsb@19Ccu!7}+IlMy4!Bxb965EtYYPN>vMkL2x( z_+vilUHojmAxO~fpU+GKpcEK@w1d=g05M2C2!M?PF+diu@UYvl~B3=DusLEFFxNP(?`Sqr2AUwN;Z delta 278 zcmdle^q617-On*3IloLHIU_YWyC6R^uY^H(qlhM>8Y2S(0|$4V2eE5iK ky}KoX1-%UmbdFmg?9U}S^giLVVN+cP!*01U+(8vpv-}7e#f|U4qW7r(Cu!x__kj_iqM9CZHM+h64}>q?u{5C!-M~)8qz5E4YE|Ai2qk ojM9_OF~$Ln6j{&qME%#|AhnMx@|FefulLvQesyrO4wD)a00adrNdN!< delta 122 zcmZqTyu=~m?&lbioL{DpoRONGU67xdSHd7XQKXZLkpTuK?v|f?lUZ!?1tzwMw{(OV ynSc@?3{t@kRy27(qckr}2rN9=mC=Y5!m41jnk>&EI@ywud-5~Jpv^H%YD@rxDHt9A diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 758ceeb2e..08c56eeae 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -600,14 +600,14 @@ package body Annotations.Dynamic_Html is Line_Stats : constant Li_Stat_Array := Line_Metrics (File_Info, - Scope_Ent.Start_Sloc.Line, + Scope_Ent.Source_Range.L.First_Sloc.Line, (if Is_Root then Last_Line (File_Info) - else Scope_Ent.End_Sloc.Line)); + else Scope_Ent.Source_Range.L.Last_Sloc.Line)); -- Adjust Scope_Ent.End_Sloc for the root node as it is -- No_Local_Location by default. - Ob_Stats : constant Ob_Stat_Array := - Obligation_Metrics (Scope_Ent.From, Scope_Ent.To); + Ob_Stats : constant Ob_Stat_Array := + Obligation_Metrics (Get_SCOs (Scope_Ent.Source_Range)); begin Scope_Metrics_JSON.Set_Field ("scopeName", Scope_Ent.Name); Scope_Metrics_JSON.Set_Field ("scopeLine", Scope_Ent.Sloc.Line); diff --git a/tools/gnatcov/annotations-xml.adb b/tools/gnatcov/annotations-xml.adb index a21240e6a..fe30b0996 100644 --- a/tools/gnatcov/annotations-xml.adb +++ b/tools/gnatcov/annotations-xml.adb @@ -586,9 +586,9 @@ package body Annotations.Xml is Line_Stats : constant Li_Stat_Array := Line_Metrics (File_Info, - Scope_Ent.Start_Sloc.Line, + Scope_Ent.Source_Range.L.First_Sloc.Line, (if Is_Root then Last_Line (File_Info) - else Scope_Ent.End_Sloc.Line)); + else Scope_Ent.Source_Range.L.Last_Sloc.Line)); -- Adjust Scope_Ent.End_Sloc for the root node as it is -- No_Local_Location by default. begin @@ -598,7 +598,7 @@ package body Annotations.Xml is Print_Coverage_Li_Stats (Pp, Line_Stats, Dest_Compilation_Unit); Print_Coverage_Ob_Stats (Pp, - Obligation_Metrics (Scope_Ent.From, Scope_Ent.To), + Obligation_Metrics (Get_SCOs (Scope_Ent.Source_Range)), Dest_Compilation_Unit); while Has_Element (Child) loop Pp_Scope_Entity (Child); diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index 0dd05164a..c3a5ec1ea 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -488,10 +488,17 @@ package body Annotations is -- because this depends on violation count for each exempted region. FI.Li_Stats := Line_Metrics (FI, 1, Last_Line (FI)); - FI.Ob_Stats := - Obligation_Metrics - (First_SCO (Comp_Unit (File_Index)), - Last_SCO (Comp_Unit (File_Index))); + + declare + SCOs : SCO_Sets.Set; + begin + for SCO_Range of SCO_Ranges (Comp_Unit (File_Index)) loop + for SCO in SCO_Range.First .. SCO_Range.Last loop + SCOs.Include (SCO); + end loop; + end loop; + FI.Ob_Stats := Obligation_Metrics (SCOs); + end; for J in Global_Stats'Range loop Global_Stats (J) := Global_Stats (J) + FI.Li_Stats (J); @@ -1030,7 +1037,7 @@ package body Annotations is -- Obligation_Metrics -- ------------------------ - function Obligation_Metrics (From, To : SCO_Id) return Ob_Stat_Array + function Obligation_Metrics (SCOs : SCO_Sets.Set) return Ob_Stat_Array is Result : Ob_Stat_Array; @@ -1076,10 +1083,7 @@ package body Annotations is end Update_Level_Stats; begin - if From = No_SCO_Id then - return Result; - end if; - for SCO in From .. To loop + for SCO of SCOs loop case Kind (SCO) is when Statement => Update_Level_Stats (SCO, Get_Line_State (SCO, Stmt), Stmt); @@ -1102,7 +1106,8 @@ package body Annotations is Coverage.Assertion_Condition_Coverage_Enabled and then Is_Assertion (SCO); begin - if Coverage.MCDC_Coverage_Enabled or else Assertion_Decision + if Coverage.MCDC_Coverage_Enabled + or else Assertion_Decision then declare Condition_Level : constant Coverage_Level := @@ -1110,7 +1115,6 @@ package body Annotations is then Coverage.Assertion_Condition_Level else Coverage.MCDC_Level); begin - -- Conditions in that decision for J in @@ -1126,11 +1130,11 @@ package body Annotations is then ATCC else MCDC)); -- If the parent decision is partially covered, - -- then the SCO_State for each condition will be - -- No_Code, and the SCO_State for the + -- then the SCO_State for each condition + -- will be No_Code, and the SCO_State for the -- MCDC/Assertion condition Coverage_Level - -- associated to the parent decision SCO will be - -- Not_Covered. + -- associated to the parent decision SCO will + -- be Not_Covered. Condition_State : SCO_State; diff --git a/tools/gnatcov/annotations.ads b/tools/gnatcov/annotations.ads index a88432b67..8854c6f4b 100644 --- a/tools/gnatcov/annotations.ads +++ b/tools/gnatcov/annotations.ads @@ -319,8 +319,8 @@ private From, To : Natural) return Li_Stat_Array; -- Return line metrics for the given line range - function Obligation_Metrics (From, To : SCO_Id) return Ob_Stat_Array; - -- Return obligation metrics for the given SCO range + function Obligation_Metrics (SCOs : SCO_Sets.Set) return Ob_Stat_Array; + -- Return obligation metrics for the given SCO set function SCO_Kind_Image (SCO : SCO_Id) return String; -- Get the string representation of the SCO_Kind of SCO. A special diff --git a/tools/gnatcov/checkpoints.ads b/tools/gnatcov/checkpoints.ads index 7725c3fd0..5c259b2e0 100644 --- a/tools/gnatcov/checkpoints.ads +++ b/tools/gnatcov/checkpoints.ads @@ -39,7 +39,7 @@ with Traces_Source; use Traces_Source; package Checkpoints is - subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 19; + subtype Checkpoint_Version is Interfaces.Unsigned_32 range 1 .. 20; -- For compatibility with previous Gnatcov versions, the checkpoint -- file format is versioned. -- @@ -63,6 +63,8 @@ package Checkpoints is -- 17 -- Add support for Fun_Call and Guarded Expression coverage -- 18 -- Removed support for tags (separate coverage) -- 19 -- Removed support for instance ids (separate coverage) + -- 20 -- Rework Scope_Entity to identify scopes by their Start/End_Sloc + -- rather than their Start/End_SCO. -- -- Note that we always use the last version when creating a checkpoint. -- @@ -115,7 +117,7 @@ package Checkpoints is (Relocs : in out Checkpoint_Relocations; CP_CU_Id : CU_Id); -- Mark the source file index or compilation unit as ignored in the - -- checkpoint relocation. Tying to remap that source file index or + -- checkpoint relocation. Trying to remap that source file index or -- compilation unit will result in an error. procedure Ignore_SCO diff --git a/tools/gnatcov/coverage-source.adb b/tools/gnatcov/coverage-source.adb index af3c1ca5e..9fa7dcf80 100644 --- a/tools/gnatcov/coverage-source.adb +++ b/tools/gnatcov/coverage-source.adb @@ -220,6 +220,13 @@ package body Coverage.Source is Ignored_SF_Map : Unit_To_Ignored_Maps.Map; -- Map units of interest to the list of associated ignored source files + procedure Initialize_SCI_For_SID + (CU : CU_Id; + SCOs_Fingerprint : SC_Obligations.Fingerprint_Type); + -- Initialize source coverage information vectors for obligations in CU, + -- for SCOs_Fingerprint version, assumed to come from source + -- instrumentation. + -------------------------- -- Basic_Block_Has_Code -- -------------------------- @@ -2192,12 +2199,11 @@ package body Coverage.Source is -- Sanity check that Fingerprint is consistent with what the -- instrumenter recorded in the CU info. - if Fingerprint /= SC_Obligations.Fingerprint (CU) - or else - Bit_Maps_Fingerprint /= SC_Obligations.Bit_Maps_Fingerprint (CU) - or else - Annotations_Fingerprint /= - SC_Obligations.Annotations_Fingerprint (CU) + if not Has_Fingerprint (CU, Fingerprint) + or else Bit_Maps_Fingerprint /= + SC_Obligations.Bit_Maps_Fingerprint (CU, Fingerprint) + or else Annotations_Fingerprint /= + SC_Obligations.Annotations_Fingerprint (CU, Fingerprint) then Warn ("traces for " & Unit_Image & " (from " & Filename & ") are" & " inconsistent with the corresponding Source Instrumentation" @@ -2211,7 +2217,7 @@ package body Coverage.Source is -- Discharge SCOs based on source traces - BM := Bit_Maps (CU); + BM := Bit_Maps (CU, Fingerprint); ST := Scope_Traversal (CU); for J in Stmt_Buffer'Range loop @@ -2227,7 +2233,7 @@ package body Coverage.Source is -- when one of them (which actually is the last) is covered. declare - Stmt_Blocks : SCO_Id_Vector_Vector renames Blocks (CU); + Stmt_Blocks : SCO_Id_Vector_Vector renames Blocks (CU, Fingerprint); Block_Index : Positive; begin if not Stmt_Blocks.Is_Empty then @@ -2473,11 +2479,13 @@ package body Coverage.Source is end if; end Initialize_SCI; - ---------------------------------------- - -- Initialize_SCI_For_Instrumented_CU -- - ---------------------------------------- + ---------------------------- + -- Initialize_SCI_For_SID -- + ---------------------------- - procedure Initialize_SCI_For_Instrumented_CU (CU : CU_Id) is + procedure Initialize_SCI_For_SID + (CU : CU_Id; + SCOs_Fingerprint : SC_Obligations.Fingerprint_Type) is procedure Set_Has_Code (SCO : SCO_Id); -- If SCO is a statement, mark it as having code @@ -2495,7 +2503,7 @@ package body Coverage.Source is end Set_Has_Code; Stmt_Bit_Map : Statement_Bit_Map renames - Bit_Maps (CU).Statement_Bits.all; + Bit_Maps (CU, SCOs_Fingerprint).Statement_Bits.all; -- Start of processing for Initialize_SCI_For_Instrumented_CU @@ -2509,7 +2517,8 @@ package body Coverage.Source is -- instrumented statement SCOs in blocks. declare - Stmt_Blocks : SCO_Id_Vector_Vector renames Blocks (CU); + Stmt_Blocks : SCO_Id_Vector_Vector renames + Blocks (CU, SCOs_Fingerprint); Block_Index : Positive; begin if not Stmt_Blocks.Is_Empty then @@ -2542,6 +2551,17 @@ package body Coverage.Source is end loop; end if; end; + end Initialize_SCI_For_SID; + + ---------------------------------------- + -- Initialize_SCI_For_Instrumented_CU -- + ---------------------------------------- + + procedure Initialize_SCI_For_Instrumented_CU (CU : CU_Id) is + begin + for Fingerprint of SC_Obligations.Fingerprints (CU) loop + Initialize_SCI_For_SID (CU, Fingerprint); + end loop; end Initialize_SCI_For_Instrumented_CU; -------------------------- diff --git a/tools/gnatcov/files_table.adb b/tools/gnatcov/files_table.adb index c7ca599a4..ea1a96e43 100644 --- a/tools/gnatcov/files_table.adb +++ b/tools/gnatcov/files_table.adb @@ -1206,6 +1206,35 @@ package body Files_Table is end; end Get_Line; + -------------- + -- Get_SCOs -- + -------------- + + function Get_SCOs + (Source_Range : Source_Location_Range) return SCO_Sets.Set + is + Result : SCO_Sets.Set; + FI : constant File_Info_Access := + Get_File (Source_Range.Source_File); + Last : constant Positive := Last_Line (FI); + begin + for Line in + Source_Range.L.First_Sloc.Line .. Source_Range.L.Last_Sloc.Line + loop + exit when Line > Last; + declare + SCOs : constant SCO_Id_Array_Acc := Get_Line (FI, Line).SCOs; + begin + if SCOs /= null then + for SCO of SCOs.all loop + Result.Include (SCO); + end loop; + end if; + end; + end loop; + return Result; + end Get_SCOs; + --------------------- -- Get_Simple_Name -- --------------------- diff --git a/tools/gnatcov/files_table.ads b/tools/gnatcov/files_table.ads index f5b73c8e1..5749e6624 100644 --- a/tools/gnatcov/files_table.ads +++ b/tools/gnatcov/files_table.ads @@ -319,7 +319,12 @@ package Files_Table is type Line_Info_Access is access all Line_Info; Empty_Line_Info : constant Line_Info_Access; - type Source_Lines is private; + -- Describe a source file - one element per line + + package Source_Line_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, + Element_Type => Line_Info_Access); + type Source_Lines is new Source_Line_Vectors.Vector with null record; type Any_Ignore_Status is (Unknown, Always, Sometimes, Never); -- Represents the different states a source file can be regarding the @@ -513,7 +518,11 @@ package Files_Table is function Get_Line (Sloc : Source_Location) return Line_Info_Access with Pre => Sloc = Slocs.No_Location - or else Get_File (Sloc.Source_File).Kind in Stub_File | Source_File; + or else Get_File (Sloc.Source_File).Kind in Stub_File | Source_File; + + function Get_SCOs + (Source_Range : Source_Location_Range) return SCO_Sets.Set; + -- Return all of the SCOs under the given Source_Range procedure Set_Encoding (Encoding : String); -- Set the encoding used to interpret source code (this is a global @@ -676,12 +685,6 @@ package Files_Table is -- "-Wimplicit-fallthrough" private - -- Describe a source file - one element per line - - package Source_Line_Vectors is new Ada.Containers.Vectors - (Index_Type => Positive, - Element_Type => Line_Info_Access); - type Source_Lines is new Source_Line_Vectors.Vector with null record; Empty_Line_Info : constant Line_Info_Access := new Line_Info; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index 402cff2e3..b4272f616 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -898,6 +898,14 @@ procedure GNATcov_Bits_Specific is (+Filename, (if Has_Matcher then Matcher'Access else null)); end loop; + -- Then, create source coverage data structure for each loaded unit. + -- Note that this must be done after having loaded every version of + -- the compilation unit, which can be found across SID files. + + for CU in Valid_CU_Id'First .. Last_CU loop + Coverage.Source.Initialize_SCI_For_Instrumented_CU (CU); + end loop; + -- Now that all the scope entities that can be referenced by -- --subprograms are known, dump them if requested. diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index fc6b8199b..45aead92f 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -8150,16 +8150,18 @@ package body Instrument.Ada_Unit is Kind => Files_Table.Source_File, Indexed_Simple_Name => True); New_Scope_Ent : constant Scope_Entity := - (From => SCO_Id (SCOs.SCO_Table.Last + 1), - To => No_SCO_Id, - Start_Sloc => Local_Sloc (Start_Sloc (N.Sloc_Range)), - End_Sloc => Local_Sloc (End_Sloc (N.Sloc_Range)), - Name => + (Source_Range => Slocs.Source_Location_Range' + (Source_File => UIC.SFI, + L => Slocs.Local_Source_Location_Range' + (First_Sloc => Local_Sloc (Start_Sloc (N.Sloc_Range)), + Last_Sloc => Local_Sloc (End_Sloc (N.Sloc_Range)))), + Name => +Langkit_Support.Text.To_UTF8 (Decl.P_Defining_Name.F_Name.Text), - Sloc => Local_Sloc (Sloc (N)), - Identifier => + Sloc => Local_Sloc (Sloc (N)), + Identifier => (Decl_SFI => Decl_SFI, - Decl_Line => Natural (Decl.Sloc_Range.Start_Line))); + Decl_Line => Natural (Decl.Sloc_Range.Start_Line)), + Start_SCO => SCO_Id (SCOs.SCO_Table.Last + 1)); Inserted : Scope_Entities_Trees.Cursor; begin UIC.Scope_Entities.Insert_Child @@ -8177,20 +8179,16 @@ package body Instrument.Ada_Unit is procedure Exit_Scope (UIC : in out Ada_Unit_Inst_Context) is use Scope_Entities_Trees; + Cur_Scope : Scope_Entity renames + Scope_Entities_Trees.Element (UIC.Current_Scope_Entity); Parent_Scope : constant Cursor := Parent (UIC.Current_Scope_Entity); -- Latch the parent value before UIC.Current_Scope_Entity is freed - Scope : constant Reference_Type := - UIC.Scope_Entities.Reference (UIC.Current_Scope_Entity); begin - -- Update the last SCO for this scope entity - - Scope.To := SCO_Id (SCOs.SCO_Table.Last); - -- If the scope has no SCO (it could be possible for a package spec with -- only subprogram declarations for instance), discard it. - if Scope.To < Scope.From then + if SCO_Id (SCOs.SCO_Table.Last) < Cur_Scope.Start_SCO then UIC.Scope_Entities.Delete_Leaf (UIC.Current_Scope_Entity); end if; @@ -10412,11 +10410,6 @@ package body Instrument.Ada_Unit is end loop; Set_Bit_Maps (UIC.CU, Bit_Maps); - - -- Remap low level SCOS in Scope_Entity records to high-level SCOs. - -- See the comment for Scope_Entity.From/To. - - Remap_Scope_Entities (UIC.Scope_Entities, SCO_Map); Set_Scope_Entities (UIC.CU, UIC.Scope_Entities); -- Remap low level SCOs in blocks to high level SCOs @@ -10533,9 +10526,6 @@ package body Instrument.Ada_Unit is CU_Name : constant Compilation_Unit_Part := CU_Names.Element (I); CU : constant CU_Id := CUs.Element (I); - Fingerprint : Unbounded_String; - -- Fingerprint for the instrumented unit - Unit_Name : constant String := Ada.Characters.Handling.To_Lower (To_Ada (CU_Name.Unit)); -- Lower-case name for the instrumented unit @@ -10557,24 +10547,10 @@ package body Instrument.Ada_Unit is Suffix : constant String := "_" & Img (I); - begin - -- Turn the fingerprint value into the corresponding Ada literal - - declare - First : Boolean := True; - begin - Append (Fingerprint, "("); - for Byte of SC_Obligations.Fingerprint (CU) loop - if First then - First := False; - else - Append (Fingerprint, ", "); - end if; - Append (Fingerprint, Strings.Img (Integer (Byte))); - end loop; - Append (Fingerprint, ")"); - end; + SCOs_Fingerprint : constant SC_Obligations.Fingerprint_Type := + SC_Obligations.Fingerprint (CU); + begin -- Create declarations for individual buffers (statement, decision -- and MC/DC) as well as their exported addresses. Put this in -- an individual package, to avoid having to suffix each @@ -10624,24 +10600,25 @@ package body Instrument.Ada_Unit is File.Put_Line (" Buffers : aliased constant" & " GNATcov_RTS_Coverage_Buffers :="); File.Put_Line (" (Fingerprint => " - & Format_Fingerprint - (SC_Obligations.Fingerprint (CU)) - & ","); + & Format_Fingerprint (SCOs_Fingerprint) & ","); File.Put_Line (" Language => Unit_Based_Language,"); File.Put_Line (" Unit_Part => " & Unit_Part & ","); File.Put_Line (" Unit_Name =>" & " (Unit_Name'Address, Unit_Name'Length),"); - File.Put_Line (" Bit_Maps_Fingerprint => " - & Format_Fingerprint - (SC_Obligations.Bit_Maps_Fingerprint (CU)) - & ","); + File.Put_Line + (" Bit_Maps_Fingerprint => " + & Format_Fingerprint + (SC_Obligations.Bit_Maps_Fingerprint (CU, SCOs_Fingerprint)) + & ","); - File.Put_Line (" Annotations_Fingerprint => " - & Format_Fingerprint - (SC_Obligations.Annotations_Fingerprint (CU)) - & ","); + File.Put_Line + (" Annotations_Fingerprint => " + & Format_Fingerprint + (SC_Obligations.Annotations_Fingerprint + (CU, SCOs_Fingerprint)) + & ","); File.Put_Line (" Statement => Statement_Buffer'Address,"); File.Put_Line (" Decision => Decision_Buffer'Address,"); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 3f6a61341..1b2457d26 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -202,15 +202,6 @@ package body Instrument.C is -- generated SCO (SCOs.SCO_Table.Last) is the last SCO for the current -- scope. - procedure Remap_Scopes - (Scopes : in out Scopes_In_Files_Map.Map; - SCO_Map : LL_HL_SCO_Map); - -- Convert low level SCOs in each scope for each file to high-level SCOs - -- using the mapping in SCO_Map. Set the file's SCO range to cover all of - -- its scopes' SCO ranges. - -- - -- Also remove from the Scopes map empty file scopes. - overriding procedure Append_SCO (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; @@ -709,13 +700,17 @@ package body Instrument.C is File_Scope : constant Scopes_In_Files_Map.Reference_Type := UIC.Scopes.Reference (File_Scope_Position); New_Scope_Ent : constant Scope_Entity := - (From => SCO_Id (SCOs.SCO_Table.Last + 1), - To => No_SCO_Id, - Start_Sloc => (Line => 1, Column => 0), - End_Sloc => No_Local_Location, - Name => +Get_Simple_Name (SFI), - Sloc => (Line => 1, Column => 0), - Identifier => (Decl_SFI => SFI, Decl_Line => 0)); + (Source_Range => Source_Location_Range' + (Source_File => SFI, + L => Local_Source_Location_Range' + (First_Sloc => (Line => 1, Column => 0), + Last_Sloc => (Line => Natural'Last, Column => 0))), + Name => +Get_Simple_Name (SFI), + Sloc => (Line => 1, Column => 0), + Identifier => (Decl_SFI => SFI, Decl_Line => 0), + Start_SCO => No_SCO_Id); + -- Set Last_Sloc to Natural'Last so that it defaults to the + -- whole file as long as the scope is not closed. Scope_Entity_Position : Scope_Entities_Trees.Cursor; begin @@ -753,13 +748,15 @@ package body Instrument.C is File_Scope : constant Scopes_In_Files_Map.Reference_Type := UIC.Scopes.Reference (C); New_Scope_Ent : constant Scope_Entity := - (From => SCO_Id (SCOs.SCO_Table.Last + 1), - To => No_SCO_Id, - Start_Sloc => Sloc.L, - End_Sloc => End_Sloc (N).L, + (Source_Range => Source_Location_Range' + (Source_File => File, + L => Local_Source_Location_Range' + (First_Sloc => Sloc.L, + Last_Sloc => End_Sloc (N).L)), Name => +Get_Decl_Name_Str (N), Sloc => Sloc.L, - Identifier => (Decl_SFI => File, Decl_Line => Sloc.L.Line)); + Identifier => (Decl_SFI => File, Decl_Line => Sloc.L.Line), + Start_SCO => No_SCO_Id); Inserted : Scope_Entities_Trees.Cursor; begin -- Add New_Scope_Ent to the children of the last open scope in the @@ -787,59 +784,14 @@ package body Instrument.C is is File_Scope_Ref : constant Scopes_In_Files_Map.Reference_Type := UIC.Scopes.Reference (UIC.Current_File_Scope); - Scope_Entity_Ref : constant Scope_Entities_Trees.Reference_Type := - File_Scope_Ref.Scope_Entities.Reference - (File_Scope_Ref.Current_Scope_Entity); Parent : constant Scope_Entities_Trees.Cursor := Scope_Entities_Trees.Parent (File_Scope_Ref.Current_Scope_Entity); begin - Scope_Entity_Ref.To := SCO_Id (SCOs.SCO_Table.Last); - - -- Discard the scope entity if it has no associated SCOs - - if Scope_Entity_Ref.To < Scope_Entity_Ref.From then - File_Scope_Ref.Scope_Entities.Delete_Leaf - (File_Scope_Ref.Current_Scope_Entity); - else - -- Update the last SCO for the file scope - - File_Scope_Ref.Scope_Entities.Reference - (File_Scope_Ref.File_Scope_Entity).To := Scope_Entity_Ref.To; - end if; - -- Go back to the parent scope entity File_Scope_Ref.Current_Scope_Entity := Parent; end Exit_Scope; - ------------------ - -- Remap_Scopes -- - ------------------ - - procedure Remap_Scopes - (Scopes : in out Scopes_In_Files_Map.Map; - SCO_Map : LL_HL_SCO_Map) - is - Res : Scopes_In_Files_Map.Map; - begin - for Cur in Scopes.Iterate loop - declare - File_Scope : File_Scope_Type := - Scopes_In_Files_Map.Element (Cur); - File_Scope_Entity : Scope_Entity renames - Scope_Entities_Trees.Element (File_Scope.File_Scope_Entity); - begin - -- If the file scope is empty, do not add it to the resulting map - - if File_Scope_Entity.To >= File_Scope_Entity.From then - Remap_Scope_Entities (File_Scope.Scope_Entities, SCO_Map); - Res.Insert (Scopes_In_Files_Map.Key (Cur), File_Scope); - end if; - end; - end loop; - Scopes := Res; - end Remap_Scopes; - ---------------- -- Append_SCO -- ---------------- @@ -4058,8 +4010,6 @@ package body Instrument.C is -- Iterate through the package level body entities - Remap_Scopes (UIC.Scopes, SCO_Map); - for C in UIC.Scopes.Iterate loop declare CU : constant Created_Unit_Maps.Cursor := @@ -4343,6 +4293,10 @@ package body Instrument.C is -- Name of the gnatcov_rts_coverage_buffers struct for this -- source file. + SCOs_Fingerprint : constant SC_Obligations.Fingerprint_Type := + SC_Obligations.Fingerprint (CU); + -- SCOs fingerprint for the unit + begin File.Put_Line ("/* Buffers for " & Get_Full_Name (SFI) & " */"); @@ -4377,7 +4331,7 @@ package body Instrument.C is & Buffers_Struct & " = {" & ASCII.LF & "/* .fingerprint = */ " - & Format_Fingerprint (SC_Obligations.Fingerprint (CU)) & "," + & Format_Fingerprint (SCOs_Fingerprint) & "," & ASCII.LF & "/* .language_kind = */ FILE_BASED_LANGUAGE," & ASCII.LF @@ -4401,13 +4355,15 @@ package body Instrument.C is & ASCII.LF & "/* .bit_maps_fingerprint = */ " - & Format_Fingerprint (SC_Obligations.Bit_Maps_Fingerprint (CU)) + & Format_Fingerprint + (SC_Obligations.Bit_Maps_Fingerprint (CU, SCOs_Fingerprint)) & "," & ASCII.LF & "/* .annotations_fingerprint = */ " & Format_Fingerprint - (SC_Obligations.Annotations_Fingerprint (CU)) + (SC_Obligations.Annotations_Fingerprint + (CU, SCOs_Fingerprint)) & "," & ASCII.LF diff --git a/tools/gnatcov/instrument-common.adb b/tools/gnatcov/instrument-common.adb index 77abd34a3..d1ab2efa0 100644 --- a/tools/gnatcov/instrument-common.adb +++ b/tools/gnatcov/instrument-common.adb @@ -355,25 +355,6 @@ package body Instrument.Common is SCOs.SCO_Table.Last; end Append_SCO; - ------------------------ - -- Remap_Scope_Entity -- - ------------------------ - - procedure Remap_Scope_Entities - (Scope_Entities : in out Scope_Entities_Tree; - SCO_Map : LL_HL_SCO_Map) is - begin - for Scope_Entity in Scope_Entities.Iterate loop - declare - Ref : constant Scope_Entities_Trees.Reference_Type := - Scope_Entities.Reference (Scope_Entity); - begin - Ref.From := SCO_Map (Nat (Ref.From)); - Ref.To := SCO_Map (Nat (Ref.To)); - end; - end loop; - end Remap_Scope_Entities; - ------------------ -- Remap_Blocks -- ------------------ diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index e8820311e..4d3b521fe 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -423,12 +423,6 @@ package Instrument.Common is -- source file, also append a new entry to the SCO_Unit_Table, otherwise -- complete its last entry. - procedure Remap_Scope_Entities - (Scope_Entities : in out Scope_Entities_Tree; - SCO_Map : LL_HL_SCO_Map); - -- Convert low level SCOs in Scope_Entity to high-level SCOs using the - -- mapping in SCO_Map. - procedure Remap_Blocks (Blocks : in out SCO_Id_Vector_Vector; SCO_Map : LL_HL_SCO_Map); diff --git a/tools/gnatcov/instrument-projects.adb b/tools/gnatcov/instrument-projects.adb index 0f800f246..36dd26999 100644 --- a/tools/gnatcov/instrument-projects.adb +++ b/tools/gnatcov/instrument-projects.adb @@ -256,7 +256,7 @@ is -- If an instrumenter supports Source_File's language and if Project is not -- externally built, add Source_File to Project_Sources. - procedure Insert_Manual_Dump_Trigger + procedure Replace_Manual_Indications (Language : Src_Supported_Language; Project_Sources : in out File_Info_Sets.Set; Instrumenter : in out Language_Instrumenter'Class; @@ -883,14 +883,14 @@ is end Add_Instrumented_Unit; -------------------------------- - -- Insert_Manual_Dump_Trigger -- + -- Replace_Manual_Indications -- -------------------------------- - procedure Insert_Manual_Dump_Trigger - (Language : Src_Supported_Language; - Project_Sources : in out File_Info_Sets.Set; - Instrumenter : in out Language_Instrumenter'Class; - Manual_Dump_Inserted : in out Boolean; + procedure Replace_Manual_Indications + (Language : Src_Supported_Language; + Project_Sources : in out File_Info_Sets.Set; + Instrumenter : in out Language_Instrumenter'Class; + Manual_Dump_Inserted : in out Boolean; Manual_Indication_Files : File_Sets.Set) is @@ -1062,7 +1062,7 @@ is & " from a source in a parent project."); end; end if; - end Insert_Manual_Dump_Trigger; + end Replace_Manual_Indications; --------------------- -- Clean_And_Print -- @@ -1292,13 +1292,20 @@ begin -- Replace manual dump indications for C-like languages for Lang in C_Family_Language loop - Insert_Manual_Dump_Trigger + Replace_Manual_Indications (Lang, Project_Sources, Instrumenters (Lang).all, Manual_Dump_Inserted, Dump_Config.Manual_Indication_Files); end loop; + + -- The replacement of manual indications may incur filling of e.g. + -- the files table, which is then dumped into the first written + -- checkpoint before being cleared out. Preemptively clear it to avoid + -- that. + + Checkpoints.Checkpoint_Clear; end if; -- Write the files of interest to temporary files in the instrumentation @@ -1613,7 +1620,7 @@ begin end; if Dump_Config.Trigger = Manual then - Insert_Manual_Dump_Trigger + Replace_Manual_Indications (Ada_Language, Project_Sources, Ada_Instrumenter, diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index c9710c4c6..6cad5f7db 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -23,6 +23,7 @@ with Ada.Strings.Fixed; use Ada.Strings.Fixed; with Ada.Text_IO; use Ada.Text_IO; with Ada.Unchecked_Deallocation; +with GNATCOLL.VFS; with Interfaces; with Aspects; use Aspects; @@ -34,7 +35,6 @@ with Snames; with Checkpoints; use Checkpoints; with Coverage; use Coverage; -with Coverage.Source; with Diagnostics; use Diagnostics; with Files_Table; use Files_Table; with Inputs; use Inputs; @@ -64,8 +64,13 @@ package body SC_Obligations is -- * properly ordered: if E1 and E2 are consecutive siblings, E1.To must be -- smaller than E2.From. + function Floor + (Tree : Scope_Entities_Trees.Tree; + Sloc : Source_Location) return Scope_Entities_Trees.Cursor; + -- Return the innermost scope containing Sloc + function Covers_SCO (SE : Scope_Entity; SCO : SCO_Id) return Boolean - is (SCO in SE.From .. SE.To); + is (In_Range (First_Sloc (SCO), SE.Source_Range)); -- Return whether SCO is covered by SE's SCO range function Covers_SCO @@ -73,9 +78,12 @@ package body SC_Obligations is -- Return whether SCO is covered by that element's SCO range. Id the SCO is -- a function SCO, then the scope can be the root of the tree. - procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) with - Pre => Get_CU (ST) = No_CU_Id - or else SCO in First_SCO (Get_CU (ST)) .. Last_SCO (Get_CU (ST)); + function Contains_SCO (SCO : SCO_Id; CU : CU_Id) return Boolean; + -- Return whether the given CU contains the given SCO + + procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) + with Pre => Get_CU (ST) = No_CU_Id + or else Contains_SCO (SCO, Get_CU (ST)); -- Position ST on the inner-most scope that contains SCO. -- -- This does nothing on a scope traversal type not initialized, or @@ -90,6 +98,29 @@ package body SC_Obligations is -- Source units table -- ------------------------ + type SID_Info is record + Blocks : SCO_Id_Vector_Vector; + -- List of blocks. A block is a list of statement SCOs. Note that + -- this is specific to source instrumentation, but a container cannot + -- be a discriminant-dependent component. + + Bit_Maps : CU_Bit_Maps; + -- Mapping of bits in coverage buffers to SCOs + + Bit_Maps_Fingerprint : Fingerprint_Type; + -- Hash of Bit_Maps, for consistency checks with source traces + + Annotations_Fingerprint : Fingerprint_Type := No_Fingerprint; + -- Hash of ALI_Annotations, for consistency checks with source traces + + end record; + -- Part of the information stored in a SID file, and needed to compute + -- coverage results. + + package SID_Info_Maps is new Ada.Containers.Ordered_Maps + (Key_Type => Fingerprint_Type, + Element_Type => SID_Info); + type CU_Info (Provider : SCO_Provider := SCO_Provider'First) is record Origin : Source_File_Index; -- File from which this unit's SCO info comes from. @@ -101,56 +132,63 @@ package body SC_Obligations is -- For Ada this is a simple name; for C this is either a simple name -- or full name, depending on whether the information is available. - First_SCO, Last_SCO : SCO_Id := No_SCO_Id; - -- First and last SCO ids for this unit - Deps : SFI_Vector; -- Mapping of this unit's dependency numbers to source file indices Has_Code : Boolean := False; -- Set True when object code for some source file in this unit is seen - Fingerprint : Fingerprint_Type; - -- Hash of SCO info in ALI, for incremental coverage consistency check - PP_Info_Map : SCO_PP_Info_Maps.Map; -- Information about preprocessing Scope_Entities : Scope_Entities_Tree := Scope_Entities_Trees.Empty_Tree; -- Scope tree, used to output e.g. subprogram metrics - Blocks : SCO_Id_Vector_Vector; - -- List of blocks. A block is a list of statement SCOs. Note that this - -- is specific to source instrumentation, but a container cannot be - -- a discriminant-dependent component. - ALI_Annotations : ALI_Annotation_Maps.Map; -- List of annotations for the unit - Annotations_Fingerprint : Fingerprint_Type := No_Fingerprint; - -- Hash of ALI_Annotations, for consistency checks with source traces + SCOs : SCO_Range_Vectors.Vector; + -- List of SCOs for this unit + + SIDs_Info : SID_Info_Maps.Map; + -- Mapping from SCOs fingerprint to SID information. A compilation + -- unit has various SID versions when it has varying SCOs: this can + -- happen when including a header file with varying inclusion + -- contexts (e.g. macro definition varying at the inclusion point). + -- Note that this is exclusively computing coverage results (e.g. + -- analyzing a trace along with SID files). + -- + -- Note that we only use the SID_Info when computing coverage results + -- resulting from instrumentation (and thus analyzing traces with SID + -- files). When retrieving coverage results from checkpoint, we only + -- need the list of SCOs fingerprints for quicker consolidation, so + -- this map elements will be empty. case Provider is when Compiler | LLVM => - null; + SCOs_Fingerprint : Fingerprint_Type; + -- Hash of SCO info in checkpoint, for incremental coverage + -- consistency check. when Instrumenter => - Bit_Maps : CU_Bit_Maps; - -- Mapping of bits in coverage buffers to SCOs - - Bit_Maps_Fingerprint : Fingerprint_Type; - -- Hash of Bit_Maps, for consistency checks with source traces + Source_Fingerprint : Fingerprint_Type; + -- Hash of source code in checkpoint, for incremental coverage + -- consistency check. Note that contrarily to binary traces, we + -- can have a varying set of SCOs from a checkpoint to another, + -- so we rely on the source code fingerprint rather than the + -- SCOs. True_Static_SCOs : SCO_Sets.Set; False_Static_SCOs : SCO_Sets.Set; - end case; + end case; end record; procedure Free (CU : in out CU_Info); function Has_SCOs (CUI : CU_Info) return Boolean is - (CUI.First_SCO <= CUI.Last_SCO); + (CUI.SCOs.Length > 0 + and then CUI.SCOs.First_Element.First <= CUI.SCOs.First_Element.Last); function Are_Bit_Maps_In_Range (Bit_Maps : CU_Bit_Maps; CU : CU_Info) return Boolean; @@ -429,7 +467,8 @@ package body SC_Obligations is when Decision => Expression : SCO_Id := No_SCO_Id; - -- Top expression node for this decision + -- Top expression node for this decision. This refers to the first + -- condition SCO of the decision. D_Kind : Decision_Kind; -- Decision kind indication @@ -527,9 +566,9 @@ package body SC_Obligations is -- contain data loaded from a checkpoint. type Source_Coverage_Vectors is record - CU_Vector : CU_Info_Vectors.Vector; - BDD_Vector : BDD.BDD_Vectors.Vector; - SCO_Vector : SCO_Vectors.Vector; + CU_Vector : CU_Info_Vectors.Vector; + BDD_Vector : BDD.BDD_Vectors.Vector; + SCO_Vector : SCO_Vectors.Vector; end record; function Index @@ -583,6 +622,11 @@ package body SC_Obligations is procedure Read (CLS : in out Checkpoint_Load_State; Value : out PP_Info); -- Read a PP_Info from CLS + procedure Read + (CLS : in out Checkpoint_Load_State; Fingerprint : out Fingerprint_Type); + -- Wrapper around CLS.Read_Fingerprint to accomodate for the Read_Map + -- instantiation below. + procedure Read is new Read_Map (Key_Type => SCO_Id, Element_Type => PP_Info, @@ -590,7 +634,7 @@ package body SC_Obligations is Clear => SCO_PP_Info_Maps.Clear, Insert => SCO_PP_Info_Maps.Insert, Read_Key => Read, - Read_element => Read); + Read_Element => Read); procedure Read (CLS : in out Checkpoint_Load_State; Value : out Scope_Entity); @@ -602,6 +646,29 @@ package body SC_Obligations is Multiway_Trees => Scope_Entities_Trees, Read_Element => Read); + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out SCO_Range); + -- Read a SCO_Range from CLS + + procedure Read is new Read_Vector + (Index_Type => Positive, + Element_Type => SCO_Range, + "=" => "=", + Vectors => SCO_Range_Vectors, + Read_Element => Read); + + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out SID_Info); + -- Read a SID_Info from CLS + + procedure Read is new Read_Map + (Key_Type => Fingerprint_Type, + Element_Type => SID_Info, + Map_Type => SID_Info_Maps.Map, + Clear => SID_Info_Maps.Clear, + Insert => SID_Info_Maps.Insert, + Read_Key => Read, + Read_Element => Read); procedure Read (CLS : in out Checkpoint_Load_State; Value : out CU_Info); -- Read a CU_Info from CLS @@ -661,32 +728,85 @@ package body SC_Obligations is Read_Element => Read); -- Read a ALI_Annotation_Maps.Map from CLS - procedure Checkpoint_Load_Merge_Unit + procedure Remap_BDD + (CP_Vectors : Source_Coverage_Vectors; + Relocs : in out Checkpoint_Relocations; + Decision_BDD : in out BDD.BDD_Type); + -- Remap a sequence of BDD nodes, for a whole decision BDD + + procedure Remap_BDD_Node + (Relocs : Checkpoint_Relocations; + B : in out BDD_Node_Id); + -- Remap a BDD node id + + procedure Remap_SCO_Id + (Relocs : Checkpoint_Relocations; + S : in out SCO_Id); + -- Remap a SCO_Id. Note: this assumes possible forward references, and + -- does not rely on SCO_Map. + + procedure Remap_SCO_Descriptor + (CP_Vectors : Source_Coverage_Vectors; + Relocs : in out Checkpoint_Relocations; + SCOD : in out SCO_Descriptor); + -- Remap one SCO_Descriptor. Note that this assumes that + -- SCOD.Sloc_Range.Source_File has already been remapped. + -- + -- Note that this expects condition SCOs of a decision to have been + -- remapped calling Remap_SCO_Descriptor + + function Sloc_Range_For_SCO + (SCOD : SCO_Descriptor) return Source_Location_Range; + -- Get the Source_Location_Range to search for in the Sloc_To_SCO map for + -- the given SCO, accounting for the specific case of decision with + -- a control location (when using binary traces): in this case, the + -- decision are located at their control location rather than the actual + -- decision location. + + function Check_SCOs_Consistency (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; - CP_CU : CU_Info; - Real_CU_Id : CU_Id); - -- Load CU from checkpoint that corresponds to a current unit of interest - -- whose ID is Real_CU_Id. - - procedure Checkpoint_Load_New_Unit + CP_CU : in out CU_Info) return Boolean; + -- Check the consistency of the SCO in CP_CU wrt. SCOs previously loaded + -- for the a different version of the same unit. When a new SCO overlaps + -- with an existing one, this breaks the consistency of SCOs. Note that we + -- accept no SCO overlaps (thus no nesting) across compilation unit + -- versions. + + procedure Checkpoint_Load_SCOs (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; - New_CU_Id : out CU_Id); - -- Load CU from checkpoint that does not correspond to a current unit of - -- interest. The newly assigned CU_Id is returned in New_CU_Id. + Real_CU : in out CU_Info; + Real_CU_Id : CU_Id); + -- Load the SCOs in CP_CU and add them to Real_CU, which is the CU entry + -- for Real_CU_Id. + + procedure Checkpoint_Load_SID_Info + (CLS : in out Checkpoint_Load_State; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info); + -- Load the SID information entries in SIDs_Info and add them to Real_CU + + procedure Checkpoint_Load_PP_Info + (CLS : in out Checkpoint_Load_State; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info); + -- Load the preprocessing information in CP_CU and add them to Real_CU + + procedure Checkpoint_Load_Scopes + (CLS : in out Checkpoint_Load_State; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info); + -- Load the scopes in CP_CU and add them to Real_CU procedure Checkpoint_Load_Unit (CLS : in out Checkpoint_Load_State; CP_Vectors : Source_Coverage_Vectors; CP_CU : in out CU_Info; - New_CU_Id : out CU_Id); + CP_CU_Id : CU_Id); -- Process one compilation unit from a checkpoint. -- CP_CU_Id is the CU_Id in the checkpoint. - -- New_CU_Id is the corresponding CU_Id in the current context, and is - -- either an already existing CU_Id (if the unit was already known), - -- or a newly assigned one (if not). ----------------------------------------- -- Helper routines for Checkpoint_Save -- @@ -726,6 +846,33 @@ package body SC_Obligations is Multiway_Trees => Scope_Entities_Trees, Write_Element => Write); + procedure Write + (CSS : in out Checkpoint_Save_State; Value : SID_Info); + -- Write a SID_Info to CSS + + procedure Write is new Write_Map + (Key_Type => Fingerprint_Type, + Element_Type => SID_Info, + Map_Type => SID_Info_Maps.Map, + Cursor_Type => SID_Info_Maps.Cursor, + Length => SID_Info_Maps.Length, + Iterate => SID_Info_Maps.Iterate, + Query_Element => SID_Info_Maps.Query_Element, + Write_Key => Write, + Write_Element => Write); + -- Write a vector of SID_Info records to CSS + + procedure Write (CSS : in out Checkpoint_Save_State; Value : SCO_Range); + -- Write a SCO_Range to CSS + + procedure Write is new Write_Vector + (Index_Type => Positive, + Element_Type => SCO_Range, + "=" => "=", + Vectors => SCO_Range_Vectors, + Write_Element => Write); + -- Write a vector of SCO_Range records to CSS + procedure Write (CSS : in out Checkpoint_Save_State; Value : CU_Info); -- Write a CU_Info to CSS @@ -845,9 +992,9 @@ package body SC_Obligations is SE : Scope_Entity renames Scope_Entities.Constant_Reference (Cur); begin - Put_Line (Prefix & Image (SE)); - Put_Line (Prefix & "... from " & Image (SE.From)); - Put_Line (Prefix & " to " & Image (SE.To)); + Put_Line + (Prefix & Image (SE) & " source range " + & Image (SE.Source_Range)); end; end loop; end Dump; @@ -877,8 +1024,10 @@ package body SC_Obligations is -- Traverse_SCO -- ------------------ - procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) is + procedure Traverse_SCO (ST : in out Scope_Traversal_Type; SCO : SCO_Id) + is use Scope_Entities_Trees; + SCO_Sloc : constant Local_Source_Location := First_Sloc (SCO).L; begin -- Don't do anything if there is no scope attached to ST. @@ -938,8 +1087,9 @@ package body SC_Obligations is declare SE : constant Scope_Entity := Element (Child); begin - In_Child := SE.From <= SCO; - exit Child_Search when SE.To >= SCO; + In_Child := SE.Source_Range.L.First_Sloc <= SCO_Sloc; + exit Child_Search when + SCO_Sloc <= SE.Source_Range.L.Last_Sloc; Child := Next_Sibling (Child); end; end loop Child_Search; @@ -1015,22 +1165,78 @@ package body SC_Obligations is end loop; end Add_SCO_To_Lines; + --------------------- + -- Has_Fingerprint -- + --------------------- + + function Has_Fingerprint + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return Boolean is + begin + return + CU_Vector.Constant_Reference (CU).SIDs_Info.Contains (SCO_Fingerprint); + end Has_Fingerprint; + + ------------------ + -- Fingerprints -- + ------------------ + + function Fingerprints (CU : CU_Id) return Fingerprint_Vectors.Vector + is + Result : Fingerprint_Vectors.Vector; + begin + for Cur in CU_Vector.Reference (CU).SIDs_Info.Iterate loop + Result.Append (SID_Info_Maps.Key (Cur)); + end loop; + return Result; + end Fingerprints; + -------------- -- Bit_Maps -- -------------- - function Bit_Maps (CU : CU_Id) return CU_Bit_Maps is + function Bit_Maps + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return CU_Bit_Maps is begin - return CU_Vector.Reference (CU).Element.Bit_Maps; + return CU_Vector.Reference (CU) + .SIDs_Info.Element (SCO_Fingerprint).Bit_Maps; end Bit_Maps; + -------------------------- + -- Bit_Maps_Fingerprint -- + -------------------------- + + function Bit_Maps_Fingerprint + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return Fingerprint_Type is + begin + return CU_Vector.Constant_Reference (CU) + .SIDs_Info.Element (SCO_Fingerprint).Bit_Maps_Fingerprint; + end Bit_Maps_Fingerprint; + + ----------------------------- + -- Annotations_Fingerprint -- + ----------------------------- + + function Annotations_Fingerprint + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return Fingerprint_Type is + begin + return CU_Vector.Constant_Reference (CU) + .SIDs_Info.Element (SCO_Fingerprint).Annotations_Fingerprint; + end Annotations_Fingerprint; + ------------ -- Blocks -- ------------ - function Blocks (CU : CU_Id) return SCO_Id_Vector_Vector is + function Blocks + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return SCO_Id_Vector_Vector is begin - return CU_Vector.Reference (CU).Element.Blocks; + return CU_Vector.Reference (CU) + .SIDs_Info.Element (SCO_Fingerprint).Blocks; end Blocks; ----------------- @@ -1098,14 +1304,58 @@ package body SC_Obligations is end Read; procedure Read - (CLS : in out Checkpoint_Load_State; Value : out Scope_Entity) + (CLS : in out Checkpoint_Load_State; Fingerprint : out Fingerprint_Type) + is + begin + Fingerprint := CLS.Read_Fingerprint; + end Read; + + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out SID_Info) is + Stmt_First, DC_First, MCDC_First : Bit_Id; + Stmt_Last, DC_Last, MCDC_Last : Any_Bit_Id; begin - Value.From := CLS.Read_SCO; - Value.To := CLS.Read_SCO; + -- Read block information + + Read (CLS, Value.Blocks); + + -- Read bit maps + + Stmt_First := CLS.Read_Bit_Id; + Stmt_Last := CLS.Read_Bit_Id; + Value.Bit_Maps.Statement_Bits := + new Statement_Bit_Map (Stmt_First .. Stmt_Last); + for SCO of Value.Bit_Maps.Statement_Bits.all loop + SCO := CLS.Read_SCO; + end loop; + + DC_First := CLS.Read_Bit_Id; + DC_Last := CLS.Read_Bit_Id; + Value.Bit_Maps.Decision_Bits := + new Decision_Bit_Map (DC_First .. DC_Last); + for Info of Value.Bit_Maps.Decision_Bits.all loop + Info.D_SCO := CLS.Read_SCO; + Info.Outcome := CLS.Read_Boolean; + end loop; - Value.Start_Sloc := CLS.Read_Local_Source_Location; - Value.End_Sloc := CLS.Read_Local_Source_Location; + MCDC_First := CLS.Read_Bit_Id; + MCDC_Last := CLS.Read_Bit_Id; + Value.Bit_Maps.MCDC_Bits := + new MCDC_Bit_Map (MCDC_First .. MCDC_Last); + for Info of Value.Bit_Maps.MCDC_Bits.all loop + Info.D_SCO := CLS.Read_SCO; + Info.Path_Index := CLS.Read_Integer; + end loop; + Value.Bit_Maps_Fingerprint := CLS.Read_Fingerprint; + Value.Annotations_Fingerprint := CLS.Read_Fingerprint; + end Read; + + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out Scope_Entity) + is + begin + Value.Source_Range := CLS.Read_Source_Location_Range; Value.Name := CLS.Read_Unbounded_String; Value.Sloc := CLS.Read_Local_Source_Location; @@ -1114,76 +1364,33 @@ package body SC_Obligations is Value.Identifier.Decl_Line := CLS.Read_Integer; end Read; + procedure Read + (CLS : in out Checkpoint_Load_State; Value : out SCO_Range) + is + begin + Value.First := CLS.Read_SCO; + Value.Last := CLS.Read_SCO; + end Read; + procedure Read (CLS : in out Checkpoint_Load_State; Value : out CU_Info) is Element_Template : CU_Info (SCO_Provider'Val (CLS.Read_U8)); begin Value := Element_Template; - - -- Checkpoint version 1 data - Value.Origin := CLS.Read_SFI; Value.Main_Source := CLS.Read_SFI; - Value.First_SCO := CLS.Read_SCO; - Value.Last_SCO := CLS.Read_SCO; Read (CLS, Value.Deps); Value.Has_Code := CLS.Read_Boolean; - Value.Fingerprint := CLS.Read_Fingerprint; Read (CLS, Value.PP_Info_Map); Read (CLS, Value.Scope_Entities); Read (CLS, Value.ALI_Annotations); - Value.Annotations_Fingerprint := CLS.Read_Fingerprint; - - case Value.Provider is + Read (CLS, Value.SCOs); + case Element_Template.Provider is when Compiler | LLVM => - null; + Value.SCOs_Fingerprint := CLS.Read_Fingerprint; when Instrumenter => - - -- By default, use "no fingerprint" for buffer bit maps - -- fingerprints: by design checkpoints contains neither bit maps - -- nor their fingerprints (all source traces are processed before - -- loading checkpoints, and bit maps are needed only to interpret - -- source traces). - - Value.Bit_Maps_Fingerprint := No_Fingerprint; - - if Purpose_Of (CLS) = Instrumentation then - declare - Stmt_First, DC_First, MCDC_First : Bit_Id; - Stmt_Last, DC_Last, MCDC_Last : Any_Bit_Id; - begin - Stmt_First := CLS.Read_Bit_Id; - Stmt_Last := CLS.Read_Bit_Id; - Value.Bit_Maps.Statement_Bits := - new Statement_Bit_Map (Stmt_First .. Stmt_Last); - for SCO of Value.Bit_Maps.Statement_Bits.all loop - SCO := CLS.Read_SCO; - end loop; - - DC_First := CLS.Read_Bit_Id; - DC_Last := CLS.Read_Bit_Id; - Value.Bit_Maps.Decision_Bits := - new Decision_Bit_Map (DC_First .. DC_Last); - for Info of Value.Bit_Maps.Decision_Bits.all loop - Info.D_SCO := CLS.Read_SCO; - Info.Outcome := CLS.Read_Boolean; - end loop; - - MCDC_First := CLS.Read_Bit_Id; - MCDC_Last := CLS.Read_Bit_Id; - Value.Bit_Maps.MCDC_Bits := - new MCDC_Bit_Map (MCDC_First .. MCDC_Last); - for Info of Value.Bit_Maps.MCDC_Bits.all loop - Info.D_SCO := CLS.Read_SCO; - Info.Path_Index := CLS.Read_Integer; - end loop; - end; - Value.Bit_Maps_Fingerprint := CLS.Read_Fingerprint; - - -- Read block information - - Read (CLS, Value.Blocks); - end if; + Read (CLS, Value.SIDs_Info); + Value.Source_Fingerprint := CLS.Read_Fingerprint; end case; end Read; @@ -1281,652 +1488,857 @@ package body SC_Obligations is Value.Undetermined_Cov_Count := 0; end Read; - -------------------------------- - -- Checkpoint_Load_Merge_Unit -- - -------------------------------- + function "<" (L, R : Static_Decision_Evaluation) return Boolean is + begin + if L.Outcome /= R.Outcome then + return L.Outcome < R.Outcome; + end if; - procedure Checkpoint_Load_Merge_Unit - (CLS : in out Checkpoint_Load_State; - CP_Vectors : Source_Coverage_Vectors; - CP_CU : CU_Info; - Real_CU_Id : CU_Id) - is - Relocs : Checkpoint_Relocations renames CLS.Relocations; - Real_CU : CU_Info renames CU_Vector.Reference (Real_CU_Id).Element.all; + for J in R.Values.First_Index .. R.Values.Last_Index loop + if J > L.Values.Last_Index then + return True; - procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) - with pre => Kind (New_SCO_Id) = Decision; + elsif L.Values.Element (J) < R.Values.Element (J) then + return True; - ------------------------- - -- Merge_Decision_SCOs -- - ------------------------- + elsif L.Values.Element (J) > R.Values.Element (J) then + return False; + end if; + end loop; - procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) - is - use SC_Obligations.BDD; + return False; + end "<"; - Old_SCOD : SCO_Descriptor renames CP_Vectors.SCO_Vector (Old_SCO_Id); - New_SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); + ------------------------ + -- Sloc_Range_For_SCO -- + ------------------------ - Old_Reachable : Reachability renames - Old_SCOD.Decision_BDD.Reachable_Outcomes; - New_Reachable : Reachability renames - New_SCOD.Decision_BDD.Reachable_Outcomes; + function Sloc_Range_For_SCO + (SCOD : SCO_Descriptor) return Source_Location_Range + is + Sloc_Range : Source_Location_Range := SCOD.Sloc_Range; + begin + if SCOD.Kind = Decision and then SCOD.Control_Location /= No_Location + then + Sloc_Range := To_Range (SCOD.Control_Location, No_Location); + end if; + return Sloc_Range; + end Sloc_Range_For_SCO; - function Decision_Static_Eval - (Vectors : Source_Coverage_Vectors; - SCO_Dec : SCO_Id; - Eval : out Static_Decision_Evaluation) return Boolean; + ---------------------------- + -- Check_SCOs_Consistency -- + ---------------------------- - procedure Register_Static_Evaluation - (SCO : SCO_Id; Eval : Static_Decision_Evaluation); + function Check_SCOs_Consistency + (CLS : in out Checkpoint_Load_State; + CP_Vectors : Source_Coverage_Vectors; + CP_CU : in out CU_Info) return Boolean is + begin + for SCO_Range of CP_CU.SCOs loop + for Old_SCO_Id in SCO_Range.First .. SCO_Range.Last loop + declare + New_SCOD : constant SCO_Descriptor := + CP_Vectors.SCO_Vector.Element (Old_SCO_Id); + Kind : Any_SCO_Kind renames New_SCOD.Kind; - -------------------------- - -- Decision_Static_Eval -- - -------------------------- + Sloc_Range : Source_Location_Range := + Sloc_Range_For_SCO (New_SCOD); - function Decision_Static_Eval - (Vectors : Source_Coverage_Vectors; - SCO_Dec : SCO_Id; - Eval : out Static_Decision_Evaluation) return Boolean - is - SCOD : SCO_Descriptor renames Vectors.SCO_Vector (SCO_Dec); + Real_SCO : SCO_Id := No_SCO_Id; + -- Value of the SCO if it already exists, otherwise left to + -- No_SCO_Id. - Reachable : constant Reachability := - SCOD.Decision_BDD.Reachable_Outcomes; + begin + -- Remap SFIs in all source locations - Outcome : constant Tristate := - (if Reachable (False) /= Reachable (True) - then To_Tristate (Reachable (True)) - else Unknown); + Remap_SFI (CLS.Relocations, Sloc_Range.Source_File); - E : Static_Decision_Evaluation; - begin + -- Only consider statement / decision / condition coverage + -- obligations as other SCO kinds are not considered by + -- Sloc_To_SCO and this is a good enough condition to ensure + -- SCOs consistency. - -- Do not process evaluations if the decision is not at least - -- partially static. + if Kind not in Statement .. Condition then + goto Continue; + end if; - if Outcome = Unknown then - return False; - end if; + -- Try to find if the SCO already exists, or if there is an + -- existing SCO at the same location but not with the same + -- source range. - E.Outcome := To_Boolean (Outcome); + -- First, try to find if we have a SCO of the exact same kind + -- and range. - for J in Condition_Index'First .. SCOD.Last_Cond_Index - loop declare - SCO_C : constant SCO_Id := - Condition (Vectors, SCO_Dec, J); - SCOD_C : SCO_Descriptor renames - Vectors.SCO_Vector (SCO_C); + use Sloc_To_SCO_Maps; + Cur : constant Cursor := + Sloc_To_SCO_Map + (Sloc_Range.Source_File, Kind).Find (Sloc_Range.L); begin - - -- If an encountered Condition has no Value, then the - -- Decision is not fully static, abort processing - - if SCOD_C.Value = Unknown then - E.Values.Clear; - return False; + if Has_Element (Cur) + and then SCO_Vector.Element (Element (Cur)).Kind = Kind + then + goto Continue; end if; - - E.Values.Append (To_Boolean (SCOD_C.Value)); end; - end loop; - Eval := E; - return True; - end Decision_Static_Eval; + -- If we did not find a SCO with the exact same range, check + -- whether there is an overlapping SCO. - -------------------------------- - -- Register_Static_Evaluation -- - -------------------------------- + Real_SCO := + Sloc_To_SCO + (Slocs.Source_Location' + (Source_File => Sloc_Range.Source_File, + L => New_SCOD.Sloc_Range.L.First_Sloc), + Include_Decisions => True); - procedure Register_Static_Evaluation - (SCO : SCO_Id; Eval : Static_Decision_Evaluation) is - begin - if not CLS.Static_Decision_Evaluations.Contains (SCO) - then - CLS.Static_Decision_Evaluations.Insert - (SCO, - Static_Decision_Evaluation_Sets.Empty_Set); - end if; - CLS.Static_Decision_Evaluations - .Reference (SCO) - .Include (Eval); - end Register_Static_Evaluation; + if Real_SCO /= No_SCO_Id then + return False; + end if; + end; + <> + end loop; + end loop; + return True; + end Check_SCOs_Consistency; - -- Start processing of Merge_Decision_SCOs + -------------------------- + -- Checkpoint_Load_SCOs -- + -------------------------- - begin - if Old_SCOD.Decision_Instrumented then - New_SCOD.Decision_Instrumented := True; - end if; - if Old_SCOD.Decision_Instrumented_For_MCDC then - New_SCOD.Decision_Instrumented_For_MCDC := True; - end if; - - -- The following code handles merging Decision SCOs that have a - -- different staticness over the 2 checkpoints that are being merged. - -- - -- If the reachability of the decision in one of the checkpoints - -- differs from `Both_Reachable`, it means that at least one of the - -- two checkpoints has some static conditions and should be handled - -- with a specific treatment. - -- - -- Upon encountering a fully-static decision, we need to register its - -- conditions' values so they can be used as a complementary - -- evaluation for MC/DC analysis. + procedure Checkpoint_Load_SCOs + (CLS : in out Checkpoint_Load_State; + CP_Vectors : Source_Coverage_Vectors; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info; + Real_CU_Id : CU_Id) + is + Relocs : Checkpoint_Relocations renames CLS.Relocations; - if Old_Reachable /= Both_Reachable - or else - New_Reachable /= Both_Reachable - then - SCOs_Trace.Trace ("Consolidation encountered a decision SCO" - & " whose staticness may differ at" - & Image (New_SCOD.Sloc_Range)); - declare - Old_Eval : Static_Decision_Evaluation; - -- Holds the result of the static evaluation of Old_SCO - -- if Old_Static is True. Otherwise, it is invalid. + Cur_Source_File : Source_File_Index := No_Source_File; + Last_Line : Natural := 0; - New_Eval : Static_Decision_Evaluation; - -- Holds the result of the static evaluation of New_SCO - -- if New_Static is True. Otherwise, it is invalid. + New_First_SCO : constant SCO_Id := SCO_Vector.Last_Index + 1; + begin + -- When loading a SCO, we check if it already exists: + -- * If it is the case, merge it and adequately set the bit map + -- relocation to the existing SCO. + -- * Otherwise, create it. + -- + -- The heuristic to consider that a SCO already exists or not is to + -- check for a SCO with the exact same source location. - Old_Static : constant Boolean := - Decision_Static_Eval (CP_Vectors, Old_SCO_Id, Old_Eval); - New_Static : constant Boolean := - Decision_Static_Eval (SC_Vectors, New_SCO_Id, New_Eval); + for SCO_Range of CP_CU.SCOs loop + for Old_SCO_Id in SCO_Range.First .. SCO_Range.Last loop + declare + New_SCOD : SCO_Descriptor := + CP_Vectors.SCO_Vector.Element (Old_SCO_Id); + Sloc_Range : Source_Location_Range := + Sloc_Range_For_SCO (New_SCOD); + Real_SCO : SCO_Id := No_SCO_Id; + -- Value of the SCO if it already exists, otherwise left to + -- No_SCO_Id. begin + if New_SCOD.Kind = Removed then + Ignore_SCO (Relocs, Old_SCO_Id); + goto Next_SCO; + end if; - -- No matter the staticness of the SCOs, we update the - -- reachability of each outcome by OR-ing the two checkpoints. + -- Remap SFIs in all source locations - New_Reachable (True) := New_Reachable (True) or else - Old_Reachable (True); + Remap_SFI (Relocs, Sloc_Range.Source_File); - New_Reachable (False) := New_Reachable (False) or else - Old_Reachable (False); + -- Try to find if the SCO already exists - if Old_Static then + declare + use Sloc_To_SCO_Maps; + Cur : constant Cursor := + Sloc_To_SCO_Map + (Sloc_Range.Source_File, + New_SCOD.Kind).Find (Sloc_Range.L); + begin + if Has_Element (Cur) then + Real_SCO := Element (Cur); + end if; + end; - -- If the decision in the Old checkpoint is static, - -- add an evaluation to the SCIs corresponding to it. + -- If the SCO already exists, only add an entry to remap the + -- Old_SCO_Id to the actual SCO. - Register_Static_Evaluation (New_SCO_Id, Old_Eval); + if Real_SCO /= No_SCO_Id then + Set_SCO_Id_Map (Relocs, Old_SCO_Id, Real_SCO); + goto Next_SCO; end if; - if New_Static then + -- At this point, if Real_SCO is No_SCO_Id, this is a new SCO: + -- it cannot overlap with an existing SCO as this was checked + -- by Check_SCOs_Consistency. - -- If the decision in the New checkpoint is static, - -- add an evaluation to the SCIs corresponding to it. + if Real_SCO = No_SCO_Id then + Set_SCO_Id_Map + (Relocs, Old_SCO_Id, SCO_Vector.Last_Index + 1); - Register_Static_Evaluation (New_SCO_Id, New_Eval); - end if; - end; - end if; - end Merge_Decision_SCOs; + -- Append new SCOD and record mapping - -- Start processing of Checkpoint_Load_Merge_Unit + Remap_SCO_Descriptor (CP_Vectors, Relocs, New_SCOD); - begin - -- Here we already have loaded full SCO information for this CU. There - -- are two things to do: - -- - -- * Populate the tables mapping the SCO for this unit in the checkpoint - -- to their counterparts in the current context, and merge - -- non-instrumented SCO information if available. - -- - -- * Merge the annotations - -- - -- * Merge the information about non instrumented SCOs. We consider that - -- a SCO was instrumented iff at least one merged unit has it - -- instrumented. + -- Preallocate line table entries for previous unit + + if New_SCOD.Sloc_Range.Source_File /= Cur_Source_File then + Prealloc_Lines (Cur_Source_File, Last_Line); + Cur_Source_File := New_SCOD.Sloc_Range.Source_File; + CU_Map.Include (Cur_Source_File, Real_CU_Id); + end if; + if New_SCOD.Kind in + Statement | Decision | Fun_Call_SCO_Kind | Guarded_Expr + then + Add_SCO_To_Lines (SCO_Vector.Last_Index + 1, New_SCOD); + end if; - -- SCOs + Last_Line := Natural'Max + (Files_Table.Last_Line (Get_File (Cur_Source_File)), + New_SCOD.Sloc_Range.L.Last_Sloc.Line); + SCO_Vector.Append (New_SCOD); - pragma Assert (CP_CU.Last_SCO - CP_CU.First_SCO - = - Real_CU.Last_SCO - Real_CU.First_SCO); + -- Add it into the Sloc_To_SCO_Map - for Old_SCO_Id in CP_CU.First_SCO .. CP_CU.Last_SCO loop - Set_SCO_Id_Map (Relocs, Old_SCO_Id, - Old_SCO_Id - + Real_CU.First_SCO - - CP_CU.First_SCO); + declare + Map : constant access Sloc_To_SCO_Maps.Map := + Writeable_Sloc_To_SCO_Map + (Sloc_Range.Source_File, New_SCOD.Kind); + begin + Map.Insert (Sloc_Range.L, SCO_Vector.Last_Index); + end; - declare + if SCOs_Trace.Is_Active then + SCOs_Trace.Trace + ("Loaded from checkpoint: " + & Image (SCO_Vector.Last_Index) + & " (was #" + & Trim (Old_SCO_Id'Img, Side => Ada.Strings.Both) + & " in checkpoint)"); + end if; + end if; + end; + <> + end loop; + end loop; - Old_SCOD : SCO_Descriptor renames - CP_Vectors.SCO_Vector (Old_SCO_Id); - New_SCO_Id : constant SCO_Id := Remap_SCO_Id (Relocs, Old_SCO_Id); - SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); + -- Add the newly created SCOs to Real_CU.SCOs + if SCO_Vector.Last_Index >= New_First_SCO then + Real_CU.SCOs.Append + (SCO_Range'(First => New_First_SCO, Last => SCO_Vector.Last_Index)); + end if; + end Checkpoint_Load_SCOs; + + ------------------------------ + -- Checkpoint_Load_SID_Info -- + ------------------------------ + + procedure Checkpoint_Load_SID_Info + (CLS : in out Checkpoint_Load_State; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info) + is + Relocs : Checkpoint_Relocations renames CLS.Relocations; + begin + for Cur in CP_CU.SIDs_Info.Iterate loop + declare + SID_Fingerprint : constant Fingerprint_Type := + SID_Info_Maps.Key (Cur); + SID_Version : SID_Info := SID_Info_Maps.Element (Cur); begin - case SCOD.Kind is - when Statement => - if Old_SCOD.Stmt_Instrumented then - SCOD.Stmt_Instrumented := True; - end if; + if not Real_CU.SIDs_Info.Contains (SID_Fingerprint) then - when Decision => - Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id); + -- Remap bit map buffers - when Fun_Call_SCO_Kind => - if Old_SCOD.Fun_Call_Instrumented then - SCOD.Fun_Call_Instrumented := True; - end if; + if SID_Version.Bit_Maps.Statement_Bits /= null then + for S_SCO of SID_Version.Bit_Maps.Statement_Bits.all loop + Remap_SCO_Id (Relocs, S_SCO); + end loop; + end if; - when Guarded_Expr => - if Old_SCOD.GExpr_Instrumented then - SCOD.GExpr_Instrumented := True; - end if; + if SID_Version.Bit_Maps.Decision_Bits /= null then + for D_Outcome of SID_Version.Bit_Maps.Decision_Bits.all + loop + Remap_SCO_Id (Relocs, D_Outcome.D_SCO); + end loop; + end if; - when others => - null; - end case; + if SID_Version.Bit_Maps.MCDC_Bits /= null then + for D_Path of SID_Version.Bit_Maps.MCDC_Bits.all loop + Remap_SCO_Id (Relocs, D_Path.D_SCO); + end loop; + end if; + + -- Remap blocks information + + for Block_Cur in SID_Version.Blocks.Iterate loop + declare + Block_Ref : constant + SCO_Id_Vector_Vectors.Reference_Type := + SID_Version.Blocks.Reference (Block_Cur); + begin + for SCO_Cur in Block_Ref.Iterate loop + Remap_SCO_Id (Relocs, Block_Ref.Reference (SCO_Cur)); + end loop; + end; + end loop; + + Real_CU.SIDs_Info.Insert (SID_Fingerprint, SID_Version); + end if; end; end loop; + end Checkpoint_Load_SID_Info; - -- Has_Code indication - - Real_CU.Has_Code := Real_CU.Has_Code or CP_CU.Has_Code; + ----------------------------- + -- Checkpoint_Load_PP_Info -- + ----------------------------- - -- Remap ALI annotations and then merge them + procedure Checkpoint_Load_PP_Info + (CLS : in out Checkpoint_Load_State; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info) + is + use SCO_PP_Info_Maps; + Relocs : Checkpoint_Relocations renames CLS.Relocations; + begin + for Cur in CP_CU.PP_Info_Map.Iterate loop + declare + SCO : SCO_Id := Key (Cur); + Info : PP_Info := Element (Cur); + begin + if not Real_CU.PP_Info_Map.Contains (SCO) then + if Info.Kind = In_Expansion then + for Expansion of Info.Expansion_Stack loop + Remap_SFI + (Relocs, + Expansion.Sloc.Source_File); + end loop; + Remap_SFI + (Relocs, + Info.Definition_Loc.Sloc.Source_File); + end if; + Remap_SCO_Id (Relocs, SCO); + Real_CU.PP_Info_Map.Insert (SCO, Info); + end if; + end; + end loop; + end Checkpoint_Load_PP_Info; - declare - Remapped_Annotations : ALI_Annotation_Maps.Map := - CP_CU.ALI_Annotations; - begin - Remap_ALI_Annotations (Relocs, Remapped_Annotations); - for Cur in Remapped_Annotations.Iterate loop - Real_CU.ALI_Annotations.Include - (ALI_Annotation_Maps.Key (Cur), - ALI_Annotation_Maps.Element (Cur)); - end loop; - end; - end Checkpoint_Load_Merge_Unit; + ---------------------------- + -- Checkpoint_Load_Scopes -- + ---------------------------- - function "<" (L, R : Static_Decision_Evaluation) return Boolean is + procedure Checkpoint_Load_Scopes + (CLS : in out Checkpoint_Load_State; + CP_CU : in out CU_Info; + Real_CU : in out CU_Info) + is + Relocs : Checkpoint_Relocations renames CLS.Relocations; begin - if L.Outcome /= R.Outcome then - return L.Outcome < R.Outcome; - end if; + -- For scope entities, only add those that do not violate the + -- nesting and ordering of the structure - for J in R.Values.First_Index .. R.Values.Last_Index loop - if J > L.Values.Last_Index then - return True; + for Scope_Ent of CP_CU.Scope_Entities loop - elsif L.Values.Element (J) < R.Values.Element (J) then - return True; + -- Scopes whose identifier references ignored source files will + -- lose their identifier: such scopes will remain, but users + -- will not be able to mark them of interest. - elsif L.Values.Element (J) > R.Values.Element (J) then - return False; + if SFI_Ignored (Relocs, Scope_Ent.Identifier.Decl_SFI) then + Scope_Ent.Identifier := No_Scope_Entity_Identifier; + else + Remap_SFI (Relocs, Scope_Ent.Identifier.Decl_SFI); end if; - end loop; - return False; - end "<"; + Remap_SFI (Relocs, Scope_Ent.Source_Range.Source_File); - ------------------------------ - -- Checkpoint_Load_New_Unit -- - ------------------------------ + declare + use Scope_Entities_Trees; - procedure Checkpoint_Load_New_Unit - (CLS : in out Checkpoint_Load_State; - CP_Vectors : Source_Coverage_Vectors; - CP_CU : in out CU_Info; - New_CU_Id : out CU_Id) - is - Relocs : Checkpoint_Relocations renames CLS.Relocations; + Real_Scope : constant Cursor := + Floor + (Real_CU.Scope_Entities, + Source_Location' + (Source_File => Scope_Ent.Source_Range.Source_File, + L => Scope_Ent.Source_Range.L.First_Sloc)); - New_First_SCO : SCO_Id; + Added_Scope : Boolean := False; + -- Whether the current Scope_Ent was added to the list of scopes + -- (it is a new scope that does not clash with existing scopes). - Cur_Source_File : Source_File_Index := No_Source_File; - Last_Line : Natural := 0; + begin + if not Scope_Entities_Trees.Has_Element (Real_Scope) then - procedure Remap_BDD (Decision_BDD : in out BDD.BDD_Type); - -- Remap a sequence of BDD nodes, for a whole decision BDD + -- This is a new scope that do not nest with an existing + -- scope (basically the case of a new compilation unit). - procedure Remap_BDD_Node (B : in out BDD_Node_Id); - -- Remap a BDD node id + Real_CU.Scope_Entities.Insert_Child + (Parent => Real_CU.Scope_Entities.Root, + Before => No_Element, + New_Item => Scope_Ent); + Added_Scope := True; + else + declare + Found_Scope_Ent : constant Scope_Entity := + Real_CU.Scope_Entities.Reference (Real_Scope); + Child : Cursor := + First_Child (Real_Scope); + Src_Range : constant Source_Location_Range := + Found_Scope_Ent.Source_Range; + begin - procedure Remap_SCO_Id (S : in out SCO_Id); - -- Remap a SCO_Id. Note: this assumes possible forward references, and - -- does not rely on SCO_Map. + if Scope_Ent.Source_Range = Src_Range then - --------------- - -- Remap_BDD -- - --------------- + -- The scope already exists: do nothing - procedure Remap_BDD (Decision_BDD : in out BDD.BDD_Type) is - CP_First : constant BDD_Node_Id := Decision_BDD.First_Node; - CP_Last : constant BDD_Node_Id := Decision_BDD.Last_Node; - New_First : constant BDD_Node_Id := BDD_Vector.Last_Index + 1; - begin - -- Import the relevant BDD nodes from CP_Vectors.BDD_Vector + null; - for Old_BDD_Node_Id in CP_First .. CP_Last loop - declare - -- We are supposed to remap individual BDD nodes only once + elsif Src_Range.L.First_Sloc < + Scope_Ent.Source_Range.L.First_Sloc + and then + Scope_Ent.Source_Range.L.Last_Sloc < + Src_Range.L.Last_Sloc + then + -- Check if it nests with the innermost scope entity. If + -- this is the case, insert it as a child. + + while Has_Element (Child) + and then Element (Child).Source_Range.L.First_Sloc + < Scope_Ent.Source_Range.L.First_Sloc + loop + Child := Next_Sibling (Child); + end loop; + Added_Scope := True; - New_BDD_Node : BDD.BDD_Node := - CP_Vectors.BDD_Vector.Element (Old_BDD_Node_Id); + if not Has_Element (Child) then - procedure Remap_BDD_Node_Id (S : in out BDD_Node_Id); - -- Remap a BDD node id + -- Insert it as the last children - ----------------------- - -- Remap_BDD_Node_Id -- - ----------------------- + Real_CU.Scope_Entities.Insert_Child + (Parent => Real_Scope, + Before => No_Element, + New_Item => Scope_Ent); - procedure Remap_BDD_Node_Id (S : in out BDD_Node_Id) is - begin - if S /= No_BDD_Node_Id then - S := S - CP_First + New_First; + else + -- Insert it before the identified child + + Real_CU.Scope_Entities.Insert_Child + (Parent => Real_Scope, + Before => Child, + New_Item => Scope_Ent); + + end if; + else + -- Discard overlapping cases + + Outputs.Fatal_Error + ("Scope " + & (+Scope_Ent.Name) + & " at source location: " + & Image (Scope_Ent.Source_Range) + & " clashes with scope " + & (+Found_Scope_Ent.Name) + & " at location: " + & Image (Found_Scope_Ent.Source_Range)); end if; - end Remap_BDD_Node_Id; + end; + end if; - begin - case New_BDD_Node.Kind is - when BDD.Condition => - Remap_BDD_Node_Id (New_BDD_Node.Parent); - for Valuation in New_BDD_Node.Dests'Range loop - Remap_BDD_Node_Id - (New_BDD_Node.Dests (Valuation)); - end loop; + -- Register each scope identifiers to make them available to + -- users on the command line. - -- Note that we leave New_BDD_Node.C_SCO unremapped here: - -- the loading of the corresponding SCO condition will - -- take care of it (see below). + if Added_Scope then + Available_Subps_Of_Interest.Include (Scope_Ent.Identifier); + end if; + end; + end loop; + pragma Assert (SCOs_Nested_And_Ordered (Real_CU.Scope_Entities)); + end Checkpoint_Load_Scopes; - when BDD.Jump => - Remap_BDD_Node_Id (New_BDD_Node.Dest); + --------------- + -- Remap_BDD -- + --------------- - when others => - null; - end case; + procedure Remap_BDD + (CP_Vectors : Source_Coverage_Vectors; + Relocs : in out Checkpoint_Relocations; + Decision_BDD : in out BDD.BDD_Type) + is + CP_First : constant BDD_Node_Id := Decision_BDD.First_Node; + CP_Last : constant BDD_Node_Id := Decision_BDD.Last_Node; + New_First : constant BDD_Node_Id := BDD_Vector.Last_Index + 1; + begin + -- Import the relevant BDD nodes from CP_Vectors.BDD_Vector - BDD_Vector.Append (New_BDD_Node); - Set_BDD_Node_Id_Map - (Relocs, Old_BDD_Node_Id, BDD_Vector.Last_Index); - end; - end loop; + for Old_BDD_Node_Id in CP_First .. CP_Last loop + declare + -- We are supposed to remap individual BDD nodes only once - -- Remap IDs in Decision_BDD + New_BDD_Node : BDD.BDD_Node := + CP_Vectors.BDD_Vector.Element (Old_BDD_Node_Id); - Remap_SCO_Id (Decision_BDD.Decision); + procedure Remap_BDD_Node_Id (S : in out BDD_Node_Id); + -- Remap a BDD node id - Remap_BDD_Node (Decision_BDD.Root_Condition); - Remap_BDD_Node (Decision_BDD.First_Node); - Remap_BDD_Node (Decision_BDD.Last_Node); - Remap_BDD_Node (Decision_BDD.First_Multipath_Condition); - end Remap_BDD; + ----------------------- + -- Remap_BDD_Node_Id -- + ----------------------- - -------------------- - -- Remap_BDD_Node -- - -------------------- + procedure Remap_BDD_Node_Id (S : in out BDD_Node_Id) is + begin + if S /= No_BDD_Node_Id then + S := S - CP_First + New_First; + end if; + end Remap_BDD_Node_Id; - procedure Remap_BDD_Node (B : in out BDD_Node_Id) is - begin - if B /= No_BDD_Node_Id then - B := Remap_BDD_Node_Id (Relocs, B); - pragma Assert (B /= No_BDD_Node_Id); - end if; - end Remap_BDD_Node; + begin + case New_BDD_Node.Kind is + when BDD.Condition => + Remap_BDD_Node_Id (New_BDD_Node.Parent); + for Valuation in New_BDD_Node.Dests'Range loop + Remap_BDD_Node_Id + (New_BDD_Node.Dests (Valuation)); + end loop; - ------------------ - -- Remap_SCO_Id -- - ------------------ + -- Note that we leave New_BDD_Node.C_SCO unremapped here: + -- the loading of the corresponding SCO condition will + -- take care of it (see below). - procedure Remap_SCO_Id (S : in out SCO_Id) is - begin - if S /= No_SCO_Id then - S := New_First_SCO + S - CP_CU.First_SCO; - pragma Assert (S /= No_SCO_Id); - end if; - end Remap_SCO_Id; + when BDD.Jump => + Remap_BDD_Node_Id (New_BDD_Node.Dest); - -- Start of processing for Checkpoint_Load_New_Unit + when others => + null; + end case; + + BDD_Vector.Append (New_BDD_Node); + Set_BDD_Node_Id_Map + (Relocs, Old_BDD_Node_Id, BDD_Vector.Last_Index); + end; + end loop; + + -- Remap IDs in Decision_BDD + + Remap_SCO_Id (Relocs, Decision_BDD.Decision); + + Remap_BDD_Node (Relocs, Decision_BDD.Root_Condition); + Remap_BDD_Node (Relocs, Decision_BDD.First_Node); + Remap_BDD_Node (Relocs, Decision_BDD.Last_Node); + Remap_BDD_Node (Relocs, Decision_BDD.First_Multipath_Condition); + end Remap_BDD; + + -------------------- + -- Remap_BDD_Node -- + -------------------- + procedure Remap_BDD_Node + (Relocs : Checkpoint_Relocations; + B : in out BDD_Node_Id) is begin - New_CU_Id := CU_Vector.Last_Index + 1; + if B /= No_BDD_Node_Id then + B := Remap_BDD_Node_Id (Relocs, B); + pragma Assert (B /= No_BDD_Node_Id); + end if; + end Remap_BDD_Node; - CU_Map.Insert (CP_CU.Main_Source, New_CU_Id); + ------------------ + -- Remap_SCO_Id -- + ------------------ - -- Remap SCO ids. Note that BDD nodes are imported (and remapped) as - -- needed during the process. + procedure Remap_SCO_Id + (Relocs : Checkpoint_Relocations; + S : in out SCO_Id) is + begin + S := Checkpoints.Remap_SCO_Id (Relocs, S); + end Remap_SCO_Id; - New_First_SCO := SCO_Vector.Last_Index + 1; - for Old_SCO_Id in CP_CU.First_SCO .. CP_CU.Last_SCO loop - declare - New_SCOD : SCO_Descriptor := - CP_Vectors.SCO_Vector.Element (Old_SCO_Id); - begin - if New_SCOD.Kind = Removed then - Ignore_SCO (Relocs, Old_SCO_Id); - goto Next_SCO; - end if; + -------------------------- + -- Remap_SCO_Descriptor -- + -------------------------- - New_SCOD.Origin := New_CU_Id; + procedure Remap_SCO_Descriptor + (CP_Vectors : Source_Coverage_Vectors; + Relocs : in out Checkpoint_Relocations; + SCOD : in out SCO_Descriptor) + is + New_First_SCO : SCO_Id := SCO_Vector.Last_Index + 1; + begin + Remap_SFI (Relocs, SCOD.Sloc_Range.Source_File); - -- Remap SFIs in all source locations + -- If this is a decision, start by recording all of the operator + -- and condition SCOs in the relocation map, before relocating all + -- of the components of the SCO_Descriptor. - Remap_SFI (Relocs, New_SCOD.Sloc_Range.Source_File); + case SCOD.Kind is + when Decision => + declare + Expr_SCO : SCO_Id := SCOD.Expression - 1; + Expr_SCOD : SCO_Descriptor := + CP_Vectors.SCO_Vector.Element (Expr_SCO); + begin + loop + Expr_SCO := Expr_SCO + 1; + exit when Expr_SCO > CP_Vectors.SCO_Vector.Last_Index; + Expr_SCOD := CP_Vectors.SCO_Vector.Element (Expr_SCO); + exit when Expr_SCOD.Kind not in Condition | Operator; + New_First_SCO := New_First_SCO + 1; + Set_SCO_Id_Map (Relocs, Expr_SCO, New_First_SCO); + end loop; + end; + when others => + null; + end case; - -- Preallocate line table entries for previous unit + SCOD.Origin := Remap_CU_Id (Relocs, SCOD.Origin); - if New_SCOD.Sloc_Range.Source_File /= Cur_Source_File then - Prealloc_Lines (Cur_Source_File, Last_Line); - Cur_Source_File := New_SCOD.Sloc_Range.Source_File; - CU_Map.Include (Cur_Source_File, New_CU_Id); - end if; + -- Remap SCO_Ids - Last_Line := Natural'Max - (Last_Line, - New_SCOD.Sloc_Range.L.Last_Sloc.Line); + Remap_SCO_Id (Relocs, SCOD.Parent); - -- Remap SCO_Ids + -- Make further adjustments based on SCO kind + -- In particular reset all components that reference + -- data that is not saved to checkpoint files (such as + -- BDD information). - Remap_SCO_Id (New_SCOD.Parent); + case SCO_Kind (SCOD.Kind) is + when Statement => + Remap_SFI (Relocs, SCOD.Dominant_Sloc.Source_File); + Remap_SFI (Relocs, SCOD.Handler_Range.Source_File); - -- Make further adjustments based on SCO kind - -- In particular reset all components that reference - -- data that is not saved to checkpoint files (such as - -- BDD information). + Remap_SCO_Id (Relocs, SCOD.Dominant); - case SCO_Kind (New_SCOD.Kind) is - when Statement => - Remap_SFI (Relocs, New_SCOD.Dominant_Sloc.Source_File); - Remap_SFI (Relocs, New_SCOD.Handler_Range.Source_File); + when Decision => + Remap_SCO_Id (Relocs, SCOD.Expression); + Remap_SFI (Relocs, SCOD.Control_Location.Source_File); + Remap_BDD (CP_Vectors, Relocs, SCOD.Decision_BDD); - Remap_SCO_Id (New_SCOD.Dominant); + when Operator => + for Op_SCO in SCOD.Operands'Range loop + Remap_SCO_Id (Relocs, SCOD.Operands (Op_SCO)); + end loop; - when Decision => - Remap_SCO_Id (New_SCOD.Expression); - Remap_SFI (Relocs, New_SCOD.Control_Location.Source_File); - Remap_BDD (New_SCOD.Decision_BDD); + when Condition => + Remap_BDD_Node (Relocs, SCOD.BDD_Node); + Remap_SCO_Id + (Relocs, BDD_Vector.Reference (SCOD.BDD_Node).C_SCO); - when Operator => - for Op_SCO in New_SCOD.Operands'Range loop - Remap_SCO_Id (New_SCOD.Operands (Op_SCO)); - end loop; + SCOD.PC_Set.Clear; - when Condition => - Remap_BDD_Node (New_SCOD.BDD_Node); - Remap_SCO_Id - (BDD_Vector.Reference (New_SCOD.BDD_Node).C_SCO); + when Fun_Call_SCO_Kind | Guarded_Expr => + null; - New_SCOD.PC_Set.Clear; + end case; + end Remap_SCO_Descriptor; - when Fun_Call_SCO_Kind | Guarded_Expr => - null; + -------------------------- + -- Checkpoint_Load_Unit -- + -------------------------- - end case; + procedure Checkpoint_Load_Unit + (CLS : in out Checkpoint_Load_State; + CP_Vectors : Source_Coverage_Vectors; + CP_CU : in out CU_Info; + CP_CU_Id : CU_Id) + is + Relocs : Checkpoint_Relocations renames CLS.Relocations; - -- Append new SCOD and record mapping + procedure Ignore_SCOs; + -- Mark all the SCOs in CP_CU as being ignored. This is useful when + -- skipping coverage information for a unit because the consistency + -- checks failed. - SCO_Vector.Append (New_SCOD); - Set_SCO_Id_Map (Relocs, Old_SCO_Id, SCO_Vector.Last_Index); - if SCOs_Trace.Is_Active then - SCOs_Trace.Trace - ("Loaded from checkpoint: " - & Image (SCO_Vector.Last_Index) - & " (was #" & Trim (Old_SCO_Id'Img, Side => Ada.Strings.Both) - & " in checkpoint)"); - end if; - end; + procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) + with Pre => Kind (New_SCO_Id) = Decision; - <> null; - end loop; + ------------------------- + -- Merge_Decision_SCOs -- + ------------------------- - -- Remap SCO_Ids in source trace bit maps + procedure Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id : SCO_Id) + is + use SC_Obligations.BDD; - if CP_CU.Provider = Instrumenter then - if CP_CU.Bit_Maps.Statement_Bits /= null then - for S_SCO of CP_CU.Bit_Maps.Statement_Bits.all loop - Remap_SCO_Id (S_SCO); - end loop; - end if; + Old_SCOD : SCO_Descriptor renames CP_Vectors.SCO_Vector (Old_SCO_Id); + New_SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); - if CP_CU.Bit_Maps.Decision_Bits /= null then - for D_Outcome of CP_CU.Bit_Maps.Decision_Bits.all loop - Remap_SCO_Id (D_Outcome.D_SCO); - end loop; - end if; + Old_Reachable : Reachability renames + Old_SCOD.Decision_BDD.Reachable_Outcomes; + New_Reachable : Reachability renames + New_SCOD.Decision_BDD.Reachable_Outcomes; - if CP_CU.Bit_Maps.MCDC_Bits /= null then - for D_Path of CP_CU.Bit_Maps.MCDC_Bits.all loop - Remap_SCO_Id (D_Path.D_SCO); - end loop; - end if; + function Decision_Static_Eval + (Vectors : Source_Coverage_Vectors; + SCO_Dec : SCO_Id; + Eval : out Static_Decision_Evaluation) return Boolean; - -- Remap blocks information + procedure Register_Static_Evaluation + (SCO : SCO_Id; Eval : Static_Decision_Evaluation); - for Block_Cur in CP_CU.Blocks.Iterate loop - declare - Block_Ref : constant SCO_Id_Vector_Vectors.Reference_Type := - CP_CU.Blocks.Reference (Block_Cur); - begin - for SCO_Cur in Block_Ref.Iterate loop - Remap_SCO_Id (Block_Ref.Reference (SCO_Cur)); - end loop; - end; - end loop; + -------------------------- + -- Decision_Static_Eval -- + -------------------------- - -- Remap macro information + function Decision_Static_Eval + (Vectors : Source_Coverage_Vectors; + SCO_Dec : SCO_Id; + Eval : out Static_Decision_Evaluation) return Boolean + is + SCOD : SCO_Descriptor renames Vectors.SCO_Vector (SCO_Dec); - declare - use SCO_PP_Info_Maps; - Remapped_PP_Info_Map : SCO_PP_Info_Maps.Map; + Reachable : constant Reachability := + SCOD.Decision_BDD.Reachable_Outcomes; + + Outcome : constant Tristate := + (if Reachable (False) /= Reachable (True) + then To_Tristate (Reachable (True)) + else Unknown); + + E : Static_Decision_Evaluation; begin - for Cur in CP_CU.PP_Info_Map.Iterate loop + + -- Do not process evaluations if the decision is not at least + -- partially static. + + if Outcome = Unknown then + return False; + end if; + + E.Outcome := To_Boolean (Outcome); + + for J in Condition_Index'First .. SCOD.Last_Cond_Index + loop declare - Info : PP_Info := Element (Cur); + SCO_C : constant SCO_Id := + Condition (Vectors, SCO_Dec, J); + SCOD_C : SCO_Descriptor renames + Vectors.SCO_Vector (SCO_C); begin - if Info.Kind = In_Expansion then - for Expansion of Info.Expansion_Stack loop - Remap_SFI - (Relocs, - Expansion.Sloc.Source_File); - end loop; - Remap_SFI - (Relocs, - Info.Definition_Loc.Sloc.Source_File); + + -- If an encountered Condition has no Value, then the + -- Decision is not fully static, abort processing + + if SCOD_C.Value = Unknown then + E.Values.Clear; + return False; end if; - declare - SCO : SCO_Id := Key (Cur); - begin - Remap_SCO_Id (SCO); - Remapped_PP_Info_Map.Insert (SCO, Info); - end; + + E.Values.Append (To_Boolean (SCOD_C.Value)); end; end loop; - CP_CU.PP_Info_Map := Remapped_PP_Info_Map; - end; - - -- Remap SCOs span for scope entities - for Scope_Ent of CP_CU.Scope_Entities loop - Remap_SCO_Id (Scope_Ent.From); - Remap_SCO_Id (Scope_Ent.To); + Eval := E; + return True; + end Decision_Static_Eval; - -- Scopes whose identifier references ignored source files will - -- lose their identifier: such scopes will remain, but users will - -- not be able to mark them of interest. + -------------------------------- + -- Register_Static_Evaluation -- + -------------------------------- - if SFI_Ignored (Relocs, Scope_Ent.Identifier.Decl_SFI) then - Scope_Ent.Identifier := No_Scope_Entity_Identifier; - else - Remap_SFI (Relocs, Scope_Ent.Identifier.Decl_SFI); + procedure Register_Static_Evaluation + (SCO : SCO_Id; Eval : Static_Decision_Evaluation) is + begin + if not CLS.Static_Decision_Evaluations.Contains (SCO) + then + CLS.Static_Decision_Evaluations.Insert + (SCO, + Static_Decision_Evaluation_Sets.Empty_Set); end if; + CLS.Static_Decision_Evaluations + .Reference (SCO) + .Include (Eval); + end Register_Static_Evaluation; + + -- Start processing of Merge_Decision_SCOs + + begin + if Old_SCOD.Decision_Instrumented then + New_SCOD.Decision_Instrumented := True; + end if; + if Old_SCOD.Decision_Instrumented_For_MCDC then + New_SCOD.Decision_Instrumented_For_MCDC := True; + end if; + + -- The following code handles merging Decision SCOs that have a + -- different staticness over the 2 checkpoints that are being merged. + -- + -- If the reachability of the decision in one of the checkpoints + -- differs from `Both_Reachable`, it means that at least one of the + -- two checkpoints has some static conditions and should be handled + -- with a specific treatment. + -- + -- Upon encountering a fully-static decision, we need to register its + -- conditions' values so they can be used as a complementary + -- evaluation for MC/DC analysis. + + if Old_Reachable /= Both_Reachable + or else + New_Reachable /= Both_Reachable + then + SCOs_Trace.Trace ("Consolidation encountered a decision SCO" + & " whose staticness may differ at" + & Image (New_SCOD.Sloc_Range)); + declare + Old_Eval : Static_Decision_Evaluation; + -- Holds the result of the static evaluation of Old_SCO + -- if Old_Static is True. Otherwise, it is invalid. - -- Register each scope identifiers to make them available to users - -- on the command line. + New_Eval : Static_Decision_Evaluation; + -- Holds the result of the static evaluation of New_SCO + -- if New_Static is True. Otherwise, it is invalid. - Available_Subps_Of_Interest.Include (Scope_Ent.Identifier); - end loop; - if not SCOs_Nested_And_Ordered (CP_CU.Scope_Entities) then - raise Program_Error - with "Error when loading scopes from checkpoints"; - end if; - end if; + Old_Static : constant Boolean := + Decision_Static_Eval (CP_Vectors, Old_SCO_Id, Old_Eval); + New_Static : constant Boolean := + Decision_Static_Eval (SC_Vectors, New_SCO_Id, New_Eval); - -- Remap ALI annotations + begin - Remap_ALI_Annotations (Relocs, CP_CU.ALI_Annotations); + -- No matter the staticness of the SCOs, we update the + -- reachability of each outcome by OR-ing the two checkpoints. - -- Preallocate line table entries for last file + New_Reachable (True) := New_Reachable (True) or else + Old_Reachable (True); - Prealloc_Lines (Cur_Source_File, Last_Line); + New_Reachable (False) := New_Reachable (False) or else + Old_Reachable (False); - -- Link new SCOs to source line tables + if Old_Static then - for SCO in New_First_SCO .. SCO_Vector.Last_Index loop - declare - SCOD : SCO_Descriptor renames SCO_Vector.Reference (SCO); - begin - if SCOD.Kind in - Statement | Decision | Fun_Call_SCO_Kind | Guarded_Expr - then - Add_SCO_To_Lines (SCO, SCOD); - end if; - end; - end loop; + -- If the decision in the Old checkpoint is static, + -- add an evaluation to the SCIs corresponding to it. - -- Perform final fixups and insert CU + Register_Static_Evaluation (New_SCO_Id, Old_Eval); + end if; - CP_CU.Last_SCO := - New_First_SCO - + CP_CU.Last_SCO - - CP_CU.First_SCO; - CP_CU.First_SCO := New_First_SCO; + if New_Static then - CU_Vector.Append (CP_CU); - Register_CU (New_CU_Id); + -- If the decision in the New checkpoint is static, + -- add an evaluation to the SCIs corresponding to it. - -- If we are loading a SID file, create source coverage data structures. - -- There is no need to do it when loading a checkpoint: that checkpoint - -- was created loading a SID file, and thus already has the - -- corresponding SCI tables populated. + Register_Static_Evaluation (New_SCO_Id, New_Eval); + end if; + end; + end if; + end Merge_Decision_SCOs; - if CLS.Purpose = Instrumentation then - Coverage.Source.Initialize_SCI_For_Instrumented_CU (New_CU_Id); - end if; - end Checkpoint_Load_New_Unit; + ----------------- + -- Ignore_SCOs -- + ----------------- - -------------------------- - -- Checkpoint_Load_Unit -- - -------------------------- + procedure Ignore_SCOs is + begin + for SCO_Range of CP_CU.SCOs loop + for SCO in SCO_Range.First .. SCO_Range.Last loop + Ignore_SCO (Relocs, SCO); + end loop; + end loop; + end Ignore_SCOs; - procedure Checkpoint_Load_Unit - (CLS : in out Checkpoint_Load_State; - CP_Vectors : Source_Coverage_Vectors; - CP_CU : in out CU_Info; - New_CU_Id : out CU_Id) - is - Relocs : Checkpoint_Relocations renames CLS.Relocations; + Actual_CU_Id : CU_Id; begin if CP_CU.Provider = Instrumenter then Instrumented_Units_Present := True; @@ -1938,11 +2350,11 @@ package body SC_Obligations is Remap_SFI (Relocs, CP_CU.Main_Source); for Dep_SFI of CP_CU.Deps loop - -- Units of interest can depend on units outside of the - -- scope of code coverage analysis. Keeping track of these - -- introduces clashes between stubbed units and the real - -- one, so they are excluded from checkpoints. Hence, allow - -- them to be missing here. + -- Units of interest can depend on units outside of the scope of + -- code coverage analysis. Keeping track of these introduces clashes + -- between stubbed units and the real one, so they are excluded from + -- checkpoints. Hence, allow them to be missing here. + if not SFI_Ignored (Relocs, Dep_SFI) then Remap_SFI (Relocs, Dep_SFI); end if; @@ -1950,30 +2362,19 @@ package body SC_Obligations is -- Next check whether this unit is already known - New_CU_Id := Comp_Unit (CP_CU.Main_Source); + Actual_CU_Id := Comp_Unit (CP_CU.Main_Source); SCOs_Trace.Trace - ("Remapped CU: id " & New_CU_Id'Img + ("Remapped CU: id " & Actual_CU_Id'Img & ", main source" & CP_CU.Main_Source'Img & " " & Get_Full_Name (CP_CU.Main_Source, Or_Simple => True)); - -- Case 1: CU not already present. Load all SCO information - -- from checkpoint. + -- If the CU was already loaded, perform consistency checks prior to + -- loading it. - if New_CU_Id = No_CU_Id then - Checkpoint_Load_New_Unit - (CLS, - CP_Vectors, - CP_CU, - New_CU_Id => New_CU_Id); - - -- Case 2: CU already loaded from LI info. Perform consistency checks, - -- skipping the checkpointed unit altogether and emitting a warning if - -- there is a mismatch. Record mapping of checkpoint SCOs otherwise. - - else + if Actual_CU_Id /= No_CU_Id then declare - CU_Record : CU_Info renames CU_Vector.Reference (New_CU_Id); + CU_Record : CU_Info renames CU_Vector.Reference (Actual_CU_Id); function Provider_Image (Provider : SCO_Provider) return String is (case Provider is @@ -1988,6 +2389,8 @@ package body SC_Obligations is -- Helper to refer to the compilation unit in an error message begin + Set_CU_Id_Map (Relocs, CP_CU_Id, Actual_CU_Id); + -- Ignore CU when the provenance of SCOs is inconsistent if CP_CU.Provider /= CU_Record.Provider then @@ -1995,40 +2398,217 @@ package body SC_Obligations is Warn ("SCOs for this unit come from both " & Provider_Image (CP_CU.Provider) & " and from " & Provider_Image (CU_Record.Provider)); + Ignore_SCOs; + return; - -- Ignore also when the fingerprints do not match. - -- - -- Note that only recent enough SID files contain buffer bit maps - -- and their fingerprints. Bit_Maps_Fingerprint is left to - -- No_Fingerprint for checkpoints. Skip the consistency check for - -- these cases, and if the loaded CU has these fingerprints, - -- record them for later consistency checks. + -- Ignore also when the fingerprints do not match - elsif CP_CU.Fingerprint /= CU_Record.Fingerprint + elsif (CP_CU.Provider = Compiler + and then CP_CU.SCOs_Fingerprint + /= CU_Record.SCOs_Fingerprint) or else (CP_CU.Provider = Instrumenter - and then CP_CU.Bit_Maps_Fingerprint /= No_Fingerprint - and then CU_Record.Bit_Maps_Fingerprint /= No_Fingerprint - and then CP_CU.Bit_Maps_Fingerprint - /= CU_Record.Bit_Maps_Fingerprint) + and then CP_CU.Source_Fingerprint + /= CU_Record.Source_Fingerprint) then Warn ("unexpected fingerprint, cannot merge coverage" & " information for " & CU_Image); + Ignore_SCOs; + return; + end if; + end; + end if; - else - if CU_Record.Provider = Instrumenter - and then CU_Record.Bit_Maps_Fingerprint = No_Fingerprint + -- Load the checkpointed information + + declare + Relocs : Checkpoint_Relocations renames CLS.Relocations; + + Is_New_CU : constant Boolean := + not CU_Map.Contains (CP_CU.Main_Source); + -- Whether this is a new compilation unit + + Has_New_SCOs : Boolean; + -- Whether the loaded checkpoint contains additional SCOs for the CU. + -- In this case, load SCOs and scopes from the loaded checkpoint. + + Real_CU_Id : constant CU_Id := + (if Is_New_CU + then CU_Vector.Last_Index + 1 + else CU_Map.Element (CP_CU.Main_Source)); + + type CU_Info_Access is access all CU_Info; + Real_CU : CU_Info_Access; + -- Pointer to the update CU_Info in CU_Vector. This is a new entry + -- into CU_Vector if Is_New_CU, otherwise an existing one. + + begin + Set_CU_Id_Map (Relocs, CP_CU_Id, Real_CU_Id); + + -- If this is a new compilation unit, add a new entry into the + -- CU_Vector. + + if Is_New_CU then + declare + New_CU : CU_Info (CP_CU.Provider); + begin + CU_Vector.Append (New_CU); + end; + end if; + + -- Then, retrieve the newly created (or existing) CU + + Real_CU := + CU_Info_Access (CU_Vector.Reference (Real_CU_Id).Element); + + -- Check if the unit has new SCOs + + Has_New_SCOs := Is_New_CU; + if not Is_New_CU then + for SID_Info in CP_CU.SIDs_Info.Iterate loop + if not Real_CU.SIDs_Info.Contains (SID_Info_Maps.Key (SID_Info)) then - CU_Record.Bit_Maps_Fingerprint := CP_CU.Bit_Maps_Fingerprint; + Has_New_SCOs := True; + exit; end if; - Checkpoint_Load_Merge_Unit - (CLS, - CP_CU => CP_CU, - CP_Vectors => CP_Vectors, - Real_CU_Id => New_CU_Id); + end loop; + end if; + + -- If this is a new CU, initialize the CU fields shared for all + -- versions. + + if Is_New_CU then + Real_CU.Origin := CP_CU.Origin; + Real_CU.Main_Source := CP_CU.Main_Source; + case Real_CU.Provider is + when Compiler | LLVM => + Real_CU.SCOs_Fingerprint := CP_CU.SCOs_Fingerprint; + when Instrumenter => + Real_CU.Source_Fingerprint := CP_CU.Source_Fingerprint; + end case; + CU_Map.Insert (CP_CU.Main_Source, Real_CU_Id); + for Dep_SFI of Real_CU.Deps loop + + -- Units of interest can depend on units outside of the + -- scope of code coverage analysis. Keeping track of these + -- introduces clashes between stubbed units and the real + -- one, so they are excluded from checkpoints. Hence, allow + -- them to be missing here. + + if not SFI_Ignored (Relocs, Dep_SFI) then + Remap_SFI (Relocs, Dep_SFI); + end if; + end loop; + Register_CU (Real_CU_Id); + + else + -- Otherwise, check that the SCOs in the new version are + -- consistent with those previously loaded. + + if not Check_SCOs_Consistency (CLS, CP_Vectors, CP_CU) then + Outputs.Warn + ("Discarding source coverage data for unit " + & Get_Full_Name (Real_CU.Main_Source) & " (from " + & Get_Full_Name (Real_CU.Origin) & "), loaded from " + & (+CLS.Filename)); + return; end if; + end if; + + -- In all cases, load the SCOs: if they already exist in Real_CU, + -- we will remap the SCOs in the loaded checkpoint to the already + -- existing ones. + + Checkpoint_Load_SCOs + (CLS => CLS, + CP_Vectors => CP_Vectors, + CP_CU => CP_CU, + Real_CU => Real_CU.all, + Real_CU_Id => Real_CU_Id); + + -- If this is a new unit / it contains new SCOs, load additional + -- information (SID information, preprocessing information, and + -- scopes). + + if Has_New_SCOs then + + -- Process SID information + + Checkpoint_Load_SID_Info + (CLS => CLS, + CP_CU => CP_CU, + Real_CU => Real_CU.all); + + -- Process macro information + + Checkpoint_Load_PP_Info + (CLS => CLS, + CP_CU => CP_CU, + Real_CU => Real_CU.all); + + -- Process scopes + + Checkpoint_Load_Scopes + (CLS => CLS, + CP_CU => CP_CU, + Real_CU => Real_CU.all); + end if; + + -- Read uninstrumented SCOs for stmt/decision + + for SCO_Range of CP_CU.SCOs loop + for Old_SCO_Id in SCO_Range.First .. SCO_Range.Last loop + declare + Old_SCOD : SCO_Descriptor renames + CP_Vectors.SCO_Vector (Old_SCO_Id); + New_SCO_Id : constant SCO_Id := + Remap_SCO_Id (Relocs, Old_SCO_Id); + SCOD : SCO_Descriptor renames SCO_Vector (New_SCO_Id); + begin + case SCOD.Kind is + when Statement => + if Old_SCOD.Stmt_Instrumented then + SCOD.Stmt_Instrumented := True; + end if; + + when Decision => + Merge_Decision_SCOs (Old_SCO_Id, New_SCO_Id); + + when Fun_Call_SCO_Kind => + if Old_SCOD.Fun_Call_Instrumented then + SCOD.Fun_Call_Instrumented := True; + end if; + + when Guarded_Expr => + if Old_SCOD.GExpr_Instrumented then + SCOD.GExpr_Instrumented := True; + end if; + + when others => + null; + end case; + end; + end loop; + end loop; + + -- Has_Code indication + + Real_CU.Has_Code := Real_CU.Has_Code or CP_CU.Has_Code; + + -- Remap ALI annotations and then merge them + + declare + Remapped_Annotations : ALI_Annotation_Maps.Map := + CP_CU.ALI_Annotations; + begin + Remap_ALI_Annotations (Relocs, Remapped_Annotations); + for Cur in Remapped_Annotations.Iterate loop + Real_CU.ALI_Annotations.Include + (ALI_Annotation_Maps.Key (Cur), + ALI_Annotation_Maps.Element (Cur)); + end loop; end; - end if; + end; end Checkpoint_Load_Unit; ----------- @@ -2065,11 +2645,7 @@ package body SC_Obligations is procedure Write (CSS : in out Checkpoint_Save_State; Value : Scope_Entity) is begin - CSS.Write_SCO (Value.From); - CSS.Write_SCO (Value.To); - - CSS.Write (Value.Start_Sloc); - CSS.Write (Value.End_Sloc); + CSS.Write (Value.Source_Range); CSS.Write (Value.Name); CSS.Write (Value.Sloc); @@ -2078,55 +2654,59 @@ package body SC_Obligations is CSS.Write_Integer (Value.Identifier.Decl_Line); end Write; + procedure Write (CSS : in out Checkpoint_Save_State; Value : SCO_Range) is + begin + CSS.Write_SCO (Value.First); + CSS.Write_SCO (Value.Last); + end Write; + + procedure Write + (CSS : in out Checkpoint_Save_State; Value : SID_Info) is + begin + Write (CSS, Value.Blocks); + CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'First); + CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'Last); + for SCO of Value.Bit_Maps.Statement_Bits.all loop + CSS.Write_SCO (SCO); + end loop; + + CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'First); + CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'Last); + for Info of Value.Bit_Maps.Decision_Bits.all loop + CSS.Write_SCO (Info.D_SCO); + CSS.Write (Info.Outcome); + end loop; + + CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'First); + CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'Last); + for Info of Value.Bit_Maps.MCDC_Bits.all loop + CSS.Write_SCO (Info.D_SCO); + CSS.Write_Integer (Info.Path_Index); + end loop; + + CSS.Write (Value.Bit_Maps_Fingerprint); + CSS.Write (Value.Annotations_Fingerprint); + end Write; + procedure Write (CSS : in out Checkpoint_Save_State; Value : CU_Info) is begin CSS.Write_U8 (SCO_Provider'Pos (Value.Provider)); CSS.Write_SFI (Value.Origin); CSS.Write_SFI (Value.Main_Source); - CSS.Write_SCO (Value.First_SCO); - CSS.Write_SCO (Value.Last_SCO); Write (CSS, Value.Deps); CSS.Write (Value.Has_Code); - CSS.Write (Value.Fingerprint); Write (CSS, Value.PP_Info_Map); Write (CSS, Value.Scope_Entities); Write (CSS, Value.ALI_Annotations); - CSS.Write (Value.Annotations_Fingerprint); + Write (CSS, Value.SCOs); case Value.Provider is - when Compiler | LLVM => - null; - + when Compiler | LLVM => + CSS.Write (Value.SCOs_Fingerprint); when Instrumenter => - if CSS.Purpose_Of = Instrumentation then - CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'First); - CSS.Write_Bit_Id (Value.Bit_Maps.Statement_Bits.all'Last); - for SCO of Value.Bit_Maps.Statement_Bits.all loop - CSS.Write_SCO (SCO); - end loop; - - CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'First); - CSS.Write_Bit_Id (Value.Bit_Maps.Decision_Bits.all'Last); - for Info of Value.Bit_Maps.Decision_Bits.all loop - CSS.Write_SCO (Info.D_SCO); - CSS.Write (Info.Outcome); - end loop; - - CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'First); - CSS.Write_Bit_Id (Value.Bit_Maps.MCDC_Bits.all'Last); - for Info of Value.Bit_Maps.MCDC_Bits.all loop - CSS.Write_SCO (Info.D_SCO); - CSS.Write_Integer (Info.Path_Index); - end loop; - - CSS.Write (Value.Bit_Maps_Fingerprint); - - -- Write the blocks information - - Write (CSS, Value.Blocks); - end if; + Write (CSS, Value.SIDs_Info); + CSS.Write (Value.Source_Fingerprint); end case; - end Write; procedure Write @@ -2207,11 +2787,11 @@ package body SC_Obligations is procedure Free is new Ada.Unchecked_Deallocation (MCDC_Bit_Map, MCDC_Bit_Map_Access); begin - if CU.Provider = Instrumenter then - Free (CU.Bit_Maps.Statement_Bits); - Free (CU.Bit_Maps.Decision_Bits); - Free (CU.Bit_Maps.MCDC_Bits); - end if; + for SID_Info of CU.SIDs_Info loop + Free (SID_Info.Bit_Maps.Statement_Bits); + Free (SID_Info.Bit_Maps.Decision_Bits); + Free (SID_Info.Bit_Maps.MCDC_Bits); + end loop; end Free; --------------------- @@ -2291,9 +2871,8 @@ package body SC_Obligations is declare use CU_Info_Vectors; - CP_CU_Id : constant CU_Id := To_Index (Cur); - CP_CU : CU_Info := Element (Cur); - New_CU_Id : CU_Id := No_CU_Id; + CP_CU_Id : constant CU_Id := To_Index (Cur); + CP_CU : CU_Info := Element (Cur); -- If the CU Origin or its Main_Source files are ignored, we -- cannot load this CU. @@ -2331,8 +2910,7 @@ package body SC_Obligations is (CLS, CP_Vectors, CP_CU, - New_CU_Id => New_CU_Id); - Set_CU_Id_Map (Relocs, CP_CU_Id, New_CU_Id); + CP_CU_Id => CP_CU_Id); end if; end; end loop; @@ -2470,8 +3048,8 @@ package body SC_Obligations is if Last_SCO < First_SCO then Warn ("[LLVM-JSON] No regions to process"); else - CU_Vector (CUID).First_SCO := First_SCO; - CU_Vector (CUID).Last_SCO := Last_SCO; + CU_Vector (CUID).SCOs.Append + (SCO_Range'(First => First_SCO, Last => Last_SCO)); end if; end; end loop; @@ -2560,31 +3138,32 @@ package body SC_Obligations is end if; end Comp_Unit; - --------------- - -- First_SCO -- - --------------- + ---------------- + -- SCO_Ranges -- + ---------------- - function First_SCO (CU : CU_Id) return SCO_Id is + function SCO_Ranges (CU : CU_Id) return SCO_Range_Vectors.Vector is begin if CU = No_CU_Id then - return No_SCO_Id; + return SCO_Range_Vectors.Empty_Vector; else - return CU_Vector.Constant_Reference (CU).First_SCO; + return CU_Vector.Constant_Reference (CU).SCOs; end if; - end First_SCO; + end SCO_Ranges; - -------------- - -- Last_SCO -- - -------------- + ----------- + -- In_CU -- + ----------- - function Last_SCO (CU : CU_Id) return SCO_Id is + function In_CU (CU : CU_Id; SCO : SCO_Id) return Boolean is begin - if CU = No_CU_Id then - return No_SCO_Id; - else - return CU_Vector.Constant_Reference (CU).Last_SCO; - end if; - end Last_SCO; + for SCO_Range of SCO_Ranges (CU) loop + if SCO >= SCO_Range.First and then SCO <= SCO_Range.Last then + return True; + end if; + end loop; + return False; + end In_CU; ----------- -- Index -- @@ -2646,7 +3225,7 @@ package body SC_Obligations is begin -- Search for the first Condition of the Decision. - while C_SCO <= Last_SCO (CU) + while In_CU (CU, C_SCO) and then (Kind (C_SCO) /= Condition or else Parent (C_SCO) /= SCO) loop @@ -2661,13 +3240,13 @@ package body SC_Obligations is Index_Mut := Index_Mut - 1; loop C_SCO := C_SCO + 1; - exit when C_SCO > Last_SCO (CU); + exit when not In_CU (CU, C_SCO); exit when Kind (C_SCO) = Condition and then Parent (C_SCO) = SCO; end loop; end loop; - if C_SCO > Last_SCO (CU) then + if not In_CU (CU, C_SCO) then Fatal_Error ("Malformed SCO Vector, a condition SCO" & " is missing"); end if; @@ -3063,8 +3642,8 @@ package body SC_Obligations is use Sloc_To_SCO_Maps; Position : Cursor := - Sloc_To_SCO_Map (Sloc_End.Source_File, Kind).Floor - ((Sloc_End.L, No_Local_Location)); + Sloc_To_SCO_Map (Sloc_End.Source_File, Kind).Floor + ((Sloc_End.L, No_Local_Location)); begin while Position /= No_Element loop declare @@ -3299,25 +3878,15 @@ package body SC_Obligations is --------------- function Comp_Unit (SCO : SCO_Id) return CU_Id is - LB, UB, Middle : Valid_CU_Id; begin - -- Assume that compilation units in CU_Vector are ordered by SCO range - -- to look up efficiently (by dichotomy) the compilation unit for the - -- SCO. + -- TODO??? we are losing the logarithmic complexity - LB := CU_Vector.First_Index; - UB := CU_Vector.Last_Index; - while LB <= UB loop - Middle := LB + (UB - LB) / 2; + for Cur in CU_Vector.Iterate loop declare - CU : CU_Info renames CU_Vector.Constant_Reference (Middle); + CU : constant CU_Id := CU_Info_Vectors.To_Index (Cur); begin - if SCO in CU.First_SCO .. CU.Last_SCO then - return Middle; - elsif SCO < CU.First_SCO then - UB := Middle - 1; - else - LB := Middle + 1; + if In_CU (CU, SCO) then + return CU; end if; end; end loop; @@ -3723,29 +4292,20 @@ package body SC_Obligations is -- Fingerprint -- ----------------- - function Fingerprint (CU : CU_Id) return Fingerprint_Type is + function Fingerprint (CU : CU_Id) return Fingerprint_Type + is + SID_Infos : constant SID_Info_Maps.Map := + CU_Vector.Element (CU).SIDs_Info; begin - return CU_Vector.Reference (CU).Fingerprint; + if SID_Infos.Length /= 1 then + Outputs.Fatal_Error + ("Found multiple versions for " + & Get_Full_Name (CU_Vector.Element (CU).Main_Source)); + end if; + pragma Assert (SID_Infos.Length = 1); + return SID_Infos.First_Key; end Fingerprint; - -------------------------- - -- Bit_Maps_Fingerprint -- - -------------------------- - - function Bit_Maps_Fingerprint (CU : CU_Id) return Fingerprint_Type is - begin - return CU_Vector.Reference (CU).Bit_Maps_Fingerprint; - end Bit_Maps_Fingerprint; - - ----------------------------- - -- Annotations_Fingerprint -- - ----------------------------- - - function Annotations_Fingerprint (CU : CU_Id) return Fingerprint_Type is - begin - return CU_Vector.Reference (CU).Annotations_Fingerprint; - end Annotations_Fingerprint; - --------------- -- Load_SCOs -- --------------- @@ -3765,7 +4325,7 @@ package body SC_Obligations is ALI_Index : constant Source_File_Index := Load_ALI (ALI_Filename, Ignored_Source_Files, Units, Deps, Temp_ALI_Annotations, With_SCOs => True); - -- Load ALI file and update the last SCO index + -- Load ALI file and update the last SCO begin if ALI_Index = No_Source_File then @@ -4050,11 +4610,14 @@ package body SC_Obligations is Created_Units : in out Created_Unit_Maps.Map) return CU_Id is use Created_Unit_Maps; + use GNATCOLL.VFS; New_CU_Info : CU_Info (Provider); - CU_Index : constant CU_Id := Comp_Unit (Main_Source); - Cur : constant Cursor := Created_Units.Find (Main_Source); + CU_Index : constant CU_Id := Comp_Unit (Main_Source); + CU_Version : SID_Info; + Cur : constant Cursor := Created_Units.Find (Main_Source); + begin -- Check whether there is already a compilation unit for this main -- source. @@ -4074,7 +4637,7 @@ package body SC_Obligations is -- this duplicate, and return no CU to signify to the caller that we -- must abort the loading. - if CU_Vector.Reference (CU_Index).Fingerprint = Fingerprint then + if SC_Obligations.Fingerprint (CU_Index) = Fingerprint then return No_CU_Id; end if; @@ -4117,9 +4680,30 @@ package body SC_Obligations is New_CU_Info.Origin := Origin; New_CU_Info.Main_Source := Main_Source; - New_CU_Info.First_SCO := Valid_SCO_Id'First; - New_CU_Info.Last_SCO := No_SCO_Id; - New_CU_Info.Fingerprint := Fingerprint; + New_CU_Info.SIDs_Info.Insert (Fingerprint, CU_Version); + + -- Also create the fingerprint: the SCOs fingerprint for binary traces, + -- which is still used for consistency checks, and the source + -- fingerprint for source traces. + + case Provider is + when Compiler | LLVM => + New_CU_Info.SCOs_Fingerprint := Fingerprint; + when Instrumenter => + declare + Source_Fingerprint_Context : GNAT.SHA1.Context; + Contents : GNAT.Strings.String_Access := + Read_File (Create (+Get_Full_Name (Main_Source))); + begin + GNAT.SHA1.Update (Source_Fingerprint_Context, Contents.all); + Free (Contents); + New_CU_Info.Source_Fingerprint := + Fingerprint_Type + (GNAT.SHA1.Binary_Message_Digest' + (GNAT.SHA1.Digest (Source_Fingerprint_Context))); + end; + end case; + CU_Vector.Append (New_CU_Info); return Result : constant CU_Id := CU_Vector.Last_Index do @@ -4548,8 +5132,10 @@ package body SC_Obligations is begin Unit.Deps := Deps; - Unit.First_SCO := First_SCO; - Unit.Last_SCO := SCO_Vector.Last_Index; + Unit.SCOs.Append + (SCO_Range' + (First => First_SCO, + Last => SCO_Vector.Last_Index)); end; end; @@ -5207,7 +5793,8 @@ package body SC_Obligations is function Are_Bit_Maps_In_Range (Bit_Maps : CU_Bit_Maps; CU : CU_Info) return Boolean is - subtype SCO_Range is SCO_Id range CU.First_SCO .. CU.Last_SCO; + subtype SCO_Range is + SCO_Id range CU.SCOs.First_Element.First .. CU.SCOs.First_Element.Last; begin return (for all SCO of Bit_Maps.Statement_Bits.all => SCO in SCO_Range) @@ -5225,6 +5812,8 @@ package body SC_Obligations is use GNAT.SHA1; Info : CU_Info renames CU_Vector.Reference (CU); + CU_Version : SID_Info renames + Info.SIDs_Info.Reference (Info.SIDs_Info.First); Ctx : GNAT.SHA1.Context; LF : constant String := (1 => ASCII.LF); @@ -5253,7 +5842,7 @@ package body SC_Obligations is ------------ procedure Update (SCO : SCO_Id) is - Relative_SCO : constant SCO_Id := SCO - Info.First_SCO; + Relative_SCO : constant SCO_Id := SCO - Info.SCOs.First_Element.First; begin Update (Ctx, Relative_SCO'Image); end Update; @@ -5261,7 +5850,7 @@ package body SC_Obligations is begin pragma Assert (Are_Bit_Maps_In_Range (Bit_Maps, Info)); - Info.Bit_Maps := Bit_Maps; + CU_Version.Bit_Maps := Bit_Maps; -- Compute the fingerprint for these bit maps @@ -5285,7 +5874,7 @@ package body SC_Obligations is end loop; Update (Ctx, LF); - Info.Bit_Maps_Fingerprint := Fingerprint_Type + CU_Version.Bit_Maps_Fingerprint := Fingerprint_Type (GNAT.SHA1.Binary_Message_Digest'(GNAT.SHA1.Digest (Ctx))); end Set_Bit_Maps; @@ -5295,8 +5884,10 @@ package body SC_Obligations is procedure Set_Blocks (CU : CU_Id; Blocks : SCO_Id_Vector_Vector) is Info : CU_Info renames CU_Vector.Reference (CU); + CU_Version : SID_Info renames + Info.SIDs_Info.Reference (Info.SIDs_Info.First); begin - Info.Blocks := Blocks; + CU_Version.Blocks := Blocks; end Set_Blocks; --------------------- @@ -5312,6 +5903,31 @@ package body SC_Obligations is Current_Ctx : GNAT.SHA1.Context := Initial_Context; -- Current file being processed + procedure Set_Annotations_Fingerprint; + -- Set the annotations fingerprint for Current_CU if it is not null, + -- stored in Current_Ctx. + + --------------------------------- + -- Set_Annotations_Fingerprint -- + --------------------------------- + + procedure Set_Annotations_Fingerprint is + begin + if Current_CU /= No_CU_Id then + declare + SID_Maps : SID_Info_Maps.Map renames + CU_Vector.Reference (Current_CU).SIDs_Info; + SID : SID_Info renames + SID_Maps.Reference (SID_Maps.First); + begin + SID.Annotations_Fingerprint := + Fingerprint_Type + (GNAT.SHA1.Binary_Message_Digest' + (GNAT.SHA1.Digest (Current_Ctx))); + end; + end if; + end Set_Annotations_Fingerprint; + begin -- As a reminder, Source_Location sort on the file index first, so we -- are guaranteed to have annotations grouped by source files. @@ -5326,12 +5942,7 @@ package body SC_Obligations is -- dump the annotations fingerprint that was processed. if Sloc.Source_File /= Current_SFI then - if Current_CU /= No_CU_Id then - CU_Vector.Reference (Current_CU).Annotations_Fingerprint := - Fingerprint_Type - (GNAT.SHA1.Binary_Message_Digest' - (GNAT.SHA1.Digest (Current_Ctx))); - end if; + Set_Annotations_Fingerprint; Current_Ctx := Initial_Context; Current_SFI := Sloc.Source_File; Current_CU := Comp_Unit (Current_SFI); @@ -5345,12 +5956,7 @@ package body SC_Obligations is (Sloc, Ann); end; end loop; - if Current_CU /= No_CU_Id then - CU_Vector.Reference (Current_CU).Annotations_Fingerprint := - Fingerprint_Type - (GNAT.SHA1.Binary_Message_Digest' - (GNAT.SHA1.Digest (Current_Ctx))); - end if; + Set_Annotations_Fingerprint; end Set_Annotations; ------------------------ @@ -5378,9 +5984,11 @@ package body SC_Obligations is -- Exception raised when the nesting/ordering invariant is found to be -- broken. - Lower_Bound : SCO_Id := No_SCO_Id; - -- At every step of the check, this designates the minimum possible SCO - -- value for the .From component for the next element to inspect. + Lower_Bound : Local_Source_Location := + Local_Source_Location'(Line => 1, Column => 0); + -- At every step of the check, this designates the minimum possible + -- source location value for the .Source_Range.L.First_Sloc component + -- for the next element to inspect. procedure Check_Element (Cur : Cursor); -- Check that Cur's From/To SCOs range is not empty and @@ -5394,14 +6002,14 @@ package body SC_Obligations is SE : Scope_Entity renames Tree.Constant_Reference (Cur); Child : Cursor := First_Child (Cur); - Last : SCO_Id; - -- SCO range upper bound for Cur's last child, or SE.From if there is - -- no child. + Last : Local_Source_Location; + -- Source_Location upper bound for Cur's last child, or + -- SE.Source_Range.First_Sloc if there is no child. begin - -- Check that SCO ranges are never empty + -- Check that source ranges are never empty - if SE.From > SE.To then - raise Failure with "empty SCO range for " & Image (SE); + if SE.Source_Range.L.Last_Sloc < SE.Source_Range.L.First_Sloc then + raise Failure with "empty source range for " & Image (SE); end if; -- Check that the SCO range lower bound is both: @@ -5412,11 +6020,12 @@ package body SC_Obligations is -- * greater than the previous sibling (if any: this checks the -- ordering). - if SE.From < Lower_Bound then - raise Failure with "SCO lower bound too low for " & Image (SE); + if SE.Source_Range.L.First_Sloc < Lower_Bound then + raise Failure with + "source range lower bound too low for " & Image (SE); end if; - Lower_Bound := SE.From; - Last := SE.From; + Lower_Bound := SE.Source_Range.L.First_Sloc; + Last := SE.Source_Range.L.First_Sloc; while Has_Element (Child) loop Check_Element (Child); @@ -5425,17 +6034,21 @@ package body SC_Obligations is -- The next sibling's SCO range cannot overlap with the current's - Lower_Bound := Lower_Bound + 1; + Lower_Bound := + Local_Source_Location' + (Line => Lower_Bound.Line, + Column => Lower_Bound.Column + 1); end loop; -- Check that the SCO range upper bound is greater or equal to -- the upper bound of the last child's upper bound (this is the -- second half of the nesting check). - if SE.To < Last then - raise Failure with "SCO higher bound too low for " & Image (SE); + if SE.Source_Range.L.Last_Sloc < Last then + raise Failure with + "Source location bound too low for " & Image (SE); end if; - Lower_Bound := SE.To; + Lower_Bound := SE.Source_Range.L.Last_Sloc; end Check_Element; Cur : Cursor := First_Child (Tree.Root); @@ -5465,6 +6078,37 @@ package body SC_Obligations is return False; end SCOs_Nested_And_Ordered; + ----------- + -- Floor -- + ----------- + + function Floor + (Tree : Scope_Entities_Trees.Tree; + Sloc : Source_Location) return Scope_Entities_Trees.Cursor + is + use Scope_Entities_Trees; + + Result : Scope_Entities_Trees.Cursor := Scope_Entities_Trees.No_Element; + + procedure Process_Node (Cur : Cursor); + + ------------------ + -- Process_Node -- + ------------------ + + procedure Process_Node (Cur : Cursor) is + begin + if In_Range (Sloc, Element (Cur).Source_Range) then + Result := Cur; + Iterate_Children (Cur, Process_Node'Access); + end if; + end Process_Node; + + begin + Iterate_Children (Tree.Root, Process_Node'Access); + return Result; + end Floor; + ---------------- -- Covers_SCO -- ---------------- @@ -5476,6 +6120,22 @@ package body SC_Obligations is and then Scope_Entities_Trees.Is_Root (ST.Cur)) or else Covers_SCO (Scope_Entities_Trees.Element (ST.Cur), SCO)); + ------------------ + -- Contains_SCO -- + ------------------ + + function Contains_SCO (SCO : SCO_Id; CU : CU_Id) return Boolean + is + Unit : CU_Info renames CU_Vector.Reference (CU); + begin + for SCO_Range of Unit.SCOs loop + if SCO in SCO_Range.First .. SCO_Range.Last then + return True; + end if; + end loop; + return False; + end Contains_SCO; + ------------------------ -- Set_Scope_Entities -- ------------------------ @@ -6285,7 +6945,7 @@ package body SC_Obligations is -- operand, if it is a condition. Cur := Sloc_To_SCO_Map (Sloc.Source_File, Operator).Find - ((Sloc.L, No_Local_Location)); + ((Sloc.L, No_Local_Location)); if Cur /= No_Element then SCO := Element (Cur); while Kind (SCO) = Operator and then Op_Kind (SCO) = Op_Not loop @@ -6377,9 +7037,7 @@ package body SC_Obligations is Cur := Sloc_To_SCO_Map (Sloc.Source_File, Decision) .Find ((Sloc.L, No_Local_Location)); - if Cur = No_Element then - SCO := No_SCO_Id; - else + if Cur /= No_Element then pragma Assert (SCO = No_SCO_Id or else SCO = Enclosing_Statement (Element (Cur))); diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index f4e310214..cafa9da99 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -133,13 +133,8 @@ package SC_Obligations is No_Fingerprint : constant Fingerprint_Type := (others => 0); function Fingerprint (CU : CU_Id) return Fingerprint_Type; - -- Hash of SCO info in ALI, for incremental coverage consistency check - - function Bit_Maps_Fingerprint (CU : CU_Id) return Fingerprint_Type; - -- Hash of buffer bit mappings in CU - - function Annotations_Fingerprint (CU : CU_Id) return Fingerprint_Type; - -- Hash of annotations in CU + -- Assuming the CU has only one SID version, return its fingerprint. See + -- CU_Info.SID_Info for more information. function Comp_Unit (Src_File : Source_File_Index) return CU_Id; -- Return the identifier for the compilation unit containing the given @@ -260,14 +255,6 @@ package SC_Obligations is -- -- Deps are the dependencies of the compilation. - --------------- - -- Instances -- - --------------- - - type Inst_Id is new Natural; - No_Inst_Id : constant Inst_Id := 0; - subtype Valid_Inst_Id is Inst_Id range No_Inst_Id + 1 .. Inst_Id'Last; - --------------------------------- -- Source Coverage Obligations -- --------------------------------- @@ -309,15 +296,10 @@ package SC_Obligations is else L.Decl_SFI < R.Decl_SFI); type Scope_Entity is record - From, To : SCO_Id; - -- SCO range for this scope. As scope entities are computed during - -- instrumentation, From and To designate low level SCOs that are then - -- converted to high level SCOs after processing the low level SCOs. - - Start_Sloc, End_Sloc : Local_Source_Location; - -- Start/End_Sloc for this scope. This is more precise than the SCO - -- range as the SCO range may skip over lines with disabled coverage, - -- which we want to report on. + Source_Range : Source_Location_Range; + -- Source_Location_Range for this scope. This is more precise than the + -- SCO range as the SCO range may skip over lines with disabled + -- coverage, which we want to report on. Name : Unbounded_String; Sloc : Local_Source_Location; @@ -325,6 +307,14 @@ package SC_Obligations is Identifier : Scope_Entity_Identifier; -- Identifier for this scope entity + + -- Below are the fields only used when instrumenting and not stored in + -- checkpoints. + + Start_SCO : SCO_Id; + -- Index of the expected start SCO. This is used to discard scopes + -- without any SCOs at instrumentation time. + end record; -- Scope_Entity (SE) stores the SCO range, the name and the sloc of a SE. -- Note that we assume that the SCOs of a SE can be designated by a range. @@ -367,12 +357,6 @@ package SC_Obligations is -- Utilities type to efficiently traverse the scopes in a compilation unit. -- This is a tree-like data structure, with an iterator pointing to the -- currently traversed inner scope. - -- - -- The intended use is to create a Scope_Traversal_Type using the - -- Scope_Traversal function, and then call Traverse_SCO every time - -- we traverse a SCO to update the scope traversal iterator, and call - -- Is_Active to know whether a given scope is active in the given - -- traversal. function Scope_Traversal (CU : CU_Id) return Scope_Traversal_Type; -- Return a scope traversal for the given compilation unit @@ -388,13 +372,11 @@ package SC_Obligations is -- (i.e. consider that all subprograms are of interest in that case). No_Scope_Entity : constant Scope_Entity := - (From => No_SCO_Id, - To => No_SCO_Id, - Start_Sloc => No_Local_Location, - End_Sloc => No_Local_Location, - Name => +"", - Sloc => No_Local_Location, - Identifier => No_Scope_Entity_Identifier); + (Source_Range => No_Range, + Name => +"", + Sloc => No_Local_Location, + Identifier => No_Scope_Entity_Identifier, + Start_SCO => No_SCO_Id); type Any_SCO_Kind is (Removed, Statement, Decision, Condition, Operator, Fun, Call, @@ -906,13 +888,46 @@ package SC_Obligations is "=" => SCO_Id_Vectors."="); subtype SCO_Id_Vector_Vector is SCO_Id_Vector_Vectors.Vector; - function Bit_Maps (CU : CU_Id) return CU_Bit_Maps; + function Has_Fingerprint + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return Boolean; + -- Return whether there is a match for the given CU and SCO_Fingerprint + + package Fingerprint_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, + Element_Type => Fingerprint_Type); + + function Fingerprints (CU : CU_Id) return Fingerprint_Vectors.Vector; + -- Return the fingerprints for all the different versions of the + -- compilation unit identified by CU. + + function Bit_Maps + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return CU_Bit_Maps; + -- For a unit whose coverage is assessed through source code + -- instrumentation, return bit maps for the version of the compilation unit + -- denoted by SCO_Fingerprint. + + function Bit_Maps_Fingerprint + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return Fingerprint_Type; + -- For a unit whose coverage is assessed through source code + -- instrumentation, return the bit maps fingerprint for the version of the + -- compilation unit denoted by SCO_Fingerprint. + + function Annotations_Fingerprint + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return Fingerprint_Type; -- For a unit whose coverage is assessed through source code - -- instrumentation, return bit maps. + -- instrumentation, return the annotations fingerprint for the version of + -- the compilation unit denoted by SCO_Fingerprint. - function Blocks (CU : CU_Id) return SCO_Id_Vector_Vector; + function Blocks + (CU : CU_Id; + SCO_Fingerprint : Fingerprint_Type) return SCO_Id_Vector_Vector; -- For a unit whose coverage is assessed through source code - -- instrumentation, return blocks information. + -- instrumentation, return blocks information for the version of the + -- compilation unit denoted by SCO_Fingerprint. procedure Set_Bit_Maps (CU : CU_Id; Bit_Maps : CU_Bit_Maps); -- Set the tables mapping source trace bit indices to SCO discharge info @@ -1005,11 +1020,22 @@ package SC_Obligations is -- Accessors for CU_Info -- --------------------------- - function First_SCO (CU : CU_Id) return SCO_Id; - -- Return the first SCO of the compilation unit + type SCO_Range is record + First, Last : SCO_Id; + end record; + + function "=" (L, R : SCO_Range) return Boolean + is (L.First = R.First and then R.Last = L.Last); + + package SCO_Range_Vectors is new Ada.Containers.Vectors + (Index_Type => Positive, + Element_Type => SCO_Range); + + function SCO_Ranges (CU : CU_Id) return SCO_Range_Vectors.Vector; + -- Return the list of SCOs for the compilation unit - function Last_SCO (CU : CU_Id) return SCO_Id; - -- Return the last SCO of the compilation unit + function In_CU (CU : CU_Id; SCO : SCO_Id) return Boolean; + -- Return whether SCO pertain to CU ------------- -- Pragmas -- diff --git a/tools/gnatcov/slocs.ads b/tools/gnatcov/slocs.ads index 9656d2144..eb46e1917 100644 --- a/tools/gnatcov/slocs.ads +++ b/tools/gnatcov/slocs.ads @@ -74,8 +74,8 @@ package Slocs is function "<" (L, R : Source_Location) return Boolean; function "<=" (L, R : Source_Location) return Boolean; - No_Location : constant Source_Location := - (No_Source_File, No_Local_Location); + No_Location : constant Source_Location := + (No_Source_File, No_Local_Location); -- Note: No_Location must sort higher than any non-null location function Image From ec550b3391ee4328d48bea363a4a0809124740fc Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 26 Aug 2025 12:07:46 +0200 Subject: [PATCH 1393/1483] Fix performance issue for CU_Id lookup Maintain a mapping from SCO to CU_Id to avoid having to loop through the CU_Vector table when retrieving the CU_Id for a given SCO_Id. --- tools/gnatcov/sc_obligations.adb | 39 ++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 6cad5f7db..12118dee2 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -525,8 +525,12 @@ package body SC_Obligations is Removed_SCO_Descriptor : constant SCO_Descriptor := (Kind => Removed); package SCO_Vectors is new Ada.Containers.Vectors - (Index_Type => Valid_SCO_Id, - Element_Type => SCO_Descriptor); + (Index_Type => Valid_SCO_Id, + Element_Type => SCO_Descriptor); + + package SCO_To_CU_Vectors is new Ada.Containers.Vectors + (Index_Type => Valid_SCO_Id, + Element_Type => CU_Id); function Next_BDD_Node (SCO : SCO_Id; @@ -566,9 +570,10 @@ package body SC_Obligations is -- contain data loaded from a checkpoint. type Source_Coverage_Vectors is record - CU_Vector : CU_Info_Vectors.Vector; - BDD_Vector : BDD.BDD_Vectors.Vector; - SCO_Vector : SCO_Vectors.Vector; + CU_Vector : CU_Info_Vectors.Vector; + BDD_Vector : BDD.BDD_Vectors.Vector; + SCO_Vector : SCO_Vectors.Vector; + SCO_To_CU_Vector : SCO_To_CU_Vectors.Vector; end record; function Index @@ -958,6 +963,10 @@ package body SC_Obligations is SCO_Vector : SCO_Vectors.Vector renames SC_Vectors.SCO_Vector; -- Vector of high-level Source Coverage Obligations (for all units) + SCO_To_CU_Vector : SCO_To_CU_Vectors.Vector renames + SC_Vectors.SCO_To_CU_Vector; + -- Mapping of SCO_Id to CU, for performance purposes + ----------- -- Image -- ----------- @@ -1700,6 +1709,7 @@ package body SC_Obligations is (Files_Table.Last_Line (Get_File (Cur_Source_File)), New_SCOD.Sloc_Range.L.Last_Sloc.Line); SCO_Vector.Append (New_SCOD); + SCO_To_CU_Vector.Append (Real_CU_Id); -- Add it into the Sloc_To_SCO_Map @@ -3021,6 +3031,7 @@ package body SC_Obligations is others => <>); end case; SCO_Vector.Append (SCOD); + SCO_To_CU_Vector.Append (CUID); SCO := SCO_Vector.Last_Index; -- Keep a reference to the just added SCO id. @@ -3069,6 +3080,7 @@ package body SC_Obligations is CU_Vector.Clear; BDD_Vector.Clear; SCO_Vector.Clear; + SCO_To_CU_Vector.Clear; end Checkpoint_Clear; --------------------- @@ -3879,18 +3891,10 @@ package body SC_Obligations is function Comp_Unit (SCO : SCO_Id) return CU_Id is begin - -- TODO??? we are losing the logarithmic complexity - - for Cur in CU_Vector.Iterate loop - declare - CU : constant CU_Id := CU_Info_Vectors.To_Index (Cur); - begin - if In_CU (CU, SCO) then - return CU; - end if; - end; - end loop; - return No_CU_Id; + if SCO = No_SCO_Id then + return No_CU_Id; + end if; + return SCO_To_CU_Vector.Element (SCO); end Comp_Unit; ----------- @@ -4771,6 +4775,7 @@ package body SC_Obligations is New_SCO : SCO_Id; begin SCO_Vector.Append (SCOD); + SCO_To_CU_Vector.Append (CU); New_SCO := SCO_Vector.Last_Index; if SCO_Map /= null then SCO_Map (SCO_Index) := New_SCO; From 55f248235f2fb446f3a5ec030b47485c98e08f00 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Mon, 11 Aug 2025 12:23:58 +0200 Subject: [PATCH 1394/1483] html report: make lineNumber an integer value --- tools/gnatcov/annotations-dynamic_html.adb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 08c56eeae..1090abefe 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -648,7 +648,7 @@ package body Annotations.Dynamic_Html is Clear (Pp.Current_SCOs); Clear (Pp.Current_Conditions); - Line_Obj.Set_Field ("lineNumber", Img (Line_Num)); + Line_Obj.Set_Field ("lineNumber", Line_Num); Line_Obj.Set_Field ("src", Line); Mapping.Set_Field ("coverage", Coverage_State); From f943ba758a8ecf411217b887e8ed1c5652c0d3c0 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 26 Aug 2025 09:32:03 +0000 Subject: [PATCH 1395/1483] integrated_instrumentation/architecture_switches: extend comment --- .../integrated_instrumentation/architecture_switches/test.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/testsuite/tests/integrated_instrumentation/architecture_switches/test.py b/testsuite/tests/integrated_instrumentation/architecture_switches/test.py index a24f8842f..6ab95b4cd 100644 --- a/testsuite/tests/integrated_instrumentation/architecture_switches/test.py +++ b/testsuite/tests/integrated_instrumentation/architecture_switches/test.py @@ -28,7 +28,10 @@ # Shadow the compiler driver with the generated wrapper env.add_search_path(env_var="PATH", path=os.getcwd()) -# Try to compile the source. The test used to fail there. +# Try to compile the source: the test used to fail there, because gnatcov used +# to run partial linking ("gcc -r"), to combine the actual code unit +# (expectedly built with -m32) with the coverage buffer unit (unexpectedly +# built with default settings: -m64), which the linker rejected. cmdrun(["gcc", "-m32", "../pkg.c", "-c"], for_pgm=False) thistest.result() From 9ccc46e3f3aed0e9d10ae4eae3ee7402dfd83331 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 26 Aug 2025 09:34:12 +0000 Subject: [PATCH 1396/1483] integrated_instrumentation/architecture_switches: kill on !x86_64 --- .../architecture_switches/test.opt | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 testsuite/tests/integrated_instrumentation/architecture_switches/test.opt diff --git a/testsuite/tests/integrated_instrumentation/architecture_switches/test.opt b/testsuite/tests/integrated_instrumentation/architecture_switches/test.opt new file mode 100644 index 000000000..e2424aac9 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/architecture_switches/test.opt @@ -0,0 +1,12 @@ +-- This tests the fixes that makes gnatcov pass the architecture-specific +-- compiler switches (-m*) to: +-- +-- 1. the compilation of buffer units, +-- 2. the compilation of buffer list units, +-- 3. the partial linking command that merges object files for the buffer +-- unit and the corresponding "user" unit. +-- +-- Since 1 and 2 are just data units (they contain no subprogram), the only +-- switch that is relevant in this context is "-m32" from x86_64 toolchains, +-- so running this test makes no sense in other contexts. +!x86_64 DEAD From 465a74177159dee4b48d5faaf3c646b4b646643a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 26 Aug 2025 09:58:15 +0000 Subject: [PATCH 1397/1483] U211-014-setup: add XFAIL for aarch64-linux --- testsuite/tests/U211-014-setup/test.opt | 1 + 1 file changed, 1 insertion(+) create mode 100644 testsuite/tests/U211-014-setup/test.opt diff --git a/testsuite/tests/U211-014-setup/test.opt b/testsuite/tests/U211-014-setup/test.opt new file mode 100644 index 000000000..3914d22d8 --- /dev/null +++ b/testsuite/tests/U211-014-setup/test.opt @@ -0,0 +1 @@ +aarch64-linux XFAIL Ongoing work for eng/shared/anod#677 From 532207d26e4c045b7e1e10a87c1ee2e1a45d8de7 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 26 Aug 2025 14:24:46 +0000 Subject: [PATCH 1398/1483] Subprocesses: use the index-returning Wait_For_Processes function Using the `Wait_For_Processes` overload in `GNATCOLL.OS.Process` that returns the process handle index in the input array allows to remove the loop to re-discover that index, and opens the way to simplify code. No change of behavior intended. --- tools/gnatcov/subprocesses.adb | 39 ++++++---------------------------- 1 file changed, 7 insertions(+), 32 deletions(-) diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index ce80b693c..11f741e6f 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -350,47 +350,25 @@ package body Subprocesses is function Wait_And_Finalize (Self : in out Process_Pool) return Positive is - Terminated_Process : Process_Handle := Invalid_Handle; - Id : Positive; - -- Terminated process - - Success : Boolean; - -- Status of the process that terminated + -- Wait until one process terminates, then free its pool slot + Id : constant Positive := Wait_For_Processes (Self.Handles); + Success : constant Boolean := Wait (Self.Handles (Id)) = 0; + Info : Process_Info renames Self.Process_Infos (Id); begin - while Terminated_Process = Invalid_Handle loop - - -- Wait until one process terminates - - Terminated_Process := - Wait_For_Processes (Self.Handles, Duration'Last); - end loop; - Self.Nb_Running_Processes := Self.Nb_Running_Processes - 1; - -- Find the id of the process that terminated - - for I in Self.Handles'Range loop - if Self.Handles (I) = Terminated_Process then - Id := I; - end if; - end loop; - - -- Get its termination status - - Success := Wait (Self.Handles (Id)) = 0; - -- Dump the output of the process that terminated to stdout if it was -- not redirected to a file. - if Self.Process_Infos (Id).Output_To_Stdout then + if Info.Output_To_Stdout then declare Output_File : Mapped_File; Region : Mapped_Region; Str : Str_Access; Str_Last : Natural; begin - Output_File := Open_Read (+Self.Process_Infos (Id).Output_File); + Output_File := Open_Read (+Info.Output_File); Region := Read (Output_File); Str := Data (Region); Str_Last := Last (Region); @@ -415,10 +393,7 @@ package body Subprocesses is -- If the subprocess terminated with an error, deal with it here Check_Status - (Success, - Self.Process_Infos (Id).Ignore_Error, - +Self.Process_Infos (Id).Command, - +Self.Process_Infos (Id).Origin_Command_Name); + (Success, Info.Ignore_Error, +Info.Command, +Info.Origin_Command_Name); return Id; end Wait_And_Finalize; From c0a0d95aa7cee1b92d6ef7c6d8efaf0b091af94e Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 26 Aug 2025 14:54:02 +0000 Subject: [PATCH 1399/1483] Subprocesses: ensure no process handle is left uninitialized Use the explicit constant Invalid_Handle for free slots in the `Handles` process handle array (both at pool initialization and when a process terminates). This will avoid unexpectedly waiting for a process that is not part of the pool (rare, but possible, if a PID gets reused on the host, or if uninitialized slot contains a valid PID by chance). --- tools/gnatcov/subprocesses.adb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 11f741e6f..aaa9d66ef 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -356,6 +356,7 @@ package body Subprocesses is Success : constant Boolean := Wait (Self.Handles (Id)) = 0; Info : Process_Info renames Self.Process_Infos (Id); begin + Self.Handles (Id) := Invalid_Handle; Self.Nb_Running_Processes := Self.Nb_Running_Processes - 1; -- Dump the output of the process that terminated to stdout if it was @@ -474,6 +475,7 @@ package body Subprocesses is procedure Initialize (Pool : in out Process_Pool) is begin Create_Temporary_Directory (Pool.Output_Dir, "gnatcov_outputs"); + Pool.Handles := (others => Invalid_Handle); Pool.Nb_Running_Processes := 0; end Initialize; From da29476ad97ef8a993b04f6bd2c5d90f37493787 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 26 Aug 2025 15:08:25 +0000 Subject: [PATCH 1400/1483] Subprocesses: workaround a GNATCOLL.OS.Process bug --- tools/gnatcov/subprocesses.adb | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index aaa9d66ef..2f55bb92a 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -350,12 +350,36 @@ package body Subprocesses is function Wait_And_Finalize (Self : in out Process_Pool) return Positive is - -- Wait until one process terminates, then free its pool slot + function Find_Waitable return Positive; + -- Wait until one process terminates, then return its index in + -- Self.Handle. - Id : constant Positive := Wait_For_Processes (Self.Handles); + ------------------- + -- Find_Waitable -- + ------------------- + + function Find_Waitable return Positive is + Result : Integer := WAIT_TIMEOUT; + begin + -- Use a long timeout (one hour) to avoid busy polling instead of + -- using INFINITE_TIMEOUT to workaround a GNATCOLL.OS.Process bug. + + while Result = WAIT_TIMEOUT loop + Result := Wait_For_Processes (Self.Handles, 3600.0); + end loop; + pragma Assert (Result in Self.Handles'Range); + return Result; + end Find_Waitable; + + Id : constant Positive := Find_Waitable; Success : constant Boolean := Wait (Self.Handles (Id)) = 0; Info : Process_Info renames Self.Process_Infos (Id); + + -- Start of processing for Wait_And_Finalize + begin + -- Free the pool slot for this terminated process + Self.Handles (Id) := Invalid_Handle; Self.Nb_Running_Processes := Self.Nb_Running_Processes - 1; From 222d34df15979c3161f5e1919f62b0f44d754f57 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 26 Aug 2025 12:44:08 +0000 Subject: [PATCH 1401/1483] setup_rts.adb: change the heuristic for our "native?" check Compare target names instead of relying on the (unreliable) executable name for the compiler. This fixes the behavior for aarch64-linux hosts (LibGPR2 picks `aarch64-linux-gnu-gcc` as the compiler driver over `gcc`, defeating the heuristic that this commit replaces). --- tools/gnatcov/setup_rts.adb | 36 ++++++++++++++++++++---------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index b3f23454c..b24589f2a 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -19,7 +19,6 @@ with Ada.Characters.Handling; use Ada.Characters.Handling; with Ada.Directories; use Ada.Directories; with Ada.Environment_Variables; -with Ada.Strings.Fixed; with Ada.Text_IO; use Ada.Text_IO; with GNAT.OS_Lib; @@ -509,23 +508,28 @@ package body Setup_RTS is Auto_RTS_Profile := Full; end if; else + -- Determine the target for the loaded project (Target) and the host + -- platform (Host): consider that project is native if both are + -- identical. + -- + -- In order to get the canonical form for the host target, we need a + -- knowledge base: if the project does not have one (that is the case + -- when a configuration project is used), we need to load the default + -- one. + declare - Driver : constant GPR2.Project.Attribute.Object := - Prj.Root_Project.Attribute - (GPR2.Project.Registry.Attribute.Compiler.Driver, - GPR2.Project.Attribute_Index.Create - (GPR2.C_Language)); + KB : constant GPR2.KB.Object := + (if Prj.Get_KB.Is_Defined + then Prj.Get_KB + else GPR2.KB.Create_Default (GPR2.KB.Default_Flags)); + Target : constant String := + String (Prj.Target (Canonical => True)); + Host : constant String := + String (KB.Normalized_Target (GPR2.Project.Tree.Target_Name)); begin - -- If C's compiler driver is defined, and contains a dash, we - -- can only suppose it's a cross compiler with an executable of - -- the form -. - - if Driver.Is_Defined - and then Ada.Strings.Fixed.Index - (Simple_Name (Driver.Value.Text), "-") > 0 - then - Auto_RTS_Profile := Embedded; - else + Setup_RTS_Trace.Trace ("Target: " & Target); + Setup_RTS_Trace.Trace ("Host: " & Host); + if Target = Host then Auto_RTS_Profile := Full; end if; end; From 7cc4ebc42520403af568a471024405b042e73bd7 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 3 Jul 2025 12:35:41 +0200 Subject: [PATCH 1402/1483] gnatcov setup: error out to avoid stack overflow --- doc/gnatcov/src_traces.rst | 1 + tools/gnatcov/setup_rts.adb | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 9f2300a31..ba949918a 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -1285,6 +1285,7 @@ included in this custom coverage runtime. Like in non-customized cases, .. code-block:: sh # Add --target and --RTS if needed according to the toolchain to use + # Make sure not to run this in my_rts.gpr directory gnatcov setup my_rts/my_rts.gpr While it is technically possible with this mechanism to modify all aspects of diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index b24589f2a..a7d5b23c7 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -370,6 +370,25 @@ package body Setup_RTS is Name : constant String := Project_Name (Project_File); File : Text_Files.File_Type; begin + -- Start by checking that Tree_Dir is not a parent dir of Tree_Dir_Copy. + -- Otherwise, we will end up with a stack overflow as Tree_Dir_Copy + -- will be recursively copied. + + declare + Tree_Dir_VF : constant Virtual_File := Create (+Tree_Dir); + Parent : Virtual_File := + Get_Parent (Create (+Tree_Dir_Copy)); + begin + while Parent /= No_File loop + if Parent = Tree_Dir_VF then + Outputs.Fatal_Error + ("Do not run this command in the same directory/in a" + & " subdirectory of the installed runtime"); + end if; + Parent := Get_Parent (Parent); + end loop; + end; + -- Copy the sources of the project to build declare From b5d56198b36f9da036a89b03563bfd9ea1832452 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 4 Jul 2025 13:02:30 +0200 Subject: [PATCH 1403/1483] Add sources for the customize instrumentation runtime doc example --- doc/gnatcov/src_traces.rst | 6 ++-- tools/gnatcov/examples/doc/custom_rt/main.adb | 6 ++++ .../examples/doc/custom_rt/my_rts/my_rts.gpr | 4 +++ .../doc/custom_rt/stateful_io/stateful_io.adb | 28 +++++++++++++++++++ .../doc/custom_rt/stateful_io/stateful_io.ads | 4 +++ .../doc/custom_rt/stateful_io/stateful_io.gpr | 9 ++++++ .../examples/doc/custom_rt/user_project.gpr | 6 ++++ 7 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 tools/gnatcov/examples/doc/custom_rt/main.adb create mode 100644 tools/gnatcov/examples/doc/custom_rt/my_rts/my_rts.gpr create mode 100644 tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.adb create mode 100644 tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.ads create mode 100644 tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.gpr create mode 100644 tools/gnatcov/examples/doc/custom_rt/user_project.gpr diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index ba949918a..07a92744d 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -1381,7 +1381,9 @@ Ultimately, it is necessary for this case to work around compiler-enforced elaboration constraints using interfacing pragmas (``pragma Import``/``pragma Export``). Assuming that the IO handling code is self-contained and is already present in the closure of the project to analyze, the following example -demonstrates how to handle this case. +demonstrates how to handle this case. The sources can be found under the +`share/examples/gnatcoverage/custom_rt/` directory of the GNATDAS distribution. + First, move the IO handling code to an independent library project: @@ -1402,7 +1404,7 @@ First, move the IO handling code to an independent library project: package Stateful_IO is procedure Put (S : String); pragma Export (Ada, Put, "stateful_io_put"); - end Stateful_IO;package Stateful_IO is + end Stateful_IO; -- stateful_io.adb with GNAT.IO; diff --git a/tools/gnatcov/examples/doc/custom_rt/main.adb b/tools/gnatcov/examples/doc/custom_rt/main.adb new file mode 100644 index 000000000..22d0bbd2a --- /dev/null +++ b/tools/gnatcov/examples/doc/custom_rt/main.adb @@ -0,0 +1,6 @@ +with Stateful_IO; + +procedure Main is +begin + Stateful_IO.Put ("Hello world!" & ASCII.LF); +end Main; diff --git a/tools/gnatcov/examples/doc/custom_rt/my_rts/my_rts.gpr b/tools/gnatcov/examples/doc/custom_rt/my_rts/my_rts.gpr new file mode 100644 index 000000000..246e912eb --- /dev/null +++ b/tools/gnatcov/examples/doc/custom_rt/my_rts/my_rts.gpr @@ -0,0 +1,4 @@ +project My_RTS extends "gnatcov_rts" is + for Object_Dir use "obj." & GNATcov_RTS.Library_Type; + for Library_Dir use "lib." & GNATcov_RTS.Library_Type; +end My_RTS; diff --git a/tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.adb b/tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.adb new file mode 100644 index 000000000..204916af4 --- /dev/null +++ b/tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.adb @@ -0,0 +1,28 @@ +with GNAT.IO; + +package body Stateful_IO is + + -- Since we are short-circuiting the Ada compiler's elaboration checks, + -- preserve a manual guard to detect attempts to send data to the IO + -- channel before elaboration has occurred. + + Initialized : Boolean := False; + + procedure Put (S : String) is + begin + if not Initialized then + raise Program_Error with + "attempt to call Stateful_IO.Put before elaboration"; + end if; + + -- Replace the following with the actual code to send data to the IO + -- stream used by coverage data. + + GNAT.IO.Put (S); + end Put; + +begin + -- Here, do whatever necessary to initialize the IO stream + + Initialized := True; +end Stateful_IO; diff --git a/tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.ads b/tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.ads new file mode 100644 index 000000000..4a5fd7475 --- /dev/null +++ b/tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.ads @@ -0,0 +1,4 @@ +package Stateful_IO is + procedure Put (S : String); + pragma Export (Ada, Put, "stateful_io_put"); +end Stateful_IO; diff --git a/tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.gpr b/tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.gpr new file mode 100644 index 000000000..4898f96e8 --- /dev/null +++ b/tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.gpr @@ -0,0 +1,9 @@ +library project Stateful_IO is + type Any_Library_Type is ("static", "relocatable", "static-pic"); + Library_Type : Any_Library_Type := external ("LIBRARY_TYPE", "static"); + + for Library_Name use "stateful_io"; + for Library_Kind use Library_Type; + for Library_Dir use "lib." & Library_Type; + for Object_Dir use "obj." & Library_Type; +end Stateful_IO; diff --git a/tools/gnatcov/examples/doc/custom_rt/user_project.gpr b/tools/gnatcov/examples/doc/custom_rt/user_project.gpr new file mode 100644 index 000000000..78d7c530f --- /dev/null +++ b/tools/gnatcov/examples/doc/custom_rt/user_project.gpr @@ -0,0 +1,6 @@ +with "stateful_io/stateful_io"; + +project User_Project is + for Object_Dir use "obj"; + for Main use ("main.adb"); +end User_Project; From b549310aebb2273a7533d0ebb8380ce099596d04 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 4 Jul 2025 13:23:53 +0200 Subject: [PATCH 1404/1483] Add sources for the consolidation traces example --- doc/gnatcov/cons_traces.rst | 6 +++++- .../gnatcov/examples/doc/cons_traces/Makefile | 8 +++++++ .../examples/doc/cons_traces/assert.adb | 6 ++++++ .../examples/doc/cons_traces/commands.adb | 21 +++++++++++++++++++ .../examples/doc/cons_traces/commands.ads | 11 ++++++++++ .../examples/doc/cons_traces/example1.gpr | 12 +++++++++++ .../doc/cons_traces/test_cmd_safe.adb | 10 +++++++++ .../doc/cons_traces/test_cmd_unsafe.adb | 9 ++++++++ 8 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 tools/gnatcov/examples/doc/cons_traces/Makefile create mode 100644 tools/gnatcov/examples/doc/cons_traces/assert.adb create mode 100644 tools/gnatcov/examples/doc/cons_traces/commands.adb create mode 100644 tools/gnatcov/examples/doc/cons_traces/commands.ads create mode 100644 tools/gnatcov/examples/doc/cons_traces/example1.gpr create mode 100644 tools/gnatcov/examples/doc/cons_traces/test_cmd_safe.adb create mode 100644 tools/gnatcov/examples/doc/cons_traces/test_cmd_unsafe.adb diff --git a/doc/gnatcov/cons_traces.rst b/doc/gnatcov/cons_traces.rst index ce71799dc..a83860cf1 100644 --- a/doc/gnatcov/cons_traces.rst +++ b/doc/gnatcov/cons_traces.rst @@ -18,6 +18,10 @@ The following subsections provide examples of possible use cases of this facilit Single unit tested by different programs ======================================== +The sources for the following example can be found under the +`share/examples/gnatcoverage/doc/cons_traces` directory of the GNATDAS +disctribution. + We will first consider achieving statement coverage of the following example Ada unit, which implements part of a robot controller able to send actuator commands depending on what a front sensor perceives is ahead of the robot: @@ -130,7 +134,7 @@ Assuming you have obtained one trace for the execution of each test, the command to produce the combined report would be something like:: gnatcov coverage --level=stmt --annotate=xcov - test_cmd_safe.trace test_cmd_unsafe.trace + test_cmd_safe.srctrace test_cmd_unsafe.srctrace The means to obtain the traces and the :cmd-option:`` switches would depend on how the functional and testing code has been diff --git a/tools/gnatcov/examples/doc/cons_traces/Makefile b/tools/gnatcov/examples/doc/cons_traces/Makefile new file mode 100644 index 000000000..6b6279d4b --- /dev/null +++ b/tools/gnatcov/examples/doc/cons_traces/Makefile @@ -0,0 +1,8 @@ +all: + gnatcov instrument -P example1 --dump-filename-simple + gprbuild -P example1 --implicit-with=gnatcov_rts --src-subdirs=gnatcov-instr + ./obj/test_cmd_safe + ./obj/test_cmd_unsafe + gnatcov coverage -P example1 --level=stmt --annotate=xcov --output-dir=safe-xcov test_cmd_safe.srctrace + gnatcov coverage -P example1 --level=stmt --annotate=xcov --output-dir=unsafe-xcov test_cmd_unsafe.srctrace + gnatcov coverage -P example1 --level=stmt --annotate=xcov --output-dir=combine-xcov test_cmd_safe.srctrace test_cmd_unsafe.srctrace diff --git a/tools/gnatcov/examples/doc/cons_traces/assert.adb b/tools/gnatcov/examples/doc/cons_traces/assert.adb new file mode 100644 index 000000000..1a6419c82 --- /dev/null +++ b/tools/gnatcov/examples/doc/cons_traces/assert.adb @@ -0,0 +1,6 @@ +procedure Assert (B : Boolean) is +begin + if not B then + raise Program_Error; + end if; +end Assert; diff --git a/tools/gnatcov/examples/doc/cons_traces/commands.adb b/tools/gnatcov/examples/doc/cons_traces/commands.adb new file mode 100644 index 000000000..5c04135dd --- /dev/null +++ b/tools/gnatcov/examples/doc/cons_traces/commands.adb @@ -0,0 +1,21 @@ +package body Commands is + + procedure Stat (Safe : Boolean) is + begin + if Safe then + N_Safe := N_Safe + 1; + else + N_Unsafe := N_Unsafe + 1; + end if; + end Stat; + + function Safe (Cmd : Command; Front : Perceived) return Boolean is + + -- Standing straight is always safe, and any other action is + -- safe as soon as there is just solid ground ahead: + Result : constant Boolean := Cmd = Hold or else Front = Ground; + begin + Stat (Result); + return Result; + end Safe; +end Commands; diff --git a/tools/gnatcov/examples/doc/cons_traces/commands.ads b/tools/gnatcov/examples/doc/cons_traces/commands.ads new file mode 100644 index 000000000..805bcbf9f --- /dev/null +++ b/tools/gnatcov/examples/doc/cons_traces/commands.ads @@ -0,0 +1,11 @@ +package Commands is + + type Command is (Step, Hold); + type Perceived is (Ground, Rock, Pit); + + function Safe (Cmd : Command; Front : Perceived) return Boolean; + -- Whether executing CMD is safe with FRONT perceived ahead + + N_Safe, N_Unsafe : Integer := 0; + -- Count the number of safe/unsafe cases we have evaluated +end Commands; diff --git a/tools/gnatcov/examples/doc/cons_traces/example1.gpr b/tools/gnatcov/examples/doc/cons_traces/example1.gpr new file mode 100644 index 000000000..8bf879f3f --- /dev/null +++ b/tools/gnatcov/examples/doc/cons_traces/example1.gpr @@ -0,0 +1,12 @@ +project Example1 is + + for Object_Dir use "obj"; + + -- Test drivers + for Main use ("test_cmd_safe.adb", "test_cmd_unsafe.adb"); + + -- State subset of units of interest to coverage analysis + package Coverage is + for Units use ("commands"); + end Coverage; +end Example1; diff --git a/tools/gnatcov/examples/doc/cons_traces/test_cmd_safe.adb b/tools/gnatcov/examples/doc/cons_traces/test_cmd_safe.adb new file mode 100644 index 000000000..749595b8b --- /dev/null +++ b/tools/gnatcov/examples/doc/cons_traces/test_cmd_safe.adb @@ -0,0 +1,10 @@ +with Assert; +with Commands; use Commands; + +procedure Test_Cmd_Safe is +begin + -- Remaining still is always safe, as is stepping with room ahead: + Assert (Safe (Cmd => Hold, Front => Rock)); + Assert (Safe (Cmd => Hold, Front => Pit)); + Assert (Safe (Cmd => Step, Front => Ground)); +end Test_Cmd_Safe; diff --git a/tools/gnatcov/examples/doc/cons_traces/test_cmd_unsafe.adb b/tools/gnatcov/examples/doc/cons_traces/test_cmd_unsafe.adb new file mode 100644 index 000000000..56721db17 --- /dev/null +++ b/tools/gnatcov/examples/doc/cons_traces/test_cmd_unsafe.adb @@ -0,0 +1,9 @@ +with Assert; +with Commands; use Commands; + +procedure Test_Cmd_Unsafe is +begin + -- Stepping forward without room ahead is always unsafe + Assert (not Safe (Cmd => Step, Front => Rock)); + Assert (not Safe (Cmd => Step, Front => Pit)); +end Test_Cmd_Unsafe; From b9cfb609e6b81550ca56548ecd4b1c299370c2fa Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 29 Aug 2025 16:59:02 +0200 Subject: [PATCH 1405/1483] doc: use the :cmd-option: syntax --- doc/gnatcov/integrated_instr.rst | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/doc/gnatcov/integrated_instr.rst b/doc/gnatcov/integrated_instr.rst index 3d31c15f5..0a705cf09 100644 --- a/doc/gnatcov/integrated_instr.rst +++ b/doc/gnatcov/integrated_instr.rst @@ -40,21 +40,21 @@ Specifying instrumentation switches The user specifies the switches through the |gcvsti| command, which accepts any option accepted by |gcvins|, except the ones using project mechanisms to filter -out units of interest: ``--units`` and ``--projects``. Refer to -:ref:`src_traces` for more information regarding the source instrumentation +out units of interest: :cmd-option:`--units` and :cmt-option:`--projects`. Refer +to :ref:`src_traces` for more information regarding the source instrumentation specific switches. As there is no project acting as a units of interest provider, every file that is not a system header is considered as a file of interest. The user can -explicitly specify files of interest through the ``--files`` switch, which -expects a list of full filenames that can be passed through the command line, or -using a response file. +explicitly specify files of interest through the :cmd-option:`--files` switch, +which expects a list of full filenames that can be passed through the command +line, or using a response file. -To generate a compiler wrapper, use the ``--compilers`` switch. The list of -supported compilers is ``gcc`` and ``g++``. +To generate a compiler wrapper, use the :cmd-option:`--compilers` switch. The +list of supported compilers is ``gcc`` and ``g++``. This will generate in the current directory, or in the directory specified by -the ``--output-dir`` switch an executable compiler wrapper and a +the :cmd-option:`--output-dir` switch an executable compiler wrapper and a ``gnatcov_config.json`` file along. Note that this configuration file is used to configure various instrumentation options: it is thus very important that it resides in the same directory as the compiler wrapper. Note that all of the From cbd0c449ea27bdce352c82128ed40f3d345b93f7 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 29 Aug 2025 16:59:32 +0200 Subject: [PATCH 1406/1483] integrated instr doc: documente the use of --sid for gnatcov coverage --- doc/gnatcov/integrated_instr.rst | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/doc/gnatcov/integrated_instr.rst b/doc/gnatcov/integrated_instr.rst index 0a705cf09..924817a29 100644 --- a/doc/gnatcov/integrated_instr.rst +++ b/doc/gnatcov/integrated_instr.rst @@ -40,7 +40,7 @@ Specifying instrumentation switches The user specifies the switches through the |gcvsti| command, which accepts any option accepted by |gcvins|, except the ones using project mechanisms to filter -out units of interest: :cmd-option:`--units` and :cmt-option:`--projects`. Refer +out units of interest: :cmd-option:`--units` and :cmd-option:`--projects`. Refer to :ref:`src_traces` for more information regarding the source instrumentation specific switches. @@ -69,6 +69,16 @@ The build process can be run unchanged after it has been configured to use the generated compiler wrapper instead of the original compiler. +Generating a coverage report +============================ + +The coverage generation report is as documented under the section :ref:`scov`. +The coverage obligations are specified through the :cmd-option:`--sid` by +passing the list of files with a sid extension generated by the build of the +instrumented executable, under the output directory that was specified or +implicitly assumed, when running the |gcvsti| command. + + A simple Makefile example ========================= From cdbdd8623fb424553d5c5de15a99dbafbb54d4e3 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 1 Sep 2025 13:18:41 +0000 Subject: [PATCH 1407/1483] U211-014-setup: increase verbosity for debugging --- testsuite/tests/U211-014-setup/test.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/U211-014-setup/test.py b/testsuite/tests/U211-014-setup/test.py index 29b5c3e48..217c1fe90 100644 --- a/testsuite/tests/U211-014-setup/test.py +++ b/testsuite/tests/U211-014-setup/test.py @@ -110,7 +110,12 @@ def xsetup(args, out, register_failure=True, auto_config_args=True): arguments. """ return xcov( - ["setup", f"--install-name={rt_prj}", f"--prefix={rt_install_dir}"] + [ + "setup", + f"--install-name={rt_prj}", + f"--prefix={rt_install_dir}", + "-v", + ] + args, out=out, register_failure=register_failure, @@ -187,7 +192,7 @@ def check_full( ) thistest.fail_if_no_match( log_file, - ".*The C language must be enabled.*", + "(.|\n)*The C language must be enabled(.\n)*", contents_of(log_file), ) From 27752feb30ea5447c0f42c943a0218a31729434a Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 1 Sep 2025 13:19:05 +0000 Subject: [PATCH 1408/1483] Setup_RTS: add a special case to consider x86-linux as native --- tools/gnatcov/setup_rts.adb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index a7d5b23c7..05659c611 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -548,7 +548,12 @@ package body Setup_RTS is begin Setup_RTS_Trace.Trace ("Target: " & Target); Setup_RTS_Trace.Trace ("Host: " & Host); - if Target = Host then + + -- TODO??? (eng/gpr/gpr-issues#683) Remove the special case for + -- x86-linux once LibGPR2 sets it as the native target when + -- gprconfig comes from a 32-bit package. + + if Target = Host or else Target = "x86-linux" then Auto_RTS_Profile := Full; end if; end; From 53ca110a76063274628934b46398584dc7389d49 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 1 Sep 2025 13:22:36 +0000 Subject: [PATCH 1409/1483] U211-014-setup: remove obsolete XFAIL --- testsuite/tests/U211-014-setup/test.opt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 testsuite/tests/U211-014-setup/test.opt diff --git a/testsuite/tests/U211-014-setup/test.opt b/testsuite/tests/U211-014-setup/test.opt deleted file mode 100644 index 3914d22d8..000000000 --- a/testsuite/tests/U211-014-setup/test.opt +++ /dev/null @@ -1 +0,0 @@ -aarch64-linux XFAIL Ongoing work for eng/shared/anod#677 From 8fb057098d785b3007935093c68615598a534790 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 29 Aug 2025 16:40:18 +0200 Subject: [PATCH 1410/1483] Instrument.C: explicitly pass -m32 for 32 bits targets to clang Otherwise, it yields a mismatching for the size_t type, resulting in clang failing to parse / check C++ constructs such as initializer lists. --- .../ForRange/WithInitializerRange/test.opt | 1 - tools/gnatcov/instrument-c.adb | 51 ++++++++++++------- tools/gnatcov/instrument-c.ads | 6 ++- tools/gnatcov/instrument-c__stub.adb | 4 +- tools/gnatcov/instrument-c__stub.ads | 2 +- tools/gnatcov/instrument-gcc_wrapper.adb | 2 +- tools/gnatcov/strings.ads | 5 ++ 7 files changed, 46 insertions(+), 25 deletions(-) delete mode 100644 testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.opt diff --git a/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.opt b/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.opt deleted file mode 100644 index 16851dbd2..000000000 --- a/testsuite/tests/C++/stmt/ForRange/WithInitializerRange/test.opt +++ /dev/null @@ -1 +0,0 @@ -bareboard,src-traces XFAIL eng/das/cov/gnatcoverage#442 diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 1b2457d26..36d10c65f 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -21,7 +21,6 @@ with Ada.Containers; use Ada.Containers; with Ada.Directories; use Ada.Directories; with Ada.IO_Exceptions; with Ada.Streams.Stream_IO; -with Ada.Strings.Fixed; with Ada.Text_IO; use Ada.Text_IO; with Clang.CX_Diagnostic; use Clang.CX_Diagnostic; @@ -558,12 +557,7 @@ package body Instrument.C is Func_Args : String := ""); -- Like Format_Extern_Decl, but write the definition to File - --------------------- - -- Compiler_Is_X86 -- - --------------------- - - function Compiler_Is_X86 - (Compiler_Driver : Unbounded_String) return Boolean + function Compiler_Target (Compiler_Driver : Unbounded_String) return String is Driver_Basename : constant String := Ada.Directories.Simple_Name (+Compiler_Driver); @@ -580,25 +574,21 @@ package body Instrument.C is & Hex_Image (Unsigned_64 (Pid_To_Integer (Current_Process_Id))) & "_" & Basename_Suffix); File : Ada.Text_IO.File_Type; - Res : Boolean := False; + Res : Unbounded_String; begin Run_Command (Command => Cmd, - Origin_Command_Name => "gnatcov insturment", + Origin_Command_Name => "gnatcov instrument", Output_File => Filename); Open (File, In_File, Filename); -- We only expect one line in the output file, with only the triplet - -- in it. Check it against a ground truth string, and if it matches - -- and we don't expect a non-native target, assume we need to forward - -- -m32 to libclang. + -- in it. - if Ada.Strings.Fixed.Index (Get_Line (File), "i686-pc") = 1 then - Res := True; - end if; + Res := +Get_Line (File); Close (File); Delete_File (Filename); - return Res; + return +Res; exception when others => if Is_Open (File) then @@ -606,7 +596,28 @@ package body Instrument.C is Delete_File (Filename); end if; raise; - end Compiler_Is_X86; + end Compiler_Target; + + ------------------------ + -- Compiler_Is_32bits -- + ------------------------ + + function Compiler_Is_32bits + (Compiler_Driver : Unbounded_String) return Boolean + is + Target : constant String := Compiler_Target (Compiler_Driver); + begin + -- Check if the triplet is a 32-bits platform. + + if Contains (Target, "i686-pc") + or else Contains (Target, "powerpc") + or else Contains (Target, "arm-eabi") + or else Contains (Target, "riscv32") + then + return True; + end if; + return False; + end Compiler_Is_32bits; ------------------------ -- To_Chars_Ptr_Array -- @@ -5731,13 +5742,15 @@ package body Instrument.C is Instrumenter.Instr_Mode, Self.Builtin_Macros); - -- Deptermine if the compiler is an x86 32bit compiler. The integrated + -- Determine if the compiler is a 32bit compiler. The integrated -- instrumentation process only forwards the actual compiler, not the -- driver to the instrumentation process, so only perform this check for -- project based instrumentation, the compiler wrapper is responsible -- for adding -m32 if needed to the compiler switches. + if Instrumenter.Instr_Mode = Project_Instrumentation - and then Compiler_Is_X86 (Prj.Compiler_Driver (Instrumenter.Language)) + and then Compiler_Is_32bits + (Prj.Compiler_Driver (Instrumenter.Language)) then Self.Clang_Needs_M32 := True; end if; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 6a3c07e88..1e994b9f1 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -451,7 +451,11 @@ package Instrument.C is -- C_String_Literal ("a\b") = """a\\b""" -- C_String_Literal ("a""b") = """a\""b""" - function Compiler_Is_X86 + function Compiler_Target (Compiler_Driver : Unbounded_String) return String; + -- Return the compiler target (i.e. the result of the + -- -dump-machine command). + + function Compiler_Is_32bits (Compiler_Driver : Unbounded_String) return Boolean; -- Check wether the compiler designated by Compiler_Driver is a native x86 -- 32 bit compiler. This function will only work if Compiler_Driver diff --git a/tools/gnatcov/instrument-c__stub.adb b/tools/gnatcov/instrument-c__stub.adb index c8974b9bb..40a351d1b 100644 --- a/tools/gnatcov/instrument-c__stub.adb +++ b/tools/gnatcov/instrument-c__stub.adb @@ -17,13 +17,13 @@ ------------------------------------------------------------------------------ package body Instrument.C is - function Compiler_Is_X86 + function Compiler_Is_32bits (Compiler_Driver : Unbounded_String) return Boolean is pragma Unreferenced (Compiler_Driver); begin raise Program_Error; return False; - end Compiler_Is_X86; + end Compiler_Is_32bits; begin Builtin_Support (C_Language) := False; Builtin_Support (CPP_Language) := False; diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index 1a0dc1f38..20aad885c 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -58,7 +58,7 @@ package Instrument.C is (Preprocessed_Filename : String; Postprocessed_Filename : String) is null; - function Compiler_Is_X86 + function Compiler_Is_32bits (Compiler_Driver : Unbounded_String) return Boolean; end Instrument.C; diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index a86731289..66f3b22d8 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -336,7 +336,7 @@ is -- sources. Adding this switch on the gcc command line should not change -- anything. - if Compiler_Is_X86 (Context.Orig_Compiler_Driver) then + if Compiler_Is_32bits (Context.Orig_Compiler_Driver) then Additional_Args.Append (+"-m32"); end if; diff --git a/tools/gnatcov/strings.ads b/tools/gnatcov/strings.ads index acd6e25f0..58ba26341 100644 --- a/tools/gnatcov/strings.ads +++ b/tools/gnatcov/strings.ads @@ -22,6 +22,7 @@ with Ada.Containers.Ordered_Maps; with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; with Ada.Streams; +with Ada.Strings.Fixed; with Ada.Strings.Unbounded; with Ada.Strings.Unbounded.Equal_Case_Insensitive; with Ada.Strings.Unbounded.Hash; @@ -164,6 +165,10 @@ package Strings is -- -- Raise Constraint_Error on invalid or unsupported escape sequences. + function Contains (Str, Substr : String) return Boolean + is (Ada.Strings.Fixed.Index (Str, Substr) /= 0); + -- Return whether Str contains the given Substr + private pragma Inline (Hash); pragma Inline (Equal); From d7f6a86215f2f0585799f466c3cf010423d4ca3b Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 29 Aug 2025 16:48:29 +0200 Subject: [PATCH 1411/1483] Clean old instrumentation artifacts even when Save_Temps is set --- tools/gnatcov/instrument-clean_objdirs.adb | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/tools/gnatcov/instrument-clean_objdirs.adb b/tools/gnatcov/instrument-clean_objdirs.adb index cc38f29f6..3d2d9e727 100644 --- a/tools/gnatcov/instrument-clean_objdirs.adb +++ b/tools/gnatcov/instrument-clean_objdirs.adb @@ -156,12 +156,10 @@ begin -- through extended projects, as their object directories can interfere -- with the build of the extending project. - if not Save_Temps then - Iterate_Projects - (Root_Project => Project.Project.Root_Project, - Process => Clean_Subdir'Access, - Recursive => True, - Include_Extended => True, - Include_Externally_Built => True); - end if; + Iterate_Projects + (Root_Project => Project.Project.Root_Project, + Process => Clean_Subdir'Access, + Recursive => True, + Include_Extended => True, + Include_Externally_Built => True); end Instrument.Clean_Objdirs; From d5d1c5a51685af9f064b1f485b78c10a17275107 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Tue, 2 Sep 2025 09:42:36 +0000 Subject: [PATCH 1412/1483] Setup_RTS: add a special case to consider x86-windows as native --- tools/gnatcov/setup_rts.adb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index 05659c611..a545b9c62 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -550,10 +550,10 @@ package body Setup_RTS is Setup_RTS_Trace.Trace ("Host: " & Host); -- TODO??? (eng/gpr/gpr-issues#683) Remove the special case for - -- x86-linux once LibGPR2 sets it as the native target when + -- x86 platforms once LibGPR2 sets them as the native target when -- gprconfig comes from a 32-bit package. - if Target = Host or else Target = "x86-linux" then + if Target = Host or else Target in "x86-linux" | "x86-windows" then Auto_RTS_Profile := Full; end if; end; From 8f182199eae979b9c4eebd272cd9b1416ebcd6d4 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 26 Aug 2025 10:53:53 +0200 Subject: [PATCH 1413/1483] Add a discriminant for testing the community build --- testsuite/SUITE/control.py | 5 +++++ testsuite/testsuite.py | 3 +++ 2 files changed, 8 insertions(+) diff --git a/testsuite/SUITE/control.py b/testsuite/SUITE/control.py index 12c6e5af2..a9e984f2f 100644 --- a/testsuite/SUITE/control.py +++ b/testsuite/SUITE/control.py @@ -676,3 +676,8 @@ def add_shared_options_to(parser, toplevel): help='Pass --block-instrument to "gnatcov instrument",' " to enable block instrumentation.", ) + + # --community + parser.add_argument( + "--community", action="store_true", help="Only run community tests." + ) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index 5da32bf7e..a4cbc0a5b 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1430,6 +1430,9 @@ def _base_discriminants(self): if self.main.args.block: result.append("block") + if self.main.args.community: + result.append("community") + return result def _board_discriminants(self): From 347512c9a9bca17e922d4dc0b84adbbecd995c89 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 26 Aug 2025 10:54:10 +0200 Subject: [PATCH 1414/1483] Do not warn for missing ALIs / SIDs for unsupported languages Also decorrelate the C support logic from the stub instrumenters implementation. --- tools/gnatcov/gnatcov.gpr | 2 ++ tools/gnatcov/gnatcov_bits_specific.adb | 2 ++ tools/gnatcov/instrument-ada_unit__stub.adb | 2 -- tools/gnatcov/project.adb | 7 ++++++ tools/gnatcov/set_builtin_support.adb | 22 ++++++++++++++++++ tools/gnatcov/set_builtin_support_no_c.adb | 25 +++++++++++++++++++++ 6 files changed, 58 insertions(+), 2 deletions(-) create mode 100644 tools/gnatcov/set_builtin_support.adb create mode 100644 tools/gnatcov/set_builtin_support_no_c.adb diff --git a/tools/gnatcov/gnatcov.gpr b/tools/gnatcov/gnatcov.gpr index e4033bc00..1a1c2f852 100644 --- a/tools/gnatcov/gnatcov.gpr +++ b/tools/gnatcov/gnatcov.gpr @@ -130,6 +130,8 @@ project Gnatcov is when "False" => for Specification ("Instrument.C") use "instrument-c__stub.ads"; for Body ("Instrument.C") use "instrument-c__stub.adb"; + for Body ("Set_Builtin_Support") + use "set_builtin_support_no_c.adb"; when "True" => null; end case; diff --git a/tools/gnatcov/gnatcov_bits_specific.adb b/tools/gnatcov/gnatcov_bits_specific.adb index b4272f616..d07f5e9cb 100644 --- a/tools/gnatcov/gnatcov_bits_specific.adb +++ b/tools/gnatcov/gnatcov_bits_specific.adb @@ -78,6 +78,7 @@ with Project; use Project; with Qemu_Traces; with Rundrv; use Rundrv; with SC_Obligations; use SC_Obligations; +with Set_Builtin_Support; with Setup_RTS; use Setup_RTS; with SS_Annotations; use SS_Annotations; with Strings; use Strings; @@ -1779,6 +1780,7 @@ begin Parse_Arguments (From_Driver => False); Raise_Stub_Internal_Error_For (Arguments_Loading); Process_Arguments; + Set_Builtin_Support; if Misc_Trace.Is_Active then Show_Version; diff --git a/tools/gnatcov/instrument-ada_unit__stub.adb b/tools/gnatcov/instrument-ada_unit__stub.adb index 8cc86f06b..12833b169 100644 --- a/tools/gnatcov/instrument-ada_unit__stub.adb +++ b/tools/gnatcov/instrument-ada_unit__stub.adb @@ -17,6 +17,4 @@ ------------------------------------------------------------------------------ package body Instrument.Ada_Unit is -begin - Builtin_Support (Ada_Language) := False; end Instrument.Ada_Unit; diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index d552e9685..396ad1ba2 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -358,6 +358,13 @@ package body Project is -- --restricted-to-languages switch. or else not Src_Enabled_Languages (Unit.Language) + + -- Ignore units in a language not supported by the tool + + or else not Builtin_Support (Unit.Language) + + -- Ignore units for which gnatcov already warned + or else not Warn_About_Missing_Info then return; diff --git a/tools/gnatcov/set_builtin_support.adb b/tools/gnatcov/set_builtin_support.adb new file mode 100644 index 000000000..dc0f2bf5c --- /dev/null +++ b/tools/gnatcov/set_builtin_support.adb @@ -0,0 +1,22 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2025, 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. -- +------------------------------------------------------------------------------ + +procedure Set_Builtin_Support is +begin + null; +end Set_Builtin_Support; diff --git a/tools/gnatcov/set_builtin_support_no_c.adb b/tools/gnatcov/set_builtin_support_no_c.adb new file mode 100644 index 000000000..825c48b61 --- /dev/null +++ b/tools/gnatcov/set_builtin_support_no_c.adb @@ -0,0 +1,25 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2025, 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 Switches; use Switches; + +procedure Set_Builtin_Support is +begin + Builtin_Support (C_Language) := False; + Builtin_Support (CPP_Language) := False; +end Set_Builtin_Support; From c720999bf4e08047d59159bd244f576dff0ea7a8 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 28 Aug 2025 16:29:03 +0200 Subject: [PATCH 1415/1483] Add missing copyright headers --- tools/gnatcov/llvm.adb | 18 ++++++++++++++++++ tools/gnatcov/llvm.ads | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/tools/gnatcov/llvm.adb b/tools/gnatcov/llvm.adb index 1741a3b8a..40680a0c5 100644 --- a/tools/gnatcov/llvm.adb +++ b/tools/gnatcov/llvm.adb @@ -1,3 +1,21 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2025, 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.Environment_Variables; with Logging; diff --git a/tools/gnatcov/llvm.ads b/tools/gnatcov/llvm.ads index 35190d70c..e79087983 100644 --- a/tools/gnatcov/llvm.ads +++ b/tools/gnatcov/llvm.ads @@ -1,3 +1,21 @@ +------------------------------------------------------------------------------ +-- -- +-- GNATcoverage -- +-- -- +-- Copyright (C) 2025, 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 Traces_Files; use Traces_Files; with Strings; use Strings; From bc4542a27cd55254679bb522380eed63d5dffba2 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 4 Sep 2025 13:22:47 +0000 Subject: [PATCH 1416/1483] subprocesses.adb: remove unused formal --- tools/gnatcov/subprocesses.adb | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 2f55bb92a..8c27f7dea 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -38,8 +38,7 @@ package body Subprocesses is Output_File : String := ""; Err_To_Out : Boolean := True; Out_To_Null : Boolean := False; - In_To_Null : Boolean := False; - Ignore_Error : Boolean := False) return Process_Handle; + In_To_Null : Boolean := False) return Process_Handle; -- Overload to run asynchronously a command function Wait_And_Finalize (Self : in out Process_Pool) return Positive; @@ -226,8 +225,7 @@ package body Subprocesses is Output_File, Err_To_Out, Out_To_Null, - In_To_Null, - Ignore_Error); + In_To_Null); Success : constant Boolean := Wait (Handle) = 0 and then Handle /= Invalid_Handle; begin @@ -243,8 +241,7 @@ package body Subprocesses is Output_File : String := ""; Err_To_Out : Boolean := True; Out_To_Null : Boolean := False; - In_To_Null : Boolean := False; - Ignore_Error : Boolean := False) return Process_Handle + In_To_Null : Boolean := False) return Process_Handle is package Process_Types renames GNATCOLL.OS.Process_Types; @@ -487,8 +484,7 @@ package body Subprocesses is Err_To_Out => Output_File = "", Out_To_Null => Out_To_Null, - In_To_Null => In_To_Null, - Ignore_Error => Ignore_Error); + In_To_Null => In_To_Null); Pool.Nb_Running_Processes := Pool.Nb_Running_Processes + 1; end Run_Command; From 31d03432b3a69905a6304265854d571324f909dd Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 4 Sep 2025 13:35:20 +0000 Subject: [PATCH 1417/1483] Subprocesses: forward redirected output of failed subp. to stderr When a subprocess fails and its output has been redirected to a file, read its output and forward it to stderr to ease investigation. --- .../460-compiler-error/test.py | 47 +++++++++++++++++++ tools/gnatcov/subprocesses.adb | 47 +++++++++++++++++-- 2 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 testsuite/tests/integrated_instrumentation/460-compiler-error/test.py diff --git a/testsuite/tests/integrated_instrumentation/460-compiler-error/test.py b/testsuite/tests/integrated_instrumentation/460-compiler-error/test.py new file mode 100644 index 000000000..fa9170160 --- /dev/null +++ b/testsuite/tests/integrated_instrumentation/460-compiler-error/test.py @@ -0,0 +1,47 @@ +""" +Test that compiler output is correctly forwarded to the user on error. +""" + +import os +import re + +from SUITE.context import thistest +from SUITE.control import env +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import cmdrun, xcov + + +Wdir("tmp_") + +# Setup the instrumentation process +with open("main.c", "w"): + pass +xcov( + [ + "setup-integration", + "--level=stmt", + "--files=main.c", + "--compilers=gcc", + "--output-dir=.", + ] +) + +# Shadow the compiler driver with the generated wrapper +env.add_search_path(env_var="PATH", path=os.getcwd()) + +# Run the GCC wrapper with an invalid flag and check its output +output_file = "gcc-output.txt" +cmdrun( + ["gcc", "-c", "main.c", "-invalid-switch"], + out=output_file, + for_pgm=False, + expect_non_zero_code=True, +) + +output = contents_of(output_file) +error_msg = "gcc: error: unrecognized command-line option '-invalid-switch'" +thistest.fail_if_no_match( + "gcc wrapper output", f"(.|\n)*{re.escape(error_msg)}(.|\n)*", output +) + +thistest.result() diff --git a/tools/gnatcov/subprocesses.adb b/tools/gnatcov/subprocesses.adb index 8c27f7dea..0a4d18ec9 100644 --- a/tools/gnatcov/subprocesses.adb +++ b/tools/gnatcov/subprocesses.adb @@ -45,12 +45,20 @@ package body Subprocesses is -- Wait for a process to terminate and handle its output. Return the id in -- Self for the process that terminated. + procedure Print_On_Stderr (Filename : String); + -- If Filename is not empty, read the content of the given file and forward + -- it to the standard error stream. + procedure Check_Status (Success : Boolean; + Output_File : String; Ignore_Error : Boolean; Command : String; Origin_Command_Name : String); - -- If Ignore_Error is False and Success is False, raise a Fatal_Error + -- If Ignore_Error is False and Success is False, raise a Fatal_Error. + -- + -- In addition, in case of failure and Output_File is not empty, forward + -- its content to the standard error strem. --------- -- "=" -- @@ -110,17 +118,35 @@ package body Subprocesses is Cmd.Arguments.Append_Vector (Args); end Append_Args; + --------------------- + -- Print_On_Stderr -- + --------------------- + + procedure Print_On_Stderr (Filename : String) is + F : File_Type; + begin + if Filename /= "" then + Open (F, In_File, Filename); + while not End_Of_File (F) loop + Warning_Or_Error (Get_Line (F)); + end loop; + Close (F); + end if; + end Print_On_Stderr; + ------------------ -- Check_Status -- ------------------ procedure Check_Status (Success : Boolean; + Output_File : String; Ignore_Error : Boolean; Command : String; Origin_Command_Name : String) is begin if not Ignore_Error and then not Success then + Print_On_Stderr (Output_File); Fatal_Error (Origin_Command_Name & " failed: aborting"); elsif Subprocesses_Trace.Is_Active then @@ -131,6 +157,7 @@ package body Subprocesses is -- here we are precisely ignoring the fact that the subprocess -- failed. + Print_On_Stderr (Output_File); Warning_Or_Error (Origin_Command_Name & " failed"); end if; end if; @@ -229,7 +256,8 @@ package body Subprocesses is Success : constant Boolean := Wait (Handle) = 0 and then Handle /= Invalid_Handle; begin - Check_Status (Success, Ignore_Error, Command, Origin_Command_Name); + Check_Status + (Success, Output_File, Ignore_Error, Command, Origin_Command_Name); return Success; end Run_Command; @@ -414,8 +442,19 @@ package body Subprocesses is -- If the subprocess terminated with an error, deal with it here - Check_Status - (Success, Info.Ignore_Error, +Info.Command, +Info.Origin_Command_Name); + declare + Output_File : constant String := + (if Info.Output_To_Stdout + then "" + else +Info.Output_File); + begin + Check_Status + (Success, + Output_File, + Info.Ignore_Error, + +Info.Command, + +Info.Origin_Command_Name); + end; return Id; end Wait_And_Finalize; From a7efe8e758ef14ed075afc63c474dab7df2a5a39 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 4 Sep 2025 13:36:49 +0000 Subject: [PATCH 1418/1483] compiler_wrappers-gcc.adb: handle Xcov_Exit_Exc errors Like in the other mains, these exceptions must be silently discarded to avoid the internal crash message: this exception is raised only when a proper error message has been displayed. --- .../integrated_instrumentation/460-compiler-error/test.py | 3 +++ tools/gnatcov/compiler_wrappers-gcc.adb | 7 +++++++ 2 files changed, 10 insertions(+) diff --git a/testsuite/tests/integrated_instrumentation/460-compiler-error/test.py b/testsuite/tests/integrated_instrumentation/460-compiler-error/test.py index fa9170160..4d83c82fd 100644 --- a/testsuite/tests/integrated_instrumentation/460-compiler-error/test.py +++ b/testsuite/tests/integrated_instrumentation/460-compiler-error/test.py @@ -43,5 +43,8 @@ thistest.fail_if_no_match( "gcc wrapper output", f"(.|\n)*{re.escape(error_msg)}(.|\n)*", output ) +thistest.fail_if_match( + "gcc wrapper output", re.escape("== gnatcov bug detected =="), output +) thistest.result() diff --git a/tools/gnatcov/compiler_wrappers-gcc.adb b/tools/gnatcov/compiler_wrappers-gcc.adb index 13a574d08..475000390 100644 --- a/tools/gnatcov/compiler_wrappers-gcc.adb +++ b/tools/gnatcov/compiler_wrappers-gcc.adb @@ -22,6 +22,7 @@ with Ada.Directories; use Ada.Directories; with GNAT.OS_Lib; with Instrument.Setup_Config; use Instrument.Setup_Config; +with Outputs; use Outputs; with Paths; use Paths; with Strings; use Strings; with Subprocesses; use Subprocesses; @@ -58,4 +59,10 @@ begin (Command => Gnatcov_Exec, Arguments => Args, Origin_Command_Name => "gnatcov gcc-wrapper"); + +exception + when Xcov_Exit_Exc => + -- An error message has already been displayed + + null; end Compiler_Wrappers.Gcc; From f26f0f2c12140b911645273c162ea035265b6fbe Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Wed, 3 Sep 2025 12:17:27 +0200 Subject: [PATCH 1419/1483] Instrument.C: refactor 32 bits detection logic Infer whether the compiler targets a 32 bits platform from the set of builtin macros rather than the compiler executable. --- tools/gnatcov/instrument-c.adb | 89 ++++-------------------- tools/gnatcov/instrument-c.ads | 11 --- tools/gnatcov/instrument-c__stub.adb | 7 -- tools/gnatcov/instrument-c__stub.ads | 3 - tools/gnatcov/instrument-common.ads | 1 + tools/gnatcov/instrument-gcc_wrapper.adb | 16 +---- 6 files changed, 18 insertions(+), 109 deletions(-) diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 36d10c65f..94e7acabf 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -557,68 +557,6 @@ package body Instrument.C is Func_Args : String := ""); -- Like Format_Extern_Decl, but write the definition to File - function Compiler_Target (Compiler_Driver : Unbounded_String) return String - is - Driver_Basename : constant String := - Ada.Directories.Simple_Name (+Compiler_Driver); - Cmd : constant Command_Type := - (Command => Compiler_Driver, - Arguments => String_Vectors.To_Vector (+"-dumpmachine", 1), - others => <>); - Basename_Suffix : constant String := "compiler_target.txt"; - Filename : constant String := - Ada.Directories.Compose - (Containing_Directory => Get_Output_Dir, - Name => - Driver_Basename & "_" - & Hex_Image (Unsigned_64 (Pid_To_Integer (Current_Process_Id))) - & "_" & Basename_Suffix); - File : Ada.Text_IO.File_Type; - Res : Unbounded_String; - begin - Run_Command - (Command => Cmd, - Origin_Command_Name => "gnatcov instrument", - Output_File => Filename); - Open (File, In_File, Filename); - - -- We only expect one line in the output file, with only the triplet - -- in it. - - Res := +Get_Line (File); - Close (File); - Delete_File (Filename); - return +Res; - exception - when others => - if Is_Open (File) then - Close (File); - Delete_File (Filename); - end if; - raise; - end Compiler_Target; - - ------------------------ - -- Compiler_Is_32bits -- - ------------------------ - - function Compiler_Is_32bits - (Compiler_Driver : Unbounded_String) return Boolean - is - Target : constant String := Compiler_Target (Compiler_Driver); - begin - -- Check if the triplet is a 32-bits platform. - - if Contains (Target, "i686-pc") - or else Contains (Target, "powerpc") - or else Contains (Target, "arm-eabi") - or else Contains (Target, "riscv32") - then - return True; - end if; - return False; - end Compiler_Is_32bits; - ------------------------ -- To_Chars_Ptr_Array -- ------------------------ @@ -5742,19 +5680,22 @@ package body Instrument.C is Instrumenter.Instr_Mode, Self.Builtin_Macros); - -- Determine if the compiler is a 32bit compiler. The integrated - -- instrumentation process only forwards the actual compiler, not the - -- driver to the instrumentation process, so only perform this check for - -- project based instrumentation, the compiler wrapper is responsible - -- for adding -m32 if needed to the compiler switches. - - if Instrumenter.Instr_Mode = Project_Instrumentation - and then Compiler_Is_32bits - (Prj.Compiler_Driver (Instrumenter.Language)) - then - Self.Clang_Needs_M32 := True; - end if; + -- Infer if the compiler is a 32 bit compiler from the value of the + -- the __SIZEOF_POINTER__ builtin macro. + declare + use Macro_Sets; + Cur : constant Cursor := Self.Builtin_Macros.Find + (Macro_Definition'(Name => +"__SIZEOF_POINTER__", others => <>)); + Size_Of_Pointer : constant Integer := + (if Has_Element (Cur) + then Integer'Value (+Self.Builtin_Macros.Element (Cur).Value) + else 8); + begin + if Size_Of_Pointer = 4 then + Self.Clang_Needs_M32 := True; + end if; + end; end Import_Options; --------------------------- diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 1e994b9f1..8c34bbd25 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -451,17 +451,6 @@ package Instrument.C is -- C_String_Literal ("a\b") = """a\\b""" -- C_String_Literal ("a""b") = """a\""b""" - function Compiler_Target (Compiler_Driver : Unbounded_String) return String; - -- Return the compiler target (i.e. the result of the - -- -dump-machine command). - - function Compiler_Is_32bits - (Compiler_Driver : Unbounded_String) return Boolean; - -- Check wether the compiler designated by Compiler_Driver is a native x86 - -- 32 bit compiler. This function will only work if Compiler_Driver - -- designates an actual driver (e.g. gcc or clang) and not a compiler (e.g. - -- cc1, cc1plus). - private function Find_Instrumented_Entities diff --git a/tools/gnatcov/instrument-c__stub.adb b/tools/gnatcov/instrument-c__stub.adb index 40a351d1b..638a3be11 100644 --- a/tools/gnatcov/instrument-c__stub.adb +++ b/tools/gnatcov/instrument-c__stub.adb @@ -17,13 +17,6 @@ ------------------------------------------------------------------------------ package body Instrument.C is - function Compiler_Is_32bits - (Compiler_Driver : Unbounded_String) return Boolean is - pragma Unreferenced (Compiler_Driver); - begin - raise Program_Error; - return False; - end Compiler_Is_32bits; begin Builtin_Support (C_Language) := False; Builtin_Support (CPP_Language) := False; diff --git a/tools/gnatcov/instrument-c__stub.ads b/tools/gnatcov/instrument-c__stub.ads index 20aad885c..95a53c33a 100644 --- a/tools/gnatcov/instrument-c__stub.ads +++ b/tools/gnatcov/instrument-c__stub.ads @@ -58,7 +58,4 @@ package Instrument.C is (Preprocessed_Filename : String; Postprocessed_Filename : String) is null; - function Compiler_Is_32bits - (Compiler_Driver : Unbounded_String) return Boolean; - end Instrument.C; diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 4d3b521fe..4361d6cc4 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -597,6 +597,7 @@ package Instrument.Common is -- defined, its optional arguments and value. function "<" (L, R : Macro_Definition) return Boolean is (L.Name < R.Name); + function "=" (L, R : Macro_Definition) return Boolean is (L.Name = R.Name); -- As we store Macro_Definition in sets, we do not want two conflicting -- definitions of the same macro to coexist. Thus, we compare only the -- name, meaning that when we insert a new definition, it will replace diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index 66f3b22d8..b24749295 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -318,8 +318,6 @@ is Parsed_Link_Command : Boolean := False; Commands_Filename : constant String := Tmp_Dir.Directory_Name / "commands"; - Additional_Args : String_Vectors.Vector := - String_Vectors.To_Vector (+"-###", 1); begin -- Grab the architecture specific switches. The heuristic is that we -- consider every switch starting with "-m" as an architecture-specific @@ -332,21 +330,11 @@ is end if; end loop; - -- Check if we shouldn't add -m32 so that clang correctly interprets the - -- sources. Adding this switch on the gcc command line should not change - -- anything. - - if Compiler_Is_32bits (Context.Orig_Compiler_Driver) then - Additional_Args.Append (+"-m32"); - end if; - - -- Expand the command line using gcc's -### option, and the addition - -- -m32 flag, if any. Putting the additional args first ensures we don't - -- override a potential (but unlikely) -m16 flag. + -- Expand the command line using gcc's -### option Run_Command (+Context.Orig_Compiler_Driver, - Additional_Args & Args, + String_Vectors.To_Vector (+"-###", 1) & Args, "gnatcov", Output_File => Commands_Filename); From e4962a67692fea4c676ae6439eb1fea804a0358e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 4 Sep 2025 16:06:01 +0200 Subject: [PATCH 1420/1483] Instrument.Gcc_Wrapper: add clarifying comment --- tools/gnatcov/instrument-gcc_wrapper.adb | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tools/gnatcov/instrument-gcc_wrapper.adb b/tools/gnatcov/instrument-gcc_wrapper.adb index b24749295..9fe0d8991 100644 --- a/tools/gnatcov/instrument-gcc_wrapper.adb +++ b/tools/gnatcov/instrument-gcc_wrapper.adb @@ -478,6 +478,11 @@ is if Result.File = No_File or else Result.Target = No_File then return No_Compilation_Command; end if; + + -- Note: we pass the compiler rather than the compiler driver, as + -- we retrieve preprocessing arguments from the compiler invocation, + -- and such arguments may not be accepted by the compiler driver. + Prj.Compiler_Driver (Result.Language) := Command.First_Element; Prj.Compiler_Options_Unit.Insert (Result.File, PP_Args); Context.Source_Mapping.Include (Result.Target, Result.File); From 151049316f65dc040884407dcf22436526387889 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Thu, 4 Sep 2025 16:53:23 +0200 Subject: [PATCH 1421/1483] Add test for initializer range when using integrated instrumentation for cross targets --- testsuite/SUITE/tutils.py | 2 +- .../initializer-range-c++/main.cpp | 12 ++ .../initializer-range-c++/test.opt | 3 + .../initializer-range-c++/test.py | 108 ++++++++++++++++++ 4 files changed, 124 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/integrated_instr_cross/initializer-range-c++/main.cpp create mode 100644 testsuite/tests/integrated_instr_cross/initializer-range-c++/test.opt create mode 100644 testsuite/tests/integrated_instr_cross/initializer-range-c++/test.py diff --git a/testsuite/SUITE/tutils.py b/testsuite/SUITE/tutils.py index 98aa8c247..dc5138ee1 100644 --- a/testsuite/SUITE/tutils.py +++ b/testsuite/SUITE/tutils.py @@ -1449,7 +1449,7 @@ def driver_for_lang(lang: str) -> str | None: the driver was not found. """ driver_match = re.search( - r'for Driver *\("' + lang + r'"\) use "(.*)";', + r'for Driver *\("' + re.escape(lang) + r'"\) use "(.*)";', contents_of(os.path.join(ROOT_DIR, "suite.cgpr")), ) diff --git a/testsuite/tests/integrated_instr_cross/initializer-range-c++/main.cpp b/testsuite/tests/integrated_instr_cross/initializer-range-c++/main.cpp new file mode 100644 index 000000000..2650762fa --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/initializer-range-c++/main.cpp @@ -0,0 +1,12 @@ +#include + +int +main (void) +{ + int sum = 0; + for (auto i : { 1, 2, 3 }) + { + sum += i; + } + return 0; +} diff --git a/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.opt b/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.opt new file mode 100644 index 000000000..1ddcc4440 --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.opt @@ -0,0 +1,3 @@ +!bareboard DEAD This test relies on examples specific to bareboard targets +morello-elf DEAD No BSP provided with this toolchain +leon3-elf XFAIL Linker cannot find fwrite (to be investigated) diff --git a/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.py b/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.py new file mode 100644 index 000000000..19017e74f --- /dev/null +++ b/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.py @@ -0,0 +1,108 @@ +""" +Test initializer range for integrated instrumentation for bareboard targets. +""" + +import os +import os.path + +from e3.fs import cp, mkdir + +from SUITE.control import env, GPRBUILD +from SUITE.cutils import Wdir +from SCOV.minicheck import check_xcov_reports +from SUITE.tutils import ( + get_c_bsp, + cmdrun, + driver_for_lang, + run_cov_program, + thistest, + xcov, +) + +Wdir("tmp_") + +# We need to setup the coverage runtime with no Ada support as otherwise we'll +# get undefined references to GNAT.IO + +gcvrt_prefix = "gcvrt" +xcov(["setup", f"--prefix={gcvrt_prefix}", "--restricted-to-languages=C,C++"]) +env.add_search_path( + "GPR_PROJECT_PATH", + os.path.join(gcvrt_prefix, "share", "gpr"), +) + +cp("../main.cpp", ".") + +# Build the C BSP +bsp_root = "bsp_root" +mkdir(bsp_root) +bsp_prj_name = get_c_bsp(thistest.options.RTS, bsp_root) + +bsp_prj = os.path.join(bsp_root, f"{bsp_prj_name}.gpr") + +# Generate a simple project +main_prj = "prj.gpr" +with open(main_prj, "w") as prj_file: + print(f'with "{bsp_prj}";', file=prj_file) + print("project Prj is", file=prj_file) + print( + f' for Target use "{thistest.env.target.platform}";', + file=prj_file, + ) + print(' for Languages use ("C++");', file=prj_file) + print(' for Source_Dirs use (".");', file=prj_file) + print(' for Main use ("main.cpp");', file=prj_file) + print(' for Object_Dir use "obj";', file=prj_file) + print(" package Compiler is", file=prj_file) + print( + f""" + for Switches ("C++") use {bsp_prj_name}.Common_Switches; + """, + file=prj_file, + ) + print(" end Compiler;", file=prj_file) + print(" package Linker is", file=prj_file) + print( + f' for Switches ("C++") use {bsp_prj_name}.Linker_Switches;', + file=prj_file, + ) + print(" end Linker;", file=prj_file) + print("end Prj;", file=prj_file) + +# Setup the integrated instrumentation +compiler = driver_for_lang("C++") +gnatcov_artifact_dir = "gcv_artifacts" +xcov( + [ + "setup-integration", + "--level=stmt+mcdc", + f"--files={os.path.abspath('main.cpp')}", + f"--compilers={os.path.basename(compiler)}", + f"--output-dir={gnatcov_artifact_dir}", + ] +) +env.add_path(gnatcov_artifact_dir) + +# Build our simple C main and execute it +cmdrun([GPRBUILD, "-P", main_prj], for_pgm=False) +run_log = "run.log" +run_cov_program("./obj/main", out=run_log) + +trace_name = "main.srctrace" +xcov(["extract-base64-trace", run_log, trace_name]) +xcov( + [ + "coverage", + "--sid", + os.path.join(gnatcov_artifact_dir, "main.cpp.sid"), + "-axcov", + "-cstmt+mcdc", + trace_name, + ] +) +check_xcov_reports( + reports_dir=".", + expected_cov={"main.cpp.xcov": {"+": {6, 7, 9, 11}}}, +) + +thistest.result() From 09ff38f40484b80b4782a3f62fa6e1e426847973 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 5 Sep 2025 09:25:28 +0200 Subject: [PATCH 1422/1483] Update test.opt --- .../tests/integrated_instr_cross/initializer-range-c++/test.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.opt b/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.opt index 1ddcc4440..0d9edcec5 100644 --- a/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.opt +++ b/testsuite/tests/integrated_instr_cross/initializer-range-c++/test.opt @@ -1,3 +1,4 @@ !bareboard DEAD This test relies on examples specific to bareboard targets morello-elf DEAD No BSP provided with this toolchain leon3-elf XFAIL Linker cannot find fwrite (to be investigated) +ppc-elf DEAD Structure of the bsp project is not as expected From 56bfe6d3212f4a16db8d95366ffc65be159e131e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Fri, 5 Sep 2025 09:30:23 +0200 Subject: [PATCH 1423/1483] Replace mentions of GNATDAS with GNAT DAS --- doc/conf.py | 2 +- doc/gnatcov/cons_traces.rst | 2 +- doc/gnatcov/getting_started.rst | 2 +- doc/gnatcov/integrated_instr.rst | 4 ++-- doc/gnatcov/src_traces.rst | 8 ++++---- doc/gnatcov/units_of_interest.rst | 2 +- tools/gnatcov/examples/doc/README.examples | 2 +- 7 files changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/conf.py b/doc/conf.py index 668ac9602..4d102252c 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -59,7 +59,7 @@ master_doc = "index" # General information about the project. -project = "GNATDAS" +project = "GNAT DAS" copyright = f"2009-{datetime.now().year}, AdaCore" # noqa: A001 docname = "Manuals" diff --git a/doc/gnatcov/cons_traces.rst b/doc/gnatcov/cons_traces.rst index a83860cf1..d9f1256c9 100644 --- a/doc/gnatcov/cons_traces.rst +++ b/doc/gnatcov/cons_traces.rst @@ -19,7 +19,7 @@ Single unit tested by different programs ======================================== The sources for the following example can be found under the -`share/examples/gnatcoverage/doc/cons_traces` directory of the GNATDAS +`share/examples/gnatcoverage/doc/cons_traces` directory of the GNAT DAS disctribution. We will first consider achieving statement coverage of the following example diff --git a/doc/gnatcov/getting_started.rst b/doc/gnatcov/getting_started.rst index a9a46dc55..0c76a0afd 100644 --- a/doc/gnatcov/getting_started.rst +++ b/doc/gnatcov/getting_started.rst @@ -116,7 +116,7 @@ Sample project -------------- The sources for this examples are provided under the -`share/examples/gnatcoverage/doc/getting_started/` directory of the GNATDAS +`share/examples/gnatcoverage/doc/getting_started/` directory of the GNAT DAS distribution. We consider an Ada package providing a set of elementary operations diff --git a/doc/gnatcov/integrated_instr.rst b/doc/gnatcov/integrated_instr.rst index 924817a29..f6b2781a8 100644 --- a/doc/gnatcov/integrated_instr.rst +++ b/doc/gnatcov/integrated_instr.rst @@ -83,7 +83,7 @@ A simple Makefile example ========================= The sources for the following example can be found under the -``share/examples/gnatcoverage/doc/integrated`` directory of the GNATDAS +``share/examples/gnatcoverage/doc/integrated`` directory of the GNAT DAS distribution. The following considers that the coverage runtime was previously installed with @@ -136,7 +136,7 @@ A simple CMake example ====================== The sources for the following example can be found under the -``share/examples/gnatcoverage/doc/integrated`` directory of the GNATDAS +``share/examples/gnatcoverage/doc/integrated`` directory of the GNAT DAS distribution. To ensure that the Makefile provided with the example sources uses CMake as a build system, specify ``BUILD_SYSTEM=CMake`` on the `make` invocation. diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 07a92744d..87f8acf93 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -925,7 +925,7 @@ Its contents are: pragma Ignore_Pragma (Refined_Depends); The source for the following example can be found under the -`share/examples/gnatcoverage/spark_instrumentation/` directory of the GNATDAS +`share/examples/gnatcoverage/spark_instrumentation/` directory of the GNAT DAS distribution. The configuration pragma file can be passed to the compiler either by @@ -993,7 +993,7 @@ very basic sample program below, assuming the existence of a ``Sensors`` source unit providing access to some sensor values. The sources for this example can be found under the -`share/examples/gnatcoverage/doc/cross_example` directory of the GNATDAS +`share/examples/gnatcoverage/doc/cross_example` directory of the GNAT DAS disctribution. .. code-block:: ada @@ -1119,7 +1119,7 @@ For the sake of the example, we will consider that at a given point in time. The sources for this example can be found under the -`share/examples/gnatcoverage/doc/library_instr/` directory of the GNATDAS +`share/examples/gnatcoverage/doc/library_instr/` directory of the GNAT DAS distribution. Setting up the coverage runtime @@ -1382,7 +1382,7 @@ elaboration constraints using interfacing pragmas (``pragma Import``/``pragma Export``). Assuming that the IO handling code is self-contained and is already present in the closure of the project to analyze, the following example demonstrates how to handle this case. The sources can be found under the -`share/examples/gnatcoverage/custom_rt/` directory of the GNATDAS distribution. +`share/examples/gnatcoverage/custom_rt/` directory of the GNAT DAS distribution. First, move the IO handling code to an independent library project: diff --git a/doc/gnatcov/units_of_interest.rst b/doc/gnatcov/units_of_interest.rst index 73884648a..cb1286a3c 100644 --- a/doc/gnatcov/units_of_interest.rst +++ b/doc/gnatcov/units_of_interest.rst @@ -267,7 +267,7 @@ when parts of the testing code is implemented with ``separate`` subunits in Ada. The sources for the following example can be found under the -`share/examples/gnatcoverage/doc/subunits/` directory of the GNATDAS +`share/examples/gnatcoverage/doc/subunits/` directory of the GNAT DAS distribution. The dummy example below shows a possible organization of this kind, diff --git a/tools/gnatcov/examples/doc/README.examples b/tools/gnatcov/examples/doc/README.examples index 3566e9e58..87319a508 100644 --- a/tools/gnatcov/examples/doc/README.examples +++ b/tools/gnatcov/examples/doc/README.examples @@ -14,7 +14,7 @@ additional context. When a section name is referenced, either in this document, or in the Makefile comments, this is always a section within the GNATcoverage manual, which is -itself a subset of the GNATDAS user's manual. +itself a subset of the GNAT DAS user's manual. - getting_started: A simple project on which the general GNATcoverage workflow From 054688ba6439fe995e76aa4fe188680d21e4e19e Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 19 Aug 2025 14:50:12 +0200 Subject: [PATCH 1424/1483] Add support for metaprogramming instances for C/C++ --- .../tests/207-srctrace-version/foo.c.sid | Bin 1186 -> 1026 bytes testsuite/tests/207-srctrace-version/main.sid | Bin 1422 -> 1426 bytes .../207-srctrace-version/reference.srctrace | Bin 336 -> 336 bytes .../213-sarif-report/all-lang/full/ref.sarif | 8 +- .../tests/213-sarif-report/c/full/ref.sarif | 6 +- .../tests/213-sarif-report/cpp/full/ref.sarif | 6 +- testsuite/tests/429-metaprog-c/bar.h | 3 + testsuite/tests/429-metaprog-c/foo.h | 3 + testsuite/tests/429-metaprog-c/test.c | 14 + .../tests/429-metaprog-c/test.c.xcov.expected | 35 ++ testsuite/tests/429-metaprog-c/test.opt | 1 + testsuite/tests/429-metaprog-c/test.py | 25 ++ .../unsupported/test.opt | 1 + .../unsupported/test.py | 31 +- .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 1508 -> 1508 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2580 -> 2580 bytes .../gen/arm-elf-linux/main_1.sid | Bin 445 -> 449 bytes .../gen/arm-elf-linux/main_2.sid | Bin 445 -> 449 bytes .../gen/arm-elf-linux/pkg.sid | Bin 1150 -> 1158 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1831 -> 1843 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1841 -> 1853 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 2422 -> 2438 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 2353 -> 2369 bytes .../gen/x86_64-windows/main_1.sid | Bin 447 -> 451 bytes .../gen/x86_64-windows/main_2.sid | Bin 447 -> 451 bytes .../gen/x86_64-windows/pkg.sid | Bin 1154 -> 1162 bytes tools/gnatcov/annotations-dynamic_html.adb | 2 + tools/gnatcov/annotations.adb | 76 +++-- tools/gnatcov/clang-extensions.ads | 12 +- tools/gnatcov/clang-wrapper.cc | 8 + tools/gnatcov/instrument-c.adb | 303 +++++++++++++----- tools/gnatcov/instrument-c.ads | 14 +- tools/gnatcov/instrument-c_utils.adb | 16 + tools/gnatcov/instrument-c_utils.ads | 5 + tools/gnatcov/sc_obligations.adb | 214 ++++++++----- tools/gnatcov/sc_obligations.ads | 62 ++-- 36 files changed, 594 insertions(+), 251 deletions(-) create mode 100644 testsuite/tests/429-metaprog-c/bar.h create mode 100644 testsuite/tests/429-metaprog-c/foo.h create mode 100644 testsuite/tests/429-metaprog-c/test.c create mode 100644 testsuite/tests/429-metaprog-c/test.c.xcov.expected create mode 100644 testsuite/tests/429-metaprog-c/test.opt create mode 100644 testsuite/tests/429-metaprog-c/test.py create mode 100644 testsuite/tests/N430-005-c-static-inline/unsupported/test.opt diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid index d0ecec554373ef0e8806b3be7e5dd46d7ea16d47..62a9e0c8ac05155a302b4828f7d31bc1f1017818 100644 GIT binary patch delta 11 ScmZ3)*~BrSaI+xeL}maNt^<$& delta 144 zcmZqTSj0J@(4K{Xfq@Z(*?bb)Dt19NimijB^^i~uRE1o!{| delta 14 Vcmcb>bb)Dt19QAd>PBZ?MgS(r1abfX diff --git a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif index 39f4563cc..327db8271 100644 --- a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif @@ -265,7 +265,7 @@ "uri": "c_source.c" }, "region": { - "startColumn": 7, + "startColumn": 8, "startLine": 24 } } @@ -307,7 +307,7 @@ "uri": "c_source.c" }, "region": { - "startColumn": 7, + "startColumn": 8, "startLine": 34 } } @@ -412,7 +412,7 @@ "uri": "cpp_source.cpp" }, "region": { - "startColumn": 7, + "startColumn": 8, "startLine": 24 } } @@ -454,7 +454,7 @@ "uri": "cpp_source.cpp" }, "region": { - "startColumn": 7, + "startColumn": 8, "startLine": 34 } } diff --git a/testsuite/tests/213-sarif-report/c/full/ref.sarif b/testsuite/tests/213-sarif-report/c/full/ref.sarif index bdd0c1513..2898d4b85 100644 --- a/testsuite/tests/213-sarif-report/c/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/c/full/ref.sarif @@ -55,7 +55,7 @@ "uri": "foo.c" }, "region": { - "startColumn": 7, + "startColumn": 8, "startLine": 9 } } @@ -97,7 +97,7 @@ "uri": "lib.c" }, "region": { - "startColumn": 7, + "startColumn": 8, "startLine": 6 } } @@ -223,7 +223,7 @@ "uri": "main.c" }, "region": { - "startColumn": 7, + "startColumn": 8, "startLine": 24 } } diff --git a/testsuite/tests/213-sarif-report/cpp/full/ref.sarif b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif index 01c84475b..897cf8cf5 100644 --- a/testsuite/tests/213-sarif-report/cpp/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif @@ -55,7 +55,7 @@ "uri": "foo.cpp" }, "region": { - "startColumn": 7, + "startColumn": 8, "startLine": 9 } } @@ -97,7 +97,7 @@ "uri": "lib.cpp" }, "region": { - "startColumn": 7, + "startColumn": 8, "startLine": 6 } } @@ -223,7 +223,7 @@ "uri": "main.cpp" }, "region": { - "startColumn": 7, + "startColumn": 8, "startLine": 24 } } diff --git a/testsuite/tests/429-metaprog-c/bar.h b/testsuite/tests/429-metaprog-c/bar.h new file mode 100644 index 000000000..f6cd799d1 --- /dev/null +++ b/testsuite/tests/429-metaprog-c/bar.h @@ -0,0 +1,3 @@ +{ + DECL (a_bar) +} diff --git a/testsuite/tests/429-metaprog-c/foo.h b/testsuite/tests/429-metaprog-c/foo.h new file mode 100644 index 000000000..5b2d73759 --- /dev/null +++ b/testsuite/tests/429-metaprog-c/foo.h @@ -0,0 +1,3 @@ +#include "bar.h" +DECL (a_foo) +return 0; diff --git a/testsuite/tests/429-metaprog-c/test.c b/testsuite/tests/429-metaprog-c/test.c new file mode 100644 index 000000000..aca39b8b8 --- /dev/null +++ b/testsuite/tests/429-metaprog-c/test.c @@ -0,0 +1,14 @@ +#define DECL(x) int x = 0; + +int +foo () +{ + DECL (a_main) +#include "foo.h" +} + +int +main () +{ + return 0; +} diff --git a/testsuite/tests/429-metaprog-c/test.c.xcov.expected b/testsuite/tests/429-metaprog-c/test.c.xcov.expected new file mode 100644 index 000000000..9b983483d --- /dev/null +++ b/testsuite/tests/429-metaprog-c/test.c.xcov.expected @@ -0,0 +1,35 @@ +33% of 3 lines covered +20% statement coverage (1 out of 5) + +Coverage level: stmt + 1 .: #define DECL(x) int x = 0; + 2 .: + 3 .: int + 4 .: foo () + 5 .: { + 6 -: DECL (a_main) +statement "int a_mai..." at 6:3 not executed + note: in definition of macro DECL at location test.c:1:17 + note: from expansion of macro DECL at location test.c:6:3 + 7 -: #include "foo.h" +statement "int a_bar..." at 7:10 not executed + note: in file bar.h at location bar.h:2:3 + note: from inclusion of bar.h at location foo.h:1:10 + note: from inclusion of foo.h at location test.c:7:10 + note: in definition of macro DECL at location test.c:1:17 + note: from expansion of macro DECL at location bar.h:2:3 +statement "int a_foo..." at 7:10 not executed + note: in file foo.h at location foo.h:2:1 + note: from inclusion of foo.h at location test.c:7:10 + note: in definition of macro DECL at location test.c:1:17 + note: from expansion of macro DECL at location foo.h:2:1 +statement "return 0;" at 7:10 not executed + note: in file foo.h at location foo.h:3:1 + note: from inclusion of foo.h at location test.c:7:10 + 8 .: } + 9 .: + 10 .: int + 11 .: main () + 12 .: { + 13 +: return 0; + 14 .: } diff --git a/testsuite/tests/429-metaprog-c/test.opt b/testsuite/tests/429-metaprog-c/test.opt new file mode 100644 index 000000000..194738427 --- /dev/null +++ b/testsuite/tests/429-metaprog-c/test.opt @@ -0,0 +1 @@ +bin-traces DEAD Use case not supported with binary traces diff --git a/testsuite/tests/429-metaprog-c/test.py b/testsuite/tests/429-metaprog-c/test.py new file mode 100644 index 000000000..0dab10777 --- /dev/null +++ b/testsuite/tests/429-metaprog-c/test.py @@ -0,0 +1,25 @@ +""" +Check that we have the right annotations for SCOs that come from +metaprogramming instances. +""" + +import os + +from SCOV.minicheck import build_run_and_coverage +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor, thistest + +Wdir("tmp_") +build_run_and_coverage( + gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["test.c"])), + covlevel="stmt", + mains=["test"], + extra_coverage_args=["--annotate=xcov+"], +) + +thistest.fail_if_diff( + os.path.join("..", "test.c.xcov.expected"), + os.path.join("obj", "test.c.xcov"), +) +thistest.result() diff --git a/testsuite/tests/N430-005-c-static-inline/unsupported/test.opt b/testsuite/tests/N430-005-c-static-inline/unsupported/test.opt new file mode 100644 index 000000000..2c8011a19 --- /dev/null +++ b/testsuite/tests/N430-005-c-static-inline/unsupported/test.opt @@ -0,0 +1 @@ +src-traces DEAD Use case supported with source traces diff --git a/testsuite/tests/N430-005-c-static-inline/unsupported/test.py b/testsuite/tests/N430-005-c-static-inline/unsupported/test.py index 6afa40593..a377299a7 100644 --- a/testsuite/tests/N430-005-c-static-inline/unsupported/test.py +++ b/testsuite/tests/N430-005-c-static-inline/unsupported/test.py @@ -28,29 +28,14 @@ tolerate_instrument_messages="unexpected SCO overlapping", ) -# With source traces, the warning is emitted at instrumentation time, whereas -# it is emitted at coverage time with binary traces. -# -# As SCOs source locations differ for binary and source traces, we get -# different warnings. Note that the instrumentation warning is the most -# precise. - -if thistest.options.trace_mode == "src": - output_string = "gnatcov instrument output" - output_file = "instrument.log" - expected_output = ( - "!!! foo.h:1:1: unexpected SCO overlapping with SCO #1: " - "STATEMENT at foo.h:1:1-13, discarding overlapping SCO\n" - "!!! foo.h:2:1: unexpected SCO overlapping with SCO #2: " - "STATEMENT at foo.h:2:1-21, discarding overlapping SCO" - ) -else: - output_string = "gnatcov coverage output" - output_file = "coverage.log" - expected_output = ( - "!!! foo.h:2:8: unexpected SCO overlapping with SCO #2: " - "STATEMENT at foo.h:2:8-20, discarding overlapping SCO" - ) +# Check that gnatcov coverage warns when using binary traces + +output_string = "gnatcov coverage output" +output_file = "coverage.log" +expected_output = ( + "!!! foo.h:2:8: unexpected SCO overlapping with SCO #2: " + "STATEMENT at foo.h:2:8-20, discarding overlapping SCO" +) thistest.fail_if_no_match( output_string, expected_output, contents_of(output_file) diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index 8d65dbe4b94a5d8e0b66773112166929960175d1..8fd2222d584f48048347816db840b63e7cb94304 100644 GIT binary patch delta 71 zcmaFD{e*jh94m(yuQk_1Wkq8n0|o|m1_lOUAT}~EGSxM(&^0nrFf_I@wX`xcVBi3X Wa|5x0k-3qHp{22rh55$vTvh^!4!Q~- delta 53 zcmbOtGDT#994k9ByAl6HWn)EiT?1nU19K}=11m#Q1`Y-W25ul$FflMQG%~U@FtyxR HK9>^!2u%s{ diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index 96f6c5407c5cdfb1fd3152e0d331593004cdd19f..0730d49454ff3fcc711da9b33c7cd3962409e446 100644 GIT binary patch delta 13 UcmdnXe2{rU`NXXP8=I{d0VqNRQ2+n{ delta 10 RcmX@eyq9@G`NnEDMgSNg1OEU3 diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid index 7323a92fefb9207223f3a92132b9facd0336c31e..2ce002c1fd893fc1a0e67a166c78afdc2d4eb220 100644 GIT binary patch delta 13 UcmdnXe2{rU`NXXP8=I{d0VqNRQ2+n{ delta 10 RcmX@eyq9@G`NnEDMgSNg1OEU3 diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid index 49d156be429897c0a3ec5e4525ea72703ced3d24..ab8c243bacaf30bf2e778667e96682f9661bb211 100644 GIT binary patch delta 18 acmeyz(Z)Gp)no@ImWiwSHk&YdF#`ZcCI+Vf delta 18 acmZqU{Kqk2)nox?mWi9XHajr7F#`ZZdIp35 diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt index d01ce8c959310edfdc0079e589d5b4757387aaf0..9901e7fd477f30415d1ef08e34dfdf9797b67e0d 100644 GIT binary patch delta 54 zcmZ3^x0!E)DAQy?Ca=j3%q)|mnfx{{Wolz)XHfE2tKHZ+*@*2TuZ6CWk%FPAm8qqb Kp}}MUc5wi#w+?y$ delta 69 zcmdnYx14W-DAQy~Cb!ASOn#fUGBq)?-;iy;7Uohl*^cd^in*?Vv4Vl6m8pT1p^1XF OfsvJg0V4whz-R!*JP&sO diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index efb763a2b70342f3e69ca18ff6a64400f66529b1..6ec661f68cf6eb5a8e8832d5ff555ec089b076aa 100644 GIT binary patch delta 73 zcmdnUx0i2&DAQyIW|qmKOm36InSwSiW$I&QU%(PFvvyy|EH`Ps@Cm9(S7zBXW$V|_m TTtUOgz{u3V!pLxP8^;F#v>FqZ delta 60 zcmZn@{wB1+k8yGk81M|(e6fj>W(doI C(-Im0 delta 36 scmX>ov{7h-8{=dz#w(MRm>x`KV{Y2q!~B?qoulS>SC~uHHq)$ diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid index c15c782f198c6dc4d6084f2a00fa285a3931b817..2ff33613884c9b1348322f6c9f688772e7f9cdd7 100644 GIT binary patch delta 13 Ucmdnbe3*Gc<;3j*8(Xay0VtFOTL1t6 delta 10 RcmX@iyq|eO<;Ge!MgSO91P1^B diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid index 4d89b525b304ae68e888d097f98b44f1d7754491..6ed8a0ea410ff1cc362d719710d8b1ffdc8ad01f 100644 GIT binary patch delta 13 Ucmdnbe3*Gc<;3j*8(Xay0VtFOTL1t6 delta 10 RcmX@iyq|eO<;Ge!MgSO91P1^B diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid index 0ef87464e0de311707f64eb0ec4f09a14721a6bb..7517581311b10b153cecd57d7da11740bc2c7bfb 100644 GIT binary patch delta 22 ecmZqT?BblTZt?{tmWk{7CM&S8Y_?%^V+H_X0tbfx delta 18 ZcmeC;Y~q}-ZsMlC$r4OFn*$iFm;pmH1}Fdk diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 1090abefe..f9763f4ea 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -262,6 +262,8 @@ package body Annotations.Dynamic_Html is -- * text -- * coverage -- * range + -- * annotations + -- * kind function Src_Range (SCO : SCO_Id) return JSON_Array; -- Return a JSON array for the range Sloc_Start .. Sloc_End from SCO diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index c3a5ec1ea..cf95b4a1c 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -691,6 +691,7 @@ package body Annotations is is Sloc_Start : Source_Location := First_Sloc (SCO); Sloc_End : Source_Location := End_Lex_Element (Last_Sloc (SCO)); + pragma Assert (Sloc_Start.Source_File = Sloc_End.Source_File); Desc : Unbounded_String; -- SCO description: shortened view of the SCO tokens, with a macro @@ -700,11 +701,11 @@ package body Annotations is -- First, if this is a SCO inside a macro expansion, get the -- preprocessed excerpt for reporting purposes. - if Has_PP_Info (SCO) and then Get_PP_Info (SCO).Kind = In_Expansion then + if Has_Macro_Info (SCO) then declare SFI : constant Source_File_Index := Sloc_Start.Source_File; - Info : constant PP_Info := Get_PP_Info (SCO); + Info : constant PP_Info := Get_Macro_Info (SCO); Preprocessed_Filename : constant String := Get_PP_Filename (SFI) & ".prepro"; Postprocessed_Filename : constant String := Get_PP_Filename (SFI); @@ -712,7 +713,6 @@ package body Annotations is Get_Index_From_Generic_Name (Postprocessed_Filename, Source_File, Insert => False); - begin if Postprocessed_SFI = No_Source_File then declare @@ -755,12 +755,19 @@ package body Annotations is end if; if Postprocessed_SFI /= No_Source_File then + Sloc_Start := First_Sloc (Info.Tokens_Source_Range); Sloc_Start.Source_File := Postprocessed_SFI; - Sloc_Start.L := Info.PP_Source_Range.First_Sloc; + Sloc_End := Last_Sloc (Info.Tokens_Source_Range); Sloc_End.Source_File := Postprocessed_SFI; - Sloc_End.L := Info.PP_Source_Range.Last_Sloc; end if; end; + elsif Has_Include_Info (SCO) then + declare + Info : constant PP_Info := Get_Include_Info (SCO); + begin + Sloc_Start := First_Sloc (Info.Tokens_Source_Range); + Sloc_End := Last_Sloc (Info.Tokens_Source_Range); + end; end if; -- As an approximation (given the diversity of provenance for sloc @@ -840,33 +847,54 @@ package body Annotations is -- SCO_Annotations -- --------------------- - function SCO_Annotations (SCO : SCO_Id) return String_Vectors.Vector is + function SCO_Annotations (SCO : SCO_Id) return String_Vectors.Vector + is + Annotations : String_Vectors.Vector; begin - if Has_PP_Info (SCO) then + -- Start by adding the inclusion information + + if Has_Include_Info (SCO) then declare - Info : constant PP_Info := Get_PP_Info (SCO); - Annotations : String_Vectors.Vector; + Info : constant PP_Info := Get_Include_Info (SCO); begin - if Info.Kind = In_Expansion then + Annotations.Append + ("in file " + & Info.Definition_Loc.Name + & " at location " + & Slocs.Image (Info.Definition_Loc.Sloc)); + + for Exp_Info of Info.Expansion_Stack loop Annotations.Append - ("in definition of macro " - & Info.Definition_Loc.Macro_Name + ("from inclusion of " + & Exp_Info.Name & " at location " - & Slocs.Image (Info.Definition_Loc.Sloc)); - - for Exp_Info of Info.Expansion_Stack loop - Annotations.Append - ("from expansion of macro " - & Exp_Info.Macro_Name - & " at location " - & Slocs.Image (Exp_Info.Sloc)); - end loop; + & Slocs.Image (Exp_Info.Sloc)); + end loop; + end; + end if; - return Annotations; - end if; + -- Then, add the macro expansion information + + if Has_Macro_Info (SCO) then + declare + Info : constant PP_Info := Get_Macro_Info (SCO); + begin + Annotations.Append + ("in definition of macro " + & Info.Definition_Loc.Name + & " at location " + & Slocs.Image (Info.Definition_Loc.Sloc)); + + for Exp_Info of Info.Expansion_Stack loop + Annotations.Append + ("from expansion of macro " + & Exp_Info.Name + & " at location " + & Slocs.Image (Exp_Info.Sloc)); + end loop; end; end if; - return String_Vectors.Empty_Vector; + return Annotations; end SCO_Annotations; ------------------------ diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index 5caacd3d2..89cdd4cc7 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -284,7 +284,7 @@ package Clang.Extensions is with Import, Convention => C, External_Name => "clang_getImmediateMacroCallerLoc"; - -- See getImmediateMacroCallerLoc in clang/Basic/SourceManager.h. + -- See getImmediateMacroCallerLoc in clang/Basic/SourceManager.h function Get_Immediate_Expansion_Loc (Loc : Source_Location_T; @@ -292,7 +292,7 @@ package Clang.Extensions is with Import, Convention => C, External_Name => "clang_getImmediateExpansionLoc"; - -- See getImmediateExpansionRange in clang/Basic/SourceManager.h. + -- See getImmediateExpansionRange in clang/Basic/SourceManager.h function Get_Expansion_End (TU : Translation_Unit_T; @@ -300,7 +300,7 @@ package Clang.Extensions is with Import, Convention => C, External_Name => "clang_getExpansionEnd"; - -- See getExpansionRange in clang/Basic/SourceManager.h. + -- See getExpansionRange in clang/Basic/SourceManager.h function Get_Spelling_Loc (TU : Translation_Unit_T; @@ -308,6 +308,12 @@ package Clang.Extensions is with Import, Convention => C, External_Name => "clang_getSpellingLoc"; -- See getSpellingLoc in clang/Basic/SourceManager.h + function Get_Include_Loc + (TU : Translation_Unit_T; + Loc : Source_Location_T) return Source_Location_T + with Import, Convention => C, External_Name => "clang_getIncludeLoc"; + -- See getIncludeLoc in clang/Basic/SourceManager.h + procedure Print_Location (TU : Translation_Unit_T; Loc : Source_Location_T) with Import, Convention => C, External_Name => "clang_printLocation"; diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index cdd4f6bc0..ea0ce94f7 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -1126,6 +1126,14 @@ clang_getExpansionEnd (CXTranslationUnit TU, CXSourceLocation Loc) return translateSLoc (TU, SM.getExpansionRange (SLoc).getEnd ()); } +extern "C" CXSourceLocation +clang_getIncludeLoc (CXTranslationUnit TU, CXSourceLocation Loc) +{ + SourceLocation SLoc = translateSourceLocation (Loc); + const SourceManager &SM = getSourceManager (TU); + return translateSLoc (TU, SM.getPresumedLoc (SLoc).getIncludeLoc ()); +} + extern "C" CXTranslationUnit clang_getCursorTU (CXCursor C) { diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 94e7acabf..a6a4f848d 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -162,6 +162,78 @@ package body Instrument.C is -- Return the list of arguments that should always be passed to -- Parse_Translation_Unit. + ------------------- + -- Scopes logic -- + ------------------- + + procedure Enter_Scope + (UIC : in out C_Unit_Inst_Context'Class; + N : Cursor_T); + -- Open a scope for N under the scope of the file in which the + -- corresponding code was written. This must be completed with a call to + -- the function Exit_Scope, defined below. Assume that the scope first SCO + -- is the next generated SCO (SCOs.SCO_Table.Last + 1). Update + -- UIC.Scopes to the created entity and UIC.Current_File_Scope to the + -- corresponding file. + + procedure Exit_Scope (UIC : in out C_Unit_Inst_Context'Class); + -- Close the current scope, removing the current scope of the current file + -- from UIC.Scopes if it does not contain SCOs. Assume that the last + -- generated SCO (SCOs.SCO_Table.Last) is the last SCO for the current + -- scope. + + function Relocate_SCO + (UIC : C_Unit_Inst_Context'Class; + Loc : Source_Location) return Boolean + is (Scopes_In_Files_Map.Key (UIC.Current_File_Scope) /= Loc.Source_File); + -- As we don't allow scopes across various files, every SCO needs to be in + -- the same file of the file its parent scope belongs to. This function + -- indicates whether the SCO located at Loc falls in the latter case, + -- meaning it should be relocated to its inclusion point in its parent + -- scope. Note that this is typically used when doing metaprogramming + -- in C/C++, along with abusing the macro system. + -- + -- See this C example (reduced from the git codebase): + -- + -- // main.c + -- /* auxiliary function for binary search in interval table */ + -- static int bisearch(int ucs, int max) + -- { + -- return 0; + -- } + -- + -- + -- static int git_wcwidth(int ch) + -- { + -- /* + -- * Sorted list of non-overlapping intervals of non-spacing characters, + -- */ + -- #include "unicode-width.h" + -- + -- return 1; + -- } + -- + -- // unicode-width.h + -- static const struct interval zero_width[] = {{ 0x0300, 0x036F }}; + -- + -- For more complex metaprogramming instances, see this C++ code excerpt + -- from the LLVM code base - which uses token concatenations in addition + -- to the macro system: + -- + -- #define OVERLOADED_OPERATOR \ + -- (Name, Spelling, Token, Unary, Binary, MemberOnly) \ + -- case OO_##Name: \ + -- OperatorName = "operator" Spelling; \ + -- break; + -- #define OVERLOADED_OPERATOR_MULTI \ + -- (Name, Spelling, Unary, Binary, MemberOnly) + -- #include "clang/Basic/OperatorKinds.def" + -- + -- In the OperatorKinds.def file, each of the overloadable C++ + -- operators is enumerated with either the OVERLOADED_OPERATOR or + -- OVERLOADED_OPERATOR_MULTI macro, each of which can be specified by + -- the code including this file. + --------------------------- -- Passes specificities -- --------------------------- @@ -182,25 +254,6 @@ package body Instrument.C is type Instrument_Pass_Kind is new Pass_Kind with null record; - overriding procedure Enter_Scope - (Pass : Instrument_Pass_Kind; - UIC : in out C_Unit_Inst_Context'Class; - N : Cursor_T); - -- Open a scope for N under the scope of the file in which the - -- corresponding code was written. This must be completed with a call to - -- the function Exit_Scope, defined below. Assume that the scope first SCO - -- is the next generated SCO (SCOs.SCO_Table.Last + 1). Update - -- UIC.Scopes to the created entity and UIC.Current_File_Scope to the - -- corresponding file. - - overriding procedure Exit_Scope - (Pass : Instrument_Pass_Kind; - UIC : in out C_Unit_Inst_Context'Class); - -- Close the current scope, removing the current scope of the current file - -- from UIC.Scopes if it does not contain SCOs. Assume that the last - -- generated SCO (SCOs.SCO_Table.Last) is the last SCO for the current - -- scope. - overriding procedure Append_SCO (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; @@ -611,10 +664,9 @@ package body Instrument.C is -- Enter_Scope -- ----------------- - overriding procedure Enter_Scope - (Pass : Instrument_Pass_Kind; - UIC : in out C_Unit_Inst_Context'Class; - N : Cursor_T) + procedure Enter_Scope + (UIC : in out C_Unit_Inst_Context'Class; + N : Cursor_T) is procedure Enter_File_Scope (UIC : in out C_Unit_Inst_Context'Class; @@ -727,9 +779,7 @@ package body Instrument.C is -- Exit_Scope -- ---------------- - overriding procedure Exit_Scope - (Pass : Instrument_Pass_Kind; - UIC : in out C_Unit_Inst_Context'Class) + procedure Exit_Scope (UIC : in out C_Unit_Inst_Context'Class) is File_Scope_Ref : constant Scopes_In_Files_Map.Reference_Type := UIC.Scopes.Reference (UIC.Current_File_Scope); @@ -754,8 +804,9 @@ package body Instrument.C is Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name) is - Loc : Source_Location_T := Start_Sloc (N); - Info : PP_Info; + Loc_C : Source_Location_T := Start_Sloc (N); + Loc : constant Source_Location := Sloc (Loc_C); + Info : PP_Info; begin Append_SCO (C1, C2, From.L, To.L, From.Source_File, Last, Pragma_Aspect_Name); @@ -767,16 +818,67 @@ package body Instrument.C is return; end if; - -- TODO??? The actual source range should be a Source_Location, and not - -- a Local_Source_Location as it can refer to #included files. + -- Start by checking whether this is an instance of metaprogramming + -- (i.e. whose parent scope is in a different file than the node). + -- In this case, set the SCO location to the file of the parent scope. + + if Relocate_SCO (UIC, From) then + + -- Retrieve the inclusion expansion chain + + -- TODO??? deal with the case where the SCO is both in an instance + -- of metaprogramming and a macro expansion (and think of adding a + -- test for it). - Info.Actual_Source_Range := (From.L, To.L); - Info.PP_Source_Range := No_Local_Range; + declare + Scope_SFI : Source_File_Index renames + Scopes_In_Files_Map.Key (UIC.Current_File_Scope); + Inclusion_Loc_C : Source_Location_T := + Get_Include_Loc (UIC.TU, Loc_C); + Inclusion_Stack : Expansion_Lists.List; + Inclusion_Loc : Source_Location := Sloc (Inclusion_Loc_C); + Inclusion_File : Source_File_Index := Loc.Source_File; + begin + loop + Inclusion_Stack.Append + (Expansion_Info' + (Name => +Get_Simple_Name (Inclusion_File), + Sloc => Inclusion_Loc)); + Inclusion_File := Inclusion_Loc.Source_File; + + -- Exit before updating Inclusion_Loc to use the initial + -- inclusion point as an Actual_Source_Range for the stored + -- preprocessing information. + + exit when Scope_SFI = Inclusion_File; + Inclusion_Loc_C := Get_Include_Loc (UIC.TU, Inclusion_Loc_C); + Inclusion_Loc := Sloc (Inclusion_Loc_C); + end loop; + + -- The actual source range for the coverage obligation is the + -- location of the include directive in the parent scope source + -- file. + + Info := + (Tokens_Source_Range => To_Range (From, To), + Actual_Source_Range => + To_Range (Inclusion_Loc, Inclusion_Loc), + Expansion_Stack => Inclusion_Stack, + Definition_Loc => + Expansion_Info' + (Name => +Get_Simple_Name (Loc.Source_File), Sloc => Loc)); + + UIC.LL_Include_Info_Map.Insert (SCOs.SCO_Table.Last, Info); + end; + end if; + + Info.Actual_Source_Range := To_Range (From, To); + Info.Tokens_Source_Range := No_Range; -- Check if this is comes from a macro expansion, in which case we need -- to record some information, for reporting purposes. - if Is_Macro_Location (Loc) then + if Is_Macro_Location (Loc_C) then declare Expansion_Stack : Expansion_Lists.List; Definition_Info : Expansion_Info; @@ -856,15 +958,15 @@ package body Instrument.C is -- API to get either a filename, or a or -- string in these cases. - if Is_Macro_Arg_Expansion (Loc, Macro_Arg_Expanded_Loc, UIC.TU) + if Is_Macro_Arg_Expansion (Loc_C, Macro_Arg_Expanded_Loc, UIC.TU) then Macro_Expansion_Name := +Get_Immediate_Macro_Name_For_Diagnostics (Macro_Arg_Expanded_Loc, UIC.TU); Definition_Info := - (Macro_Name => Macro_Expansion_Name, - Sloc => + (Name => Macro_Expansion_Name, + Sloc => Presumed_Spelling_Location (UIC.TU, Macro_Arg_Expanded_Loc, @@ -872,20 +974,20 @@ package body Instrument.C is UIC.Options.Builtin_Macros)); else Macro_Expansion_Name := - +Get_Immediate_Macro_Name_For_Diagnostics (Loc, UIC.TU); + +Get_Immediate_Macro_Name_For_Diagnostics (Loc_C, UIC.TU); Definition_Info := - (Macro_Name => Macro_Expansion_Name, - Sloc => + (Name => Macro_Expansion_Name, + Sloc => Presumed_Spelling_Location (UIC.TU, - Loc, + Loc_C, Macro_Expansion_Name, UIC.Options.Builtin_Macros)); end if; - while Is_Macro_Location (Loc) loop + while Is_Macro_Location (Loc_C) loop - Immediate_Expansion_Loc := Loc; + Immediate_Expansion_Loc := Loc_C; -- Find the location of the immediately expanded macro. Getting -- the immediate expansion location yields a location in the @@ -945,11 +1047,11 @@ package body Instrument.C is Immediate_Expansion_Loc := Get_Immediate_Expansion_Loc (Immediate_Expansion_Loc, UIC.TU); Macro_Expansion_Name := - +Get_Immediate_Macro_Name_For_Diagnostics (Loc, UIC.TU); + +Get_Immediate_Macro_Name_For_Diagnostics (Loc_C, UIC.TU); -- Then, keep going up the expansion stack - Loc := Get_Immediate_Macro_Caller_Loc (Loc, UIC.TU); + Loc_C := Get_Immediate_Macro_Caller_Loc (Loc_C, UIC.TU); -- If the returned Macro_Definition_Name is an empty string, -- then it means the location refers to a token paste, or @@ -957,8 +1059,8 @@ package body Instrument.C is if Macro_Expansion_Name /= "" then Expansion_Stack.Append - ((Macro_Name => Macro_Expansion_Name, - Sloc => + ((Name => Macro_Expansion_Name, + Sloc => Presumed_Spelling_Location (UIC.TU, Immediate_Expansion_Loc, @@ -968,15 +1070,13 @@ package body Instrument.C is end loop; Info := - (Kind => In_Expansion, - PP_Source_Range => Info.PP_Source_Range, + (Tokens_Source_Range => Info.Tokens_Source_Range, Actual_Source_Range => Info.Actual_Source_Range, Expansion_Stack => Expansion_Stack, Definition_Loc => Definition_Info); end; + UIC.LL_Macro_Info_Map.Insert (SCOs.SCO_Table.Last, Info); end if; - - UIC.LL_PP_Info_Map.Insert (SCOs.SCO_Table.Last, Info); end Append_SCO; overriding procedure Append_SCO @@ -988,11 +1088,50 @@ package body Instrument.C is Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name) is + Actual_From : Source_Location := From; + Actual_To : Source_Location := To; + -- TODO??? clarify whether we still need From and To begin if UIC.Disable_Coverage then return; end if; + if Relocate_SCO (UIC, From) then + + -- If we relocate the SCO, we still preserve the SCO nesting by + -- locating it at: + -- + -- :- + -- + -- where Offset is the location of the sloc in the text buffer. + + declare + Relocation_SFI : Source_File_Index renames + Scopes_In_Files_Map.Key (UIC.Current_File_Scope); + Include_Loc_C : Source_Location_T := + Get_Include_Loc (UIC.TU, Start_Sloc (N)); + Include_Loc : Source_Location; + begin + loop + Include_Loc := Sloc (Include_Loc_C); + exit when Include_Loc.Source_File = Relocation_SFI; + Include_Loc_C := Get_Include_Loc (UIC.TU, Include_Loc_C); + end loop; + + Actual_From := Source_Location' + (Source_File => Relocation_SFI, + L => Local_Source_Location' + (Line => Include_Loc.L.Line, + Column => Integer (Offset (Start_Sloc (N))))); + + Actual_To := Source_Location' + (Source_File => Relocation_SFI, + L => Local_Source_Location' + (Line => Include_Loc.L.Line, + Column => Integer (Offset (End_Sloc (N))))); + end; + end if; + -- Insert a new entry to the UIC.Instrumented_Entities maps: even if -- this SOI does not possess instrumented SCOs (it can be the case if -- all of the code constructs are not instrumentable), we want an empty @@ -1000,8 +1139,9 @@ package body Instrument.C is -- proper initialization of checkpoints structures (e.g. Statement_Bits) -- later on. - if not UIC.Instrumented_Entities.Contains (From.Source_File) then - UIC.Instrumented_Entities.Insert (From.Source_File, (others => <>)); + if not UIC.Instrumented_Entities.Contains (Actual_From.Source_File) then + UIC.Instrumented_Entities.Insert + (Actual_From.Source_File, (others => <>)); end if; -- End the statement block if we entered a new file: we do not want @@ -1011,7 +1151,7 @@ package body Instrument.C is use type SCOs.SCO_Unit_Index; begin if SCOs.SCO_Unit_Table.Last /= 0 - and then Last_File /= From.Source_File + and then Last_File /= Actual_From.Source_File then UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); @@ -1019,7 +1159,8 @@ package body Instrument.C is end; Append_SCO - (C1, C2, From.L, To.L, From.Source_File, Last, Pragma_Aspect_Name); + (C1, C2, Actual_From.L, Actual_To.L, Actual_From.Source_File, Last, + Pragma_Aspect_Name); -- If this SCO is in a macro expansion, let's add source location -- information: we want to be able to know the actual source location @@ -1027,12 +1168,12 @@ package body Instrument.C is -- retrieve the actual string (from the preprocessed code) when -- producing a coverage report. - if UIC.LL_PP_Info_Map.Contains (SCOs.SCO_Table.Last) then + if UIC.LL_Macro_Info_Map.Contains (SCOs.SCO_Table.Last) then declare Start_Loc : constant Source_Location_T := Start_Sloc (N); End_Loc : constant Source_Location_T := End_Sloc (N); - Cursor_Source_Range : Slocs.Local_Source_Location_Range; + Cursor_Source_Range : Slocs.Source_Location_Range; procedure Update (LL_SCO : Nat; Info : in out PP_Info); @@ -1043,22 +1184,22 @@ package body Instrument.C is procedure Update (LL_SCO : Nat; Info : in out PP_Info) is pragma Unreferenced (LL_SCO); begin - if Info.Kind = In_Expansion then - Info.PP_Source_Range := Cursor_Source_Range; - end if; + Info.Tokens_Source_Range := Cursor_Source_Range; end Update; begin -- Get start and end of the range. Note: End_Loc is exclusive, -- whereas we need Cursor_Source_Range.Last_Sloc to be inclusive. - Cursor_Source_Range.First_Sloc := File_Location (Start_Loc); - Cursor_Source_Range.Last_Sloc := File_Location (End_Loc); - Cursor_Source_Range.Last_Sloc.Column := - Cursor_Source_Range.Last_Sloc.Column - 1; + Cursor_Source_Range.Source_File := Actual_From.Source_File; + Cursor_Source_Range.L.First_Sloc := File_Location (Start_Loc); + Cursor_Source_Range.L.Last_Sloc := File_Location (End_Loc); + Cursor_Source_Range.L.Last_Sloc.Column := + Cursor_Source_Range.L.Last_Sloc.Column - 1; - UIC.LL_PP_Info_Map.Update_Element - (UIC.LL_PP_Info_Map.Find (SCOs.SCO_Table.Last), Update'Access); + UIC.LL_Macro_Info_Map.Update_Element + (UIC.LL_Macro_Info_Map.Find (SCOs.SCO_Table.Last), + Update'Access); end; end if; end Append_SCO; @@ -2776,7 +2917,7 @@ package body Instrument.C is end if; if Cursor_Kind /= Cursor_Lambda_Expr then - UIC.Pass.Enter_Scope (UIC, N); + Enter_Scope (UIC, N); end if; if Stmts.Length > 0 then @@ -2821,7 +2962,7 @@ package body Instrument.C is end if; if Cursor_Kind /= Cursor_Lambda_Expr then - UIC.Pass.Exit_Scope (UIC); + Exit_Scope (UIC); end if; end; @@ -2833,11 +2974,11 @@ package body Instrument.C is | Cursor_Class_Decl | Cursor_Struct_Decl => - UIC.Pass.Enter_Scope (UIC, N); + Enter_Scope (UIC, N); Traverse_Declarations (UIC, Get_Children (N)); - UIC.Pass.Exit_Scope (UIC); + Exit_Scope (UIC); when Cursor_Linkage_Spec => Traverse_Declarations (UIC, Get_Children (N)); @@ -3578,7 +3719,8 @@ package body Instrument.C is -- Save into UIC the preprocessing information - UIC.LL_PP_Info_Map := UIC_Copy.LL_PP_Info_Map; + UIC.LL_Macro_Info_Map := UIC_Copy.LL_Macro_Info_Map; + UIC.LL_Include_Info_Map := UIC_Copy.LL_Include_Info_Map; -- Also copy back the annotation map and disabled region vector as well -- as the info on sources of interest, to avoid double processing. @@ -3703,6 +3845,8 @@ package body Instrument.C is Record_PP_Info_Last_SCO := SCOs.SCO_Table.Last; SCOs.Initialize; + UIC.Scopes.Clear; + UIC.Current_File_Scope := Scopes_In_Files_Map.No_Element; -- Then, instrument @@ -3734,7 +3878,8 @@ package body Instrument.C is & Nat'Image (Record_PP_Info_Last_SCO) & " coverage obligations," & " but got" & Nat'Image (SCOs.SCO_Table.Last) & ". Discarding preprocessing information."); - UIC.LL_PP_Info_Map.Clear; + UIC.LL_Macro_Info_Map.Clear; + UIC.LL_Include_Info_Map.Clear; end if; -- Now that the set of coverage obligations and the set of source files @@ -3765,13 +3910,25 @@ package body Instrument.C is -- SCO macro info map in our unit instrumentation context (bound to -- low level SCOs), and add it to the global macro info map. - for Cursor in UIC.LL_PP_Info_Map.Iterate loop + for Cursor in UIC.LL_Macro_Info_Map.Iterate loop + declare + use LL_SCO_PP_Info_Maps; + LL_SCO : constant Nat := Key (Cursor); + Info : constant PP_Info := Element (Cursor); + begin + Add_Macro_Info (SCO_Map (LL_SCO), Info); + end; + end loop; + + -- Do the same for inclusion information + + for Cursor in UIC.LL_Include_Info_Map.Iterate loop declare use LL_SCO_PP_Info_Maps; LL_SCO : constant Nat := Key (Cursor); Info : constant PP_Info := Element (Cursor); begin - Add_PP_Info (SCO_Map (LL_SCO), Info); + Add_Include_Info (SCO_Map (LL_SCO), Info); end; end loop; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 8c34bbd25..00243dee7 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -395,8 +395,11 @@ package Instrument.C is Pass : Pass_Kind_Acc; -- Current pass. See the Pass_Kind documentation for more details. - LL_PP_Info_Map : LL_SCO_PP_Info_Maps.Map; - -- Preprocessing information for low level SCOs + LL_Macro_Info_Map : LL_SCO_PP_Info_Maps.Map; + -- Macro information for low level SCOs + + LL_Include_Info_Map : LL_SCO_PP_Info_Maps.Map; + -- Inclusion information for low level SCOs Files_Of_Interest : File_Sets.Set; Sources_Of_Interest_Info : Source_Of_Interest_Maps.Map; @@ -472,13 +475,6 @@ private Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name) is null; - procedure Enter_Scope (Pass : Pass_Kind; - UIC : in out C_Unit_Inst_Context'Class; - N : Cursor_T) is null; - - procedure Exit_Scope (Pass : Pass_Kind; - UIC : in out C_Unit_Inst_Context'Class) is null; - procedure Instrument_Statement (Pass : Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index 4c2bdde01..8a83a7aa7 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -152,6 +152,22 @@ package body Instrument.C_Utils is return Sloc (Loc); end End_Sloc; + ------------ + -- Offset -- + ------------ + + function Offset (Loc : Source_Location_T) return unsigned is + Offset : aliased unsigned; + begin + Get_File_Location + (Loc, + System.Null_Address, + null, + null, + Offset'Access); + return Offset; + end Offset; + ---------- -- Kind -- ---------- diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 71825c142..3fb723568 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -19,6 +19,8 @@ with Ada.Containers; use Ada.Containers; with Ada.Containers.Vectors; +with Interfaces.C; + with Clang.CX_Source_Location; use Clang.CX_Source_Location; with Clang.Index; use Clang.Index; with Clang.Rewrite; use Clang.Rewrite; @@ -62,6 +64,9 @@ package Instrument.C_Utils is function End_Sloc (N : Cursor_T) return Source_Location; -- Return the end location of a node + function Offset (Loc : Source_Location_T) return Interfaces.C.unsigned; + -- Return the offset of the location in the text buffer + function Kind (N : Cursor_T) return Cursor_Kind_T; -- Return the kind of the node N diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 12118dee2..45aaf463b 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -138,8 +138,14 @@ package body SC_Obligations is Has_Code : Boolean := False; -- Set True when object code for some source file in this unit is seen - PP_Info_Map : SCO_PP_Info_Maps.Map; - -- Information about preprocessing + Macro_Info_Map : SCO_PP_Info_Maps.Map; + -- Information about preprocessing wrt. macro expansions + + Include_Info_Map : SCO_PP_Info_Maps.Map; + -- Information about inclusion directive expansion, to indicate the + -- chain of inclusion for a relocated source coverage obligation. For + -- more information about this, refer to the comment of the + -- Instrument.C.Relocate_SCO subprogram. Scope_Entities : Scope_Entities_Tree := Scope_Entities_Trees.Empty_Tree; -- Scope tree, used to output e.g. subprogram metrics @@ -750,6 +756,12 @@ package body SC_Obligations is -- Remap a SCO_Id. Note: this assumes possible forward references, and -- does not rely on SCO_Map. + procedure Remap_PP_Info_Map + (Relocs : in out Checkpoint_Relocations; + Added_PP_Info : SCO_PP_Info_Maps.Map; + Real_PP_Info : in out SCO_PP_Info_Maps.Map); + -- Remap and add the contents of Added_PP_Info not in Real_PP_Info + procedure Remap_SCO_Descriptor (CP_Vectors : Source_Coverage_Vectors; Relocs : in out Checkpoint_Relocations; @@ -1248,28 +1260,71 @@ package body SC_Obligations is .SIDs_Info.Element (SCO_Fingerprint).Blocks; end Blocks; - ----------------- - -- Has_PP_Info -- - ----------------- + -------------------- + -- Has_Macro_Info -- + -------------------- - function Has_PP_Info (SCO : SCO_Id) return Boolean is + function Has_Macro_Info (SCO : SCO_Id) return Boolean is CU : constant CU_Id := Comp_Unit (SCO); begin if CU = No_CU_Id then return False; end if; - return CU_Vector.Reference (CU).Element.PP_Info_Map.Contains (SCO); - end Has_PP_Info; + return CU_Vector.Element (CU).Macro_Info_Map.Contains (SCO); + end Has_Macro_Info; - ----------------- - -- Get_PP_Info -- - ----------------- + ---------------------- + -- Has_Include_Info -- + ---------------------- + + function Has_Include_Info (SCO : SCO_Id) return Boolean is + CU : constant CU_Id := Comp_Unit (SCO); + begin + if CU = No_CU_Id then + return False; + end if; + return CU_Vector.Element (CU).Include_Info_Map.Contains (SCO); + end Has_Include_Info; + + -------------------- + -- Get_Macro_Info -- + -------------------- + + function Get_Macro_Info (SCO : SCO_Id) return PP_Info is + CU : constant CU_Id := Comp_Unit (SCO); + begin + return CU_Vector.Reference (CU).Element.Macro_Info_Map.Element (SCO); + end Get_Macro_Info; + + ---------------------- + -- Get_Include_Info -- + ---------------------- + + function Get_Include_Info (SCO : SCO_Id) return PP_Info is + CU : constant CU_Id := Comp_Unit (SCO); + begin + return CU_Vector.Reference (CU).Element.Include_Info_Map.Element (SCO); + end Get_Include_Info; + + -------------------- + -- Add_Macro_Info -- + -------------------- + + procedure Add_Macro_Info (SCO : SCO_Id; Info : PP_Info) is + CU : constant CU_Id := Comp_Unit (SCO); + begin + CU_Vector.Reference (CU).Element.Macro_Info_Map.Insert (SCO, Info); + end Add_Macro_Info; + + ---------------------- + -- Add_Include_Info -- + ---------------------- - function Get_PP_Info (SCO : SCO_Id) return PP_Info is + procedure Add_Include_Info (SCO : SCO_Id; Info : PP_Info) is CU : constant CU_Id := Comp_Unit (SCO); begin - return CU_Vector.Reference (CU).Element.PP_Info_Map.Element (SCO); - end Get_PP_Info; + CU_Vector.Reference (CU).Element.Include_Info_Map.Insert (SCO, Info); + end Add_Include_Info; ---------- -- Read -- @@ -1279,16 +1334,16 @@ package body SC_Obligations is (CLS : in out Checkpoint_Load_State; Value : out Expansion_Info) is begin - Value.Macro_Name := CLS.Read_Unbounded_String; + Value.Name := CLS.Read_Unbounded_String; Value.Sloc := CLS.Read_Source_Location; end Read; procedure Read (CLS : in out Checkpoint_Load_State; Value : out PP_Info) is - Result : PP_Info (SCO_PP_Kind'Val (CLS.Read_U8)); + Result : PP_Info; Count : Interfaces.Integer_32; begin - Result.Actual_Source_Range := CLS.Read_Local_Source_Location_Range; - Result.PP_Source_Range := CLS.Read_Local_Source_Location_Range; + Result.Actual_Source_Range := CLS.Read_Source_Location_Range; + Result.Tokens_Source_Range := CLS.Read_Source_Location_Range; Result.Expansion_Stack.Clear; Count := CLS.Read_I32; @@ -1300,15 +1355,7 @@ package body SC_Obligations is Result.Expansion_Stack.Append (EI); end; end loop; - - case Result.Kind is - when In_Expansion => - Read (CLS, Result.Definition_Loc); - - when others => - null; - end case; - + Read (CLS, Result.Definition_Loc); Value := Result; end Read; @@ -1390,7 +1437,8 @@ package body SC_Obligations is Value.Main_Source := CLS.Read_SFI; Read (CLS, Value.Deps); Value.Has_Code := CLS.Read_Boolean; - Read (CLS, Value.PP_Info_Map); + Read (CLS, Value.Macro_Info_Map); + Read (CLS, Value.Include_Info_Map); Read (CLS, Value.Scope_Entities); Read (CLS, Value.ALI_Annotations); Read (CLS, Value.SCOs); @@ -1810,32 +1858,17 @@ package body SC_Obligations is procedure Checkpoint_Load_PP_Info (CLS : in out Checkpoint_Load_State; CP_CU : in out CU_Info; - Real_CU : in out CU_Info) - is - use SCO_PP_Info_Maps; - Relocs : Checkpoint_Relocations renames CLS.Relocations; + Real_CU : in out CU_Info) is begin - for Cur in CP_CU.PP_Info_Map.Iterate loop - declare - SCO : SCO_Id := Key (Cur); - Info : PP_Info := Element (Cur); - begin - if not Real_CU.PP_Info_Map.Contains (SCO) then - if Info.Kind = In_Expansion then - for Expansion of Info.Expansion_Stack loop - Remap_SFI - (Relocs, - Expansion.Sloc.Source_File); - end loop; - Remap_SFI - (Relocs, - Info.Definition_Loc.Sloc.Source_File); - end if; - Remap_SCO_Id (Relocs, SCO); - Real_CU.PP_Info_Map.Insert (SCO, Info); - end if; - end; - end loop; + -- Remap macro information + + Remap_PP_Info_Map + (CLS.Relocations, CP_CU.Macro_Info_Map, Real_CU.Macro_Info_Map); + + -- Remap include information + + Remap_PP_Info_Map + (CLS.Relocations, CP_CU.Include_Info_Map, Real_CU.Include_Info_Map); end Checkpoint_Load_PP_Info; ---------------------------- @@ -2066,6 +2099,38 @@ package body SC_Obligations is S := Checkpoints.Remap_SCO_Id (Relocs, S); end Remap_SCO_Id; + ----------------------- + -- Remap_PP_Info_Map -- + ----------------------- + + procedure Remap_PP_Info_Map + (Relocs : in out Checkpoint_Relocations; + Added_PP_Info : SCO_PP_Info_Maps.Map; + Real_PP_Info : in out SCO_PP_Info_Maps.Map) + is + use SCO_PP_Info_Maps; + begin + for Cur in Added_PP_Info.Iterate loop + declare + Info : PP_Info := Element (Cur); + SCO : SCO_Id := Key (Cur); + begin + if not Real_PP_Info.Contains (SCO) then + for Expansion of Info.Expansion_Stack loop + Remap_SFI + (Relocs, + Expansion.Sloc.Source_File); + end loop; + Remap_SFI + (Relocs, + Info.Definition_Loc.Sloc.Source_File); + Remap_SCO_Id (Relocs, SCO); + Real_PP_Info.Insert (SCO, Info); + end if; + end; + end loop; + end Remap_PP_Info_Map; + -------------------------- -- Remap_SCO_Descriptor -- -------------------------- @@ -2628,28 +2693,19 @@ package body SC_Obligations is procedure Write (CSS : in out Checkpoint_Save_State; Value : Expansion_Info) is begin - CSS.Write (Value.Macro_Name); + CSS.Write (Value.Name); CSS.Write (Value.Sloc); end Write; procedure Write (CSS : in out Checkpoint_Save_State; Value : PP_Info) is begin - CSS.Write_U8 (SCO_PP_Kind'Pos (Value.Kind)); CSS.Write (Value.Actual_Source_Range); - CSS.Write (Value.PP_Source_Range); - + CSS.Write (Value.Tokens_Source_Range); CSS.Write_Count (Value.Expansion_Stack.Length); for EI of Value.Expansion_Stack loop Write (CSS, EI); end loop; - - case Value.Kind is - when In_Expansion => - Write (CSS, Value.Definition_Loc); - - when others => - null; - end case; + Write (CSS, Value.Definition_Loc); end Write; procedure Write (CSS : in out Checkpoint_Save_State; Value : Scope_Entity) @@ -2705,7 +2761,8 @@ package body SC_Obligations is CSS.Write_SFI (Value.Main_Source); Write (CSS, Value.Deps); CSS.Write (Value.Has_Code); - Write (CSS, Value.PP_Info_Map); + Write (CSS, Value.Macro_Info_Map); + Write (CSS, Value.Include_Info_Map); Write (CSS, Value.Scope_Entities); Write (CSS, Value.ALI_Annotations); Write (CSS, Value.SCOs); @@ -3577,8 +3634,13 @@ package body SC_Obligations is Sloc : Source_Location := First_Sloc (SCO_Vector.Reference (SCO).Sloc_Range); begin - if Has_PP_Info (SCO) then - Sloc.L := Get_PP_Info (SCO).Actual_Source_Range.First_Sloc; + -- First check if the SCO has inclusion information: if that is the + -- case, then return the inclusion source location. + + if Has_Include_Info (SCO) then + Sloc.L := Get_Include_Info (SCO).Actual_Source_Range.L.First_Sloc; + elsif Has_Macro_Info (SCO) then + Sloc.L := Get_Macro_Info (SCO).Actual_Source_Range.L.First_Sloc; end if; return Sloc; end First_Sloc; @@ -4255,8 +4317,10 @@ package body SC_Obligations is Sloc : Source_Location := Last_Sloc (SCO_Vector.Reference (SCO).Sloc_Range); begin - if Has_PP_Info (SCO) then - Sloc.L := Get_PP_Info (SCO).Actual_Source_Range.Last_Sloc; + if Has_Include_Info (SCO) then + Sloc.L := Get_Include_Info (SCO).Actual_Source_Range.L.Last_Sloc; + elsif Has_Macro_Info (SCO) then + Sloc.L := Get_Macro_Info (SCO).Actual_Source_Range.L.Last_Sloc; end if; return Sloc; end Last_Sloc; @@ -7168,16 +7232,6 @@ package body SC_Obligations is end; end Case_Insensitive_Get_Pragma_Id; - ------------------ - -- Add_PP_Info -- - ------------------ - - procedure Add_PP_Info (SCO : SCO_Id; Info : PP_Info) is - CU : constant CU_Id := Comp_Unit (SCO); - begin - CU_Vector.Reference (CU).Element.PP_Info_Map.Insert (SCO, Info); - end Add_PP_Info; - begin Snames.Initialize; end SC_Obligations; diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index cafa9da99..35eaa02fc 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -20,7 +20,6 @@ with Ada.Containers; use Ada.Containers; with Ada.Containers.Doubly_Linked_Lists; -with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Containers.Ordered_Maps; with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; @@ -940,55 +939,60 @@ package SC_Obligations is -- mechanisms to let us track and eventually report how expanded SCOs -- connect to the original sources. - type SCO_PP_Kind is (In_Expansion, No_Expansion); - type Expansion_Info is record - Macro_Name : Unbounded_String; - Sloc : Slocs.Source_Location; + Name : Unbounded_String; + Sloc : Slocs.Source_Location; end record; package Expansion_Lists is new Ada.Containers.Doubly_Linked_Lists (Element_Type => Expansion_Info); - type PP_Info (Kind : SCO_PP_Kind := No_Expansion) is record - Actual_Source_Range : Slocs.Local_Source_Location_Range; - -- Refers to the source location of a SCO in the unpreprocessed view - -- of the source file. + type PP_Info is record + Actual_Source_Range : Slocs.Source_Location_Range; + -- Refers to the source location of a SCO in the original (as opposed to + -- preprocessed) view of the source file. TODO??? remap this. - PP_Source_Range : Slocs.Local_Source_Location_Range; - -- Refer to a source location from the preprocessed version of the - -- source file, without accounting for preprocessor-inserted line - -- directives. + Tokens_Source_Range : Slocs.Source_Location_Range; + -- Source location for the tokens representing this source coverage + -- obligation. Note that this source location refers to the + -- *preprocessed* view of the file when this is a macro expansion. Expansion_Stack : Expansion_Lists.List; - -- Empty if PP_Info.Kind = No_Expansion + -- Chain of expansions - case Kind is - when In_Expansion => - Definition_Loc : Expansion_Info; - -- Location in the definition of the ultimate macro expansion + Definition_Loc : Expansion_Info; + -- Location in the macro definition / file of the ultimate + -- expansion. - when others => - null; - end case; end record; -- Preprocessing information for SCOs. Hold basic information to enhance -- the report output with more precise messages. - package SCO_PP_Info_Maps is new Ada.Containers.Indefinite_Ordered_Maps + package SCO_PP_Info_Maps is new Ada.Containers.Ordered_Maps (Key_Type => SCO_Id, Element_Type => PP_Info); - procedure Add_PP_Info (SCO : SCO_Id; Info : PP_Info) - with Pre => not Has_PP_Info (SCO); - -- Add macro expansion information for the given SCO + procedure Add_Macro_Info (SCO : SCO_Id; Info : PP_Info) + with Pre => not Has_Macro_Info (SCO); + -- Add macro expansion information for the given SCO - function Has_PP_Info (SCO : SCO_Id) return Boolean; + procedure Add_Include_Info (SCO : SCO_Id; Info : PP_Info) + with Pre => not Has_Include_Info (SCO); + -- Add inclusion expansion information for the given SCO + + function Has_Macro_Info (SCO : SCO_Id) return Boolean; + -- Return whether the given SCO comes has preprocessing information + + function Has_Include_Info (SCO : SCO_Id) return Boolean; -- Return whether the given SCO comes has preprocessing information - function Get_PP_Info (SCO : SCO_Id) return PP_Info - with Pre => Has_PP_Info (SCO); - -- Return the preprocessing information (if any) for the given SCO + function Get_Macro_Info (SCO : SCO_Id) return PP_Info + with Pre => Has_Macro_Info (SCO); + -- Return the macro expansion information (if any) for the given SCO + + function Get_Include_Info (SCO : SCO_Id) return PP_Info + with Pre => Has_Include_Info (SCO); + -- Return the macro expansion information (if any) for the given SCO function Get_Scope_Entities (CU : CU_Id) return Scope_Entities_Trees.Tree; -- Return the scope entities for the given compilation unit From 9faa060f29ae6af393fbdc49a93a40f622dee055 Mon Sep 17 00:00:00 2001 From: Matthieu Eyraud Date: Tue, 2 Sep 2025 10:31:00 +0200 Subject: [PATCH 1425/1483] Add runtime version check for C/C++ --- .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 1508 -> 1692 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2580 -> 2580 bytes .../gen/arm-elf-linux/gcvrt-pz3791e32c.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68b.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68c.ads | 2 +- .../gen/arm-elf-linux/main_1.adb | 2 +- .../gen/arm-elf-linux/main_2.adb | 2 +- .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1843 -> 1843 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1853 -> 1853 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 2438 -> 2438 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 2369 -> 2369 bytes .../gen/x86_64-windows/gcvrt-pz3791e32c.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68b.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68c.ads | 2 +- .../gen/x86_64-windows/main_1.adb | 2 +- .../gen/x86_64-windows/main_2.adb | 2 +- tools/gnatcov/instrument-ada_unit.adb | 4 ++-- tools/gnatcov/instrument-c.adb | 4 ++++ tools/gnatcov/instrument-common.ads | 22 ++++++++++++++---- tools/gnatcov/rts/gnatcov_rts.ads | 6 +++-- tools/gnatcov/rts/gnatcov_rts_c.h | 21 +++++++++++++++++ 21 files changed, 58 insertions(+), 19 deletions(-) create mode 100644 tools/gnatcov/rts/gnatcov_rts_c.h diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index 8fd2222d584f48048347816db840b63e7cb94304..f247f1c5bfe34948c51f3c8a0fbb5f4e66e7060f 100644 GIT binary patch literal 1692 zcmYk6K}b|l6o$`CPqXvPDS$f8JR%@aCKU{O8_t=DhcA`@P$DAM}=& zrXN3f8H*=Gxq7bGHWb1>Nha=H~kQ28y|S78}^7{r~!`jQaamBuGdol{yLH;$=qZ zWEM<7&zYVF1L!5w%jU0|UQ^%6hH5XH7T*Hv#mSEPp_Edr6UqVVHX?okrlBJ`IoEi| z!2}Mz0|WRGoiszU-{BewlIZ6Sm_XjR(#w6*li&>eebWaZCMYEH50zd%m_9O}qyFU#g{;?Be`xx>1ECIIyeRY%=9_Pe3JR!lwQ7@ z{skuS9Q_5EN3!0f5mD7~kk8wu%_RxVe3JX7lwLBXo%tmFM)R9Zx0+AVZ!^Esbhr5= z{Tt@zP4|OisJ~%)3miv(6L`Pa=N@zi)}4YC6mO;d>c$*o;%7=3Lw|7fJx+6ExwC-jC+uC+Qt9kT+Tu2 zPRxUR4YJN#kn=0U=lz)iIhO|2m>oKMs(#x|vw IE|CB8A3bV?w*UYD literal 1508 zcmYk6K}Z!*6o${6UgPvKX{L~n78jI=KzeUfo|=mm79kcDCT}67W>G>G1>rJUxR7We zAtDhHA`%i25)u+FTs-0t5)vUUT1Y5}M1+Wh^#5nhq6hQ7`OkmOJ$L5Lz13IFUA$J? z@v!IStw$*@Epk!>{}SNZC<`hNoykZF_ZeLGd;3q{>$y8{BPZfR^K!X-eVi33!~GFl zaW-zK%{JD?vCGvpH#9ZpvO3m5=EnKBKG#$iH|C*|U-kd}*%|$_`y@z9C~IXBc;e)z zGLm&L4ZUf43k;yQP49rdM6w5_K`%(?gB%CRU?dsvFjxf!=(C{lQ0mdQ67e>$9Pxya zbZR`5K`??p46-g^BqPwAZxQs-=Zoq{zABx3GraOBO)r4#M>2m=>7;171Qy}H*q``gAoEG)zf?Mz zFg8Po5~C+W|cKWBPg8On~XgOgolB!5A!w;V{;%~N8%kgxN%`b8z?Z@OeY z$$m@bFPr`j@_SfOMzU)0A0WpiS+}NivTl0Q^e>R#(Qk`ygRCQ2x2trrXWH{6=z@P8 zq~8lNpQOI6bkc8n0QB)aJpq|Vvfoqlhm@fN_CAI!kK}mIl}<)XkD5=?A2DT6y z^ry^!WBRT6B>ng1e=z+KY{xu(+jkl866U|G8v6>YL0tjtM&6vpBbf)e4xf~fEPw&> ziWdKD@e;_sOUh72bw7pDiest*eQLnt;8l?O@F>Xr+YKH=-5|*K`OM-ako$iXtU|mo z#c?7z53)}iSOxZh<=_L5=fV)^A%7cnr@%X2Qui2i(6b=Vg;9%7f*fxe10OZk^BSf#gn`M diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_2.trace b/testsuite/tests/U204-026-arch-mix/bin-main_2.trace index d8b3af39d1ff4dc6998caa000777e66ec0a3d3f9..a9caab5e1f2f925be89da963facd660afc6f031c 100644 GIT binary patch delta 69 zcmbOtGDT#994jX)53l4zWo1KCBX$M`24NsJGB7gLHL%n*FjX)#vNANbGBRc00E%-1 Uv4WwYfvJVDg@L)*#`3wG0D_nchyVZp delta 69 zcmbOtGDT#994m(yuQm5XWo1JX6Ltm$24NsJGB7gLHL%b%GEy)!wlcM}GBjl10E%-1 Uv4WAMshN?9frX{<#`3wG0FOHh#{d8T diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads index 59a1337ec..1c808ade0 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz3791e32c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads index faa4d9e4d..927e8b086 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68b is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads index 5e6ce0228..870f9ae12 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb index d7ef728a8..656f51403 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=8,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=9,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); GCVRT.DB_z794ac68b.Dump_Buffers;end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb index 4bbc2b311..285a40eb7 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=8,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=9,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); GCVRT.DB_z794ac68c.Dump_Buffers;end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt index 9901e7fd477f30415d1ef08e34dfdf9797b67e0d..7a5b106c09fde92a5f8bbca9cfade34871dcb8fa 100644 GIT binary patch delta 70 zcmdnYx0!E4Eeqqn$#pEcOe~C>*RpgmvUlixZn^%wcd{MZMHNe315*V<6DvbwDvq=ut diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index 6ec661f68cf6eb5a8e8832d5ff555ec089b076aa..91cb77a1af470cecd50fa5dc1ec3409cbab51476 100644 GIT binary patch delta 56 zcmdnXx0i2&JsW#R^t~t7zxPgdW4o+kscT@WU}$1xXl!L6&LPhsmg~g-v-cz;0|SEq5F4548I&t%7#SFu8dw^bOrFN^0RZpP3i$v4 delta 43 xcmZn@ZWG>6&LRJ0LW-N}rp}X$3=9kcKx|~DXHc%7VPs%rYG7exIC&b!2LKt03?l#l diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt index 8e8e44f2abfcf90e59d28d42c34b882d958227de..9c70eb507e891065698eed77c43705d32a6a2835 100644 GIT binary patch delta 19 bcmX>obWmtRJ_q}O*l@?|-+L#QahwJKQl|*P delta 19 bcmX>obWmtRJ_ozR2c8=>8#^bLahwJKPYnoD diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads index 3e54dc4f9..03f085d72 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz3791e32c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads index c37eb3685..08e30c044 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68b is diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads index a41ab39aa..235f1a41a 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb index c7f0007ae..2506d1b0c 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=8,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=9,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is GNATcov_Dump_Object:GCVRT.DB_z794ac68b.Dump_Controlled_Type;begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb index 0480a5e96..7feb3b7a6 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=8,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=9,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is GNATcov_Dump_Object:GCVRT.DB_z794ac68c.Dump_Controlled_Type;begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); end Main_2; diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 45aead92f..54190886f 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -9577,7 +9577,7 @@ package body Instrument.Ada_Unit is Runtime_Version_Check_Node : constant Node_Rewriting_Handle := Create_From_Template (RH, - Template => To_Wide_Wide_String (Runtime_Version_Check), + Template => To_Wide_Wide_String (Ada_Runtime_Version_Check), Arguments => (1 .. 0 => No_Node_Rewriting_Handle), Rule => Pragma_Rule); @@ -10707,7 +10707,7 @@ package body Instrument.Ada_Unit is File.Put_Line ("with GNATcov_RTS;"); File.Put_Line ("with GNATcov_RTS.Buffers;"); - File.Put_Line (Runtime_Version_Check); + File.Put_Line (Ada_Runtime_Version_Check); File.New_Line; File.Put_Line ("package " & Pkg_Name & " is"); diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index a6a4f848d..2ff0da0c1 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -4355,7 +4355,9 @@ package body Instrument.C is Create_File (Prj, File, +CU_Name.Filename); + File.Put_Line ("#include ""gnatcov_rts_c.h"""); File.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); + File.Put_Line (C_Runtime_Version_Check); File.New_Line; -- Define coverage buffers for each source file: @@ -4617,8 +4619,10 @@ package body Instrument.C is Create_File (Prj, File, Filename); + File.Put_Line ("#include ""gnatcov_rts_c.h"""); File.Put_Line ("#include ""gnatcov_rts_c-strings.h"""); File.Put_Line ("#include ""gnatcov_rts_c-buffers.h"""); + File.Put_Line (C_Runtime_Version_Check); case Dump_Config.Channel is when Binary_File => diff --git a/tools/gnatcov/instrument-common.ads b/tools/gnatcov/instrument-common.ads index 4361d6cc4..345588cd7 100644 --- a/tools/gnatcov/instrument-common.ads +++ b/tools/gnatcov/instrument-common.ads @@ -397,12 +397,24 @@ package Instrument.Common is function Img (Bit : Any_Bit_Id) return String is (Strings.Img (Integer (Bit))); - Runtime_Version_Check : constant String := - "pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, " - & """Incompatible GNATcov_RTS version, please use" + Runtime_Version : constant Natural := 9; + Runtime_Error : constant String := + "Incompatible GNATcov_RTS version, please use" & " the GNATcov_RTS project provided with your" - & " GNATcoverage distribution."");"; - -- Check to be inserted in Ada units generated by the instrumenter to + & " GNATcoverage distribution."; + -- Must be up-to-date with GNATcov_RTS.Version + + Ada_Runtime_Version_Check : constant String := + "pragma Compile_Time_Error (GNATcov_RTS.Version /= " + & Img (Runtime_Version) & " ,""" & Runtime_Error & """);"; + C_Runtime_Version_Check : constant String := + "#if GNATCOV_RTS_VERSION != " + & Img (Runtime_Version) + & ASCII.LF + & "#error """ & Runtime_Error & """" + & ASCII.LF + & "#endif"; + -- Check to be inserted in Ada / C units generated by the instrumenter to -- verify that they are built with the version of GNATcov_RTS the -- instrumenter expects. -- diff --git a/tools/gnatcov/rts/gnatcov_rts.ads b/tools/gnatcov/rts/gnatcov_rts.ads index 2c8e5bf37..e2d83517c 100644 --- a/tools/gnatcov/rts/gnatcov_rts.ads +++ b/tools/gnatcov/rts/gnatcov_rts.ads @@ -42,9 +42,10 @@ package GNATcov_RTS is pragma Warnings (Off, Std); pragma Warnings (Off, Sys); - Version : constant := 8; + Version : constant := 9; -- For compatibility with the GNATcoverage in use, GNATcov_RTS is - -- versioned. + -- versioned. When updating the runtime version, also update it in + -- gnatcov_rts_c.h, and in the Instrument.Common unit. -- -- 1 -- initial runtime version -- 2 -- extend trace entry model to account for C files @@ -55,5 +56,6 @@ package GNATcov_RTS is -- 6 -- buffer clear mechanism and trace filename indices -- 7 -- enable inlining of witness subprograms -- 8 -- introduce fingerprints for annotations + -- 9 -- add versioning for C sources end GNATcov_RTS; diff --git a/tools/gnatcov/rts/gnatcov_rts_c.h b/tools/gnatcov/rts/gnatcov_rts_c.h new file mode 100644 index 000000000..9802afd4f --- /dev/null +++ b/tools/gnatcov/rts/gnatcov_rts_c.h @@ -0,0 +1,21 @@ +/**************************************************************************** + * * + * GNATcoverage Instrumentation Runtime * + * * + * Copyright (C) 2025, 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. * + * * + ****************************************************************************/ + +#define GNATCOV_RTS_VERSION 9 +// See comment in gnatcov_rts.ads From 554726008c4656c440d6076fe3088d4ceaf465bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 8 Sep 2025 10:00:11 +0200 Subject: [PATCH 1426/1483] Deduplicate the gnatcov_rts.ads source It contains among other things the current runtime version, and was until now duplicated between the regular runtime and the Ada only version. To avoid forgetting to update one file and not the other in the future, only keep the one from the regular runtime and copy it when installing gnatcov. --- tools/gnatcov/Makefile | 3 ++ tools/gnatcov/ada-rts/gnatcov_rts.ads | 56 --------------------------- 2 files changed, 3 insertions(+), 56 deletions(-) delete mode 100644 tools/gnatcov/ada-rts/gnatcov_rts.ads diff --git a/tools/gnatcov/Makefile b/tools/gnatcov/Makefile index 8a00a2b75..49eecb466 100644 --- a/tools/gnatcov/Makefile +++ b/tools/gnatcov/Makefile @@ -263,6 +263,9 @@ install-gnatcov_rts: $(PREFIX)/share/$(DIRNAME)/gnatcov_rts $(CP) -r ada-rts/*.gpr ada-rts/*.ads ada-rts/*.adb \ $(PREFIX)/share/$(DIRNAME)/gnatcov_ada_rts + # Copy gnatcov_rts.ads from the regular runtime to the Ada only one to make + # sure we keep the runtime versions in sync + $(CP) rts/gnatcov_rts.ads $(PREFIX)/share/$(DIRNAME)/gnatcov_ada_rts # Create library/object directories for gnatcov_rts in the installed tree. # This is necessary for out-of-tree builds of gnatcov_rts to work, as # gnatcov_rts may be read-only after final installation, and gprbuild diff --git a/tools/gnatcov/ada-rts/gnatcov_rts.ads b/tools/gnatcov/ada-rts/gnatcov_rts.ads deleted file mode 100644 index ca00975fe..000000000 --- a/tools/gnatcov/ada-rts/gnatcov_rts.ads +++ /dev/null @@ -1,56 +0,0 @@ ------------------------------------------------------------------------------- --- -- --- GNATcoverage Instrumentation Runtime -- --- -- --- Copyright (C) 2019-2021, 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. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- . -- --- -- ------------------------------------------------------------------------------- - --- Namespace for all support packages required to do instrumentation-based --- coverage computation in GNATcoverage. - --- This unit needs to be compilable with Ada 95 compilers - -with System; - -package GNATcov_RTS is - - pragma Pure; - pragma Warnings (Off); - pragma No_Elaboration_Code_All; - pragma Warnings (On); - - package Std renames Standard; - package Sys renames System; - - Version : constant := 8; - -- For compatibility with the GNATcoverage in use, GNATcov_RTS is - -- versioned. - -- - -- 1 -- initial runtime version - -- 2 -- extend trace entry model to account for C files - -- 3 -- add a renaming of the Standard and System packages in GNATcov_RTS - -- 4 -- add C witness functions / buffer types - -- 5 -- add a non-volatile version of the Witness_Dummy_Type and - -- the associated Witness function. - -- 6 -- buffer clear mechanism and trace filename indices - -- 7 -- enable inlining of witness subprograms - -- 8 -- introduce fingerprint for annotations - -end GNATcov_RTS; From 7d6eedb168a6acb7769e290348d5582569847727 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 21 Aug 2025 17:35:55 +0200 Subject: [PATCH 1427/1483] doc: Add documentation for rust coverage analysis --- doc/gnatcov/cov_rust.rst | 115 +++++++++++++++++++++++++++++++++++ doc/gnatcov/gnatcov_part.rst | 1 + 2 files changed, 116 insertions(+) create mode 100644 doc/gnatcov/cov_rust.rst diff --git a/doc/gnatcov/cov_rust.rst b/doc/gnatcov/cov_rust.rst new file mode 100644 index 000000000..8bba0e62d --- /dev/null +++ b/doc/gnatcov/cov_rust.rst @@ -0,0 +1,115 @@ +.. _rust_cov: + +************************************ +Rust coverage analysis with |gcvcov| +************************************ + +Source coverage analysis for the Rust language is an unstable feature of +|gcv|. It relies on the internal coverage instrumentation of the rustc +compiler, which is itself leaning on the code coverage framework of the +LLVM project. + +.. note:: + This feature is made to be compatible with the **GNATPro For Rust** + tool suite, compatibility with other rust toolchains is not guaranteed. + +.. _rust_cov_workflow: + +Rust coverage workflow +====================== + +The workflow consists in 3 steps. First, build the program while instrumenting +it for coverage analysis. The instrumentation is delegated to ``rustc``. +Then, run the program, which produces trace files. Finally, use |gcvcov| to +generate a coverage report. + +.. _rust_cov_workflow_1: + +Instrument and build the project +-------------------------------- + +Unlike source coverage analysis for Ada, C and C++ which rely on |gcv| to +instrument the source code *before* compiling it, the Rust workflow delegates +instrumentation to the ``rustc`` compiler. + +To instrument the code, pass the :cmd-option:`-Cinstrument-coverage` argument +to the compiler. If instrumenting for the ``stmt+decision`` or ``stmt+mcdc`` +coverage levels, pass the :cmd-option:`-Ccoverage-options=mcdc` additionally. + +Decision coverage as defined by |gcv| does not exist in the rust compiler, +thus |gcv| will infer the decision coverage from MC/DC coverage. + +The example showcases using the ``Cargo`` build system to instrument a project +for ``stmt+mcdc`` analysis analysis. + +:: + + RUSTFLAGS="-Cinstrument-coverage -Ccoverage-options=mcdc" cargo build + +.. _rust_cov_workflow_2: + +Run the executed binary +----------------------- + +Once again, the example showcases running the compiled program through +``Cargo``. At the end of execution, a trace file ending with ``.profraw`` is +created. + +The name of the file can be customized with the ``LLVM_PROFILE_FILE`` +environment variable. +See `LLVM_PROFILE_FILE format `_. + +:: + + LLVM_PROFILE_FILE="trace-%p.profraw" cargo run -- ARGS... + +The program may be run several times with different inputs to improve final +coverage. + +.. _rust_cov_workflow_3: + +Produce a coverage report +------------------------- + +To produce the coverage analysis from the obtained ``.profraw`` files, proceed +as follow: + +:: + + gnatcov coverage --level=stmt+mcdc -a xcov --exec EXEC_BIN PROFRAW_FILES... + +The important part is that the program binary needs to be passed with the +:cmd-option:`--exec` argument. In a ``Cargo`` project, the binary usually lives +under ``target/debug`` or ``target/release``. + +Note that aside of producing a report, the rust coverage report can be saved +as a :ref:`checkpoint` and reused for consolidation. + +.. _rust_cov_limitations: + +Rust coverage limitations +========================= + +This feature being relatively new, there are known limitations that we shall +mention hereafter. + +MC/DC false-negatives related to instrumentation level +-------------------------------------------------------- + +While the |gcvins| workflow controls and tracks the instrumentation level +of artifacts, making it possible to raise an error when trying to perform +MC/DC analysis on an artifact that was not instrumented for MC/DC, the Rust +workflow does not have such a safety feature yet. + +It means that if the project is instrumented without MC/DC support, and +the analysis is done with :cmd-option:`--level=stmt+mcdc`, no MC/DC violation +will be raised, even though there could have been some if the program had been +instrumented adequately. + +Approximative source location ranges +------------------------------------ + +Currently, you may witness that some SCOs have a source location range that +can overlap or merge with its neighbours. This is due to bugs in the +compiler's instrumentation logic and will be fixed in coming releases. diff --git a/doc/gnatcov/gnatcov_part.rst b/doc/gnatcov/gnatcov_part.rst index 51edc9dc9..1f55498ba 100644 --- a/doc/gnatcov/gnatcov_part.rst +++ b/doc/gnatcov/gnatcov_part.rst @@ -10,6 +10,7 @@ GNATcoverage User's Guide src_traces integrated_instr cov_source + cov_rust consolidation exemptions disable_cov From 5780b3b3af6324b46e5fb0e67d10eb967df36b0e Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 29 Aug 2025 16:17:18 +0200 Subject: [PATCH 1428/1483] doc(rust): Add a paragraph for unsupported constructs --- doc/gnatcov/cov_rust.rst | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/doc/gnatcov/cov_rust.rst b/doc/gnatcov/cov_rust.rst index 8bba0e62d..b010b45f4 100644 --- a/doc/gnatcov/cov_rust.rst +++ b/doc/gnatcov/cov_rust.rst @@ -113,3 +113,15 @@ Approximative source location ranges Currently, you may witness that some SCOs have a source location range that can overlap or merge with its neighbours. This is due to bugs in the compiler's instrumentation logic and will be fixed in coming releases. + +Unsupported constructs +---------------------- + +Some constructs are not yet supported: + +- MC/DC instrumentation of pattern matching. Pattern matching can be viewed + as a decision with multiple conditions. However, it can lead to more than + just 2 outcomes. + +- Rust ``macros by example`` and procedural macros are not yet instrumented. + From 6e431ae36f727c29e582857c6579819786051080 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Fri, 29 Aug 2025 16:16:52 +0200 Subject: [PATCH 1429/1483] examples: Add a doc example for rust coverage --- doc/gnatcov/cov_rust.rst | 3 ++ .../gnatcov/examples/doc/rust_cov/.gitignore | 3 ++ .../gnatcov/examples/doc/rust_cov/Cargo.lock | 7 ++++ .../gnatcov/examples/doc/rust_cov/Cargo.toml | 6 ++++ tools/gnatcov/examples/doc/rust_cov/Makefile | 34 +++++++++++++++++++ tools/gnatcov/examples/doc/rust_cov/README.md | 10 ++++++ .../gnatcov/examples/doc/rust_cov/src/main.rs | 11 ++++++ 7 files changed, 74 insertions(+) create mode 100644 tools/gnatcov/examples/doc/rust_cov/.gitignore create mode 100644 tools/gnatcov/examples/doc/rust_cov/Cargo.lock create mode 100644 tools/gnatcov/examples/doc/rust_cov/Cargo.toml create mode 100644 tools/gnatcov/examples/doc/rust_cov/Makefile create mode 100644 tools/gnatcov/examples/doc/rust_cov/README.md create mode 100644 tools/gnatcov/examples/doc/rust_cov/src/main.rs diff --git a/doc/gnatcov/cov_rust.rst b/doc/gnatcov/cov_rust.rst index b010b45f4..7e3122461 100644 --- a/doc/gnatcov/cov_rust.rst +++ b/doc/gnatcov/cov_rust.rst @@ -23,6 +23,9 @@ it for coverage analysis. The instrumentation is delegated to ``rustc``. Then, run the program, which produces trace files. Finally, use |gcvcov| to generate a coverage report. +An example project demonstrating Rust instrumentation can be found at +``share/examples/gnatcoverage/doc/rust_cov``. + .. _rust_cov_workflow_1: Instrument and build the project diff --git a/tools/gnatcov/examples/doc/rust_cov/.gitignore b/tools/gnatcov/examples/doc/rust_cov/.gitignore new file mode 100644 index 000000000..f1a2da67d --- /dev/null +++ b/tools/gnatcov/examples/doc/rust_cov/.gitignore @@ -0,0 +1,3 @@ +target/ +stats/ +*.profraw diff --git a/tools/gnatcov/examples/doc/rust_cov/Cargo.lock b/tools/gnatcov/examples/doc/rust_cov/Cargo.lock new file mode 100644 index 000000000..9be6a6d86 --- /dev/null +++ b/tools/gnatcov/examples/doc/rust_cov/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "rust_cov" +version = "0.1.0" diff --git a/tools/gnatcov/examples/doc/rust_cov/Cargo.toml b/tools/gnatcov/examples/doc/rust_cov/Cargo.toml new file mode 100644 index 000000000..d0842d236 --- /dev/null +++ b/tools/gnatcov/examples/doc/rust_cov/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "rust_cov" +version = "0.1.0" +edition = "2024" + +[dependencies] diff --git a/tools/gnatcov/examples/doc/rust_cov/Makefile b/tools/gnatcov/examples/doc/rust_cov/Makefile new file mode 100644 index 000000000..e021b3e08 --- /dev/null +++ b/tools/gnatcov/examples/doc/rust_cov/Makefile @@ -0,0 +1,34 @@ +RUSTFLAGS=-Cinstrument-coverage + +ifeq (${DEBUG}, 1) +PROFILE=debug +else +PROFILE=release +endif + +ifeq (${MCDC}, 1) +EXTRA_RUSTFLAGS=-Ccoverage-options=mcdc +LEVEL=stmt+mcdc +else +LEVEL=stmt +endif + +PROFRAW=trace.profraw + +.PHONY: build run coverage clean + +default: coverage + +build: + RUSTFLAGS="${RUSTFLAGS} ${EXTRA_RUSTFLAGS}" cargo build --${PROFILE} + +run: build + LLVM_PROFILE_FILE=${PROFRAW} target/${PROFILE}/rust_cov + +coverage: run + gnatcov coverage --level=${LEVEL} -areport --exec target/${PROFILE}/rust_cov ${PROFRAW} + +clean: + ${RM} ${PROFRAW} + ${RM} -r stats + cargo clean diff --git a/tools/gnatcov/examples/doc/rust_cov/README.md b/tools/gnatcov/examples/doc/rust_cov/README.md new file mode 100644 index 000000000..41fccbe87 --- /dev/null +++ b/tools/gnatcov/examples/doc/rust_cov/README.md @@ -0,0 +1,10 @@ +This example showcases the coverage of Rust programs. + +To run the whole example, just run `make`. It will compile the project with +instrumentation, run the executable, and create a gnatcoverage report from the +generated trace file. + +Additionally, variables can be passed to `make`: + +- `make MCDC=1`: Enable MC/DC coverage (is simple statement coverage otherwise) +- `make DEBUG=1`: Enable debug build diff --git a/tools/gnatcov/examples/doc/rust_cov/src/main.rs b/tools/gnatcov/examples/doc/rust_cov/src/main.rs new file mode 100644 index 000000000..445309209 --- /dev/null +++ b/tools/gnatcov/examples/doc/rust_cov/src/main.rs @@ -0,0 +1,11 @@ +fn foo(a: bool, b: bool, c: bool) { + if a && b && c { + println!("A and B and C is TRUE") + } +} + +fn main() { + println!("Hello, world!"); + foo(true, true, true); + foo(false, true, true); +} From 025aa4da5795caf9c8e2d19bdea4a753ba174b28 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Mon, 1 Sep 2025 15:33:14 +0200 Subject: [PATCH 1430/1483] tests: Ensure that conflicting packages outside of closure are not problematic --- .../385-same_pkg_different_files/foo.ads | 8 +++++ .../385-same_pkg_different_files/main.adb | 7 +++++ .../385-same_pkg_different_files/pkg.adb | 8 +++++ .../385-same_pkg_different_files/pkg.ads | 5 ++++ .../385-same_pkg_different_files/test.opt | 1 + .../385-same_pkg_different_files/test.py | 30 +++++++++++++++++++ 6 files changed, 59 insertions(+) create mode 100644 testsuite/tests/385-same_pkg_different_files/foo.ads create mode 100644 testsuite/tests/385-same_pkg_different_files/main.adb create mode 100644 testsuite/tests/385-same_pkg_different_files/pkg.adb create mode 100644 testsuite/tests/385-same_pkg_different_files/pkg.ads create mode 100644 testsuite/tests/385-same_pkg_different_files/test.opt create mode 100644 testsuite/tests/385-same_pkg_different_files/test.py diff --git a/testsuite/tests/385-same_pkg_different_files/foo.ads b/testsuite/tests/385-same_pkg_different_files/foo.ads new file mode 100644 index 000000000..088c56c23 --- /dev/null +++ b/testsuite/tests/385-same_pkg_different_files/foo.ads @@ -0,0 +1,8 @@ +package Pkg is + + -- Extra feature to ensure the file is not instrumented or compiled: we use + -- an expression function, which is Ada2012. + + function Bar (X : Integer) return Integer is (if X > 0 then X else X); + +end Pkg; diff --git a/testsuite/tests/385-same_pkg_different_files/main.adb b/testsuite/tests/385-same_pkg_different_files/main.adb new file mode 100644 index 000000000..c44a7c435 --- /dev/null +++ b/testsuite/tests/385-same_pkg_different_files/main.adb @@ -0,0 +1,7 @@ +with Pkg; + +procedure Main is + I : constant Integer := Pkg.Ident (2); +begin + null; +end Main; diff --git a/testsuite/tests/385-same_pkg_different_files/pkg.adb b/testsuite/tests/385-same_pkg_different_files/pkg.adb new file mode 100644 index 000000000..7a73f74bb --- /dev/null +++ b/testsuite/tests/385-same_pkg_different_files/pkg.adb @@ -0,0 +1,8 @@ +package body Pkg is + + function Ident (X : Integer) return Integer is + begin + return X; + end Ident; + +end Pkg; diff --git a/testsuite/tests/385-same_pkg_different_files/pkg.ads b/testsuite/tests/385-same_pkg_different_files/pkg.ads new file mode 100644 index 000000000..9ff0e430a --- /dev/null +++ b/testsuite/tests/385-same_pkg_different_files/pkg.ads @@ -0,0 +1,5 @@ +package Pkg is + + function Ident (X : Integer) return Integer; + +end Pkg; diff --git a/testsuite/tests/385-same_pkg_different_files/test.opt b/testsuite/tests/385-same_pkg_different_files/test.opt new file mode 100644 index 000000000..40a7e7cb0 --- /dev/null +++ b/testsuite/tests/385-same_pkg_different_files/test.opt @@ -0,0 +1 @@ +!src-traces DEAD diff --git a/testsuite/tests/385-same_pkg_different_files/test.py b/testsuite/tests/385-same_pkg_different_files/test.py new file mode 100644 index 000000000..8a66b469e --- /dev/null +++ b/testsuite/tests/385-same_pkg_different_files/test.py @@ -0,0 +1,30 @@ +""" +foo.ads declares the same package as pkg.ads but with a different interface. It +is not used and probably an error in the clients' code, but it does not disturb +non-instrumented builds, so it shall not disturb instrumented builds either. +""" + +from SCOV.minicheck import build_and_run +from SUITE.context import thistest +from SUITE.cutils import Wdir +from SUITE.gprutils import GPRswitches +from SUITE.tutils import gprfor + + +tmp = Wdir("tmp_") + +gpr = gprfor( + mains=["main.adb"], + srcdirs=[".."], +) + +cov_args = build_and_run( + gprsw=GPRswitches(root_project=gpr), + covlevel="stmt", + mains=["main"], + extra_coverage_args=[], + tolerate_instrument_messages=r"warning: unit name \"PKG\" does not match" + " source name.*", +) + +thistest.result() From bd94d641e2da935a9944cf3b36bd172136f8f599 Mon Sep 17 00:00:00 2001 From: Tonu Naks Date: Wed, 10 Jan 2024 12:09:38 +0000 Subject: [PATCH 1431/1483] Revive pre-qm TOR scripts eng/das/cov/gnatcoverage#203 --- qualification/tor/scripts/Makefile | 130 ++ qualification/tor/scripts/conf.py | 216 +++ qualification/tor/scripts/genrest.py | 1472 +++++++++++++++++ qualification/tor/scripts/rest.py | 99 ++ .../tor/scripts/theme/static/gnatpython.css_t | 239 +++ qualification/tor/scripts/theme/theme.conf | 4 + 6 files changed, 2160 insertions(+) create mode 100644 qualification/tor/scripts/Makefile create mode 100644 qualification/tor/scripts/conf.py create mode 100755 qualification/tor/scripts/genrest.py create mode 100644 qualification/tor/scripts/rest.py create mode 100644 qualification/tor/scripts/theme/static/gnatpython.css_t create mode 100644 qualification/tor/scripts/theme/theme.conf diff --git a/qualification/tor/scripts/Makefile b/qualification/tor/scripts/Makefile new file mode 100644 index 000000000..34b8c9e07 --- /dev/null +++ b/qualification/tor/scripts/Makefile @@ -0,0 +1,130 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = -c . +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* source/*.rst + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Couverture.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Couverture.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Couverture" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Couverture" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latexpdf + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/latexpdf all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/qualification/tor/scripts/conf.py b/qualification/tor/scripts/conf.py new file mode 100644 index 000000000..9169ea24f --- /dev/null +++ b/qualification/tor/scripts/conf.py @@ -0,0 +1,216 @@ +# -*- coding: utf-8 -*- +# +# Couverture documentation build configuration file, created by +# sphinx-quickstart on Fri Nov 19 14:56:55 2010. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.insert(0, os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = [] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'GNATcoverage' +copyright = u'2011, AdaCore' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '1.0' +# The full version, including alpha/beta/rc tags. +release = '1.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +html_theme_path = ['.'] + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +html_title = "%s TORs" % project + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = 'source/_static/intranet_branding.png' + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_domain_indices = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'GNATcoveragedoc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'GNATcoverage.tex', u'GNATcoverage Documentation', + u'AdaCore', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'couverture', u'GNATcoverage Documentation', + [u'AdaCore'], 1) +] diff --git a/qualification/tor/scripts/genrest.py b/qualification/tor/scripts/genrest.py new file mode 100755 index 000000000..f843d4455 --- /dev/null +++ b/qualification/tor/scripts/genrest.py @@ -0,0 +1,1472 @@ +#!/usr/bin/env python + +import os +import rest +import glob +import re +import sys +import json +import optparse + +from gnatpython.fileutils import mkdir + +# ***************************************************************************** +# ** GENERAL DESCRIPTION ** +# ***************************************************************************** + +# This file implements the core of the GNATcoverage TOR document production, +# generating sphinx-REST from artifacts held within our testsuite/Qualif +# filesystem tree. + +# Except on rare occasions, each directory in this tree represents some TOR +# related entity: requirement, testcase, appendix material, or groups of such, +# possibly nested (groups may hold direct artifacts or further intermediate +# groups). +# +# The general structure is very hierarchical, going from requirement +# groups (REQG kind) to requirements (REQ kind), to testcases (TC kind) +# possibly via testcase groups (TCG kind). +# +# Very roughly, our processing here first constructs an internal tree +# datastructure representing the directory tree, where each node holds +# attributes qualifying its nature (e.g. "this node/directory holds a +# testcase"). This is determined from two elements: +# +# * The presence in the directory of some text file: +# - tc.txt for a testcase, +# - req.txt for a requirement, +# - set.txt for a group +# +# * For groups, the node is further qualified by looking at the set of +# children of the node. Despite the possibility to nest groups within +# groups, mixing a testcase artifacts at the same level as requirement +# artifacts is disallowed. + +# Relative to where this script reside, path to ... + +# The root of the directory tree mapping qualification artifacts +# (requirements, testcases, ...): + +RST_ROOTDIR = "source" + +# The root of the directory where the REST documents describing +# these artifacts will reside: + +ART_ROOTDIR = "../../../testsuite/Qualif" + +# ********************** +# ** Helper functions ** +# ********************** + +def get_content(filename): + """Return contents of file FILENAME as a string""" + + fd = open(filename, 'r') + content = fd.read() + fd.close() + return content + +def copy(l): + """Return a copy of list L""" + return [item for item in l] + +def to_title(str): + """Given an entity name return a suitable string to be insterted + in the documentation""" + m = re.search(r'^[0-9]+_(.*)$', str) + if m is not None: + str = m.group(1) + return str.replace('_', ' ') + +def header(str, pre_skip, post_skip): + """Return the string to be used as a section header for STR, + framed with PRE_SKIP new_lines before and POST_SKIP new_lines after""" + return '\n' * pre_skip + str + '\n' * post_skip + +def sec_header(str): + """Return a Section header text to be used for section title STR""" + return header(rest.strong(str), pre_skip=2, post_skip=2) + +def subsec_header(str): + """Return a Subsection header text to be used for subsection title STR""" + return header(rest.emphasis(str), pre_skip=2, post_skip=2) + +def warn(text): + print "warning: %s" % text + +def warn_if(cond, text): + if cond: warn(text) + +def exit_if (p, msg): + if p: + print msg + sys.exit(1) + +# ************************** +# ** TestCase abstraction ** +# ************************** + +# Helper for the Directory abstraction, to encapsulate research of driver +# and functional source file sets + +class TestCase: + def __init__(self, dir, dgen): + self.dir = dir + self.dgen = dgen + + self.fnsources = None + self.drsources = None + self.find_sources() + + def parent_globbing(self, dir, pattern, include_start_dir=True): + """Look for src/[pattern] files in dir and its parents directory + up to document root directory""" + head = os.path.relpath(dir, self.dgen.art_rootdir) + tail = '' + if not include_start_dir: + head, tail = os.path.split(head) + files = set([]) + while len(head) > 0: + files |= set( + glob.glob( + os.path.join(self.dgen.art_rootdir, head, 'src', pattern)) + ) + head, tail = os.path.split(head) + return files + + def find_with_clauses(self, dir, sourcefile): + content = get_content(sourcefile) + # Remove all comments + content = '\n'.join([k for k in content.splitlines() \ + if not re.match('\s*--', k)]) + + # Find all the with clauses + matches = re.findall(r'(?:\n|;|^)\s*with\s*([^;]+)\s*;', content, re.S) + matches = [k.replace(' ', '') for k in matches] + matches = [k.replace('.', '-') for k in matches] + + result = [] + [result.extend (m.lower().split(',')) for m in matches] + result = set(result) + + # Remove packages we don't care about and probably could locate + result -= set(['support', 'system']) + + file_list = set([]) + for item in result: + + spec = self.parent_globbing(dir, item + '.ads', True) + warn_if (len(spec) > 1, 'multiple specs for unit "%s"' % item) + file_list |= spec + + body = self.parent_globbing(dir, item + '.adb', True) + warn_if (len(body) > 1, 'multiple bodies for unit "%s"' % item) + file_list |= body + + warn_if (len(body | spec) == 0, + 'no body or spec source found for unit "%s" (from %s)' + % (item, sourcefile)) + + return file_list + + def find_closure(self, dir, sourcefile): + """Given an Ada source file find it's closure. Not that we ignore the + support package""" + + result_set = self.find_with_clauses(dir, sourcefile) + + current_size = len(result_set) + previous_size = 0 + while current_size > previous_size: + + previous_size = current_size + tmp = set([]) + for item in result_set: + tmp |= self.find_with_clauses(dir, item) + + result_set |= tmp + current_size = len(result_set) + + return result_set + + def find_sources(self): + """Locate the functional and driver sources of testcase SELF""" + + # Seek the test drivers first, and infer closure from there. Then + # append consolidation specs to the set of drivers. We will typically + # end up on common functional units from drivers, so use sets to + # prevent dupicates. + + # Test drivers: search the local "src" subdir first, walk uptree + # if no driver there. + + local_sources = set( + glob.glob(os.path.join(self.dir, 'src', '*.ad[sb]'))) + + self.drsources = set( + [k for k in local_sources + if os.path.basename(k).startswith('test_')]) + + if len(self.drsources) == 0: + data_names = set( + [os.path.basename(k).split('.')[0] for k in local_sources]) + [self.drsources.update( + self.parent_globbing(self.dir, 'test_'+name+'*.ad[sb]')) + for name in data_names] + + warn_if (len(self.drsources) == 0, + 'no driver source for testcase in %s' % self.dir) + + # Driver Closure: + + self.fnsources = set([]) + [self.fnsources.update(self.find_closure(self.dir, driver)) + for driver in self.drsources] + + warn_if (len(self.fnsources) == 0, + 'no functional source for testcase in %s' % self.dir) + + # Consolidation specs. These are always local. + + self.conspecs = set([]) + self.conspecs |= set( + glob.glob(os.path.join(self.dir, 'src', 'cons_*.txt'))) + +# *************************** +# ** Path Info abstraction ** +# *************************** + +class PathInfo: + """Holds info about the path to the current node when walking + a directory tree""" + + def __init__(self): + self.n_req = 0 # Number of requirement expressions so far + self.n_tc = 0 # Number of tc nodes so far + self.depth = 0 # Depth of this node wrt root of walk operation + +# ************************** +# ** Node Set abstraction ** +# ************************** + +class NodeSet: + + """Node Set abstraction, used to compute composite attributes + for a set of nodes. We compute two categories of composite attributes: + + * The "some_" attributes tell whether some (at least one) node in set has + such or such characteristic. These are updated as nodes are added to the + set, via the "register_one" method. + + * The "all_" attributes tell whether all the nodes in the set has such or + such characteristic. These are computed from the current "some_" values + when the "sync" method is called, + """ + + def __init__(self, diros=()): + """Initialize the some_ attributes for SELF, then register + each directory object in the DIROS sequence and sync() to update + the all_ attributes from there.""" + + self.some_reqgroup = False + self.some_notreqgroup = False + self.some_tcgroup = False + self.some_nottcgroup = False + self.some_appmat = False + self.some_notappmat = False + + self.some_reqorset = False + self.some_notreqorset = False + self.some_tcorset = False + self.some_nottcorset = False + + self.some_reqorgroup = False + self.some_notreqorgroup = False + self.some_tcorgroup = False + self.some_nottcorgroup = False + + self.some_req = False + self.some_notreq = False + self.some_tc = False + self.some_nottc = False + self.some_app = False + self.some_notapp = False + self.some_set = False + self.some_notset = False + + self.some_notreqset = False + self.some_nottcset = False + self.some_notappset = False + + self.diros = [] + + [self.register_one (diro) for diro in diros] + self.sync() + + def register_one (self, diro): + """Add one directory object to this set, updating the + some_ attributes accordingly.""" + + self.some_req |= diro.req + self.some_tc |= diro.tc + self.some_set |= diro.set + self.some_app |= diro.app + + self.some_notreq |= not diro.req + self.some_nottc |= not diro.tc + self.some_notset |= not diro.set + self.some_notapp |= not diro.app + + self.some_notreqset |= not diro.reqset + self.some_nottcset |= not diro.tcset + self.some_notappset |= not diro.appset + + self.some_reqgroup |= diro.reqgroup + self.some_notreqgroup |= not diro.reqgroup + + self.some_tcgroup |= diro.tcgroup + self.some_nottcgroup |= not diro.tcgroup + + self.some_appmat |= diro.appmat + self.some_notappmat |= not diro.appmat + + self.some_reqorset |= diro.req | diro.reqset + self.some_tcorset |= diro.tc | diro.tcset + + self.some_notreqorset |= not (diro.req | diro.reqset) + self.some_nottcorset |= not (diro.tc | diro.tcset) + + self.some_reqorgroup |= diro.req | diro.reqgroup + self.some_tcorgroup |= diro.tc | diro.tcgroup + + self.some_notreqorgroup |= not (diro.req | diro.reqgroup) + self.some_nottcorgroup |= not (diro.tc | diro.tcgroup) + + self.diros.append (diro) + + def sync(self): + """Compute the all_ attributes of this set from what we know of the + current elements in the set. All the all_ attributes are set to False + on empty sets.""" + + # Beware of queries over empty sets. All the some_ attributes + # start False, so the all_ attributes would turn true if we're + # not cautious + + has_diro = len(self.diros) > 0 + + self.all_tc = has_diro and not self.some_nottc + self.all_req = has_diro and not self.some_notreq + self.all_set = has_diro and not self.some_notset + self.all_app = has_diro and not self.some_notapp + + self.all_reqset = has_diro and not self.some_notreqset + self.all_tcset = has_diro and not self.some_nottcset + self.all_appset = has_diro and not self.some_notappset + + self.all_reqorset = has_diro and not self.some_notreqorset + self.all_tcorset = has_diro and not self.some_nottcorset + + self.all_reqgroup = has_diro and not self.some_notreqgroup + self.all_tcgroup = has_diro and not self.some_nottcgroup + self.all_appmat = has_diro and not self.some_notappmat + + self.all_reqorgroup = has_diro and not self.some_notreqorgroup + self.all_tcorgroup = has_diro and not self.some_nottcorgroup + +# *************************** +# ** Directory abstraction ** +# *************************** + +# The kind of material node that the directory holds. This is used +# to determine the hyperlink and the page title texts + +class DirKind: + def __init__ (self, txthdl, image): + self.image = image + self.txthdl = txthdl + +class dcl: + + TC = DirKind ( + image="tc", txthdl = "Testcase") + + TCG = DirKind ( + image="tcg", txthdl = "Testcase Group") + + REQ = DirKind ( + image="rq", txthdl = "Requirement") + + REQG = DirKind ( + image="rqg", txthdl = "Requirement Group") + + APP = DirKind ( + image="app", txthdl = "Appendix Material") + + INTRO = DirKind ( + image="intro", txthdl = "Introductory Material") + + kinds = (TC, TCG, REQ, REQG, APP, INTRO) + +# DocGenerator helper to process one specific subdirectory of the TOR/TC +# hierarchy + +class Dir: + def __init__(self, root, subdirs, files): + + # Filesystem attributes for this directory + + self.root = root # path to this dir + self.subdirs = subdirs # list of local subdir names + self.files = files # list of local file names + + self.name = os.path.basename(root) # local name of this dir + + # Links to parent and children in the directory tree. These are + # set as dir objects get mapped within a DirTree instance. + + self.pdo = None + self.subdos = [] + + # NodeSet for subdos, which we'll populate when computing + # attributes bottom-up + + self.sdset = None + + # Properties from presence of local files, better cached to prevent + # repeated real file presence checks + + self.req = "req.txt" in self.files + self.hreq = "hreq.txt" in self.files + self.test = "test.py" in self.files + self.tc = "tc.txt" in self.files + self.htc = "htc.txt" in self.files + self.set = "set.txt" in self.files + self.app = "app.txt" in self.files + + # title name, to be displayed in index tables, and sorting key. + + # The sorting key is the directory name (not title name) for starters, + # which is meant to allow prefix characters (numbers prior to the + # first '_') to influence sorts while not being displayed. We will + # need to update that when bridging over nodes, to make sure that the + # children remain grouped wrt their new parent and set of siblings. + + self.tname = to_title (self.name) + self.sname = self.name + + # ------------------------------------------ + # -- Bottom-Up node attribute computation -- + # ------------------------------------------ + + def botmup_compute_attributes (self, pathi, data): + + # Compute predicates over our set of children. We expect the children + # attributes to be available here. + + self.sdset = NodeSet (diros=self.subdos) + + # Populate extra attributes on this node + + self.container = self.set or self.req + + # TC, APP or REQ SETS are nodes with consistent children (all reqs, + # all tcs, or all apps). + + self.tcset = self.set and self.sdset.all_tc + self.reqset = self.set and self.sdset.all_req + self.appset = self.set and self.sdset.all_app + + # Some mixes are legitimate, as long as the leaf item kinds (tc + # or req) remain consistent. We call GROUPS those containers, and at + # this stage we let the notion propagate up pretty freely: + + self.tcgroup = self.set and self.sdset.all_tcorgroup + self.reqgroup = self.set and self.sdset.all_reqorgroup + self.appmat = self.app or (self.set and self.sdset.all_appmat) + + # Consistency checks need to be applied elswhere to determine whether + # such or such mix is acceptable. Consider for example the difference + # in consistency between + # + # 1) either: + # set/tc + # /tc + # /tc + # + # or: + # set/set/tc + # /tc + # /set/tc + # /tc + # + # (only allow sets of TCs, or sets of sets) + # + # 2) or possibly + # set/set/tc + # /tc + # /tc + # + # (allow sets of either tc or set) + + # Now compute the node KIND, which conveys how we want the node to be + # referenced (in index table hyperlinks) and titled. This is not meant + # to be representative of structural properties. REQ nodes often are + # tcset or tcgroup as well, for example. + + self.kind = ( + dcl.TC if self.tc + else dcl.REQ if self.req + else dcl.TCG if self.tcgroup + else dcl.REQG if self.reqgroup + else dcl.APP if self.appmat + else dcl.INTRO) + + def dfile(self, path=False): + """Name of the text file which holds the meat of this dir/artifact""" + + base = ( + 'tc.txt' if self.tc else + 'set.txt' if self.set else + 'req.txt' if self.req else + 'htc.txt' if self.htc else + 'hreq.txt' if self.hreq else + 'app.txt' if self.app else + None) + + return ( + os.path.join (self.root, base) if base and path + else base) + + def dtext (self): + if self.dfile() == None: + warn ("missing description file in %s" % self.root) + return "" + else: + return get_content (self.dfile(path=True)) + + +# ******************************** +# ** Directory Tree abstraction ** +# ******************************** + +# Helper to manage dirname -> dirobject associations and establish +# parent/children relationships over dir objects, assuming the tree +# is walked top down. + +# Values to denote possible ways to walk a tree and possible actions to take +# at every directory node when walking the tree + +topdown, botmup = range (2) + +dirProcess, dirSkip, dirCutPre, dirCutPost = range (4) +# dirProcess: process this node and walk children +# dirCutPre: don't process this node and don't walk children +# dirCutPost: process this node and don't walk children +# dirSkip: skip processing for this node, walk children nevertheless + +im = { dirSkip: "dirSkip", dirProcess: "dirProcess", + dirCutPre: "dirCutPre", dirCutPost: "dirCutPost" } + +class DirTree: + def __init__(self, roots): + self.roots = roots + + # ------------------------------------------------------------ + # -- Tree walking facilities, once we're past the first doc -- + # -- generation pass, all the parent children links are set -- + # ------------------------------------------------------------ + + # Local facilities. Beware that walks are used to compute directory + # object attributes, so these can't be relied upon. + + class WalkInfo: + def __init__(self, data, pathi, process, ctl, mode): + self.process = process + self.ctl = ctl + self.mode = mode + self.pathi = pathi + self.data = data + + def __enter(self, diro, wi): + if diro.req: wi.pathi.n_req += 1 + if diro.tc: wi.pathi.n_tc += 1 + return wi.ctl (diro, wi.pathi, wi.data) + + def __exit(self, diro, wi): + if diro.req: wi.pathi.n_req -= 1 + if diro.tc: wi.pathi.n_tc -= 1 + + def __visit (self, diro, wi): + ctl = self.__enter(diro, wi) + + process_this = ctl not in [dirSkip, dirCutPre] + visit_children = ctl not in [dirCutPre, dirCutPost] + + if process_this and wi.mode == topdown: + wi.process(diro, wi.pathi, wi.data) + + if visit_children: + wi.pathi.depth += 1 + [self.__visit(subdo, wi) for subdo in diro.subdos] + wi.pathi.depth -= 1 + + if process_this and wi.mode == botmup: + wi.process(diro, wi.pathi, wi.data) + + self.__exit(diro, wi) + + def __default_ctl(self, diro, pathi, widata): + return dirProcess + + # Exposed facilities. + + def walk(self, mode, process, data=None, ctl=None): + + if ctl is None: ctl = self.__default_ctl + + [self.__visit ( + diro=diro, wi=DirTree.WalkInfo ( + process=process, pathi=PathInfo(), + data=data, mode=mode, ctl=ctl)) + for diro in self.roots] + + # --------------------------------------- + # -- Tree filtering/pruning facilities -- + # --------------------------------------- + + def rprune (self, namelist): + + """prune all subdirs of self that are do *not* lead to any dir + in NAMELIST""" + + class WalkInfo: + def __init__(self, tokeep): + self.tokeep = tokeep + self.toprune = [] + + def prunectl (diro, pathi, wi): + + # See if diro is within or beyond any of our dirs to keep. + # Keep going (skip) if within. Cut search if beyond. + + # Append "/" to items to prevent "bla/C" from being considered + # a directory prefix of "bla/Common" + + rootdir = diro.root + os.sep + + for tokeep in wi.tokeep: + dirtokeep = tokeep + os.sep + if os.path.commonprefix ((rootdir, dirtokeep)) == rootdir: + return ( + dirSkip if len(rootdir) < len(dirtokeep) + else dirCutPre) + + # diro is for sure not within or down any of our dirs to keep. + # register for actual pruning and don't search past it. + + wi.toprune.append (diro) + return dirCutPre + + # Walk this tree to compute the list of directories to prune, then do + # prune for real. We don't effectively prune nodes during the walk to + # prevent mishaps caused by changes to our internal datastructures + # while they are being processed. + + wi = WalkInfo (tokeep=namelist) + self.walk ( + mode=topdown, process=lambda diro, pathi, wi: None, + ctl=prunectl, data=wi) + + [diro.pdo.subdos.remove (diro) for diro in wi.toprune] + + # --------------------- + # -- Sorting entries -- + # --------------------- + + def sort (self): + + """Sort the list of subdirectory objects registered for each tree + node, to influence processing order in tree walks (hence insertion + order in auto-indexes)""" + + def sort_subdos(diro, pathi, wi): + + # Sort subdirectories of DIRO. Arrange to get + # + # * All the non containers first, to make sure that + # + # sub/x + # y + # + # gets out as + # + # y bla + # sub blo + # x blu + # + # and not as + # + # sub blo + # x blu + # y bla + # + # where y would be perceived as a child of "sub" + # + # * Those for which a local key in their respective key order, + # all before or after those without explicit keys depending + # on the "default" entry, + # + # * In every subcase, sort by subdirectory name + + # Fetch the local { subdirname: key } dictionary, if any + + kfile = os.path.join (diro.root, "keys.txt") + keys = ( + json.loads (get_content(kfile)) if os.path.exists(kfile) + else {"default": 0} + ) + + # Then sort according to our three criteria of interest + + diro.subdos.sort ( + key = lambda subdo: + (subdo.container, + keys[subdo.sname] if subdo.sname in keys + else keys["default"], + subdo.sname) + ) + + self.walk (mode=botmup, process=sort_subdos) + + # ----------------------------------------- + # -- Checking directory tree consistency -- + # ----------------------------------------- + + def check_local_consistency (self, diro, pathi): + """Perform checks on the files present in DIRO""" + + warn_if ( + not (diro.set or diro.req or diro.tc or diro.app + or diro.htc or diro.hreq), + "missing description text at %s" % diro.root) + warn_if (diro.req and len(diro.files) > 1, + "req.txt not alone in %s" % diro.root) + warn_if (diro.set and len(diro.files) > 1, + "set.txt not alone in %s" % diro.root) + warn_if (diro.tc and not diro.test, + "tc.txt without test.py in %s" % diro.root) + warn_if (diro.test and not diro.tc and not diro.htc, + "test.py without tc.txt in %s" % diro.root) + + warn_if ((diro.tc or diro.tcgroup) and pathi.n_req < 1, + "tc or set without req uptree at %s" % diro.root) + + warn_if (diro.req and pathi.n_req > 1, + "nested req (%d up) at %s" % (pathi.n_req - 1, diro.root)) + + warn_if (diro.req and pathi.n_tc > 0, + "req with tc uptree at %s" % diro.root) + + def check_downtree_consistency (self, diro, pathi): + """Perform checks on the relationships DIRO and its children""" + + warn_if ((diro.req or diro.set) and not diro.subdos, + "missing subdirs for artifact at %s" % diro.root) + + if not diro.subdos: return + + # Warn on structural inconsistencies + + warn_if (diro.req and not diro.sdset.all_tcorgroup, + "inconsistent subdirs down req.txt at %s" % diro.root) + + warn_if ( + diro.req and not (diro.sdset.all_reqorgroup + or diro.sdset.all_tcorgroup), + "missing testcases for leaf req in %s" % diro.root) + + # Warn on missing testing strategy in leaf requirement with multiple + # testcases + + warn_if (diro.req and len (diro.subdos) > 1 and diro.sdset.all_tcorset + and "%(tstrategy-headline)s" not in diro.dtext(), + "req at %s misses testing strategy description" % diro.root) + + def topdown_check_consistency (self, diro, pathi, data): + self.check_local_consistency(diro, pathi) + self.check_downtree_consistency(diro, pathi) + + def check_consistency(self): + self.walk (mode=topdown, process=self.topdown_check_consistency) + +class DirTree_FromPath (DirTree): + + def __init__(self, rootp): + + DirTree.__init__(self, roots=[]) + + # First compute the tree of directory objects starting at path ROOTP, + # setting up for each the .pdo link to parent and the .subdos list of + # children. This is achieved by performing a top down walk of the os + # directory structure. + + self.dir = {} # dir-name -> dir-object dictionary + [self.topdown_map (dirname, subdirs, files) + for (dirname, subdirs, files) in os.walk(os.path.abspath(rootp))] + + # Arrange for the intermediate directories just there for file + # organisation purposes to disappear from our tree representation + + self.do_cross_overs() + + # Then compute exta node attributes, once the tree of internal + # directory objects is setup. + + self.compute_attributes() + + def topdown_map(self, dirname, subdirs, files): + + # Map directory DIRNAME into our dictionary and set up links to/from + # its parent directory, if any. We're called along a topdown walk, so + # we have mapped the parent directory already if there is one. + + # Ignore some subdirectories + + [subdirs.remove(d) for d in copy(subdirs) + if d in ('.svn', 'src') or d.startswith('tmp_')] + + # Map a new object for this dir ... + + diro = Dir (root=dirname, subdirs=subdirs, files=files) + + self.dir[dirname] = diro + + # Find out its parent object by name. If there's no parent object, + # this dir is a root. Setup the links otherwise. + + parentname = os.path.dirname(dirname) + + if parentname not in self.dir: + self.roots.append(diro) + else: + parento = self.dir[parentname] + diro.pdo = parento + parento.subdos.append(diro) + + # -------------------------------------------------------------- + # -- Abstract away nodes that were introduced only for source -- + # -- sharing purposes, and that should not introduce an extra -- + # -- layer in the qualification material. -- + # -- ----------------------------------------------------------- + + def __do_bridge_over(self, diro): + """Arrange for DIRO to disappear from the dir tree structure + it is in.""" + + print "======== Bridging over " + diro.root + + # Remove this diro from the list of children of its parent, + # and update each of this diro's children to have its parent + # as a new parent instead of this diro itself. + + # Turn: + # P <----- PARENT + # | + # DIRO <----- TO VANISH + # | + # +---+---+---+ + # | | | | + # c1 c2 c3 c4 <---- CHILDREN + # + # into: + # + # P <----- PARENT + # | + # +---+---+---+ + # | | | | + # c1 c2 c3 c4 <---- CHILDREN + + diro.pdo.subdos.remove(diro) + + for subdo in diro.subdos: + diro.pdo.subdos.append(subdo) + subdo.pdo = diro.pdo + + subdo.tname = '.'.join ([diro.tname, subdo.tname]) + subdo.sname = '.'.join ([diro.sname, subdo.sname]) + + def __decide_cross_over (self, diro, pathi, wi): + """Add DIRO to WI.tobridge if DIRO ought to be removed from the + tree.""" + + if diro.set and os.path.getsize (diro.dfile(path=True)) == 0: + wi.tobridge.append (diro) + + def do_cross_overs(self): + """Remove (bridge links over) intermediate nodes that should not + produce intermediate layers in the final document.""" + + # Collect the set of nodes to remove first, then remove each one in + # turn. Removing while we're walking the tree is, mm, hazardous. + + class WalkInfo: + def __init__(self): + self.tobridge = [] + + wi = WalkInfo () + self.walk ( + mode=topdown, process=self.__decide_cross_over, data=wi) + + [self.__do_bridge_over (diro) for diro in wi.tobridge] + + # --------------------------------------------- + # -- Computing tree/node attributes, before -- + # -- more sophisticated walks can take place -- + # --------------------------------------------- + + def compute_attributes(self): + self.walk (mode=botmup, process=Dir.botmup_compute_attributes) + +# ************************ +# ** Document Generator ** +# ************************ + +icLink, icNid, icBrief = range (3) + +class DocGenerator(object): + + def __init__(self, art_rootdir, rst_rootdir, options): + + # Command line options + self.o = options + + # Root of the directory tree where the qualification artifacts + # are to be found: + self.art_rootdir = os.path.abspath(art_rootdir) + + # Root of the directory tree where the generated document sources + # are to be produced: + self.rst_rootdir = os.path.abspath(rst_rootdir) + mkdir (self.rst_rootdir) + + self.resource_list = set([]) + + # current output file descriptor, while walking the tor/tc tree + self.ofd = None + + def register_resources(self, rset): + self.resource_list |= rset + + def docpath_to(self, filename): + return os.path.join(self.rst_rootdir, filename) + + def file2docfile(self, filename): + """Return the associated filename for a given path""" + docfile = os.path.relpath(filename, self.art_rootdir) + # If we are at the root directory then return our documentation + # entry point. + if docfile == ".": + return "index.rst" + + docfile = docfile.replace('/', '_').replace('\\', '_') + ".rst" + return docfile + + def ref(self, name): + """Transform string NAME into another string suitable to be used as + index name""" + result = os.path.relpath(name, self.art_rootdir) + return result.replace('/', '_').replace('\\', '_').replace('.', '_') + + # --------------------------------------------- + # -- Generating doc contents for a directory -- + # --------------------------------------------- + + def contents_from(self, diro, name): + + """Fetch descriptive text in file NAME for artifact in DIRO, and + proceed with supported macro-replacements. Append a TC index to TC + set descriptions that don't have one.""" + + # Fetch the descriptive text + + contents = get_content(os.path.join(diro.root, name)) + + # Compute the dictionary of substitutions to apply + + SUBST = { + "toplevel-index": self.toplev_index, + "tc-index": self.tc_index, + "app-index": self.app_index, + "subset-index": self.subset_index, + "global-reqindex": self.global_reqindex, + "req-headline": self.req_headline, + "tstrategy-headline": self.tstrat_headline, + "toc": self.toc + } + + dosubst = dict( + [(key, SUBST[key](diro)) + for key in SUBST if ("(%s)s" % key) in contents] + ) + + # Compute the extra text to add at the end, depending on + # the kind of artifact and on what substitutions apply + + extratext = ( + self.tc_index(diro) if ( + diro.tcgroup and "tc-index" not in dosubst + and "subset-index" not in dosubst) + else "" + ) + + return contents % dosubst + extratext + + def gen_tc_section(self, diro): + """Generate the TestCase Sources section, and register the + sources as resources""" + + tco = TestCase (dir=diro.root, dgen=self) + + self.ofd.write(rest.subsection ("Test Sources")) + + self.ofd.write(subsec_header("Functional Code")) + self.ofd.write(rest.list( + [':ref:`%s`' % self.ref(d) for d in sorted(tco.fnsources)])) + + self.ofd.write(subsec_header("Program Tests")) + self.ofd.write(rest.list( + [':ref:`%s`' % self.ref(d) for d in tco.drsources])) + + if tco.conspecs: + self.ofd.write(subsec_header("Consolidation Tests")) + self.ofd.write(rest.list( + [':ref:`%s`' % self.ref(d) for d in tco.conspecs])) + + self.register_resources ( + tco.fnsources | tco.drsources | tco.conspecs) + + def gen_toc_section(self, diro): + """Generate the Table Of Contents section as needed""" + + tocentries = [ + self.file2docfile(os.path.join(diro.root, sdo.root)) + for sdo in diro.subdos] + + self.ofd.write('\n\n' + rest.toctree( + itemlist=tocentries, depth=1, attrlist=[":hidden:"])) + + # -------------------------------------- + # -- Tailored directory tree instance -- + # -------------------------------------- + + def art_dirtree_for(self, chapdirs): + + dirtree = DirTree_FromPath(rootp=self.art_rootdir) + + dirtree.rprune ( + [os.path.join (self.art_rootdir, dir) for dir in chapdirs]) + + dirtree.check_consistency() + dirtree.sort () + + return dirtree + + # --------------------------- + # -- generate doc chapters -- + # --------------------------- + + ALT_TITLES = { + "Qualif": "GNATcoverage TORs" + } + + def __gen_doc_contents (self, diro, pathi, wi): + """Generate the RST file for the DIRO artifact/directory-object, as + part of a dirtree walk carrying a general DirTree.WalkInfo object WI + and path info PATHI""" + + self.ofd = open( + self.docpath_to (self.file2docfile(diro.root)), 'w') + + ttext = ( + self.ALT_TITLES[diro.tname] if diro.tname in self.ALT_TITLES + else diro.tname) + + txthdl = diro.kind.txthdl + self.ofd.write(rest.section( + ttext + (" -- %s" % txthdl if txthdl else "") + )) + + if diro.dfile(): + self.ofd.write(self.contents_from (diro=diro, name=diro.dfile())) + + if diro.tc: + self.gen_tc_section(diro) + + self.gen_toc_section(diro) + + self.ofd.close() + + + def generate_chapters(self): + + self.art_dirtree.walk (mode=topdown, process=self.__gen_doc_contents) + + # --------------------------- + # -- generate index tables -- + # --------------------------- + + # Most index tables obey a common construction process, where some table + # header is produced and a set of lines is added, corresponding to + # subdirectories of where the table is produced. The general construction + # process is driven by the "index_table" method, which performs a walk of + # of the local subdirtree controled by callbacks to decide which dir/lines + # are added and using what style. + + class WalkInfo: + """Class of an object carried over the whole tree walk, to help + control the overall table construction process.""" + + def __init__ (self, rootp, emphctl): + + # root path from which the tree walk starts + self.rootp = rootp + + # line emphasis control callback + self.emphctl = emphctl + + # max depth reached during the tree walk + self.topdepth = sys.maxint + + # text outcome of the tree walk, the table body + self.text = None + + # Node (Line) Set reached by the walk. Attributes of this will + # help compute the table headers, in particular column titles + # tailored from the set of nodes/lines that the table includes: + self.lset = NodeSet() + + def __addline_for (self, diro, pathi, wi): + """Reached directory object DIRO during the tree walk, with specific + path info PATHI and overall walk info state in WI. Update the relevant + walk info attributes (e.g. topdepth), then compute and add the table + text line for this entry.""" + + if pathi.depth < wi.topdepth: + wi.topdepth = pathi.depth + + # Fetch the contents aimed at the Summary column, first paragraph in + # the description file. + + dtext = diro.dtext().strip() + toblank = re.search (".*?(\n[ \t]*\n)", dtext, re.DOTALL) + sumtext = (toblank.group(0) if toblank else dtext).replace ('\n', ' ') + + # Compute the link and the entry text, then apply the emphasis + # control if we have any: + + linktext = ':doc:`%s <%s>`' % ( + diro.kind.image, self.ref(diro.root)) + + entrytext = "%s%s" % ( + ". . " * (pathi.depth - wi.topdepth), diro.tname) + + if wi.emphctl: + sumtext = wi.emphctl(sumtext.strip(), diro, pathi) + entrytext = wi.emphctl(entrytext.strip(), diro, pathi) + + # Then append the whole entry and update the node set + # covered by the walk: + + wi.text.append ( + ' %s#%s#%s' % (linktext, entrytext, sumtext)) + + wi.lset.register_one (diro=diro) + + def index_table(self, rooto, nodectl, emphctl, tblhdr): + """Common helper to index table constructors.""" + + local_dirtree = DirTree (roots=[rooto]) + + wi = self.WalkInfo ( + rootp=rooto.root, emphctl=emphctl) + + # Start by computing the list of lines of the table body + + wi.text = [] + + local_dirtree.walk ( + mode=topdown, process=self.__addline_for, + ctl=nodectl, data=wi) + + # sync the line attributes and pick defaults for each column header + + wi.lset.sync() + + if icLink not in tblhdr: + tblhdr[icLink] = "" + + if icNid not in tblhdr: + tblhdr[icNid] = ( + "Testcase" if wi.lset.all_tc + else "Testcase Group" if wi.lset.all_tcgroup + else "Testcase or Group" if wi.lset.all_tcorgroup + else "Requirement" if wi.lset.all_req + else "Requirement Group" if wi.lset.all_reqgroup + else "Requirement or Group" if wi.lset.all_reqorgroup + else "Item") + + if icBrief not in tblhdr: + tblhdr[icBrief] = "Description" + + # Compute the table header + + wi.text = [ + "", + '.. tabularcolumns:: |l|l|p{0.70\linewidth}|', + '.. csv-table::', + ' :delim: #', + ' :widths: 2, 20, 70' + ] + [ + ' :header: %s' % ','.join ( + [tblhdr[cid] for cid in [icLink, icNid, icBrief]] + ) + ] + ['', ''] + wi.text + + linkcolheader = tblhdr[icLink] + if linkcolheader: + wi.text.extend ( + ["", + "**%s** " % linkcolheader + + + "For each section described by a line, this column features " + "an hyperlink to the section contents. The hyperlink text is " + "indicative of the section kind:", + ""] + ["* *%s*\tdesignates some %s" % (k.image, k.txthdl) + for k in dcl.kinds] + ) + + + wi.text = '\n'.join (wi.text) + return wi + + def tc_index(self, diro): + """Produce an index table referencing all the testcases reachable + downtree from directory DIRO, including lines for all the intermediate + artifacts that need to be traversed to reach the testcases + (requirements, groups, whatever). No line is included for the DIRO + directory itself. Lines for groups at depth 1 are bold. Lines for + deeper groups are italic.""" + + return self.index_table ( + rooto = diro, + tblhdr = {}, + emphctl = lambda text, diro, pathi: + (rest.strong(text) if diro.container and pathi.depth == 1 + else rest.emphasis(text) if diro.container + else text), + nodectl = lambda diro, pathi, wi: + (dirProcess if pathi.depth > 0 + else dirSkip) + ).text + + def subset_index(self, diro): + """Produce an index table referencing all the requirements or groups + reachable first from DIRO and only these. No line is included for DIRO + itself or for any element deeper than those first reached.""" + + return self.index_table ( + rooto = diro, + tblhdr = {}, + emphctl = None, + nodectl = lambda diro, pathi, wi: + (dirCutPost if pathi.depth > 0 and (diro.set or diro.req) + else dirSkip) + ).text + + def app_index(self, diro): + """Produce an index table referencing all the appendix artifacts + reachable from DIRO and only these.""" + + return self.index_table ( + rooto = diro, + tblhdr = {}, + emphctl = None, + nodectl = lambda diro, pathi, wi: + (dirProcess if pathi.depth > 0 and diro.appmat + else dirSkip) + ).text + + def toplev_index(self, diro): + return self.index_table ( + rooto = diro, + tblhdr = {icLink: "(*)", icNid: "Chapter"}, + emphctl = lambda text, diro, pathi: + (rest.strong(text) if pathi.depth == 1 + else text), + nodectl = lambda diro, pathi, wi: + (dirProcess if pathi.depth == 1 and diro.container + else dirCutPost if ( + pathi.depth > 1 and (diro.container or diro.appmat)) + else dirSkip) + ).text + + # --------------------------- + # -- generate general index -- + # --------------------------- + + def local_reqindex(self, diro): + return self.index_table ( + rooto = diro, + tblhdr = {}, + emphctl = lambda text, diro, pathi: + (rest.strong(text) if pathi.depth == 1 + else rest.emphasis(text) if pathi.depth > 1 + else text), + nodectl = lambda diro, pathi, wi: + (dirSkip if pathi.depth == 0 + else dirCutPost if diro.req + else dirProcess) + ) + + def __gen_index_contents (self, diro, pathi, wi): + + lwi = self.local_reqindex (diro) + + lwi.text = ''.join ( + [self.headline (diro.tname + " Requirements"), lwi.text] + ) if lwi.lset.some_req else "" + + wi.text = ''.join ([wi.text, lwi.text]) + + def global_reqindex(self, diro): + + class WalkInfo: + def __init__(self): + self.text="" + + wi = WalkInfo() + + self.art_dirtree.walk ( + mode=topdown, process=self.__gen_index_contents, + data=wi, ctl = lambda diro, pathi, wi: + (dirSkip if pathi.depth == 0 else dirCutPost) + ) + + return wi.text + + # --------------------------------- + # -- req and tstrategy headlines -- + # --------------------------------- + + def headline (self, text): + return rest.subsection (text) + + def req_headline (self, diro, plural=False): + return self.headline ("Requirement" + ("s" if plural else "")) + + def tstrat_headline (self, diro): + return self.headline ("Testing Strategy") + + # ----------------- + # -- toc entries -- + # ----------------- + + def toc(self, diro): + + tocentries = [ + self.file2docfile(os.path.join(diro.root, sd)) + for sd in diro.subdirs] + + return ''.join ( + [sec_header("Links"), + rest.toctree(tocentries, depth = 1 if not diro.pdo else 2)] + ) if tocentries else "" + + # ---------------------------- + # -- generate resource file -- + # ---------------------------- + + def generate_resources(self): + fd = open(self.docpath_to ('resources.rst'), 'w') + fd.write(rest.chapter('Resources')) + fd.write(rest.toctree( + [self.file2docfile(d) for d in self.resource_list])) + fd.close() + + for r in self.resource_list: + fd = open(self.docpath_to(self.file2docfile(r)), 'w') + fd.write('\n.. _%s:\n\n' % self.ref(r)) + fd.write(rest.section(os.path.basename(r))) + fd.write(rest.code_block(get_content(r), 'ada')) + fd.close() + + # --------------------------------------------- + # -- generate all the document items, -- + # -- checking tree consistency along the way -- + # --------------------------------------------- + + def generate_all(self): + + # Compute the set of subdirs/chapters our document ought to include. + # This is the explicit list when one was provided, and a set of common + # subdirs + those of relevance for the requested criterion otherwise. + + crit_subdirs_for = { + 'doC': ["stmt"], + 'doB': ["stmt", "decision"], + 'doA': ["stmt", "decision", "mcdc"] + } + + this_subdirs = ( + self.o.chapdirs.split(',') if self.o.chapdirs + else ( + ["OpEnviron", "Appendix", "Common"] + + [os.path.join ("Ada", csd) + for csd in crit_subdirs_for[self.o.dolevel]] + ) + ) + + self.art_dirtree = self.art_dirtree_for (this_subdirs) + + self.generate_chapters() + self.generate_resources() + +# The main of the script + +valid_dolevels = ('doA', 'doB', 'doC') + +if __name__ == "__main__": + + op = optparse.OptionParser(usage="%prog ") + + op.add_option ( + "--dolevel", dest="dolevel", default=None, + type='choice', choices=valid_dolevels, + help = ( + "Target DO178 qualification level." + )) + + op.add_option ( + "--chapdirs", dest="chapdirs", default=None, + help = ( + "Comma separated list of chapter directories to consider" + )) + + (options, args) = op.parse_args() + + exit_if ( + not options.chapdirs and not options.dolevel, + "A DO level or a set of chapter dirs must be specified" + ) + + exit_if ( + options.chapdirs and options.dolevel, + "A DO level may not be specified together with an explicit " + "set of chapter dirs." + ) + + mygen = DocGenerator( + art_rootdir=ART_ROOTDIR, rst_rootdir=RST_ROOTDIR, options=options) + + mygen.generate_all() diff --git a/qualification/tor/scripts/rest.py b/qualification/tor/scripts/rest.py new file mode 100644 index 000000000..9228b1622 --- /dev/null +++ b/qualification/tor/scripts/rest.py @@ -0,0 +1,99 @@ +"""Implement some utility function that ease generation of ReST code""" + +HEADING_CHARS = ['#', '*', '=', '-', '^', '"'] + + +def heading(title, heading_char): + if isinstance(heading_char, int): + heading_char = HEADING_CHARS[heading_char] + + result = "\n\n" + result += heading_char * len(title) + '\n' + result += title + '\n' + result += heading_char * len(title) + '\n\n' + return result + + +def part(title): + return heading(title, '#') + + +def chapter(title): + return heading(title, '*') + + +def section(title): + return heading(title, '=') + + +def subsection(title): + return heading(title, '-') + + +def subsubseciton(title): + return heading(title, '^') + + +def paragraph(title): + return heading(title, '"') + + +def toctree(itemlist, depth=2, attrlist=()): + return '\n'.join ( + [".. toctree::", + " :maxdepth: %s" % depth] + + + [" %s" % attr for attr in attrlist] + + ['\n'] + + [" %s" % item for item in itemlist] + ) + '\n' + + +def emphasis(content): + return "*" + content + "*" + + +def strong(content): + return "**" + content + "**" + + +def generic_block(command, content, command_arg=None): + if content == '': + return '' + + if command_arg is None: + command_arg = '' + + result = "\n.. %s:: %s\n\n" % (command, command_arg) + result += '\n'.join([' ' + line for line in content.splitlines()]) + result += '\n\n' + return result + + +def warning(content): + return generic_block('warning', content) + + +def parsed_literal(content): + return generic_block('parsed-literal', content) + + +def code_block(content, language): + return generic_block('code-block', content, language) + + +def raw(content, doc_type): + return generic_block('raw', content, doc_type) + + +def line_block(content): + result = '\n\n' + result += '\n'.join([' ' + line for line in content.splitlines()]) + return result + +def list(content): + result = '\n\n' + result += '\n'.join([' * %s' % l for l in content]) + result += '\n\n' + return result + diff --git a/qualification/tor/scripts/theme/static/gnatpython.css_t b/qualification/tor/scripts/theme/static/gnatpython.css_t new file mode 100644 index 000000000..10e295ff1 --- /dev/null +++ b/qualification/tor/scripts/theme/static/gnatpython.css_t @@ -0,0 +1,239 @@ +/* + * nature.css_t + * ~~~~~~~~~~~~ + * + * Sphinx stylesheet -- nature theme. + * + * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. + * :license: BSD, see LICENSE for details. + * + */ + +@import url("basic.css"); + +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: Arial, sans-serif; + font-size: 100%; + background-color: #111; + color: #555; + margin: 0; + padding: 0; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 230px; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.document { + background-color: #eee; +} + +div.body { + background-color: #ffffff; + color: #3E4349; + padding: 0 30px 30px 30px; + font-size: 0.9em; +} + +div.footer { + color: #555; + width: 100%; + padding: 13px 0; + text-align: center; + font-size: 75%; +} + +div.footer a { + color: #444; + text-decoration: underline; +} + +div.related { + background-color: #4A7697; + line-height: 32px; + color: #fff; + font-size: 0.9em; +} + +div.related a { + color: #E2F3CC; +} + +div.sphinxsidebar { + font-size: 0.75em; + line-height: 1.5em; +} + +div.sphinxsidebarwrapper{ + padding: 20px 0; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Arial, sans-serif; + color: #222; + font-size: 1.2em; + font-weight: normal; + margin: 0; + padding: 5px 10px; + background-color: #ccc; + text-shadow: 1px 1px 0 white +} + +div.sphinxsidebar h4{ + font-size: 1.1em; +} + +div.sphinxsidebar h3 a { + color: #444; +} + + +div.sphinxsidebar p { + color: #888888; + padding: 5px 20px; +} + +div.sphinxsidebar p.topless { +} + +div.sphinxsidebar ul { + margin: 10px 20px; + padding: 0; + color: #000; +} + +div.sphinxsidebar a { + color: #444; +} + +div.sphinxsidebar input { + border: 1px solid #ccc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar input[type=text]{ + margin-left: 20px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #005B81; + text-decoration: none; +} + +a:hover { + color: #E32E00; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Arial, sans-serif; + background-color: #6A96B7; + font-weight: normal; + color: #212224; + margin: 30px 0px 10px 0px; + padding: 5px 0 5px 10px; +} + +div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; } +div.body h2 { font-size: 150%; background-color: #C8D5E3; } +div.body h3 { font-size: 120%; background-color: #D8DEE3; } +div.body h4 { font-size: 110%; background-color: #D8DEE3; } +div.body h5 { font-size: 100%; background-color: #D8DEE3; } +div.body h6 { font-size: 100%; background-color: #D8DEE3; } + +a.headerlink { + color: #c60f0f; + font-size: 0.8em; + padding: 0 4px 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + background-color: #c60f0f; + color: white; +} + +div.body p, div.body dd, div.body li { + line-height: 1.5em; +} + +div.admonition p.admonition-title + p { + display: inline; +} + +div.highlight{ + background-color: white; +} + +div.note { + background-color: #eee; + border: 1px solid #ccc; +} + +div.seealso { + background-color: #ffc; + border: 1px solid #ff6; +} + +div.topic { + background-color: #eee; +} + +div.warning { + background-color: #ffe4e4; + border: 1px solid #f66; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre { + padding: 10px; + background-color: #E4FFCB; + color: #222; + border: 1px solid #C6C9CB; + font-size: 1.1em; +} + +tt { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ + font-size: 1.1em; + font-family: monospace; +} + +.viewcode-back { + font-family: Arial, sans-serif; +} + +div.viewcode-block:target { + background-color: #f4debf; + border-top: 1px solid #ac9; + border-bottom: 1px solid #ac9; +} diff --git a/qualification/tor/scripts/theme/theme.conf b/qualification/tor/scripts/theme/theme.conf new file mode 100644 index 000000000..f35da3eae --- /dev/null +++ b/qualification/tor/scripts/theme/theme.conf @@ -0,0 +1,4 @@ +[theme] +inherit = basic +stylesheet = gnatpython.css +pygments_style = sphinx From b2b08fa94fc5827b09d10430cd65bd93863119bf Mon Sep 17 00:00:00 2001 From: Tonu Naks Date: Wed, 10 Jan 2024 12:21:09 +0000 Subject: [PATCH 1432/1483] Generate TOR without QM eng/das/cov/gnatcoverage#203 --- .gitignore | 13 + qualification/{qm => }/LRM/lrm_ref.txt | 0 qualification/LRM/lrm_ref_.txt | 252 +++ qualification/__init__.py | 0 qualification/genbundle.py | 18 +- .../Introduction/Definitions/content.rst | 0 .../Introduction/Document_Purpose/content.rst | 0 .../Organization_And_Roles/content.rst | 3 +- .../Referenced_Documents/content.rst | 0 qualification/plans/Introduction/content.rst | 11 + qualification/plans/Makefile | 130 ++ .../Developer/Compliance/content.rst | 3 + .../Methods_And_Activities/content.rst | 0 .../Developer/Traceability/content.rst | 0 .../Developer/Version_Control/content.rst | 0 .../Developer/content.rst | 11 +- .../User/Compliance/content.rst | 3 +- .../User/Suggested_Items/content.rst | 2 + .../User/content.rst | 7 +- .../content.rst | 7 +- .../Certification_Credit/content.rst | 0 .../Compliance/content.rst | 0 .../Data_Production/content.rst | 0 .../Operational_Conditions/content.rst | 0 .../Qualification_Data_Overview/content.rst | 0 .../Qualified_Interface/content.rst | 106 + .../Qualified_Interface/content_bin.rst | 0 .../Qualified_Interface/content_src.rst | 0 .../Tool_Overview/content.rst | 0 .../Tool_Qualification_Level/content.rst | 0 .../User_Activities/Archiving/content.rst | 0 .../User_Activities/Qualification/content.rst | 0 .../User_Activities/Usage/content.rst | 0 .../User_Activities/content.rst | 13 +- .../plans/Tool_Qualification_Plan/content.rst | 16 + .../Activities/content.rst | 0 .../Compliance/content.rst | 0 .../Conformity_Review/content.rst | 0 .../Cycles/content.rst | 0 .../Tool_Quality_Assurance_Plan/content.rst | 11 +- qualification/plans/conf.py | 175 ++ .../{qm/plans/content.rst => plans/index.rst} | 11 +- .../qm/.qm/cnt_env.py/artifactstamp.json | 7 - qualification/qm/README_FIRST | 25 - qualification/qm/common_conf.py | 66 - qualification/qm/env/env.py | 9 - qualification/qm/genmodel.py | 191 -- qualification/qm/plans/.qm/artifactstamp.json | 10 - .../plans/Introduction/.qm/artifactstamp.json | 9 - .../qm/plans/Introduction/content.rst | 11 - .../.qm/artifactstamp.json | 9 - .../.qm/artifactstamp.json | 9 - .../.qm/artifactstamp.json | 9 - .../Tool_Overview/.qm/artifactstamp.json | 9 - .../User_Activities/.qm/artifactstamp.json | 9 - .../plans/Tool_Qualification_Plan/content.rst | 15 - qualification/qm/plans/qmconf.py | 26 - qualification/qm/qm_plugins/generate_doc.py | 62 - qualification/qm/qm_prolog.py | 81 - .../qm/scripts/generate_plans_html.py | 6 - .../qm/scripts/generate_plans_pdf.py | 6 - qualification/qm/scripts/generate_tor_html.py | 6 - qualification/qm/scripts/generate_tor_pdf.py | 6 - qualification/qm/template.xml | 421 ---- qualification/scripts/__init__.py | 0 qualification/scripts/common_conf.py | 168 ++ qualification/scripts/logger.py | 93 + qualification/scripts/missing_tr_log.txt | 0 qualification/scripts/qm_plugins/__init__.py | 0 .../{qm => scripts}/qm_plugins/importers.py | 459 ++-- .../{qm => scripts}/qm_plugins/link_lrm.py | 0 .../qm_plugins/lrm_index_parser.py | 0 qualification/scripts/rest/__init__.py | 310 +++ qualification/scripts/rest/writer.py | 470 ++++ qualification/tor/{scripts => }/Makefile | 0 qualification/tor/__init__.py | 0 qualification/tor/conf.py | 195 ++ qualification/tor/genrest.py | 1962 +++++++++++++++++ qualification/tor/genrest_conf.py | 13 + qualification/tor/missing_tr_log.txt | 0 qualification/tor/proj_conf.py | 8 + qualification/tor/scripts/conf.py | 216 -- qualification/tor/scripts/genrest.py | 1472 ------------- qualification/tor/scripts/rest.py | 99 - .../tor/scripts/theme/static/gnatpython.css_t | 239 -- qualification/tor/scripts/theme/theme.conf | 4 - testsuite/Qualif/Ada/decision/1_Core/req.rst | 2 - .../Qualif/Ada/decision/Consolidation/req.rst | 2 - .../Qualif/Ada/decision/Exemptions/req.rst | 2 - .../Ada/decision/MixedConstructs/req.rst | 2 - .../Qualif/Ada/decision/Robustness/req.rst | 2 - testsuite/Qualif/Ada/mcdc/1_Core/req.rst | 2 - .../Qualif/Ada/mcdc/Consolidation/req.rst | 2 - testsuite/Qualif/Ada/mcdc/Exemptions/req.rst | 2 - .../Qualif/Ada/mcdc/MixedConstructs/req.rst | 2 - testsuite/Qualif/Ada/mcdc/Robustness/req.rst | 2 - .../1_Core/02_LexicalElements/Pragmas/req.rst | 2 - .../Ada/stmt/1_Core/03_DeclsAndTypes/req.rst | 2 - .../Ada/stmt/1_Core/051_SimpleStmts/req.rst | 2 - .../1_Core/052_CompoundStmts/53_If/req.rst | 2 - .../1_Core/052_CompoundStmts/54_Case/req.rst | 2 - .../1_Core/052_CompoundStmts/550_Loop/req.rst | 2 - .../052_CompoundStmts/552_Iteration/req.rst | 2 - .../1_Core/052_CompoundStmts/56_Block/req.rst | 2 - .../06_Subprograms/DeclsAndCalls/req.rst | 2 - .../1_Core/06_Subprograms/Derived/req.rst | 2 - .../stmt/1_Core/06_Subprograms/Inline/req.rst | 2 - .../1_Core/06_Subprograms/No_Return/req.rst | 2 - .../stmt/1_Core/06_Subprograms/Null/req.rst | 2 - .../06_Subprograms/ParameterModes/req.rst | 2 - .../stmt/1_Core/06_Subprograms/Return/req.rst | 2 - .../1_Core/06_Subprograms/Xfunctions/req.rst | 2 - .../Ada/stmt/1_Core/07_Packages/req.rst | 2 - .../08_VisibilityRules/Renamings/req.rst | 2 - .../stmt/1_Core/10_Structure/Subunits/req.rst | 2 - .../Ada/stmt/1_Core/11_Exceptions/req.rst | 2 - .../Ada/stmt/1_Core/12_GenericUnits/req.rst | 2 - .../13_Representation/MachineCode/req.rst | 2 - .../13_Representation/OpAttributes/req.rst | 2 - .../13_Representation/RepAttributes/req.rst | 2 - testsuite/Qualif/Ada/stmt/1_Core/req_set.rst | 8 +- .../Qualif/Ada/stmt/Consolidation/req.rst | 2 - testsuite/Qualif/Ada/stmt/ControlFlow/req.rst | 2 - testsuite/Qualif/Ada/stmt/Exemptions/req.rst | 2 - .../Qualif/Ada/stmt/MixedConstructs/req.rst | 2 - testsuite/Qualif/Ada/stmt/Robustness/req.rst | 2 - .../Appendix/Testsuite/Selftest/hreq.rst | 3 + .../Qualif/C/stmt/Core/05_Expressions/req.rst | 2 - .../Common/GprFacilities/ConfigAttr/req.rst | 2 - .../GprFacilities/GnatcovSwitches/req.rst | 2 - .../Common/GprFacilities/MainAttr/req.rst | 2 - .../Common/GprFacilities/Subdirs/req.rst | 2 - .../Qualif/Common/GprFacilities/req_set.rst | 2 +- testsuite/Qualif/Common/Report/req.rst | 2 - .../Qualif/Common/UnitsOfInterest/GPR/req.rst | 2 - .../Common/UnitsOfInterest/SCOS/req.rst | 2 - testsuite/Qualif/Environment/content.rst | 139 ++ .../Qualif/Environment/env_table_bin.rst | 2 +- .../Qualif/Environment/env_table_src.rst | 2 +- testsuite/Qualif/Index/content.rst | 3 - testsuite/Qualif/Introduction/content.rst | 2 +- testsuite/Qualif/content.rst | 3 +- testsuite/Qualif/qmconf.py | 28 - testsuite/STR/conf.py | 19 +- testsuite/STR/genrest.py | 4 +- 145 files changed, 4321 insertions(+), 3490 deletions(-) rename qualification/{qm => }/LRM/lrm_ref.txt (100%) create mode 100644 qualification/LRM/lrm_ref_.txt create mode 100644 qualification/__init__.py rename qualification/{qm => }/plans/Introduction/Definitions/content.rst (100%) rename qualification/{qm => }/plans/Introduction/Document_Purpose/content.rst (100%) rename qualification/{qm => }/plans/Introduction/Organization_And_Roles/content.rst (93%) rename qualification/{qm => }/plans/Introduction/Referenced_Documents/content.rst (100%) create mode 100644 qualification/plans/Introduction/content.rst create mode 100644 qualification/plans/Makefile rename qualification/{qm => }/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst (98%) rename qualification/{qm => }/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst (100%) rename qualification/{qm => }/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst (100%) rename qualification/{qm => }/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst (100%) rename qualification/{qm => }/plans/Tool_Configuration_Management_Plan/Developer/content.rst (76%) rename qualification/{qm => }/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst (94%) rename qualification/{qm => }/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst (91%) rename qualification/{qm => }/plans/Tool_Configuration_Management_Plan/User/content.rst (61%) rename qualification/{qm => }/plans/Tool_Configuration_Management_Plan/content.rst (64%) rename qualification/{qm => }/plans/Tool_Qualification_Plan/Certification_Credit/content.rst (100%) rename qualification/{qm => }/plans/Tool_Qualification_Plan/Compliance/content.rst (100%) rename qualification/{qm => }/plans/Tool_Qualification_Plan/Data_Production/content.rst (100%) rename qualification/{qm => }/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst (100%) rename qualification/{qm => }/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst (100%) create mode 100644 qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst rename qualification/{qm => }/plans/Tool_Qualification_Plan/Qualified_Interface/content_bin.rst (100%) rename qualification/{qm => }/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst (100%) rename qualification/{qm => }/plans/Tool_Qualification_Plan/Tool_Overview/content.rst (100%) rename qualification/{qm => }/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst (100%) rename qualification/{qm => }/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst (100%) rename qualification/{qm => }/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst (100%) rename qualification/{qm => }/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst (100%) rename qualification/{qm => }/plans/Tool_Qualification_Plan/User_Activities/content.rst (57%) create mode 100644 qualification/plans/Tool_Qualification_Plan/content.rst rename qualification/{qm => }/plans/Tool_Quality_Assurance_Plan/Activities/content.rst (100%) rename qualification/{qm => }/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst (100%) rename qualification/{qm => }/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst (100%) rename qualification/{qm => }/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst (100%) rename qualification/{qm => }/plans/Tool_Quality_Assurance_Plan/content.rst (78%) create mode 100644 qualification/plans/conf.py rename qualification/{qm/plans/content.rst => plans/index.rst} (66%) delete mode 100644 qualification/qm/.qm/cnt_env.py/artifactstamp.json delete mode 100644 qualification/qm/README_FIRST delete mode 100644 qualification/qm/common_conf.py delete mode 100644 qualification/qm/env/env.py delete mode 100755 qualification/qm/genmodel.py delete mode 100644 qualification/qm/plans/.qm/artifactstamp.json delete mode 100644 qualification/qm/plans/Introduction/.qm/artifactstamp.json delete mode 100644 qualification/qm/plans/Introduction/content.rst delete mode 100644 qualification/qm/plans/Tool_Configuration_Management_Plan/.qm/artifactstamp.json delete mode 100644 qualification/qm/plans/Tool_Qualification_Plan/.qm/artifactstamp.json delete mode 100644 qualification/qm/plans/Tool_Qualification_Plan/Operational_Conditions/.qm/artifactstamp.json delete mode 100644 qualification/qm/plans/Tool_Qualification_Plan/Tool_Overview/.qm/artifactstamp.json delete mode 100644 qualification/qm/plans/Tool_Qualification_Plan/User_Activities/.qm/artifactstamp.json delete mode 100644 qualification/qm/plans/Tool_Qualification_Plan/content.rst delete mode 100644 qualification/qm/plans/qmconf.py delete mode 100644 qualification/qm/qm_plugins/generate_doc.py delete mode 100644 qualification/qm/qm_prolog.py delete mode 100644 qualification/qm/scripts/generate_plans_html.py delete mode 100644 qualification/qm/scripts/generate_plans_pdf.py delete mode 100644 qualification/qm/scripts/generate_tor_html.py delete mode 100644 qualification/qm/scripts/generate_tor_pdf.py delete mode 100644 qualification/qm/template.xml create mode 100644 qualification/scripts/__init__.py create mode 100644 qualification/scripts/common_conf.py create mode 100644 qualification/scripts/logger.py create mode 100644 qualification/scripts/missing_tr_log.txt create mode 100644 qualification/scripts/qm_plugins/__init__.py rename qualification/{qm => scripts}/qm_plugins/importers.py (74%) rename qualification/{qm => scripts}/qm_plugins/link_lrm.py (100%) rename qualification/{qm => scripts}/qm_plugins/lrm_index_parser.py (100%) create mode 100644 qualification/scripts/rest/__init__.py create mode 100644 qualification/scripts/rest/writer.py rename qualification/tor/{scripts => }/Makefile (100%) create mode 100644 qualification/tor/__init__.py create mode 100644 qualification/tor/conf.py create mode 100755 qualification/tor/genrest.py create mode 100644 qualification/tor/genrest_conf.py create mode 100644 qualification/tor/missing_tr_log.txt create mode 100644 qualification/tor/proj_conf.py delete mode 100644 qualification/tor/scripts/conf.py delete mode 100755 qualification/tor/scripts/genrest.py delete mode 100644 qualification/tor/scripts/rest.py delete mode 100644 qualification/tor/scripts/theme/static/gnatpython.css_t delete mode 100644 qualification/tor/scripts/theme/theme.conf create mode 100644 testsuite/Qualif/Environment/content.rst delete mode 100644 testsuite/Qualif/qmconf.py diff --git a/.gitignore b/.gitignore index e05ca0b2e..b15f24716 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,16 @@ gnatinspect.db README.html TAGS *.~undo-tree~ +*.log + +# temporary output of genrest.py +qualification/tor/scripts/source/ + +# generated output of genbundle.py +**/build +**/source + +# vscode local settings +.env +.vscode + diff --git a/qualification/qm/LRM/lrm_ref.txt b/qualification/LRM/lrm_ref.txt similarity index 100% rename from qualification/qm/LRM/lrm_ref.txt rename to qualification/LRM/lrm_ref.txt diff --git a/qualification/LRM/lrm_ref_.txt b/qualification/LRM/lrm_ref_.txt new file mode 100644 index 000000000..cb5bda93d --- /dev/null +++ b/qualification/LRM/lrm_ref_.txt @@ -0,0 +1,252 @@ +# secnum # Ada revs # sectitle # applicable? # comment # +# ---------#----------#--------------------------------------------------------- #------------ #--------------------------# +# # # # # # +1 # 95,05,12 # General # no # General overview material +1.1 # 95,05,12 # Scope # no # Not relevant to SCA +1.1.1 # 95,05,12 # Extent # no # Not relevant to SCA +1.1.2 # 95,05,12 # Structure # no # Not relevant to SCA +1.1.3 # 95,05,12 # Conformity of an Implementation with the Standard # no # Not relevant to SCA +1.1.4 # 95,05,12 # Method of Description and Syntax Notation # no # Not relevant to SCA +1.1.5 # 95,05,12 # Classification of Errors # no # Not relevant to SCA +1.2 # 95,05,12 # Normative References # no # Not relevant to SCA +1.3 # 95,05 # Definitiona # no # Not relevant to SCA +1.3 # 12 # Terms and Definitions # no # Not relevant to SCA + +2 # 95,05,12 # Lexical Elements # no # General overview material +2.1 # 95,05,12 # Character Set # no # Not relevant to SCA +2.2 # 95,05,12 # Lexical Elements, Separators, and Delimiters # no # Not relevant to SCA +2.3 # 95,05,12 # Identifiers # no # Not relevant to SCA +2.4 # 95,05,12 # Numeric Literals # no # Not relevant to SCA +2.4.1 # 95,05,12 # Decimal Literals # no # Not relevant to SCA +2.4.2 # 95,05,12 # Based Literals # no # Not relevant to SCA +2.5 # 95,05,12 # Character Literals # no # Not relevant to SCA +2.6 # 95,05,12 # String Literals # no # Not relevant to SCA +2.7 # 95,05,12 # Comments # no # Not relevant to SCA +2.8 # 95,05,12 # Pragmas # yes # +2.9 # 95,05,12 # Reserved Words # no # Not relevant to SCA + +3 # 95,05,12 # Declarations and Types # no # General overview material +3.1 # 95,05,12 # Declarations # no # This is a general overview section; TOR references are supplied for the associated specific sections. Only declarations that result in generated code are considered to have SCA obligations. +3.2 # 95,05,12 # Types and Subtypes # no # General overview material +3.2.1 # 95,05,12 # Type Declarations # no # This is a general syntax section; TOR references are supplied for the relevant specific sections +3.2.2 # 95,05,12 # Subtype Declarations # yes # +3.2.3 # 95,05,12 # Classification of Operations # no # Not relevant to SCA +3.2.4 # 12 # Subtype Predicates # yes # +3.3 # 95,05,12 # Objects and Named Numbers # no # General overview material +3.3.1 # 95,05,12 # Object Declarations # yes # +3.3.2 # 95,05,12 # Number Declarations # no # Not relevant to SCA +3.4 # 95,05,12 # Derived Types and Classes # no # Covered by 3.2.2 +3.4.1 # 95,05,12 # Derivation Classes # no # Not relevant to SCA +3.5 # 95,05,12 # Scalar Types # no # Covered by subsections +3.5.1 # 95,05,12 # Enumeration Types # yes # +3.5.2 # 95,05,12 # Character Types # yes # +3.5.3 # 95,05,12 # Boolean Types # yes # +3.5.4 # 95,05,12 # Integer Types # yes # +3.5.5 # 95,05,12 # Operations of Discrete Types # no # Not relevant to SCA +3.5.6 # 95,05,12 # Real Types # no # Deferred to 3.5.7 and 3.5.9 +3.5.7 # 95,05,12 # Floating Point Types # yes # +3.5.8 # 95,05,12 # Operations of Floating Point Types # no # Not relevant to SCA +3.5.9 # 95,05,12 # Fixed Point Types # yes # +3.5.10 # 95,05,12 # Operations of Fixed Point Types # no # Not relevant to SCA +3.6 # 95,05,12 # Array Types # yes # +3.6.1 # 95,05,12 # Index Constraints and Discrete Ranges # yes # +3.6.2 # 95,05,12 # Operations of Array Types # no # Not relevant to SCA +3.6.3 # 95,05,12 # String Types # no # Not relevant to SCA +3.7 # 95,05,12 # Discriminants # no # Not relevant to SCA +3.7.1 # 95,05,12 # Discriminant Constraints # no # Not relevant to SCA +3.7.2 # 95,05,12 # Operations of Discriminated Types # no # Covered by 4.1.4 +3.8 # 95,05,12 # Record Types # partial # SCA obligations are associated with default initializations for record components +3.8.1 # 95,05,12 # Variant Parts and Discrete Choices # yes # +3.9 # 95,05,12 # Tagged Types and Type Extensions # no # Covered by subsections +3.9.1 # 95,05,12 # Type Extensions # no # Not relevant to SCA +3.9.2 # 95,05,12 # Dispatching Operations of Tagged Types # yes # +3.9.3 # 95,05,12 # Abstract Types and Subprograms # no # Not relevant to SCA +3.9.4 # 05,12 # Interface Types # yes # +3.10 # 95,05,12 # Access Types # partial # SCA obligations are associated with default initializations for access values +3.10.1 # 95,05,12 # Incomplete Type Declarations # no # Not relevant to SCA +3.10.2 # 95,05,12 # Operations of Access Types # no # Not relevant to SCA +3.11 # 95,05,12 # Declarative Parts # no # SCA obligations for a declarative_part are covered in other sections: either for the unit in which the declarative_part occurs, or the constituent declarative_items in the declarative_part +3.11.1 # 95,05,12 # Completions of Declarations # no # Not relevant to SCA + +4 # 95,05,12 # Names and Expressions # no # General overview material +4.1 # 95,05,12 # Names # no # This is a general syntax section; TOR references are supplied for the relevant specific sections +4.1.1 # 95,05,12 # Indexed Components # partial # This section applies when the indexed component is an element of a Boolean array and is used as a condition +4.1.2 # 95,05,12 # Slices # no # Not relevant to SCA +4.1.3 # 95,05,12 # Selected Components # partial # This section applies when the selected component is a Boolean value and is used as a condition +4.1.4 # 95,05,12 # Attributes # partial # This section applies when the attribute is a Boolean value and is used as a condition +4.1.5 # 12 # User-Defined References # yes # +4.1.6 # 12 # User-Defined Indexing # yes # +4.2 # 95,05,12 # Literals # no # Not relevant to SCA +4.3 # 95,05,12 # Aggregates # no # Not relevant to SCA +4.3.1 # 95,05,12 # Record Aggregates # no # Not relevant to SCA +4.3.2 # 95,05,12 # Extension Aggregates # no # Not relevant to SCA +4.3.3 # 95,05,12 # Array Aggregates # no # Not relevant to SCA +4.4 # 95,05,12 # Expressions # no # This is a general syntax section; TOR references are supplied for the relevant specific sections +4.5 # 95,05,12 # Operators and Expression Evaluation # no # This is a general syntax section; TOR references are supplied for the relevant specific sections +4.5.1 # 95,05,12 # Logical Operators and Short-circuit Control Forms # yes # +4.5.2 # 95,05,12 # Relational Operators and Membership Tests # yes # +4.5.3 # 95,05,12 # Binary Adding Operators # no # Not relevant to SCA +4.5.4 # 95,05,12 # Unary Adding Operators # no # Not relevant to SCA +4.5.5 # 95,05,12 # Multiplying Operators # no # Not relevant to SCA +4.5.6 # 95,05,12 # Highest Precedence Operators # partial # The "not" operator is the only highest_precedence_operator relevant to SCA +4.5.7 # 12 # Conditional Expressions # yes # +4.5.8 # 12 # Quantified Expressions # yes # +4.6 # 95,05,12 # Type Conversions # partial # This section applies when the type conversion is to type Boolean and is used as a condition +4.7 # 95,05,12 # Qualified Expressions # partial # This section applies when the type qualification is to type Boolean and is used as a condition +4.8 # 95,05,12 # Allocators # no # Not relevant to SCA +4.9 # 95,05,12 # Static Expressions and Static Subtypes # no # SCA-related requirements for static expressions are the same as for non-static expressions and are addressed in the corresponding sections +4.9.1 # 95,05,12 # Statically Matching Constraints and Subtypes # no # Not relevant to SCA + +5 # 95,05,12 # Statements # no # General overview material +5.1 # 95,05,12 # Simple and Compound Statements - Sequences of Statements # partial # This is a general syntax section; the null statement is specifically addressed here, all others covered elsewhere. +5.2 # 95,05,12 # Assignment Statements # yes # +5.3 # 95,05,12 # If Statements # yes # +5.4 # 95,05,12 # Case Statements # yes # +5.5 # 95,05,12 # Loop Statements # yes # +5.5.1 # 12 # User-Defined Iterator Types # yes # +5.5.2 # 12 # Generalized Loop Iteration # yes # +5.6 # 95,05,12 # Block Statements # yes # +5.7 # 95,05,12 # Exit Statements # yes # +5.8 # 95,05,12 # Goto Statements # yes # + +6 # 95,05,12 # Subprograms # no # General overview material +6.1 # 95,05,12 # Subprogram Declarations # no # Not relevant to SCA +6.1.1 # 12 # Preconditions and Postconditions # yes # +6.2 # 95,05,12 # Formal Parameter Modes # no # Not relevant to SCA +6.3 # 95,05,12 # Subprogram Bodies # no # SCA obligations are associated with the constituents of the subprogram body +6.3.1 # 95,05,12 # Conformance Rules # no # Not relevant to SCA +6.3.2 # 95,05,12 # Inline Expansion of Subprograms # yes # +6.4 # 95,05,12 # Subprogram Calls # yes # +6.4.1 # 95,05,12 # Parameter Associations # no # Covered by 6.4 +6.5 # 95,05,12 # Return Statements # yes # +6.5.1 # 05 # Pragma No_Return # yes # +6.5.1 # 12 # Nonreturning Procedures # yes # +6.6 # 95,05,12 # Overloading of Operators # no # Not relevant to SCA +6.7 # 05,12 # Null Procedures # yes # +6.8 # 12 # Expression Functions # yes # + +7 # 95,05,12 # Packages # no # General overview material +7.1 # 95,05,12 # Package Specifications and Declarations # no # SCA obligations are associated with the constituent basic_declarative_items in the package_specification +7.2 # 95,05,12 # Package Bodies # no # SCA obligations are associated with the constituent declarations and statements in the package_body +7.3 # 95,05,12 # Private Types and Private Extensions # no # Not relevant to SCA +7.3.1 # 95,05,12 # Private Operations # no # Not relevant to SCA +7.3.2 # 12 # Type Invariants # yes # +7.4 # 95,05,12 # Deferred Constants # yes # +7.5 # 95,05,12 # Limited Types # no # Not relevant to SCA +7.6 # 95,05 # User-Defined Assignment and Finalization # no # GNATcoverage is not qualified for controlled type definitions +7.6 # 12 # Assignment and Finalization # no # Only relevant to task types, protected types and controlled type definitions, for which GNATcoverage is not qualified +7.6.1 # 95,05,12 # Completion and Finalization # no # Only relevant to task types, protected types and controlled type definitions, for which GNATcoverage is not qualified + +8 # 95,05,12 # Visibility Rules # no # General overview material +8.1 # 95,05,12 # Declarative Region # no # Not relevant to SCA +8.2 # 95,05,12 # Scope of Declarations # no # Not relevant to SCA +8.3 # 95,05,12 # Visibility # no # Not relevant to SCA +8.3.1 # 05,12 # Overriding Indicators # yes # +8.4 # 95,05,12 # Use Clauses # no # Not relevant to SCA +8.5 # 95,05,12 # Renaming Declarations # no # Not relevant to SCA +8.5.1 # 95,05,12 # Object Renaming Declarations # no # Not relevant to SCA +8.5.2 # 95,05,12 # Exception Renaming Declarations # no # Not relevant to SCA +8.5.3 # 95,05,12 # Package Renaming Declarations # no # Not relevant to SCA +8.5.4 # 95,05,12 # Subprogram Renaming Declarations # no # Not relevant to SCA +8.5.5 # 95,05,12 # Generic Renaming Declarations # no # Not relevant to SCA +8.6 # 95,05,12 # The Context of Overload Resolution # no # Not relevant to SCA + +9 # 95,05,12 # Tasks and Synchronization # no # GNATcoverage is not qualified for tasking constructs +9.1 # 95,05,12 # Task Units and Task Objects # no # GNATcoverage is not qualified for tasking constructs +9.2 # 95,05,12 # Task Execution - Task Activation # no # GNATcoverage is not qualified for tasking constructs +9.3 # 95,05,12 # Task Dependence - Termination of Tasks # no # GNATcoverage is not qualified for tasking constructs +9.4 # 95,05,12 # Protected Units and Protected Objects # no # GNATcoverage is not qualified for tasking constructs +9.5 # 95,05,12 # Intertask Communication # no # GNATcoverage is not qualified for tasking constructs +9.5.1 # 95,05,12 # Protected Subprograms and Protected Actions # no # GNATcoverage is not qualified for tasking constructs +9.5.2 # 95,05,12 # Entries and Accept Statements # no # GNATcoverage is not qualified for tasking constructs +9.5.3 # 95,05,12 # Entry Calls # no # GNATcoverage is not qualified for tasking constructs +9.5.4 # 95,05,12 # Requeue Statements # no # GNATcoverage is not qualified for tasking constructs +9.6 # 95,05,12 # Delay Statements, Duration, and Time # no # GNATcoverage is not qualified for tasking constructs +9.6.1 # 05,12 # Formatting, Time Zones, and other operations for Time # no # GNATcoverage is not qualified for tasking constructs +9.7 # 95,05,12 # Select Statements # no # GNATcoverage is not qualified for tasking constructs +9.7.1 # 95,05,12 # Selective Accept # no # GNATcoverage is not qualified for tasking constructs +9.7.2 # 95,05,12 # Timed Entry Calls # no # GNATcoverage is not qualified for tasking constructs +9.7.3 # 95,05,12 # Conditional Entry Calls # no # GNATcoverage is not qualified for tasking constructs +9.7.4 # 95,05,12 # Asynchronous Transfer of Control # no # GNATcoverage is not qualified for tasking constructs +9.8 # 95,05,12 # Abort of a Task - Abort of a Sequence of Statements # no # GNATcoverage is not qualified for tasking constructs +9.9 # 95,05,12 # Task and Entry Attributes # no # GNATcoverage is not qualified for tasking constructs +9.10 # 95,05,12 # Shared Variables # no # GNATcoverage is not qualified for tasking constructs +9.11 # 95,05,12 # Example of Tasking and Synchronization # no # GNATcoverage is not qualified for tasking constructs + +10 # 95,05,12 # Program Structure and Compilation Issues # no # General overview material +10.1 # 95,05,12 # Separate Compilation # no # Not relevant to SCA +10.1.1 # 95,05,12 # Compilation Units - Library Units # no # Not relevant to SCA +10.1.2 # 95,05,12 # Context Clauses - With Clauses # no # Not relevant to SCA +10.1.3 # 95,05,12 # Subunits of Compilation Units # no # Not relevant to SCA +10.1.4 # 95,05,12 # The Compilation Process # no # Not relevant to SCA +10.1.5 # 95,05,12 # Pragmas and Program Units # no # Not relevant to SCA +10.1.6 # 95,05,12 # Environment-Level Visibility Rules # no # Not relevant to SCA +10.2 # 95,05,12 # Program Execution # no # SCA obligations are associated with the constituents of the units comprising the program's partitions +10.2.1 # 95,05,12 # Elaboration Control # no # SCA obligations are associated with the constituents of the units whose elaboration is controlled by the pragmas defined in this section + +11 # 95,05,12 # Exceptions # no # General overview material +11.1 # 95,05,12 # Exception Declarations # no # Not relevant to SCA +11.2 # 95,05,12 # Exception Handlers # yes # +11.3 # 95,05,12 # Raise Statements # yes # +11.4 # 95,05,12 # Exception Handling # partial # The semantics for control transferring to a local handler are described in 11.2. The more general propagation described in 11.4 is only partially supported, see the :ref:`operational-conditions` section of this document. +11.4.1 # 95,05,12 # The Package Exceptions # no # The only subprogram defined in Ada.Exceptions that has SCA obligations is Raise_Exception, and this has the same treatment as the raise statement (11.3) +11.4.2 # 95 # Example of Exception Handling # no # Not relevant to SCA +11.4.2 # 05,12 # Pragmas Assert and Assertion_Policy # yes # +11.4.3 # 05,12 # Example of Exception Handling # no # Not relevant to SCA +11.5 # 95,05,12 # Suppressing Checks # no # Not relevant to SCA +11.6 # 95,05,12 # Exceptions and Optimization # no # Not relevant to SCA + +12 # 95,05,12 # Generic Units # no # General overview material +12.1 # 95,05,12 # Generic Declarations # no # The SCA obligations of generic declarations are only manifest at instantiations (12.3) +12.2 # 95,05,12 # Generic Bodies # no # The SCA obligations of generic bodies are only manifest at instantiations (12.3) +12.3 # 95,05,12 # Generic Instantiation # yes # +12.4 # 95,05,12 # Formal Objects # no # Not relevant to SCA +12.5 # 95,05,12 # Formal Types # no # Not relevant to SCA +12.5.1 # 95,05,12 # Formal Private and Derived Types # no # Not relevant to SCA +12.5.2 # 95,05,12 # Formal Scalar Types # no # Not relevant to SCA +12.5.3 # 95,05,12 # Formal Array Types # no # Not relevant to SCA +12.5.4 # 95,05,12 # Formal Access Types # no # Not relevant to SCA +12.5.5 # 05,12 # Formal Interface Types # no # Not relevant to SCA +12.6 # 95,05,12 # Formal Subprograms # no # Not relevant to SCA +12.7 # 95,05,12 # Formal Packages # no # Not relevant to SCA +12.8 # 95,05,12 # Example of a Generic Package # no # Not relevant to SCA + +13 # 95,05,12 # Representation Issues # no # General overview material +13.1 # 95,05 # Operational and Representation Items # no # This is a general syntax section; TOR references are supplied for the relevant specific sections +13.1 # 12 # Operational and Representation Aspects # no # This is a general syntax section; TOR references are supplied for the relevant specific sections +13.1.1 # 12 # Aspect Specifications # no # Not relevant to SCA. Particular aspects are, e.g. Precondition, and these are handled as part of their specific section. +13.2 # 95,05 # Pragma Pack # partial # Use of packed component in decisions +13.2 # 12 # Packed Types # partial # Use of packed component in decisions +13.3 # 95 # Representation Attributes # partial # The only construct relevant to SCA is the address attribute definition +13.3 # 05,12 # Operational and Representation Attributes # partial # The only construct relevant to SCA is the address attribute definition +13.4 # 95,05,12 # Enumeration Representation Clauses # no # Not relevant to SCA +13.5 # 95,05,12 # Record Layout # no # General overview material +13.5.1 # 95,05,12 # Record Representation Clauses # yes # +13.5.2 # 95,05,12 # Storage Place Attributes # no # Not relevant to SCA +13.5.3 # 95,05,12 # Bit Ordering # yes # +13.6 # 95,05,12 # Change of Representation # no # Not relevant to SCA +13.7 # 95,05,12 # The Package System # partial # The only consitutents of package System that are relevant to SCA are the relational operators for type Address +13.7.1 # 95,05,12 # The Package System.Storage_Elements # no # Not relevant to SCA +13.7.2 # 95,05,12 # The Package System.Address_To_Access_Conversions # no # Not relevant to SCA +13.8 # 95,05,12 # Machine Code Insertions # yes # +13.9 # 95,05,12 # Unchecked Type Conversions # no # Not relevant to SCA +13.9.1 # 95,05,12 # Data Validity # no # General overview material +13.9.2 # 95,05,12 # The Valid Attribute # no # Covered by 4.1.4 +13.10 # 95,05,12 # Unchecked Access Value Creation # no # Not relevant to SCA +13.11 # 95,05,12 # Storage Management # no # Not relevant to SCA +13.11.1 # 95,05 # The Max_Size_In_Storage_Elements Attribute # no # Not relevant to SCA +13.11.1 # 12 # Storage Allocation Attributes # no # Not relevant to SCA +13.11.2 # 95,05,12 # Unchecked Storage Deallocation # no # Not relevant to SCA +13.11.3 # 95,05 # Pragma Controlled # no # Not relevant to SCA +13.11.3 # 12 # Default Storage Pools # no # Storage Pools imply controlled type definitions, for which GNATcoverage is not qualified +13.11.4 # 12 # Storage Subpools # no # Storage Pools imply controlled type definitions, for which GNATcoverage is not qualified +13.11.5 # 12 # Subpool Reclamation # no # Storage Pools imply controlled type definitions, for which GNATcoverage is not qualified +13.11.6 # 12 # Storage Subpool Example # no # Storage Pools imply controlled type definitions, for which GNATcoverage is not qualified +13.12 # 95,05 # Pragma Restrictions # no # Not relevant to SCA +13.12 # 12 # Pragma Restrictions and Pragma Profile # no # Not relevant to SCA +13.12.1 # 05 # Language-Defined Restrictions # no # Not relevant to applicable SCA +13.12.1 # 12 # Language-Defined Restrictions and Profiles # no # Not relevant to applicable SCA +13.13 # 95,05,12 # Streams # no # General overview material +13.13.1 # 95,05,12 # The Package Streams # no # Not relevant to SCA +13.13.2 # 95,05,12 # Stream-Oriented Attributes # no # Not relevant to SCA +13.14 # 95,05,12 # Freezing Rules # no # Not relevant to SCA diff --git a/qualification/__init__.py b/qualification/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 6bf1fe46d..9e2b3a82d 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -202,7 +202,7 @@ import re import sys -# This lets us access modules that the testuite +# This lets us access modules that the testsuite # code features: MY_TESTSUITE_DIR = os.path.abspath("../testsuite") sys.path.append(MY_TESTSUITE_DIR) @@ -675,7 +675,7 @@ def sync(tr): if os.path.exists(target_dir): cp(tr, target_dir) else: - print("ERRRR !! inexistant target dir for %s" % tr) + print("ERROR !! inexistent target dir for %s" % tr) [sync(tr) for tr in find(root=".", pattern="tcs.dump")] @@ -684,7 +684,19 @@ def sync(tr): ) self.process_imports(env_chapter_dir) - self.__qm_build(part="tor") + announce("building %s %s" % (self.this_docformat, "TOR")) + + os.chdir(os.path.join(self.repodir, "qualification", "tor", "scripts")) + + run( + "python genrest.py --dolevel %s --force" % (self.o.dolevel) + ) + run( + "make %s" % (self.this_docformat), + env={"GENBUNDLE_DOLEVEL": self.o.dolevel}, + ) + + self.__latch_into(dir=self.itemsdir(), part="tor", toplevel=False) # ------------------------------ # -- dump_kit_consistency_log -- diff --git a/qualification/qm/plans/Introduction/Definitions/content.rst b/qualification/plans/Introduction/Definitions/content.rst similarity index 100% rename from qualification/qm/plans/Introduction/Definitions/content.rst rename to qualification/plans/Introduction/Definitions/content.rst diff --git a/qualification/qm/plans/Introduction/Document_Purpose/content.rst b/qualification/plans/Introduction/Document_Purpose/content.rst similarity index 100% rename from qualification/qm/plans/Introduction/Document_Purpose/content.rst rename to qualification/plans/Introduction/Document_Purpose/content.rst diff --git a/qualification/qm/plans/Introduction/Organization_And_Roles/content.rst b/qualification/plans/Introduction/Organization_And_Roles/content.rst similarity index 93% rename from qualification/qm/plans/Introduction/Organization_And_Roles/content.rst rename to qualification/plans/Introduction/Organization_And_Roles/content.rst index 6f57bd563..4048cc127 100644 --- a/qualification/qm/plans/Introduction/Organization_And_Roles/content.rst +++ b/qualification/plans/Introduction/Organization_And_Roles/content.rst @@ -23,5 +23,4 @@ qualification process for GNATcoverage, along with their responsibilities: management of the artifacts it produces (mostly Quality Assurance reports). * **GNATcoverage users**: GNATcoverage users are expected to perform the - activities identified in section - :qmref:`/PLANS/Tool_Qualification_Plan/User_Activities`. + activities identified in section :ref:`tqp-user-activities`. diff --git a/qualification/qm/plans/Introduction/Referenced_Documents/content.rst b/qualification/plans/Introduction/Referenced_Documents/content.rst similarity index 100% rename from qualification/qm/plans/Introduction/Referenced_Documents/content.rst rename to qualification/plans/Introduction/Referenced_Documents/content.rst diff --git a/qualification/plans/Introduction/content.rst b/qualification/plans/Introduction/content.rst new file mode 100644 index 000000000..09317a171 --- /dev/null +++ b/qualification/plans/Introduction/content.rst @@ -0,0 +1,11 @@ +============ +Introduction +============ + +.. toctree:: + :maxdepth: 1 + + Document_Purpose/content + Referenced_Documents/content + Definitions/content + Organization_And_Roles/content diff --git a/qualification/plans/Makefile b/qualification/plans/Makefile new file mode 100644 index 000000000..390b4f07f --- /dev/null +++ b/qualification/plans/Makefile @@ -0,0 +1,130 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = -c . +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Couverture.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Couverture.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Couverture" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Couverture" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latexpdf + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/latexpdf all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst b/qualification/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst similarity index 98% rename from qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst rename to qualification/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst index 6532580a1..9fd4606de 100644 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst +++ b/qualification/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst @@ -1,3 +1,6 @@ +Compliance Matrices +******************* + .. tabularcolumns:: |p{0.05\linewidth}|p{0.30\linewidth}|p{0.13\linewidth}|p{0.10\linewidth}|p{0.32\linewidth}| .. csv-table:: Compliance matrix for Table 7-1 of |tool_standard| diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst b/qualification/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst rename to qualification/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst b/qualification/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst rename to qualification/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst b/qualification/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst rename to qualification/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/content.rst b/qualification/plans/Tool_Configuration_Management_Plan/Developer/content.rst similarity index 76% rename from qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/content.rst rename to qualification/plans/Tool_Configuration_Management_Plan/Developer/content.rst index 09a65109c..fa78c7359 100644 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/Developer/content.rst +++ b/qualification/plans/Tool_Configuration_Management_Plan/Developer/content.rst @@ -10,9 +10,10 @@ perform is defined by Tables 7-1 and T-8 of |tool_standard|. This section describes the processes in place at AdaCore, the Tool Developer. -.. qmlink:: +.. toctree:: + :maxdepth: 1 - Compliance - Version_Control - Traceability - Methods_And_Activities + Compliance/content + Version_Control/content + Traceability/content + Methods_And_Activities/content diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst b/qualification/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst similarity index 94% rename from qualification/qm/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst rename to qualification/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst index be47a99f0..e7f9e1858 100644 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst +++ b/qualification/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst @@ -1,3 +1,5 @@ +Compliance Matrices +******************* .. tabularcolumns:: |p{0.05\linewidth}|p{0.35\linewidth}|p{0.10\linewidth}|p{0.30\linewidth}| @@ -10,4 +12,3 @@ 3 | Problem reporting, change control, change review, and configuration status accounting are established.|7.1c,d,e,f| Not required for TQL-5 tools. 4 | Archive, retrieval, and release are established. |7.1.g| Up to the applicant. 5 | Tool life cycle environment control is established. |7.1.h| Not required for TQL-5 tools. - diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst b/qualification/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst similarity index 91% rename from qualification/qm/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst rename to qualification/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst index 8f5278232..04b95f753 100644 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst +++ b/qualification/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst @@ -1,3 +1,5 @@ +Configuration management suggestions +************************************ What follows is a set of configuration management suggestions for the items up to the applicant as per the compliance matrix above. diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/User/content.rst b/qualification/plans/Tool_Configuration_Management_Plan/User/content.rst similarity index 61% rename from qualification/qm/plans/Tool_Configuration_Management_Plan/User/content.rst rename to qualification/plans/Tool_Configuration_Management_Plan/User/content.rst index d6c5583dd..d073b514c 100644 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/User/content.rst +++ b/qualification/plans/Tool_Configuration_Management_Plan/User/content.rst @@ -3,7 +3,8 @@ Tool User Configuration Management Suggestions ============================================== -.. qmlink:: +.. toctree:: + :maxdepth: 1 - Compliance - Suggested_Items + Compliance/content + Suggested_Items/content diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/content.rst b/qualification/plans/Tool_Configuration_Management_Plan/content.rst similarity index 64% rename from qualification/qm/plans/Tool_Configuration_Management_Plan/content.rst rename to qualification/plans/Tool_Configuration_Management_Plan/content.rst index ad80f0ae2..ee2d19640 100644 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/content.rst +++ b/qualification/plans/Tool_Configuration_Management_Plan/content.rst @@ -4,7 +4,8 @@ Tool Configuration Management Plan ================================== -.. qmlink:: +.. toctree:: + :maxdepth: 1 - Developer - User + Developer/content + User/content diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Certification_Credit/content.rst b/qualification/plans/Tool_Qualification_Plan/Certification_Credit/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/Certification_Credit/content.rst rename to qualification/plans/Tool_Qualification_Plan/Certification_Credit/content.rst diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Compliance/content.rst b/qualification/plans/Tool_Qualification_Plan/Compliance/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/Compliance/content.rst rename to qualification/plans/Tool_Qualification_Plan/Compliance/content.rst diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Data_Production/content.rst b/qualification/plans/Tool_Qualification_Plan/Data_Production/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/Data_Production/content.rst rename to qualification/plans/Tool_Qualification_Plan/Data_Production/content.rst diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst b/qualification/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst rename to qualification/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst b/qualification/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst rename to qualification/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst diff --git a/qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst b/qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst new file mode 100644 index 000000000..6ceb67e22 --- /dev/null +++ b/qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst @@ -0,0 +1,106 @@ +.. _qualified-interface: + +GNATcoverage Qualified Interface +================================ + +To obtain reports suitable for use as certification evidence, applicants shall +use GNATcoverage as follows: + +* Build and install the coverage runtime in a dedicated + directory. Use the GNAT Pro toolchain identified in the + *Operational Environment* section of the |tor_doc| document for this, + taking care to specify the and if the application is + not a native one. + + This would be achieved with a command such as: + + .. code-block:: text + + gnatcov setup [--target= --RTS=] --prefix= + + + This step needs only to be done once, provided that the *Operational + Environment* described in the |tor_doc| document has not changed as of + the previous coverage runtime setup. + + +* Instrument the application for coverage assessment and test harness main + units for coverage buffer dumping using the ``gnatcov instrument`` command; + Specify the coverage criterion level to be assessed as well as a trace + and as specified in the + *Operational Environment* section of the |tor_doc| document. Also specify the + set of units of interest for which coverage should be assessed trough + the arguments, which should at least include a + indication using the :literal:`-P` switch: + + .. code-block:: text + + gnatcov instrument [--target= --RTS=] --level= --dump-trigger= --dump-channel= -P + + +* Build the application and test executables with the GNAT Pro toolchain + identified in the *Operational Environment* section of the |tor_doc| document, + obeying the coding standard rules, and compilation switches documented there + as well. The gprbuild invocation to build the application shall contain the + ``--src-subdirs=gnatcov-instr`` argument on the command line, as well as a + ``--implicit-with=gnatcov_rts.gpr`` argument to link against the coverage + runtime. The coverage runtime project must be made available to gprbuild by + adding ``/share/gpr`` to the ``GPR_PROJECT_PATH`` environment + variable. + + +* Obtain as many execution trace files () as needed, by + running the test executables. + +* Optionally, produce a single file (format documented in the + GNATcoverage User's Guide), consolidating the coverage outcome for the list of + execution traces, produced in the previous step and stored in the + file, and querying results for the source units designated by + the argument: + + .. code-block:: text + + gnatcov coverage --annotate=report --level= -P @ -o + + +In the sample commands above: + +* designates the path to a directory in which the coverage + runtime will be installed. It shall be accessible for writing and reading by + the tool; +* identifies the trigger to produce execution traces, as + described in the tool User's Manual, and for which the value to be used + is defined in the |tor_doc| document; +* identifies the medium used by the instrumented executable to + output the execution traces, as described in the tool User's Manual and for + which the value to be used is defined in the |tor_doc| document; +* designates the coverage criteria to assess, depending on the software + level; + + * For level C, statement coverage data is obtained with :literal:`--level=stmt`; + + * For level B, statement *and* decision coverage data is obtained with + :literal:`--level=stmt+decision`; + + * For level A, statement *and* decision *and* mcdc coverage data is obtained + with :literal:`--level=stmt+mcdc`. + +* is the output file containing the GNATcoverage report; +* identifies the target platform (as in the GNAT Pro toolchain + prefixes, e.g. arm-elf); +* identifies the Ada runtime library to be used, (either a GNAT Pro + provided runtime, identified by its name, e.g. embedded-stm32f4, or the path + to a custom runtime project); +* is the name of an output file containing an execution trace; +* is the path to the GPR project file defining the main units for + the application testing; +* is a specification of the units for which coverage is to be + assessed (so called *Units Of Interest*), with GPR project file facilities, + as documented in the tool User's Guide and summarized in the |tor_doc| + document; + +* is a text file containing the list of execution traces to + operate on. + +IO redirections, sometimes necessary for proper operation of the programs +within the execution environment, are allowed. diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_bin.rst b/qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content_bin.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_bin.rst rename to qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content_bin.rst diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst b/qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst rename to qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Tool_Overview/content.rst b/qualification/plans/Tool_Qualification_Plan/Tool_Overview/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/Tool_Overview/content.rst rename to qualification/plans/Tool_Qualification_Plan/Tool_Overview/content.rst diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst b/qualification/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst rename to qualification/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst diff --git a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst b/qualification/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst rename to qualification/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst diff --git a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst b/qualification/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst rename to qualification/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst diff --git a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst b/qualification/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst rename to qualification/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst diff --git a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/content.rst b/qualification/plans/Tool_Qualification_Plan/User_Activities/content.rst similarity index 57% rename from qualification/qm/plans/Tool_Qualification_Plan/User_Activities/content.rst rename to qualification/plans/Tool_Qualification_Plan/User_Activities/content.rst index 12a3d647b..178808255 100644 --- a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/content.rst +++ b/qualification/plans/Tool_Qualification_Plan/User_Activities/content.rst @@ -1,13 +1,14 @@ -=============== +.. _tqp-user-activities: + User Activities =============== To finalize the qualification of |project_name|, the Tool User needs to perform a set of activities, described hereafter: -.. qmlink:: - - Qualification - Usage - Archiving +.. toctree:: + :maxdepth: 1 + Qualification/content + Usage/content + Archiving/content diff --git a/qualification/plans/Tool_Qualification_Plan/content.rst b/qualification/plans/Tool_Qualification_Plan/content.rst new file mode 100644 index 000000000..64f6ab886 --- /dev/null +++ b/qualification/plans/Tool_Qualification_Plan/content.rst @@ -0,0 +1,16 @@ +======================= +Tool Qualification Plan +======================= + +.. toctree:: + :maxdepth: 1 + + Qualification_Data_Overview/content + Compliance/content + Tool_Overview/content + Certification_Credit/content + Tool_Qualification_Level/content + Data_Production/content + Qualified_Interface/content + Operational_Conditions/content + User_Activities/content diff --git a/qualification/qm/plans/Tool_Quality_Assurance_Plan/Activities/content.rst b/qualification/plans/Tool_Quality_Assurance_Plan/Activities/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Quality_Assurance_Plan/Activities/content.rst rename to qualification/plans/Tool_Quality_Assurance_Plan/Activities/content.rst diff --git a/qualification/qm/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst b/qualification/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst rename to qualification/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst diff --git a/qualification/qm/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst b/qualification/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst rename to qualification/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst diff --git a/qualification/qm/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst b/qualification/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst similarity index 100% rename from qualification/qm/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst rename to qualification/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst diff --git a/qualification/qm/plans/Tool_Quality_Assurance_Plan/content.rst b/qualification/plans/Tool_Quality_Assurance_Plan/content.rst similarity index 78% rename from qualification/qm/plans/Tool_Quality_Assurance_Plan/content.rst rename to qualification/plans/Tool_Quality_Assurance_Plan/content.rst index e98dc4141..2bb49f112 100644 --- a/qualification/qm/plans/Tool_Quality_Assurance_Plan/content.rst +++ b/qualification/plans/Tool_Quality_Assurance_Plan/content.rst @@ -12,9 +12,10 @@ project for which the kit is produced. The most significant output is the The responsibility for the |QA| process belongs to the |QA| team. -.. qmlink:: +.. toctree:: + :maxdepth: 1 - Compliance - Cycles - Activities - Conformity_Review + Compliance/content + Cycles/content + Activities/content + Conformity_Review/content diff --git a/qualification/plans/conf.py b/qualification/plans/conf.py new file mode 100644 index 000000000..844c884c2 --- /dev/null +++ b/qualification/plans/conf.py @@ -0,0 +1,175 @@ +from collections import OrderedDict +from scripts.common_conf import ( + version, + project_name, + owner, + users, + assignments, + plans_doc_id, + rst_prolog, + VAR_REPLACEMENTS, +) + +doc_id = plans_doc_id + +extensions: list[str] = [] +papersize = "a4paper" +latex_show_pagerefs = True +html_sidebars = {"**": ["localtoc.html", "sourcelink.html", "searchbox.html"]} +latex_use_parts = False +toc_depth = 2 + +# roles definition +# ??? This is standard-specific and should not be defined here. +roles = OrderedDict( + [ + ("authors", {"description": "the authors of the document"}), + ("reviewers", {"description": "the reviewers of the document"}), + ("approvers", {"description": "the approvers of the document"}), + ] +) + +# Do some checks +assert rst_prolog is not None, "rst_prolog should be set in common_conf.py" + +templates_path = ["_templates"] + +# These parameters cannot be overriden so just force their value after +# reading user conf file +master_doc = "index" + +source_suffix = ".rst" +project = project_name +exclude_patterns = ["_build", "**/*_bin.rst", "**/*_src.rst"] +pygments_style = "sphinx" +html_theme = "classic" +html_theme_path = ["."] +html_theme_options = {"body_max_width": None} + + +PAGE_BLANK = r""" +\makeatletter +\def\cleartooddpage{%% + \cleardoublepage%% +} +\def\cleardoublepage{%% +\clearpage%% + \if@twoside%% + \ifodd\c@page%% + %% nothing to do + \else%% + \hbox{}%% + \thispagestyle{plain}%% + \vspace*{\fill}%% + \begin{center}%% + \textbf{\em This page is intentionally left blank.}%% + \end{center}%% + \vspace{\fill}%% + \newpage%% + \if@twocolumn%% + \hbox{}%% + \newpage%% + \fi%% + \fi%% + \fi%% +} +\makeatother +""" + +TOC_DEPTH = ( + r""" +\pagenumbering{arabic} +\setcounter{tocdepth}{%d} +""" + % toc_depth +) + +TOC_CMD = r""" +\makeatletter +\def\tableofcontents{%% + \pagestyle{plain}%% + \chapter*{\contentsname}%% + \@mkboth{\MakeUppercase{\contentsname}}%% + {\MakeUppercase{\contentsname}}%% + \@starttoc{toc}%% +} +\makeatother +""" + + +def latex_hyphen(): + return "\n".join([r"\hyphenpenalty=5000", r"\tolerance=1000"]) + + +def project_settings(): + + HLINE = r"\hline" + HEADERS = r"Name & Company & Team & Email \\" + assignment_tab = [] + + for role in filter(lambda x: x in assignments, roles.keys()): + title = ( + r"\multicolumn{4}{l}{\large \par} \\" + r" \multicolumn{4}{l}{\large %s \par} \\" % (role.capitalize()) + ) + + assignment_tab.append(title) + assignment_tab.append(HLINE) + assignment_tab.append(HEADERS) + assignment_tab.append(HLINE) + + for login in assignments[role]: + user = users[login] + assignment_tab.append( + r"%s & %s & %s & %s \\" + % (user["name"], user["company"], user["team"], user["email"]) + ) + + assignment_tab.append(HLINE) + + full_document_name = project_name + if doc_id is not None and len(doc_id) > 0: + full_document_name = "%s - %s" % (project_name, doc_id) + + return "\n".join( + [ + r"\newcommand*{\QMFullDocumentName}[0]{" + + full_document_name + + r"}", + r"\newcommand*{\QMProjectName}[0]{" + project_name + r"}", + r"\newcommand*{\QMDocID}[0]{" + doc_id + r"}", + r"\newcommand*{\QMVersion}[0]{" + version + r"}", + r"\newcommand*{\QMTabUsers}[0]{" + + "\n".join(assignment_tab) + + r"}", + ] + ) + + +TOC = r""" +\cleardoublepage +\tableofcontents +\cleardoublepage\pagestyle{plain} +""" + +latex_elements = { + "preamble": TOC_DEPTH + + PAGE_BLANK + + TOC_CMD + + latex_hyphen() + + "\n" + + project_settings(), + "tableofcontents": TOC, + "papersize": papersize, +} + +latex_documents = [ + ( + "index", + "PLANS.tex", + f"GNATcoverage DO-178C/ED-12C Qualification Material" + f": {VAR_REPLACEMENTS["plans_doc_title"]}", + owner, + "manual", + ), +] diff --git a/qualification/qm/plans/content.rst b/qualification/plans/index.rst similarity index 66% rename from qualification/qm/plans/content.rst rename to qualification/plans/index.rst index 41b2e5526..8366db2e1 100644 --- a/qualification/qm/plans/content.rst +++ b/qualification/plans/index.rst @@ -10,9 +10,10 @@ GNATcoverage - |standard| Qualification Material: |plans_doc_title| |release| & |today| & Initial version -.. qmlink:: +.. toctree:: + :maxdepth: 1 - Introduction - Tool_Qualification_Plan - Tool_Configuration_Management_Plan - Tool_Quality_Assurance_Plan + Introduction/content + Tool_Qualification_Plan/content + Tool_Configuration_Management_Plan/content + Tool_Quality_Assurance_Plan/content diff --git a/qualification/qm/.qm/cnt_env.py/artifactstamp.json b/qualification/qm/.qm/cnt_env.py/artifactstamp.json deleted file mode 100644 index 467e491c5..000000000 --- a/qualification/qm/.qm/cnt_env.py/artifactstamp.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "content-kind": "content", - "signature": "5358c2c895991794a84246b9834b39dba9149e85", - "location": "default:///env.py", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/README_FIRST b/qualification/qm/README_FIRST deleted file mode 100644 index 539562898..000000000 --- a/qualification/qm/README_FIRST +++ /dev/null @@ -1,25 +0,0 @@ -To run the QM: - -* Download a recent wavefront (synchronize with the QM team for that) -* Unzip it (if on Windows) or untar it (on Unix). The created directory will be - denoted by . You can safely move it to any convenient - location. -* Make sure the bin directory is in your PATH: - on unix: export PATH=/bin:$PATH - on windows: right click on start menu->computer, select properties, - select advanced properties, environment variables, update the PATH definition - or define it to \bin;%PATH% -* In the directory containing this README file, using the command line: - - To run the qmachine with the GUI (requires gnatpython): - - ./genmodel.py --dolevel=doB - qmachine model.xml - - - To generate the documentation (html and pdf) - - qmachine model.xml -l scripts/generate_[tor|plans]_[html|pdf].py - - The documentation will be generated in the release folder - -Important Note: -In order to generate the PDF, you will need make, and LaTeX installed. diff --git a/qualification/qm/common_conf.py b/qualification/qm/common_conf.py deleted file mode 100644 index 1133511cb..000000000 --- a/qualification/qm/common_conf.py +++ /dev/null @@ -1,66 +0,0 @@ -from collections import OrderedDict -from datetime import date - -project_name = "GNATcoverage" -project_name_it = "*%s*" % project_name -owner = "AdaCore" - -users = { - "unassigned": { - "name": "Unassigned", - "company": "", - "email": "", - "team": "", - }, - "hainque": { - "name": "Olivier Hainque", - "company": owner, - "email": "hainque@adacore.com", - "team": "Qualification", - }, - "guitton": { - "name": "Jerome Guitton", - "company": owner, - "email": "guitton@adacore.com", - "team": "Qualification", - }, - "leguillou": { - "name": "Erwan Leguillou", - "company": owner, - "email": "leguillou@adacore.com", - "team": "Qualification", - }, - "fofanov": { - "name": "Vasily Fofanov", - "company": owner, - "email": "fofanov@adacore.com", - "team": "Qualification", - }, -} - -roles = OrderedDict( - [ - ("authors", {"description": "the authors of the document"}), - ] -) - -assignments = {"authors": ["hainque"]} - -release = "DRAFT 0.0" -version = "(version %s)" % release - -copyright = "%s, %d" % (owner, date.today().year) # noqa: A001 - -extensions = ["sphinx.ext.ifconfig"] - -# Parameters - which could be templated and instantiated -# from parameters known at higher levels of the kit production -# process: - -tor_doc_id = "PE." -str_doc_id = "PE." -plans_doc_id = "PE." - -gnatpro_version = "GNATPRO.X" -gprbuild_version = "GPRBUILD.Y" -gnatcov_version = "GNATCOV.Z" diff --git a/qualification/qm/env/env.py b/qualification/qm/env/env.py deleted file mode 100644 index 76339cade..000000000 --- a/qualification/qm/env/env.py +++ /dev/null @@ -1,9 +0,0 @@ -{ - "gnat": "powerpc-elf", - "version": "7.0.3", - "switches": ["-O1 -fpreserve-control-flow"], - "coding standard": "", - "project_full": "SomeProject", -} - -# flake8: noqa diff --git a/qualification/qm/genmodel.py b/qualification/qm/genmodel.py deleted file mode 100755 index 823074317..000000000 --- a/qualification/qm/genmodel.py +++ /dev/null @@ -1,191 +0,0 @@ -#!/usr/bin/env python - -# Generate the "model.xml" file from which the qm driven document -# generators will work, with 2 specifities driven by info provided -# on the command line: -# -# * The target do-level, which lets us include level-specific -# directories that the QM will look into for e.g. TOR artifacts -# (typical example is the doB specific testcases for DC on non -# short-circuit operators) -# -# * The target Ada language version, so we can focus the LRM -# traceability matrix production (and maybe the set of TORs -# and testcases someday) - -import optparse -import re -import sys - - -def exit_if(p, msg): - if p: - print(msg) - sys.exit(1) - - -def contents_of(filename): - with open(filename) as fd: - return fd.read() - - -def __extra_block_for(dolevel): - """Allow level specific local subsets of testcases.""" - - return f""" - - - - - -""" - - -RE_LANG = "([a-zA-Z]*)([0-9]*)" - - -def __langdir_for(lang): - # Requirements for all the versions Ada are all under Ada/ etc; - # only keep the non-digital start of the language name as the subdir - # to search: - return re.match(RE_LANG, string=lang).group(1) - - -def __langversion_for(lang): - return re.match(RE_LANG, string=lang).group(2) - - -def __reqset_triggers_for(lang, chapter): - return "\n".join( - ( - "", - ) - ) - - -def __langlevel_triggers_for(dolevel, languages): - """Triggers so only the language/criterion sections of relevance - are included.""" - - chapters_for = { - "doC": ["stmt"], - "doB": ["stmt", "decision"], - "doA": ["stmt", "decision", "mcdc"], - } - - return "\n" + "\n".join( - ( - __reqset_triggers_for(lang, chapter) - for lang in languages - for chapter in chapters_for[dolevel] - ) - ) - - -def __gen_model_for(dolevel, languages): - """Generate model.xml from template.xml""" - - # We expect one version of Ada to be part of the language set - - ada_lang = [lang for lang in languages if "Ada" in lang][0] - - with open("model.xml", "w") as f: - f.write( - contents_of("template.xml") - % { - "langlevel_reqset_triggers": __langlevel_triggers_for( - dolevel=dolevel, languages=languages - ), - "ada_version": __langversion_for(ada_lang), - "extra_block": __extra_block_for(dolevel=dolevel), - } - ) - - -def __gen_lrm_ref_for(lang): - """Generate lrm_ref_.txt from lrm_ref.txt, filtering - out the lines that don't apply to (extracted from the - input LANGuage name.""" - - lang_version = __langversion_for(lang) - - # The reference matrix lines with section numbers and corresponding - # language versions are of the form: - # - # # # # # - # - # language versions are shortened to their last two digits, - # for example: - # - # 13.8 # 95,05,12 # Machine Code # yes # - - # Produce an output file which has all the lines of the input one - # except those corresponding to sections not for the targeted language. - - short_version = lang_version[-2:] - - with open("LRM/lrm_ref.txt", mode="r") as inf: - with open("LRM/lrm_ref_%s.txt" % lang_version, mode="w") as outf: - for line in inf: - m = re.match(pattern="([0-9. ]*)#([0-9, ]*?)#", string=line) - if m and short_version not in m.group(2): - continue - - outf.write(line) - - -# ======================================================================= -# == MAIN SCRIPT BODY == -# ======================================================================= - -valid_dolevels = ("doA", "doB", "doC") -valid_languages = ("Ada95", "Ada2005", "Ada2012") - -if __name__ == "__main__": - op = optparse.OptionParser(usage="%prog ") - - op.add_option( - "--dolevel", - dest="dolevel", - default=None, - type="choice", - choices=valid_dolevels, - help=( - "Target DO178 qualification level. One of %s." - % valid_dolevels.__str__() - ), - ) - - op.add_option( - "--languages", - dest="languages", - default=None, - help=( - "comma separated list of languages amongst %s" - % valid_languages.__str__() - ), - ) - - (options, args) = op.parse_args() - - exit_if(not options.dolevel, "Please specify a DO level (--dolevel).") - - exit_if(not options.languages, "Please specify languages (--languages).") - - languages = options.languages.split(",") - - # should check that there is only one instance of a given - # language (e.g. only one Ada) - - __gen_model_for(dolevel=options.dolevel, languages=languages) - - [__gen_lrm_ref_for(lang=lang) for lang in languages if "Ada" in lang] diff --git a/qualification/qm/plans/.qm/artifactstamp.json b/qualification/qm/plans/.qm/artifactstamp.json deleted file mode 100644 index 7d7d9d5e5..000000000 --- a/qualification/qm/plans/.qm/artifactstamp.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/content.rst": "ee5d37c85291ef70f198197d8277bf0031c4ba36", - "default:///plans/qmconf.py": "ef65551845c160016f1c6a064acf7eb377a9485a" - }, - "location": "default:///plans", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Introduction/.qm/artifactstamp.json b/qualification/qm/plans/Introduction/.qm/artifactstamp.json deleted file mode 100644 index fee95daa0..000000000 --- a/qualification/qm/plans/Introduction/.qm/artifactstamp.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/Documentation_Introduction/content.rst": "58c64e74ae5f2a14f8f80a4551dbd8399b1b30af" - }, - "location": "default:///plans/Documentation_Introduction", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Introduction/content.rst b/qualification/qm/plans/Introduction/content.rst deleted file mode 100644 index 81cfe7ebd..000000000 --- a/qualification/qm/plans/Introduction/content.rst +++ /dev/null @@ -1,11 +0,0 @@ -============ -Introduction -============ - -.. qmlink:: - - Document_Purpose - Referenced_Documents - Definitions - Organization_And_Roles - diff --git a/qualification/qm/plans/Tool_Configuration_Management_Plan/.qm/artifactstamp.json b/qualification/qm/plans/Tool_Configuration_Management_Plan/.qm/artifactstamp.json deleted file mode 100644 index d510e8739..000000000 --- a/qualification/qm/plans/Tool_Configuration_Management_Plan/.qm/artifactstamp.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/Software_Configuration_Management_Plan/content.rst": "49090be777e8db68e6f42042cdc1b56921fed642" - }, - "location": "default:///plans/Software_Configuration_Management_Plan", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Tool_Qualification_Plan/.qm/artifactstamp.json b/qualification/qm/plans/Tool_Qualification_Plan/.qm/artifactstamp.json deleted file mode 100644 index 9cee7f273..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/.qm/artifactstamp.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/Tool_Qualification_Plan/content.rst": "9107595cbe85926f695d71d01f3aa73b192ebe4c" - }, - "location": "default:///plans/Tool_Qualification_Plan", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Operational_Conditions/.qm/artifactstamp.json b/qualification/qm/plans/Tool_Qualification_Plan/Operational_Conditions/.qm/artifactstamp.json deleted file mode 100644 index 6ed03541b..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/Operational_Conditions/.qm/artifactstamp.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/Tool_Qualification_Plan/Environment_Equivalence/content.rst": "4c4b3b0cb6ca7af7026dcd008f15bc6d022db0f0" - }, - "location": "default:///plans/Tool_Qualification_Plan/Environment_Equivalence", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Tool_Qualification_Plan/Tool_Overview/.qm/artifactstamp.json b/qualification/qm/plans/Tool_Qualification_Plan/Tool_Overview/.qm/artifactstamp.json deleted file mode 100644 index b772f14bb..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/Tool_Overview/.qm/artifactstamp.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/Tool_Qualification_Plan/Tool_Overview/content.rst": "62c9dd406c5253722e013bcfb4fc1919cef2d1fd" - }, - "location": "default:///plans/Tool_Qualification_Plan/Tool_Overview", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/.qm/artifactstamp.json b/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/.qm/artifactstamp.json deleted file mode 100644 index f6a8beb3d..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/User_Activities/.qm/artifactstamp.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "content-kind": "container", - "signature": { - "default:///plans/Tool_Qualification_Plan/User_Activities/content.rst": "7b61cda26525a947e1ec27e878d4110a3c6027d4" - }, - "location": "default:///plans/Tool_Qualification_Plan/User_Activities", - "dependencies": [ - ] -} \ No newline at end of file diff --git a/qualification/qm/plans/Tool_Qualification_Plan/content.rst b/qualification/qm/plans/Tool_Qualification_Plan/content.rst deleted file mode 100644 index 0a1832dc9..000000000 --- a/qualification/qm/plans/Tool_Qualification_Plan/content.rst +++ /dev/null @@ -1,15 +0,0 @@ -======================= -Tool Qualification Plan -======================= - -.. qmlink:: - - Qualification_Data_Overview - Compliance - Tool_Overview - Certification_Credit - Tool_Qualification_Level - Data_Production - Qualified_Interface - Operational_Conditions - User_Activities diff --git a/qualification/qm/plans/qmconf.py b/qualification/qm/plans/qmconf.py deleted file mode 100644 index a5e760896..000000000 --- a/qualification/qm/plans/qmconf.py +++ /dev/null @@ -1,26 +0,0 @@ -# This file gets copied by sphinx as something like: -# .../qualification/qm/.qm/PLANS/_sphinx/conf.py -# -# and the common configuration file is in qualification/qm ... - -common_file = os.path.join( - os.path.dirname( - os.path.dirname( - os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - ) - ), - "common_conf.py", -) - -if os.path.isfile(common_file): - execfile(common_file) - execfile(os.path.join(os.path.dirname(common_file), "qm_prolog.py")) -else: - print("Couldn't find common configuration file") - print(common_file) - print("from: %s" % __file__) - -doc_id = plans_doc_id - - -# flake8: noqa diff --git a/qualification/qm/qm_plugins/generate_doc.py b/qualification/qm/qm_plugins/generate_doc.py deleted file mode 100644 index 4388dfcd0..000000000 --- a/qualification/qm/qm_plugins/generate_doc.py +++ /dev/null @@ -1,62 +0,0 @@ -import os.path -import qm -import qm.rest.pdfgenerator - - -def get_userconf(): - # retrieve the author from the environment data artifact - env = os.path.join(os.path.dirname(os.path.dirname(__file__)), "env.py") - with open(env, "r") as fd: - envdata = eval(fd.read()) - - author = "AdaCore for %s" % (envdata["project_full"]) - - return author - - -class GenPDF(qm.rest.pdfgenerator.SphinxGeneratePdf): - def userconf(self): - # use method from super just to retrieve the 'extras' field - [ - author, - version, - extras, - ] = qm.rest.pdfgenerator.SphinxGeneratePdf.userconf(self) - author = get_userconf() - - return [author, version, extras] - - -class GenHTML(qm.rest.pdfgenerator.SphinxGenerateHtml): - def userconf(self): - # use method from super just to retrieve the 'extras' field - [ - author, - version, - extras, - ] = qm.rest.pdfgenerator.SphinxGenerateHtml.userconf(self) - author = get_userconf() - - return [author, version, extras] - - -def _generate(name, path, generator): - root = None - top = qm.get_toplevel_artifacts() - for artifact in top: - if artifact.name == name: - root = artifact - break - if root is None: - qm.log_error("Cannot find an artifact named " + name) - else: - full = os.path.abspath(path) - generator.execute(root, full) - - -def generate_pdf(name, path): - _generate(name, os.path.join(path, "%s.pdf" % name), GenPDF()) - - -def generate_html(name, path): - _generate(name, path, GenHTML()) diff --git a/qualification/qm/qm_prolog.py b/qualification/qm/qm_prolog.py deleted file mode 100644 index 8350484d3..000000000 --- a/qualification/qm/qm_prolog.py +++ /dev/null @@ -1,81 +0,0 @@ -import os - -opcond_section_title = "Operational Conditions of Use" -torintro_section_title = "Document Purpose and Organization" -testproc_section_title = "Overview of the Test Procedures Organization" - -rst_prolog = ( - writer.macro("project_command", "``gnatcov``") - + writer.role("raw-latex", r"\renewcommand{\labelitemi}{$\bullet$}") - + "\n\n" - + writer.role("raw-latex", r"\renewcommand{\labelitemii}{$\circ$}") - + "\n\n" - + writer.role("raw-latex", r"\renewcommand{\labelitemiii}{$\cdots$}") - + "\n\n" - + writer.role("raw-latex", r"\renewcommand{\labelitemiv}{$-$}") - + "\n\n" - + writer.macro("adacore", "AdaCore") - + writer.macro("gnatpro", "GNAT Pro") - + writer.macro("gnatpro_it", "*GNAT Pro*") - + writer.macro("gnatpro_bold", "**GNAT Pro**") - + writer.macro("Ada83", "`Ada 83`") - + writer.macro("Ada95", "`Ada 95`") - + writer.macro("Ada05", "`Ada 2005`") - + writer.macro("Ada12", "`Ada 2012`") - + writer.macro("QA", "Quality Assurance") - + writer.macro("plans_pdf", r"``PLANS.pdf``") - + writer.macro("tor_pdf", r"``TOR.pdf``") - + writer.macro("str_pdf", r"``STR.pdf``") - + writer.macro("tqa_file", r"``qa.doc``") - + writer.macro("tors", r"Tool Operational Requirements") - + writer.macro("plans_doc_title", r"*Qualification Plans*") - + writer.macro( - "tor_doc_title", - r"*Tool Operational Requirements and V&V Cases and Procedures*", - ) - + writer.macro( - "str_doc_title", - r"*Tool Operational Verification and Validation Results*", - ) - + writer.macro("tqa_doc_title", r"*Tool Quality Assurance Records*") - + writer.macro("plans_doc", r"*PLANS*") - + writer.macro("tor_doc", r"*TOR*") - + writer.macro("str_doc", r"*STR*") - + writer.macro("tqa_doc", "|tqa_doc_title|") - + writer.macro("plans_doc_id", r"*" + plans_doc_id + r"*") - + writer.macro("tor_doc_id", r"*" + tor_doc_id + r"*") - + writer.macro("str_doc_id", r"*" + str_doc_id + r"*") - + writer.macro("gnatcov_version", r"%s" % gnatcov_version) - + writer.macro("gnatpro_version", r"%s" % gnatpro_version) - + writer.macro("gprbuild_version", r"%s" % gprbuild_version) - + writer.macro("opcond_section_title", r"%s" % opcond_section_title) - + writer.macro("opcond_section_title_ref", r"*%s*" % opcond_section_title) - + writer.macro("torintro_section_title", r"%s" % torintro_section_title) - + writer.macro( - "torintro_section_title_ref", r"*%s*" % torintro_section_title - ) - + writer.macro("testproc_section_title", r"%s" % testproc_section_title) - + writer.macro( - "testproc_section_title_ref", r"*%s*" % testproc_section_title - ) - + writer.macro("DAL", "Design Assurance Level") - + writer.macro("PSAC", "Plan for Software Aspects of Certification") - + writer.macro( - "PSAC_bold", "**Plan for Software Aspects of Certification**" - ) - + writer.macro("V&V", "Verification and Validation") - + writer.macro( - "RAMS", "Reliability, Availability, Maintainability and Safety" - ) - + writer.macro("ARM", "Ada Reference Manual") - + writer.macro("standard", "DO-178C/ED-12C") - + writer.macro("tool_standard", "DO-330/ED-215") - + writer.macro("client", "`GENERIC CLIENT`") -) - -# We expect to be called through genbundle.py, which should export an -# environment variable stating what --dolevel it was passed ('doA', 'doB', -# or 'doC'). Expose the significant letter to documents: -rst_prolog += writer.macro("dolevel", os.environ.get("GENBUNDLE_DOLEVEL")[-1]) - -# flake8: noqa diff --git a/qualification/qm/scripts/generate_plans_html.py b/qualification/qm/scripts/generate_plans_html.py deleted file mode 100644 index 3bfa3ef63..000000000 --- a/qualification/qm/scripts/generate_plans_html.py +++ /dev/null @@ -1,6 +0,0 @@ -import generate_doc - -# Locate the output as the other sphinx-based components do, facilitating the -# toplevel driver for qmat generation. Not an unreasonable name anyway. - -generate_doc.generate_html("PLANS", "build/html") diff --git a/qualification/qm/scripts/generate_plans_pdf.py b/qualification/qm/scripts/generate_plans_pdf.py deleted file mode 100644 index d50cd6976..000000000 --- a/qualification/qm/scripts/generate_plans_pdf.py +++ /dev/null @@ -1,6 +0,0 @@ -import generate_doc - -# Locate the output as the other sphinx-based components do, facilitating the -# toplevel driver for qmat generation. Not an unreasonable name anyway. - -generate_doc.generate_pdf("PLANS", "build/latexpdf") diff --git a/qualification/qm/scripts/generate_tor_html.py b/qualification/qm/scripts/generate_tor_html.py deleted file mode 100644 index cb6b1e713..000000000 --- a/qualification/qm/scripts/generate_tor_html.py +++ /dev/null @@ -1,6 +0,0 @@ -import generate_doc - -# Locate the output as the other sphinx-based components do, facilitating the -# toplevel driver for qmat generation. Not an unreasonable name anyway. - -generate_doc.generate_html("TOR", "build/html") diff --git a/qualification/qm/scripts/generate_tor_pdf.py b/qualification/qm/scripts/generate_tor_pdf.py deleted file mode 100644 index 8bc6c5d8b..000000000 --- a/qualification/qm/scripts/generate_tor_pdf.py +++ /dev/null @@ -1,6 +0,0 @@ -import generate_doc - -# Locate the output as the other sphinx-based components do, facilitating the -# toplevel driver for qmat generation. Not an unreasonable name anyway. - -generate_doc.generate_pdf("TOR", "build/latexpdf") diff --git a/qualification/qm/template.xml b/qualification/qm/template.xml deleted file mode 100644 index a9ff80221..000000000 --- a/qualification/qm/template.xml +++ /dev/null @@ -1,421 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %(langlevel_reqset_triggers)s - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - %(extra_block)s - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/qualification/scripts/__init__.py b/qualification/scripts/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/qualification/scripts/common_conf.py b/qualification/scripts/common_conf.py new file mode 100644 index 000000000..0bf747e22 --- /dev/null +++ b/qualification/scripts/common_conf.py @@ -0,0 +1,168 @@ +from collections import OrderedDict +from datetime import date + +project_name = "GNATcoverage" +project_name_it = "*%s*" % project_name +owner = "AdaCore" + +users = { + "unassigned": { + "name": "Unassigned", + "company": "", + "email": "", + "team": "", + }, + "hainque": { + "name": "Olivier Hainque", + "company": owner, + "email": "hainque@adacore.com", + "team": "Qualification", + }, + "guitton": { + "name": "Jerome Guitton", + "company": owner, + "email": "guitton@adacore.com", + "team": "Qualification", + }, + "leguillou": { + "name": "Erwan Leguillou", + "company": owner, + "email": "leguillou@adacore.com", + "team": "Qualification", + }, + "fofanov": { + "name": "Vasily Fofanov", + "company": owner, + "email": "fofanov@adacore.com", + "team": "Qualification", + }, +} + +roles = OrderedDict( + [ + ("authors", {"description": "the authors of the document"}), + ] +) + +assignments = {"authors": ["hainque"]} + +release = "DRAFT 0.0" +version = "(version %s)" % release + +copyright = "%s, %d" % (owner, date.today().year) # noqa: A001 + +extensions = ["sphinx.ext.ifconfig"] + +# Parameters - which could be templated and instantiated +# from parameters known at higher levels of the kit production +# process: + +tor_doc_id = "PE." +str_doc_id = "PE." +plans_doc_id = "PE." + +gnatpro_version = "GNATPRO.X" +gprbuild_version = "GPRBUILD.Y" +gnatcov_version = "GNATCOV.Z" + +opcond_section_title = "Operational Conditions of Use" +torintro_section_title = "Document Purpose and Organization" +testproc_section_title = "Overview of the Test Procedures Organization" + +VAR_REPLACEMENTS = { + "project_name": project_name, + "project_name_bold": "**%s**" % project_name, + "project_name_it": "*%s*" % project_name, + "current_version": version, + "project_command": "``gnatcov``", + "adacore": "AdaCore", + "gnatpro": "GNAT Pro", + "gnatpro_it": "*GNAT Pro*", + "gnatpro_bold": "**GNAT Pro**", + "Ada83": "`Ada 83`", + "Ada95": "`Ada 95`", + "Ada05": "`Ada 2005`", + "Ada12": "`Ada 2012`", + "Ada22": "`Ada 2022`", + "QA": "Quality Assurance", + "plans_pdf": r"``PLANS.pdf``", + "tor_pdf": r"``TOR.pdf``", + "str_pdf": r"``STR.pdf``", + "tqa_file": r"``qa.doc``", + "tors": r"Tool Operational Requirements", + "plans_doc_title": r"*Qualification Plans*", + "tor_doc_title": ( + r"*Tool Operational Requirements and V&V Cases and Procedures*" + ), + "str_doc_title": r"*Tool Operational Verification and Validation Results*", + "tqa_doc_title": r"*Tool Quality Assurance Records*", + "plans_doc": r"*PLANS*", + "tor_doc": r"*TOR*", + "str_doc": r"*STR*", + "tqa_doc": "|tqa_doc_title|", + "plans_doc_id": r"*" + plans_doc_id + r"*", + "tor_doc_id": r"*" + tor_doc_id + r"*", + "str_doc_id": r"*" + str_doc_id + r"*", + "gnatcov_version": r"%s" % gnatcov_version, + "gnatpro_version": r"%s" % gnatpro_version, + "gprbuild_version": r"%s" % gprbuild_version, + "opcond_section_title": r"%s" % opcond_section_title, + "opcond_section_title_ref": r"*%s*" % opcond_section_title, + "torintro_section_title": r"%s" % torintro_section_title, + "torintro_section_title_ref": r"*%s*" % torintro_section_title, + "testproc_section_title": r"%s" % testproc_section_title, + "testproc_section_title_ref": r"*%s*" % testproc_section_title, + "DAL": "Design Assurance Level", + "PSAC": "Plan for Software Aspects of Certification", + "PSAC_bold": "**Plan for Software Aspects of Certification**", + "V&V": "Verification and Validation", + "ARM": "Ada Reference Manual", + "standard": "DO-178C/ED-12C", + "tool_standard": "DO-330/ED-215", + "client": "`GENERIC CLIENT`", + "current_authors": ( + owner + if not assignments + else ", ".join([name.capitalize() for name in assignments["authors"]]) + ), + "release": release, + "version": version, +} + +rst_prolog = """ +.. |LF| raw:: latex + + \\\\ + +.. |newline| raw:: latex + + \\newline + + + +.. |nbsp| raw:: latex + + ~ + + + +.. |pagebreak| raw:: latex + + \\newpage + +.. role:: raw-latex(raw) + :format: latex + +:raw-latex:`\\renewcommand{\\labelitemi}{$\\bullet$}` +:raw-latex:`\\renewcommand{\\labelitemii}{$\\circ$}` +:raw-latex:`\\renewcommand{\\labelitemiii}{$\\cdots$}` +:raw-latex:`\\renewcommand{\\labelitemiv}{$-$}` + +.. role:: raw-html(raw) + :format: html +""" + "\n\n".join( + [ + f".. |{key}| replace:: {VAR_REPLACEMENTS[key]}" + for key in VAR_REPLACEMENTS + ] +) diff --git a/qualification/scripts/logger.py b/qualification/scripts/logger.py new file mode 100644 index 000000000..fbe006c98 --- /dev/null +++ b/qualification/scripts/logger.py @@ -0,0 +1,93 @@ +############################################################################ +# # +# The Qualifying Machine (QM) # +# # +# Copyright (C) 2010-2024, AdaCore # +# # +# The QM 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. The QM 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 the QM; see file COPYING3. If # +# not, write to the Free Software Foundation, 59 Temple Place - Suite # +# 330, Boston, MA 02111-1307, USA. # +# # +############################################################################ + +"""Module providing a message logger""" + +from enum import Enum + + +class Log_Level_Kind(Enum): + DEBUG = 1 + VERBOSE = 2 + INFO = 3 + WARNING = 4 + ERROR = 5 + + +current_level = Log_Level_Kind.VERBOSE + + +def print_msg(prefix, msg: str) -> None: + print(prefix + ": " + msg) + + +def log_error(msg: str) -> None: + """ + Logs an error message. + Error messages are always displayed. + """ + print_msg("ERROR", msg) + + +def log_warning(msg: str) -> None: + """ + Logs a warning message. + Warnings are always displayed + + :param msg: the message + :type msg: a string + """ + if current_level <= Log_Level_Kind.WARNING: + print_msg("WARNING", msg) + + +def log_info(msg: str) -> None: + """ + Logs an informative message. Such message is displayed by default, unless + the QM is run using -v or -d switches. + + :param msg: the message + :type msg: a string + """ + if current_level <= Log_Level_Kind.INFO: + print_msg("INFO", msg) + + +def log_verbose(msg: str) -> None: + """ + Logs a message that is only displayed when the QM is run is verbose + mode or debug mode (respectively -v switch and -d switches). + + :param msg: the message + :type msg: a string + """ + if current_level <= Log_Level_Kind.VERBOSE: + print_msg("VERBOSE", msg) + + +def log_debug(msg: str) -> None: + """ + Logs an debug message. + Such message is not displayed, unless in debug mode (-d switch) + + :param msg: the message + :type msg: a string + """ + if current_level <= Log_Level_Kind.DEBUG: + print_msg("DEBUG", msg) diff --git a/qualification/scripts/missing_tr_log.txt b/qualification/scripts/missing_tr_log.txt new file mode 100644 index 000000000..e69de29bb diff --git a/qualification/scripts/qm_plugins/__init__.py b/qualification/scripts/qm_plugins/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/qualification/qm/qm_plugins/importers.py b/qualification/scripts/qm_plugins/importers.py similarity index 74% rename from qualification/qm/qm_plugins/importers.py rename to qualification/scripts/qm_plugins/importers.py index 5926e946d..fa13157c5 100644 --- a/qualification/qm/qm_plugins/importers.py +++ b/qualification/scripts/qm_plugins/importers.py @@ -1,79 +1,66 @@ -import qm -from qm.rest import ArtifactImporter, writer -from qm.rest.pdfgenerator import artifact_hash -from itertools import izip_longest +from __future__ import annotations + +from scripts.rest import ArtifactImporter, DefaultImporter, writer + +from itertools import zip_longest from collections import OrderedDict -import re import os +# FIXME +# MISSING_TR_LOG = os.path.join(get_project_dir(), "missing_tr_log.txt") +MISSING_TR_LOG = "missing_tr_log.txt" + + +def resolve_importer(qmlink_txt: str) -> ArtifactImporter | None: + """Return importer corresponding to the qmlink text""" -MISSING_TR_LOG = os.path.join(qm.get_project_dir(), "missing_tr_log.txt") + # get importer name + importer_name = qmlink_txt.partition("\n")[0][ + len(ArtifactImporter.QMLINK_TAG) : + ].strip() + + # get importer + importer = ArtifactImporter.new(importer_name) + return importer def class_to_string(a): """ Returns the two or three letters string - refering to the class of the artifact 'a' if defined, + referring to the class of the artifact 'a' if defined, the name of the class otherwise. :param a: the artifact :type a: artifact """ - d = {"TORReq_Set": "rqg", "TORReq": "rq", "TC": "tc", "TC_Set": "tcg"} - if "Appendix" in a.full_name: + if "Appendix" in a.id: return "app" elif a.name == "OpEnviron": return "env" - elif a.__class__.__name__ in d: - return d[a.__class__.__name__] + elif is_reqset(a): + return "rqg" + elif is_req(a): + return "rq" + elif is_tc(a): + return "tc" + elif is_tcset(a): + return "tcg" else: return a.__class__.__name__ -def class_to_content_key(a): - """ - Returns key name for the main content of an artifact - which is a container. (defined in xml model). - - :param a: the artifact - :type a: artifact - """ - - # keys in the model are dependant of the artifact class - d = { - "TORReq_Set": "set_content", - "TORReq": "requirement", - "TC": "tc_content", - "TC_Set": "tc_set_content", - } - - if "Appendix" in a.full_name: - return "app" - elif a.name == "OpEnviron": - # OpEnv only is content, not container - return None - elif a.__class__.__name__ in d: - return d[a.__class__.__name__] - else: - return None - - ########################### # Tests on artifact class # ########################### def is_req(a): - from qm import TORReq - - return isinstance(a, TORReq) + return getattr(a, "req", False) def is_reqset(a): - from qm import TORReq_Set - - return isinstance(a, TORReq_Set) + return getattr(a, "reqset", False) def is_req_or_set(a): @@ -81,43 +68,42 @@ def is_req_or_set(a): def is_tc(a): - from qm import TC - - return isinstance(a, TC) - + return getattr(a, "tc", False) or getattr(a, "htc", False) -def is_tcset(a): - from qm import TC_Set - return isinstance(a, TC_Set) +def is_tcset(a, extended: bool = False): + """Return True if tcset attribute is set + If extended if True then return true also when + the type is unknown, but some of the children are tc + """ + if extended: + return getattr(a, "ext_tcset", False) + else: + return getattr(a, "tcset", False) -def is_tc_or_set(a): - return is_tc(a) or is_tcset(a) +def is_tc_or_set(a, extended: bool = False): + return is_tc(a) or is_tcset(a, extended) def is_test_result(a): - from qm import TR - - return isinstance(a, TR) + # FIXME + return False def is_lrm_section(a): - from qm import LRM_Section - - return isinstance(a, LRM_Section) + # FIXME + return False def is_source(a): - from qm import Source_files - - return isinstance(a, Source_files) + # FIXME + return False def is_consolidation(a): - from qm import Conso_Sources - - return isinstance(a, Conso_Sources) + # FIXME + return False def is_helper(source_resource): @@ -125,7 +111,7 @@ def is_helper(source_resource): def is_driver(source_resource): - # a resource named with "test_" is necsseraly a 'driver' + # a resource named with "test_" is necessarily a 'driver' return "test_" in source_resource.basename @@ -148,29 +134,6 @@ def is_functional(source_resource): ######### -def get_short_description(artifact): - """ - Get the first line of a file as the short description. - Layout elements are removed from the description. - - :param artifact: the artifact - :type artifact: artifact - """ - - for item in artifact.contents(class_to_content_key(artifact)): - content = item.get_content() - - for line in content.splitlines(): - line = line.strip() - if len(line) > 0: - # ** has to be removed - # from short_description when used in tables - first_line = line.replace("**", "") - break - - return first_line - - def get_first_req_relative(artifact): """ Returns the first parent which is a req. @@ -234,29 +197,6 @@ def short_kind_of(artifact): return "Group" if "Group" in kind else kind -def relative_links_for(artifact): - """ - :param artifact: the artifact - :type artifact: artifact - """ - output = "" - - req = get_first_req_relative(artifact) - if req: - output += writer.paragraph( - "**Parent Requirement**: %s\n\n" % writer.qmref(req.full_name) - ) - - ancestor = artifact.relative_to - if ancestor and ancestor != req: - output += writer.paragraph( - "**Parent %s**: %s\n\n" - % (short_kind_of(ancestor), write_artifact_ref(ancestor.full_name)) - ) - - return output - - def default_importer(artifact): """ Returns the importer whom the to_rest() method @@ -269,8 +209,10 @@ def default_importer(artifact): return RequirementImporter() elif is_tcset(artifact): return TCSetImporter() + elif is_tc(artifact): + return TestCaseImporter() else: - return qm.rest.DefaultImporter() + return DefaultImporter() #################################################################### @@ -281,6 +223,9 @@ class LRMTableImporter(ArtifactImporter): """ The specific importer to generate the Traceability matrix between reference manual and testcases and requirements + + TODO: This is currently not used, but we keep the code around in case we + want to restore the LRMEF table generation. """ def qmlink_to_rest(self, parent, artifacts): @@ -303,6 +248,7 @@ def qmlink_to_rest(self, parent, artifacts): for a in artifacts: if is_lrm_section(a): + if not language_version: language_version = a.attributes["language"].strip() @@ -310,16 +256,13 @@ def qmlink_to_rest(self, parent, artifacts): for children in a.derived_to: for child in children.all: if is_tc(child): - parent = get_first_req_relative(child).full_name + parent = get_first_req_relative(child).id if parent not in ref.keys(): ref[parent] = [] ref[parent].append( - [ - child.full_name, - child.full_name.replace(parent, ""), - ] + [child.id, child.id.replace(parent, "")] ) pdf_tc_list = "" @@ -328,6 +271,7 @@ def qmlink_to_rest(self, parent, artifacts): html_comment = "" for req in ref.keys(): + pdf_other_tcs = "" html_tcs = "" @@ -461,7 +405,7 @@ def qmlink_to_rest(self, parent, artifacts): pdf_items.append( [ - "%s" % a.full_name.replace("/", ""), + "%s" % a.id.replace("/", ""), a.attributes["title"].strip(), relevance, pdf_comment, @@ -470,7 +414,7 @@ def qmlink_to_rest(self, parent, artifacts): html_items.append( [ - "%s" % a.full_name.replace("/", ""), + "%s" % a.id.replace("/", ""), a.attributes["title"].strip(), relevance, html_comment, @@ -482,7 +426,7 @@ def qmlink_to_rest(self, parent, artifacts): title="TOR/LRM Traceability Matrix for Ada %s" % language_version, headers=["Section", "Title", "Applicable", "Comment"], latex_format=r"|p{0.08\linewidth}|p{0.20\linewidth}|" - + r"p{0.10\linewidth}|p{0.50\linewidth}|", + r"p{0.10\linewidth}|p{0.50\linewidth}|", ) html_table = writer.csv_table( @@ -493,10 +437,10 @@ def qmlink_to_rest(self, parent, artifacts): output += ( writer.paragraph( - "This particular table is established for **Ada %s**." - "\n\\The requirement identifiers in this table were shortened" - " by removing the *%s* common prefix.\n\n" - % (language_version, REQ_NAME_PREFIX) + "This particular table is established for **Ada %s**.\n\n" + % language_version + + r"the requirement identifiers in this table were shortened " + "by removing the *%s* common prefix.\n\n" % REQ_NAME_PREFIX ) + writer.only(pdf_table, "latex") + writer.only(html_table, "html") @@ -508,10 +452,11 @@ def qmlink_to_rest(self, parent, artifacts): class TCIndexImporter(ArtifactImporter): + def get_recursive_relatives(self, artifact, depth): """ Returns the list of the tc or tc_set children of an artifact - and recurcively the children of its children until the + and recursively the children of its children until the required depth :param artifact: @@ -523,7 +468,7 @@ def get_recursive_relatives(self, artifact, depth): result = [] for child in artifact.relatives: - if is_tc_or_set(child): + if is_tc_or_set(child, extended=True): result.append(child) if depth > 1: result += self.get_recursive_relatives(child, depth - 1) @@ -531,43 +476,44 @@ def get_recursive_relatives(self, artifact, depth): return result def qmlink_to_rest(self, parent, artifacts): + html_items = [] pdf_items = [] output = "" + docrefs = set() for a in artifacts: # Don't put sources in the tables if is_source(a): continue - if is_tc_or_set(a): - reference = write_artifact_ref( - a.full_name, get_short_description(a) - ) - - html_items.append( - [ - writer.strong(class_to_string(a)), - writer.strong(a.name), - reference, - ] - ) - pdf_items.append([class_to_string(a), a.name, reference]) - for suba in self.get_recursive_relatives(a, 1): - # We do include in the table children artifacts only - # in html format. - - if is_tc(suba): - subref = write_artifact_ref( - suba.full_name, get_short_description(suba) - ) - - if is_tcset(suba): - subref = writer.qmref(suba.full_name) + if is_tc_or_set(a, extended=True): + reference = a.rest_doc_ref() + docrefs.add(a.docfile()) html_items.append( - [class_to_string(suba), "`..` %s" % suba.name, subref] + [ + writer.strong(class_to_string(a)), + writer.strong(a.name), + reference, + ] ) + pdf_items.append([class_to_string(a), a.name, reference]) + for suba in self.get_recursive_relatives(a, 1): + # We do include in the table children artifacts only + # in html format. + + if is_tc(suba) or is_tcset(suba, extended=True): + subref = suba.rest_doc_ref() + + html_items.append( + [ + class_to_string(suba), + "`..` %s" % suba.name, + subref, + ] + ) + docrefs.add(suba.docfile()) html_table = writer.csv_table( html_items, @@ -595,11 +541,11 @@ def qmlink_to_rest(self, parent, artifacts): links.append((a, default_importer(a))) output += writer.toctree( - [ - "/%s/content" % artifact_hash(*link) - for link in links - if not is_tc_or_set(link[0]) or is_tc_or_set(parent) - ], + # [lnk[0].docfile() + # for lnk in links + # if not is_tc_or_set(lnk[0]) or is_tc_or_set(parent)], + # [lnk[0].docfile() for lnk in links], + docrefs, hidden=True, ) @@ -607,6 +553,7 @@ def qmlink_to_rest(self, parent, artifacts): class AppIndexImporter(ArtifactImporter): + def qmlink_to_rest(self, parent, artifacts): return "", [] @@ -618,19 +565,12 @@ class RequirementImporter(ArtifactImporter): def to_rest(self, artifact): """ - Returns the 'rest' content of a requirement having the - macro %REQ_ID% replaced by the requirement fullname + Returns the 'rest' content of a requirement with artifact + type and ID on the first line """ - reference = ".. _%s:\n\n" % artifact.full_name.replace("/", "_")[1:] - - result = qm.rest.DefaultImporter().to_rest(artifact) + "\n\n" - - result = reference + re.sub( - pattern="%REQ_ID%", - repl="**REQUIREMENT** %s" % artifact.full_name, - string=result, - ) + result = ".. _%s:\n\n" % artifact.id.replace("/", "_")[1:] + result += DefaultImporter().to_rest(artifact) + "\n\n" return result @@ -647,11 +587,11 @@ def to_rest(self, artifact): in order to keep them close in the final pdf generation """ - reference = ".. _%s:\n\n" % artifact.full_name.replace("/", "_")[1:] + reference = ".. _%s:\n\n" % artifact.id.replace("/", "_")[1:] result = "" qmlink = "" in_qmlink = False - content = qm.rest.DefaultImporter().to_rest(artifact) + content = DefaultImporter().to_rest(artifact) for line in content.splitlines(): if line.startswith(".. qmlink:: TCIndexImporter"): @@ -663,7 +603,6 @@ def to_rest(self, artifact): result += line + "\n" result = reference + result + "\n\n" - result += relative_links_for(artifact) result = ( "|\n\n" + writer.minipage(result, r"\linewidth") + "\n\n" + qmlink ) @@ -672,12 +611,15 @@ def to_rest(self, artifact): class ToplevelIndexImporter(ArtifactImporter): + def qmlink_to_rest(self, parent, artifacts): + items = [] html_top_index = "" for a in artifacts: - items.append([writer.strong(a.name), writer.qmref(a.full_name)]) + + items.append([writer.strong(a.tname), a.rest_doc_ref()]) if a.name == "Ada": @@ -694,9 +636,7 @@ def key(a): selected = a.relatives for suba in selected: - items.append( - ["`..` %s" % suba.name, writer.qmref(suba.full_name)] - ) + items.append(["`..` %s" % suba.tname, suba.rest_doc_ref()]) html_top_index += writer.csv_table( items, headers=["Chapter", "Description"], widths=[30, 70] @@ -705,17 +645,11 @@ def key(a): output = writer.only(html_top_index, "html") links = [ - (a, qm.rest.DefaultImporter()) - for a in artifacts - if "Index/.+" not in a.full_name + (a, DefaultImporter()) for a in artifacts if "Index/.+" not in a.id ] output += writer.toctree( - [ - "/%s/content" % artifact_hash(*link) - for link in links - if not is_tc_or_set(link[0]) - ], + [lnk[0].docfile() for lnk in links if not is_tc_or_set(lnk[0])], hidden=True, ) @@ -723,7 +657,9 @@ def key(a): class SubsetIndexTable(ArtifactImporter): + def qmlink_to_rest(self, parent, artifacts): + items = [] header = "" @@ -733,8 +669,9 @@ def qmlink_to_rest(self, parent, artifacts): tc = len([a for a in artifacts if class_to_string(a) == "tc"]) for a in artifacts: - name = a.name - items.append([class_to_string(a), name, writer.qmref(a.full_name)]) + + name = a.tname + items.append([class_to_string(a), name, a.rest_doc_ref()]) # in the html, the title is adapted to the content of the table header = ( @@ -781,15 +718,13 @@ def qmlink_to_rest(self, parent, artifacts): class SubsetIndexTocTree(ArtifactImporter): + def qmlink_to_rest(self, parent, artifacts): + links = [(a, default_importer(a)) for a in artifacts] output = writer.toctree( - [ - "/%s/content" % artifact_hash(*link) - for link in links - if not is_tc_or_set(link[0]) - ], + [lnk[0].docfile() for lnk in links if not is_tc_or_set(lnk[0])], hidden=True, ) @@ -797,7 +732,9 @@ def qmlink_to_rest(self, parent, artifacts): class SubsetIndexImporter(SubsetIndexTable): + def qmlink_to_rest(self, parent, artifacts): + output, links = SubsetIndexTable.qmlink_to_rest( self, parent, artifacts ) @@ -805,17 +742,14 @@ def qmlink_to_rest(self, parent, artifacts): links = [(a, default_importer(a)) for a in artifacts] output += writer.toctree( - [ - "/%s/content" % artifact_hash(*link) - for link in links - if not is_tc_or_set(link[0]) - ], + [lnk[0].docfile() for lnk in links if not is_tc_or_set(lnk[0])], hidden=True, ) return output, links class TestCaseImporter(ArtifactImporter): + def log_missing_TR(self, artifact): """ Logs in a specific files the test case @@ -834,10 +768,7 @@ def log_missing_TR(self, artifact): if not has_TR: with open(MISSING_TR_LOG, "a") as fd: - fd.write( - "No TR for artifact %s location: %s\n" - % (artifact.full_name, artifact.location) - ) + fd.write("No TR for artifact %s\n" % (artifact.id)) def get_sources(self, artifact): """ @@ -861,27 +792,20 @@ def get_sources(self, artifact): return result def to_rest(self, artifact): - reference = "\n\n.. _%s:\n" % artifact.full_name.replace("/", "_")[1:] - result_pdf = "**TEST CASE**: %s\n\n" % artifact.full_name - result_html = "%s\n%s\n" % ( - artifact.full_name, - "=" * len(artifact.full_name), - ) + reference = "\n\n.. _%s:\n" % artifact.id.replace("/", "_")[1:] - result_pdf += qm.rest.DefaultImporter().to_rest(artifact) + "\n\n" - result_html += qm.rest.DefaultImporter().to_rest(artifact) + "\n\n" + result_pdf = "**TEST CASE**: %s\n\n" % artifact.id + result_html = "%s\n%s\n" % (artifact.id, "=" * len(artifact.id)) + + result_pdf += DefaultImporter().to_rest(artifact) + "\n\n" + result_html += DefaultImporter().to_rest(artifact) + "\n\n" result = reference + writer.only(result_pdf, "latex") result += writer.only(result_html, "html") self.log_missing_TR(artifact) - # Create a navigation links from this TC up to its requirement - # and group if any: - - result += relative_links_for(artifact) - # Managing the list of the sources driver_list = [] @@ -898,34 +822,40 @@ def to_rest(self, artifact): do_pdf = False for item in self.get_sources(artifact): + if is_consolidation(item): - consolidation_list += [item.name] - consolidation_list_qmref += [ - writer.qmref(item.full_name, item.name) - ] + + consolidation_list += [item.tname] + consolidation_list_qmref += [item.rest_doc_ref()] continue for key in item.contents_keys: if len(item.contents(key)) > 0: + for resource in item.contents(key): + if is_driver(resource): driver_list += [resource.basename] driver_list_qmref += [ - writer.qmref(item.full_name, resource.basename) + writer.qmref( + item.docfile(True), resource.basename + ) ] continue if is_functional(resource): func_list += [resource.basename] func_list_qmref += [ - writer.qmref(item.full_name, resource.basename) + writer.qmref( + item.docfile(True), resource.basename + ) ] continue helper_list += [resource.basename] helper_list_qmref += [ - writer.qmref(item.full_name, resource.basename) + writer.qmref(item.docfile(True), resource.basename) ] driver_list.sort() @@ -942,7 +872,7 @@ def to_rest(self, artifact): consolidation_list.sort() consolidation_list_qmref.sort() - for_table_qmref = izip_longest( + for_table_qmref = zip_longest( func_list_qmref, driver_list_qmref, helper_list_qmref, @@ -950,7 +880,7 @@ def to_rest(self, artifact): fillvalue="", ) - for_table = izip_longest( + for_table = zip_longest( func_list, driver_list, helper_list, @@ -958,14 +888,14 @@ def to_rest(self, artifact): fillvalue="", ) else: - for_table_qmref = izip_longest( + for_table_qmref = zip_longest( func_list_qmref, driver_list_qmref, helper_list_qmref, fillvalue="", ) - for_table = izip_longest( + for_table = zip_longest( func_list, driver_list, helper_list, fillvalue="" ) @@ -974,7 +904,10 @@ def to_rest(self, artifact): result += writer.only(html_content, "html") if do_pdf: - latex_content = writer.csv_table(list(for_table), headers).strip() + latex_content = writer.csv_table( + list(for_table), + headers, + ).strip() result += writer.only(latex_content, "latex") output = "\n\n" + writer.minipage(result, r"\linewidth") + "|\n\n" @@ -982,60 +915,28 @@ def to_rest(self, artifact): return output -class SourceCodeImporter(ArtifactImporter): - def to_rest(self, artifact): - from qm import Ada_Sources, C_Sources, Conso_Sources - - result = "" - - if isinstance(artifact, Ada_Sources): - for key in artifact.contents_keys: - for item in artifact.contents(key): - result += writer.paragraph_title(item.basename) - result += writer.code_block(item.get_content(), "ada") - - if isinstance(artifact, C_Sources): - for key in artifact.contents_keys: - for item in artifact.contents(key): - result += writer.paragraph_title(item.basename) - result += writer.code_block(item.get_content(), "c") - - if isinstance(artifact, Conso_Sources): - result += writer.paragraph_title(artifact.name) - result += writer.code_block( - artifact.location.get_content(), "bash" - ) - - return result - - class IndexImporter(ArtifactImporter): + def append_to_items(self, art, depth): + if is_req(art): self.current_req = art kind_text = writer.strong("(%s)" % class_to_string(art)) - id_text = writer.strong("%s" % art.full_name.replace("/TOR", "")) + id_text = writer.strong("%s" % art.id.replace("/TOR", "")) elif is_tc(art): kind_text = "(%s)" % class_to_string(art) common_prefix_parent_req = os.path.commonprefix( - (art.full_name, self.current_req.full_name) + (art.id, self.current_req.id) ) - id_text = "[...]" + art.full_name.replace( - common_prefix_parent_req, "" - ) + id_text = "[...]" + art.id.replace(common_prefix_parent_req, "") - self.items.append( - [ - kind_text, - id_text, - write_artifact_ref(art.full_name, get_short_description(art)), - ] - ) + self.items.append([kind_text, id_text, art.rest_doc_ref()]) def handle(self, art, depth): + if is_req(art) or is_tc(art): self.append_to_items(art, depth) @@ -1043,9 +944,11 @@ def handle(self, art, depth): self.handle(art=child, depth=depth + 1) def qmlink_to_rest(self, parent, artifacts): + self.items = [] def sortkey_for(art): + # Arrange for stmt requirements to come first, before decision and # mcdc. Work from locations, which contain the explicit ordering # requests in the names (numeric prefixes like 1_). @@ -1079,6 +982,7 @@ def sortkey_for(art): class TestCasesImporter(ArtifactImporter): + def short_descs_of_main_ancestors(self, artifact, head): """ Get the first line of both itself and the ancestor @@ -1096,9 +1000,9 @@ def short_descs_of_main_ancestors(self, artifact, head): main_desc = None if parent is not None: - if parent.full_name.endswith(head): - main_desc = get_short_description(parent) - desc = get_short_description(artifact) + if parent.id.endswith(head): + main_desc = parent.title() + desc = artifact.title() else: main_desc, desc = self.short_descs_of_main_ancestors( parent, head @@ -1192,7 +1096,7 @@ def tc_pdf_for_subdir(self, toplevel, subdir, links): subdir_links = [ sdl for sdl in links - if sdl[0].full_name.startswith("/TOR/%s/%s" % (toplevel, subdir)) + if sdl[0].id.startswith("/TOR/%s/%s" % (toplevel, subdir)) ] if not subdir_links: @@ -1203,9 +1107,10 @@ def tc_pdf_for_subdir(self, toplevel, subdir, links): main_desc, desc = self.short_descs_of_main_ancestors( sdl[0], subdir ) - if desc not in links_dict: - links_dict[desc] = [] - links_dict[desc].append(sdl) + if desc: + if desc not in links_dict: + links_dict[desc] = [] + links_dict[desc].append(sdl) pdf_output = "" pdf_output += writer.subsection("%s" % main_desc) + "\n" @@ -1213,16 +1118,13 @@ def tc_pdf_for_subdir(self, toplevel, subdir, links): for desc in links_dict.keys(): pdf_output += writer.subsubsection(desc) + "\n" pdf_output += writer.toctree( - [ - "/%s/content" % artifact_hash(*link) - for link in links_dict[desc] - ], - hidden=True, + [lnk[0].docfile() for lnk in links_dict[desc]], hidden=True ) return pdf_output def qmlink_to_rest(self, parent, artifacts): + # cleanup missingTRfile with open(MISSING_TR_LOG, "w") as fd: fd.write("") @@ -1238,16 +1140,13 @@ def qmlink_to_rest(self, parent, artifacts): tc_or_set_links.append((suba, TestCaseImporter())) elif is_tcset(suba): tc_or_set_links.append((suba, TCSetImporter())) - elif is_source(suba): - src_links.append((suba, SourceCodeImporter())) mixed_links = src_links + tc_or_set_links # Build the html output html_output = writer.toctree( - ["/%s/content" % artifact_hash(*link) for link in mixed_links], - hidden=True, + [lnk[0].docfile() for lnk in mixed_links], hidden=True ) # Then the PDF variant. A bit more work as we need to output diff --git a/qualification/qm/qm_plugins/link_lrm.py b/qualification/scripts/qm_plugins/link_lrm.py similarity index 100% rename from qualification/qm/qm_plugins/link_lrm.py rename to qualification/scripts/qm_plugins/link_lrm.py diff --git a/qualification/qm/qm_plugins/lrm_index_parser.py b/qualification/scripts/qm_plugins/lrm_index_parser.py similarity index 100% rename from qualification/qm/qm_plugins/lrm_index_parser.py rename to qualification/scripts/qm_plugins/lrm_index_parser.py diff --git a/qualification/scripts/rest/__init__.py b/qualification/scripts/rest/__init__.py new file mode 100644 index 000000000..c2406a8b7 --- /dev/null +++ b/qualification/scripts/rest/__init__.py @@ -0,0 +1,310 @@ +############################################################################ +# # +# The Qualifying Machine (QM) # +# # +# Copyright (C) 2010-2014, AdaCore # +# # +# The QM 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. The QM 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 the QM; see file COPYING3. If # +# not, write to the Free Software Foundation, 59 Temple Place - Suite # +# 330, Boston, MA 02111-1307, USA. # +# # +############################################################################ + +"""This module handles the ReST related tasks. This involves both docutils used + for live previews and sphinx for the final documents creation""" +from __future__ import annotations + +import os.path +import hashlib + +from typing import Optional, Sequence + +ARTIFACT_IMPORTER_PLUGINS = {} + +"""Implement some utility function that ease generation of ReST code""" + +HEADING_CHARS = ["#", "*", "=", "-", "^", '"'] + + +def heading(title, heading_char): + if isinstance(heading_char, int): + heading_char = HEADING_CHARS[heading_char] + + result = "\n\n" + result += heading_char * len(title) + "\n" + result += title + "\n" + result += heading_char * len(title) + "\n\n" + return result + + +def part(title): + return heading(title, "#") + + +def chapter(title): + return heading(title, "*") + + +def section(title): + return heading(title, "=") + + +def subsection(title): + return heading(title, "-") + + +def subsubseciton(title): + return heading(title, "^") + + +def paragraph(title): + return heading(title, '"') + + +def toctree(itemlist, depth=2, attrlist=()): + return ( + "\n".join( + [".. toctree::", " :maxdepth: %s" % depth] + + [" %s" % attr for attr in attrlist] + + ["\n"] + + [" %s" % item for item in itemlist] + ) + + "\n" + ) + + +def emphasis(content): + return "*" + content + "*" + + +def strong(content): + return "**" + content + "**" + + +def generic_block(command, content, command_arg=None): + if content == "": + return "" + + if command_arg is None: + command_arg = "" + + result = "\n.. %s:: %s\n\n" % (command, command_arg) + result += "\n".join([" " + line for line in content.splitlines()]) + result += "\n\n" + return result + + +def warning(content): + return generic_block("warning", content) + + +def parsed_literal(content): + return generic_block("parsed-literal", content) + + +def code_block(content, language): + return generic_block("code-block", content, language) + + +def raw(content, doc_type): + return generic_block("raw", content, doc_type) + + +def line_block(content): + result = "\n\n" + result += "\n".join([" " + line for line in content.splitlines()]) + return result + + +def list(content): # noqa: A001 + result = "\n\n" + result += "\n".join([" * %s" % line for line in content]) + result += "\n\n" + return result + + +class Artifact(object): + pass + + def get_children(self: Artifact) -> Sequence[Artifact]: + """Return list of subartifacts""" + return [] + + def get_child(self: Artifact, name: str) -> Artifact | None: + """Return child artifact by name""" + stripped_name = name.strip() + for a in self.get_children(): + if a.get_name() == stripped_name: + return a + + return None + + def get_name(self: Artifact) -> str: + return "" + + @property + def full_name(self: Artifact) -> str: + return "" + + def dtext(self: Artifact) -> str: + """Return text of the artifact""" + return "" + + def title(self: Artifact) -> str: + """Return first line of artifact dtext(), remove formatting""" + content = self.dtext() + for line in content.splitlines(): + line = line.strip().strip("*") + if len(line) > 0 and not line.startswith(".. "): + # ** has to be removed + # from short_description when used in tables + line = line.replace("**", "") + import re + + # remove all directives + line = re.sub(r":[a-zA-Z0-9]*:", "", line) + # replace backquotes with single quotes + line = line.replace("`", "'") + + return line + + return "" + + def docfile(self: Artifact, no_extension: bool = False) -> str: + """Filename for the generated RST file""" + return "" + + def rest_doc_ref(self: Artifact) -> str: + """Returns a sphinx :doc: reference""" + return "" + + @property + def relatives(self: Artifact) -> Sequence[Artifact]: + """ + The list of sub-artifacts that are relative to self. + + :rtype: A list of :class:`Artifact` + """ + return [] + + @property + def relative_to(self: Artifact) -> Optional[Artifact]: + """ + The instance this artifact is relative to. + + :rtype: An instance of :class:`Artifact`, or None + """ + return None + + def hash(self: Artifact) -> str: # noqa: A003 + """Return a hash based on the artifact full name""" + hashobj = hashlib.new("sha1") + hashobj.update(self.full_name.encode("utf-8")) + return hashobj.hexdigest() + + +class MetaArtifactImporter(type): + """ + Metaclass for Artifact Importers: automatically registers new + importers. + """ + + def __new__(mcs, classname, bases, class_dict): + result = type.__new__(mcs, classname, bases, class_dict) + if classname != "ArtifactImporter": + ARTIFACT_IMPORTER_PLUGINS[classname] = result + return result + + +class ArtifactImporter(metaclass=MetaArtifactImporter): + """ + ArtifactImporter is responsible for the translation of an artifact to + rest format. + To declare a new Importer, just override the + :func:`ArtifactImporter.to_rest`. + """ + + QMLINK_TAG = ".. qmlink::" + + def __init__(self): + self._concatenate = False + + @classmethod + def new(cls, name): + """ + Given an importer class name, return a new instance of that importer + + :param str name: The name of the class + :return: an ArtifactImporter instance + """ + + if name not in ARTIFACT_IMPORTER_PLUGINS: + raise Exception("No such importer: %s" % name) + return ARTIFACT_IMPORTER_PLUGINS[name]() + + @staticmethod + def is_qmlink(line: str) -> bool: + return line.startswith(ArtifactImporter.QMLINK_TAG) + + @property + def concatenate(self): + """ + Wether the imported artifacts should be directly concatenated (if + several are present in the same qmlink directive) or should have + separate content. + + :return: A boolean (False by default) + """ + return self._concatenate + + @concatenate.setter + def concatenate(self, value): + "concatenate setter" + self._concatenate = value + + def copy_resources(self, artifact, dest_dir): + """ + Copies additional resources to the destination directory if needed, for + documentation generation purpose. + + By default, this is a no-op. + + :param artifact: The artifact being imported + :type artifact: a :class:`qm.Artifact` + :param dest_dir: The destination directory + :type dest_dir: A string + """ + pass + + def to_rest(self, artifact): + """ + Needs to be overriden. + + :param Artifact: the artifact to translate + :type Artifact: an instance of :class:`qm.Artifact` + + :rtype: a string + """ + + def qmlink_to_rest(self, parent, artifacts): + """ + Needs to be overriden. + """ + raise NotImplementedError("not implemented") + + +class DefaultImporter(ArtifactImporter): + """ + The default importer, used for importing artifacts with files already + in rest format + """ + + def to_rest(self, artifact): + return artifact.dtext() diff --git a/qualification/scripts/rest/writer.py b/qualification/scripts/rest/writer.py new file mode 100644 index 000000000..432fe2b62 --- /dev/null +++ b/qualification/scripts/rest/writer.py @@ -0,0 +1,470 @@ +############################################################################ +# # +# The Qualifying Machine (QM) # +# # +# Copyright (C) 2010-2014, AdaCore # +# # +# The QM 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. The QM 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 the QM; see file COPYING3. If # +# not, write to the Free Software Foundation, 59 Temple Place - Suite # +# 330, Boston, MA 02111-1307, USA. # +# # +############################################################################ + +"""Provides some high level function to ease generation of ReST strings""" + +INDENT = " " + + +# paragraph # +def paragraph(content=None): + """Return a string representing the inlining of a content + + :param content: the directive content + :type content: either a string or a list of strings + """ + if content is None: + return "\n" + + if isinstance(content, str): + result = content.splitlines() + else: + result = content[:] + + result.append("") + + return "\n".join(result) + "\n" + + +# Directives # +def directive(name, content=None, argument=None, options=None): + """Return a string representing a directive + + :param name: the directive name + :type name: a string + :param content: the directive content + :type content: either a string or a list of strings + :param argument: the directive argument (for example the language for + for a ``code-block`` directive + :type argument: a string + :param options: the directive options + :type options: None or a dictionnary + :rtype: a string + """ + result = [".. %s::" % name] + if argument is not None: + result[0] += " %s" % argument + + if options is not None: + for option in options: + if options[option] is None: + result.append("%s:%s:" % (INDENT, option)) + else: + result.append("%s:%s: %s" % (INDENT, option, options[option])) + + # add empty line + result.append("") + + if content is not None: + # add directive content. content can either be a string or a list + if isinstance(content, str): + content = content.splitlines() + + for line in content: + result.append("%s%s" % (INDENT, line)) + + result.append("") + + return "\n".join(result) + "\n" + + +def code_block(content, language=None): + """Return a code-block directive string + + :param content: the code to be highlighted + :type content: string or list of strings + :param language: the programming language name + :type language: string + :rtype: a string + """ + return directive("code-block", content=content, argument=language) + + +def toctree(content, hidden=False): + """Return a toctree directive + + :param content: the list of sub documents + :type content: list of string + :param hidden: if True then toctree is hidden + :type hidden: boolean + :rtype: a string + """ + options = {} + if hidden: + options["hidden"] = None + options["maxdepth"] = 1 + + return directive("toctree", content=content, options=options) + + +def csv_table( + content, headers=None, title=None, widths=None, latex_format=None +): + """Return a ReST csv-table + + :param content: the elements of the table + :type content: a list of list of strings + :param headers: the column titles + :type headers: a list of strings + :param title: the table title + :type title: a string + :param widths: list of width percentage (for html) + :type widths: list of integers + :param latex_format: set the LateX tabular env environment + :type latex_format: string + :rtype: a string + """ + + table_content = [] + for line in content: + table_line = ", ".join(['"%s"' % k.replace('"', '""') for k in line]) + table_content.append(table_line) + + options = {} + if headers is not None: + options["header"] = ", ".join(['"%s"' % k for k in headers]) + if widths is not None: + options["widths"] = ",".join(["%s" % k for k in widths]) + + result = "" + if latex_format is not None: + result += directive("tabularcolumns", argument=latex_format) + elif widths is not None: + latex_w = ["p{%.2f\\textwidth}" % (float(w) / 100.0) for w in widths] + result += directive( + "tabularcolumns", argument="|" + "|".join(latex_w) + "|" + ) + + result += directive( + "csv-table", table_content, argument=title, options=options + ) + return result + + +def raw(content, format_tag): + """Raw output for a given format + + Allows to emit directly latex, html, ... into a sphinx document + + :param content: the raw content + :type content: a string + :param format_tag: the selected format (html, latex) + :type format_tag: a string + :rtype: a string + """ + + return directive("raw", content=content, argument=format_tag) + + +def only(content, format_tag): + """Return a ReST only directive + + :param content: the content + :type content: a string + :param format_tag: expression of format tags (html, latex, ...) + :type format_tag: a string + :rtype: a string + """ + + return directive("only", content=content, argument=format_tag) + + +# Roles # +def role(name, argument): + """Generic function to generate ReST roles + + :param name: the role name + :type name: a string + :param argument: the content on which the role is applied + :type argument: a string + :rtype: a string + """ + return ":%s:`%s`" % (name, argument) + + +def qmref(full_path, name=None): + """Generate a qmref role + + :param full_path: the target of the ref + :type full_path: a string + :param name: intelligible name or description + :type name: a string + :rtype: a string + """ + + if name is not None: + # Protect potential '<' in the explicit text. + name = name.replace("<", r"\<") + content = "%s <%s>" % (name, full_path) + else: + content = full_path + + return role("doc", content) + + +def doc(name, explicit_text=None): + """Generate a doc role + + :param name: name of the doc file + :type name: a string + :param explicit_text: intelligible name or description + :type explicit_text: a string + :rtype: a string + """ + + # if explicit_text is not None: + # # Protect potential '<' in the explicit text. + # explicit_text = explicit_text.replace('<', '\<') + # content = '%s <%s>' % (explicit_text, name) + # else: + # content = name + + return role("doc", name) + + +def ref(reflabel, explicit_text=None): + """Generate a ref role + + :param reflabel: the target label to reference + :type reflabel: a string + :param explicit_text: intelligible name or description + :type explicit_text: a string + :rtype: a string + """ + + if explicit_text is not None: + # Protect potential '<' in the explicit text. + explicit_text = explicit_text.replace("<", r"\<") + content = "%s <%s>" % (explicit_text, reflabel) + else: + content = reflabel + + return role("ref", content) + + +def emphasis(content): + """Generate an emphasis role equivalent to ``*content*`` + + :param content: the content + :type content: a string + :rtype: a string + """ + return role("emphasis", content) + + +def strong(content): + """Generate a string role equivalent to ``**content**`` + + :param content: the content + :type content: a string + :rtype: a string + """ + return role("strong", content) + + +def literal(content): + """Generate an inline code sample + + :param content: the content + :type content: a string + :rtype: a string + """ + return role("literal", content) + + +# Lists # +def generic_list(content_list, marker="*"): + """Generate a ReST list + + :param content: the elements of the list + :type content: a list of strings and list (to generate sublists) + :param marker: the marker used to mark new elements + :type marker: a string + :rtype: a string + """ + prefix = "%s " % marker + blank = " " * len(prefix) + result = [] + for element in content_list: + + if isinstance(element, str): + element = element.splitlines() + + result.append("%s%s" % (prefix, element[0])) + for line in element[1:]: + result.append("%s%s" % (blank, line)) + else: + # assume element is either a list or a tuple + result.append("") + result.append(generic_list(element, " " * len(prefix) + marker)) + result.append("") + return "\n".join(result) + "\n\n" + + +def enumerated_list(content_list): + """Generate an enumerated ReST list + + :param content: the elements of the list + :type content: a list of strings and list (to generate sublists) + :rtype: a string + """ + return generic_list(content_list, marker="#.") + + +def definition_list_item(definition_name, definition_text): + """Generate a single definition ReST list + + :param definition_name: The name of the definition + :type definition_name: a string + :param definition_text: The text of the definition + :type definition_text: a string + :rtype: a string + """ + res = [definition_name] + + if isinstance(definition_text, str): + definition_text = definition_text.splitlines() + + for line in definition_text: + res.append("%s%s" % (INDENT, line)) + + return "\n".join(res) + "\n\n" + + +def definition_list(content_list): + """Generate a definition ReST list + + :param content: the elements of the list, each element containing first + the name of the definition, then the definition itself + :type content: a list of tuple (string, string) + :rtype: a string + """ + result = "" + for defname, deftext in content_list: + result += definition_list_item(defname, deftext) + + return result + + +# Sections # +def heading(title, level=1): + """Generate a ReST heading + + :param title: the title of that heading + :type title: a string + :param level: depth of the heading + :type level: integer + :rtype: a string + """ + markers = ["#", "*", "=", "-", "^", '"'] + marker = markers[level - 1] + result = [title, marker * len(title)] + return "\n".join(result) + "\n\n" + + +def part(title): + """Equivalent to heading with level set to 1""" + return heading(title, 1) + + +def chapter(title): + """Equivalent to heading with level set to 2""" + return heading(title, 2) + + +def section(title): + """Equivalent to heading with level set to 3""" + return heading(title, 3) + + +def subsection(title): + """Equivalent to heading with level set to 4""" + return heading(title, 4) + + +def subsubsection(title): + """Equivalent to heading with level set to 5""" + return heading(title, 5) + + +def paragraph_title(title): + """Equivalent to heading with level set to 6""" + return heading(title, 6) + + +def rubric(title): + return directive("rubric", argument=title) + + +def macro(value, expanded): + """Creates a sphinx macro""" + return "\n\n.. |%s| replace:: %s\n\n" % (value, expanded) + + +def macrolatex(value, expanded): + """Creates a latex specific sphinx macro""" + return "\n\n.. |%s| raw:: latex\n\n %s\n\n" % (value, expanded) + + +def minipage(content, latex_format=r"{\linewidth}"): + """ + Return a string representing the insertion of a latex minipage + 'around' the given content. + if not latex generation then, only includes the content as it. + + :param content: the content to be included in minipage + :type content: either a string or a list of strings + :param latex_format: the format to be associated with the minipage + structure + :type latex_format: a string + """ + + result = [] + result.append( + directive( + "raw", + ("\\begin{minipage}%s" % latex_format).replace("\\\\", "\\"), + "latex", + ) + ) + + if content is not None: + # add mini page content. content can either be a string or a list + if isinstance(content, str): + content = content.splitlines() + + result += content + + result.append(directive("raw", r"\end{minipage}", "latex")) + + str_result = "\n".join(result) + + return str_result + + +def define_role(role_name, options): + """Allows to define a new role + then usable through the previous function 'role' + + :param role_name: the name of the role to be defined + :type role_name: a string, + :param options: the expected effect of the role + :type options: a dictionnary or None + """ + return directive("role", argument=role_name, options=options) diff --git a/qualification/tor/scripts/Makefile b/qualification/tor/Makefile similarity index 100% rename from qualification/tor/scripts/Makefile rename to qualification/tor/Makefile diff --git a/qualification/tor/__init__.py b/qualification/tor/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/qualification/tor/conf.py b/qualification/tor/conf.py new file mode 100644 index 000000000..01bc88781 --- /dev/null +++ b/qualification/tor/conf.py @@ -0,0 +1,195 @@ +############################################################################ +# # +# The Qualifying Machine (QM) # +# # +# Copyright (C) 2010-2014, AdaCore # +# # +# The QM 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. The QM 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 the QM; see file COPYING3. If # +# not, write to the Free Software Foundation, 59 Temple Place - Suite # +# 330, Boston, MA 02111-1307, USA. # +# # +############################################################################ + + +from collections import OrderedDict +from scripts.common_conf import ( + version, + project_name, + owner, + users, + assignments, + tor_doc_id, + rst_prolog, + VAR_REPLACEMENTS, +) + +doc_id = tor_doc_id + +extensions = [] +papersize = "a4paper" +latex_show_pagerefs = True +html_sidebars = {"**": ["localtoc.html", "sourcelink.html", "searchbox.html"]} +latex_use_parts = False +toc_depth = 2 + +# roles definition +# ??? This is standard-specific and should not be defined here. +roles = OrderedDict( + [ + ("authors", {"description": "the authors of the document"}), + ("reviewers", {"description": "the reviewers of the document"}), + ("approvers", {"description": "the approvers of the document"}), + ] +) + +# Do some checks +assert rst_prolog is not None, "rst_prolog should be set in common_conf.py" + +templates_path = ["_templates"] + +# These parameters cannot be overriden so just force their value after +# reading user conf file +master_doc = "index" + +source_suffix = ".rst" +project = project_name +exclude_patterns = ["_build"] +pygments_style = "sphinx" +html_theme = "classic" +html_theme_path = ["."] +html_theme_options = {"body_max_width": None} + + +PAGE_BLANK = r""" +\makeatletter +\def\cleartooddpage{%% + \cleardoublepage%% +} +\def\cleardoublepage{%% +\clearpage%% + \if@twoside%% + \ifodd\c@page%% + %% nothing to do + \else%% + \hbox{}%% + \thispagestyle{plain}%% + \vspace*{\fill}%% + \begin{center}%% + \textbf{\em This page is intentionally left blank.}%% + \end{center}%% + \vspace{\fill}%% + \newpage%% + \if@twocolumn%% + \hbox{}%% + \newpage%% + \fi%% + \fi%% + \fi%% +} +\makeatother +""" + +TOC_DEPTH = ( + r""" +\pagenumbering{arabic} +\setcounter{tocdepth}{%d} +""" + % toc_depth +) + +TOC_CMD = r""" +\makeatletter +\def\tableofcontents{%% + \pagestyle{plain}%% + \chapter*{\contentsname}%% + \@mkboth{\MakeUppercase{\contentsname}}%% + {\MakeUppercase{\contentsname}}%% + \@starttoc{toc}%% +} +\makeatother +""" + + +def latex_hyphen(): + return "\n".join([r"\hyphenpenalty=5000", r"\tolerance=1000"]) + + +def project_settings(): + + HLINE = r"\hline" + HEADERS = r"Name & Company & Team & Email \\" + assignment_tab = [] + + for role in filter(lambda x: x in assignments, roles.keys()): + title = ( + r"\multicolumn{4}{l}{\large \par} \\" + r" \multicolumn{4}{l}{\large %s \par} \\" % (role.capitalize()) + ) + + assignment_tab.append(title) + assignment_tab.append(HLINE) + assignment_tab.append(HEADERS) + assignment_tab.append(HLINE) + + for login in assignments[role]: + user = users[login] + assignment_tab.append( + r"%s & %s & %s & %s \\" + % (user["name"], user["company"], user["team"], user["email"]) + ) + + assignment_tab.append(HLINE) + + full_document_name = project_name + if doc_id is not None and len(doc_id) > 0: + full_document_name = "%s - %s" % (project_name, doc_id) + + return "\n".join( + [ + r"\newcommand*{\QMFullDocumentName}[0]{" + + full_document_name + + r"}", + r"\newcommand*{\QMProjectName}[0]{" + project_name + r"}", + r"\newcommand*{\QMDocID}[0]{" + doc_id + r"}", + r"\newcommand*{\QMVersion}[0]{" + version + r"}", + r"\newcommand*{\QMTabUsers}[0]{" + + "\n".join(assignment_tab) + + r"}", + ] + ) + + +TOC = r""" +\cleardoublepage +\tableofcontents +\cleardoublepage\pagestyle{plain} +""" + +latex_elements = { + "preamble": TOC_DEPTH + + PAGE_BLANK + + TOC_CMD + + latex_hyphen() + + "\n" + + project_settings(), + "tableofcontents": TOC, + "papersize": papersize, +} + +latex_documents = [ + ( + "index", + "TOR.tex", + f"GNATcoverage DO-178C/ED-12C Qualification Material: " + f"{VAR_REPLACEMENTS["plans_doc_title"]}", + owner, + "manual", + ), +] diff --git a/qualification/tor/genrest.py b/qualification/tor/genrest.py new file mode 100755 index 000000000..dab759a7d --- /dev/null +++ b/qualification/tor/genrest.py @@ -0,0 +1,1962 @@ +#!/usr/bin/env python +from __future__ import annotations + +import os +import glob +import re +import sys +import json +import optparse + +from tor.genrest_conf import ALLOW_UNCLASSIFIED_FOLDERS, SUPRESS_MSG_TYPES + +import scripts.rest as rest +import scripts.logger as logger +from scripts.rest import Artifact, ArtifactImporter, writer +from scripts.qm_plugins.importers import resolve_importer +from itertools import zip_longest +from scripts.common_conf import tor_doc_id +from tor.proj_conf import get_var_replacements + +from typing import Callable, Dict, List, Set, Optional, Sequence, Any, IO + +# ***************************************************************************** +# ** GENERAL DESCRIPTION ** +# ***************************************************************************** + +# This file implements the core of the GNATcoverage TOR document production, +# generating sphinx-REST from artifacts held within our testsuite/Qualif +# filesystem tree. + +# Except on rare occasions, each directory in this tree represents some TOR +# related entity: requirement, testcase, appendix material, or groups of such, +# possibly nested (groups may hold direct artifacts or further intermediate +# groups). +# +# The general structure is very hierarchical, going from requirement +# groups (REQG kind) to requirements (REQ kind), to testcases (TC kind) +# possibly via testcase groups (TCG kind). +# +# Very roughly, our processing here first constructs an internal tree +# datastructure representing the directory tree, where each node holds +# attributes qualifying its nature (e.g. "this node/directory holds a +# testcase"). This is determined from two elements: +# +# * The presence in the directory of some text file: +# - tc.rst for a testcase, +# - req.rst for a requirement, +# - content.rst for a group +# +# * For groups, the node is further qualified by looking at the set of +# children of the node. Despite the possibility to nest groups within +# groups, mixing a testcase artifacts at the same level as requirement +# artifacts is disallowed. +# +# Expected tree structure is as follows: +# +# content.rst +# content.rst +# req_set.rst +# req.rst +# tc_set.rst +# tc.rst +# tc.rst +# req.rst +# +# req.txt -> req.rst +# set.txt -> tc_set.rst +# set.txt -> content.rst +# [tc.txt; test.py] -> [tc.rst; test.py] +# +# Relative to where this script reside, path to ... + +# The root of the directory tree mapping qualification artifacts +# (requirements, testcases, ...): + +RST_ROOTDIR = "source" + +# The root of the directory where the REST documents describing +# these artifacts will reside: + +ART_ROOTDIR = "../../testsuite/Qualif" + +# Prefix artifact ID with this string + +ART_ID_PREFIX = "TOR" + +# Switch verbose messages on/off + +verbose = False + +# Maximum accepted directory tree depth + +MAX_TREE_DEPTH = 255 + +# count of typed warnings + +warn_stats: Dict[str, int] = {} + +# replacements for variables in rst text +# the dictionary is filled by DocGenerator.generate_all before +# doing any other transpormations +VAR_REPLACEMENTS: Dict[str, str] = {} + +# ********************** +# ** Helper functions ** +# ********************** + + +def replace_variables(content_text: str) -> str: + """Replace variables enclosed between | symbols.""" + + for rst_var in VAR_REPLACEMENTS: + content_text = re.sub( + r"\|%s\|" % rst_var, VAR_REPLACEMENTS[rst_var], content_text + ) + + return content_text + + +def get_content(filename: str) -> str: + """Return contents of file FILENAME as a string""" + + with open(filename, "r") as fd: + return fd.read() + + +def to_title(title: str) -> str: + """Given an entity name return a suitable string to be inserted + in the documentation""" + m = re.search(r"^[0-9]+_(.*)$", title) + if m is not None: + title = m.group(1) + return title.replace("_", " ") + + +def header(text: str, pre_skip: int, post_skip: int) -> str: + """Return the string to be used as a section header for STR, + framed with PRE_SKIP new_lines before and POST_SKIP new_lines after""" + return "\n" * pre_skip + text + "\n" * post_skip + + +def sec_header(text: str) -> str: + """Return a Section header text to be used for section title STR""" + return header(rest.strong(text), pre_skip=2, post_skip=2) + + +def subsec_header(text: str) -> str: + """Return a Subsection header text to be used for subsection title STR""" + return header(rest.emphasis(text), pre_skip=2, post_skip=2) + + +def info(text: str): + if verbose: + print("info: %s" % text) + + +def warn(text: str, msg_type: str = ""): + if not msg_type or not any( + re.match(pattern, msg_type) for pattern in SUPRESS_MSG_TYPES + ): + print("warning: %s" % text) + + if msg_type: + if msg_type in warn_stats: + warn_stats[msg_type] += 1 + else: + warn_stats[msg_type] = 1 + + +def warn_if(cond: bool, text: str, msg_type: str = ""): + if cond: + warn(text, msg_type) + + +def exit_if(p: bool, msg: str): + if p: + print(msg) + sys.exit(1) + + +def err(text: str): + print("error: %s" % text) + sys.exit(1) + + +def print_warn_stats(): + for key in warn_stats: + print("%s: %d" % (key, warn_stats[key])) + + +def err_if(p: bool, text: str): + if p: + print("error: %s" % text) + sys.exit(1) + + +def is_functional(src: str) -> bool: + # a resource whom content contains "-- #" is + # a functional source. In case of Ada Sources !! + + with open(src) as f: + content = f.read() + + is_func = False + + for line in content.splitlines(): + if "-- #" in line: + is_func = True + break + return is_func + + +# ************************** +# ** TestCase abstraction ** +# ************************** + +# Helper for the Directory abstraction, to encapsulate research of driver +# and functional source file sets + + +class TestCase: + def __init__(self: TestCase, dir_name: str, dgen: DocGenerator): + self.dir = dir_name + self.dgen = dgen + + self.fnsources: set[str] = set() + self.hlpsources: set[str] = set() + self.drsources: set[str] = set() + self.conspecs: set[str] = set() + self.find_sources() + + def parent_globbing( + self: TestCase, + dir_name: str, + pattern: str, + include_start_dir: bool = True, + ) -> Set[str]: + """Look for src/[pattern] files in dir and its parents directory + up to document root directory""" + + head = os.path.relpath(dir_name, self.dgen.art_rootdir) + tail = "" + if not include_start_dir: + head, tail = os.path.split(head) + files = set() + while len(head) > 0: + files |= set( + glob.glob( + os.path.join( + self.dgen.art_rootdir, + head, + "src", + pattern, + ) + ) + ) + head, tail = os.path.split(head) + return files + + def find_with_clauses( + self: TestCase, + dir_name: str, + sourcefile: str, + ) -> Set[str]: + content = get_content(sourcefile) + # Remove all comments + content = "\n".join( + [k for k in content.splitlines() if not re.match(r"\s*--", k)] + ) + + # Find all the with clauses + matches = re.findall(r"(?:\n|;|^)\s*with\s*([^;]+)\s*;", content, re.S) + matches = [k.replace(" ", "") for k in matches] + matches = [k.replace(".", "-") for k in matches] + + result = set() + for m in matches: + result |= set(m.lower().split(",")) + + # Remove packages we don't care about and probably could locate + result -= {"support", "system"} + + file_list = set() + for item in result: + spec = self.parent_globbing(dir_name, item + ".ads", True) + warn_if( + len(spec) > 1, + 'multiple specs for unit "%s" (from %s)' % (item, sourcefile), + "SRC_MULTIPLE_SPECS", + ) + file_list |= spec + + body = self.parent_globbing(dir_name, item + ".adb", True) + warn_if( + len(body) > 1, + 'multiple bodies for unit "%s" (from %s)' % (item, sourcefile), + "SRC_MULTIPLE_BODIES", + ) + file_list |= body + + warn_if( + len(body | spec) == 0, + 'no body or spec source found for unit "%s" (from %s)' + % (item, sourcefile), + "SRC_NO_BODY_OR_SPEC", + ) + + return file_list + + def find_closure( + self: TestCase, + dir_name: str, + sourcefile: str, + ) -> Set[str]: + """Given an Ada source file find it's closure. Not that we ignore the + support package""" + + result_set = self.find_with_clauses(dir_name, sourcefile) + + current_size = len(result_set) + previous_size = 0 + while current_size > previous_size: + previous_size = current_size + tmp = set() + for item in result_set: + tmp |= self.find_with_clauses(dir_name, item) + + result_set |= tmp + current_size = len(result_set) + + return result_set + + def find_sources(self: TestCase) -> None: + """Locate the functional and driver sources of testcase SELF""" + + # Seek the test drivers first, and infer closure from there. Then + # append consolidation specs to the set of drivers. We will typically + # end up on common functional units from drivers, so use sets to + # prevent duplicates. + + # Test drivers: search the local "src" subdir first, walk uptree + # if no driver there. + + local_sources = set( + glob.glob(os.path.join(self.dir, "src", "*.ad[sb]")) + ) + + self.drsources = { + k for k in local_sources if os.path.basename(k).startswith("test_") + } + + if len(self.drsources) == 0: + data_names = { + os.path.basename(k).split(".")[0] for k in local_sources + } + for name in data_names: + self.drsources.update( + self.parent_globbing(self.dir, "test_" + name + "*.ad[sb]") + ) + + warn_if( + len(self.drsources) == 0, + "no driver source for testcase in %s" % self.dir, + "SRC_NO_DRIVER_SOURCE", + ) + + # Driver Closure: + + self.fnsources = set() + self.hlpsources = set() + for driver in self.drsources: + for src in self.find_closure(self.dir, driver): + if is_functional(src): + self.fnsources.add(src) + else: + self.hlpsources.add(src) + + warn_if( + len(self.fnsources) == 0, + "no functional source for testcase in %s" % self.dir, + "SRC_NO_FUNCTIONAL_SOURCE", + ) + + # Consolidation specs. These are always local. + + self.conspecs = set() + self.conspecs |= set( + glob.glob(os.path.join(self.dir, "src", "cons_*.txt")) + ) + + +# *************************** +# ** Path Info abstraction ** +# *************************** + + +class PathInfo: + """Holds info about the path to the current node when walking + a directory tree""" + + def __init__(self: PathInfo): + self.n_req = 0 # Number of requirement expressions so far + self.n_tc = 0 # Number of tc nodes so far + self.depth = 0 # Depth of this node wrt root of walk operation + + +# ************************** +# ** Node Set abstraction ** +# ************************** + + +class NodeSet: + """Node Set abstraction, used to compute composite attributes + for a set of nodes. We compute two categories of composite attributes: + + * The "some_" attributes tell whether some (at least one) node in set has + such or such characteristic. These are updated as nodes are added to the + set, via the "register_one" method. + + * The "all_" attributes tell whether all the nodes in the set has such or + such characteristic. These are computed from the current "some_" values + when the "sync" method is called, + """ + + def __init__(self: NodeSet, diros: List[Dir]): + """Initialize the some_ attributes for SELF, then register + each directory object in the DIROS sequence and sync() to update + the all_ attributes from there.""" + + self.some_reqgroup = False + self.some_notreqgroup = False + self.some_tcgroup = False + self.some_nottcgroup = False + self.some_appmat = False + self.some_notappmat = False + + self.some_reqorset = False + self.some_notreqorset = False + self.some_tcorset = False + self.some_nottcorset = False + + self.some_reqorgroup = False + self.some_notreqorgroup = False + self.some_tcorgroup = False + self.some_nottcorgroup = False + + self.some_req = False + self.some_notreq = False + self.some_tc = False + self.some_nottc = False + self.some_app = False + self.some_notapp = False + self.some_set = False + self.some_notset = False + + self.some_notreqset = False + self.some_nottcset = False + self.some_notappset = False + + self.diros: List[Dir] = [] + + [self.register_one(diro) for diro in diros] + self.sync() + + def register_one(self: NodeSet, diro: Dir): + """Add one directory object to this set, updating the + some_ attributes accordingly.""" + + self.some_req |= diro.req + self.some_tc |= diro.tc + self.some_set |= diro.set + self.some_app |= diro.app + + self.some_notreq |= not diro.req + self.some_nottc |= not diro.tc + self.some_notset |= not diro.set + self.some_notapp |= not diro.app + + self.some_notreqset |= not diro.reqset + self.some_nottcset |= not diro.tcset + self.some_notappset |= not diro.appset + + self.some_reqgroup |= diro.reqgroup + self.some_notreqgroup |= not diro.reqgroup + + self.some_tcgroup |= diro.tcgroup + self.some_nottcgroup |= not diro.tcgroup + + self.some_appmat |= diro.appmat + self.some_notappmat |= not diro.appmat + + self.some_reqorset |= diro.req | diro.reqset + self.some_tcorset |= diro.tc | diro.tcset + + self.some_notreqorset |= not (diro.req | diro.reqset) + self.some_nottcorset |= not (diro.tc | diro.tcset) + + self.some_reqorgroup |= diro.req | diro.reqgroup + self.some_tcorgroup |= diro.tc | diro.tcgroup + + self.some_notreqorgroup |= not (diro.req | diro.reqgroup) + self.some_nottcorgroup |= not (diro.tc | diro.tcgroup) + + self.diros.append(diro) + info( + f"registering {diro.root}: TC {diro.tc}, REQ {diro.req}, " + "TCG {diro.tcgroup}, RG {diro.reqgroup}" + ) + + def sync(self: NodeSet): + """Compute the all_ attributes of this set from what we know of the + current elements in the set. All the all_ attributes are set to False + on empty sets.""" + + # Beware of queries over empty sets. All the some_ attributes + # start False, so the all_ attributes would turn true if we're + # not cautious + + has_diro = len(self.diros) > 0 + + self.all_tc = has_diro and not self.some_nottc + self.all_req = has_diro and not self.some_notreq + self.all_set = has_diro and not self.some_notset + self.all_app = has_diro and not self.some_notapp + + self.all_reqset = has_diro and not self.some_notreqset + self.all_tcset = has_diro and not self.some_nottcset + self.all_appset = has_diro and not self.some_notappset + + self.all_reqorset = has_diro and not self.some_notreqorset + self.all_tcorset = has_diro and not self.some_nottcorset + + self.all_reqgroup = has_diro and not self.some_notreqgroup + self.all_tcgroup = has_diro and not self.some_nottcgroup + self.all_appmat = has_diro and not self.some_notappmat + + self.all_reqorgroup = has_diro and not self.some_notreqorgroup + self.all_tcorgroup = has_diro and not self.some_nottcorgroup + + +# *************************** +# ** Directory abstraction ** +# *************************** + +# The kind of material node that the directory holds. This is used +# to determine the hyperlink and the page title texts + + +class DirKind: + def __init__(self: DirKind, txthdl: str, image: str): + self.image = image + self.txthdl = txthdl + + +class dcl: + TC = DirKind(image="tc", txthdl="Testcase") + + TCG = DirKind(image="tcg", txthdl="Testcase Group") + + REQ = DirKind(image="rq", txthdl="Requirement") + + REQG = DirKind(image="rqg", txthdl="Requirement Group") + + APP = DirKind(image="app", txthdl="Appendix Material") + + INTRO = DirKind(image="intro", txthdl="Introductory Material") + + kinds = (TC, TCG, REQ, REQG, APP, INTRO) + + +# DocGenerator helper to process one specific subdirectory of the TOR/TC +# hierarchy + + +class Dir(Artifact): + def __init__( + self: Dir, + root: str, + subdirs: List[str], + files: List[str], + parent: Optional[Dir], + ): + # Filesystem attributes for this directory + + def to_id(name: str) -> str: + """remove leading number from name""" + m = re.search(r"^[0-9]+_(.*)$", name) + if m is not None: + return m.group(1) + else: + return name + + self.root = root # path to this dir + self.subdirs = subdirs # list of local subdir names + self.files = files # list of local file names + self.pdo = parent + self.id: str = "" + + self.name = os.path.basename(root) # local name of this dir + if self.pdo: + self.id = self.pdo.id + "/" + to_id(self.name) + else: + self.id = ( + "/" + + ART_ID_PREFIX + + to_id(self.root[len(os.path.abspath(ART_ROOTDIR)) :]) + ) + + # If we are at the root directory then return our documentation + # entry point. + if os.path.relpath(self.root, ART_ROOTDIR) == ".": + # predefined name of the root document + self._docfile_base_ = "index" + else: + # avoid name conflict with the root document + self._docfile_base_ = self.hash() + + # Links children in the directory tree. These are + # set as dir objects get mapped within a DirTree instance. + + # list of pruned Dir objects + self.subdos: List[Dir] = [] + # list of child Dir obejects eactly as they appear in the + # folder tree + self.children: List[Dir] = [] + + # NodeSet for subdos, which we'll populate when computing + # attributes bottom-up + + self.sdset: NodeSet | None = None + + # Properties from presence of local files, better cached to prevent + # repeated real file presence checks + + self.req: bool = "req.rst" in self.files + self.hreq: bool = "hreq.rst" in self.files + self.test: bool = "test.py" in self.files + self.tc: bool = "tc.rst" in self.files + self.htc: bool = "htc.rst" in self.files + self.chset: bool = "content.rst" in self.files + self.reqset: bool = "req_set.rst" in self.files + self.tcset: bool = "tc_set.rst" in self.files + self.app: bool = "app.rst" in self.files + + # TODO: decide later if this is required + # currently it is to silence the warning about missing description file + self.tcres = "test.rep" in self.files + + self.set = self.chset or self.reqset or self.tcset + + # title name, to be displayed in index tables, and sorting key. + + # The sorting key is the directory name (not title name) for starters, + # which is meant to allow prefix characters (numbers prior to the + # first '_') to influence sorts while not being displayed. We will + # need to update that when bridging over nodes, to make sure that the + # children remain grouped wrt their new parent and set of siblings. + + self.tname = to_title(self.name) + self.sname = self.name + + # source file copies for rst toctree + self.sources: Set[str] = set() + + # ------------------------------------------ + # -- Bottom-Up node attribute computation -- + # ------------------------------------------ + + def botmup_compute_attributes(self: Dir, pathi, data): + # Compute predicates over our set of children. We expect the children + # attributes to be available here. + # + # pathi and data are note used here. The method is eventually called + # through a generic lambda function "process" that may instantiate + # to a method that does use them. + + self.sdset = NodeSet(diros=self.subdos) + + # Populate extra attributes on this node + + self.container = self.set or self.req or self.reqset or self.tcset + + # TC, APP or REQ SETS are nodes with consistent children (all reqs, + # all tcs, or all apps). + + self.appset = self.set and self.sdset.all_app + + # Some mixes are legitimate, as long as the leaf item kinds (tc + # or req) remain consistent. We call GROUPS those containers, and at + # this stage we let the notion propagate up pretty freely: + + self.tcgroup = self.set and self.sdset.all_tcorgroup + self.reqgroup = self.set and self.sdset.all_reqorgroup + self.appmat = self.app or (self.set and self.sdset.all_appmat) + + # when configuration permits implicit folder types then derive type for + # folders without an existing content file + if self.children and not self.dfile(): + if ALLOW_UNCLASSIFIED_FOLDERS: + if self.sdset.all_reqorgroup: + self.reqset = True + elif self.sdset.all_tcorgroup: + self.tcset = True + else: + warn( + f"Artifact without a default content file" + f" in {self.full_name}", + "ARTIFACT_WITH_CHILDREN_NO_FILE", + ) + + # Consistency checks need to be applied elswhere to determine whether + # such or such mix is acceptable. Consider for example the difference + # in consistency between + # + # 1) either: + # set/tc + # /tc + # /tc + # + # or: + # set/set/tc + # /tc + # /set/tc + # /tc + # + # (only allow sets of TCs, or sets of sets) + # + # 2) or possibly + # set/set/tc + # /tc + # /tc + # + # (allow sets of either tc or set) + + # Now compute the node KIND, which conveys how we want the node to be + # referenced (in index table hyperlinks) and titled. This is not meant + # to be representative of structural properties. REQ nodes often are + # tcset or tcgroup as well, for example. + + self.kind = ( + dcl.TC + if self.tc + else ( + dcl.REQ + if self.req + else ( + dcl.TCG + if self.tcgroup + else ( + dcl.REQG + if self.reqgroup + else dcl.APP if self.appmat else dcl.INTRO + ) + ) + ) + ) + + def dfile(self: Dir, path: bool = False) -> str | None: + """Name of the text file which holds the meat of this dir/artifact""" + + base = ( + "tc.rst" + if self.tc + else ( + "content.rst" + if self.chset + else ( + "req_set.rst" + if self.reqset + else ( + "tc_set.rst" + if self.tcset + else ( + "req.rst" + if self.req + else ( + "htc.rst" + if self.htc + else ( + "hreq.rst" + if self.hreq + else "app.rst" if self.app else None + ) + ) + ) + ) + ) + ) + ) + + # if not base and self.sdset.some_tcorset: + # self.tcset = True + # base = "tc_set.rst" + + return os.path.join(self.root, base) if base and path else base + + @property + def ext_tcset(self: Dir) -> bool: + self.tcset = self.tcset or ( + not self.dfile() + and (self.sdset.some_tcorset if self.sdset else False) + ) + + return self.tcset + + def dtext(self: Dir) -> str: + if self.dfile() is None: + # This means that dtext was called on an artifact with unknown type + if ALLOW_UNCLASSIFIED_FOLDERS: + warn( + "Artifact without a default content file" + " in %s" % self.full_name + ) + return "" + else: + err( + "Artifact without a default content file in" + " %s" % self.full_name + ) + return "" + else: + file = self.dfile(path=True) + content = "" + if file and os.path.isfile(file): + content = get_content(file) + else: + warn("Content file %s does not exist." % file) + if self.tcset: + # the folder contains test cases, construct a default tcset + content = ( + self.id + + """ + +.. qmlink:: TCIndexImporter + + * +""" + ) + # ensure that content starts with title + if file and file.endswith(".rst"): + title_prefix = "" + title = "" + body = "" + title_candidate = "" + + for line in content.splitlines(): + if title: + # The title is identified. + # Add all the remaining lines to the body + body += "\n" + line + else: + if title_candidate: + # check the line following the title candidate + clean_line = line.strip() + if not clean_line: + # empty line after the first row. Promote the + # first row to be the title. + title = ( + title_candidate + + "\n" + + "*" * (len(title_candidate) + 1) + ) + elif ( + not re.search(r"[^=]", clean_line) + or not re.search(r"[^\*]", clean_line) + or not re.search(r"[^#]", clean_line) + ): + # first level title -- the next line is + # entirely composed of one of the title markers + title = title_candidate + "\n" + clean_line + else: + # the following line contains arbitrary text + # give a warning and stop the search + warn(f"No title found in {file}") + break + else: + # no lines with content yet + # if we find one then that is treated as + # a title candidate. + if not line or line.startswith(".. "): + # preserve empty lines and rst directives + title_prefix += line + "\n" + else: + # any other text is considered as title + title_candidate = line.strip().strip("*") + + if title: + content = ( + title + + "\n\n" + + self.full_id + + "\n\n" + + self.parent_ref + + "\n\n" + + body + ) + + return content + + def docfile(self: Dir, no_extension: bool = True) -> str: + """Filename for the generated RST file""" + + if no_extension: + return self._docfile_base_ + else: + return self._docfile_base_ + ".rst" + + def get_children(self: Dir) -> Sequence[Dir]: + """Return list of subartifacts""" + return self.children + + def get_name(self: Dir) -> str: + return self.name + + def rest_doc_ref(self: Dir, id_as_title: bool = False) -> str: + """Returns a sphinx :doc: on a.docfile() + + By default uses the title string as link label. + id_as_title=True replaces it with id string. + """ + + return writer.qmref( + self.docfile(True), + replace_variables(self.title()) if not id_as_title else self.id, + ) + + @property + def full_name(self: Dir) -> str: + return self.root + + @property + def relatives(self: Dir) -> Sequence[Dir]: + """ + The list of sub-artifacts that are relative to self. + """ + return self.children + + @property + def relative_to(self) -> Optional[Dir]: + """ + The instance this artifact is relative to. + """ + return self.pdo + + @property + def full_id(self: Dir) -> str: + """Return an id prefixed with item kind""" + return "**" + self.kind.txthdl.upper() + "** " + self.id + + @property + def parent_ref(self: Dir) -> str: + """Return link to the parent object. + + Include artifact type when parent is requirement. + """ + if self.pdo: + return ( + "**Parent" + + ( + (" " + self.pdo.kind.txthdl.lower()) + if self.pdo.req + else "" + ) + + "** " + + self.pdo.rest_doc_ref() + ) + else: + return "" + + +# ******************************** +# ** Directory Tree abstraction ** +# ******************************** + +# Helper to manage dirname -> dirobject associations and establish +# parent/children relationships over dir objects, assuming the tree +# is walked top down. + +# Values to denote possible ways to walk a tree and possible actions to take +# at every directory node when walking the tree + + +topdown, botmup = range(2) + +dirProcess, dirSkip, dirCutPre, dirCutPost = range(4) +# dirProcess: process this node and walk children +# dirCutPre: don't process this node and don't walk children +# dirCutPost: process this node and don't walk children +# dirSkip: skip processing for this node, walk children nevertheless + +im = { + dirSkip: "dirSkip", + dirProcess: "dirProcess", + dirCutPre: "dirCutPre", + dirCutPost: "dirCutPost", +} + + +class DirTree: + def __init__(self: DirTree, roots: List[Dir]): + self.roots = roots + + # ------------------------------------------------------------ + # -- Tree walking facilities, once we're past the first doc -- + # -- generation pass, all the parent children links are set -- + # ------------------------------------------------------------ + + # Local facilities. Beware that walks are used to compute directory + # object attributes, so these can't be relied upon. + + class WalkInfo: + def __init__( + self: DirTree.WalkInfo, + data: DirTree.WalkInfo | None, + pathi: PathInfo, + process: Callable | None, + ctl: Callable, + mode: int, + ): + self.process = process if process else lambda diro, pathi, wi: None + self.ctl = ctl + self.mode = mode + self.pathi = pathi + self.data = data + + def __enter(self: DirTree, diro: Dir, wi): + if diro.req: + wi.pathi.n_req += 1 + if diro.tc: + wi.pathi.n_tc += 1 + return wi.ctl(diro, wi.pathi, wi.data) + + def __exit(self: DirTree, diro: Dir, wi: DirTree.WalkInfo): + if diro.req: + wi.pathi.n_req -= 1 + if diro.tc: + wi.pathi.n_tc -= 1 + + def __visit(self: DirTree, diro: Dir, wi: DirTree.WalkInfo): + ctl = self.__enter(diro, wi) + + process_this = ctl not in [dirSkip, dirCutPre] + visit_children = ctl not in [dirCutPre, dirCutPost] + + if process_this and wi.mode == topdown: + wi.process(diro, wi.pathi, wi.data) + + if visit_children: + wi.pathi.depth += 1 + [self.__visit(subdo, wi) for subdo in diro.subdos] + wi.pathi.depth -= 1 + + if process_this and wi.mode == botmup: + wi.process(diro, wi.pathi, wi.data) + + self.__exit(diro, wi) + + def __default_ctl(self: DirTree, diro: Dir, pathi, widata): + return dirProcess + + # Exposed facilities. + + def walk( + self: DirTree, + mode: int, + process: Callable, + data: WalkInfo | None = None, + ctl: Callable | None = None, + ): + if ctl is None: + ctl = self.__default_ctl + + [ + self.__visit( + diro=diro, + wi=DirTree.WalkInfo( + process=process, + pathi=PathInfo(), + data=data, + mode=mode, + ctl=ctl, + ), + ) + for diro in sorted(self.roots, key=Dir.get_name) + ] + + # --------------------------------------- + # -- Tree filtering/pruning facilities -- + # --------------------------------------- + + def rprune(self: DirTree, namelist: List[str]): + """prune all subdirs of self that are do *not* lead to any dir + in NAMELIST""" + + class WalkInfo: + def __init__(self: WalkInfo, tokeep: List[str]): + self.tokeep = tokeep + self.toprune: List[Dir] = [] + + def prunectl(diro: Dir, pathi, wi: WalkInfo) -> int: + # See if diro is within or beyond any of our dirs to keep. + # Keep going (skip) if within. Cut search if beyond. + + # Append "/" to items to prevent "bla/C" from being considered + # a directory prefix of "bla/Common" + + rootdir = diro.root + os.sep + + for tokeep in wi.tokeep: + dirtokeep = tokeep + os.sep + if os.path.commonprefix((rootdir, dirtokeep)) == rootdir: + return ( + dirSkip if len(rootdir) < len(dirtokeep) else dirCutPre + ) + + # diro is for sure not within or down any of our dirs to keep. + # register for actual pruning and don't search past it. + + wi.toprune.append(diro) + return dirCutPre + + # Walk this tree to compute the list of directories to prune, then do + # prune for real. We don't effectively prune nodes during the walk to + # prevent mishaps caused by changes to our internal datastructures + # while they are being processed. + + wi = WalkInfo(tokeep=namelist) + self.walk( + mode=topdown, + process=lambda diro, pathi, wi: None, + ctl=prunectl, + data=wi, + ) + + for diro in wi.toprune: + if diro.pdo: + diro.pdo.subdos.remove(diro) + + # --------------------- + # -- Sorting entries -- + # --------------------- + + def sort(self: DirTree): + """Sort the list of subdirectory objects registered for each tree + node, to influence processing order in tree walks (hence insertion + order in auto-indexes)""" + + def sort_subdos(diro, pathi, wi): + # Sort subdirectories of DIRO. Arrange to get + # + # * All the non containers first, to make sure that + # + # sub/x + # y + # + # gets out as + # + # y bla + # sub blo + # x blu + # + # and not as + # + # sub blo + # x blu + # y bla + # + # where y would be perceived as a child of "sub" + # + # * Those for which a local key in their respective key order, + # all before or after those without explicit keys depending + # on the "default" entry, + # + # * In every subcase, sort by subdirectory name + + # Fetch the local { subdirname: key } dictionary, if any + + kfile = os.path.join(diro.root, "keys.txt") + keys = ( + json.loads(get_content(kfile)) + if os.path.exists(kfile) + else {"default": 0} + ) + + # Then sort according to our three criteria of interest + + diro.subdos.sort( + key=lambda subdo: ( + subdo.container, + ( + keys[subdo.sname] + if subdo.sname in keys + else keys["default"] + ), + subdo.sname, + ) + ) + + self.walk(mode=botmup, process=sort_subdos) + + # ----------------------------------------- + # -- Checking directory tree consistency -- + # ----------------------------------------- + + def check_local_consistency(self: DirTree, diro: Dir, pathi: PathInfo): + """Perform checks on the files present in DIRO""" + + warn_if( + not ( + diro.set + or diro.req + or diro.tc + or diro.app + or diro.htc + or diro.hreq + or diro.tcres + ), + "missing description text at %s" % diro.root, + "MISSING_DESCRITPTION_TEXT", + ) + rst_count = len([f for f in diro.files if f.endswith(".rst")]) + warn_if( + diro.req and rst_count > 1, + "req.rst not alone in %s" % diro.root, + ) + warn_if( + diro.chset and rst_count > 1, + "content.rst not alone in %s" % diro.root, + ) + warn_if( + diro.tc and not diro.test, + "tc.rst without test.py in %s" % diro.root, + ) + warn_if( + diro.test and not diro.tc and not diro.htc, + "test.py without tc.rst in %s" % diro.root, + ) + + warn_if( + (diro.tc or diro.tcgroup) and pathi.n_req < 1, + "tc or set without req uptree at %s" % diro.root, + ) + + warn_if( + diro.req and pathi.n_req > 1, + "nested req (%d up) at %s" % (pathi.n_req - 1, diro.root), + ) + + warn_if( + diro.req and pathi.n_tc > 0, + "req with tc uptree at %s" % diro.root, + ) + + def check_downtree_consistency(self, diro, pathi): + """Perform checks on the relationships DIRO and its children""" + + warn_if( + (diro.req or diro.set) and not diro.subdos, + "missing subdirs for artifact at %s" % diro.root, + ) + + if not diro.subdos: + return + + # Warn on structural inconsistencies + + warn_if( + diro.req and not diro.sdset.all_tcorgroup, + "inconsistent subdirs down req.rst at %s" % diro.root, + ) + + warn_if( + diro.req + and not (diro.sdset.all_reqorgroup or diro.sdset.all_tcorgroup), + "missing testcases for leaf req in %s" % diro.root, + ) + + # Warn on missing testing strategy in leaf requirement with multiple + # testcases + + # CAN NOT BE DIAGNOSED IN RST DATA ANY MORE + + # warn_if( + # diro.req + # and len(diro.subdos) > 1 + # and diro.sdset.all_tcorset + # and "%(tstrategy-headline)s" not in diro.dtext(), + # "req at %s misses testing strategy description" % diro.root, + # ) + + def topdown_check_consistency( + self: DirTree, diro: Dir, pathi: PathInfo, data + ): + self.check_local_consistency(diro, pathi) + self.check_downtree_consistency(diro, pathi) + + def check_consistency(self: DirTree): + self.walk(mode=topdown, process=self.topdown_check_consistency) + + +class DirTree_FromPath(DirTree): + def __init__(self: DirTree_FromPath, rootp: str): + DirTree.__init__(self, roots=[]) + + # First compute the tree of directory objects starting at path ROOTP, + # setting up for each the .pdo link to parent and the .subdos list of + # children. This is achieved by performing a top down walk of the os + # directory structure. + + self.dir = {} # dir-name -> dir-object dictionary + [ + self.topdown_map(dirname, subdirs, files) + for (dirname, subdirs, files) in os.walk(os.path.abspath(rootp)) + ] + + # Arrange for the intermediate directories just there for file + # organisation purposes to disappear from our tree representation + + self.do_cross_overs() + + # Then compute exta node attributes, once the tree of internal + # directory objects is setup. + + self.compute_attributes() + + def topdown_map( + self: DirTree_FromPath, + dirname: str, + subdirs: List[str], + files: List[str], + ): + # Map directory DIRNAME into our dictionary and set up links to/from + # its parent directory, if any. We're called along a topdown walk, so + # we have mapped the parent directory already if there is one. + + # Ignore some subdirectories + for d in subdirs.copy(): + if ( + d in (".svn", "mylib", "App", "__pycache__") + or "src" in d + or "obj" in d + or d.startswith("tmp_") + or d.startswith("s_") + or d.startswith("d_") + or d.startswith("m_") + or d.startswith("u_") + or os.path.exists(os.path.join(dirname, d, ".tor_ignore")) + ): + subdirs.remove(d) + + # Find out its parent object by name. If there's no parent object, + # this dir is a root. Setup the links otherwise. + + parentname = os.path.dirname(dirname) + + if parentname not in self.dir: + parento = None + else: + parento = self.dir[parentname] + + # Map a new object for this dir ... + + diro = Dir(root=dirname, subdirs=subdirs, files=files, parent=parento) + + self.dir[dirname] = diro + + # Set links to parent + + if not parento: + self.roots.append(diro) + else: + parento.subdos.append(diro) + parento.children.append(diro) + + # -------------------------------------------------------------- + # -- Abstract away nodes that were introduced only for source -- + # -- sharing purposes, and that should not introduce an extra -- + # -- layer in the qualification material. -- + # -- ----------------------------------------------------------- + + def __do_bridge_over(self: DirTree_FromPath, diro: Dir): + """Arrange for DIRO to disappear from the dir tree structure + it is in.""" + + print("======== Bridging over " + diro.root) + + # Remove this diro from the list of children of its parent, + # and update each of this diro's children to have its parent + # as a new parent instead of this diro itself. + + # Turn: + # P <----- PARENT + # | + # DIRO <----- TO VANISH + # | + # +---+---+---+ + # | | | | + # c1 c2 c3 c4 <---- CHILDREN + # + # into: + # + # P <----- PARENT + # | + # +---+---+---+ + # | | | | + # c1 c2 c3 c4 <---- CHILDREN + + if not diro.pdo: + err(f"malformed direcotry object: {diro.get_name()}") + return + + diro.pdo.subdos.remove(diro) + + for subdo in diro.subdos: + diro.pdo.subdos.append(subdo) + subdo.pdo = diro.pdo + + subdo.tname = ".".join([diro.tname, subdo.tname]) + subdo.sname = ".".join([diro.sname, subdo.sname]) + + def __decide_cross_over( + self: DirTree_FromPath, + diro: Dir, + pathi: PathInfo, + wi: DirTree.WalkInfo, + ): + """Add DIRO to WI.tobridge if DIRO ought to be removed from the + tree.""" + + file = diro.dfile(path=True) + if file is None: + file = "" + + if diro.set and os.path.getsize(file) == 0: + wi.tobridge.append(diro) + + def do_cross_overs(self: DirTree_FromPath): + """Remove (bridge links over) intermediate nodes that should not + produce intermediate layers in the final document.""" + + # Collect the set of nodes to remove first, then remove each one in + # turn. Removing while we're walking the tree is, mm, hazardous. + + class WalkInfo: + def __init__(self: WalkInfo): + self.tobridge = [] + + wi = WalkInfo() + self.walk(mode=topdown, process=self.__decide_cross_over, data=wi) + + [self.__do_bridge_over(diro) for diro in wi.tobridge] + + # --------------------------------------------- + # -- Computing tree/node attributes, before -- + # -- more sophisticated walks can take place -- + # --------------------------------------------- + + def compute_attributes(self: DirTree_FromPath): + self.walk(mode=botmup, process=Dir.botmup_compute_attributes) + + +# ************************ +# ** Document Generator ** +# ************************ + +icLink, icNid, icBrief = range(3) + + +class DocGenerator(object): + def __init__( + self: DocGenerator, + art_rootdir: str, + rst_rootdir: str, + options: optparse.Values, + ): + + # Command line options + self.o = options + + # Root of the directory tree where the qualification artifacts + # are to be found: + self.art_rootdir = os.path.abspath(art_rootdir) + + # Root of the directory tree where the generated document sources + # are to be produced: + self.rst_rootdir = os.path.abspath(rst_rootdir) + + if os.path.exists(self.rst_rootdir): + if self.o.force: + warn("Deleting an existing directory %s" % self.rst_rootdir) + for root, dirs, files in os.walk( + self.rst_rootdir, topdown=False + ): + for name in files: + os.remove(os.path.join(root, name)) + for name in dirs: + os.rmdir(os.path.join(root, name)) + os.rmdir(self.rst_rootdir) + else: + err( + "Directory %s already exists. " + "Use --force to delete it or clean up filesystem manually." + % self.rst_rootdir + ) + + os.mkdir(self.rst_rootdir) + + self.resource_list: Set[str] = set() + + # current output file descriptor, while walking the tor/tc tree + self.ofd: IO[Any] + + def register_resources(self: DocGenerator, rset: Set[str]): + self.resource_list |= rset + + def docpath_to(self: DocGenerator, filename: str) -> str: + return os.path.join(self.rst_rootdir, filename) + + def get_docfile( + self: DocGenerator, diro: Dir, must_exist: bool = False + ) -> str | None: + """Return full path to output file of diro. + If must_exist is True, then return the name only for existing files + """ + name = self.docpath_to(diro.docfile(no_extension=False)) + return name if not must_exist or os.path.isfile(name) else None + + def file2docfile( + self: DocGenerator, filename: str, must_exist: bool = False + ) -> str | None: + """Return the associated filename for a given path""" + docfile = os.path.relpath(filename, self.art_rootdir) + # If we are at the root directory then return our documentation + # entry point. + if docfile == ".": + return "index.rst" + + docfile = docfile.replace("/", "_").replace("\\", "_") + ".rst" + return docfile if not must_exist or os.path.isfile(docfile) else None + + def ref(self: DocGenerator, name: str) -> str: + """Transform string NAME into another string suitable to be used as + index name""" + result = os.path.relpath(name, self.art_rootdir) + return result.replace("/", "_").replace("\\", "_").replace(".", "_") + + # --------------------------------------------- + # -- Generating doc contents for a directory -- + # --------------------------------------------- + + def contents_from(self: DocGenerator, diro: Dir) -> str: + """Fetch descriptive text form the file corresponding to diro. + Append a TC index to TC set descriptions that don't have one.""" + + # Fetch the descriptive text + + res = diro.dtext() + + # Compute the dictionary of substitutions to apply + + # SUBST = { + # "toplevel-index": self.toplev_index, + # "tc-index": self.tc_index, + # "app-index": self.app_index, + # "subset-index": self.subset_index, + # "global-reqindex": self.global_reqindex, + # "req-headline": self.req_headline, + # "tstrategy-headline": self.tstrat_headline, + # "toc": self.toc, + # } + + # dosubst = { + # (key, SUBST[key](diro)) + # for key in SUBST + # if (f"%({key})s") in contents + # } + # Compute the extra text to add at the end, depending on + # the kind of artifact and on what substitutions apply + + # extratext = ( + # self.tc_index(diro) + # if ( + # diro.tcgroup + # and "tc-index" not in dosubst + # and "subset-index" not in dosubst + # ) + # else "" + # ) + # if len(dosubst) != 0: + # try: + # res = contents % dosubst # + extratext + # except Exception as e: + # err("Failed to apply substitutes %s\n\n%s" % (e, contents)) + # else: + # res = contents + res = replace_variables(res) + res = self.process_qmlink(diro, res) + + return res + + def process_qmlink( + self: DocGenerator, diro: Dir, content_text: str + ) -> str: + """extract ´.. qmlink::´ directives and replace their content""" + + res = "" + in_qmlink = False + subartifacts: Sequence[Artifact] = [] + importer: ArtifactImporter | None = None + for line in content_text.splitlines(): + if in_qmlink: + stripped_line = line.rstrip() + if stripped_line: + indent_len = len(stripped_line) - len( + stripped_line.strip() + ) + if indent_len == 0 or stripped_line.startswith(".. "): + # the indent declined or a new block + # end the current block + if importer: + qmlink_rst, links = importer.qmlink_to_rest( + diro, subartifacts + ) + diro.subdos += [ + item + for item in subartifacts + if item not in diro.subdos + ] + res += "\n" + qmlink_rst + + in_qmlink = False + subartifacts = [] + importer = None + + elif stripped_line.strip() == "*": + subartifacts.extend( + sorted(diro.get_children(), key=Dir.get_name) + ) + else: + a = diro.get_child(stripped_line) + if a: + subartifacts.append(a) + else: + logger.log_error( + "Cannot locate artifact '" + + stripped_line + + "'" + ) + + if ArtifactImporter.is_qmlink(line): + in_qmlink = True + importer = resolve_importer(line) + if not importer: + logger.log_error( + "Cannot locate importer for '" + line + "'" + ) + elif not in_qmlink: + res += "\n" + line + + if importer and subartifacts: + # rst section in the end of the document + qmlink_rst, links = importer.qmlink_to_rest(diro, subartifacts) + diro.subdos += [ + item for item in subartifacts if item not in diro.subdos + ] + res += "\n" + qmlink_rst + + return res + + def gen_tc_section(self: DocGenerator, diro: Dir): + """Generate the TestCase Sources section, and register the + sources as resources + + TODO: This should really belong in an artifatc importer?? + """ + + def restore_extension(name: str) -> str: + """restores .ad[bs] extension in name""" + if name.endswith("_ads"): + return name[:-4] + ".ads" + elif name.endswith("_adb"): + return name[:-4] + ".adb" + elif name.endswith("_txt"): + return name[:-4] + ".txt" + else: + return name + + tco = TestCase(dir_name=diro.root, dgen=self) + + if ( + not tco.fnsources + and not tco.drsources + and not tco.hlpsources + and not tco.conspecs + ): + # no sources, nothing to process + return + + headers = ["Functional Sources", "Drivers Sources", "Helpers Sources"] + + func_list = sorted(tco.fnsources) + driver_list = sorted(tco.drsources) + helper_list = sorted(tco.hlpsources) + + func_list_ref = [self.ref(d) for d in func_list] + driver_list_ref = [self.ref(d) for d in driver_list] + helper_list_ref = [self.ref(d) for d in helper_list] + + func_list_qmref = [":ref:`%s`" % d for d in func_list_ref] + driver_list_qmref = [":ref:`%s`" % d for d in driver_list_ref] + helper_list_qmref = [":ref:`%s`" % d for d in helper_list_ref] + + if tco.conspecs: + consolidation_list_ref = [ + self.ref(d) for d in sorted(tco.conspecs) + ] + consolidation_list_qmref = [ + ":ref:`%s`" % d for d in consolidation_list_ref + ] + + headers += ["Consolidation Sources"] + + for_table_qmref = zip_longest( + func_list_qmref, + driver_list_qmref, + helper_list_qmref, + consolidation_list_qmref, + fillvalue="", + ) + + else: + consolidation_list_ref = [] + for_table_qmref = zip_longest( + func_list_qmref, + driver_list_qmref, + helper_list_qmref, + fillvalue="", + ) + + html_content = writer.only( + writer.csv_table(list(for_table_qmref), headers), "html" + ) + + self.ofd.write(html_content) + + diro.sources = { + restore_extension(f) + for f in ( + func_list_ref + + driver_list_ref + + helper_list_ref + + consolidation_list_ref + ) + if f + } + + self.register_resources( + tco.fnsources | tco.drsources | tco.hlpsources | tco.conspecs + ) + + # -------------------------------------- + # -- Tailored directory tree instance -- + # -------------------------------------- + + def art_dirtree_for( + self: DocGenerator, chapdirs: List[str] + ) -> DirTree_FromPath: + dirtree = DirTree_FromPath(rootp=self.art_rootdir) + + dirtree.rprune( + [os.path.join(self.art_rootdir, dirname) for dirname in chapdirs] + ) + + dirtree.check_consistency() + dirtree.sort() + + return dirtree + + # --------------------------- + # -- generate doc chapters -- + # --------------------------- + + ALT_TITLES = {"Qualif": "GNATcoverage TORs"} + + def __gen_doc_contents(self: DocGenerator, diro: Dir, pathi, wi): + """Generate the RST file for the DIRO artifact/directory-object, as + part of a dirtree walk carrying a general DirTree.WalkInfo object WI + and path info PATHI""" + + filename = self.get_docfile(diro) + if not filename: + err(f"Could not get filename for {diro.get_name()}") + return + if not os.path.isdir(os.path.dirname(filename)): + os.makedirs(os.path.dirname(filename)) + self.ofd = open(filename, "w") + + # FIXME Double-check why this was here. It adds an extra title not + # conforming to that in the existing qualkits + # ttext = ( + # self.ALT_TITLES[diro.tname] + # if diro.tname in self.ALT_TITLES else diro.tname + # ) + + # txthdl = diro.kind.txthdl + # self.ofd.write( + # rest.section(ttext + (" -- %s" % txthdl if txthdl else ""))) + + if diro.dfile(): + self.ofd.write(self.contents_from(diro)) + + if diro.tc: + # importer = qm_plugins.importers.default_importer(diro) + # qmlink_rst = importer.to_rest(diro) + # self.ofd.write(qmlink_rst) + self.gen_tc_section(diro) + + # close the document to measure the size + # that is more robust than trying to keep track of all the write + # operations and we can affort the small overhead of reopening it + # once more + self.ofd.close() + + # remove the document if no content was generated + if os.path.getsize(filename) == 0: + os.remove(filename) + else: + # reopen the file to add toc + self.ofd = open(filename, "a") + self.ofd.close() + + def generate_chapters(self: DocGenerator): + self.art_dirtree.walk(mode=topdown, process=self.__gen_doc_contents) + + # ---------------------------- + # -- generate resource file -- + # ---------------------------- + + def generate_resources(self: DocGenerator): + fd = open(self.docpath_to("resources.rst"), "w") + fd.write(rest.chapter("Resources")) + fd.write( + rest.toctree( + [ + file + for d in self.resource_list + if (file := self.file2docfile(d, must_exist=True)) + ] + ) + ) + fd.close() + + for r in self.resource_list: + filename = self.file2docfile(r) + if not filename: + err(f"Could not get doc filename for {r}") + return + fd = open(self.docpath_to(filename), "w") + fd.write("\n.. _%s:\n\n" % self.ref(r)) + fd.write(rest.section(os.path.basename(r))) + fd.write(rest.code_block(get_content(r), "ada")) + fd.close() + + # --------------------------------------------- + # -- generate all the document items, -- + # -- checking tree consistency along the way -- + # --------------------------------------------- + + def generate_all(self: DocGenerator): + # Compute the set of subdirs/chapters our document ought to include. + # This is the explicit list when one was provided, and a set of common + # subdirs + those of relevance for the requested criterion otherwise. + + crit_subdirs_for = { + "doC": ["stmt"], + "doB": ["stmt", "decision"], + "doA": ["stmt", "decision", "mcdc"], + } + + this_subdirs = ( + self.o.chapdirs.split(",") + if self.o.chapdirs + else ( + ["OpEnviron", "Appendix", "Common"] + + [ + os.path.join("Ada", csd) + for csd in crit_subdirs_for[self.o.dolevel] + ] + ) + ) + + VAR_REPLACEMENTS.update( + get_var_replacements(do_level=self.o.dolevel, doc_id=tor_doc_id) + ) + + self.art_dirtree = self.art_dirtree_for(this_subdirs) + + self.generate_chapters() + self.generate_resources() + + print_warn_stats() + + +# The main of the script + +valid_dolevels = ("doA", "doB", "doC") + +if __name__ == "__main__": + op = optparse.OptionParser(usage="%prog ") + + op.add_option( + "--dolevel", + dest="dolevel", + default=None, + type="choice", + choices=valid_dolevels, + help=("Target DO178 qualification level."), + ) + + op.add_option( + "--chapdirs", + dest="chapdirs", + default=None, + help=("Comma separated list of chapter directories to consider"), + ) + + op.add_option( + "--force", + dest="force", + action="store_true", + default=False, + help=("Delete existing output directory if it exists and continue"), + ) + + op.add_option( + "--verbose", + "-v", + dest="verbose", + action="store_true", + default=False, + help=("Show detailed info messages"), + ) + (options, args) = op.parse_args() + + exit_if( + not options.chapdirs and not options.dolevel, + "A DO level or a set of chapter dirs must be specified", + ) + + exit_if( + options.chapdirs and options.dolevel, + "A DO level may not be specified together with an explicit " + "set of chapter dirs.", + ) + + verbose = options.verbose + + mygen = DocGenerator( + art_rootdir=ART_ROOTDIR, rst_rootdir=RST_ROOTDIR, options=options + ) + + mygen.generate_all() diff --git a/qualification/tor/genrest_conf.py b/qualification/tor/genrest_conf.py new file mode 100644 index 000000000..722d08ee4 --- /dev/null +++ b/qualification/tor/genrest_conf.py @@ -0,0 +1,13 @@ +# configurable options of the genrest module + +# when this constant is true, genrest tries to deduce the artifact type of a +# folder that doesn't have content .rst file by looking a the subartifacts. +# In case of False, the processing stops with error if such a folder is +# encountered. + +ALLOW_UNCLASSIFIED_FOLDERS = False + +# a list of warning type patters that should be suppressed +# if there is a match, then genrest computes only the stats + +SUPRESS_MSG_TYPES = ["SRC_.*", "MISSING_DESCRITPTION_TEXT"] diff --git a/qualification/tor/missing_tr_log.txt b/qualification/tor/missing_tr_log.txt new file mode 100644 index 000000000..e69de29bb diff --git a/qualification/tor/proj_conf.py b/qualification/tor/proj_conf.py new file mode 100644 index 000000000..ccfe5d97e --- /dev/null +++ b/qualification/tor/proj_conf.py @@ -0,0 +1,8 @@ +from typing import Dict +from scripts.common_conf import VAR_REPLACEMENTS + + +def get_var_replacements(do_level: str, doc_id: str) -> Dict[str, str]: + """Return var replacements for the given project""" + + return VAR_REPLACEMENTS | {"doc_id": doc_id, "dolevel": do_level} diff --git a/qualification/tor/scripts/conf.py b/qualification/tor/scripts/conf.py deleted file mode 100644 index 9169ea24f..000000000 --- a/qualification/tor/scripts/conf.py +++ /dev/null @@ -1,216 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Couverture documentation build configuration file, created by -# sphinx-quickstart on Fri Nov 19 14:56:55 2010. -# -# This file is execfile()d with the current directory set to its containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys, os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ----------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'GNATcoverage' -copyright = u'2011, AdaCore' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '1.0' -# The full version, including alpha/beta/rc tags. -release = '1.0' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - - -# -- Options for HTML output --------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ['.'] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -html_title = "%s TORs" % project - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = 'source/_static/intranet_branding.png' - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'GNATcoveragedoc' - - -# -- Options for LaTeX output -------------------------------------------------- - -# The paper size ('letter' or 'a4'). -#latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -#latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). -latex_documents = [ - ('index', 'GNATcoverage.tex', u'GNATcoverage Documentation', - u'AdaCore', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Additional stuff for the LaTeX preamble. -#latex_preamble = '' - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output -------------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'couverture', u'GNATcoverage Documentation', - [u'AdaCore'], 1) -] diff --git a/qualification/tor/scripts/genrest.py b/qualification/tor/scripts/genrest.py deleted file mode 100755 index f843d4455..000000000 --- a/qualification/tor/scripts/genrest.py +++ /dev/null @@ -1,1472 +0,0 @@ -#!/usr/bin/env python - -import os -import rest -import glob -import re -import sys -import json -import optparse - -from gnatpython.fileutils import mkdir - -# ***************************************************************************** -# ** GENERAL DESCRIPTION ** -# ***************************************************************************** - -# This file implements the core of the GNATcoverage TOR document production, -# generating sphinx-REST from artifacts held within our testsuite/Qualif -# filesystem tree. - -# Except on rare occasions, each directory in this tree represents some TOR -# related entity: requirement, testcase, appendix material, or groups of such, -# possibly nested (groups may hold direct artifacts or further intermediate -# groups). -# -# The general structure is very hierarchical, going from requirement -# groups (REQG kind) to requirements (REQ kind), to testcases (TC kind) -# possibly via testcase groups (TCG kind). -# -# Very roughly, our processing here first constructs an internal tree -# datastructure representing the directory tree, where each node holds -# attributes qualifying its nature (e.g. "this node/directory holds a -# testcase"). This is determined from two elements: -# -# * The presence in the directory of some text file: -# - tc.txt for a testcase, -# - req.txt for a requirement, -# - set.txt for a group -# -# * For groups, the node is further qualified by looking at the set of -# children of the node. Despite the possibility to nest groups within -# groups, mixing a testcase artifacts at the same level as requirement -# artifacts is disallowed. - -# Relative to where this script reside, path to ... - -# The root of the directory tree mapping qualification artifacts -# (requirements, testcases, ...): - -RST_ROOTDIR = "source" - -# The root of the directory where the REST documents describing -# these artifacts will reside: - -ART_ROOTDIR = "../../../testsuite/Qualif" - -# ********************** -# ** Helper functions ** -# ********************** - -def get_content(filename): - """Return contents of file FILENAME as a string""" - - fd = open(filename, 'r') - content = fd.read() - fd.close() - return content - -def copy(l): - """Return a copy of list L""" - return [item for item in l] - -def to_title(str): - """Given an entity name return a suitable string to be insterted - in the documentation""" - m = re.search(r'^[0-9]+_(.*)$', str) - if m is not None: - str = m.group(1) - return str.replace('_', ' ') - -def header(str, pre_skip, post_skip): - """Return the string to be used as a section header for STR, - framed with PRE_SKIP new_lines before and POST_SKIP new_lines after""" - return '\n' * pre_skip + str + '\n' * post_skip - -def sec_header(str): - """Return a Section header text to be used for section title STR""" - return header(rest.strong(str), pre_skip=2, post_skip=2) - -def subsec_header(str): - """Return a Subsection header text to be used for subsection title STR""" - return header(rest.emphasis(str), pre_skip=2, post_skip=2) - -def warn(text): - print "warning: %s" % text - -def warn_if(cond, text): - if cond: warn(text) - -def exit_if (p, msg): - if p: - print msg - sys.exit(1) - -# ************************** -# ** TestCase abstraction ** -# ************************** - -# Helper for the Directory abstraction, to encapsulate research of driver -# and functional source file sets - -class TestCase: - def __init__(self, dir, dgen): - self.dir = dir - self.dgen = dgen - - self.fnsources = None - self.drsources = None - self.find_sources() - - def parent_globbing(self, dir, pattern, include_start_dir=True): - """Look for src/[pattern] files in dir and its parents directory - up to document root directory""" - head = os.path.relpath(dir, self.dgen.art_rootdir) - tail = '' - if not include_start_dir: - head, tail = os.path.split(head) - files = set([]) - while len(head) > 0: - files |= set( - glob.glob( - os.path.join(self.dgen.art_rootdir, head, 'src', pattern)) - ) - head, tail = os.path.split(head) - return files - - def find_with_clauses(self, dir, sourcefile): - content = get_content(sourcefile) - # Remove all comments - content = '\n'.join([k for k in content.splitlines() \ - if not re.match('\s*--', k)]) - - # Find all the with clauses - matches = re.findall(r'(?:\n|;|^)\s*with\s*([^;]+)\s*;', content, re.S) - matches = [k.replace(' ', '') for k in matches] - matches = [k.replace('.', '-') for k in matches] - - result = [] - [result.extend (m.lower().split(',')) for m in matches] - result = set(result) - - # Remove packages we don't care about and probably could locate - result -= set(['support', 'system']) - - file_list = set([]) - for item in result: - - spec = self.parent_globbing(dir, item + '.ads', True) - warn_if (len(spec) > 1, 'multiple specs for unit "%s"' % item) - file_list |= spec - - body = self.parent_globbing(dir, item + '.adb', True) - warn_if (len(body) > 1, 'multiple bodies for unit "%s"' % item) - file_list |= body - - warn_if (len(body | spec) == 0, - 'no body or spec source found for unit "%s" (from %s)' - % (item, sourcefile)) - - return file_list - - def find_closure(self, dir, sourcefile): - """Given an Ada source file find it's closure. Not that we ignore the - support package""" - - result_set = self.find_with_clauses(dir, sourcefile) - - current_size = len(result_set) - previous_size = 0 - while current_size > previous_size: - - previous_size = current_size - tmp = set([]) - for item in result_set: - tmp |= self.find_with_clauses(dir, item) - - result_set |= tmp - current_size = len(result_set) - - return result_set - - def find_sources(self): - """Locate the functional and driver sources of testcase SELF""" - - # Seek the test drivers first, and infer closure from there. Then - # append consolidation specs to the set of drivers. We will typically - # end up on common functional units from drivers, so use sets to - # prevent dupicates. - - # Test drivers: search the local "src" subdir first, walk uptree - # if no driver there. - - local_sources = set( - glob.glob(os.path.join(self.dir, 'src', '*.ad[sb]'))) - - self.drsources = set( - [k for k in local_sources - if os.path.basename(k).startswith('test_')]) - - if len(self.drsources) == 0: - data_names = set( - [os.path.basename(k).split('.')[0] for k in local_sources]) - [self.drsources.update( - self.parent_globbing(self.dir, 'test_'+name+'*.ad[sb]')) - for name in data_names] - - warn_if (len(self.drsources) == 0, - 'no driver source for testcase in %s' % self.dir) - - # Driver Closure: - - self.fnsources = set([]) - [self.fnsources.update(self.find_closure(self.dir, driver)) - for driver in self.drsources] - - warn_if (len(self.fnsources) == 0, - 'no functional source for testcase in %s' % self.dir) - - # Consolidation specs. These are always local. - - self.conspecs = set([]) - self.conspecs |= set( - glob.glob(os.path.join(self.dir, 'src', 'cons_*.txt'))) - -# *************************** -# ** Path Info abstraction ** -# *************************** - -class PathInfo: - """Holds info about the path to the current node when walking - a directory tree""" - - def __init__(self): - self.n_req = 0 # Number of requirement expressions so far - self.n_tc = 0 # Number of tc nodes so far - self.depth = 0 # Depth of this node wrt root of walk operation - -# ************************** -# ** Node Set abstraction ** -# ************************** - -class NodeSet: - - """Node Set abstraction, used to compute composite attributes - for a set of nodes. We compute two categories of composite attributes: - - * The "some_" attributes tell whether some (at least one) node in set has - such or such characteristic. These are updated as nodes are added to the - set, via the "register_one" method. - - * The "all_" attributes tell whether all the nodes in the set has such or - such characteristic. These are computed from the current "some_" values - when the "sync" method is called, - """ - - def __init__(self, diros=()): - """Initialize the some_ attributes for SELF, then register - each directory object in the DIROS sequence and sync() to update - the all_ attributes from there.""" - - self.some_reqgroup = False - self.some_notreqgroup = False - self.some_tcgroup = False - self.some_nottcgroup = False - self.some_appmat = False - self.some_notappmat = False - - self.some_reqorset = False - self.some_notreqorset = False - self.some_tcorset = False - self.some_nottcorset = False - - self.some_reqorgroup = False - self.some_notreqorgroup = False - self.some_tcorgroup = False - self.some_nottcorgroup = False - - self.some_req = False - self.some_notreq = False - self.some_tc = False - self.some_nottc = False - self.some_app = False - self.some_notapp = False - self.some_set = False - self.some_notset = False - - self.some_notreqset = False - self.some_nottcset = False - self.some_notappset = False - - self.diros = [] - - [self.register_one (diro) for diro in diros] - self.sync() - - def register_one (self, diro): - """Add one directory object to this set, updating the - some_ attributes accordingly.""" - - self.some_req |= diro.req - self.some_tc |= diro.tc - self.some_set |= diro.set - self.some_app |= diro.app - - self.some_notreq |= not diro.req - self.some_nottc |= not diro.tc - self.some_notset |= not diro.set - self.some_notapp |= not diro.app - - self.some_notreqset |= not diro.reqset - self.some_nottcset |= not diro.tcset - self.some_notappset |= not diro.appset - - self.some_reqgroup |= diro.reqgroup - self.some_notreqgroup |= not diro.reqgroup - - self.some_tcgroup |= diro.tcgroup - self.some_nottcgroup |= not diro.tcgroup - - self.some_appmat |= diro.appmat - self.some_notappmat |= not diro.appmat - - self.some_reqorset |= diro.req | diro.reqset - self.some_tcorset |= diro.tc | diro.tcset - - self.some_notreqorset |= not (diro.req | diro.reqset) - self.some_nottcorset |= not (diro.tc | diro.tcset) - - self.some_reqorgroup |= diro.req | diro.reqgroup - self.some_tcorgroup |= diro.tc | diro.tcgroup - - self.some_notreqorgroup |= not (diro.req | diro.reqgroup) - self.some_nottcorgroup |= not (diro.tc | diro.tcgroup) - - self.diros.append (diro) - - def sync(self): - """Compute the all_ attributes of this set from what we know of the - current elements in the set. All the all_ attributes are set to False - on empty sets.""" - - # Beware of queries over empty sets. All the some_ attributes - # start False, so the all_ attributes would turn true if we're - # not cautious - - has_diro = len(self.diros) > 0 - - self.all_tc = has_diro and not self.some_nottc - self.all_req = has_diro and not self.some_notreq - self.all_set = has_diro and not self.some_notset - self.all_app = has_diro and not self.some_notapp - - self.all_reqset = has_diro and not self.some_notreqset - self.all_tcset = has_diro and not self.some_nottcset - self.all_appset = has_diro and not self.some_notappset - - self.all_reqorset = has_diro and not self.some_notreqorset - self.all_tcorset = has_diro and not self.some_nottcorset - - self.all_reqgroup = has_diro and not self.some_notreqgroup - self.all_tcgroup = has_diro and not self.some_nottcgroup - self.all_appmat = has_diro and not self.some_notappmat - - self.all_reqorgroup = has_diro and not self.some_notreqorgroup - self.all_tcorgroup = has_diro and not self.some_nottcorgroup - -# *************************** -# ** Directory abstraction ** -# *************************** - -# The kind of material node that the directory holds. This is used -# to determine the hyperlink and the page title texts - -class DirKind: - def __init__ (self, txthdl, image): - self.image = image - self.txthdl = txthdl - -class dcl: - - TC = DirKind ( - image="tc", txthdl = "Testcase") - - TCG = DirKind ( - image="tcg", txthdl = "Testcase Group") - - REQ = DirKind ( - image="rq", txthdl = "Requirement") - - REQG = DirKind ( - image="rqg", txthdl = "Requirement Group") - - APP = DirKind ( - image="app", txthdl = "Appendix Material") - - INTRO = DirKind ( - image="intro", txthdl = "Introductory Material") - - kinds = (TC, TCG, REQ, REQG, APP, INTRO) - -# DocGenerator helper to process one specific subdirectory of the TOR/TC -# hierarchy - -class Dir: - def __init__(self, root, subdirs, files): - - # Filesystem attributes for this directory - - self.root = root # path to this dir - self.subdirs = subdirs # list of local subdir names - self.files = files # list of local file names - - self.name = os.path.basename(root) # local name of this dir - - # Links to parent and children in the directory tree. These are - # set as dir objects get mapped within a DirTree instance. - - self.pdo = None - self.subdos = [] - - # NodeSet for subdos, which we'll populate when computing - # attributes bottom-up - - self.sdset = None - - # Properties from presence of local files, better cached to prevent - # repeated real file presence checks - - self.req = "req.txt" in self.files - self.hreq = "hreq.txt" in self.files - self.test = "test.py" in self.files - self.tc = "tc.txt" in self.files - self.htc = "htc.txt" in self.files - self.set = "set.txt" in self.files - self.app = "app.txt" in self.files - - # title name, to be displayed in index tables, and sorting key. - - # The sorting key is the directory name (not title name) for starters, - # which is meant to allow prefix characters (numbers prior to the - # first '_') to influence sorts while not being displayed. We will - # need to update that when bridging over nodes, to make sure that the - # children remain grouped wrt their new parent and set of siblings. - - self.tname = to_title (self.name) - self.sname = self.name - - # ------------------------------------------ - # -- Bottom-Up node attribute computation -- - # ------------------------------------------ - - def botmup_compute_attributes (self, pathi, data): - - # Compute predicates over our set of children. We expect the children - # attributes to be available here. - - self.sdset = NodeSet (diros=self.subdos) - - # Populate extra attributes on this node - - self.container = self.set or self.req - - # TC, APP or REQ SETS are nodes with consistent children (all reqs, - # all tcs, or all apps). - - self.tcset = self.set and self.sdset.all_tc - self.reqset = self.set and self.sdset.all_req - self.appset = self.set and self.sdset.all_app - - # Some mixes are legitimate, as long as the leaf item kinds (tc - # or req) remain consistent. We call GROUPS those containers, and at - # this stage we let the notion propagate up pretty freely: - - self.tcgroup = self.set and self.sdset.all_tcorgroup - self.reqgroup = self.set and self.sdset.all_reqorgroup - self.appmat = self.app or (self.set and self.sdset.all_appmat) - - # Consistency checks need to be applied elswhere to determine whether - # such or such mix is acceptable. Consider for example the difference - # in consistency between - # - # 1) either: - # set/tc - # /tc - # /tc - # - # or: - # set/set/tc - # /tc - # /set/tc - # /tc - # - # (only allow sets of TCs, or sets of sets) - # - # 2) or possibly - # set/set/tc - # /tc - # /tc - # - # (allow sets of either tc or set) - - # Now compute the node KIND, which conveys how we want the node to be - # referenced (in index table hyperlinks) and titled. This is not meant - # to be representative of structural properties. REQ nodes often are - # tcset or tcgroup as well, for example. - - self.kind = ( - dcl.TC if self.tc - else dcl.REQ if self.req - else dcl.TCG if self.tcgroup - else dcl.REQG if self.reqgroup - else dcl.APP if self.appmat - else dcl.INTRO) - - def dfile(self, path=False): - """Name of the text file which holds the meat of this dir/artifact""" - - base = ( - 'tc.txt' if self.tc else - 'set.txt' if self.set else - 'req.txt' if self.req else - 'htc.txt' if self.htc else - 'hreq.txt' if self.hreq else - 'app.txt' if self.app else - None) - - return ( - os.path.join (self.root, base) if base and path - else base) - - def dtext (self): - if self.dfile() == None: - warn ("missing description file in %s" % self.root) - return "" - else: - return get_content (self.dfile(path=True)) - - -# ******************************** -# ** Directory Tree abstraction ** -# ******************************** - -# Helper to manage dirname -> dirobject associations and establish -# parent/children relationships over dir objects, assuming the tree -# is walked top down. - -# Values to denote possible ways to walk a tree and possible actions to take -# at every directory node when walking the tree - -topdown, botmup = range (2) - -dirProcess, dirSkip, dirCutPre, dirCutPost = range (4) -# dirProcess: process this node and walk children -# dirCutPre: don't process this node and don't walk children -# dirCutPost: process this node and don't walk children -# dirSkip: skip processing for this node, walk children nevertheless - -im = { dirSkip: "dirSkip", dirProcess: "dirProcess", - dirCutPre: "dirCutPre", dirCutPost: "dirCutPost" } - -class DirTree: - def __init__(self, roots): - self.roots = roots - - # ------------------------------------------------------------ - # -- Tree walking facilities, once we're past the first doc -- - # -- generation pass, all the parent children links are set -- - # ------------------------------------------------------------ - - # Local facilities. Beware that walks are used to compute directory - # object attributes, so these can't be relied upon. - - class WalkInfo: - def __init__(self, data, pathi, process, ctl, mode): - self.process = process - self.ctl = ctl - self.mode = mode - self.pathi = pathi - self.data = data - - def __enter(self, diro, wi): - if diro.req: wi.pathi.n_req += 1 - if diro.tc: wi.pathi.n_tc += 1 - return wi.ctl (diro, wi.pathi, wi.data) - - def __exit(self, diro, wi): - if diro.req: wi.pathi.n_req -= 1 - if diro.tc: wi.pathi.n_tc -= 1 - - def __visit (self, diro, wi): - ctl = self.__enter(diro, wi) - - process_this = ctl not in [dirSkip, dirCutPre] - visit_children = ctl not in [dirCutPre, dirCutPost] - - if process_this and wi.mode == topdown: - wi.process(diro, wi.pathi, wi.data) - - if visit_children: - wi.pathi.depth += 1 - [self.__visit(subdo, wi) for subdo in diro.subdos] - wi.pathi.depth -= 1 - - if process_this and wi.mode == botmup: - wi.process(diro, wi.pathi, wi.data) - - self.__exit(diro, wi) - - def __default_ctl(self, diro, pathi, widata): - return dirProcess - - # Exposed facilities. - - def walk(self, mode, process, data=None, ctl=None): - - if ctl is None: ctl = self.__default_ctl - - [self.__visit ( - diro=diro, wi=DirTree.WalkInfo ( - process=process, pathi=PathInfo(), - data=data, mode=mode, ctl=ctl)) - for diro in self.roots] - - # --------------------------------------- - # -- Tree filtering/pruning facilities -- - # --------------------------------------- - - def rprune (self, namelist): - - """prune all subdirs of self that are do *not* lead to any dir - in NAMELIST""" - - class WalkInfo: - def __init__(self, tokeep): - self.tokeep = tokeep - self.toprune = [] - - def prunectl (diro, pathi, wi): - - # See if diro is within or beyond any of our dirs to keep. - # Keep going (skip) if within. Cut search if beyond. - - # Append "/" to items to prevent "bla/C" from being considered - # a directory prefix of "bla/Common" - - rootdir = diro.root + os.sep - - for tokeep in wi.tokeep: - dirtokeep = tokeep + os.sep - if os.path.commonprefix ((rootdir, dirtokeep)) == rootdir: - return ( - dirSkip if len(rootdir) < len(dirtokeep) - else dirCutPre) - - # diro is for sure not within or down any of our dirs to keep. - # register for actual pruning and don't search past it. - - wi.toprune.append (diro) - return dirCutPre - - # Walk this tree to compute the list of directories to prune, then do - # prune for real. We don't effectively prune nodes during the walk to - # prevent mishaps caused by changes to our internal datastructures - # while they are being processed. - - wi = WalkInfo (tokeep=namelist) - self.walk ( - mode=topdown, process=lambda diro, pathi, wi: None, - ctl=prunectl, data=wi) - - [diro.pdo.subdos.remove (diro) for diro in wi.toprune] - - # --------------------- - # -- Sorting entries -- - # --------------------- - - def sort (self): - - """Sort the list of subdirectory objects registered for each tree - node, to influence processing order in tree walks (hence insertion - order in auto-indexes)""" - - def sort_subdos(diro, pathi, wi): - - # Sort subdirectories of DIRO. Arrange to get - # - # * All the non containers first, to make sure that - # - # sub/x - # y - # - # gets out as - # - # y bla - # sub blo - # x blu - # - # and not as - # - # sub blo - # x blu - # y bla - # - # where y would be perceived as a child of "sub" - # - # * Those for which a local key in their respective key order, - # all before or after those without explicit keys depending - # on the "default" entry, - # - # * In every subcase, sort by subdirectory name - - # Fetch the local { subdirname: key } dictionary, if any - - kfile = os.path.join (diro.root, "keys.txt") - keys = ( - json.loads (get_content(kfile)) if os.path.exists(kfile) - else {"default": 0} - ) - - # Then sort according to our three criteria of interest - - diro.subdos.sort ( - key = lambda subdo: - (subdo.container, - keys[subdo.sname] if subdo.sname in keys - else keys["default"], - subdo.sname) - ) - - self.walk (mode=botmup, process=sort_subdos) - - # ----------------------------------------- - # -- Checking directory tree consistency -- - # ----------------------------------------- - - def check_local_consistency (self, diro, pathi): - """Perform checks on the files present in DIRO""" - - warn_if ( - not (diro.set or diro.req or diro.tc or diro.app - or diro.htc or diro.hreq), - "missing description text at %s" % diro.root) - warn_if (diro.req and len(diro.files) > 1, - "req.txt not alone in %s" % diro.root) - warn_if (diro.set and len(diro.files) > 1, - "set.txt not alone in %s" % diro.root) - warn_if (diro.tc and not diro.test, - "tc.txt without test.py in %s" % diro.root) - warn_if (diro.test and not diro.tc and not diro.htc, - "test.py without tc.txt in %s" % diro.root) - - warn_if ((diro.tc or diro.tcgroup) and pathi.n_req < 1, - "tc or set without req uptree at %s" % diro.root) - - warn_if (diro.req and pathi.n_req > 1, - "nested req (%d up) at %s" % (pathi.n_req - 1, diro.root)) - - warn_if (diro.req and pathi.n_tc > 0, - "req with tc uptree at %s" % diro.root) - - def check_downtree_consistency (self, diro, pathi): - """Perform checks on the relationships DIRO and its children""" - - warn_if ((diro.req or diro.set) and not diro.subdos, - "missing subdirs for artifact at %s" % diro.root) - - if not diro.subdos: return - - # Warn on structural inconsistencies - - warn_if (diro.req and not diro.sdset.all_tcorgroup, - "inconsistent subdirs down req.txt at %s" % diro.root) - - warn_if ( - diro.req and not (diro.sdset.all_reqorgroup - or diro.sdset.all_tcorgroup), - "missing testcases for leaf req in %s" % diro.root) - - # Warn on missing testing strategy in leaf requirement with multiple - # testcases - - warn_if (diro.req and len (diro.subdos) > 1 and diro.sdset.all_tcorset - and "%(tstrategy-headline)s" not in diro.dtext(), - "req at %s misses testing strategy description" % diro.root) - - def topdown_check_consistency (self, diro, pathi, data): - self.check_local_consistency(diro, pathi) - self.check_downtree_consistency(diro, pathi) - - def check_consistency(self): - self.walk (mode=topdown, process=self.topdown_check_consistency) - -class DirTree_FromPath (DirTree): - - def __init__(self, rootp): - - DirTree.__init__(self, roots=[]) - - # First compute the tree of directory objects starting at path ROOTP, - # setting up for each the .pdo link to parent and the .subdos list of - # children. This is achieved by performing a top down walk of the os - # directory structure. - - self.dir = {} # dir-name -> dir-object dictionary - [self.topdown_map (dirname, subdirs, files) - for (dirname, subdirs, files) in os.walk(os.path.abspath(rootp))] - - # Arrange for the intermediate directories just there for file - # organisation purposes to disappear from our tree representation - - self.do_cross_overs() - - # Then compute exta node attributes, once the tree of internal - # directory objects is setup. - - self.compute_attributes() - - def topdown_map(self, dirname, subdirs, files): - - # Map directory DIRNAME into our dictionary and set up links to/from - # its parent directory, if any. We're called along a topdown walk, so - # we have mapped the parent directory already if there is one. - - # Ignore some subdirectories - - [subdirs.remove(d) for d in copy(subdirs) - if d in ('.svn', 'src') or d.startswith('tmp_')] - - # Map a new object for this dir ... - - diro = Dir (root=dirname, subdirs=subdirs, files=files) - - self.dir[dirname] = diro - - # Find out its parent object by name. If there's no parent object, - # this dir is a root. Setup the links otherwise. - - parentname = os.path.dirname(dirname) - - if parentname not in self.dir: - self.roots.append(diro) - else: - parento = self.dir[parentname] - diro.pdo = parento - parento.subdos.append(diro) - - # -------------------------------------------------------------- - # -- Abstract away nodes that were introduced only for source -- - # -- sharing purposes, and that should not introduce an extra -- - # -- layer in the qualification material. -- - # -- ----------------------------------------------------------- - - def __do_bridge_over(self, diro): - """Arrange for DIRO to disappear from the dir tree structure - it is in.""" - - print "======== Bridging over " + diro.root - - # Remove this diro from the list of children of its parent, - # and update each of this diro's children to have its parent - # as a new parent instead of this diro itself. - - # Turn: - # P <----- PARENT - # | - # DIRO <----- TO VANISH - # | - # +---+---+---+ - # | | | | - # c1 c2 c3 c4 <---- CHILDREN - # - # into: - # - # P <----- PARENT - # | - # +---+---+---+ - # | | | | - # c1 c2 c3 c4 <---- CHILDREN - - diro.pdo.subdos.remove(diro) - - for subdo in diro.subdos: - diro.pdo.subdos.append(subdo) - subdo.pdo = diro.pdo - - subdo.tname = '.'.join ([diro.tname, subdo.tname]) - subdo.sname = '.'.join ([diro.sname, subdo.sname]) - - def __decide_cross_over (self, diro, pathi, wi): - """Add DIRO to WI.tobridge if DIRO ought to be removed from the - tree.""" - - if diro.set and os.path.getsize (diro.dfile(path=True)) == 0: - wi.tobridge.append (diro) - - def do_cross_overs(self): - """Remove (bridge links over) intermediate nodes that should not - produce intermediate layers in the final document.""" - - # Collect the set of nodes to remove first, then remove each one in - # turn. Removing while we're walking the tree is, mm, hazardous. - - class WalkInfo: - def __init__(self): - self.tobridge = [] - - wi = WalkInfo () - self.walk ( - mode=topdown, process=self.__decide_cross_over, data=wi) - - [self.__do_bridge_over (diro) for diro in wi.tobridge] - - # --------------------------------------------- - # -- Computing tree/node attributes, before -- - # -- more sophisticated walks can take place -- - # --------------------------------------------- - - def compute_attributes(self): - self.walk (mode=botmup, process=Dir.botmup_compute_attributes) - -# ************************ -# ** Document Generator ** -# ************************ - -icLink, icNid, icBrief = range (3) - -class DocGenerator(object): - - def __init__(self, art_rootdir, rst_rootdir, options): - - # Command line options - self.o = options - - # Root of the directory tree where the qualification artifacts - # are to be found: - self.art_rootdir = os.path.abspath(art_rootdir) - - # Root of the directory tree where the generated document sources - # are to be produced: - self.rst_rootdir = os.path.abspath(rst_rootdir) - mkdir (self.rst_rootdir) - - self.resource_list = set([]) - - # current output file descriptor, while walking the tor/tc tree - self.ofd = None - - def register_resources(self, rset): - self.resource_list |= rset - - def docpath_to(self, filename): - return os.path.join(self.rst_rootdir, filename) - - def file2docfile(self, filename): - """Return the associated filename for a given path""" - docfile = os.path.relpath(filename, self.art_rootdir) - # If we are at the root directory then return our documentation - # entry point. - if docfile == ".": - return "index.rst" - - docfile = docfile.replace('/', '_').replace('\\', '_') + ".rst" - return docfile - - def ref(self, name): - """Transform string NAME into another string suitable to be used as - index name""" - result = os.path.relpath(name, self.art_rootdir) - return result.replace('/', '_').replace('\\', '_').replace('.', '_') - - # --------------------------------------------- - # -- Generating doc contents for a directory -- - # --------------------------------------------- - - def contents_from(self, diro, name): - - """Fetch descriptive text in file NAME for artifact in DIRO, and - proceed with supported macro-replacements. Append a TC index to TC - set descriptions that don't have one.""" - - # Fetch the descriptive text - - contents = get_content(os.path.join(diro.root, name)) - - # Compute the dictionary of substitutions to apply - - SUBST = { - "toplevel-index": self.toplev_index, - "tc-index": self.tc_index, - "app-index": self.app_index, - "subset-index": self.subset_index, - "global-reqindex": self.global_reqindex, - "req-headline": self.req_headline, - "tstrategy-headline": self.tstrat_headline, - "toc": self.toc - } - - dosubst = dict( - [(key, SUBST[key](diro)) - for key in SUBST if ("(%s)s" % key) in contents] - ) - - # Compute the extra text to add at the end, depending on - # the kind of artifact and on what substitutions apply - - extratext = ( - self.tc_index(diro) if ( - diro.tcgroup and "tc-index" not in dosubst - and "subset-index" not in dosubst) - else "" - ) - - return contents % dosubst + extratext - - def gen_tc_section(self, diro): - """Generate the TestCase Sources section, and register the - sources as resources""" - - tco = TestCase (dir=diro.root, dgen=self) - - self.ofd.write(rest.subsection ("Test Sources")) - - self.ofd.write(subsec_header("Functional Code")) - self.ofd.write(rest.list( - [':ref:`%s`' % self.ref(d) for d in sorted(tco.fnsources)])) - - self.ofd.write(subsec_header("Program Tests")) - self.ofd.write(rest.list( - [':ref:`%s`' % self.ref(d) for d in tco.drsources])) - - if tco.conspecs: - self.ofd.write(subsec_header("Consolidation Tests")) - self.ofd.write(rest.list( - [':ref:`%s`' % self.ref(d) for d in tco.conspecs])) - - self.register_resources ( - tco.fnsources | tco.drsources | tco.conspecs) - - def gen_toc_section(self, diro): - """Generate the Table Of Contents section as needed""" - - tocentries = [ - self.file2docfile(os.path.join(diro.root, sdo.root)) - for sdo in diro.subdos] - - self.ofd.write('\n\n' + rest.toctree( - itemlist=tocentries, depth=1, attrlist=[":hidden:"])) - - # -------------------------------------- - # -- Tailored directory tree instance -- - # -------------------------------------- - - def art_dirtree_for(self, chapdirs): - - dirtree = DirTree_FromPath(rootp=self.art_rootdir) - - dirtree.rprune ( - [os.path.join (self.art_rootdir, dir) for dir in chapdirs]) - - dirtree.check_consistency() - dirtree.sort () - - return dirtree - - # --------------------------- - # -- generate doc chapters -- - # --------------------------- - - ALT_TITLES = { - "Qualif": "GNATcoverage TORs" - } - - def __gen_doc_contents (self, diro, pathi, wi): - """Generate the RST file for the DIRO artifact/directory-object, as - part of a dirtree walk carrying a general DirTree.WalkInfo object WI - and path info PATHI""" - - self.ofd = open( - self.docpath_to (self.file2docfile(diro.root)), 'w') - - ttext = ( - self.ALT_TITLES[diro.tname] if diro.tname in self.ALT_TITLES - else diro.tname) - - txthdl = diro.kind.txthdl - self.ofd.write(rest.section( - ttext + (" -- %s" % txthdl if txthdl else "") - )) - - if diro.dfile(): - self.ofd.write(self.contents_from (diro=diro, name=diro.dfile())) - - if diro.tc: - self.gen_tc_section(diro) - - self.gen_toc_section(diro) - - self.ofd.close() - - - def generate_chapters(self): - - self.art_dirtree.walk (mode=topdown, process=self.__gen_doc_contents) - - # --------------------------- - # -- generate index tables -- - # --------------------------- - - # Most index tables obey a common construction process, where some table - # header is produced and a set of lines is added, corresponding to - # subdirectories of where the table is produced. The general construction - # process is driven by the "index_table" method, which performs a walk of - # of the local subdirtree controled by callbacks to decide which dir/lines - # are added and using what style. - - class WalkInfo: - """Class of an object carried over the whole tree walk, to help - control the overall table construction process.""" - - def __init__ (self, rootp, emphctl): - - # root path from which the tree walk starts - self.rootp = rootp - - # line emphasis control callback - self.emphctl = emphctl - - # max depth reached during the tree walk - self.topdepth = sys.maxint - - # text outcome of the tree walk, the table body - self.text = None - - # Node (Line) Set reached by the walk. Attributes of this will - # help compute the table headers, in particular column titles - # tailored from the set of nodes/lines that the table includes: - self.lset = NodeSet() - - def __addline_for (self, diro, pathi, wi): - """Reached directory object DIRO during the tree walk, with specific - path info PATHI and overall walk info state in WI. Update the relevant - walk info attributes (e.g. topdepth), then compute and add the table - text line for this entry.""" - - if pathi.depth < wi.topdepth: - wi.topdepth = pathi.depth - - # Fetch the contents aimed at the Summary column, first paragraph in - # the description file. - - dtext = diro.dtext().strip() - toblank = re.search (".*?(\n[ \t]*\n)", dtext, re.DOTALL) - sumtext = (toblank.group(0) if toblank else dtext).replace ('\n', ' ') - - # Compute the link and the entry text, then apply the emphasis - # control if we have any: - - linktext = ':doc:`%s <%s>`' % ( - diro.kind.image, self.ref(diro.root)) - - entrytext = "%s%s" % ( - ". . " * (pathi.depth - wi.topdepth), diro.tname) - - if wi.emphctl: - sumtext = wi.emphctl(sumtext.strip(), diro, pathi) - entrytext = wi.emphctl(entrytext.strip(), diro, pathi) - - # Then append the whole entry and update the node set - # covered by the walk: - - wi.text.append ( - ' %s#%s#%s' % (linktext, entrytext, sumtext)) - - wi.lset.register_one (diro=diro) - - def index_table(self, rooto, nodectl, emphctl, tblhdr): - """Common helper to index table constructors.""" - - local_dirtree = DirTree (roots=[rooto]) - - wi = self.WalkInfo ( - rootp=rooto.root, emphctl=emphctl) - - # Start by computing the list of lines of the table body - - wi.text = [] - - local_dirtree.walk ( - mode=topdown, process=self.__addline_for, - ctl=nodectl, data=wi) - - # sync the line attributes and pick defaults for each column header - - wi.lset.sync() - - if icLink not in tblhdr: - tblhdr[icLink] = "" - - if icNid not in tblhdr: - tblhdr[icNid] = ( - "Testcase" if wi.lset.all_tc - else "Testcase Group" if wi.lset.all_tcgroup - else "Testcase or Group" if wi.lset.all_tcorgroup - else "Requirement" if wi.lset.all_req - else "Requirement Group" if wi.lset.all_reqgroup - else "Requirement or Group" if wi.lset.all_reqorgroup - else "Item") - - if icBrief not in tblhdr: - tblhdr[icBrief] = "Description" - - # Compute the table header - - wi.text = [ - "", - '.. tabularcolumns:: |l|l|p{0.70\linewidth}|', - '.. csv-table::', - ' :delim: #', - ' :widths: 2, 20, 70' - ] + [ - ' :header: %s' % ','.join ( - [tblhdr[cid] for cid in [icLink, icNid, icBrief]] - ) - ] + ['', ''] + wi.text - - linkcolheader = tblhdr[icLink] - if linkcolheader: - wi.text.extend ( - ["", - "**%s** " % linkcolheader - + - "For each section described by a line, this column features " - "an hyperlink to the section contents. The hyperlink text is " - "indicative of the section kind:", - ""] + ["* *%s*\tdesignates some %s" % (k.image, k.txthdl) - for k in dcl.kinds] - ) - - - wi.text = '\n'.join (wi.text) - return wi - - def tc_index(self, diro): - """Produce an index table referencing all the testcases reachable - downtree from directory DIRO, including lines for all the intermediate - artifacts that need to be traversed to reach the testcases - (requirements, groups, whatever). No line is included for the DIRO - directory itself. Lines for groups at depth 1 are bold. Lines for - deeper groups are italic.""" - - return self.index_table ( - rooto = diro, - tblhdr = {}, - emphctl = lambda text, diro, pathi: - (rest.strong(text) if diro.container and pathi.depth == 1 - else rest.emphasis(text) if diro.container - else text), - nodectl = lambda diro, pathi, wi: - (dirProcess if pathi.depth > 0 - else dirSkip) - ).text - - def subset_index(self, diro): - """Produce an index table referencing all the requirements or groups - reachable first from DIRO and only these. No line is included for DIRO - itself or for any element deeper than those first reached.""" - - return self.index_table ( - rooto = diro, - tblhdr = {}, - emphctl = None, - nodectl = lambda diro, pathi, wi: - (dirCutPost if pathi.depth > 0 and (diro.set or diro.req) - else dirSkip) - ).text - - def app_index(self, diro): - """Produce an index table referencing all the appendix artifacts - reachable from DIRO and only these.""" - - return self.index_table ( - rooto = diro, - tblhdr = {}, - emphctl = None, - nodectl = lambda diro, pathi, wi: - (dirProcess if pathi.depth > 0 and diro.appmat - else dirSkip) - ).text - - def toplev_index(self, diro): - return self.index_table ( - rooto = diro, - tblhdr = {icLink: "(*)", icNid: "Chapter"}, - emphctl = lambda text, diro, pathi: - (rest.strong(text) if pathi.depth == 1 - else text), - nodectl = lambda diro, pathi, wi: - (dirProcess if pathi.depth == 1 and diro.container - else dirCutPost if ( - pathi.depth > 1 and (diro.container or diro.appmat)) - else dirSkip) - ).text - - # --------------------------- - # -- generate general index -- - # --------------------------- - - def local_reqindex(self, diro): - return self.index_table ( - rooto = diro, - tblhdr = {}, - emphctl = lambda text, diro, pathi: - (rest.strong(text) if pathi.depth == 1 - else rest.emphasis(text) if pathi.depth > 1 - else text), - nodectl = lambda diro, pathi, wi: - (dirSkip if pathi.depth == 0 - else dirCutPost if diro.req - else dirProcess) - ) - - def __gen_index_contents (self, diro, pathi, wi): - - lwi = self.local_reqindex (diro) - - lwi.text = ''.join ( - [self.headline (diro.tname + " Requirements"), lwi.text] - ) if lwi.lset.some_req else "" - - wi.text = ''.join ([wi.text, lwi.text]) - - def global_reqindex(self, diro): - - class WalkInfo: - def __init__(self): - self.text="" - - wi = WalkInfo() - - self.art_dirtree.walk ( - mode=topdown, process=self.__gen_index_contents, - data=wi, ctl = lambda diro, pathi, wi: - (dirSkip if pathi.depth == 0 else dirCutPost) - ) - - return wi.text - - # --------------------------------- - # -- req and tstrategy headlines -- - # --------------------------------- - - def headline (self, text): - return rest.subsection (text) - - def req_headline (self, diro, plural=False): - return self.headline ("Requirement" + ("s" if plural else "")) - - def tstrat_headline (self, diro): - return self.headline ("Testing Strategy") - - # ----------------- - # -- toc entries -- - # ----------------- - - def toc(self, diro): - - tocentries = [ - self.file2docfile(os.path.join(diro.root, sd)) - for sd in diro.subdirs] - - return ''.join ( - [sec_header("Links"), - rest.toctree(tocentries, depth = 1 if not diro.pdo else 2)] - ) if tocentries else "" - - # ---------------------------- - # -- generate resource file -- - # ---------------------------- - - def generate_resources(self): - fd = open(self.docpath_to ('resources.rst'), 'w') - fd.write(rest.chapter('Resources')) - fd.write(rest.toctree( - [self.file2docfile(d) for d in self.resource_list])) - fd.close() - - for r in self.resource_list: - fd = open(self.docpath_to(self.file2docfile(r)), 'w') - fd.write('\n.. _%s:\n\n' % self.ref(r)) - fd.write(rest.section(os.path.basename(r))) - fd.write(rest.code_block(get_content(r), 'ada')) - fd.close() - - # --------------------------------------------- - # -- generate all the document items, -- - # -- checking tree consistency along the way -- - # --------------------------------------------- - - def generate_all(self): - - # Compute the set of subdirs/chapters our document ought to include. - # This is the explicit list when one was provided, and a set of common - # subdirs + those of relevance for the requested criterion otherwise. - - crit_subdirs_for = { - 'doC': ["stmt"], - 'doB': ["stmt", "decision"], - 'doA': ["stmt", "decision", "mcdc"] - } - - this_subdirs = ( - self.o.chapdirs.split(',') if self.o.chapdirs - else ( - ["OpEnviron", "Appendix", "Common"] - + [os.path.join ("Ada", csd) - for csd in crit_subdirs_for[self.o.dolevel]] - ) - ) - - self.art_dirtree = self.art_dirtree_for (this_subdirs) - - self.generate_chapters() - self.generate_resources() - -# The main of the script - -valid_dolevels = ('doA', 'doB', 'doC') - -if __name__ == "__main__": - - op = optparse.OptionParser(usage="%prog ") - - op.add_option ( - "--dolevel", dest="dolevel", default=None, - type='choice', choices=valid_dolevels, - help = ( - "Target DO178 qualification level." - )) - - op.add_option ( - "--chapdirs", dest="chapdirs", default=None, - help = ( - "Comma separated list of chapter directories to consider" - )) - - (options, args) = op.parse_args() - - exit_if ( - not options.chapdirs and not options.dolevel, - "A DO level or a set of chapter dirs must be specified" - ) - - exit_if ( - options.chapdirs and options.dolevel, - "A DO level may not be specified together with an explicit " - "set of chapter dirs." - ) - - mygen = DocGenerator( - art_rootdir=ART_ROOTDIR, rst_rootdir=RST_ROOTDIR, options=options) - - mygen.generate_all() diff --git a/qualification/tor/scripts/rest.py b/qualification/tor/scripts/rest.py deleted file mode 100644 index 9228b1622..000000000 --- a/qualification/tor/scripts/rest.py +++ /dev/null @@ -1,99 +0,0 @@ -"""Implement some utility function that ease generation of ReST code""" - -HEADING_CHARS = ['#', '*', '=', '-', '^', '"'] - - -def heading(title, heading_char): - if isinstance(heading_char, int): - heading_char = HEADING_CHARS[heading_char] - - result = "\n\n" - result += heading_char * len(title) + '\n' - result += title + '\n' - result += heading_char * len(title) + '\n\n' - return result - - -def part(title): - return heading(title, '#') - - -def chapter(title): - return heading(title, '*') - - -def section(title): - return heading(title, '=') - - -def subsection(title): - return heading(title, '-') - - -def subsubseciton(title): - return heading(title, '^') - - -def paragraph(title): - return heading(title, '"') - - -def toctree(itemlist, depth=2, attrlist=()): - return '\n'.join ( - [".. toctree::", - " :maxdepth: %s" % depth] - + - [" %s" % attr for attr in attrlist] - + ['\n'] + - [" %s" % item for item in itemlist] - ) + '\n' - - -def emphasis(content): - return "*" + content + "*" - - -def strong(content): - return "**" + content + "**" - - -def generic_block(command, content, command_arg=None): - if content == '': - return '' - - if command_arg is None: - command_arg = '' - - result = "\n.. %s:: %s\n\n" % (command, command_arg) - result += '\n'.join([' ' + line for line in content.splitlines()]) - result += '\n\n' - return result - - -def warning(content): - return generic_block('warning', content) - - -def parsed_literal(content): - return generic_block('parsed-literal', content) - - -def code_block(content, language): - return generic_block('code-block', content, language) - - -def raw(content, doc_type): - return generic_block('raw', content, doc_type) - - -def line_block(content): - result = '\n\n' - result += '\n'.join([' ' + line for line in content.splitlines()]) - return result - -def list(content): - result = '\n\n' - result += '\n'.join([' * %s' % l for l in content]) - result += '\n\n' - return result - diff --git a/qualification/tor/scripts/theme/static/gnatpython.css_t b/qualification/tor/scripts/theme/static/gnatpython.css_t deleted file mode 100644 index 10e295ff1..000000000 --- a/qualification/tor/scripts/theme/static/gnatpython.css_t +++ /dev/null @@ -1,239 +0,0 @@ -/* - * nature.css_t - * ~~~~~~~~~~~~ - * - * Sphinx stylesheet -- nature theme. - * - * :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -@import url("basic.css"); - -/* -- page layout ----------------------------------------------------------- */ - -body { - font-family: Arial, sans-serif; - font-size: 100%; - background-color: #111; - color: #555; - margin: 0; - padding: 0; -} - -div.documentwrapper { - float: left; - width: 100%; -} - -div.bodywrapper { - margin: 0 0 0 230px; -} - -hr { - border: 1px solid #B1B4B6; -} - -div.document { - background-color: #eee; -} - -div.body { - background-color: #ffffff; - color: #3E4349; - padding: 0 30px 30px 30px; - font-size: 0.9em; -} - -div.footer { - color: #555; - width: 100%; - padding: 13px 0; - text-align: center; - font-size: 75%; -} - -div.footer a { - color: #444; - text-decoration: underline; -} - -div.related { - background-color: #4A7697; - line-height: 32px; - color: #fff; - font-size: 0.9em; -} - -div.related a { - color: #E2F3CC; -} - -div.sphinxsidebar { - font-size: 0.75em; - line-height: 1.5em; -} - -div.sphinxsidebarwrapper{ - padding: 20px 0; -} - -div.sphinxsidebar h3, -div.sphinxsidebar h4 { - font-family: Arial, sans-serif; - color: #222; - font-size: 1.2em; - font-weight: normal; - margin: 0; - padding: 5px 10px; - background-color: #ccc; - text-shadow: 1px 1px 0 white -} - -div.sphinxsidebar h4{ - font-size: 1.1em; -} - -div.sphinxsidebar h3 a { - color: #444; -} - - -div.sphinxsidebar p { - color: #888888; - padding: 5px 20px; -} - -div.sphinxsidebar p.topless { -} - -div.sphinxsidebar ul { - margin: 10px 20px; - padding: 0; - color: #000; -} - -div.sphinxsidebar a { - color: #444; -} - -div.sphinxsidebar input { - border: 1px solid #ccc; - font-family: sans-serif; - font-size: 1em; -} - -div.sphinxsidebar input[type=text]{ - margin-left: 20px; -} - -/* -- body styles ----------------------------------------------------------- */ - -a { - color: #005B81; - text-decoration: none; -} - -a:hover { - color: #E32E00; - text-decoration: underline; -} - -div.body h1, -div.body h2, -div.body h3, -div.body h4, -div.body h5, -div.body h6 { - font-family: Arial, sans-serif; - background-color: #6A96B7; - font-weight: normal; - color: #212224; - margin: 30px 0px 10px 0px; - padding: 5px 0 5px 10px; -} - -div.body h1 { border-top: 20px solid white; margin-top: 0; font-size: 200%; } -div.body h2 { font-size: 150%; background-color: #C8D5E3; } -div.body h3 { font-size: 120%; background-color: #D8DEE3; } -div.body h4 { font-size: 110%; background-color: #D8DEE3; } -div.body h5 { font-size: 100%; background-color: #D8DEE3; } -div.body h6 { font-size: 100%; background-color: #D8DEE3; } - -a.headerlink { - color: #c60f0f; - font-size: 0.8em; - padding: 0 4px 0 4px; - text-decoration: none; -} - -a.headerlink:hover { - background-color: #c60f0f; - color: white; -} - -div.body p, div.body dd, div.body li { - line-height: 1.5em; -} - -div.admonition p.admonition-title + p { - display: inline; -} - -div.highlight{ - background-color: white; -} - -div.note { - background-color: #eee; - border: 1px solid #ccc; -} - -div.seealso { - background-color: #ffc; - border: 1px solid #ff6; -} - -div.topic { - background-color: #eee; -} - -div.warning { - background-color: #ffe4e4; - border: 1px solid #f66; -} - -p.admonition-title { - display: inline; -} - -p.admonition-title:after { - content: ":"; -} - -pre { - padding: 10px; - background-color: #E4FFCB; - color: #222; - border: 1px solid #C6C9CB; - font-size: 1.1em; -} - -tt { - background-color: #ecf0f3; - color: #222; - /* padding: 1px 2px; */ - font-size: 1.1em; - font-family: monospace; -} - -.viewcode-back { - font-family: Arial, sans-serif; -} - -div.viewcode-block:target { - background-color: #f4debf; - border-top: 1px solid #ac9; - border-bottom: 1px solid #ac9; -} diff --git a/qualification/tor/scripts/theme/theme.conf b/qualification/tor/scripts/theme/theme.conf deleted file mode 100644 index f35da3eae..000000000 --- a/qualification/tor/scripts/theme/theme.conf +++ /dev/null @@ -1,4 +0,0 @@ -[theme] -inherit = basic -stylesheet = gnatpython.css -pygments_style = sphinx diff --git a/testsuite/Qualif/Ada/decision/1_Core/req.rst b/testsuite/Qualif/Ada/decision/1_Core/req.rst index 0fcbc5d75..e2254d79d 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/req.rst +++ b/testsuite/Qualif/Ada/decision/1_Core/req.rst @@ -4,8 +4,6 @@ Core DC requirements Core expectations for Decision Coverage (DC) assessments. All the other DC-related sections rely on this one. -%REQ_ID% - For Decision Coverage assessments, the tool processes as decisions the following set of expressions: diff --git a/testsuite/Qualif/Ada/decision/Consolidation/req.rst b/testsuite/Qualif/Ada/decision/Consolidation/req.rst index 8d40923b5..698c6f1eb 100644 --- a/testsuite/Qualif/Ada/decision/Consolidation/req.rst +++ b/testsuite/Qualif/Ada/decision/Consolidation/req.rst @@ -1,8 +1,6 @@ DC requirements for the combination of multiple execution traces ================================================================ -%REQ_ID% - When the coverage achieved by multiple execution traces is evaluated, a decision coverage violation shall only be reported when it would have been reported for each trace individually. diff --git a/testsuite/Qualif/Ada/decision/Exemptions/req.rst b/testsuite/Qualif/Ada/decision/Exemptions/req.rst index 972d1751d..3f8522ad2 100644 --- a/testsuite/Qualif/Ada/decision/Exemptions/req.rst +++ b/testsuite/Qualif/Ada/decision/Exemptions/req.rst @@ -1,8 +1,6 @@ DC requirements for exemption regions ===================================== -%REQ_ID% - Exemption regions shall apply to decision coverage violations as they do to statement coverage violations. diff --git a/testsuite/Qualif/Ada/decision/MixedConstructs/req.rst b/testsuite/Qualif/Ada/decision/MixedConstructs/req.rst index bf260e864..2675394c7 100644 --- a/testsuite/Qualif/Ada/decision/MixedConstructs/req.rst +++ b/testsuite/Qualif/Ada/decision/MixedConstructs/req.rst @@ -5,8 +5,6 @@ DC requirements for combinations of statement and decision constructs representative of application code. -%REQ_ID% - Correct coverage is reported for programs that use a combination of Ada constructs, with arbitrary levels of syntactic nesting diff --git a/testsuite/Qualif/Ada/decision/Robustness/req.rst b/testsuite/Qualif/Ada/decision/Robustness/req.rst index 20fedebc9..02b321d1b 100644 --- a/testsuite/Qualif/Ada/decision/Robustness/req.rst +++ b/testsuite/Qualif/Ada/decision/Robustness/req.rst @@ -1,8 +1,6 @@ DC requirements for potentially confusing constructs ==================================================== -%REQ_ID% - Combined Statement and Decision Coverage assessments shall remain correct in the presence of code constructs that require sophisticated analysis by the coverage tool not to end up confused by the visible or internal complexity, diff --git a/testsuite/Qualif/Ada/mcdc/1_Core/req.rst b/testsuite/Qualif/Ada/mcdc/1_Core/req.rst index f6b301e8e..a1fc30ba9 100644 --- a/testsuite/Qualif/Ada/mcdc/1_Core/req.rst +++ b/testsuite/Qualif/Ada/mcdc/1_Core/req.rst @@ -1,8 +1,6 @@ Core MCDC requirements ====================== -%REQ_ID% - For MCDC assessments, the tool processes as decisions all the expressions processed as such for Decision Coverage (Boolean expressions used to influence control flow constructs), as well as all the Boolean expressions with more than diff --git a/testsuite/Qualif/Ada/mcdc/Consolidation/req.rst b/testsuite/Qualif/Ada/mcdc/Consolidation/req.rst index 015f8e5e2..b036bc633 100644 --- a/testsuite/Qualif/Ada/mcdc/Consolidation/req.rst +++ b/testsuite/Qualif/Ada/mcdc/Consolidation/req.rst @@ -1,8 +1,6 @@ MCDC requirements for the combination of multiple execution traces ================================================================== -%REQ_ID% - When the coverage achieved by multiple execution traces is evaluated, an mcdc violation shall only be reported when it would have been for all the traces individually. diff --git a/testsuite/Qualif/Ada/mcdc/Exemptions/req.rst b/testsuite/Qualif/Ada/mcdc/Exemptions/req.rst index 4d946b9f5..7169abce4 100644 --- a/testsuite/Qualif/Ada/mcdc/Exemptions/req.rst +++ b/testsuite/Qualif/Ada/mcdc/Exemptions/req.rst @@ -1,8 +1,6 @@ MCDC requirements for exemption regions ======================================= -%REQ_ID% - Exemption regions shall operate over MCDC violations as they do for statement coverage violations. diff --git a/testsuite/Qualif/Ada/mcdc/MixedConstructs/req.rst b/testsuite/Qualif/Ada/mcdc/MixedConstructs/req.rst index 27da5178f..c6c9179e3 100644 --- a/testsuite/Qualif/Ada/mcdc/MixedConstructs/req.rst +++ b/testsuite/Qualif/Ada/mcdc/MixedConstructs/req.rst @@ -1,8 +1,6 @@ MCDC requirements for mixed statement and decision constructs ============================================================= -%REQ_ID% - The Core requirements are honored on programs mixing arbitrary Ada constructs together, with arbitrary levels of syntactic nesting (such as loops within IFs within subprograms etc). diff --git a/testsuite/Qualif/Ada/mcdc/Robustness/req.rst b/testsuite/Qualif/Ada/mcdc/Robustness/req.rst index dc6c9958f..bef165965 100644 --- a/testsuite/Qualif/Ada/mcdc/Robustness/req.rst +++ b/testsuite/Qualif/Ada/mcdc/Robustness/req.rst @@ -1,8 +1,6 @@ MCDC requirements for potentially confusing constructs ====================================================== -%REQ_ID% - The Core MCDC requirements shall remain satisfied in presence of constructs that could fool simple minded analyzers, e.g. multiple decisions sharing a line. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/req.rst index 314902891..ac653e750 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/02_LexicalElements/Pragmas/req.rst @@ -2,8 +2,6 @@ SC requirements for Pragmas (ARM 2.8) ===================================== -%REQ_ID% - Different kinds of pragmas exist, some possibly generating code such diff --git a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/req.rst index 8aef7d67b..31647949c 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/03_DeclsAndTypes/req.rst @@ -1,8 +1,6 @@ SC requirements for ARM chap. 3 : Declarations and Types ======================================================== -%REQ_ID% - Declarations that were never elaborated as part of the program execution shall be reported as uncovered. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/req.rst index 6531fea1d..11fe795d7 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/051_SimpleStmts/req.rst @@ -2,8 +2,6 @@ SC requirements for ARM chap. 5 : Simple Statements =================================================== -%REQ_ID% - A simple statement (i.e., one that does not contain other statements) diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/req.rst index c1290a710..c6930ad6e 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/53_If/req.rst @@ -2,8 +2,6 @@ SC requirements for If statements (ARM 5.3) =========================================== -%REQ_ID% - An IF statement comprises an IF branch, zero or more ELSIF branches and zero diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/req.rst index 723e27132..4958440df 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/54_Case/req.rst @@ -2,8 +2,6 @@ SC requirements for Case statements (ARM 5.4) ============================================= -%REQ_ID% - A CASE statement starts with a *header* that introduces the controlling diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/req.rst index fcc07e017..a73e70118 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/550_Loop/req.rst @@ -2,8 +2,6 @@ SC requirements for Loop statements (ARM 5.5) ============================================= -%REQ_ID% - A LOOP statement contains a loop *header* (optional iteration scheme followed diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/req.rst index 7fb0efb3e..973cdbbf4 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/552_Iteration/req.rst @@ -2,8 +2,6 @@ SC requirements for generalized Loop iterations (ARM 5.5.2) =========================================================== -%REQ_ID% - Generalized loop iterators are similar to simple For loop statements in structure so share the same set of structural coverage requirements. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/req.rst index 97a80b19a..8cd2bb652 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/052_CompoundStmts/56_Block/req.rst @@ -2,8 +2,6 @@ SC requirements for Block statements (ARM 5.6) ============================================== -%REQ_ID% - A block statement contains a sequence of statements and, optionally, diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/req.rst index 498742051..0a9ad65a0 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/DeclsAndCalls/req.rst @@ -2,8 +2,6 @@ SC requirements for subprogram declarations and calls ===================================================== -%REQ_ID% - SC shall be assessed correctly within each kind of subprogram, diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/req.rst index 44ded4b57..ac2320988 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Derived/req.rst @@ -2,8 +2,6 @@ SC requirements for subprogram overridings ========================================== -%REQ_ID% - An overriding subprogram shall be recognized as distinct from the one it diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Inline/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Inline/req.rst index 10542e1b1..6421884ea 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Inline/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Inline/req.rst @@ -2,8 +2,6 @@ SC requirements for Inlining effects ==================================== -%REQ_ID% - SC assessments for simple statements shall not be influenced by subprogram diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/req.rst index aa0f52bb9..c029d577c 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/No_Return/req.rst @@ -2,8 +2,6 @@ SC requirements for No_Return pragmas on subprograms ==================================================== -%REQ_ID% - SC assessments shall not be influenced by the presence of a No_Return pragma attached to a subprogram. In particular, calls to such subprograms, statements within such subprograms or within subprograms called by them shall be diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/req.rst index caf6a4396..66b65dc2d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Null/req.rst @@ -1,8 +1,6 @@ SC requirements for Null subprograms ===================================== -%REQ_ID% - The null statement attached to a null procedure, as a completion or part of a definition, shall be treated as a regular statement, diagnosed uncovered if the procedure is not called. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/req.rst index 0270323fd..38a1c2493 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/ParameterModes/req.rst @@ -2,8 +2,6 @@ SC requirements for parameter modes =================================== -%REQ_ID% - The formal mode of subprogram parameters shall not influence the coverage assessment of statements referring to those parameters. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/req.rst index 1a479638f..efdb9efa0 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Return/req.rst @@ -2,8 +2,6 @@ SC requirements for Return statements ===================================== -%REQ_ID% - A RETURN statement is both a statement per se and a control flow diff --git a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/req.rst index 9e2bd8b66..9f59b5534 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/06_Subprograms/Xfunctions/req.rst @@ -1,8 +1,6 @@ SC requirements for Expression functions ======================================== -%REQ_ID% - An expression function definition (profile and expression), shall be recognized as a statement, diagnosed as not-executed when the function is never called. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/req.rst index 3c88eadbe..e3af286ca 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/07_Packages/req.rst @@ -1,8 +1,6 @@ SC requirements for ARM chap. 7 : Packages ========================================== -%REQ_ID% - The core SC requirements for statements and declarations shall be obeyed in all context variations allowed by package-related constructs. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/08_VisibilityRules/Renamings/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/08_VisibilityRules/Renamings/req.rst index 84246e0d6..7926a8bd2 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/08_VisibilityRules/Renamings/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/08_VisibilityRules/Renamings/req.rst @@ -2,8 +2,6 @@ SC requirements for Renaming declarations (ARM 8.5) =================================================== -%REQ_ID% - * Renaming declarations shall be recognized and processed as regular object diff --git a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/req.rst index 93b94708c..feb393f38 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/10_Structure/Subunits/req.rst @@ -2,8 +2,6 @@ SC requirements for Subunits (ARM 10.1.3) ========================================= -%REQ_ID% - SC assessments shall treat subunits as regular units. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst index 7ef5a4968..f96aa9865 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/11_Exceptions/req.rst @@ -4,8 +4,6 @@ SC requirements for ARM chap. 11 : Exceptions ============================================= -%REQ_ID% - Statement Coverage assessments shall handle the Ada exceptions related features described in Chapter 11 of the language Reference Manual. This requires accounting for exception handlers, implicit or explicit raise diff --git a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/req.rst index 34de34b59..15073dad9 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/12_GenericUnits/req.rst @@ -2,8 +2,6 @@ SC requirements for ARM chap. 12 : Generic Units ================================================ -%REQ_ID% - For a given `generic` source (package or subprogram), the tool aggregates the coverage achieved by different instantiations of the entities offered by this source. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/req.rst index 45e5d850d..1c1baa7d2 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/MachineCode/req.rst @@ -1,8 +1,6 @@ Machine_Code insertions ======================= -%REQ_ID% - Machine code insertions shall be processed as simple statements. .. rubric:: Testing Strategy diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/req.rst index 7da1032ea..b5b26e14d 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/OpAttributes/req.rst @@ -1,8 +1,6 @@ Attribute Definition Clauses for Operational Attributes ======================================================= -%REQ_ID% - Subprogram calls issued through operational attributes shall be treated as regular subprogram calls, regarding both the call statement itself and the called subprogram code. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/req.rst b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/req.rst index f96bbadb4..690ecd062 100644 --- a/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/req.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/13_Representation/RepAttributes/req.rst @@ -5,8 +5,6 @@ Attribute definition clauses for representation attributes are of interest in that some of them allow the evaluation of expressions with possible side effects. -%REQ_ID% - Attribute definition clauses for representation attributes aren't statements in the language definition sense and shall not be considered as such by the tool. diff --git a/testsuite/Qualif/Ada/stmt/1_Core/req_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/req_set.rst index 53a8eed5c..f83693e5d 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/req_set.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/req_set.rst @@ -14,15 +14,15 @@ Manual (Ada LRM), commonly designated as the Ada Reference Manual, or *ARM*: Several chapters aren't included for reasons listed in the following table: - + .. tabularcolumns:: |p{0.3\textwidth}|p{0.65\textwidth}| .. csv-table:: - :header: "Chapter", "Not included because ..." + :header: "Chapter"| "Not included because ..." :widths: 28, 65 - :delim: | + :delim: | - ARM chap. 1 : General | No language construct described + ARM chap. 1 : General | No language construct described ARM chap. 4 : Names and Expressions | "The described constructs are not considered on their own for coverage analysis purposes. The coverage information is computed for enclosing statement or declaration constructs." diff --git a/testsuite/Qualif/Ada/stmt/Consolidation/req.rst b/testsuite/Qualif/Ada/stmt/Consolidation/req.rst index c39d58d9d..b3e2a39f8 100644 --- a/testsuite/Qualif/Ada/stmt/Consolidation/req.rst +++ b/testsuite/Qualif/Ada/stmt/Consolidation/req.rst @@ -1,8 +1,6 @@ SC requirements for the combination of multiple execution traces ================================================================ -%REQ_ID% - When the coverage achieved by multiple execution traces is evaluated, a statement coverage violation shall only be reported when it would have been reported for all the traces individually. diff --git a/testsuite/Qualif/Ada/stmt/ControlFlow/req.rst b/testsuite/Qualif/Ada/stmt/ControlFlow/req.rst index 7dfe664e0..44621e6d0 100644 --- a/testsuite/Qualif/Ada/stmt/ControlFlow/req.rst +++ b/testsuite/Qualif/Ada/stmt/ControlFlow/req.rst @@ -1,8 +1,6 @@ SC requirements for statement sequences and control-flow transfers ================================================================== -%REQ_ID% - Statement coverage shall be assessed correctly for straightline sequences (basic blocks) of statements, and combinations of such using jump-like control flow transfers (goto, return, raise, exit). diff --git a/testsuite/Qualif/Ada/stmt/Exemptions/req.rst b/testsuite/Qualif/Ada/stmt/Exemptions/req.rst index b6153c063..dd00e70d5 100644 --- a/testsuite/Qualif/Ada/stmt/Exemptions/req.rst +++ b/testsuite/Qualif/Ada/stmt/Exemptions/req.rst @@ -1,8 +1,6 @@ SC requirements for exemption regions ===================================== -%REQ_ID% - For proper behavior of the Coverage Exemptions facility, the following set of rules shall be obeyed: diff --git a/testsuite/Qualif/Ada/stmt/MixedConstructs/req.rst b/testsuite/Qualif/Ada/stmt/MixedConstructs/req.rst index aebf2ef76..4ccf4678e 100644 --- a/testsuite/Qualif/Ada/stmt/MixedConstructs/req.rst +++ b/testsuite/Qualif/Ada/stmt/MixedConstructs/req.rst @@ -1,8 +1,6 @@ SC requirements for mixed statement constructs ============================================== -%REQ_ID% - Correct coverage shall be reported for programs that use combinations of Ada constructs with arbitrary levels of syntactic nesting, for example on statements nested within LOOPs within IF constructs within subprograms. diff --git a/testsuite/Qualif/Ada/stmt/Robustness/req.rst b/testsuite/Qualif/Ada/stmt/Robustness/req.rst index d1f776a9d..63af6eab3 100644 --- a/testsuite/Qualif/Ada/stmt/Robustness/req.rst +++ b/testsuite/Qualif/Ada/stmt/Robustness/req.rst @@ -5,8 +5,6 @@ SC requirements regarding potentially confusing constructs, e.g. multiple statements sharing a line. -%REQ_ID% - Statement Coverage assessment is correct in the presence of code diff --git a/testsuite/Qualif/Appendix/Testsuite/Selftest/hreq.rst b/testsuite/Qualif/Appendix/Testsuite/Selftest/hreq.rst index 6898460b6..83fda58c2 100644 --- a/testsuite/Qualif/Appendix/Testsuite/Selftest/hreq.rst +++ b/testsuite/Qualif/Appendix/Testsuite/Selftest/hreq.rst @@ -24,3 +24,6 @@ The test harness shall comply to the following requirements: * Presence in the output report of violations not applicable to the test category shall be ignored +.. qmlink:: TCIndexImporter + + * diff --git a/testsuite/Qualif/C/stmt/Core/05_Expressions/req.rst b/testsuite/Qualif/C/stmt/Core/05_Expressions/req.rst index a8c56ced9..fb761b24b 100644 --- a/testsuite/Qualif/C/stmt/Core/05_Expressions/req.rst +++ b/testsuite/Qualif/C/stmt/Core/05_Expressions/req.rst @@ -4,8 +4,6 @@ SC requirements for chapter 6, section 5: Expressions SC requirements regarding chapter 6, section 5: Expressions -%REQ_ID% - All C expressions can be used as a statement. diff --git a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/req.rst b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/req.rst index 656225b46..a0dd90ef8 100644 --- a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/req.rst +++ b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/req.rst @@ -1,8 +1,6 @@ Requirements for Target and Runtime attributes ==================================================== -%REQ_ID% - For cross configurations, unless an explicit :option:`--target` or :option:`--RTS` option is provided on the command line, the tool shall assume their respective values from a :option:`Target` or a diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/req.rst b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/req.rst index 06afe0b77..d8c4d1831 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/req.rst +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/req.rst @@ -1,8 +1,6 @@ Requirements for gnatcov command switches in project files ================================================================ -%REQ_ID% - The tool shall handle *Switches* attributes in the Coverage package of the root project file, indexed by gnatcov command name and where the value is a list of switch strings that could be passed to the gnatcov diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/req.rst b/testsuite/Qualif/Common/GprFacilities/MainAttr/req.rst index 530a6b606..86f2e64a9 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/req.rst +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/req.rst @@ -1,8 +1,6 @@ Requirements for Main attributes in project files ======================================================= -%REQ_ID% - The gnatcov run command shall handle a Main attribute in the root project file. diff --git a/testsuite/Qualif/Common/GprFacilities/Subdirs/req.rst b/testsuite/Qualif/Common/GprFacilities/Subdirs/req.rst index 86aae778d..d145efd77 100644 --- a/testsuite/Qualif/Common/GprFacilities/Subdirs/req.rst +++ b/testsuite/Qualif/Common/GprFacilities/Subdirs/req.rst @@ -1,8 +1,6 @@ Requirements for the :option:`--subdirs` switch ===================================================== -%REQ_ID% - The tool shall handle the :option:`--subdirs` command line switch, following similar semantics as for gprbuild: with :option:`--subdir=`, everything which should normally be performed within a project's diff --git a/testsuite/Qualif/Common/GprFacilities/req_set.rst b/testsuite/Qualif/Common/GprFacilities/req_set.rst index 0f8d7bb5a..8bf6ade2e 100644 --- a/testsuite/Qualif/Common/GprFacilities/req_set.rst +++ b/testsuite/Qualif/Common/GprFacilities/req_set.rst @@ -21,5 +21,5 @@ This incurs a set of related requirements summarized in the following table: GnatcovSwitches MainAttr ConfigAttr - SubdirsSwitch + Subdirs diff --git a/testsuite/Qualif/Common/Report/req.rst b/testsuite/Qualif/Common/Report/req.rst index 1843edf34..8706fd4e5 100644 --- a/testsuite/Qualif/Common/Report/req.rst +++ b/testsuite/Qualif/Common/Report/req.rst @@ -1,8 +1,6 @@ Output report format ==================== -%REQ_ID% - The tool qualified output is the synthetic report produced by the :literal:`--annotate=report` command line option. The output report shall: diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/req.rst b/testsuite/Qualif/Common/UnitsOfInterest/GPR/req.rst index 5927de5ff..3ba0cc91f 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/req.rst +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/req.rst @@ -1,8 +1,6 @@ Use of GPR project files to state Units Of Interest =================================================== -%REQ_ID% - The tool shall support the use of project file facilities to let users designate Units Of Interest for an analysis, as a replacement of the mechanism where users would instead provide an explicit list diff --git a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/req.rst b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/req.rst index 4f50ad640..c20e2a240 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/req.rst +++ b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/req.rst @@ -1,8 +1,6 @@ Use of SCO files to state Units Of Interest =========================================== -%REQ_ID% - As an alternative to the use of project file facilities to designate Units Of Interest for an analysis, the tool shall let users specify those units by listing their corresponding .ali files with a set of diff --git a/testsuite/Qualif/Environment/content.rst b/testsuite/Qualif/Environment/content.rst new file mode 100644 index 000000000..3c68a0e04 --- /dev/null +++ b/testsuite/Qualif/Environment/content.rst @@ -0,0 +1,139 @@ +.. _operational-conditions: + +|opcond_section_title| +====================== + +This chapter describes rules on which the correctness of the source coverage +assessments performed by GNATcoverage depends. This instance of the document +is valid for use in a certification context no stricter than DAL |dolevel|. + +.. _operational-context: + +Operational Environment +----------------------- + +The Operational Environment in which the tool is used shall match the +Verification Environment in which the tool was qualified, as characterized by +the items presented in the following table. The *Expected value* column here +states the intended value for qualification, which should match what +eventually gets logged within the |str_doc| report. The *Item #* column +provides item identifiers that are produced in this report to facilitate the +matching process. + +.. tabularcolumns:: |p{0.06\textwidth}|p{0.30\textwidth}|p{0.60\textwidth}| + +.. csv-table:: + :header: "Item #"| "Description"| "Expected value" + :widths: 5, 30, 60 + :delim: | + + e1 | Host Operating System name and version | Linux Redhat 7 + e2 | GNATcoverage executable name and version | GNATcoverage 19.3 (20200318) + e3 | GNAT Pro compiler executable name and version | gcc (GCC) 7.3.1 20180924 (for GNAT Pro 19lts 20200331) [i686-pc-linux-gnu] + s1 | GNAT Pro compilation switches | -gnat12 + s2 | GNAT Pro Runtime Library Profile | No --RTS switch expected. Programs shall honor the :ref:`language-scope` restrictions, nevertheless. + s3 | GNATcov dump trigger switch value | :literal:`--dump-triger=atexit` + s4 | GNATcov dump channel switch value | :literal:`--dump-channel=bin-file` + + +For the GNAT Pro compilation switches, additional options which do not +influence code generation are allowed. This may, for example, include options +controlling warnings, confirming compiler defaults, or designating a +configuration pragma file which contains only pragmas not influencing code +generation (``Restriction_Warnings`` pragmas or specific ``Restrictions`` such +as ``No_Direct_Boolean_Operators`` for instance). + +The Runtime Library Profile indication conveys the --RTS switch for which the +Verification Environment should be setup, designating a runtime library +delivered with the GNAT Pro toolchain. Tool Users shall have their toolchain +setup to compile programs with a :literal:`--RTS` switch as well, designating +a runtime with a ``system.ads`` identical to the qualification one. + +The indications for the GNATcov dump trigger and GNATcov dump channel switch +values represent the retained values for the corresponding switches, required +as part of the :literal:`gnatcov instrument` command, in accordance to the +restrictions imposed by the GNATPro runtime library profile and execution host +capabilities defined above, as described in the tool's User Manual. + +Installation, Documentation and Qualified Interface +--------------------------------------------------- + +All AdaCore tool packages use a common installation procedure, that depends on +the host platform. + +* On Windows hosts, the tool packages are provided as + self-installing executables. The Tool User should run the executable + corresponding to the tool he wants to install, then follow the instructions + on screen. + +* On non-Windows hosts, the tool packages are provided as .tar.gz + archives. The Tool User should unpack the archive corresponding to the tool + he wants to install, then run the script doinstall located at the root of + the archive directory structure, and follow the instructions on screen. + +General use of the tool is described in the Tool User's Guide document, which +can be found in the subdirectory :literal:`share/doc` of the tool +installation. For qualified use more specifically, the Tool User shall also +conform to the rules described in the *Qualified Interface* section of the +qualification |plans_doc| document. + + +.. _language-scope: + +Language Version and Scope +-------------------------- + +The general contents of this document is not tailored for a particular +version of the Ada language. The requirements and testcases sections +might contain items matching up to Ada 2012 even if the intended +qualified use is for an Ada 95 or Ada 2005 project. + +Nevertheless, to make sure there is no ambiguity on the intended use of the +tool for a given project: + +* The version language for which qualification is sought shall be stated by + way of a :literal:`-gnat95` :literal:`-gnat05` or :literal:`-gnat12` + compilation option in the :ref:`operational-context` section. + +In addition: + +* The tool is not qualified to analyze programs featuring tasking constructs, + controlled type definitions or pointers to nested subprograms. + + One possible way to ensure that the code subject to analysis conforms to + what this qualification material encompasses is to verify that it compiles + without error under control of a Zero Footprint Runtime Library Profile, or + free of warnings out of the following set of configuration pragmas:: + + pragma Restriction_Warnings (No_Tasking); + pragma Restriction_Warnings (No_Finalization); + pragma Restriction_Warnings (No_Implicit_Dynamic_Code); + +* For mcdc assessments, the tool requires the use of short-circuit variants + for the Boolean binary operators composing decisions: ``&&`` or ``||`` in C, + ``and then`` or ``or else`` in Ada. + + One possible way to ensure this for Ada is to verify that the code subject + to analysis compiles without error under control of the following + configuration pragma:: + + pragma Restrictions (No_Direct_Boolean_Operator); + +* For decision or mcdc analysis, the tool is not qualified to assess coverage + of expressions used in assertion constructs such as Assert pragmas or their + contract programming model extensions in Ada 2012 (Pre/Post pragmas or + aspects, their 'Class variants, static/dynamic subtype predicates or type + invariants). + + This material is designed with the assumption that such constructs, if + present in the source programs at all, are disabled, for instance thanks to + an Assertion_Policy pragma. + +* For statement, decision or mcdc analysis on Ada 2012, the tool is not + qualified to assess coverage of the new forms of expression introduced in + the language, in particular *conditional expressions*, *generalized + membership tests* with more than one alternative, and *quantified + expressions*. + + Such expressions are only allowed in assertion/contracts contexts, disabled + for coverage analysis purposes as previously described in this section. diff --git a/testsuite/Qualif/Environment/env_table_bin.rst b/testsuite/Qualif/Environment/env_table_bin.rst index acf3069dd..54016ea62 100644 --- a/testsuite/Qualif/Environment/env_table_bin.rst +++ b/testsuite/Qualif/Environment/env_table_bin.rst @@ -1,5 +1,5 @@ .. csv-table:: - :header: "Item #", "Description", "Expected value" + :header: "Item #"| "Description"| "Expected value" :widths: 5, 30, 60 :delim: | diff --git a/testsuite/Qualif/Environment/env_table_src.rst b/testsuite/Qualif/Environment/env_table_src.rst index c946ceb96..319435685 100644 --- a/testsuite/Qualif/Environment/env_table_src.rst +++ b/testsuite/Qualif/Environment/env_table_src.rst @@ -1,5 +1,5 @@ .. csv-table:: - :header: "Item #", "Description", "Expected value" + :header: "Item #"| "Description"| "Expected value" :widths: 5, 30, 60 :delim: | diff --git a/testsuite/Qualif/Index/content.rst b/testsuite/Qualif/Index/content.rst index 312f9506c..fb37991c3 100644 --- a/testsuite/Qualif/Index/content.rst +++ b/testsuite/Qualif/Index/content.rst @@ -19,6 +19,3 @@ directions: .. qmlink:: IndexImporter - - :allclass:TORReq - diff --git a/testsuite/Qualif/Introduction/content.rst b/testsuite/Qualif/Introduction/content.rst index 4ec1863e9..60d15b442 100644 --- a/testsuite/Qualif/Introduction/content.rst +++ b/testsuite/Qualif/Introduction/content.rst @@ -111,7 +111,7 @@ The following abbreviations are used throughout this document: .. csv-table:: :delim: | :widths: 30, 40 - :header: "Abbreviation", "Meaning" + :header: "Abbreviation"| "Meaning" ARM|Ada Reference Manual LRM|(Ada) Language Reference Manual diff --git a/testsuite/Qualif/content.rst b/testsuite/Qualif/content.rst index 1be316087..7bcea1ead 100644 --- a/testsuite/Qualif/content.rst +++ b/testsuite/Qualif/content.rst @@ -8,7 +8,7 @@ GNATcoverage - |standard| Qualification Material: |tor_doc_title| .. csv-table:: :delim: ; :widths: 10, 90 - :header: "Designation", "Referenced document" + :header: "Designation"; "Referenced document" |plans_doc| ; |project_name_it| - |plans_doc_title| (|plans_doc_id|) Ada 2012 LRM ; Ada 2012 Reference Manual. Language and Standard Libraries, ISO/IEC 8652:2012(E) @@ -57,4 +57,3 @@ GNATcoverage - |standard| Qualification Material: |tor_doc_title| Index Appendix - diff --git a/testsuite/Qualif/qmconf.py b/testsuite/Qualif/qmconf.py deleted file mode 100644 index a589a6f54..000000000 --- a/testsuite/Qualif/qmconf.py +++ /dev/null @@ -1,28 +0,0 @@ -import os.path - -latex_show_pagerefs = True - -common_file = os.path.join( - os.path.dirname( - os.path.dirname( - os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - ) - ), - "common_conf.py", -) - -if os.path.isfile(common_file): - execfile(common_file) - execfile(os.path.join(os.path.dirname(common_file), "qm_prolog.py")) -else: - print("Couldn't find common configuration file") - print(common_file) - print("from: %s" % __file__) - -rst_prolog += writer.define_role("raw-html(raw)", {"format": "html"}) - -doc_id = tor_doc_id - -html_sidebars = {"**": ["localtoc.html", "sourcelink.html", "searchbox.html"]} - -# flake8: noqa diff --git a/testsuite/STR/conf.py b/testsuite/STR/conf.py index 46e161ef9..39a30e302 100644 --- a/testsuite/STR/conf.py +++ b/testsuite/STR/conf.py @@ -3,7 +3,8 @@ # GNATcoverage documentation build configuration file, created by # sphinx-quickstart on Fri Apr 22 12:56:32 2011. # -# This file is execfile()d with the current directory set to its containing dir. +# This file is execfile()d with the current directory set to its +# containing dir. # # Note that not all possible configuration values are present in this # autogenerated file. @@ -14,6 +15,9 @@ import sys, os, glob doc_standard_name = "Tool Operational Verification and Validation Results" +project_name = "GNAT Coverage" +str_doc_id = "TOVVR" +version = "DRAFT" rst_prolog = ".. |str_doc| replace:: *%s*" % doc_standard_name @@ -39,13 +43,13 @@ # documentation root, use os.path.abspath to make it absolute, like shown here. # sys.path.insert(0, os.path.abspath('.')) -# -- General configuration ----------------------------------------------------- +# -- General configuration --------------------------------------------------- # If your documentation needs a minimal Sphinx version, state it here. # needs_sphinx = '1.0' -# Add any Sphinx extension module names here, as strings. They can be extensions -# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones. extensions = [] # Add any paths that contain templates here, relative to this directory. @@ -95,7 +99,7 @@ # modindex_common_prefix = [] -# -- Options for HTML output --------------------------------------------------- +# -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. @@ -175,7 +179,7 @@ htmlhelp_basename = "GNATcoveragedoc" -# -- Options for LaTeX output -------------------------------------------------- +# -- Options for LaTeX output ------------------------------------------------ # The paper size ('letter' or 'a4'). # latex_paper_size = 'letter' @@ -184,7 +188,8 @@ # latex_font_size = '10pt' # Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass [howto/manual]). +# (source start file, target name, title, author, +# documentclass [howto/manual]). latex_documents = [ ( "content", diff --git a/testsuite/STR/genrest.py b/testsuite/STR/genrest.py index 7b41dfae6..c0fef9bdc 100644 --- a/testsuite/STR/genrest.py +++ b/testsuite/STR/genrest.py @@ -21,9 +21,7 @@ # --testsuite-dir, though the two should be consistent wrt the python script # sources (e.g. the CTXdata structure must match) -LOCAL_TESTSUITE_DIR = os.path.dirname( - os.path.dirname(os.path.abspath(__file__)) -) +LOCAL_TESTSUITE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.append(LOCAL_TESTSUITE_DIR) TEST_LOG = "test.py.log" From 16aac65dd4695b48558a99730ae066f8d341c1c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 18 Apr 2025 12:11:57 +0200 Subject: [PATCH 1433/1483] Qualif: standardize temporary directory naming convention --- .../Qualif/Common/GprFacilities/ConfigAttr/Target/test.py | 4 ++-- .../Common/GprFacilities/GnatcovSwitches/Commands/test.py | 2 +- .../GprFacilities/GnatcovSwitches/InSubproject/test.py | 2 +- .../Common/GprFacilities/MainAttr/MultiMain/test.py | 2 +- .../Common/GprFacilities/MainAttr/SingleMain/test.py | 2 +- .../Qualif/Common/GprFacilities/MainAttr/ZeroMain/test.py | 2 +- .../Common/GprFacilities/Subdirs/BuildRunAnalyze/test.py | 2 +- .../Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py | 2 +- .../Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py | 6 +++--- .../Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py | 6 +++--- .../Common/UnitsOfInterest/GPR/ByAttr/ListInOut/test.py | 6 +++--- .../Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py | 6 +++--- .../Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py | 2 +- .../Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py | 2 +- .../Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py | 6 +++--- .../Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py | 6 +++--- .../Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py | 4 ++-- .../Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py | 6 +++--- .../Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py | 2 +- .../UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py | 2 +- .../GPR/ExtendedGprs/ExtendedHasMain/test.py | 2 +- .../GPR/ExtendedGprs/PartialOverride/test.py | 2 +- .../Common/UnitsOfInterest/GPR/GprsOfInterest/test.py | 2 +- .../Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py | 8 ++++---- .../UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py | 2 +- .../GPR/Robustness/BadUnitInSwitch/test.py | 2 +- .../UnitsOfInterest/GPR/Robustness/MissingLI/test.py | 2 +- .../UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py | 4 ++-- .../Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py | 6 +++--- .../UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py | 4 ++-- .../GPR/Robustness/UnitNotInProjects/test.py | 2 +- .../Qualif/Common/UnitsOfInterest/SCOS/MultiGpr/test.py | 2 +- .../Qualif/Common/UnitsOfInterest/SCOS/SingleGpr/test.py | 2 +- 33 files changed, 56 insertions(+), 56 deletions(-) diff --git a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py index 9b7eee47b..6b40c6be2 100644 --- a/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py +++ b/testsuite/Qualif/Common/GprFacilities/ConfigAttr/Target/test.py @@ -28,7 +28,7 @@ env = Env() target = env.target.triplet -Wdir("wd_") +Wdir("tmp_") # Get a template for the project file. gpr_filename = gprfor( @@ -58,7 +58,7 @@ def instantiate_gpr(target): for mode in ("no_arg", "with_arg"): - wd = Wdir("wd_{}".format(mode)) + wd = Wdir("tmp_{}".format(mode)) exe = exepath_to(mainbase) trace = tracename_for(mainbase) diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py index 13a3bd6fd..0ca37d0b5 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/Commands/test.py @@ -9,7 +9,7 @@ # Check correctness of transmission from Switches to commands for a few # particular commands. Check that Switches ("*") comes before Switches (cmd). -wd = Wdir("wd_") +wd = Wdir("tmp_") # We will be exercising combinations of run/coverage operations with option diff --git a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/test.py b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/test.py index a86ede146..2a28a1b94 100644 --- a/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/test.py +++ b/testsuite/Qualif/Common/GprFacilities/GnatcovSwitches/InSubproject/test.py @@ -9,7 +9,7 @@ pgm = "test_lt0" -wd = Wdir("wd_") +wd = Wdir("tmp_") # Build and run the single test program, which volontarily performs stmt and # decision coverage violations. diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/MultiMain/test.py b/testsuite/Qualif/Common/GprFacilities/MainAttr/MultiMain/test.py index 23d6b3631..7970a2a79 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/MultiMain/test.py +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/MultiMain/test.py @@ -5,7 +5,7 @@ from SUITE.tutils import exepath_to, gprbuild, gprfor, xcov, xrun -wd = Wdir("wd_") +wd = Wdir("tmp_") # GPR with multiple mains diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/SingleMain/test.py b/testsuite/Qualif/Common/GprFacilities/MainAttr/SingleMain/test.py index fd35410a5..ba1f22dd2 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/SingleMain/test.py +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/SingleMain/test.py @@ -5,7 +5,7 @@ from SUITE.tutils import exepath_to, gprbuild, gprfor, xcov, xrun -wd = Wdir("wd_") +wd = Wdir("tmp_") # We have two candidate main drivers. Craft a gpr # with a Main attribute listing only the first one. diff --git a/testsuite/Qualif/Common/GprFacilities/MainAttr/ZeroMain/test.py b/testsuite/Qualif/Common/GprFacilities/MainAttr/ZeroMain/test.py index 95646e1ba..c74718e87 100644 --- a/testsuite/Qualif/Common/GprFacilities/MainAttr/ZeroMain/test.py +++ b/testsuite/Qualif/Common/GprFacilities/MainAttr/ZeroMain/test.py @@ -5,7 +5,7 @@ from SUITE.tutils import exepath_to, gprbuild, gprfor, xcov, xrun -wd = Wdir("wd_") +wd = Wdir("tmp_") # GPR without a main. # diff --git a/testsuite/Qualif/Common/GprFacilities/Subdirs/BuildRunAnalyze/test.py b/testsuite/Qualif/Common/GprFacilities/Subdirs/BuildRunAnalyze/test.py index 5699b06ec..a331e1a0d 100644 --- a/testsuite/Qualif/Common/GprFacilities/Subdirs/BuildRunAnalyze/test.py +++ b/testsuite/Qualif/Common/GprFacilities/Subdirs/BuildRunAnalyze/test.py @@ -9,7 +9,7 @@ from SUITE.tutils import gprfor -wd = Wdir("wd_") +wd = Wdir("tmp_") gprname = "p" diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py index e2689ee36..47a045d41 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobInList/test.py @@ -5,7 +5,7 @@ wd = Wdir() -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( covcontrol=CovControl( ulist_in="../" + list_to_file(["ops*"]), diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py index c3ba7318e..ad2099faf 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/GlobUnits/test.py @@ -6,7 +6,7 @@ wd = Wdir() -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( covcontrol=CovControl( units_in=["ops*"], @@ -21,7 +21,7 @@ ) ) -wd.to_subdir("wd_2") +wd.to_subdir("tmp_2") TestCase(category=None).run( covcontrol=CovControl( units_out=["test*"], @@ -36,7 +36,7 @@ ) ) -wd.to_subdir("wd_3") +wd.to_subdir("tmp_3") TestCase(category=None).run( covcontrol=CovControl( units_in=["ops*"], diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py index 701c96741..44be424a9 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListIn/test.py @@ -7,7 +7,7 @@ # Check on lone node unit only -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( covcontrol=CovControl( @@ -16,7 +16,7 @@ ) # Check on lone node + child unit -wd.to_subdir("wd_2") +wd.to_subdir("tmp_2") TestCase(category=None).run( covcontrol=CovControl( ulist_in="../" + list_to_file(["ops", "ops.andthen"]), @@ -25,7 +25,7 @@ ) # Check on lone child unit only -wd.to_subdir("wd_3") +wd.to_subdir("tmp_3") TestCase(category=None).run( covcontrol=CovControl( ulist_in="../" + list_to_file(["ops.andthen"]), diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListInOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListInOut/test.py index c9166729e..dfcf8bc81 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListInOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListInOut/test.py @@ -7,7 +7,7 @@ wd = Wdir() # Remove a parent unit -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( covcontrol=CovControl( ulist_in=list_to_tmp(["ops", "ops.andthen"]), @@ -17,7 +17,7 @@ ) # Remove a child unit -wd.to_subdir("wd_2") +wd.to_subdir("tmp_2") TestCase(category=None).run( covcontrol=CovControl( ulist_in=list_to_tmp(["ops", "ops.andthen"]), @@ -27,7 +27,7 @@ ) # Remove one that's not in -wd.to_subdir("wd_3") +wd.to_subdir("tmp_3") TestCase(category=None).run( covcontrol=CovControl( ulist_in=list_to_tmp(["ops", "ops.andthen"]), diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py index 844f028c8..5b2e3d2d9 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/ListOut/test.py @@ -8,7 +8,7 @@ wd = Wdir() # Check on lone node unit only -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( covcontrol=CovControl( ulist_out="../" + list_to_file(base_out + ["ops"]), @@ -22,7 +22,7 @@ ) # Check on child units only -wd.to_subdir("wd_2") +wd.to_subdir("tmp_2") TestCase(category=None).run( covcontrol=CovControl( ulist_out="../" @@ -32,7 +32,7 @@ ) # Check on root + child unit -wd.to_subdir("wd_3") +wd.to_subdir("tmp_3") TestCase(category=None).run( covcontrol=CovControl( ulist_out="../" + list_to_file(base_out + ["ops", "ops.andthen"]), diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py index 8a2c61223..c24c71588 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixIn/test.py @@ -6,7 +6,7 @@ # Mixing units and lists to include wd = Wdir() -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( covcontrol=CovControl( units_in=["ops"], diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py index 0bf62d2d0..c4ba3b654 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixInOut/test.py @@ -6,7 +6,7 @@ # Mixing units and lists to include / exclude wd = Wdir() -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( covcontrol=CovControl( units_in=["ops", "ops.andthen"], diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py index dd4a53bf3..f8dade53e 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/MixOut/test.py @@ -10,7 +10,7 @@ wd = Wdir() # Check on lone node unit only -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( covcontrol=CovControl( units_out=base_out, @@ -25,7 +25,7 @@ ) # Check on child units only -wd.to_subdir("wd_2") +wd.to_subdir("tmp_2") TestCase(category=None).run( covcontrol=CovControl( units_out=base_out, @@ -35,7 +35,7 @@ ) # Check on root + child unit -wd.to_subdir("wd_3") +wd.to_subdir("tmp_3") TestCase(category=None).run( covcontrol=CovControl( units_out=base_out, diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py index dce70ded8..357a2791f 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsIn/test.py @@ -7,13 +7,13 @@ wd = Wdir() # Check on lone node unit only -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( covcontrol=CovControl(units_in=["ops"], xreports=["ops.ads", "ops.adb"]) ) # Check on lone node + child unit -wd.to_subdir("wd_2") +wd.to_subdir("tmp_2") TestCase(category=None).run( covcontrol=CovControl( units_in=["ops", "ops.andthen"], @@ -22,7 +22,7 @@ ) # Check on lone child unit only -wd.to_subdir("wd_3") +wd.to_subdir("tmp_3") TestCase(category=None).run( covcontrol=CovControl( units_in=["ops.andthen"], diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py index 12f04a399..9e3b726b4 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsInOut/test.py @@ -12,7 +12,7 @@ # Out empty (In only) out is another testcase # Out overlaps In -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( covcontrol=CovControl( units_in=["ops", "ops.andthen"], @@ -30,7 +30,7 @@ ) # Out does not overlap In -wd.to_subdir("wd_2") +wd.to_subdir("tmp_2") TestCase(category=None).run( covcontrol=CovControl( diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py index 0be723bad..9942bc17e 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByAttr/UnitsOut/test.py @@ -8,7 +8,7 @@ wd = Wdir() # Check on lone node unit only -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") TestCase(category=None).run( covcontrol=CovControl( units_out=base_out + ["ops"], @@ -22,7 +22,7 @@ ) # Check on child units only -wd.to_subdir("wd_2") +wd.to_subdir("tmp_2") TestCase(category=None).run( covcontrol=CovControl( units_out=base_out + ["ops.orelse", "ops.andthen"], @@ -31,7 +31,7 @@ ) # Check on root + child unit -wd.to_subdir("wd_3") +wd.to_subdir("tmp_3") TestCase(category=None).run( covcontrol=CovControl( units_out=base_out + ["ops", "ops.andthen"], diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py index 2502f3e69..02667dad6 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ByCmdLine/test_support.py @@ -83,7 +83,7 @@ def check(root_project, recurse, projects=None, units=None, xreports=None): # Arrange to execute each check in its own temporary directory and copying # shared projects in that directory prevent mixups across test variants. - tmpdir = f"wd_{label}" + tmpdir = f"tmp_{label}" wd = Wdir(tmpdir) # Copy shared projects in the temporary directory and create their object diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py index f218adcee..7fdcbe2c5 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/AttrOverride/test.py @@ -5,7 +5,7 @@ from SUITE.tutils import gprfor -wd = Wdir("wd_") +wd = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches( diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py index 99b9600e7..5a3d14755 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/test.py @@ -10,7 +10,7 @@ from SUITE.tutils import gprfor -wd = Wdir("wd_") +wd = Wdir("tmp_") # Prepare the two project files p = gprfor(prjid="p", mains=["main1.adb"], srcdirs=["../src"], objdir="obj-p") diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py index f9ef4886b..52fc4c43b 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/PartialOverride/test.py @@ -12,7 +12,7 @@ from SUITE.tutils import gprfor -tmp = Wdir("wd_") +tmp = Wdir("tmp_") # The "orig" project contains two units: "main" and "helper". The "ext" project # extends "orig" and overrides only the "helper" unit. diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py index 745ddf0a4..6c12ca7ce 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/GprsOfInterest/test.py @@ -17,7 +17,7 @@ root_project = os.path.abspath("root.gpr") board = gnatemu_board_name(env.target.machine) board_arg = "-XBOARD={}".format(board) -wd = Wdir("wd_") +wd = Wdir("tmp_") # Every project of interest is setup to feature a single unit named after the # project. Dumping the units of interest for a given analysis, with diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py index c1a3c0285..4d93e1281 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/InnerAttr/test.py @@ -30,7 +30,7 @@ def check(subdir, opspkg, xreports): "ops-orelse.ads", "ops-orelse.adb", ], - subdir="wd_1", + subdir="tmp_1", ) # ops.gpr: for Units use ... @@ -38,7 +38,7 @@ def check(subdir, opspkg, xreports): check( opspkg=gprcov_for(units_in=["ops.andthen"]), xreports=["ops-andthen.ads", "ops-andthen.adb"], - subdir="wd_2", + subdir="tmp_2", ) # ops.gpr: for Excluded_Units use ... @@ -46,7 +46,7 @@ def check(subdir, opspkg, xreports): check( opspkg=gprcov_for(units_out=["ops.andthen"]), xreports=["ops.ads", "ops.adb", "ops-orelse.ads", "ops-orelse.adb"], - subdir="wd_3", + subdir="tmp_3", ) # ops.gpr: for Units use ... for Excluded_Units use ... @@ -56,7 +56,7 @@ def check(subdir, opspkg, xreports): units_in=["ops", "ops.orelse", "ops.andthen"], units_out=["ops.orelse"] ), xreports=["ops.ads", "ops.adb", "ops-andthen.ads", "ops-andthen.adb"], - subdir="wd_3", + subdir="tmp_3", ) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py index 18deed2ea..0e68908fb 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInAttr/test.py @@ -9,7 +9,7 @@ from SUITE.tutils import gprfor -tmp = Wdir("wd_") +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches( diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py index ed8b714a5..a867d739b 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/BadUnitInSwitch/test.py @@ -9,7 +9,7 @@ from SUITE.tutils import gprfor -tmp = Wdir("wd_") +tmp = Wdir("tmp_") build_run_and_coverage( gprsw=GPRswitches( diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py index 176780fc8..ec9e513d5 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/MissingLI/test.py @@ -22,7 +22,7 @@ from SUITE.tutils import gprfor, xcov -tmp = Wdir("wd_") +tmp = Wdir("tmp_") xcov_args = build_and_run( gprsw=GPRswitches(root_project=gprfor("main.adb", srcdirs="..")), diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py index 05f288ed9..12ca54a28 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoContribPrj/test.py @@ -15,7 +15,7 @@ from SUITE.tutils import gprfor -tmp = Wdir("wd_") +tmp = Wdir("tmp_") class ProjectConfig(object): @@ -74,7 +74,7 @@ def run_test( expected_cov_list = expected_cov_list or [] thistest.log("== [{}] {} ==".format(slug, label)) - tmp.to_subdir("wd_/{}".format(slug)) + tmp.to_subdir("tmp_/{}".format(slug)) expected_output = "\n".join( "warning: project {} provides no unit of interest".format(project) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py index db3e96c4b..b0846b6ac 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/NoUnit/test.py @@ -38,7 +38,7 @@ def try_one_gpr(gpr, no_such): # Empty by specifying a single, non-existing unit in only -wd.to_subdir("wd_1") +wd.to_subdir("tmp_1") try_one_gpr( gpr=gprfor( srcdirs="../src", @@ -49,7 +49,7 @@ def try_one_gpr(gpr, no_such): ) # Empty by excluding the only candidate unit -wd.to_subdir("wd_2") +wd.to_subdir("tmp_2") try_one_gpr( gpr=gprfor( srcdirs="../src", @@ -60,7 +60,7 @@ def try_one_gpr(gpr, no_such): ) # Empty by including the empty set explicitly -wd.to_subdir("wd_3") +wd.to_subdir("tmp_3") try_one_gpr( gpr=gprfor( srcdirs="../src", mains="p.adb", extra=CovControl(units_in=[]).gpr() diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py index 19d529234..74f9a663b 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/SourcesAttr/test.py @@ -59,7 +59,7 @@ def try_one(subdir, extra_covargs, xreports, xwarnings): try_one( - subdir="wd_1", + subdir="tmp_1", extra_covargs=[], xreports={ "flip.adb.xcov": {"+": {3}}, @@ -70,7 +70,7 @@ def try_one(subdir, extra_covargs, xreports, xwarnings): ) try_one( - subdir="wd_2", + subdir="tmp_2", extra_covargs=["--units=flop"], xreports={}, xwarnings=["no unit flop (from --units) in the projects of interest"], diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py index bd18cb2f2..fd84c6be2 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/Robustness/UnitNotInProjects/test.py @@ -16,7 +16,7 @@ from SUITE.tutils import gprfor -tmp = Wdir("wd_") +tmp = Wdir("tmp_") mkdir("obj-helper") mkdir("obj-main") diff --git a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/MultiGpr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/MultiGpr/test.py index 10e80d8ea..56e1ca078 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/MultiGpr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/MultiGpr/test.py @@ -4,7 +4,7 @@ from test_support import check -wd = Wdir("wd_") +wd = Wdir("tmp_") gprbuild( gprfor( srcdirs=[ diff --git a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/SingleGpr/test.py b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/SingleGpr/test.py index 19029b9f3..ce4cd44c2 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/SCOS/SingleGpr/test.py +++ b/testsuite/Qualif/Common/UnitsOfInterest/SCOS/SingleGpr/test.py @@ -4,7 +4,7 @@ from test_support import check -wd = Wdir("wd_") +wd = Wdir("tmp_") gprbuild( gprfor( srcdirs=[ From 8cb038b461cb4708e08d30b0302077574f2eb1fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 23 Apr 2025 14:28:45 +0200 Subject: [PATCH 1434/1483] Qualif: reorganize CustomBool tests This simplifies qualification document generation --- .../DerivedBody => CustomBoolDerivedBody}/src/andthen.adb | 0 .../DerivedBody => CustomBoolDerivedBody}/src/andthen.ads | 0 .../{CustomBool/DerivedBody => CustomBoolDerivedBody}/tc.rst | 0 .../{CustomBool/DerivedBody => CustomBoolDerivedBody}/test.py | 0 .../DerivedInvis => CustomBoolDerivedInvis}/src/andthen.adb | 0 .../DerivedInvis => CustomBoolDerivedInvis}/src/andthen.ads | 0 .../DerivedInvis => CustomBoolDerivedInvis}/src/customdef.ads | 0 .../DerivedInvis => CustomBoolDerivedInvis}/src/usedef.adb | 0 .../DerivedInvis => CustomBoolDerivedInvis}/src/usedef.ads | 0 .../{CustomBool/DerivedInvis => CustomBoolDerivedInvis}/tc.rst | 0 .../{CustomBool/DerivedInvis => CustomBoolDerivedInvis}/test.py | 0 .../DerivedSpec => CustomBoolDerivedSpec}/src/andthen.adb | 0 .../DerivedSpec => CustomBoolDerivedSpec}/src/andthen.ads | 0 .../{CustomBool/DerivedSpec => CustomBoolDerivedSpec}/tc.rst | 0 .../{CustomBool/DerivedSpec => CustomBoolDerivedSpec}/test.py | 0 .../{CustomBool/Subtype => CustomBoolSubtype}/src/andthen.adb | 0 .../{CustomBool/Subtype => CustomBoolSubtype}/src/andthen.ads | 0 .../Operands/{CustomBool/Subtype => CustomBoolSubtype}/tc.rst | 0 .../Operands/{CustomBool/Subtype => CustomBoolSubtype}/test.py | 0 .../1_Core/Operands/{CustomBool => }/src/test_andthen_0.adb | 0 .../1_Core/Operands/{CustomBool => }/src/test_andthen_f.adb | 0 .../1_Core/Operands/{CustomBool => }/src/test_andthen_fu.adb | 0 .../1_Core/Operands/{CustomBool => }/src/test_andthen_fx.adb | 0 .../1_Core/Operands/{CustomBool => }/src/test_andthen_t.adb | 0 .../1_Core/Operands/{CustomBool => }/src/test_andthen_tf.adb | 0 25 files changed, 0 insertions(+), 0 deletions(-) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedBody => CustomBoolDerivedBody}/src/andthen.adb (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedBody => CustomBoolDerivedBody}/src/andthen.ads (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedBody => CustomBoolDerivedBody}/tc.rst (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedBody => CustomBoolDerivedBody}/test.py (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedInvis => CustomBoolDerivedInvis}/src/andthen.adb (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedInvis => CustomBoolDerivedInvis}/src/andthen.ads (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedInvis => CustomBoolDerivedInvis}/src/customdef.ads (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedInvis => CustomBoolDerivedInvis}/src/usedef.adb (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedInvis => CustomBoolDerivedInvis}/src/usedef.ads (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedInvis => CustomBoolDerivedInvis}/tc.rst (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedInvis => CustomBoolDerivedInvis}/test.py (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedSpec => CustomBoolDerivedSpec}/src/andthen.adb (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedSpec => CustomBoolDerivedSpec}/src/andthen.ads (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedSpec => CustomBoolDerivedSpec}/tc.rst (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/DerivedSpec => CustomBoolDerivedSpec}/test.py (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/Subtype => CustomBoolSubtype}/src/andthen.adb (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/Subtype => CustomBoolSubtype}/src/andthen.ads (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/Subtype => CustomBoolSubtype}/tc.rst (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool/Subtype => CustomBoolSubtype}/test.py (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool => }/src/test_andthen_0.adb (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool => }/src/test_andthen_f.adb (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool => }/src/test_andthen_fu.adb (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool => }/src/test_andthen_fx.adb (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool => }/src/test_andthen_t.adb (100%) rename testsuite/Qualif/Ada/decision/1_Core/Operands/{CustomBool => }/src/test_andthen_tf.adb (100%) diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/src/andthen.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/src/andthen.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/src/andthen.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/src/andthen.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/src/andthen.ads similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/src/andthen.ads rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/src/andthen.ads diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/tc.rst b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/tc.rst rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/tc.rst diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/test.py b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/test.py similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedBody/test.py rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedBody/test.py diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/andthen.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/andthen.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/andthen.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/andthen.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/andthen.ads similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/andthen.ads rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/andthen.ads diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/customdef.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/customdef.ads similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/customdef.ads rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/customdef.ads diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/usedef.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/usedef.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/usedef.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/usedef.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/usedef.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/usedef.ads similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/src/usedef.ads rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/src/usedef.ads diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/tc.rst b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/tc.rst rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/tc.rst diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/test.py b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/test.py similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedInvis/test.py rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedInvis/test.py diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/src/andthen.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/src/andthen.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/src/andthen.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/src/andthen.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/src/andthen.ads similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/src/andthen.ads rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/src/andthen.ads diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/tc.rst b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/tc.rst rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/tc.rst diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/test.py b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/test.py similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/DerivedSpec/test.py rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolDerivedSpec/test.py diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/src/andthen.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/src/andthen.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/src/andthen.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/src/andthen.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/src/andthen.ads b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/src/andthen.ads similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/src/andthen.ads rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/src/andthen.ads diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/tc.rst b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/tc.rst similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/tc.rst rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/tc.rst diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/test.py b/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/test.py similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/Subtype/test.py rename to testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBoolSubtype/test.py diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_0.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_0.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_0.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_0.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_f.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_f.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_f.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_fu.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_fu.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_fu.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_fu.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_fx.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_fx.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_fx.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_fx.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_t.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_t.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_t.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_t.adb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_tf.adb b/testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_tf.adb similarity index 100% rename from testsuite/Qualif/Ada/decision/1_Core/Operands/CustomBool/src/test_andthen_tf.adb rename to testsuite/Qualif/Ada/decision/1_Core/Operands/src/test_andthen_tf.adb From b7a253ab2dbd1b9e2029a955beb532114c28fdb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 24 Apr 2025 13:43:49 +0200 Subject: [PATCH 1435/1483] Add missing tc_set.rts for pure doB tests --- .../Qualif/Ada/decision/1_Core/Topologies/doB/tc_set.rst | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/tc_set.rst diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/tc_set.rst b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/tc_set.rst new file mode 100644 index 000000000..c33d664f5 --- /dev/null +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/doB/tc_set.rst @@ -0,0 +1,6 @@ +Check DC on various expressions form involving non-short-circuiting operators in various contexts +================================================================================================= + +.. qmlink:: TCIndexImporter + + * From c5159897f4242aa28f48f072d0dcab57daa34edd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 24 Apr 2025 14:48:07 +0200 Subject: [PATCH 1436/1483] Instrument.adb: fix instrumentation of Debug pragma It used to be disabled if the various assertion coverage levels were not active. --- qualification/scripts/qm_plugins/importers.py | 28 +++--- qualification/scripts/rest/__init__.py | 14 ++- qualification/scripts/rest/writer.py | 8 +- qualification/tor/genrest.py | 85 +++++-------------- .../Topologies/Flip/Pragmas/src/pval.adb | 18 ++++ .../Topologies/Flip/Pragmas/src/pval.ads | 3 + .../Flip/Pragmas/src/test_pval_0.adb | 14 ++- .../Flip/Pragmas/src/test_pval_f.adb | 19 +++-- .../Flip/Pragmas/src/test_pval_t.adb | 23 ++--- .../Flip/Pragmas/src/test_pval_tf.adb | 17 ++-- .../1_Core/Topologies/Flip/Pragmas/tc.rst | 1 + .../1_Core/Topologies/Flip/Pragmas/tc_set.rst | 8 -- .../1_Core/Topologies/Flip/Pragmas/test.opt | 0 .../1_Core/Topologies/Flip/Pragmas/test.py | 5 ++ tools/gnatcov/instrument-ada_unit.adb | 7 +- 15 files changed, 123 insertions(+), 127 deletions(-) create mode 100644 testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.adb create mode 100644 testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.ads create mode 100644 testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc.rst delete mode 100644 testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc_set.rst create mode 100644 testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/test.opt create mode 100644 testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/test.py diff --git a/qualification/scripts/qm_plugins/importers.py b/qualification/scripts/qm_plugins/importers.py index fa13157c5..30363f0d3 100644 --- a/qualification/scripts/qm_plugins/importers.py +++ b/qualification/scripts/qm_plugins/importers.py @@ -541,11 +541,12 @@ def qmlink_to_rest(self, parent, artifacts): links.append((a, default_importer(a))) output += writer.toctree( - # [lnk[0].docfile() - # for lnk in links - # if not is_tc_or_set(lnk[0]) or is_tc_or_set(parent)], - # [lnk[0].docfile() for lnk in links], - docrefs, + [ + lnk[0].docfile() + for lnk in links + if not is_tc_or_set(lnk[0]) or is_tc_or_set(parent) + ], + # docrefs, hidden=True, ) @@ -569,7 +570,7 @@ def to_rest(self, artifact): type and ID on the first line """ - result = ".. _%s:\n\n" % artifact.id.replace("/", "_")[1:] + result = ".. _%s:\n\n" % artifact.docfile(True) result += DefaultImporter().to_rest(artifact) + "\n\n" return result @@ -587,7 +588,10 @@ def to_rest(self, artifact): in order to keep them close in the final pdf generation """ - reference = ".. _%s:\n\n" % artifact.id.replace("/", "_")[1:] + reference = ".. _%s:\n\n" % artifact.docfile(True) + reference += writer.raw( + "\\label{%s::doc}" % artifact.docfile(True), "latex" + ) result = "" qmlink = "" in_qmlink = False @@ -793,7 +797,11 @@ def get_sources(self, artifact): def to_rest(self, artifact): - reference = "\n\n.. _%s:\n" % artifact.id.replace("/", "_")[1:] + reference = "\n\n.. _%s:\n" % artifact.docfile(True) + + reference += writer.raw( + "\\label{%s::doc}" % artifact.docfile(True), "latex" + ) result_pdf = "**TEST CASE**: %s\n\n" % artifact.id result_html = "%s\n%s\n" % (artifact.id, "=" * len(artifact.id)) @@ -1165,7 +1173,7 @@ def qmlink_to_rest(self, parent, artifacts): links=tc_or_set_links, ) - output = writer.only(html_output, "html") - output += writer.only(pdf_output, "latex") + output = writer.only(pdf_output, "latex") + output += writer.only(html_output, "html") return output, mixed_links diff --git a/qualification/scripts/rest/__init__.py b/qualification/scripts/rest/__init__.py index c2406a8b7..98bdf4128 100644 --- a/qualification/scripts/rest/__init__.py +++ b/qualification/scripts/rest/__init__.py @@ -205,9 +205,17 @@ def relative_to(self: Artifact) -> Optional[Artifact]: def hash(self: Artifact) -> str: # noqa: A003 """Return a hash based on the artifact full name""" - hashobj = hashlib.new("sha1") - hashobj.update(self.full_name.encode("utf-8")) - return hashobj.hexdigest() + use_full_slug = os.environ.get("GNATCOV_QUALKIT_FULL_SLUGS", None) + + if not use_full_slug or use_full_slug == "False": + hashobj = hashlib.new("sha1") + hashobj.update(self.full_name.encode("utf-8")) + return hashobj.hexdigest() + return ( + os.path.relpath(os.path.abspath(self.full_name), os.getcwd()) + .replace("/", "_") + .replace(".._", "") + ) class MetaArtifactImporter(type): diff --git a/qualification/scripts/rest/writer.py b/qualification/scripts/rest/writer.py index 432fe2b62..4d18dd168 100644 --- a/qualification/scripts/rest/writer.py +++ b/qualification/scripts/rest/writer.py @@ -57,7 +57,7 @@ def directive(name, content=None, argument=None, options=None): :type options: None or a dictionnary :rtype: a string """ - result = [".. %s::" % name] + result = ["\n\n.. %s::" % name] if argument is not None: result[0] += " %s" % argument @@ -185,6 +185,12 @@ def only(content, format_tag): return directive("only", content=content, argument=format_tag) +def include(format_tag): + """Return a ReST include directive""" + + return directive("include", argument=format_tag) + + # Roles # def role(name, argument): """Generic function to generate ReST roles diff --git a/qualification/tor/genrest.py b/qualification/tor/genrest.py index dab759a7d..f290d1788 100755 --- a/qualification/tor/genrest.py +++ b/qualification/tor/genrest.py @@ -13,7 +13,10 @@ import scripts.rest as rest import scripts.logger as logger from scripts.rest import Artifact, ArtifactImporter, writer -from scripts.qm_plugins.importers import resolve_importer +from scripts.qm_plugins.importers import ( + resolve_importer, + default_importer, +) from itertools import zip_longest from scripts.common_conf import tor_doc_id from tor.proj_conf import get_var_replacements @@ -854,12 +857,8 @@ def dtext(self: Dir) -> str: clean_line = line.strip() if not clean_line: # empty line after the first row. Promote the - # first row to be the title. - title = ( - title_candidate - + "\n" - + "*" * (len(title_candidate) + 1) - ) + # first row to be the "title". + title = title_candidate elif ( not re.search(r"[^=]", clean_line) or not re.search(r"[^\*]", clean_line) @@ -882,18 +881,14 @@ def dtext(self: Dir) -> str: title_prefix += line + "\n" else: # any other text is considered as title - title_candidate = line.strip().strip("*") + title_candidate = line.strip() if title: - content = ( - title - + "\n\n" - + self.full_id - + "\n\n" - + self.parent_ref - + "\n\n" - + body - ) + content = title + "\n\n" + self.parent_ref + "\n\n" + body + else: + content = content + "\n\n" + self.parent_ref + else: + content = content + "\n\n" + self.parent_ref return content @@ -956,11 +951,7 @@ def parent_ref(self: Dir) -> str: if self.pdo: return ( "**Parent" - + ( - (" " + self.pdo.kind.txthdl.lower()) - if self.pdo.req - else "" - ) + + ((" " + self.pdo.kind.txthdl) if self.pdo.req else "") + "** " + self.pdo.rest_doc_ref() ) @@ -1552,47 +1543,14 @@ def contents_from(self: DocGenerator, diro: Dir) -> str: """Fetch descriptive text form the file corresponding to diro. Append a TC index to TC set descriptions that don't have one.""" - # Fetch the descriptive text - - res = diro.dtext() - - # Compute the dictionary of substitutions to apply - - # SUBST = { - # "toplevel-index": self.toplev_index, - # "tc-index": self.tc_index, - # "app-index": self.app_index, - # "subset-index": self.subset_index, - # "global-reqindex": self.global_reqindex, - # "req-headline": self.req_headline, - # "tstrategy-headline": self.tstrat_headline, - # "toc": self.toc, - # } - - # dosubst = { - # (key, SUBST[key](diro)) - # for key in SUBST - # if (f"%({key})s") in contents - # } - # Compute the extra text to add at the end, depending on - # the kind of artifact and on what substitutions apply - - # extratext = ( - # self.tc_index(diro) - # if ( - # diro.tcgroup - # and "tc-index" not in dosubst - # and "subset-index" not in dosubst - # ) - # else "" - # ) - # if len(dosubst) != 0: - # try: - # res = contents % dosubst # + extratext - # except Exception as e: - # err("Failed to apply substitutes %s\n\n%s" % (e, contents)) + # Fetch the descriptive text either through a specialized importer, or + # through our own + + importer = default_importer(diro) + # if isinstance(importer, DefaultImporter): + # res = diro.to_rest() # else: - # res = contents + res = importer.to_rest(diro) res = replace_variables(res) res = self.process_qmlink(diro, res) @@ -1810,9 +1768,6 @@ def __gen_doc_contents(self: DocGenerator, diro: Dir, pathi, wi): self.ofd.write(self.contents_from(diro)) if diro.tc: - # importer = qm_plugins.importers.default_importer(diro) - # qmlink_rst = importer.to_rest(diro) - # self.ofd.write(qmlink_rst) self.gen_tc_section(diro) # close the document to measure the size diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.adb new file mode 100644 index 000000000..d6befcfba --- /dev/null +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.adb @@ -0,0 +1,18 @@ +pragma Debug_Policy (Check); + +with Support; use Support; + +package body Pval is + function F (X : Boolean) return Boolean is + Res : Boolean := False; -- # true + + procedure Set_Res_True is + begin + Res := True; -- # false + end Set_Res_True; + + begin + pragma Debug (Identity (not X), Set_Res_True); -- # eval + return Res; -- # ret + end F; +end Pval; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.ads b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.ads new file mode 100644 index 000000000..39b9ab7f1 --- /dev/null +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/pval.ads @@ -0,0 +1,3 @@ +package Pval is + function F (X : Boolean) return Boolean; +end Pval; diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_0.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_0.adb index 54995c862..c06c62e22 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_0.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_0.adb @@ -3,14 +3,10 @@ with Support, Pval; use Support, Pval; procedure Test_Pval_0 is begin Assert (True); -end; - ---# pval.ads --- /eval/ l- ## s- +end Test_Pval_0; --# pval.adb --- /__l!d!/ l- ## s- --- /eval/ l- ## s- --- /returnTrue/ l- ## s- --- /returnFalse/ l- ## s- --- /returnVal/ l- ## s- +-- /eval/ l- ## s- +-- /true/ l- ## s- +-- /false/ l- ## s- +-- /ret/ l- ## s- diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_f.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_f.adb index 0c73f2c12..d03986b11 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_f.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_f.adb @@ -3,13 +3,16 @@ with Support, Pval; use Support, Pval; procedure Test_Pval_F is begin Assert (F (False) = True); -end; - ---# pval.ads --- /eval/ l! ## o! +end Test_Pval_F; --# pval.adb --- /eval/ l! ## o! --- /returnTrue/ l+ ## 0 --- /returnFalse/ l- ## s- --- /returnVal/ l+ ## 0 +-- /eval/ l! ## dF- +-- /true/ l+ ## 0 +-- /false/ l+ ## 0 +-- /val/ l+ ## 0 + +-- Decision coverage with bin traces is imprecise on simple expressions + +-- %opts: --trace-mode=bin +-- +-- =/eval/ l! ## d! diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_t.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_t.adb index d69d07563..b3a95fafa 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_t.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_t.adb @@ -1,17 +1,18 @@ -with Support, Silent_Last_Chance, Pval; use Support, Pval; +with Support, Pval; use Support, Pval; procedure Test_Pval_T is begin Assert (F (True) = False); -exception - when others => null; -end; - ---# pval.ads --- /eval/ l! ## o! +end Test_Pval_T; --# pval.adb --- /eval/ l! ## o! --- /returnTrue/ l- ## s- --- /returnFalse/ l- ## s- --- /returnVal/ l- ## s- +-- /eval/ l! ## dT- +-- /true/ l+ ## 0 +-- /false/ l- ## s- +-- /val/ l+ ## 0 + +-- Decision coverage with bin traces is imprecise on simple expressions + +-- %opts: --trace-mode=bin +-- +-- =/eval/ l! ## d! diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_tf.adb b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_tf.adb index 4aae54331..ff28f6a50 100644 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_tf.adb +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/src/test_pval_tf.adb @@ -1,18 +1,13 @@ -with Support, Silent_Last_Chance, Pval; use Support, Pval; +with Support, Pval; use Support, Pval; procedure Test_Pval_TF is begin Assert (F (False) = True); Assert (F (True) = False); -exception - when others => null; -end; - ---# pval.ads --- /eval/ l+ ## 0 +end Test_Pval_TF; --# pval.adb --- /eval/ l+ ## 0 --- /returnTrue/ l+ ## 0 --- /returnFalse/ l+ ## 0 --- /returnVal/ l+ ## 0 +-- /eval/ l+ ## 0 +-- /set_true/ l+ ## 0 +-- /set_false/ l+ ## 0 +-- /ret_val/ l+ ## 0 diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc.rst b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc.rst new file mode 100644 index 000000000..09dbbe139 --- /dev/null +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc.rst @@ -0,0 +1 @@ +**DC on a negated single-value expression in a pragma** diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc_set.rst b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc_set.rst deleted file mode 100644 index c11cf3760..000000000 --- a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/tc_set.rst +++ /dev/null @@ -1,8 +0,0 @@ -Check DC on a negated single-value expression in various Pragma contexts -======================================================================== -| -.. qmlink:: TCIndexImporter - - * - - diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/test.opt b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/test.opt new file mode 100644 index 000000000..e69de29bb diff --git a/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/test.py b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/test.py new file mode 100644 index 000000000..aa9c1b42b --- /dev/null +++ b/testsuite/Qualif/Ada/decision/1_Core/Topologies/Flip/Pragmas/test.py @@ -0,0 +1,5 @@ +from SCOV.tc import TestCase +from SUITE.context import thistest + +TestCase().run() +thistest.result() diff --git a/tools/gnatcov/instrument-ada_unit.adb b/tools/gnatcov/instrument-ada_unit.adb index 54190886f..c8492a893 100644 --- a/tools/gnatcov/instrument-ada_unit.adb +++ b/tools/gnatcov/instrument-ada_unit.adb @@ -258,6 +258,7 @@ package body Instrument.Ada_Unit is -- Pragmas Convention, + Debug, Profile, Restrictions, @@ -302,6 +303,7 @@ package body Instrument.Ada_Unit is Type_Invariant => Precompute_Symbol (Type_Invariant), Convention => Precompute_Symbol (Convention), Profile => Precompute_Symbol (Profile), + Debug => Precompute_Symbol (Debug), Restrictions => Precompute_Symbol (Restrictions), No_Dependence => Precompute_Symbol (No_Dependence), No_Finalization => Precompute_Symbol (No_Finalization), @@ -6970,7 +6972,7 @@ package body Instrument.Ada_Unit is Nam : Name_Id := Namet.No_Name; -- For the case of an aspect, aspect name - Is_Contract : constant Boolean := T in 'a' | 'A' | 'P'; + Is_Contract : Boolean := T in 'a' | 'A' | 'P'; -- Is the decision that of a contract begin @@ -7015,6 +7017,9 @@ package body Instrument.Ada_Unit is PN := PN.Parent; end loop; Loc := Sloc (PN); + Is_Contract := + Pragma_Name (PN.As_Pragma_Node) + /= Precomputed_Symbols (Debug); end; when 'X' => From c60b85669579e5f7c04fb734dbf593d4f69ceed9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 20 May 2025 14:17:20 +0200 Subject: [PATCH 1437/1483] genbundle: Adapt to new plans & tor generation without the QMachine --- qualification/genbundle.py | 77 +++++++++++------------------------- qualification/tor/genrest.py | 43 ++++---------------- 2 files changed, 31 insertions(+), 89 deletions(-) diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 9e2b3a82d..760257174 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -368,6 +368,7 @@ def __init__(self, options): self.workdir = os.path.abspath(options.workdir) self.repodir = os.path.join(self.workdir, REPO_IMAGE_SUBDIR) + self.qualdir = os.path.join(self.repodir, "qualification") # A local place where the testsuite tree may be found, # possibly after remote syncing from testsuite_dir if that @@ -377,7 +378,7 @@ def __init__(self, options): # To be set prior to build_as_needed(): - self.this_docformat = None + self.this_docformat: str = "" # Sequence number of doc build pass we are processing: @@ -616,53 +617,13 @@ def __latch_into(self, dirname, part, toplevel, copy_from=None): ) ) - # ------------------ - # -- gen_qm_model -- - # ------------------ - - def gen_qm_model(self): - """Generate model.xml that __qm_build will use.""" - - announce("generating qm model") - - os.chdir(os.path.join(self.repodir, "qualification", "qm")) - - run( - sys.executable - + " genmodel.py --dolevel=%s --languages=%s" - % (self.o.dolevel, self.o.languages) - ) - - # ---------------- - # -- __qm_build -- - # ---------------- - - def __qm_build(self, part): - """Build one PART of using the Qualifying Machine.""" - - announce("building %s %s" % (self.this_docformat, part.upper())) - - os.chdir(os.path.join(self.repodir, "qualification", "qm")) - - # The qmachine model might use the "build" directory as - # a repository, and it has to preexist: - - mkdir("build") - run( - "qmachine model.xml -l scripts/generate_%s_%s.py" - % (part, self.this_docformat), - env={"GENBUNDLE_DOLEVEL": self.o.dolevel}, - ) - - self.__latch_into(dirname=self.itemsdir(), part=part, toplevel=False) - # --------------- # -- build_tor -- # --------------- def build_tor(self): # If we have a local testsuite dir at hand and we haven't done so - # already, fetch the testsresults that the QM needs to check TOR/TC + # already, fetch the tests results that the QM needs to check TOR/TC # consistency: if self.local_testsuite_dir and self.passno == 1: @@ -686,17 +647,21 @@ def sync(tr): announce("building %s %s" % (self.this_docformat, "TOR")) - os.chdir(os.path.join(self.repodir, "qualification", "tor", "scripts")) + os.chdir(os.path.join(self.repodir, "qualification", "tor")) run( - "python genrest.py --dolevel %s --force" % (self.o.dolevel) + "python genrest.py --dolevel %s --force" % (self.o.dolevel), + env={"PYTHONPATH": self.qualdir}, ) run( - "make %s" % (self.this_docformat), - env={"GENBUNDLE_DOLEVEL": self.o.dolevel}, + "make %s" % (sphinx_target_for[self.this_docformat]), + env={ + "GENBUNDLE_DOLEVEL": self.o.dolevel, + "PYTHONPATH": self.qualdir, + }, ) - self.__latch_into(dir=self.itemsdir(), part="tor", toplevel=False) + self.__latch_into(dirname=self.itemsdir(), part="tor", toplevel=False) # ------------------------------ # -- dump_kit_consistency_log -- @@ -949,14 +914,23 @@ def build_str(self): # ----------------- def build_plans(self): - plans_root = os.path.join(self.repodir, "qualification", "qm", "plans") + plans_root = os.path.join(self.repodir, "qualification", "plans") trace_specific_content = [ os.path.join( plans_root, "Tool_Qualification_Plan", "Qualified_Interface" ) ] self.prepare_content(trace_specific_content) - self.__qm_build(part="plans") + + os.chdir(plans_root) + run( + f"make {sphinx_target_for[self.this_docformat]}", + env={"PYTHONPATH": self.qualdir}, + ) + + self.__latch_into( + dirname=self.itemsdir(), part="plans", toplevel=False + ) # --------------- # -- build_kit -- @@ -1368,11 +1342,6 @@ def check_valid(options, args): if options.branchname: qmat.switch_to_branch() - # Produce each part we are requested to produce, with a tailored - # QM model: - - qmat.gen_qm_model() - # Build the various parts and maybe the kit for each requested format: [qmat.build_as_needed(docformat=f) for f in options.docformat.split(",")] diff --git a/qualification/tor/genrest.py b/qualification/tor/genrest.py index f290d1788..99f828428 100755 --- a/qualification/tor/genrest.py +++ b/qualification/tor/genrest.py @@ -791,10 +791,6 @@ def dfile(self: Dir, path: bool = False) -> str | None: ) ) - # if not base and self.sdset.some_tcorset: - # self.tcset = True - # base = "tc_set.rst" - return os.path.join(self.root, base) if base and path else base @property @@ -1083,7 +1079,7 @@ def rprune(self: DirTree, namelist: List[str]): """prune all subdirs of self that are do *not* lead to any dir in NAMELIST""" - class WalkInfo: + class WalkInfo(DirTree.WalkInfo): def __init__(self: WalkInfo, tokeep: List[str]): self.tokeep = tokeep self.toprune: List[Dir] = [] @@ -1266,19 +1262,6 @@ def check_downtree_consistency(self, diro, pathi): "missing testcases for leaf req in %s" % diro.root, ) - # Warn on missing testing strategy in leaf requirement with multiple - # testcases - - # CAN NOT BE DIAGNOSED IN RST DATA ANY MORE - - # warn_if( - # diro.req - # and len(diro.subdos) > 1 - # and diro.sdset.all_tcorset - # and "%(tstrategy-headline)s" not in diro.dtext(), - # "req at %s misses testing strategy description" % diro.root, - # ) - def topdown_check_consistency( self: DirTree, diro: Dir, pathi: PathInfo, data ): @@ -1290,6 +1273,7 @@ def check_consistency(self: DirTree): class DirTree_FromPath(DirTree): + def __init__(self: DirTree_FromPath, rootp: str): DirTree.__init__(self, roots=[]) @@ -1409,11 +1393,15 @@ def __do_bridge_over(self: DirTree_FromPath, diro: Dir): subdo.tname = ".".join([diro.tname, subdo.tname]) subdo.sname = ".".join([diro.sname, subdo.sname]) + class WalkInfo(DirTree.WalkInfo): + def __init__(self: DirTree_FromPath.WalkInfo): + self.tobridge = [] + def __decide_cross_over( self: DirTree_FromPath, diro: Dir, pathi: PathInfo, - wi: DirTree.WalkInfo, + wi: DirTree_FromPath.WalkInfo, ): """Add DIRO to WI.tobridge if DIRO ought to be removed from the tree.""" @@ -1432,11 +1420,7 @@ def do_cross_overs(self: DirTree_FromPath): # Collect the set of nodes to remove first, then remove each one in # turn. Removing while we're walking the tree is, mm, hazardous. - class WalkInfo: - def __init__(self: WalkInfo): - self.tobridge = [] - - wi = WalkInfo() + wi = DirTree_FromPath.WalkInfo() self.walk(mode=topdown, process=self.__decide_cross_over, data=wi) [self.__do_bridge_over(diro) for diro in wi.tobridge] @@ -1753,17 +1737,6 @@ def __gen_doc_contents(self: DocGenerator, diro: Dir, pathi, wi): os.makedirs(os.path.dirname(filename)) self.ofd = open(filename, "w") - # FIXME Double-check why this was here. It adds an extra title not - # conforming to that in the existing qualkits - # ttext = ( - # self.ALT_TITLES[diro.tname] - # if diro.tname in self.ALT_TITLES else diro.tname - # ) - - # txthdl = diro.kind.txthdl - # self.ofd.write( - # rest.section(ttext + (" -- %s" % txthdl if txthdl else ""))) - if diro.dfile(): self.ofd.write(self.contents_from(diro)) From 05e284b29202d5b6a57c7242bb73763745741d0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 20 May 2025 14:18:06 +0200 Subject: [PATCH 1438/1483] Add missing title in testcase description file --- .../UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/tc.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/tc.rst b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/tc.rst index a64538622..88d3b5c5d 100644 --- a/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/tc.rst +++ b/testsuite/Qualif/Common/UnitsOfInterest/GPR/ExtendedGprs/ExtendedHasMain/tc.rst @@ -1,2 +1 @@ -**Check that sources in extended projects are considered when looking for -mains** +**Check that sources in extended projects are considered when looking for mains** From ba9eaf033cdd41c2a96c6e6f21602530c7edd7ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 20 May 2025 14:18:51 +0200 Subject: [PATCH 1439/1483] Adapt STR generation to new script location and new expectation notes --- qualification/genbundle.py | 5 ++++- testsuite/STR/conf.py | 25 +++++-------------------- testsuite/STR/genrest.py | 13 +++++++++++-- 3 files changed, 20 insertions(+), 23 deletions(-) diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 760257174..6a310285b 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -905,7 +905,10 @@ def build_str(self): os.chdir(os.path.join(self.local_testsuite_dir, "STR")) - run("make %s" % sphinx_target_for[self.this_docformat]) + run( + "make %s" % sphinx_target_for[self.this_docformat], + env={"PYTHONPATH": self.qualdir}, + ) self.__latch_into(dirname=self.itemsdir(), part="str", toplevel=False) diff --git a/testsuite/STR/conf.py b/testsuite/STR/conf.py index 39a30e302..459526d26 100644 --- a/testsuite/STR/conf.py +++ b/testsuite/STR/conf.py @@ -12,31 +12,16 @@ # All configuration values have a default; values that are commented out # serve to show the default. -import sys, os, glob +from scripts.common_conf import ( + project_name, + str_doc_id, + version, +) doc_standard_name = "Tool Operational Verification and Validation Results" -project_name = "GNAT Coverage" -str_doc_id = "TOVVR" -version = "DRAFT" rst_prolog = ".. |str_doc| replace:: *%s*" % doc_standard_name -# Locate and import common_conf.py - -work_dir = os.path.join( - os.path.dirname( - os.path.dirname(os.path.dirname(os.path.abspath(__file__))) - ) -) -common_conf_glob = f"{work_dir}/*/qualification/qm/common_conf.py" -common_conf_candidates = glob.glob(common_conf_glob) - -assert ( - len(common_conf_candidates) == 1 -), f"{__file__} couldn't locate lone common_conf.py out of {common_conf_glob}" - -common_conf_py = common_conf_candidates[0] -exec(open(common_conf_py).read()) # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the diff --git a/testsuite/STR/genrest.py b/testsuite/STR/genrest.py index c0fef9bdc..373a0e1a4 100644 --- a/testsuite/STR/genrest.py +++ b/testsuite/STR/genrest.py @@ -21,7 +21,9 @@ # --testsuite-dir, though the two should be consistent wrt the python script # sources (e.g. the CTXdata structure must match) -LOCAL_TESTSUITE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +LOCAL_TESTSUITE_DIR = os.path.dirname( + os.path.dirname(os.path.abspath(__file__)) +) sys.path.append(LOCAL_TESTSUITE_DIR) TEST_LOG = "test.py.log" @@ -48,6 +50,8 @@ ePartCov, eNoCov, cPartCov, + XsNoCov, + Xr0c, xBlock1, ) from SUITE.cutils import FatalError, lines_of @@ -911,6 +915,7 @@ def tcdata_for(self, qd): for src in qde.xrnotes for notelist in qde.xrnotes[src].values() for note in notelist + if note.kind not in range(XsNoCov, Xr0c + 1) ] return this_tcdata @@ -1214,7 +1219,11 @@ def switches_with_eq_from(switches_string): of the form = in SWITCHES_STRING.""" return dict( - [sw.split("=") for sw in switches_string.split() if "=" in sw] + [ + sw.split("=", 1) + for sw in switches_string.split() + if "=" in sw + ] ) itemno = Column(htext="Item #", legend=None) From ee6863666345c23ba1c02e1112d3e0244cdec3de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 20 May 2025 14:20:37 +0200 Subject: [PATCH 1440/1483] Ignore C qualification material for now --- testsuite/Qualif/C/.tor_ignore | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 testsuite/Qualif/C/.tor_ignore diff --git a/testsuite/Qualif/C/.tor_ignore b/testsuite/Qualif/C/.tor_ignore new file mode 100644 index 000000000..e69de29bb From fcce27da037a005277851a20529d2eb23199d648 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 20 May 2025 15:12:15 +0200 Subject: [PATCH 1441/1483] Update gitignore --- .gitignore | 3 ++- qualification/tor/missing_tr_log.txt | 0 2 files changed, 2 insertions(+), 1 deletion(-) delete mode 100644 qualification/tor/missing_tr_log.txt diff --git a/.gitignore b/.gitignore index b15f24716..21538c405 100644 --- a/.gitignore +++ b/.gitignore @@ -35,11 +35,12 @@ TAGS *.log # temporary output of genrest.py -qualification/tor/scripts/source/ +qualification/tor/source/ # generated output of genbundle.py **/build **/source +**/missing_tr_log.txt # vscode local settings .env diff --git a/qualification/tor/missing_tr_log.txt b/qualification/tor/missing_tr_log.txt deleted file mode 100644 index e69de29bb..000000000 From 93b87350192ca349a09926406029439d2b0b9f3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 20 May 2025 15:13:29 +0200 Subject: [PATCH 1442/1483] Fixup consistency log generation --- qualification/genbundle.py | 2 +- qualification/scripts/missing_tr_log.txt | 0 qualification/scripts/qm_plugins/importers.py | 4 +--- 3 files changed, 2 insertions(+), 4 deletions(-) delete mode 100644 qualification/scripts/missing_tr_log.txt diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 6a310285b..2a183a667 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -769,7 +769,7 @@ def __dump_tr_consistency_info(self, log): log.write("\n-- TOR/TR CONSISTENCY LOG:\n") tor_tr_logfile = os.path.join( - self.repodir, "qualification", "qm", "missing_tr_log.txt" + self.repodir, "qualification", "tor", "missing_tr_log.txt" ) if not os.path.exists(tor_tr_logfile): diff --git a/qualification/scripts/missing_tr_log.txt b/qualification/scripts/missing_tr_log.txt deleted file mode 100644 index e69de29bb..000000000 diff --git a/qualification/scripts/qm_plugins/importers.py b/qualification/scripts/qm_plugins/importers.py index 30363f0d3..40784e225 100644 --- a/qualification/scripts/qm_plugins/importers.py +++ b/qualification/scripts/qm_plugins/importers.py @@ -6,9 +6,7 @@ from collections import OrderedDict import os -# FIXME -# MISSING_TR_LOG = os.path.join(get_project_dir(), "missing_tr_log.txt") -MISSING_TR_LOG = "missing_tr_log.txt" +MISSING_TR_LOG = os.path.join(os.getcwd(), "missing_tr_log.txt") def resolve_importer(qmlink_txt: str) -> ArtifactImporter | None: From 8be2b49e9764536fb42126e62aef65e6654de75f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 30 Jun 2025 14:22:47 +0200 Subject: [PATCH 1443/1483] Testsuite.py: Fix detection of Ada language version --- testsuite/testsuite.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index a4cbc0a5b..23fa5531e 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -1208,7 +1208,7 @@ def _get_canonical_ada_version(ada_ver: str) -> str: gnatcov_instr_ada_version = None qualifiable_ada_versions = ["95", "05", "12"] qav_str = "|".join(qualifiable_ada_versions) - ada_version_match = re.match( + ada_version_match = re.search( r"-gnat(95|(?:20)?(?:05|12)|2022)", cargs_ada + cargs ) From eddaaee201774cc657d5d54d8881a72d369e10f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 26 May 2025 14:12:58 +0200 Subject: [PATCH 1444/1483] Add CI job to build the qualification kit documents This job only triggers upon changes on the qualification material (PLANS. TORS or STR), and upon changes on the qualification testsuite (tests and infrastructure) --- .gitlab-ci.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 67e84bb02..9d05adfb8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -266,3 +266,38 @@ test_src_light: - testsuite_reports <<: *artifacts + +test_qualkit: + interruptible: true + services: + - image:pe-base + - cpu:16 + - mem:16 + stage: test + script: + - *basic_test_setup + + # Use the gnatcov-qualrun and gnatcov-qualkit specs to run the + # qualification testsuite and create a qualification kit + - anod test gnatcov-qualrun --minimal -Qci $ACI_TRACK_QUALIFIER + - anod build gnatcov-qualkit --minimal -Qci $ACI_TRACK_QUALIFIER + - QUALKIT_BSN=$(anod eval --primitive=build gnatcov-qualkit -Qci $ACI_TRACK_QUALIFIER build_space_name) + - mkdir $CI_PROJECT_DIR/qualkits + - cp $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$QUALKIT_BSN/install/*.zip $CI_PROJECT_DIR/qualkits/ + - testsuite_reports + rules: + - if: $CI_PIPELINE_SOURCE == 'merge_request_event' + changes: + paths: + - "qualification/**/*" + - "testsuite/Qualif/**/*" + - "testsuite/STR/**/*" + - "testsuite/SCOV/**/*" + compare_to: $CI_MERGE_REQUEST_TARGET_BRANCH_NAME + artifacts: + when: always + paths: + - xunit-*.xml + - qualkits/*.zip + reports: + junit: xunit-*.xml From 622999d57dee5fcd1bd4e49ed982425a9c5c9c6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 1 Sep 2025 09:46:21 +0200 Subject: [PATCH 1445/1483] Add small Readme to explain how to build the qualification documents --- qualification/qualification.md | 184 +++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 qualification/qualification.md diff --git a/qualification/qualification.md b/qualification/qualification.md new file mode 100644 index 000000000..5055e6fc4 --- /dev/null +++ b/qualification/qualification.md @@ -0,0 +1,184 @@ +# Producing a qualification kit for GNATcoverage + + +This documents describes how to produce the various documents that +comprise the DO-178C qualification kit for GNATcoverage, and provide +some details as to how each document is generated and about the scripts +used to generate them. + +## General components and structure of a qualkit + +### Qualification kit contents + +A qualification kit (qualkit) is comprised of three main documents: +- The TORs, which stands for tool operational requirements, which describes + the coverage results gnatcov is expected to generate for the relevant Ada + language constructs, and how it is supposed to behave depending on the + various command line arguments that can be used in certification projects; + +- The STR, which stands for Software Test Results, which mostly contains the + results from a qualification testsuite run (qualrun), along with statistics + on the kind and numbers of verified coverage obligations in the tests; + +- The PLANs document, which describe all things procedure related. This + includes the tools developments practices, the tool testing procedure, the + qualkit verification procedure, and the tool interface users must adhere to + when using it in a certification project. + +### Source material for qualkit production + +To produce a qualkit we thus need: +- The sources for the various documents which are + * In the `qualification/plans/` directory for the PLANS; + * In the testsuite all the `testsuite/Qualif/**/content.rst` for the TORs; + * Mostly generated for the STR, but some static bits are placed in + `testsuite/STR/` +- The testsuite tree after execution of the testsuite in qualification mode. + It will contain, in addition to the usual artifacts, some `.dump` files + containing some information about the test context and the amount of tested + obligations. + +The TOR production is a bit delicate as the source `content.rst` are not valid +ReST documents, but instead contain some custom directives that need to be +expanded by the `tor/genrest.py` script. This script has a two pass approach to +compute the full view of the testcases and requirements: +- A top-down traversal of the testsuite to determine the hierarchy between + documents; +- A bottom-up approach to compute for a given test-case, which are the sources + that are actually part of the testcase. + +Once we have an in-memeory representation of the various test-cases & +requirements, along with the sources that go with them, the contents of each +file are processed to replace the "importers" (custom directives) to generate +tables of links to the children and artifacts. + +The importers would gain to be inlined, we can't completely get rid of them yet +as we still need to compute the actual set of sources that belong to a testcase. + + +## Producing a qualification kit with anod + +The simplest way to generate a qualkit is to use the anod specs that will run +the qualification testsuite and produce the documents. +To do so, from a **linux** wavefront sandbox run + +``` +anod build gnatcov-qualkit +``` + +There are multiple qualifiers available to customize the qualification +parameters, a description of which is available through `anod help +gnatcov-qualkit`. + +One important caveat is that with this mechanism it is not possible to create +a qualkit for a Windows hosted testsuite run, unless it is scheduled in a +nightly run through the plans. This is because the production of the pdf +documents depend on texlive, which is not available on Windows hosts, the +`gnatcov-qualkit` spec thus expects the artifacts from the testsuite run to +be available through a cathod component. + +## Producing a kit from source + +To produce a qualkit from source, the first step is to obtain the artifacts +form a qualrun, either through anod, or by running the testsuite manually. + +### Producing a qualrun + +#### Through anod: + +From a wavefront sandbox simply run: + +``` +anod test gnatcov-qualrun +``` + +The qualrun artifacts will be available under +`//gnatcov-qualrun-/artifacts/`. + +#### Running the testsuite manually: + +The requirements to run a qualification testsuite are the same as those for a +"regular" testsuite run, so the environment produced by `gnatcov-dev.anod` is suitable. + +``` +./testsuite.py --trace-mode=src --qualif-level=doA --cargs:ada="-gnatec=native-doA.adc -gnat12" +``` + +The artifacts are in the `testsuite` directory. + +### The genbundle script + +The main entrypoint to produce a qualkit is the `qualification/genbundle.py` +script. It will set the required environment to produce a qualification kit, +generate the sources for the TOR and STR documents, invoke the sphinx +invocations to produce the pdf or html documents, and zip everything together. + +A typical invocation for this script will look like: + +``` +python genbundle.py --docformat=html,pdf --work-dir=$HOME/qualkit-dev/ --dolevel=doA --languages=Ada2012 --testsuite-dir=$HOME/repos/gnatcoverage/testsuite --git-rsync $HOME/repos/gnatcoverage --trace-mode=src +``` + +This invocation will produce kits in both HTML and pdf formats, in the +`$HOME/qualkit-dev/` directory, for a `doA` qualification level, targeting +`Ada2012`, assuming source traces using the testsuite artifacts from +`$HOME/repos/gnatcoverage/testsuite` and the qualification sources & scripts +from `$HOME/repos/gnatcoverage`. + +Parameters may of course be tweaked, see the help of `genbundle.py` for more +information. + +It is also possible not to produce a whole kit but only a single document using +the `--parts` option. + +### Producing the documents individually + +When working on the qualification source directly it may be faster to build the +documents directly. The only requirement is to install `doctools-e3` from a +wave sandbox and set its environment. Beware that the setenv primitive for this +spec will modify the locale, which will most certainly break your shell. You +can instead print the environment variables that would be set, and only export +`PATH` and `LD_LIBRARY_PATH`. + +For all the documents it is necessary to add `/qualification` to +the `PTYHONPATH`. This is done by `genbundle.py` so it not necessary when using +this wrapper. + +#### Producing the PLANS + +The plans are a "simple" ReST document, in order to build either the html or +pdf document go to `qualification/plans` and run: + +``` +(qualification/plans)$ make [html|latexpdf] +``` + +### Producing the TORs + +To generate the TORs, the first step is to gather the required sources, using +the `qualification/tor/genrest.py` script: + +``` +(qualification/tor)$ python genrest.py --dolevel=doA +``` + +You can then build the ReST document via make: + +``` +(qualification/tor)$ make [html|latexpdf] +``` + +### Producing the STR + +Similarly, the STR first needs to go through a source generations gathering +phase: + +``` +(testsuite/STR)$ python genrest.py --testsuite-dir=../ --dolevl=doA +``` + +then followed by + +``` +(testsuite/STR)$ make [html|latexpdf] +``` From 81296974e724a6760ed8ecda387067e29ff24853 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 5 Sep 2025 11:16:22 +0200 Subject: [PATCH 1446/1483] Qualification: Rework qualkit production to use gnatchek-qualkit helpers and style This involves moving large chuncks of the sources to more deeply nested directories, as there are some assumptions as to where some config files are located. --- .gitignore | 13 +- .gitlab-ci.yml | 6 + env/env.yaml | 10 + qualification/Makefile.common | 58 +++++ qualification/genbundle.py | 117 +++++---- qualification/plans/Makefile | 130 ---------- qualification/plans/conf.py | 175 -------------- qualification/qualification.md | 73 ++++-- .../qualkit/_common/project_settings.yaml | 225 ++++++++++++++++++ .../Introduction/Definitions/content.rst | 4 +- .../Introduction/Document_Purpose/content.rst | 0 .../Organization_And_Roles/content.rst | 0 .../Referenced_Documents/content.rst | 25 +- .../plans/Introduction/content.rst | 0 qualification/qualkit/plans/Makefile | 3 + .../Developer/Compliance/content.rst | 4 +- .../Methods_And_Activities/content.rst | 0 .../Developer/Traceability/content.rst | 0 .../Developer/Version_Control/content.rst | 0 .../Developer/content.rst | 2 +- .../User/Compliance/content.rst | 2 +- .../User/Suggested_Items/content.rst | 2 +- .../User/content.rst | 0 .../content.rst | 0 .../Certification_Credit/content.rst | 6 +- .../Compliance/content.rst | 16 +- .../Data_Production/content.rst | 18 +- .../Operational_Conditions/content.rst | 7 +- .../Qualification_Data_Overview/content.rst | 17 +- .../Qualified_Interface/bin_content.rst} | 2 +- .../Qualified_Interface/content.rst | 12 +- .../Qualified_Interface/src_content.rst} | 12 +- .../Tool_Overview/content.rst | 0 .../Tool_Qualification_Level/content.rst | 3 +- .../User_Activities/Archiving/content.rst | 0 .../User_Activities/Qualification/content.rst | 20 +- .../User_Activities/Usage/content.rst | 8 +- .../User_Activities/content.rst | 2 +- .../plans/Tool_Qualification_Plan/content.rst | 0 .../Activities/content.rst | 17 +- .../Compliance/content.rst | 5 +- .../Conformity_Review/content.rst | 5 +- .../Cycles/content.rst | 16 +- .../Tool_Quality_Assurance_Plan/content.rst | 2 +- .../qualkit/plans/document_settings.yaml | 21 ++ .../index.rst => qualkit/plans/plans.rst} | 2 +- .../{ => qualkit}/scripts/__init__.py | 0 qualification/{ => qualkit}/scripts/logger.py | 7 + .../scripts/qm_plugins/__init__.py | 0 .../scripts/qm_plugins/importers.py | 8 +- .../scripts/qm_plugins/link_lrm.py | 0 .../scripts/qm_plugins/lrm_index_parser.py | 0 .../{ => qualkit}/scripts/rest/__init__.py | 0 .../{ => qualkit}/scripts/rest/writer.py | 0 qualification/qualkit/str/Makefile | 4 + .../qualkit/str/document_settings.yaml | 21 ++ qualification/qualkit/tor/Makefile | 4 + qualification/{ => qualkit}/tor/__init__.py | 0 .../qualkit/tor/document_settings.yaml | 21 ++ qualification/{ => qualkit}/tor/genrest.py | 100 ++++---- .../{ => qualkit}/tor/genrest_conf.py | 0 qualification/scripts/common_conf.py | 168 ------------- qualification/tor/Makefile | 130 ---------- qualification/tor/conf.py | 195 --------------- qualification/tor/proj_conf.py | 8 - testsuite/Qualif/Ada/stmt/1_Core/req_set.rst | 5 +- testsuite/Qualif/Appendix/Testsuite/app.rst | 8 +- .../Environment/additional_switches_bin.rst | 0 .../Environment/additional_switches_src.rst | 5 - testsuite/Qualif/Environment/content.rst | 28 +-- testsuite/Qualif/Environment/content.tmpl | 121 ---------- .../Qualif/Environment/env_table_bin.rst | 11 - .../Qualif/Environment/env_table_src.rst | 13 - testsuite/Qualif/Introduction/content.rst | 11 +- testsuite/Qualif/content.rst | 17 +- testsuite/STR/genrest.py | 27 +-- testsuite/STR/source/content.rst | 3 +- 77 files changed, 697 insertions(+), 1258 deletions(-) create mode 100644 env/env.yaml create mode 100644 qualification/Makefile.common delete mode 100644 qualification/plans/Makefile delete mode 100644 qualification/plans/conf.py create mode 100644 qualification/qualkit/_common/project_settings.yaml rename qualification/{ => qualkit}/plans/Introduction/Definitions/content.rst (90%) rename qualification/{ => qualkit}/plans/Introduction/Document_Purpose/content.rst (100%) rename qualification/{ => qualkit}/plans/Introduction/Organization_And_Roles/content.rst (100%) rename qualification/{ => qualkit}/plans/Introduction/Referenced_Documents/content.rst (60%) rename qualification/{ => qualkit}/plans/Introduction/content.rst (100%) create mode 100644 qualification/qualkit/plans/Makefile rename qualification/{ => qualkit}/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst (93%) rename qualification/{ => qualkit}/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst (100%) rename qualification/{ => qualkit}/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst (100%) rename qualification/{ => qualkit}/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst (100%) rename qualification/{ => qualkit}/plans/Tool_Configuration_Management_Plan/Developer/content.rst (87%) rename qualification/{ => qualkit}/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst (90%) rename qualification/{ => qualkit}/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst (92%) rename qualification/{ => qualkit}/plans/Tool_Configuration_Management_Plan/User/content.rst (100%) rename qualification/{ => qualkit}/plans/Tool_Configuration_Management_Plan/content.rst (100%) rename qualification/{ => qualkit}/plans/Tool_Qualification_Plan/Certification_Credit/content.rst (70%) rename qualification/{ => qualkit}/plans/Tool_Qualification_Plan/Compliance/content.rst (73%) rename qualification/{ => qualkit}/plans/Tool_Qualification_Plan/Data_Production/content.rst (87%) rename qualification/{ => qualkit}/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst (67%) rename qualification/{ => qualkit}/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst (84%) rename qualification/{plans/Tool_Qualification_Plan/Qualified_Interface/content_bin.rst => qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/bin_content.rst} (98%) rename qualification/{ => qualkit}/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst (93%) rename qualification/{plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst => qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/src_content.rst} (93%) rename qualification/{ => qualkit}/plans/Tool_Qualification_Plan/Tool_Overview/content.rst (100%) rename qualification/{ => qualkit}/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst (74%) rename qualification/{ => qualkit}/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst (100%) rename qualification/{ => qualkit}/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst (70%) rename qualification/{ => qualkit}/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst (65%) rename qualification/{ => qualkit}/plans/Tool_Qualification_Plan/User_Activities/content.rst (73%) rename qualification/{ => qualkit}/plans/Tool_Qualification_Plan/content.rst (100%) rename qualification/{ => qualkit}/plans/Tool_Quality_Assurance_Plan/Activities/content.rst (88%) rename qualification/{ => qualkit}/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst (76%) rename qualification/{ => qualkit}/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst (87%) rename qualification/{ => qualkit}/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst (92%) rename qualification/{ => qualkit}/plans/Tool_Quality_Assurance_Plan/content.rst (89%) create mode 100644 qualification/qualkit/plans/document_settings.yaml rename qualification/{plans/index.rst => qualkit/plans/plans.rst} (87%) rename qualification/{ => qualkit}/scripts/__init__.py (100%) rename qualification/{ => qualkit}/scripts/logger.py (93%) rename qualification/{ => qualkit}/scripts/qm_plugins/__init__.py (100%) rename qualification/{ => qualkit}/scripts/qm_plugins/importers.py (99%) rename qualification/{ => qualkit}/scripts/qm_plugins/link_lrm.py (100%) rename qualification/{ => qualkit}/scripts/qm_plugins/lrm_index_parser.py (100%) rename qualification/{ => qualkit}/scripts/rest/__init__.py (100%) rename qualification/{ => qualkit}/scripts/rest/writer.py (100%) create mode 100644 qualification/qualkit/str/Makefile create mode 100644 qualification/qualkit/str/document_settings.yaml create mode 100644 qualification/qualkit/tor/Makefile rename qualification/{ => qualkit}/tor/__init__.py (100%) create mode 100644 qualification/qualkit/tor/document_settings.yaml rename qualification/{ => qualkit}/tor/genrest.py (96%) rename qualification/{ => qualkit}/tor/genrest_conf.py (100%) delete mode 100644 qualification/scripts/common_conf.py delete mode 100644 qualification/tor/Makefile delete mode 100644 qualification/tor/conf.py delete mode 100644 qualification/tor/proj_conf.py delete mode 100644 testsuite/Qualif/Environment/additional_switches_bin.rst delete mode 100644 testsuite/Qualif/Environment/additional_switches_src.rst delete mode 100644 testsuite/Qualif/Environment/content.tmpl delete mode 100644 testsuite/Qualif/Environment/env_table_bin.rst delete mode 100644 testsuite/Qualif/Environment/env_table_src.rst diff --git a/.gitignore b/.gitignore index 21538c405..4e37d3074 100644 --- a/.gitignore +++ b/.gitignore @@ -35,12 +35,17 @@ TAGS *.log # temporary output of genrest.py -qualification/tor/source/ +qualification/qualkit/tor/source/ + +# local copy/link to the gnatcheck-qualkit sources +qualification/gnatcheck_qualkit_common # generated output of genbundle.py -**/build -**/source -**/missing_tr_log.txt +qualification/**/build +qualification/**/source +qualification/**/missing_tr_log.txt +testsuite/STR/build +testsuite/STR/source # vscode local settings .env diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9d05adfb8..1967c666c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -282,8 +282,12 @@ test_qualkit: - anod test gnatcov-qualrun --minimal -Qci $ACI_TRACK_QUALIFIER - anod build gnatcov-qualkit --minimal -Qci $ACI_TRACK_QUALIFIER - QUALKIT_BSN=$(anod eval --primitive=build gnatcov-qualkit -Qci $ACI_TRACK_QUALIFIER build_space_name) + - QUALRUN_BSN=$(anod eval --primitive=test gnatcov-qualrun -Qci $ACI_TRACK_QUALIFIER build_space_name) - mkdir $CI_PROJECT_DIR/qualkits + - mkdir $CI_PROJECT_DIR/qualrun + - cp $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$QUALRUN_BSN/tmp/attachment-testsuite_tree.tgz $CI_PROJECT_DIR/qualrun/ - cp $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$QUALKIT_BSN/install/*.zip $CI_PROJECT_DIR/qualkits/ + - cp $ANOD_DEFAULT_SANDBOX_DIR/x86_64-linux/$QUALKIT_BSN/install/consistency.log $CI_PROJECT_DIR/qualkits/ - testsuite_reports rules: - if: $CI_PIPELINE_SOURCE == 'merge_request_event' @@ -299,5 +303,7 @@ test_qualkit: paths: - xunit-*.xml - qualkits/*.zip + - qualkits/consistency.log + - qualrun/attachment-testsuite_tree.tgz reports: junit: xunit-*.xml diff --git a/env/env.yaml b/env/env.yaml new file mode 100644 index 000000000..3ec3c3591 --- /dev/null +++ b/env/env.yaml @@ -0,0 +1,10 @@ +coding_standard: adacore +ada_version: '2012' + +target_exec: '' +runtime: '' + +version_number: 0.00 (YYYYMMDD) + +tags: [] + diff --git a/qualification/Makefile.common b/qualification/Makefile.common new file mode 100644 index 000000000..9c9600817 --- /dev/null +++ b/qualification/Makefile.common @@ -0,0 +1,58 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +CONFDIR = ../../gnatcheck_qualkit_common +SOURCEDIR = .. +SPHINXOPTS = -c $(CONFDIR) +SPHINXBUILD = DOC_NAME=$(DOC) TOOL_DIR=$(TOOL) MASTER=$(MASTER_DOC) sphinx-build +PAPER = +BUILDDIR = build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SOURCEDIR) + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + + +pdf: + @echo "Copying adacore.png to $(BUILDDIR)/pdf" + @echo "Source: $(CONFDIR)/adacore.png" + @echo "Destination: $(BUILDDIR)/pdf" + @if [ -f $(CONFDIR)/adacore.png ]; then echo "Source file exists"; else echo "Source file does not exist"; fi + @if [ -d $(BUILDDIR)/pdf ]; then echo "Destination directory exists"; else echo "Creating destination directory"; mkdir -p $(BUILDDIR)/pdf; fi + cp $(CONFDIR)/adacore.png $(BUILDDIR)/pdf + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/pdf + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/pdf all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/pdf." + +.PHONY: all +all : html latexpdf diff --git a/qualification/genbundle.py b/qualification/genbundle.py index 2a183a667..397f1efbf 100644 --- a/qualification/genbundle.py +++ b/qualification/genbundle.py @@ -192,7 +192,7 @@ # ***************************************************************************** from e3.os.process import Run -from e3.fs import cp, mv, rm, mkdir, ls, find +from e3.fs import cp, mv, rm, mkdir, ls, find, sync_tree from datetime import date @@ -368,13 +368,13 @@ def __init__(self, options): self.workdir = os.path.abspath(options.workdir) self.repodir = os.path.join(self.workdir, REPO_IMAGE_SUBDIR) - self.qualdir = os.path.join(self.repodir, "qualification") + self.qualdir = os.path.join(self.repodir, "qualification", "qualkit") # A local place where the testsuite tree may be found, # possibly after remote syncing from testsuite_dir if that # is non-local: - self.local_testsuite_dir = None + self.local_testsuite_dir = "" # To be set prior to build_as_needed(): @@ -384,41 +384,21 @@ def __init__(self, options): self.passno = 0 - def process_imports(self, dirname): - """ - Process the template file in dirname, replacing the occurrences of - <%name%> in the text by the contents of name_.rst, - according to the qualification parameters - """ - - def replace_one(p): - return contents_of( - os.path.join(dirname, p.group(1) + f"_{self.o.trace_mode}.rst") - ) - - template_content = contents_of(os.path.join(dirname, "content.tmpl")) - with open(os.path.join(dirname, "content.rst"), "w") as f: - f.write( - re.sub( - pattern=r"<%([^%]+)%>", - repl=replace_one, - string=template_content, - ) - ) - # --------------------- # -- prepare_content -- # --------------------- - def prepare_content(self, dirs): + def prepare_content(self, dirs, root): """ - Prepare the content files by choosing the correct content_*.rst file + Prepare the content files by choosing the correct *_content.rst file according to the qualification parameters. """ for dirname in dirs: cp( - os.path.join(dirname, f"content_{self.o.trace_mode}.rst"), - os.path.join(dirname, "content.rst"), + os.path.join( + root, dirname, f"{self.o.trace_mode}_content.rst" + ), + os.path.join(root, dirname, "content.rst"), ) # -------------------- @@ -520,7 +500,7 @@ def kititem_for(self, part): ) return "%(part)s%(suffix)s" % { - "part": part.upper(), + "part": part.lower(), "suffix": this_item_suffix, } @@ -580,14 +560,14 @@ def __latch_into(self, dirname, part, toplevel, copy_from=None): this_build_subdir = os.path.join( copy_from if copy_from is not None else "build", - sphinx_target_for[self.this_docformat], + self.this_docformat, ) this_source = ( this_build_subdir if this_target_is_tree else os.path.join( - this_build_subdir, part.upper() + ".%s" % self.this_docformat + this_build_subdir, part.lower() + ".%s" % self.this_docformat ) ) @@ -640,28 +620,23 @@ def sync(tr): [sync(tr) for tr in find(root=".", pattern="tcs.dump")] - env_chapter_dir = os.path.join( - self.repodir, "testsuite", "Qualif", "Environment" - ) - self.process_imports(env_chapter_dir) - announce("building %s %s" % (self.this_docformat, "TOR")) - os.chdir(os.path.join(self.repodir, "qualification", "tor")) - + tor_dir = os.path.join(self.repodir, "qualification", "qualkit", "tor") run( - "python genrest.py --dolevel %s --force" % (self.o.dolevel), + f"python genrest.py --dolevel {self.o.dolevel} --force" + f" --testsuite-dir {self.o.testsuite_dir}", env={"PYTHONPATH": self.qualdir}, + dirname=tor_dir, ) - run( - "make %s" % (sphinx_target_for[self.this_docformat]), - env={ - "GENBUNDLE_DOLEVEL": self.o.dolevel, - "PYTHONPATH": self.qualdir, - }, - ) + run("make %s" % (self.this_docformat), dirname=tor_dir) - self.__latch_into(dirname=self.itemsdir(), part="tor", toplevel=False) + self.__latch_into( + dirname=self.itemsdir(), + part="tor", + toplevel=False, + copy_from=os.path.join(tor_dir, "build"), + ) # ------------------------------ # -- dump_kit_consistency_log -- @@ -769,7 +744,11 @@ def __dump_tr_consistency_info(self, log): log.write("\n-- TOR/TR CONSISTENCY LOG:\n") tor_tr_logfile = os.path.join( - self.repodir, "qualification", "tor", "missing_tr_log.txt" + self.repodir, + "qualification", + "qualkit", + "tor", + "missing_tr_log.txt", ) if not os.path.exists(tor_tr_logfile): @@ -903,36 +882,50 @@ def __prepare_str_dir(self): def build_str(self): announce("building %s STR" % self.this_docformat) - os.chdir(os.path.join(self.local_testsuite_dir, "STR")) + str_dir = os.path.join(self.qualdir, "str") - run( - "make %s" % sphinx_target_for[self.this_docformat], - env={"PYTHONPATH": self.qualdir}, + source_str_dir = os.path.join( + self.local_testsuite_dir, "STR", "source" ) + dest_str_dir = os.path.join(str_dir, "source") + + # Copy the sources from the testsuite into the work dir + sync_tree(source_str_dir, dest_str_dir, delete=True) - self.__latch_into(dirname=self.itemsdir(), part="str", toplevel=False) + run("make %s" % self.this_docformat, dirname=str_dir) + + self.__latch_into( + dirname=self.itemsdir(), + part="str", + toplevel=False, + copy_from=os.path.join(str_dir, "build"), + ) # ----------------- # -- build_plans -- # ----------------- def build_plans(self): - plans_root = os.path.join(self.repodir, "qualification", "plans") + plans_root = os.path.join( + self.repodir, + "qualification", + "qualkit", + "plans", + ) trace_specific_content = [ os.path.join( plans_root, "Tool_Qualification_Plan", "Qualified_Interface" ) ] - self.prepare_content(trace_specific_content) + self.prepare_content(trace_specific_content, root=plans_root) - os.chdir(plans_root) - run( - f"make {sphinx_target_for[self.this_docformat]}", - env={"PYTHONPATH": self.qualdir}, - ) + run(f"make {self.this_docformat}", dirname=plans_root) self.__latch_into( - dirname=self.itemsdir(), part="plans", toplevel=False + dirname=self.itemsdir(), + part="plans", + toplevel=False, + copy_from=os.path.join(plans_root, "build"), ) # --------------- diff --git a/qualification/plans/Makefile b/qualification/plans/Makefile deleted file mode 100644 index 390b4f07f..000000000 --- a/qualification/plans/Makefile +++ /dev/null @@ -1,130 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -c . -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Couverture.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Couverture.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/Couverture" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Couverture" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latexpdf - @echo "Running LaTeX files through pdflatex..." - make -C $(BUILDDIR)/latexpdf all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/qualification/plans/conf.py b/qualification/plans/conf.py deleted file mode 100644 index 844c884c2..000000000 --- a/qualification/plans/conf.py +++ /dev/null @@ -1,175 +0,0 @@ -from collections import OrderedDict -from scripts.common_conf import ( - version, - project_name, - owner, - users, - assignments, - plans_doc_id, - rst_prolog, - VAR_REPLACEMENTS, -) - -doc_id = plans_doc_id - -extensions: list[str] = [] -papersize = "a4paper" -latex_show_pagerefs = True -html_sidebars = {"**": ["localtoc.html", "sourcelink.html", "searchbox.html"]} -latex_use_parts = False -toc_depth = 2 - -# roles definition -# ??? This is standard-specific and should not be defined here. -roles = OrderedDict( - [ - ("authors", {"description": "the authors of the document"}), - ("reviewers", {"description": "the reviewers of the document"}), - ("approvers", {"description": "the approvers of the document"}), - ] -) - -# Do some checks -assert rst_prolog is not None, "rst_prolog should be set in common_conf.py" - -templates_path = ["_templates"] - -# These parameters cannot be overriden so just force their value after -# reading user conf file -master_doc = "index" - -source_suffix = ".rst" -project = project_name -exclude_patterns = ["_build", "**/*_bin.rst", "**/*_src.rst"] -pygments_style = "sphinx" -html_theme = "classic" -html_theme_path = ["."] -html_theme_options = {"body_max_width": None} - - -PAGE_BLANK = r""" -\makeatletter -\def\cleartooddpage{%% - \cleardoublepage%% -} -\def\cleardoublepage{%% -\clearpage%% - \if@twoside%% - \ifodd\c@page%% - %% nothing to do - \else%% - \hbox{}%% - \thispagestyle{plain}%% - \vspace*{\fill}%% - \begin{center}%% - \textbf{\em This page is intentionally left blank.}%% - \end{center}%% - \vspace{\fill}%% - \newpage%% - \if@twocolumn%% - \hbox{}%% - \newpage%% - \fi%% - \fi%% - \fi%% -} -\makeatother -""" - -TOC_DEPTH = ( - r""" -\pagenumbering{arabic} -\setcounter{tocdepth}{%d} -""" - % toc_depth -) - -TOC_CMD = r""" -\makeatletter -\def\tableofcontents{%% - \pagestyle{plain}%% - \chapter*{\contentsname}%% - \@mkboth{\MakeUppercase{\contentsname}}%% - {\MakeUppercase{\contentsname}}%% - \@starttoc{toc}%% -} -\makeatother -""" - - -def latex_hyphen(): - return "\n".join([r"\hyphenpenalty=5000", r"\tolerance=1000"]) - - -def project_settings(): - - HLINE = r"\hline" - HEADERS = r"Name & Company & Team & Email \\" - assignment_tab = [] - - for role in filter(lambda x: x in assignments, roles.keys()): - title = ( - r"\multicolumn{4}{l}{\large \par} \\" - r" \multicolumn{4}{l}{\large %s \par} \\" % (role.capitalize()) - ) - - assignment_tab.append(title) - assignment_tab.append(HLINE) - assignment_tab.append(HEADERS) - assignment_tab.append(HLINE) - - for login in assignments[role]: - user = users[login] - assignment_tab.append( - r"%s & %s & %s & %s \\" - % (user["name"], user["company"], user["team"], user["email"]) - ) - - assignment_tab.append(HLINE) - - full_document_name = project_name - if doc_id is not None and len(doc_id) > 0: - full_document_name = "%s - %s" % (project_name, doc_id) - - return "\n".join( - [ - r"\newcommand*{\QMFullDocumentName}[0]{" - + full_document_name - + r"}", - r"\newcommand*{\QMProjectName}[0]{" + project_name + r"}", - r"\newcommand*{\QMDocID}[0]{" + doc_id + r"}", - r"\newcommand*{\QMVersion}[0]{" + version + r"}", - r"\newcommand*{\QMTabUsers}[0]{" - + "\n".join(assignment_tab) - + r"}", - ] - ) - - -TOC = r""" -\cleardoublepage -\tableofcontents -\cleardoublepage\pagestyle{plain} -""" - -latex_elements = { - "preamble": TOC_DEPTH - + PAGE_BLANK - + TOC_CMD - + latex_hyphen() - + "\n" - + project_settings(), - "tableofcontents": TOC, - "papersize": papersize, -} - -latex_documents = [ - ( - "index", - "PLANS.tex", - f"GNATcoverage DO-178C/ED-12C Qualification Material" - f": {VAR_REPLACEMENTS["plans_doc_title"]}", - owner, - "manual", - ), -] diff --git a/qualification/qualification.md b/qualification/qualification.md index 5055e6fc4..37c01b12d 100644 --- a/qualification/qualification.md +++ b/qualification/qualification.md @@ -6,6 +6,23 @@ comprise the DO-178C qualification kit for GNATcoverage, and provide some details as to how each document is generated and about the scripts used to generate them. +## Prerequisites + +All documents require some common configuration that we pull from the +/eng/libadalang/gnatcheck-qualkit repository. +To set things up correctly clone the repository somewhere (later referenced +as ) and copy / make a symbolic link as follows + +```console +(gnatcov/qualification)$ ln -s /doc/_common gnatcheck_qualkit_common +``` + +or + +```console +(gnatcov/qualification)$ cp -r /doc/_common gnatcheck_qualkit_common +``` + ## General components and structure of a qualkit ### Qualification kit contents @@ -29,7 +46,7 @@ A qualification kit (qualkit) is comprised of three main documents: To produce a qualkit we thus need: - The sources for the various documents which are - * In the `qualification/plans/` directory for the PLANS; + * In the `qualification/qualkit/plans/` directory for the PLANS; * In the testsuite all the `testsuite/Qualif/**/content.rst` for the TORs; * Mostly generated for the STR, but some static bits are placed in `testsuite/STR/` @@ -40,14 +57,14 @@ To produce a qualkit we thus need: The TOR production is a bit delicate as the source `content.rst` are not valid ReST documents, but instead contain some custom directives that need to be -expanded by the `tor/genrest.py` script. This script has a two pass approach to -compute the full view of the testcases and requirements: +expanded by the `qualkit/tor/genrest.py` script. This script has a two pass +approach to compute the full view of the testcases and requirements: - A top-down traversal of the testsuite to determine the hierarchy between documents; - A bottom-up approach to compute for a given test-case, which are the sources that are actually part of the testcase. -Once we have an in-memeory representation of the various test-cases & +Once we have an in-memory representation of the various test-cases & requirements, along with the sources that go with them, the contents of each file are processed to replace the "importers" (custom directives) to generate tables of links to the children and artifacts. @@ -62,8 +79,8 @@ The simplest way to generate a qualkit is to use the anod specs that will run the qualification testsuite and produce the documents. To do so, from a **linux** wavefront sandbox run -``` -anod build gnatcov-qualkit +```console +(wave)$ anod build gnatcov-qualkit ``` There are multiple qualifiers available to customize the qualification @@ -89,7 +106,7 @@ form a qualrun, either through anod, or by running the testsuite manually. From a wavefront sandbox simply run: ``` -anod test gnatcov-qualrun +(wave)$ anod test gnatcov-qualrun ``` The qualrun artifacts will be available under @@ -100,8 +117,8 @@ The qualrun artifacts will be available under The requirements to run a qualification testsuite are the same as those for a "regular" testsuite run, so the environment produced by `gnatcov-dev.anod` is suitable. -``` -./testsuite.py --trace-mode=src --qualif-level=doA --cargs:ada="-gnatec=native-doA.adc -gnat12" +```console +(gnatcov/testsuite)$ ./testsuite.py --trace-mode=src --qualif-level=doA --cargs:ada="-gnatec=native-doA.adc -gnat12" ``` The artifacts are in the `testsuite` directory. @@ -116,7 +133,9 @@ invocations to produce the pdf or html documents, and zip everything together. A typical invocation for this script will look like: ``` -python genbundle.py --docformat=html,pdf --work-dir=$HOME/qualkit-dev/ --dolevel=doA --languages=Ada2012 --testsuite-dir=$HOME/repos/gnatcoverage/testsuite --git-rsync $HOME/repos/gnatcoverage --trace-mode=src +(gnatcov/qualification)$ python genbundle.py --docformat=html,pdf --work-dir=$HOME/qualkit-dev/ \ +--dolevel=doA --languages=Ada2012 --testsuite-dir=$HOME/repos/gnatcoverage/testsuite \ +--rsync-from $HOME/repos/gnatcoverage --trace-mode=src ``` This invocation will produce kits in both HTML and pdf formats, in the @@ -140,17 +159,17 @@ spec will modify the locale, which will most certainly break your shell. You can instead print the environment variables that would be set, and only export `PATH` and `LD_LIBRARY_PATH`. -For all the documents it is necessary to add `/qualification` to -the `PTYHONPATH`. This is done by `genbundle.py` so it not necessary when using -this wrapper. +For the TOR document it is necessary to add `/qualification/qualkit` +to the `PYTHONPATH`. This is done by `genbundle.py` so it not necessary when +using this wrapper. #### Producing the PLANS The plans are a "simple" ReST document, in order to build either the html or pdf document go to `qualification/plans` and run: -``` -(qualification/plans)$ make [html|latexpdf] +```console +(qualification/qualkit/plans)$ make [html|pdf] ``` ### Producing the TORs @@ -158,14 +177,15 @@ pdf document go to `qualification/plans` and run: To generate the TORs, the first step is to gather the required sources, using the `qualification/tor/genrest.py` script: -``` -(qualification/tor)$ python genrest.py --dolevel=doA +```console +(qualification/qualkit/tor)$ python genrest.py --dolevel=doA ``` -You can then build the ReST document via make: +You can then build the ReST document via make (this takes a while and generates +lots of warnings, it is expected): -``` -(qualification/tor)$ make [html|latexpdf] +```console +(qualification/qualkit/tor)$ make [html|pdf] ``` ### Producing the STR @@ -173,12 +193,19 @@ You can then build the ReST document via make: Similarly, the STR first needs to go through a source generations gathering phase: +```console +(testsuite/STR)$ python genrest.py --testsuite-dir=../ --dolevel=doA ``` -(testsuite/STR)$ python genrest.py --testsuite-dir=../ --dolevl=doA + +The generated sources need to be copied into the `qualification/qualkit/str` +directory: + +```console +(qualification/qualkit/str)$ cp -r ../../../testsuite/STR/source . ``` then followed by -``` -(testsuite/STR)$ make [html|latexpdf] +```console +(qualification/qualkit/str)$ make [html|pdf] ``` diff --git a/qualification/qualkit/_common/project_settings.yaml b/qualification/qualkit/_common/project_settings.yaml new file mode 100644 index 000000000..863d962df --- /dev/null +++ b/qualification/qualkit/_common/project_settings.yaml @@ -0,0 +1,225 @@ +project: + subst: { + + # USER_ENTRIES + + # Project definitions + 'prj_title': 'GNATcoverage - DO-330/ED-215 QDP', + 'prj_toolset': 'GNATcoverage', + 'prj_toolset_bold': '**GNATcoverage**', + 'prj_switches': '', + 'prj_platform': 'TBD', + 'prj_host_platform': 'TBD', + 'prj_RTS': 'No --RTS switch expected. Programs shall honor the :ref:`language-scope` restrictions, nevertheless.', + 'prj_dump_trigger': ':literal:`--dump-triger=atexit`', + 'prj_dump_channel': ':literal:`--dump-channel=bin-file`', + 'prj_ASIL': 'ASIL D', + 'prj_DAL': 'A', + 'prj_TCL': 'TCL 3', + 'prj_TQL': 'TQL-5', + 'tool_standard': 'DO-178C/ED-12C', + 'tool_supplement_standard': 'DO-330/ED-215', + 'prj_release_plan_repository': 'git@ssh.gitlab.adacore-it.com:eng/it/anod.git', + 'prj_release_process_database': 'TBD', + 'prj_new_features': 'TBD', + 'prj_known_problems': 'TBD', + 'prj_gpr_new_features': 'TBD', + 'prj_gpr_known_problems': 'TBD', + 'prj_known_problems_date': 'TBD', + + # Project assignments + + 'prj_pm': &prj_assignment_pm 'Vasiliy Fofanov', + 'prj_sm': &prj_assignment_sm 'TBD', + 'prj_ver': &prj_assignment_ver 'TBD', + 'prj_wri': &prj_assignment_wri 'TBD', + + # Document definitions + 'plans_doc': &prj_doc_plans 'Qualification Plans', + 'plans_id': &prj_docid_plans 'SE.DOC-TBD', + 'plans_abb': '*PLANS*', + + 'tor_doc': &prj_doc_tor 'Tool Operational Requirements and V\&V Cases and Procedures', + 'tor_id': &prj_docid_tor 'SE.DOC-TBD', + 'tor_abb': '*TOR*', + + 'str_doc': &prj_doc_str 'Tool Operational Verification and Validation Results', + 'str_id': &prj_docid_str 'SE.DOC-TBD', + 'str_abb': '*STR*', + + 'tqa_doc': &prj_doc_tqa 'Tool Quality Assurance Records', + 'tqa_id': &prj_docid_tqa 'SE.DOC-TBD', + + # Project tool versions + + 'gnatcov_version': 'TDB', + 'gnatpro_version': 'TDB', + 'gprbuild_version': 'TDB', + 'gnatemu_version': 'TDB', + + # END_OF_USER_ENTRIES + + # Project abbreviations + + 'TBD': &prj_abbr_tbd 'To Be Done', + 'QA': 'Quality Assurance', + 'adacore': 'AdaCore', + + # AdaCore QMS documents + + 'acqp_doc': 'AdaCore Quality Procedures', + 'acqp_ref': 'ACQP', + 'acqp_id': 'ENG.DOC-107', + 'acqp_version': 'Version 13', + + 'accm_doc': 'AdaCore ISO 9001:2015 Compliance Matrix', + 'accm_ref': 'ACCM', + 'accm_id': 'ENG.DOC-101', + 'accm_version': 'Version 3', + + 'acip_doc': 'AdaCore ISO 9001:2015 Procedures', + 'acip_ref': 'ACIP', + 'acip_id': 'ENG.DOC-102', + 'acip_version': 'Version 4', + + 'acp_doc': 'AdaCore Procedures', + 'acp_ref': 'ACP', + 'acp_id': 'SE.DOC-353', + 'acp_version': 'Version 10', + + 'acqm_doc': 'AdaCore Quality Manual', + 'acqm_ref': 'ACQM', + 'acqm_id': 'ENG.DOC-104', + 'acqm_version': 'Version 4', + + 'acrp_doc': 'AdaCore Release Procedures', + 'acrp_ref': 'ACRP', + 'acrp_id': 'SE.DOC-361', + 'acrp_version': 'Version 13', + + 'pep_doc': 'Product Engineering Procedures', + 'pep_ref': 'PEP', + 'pep_id': 'ENG.DOC-383', + 'pep_version': 'Version 6', + + # Technical documents + + 'acs_doc': 'Ada Coding Style', + 'acs_ref': 'ACS', + 'acs_id': 'SE.DOC-359', + 'acs_version': 'Version 6', + + 'alrm_doc': 'Ada Reference Manual - Language and Standard Libraries', + 'alrm_ref': 'ALRM', + 'alrm_id': 'N/A', + 'alrm_version': 'ISO/IEC 8652:2012(E) with COR.1:2016', + + 'atsug_doc': 'The Ada Conformity Assessment Test Suite (ACATS) User''s guide', + 'atsug_ref': 'ATSUG', + 'atsug_id': 'N/A', + 'atsug_version': 'Version 3.1, January 30, 2014', + + 'gaug_doc': 'Using as', + 'gaug_ref': 'GAUG', + 'gaug_id': 'N/A', + 'gaug_version': 'TBD', + + 'gbu_doc': 'GNU Binary Utilities', + 'gbu_ref': 'GBU', + 'gbu_id': 'N/A', + 'gbu_version': 'TBD', + + 'gbug_doc': 'GPR Tools User''s Guide', + 'gbug_ref': 'GPRUG', + 'gbug_id': 'N/A', + 'gbug_version': '19.8', + + 'gccug_doc': 'using gcc', + 'gccug_ref': 'GCCUG', + 'gccug_id': 'n/a', + 'gccug_version': 'TBD', + + 'glug_doc': 'The GNU linker', + 'glug_ref': 'GLUG', + 'glug_id': 'n/a', + 'glug_version': 'TBD', + + 'gprm_doc': 'GNAT Pro Reference Manual', + 'gprm_ref': 'GPRM', + 'gprm_id': 'N/A', + 'gprm_version': '19.8', + + 'gpug_doc': 'GNAT Pro User''s Guide for Native Platforms', + 'gpug_ref': 'GPUG', + 'gpug_id': 'N/A', + 'gpug_version': 'TBD', + + 'gpugc_doc': 'GNAT Pro User Guide Supplement for Cross Platforms', + 'gpugc_ref': 'GPUGC', + 'gpugc_id': 'N/A', + 'gpugc_version': 'TBD', + + 'spug_doc': 'SPARK 2014 Toolset User''s Guide', + 'spug_ref': 'SPUG', + 'spug_id': 'N/A', + 'spug_version': 'TBD', + + 'gcheck_doc': 'GNATcheck Reference Manual', + 'gcheck_ref': 'GCRM', + 'gcheck_id': 'N/A', + 'gcheck_version': '19.8', + + 'gsas_doc': 'GNAT SAS User''s Guide', + 'gsas_ref': 'GSASUG', + 'gsas_id': 'N/A', + 'gsas_version': 'TBD', + + # Standards + + 'guapl_doc': 'Information technology - Programming languages - Guide for the Use of the Ada Programming Language in High Integrity Systems', + 'guapl_ref': 'GUAPL', + 'guapl_id': 'N/A', + 'guapl_version': 'ISO/IEC TR 15942:2000(E)', + + 'iec_doc': 'Functional safety of electrical/electronic/programmable electronic safety-related systems', + 'iec_ref' : 'IEC-61508', + 'iec_id': 'N/A', + 'iec_version': 'IEC 61508:2010', + + 'iqms_doc': 'ISO 9001:2015(E) Quality Management Systems - Requirements', + 'iqms_ref': 'IQMS', + 'iqms_id': 'N/A', + 'iqms_version': 'ISO 9001:2015(E)', + + 'iso_doc': 'Road Vehicles - Functional Safety', + 'iso_ref' : 'ISO-26262', + 'iso_id': 'N/A', + 'iso_version': 'ISO 26262:2018', + + 'racsps_doc': 'Railway applications - Communications, signalling and processing systems - Software for railway control and protection systems', + 'racsps_ref': 'RACSPS', + 'racsps_id': 'N/A', + 'racsps_version': 'EN 50128:2001', + + 'racspsb_doc': 'Railway applications - Communications, signalling and processing systems - Software for railway control and protection systems', + 'racspsb_ref': 'RACSPSB', + 'racspsb_id': 'N/A', + 'racspsb_version': 'EN 50128:2011', + + 'spasb_doc': 'Space Product Assurance', + 'spasb_ref': 'SPASB', + 'spasb_id': 'N/A', + 'spasb_version': 'B', + + 'spasc_doc': 'Space Product Assurance', + 'spasc_ref': 'SPASC', + 'spasc_id': 'N/A', + 'spasc_version': 'C', + + 'do_doc': 'Software Considerations in Airborne Systems and Equipment Certification', + 'do_ref': 'DO-178', + 'do_id': 'N/A', + 'do_version': 'DO-178C', + + + } diff --git a/qualification/plans/Introduction/Definitions/content.rst b/qualification/qualkit/plans/Introduction/Definitions/content.rst similarity index 90% rename from qualification/plans/Introduction/Definitions/content.rst rename to qualification/qualkit/plans/Introduction/Definitions/content.rst index f71b18960..f47fa4476 100644 --- a/qualification/plans/Introduction/Definitions/content.rst +++ b/qualification/qualkit/plans/Introduction/Definitions/content.rst @@ -4,7 +4,7 @@ Definitions General Definitions ------------------- -The Annex B of [|tool_standard|] provides a list of acronyms and glossary of +The Annex B of [|tool_supplement_standard|] provides a list of acronyms and glossary of common terms used throughout this qualification material. Project Specific Definitions @@ -35,5 +35,3 @@ Requirement. .. rubric:: Tool Operational Requirement (TOR) A TOR describes the expected behavior of a tool from the user point of view. - - diff --git a/qualification/plans/Introduction/Document_Purpose/content.rst b/qualification/qualkit/plans/Introduction/Document_Purpose/content.rst similarity index 100% rename from qualification/plans/Introduction/Document_Purpose/content.rst rename to qualification/qualkit/plans/Introduction/Document_Purpose/content.rst diff --git a/qualification/plans/Introduction/Organization_And_Roles/content.rst b/qualification/qualkit/plans/Introduction/Organization_And_Roles/content.rst similarity index 100% rename from qualification/plans/Introduction/Organization_And_Roles/content.rst rename to qualification/qualkit/plans/Introduction/Organization_And_Roles/content.rst diff --git a/qualification/plans/Introduction/Referenced_Documents/content.rst b/qualification/qualkit/plans/Introduction/Referenced_Documents/content.rst similarity index 60% rename from qualification/plans/Introduction/Referenced_Documents/content.rst rename to qualification/qualkit/plans/Introduction/Referenced_Documents/content.rst index e12485a96..0d55c4e0c 100644 --- a/qualification/plans/Introduction/Referenced_Documents/content.rst +++ b/qualification/qualkit/plans/Introduction/Referenced_Documents/content.rst @@ -6,13 +6,13 @@ Referenced Documents Bordin et al.: *Couverture: An Innovative Open Framework for Coverage Analysis of Safety Critical Applications* - Ada User Journal, December 2009. -.. rubric:: |standard| +.. rubric:: |tool_standard| RTCA DO-178C/EUROCAE ED-12C: *Software Considerations in Airborne Systems and Equipment Certification*; December 13, 2011 -.. rubric:: |tool_standard| +.. rubric:: |tool_supplement_standard| RTCA DO-330/EUROCAE ED-215: *Software Tool Qualification Considerations*; @@ -25,30 +25,29 @@ for Safety-Critical Applications* - ERTS2 2010 .. rubric:: GNAT Pro UG -AdaCore: *GNAT User's Guide for Native Platforms*, part of the GNAT Pro +|adacore|: *GNAT User's Guide for Native Platforms*, part of the GNAT Pro |gnatpro_version| release documentation (file *share/doc/gnat/pdf/gnat_ugn.pdf*). .. rubric:: GNATcoverage UG -AdaCore: *GNATcoverage User's Guide*, part of the GNATcoverage +|adacore|: *GNATcoverage User's Guide*, part of the GNATcoverage |gnatcov_version| release documentation (file *share/doc/gnatdas/pdf/gnatdas.pdf*). -.. rubric:: |plans_doc_title| +.. rubric:: |plans_doc| -AdaCore: |project_name_it| - |plans_doc_title|, |plans_doc_id|, this document. +|adacore|: |prj_toolset| - |plans_doc|, |plans_id|, this document. -.. rubric:: |tor_doc_title| +.. rubric:: |tor_doc| -AdaCore: |project_name_it| - |tor_doc_title|, |tor_doc_id|, included in this +|adacore|: |prj_toolset| - |tor_doc|, |tor_id|, included in this qualification package. -.. rubric:: |str_doc_title| +.. rubric:: |str_doc| -AdaCore: |project_name_it| - |str_doc_title|, |str_doc_id|, included in this +|adacore|: |prj_toolset| - |str_doc|, |str_id|, included in this qualification package. -.. rubric:: |tqa_doc_title| +.. rubric:: |tqa_doc| -AdaCore: |project_name_it| - |tqa_doc_title|, accompanying this qualification +|adacore|: |prj_toolset| - |tqa_doc|, accompanying this qualification package. - diff --git a/qualification/plans/Introduction/content.rst b/qualification/qualkit/plans/Introduction/content.rst similarity index 100% rename from qualification/plans/Introduction/content.rst rename to qualification/qualkit/plans/Introduction/content.rst diff --git a/qualification/qualkit/plans/Makefile b/qualification/qualkit/plans/Makefile new file mode 100644 index 000000000..f76f6230e --- /dev/null +++ b/qualification/qualkit/plans/Makefile @@ -0,0 +1,3 @@ +DOC=plans +TOOL?=$(realpath ../) +include ../../Makefile.common diff --git a/qualification/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst similarity index 93% rename from qualification/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst rename to qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst index 9fd4606de..d16c75b1c 100644 --- a/qualification/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst +++ b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Compliance/content.rst @@ -3,7 +3,7 @@ Compliance Matrices .. tabularcolumns:: |p{0.05\linewidth}|p{0.30\linewidth}|p{0.13\linewidth}|p{0.10\linewidth}|p{0.32\linewidth}| -.. csv-table:: Compliance matrix for Table 7-1 of |tool_standard| +.. csv-table:: Compliance matrix for Table 7-1 of |tool_supplement_standard| :delim: & :header: "Item", "Description", "Ref.", "Achieved", "Notes" @@ -23,7 +23,7 @@ Compliance Matrices .. tabularcolumns:: |p{0.05\linewidth}|p{0.30\linewidth}|p{0.13\linewidth}|p{0.10\linewidth}|p{0.32\linewidth}| -.. csv-table:: Compliance matrix for Table T-8 of |tool_standard| +.. csv-table:: Compliance matrix for Table T-8 of |tool_supplement_standard| :delim: & :header: "Item", "Description", "Ref.", "Achieved", "Notes" diff --git a/qualification/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst similarity index 100% rename from qualification/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst rename to qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Methods_And_Activities/content.rst diff --git a/qualification/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst similarity index 100% rename from qualification/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst rename to qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Traceability/content.rst diff --git a/qualification/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst similarity index 100% rename from qualification/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst rename to qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/Version_Control/content.rst diff --git a/qualification/plans/Tool_Configuration_Management_Plan/Developer/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/content.rst similarity index 87% rename from qualification/plans/Tool_Configuration_Management_Plan/Developer/content.rst rename to qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/content.rst index fa78c7359..9fda75fc4 100644 --- a/qualification/plans/Tool_Configuration_Management_Plan/Developer/content.rst +++ b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/Developer/content.rst @@ -6,7 +6,7 @@ Tool Developer Configuration Management Plan GNATcoverage is a TQL-5 tool, and as such, its tool developer configuration items are managed at Control Category 2 (CC2). The corresponding subset of TCM process activities to -perform is defined by Tables 7-1 and T-8 of |tool_standard|. +perform is defined by Tables 7-1 and T-8 of |tool_supplement_standard|. This section describes the processes in place at AdaCore, the Tool Developer. diff --git a/qualification/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst similarity index 90% rename from qualification/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst rename to qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst index e7f9e1858..96d2a5833 100644 --- a/qualification/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst +++ b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/Compliance/content.rst @@ -3,7 +3,7 @@ Compliance Matrices .. tabularcolumns:: |p{0.05\linewidth}|p{0.35\linewidth}|p{0.10\linewidth}|p{0.30\linewidth}| -.. csv-table:: Compliance matrix for Table T-8 of |tool_standard| +.. csv-table:: Compliance matrix for Table T-8 of |tool_supplement_standard| :delim: | :header: "Item", "Description", "Ref.", "Notes" diff --git a/qualification/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst similarity index 92% rename from qualification/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst rename to qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst index 04b95f753..78954f1be 100644 --- a/qualification/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst +++ b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/Suggested_Items/content.rst @@ -6,7 +6,7 @@ items up to the applicant as per the compliance matrix above. * **Activity 7.2.1:** The suggested configuration items are: - #. The .zip packages of this |project_name| qualification kit; + #. The .zip packages of this |prj_toolset| qualification kit; #. The |tqa_doc| document, output of the Quality Assurance activities described in the :ref:`tqap` chapter of this document; #. The GNAT Pro and GNATcoverage binary packages containing the executable diff --git a/qualification/plans/Tool_Configuration_Management_Plan/User/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/content.rst similarity index 100% rename from qualification/plans/Tool_Configuration_Management_Plan/User/content.rst rename to qualification/qualkit/plans/Tool_Configuration_Management_Plan/User/content.rst diff --git a/qualification/plans/Tool_Configuration_Management_Plan/content.rst b/qualification/qualkit/plans/Tool_Configuration_Management_Plan/content.rst similarity index 100% rename from qualification/plans/Tool_Configuration_Management_Plan/content.rst rename to qualification/qualkit/plans/Tool_Configuration_Management_Plan/content.rst diff --git a/qualification/plans/Tool_Qualification_Plan/Certification_Credit/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Certification_Credit/content.rst similarity index 70% rename from qualification/plans/Tool_Qualification_Plan/Certification_Credit/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/Certification_Credit/content.rst index 735ebe886..5860bdb17 100644 --- a/qualification/plans/Tool_Qualification_Plan/Certification_Credit/content.rst +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Certification_Credit/content.rst @@ -4,13 +4,13 @@ Sought Certification Credit =========================== GNATcoverage aims at automating the Structural Coverage Analysis activities -required by the Software Verification Process of |standard|, in section +required by the Software Verification Process of |tool_standard|, in section 6.4.4.2 and table A-7, objectives 5, 6 and 7 depending on the software level; or Structural Coverage Analysis activities -required by the Tool Verification Process of |tool_standard|, in section +required by the Tool Verification Process of |tool_supplement_standard|, in section 6.1.4.3 and table T-7, objectives 6, 7 and 8 depending on the qualification level. Any coverage limitations are enumerated in section *Language Version and -Scope* of the |tor_doc_title| document; it is the user's responsibility to +Scope* of the |tor_abb| document; it is the user's responsibility to assure that the code subject to analysis conforms to what this qualification material encompasses. diff --git a/qualification/plans/Tool_Qualification_Plan/Compliance/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Compliance/content.rst similarity index 73% rename from qualification/plans/Tool_Qualification_Plan/Compliance/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/Compliance/content.rst index 9336a1b6f..27a2d8ff9 100644 --- a/qualification/plans/Tool_Qualification_Plan/Compliance/content.rst +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Compliance/content.rst @@ -2,12 +2,12 @@ Compliance With Guidance ======================== This section contains the compliance matrices with the guidance contained in -section 12.2 of [|standard|] (or section 4.4(e) of [|tool_standard|], as appropriate) -and section 11.3.2 of [|tool_standard|]. +section 12.2 of [|tool_standard|] (or section 4.4(e) of [|tool_supplement_standard|], as appropriate) +and section 11.3.2 of [|tool_supplement_standard|]. .. tabularcolumns:: |p{0.15\linewidth}|p{0.10\linewidth}|p{0.65\linewidth}| -.. csv-table:: Compliance with Section 12.2 of |standard| or section 4.4(e) of |tool_standard|, as appropriate +.. csv-table:: Compliance with Section 12.2 of |tool_standard| or section 4.4(e) of |tool_supplement_standard|, as appropriate :delim: # :header: "Section", "Achieved", "Notes" @@ -17,15 +17,15 @@ and section 11.3.2 of [|tool_standard|]. .. tabularcolumns:: |p{0.15\linewidth}|p{0.18\linewidth}|p{0.60\linewidth}| -.. csv-table:: Compliance with Table 11-1 of |tool_standard| +.. csv-table:: Compliance with Table 11-1 of |tool_supplement_standard| :delim: # :header: "Section", "Achieved", "Notes" - T-0, Objectives 1, 3, 6, 7 # Not applicable # Apply to Tool User, not to Tool Developer per section 11.3 of |tool_standard|. - T-0, Objective 2 # Yes # See the requirement description items in the |tor_doc| document. + T-0, Objectives 1, 3, 6, 7 # Not applicable # Apply to Tool User, not to Tool Developer per section 11.3 of |tool_supplement_standard|. + T-0, Objective 2 # Yes # See the requirement description items in the |tor_abb| document. T-0, Objective 4 # Not Applicable # Not required for TQL-5. Nevertheless, see :ref:`tqap` for AdaCore's QA procedures. - T-0, Objective 5 # Yes # See the test and test-cases description items in the |tor_doc| document. + T-0, Objective 5 # Yes # See the test and test-cases description items in the |tor_abb| document. T-1 to T-7 # Not Applicable # Not required for TQL-5. T-8 # Up to the applicant # See :ref:`user-conf-management` for suggested configuration items. T-9 # Yes # See the |tqa_doc| document accompanying this qualification package. - T-10 # Up to the applicant # Applies to Tool User, not to Tool Developer per section 11.3 of |tool_standard|. + T-10 # Up to the applicant # Applies to Tool User, not to Tool Developer per section 11.3 of |tool_supplement_standard|. diff --git a/qualification/plans/Tool_Qualification_Plan/Data_Production/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Data_Production/content.rst similarity index 87% rename from qualification/plans/Tool_Qualification_Plan/Data_Production/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/Data_Production/content.rst index a05a6e833..8544d5e91 100644 --- a/qualification/plans/Tool_Qualification_Plan/Data_Production/content.rst +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Data_Production/content.rst @@ -4,8 +4,8 @@ Production of Qualification Data For a given project, the production of qualification data proceeds in several steps described hereafter: -Settle on the |opcond_section_title| -************************************ +Settle on the Operational Conditions of Use +******************************************* As the Tool Developer, AdaCore first discusses with the Tool User to define the use @@ -13,10 +13,10 @@ that will be made of the tool, agreeing on items such as the tool interface, the source language version, the runtime profile and language features, the software level. This eventually translates as specific indications in the -|opcond_section_title_ref| section of the |tor_doc| document and in the -:ref:`qualified-interface` section of the |plans_doc| document, then |tors| -and their Tests derivatives are refined to accommodate changes in the -scope for which the tool had been qualified so far. +*Operational Conditions of Use* section of the |tor_abb| document and in the +:ref:`qualified-interface` section of the |plans_abb| document, then +Tool Operational Requirements and their Tests derivatives are refined to +accommodate changes in the scope for which the tool had been qualified so far. Produce TORs, Test Cases and Tests Artifacts ******************************************** @@ -33,7 +33,7 @@ major lines: consolidation. The general organization is described in the -|torintro_section_title_ref| of the |tor_doc| document. +*Document Purpose and Organization* of the |tor_abb| document. A TOR always comes with a Testing Strategy, to be implemented by Test Cases and eventually Tests. The TOR expresses expected behavior of the tool and the @@ -59,7 +59,7 @@ specific coverage objective purpose, for instance evaluating a decision both True and False but demonstrating independent influence of only the first condition. -Section |testproc_section_title_ref| of the |tor_doc| document +Section *Overview of the Test Procedures Organization* of the |tor_abb| document provides more details on how Tests are composed, and in particular on how expected results are stated. @@ -82,7 +82,7 @@ and runs them with provided control parameters. The tests are taken from a branch dedicated to the kit construction in AdaCore's repositories. This produces execution logs and data files that are later on gathered to -elaborate the |str_doc| report. The Qualification Team verifies at this point +elaborate the |str_abb| report. The Qualification Team verifies at this point that test results conform to expectations, making sure that the only failures, if any, are understood and registered in AdaCore's tracking system. diff --git a/qualification/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst similarity index 67% rename from qualification/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst index 841ac1fb4..5b280571f 100644 --- a/qualification/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Operational_Conditions/content.rst @@ -1,10 +1,9 @@ ============================= -|opcond_section_title| +Operational Conditions of Use ============================= Beyond the Qualified Interface, qualified use of the tool requires following a number of rules regarding the Operational Environment, the language revision, the runtime library profile and the set of language constructs used in the -programs. These rules are described in the |opcond_section_title_ref| section of -the |tor_doc| document. - +programs. These rules are described in the *Operational Conditions of Use* +section of the |tor_abb| document. diff --git a/qualification/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst similarity index 84% rename from qualification/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst index 8eb1b26c1..0a2f1d5e4 100644 --- a/qualification/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualification_Data_Overview/content.rst @@ -14,14 +14,14 @@ The qualification data that comes with the tool, composing the tool * **PDF documents package**, containing the following three documents: - * The |plans_doc_title| document, |plans_pdf|, which is this document - and which we'll refer to as the |plans_doc| document. + * The |doc_title| document, which is this document + and which we'll refer to as the |plans_abb| document. - * The |tor_doc_title| document, |tor_pdf|, which contains the description of + * The |tor_doc| document, which contains the description of the tool operational requirements together with the associated testing - strategy and test cases, and which we'll refer to as the |tor_doc| document. + strategy and test cases, and which we'll refer to as the |tor_abb| document. - The *Document Purpose and Organization* section of the |tor_doc| document + The *Document Purpose and Organization* section of the |tor_abb| document includes a high level description of our overall testing strategy. The *Overview of the test procedures organization* appendix explains how expectations on coverage results for each test are stated and used to @@ -30,14 +30,14 @@ The qualification data that comes with the tool, composing the tool The test sources aren't included in this version of the document. They are included in an HTML version, presented below. - * The |str_doc_title| report, |str_pdf|, which contains a synthetic summary + * The |str_doc| report, which contains a synthetic summary of the testsuite run performed to assess the tool behavioral correctness - with respect to its intended use, and which we'll refer to as the |str_doc| + with respect to its intended use, and which we'll refer to as the |str_abb| report. * **HTML documents package**, containing HTML versions of the PDF documents described above, presented differently and including test sources for the - |tor_doc_title| item. The tests are organized in a very hierarchical manner + |tor_doc| item. The tests are organized in a very hierarchical manner so much easier to present and browse in this format than in PDF. See the :ref:`qa-activities` section of this document for a description of which |QA| activities are performed on which document variant. @@ -51,4 +51,3 @@ The qualification data that comes with the tool, composing the tool * |tqa_doc| document, where all Quality Assurance cycles are tracked. - diff --git a/qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content_bin.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/bin_content.rst similarity index 98% rename from qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content_bin.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/bin_content.rst index 2788eafd4..ea8f13931 100644 --- a/qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content_bin.rst +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/bin_content.rst @@ -73,7 +73,7 @@ In the sample commands above: the units of interest; *or* * GPR project file facilities, as documented in the tool User's Guide and - summarized in the |tor_doc| document. + summarized in the |tor_abb| document. * is a text file containing the list of execution traces to operate on. diff --git a/qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst similarity index 93% rename from qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst index 6ceb67e22..e55200e66 100644 --- a/qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/content.rst @@ -8,7 +8,7 @@ use GNATcoverage as follows: * Build and install the coverage runtime in a dedicated directory. Use the GNAT Pro toolchain identified in the - *Operational Environment* section of the |tor_doc| document for this, + *Operational Environment* section of the |tor_abb| document for this, taking care to specify the and if the application is not a native one. @@ -20,7 +20,7 @@ use GNATcoverage as follows: This step needs only to be done once, provided that the *Operational - Environment* described in the |tor_doc| document has not changed as of + Environment* described in the |tor_abb| document has not changed as of the previous coverage runtime setup. @@ -28,7 +28,7 @@ use GNATcoverage as follows: units for coverage buffer dumping using the ``gnatcov instrument`` command; Specify the coverage criterion level to be assessed as well as a trace and as specified in the - *Operational Environment* section of the |tor_doc| document. Also specify the + *Operational Environment* section of the |tor_abb| document. Also specify the set of units of interest for which coverage should be assessed trough the arguments, which should at least include a indication using the :literal:`-P` switch: @@ -39,7 +39,7 @@ use GNATcoverage as follows: * Build the application and test executables with the GNAT Pro toolchain - identified in the *Operational Environment* section of the |tor_doc| document, + identified in the *Operational Environment* section of the |tor_abb| document, obeying the coding standard rules, and compilation switches documented there as well. The gprbuild invocation to build the application shall contain the ``--src-subdirs=gnatcov-instr`` argument on the command line, as well as a @@ -70,10 +70,10 @@ In the sample commands above: the tool; * identifies the trigger to produce execution traces, as described in the tool User's Manual, and for which the value to be used - is defined in the |tor_doc| document; + is defined in the |tor_abb| document; * identifies the medium used by the instrumented executable to output the execution traces, as described in the tool User's Manual and for - which the value to be used is defined in the |tor_doc| document; + which the value to be used is defined in the |tor_abb| document; * designates the coverage criteria to assess, depending on the software level; diff --git a/qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/src_content.rst similarity index 93% rename from qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/src_content.rst index fda785784..21b165424 100644 --- a/qualification/plans/Tool_Qualification_Plan/Qualified_Interface/content_src.rst +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Qualified_Interface/src_content.rst @@ -8,7 +8,7 @@ use GNATcoverage as follows: * Build and install the coverage runtime in a dedicated directory. Use the GNAT Pro toolchain identified in the - *Operational Environment* section of the |tor_doc| document for this, + *Operational Environment* section of the |tor_abb| document for this, taking care to specify the and if the application is not a native one. @@ -20,7 +20,7 @@ use GNATcoverage as follows: This step needs only to be done once, provided that the *Operational - Environment* described in the |tor_doc| document has not changed as of + Environment* described in the |tor_abb| document has not changed as of the previous coverage runtime setup. @@ -28,7 +28,7 @@ use GNATcoverage as follows: units for coverage buffer dumping using the ``gnatcov instrument`` command; Specify the coverage criterion level to be assessed as well as a trace and as specified in the - *Operational Environment* section of the |tor_doc| document. Also specify the + *Operational Environment* section of the |tor_abb| document. Also specify the set of units of interest for which coverage should be assessed trough the arguments, which should at least include a indication using the :literal:`-P` switch: @@ -41,7 +41,7 @@ use GNATcoverage as follows: * Build the application and test executables with the GNAT Pro toolchain - identified in the *Operational Environment* section of the |tor_doc| document, + identified in the *Operational Environment* section of the |tor_abb| document, obeying the coding standard rules, and compilation switches documented there as well. The gprbuild invocation to build the application shall contain the ``--src-subdirs=gnatcov-instr`` argument on the command line, as well as a @@ -73,10 +73,10 @@ In the sample commands above: the tool; * identifies the trigger to produce execution traces, as described in the tool User's Manual, and for which the value to be used - is defined in the |tor_doc| document; + is defined in the |tor_abb| document; * identifies the medium used by the instrumented executable to output the execution traces, as described in the tool User's Manual and for - which the value to be used is defined in the |tor_doc| document; + which the value to be used is defined in the |tor_abb| document; * designates the coverage criteria to assess, depending on the software level; diff --git a/qualification/plans/Tool_Qualification_Plan/Tool_Overview/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Tool_Overview/content.rst similarity index 100% rename from qualification/plans/Tool_Qualification_Plan/Tool_Overview/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/Tool_Overview/content.rst diff --git a/qualification/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst similarity index 74% rename from qualification/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst index f2b250968..428cf70b9 100644 --- a/qualification/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/Tool_Qualification_Level/content.rst @@ -4,7 +4,6 @@ Tool Qualification Level ======================== GNATcoverage is qualified as a COTS tool, with impact corresponding to -**Criteria 3** of |standard| section 12.2.2. From Table 12-1, the +**Criteria 3** of |tool_standard| section 12.2.2. From Table 12-1, the GNATcoverage Tool Qualification Level is then **TQL-5** for all software levels. - diff --git a/qualification/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst similarity index 100% rename from qualification/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Archiving/content.rst diff --git a/qualification/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst similarity index 70% rename from qualification/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst index d623b53f7..098c747d4 100644 --- a/qualification/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Qualification/content.rst @@ -1,18 +1,18 @@ -|project_name| Qualification +|prj_toolset| Qualification ============================ -#. **Reference** |project_name_bold| **in the Plan for Software Aspects of +#. **Reference** |prj_toolset_bold| **in the Plan for Software Aspects of Certification (PSAC) and, if appropriate, in Tool Qualification Plan**. The user needs to: - * identify |project_name| as a TQL-5 tool with regard to software level + * identify |prj_toolset| as a TQL-5 tool with regard to software level A, B, and C, or with regard to tool qualification level 1, 2, and 3, whichever is appropriate, that needs to be qualified; - * Include references to the |project_name| qualification kit documents that + * Include references to the |prj_toolset| qualification kit documents that were received to support this particular use of the tool. -#. **Delivery Acceptance.** On delivery of |project_name| and its +#. **Delivery Acceptance.** On delivery of |prj_toolset| and its qualification kit, the user shall: * Assess whether the qualified Operational Environment is @@ -30,18 +30,18 @@ all qualification data under configuration management. #. **Obtain a tool qualification agreement**, see section 9.0.b of - |tool_standard|. + |tool_supplement_standard|. #. **Update the Software or Tool Life Cycle Environment Configuration Index.** - Refer to the |project_name| qualification kit for details associated with + Refer to the |prj_toolset| qualification kit for details associated with its environment configuration. #. **Update the Software or Tool Accomplishment Summary (SAS or TAS).** The SAS/TAS needs to be updated: - * For Table A-7 of |standard|: achievement of the objectives 5, 6 and 7, - depending on the software level; or for Table T-7 of |tool_standard|: + * For Table A-7 of |tool_standard|: achievement of the objectives 5, 6 and 7, + depending on the software level; or for Table T-7 of |tool_supplement_standard|: achievement of the objectives 6, 7 and 8, depending on the qualification level (as appropriate). - * For qualification status of |project_name|: refer to |str_doc| report. + * For qualification status of |prj_toolset|: refer to |str_abb| report. diff --git a/qualification/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst similarity index 65% rename from qualification/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst index b74d75506..19f5dd53b 100644 --- a/qualification/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/Usage/content.rst @@ -1,13 +1,13 @@ -|project_name| Usage +|prj_toolset| Usage ==================== #. **Install the tool in the Operational Environment.** The user needs to install the tool in an Operational Environment deemed equivalent - to the one prescribed by the |opcond_section_title_ref| chapter of - the |tor_doc| document (*Operational Environment* section, item e1). + to the one prescribed by the *Operational Conditions of Use* chapter of + the |tor_abb| document (*Operational Environment* section, item e1). #. **Check correct usage of the tool.** For the tool results to be used in a certification context, users must comply with the interface presented in the :ref:`qualified-interface` section of this document, as well as with the rules and scope prescribed by - the |opcond_section_title_ref| chapter of the |tor_doc| document. + the *Operational Conditions of Use* chapter of the |tor_abb| document. diff --git a/qualification/plans/Tool_Qualification_Plan/User_Activities/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/content.rst similarity index 73% rename from qualification/plans/Tool_Qualification_Plan/User_Activities/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/content.rst index 178808255..13864b621 100644 --- a/qualification/plans/Tool_Qualification_Plan/User_Activities/content.rst +++ b/qualification/qualkit/plans/Tool_Qualification_Plan/User_Activities/content.rst @@ -3,7 +3,7 @@ User Activities =============== -To finalize the qualification of |project_name|, the Tool User needs to +To finalize the qualification of |prj_toolset|, the Tool User needs to perform a set of activities, described hereafter: .. toctree:: diff --git a/qualification/plans/Tool_Qualification_Plan/content.rst b/qualification/qualkit/plans/Tool_Qualification_Plan/content.rst similarity index 100% rename from qualification/plans/Tool_Qualification_Plan/content.rst rename to qualification/qualkit/plans/Tool_Qualification_Plan/content.rst diff --git a/qualification/plans/Tool_Quality_Assurance_Plan/Activities/content.rst b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Activities/content.rst similarity index 88% rename from qualification/plans/Tool_Quality_Assurance_Plan/Activities/content.rst rename to qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Activities/content.rst index 09cccdb57..7e48c8b89 100644 --- a/qualification/plans/Tool_Quality_Assurance_Plan/Activities/content.rst +++ b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Activities/content.rst @@ -13,7 +13,7 @@ described here are performed on the PDF version of the documents. Only those steps requiring access to test sources are performed with the help of the HTML contents. -Reading the |plans_doc| document +Reading the |plans_abb| document ******************************** **Objectives:** @@ -39,7 +39,7 @@ two. Each metric family is further divided into groups and possibly subgroups, as needed. This is all summarized in the *Document Purpose and Organization* chapter of -the |tor_doc| document, section *Organization Guidelines*, which the |QA| +the |tor_abb| document, section *Organization Guidelines*, which the |QA| reviewer reads first. The reviewer then selects a set of requirements for review and this set is @@ -60,7 +60,7 @@ also documented in the |QA| report. To help understanding the tests performed for a test case, the reviewer first gets acquainted with the *Overview of the test Procedures Organization* -appendix of the |tor_doc| document, where we describe the specific syntax we +appendix of the |tor_abb| document, where we describe the specific syntax we use to state expected coverage results. Inspection of test execution results @@ -68,7 +68,7 @@ Inspection of test execution results **Objectives:** - * Check that the Verification Environment reported in the |str_doc| report + * Check that the Verification Environment reported in the |str_abb| report is equivalent to the Operational Environment described in the |tor_doc| document. @@ -78,14 +78,13 @@ Inspection of test execution results source of error is: * A misbehavior of the infrastructure used to run tests and compare actual - results to expected results: in this case, the |project_name| + results to expected results: in this case, the |prj_toolset| Qualification Team is in charge of reporting and fixing the problem. - * A bug in the |project_name| implementation: in this case, the - |project_name| Development Team is in charge of reporting and fixing the + * A bug in the |prj_toolset| implementation: in this case, the + |prj_toolset| Development Team is in charge of reporting and fixing the problem. - * A reasonable limitation of the tool: in this case, the |project_name| + * A reasonable limitation of the tool: in this case, the |prj_toolset| Qualification Team is in charge of reporting and justifying the problem as part of the known limitations of the tool. - diff --git a/qualification/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst similarity index 76% rename from qualification/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst rename to qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst index a7435574a..0d0ff47c3 100644 --- a/qualification/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst +++ b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Compliance/content.rst @@ -1,15 +1,14 @@ Compliance With Guidance ======================== -|project_name| is qualified as a TQL-5 tool. +|prj_toolset| is qualified as a TQL-5 tool. .. tabularcolumns:: |p{0.05\linewidth}|p{0.20\linewidth}|p{0.15\linewidth}|p{0.45\linewidth}| -.. csv-table:: Compliance matrix for Table T-9 of |tool_standard| +.. csv-table:: Compliance matrix for Table T-9 of |tool_supplement_standard| :delim: & :header: "Item", "Ref.", "Achieved", "Notes" 1,3,4 & 8.1.a,b,c & Not applicable & Not required for TQL-5 tools 2 & 8.1.b & Yes & See :ref:`qa-activities` 5 & 8.1.d & Yes & See :ref:`tool-conformity-review` - diff --git a/qualification/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst similarity index 87% rename from qualification/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst rename to qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst index ae8f5897f..1302e2509 100644 --- a/qualification/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst +++ b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Conformity_Review/content.rst @@ -14,13 +14,12 @@ These objectives are achieved in the scope of the tool conformity review: the :ref:`tcmp`. * **8.3.d**: Record and approve software requirements deviations arising from two sources: (1) deviations exposed by test failures reported in the - |project_name| |str_doc| provided as part of the tool qualification data; + |prj_toolset| |str_doc| provided as part of the tool qualification data; and (2) deviations due to issues recorded in the known-problems - file maintained by |adacore| for a given release of |project_name|. + file maintained by |adacore| for a given release of |prj_toolset|. * **8.3.e**: Check that the tool executable object code can be re-generated from the tool source code. * **8.3.f**: Check that problems from a previous Tool Conformity Review are re-evaluated. * **8.3.g**: Not applicable since no credit is sought for the use of previously developed tools. - diff --git a/qualification/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst similarity index 92% rename from qualification/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst rename to qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst index 7b69d4b73..4add34a34 100644 --- a/qualification/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst +++ b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/Cycles/content.rst @@ -7,7 +7,9 @@ Each |QA| cycle consists of the following iterations: submitted for review into the ``qa`` area. The **Quality Assurance Team** is then notified. -:raw-latex:`\begin{minipage}{\linewidth}` +.. raw:: latex + + \begin{minipage}{\linewidth} * The **Quality Assurance Team** identifies defects in the documents. For each defect the **Quality Assurance Team** enters in the report a unique *defect @@ -21,9 +23,10 @@ Each |QA| cycle consists of the following iterations: **Qualification Team** is notified when the review is complete. -:raw-latex:`\end{minipage}` - -:raw-latex:`\begin{minipage}{\linewidth}` +.. raw:: latex + + \end{minipage} + \begin{minipage}{\linewidth} * The **Qualification Team** reviews each defect, and either Accepts or Rejects it. @@ -31,7 +34,9 @@ Each |QA| cycle consists of the following iterations: * If a defect is **Accepted**: *Corrective Action* is described and applied. * If a defect is **Rejected**: *Reason* is provided. -:raw-latex:`\end{minipage}` +.. raw:: latex + + \end{minipage} * If any defects have been **Accepted** and *Corrective Actions* applied: new version of the document(s) is generated and added to the ``qa`` area. @@ -49,4 +54,3 @@ Each |QA| cycle consists of the following iterations: its proper application has then been verified) if defect is **Accepted**. * The documents are then deemed ready for release. - diff --git a/qualification/plans/Tool_Quality_Assurance_Plan/content.rst b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/content.rst similarity index 89% rename from qualification/plans/Tool_Quality_Assurance_Plan/content.rst rename to qualification/qualkit/plans/Tool_Quality_Assurance_Plan/content.rst index 2bb49f112..641095096 100644 --- a/qualification/plans/Tool_Quality_Assurance_Plan/content.rst +++ b/qualification/qualkit/plans/Tool_Quality_Assurance_Plan/content.rst @@ -4,7 +4,7 @@ Tool Quality Assurance Plan =========================== -|project_name| |QA| (QA) proceeds in cycles of activities. +|prj_toolset| |QA| (QA) proceeds in cycles of activities. The QA outputs for a kit are stored in a "qa" directory dedicated to the project for which the kit is produced. The most significant output is the diff --git a/qualification/qualkit/plans/document_settings.yaml b/qualification/qualkit/plans/document_settings.yaml new file mode 100644 index 000000000..058036f4d --- /dev/null +++ b/qualification/qualkit/plans/document_settings.yaml @@ -0,0 +1,21 @@ +document: + subst: + doc_title: *prj_doc_plans + # USER_ENTRIES + doc_short_title: 'PLANS' + doc_hdr_title: *prj_doc_plans + doc_version: '1' + doc_status: 'DRAFT' + doc_id: *prj_docid_plans + + assignments: + authors: [*prj_assignment_wri] + project_manager: [*prj_assignment_pm] + verifier: [*prj_assignment_ver] + + history: + - version: 1 + date: today + comments: Initial version + + # END_OF_USER_ENTRIES diff --git a/qualification/plans/index.rst b/qualification/qualkit/plans/plans.rst similarity index 87% rename from qualification/plans/index.rst rename to qualification/qualkit/plans/plans.rst index 8366db2e1..7d9c1842c 100644 --- a/qualification/plans/index.rst +++ b/qualification/qualkit/plans/plans.rst @@ -1,5 +1,5 @@ =================================================================== -GNATcoverage - |standard| Qualification Material: |plans_doc_title| +GNATcoverage - |tool_standard| Qualification Material: |doc_title| =================================================================== .. rubric:: Revision History diff --git a/qualification/scripts/__init__.py b/qualification/qualkit/scripts/__init__.py similarity index 100% rename from qualification/scripts/__init__.py rename to qualification/qualkit/scripts/__init__.py diff --git a/qualification/scripts/logger.py b/qualification/qualkit/scripts/logger.py similarity index 93% rename from qualification/scripts/logger.py rename to qualification/qualkit/scripts/logger.py index fbe006c98..621cb37b0 100644 --- a/qualification/scripts/logger.py +++ b/qualification/qualkit/scripts/logger.py @@ -20,8 +20,10 @@ """Module providing a message logger""" from enum import Enum +from functools import total_ordering +@total_ordering class Log_Level_Kind(Enum): DEBUG = 1 VERBOSE = 2 @@ -29,6 +31,11 @@ class Log_Level_Kind(Enum): WARNING = 4 ERROR = 5 + def __lt__(self, other): + if self.__class__ is other.__class__: + return self.value < other.value + return NotImplementedError + current_level = Log_Level_Kind.VERBOSE diff --git a/qualification/scripts/qm_plugins/__init__.py b/qualification/qualkit/scripts/qm_plugins/__init__.py similarity index 100% rename from qualification/scripts/qm_plugins/__init__.py rename to qualification/qualkit/scripts/qm_plugins/__init__.py diff --git a/qualification/scripts/qm_plugins/importers.py b/qualification/qualkit/scripts/qm_plugins/importers.py similarity index 99% rename from qualification/scripts/qm_plugins/importers.py rename to qualification/qualkit/scripts/qm_plugins/importers.py index 40784e225..9a721e232 100644 --- a/qualification/scripts/qm_plugins/importers.py +++ b/qualification/qualkit/scripts/qm_plugins/importers.py @@ -588,7 +588,7 @@ def to_rest(self, artifact): reference = ".. _%s:\n\n" % artifact.docfile(True) reference += writer.raw( - "\\label{%s::doc}" % artifact.docfile(True), "latex" + "\\label{tor/source/%s::doc}" % artifact.docfile(True), "latex" ) result = "" qmlink = "" @@ -763,8 +763,8 @@ def log_missing_TR(self, artifact): has_TR = False - for child in artifact.relatives: - has_TR = is_test_result(child) + for child in artifact.files: + has_TR = "tcs.dump" in child if has_TR: break @@ -798,7 +798,7 @@ def to_rest(self, artifact): reference = "\n\n.. _%s:\n" % artifact.docfile(True) reference += writer.raw( - "\\label{%s::doc}" % artifact.docfile(True), "latex" + "\\label{tor/source/%s::doc}" % artifact.docfile(True), "latex" ) result_pdf = "**TEST CASE**: %s\n\n" % artifact.id diff --git a/qualification/scripts/qm_plugins/link_lrm.py b/qualification/qualkit/scripts/qm_plugins/link_lrm.py similarity index 100% rename from qualification/scripts/qm_plugins/link_lrm.py rename to qualification/qualkit/scripts/qm_plugins/link_lrm.py diff --git a/qualification/scripts/qm_plugins/lrm_index_parser.py b/qualification/qualkit/scripts/qm_plugins/lrm_index_parser.py similarity index 100% rename from qualification/scripts/qm_plugins/lrm_index_parser.py rename to qualification/qualkit/scripts/qm_plugins/lrm_index_parser.py diff --git a/qualification/scripts/rest/__init__.py b/qualification/qualkit/scripts/rest/__init__.py similarity index 100% rename from qualification/scripts/rest/__init__.py rename to qualification/qualkit/scripts/rest/__init__.py diff --git a/qualification/scripts/rest/writer.py b/qualification/qualkit/scripts/rest/writer.py similarity index 100% rename from qualification/scripts/rest/writer.py rename to qualification/qualkit/scripts/rest/writer.py diff --git a/qualification/qualkit/str/Makefile b/qualification/qualkit/str/Makefile new file mode 100644 index 000000000..2090b7862 --- /dev/null +++ b/qualification/qualkit/str/Makefile @@ -0,0 +1,4 @@ +DOC=str +MASTER_DOC=source/content +TOOL?=$(realpath ../) +include ../../Makefile.common diff --git a/qualification/qualkit/str/document_settings.yaml b/qualification/qualkit/str/document_settings.yaml new file mode 100644 index 000000000..9b9094cca --- /dev/null +++ b/qualification/qualkit/str/document_settings.yaml @@ -0,0 +1,21 @@ +document: + subst: + doc_title: *prj_doc_str + # USER_ENTRIES + doc_short_title: 'STR' + doc_hdr_title: *prj_doc_str + doc_version: '1' + doc_status: 'DRAFT' + doc_id: *prj_docid_str + + assignments: + authors: [*prj_assignment_wri] + project_manager: [*prj_assignment_pm] + verifier: [*prj_assignment_ver] + + history: + - version: 1 + date: today + comments: Initial version + + # END_OF_USER_ENTRIES diff --git a/qualification/qualkit/tor/Makefile b/qualification/qualkit/tor/Makefile new file mode 100644 index 000000000..3d212a0f1 --- /dev/null +++ b/qualification/qualkit/tor/Makefile @@ -0,0 +1,4 @@ +DOC=tor +MASTER_DOC=source/index +TOOL?=$(realpath ../) +include ../../Makefile.common diff --git a/qualification/tor/__init__.py b/qualification/qualkit/tor/__init__.py similarity index 100% rename from qualification/tor/__init__.py rename to qualification/qualkit/tor/__init__.py diff --git a/qualification/qualkit/tor/document_settings.yaml b/qualification/qualkit/tor/document_settings.yaml new file mode 100644 index 000000000..c660ebced --- /dev/null +++ b/qualification/qualkit/tor/document_settings.yaml @@ -0,0 +1,21 @@ +document: + subst: + doc_title: *prj_doc_tor + # USER_ENTRIES + doc_short_title: 'TOR' + doc_hdr_title: 'Tool Operational Requirements' + doc_version: '1' + doc_status: 'DRAFT' + doc_id: *prj_docid_tor + + assignments: + authors: [*prj_assignment_wri] + project_manager: [*prj_assignment_pm] + verifier: [*prj_assignment_ver] + + history: + - version: 1 + date: today + comments: Initial version + + # END_OF_USER_ENTRIES diff --git a/qualification/tor/genrest.py b/qualification/qualkit/tor/genrest.py similarity index 96% rename from qualification/tor/genrest.py rename to qualification/qualkit/tor/genrest.py index 99f828428..1157cd992 100755 --- a/qualification/tor/genrest.py +++ b/qualification/qualkit/tor/genrest.py @@ -16,10 +16,10 @@ from scripts.qm_plugins.importers import ( resolve_importer, default_importer, + is_req_or_set, + is_tc_or_set, ) from itertools import zip_longest -from scripts.common_conf import tor_doc_id -from tor.proj_conf import get_var_replacements from typing import Callable, Dict, List, Set, Optional, Sequence, Any, IO @@ -81,7 +81,7 @@ # The root of the directory where the REST documents describing # these artifacts will reside: -ART_ROOTDIR = "../../testsuite/Qualif" +ART_ROOTDIR = "../../../testsuite/Qualif" # Prefix artifact ID with this string @@ -99,27 +99,11 @@ warn_stats: Dict[str, int] = {} -# replacements for variables in rst text -# the dictionary is filled by DocGenerator.generate_all before -# doing any other transpormations -VAR_REPLACEMENTS: Dict[str, str] = {} - # ********************** # ** Helper functions ** # ********************** -def replace_variables(content_text: str) -> str: - """Replace variables enclosed between | symbols.""" - - for rst_var in VAR_REPLACEMENTS: - content_text = re.sub( - r"\|%s\|" % rst_var, VAR_REPLACEMENTS[rst_var], content_text - ) - - return content_text - - def get_content(filename: str) -> str: """Return contents of file FILENAME as a string""" @@ -153,15 +137,14 @@ def subsec_header(text: str) -> str: def info(text: str): - if verbose: - print("info: %s" % text) + logger.log_info(text) def warn(text: str, msg_type: str = ""): if not msg_type or not any( re.match(pattern, msg_type) for pattern in SUPRESS_MSG_TYPES ): - print("warning: %s" % text) + logger.log_warning(text) if msg_type: if msg_type in warn_stats: @@ -177,23 +160,23 @@ def warn_if(cond: bool, text: str, msg_type: str = ""): def exit_if(p: bool, msg: str): if p: - print(msg) + logger.log_error(msg) sys.exit(1) def err(text: str): - print("error: %s" % text) + logger.log_error(text) sys.exit(1) def print_warn_stats(): for key in warn_stats: - print("%s: %d" % (key, warn_stats[key])) + logger.log_info("%s: %d" % (key, warn_stats[key])) def err_if(p: bool, text: str): if p: - print("error: %s" % text) + logger.log_error(text) sys.exit(1) @@ -582,6 +565,7 @@ def __init__( subdirs: List[str], files: List[str], parent: Optional[Dir], + art_root: str, ): # Filesystem attributes for this directory @@ -606,12 +590,12 @@ def to_id(name: str) -> str: self.id = ( "/" + ART_ID_PREFIX - + to_id(self.root[len(os.path.abspath(ART_ROOTDIR)) :]) + + to_id(self.root[len(os.path.abspath(art_root)) :]) ) # If we are at the root directory then return our documentation # entry point. - if os.path.relpath(self.root, ART_ROOTDIR) == ".": + if os.path.relpath(self.root, art_root) == ".": # predefined name of the root document self._docfile_base_ = "index" else: @@ -912,7 +896,7 @@ def rest_doc_ref(self: Dir, id_as_title: bool = False) -> str: return writer.qmref( self.docfile(True), - replace_variables(self.title()) if not id_as_title else self.id, + self.title() if not id_as_title else self.id, ) @property @@ -940,11 +924,17 @@ def full_id(self: Dir) -> str: @property def parent_ref(self: Dir) -> str: - """Return link to the parent object. + """Return link to the parent object, if self's parent is a + requirement(set) or testcase(set) Include artifact type when parent is requirement. """ - if self.pdo: + if self.pdo and ( + is_req_or_set(self.pdo) + or is_tc_or_set(self.pdo) + or self.pdo.tcgroup + or self.pdo.reqgroup + ): return ( "**Parent" + ((" " + self.pdo.kind.txthdl) if self.pdo.req else "") @@ -1274,7 +1264,7 @@ def check_consistency(self: DirTree): class DirTree_FromPath(DirTree): - def __init__(self: DirTree_FromPath, rootp: str): + def __init__(self: DirTree_FromPath, rootp: str, dolevel: str): DirTree.__init__(self, roots=[]) # First compute the tree of directory objects starting at path ROOTP, @@ -1282,6 +1272,9 @@ def __init__(self: DirTree_FromPath, rootp: str): # children. This is achieved by performing a top down walk of the os # directory structure. + self.dolevel = dolevel + self.root = rootp + self.dir = {} # dir-name -> dir-object dictionary [ self.topdown_map(dirname, subdirs, files) @@ -1309,6 +1302,9 @@ def topdown_map( # we have mapped the parent directory already if there is one. # Ignore some subdirectories + excluded_levels = {"doA", "doB", "doC"} + excluded_levels.remove(self.dolevel) + for d in subdirs.copy(): if ( d in (".svn", "mylib", "App", "__pycache__") @@ -1319,6 +1315,7 @@ def topdown_map( or d.startswith("d_") or d.startswith("m_") or d.startswith("u_") + or d in excluded_levels or os.path.exists(os.path.join(dirname, d, ".tor_ignore")) ): subdirs.remove(d) @@ -1335,7 +1332,13 @@ def topdown_map( # Map a new object for this dir ... - diro = Dir(root=dirname, subdirs=subdirs, files=files, parent=parento) + diro = Dir( + root=dirname, + subdirs=subdirs, + files=files, + parent=parento, + art_root=self.root, + ) self.dir[dirname] = diro @@ -1455,6 +1458,7 @@ def __init__( # Root of the directory tree where the qualification artifacts # are to be found: self.art_rootdir = os.path.abspath(art_rootdir) + logger.log_debug(f"Root testsuite dir: {self.art_rootdir}") # Root of the directory tree where the generated document sources # are to be produced: @@ -1535,7 +1539,6 @@ def contents_from(self: DocGenerator, diro: Dir) -> str: # res = diro.to_rest() # else: res = importer.to_rest(diro) - res = replace_variables(res) res = self.process_qmlink(diro, res) return res @@ -1707,7 +1710,9 @@ def restore_extension(name: str) -> str: def art_dirtree_for( self: DocGenerator, chapdirs: List[str] ) -> DirTree_FromPath: - dirtree = DirTree_FromPath(rootp=self.art_rootdir) + dirtree = DirTree_FromPath( + rootp=self.art_rootdir, dolevel=self.o.dolevel + ) dirtree.rprune( [os.path.join(self.art_rootdir, dirname) for dirname in chapdirs] @@ -1817,10 +1822,6 @@ def generate_all(self: DocGenerator): ) ) - VAR_REPLACEMENTS.update( - get_var_replacements(do_level=self.o.dolevel, doc_id=tor_doc_id) - ) - self.art_dirtree = self.art_dirtree_for(this_subdirs) self.generate_chapters() @@ -1868,6 +1869,14 @@ def generate_all(self: DocGenerator): default=False, help=("Show detailed info messages"), ) + + op.add_option( + "--testsuite-dir", + dest="testsuite_dir", + default=None, + help="Root directory of the qualification testsuite", + ) + (options, args) = op.parse_args() exit_if( @@ -1882,9 +1891,20 @@ def generate_all(self: DocGenerator): ) verbose = options.verbose + logger.current_level = ( + logger.Log_Level_Kind.DEBUG + if verbose + else logger.Log_Level_Kind.WARNING + ) + + actual_root_dir = ( + options.testsuite_dir if options.testsuite_dir else ART_ROOTDIR + ) + if not actual_root_dir.endswith("Qualif"): + actual_root_dir = os.path.join(actual_root_dir, "Qualif") mygen = DocGenerator( - art_rootdir=ART_ROOTDIR, rst_rootdir=RST_ROOTDIR, options=options + art_rootdir=actual_root_dir, rst_rootdir=RST_ROOTDIR, options=options ) mygen.generate_all() diff --git a/qualification/tor/genrest_conf.py b/qualification/qualkit/tor/genrest_conf.py similarity index 100% rename from qualification/tor/genrest_conf.py rename to qualification/qualkit/tor/genrest_conf.py diff --git a/qualification/scripts/common_conf.py b/qualification/scripts/common_conf.py deleted file mode 100644 index 0bf747e22..000000000 --- a/qualification/scripts/common_conf.py +++ /dev/null @@ -1,168 +0,0 @@ -from collections import OrderedDict -from datetime import date - -project_name = "GNATcoverage" -project_name_it = "*%s*" % project_name -owner = "AdaCore" - -users = { - "unassigned": { - "name": "Unassigned", - "company": "", - "email": "", - "team": "", - }, - "hainque": { - "name": "Olivier Hainque", - "company": owner, - "email": "hainque@adacore.com", - "team": "Qualification", - }, - "guitton": { - "name": "Jerome Guitton", - "company": owner, - "email": "guitton@adacore.com", - "team": "Qualification", - }, - "leguillou": { - "name": "Erwan Leguillou", - "company": owner, - "email": "leguillou@adacore.com", - "team": "Qualification", - }, - "fofanov": { - "name": "Vasily Fofanov", - "company": owner, - "email": "fofanov@adacore.com", - "team": "Qualification", - }, -} - -roles = OrderedDict( - [ - ("authors", {"description": "the authors of the document"}), - ] -) - -assignments = {"authors": ["hainque"]} - -release = "DRAFT 0.0" -version = "(version %s)" % release - -copyright = "%s, %d" % (owner, date.today().year) # noqa: A001 - -extensions = ["sphinx.ext.ifconfig"] - -# Parameters - which could be templated and instantiated -# from parameters known at higher levels of the kit production -# process: - -tor_doc_id = "PE." -str_doc_id = "PE." -plans_doc_id = "PE." - -gnatpro_version = "GNATPRO.X" -gprbuild_version = "GPRBUILD.Y" -gnatcov_version = "GNATCOV.Z" - -opcond_section_title = "Operational Conditions of Use" -torintro_section_title = "Document Purpose and Organization" -testproc_section_title = "Overview of the Test Procedures Organization" - -VAR_REPLACEMENTS = { - "project_name": project_name, - "project_name_bold": "**%s**" % project_name, - "project_name_it": "*%s*" % project_name, - "current_version": version, - "project_command": "``gnatcov``", - "adacore": "AdaCore", - "gnatpro": "GNAT Pro", - "gnatpro_it": "*GNAT Pro*", - "gnatpro_bold": "**GNAT Pro**", - "Ada83": "`Ada 83`", - "Ada95": "`Ada 95`", - "Ada05": "`Ada 2005`", - "Ada12": "`Ada 2012`", - "Ada22": "`Ada 2022`", - "QA": "Quality Assurance", - "plans_pdf": r"``PLANS.pdf``", - "tor_pdf": r"``TOR.pdf``", - "str_pdf": r"``STR.pdf``", - "tqa_file": r"``qa.doc``", - "tors": r"Tool Operational Requirements", - "plans_doc_title": r"*Qualification Plans*", - "tor_doc_title": ( - r"*Tool Operational Requirements and V&V Cases and Procedures*" - ), - "str_doc_title": r"*Tool Operational Verification and Validation Results*", - "tqa_doc_title": r"*Tool Quality Assurance Records*", - "plans_doc": r"*PLANS*", - "tor_doc": r"*TOR*", - "str_doc": r"*STR*", - "tqa_doc": "|tqa_doc_title|", - "plans_doc_id": r"*" + plans_doc_id + r"*", - "tor_doc_id": r"*" + tor_doc_id + r"*", - "str_doc_id": r"*" + str_doc_id + r"*", - "gnatcov_version": r"%s" % gnatcov_version, - "gnatpro_version": r"%s" % gnatpro_version, - "gprbuild_version": r"%s" % gprbuild_version, - "opcond_section_title": r"%s" % opcond_section_title, - "opcond_section_title_ref": r"*%s*" % opcond_section_title, - "torintro_section_title": r"%s" % torintro_section_title, - "torintro_section_title_ref": r"*%s*" % torintro_section_title, - "testproc_section_title": r"%s" % testproc_section_title, - "testproc_section_title_ref": r"*%s*" % testproc_section_title, - "DAL": "Design Assurance Level", - "PSAC": "Plan for Software Aspects of Certification", - "PSAC_bold": "**Plan for Software Aspects of Certification**", - "V&V": "Verification and Validation", - "ARM": "Ada Reference Manual", - "standard": "DO-178C/ED-12C", - "tool_standard": "DO-330/ED-215", - "client": "`GENERIC CLIENT`", - "current_authors": ( - owner - if not assignments - else ", ".join([name.capitalize() for name in assignments["authors"]]) - ), - "release": release, - "version": version, -} - -rst_prolog = """ -.. |LF| raw:: latex - - \\\\ - -.. |newline| raw:: latex - - \\newline - - - -.. |nbsp| raw:: latex - - ~ - - - -.. |pagebreak| raw:: latex - - \\newpage - -.. role:: raw-latex(raw) - :format: latex - -:raw-latex:`\\renewcommand{\\labelitemi}{$\\bullet$}` -:raw-latex:`\\renewcommand{\\labelitemii}{$\\circ$}` -:raw-latex:`\\renewcommand{\\labelitemiii}{$\\cdots$}` -:raw-latex:`\\renewcommand{\\labelitemiv}{$-$}` - -.. role:: raw-html(raw) - :format: html -""" + "\n\n".join( - [ - f".. |{key}| replace:: {VAR_REPLACEMENTS[key]}" - for key in VAR_REPLACEMENTS - ] -) diff --git a/qualification/tor/Makefile b/qualification/tor/Makefile deleted file mode 100644 index 34b8c9e07..000000000 --- a/qualification/tor/Makefile +++ /dev/null @@ -1,130 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -c . -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = build - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) source - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest - -help: - @echo "Please use \`make ' where is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - -rm -rf $(BUILDDIR)/* source/*.rst - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Couverture.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Couverture.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/Couverture" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Couverture" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latexpdf - @echo "Running LaTeX files through pdflatex..." - make -C $(BUILDDIR)/latexpdf all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." diff --git a/qualification/tor/conf.py b/qualification/tor/conf.py deleted file mode 100644 index 01bc88781..000000000 --- a/qualification/tor/conf.py +++ /dev/null @@ -1,195 +0,0 @@ -############################################################################ -# # -# The Qualifying Machine (QM) # -# # -# Copyright (C) 2010-2014, AdaCore # -# # -# The QM 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. The QM 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 the QM; see file COPYING3. If # -# not, write to the Free Software Foundation, 59 Temple Place - Suite # -# 330, Boston, MA 02111-1307, USA. # -# # -############################################################################ - - -from collections import OrderedDict -from scripts.common_conf import ( - version, - project_name, - owner, - users, - assignments, - tor_doc_id, - rst_prolog, - VAR_REPLACEMENTS, -) - -doc_id = tor_doc_id - -extensions = [] -papersize = "a4paper" -latex_show_pagerefs = True -html_sidebars = {"**": ["localtoc.html", "sourcelink.html", "searchbox.html"]} -latex_use_parts = False -toc_depth = 2 - -# roles definition -# ??? This is standard-specific and should not be defined here. -roles = OrderedDict( - [ - ("authors", {"description": "the authors of the document"}), - ("reviewers", {"description": "the reviewers of the document"}), - ("approvers", {"description": "the approvers of the document"}), - ] -) - -# Do some checks -assert rst_prolog is not None, "rst_prolog should be set in common_conf.py" - -templates_path = ["_templates"] - -# These parameters cannot be overriden so just force their value after -# reading user conf file -master_doc = "index" - -source_suffix = ".rst" -project = project_name -exclude_patterns = ["_build"] -pygments_style = "sphinx" -html_theme = "classic" -html_theme_path = ["."] -html_theme_options = {"body_max_width": None} - - -PAGE_BLANK = r""" -\makeatletter -\def\cleartooddpage{%% - \cleardoublepage%% -} -\def\cleardoublepage{%% -\clearpage%% - \if@twoside%% - \ifodd\c@page%% - %% nothing to do - \else%% - \hbox{}%% - \thispagestyle{plain}%% - \vspace*{\fill}%% - \begin{center}%% - \textbf{\em This page is intentionally left blank.}%% - \end{center}%% - \vspace{\fill}%% - \newpage%% - \if@twocolumn%% - \hbox{}%% - \newpage%% - \fi%% - \fi%% - \fi%% -} -\makeatother -""" - -TOC_DEPTH = ( - r""" -\pagenumbering{arabic} -\setcounter{tocdepth}{%d} -""" - % toc_depth -) - -TOC_CMD = r""" -\makeatletter -\def\tableofcontents{%% - \pagestyle{plain}%% - \chapter*{\contentsname}%% - \@mkboth{\MakeUppercase{\contentsname}}%% - {\MakeUppercase{\contentsname}}%% - \@starttoc{toc}%% -} -\makeatother -""" - - -def latex_hyphen(): - return "\n".join([r"\hyphenpenalty=5000", r"\tolerance=1000"]) - - -def project_settings(): - - HLINE = r"\hline" - HEADERS = r"Name & Company & Team & Email \\" - assignment_tab = [] - - for role in filter(lambda x: x in assignments, roles.keys()): - title = ( - r"\multicolumn{4}{l}{\large \par} \\" - r" \multicolumn{4}{l}{\large %s \par} \\" % (role.capitalize()) - ) - - assignment_tab.append(title) - assignment_tab.append(HLINE) - assignment_tab.append(HEADERS) - assignment_tab.append(HLINE) - - for login in assignments[role]: - user = users[login] - assignment_tab.append( - r"%s & %s & %s & %s \\" - % (user["name"], user["company"], user["team"], user["email"]) - ) - - assignment_tab.append(HLINE) - - full_document_name = project_name - if doc_id is not None and len(doc_id) > 0: - full_document_name = "%s - %s" % (project_name, doc_id) - - return "\n".join( - [ - r"\newcommand*{\QMFullDocumentName}[0]{" - + full_document_name - + r"}", - r"\newcommand*{\QMProjectName}[0]{" + project_name + r"}", - r"\newcommand*{\QMDocID}[0]{" + doc_id + r"}", - r"\newcommand*{\QMVersion}[0]{" + version + r"}", - r"\newcommand*{\QMTabUsers}[0]{" - + "\n".join(assignment_tab) - + r"}", - ] - ) - - -TOC = r""" -\cleardoublepage -\tableofcontents -\cleardoublepage\pagestyle{plain} -""" - -latex_elements = { - "preamble": TOC_DEPTH - + PAGE_BLANK - + TOC_CMD - + latex_hyphen() - + "\n" - + project_settings(), - "tableofcontents": TOC, - "papersize": papersize, -} - -latex_documents = [ - ( - "index", - "TOR.tex", - f"GNATcoverage DO-178C/ED-12C Qualification Material: " - f"{VAR_REPLACEMENTS["plans_doc_title"]}", - owner, - "manual", - ), -] diff --git a/qualification/tor/proj_conf.py b/qualification/tor/proj_conf.py deleted file mode 100644 index ccfe5d97e..000000000 --- a/qualification/tor/proj_conf.py +++ /dev/null @@ -1,8 +0,0 @@ -from typing import Dict -from scripts.common_conf import VAR_REPLACEMENTS - - -def get_var_replacements(do_level: str, doc_id: str) -> Dict[str, str]: - """Return var replacements for the given project""" - - return VAR_REPLACEMENTS | {"doc_id": doc_id, "dolevel": do_level} diff --git a/testsuite/Qualif/Ada/stmt/1_Core/req_set.rst b/testsuite/Qualif/Ada/stmt/1_Core/req_set.rst index f83693e5d..a0b72209a 100755 --- a/testsuite/Qualif/Ada/stmt/1_Core/req_set.rst +++ b/testsuite/Qualif/Ada/stmt/1_Core/req_set.rst @@ -17,8 +17,8 @@ Several chapters aren't included for reasons listed in the following table: .. tabularcolumns:: |p{0.3\textwidth}|p{0.65\textwidth}| -.. csv-table:: - :header: "Chapter"| "Not included because ..." +.. csv-table:: ARM chapter exclusions + :header: "Chapter", "Not included because ..." :widths: 28, 65 :delim: | @@ -32,4 +32,3 @@ Several chapters aren't included for reasons listed in the following table: .. qmlink:: SubsetIndexTocTree * - diff --git a/testsuite/Qualif/Appendix/Testsuite/app.rst b/testsuite/Qualif/Appendix/Testsuite/app.rst index 2516783a0..d0c6bc758 100644 --- a/testsuite/Qualif/Appendix/Testsuite/app.rst +++ b/testsuite/Qualif/Appendix/Testsuite/app.rst @@ -1,13 +1,13 @@ .. _testsuite-overview: -|testproc_section_title| -************************ +Overview of the Test Procedures Organization +******************************************** The GNATcoverage *testsuite* consists of the set of executable *tests* that implement *Testcases*, driven by an execution and control harness to validate part or all of a *Tool Operational Requirement*. Each test involves sources and a description of expected results, which, in association with the harness -operation, consitutes a *test procedure*. +operation, constitutes a *test procedure*. Very broadly, the testsuite harness builds executables from the sources, executes the resulting programs, invokes GNATcoverage to perform some coverage @@ -394,5 +394,3 @@ with the test category to prevent FAILures from violations of stricter criteria. In our example test of statement category, the ``0`` expectations are meant to convey that we expect no *statement coverage* violation on the lines, and violations of stricter criteria there ought to be ignored. - - diff --git a/testsuite/Qualif/Environment/additional_switches_bin.rst b/testsuite/Qualif/Environment/additional_switches_bin.rst deleted file mode 100644 index e69de29bb..000000000 diff --git a/testsuite/Qualif/Environment/additional_switches_src.rst b/testsuite/Qualif/Environment/additional_switches_src.rst deleted file mode 100644 index 92a2e016a..000000000 --- a/testsuite/Qualif/Environment/additional_switches_src.rst +++ /dev/null @@ -1,5 +0,0 @@ -The indications for the GNATcov dump trigger and GNATcov dump channel switch -values represent the retained values for the corresponding switches, required -as part of the :literal:`gnatcov instrument` command, in accordance to the -restrictions imposed by the GNATPro runtime library profile and execution host -capabilities defined above, as described in the tool's User Manual. \ No newline at end of file diff --git a/testsuite/Qualif/Environment/content.rst b/testsuite/Qualif/Environment/content.rst index 3c68a0e04..d011b2e93 100644 --- a/testsuite/Qualif/Environment/content.rst +++ b/testsuite/Qualif/Environment/content.rst @@ -1,11 +1,11 @@ .. _operational-conditions: -|opcond_section_title| -====================== +Operational Conditions of Use +============================= This chapter describes rules on which the correctness of the source coverage assessments performed by GNATcoverage depends. This instance of the document -is valid for use in a certification context no stricter than DAL |dolevel|. +is valid for use in a certification context no stricter than DAL |prj_DAL|. .. _operational-context: @@ -22,18 +22,18 @@ matching process. .. tabularcolumns:: |p{0.06\textwidth}|p{0.30\textwidth}|p{0.60\textwidth}| -.. csv-table:: - :header: "Item #"| "Description"| "Expected value" +.. csv-table:: Expected verification Environment values + :header: "Item #", "Description", "Expected value" :widths: 5, 30, 60 - :delim: | + :delim: / - e1 | Host Operating System name and version | Linux Redhat 7 - e2 | GNATcoverage executable name and version | GNATcoverage 19.3 (20200318) - e3 | GNAT Pro compiler executable name and version | gcc (GCC) 7.3.1 20180924 (for GNAT Pro 19lts 20200331) [i686-pc-linux-gnu] - s1 | GNAT Pro compilation switches | -gnat12 - s2 | GNAT Pro Runtime Library Profile | No --RTS switch expected. Programs shall honor the :ref:`language-scope` restrictions, nevertheless. - s3 | GNATcov dump trigger switch value | :literal:`--dump-triger=atexit` - s4 | GNATcov dump channel switch value | :literal:`--dump-channel=bin-file` + e1 / Host Operating System name and version / |prj_host_platform| + e2 / GNATcoverage executable name and version / |gnatcov_version| + e3 / GNAT Pro compiler executable name and version / |gnatpro_version| + s1 / GNAT Pro compilation switches / |prj_switches| + s2 / GNAT Pro Runtime Library Profile / |prj_RTS| + s3 / GNATcov dump trigger switch value / |prj_dump_trigger| + s4 / GNATcov dump channel switch value / |prj_dump_channel| For the GNAT Pro compilation switches, additional options which do not @@ -75,7 +75,7 @@ General use of the tool is described in the Tool User's Guide document, which can be found in the subdirectory :literal:`share/doc` of the tool installation. For qualified use more specifically, the Tool User shall also conform to the rules described in the *Qualified Interface* section of the -qualification |plans_doc| document. + |plans_doc| document. .. _language-scope: diff --git a/testsuite/Qualif/Environment/content.tmpl b/testsuite/Qualif/Environment/content.tmpl deleted file mode 100644 index cd37ce2b5..000000000 --- a/testsuite/Qualif/Environment/content.tmpl +++ /dev/null @@ -1,121 +0,0 @@ -.. _operational-conditions: - -|opcond_section_title| -====================== - -This chapter describes rules on which the correctness of the source coverage -assessments performed by GNATcoverage depends. This instance of the document -is valid for use in a certification context no stricter than DAL |dolevel|. - -.. _operational-context: - -Operational Environment ------------------------ - -The Operational Environment in which the tool is used shall match the -Verification Environment in which the tool was qualified, as characterized by -the items presented in the following table. The *Expected value* column here -states the intended value for qualification, which should match what -eventually gets logged within the |str_doc| report. The *Item #* column -provides item identifiers that are produced in this report to facilitate the -matching process. - -.. tabularcolumns:: |p{0.06\textwidth}|p{0.30\textwidth}|p{0.60\textwidth}| - -<%env_table%> - -For the GNAT Pro compilation switches, additional options which do not -influence code generation are allowed. This may, for example, include options -controlling warnings, confirming compiler defaults, or designating a -configuration pragma file which contains only pragmas not influencing code -generation (``Restriction_Warnings`` pragmas or specific ``Restrictions`` such -as ``No_Direct_Boolean_Operators`` for instance). - -The Runtime Library Profile indication conveys the --RTS switch for which the -Verification Environment should be setup, designating a runtime library -delivered with the GNAT Pro toolchain. Tool Users shall have their toolchain -setup to compile programs with a :literal:`--RTS` switch as well, designating -a runtime with a ``system.ads`` identical to the qualification one. - -<%additional_switches%> - -Installation, Documentation and Qualified Interface ---------------------------------------------------- - -All AdaCore tool packages use a common installation procedure, that depends on -the host platform. - -* On Windows hosts, the tool packages are provided as - self-installing executables. The Tool User should run the executable - corresponding to the tool he wants to install, then follow the instructions - on screen. - -* On non-Windows hosts, the tool packages are provided as .tar.gz - archives. The Tool User should unpack the archive corresponding to the tool - he wants to install, then run the script doinstall located at the root of - the archive directory structure, and follow the instructions on screen. - -General use of the tool is described in the Tool User's Guide document, which -can be found in the subdirectory :literal:`share/doc` of the tool -installation. For qualified use more specifically, the Tool User shall also -conform to the rules described in the *Qualified Interface* section of the -qualification |plans_doc| document. - - -.. _language-scope: - -Language Version and Scope --------------------------- - -The general contents of this document is not tailored for a particular -version of the Ada language. The requirements and testcases sections -might contain items matching up to Ada 2012 even if the intended -qualified use is for an Ada 95 or Ada 2005 project. - -Nevertheless, to make sure there is no ambiguity on the intended use of the -tool for a given project: - -* The version language for which qualification is sought shall be stated by - way of a :literal:`-gnat95` :literal:`-gnat05` or :literal:`-gnat12` - compilation option in the :ref:`operational-context` section. - -In addition: - -* The tool is not qualified to analyze programs featuring tasking constructs, - controlled type definitions or pointers to nested subprograms. - - One possible way to ensure that the code subject to analysis conforms to - what this qualification material encompasses is to verify that it compiles - without error under control of a Zero Footprint Runtime Library Profile, or - free of warnings out of the following set of configuration pragmas:: - - pragma Restriction_Warnings (No_Tasking); - pragma Restriction_Warnings (No_Finalization); - pragma Restriction_Warnings (No_Implicit_Dynamic_Code); - -* For mcdc assessments, the tool requires the use of short-circuit variants - for the Boolean binary operators composing decisions: ``&&`` or ``||`` in C, - ``and then`` or ``or else`` in Ada. - - One possible way to ensure this for Ada is to verify that the code subject - to analysis compiles without error under control of the following - configuration pragma:: - - pragma Restrictions (No_Direct_Boolean_Operator); - -* For decision or mcdc analysis, the tool is not qualified to assess coverage - of expressions used in assertion constructs such as Assert pragmas or their - contract programming model extensions in Ada 2012 (Pre/Post pragmas or - aspects, their 'Class variants, static/dynamic subtype predicates or type - invariants). - - This material is designed with the assumption that such constructs, if - present in the source programs at all, are disabled, for instance thanks to - an Assertion_Policy pragma. - -* For decision or mcdc analysis on Ada 2012, the tool is not - qualified to assess coverage *generalized membership tests* with - more than one alternative. - - Such expressions are only allowed in assertion/contracts contexts, disabled - for coverage analysis purposes as previously described in this section. diff --git a/testsuite/Qualif/Environment/env_table_bin.rst b/testsuite/Qualif/Environment/env_table_bin.rst deleted file mode 100644 index 54016ea62..000000000 --- a/testsuite/Qualif/Environment/env_table_bin.rst +++ /dev/null @@ -1,11 +0,0 @@ -.. csv-table:: - :header: "Item #"| "Description"| "Expected value" - :widths: 5, 30, 60 - :delim: | - - e1 | Host Operating System name and version | Linux Redhat 7 - e2 | GNATcoverage executable name and version | GNATcoverage 19.3 (20200318) - e3 | GNAT Pro compiler executable name and version | gcc (GCC) 7.3.1 20180924 (for GNAT Pro 19lts 20200331) [i686-pc-linux-gnu] - s1 | GNAT Pro compilation switches | -g -fpreserve-control-flow -fdump-scos -gnat12 - s2 | GNAT Pro Runtime Library Profile | No --RTS switch expected. Programs - shall honor the :ref:`language-scope` restrictions, nevertheless. diff --git a/testsuite/Qualif/Environment/env_table_src.rst b/testsuite/Qualif/Environment/env_table_src.rst deleted file mode 100644 index 319435685..000000000 --- a/testsuite/Qualif/Environment/env_table_src.rst +++ /dev/null @@ -1,13 +0,0 @@ -.. csv-table:: - :header: "Item #"| "Description"| "Expected value" - :widths: 5, 30, 60 - :delim: | - - e1 | Host Operating System name and version | Windows x86_64 - e2 | GNATcoverage version | GNATcoverage 23.1 (20230113) - e3 | GNAT Pro GCC version | GCC 11.3.1 20220922 (for GNAT Pro 23.1 20230113) - e4 | gprbuild version | GPRBUILD Pro 23.1 (20230113) (x86_64-w64-mingw32) - s1 | GNAT Pro compilation switches | -gnat12 - s2 | GNAT Pro Runtime Library Profile | No --RTS switch expected. Programs shall nevertheless honor the :ref:`language-scope` restrictions. - s3 | GNATcov dump trigger switch value | :literal:`--dump-triger=atexit` - s4 | GNATcov dump channel switch value | :literal:`--dump-channel=bin-file` diff --git a/testsuite/Qualif/Introduction/content.rst b/testsuite/Qualif/Introduction/content.rst index 60d15b442..d1077e0be 100644 --- a/testsuite/Qualif/Introduction/content.rst +++ b/testsuite/Qualif/Introduction/content.rst @@ -1,5 +1,5 @@ -|torintro_section_title| -************************ +Document Purpose and Organization +********************************* Document Purpose ================ @@ -94,7 +94,7 @@ so testcase identifiers are continuations of the parent requirement's identifier, for example `/TOR/Ada/stmt/Core/CompoudStatements/Loop/Incomplete_Iteration`. -These identifiers are used to denote individual testcases in the |str_doc| +These identifiers are used to denote individual testcases in the |str_abb| report produced out of testuite runs for qualification. For a more detailed description of how testscase sources are organized and how @@ -108,10 +108,10 @@ Abbreviations The following abbreviations are used throughout this document: -.. csv-table:: +.. csv-table:: Abbreviation definitions :delim: | :widths: 30, 40 - :header: "Abbreviation"| "Meaning" + :header: "Abbreviation", "Meaning" ARM|Ada Reference Manual LRM|(Ada) Language Reference Manual @@ -124,4 +124,3 @@ The following abbreviations are used throughout this document: rqg|requirement group tc|test case tcg|test case group - diff --git a/testsuite/Qualif/content.rst b/testsuite/Qualif/content.rst index 7bcea1ead..7a7bfa075 100644 --- a/testsuite/Qualif/content.rst +++ b/testsuite/Qualif/content.rst @@ -1,27 +1,20 @@ -GNATcoverage - |standard| Qualification Material: |tor_doc_title| +GNATcoverage - |tool_standard| Qualification Material: |doc_title| ################################################################# .. rubric:: List of referenced documents .. tabularcolumns:: |p{0.20\textwidth}|p{0.80\textwidth}| -.. csv-table:: +.. csv-table:: Reference documents :delim: ; :widths: 10, 90 - :header: "Designation"; "Referenced document" + :header: "Designation", "Referenced document" - |plans_doc| ; |project_name_it| - |plans_doc_title| (|plans_doc_id|) + |plans_abb| ; |prj_toolset| - |plans_doc| (|plans_id|) Ada 2012 LRM ; Ada 2012 Reference Manual. Language and Standard Libraries, ISO/IEC 8652:2012(E) Ada 2005 LRM ; Ada 2005 Reference Manual. Language and Standard Libraries. International Standard ISO/IEC 8652/1995(E) with Technical Corrigendum 1 and Amendment 1. Ada 95 LRM ; Ada 1995 Reference Manual. Language and Standard Libraries. International Standard ISO/IEC 8652:1995 Technical Corrigendum 1 (ISO/IEC 8652:1995:TC1:2000) - Tool User's Guide ; *GNATcoverage User's Guide*, part of the GNATcoverage 19.3 release documentation - -.. rubric:: Revision History -.. csv-table:: - :delim: & - :header: "Version #", "Date", "Comment" - - |release| & |today| & Latest revision + Tool User's Guide ; *GNATcoverage User's Guide*, part of the GNATcoverage |gnatcov_version| release documentation .. only:: html diff --git a/testsuite/STR/genrest.py b/testsuite/STR/genrest.py index 373a0e1a4..fea689796 100644 --- a/testsuite/STR/genrest.py +++ b/testsuite/STR/genrest.py @@ -111,6 +111,7 @@ def __init__(self, testsuite_dir): self.qdl = [] self.load_all(root=testsuite_dir) + self.root = testsuite_dir def load_all(self, root): """Load all data generated by a testsuite run. @@ -354,8 +355,9 @@ def img(self, details=False): class TcidCell(object): - def __init__(self, text): + def __init__(self, text, root): self.text = text + self.root = root def img(self, details=False): # Arrange to strip: @@ -376,6 +378,7 @@ def img(self, details=False): re_strip = collections.OrderedDict( ( + (re.escape(self.root), ""), (QROOTDIR + "/", ""), ("(Ada|C)/(stmt|decision|mcdc)/", ""), ("Common/Report/", ""), @@ -816,12 +819,6 @@ def __init__(self, options): self.gen_tctables(sepfile="tctables.rst") self.gen_tssummary(sepfile="tssummary.rst") - # Rely on a static toplevel index instead of generating one here. - # This is much simpler to tailor and the harcoded knowledge (set of - # sections/documents) is very limited and unlikely to change. - - # self.gen_index(sepfiles=["env.rst", "tctables.rst", "tssummary.rst"]) - def _check_one_dump_option(self, line, option_name, current_value): """ Helper for gather_trigger_and_channel, inspect a line to determine @@ -904,7 +901,7 @@ def tcdata_for(self, qd): # for one testcase this_tcdata = dict( - [(colid.tc, TcidCell(qd.tcid))] + [(colid.tc, TcidCell(qd.tcid, self.o.testsuite_dir))] + [(key, CountersCell()) for key in self.viocnt_columns] + [(colid.sta, QstatusCell(qd.status))] ) @@ -1353,7 +1350,7 @@ def switches_with_eq_from(switches_string): ) CSVtable( - title=None, + title="Testsuite execution options", text=None, columns=(itemno, item, value), controls=[":widths: 7, 30, 60"], @@ -1432,7 +1429,7 @@ def gen_suite_environ(self): ) CSVtable( - title=None, + title="Testsuite execution environment", text=None, columns=(itemno, item, v1, v2), controls=[":widths: 7, 25, 20, 48"], @@ -1455,16 +1452,6 @@ def gen_envinfo(self, sepfile=None): if sepfile: self.rstf.close() - # --------------- - # -- gen_index -- - # --------------- - - def gen_index(self, sepfiles): - self.rstf = RSTfile("index.rst") - self.rstf.write(rest.chapter("GNATcoverage Software Test Results")) - self.rstf.write(rest.toctree(sepfiles, depth=1)) - self.rstf.close() - # ====================== # == main entry point == diff --git a/testsuite/STR/source/content.rst b/testsuite/STR/source/content.rst index 54b06697c..b03998cd3 100644 --- a/testsuite/STR/source/content.rst +++ b/testsuite/STR/source/content.rst @@ -11,6 +11,5 @@ GNATcoverage DO178C/ED-12C Qualification Material: Tool Operational Verification intro.rst env.rst - tctables.rst tssummary.rst - + tctables.rst From bb40dad7286d8871d00605791c336e9890a08b67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 5 Sep 2025 16:49:58 +0200 Subject: [PATCH 1447/1483] Qualification/TOR: Fix testcase index generation Had to go through a bit of a hack to do this as I can't really understand how this worked in the first place with the QM. --- .../qualkit/scripts/qm_plugins/importers.py | 17 +++++++++++++++-- qualification/qualkit/tor/genrest.py | 2 +- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/qualification/qualkit/scripts/qm_plugins/importers.py b/qualification/qualkit/scripts/qm_plugins/importers.py index 9a721e232..093884628 100644 --- a/qualification/qualkit/scripts/qm_plugins/importers.py +++ b/qualification/qualkit/scripts/qm_plugins/importers.py @@ -922,6 +922,7 @@ def to_rest(self, artifact): class IndexImporter(ArtifactImporter): + current_req = None def append_to_items(self, art, depth): @@ -930,7 +931,7 @@ def append_to_items(self, art, depth): kind_text = writer.strong("(%s)" % class_to_string(art)) id_text = writer.strong("%s" % art.id.replace("/TOR", "")) - elif is_tc(art): + else: kind_text = "(%s)" % class_to_string(art) common_prefix_parent_req = os.path.commonprefix( @@ -953,14 +954,26 @@ def qmlink_to_rest(self, parent, artifacts): self.items = [] + # HACK: not sure how this importer is supposed to work, the only + # IndexImporter occurence in the `Qualif/Index` directory which doesn't + # have any subdirectories, and the directive does not feature any + # param/links to resolve. As we want this to walk all the tests and + # requirements, we hardcode the artifacts list to be all the children + # of the parents of self. + def sortkey_for(art): # Arrange for stmt requirements to come first, before decision and # mcdc. Work from locations, which contain the explicit ordering # requests in the names (numeric prefixes like 1_). - return str(art.location).replace("/stmt", "/a") + return str(art.id).replace("/stmt", "/a") + artifacts = [ + art + for art in parent.pdo.relatives + if "Ada" in art.id or "Common" in art.id + ] artifacts.sort(key=sortkey_for) for art in artifacts: diff --git a/qualification/qualkit/tor/genrest.py b/qualification/qualkit/tor/genrest.py index 1157cd992..1be4ad914 100755 --- a/qualification/qualkit/tor/genrest.py +++ b/qualification/qualkit/tor/genrest.py @@ -1602,7 +1602,7 @@ def process_qmlink( elif not in_qmlink: res += "\n" + line - if importer and subartifacts: + if importer: # rst section in the end of the document qmlink_rst, links = importer.qmlink_to_rest(diro, subartifacts) diro.subdos += [ From ed15f1ba5e6f3dcf43ae404fe9d21ea0004843cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Fri, 5 Sep 2025 17:37:45 +0200 Subject: [PATCH 1448/1483] Qualification: Various fixes including: - typo fixes in the TOR introduction - Adding the proper appendix latex command - Remove some unsupported latex roles --- .../qualkit/scripts/qm_plugins/importers.py | 16 ++++++---------- testsuite/Qualif/Introduction/content.rst | 8 ++++---- testsuite/Qualif/content.rst | 6 +++++- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/qualification/qualkit/scripts/qm_plugins/importers.py b/qualification/qualkit/scripts/qm_plugins/importers.py index 093884628..c976024cd 100644 --- a/qualification/qualkit/scripts/qm_plugins/importers.py +++ b/qualification/qualkit/scripts/qm_plugins/importers.py @@ -275,7 +275,7 @@ def qmlink_to_rest(self, parent, artifacts): if len(ref[req]) > 1: pdf_other_tcs = "%s + %d other tests" % ( - writer.role("raw-latex", r"\newline"), + writer.raw(r"\newline", "latex"), (len(ref[req]) - 1), ) @@ -301,10 +301,10 @@ def qmlink_to_rest(self, parent, artifacts): pdf_tc_list += "%s %s %s %s %s " % ( requirement_str, - writer.role("raw-latex", r"\newline"), + writer.raw(r"\newline", "latex"), first_tc_str, pdf_other_tcs, - writer.role("raw-latex", r"\newline"), + writer.raw(r"\newline", "latex"), ) html_tc_list += "%s %s * TC: %s %s " % ( @@ -323,7 +323,7 @@ def qmlink_to_rest(self, parent, artifacts): pdf_comment = ( comment + " " - + writer.role("raw-latex", r"\newline") + + writer.raw(r"\newline", "latex") + " " ) html_comment = ( @@ -343,9 +343,7 @@ def qmlink_to_rest(self, parent, artifacts): ) pdf_comment = ( - comment - + writer.role("raw-latex", r"\newline") - + " " + comment + writer.raw(r"\newline", "latex") + " " ) html_comment = ( comment + writer.role("raw-html", r"
") + " " @@ -1099,9 +1097,7 @@ def tc_pdf_for(self, toplevel, subdirs, links): writer.section("%s Testcases" % toplevel) + "\n" ) else: - pdf_output += ( - writer.role("raw-latex", r"\newpage") + "\n\n" - ) + pdf_output += writer.raw(r"\newpage", "latex") + "\n\n" pdf_output += subdir_output diff --git a/testsuite/Qualif/Introduction/content.rst b/testsuite/Qualif/Introduction/content.rst index d1077e0be..b333fa613 100644 --- a/testsuite/Qualif/Introduction/content.rst +++ b/testsuite/Qualif/Introduction/content.rst @@ -45,7 +45,7 @@ for this requirement. Each line in such a table designates a particular testcase, requirement or group artifact, with an abbreviation denoting the kind of artifact in the first column, the artifact local name in the second column and a short description of the artifact contents in the third. See the -:ref:`abbrevs` section later in this chapter for the list of abbrevations used +:ref:`abbrevs` section later in this chapter for the list of abbreviations used in the first column. At the top of the hierarchy, collections of high level requirement groups are @@ -71,7 +71,7 @@ requirement groups, addressing: tool behavior with respect to the stated requirements, testcases in this category are also typically designed to exercise multiple kinds of language constructs mixed together. They represent a good opportunity to do so as - they are not directed to focus on specific contructs by the nature of the + they are not directed to focus on specific constructs by the nature of the requirements to exercise, unlike a core requirement on, say, *If* statements for example. @@ -85,14 +85,14 @@ testsuite harness to search for criteria violation messages. Every requirement is assigned a unique **Requirement Identifier** computed from its local name and position in the hierarchy of chapters and groups. This identifier is denoted as a path with slashes between each intermediate -level, for example `/TOR/Ada/stmt/Core/CompoudStatements/Loop`. +level, for example `/TOR/Ada/stmt/Core/CompoundStatements/Loop`. Likewise, each Testcase is assigned a unique **Testcase Identifier**, computed from its local name and position in the hierarchy of requirements and testcases. Each testcase or group is always attached to a single requirement, so testcase identifiers are continuations of the parent requirement's identifier, for example -`/TOR/Ada/stmt/Core/CompoudStatements/Loop/Incomplete_Iteration`. +`/TOR/Ada/stmt/Core/CompoundStatements/Loop/Incomplete_Iteration`. These identifiers are used to denote individual testcases in the |str_abb| report produced out of testuite runs for qualification. diff --git a/testsuite/Qualif/content.rst b/testsuite/Qualif/content.rst index 7a7bfa075..2f3b01870 100644 --- a/testsuite/Qualif/content.rst +++ b/testsuite/Qualif/content.rst @@ -1,5 +1,5 @@ GNATcoverage - |tool_standard| Qualification Material: |doc_title| -################################################################# +################################################################## .. rubric:: List of referenced documents @@ -39,6 +39,10 @@ GNATcoverage - |tool_standard| Qualification Material: |doc_title| Ada Common +.. raw:: latex + + \appendix + .. only:: html From aa2b8f88d19b4a1770089cdeccafb41607d98b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 10 Sep 2025 10:41:55 +0200 Subject: [PATCH 1449/1483] Revert "Merge branch 'eyraud/429' into 'master'" This reverts commit 69a14415abc314a779c4c8653dc1f578b7b4eed3, reversing changes made to 3341e2fe68474dfbff82916ecf9902dcb35b06b1. The issue is that this MR localized all coverage obligations from an included header on the single line where the inclusion takes place, and on the column range corresponding to the buffer index in the original header. When creating low leve SCOs, the column number is limited to 2^15, which is easily smaller than the number of characters in a header. Ignoring these SCOs reveals more challenges, so this is reverted while we take some time to find a better encoding for these SCOs. --- .../tests/207-srctrace-version/foo.c.sid | Bin 1026 -> 1186 bytes testsuite/tests/207-srctrace-version/main.sid | Bin 1426 -> 1422 bytes .../207-srctrace-version/reference.srctrace | Bin 336 -> 336 bytes .../213-sarif-report/all-lang/full/ref.sarif | 8 +- .../tests/213-sarif-report/c/full/ref.sarif | 6 +- .../tests/213-sarif-report/cpp/full/ref.sarif | 6 +- testsuite/tests/429-metaprog-c/bar.h | 3 - testsuite/tests/429-metaprog-c/foo.h | 3 - testsuite/tests/429-metaprog-c/test.c | 14 - .../tests/429-metaprog-c/test.c.xcov.expected | 35 -- testsuite/tests/429-metaprog-c/test.opt | 1 - testsuite/tests/429-metaprog-c/test.py | 25 -- .../unsupported/test.opt | 1 - .../unsupported/test.py | 31 +- .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 1692 -> 1508 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2580 -> 2580 bytes .../gen/arm-elf-linux/gcvrt-pz3791e32c.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68b.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68c.ads | 2 +- .../gen/arm-elf-linux/main_1.adb | 2 +- .../gen/arm-elf-linux/main_1.sid | Bin 449 -> 445 bytes .../gen/arm-elf-linux/main_2.adb | 2 +- .../gen/arm-elf-linux/main_2.sid | Bin 449 -> 445 bytes .../gen/arm-elf-linux/pkg.sid | Bin 1158 -> 1150 bytes .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1843 -> 1831 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1853 -> 1841 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 2438 -> 2422 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 2369 -> 2353 bytes .../gen/x86_64-windows/gcvrt-pz3791e32c.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68b.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68c.ads | 2 +- .../gen/x86_64-windows/main_1.adb | 2 +- .../gen/x86_64-windows/main_1.sid | Bin 451 -> 447 bytes .../gen/x86_64-windows/main_2.adb | 2 +- .../gen/x86_64-windows/main_2.sid | Bin 451 -> 447 bytes .../gen/x86_64-windows/pkg.sid | Bin 1162 -> 1154 bytes tools/gnatcov/annotations-dynamic_html.adb | 2 - tools/gnatcov/annotations.adb | 76 ++--- tools/gnatcov/clang-extensions.ads | 12 +- tools/gnatcov/clang-wrapper.cc | 8 - tools/gnatcov/instrument-c.adb | 303 +++++------------- tools/gnatcov/instrument-c.ads | 14 +- tools/gnatcov/instrument-c_utils.adb | 16 - tools/gnatcov/instrument-c_utils.ads | 5 - tools/gnatcov/sc_obligations.adb | 214 +++++-------- tools/gnatcov/sc_obligations.ads | 62 ++-- 46 files changed, 261 insertions(+), 604 deletions(-) delete mode 100644 testsuite/tests/429-metaprog-c/bar.h delete mode 100644 testsuite/tests/429-metaprog-c/foo.h delete mode 100644 testsuite/tests/429-metaprog-c/test.c delete mode 100644 testsuite/tests/429-metaprog-c/test.c.xcov.expected delete mode 100644 testsuite/tests/429-metaprog-c/test.opt delete mode 100644 testsuite/tests/429-metaprog-c/test.py delete mode 100644 testsuite/tests/N430-005-c-static-inline/unsupported/test.opt diff --git a/testsuite/tests/207-srctrace-version/foo.c.sid b/testsuite/tests/207-srctrace-version/foo.c.sid index 62a9e0c8ac05155a302b4828f7d31bc1f1017818..d0ecec554373ef0e8806b3be7e5dd46d7ea16d47 100644 GIT binary patch delta 144 zcmZqTSj0J@(4K{Xfq@Z(*?bb)Dt19QAd>PBZ?MgS(r1abfX delta 14 Vcmcb>bb)Dt19NimijB^^i~uRE1o!{| diff --git a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif index 327db8271..39f4563cc 100644 --- a/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/all-lang/full/ref.sarif @@ -265,7 +265,7 @@ "uri": "c_source.c" }, "region": { - "startColumn": 8, + "startColumn": 7, "startLine": 24 } } @@ -307,7 +307,7 @@ "uri": "c_source.c" }, "region": { - "startColumn": 8, + "startColumn": 7, "startLine": 34 } } @@ -412,7 +412,7 @@ "uri": "cpp_source.cpp" }, "region": { - "startColumn": 8, + "startColumn": 7, "startLine": 24 } } @@ -454,7 +454,7 @@ "uri": "cpp_source.cpp" }, "region": { - "startColumn": 8, + "startColumn": 7, "startLine": 34 } } diff --git a/testsuite/tests/213-sarif-report/c/full/ref.sarif b/testsuite/tests/213-sarif-report/c/full/ref.sarif index 2898d4b85..bdd0c1513 100644 --- a/testsuite/tests/213-sarif-report/c/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/c/full/ref.sarif @@ -55,7 +55,7 @@ "uri": "foo.c" }, "region": { - "startColumn": 8, + "startColumn": 7, "startLine": 9 } } @@ -97,7 +97,7 @@ "uri": "lib.c" }, "region": { - "startColumn": 8, + "startColumn": 7, "startLine": 6 } } @@ -223,7 +223,7 @@ "uri": "main.c" }, "region": { - "startColumn": 8, + "startColumn": 7, "startLine": 24 } } diff --git a/testsuite/tests/213-sarif-report/cpp/full/ref.sarif b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif index 897cf8cf5..01c84475b 100644 --- a/testsuite/tests/213-sarif-report/cpp/full/ref.sarif +++ b/testsuite/tests/213-sarif-report/cpp/full/ref.sarif @@ -55,7 +55,7 @@ "uri": "foo.cpp" }, "region": { - "startColumn": 8, + "startColumn": 7, "startLine": 9 } } @@ -97,7 +97,7 @@ "uri": "lib.cpp" }, "region": { - "startColumn": 8, + "startColumn": 7, "startLine": 6 } } @@ -223,7 +223,7 @@ "uri": "main.cpp" }, "region": { - "startColumn": 8, + "startColumn": 7, "startLine": 24 } } diff --git a/testsuite/tests/429-metaprog-c/bar.h b/testsuite/tests/429-metaprog-c/bar.h deleted file mode 100644 index f6cd799d1..000000000 --- a/testsuite/tests/429-metaprog-c/bar.h +++ /dev/null @@ -1,3 +0,0 @@ -{ - DECL (a_bar) -} diff --git a/testsuite/tests/429-metaprog-c/foo.h b/testsuite/tests/429-metaprog-c/foo.h deleted file mode 100644 index 5b2d73759..000000000 --- a/testsuite/tests/429-metaprog-c/foo.h +++ /dev/null @@ -1,3 +0,0 @@ -#include "bar.h" -DECL (a_foo) -return 0; diff --git a/testsuite/tests/429-metaprog-c/test.c b/testsuite/tests/429-metaprog-c/test.c deleted file mode 100644 index aca39b8b8..000000000 --- a/testsuite/tests/429-metaprog-c/test.c +++ /dev/null @@ -1,14 +0,0 @@ -#define DECL(x) int x = 0; - -int -foo () -{ - DECL (a_main) -#include "foo.h" -} - -int -main () -{ - return 0; -} diff --git a/testsuite/tests/429-metaprog-c/test.c.xcov.expected b/testsuite/tests/429-metaprog-c/test.c.xcov.expected deleted file mode 100644 index 9b983483d..000000000 --- a/testsuite/tests/429-metaprog-c/test.c.xcov.expected +++ /dev/null @@ -1,35 +0,0 @@ -33% of 3 lines covered -20% statement coverage (1 out of 5) - -Coverage level: stmt - 1 .: #define DECL(x) int x = 0; - 2 .: - 3 .: int - 4 .: foo () - 5 .: { - 6 -: DECL (a_main) -statement "int a_mai..." at 6:3 not executed - note: in definition of macro DECL at location test.c:1:17 - note: from expansion of macro DECL at location test.c:6:3 - 7 -: #include "foo.h" -statement "int a_bar..." at 7:10 not executed - note: in file bar.h at location bar.h:2:3 - note: from inclusion of bar.h at location foo.h:1:10 - note: from inclusion of foo.h at location test.c:7:10 - note: in definition of macro DECL at location test.c:1:17 - note: from expansion of macro DECL at location bar.h:2:3 -statement "int a_foo..." at 7:10 not executed - note: in file foo.h at location foo.h:2:1 - note: from inclusion of foo.h at location test.c:7:10 - note: in definition of macro DECL at location test.c:1:17 - note: from expansion of macro DECL at location foo.h:2:1 -statement "return 0;" at 7:10 not executed - note: in file foo.h at location foo.h:3:1 - note: from inclusion of foo.h at location test.c:7:10 - 8 .: } - 9 .: - 10 .: int - 11 .: main () - 12 .: { - 13 +: return 0; - 14 .: } diff --git a/testsuite/tests/429-metaprog-c/test.opt b/testsuite/tests/429-metaprog-c/test.opt deleted file mode 100644 index 194738427..000000000 --- a/testsuite/tests/429-metaprog-c/test.opt +++ /dev/null @@ -1 +0,0 @@ -bin-traces DEAD Use case not supported with binary traces diff --git a/testsuite/tests/429-metaprog-c/test.py b/testsuite/tests/429-metaprog-c/test.py deleted file mode 100644 index 0dab10777..000000000 --- a/testsuite/tests/429-metaprog-c/test.py +++ /dev/null @@ -1,25 +0,0 @@ -""" -Check that we have the right annotations for SCOs that come from -metaprogramming instances. -""" - -import os - -from SCOV.minicheck import build_run_and_coverage -from SUITE.cutils import Wdir -from SUITE.gprutils import GPRswitches -from SUITE.tutils import gprfor, thistest - -Wdir("tmp_") -build_run_and_coverage( - gprsw=GPRswitches(root_project=gprfor(srcdirs=[".."], mains=["test.c"])), - covlevel="stmt", - mains=["test"], - extra_coverage_args=["--annotate=xcov+"], -) - -thistest.fail_if_diff( - os.path.join("..", "test.c.xcov.expected"), - os.path.join("obj", "test.c.xcov"), -) -thistest.result() diff --git a/testsuite/tests/N430-005-c-static-inline/unsupported/test.opt b/testsuite/tests/N430-005-c-static-inline/unsupported/test.opt deleted file mode 100644 index 2c8011a19..000000000 --- a/testsuite/tests/N430-005-c-static-inline/unsupported/test.opt +++ /dev/null @@ -1 +0,0 @@ -src-traces DEAD Use case supported with source traces diff --git a/testsuite/tests/N430-005-c-static-inline/unsupported/test.py b/testsuite/tests/N430-005-c-static-inline/unsupported/test.py index a377299a7..6afa40593 100644 --- a/testsuite/tests/N430-005-c-static-inline/unsupported/test.py +++ b/testsuite/tests/N430-005-c-static-inline/unsupported/test.py @@ -28,14 +28,29 @@ tolerate_instrument_messages="unexpected SCO overlapping", ) -# Check that gnatcov coverage warns when using binary traces - -output_string = "gnatcov coverage output" -output_file = "coverage.log" -expected_output = ( - "!!! foo.h:2:8: unexpected SCO overlapping with SCO #2: " - "STATEMENT at foo.h:2:8-20, discarding overlapping SCO" -) +# With source traces, the warning is emitted at instrumentation time, whereas +# it is emitted at coverage time with binary traces. +# +# As SCOs source locations differ for binary and source traces, we get +# different warnings. Note that the instrumentation warning is the most +# precise. + +if thistest.options.trace_mode == "src": + output_string = "gnatcov instrument output" + output_file = "instrument.log" + expected_output = ( + "!!! foo.h:1:1: unexpected SCO overlapping with SCO #1: " + "STATEMENT at foo.h:1:1-13, discarding overlapping SCO\n" + "!!! foo.h:2:1: unexpected SCO overlapping with SCO #2: " + "STATEMENT at foo.h:2:1-21, discarding overlapping SCO" + ) +else: + output_string = "gnatcov coverage output" + output_file = "coverage.log" + expected_output = ( + "!!! foo.h:2:8: unexpected SCO overlapping with SCO #2: " + "STATEMENT at foo.h:2:8-20, discarding overlapping SCO" + ) thistest.fail_if_no_match( output_string, expected_output, contents_of(output_file) diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index f247f1c5bfe34948c51f3c8a0fbb5f4e66e7060f..8d65dbe4b94a5d8e0b66773112166929960175d1 100644 GIT binary patch literal 1508 zcmYk6Pe@cz6vodyr#G)jr1y%5p~VFyB9P{vjfjgD79kcDCN8AZEK10tAY4WZ7ZNQb zL?l8&L_#7$LPElYiy?-PkO*fA#wYLf~<=f$rv=}TLyjf`K&sUFG?q0O|OB+QIE$AT9MZZa-L^Eyd5QVo5r1- zH^0MtlKv(0J56_+Ptxx(zt{8t*p2ZQO)r7$M>2m|>7;DB0+!)F-xvE6AoEG)zfd}v zGCgfRNq^S-In!^=C+W|dzhHV%8On~XgOgolB!5A!x9pGC%~N8%kgxN%`eh~NZ@OYW z$$l&5ubTb_@_SfQMzU`4?;yt|S+}8dvT1tD^e>R#(Qk`aLDrG1+f_Q*Gwt~j^uWIc z((ebEPg37fIvF%Q1p4@%9)rvy+3$(@Bg#+$dmp2gM{>MpN+)Bc$IU0{Pn!SI^egj8 z`ZMOgHvPtYlKwmM-<$pbc3_^q?YlI15%XVFjeP|+pspM2Mc#tOBUuEw4j+|~EP(;? z$`=1*@e0VkE6PyDbw7pDhGVJ@eHy@H;1!Vj@G!{z+Y25=-7v`a`PAYSko$if%pl&J z;5d<-1KFn?%zy)6EqEW~xiA8H$giUABzW74>mGp)dLHDtFmCZ_kmJpQ94FQZ*|WHZ x=SbuE>y)9)APqXvPDS$f8JR%@aCKU{O8_t=DhcA`@P$DAM}=& zrXN3f8H*=Gxq7bGHWb1>Nha=H~kQ28y|S78}^7{r~!`jQaamBuGdol{yLH;$=qZ zWEM<7&zYVF1L!5w%jU0|UQ^%6hH5XH7T*Hv#mSEPp_Edr6UqVVHX?okrlBJ`IoEi| z!2}Mz0|WRGoiszU-{BewlIZ6Sm_XjR(#w6*li&>eebWaZCMYEH50zd%m_9O}qyFU#g{;?Be`xx>1ECIIyeRY%=9_Pe3JR!lwQ7@ z{skuS9Q_5EN3!0f5mD7~kk8wu%_RxVe3JX7lwLBXo%tmFM)R9Zx0+AVZ!^Esbhr5= z{Tt@zP4|OisJ~%)3miv(6L`Pa=N@zi)}4YC6mO;d>c$*o;%7=3Lw|7fJx+6ExwC-jC+uC+Qt9kT+Tu2 zPRxUR4YJN#kn=0U=lz)iIhO|2m>oKMs(#x|vw IE|CB8A3bV?w*UYD diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_2.trace b/testsuite/tests/U204-026-arch-mix/bin-main_2.trace index a9caab5e1f2f925be89da963facd660afc6f031c..2f231d9f7e9a9f8d4ed8584d4f9ac4b50af1f324 100644 GIT binary patch delta 69 zcmbOtGDT#994k9ByAl6HWo1JX6Ltm$24NsJGB7gLH89sTFjg=yw=y-bGBjo20E%-1 Uv4V+#nW2%9rGcsC#`3wG0EXTRng9R* delta 69 zcmbOtGDT#994jX)53l4zWo1KCBX$M`24NsJGB7gLHL%n*FjX)#vNANbGBRc00E%-1 Uv4WwYfvJVDg@L)*#`3wG0D_nchyVZp diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads index 1c808ade0..59a1337ec 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz3791e32c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz3791e32c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads index 927e8b086..faa4d9e4d 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68b.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68b is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads index 870f9ae12..5e6ce0228 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/gcvrt-pz794ac68c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb index 656f51403..d7ef728a8 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=9,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=8,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); GCVRT.DB_z794ac68b.Dump_Buffers;end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_1.sid index 0730d49454ff3fcc711da9b33c7cd3962409e446..96f6c5407c5cdfb1fd3152e0d331593004cdd19f 100644 GIT binary patch delta 10 RcmX@eyq9@G`NnEDMgSNg1OEU3 delta 13 UcmdnXe2{rU`NXXP8=I{d0VqNRQ2+n{ diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb index 285a40eb7..4bbc2b311 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=9,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=8,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); GCVRT.DB_z794ac68c.Dump_Buffers;end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/main_2.sid index 2ce002c1fd893fc1a0e67a166c78afdc2d4eb220..7323a92fefb9207223f3a92132b9facd0336c31e 100644 GIT binary patch delta 10 RcmX@eyq9@G`NnEDMgSNg1OEU3 delta 13 UcmdnXe2{rU`NXXP8=I{d0VqNRQ2+n{ diff --git a/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/arm-elf-linux/pkg.sid index ab8c243bacaf30bf2e778667e96682f9661bb211..49d156be429897c0a3ec5e4525ea72703ced3d24 100644 GIT binary patch delta 18 acmZqU{Kqk2)nox?mWi9XHajr7F#`ZZdIp35 delta 18 acmeyz(Z)Gp)no@ImWiwSHk&YdF#`ZcCI+Vf diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_1.ckpt index 7a5b106c09fde92a5f8bbca9cfade34871dcb8fa..d01ce8c959310edfdc0079e589d5b4757387aaf0 100644 GIT binary patch delta 83 zcmdnYx14W-DAQy~Cb!ASOn#fUGM!*#ESp@%qRUjnuz4*@7bE)(+4gH;E>)B5*elzp<7+6}F8dw>cC}0#37~0?Yvc{*!V9Edm4qv!Miv0SAaK^Mu#; ZjgvA4(F{2)Ff|}CG&(UeIx>?F2N>X*6y5*; diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index 91cb77a1af470cecd50fa5dc1ec3409cbab51476..efb763a2b70342f3e69ca18ff6a64400f66529b1 100644 GIT binary patch delta 68 zcmdnXw~=pyDAQy~Cb!ASOn#fUGIcYv?O)*+?ou_`jqS3Exvqh+f`O%#sezTDse-nF Nk(Ge~BLf7$XaK9Q4*~!H delta 72 zcmdnUx0i2&DAQyIW|qmKOm36InSwSiW$I^Ui@x{d`uE<+R&1A5EOiY`6%0+R42`Xf SOck^ZjI0a{7#Sb{MgssX*%4*{ diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 70f004d42013b5d154130990a034e1af61adcb6a..309ed84ff45210f78dda60cbd59cb5d97dee8d76 100644 GIT binary patch delta 60 zcmZn@{wB1+k8yGkov{7h-8{=dz#w(MRm>x`KV{Y2q!~B?qoulS>SC~uHHq)$ delta 44 zcmV+{0Mq}m62TI%MgfzA0T7c?0mzdU0_2nM0R)r!0)n%61Lp(>z+G2C*Y}N+W(doM CZ4!t8 diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads index 03f085d72..3e54dc4f9 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz3791e32c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz3791e32c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads index 08e30c044..c37eb3685 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68b.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68b is diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads index 235f1a41a..a41ab39aa 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/gcvrt-pz794ac68c.ads @@ -2,7 +2,7 @@ pragma Style_Checks (Off); pragma Warnings (Off); with System; with GNATcov_RTS; with GNATcov_RTS.Buffers; -pragma Compile_Time_Error (GNATcov_RTS.Version /= 9 ,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); +pragma Compile_Time_Error (GNATcov_RTS.Version /= 8, "Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution."); package GCVRT.Pz794ac68c is diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb index 2506d1b0c..c7f0007ae 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=9,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68b;with GCVRT.DB_z794ac68b;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=8,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_1 is GNATcov_Dump_Object:GCVRT.DB_z794ac68b.Dump_Controlled_Type;begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68b.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, False); end Main_1; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_1.sid index 2ff33613884c9b1348322f6c9f688772e7f9cdd7..c15c782f198c6dc4d6084f2a00fa285a3931b817 100644 GIT binary patch delta 10 RcmX@iyq|eO<;Ge!MgSO91P1^B delta 13 Ucmdnbe3*Gc<;3j*8(Xay0VtFOTL1t6 diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb index 7feb3b7a6..0480a5e96 100644 --- a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb +++ b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.adb @@ -1,6 +1,6 @@ pragma Style_Checks (Off); pragma Warnings (Off);with Pkg; -with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=9,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is +with GNATcov_RTS.Buffers;with GCVRT.Pz794ac68c;with GCVRT.DB_z794ac68c;with GNATcov_RTS;with GNATcov_RTS.Buffers;pragma Compile_Time_Error(GNATcov_RTS.Version/=8,"Incompatible GNATcov_RTS version, please use the GNATcov_RTS project provided with your GNATcoverage distribution.");procedure Main_2 is GNATcov_Dump_Object:GCVRT.DB_z794ac68c.Dump_Controlled_Type;begin GNATcov_RTS.Buffers.Witness(GCVRT.Pz794ac68c.Buffers_1.Statement_Buffer,0);Pkg.Compute (True, True); end Main_2; diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/main_2.sid index 6ed8a0ea410ff1cc362d719710d8b1ffdc8ad01f..4d89b525b304ae68e888d097f98b44f1d7754491 100644 GIT binary patch delta 10 RcmX@iyq|eO<;Ge!MgSO91P1^B delta 13 Ucmdnbe3*Gc<;3j*8(Xay0VtFOTL1t6 diff --git a/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid b/testsuite/tests/U204-026-arch-mix/gen/x86_64-windows/pkg.sid index 7517581311b10b153cecd57d7da11740bc2c7bfb..0ef87464e0de311707f64eb0ec4f09a14721a6bb 100644 GIT binary patch delta 18 ZcmeC;Y~q}-ZsMlC$r4OFn*$iFm;pmH1}Fdk delta 22 ecmZqT?BblTZt?{tmWk{7CM&S8Y_?%^V+H_X0tbfx diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index f9763f4ea..1090abefe 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -262,8 +262,6 @@ package body Annotations.Dynamic_Html is -- * text -- * coverage -- * range - -- * annotations - -- * kind function Src_Range (SCO : SCO_Id) return JSON_Array; -- Return a JSON array for the range Sloc_Start .. Sloc_End from SCO diff --git a/tools/gnatcov/annotations.adb b/tools/gnatcov/annotations.adb index cf95b4a1c..c3a5ec1ea 100644 --- a/tools/gnatcov/annotations.adb +++ b/tools/gnatcov/annotations.adb @@ -691,7 +691,6 @@ package body Annotations is is Sloc_Start : Source_Location := First_Sloc (SCO); Sloc_End : Source_Location := End_Lex_Element (Last_Sloc (SCO)); - pragma Assert (Sloc_Start.Source_File = Sloc_End.Source_File); Desc : Unbounded_String; -- SCO description: shortened view of the SCO tokens, with a macro @@ -701,11 +700,11 @@ package body Annotations is -- First, if this is a SCO inside a macro expansion, get the -- preprocessed excerpt for reporting purposes. - if Has_Macro_Info (SCO) then + if Has_PP_Info (SCO) and then Get_PP_Info (SCO).Kind = In_Expansion then declare SFI : constant Source_File_Index := Sloc_Start.Source_File; - Info : constant PP_Info := Get_Macro_Info (SCO); + Info : constant PP_Info := Get_PP_Info (SCO); Preprocessed_Filename : constant String := Get_PP_Filename (SFI) & ".prepro"; Postprocessed_Filename : constant String := Get_PP_Filename (SFI); @@ -713,6 +712,7 @@ package body Annotations is Get_Index_From_Generic_Name (Postprocessed_Filename, Source_File, Insert => False); + begin if Postprocessed_SFI = No_Source_File then declare @@ -755,19 +755,12 @@ package body Annotations is end if; if Postprocessed_SFI /= No_Source_File then - Sloc_Start := First_Sloc (Info.Tokens_Source_Range); Sloc_Start.Source_File := Postprocessed_SFI; - Sloc_End := Last_Sloc (Info.Tokens_Source_Range); + Sloc_Start.L := Info.PP_Source_Range.First_Sloc; Sloc_End.Source_File := Postprocessed_SFI; + Sloc_End.L := Info.PP_Source_Range.Last_Sloc; end if; end; - elsif Has_Include_Info (SCO) then - declare - Info : constant PP_Info := Get_Include_Info (SCO); - begin - Sloc_Start := First_Sloc (Info.Tokens_Source_Range); - Sloc_End := Last_Sloc (Info.Tokens_Source_Range); - end; end if; -- As an approximation (given the diversity of provenance for sloc @@ -847,54 +840,33 @@ package body Annotations is -- SCO_Annotations -- --------------------- - function SCO_Annotations (SCO : SCO_Id) return String_Vectors.Vector - is - Annotations : String_Vectors.Vector; + function SCO_Annotations (SCO : SCO_Id) return String_Vectors.Vector is begin - -- Start by adding the inclusion information - - if Has_Include_Info (SCO) then + if Has_PP_Info (SCO) then declare - Info : constant PP_Info := Get_Include_Info (SCO); + Info : constant PP_Info := Get_PP_Info (SCO); + Annotations : String_Vectors.Vector; begin - Annotations.Append - ("in file " - & Info.Definition_Loc.Name - & " at location " - & Slocs.Image (Info.Definition_Loc.Sloc)); - - for Exp_Info of Info.Expansion_Stack loop + if Info.Kind = In_Expansion then Annotations.Append - ("from inclusion of " - & Exp_Info.Name + ("in definition of macro " + & Info.Definition_Loc.Macro_Name & " at location " - & Slocs.Image (Exp_Info.Sloc)); - end loop; - end; - end if; - - -- Then, add the macro expansion information - - if Has_Macro_Info (SCO) then - declare - Info : constant PP_Info := Get_Macro_Info (SCO); - begin - Annotations.Append - ("in definition of macro " - & Info.Definition_Loc.Name - & " at location " - & Slocs.Image (Info.Definition_Loc.Sloc)); + & Slocs.Image (Info.Definition_Loc.Sloc)); + + for Exp_Info of Info.Expansion_Stack loop + Annotations.Append + ("from expansion of macro " + & Exp_Info.Macro_Name + & " at location " + & Slocs.Image (Exp_Info.Sloc)); + end loop; - for Exp_Info of Info.Expansion_Stack loop - Annotations.Append - ("from expansion of macro " - & Exp_Info.Name - & " at location " - & Slocs.Image (Exp_Info.Sloc)); - end loop; + return Annotations; + end if; end; end if; - return Annotations; + return String_Vectors.Empty_Vector; end SCO_Annotations; ------------------------ diff --git a/tools/gnatcov/clang-extensions.ads b/tools/gnatcov/clang-extensions.ads index 89cdd4cc7..5caacd3d2 100644 --- a/tools/gnatcov/clang-extensions.ads +++ b/tools/gnatcov/clang-extensions.ads @@ -284,7 +284,7 @@ package Clang.Extensions is with Import, Convention => C, External_Name => "clang_getImmediateMacroCallerLoc"; - -- See getImmediateMacroCallerLoc in clang/Basic/SourceManager.h + -- See getImmediateMacroCallerLoc in clang/Basic/SourceManager.h. function Get_Immediate_Expansion_Loc (Loc : Source_Location_T; @@ -292,7 +292,7 @@ package Clang.Extensions is with Import, Convention => C, External_Name => "clang_getImmediateExpansionLoc"; - -- See getImmediateExpansionRange in clang/Basic/SourceManager.h + -- See getImmediateExpansionRange in clang/Basic/SourceManager.h. function Get_Expansion_End (TU : Translation_Unit_T; @@ -300,7 +300,7 @@ package Clang.Extensions is with Import, Convention => C, External_Name => "clang_getExpansionEnd"; - -- See getExpansionRange in clang/Basic/SourceManager.h + -- See getExpansionRange in clang/Basic/SourceManager.h. function Get_Spelling_Loc (TU : Translation_Unit_T; @@ -308,12 +308,6 @@ package Clang.Extensions is with Import, Convention => C, External_Name => "clang_getSpellingLoc"; -- See getSpellingLoc in clang/Basic/SourceManager.h - function Get_Include_Loc - (TU : Translation_Unit_T; - Loc : Source_Location_T) return Source_Location_T - with Import, Convention => C, External_Name => "clang_getIncludeLoc"; - -- See getIncludeLoc in clang/Basic/SourceManager.h - procedure Print_Location (TU : Translation_Unit_T; Loc : Source_Location_T) with Import, Convention => C, External_Name => "clang_printLocation"; diff --git a/tools/gnatcov/clang-wrapper.cc b/tools/gnatcov/clang-wrapper.cc index ea0ce94f7..cdd4f6bc0 100644 --- a/tools/gnatcov/clang-wrapper.cc +++ b/tools/gnatcov/clang-wrapper.cc @@ -1126,14 +1126,6 @@ clang_getExpansionEnd (CXTranslationUnit TU, CXSourceLocation Loc) return translateSLoc (TU, SM.getExpansionRange (SLoc).getEnd ()); } -extern "C" CXSourceLocation -clang_getIncludeLoc (CXTranslationUnit TU, CXSourceLocation Loc) -{ - SourceLocation SLoc = translateSourceLocation (Loc); - const SourceManager &SM = getSourceManager (TU); - return translateSLoc (TU, SM.getPresumedLoc (SLoc).getIncludeLoc ()); -} - extern "C" CXTranslationUnit clang_getCursorTU (CXCursor C) { diff --git a/tools/gnatcov/instrument-c.adb b/tools/gnatcov/instrument-c.adb index 2ff0da0c1..8605fc963 100644 --- a/tools/gnatcov/instrument-c.adb +++ b/tools/gnatcov/instrument-c.adb @@ -162,78 +162,6 @@ package body Instrument.C is -- Return the list of arguments that should always be passed to -- Parse_Translation_Unit. - ------------------- - -- Scopes logic -- - ------------------- - - procedure Enter_Scope - (UIC : in out C_Unit_Inst_Context'Class; - N : Cursor_T); - -- Open a scope for N under the scope of the file in which the - -- corresponding code was written. This must be completed with a call to - -- the function Exit_Scope, defined below. Assume that the scope first SCO - -- is the next generated SCO (SCOs.SCO_Table.Last + 1). Update - -- UIC.Scopes to the created entity and UIC.Current_File_Scope to the - -- corresponding file. - - procedure Exit_Scope (UIC : in out C_Unit_Inst_Context'Class); - -- Close the current scope, removing the current scope of the current file - -- from UIC.Scopes if it does not contain SCOs. Assume that the last - -- generated SCO (SCOs.SCO_Table.Last) is the last SCO for the current - -- scope. - - function Relocate_SCO - (UIC : C_Unit_Inst_Context'Class; - Loc : Source_Location) return Boolean - is (Scopes_In_Files_Map.Key (UIC.Current_File_Scope) /= Loc.Source_File); - -- As we don't allow scopes across various files, every SCO needs to be in - -- the same file of the file its parent scope belongs to. This function - -- indicates whether the SCO located at Loc falls in the latter case, - -- meaning it should be relocated to its inclusion point in its parent - -- scope. Note that this is typically used when doing metaprogramming - -- in C/C++, along with abusing the macro system. - -- - -- See this C example (reduced from the git codebase): - -- - -- // main.c - -- /* auxiliary function for binary search in interval table */ - -- static int bisearch(int ucs, int max) - -- { - -- return 0; - -- } - -- - -- - -- static int git_wcwidth(int ch) - -- { - -- /* - -- * Sorted list of non-overlapping intervals of non-spacing characters, - -- */ - -- #include "unicode-width.h" - -- - -- return 1; - -- } - -- - -- // unicode-width.h - -- static const struct interval zero_width[] = {{ 0x0300, 0x036F }}; - -- - -- For more complex metaprogramming instances, see this C++ code excerpt - -- from the LLVM code base - which uses token concatenations in addition - -- to the macro system: - -- - -- #define OVERLOADED_OPERATOR \ - -- (Name, Spelling, Token, Unary, Binary, MemberOnly) \ - -- case OO_##Name: \ - -- OperatorName = "operator" Spelling; \ - -- break; - -- #define OVERLOADED_OPERATOR_MULTI \ - -- (Name, Spelling, Unary, Binary, MemberOnly) - -- #include "clang/Basic/OperatorKinds.def" - -- - -- In the OperatorKinds.def file, each of the overloadable C++ - -- operators is enumerated with either the OVERLOADED_OPERATOR or - -- OVERLOADED_OPERATOR_MULTI macro, each of which can be specified by - -- the code including this file. - --------------------------- -- Passes specificities -- --------------------------- @@ -254,6 +182,25 @@ package body Instrument.C is type Instrument_Pass_Kind is new Pass_Kind with null record; + overriding procedure Enter_Scope + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class; + N : Cursor_T); + -- Open a scope for N under the scope of the file in which the + -- corresponding code was written. This must be completed with a call to + -- the function Exit_Scope, defined below. Assume that the scope first SCO + -- is the next generated SCO (SCOs.SCO_Table.Last + 1). Update + -- UIC.Scopes to the created entity and UIC.Current_File_Scope to the + -- corresponding file. + + overriding procedure Exit_Scope + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class); + -- Close the current scope, removing the current scope of the current file + -- from UIC.Scopes if it does not contain SCOs. Assume that the last + -- generated SCO (SCOs.SCO_Table.Last) is the last SCO for the current + -- scope. + overriding procedure Append_SCO (Pass : Instrument_Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; @@ -664,9 +611,10 @@ package body Instrument.C is -- Enter_Scope -- ----------------- - procedure Enter_Scope - (UIC : in out C_Unit_Inst_Context'Class; - N : Cursor_T) + overriding procedure Enter_Scope + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class; + N : Cursor_T) is procedure Enter_File_Scope (UIC : in out C_Unit_Inst_Context'Class; @@ -779,7 +727,9 @@ package body Instrument.C is -- Exit_Scope -- ---------------- - procedure Exit_Scope (UIC : in out C_Unit_Inst_Context'Class) + overriding procedure Exit_Scope + (Pass : Instrument_Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class) is File_Scope_Ref : constant Scopes_In_Files_Map.Reference_Type := UIC.Scopes.Reference (UIC.Current_File_Scope); @@ -804,9 +754,8 @@ package body Instrument.C is Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name) is - Loc_C : Source_Location_T := Start_Sloc (N); - Loc : constant Source_Location := Sloc (Loc_C); - Info : PP_Info; + Loc : Source_Location_T := Start_Sloc (N); + Info : PP_Info; begin Append_SCO (C1, C2, From.L, To.L, From.Source_File, Last, Pragma_Aspect_Name); @@ -818,67 +767,16 @@ package body Instrument.C is return; end if; - -- Start by checking whether this is an instance of metaprogramming - -- (i.e. whose parent scope is in a different file than the node). - -- In this case, set the SCO location to the file of the parent scope. - - if Relocate_SCO (UIC, From) then - - -- Retrieve the inclusion expansion chain - - -- TODO??? deal with the case where the SCO is both in an instance - -- of metaprogramming and a macro expansion (and think of adding a - -- test for it). + -- TODO??? The actual source range should be a Source_Location, and not + -- a Local_Source_Location as it can refer to #included files. - declare - Scope_SFI : Source_File_Index renames - Scopes_In_Files_Map.Key (UIC.Current_File_Scope); - Inclusion_Loc_C : Source_Location_T := - Get_Include_Loc (UIC.TU, Loc_C); - Inclusion_Stack : Expansion_Lists.List; - Inclusion_Loc : Source_Location := Sloc (Inclusion_Loc_C); - Inclusion_File : Source_File_Index := Loc.Source_File; - begin - loop - Inclusion_Stack.Append - (Expansion_Info' - (Name => +Get_Simple_Name (Inclusion_File), - Sloc => Inclusion_Loc)); - Inclusion_File := Inclusion_Loc.Source_File; - - -- Exit before updating Inclusion_Loc to use the initial - -- inclusion point as an Actual_Source_Range for the stored - -- preprocessing information. - - exit when Scope_SFI = Inclusion_File; - Inclusion_Loc_C := Get_Include_Loc (UIC.TU, Inclusion_Loc_C); - Inclusion_Loc := Sloc (Inclusion_Loc_C); - end loop; - - -- The actual source range for the coverage obligation is the - -- location of the include directive in the parent scope source - -- file. - - Info := - (Tokens_Source_Range => To_Range (From, To), - Actual_Source_Range => - To_Range (Inclusion_Loc, Inclusion_Loc), - Expansion_Stack => Inclusion_Stack, - Definition_Loc => - Expansion_Info' - (Name => +Get_Simple_Name (Loc.Source_File), Sloc => Loc)); - - UIC.LL_Include_Info_Map.Insert (SCOs.SCO_Table.Last, Info); - end; - end if; - - Info.Actual_Source_Range := To_Range (From, To); - Info.Tokens_Source_Range := No_Range; + Info.Actual_Source_Range := (From.L, To.L); + Info.PP_Source_Range := No_Local_Range; -- Check if this is comes from a macro expansion, in which case we need -- to record some information, for reporting purposes. - if Is_Macro_Location (Loc_C) then + if Is_Macro_Location (Loc) then declare Expansion_Stack : Expansion_Lists.List; Definition_Info : Expansion_Info; @@ -958,15 +856,15 @@ package body Instrument.C is -- API to get either a filename, or a or -- string in these cases. - if Is_Macro_Arg_Expansion (Loc_C, Macro_Arg_Expanded_Loc, UIC.TU) + if Is_Macro_Arg_Expansion (Loc, Macro_Arg_Expanded_Loc, UIC.TU) then Macro_Expansion_Name := +Get_Immediate_Macro_Name_For_Diagnostics (Macro_Arg_Expanded_Loc, UIC.TU); Definition_Info := - (Name => Macro_Expansion_Name, - Sloc => + (Macro_Name => Macro_Expansion_Name, + Sloc => Presumed_Spelling_Location (UIC.TU, Macro_Arg_Expanded_Loc, @@ -974,20 +872,20 @@ package body Instrument.C is UIC.Options.Builtin_Macros)); else Macro_Expansion_Name := - +Get_Immediate_Macro_Name_For_Diagnostics (Loc_C, UIC.TU); + +Get_Immediate_Macro_Name_For_Diagnostics (Loc, UIC.TU); Definition_Info := - (Name => Macro_Expansion_Name, - Sloc => + (Macro_Name => Macro_Expansion_Name, + Sloc => Presumed_Spelling_Location (UIC.TU, - Loc_C, + Loc, Macro_Expansion_Name, UIC.Options.Builtin_Macros)); end if; - while Is_Macro_Location (Loc_C) loop + while Is_Macro_Location (Loc) loop - Immediate_Expansion_Loc := Loc_C; + Immediate_Expansion_Loc := Loc; -- Find the location of the immediately expanded macro. Getting -- the immediate expansion location yields a location in the @@ -1047,11 +945,11 @@ package body Instrument.C is Immediate_Expansion_Loc := Get_Immediate_Expansion_Loc (Immediate_Expansion_Loc, UIC.TU); Macro_Expansion_Name := - +Get_Immediate_Macro_Name_For_Diagnostics (Loc_C, UIC.TU); + +Get_Immediate_Macro_Name_For_Diagnostics (Loc, UIC.TU); -- Then, keep going up the expansion stack - Loc_C := Get_Immediate_Macro_Caller_Loc (Loc_C, UIC.TU); + Loc := Get_Immediate_Macro_Caller_Loc (Loc, UIC.TU); -- If the returned Macro_Definition_Name is an empty string, -- then it means the location refers to a token paste, or @@ -1059,8 +957,8 @@ package body Instrument.C is if Macro_Expansion_Name /= "" then Expansion_Stack.Append - ((Name => Macro_Expansion_Name, - Sloc => + ((Macro_Name => Macro_Expansion_Name, + Sloc => Presumed_Spelling_Location (UIC.TU, Immediate_Expansion_Loc, @@ -1070,13 +968,15 @@ package body Instrument.C is end loop; Info := - (Tokens_Source_Range => Info.Tokens_Source_Range, + (Kind => In_Expansion, + PP_Source_Range => Info.PP_Source_Range, Actual_Source_Range => Info.Actual_Source_Range, Expansion_Stack => Expansion_Stack, Definition_Loc => Definition_Info); end; - UIC.LL_Macro_Info_Map.Insert (SCOs.SCO_Table.Last, Info); end if; + + UIC.LL_PP_Info_Map.Insert (SCOs.SCO_Table.Last, Info); end Append_SCO; overriding procedure Append_SCO @@ -1088,50 +988,11 @@ package body Instrument.C is Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name) is - Actual_From : Source_Location := From; - Actual_To : Source_Location := To; - -- TODO??? clarify whether we still need From and To begin if UIC.Disable_Coverage then return; end if; - if Relocate_SCO (UIC, From) then - - -- If we relocate the SCO, we still preserve the SCO nesting by - -- locating it at: - -- - -- :- - -- - -- where Offset is the location of the sloc in the text buffer. - - declare - Relocation_SFI : Source_File_Index renames - Scopes_In_Files_Map.Key (UIC.Current_File_Scope); - Include_Loc_C : Source_Location_T := - Get_Include_Loc (UIC.TU, Start_Sloc (N)); - Include_Loc : Source_Location; - begin - loop - Include_Loc := Sloc (Include_Loc_C); - exit when Include_Loc.Source_File = Relocation_SFI; - Include_Loc_C := Get_Include_Loc (UIC.TU, Include_Loc_C); - end loop; - - Actual_From := Source_Location' - (Source_File => Relocation_SFI, - L => Local_Source_Location' - (Line => Include_Loc.L.Line, - Column => Integer (Offset (Start_Sloc (N))))); - - Actual_To := Source_Location' - (Source_File => Relocation_SFI, - L => Local_Source_Location' - (Line => Include_Loc.L.Line, - Column => Integer (Offset (End_Sloc (N))))); - end; - end if; - -- Insert a new entry to the UIC.Instrumented_Entities maps: even if -- this SOI does not possess instrumented SCOs (it can be the case if -- all of the code constructs are not instrumentable), we want an empty @@ -1139,9 +1000,8 @@ package body Instrument.C is -- proper initialization of checkpoints structures (e.g. Statement_Bits) -- later on. - if not UIC.Instrumented_Entities.Contains (Actual_From.Source_File) then - UIC.Instrumented_Entities.Insert - (Actual_From.Source_File, (others => <>)); + if not UIC.Instrumented_Entities.Contains (From.Source_File) then + UIC.Instrumented_Entities.Insert (From.Source_File, (others => <>)); end if; -- End the statement block if we entered a new file: we do not want @@ -1151,7 +1011,7 @@ package body Instrument.C is use type SCOs.SCO_Unit_Index; begin if SCOs.SCO_Unit_Table.Last /= 0 - and then Last_File /= Actual_From.Source_File + and then Last_File /= From.Source_File then UIC.Pass.End_Statement_Block (UIC); UIC.Pass.Start_Statement_Block (UIC); @@ -1159,8 +1019,7 @@ package body Instrument.C is end; Append_SCO - (C1, C2, Actual_From.L, Actual_To.L, Actual_From.Source_File, Last, - Pragma_Aspect_Name); + (C1, C2, From.L, To.L, From.Source_File, Last, Pragma_Aspect_Name); -- If this SCO is in a macro expansion, let's add source location -- information: we want to be able to know the actual source location @@ -1168,12 +1027,12 @@ package body Instrument.C is -- retrieve the actual string (from the preprocessed code) when -- producing a coverage report. - if UIC.LL_Macro_Info_Map.Contains (SCOs.SCO_Table.Last) then + if UIC.LL_PP_Info_Map.Contains (SCOs.SCO_Table.Last) then declare Start_Loc : constant Source_Location_T := Start_Sloc (N); End_Loc : constant Source_Location_T := End_Sloc (N); - Cursor_Source_Range : Slocs.Source_Location_Range; + Cursor_Source_Range : Slocs.Local_Source_Location_Range; procedure Update (LL_SCO : Nat; Info : in out PP_Info); @@ -1184,22 +1043,22 @@ package body Instrument.C is procedure Update (LL_SCO : Nat; Info : in out PP_Info) is pragma Unreferenced (LL_SCO); begin - Info.Tokens_Source_Range := Cursor_Source_Range; + if Info.Kind = In_Expansion then + Info.PP_Source_Range := Cursor_Source_Range; + end if; end Update; begin -- Get start and end of the range. Note: End_Loc is exclusive, -- whereas we need Cursor_Source_Range.Last_Sloc to be inclusive. - Cursor_Source_Range.Source_File := Actual_From.Source_File; - Cursor_Source_Range.L.First_Sloc := File_Location (Start_Loc); - Cursor_Source_Range.L.Last_Sloc := File_Location (End_Loc); - Cursor_Source_Range.L.Last_Sloc.Column := - Cursor_Source_Range.L.Last_Sloc.Column - 1; + Cursor_Source_Range.First_Sloc := File_Location (Start_Loc); + Cursor_Source_Range.Last_Sloc := File_Location (End_Loc); + Cursor_Source_Range.Last_Sloc.Column := + Cursor_Source_Range.Last_Sloc.Column - 1; - UIC.LL_Macro_Info_Map.Update_Element - (UIC.LL_Macro_Info_Map.Find (SCOs.SCO_Table.Last), - Update'Access); + UIC.LL_PP_Info_Map.Update_Element + (UIC.LL_PP_Info_Map.Find (SCOs.SCO_Table.Last), Update'Access); end; end if; end Append_SCO; @@ -2917,7 +2776,7 @@ package body Instrument.C is end if; if Cursor_Kind /= Cursor_Lambda_Expr then - Enter_Scope (UIC, N); + UIC.Pass.Enter_Scope (UIC, N); end if; if Stmts.Length > 0 then @@ -2962,7 +2821,7 @@ package body Instrument.C is end if; if Cursor_Kind /= Cursor_Lambda_Expr then - Exit_Scope (UIC); + UIC.Pass.Exit_Scope (UIC); end if; end; @@ -2974,11 +2833,11 @@ package body Instrument.C is | Cursor_Class_Decl | Cursor_Struct_Decl => - Enter_Scope (UIC, N); + UIC.Pass.Enter_Scope (UIC, N); Traverse_Declarations (UIC, Get_Children (N)); - Exit_Scope (UIC); + UIC.Pass.Exit_Scope (UIC); when Cursor_Linkage_Spec => Traverse_Declarations (UIC, Get_Children (N)); @@ -3719,8 +3578,7 @@ package body Instrument.C is -- Save into UIC the preprocessing information - UIC.LL_Macro_Info_Map := UIC_Copy.LL_Macro_Info_Map; - UIC.LL_Include_Info_Map := UIC_Copy.LL_Include_Info_Map; + UIC.LL_PP_Info_Map := UIC_Copy.LL_PP_Info_Map; -- Also copy back the annotation map and disabled region vector as well -- as the info on sources of interest, to avoid double processing. @@ -3845,8 +3703,6 @@ package body Instrument.C is Record_PP_Info_Last_SCO := SCOs.SCO_Table.Last; SCOs.Initialize; - UIC.Scopes.Clear; - UIC.Current_File_Scope := Scopes_In_Files_Map.No_Element; -- Then, instrument @@ -3878,8 +3734,7 @@ package body Instrument.C is & Nat'Image (Record_PP_Info_Last_SCO) & " coverage obligations," & " but got" & Nat'Image (SCOs.SCO_Table.Last) & ". Discarding preprocessing information."); - UIC.LL_Macro_Info_Map.Clear; - UIC.LL_Include_Info_Map.Clear; + UIC.LL_PP_Info_Map.Clear; end if; -- Now that the set of coverage obligations and the set of source files @@ -3910,25 +3765,13 @@ package body Instrument.C is -- SCO macro info map in our unit instrumentation context (bound to -- low level SCOs), and add it to the global macro info map. - for Cursor in UIC.LL_Macro_Info_Map.Iterate loop - declare - use LL_SCO_PP_Info_Maps; - LL_SCO : constant Nat := Key (Cursor); - Info : constant PP_Info := Element (Cursor); - begin - Add_Macro_Info (SCO_Map (LL_SCO), Info); - end; - end loop; - - -- Do the same for inclusion information - - for Cursor in UIC.LL_Include_Info_Map.Iterate loop + for Cursor in UIC.LL_PP_Info_Map.Iterate loop declare use LL_SCO_PP_Info_Maps; LL_SCO : constant Nat := Key (Cursor); Info : constant PP_Info := Element (Cursor); begin - Add_Include_Info (SCO_Map (LL_SCO), Info); + Add_PP_Info (SCO_Map (LL_SCO), Info); end; end loop; diff --git a/tools/gnatcov/instrument-c.ads b/tools/gnatcov/instrument-c.ads index 00243dee7..8c34bbd25 100644 --- a/tools/gnatcov/instrument-c.ads +++ b/tools/gnatcov/instrument-c.ads @@ -395,11 +395,8 @@ package Instrument.C is Pass : Pass_Kind_Acc; -- Current pass. See the Pass_Kind documentation for more details. - LL_Macro_Info_Map : LL_SCO_PP_Info_Maps.Map; - -- Macro information for low level SCOs - - LL_Include_Info_Map : LL_SCO_PP_Info_Maps.Map; - -- Inclusion information for low level SCOs + LL_PP_Info_Map : LL_SCO_PP_Info_Maps.Map; + -- Preprocessing information for low level SCOs Files_Of_Interest : File_Sets.Set; Sources_Of_Interest_Info : Source_Of_Interest_Maps.Map; @@ -475,6 +472,13 @@ private Last : Boolean; Pragma_Aspect_Name : Name_Id := Namet.No_Name) is null; + procedure Enter_Scope (Pass : Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class; + N : Cursor_T) is null; + + procedure Exit_Scope (Pass : Pass_Kind; + UIC : in out C_Unit_Inst_Context'Class) is null; + procedure Instrument_Statement (Pass : Pass_Kind; UIC : in out C_Unit_Inst_Context'Class; diff --git a/tools/gnatcov/instrument-c_utils.adb b/tools/gnatcov/instrument-c_utils.adb index 8a83a7aa7..4c2bdde01 100644 --- a/tools/gnatcov/instrument-c_utils.adb +++ b/tools/gnatcov/instrument-c_utils.adb @@ -152,22 +152,6 @@ package body Instrument.C_Utils is return Sloc (Loc); end End_Sloc; - ------------ - -- Offset -- - ------------ - - function Offset (Loc : Source_Location_T) return unsigned is - Offset : aliased unsigned; - begin - Get_File_Location - (Loc, - System.Null_Address, - null, - null, - Offset'Access); - return Offset; - end Offset; - ---------- -- Kind -- ---------- diff --git a/tools/gnatcov/instrument-c_utils.ads b/tools/gnatcov/instrument-c_utils.ads index 3fb723568..71825c142 100644 --- a/tools/gnatcov/instrument-c_utils.ads +++ b/tools/gnatcov/instrument-c_utils.ads @@ -19,8 +19,6 @@ with Ada.Containers; use Ada.Containers; with Ada.Containers.Vectors; -with Interfaces.C; - with Clang.CX_Source_Location; use Clang.CX_Source_Location; with Clang.Index; use Clang.Index; with Clang.Rewrite; use Clang.Rewrite; @@ -64,9 +62,6 @@ package Instrument.C_Utils is function End_Sloc (N : Cursor_T) return Source_Location; -- Return the end location of a node - function Offset (Loc : Source_Location_T) return Interfaces.C.unsigned; - -- Return the offset of the location in the text buffer - function Kind (N : Cursor_T) return Cursor_Kind_T; -- Return the kind of the node N diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 45aaf463b..12118dee2 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -138,14 +138,8 @@ package body SC_Obligations is Has_Code : Boolean := False; -- Set True when object code for some source file in this unit is seen - Macro_Info_Map : SCO_PP_Info_Maps.Map; - -- Information about preprocessing wrt. macro expansions - - Include_Info_Map : SCO_PP_Info_Maps.Map; - -- Information about inclusion directive expansion, to indicate the - -- chain of inclusion for a relocated source coverage obligation. For - -- more information about this, refer to the comment of the - -- Instrument.C.Relocate_SCO subprogram. + PP_Info_Map : SCO_PP_Info_Maps.Map; + -- Information about preprocessing Scope_Entities : Scope_Entities_Tree := Scope_Entities_Trees.Empty_Tree; -- Scope tree, used to output e.g. subprogram metrics @@ -756,12 +750,6 @@ package body SC_Obligations is -- Remap a SCO_Id. Note: this assumes possible forward references, and -- does not rely on SCO_Map. - procedure Remap_PP_Info_Map - (Relocs : in out Checkpoint_Relocations; - Added_PP_Info : SCO_PP_Info_Maps.Map; - Real_PP_Info : in out SCO_PP_Info_Maps.Map); - -- Remap and add the contents of Added_PP_Info not in Real_PP_Info - procedure Remap_SCO_Descriptor (CP_Vectors : Source_Coverage_Vectors; Relocs : in out Checkpoint_Relocations; @@ -1260,71 +1248,28 @@ package body SC_Obligations is .SIDs_Info.Element (SCO_Fingerprint).Blocks; end Blocks; - -------------------- - -- Has_Macro_Info -- - -------------------- - - function Has_Macro_Info (SCO : SCO_Id) return Boolean is - CU : constant CU_Id := Comp_Unit (SCO); - begin - if CU = No_CU_Id then - return False; - end if; - return CU_Vector.Element (CU).Macro_Info_Map.Contains (SCO); - end Has_Macro_Info; - - ---------------------- - -- Has_Include_Info -- - ---------------------- + ----------------- + -- Has_PP_Info -- + ----------------- - function Has_Include_Info (SCO : SCO_Id) return Boolean is + function Has_PP_Info (SCO : SCO_Id) return Boolean is CU : constant CU_Id := Comp_Unit (SCO); begin if CU = No_CU_Id then return False; end if; - return CU_Vector.Element (CU).Include_Info_Map.Contains (SCO); - end Has_Include_Info; - - -------------------- - -- Get_Macro_Info -- - -------------------- - - function Get_Macro_Info (SCO : SCO_Id) return PP_Info is - CU : constant CU_Id := Comp_Unit (SCO); - begin - return CU_Vector.Reference (CU).Element.Macro_Info_Map.Element (SCO); - end Get_Macro_Info; - - ---------------------- - -- Get_Include_Info -- - ---------------------- + return CU_Vector.Reference (CU).Element.PP_Info_Map.Contains (SCO); + end Has_PP_Info; - function Get_Include_Info (SCO : SCO_Id) return PP_Info is - CU : constant CU_Id := Comp_Unit (SCO); - begin - return CU_Vector.Reference (CU).Element.Include_Info_Map.Element (SCO); - end Get_Include_Info; - - -------------------- - -- Add_Macro_Info -- - -------------------- - - procedure Add_Macro_Info (SCO : SCO_Id; Info : PP_Info) is - CU : constant CU_Id := Comp_Unit (SCO); - begin - CU_Vector.Reference (CU).Element.Macro_Info_Map.Insert (SCO, Info); - end Add_Macro_Info; - - ---------------------- - -- Add_Include_Info -- - ---------------------- + ----------------- + -- Get_PP_Info -- + ----------------- - procedure Add_Include_Info (SCO : SCO_Id; Info : PP_Info) is + function Get_PP_Info (SCO : SCO_Id) return PP_Info is CU : constant CU_Id := Comp_Unit (SCO); begin - CU_Vector.Reference (CU).Element.Include_Info_Map.Insert (SCO, Info); - end Add_Include_Info; + return CU_Vector.Reference (CU).Element.PP_Info_Map.Element (SCO); + end Get_PP_Info; ---------- -- Read -- @@ -1334,16 +1279,16 @@ package body SC_Obligations is (CLS : in out Checkpoint_Load_State; Value : out Expansion_Info) is begin - Value.Name := CLS.Read_Unbounded_String; + Value.Macro_Name := CLS.Read_Unbounded_String; Value.Sloc := CLS.Read_Source_Location; end Read; procedure Read (CLS : in out Checkpoint_Load_State; Value : out PP_Info) is - Result : PP_Info; + Result : PP_Info (SCO_PP_Kind'Val (CLS.Read_U8)); Count : Interfaces.Integer_32; begin - Result.Actual_Source_Range := CLS.Read_Source_Location_Range; - Result.Tokens_Source_Range := CLS.Read_Source_Location_Range; + Result.Actual_Source_Range := CLS.Read_Local_Source_Location_Range; + Result.PP_Source_Range := CLS.Read_Local_Source_Location_Range; Result.Expansion_Stack.Clear; Count := CLS.Read_I32; @@ -1355,7 +1300,15 @@ package body SC_Obligations is Result.Expansion_Stack.Append (EI); end; end loop; - Read (CLS, Result.Definition_Loc); + + case Result.Kind is + when In_Expansion => + Read (CLS, Result.Definition_Loc); + + when others => + null; + end case; + Value := Result; end Read; @@ -1437,8 +1390,7 @@ package body SC_Obligations is Value.Main_Source := CLS.Read_SFI; Read (CLS, Value.Deps); Value.Has_Code := CLS.Read_Boolean; - Read (CLS, Value.Macro_Info_Map); - Read (CLS, Value.Include_Info_Map); + Read (CLS, Value.PP_Info_Map); Read (CLS, Value.Scope_Entities); Read (CLS, Value.ALI_Annotations); Read (CLS, Value.SCOs); @@ -1858,17 +1810,32 @@ package body SC_Obligations is procedure Checkpoint_Load_PP_Info (CLS : in out Checkpoint_Load_State; CP_CU : in out CU_Info; - Real_CU : in out CU_Info) is + Real_CU : in out CU_Info) + is + use SCO_PP_Info_Maps; + Relocs : Checkpoint_Relocations renames CLS.Relocations; begin - -- Remap macro information - - Remap_PP_Info_Map - (CLS.Relocations, CP_CU.Macro_Info_Map, Real_CU.Macro_Info_Map); - - -- Remap include information - - Remap_PP_Info_Map - (CLS.Relocations, CP_CU.Include_Info_Map, Real_CU.Include_Info_Map); + for Cur in CP_CU.PP_Info_Map.Iterate loop + declare + SCO : SCO_Id := Key (Cur); + Info : PP_Info := Element (Cur); + begin + if not Real_CU.PP_Info_Map.Contains (SCO) then + if Info.Kind = In_Expansion then + for Expansion of Info.Expansion_Stack loop + Remap_SFI + (Relocs, + Expansion.Sloc.Source_File); + end loop; + Remap_SFI + (Relocs, + Info.Definition_Loc.Sloc.Source_File); + end if; + Remap_SCO_Id (Relocs, SCO); + Real_CU.PP_Info_Map.Insert (SCO, Info); + end if; + end; + end loop; end Checkpoint_Load_PP_Info; ---------------------------- @@ -2099,38 +2066,6 @@ package body SC_Obligations is S := Checkpoints.Remap_SCO_Id (Relocs, S); end Remap_SCO_Id; - ----------------------- - -- Remap_PP_Info_Map -- - ----------------------- - - procedure Remap_PP_Info_Map - (Relocs : in out Checkpoint_Relocations; - Added_PP_Info : SCO_PP_Info_Maps.Map; - Real_PP_Info : in out SCO_PP_Info_Maps.Map) - is - use SCO_PP_Info_Maps; - begin - for Cur in Added_PP_Info.Iterate loop - declare - Info : PP_Info := Element (Cur); - SCO : SCO_Id := Key (Cur); - begin - if not Real_PP_Info.Contains (SCO) then - for Expansion of Info.Expansion_Stack loop - Remap_SFI - (Relocs, - Expansion.Sloc.Source_File); - end loop; - Remap_SFI - (Relocs, - Info.Definition_Loc.Sloc.Source_File); - Remap_SCO_Id (Relocs, SCO); - Real_PP_Info.Insert (SCO, Info); - end if; - end; - end loop; - end Remap_PP_Info_Map; - -------------------------- -- Remap_SCO_Descriptor -- -------------------------- @@ -2693,19 +2628,28 @@ package body SC_Obligations is procedure Write (CSS : in out Checkpoint_Save_State; Value : Expansion_Info) is begin - CSS.Write (Value.Name); + CSS.Write (Value.Macro_Name); CSS.Write (Value.Sloc); end Write; procedure Write (CSS : in out Checkpoint_Save_State; Value : PP_Info) is begin + CSS.Write_U8 (SCO_PP_Kind'Pos (Value.Kind)); CSS.Write (Value.Actual_Source_Range); - CSS.Write (Value.Tokens_Source_Range); + CSS.Write (Value.PP_Source_Range); + CSS.Write_Count (Value.Expansion_Stack.Length); for EI of Value.Expansion_Stack loop Write (CSS, EI); end loop; - Write (CSS, Value.Definition_Loc); + + case Value.Kind is + when In_Expansion => + Write (CSS, Value.Definition_Loc); + + when others => + null; + end case; end Write; procedure Write (CSS : in out Checkpoint_Save_State; Value : Scope_Entity) @@ -2761,8 +2705,7 @@ package body SC_Obligations is CSS.Write_SFI (Value.Main_Source); Write (CSS, Value.Deps); CSS.Write (Value.Has_Code); - Write (CSS, Value.Macro_Info_Map); - Write (CSS, Value.Include_Info_Map); + Write (CSS, Value.PP_Info_Map); Write (CSS, Value.Scope_Entities); Write (CSS, Value.ALI_Annotations); Write (CSS, Value.SCOs); @@ -3634,13 +3577,8 @@ package body SC_Obligations is Sloc : Source_Location := First_Sloc (SCO_Vector.Reference (SCO).Sloc_Range); begin - -- First check if the SCO has inclusion information: if that is the - -- case, then return the inclusion source location. - - if Has_Include_Info (SCO) then - Sloc.L := Get_Include_Info (SCO).Actual_Source_Range.L.First_Sloc; - elsif Has_Macro_Info (SCO) then - Sloc.L := Get_Macro_Info (SCO).Actual_Source_Range.L.First_Sloc; + if Has_PP_Info (SCO) then + Sloc.L := Get_PP_Info (SCO).Actual_Source_Range.First_Sloc; end if; return Sloc; end First_Sloc; @@ -4317,10 +4255,8 @@ package body SC_Obligations is Sloc : Source_Location := Last_Sloc (SCO_Vector.Reference (SCO).Sloc_Range); begin - if Has_Include_Info (SCO) then - Sloc.L := Get_Include_Info (SCO).Actual_Source_Range.L.Last_Sloc; - elsif Has_Macro_Info (SCO) then - Sloc.L := Get_Macro_Info (SCO).Actual_Source_Range.L.Last_Sloc; + if Has_PP_Info (SCO) then + Sloc.L := Get_PP_Info (SCO).Actual_Source_Range.Last_Sloc; end if; return Sloc; end Last_Sloc; @@ -7232,6 +7168,16 @@ package body SC_Obligations is end; end Case_Insensitive_Get_Pragma_Id; + ------------------ + -- Add_PP_Info -- + ------------------ + + procedure Add_PP_Info (SCO : SCO_Id; Info : PP_Info) is + CU : constant CU_Id := Comp_Unit (SCO); + begin + CU_Vector.Reference (CU).Element.PP_Info_Map.Insert (SCO, Info); + end Add_PP_Info; + begin Snames.Initialize; end SC_Obligations; diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 35eaa02fc..cafa9da99 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -20,6 +20,7 @@ with Ada.Containers; use Ada.Containers; with Ada.Containers.Doubly_Linked_Lists; +with Ada.Containers.Indefinite_Ordered_Maps; with Ada.Containers.Ordered_Maps; with Ada.Containers.Ordered_Sets; with Ada.Containers.Vectors; @@ -939,60 +940,55 @@ package SC_Obligations is -- mechanisms to let us track and eventually report how expanded SCOs -- connect to the original sources. + type SCO_PP_Kind is (In_Expansion, No_Expansion); + type Expansion_Info is record - Name : Unbounded_String; - Sloc : Slocs.Source_Location; + Macro_Name : Unbounded_String; + Sloc : Slocs.Source_Location; end record; package Expansion_Lists is new Ada.Containers.Doubly_Linked_Lists (Element_Type => Expansion_Info); - type PP_Info is record - Actual_Source_Range : Slocs.Source_Location_Range; - -- Refers to the source location of a SCO in the original (as opposed to - -- preprocessed) view of the source file. TODO??? remap this. + type PP_Info (Kind : SCO_PP_Kind := No_Expansion) is record + Actual_Source_Range : Slocs.Local_Source_Location_Range; + -- Refers to the source location of a SCO in the unpreprocessed view + -- of the source file. - Tokens_Source_Range : Slocs.Source_Location_Range; - -- Source location for the tokens representing this source coverage - -- obligation. Note that this source location refers to the - -- *preprocessed* view of the file when this is a macro expansion. + PP_Source_Range : Slocs.Local_Source_Location_Range; + -- Refer to a source location from the preprocessed version of the + -- source file, without accounting for preprocessor-inserted line + -- directives. Expansion_Stack : Expansion_Lists.List; - -- Chain of expansions + -- Empty if PP_Info.Kind = No_Expansion - Definition_Loc : Expansion_Info; - -- Location in the macro definition / file of the ultimate - -- expansion. + case Kind is + when In_Expansion => + Definition_Loc : Expansion_Info; + -- Location in the definition of the ultimate macro expansion + when others => + null; + end case; end record; -- Preprocessing information for SCOs. Hold basic information to enhance -- the report output with more precise messages. - package SCO_PP_Info_Maps is new Ada.Containers.Ordered_Maps + package SCO_PP_Info_Maps is new Ada.Containers.Indefinite_Ordered_Maps (Key_Type => SCO_Id, Element_Type => PP_Info); - procedure Add_Macro_Info (SCO : SCO_Id; Info : PP_Info) - with Pre => not Has_Macro_Info (SCO); - -- Add macro expansion information for the given SCO + procedure Add_PP_Info (SCO : SCO_Id; Info : PP_Info) + with Pre => not Has_PP_Info (SCO); + -- Add macro expansion information for the given SCO - procedure Add_Include_Info (SCO : SCO_Id; Info : PP_Info) - with Pre => not Has_Include_Info (SCO); - -- Add inclusion expansion information for the given SCO - - function Has_Macro_Info (SCO : SCO_Id) return Boolean; - -- Return whether the given SCO comes has preprocessing information - - function Has_Include_Info (SCO : SCO_Id) return Boolean; + function Has_PP_Info (SCO : SCO_Id) return Boolean; -- Return whether the given SCO comes has preprocessing information - function Get_Macro_Info (SCO : SCO_Id) return PP_Info - with Pre => Has_Macro_Info (SCO); - -- Return the macro expansion information (if any) for the given SCO - - function Get_Include_Info (SCO : SCO_Id) return PP_Info - with Pre => Has_Include_Info (SCO); - -- Return the macro expansion information (if any) for the given SCO + function Get_PP_Info (SCO : SCO_Id) return PP_Info + with Pre => Has_PP_Info (SCO); + -- Return the preprocessing information (if any) for the given SCO function Get_Scope_Entities (CU : CU_Id) return Scope_Entities_Trees.Tree; -- Return the scope entities for the given compilation unit From 2ff2a2a719e3c52f59418d196000f10f3f154716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Wed, 10 Sep 2025 16:46:20 +0200 Subject: [PATCH 1450/1483] Update U204-026-arch-mix artifacts following revert of !938 --- .../tests/U204-026-arch-mix/bin-main_1.trace | Bin 1508 -> 1508 bytes .../tests/U204-026-arch-mix/bin-main_2.trace | Bin 2580 -> 2580 bytes .../gen/arm-elf-linux/gcvrt-pz3791e32c.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68b.ads | 2 +- .../gen/arm-elf-linux/gcvrt-pz794ac68c.ads | 2 +- .../gen/arm-elf-linux/main_1.adb | 2 +- .../gen/arm-elf-linux/main_2.adb | 2 +- .../U204-026-arch-mix/gen/bin-main_1.ckpt | Bin 1831 -> 1831 bytes .../U204-026-arch-mix/gen/bin-main_2.ckpt | Bin 1841 -> 1841 bytes .../U204-026-arch-mix/gen/src-main_1.ckpt | Bin 2422 -> 2422 bytes .../U204-026-arch-mix/gen/src-main_2.ckpt | Bin 2353 -> 2353 bytes .../gen/x86_64-windows/gcvrt-pz3791e32c.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68b.ads | 2 +- .../gen/x86_64-windows/gcvrt-pz794ac68c.ads | 2 +- .../gen/x86_64-windows/main_1.adb | 2 +- .../gen/x86_64-windows/main_2.adb | 2 +- 16 files changed, 10 insertions(+), 10 deletions(-) diff --git a/testsuite/tests/U204-026-arch-mix/bin-main_1.trace b/testsuite/tests/U204-026-arch-mix/bin-main_1.trace index 8d65dbe4b94a5d8e0b66773112166929960175d1..601c5f5e5f703b67f96037fec79f0c6a88e57056 100644 GIT binary patch delta 71 zcmaFD{e*jh94jXmAA{gTWkq8H3kC*u1_lOUAT}~EGSxM()HO6vFf_3;Ft9Q-XW#&e Wa{;k}v4ydvsi}#%Im5>CTvh!~>KYm-7@Aob7+4vaPZnSo2LRk|3Pb<^ delta 37 tcmZ3^x14W-HXHj5+4gH;E>)9_*e>##>lzp<7+6}F8dw>cOcr1l2LS2q3b6nH diff --git a/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/bin-main_2.ckpt index efb763a2b70342f3e69ca18ff6a64400f66529b1..a13c938c3026b31c95c34a743937764abfdab448 100644 GIT binary patch delta 56 zcmdnUw~=pyF&jHW^s|SP+xjP4v0YZN)HO6vFf_9=Ft9STP|!9o0)AQ*e>lzp<7+6}F8dw>cDrg%RSs55GGC%-~1^~rY B3u6EP diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_1.ckpt index 309ed84ff45210f78dda60cbd59cb5d97dee8d76..1128b0dcb069362db5d38510b1fbdac0591f064e 100644 GIT binary patch delta 43 xcmew+^i60(I){9K$NP85kG@fY``P&!AjE!^ptM)WF=pXmT6J2LLd}44wc0 diff --git a/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt b/testsuite/tests/U204-026-arch-mix/gen/src-main_2.ckpt index 2b340c9cf09791bc5897a700b538781ba3eadf9f..12b59f154ea7328e830225b8232bb6a3f3b19a4c 100644 GIT binary patch delta 19 bcmdlev{7h7JO{f+{-pZJZT*weI8FlqN^S?? delta 19 acmdlev{7h7JO?{R&GD` Date: Tue, 9 Sep 2025 15:37:58 +0200 Subject: [PATCH 1451/1483] Gracefully error out upon PATH lookup failure We perform a PATH lookup of gnatcov to determine the installation prefix of gnatcov, and in select situations this can fail. This used to raise an exception during elaboration, it is now changed to emit a better error message. --- testsuite/tests/393-casing_crash/test.opt | 1 + testsuite/tests/393-casing_crash/test.py | 73 +++++++++++++++++++++++ tools/gnatcov/gnatcov.adb | 13 ++++ tools/gnatcov/support_files.ads | 21 +++++-- 4 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 testsuite/tests/393-casing_crash/test.opt create mode 100644 testsuite/tests/393-casing_crash/test.py diff --git a/testsuite/tests/393-casing_crash/test.opt b/testsuite/tests/393-casing_crash/test.opt new file mode 100644 index 000000000..b2beb5496 --- /dev/null +++ b/testsuite/tests/393-casing_crash/test.opt @@ -0,0 +1 @@ +!windows-host DEAD Test requires conditions only available on Windows, see #393 diff --git a/testsuite/tests/393-casing_crash/test.py b/testsuite/tests/393-casing_crash/test.py new file mode 100644 index 000000000..1d8f17931 --- /dev/null +++ b/testsuite/tests/393-casing_crash/test.py @@ -0,0 +1,73 @@ +""" +Check that gnatcov does not crash during elaboration when it fails to find +itself in PATH. + +This requires a fairly specific setup for both path lookup to work in the +terminal, but not from gnatcov. So far we have managed to do it by +- Being on a Windows system +- Having the gnatcov executable being in a case-sensitive directory +- Modifying the gnatcov.exe filename to change the case of the executable + suffix +- Invoking gnatcov without the executable suffix. + +This test aims to re-create these conditions, and thus removes some stuff from +the environment to make sure we have a the right conditions. +""" + +import os + +from e3.os.fs import which +from e3.fs import mkdir, cp + +from SUITE.context import thistest +from SUITE.cutils import Wdir, contents_of +from SUITE.tutils import run_and_log + + +tmp = Wdir("tmp_") + +# Create an empty directory in which we'll change the case sensitivity and +# butcher the gnatcov exec. +gnatcov_install = os.path.abspath("fake_gnatcov_bin") +mkdir(gnatcov_install) + +# Enable file sensitivity for the install dir. This needs to be done while the +# directory is empty. +run_and_log( + ["fsutil.exe", "file", "setCaseSensitiveInfo", gnatcov_install, "enable"] +) + +# Copy the gnatcov.exe program and change its executable suffix casing +cp(which("gnatcov.exe"), os.path.join(gnatcov_install, "gnatcov.EXE")) + +# Run gnatcov without anything on the environment to make sure we don't pick up +# the correctly installed gnatcov, not the GNATCOV_PREFIX env var which would +# bypass the path lookup check. We also go through a cmd indirection to avoid +# the path lookup that takes place in e3.os.process.Run. +# +# We also need gnatcov to be invoked without the exe prefix here as the os +# search should work, but the command name for gnatcov will still not have +# the exe suffix. +crash_log = "xcov.log" +p = run_and_log( + ["cmd", "/c", "gnatcov"], + env={"PATH": gnatcov_install}, + output=crash_log, + ignore_environ=True, +) + +thistest.fail_if( + p.status == 0, + comment="gnatcov did not exit with a failure status", +) + +thistest.fail_if_not_equal( + what="Unexpected error message from gnatcov", + expected="Could not locate the invoked gnatcov command: ." + " If gnatcov is installed on a case sensitive filesystem or directory," + " ensure the casing as the executable filename is used when invoking the" + " program.", + actual=contents_of(crash_log).strip(), +) + +thistest.result() diff --git a/tools/gnatcov/gnatcov.adb b/tools/gnatcov/gnatcov.adb index ebe229f3b..0daa1b637 100644 --- a/tools/gnatcov/gnatcov.adb +++ b/tools/gnatcov/gnatcov.adb @@ -31,6 +31,19 @@ with Switches; use Switches; procedure GNATcov is Use_Gnatcov64 : Boolean := False; begin + -- Check that gnatcov detected its own installation directory correctly + + if Support_Files.Gnatcov_Prefix = Support_Files.Not_Found then + Warning_Or_Error + ("Could not locate the invoked gnatcov command: " + & (if Command_Name /= "" then Command_Name else "") + & ". If gnatcov is installed on a case sensitive filesystem or" + & " directory, ensure the casing as the executable filename is" + & " used when invoking the program."); + Set_Exit_Status (Failure); + raise Xcov_Exit_Exc; + end if; + -- Parse arguments just enough to determine the target, then run the -- corresponding bits-specific main (see gnatcov_arch_specific.adb), -- forwarding all arguments as-is. diff --git a/tools/gnatcov/support_files.ads b/tools/gnatcov/support_files.ads index 3fce99eb6..70433e473 100644 --- a/tools/gnatcov/support_files.ads +++ b/tools/gnatcov/support_files.ads @@ -23,6 +23,7 @@ with Ada.Environment_Variables; use Ada.Environment_Variables; with GNAT.OS_Lib; package Support_Files is + use type GNAT.OS_Lib.String_Access; -- This package offers various helpers to locate support files in gnatcov's -- installation prefix. @@ -35,18 +36,30 @@ package Support_Files is -- Name of the environment variable which, when defined, provides the name -- of the "gnatcov" command that the user ran. + Not_Found : constant String := "GNATCOV_NOT_FOUND"; + -- Magic value propagated throughout the elaboration if we can't lookup + -- gnatcov on PATH. An error will be reported after elaboration completes. + Gnatcov_Command_Name : String := (if Value (Command_Name_Envvar, "") = "" then Command_Name else Value (Command_Name_Envvar)); - Gnatcov_Dir : constant String := Containing_Directory - (GNAT.OS_Lib.Locate_Exec_On_Path (Command_Name).all); - -- Directory that contains the current program + Gnatcov_Exec : constant GNAT.OS_Lib.String_Access := + GNAT.OS_Lib.Locate_Exec_On_Path (Command_Name); + + Gnatcov_Dir : constant String := + (if Gnatcov_Exec /= null + then Containing_Directory (Gnatcov_Exec.all) + else Not_Found); + -- Use a magic value when we can't locate gnatcov on path Gnatcov_Prefix : constant String := (if Value (Prefix_Envvar, "") = "" - then Containing_Directory (Gnatcov_Dir) + then + (if Gnatcov_Dir /= Not_Found + then Containing_Directory (Gnatcov_Dir) + else Not_Found) else Value (Prefix_Envvar)); -- Installation prefix for gnatcov From 495a57a8029e7c53aee934c2bf5f169a2f2c6b49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Thu, 18 Sep 2025 16:06:25 +0200 Subject: [PATCH 1452/1483] tests/393-casing_crash: XFail We cannot replicate the nightly testing failure in local testsing, nor on a telegraph machine, so XFailing while we investigate the issue. --- testsuite/tests/393-casing_crash/test.opt | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/tests/393-casing_crash/test.opt b/testsuite/tests/393-casing_crash/test.opt index b2beb5496..04e8015f3 100644 --- a/testsuite/tests/393-casing_crash/test.opt +++ b/testsuite/tests/393-casing_crash/test.opt @@ -1 +1,2 @@ !windows-host DEAD Test requires conditions only available on Windows, see #393 +all XFAIL Difference in config between prod and development setup, see #393 From c15844cbb9c86735b3edc5a9699b867fdab1f780 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 30 Jul 2025 14:53:07 +0200 Subject: [PATCH 1453/1483] sc_obligations: Add 'Assertion_Level' and 'Unsigned_Base_Range' pragmas (cherry picked from commit a98f528ec29198cce0ad129a2f4d5cfa7c0e78f7) --- tools/gnatcov/sc_obligations.ads | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index cafa9da99..38e8172d5 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -1059,6 +1059,7 @@ package SC_Obligations is Pragma_Annotate, Pragma_Assert, Pragma_Assert_And_Cut, + Pragma_Assertion_Level, Pragma_Assertion_Policy, Pragma_Assume, Pragma_Assume_No_Invalid_Values, @@ -1289,6 +1290,7 @@ package SC_Obligations is Pragma_Unreferenced, Pragma_Unreferenced_Objects, Pragma_Unreserve_All_Interrupts, + Pragma_Unsigned_Base_Range, Pragma_Unsuppress, Pragma_Unused, Pragma_Use_VADS_Size, @@ -1338,6 +1340,7 @@ package SC_Obligations is Pragma_Aggregate_Individually_Assign => False, Pragma_Allow_Integer_Address => False, Pragma_Annotate => False, + Pragma_Assertion_Level => False, Pragma_Assertion_Policy => False, Pragma_Assume_No_Invalid_Values => False, Pragma_C_Pass_By_Copy => False, @@ -1552,6 +1555,7 @@ package SC_Obligations is Pragma_Unreferenced => False, Pragma_Unreferenced_Objects => False, Pragma_Unreserve_All_Interrupts => False, + Pragma_Unsigned_Base_Range => False, Pragma_Unused => False, Pragma_Volatile => False, Pragma_Volatile_Components => False, From 5bb1cd5631e254fe93d78b1195395f6b35f47829 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Fri, 22 Aug 2025 12:53:00 +0000 Subject: [PATCH 1454/1483] Ada2022/aggregates/containers: remove XFAIL and fix cov expectations (cherry picked from commit 2a7ac2239d722cae384ce20d774169e1f552217d) --- testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb | 8 ++++---- testsuite/tests/Ada2022/aggregates/containers/src/pkg.ads | 2 +- .../tests/Ada2022/aggregates/containers/src/test_0.adb | 6 ++++-- .../Ada2022/aggregates/containers/src/test_empty.adb | 6 ++++-- .../tests/Ada2022/aggregates/containers/src/test_full.adb | 6 ++++-- .../Ada2022/aggregates/containers/src/test_multi.adb | 6 ++++-- .../Ada2022/aggregates/containers/src/test_single.adb | 6 ++++-- testsuite/tests/Ada2022/aggregates/containers/test.opt | 1 - 8 files changed, 25 insertions(+), 16 deletions(-) diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb index 233ebf474..dd2a70682 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb +++ b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.adb @@ -14,13 +14,13 @@ package body Pkg is declare Elt : constant Integer := Input.First_Element; -- # single_elt_st begin - return [(if Elt > 0 then Elt else Elt) => -- # single_elt_dc - (if Elt > 0 then Elt else Elt)]; -- # single_elt_dc + return [(if Elt > 0 then Elt else Elt) => -- # single_elt_dc1 + (if Elt > 0 then Elt else Elt)]; -- # single_elt_dc2 end; else return [for Elt of Input use -- # multi_elt_st - (if Elt > 0 then Elt else Elt) => -- # multi_elt_dc - (if Elt > 0 then Elt else Elt)]; -- # multi_elt_dc + (if Elt > 0 then Elt else Elt) => -- # multi_elt_dc1 + (if Elt > 0 then Elt else Elt)]; -- # multi_elt_dc2 end if; end Overly_Complex_Identity_Build; diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/pkg.ads b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.ads index d7f3a50c0..76532bfe6 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/src/pkg.ads +++ b/testsuite/tests/Ada2022/aggregates/containers/src/pkg.ads @@ -4,7 +4,7 @@ with Ada.Containers.Ordered_Sets; package Pkg is package Int_Maps is new Ada.Containers.Ordered_Maps - (Key_Type => Positive, Element_Type => Integer); + (Key_Type => Integer, Element_Type => Integer); subtype Int_Map is Int_Maps.Map; package Int_Sets is new Ada.Containers.Ordered_Sets diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_0.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_0.adb index a6a31f605..25b1472ad 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/src/test_0.adb +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_0.adb @@ -12,6 +12,8 @@ end Test_0; -- /empty_aggr_st/ l- ## s- -- /single_elt_guard/ l- ## s- -- /single_elt_st/ l- ## s- --- /single_elt_dc/ l- ## 0 +-- /single_elt_dc1/ l- ## s- +-- /single_elt_dc2/ l- ## 0 -- /multi_elt_st/ l- ## s- --- /multi_elt_dc/ l- ## 0 +-- /multi_elt_dc1/ l- ## 0 +-- /multi_elt_dc2/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb index 100c9db9e..37b96acfd 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_empty.adb @@ -15,6 +15,8 @@ end Test_Empty; -- /empty_aggr_st/ l+ ## 0 -- /single_elt_guard/ l- ## s- -- /single_elt_st/ l- ## s- --- /single_elt_dc/ l- ## 0 +-- /single_elt_dc1/ l- ## s- +-- /single_elt_dc2/ l- ## 0 -- /multi_elt_st/ l- ## s- --- /multi_elt_dc/ l- ## 0 +-- /multi_elt_dc1/ l- ## 0 +-- /multi_elt_dc2/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_full.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_full.adb index 32c7bafb0..1b412544f 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/src/test_full.adb +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_full.adb @@ -18,6 +18,8 @@ end Test_Full; -- /empty_aggr_st/ l+ ## 0 -- /single_elt_guard/ l+ ## 0 -- /single_elt_st/ l+ ## 0 --- /single_elt_dc/ l+ ## 0 +-- /single_elt_dc1/ l+ ## 0 +-- /single_elt_dc2/ l+ ## 0 -- /multi_elt_st/ l+ ## 0 --- /multi_elt_dc/ l+ ## 0 +-- /multi_elt_dc1/ l+ ## 0 +-- /multi_elt_dc2/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_multi.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_multi.adb index 8295232c9..51bc3837f 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/src/test_multi.adb +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_multi.adb @@ -15,6 +15,8 @@ end Test_Multi; -- /empty_aggr_st/ l- ## s- -- /single_elt_guard/ l! ## dT- -- /single_elt_st/ l- ## s- --- /single_elt_dc/ l- ## 0 +-- /single_elt_dc1/ l- ## s- +-- /single_elt_dc2/ l- ## 0 -- /multi_elt_st/ l+ ## 0 --- /multi_elt_dc/ l+ ## 0 +-- /multi_elt_dc1/ l+ ## 0 +-- /multi_elt_dc2/ l+ ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/src/test_single.adb b/testsuite/tests/Ada2022/aggregates/containers/src/test_single.adb index e19d5bf80..d281efa3e 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/src/test_single.adb +++ b/testsuite/tests/Ada2022/aggregates/containers/src/test_single.adb @@ -15,6 +15,8 @@ end Test_Single; -- /empty_aggr_st/ l- ## s- -- /single_elt_guard/ l! ## dF- -- /single_elt_st/ l+ ## 0 --- /single_elt_dc/ l! ## dF- +-- /single_elt_dc1/ l! ## dF- +-- /single_elt_dc2/ l! ## dF- -- /multi_elt_st/ l- ## s- --- /multi_elt_dc/ l- ## 0 +-- /multi_elt_dc1/ l- ## 0 +-- /multi_elt_dc2/ l- ## 0 diff --git a/testsuite/tests/Ada2022/aggregates/containers/test.opt b/testsuite/tests/Ada2022/aggregates/containers/test.opt index 84bd4b77f..1ae7db54d 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/test.opt +++ b/testsuite/tests/Ada2022/aggregates/containers/test.opt @@ -1,2 +1 @@ RTS_ZFP DEAD Test instantiates containers -!RTS_ZFP XFAIL Compiler crash (eng/toolchain/gnat#1543) From 04be133e079c044731e70a41bf1f7aa3cd149288 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Wed, 27 Aug 2025 13:10:47 +0000 Subject: [PATCH 1455/1483] Disable the new GPR2 warning when compiler drivers are missing gnatcov already takes care of emitting fatal errors in that case, so the new warning only adds noise: disable it (like all GPR tools seem to do anyway...). (cherry picked from commit 73666361332d853cd1dfa163b1a2711ef4b06cc3) --- tools/gnatcov/project.adb | 3 ++- tools/gnatcov/setup_rts.adb | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/gnatcov/project.adb b/tools/gnatcov/project.adb index 396ad1ba2..e1e5d6a95 100644 --- a/tools/gnatcov/project.adb +++ b/tools/gnatcov/project.adb @@ -1312,7 +1312,8 @@ package body Project is With_Runtime => True, Reporter => Create_Reporter, Artifacts_Info_Level => GPR2.Sources_Units, - Absent_Dir_Error => GPR2.No_Error) + Absent_Dir_Error => GPR2.No_Error, + Check_Drivers => False) then Fatal_Error ("Could not load the project file, aborting."); end if; diff --git a/tools/gnatcov/setup_rts.adb b/tools/gnatcov/setup_rts.adb index a545b9c62..5abb5d74d 100644 --- a/tools/gnatcov/setup_rts.adb +++ b/tools/gnatcov/setup_rts.adb @@ -237,7 +237,8 @@ package body Setup_RTS is then GPR2.Reporter.Regular else GPR2.Reporter.No_Warnings)), With_Runtime => True, - Absent_Dir_Error => GPR2.No_Error); + Absent_Dir_Error => GPR2.No_Error, + Check_Drivers => False); end Load_Project; ----------- From e999e9fe80edee9774d926ba5997da0a1c428539 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Thu, 28 Aug 2025 12:24:16 +0000 Subject: [PATCH 1456/1483] Ada2022/aggregates/containers: kill on QNX and with embedded-* runtimes The `Ada.Containers` runtime package hierarchy does not seem to be in a working state on cross targets, so kill this testcase on the remaining non-native configurations. (cherry picked from commit 655eecc2bb9105c86ad1d7c3e78f96f4fbaf510b) --- testsuite/tests/Ada2022/aggregates/containers/test.opt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/Ada2022/aggregates/containers/test.opt b/testsuite/tests/Ada2022/aggregates/containers/test.opt index 1ae7db54d..34e52284f 100644 --- a/testsuite/tests/Ada2022/aggregates/containers/test.opt +++ b/testsuite/tests/Ada2022/aggregates/containers/test.opt @@ -1 +1 @@ -RTS_ZFP DEAD Test instantiates containers +!native DEAD Test instantiates containers From fc616c81d684dc2d12ba9acd4a90bc04c7823d7b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 2 Sep 2025 15:34:53 +0200 Subject: [PATCH 1457/1483] SS_Annotations: Change default backend for C/C++ sources Stable_Sloc now offers a backend that can remap regions defined within a declaration for C & C++ sources. Use this backend by default for these languages. (cherry picked from commit 78e9c472d92912ccb66a662941666dbdbf1c84f5) --- .../ext_annotations/gen/invalidation/show_expected.txt | 2 +- tools/gnatcov/ss_annotations.adb | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/testsuite/tests/ext_annotations/gen/invalidation/show_expected.txt b/testsuite/tests/ext_annotations/gen/invalidation/show_expected.txt index aae5b772a..714f23df4 100644 --- a/testsuite/tests/ext_annotations/gen/invalidation/show_expected.txt +++ b/testsuite/tests/ext_annotations/gen/invalidation/show_expected.txt @@ -3,4 +3,4 @@ main.adb: - STALE ANNOTATION; id: exempt_ada; kind: Exempt_Region; Justification: Useless code; diagnostic: Contents of changed main_c.c: -- STALE ANNOTATION; id: exempt_c; kind: Exempt_Region; Justification: Useless code; diagnostic: file has been modified +- STALE ANNOTATION; id: exempt_c; kind: Exempt_Region; Justification: Useless code; diagnostic: Content of declaration ident has changed diff --git a/tools/gnatcov/ss_annotations.adb b/tools/gnatcov/ss_annotations.adb index 43be452d3..b94b71d53 100644 --- a/tools/gnatcov/ss_annotations.adb +++ b/tools/gnatcov/ss_annotations.adb @@ -940,10 +940,13 @@ package body SS_Annotations is case Language is when Ada_Language => SS_Backend := +"lal_context"; - -- Stable_Sloc is missing a stable backend for C/C++, so default - -- to an absolute entry. + when C_Language | CPP_Language => SS_Backend := +"clang_context"; + + when All_Languages => + + -- This should not hit but maybe with rust coverage we may + -- hit this? - when All_Languages | C_Language | CPP_Language => SS_Backend := +"absolute"; end case; end if; From 4f7931c3fe2b6ce0d6854aae0ac43ad9ff841f0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 2 Sep 2025 17:18:41 +0200 Subject: [PATCH 1458/1483] SS_Annotations: Add fallback mechanism when an annotation cannot be generated Some Stable_Sloc backends can fail to generate an annotation, e.g. when part of the designated location span lies outside of a library item in Ada sources, or outside of any declaration in C/C++. In such cases, generate an absolute matcher annotation instead. (cherry picked from commit e23dda13038345c17ad0f4a4a39e8a432c713e6d) --- .../ext_annotations/gen/c_ex/Nominal/test.py | 9 ++- tools/gnatcov/ss_annotations.adb | 67 +++++++++++++++++-- 2 files changed, 68 insertions(+), 8 deletions(-) diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py index 7952ccf62..4c4fafbea 100644 --- a/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py +++ b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py @@ -28,7 +28,14 @@ ), ] -annot_file = generate_annotations(annotations) +annot_file = generate_annotations( + annotations, + tolerate_messages=( + "warning: Could not create an auto-relocating annotation for src/" + "pkg.c:6:4 - 12:22, creating an absolute location annotation instead." + ), +) + # Check we get the expected results TestCase(category=CAT.mcdc).run( diff --git a/tools/gnatcov/ss_annotations.adb b/tools/gnatcov/ss_annotations.adb index b94b71d53..767d18013 100644 --- a/tools/gnatcov/ss_annotations.adb +++ b/tools/gnatcov/ss_annotations.adb @@ -167,6 +167,10 @@ package body SS_Annotations is -- Helper for the above procedure, validate a single entry, if it is ok -- then copy it in Valid_Annotation_DB, otherwise emit a warning. + procedure Check_New_Entry_Diags (Diags : Load_Diagnostic_Arr); + -- Check if Diags is empty, and if not error out while displaying the + -- diagnostics. + --------------------- -- Annotation_Kind -- --------------------- @@ -1009,6 +1013,7 @@ package body SS_Annotations is end if; declare + Target_Span : constant Sloc_Span := (+Start_Sloc, +End_Sloc); Diags : constant Load_Diagnostic_Arr := Add_Or_Update_Entry (DB => New_Annot_DB, @@ -1016,16 +1021,49 @@ package body SS_Annotations is Annotation => Annotation, Kind => SS_Backend, File => Target_File, - Span => (+Start_Sloc, +End_Sloc), + Span => Target_Span, File_Prefix => File_Prefix); begin - if Diags'Length /= 0 then - Outputs.Error ("Error while generating annotation:"); - for Diag of Diags loop - Outputs.Error (Format_Diagnostic (Diag)); - end loop; - raise Xcov_Exit_Exc; + -- Do not fallback if we have an explicit backend specified on + -- command line, or if the backend is already "absolute" + + if Diags'Length /= 0 + and then SS_Backend /= "absolute" + and then not Args.String_Args (Opt_SS_Backend).Present + then + -- Try again, but with the "absolute" backend. If that fails do + -- not log a warning about the first attempt. + + declare + Msg : Unbounded_String := + +("Could not create an auto-relocating annotation for " + & Target_File.Display_Full_Name & ":" & Image (Target_Span) + & ", creating an absolute location annotation instead."); + Abs_Diags : constant Load_Diagnostic_Arr := + Add_Or_Update_Entry + (DB => New_Annot_DB, + Identifier => Entry_Id, + Annotation => Annotation, + Kind => +"absolute", + File => Target_File, + Span => Target_Span, + File_Prefix => File_Prefix); + begin + Check_New_Entry_Diags (Abs_Diags); + + if Ext_Annotation_Trace.Is_Active then + Msg := Msg & (ASCII.LF & "Error was: "); + + for Diag of Diags loop + Msg := Msg & (ASCII.LF & Format_Diagnostic (Diag)); + end loop; + end if; + Warn (+Msg); + end; + else + Check_New_Entry_Diags (Diags); end if; + end; -- Check if there already is an entry with the same identifier in the @@ -1390,4 +1428,19 @@ package body SS_Annotations is end if; end Validate_Annotation; + --------------------------- + -- Check_New_Entry_Diags -- + --------------------------- + + procedure Check_New_Entry_Diags (Diags : Load_Diagnostic_Arr) is + begin + if Diags'Length /= 0 then + Outputs.Error ("Error while generating annotation:"); + for Diag of Diags loop + Outputs.Error (Format_Diagnostic (Diag)); + end loop; + raise Xcov_Exit_Exc; + end if; + end Check_New_Entry_Diags; + end SS_Annotations; From fcf300c361e7464df20b2fb59fc74c73171620c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Tue, 2 Sep 2025 17:26:37 +0200 Subject: [PATCH 1459/1483] Doc: Update documentation to reflect current capabilities. (cherry picked from commit aa98ca919c2c7d9de9b27f78adef7f90ceaf4690) --- doc/gnatcov/external_annotations.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/doc/gnatcov/external_annotations.rst b/doc/gnatcov/external_annotations.rst index 4ca33393d..0c83b984c 100644 --- a/doc/gnatcov/external_annotations.rst +++ b/doc/gnatcov/external_annotations.rst @@ -378,8 +378,14 @@ This depends mainly on the language of the file to be annotated: of that construct the annotation will be remapped properly. If the enclosing construct is modified, the annotation will be invalidated. -- For C sources, the annotations are currently not stable through modifications. - Any modification to the annotated source file will invalidate the annotations. +- For Cor C++ sources, the annotations are tied to the inner-most enclosing + named declaration, such as a function declaration for C, or any of a + namespace declaration, a class declaration or function/method declaration for + C++. + +Note that in both cases, if no enclosing named construct can be found, the +|gcvaddan| command will emit a warning and fall back to an absolute annotation, +which is invalidated as soon as the file is modified. If an annotation is invalidated gnatcov will emit a warning stating that the annotation was ignored, along with its unique identifier. From bf68c239b96ef43105ffc4cc8816bae400ac16ec Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 15 Sep 2025 15:25:33 +0000 Subject: [PATCH 1460/1483] Sc_Obligations: rename Unknown_Pragma to Pragma_Unknown (cherry picked from commit 81aa03841cbf4c2797c43d1ddf37bd45d857753b) --- tools/gnatcov/sc_obligations.adb | 4 ++-- tools/gnatcov/sc_obligations.ads | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/gnatcov/sc_obligations.adb b/tools/gnatcov/sc_obligations.adb index 12118dee2..fc9b08205 100644 --- a/tools/gnatcov/sc_obligations.adb +++ b/tools/gnatcov/sc_obligations.adb @@ -7145,7 +7145,7 @@ package body SC_Obligations is is begin if Pragma_Name = No_Name then - return Unknown_Pragma; + return Pragma_Unknown; end if; -- Retrieve the pragma name as a string @@ -7164,7 +7164,7 @@ package body SC_Obligations is return Pragma_Id'Value (Enum_Name); exception when Constraint_Error => - return Unknown_Pragma; + return Pragma_Unknown; end; end Case_Insensitive_Get_Pragma_Id; diff --git a/tools/gnatcov/sc_obligations.ads b/tools/gnatcov/sc_obligations.ads index 38e8172d5..af5a4278f 100644 --- a/tools/gnatcov/sc_obligations.ads +++ b/tools/gnatcov/sc_obligations.ads @@ -1304,8 +1304,8 @@ package SC_Obligations is Pragma_Warnings, Pragma_Weak_External, Pragma_Wide_Character_Encoding, - Unknown_Pragma); - -- Set of pragmas that GNATcoverage knows (or Unknown_Pragma if not) + Pragma_Unknown); + -- Set of pragmas that GNATcoverage knows (or Pragma_Unknown if not) function Case_Insensitive_Get_Pragma_Id (Pragma_Name : Namet.Name_Id) return Pragma_Id; @@ -1619,7 +1619,7 @@ package SC_Obligations is Pragma_Type_Invariant => True, Pragma_Type_Invariant_Class => True, - Unknown_Pragma => True); + Pragma_Unknown => True); procedure Populate_From_Static_Eval_Vector (SCO : SCO_Id; From bc964b33f3fcd960324cb3001bda6478e0c53269 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 22 Sep 2025 11:46:30 +0200 Subject: [PATCH 1461/1483] gnatcov doc: clarify how to use --src-subdirs --- doc/gnatcov/src_traces.rst | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/doc/gnatcov/src_traces.rst b/doc/gnatcov/src_traces.rst index 87f8acf93..1b87cfd9e 100644 --- a/doc/gnatcov/src_traces.rst +++ b/doc/gnatcov/src_traces.rst @@ -768,10 +768,12 @@ reuse of a project hierarchy without replication of the directory structure, not even modification of the project files. For each project in the closure of-interest, the instrumentation generates the -alternative sources in the ``gnatcov-instr`` subdirectory of the project's -object directory. Giving priority to this subdir when it exists is achieved by -passing a :cmd-option:`--src-subdirs` switch to :command:`gprbuild`, naming -that particular relative subdirectory. +alternative sources in the ``PROJECT-gnatcov-instr`` subdirectory of the +project's object directory (replace ``PROJECT`` with the lower cased actual +name of the project: e.g. ``mylib-gnatcov-instr`` for ``mylib.gpr``). Giving +priority to this subdir when it exists is achieved by passing a +:cmd-option:`--src-subdirs` switch to :command:`gprbuild`, naming that +particular relative subdirectory. Then :command:`gprbuild` now supports a :cmd-option:`--implicit-with` option which requests processing every project as if it started with a ``with`` From 8114a3a5516813da011779fac7b5e00464b266da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 29 Sep 2025 16:28:07 +0200 Subject: [PATCH 1462/1483] gnatcov.adb: Fix indendation Tabs were used instead of spaces, which breaks some style checks --- tools/gnatcov/gnatcov.adb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tools/gnatcov/gnatcov.adb b/tools/gnatcov/gnatcov.adb index 0daa1b637..4ed1a14e1 100644 --- a/tools/gnatcov/gnatcov.adb +++ b/tools/gnatcov/gnatcov.adb @@ -36,10 +36,10 @@ begin if Support_Files.Gnatcov_Prefix = Support_Files.Not_Found then Warning_Or_Error ("Could not locate the invoked gnatcov command: " - & (if Command_Name /= "" then Command_Name else "") - & ". If gnatcov is installed on a case sensitive filesystem or" - & " directory, ensure the casing as the executable filename is" - & " used when invoking the program."); + & (if Command_Name /= "" then Command_Name else "") + & ". If gnatcov is installed on a case sensitive filesystem or" + & " directory, ensure the casing as the executable filename is" + & " used when invoking the program."); Set_Exit_Status (Failure); raise Xcov_Exit_Exc; end if; From f20ce3ab3d6375e88d29c20e050af830a0ca72ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Creuse?= Date: Mon, 29 Sep 2025 16:31:23 +0200 Subject: [PATCH 1463/1483] Fix regexp in external annotation test The external annotation test for C generates a warning containing a path component, which can become a backslash on Windows. This change ensures the expected message can match on both hosts. --- testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py index 4c4fafbea..00f693d55 100644 --- a/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py +++ b/testsuite/tests/ext_annotations/gen/c_ex/Nominal/test.py @@ -31,7 +31,7 @@ annot_file = generate_annotations( annotations, tolerate_messages=( - "warning: Could not create an auto-relocating annotation for src/" + r"warning: Could not create an auto-relocating annotation for src." "pkg.c:6:4 - 12:22, creating an absolute location annotation instead." ), ) From 66508d5a5917c4e5c354800ec3fd86a22b60b8af Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Wed, 30 Jul 2025 17:02:45 +0200 Subject: [PATCH 1464/1483] pre-commit: Add a gnatformat job --- .pre-commit-config.yaml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c4c7640e1..e327ac177 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,8 +16,7 @@ repos: SpacesInLineCommentPrefix: { Minimum: 0, Maximum: -1 - } - }"] + }}"] - repo: https://github.com/pycqa/flake8 rev: 7.1.1 hooks: @@ -40,3 +39,12 @@ repos: entry: python .check-formatting.py language: system args: ["--autofix", "--ignore-non-source"] + - repo: local + hooks: + - id: gnatformat + name: Run gnatformat + entry: gnatformat + args: ["--no-project"] + language: system + files: "^tools/gnatcov/.*\\.ad(b|s)$" + From b80cb43f3098d78a4ab586df663634b911df79e7 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 31 Jul 2025 11:47:09 +0200 Subject: [PATCH 1465/1483] run gnatformat in CI --- .gitlab-ci.yml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 1967c666c..ec9736830 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,11 +6,24 @@ workflow: variables: PACKAGE_BASE_NAME: gnatcoverage.tar.gz PACKAGE_ABSOLUTE_NAME: $CI_PROJECT_DIR/$PACKAGE_BASE_NAME + GNATFORMAT_DATE: 20250917 include: - component: $CI_SERVER_FQDN/eng/gitlab-templates/pre-commit@~latest inputs: - stage: test + stage: check + # Do not run gnatformat in pre-commit as it is missing from the environment. + # A specific CI job is used instead. + pre-commit-skip: "gnatformat" + + - component: $CI_SERVER_FQDN/eng/gitlab-templates/gnatformat@~latest + inputs: + stage: check + anod-spec: gnatcov + gnatformat-args: --no-project --check $(find tools/gnatcov -iname '*.ad[bs]') + install-gnatformat: true + install-gnatformat-extra-anod-args: -Qedge -Qdate=$GNATFORMAT_DATE + #TODO: workaround to allow dynamically setting the interruptible policy until https://gitlab.com/gitlab-org/gitlab/-/issues/194023 is implemented - local: utils/ci/interruptible.yml rules: @@ -206,6 +219,9 @@ test_spark: <<: *artifacts +########## +# Checks # +########## pre-commit: before_script: @@ -214,6 +230,7 @@ pre-commit: # Install the clang-format executable and make it available - anod install libclang -Qstable - eval `anod printenv libclang -Qstable` + ################# # Optional jobs # ################# From 9b221a6a55e90e11fbc9219b8d6e65f81ca2fe49 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 28 Aug 2025 15:38:07 +0200 Subject: [PATCH 1466/1483] gnatformat: format ada-rts/, rts/, trace_adapters/, examples/ --- .../ada-rts/gnatcov_rts-buffers-lists.adb | 8 +- tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb | 3 +- tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads | 10 +- .../gnatcov_rts-traces-output-base64.adb | 34 ++-- .../ada-rts/gnatcov_rts-traces-output.adb | 40 ++-- .../ada-rts/gnatcov_rts-traces-output.ads | 8 +- tools/gnatcov/ada-rts/gnatcov_rts-traces.ads | 33 ++- tools/gnatcov/ada-rts/gnatcov_rts-types.ads | 6 +- .../harness/fixture/geomaps-test-suite.adb | 6 +- .../harness/fixture/geomaps-test-suite.ads | 2 +- .../fixture/links-gen_test-gen_suite.adb | 41 ++-- .../fixture/links-gen_test-gen_suite.ads | 23 ++- .../harness/fixture/main_suite.adb | 15 +- .../harness/fixture/robots-test-suite.adb | 10 +- .../harness/fixture/robots-test-suite.ads | 8 +- .../harness/fixture/stations-test-suite.adb | 7 +- .../harness/fixture/stations-test-suite.ads | 5 +- .../aunit_variant/harness/old/test_ports.adb | 4 +- .../harness/tests/controls-test.ads | 11 +- .../harness/tests/geomaps-test.adb | 7 +- .../harness/tests/geomaps-test.ads | 17 +- .../harness/tests/links-gen_test.adb | 192 +++++++++--------- .../harness/tests/links-gen_test.ads | 21 +- .../harness/tests/robots-test.adb | 122 ++++++----- .../harness/tests/robots-test.ads | 12 +- .../harness/tests/stations-test.adb | 15 +- .../examples/aunit_variant/src/explore.adb | 16 +- .../examples/aunit_variant/src/geomaps.adb | 16 +- .../examples/aunit_variant/src/links.adb | 6 +- .../examples/aunit_variant/src/links.ads | 4 +- .../examples/aunit_variant/src/queues.ads | 4 +- .../examples/aunit_variant/src/robots.adb | 23 +-- .../examples/aunit_variant/src/robots.ads | 4 +- .../src/robots_devices-dummy.adb | 16 +- .../src/robots_devices-dummy.ads | 6 +- .../aunit_variant/src/robots_devices.ads | 14 +- .../examples/aunit_variant/src/stations.adb | 21 +- .../examples/aunit_variant/src/stations.ads | 2 +- .../doc/cross_example/src/monitor.adb | 2 +- .../doc/cross_example/src/sensors.adb | 15 +- .../doc/custom_rt/stateful_io/stateful_io.adb | 4 +- .../doc/getting_started/opslib/ops.adb | 7 +- .../examples/doc/library_instr/code/ops.adb | 7 +- .../examples/doc/subunits/src/run_all.adb | 1 + .../mcdc_checkpoints/src/test_stable.adb | 3 +- .../mcdc_checkpoints/src/test_unstable_p.adb | 3 +- .../mcdc_checkpoints/src/test_unstable_t.adb | 3 +- .../spark_instrumentation/src/foo.adb | 9 +- .../spark_instrumentation/src/foo.ads | 2 +- .../support/lch/silent_last_chance-exit.adb | 2 +- .../support/lch/silent_last_chance.ads | 7 +- .../simple_last_chance_handler.ads | 7 +- .../support/src/helpers/simple_pools.adb | 2 +- .../examples/support/src/helpers/support.adb | 1 - .../examples/support/src/helpers/support.ads | 1 - .../simple_last_chance_handler.ads | 7 +- .../simple_last_chance_handler.ads | 7 +- .../simple_last_chance_handler.ads | 7 +- .../support/src/memory/libsupport-memory.ads | 2 +- tools/gnatcov/examples/xml/src/services.ads | 4 +- tools/gnatcov/libopcodes_bind/dis_opcodes.ads | 94 +++++---- .../gnatcov/rts/gnatcov_rts-buffers-lists.adb | 3 +- tools/gnatcov/rts/gnatcov_rts-buffers.adb | 6 +- tools/gnatcov/rts/gnatcov_rts-buffers.ads | 18 +- .../rts/gnatcov_rts-traces-output-base64.adb | 4 +- .../rts/gnatcov_rts-traces-output-base64.ads | 3 +- .../rts/gnatcov_rts-traces-output-files.adb | 27 +-- .../rts/gnatcov_rts-traces-output-files.ads | 8 +- tools/gnatcov/rts/gnatcov_rts-types.ads | 6 +- .../trace32/instructions_info.adb | 53 +++-- .../trace32/instructions_info.ads | 29 +-- .../trace32/trace32-branchflow.adb | 39 ++-- .../trace32/trace32-branchflow.ads | 37 ++-- .../trace32/trace32-conversion.adb | 65 +++--- .../trace_adapters/trace32/trace32_drv.adb | 48 +++-- .../trace_adapters/trace32/trace_output.adb | 97 ++++----- .../trace_adapters/trace32/trace_output.ads | 41 ++-- 77 files changed, 724 insertions(+), 749 deletions(-) diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.adb b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.adb index 71821e96f..b1df4896f 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.adb +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers-lists.adb @@ -84,8 +84,8 @@ package body GNATcov_RTS.Buffers.Lists is return; end if; declare - Buffers_Group : Coverage_Buffers_Group - (1 .. Integer (C_Buffers_Group.Length)); + Buffers_Group : + Coverage_Buffers_Group (1 .. Integer (C_Buffers_Group.Length)); pragma Import (C, Buffers_Group); for Buffers_Group'Address use C_Buffers_Group.Buffers; begin @@ -102,8 +102,8 @@ package body GNATcov_RTS.Buffers.Lists is procedure Reset_Group_Array_Buffers (Arr : GNATcov_RTS_Coverage_Buffers_Group_Array) is - Buffers_Groups : Coverage_Buffers_Group_Array - (1 .. Integer (Arr.Length)); + Buffers_Groups : + Coverage_Buffers_Group_Array (1 .. Integer (Arr.Length)); pragma Import (C, Buffers_Groups); for Buffers_Groups'Address use Arr.Groups; begin diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb index 2d47e87ec..c6e607d4e 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.adb @@ -47,8 +47,7 @@ package body GNATcov_RTS.Buffers is end Witness; function Witness - (Buffer_Address : System.Address; Bit : Bit_Id) return Boolean - is + (Buffer_Address : System.Address; Bit : Bit_Id) return Boolean is begin Witness (Buffer_Address, Bit); return False; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads index fdc040a52..4801a6c61 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-buffers.ads @@ -100,12 +100,12 @@ package GNATcov_RTS.Buffers is -- "foo.c". Bit_Maps_Fingerprint : Fingerprint_Type; - -- Hash of buffer bit mappings for this unit, as gnatcov computes it - -- (see SC_Obligations). Used as a fast way to check that gnatcov will - -- be able to interpret buffer bits from a source traces using buffer - -- bit mappings from SID files. + -- Hash of buffer bit mappings for this unit, as gnatcov computes it + -- (see SC_Obligations). Used as a fast way to check that gnatcov will + -- be able to interpret buffer bits from a source traces using buffer + -- bit mappings from SID files. - Annotations_Fingerprint : Fingerprint_Type; + Annotations_Fingerprint : Fingerprint_Type; -- Hash of annotations for this unit, as gnatcov computes it (see -- SC_Obligations). Used as a fast way to check that source traces and -- coverage data are consistent. diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb index b409cf657..deab9df34 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output-base64.adb @@ -32,13 +32,13 @@ package body GNATcov_RTS.Traces.Output.Base64 is -- Base64-over-stdout stream - type Uint6 is mod 2 ** 6; + type Uint6 is mod 2**6; Base64_Alphabet : constant array (Uint6) of Character := - "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - & "abcdefghijklmnopqrstuvwxyz" - & "0123456789" - & "+/"; - Base64_Padding : constant Character := '='; + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + & "abcdefghijklmnopqrstuvwxyz" + & "0123456789" + & "+/"; + Base64_Padding : constant Character := '='; type Base64_Buffer_Index is range 1 .. 4; subtype Valid_Base64_Buffer_Index is Base64_Buffer_Index range 1 .. 3; @@ -59,8 +59,7 @@ package body GNATcov_RTS.Traces.Output.Base64 is -- break lines at 80 digits. end record; - procedure Write_Bytes - (Output : in out Base64_Buffer; Bytes : Uint8_Array); + procedure Write_Bytes (Output : in out Base64_Buffer; Bytes : Uint8_Array); -- Callback for Generic_Write_Trace_File procedure Flush (Output : in out Base64_Buffer); @@ -72,8 +71,7 @@ package body GNATcov_RTS.Traces.Output.Base64 is -- Write_Bytes -- ----------------- - procedure Write_Bytes - (Output : in out Base64_Buffer; Bytes : Uint8_Array) + procedure Write_Bytes (Output : in out Base64_Buffer; Bytes : Uint8_Array) is begin for I in Bytes'Range loop @@ -120,17 +118,17 @@ package body GNATcov_RTS.Traces.Output.Base64 is when 3 => Out_Digits (1) := +Uint6 (In_Bytes (1) / 4); - Out_Digits (2) := +(Uint6 (In_Bytes (1) mod 4) * 16 - or Uint6 (In_Bytes (2) / 16)); + Out_Digits (2) := + +(Uint6 (In_Bytes (1) mod 4) * 16 or Uint6 (In_Bytes (2) / 16)); Out_Digits (3) := +(Uint6 (In_Bytes (2) mod 16) * 4); Out_Digits (4) := Base64_Padding; when 4 => Out_Digits (1) := +Uint6 (In_Bytes (1) / 4); - Out_Digits (2) := +(Uint6 (In_Bytes (1) mod 4) * 16 - or Uint6 (In_Bytes (2) / 16)); - Out_Digits (3) := +(Uint6 (In_Bytes (2) mod 16) * 4 - or Uint6 (In_Bytes (3) / 64)); + Out_Digits (2) := + +(Uint6 (In_Bytes (1) mod 4) * 16 or Uint6 (In_Bytes (2) / 16)); + Out_Digits (3) := + +(Uint6 (In_Bytes (2) mod 16) * 4 or Uint6 (In_Bytes (3) / 64)); Out_Digits (4) := +(Uint6 (In_Bytes (3) mod 64)); end case; @@ -161,9 +159,7 @@ package body GNATcov_RTS.Traces.Output.Base64 is is procedure Helper is new Generic_Write_Trace_File (Base64_Buffer); Buffer : Base64_Buffer := - (Bytes => (others => 0), - Next => 1, - Columns => 0); + (Bytes => (others => 0), Next => 1, Columns => 0); begin TIO.New_Line; TIO.Put_Line ("== GNATcoverage source trace file =="); diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb index 9e467febf..f74eccc13 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.adb @@ -50,9 +50,8 @@ package body GNATcov_RTS.Traces.Output is generic type T is mod <>; - with function Shift_Right - (Value : T; - Amount : Natural) return T is <>; + with + function Shift_Right (Value : T; Amount : Natural) return T is <>; procedure Write_Unsigned (Output : in out Output_Stream; U : T); -- Generic implementation for Write_U8, Write_U16 and Write_U32. -- Write the bytes in little-endian order. @@ -71,7 +70,8 @@ package body GNATcov_RTS.Traces.Output is -- Write a trace info entry to Output procedure Write_Entry - (Output : in out Output_Stream; Buffers : GNATcov_RTS_Coverage_Buffers); + (Output : in out Output_Stream; + Buffers : GNATcov_RTS_Coverage_Buffers); -- Write a whole trace entry (header, unit name and buffers) for Buffers -- to Output. @@ -117,7 +117,7 @@ package body GNATcov_RTS.Traces.Output is procedure Write_Padding (Output : in out Output_Stream; Count : Natural) is Alignment : constant Natural := - Natural (Generic_Write_Trace_File.Alignment); + Natural (Generic_Write_Trace_File.Alignment); Pad_Count : constant Natural := Alignment - Count mod Alignment; begin if Pad_Count /= Alignment then @@ -135,10 +135,9 @@ package body GNATcov_RTS.Traces.Output is -- Write_Header -- ------------------ - procedure Write_Header (Output : in out Output_Stream) - is - Trace_File_Magic_Bytes : constant Uint8_Array - (1 .. Trace_File_Magic'Length); + procedure Write_Header (Output : in out Output_Stream) is + Trace_File_Magic_Bytes : + constant Uint8_Array (1 .. Trace_File_Magic'Length); for Trace_File_Magic_Bytes'Address use Trace_File_Magic'Address; pragma Import (Ada, Trace_File_Magic_Bytes); begin @@ -179,15 +178,14 @@ package body GNATcov_RTS.Traces.Output is procedure Write_Entry (Output : in out Output_Stream; Buffers : GNATcov_RTS_Coverage_Buffers) is - Unit_Name_Bytes : Uint8_Array - (1 .. Integer (Buffers.Unit_Name.Length)); + Unit_Name_Bytes : + Uint8_Array (1 .. Integer (Buffers.Unit_Name.Length)); for Unit_Name_Bytes'Address use Buffers.Unit_Name.Str; pragma Import (Ada, Unit_Name_Bytes); subtype Bounded_Uint8_Array is Uint8_Array (1 .. 20); - function To_Uint8_Array is - new Ada.Unchecked_Conversion - (Fingerprint_Type, Bounded_Uint8_Array); + function To_Uint8_Array is new + Ada.Unchecked_Conversion (Fingerprint_Type, Bounded_Uint8_Array); begin -- Write trace entry header @@ -196,8 +194,7 @@ package body GNATcov_RTS.Traces.Output is Write_U32 (Output, Unsigned_32 (Buffers.Decision_Last_Bit + 1)); Write_U32 (Output, Unsigned_32 (Buffers.MCDC_Last_Bit + 1)); Write_U8 - (Output, - Unsigned_8 (Any_Language_Kind_Map (Buffers.Language))); + (Output, Unsigned_8 (Any_Language_Kind_Map (Buffers.Language))); Write_U8 (Output, Unsigned_8 @@ -246,7 +243,7 @@ package body GNATcov_RTS.Traces.Output is Current_Byte := Current_Byte or Bit_Mask; end if; Bit_Mask := 2 * Bit_Mask; - if Bit_Mask = 2 ** 8 then + if Bit_Mask = 2**8 then Flush; end if; end Append_Bit; @@ -265,7 +262,7 @@ package body GNATcov_RTS.Traces.Output is end if; end Flush; - -- Start of processing for Write_Buffer + -- Start of processing for Write_Buffer begin -- Write bytes that are included in the coverage buffer @@ -300,7 +297,7 @@ package body GNATcov_RTS.Traces.Output is Write_Buffer (Output, Buffer); end Write_Buffer; - -- Start of processing for Generic_Write_Trace_File + -- Start of processing for Generic_Write_Trace_File begin Write_Header (Output); @@ -326,8 +323,9 @@ package body GNATcov_RTS.Traces.Output is Write_Info (Output, Info_End, ""); for I in Buffers_Groups'Range loop declare - Buffers : Coverage_Buffers_Group - (1 .. Integer (Buffers_Groups (I).Length)); + Buffers : + Coverage_Buffers_Group + (1 .. Integer (Buffers_Groups (I).Length)); for Buffers'Address use Buffers_Groups (I).Buffers; pragma Import (C, Buffers); begin diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads index af15fc85a..06b161ec0 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces-output.ads @@ -39,12 +39,12 @@ package GNATcov_RTS.Traces.Output is type Output_Stream (<>) is limited private; -- Entity where the trace file is written - with procedure Write_Bytes - (Stream : in out Output_Stream; - Bytes : Uint8_Array) is <>; + with + procedure Write_Bytes + (Stream : in out Output_Stream; Bytes : Uint8_Array) is <>; -- Write Bytes to the given Stream - procedure Generic_Write_Trace_File + procedure Generic_Write_Trace_File (Output : in out Output_Stream; Buffers_Groups : Coverage_Buffers_Group_Array; Program_Name : String; diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads b/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads index 51a1de424..3304f60c2 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-traces.ads @@ -72,7 +72,7 @@ package GNATcov_RTS.Traces is Little_Endian : constant Any_Endianity := 0; Big_Endian : constant Any_Endianity := 1; subtype Supported_Endianity is - Any_Endianity range Little_Endian .. Big_Endian; + Any_Endianity range Little_Endian .. Big_Endian; -- Endianity to decode multi-byte scalars function Native_Endianity return Supported_Endianity; @@ -80,21 +80,20 @@ package GNATcov_RTS.Traces is type Any_Unit_Part is new Unsigned_8; Not_Applicable_Part : constant Any_Unit_Part := - Buffers.Any_Unit_Part'Pos (Buffers.Not_Applicable_Part); + Buffers.Any_Unit_Part'Pos (Buffers.Not_Applicable_Part); Unit_Body : constant Any_Unit_Part := - Buffers.Any_Unit_Part'Pos (Buffers.Unit_Body); + Buffers.Any_Unit_Part'Pos (Buffers.Unit_Body); Unit_Spec : constant Any_Unit_Part := - Buffers.Any_Unit_Part'Pos (Buffers.Unit_Spec); + Buffers.Any_Unit_Part'Pos (Buffers.Unit_Spec); Unit_Separate : constant Any_Unit_Part := - Buffers.Any_Unit_Part'Pos (Buffers.Unit_Separate); + Buffers.Any_Unit_Part'Pos (Buffers.Unit_Separate); subtype All_Unit_Part is - Any_Unit_Part range Not_Applicable_Part .. Unit_Separate; + Any_Unit_Part range Not_Applicable_Part .. Unit_Separate; subtype Supported_Unit_Part is - Any_Unit_Part range Unit_Body .. Unit_Separate; + Any_Unit_Part range Unit_Body .. Unit_Separate; -- Describe the kind of unit referenced by a trace entry - Unit_Part_Map : constant - array (Buffers.Any_Unit_Part) of All_Unit_Part := + Unit_Part_Map : constant array (Buffers.Any_Unit_Part) of All_Unit_Part := (Buffers.Not_Applicable_Part => Not_Applicable_Part, Buffers.Unit_Body => Unit_Body, Buffers.Unit_Spec => Unit_Spec, @@ -112,17 +111,17 @@ package GNATcov_RTS.Traces is Any_Language_Kind range Unit_Based_Language .. File_Based_Language; -- Language kind for a compilation unit - Any_Language_Kind_Map : constant - array (Buffers.Any_Language_Kind) of Supported_Language_Kind := - (Buffers.Unit_Based_Language => Unit_Based_Language, - Buffers.File_Based_Language => File_Based_Language); + Any_Language_Kind_Map : + constant array (Buffers.Any_Language_Kind) of Supported_Language_Kind := + (Buffers.Unit_Based_Language => Unit_Based_Language, + Buffers.File_Based_Language => File_Based_Language); ----------------------- -- Trace file header -- ----------------------- Trace_File_Magic : constant String (1 .. 32) := - "GNATcov source trace file" & (26 .. 32 => ASCII.NUL); + "GNATcov source trace file" & (26 .. 32 => ASCII.NUL); -- Expected value of the Trace_File_Header.Magic field (32 bytes) type Trace_File_Header is record @@ -163,7 +162,7 @@ package GNATcov_RTS.Traces is -- "tag". subtype Supported_Info_Kind is - Any_Info_Kind range Info_End .. Info_User_Data; + Any_Info_Kind range Info_End .. Info_User_Data; type Trace_Info_Header is record Kind : Any_Info_Kind; @@ -205,7 +204,7 @@ package GNATcov_RTS.Traces is -- significant bit maps to bit 8 * Y + 7. subtype Supported_Bit_Buffer_Encoding is - Any_Bit_Buffer_Encoding range LSB_First_Bytes .. LSB_First_Bytes; + Any_Bit_Buffer_Encoding range LSB_First_Bytes .. LSB_First_Bytes; type Trace_Entry_Header is record Unit_Name_Length : Unsigned_32; @@ -238,7 +237,7 @@ package GNATcov_RTS.Traces is -- be able to interpret buffer bits from a source traces using buffer -- bit mappings from SID files. - Annotations_Fingerprint : Fingerprint_Type; + Annotations_Fingerprint : Fingerprint_Type; -- Hash of annotations for this unit, as gnatcov computes it (see -- SC_Obligations). Used as a fast way to check that source traces and -- coverage data are consistent. diff --git a/tools/gnatcov/ada-rts/gnatcov_rts-types.ads b/tools/gnatcov/ada-rts/gnatcov_rts-types.ads index 0ace624a6..40767cd9a 100644 --- a/tools/gnatcov/ada-rts/gnatcov_rts-types.ads +++ b/tools/gnatcov/ada-rts/gnatcov_rts-types.ads @@ -38,13 +38,13 @@ package GNATcov_RTS.Types is pragma No_Elaboration_Code_All; pragma Warnings (On); - type Unsigned_8 is mod 2 ** 8; - type Unsigned_64 is mod 2 ** 64; + type Unsigned_8 is mod 2**8; + type Unsigned_64 is mod 2**64; -- We assume here that Integer (Ada) is a correct mapping for int (C) type int is new Integer; - type unsigned is mod 2 ** int'Size; + type unsigned is mod 2**int'Size; type size_t is mod System.Memory_Size; end GNATcov_RTS.Types; diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.adb b/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.adb index 5cb629a49..49fb05add 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.adb @@ -33,10 +33,10 @@ package body Geomaps.Test.Suite is Ret : constant Access_Test_Suite := New_Suite; begin AUnit.Test_Suites.Add_Test - (Ret, Caller.Create + (Ret, + Caller.Create ("Test Geomaps.Pos_Ahead_Of", Test_Pos_Ahead_Of_Access)); - AUnit.Test_Suites.Add_Test - (Ret, Situation_Link_Suite.Suite); + AUnit.Test_Suites.Add_Test (Ret, Situation_Link_Suite.Suite); return Ret; end Suite; diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.ads b/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.ads index d90d89905..43206d0f4 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/geomaps-test-suite.ads @@ -28,6 +28,6 @@ private package Caller is new AUnit.Test_Caller (Geomaps.Test.Test); Test_Pos_Ahead_Of_Access : constant Caller.Test_Method := - Test_Pos_Ahead_Of'Access; + Test_Pos_Ahead_Of'Access; end Geomaps.Test.Suite; diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.adb b/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.adb index ec0f69244..a8da2790a 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.adb @@ -23,32 +23,35 @@ package body Links.Gen_Test.Gen_Suite is Ret : Access_Test_Suite := New_Suite; begin AUnit.Test_Suites.Add_Test - (Ret, Caller.Create - ("Test " & Instance_Name & ".Full", Test_Full_Access)); + (Ret, + Caller.Create ("Test " & Instance_Name & ".Full", Test_Full_Access)); AUnit.Test_Suites.Add_Test - (Ret, Caller.Create - ("Test " & Instance_Name & ".Empty", Test_Empty_Access)); + (Ret, + Caller.Create + ("Test " & Instance_Name & ".Empty", Test_Empty_Access)); AUnit.Test_Suites.Add_Test - (Ret, Caller.Create - ("Test " & Instance_Name & ".Pop", Test_Pop_Access)); + (Ret, + Caller.Create ("Test " & Instance_Name & ".Pop", Test_Pop_Access)); AUnit.Test_Suites.Add_Test - (Ret, Caller.Create - ("Test " & Instance_Name & ".Push", Test_Push_Access)); + (Ret, + Caller.Create ("Test " & Instance_Name & ".Push", Test_Push_Access)); AUnit.Test_Suites.Add_Test - (Ret, Caller.Create - ("Test " & Instance_Name & ".Owner", Test_Owner_Access)); + (Ret, + Caller.Create + ("Test " & Instance_Name & ".Owner", Test_Owner_Access)); AUnit.Test_Suites.Add_Test - (Ret, Caller.Create + (Ret, + Caller.Create ("Test " & Instance_Name & ".Connect", Test_Connect_Access)); --- AUnit.Test_Suites.Add_Test --- (Ret, Caller.Create --- ("Test " & Instance_Name & ".Pop raises expected exceptions", --- Test_Pop_Raise_Access)); --- AUnit.Test_Suites.Add_Test --- (Ret, Caller.Create --- ("Test " & Instance_Name & ".Push raises expected exceptions", --- Test_Push_Raise_Access)); + -- AUnit.Test_Suites.Add_Test + -- (Ret, Caller.Create + -- ("Test " & Instance_Name & ".Pop raises expected exceptions", + -- Test_Pop_Raise_Access)); + -- AUnit.Test_Suites.Add_Test + -- (Ret, Caller.Create + -- ("Test " & Instance_Name & ".Push raises expected exceptions", + -- Test_Push_Raise_Access)); return Ret; end Suite; diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.ads b/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.ads index 78e1ed9b5..cfc364929 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/links-gen_test-gen_suite.ads @@ -24,24 +24,25 @@ generic Instance_Name : String; -package Links.Gen_Test.Gen_Suite is +package Links.Gen_Test.Gen_Suite +is function Suite return Access_Test_Suite; private package Caller is new AUnit.Test_Caller (Test); - Test_Full_Access : constant Caller.Test_Method := Test_Full'Access; - Test_Empty_Access : constant Caller.Test_Method := Test_Empty'Access; - Test_Pop_Access : constant Caller.Test_Method := Test_Pop'Access; - Test_Push_Access : constant Caller.Test_Method := Test_Push'Access; - Test_Owner_Access : constant Caller.Test_Method := Test_Owner'Access; - Test_Connect_Access : constant Caller.Test_Method := Test_Connect'Access; + Test_Full_Access : constant Caller.Test_Method := Test_Full'Access; + Test_Empty_Access : constant Caller.Test_Method := Test_Empty'Access; + Test_Pop_Access : constant Caller.Test_Method := Test_Pop'Access; + Test_Push_Access : constant Caller.Test_Method := Test_Push'Access; + Test_Owner_Access : constant Caller.Test_Method := Test_Owner'Access; + Test_Connect_Access : constant Caller.Test_Method := Test_Connect'Access; -- The following test exceptions raise. They require AUnit 3.2. --- Test_Pop_Raise_Access : constant Caller.Test_Method := --- Test_Pop_Raise'Access; --- Test_Push_Raise_Access : constant Caller.Test_Method := --- Test_Push_Raise'Access; + -- Test_Pop_Raise_Access : constant Caller.Test_Method := + -- Test_Pop_Raise'Access; + -- Test_Push_Raise_Access : constant Caller.Test_Method := + -- Test_Push_Raise'Access; end Links.Gen_Test.Gen_Suite; diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/main_suite.adb b/tools/gnatcov/examples/aunit_variant/harness/fixture/main_suite.adb index 49332013b..706b26b54 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/main_suite.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/main_suite.adb @@ -28,17 +28,10 @@ package body Main_Suite is Ret : constant Access_Test_Suite := New_Suite; begin AUnit.Test_Suites.Add_Test - (Ret, - Controls.Test.Suite.Robot_Control_Link_Suite.Suite); - AUnit.Test_Suites.Add_Test - (Ret, - Geomaps.Test.Suite.Suite); - AUnit.Test_Suites.Add_Test - (Ret, - Robots.Test.Suite.Suite); - AUnit.Test_Suites.Add_Test - (Ret, - Stations.Test.Suite.Suite); + (Ret, Controls.Test.Suite.Robot_Control_Link_Suite.Suite); + AUnit.Test_Suites.Add_Test (Ret, Geomaps.Test.Suite.Suite); + AUnit.Test_Suites.Add_Test (Ret, Robots.Test.Suite.Suite); + AUnit.Test_Suites.Add_Test (Ret, Stations.Test.Suite.Suite); return Ret; end Suite; diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.adb b/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.adb index c2b993c2c..a9320987f 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.adb @@ -27,14 +27,12 @@ package body Robots.Test.Suite is Ret : constant Access_Test_Suite := New_Suite; begin AUnit.Test_Suites.Add_Test - (Ret, Caller.Create - ("Test Robots.Kill/Live", Test_Live_And_Kill_Access)); + (Ret, + Caller.Create ("Test Robots.Kill/Live", Test_Live_And_Kill_Access)); AUnit.Test_Suites.Add_Test - (Ret, Caller.Create - ("Test Robots.Init", Test_Init_Access)); + (Ret, Caller.Create ("Test Robots.Init", Test_Init_Access)); AUnit.Test_Suites.Add_Test - (Ret, Caller.Create - ("Test Robots.Run", Test_Run_Access)); + (Ret, Caller.Create ("Test Robots.Run", Test_Run_Access)); return Ret; end Suite; diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.ads b/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.ads index 7d939b2a1..2b8147ed8 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/robots-test-suite.ads @@ -28,10 +28,8 @@ private package Caller is new AUnit.Test_Caller (Robots.Test.Test); Test_Live_And_Kill_Access : constant Caller.Test_Method := - Test_Live_And_Kill'Access; - Test_Init_Access : constant Caller.Test_Method := - Test_Init'Access; - Test_Run_Access : constant Caller.Test_Method := - Test_Run'Access; + Test_Live_And_Kill'Access; + Test_Init_Access : constant Caller.Test_Method := Test_Init'Access; + Test_Run_Access : constant Caller.Test_Method := Test_Run'Access; end Robots.Test.Suite; diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.adb b/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.adb index 38a37d88b..dec22d4c9 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.adb @@ -27,11 +27,10 @@ package body Stations.Test.Suite is Ret : constant Access_Test_Suite := New_Suite; begin AUnit.Test_Suites.Add_Test - (Ret, Caller.Create - ("Test Stations.Kill/Live", Test_Live_And_Kill_Access)); + (Ret, + Caller.Create ("Test Stations.Kill/Live", Test_Live_And_Kill_Access)); AUnit.Test_Suites.Add_Test - (Ret, Caller.Create - ("Test Stations.Init", Test_Init_Access)); + (Ret, Caller.Create ("Test Stations.Init", Test_Init_Access)); return Ret; end Suite; diff --git a/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.ads b/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.ads index fec422d37..53a040363 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/fixture/stations-test-suite.ads @@ -28,8 +28,7 @@ private package Caller is new AUnit.Test_Caller (Stations.Test.Test); Test_Live_And_Kill_Access : constant Caller.Test_Method := - Test_Live_And_Kill'Access; - Test_Init_Access : constant Caller.Test_Method := - Test_Init'Access; + Test_Live_And_Kill'Access; + Test_Init_Access : constant Caller.Test_Method := Test_Init'Access; end Stations.Test.Suite; diff --git a/tools/gnatcov/examples/aunit_variant/harness/old/test_ports.adb b/tools/gnatcov/examples/aunit_variant/harness/old/test_ports.adb index c3631649e..aa98e0ece 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/old/test_ports.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/old/test_ports.adb @@ -23,9 +23,9 @@ procedure Test_Ports is package Integer_Links is new Links (Data_Type => Integer); use Integer_Links; - X : Integer; + X : Integer; IP, OP : aliased Integer_Links.IOport (Capacity => 1); - L : aliased Integer_Links.IOlink; + L : aliased Integer_Links.IOlink; begin Connect (Outp => OP'Access, Inp => IP'Access, Link => L); diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/controls-test.ads b/tools/gnatcov/examples/aunit_variant/harness/tests/controls-test.ads index 23b4a7dae..eeeb2f484 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/controls-test.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/controls-test.ads @@ -21,10 +21,11 @@ with Links.Gen_Test; package Controls.Test is - package Robot_Link_Test is new Controls.Robot_Control_Links.Gen_Test - (Act1 => null, - Act2 => null, - Data_Val1 => Robot_Control'(Code => Nop, Value => 0), - Data_Val2 => Robot_Control'(Code => Opmode, Value => 1)); + package Robot_Link_Test is new + Controls.Robot_Control_Links.Gen_Test + (Act1 => null, + Act2 => null, + Data_Val1 => Robot_Control'(Code => Nop, Value => 0), + Data_Val2 => Robot_Control'(Code => Opmode, Value => 1)); end Controls.Test; diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.adb b/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.adb index 8b33bf4b3..54cd30242 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.adb @@ -25,12 +25,9 @@ package body Geomaps.Test is -- Test_Pos_Ahead_Of -- ----------------------- - procedure Test_Pos_Ahead_Of (T : in out Test) - is + procedure Test_Pos_Ahead_Of (T : in out Test) is Situ : Situation := - (Pos => (X => 3, Y => 3), - Dir => South, - Sqa => Ground); + (Pos => (X => 3, Y => 3), Dir => South, Sqa => Ground); Res : Position; begin diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.ads b/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.ads index 01b361b94..d701e293b 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/geomaps-test.ads @@ -26,16 +26,11 @@ package Geomaps.Test is procedure Test_Pos_Ahead_Of (T : in out Test); - package Situation_Link_Test is new Geomaps.Situation_Links.Gen_Test - (Act1 => null, - Act2 => null, - Data_Val1 => Situation' - (Pos => (1, 1), - Dir => South, - Sqa => Block), - Data_Val2 => Situation' - (Pos => (4, 3), - Dir => North, - Sqa => Water)); + package Situation_Link_Test is new + Geomaps.Situation_Links.Gen_Test + (Act1 => null, + Act2 => null, + Data_Val1 => Situation'(Pos => (1, 1), Dir => South, Sqa => Block), + Data_Val2 => Situation'(Pos => (4, 3), Dir => North, Sqa => Water)); end Geomaps.Test; diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.adb b/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.adb index e489b6649..1a6c0d4bf 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.adb @@ -18,7 +18,7 @@ ------------------------------------------------------------------------------ with System; -with AUnit.Assertions; use AUnit.Assertions; +with AUnit.Assertions; use AUnit.Assertions; package body Links.Gen_Test is @@ -47,11 +47,10 @@ package body Links.Gen_Test is -- Test_Full -- --------------- - procedure Test_Full (T : in out Test) is + procedure Test_Full (T : in out Test) is begin Assert - (Full (T.Port0), - "Port with a capacity of 0 should always be full"); + (Full (T.Port0), "Port with a capacity of 0 should always be full"); Assert (not Full (T.Port1), "Port with a capacity > 0 should not be full by default"); @@ -61,8 +60,7 @@ package body Links.Gen_Test is Push (Data_Val1, T.Port1); Assert - (Full (T.Port1), - "Port with 'capacity' pushed items should be full"); + (Full (T.Port1), "Port with 'capacity' pushed items should be full"); Push (Data_Val1, T.Port4); Assert @@ -77,8 +75,7 @@ package body Links.Gen_Test is procedure Test_Empty (T : in out Test) is begin Assert - (Empty (T.Port0), - "Port with a capacity of 0 should always be empty"); + (Empty (T.Port0), "Port with a capacity of 0 should always be empty"); Assert (Empty (T.Port1), "Port with a capacity > 0 should be empty by default"); @@ -101,23 +98,18 @@ package body Links.Gen_Test is -- Test_Pop -- -------------- - procedure Test_Pop (T : in out Test) - is + procedure Test_Pop (T : in out Test) is D : Data_Type; begin Push (Data_Val1, T.Port1); Pop (D, T.Port1); - Assert - (D = Data_Val1, - "Poped value after a push is not the same"); + Assert (D = Data_Val1, "Poped value after a push is not the same"); Push (Data_Val1, T.Port4); Push (Data_Val2, T.Port4); Pop (D, T.Port4); - Assert - (D = Data_Val1, - "Poped value after a two pushes is not the same"); + Assert (D = Data_Val1, "Poped value after a two pushes is not the same"); Pop (D, T.Port4); Assert (D = Data_Val2, @@ -128,7 +120,7 @@ package body Links.Gen_Test is -- Test_Push -- --------------- - procedure Test_Push (T : in out Test) is + procedure Test_Push (T : in out Test) is Tested_Port : Links.IOport_Access := null; begin @@ -165,8 +157,7 @@ package body Links.Gen_Test is Assert (Empty (T.Outp), "Output port shall be empty after initialisation"); - Assert - (Empty (T.Inp), "Input port shall be empty after initialisation"); + Assert (Empty (T.Inp), "Input port shall be empty after initialisation"); Push (Data_Val1, T.Outp); @@ -181,100 +172,99 @@ package body Links.Gen_Test is Assert (D = Data_Val1, - "The value received by the input port shall be the same as the one" & - " sent to the output port"); + "The value received by the input port shall be the same as the one" + & " sent to the output port"); Push (Data_Val2, T.Outp); Pop (D, T.Inp); Assert (D = Data_Val2, - "The value received by the input port shall be the same as the one" & - " sent to the output port"); + "The value received by the input port shall be the same as the one" + & " sent to the output port"); Assert - (Empty (T.Outp), - "Output port shall be empty after sending messages"); + (Empty (T.Outp), "Output port shall be empty after sending messages"); Assert (Empty (T.Inp), "Input port shall be empty after all messages are read"); end Test_Connect; --- -------------------- --- -- Test_Pop_Raise -- --- -------------------- --- --- procedure Test_Pop_Raise (T : in out Test) --- is --- Tested_Port : Links.IOport_Access := null; --- D : Data_Type; --- --- procedure Pop_Raise; --- -- Pop on Tested_Port with expected exception raised --- --- ---------------- --- -- Pop_Raise -- --- ---------------- --- --- procedure Pop_Raise is --- begin --- Pop (D, Tested_Port); --- end Pop_Raise; --- --- procedure Test_Pop_Raise is new Assert_Exception (Pop_Raise); --- --- begin --- Tested_Port := T.Port0; --- Test_Pop_Raise --- ("Pop with 0 capacity should always raise an exception"); --- --- Tested_Port := T.Port1; --- Test_Pop_Raise --- ("Pop on an empty port should raise an exception"); --- --- Push (Data_Val1, T.Port1); --- Pop (D, T.Port1); --- Tested_Port := T.Port1; --- Test_Pop_Raise --- ("Calling two pops with a single pushed value should raise " & --- "an exception"); --- end Test_Pop_Raise; --- --- --------------------- --- -- Test_Push_Raise -- --- --------------------- --- --- procedure Test_Push_Raise (T : in out Test) --- is --- Tested_Port : Links.IOport_Access := null; --- --- procedure Push_Raise; --- -- Push on Tested_Port with expected exception raised --- --- ---------------- --- -- Push_Raise -- --- ---------------- --- --- procedure Push_Raise is --- begin --- Push (Data_Val1, Tested_Port); --- end Push_Raise; --- --- procedure Test_Push_Raise is new Assert_Exception (Push_Raise); --- --- begin --- Tested_Port := null; --- Test_Push_Raise --- ("Push on a null port should raise an exception"); --- --- Tested_Port := T.Port0; --- Test_Push_Raise --- ("Push on a port with 0 capacity should raise an exception"); --- --- Tested_Port := T.Port1; --- Push (Data_Val1, T.Port1); --- Test_Push_Raise --- ("Push on a full port should raise an exception"); --- end Test_Push_Raise; + -- -------------------- + -- -- Test_Pop_Raise -- + -- -------------------- + -- + -- procedure Test_Pop_Raise (T : in out Test) + -- is + -- Tested_Port : Links.IOport_Access := null; + -- D : Data_Type; + -- + -- procedure Pop_Raise; + -- -- Pop on Tested_Port with expected exception raised + -- + -- ---------------- + -- -- Pop_Raise -- + -- ---------------- + -- + -- procedure Pop_Raise is + -- begin + -- Pop (D, Tested_Port); + -- end Pop_Raise; + -- + -- procedure Test_Pop_Raise is new Assert_Exception (Pop_Raise); + -- + -- begin + -- Tested_Port := T.Port0; + -- Test_Pop_Raise + -- ("Pop with 0 capacity should always raise an exception"); + -- + -- Tested_Port := T.Port1; + -- Test_Pop_Raise + -- ("Pop on an empty port should raise an exception"); + -- + -- Push (Data_Val1, T.Port1); + -- Pop (D, T.Port1); + -- Tested_Port := T.Port1; + -- Test_Pop_Raise + -- ("Calling two pops with a single pushed value should raise " & + -- "an exception"); + -- end Test_Pop_Raise; + -- + -- --------------------- + -- -- Test_Push_Raise -- + -- --------------------- + -- + -- procedure Test_Push_Raise (T : in out Test) + -- is + -- Tested_Port : Links.IOport_Access := null; + -- + -- procedure Push_Raise; + -- -- Push on Tested_Port with expected exception raised + -- + -- ---------------- + -- -- Push_Raise -- + -- ---------------- + -- + -- procedure Push_Raise is + -- begin + -- Push (Data_Val1, Tested_Port); + -- end Push_Raise; + -- + -- procedure Test_Push_Raise is new Assert_Exception (Push_Raise); + -- + -- begin + -- Tested_Port := null; + -- Test_Push_Raise + -- ("Push on a null port should raise an exception"); + -- + -- Tested_Port := T.Port0; + -- Test_Push_Raise + -- ("Push on a port with 0 capacity should raise an exception"); + -- + -- Tested_Port := T.Port1; + -- Push (Data_Val1, T.Port1); + -- Test_Push_Raise + -- ("Push on a full port should raise an exception"); + -- end Test_Push_Raise; end Links.Gen_Test; diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.ads b/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.ads index b164aeff8..0d612d7d9 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/links-gen_test.ads @@ -26,26 +26,27 @@ with Actors; generic Act1, Act2 : Actors.Actor_Ref; - Data_Val1 : Links.Data_Type; - Data_Val2 : Links.Data_Type; + Data_Val1 : Links.Data_Type; + Data_Val2 : Links.Data_Type; -package Links.Gen_Test is +package Links.Gen_Test +is type Test is new AUnit.Test_Fixtures.Test_Fixture with private; procedure Set_Up (T : in out Test); - procedure Test_Full (T : in out Test); - procedure Test_Empty (T : in out Test); - procedure Test_Pop (T : in out Test); - procedure Test_Push (T : in out Test); - procedure Test_Owner (T : in out Test); + procedure Test_Full (T : in out Test); + procedure Test_Empty (T : in out Test); + procedure Test_Pop (T : in out Test); + procedure Test_Push (T : in out Test); + procedure Test_Owner (T : in out Test); procedure Test_Connect (T : in out Test); -- The following tests require AUnit 3.2. -- Uncomment also in links-gen_test-gen_suite.ad[bs] to enable --- procedure Test_Pop_Raise (T : in out Test); --- procedure Test_Push_Raise (T : in out Test); + -- procedure Test_Pop_Raise (T : in out Test); + -- procedure Test_Push_Raise (T : in out Test); private diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.adb b/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.adb index 6fb2d38b4..9bd4ce297 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.adb @@ -19,17 +19,19 @@ with AUnit.Assertions; use AUnit.Assertions; with Actors; use Actors; -with Geomaps; use Geomaps, Geomaps.Situation_Links; -with Controls; use Controls, Controls.Robot_Control_Links; +with Geomaps; +use Geomaps, Geomaps.Situation_Links; +with Controls; +use Controls, Controls.Robot_Control_Links; with Robots_Devices; use Robots_Devices; package body Robots.Test is Default_Env : constant Test_Env := - (Robot_Destroyed => False, - Probe_Ahead_Square => Ground, - Position => (X => 2, Y => 2), - Direction => East); + (Robot_Destroyed => False, + Probe_Ahead_Square => Ground, + Position => (X => 2, Y => 2), + Direction => East); ------------------ -- Step_Forward -- @@ -40,11 +42,14 @@ package body Robots.Test is case Device.Env.Direction is when North => Device.Env.Position.Y := Device.Env.Position.Y - 1; + when South => Device.Env.Position.Y := Device.Env.Position.Y + 1; - when West => + + when West => Device.Env.Position.X := Device.Env.Position.X - 1; - when East => + + when East => Device.Env.Position.X := Device.Env.Position.X + 1; end case; @@ -59,16 +64,19 @@ package body Robots.Test is -- Rotate_Left -- ----------------- - procedure Rotate_Left (Device : access Test_Engine) is + procedure Rotate_Left (Device : access Test_Engine) is begin case Device.Env.Direction is when North => Device.Env.Direction := West; - when West => + + when West => Device.Env.Direction := South; + when South => Device.Env.Direction := East; - when East => + + when East => Device.Env.Direction := North; end case; end Rotate_Left; @@ -82,11 +90,14 @@ package body Robots.Test is case Device.Env.Direction is when South => Device.Env.Direction := West; - when East => + + when East => Device.Env.Direction := South; + when North => Device.Env.Direction := East; - when West => + + when West => Device.Env.Direction := North; end case; end Rotate_Right; @@ -104,7 +115,7 @@ package body Robots.Test is -- Get_Position -- ------------------ - function Get_Position (Device : access Test_Locator) return Position is + function Get_Position (Device : access Test_Locator) return Position is begin return Device.Env.Position; end Get_Position; @@ -141,17 +152,18 @@ package body Robots.Test is Loc => new Test_Locator); T.Env := new Test_Env; - Test_Engine (T.Hardware.Eng.all).Env := T.Env; - Test_Radar (T.Hardware.Rad.all).Env := T.Env; + Test_Engine (T.Hardware.Eng.all).Env := T.Env; + Test_Radar (T.Hardware.Rad.all).Env := T.Env; Test_Locator (T.Hardware.Loc.all).Env := T.Env; end if; T.Test_Robot.all := - (Actors.Actor with - Robot_Control_Inp => null, - Robot_Situation_Outp => null, - Hw => (Eng => null, Rad => null, Loc => null), - Mode => Cautious); + (Actors.Actor + with + Robot_Control_Inp => null, + Robot_Situation_Outp => null, + Hw => (Eng => null, Rad => null, Loc => null), + Mode => Cautious); T.Env.all := Default_Env; end Set_Up; @@ -185,9 +197,7 @@ package body Robots.Test is -- Nop T.Env.all := Default_Env; Controls.Robot_Control_Links.Push - (Robot_Control' - (Code => Nop, - Value => 0), + (Robot_Control'(Code => Nop, Value => 0), Robot_Control_Inport (T.Test_Robot.all)); Run (T.Test_Robot); Assert @@ -200,9 +210,7 @@ package body Robots.Test is -- Opmode T.Env.all := Default_Env; Controls.Robot_Control_Links.Push - (Robot_Control' - (Code => Opmode, - Value => Robot_Opmode'Pos (Dumb)), + (Robot_Control'(Code => Opmode, Value => Robot_Opmode'Pos (Dumb)), Robot_Control_Inport (T.Test_Robot.all)); Run (T.Test_Robot); Assert @@ -213,15 +221,13 @@ package body Robots.Test is "The robot should not send situation report upon Opmode reception"); Controls.Robot_Control_Links.Push - (Robot_Control' - (Code => Opmode, - Value => Robot_Opmode'Pos (Cautious)), + (Robot_Control'(Code => Opmode, Value => Robot_Opmode'Pos (Cautious)), Robot_Control_Inport (T.Test_Robot.all)); Run (T.Test_Robot); Assert (T.Test_Robot.Mode = Cautious, - "The robot mode should be set to Cautions after (Opmode, Cautious)" & - " is sent"); + "The robot mode should be set to Cautions after (Opmode, Cautious)" + & " is sent"); Assert (Empty (Robot_Situation_Outport (T.Test_Robot.all)), "The robot should not send situation report upon Opmode reception"); @@ -245,20 +251,18 @@ package body Robots.Test is T.Env.Direction := South; Controls.Robot_Control_Links.Push - (Robot_Control' - (Code => Step_Forward, - Value => 0), + (Robot_Control'(Code => Step_Forward, Value => 0), Robot_Control_Inport (T.Test_Robot.all)); Run (T.Test_Robot); Assert (T.Env.Position = (X => 2, Y => 3), - "The robot should have stepped forward upon Step_Forward with" & - " ground ahead"); + "The robot should have stepped forward upon Step_Forward with" + & " ground ahead"); Assert (Empty (Robot_Situation_Outport (T.Test_Robot.all)), - "The robot should not send situation report upon Step forward" & - " reception"); + "The robot should not send situation report upon Step forward" + & " reception"); end loop; -- Test Step_Forward 2: Water/Block ahead, mode = cautious @@ -271,17 +275,15 @@ package body Robots.Test is T.Env.Direction := South; Controls.Robot_Control_Links.Push - (Robot_Control' - (Code => Step_Forward, - Value => 0), + (Robot_Control'(Code => Step_Forward, Value => 0), Robot_Control_Inport (T.Test_Robot.all)); Run (T.Test_Robot); Assert (not T.Env.Robot_Destroyed and then T.Env.Position = (X => 2, Y => 2), - "The robot should not have stepped forward upon Step_Forward " & - "with water or block ahead (Cautious mode)"); + "The robot should not have stepped forward upon Step_Forward " + & "with water or block ahead (Cautious mode)"); end loop; -- Test Step_Forward 3: Water/Block ahead, mode = dumb @@ -294,20 +296,18 @@ package body Robots.Test is T.Env.Direction := South; Controls.Robot_Control_Links.Push - (Robot_Control' - (Code => Step_Forward, - Value => 0), + (Robot_Control'(Code => Step_Forward, Value => 0), Robot_Control_Inport (T.Test_Robot.all)); Run (T.Test_Robot); Assert (T.Env.Robot_Destroyed, - "The robot should have stepped forward upon Step_Forward " & - "with water or block ahead (Dumb mode)"); + "The robot should have stepped forward upon Step_Forward " + & "with water or block ahead (Dumb mode)"); Assert (Empty (Robot_Situation_Outport (T.Test_Robot.all)), - "The robot should not send situation report upon Step forward" & - " reception"); + "The robot should not send situation report upon Step forward" + & " reception"); end loop; -- Turn_Right, Turn_Left @@ -321,9 +321,7 @@ package body Robots.Test is T.Env.Direction := South; Controls.Robot_Control_Links.Push - (Robot_Control' - (Code => Rotate_Right, - Value => 0), + (Robot_Control'(Code => Rotate_Right, Value => 0), Robot_Control_Inport (T.Test_Robot.all)); Run (T.Test_Robot); Assert @@ -331,9 +329,7 @@ package body Robots.Test is "The robot should have turned right upon Rotate_Right cmd"); Controls.Robot_Control_Links.Push - (Robot_Control' - (Code => Rotate_Left, - Value => 0), + (Robot_Control'(Code => Rotate_Left, Value => 0), Robot_Control_Inport (T.Test_Robot.all)); Run (T.Test_Robot); Assert @@ -341,8 +337,8 @@ package body Robots.Test is "The robot should have turned left upon Rotate_Left cmd"); Assert (Empty (Robot_Situation_Outport (T.Test_Robot.all)), - "The robot should not send situation report upon Step forward" & - " reception"); + "The robot should not send situation report upon Step forward" + & " reception"); end loop; end loop; @@ -361,9 +357,7 @@ package body Robots.Test is T.Env.all := The_Env; Controls.Robot_Control_Links.Push - (Robot_Control' - (Code => Probe, - Value => 0), + (Robot_Control'(Code => Probe, Value => 0), Robot_Control_Inport (T.Test_Robot.all)); Run (T.Test_Robot); @@ -376,9 +370,7 @@ package body Robots.Test is Pop (Situ, Robot_Situation_Outport (T.Test_Robot.all)); Assert - (Situ = (Pos => The_Env.Position, - Dir => Dir, - Sqa => Sq), + (Situ = (Pos => The_Env.Position, Dir => Dir, Sqa => Sq), "Unexpected Situation received after a probe"); end; end loop; diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.ads b/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.ads index f8ed7018b..744add00b 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.ads +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/robots-test.ads @@ -35,10 +35,10 @@ package Robots.Test is private type Test_Env is record - Robot_Destroyed : Boolean; - Probe_Ahead_Square : Geomaps.Square; - Position : Geomaps.Position; - Direction : Geomaps.Direction; + Robot_Destroyed : Boolean; + Probe_Ahead_Square : Geomaps.Square; + Position : Geomaps.Position; + Direction : Geomaps.Direction; end record; type Test_Env_Access is access all Test_Env; @@ -52,7 +52,7 @@ private Env : Test_Env_Access; end record; procedure Step_Forward (Device : access Test_Engine); - procedure Rotate_Left (Device : access Test_Engine); + procedure Rotate_Left (Device : access Test_Engine); procedure Rotate_Right (Device : access Test_Engine); type Test_Radar is new Robots_Devices.Radar with record @@ -63,7 +63,7 @@ private type Test_Locator is new Robots_Devices.Locator with record Env : Test_Env_Access; end record; - function Get_Position (Device : access Test_Locator) return Position; + function Get_Position (Device : access Test_Locator) return Position; function Get_Direction (Device : access Test_Locator) return Direction; end Robots.Test; diff --git a/tools/gnatcov/examples/aunit_variant/harness/tests/stations-test.adb b/tools/gnatcov/examples/aunit_variant/harness/tests/stations-test.adb index 3df16ff17..51077aad2 100644 --- a/tools/gnatcov/examples/aunit_variant/harness/tests/stations-test.adb +++ b/tools/gnatcov/examples/aunit_variant/harness/tests/stations-test.adb @@ -19,8 +19,10 @@ with AUnit.Assertions; use AUnit.Assertions; with Actors; use Actors; -with Geomaps; use Geomaps, Geomaps.Situation_Links; -with Controls; use Controls, Controls.Robot_Control_Links; +with Geomaps; +use Geomaps, Geomaps.Situation_Links; +with Controls; +use Controls, Controls.Robot_Control_Links; package body Stations.Test is @@ -44,10 +46,11 @@ package body Stations.Test is end if; T.Test_Station.all := - (Actors.Actor with - Robot_Control_Outp => null, - Robot_Situation_Inp => null, - Map => (others => (others => Ground))); + (Actors.Actor + with + Robot_Control_Outp => null, + Robot_Situation_Inp => null, + Map => (others => (others => Ground))); end Set_Up; --------------- diff --git a/tools/gnatcov/examples/aunit_variant/src/explore.adb b/tools/gnatcov/examples/aunit_variant/src/explore.adb index e16f64ab6..9707d4016 100644 --- a/tools/gnatcov/examples/aunit_variant/src/explore.adb +++ b/tools/gnatcov/examples/aunit_variant/src/explore.adb @@ -26,7 +26,7 @@ -- separated out to allow inclusion into the documentation. with Overview, Actors, Robots, Stations, Controls, Geomaps; -use Overview, Actors, Robots, Stations, Controls, Geomaps; +use Overview, Actors, Robots, Stations, Controls, Geomaps; with Robots_Devices.Dummy; @@ -57,16 +57,18 @@ begin -- to their dedicated ports on both sides. declare - SR_Control_Link : Robot_Control_Links.IOlink_Access - := new Robot_Control_Links.IOlink; - SR_Situation_Link : Situation_Links.IOlink_Access - := new Situation_Links.IOlink; + SR_Control_Link : Robot_Control_Links.IOlink_Access := + new Robot_Control_Links.IOlink; + SR_Situation_Link : Situation_Links.IOlink_Access := + new Situation_Links.IOlink; begin Robot_Control_Links.Connect - (Robot_Control_Outport (S.all), Robot_Control_Inport (R.all), + (Robot_Control_Outport (S.all), + Robot_Control_Inport (R.all), SR_Control_Link); Situation_Links.Connect - (Robot_Situation_Outport (R.all), Robot_Situation_Inport (S.all), + (Robot_Situation_Outport (R.all), + Robot_Situation_Inport (S.all), SR_Situation_Link); end; diff --git a/tools/gnatcov/examples/aunit_variant/src/geomaps.adb b/tools/gnatcov/examples/aunit_variant/src/geomaps.adb index 2ec3c5f0e..7a0df580d 100644 --- a/tools/gnatcov/examples/aunit_variant/src/geomaps.adb +++ b/tools/gnatcov/examples/aunit_variant/src/geomaps.adb @@ -24,11 +24,11 @@ package body Geomaps is -- Characters to printout for each possible kind of field Square, -- and to represent an actor heading to a specific direction. - Square_Image : array (Square) of Character - := (Ground => ' ', Block => '#', Water => '~', Unknown => '.'); + Square_Image : array (Square) of Character := + (Ground => ' ', Block => '#', Water => '~', Unknown => '.'); - Situ_Image : array (Direction) of Character - := (North => '^', West => '<', East => '>', South => 'v'); + Situ_Image : array (Direction) of Character := + (North => '^', West => '<', East => '>', South => 'v'); ---------- -- Dump -- @@ -60,9 +60,11 @@ package body Geomaps is Dx, Dy : Move_XYrange; end record; - XYmoves : constant array (Direction) of Move - := (West => (Dx => -1, Dy => 0), East => (Dx => +1, Dy => 0), - South => (Dx => 0, Dy => +1), North => (Dx => 0, Dy => -1)); + XYmoves : constant array (Direction) of Move := + (West => (Dx => -1, Dy => 0), + East => (Dx => +1, Dy => 0), + South => (Dx => 0, Dy => +1), + North => (Dx => 0, Dy => -1)); XYmove : Move renames XYmoves (Situ.Dir); begin diff --git a/tools/gnatcov/examples/aunit_variant/src/links.adb b/tools/gnatcov/examples/aunit_variant/src/links.adb index 9ee8bb21c..d23056100 100644 --- a/tools/gnatcov/examples/aunit_variant/src/links.adb +++ b/tools/gnatcov/examples/aunit_variant/src/links.adb @@ -32,8 +32,7 @@ package body Links is return Ret; end Create_IOport; - procedure On_Push - (Port : IOport_Access; Callback : Callback_Access) is + procedure On_Push (Port : IOport_Access; Callback : Callback_Access) is begin Port.Push_Callback := Callback; end On_Push; @@ -85,8 +84,7 @@ package body Links is end loop; end Flush; - procedure Connect - (Outp, Inp : IOport_Access; Link : IOlink_Access) is + procedure Connect (Outp, Inp : IOport_Access; Link : IOlink_Access) is begin Inp.Link := Link; Outp.Link := Link; diff --git a/tools/gnatcov/examples/aunit_variant/src/links.ads b/tools/gnatcov/examples/aunit_variant/src/links.ads index 986f8d47c..9c8812f32 100644 --- a/tools/gnatcov/examples/aunit_variant/src/links.ads +++ b/tools/gnatcov/examples/aunit_variant/src/links.ads @@ -47,7 +47,7 @@ -- only one to one connections. with Actors, Queues; -use Actors; +use Actors; generic type Data_Type is private; @@ -106,7 +106,7 @@ private type Callback_Access is access procedure (Port : IOport_Access); type IOport (Capacity : Natural) is record - Data : Data_Queue (Capacity => Capacity); + Data : Data_Queue (Capacity => Capacity); Push_Callback : Callback_Access; Owner : Actor_Ref; diff --git a/tools/gnatcov/examples/aunit_variant/src/queues.ads b/tools/gnatcov/examples/aunit_variant/src/queues.ads index 4ac20a203..a5bfd8ae2 100644 --- a/tools/gnatcov/examples/aunit_variant/src/queues.ads +++ b/tools/gnatcov/examples/aunit_variant/src/queues.ads @@ -42,8 +42,8 @@ private type Data_Array is array (Natural range <>) of Data_Type; type Queue (Capacity : Natural) is record - Items : Data_Array (1 .. Capacity); - Size : Natural := 0; + Items : Data_Array (1 .. Capacity); + Size : Natural := 0; Front, Back : Natural := 1; end record; end Queues; diff --git a/tools/gnatcov/examples/aunit_variant/src/robots.adb b/tools/gnatcov/examples/aunit_variant/src/robots.adb index 7b40b847f..a28da78b7 100644 --- a/tools/gnatcov/examples/aunit_variant/src/robots.adb +++ b/tools/gnatcov/examples/aunit_variant/src/robots.adb @@ -52,18 +52,14 @@ package body Robots is begin -- Stepping forward with a rock block or a water pit ahead is Unsafe - return - Cmd = Step_Forward - and then (Sqa = Block or else Sqa = Water); + return Cmd = Step_Forward and then (Sqa = Block or else Sqa = Water); end Unsafe; -------------------------- -- Process_Next_Control -- -------------------------- - procedure Process_Next_Control - (Port : Robot_Control_Links.IOport_Access) - is + procedure Process_Next_Control (Port : Robot_Control_Links.IOport_Access) is Ctrl : Robot_Control; Robot : Robot_Access := Robot_Access (Owner (Port)); @@ -79,22 +75,22 @@ package body Robots is end if; case Ctrl.Code is - when Nop => + when Nop => return; - when Opmode => + when Opmode => Robot.Mode := Robot_Opmode'Val (Ctrl.Value); when Step_Forward => Step_Forward (Robot.Hw.Eng); - when Rotate_Left => + when Rotate_Left => Rotate_Left (Robot.Hw.Eng); when Rotate_Right => Rotate_Right (Robot.Hw.Eng); - when Probe => + when Probe => Situation_Links.Push (Situation' (Pos => Get_Position (Robot.Hw.Loc), @@ -124,13 +120,10 @@ package body Robots is procedure Init (R : Robot_Access; Hw : Robot_Hardware) is begin R.Robot_Situation_Outp := - Situation_Links.Create_IOport - (Capacity => 1, - Owner => Actor_Ref (R)); + Situation_Links.Create_IOport (Capacity => 1, Owner => Actor_Ref (R)); R.Robot_Control_Inp := Robot_Control_Links.Create_IOport - (Capacity => 2, - Owner => Actor_Ref (R)); + (Capacity => 2, Owner => Actor_Ref (R)); R.Hw := Hw; end Init; diff --git a/tools/gnatcov/examples/aunit_variant/src/robots.ads b/tools/gnatcov/examples/aunit_variant/src/robots.ads index 2ee117301..555458f7c 100644 --- a/tools/gnatcov/examples/aunit_variant/src/robots.ads +++ b/tools/gnatcov/examples/aunit_variant/src/robots.ads @@ -55,8 +55,8 @@ private Robot_Control_Inp : Robot_Control_Links.IOport_Access; Robot_Situation_Outp : Situation_Links.IOport_Access; - Hw : Robot_Hardware; - Mode : Robot_Opmode := Cautious; + Hw : Robot_Hardware; + Mode : Robot_Opmode := Cautious; end record; function Unsafe (Cmd : Robot_Command; Sqa : Square) return Boolean; diff --git a/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.adb b/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.adb index 1394d0006..ca98888c7 100644 --- a/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.adb +++ b/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.adb @@ -124,22 +124,20 @@ package body Robots_Devices.Dummy is Env : Environment_Access := new Environment; begin -- Create the hardware set. - Hw := (Eng => new Dummy_Engine, - Rad => new Dummy_Radar, - Loc => new Dummy_Locator); + Hw := + (Eng => new Dummy_Engine, + Rad => new Dummy_Radar, + Loc => new Dummy_Locator); -- All devices share the same environment. - Dummy_Engine (Hw.Eng.all).Env := Env; - Dummy_Radar (Hw.Rad.all).Env := Env; + Dummy_Engine (Hw.Eng.all).Env := Env; + Dummy_Radar (Hw.Rad.all).Env := Env; Dummy_Locator (Hw.Loc.all).Env := Env; -- We now initialize the environment with a dummy map and initial -- position Fake_Map (Env.Map); - Env.Situ := - (Pos => (X => 2, Y => 2), - Dir => East, - Sqa => Ground); + Env.Situ := (Pos => (X => 2, Y => 2), Dir => East, Sqa => Ground); -- Verify that the Sqa value is correct. Update_Square_Ahead (Dummy_Engine (Hw.Eng.all)'Access); diff --git a/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.ads b/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.ads index 548a2667c..d0b7862b5 100644 --- a/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.ads +++ b/tools/gnatcov/examples/aunit_variant/src/robots_devices-dummy.ads @@ -26,10 +26,10 @@ package Robots_Devices.Dummy is procedure Step_Forward (Device : access Dummy_Engine); -- Make the Engines step forward - procedure Rotate_Left (Device : access Dummy_Engine); + procedure Rotate_Left (Device : access Dummy_Engine); -- Make the Engines rotate left - procedure Rotate_Right (Device : access Dummy_Engine); + procedure Rotate_Right (Device : access Dummy_Engine); -- Make the Engines rotate right type Dummy_Radar is new Robots_Devices.Radar with private; @@ -39,7 +39,7 @@ package Robots_Devices.Dummy is type Dummy_Locator is new Robots_Devices.Locator with private; - function Get_Position (Device : access Dummy_Locator) return Position; + function Get_Position (Device : access Dummy_Locator) return Position; function Get_Direction (Device : access Dummy_Locator) return Direction; -- Use the locator to retrieve the current position and direction. diff --git a/tools/gnatcov/examples/aunit_variant/src/robots_devices.ads b/tools/gnatcov/examples/aunit_variant/src/robots_devices.ads index 4ecbd3df2..7a9c5a664 100644 --- a/tools/gnatcov/examples/aunit_variant/src/robots_devices.ads +++ b/tools/gnatcov/examples/aunit_variant/src/robots_devices.ads @@ -30,8 +30,7 @@ -- - a locator, able to evaluate the robot's position and orientation on -- the field. -with Controls, Geomaps; -use Controls, Geomaps; +with Controls, Geomaps; use Controls, Geomaps; package Robots_Devices is @@ -41,10 +40,10 @@ package Robots_Devices is procedure Step_Forward (Device : access Engine) is abstract; -- Make the Engines step forward - procedure Rotate_Left (Device : access Engine) is abstract; + procedure Rotate_Left (Device : access Engine) is abstract; -- Make the Engines rotate left - procedure Rotate_Right (Device : access Engine) is abstract; + procedure Rotate_Right (Device : access Engine) is abstract; -- Make the Engines rotate right type Radar is abstract tagged null record; @@ -56,10 +55,9 @@ package Robots_Devices is type Locator is abstract tagged null record; type Locator_Access is access all Locator'Class; - function Get_Position - (Device : access Locator) return Position is abstract; - function Get_Direction - (Device : access Locator) return Direction is abstract; + function Get_Position (Device : access Locator) return Position is abstract; + function Get_Direction (Device : access Locator) return Direction + is abstract; -- Use the locator to retrieve the current position and direction. type Robot_Hardware is record diff --git a/tools/gnatcov/examples/aunit_variant/src/stations.adb b/tools/gnatcov/examples/aunit_variant/src/stations.adb index cd99e0ced..a009a233b 100644 --- a/tools/gnatcov/examples/aunit_variant/src/stations.adb +++ b/tools/gnatcov/examples/aunit_variant/src/stations.adb @@ -87,23 +87,28 @@ package body Stations is -- Map user input character C to Robot_Control command, Nop if -- the input isn't recognized. - function Control_For - (C : Character) return Robot_Control is + function Control_For (C : Character) return Robot_Control is begin case C is when 'p' | 'P' => return (Code => Probe, Value => 0); + when 's' | 'S' => return (Code => Step_Forward, Value => 0); + when 'l' | 'L' => return (Code => Rotate_Left, Value => 0); + when 'r' | 'R' => return (Code => Rotate_Right, Value => 0); + when 'c' | 'C' => return (Code => Opmode, Value => Robot_Opmode'Pos (Cautious)); + when 'd' | 'D' => return (Code => Opmode, Value => Robot_Opmode'Pos (Dumb)); - when others => + + when others => return (Code => Nop, Value => 0); end case; end Control_For; @@ -120,7 +125,9 @@ package body Stations is Put_Line ("'C'autious mode, 'D'umb mode"); Put_Line ("'P'robe, 'S'tep, Rotate 'L'eft/'R'ight, 'Q'uit ? "); - Get (C); Put (C); New_Line; + Get (C); + Put (C); + New_Line; if C = 'Q' or else C = 'q' then Kill (Sta.all); @@ -167,12 +174,10 @@ package body Stations is begin Sta.Robot_Control_Outp := Robot_Control_Links.Create_IOport - (Capacity => 2, - Owner => Actor_Ref (Sta)); + (Capacity => 2, Owner => Actor_Ref (Sta)); Sta.Robot_Situation_Inp := Situation_Links.Create_IOport - (Capacity => 1, - Owner => Actor_Ref (Sta)); + (Capacity => 1, Owner => Actor_Ref (Sta)); All_Unknown (Sta.Map); end Init; diff --git a/tools/gnatcov/examples/aunit_variant/src/stations.ads b/tools/gnatcov/examples/aunit_variant/src/stations.ads index 893e76f47..e478b8f2d 100644 --- a/tools/gnatcov/examples/aunit_variant/src/stations.ads +++ b/tools/gnatcov/examples/aunit_variant/src/stations.ads @@ -43,7 +43,7 @@ package Stations is private type Station is new Actor with record - Robot_Control_Outp : Robot_Control_Links.IOport_Access; + Robot_Control_Outp : Robot_Control_Links.IOport_Access; Robot_Situation_Inp : Situation_Links.IOport_Access; Map : Geomap; diff --git a/tools/gnatcov/examples/doc/cross_example/src/monitor.adb b/tools/gnatcov/examples/doc/cross_example/src/monitor.adb index e6f1ea428..6af3d80ea 100644 --- a/tools/gnatcov/examples/doc/cross_example/src/monitor.adb +++ b/tools/gnatcov/examples/doc/cross_example/src/monitor.adb @@ -3,7 +3,7 @@ -- Copyright (C) 2012-2025, AdaCore -- ------------------------------------------------------------------------------ -with Sensors; use Sensors; +with Sensors; use Sensors; with Ada.Text_IO; use Ada.Text_IO; procedure Monitor is diff --git a/tools/gnatcov/examples/doc/cross_example/src/sensors.adb b/tools/gnatcov/examples/doc/cross_example/src/sensors.adb index f991e735f..1322ddec6 100644 --- a/tools/gnatcov/examples/doc/cross_example/src/sensors.adb +++ b/tools/gnatcov/examples/doc/cross_example/src/sensors.adb @@ -10,10 +10,17 @@ package body Sensors is -- Dummy implementation, for demonstration purposes case Index is - when 1 => return 1; - when 2 => return 5; - when 3 => return 3; - when 4 => return 7; + when 1 => + return 1; + + when 2 => + return 5; + + when 3 => + return 3; + + when 4 => + return 7; end case; end Value; diff --git a/tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.adb b/tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.adb index 204916af4..81e3ac823 100644 --- a/tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.adb +++ b/tools/gnatcov/examples/doc/custom_rt/stateful_io/stateful_io.adb @@ -11,8 +11,8 @@ package body Stateful_IO is procedure Put (S : String) is begin if not Initialized then - raise Program_Error with - "attempt to call Stateful_IO.Put before elaboration"; + raise Program_Error + with "attempt to call Stateful_IO.Put before elaboration"; end if; -- Replace the following with the actual code to send data to the IO diff --git a/tools/gnatcov/examples/doc/getting_started/opslib/ops.adb b/tools/gnatcov/examples/doc/getting_started/opslib/ops.adb index 54f54cc96..6cbdfd6c3 100644 --- a/tools/gnatcov/examples/doc/getting_started/opslib/ops.adb +++ b/tools/gnatcov/examples/doc/getting_started/opslib/ops.adb @@ -7,8 +7,11 @@ package body Ops is procedure Apply (Op : Op_Kind; X : in out Integer) is begin case Op is - when Increment => X := X + 1; - when Decrement => X := X - 1; + when Increment => + X := X + 1; + + when Decrement => + X := X - 1; end case; end Apply; end Ops; diff --git a/tools/gnatcov/examples/doc/library_instr/code/ops.adb b/tools/gnatcov/examples/doc/library_instr/code/ops.adb index 54f54cc96..6cbdfd6c3 100644 --- a/tools/gnatcov/examples/doc/library_instr/code/ops.adb +++ b/tools/gnatcov/examples/doc/library_instr/code/ops.adb @@ -7,8 +7,11 @@ package body Ops is procedure Apply (Op : Op_Kind; X : in out Integer) is begin case Op is - when Increment => X := X + 1; - when Decrement => X := X - 1; + when Increment => + X := X + 1; + + when Decrement => + X := X - 1; end case; end Apply; end Ops; diff --git a/tools/gnatcov/examples/doc/subunits/src/run_all.adb b/tools/gnatcov/examples/doc/subunits/src/run_all.adb index 20cf557e6..ba3810848 100644 --- a/tools/gnatcov/examples/doc/subunits/src/run_all.adb +++ b/tools/gnatcov/examples/doc/subunits/src/run_all.adb @@ -4,6 +4,7 @@ ------------------------------------------------------------------------------ with Data_Processing; + procedure Run_All is begin Data_Processing.Test; diff --git a/tools/gnatcov/examples/mcdc_checkpoints/src/test_stable.adb b/tools/gnatcov/examples/mcdc_checkpoints/src/test_stable.adb index 73fd13e26..c58a81e9d 100644 --- a/tools/gnatcov/examples/mcdc_checkpoints/src/test_stable.adb +++ b/tools/gnatcov/examples/mcdc_checkpoints/src/test_stable.adb @@ -16,7 +16,8 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Assert, Engines; use Engines; +with Assert, Engines; +use Engines; procedure Test_Stable is E : Engine; diff --git a/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_p.adb b/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_p.adb index 1a3a8624c..03e23dc5d 100644 --- a/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_p.adb +++ b/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_p.adb @@ -16,7 +16,8 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Assert, Engines; use Engines; +with Assert, Engines; +use Engines; procedure Test_Unstable_P is E : Engine; diff --git a/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_t.adb b/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_t.adb index 2f7fd4324..cbe7e9588 100644 --- a/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_t.adb +++ b/tools/gnatcov/examples/mcdc_checkpoints/src/test_unstable_t.adb @@ -16,7 +16,8 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Assert, Engines; use Engines; +with Assert, Engines; +use Engines; procedure Test_Unstable_T is E : Engine; diff --git a/tools/gnatcov/examples/spark_instrumentation/src/foo.adb b/tools/gnatcov/examples/spark_instrumentation/src/foo.adb index a20566e07..93614874b 100644 --- a/tools/gnatcov/examples/spark_instrumentation/src/foo.adb +++ b/tools/gnatcov/examples/spark_instrumentation/src/foo.adb @@ -13,7 +13,7 @@ is Data_Array : array (1 .. 4) of Integer := (others => 0); procedure Process_1 (Value : Integer) - with Global => (Output => (Data_Array, Last_Increment)), Pre => Value > 0; + with Global => (Output => (Data_Array, Last_Increment)), Pre => Value > 0; procedure Process (Value : Integer) is begin @@ -25,9 +25,10 @@ is for I in Data_Array'Range loop Data_Array (I) := Data_Array (I) + Value; - pragma Loop_Invariant - (for all J in Data_Array'First .. I => - Data_Array (J) = Data_Array'Loop_Entry (J) + Value); + pragma + Loop_Invariant + (for all J in Data_Array'First .. I => + Data_Array (J) = Data_Array'Loop_Entry (J) + Value); end loop; Last_Increment := Value; end Process_1; diff --git a/tools/gnatcov/examples/spark_instrumentation/src/foo.ads b/tools/gnatcov/examples/spark_instrumentation/src/foo.ads index cafed0af7..420700e04 100644 --- a/tools/gnatcov/examples/spark_instrumentation/src/foo.ads +++ b/tools/gnatcov/examples/spark_instrumentation/src/foo.ads @@ -7,7 +7,7 @@ ------------------------------------------------------------------------------ package Foo - with Abstract_State => (Data) + with Abstract_State => (Data) is procedure Process (Value : Integer); end Foo; diff --git a/tools/gnatcov/examples/support/lch/silent_last_chance-exit.adb b/tools/gnatcov/examples/support/lch/silent_last_chance-exit.adb index cfd1632c3..b59197e25 100644 --- a/tools/gnatcov/examples/support/lch/silent_last_chance-exit.adb +++ b/tools/gnatcov/examples/support/lch/silent_last_chance-exit.adb @@ -20,7 +20,7 @@ package body Silent_Last_Chance is pragma Import (Ada, Lch_Enter, "__lch_enter"); begin Lch_Enter; - C_exit(0); + C_exit (0); end Last_Chance_Handler; end; diff --git a/tools/gnatcov/examples/support/lch/silent_last_chance.ads b/tools/gnatcov/examples/support/lch/silent_last_chance.ads index 5b54a7b87..d985a1a05 100644 --- a/tools/gnatcov/examples/support/lch/silent_last_chance.ads +++ b/tools/gnatcov/examples/support/lch/silent_last_chance.ads @@ -7,8 +7,11 @@ with System; package Silent_Last_Chance is Unexpected_Last_Chance_Call : Integer := 0; - pragma Export (Ada, Unexpected_Last_Chance_Call, - "__gnat_unexpected_last_chance_call"); + pragma + Export + (Ada, + Unexpected_Last_Chance_Call, + "__gnat_unexpected_last_chance_call"); -- This declaration and comment should appear in all of the Ada -- specs defining __gnat_last_chance_handler, and being used by -- the GNATcoverage testsuite. Even if the value is not modified diff --git a/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.ads b/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.ads index 2f6a3c7bd..0c423d900 100644 --- a/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.ads +++ b/tools/gnatcov/examples/support/src/aarch64-nto-qnx/simple_last_chance_handler.ads @@ -22,8 +22,11 @@ with System; package Simple_Last_Chance_Handler is Unexpected_Last_Chance_Call : Integer := 0; - pragma Export (Ada, Unexpected_Last_Chance_Call, - "__gnat_unexpected_last_chance_call"); + pragma + Export + (Ada, + Unexpected_Last_Chance_Call, + "__gnat_unexpected_last_chance_call"); -- This declaration and comment should appear in all of the Ada -- specs defining __gnat_last_chance_handler, and being used by -- the GNATcoverage testsuite. Even if the value is not modified diff --git a/tools/gnatcov/examples/support/src/helpers/simple_pools.adb b/tools/gnatcov/examples/support/src/helpers/simple_pools.adb index eac17a732..540498818 100644 --- a/tools/gnatcov/examples/support/src/helpers/simple_pools.adb +++ b/tools/gnatcov/examples/support/src/helpers/simple_pools.adb @@ -2,7 +2,7 @@ package body Simple_Pools is package body Basic_Pool is - Store : array (1 .. Capacity) of aliased Data_Type; + Store : array (1 .. Capacity) of aliased Data_Type; Next_Free : Natural := Store'First; function Allocate return Data_Access is diff --git a/tools/gnatcov/examples/support/src/helpers/support.adb b/tools/gnatcov/examples/support/src/helpers/support.adb index e7e059c05..875c6eeca 100644 --- a/tools/gnatcov/examples/support/src/helpers/support.adb +++ b/tools/gnatcov/examples/support/src/helpers/support.adb @@ -1,4 +1,3 @@ - package body Support is procedure Assert (Cond : Boolean) is diff --git a/tools/gnatcov/examples/support/src/helpers/support.ads b/tools/gnatcov/examples/support/src/helpers/support.ads index f8a6f2972..52f2c0c03 100644 --- a/tools/gnatcov/examples/support/src/helpers/support.ads +++ b/tools/gnatcov/examples/support/src/helpers/support.ads @@ -1,4 +1,3 @@ - package Support is -- First, common subprograms intended for either Ada or C tests. diff --git a/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.ads b/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.ads index 2f6a3c7bd..0c423d900 100644 --- a/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.ads +++ b/tools/gnatcov/examples/support/src/last_chance_/simple_last_chance_handler.ads @@ -22,8 +22,11 @@ with System; package Simple_Last_Chance_Handler is Unexpected_Last_Chance_Call : Integer := 0; - pragma Export (Ada, Unexpected_Last_Chance_Call, - "__gnat_unexpected_last_chance_call"); + pragma + Export + (Ada, + Unexpected_Last_Chance_Call, + "__gnat_unexpected_last_chance_call"); -- This declaration and comment should appear in all of the Ada -- specs defining __gnat_last_chance_handler, and being used by -- the GNATcoverage testsuite. Even if the value is not modified diff --git a/tools/gnatcov/examples/support/src/last_chance_iSystem-5554/simple_last_chance_handler.ads b/tools/gnatcov/examples/support/src/last_chance_iSystem-5554/simple_last_chance_handler.ads index 2f6a3c7bd..0c423d900 100644 --- a/tools/gnatcov/examples/support/src/last_chance_iSystem-5554/simple_last_chance_handler.ads +++ b/tools/gnatcov/examples/support/src/last_chance_iSystem-5554/simple_last_chance_handler.ads @@ -22,8 +22,11 @@ with System; package Simple_Last_Chance_Handler is Unexpected_Last_Chance_Call : Integer := 0; - pragma Export (Ada, Unexpected_Last_Chance_Call, - "__gnat_unexpected_last_chance_call"); + pragma + Export + (Ada, + Unexpected_Last_Chance_Call, + "__gnat_unexpected_last_chance_call"); -- This declaration and comment should appear in all of the Ada -- specs defining __gnat_last_chance_handler, and being used by -- the GNATcoverage testsuite. Even if the value is not modified diff --git a/tools/gnatcov/examples/support/src/last_chance_iSystem-5634/simple_last_chance_handler.ads b/tools/gnatcov/examples/support/src/last_chance_iSystem-5634/simple_last_chance_handler.ads index 2f6a3c7bd..0c423d900 100644 --- a/tools/gnatcov/examples/support/src/last_chance_iSystem-5634/simple_last_chance_handler.ads +++ b/tools/gnatcov/examples/support/src/last_chance_iSystem-5634/simple_last_chance_handler.ads @@ -22,8 +22,11 @@ with System; package Simple_Last_Chance_Handler is Unexpected_Last_Chance_Call : Integer := 0; - pragma Export (Ada, Unexpected_Last_Chance_Call, - "__gnat_unexpected_last_chance_call"); + pragma + Export + (Ada, + Unexpected_Last_Chance_Call, + "__gnat_unexpected_last_chance_call"); -- This declaration and comment should appear in all of the Ada -- specs defining __gnat_last_chance_handler, and being used by -- the GNATcoverage testsuite. Even if the value is not modified diff --git a/tools/gnatcov/examples/support/src/memory/libsupport-memory.ads b/tools/gnatcov/examples/support/src/memory/libsupport-memory.ads index 917b0d267..e0074be69 100644 --- a/tools/gnatcov/examples/support/src/memory/libsupport-memory.ads +++ b/tools/gnatcov/examples/support/src/memory/libsupport-memory.ads @@ -16,7 +16,7 @@ -- of the license. -- ------------------------------------------------------------------------------ -with System; use System; +with System; use System; with Interfaces.C; use Interfaces.C; package Libsupport.Memory is diff --git a/tools/gnatcov/examples/xml/src/services.ads b/tools/gnatcov/examples/xml/src/services.ads index 9373a474a..f28ffb6c4 100644 --- a/tools/gnatcov/examples/xml/src/services.ads +++ b/tools/gnatcov/examples/xml/src/services.ads @@ -8,7 +8,7 @@ package Services is function Andthen (A, B : Boolean) return Boolean; - function Orelse (A, B : Boolean) return Boolean; + function Orelse (A, B : Boolean) return Boolean; - function Oor (A, B : Boolean) return Boolean; + function Oor (A, B : Boolean) return Boolean; end Services; diff --git a/tools/gnatcov/libopcodes_bind/dis_opcodes.ads b/tools/gnatcov/libopcodes_bind/dis_opcodes.ads index 49e0d2efd..f3999070b 100644 --- a/tools/gnatcov/libopcodes_bind/dis_opcodes.ads +++ b/tools/gnatcov/libopcodes_bind/dis_opcodes.ads @@ -34,9 +34,8 @@ package Dis_Opcodes is type BFD_Byte_Array is array (Natural range <>) of BFD_Byte; - type BFD_Endian is - (BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN) - with Convention => C; + type BFD_Endian is (BFD_ENDIAN_BIG, BFD_ENDIAN_LITTLE, BFD_ENDIAN_UNKNOWN) + with Convention => C; -- Possible endianness values of the program to disassemble --------------- @@ -47,57 +46,66 @@ package Dis_Opcodes is -- Opaque object used to disassemble binary code function Create_Arm_Disassembler return Disassemble_Handle - with Import => True, - Convention => C, - External_Name => "create_arm_disassembler"; + with + Import => True, + Convention => C, + External_Name => "create_arm_disassembler"; -- Returns a handle to disassemble ARM binary code function Create_Thumb_Disassembler return Disassemble_Handle - with Import => True, - Convention => C, - External_Name => "create_thumb_disassembler"; + with + Import => True, + Convention => C, + External_Name => "create_thumb_disassembler"; -- Returns a handle to disassemble Thumb binary code function Create_X86_Disassembler return Disassemble_Handle - with Import => True, - Convention => C, - External_Name => "create_x86_disassembler"; + with + Import => True, + Convention => C, + External_Name => "create_x86_disassembler"; -- Returns a handle to disassemble x86 binary code function Create_Visium_Disassembler return Disassemble_Handle - with Import => True, - Convention => C, - External_Name => "create_visium_disassembler"; + with + Import => True, + Convention => C, + External_Name => "create_visium_disassembler"; -- Returns a handle to disassemble Visium binary code function Create_Ppc_Disassembler return Disassemble_Handle - with Import => True, - Convention => C, - External_Name => "create_ppc_disassembler"; + with + Import => True, + Convention => C, + External_Name => "create_ppc_disassembler"; -- Returns a handle to disassemble PowerPC binary code function Create_E500_Disassembler return Disassemble_Handle - with Import => True, - Convention => C, - External_Name => "create_e500_disassembler"; + with + Import => True, + Convention => C, + External_Name => "create_e500_disassembler"; -- Return a handle to disassemble e500 binary code function Create_Sparc_Disassembler return Disassemble_Handle - with Import => True, - Convention => C, - External_Name => "create_sparc_disassembler"; + with + Import => True, + Convention => C, + External_Name => "create_sparc_disassembler"; -- Returns a handle to disassemble SPARC binary code function Create_AArch64_Disassembler return Disassemble_Handle - with Import => True, - Convention => C, - External_Name => "create_aarch64_disassembler"; + with + Import => True, + Convention => C, + External_Name => "create_aarch64_disassembler"; -- Returns a handle to disassemble Aarch64 binary code procedure Delete_Disassembler (DH : Disassemble_Handle) - with Import => True, - Convention => C, - External_Name => "delete_disassembler"; + with + Import => True, + Convention => C, + External_Name => "delete_disassembler"; -- Frees any memory used by the handle function Disassemble_To_Text @@ -108,9 +116,10 @@ package Dis_Opcodes is Insn_Buffer : BFD_Byte_Array; Ib_Size : unsigned; Endian : BFD_Endian) return int - with Import => True, - Convention => C, - External_Name => "disassemble_to_text"; + with + Import => True, + Convention => C, + External_Name => "disassemble_to_text"; -- Disassemble the instruction in Insn_Buffer of size Ib_Size. -- The instruction is considered to be located at address Pc and -- represented in endianness Endian. @@ -118,11 +127,13 @@ package Dis_Opcodes is -- Returns the size (in bytes) of the binary instruction that was -- disassembled. - type Print_Symbol_Cb is access function - (Addr : BFD_VMA; - Symbolizer : System.Address; - Buff_Addr : System.Address; - Buff_Size : int) return int with Convention => C; + type Print_Symbol_Cb is + access function + (Addr : BFD_VMA; + Symbolizer : System.Address; + Buff_Addr : System.Address; + Buff_Size : int) return int + with Convention => C; -- Symbolizer should denote the address of a Symbolizer'Class object. -- Functions of this type should return the number of characters written -- by the function. @@ -132,9 +143,10 @@ package Dis_Opcodes is (DH : Disassemble_Handle; Symbolizer : System.Address; Address_Cb : Print_Symbol_Cb) - with Import => True, - Convention => C, - External_Name => "set_disassembler_symbolizer"; + with + Import => True, + Convention => C, + External_Name => "set_disassembler_symbolizer"; -- Sets the callback to print symbols for the given handle. -- Symbolizer is the argument that will be given to Address_Cb for its -- formal parameter of the same name. diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.adb b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.adb index 40c6998e3..5089c382a 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers-lists.adb +++ b/tools/gnatcov/rts/gnatcov_rts-buffers-lists.adb @@ -30,8 +30,7 @@ package body GNATcov_RTS.Buffers.Lists is pragma Import (C, Clear_Buffers_C, "gnatcov_rts_reset_group_array"); procedure Reset_Group_Array_Buffers - (Arr : GNATcov_RTS_Coverage_Buffers_Group_Array) - is + (Arr : GNATcov_RTS_Coverage_Buffers_Group_Array) is begin Clear_Buffers_C (Arr'Address); end Reset_Group_Array_Buffers; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.adb b/tools/gnatcov/rts/gnatcov_rts-buffers.adb index aa4751120..6faff0ecf 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.adb +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.adb @@ -53,16 +53,14 @@ package body GNATcov_RTS.Buffers is function Witness (Buffer_Address : System.Address; Bit : Bit_Id) - return Non_Volatile_Witness_Dummy_Type - is + return Non_Volatile_Witness_Dummy_Type is begin Witness (Buffer_Address, Bit); return (Data => False); end Witness; function Witness - (Buffer_Address : System.Address; Bit : Bit_Id) return Boolean - is + (Buffer_Address : System.Address; Bit : Bit_Id) return Boolean is begin Witness (Buffer_Address, Bit); return False; diff --git a/tools/gnatcov/rts/gnatcov_rts-buffers.ads b/tools/gnatcov/rts/gnatcov_rts-buffers.ads index 42367696f..199c7c83c 100644 --- a/tools/gnatcov/rts/gnatcov_rts-buffers.ads +++ b/tools/gnatcov/rts/gnatcov_rts-buffers.ads @@ -76,15 +76,15 @@ package GNATcov_RTS.Buffers is -- Obligations. 20-byte to hold a SHA-1. type GNATcov_RTS_Coverage_Buffers is record - Fingerprint : Fingerprint_Type; - Language : Any_Language_Kind; - Unit_Part : Any_Unit_Part; - Unit_Name : GNATcov_RTS_String; - Bit_Maps_Fingerprint : Fingerprint_Type; - Annotations_Fingerprint : Fingerprint_Type; - Statement, Decision, MCDC : System.Address; - Statement_Last_Bit, Decision_Last_Bit, - MCDC_Last_Bit : Any_Bit_Id; + Fingerprint : Fingerprint_Type; + Language : Any_Language_Kind; + Unit_Part : Any_Unit_Part; + Unit_Name : + GNATcov_RTS_String; + Bit_Maps_Fingerprint : Fingerprint_Type; + Annotations_Fingerprint : Fingerprint_Type; + Statement, Decision, MCDC : System.Address; + Statement_Last_Bit, Decision_Last_Bit, MCDC_Last_Bit : Any_Bit_Id; end record; pragma Convention (C, GNATcov_RTS_Coverage_Buffers); diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb index bd01fcf52..3ab601389 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.adb @@ -33,8 +33,8 @@ package body GNATcov_RTS.Traces.Output.Base64 is Program_Name : GNATcov_RTS_String; Exec_Date : Unsigned_64; User_Data : GNATcov_RTS_String); - pragma Import - (C, Write_Trace_File_C, "gnatcov_rts_write_trace_file_base64"); + pragma + Import (C, Write_Trace_File_C, "gnatcov_rts_write_trace_file_base64"); ---------------------- -- Write_Trace_File -- diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads index 8b3f63737..f12d103b0 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-base64.ads @@ -41,7 +41,8 @@ package GNATcov_RTS.Traces.Output.Base64 is (Buffers_Groups : Coverage_Buffers_Group_Array; Program_Name : String; Exec_Date : Unsigned_64; - User_Data : String := "") renames Write_Trace_File; + User_Data : String := "") + renames Write_Trace_File; -- Renaming to mirror the API in GNATcov_RTS.Traces.Output.Files. This -- avoids special cases in the generation of automatic buffer dumps: except -- for the package that is WITHed, generated code is the same for diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb index 83740c9a6..0fe1764f9 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.adb @@ -36,34 +36,37 @@ package body GNATcov_RTS.Traces.Output.Files is Program_Name : GNATcov_RTS_String; Exec_Date : Unsigned_64; User_Data : GNATcov_RTS_String); - pragma Import - (C, - Write_Trace_File_C, - External_Name => "gnatcov_rts_write_trace_file"); + pragma + Import + (C, + Write_Trace_File_C, + External_Name => "gnatcov_rts_write_trace_file"); function Default_Trace_Filename_C (Env_Var : chars_ptr; Prefix : chars_ptr; Tag : chars_ptr; Simple : unsigned) return chars_ptr; - pragma Import - (C, Default_Trace_Filename_C, - External_Name => "gnatcov_rts_default_trace_filename"); + pragma + Import + (C, + Default_Trace_Filename_C, + External_Name => "gnatcov_rts_default_trace_filename"); ---------------------------- -- Default_Trace_Filename -- ---------------------------- function Default_Trace_Filename - (Env_Var : String := Default_Trace_Filename_Env_Var; - Prefix : String := "gnatcov"; - Tag : String := ""; + (Env_Var : String := Default_Trace_Filename_Env_Var; + Prefix : String := "gnatcov"; + Tag : String := ""; Simple : Boolean := False) return chars_ptr is Env_Var_C : chars_ptr := New_String (Env_Var); Prefix_C : chars_ptr := New_String (Prefix); Tag_C : chars_ptr := New_String (Tag); - Simple_C : constant unsigned := Boolean'Pos (Simple); + Simple_C : constant unsigned := Boolean'Pos (Simple); Result : constant chars_ptr := Default_Trace_Filename_C (Env_Var_C, Prefix_C, Tag_C, Simple_C); @@ -93,7 +96,7 @@ package body GNATcov_RTS.Traces.Output.Files is (Buffers_Groups : Coverage_Buffers_Group_Array; Filename : chars_ptr := Default_Trace_Filename; Program_Name : String := "unknown"; - Exec_Date : Time := Clock; + Exec_Date : Time := Clock; User_Data : String := "") is -- See the note about -gnatw.X in gnatcov_rts.gpr diff --git a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads index 2128d8c80..0f43d10fa 100644 --- a/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads +++ b/tools/gnatcov/rts/gnatcov_rts-traces-output-files.ads @@ -45,9 +45,9 @@ package GNATcov_RTS.Traces.Output.Files is -- Returns the number of seconds since the UNIX epoch function Default_Trace_Filename - (Env_Var : String := Default_Trace_Filename_Env_Var; - Prefix : String := "gnatcov"; - Tag : String := ""; + (Env_Var : String := Default_Trace_Filename_Env_Var; + Prefix : String := "gnatcov"; + Tag : String := ""; Simple : Boolean := False) return chars_ptr; -- Return the default name of the trace file to write. Please refer to the -- gnatcov_rts_default_trace_filename function defined in @@ -57,7 +57,7 @@ package GNATcov_RTS.Traces.Output.Files is (Buffers_Groups : Coverage_Buffers_Group_Array; Filename : chars_ptr := Default_Trace_Filename; Program_Name : String := "unknown"; - Exec_Date : Time := Clock; + Exec_Date : Time := Clock; User_Data : String := ""); -- Write a trace file in Filename to contain the data in Buffers_Groups. -- If the source trace file creation fails, print an error message on the diff --git a/tools/gnatcov/rts/gnatcov_rts-types.ads b/tools/gnatcov/rts/gnatcov_rts-types.ads index 0ace624a6..40767cd9a 100644 --- a/tools/gnatcov/rts/gnatcov_rts-types.ads +++ b/tools/gnatcov/rts/gnatcov_rts-types.ads @@ -38,13 +38,13 @@ package GNATcov_RTS.Types is pragma No_Elaboration_Code_All; pragma Warnings (On); - type Unsigned_8 is mod 2 ** 8; - type Unsigned_64 is mod 2 ** 64; + type Unsigned_8 is mod 2**8; + type Unsigned_64 is mod 2**64; -- We assume here that Integer (Ada) is a correct mapping for int (C) type int is new Integer; - type unsigned is mod 2 ** int'Size; + type unsigned is mod 2**int'Size; type size_t is mod System.Memory_Size; end GNATcov_RTS.Types; diff --git a/tools/gnatcov/trace_adapters/trace32/instructions_info.adb b/tools/gnatcov/trace_adapters/trace32/instructions_info.adb index a857cead5..c6a45a5c6 100644 --- a/tools/gnatcov/trace_adapters/trace32/instructions_info.adb +++ b/tools/gnatcov/trace_adapters/trace32/instructions_info.adb @@ -18,10 +18,10 @@ with Interfaces; use Interfaces; -with Binary_Files; use Binary_Files; -with Disassemblers; use Disassemblers; +with Binary_Files; use Binary_Files; +with Disassemblers; use Disassemblers; with Execs_Dbase; -with Outputs; use Outputs; +with Outputs; use Outputs; package body Instructions_Info is @@ -29,10 +29,7 @@ package body Instructions_Info is -- Load_Elf -- -------------- - procedure Load_Elf - (This : in out Insn_Info; - Exec_Path : String) - is + procedure Load_Elf (This : in out Insn_Info; Exec_Path : String) is Section_Iterator : Addresses_Iterator; begin begin @@ -52,8 +49,9 @@ package body Instructions_Info is if This.Section.Section_Name.all = ".text" then Load_Section_Content (This.Exec.all, This.Section); - This.I_Ranges := Get_Insn_Set_Ranges - (This.Exec.all, This.Section.Section_Sec_Idx).all; + This.I_Ranges := + Get_Insn_Set_Ranges + (This.Exec.all, This.Section.Section_Sec_Idx).all; return; end if; end loop; @@ -64,17 +62,15 @@ package body Instructions_Info is -- Loaded -- ------------ - function Loaded (This : Insn_Info) return Boolean is - (This.Exec /= null); + function Loaded (This : Insn_Info) return Boolean + is (This.Exec /= null); --------------------------- -- Get_Next_Insn_Address -- --------------------------- function Get_Next_Insn_Address - (This : in out Insn_Info; - PC : Pc_Type) return Pc_Type - is + (This : in out Insn_Info; PC : Pc_Type) return Pc_Type is begin return PC + This.Get_Insn_Length (PC); end Get_Next_Insn_Address; @@ -84,11 +80,10 @@ package body Instructions_Info is --------------------- function Get_Insn_Length - (This : in out Insn_Info; - PC : Pc_Type) return Pc_Type + (This : in out Insn_Info; PC : Pc_Type) return Pc_Type is - Disas : access Disassembler'Class; - Code : constant Binary_Content := This.Section.Section_Content; + Disas : access Disassembler'Class; + Code : constant Binary_Content := This.Section.Section_Content; begin Disas := Disa_For_Machine (Machine, This.I_Ranges, This.Cache, PC); @@ -101,8 +96,7 @@ package body Instructions_Info is ---------- function Kind - (This : in out Insn_Info; - PC : Pc_Type) return Instruction_Kind + (This : in out Insn_Info; PC : Pc_Type) return Instruction_Kind is Disas : access Disassembler'Class; Code : constant Binary_Content := This.Section.Section_Content; @@ -116,13 +110,14 @@ package body Instructions_Info is return Unknown; end if; Disas := Disa_For_Machine (Machine, This.I_Ranges, This.Cache, PC); - Disas.Get_Insn_Properties (Slice (Code, PC, Code.Last), - Pc => PC, - Branch => Br, - Flag_Indir => Flag_Indir, - Flag_Cond => Flag_Cond, - Branch_Dest => Branch_Dest, - FT_Dest => FT_Dest); + Disas.Get_Insn_Properties + (Slice (Code, PC, Code.Last), + Pc => PC, + Branch => Br, + Flag_Indir => Flag_Indir, + Flag_Cond => Flag_Cond, + Branch_Dest => Branch_Dest, + FT_Dest => FT_Dest); if Br /= Br_None then return Branch; else @@ -135,9 +130,7 @@ package body Instructions_Info is ----------------- function Fallthrough_Address - (This : in out Insn_Info; - Caller, Target : Pc_Type) return Boolean - is + (This : in out Insn_Info; Caller, Target : Pc_Type) return Boolean is begin return Get_Next_Insn_Address (This, Caller) = Target; end Fallthrough_Address; diff --git a/tools/gnatcov/trace_adapters/trace32/instructions_info.ads b/tools/gnatcov/trace_adapters/trace32/instructions_info.ads index 0329e228e..df4952148 100644 --- a/tools/gnatcov/trace_adapters/trace32/instructions_info.ads +++ b/tools/gnatcov/trace_adapters/trace32/instructions_info.ads @@ -24,43 +24,34 @@ package Instructions_Info is type Insn_Info is tagged limited private; - procedure Load_Elf (This : in out Insn_Info; - Exec_Path : String); + procedure Load_Elf (This : in out Insn_Info; Exec_Path : String); -- Load .text section of the given ELF binary file - function Loaded (This : Insn_Info) return Boolean; + function Loaded (This : Insn_Info) return Boolean; -- Return True if a .text section is loaded type Instruction_Kind is (Unknown, Branch, Not_A_Branch); function Kind - (This : in out Insn_Info; - PC : Pc_Type) return Instruction_Kind - with - Pre => Loaded (This); + (This : in out Insn_Info; PC : Pc_Type) return Instruction_Kind + with Pre => Loaded (This); -- Return the kind of the instruction at PC. Either a branch, not a branch -- or an unknown kind. Unknown can be return when the disassembler doesn't -- have enough information to determine the kind of instruction. function Get_Next_Insn_Address - (This : in out Insn_Info; - PC : Pc_Type) return Pc_Type - with - Pre => Loaded (This) and then Kind (This, PC) /= Unknown; + (This : in out Insn_Info; PC : Pc_Type) return Pc_Type + with Pre => Loaded (This) and then Kind (This, PC) /= Unknown; -- Return the address of the next instruction after PC function Get_Insn_Length - (This : in out Insn_Info; - PC : Pc_Type) return Pc_Type - with - Pre => Loaded (This) and then Kind (This, PC) /= Unknown; + (This : in out Insn_Info; PC : Pc_Type) return Pc_Type + with Pre => Loaded (This) and then Kind (This, PC) /= Unknown; -- Return memory lenght of the instruction at PC function Fallthrough_Address - (This : in out Insn_Info; - Caller, Target : Pc_Type) return Boolean - with - Pre => Loaded (This) and then Kind (This, Caller) = Branch; + (This : in out Insn_Info; Caller, Target : Pc_Type) return Boolean + with Pre => Loaded (This) and then Kind (This, Caller) = Branch; -- Return True if Target is the fallthouth address of the branch -- instruction at Caller. diff --git a/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.adb b/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.adb index 25d76738c..a7f8858a1 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.adb +++ b/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.adb @@ -18,7 +18,7 @@ with Ada.IO_Exceptions; -with GNAT.Regpat; use GNAT.Regpat; +with GNAT.Regpat; use GNAT.Regpat; with Outputs; @@ -35,8 +35,7 @@ package body Trace32.Branchflow is --------------------- function Open - (This : in out Branchflow_Trace; - Path : String) return Status_Kind + (This : in out Branchflow_Trace; Path : String) return Status_Kind is function Check_Header return Boolean; -- Return True if the trace header is correct @@ -52,15 +51,14 @@ package body Trace32.Branchflow is Line4 : constant String := Get_Line (This.File); begin return - (Line1 = "######################################################" & - "#################" - and then - Line2 = "# Branch Flow trace file" - and then - Line3 = "# target; caller; trace record" - and then - Line4 = "######################################################" & - "#################"); + (Line1 + = "######################################################" + & "#################" + and then Line2 = "# Branch Flow trace file" + and then Line3 = "# target; caller; trace record" + and then Line4 + = "######################################################" + & "#################"); end Check_Header; begin This.Open := False; @@ -77,7 +75,8 @@ package body Trace32.Branchflow is This.Line_Number := 4; return Status_Ok; exception - when others => return File_Error; + when others => + return File_Error; end Open; ------------- @@ -93,8 +92,7 @@ package body Trace32.Branchflow is -- Close_Trace_File -- ---------------------- - procedure Close_Trace_File (This : in out Branchflow_Trace) - is + procedure Close_Trace_File (This : in out Branchflow_Trace) is begin Close (This.File); This.Open := False; @@ -105,9 +103,8 @@ package body Trace32.Branchflow is ---------------- function Next_Entry - (This : in out Branchflow_Trace; - Ent : out Branchflow_Trace_Entry) return Status_Kind - is + (This : in out Branchflow_Trace; Ent : out Branchflow_Trace_Entry) + return Status_Kind is begin declare Line : constant String := Get_Line (This.File); @@ -124,8 +121,10 @@ package body Trace32.Branchflow is Match (Matcher, Line, Matches); if (for some M of Matches => M = No_Match) then - Outputs.Warn ("Bad line format in branchflow file (line " & - This.Line_Number'Img & ")"); + Outputs.Warn + ("Bad line format in branchflow file (line " + & This.Line_Number'Img + & ")"); return No_More_Entry; end if; diff --git a/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.ads b/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.ads index 9d30b536d..c2bd93dd6 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.ads +++ b/tools/gnatcov/trace_adapters/trace32/trace32-branchflow.ads @@ -18,33 +18,29 @@ with Ada.Text_IO; use Ada.Text_IO; -with Traces; use Traces; +with Traces; use Traces; package Trace32.Branchflow is type Branchflow_Trace is tagged limited private; - type Status_Kind is (Status_Ok, - File_Error, - Invalid_Trace_File, - No_More_Entry); + type Status_Kind is + (Status_Ok, File_Error, Invalid_Trace_File, No_More_Entry); function Open - (This : in out Branchflow_Trace; - Path : String) return Status_Kind - with Pre => not This.Is_Open, - Post => Open'Result in Status_Ok | File_Error | Invalid_Trace_File - and then - (if Open'Result = Status_Ok then This.Is_Open); + (This : in out Branchflow_Trace; Path : String) return Status_Kind + with + Pre => not This.Is_Open, + Post => + Open'Result in Status_Ok | File_Error | Invalid_Trace_File + and then (if Open'Result = Status_Ok then This.Is_Open); -- Open a Trace32 branchflow file for input function Is_Open (This : in out Branchflow_Trace) return Boolean; -- Return true if the Trace32 branchflow file is open procedure Close_Trace_File (This : in out Branchflow_Trace) - with - Pre => This.Is_Open, - Post => not This.Is_Open; + with Pre => This.Is_Open, Post => not This.Is_Open; -- Close Trace32 branchflow file type Branchflow_Trace_Entry is record @@ -57,10 +53,11 @@ package Trace32.Branchflow is end record; function Next_Entry - (This : in out Branchflow_Trace; - Ent : out Branchflow_Trace_Entry) return Status_Kind - with Pre => This.Is_Open, - Post => Next_Entry'Result in Status_Ok | No_More_Entry; + (This : in out Branchflow_Trace; Ent : out Branchflow_Trace_Entry) + return Status_Kind + with + Pre => This.Is_Open, + Post => Next_Entry'Result in Status_Ok | No_More_Entry; -- Read the next entry in the branchflow file. This function returns -- No_More_Entry once there's no more entries to read in the file, @@ -68,8 +65,8 @@ package Trace32.Branchflow is -- Pretty print a trace entry private type Branchflow_Trace is tagged limited record - File : File_Type; - Open : Boolean; + File : File_Type; + Open : Boolean; Line_Number : Natural := 0; -- Use to display diff --git a/tools/gnatcov/trace_adapters/trace32/trace32-conversion.adb b/tools/gnatcov/trace_adapters/trace32/trace32-conversion.adb index 06c3a0c25..f59f57da8 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace32-conversion.adb +++ b/tools/gnatcov/trace_adapters/trace32/trace32-conversion.adb @@ -17,13 +17,13 @@ ------------------------------------------------------------------------------ with Ada.Text_IO; -with Interfaces; use Interfaces; +with Interfaces; use Interfaces; -with Diagnostics; use Diagnostics; -with Outputs; use Outputs; +with Diagnostics; use Diagnostics; +with Outputs; use Outputs; with Qemu_Traces; -with Traces; use Traces; -with Trace_Output; use Trace_Output; +with Traces; use Traces; +with Trace_Output; use Trace_Output; with Instructions_Info; use Instructions_Info; with Trace32.Branchflow; use Trace32.Branchflow; @@ -56,29 +56,28 @@ package body Trace32.Conversion is Qemu_Trace_File : String; Decision_Map_File : String) is - Insn : Instructions_Info.Insn_Info; - Branch_Flow : BF.Branchflow_Trace; - BF_Entry : BF.Branchflow_Trace_Entry; - BF_Status : BF.Status_Kind; - Prev_Landing : Pc_Type; - Output : Trace_Output.QEMU_Trace_Output; - Kind : Instruction_Kind; + Insn : Instructions_Info.Insn_Info; + Branch_Flow : BF.Branchflow_Trace; + BF_Entry : BF.Branchflow_Trace_Entry; + BF_Status : BF.Status_Kind; + Prev_Landing : Pc_Type; + Output : Trace_Output.QEMU_Trace_Output; + Kind : Instruction_Kind; begin -- Load the instruction info from the ELF file Insn.Load_Elf (Elf_File); if not Insn.Loaded then - Outputs.Fatal_Error ("Cannot load .text section for ELF file: '" - & Elf_File & "'"); + Outputs.Fatal_Error + ("Cannot load .text section for ELF file: '" & Elf_File & "'"); end if; Report ("Loading Trace32 Branch Flow file: " & Branchflow_File); - if Branch_Flow.Open (Branchflow_File) /= BF.Status_Ok - then - Outputs.Fatal_Error ("Cannot open Trace32 Branch Flow file: '" - & Branchflow_File & "'"); + if Branch_Flow.Open (Branchflow_File) /= BF.Status_Ok then + Outputs.Fatal_Error + ("Cannot open Trace32 Branch Flow file: '" & Branchflow_File & "'"); end if; Output.Open (Qemu_Trace_File, Decision_Map_File); @@ -95,15 +94,16 @@ package body Trace32.Conversion is if BF_Status /= Status_Ok then -- No entry in Branchflow file - Outputs.Fatal_Error ("No entry in Trace32 Branchflow file'" - & Branchflow_File & "'"); + Outputs.Fatal_Error + ("No entry in Trace32 Branchflow file'" & Branchflow_File & "'"); else -- Use Target address of first branchflow entry as the first address -- of the first basic block. Prev_Landing := BF_Entry.Target; end if; - Conversion : loop + Conversion : + loop BF_Status := Branch_Flow.Next_Entry (BF_Entry); @@ -124,17 +124,19 @@ package body Trace32.Conversion is -- Set the address of the last byte of the last instruction -- in the basic block. - Ent.Last := BF_Entry.Caller + - Insn.Get_Insn_Length (BF_Entry.Caller) - 1; + Ent.Last := + BF_Entry.Caller + + Insn.Get_Insn_Length (BF_Entry.Caller) + - 1; -- Mark the basic block as executed - Ent.Op := Qemu_Traces.Trace_Op_Block; + Ent.Op := Qemu_Traces.Trace_Op_Block; if Kind = Branch then -- Check if Target is the fallthrough address of Caller -- instruction. - if Insn.Fallthrough_Address (BF_Entry.Caller, - BF_Entry.Target) + if Insn.Fallthrough_Address + (BF_Entry.Caller, BF_Entry.Target) then -- Fallthrough Ent.Op := Ent.Op or Qemu_Traces.Trace_Op_Br1; @@ -153,7 +155,7 @@ package body Trace32.Conversion is Output.Push_Entry (Ent); end; - when Unknown => + when Unknown => -- The kind of instruction is unknown, this most probably means -- that the instruction is not within the sections of the ELF @@ -164,18 +166,21 @@ package body Trace32.Conversion is -- so we will try to recover from this situation by searching -- for the next known instruction. - Recovery : loop + Recovery : + loop if Insn.Kind (BF_Entry.Caller) /= Unknown then Outputs.Warn ("Recovering from unknown instruction (" - & Hex_Image (BF_Entry.Target) & ")"); + & Hex_Image (BF_Entry.Target) + & ")"); exit Recovery; else Outputs.Warning_Or_Error ("Could not get instruction info (" - & Hex_Image (BF_Entry.Caller) & ")"); + & Hex_Image (BF_Entry.Caller) + & ")"); end if; BF_Status := Branch_Flow.Next_Entry (BF_Entry); diff --git a/tools/gnatcov/trace_adapters/trace32/trace32_drv.adb b/tools/gnatcov/trace_adapters/trace32/trace32_drv.adb index e28aa6253..e432ee110 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace32_drv.adb +++ b/tools/gnatcov/trace_adapters/trace32/trace32_drv.adb @@ -16,10 +16,10 @@ -- of the license. -- ------------------------------------------------------------------------------ -with Ada.Command_Line; use Ada.Command_Line; -with Ada.Text_IO; use Ada.Text_IO; +with Ada.Command_Line; use Ada.Command_Line; +with Ada.Text_IO; use Ada.Text_IO; -with GNAT.OS_Lib; use GNAT.OS_Lib; +with GNAT.OS_Lib; use GNAT.OS_Lib; with Outputs; @@ -75,7 +75,8 @@ procedure Trace32_Drv is S_Idx1, S_Idx2 : Positive; - Processor : String_Access with Unreferenced; + Processor : String_Access + with Unreferenced; -- The processor name will be useful for the run mode that is not yet -- implemented. @@ -114,24 +115,26 @@ begin -- map file in the first case above. S_Idx1 := Argument (3)'First; - if Argument (3)'Length > 8 and then - Argument (3) (S_Idx1 .. S_Idx1 + 7) = "histmap=" + if Argument (3)'Length > 8 + and then Argument (3) (S_Idx1 .. S_Idx1 + 7) = "histmap=" then S_Idx1 := S_Idx1 + 8; S_Idx2 := S_Idx1; loop - exit when S_Idx2 = Argument (3)'Last - or else Argument (3) (S_Idx2) = ','; + exit when + S_Idx2 = Argument (3)'Last or else Argument (3) (S_Idx2) = ','; S_Idx2 := S_Idx2 + 1; end loop; if S_Idx2 = Argument (3)'Last then Put_Line (Standard_Error, "Missing tracefile arg to trace32_drv."); OS_Exit (1); end if; - Histfile_Path := new String' - (Normalize_Pathname (Argument (3) (S_Idx1 .. S_Idx2 - 1))); - Tracefile_Path := new String' - (Normalize_Pathname (Argument (3) (S_Idx2 + 1 .. Argument (3)'Last))); + Histfile_Path := + new String'(Normalize_Pathname (Argument (3) (S_Idx1 .. S_Idx2 - 1))); + Tracefile_Path := + new String' + (Normalize_Pathname + (Argument (3) (S_Idx2 + 1 .. Argument (3)'Last))); else Histfile_Path := new String'(""); Tracefile_Path := new String'(Argument (3)); @@ -139,16 +142,17 @@ begin if Mode = Run then Outputs.Fatal_Error ("Run mode not supported yet"); - -- Trace32.API.Load; - -- Trace32.API.Connect ("localhost", "20000", "1024"); - -- if Processor.all = "stm32f7" then - -- Trace32.API.STM32F7_Setup; - -- end if; - -- Trace32.API.Load_Executable (Executable_Path.all); - -- Trace32.API.Set_Breakpoint ("__gnat_last_chance_handler"); - -- Trace32.API.Run_Until ("_exit", 500); - -- Trace32.API.Export_Branchflow_Trace (Tracefile_Path.all & - -- ".branchflow"); + -- Trace32.API.Load; + -- Trace32.API.Connect ("localhost", "20000", "1024"); + -- if Processor.all = "stm32f7" then + -- Trace32.API.STM32F7_Setup; + -- end if; + -- Trace32.API.Load_Executable (Executable_Path.all); + -- Trace32.API.Set_Breakpoint ("__gnat_last_chance_handler"); + -- Trace32.API.Run_Until ("_exit", 500); + -- Trace32.API.Export_Branchflow_Trace (Tracefile_Path.all & + -- ".branchflow"); + else Outputs.Warn ("Starting to convert..."); diff --git a/tools/gnatcov/trace_adapters/trace32/trace_output.adb b/tools/gnatcov/trace_adapters/trace32/trace_output.adb index d454d9f95..379c6fa6d 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace_output.adb +++ b/tools/gnatcov/trace_adapters/trace32/trace_output.adb @@ -31,12 +31,10 @@ package body Trace_Output is procedure Open (This : in out QEMU_Trace_Output; Output_Trace_Path : String; - Decision_Map_Path : String := "") - is + Decision_Map_Path : String := "") is begin - Open_Output_Flat_Trace_File (Output_Trace_Path, - This.Desc, - This.Trace_File); + Open_Output_Flat_Trace_File + (Output_Trace_Path, This.Desc, This.Trace_File); This.Open := True; Traces_Dbase.Init_Base (This.Base); @@ -50,17 +48,15 @@ package body Trace_Output is -- Is_Open -- ------------- - function Is_Open (This : in out QEMU_Trace_Output) return Boolean is - (This.Open); + function Is_Open (This : in out QEMU_Trace_Output) return Boolean + is (This.Open); ---------------- -- Push_Entry -- ---------------- procedure Push_Entry - (This : in out QEMU_Trace_Output; - Trace_Entry : Traces.Trace_Entry) - is + (This : in out QEMU_Trace_Output; Trace_Entry : Traces.Trace_Entry) is begin if This.Keep_History (Trace_Entry.Last) then -- If we have to keep history for this trace, we write it directly to @@ -76,9 +72,7 @@ package body Trace_Output is -- Close_Trace_File -- ---------------------- - procedure Close_Trace_File - (This : in out QEMU_Trace_Output) - is + procedure Close_Trace_File (This : in out QEMU_Trace_Output) is procedure Write_Entry (E : Trace_Entry); procedure Write_Entry (E : Trace_Entry) is @@ -99,16 +93,13 @@ package body Trace_Output is -- Update_Entry -- ------------------ - procedure Update_Entry (This : in out QEMU_Trace_Output; - Trace_Entry : Traces.Trace_Entry) - is + procedure Update_Entry + (This : in out QEMU_Trace_Output; Trace_Entry : Traces.Trace_Entry) is begin -- Traces_Dbase.Add_Entry is expected handle the merge of Op if we see -- the same entry twice. - Traces_Dbase.Add_Entry (This.Base, - Trace_Entry.First, - Trace_Entry.Last, - Trace_Entry.Op); + Traces_Dbase.Add_Entry + (This.Base, Trace_Entry.First, Trace_Entry.Last, Trace_Entry.Op); end Update_Entry; ----------------------- @@ -116,57 +107,53 @@ package body Trace_Output is ----------------------- procedure Load_Decision_Map - (This : in out QEMU_Trace_Output; - Decision_Map_Path : String) + (This : in out QEMU_Trace_Output; Decision_Map_Path : String) is function Load_Shared_Object - (Ignored_Trace_File : Trace_File_Type; - Ignored_Filename : String; - Ignored_Signature : Binary_File_Signature; - Ignored_First, - Ignored_Last : Traces.Pc_Type) return Boolean + (Ignored_Trace_File : Trace_File_Type; + Ignored_Filename : String; + Ignored_Signature : Binary_File_Signature; + Ignored_First, Ignored_Last : Traces.Pc_Type) return Boolean is (True); procedure Process_Info_Entries - (Trace_File : Trace_File_Type; - Result : out Read_Result); + (Trace_File : Trace_File_Type; Result : out Read_Result); procedure Process_Trace_Entry - (Trace_File : Trace_File_Type; - SO : Boolean; - E : Trace_Entry); + (Trace_File : Trace_File_Type; SO : Boolean; E : Trace_Entry); - procedure Read_Decision_Map_File is new Read_Trace_File_Gen - (Shared_Object_Type => Boolean, - No_Shared_Object => False, - Process_Info_Entries => Process_Info_Entries, - Load_Shared_Object => Load_Shared_Object, - Process_Trace_Entry => Process_Trace_Entry); + procedure Read_Decision_Map_File is new + Read_Trace_File_Gen + (Shared_Object_Type => Boolean, + No_Shared_Object => False, + Process_Info_Entries => Process_Info_Entries, + Load_Shared_Object => Load_Shared_Object, + Process_Trace_Entry => Process_Trace_Entry); -------------------------- -- Process_Info_Entries -- -------------------------- procedure Process_Info_Entries - (Trace_File : Trace_File_Type; - Result : out Read_Result) is + (Trace_File : Trace_File_Type; Result : out Read_Result) is begin case Kind (Trace_File) is - when Flat | History => - Create_Error - (Result, "decision map expected, but this is a execution trace"); + when Flat | History => + Create_Error + (Result, + "decision map expected, but this is a execution trace"); - when Decision_Map => - null; + when Decision_Map => + null; - when Info => - -- If Trace_File's first header has an Info kind, then it is - -- supposed to have a second header, and Trace_File's kind must - -- come from this second header. Header reading must have already - -- ensured that. + when Info => + -- If Trace_File's first header has an Info kind, then it is + -- supposed to have a second header, and Trace_File's kind must + -- come from this second header. Header reading must have + -- already ensured that. - raise Program_Error; + raise Program_Error; end case; end Process_Info_Entries; @@ -175,9 +162,7 @@ package body Trace_Output is ------------------------- procedure Process_Trace_Entry - (Trace_File : Trace_File_Type; - SO : Boolean; - E : Trace_Entry) + (Trace_File : Trace_File_Type; SO : Boolean; E : Trace_Entry) is pragma Unreferenced (Trace_File); pragma Unreferenced (SO); @@ -203,8 +188,8 @@ package body Trace_Output is -- Keep_History -- ------------------ - function Keep_History (This : in out QEMU_Trace_Output; - Pc : Pc_Type) return Boolean + function Keep_History + (This : in out QEMU_Trace_Output; Pc : Pc_Type) return Boolean is use Address_Set; begin diff --git a/tools/gnatcov/trace_adapters/trace32/trace_output.ads b/tools/gnatcov/trace_adapters/trace32/trace_output.ads index 7bed11c60..6d7029a1a 100644 --- a/tools/gnatcov/trace_adapters/trace32/trace_output.ads +++ b/tools/gnatcov/trace_adapters/trace32/trace_output.ads @@ -20,7 +20,7 @@ private with Ada.Containers.Ordered_Sets; private with Interfaces; -with Traces; use Traces; +with Traces; use Traces; with Traces_Files; with Traces_Dbase; @@ -28,35 +28,35 @@ package Trace_Output is type QEMU_Trace_Output is tagged limited private; - procedure Open (This : in out QEMU_Trace_Output; - Output_Trace_Path : String; - Decision_Map_Path : String := "") - with Pre => not Is_Open (This), - Post => Is_Open (This); + procedure Open + (This : in out QEMU_Trace_Output; + Output_Trace_Path : String; + Decision_Map_Path : String := "") + with Pre => not Is_Open (This), Post => Is_Open (This); -- Open a flat trace file for output. An optional decision map can be -- loaded. function Is_Open (This : in out QEMU_Trace_Output) return Boolean; -- Return true if the trace file is open - procedure Push_Entry (This : in out QEMU_Trace_Output; - Trace_Entry : Traces.Trace_Entry) - with Pre => Is_Open (This); + procedure Push_Entry + (This : in out QEMU_Trace_Output; Trace_Entry : Traces.Trace_Entry) + with Pre => Is_Open (This); -- Call this procedure every time an entry is executed. This procedure -- takes care of recording/updating the entry, it also handles entry -- history when necessary. procedure Close_Trace_File (This : in out QEMU_Trace_Output) - with Pre => Is_Open (This), - Post => not Is_Open (This); + with Pre => Is_Open (This), Post => not Is_Open (This); -- Write remaining trace entries and close the trace file private - package Address_Set is - new Ada.Containers.Ordered_Sets (Element_Type => Traces.Pc_Type, - "<" => Interfaces."<", - "=" => Interfaces."="); + package Address_Set is new + Ada.Containers.Ordered_Sets + (Element_Type => Traces.Pc_Type, + "<" => Interfaces."<", + "=" => Interfaces."="); type QEMU_Trace_Output is tagged limited record Open : Boolean := False; @@ -66,19 +66,18 @@ private Decision_Map : Address_Set.Set; end record; - procedure Update_Entry (This : in out QEMU_Trace_Output; - Trace_Entry : Traces.Trace_Entry); + procedure Update_Entry + (This : in out QEMU_Trace_Output; Trace_Entry : Traces.Trace_Entry); -- Update flags of an existing entry or add a new entry to the database procedure Load_Decision_Map - (This : in out QEMU_Trace_Output; - Decision_Map_Path : String); + (This : in out QEMU_Trace_Output; Decision_Map_Path : String); -- Open decision map file, load addresses in a database and close the file. -- If the decision map cannot be loaded, it is not considered as an error -- state. - function Keep_History (This : in out QEMU_Trace_Output; - Pc : Pc_Type) return Boolean; + function Keep_History + (This : in out QEMU_Trace_Output; Pc : Pc_Type) return Boolean; -- Return true if execution history should be kept for this address end Trace_Output; From 707b1aa479c1afdcb5b12b318bfe988fd51d13f6 Mon Sep 17 00:00:00 2001 From: Dorian Peron Date: Thu, 18 Sep 2025 10:56:42 +0200 Subject: [PATCH 1467/1483] gnatformat: run gnatformat and fix comments exceeding limit --- tools/gnatcov/annotations-cobertura.adb | 182 +- tools/gnatcov/annotations-dynamic_html.adb | 193 +- tools/gnatcov/annotations-html.adb | 234 +- tools/gnatcov/annotations-html.ads | 3 +- tools/gnatcov/annotations-index.adb | 173 +- tools/gnatcov/annotations-report.adb | 176 +- tools/gnatcov/annotations-report.ads | 7 +- tools/gnatcov/annotations-sarif.adb | 157 +- tools/gnatcov/annotations-xcov.adb | 17 +- tools/gnatcov/annotations-xcov.ads | 3 +- tools/gnatcov/annotations-xml.adb | 246 +- tools/gnatcov/annotations.adb | 253 +- tools/gnatcov/annotations.ads | 116 +- tools/gnatcov/arch__32.ads | 26 +- tools/gnatcov/arch__64.ads | 26 +- tools/gnatcov/argparse.adb | 489 +-- tools/gnatcov/argparse.ads | 131 +- tools/gnatcov/binary_files.adb | 137 +- tools/gnatcov/binary_files.ads | 100 +- tools/gnatcov/calendar_utils.adb | 15 +- tools/gnatcov/cfg_dump.adb | 617 ++- tools/gnatcov/cfg_dump.ads | 15 +- tools/gnatcov/check_scos.adb | 20 +- tools/gnatcov/checkpoints.adb | 280 +- tools/gnatcov/checkpoints.ads | 239 +- tools/gnatcov/clang-extensions.adb | 156 +- tools/gnatcov/clang-extensions.ads | 194 +- tools/gnatcov/coff.ads | 6 +- tools/gnatcov/command_line.adb | 20 +- tools/gnatcov/command_line.ads | 3190 +++++++------- tools/gnatcov/commands.adb | 6 +- tools/gnatcov/commands.ads | 3 +- tools/gnatcov/compiler_wrappers-gcc.adb | 4 +- tools/gnatcov/convert.adb | 68 +- tools/gnatcov/convert.ads | 9 +- tools/gnatcov/coverage-object.adb | 55 +- tools/gnatcov/coverage-object.ads | 11 +- tools/gnatcov/coverage-source.adb | 687 +-- tools/gnatcov/coverage-source.ads | 20 +- tools/gnatcov/coverage.adb | 52 +- tools/gnatcov/coverage.ads | 30 +- tools/gnatcov/coverage_options.adb | 76 +- tools/gnatcov/coverage_options.ads | 13 +- tools/gnatcov/decision_map.adb | 838 ++-- tools/gnatcov/decision_map.ads | 58 +- tools/gnatcov/diagnostics.adb | 111 +- tools/gnatcov/diagnostics.ads | 28 +- tools/gnatcov/disa_aarch64.adb | 123 +- tools/gnatcov/disa_aarch64.ads | 44 +- tools/gnatcov/disa_arm.adb | 151 +- tools/gnatcov/disa_arm.ads | 44 +- tools/gnatcov/disa_common.adb | 64 +- tools/gnatcov/disa_common.ads | 11 +- tools/gnatcov/disa_lmp.adb | 135 +- tools/gnatcov/disa_lmp.ads | 44 +- tools/gnatcov/disa_ppc.adb | 46 +- tools/gnatcov/disa_ppc.ads | 51 +- tools/gnatcov/disa_sparc.adb | 57 +- tools/gnatcov/disa_sparc.ads | 43 +- tools/gnatcov/disa_symbolize.adb | 3 +- tools/gnatcov/disa_symbolize.ads | 20 +- tools/gnatcov/disa_thumb.adb | 401 +- tools/gnatcov/disa_thumb.ads | 44 +- tools/gnatcov/disa_x86.adb | 286 +- tools/gnatcov/disa_x86.ads | 44 +- tools/gnatcov/disassemble_insn_properties.adb | 55 +- tools/gnatcov/disassemble_insn_properties.ads | 4 +- tools/gnatcov/disassemblers.adb | 16 +- tools/gnatcov/disassemblers.ads | 43 +- tools/gnatcov/display.adb | 6 +- tools/gnatcov/display.ads | 1 + tools/gnatcov/dwarf.ads | 516 +-- tools/gnatcov/dwarf_handling.adb | 101 +- tools/gnatcov/dwarf_handling.ads | 73 +- tools/gnatcov/elf32.adb | 77 +- tools/gnatcov/elf32.ads | 12 +- tools/gnatcov/elf64.adb | 79 +- tools/gnatcov/elf64.ads | 16 +- tools/gnatcov/elf_common.adb | 25 +- tools/gnatcov/elf_common.ads | 19 +- tools/gnatcov/elf_disassemblers.adb | 92 +- tools/gnatcov/elf_disassemblers.ads | 16 +- tools/gnatcov/elf_files.adb | 105 +- tools/gnatcov/elf_files.ads | 55 +- tools/gnatcov/execs_dbase.adb | 20 +- tools/gnatcov/execs_dbase.ads | 19 +- tools/gnatcov/factory_registry.adb | 13 +- tools/gnatcov/factory_registry.ads | 3 +- tools/gnatcov/files_handling.ads | 51 +- tools/gnatcov/files_table.adb | 568 +-- tools/gnatcov/files_table.ads | 155 +- tools/gnatcov/gnatcov.adb | 21 +- tools/gnatcov/gnatcov_bits_specific.adb | 688 +-- tools/gnatcov/hex_images.adb | 20 +- tools/gnatcov/highlighting.adb | 17 +- tools/gnatcov/highlighting.ads | 28 +- tools/gnatcov/inputs.adb | 25 +- tools/gnatcov/inputs.ads | 3 +- .../gnatcov/instrument-ada_preprocessing.adb | 32 +- .../instrument-ada_unit-rewriting_utils.adb | 44 +- .../instrument-ada_unit-rewriting_utils.ads | 6 +- tools/gnatcov/instrument-ada_unit.adb | 3687 +++++++++-------- tools/gnatcov/instrument-ada_unit.ads | 273 +- tools/gnatcov/instrument-ada_unit__stub.ads | 9 +- .../gnatcov/instrument-ada_unit_provider.adb | 66 +- .../gnatcov/instrument-ada_unit_provider.ads | 44 +- tools/gnatcov/instrument-c.adb | 1262 +++--- tools/gnatcov/instrument-c.ads | 288 +- tools/gnatcov/instrument-c__stub.ads | 30 +- tools/gnatcov/instrument-c_utils.adb | 128 +- tools/gnatcov/instrument-c_utils.ads | 40 +- tools/gnatcov/instrument-checkpoints.adb | 19 +- tools/gnatcov/instrument-clean_objdirs.adb | 16 +- tools/gnatcov/instrument-common.adb | 154 +- tools/gnatcov/instrument-common.ads | 248 +- tools/gnatcov/instrument-config.adb | 34 +- tools/gnatcov/instrument-gcc_wrapper.adb | 166 +- tools/gnatcov/instrument-input_traces.adb | 296 +- tools/gnatcov/instrument-input_traces.ads | 28 +- tools/gnatcov/instrument-main.adb | 4 +- tools/gnatcov/instrument-projects.adb | 269 +- tools/gnatcov/instrument-setup_config.adb | 66 +- tools/gnatcov/instrument-source.adb | 4 +- tools/gnatcov/instrument.adb | 92 +- tools/gnatcov/instrument.ads | 149 +- tools/gnatcov/json.adb | 38 +- tools/gnatcov/json.ads | 2 +- tools/gnatcov/llvm.adb | 13 +- tools/gnatcov/llvm.ads | 4 +- tools/gnatcov/llvm_json_checkpoints.adb | 241 +- tools/gnatcov/llvm_json_checkpoints.ads | 27 +- tools/gnatcov/logging.adb | 9 +- tools/gnatcov/logging.ads | 3 +- tools/gnatcov/mc_dc.adb | 31 +- tools/gnatcov/mc_dc.ads | 34 +- tools/gnatcov/object_locations.adb | 118 +- tools/gnatcov/object_locations.ads | 36 +- tools/gnatcov/outputs.adb | 33 +- tools/gnatcov/outputs.ads | 31 +- tools/gnatcov/paths.adb | 93 +- tools/gnatcov/paths.ads | 17 +- tools/gnatcov/pecoff_files.adb | 75 +- tools/gnatcov/pecoff_files.ads | 20 +- tools/gnatcov/perf_counters.adb | 7 +- tools/gnatcov/perf_counters.ads | 6 +- tools/gnatcov/ppc_descs.adb | 15 +- tools/gnatcov/ppc_descs.ads | 113 +- tools/gnatcov/project.adb | 336 +- tools/gnatcov/project.ads | 68 +- tools/gnatcov/qemu_traces.ads | 15 +- tools/gnatcov/rundrv-config.adb | 23 +- tools/gnatcov/rundrv-config.ads | 12 +- tools/gnatcov/rundrv-handlers.adb | 33 +- tools/gnatcov/rundrv.adb | 40 +- tools/gnatcov/rundrv.ads | 11 +- tools/gnatcov/sc_obligations-bdd.adb | 219 +- tools/gnatcov/sc_obligations-bdd.ads | 28 +- tools/gnatcov/sc_obligations.adb | 2642 ++++++------ tools/gnatcov/sc_obligations.ads | 854 ++-- tools/gnatcov/setup_rts.adb | 232 +- tools/gnatcov/setup_rts.ads | 4 +- tools/gnatcov/setup_rts__stub.adb | 4 +- tools/gnatcov/slocs.adb | 158 +- tools/gnatcov/slocs.ads | 23 +- tools/gnatcov/sparc_descs.ads | 35 +- tools/gnatcov/ss_annotations.adb | 382 +- tools/gnatcov/ss_annotations.ads | 27 +- tools/gnatcov/strings.adb | 136 +- tools/gnatcov/strings.ads | 53 +- tools/gnatcov/subprocesses.adb | 152 +- tools/gnatcov/subprocesses.ads | 13 +- tools/gnatcov/support_files.ads | 24 +- tools/gnatcov/switches.adb | 161 +- tools/gnatcov/switches.ads | 25 +- tools/gnatcov/symbols.adb | 8 +- tools/gnatcov/temp_dirs.adb | 5 +- tools/gnatcov/temp_dirs.ads | 7 +- tools/gnatcov/text_files.adb | 9 +- tools/gnatcov/text_files.ads | 46 +- tools/gnatcov/traces.adb | 26 +- tools/gnatcov/traces.ads | 40 +- tools/gnatcov/traces_dbase.adb | 76 +- tools/gnatcov/traces_dbase.ads | 33 +- tools/gnatcov/traces_disa.adb | 88 +- tools/gnatcov/traces_disa.ads | 53 +- tools/gnatcov/traces_dump.adb | 81 +- tools/gnatcov/traces_elf.adb | 1542 +++---- tools/gnatcov/traces_elf.ads | 208 +- tools/gnatcov/traces_files.adb | 546 ++- tools/gnatcov/traces_files.ads | 98 +- tools/gnatcov/traces_files_registry.adb | 60 +- tools/gnatcov/traces_files_registry.ads | 17 +- tools/gnatcov/traces_lines.adb | 10 +- tools/gnatcov/traces_lines.ads | 3 +- tools/gnatcov/traces_names.adb | 152 +- tools/gnatcov/traces_names.ads | 50 +- tools/gnatcov/traces_source.ads | 81 +- tools/gnatcov/traces_stats.adb | 33 +- tools/gnatcov/traces_stats.ads | 3 +- 199 files changed, 16032 insertions(+), 15416 deletions(-) diff --git a/tools/gnatcov/annotations-cobertura.adb b/tools/gnatcov/annotations-cobertura.adb index 1a0431955..28c4136a4 100644 --- a/tools/gnatcov/annotations-cobertura.adb +++ b/tools/gnatcov/annotations-cobertura.adb @@ -29,14 +29,14 @@ with GNAT.Regpat; use GNAT.Regpat; with Interfaces.C; use Interfaces.C; -with Annotations.Xml; use Annotations.Xml; -with Command_Line; use Command_Line; -with Coverage; use Coverage; -with Coverage.Source; use Coverage.Source; -with Outputs; use Outputs; +with Annotations.Xml; use Annotations.Xml; +with Command_Line; use Command_Line; +with Coverage; use Coverage; +with Coverage.Source; use Coverage.Source; +with Outputs; use Outputs; with Paths; with Support_Files; -with Switches; use Switches; +with Switches; use Switches; with Version; package body Annotations.Cobertura is @@ -45,8 +45,8 @@ package body Annotations.Cobertura is DTD_Filename : constant String := Support_Files.In_Lib_Dir (DTD_Basename); type Pattern_Matcher_Acc is access all Pattern_Matcher; - procedure Free is new Ada.Unchecked_Deallocation - (Pattern_Matcher, Pattern_Matcher_Acc); + procedure Free is new + Ada.Unchecked_Deallocation (Pattern_Matcher, Pattern_Matcher_Acc); type Cobertura_Pretty_Printer is new Pretty_Printer with record Report_Filename : Unbounded_String; @@ -66,7 +66,8 @@ package body Annotations.Cobertura is end record; -- Pretty printer type for the Cobertura annotation format - overriding function Format + overriding + function Format (Pp : Cobertura_Pretty_Printer) return Annotation_Format_Family is (Annotate_Cobertura); @@ -100,14 +101,10 @@ package body Annotations.Cobertura is -- Print a string representing a start tag whose name and attributes are -- given in parameter, i.e. . - procedure ST - (Pp : in out Cobertura_Pretty_Printer'Class; - Name : String); + procedure ST (Pp : in out Cobertura_Pretty_Printer'Class; Name : String); -- Same as ST, with no attributes - procedure ET - (Pp : in out Cobertura_Pretty_Printer'Class; - Name : String); + procedure ET (Pp : in out Cobertura_Pretty_Printer'Class; Name : String); -- Print a string representing an end tag whose name is given in parameter, -- i.e. . @@ -116,21 +113,23 @@ package body Annotations.Cobertura is -- (inherited from Pretty_Printer) -- ----------------------------------------------------- - overriding procedure Pretty_Print_Start - (Pp : in out Cobertura_Pretty_Printer); + overriding + procedure Pretty_Print_Start (Pp : in out Cobertura_Pretty_Printer); - overriding procedure Pretty_Print_End - (Pp : in out Cobertura_Pretty_Printer); + overriding + procedure Pretty_Print_End (Pp : in out Cobertura_Pretty_Printer); - overriding procedure Pretty_Print_Start_File + overriding + procedure Pretty_Print_Start_File (Pp : in out Cobertura_Pretty_Printer; File : Source_File_Index; Skip : out Boolean); - overriding procedure Pretty_Print_End_File - (Pp : in out Cobertura_Pretty_Printer); + overriding + procedure Pretty_Print_End_File (Pp : in out Cobertura_Pretty_Printer); - overriding procedure Pretty_Print_Start_Line + overriding + procedure Pretty_Print_Start_Line (Pp : in out Cobertura_Pretty_Printer; Line_Num : Natural; Info : Line_Info_Access; @@ -140,9 +139,7 @@ package body Annotations.Cobertura is -- Shortcut for Put_Line's -- ----------------------------- - procedure P - (Pp : Cobertura_Pretty_Printer'Class; - S : String); + procedure P (Pp : Cobertura_Pretty_Printer'Class; S : String); -- Put_Line S in the destination file ----------------------------- @@ -188,10 +185,7 @@ package body Annotations.Cobertura is Result : String (1 .. 8); begin Float_IO.Put - (To => Result, - Item => R, - Aft => Rate_Type'Digits - 1, - Exp => 0); + (To => Result, Item => R, Aft => Rate_Type'Digits - 1, Exp => 0); return Ada.Strings.Fixed.Trim (Result, Side => Ada.Strings.Both); end Img; @@ -208,9 +202,7 @@ package body Annotations.Cobertura is -- ET -- -------- - procedure ET - (Pp : in out Cobertura_Pretty_Printer'Class; - Name : String) is + procedure ET (Pp : in out Cobertura_Pretty_Printer'Class; Name : String) is begin Pp.Indentation := Pp.Indentation - 1; Pp.P (""); @@ -255,8 +247,7 @@ package body Annotations.Cobertura is Pp.Need_Sources := False; - Annotations.Generate_Report - (Pp, True, Subdir => "cobertura"); + Annotations.Generate_Report (Pp, True, Subdir => "cobertura"); Free (Pp.Source_Prefix_Pattern); end Generate_Report; @@ -264,10 +255,7 @@ package body Annotations.Cobertura is -- P -- ------- - procedure P - (Pp : Cobertura_Pretty_Printer'Class; - S : String) - is + procedure P (Pp : Cobertura_Pretty_Printer'Class; S : String) is Spaces : constant String (1 .. Pp.Indentation) := (others => ' '); begin Put_Line (Pp.Report_File, Spaces & S); @@ -277,8 +265,8 @@ package body Annotations.Cobertura is -- Pretty_Print_End -- ---------------------- - overriding procedure Pretty_Print_End (Pp : in out Cobertura_Pretty_Printer) - is + overriding + procedure Pretty_Print_End (Pp : in out Cobertura_Pretty_Printer) is begin Pp.ET ("packages"); Pp.ET ("coverage"); @@ -289,8 +277,8 @@ package body Annotations.Cobertura is -- Pretty_Print_End_File -- --------------------------- - overriding procedure Pretty_Print_End_File - (Pp : in out Cobertura_Pretty_Printer) is + overriding + procedure Pretty_Print_End_File (Pp : in out Cobertura_Pretty_Printer) is begin Pp.ET ("lines"); Pp.ET ("class"); @@ -331,7 +319,8 @@ package body Annotations.Cobertura is + Ob_Stats (Decision).Stats (Not_Covered) + Ob_Stats (Decision).Stats (Partially_Covered); Branches_Covered := - 2 * Ob_Stats (Decision).Stats (Covered) + 2 + * Ob_Stats (Decision).Stats (Covered) + Ob_Stats (Decision).Stats (Partially_Covered); if Branches_Valid = 0 then Branch_Rate := 1.0; @@ -345,9 +334,8 @@ package body Annotations.Cobertura is -- Pretty_Print_Start -- ------------------------ - overriding procedure Pretty_Print_Start - (Pp : in out Cobertura_Pretty_Printer) - is + overriding + procedure Pretty_Print_Start (Pp : in out Cobertura_Pretty_Printer) is Success : Boolean; Timestamp : constant String := Ada.Strings.Fixed.Trim @@ -363,7 +351,8 @@ package body Annotations.Cobertura is Mode => GNAT.OS_Lib.Overwrite); if not Success then Fatal_Error - ("Error while copying " & DTD_Filename + ("Error while copying " + & DTD_Filename & " to the output directory"); end if; @@ -386,20 +375,21 @@ package body Annotations.Cobertura is Compute_Branch_Stats (Global_Ob_Stats, Branches_Valid, Branches_Covered, Branch_Rate); - Pp.ST ("coverage", - A ("line-rate", Img (Line_Rate)) - & A ("branch-rate", Img (Branch_Rate)) - & A ("lines-covered", Img (Lines_Covered)) - & A ("lines-valid", Img (Lines_Valid)) - & A ("branches-covered", Img (Branches_Covered)) - & A ("branches-valid", Img (Branches_Valid)) + Pp.ST + ("coverage", + A ("line-rate", Img (Line_Rate)) + & A ("branch-rate", Img (Branch_Rate)) + & A ("lines-covered", Img (Lines_Covered)) + & A ("lines-valid", Img (Lines_Valid)) + & A ("branches-covered", Img (Branches_Covered)) + & A ("branches-valid", Img (Branches_Valid)) - -- Cobertura also provides the cyclomatic complexity number. - -- As we don't compute this, print an arbitrary invalid value. + -- Cobertura also provides the cyclomatic complexity number. + -- As we don't compute this, print an arbitrary invalid value. - & A ("complexity", "-1") - & A ("version", Version.Xcov_Version) - & A ("timestamp", Timestamp)); + & A ("complexity", "-1") + & A ("version", Version.Xcov_Version) + & A ("timestamp", Timestamp)); Pp.ST ("sources"); Pp.ET ("sources"); @@ -411,7 +401,8 @@ package body Annotations.Cobertura is -- Pretty_Print_Start_File -- ----------------------------- - overriding procedure Pretty_Print_Start_File + overriding + procedure Pretty_Print_Start_File (Pp : in out Cobertura_Pretty_Printer; File : Source_File_Index; Skip : out Boolean) @@ -437,10 +428,7 @@ package body Annotations.Cobertura is Compute_Line_Stats (Info.Li_Stats, Lines_Valid, Lines_Covered, Line_Rate); Compute_Branch_Stats - (Info.Ob_Stats, - Branches_Valid, - Branches_Covered, - Branch_Rate); + (Info.Ob_Stats, Branches_Valid, Branches_Covered, Branch_Rate); -- Remove the source root prefix (if present) from Filename so that, if -- Filename designates a source file that is inside the directory @@ -473,18 +461,20 @@ package body Annotations.Cobertura is end; end if; - Pp.ST ("package", - A ("name", Simple_Source_Filename) - & A ("line-rate", Img (Line_Rate)) - & A ("branch-rate", Img (Branch_Rate)) - & A ("complexity", "-1")); + Pp.ST + ("package", + A ("name", Simple_Source_Filename) + & A ("line-rate", Img (Line_Rate)) + & A ("branch-rate", Img (Branch_Rate)) + & A ("complexity", "-1")); Pp.ST ("classes"); - Pp.ST ("class", - A ("name", Simple_Source_Filename) - & A ("filename", +Filename) - & A ("line-rate", Img (Line_Rate)) - & A ("branch-rate", Img (Branch_Rate)) - & A ("complexity", "-1")); + Pp.ST + ("class", + A ("name", Simple_Source_Filename) + & A ("filename", +Filename) + & A ("line-rate", Img (Line_Rate)) + & A ("branch-rate", Img (Branch_Rate)) + & A ("complexity", "-1")); Pp.ST ("methods"); Pp.ET ("methods"); Pp.ST ("lines"); @@ -494,23 +484,24 @@ package body Annotations.Cobertura is -- Pretty_Print_Start_Line -- ----------------------------- - overriding procedure Pretty_Print_Start_Line + overriding + procedure Pretty_Print_Start_Line (Pp : in out Cobertura_Pretty_Printer; Line_Num : Natural; Info : Line_Info_Access; Line : String) is - Coverage_State : constant Any_Line_State := - Aggregated_State (Info.all); + Coverage_State : constant Any_Line_State := Aggregated_State (Info.all); Exempted : constant Boolean := Info.Exemption /= Slocs.No_Location; begin if not Exempted and then Coverage_State /= No_Code then declare subtype Coverage_Line_State is - Any_Line_State range Not_Covered .. Covered; - package SCOs_State_Maps is new Ada.Containers.Ordered_Maps - (Key_Type => SCO_Id, - Element_Type => Coverage_Line_State); + Any_Line_State range Not_Covered .. Covered; + package SCOs_State_Maps is new + Ada.Containers.Ordered_Maps + (Key_Type => SCO_Id, + Element_Type => Coverage_Line_State); Hit : Natural := 0; -- Whether the line was covered or not. Cobertura enables counting @@ -542,10 +533,9 @@ package body Annotations.Cobertura is for SCO of Info.SCOs.all loop if Kind (SCO) /= Removed and then First_Sloc (SCO).L.Line = Line_Num - and then SCO_Kind (Kind (SCO)) = Decision - and then - (Coverage.Enabled (Decision) - or else Coverage.MCDC_Coverage_Enabled) + and then SCO_Kind (Kind (SCO)) = Decision + and then (Coverage.Enabled (Decision) + or else Coverage.MCDC_Coverage_Enabled) then declare Line_State : constant Any_Line_State := @@ -590,8 +580,12 @@ package body Annotations.Cobertura is A ("condition-coverage", Img (Ratio (Branches_Covered, Branches_Valid)) - & "%" & "(" & Img (Branches_Covered) & "/" - & Img (Branches_Valid) & ")")); + & "%" + & "(" + & Img (Branches_Covered) + & "/" + & Img (Branches_Valid) + & ")")); else Append (Line_Attributes, A ("branch", "false")); end if; @@ -605,9 +599,9 @@ package body Annotations.Cobertura is for State_Decision of State_Decisions loop Coverage_Ratio := (case State_Decision is - when Not_Covered => 0, - when Partially_Covered => 50, - when Covered => 100); + when Not_Covered => 0, + when Partially_Covered => 50, + when Covered => 100); Pp.T ("condition", A ("number", Img (I)) @@ -649,9 +643,7 @@ package body Annotations.Cobertura is Pp.Indentation := Pp.Indentation + 1; end ST; - procedure ST - (Pp : in out Cobertura_Pretty_Printer'Class; - Name : String) is + procedure ST (Pp : in out Cobertura_Pretty_Printer'Class; Name : String) is begin Pp.P ("<" & Name & ">"); Pp.Indentation := Pp.Indentation + 1; diff --git a/tools/gnatcov/annotations-dynamic_html.adb b/tools/gnatcov/annotations-dynamic_html.adb index 1090abefe..b37aa450f 100644 --- a/tools/gnatcov/annotations-dynamic_html.adb +++ b/tools/gnatcov/annotations-dynamic_html.adb @@ -32,10 +32,10 @@ with Hex_Images; with Interfaces; with Outputs; with Project; -with Support_Files; use Support_Files; -with Switches; use Switches; +with Support_Files; use Support_Files; +with Switches; use Switches; with Traces_Disa; -with Traces_Files; use Traces_Files; +with Traces_Files; use Traces_Files; -- This package generates a dynamic HTML report, i.e. an HTML document heavily -- relying on JavaScript for presenting advanced graphical components. @@ -65,36 +65,36 @@ package body Annotations.Dynamic_Html is -- this node with children. It will then be written into a